diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 8dfc670..f607367 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -328,8 +328,6 @@ sysrq.txt
 	- info on the magic SysRq key.
 telephony/
 	- directory with info on telephony (e.g. voice over IP) support.
-time_interpolators.txt
-	- info on time interpolators.
 uml/
 	- directory with information about User Mode Linux.
 unicode.txt
@@ -346,8 +344,6 @@ vm/
 	- directory with info on the Linux vm code.
 volatile-considered-harmful.txt
 	- Why the "volatile" type class should not be used
-voyager.txt
-	- guide to running Linux on the Voyager architecture.
 w1/
 	- directory with documents regarding the 1-wire (w1) subsystem.
 watchdog/
diff --git a/Documentation/ABI/stable/sysfs-class-backlight b/Documentation/ABI/stable/sysfs-class-backlight
index 4d637e1..70302f3 100644
--- a/Documentation/ABI/stable/sysfs-class-backlight
+++ b/Documentation/ABI/stable/sysfs-class-backlight
@@ -34,3 +34,23 @@ Contact:	Richard Purdie <rpurdie@rpsys.net>
 Description:
 		Maximum brightness for <backlight>.
 Users:		HAL
+
+What:		/sys/class/backlight/<backlight>/type
+Date:		September 2010
+KernelVersion:	2.6.37
+Contact:	Matthew Garrett <mjg@redhat.com>
+Description:
+		The type of interface controlled by <backlight>.
+		"firmware": The driver uses a standard firmware interface
+		"platform": The driver uses a platform-specific interface
+		"raw": The driver controls hardware registers directly
+
+		In the general case, when multiple backlight
+		interfaces are available for a single device, firmware
+		control should be preferred to platform control should
+		be preferred to raw control. Using a firmware
+		interface reduces the probability of confusion with
+		the hardware and the OS independently updating the
+		backlight state. Platform interfaces are mostly a
+		holdover from pre-standardisation of firmware
+		interfaces.
diff --git a/Documentation/ABI/stable/sysfs-firmware-efi-vars b/Documentation/ABI/stable/sysfs-firmware-efi-vars
new file mode 100644
index 0000000..5def20b
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-firmware-efi-vars
@@ -0,0 +1,75 @@
+What:		/sys/firmware/efi/vars
+Date:		April 2004
+Contact:	Matt Domsch <Matt_Domsch@dell.com>
+Description:
+		This directory exposes interfaces for interactive with
+		EFI variables.  For more information on EFI variables,
+		see 'Variable Services' in the UEFI specification
+		(section 7.2 in specification version 2.3 Errata D).
+
+		In summary, EFI variables are named, and are classified
+		into separate namespaces through the use of a vendor
+		GUID.  They also have an arbitrary binary value
+		associated with them.
+
+		The efivars module enumerates these variables and
+		creates a separate directory for each one found.  Each
+		directory has a name of the form "<key>-<vendor guid>"
+		and contains the following files:
+
+		attributes:	A read-only text file enumerating the
+				EFI variable flags.  Potential values
+				include:
+
+				EFI_VARIABLE_NON_VOLATILE
+				EFI_VARIABLE_BOOTSERVICE_ACCESS
+				EFI_VARIABLE_RUNTIME_ACCESS
+				EFI_VARIABLE_HARDWARE_ERROR_RECORD
+				EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+
+				See the EFI documentation for an
+				explanation of each of these variables.
+
+		data:		A read-only binary file that can be read
+				to attain the value of the EFI variable
+
+		guid:		The vendor GUID of the variable.  This
+				should always match the GUID in the
+				variable's name.
+
+		raw_var:	A binary file that can be read to obtain
+				a structure that contains everything
+				there is to know about the variable.
+				For structure definition see "struct
+				efi_variable" in the kernel sources.
+
+				This file can also be written to in
+				order to update the value of a variable.
+				For this to work however, all fields of
+				the "struct efi_variable" passed must
+				match byte for byte with the structure
+				read out of the file, save for the value
+				portion.
+
+				**Note** the efi_variable structure
+				read/written with this file contains a
+				'long' type that may change widths
+				depending on your underlying
+				architecture.
+
+		size:		As ASCII representation of the size of
+				the variable's value.
+
+
+		In addition, two other magic binary files are provided
+		in the top-level directory and are used for adding and
+		removing variables:
+
+		new_var:	Takes a "struct efi_variable" and
+				instructs the EFI firmware to create a
+				new variable.
+
+		del_var:	Takes a "struct efi_variable" and
+				instructs the EFI firmware to remove any
+				variable that has a matching vendor GUID
+				and variable key name.
diff --git a/Documentation/ABI/testing/configfs-spear-pcie-gadget b/Documentation/ABI/testing/configfs-spear-pcie-gadget
new file mode 100644
index 0000000..8759881
--- /dev/null
+++ b/Documentation/ABI/testing/configfs-spear-pcie-gadget
@@ -0,0 +1,31 @@
+What:		/config/pcie-gadget
+Date:		Feb 2011
+KernelVersion:	2.6.37
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+
+	Interface is used to configure selected dual mode PCIe controller
+	as device and then program its various registers to configure it
+	as a particular device type.
+	This interfaces can be used to show spear's PCIe device capability.
+
+	Nodes are only visible when configfs is mounted. To mount configfs
+	in /config directory use:
+	# mount -t configfs none /config/
+
+	For nth PCIe Device Controller
+	/config/pcie-gadget.n/
+		link ... used to enable ltssm and read its status.
+		int_type ...used to configure and read type of supported
+			interrupt
+		no_of_msi ... used to configure number of MSI vector needed and
+			to read no of MSI granted.
+		inta ... write 1 to assert INTA and 0 to de-assert.
+		send_msi ... write MSI vector to be sent.
+		vendor_id ... used to write and read vendor id (hex)
+		device_id ... used to write and read device id (hex)
+		bar0_size ... used to write and read bar0_size
+		bar0_address ... used to write and read bar0 mapped area in hex.
+		bar0_rw_offset ... used to write and read offset of bar0 where
+			bar0_data will be written or read.
+		bar0_data ... used to write and read data at bar0_rw_offset.
diff --git a/Documentation/ABI/testing/pstore b/Documentation/ABI/testing/pstore
new file mode 100644
index 0000000..ddf451e
--- /dev/null
+++ b/Documentation/ABI/testing/pstore
@@ -0,0 +1,41 @@
+Where:		/dev/pstore/...
+Date:		March 2011
+Kernel Version: 2.6.39
+Contact:	tony.luck@intel.com
+Description:	Generic interface to platform dependent persistent storage.
+
+		Platforms that provide a mechanism to preserve some data
+		across system reboots can register with this driver to
+		provide a generic interface to show records captured in
+		the dying moments.  In the case of a panic the last part
+		of the console log is captured, but other interesting
+		data can also be saved.
+
+		# mount -t pstore -o kmsg_bytes=8000 - /dev/pstore
+
+		$ ls -l /dev/pstore
+		total 0
+		-r--r--r-- 1 root root 7896 Nov 30 15:38 dmesg-erst-1
+
+		Different users of this interface will result in different
+		filename prefixes.  Currently two are defined:
+
+		"dmesg"	- saved console log
+		"mce"	- architecture dependent data from fatal h/w error
+
+		Once the information in a file has been read, removing
+		the file will signal to the underlying persistent storage
+		device that it can reclaim the space for later re-use.
+
+		$ rm /dev/pstore/dmesg-erst-1
+
+		The expectation is that all files in /dev/pstore
+		will be saved elsewhere and erased from persistent store
+		soon after boot to free up space ready for the next
+		catastrophe.
+
+		The 'kmsg_bytes' mount option changes the target amount of
+		data saved on each oops/panic. Pstore saves (possibly
+		multiple) files based on the record size of the underlying
+		persistent storage until at least this amount is reached.
+		Default is 10 Kbytes.
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index f979d82..36bf454 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -145,9 +145,11 @@ Date:		July 2010
 Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
 Description:
 		Reading this attribute will provide the firmware
-		given name(SMBIOS type 41 string) of the PCI device.
-		The attribute will be created only if the firmware
-		has given a name to the PCI device.
+		given name (SMBIOS type 41 string or ACPI _DSM string) of
+		the PCI device.	The attribute will be created only
+		if the firmware	has given a name to the PCI device.
+		ACPI _DSM string name will be given priority if the
+		system firmware provides SMBIOS type 41 string also.
 Users:
 		Userspace applications interested in knowing the
 		firmware assigned name of the PCI device.
@@ -157,12 +159,27 @@ Date:		July 2010
 Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
 Description:
 		Reading this attribute will provide the firmware
-		given instance(SMBIOS type 41 device type instance)
-		of the PCI device. The attribute will be created
-		only if the firmware has given a device type instance
-		to the PCI device.
+		given instance (SMBIOS type 41 device type instance) of the
+		PCI device. The attribute will be created only if the firmware
+		has given an instance number to the PCI device.
 Users:
 		Userspace applications interested in knowing the
 		firmware assigned device type instance of the PCI
 		device that can help in understanding the firmware
 		intended order of the PCI device.
+
+What:		/sys/bus/pci/devices/.../acpi_index
+Date:		July 2010
+Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
+Description:
+		Reading this attribute will provide the firmware
+		given instance (ACPI _DSM instance number) of the PCI device.
+		The attribute will be created only if the firmware has given
+		an instance number to the PCI device. ACPI _DSM instance number
+		will be given priority if the system firmware provides SMBIOS
+		type 41 device type instance also.
+Users:
+		Userspace applications interested in knowing the
+		firmware assigned instance number of the PCI
+		device that can help in understanding the firmware
+		intended order of the PCI device.
diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd
index 90a87e2..fa72ccb 100644
--- a/Documentation/ABI/testing/sysfs-bus-rbd
+++ b/Documentation/ABI/testing/sysfs-bus-rbd
@@ -1,6 +1,6 @@
 What:		/sys/bus/rbd/
 Date:		November 2010
-Contact:	Yehuda Sadeh <yehuda@hq.newdream.net>,
+Contact:	Yehuda Sadeh <yehuda@newdream.net>,
 		Sage Weil <sage@newdream.net>
 Description:
 
diff --git a/Documentation/ABI/testing/sysfs-devices-mmc b/Documentation/ABI/testing/sysfs-devices-mmc
new file mode 100644
index 0000000..5a50ab6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices-mmc
@@ -0,0 +1,21 @@
+What:		/sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_offset
+Date:		January 2011
+Contact:	Chuanxiao Dong <chuanxiao.dong@intel.com>
+Description:
+		Enhanced area is a new feature defined in eMMC4.4 standard.
+		eMMC4.4 or later card can support such feature. This kind of
+		area can help to improve the card performance. If the feature
+		is enabled, this attribute will indicate the start address of
+		enhanced data area. If not, this attribute will be -EINVAL.
+		Unit Byte. Format decimal.
+
+What:		/sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_size
+Date:		January 2011
+Contact:	Chuanxiao Dong <chuanxiao.dong@intel.com>
+Description:
+		Enhanced area is a new feature defined in eMMC4.4 standard.
+		eMMC4.4 or later card can support such feature. This kind of
+		area can help to improve the card performance. If the feature
+		is enabled, this attribute will indicate the size of enhanced
+		data area. If not, this attribute will be -EINVAL.
+		Unit KByte. Format decimal.
diff --git a/Documentation/ABI/testing/sysfs-devices-power b/Documentation/ABI/testing/sysfs-devices-power
index 7628cd1..8ffbc25 100644
--- a/Documentation/ABI/testing/sysfs-devices-power
+++ b/Documentation/ABI/testing/sysfs-devices-power
@@ -29,9 +29,8 @@ Description:
 		"disabled" to it.
 
 		For the devices that are not capable of generating system wakeup
-		events this file contains "\n".  In that cases the user space
-		cannot modify the contents of this file and the device cannot be
-		enabled to wake up the system.
+		events this file is not present.  In that case the device cannot
+		be enabled to wake up the system from sleep states.
 
 What:		/sys/devices/.../power/control
 Date:		January 2009
@@ -85,7 +84,7 @@ Description:
 		The /sys/devices/.../wakeup_count attribute contains the number
 		of signaled wakeup events associated with the device.  This
 		attribute is read-only.  If the device is not enabled to wake up
-		the system from sleep states, this attribute is empty.
+		the system from sleep states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_active_count
 Date:		September 2010
@@ -95,7 +94,7 @@ Description:
 		number of times the processing of wakeup events associated with
 		the device was completed (at the kernel level).  This attribute
 		is read-only.  If the device is not enabled to wake up the
-		system from sleep states, this attribute is empty.
+		system from sleep states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_hit_count
 Date:		September 2010
@@ -105,7 +104,8 @@ Description:
 		number of times the processing of a wakeup event associated with
 		the device might prevent the system from entering a sleep state.
 		This attribute is read-only.  If the device is not enabled to
-		wake up the system from sleep states, this attribute is empty.
+		wake up the system from sleep states, this attribute is not
+		present.
 
 What:		/sys/devices/.../power/wakeup_active
 Date:		September 2010
@@ -115,7 +115,7 @@ Description:
 		or 0, depending on whether or not a wakeup event associated with
 		the device is being processed (1).  This attribute is read-only.
 		If the device is not enabled to wake up the system from sleep
-		states, this attribute is empty.
+		states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_total_time_ms
 Date:		September 2010
@@ -125,7 +125,7 @@ Description:
 		the total time of processing wakeup events associated with the
 		device, in milliseconds.  This attribute is read-only.  If the
 		device is not enabled to wake up the system from sleep states,
-		this attribute is empty.
+		this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_max_time_ms
 Date:		September 2010
@@ -135,7 +135,7 @@ Description:
 		the maximum time of processing a single wakeup event associated
 		with the device, in milliseconds.  This attribute is read-only.
 		If the device is not enabled to wake up the system from sleep
-		states, this attribute is empty.
+		states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_last_time_ms
 Date:		September 2010
@@ -146,7 +146,7 @@ Description:
 		signaling the last wakeup event associated with the device, in
 		milliseconds.  This attribute is read-only.  If the device is
 		not enabled to wake up the system from sleep states, this
-		attribute is empty.
+		attribute is not present.
 
 What:		/sys/devices/.../power/autosuspend_delay_ms
 Date:		September 2010
diff --git a/Documentation/ABI/testing/sysfs-driver-hid b/Documentation/ABI/testing/sysfs-driver-hid
new file mode 100644
index 0000000..b6490e1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid
@@ -0,0 +1,10 @@
+What:		For USB devices	: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
+		For BT devices	: /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
+		Symlink		: /sys/class/hidraw/hidraw<num>/device/report_descriptor
+Date:		Jan 2011
+KernelVersion:	2.0.39
+Contact:	Alan Ott <alan@signal11.us>
+Description:	When read, this file returns the device's raw binary HID
+		report descriptor.
+		This file cannot be written.
+Users:		HIDAPI library (http://www.signal11.us/oss/hidapi)
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo
new file mode 100644
index 0000000..55e281b
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo
@@ -0,0 +1,53 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/actual_profile
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-5.
+		When read, this attribute returns the number of the actual
+		profile which is also the profile that's active on device startup.
+		When written this attribute activates the selected profile
+		immediately.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/button
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The keyboard can store short macros with consist of 1 button with
+		several modifier keys 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 24 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>/arvo/roccatarvo<minor>/info
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns some info about the device like the
+		installed firmware version.
+		The size of the data is 8 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/key_mask
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The keyboard lets the user deactivate 5 certain keys like the
+		windows and application keys, to protect the user from the outcome
+		of accidentally pressing them.
+		The integer value of this attribute has bits 0-4 set depending
+		on the state of the corresponding key.
+		When read, this file returns the current state of the buttons.
+		When written, the given buttons are activated/deactivated
+		immediately.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/mode_key
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The keyboard has a condensed layout without num-lock key.
+		Instead it uses a mode-key which activates a gaming mode where
+		the assignment of the number block changes.
+		The integer value of this attribute ranges from 0 (OFF) to 1 (ON).
+		When read, this file returns the actual state of the key.
+		When written, the key is activated/deactivated immediately.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
index 698b808..b4c4f15 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
@@ -16,12 +16,14 @@ Description:	It is possible to switch the dpi setting of the mouse with the
 		6     3200
 
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/actual_profile
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the number of the actual profile.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/firmware_version
 Date:		March 2010
@@ -32,6 +34,7 @@ Description:	When read, this file returns the raw integer version number of the
 		number the decimal point has to be shifted 2 positions to the
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/profile[1-5]
 Date:		March 2010
@@ -47,6 +50,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		The mouse will reject invalid data, whereas the profile number
 		stored in the profile doesn't need to fit the number of the
 		store.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/settings
 Date:		March 2010
@@ -57,6 +61,7 @@ Description:	When read, this file returns the settings stored in the mouse.
 		When written, this file lets write settings back to the mouse.
 		The data has to be 36 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>/kone/roccatkone<minor>/startup_profile
 Date:		March 2010
@@ -66,6 +71,7 @@ Description:	The integer value of this attribute ranges from 1 to 5.
                 that's active when the mouse is powered on.
 		When written, this file sets the number of the startup profile
 		and the mouse activates this profile immediately.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/tcu
 Date:		March 2010
@@ -77,6 +83,7 @@ Description:	The mouse has a "Tracking Control Unit" which lets the user
 		Writing 0 in this file will switch the TCU off.
 		Writing 1 in this file will start the calibration which takes
 		around 6 seconds to complete and activates the TCU.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/weight
 Date:		March 2010
@@ -96,3 +103,4 @@ Description:	The mouse can be equipped with one of four supplied weights
 		4     20g
 
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
index 0f9f30e..00efced 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
@@ -4,6 +4,7 @@ Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the number of the actual profile in
 		range 0-4.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
 Date:		October 2010
@@ -14,6 +15,7 @@ Description:	When read, this file returns the raw integer version number of the
 		number the decimal point has to be shifted 2 positions to the
 		left. E.g. a returned value of 121 means 1.21
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
 Date:		October 2010
@@ -24,6 +26,7 @@ Description:	The mouse can store a macro with max 500 key/button strokes
 		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>/koneplus/roccatkoneplus<minor>/profile_buttons
 Date:		August 2010
@@ -37,6 +40,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		Which profile to write is determined by the profile number
 		contained in the data.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
 Date:		August 2010
@@ -47,6 +51,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		When read, these files return the respective profile buttons.
 		The returned data is 77 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
 Date:		October 2010
@@ -61,6 +66,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		Which profile to write is determined by the profile number
 		contained in the data.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
 Date:		August 2010
@@ -72,6 +78,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		When read, these files return the respective profile settings.
 		The returned data is 43 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
 Date:		October 2010
@@ -80,6 +87,7 @@ 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>/koneplus/roccatkoneplus<minor>/startup_profile
 Date:		October 2010
@@ -89,6 +97,7 @@ Description:	The integer value of this attribute ranges from 0-4.
                 that's active when the mouse is powered on.
 		When written, this file sets the number of the startup profile
 		and the mouse activates this profile immediately.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
 Date:		October 2010
@@ -97,6 +106,7 @@ Description:	When written a calibration process for the tracking control unit
 		can be initiated/cancelled.
 		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>/koneplus/roccatkoneplus<minor>/tcu_image
 Date:		October 2010
@@ -106,3 +116,4 @@ Description:	When read the mouse returns a 30x30 pixel image of the
 		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-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
new file mode 100644
index 0000000..fdfa16f
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
@@ -0,0 +1,100 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-4.
+		When read, this attribute returns the number of the active
+		cpi level.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 0-4.
+		When read, this attribute returns the number of the active
+		profile.
+		When written, the mouse activates this profile immediately.
+		The profile that's active when powered down is the same that's
+		active when the mouse is powered on.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-10.
+		When read, this attribute returns the number of the actual
+		sensitivity in x direction.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-10.
+		When read, this attribute returns the number of the actual
+		sensitivity in y direction.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the raw integer version number of the
+		firmware reported by the mouse. Using the integer value eases
+		further usage in other programs. To receive the real version
+		number the decimal point has to be shifted 2 positions to the
+		left. E.g. a returned value of 121 means 1.21
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
+Date:		January 2011
+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 informations about button layout.
+		When written, this file lets one write the respective profile
+		buttons back to the mouse. The data has to be 23 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		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>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
+Date:		January 2011
+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 informations about button layout.
+		When read, these files return the respective profile buttons.
+		The returned data is 23 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
+Date:		January 2011
+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 informations 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 16 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		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>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
+Date:		January 2011
+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 informations like resolution, sensitivity
+		and light effects.
+		When read, these files return the respective profile settings.
+		The returned data is 16 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
index 1c37b82..5fab71a 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
+++ b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
@@ -13,6 +13,7 @@ Description:	It is possible to switch the cpi setting of the mouse with the
 		4     1600
 
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
 Date:		August 2010
@@ -20,6 +21,7 @@ Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the number of the actual profile in
 		range 0-4.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
 Date:		August 2010
@@ -30,6 +32,7 @@ Description:	When read, this file returns the raw integer version number of the
 		number the decimal point has to be shifted 2 positions to the
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
 Date:		August 2010
@@ -44,6 +47,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		Which profile to write is determined by the profile number
 		contained in the data.
 		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>/pyra/roccatpyra<minor>/profile[1-5]_settings
 Date:		August 2010
@@ -55,6 +59,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		When read, these files return the respective profile settings.
 		The returned data is 13 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
 Date:		August 2010
@@ -68,6 +73,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		Which profile to write is determined by the profile number
 		contained in the data.
 		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>/pyra/roccatpyra<minor>/profile[1-5]_buttons
 Date:		August 2010
@@ -78,6 +84,7 @@ Description:	The mouse can store 5 profiles which can be switched by the
 		When read, these files return the respective profile buttons.
 		The returned data is 19 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
 Date:		August 2010
@@ -86,6 +93,7 @@ Description:	The integer value of this attribute ranges from 0-4.
                 When read, this attribute returns the number of the profile
                 that's active when the mouse is powered on.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
 Date:		August 2010
@@ -96,3 +104,4 @@ Description:	When read, this file returns the settings stored in the mouse.
 		When written, this file lets write settings back to the mouse.
 		The data has to be 3 bytes long. The mouse will reject invalid
 		data.
+Users:		http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-firmware-dmi b/Documentation/ABI/testing/sysfs-firmware-dmi
new file mode 100644
index 0000000..ba9da95
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-dmi
@@ -0,0 +1,110 @@
+What:		/sys/firmware/dmi/
+Date:		February 2011
+Contact:	Mike Waychison <mikew@google.com>
+Description:
+		Many machines' firmware (x86 and ia64) export DMI /
+		SMBIOS tables to the operating system.  Getting at this
+		information is often valuable to userland, especially in
+		cases where there are OEM extensions used.
+
+		The kernel itself does not rely on the majority of the
+		information in these tables being correct.  It equally
+		cannot ensure that the data as exported to userland is
+		without error either.
+
+		DMI is structured as a large table of entries, where
+		each entry has a common header indicating the type and
+		length of the entry, as well as 'handle' that is
+		supposed to be unique amongst all entries.
+
+		Some entries are required by the specification, but many
+		others are optional.  In general though, users should
+		never expect to find a specific entry type on their
+		system unless they know for certain what their firmware
+		is doing.  Machine to machine will vary.
+
+		Multiple entries of the same type are allowed.  In order
+		to handle these duplicate entry types, each entry is
+		assigned by the operating system an 'instance', which is
+		derived from an entry type's ordinal position.  That is
+		to say, if there are 'N' multiple entries with the same type
+		'T' in the DMI tables (adjacent or spread apart, it
+		doesn't matter), they will be represented in sysfs as
+		entries "T-0" through "T-(N-1)":
+
+		Example entry directories:
+
+			/sys/firmware/dmi/entries/17-0
+			/sys/firmware/dmi/entries/17-1
+			/sys/firmware/dmi/entries/17-2
+			/sys/firmware/dmi/entries/17-3
+			...
+
+		Instance numbers are used in lieu of the firmware
+		assigned entry handles as the kernel itself makes no
+		guarantees that handles as exported are unique, and
+		there are likely firmware images that get this wrong in
+		the wild.
+
+		Each DMI entry in sysfs has the common header values
+		exported as attributes:
+
+		handle	: The 16bit 'handle' that is assigned to this
+			  entry by the firmware.  This handle may be
+			  referred to by other entries.
+		length	: The length of the entry, as presented in the
+			  entry itself.  Note that this is _not the
+			  total count of bytes associated with the
+			  entry_.  This value represents the length of
+			  the "formatted" portion of the entry.  This
+			  "formatted" region is sometimes followed by
+			  the "unformatted" region composed of nul
+			  terminated strings, with termination signalled
+			  by a two nul characters in series.
+		raw	: The raw bytes of the entry. This includes the
+			  "formatted" portion of the entry, the
+			  "unformatted" strings portion of the entry,
+			  and the two terminating nul characters.
+		type	: The type of the entry.  This value is the same
+			  as found in the directory name.  It indicates
+			  how the rest of the entry should be
+			  interpreted.
+		instance: The instance ordinal of the entry for the
+			  given type.  This value is the same as found
+			  in the parent directory name.
+		position: The position of the entry within the entirety
+			  of the entirety.
+
+		=== Entry Specialization ===
+
+		Some entry types may have other information available in
+		sysfs.
+
+		--- Type 15 - System Event Log ---
+
+		This entry allows the firmware to export a log of
+		events the system has taken.  This information is
+		typically backed by nvram, but the implementation
+		details are abstracted by this table.  This entries data
+		is exported in the directory:
+
+		/sys/firmware/dmi/entries/15-0/system_event_log
+
+		and has the following attributes (documented in the
+		SMBIOS / DMI specification under "System Event Log (Type 15)":
+
+		area_length
+		header_start_offset
+		data_start_offset
+		access_method
+		status
+		change_token
+		access_method_address
+		header_format
+		per_log_type_descriptor_length
+		type_descriptors_supported_count
+
+		As well, the kernel exports the binary attribute:
+
+		raw_event_log	: The raw binary bits of the event log
+				  as described by the DMI entry.
diff --git a/Documentation/ABI/testing/sysfs-platform-kim b/Documentation/ABI/testing/sysfs-platform-kim
new file mode 100644
index 0000000..c165327
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-kim
@@ -0,0 +1,48 @@
+What:		/sys/devices/platform/kim/dev_name
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		Name of the UART device at which the WL128x chip
+		is connected. example: "/dev/ttyS0".
+		The device name flows down to architecture specific board
+		initialization file from the SFI/ATAGS bootloader
+		firmware. The name exposed is read from the user-space
+		dameon and opens the device when install is requested.
+
+What:		/sys/devices/platform/kim/baud_rate
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		The maximum reliable baud-rate the host can support.
+		Different platforms tend to have different high-speed
+		UART configurations, so the baud-rate needs to be set
+		locally and also sent across to the WL128x via a HCI-VS
+		command. The entry is read and made use by the user-space
+		daemon when the ldisc install is requested.
+
+What:		/sys/devices/platform/kim/flow_cntrl
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		The WL128x makes use of flow control mechanism, and this
+		entry most often should be 1, the host's UART is required
+		to have the capability of flow-control, or else this
+		entry can be made use of for exceptions.
+
+What:		/sys/devices/platform/kim/install
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		When one of the protocols Bluetooth, FM or GPS wants to make
+		use of the shared UART transport, it registers to the shared
+		transport driver, which will signal the user-space for opening,
+		configuring baud and install line discipline via this sysfs
+		entry. This entry would be polled upon by the user-space
+		daemon managing the UART, and is notified about the change
+		by the sysfs_notify. The value would be '1' when UART needs
+		to be opened/ldisc installed, and would be '0' when UART
+		is no more required and needs to be closed.
diff --git a/Documentation/Changes b/Documentation/Changes
index 4fb88f1..5f4828a 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -35,7 +35,7 @@ o  util-linux             2.10o                   # fdformat --version
 o  module-init-tools      0.9.10                  # depmod -V
 o  e2fsprogs              1.41.4                  # e2fsck -V
 o  jfsutils               1.1.3                   # fsck.jfs -V
-o  reiserfsprogs          3.6.3                   # reiserfsck -V 2>&1|grep reiserfsprogs
+o  reiserfsprogs          3.6.3                   # reiserfsck -V
 o  xfsprogs               2.6.0                   # xfs_db -V
 o  squashfs-tools         4.0                     # mksquashfs -version
 o  btrfs-progs            0.18                    # btrfsck
@@ -46,9 +46,9 @@ o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
 o  nfs-utils              1.0.5                   # showmount --version
 o  procps                 3.2.0                   # ps --version
 o  oprofile               0.9                     # oprofiled --version
-o  udev                   081                     # udevinfo -V
-o  grub                   0.93                    # grub --version
-o  mcelog		  0.6
+o  udev                   081                     # udevd --version
+o  grub                   0.93                    # grub --version || grub-install --version
+o  mcelog                 0.6                     # mcelog --version
 o  iptables               1.4.2                   # iptables -V
 
 
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index 8bb3723..58b0bf9 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -168,6 +168,13 @@ Do not unnecessarily use braces where a single statement will do.
 if (condition)
 	action();
 
+and
+
+if (condition)
+	do_this();
+else
+	do_that();
+
 This does not apply if one branch of a conditional statement is a single
 statement. Use braces in both branches.
 
@@ -659,7 +666,7 @@ There are a number of driver model diagnostic macros in <linux/device.h>
 which you should use to make sure messages are matched to the right device
 and driver, and are tagged with the right level:  dev_err(), dev_warn(),
 dev_info(), and so forth.  For messages that aren't associated with a
-particular device, <linux/kernel.h> defines pr_debug() and pr_info().
+particular device, <linux/printk.h> defines pr_debug() and pr_info().
 
 Coming up with good debugging messages can be quite a challenge; and once
 you have them, they can be a huge help for remote troubleshooting.  Such
@@ -819,6 +826,3 @@ language C, URL: http://www.open-std.org/JTC1/SC22/WG14/
 Kernel CodingStyle, by greg@kroah.com at OLS 2002:
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
 
---
-Last updated on 2007-July-13.
-
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index cfaac34..6ef6926 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -849,6 +849,37 @@ All:  lockdep-checked RCU-protected pointer access
 See the comment headers in the source code (or the docbook generated
 from them) for more information.
 
+However, given that there are no fewer than four families of RCU APIs
+in the Linux kernel, how do you choose which one to use?  The following
+list can be helpful:
+
+a.	Will readers need to block?  If so, you need SRCU.
+
+b.	What about the -rt patchset?  If readers would need to block
+	in an non-rt kernel, you need SRCU.  If readers would block
+	in a -rt kernel, but not in a non-rt kernel, SRCU is not
+	necessary.
+
+c.	Do you need to treat NMI handlers, hardirq handlers,
+	and code segments with preemption disabled (whether
+	via preempt_disable(), local_irq_save(), local_bh_disable(),
+	or some other mechanism) as if they were explicit RCU readers?
+	If so, you need RCU-sched.
+
+d.	Do you need RCU grace periods to complete even in the face
+	of softirq monopolization of one or more of the CPUs?  For
+	example, is your code subject to network-based denial-of-service
+	attacks?  If so, you need RCU-bh.
+
+e.	Is your workload too update-intensive for normal use of
+	RCU, but inappropriate for other synchronization mechanisms?
+	If so, consider SLAB_DESTROY_BY_RCU.  But please be careful!
+
+f.	Otherwise, use RCU.
+
+Of course, this all assumes that you have determined that RCU is in fact
+the right tool for your job.
+
 
 8.  ANSWERS TO QUICK QUIZZES
 
diff --git a/Documentation/arm/SH-Mobile/Makefile b/Documentation/arm/SH-Mobile/Makefile
new file mode 100644
index 0000000..8771d83
--- /dev/null
+++ b/Documentation/arm/SH-Mobile/Makefile
@@ -0,0 +1,8 @@
+BIN := vrl4
+
+.PHONY: all
+all: $(BIN)
+
+.PHONY: clean
+clean:
+	rm -f *.o $(BIN)
diff --git a/Documentation/arm/SH-Mobile/vrl4.c b/Documentation/arm/SH-Mobile/vrl4.c
new file mode 100644
index 0000000..e8a1913
--- /dev/null
+++ b/Documentation/arm/SH-Mobile/vrl4.c
@@ -0,0 +1,169 @@
+/*
+ * vrl4 format generator
+ *
+ * Copyright (C) 2010 Simon Horman
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * usage: vrl4 < zImage > out
+ *	  dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1
+ *
+ * Reads a zImage from stdin and writes a vrl4 image to stdout.
+ * In practice this means writing a padded vrl4 header to stdout followed
+ * by the zImage.
+ *
+ * The padding places the zImage at ALIGN bytes into the output.
+ * The vrl4 uses ALIGN + START_BASE as the start_address.
+ * This is where the mask ROM will jump to after verifying the header.
+ *
+ * The header sets copy_size to min(sizeof(zImage), MAX_BOOT_PROG_LEN) + ALIGN.
+ * That is, the mask ROM will load the padded header (ALIGN bytes)
+ * And then MAX_BOOT_PROG_LEN bytes of the image, or the entire image,
+ * whichever is smaller.
+ *
+ * The zImage is not modified in any way.
+ */
+
+#define _BSD_SOURCE
+#include <endian.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+
+struct hdr {
+	uint32_t magic1;
+	uint32_t reserved1;
+	uint32_t magic2;
+	uint32_t reserved2;
+	uint16_t copy_size;
+	uint16_t boot_options;
+	uint32_t reserved3;
+	uint32_t start_address;
+	uint32_t reserved4;
+	uint32_t reserved5;
+	char     reserved6[308];
+};
+
+#define DECLARE_HDR(h)					\
+	struct hdr (h) = {				\
+		.magic1 =	htole32(0xea000000),	\
+		.reserved1 =	htole32(0x56),		\
+		.magic2 =	htole32(0xe59ff008),	\
+		.reserved3 =	htole16(0x1) }
+
+/* Align to 512 bytes, the MMCIF sector size */
+#define ALIGN_BITS	9
+#define ALIGN		(1 << ALIGN_BITS)
+
+#define START_BASE	0xe55b0000
+
+/*
+ * With an alignment of 512 the header uses the first sector.
+ * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM.
+ * So there are 127 sectors left for the boot programme. But in practice
+ * Only a small portion of a zImage is needed, 16 sectors should be more
+ * than enough.
+ *
+ * Note that this sets how much of the zImage is copied by the mask ROM.
+ * The entire zImage is present after the header and is loaded
+ * by the code in the boot program (which is the first portion of the zImage).
+ */
+#define	MAX_BOOT_PROG_LEN (16 * 512)
+
+#define ROUND_UP(x)	((x + ALIGN - 1) & ~(ALIGN - 1))
+
+ssize_t do_read(int fd, void *buf, size_t count)
+{
+	size_t offset = 0;
+	ssize_t l;
+
+	while (offset < count) {
+		l = read(fd, buf + offset, count - offset);
+		if (!l)
+			break;
+		if (l < 0) {
+			if (errno == EAGAIN || errno == EWOULDBLOCK)
+				continue;
+			perror("read");
+			return -1;
+		}
+		offset += l;
+	}
+
+	return offset;
+}
+
+ssize_t do_write(int fd, const void *buf, size_t count)
+{
+	size_t offset = 0;
+	ssize_t l;
+
+	while (offset < count) {
+		l = write(fd, buf + offset, count - offset);
+		if (l < 0) {
+			if (errno == EAGAIN || errno == EWOULDBLOCK)
+				continue;
+			perror("write");
+			return -1;
+		}
+		offset += l;
+	}
+
+	return offset;
+}
+
+ssize_t write_zero(int fd, size_t len)
+{
+	size_t i = len;
+
+	while (i--) {
+		const char x = 0;
+		if (do_write(fd, &x, 1) < 0)
+			return -1;
+	}
+
+	return len;
+}
+
+int main(void)
+{
+	DECLARE_HDR(hdr);
+	char boot_program[MAX_BOOT_PROG_LEN];
+	size_t aligned_hdr_len, alligned_prog_len;
+	ssize_t prog_len;
+
+	prog_len = do_read(0, boot_program, sizeof(boot_program));
+	if (prog_len <= 0)
+		return -1;
+
+	aligned_hdr_len = ROUND_UP(sizeof(hdr));
+	hdr.start_address = htole32(START_BASE + aligned_hdr_len);
+	alligned_prog_len = ROUND_UP(prog_len);
+	hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len);
+
+	if (do_write(1, &hdr, sizeof(hdr)) < 0)
+		return -1;
+	if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0)
+		return -1;
+
+	if (do_write(1, boot_program, prog_len) < 0)
+		return 1;
+
+	/* Write out the rest of the kernel */
+	while (1) {
+		prog_len = do_read(0, boot_program, sizeof(boot_program));
+		if (prog_len < 0)
+			return 1;
+		if (prog_len == 0)
+			break;
+		if (do_write(1, boot_program, prog_len) < 0)
+			return 1;
+	}
+
+	return 0;
+}
diff --git a/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt b/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt
new file mode 100644
index 0000000..efff8ae
--- /dev/null
+++ b/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt
@@ -0,0 +1,29 @@
+ROM-able zImage boot from MMC
+-----------------------------
+
+An ROM-able zImage compiled with ZBOOT_ROM_MMCIF may be written to MMC and
+SuperH Mobile ARM will to boot directly from the MMCIF hardware block.
+
+This is achieved by the mask ROM loading the first portion of the image into
+MERAM and then jumping to it. This portion contains loader code which
+copies the entire image to SDRAM and jumps to it. From there the zImage
+boot code proceeds as normal, uncompressing the image into its final
+location and then jumping to it.
+
+This code has been tested on an AP4EB board using the developer 1A eMMC
+boot mode which is configured using the following jumper settings.
+The board used for testing required a patched mask ROM in order for
+this mode to function.
+
+   8 7 6 5 4 3 2 1
+   x|x|x|x|x| |x|
+S4 -+-+-+-+-+-+-+-
+    | | | | |x| |x on
+
+The zImage must be written to the MMC card at sector 1 (512 bytes) in
+vrl4 format. A utility vrl4 is supplied to accomplish this.
+
+e.g.
+	vrl4 < zImage | dd of=/dev/sdX bs=512 seek=1
+
+A dual-voltage MMC 4.0 card was used for testing.
diff --git a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
deleted file mode 100644
index dc460f0..0000000
--- a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
+++ /dev/null
@@ -1,61 +0,0 @@
-README on the ADC/Touchscreen Controller
-========================================
-
-The LH79524 and LH7A404 include a built-in Analog to Digital
-controller (ADC) that is used to process input from a touchscreen.
-The driver only implements a four-wire touch panel protocol.
-
-The touchscreen driver is maintenance free except for the pen-down or
-touch threshold.  Some resistive displays and board combinations may
-require tuning of this threshold.  The driver exposes some of its
-internal state in the sys filesystem.  If the kernel is configured
-with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a
-directory
-
-  /sys/devices/platform/adc-lh7.0
-
-containing these files.
-
-  -r--r--r--    1 root     root         4096 Jan  1 00:00 samples
-  -rw-r--r--    1 root     root         4096 Jan  1 00:00 threshold
-  -r--r--r--    1 root     root         4096 Jan  1 00:00 threshold_range
-
-The threshold is the current touch threshold.  It defaults to 750 on
-most targets.
-
-  # cat threshold
- 750
-
-The threshold_range contains the range of valid values for the
-threshold.  Values outside of this range will be silently ignored.
-
-  # cat threshold_range
-  0 1023
-
-To change the threshold, write a value to the threshold file.
-
-  # echo 500 > threshold
-  # cat threshold
-  500
-
-The samples file contains the most recently sampled values from the
-ADC.  There are 12.  Below are typical of the last sampled values when
-the pen has been released.  The first two and last two samples are for
-detecting whether or not the pen is down.  The third through sixth are
-X coordinate samples.  The seventh through tenth are Y coordinate
-samples.
-
-  # cat samples
-  1023 1023 0 0 0 0 530 529 530 529 1023 1023
-
-To determine a reasonable threshold, press on the touch panel with an
-appropriate stylus and read the values from samples.
-
-  # cat samples
-  1023 676 92 103 101 102 855 919 922 922 1023 679
-
-The first and eleventh samples are discarded.  Thus, the important
-values are the second and twelfth which are used to determine if the
-pen is down.  When both are below the threshold, the driver registers
-that the pen is down.  When either is above the threshold, it
-registers then pen is up.
diff --git a/Documentation/arm/Sharp-LH/CompactFlash b/Documentation/arm/Sharp-LH/CompactFlash
deleted file mode 100644
index 8616d87..0000000
--- a/Documentation/arm/Sharp-LH/CompactFlash
+++ /dev/null
@@ -1,32 +0,0 @@
-README on the Compact Flash for Card Engines
-============================================
-
-There are three challenges in supporting the CF interface of the Card
-Engines.  First, every IO operation must be followed with IO to
-another memory region.  Second, the slot is wired for one-to-one
-address mapping *and* it is wired for 16 bit access only.  Second, the
-interrupt request line from the CF device isn't wired.
-
-The IOBARRIER issue is covered in README.IOBARRIER.  This isn't an
-onerous problem.  Enough said here.
-
-The addressing issue is solved in the
-arch/arm/mach-lh7a40x/ide-lpd7a40x.c file with some awkward
-work-arounds.  We implement a special SELECT_DRIVE routine that is
-called before the IDE driver performs its own SELECT_DRIVE.  Our code
-recognizes that the SELECT register cannot be modified without also
-writing a command.  It send an IDLE_IMMEDIATE command on selecting a
-drive.  The function also prevents drive select to the slave drive
-since there can be only one.  The awkward part is that the IDE driver,
-even though we have a select procedure, also attempts to change the
-drive by writing directly the SELECT register.  This attempt is
-explicitly blocked by the OUTB function--not pretty, but effective.
-
-The lack of interrupts is a more serious problem.  Even though the CF
-card is fast when compared to a normal IDE device, we don't know that
-the CF is really flash.  A user could use one of the very small hard
-drives being shipped with a CF interface.  The IDE code includes a
-check for interfaces that lack an IRQ.  In these cases, submitting a
-command to the IDE controller is followed by a call to poll for
-completion.  If the device isn't immediately ready, it schedules a
-timer to poll again later.
diff --git a/Documentation/arm/Sharp-LH/IOBarrier b/Documentation/arm/Sharp-LH/IOBarrier
deleted file mode 100644
index 2e953e2..0000000
--- a/Documentation/arm/Sharp-LH/IOBarrier
+++ /dev/null
@@ -1,45 +0,0 @@
-README on the IOBARRIER for CardEngine IO
-=========================================
-
-Due to an unfortunate oversight when the Card Engines were designed,
-the signals that control access to some peripherals, most notably the
-SMC91C9111 ethernet controller, are not properly handled.
-
-The symptom is that some back to back IO with the peripheral returns
-unreliable data.  With the SMC chip, you'll see errors about the bank
-register being 'screwed'.
-
-The cause is that the AEN signal to the SMC chip does not transition
-for every memory access.  It is driven through the CPLD from the CS7
-line of the CPU's static memory controller which is optimized to
-eliminate unnecessary transitions.  Yet, the SMC requires a transition
-for every write access.  The Sharp website has more information about
-the effect this power-conserving feature has on peripheral
-interfacing.
-
-The solution is to follow every write access to the SMC chip with an
-access to another memory region that will force the CPU to release the
-chip select line.  It is important to guarantee that this access
-forces the CPU off-chip.  We map a page of SDRAM as if it were an
-uncacheable IO device and read from it after every SMC IO write
-operation.
-
-  SMC IO
-  BARRIER IO
-
-Only this sequence is important.  It does not matter that there is no
-BARRIER IO before the access to the SMC chip because the AEN latch
-only needs occurs after the SMC IO write cycle.  The routines that
-implement this work-around make an additional concession which is to
-disable interrupts during the IO sequence.  Other hardware devices
-(the LogicPD CPLD) have registers in the same physical memory
-region as the SMC chip.  An interrupt might allow an access to one of
-those registers while SMC IO is being performed.
-
-You might be tempted to think that we have to access another device
-attached to the static memory controller, but the empirical evidence
-indicates that this is not so.  Mapping 0x00000000 (flash) and
-0xc0000000 (SDRAM) appear to have the same effect.  Using SDRAM seems
-to be faster.  Choosing to access an undecoded memory region is not
-desirable as there is no way to know how that chip select will be used
-in the future.
diff --git a/Documentation/arm/Sharp-LH/KEV7A400 b/Documentation/arm/Sharp-LH/KEV7A400
deleted file mode 100644
index be32b14..0000000
--- a/Documentation/arm/Sharp-LH/KEV7A400
+++ /dev/null
@@ -1,8 +0,0 @@
-README on Implementing Linux for Sharp's KEV7a400
-=================================================
-
-This product has been discontinued by Sharp.  For the time being, the
-partially implemented code remains in the kernel.  At some point in
-the future, either the code will be finished or it will be removed
-completely.  This depends primarily on how many of the development
-boards are in the field.
diff --git a/Documentation/arm/Sharp-LH/LCDPanels b/Documentation/arm/Sharp-LH/LCDPanels
deleted file mode 100644
index fb1b21c..0000000
--- a/Documentation/arm/Sharp-LH/LCDPanels
+++ /dev/null
@@ -1,59 +0,0 @@
-README on the LCD Panels
-========================
-
-Configuration options for several LCD panels, available from Logic PD,
-are included in the kernel source.  This README will help you
-understand the configuration data and give you some guidance for
-adding support for other panels if you wish.
-
-
-lcd-panels.h
-------------
-
-There is no way, at present, to detect which panel is attached to the
-system at runtime.  Thus the kernel configuration is static.  The file
-arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the
-panel specific parameters.
-
-It should be possible for this data to be shared among several device
-families.  The current layout may be insufficiently general, but it is
-amenable to improvement.
-
-
-PIXEL_CLOCK
------------
-
-The panel data sheets will give a range of acceptable pixel clocks.
-The fundamental LCDCLK input frequency is divided down by a PCD
-constant in field '.tim2'.  It may happen that it is impossible to set
-the pixel clock within this range.  A clock which is too slow will
-tend to flicker.  For the highest quality image, set the clock as high
-as possible.
-
-
-MARGINS
--------
-
-These values may be difficult to glean from the panel data sheet.  In
-the case of the Sharp panels, the upper margin is explicitly called
-out as a specific number of lines from the top of the frame.  The
-other values may not matter as much as the panels tend to
-automatically center the image.
-
-
-Sync Sense
-----------
-
-The sense of the hsync and vsync pulses may be called out in the data
-sheet.  On one panel, the sense of these pulses determine the height
-of the visible region on the panel.  Most of the Sharp panels use
-negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in
-'.tim2'.
-
-
-Pel Layout
-----------
-
-The Sharp color TFT panels are all configured for 16 bit direct color
-modes.  The amba-lcd driver sets the pel mode to 565 for 5 bits of
-each red and blue and 6 bits of green.
diff --git a/Documentation/arm/Sharp-LH/LPD7A400 b/Documentation/arm/Sharp-LH/LPD7A400
deleted file mode 100644
index 3275b45..0000000
--- a/Documentation/arm/Sharp-LH/LPD7A400
+++ /dev/null
@@ -1,15 +0,0 @@
-README on Implementing Linux for the Logic PD LPD7A400-10
-=========================================================
-
-- CPLD memory mapping
-
-  The board designers chose to use high address lines for controlling
-  access to the CPLD registers.  It turns out to be a big waste
-  because we're using an MMU and must map IO space into virtual
-  memory.  The result is that we have to make a mapping for every
-  register.
-
-- Serial Console
-
-  It may be OK not to use the serial console option if the user passes
-  the console device name to the kernel.  This deserves some exploration.
diff --git a/Documentation/arm/Sharp-LH/LPD7A40X b/Documentation/arm/Sharp-LH/LPD7A40X
deleted file mode 100644
index 8c29a27..0000000
--- a/Documentation/arm/Sharp-LH/LPD7A40X
+++ /dev/null
@@ -1,16 +0,0 @@
-README on Implementing Linux for the Logic PD LPD7A40X-10
-=========================================================
-
-- CPLD memory mapping
-
-  The board designers chose to use high address lines for controlling
-  access to the CPLD registers.  It turns out to be a big waste
-  because we're using an MMU and must map IO space into virtual
-  memory.  The result is that we have to make a mapping for every
-  register.
-
-- Serial Console
-
-  It may be OK not to use the serial console option if the user passes
-  the console device name to the kernel.  This deserves some exploration.
-
diff --git a/Documentation/arm/Sharp-LH/SDRAM b/Documentation/arm/Sharp-LH/SDRAM
deleted file mode 100644
index 93ddc23..0000000
--- a/Documentation/arm/Sharp-LH/SDRAM
+++ /dev/null
@@ -1,51 +0,0 @@
-README on the SDRAM Controller for the LH7a40X
-==============================================
-
-The standard configuration for the SDRAM controller generates a sparse
-memory array.  The precise layout is determined by the SDRAM chips.  A
-default kernel configuration assembles the discontiguous memory
-regions into separate memory nodes via the NUMA (Non-Uniform Memory
-Architecture) facilities.  In this default configuration, the kernel
-is forgiving about the precise layout.  As long as it is given an
-accurate picture of available memory by the bootloader the kernel will
-execute correctly.
-
-The SDRC supports a mode where some of the chip select lines are
-swapped in order to make SDRAM look like a synchronous ROM.  Setting
-this bit means that the RAM will present as a contiguous array.  Some
-programmers prefer this to the discontiguous layout.  Be aware that
-may be a penalty for this feature where some some configurations of
-memory are significantly reduced; i.e. 64MiB of RAM appears as only 32
-MiB.
-
-There are a couple of configuration options to override the default
-behavior.  When the SROMLL bit is set and memory appears as a
-contiguous array, there is no reason to support NUMA.
-CONFIG_LH7A40X_CONTIGMEM disables NUMA support.  When physical memory
-is discontiguous, the memory tables are organized such that there are
-two banks per nodes with a small gap between them.  This layout wastes
-some kernel memory for page tables representing non-existent memory.
-CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that
-there are no gaps.  These options control the low level organization
-of the memory management tables in ways that may prevent the kernel
-from booting or may cause the kernel to allocated excessively large
-page tables.  Be warned.  Only change these options if you know what
-you are doing.  The default behavior is a reasonable compromise that
-will suit all users.
-
---
-
-A typical 32MiB system with the default configuration options will
-find physical memory managed as follows.
-
-   node 0: 0xc0000000 4MiB
-           0xc1000000 4MiB
-   node 1: 0xc4000000 4MiB
-           0xc5000000 4MiB
-   node 2: 0xc8000000 4MiB
-           0xc9000000 4MiB
-   node 3: 0xcc000000 4MiB
-           0xcd000000 4MiB
-
-Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a
-separate node.
diff --git a/Documentation/arm/Sharp-LH/VectoredInterruptController b/Documentation/arm/Sharp-LH/VectoredInterruptController
deleted file mode 100644
index 23047e9..0000000
--- a/Documentation/arm/Sharp-LH/VectoredInterruptController
+++ /dev/null
@@ -1,80 +0,0 @@
-README on the Vectored Interrupt Controller of the LH7A404
-==========================================================
-
-The 404 revision of the LH7A40X series comes with two vectored
-interrupts controllers.  While the kernel does use some of the
-features of these devices, it is far from the purpose for which they
-were designed.
-
-When this README was written, the implementation of the VICs was in
-flux.  It is possible that some details, especially with priorities,
-will change.
-
-The VIC support code is inspired by routines written by Sharp.
-
-
-Priority Control
-----------------
-
-The significant reason for using the VIC's vectoring is to control
-interrupt priorities.  There are two tables in
-arch/arm/mach-lh7a40x/irq-lh7a404.c that look something like this.
-
-  static unsigned char irq_pri_vic1[] = { IRQ_GPIO3INTR, };
-  static unsigned char irq_pri_vic2[] = {
-	IRQ_T3UI, IRQ_GPIO7INTR,
-	IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR, };
-
-The initialization code reads these tables and inserts a vector
-address and enable for each indicated IRQ.  Vectored interrupts have
-higher priority than non-vectored interrupts.  So, on VIC1,
-IRQ_GPIO3INTR will be served before any other non-FIQ interrupt.  Due
-to the way that the vectoring works, IRQ_T3UI is the next highest
-priority followed by the other vectored interrupts on VIC2.  After
-that, the non-vectored interrupts are scanned in VIC1 then in VIC2.
-
-
-ISR
----
-
-The interrupt service routine macro get_irqnr() in
-arch/arm/kernel/entry-armv.S scans the VICs for the next active
-interrupt.  The vectoring makes this code somewhat larger than it was
-before using vectoring (refer to the LH7A400 implementation).  In the
-case where an interrupt is vectored, the implementation will tend to
-be faster than the non-vectored version.  However, the worst-case path
-is longer.
-
-It is worth noting that at present, there is no need to read
-VIC2_VECTADDR because the register appears to be shared between the
-controllers.  The code is written such that if this changes, it ought
-to still work properly.
-
-
-Vector Addresses
-----------------
-
-The proper use of the vectoring hardware would jump to the ISR
-specified by the vectoring address.  Linux isn't structured to take
-advantage of this feature, though it might be possible to change
-things to support it.
-
-In this implementation, the vectoring address is used to speed the
-search for the active IRQ.  The address is coded such that the lowest
-6 bits store the IRQ number for vectored interrupts.  These numbers
-correspond to the bits in the interrupt status registers.  IRQ zero is
-the lowest interrupt bit in VIC1.  IRQ 32 is the lowest interrupt bit
-in VIC2.  Because zero is a valid IRQ number and because we cannot
-detect whether or not there is a valid vectoring address if that
-address is zero, the eigth bit (0x100) is set for vectored interrupts.
-The address for IRQ 0x18 (VIC2) is 0x118.  Only the ninth bit is set
-for the default handler on VIC1 and only the tenth bit is set for the
-default handler on VIC2.
-
-In other words.
-
-  0x000		- no active interrupt
-  0x1ii		- vectored interrupt 0xii
-  0x2xx		- unvectored interrupt on VIC1 (xx is don't care)
-  0x4xx		- unvectored interrupt on VIC2 (xx is don't care)
-
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 44b8b7a..cbdfb7d 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -349,6 +349,10 @@ To mount a cgroup hierarchy with all available subsystems, type:
 The "xxx" is not interpreted by the cgroup code, but will appear in
 /proc/mounts so may be any useful identifying string that you like.
 
+Note: Some subsystems do not work without some user input first.  For instance,
+if cpusets are enabled the user will have to populate the cpus and mems files
+for each new cgroup created before that group can be used.
+
 To mount a cgroup hierarchy with just the cpuset and memory
 subsystems, type:
 # mount -t cgroup -o cpuset,memory hier1 /dev/cgroup
@@ -426,6 +430,14 @@ You can attach the current shell task by echoing 0:
 
 # echo 0 > tasks
 
+Note: Since every task is always a member of exactly one cgroup in each
+mounted hierarchy, to remove a task from its current cgroup you must
+move it into a new cgroup (possibly the root cgroup) by writing to the
+new cgroup's tasks file.
+
+Note: If the ns cgroup is active, moving a process to another cgroup can
+fail.
+
 2.3 Mounting hierarchies by name
 --------------------------------
 
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 5d0d569..98a3082 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -693,7 +693,7 @@ There are ways to query or modify cpusets:
  - via the C library libcgroup.
    (http://sourceforge.net/projects/libcg/)
  - via the python application cset.
-   (http://developer.novell.com/wiki/index.php/Cpuset)
+   (http://code.google.com/p/cpuset/)
 
 The sched_setaffinity calls can also be done at the shell prompt using
 SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
@@ -725,13 +725,14 @@ Now you want to do something with this cpuset.
 
 In this directory you can find several files:
 # ls
-cpuset.cpu_exclusive       cpuset.memory_spread_slab
-cpuset.cpus                cpuset.mems
-cpuset.mem_exclusive       cpuset.sched_load_balance
-cpuset.mem_hardwall        cpuset.sched_relax_domain_level
-cpuset.memory_migrate      notify_on_release
-cpuset.memory_pressure     tasks
-cpuset.memory_spread_page
+cgroup.clone_children  cpuset.memory_pressure
+cgroup.event_control   cpuset.memory_spread_page
+cgroup.procs           cpuset.memory_spread_slab
+cpuset.cpu_exclusive   cpuset.mems
+cpuset.cpus            cpuset.sched_load_balance
+cpuset.mem_exclusive   cpuset.sched_relax_domain_level
+cpuset.mem_hardwall    notify_on_release
+cpuset.memory_migrate  tasks
 
 Reading them will give you information about the state of this cpuset:
 the CPUs and Memory Nodes it can use, the processes that are using
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 7781857..b6ed61c 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -485,8 +485,9 @@ The feature can be disabled by
 
 # echo 0 > memory.use_hierarchy
 
-NOTE1: Enabling/disabling will fail if the cgroup already has other
-       cgroups created below it.
+NOTE1: Enabling/disabling will fail if either the cgroup already has other
+       cgroups created below it, or if the parent cgroup has use_hierarchy
+       enabled.
 
 NOTE2: When panic_on_oom is set to "2", the whole system will panic in
        case of an OOM event in any cgroup.
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 737988f..e74d0a2 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -158,6 +158,17 @@ intensive calculation on your laptop that you do not care how long it
 takes to complete as you can 'nice' it and prevent it from taking part
 in the deciding process of whether to increase your CPU frequency.
 
+sampling_down_factor: this parameter controls the rate at which the
+kernel makes a decision on when to decrease the frequency while running
+at top speed. When set to 1 (the default) decisions to reevaluate load
+are made at the same interval regardless of current clock speed. But
+when set to greater than 1 (e.g. 100) it acts as a multiplier for the
+scheduling interval for reevaluating load when the CPU is at its top
+speed due to high load. This improves performance by reducing the overhead
+of load evaluation and helping the CPU stay at its top speed when truly
+busy, rather than shifting back and forth in speed. This tunable has no
+effect on behavior at lower speeds/lower CPU loads.
+
 
 2.5 Conservative
 ----------------
diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt
index 59293ac..6b5c42d 100644
--- a/Documentation/device-mapper/dm-crypt.txt
+++ b/Documentation/device-mapper/dm-crypt.txt
@@ -41,7 +41,7 @@ Example scripts
 ===============
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
 encryption with dm-crypt using the 'cryptsetup' utility, see
-http://clemens.endorphin.org/cryptography
+http://code.google.com/p/cryptsetup/
 
 [[
 #!/bin/sh
diff --git a/Documentation/devicetree/00-INDEX b/Documentation/devicetree/00-INDEX
new file mode 100644
index 0000000..b78f691
--- /dev/null
+++ b/Documentation/devicetree/00-INDEX
@@ -0,0 +1,10 @@
+Documentation for device trees, a data structure by which bootloaders pass
+hardware layout to Linux in a device-independent manner, simplifying hardware
+probing.  This subsystem is maintained by Grant Likely
+<grant.likely@secretlab.ca> and has a mailing list at
+https://lists.ozlabs.org/listinfo/devicetree-discuss
+
+00-INDEX
+	- this file
+booting-without-of.txt
+	- Booting Linux without Open Firmware, describes history and format of device trees.
diff --git a/Documentation/devicetree/bindings/hwmon/ads1015.txt b/Documentation/devicetree/bindings/hwmon/ads1015.txt
new file mode 100644
index 0000000..918a507
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/ads1015.txt
@@ -0,0 +1,73 @@
+ADS1015 (I2C)
+
+This device is a 12-bit A-D converter with 4 inputs.
+
+The inputs can be used single ended or in certain differential combinations.
+
+For configuration all possible combinations are mapped to 8 channels:
+  0: Voltage over AIN0 and AIN1.
+  1: Voltage over AIN0 and AIN3.
+  2: Voltage over AIN1 and AIN3.
+  3: Voltage over AIN2 and AIN3.
+  4: Voltage over AIN0 and GND.
+  5: Voltage over AIN1 and GND.
+  6: Voltage over AIN2 and GND.
+  7: Voltage over AIN3 and GND.
+
+Each channel can be configured individually:
+ - pga is the programmable gain amplifier (values are full scale)
+    0: +/- 6.144 V
+    1: +/- 4.096 V
+    2: +/- 2.048 V (default)
+    3: +/- 1.024 V
+    4: +/- 0.512 V
+    5: +/- 0.256 V
+ - data_rate in samples per second
+    0: 128
+    1: 250
+    2: 490
+    3: 920
+    4: 1600 (default)
+    5: 2400
+    6: 3300
+
+1) The /ads1015 node
+
+  Required properties:
+
+   - compatible : must be "ti,ads1015"
+   - reg : I2C bus address of the device
+   - #address-cells : must be <1>
+   - #size-cells : must be <0>
+
+  The node contains child nodes for each channel that the platform uses.
+
+  Example ADS1015 node:
+
+    ads1015@49 {
+	    compatible = "ti,ads1015";
+	    reg = <0x49>;
+	    #address-cells = <1>;
+	    #size-cells = <0>;
+
+	    [ child node definitions... ]
+    }
+
+2) channel nodes
+
+  Required properties:
+
+   - reg : the channel number
+
+  Optional properties:
+
+   - ti,gain : the programmable gain amplifier setting
+   - ti,datarate : the converter data rate
+
+  Example ADS1015 channel node:
+
+    channel@4 {
+	    reg = <4>;
+	    ti,gain = <3>;
+	    ti,datarate = <5>;
+    };
diff --git a/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
new file mode 100644
index 0000000..569b162
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
@@ -0,0 +1,93 @@
+CE4100 I2C
+----------
+
+CE4100 has one PCI device which is described as the I2C-Controller. This
+PCI device has three PCI-bars, each bar contains a complete I2C
+controller. So we have a total of three independent I2C-Controllers
+which share only an interrupt line.
+The driver is probed via the PCI-ID and is gathering the information of
+attached devices from the devices tree.
+Grant Likely recommended to use the ranges property to map the PCI-Bar
+number to its physical address and to use this to find the child nodes
+of the specific I2C controller. This were his exact words:
+
+       Here's where the magic happens.  Each entry in
+       ranges describes how the parent pci address space
+       (middle group of 3) is translated to the local
+       address space (first group of 2) and the size of
+       each range (last cell).  In this particular case,
+       the first cell of the local address is chosen to be
+       1:1 mapped to the BARs, and the second is the
+       offset from be base of the BAR (which would be
+       non-zero if you had 2 or more devices mapped off
+       the same BAR)
+
+       ranges allows the address mapping to be described
+       in a way that the OS can interpret without
+       requiring custom device driver code.
+
+This is an example which is used on FalconFalls:
+------------------------------------------------
+	i2c-controller@b,2 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "pci8086,2e68.2",
+				"pci8086,2e68",
+				"pciclass,ff0000",
+				"pciclass,ff00";
+
+		reg = <0x15a00 0x0 0x0 0x0 0x0>;
+		interrupts = <16 1>;
+
+		/* as described by Grant, the first number in the group of
+		* three is the bar number followed by the 64bit bar address
+		* followed by size of the mapping. The bar address
+		* requires also a valid translation in parents ranges
+		* property.
+		*/
+		ranges = <0 0   0x02000000 0 0xdffe0500 0x100
+			  1 0   0x02000000 0 0xdffe0600 0x100
+			  2 0   0x02000000 0 0xdffe0700 0x100>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+
+			/* The first number in the reg property is the
+			* number of the bar
+			*/
+			reg = <0 0 0x100>;
+
+			/* This I2C controller has no devices */
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+			reg = <1 0 0x100>;
+
+			/* This I2C controller has one gpio controller */
+			gpio@26 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8575";
+				reg = <0x26>;
+				gpio-controller;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+			reg = <2 0 0x100>;
+
+			gpio@26 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8575";
+				reg = <0x26>;
+				gpio-controller;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
index c39ac28..89a0084 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
+++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
@@ -7,8 +7,13 @@ Required properties:
 - voltage-ranges : two cells are required, first cell specifies minimum
   slot voltage (mV), second cell specifies maximum slot voltage (mV).
   Several ranges could be specified.
-- gpios : (optional) may specify GPIOs in this order: Card-Detect GPIO,
+
+Optional properties:
+- gpios : may specify GPIOs in this order: Card-Detect GPIO,
   Write-Protect GPIO.
+- interrupts : the interrupt of a card detect interrupt.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
 
 Example:
 
@@ -20,4 +25,6 @@ Example:
 			 &qe_pio_d 15 0>;
 		voltage-ranges = <3300 3300>;
 		spi-max-frequency = <50000000>;
+		interrupts = <42>;
+		interrupt-parent = <&PIC>;
 	};
diff --git a/Documentation/devicetree/bindings/open-pic.txt b/Documentation/devicetree/bindings/open-pic.txt
new file mode 100644
index 0000000..909a902
--- /dev/null
+++ b/Documentation/devicetree/bindings/open-pic.txt
@@ -0,0 +1,98 @@
+* Open PIC Binding
+
+This binding specifies what properties must be available in the device tree
+representation of an Open PIC compliant interrupt controller.  This binding is
+based on the binding defined for Open PIC in [1] and is a superset of that
+binding.
+
+Required properties:
+
+  NOTE: Many of these descriptions were paraphrased here from [1] to aid
+        readability.
+
+    - compatible: Specifies the compatibility list for the PIC.  The type
+      shall be <string> and the value shall include "open-pic".
+
+    - reg: Specifies the base physical address(s) and size(s) of this
+      PIC's addressable register space.  The type shall be <prop-encoded-array>.
+
+    - interrupt-controller: The presence of this property identifies the node
+      as an Open PIC.  No property value shall be defined.
+
+    - #interrupt-cells: Specifies the number of cells needed to encode an
+      interrupt source.  The type shall be a <u32> and the value shall be 2.
+
+    - #address-cells: Specifies the number of cells needed to encode an
+      address.  The type shall be <u32> and the value shall be 0.  As such,
+      'interrupt-map' nodes do not have to specify a parent unit address.
+
+Optional properties:
+
+    - pic-no-reset: The presence of this property indicates that the PIC
+      shall not be reset during runtime initialization.  No property value shall
+      be defined.  The presence of this property also mandates that any
+      initialization related to interrupt sources shall be limited to sources
+      explicitly referenced in the device tree.
+
+* Interrupt Specifier Definition
+
+  Interrupt specifiers consists of 2 cells encoded as
+  follows:
+
+    - <1st-cell>: The interrupt-number that identifies the interrupt source.
+
+    - <2nd-cell>: The level-sense information, encoded as follows:
+                    0 = low-to-high edge triggered
+                    1 = active low level-sensitive
+                    2 = active high level-sensitive
+                    3 = high-to-low edge triggered
+
+* Examples
+
+Example 1:
+
+	/*
+	 * An Open PIC interrupt controller
+	 */
+	mpic: pic@40000 {
+		// This is an interrupt controller node.
+		interrupt-controller;
+
+		// No address cells so that 'interrupt-map' nodes which reference
+		// this Open PIC node do not need a parent address specifier.
+		#address-cells = <0>;
+
+		// Two cells to encode interrupt sources.
+		#interrupt-cells = <2>;
+
+		// Offset address of 0x40000 and size of 0x40000.
+		reg = <0x40000 0x40000>;
+
+		// Compatible with Open PIC.
+		compatible = "open-pic";
+
+		// The PIC shall not be reset.
+		pic-no-reset;
+	};
+
+Example 2:
+
+	/*
+	 * An interrupt generating device that is wired to an Open PIC.
+	 */
+	serial0: serial@4500 {
+		// Interrupt source '42' that is active high level-sensitive.
+		// Note that there are only two cells as specified in the interrupt
+		// parent's '#interrupt-cells' property.
+		interrupts = <42 2>;
+
+		// The interrupt controller that this device is wired to.
+		interrupt-parent = <&mpic>;
+	};
+
+* References
+
+[1] Power.org (TM) Standard for Embedded Power Architecture (TM) Platform
+    Requirements (ePAPR), Version 1.0, July 2008.
+    (http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf)
+
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt b/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt
new file mode 100644
index 0000000..781955f
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt
@@ -0,0 +1,20 @@
+* Freescale PQ3 and QorIQ based Cache SRAM
+
+Freescale's mpc85xx and some QorIQ platforms provide an
+option of configuring a part of (or full) cache memory
+as SRAM. This cache SRAM representation in the device
+tree should be done as under:-
+
+Required properties:
+
+- compatible : should be "fsl,p2020-cache-sram"
+- fsl,cache-sram-ctlr-handle : points to the L2 controller
+- reg : offset and length of the cache-sram.
+
+Example:
+
+cache-sram@fff00000 {
+	fsl,cache-sram-ctlr-handle = <&L2>;
+	reg = <0 0xfff00000 0 0x10000>;
+	compatible = "fsl,p2020-cache-sram";
+};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
index 71e39cf..8aa10f4 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
@@ -1,42 +1,211 @@
-* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores
-
-The OpenPIC specification does not specify which interrupt source has to
-become which interrupt number. This is up to the software implementation
-of the interrupt controller. The only requirement is that every
-interrupt source has to have an unique interrupt number / vector number.
-To accomplish this the current implementation assigns the number zero to
-the first source, the number one to the second source and so on until
-all interrupt sources have their unique number.
-Usually the assigned vector number equals the interrupt number mentioned
-in the documentation for a given core / CPU. This is however not true
-for the e500 cores (MPC85XX CPUs) where the documentation distinguishes
-between internal and external interrupt sources and starts counting at
-zero for both of them.
-
-So what to write for external interrupt source X or internal interrupt
-source Y into the device tree? Here is an example:
-
-The memory map for the interrupt controller in the MPC8544[0] shows,
-that the first interrupt source starts at 0x5_0000 (PIC Register Address
-Map-Interrupt Source Configuration Registers). This source becomes the
-number zero therefore:
- External interrupt 0 = interrupt number 0
- External interrupt 1 = interrupt number 1
- External interrupt 2 = interrupt number 2
- ...
-Every interrupt number allocates 0x20 bytes register space. So to get
-its number it is sufficient to shift the lower 16bits to right by five.
-So for the external interrupt 10 we have:
-  0x0140 >> 5 = 10
-
-After the external sources, the internal sources follow. The in core I2C
-controller on the MPC8544 for instance has the internal source number
-27. Oo obtain its interrupt number we take the lower 16bits of its memory
-address (0x5_0560) and shift it right:
- 0x0560 >> 5 = 43
-
-Therefore the I2C device node for the MPC8544 CPU has to have the
-interrupt number 43 specified in the device tree.
-
-[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual
-    MPC8544ERM Rev. 1 10/2007
+=====================================================================
+Freescale MPIC Interrupt Controller Node
+Copyright (C) 2010,2011 Freescale Semiconductor Inc.
+=====================================================================
+
+The Freescale MPIC interrupt controller is found on all PowerQUICC
+and QorIQ processors and is compatible with the Open PIC.  The
+notable difference from Open PIC binding is the addition of 2
+additional cells in the interrupt specifier defining interrupt type
+information.
+
+PROPERTIES
+
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Shall include "fsl,mpic".  Freescale MPIC
+          controllers compatible with this binding have Block
+          Revision Registers BRR1 and BRR2 at offset 0x0 and
+          0x10 in the MPIC.
+
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  Specifies the physical
+          offset and length of the device's registers within the
+          CCSR address space.
+
+  - interrupt-controller
+      Usage: required
+      Value type: <empty>
+      Definition: Specifies that this node is an interrupt
+          controller
+
+  - #interrupt-cells
+      Usage: required
+      Value type: <u32>
+      Definition: Shall be 2 or 4.  A value of 2 means that interrupt
+          specifiers do not contain the interrupt-type or type-specific
+          information cells.
+
+  - #address-cells
+      Usage: required
+      Value type: <u32>
+      Definition: Shall be 0.
+
+  - pic-no-reset
+      Usage: optional
+      Value type: <empty>
+      Definition: The presence of this property specifies that the
+          MPIC must not be reset by the client program, and that
+          the boot program has initialized all interrupt source
+          configuration registers to a sane state-- masked or
+          directed at other cores.  This ensures that the client
+          program will not receive interrupts for sources not belonging
+          to the client.  The presence of this property also mandates
+          that any initialization related to interrupt sources shall
+          be limited to sources explicitly referenced in the device tree.
+       
+INTERRUPT SPECIFIER DEFINITION
+
+  Interrupt specifiers consists of 4 cells encoded as
+  follows:
+
+   <1st-cell>   interrupt-number
+
+                Identifies the interrupt source.  The meaning
+                depends on the type of interrupt.
+
+                Note: If the interrupt-type cell is undefined
+                (i.e. #interrupt-cells = 2), this cell
+                should be interpreted the same as for
+                interrupt-type 0-- i.e. an external or
+                normal SoC device interrupt.
+
+   <2nd-cell>   level-sense information, encoded as follows:
+                    0 = low-to-high edge triggered
+                    1 = active low level-sensitive
+                    2 = active high level-sensitive
+                    3 = high-to-low edge triggered
+
+   <3rd-cell>   interrupt-type
+
+                The following types are supported:
+
+                  0 = external or normal SoC device interrupt
+
+                      The interrupt-number cell contains
+                      the SoC device interrupt number.  The
+                      type-specific cell is undefined.  The
+                      interrupt-number is derived from the
+                      MPIC a block of registers referred to as
+                      the "Interrupt Source Configuration Registers".
+                      Each source has 32-bytes of registers
+                      (vector/priority and destination) in this
+                      region.   So interrupt 0 is at offset 0x0,
+                      interrupt 1 is at offset 0x20, and so on.
+
+                  1 = error interrupt
+
+                      The interrupt-number cell contains
+                      the SoC device interrupt number for
+                      the error interrupt.  The type-specific
+                      cell identifies the specific error
+                      interrupt number.
+
+                  2 = MPIC inter-processor interrupt (IPI)
+
+                      The interrupt-number cell identifies
+                      the MPIC IPI number.  The type-specific
+                      cell is undefined.
+
+                  3 = MPIC timer interrupt
+
+                      The interrupt-number cell identifies
+                      the MPIC timer number.  The type-specific
+                      cell is undefined.
+
+   <4th-cell>   type-specific information
+
+                The type-specific cell is encoded as follows:
+
+                 - For interrupt-type 1 (error interrupt),
+                   the type-specific cell contains the
+                   bit number of the error interrupt in the
+                   Error Interrupt Summary Register.
+
+EXAMPLE 1
+	/*
+	 * mpic interrupt controller with 4 cells per specifier
+	 */
+	mpic: pic@40000 {
+		compatible = "fsl,mpic";
+		interrupt-controller;
+		#interrupt-cells = <4>;
+		#address-cells = <0>;
+		reg = <0x40000 0x40000>;
+	};
+
+EXAMPLE 2
+	/*
+	 * The MPC8544 I2C controller node has an internal
+	 * interrupt number of 27.  As per the reference manual
+	 * this corresponds to interrupt source configuration
+	 * registers at 0x5_0560.
+	 *
+	 * The interrupt source configuration registers begin
+	 * at 0x5_0000.
+	 *
+	 * To compute the interrupt specifier interrupt number
+         *
+	 *       0x560 >> 5 = 43
+	 *
+	 * The interrupt source configuration registers begin
+	 * at 0x5_0000, and so the i2c vector/priority registers
+	 * are at 0x5_0560.
+	 */
+	i2c@3000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		compatible = "fsl-i2c";
+		reg = <0x3000 0x100>;
+		interrupts = <43 2>;
+		interrupt-parent = <&mpic>;
+		dfsrr;
+	};
+
+
+EXAMPLE 3
+	/*
+	 *  Definition of a node defining the 4
+	 *  MPIC IPI interrupts.  Note the interrupt
+	 *  type of 2.
+	 */
+	ipi@410a0 {
+		compatible = "fsl,mpic-ipi";
+		reg = <0x40040 0x10>;
+		interrupts = <0 0 2 0
+		              1 0 2 0
+		              2 0 2 0
+		              3 0 2 0>;
+	};
+
+EXAMPLE 4
+	/*
+	 *  Definition of a node defining the MPIC
+	 *  global timers.  Note the interrupt
+	 *  type of 3.
+	 */
+	timer0: timer@41100 {
+		compatible = "fsl,mpic-global-timer";
+		reg = <0x41100 0x100>;
+		interrupts = <0 0 3 0
+		              1 0 3 0
+		              2 0 3 0
+		              3 0 3 0>;
+	};
+
+EXAMPLE 5
+	/*
+	 * Definition of an error interrupt (interupt type 1).
+	 * SoC interrupt number is 16 and the specific error
+         * interrupt bit in the error interrupt summary register
+	 * is 23.
+	 */
+	memory-controller@8000 {
+		compatible = "fsl,p4080-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 23>;
+	};
diff --git a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
index bcc30ba..70558c3 100644
--- a/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
+++ b/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
@@ -5,14 +5,21 @@ Required properties:
   first is "fsl,CHIP-msi", where CHIP is the processor(mpc8610, mpc8572,
   etc.) and the second is "fsl,mpic-msi" or "fsl,ipic-msi" depending on
   the parent type.
+
 - reg : should contain the address and the length of the shared message
   interrupt register set.
+
 - msi-available-ranges: use <start count> style section to define which
   msi interrupt can be used in the 256 msi interrupts. This property is
   optional, without this, all the 256 MSI interrupts can be used.
+  Each available range must begin and end on a multiple of 32 (i.e.
+  no splitting an individual MSI register or the associated PIC interrupt).
+
 - interrupts : each one of the interrupts here is one entry per 32 MSIs,
   and routed to the host interrupt controller. the interrupts should
-  be set as edge sensitive.
+  be set as edge sensitive.  If msi-available-ranges is present, only
+  the interrupts that correspond to available ranges shall be present.
+
 - interrupt-parent: the phandle for the interrupt controller
   that services interrupts for this device. for 83xx cpu, the interrupts
   are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
diff --git a/Documentation/devicetree/bindings/rtc/rtc-cmos.txt b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
new file mode 100644
index 0000000..7382989
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
@@ -0,0 +1,28 @@
+ Motorola mc146818 compatible RTC
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Required properties:
+  - compatible : "motorola,mc146818"
+  - reg : should contain registers location and length.
+
+Optional properties:
+  - interrupts : should contain interrupt.
+  - interrupt-parent : interrupt source phandle.
+  - ctrl-reg : Contains the initial value of the control register also
+    called "Register B".
+  - freq-reg : Contains the initial value of the frequency register also
+    called "Regsiter A".
+
+"Register A" and "B" are usually initialized by the firmware (BIOS for
+instance). If this is not done, it can be performed by the driver.
+
+ISA Example:
+
+	rtc@70 {
+	         compatible = "motorola,mc146818";
+	         interrupts = <8 3>;
+	         interrupt-parent = <&ioapic1>;
+	         ctrl-reg = <2>;
+	         freq-reg = <0x26>;
+	         reg = <1 0x70 2>;
+	 };
diff --git a/Documentation/devicetree/bindings/serial/altera_jtaguart.txt b/Documentation/devicetree/bindings/serial/altera_jtaguart.txt
new file mode 100644
index 0000000..c152f65
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/altera_jtaguart.txt
@@ -0,0 +1,4 @@
+Altera JTAG UART
+
+Required properties:
+- compatible : should be "ALTR,juart-1.0"
diff --git a/Documentation/devicetree/bindings/serial/altera_uart.txt b/Documentation/devicetree/bindings/serial/altera_uart.txt
new file mode 100644
index 0000000..71cae3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/altera_uart.txt
@@ -0,0 +1,7 @@
+Altera UART
+
+Required properties:
+- compatible : should be "ALTR,uart-1.0"
+
+Optional properties:
+- clock-frequency : frequency of the clock input to the UART
diff --git a/Documentation/devicetree/bindings/serio/altera_ps2.txt b/Documentation/devicetree/bindings/serio/altera_ps2.txt
new file mode 100644
index 0000000..4d9eecc
--- /dev/null
+++ b/Documentation/devicetree/bindings/serio/altera_ps2.txt
@@ -0,0 +1,4 @@
+Altera UP PS/2 controller
+
+Required properties:
+- compatible : should be "ALTR,ps2-1.0".
diff --git a/Documentation/devicetree/bindings/spi/spi_altera.txt b/Documentation/devicetree/bindings/spi/spi_altera.txt
new file mode 100644
index 0000000..dda3759
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_altera.txt
@@ -0,0 +1,4 @@
+Altera SPI
+
+Required properties:
+- compatible : should be "ALTR,spi-1.0".
diff --git a/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt b/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt
new file mode 100644
index 0000000..d95c0b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt
@@ -0,0 +1,12 @@
+OpenCores tiny SPI
+
+Required properties:
+- compatible : should be "opencores,tiny-spi-rtlsvn2".
+- gpios : should specify GPIOs used for chipselect.
+Optional properties:
+- clock-frequency : input clock frequency to the core.
+- baud-width: width, in bits, of the programmable divider used to scale
+	the input clock to SCLK.
+
+The clock-frequency and baud-width properties are needed only if the divider
+is programmable. They are not needed if the divider is fixed.
diff --git a/Documentation/devicetree/bindings/x86/ce4100.txt b/Documentation/devicetree/bindings/x86/ce4100.txt
new file mode 100644
index 0000000..b49ae59
--- /dev/null
+++ b/Documentation/devicetree/bindings/x86/ce4100.txt
@@ -0,0 +1,38 @@
+CE4100 Device Tree Bindings
+---------------------------
+
+The CE4100 SoC uses for in core peripherals the following compatible
+format: <vendor>,<chip>-<device>.
+Many of the "generic" devices like HPET or IO APIC have the ce4100
+name in their compatible property because they first appeared in this
+SoC.
+
+The CPU node
+------------
+	cpu@0 {
+		device_type = "cpu";
+		compatible = "intel,ce4100";
+		reg = <0>;
+		lapic = <&lapic0>;
+	};
+
+The reg property describes the CPU number. The lapic property points to
+the local APIC timer.
+
+The SoC node
+------------
+
+This node describes the in-core peripherals. Required property:
+  compatible = "intel,ce4100-cp";
+
+The PCI node
+------------
+This node describes the PCI bus on the SoC. Its property should be
+  compatible = "intel,ce4100-pci", "pci";
+
+If the OS is using the IO-APIC for interrupt routing then the reported
+interrupt numbers for devices is no longer true. In order to obtain the
+correct interrupt number, the child node which represents the device has
+to contain the interrupt property. Besides the interrupt property it has
+to contain at least the reg property containing the PCI bus address and
+compatible property according to "PCI Bus Binding Revision 2.1".
diff --git a/Documentation/devicetree/bindings/x86/interrupt.txt b/Documentation/devicetree/bindings/x86/interrupt.txt
new file mode 100644
index 0000000..7d19f49
--- /dev/null
+++ b/Documentation/devicetree/bindings/x86/interrupt.txt
@@ -0,0 +1,26 @@
+Interrupt chips
+---------------
+
+* Intel I/O Advanced Programmable Interrupt Controller (IO APIC)
+
+  Required properties:
+  --------------------
+     compatible = "intel,ce4100-ioapic";
+     #interrupt-cells = <2>;
+
+  Device's interrupt property:
+
+     interrupts = <P S>;
+
+  The first number (P) represents the interrupt pin which is wired to the
+  IO APIC. The second number (S) represents the sense of interrupt which
+  should be configured and can be one of:
+    0 - Edge Rising
+    1 - Level Low
+    2 - Level High
+    3 - Edge Falling
+
+* Local APIC
+  Required property:
+
+     compatible = "intel,ce4100-lapic";
diff --git a/Documentation/devicetree/bindings/x86/timer.txt b/Documentation/devicetree/bindings/x86/timer.txt
new file mode 100644
index 0000000..c688af5
--- /dev/null
+++ b/Documentation/devicetree/bindings/x86/timer.txt
@@ -0,0 +1,6 @@
+Timers
+------
+
+* High Precision Event Timer (HPET)
+  Required property:
+     compatible = "intel,ce4100-hpet";
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt
index 28b1c9d..55fd262 100644
--- a/Documentation/devicetree/booting-without-of.txt
+++ b/Documentation/devicetree/booting-without-of.txt
@@ -13,6 +13,7 @@ Table of Contents
 
   I - Introduction
     1) Entry point for arch/powerpc
+    2) Entry point for arch/x86
 
   II - The DT block format
     1) Header
@@ -225,6 +226,25 @@ it with special cases.
   cannot support both configurations with Book E and configurations
   with classic Powerpc architectures.
 
+2) Entry point for arch/x86
+-------------------------------
+
+  There is one single 32bit entry point to the kernel at code32_start,
+  the decompressor (the real mode entry point goes to the same  32bit
+  entry point once it switched into protected mode). That entry point
+  supports one calling convention which is documented in
+  Documentation/x86/boot.txt
+  The physical pointer to the device-tree block (defined in chapter II)
+  is passed via setup_data which requires at least boot protocol 2.09.
+  The type filed is defined as
+
+  #define SETUP_DTB                      2
+
+  This device-tree is used as an extension to the "boot page". As such it
+  does not parse / consider data which is already covered by the boot
+  page. This includes memory size, reserved ranges, command line arguments
+  or initrd address. It simply holds information which can not be retrieved
+  otherwise like interrupt routing or a list of devices behind an I2C bus.
 
 II - The DT block format
 ========================
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt
index 58ea64a..e6c4b75 100644
--- a/Documentation/dynamic-debug-howto.txt
+++ b/Documentation/dynamic-debug-howto.txt
@@ -205,12 +205,20 @@ of the characters:
 
 The flags are:
 
+f
+    Include the function name in the printed message
+l
+    Include line number in the printed message
+m
+    Include module name in the printed message
 p
     Causes a printk() message to be emitted to dmesg
+t
+    Include thread ID in messages not generated from interrupt context
 
-Note the regexp ^[-+=][scp]+$ matches a flags specification.
+Note the regexp ^[-+=][flmpt]+$ matches a flags specification.
 Note also that there is no convenient syntax to remove all
-the flags at once, you need to use "-psc".
+the flags at once, you need to use "-flmpt".
 
 
 Debug messages during boot process
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b3f35e5..8953309 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -35,6 +35,17 @@ Who:	Luis R. Rodriguez <lrodriguez@atheros.com>
 
 ---------------------------
 
+What:	AR9170USB
+When:	2.6.40
+
+Why:	This driver is deprecated and the firmware is no longer
+	maintained. The replacement driver "carl9170" has been
+	around for a while, so the devices are still supported.
+
+Who:	Christian Lamparter <chunkeey@googlemail.com>
+
+---------------------------
+
 What:	IRQF_SAMPLE_RANDOM
 Check:	IRQF_SAMPLE_RANDOM
 When:	July 2009
@@ -574,16 +585,6 @@ Who:    NeilBrown <neilb@suse.de>
 
 ----------------------------
 
-What:	i2c_adapter.id
-When:	June 2011
-Why:	This field is deprecated. I2C device drivers shouldn't change their
-	behavior based on the underlying I2C adapter. Instead, the I2C
-	adapter driver should instantiate the I2C devices and provide the
-	needed platform-specific information.
-Who:	Jean Delvare <khali@linux-fr.org>
-
-----------------------------
-
 What:	cancel_rearming_delayed_work[queue]()
 When:	2.6.39
 
@@ -604,6 +605,13 @@ Who:	Jean Delvare <khali@linux-fr.org>
 
 ----------------------------
 
+What:	xt_connlimit rev 0
+When:	2012
+Who:	Jan Engelhardt <jengelh@medozas.de>
+Files:	net/netfilter/xt_connlimit.c
+
+----------------------------
+
 What:	noswapaccount kernel command line parameter
 When:	2.6.40
 Why:	The original implementation of memsw feature enabled by
@@ -619,3 +627,20 @@ Why:	The original implementation of memsw feature enabled by
 Who:	Michal Hocko <mhocko@suse.cz>
 
 ----------------------------
+
+What:	ipt_addrtype match include file
+When:	2012
+Why:	superseded by xt_addrtype
+Who:	Florian Westphal <fw@strlen.de>
+Files:	include/linux/netfilter_ipv4/ipt_addrtype.h
+
+----------------------------
+
+What:	i2c_driver.attach_adapter
+	i2c_driver.detach_adapter
+When:	September 2011
+Why:	These legacy callbacks should no longer be used as i2c-core offers
+	a variety of preferable alternative ways to instantiate I2C devices.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+----------------------------
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 4471a41..2e994ef 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -166,13 +166,11 @@ prototypes:
 	void (*kill_sb) (struct super_block *);
 locking rules:
 		may block
-get_sb		yes
 mount		yes
 kill_sb		yes
 
-->get_sb() returns error or 0 with locked superblock attached to the vfsmount
-(exclusive on ->s_umount).
-->mount() returns ERR_PTR or the root dentry.
+->mount() returns ERR_PTR or the root dentry; its superblock should be locked
+on return.
 ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
 unlocks and drops the reference.
 
diff --git a/Documentation/filesystems/adfs.txt b/Documentation/filesystems/adfs.txt
index 9e8811f..5949766 100644
--- a/Documentation/filesystems/adfs.txt
+++ b/Documentation/filesystems/adfs.txt
@@ -9,6 +9,9 @@ Mount options for ADFS
 		will be nnn.  Default 0700.
   othmask=nnn	The permission mask for ADFS 'other' permissions
 		will be nnn.  Default 0077.
+  ftsuffix=n	When ftsuffix=0, no file type suffix will be applied.
+		When ftsuffix=1, a hexadecimal suffix corresponding to
+		the RISC OS file type will be added.  Default 0.
 
 Mapping of ADFS permissions to Linux permissions
 ------------------------------------------------
@@ -55,3 +58,18 @@ Mapping of ADFS permissions to Linux permissions
 
   You can therefore tailor the permission translation to whatever you
   desire the permissions should be under Linux.
+
+RISC OS file type suffix
+------------------------
+
+  RISC OS file types are stored in bits 19..8 of the file load address.
+
+  To enable non-RISC OS systems to be used to store files without losing
+  file type information, a file naming convention was devised (initially
+  for use with NFS) such that a hexadecimal suffix of the form ,xyz
+  denoted the file type: e.g. BasicFile,ffb is a BASIC (0xffb) file.  This
+  naming convention is now also used by RISC OS emulators such as RPCEmu.
+
+  Mounting an ADFS disc with option ftsuffix=1 will cause appropriate file
+  type suffixes to be appended to file names read from a directory.  If the
+  ftsuffix option is zero or omitted, no file type suffixes will be added.
diff --git a/Documentation/filesystems/nfs/pnfs.txt b/Documentation/filesystems/nfs/pnfs.txt
index bc0b9cf..983e14a 100644
--- a/Documentation/filesystems/nfs/pnfs.txt
+++ b/Documentation/filesystems/nfs/pnfs.txt
@@ -46,3 +46,10 @@ data server cache
 file driver devices refer to data servers, which are kept in a module
 level cache.  Its reference is held over the lifetime of the deviceid
 pointing to it.
+
+lseg
+----
+lseg maintains an extra reference corresponding to the NFS_LSEG_VALID
+bit which holds it in the pnfs_layout_hdr's list.  When the final lseg
+is removed from the pnfs_layout_hdr's list, the NFS_LAYOUT_DESTROYED
+bit is set, preventing any new lsegs from being added.
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index dfbcd1b..0c986c9 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -394,3 +394,10 @@ file) you must return -EOPNOTSUPP if FALLOC_FL_PUNCH_HOLE is set in mode.
 Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set,
 so the i_size should not change when hole punching, even when puching the end of
 a file off.
+
+--
+[mandatory]
+	->get_sb() is gone.  Switch to use of ->mount().  Typically it's just
+a matter of switching from calling get_sb_... to mount_... and changing the
+function type.  If you were doing it manually, just switch from setting ->mnt_root
+to some pointer to returning that pointer.  On errors return ERR_PTR(...).
diff --git a/Documentation/filesystems/romfs.txt b/Documentation/filesystems/romfs.txt
index 2d2a7b2..e2b07cc 100644
--- a/Documentation/filesystems/romfs.txt
+++ b/Documentation/filesystems/romfs.txt
@@ -17,8 +17,7 @@ comparison, an actual rescue disk used up 3202 blocks with ext2, while
 with romfs, it needed 3079 blocks.
 
 To create such a file system, you'll need a user program named
-genromfs.  It is available via anonymous ftp on sunsite.unc.edu and
-its mirrors, in the /pub/Linux/system/recovery/ directory.
+genromfs. It is available on http://romfs.sourceforge.net/
 
 As the name suggests, romfs could be also used (space-efficiently) on
 various read-only media, like (E)EPROM disks if someone will have the
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 5d1335fae..f806e50 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -39,10 +39,12 @@ userspace. Top-level directories in sysfs represent the common
 ancestors of object hierarchies; i.e. the subsystems the objects
 belong to. 
 
-Sysfs internally stores the kobject that owns the directory in the
-->d_fsdata pointer of the directory's dentry. This allows sysfs to do
-reference counting directly on the kobject when the file is opened and
-closed. 
+Sysfs internally stores a pointer to the kobject that implements a
+directory in the sysfs_dirent object associated with the directory. In
+the past this kobject pointer has been used by sysfs to do reference
+counting directly on the kobject whenever the file is opened or closed.
+With the current sysfs implementation the kobject reference count is
+only modified directly by the function sysfs_schedule_callback().
 
 
 Attributes
@@ -208,9 +210,9 @@ Other notes:
   is 4096. 
 
 - show() methods should return the number of bytes printed into the
-  buffer. This is the return value of snprintf().
+  buffer. This is the return value of scnprintf().
 
-- show() should always use snprintf(). 
+- show() should always use scnprintf().
 
 - store() should return the number of bytes used from the buffer. If the
   entire buffer has been used, just return the count argument.
@@ -229,7 +231,7 @@ A very simple (and naive) implementation of a device attribute is:
 static ssize_t show_name(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
 }
 
 static ssize_t store_name(struct device *dev, struct device_attribute *attr,
diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index 12fedb7..d7b13b0 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -82,12 +82,12 @@ Mount options
 bulk_read		read more in one go to take advantage of flash
 			media that read faster sequentially
 no_bulk_read (*)	do not bulk-read
-no_chk_data_crc		skip checking of CRCs on data nodes in order to
+no_chk_data_crc (*)	skip checking of CRCs on data nodes in order to
 			improve read performance. Use this option only
 			if the flash media is highly reliable. The effect
 			of this option is that corruption of the contents
 			of a file can go unnoticed.
-chk_data_crc (*)	do not skip checking CRCs on data nodes
+chk_data_crc		do not skip checking CRCs on data nodes
 compr=none              override default compressor and set it to "none"
 compr=lzo               override default compressor and set it to "lzo"
 compr=zlib              override default compressor and set it to "zlib"
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 94cf97b..306f0ae 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -95,10 +95,11 @@ functions:
    extern int unregister_filesystem(struct file_system_type *);
 
 The passed struct file_system_type describes your filesystem. When a
-request is made to mount a device onto a directory in your filespace,
-the VFS will call the appropriate get_sb() method for the specific
-filesystem. The dentry for the mount point will then be updated to
-point to the root inode for the new filesystem.
+request is made to mount a filesystem onto a directory in your namespace,
+the VFS will call the appropriate mount() method for the specific
+filesystem.  New vfsmount refering to the tree returned by ->mount()
+will be attached to the mountpoint, so that when pathname resolution
+reaches the mountpoint it will jump into the root of that vfsmount.
 
 You can see all filesystems that are registered to the kernel in the
 file /proc/filesystems.
@@ -107,14 +108,14 @@ file /proc/filesystems.
 struct file_system_type
 -----------------------
 
-This describes the filesystem. As of kernel 2.6.22, the following
+This describes the filesystem. As of kernel 2.6.39, the following
 members are defined:
 
 struct file_system_type {
 	const char *name;
 	int fs_flags;
-        int (*get_sb) (struct file_system_type *, int,
-                       const char *, void *, struct vfsmount *);
+        struct dentry (*mount) (struct file_system_type *, int,
+                       const char *, void *);
         void (*kill_sb) (struct super_block *);
         struct module *owner;
         struct file_system_type * next;
@@ -128,11 +129,11 @@ struct file_system_type {
 
   fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
 
-  get_sb: the method to call when a new instance of this
+  mount: the method to call when a new instance of this
 	filesystem should be mounted
 
   kill_sb: the method to call when an instance of this filesystem
-	should be unmounted
+	should be shut down
 
   owner: for internal VFS use: you should initialize this to THIS_MODULE in
   	most cases.
@@ -141,7 +142,7 @@ struct file_system_type {
 
   s_lock_key, s_umount_key: lockdep-specific
 
-The get_sb() method has the following arguments:
+The mount() method has the following arguments:
 
   struct file_system_type *fs_type: describes the filesystem, partly initialized
   	by the specific filesystem code
@@ -153,32 +154,39 @@ The get_sb() method has the following arguments:
   void *data: arbitrary mount options, usually comes as an ASCII
 	string (see "Mount Options" section)
 
-  struct vfsmount *mnt: a vfs-internal representation of a mount point
+The mount() method must return the root dentry of the tree requested by
+caller.  An active reference to its superblock must be grabbed and the
+superblock must be locked.  On failure it should return ERR_PTR(error).
 
-The get_sb() method must determine if the block device specified
-in the dev_name and fs_type contains a filesystem of the type the method
-supports. If it succeeds in opening the named block device, it initializes a
-struct super_block descriptor for the filesystem contained by the block device.
-On failure it returns an error.
+The arguments match those of mount(2) and their interpretation
+depends on filesystem type.  E.g. for block filesystems, dev_name is
+interpreted as block device name, that device is opened and if it
+contains a suitable filesystem image the method creates and initializes
+struct super_block accordingly, returning its root dentry to caller.
+
+->mount() may choose to return a subtree of existing filesystem - it
+doesn't have to create a new one.  The main result from the caller's
+point of view is a reference to dentry at the root of (sub)tree to
+be attached; creation of new superblock is a common side effect.
 
 The most interesting member of the superblock structure that the
-get_sb() method fills in is the "s_op" field. This is a pointer to
+mount() method fills in is the "s_op" field. This is a pointer to
 a "struct super_operations" which describes the next level of the
 filesystem implementation.
 
-Usually, a filesystem uses one of the generic get_sb() implementations
-and provides a fill_super() method instead. The generic methods are:
+Usually, a filesystem uses one of the generic mount() implementations
+and provides a fill_super() callback instead. The generic variants are:
 
-  get_sb_bdev: mount a filesystem residing on a block device
+  mount_bdev: mount a filesystem residing on a block device
 
-  get_sb_nodev: mount a filesystem that is not backed by a device
+  mount_nodev: mount a filesystem that is not backed by a device
 
-  get_sb_single: mount a filesystem which shares the instance between
+  mount_single: mount a filesystem which shares the instance between
   	all mounts
 
-A fill_super() method implementation has the following arguments:
+A fill_super() callback implementation has the following arguments:
 
-  struct super_block *sb: the superblock structure. The method fill_super()
+  struct super_block *sb: the superblock structure. The callback
   	must initialize this properly.
 
   void *data: arbitrary mount options, usually comes as an ASCII
@@ -865,7 +873,7 @@ struct dentry_operations {
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)(struct dentry *, char *, int);
 	struct vfsmount *(*d_automount)(struct path *);
-	int (*d_manage)(struct dentry *, bool, bool);
+	int (*d_manage)(struct dentry *, bool);
 };
 
   d_revalidate: called when the VFS needs to revalidate a dentry. This
@@ -961,10 +969,6 @@ struct dentry_operations {
 	mounted on it and not to check the automount flag.  Any other error
 	code will abort pathwalk completely.
 
-	If the 'mounting_here' parameter is true, then namespace_sem is being
-	held by the caller and the function should not initiate any mounts or
-	unmounts that it will then wait for.
-
 	If the 'rcu_walk' parameter is true, then the caller is doing a
 	pathwalk in RCU-walk mode.  Sleeping is not permitted in this mode,
 	and the caller can be asked to leave it and call again by returing
diff --git a/Documentation/filesystems/xfs-delayed-logging-design.txt b/Documentation/filesystems/xfs-delayed-logging-design.txt
index 7445bf3..5282e3e 100644
--- a/Documentation/filesystems/xfs-delayed-logging-design.txt
+++ b/Documentation/filesystems/xfs-delayed-logging-design.txt
@@ -791,10 +791,3 @@ mount option. Fundamentally, there is no reason why the log manager would not
 be able to swap methods automatically and transparently depending on load
 characteristics, but this should not be necessary if delayed logging works as
 designed.
-
-Roadmap:
-
-2.6.39 Switch default mount option to use delayed logging
-	=> should be roughly 12 months after initial merge
-	=> enough time to shake out remaining problems before next round of
-	   enterprise distro kernel rebases
diff --git a/Documentation/hwmon/ads1015 b/Documentation/hwmon/ads1015
new file mode 100644
index 0000000..f6fe9c2
--- /dev/null
+++ b/Documentation/hwmon/ads1015
@@ -0,0 +1,72 @@
+Kernel driver ads1015
+=====================
+
+Supported chips:
+  * Texas Instruments ADS1015
+    Prefix: 'ads1015'
+    Datasheet: Publicly available at the Texas Instruments website :
+               http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+
+Authors:
+        Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+
+Description
+-----------
+
+This driver implements support for the Texas Instruments ADS1015.
+
+This device is a 12-bit A-D converter with 4 inputs.
+
+The inputs can be used single ended or in certain differential combinations.
+
+The inputs can be made available by 8 sysfs input files in0_input - in7_input:
+in0: Voltage over AIN0 and AIN1.
+in1: Voltage over AIN0 and AIN3.
+in2: Voltage over AIN1 and AIN3.
+in3: Voltage over AIN2 and AIN3.
+in4: Voltage over AIN0 and GND.
+in5: Voltage over AIN1 and GND.
+in6: Voltage over AIN2 and GND.
+in7: Voltage over AIN3 and GND.
+
+Which inputs are available can be configured using platform data or devicetree.
+
+By default all inputs are exported.
+
+Platform Data
+-------------
+
+In linux/i2c/ads1015.h platform data is defined, channel_data contains
+configuration data for the used input combinations:
+- pga is the programmable gain amplifier (values are full scale)
+  0: +/- 6.144 V
+  1: +/- 4.096 V
+  2: +/- 2.048 V
+  3: +/- 1.024 V
+  4: +/- 0.512 V
+  5: +/- 0.256 V
+- data_rate in samples per second
+  0: 128
+  1: 250
+  2: 490
+  3: 920
+  4: 1600
+  5: 2400
+  6: 3300
+
+Example:
+struct ads1015_platform_data data = {
+	.channel_data = {
+		[2] = { .enabled = true, .pga = 1, .data_rate = 0 },
+		[4] = { .enabled = true, .pga = 4, .data_rate = 5 },
+	}
+};
+
+In this case only in2_input (FS +/- 4.096 V, 128 SPS) and in4_input
+(FS +/- 0.512 V, 2400 SPS) would be created.
+
+Devicetree
+----------
+
+Configuration is also possible via devicetree:
+Documentation/devicetree/bindings/hwmon/ads1015.txt
diff --git a/Documentation/hwmon/f71882fg b/Documentation/hwmon/f71882fg
index a7952c2..4d0bc70 100644
--- a/Documentation/hwmon/f71882fg
+++ b/Documentation/hwmon/f71882fg
@@ -10,6 +10,10 @@ Supported chips:
     Prefix: 'f71862fg'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Available from the Fintek website
+  * Fintek F71869F and F71869E
+    Prefix: 'f71869'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available from the Fintek website
   * Fintek F71882FG and F71883FG
     Prefix: 'f71882fg'
     Addresses scanned: none, address read from Super I/O config space
@@ -17,6 +21,10 @@ Supported chips:
   * Fintek F71889FG
     Prefix: 'f71889fg'
     Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available from the Fintek website
+  * Fintek F71889ED
+    Prefix: 'f71889ed'
+    Addresses scanned: none, address read from Super I/O config space
     Datasheet: Should become available on the Fintek website soon
   * Fintek F8000
     Prefix: 'f8000'
@@ -29,9 +37,9 @@ Author: Hans de Goede <hdegoede@redhat.com>
 Description
 -----------
 
-Fintek F718xxFG/F8000 Super I/O chips include complete hardware monitoring
-capabilities. They can monitor up to 9 voltages (3 for the F8000), 4 fans and
-3 temperature sensors.
+Fintek F718xx/F8000 Super I/O chips include complete hardware monitoring
+capabilities. They can monitor up to 9 voltages, 4 fans and 3 temperature
+sensors.
 
 These chips also have fan controlling features, using either DC or PWM, in
 three different modes (one manual, two automatic).
@@ -99,5 +107,5 @@ Writing an unsupported mode will result in an invalid parameter error.
   The fan speed is regulated to keep the temp the fan is mapped to between
   temp#_auto_point2_temp and temp#_auto_point3_temp.
 
-Both of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
+All of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
 fan2 and pwm3 to fan3.
diff --git a/Documentation/hwmon/hpfall.c b/Documentation/hwmon/hpfall.c
deleted file mode 100644
index a4a8fc5..0000000
--- a/Documentation/hwmon/hpfall.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Disk protection for HP machines.
- *
- * Copyright 2008 Eric Piel
- * Copyright 2009 Pavel Machek <pavel@ucw.cz>
- *
- * GPLv2.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sched.h>
-
-char unload_heads_path[64];
-
-int set_unload_heads_path(char *device)
-{
-	char devname[64];
-
-	if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
-		return -EINVAL;
-	strncpy(devname, device + 5, sizeof(devname));
-
-	snprintf(unload_heads_path, sizeof(unload_heads_path),
-				"/sys/block/%s/device/unload_heads", devname);
-	return 0;
-}
-int valid_disk(void)
-{
-	int fd = open(unload_heads_path, O_RDONLY);
-	if (fd < 0) {
-		perror(unload_heads_path);
-		return 0;
-	}
-
-	close(fd);
-	return 1;
-}
-
-void write_int(char *path, int i)
-{
-	char buf[1024];
-	int fd = open(path, O_RDWR);
-	if (fd < 0) {
-		perror("open");
-		exit(1);
-	}
-	sprintf(buf, "%d", i);
-	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
-		perror("write");
-		exit(1);
-	}
-	close(fd);
-}
-
-void set_led(int on)
-{
-	write_int("/sys/class/leds/hp::hddprotect/brightness", on);
-}
-
-void protect(int seconds)
-{
-	write_int(unload_heads_path, seconds*1000);
-}
-
-int on_ac(void)
-{
-//	/sys/class/power_supply/AC0/online
-}
-
-int lid_open(void)
-{
-//	/proc/acpi/button/lid/LID/state
-}
-
-void ignore_me(void)
-{
-	protect(0);
-	set_led(0);
-}
-
-int main(int argc, char **argv)
-{
-	int fd, ret;
-	struct sched_param param;
-
-	if (argc == 1)
-		ret = set_unload_heads_path("/dev/sda");
-	else if (argc == 2)
-		ret = set_unload_heads_path(argv[1]);
-	else
-		ret = -EINVAL;
-
-	if (ret || !valid_disk()) {
-		fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n",
-				argv[0]);
-		exit(1);
-	}
-
-	fd = open("/dev/freefall", O_RDONLY);
-	if (fd < 0) {
-		perror("/dev/freefall");
-		return EXIT_FAILURE;
-	}
-
-	daemon(0, 0);
-	param.sched_priority = sched_get_priority_max(SCHED_FIFO);
-	sched_setscheduler(0, SCHED_FIFO, &param);
-	mlockall(MCL_CURRENT|MCL_FUTURE);
-
-	signal(SIGALRM, ignore_me);
-
-	for (;;) {
-		unsigned char count;
-
-		ret = read(fd, &count, sizeof(count));
-		alarm(0);
-		if ((ret == -1) && (errno == EINTR)) {
-			/* Alarm expired, time to unpark the heads */
-			continue;
-		}
-
-		if (ret != sizeof(count)) {
-			perror("read");
-			break;
-		}
-
-		protect(21);
-		set_led(1);
-		if (1 || on_ac() || lid_open())
-			alarm(2);
-		else
-			alarm(20);
-	}
-
-	close(fd);
-	return EXIT_SUCCESS;
-}
diff --git a/Documentation/hwmon/lineage-pem b/Documentation/hwmon/lineage-pem
new file mode 100644
index 0000000..2ba5ed1
--- /dev/null
+++ b/Documentation/hwmon/lineage-pem
@@ -0,0 +1,77 @@
+Kernel driver lineage-pem
+=========================
+
+Supported devices:
+  * Lineage Compact Power Line Power Entry Modules
+    Prefix: 'lineage-pem'
+    Addresses scanned: -
+    Documentation:
+        http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports various Lineage Compact Power Line DC/DC and AC/DC
+converters such as CP1800, CP2000AC, CP2000DC, CP2100DC, and others.
+
+Lineage CPL power entry modules are nominally PMBus compliant. However, most
+standard PMBus commands are not supported. Specifically, all hardware monitoring
+and status reporting commands are non-standard. For this reason, a standard
+PMBus driver can not be used.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for Lineage CPL devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for a Lineage PEM at address 0x40
+on I2C bus #1:
+$ modprobe lineage-pem
+$ echo lineage-pem 0x40 > /sys/bus/i2c/devices/i2c-1/new_device
+
+All Lineage CPL power entry modules have a built-in I2C bus master selector
+(PCA9541). To ensure device access, this driver should only be used as client
+driver to the pca9541 I2C master selector driver.
+
+
+Sysfs entries
+-------------
+
+All Lineage CPL devices report output voltage and device temperature as well as
+alarms for output voltage, temperature, input voltage, input current, input power,
+and fan status.
+
+Input voltage, input current, input power, and fan speed measurement is only
+supported on newer devices. The driver detects if those attributes are supported,
+and only creates respective sysfs entries if they are.
+
+in1_input		Output voltage (mV)
+in1_min_alarm		Output undervoltage alarm
+in1_max_alarm		Output overvoltage alarm
+in1_crit		Output voltage critical alarm
+
+in2_input		Input voltage (mV, optional)
+in2_alarm		Input voltage alarm
+
+curr1_input		Input current (mA, optional)
+curr1_alarm		Input overcurrent alarm
+
+power1_input		Input power (uW, optional)
+power1_alarm		Input power alarm
+
+fan1_input		Fan 1 speed (rpm, optional)
+fan2_input		Fan 2 speed (rpm, optional)
+fan3_input		Fan 3 speed (rpm, optional)
+
+temp1_input
+temp1_max
+temp1_crit
+temp1_alarm
+temp1_crit_alarm
+temp1_fault
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d
deleted file mode 100644
index 06534f2..0000000
--- a/Documentation/hwmon/lis3lv02d
+++ /dev/null
@@ -1,92 +0,0 @@
-Kernel driver lis3lv02d
-=======================
-
-Supported chips:
-
-  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
-  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
-
-Authors:
-        Yan Burman <burman.yan@gmail.com>
-	Eric Piel <eric.piel@tremplin-utc.net>
-
-
-Description
------------
-
-This driver provides support for the accelerometer found in various HP laptops
-sporting the feature officially called "HP Mobile Data Protection System 3D" or
-"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known
-models (full list can be found in drivers/hwmon/hp_accel.c) will have their
-axis automatically oriented on standard way (eg: you can directly play
-neverball). The accelerometer data is readable via
-/sys/devices/platform/lis3lv02d. Reported values are scaled
-to mg values (1/1000th of earth gravity).
-
-Sysfs attributes under /sys/devices/platform/lis3lv02d/:
-position - 3D position that the accelerometer reports. Format: "(x,y,z)"
-rate - read reports the sampling rate of the accelerometer device in HZ.
-	write changes sampling rate of the accelerometer device.
-	Only values which are supported by HW are accepted.
-selftest - performs selftest for the chip as specified by chip manufacturer.
-
-This driver also provides an absolute input class device, allowing
-the laptop to act as a pinball machine-esque joystick. Joystick device can be
-calibrated. Joystick device can be in two different modes.
-By default output values are scaled between -32768 .. 32767. In joystick raw
-mode, joystick and sysfs position entry have the same scale. There can be
-small difference due to input system fuzziness feature.
-Events are also available as input event device.
-
-Selftest is meant only for hardware diagnostic purposes. It is not meant to be
-used during normal operations. Position data is not corrupted during selftest
-but interrupt behaviour is not guaranteed to work reliably. In test mode, the
-sensing element is internally moved little bit. Selftest measures difference
-between normal mode and test mode. Chip specifications tell the acceptance
-limit for each type of the chip. Limits are provided via platform data
-to allow adjustment of the limits without a change to the actual driver.
-Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are
-measured difference between modes. Axes are not remapped in selftest mode.
-Measurement values are provided to help HW diagnostic applications to make
-final decision.
-
-On HP laptops, if the led infrastructure is activated, support for a led
-indicating disk protection will be provided as /sys/class/leds/hp::hddprotect.
-
-Another feature of the driver is misc device called "freefall" that
-acts similar to /dev/rtc and reacts on free-fall interrupts received
-from the device. It supports blocking operations, poll/select and
-fasync operation modes. You must read 1 bytes from the device.  The
-result is number of free-fall interrupts since the last successful
-read (or 255 if number of interrupts would not fit). See the hpfall.c
-file for an example on using the device.
-
-
-Axes orientation
-----------------
-
-For better compatibility between the various laptops. The values reported by
-the accelerometer are converted into a "standard" organisation of the axes
-(aka "can play neverball out of the box"):
- * When the laptop is horizontal the position reported is about 0 for X and Y
-	and a positive value for Z
- * If the left side is elevated, X increases (becomes positive)
- * If the front side (where the touchpad is) is elevated, Y decreases
-	(becomes negative)
- * If the laptop is put upside-down, Z becomes negative
-
-If your laptop model is not recognized (cf "dmesg"), you can send an
-email to the maintainer to add it to the database.  When reporting a new
-laptop, please include the output of "dmidecode" plus the value of
-/sys/devices/platform/lis3lv02d/position in these four cases.
-
-Q&A
----
-
-Q: How do I safely simulate freefall? I have an HP "portable
-workstation" which has about 3.5kg and a plastic case, so letting it
-fall to the ground is out of question...
-
-A: The sensor is pretty sensitive, so your hands can do it. Lift it
-into free space, follow the fall with your hands for like 10
-centimeters. That should be enough to trigger the detection.
diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75
index 8e6356f..a179040 100644
--- a/Documentation/hwmon/lm75
+++ b/Documentation/hwmon/lm75
@@ -7,6 +7,11 @@ Supported chips:
     Addresses scanned: I2C 0x48 - 0x4f
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
+  * National Semiconductor LM75A
+    Prefix: 'lm75a'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
   * Dallas Semiconductor DS75
     Prefix: 'lm75'
     Addresses scanned: I2C 0x48 - 0x4f
diff --git a/Documentation/hwmon/lm85 b/Documentation/hwmon/lm85
index 239258a..7c49fea 100644
--- a/Documentation/hwmon/lm85
+++ b/Documentation/hwmon/lm85
@@ -26,6 +26,14 @@ Supported chips:
     Prefix: 'emc6d102'
     Addresses scanned: I2C 0x2c, 0x2d, 0x2e
     Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
+  * SMSC EMC6D103
+    Prefix: 'emc6d103'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/catalog/emc6d103.html
+  * SMSC EMC6D103S
+    Prefix: 'emc6d103s'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/catalog/emc6d103s.html
 
 Authors:
         Philip Pokorny <ppokorny@penguincomputing.com>,
@@ -122,9 +130,11 @@ to be register compatible. The EMC6D100 offers all the features of the
 EMC6D101 plus additional voltage monitoring and system control features.
 Unfortunately it is not possible to distinguish between the package
 versions on register level so these additional voltage inputs may read
-zero. The EMC6D102 features addtional ADC bits thus extending precision
+zero. EMC6D102 and EMC6D103 feature additional ADC bits thus extending precision
 of voltage and temperature channels.
 
+SMSC EMC6D103S is similar to EMC6D103, but does not support pwm#_auto_pwm_minctl
+and temp#_auto_temp_off.
 
 Hardware Configurations
 -----------------------
diff --git a/Documentation/hwmon/ltc4151 b/Documentation/hwmon/ltc4151
new file mode 100644
index 0000000..43c667e
--- /dev/null
+++ b/Documentation/hwmon/ltc4151
@@ -0,0 +1,47 @@
+Kernel driver ltc4151
+=====================
+
+Supported chips:
+  * Linear Technology LTC4151
+    Prefix: 'ltc4151'
+    Addresses scanned: -
+    Datasheet:
+        http://www.linear.com/docs/Datasheet/4151fc.pdf
+
+Author: Per Dalen <per.dalen@appeartv.com>
+
+
+Description
+-----------
+
+The LTC4151 is a High Voltage I2C Current and Voltage Monitor.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4151 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC4151 at address 0x6f
+on I2C bus #0:
+# modprobe ltc4151
+# echo ltc4151 0x6f > /sys/bus/i2c/devices/i2c-0/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADIN
+and VIN registers.
+
+Current reading provided by this driver is reported as obtained from the Current
+Sense register. The reported value assumes that a 1 mOhm sense resistor is
+installed.
+
+in1_input		VDIN voltage (mV)
+
+in2_input		ADIN voltage (mV)
+
+curr1_input		SENSE current (mA)
diff --git a/Documentation/hwmon/max6639 b/Documentation/hwmon/max6639
new file mode 100644
index 0000000..dc49f8b
--- /dev/null
+++ b/Documentation/hwmon/max6639
@@ -0,0 +1,49 @@
+Kernel driver max6639
+=====================
+
+Supported chips:
+  * Maxim MAX6639
+    Prefix: 'max6639'
+    Addresses scanned: I2C 0x2c, 0x2e, 0x2f
+    Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6639.pdf
+
+Authors:
+    He Changqing <hechangqing@semptian.com>
+    Roland Stigge <stigge@antcom.de>
+
+Description
+-----------
+
+This driver implements support for the Maxim MAX6639. This chip is a 2-channel
+temperature monitor with dual PWM fan speed controller. It can monitor its own
+temperature and one external diode-connected transistor or two external
+diode-connected transistors.
+
+The following device attributes are implemented via sysfs:
+
+Attribute              R/W  Contents
+----------------------------------------------------------------------------
+temp1_input            R    Temperature channel 1 input (0..150 C)
+temp2_input            R    Temperature channel 2 input (0..150 C)
+temp1_fault            R    Temperature channel 1 diode fault
+temp2_fault            R    Temperature channel 2 diode fault
+temp1_max              RW   Set THERM temperature for input 1
+                            (in C, see datasheet)
+temp2_max              RW   Set THERM temperature for input 2
+temp1_crit             RW   Set ALERT temperature for input 1
+temp2_crit             RW   Set ALERT temperature for input 2
+temp1_emergency        RW   Set OT temperature for input 1
+                            (in C, see datasheet)
+temp2_emergency        RW   Set OT temperature for input 2
+pwm1                   RW   Fan 1 target duty cycle (0..255)
+pwm2                   RW   Fan 2 target duty cycle (0..255)
+fan1_input             R    TACH1 fan tachometer input (in RPM)
+fan2_input             R    TACH2 fan tachometer input (in RPM)
+fan1_fault             R    Fan 1 fault
+fan2_fault             R    Fan 2 fault
+temp1_max_alarm        R    Alarm on THERM temperature on channel 1
+temp2_max_alarm        R    Alarm on THERM temperature on channel 2
+temp1_crit_alarm       R    Alarm on ALERT temperature on channel 1
+temp2_crit_alarm       R    Alarm on ALERT temperature on channel 2
+temp1_emergency_alarm  R    Alarm on OT temperature on channel 1
+temp2_emergency_alarm  R    Alarm on OT temperature on channel 2
diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus
new file mode 100644
index 0000000..f2d42e8
--- /dev/null
+++ b/Documentation/hwmon/pmbus
@@ -0,0 +1,215 @@
+Kernel driver pmbus
+====================
+
+Supported chips:
+  * Ericsson BMR45X series
+    DC/DC Converter
+    Prefixes: 'bmr450', 'bmr451', 'bmr453', 'bmr454'
+    Addresses scanned: -
+    Datasheet:
+ http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395
+  * Linear Technology LTC2978
+    Octal PMBus Power Supply Monitor and Controller
+    Prefix: 'ltc2978'
+    Addresses scanned: -
+    Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+  * Maxim MAX16064
+    Quad Power-Supply Controller
+    Prefix: 'max16064'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
+  * Maxim MAX34440
+    PMBus 6-Channel Power-Supply Manager
+    Prefixes: 'max34440'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
+  * Maxim MAX34441
+    PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
+    Prefixes: 'max34441'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
+  * Maxim MAX8688
+    Digital Power-Supply Controller/Monitor
+    Prefix: 'max8688'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
+  * Generic PMBus devices
+    Prefix: 'pmbus'
+    Addresses scanned: -
+    Datasheet: n.a.
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for various PMBus compliant devices.
+It supports voltage, current, power, and temperature sensors as supported
+by the device.
+
+Each monitored channel has its own high and low limits, plus a critical
+limit.
+
+Fan support will be added in a later version of this driver.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for PMBus devices, since there is no register
+which can be safely used to identify the chip (The MFG_ID register is not
+supported by all chips), and since there is no well defined address range for
+PMBus devices. You will have to instantiate the devices explicitly.
+
+Example: the following will load the driver for an LTC2978 at address 0x60
+on I2C bus #1:
+$ modprobe pmbus
+$ echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Platform data support
+---------------------
+
+Support for additional PMBus chips can be added by defining chip parameters in
+a new chip specific driver file. For example, (untested) code to add support for
+Emerson DS1200 power modules might look as follows.
+
+static struct pmbus_driver_info ds1200_info = {
+	.pages = 1,
+	/* Note: All other sensors are in linear mode */
+	.direct[PSC_VOLTAGE_OUT] = true,
+	.direct[PSC_TEMPERATURE] = true,
+	.direct[PSC_CURRENT_OUT] = true,
+	.m[PSC_VOLTAGE_IN] = 1,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = 3,
+	.m[PSC_VOLTAGE_OUT] = 1,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = 3,
+	.m[PSC_TEMPERATURE] = 1,
+	.b[PSC_TEMPERATURE] = 0,
+	.R[PSC_TEMPERATURE] = 3,
+	.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_STATUS_TEMP
+		   | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
+};
+
+static int ds1200_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &ds1200_info);
+}
+
+static int ds1200_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id ds1200_id[] = {
+	{"ds1200", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ds1200_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ds1200_driver = {
+	.driver = {
+		   .name = "ds1200",
+		   },
+	.probe = ds1200_probe,
+	.remove = ds1200_remove,
+	.id_table = ds1200_id,
+};
+
+static int __init ds1200_init(void)
+{
+	return i2c_add_driver(&ds1200_driver);
+}
+
+static void __exit ds1200_exit(void)
+{
+	i2c_del_driver(&ds1200_driver);
+}
+
+
+Sysfs entries
+-------------
+
+When probing the chip, the driver identifies which PMBus registers are
+supported, and determines available sensors from this information.
+Attribute files only exist if respective sensors are suported by the chip.
+Labels are provided to inform the user about the sensor associated with
+a given sysfs entry.
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+inX_input		Measured voltage. From READ_VIN or READ_VOUT register.
+inX_min			Minumum Voltage.
+			From VIN_UV_WARN_LIMIT or VOUT_UV_WARN_LIMIT register.
+inX_max			Maximum voltage.
+			From VIN_OV_WARN_LIMIT or VOUT_OV_WARN_LIMIT register.
+inX_lcrit		Critical minumum Voltage.
+			From VIN_UV_FAULT_LIMIT or VOUT_UV_FAULT_LIMIT register.
+inX_crit		Critical maximum voltage.
+			From VIN_OV_FAULT_LIMIT or VOUT_OV_FAULT_LIMIT register.
+inX_min_alarm		Voltage low alarm. From VOLTAGE_UV_WARNING status.
+inX_max_alarm		Voltage high alarm. From VOLTAGE_OV_WARNING status.
+inX_lcrit_alarm		Voltage critical low alarm.
+			From VOLTAGE_UV_FAULT status.
+inX_crit_alarm		Voltage critical high alarm.
+			From VOLTAGE_OV_FAULT status.
+inX_label		"vin", "vcap", or "voutY"
+
+currX_input		Measured current. From READ_IIN or READ_IOUT register.
+currX_max		Maximum current.
+			From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT register.
+currX_lcrit		Critical minumum output current.
+			From IOUT_UC_FAULT_LIMIT register.
+currX_crit		Critical maximum current.
+			From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register.
+currX_alarm		Current high alarm.
+			From IIN_OC_WARNING or IOUT_OC_WARNING status.
+currX_lcrit_alarm	Output current critical low alarm.
+			From IOUT_UC_FAULT status.
+currX_crit_alarm	Current critical high alarm.
+			From IIN_OC_FAULT or IOUT_OC_FAULT status.
+currX_label		"iin" or "vinY"
+
+powerX_input		Measured power. From READ_PIN or READ_POUT register.
+powerX_cap		Output power cap. From POUT_MAX register.
+powerX_max		Power limit. From PIN_OP_WARN_LIMIT or
+			POUT_OP_WARN_LIMIT register.
+powerX_crit		Critical output power limit.
+			From POUT_OP_FAULT_LIMIT register.
+powerX_alarm		Power high alarm.
+			From PIN_OP_WARNING or POUT_OP_WARNING status.
+powerX_crit_alarm	Output power critical high alarm.
+			From POUT_OP_FAULT status.
+powerX_label		"pin" or "poutY"
+
+tempX_input		Measured tempererature.
+			From READ_TEMPERATURE_X register.
+tempX_min		Mimimum tempererature. From UT_WARN_LIMIT register.
+tempX_max		Maximum tempererature. From OT_WARN_LIMIT register.
+tempX_lcrit		Critical low tempererature.
+			From UT_FAULT_LIMIT register.
+tempX_crit		Critical high tempererature.
+			From OT_FAULT_LIMIT register.
+tempX_min_alarm		Chip temperature low alarm. Set by comparing
+			READ_TEMPERATURE_X with UT_WARN_LIMIT if
+			TEMP_UT_WARNING status is set.
+tempX_max_alarm		Chip temperature high alarm. Set by comparing
+			READ_TEMPERATURE_X with OT_WARN_LIMIT if
+			TEMP_OT_WARNING status is set.
+tempX_lcrit_alarm	Chip temperature critical low alarm. Set by comparing
+			READ_TEMPERATURE_X with UT_FAULT_LIMIT if
+			TEMP_UT_FAULT status is set.
+tempX_crit_alarm	Chip temperature critical high alarm. Set by comparing
+			READ_TEMPERATURE_X with OT_FAULT_LIMIT if
+			TEMP_OT_FAULT status is set.
diff --git a/Documentation/hwmon/sch5627 b/Documentation/hwmon/sch5627
new file mode 100644
index 0000000..446a054
--- /dev/null
+++ b/Documentation/hwmon/sch5627
@@ -0,0 +1,22 @@
+Kernel driver sch5627
+=====================
+
+Supported chips:
+  * SMSC SCH5627
+    Prefix: 'sch5627'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Application Note available upon request
+
+Author: Hans de Goede <hdegoede@redhat.com>
+
+
+Description
+-----------
+
+SMSC SCH5627 Super I/O chips include complete hardware monitoring
+capabilities. They can monitor up to 5 voltages, 4 fans and 8 temperatures.
+
+The hardware monitoring part of the SMSC SCH5627 is accessed by talking
+through an embedded microcontroller. An application note describing the
+protocol for communicating with the microcontroller is available upon
+request. Please mail me if you want a copy.
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index c6559f1..83a6987 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -187,6 +187,17 @@ fan[1-*]_div	Fan divisor.
 		Note that this is actually an internal clock divisor, which
 		affects the measurable speed range, not the read value.
 
+fan[1-*]_pulses	Number of tachometer pulses per fan revolution.
+		Integer value, typically between 1 and 4.
+		RW
+		This value is a characteristic of the fan connected to the
+		device's input, so it has to be set in accordance with the fan
+		model.
+		Should only be created if the chip has a register to configure
+		the number of pulses. In the absence of such a register (and
+		thus attribute) the value assumed by all devices is 2 pulses
+		per fan revolution.
+
 fan[1-*]_target
 		Desired fan speed
 		Unit: revolution/min (RPM)
diff --git a/Documentation/hwmon/w83627ehf b/Documentation/hwmon/w83627ehf
index 13d5561..76ffef9 100644
--- a/Documentation/hwmon/w83627ehf
+++ b/Documentation/hwmon/w83627ehf
@@ -5,13 +5,11 @@ Supported chips:
   * Winbond W83627EHF/EHG (ISA access ONLY)
     Prefix: 'w83627ehf'
     Addresses scanned: ISA address retrieved from Super I/O registers
-    Datasheet:
-        http://www.nuvoton.com.tw/NR/rdonlyres/A6A258F0-F0C9-4F97-81C0-C4D29E7E943E/0/W83627EHF.pdf
+    Datasheet: not available
   * Winbond W83627DHG
     Prefix: 'w83627dhg'
     Addresses scanned: ISA address retrieved from Super I/O registers
-    Datasheet:
-        http://www.nuvoton.com.tw/NR/rdonlyres/7885623D-A487-4CF9-A47F-30C5F73D6FE6/0/W83627DHG.pdf
+    Datasheet: not available
   * Winbond W83627DHG-P
     Prefix: 'w83627dhg'
     Addresses scanned: ISA address retrieved from Super I/O registers
@@ -24,6 +22,14 @@ Supported chips:
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6775F/W83667HG-I
+    Prefix: 'nct6775'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6776F
+    Prefix: 'nct6776'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
 
 Authors:
         Jean Delvare <khali@linux-fr.org>
@@ -36,19 +42,28 @@ Description
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips.
-We will refer to them collectively as Winbond chips.
-
-The chips implement three temperature sensors, five fan rotation
-speed sensors, ten analog voltage sensors (only nine for the 627DHG), one
-VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG), alarms
-with beep warnings (control unimplemented), and some automatic fan
-regulation strategies (plus manual fan control mode).
+W83627DHG, W83627DHG-P, W83667HG, W83667HG-B, W83667HG-I (NCT6775F),
+and NCT6776F super I/O chips. We will refer to them collectively as
+Winbond chips.
+
+The chips implement three temperature sensors (up to four for 667HG-B, and nine
+for NCT6775F and NCT6776F), five fan rotation speed sensors, ten analog voltage
+sensors (only nine for the 627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins
+for the 627DHG and 667HG), alarms with beep warnings (control unimplemented),
+and some automatic fan regulation strategies (plus manual fan control mode).
+
+The temperature sensor sources on W82677HG-B, NCT6775F, and NCT6776F are
+configurable. temp4 and higher attributes are only reported if its temperature
+source differs from the temperature sources of the already reported temperature
+sensors. The configured source for each of the temperature sensors is provided
+in tempX_label.
 
 Temperatures are measured in degrees Celsius and measurement resolution is 1
-degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
-the temperature gets higher than high limit; it stays on until the temperature
-falls below the hysteresis value.
+degC for temp1 and and 0.5 degC for temp2 and temp3. For temp4 and higher,
+resolution is 1 degC for W83667HG-B and 0.0 degC for NCT6775F and NCT6776F.
+An alarm is triggered when the temperature gets higher than high limit;
+it stays on until the temperature falls below the hysteresis value.
+Alarms are only supported for temp1, temp2, and temp3.
 
 Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
 triggered if the rotation speed has dropped below a programmable limit. Fan
@@ -80,7 +95,8 @@ prog  -> pwm4 (not on 667HG and 667HG-B; the programmable setting is not
 
 name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
        it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg",
-       and for the W83667HG it is set to "w83667hg".
+       for the W83667HG and W83667HG-B it is set to "w83667hg", for NCT6775F it
+       is set to "nct6775", and for NCT6776F it is set to "nct6776".
 
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
 	   0 (stop) to 255 (full)
@@ -90,6 +106,18 @@ pwm[1-4]_enable - this file controls mode of fan/temperature control:
 	* 2 "Thermal Cruise" mode
 	* 3 "Fan Speed Cruise" mode
 	* 4 "Smart Fan III" mode
+	* 5 "Smart Fan IV" mode
+
+	SmartFan III mode is not supported on NCT6776F.
+
+	SmartFan IV mode is configurable only if it was configured at system
+	startup, and is only supported for W83677HG-B, NCT6775F, and NCT6776F.
+	SmartFan IV operational parameters can not be configured at this time,
+	and the various pwm attributes are not used in SmartFan IV mode.
+	The attributes can be written to, which is useful if you plan to
+	configure the system for a different pwm mode. However, the information
+	returned when reading pwm attributes is unrelated to SmartFan IV
+	operation.
 
 pwm[1-4]_mode - controls if output is PWM or DC level
         * 0 DC output (0 - 12v)
diff --git a/Documentation/hwmon/w83795 b/Documentation/hwmon/w83795
new file mode 100644
index 0000000..9f16037
--- /dev/null
+++ b/Documentation/hwmon/w83795
@@ -0,0 +1,127 @@
+Kernel driver w83795
+====================
+
+Supported chips:
+  * Winbond/Nuvoton W83795G
+    Prefix: 'w83795g'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Available for download on nuvoton.com
+  * Winbond/Nuvoton W83795ADG
+    Prefix: 'w83795adg'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Available for download on nuvoton.com
+
+Authors:
+    Wei Song (Nuvoton)
+    Jean Delvare <khali@linux-fr.org>
+
+
+Pin mapping
+-----------
+
+Here is a summary of the pin mapping for the W83795G and W83795ADG.
+This can be useful to convert data provided by board manufacturers
+into working libsensors configuration statements.
+
+    W83795G			|
+  Pin	| Name			| Register	| Sysfs attribute
+------------------------------------------------------------------
+   13	| VSEN1 (VCORE1)	| 10h		| in0
+   14	| VSEN2 (VCORE2)	| 11h		| in1
+   15	| VSEN3 (VCORE3)	| 12h		| in2
+   16	| VSEN4			| 13h		| in3
+   17	| VSEN5			| 14h		| in4
+   18	| VSEN6			| 15h		| in5
+   19	| VSEN7			| 16h		| in6
+   20	| VSEN8			| 17h		| in7
+   21	| VSEN9			| 18h		| in8
+   22	| VSEN10		| 19h		| in9
+   23	| VSEN11		| 1Ah		| in10
+   28	| VTT			| 1Bh		| in11
+   24	| 3VDD			| 1Ch		| in12
+   25	| 3VSB			| 1Dh		| in13
+   26	| VBAT			| 1Eh		| in14
+    3	| VSEN12/TR5		| 1Fh		| in15/temp5
+    4	| VSEN13/TR5		| 20h		| in16/temp6
+  5/  6	| VDSEN14/TR1/TD1	| 21h		| in17/temp1
+  7/  8	| VDSEN15/TR2/TD2	| 22h		| in18/temp2
+  9/ 10	| VDSEN16/TR3/TD3	| 23h		| in19/temp3
+ 11/ 12	| VDSEN17/TR4/TD4	| 24h		| in20/temp4
+   40	| FANIN1		| 2Eh		| fan1
+   42	| FANIN2		| 2Fh		| fan2
+   44	| FANIN3		| 30h		| fan3
+   46	| FANIN4		| 31h		| fan4
+   48	| FANIN5		| 32h		| fan5
+   50	| FANIN6		| 33h		| fan6
+   52	| FANIN7		| 34h		| fan7
+   54	| FANIN8		| 35h		| fan8
+   57	| FANIN9		| 36h		| fan9
+   58	| FANIN10		| 37h		| fan10
+   59	| FANIN11		| 38h		| fan11
+   60	| FANIN12		| 39h		| fan12
+   31	| FANIN13		| 3Ah		| fan13
+   35	| FANIN14		| 3Bh		| fan14
+   41	| FANCTL1		| 10h (bank 2)	| pwm1
+   43	| FANCTL2		| 11h (bank 2)	| pwm2
+   45	| FANCTL3		| 12h (bank 2)	| pwm3
+   47	| FANCTL4		| 13h (bank 2)	| pwm4
+   49	| FANCTL5		| 14h (bank 2)	| pwm5
+   51	| FANCTL6		| 15h (bank 2)	| pwm6
+   53	| FANCTL7		| 16h (bank 2)	| pwm7
+   55	| FANCTL8		| 17h (bank 2)	| pwm8
+ 29/ 30	| PECI/TSI (DTS1)	| 26h		| temp7
+ 29/ 30	| PECI/TSI (DTS2)	| 27h		| temp8
+ 29/ 30	| PECI/TSI (DTS3)	| 28h		| temp9
+ 29/ 30	| PECI/TSI (DTS4)	| 29h		| temp10
+ 29/ 30	| PECI/TSI (DTS5)	| 2Ah		| temp11
+ 29/ 30	| PECI/TSI (DTS6)	| 2Bh		| temp12
+ 29/ 30	| PECI/TSI (DTS7)	| 2Ch		| temp13
+ 29/ 30	| PECI/TSI (DTS8)	| 2Dh		| temp14
+   27	| CASEOPEN#		| 46h		| intrusion0
+
+    W83795ADG			|
+  Pin	| Name			| Register	| Sysfs attribute
+------------------------------------------------------------------
+   10	| VSEN1 (VCORE1)	| 10h		| in0
+   11	| VSEN2 (VCORE2)	| 11h		| in1
+   12	| VSEN3 (VCORE3)	| 12h		| in2
+   13	| VSEN4			| 13h		| in3
+   14	| VSEN5			| 14h		| in4
+   15	| VSEN6			| 15h		| in5
+   16	| VSEN7			| 16h		| in6
+   17	| VSEN8			| 17h		| in7
+   22	| VTT			| 1Bh		| in11
+   18	| 3VDD			| 1Ch		| in12
+   19	| 3VSB			| 1Dh		| in13
+   20	| VBAT			| 1Eh		| in14
+   48	| VSEN12/TR5		| 1Fh		| in15/temp5
+    1	| VSEN13/TR5		| 20h		| in16/temp6
+  2/  3	| VDSEN14/TR1/TD1	| 21h		| in17/temp1
+  4/  5	| VDSEN15/TR2/TD2	| 22h		| in18/temp2
+  6/  7	| VDSEN16/TR3/TD3	| 23h		| in19/temp3
+  8/  9	| VDSEN17/TR4/TD4	| 24h		| in20/temp4
+   32	| FANIN1		| 2Eh		| fan1
+   34	| FANIN2		| 2Fh		| fan2
+   36	| FANIN3		| 30h		| fan3
+   37	| FANIN4		| 31h		| fan4
+   38	| FANIN5		| 32h		| fan5
+   39	| FANIN6		| 33h		| fan6
+   40	| FANIN7		| 34h		| fan7
+   41	| FANIN8		| 35h		| fan8
+   43	| FANIN9		| 36h		| fan9
+   44	| FANIN10		| 37h		| fan10
+   45	| FANIN11		| 38h		| fan11
+   46	| FANIN12		| 39h		| fan12
+   24	| FANIN13		| 3Ah		| fan13
+   28	| FANIN14		| 3Bh		| fan14
+   33	| FANCTL1		| 10h (bank 2)	| pwm1
+   35	| FANCTL2		| 11h (bank 2)	| pwm2
+   23	| PECI (DTS1)		| 26h		| temp7
+   23	| PECI (DTS2)		| 27h		| temp8
+   23	| PECI (DTS3)		| 28h		| temp9
+   23	| PECI (DTS4)		| 29h		| temp10
+   23	| PECI (DTS5)		| 2Ah		| temp11
+   23	| PECI (DTS6)		| 2Bh		| temp12
+   23	| PECI (DTS7)		| 2Ch		| temp13
+   23	| PECI (DTS8)		| 2Dh		| temp14
+   21	| CASEOPEN#		| 46h		| intrusion0
diff --git a/Documentation/hwspinlock.txt b/Documentation/hwspinlock.txt
new file mode 100644
index 0000000..7dcd1a4
--- /dev/null
+++ b/Documentation/hwspinlock.txt
@@ -0,0 +1,293 @@
+Hardware Spinlock Framework
+
+1. Introduction
+
+Hardware spinlock modules provide hardware assistance for synchronization
+and mutual exclusion between heterogeneous processors and those not operating
+under a single, shared operating system.
+
+For example, OMAP4 has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP,
+each of which is running a different Operating System (the master, A9,
+is usually running Linux and the slave processors, the M3 and the DSP,
+are running some flavor of RTOS).
+
+A generic hwspinlock framework allows platform-independent drivers to use
+the hwspinlock device in order to access data structures that are shared
+between remote processors, that otherwise have no alternative mechanism
+to accomplish synchronization and mutual exclusion operations.
+
+This is necessary, for example, for Inter-processor communications:
+on OMAP4, cpu-intensive multimedia tasks are offloaded by the host to the
+remote M3 and/or C64x+ slave processors (by an IPC subsystem called Syslink).
+
+To achieve fast message-based communications, a minimal kernel support
+is needed to deliver messages arriving from a remote processor to the
+appropriate user process.
+
+This communication is based on simple data structures that is shared between
+the remote processors, and access to it is synchronized using the hwspinlock
+module (remote processor directly places new messages in this shared data
+structure).
+
+A common hwspinlock interface makes it possible to have generic, platform-
+independent, drivers.
+
+2. User API
+
+  struct hwspinlock *hwspin_lock_request(void);
+   - dynamically assign an hwspinlock and return its address, or NULL
+     in case an unused hwspinlock isn't available. Users of this
+     API will usually want to communicate the lock's id to the remote core
+     before it can be used to achieve synchronization.
+     Can be called from an atomic context (this function will not sleep) but
+     not from within interrupt context.
+
+  struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
+   - assign a specific hwspinlock id and return its address, or NULL
+     if that hwspinlock is already in use. Usually board code will
+     be calling this function in order to reserve specific hwspinlock
+     ids for predefined purposes.
+     Can be called from an atomic context (this function will not sleep) but
+     not from within interrupt context.
+
+  int hwspin_lock_free(struct hwspinlock *hwlock);
+   - free a previously-assigned hwspinlock; returns 0 on success, or an
+     appropriate error code on failure (e.g. -EINVAL if the hwspinlock
+     is already free).
+     Can be called from an atomic context (this function will not sleep) but
+     not from within interrupt context.
+
+  int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
+   - lock a previously-assigned hwspinlock with a timeout limit (specified in
+     msecs). If the hwspinlock is already taken, the function will busy loop
+     waiting for it to be released, but give up when the timeout elapses.
+     Upon a successful return from this function, preemption is disabled so
+     the caller must not sleep, and is advised to release the hwspinlock as
+     soon as possible, in order to minimize remote cores polling on the
+     hardware interconnect.
+     Returns 0 when successful and an appropriate error code otherwise (most
+     notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
+     The function will never sleep.
+
+  int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int timeout);
+   - lock a previously-assigned hwspinlock with a timeout limit (specified in
+     msecs). If the hwspinlock is already taken, the function will busy loop
+     waiting for it to be released, but give up when the timeout elapses.
+     Upon a successful return from this function, preemption and the local
+     interrupts are disabled, so the caller must not sleep, and is advised to
+     release the hwspinlock as soon as possible.
+     Returns 0 when successful and an appropriate error code otherwise (most
+     notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
+     The function will never sleep.
+
+  int hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock, unsigned int to,
+							unsigned long *flags);
+   - lock a previously-assigned hwspinlock with a timeout limit (specified in
+     msecs). If the hwspinlock is already taken, the function will busy loop
+     waiting for it to be released, but give up when the timeout elapses.
+     Upon a successful return from this function, preemption is disabled,
+     local interrupts are disabled and their previous state is saved at the
+     given flags placeholder. The caller must not sleep, and is advised to
+     release the hwspinlock as soon as possible.
+     Returns 0 when successful and an appropriate error code otherwise (most
+     notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
+     The function will never sleep.
+
+  int hwspin_trylock(struct hwspinlock *hwlock);
+   - attempt to lock a previously-assigned hwspinlock, but immediately fail if
+     it is already taken.
+     Upon a successful return from this function, preemption is disabled so
+     caller must not sleep, and is advised to release the hwspinlock as soon as
+     possible, in order to minimize remote cores polling on the hardware
+     interconnect.
+     Returns 0 on success and an appropriate error code otherwise (most
+     notably -EBUSY if the hwspinlock was already taken).
+     The function will never sleep.
+
+  int hwspin_trylock_irq(struct hwspinlock *hwlock);
+   - attempt to lock a previously-assigned hwspinlock, but immediately fail if
+     it is already taken.
+     Upon a successful return from this function, preemption and the local
+     interrupts are disabled so caller must not sleep, and is advised to
+     release the hwspinlock as soon as possible.
+     Returns 0 on success and an appropriate error code otherwise (most
+     notably -EBUSY if the hwspinlock was already taken).
+     The function will never sleep.
+
+  int hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags);
+   - attempt to lock a previously-assigned hwspinlock, but immediately fail if
+     it is already taken.
+     Upon a successful return from this function, preemption is disabled,
+     the local interrupts are disabled and their previous state is saved
+     at the given flags placeholder. The caller must not sleep, and is advised
+     to release the hwspinlock as soon as possible.
+     Returns 0 on success and an appropriate error code otherwise (most
+     notably -EBUSY if the hwspinlock was already taken).
+     The function will never sleep.
+
+  void hwspin_unlock(struct hwspinlock *hwlock);
+   - unlock a previously-locked hwspinlock. Always succeed, and can be called
+     from any context (the function never sleeps). Note: code should _never_
+     unlock an hwspinlock which is already unlocked (there is no protection
+     against this).
+
+  void hwspin_unlock_irq(struct hwspinlock *hwlock);
+   - unlock a previously-locked hwspinlock and enable local interrupts.
+     The caller should _never_ unlock an hwspinlock which is already unlocked.
+     Doing so is considered a bug (there is no protection against this).
+     Upon a successful return from this function, preemption and local
+     interrupts are enabled. This function will never sleep.
+
+  void
+  hwspin_unlock_irqrestore(struct hwspinlock *hwlock, unsigned long *flags);
+   - unlock a previously-locked hwspinlock.
+     The caller should _never_ unlock an hwspinlock which is already unlocked.
+     Doing so is considered a bug (there is no protection against this).
+     Upon a successful return from this function, preemption is reenabled,
+     and the state of the local interrupts is restored to the state saved at
+     the given flags. This function will never sleep.
+
+  int hwspin_lock_get_id(struct hwspinlock *hwlock);
+   - retrieve id number of a given hwspinlock. This is needed when an
+     hwspinlock is dynamically assigned: before it can be used to achieve
+     mutual exclusion with a remote cpu, the id number should be communicated
+     to the remote task with which we want to synchronize.
+     Returns the hwspinlock id number, or -EINVAL if hwlock is null.
+
+3. Typical usage
+
+#include <linux/hwspinlock.h>
+#include <linux/err.h>
+
+int hwspinlock_example1(void)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	/* dynamically assign a hwspinlock */
+	hwlock = hwspin_lock_request();
+	if (!hwlock)
+		...
+
+	id = hwspin_lock_get_id(hwlock);
+	/* probably need to communicate id to a remote processor now */
+
+	/* take the lock, spin for 1 sec if it's already taken */
+	ret = hwspin_lock_timeout(hwlock, 1000);
+	if (ret)
+		...
+
+	/*
+	 * we took the lock, do our thing now, but do NOT sleep
+	 */
+
+	/* release the lock */
+	hwspin_unlock(hwlock);
+
+	/* free the lock */
+	ret = hwspin_lock_free(hwlock);
+	if (ret)
+		...
+
+	return ret;
+}
+
+int hwspinlock_example2(void)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	/*
+	 * assign a specific hwspinlock id - this should be called early
+	 * by board init code.
+	 */
+	hwlock = hwspin_lock_request_specific(PREDEFINED_LOCK_ID);
+	if (!hwlock)
+		...
+
+	/* try to take it, but don't spin on it */
+	ret = hwspin_trylock(hwlock);
+	if (!ret) {
+		pr_info("lock is already taken\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * we took the lock, do our thing now, but do NOT sleep
+	 */
+
+	/* release the lock */
+	hwspin_unlock(hwlock);
+
+	/* free the lock */
+	ret = hwspin_lock_free(hwlock);
+	if (ret)
+		...
+
+	return ret;
+}
+
+
+4. API for implementors
+
+  int hwspin_lock_register(struct hwspinlock *hwlock);
+   - to be called from the underlying platform-specific implementation, in
+     order to register a new hwspinlock instance. Can be called from an atomic
+     context (this function will not sleep) but not from within interrupt
+     context. Returns 0 on success, or appropriate error code on failure.
+
+  struct hwspinlock *hwspin_lock_unregister(unsigned int id);
+   - to be called from the underlying vendor-specific implementation, in order
+     to unregister an existing (and unused) hwspinlock instance.
+     Can be called from an atomic context (will not sleep) but not from
+     within interrupt context.
+     Returns the address of hwspinlock on success, or NULL on error (e.g.
+     if the hwspinlock is sill in use).
+
+5. struct hwspinlock
+
+This struct represents an hwspinlock instance. It is registered by the
+underlying hwspinlock implementation using the hwspin_lock_register() API.
+
+/**
+ * struct hwspinlock - vendor-specific hwspinlock implementation
+ *
+ * @dev: underlying device, will be used with runtime PM api
+ * @ops: vendor-specific hwspinlock handlers
+ * @id: a global, unique, system-wide, index of the lock.
+ * @lock: initialized and used by hwspinlock core
+ * @owner: underlying implementation module, used to maintain module ref count
+ */
+struct hwspinlock {
+	struct device *dev;
+	const struct hwspinlock_ops *ops;
+	int id;
+	spinlock_t lock;
+	struct module *owner;
+};
+
+The underlying implementation is responsible to assign the dev, ops, id and
+owner members. The lock member, OTOH, is initialized and used by the hwspinlock
+core.
+
+6. Implementation callbacks
+
+There are three possible callbacks defined in 'struct hwspinlock_ops':
+
+struct hwspinlock_ops {
+	int (*trylock)(struct hwspinlock *lock);
+	void (*unlock)(struct hwspinlock *lock);
+	void (*relax)(struct hwspinlock *lock);
+};
+
+The first two callbacks are mandatory:
+
+The ->trylock() callback should make a single attempt to take the lock, and
+return 0 on failure and 1 on success. This callback may _not_ sleep.
+
+The ->unlock() callback releases the lock. It always succeed, and it, too,
+may _not_ sleep.
+
+The ->relax() callback is optional. It is called by hwspinlock core while
+spinning on a lock, and can be used by the underlying implementation to force
+a delay between two successive invocations of ->trylock(). It may _not_ sleep.
diff --git a/Documentation/i2c/busses/i2c-diolan-u2c b/Documentation/i2c/busses/i2c-diolan-u2c
new file mode 100644
index 0000000..30fe4bb
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-diolan-u2c
@@ -0,0 +1,26 @@
+Kernel driver i2c-diolan-u2c
+
+Supported adapters:
+  * Diolan U2C-12 I2C-USB adapter
+    Documentation:
+	http://www.diolan.com/i2c/u2c12.html
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+Description
+-----------
+
+This is the driver for the Diolan U2C-12 USB-I2C adapter.
+
+The Diolan U2C-12 I2C-USB Adapter provides a low cost solution to connect
+a computer to I2C slave devices using a USB interface. It also supports
+connectivity to SPI devices.
+
+This driver only supports the I2C interface of U2C-12. The driver does not use
+interrupts.
+
+
+Module parameters
+-----------------
+
+* frequency: I2C bus frequency
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index 93fe76e..6df6976 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -16,8 +16,9 @@ Supported adapters:
   * Intel EP80579 (Tolapai)
   * Intel 82801JI (ICH10)
   * Intel 5/3400 Series (PCH)
-  * Intel Cougar Point (PCH)
+  * Intel 6 Series (PCH)
   * Intel Patsburg (PCH)
+  * Intel DH89xxCC (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
index 87da405..9edb75d 100644
--- a/Documentation/i2c/instantiating-devices
+++ b/Documentation/i2c/instantiating-devices
@@ -100,7 +100,7 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
 	(...)
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c, NULL);
 	i2c_put_adapter(i2c_adap);
diff --git a/Documentation/i2c/upgrading-clients b/Documentation/i2c/upgrading-clients
index 9a45f9b..d699162 100644
--- a/Documentation/i2c/upgrading-clients
+++ b/Documentation/i2c/upgrading-clients
@@ -61,7 +61,7 @@ static int example_attach(struct i2c_adapter *adap, int addr, int kind)
 	return 0;
 }
 
-static int __devexit example_detach(struct i2c_client *client)
+static int example_detach(struct i2c_client *client)
 {
 	struct example_state *state = i2c_get_clientdata(client);
 
@@ -81,7 +81,7 @@ static struct i2c_driver example_driver = {
 		.name		= "example",
 	},
 	.attach_adapter = example_attach_adapter,
-	.detach_client	= __devexit_p(example_detach),
+	.detach_client	= example_detach,
 	.suspend	= example_suspend,
 	.resume		= example_resume,
 };
@@ -93,7 +93,7 @@ Updating the client
 The new style binding model will check against a list of supported
 devices and their associated address supplied by the code registering
 the busses. This means that the driver .attach_adapter and
-.detach_adapter methods can be removed, along with the addr_data,
+.detach_client methods can be removed, along with the addr_data,
 as follows:
 
 - static struct i2c_driver example_driver;
@@ -110,14 +110,14 @@ as follows:
 
  static struct i2c_driver example_driver = {
 -	.attach_adapter = example_attach_adapter,
--	.detach_client	= __devexit_p(example_detach),
+-	.detach_client	= example_detach,
  }
 
 Add the probe and remove methods to the i2c_driver, as so:
 
  static struct i2c_driver example_driver = {
 +	.probe		= example_probe,
-+	.remove		= __devexit_p(example_remove),
++	.remove		= example_remove,
  }
 
 Change the example_attach method to accept the new parameters
@@ -199,8 +199,8 @@ to delete the i2c_detach_client call. It is possible that you
 can also remove the ret variable as it is not not needed for
 any of the core functions.
 
-- static int __devexit example_detach(struct i2c_client *client)
-+ static int __devexit example_remove(struct i2c_client *client)
+- static int example_detach(struct i2c_client *client)
++ static int example_remove(struct i2c_client *client)
 {
 	struct example_state *state = i2c_get_clientdata(client);
 
@@ -253,7 +253,7 @@ static int example_probe(struct i2c_client *client,
 	return 0;
 }
 
-static int __devexit example_remove(struct i2c_client *client)
+static int example_remove(struct i2c_client *client)
 {
 	struct example_state *state = i2c_get_clientdata(client);
 
@@ -275,7 +275,7 @@ static struct i2c_driver example_driver = {
 	},
 	.id_table	= example_idtable,
 	.probe		= example_probe,
-	.remove		= __devexit_p(example_remove),
+	.remove		= example_remove,
 	.suspend	= example_suspend,
 	.resume		= example_resume,
 };
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index ac293e9..e68543f 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -133,6 +133,7 @@ Code  Seq#(hex)	Include File		Comments
 'H'	C0-DF	net/bluetooth/hidp/hidp.h	conflict!
 'H'	C0-DF	net/bluetooth/cmtp/cmtp.h	conflict!
 'H'	C0-DF	net/bluetooth/bnep/bnep.h	conflict!
+'H'	F1	linux/hid-roccat.h	<mailto:erazor_de@users.sourceforge.net>
 'I'	all	linux/isdn.h		conflict!
 'I'	00-0F	drivers/isdn/divert/isdn_divert.h	conflict!
 'I'	40-4F	linux/mISDNif.h		conflict!
diff --git a/Documentation/kbuild/kbuild.txt b/Documentation/kbuild/kbuild.txt
index 4a99031..f1431d0 100644
--- a/Documentation/kbuild/kbuild.txt
+++ b/Documentation/kbuild/kbuild.txt
@@ -146,7 +146,7 @@ INSTALL_MOD_STRIP
 INSTALL_MOD_STRIP, if defined, will cause modules to be
 stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
 the default option --strip-debug will be used.  Otherwise,
-INSTALL_MOD_STRIP will used as the options to the strip command.
+INSTALL_MOD_STRIP value will be used as the options to the strip command.
 
 INSTALL_FW_PATH
 --------------------------------------------------
@@ -196,3 +196,8 @@ to be included in the databases, separated by blank space. E.g.:
 To get all available archs you can also specify all. E.g.:
 
     $ make ALLSOURCE_ARCHS=all tags
+
+KBUILD_ENABLE_EXTRA_GCC_CHECKS
+--------------------------------------------------
+If enabled over the make command line with "W=1", it turns on additional
+gcc -W... options for more extensive build-time checking.
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 86e3cd0..5d145bb 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1325,7 +1325,8 @@ The top Makefile exports the following variables:
 	If this variable is specified, will cause modules to be stripped
 	after they are installed.  If INSTALL_MOD_STRIP is '1', then the
 	default option --strip-debug will be used.  Otherwise,
-	INSTALL_MOD_STRIP will used as the option(s) to the strip command.
+	INSTALL_MOD_STRIP value will be used as the option(s) to the strip
+	command.
 
 
 === 9 Makefile language
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f4a04c0..c357a31 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -626,6 +626,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 	disable=	[IPV6]
 			See Documentation/networking/ipv6.txt.
 
+	disable_ddw     [PPC/PSERIES]
+			Disable Dynamic DMA Window support. Use this if
+			to workaround buggy firmware.
+
 	disable_ipv6=	[IPV6]
 			See Documentation/networking/ipv6.txt.
 
@@ -868,6 +872,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			       If specified, z/VM IUCV HVC accepts connections
 			       from listed z/VM user IDs only.
 
+	keep_bootcon	[KNL]
+			Do not unregister boot console at start. This is only
+			useful for debugging when something happens in the window
+			between unregistering the boot console and initializing
+			the real console.
+
 	i2c_bus=	[HW] Override the default board specific I2C bus speed
 			     or register an additional I2C bus that is not
 			     registered from board initialization code.
@@ -1580,16 +1590,25 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			of returning the full 64-bit number.
 			The default is to return 64-bit inode numbers.
 
+	nfs.nfs4_disable_idmapping=
+			[NFSv4] When set, this option disables the NFSv4
+			idmapper on the client, but only if the mount
+			is using the 'sec=sys' security flavour. This may
+			make migration from legacy NFSv2/v3 systems easier
+			provided that the server has the appropriate support.
+			The default is to always enable NFSv4 idmapping.
+
 	nmi_debug=	[KNL,AVR32,SH] Specify one or more actions to take
 			when a NMI is triggered.
 			Format: [state][,regs][,debounce][,die]
 
 	nmi_watchdog=	[KNL,BUGS=X86] Debugging features for SMP kernels
-			Format: [panic,][num]
+			Format: [panic,][nopanic,][num]
 			Valid num: 0
 			0 - turn nmi_watchdog off
 			When panic is specified, panic when an NMI watchdog
-			timeout occurs.
+			timeout occurs (or 'nopanic' to override the opposite
+			default).
 			This is useful when you use a panic=... timeout and
 			need the box quickly up again.
 
@@ -1813,6 +1832,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 				perfmon on Intel CPUs instead of the
 				CPU specific event set.
 
+	oops=panic	Always panic on oopses. Default is to just kill the process,
+			but there is a small probability of deadlocking the machine.
+			This will also cause panics on machine check exceptions.
+			Useful together with panic=30 to trigger a reboot.
+
 	OSS		[HW,OSS]
 			See Documentation/sound/oss/oss-parameters.txt
 
@@ -2444,6 +2468,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			<deci-seconds>: poll all this frequency
 			0: no polling (default)
 
+	threadirqs	[KNL]
+			Force threading of all interrupt handlers except those
+			marked explicitely IRQF_NO_THREAD.
+
 	topology=	[S390]
 			Format: {off | on}
 			Specify if the kernel should make use of the cpu
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt
index 09b55e4..69686ad 100644
--- a/Documentation/keys-request-key.txt
+++ b/Documentation/keys-request-key.txt
@@ -127,14 +127,15 @@ This is because process A's keyrings can't simply be attached to
 of them, and (b) it requires the same UID/GID/Groups all the way through.
 
 
-======================
-NEGATIVE INSTANTIATION
-======================
+====================================
+NEGATIVE INSTANTIATION AND REJECTION
+====================================
 
 Rather than instantiating a key, it is possible for the possessor of an
 authorisation key to negatively instantiate a key that's under construction.
 This is a short duration placeholder that causes any attempt at re-requesting
-the key whilst it exists to fail with error ENOKEY.
+the key whilst it exists to fail with error ENOKEY if negated or the specified
+error if rejected.
 
 This is provided to prevent excessive repeated spawning of /sbin/request-key
 processes for a key that will never be obtainable.
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index e4dbbdb..6523a9e 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -637,6 +637,9 @@ The keyctl syscall functions are:
 	long keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
 		    const void *payload, size_t plen,
 		    key_serial_t keyring);
+	long keyctl(KEYCTL_INSTANTIATE_IOV, key_serial_t key,
+		    const struct iovec *payload_iov, unsigned ioc,
+		    key_serial_t keyring);
 
      If the kernel calls back to userspace to complete the instantiation of a
      key, userspace should use this call to supply data for the key before the
@@ -652,11 +655,16 @@ The keyctl syscall functions are:
 
      The payload and plen arguments describe the payload data as for add_key().
 
+     The payload_iov and ioc arguments describe the payload data in an iovec
+     array instead of a single buffer.
+
 
  (*) Negatively instantiate a partially constructed key.
 
 	long keyctl(KEYCTL_NEGATE, key_serial_t key,
 		    unsigned timeout, key_serial_t keyring);
+	long keyctl(KEYCTL_REJECT, key_serial_t key,
+		    unsigned timeout, unsigned error, key_serial_t keyring);
 
      If the kernel calls back to userspace to complete the instantiation of a
      key, userspace should use this call mark the key as negative before the
@@ -669,6 +677,10 @@ The keyctl syscall functions are:
      that keyring, however all the constraints applying in KEYCTL_LINK apply in
      this case too.
 
+     If the key is rejected, future searches for it will return the specified
+     error code until the rejected key expires.  Negating the key is the same
+     as rejecting the key with ENOKEY as the error code.
+
 
  (*) Set the default request-key destination keyring.
 
@@ -1062,6 +1074,13 @@ The structure has a number of fields, some of which are mandatory:
      viable.
 
 
+ (*) int (*vet_description)(const char *description);
+
+     This optional method is called to vet a key description.  If the key type
+     doesn't approve of the key description, it may return an error, otherwise
+     it should return 0.
+
+
  (*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
 
      This method is called to attach a payload to a key during construction.
@@ -1231,10 +1250,11 @@ hand the request off to (perhaps a path held in placed in another key by, for
 example, the KDE desktop manager).
 
 The program (or whatever it calls) should finish construction of the key by
-calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of
-the keyrings (probably the session ring) before returning. Alternatively, the
-key can be marked as negative with KEYCTL_NEGATE; this also permits the key to
-be cached in one of the keyrings.
+calling KEYCTL_INSTANTIATE or KEYCTL_INSTANTIATE_IOV, which also permits it to
+cache the key in one of the keyrings (probably the session ring) before
+returning.  Alternatively, the key can be marked as negative with KEYCTL_NEGATE
+or KEYCTL_REJECT; this also permits the key to be cached in one of the
+keyrings.
 
 If it returns with the key remaining in the unconstructed state, the key will
 be marked as being negative, it will be added to the session keyring, and an
diff --git a/Documentation/kref.txt b/Documentation/kref.txt
index ae203f9..48ba715 100644
--- a/Documentation/kref.txt
+++ b/Documentation/kref.txt
@@ -156,7 +156,7 @@ static struct my_data *get_entry()
 	struct my_data *entry = NULL;
 	mutex_lock(&mutex);
 	if (!list_empty(&q)) {
-		entry = container_of(q.next, struct my_q_entry, link);
+		entry = container_of(q.next, struct my_data, link);
 		kref_get(&entry->refcount);
 	}
 	mutex_unlock(&mutex);
diff --git a/Documentation/kvm/api.txt b/Documentation/kvm/api.txt
index ad85797..9bef4e4 100644
--- a/Documentation/kvm/api.txt
+++ b/Documentation/kvm/api.txt
@@ -166,7 +166,7 @@ Returns: 0 on success, -1 on error
 
 This ioctl is obsolete and has been removed.
 
-4.6 KVM_CREATE_VCPU
+4.7 KVM_CREATE_VCPU
 
 Capability: basic
 Architectures: all
@@ -177,7 +177,7 @@ Returns: vcpu fd on success, -1 on error
 This API adds a vcpu to a virtual machine.  The vcpu id is a small integer
 in the range [0, max_vcpus).
 
-4.7 KVM_GET_DIRTY_LOG (vm ioctl)
+4.8 KVM_GET_DIRTY_LOG (vm ioctl)
 
 Capability: basic
 Architectures: x86
@@ -200,7 +200,7 @@ since the last call to this ioctl.  Bit 0 is the first page in the
 memory slot.  Ensure the entire structure is cleared to avoid padding
 issues.
 
-4.8 KVM_SET_MEMORY_ALIAS
+4.9 KVM_SET_MEMORY_ALIAS
 
 Capability: basic
 Architectures: x86
@@ -210,7 +210,7 @@ Returns: 0 (success), -1 (error)
 
 This ioctl is obsolete and has been removed.
 
-4.9 KVM_RUN
+4.10 KVM_RUN
 
 Capability: basic
 Architectures: all
@@ -226,7 +226,7 @@ obtained by mmap()ing the vcpu fd at offset 0, with the size given by
 KVM_GET_VCPU_MMAP_SIZE.  The parameter block is formatted as a 'struct
 kvm_run' (see below).
 
-4.10 KVM_GET_REGS
+4.11 KVM_GET_REGS
 
 Capability: basic
 Architectures: all
@@ -246,7 +246,7 @@ struct kvm_regs {
 	__u64 rip, rflags;
 };
 
-4.11 KVM_SET_REGS
+4.12 KVM_SET_REGS
 
 Capability: basic
 Architectures: all
@@ -258,7 +258,7 @@ Writes the general purpose registers into the vcpu.
 
 See KVM_GET_REGS for the data structure.
 
-4.12 KVM_GET_SREGS
+4.13 KVM_GET_SREGS
 
 Capability: basic
 Architectures: x86
@@ -283,7 +283,7 @@ interrupt_bitmap is a bitmap of pending external interrupts.  At most
 one bit may be set.  This interrupt has been acknowledged by the APIC
 but not yet injected into the cpu core.
 
-4.13 KVM_SET_SREGS
+4.14 KVM_SET_SREGS
 
 Capability: basic
 Architectures: x86
@@ -294,7 +294,7 @@ Returns: 0 on success, -1 on error
 Writes special registers into the vcpu.  See KVM_GET_SREGS for the
 data structures.
 
-4.14 KVM_TRANSLATE
+4.15 KVM_TRANSLATE
 
 Capability: basic
 Architectures: x86
@@ -317,7 +317,7 @@ struct kvm_translation {
 	__u8  pad[5];
 };
 
-4.15 KVM_INTERRUPT
+4.16 KVM_INTERRUPT
 
 Capability: basic
 Architectures: x86, ppc
@@ -365,7 +365,7 @@ c) KVM_INTERRUPT_SET_LEVEL
 Note that any value for 'irq' other than the ones stated above is invalid
 and incurs unexpected behavior.
 
-4.16 KVM_DEBUG_GUEST
+4.17 KVM_DEBUG_GUEST
 
 Capability: basic
 Architectures: none
@@ -375,7 +375,7 @@ Returns: -1 on error
 
 Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
 
-4.17 KVM_GET_MSRS
+4.18 KVM_GET_MSRS
 
 Capability: basic
 Architectures: x86
@@ -403,7 +403,7 @@ Application code should set the 'nmsrs' member (which indicates the
 size of the entries array) and the 'index' member of each array entry.
 kvm will fill in the 'data' member.
 
-4.18 KVM_SET_MSRS
+4.19 KVM_SET_MSRS
 
 Capability: basic
 Architectures: x86
@@ -418,7 +418,7 @@ Application code should set the 'nmsrs' member (which indicates the
 size of the entries array), and the 'index' and 'data' members of each
 array entry.
 
-4.19 KVM_SET_CPUID
+4.20 KVM_SET_CPUID
 
 Capability: basic
 Architectures: x86
@@ -446,7 +446,7 @@ struct kvm_cpuid {
 	struct kvm_cpuid_entry entries[0];
 };
 
-4.20 KVM_SET_SIGNAL_MASK
+4.21 KVM_SET_SIGNAL_MASK
 
 Capability: basic
 Architectures: x86
@@ -468,7 +468,7 @@ struct kvm_signal_mask {
 	__u8  sigset[0];
 };
 
-4.21 KVM_GET_FPU
+4.22 KVM_GET_FPU
 
 Capability: basic
 Architectures: x86
@@ -493,7 +493,7 @@ struct kvm_fpu {
 	__u32 pad2;
 };
 
-4.22 KVM_SET_FPU
+4.23 KVM_SET_FPU
 
 Capability: basic
 Architectures: x86
@@ -518,7 +518,7 @@ struct kvm_fpu {
 	__u32 pad2;
 };
 
-4.23 KVM_CREATE_IRQCHIP
+4.24 KVM_CREATE_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -531,7 +531,7 @@ ioapic, a virtual PIC (two PICs, nested), and sets up future vcpus to have a
 local APIC.  IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
 only go to the IOAPIC.  On ia64, a IOSAPIC is created.
 
-4.24 KVM_IRQ_LINE
+4.25 KVM_IRQ_LINE
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -552,7 +552,7 @@ struct kvm_irq_level {
 	__u32 level;           /* 0 or 1 */
 };
 
-4.25 KVM_GET_IRQCHIP
+4.26 KVM_GET_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -573,7 +573,7 @@ struct kvm_irqchip {
 	} chip;
 };
 
-4.26 KVM_SET_IRQCHIP
+4.27 KVM_SET_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -594,7 +594,7 @@ struct kvm_irqchip {
 	} chip;
 };
 
-4.27 KVM_XEN_HVM_CONFIG
+4.28 KVM_XEN_HVM_CONFIG
 
 Capability: KVM_CAP_XEN_HVM
 Architectures: x86
@@ -618,7 +618,7 @@ struct kvm_xen_hvm_config {
 	__u8 pad2[30];
 };
 
-4.27 KVM_GET_CLOCK
+4.29 KVM_GET_CLOCK
 
 Capability: KVM_CAP_ADJUST_CLOCK
 Architectures: x86
@@ -636,7 +636,7 @@ struct kvm_clock_data {
 	__u32 pad[9];
 };
 
-4.28 KVM_SET_CLOCK
+4.30 KVM_SET_CLOCK
 
 Capability: KVM_CAP_ADJUST_CLOCK
 Architectures: x86
@@ -654,7 +654,7 @@ struct kvm_clock_data {
 	__u32 pad[9];
 };
 
-4.29 KVM_GET_VCPU_EVENTS
+4.31 KVM_GET_VCPU_EVENTS
 
 Capability: KVM_CAP_VCPU_EVENTS
 Extended by: KVM_CAP_INTR_SHADOW
@@ -693,7 +693,7 @@ struct kvm_vcpu_events {
 KVM_VCPUEVENT_VALID_SHADOW may be set in the flags field to signal that
 interrupt.shadow contains a valid state. Otherwise, this field is undefined.
 
-4.30 KVM_SET_VCPU_EVENTS
+4.32 KVM_SET_VCPU_EVENTS
 
 Capability: KVM_CAP_VCPU_EVENTS
 Extended by: KVM_CAP_INTR_SHADOW
@@ -719,7 +719,7 @@ If KVM_CAP_INTR_SHADOW is available, KVM_VCPUEVENT_VALID_SHADOW can be set in
 the flags field to signal that interrupt.shadow contains a valid state and
 shall be written into the VCPU.
 
-4.32 KVM_GET_DEBUGREGS
+4.33 KVM_GET_DEBUGREGS
 
 Capability: KVM_CAP_DEBUGREGS
 Architectures: x86
@@ -737,7 +737,7 @@ struct kvm_debugregs {
 	__u64 reserved[9];
 };
 
-4.33 KVM_SET_DEBUGREGS
+4.34 KVM_SET_DEBUGREGS
 
 Capability: KVM_CAP_DEBUGREGS
 Architectures: x86
@@ -750,7 +750,7 @@ Writes debug registers into the vcpu.
 See KVM_GET_DEBUGREGS for the data structure. The flags field is unused
 yet and must be cleared on entry.
 
-4.34 KVM_SET_USER_MEMORY_REGION
+4.35 KVM_SET_USER_MEMORY_REGION
 
 Capability: KVM_CAP_USER_MEM
 Architectures: all
@@ -796,7 +796,7 @@ It is recommended to use this API instead of the KVM_SET_MEMORY_REGION ioctl.
 The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
 allocation and is deprecated.
 
-4.35 KVM_SET_TSS_ADDR
+4.36 KVM_SET_TSS_ADDR
 
 Capability: KVM_CAP_SET_TSS_ADDR
 Architectures: x86
@@ -814,7 +814,7 @@ This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
 because of a quirk in the virtualization implementation (see the internals
 documentation when it pops into existence).
 
-4.36 KVM_ENABLE_CAP
+4.37 KVM_ENABLE_CAP
 
 Capability: KVM_CAP_ENABLE_CAP
 Architectures: ppc
@@ -849,7 +849,7 @@ function properly, this is the place to put them.
        __u8  pad[64];
 };
 
-4.37 KVM_GET_MP_STATE
+4.38 KVM_GET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
 Architectures: x86, ia64
@@ -879,7 +879,7 @@ Possible values are:
 This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
 irqchip, the multiprocessing state must be maintained by userspace.
 
-4.38 KVM_SET_MP_STATE
+4.39 KVM_SET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
 Architectures: x86, ia64
@@ -893,7 +893,7 @@ arguments.
 This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
 irqchip, the multiprocessing state must be maintained by userspace.
 
-4.39 KVM_SET_IDENTITY_MAP_ADDR
+4.40 KVM_SET_IDENTITY_MAP_ADDR
 
 Capability: KVM_CAP_SET_IDENTITY_MAP_ADDR
 Architectures: x86
@@ -911,7 +911,7 @@ This ioctl is required on Intel-based hosts.  This is needed on Intel hardware
 because of a quirk in the virtualization implementation (see the internals
 documentation when it pops into existence).
 
-4.40 KVM_SET_BOOT_CPU_ID
+4.41 KVM_SET_BOOT_CPU_ID
 
 Capability: KVM_CAP_SET_BOOT_CPU_ID
 Architectures: x86, ia64
@@ -923,7 +923,7 @@ Define which vcpu is the Bootstrap Processor (BSP).  Values are the same
 as the vcpu id in KVM_CREATE_VCPU.  If this ioctl is not called, the default
 is vcpu 0.
 
-4.41 KVM_GET_XSAVE
+4.42 KVM_GET_XSAVE
 
 Capability: KVM_CAP_XSAVE
 Architectures: x86
@@ -937,7 +937,7 @@ struct kvm_xsave {
 
 This ioctl would copy current vcpu's xsave struct to the userspace.
 
-4.42 KVM_SET_XSAVE
+4.43 KVM_SET_XSAVE
 
 Capability: KVM_CAP_XSAVE
 Architectures: x86
@@ -951,7 +951,7 @@ struct kvm_xsave {
 
 This ioctl would copy userspace's xsave struct to the kernel.
 
-4.43 KVM_GET_XCRS
+4.44 KVM_GET_XCRS
 
 Capability: KVM_CAP_XCRS
 Architectures: x86
@@ -974,7 +974,7 @@ struct kvm_xcrs {
 
 This ioctl would copy current vcpu's xcrs to the userspace.
 
-4.44 KVM_SET_XCRS
+4.45 KVM_SET_XCRS
 
 Capability: KVM_CAP_XCRS
 Architectures: x86
@@ -997,7 +997,7 @@ struct kvm_xcrs {
 
 This ioctl would set vcpu's xcr to the value userspace specified.
 
-4.45 KVM_GET_SUPPORTED_CPUID
+4.46 KVM_GET_SUPPORTED_CPUID
 
 Capability: KVM_CAP_EXT_CPUID
 Architectures: x86
@@ -1062,7 +1062,7 @@ emulate them efficiently. The fields in each entry are defined as follows:
    eax, ebx, ecx, edx: the values returned by the cpuid instruction for
          this function/index combination
 
-4.46 KVM_PPC_GET_PVINFO
+4.47 KVM_PPC_GET_PVINFO
 
 Capability: KVM_CAP_PPC_GET_PVINFO
 Architectures: ppc
@@ -1085,7 +1085,7 @@ of 4 instructions that make up a hypercall.
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
-4.47 KVM_ASSIGN_PCI_DEVICE
+4.48 KVM_ASSIGN_PCI_DEVICE
 
 Capability: KVM_CAP_DEVICE_ASSIGNMENT
 Architectures: x86 ia64
@@ -1113,7 +1113,7 @@ following flags are specified:
 /* Depends on KVM_CAP_IOMMU */
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 
-4.48 KVM_DEASSIGN_PCI_DEVICE
+4.49 KVM_DEASSIGN_PCI_DEVICE
 
 Capability: KVM_CAP_DEVICE_DEASSIGNMENT
 Architectures: x86 ia64
@@ -1126,7 +1126,7 @@ Ends PCI device assignment, releasing all associated resources.
 See KVM_CAP_DEVICE_ASSIGNMENT for the data structure. Only assigned_dev_id is
 used in kvm_assigned_pci_dev to identify the device.
 
-4.49 KVM_ASSIGN_DEV_IRQ
+4.50 KVM_ASSIGN_DEV_IRQ
 
 Capability: KVM_CAP_ASSIGN_DEV_IRQ
 Architectures: x86 ia64
@@ -1164,7 +1164,7 @@ The following flags are defined:
 It is not valid to specify multiple types per host or guest IRQ. However, the
 IRQ type of host and guest can differ or can even be null.
 
-4.50 KVM_DEASSIGN_DEV_IRQ
+4.51 KVM_DEASSIGN_DEV_IRQ
 
 Capability: KVM_CAP_ASSIGN_DEV_IRQ
 Architectures: x86 ia64
@@ -1178,7 +1178,7 @@ See KVM_ASSIGN_DEV_IRQ for the data structure. The target device is specified
 by assigned_dev_id, flags must correspond to the IRQ type specified on
 KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
 
-4.51 KVM_SET_GSI_ROUTING
+4.52 KVM_SET_GSI_ROUTING
 
 Capability: KVM_CAP_IRQ_ROUTING
 Architectures: x86 ia64
@@ -1226,7 +1226,7 @@ struct kvm_irq_routing_msi {
 	__u32 pad;
 };
 
-4.52 KVM_ASSIGN_SET_MSIX_NR
+4.53 KVM_ASSIGN_SET_MSIX_NR
 
 Capability: KVM_CAP_DEVICE_MSIX
 Architectures: x86 ia64
@@ -1245,7 +1245,7 @@ struct kvm_assigned_msix_nr {
 
 #define KVM_MAX_MSIX_PER_DEV		256
 
-4.53 KVM_ASSIGN_SET_MSIX_ENTRY
+4.54 KVM_ASSIGN_SET_MSIX_ENTRY
 
 Capability: KVM_CAP_DEVICE_MSIX
 Architectures: x86 ia64
diff --git a/Documentation/kvm/locking.txt b/Documentation/kvm/locking.txt
new file mode 100644
index 0000000..3b4cd3b
--- /dev/null
+++ b/Documentation/kvm/locking.txt
@@ -0,0 +1,25 @@
+KVM Lock Overview
+=================
+
+1. Acquisition Orders
+---------------------
+
+(to be written)
+
+2. Reference
+------------
+
+Name:		kvm_lock
+Type:		raw_spinlock
+Arch:		any
+Protects:	- vm_list
+		- hardware virtualization enable/disable
+Comment:	'raw' because hardware enabling/disabling must be atomic /wrt
+		migration.
+
+Name:		kvm_arch::tsc_write_lock
+Type:		raw_spinlock
+Arch:		x86
+Protects:	- kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
+		- tsc offset in vmcb
+Comment:	'raw' because updating the tsc offsets must not be preempted.
diff --git a/Documentation/laptops/hpfall.c b/Documentation/laptops/hpfall.c
new file mode 100644
index 0000000..a4a8fc5
--- /dev/null
+++ b/Documentation/laptops/hpfall.c
@@ -0,0 +1,146 @@
+/* Disk protection for HP machines.
+ *
+ * Copyright 2008 Eric Piel
+ * Copyright 2009 Pavel Machek <pavel@ucw.cz>
+ *
+ * GPLv2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sched.h>
+
+char unload_heads_path[64];
+
+int set_unload_heads_path(char *device)
+{
+	char devname[64];
+
+	if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
+		return -EINVAL;
+	strncpy(devname, device + 5, sizeof(devname));
+
+	snprintf(unload_heads_path, sizeof(unload_heads_path),
+				"/sys/block/%s/device/unload_heads", devname);
+	return 0;
+}
+int valid_disk(void)
+{
+	int fd = open(unload_heads_path, O_RDONLY);
+	if (fd < 0) {
+		perror(unload_heads_path);
+		return 0;
+	}
+
+	close(fd);
+	return 1;
+}
+
+void write_int(char *path, int i)
+{
+	char buf[1024];
+	int fd = open(path, O_RDWR);
+	if (fd < 0) {
+		perror("open");
+		exit(1);
+	}
+	sprintf(buf, "%d", i);
+	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+		perror("write");
+		exit(1);
+	}
+	close(fd);
+}
+
+void set_led(int on)
+{
+	write_int("/sys/class/leds/hp::hddprotect/brightness", on);
+}
+
+void protect(int seconds)
+{
+	write_int(unload_heads_path, seconds*1000);
+}
+
+int on_ac(void)
+{
+//	/sys/class/power_supply/AC0/online
+}
+
+int lid_open(void)
+{
+//	/proc/acpi/button/lid/LID/state
+}
+
+void ignore_me(void)
+{
+	protect(0);
+	set_led(0);
+}
+
+int main(int argc, char **argv)
+{
+	int fd, ret;
+	struct sched_param param;
+
+	if (argc == 1)
+		ret = set_unload_heads_path("/dev/sda");
+	else if (argc == 2)
+		ret = set_unload_heads_path(argv[1]);
+	else
+		ret = -EINVAL;
+
+	if (ret || !valid_disk()) {
+		fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n",
+				argv[0]);
+		exit(1);
+	}
+
+	fd = open("/dev/freefall", O_RDONLY);
+	if (fd < 0) {
+		perror("/dev/freefall");
+		return EXIT_FAILURE;
+	}
+
+	daemon(0, 0);
+	param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+	sched_setscheduler(0, SCHED_FIFO, &param);
+	mlockall(MCL_CURRENT|MCL_FUTURE);
+
+	signal(SIGALRM, ignore_me);
+
+	for (;;) {
+		unsigned char count;
+
+		ret = read(fd, &count, sizeof(count));
+		alarm(0);
+		if ((ret == -1) && (errno == EINTR)) {
+			/* Alarm expired, time to unpark the heads */
+			continue;
+		}
+
+		if (ret != sizeof(count)) {
+			perror("read");
+			break;
+		}
+
+		protect(21);
+		set_led(1);
+		if (1 || on_ac() || lid_open())
+			alarm(2);
+		else
+			alarm(20);
+	}
+
+	close(fd);
+	return EXIT_SUCCESS;
+}
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 631ad2f..f0d3a80 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -21,6 +21,7 @@ Contents:
      - SMP barrier pairing.
      - Examples of memory barrier sequences.
      - Read memory barriers vs load speculation.
+     - Transitivity
 
  (*) Explicit kernel barriers.
 
@@ -959,6 +960,63 @@ the speculation will be cancelled and the value reloaded:
 	retrieved                               :       :       +-------+
 
 
+TRANSITIVITY
+------------
+
+Transitivity is a deeply intuitive notion about ordering that is not
+always provided by real computer systems.  The following example
+demonstrates transitivity (also called "cumulativity"):
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<general barrier>	<general barrier>
+				LOAD Y			LOAD X
+
+Suppose that CPU 2's load from X returns 1 and its load from Y returns 0.
+This indicates that CPU 2's load from X in some sense follows CPU 1's
+store to X and that CPU 2's load from Y in some sense preceded CPU 3's
+store to Y.  The question is then "Can CPU 3's load from X return 0?"
+
+Because CPU 2's load from X in some sense came after CPU 1's store, it
+is natural to expect that CPU 3's load from X must therefore return 1.
+This expectation is an example of transitivity: if a load executing on
+CPU A follows a load from the same variable executing on CPU B, then
+CPU A's load must either return the same value that CPU B's load did,
+or must return some later value.
+
+In the Linux kernel, use of general memory barriers guarantees
+transitivity.  Therefore, in the above example, if CPU 2's load from X
+returns 1 and its load from Y returns 0, then CPU 3's load from X must
+also return 1.
+
+However, transitivity is -not- guaranteed for read or write barriers.
+For example, suppose that CPU 2's general barrier in the above example
+is changed to a read barrier as shown below:
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<read barrier>		<general barrier>
+				LOAD Y			LOAD X
+
+This substitution destroys transitivity: in this example, it is perfectly
+legal for CPU 2's load from X to return 1, its load from Y to return 0,
+and CPU 3's load from X to return 0.
+
+The key point is that although CPU 2's read barrier orders its pair
+of loads, it does not guarantee to order CPU 1's store.  Therefore, if
+this example runs on a system where CPUs 1 and 2 share a store buffer
+or a level of cache, CPU 2 might have early access to CPU 1's writes.
+General barriers are therefore required to ensure that all CPUs agree
+on the combined order of CPU 1's and CPU 2's accesses.
+
+To reiterate, if your code requires transitivity, use general barriers
+throughout.
+
+
 ========================
 EXPLICIT KERNEL BARRIERS
 ========================
diff --git a/Documentation/memory-hotplug.txt b/Documentation/memory-hotplug.txt
index 57e7e9c..8f485d7 100644
--- a/Documentation/memory-hotplug.txt
+++ b/Documentation/memory-hotplug.txt
@@ -126,36 +126,51 @@ config options.
 --------------------------------
 4 sysfs files for memory hotplug
 --------------------------------
-All sections have their device information under /sys/devices/system/memory as
+All sections have their device information in sysfs.  Each section is part of
+a memory block under /sys/devices/system/memory as
 
 /sys/devices/system/memory/memoryXXX
-(XXX is section id.)
+(XXX is the section id.)
 
-Now, XXX is defined as start_address_of_section / section_size.
+Now, XXX is defined as (start_address_of_section / section_size) of the first
+section contained in the memory block.  The files 'phys_index' and
+'end_phys_index' under each directory report the beginning and end section id's
+for the memory block covered by the sysfs directory.  It is expected that all
+memory sections in this range are present and no memory holes exist in the
+range. Currently there is no way to determine if there is a memory hole, but
+the existence of one should not affect the hotplug capabilities of the memory
+block.
 
 For example, assume 1GiB section size. A device for a memory starting at
 0x100000000 is /sys/device/system/memory/memory4
 (0x100000000 / 1Gib = 4)
 This device covers address range [0x100000000 ... 0x140000000)
 
-Under each section, you can see 4 files.
+Under each section, you can see 4 or 5 files, the end_phys_index file being
+a recent addition and not present on older kernels.
 
-/sys/devices/system/memory/memoryXXX/phys_index
+/sys/devices/system/memory/memoryXXX/start_phys_index
+/sys/devices/system/memory/memoryXXX/end_phys_index
 /sys/devices/system/memory/memoryXXX/phys_device
 /sys/devices/system/memory/memoryXXX/state
 /sys/devices/system/memory/memoryXXX/removable
 
-'phys_index' : read-only and contains section id, same as XXX.
-'state'      : read-write
-               at read:  contains online/offline state of memory.
-               at write: user can specify "online", "offline" command
-'phys_device': read-only: designed to show the name of physical memory device.
-               This is not well implemented now.
-'removable'  : read-only: contains an integer value indicating
-               whether the memory section is removable or not
-               removable.  A value of 1 indicates that the memory
-               section is removable and a value of 0 indicates that
-               it is not removable.
+'phys_index'      : read-only and contains section id of the first section
+		    in the memory block, same as XXX.
+'end_phys_index'  : read-only and contains section id of the last section
+		    in the memory block.
+'state'           : read-write
+                    at read:  contains online/offline state of memory.
+                    at write: user can specify "online", "offline" command
+                    which will be performed on al sections in the block.
+'phys_device'     : read-only: designed to show the name of physical memory
+                    device.  This is not well implemented now.
+'removable'       : read-only: contains an integer value indicating
+                    whether the memory block is removable or not
+                    removable.  A value of 1 indicates that the memory
+                    block is removable and a value of 0 indicates that
+                    it is not removable. A memory block is removable only if
+                    every section in the block is removable.
 
 NOTE:
   These directories/files appear after physical memory hotplug phase.
diff --git a/Documentation/misc-devices/lis3lv02d b/Documentation/misc-devices/lis3lv02d
new file mode 100644
index 0000000..f1a4ec8
--- /dev/null
+++ b/Documentation/misc-devices/lis3lv02d
@@ -0,0 +1,92 @@
+Kernel driver lis3lv02d
+=======================
+
+Supported chips:
+
+  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
+  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
+
+Authors:
+        Yan Burman <burman.yan@gmail.com>
+	Eric Piel <eric.piel@tremplin-utc.net>
+
+
+Description
+-----------
+
+This driver provides support for the accelerometer found in various HP laptops
+sporting the feature officially called "HP Mobile Data Protection System 3D" or
+"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known
+models (full list can be found in drivers/platform/x86/hp_accel.c) will have
+their axis automatically oriented on standard way (eg: you can directly play
+neverball). The accelerometer data is readable via
+/sys/devices/platform/lis3lv02d. Reported values are scaled
+to mg values (1/1000th of earth gravity).
+
+Sysfs attributes under /sys/devices/platform/lis3lv02d/:
+position - 3D position that the accelerometer reports. Format: "(x,y,z)"
+rate - read reports the sampling rate of the accelerometer device in HZ.
+	write changes sampling rate of the accelerometer device.
+	Only values which are supported by HW are accepted.
+selftest - performs selftest for the chip as specified by chip manufacturer.
+
+This driver also provides an absolute input class device, allowing
+the laptop to act as a pinball machine-esque joystick. Joystick device can be
+calibrated. Joystick device can be in two different modes.
+By default output values are scaled between -32768 .. 32767. In joystick raw
+mode, joystick and sysfs position entry have the same scale. There can be
+small difference due to input system fuzziness feature.
+Events are also available as input event device.
+
+Selftest is meant only for hardware diagnostic purposes. It is not meant to be
+used during normal operations. Position data is not corrupted during selftest
+but interrupt behaviour is not guaranteed to work reliably. In test mode, the
+sensing element is internally moved little bit. Selftest measures difference
+between normal mode and test mode. Chip specifications tell the acceptance
+limit for each type of the chip. Limits are provided via platform data
+to allow adjustment of the limits without a change to the actual driver.
+Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are
+measured difference between modes. Axes are not remapped in selftest mode.
+Measurement values are provided to help HW diagnostic applications to make
+final decision.
+
+On HP laptops, if the led infrastructure is activated, support for a led
+indicating disk protection will be provided as /sys/class/leds/hp::hddprotect.
+
+Another feature of the driver is misc device called "freefall" that
+acts similar to /dev/rtc and reacts on free-fall interrupts received
+from the device. It supports blocking operations, poll/select and
+fasync operation modes. You must read 1 bytes from the device.  The
+result is number of free-fall interrupts since the last successful
+read (or 255 if number of interrupts would not fit). See the hpfall.c
+file for an example on using the device.
+
+
+Axes orientation
+----------------
+
+For better compatibility between the various laptops. The values reported by
+the accelerometer are converted into a "standard" organisation of the axes
+(aka "can play neverball out of the box"):
+ * When the laptop is horizontal the position reported is about 0 for X and Y
+	and a positive value for Z
+ * If the left side is elevated, X increases (becomes positive)
+ * If the front side (where the touchpad is) is elevated, Y decreases
+	(becomes negative)
+ * If the laptop is put upside-down, Z becomes negative
+
+If your laptop model is not recognized (cf "dmesg"), you can send an
+email to the maintainer to add it to the database.  When reporting a new
+laptop, please include the output of "dmidecode" plus the value of
+/sys/devices/platform/lis3lv02d/position in these four cases.
+
+Q&A
+---
+
+Q: How do I safely simulate freefall? I have an HP "portable
+workstation" which has about 3.5kg and a plastic case, so letting it
+fall to the ground is out of question...
+
+A: The sensor is pretty sensitive, so your hands can do it. Lift it
+into free space, follow the fall with your hands for like 10
+centimeters. That should be enough to trigger the detection.
diff --git a/Documentation/misc-devices/spear-pcie-gadget.txt b/Documentation/misc-devices/spear-pcie-gadget.txt
new file mode 100644
index 0000000..02c13ef
--- /dev/null
+++ b/Documentation/misc-devices/spear-pcie-gadget.txt
@@ -0,0 +1,130 @@
+Spear PCIe Gadget Driver:
+
+Author
+=============
+Pratyush Anand (pratyush.anand@st.com)
+
+Location
+============
+driver/misc/spear13xx_pcie_gadget.c
+
+Supported Chip:
+===================
+SPEAr1300
+SPEAr1310
+
+Menuconfig option:
+==========================
+Device Drivers
+	Misc devices
+		PCIe gadget support for SPEAr13XX platform
+purpose
+===========
+This driver has several nodes which can be read/written by configfs interface.
+Its main purpose is to configure selected dual mode PCIe controller as device
+and then program its various registers to configure it as a particular device
+type. This driver can be used to show spear's PCIe device capability.
+
+Description of different nodes:
+=================================
+
+read behavior of nodes:
+------------------------------
+link 		:gives ltssm status.
+int_type 	:type of supported interrupt
+no_of_msi 	:zero if MSI is not enabled by host. A positive value is the
+		number of MSI vector granted.
+vendor_id	:returns programmed vendor id (hex)
+device_id	:returns programmed device id(hex)
+bar0_size:	:returns size of bar0 in hex.
+bar0_address	:returns address of bar0 mapped area in hex.
+bar0_rw_offset	:returns offset of bar0 for which bar0_data will return value.
+bar0_data	:returns data at bar0_rw_offset.
+
+write behavior of nodes:
+------------------------------
+link 		:write UP to enable ltsmm DOWN to disable
+int_type	:write interrupt type to be configured and (int_type could be
+		INTA, MSI or NO_INT). Select MSI only when you have programmed
+		no_of_msi node.
+no_of_msi	:number of MSI vector needed.
+inta		:write 1 to assert INTA and 0 to de-assert.
+send_msi	:write MSI vector to be sent.
+vendor_id	:write vendor id(hex) to be programmed.
+device_id	:write device id(hex) to be programmed.
+bar0_size	:write size of bar0 in hex. default bar0 size is 1000 (hex)
+		bytes.
+bar0_address	:write	address of bar0 mapped area in hex. (default mapping of
+		bar0 is SYSRAM1(E0800000). Always program bar size before bar
+		address. Kernel might modify bar size and address for alignment, so
+		read back bar size and address after writing to cross check.
+bar0_rw_offset	:write offset of bar0 for which	bar0_data will write value.
+bar0_data	:write data to be written at bar0_rw_offset.
+
+Node programming example
+===========================
+Program all PCIe registers in such a way that when this device is connected
+to the PCIe host, then host sees this device as 1MB RAM.
+#mount -t configfs none /Config
+For nth PCIe Device Controller
+# cd /config/pcie_gadget.n/
+Now you have all the nodes in this directory.
+program vendor id as 0x104a
+# echo 104A >> vendor_id
+
+program device id as 0xCD80
+# echo CD80 >> device_id
+
+program BAR0 size as 1MB
+# echo 100000 >> bar0_size
+
+check for programmed bar0 size
+# cat bar0_size
+
+Program BAR0 Address as DDR (0x2100000). This is the physical address of
+memory, which is to be made visible to PCIe host. Similarly any other peripheral
+can also be made visible to PCIe host. E.g., if you program base address of UART
+as BAR0 address then when this device will be connected to a host, it will be
+visible as UART.
+# echo 2100000 >> bar0_address
+
+program interrupt type : INTA
+# echo INTA >> int_type
+
+go for link up now.
+# echo UP >> link
+
+It will have to be insured that, once link up is done on gadget, then only host
+is initialized and start to search PCIe devices on its port.
+
+/*wait till link is up*/
+# cat link
+wait till it returns UP.
+
+To assert INTA
+# echo 1 >> inta
+
+To de-assert INTA
+# echo 0 >> inta
+
+if MSI is to be used as interrupt, program no of msi vector needed (say4)
+# echo 4 >> no_of_msi
+
+select MSI as interrupt type
+# echo MSI >> int_type
+
+go for link up now
+# echo UP >> link
+
+wait till link is up
+# cat link
+An application can repetitively read this node till link is found UP. It can
+sleep between two read.
+
+wait till msi is enabled
+# cat no_of_msi
+Should return 4 (number of requested MSI vector)
+
+to send msi vector 2
+# echo 2 >> send_msi
+#cd -
diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt
index 77f0cdd..18afcd8 100644
--- a/Documentation/networking/batman-adv.txt
+++ b/Documentation/networking/batman-adv.txt
@@ -1,4 +1,4 @@
-[state: 21-11-2010]
+[state: 27-01-2011]
 
 BATMAN-ADV
 ----------
@@ -67,15 +67,16 @@ All  mesh  wide  settings  can be found in batman's own interface
 folder:
 
 #  ls  /sys/class/net/bat0/mesh/
-#  aggregated_ogms  bonding  fragmentation  orig_interval
-#  vis_mode
+#  aggregated_ogms  gw_bandwidth  hop_penalty
+#  bonding          gw_mode       orig_interval
+#  fragmentation    gw_sel_class  vis_mode
 
 
 There is a special folder for debugging informations:
 
 #  ls /sys/kernel/debug/batman_adv/bat0/
-#  originators  socket  transtable_global  transtable_local
-#  vis_data
+#  gateways     socket        transtable_global  vis_data
+#  originators  softif_neigh  transtable_local
 
 
 Some of the files contain all sort of status information  regard-
@@ -230,9 +231,8 @@ CONTACT
 Please send us comments, experiences, questions, anything :)
 
 IRC:            #batman   on   irc.freenode.org
-Mailing-list:   b.a.t.m.a.n@b.a.t.m.a.n@lists.open-mesh.org
-                (optional   subscription   at
-                 https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
+Mailing-list:   b.a.t.m.a.n@open-mesh.org (optional  subscription
+          at https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
 
 You can also contact the Authors:
 
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 25d2f41..b36e741 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -2558,18 +2558,15 @@ enslaved.
 16. Resources and Links
 =======================
 
-The latest version of the bonding driver can be found in the latest
+	The latest version of the bonding driver can be found in the latest
 version of the linux kernel, found on http://kernel.org
 
-The latest version of this document can be found in either the latest
-kernel source (named Documentation/networking/bonding.txt), or on the
-bonding sourceforge site:
+	The latest version of this document can be found in the latest kernel
+source (named Documentation/networking/bonding.txt).
 
-http://www.sourceforge.net/projects/bonding
-
-Discussions regarding the bonding driver take place primarily on the
-bonding-devel mailing list, hosted at sourceforge.net.  If you have
-questions or problems, post them to the list.  The list address is:
+	Discussions regarding the usage of the bonding driver take place on the
+bonding-devel mailing list, hosted at sourceforge.net. If you have questions or
+problems, post them to the list.  The list address is:
 
 bonding-devel@lists.sourceforge.net
 
@@ -2578,6 +2575,17 @@ be found at:
 
 https://lists.sourceforge.net/lists/listinfo/bonding-devel
 
+	Discussions regarding the developpement of the bonding driver take place
+on the main Linux network mailing list, hosted at vger.kernel.org. The list
+address is:
+
+netdev@vger.kernel.org
+
+	The administrative interface (to subscribe or unsubscribe) can
+be found at:
+
+http://vger.kernel.org/vger-lists.html#netdev
+
 Donald Becker's Ethernet Drivers and diag programs may be found at :
  - http://web.archive.org/web/*/http://www.scyld.com/network/ 
 
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ac3b4a7..d3d653a 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -280,6 +280,17 @@ tcp_max_orphans - INTEGER
 	more aggressively. Let me to remind again: each orphan eats
 	up to ~64K of unswappable memory.
 
+tcp_max_ssthresh - INTEGER
+	Limited Slow-Start for TCP with large congestion windows (cwnd) defined in
+	RFC3742. Limited slow-start is a mechanism to limit growth of the cwnd
+	on the region where cwnd is larger than tcp_max_ssthresh. TCP increases cwnd
+	by at most tcp_max_ssthresh segments, and by at least tcp_max_ssthresh/2
+	segments per RTT when the cwnd is above tcp_max_ssthresh.
+	If TCP connection increased cwnd to thousands (or tens of thousands) segments,
+	and thousands of packets were being dropped during slow-start, you can set
+	tcp_max_ssthresh to improve performance for new TCP connection.
+	Default: 0 (off)
+
 tcp_max_syn_backlog - INTEGER
 	Maximal number of remembered connection requests, which are
 	still did not receive an acknowledgment from connecting client.
diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
index 24ad2ad..8100358 100644
--- a/Documentation/networking/phonet.txt
+++ b/Documentation/networking/phonet.txt
@@ -154,9 +154,28 @@ connections, one per accept()'d socket.
     write(cfd, msg, msglen);
   }
 
-Connections are established between two endpoints by a "third party"
-application. This means that both endpoints are passive; so connect()
-is not possible.
+Connections are traditionally established between two endpoints by a
+"third party" application. This means that both endpoints are passive.
+
+
+As of Linux kernel version 2.6.39, it is also possible to connect
+two endpoints directly, using connect() on the active side. This is
+intended to support the newer Nokia Wireless Modem API, as found in
+e.g. the Nokia Slim Modem in the ST-Ericsson U8500 platform:
+
+  struct sockaddr_spn spn;
+  int fd;
+
+  fd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE);
+  memset(&spn, 0, sizeof(spn));
+  spn.spn_family = AF_PHONET;
+  spn.spn_obj = ...;
+  spn.spn_dev = ...;
+  spn.spn_resource = 0xD9;
+  connect(fd, (struct sockaddr *)&spn, sizeof(spn));
+  /* normal I/O here ... */
+  close(fd);
+
 
 WARNING:
 When polling a connected pipe socket for writability, there is an
@@ -181,45 +200,9 @@ The pipe protocol provides two socket options at the SOL_PNPIPE level:
     interface index of the network interface created by PNPIPE_ENCAP,
     or zero if encapsulation is off.
 
-
-Phonet Pipe-controller Implementation
--------------------------------------
-
-Phonet Pipe-controller is enabled by selecting the CONFIG_PHONET_PIPECTRLR Kconfig
-option. It is useful when communicating with those Nokia Modems which do not
-implement Pipe controller in them e.g. Nokia Slim Modem used in ST-Ericsson
-U8500 platform.
-
-The implementation is based on the Data Connection Establishment Sequence
-depicted in 'Nokia Wireless Modem API - Wireless_modem_user_guide.pdf'
-document.
-
-It allows a phonet sequenced socket (host-pep) to initiate a Pipe connection
-between itself and a remote pipe-end point (e.g. modem).
-
-The implementation adds socket options at SOL_PNPIPE level:
-
- PNPIPE_PIPE_HANDLE
-	It accepts an integer argument for setting value of pipe handle.
-
-  PNPIPE_ENABLE accepts one integer value (int). If set to zero, the pipe
-    is disabled. If the value is non-zero, the pipe is enabled. If the pipe
-    is not (yet) connected, ENOTCONN is error is returned.
-
-The implementation also adds socket 'connect'. On calling the 'connect', pipe
-will be created between the source socket and the destination, and the pipe
-state will be set to PIPE_DISABLED.
-
-After a pipe has been created and enabled successfully, the Pipe data can be
-exchanged between the host-pep and remote-pep (modem).
-
-User-space would typically follow below sequence with Pipe controller:-
--socket
--bind
--setsockopt for PNPIPE_PIPE_HANDLE
--connect
--setsockopt for PNPIPE_ENCAP_IP
--setsockopt for PNPIPE_ENABLE
+  PNPIPE_HANDLE is a read-only integer value. It contains the underlying
+    identifier ("pipe handle") of the pipe. This is only defined for
+    socket descriptors that are already connected or being connected.
 
 
 Authors
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 57080cd..f023ba6 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -1,6 +1,6 @@
 Device Power Management
 
-Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
 Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 
@@ -159,18 +159,18 @@ matter, and the kernel is responsible for keeping track of it.  By contrast,
 whether or not a wakeup-capable device should issue wakeup events is a policy
 decision, and it is managed by user space through a sysfs attribute: the
 power/wakeup file.  User space can write the strings "enabled" or "disabled" to
-set or clear the should_wakeup flag, respectively.  Reads from the file will
-return the corresponding string if can_wakeup is true, but if can_wakeup is
-false then reads will return an empty string, to indicate that the device
-doesn't support wakeup events.  (But even though the file appears empty, writes
-will still affect the should_wakeup flag.)
+set or clear the "should_wakeup" flag, respectively.  This file is only present
+for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
+and is created (or removed) by device_set_wakeup_capable().  Reads from the
+file will return the corresponding string.
 
 The device_may_wakeup() routine returns true only if both flags are set.
-Drivers should check this routine when putting devices in a low-power state
-during a system sleep transition, to see whether or not to enable the devices'
-wakeup mechanisms.  However for runtime power management, wakeup events should
-be enabled whenever the device and driver both support them, regardless of the
-should_wakeup flag.
+This information is used by subsystems, like the PCI bus type code, to see
+whether or not to enable the devices' wakeup mechanisms.  If device wakeup
+mechanisms are enabled or disabled directly by drivers, they also should use
+device_may_wakeup() to decide what to do during a system sleep transition.
+However for runtime power management, wakeup events should be enabled whenever
+the device and driver both support them, regardless of the should_wakeup flag.
 
 
 /sys/devices/.../power/control files
@@ -249,23 +249,18 @@ various phases always run after tasks have been frozen and before they are
 unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
 been disabled (except for those marked with the IRQ_WAKEUP flag).
 
-Most phases use bus, type, and class callbacks (that is, methods defined in
-dev->bus->pm, dev->type->pm, and dev->class->pm).  The prepare and complete
-phases are exceptions; they use only bus callbacks.  When multiple callbacks
-are used in a phase, they are invoked in the order: <class, type, bus> during
-power-down transitions and in the opposite order during power-up transitions.
-For example, during the suspend phase the PM core invokes
-
-	dev->class->pm.suspend(dev);
-	dev->type->pm.suspend(dev);
-	dev->bus->pm.suspend(dev);
-
-before moving on to the next device, whereas during the resume phase the core
-invokes
-
-	dev->bus->pm.resume(dev);
-	dev->type->pm.resume(dev);
-	dev->class->pm.resume(dev);
+All phases use bus, type, or class callbacks (that is, methods defined in
+dev->bus->pm, dev->type->pm, or dev->class->pm).  These callbacks are mutually
+exclusive, so if the device type provides a struct dev_pm_ops object pointed to
+by its pm field (i.e. both dev->type and dev->type->pm are defined), the
+callbacks included in that object (i.e. dev->type->pm) will be used.  Otherwise,
+if the class provides a struct dev_pm_ops object pointed to by its pm field
+(i.e. both dev->class and dev->class->pm are defined), the PM core will use the
+callbacks from that object (i.e. dev->class->pm).  Finally, if the pm fields of
+both the device type and class objects are NULL (or those objects do not exist),
+the callbacks provided by the bus (that is, the callbacks from dev->bus->pm)
+will be used (this allows device types to override callbacks provided by bus
+types or classes if necessary).
 
 These callbacks may in turn invoke device- or driver-specific methods stored in
 dev->driver->pm, but they don't have to.
@@ -507,6 +502,49 @@ routines.  Nevertheless, different callback pointers are used in case there is a
 situation where it actually matters.
 
 
+Device Power Domains
+--------------------
+Sometimes devices share reference clocks or other power resources.  In those
+cases it generally is not possible to put devices into low-power states
+individually.  Instead, a set of devices sharing a power resource can be put
+into a low-power state together at the same time by turning off the shared
+power resource.  Of course, they also need to be put into the full-power state
+together, by turning the shared power resource on.  A set of devices with this
+property is often referred to as a power domain.
+
+Support for power domains is provided through the pwr_domain field of struct
+device.  This field is a pointer to an object of type struct dev_power_domain,
+defined in include/linux/pm.h, providing a set of power management callbacks
+analogous to the subsystem-level and device driver callbacks that are executed
+for the given device during all power transitions, in addition to the respective
+subsystem-level callbacks.  Specifically, the power domain "suspend" callbacks
+(i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are
+executed after the analogous subsystem-level callbacks, while the power domain
+"resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore,
+etc.) are executed before the analogous subsystem-level callbacks.  Error codes
+returned by the "suspend" and "resume" power domain callbacks are ignored.
+
+Power domain ->runtime_idle() callback is executed before the subsystem-level
+->runtime_idle() callback and the result returned by it is not ignored.  Namely,
+if it returns error code, the subsystem-level ->runtime_idle() callback will not
+be called and the helper function rpm_idle() executing it will return error
+code.  This mechanism is intended to help platforms where saving device state
+is a time consuming operation and should only be carried out if all devices
+in the power domain are idle, before turning off the shared power resource(s).
+Namely, the power domain ->runtime_idle() callback may return error code until
+the pm_runtime_idle() helper (or its asychronous version) has been called for
+all devices in the power domain (it is recommended that the returned error code
+be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle()
+callback from being run prematurely.
+
+The support for device power domains is only relevant to platforms needing to
+use the same subsystem-level (e.g. platform bus type) and device driver power
+management callbacks in many different power domain configurations and wanting
+to avoid incorporating the support for power domains into the subsystem-level
+callbacks.  The other platforms need not implement it or take it into account
+in any way.
+
+
 System Devices
 --------------
 System devices (sysdevs) follow a slightly different API, which can be found in
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index ffe55ff..654097b 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -1,6 +1,6 @@
 Run-time Power Management Framework for I/O Devices
 
-(C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+(C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
 (C) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 1. Introduction
@@ -44,11 +44,12 @@ struct dev_pm_ops {
 };
 
 The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are
-executed by the PM core for either the bus type, or device type (if the bus
-type's callback is not defined), or device class (if the bus type's and device
-type's callbacks are not defined) of given device.  The bus type, device type
-and device class callbacks are referred to as subsystem-level callbacks in what
-follows.
+executed by the PM core for either the device type, or the class (if the device
+type's struct dev_pm_ops object does not exist), or the bus type (if the
+device type's and class' struct dev_pm_ops objects do not exist) of the given
+device (this allows device types to override callbacks provided by bus types or
+classes if necessary).  The bus type, device type and class callbacks are
+referred to as subsystem-level callbacks in what follows.
 
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
diff --git a/Documentation/power/states.txt b/Documentation/power/states.txt
index 34800cc..4416b28 100644
--- a/Documentation/power/states.txt
+++ b/Documentation/power/states.txt
@@ -62,12 +62,12 @@ setup via another operating system for it to use. Despite the
 inconvenience, this method requires minimal work by the kernel, since
 the firmware will also handle restoring memory contents on resume. 
 
-For suspend-to-disk, a mechanism called swsusp called 'swsusp' (Swap
-Suspend) is used to write memory contents to free swap space.
-swsusp has some restrictive requirements, but should work in most
-cases. Some, albeit outdated, documentation can be found in
-Documentation/power/swsusp.txt. Alternatively, userspace can do most
-of the actual suspend to disk work, see userland-swsusp.txt.
+For suspend-to-disk, a mechanism called 'swsusp' (Swap Suspend) is used
+to write memory contents to free swap space. swsusp has some restrictive
+requirements, but should work in most cases. Some, albeit outdated,
+documentation can be found in Documentation/power/swsusp.txt.
+Alternatively, userspace can do most of the actual suspend to disk work,
+see userland-swsusp.txt.
 
 Once memory state is written to disk, the system may either enter a
 low-power state (like ACPI S4), or it may simply power down. Powering
diff --git a/Documentation/powerpc/00-INDEX b/Documentation/powerpc/00-INDEX
index e3960b8..5620fb5 100644
--- a/Documentation/powerpc/00-INDEX
+++ b/Documentation/powerpc/00-INDEX
@@ -5,8 +5,6 @@ please mail me.
 
 00-INDEX
 	- this file
-booting-without-of.txt
-	- Booting the Linux/ppc kernel without Open Firmware
 cpu_features.txt
 	- info on how we support a variety of CPUs with minimal compile-time
 	options.
@@ -16,8 +14,6 @@ hvcs.txt
 	- IBM "Hypervisor Virtual Console Server" Installation Guide
 mpc52xx.txt
 	- Linux 2.6.x on MPC52xx family
-mpc52xx-device-tree-bindings.txt
-	- MPC5200 Device Tree Bindings
 sound.txt
 	- info on sound support under Linux/PPC
 zImage_layout.txt
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 9104c10..2501604 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -178,38 +178,29 @@ RTC class framework, but can't be supported by the older driver.
 	setting the longer alarm time and enabling its IRQ using a single
 	request (using the same model as EFI firmware).
 
-    *	RTC_UIE_ON, RTC_UIE_OFF ... if the RTC offers IRQs, it probably
-	also offers update IRQs whenever the "seconds" counter changes.
-	If needed, the RTC framework can emulate this mechanism.
+    *	RTC_UIE_ON, RTC_UIE_OFF ... if the RTC offers IRQs, the RTC framework
+	will emulate this mechanism.
 
-    *	RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ ... another
-	feature often accessible with an IRQ line is a periodic IRQ, issued
-	at settable frequencies (usually 2^N Hz).
+    *	RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ ... these icotls
+	are emulated via a kernel hrtimer.
 
 In many cases, the RTC alarm can be a system wake event, used to force
 Linux out of a low power sleep state (or hibernation) back to a fully
 operational state.  For example, a system could enter a deep power saving
 state until it's time to execute some scheduled tasks.
 
-Note that many of these ioctls need not actually be implemented by your
-driver.  The common rtc-dev interface handles many of these nicely if your
-driver returns ENOIOCTLCMD.  Some common examples:
+Note that many of these ioctls are handled by the common rtc-dev interface.
+Some common examples:
 
     *	RTC_RD_TIME, RTC_SET_TIME: the read_time/set_time functions will be
 	called with appropriate values.
 
-    *	RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
-	set_alarm/read_alarm functions will be called.
+    *	RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: gets or sets
+	the alarm rtc_timer. May call the set_alarm driver function.
 
-    *	RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
-	to set the frequency while the framework will handle the read for you
-	since the frequency is stored in the irq_freq member of the rtc_device
-	structure.  Your driver needs to initialize the irq_freq member during
-	init.  Make sure you check the requested frequency is in range of your
-	hardware in the irq_set_freq function.  If it isn't, return -EINVAL.  If
-	you cannot actually change the frequency, do not define irq_set_freq.
+    *	RTC_IRQP_SET, RTC_IRQP_READ: These are emulated by the generic code.
 
-    *	RTC_PIE_ON, RTC_PIE_OFF: the irq_set_state function will be called.
+    *	RTC_PIE_ON, RTC_PIE_OFF: These are also emulated by the generic code.
 
 If all else fails, check out the rtc-test.c driver!
 
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index b64d10d..4d9ce73 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,26 @@
+Release Date    : Thu. Feb 24, 2011 17:00:00 PST 2010 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Adam Radford
+Current Version : 00.00.05.34-rc1
+Old Version     : 00.00.05.29-rc1
+    1. Fix some failure gotos from megasas_probe_one(), etc.
+    2. Add missing check_and_restore_queue_depth() call in
+       complete_cmd_fusion().
+    3. Enable MSI-X before calling megasas_init_fw().
+    4. Call tasklet_schedule() even if outbound_intr_status == 0 for MFI based
+       boards in MSI-X mode.
+    5. Fix megasas_probe_one() to clear PCI_MSIX_FLAGS_ENABLE in msi control
+       register in kdump kernel.
+    6. Fix megasas_get_cmd() to only print "Command pool empty" if
+       megasas_dbg_lvl is set.
+    7. Fix megasas_build_dcdb_fusion() to not filter by TYPE_DISK.
+    8. Fix megasas_build_dcdb_fusion() to use io_request->LUN[1] field.
+    9. Add MR_EVT_CFG_CLEARED to megasas_aen_polling().
+    10. Fix tasklet_init() in megasas_init_fw() to use instancet->tasklet.
+    11. Fix fault state handling in megasas_transition_to_ready().
+    12. Fix max_sectors setting for IEEE SGL's.
+    13. Fix iMR OCR support to work correctly.
+-------------------------------------------------------------------------------
 Release Date    : Tues.  Dec 14, 2010 17:00:00 PST 2010 -
 			(emaild-id:megaraidlinux@lsi.com)
 			Adam Radford
diff --git a/Documentation/scsi/hpsa.txt b/Documentation/scsi/hpsa.txt
index dca6583..891435a 100644
--- a/Documentation/scsi/hpsa.txt
+++ b/Documentation/scsi/hpsa.txt
@@ -28,6 +28,12 @@ boot parameter "hpsa_allow_any=1" is specified, however these are not tested
 nor supported by HP with this driver.  For older Smart Arrays, the cciss
 driver should still be used.
 
+The "hpsa_simple_mode=1" boot parameter may be used to prevent the driver from
+putting the controller into "performant" mode.  The difference is that with simple
+mode, each command completion requires an interrupt, while with "performant mode"
+(the default, and ordinarily better performing) it is possible to have multiple
+command completions indicated by a single interrupt.
+
 HPSA specific entries in /sys
 -----------------------------
 
@@ -39,6 +45,8 @@ HPSA specific entries in /sys
 
   /sys/class/scsi_host/host*/rescan
   /sys/class/scsi_host/host*/firmware_revision
+  /sys/class/scsi_host/host*/resettable
+  /sys/class/scsi_host/host*/transport_mode
 
   the host "rescan" attribute is a write only attribute.  Writing to this
   attribute will cause the driver to scan for new, changed, or removed devices
@@ -55,6 +63,21 @@ HPSA specific entries in /sys
 	root@host:/sys/class/scsi_host/host4# cat firmware_revision
 	7.14
 
+  The transport_mode indicates whether the controller is in "performant"
+  or "simple" mode.  This is controlled by the "hpsa_simple_mode" module
+  parameter.
+
+  The "resettable" read-only attribute indicates whether a particular
+  controller is able to honor the "reset_devices" kernel parameter.  If the
+  device is resettable, this file will contain a "1", otherwise, a "0".  This
+  parameter is used by kdump, for example, to reset the controller at driver
+  load time to eliminate any outstanding commands on the controller and get the
+  controller into a known state so that the kdump initiated i/o will work right
+  and not be disrupted in any way by stale commands or other stale state
+  remaining on the controller from the previous kernel.  This attribute enables
+  kexec tools to warn the user if they attempt to designate a device which is
+  unable to honor the reset_devices kernel parameter as a dump device.
+
   HPSA specific disk attributes:
   ------------------------------
 
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index df322c1..5f17d29 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -1343,7 +1343,7 @@ Members of interest:
                    underruns (overruns should be rare). If possible an LLD
                    should set 'resid' prior to invoking 'done'. The most
                    interesting case is data transfers from a SCSI target
-                   device device (i.e. READs) that underrun. 
+                   device (e.g. READs) that underrun.
     underflow    - LLD should place (DID_ERROR << 16) in 'result' if
                    actual number of bytes transferred is less than this
                    figure. Not many LLDs implement this check and some that
@@ -1351,6 +1351,18 @@ Members of interest:
                    report a DID_ERROR. Better for an LLD to implement
                    'resid'.
 
+It is recommended that a LLD set 'resid' on data transfers from a SCSI
+target device (e.g. READs). It is especially important that 'resid' is set
+when such data transfers have sense keys of MEDIUM ERROR and HARDWARE ERROR
+(and possibly RECOVERED ERROR). In these cases if a LLD is in doubt how much
+data has been received then the safest approach is to indicate no bytes have
+been received. For example: to indicate that no valid data has been received
+a LLD might use these helpers:
+    scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
+where 'SCpnt' is a pointer to a scsi_cmnd object. To indicate only three 512
+bytes blocks has been received 'resid' could be set like this:
+    scsi_set_resid(SCpnt, scsi_bufflen(SCpnt) - (3 * 512));
+
 The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h
 
 
diff --git a/Documentation/serial/n_gsm.txt b/Documentation/serial/n_gsm.txt
new file mode 100644
index 0000000..397f41a
--- /dev/null
+++ b/Documentation/serial/n_gsm.txt
@@ -0,0 +1,89 @@
+n_gsm.c GSM 0710 tty multiplexor HOWTO
+===================================================
+
+This line discipline implements the GSM 07.10 multiplexing protocol
+detailed in the following 3GPP document :
+http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
+
+This document give some hints on how to use this driver with GPRS and 3G
+modems connected to a physical serial port.
+
+How to use it
+-------------
+1- initialize the modem in 0710 mux mode (usually AT+CMUX= command) through
+its serial port. Depending on the modem used, you can pass more or less
+parameters to this command,
+2- switch the serial line to using the n_gsm line discipline by using
+TIOCSETD ioctl,
+3- configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl,
+
+Major parts of the initialization program :
+(a good starting point is util-linux-ng/sys-utils/ldattach.c)
+#include <linux/gsmmux.h>
+#define N_GSM0710	21	/* GSM 0710 Mux */
+#define DEFAULT_SPEED	B115200
+#define SERIAL_PORT	/dev/ttyS0
+
+	int ldisc = N_GSM0710;
+	struct gsm_config c;
+	struct termios configuration;
+
+	/* open the serial port connected to the modem */
+	fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
+
+	/* configure the serial port : speed, flow control ... */
+
+	/* send the AT commands to switch the modem to CMUX mode
+	   and check that it's succesful (should return OK) */
+	write(fd, "AT+CMUX=0\r", 10);
+
+	/* experience showed that some modems need some time before
+	   being able to answer to the first MUX packet so a delay
+	   may be needed here in some case */
+	sleep(3);
+
+	/* use n_gsm line discipline */
+	ioctl(fd, TIOCSETD, &ldisc);
+
+	/* get n_gsm configuration */
+	ioctl(fd, GSMIOC_GETCONF, &c);
+	/* we are initiator and need encoding 0 (basic) */
+	c.initiator = 1;
+	c.encapsulation = 0;
+	/* our modem defaults to a maximum size of 127 bytes */
+	c.mru = 127;
+	c.mtu = 127;
+	/* set the new configuration */
+	ioctl(fd, GSMIOC_SETCONF, &c);
+
+	/* and wait for ever to keep the line discipline enabled */
+	daemon(0,0);
+	pause();
+
+4- create the devices corresponding to the "virtual" serial ports (take care,
+each modem has its configuration and some DLC have dedicated functions,
+for example GPS), starting with minor 1 (DLC0 is reserved for the management
+of the mux)
+
+MAJOR=`cat /proc/devices |grep gsmtty | awk '{print $1}`
+for i in `seq 1 4`; do
+	mknod /dev/ttygsm$i c $MAJOR $i
+done
+
+5- use these devices as plain serial ports.
+for example, it's possible :
+- and to use gnokii to send / receive SMS on ttygsm1
+- to use ppp to establish a datalink on ttygsm2
+
+6- first close all virtual ports before closing the physical port.
+
+Additional Documentation
+------------------------
+More practical details on the protocol and how it's supported by industrial
+modems can be found in the following documents :
+http://www.telit.com/module/infopool/download.php?id=616
+http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf
+http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx
+http://wm.sim.com/sim/News/photo/2010721161442.pdf
+
+11-03-08 - Eric BĂŠnard - <eric@eukrea.com>
diff --git a/Documentation/spinlocks.txt b/Documentation/spinlocks.txt
index 178c831..2e3c64b 100644
--- a/Documentation/spinlocks.txt
+++ b/Documentation/spinlocks.txt
@@ -86,7 +86,7 @@ to change the variables it has to get an exclusive write lock.
 
 The routines look the same as above:
 
-   rwlock_t xxx_lock = RW_LOCK_UNLOCKED;
+   rwlock_t xxx_lock = __RW_LOCK_UNLOCKED(xxx_lock);
 
 	unsigned long flags;
 
@@ -196,25 +196,3 @@ appropriate:
 
 For static initialization, use DEFINE_SPINLOCK() / DEFINE_RWLOCK() or
 __SPIN_LOCK_UNLOCKED() / __RW_LOCK_UNLOCKED() as appropriate.
-
-SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated.  These interfere
-with lockdep state tracking.
-
-Most of the time, you can simply turn:
-	static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
-into:
-	static DEFINE_SPINLOCK(xxx_lock);
-
-Static structure member variables go from:
-
-	struct foo bar {
-		.lock	=	SPIN_LOCK_UNLOCKED;
-	};
-
-to:
-
-	struct foo bar {
-		.lock	=	__SPIN_LOCK_UNLOCKED(bar.lock);
-	};
-
-Declaration of static rw_locks undergo a similar transformation.
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 6268250..4af0614 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -88,20 +88,19 @@ you might want to raise the limit.
 
 file-max & file-nr:
 
-The kernel allocates file handles dynamically, but as yet it
-doesn't free them again.
-
 The value in file-max denotes the maximum number of file-
 handles that the Linux kernel will allocate. When you get lots
 of error messages about running out of file handles, you might
 want to increase this limit.
 
-Historically, the three values in file-nr denoted the number of
-allocated file handles, the number of allocated but unused file
-handles, and the maximum number of file handles. Linux 2.6 always
-reports 0 as the number of free file handles -- this is not an
-error, it just means that the number of allocated file handles
-exactly matches the number of used file handles.
+Historically,the kernel was able to allocate file handles
+dynamically, but not to free them again. The three values in
+file-nr denote the number of allocated file handles, the number
+of allocated but unused file handles, and the maximum number of
+file handles. Linux 2.6 always reports 0 as the number of free
+file handles -- this is not an error, it just means that the
+number of allocated file handles exactly matches the number of
+used file handles.
 
 Attempts to allocate more file descriptors than file-max are
 reported with printk, look for "VFS: file-max limit <number>
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 11d5ced..36f0075 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -367,7 +367,7 @@ the different loglevels.
 
 - console_loglevel: messages with a higher priority than
   this will be printed to the console
-- default_message_level: messages without an explicit priority
+- default_message_loglevel: messages without an explicit priority
   will be printed with this priority
 - minimum_console_loglevel: minimum (highest) value to which
   console_loglevel can be set
diff --git a/Documentation/trace/ftrace-design.txt b/Documentation/trace/ftrace-design.txt
index dc52bd4..79fcafc 100644
--- a/Documentation/trace/ftrace-design.txt
+++ b/Documentation/trace/ftrace-design.txt
@@ -247,6 +247,13 @@ You need very few things to get the syscalls tracing in an arch.
 - Support the TIF_SYSCALL_TRACEPOINT thread flags.
 - Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
   in the ptrace syscalls tracing path.
+- If the system call table on this arch is more complicated than a simple array
+  of addresses of the system calls, implement an arch_syscall_addr to return
+  the address of a given system call.
+- If the symbol names of the system calls do not match the function names on
+  this arch, define ARCH_HAS_SYSCALL_MATCH_SYM_NAME in asm/ftrace.h and
+  implement arch_syscall_match_sym_name with the appropriate logic to return
+  true if the function name corresponds with the symbol name.
 - Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
 
 
diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index 557c1ed..1ebc24c 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -80,11 +80,11 @@ of ftrace. Here is a list of some of the key files:
 	tracers listed here can be configured by
 	echoing their name into current_tracer.
 
-  tracing_enabled:
+  tracing_on:
 
-	This sets or displays whether the current_tracer
-	is activated and tracing or not. Echo 0 into this
-	file to disable the tracer or 1 to enable it.
+	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.
 
   trace:
 
@@ -202,10 +202,6 @@ Here is the list of current tracers that may be configured.
 	to draw a graph of function calls similar to C code
 	source.
 
-  "sched_switch"
-
-	Traces the context switches and wakeups between tasks.
-
   "irqsoff"
 
 	Traces the areas that disable interrupts and saves
@@ -273,39 +269,6 @@ 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 sched_switch tracer also includes tracing of task wakeups
-and context switches.
-
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:R   +  2916:115:S
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:R   +    10:115:S
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:R ==>    10:115:R
-        events/1-10    [01]  1453.070013:     10:115:S ==>  2916:115:R
-     kondemand/1-2916  [01]  1453.070013:   2916:115:S ==>     7:115:R
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:S ==>     0:140:R
-
-Wake ups are represented by a "+" and the context switches are
-shown as "==>".  The format is:
-
- Context switches:
-
-       Previous task              Next Task
-
-  <pid>:<prio>:<state>  ==>  <pid>:<prio>:<state>
-
- Wake ups:
-
-       Current task               Task waking up
-
-  <pid>:<prio>:<state>    +  <pid>:<prio>:<state>
-
-The prio is the internal kernel priority, which is the inverse
-of the priority that is usually displayed by user-space tools.
-Zero represents the highest priority (99). Prio 100 starts the
-"nice" priorities with 100 being equal to nice -20 and 139 being
-nice 19. The prio "140" is reserved for the idle task which is
-the lowest priority thread (pid 0).
-
-
 Latency trace format
 --------------------
 
@@ -491,78 +454,10 @@ x494] <- /root/a.out[+0x4a8] <- /lib/libc-2.7.so[+0x1e1a6]
                    latencies, as described in "Latency
                    trace format".
 
-sched_switch
-------------
-
-This tracer simply records schedule switches. Here is an example
-of how to use it.
-
- # echo sched_switch > current_tracer
- # echo 1 > tracing_enabled
- # sleep 1
- # echo 0 > tracing_enabled
- # cat trace
-
-# tracer: sched_switch
-#
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-            bash-3997  [01]   240.132281:   3997:120:R   +  4055:120:R
-            bash-3997  [01]   240.132284:   3997:120:R ==>  4055:120:R
-           sleep-4055  [01]   240.132371:   4055:120:S ==>  3997:120:R
-            bash-3997  [01]   240.132454:   3997:120:R   +  4055:120:S
-            bash-3997  [01]   240.132457:   3997:120:R ==>  4055:120:R
-           sleep-4055  [01]   240.132460:   4055:120:D ==>  3997:120:R
-            bash-3997  [01]   240.132463:   3997:120:R   +  4055:120:D
-            bash-3997  [01]   240.132465:   3997:120:R ==>  4055:120:R
-          <idle>-0     [00]   240.132589:      0:140:R   +     4:115:S
-          <idle>-0     [00]   240.132591:      0:140:R ==>     4:115:R
-     ksoftirqd/0-4     [00]   240.132595:      4:115:S ==>     0:140:R
-          <idle>-0     [00]   240.132598:      0:140:R   +     4:115:S
-          <idle>-0     [00]   240.132599:      0:140:R ==>     4:115:R
-     ksoftirqd/0-4     [00]   240.132603:      4:115:S ==>     0:140:R
-           sleep-4055  [01]   240.133058:   4055:120:S ==>  3997:120:R
- [...]
-
-
-As we have discussed previously about this format, the header
-shows the name of the trace and points to the options. The
-"FUNCTION" is a misnomer since here it represents the wake ups
-and context switches.
-
-The sched_switch file only lists the wake ups (represented with
-'+') and context switches ('==>') with the previous task or
-current task first followed by the next task or task waking up.
-The format for both of these is PID:KERNEL-PRIO:TASK-STATE.
-Remember that the KERNEL-PRIO is the inverse of the actual
-priority with zero (0) being the highest priority and the nice
-values starting at 100 (nice -20). Below is a quick chart to map
-the kernel priority to user land priorities.
-
-   Kernel Space                     User Space
- ===============================================================
-   0(high) to  98(low)     user RT priority 99(high) to 1(low)
-                           with SCHED_RR or SCHED_FIFO
- ---------------------------------------------------------------
-  99                       sched_priority is not used in scheduling
-                           decisions(it must be specified as 0)
- ---------------------------------------------------------------
- 100(high) to 139(low)     user nice -20(high) to 19(low)
- ---------------------------------------------------------------
- 140                       idle task priority
- ---------------------------------------------------------------
-
-The task states are:
-
- R - running : wants to run, may not actually be running
- S - sleep   : process is waiting to be woken up (handles signals)
- D - disk sleep (uninterruptible sleep) : process must be woken up
-					(ignores signals)
- T - stopped : process suspended
- t - traced  : process is being traced (with something like gdb)
- Z - zombie  : process waiting to be cleaned up
- X - unknown
-
+  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.
 
 ftrace_enabled
 --------------
@@ -607,10 +502,10 @@ an example:
  # echo irqsoff > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # ls -ltr
  [...]
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: irqsoff
 #
@@ -715,10 +610,10 @@ is much like the irqsoff tracer.
  # echo preemptoff > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # ls -ltr
  [...]
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: preemptoff
 #
@@ -863,10 +758,10 @@ tracers.
  # echo preemptirqsoff > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # ls -ltr
  [...]
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: preemptirqsoff
 #
@@ -1026,9 +921,9 @@ Instead of performing an 'ls', we will run 'sleep 1' under
  # echo wakeup > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # chrt -f 5 sleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: wakeup
 #
@@ -1140,9 +1035,9 @@ ftrace_enabled is set; otherwise this tracer is a nop.
 
  # sysctl kernel.ftrace_enabled=1
  # echo function > current_tracer
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # usleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: function
 #
@@ -1180,7 +1075,7 @@ int trace_fd;
 [...]
 int main(int argc, char *argv[]) {
 	[...]
-	trace_fd = open(tracing_file("tracing_enabled"), O_WRONLY);
+	trace_fd = open(tracing_file("tracing_on"), O_WRONLY);
 	[...]
 	if (condition_hit()) {
 		write(trace_fd, "0", 1);
@@ -1631,9 +1526,9 @@ If I am only interested in sys_nanosleep and hrtimer_interrupt:
  # echo sys_nanosleep hrtimer_interrupt \
 		> set_ftrace_filter
  # echo function > current_tracer
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # usleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: ftrace
 #
@@ -1879,9 +1774,9 @@ different. The trace is live.
  # echo function > current_tracer
  # cat trace_pipe > /tmp/trace.out &
 [1] 4153
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # usleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: function
 #
diff --git a/Documentation/trace/kprobetrace.txt b/Documentation/trace/kprobetrace.txt
index 5f77d94..6d27ab8 100644
--- a/Documentation/trace/kprobetrace.txt
+++ b/Documentation/trace/kprobetrace.txt
@@ -42,11 +42,25 @@ Synopsis of kprobe_events
   +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
   NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
   FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
-		  (u8/u16/u32/u64/s8/s16/s32/s64) and string are supported.
+		  (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield
+		  are supported.
 
   (*) only for return probe.
   (**) this is useful for fetching a field of data structures.
 
+Types
+-----
+Several types are supported for fetch-args. Kprobe tracer will access memory
+by given type. Prefix 's' and 'u' means those types are signed and unsigned
+respectively. Traced arguments are shown in decimal (signed) or hex (unsigned).
+String type is a special type, which fetches a "null-terminated" string from
+kernel space. This means it will fail and store NULL if the string container
+has been paged out.
+Bitfield is another special type, which takes 3 parameters, bit-width, bit-
+offset, and container-size (usually 32). The syntax is;
+
+ b<bit-width>@<bit-offset>/<container-size>
+
 
 Per-Probe Event Filtering
 -------------------------
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 66f92d1..a4efa04 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -12,6 +12,10 @@ Controller Drivers (HCD). So, if HCD is buggy, the traces reported by
 usbmon may not correspond to bus transactions precisely. This is the same
 situation as with tcpdump.
 
+Two APIs are currently implemented: "text" and "binary". The binary API
+is available through a character device in /dev namespace and is an ABI.
+The text API is deprecated since 2.6.35, but available for convenience.
+
 * How to use usbmon to collect raw text traces
 
 Unlike the packet socket, usbmon has an interface which provides traces
@@ -162,39 +166,11 @@ Here is the list of words, from left to right:
   not machine words, but really just a byte stream split into words to make
   it easier to read. Thus, the last word may contain from one to four bytes.
   The length of collected data is limited and can be less than the data length
-  report in Data Length word.
-
-Here is an example of code to read the data stream in a well known programming
-language:
-
-class ParsedLine {
-	int data_len;		/* Available length of data */
-	byte data[];
-
-	void parseData(StringTokenizer st) {
-		int availwords = st.countTokens();
-		data = new byte[availwords * 4];
-		data_len = 0;
-		while (st.hasMoreTokens()) {
-			String data_str = st.nextToken();
-			int len = data_str.length() / 2;
-			int i;
-			int b;	// byte is signed, apparently?! XXX
-			for (i = 0; i < len; i++) {
-				// data[data_len] = Byte.parseByte(
-				//     data_str.substring(i*2, i*2 + 2),
-				//     16);
-				b = Integer.parseInt(
-				     data_str.substring(i*2, i*2 + 2),
-				     16);
-				if (b >= 128)
-					b *= -1;
-				data[data_len] = (byte) b;
-				data_len++;
-			}
-		}
-	}
-}
+  reported in the Data Length word. In the case of an Isochronous input (Zi)
+  completion where the received data is sparse in the buffer, the length of
+  the collected data can be greater than the Data Length value (because Data
+  Length counts only the bytes that were received whereas the Data words
+  contain the entire transfer buffer).
 
 Examples:
 
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index 699b60e..c40e3ba 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -130,7 +130,7 @@ Card number: 4
 
 Note: No module for the mse3000 is available yet
 Note: No module for the vpx3224 is available yet
-Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h)
+Note: use encoder=X or decoder=X for non-default i2c chips
 
 ===========================
 
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c
index cc96ee2..7445caa 100644
--- a/Documentation/vm/page-types.c
+++ b/Documentation/vm/page-types.c
@@ -32,8 +32,20 @@
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <sys/fcntl.h>
+#include <sys/mount.h>
+#include <sys/statfs.h>
+#include "../../include/linux/magic.h"
 
 
+#ifndef MAX_PATH
+# define MAX_PATH 256
+#endif
+
+#ifndef STR
+# define _STR(x) #x
+# define STR(x) _STR(x)
+#endif
+
 /*
  * pagemap kernel ABI bits
  */
@@ -152,6 +164,12 @@ static const char *page_flag_names[] = {
 };
 
 
+static const char *debugfs_known_mountpoints[] = {
+	"/sys/kernel/debug",
+	"/debug",
+	0,
+};
+
 /*
  * data structures
  */
@@ -184,7 +202,7 @@ static int		kpageflags_fd;
 static int		opt_hwpoison;
 static int		opt_unpoison;
 
-static const char	hwpoison_debug_fs[] = "/debug/hwpoison";
+static char		hwpoison_debug_fs[MAX_PATH+1];
 static int		hwpoison_inject_fd;
 static int		hwpoison_forget_fd;
 
@@ -464,21 +482,100 @@ static uint64_t kpageflags_flags(uint64_t flags)
 	return flags;
 }
 
+/* verify that a mountpoint is actually a debugfs instance */
+static int debugfs_valid_mountpoint(const char *debugfs)
+{
+	struct statfs st_fs;
+
+	if (statfs(debugfs, &st_fs) < 0)
+		return -ENOENT;
+	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+		return -ENOENT;
+
+	return 0;
+}
+
+/* find the path to the mounted debugfs */
+static const char *debugfs_find_mountpoint(void)
+{
+	const char **ptr;
+	char type[100];
+	FILE *fp;
+
+	ptr = debugfs_known_mountpoints;
+	while (*ptr) {
+		if (debugfs_valid_mountpoint(*ptr) == 0) {
+			strcpy(hwpoison_debug_fs, *ptr);
+			return hwpoison_debug_fs;
+		}
+		ptr++;
+	}
+
+	/* give up and parse /proc/mounts */
+	fp = fopen("/proc/mounts", "r");
+	if (fp == NULL)
+		perror("Can't open /proc/mounts for read");
+
+	while (fscanf(fp, "%*s %"
+		      STR(MAX_PATH)
+		      "s %99s %*s %*d %*d\n",
+		      hwpoison_debug_fs, type) == 2) {
+		if (strcmp(type, "debugfs") == 0)
+			break;
+	}
+	fclose(fp);
+
+	if (strcmp(type, "debugfs") != 0)
+		return NULL;
+
+	return hwpoison_debug_fs;
+}
+
+/* mount the debugfs somewhere if it's not mounted */
+
+static void debugfs_mount(void)
+{
+	const char **ptr;
+
+	/* see if it's already mounted */
+	if (debugfs_find_mountpoint())
+		return;
+
+	ptr = debugfs_known_mountpoints;
+	while (*ptr) {
+		if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) {
+			/* save the mountpoint */
+			strcpy(hwpoison_debug_fs, *ptr);
+			break;
+		}
+		ptr++;
+	}
+
+	if (*ptr == NULL) {
+		perror("mount debugfs");
+		exit(EXIT_FAILURE);
+	}
+}
+
 /*
  * page actions
  */
 
 static void prepare_hwpoison_fd(void)
 {
-	char buf[100];
+	char buf[MAX_PATH + 1];
+
+	debugfs_mount();
 
 	if (opt_hwpoison && !hwpoison_inject_fd) {
-		sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs);
+		snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn",
+			hwpoison_debug_fs);
 		hwpoison_inject_fd = checked_open(buf, O_WRONLY);
 	}
 
 	if (opt_unpoison && !hwpoison_forget_fd) {
-		sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs);
+		snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn",
+			hwpoison_debug_fs);
 		hwpoison_forget_fd = checked_open(buf, O_WRONLY);
 	}
 }
diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt
index 2d70d0d..97bae3c 100644
--- a/Documentation/vm/unevictable-lru.txt
+++ b/Documentation/vm/unevictable-lru.txt
@@ -84,8 +84,7 @@ indicate that the page is being managed on the unevictable list.
 
 The PG_unevictable flag is analogous to, and mutually exclusive with, the
 PG_active flag in that it indicates on which LRU list a page resides when
-PG_lru is set.  The unevictable list is compile-time configurable based on the
-UNEVICTABLE_LRU Kconfig option.
+PG_lru is set.
 
 The Unevictable LRU infrastructure maintains unevictable pages on an additional
 LRU list for a few reasons:
diff --git a/Documentation/x86/x86_64/boot-options.txt b/Documentation/x86/x86_64/boot-options.txt
index 7fbbaf8..092e596 100644
--- a/Documentation/x86/x86_64/boot-options.txt
+++ b/Documentation/x86/x86_64/boot-options.txt
@@ -189,13 +189,13 @@ ACPI
 
 PCI
 
-  pci=off	Don't use PCI
-  pci=conf1	Use conf1 access.
-  pci=conf2	Use conf2 access.
-  pci=rom	Assign ROMs.
-  pci=assign-busses    Assign busses
-  pci=irqmask=MASK	       Set PCI interrupt mask to MASK
-  pci=lastbus=NUMBER	       Scan upto NUMBER busses, no matter what the mptable says.
+  pci=off		Don't use PCI
+  pci=conf1		Use conf1 access.
+  pci=conf2		Use conf2 access.
+  pci=rom		Assign ROMs.
+  pci=assign-busses	Assign busses
+  pci=irqmask=MASK	Set PCI interrupt mask to MASK
+  pci=lastbus=NUMBER	Scan up to NUMBER busses, no matter what the mptable says.
   pci=noacpi		Don't use ACPI to set up PCI interrupt routing.
 
 IOMMU (input/output memory management unit)
@@ -293,11 +293,6 @@ IOMMU (input/output memory management unit)
 
 Debugging
 
-  oops=panic	Always panic on oopses. Default is to just kill the process,
-		but there is a small probability of deadlocking the machine.
-		This will also cause panics on machine check exceptions.
-		Useful together with panic=30 to trigger a reboot.
-
   kstack=N	Print N words from the kernel stack in oops dumps.
 
   pagefaulttrace  Dump all page faults. Only useful for extreme debugging
diff --git a/Documentation/zh_CN/SecurityBugs b/Documentation/zh_CN/SecurityBugs
new file mode 100644
index 0000000..d21eb07
--- /dev/null
+++ b/Documentation/zh_CN/SecurityBugs
@@ -0,0 +1,50 @@
+Chinese translated version of Documentation/SecurityBugs
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/SecurityBugs çä¸­ćçżťčŻ
+
+ĺŚććłčŻčŽşćć´ć°ćŹćçĺĺŽšďźčŻˇç´ćĽčçłťĺććĄŁççť´ć¤čăĺŚćä˝ ä˝żç¨čąć
+äş¤ćľćĺ°éžçčŻďźäšĺŻäťĽĺä¸­ćççť´ć¤čćąĺŠăĺŚććŹçżťčŻć´ć°ä¸ĺćśćčçżť
+čŻĺ­ĺ¨éŽé˘ďźčŻˇčçłťä¸­ćççť´ć¤čă
+
+ä¸­ćççť´ć¤čďź č´žĺ¨ĺ¨ Harry Wei <harryxiyou@gmail.com>
+ä¸­ćççżťčŻčďź č´žĺ¨ĺ¨ Harry Wei <harryxiyou@gmail.com>
+ä¸­ćçć ĄčŻčďź č´žĺ¨ĺ¨ Harry Wei <harryxiyou@gmail.com>
+
+
+äťĽä¸ä¸şć­Łć
+---------------------------------------------------------------------
+Linuxĺć ¸ĺźĺččŽ¤ä¸şĺŽĺ¨éĺ¸¸éčŚăĺ ć­¤ďźćäťŹćłčŚçĽéĺ˝ä¸ä¸Şćĺłäş
+ĺŽĺ¨çćźć´č˘Ťĺç°çćśĺďźĺšśä¸ĺŽĺŻč˝äźč˘Ťĺ°˝ĺżŤçäżŽĺ¤ćčĺŹĺźăčŻˇćčżä¸ŞĺŽĺ¨
+ćźć´ćĽĺçťLinuxĺć ¸ĺŽĺ¨ĺ˘éă
+
+1) čçłť
+
+linuxĺć ¸ĺŽĺ¨ĺ˘éĺŻäťĽéčżemail<security@kernel.org>ćĽčçłťăčżćŻ
+ä¸çťçŹçŤçĺŽĺ¨ĺˇĽä˝äşşĺďźĺŻäťĽĺ¸ŽĺŠćšĺćźć´ćĽĺĺšśä¸ĺŹĺ¸ĺĺćśä¸ä¸ŞäżŽĺ¤ăĺŽ
+ĺ¨ĺ˘éćĺŻč˝äźäťé¨ĺççť´ć¤čéŁéĺźčżé˘ĺ¤çĺ¸ŽĺŠćĽäşč§Łĺšśä¸äżŽĺ¤ĺŽĺ¨ćźć´ă
+ĺ˝éĺ°äťťä˝ćźć´ďźćč˝ćäžçäżĄćŻčśĺ¤ĺ°ąčśč˝čŻć­ĺäżŽĺ¤ăĺŚćä˝ ä¸ć¸ćĽäťäš
+ćŻćĺ¸ŽĺŠçäżĄćŻďźéŁĺ°ąčŻˇéć¸Šä¸ä¸REPORTING-BUGSćäťśä¸­çćŚčż°čżç¨ăäťť
+ä˝ćťĺťć§çäťŁç é˝ćŻéĺ¸¸ćç¨çďźćŞçťćĽĺčçĺćä¸äźč˘Ťĺćśďźé¤éĺŽĺˇ˛çť
+č˘ŤĺŹĺ¸äşäźă
+
+2) ĺŹĺź
+
+Linuxĺć ¸ĺŽĺ¨ĺ˘éçĺŽć¨ĺ°ąćŻĺćźć´ćäş¤čä¸čľˇĺ¤çćźć´çč§ŁĺłćšćĄç´
+ĺ°ĺŹĺźăćäťŹĺćŹ˘ĺ°˝ĺżŤĺ°ĺŽĺ¨ĺŹĺźćźć´ăĺ˝ä¸ä¸Şćźć´ćčäżŽĺ¤čżć˛Ąćč˘ŤĺŽĺ¨ĺ°ç
+č§Łďźč§ŁĺłćšćĄć˛ĄćéčżćľčŻćčäžĺşĺĺč°ďźĺŻäťĽĺçĺ°ĺťśčżĺŹĺźăçśčďźćäťŹ
+ććčżäşĺťśčżĺ°˝ĺŻč˝çç­äşďźćŻĺŻć°çĺ ĺ¤Šďźčä¸ćŻĺ ä¸Şćććčĺ ä¸ŞćăĺŹĺź
+ćĽććŻéčżĺŽĺ¨ĺ˘éĺćźć´ćäžčäťĽĺäžĺşĺć´˝č°ĺççťćăĺŹĺźćśé´čĄ¨ćŻäťĺž
+ç­ďźçšćŽçďźĺŽĺˇ˛çťč˘ŤĺŹäźćçĽéďźĺ°ĺ ä¸Şććăä˝ä¸şä¸ä¸ŞĺşćŹçéťčŽ¤ćżç­ďźć
+äťŹćććéçĽĺŹäźçćĽććŻ7ĺ¤ŠçĺŽćă
+
+3) äżĺŻĺčŽŽ
+
+Linuxĺć ¸ĺŽĺ¨ĺ˘éä¸ćŻä¸ä¸Şć­Łĺźçĺ˘ä˝ďźĺ ć­¤ä¸č˝ĺ ĺĽäťťä˝çäżĺŻĺčŽŽă
diff --git a/Documentation/zh_CN/SubmitChecklist b/Documentation/zh_CN/SubmitChecklist
new file mode 100644
index 0000000..951415b
--- /dev/null
+++ b/Documentation/zh_CN/SubmitChecklist
@@ -0,0 +1,109 @@
+Chinese translated version of Documentation/SubmitChecklist
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/SubmitChecklist ľÄÖĐÎÄˇ­Ňë
+
+ČçšűĎëĆŔÂŰťň¸üĐÂąžÎÄľÄÄÚČÝŁŹÇëÖą˝ÓÁŞĎľÔ­ÎÄľľľÄÎŹť¤ŐßĄŁČçšűÄăĘšÓĂÓ˘ÎÄ
+˝ťÁ÷ÓĐŔ§ÄŃľÄť°ŁŹŇ˛żÉŇÔĎňÖĐÎÄ°ćÎŹť¤ŐßÇóÖúĄŁČçšűąžˇ­Ňë¸üĐÂ˛ťź°ĘąťňŐßˇ­
+Ňë´ćÔÚÎĘĚâŁŹÇëÁŞĎľÖĐÎÄ°ćÎŹť¤ŐßĄŁ
+
+ÖĐÎÄ°ćÎŹť¤ŐßŁş źÖÍţÍţ Harry Wei <harryxiyou@gmail.com>
+ÖĐÎÄ°ćˇ­ŇëŐßŁş źÖÍţÍţ Harry Wei <harryxiyou@gmail.com>
+ÖĐÎÄ°ćĐŁŇëŐßŁş źÖÍţÍţ Harry Wei <harryxiyou@gmail.com>
+
+
+ŇÔĎÂÎŞŐýÎÄ
+---------------------------------------------------------------------
+LinuxÄÚşËĚá˝ťÇĺľĽ
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ŐâŔďÓĐŇťĐŠÄÚşËżŞˇ˘ŐßÓŚ¸Ă×öľÄťůąžĘÂÇéŁŹČçšűËűĂÇĎëż´ľ˝×ÔźşľÄÄÚşË˛šśĄĚá˝ť
+ąť˝ÓĘÜľÄ¸üżěĄŁ
+
+ŐâĐŠśźĘÇłŹłöDocumentation/SubmittingPatchesÎÄľľŔďËůĚášŠľÄŇÔź°ĆäËű
+šŘÓÚĚá˝ťLinuxÄÚşË˛šśĄľÄËľĂ÷ĄŁ
+
+1ŁşČçšűÄăĘšÓĂÁËŇť¸öšŚÄÜÄÇĂ´žÍ#includeś¨Ňĺ/ÉůĂ÷ÄÇ¸öšŚÄÜľÄÄÇ¸öÎÄźţĄŁ
+   ˛ťŇŞŇŔżżĆäËűźä˝ÓŇýČëś¨Ňĺ/ÉůĂ÷ÄÇ¸öšŚÄÜľÄÍˇÎÄźţĄŁ
+
+2Łşšš˝¨źň˝ŕĘĘÓĂťňŐß¸ü¸ÄCONFIGŃĄĎî =yŁŹ=mŁŹťňŐß=nĄŁ
+   ˛ťŇŞÓĐąŕŇëžŻ¸ć/´íÎóŁŹ ˛ťŇŞÓĐÁ´˝ÓžŻ¸ć/´íÎóĄŁ
+
+2bŁşÍ¨šý allnoconfig, allmodconfig
+
+2cŁşľąĘšÓĂ 0=builddir łÉšŚľŘšš˝¨
+
+3ŁşÍ¨šýĘšÓĂąžľŘ˝ť˛ćąŕŇëš¤žßťňŐßĆäËűŇťĐŠšš˝¨˛úËůŁŹÔÚśŕCPUżňźÜÉĎšš˝¨ĄŁ
+
+4Łşppc64 ĘÇŇť¸öşÜşĂľÄźě˛é˝ť˛ćąŕŇëľÄżňźÜŁŹŇňÎŞËüÍůÍů°ŃĄŽunsigned longĄŻ
+   ľą64ÎťÖľŔ´ĘšÓĂĄŁ
+
+5Łş°´ŐŐDocumentation/CodingStyleÎÄźţŔďľÄĎęĎ¸ĂčĘöŁŹźě˛éÄă˛šśĄľÄŐűĚĺˇç¸ńĄŁ
+   ĘšÓĂ˛šśĄˇç¸ńźě˛éËöËéľÄÎĽšć(scripts/checkpatch.pl)ŁŹÉóşËÔąÓĹĎČĚá˝ťĄŁ
+   ÄăÓŚ¸Ăľ÷ŐűŇĹÁôÔÚÄă˛šśĄÖĐľÄËůÓĐÎĽšćĄŁ
+
+6ŁşČÎşÎ¸üĐÂťňŐß¸ÄśŻCONFIGŃĄĎîśź˛ťÄÜ´ňÂŇĹäÖĂ˛ËľĽĄŁ
+
+7ŁşËůÓĐľÄKconfigŃĄĎî¸üĐÂśźŇŞÓĐËľĂ÷ÎÄ×ÖĄŁ
+
+8ŁşŇŃž­ČĎŐćľŘ×Ü˝áÁËĎŕšŘľÄKconfig×éşĎĄŁŐâĘÇşÜÄŃÍ¨šý˛âĘÔ×öşĂľÄ--ÄÔÁŚÔÚŐâŔďĎÂ˝ľĄŁ
+
+9Łşźě˛éžßÓĐźň˝ŕĐÔĄŁ
+
+10ŁşĘšÓĂ'make checkstack'şÍ'make namespacecheck'źě˛éŁŹČťşóĐŢ¸ÄËůŐŇľ˝ľÄÎĘĚâĄŁ
+    ×˘ŇâŁşśŃŐťźě˛é˛ťťáĂ÷ČˇľŘłöĎÖÎĘĚâŁŹľŤĘÇČÎşÎľÄŇť¸öşŻĘýÔÚśŃŐťÉĎĘšÓĂśŕÓÚ512×Ö˝Ú
+    śźŇŞ×źą¸ĐŢ¸ÄĄŁ
+
+11Łş°üşŹkernel-docľ˝ČŤžÖÄÚşËAPIsÎÄźţĄŁŁ¨˛ťŇŞÇóž˛ĚŹľÄşŻĘýŁŹľŤĘÇ°üşŹŇ˛ÎŢËůÎ˝ĄŁŁŠ
+    ĘšÓĂ'make htmldocs'ťňŐß'make mandocs'Ŕ´źě˛ékernel-docŁŹČťşóĐŢ¸ÄČÎşÎ
+    ˇ˘ĎÖľÄÎĘĚâĄŁ
+
+12ŁşŇŃž­Í¨šýCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
+    CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
+    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP˛âĘÔŁŹ˛˘ÇŇÍŹĘąśź
+    ĘšÄÜĄŁ
+
+13ŁşŇŃž­śźšš˝¨˛˘ÇŇĘšÓĂťňŐß˛ťĘšÓĂ CONFIG_SMP şÍ CONFIG_PREEMPT˛âĘÔÖ´ĐĐĘąźäĄŁ
+
+14ŁşČçšű˛šśĄÓ°ĎěIO/DiskŁŹľČľČŁşŇŃž­Í¨šýĘšÓĂťňŐß˛ťĘšÓĂ CONFIG_LBDAF ˛âĘÔĄŁ
+
+15ŁşËůÓĐľÄcodepathsŇŃž­ĐĐĘšËůÓĐlockdepĆôÓĂšŚÄÜĄŁ
+
+16ŁşËůÓĐľÄ/procźÇÂź¸üĐÂśźŇŞ×÷łÉÎÄźţˇĹÔÚDocumentation/ÄżÂźĎÂĄŁ
+
+17ŁşËůÓĐľÄÄÚşËĆôśŻ˛ÎĘý¸üĐÂśźąťźÇÂźľ˝Documentation/kernel-parameters.txtÎÄźţÖĐĄŁ
+
+18ŁşËůÓĐľÄÄŁżé˛ÎĘý¸üĐÂśźÓĂMODULE_PARM_DESC()źÇÂźĄŁ
+
+19ŁşËůÓĐľÄÓĂť§żŐźä˝ÓżÚ¸üĐÂśźąťźÇÂźľ˝Documentation/ABI/ĄŁ˛éż´Documentation/ABI/README
+    żÉŇÔťńľĂ¸üśŕľÄĐĹĎ˘ĄŁ¸ÄąäÓĂť§żŐźä˝ÓżÚľÄ˛šśĄÓŚ¸ĂąťÓĘźţł­ËÍ¸řlinux-api@vger.kernel.orgĄŁ
+
+20Łşźě˛éËüĘÇ˛ťĘÇśźÍ¨šý`make headers_check'ĄŁ
+
+21ŁşŇŃž­Í¨šýÖÁÉŮŇýČëslabşÍpage-allocationĘ§°Üźě˛éĄŁ˛éż´Documentation/fault-injection/ĄŁ
+
+22ŁşĐÂźÓČëľÄÔ´ÂëŇŃž­Í¨šý`gcc -W'Ł¨ĘšÓĂ"make EXTRA_CFLAGS=-W"ŁŠąŕŇëĄŁŐâŃů˝Ť˛úÉúşÜśŕˇłÄŐŁŹ
+    ľŤĘÇśÔÓÚŃ°ŐŇÂŠś´şÜÓĐŇć´ŚŁŹŔýČç:"warning: comparison between signed and unsigned"ĄŁ
+
+23ŁşľąËüąťşĎ˛˘ľ˝-mm˛šśĄźŻşóÔŮ˛âĘÔŁŹÓĂŔ´Čˇś¨ËüĘÇˇńťšşÍ˛šśĄśÓÁĐÖĐľÄĆäËű˛šśĄŇťĆđš¤×÷ŇÔź°ÔÚVMŁŹVFS
+    şÍĆäËű×ÓĎľÍłÖĐ¸÷¸öąäťŻĄŁ
+
+24ŁşËůÓĐľÄÄÚ´ćĆÁŐĎ{e.g., barrier(), rmb(), wmb()}ĐčŇŞÔÚÔ´´úÂëÖĐľÄŇť¸ö×˘ĘÍŔ´˝âĘÍËűĂÇśźĘÇ¸ÉĘ˛Ă´ľÄ
+    ŇÔź°Ô­ŇňĄŁ
+
+25ŁşČçšűÓĐČÎşÎĘäČëĘäłöżŘÖĆľÄ˛šśĄąťĚíźÓŁŹŇ˛ŇŞ¸üĐÂDocumentation/ioctl/ioctl-number.txtĄŁ
+
+26ŁşČçšűÄăľÄ¸ü¸Ä´úÂëŇŔżżťňŐßĘšÓĂČÎşÎľÄÄÚşËAPIsťňŐßÓëĎÂĂćľÄkconfigˇűşĹÓĐšŘĎľľÄšŚÄÜŁŹÄăžÍŇŞ
+    ĘšÓĂĎŕšŘľÄkconfigˇűşĹšŘąŐŁŹ and/or =mŁ¨ČçšűŃĄĎîĚášŠŁŠ[ÔÚÍŹŇťĘąźä˛ťĘÇËůÓĂľÄśźĆôÓĂŁŹ˝ö˝ö¸÷¸öťňŐß×ÔÓÉ
+    ×éşĎËűĂÇ]Łş
+
+    CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI,
+    CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ,
+    CONFIG_NET, CONFIG_INET=n (şóŇť¸öĘšÓĂ CONFIG_NET=y)
diff --git a/Documentation/zh_CN/SubmittingPatches b/Documentation/zh_CN/SubmittingPatches
index 9a1a6e1..0f4385a 100644
--- a/Documentation/zh_CN/SubmittingPatches
+++ b/Documentation/zh_CN/SubmittingPatches
@@ -100,7 +100,7 @@ http://userweb.kernel.org/~akpm/stuff/patch-scripts.tar.gz
 
 ĺ°ćšĺ¨ćĺďźéťčžçąťäźźçćžĺ°ĺä¸ä¸ŞčĄĽä¸ćäťśéă
 
-äžĺŚďźĺŚćä˝ çćšĺ¨éĺćśćbugäżŽć­Łĺć§č˝äźĺďźéŁäšćčżäşćšĺ¨ćĺĺ°ä¸¤ä¸Şć
+äžĺŚďźĺŚćä˝ çćšĺ¨éĺćśćbugäżŽć­Łĺć§č˝äźĺďźéŁäšćčżäşćšĺ¨ćĺĺ°ä¸¤ä¸Şć
 čć´ĺ¤çčĄĽä¸ćäťśä¸­ăĺŚćä˝ çćšĺ¨ĺĺŤĺŻšAPIçäżŽćšďźĺšśä¸äżŽćšäşéŠąĺ¨ç¨ĺşćĽé
 ĺşčżäşć°çAPIďźéŁäšćčżäşäżŽćšĺćä¸¤ä¸ŞčĄĽä¸ă
 
@@ -230,7 +230,7 @@ pref("mailnews.display.disable_format_flowed_support", true);
 äşĺĺ ďźäżŽć­ŁéčŻŻďźéć°ćäş¤ć´ć°ĺçćšĺ¨ďźćŻä˝ čŞĺˇąçĺˇĽä˝ă
 
 Linusä¸çťĺşäťťä˝čŻčŽşĺ°ąâä¸˘ĺźâä˝ çčĄĽä¸ćŻĺ¸¸č§çäşćăĺ¨çłťçťä¸­čżć ˇçäşćĺž
-ĺšłĺ¸¸ăĺŚćäťć˛ĄććĽĺä˝ çčĄĽä¸ďźäščŽ¸ćŻçąäşäťĽä¸ĺćŹďź
+ĺšłĺ¸¸ăĺŚćäťć˛ĄććĽĺä˝ çčĄĽä¸ďźäščŽ¸ćŻçąäşäťĽä¸ĺĺ ďź
 * ä˝ çčĄĽä¸ä¸č˝ĺ¨ćć°çćŹçĺć ¸ä¸ĺš˛ĺçćä¸ă
 * ä˝ çčĄĽä¸ĺ¨ linux-kernel éŽäťśĺčĄ¨ä¸­ć˛Ąćĺžĺ°ĺĺçčŽ¨čŽşă
 * éŁć źéŽé˘ďźĺç§çŹŹ2ĺ°čďź
diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt
new file mode 100644
index 0000000..4c4ce85
--- /dev/null
+++ b/Documentation/zh_CN/magic-number.txt
@@ -0,0 +1,167 @@
+Chinese translated version of Documentation/magic-number.txt
+
+If you have any comment or update to the content, please post to LKML directly.
+However, if you have problem communicating in English you can also ask the
+Chinese maintainer for help.  Contact the Chinese maintainer, if this
+translation is outdated or there is problem with translation.
+
+Chinese maintainer: Jia Wei Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/magic-number.txtçä¸­ćçżťčŻ
+
+ĺŚććłčŻčŽşćć´ć°ćŹćçĺĺŽšďźčŻˇç´ćĽĺäżĄĺ°LKMLăĺŚćä˝ ä˝żç¨čąćäş¤ćľćĺ°éžçčŻďźäšĺŻ
+äťĽĺä¸­ćççť´ć¤čćąĺŠăĺŚććŹçżťčŻć´ć°ä¸ĺćśćčçżťčŻĺ­ĺ¨éŽé˘ďźčŻˇčçłťä¸­ćççť´ć¤čă
+
+ä¸­ćççť´ć¤čďź č´žĺ¨ĺ¨ Jia Wei Wei <harryxiyou@gmail.com>
+ä¸­ćççżťčŻčďź č´žĺ¨ĺ¨ Jia Wei Wei <harryxiyou@gmail.com>
+ä¸­ćçć ĄčŻčďź č´žĺ¨ĺ¨ Jia Wei Wei <harryxiyou@gmail.com>
+
+äťĽä¸ä¸şć­Łć
+---------------------------------------------------------------------
+čżä¸ŞćäťśćŻćĺłĺ˝ĺä˝żç¨çé­ćŻĺźćł¨ĺčĄ¨ăĺ˝ä˝ çťä¸ä¸Şçťććˇťĺ äşä¸ä¸Şé­ćŻĺźďźä˝ äšĺşčŻĽćčżä¸Şé­ćŻĺźćˇťĺ ĺ°čżä¸Şćäťśďźĺ ä¸şćäťŹćĺĽ˝ćç¨äşĺç§çťćçé­ćŻĺźçťä¸čľˇćĽă
+
+ä˝żç¨é­ćŻĺźćĽäżć¤ĺć ¸ć°ćŽçťććŻä¸ä¸Şéĺ¸¸ĺĽ˝çä¸ťćăčżĺ°ąĺčŽ¸ä˝ ĺ¨čżčĄććŁćĽ(a)ä¸ä¸ŞçťććŻĺŚĺˇ˛çťč˘Ťćťĺťďźćč(b)ä˝ ĺˇ˛çťçťä¸ä¸ŞäžčĄç¨ĺşéčżäşä¸ä¸ŞéčŻŻççťćăĺä¸ç§ćĺľçšĺŤĺ°ćç¨---çšĺŤćŻĺ˝ä˝ éčżä¸ä¸ŞçŠşćéćĺçťćä˝çćśĺăttyćşç ďźäžĺŚďźçťĺ¸¸éčżçšĺŽéŠąĺ¨ä˝żç¨čżç§ćšćłĺšśä¸ĺĺ¤ĺ°ćĺçšĺŽćšé˘ççťćă
+
+ä˝żç¨é­ćŻĺźçćšćłćŻĺ¨çťćçĺźĺ§ĺ¤ĺŁ°ćçďźĺŚä¸ďź
+
+struct tty_ldisc {
+	int	magic;
+	...
+};
+
+ĺ˝ä˝ äťĽĺçťĺć ¸ćˇťĺ ĺ˘ĺźşĺč˝çćśĺďźčŻˇéľĺŽčżćĄč§ĺďźčżć ˇĺ°ąäźčçć°ä¸ć¸çč°čŻćśé´ďźçšĺŤćŻä¸äşĺ¤ćŞçćĺľďźäžĺŚďźć°çťčśĺşčĺ´ĺšśä¸éć°ĺäşčśĺşé¨ĺăéľĺŽčżä¸Şč§ĺďźâŞčżäşćĺľĺŻäťĽč˘ŤĺżŤéĺ°ďźĺŽĺ¨ĺ°éżĺă
+
+		Theodore Ts'o
+		  31 Mar 94
+
+çťĺ˝ĺçLinux 2.1.55ćˇťĺ é­ćŻčĄ¨ă
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+ç°ĺ¨ĺşčŻĽćć°çLinux 2.1.112.ĺ ä¸şĺ¨çšć§ĺťçťćé´ďźä¸č˝ĺ¨2.2.xĺćšĺäťťä˝ä¸čĽżăčżäşćĄçŽč˘Ťć°ĺććĺşă
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+ć´ć°é­ćŻčĄ¨ĺ°Linux 2.5.45ăĺĺĽ˝čśčżçšć§ĺťçťďźä˝ćŻćĺŻč˝čżäźćä¸äşć°çé­ćŻĺźĺ¨2.6.xäšĺčĺĽĺ°ĺć ¸ä¸­ă
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+ć´ć°é­ćŻčĄ¨ĺ°Linux 2.5.74ă
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+é­ćŻĺ                 ĺ°ĺ         çťć               ćĺ¨ćäťś
+===========================================================================
+PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
+CMAGIC                0x0111      user              include/linux/a.out.h
+MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
+RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
+SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
+HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
+APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
+CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
+DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
+DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
+FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
+FF_MAGIC              0x4646      fc_info           drivers/net/iph5526_novram.c
+ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
+PTY_MAGIC             0x5001                        drivers/char/pty.c
+PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
+SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
+SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
+SLIP_MAGIC            0x5302      slip              drivers/net/slip.h
+STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
+X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
+SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
+AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
+ESP_MAGIC             0x53ee      esp_struct        drivers/char/esp.h
+TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
+MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
+TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
+MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
+TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
+USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
+FULL_DUPLEX_MAGIC     0x6969                        drivers/net/tulip/de2104x.c
+USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
+RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
+USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
+CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
+A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
+RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
+LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
+GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
+RIO_MAGIC             0x12345678  gs_port           drivers/char/rio/rio_linux.c
+SX_MAGIC              0x12345678  gs_port           drivers/char/sx.h
+NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
+RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
+BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
+ISDN_X25IFACE_MAGIC   0x1e75a2b9  isdn_x25iface_proto_data
+                                                    drivers/isdn/isdn_x25iface.h
+ECP_MAGIC             0x21504345  cdkecpsig         include/linux/cdk.h
+LSOMAGIC              0x27091997  lso               drivers/fc4/fc.c
+LSMAGIC               0x2a3b4d2a  ls                drivers/fc4/fc.c
+WANPIPE_MAGIC         0x414C4453  sdla_{dump,exec}  include/linux/wanpipe.h
+CS_CARD_MAGIC         0x43525553  cs_card           sound/oss/cs46xx.c
+LABELCL_MAGIC         0x4857434c  labelcl_info_s    include/asm/ia64/sn/labelcl.h
+ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
+CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
+ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
+SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
+STLI_BOARDMAGIC       0x4bc6c825  stlibrd           include/linux/istallion.h
+CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
+SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
+COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
+I810_CARD_MAGIC       0x5072696E  i810_card         sound/oss/i810_audio.c
+TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
+ROUTER_MAGIC          0x524d4157  wan_device        include/linux/wanrouter.h
+SCC_MAGIC             0x52696368  gs_port           drivers/char/scc.h
+SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
+GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
+RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
+STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
+EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
+HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
+EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
+PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
+KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
+I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
+TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
+M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
+FW_HEADER_MAGIC       0x65726F66  fw_header         drivers/atm/fore200e.h
+SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
+SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
+LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
+OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
+M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
+STL_PANELMAGIC        0x7ef621a1  stlpanel          include/linux/stallion.h
+VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
+KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
+PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
+NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
+STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
+ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
+SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
+CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
+DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
+STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
+YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
+CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
+QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
+QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
+HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
+NMI_MAGIC             0x48414d4d455201 nmi_s        arch/mips/include/asm/sn/nmi.h
+
+čŻˇćł¨ćďźĺ¨ĺŁ°éłčŽ°ĺżçŽĄçä¸­äťçśććŻä¸äşč˘ŤĺŽäšçéŠąĺ¨é­ćŻĺźăćĽçinclude/sound/sndmagic.hćĽčˇĺäťäťŹĺŽć´çĺčĄ¨äżĄćŻăĺžĺ¤OSSĺŁ°éłéŠąĺ¨ćĽćčŞĺˇąäťĺŁ°ĺĄPCI IDćĺťşçé­ćŻĺź-äťäťŹäšć˛Ąćč˘Ťĺĺ¨čżéă
+
+IrDAĺ­çłťçťäšä˝żç¨äşĺ¤§éçčŞĺˇąçé­ćŻĺźďźćĽçinclude/net/irda/irda.hćĽčˇĺäťäťŹĺŽć´çäżĄćŻă
+
+HFSćŻĺŚĺ¤ä¸ä¸ŞćŻčžĺ¤§çä˝żç¨é­ćŻĺźçćäťśçłťçť-ä˝ ĺŻäťĽĺ¨fs/hfs/hfs.hä¸­ćžĺ°äťäťŹă
diff --git a/MAINTAINERS b/MAINTAINERS
index f1bc3dc..e11953d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -72,7 +72,7 @@ Descriptions of section entries:
 	L: Mailing list that is relevant to this area
 	W: Web-page with status/info
 	Q: Patchwork web based patch tracking system site
-	T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit.
+	T: SCM tree type and location.  Type is one of: git, hg, quilt, stgit, topgit.
 	S: Status, one of the following:
 	   Supported:	Someone is actually paid to look after this.
 	   Maintained:	Someone actually looks after it.
@@ -198,7 +198,7 @@ F:	Documentation/scsi/aacraid.txt
 F:	drivers/scsi/aacraid/
 
 ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
-M:	Hans de Goede <j.w.r.degoede@hhs.nl>
+M:	Hans de Goede <hdegoede@redhat.com>
 L:	lm-sensors@lm-sensors.org
 S:	Maintained
 F:	drivers/hwmon/abituguru.c
@@ -288,35 +288,35 @@ F:	sound/pci/ad1889.*
 AD525X ANALOG DEVICES DIGITAL POTENTIOMETERS DRIVER
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/AD5254
+W:	http://wiki.analog.com/AD5254
 S:	Supported
 F:	drivers/misc/ad525x_dpot.c
 
 AD5398 CURRENT REGULATOR DRIVER (AD5398/AD5821)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/AD5398
+W:	http://wiki.analog.com/AD5398
 S:	Supported
 F:	drivers/regulator/ad5398.c
 
 AD714X CAPACITANCE TOUCH SENSOR DRIVER (AD7142/3/7/8/7A)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/AD7142
+W:	http://wiki.analog.com/AD7142
 S:	Supported
 F:	drivers/input/misc/ad714x.c
 
 AD7877 TOUCHSCREEN DRIVER
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/AD7877
+W:	http://wiki.analog.com/AD7877
 S:	Supported
 F:	drivers/input/touchscreen/ad7877.c
 
 AD7879 TOUCHSCREEN DRIVER (AD7879/AD7889)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/AD7879
+W:	http://wiki.analog.com/AD7879
 S:	Supported
 F:	drivers/input/touchscreen/ad7879.c
 
@@ -342,18 +342,18 @@ F:	drivers/net/wireless/adm8211.*
 ADP5520 BACKLIGHT DRIVER WITH IO EXPANDER (ADP5520/ADP5501)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/ADP5520
+W:	http://wiki.analog.com/ADP5520
 S:	Supported
 F:	drivers/mfd/adp5520.c
 F:	drivers/video/backlight/adp5520_bl.c
-F:	drivers/led/leds-adp5520.c
+F:	drivers/leds/leds-adp5520.c
 F:	drivers/gpio/adp5520-gpio.c
 F:	drivers/input/keyboard/adp5520-keys.c
 
 ADP5588 QWERTY KEYPAD AND IO EXPANDER DRIVER (ADP5588/ADP5587)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/ADP5588
+W:	http://wiki.analog.com/ADP5588
 S:	Supported
 F:	drivers/input/keyboard/adp5588-keys.c
 F:	drivers/gpio/adp5588-gpio.c
@@ -361,10 +361,18 @@ F:	drivers/gpio/adp5588-gpio.c
 ADP8860 BACKLIGHT DRIVER (ADP8860/ADP8861/ADP8863)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/ADP8860
+W:	http://wiki.analog.com/ADP8860
 S:	Supported
 F:	drivers/video/backlight/adp8860_bl.c
 
+ADS1015 HARDWARE MONITOR DRIVER
+M:	Dirk Eibach <eibach@gdsys.de>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	Documentation/hwmon/ads1015
+F:	drivers/hwmon/ads1015.c
+F:	include/linux/i2c/ads1015.h
+
 ADT746X FAN DRIVER
 M:	Colin Leroy <colin@colino.net>
 S:	Maintained
@@ -380,7 +388,7 @@ F:	drivers/hwmon/adt7475.c
 ADXL34X THREE-AXIS DIGITAL ACCELEROMETER DRIVER (ADXL345/ADXL346)
 M:	Michael Hennerich <michael.hennerich@analog.com>
 L:	device-driver-devel@blackfin.uclinux.org
-W:	http://wiki-analog.com/ADXL345
+W:	http://wiki.analog.com/ADXL345
 S:	Supported
 F:	drivers/input/misc/adxl34x.c
 
@@ -465,6 +473,16 @@ M:	Matt Turner <mattst88@gmail.com>
 L:	linux-alpha@vger.kernel.org
 F:	arch/alpha/
 
+ALTERA UART/JTAG UART SERIAL DRIVERS
+M:	Tobias Klauser <tklauser@distanz.ch>
+L:	linux-serial@vger.kernel.org
+L:	nios2-dev@sopc.et.ntust.edu.tw (moderated for non-subscribers)
+S:	Maintained
+F:	drivers/tty/serial/altera_uart.c
+F:	drivers/tty/serial/altera_jtaguart.c
+F:	include/linux/altera_uart.h
+F:	include/linux/altera_jtaguart.h
+
 AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
 M:	Thomas Dahlmann <dahlmann.thomas@arcor.de>
 L:	linux-geode@lists.infradead.org (moderated for non-subscribers)
@@ -510,11 +528,9 @@ F:	drivers/infiniband/hw/amso1100/
 ANALOG DEVICES INC ASOC CODEC DRIVERS
 L:	device-driver-devel@blackfin.uclinux.org
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
-W:	http://wiki-analog.com/
+W:	http://wiki.analog.com/
 S:	Supported
 F:	sound/soc/codecs/ad1*
-F:	sound/soc/codecs/adau*
-F:	sound/soc/codecs/adav*
 F:	sound/soc/codecs/ssm*
 
 ANALOG DEVICES INC ASOC DRIVERS
@@ -557,6 +573,13 @@ S:	Maintained
 F:	drivers/net/appletalk/
 F:	net/appletalk/
 
+ARASAN COMPACT FLASH PATA CONTROLLER
+M:	Viresh Kumar <viresh.kumar@st.com>
+L:	linux-ide@vger.kernel.org
+S:	Maintained
+F:	include/linux/pata_arasan_cf_data.h
+F:	drivers/ata/pata_arasan_cf.c
+
 ARC FRAMEBUFFER DRIVER
 M:	Jaya Kumar <jayalk@intworks.biz>
 S:	Maintained
@@ -672,8 +695,8 @@ S:	Maintained
 ARM/CLKDEV SUPPORT
 M:	Russell King <linux@arm.linux.org.uk>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-F:	arch/arm/common/clkdev.c
 F:	arch/arm/include/asm/clkdev.h
+F:	drivers/clk/clkdev.c
 
 ARM/COMPULAB CM-X270/EM-X270 and CM-X300 MACHINE SUPPORT
 M:	Mike Rapoport <mike@compulab.co.il>
@@ -894,6 +917,7 @@ F:	drivers/mmc/host/msm_sdcc.c
 F:	drivers/mmc/host/msm_sdcc.h
 F:	drivers/tty/serial/msm_serial.h
 F:	drivers/tty/serial/msm_serial.c
+F:	drivers/platform/msm/
 T:	git git://codeaurora.org/quic/kernel/davidb/linux-msm.git
 S:	Maintained
 
@@ -1053,7 +1077,7 @@ L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 
 ARM/TETON BGA MACHINE SUPPORT
-M:	Mark F. Brown <mark.brown314@gmail.com>
+M:	"Mark F. Brown" <mark.brown314@gmail.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
 
@@ -1214,7 +1238,7 @@ ATHEROS AR9170 WIRELESS DRIVER
 M:	Christian Lamparter <chunkeey@web.de>
 L:	linux-wireless@vger.kernel.org
 W:	http://wireless.kernel.org/en/users/Drivers/ar9170
-S:	Maintained
+S:	Obsolete
 F:	drivers/net/wireless/ath/ar9170/
 
 CARL9170 LINUX COMMUNITY WIRELESS DRIVER
@@ -1457,7 +1481,7 @@ F:	drivers/mtd/devices/block2mtd.c
 
 BLUETOOTH DRIVERS
 M:	Marcel Holtmann <marcel@holtmann.org>
-M:	Gustavo F. Padovan <padovan@profusion.mobi>
+M:	"Gustavo F. Padovan" <padovan@profusion.mobi>
 L:	linux-bluetooth@vger.kernel.org
 W:	http://www.bluez.org/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
@@ -1466,7 +1490,7 @@ F:	drivers/bluetooth/
 
 BLUETOOTH SUBSYSTEM
 M:	Marcel Holtmann <marcel@holtmann.org>
-M:	Gustavo F. Padovan <padovan@profusion.mobi>
+M:	"Gustavo F. Padovan" <padovan@profusion.mobi>
 L:	linux-bluetooth@vger.kernel.org
 W:	http://www.bluez.org/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git
@@ -1710,6 +1734,7 @@ S:	Maintained
 F:	Documentation/zh_CN/
 
 CISCO VIC ETHERNET NIC DRIVER
+M:	Christian Benvenuti <benve@cisco.com>
 M:	Vasanthy Kolluri <vkolluri@cisco.com>
 M:	Roopa Prabhu <roprabhu@cisco.com>
 M:	David Wang <dwang2@cisco.com>
@@ -2112,6 +2137,12 @@ F:	Documentation/serial/digiepca.txt
 F:	drivers/char/epca*
 F:	drivers/char/digi*
 
+DIOLAN U2C-12 I2C DRIVER
+M:	Guenter Roeck <guenter.roeck@ericsson.com>
+L:	linux-i2c@vger.kernel.org
+S:	Maintained
+F:	drivers/i2c/busses/i2c-diolan-u2c.c
+
 DIRECTORY NOTIFICATION (DNOTIFY)
 M:	Eric Paris <eparis@parisplace.org>
 S:	Maintained
@@ -2358,7 +2389,7 @@ F:	include/linux/edac_mce.h
 
 EDAC-I82975X
 M:	Ranganathan Desikan <ravi@jetztechnologies.com>
-M:	"Arvind R." <arvind@jetztechnologies.com>
+M:	"Arvind R." <arvino55@gmail.com>
 L:	bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
 W:	bluesmoke.sourceforge.net
 S:	Maintained
@@ -2449,8 +2480,7 @@ F:	include/linux/cb710.h
 ENE KB2426 (ENE0100/ENE020XX) INFRARED RECEIVER
 M:	Maxim Levitsky <maximlevitsky@gmail.com>
 S:	Maintained
-F:	drivers/media/IR/ene_ir.c
-F:	drivers/media/IR/ene_ir.h
+F:	drivers/media/rc/ene_ir.*
 
 EPSON 1355 FRAMEBUFFER DRIVER
 M:	Christopher Hoover <ch@murgatroid.com>
@@ -2794,7 +2824,6 @@ F:	include/linux/gigaset_dev.h
 
 GPIO SUBSYSTEM
 M:	Grant Likely <grant.likely@secretlab.ca>
-L:	linux-kernel@vger.kernel.org
 S:	Maintained
 T:	git git://git.secretlab.ca/git/linux-2.6.git
 F:	Documentation/gpio/gpio.txt
@@ -2817,7 +2846,6 @@ F:	drivers/platform/x86/hdaps.c
 HWPOISON MEMORY FAILURE HANDLING
 M:	Andi Kleen <andi@firstfloor.org>
 L:	linux-mm@kvack.org
-L:	linux-kernel@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ak/linux-mce-2.6.git hwpoison
 S:	Maintained
 F:	mm/memory-failure.c
@@ -2826,7 +2854,7 @@ F:	mm/hwpoison-inject.c
 HYPERVISOR VIRTUAL CONSOLE DRIVER
 L:	linuxppc-dev@lists.ozlabs.org
 S:	Odd Fixes
-F:	drivers/char/hvc_*
+F:	drivers/tty/hvc/
 
 iSCSI BOOT FIRMWARE TABLE (iBFT) DRIVER
 M:	Peter Jones <pjones@redhat.com>
@@ -2918,7 +2946,7 @@ F:	Documentation/blockdev/cpqarray.txt
 F:	drivers/block/cpqarray.*
 
 HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
-M:	Stephen M. Cameron <scameron@beardog.cce.hp.com>
+M:	"Stephen M. Cameron" <scameron@beardog.cce.hp.com>
 L:	iss_storagedev@hp.com
 S:	Supported
 F:	Documentation/scsi/hpsa.txt
@@ -2975,7 +3003,7 @@ F:	kernel/hrtimer.c
 F:	kernel/time/clockevents.c
 F:	kernel/time/tick*.*
 F:	kernel/time/timer_*.c
-F	include/linux/clockevents.h
+F:	include/linux/clockevents.h
 F:	include/linux/hrtimer.h
 
 HIGH-SPEED SCC DRIVER FOR AX.25
@@ -3148,15 +3176,6 @@ L:	linux-pm@lists.linux-foundation.org
 S:	Supported
 F:	drivers/idle/i7300_idle.c
 
-IEEE 1394 SUBSYSTEM
-M:	Stefan Richter <stefanr@s5r6.in-berlin.de>
-L:	linux1394-devel@lists.sourceforge.net
-W:	http://ieee1394.wiki.kernel.org/
-T:	git git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git
-S:	Obsolete
-F:	Documentation/debugging-via-ohci1394.txt
-F:	drivers/ieee1394/
-
 IEEE 802.15.4 SUBSYSTEM
 M:	Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
 M:	Sergey Lapin <slapin@ossfans.org>
@@ -3441,7 +3460,7 @@ M:	Jiri Kosina <jkosina@suse.cz>
 M:	David Sterba <dsterba@suse.cz>
 S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git
-F:	drivers/char/pcmcia/ipwireless/
+F:	drivers/tty/ipwireless/
 
 IPX NETWORK LAYER
 M:	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
@@ -3454,6 +3473,7 @@ F:	net/ipx/
 IRDA SUBSYSTEM
 M:	Samuel Ortiz <samuel@sortiz.org>
 L:	irda-users@lists.sourceforge.net (subscribers-only)
+L:	netdev@vger.kernel.org
 W:	http://irda.sourceforge.net/
 S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/sameo/irda-2.6.git
@@ -3596,12 +3616,6 @@ W:	http://lse.sourceforge.net/kdump/
 S:	Maintained
 F:	Documentation/kdump/
 
-KERNEL AUTOMOUNTER (AUTOFS)
-M:	"H. Peter Anvin" <hpa@zytor.com>
-L:	autofs@linux.kernel.org
-S:	Obsolete
-F:	drivers/staging/autofs/
-
 KERNEL AUTOMOUNTER v4 (AUTOFS4)
 M:	Ian Kent <raven@themaw.net>
 L:	autofs@linux.kernel.org
@@ -3897,6 +3911,12 @@ L:	linux-security-module@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git
 S:	Supported
 
+LIS3LV02D ACCELEROMETER DRIVER
+M:	Eric Piel <eric.piel@tremplin-utc.net>
+S:	Maintained
+F:	Documentation/misc-devices/lis3lv02d
+F:	drivers/misc/lis3lv02d/
+
 LLC (802.2)
 M:	Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 S:	Maintained
@@ -3904,12 +3924,6 @@ F:	include/linux/llc.h
 F:	include/net/llc*
 F:	net/llc/
 
-LIS3LV02D ACCELEROMETER DRIVER
-M:	Eric Piel <eric.piel@tremplin-utc.net>
-S:	Maintained
-F:	Documentation/hwmon/lis3lv02d
-F:	drivers/hwmon/lis3lv02d.*
-
 LM73 HARDWARE MONITOR DRIVER
 M:	Guillaume Ligneul <guillaume.ligneul@gmail.com>
 L:	lm-sensors@lm-sensors.org
@@ -4205,7 +4219,7 @@ F:	Documentation/serial/moxa-smartio
 F:	drivers/char/mxser.*
 
 MSI LAPTOP SUPPORT
-M:	Lee, Chun-Yi <jlee@novell.com>
+M:	"Lee, Chun-Yi" <jlee@novell.com>
 L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/msi-laptop.c
@@ -4498,11 +4512,21 @@ S:	Maintained
 F:	arch/arm/*omap*/*clock*
 
 OMAP POWER MANAGEMENT SUPPORT
-M:	Kevin Hilman <khilman@deeprootsystems.com>
+M:	Kevin Hilman <khilman@ti.com>
 L:	linux-omap@vger.kernel.org
 S:	Maintained
 F:	arch/arm/*omap*/*pm*
 
+OMAP POWERDOMAIN/CLOCKDOMAIN SOC ADAPTATION LAYER SUPPORT
+M:	Rajendra Nayak <rnayak@ti.com>
+M:	Paul Walmsley <paul@pwsan.com>
+L:	linux-omap@vger.kernel.org
+S:	Maintained
+F:	arch/arm/mach-omap2/powerdomain2xxx_3xxx.c
+F:	arch/arm/mach-omap2/powerdomain44xx.c
+F:	arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
+F:	arch/arm/mach-omap2/clockdomain44xx.c
+
 OMAP AUDIO SUPPORT
 M:	Jarkko Nikula <jhnikula@gmail.com>
 L:	alsa-devel@alsa-project.org (subscribers-only)
@@ -4690,7 +4714,6 @@ F:	drivers/i2c/busses/i2c-pasemi.c
 
 PADATA PARALLEL EXECUTION MECHANISM
 M:	Steffen Klassert <steffen.klassert@secunet.com>
-L:	linux-kernel@vger.kernel.org
 L:	linux-crypto@vger.kernel.org
 S:	Maintained
 F:	kernel/padata.c
@@ -4840,7 +4863,6 @@ F:	include/crypto/pcrypt.h
 PER-CPU MEMORY ALLOCATOR
 M:	Tejun Heo <tj@kernel.org>
 M:	Christoph Lameter <cl@linux-foundation.org>
-L:	linux-kernel@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu.git
 S:	Maintained
 F:	include/linux/percpu*.h
@@ -4895,6 +4917,15 @@ S:	Maintained
 F:	drivers/block/pktcdvd.c
 F:	include/linux/pktcdvd.h
 
+PKUNITY SOC DRIVERS
+M:	Guan Xuetao <gxt@mprc.pku.edu.cn>
+W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
+F:	drivers/input/serio/i8042-unicore32io.h
+F:	drivers/i2c/busses/i2c-puv3.c
+F:	drivers/video/fb-puv3.c
+
 PMC SIERRA MaxRAID DRIVER
 M:	Anil Ravindranath <anil_ravindranath@pmc-sierra.com>
 L:	linux-scsi@vger.kernel.org
@@ -5158,6 +5189,7 @@ RALINK RT2X00 WIRELESS LAN DRIVER
 P:	rt2x00 project
 M:	Ivo van Doorn <IvDoorn@gmail.com>
 M:	Gertjan van Wingerde <gwingerde@gmail.com>
+M:	Helmut Schaa <helmut.schaa@googlemail.com>
 L:	linux-wireless@vger.kernel.org
 L:	users@rt2x00.serialmonkey.com (moderated for non-subscribers)
 W:	http://rt2x00.serialmonkey.com/
@@ -5337,8 +5369,7 @@ S:	Supported
 F:	drivers/s390/crypto/
 
 S390 ZFCP DRIVER
-M:	Christof Schmitt <christof.schmitt@de.ibm.com>
-M:	Swen Schillig <swen@vnet.ibm.com>
+M:	Steffen Maier <maier@linux.vnet.ibm.com>
 M:	linux390@de.ibm.com
 L:	linux-s390@vger.kernel.org
 W:	http://www.ibm.com/developerworks/linux/linux390/
@@ -5377,6 +5408,12 @@ L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:	Supported
 F:	sound/soc/samsung
 
+SERIAL DRIVERS
+M:	Alan Cox <alan@linux.intel.com>
+L:	linux-serial@vger.kernel.org
+S:	Maintained
+F:	drivers/tty/serial
+
 TIMEKEEPING, NTP
 M:	John Stultz <johnstul@us.ibm.com>
 M:	Thomas Gleixner <tglx@linutronix.de>
@@ -5384,7 +5421,6 @@ S:	Supported
 F:	include/linux/clocksource.h
 F:	include/linux/time.h
 F:	include/linux/timex.h
-F:	include/linux/timekeeping.h
 F:	kernel/time/clocksource.c
 F:	kernel/time/time*.c
 F:	kernel/time/ntp.c
@@ -5472,7 +5508,7 @@ SCx200 CPU SUPPORT
 M:	Jim Cromie <jim.cromie@gmail.com>
 S:	Odd Fixes
 F:	Documentation/i2c/busses/scx200_acb
-F:	arch/x86/kernel/scx200_32.c
+F:	arch/x86/platform/scx200/
 F:	drivers/watchdog/scx200_wdt.c
 F:	drivers/i2c/busses/scx200*
 F:	drivers/mtd/maps/scx200_docflash.c
@@ -5616,24 +5652,13 @@ M:	Robin Holt <holt@sgi.com>
 S:	Maintained
 F:	drivers/misc/sgi-xp/
 
-SHARP LH SUPPORT (LH7952X & LH7A40X)
-M:	Marc Singer <elf@buici.com>
-W:	http://projects.buici.com/arm
-L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:	Maintained
-F:	Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
-F:	arch/arm/mach-lh7a40x/
-F:	drivers/tty/serial/serial_lh7a40x.c
-F:	drivers/usb/gadget/lh7a40*
-F:	drivers/usb/host/ohci-lh7a40*
-
 SIMPLE FIRMWARE INTERFACE (SFI)
 M:	Len Brown <lenb@kernel.org>
 L:	sfi-devel@simplefirmware.org
 W:	http://simplefirmware.org/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git
 S:	Supported
-F:	arch/x86/kernel/*sfi*
+F:	arch/x86/platform/sfi/
 F:	drivers/sfi/
 F:	include/linux/sfi*.h
 
@@ -5655,7 +5680,8 @@ F:	arch/arm/mach-s3c2410/bast-ide.c
 F:	arch/arm/mach-s3c2410/bast-irq.c
 
 TI DAVINCI MACHINE SUPPORT
-M:	Kevin Hilman <khilman@deeprootsystems.com>
+M:	Sekhar Nori <nsekhar@ti.com>
+M:	Kevin Hilman <khilman@ti.com>
 L:	davinci-linux-open-source@linux.davincidsp.com (subscribers-only)
 Q:	http://patchwork.kernel.org/project/linux-davinci/list/
 S:	Supported
@@ -5730,6 +5756,13 @@ S:	Supported
 F:	Documentation/hwmon/emc2103
 F:	drivers/hwmon/emc2103.c
 
+SMSC SCH5627 HARDWARE MONITOR DRIVER
+M:	Hans de Goede <hdegoede@redhat.com>
+L:	lm-sensors@lm-sensors.org
+S:	Supported
+F:	Documentation/hwmon/sch5627
+F:	drivers/hwmon/sch5627.c
+
 SMSC47B397 HARDWARE MONITOR DRIVER
 M:	"Mark M. Hoffman" <mhoffman@lightlink.com>
 L:	lm-sensors@lm-sensors.org
@@ -6081,13 +6114,11 @@ F:	sound/soc/codecs/twl4030*
 TIPC NETWORK LAYER
 M:	Jon Maloy <jon.maloy@ericsson.com>
 M:	Allan Stephens <allan.stephens@windriver.com>
-L:	tipc-discussion@lists.sourceforge.net
+L:	netdev@vger.kernel.org (core kernel code)
+L:	tipc-discussion@lists.sourceforge.net (user apps, general discussion)
 W:	http://tipc.sourceforge.net/
-W:	http://tipc.cslab.ericsson.net/
-T:	git git://tipc.cslab.ericsson.net/pub/git/tipc.git
 S:	Maintained
 F:	include/linux/tipc*.h
-F:	include/net/tipc/
 F:	net/tipc/
 
 TILE ARCHITECTURE
@@ -6095,8 +6126,9 @@ M:	Chris Metcalf <cmetcalf@tilera.com>
 W:	http://www.tilera.com/scm/
 S:	Supported
 F:	arch/tile/
-F:	drivers/char/hvc_tile.c
+F:	drivers/tty/hvc/hvc_tile.c
 F:	drivers/net/tile/
+F:	drivers/edac/tile_edac.c
 
 TLAN NETWORK DRIVER
 M:	Samuel Chessman <chessman@tux.org>
@@ -6259,6 +6291,13 @@ F:	drivers/uwb/
 F:	include/linux/uwb.h
 F:	include/linux/uwb/
 
+UNICORE32 ARCHITECTURE:
+M:	Guan Xuetao <gxt@mprc.pku.edu.cn>
+W:	http://mprc.pku.edu.cn/~guanxuetao/linux
+S:	Maintained
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/epip/linux-2.6-unicore32.git
+F:	arch/unicore32/
+
 UNIFDEF
 M:	Tony Finch <dot@dotat.at>
 W:	http://dotat.at/prog/unifdef
@@ -6427,12 +6466,11 @@ S:	Maintained
 F:	drivers/net/usb/rtl8150.c
 
 USB SE401 DRIVER
-M:	Jeroen Vreeken <pe1rxq@amsat.org>
 L:	linux-usb@vger.kernel.org
 W:	http://www.chello.nl/~j.vreeken/se401/
-S:	Maintained
+S:	Orphan
 F:	Documentation/video4linux/se401.txt
-F:	drivers/media/video/se401.*
+F:	drivers/staging/se401/
 
 USB SERIAL BELKIN F5U103 DRIVER
 M:	William Greathouse <wgreathouse@smva.com>
@@ -6782,7 +6820,7 @@ F:	drivers/scsi/wd7000.c
 WINBOND CIR DRIVER
 M:	David HĂ¤rdeman <david@hardeman.nu>
 S:	Maintained
-F:	drivers/input/misc/winbond-cir.c
+F:	drivers/media/rc/winbond-cir.c
 
 WIMAX STACK
 M:	Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
@@ -6859,7 +6897,6 @@ F:	sound/soc/codecs/wm*
 
 WORKQUEUE
 M:	Tejun Heo <tj@kernel.org>
-L:	linux-kernel@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq.git
 S:	Maintained
 F:	include/linux/workqueue.h
diff --git a/Makefile b/Makefile
index d6592b6..7d4e9c8 100644
--- a/Makefile
+++ b/Makefile
@@ -102,6 +102,10 @@ ifeq ("$(origin O)", "command line")
   KBUILD_OUTPUT := $(O)
 endif
 
+ifeq ("$(origin W)", "command line")
+  export KBUILD_ENABLE_EXTRA_GCC_CHECKS := 1
+endif
+
 # That's our default target when none is given on the command line
 PHONY := _all
 _all:
@@ -421,7 +425,7 @@ endif
 # of make so .config is not included in this case either (for *config).
 
 no-dot-config-targets := clean mrproper distclean \
-			 cscope TAGS tags help %docs check% coccicheck \
+			 cscope gtags TAGS tags help %docs check% coccicheck \
 			 include/linux/version.h headers_% \
 			 kernelversion %src-pkg
 
@@ -666,7 +670,7 @@ export MODLIB
 #  INSTALL_MOD_STRIP, if defined, will cause modules to be
 #  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
 #  the default option --strip-debug will be used.  Otherwise,
-#  INSTALL_MOD_STRIP will used as the options to the strip command.
+#  INSTALL_MOD_STRIP value will be used as the options to the strip command.
 
 ifdef INSTALL_MOD_STRIP
 ifeq ($(INSTALL_MOD_STRIP),1)
@@ -1018,7 +1022,7 @@ hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
 
 PHONY += __headers
 __headers: include/linux/version.h scripts_basic FORCE
-	$(Q)$(MAKE) $(build)=scripts scripts/unifdef
+	$(Q)$(MAKE) $(build)=scripts build_unifdef
 
 PHONY += headers_install_all
 headers_install_all:
@@ -1135,7 +1139,7 @@ CLEAN_FILES +=	vmlinux System.map \
 MRPROPER_DIRS  += include/config usr/include include/generated
 MRPROPER_FILES += .config .config.old .version .old_version             \
                   include/linux/version.h                               \
-		  Module.symvers tags TAGS cscope*
+		  Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1222,6 +1226,7 @@ help:
 	@echo  '  modules_prepare - Set up for building external modules'
 	@echo  '  tags/TAGS	  - Generate tags file for editors'
 	@echo  '  cscope	  - Generate cscope index'
+	@echo  '  gtags           - Generate GNU GLOBAL index'
 	@echo  '  kernelrelease	  - Output the release version string'
 	@echo  '  kernelversion	  - Output the version stored in Makefile'
 	@echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
@@ -1262,6 +1267,7 @@ help:
 	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
 	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse by default)'
 	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK'
+	@echo  '  make W=1   [targets] Enable extra gcc checks'
 	@echo  ''
 	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
 	@echo  'For further info see the ./README file'
@@ -1380,7 +1386,7 @@ clean: $(clean-dirs)
 quiet_cmd_tags = GEN     $@
       cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@
 
-tags TAGS cscope: FORCE
+tags TAGS cscope gtags: FORCE
 	$(call cmd,tags)
 
 # Scripts to check various things for consistency
diff --git a/README b/README
index 1b81d28..8510017 100644
--- a/README
+++ b/README
@@ -24,7 +24,7 @@ ON WHAT HARDWARE DOES IT RUN?
   today Linux also runs on (at least) the Compaq Alpha AXP, Sun SPARC and
   UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell,
   IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS,
-  Xtensa, AVR32 and Renesas M32R architectures.
+  Xtensa, Tilera TILE, AVR32 and Renesas M32R architectures.
 
   Linux is easily portable to most general-purpose 32- or 64-bit architectures
   as long as they have a paged memory management unit (PMMU) and a port of the
diff --git a/arch/alpha/include/asm/cacheflush.h b/arch/alpha/include/asm/cacheflush.h
index 012f124..a9cb6aa 100644
--- a/arch/alpha/include/asm/cacheflush.h
+++ b/arch/alpha/include/asm/cacheflush.h
@@ -63,7 +63,7 @@ extern void flush_icache_user_range(struct vm_area_struct *vma,
 		struct page *page, unsigned long addr, int len);
 #endif
 
-/* This is used only in do_no_page and do_swap_page.  */
+/* This is used only in __do_fault and do_swap_page.  */
 #define flush_icache_page(vma, page) \
   flush_icache_user_range((vma), (page), 0, 0)
 
diff --git a/arch/alpha/include/asm/errno.h b/arch/alpha/include/asm/errno.h
index 98099bd..e5f29ca 100644
--- a/arch/alpha/include/asm/errno.h
+++ b/arch/alpha/include/asm/errno.h
@@ -122,4 +122,6 @@
 
 #define	ERFKILL		138	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	139	/* Memory page has hardware error */
+
 #endif
diff --git a/arch/alpha/include/asm/fcntl.h b/arch/alpha/include/asm/fcntl.h
index 70145cb..1b71ca7 100644
--- a/arch/alpha/include/asm/fcntl.h
+++ b/arch/alpha/include/asm/fcntl.h
@@ -31,6 +31,8 @@
 #define __O_SYNC	020000000
 #define O_SYNC		(__O_SYNC|O_DSYNC)
 
+#define O_PATH		040000000
+
 #define F_GETLK		7
 #define F_SETLK		8
 #define F_SETLKW	9
diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index 945de22..e8a761a 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -29,7 +29,7 @@
 	:	"r" (uaddr), "r"(oparg)				\
 	:	"memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -81,21 +81,23 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
 		__ASM_SMP_MB
-	"1:	ldl_l	%0,0(%2)\n"
-	"	cmpeq	%0,%3,%1\n"
-	"	beq	%1,3f\n"
-	"	mov	%4,%1\n"
-	"2:	stl_c	%1,0(%2)\n"
-	"	beq	%1,4f\n"
+	"1:	ldl_l	%1,0(%3)\n"
+	"	cmpeq	%1,%4,%2\n"
+	"	beq	%2,3f\n"
+	"	mov	%5,%2\n"
+	"2:	stl_c	%2,0(%3)\n"
+	"	beq	%2,4f\n"
 	"3:	.subsection 2\n"
 	"4:	br	1b\n"
 	"	.previous\n"
@@ -105,11 +107,12 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	"	.long	2b-.\n"
 	"	lda	$31,3b-2b(%0)\n"
 	"	.previous\n"
-	:	"=&r"(prev), "=&r"(cmp)
+	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
 	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
 	:	"memory");
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/alpha/include/asm/ioctls.h b/arch/alpha/include/asm/ioctls.h
index 034b6cf..80e1cee 100644
--- a/arch/alpha/include/asm/ioctls.h
+++ b/arch/alpha/include/asm/ioctls.h
@@ -94,6 +94,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff --git a/arch/alpha/include/asm/rwsem.h b/arch/alpha/include/asm/rwsem.h
index 1570c0b..a83bbea 100644
--- a/arch/alpha/include/asm/rwsem.h
+++ b/arch/alpha/include/asm/rwsem.h
@@ -13,44 +13,13 @@
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
 
-struct rwsem_waiter;
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	long			count;
 #define RWSEM_UNLOCKED_VALUE		0x0000000000000000L
 #define RWSEM_ACTIVE_BIAS		0x0000000000000001L
 #define RWSEM_ACTIVE_MASK		0x00000000ffffffffL
 #define RWSEM_WAITING_BIAS		(-0x0000000100000000L)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-};
-
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	LIST_HEAD_INIT((name).wait_list) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
 
 static inline void __down_read(struct rw_semaphore *sem)
 {
@@ -250,10 +219,5 @@ static inline long rwsem_atomic_update(long val, struct rw_semaphore *sem)
 #endif
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_RWSEM_H */
diff --git a/arch/alpha/include/asm/types.h b/arch/alpha/include/asm/types.h
index bd621ec..e46e503 100644
--- a/arch/alpha/include/asm/types.h
+++ b/arch/alpha/include/asm/types.h
@@ -27,7 +27,6 @@ typedef unsigned int umode_t;
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-typedef u64 dma_addr_t;
 typedef u64 dma64_addr_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index fe698b5..376f221 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -230,44 +230,24 @@ linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_st
 	return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
 }
 
-static int
-do_osf_statfs(struct path *path, struct osf_statfs __user *buffer,
-	      unsigned long bufsiz)
+SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
+		struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
 	struct kstatfs linux_stat;
-	int error = vfs_statfs(path, &linux_stat);
+	int error = user_statfs(pathname, &linux_stat);
 	if (!error)
 		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
 	return error;	
 }
 
-SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
-		struct osf_statfs __user *, buffer, unsigned long, bufsiz)
-{
-	struct path path;
-	int retval;
-
-	retval = user_path(pathname, &path);
-	if (!retval) {
-		retval = do_osf_statfs(&path, buffer, bufsiz);
-		path_put(&path);
-	}
-	return retval;
-}
-
 SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd,
 		struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
-	struct file *file;
-	int retval;
-
-	retval = -EBADF;
-	file = fget(fd);
-	if (file) {
-		retval = do_osf_statfs(&file->f_path, buffer, bufsiz);
-		fput(file);
-	}
-	return retval;
+	struct kstatfs linux_stat;
+	int error = fd_statfs(fd, &linux_stat);
+	if (!error)
+		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
+	return error;
 }
 
 /*
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index c1f3e7c..a58e84f 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -159,7 +159,7 @@ void read_persistent_clock(struct timespec *ts)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 irqreturn_t timer_interrupt(int irq, void *dev)
 {
@@ -172,8 +172,6 @@ irqreturn_t timer_interrupt(int irq, void *dev)
 	profile_tick(CPU_PROFILING);
 #endif
 
-	write_seqlock(&xtime_lock);
-
 	/*
 	 * Calculate how many ticks have passed since the last update,
 	 * including any previous partial leftover.  Save any resulting
@@ -187,9 +185,7 @@ irqreturn_t timer_interrupt(int irq, void *dev)
 	nticks = delta >> FIX_SHIFT;
 
 	if (nticks)
-		do_timer(nticks);
-
-	write_sequnlock(&xtime_lock);
+		xtime_update(nticks);
 
 	if (test_irq_work_pending()) {
 		clear_irq_work_pending();
diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
index 003ef4c..433be2a 100644
--- a/arch/alpha/kernel/vmlinux.lds.S
+++ b/arch/alpha/kernel/vmlinux.lds.S
@@ -1,5 +1,6 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
+#include <asm/cache.h>
 #include <asm/page.h>
 
 OUTPUT_FORMAT("elf64-alpha")
@@ -38,7 +39,7 @@ SECTIONS
 	__init_begin = ALIGN(PAGE_SIZE);
 	INIT_TEXT_SECTION(PAGE_SIZE)
 	INIT_DATA_SECTION(16)
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 	/* Align to THREAD_SIZE rather than PAGE_SIZE here so any padding page
 	   needed for the THREAD_SIZE aligned init_task gets freed after init */
 	. = ALIGN(THREAD_SIZE);
@@ -46,7 +47,7 @@ SECTIONS
 	/* Freed after init ends here */
 
 	_data = .;
-	RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
 
 	.got : {
 		*(.got)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 166efa2..599e163 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -7,7 +7,7 @@ config ARM
 	select HAVE_MEMBLOCK
 	select RTC_LIB
 	select SYS_SUPPORTS_APM_EMULATION
-	select GENERIC_ATOMIC64 if (!CPU_32v6K || !AEABI)
+	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
 	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
 	select HAVE_ARCH_KGDB
 	select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
@@ -24,7 +24,7 @@ config ARM
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_REGS_AND_STACK_ACCESS_API
-	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
 	select HAVE_C_RECORDMCOUNT
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
@@ -63,6 +63,10 @@ config GENERIC_CLOCKEVENTS_BROADCAST
 	depends on GENERIC_CLOCKEVENTS
 	default y if SMP
 
+config KTIME_SCALAR
+	bool
+	default y
+
 config HAVE_TCM
 	bool
 	select GENERIC_ALLOCATOR
@@ -178,11 +182,6 @@ config FIQ
 config ARCH_MTD_XIP
 	bool
 
-config ARM_L1_CACHE_SHIFT_6
-	bool
-	help
-	  Setting ARM L1 cache line size to 64 Bytes.
-
 config VECTORS_BASE
 	hex
 	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -191,6 +190,22 @@ config VECTORS_BASE
 	help
 	  The base address of exception vectors.
 
+config ARM_PATCH_PHYS_VIRT
+	bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on !XIP_KERNEL && MMU
+	depends on !ARCH_REALVIEW || !SPARSEMEM
+	help
+	  Patch phys-to-virt translation functions at runtime according to
+	  the position of the kernel in system memory.
+
+	  This can only be used with non-XIP with MMU kernels where
+	  the base of physical memory is at a 16MB boundary.
+
+config ARM_PATCH_PHYS_VIRT_16BIT
+	def_bool y
+	depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -212,15 +227,6 @@ choice
 	prompt "ARM system type"
 	default ARCH_VERSATILE
 
-config ARCH_AAEC2000
-	bool "Agilent AAEC-2000 based"
-	select CPU_ARM920T
-	select ARM_AMBA
-	select HAVE_CLK
-	select ARCH_USES_GETTIMEOFFSET
-	help
-	  This enables support for systems based on the Agilent AAEC-2000
-
 config ARCH_INTEGRATOR
 	bool "ARM Ltd. Integrator family"
 	select ARM_AMBA
@@ -346,7 +352,7 @@ config ARCH_FOOTBRIDGE
 	bool "FootBridge"
 	select CPU_SA110
 	select FOOTBRIDGE
-	select ARCH_USES_GETTIMEOFFSET
+	select GENERIC_CLOCKEVENTS
 	help
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -457,6 +463,7 @@ config ARCH_IXP4XX
 
 config ARCH_DOVE
 	bool "Marvell Dove"
+	select CPU_V6K
 	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
@@ -619,6 +626,7 @@ config ARCH_MSM
 	select HAVE_CLK
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
 	help
 	  Support for Qualcomm MSM/QSD based systems.  This runs on the
 	  apps processor of the MSM/QSD and depends on a shared memory
@@ -715,7 +723,8 @@ config ARCH_S5P64X0
 	select GENERIC_GPIO
 	select HAVE_CLK
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
-	select ARCH_USES_GETTIMEOFFSET
+	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	help
@@ -753,15 +762,16 @@ config ARCH_S5PV210
 	select HAVE_CLK
 	select ARM_L1_CACHE_SHIFT_6
 	select ARCH_HAS_CPUFREQ
-	select ARCH_USES_GETTIMEOFFSET
+	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	  Samsung S5PV210/S5PC110 series based systems
 
-config ARCH_S5PV310
-	bool "Samsung S5PV310/S5PC210"
+config ARCH_EXYNOS4
+	bool "Samsung EXYNOS4"
 	select CPU_V7
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_GPIO
@@ -772,7 +782,7 @@ config ARCH_S5PV310
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
-	  Samsung S5PV310 series based systems
+	  Samsung EXYNOS4 series based systems
 
 config ARCH_SHARK
 	bool "Shark"
@@ -795,17 +805,6 @@ config ARCH_TCC_926
 	help
 	  Support for Telechips TCC ARM926-based systems.
 
-config ARCH_LH7A40X
-	bool "Sharp LH7A40X"
-	select CPU_ARM922T
-	select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM
-	select ARCH_USES_GETTIMEOFFSET
-	help
-	  Say Y here for systems based on one of the Sharp LH7A40X
-	  System on a Chip processors.  These CPUs include an ARM922T
-	  core with a wide array of integrated devices for
-	  hand-held and low-power applications.
-
 config ARCH_U300
 	bool "ST-Ericsson U300 Series"
 	depends on MMU
@@ -875,6 +874,16 @@ config PLAT_SPEAR
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
+config ARCH_VT8500
+	bool "VIA/WonderMedia 85xx"
+	select CPU_ARM926T
+	select GENERIC_GPIO
+	select ARCH_HAS_CPUFREQ
+	select GENERIC_CLOCKEVENTS
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_PWM
+	help
+	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
 endchoice
 
 #
@@ -882,8 +891,6 @@ endchoice
 # Kconfigs may be included either alphabetically (according to the
 # plat- suffix) or along side the corresponding mach-* source.
 #
-source "arch/arm/mach-aaec2000/Kconfig"
-
 source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcmring/Kconfig"
@@ -922,8 +929,6 @@ source "arch/arm/mach-kirkwood/Kconfig"
 
 source "arch/arm/mach-ks8695/Kconfig"
 
-source "arch/arm/mach-lh7a40x/Kconfig"
-
 source "arch/arm/mach-loki/Kconfig"
 
 source "arch/arm/mach-lpc32xx/Kconfig"
@@ -991,7 +996,7 @@ source "arch/arm/mach-s5pc100/Kconfig"
 
 source "arch/arm/mach-s5pv210/Kconfig"
 
-source "arch/arm/mach-s5pv310/Kconfig"
+source "arch/arm/mach-exynos4/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
@@ -1007,6 +1012,8 @@ source "arch/arm/mach-versatile/Kconfig"
 
 source "arch/arm/mach-vexpress/Kconfig"
 
+source "arch/arm/mach-vt8500/Kconfig"
+
 source "arch/arm/mach-w90x900/Kconfig"
 
 # Definitions to make life easier
@@ -1048,7 +1055,7 @@ config XSCALE_PMU
 	default y
 
 config CPU_HAS_PMU
-	depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \
+	depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \
 		   (!ARCH_OMAP3 || OMAP3_EMU)
 	default y
 	bool
@@ -1064,7 +1071,7 @@ endif
 
 config ARM_ERRATA_411920
 	bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
-	depends on CPU_V6
+	depends on CPU_V6 || CPU_V6K
 	help
 	  Invalidation of the Instruction Cache operation can
 	  fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
@@ -1140,7 +1147,7 @@ config ARM_ERRATA_742231
 
 config PL310_ERRATA_588369
 	bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
-	depends on CACHE_L2X0 && ARCH_OMAP4
+	depends on CACHE_L2X0
 	help
 	   The PL310 L2 cache controller implements three types of Clean &
 	   Invalidate maintenance operations: by Physical Address
@@ -1149,8 +1156,7 @@ config PL310_ERRATA_588369
 	   clean operation followed immediately by an invalidate operation,
 	   both performing to the same memory location. This functionality
 	   is not correctly implemented in PL310 as clean lines are not
-	   invalidated as a result of these operations. Note that this errata
-	   uses Texas Instrument's secure monitor api.
+	   invalidated as a result of these operations.
 
 config ARM_ERRATA_720789
 	bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
@@ -1164,6 +1170,17 @@ config ARM_ERRATA_720789
 	  tables. The workaround changes the TLB flushing routines to invalidate
 	  entries regardless of the ASID.
 
+config PL310_ERRATA_727915
+	bool "Background Clean & Invalidate by Way operation can cause data corruption"
+	depends on CACHE_L2X0
+	help
+	  PL310 implements the Clean & Invalidate by Way L2 cache maintenance
+	  operation (offset 0x7FC). This operation runs in background so that
+	  PL310 can handle normal accesses while it is in progress. Under very
+	  rare circumstances, due to this erratum, write data can be lost when
+	  PL310 treats a cacheable write transaction during a Clean &
+	  Invalidate by Way operation.
+
 config ARM_ERRATA_743622
 	bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
 	depends on CPU_V7
@@ -1202,6 +1219,28 @@ config ARM_ERRATA_753970
 	  This has the same effect as the cache sync operation: store buffer
 	  drain and waiting for all buffers empty.
 
+config ARM_ERRATA_754322
+	bool "ARM errata: possible faulty MMU translations following an ASID switch"
+	depends on CPU_V7
+	help
+	  This option enables the workaround for the 754322 Cortex-A9 (r2p*,
+	  r3p*) erratum. A speculative memory access may cause a page table walk
+	  which starts prior to an ASID switch but completes afterwards. This
+	  can populate the micro-TLB with a stale entry which may be hit with
+	  the new ASID. This workaround places two dsb instructions in the mm
+	  switching code so that no page table walks can cross the ASID switch.
+
+config ARM_ERRATA_754327
+	bool "ARM errata: no automatic Store Buffer drain"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 754327 Cortex-A9 (prior to
+	  r2p0) erratum. The Store Buffer does not have any automatic draining
+	  mechanism and therefore a livelock may occur if an external agent
+	  continuously polls a memory location waiting to observe an update.
+	  This workaround defines cpu_relax() as smp_mb(), preventing correctly
+	  written polling loops from denying visibility of updates to memory.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1275,10 +1314,11 @@ source "kernel/time/Kconfig"
 config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	depends on CPU_V6K || CPU_V7
 	depends on GENERIC_CLOCKEVENTS
 	depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
-		 ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+		 ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
 		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
 	select USE_GENERIC_SMP_HELPERS
 	select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
@@ -1366,7 +1406,7 @@ config LOCAL_TIMERS
 	bool "Use local timer interrupts"
 	depends on SMP
 	default y
-	select HAVE_ARM_TWD if !ARCH_MSM_SCORPIONMP
+	select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -1378,7 +1418,7 @@ source kernel/Kconfig.preempt
 config HZ
 	int
 	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
-		ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
+		ARCH_S5P6442 || ARCH_S5PV210 || ARCH_EXYNOS4
 	default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
 	default AT91_TIMER_HZ if ARCH_AT91
 	default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE
@@ -1386,7 +1426,7 @@ config HZ
 
 config THUMB2_KERNEL
 	bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-	depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
+	depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
 	select AEABI
 	select ARM_ASM_UNIFIED
 	help
@@ -1396,6 +1436,37 @@ config THUMB2_KERNEL
 
 	  If unsure, say N.
 
+config THUMB2_AVOID_R_ARM_THM_JUMP11
+	bool "Work around buggy Thumb-2 short branch relocations in gas"
+	depends on THUMB2_KERNEL && MODULES
+	default y
+	help
+	  Various binutils versions can resolve Thumb-2 branches to
+	  locally-defined, preemptible global symbols as short-range "b.n"
+	  branch instructions.
+
+	  This is a problem, because there's no guarantee the final
+	  destination of the symbol, or any candidate locations for a
+	  trampoline, are within range of the branch.  For this reason, the
+	  kernel does not support fixing up the R_ARM_THM_JUMP11 (102)
+	  relocation in modules at all, and it makes little sense to add
+	  support.
+
+	  The symptom is that the kernel fails with an "unsupported
+	  relocation" error when loading some modules.
+
+	  Until fixed tools are available, passing
+	  -fno-optimize-sibling-calls to gcc should prevent gcc generating
+	  code which hits this problem, at the cost of a bit of extra runtime
+	  stack usage in some cases.
+
+	  The problem is described in more detail at:
+	      https://bugs.launchpad.net/binutils-linaro/+bug/725126
+
+	  Only Thumb-2 kernels are affected.
+
+	  Unless you are sure your tools don't have this problem, say Y.
+
 config ARM_ASM_UNIFIED
 	bool
 
@@ -1644,6 +1715,18 @@ config ZBOOT_ROM
 	  Say Y here if you intend to execute your compressed kernel image
 	  (zImage) directly from ROM or flash.  If unsure, say N.
 
+config ZBOOT_ROM_MMCIF
+	bool "Include MMCIF loader in zImage (EXPERIMENTAL)"
+	depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL
+	help
+	  Say Y here to include experimental MMCIF loading code in the
+	  ROM-able zImage. With this enabled it is possible to write the
+	  the ROM-able zImage kernel image to an MMC card and boot the
+	  kernel straight from the reset vector. At reset the processor
+	  Mask ROM will load the first part of the the ROM-able zImage
+	  which in turn loads the rest the kernel image to RAM using the
+	  MMCIF hardware block.
+
 config CMDLINE
 	string "Default kernel command string"
 	default ""
@@ -1877,7 +1960,7 @@ config FPE_FASTFPE
 
 config VFP
 	bool "VFP-format floating point maths"
-	depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
+	depends on CPU_V6 || CPU_V6K || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
 	help
 	  Say Y to include VFP support code in the kernel. This is needed
 	  if your hardware includes a VFP unit.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6f7b292..c7d321a 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -89,6 +89,7 @@ tune-$(CONFIG_CPU_XSCALE)	:=$(call cc-option,-mtune=xscale,-mtune=strongarm110)
 tune-$(CONFIG_CPU_XSC3)		:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
 tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
 tune-$(CONFIG_CPU_V6)		:=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
+tune-$(CONFIG_CPU_V6K)		:=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
 
 ifeq ($(CONFIG_AEABI),y)
 CFLAGS_ABI	:=-mabi=aapcs-linux -mno-thumb-interwork
@@ -105,6 +106,10 @@ AFLAGS_AUTOIT	:=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mau
 AFLAGS_NOWARN	:=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
 CFLAGS_THUMB2	:=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
 AFLAGS_THUMB2	:=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+# Work around buggy relocation from gas if requested:
+ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
+CFLAGS_MODULE	+=-fno-optimize-sibling-calls
+endif
 endif
 
 # Need -Uarm for gcc < 3.x
@@ -126,7 +131,6 @@ endif
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
-machine-$(CONFIG_ARCH_AAEC2000)		:= aaec2000
 machine-$(CONFIG_ARCH_AT91)		:= at91
 machine-$(CONFIG_ARCH_BCMRING)		:= bcmring
 machine-$(CONFIG_ARCH_CLPS711X)		:= clps711x
@@ -146,7 +150,6 @@ machine-$(CONFIG_ARCH_IXP23XX)		:= ixp23xx
 machine-$(CONFIG_ARCH_IXP4XX)		:= ixp4xx
 machine-$(CONFIG_ARCH_KIRKWOOD)		:= kirkwood
 machine-$(CONFIG_ARCH_KS8695)		:= ks8695
-machine-$(CONFIG_ARCH_LH7A40X)		:= lh7a40x
 machine-$(CONFIG_ARCH_LOKI) 		:= loki
 machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		:= mmp
@@ -178,7 +181,7 @@ machine-$(CONFIG_ARCH_S5P64X0)		:= s5p64x0
 machine-$(CONFIG_ARCH_S5P6442)		:= s5p6442
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
-machine-$(CONFIG_ARCH_S5PV310)		:= s5pv310
+machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos4
 machine-$(CONFIG_ARCH_SA1100)		:= sa1100
 machine-$(CONFIG_ARCH_SHARK)		:= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
@@ -190,6 +193,7 @@ machine-$(CONFIG_ARCH_U300)		:= u300
 machine-$(CONFIG_ARCH_U8500)		:= ux500
 machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
 machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
+machine-$(CONFIG_ARCH_VT8500)		:= vt8500
 machine-$(CONFIG_ARCH_W90X900)		:= w90x900
 machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
@@ -280,7 +284,7 @@ bzImage: zImage
 zImage Image xipImage bootpImage uImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
-zinstall install: vmlinux
+zinstall uinstall install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
@@ -301,6 +305,7 @@ define archhelp
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
+  echo  '  uinstall      - Install U-Boot wrapped compressed kernel'
   echo  '                  Install using (your) ~/bin/$(INSTALLKERNEL) or'
   echo  '                  (distribution) /sbin/$(INSTALLKERNEL) or'
   echo  '                  install to $$(INSTALL_PATH) and run lilo'
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index 4d26f2c..9128fdd 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -99,6 +99,10 @@ zinstall: $(obj)/zImage
 	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
+uinstall: $(obj)/uImage
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(obj)/uImage System.map "$(INSTALL_PATH)"
+
 zi:
 	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 0a8f748..8ebbb51 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -4,9 +4,20 @@
 # create a compressed vmlinuz image from the original vmlinux
 #
 
+OBJS		=
+
+# Ensure that mmcif loader code appears early in the image
+# to minimise that number of bocks that have to be read in
+# order to load it.
+ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y)
+ifeq ($(CONFIG_ARCH_SH7372),y)
+OBJS		+= mmcif-sh7372.o
+endif
+endif
+
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
 HEAD	= head.o
-OBJS	= misc.o decompress.o
+OBJS	+= misc.o decompress.o
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
@@ -29,6 +40,10 @@ ifeq ($(CONFIG_ARCH_SA1100),y)
 OBJS		+= head-sa1100.o
 endif
 
+ifeq ($(CONFIG_ARCH_VT8500),y)
+OBJS		+= head-vt8500.o
+endif
+
 ifeq ($(CONFIG_CPU_XSCALE),y)
 OBJS		+= head-xscale.o
 endif
@@ -80,12 +95,14 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-EXTRA_CFLAGS  := -fpic -fno-builtin
-EXTRA_AFLAGS  := -Wa,-march=all
+ccflags-y := -fpic -fno-builtin
+asflags-y := -Wa,-march=all
 
+# Provide size of uncompressed kernel to the decompressor via a linker symbol.
+LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
-LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
+LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
 endif
 ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
 LDFLAGS_vmlinux += --be8
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
index 30973b7..c943d2e 100644
--- a/arch/arm/boot/compressed/head-shmobile.S
+++ b/arch/arm/boot/compressed/head-shmobile.S
@@ -25,6 +25,36 @@
 	/* load board-specific initialization code */
 #include <mach/zboot.h>
 
+#ifdef CONFIG_ZBOOT_ROM_MMCIF
+	/* Load image from MMC */
+	adr	sp, __tmp_stack + 128
+	ldr	r0, __image_start
+	ldr	r1, __image_end
+	subs	r1, r1, r0
+	ldr	r0, __load_base
+	bl	mmcif_loader
+
+	/* Jump to loaded code */
+	ldr	r0, __loaded
+	ldr	r1, __image_start
+	sub	r0, r0, r1
+	ldr	r1, __load_base
+	add	pc, r0, r1
+
+__image_start:
+	.long	_start
+__image_end:
+	.long	_got_end
+__load_base:
+	.long	CONFIG_MEMORY_START + 0x02000000 @ Load at 32Mb into SDRAM
+__loaded:
+	.long	__continue
+	.align
+__tmp_stack:
+	.space	128
+__continue:
+#endif /* CONFIG_ZBOOT_ROM_MMCIF */
+
 	b	1f
 __atags:@ tag #1
 	.long	12			@ tag->hdr.size = tag_size(tag_core);
diff --git a/arch/arm/boot/compressed/head-vt8500.S b/arch/arm/boot/compressed/head-vt8500.S
new file mode 100644
index 0000000..1dc1e21
--- /dev/null
+++ b/arch/arm/boot/compressed/head-vt8500.S
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/arm/boot/compressed/head-vt8500.S
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * VIA VT8500 specific tweaks. This is merged into head.S by the linker.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+		.section        ".start", "ax"
+
+__VT8500_start:
+	@ Compare the SCC ID register against a list of known values
+	ldr	r1, .SCCID
+	ldr	r3, [r1]
+
+	@ VT8500 override
+	ldr	r4, .VT8500SCC
+	cmp	r3, r4
+	ldreq	r7, .ID_BV07
+	beq	.Lendvt8500
+
+	@ WM8505 override
+	ldr	r4, .WM8505SCC
+	cmp	r3, r4
+	ldreq	r7, .ID_8505
+	beq	.Lendvt8500
+
+	@ Otherwise, leave the bootloader's machine id untouched
+
+.SCCID:
+	.word	0xd8120000
+.VT8500SCC:
+	.word	0x34000102
+.WM8505SCC:
+	.word	0x34260103
+
+.ID_BV07:
+	.word	MACH_TYPE_BV07
+.ID_8505:
+	.word	MACH_TYPE_WM8505_7IN_NETBOOK
+
+.Lendvt8500:
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 7193884..84ac4d6 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -21,7 +21,7 @@
 
 #if defined(CONFIG_DEBUG_ICEDCC)
 
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 		.macro	loadsp, rb, tmp
 		.endm
 		.macro	writeb, ch, rb
@@ -128,14 +128,14 @@ wait:		mrc	p14, 0, pc, c0, c1, 0
 		.arm				@ Always enter in ARM state
 start:
 		.type	start,#function
- THUMB(		adr	r12, BSYM(1f)	)
- THUMB(		bx	r12		)
- THUMB(		.rept	6		)
- ARM(		.rept	8		)
+		.rept	7
 		mov	r0, r0
 		.endr
+   ARM(		mov	r0, r0		)
+   ARM(		b	1f		)
+ THUMB(		adr	r12, BSYM(1f)	)
+ THUMB(		bx	r12		)
 
-		b	1f
 		.word	0x016f2818		@ Magic numbers to help the loader
 		.word	start			@ absolute load/run zImage address
 		.word	_edata			@ zImage end address
@@ -174,9 +174,7 @@ not_angel:
 		 */
 
 		.text
-		adr	r0, LC0
-		ldmia	r0, {r1, r2, r3, r5, r6, r11, ip}
-		ldr	sp, [r0, #28]
+
 #ifdef CONFIG_AUTO_ZRELADDR
 		@ determine final kernel image address
 		mov	r4, pc
@@ -185,35 +183,108 @@ not_angel:
 #else
 		ldr	r4, =zreladdr
 #endif
-		subs	r0, r0, r1		@ calculate the delta offset
 
-						@ if delta is zero, we are
-		beq	not_relocated		@ running at the address we
-						@ were linked at.
+		bl	cache_on
+
+restart:	adr	r0, LC0
+		ldmia	r0, {r1, r2, r3, r5, r6, r9, r11, r12}
+		ldr	sp, [r0, #32]
+
+		/*
+		 * We might be running at a different address.  We need
+		 * to fix up various pointers.
+		 */
+		sub	r0, r0, r1		@ calculate the delta offset
+		add	r5, r5, r0		@ _start
+		add	r6, r6, r0		@ _edata
 
+#ifndef CONFIG_ZBOOT_ROM
+		/* malloc space is above the relocated stack (64k max) */
+		add	sp, sp, r0
+		add	r10, sp, #0x10000
+#else
 		/*
-		 * We're running at a different address.  We need to fix
-		 * up various pointers:
-		 *   r5 - zImage base address (_start)
-		 *   r6 - size of decompressed image
-		 *   r11 - GOT start
-		 *   ip - GOT end
+		 * With ZBOOT_ROM the bss/stack is non relocatable,
+		 * but someone could still run this code from RAM,
+		 * in which case our reference is _edata.
 		 */
-		add	r5, r5, r0
+		mov	r10, r6
+#endif
+
+/*
+ * Check to see if we will overwrite ourselves.
+ *   r4  = final kernel address
+ *   r5  = start of this image
+ *   r9  = size of decompressed image
+ *   r10 = end of this image, including  bss/stack/malloc space if non XIP
+ * We basically want:
+ *   r4 >= r10 -> OK
+ *   r4 + image length <= r5 -> OK
+ */
+		cmp	r4, r10
+		bhs	wont_overwrite
+		add	r10, r4, r9
+		cmp	r10, r5
+		bls	wont_overwrite
+
+/*
+ * Relocate ourselves past the end of the decompressed kernel.
+ *   r5  = start of this image
+ *   r6  = _edata
+ *   r10 = end of the decompressed kernel
+ * Because we always copy ahead, we need to do it from the end and go
+ * backward in case the source and destination overlap.
+ */
+		/* Round up to next 256-byte boundary. */
+		add	r10, r10, #256
+		bic	r10, r10, #255
+
+		sub	r9, r6, r5		@ size to copy
+		add	r9, r9, #31		@ rounded up to a multiple
+		bic	r9, r9, #31		@ ... of 32 bytes
+		add	r6, r9, r5
+		add	r9, r9, r10
+
+1:		ldmdb	r6!, {r0 - r3, r10 - r12, lr}
+		cmp	r6, r5
+		stmdb	r9!, {r0 - r3, r10 - r12, lr}
+		bhi	1b
+
+		/* Preserve offset to relocated code. */
+		sub	r6, r9, r6
+
+		bl	cache_clean_flush
+
+		adr	r0, BSYM(restart)
+		add	r0, r0, r6
+		mov	pc, r0
+
+wont_overwrite:
+/*
+ * If delta is zero, we are running at the address we were linked at.
+ *   r0  = delta
+ *   r2  = BSS start
+ *   r3  = BSS end
+ *   r4  = kernel execution address
+ *   r7  = architecture ID
+ *   r8  = atags pointer
+ *   r11 = GOT start
+ *   r12 = GOT end
+ *   sp  = stack pointer
+ */
+		teq	r0, #0
+		beq	not_relocated
 		add	r11, r11, r0
-		add	ip, ip, r0
+		add	r12, r12, r0
 
 #ifndef CONFIG_ZBOOT_ROM
 		/*
 		 * If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
 		 * we need to fix up pointers into the BSS region.
-		 *   r2 - BSS start
-		 *   r3 - BSS end
-		 *   sp - stack pointer
+		 * Note that the stack pointer has already been fixed up.
 		 */
 		add	r2, r2, r0
 		add	r3, r3, r0
-		add	sp, sp, r0
 
 		/*
 		 * Relocate all entries in the GOT table.
@@ -221,7 +292,7 @@ not_angel:
 1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
 		add	r1, r1, r0		@ table.  This fixes up the
 		str	r1, [r11], #4		@ C references.
-		cmp	r11, ip
+		cmp	r11, r12
 		blo	1b
 #else
 
@@ -234,7 +305,7 @@ not_angel:
 		cmphs	r3, r1			@ _end < entry
 		addlo	r1, r1, r0		@ table.  This fixes up the
 		str	r1, [r11], #4		@ C references.
-		cmp	r11, ip
+		cmp	r11, r12
 		blo	1b
 #endif
 
@@ -246,76 +317,24 @@ not_relocated:	mov	r0, #0
 		cmp	r2, r3
 		blo	1b
 
-		/*
-		 * The C runtime environment should now be setup
-		 * sufficiently.  Turn the cache on, set up some
-		 * pointers, and start decompressing.
-		 */
-		bl	cache_on
-
-		mov	r1, sp			@ malloc space above stack
-		add	r2, sp, #0x10000	@ 64k max
-
 /*
- * Check to see if we will overwrite ourselves.
- *   r4 = final kernel address
- *   r5 = start of this image
- *   r6 = size of decompressed image
- *   r2 = end of malloc space (and therefore this image)
- * We basically want:
- *   r4 >= r2 -> OK
- *   r4 + image length <= r5 -> OK
+ * The C runtime environment should now be setup sufficiently.
+ * Set up some pointers, and start decompressing.
+ *   r4  = kernel execution address
+ *   r7  = architecture ID
+ *   r8  = atags pointer
  */
-		cmp	r4, r2
-		bhs	wont_overwrite
-		add	r0, r4, r6
-		cmp	r0, r5
-		bls	wont_overwrite
-
-		mov	r5, r2			@ decompress after malloc space
-		mov	r0, r5
+		mov	r0, r4
+		mov	r1, sp			@ malloc space above stack
+		add	r2, sp, #0x10000	@ 64k max
 		mov	r3, r7
 		bl	decompress_kernel
-
-		add	r0, r0, #127 + 128	@ alignment + stack
-		bic	r0, r0, #127		@ align the kernel length
-/*
- * r0     = decompressed kernel length
- * r1-r3  = unused
- * r4     = kernel execution address
- * r5     = decompressed kernel start
- * r7     = architecture ID
- * r8     = atags pointer
- * r9-r12,r14 = corrupted
- */
-		add	r1, r5, r0		@ end of decompressed kernel
-		adr	r2, reloc_start
-		ldr	r3, LC1
-		add	r3, r2, r3
-1:		ldmia	r2!, {r9 - r12, r14}	@ copy relocation code
-		stmia	r1!, {r9 - r12, r14}
-		ldmia	r2!, {r9 - r12, r14}
-		stmia	r1!, {r9 - r12, r14}
-		cmp	r2, r3
-		blo	1b
-		mov	sp, r1
-		add	sp, sp, #128		@ relocate the stack
-
 		bl	cache_clean_flush
- ARM(		add	pc, r5, r0		) @ call relocation code
- THUMB(		add	r12, r5, r0		)
- THUMB(		mov	pc, r12			) @ call relocation code
-
-/*
- * We're not in danger of overwriting ourselves.  Do this the simple way.
- *
- * r4     = kernel execution address
- * r7     = architecture ID
- */
-wont_overwrite:	mov	r0, r4
-		mov	r3, r7
-		bl	decompress_kernel
-		b	call_kernel
+		bl	cache_off
+		mov	r0, #0			@ must be zero
+		mov	r1, r7			@ restore architecture number
+		mov	r2, r8			@ restore atags pointer
+		mov	pc, r4			@ call kernel
 
 		.align	2
 		.type	LC0, #object
@@ -323,11 +342,11 @@ LC0:		.word	LC0			@ r1
 		.word	__bss_start		@ r2
 		.word	_end			@ r3
 		.word	_start			@ r5
-		.word	_image_size		@ r6
+		.word	_edata			@ r6
+		.word	_image_size		@ r9
 		.word	_got_start		@ r11
 		.word	_got_end		@ ip
 		.word	user_stack_end		@ sp
-LC1:		.word	reloc_end - reloc_start
 		.size	LC0, . - LC0
 
 #ifdef CONFIG_ARCH_RPC
@@ -353,7 +372,7 @@ params:		ldr	r0, =0x10000100		@ params_phys for RPC
  * On exit,
  *  r0, r1, r2, r3, r9, r10, r12 corrupted
  * This routine must preserve:
- *  r4, r5, r6, r7, r8
+ *  r4, r7, r8
  */
 		.align	5
 cache_on:	mov	r3, #8			@ cache_on function
@@ -551,43 +570,6 @@ __common_mmu_cache_on:
 #endif
 
 /*
- * All code following this line is relocatable.  It is relocated by
- * the above code to the end of the decompressed kernel image and
- * executed there.  During this time, we have no stacks.
- *
- * r0     = decompressed kernel length
- * r1-r3  = unused
- * r4     = kernel execution address
- * r5     = decompressed kernel start
- * r7     = architecture ID
- * r8     = atags pointer
- * r9-r12,r14 = corrupted
- */
-		.align	5
-reloc_start:	add	r9, r5, r0
-		sub	r9, r9, #128		@ do not copy the stack
-		debug_reloc_start
-		mov	r1, r4
-1:
-		.rept	4
-		ldmia	r5!, {r0, r2, r3, r10 - r12, r14}	@ relocate kernel
-		stmia	r1!, {r0, r2, r3, r10 - r12, r14}
-		.endr
-
-		cmp	r5, r9
-		blo	1b
-		mov	sp, r1
-		add	sp, sp, #128		@ relocate the stack
-		debug_reloc_end
-
-call_kernel:	bl	cache_clean_flush
-		bl	cache_off
-		mov	r0, #0			@ must be zero
-		mov	r1, r7			@ restore architecture number
-		mov	r2, r8			@ restore atags pointer
-		mov	pc, r4			@ call kernel
-
-/*
  * Here follow the relocatable cache support functions for the
  * various processors.  This is a generic hook for locating an
  * entry and jumping to an instruction at the specified offset
@@ -791,7 +773,7 @@ proc_types:
  * On exit,
  *  r0, r1, r2, r3, r9, r12 corrupted
  * This routine must preserve:
- *  r4, r6, r7
+ *  r4, r7, r8
  */
 		.align	5
 cache_off:	mov	r3, #12			@ cache_off function
@@ -866,7 +848,7 @@ __armv3_mmu_cache_off:
  * On exit,
  *  r1, r2, r3, r9, r10, r11, r12 corrupted
  * This routine must preserve:
- *  r0, r4, r5, r6, r7
+ *  r4, r6, r7, r8
  */
 		.align	5
 cache_clean_flush:
@@ -1088,7 +1070,6 @@ memdump:	mov	r12, r0
 #endif
 
 		.ltorg
-reloc_end:
 
 		.align
 		.section ".stack", "aw", %nobits
diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c
index e653a6d..4657e87 100644
--- a/arch/arm/boot/compressed/misc.c
+++ b/arch/arm/boot/compressed/misc.c
@@ -36,7 +36,7 @@ extern void error(char *x);
 
 #ifdef CONFIG_DEBUG_ICEDCC
 
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 
 static void icedcc_putc(int ch)
 {
diff --git a/arch/arm/boot/compressed/mmcif-sh7372.c b/arch/arm/boot/compressed/mmcif-sh7372.c
new file mode 100644
index 0000000..e6180af
--- /dev/null
+++ b/arch/arm/boot/compressed/mmcif-sh7372.c
@@ -0,0 +1,87 @@
+/*
+ * sh7372 MMCIF loader
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Simon Horman
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/mmc/sh_mmcif.h>
+#include <mach/mmcif.h>
+
+#define MMCIF_BASE      (void __iomem *)0xe6bd0000
+
+#define PORT84CR	(void __iomem *)0xe6050054
+#define PORT85CR	(void __iomem *)0xe6050055
+#define PORT86CR	(void __iomem *)0xe6050056
+#define PORT87CR	(void __iomem *)0xe6050057
+#define PORT88CR	(void __iomem *)0xe6050058
+#define PORT89CR	(void __iomem *)0xe6050059
+#define PORT90CR	(void __iomem *)0xe605005a
+#define PORT91CR	(void __iomem *)0xe605005b
+#define PORT92CR	(void __iomem *)0xe605005c
+#define PORT99CR	(void __iomem *)0xe6050063
+
+#define SMSTPCR3	(void __iomem *)0xe615013c
+
+/* SH7372 specific MMCIF loader
+ *
+ * loads the zImage from an MMC card starting from block 1.
+ *
+ * The image must be start with a vrl4 header and
+ * the zImage must start at offset 512 of the image. That is,
+ * at block 2 (=byte 1024) on the media
+ *
+ * Use the following line to write the vrl4 formated zImage
+ * to an MMC card
+ * # dd if=vrl4.out of=/dev/sdx bs=512 seek=1
+ */
+asmlinkage void mmcif_loader(unsigned char *buf, unsigned long len)
+{
+	mmcif_init_progress();
+	mmcif_update_progress(MMCIF_PROGRESS_ENTER);
+
+	/* Initialise MMC
+	 * registers: PORT84CR-PORT92CR
+	 *            (MMCD0_0-MMCD0_7,MMCCMD0 Control)
+	 * value: 0x04 - select function 4
+	 */
+	 __raw_writeb(0x04, PORT84CR);
+	 __raw_writeb(0x04, PORT85CR);
+	 __raw_writeb(0x04, PORT86CR);
+	 __raw_writeb(0x04, PORT87CR);
+	 __raw_writeb(0x04, PORT88CR);
+	 __raw_writeb(0x04, PORT89CR);
+	 __raw_writeb(0x04, PORT90CR);
+	 __raw_writeb(0x04, PORT91CR);
+	 __raw_writeb(0x04, PORT92CR);
+
+	/* Initialise MMC
+	 * registers: PORT99CR (MMCCLK0 Control)
+	 * value: 0x10 | 0x04 - enable output | select function 4
+	 */
+	__raw_writeb(0x14, PORT99CR);
+
+	/* Enable clock to MMC hardware block */
+	__raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 12), SMSTPCR3);
+
+	mmcif_update_progress(MMCIF_PROGRESS_INIT);
+
+	/* setup MMCIF hardware */
+	sh_mmcif_boot_init(MMCIF_BASE);
+
+	mmcif_update_progress(MMCIF_PROGRESS_LOAD);
+
+	/* load kernel via MMCIF interface */
+	sh_mmcif_boot_do_read(MMCIF_BASE, 2, /* Kernel is at block 2 */
+			      (len + SH_MMCIF_BBS - 1) / SH_MMCIF_BBS, buf);
+
+
+	/* Disable clock to MMC hardware block */
+	__raw_writel(__raw_readl(SMSTPCR3) & (1 << 12), SMSTPCR3);
+
+	mmcif_update_progress(MMCIF_PROGRESS_DONE);
+}
diff --git a/arch/arm/boot/compressed/vmlinux.lds.in b/arch/arm/boot/compressed/vmlinux.lds.in
index 366a924..5309909 100644
--- a/arch/arm/boot/compressed/vmlinux.lds.in
+++ b/arch/arm/boot/compressed/vmlinux.lds.in
@@ -43,9 +43,6 @@ SECTIONS
 
   _etext = .;
 
-  /* Assume size of decompressed image is 4x the compressed image */
-  _image_size = (_etext - _text) * 4;
-
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 2243772..cb6b041 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -44,6 +44,19 @@ struct gic_chip_data {
 	void __iomem *cpu_base;
 };
 
+/*
+ * Supported arch specific GIC irq extension.
+ * Default make them NULL.
+ */
+struct irq_chip gic_arch_extn = {
+	.irq_ack	= NULL,
+	.irq_mask	= NULL,
+	.irq_unmask	= NULL,
+	.irq_retrigger	= NULL,
+	.irq_set_type	= NULL,
+	.irq_set_wake	= NULL,
+};
+
 #ifndef MAX_GIC_NR
 #define MAX_GIC_NR	1
 #endif
@@ -74,6 +87,8 @@ static inline unsigned int gic_irq(struct irq_data *d)
 static void gic_ack_irq(struct irq_data *d)
 {
 	spin_lock(&irq_controller_lock);
+	if (gic_arch_extn.irq_ack)
+		gic_arch_extn.irq_ack(d);
 	writel(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 	spin_unlock(&irq_controller_lock);
 }
@@ -84,6 +99,8 @@ static void gic_mask_irq(struct irq_data *d)
 
 	spin_lock(&irq_controller_lock);
 	writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
+	if (gic_arch_extn.irq_mask)
+		gic_arch_extn.irq_mask(d);
 	spin_unlock(&irq_controller_lock);
 }
 
@@ -92,6 +109,8 @@ static void gic_unmask_irq(struct irq_data *d)
 	u32 mask = 1 << (d->irq % 32);
 
 	spin_lock(&irq_controller_lock);
+	if (gic_arch_extn.irq_unmask)
+		gic_arch_extn.irq_unmask(d);
 	writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
 	spin_unlock(&irq_controller_lock);
 }
@@ -116,6 +135,9 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 
 	spin_lock(&irq_controller_lock);
 
+	if (gic_arch_extn.irq_set_type)
+		gic_arch_extn.irq_set_type(d, type);
+
 	val = readl(base + GIC_DIST_CONFIG + confoff);
 	if (type == IRQ_TYPE_LEVEL_HIGH)
 		val &= ~confmask;
@@ -141,32 +163,54 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
 	return 0;
 }
 
+static int gic_retrigger(struct irq_data *d)
+{
+	if (gic_arch_extn.irq_retrigger)
+		return gic_arch_extn.irq_retrigger(d);
+
+	return -ENXIO;
+}
+
 #ifdef CONFIG_SMP
-static int
-gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force)
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
+			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
 	unsigned int shift = (d->irq % 4) * 8;
 	unsigned int cpu = cpumask_first(mask_val);
-	u32 val;
-	struct irq_desc *desc;
+	u32 val, mask, bit;
 
-	spin_lock(&irq_controller_lock);
-	desc = irq_to_desc(d->irq);
-	if (desc == NULL) {
-		spin_unlock(&irq_controller_lock);
+	if (cpu >= 8)
 		return -EINVAL;
-	}
+
+	mask = 0xff << shift;
+	bit = 1 << (cpu + shift);
+
+	spin_lock(&irq_controller_lock);
 	d->node = cpu;
-	val = readl(reg) & ~(0xff << shift);
-	val |= 1 << (cpu + shift);
-	writel(val, reg);
+	val = readl(reg) & ~mask;
+	writel(val | bit, reg);
 	spin_unlock(&irq_controller_lock);
 
 	return 0;
 }
 #endif
 
+#ifdef CONFIG_PM
+static int gic_set_wake(struct irq_data *d, unsigned int on)
+{
+	int ret = -ENXIO;
+
+	if (gic_arch_extn.irq_set_wake)
+		ret = gic_arch_extn.irq_set_wake(d, on);
+
+	return ret;
+}
+
+#else
+#define gic_set_wake	NULL
+#endif
+
 static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
 	struct gic_chip_data *chip_data = get_irq_data(irq);
@@ -202,9 +246,11 @@ static struct irq_chip gic_chip = {
 	.irq_mask		= gic_mask_irq,
 	.irq_unmask		= gic_unmask_irq,
 	.irq_set_type		= gic_set_type,
+	.irq_retrigger		= gic_retrigger,
 #ifdef CONFIG_SMP
-	.irq_set_affinity	= gic_set_cpu,
+	.irq_set_affinity	= gic_set_affinity,
 #endif
+	.irq_set_wake		= gic_set_wake,
 };
 
 void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
diff --git a/arch/arm/configs/exynos4_defconfig b/arch/arm/configs/exynos4_defconfig
new file mode 100644
index 0000000..2ffba24
--- /dev/null
+++ b/arch/arm/configs/exynos4_defconfig
@@ -0,0 +1,70 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_EXYNOS4=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_SMDKV310=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_S3C_UART=1
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 2f70428..aeb3af5 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -24,6 +24,7 @@ CONFIG_MACH_OPENRD_ULTIMATE=y
 CONFIG_MACH_NETSPACE_V2=y
 CONFIG_MACH_INETSPACE_V2=y
 CONFIG_MACH_NETSPACE_MAX_V2=y
+CONFIG_MACH_D2NET_V2=y
 CONFIG_MACH_NET2BIG_V2=y
 CONFIG_MACH_NET5BIG_V2=y
 CONFIG_MACH_T5325=y
diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig
deleted file mode 100644
index 5a48f17..0000000
--- a/arch/arm/configs/lpd7a400_defconfig
+++ /dev/null
@@ -1,68 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_EPOLL is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_LH7A40X=y
-CONFIG_MACH_LPD7A400=y
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=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_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_LH7A40X=y
-CONFIG_SERIAL_LH7A40X_CONSOLE=y
-CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig
deleted file mode 100644
index 22d0631..0000000
--- a/arch/arm/configs/lpd7a404_defconfig
+++ /dev/null
@@ -1,81 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_EPOLL is not set
-CONFIG_SLAB=y
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_LH7A40X=y
-CONFIG_MACH_LPD7A404=y
-CONFIG_PREEMPT=y
-CONFIG_DISCONTIGMEM_MANUAL=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=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_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_LH7A40X=y
-CONFIG_SERIAL_LH7A40X_CONSOLE=y
-CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff --git a/arch/arm/configs/mx51_defconfig b/arch/arm/configs/mx51_defconfig
index 9cba68c..e3c9032 100644
--- a/arch/arm/configs/mx51_defconfig
+++ b/arch/arm/configs/mx51_defconfig
@@ -110,7 +110,7 @@ CONFIG_MMC=y
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_SDHCI=m
 CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index ae890ca..019fb7c 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -58,6 +58,7 @@ CONFIG_ARM_ERRATA_411920=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=2
 # CONFIG_LOCAL_TIMERS is not set
 CONFIG_AEABI=y
 CONFIG_LEDS=y
diff --git a/arch/arm/configs/s5p64x0_defconfig b/arch/arm/configs/s5p64x0_defconfig
index 2993ecd..ad6b61b 100644
--- a/arch/arm/configs/s5p64x0_defconfig
+++ b/arch/arm/configs/s5p64x0_defconfig
@@ -10,6 +10,8 @@ CONFIG_S3C_BOOT_ERROR_RESET=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDK6440=y
 CONFIG_MACH_SMDK6450=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_CPU_32v6K=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
diff --git a/arch/arm/configs/s5pv210_defconfig b/arch/arm/configs/s5pv210_defconfig
index 0488a1e..fa98990 100644
--- a/arch/arm/configs/s5pv210_defconfig
+++ b/arch/arm/configs/s5pv210_defconfig
@@ -13,6 +13,8 @@ CONFIG_MACH_AQUILA=y
 CONFIG_MACH_GONI=y
 CONFIG_MACH_SMDKC110=y
 CONFIG_MACH_SMDKV210=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
diff --git a/arch/arm/configs/tegra_defconfig b/arch/arm/configs/tegra_defconfig
new file mode 100644
index 0000000..7a9267e
--- /dev/null
+++ b/arch/arm/configs/tegra_defconfig
@@ -0,0 +1,123 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_TEGRA=y
+CONFIG_MACH_HARMONY=y
+CONFIG_TEGRA_DEBUG_UARTD=y
+CONFIG_ARM_ERRATA_742230=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_VFP=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_INET_ESP=y
+# 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_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=y
+CONFIG_AD525X_DPOT_I2C=y
+CONFIG_ICS932S401=y
+CONFIG_APDS9802ALS=y
+CONFIG_ISL29003=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_SG=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 52d86c4..a5cce24 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
@@ -13,43 +12,89 @@ CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
 CONFIG_MACH_U8500=y
 CONFIG_MACH_U5500=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PHONET=y
+CONFIG_PHONET_PIPECTRLR=y
+# CONFIG_WIRELESS is not set
+CONFIG_CAIF=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AB8500_PWM=y
+CONFIG_SENSORS_BH1780=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_NOMADIK=y
+CONFIG_KEYBOARD_STMPE=y
+CONFIG_KEYBOARD_TC3589X=y
 # CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_BU21013=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AB8500_PONKEY=y
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_NOMADIK=y
+CONFIG_I2C=y
+CONFIG_I2C_NOMADIK=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
+CONFIG_GPIO_STMPE=y
+CONFIG_GPIO_TC3589X=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_MFD_STMPE=y
+CONFIG_MFD_TC3589X=y
+CONFIG_AB8500_CORE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LP5521=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AB8500=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_DMADEVICES=y
+CONFIG_STE_DMA40=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
-CONFIG_INOTIFY=y
+CONFIG_EXT3_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_CONFIGFS_FS=m
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
@@ -58,5 +103,3 @@ CONFIG_DEBUG_INFO=y
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
-CONFIG_CRC_T10DIF=m
-# CONFIG_CRC32 is not set
diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig
new file mode 100644
index 0000000..f2de51f
--- /dev/null
+++ b/arch/arm/configs/vexpress_defconfig
@@ -0,0 +1,140 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CPUSETS=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_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_VEXPRESS=y
+CONFIG_ARCH_VEXPRESS_CA9X4=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M"
+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_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=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_CFI_AMDSTD=y
+CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_MISC_DEVICES=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_SATA_PMP is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_ARMAACI=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/arm/include/asm/a.out-core.h b/arch/arm/include/asm/a.out-core.h
index 93d04ac..92f10cb 100644
--- a/arch/arm/include/asm/a.out-core.h
+++ b/arch/arm/include/asm/a.out-core.h
@@ -32,11 +32,7 @@ static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump)
 	dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	dump->u_ssize = 0;
 
-	dump->u_debugreg[0] = tsk->thread.debug.bp[0].address;
-	dump->u_debugreg[1] = tsk->thread.debug.bp[1].address;
-	dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm;
-	dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm;
-	dump->u_debugreg[4] = tsk->thread.debug.nsaved;
+	memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg));
 
 	if (dump->start_stack < 0x04000000)
 		dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
diff --git a/arch/arm/include/asm/bitops.h b/arch/arm/include/asm/bitops.h
index 7b1bb2b..af54ed1 100644
--- a/arch/arm/include/asm/bitops.h
+++ b/arch/arm/include/asm/bitops.h
@@ -149,14 +149,18 @@ ____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
  */
 
 /*
+ * Native endian assembly bitops.  nr = 0 -> word 0 bit 0.
+ */
+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);
+
+/*
  * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
  */
-extern void _set_bit_le(int nr, volatile unsigned long * p);
-extern void _clear_bit_le(int nr, volatile unsigned long * p);
-extern void _change_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
 extern int _find_first_zero_bit_le(const void * p, unsigned size);
 extern int _find_next_zero_bit_le(const void * p, int size, int offset);
 extern int _find_first_bit_le(const unsigned long *p, unsigned size);
@@ -165,12 +169,6 @@ extern int _find_next_bit_le(const unsigned long *p, int size, int offset);
 /*
  * Big endian assembly bitops.  nr = 0 -> byte 3 bit 0.
  */
-extern void _set_bit_be(int nr, volatile unsigned long * p);
-extern void _clear_bit_be(int nr, volatile unsigned long * p);
-extern void _change_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
 extern int _find_first_zero_bit_be(const void * p, unsigned size);
 extern int _find_next_zero_bit_be(const void * p, int size, int offset);
 extern int _find_first_bit_be(const unsigned long *p, unsigned size);
@@ -180,33 +178,26 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
 /*
  * The __* form of bitops are non-atomic and may be reordered.
  */
-#define	ATOMIC_BITOP_LE(name,nr,p)		\
-	(__builtin_constant_p(nr) ?		\
-	 ____atomic_##name(nr, p) :		\
-	 _##name##_le(nr,p))
-
-#define	ATOMIC_BITOP_BE(name,nr,p)		\
-	(__builtin_constant_p(nr) ?		\
-	 ____atomic_##name(nr, p) :		\
-	 _##name##_be(nr,p))
+#define ATOMIC_BITOP(name,nr,p)			\
+	(__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
 #else
-#define ATOMIC_BITOP_LE(name,nr,p)	_##name##_le(nr,p)
-#define ATOMIC_BITOP_BE(name,nr,p)	_##name##_be(nr,p)
+#define ATOMIC_BITOP(name,nr,p)		_##name(nr,p)
 #endif
 
-#define NONATOMIC_BITOP(name,nr,p)		\
-	(____nonatomic_##name(nr, p))
+/*
+ * Native endian atomic definitions.
+ */
+#define set_bit(nr,p)			ATOMIC_BITOP(set_bit,nr,p)
+#define clear_bit(nr,p)			ATOMIC_BITOP(clear_bit,nr,p)
+#define change_bit(nr,p)		ATOMIC_BITOP(change_bit,nr,p)
+#define test_and_set_bit(nr,p)		ATOMIC_BITOP(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p)	ATOMIC_BITOP(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p)	ATOMIC_BITOP(test_and_change_bit,nr,p)
 
 #ifndef __ARMEB__
 /*
  * These are the little endian, atomic definitions.
  */
-#define set_bit(nr,p)			ATOMIC_BITOP_LE(set_bit,nr,p)
-#define clear_bit(nr,p)			ATOMIC_BITOP_LE(clear_bit,nr,p)
-#define change_bit(nr,p)		ATOMIC_BITOP_LE(change_bit,nr,p)
-#define test_and_set_bit(nr,p)		ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p)	ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p)	ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
 #define find_first_zero_bit(p,sz)	_find_first_zero_bit_le(p,sz)
 #define find_next_zero_bit(p,sz,off)	_find_next_zero_bit_le(p,sz,off)
 #define find_first_bit(p,sz)		_find_first_bit_le(p,sz)
@@ -215,16 +206,9 @@ extern int _find_next_bit_be(const unsigned long *p, int size, int offset);
 #define WORD_BITOFF_TO_LE(x)		((x))
 
 #else
-
 /*
  * These are the big endian, atomic definitions.
  */
-#define set_bit(nr,p)			ATOMIC_BITOP_BE(set_bit,nr,p)
-#define clear_bit(nr,p)			ATOMIC_BITOP_BE(clear_bit,nr,p)
-#define change_bit(nr,p)		ATOMIC_BITOP_BE(change_bit,nr,p)
-#define test_and_set_bit(nr,p)		ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p)	ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p)	ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
 #define find_first_zero_bit(p,sz)	_find_first_zero_bit_be(p,sz)
 #define find_next_zero_bit(p,sz,off)	_find_next_zero_bit_be(p,sz,off)
 #define find_first_bit(p,sz)		_find_first_bit_be(p,sz)
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 3acd8fa..d5d8d5c 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -12,7 +12,7 @@
 
 #include <linux/mm.h>
 
-#include <asm/glue.h>
+#include <asm/glue-cache.h>
 #include <asm/shmparam.h>
 #include <asm/cachetype.h>
 #include <asm/outercache.h>
@@ -20,123 +20,6 @@
 #define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
- *	Cache Model
- *	===========
- */
-#undef _CACHE
-#undef MULTI_CACHE
-
-#if defined(CONFIG_CPU_CACHE_V3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_CACHE_V4)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v4
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
-    defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \
-    defined(CONFIG_CPU_ARM1026)
-# define MULTI_CACHE 1
-#endif
-
-#if defined(CONFIG_CPU_FA526)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE fa
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM926T)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm926
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM940T)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm940
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM946E)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm946
-# endif
-#endif
-
-#if defined(CONFIG_CPU_CACHE_V4WB)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v4wb
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSCALE)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE xscale
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSC3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE xsc3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_MOHAWK)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE mohawk
-# endif
-#endif
-
-#if defined(CONFIG_CPU_FEROCEON)
-# define MULTI_CACHE 1
-#endif
-
-#if defined(CONFIG_CPU_V6)
-//# ifdef _CACHE
-#  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v6
-//# endif
-#endif
-
-#if defined(CONFIG_CPU_V7)
-//# ifdef _CACHE
-#  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v7
-//# endif
-#endif
-
-#if !defined(_CACHE) && !defined(MULTI_CACHE)
-#error Unknown cache maintainence model
-#endif
-
-/*
  * This flag is used to indicate that the page pointed to by a pte is clean
  * and does not require cleaning before returning it to the user.
  */
@@ -249,19 +132,11 @@ extern struct cpu_cache_fns cpu_cache;
  * visible to the CPU.
  */
 #define dmac_map_area			cpu_cache.dma_map_area
-#define dmac_unmap_area		cpu_cache.dma_unmap_area
+#define dmac_unmap_area			cpu_cache.dma_unmap_area
 #define dmac_flush_range		cpu_cache.dma_flush_range
 
 #else
 
-#define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
-#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
-#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
-#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
-#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
-#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
-#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
-
 extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
@@ -276,10 +151,6 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
-#define dmac_map_area			__glue(_CACHE,_dma_map_area)
-#define dmac_unmap_area		__glue(_CACHE,_dma_unmap_area)
-#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
-
 extern void dmac_map_area(const void *, size_t, int);
 extern void dmac_unmap_area(const void *, size_t, int);
 extern void dmac_flush_range(const void *, const void *);
@@ -316,7 +187,8 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
  * Optimized __flush_icache_all for the common cases. Note that UP ARMv7
  * will fall through to use __flush_icache_all_generic.
  */
-#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) ||		\
+#if (defined(CONFIG_CPU_V7) && \
+     (defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K))) || \
 	defined(CONFIG_SMP_ON_UP)
 #define __flush_icache_preferred	__cpuc_flush_icache_all
 #elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
diff --git a/arch/arm/include/asm/cpu-multi32.h b/arch/arm/include/asm/cpu-multi32.h
deleted file mode 100644
index e2b5b0b..0000000
--- a/arch/arm/include/asm/cpu-multi32.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  arch/arm/include/asm/cpu-multi32.h
- *
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <asm/page.h>
-
-struct mm_struct;
-
-/*
- * Don't change this structure - ASM code
- * relies on it.
- */
-extern struct processor {
-	/* MISC
-	 * get data abort address/flags
-	 */
-	void (*_data_abort)(unsigned long pc);
-	/*
-	 * Retrieve prefetch fault address
-	 */
-	unsigned long (*_prefetch_abort)(unsigned long lr);
-	/*
-	 * Set up any processor specifics
-	 */
-	void (*_proc_init)(void);
-	/*
-	 * Disable any processor specifics
-	 */
-	void (*_proc_fin)(void);
-	/*
-	 * Special stuff for a reset
-	 */
-	void (*reset)(unsigned long addr) __attribute__((noreturn));
-	/*
-	 * Idle the processor
-	 */
-	int (*_do_idle)(void);
-	/*
-	 * Processor architecture specific
-	 */
-	/*
-	 * clean a virtual address range from the
-	 * D-cache without flushing the cache.
-	 */
-	void (*dcache_clean_area)(void *addr, int size);
-
-	/*
-	 * Set the page table
-	 */
-	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
-	/*
-	 * Set a possibly extended PTE.  Non-extended PTEs should
-	 * ignore 'ext'.
-	 */
-	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
-} processor;
-
-#define cpu_proc_init()			processor._proc_init()
-#define cpu_proc_fin()			processor._proc_fin()
-#define cpu_reset(addr)			processor.reset(addr)
-#define cpu_do_idle()			processor._do_idle()
-#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
-#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
-#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
diff --git a/arch/arm/include/asm/cpu-single.h b/arch/arm/include/asm/cpu-single.h
deleted file mode 100644
index f073a6d..0000000
--- a/arch/arm/include/asm/cpu-single.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *  arch/arm/include/asm/cpu-single.h
- *
- *  Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-/*
- * Single CPU
- */
-#ifdef __STDC__
-#define __catify_fn(name,x)	name##x
-#else
-#define __catify_fn(name,x)	name/**/x
-#endif
-#define __cpu_fn(name,x)	__catify_fn(name,x)
-
-/*
- * If we are supporting multiple CPUs, then we must use a table of
- * function pointers for this lot.  Otherwise, we can optimise the
- * table away.
- */
-#define cpu_proc_init			__cpu_fn(CPU_NAME,_proc_init)
-#define cpu_proc_fin			__cpu_fn(CPU_NAME,_proc_fin)
-#define cpu_reset			__cpu_fn(CPU_NAME,_reset)
-#define cpu_do_idle			__cpu_fn(CPU_NAME,_do_idle)
-#define cpu_dcache_clean_area		__cpu_fn(CPU_NAME,_dcache_clean_area)
-#define cpu_do_switch_mm		__cpu_fn(CPU_NAME,_switch_mm)
-#define cpu_set_pte_ext			__cpu_fn(CPU_NAME,_set_pte_ext)
-
-#include <asm/page.h>
-
-struct mm_struct;
-
-/* declare all the functions as extern */
-extern void cpu_proc_init(void);
-extern void cpu_proc_fin(void);
-extern int cpu_do_idle(void);
-extern void cpu_dcache_clean_area(void *, int);
-extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
-extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
-extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 20ae96c..ed5bc9e 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -23,6 +23,8 @@
 #define CPUID_EXT_ISAR4	"c2, 4"
 #define CPUID_EXT_ISAR5	"c2, 5"
 
+extern unsigned int processor_id;
+
 #ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)							\
 	({								\
@@ -43,7 +45,6 @@
 		__val;							\
 	})
 #else
-extern unsigned int processor_id;
 #define read_cpuid(reg) (processor_id)
 #define read_cpuid_ext(reg) 0
 #endif
diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h
new file mode 100644
index 0000000..de53547
--- /dev/null
+++ b/arch/arm/include/asm/fncpy.h
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/include/asm/fncpy.h - helper macros for function body copying
+ *
+ * Copyright (C) 2011 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ */
+
+/*
+ * These macros are intended for use when there is a need to copy a low-level
+ * function body into special memory.
+ *
+ * For example, when reconfiguring the SDRAM controller, the code doing the
+ * reconfiguration may need to run from SRAM.
+ *
+ * NOTE: that the copied function body must be entirely self-contained and
+ * position-independent in order for this to work properly.
+ *
+ * NOTE: in order for embedded literals and data to get referenced correctly,
+ * the alignment of functions must be preserved when copying.  To ensure this,
+ * the source and destination addresses for fncpy() must be aligned to a
+ * multiple of 8 bytes: you will be get a BUG() if this condition is not met.
+ * You will typically need a ".align 3" directive in the assembler where the
+ * function to be copied is defined, and ensure that your allocator for the
+ * destination buffer returns 8-byte-aligned pointers.
+ *
+ * Typical usage example:
+ *
+ * extern int f(args);
+ * extern uint32_t size_of_f;
+ * int (*copied_f)(args);
+ * void *sram_buffer;
+ *
+ * copied_f = fncpy(sram_buffer, &f, size_of_f);
+ *
+ * ... later, call the function: ...
+ *
+ * copied_f(args);
+ *
+ * The size of the function to be copied can't be determined from C:
+ * this must be determined by other means, such as adding assmbler directives
+ * in the file where f is defined.
+ */
+
+#ifndef __ASM_FNCPY_H
+#define __ASM_FNCPY_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/bug.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Minimum alignment requirement for the source and destination addresses
+ * for function copying.
+ */
+#define FNCPY_ALIGN 8
+
+#define fncpy(dest_buf, funcp, size) ({					\
+	uintptr_t __funcp_address;					\
+	typeof(funcp) __result;						\
+									\
+	asm("" : "=r" (__funcp_address) : "0" (funcp));			\
+									\
+	/*								\
+	 * Ensure alignment of source and destination addresses,	\
+	 * disregarding the function's Thumb bit:			\
+	 */								\
+	BUG_ON((uintptr_t)(dest_buf) & (FNCPY_ALIGN - 1) ||		\
+		(__funcp_address & ~(uintptr_t)1 & (FNCPY_ALIGN - 1)));	\
+									\
+	memcpy(dest_buf, (void const *)(__funcp_address & ~1), size);	\
+	flush_icache_range((unsigned long)(dest_buf),			\
+		(unsigned long)(dest_buf) + (size));			\
+									\
+	asm("" : "=r" (__result)					\
+		: "0" ((uintptr_t)(dest_buf) | (__funcp_address & 1)));	\
+									\
+	__result;							\
+})
+
+#endif /* !__ASM_FNCPY_H */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index b33fe70..199a6b6 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -35,7 +35,7 @@
 	: "cc", "memory")
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -46,7 +46,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();	/* implies preempt_disable() */
@@ -88,36 +88,35 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	pagefault_disable();	/* implies preempt_disable() */
-
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	" T(ldr) "	%0, [%3]\n"
-	"	teq	%0, %1\n"
+	"1:	" T(ldr) "	%1, [%4]\n"
+	"	teq	%1, %2\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	" T(streq) "	%2, [%3]\n"
+	"2:	" T(streq) "	%3, [%4]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
 	"	.long	1b, 4f, 2b, 4f\n"
 	"	.popsection\n"
 	"	.pushsection .fixup,\"ax\"\n"
-	"4:	mov	%0, %4\n"
+	"4:	mov	%0, %5\n"
 	"	b	3b\n"
 	"	.popsection"
-	: "=&r" (val)
+	: "+r" (ret), "=&r" (val)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	pagefault_enable();	/* subsumes preempt_enable() */
-
-	return val;
+	*uval = val;
+	return ret;
 }
 
 #endif /* !SMP */
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
new file mode 100644
index 0000000..c7afbc5
--- /dev/null
+++ b/arch/arm/include/asm/glue-cache.h
@@ -0,0 +1,146 @@
+/*
+ *  arch/arm/include/asm/glue-cache.h
+ *
+ *  Copyright (C) 1999-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_CACHE_H
+#define ASM_GLUE_CACHE_H
+
+#include <asm/glue.h>
+
+/*
+ *	Cache Model
+ *	===========
+ */
+#undef _CACHE
+#undef MULTI_CACHE
+
+#if defined(CONFIG_CPU_CACHE_V3)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
+    defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \
+    defined(CONFIG_CPU_ARM1026)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_FA526)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE fa
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM926T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm926
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM940T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm940
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM946E)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm946
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4WB)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4wb
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSCALE)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xscale
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSC3)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xsc3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_MOHAWK)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE mohawk
+# endif
+#endif
+
+#if defined(CONFIG_CPU_FEROCEON)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v6
+//# endif
+#endif
+
+#if defined(CONFIG_CPU_V7)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v7
+//# endif
+#endif
+
+#if !defined(_CACHE) && !defined(MULTI_CACHE)
+#error Unknown cache maintainence model
+#endif
+
+#ifndef MULTI_CACHE
+#define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
+#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
+#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
+#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
+#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
+#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
+
+#define dmac_map_area			__glue(_CACHE,_dma_map_area)
+#define dmac_unmap_area			__glue(_CACHE,_dma_unmap_area)
+#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue-df.h b/arch/arm/include/asm/glue-df.h
new file mode 100644
index 0000000..354d571
--- /dev/null
+++ b/arch/arm/include/asm/glue-df.h
@@ -0,0 +1,110 @@
+/*
+ *  arch/arm/include/asm/glue-df.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000-2002 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_DF_H
+#define ASM_GLUE_DF_H
+
+#include <asm/glue.h>
+
+/*
+ *	Data Abort Model
+ *	================
+ *
+ *	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
+ *	  xscale	- ARMv5 with Thumb with Xscale extensions
+ *	  v6_early	- ARMv6 generic early abort handler
+ *	  v7_early	- ARMv7 generic early abort handler
+ */
+#undef CPU_DABORT_HANDLER
+#undef MULTI_DABORT
+
+#if defined(CONFIG_CPU_ARM610)
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM710)
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_LV4T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4t_late_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV4
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV4T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4t_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV5TJ
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v5tj_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV5T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v5t_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV6
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v6_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV7
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v7_early_abort
+# endif
+#endif
+
+#ifndef CPU_DABORT_HANDLER
+#error Unknown data abort handler type
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue-pf.h b/arch/arm/include/asm/glue-pf.h
new file mode 100644
index 0000000..d385f37
--- /dev/null
+++ b/arch/arm/include/asm/glue-pf.h
@@ -0,0 +1,57 @@
+/*
+ *  arch/arm/include/asm/glue-pf.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000-2002 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_PF_H
+#define ASM_GLUE_PF_H
+
+#include <asm/glue.h>
+
+/*
+ *	Prefetch Abort Model
+ *	================
+ *
+ *	We have the following to choose from:
+ *	  legacy	- no IFSR, no IFAR
+ *	  v6		- ARMv6: IFSR, no IFAR
+ *	  v7		- ARMv7: IFSR and IFAR
+ */
+
+#undef CPU_PABORT_HANDLER
+#undef MULTI_PABORT
+
+#ifdef CONFIG_CPU_PABRT_LEGACY
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER legacy_pabort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_PABRT_V6
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER v6_pabort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_PABRT_V7
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER v7_pabort
+# endif
+#endif
+
+#ifndef CPU_PABORT_HANDLER
+#error Unknown prefetch abort handler type
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue-proc.h b/arch/arm/include/asm/glue-proc.h
new file mode 100644
index 0000000..e2be7f1
--- /dev/null
+++ b/arch/arm/include/asm/glue-proc.h
@@ -0,0 +1,264 @@
+/*
+ *  arch/arm/include/asm/glue-proc.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000 Deep Blue Solutions Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_GLUE_PROC_H
+#define ASM_GLUE_PROC_H
+
+#include <asm/glue.h>
+
+/*
+ * Work out if we need multiple CPU support
+ */
+#undef MULTI_CPU
+#undef CPU_NAME
+
+/*
+ * CPU_NAME - the prefix for CPU related functions
+ */
+
+#ifdef CONFIG_CPU_ARM610
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm6
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM7TDMI
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm7tdmi
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM710
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm7
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM720T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm720
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM740T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm740
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM9TDMI
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm9tdmi
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM920T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm920
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM922T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm922
+# endif
+#endif
+
+#ifdef CONFIG_CPU_FA526
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_fa526
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM925T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm925
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM926T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm926
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM940T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm940
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM946E
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm946
+# endif
+#endif
+
+#ifdef CONFIG_CPU_SA110
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_sa110
+# endif
+#endif
+
+#ifdef CONFIG_CPU_SA1100
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_sa1100
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1020
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1020
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1020E
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1020e
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1022
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1022
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1026
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1026
+# endif
+#endif
+
+#ifdef CONFIG_CPU_XSCALE
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_xscale
+# endif
+#endif
+
+#ifdef CONFIG_CPU_XSC3
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_xsc3
+# endif
+#endif
+
+#ifdef CONFIG_CPU_MOHAWK
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_mohawk
+# endif
+#endif
+
+#ifdef CONFIG_CPU_FEROCEON
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_feroceon
+# endif
+#endif
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v6
+# endif
+#endif
+
+#ifdef CONFIG_CPU_V7
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7
+# endif
+#endif
+
+#ifndef MULTI_CPU
+#define cpu_proc_init			__glue(CPU_NAME,_proc_init)
+#define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
+#define cpu_reset			__glue(CPU_NAME,_reset)
+#define cpu_do_idle			__glue(CPU_NAME,_do_idle)
+#define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
+#define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
+#define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
+#define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
+#define cpu_do_resume			__glue(CPU_NAME,_do_resume)
+#endif
+
+#endif
diff --git a/arch/arm/include/asm/glue.h b/arch/arm/include/asm/glue.h
index 234a3fc..0ec35d1 100644
--- a/arch/arm/include/asm/glue.h
+++ b/arch/arm/include/asm/glue.h
@@ -15,7 +15,6 @@
  */
 #ifdef __KERNEL__
 
-
 #ifdef __STDC__
 #define ____glue(name,fn)	name##fn
 #else
@@ -23,141 +22,4 @@
 #endif
 #define __glue(name,fn)		____glue(name,fn)
 
-
-
-/*
- *	Data Abort Model
- *	================
- *
- *	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
- *	  xscale	- ARMv5 with Thumb with Xscale extensions
- *	  v6_early	- ARMv6 generic early abort handler
- *	  v7_early	- ARMv7 generic early abort handler
- */
-#undef CPU_DABORT_HANDLER
-#undef MULTI_DABORT
-
-#if defined(CONFIG_CPU_ARM610)
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM710)
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_LV4T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4t_late_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV4
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV4T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4t_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV5TJ
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v5tj_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV5T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v5t_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV6
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v6_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV7
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v7_early_abort
-# endif
-#endif
-
-#ifndef CPU_DABORT_HANDLER
-#error Unknown data abort handler type
-#endif
-
-/*
- *	Prefetch Abort Model
- *	================
- *
- *	We have the following to choose from:
- *	  legacy	- no IFSR, no IFAR
- *	  v6		- ARMv6: IFSR, no IFAR
- *	  v7		- ARMv7: IFSR and IFAR
- */
-
-#undef CPU_PABORT_HANDLER
-#undef MULTI_PABORT
-
-#ifdef CONFIG_CPU_PABRT_LEGACY
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER legacy_pabort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_PABRT_V6
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER v6_pabort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_PABRT_V7
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER v7_pabort
-# endif
-#endif
-
-#ifndef CPU_PABORT_HANDLER
-#error Unknown prefetch abort handler type
-#endif
-
 #endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 84557d3..0691f9d 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -34,6 +34,7 @@
 
 #ifndef __ASSEMBLY__
 extern void __iomem *gic_cpu_base_addr;
+extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
 void gic_secondary_init(unsigned int);
diff --git a/arch/arm/include/asm/highmem.h b/arch/arm/include/asm/highmem.h
index 7080e2c..a4edd19 100644
--- a/arch/arm/include/asm/highmem.h
+++ b/arch/arm/include/asm/highmem.h
@@ -19,11 +19,36 @@
 
 extern pte_t *pkmap_page_table;
 
+extern void *kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+/*
+ * The reason for kmap_high_get() is to ensure that the currently kmap'd
+ * page usage count does not decrease to zero while we're using its
+ * existing virtual mapping in an atomic context.  With a VIVT cache this
+ * is essential to do, but with a VIPT cache this is only an optimization
+ * so not to pay the price of establishing a second mapping if an existing
+ * one can be used.  However, on platforms without hardware TLB maintenance
+ * broadcast, we simply cannot use ARCH_NEEDS_KMAP_HIGH_GET at all since
+ * the locking involved must also disable IRQs which is incompatible with
+ * the IPI mechanism used by global TLB operations.
+ */
 #define ARCH_NEEDS_KMAP_HIGH_GET
+#if defined(CONFIG_SMP) && defined(CONFIG_CPU_TLB_V6)
+#undef ARCH_NEEDS_KMAP_HIGH_GET
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_CPU_CACHE_VIVT)
+#error "The sum of features in your kernel config cannot be supported together"
+#endif
+#endif
 
-extern void *kmap_high(struct page *page);
+#ifdef ARCH_NEEDS_KMAP_HIGH_GET
 extern void *kmap_high_get(struct page *page);
-extern void kunmap_high(struct page *page);
+#else
+static inline void *kmap_high_get(struct page *page)
+{
+	return NULL;
+}
+#endif
 
 /*
  * The following functions are already defined by <linux/highmem.h>
diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h
index c0094d8..c2b9b4b 100644
--- a/arch/arm/include/asm/kexec.h
+++ b/arch/arm/include/asm/kexec.h
@@ -50,6 +50,9 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 	}
 }
 
+/* Function pointer to optional machine-specific reinitialization */
+extern void (*kexec_reinit)(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* CONFIG_KEXEC */
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index 22ac140..febe495 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -34,4 +34,35 @@ 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/memory.h b/arch/arm/include/asm/memory.h
index d0ee74b..431077c 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -15,6 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/const.h>
+#include <linux/types.h>
 #include <mach/memory.h>
 #include <asm/sizes.h>
 
@@ -133,20 +134,10 @@
 #endif
 
 /*
- * Physical vs virtual RAM address space conversion.  These are
- * private definitions which should NOT be used outside memory.h
- * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
- */
-#ifndef __virt_to_phys
-#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
-#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
-#endif
-
-/*
  * Convert a physical address to a Page Frame Number and back
  */
-#define	__phys_to_pfn(paddr)	((paddr) >> PAGE_SHIFT)
-#define	__pfn_to_phys(pfn)	((pfn) << PAGE_SHIFT)
+#define	__phys_to_pfn(paddr)	((unsigned long)((paddr) >> PAGE_SHIFT))
+#define	__pfn_to_phys(pfn)	((phys_addr_t)(pfn) << PAGE_SHIFT)
 
 /*
  * Convert a page to/from a physical address
@@ -157,6 +148,62 @@
 #ifndef __ASSEMBLY__
 
 /*
+ * Physical vs virtual RAM address space conversion.  These are
+ * private definitions which should NOT be used outside memory.h
+ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#ifndef __virt_to_phys
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+
+/*
+ * Constants used to force the right instruction encodings and shifts
+ * so that all we need to do is modify the 8-bit constant field.
+ */
+#define __PV_BITS_31_24	0x81000000
+#define __PV_BITS_23_16	0x00810000
+
+extern unsigned long __pv_phys_offset;
+#define PHYS_OFFSET __pv_phys_offset
+
+#define __pv_stub(from,to,instr,type)			\
+	__asm__("@ __pv_stub\n"				\
+	"1:	" instr "	%0, %1, %2\n"		\
+	"	.pushsection .pv_table,\"a\"\n"		\
+	"	.long	1b\n"				\
+	"	.popsection\n"				\
+	: "=r" (to)					\
+	: "r" (from), "I" (type))
+
+static inline unsigned long __virt_to_phys(unsigned long x)
+{
+	unsigned long t;
+	__pv_stub(x, t, "add", __PV_BITS_31_24);
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	__pv_stub(t, t, "add", __PV_BITS_23_16);
+#endif
+	return t;
+}
+
+static inline unsigned long __phys_to_virt(unsigned long x)
+{
+	unsigned long t;
+	__pv_stub(x, t, "sub", __PV_BITS_31_24);
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	__pv_stub(t, t, "sub", __PV_BITS_23_16);
+#endif
+	return t;
+}
+#else
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+#endif
+#endif
+
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET	PLAT_PHYS_OFFSET
+#endif
+
+/*
  * The DMA mask corresponding to the maximum bus address allocatable
  * using GFP_DMA.  The default here places no restriction on DMA
  * allocations.  This must be the smallest DMA mask in the system,
@@ -188,12 +235,12 @@
  * translation for translating DMA addresses.  Use the driver
  * DMA support - see dma-mapping.h.
  */
-static inline unsigned long virt_to_phys(const volatile void *x)
+static inline phys_addr_t virt_to_phys(const volatile void *x)
 {
 	return __virt_to_phys((unsigned long)(x));
 }
 
-static inline void *phys_to_virt(unsigned long x)
+static inline void *phys_to_virt(phys_addr_t x)
 {
 	return (void *)(__phys_to_virt((unsigned long)(x)));
 }
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 12c8e68..543b449 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -25,8 +25,31 @@ struct mod_arch_specific {
 };
 
 /*
- * Include the ARM architecture version.
+ * Add the ARM architecture version to the version magic string
  */
-#define MODULE_ARCH_VERMAGIC	"ARMv" __stringify(__LINUX_ARM_ARCH__) " "
+#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " "
+
+/* Add __virt_to_phys patching state as well */
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+#define MODULE_ARCH_VERMAGIC_P2V "p2v16 "
+#else
+#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
+#endif
+#else
+#define MODULE_ARCH_VERMAGIC_P2V ""
+#endif
+
+/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */
+#ifdef CONFIG_THUMB2_KERNEL
+#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 "
+#else
+#define MODULE_ARCH_VERMAGIC_ARMTHUMB ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+	MODULE_ARCH_VERMAGIC_ARMVSN \
+	MODULE_ARCH_VERMAGIC_ARMTHUMB \
+	MODULE_ARCH_VERMAGIC_P2V
 
 #endif /* _ASM_ARM_MODULE_H */
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index fc19009..348d513 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -31,6 +31,7 @@ struct outer_cache_fns {
 #ifdef CONFIG_OUTER_CACHE_SYNC
 	void (*sync)(void);
 #endif
+	void (*set_debug)(unsigned long);
 };
 
 #ifdef CONFIG_OUTER_CACHE
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 8ccea01..7544ce6 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -12,11 +12,25 @@
 #ifndef __ARM_PMU_H__
 #define __ARM_PMU_H__
 
+#include <linux/interrupt.h>
+
 enum arm_pmu_type {
 	ARM_PMU_DEVICE_CPU	= 0,
 	ARM_NUM_PMU_DEVICES,
 };
 
+/*
+ * struct arm_pmu_platdata - ARM PMU platform data
+ *
+ * @handle_irq: an optional handler which will be called from the interrupt and
+ * passed the address of the low level handler, and can be used to implement
+ * any platform specific handling before or after calling it.
+ */
+struct arm_pmu_platdata {
+	irqreturn_t (*handle_irq)(int irq, void *dev,
+				  irq_handler_t pmu_handler);
+};
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 /**
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index 8fdae9b..8ec535e 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -13,250 +13,86 @@
 
 #ifdef __KERNEL__
 
+#include <asm/glue-proc.h>
+#include <asm/page.h>
 
-/*
- * Work out if we need multiple CPU support
- */
-#undef MULTI_CPU
-#undef CPU_NAME
+#ifndef __ASSEMBLY__
+
+struct mm_struct;
 
 /*
- * CPU_NAME - the prefix for CPU related functions
+ * Don't change this structure - ASM code relies on it.
  */
-
-#ifdef CONFIG_CPU_ARM610
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm6
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM7TDMI
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm7tdmi
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM710
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm7
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM720T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm720
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM740T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm740
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM9TDMI
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm9tdmi
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM920T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm920
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM922T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm922
-# endif
-#endif
-
-#ifdef CONFIG_CPU_FA526
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_fa526
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM925T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm925
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM926T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm926
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM940T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm940
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM946E
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm946
-# endif
-#endif
-
-#ifdef CONFIG_CPU_SA110
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_sa110
-# endif
-#endif
-
-#ifdef CONFIG_CPU_SA1100
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_sa1100
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1020
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1020
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1020E
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1020e
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1022
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1022
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1026
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1026
-# endif
-#endif
-
-#ifdef CONFIG_CPU_XSCALE
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_xscale
-# endif
-#endif
-
-#ifdef CONFIG_CPU_XSC3
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_xsc3
-# endif
-#endif
-
-#ifdef CONFIG_CPU_MOHAWK
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_mohawk
-# endif
-#endif
-
-#ifdef CONFIG_CPU_FEROCEON
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_feroceon
-# endif
-#endif
-
-#ifdef CONFIG_CPU_V6
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v6
-# endif
-#endif
-
-#ifdef CONFIG_CPU_V7
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v7
-# endif
-#endif
-
-#ifndef __ASSEMBLY__
+extern struct processor {
+	/* MISC
+	 * get data abort address/flags
+	 */
+	void (*_data_abort)(unsigned long pc);
+	/*
+	 * Retrieve prefetch fault address
+	 */
+	unsigned long (*_prefetch_abort)(unsigned long lr);
+	/*
+	 * Set up any processor specifics
+	 */
+	void (*_proc_init)(void);
+	/*
+	 * Disable any processor specifics
+	 */
+	void (*_proc_fin)(void);
+	/*
+	 * Special stuff for a reset
+	 */
+	void (*reset)(unsigned long addr) __attribute__((noreturn));
+	/*
+	 * Idle the processor
+	 */
+	int (*_do_idle)(void);
+	/*
+	 * Processor architecture specific
+	 */
+	/*
+	 * clean a virtual address range from the
+	 * D-cache without flushing the cache.
+	 */
+	void (*dcache_clean_area)(void *addr, int size);
+
+	/*
+	 * Set the page table
+	 */
+	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
+	/*
+	 * Set a possibly extended PTE.  Non-extended PTEs should
+	 * ignore 'ext'.
+	 */
+	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
+
+	/* Suspend/resume */
+	unsigned int suspend_size;
+	void (*do_suspend)(void *);
+	void (*do_resume)(void *);
+} processor;
 
 #ifndef MULTI_CPU
-#include <asm/cpu-single.h>
+extern void cpu_proc_init(void);
+extern void cpu_proc_fin(void);
+extern int cpu_do_idle(void);
+extern void cpu_dcache_clean_area(void *, int);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #else
-#include <asm/cpu-multi32.h>
+#define cpu_proc_init()			processor._proc_init()
+#define cpu_proc_fin()			processor._proc_fin()
+#define cpu_reset(addr)			processor.reset(addr)
+#define cpu_do_idle()			processor._do_idle()
+#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
+#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
+#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
+extern void cpu_resume(void);
+
 #include <asm/memory.h>
 
 #ifdef CONFIG_MMU
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 67357ba..b2d9df5 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -29,19 +29,7 @@
 #define STACK_TOP_MAX	TASK_SIZE
 #endif
 
-union debug_insn {
-	u32	arm;
-	u16	thumb;
-};
-
-struct debug_entry {
-	u32			address;
-	union debug_insn	insn;
-};
-
 struct debug_info {
-	int			nsaved;
-	struct debug_entry	bp[2];
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 	struct perf_event	*hbp[ARM_MAX_HBP_SLOTS];
 #endif
@@ -95,7 +83,7 @@ extern void release_thread(struct task_struct *);
 
 unsigned long get_wchan(struct task_struct *p);
 
-#if __LINUX_ARM_ARCH__ == 6
+#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327)
 #define cpu_relax()			smp_mb()
 #else
 #define cpu_relax()			barrier()
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 783d50f..a8ff22b 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -130,8 +130,6 @@ struct pt_regs {
 
 #ifdef __KERNEL__
 
-#define arch_has_single_step()	(1)
-
 #define user_mode(regs)	\
 	(((regs)->ARM_cpsr & 0xf) == 0)
 
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index f1e5a9b..da8b52e 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -192,11 +192,7 @@ static struct tagtable __tagtable_##fn __tag = { tag, fn }
 /*
  * Memory map description
  */
-#ifdef CONFIG_ARCH_LH7A40X
-# define NR_BANKS 16
-#else
-# define NR_BANKS 8
-#endif
+#define NR_BANKS 8
 
 struct membank {
 	unsigned long start;
diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 2376835..4eb6d00 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -1,7 +1,14 @@
 #ifndef __ASMARM_ARCH_SCU_H
 #define __ASMARM_ARCH_SCU_H
 
+#define SCU_PM_NORMAL	0
+#define SCU_PM_DORMANT	2
+#define SCU_PM_POWEROFF	3
+
+#ifndef __ASSEMBLER__
 unsigned int scu_get_core_count(void __iomem *);
 void scu_enable(void __iomem *);
+int scu_power_mode(void __iomem *, unsigned int);
+#endif
 
 #endif
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index 17eb355..fdd3820 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -5,17 +5,52 @@
 #error SMP not supported on pre-ARMv6 CPUs
 #endif
 
+/*
+ * sev and wfe are ARMv6K extensions.  Uniprocessor ARMv6 may not have the K
+ * extensions, so when running on UP, we have to patch these instructions away.
+ */
+#define ALT_SMP(smp, up)					\
+	"9998:	" smp "\n"					\
+	"	.pushsection \".alt.smp.init\", \"a\"\n"	\
+	"	.long	9998b\n"				\
+	"	" up "\n"					\
+	"	.popsection\n"
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define SEV		ALT_SMP("sev.w", "nop.w")
+/*
+ * For Thumb-2, special care is needed to ensure that the conditional WFE
+ * instruction really does assemble to exactly 4 bytes (as required by
+ * the SMP_ON_UP fixup code).   By itself "wfene" might cause the
+ * assembler to insert a extra (16-bit) IT instruction, depending on the
+ * presence or absence of neighbouring conditional instructions.
+ *
+ * To avoid this unpredictableness, an approprite IT is inserted explicitly:
+ * the assembler won't change IT instructions which are explicitly present
+ * in the input.
+ */
+#define WFE(cond)	ALT_SMP(		\
+	"it " cond "\n\t"			\
+	"wfe" cond ".n",			\
+						\
+	"nop.w"					\
+)
+#else
+#define SEV		ALT_SMP("sev", "nop")
+#define WFE(cond)	ALT_SMP("wfe" cond, "nop")
+#endif
+
 static inline void dsb_sev(void)
 {
 #if __LINUX_ARM_ARCH__ >= 7
 	__asm__ __volatile__ (
 		"dsb\n"
-		"sev"
+		SEV
 	);
-#elif defined(CONFIG_CPU_32v6K)
+#else
 	__asm__ __volatile__ (
 		"mcr p15, 0, %0, c7, c10, 4\n"
-		"sev"
+		SEV
 		: : "r" (0)
 	);
 #endif
@@ -46,9 +81,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
-#ifdef CONFIG_CPU_32v6K
-"	wfene\n"
-#endif
+	WFE("ne")
 "	strexeq	%0, %2, [%1]\n"
 "	teqeq	%0, #0\n"
 "	bne	1b"
@@ -107,9 +140,7 @@ static inline void arch_write_lock(arch_rwlock_t *rw)
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
-#ifdef CONFIG_CPU_32v6K
-"	wfene\n"
-#endif
+	WFE("ne")
 "	strexeq	%0, %2, [%1]\n"
 "	teq	%0, #0\n"
 "	bne	1b"
@@ -176,9 +207,7 @@ static inline void arch_read_lock(arch_rwlock_t *rw)
 "1:	ldrex	%0, [%2]\n"
 "	adds	%0, %0, #1\n"
 "	strexpl	%1, %0, [%2]\n"
-#ifdef CONFIG_CPU_32v6K
-"	wfemi\n"
-#endif
+	WFE("mi")
 "	rsbpls	%0, %1, #0\n"
 "	bmi	1b"
 	: "=&r" (tmp), "=&r" (tmp2)
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 97f6d60..9a87823 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -347,6 +347,7 @@ void cpu_idle_wait(void);
 #include <asm-generic/cmpxchg-local.h>
 
 #if __LINUX_ARM_ARCH__ < 6
+/* min ARCH < ARMv6 */
 
 #ifdef CONFIG_SMP
 #error "SMP is not supported on this platform"
@@ -365,7 +366,7 @@ void cpu_idle_wait(void);
 #include <asm-generic/cmpxchg.h>
 #endif
 
-#else	/* __LINUX_ARM_ARCH__ >= 6 */
+#else	/* min ARCH >= ARMv6 */
 
 extern void __bad_cmpxchg(volatile void *ptr, int size);
 
@@ -379,7 +380,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 	unsigned long oldval, res;
 
 	switch (size) {
-#ifdef CONFIG_CPU_32v6K
+#ifndef CONFIG_CPU_V6	/* min ARCH >= ARMv6K */
 	case 1:
 		do {
 			asm volatile("@ __cmpxchg1\n"
@@ -404,7 +405,7 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 				: "memory", "cc");
 		} while (res);
 		break;
-#endif /* CONFIG_CPU_32v6K */
+#endif
 	case 4:
 		do {
 			asm volatile("@ __cmpxchg4\n"
@@ -450,12 +451,12 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 	unsigned long ret;
 
 	switch (size) {
-#ifndef CONFIG_CPU_32v6K
+#ifdef CONFIG_CPU_V6	/* min ARCH == ARMv6 */
 	case 1:
 	case 2:
 		ret = __cmpxchg_local_generic(ptr, old, new, size);
 		break;
-#endif	/* !CONFIG_CPU_32v6K */
+#endif
 	default:
 		ret = __cmpxchg(ptr, old, new, size);
 	}
@@ -469,7 +470,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr,
 				       (unsigned long)(n),		\
 				       sizeof(*(ptr))))
 
-#ifdef CONFIG_CPU_32v6K
+#ifndef CONFIG_CPU_V6	/* min ARCH >= ARMv6K */
 
 /*
  * Note : ARMv7-M (currently unsupported by Linux) does not support
@@ -524,11 +525,11 @@ static inline unsigned long long __cmpxchg64_mb(volatile void *ptr,
 					 (unsigned long long)(o),	\
 					 (unsigned long long)(n)))
 
-#else	/* !CONFIG_CPU_32v6K */
+#else /* min ARCH = ARMv6 */
 
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-#endif	/* CONFIG_CPU_32v6K */
+#endif
 
 #endif	/* __LINUX_ARM_ARCH__ >= 6 */
 
diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index e71d6ff..60843eb 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -28,15 +28,14 @@
 #define tls_emu		1
 #define has_tls_reg		1
 #define set_tls		set_tls_none
-#elif __LINUX_ARM_ARCH__ >= 7 ||					\
-	(__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
-#define tls_emu		0
-#define has_tls_reg		1
-#define set_tls		set_tls_v6k
-#elif __LINUX_ARM_ARCH__ == 6
+#elif defined(CONFIG_CPU_V6)
 #define tls_emu		0
 #define has_tls_reg		(elf_hwcap & HWCAP_TLS)
 #define set_tls		set_tls_v6
+#elif defined(CONFIG_CPU_32v6K)
+#define tls_emu		0
+#define has_tls_reg		1
+#define set_tls		set_tls_v6k
 #else
 #define tls_emu		0
 #define has_tls_reg		0
diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index 1b960d5..f90756d 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -45,6 +45,7 @@ static inline int in_exception_text(unsigned long ptr)
 
 extern void __init early_trap_init(void);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
+extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
 
 extern void *vectors_page;
 
diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h
index 345df01..c684e37 100644
--- a/arch/arm/include/asm/types.h
+++ b/arch/arm/include/asm/types.h
@@ -18,9 +18,6 @@ typedef unsigned short umode_t;
 
 #ifndef __ASSEMBLY__
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
 typedef u32 dma64_addr_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/user.h b/arch/arm/include/asm/user.h
index 05ac4b0..35917b3 100644
--- a/arch/arm/include/asm/user.h
+++ b/arch/arm/include/asm/user.h
@@ -71,7 +71,7 @@ struct user{
 				/* the registers. */
   unsigned long magic;		/* To uniquely identify a core file */
   char u_comm[32];		/* User command that was responsible */
-  int u_debugreg[8];
+  int u_debugreg[8];		/* No longer used */
   struct user_fp u_fp;		/* FP state */
   struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */
   				/* the FP registers. */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 185ee82..74554f1 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_MODULES)		+= armksyms.o module.o
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
+obj-$(CONFIG_PM)		+= sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index e5e1e53..acca35a 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -140,24 +140,18 @@ EXPORT_SYMBOL(__aeabi_ulcmp);
 #endif
 
 	/* bitops */
-EXPORT_SYMBOL(_set_bit_le);
-EXPORT_SYMBOL(_test_and_set_bit_le);
-EXPORT_SYMBOL(_clear_bit_le);
-EXPORT_SYMBOL(_test_and_clear_bit_le);
-EXPORT_SYMBOL(_change_bit_le);
-EXPORT_SYMBOL(_test_and_change_bit_le);
+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);
 EXPORT_SYMBOL(_find_first_zero_bit_le);
 EXPORT_SYMBOL(_find_next_zero_bit_le);
 EXPORT_SYMBOL(_find_first_bit_le);
 EXPORT_SYMBOL(_find_next_bit_le);
 
 #ifdef __ARMEB__
-EXPORT_SYMBOL(_set_bit_be);
-EXPORT_SYMBOL(_test_and_set_bit_be);
-EXPORT_SYMBOL(_clear_bit_be);
-EXPORT_SYMBOL(_test_and_clear_bit_be);
-EXPORT_SYMBOL(_change_bit_be);
-EXPORT_SYMBOL(_test_and_change_bit_be);
 EXPORT_SYMBOL(_find_first_zero_bit_be);
 EXPORT_SYMBOL(_find_next_zero_bit_be);
 EXPORT_SYMBOL(_find_first_bit_be);
@@ -170,3 +164,7 @@ EXPORT_SYMBOL(mcount);
 #endif
 EXPORT_SYMBOL(__gnu_mcount_nc);
 #endif
+
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+EXPORT_SYMBOL(__pv_phys_offset);
+#endif
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 82da661..927522c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -13,6 +13,9 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/glue-df.h>
+#include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
@@ -114,6 +117,14 @@ int main(void)
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
 #endif
+#ifdef MULTI_CPU
+  DEFINE(CPU_SLEEP_SIZE,	offsetof(struct processor, suspend_size));
+  DEFINE(CPU_DO_SUSPEND,	offsetof(struct processor, do_suspend));
+  DEFINE(CPU_DO_RESUME,		offsetof(struct processor, do_resume));
+#endif
+#ifdef MULTI_CACHE
+  DEFINE(CACHE_FLUSH_KERN_ALL,	offsetof(struct cpu_cache_fns, flush_kern_all));
+#endif
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index c6273a3..d86fcd4 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -583,6 +583,11 @@ void __init pci_common_init(struct hw_pci *hw)
 			 * Assign resources.
 			 */
 			pci_bus_assign_resources(bus);
+
+			/*
+			 * Enable bridges
+			 */
+			pci_enable_bridges(bus);
 		}
 
 		/*
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index a0f0752..d2d983b 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -25,7 +25,7 @@
 		.macro	addruart, rp, rv
 		.endm
 
-#if defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 
 		.macro	senduart, rd, rx
 		mcr	p14, 0, \rd, c0, c5, 0
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2b46fea..e8d8856 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -16,7 +16,8 @@
  */
 
 #include <asm/memory.h>
-#include <asm/glue.h>
+#include <asm/glue-df.h>
+#include <asm/glue-pf.h>
 #include <asm/vfpmacros.h>
 #include <mach/entry-macro.S>
 #include <asm/thread_notify.h>
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index ae94649..051166c 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -76,13 +76,13 @@
 #ifndef CONFIG_THUMB2_KERNEL
 	.macro	svc_exit, rpsr
 	msr	spsr_cxsf, \rpsr
-#if defined(CONFIG_CPU_32v6K)
-	clrex					@ clear the exclusive monitor
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
-#elif defined (CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6)
 	ldr	r0, [sp]
 	strex	r1, r2, [sp]			@ clear the exclusive monitor
 	ldmib	sp, {r1 - pc}^			@ load r1 - pc, cpsr
+#elif defined(CONFIG_CPU_32v6K)
+	clrex					@ clear the exclusive monitor
+	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 #else
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 #endif
@@ -92,10 +92,10 @@
 	ldr	r1, [sp, #\offset + S_PSR]	@ get calling cpsr
 	ldr	lr, [sp, #\offset + S_PC]!	@ get pc
 	msr	spsr_cxsf, r1			@ save in spsr_svc
-#if defined(CONFIG_CPU_32v6K)
-	clrex					@ clear the exclusive monitor
-#elif defined (CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6)
 	strex	r1, r2, [sp]			@ clear the exclusive monitor
+#elif defined(CONFIG_CPU_32v6K)
+	clrex					@ clear the exclusive monitor
 #endif
 	.if	\fast
 	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 11db628..052b509 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -338,7 +338,7 @@ static struct miscdevice etb_miscdev = {
 	.fops = &etb_fops,
 };
 
-static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
+static int __init etb_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
 	int ret = 0;
@@ -530,7 +530,7 @@ static ssize_t trace_mode_store(struct kobject *kobj,
 static struct kobj_attribute trace_mode_attr =
 	__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
 
-static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
+static int __init etm_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
 	int ret = 0;
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index 8f57515..c84b57d 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -25,83 +25,6 @@
  * machine ID for example).
  */
 	__HEAD
-__error_a:
-#ifdef CONFIG_DEBUG_LL
-	mov	r4, r1				@ preserve machine ID
-	adr	r0, str_a1
-	bl	printascii
-	mov	r0, r4
-	bl	printhex8
-	adr	r0, str_a2
-	bl	printascii
-	adr	r3, __lookup_machine_type_data
-	ldmia	r3, {r4, r5, r6}		@ get machine desc list
-	sub	r4, r3, r4			@ get offset between virt&phys
-	add	r5, r5, r4			@ convert virt addresses to
-	add	r6, r6, r4			@ physical address space
-1:	ldr	r0, [r5, #MACHINFO_TYPE]	@ get machine type
-	bl	printhex8
-	mov	r0, #'\t'
-	bl	printch
-	ldr     r0, [r5, #MACHINFO_NAME]	@ get machine name
-	add	r0, r0, r4
-	bl	printascii
-	mov	r0, #'\n'
-	bl	printch
-	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
-	cmp	r5, r6
-	blo	1b
-	adr	r0, str_a3
-	bl	printascii
-	b	__error
-ENDPROC(__error_a)
-
-str_a1:	.asciz	"\nError: unrecognized/unsupported machine ID (r1 = 0x"
-str_a2:	.asciz	").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
-str_a3:	.asciz	"\nPlease check your kernel config and/or bootloader.\n"
-	.align
-#else
-	b	__error
-#endif
-
-/*
- * Lookup machine architecture in the linker-build list of architectures.
- * Note that we can't use the absolute addresses for the __arch_info
- * lists since we aren't running with the MMU on (and therefore, we are
- * not in the correct address space).  We have to calculate the offset.
- *
- *  r1 = machine architecture number
- * Returns:
- *  r3, r4, r6 corrupted
- *  r5 = mach_info pointer in physical address space
- */
-__lookup_machine_type:
-	adr	r3, __lookup_machine_type_data
-	ldmia	r3, {r4, r5, r6}
-	sub	r3, r3, r4			@ get offset between virt&phys
-	add	r5, r5, r3			@ convert virt addresses to
-	add	r6, r6, r3			@ physical address space
-1:	ldr	r3, [r5, #MACHINFO_TYPE]	@ get machine type
-	teq	r3, r1				@ matches loader number?
-	beq	2f				@ found
-	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
-	cmp	r5, r6
-	blo	1b
-	mov	r5, #0				@ unknown machine
-2:	mov	pc, lr
-ENDPROC(__lookup_machine_type)
-
-/*
- * Look in arch/arm/kernel/arch.[ch] for information about the
- * __arch_info structures.
- */
-	.align	2
-	.type	__lookup_machine_type_data, %object
-__lookup_machine_type_data:
-	.long	.
-	.long	__arch_info_begin
-	.long	__arch_info_end
-	.size	__lookup_machine_type_data, . - __lookup_machine_type_data
 
 /* Determine validity of the r2 atags pointer.  The heuristic requires
  * that the pointer be aligned, in the first 16k of physical RAM and
@@ -109,8 +32,6 @@ __lookup_machine_type_data:
  * of this function may be more lenient with the physical address and
  * may also be able to move the ATAGS block if necessary.
  *
- * r8  = machinfo
- *
  * Returns:
  *  r2 either valid atags pointer, or zero
  *  r5, r6 corrupted
@@ -185,17 +106,6 @@ __mmap_switched_data:
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
 /*
- * This provides a C-API version of __lookup_machine_type
- */
-ENTRY(lookup_machine_type)
-	stmfd	sp!, {r4 - r6, lr}
-	mov	r1, r0
-	bl	__lookup_machine_type
-	mov	r0, r5
-	ldmfd	sp!, {r4 - r6, pc}
-ENDPROC(lookup_machine_type)
-
-/*
  * This provides a C-API version of __lookup_processor_type
  */
 ENTRY(lookup_processor_type)
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index 814ce1a..6b1e0ad 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -44,9 +44,6 @@ ENTRY(stext)
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
 	beq	__error_p				@ yes, error 'p'
-	bl	__lookup_machine_type		@ r5=machinfo
-	movs	r8, r5				@ invalid machine (r5=0)?
-	beq	__error_a			@ yes, error 'a'
 
 	adr	lr, BSYM(__after_proc_init)	@ return (PIC) address
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index f06ff9f..c9173cf 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -26,14 +26,6 @@
 #include <mach/debug-macro.S>
 #endif
 
-#if (PHYS_OFFSET & 0x001fffff)
-#error "PHYS_OFFSET must be at an even 2MiB boundary!"
-#endif
-
-#define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
-#define KERNEL_RAM_PADDR	(PHYS_OFFSET + TEXT_OFFSET)
-
-
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -41,6 +33,7 @@
  * the least significant 16 bits to be 0x8000, but we could probably
  * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000.
  */
+#define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
 #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
 #error KERNEL_RAM_VADDR must start at 0xXXXX8000
 #endif
@@ -48,8 +41,8 @@
 	.globl	swapper_pg_dir
 	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
 
-	.macro	pgtbl, rd
-	ldr	\rd, =(KERNEL_RAM_PADDR - 0x4000)
+	.macro	pgtbl, rd, phys
+	add	\rd, \phys, #TEXT_OFFSET - 0x4000
 	.endm
 
 #ifdef CONFIG_XIP_KERNEL
@@ -87,25 +80,33 @@ ENTRY(stext)
 	movs	r10, r5				@ invalid processor (r5=0)?
  THUMB( it	eq )		@ force fixup-able long branch encoding
 	beq	__error_p			@ yes, error 'p'
-	bl	__lookup_machine_type		@ r5=machinfo
-	movs	r8, r5				@ invalid machine (r5=0)?
- THUMB( it	eq )		@ force fixup-able long branch encoding
-	beq	__error_a			@ yes, error 'a'
+
+#ifndef CONFIG_XIP_KERNEL
+	adr	r3, 2f
+	ldmia	r3, {r4, r8}
+	sub	r4, r3, r4			@ (PHYS_OFFSET - PAGE_OFFSET)
+	add	r8, r8, r4			@ PHYS_OFFSET
+#else
+	ldr	r8, =PLAT_PHYS_OFFSET
+#endif
 
 	/*
 	 * r1 = machine no, r2 = atags,
-	 * r8 = machinfo, r9 = cpuid, r10 = procinfo
+	 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
 	 */
 	bl	__vet_atags
 #ifdef CONFIG_SMP_ON_UP
 	bl	__fixup_smp
 #endif
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+	bl	__fixup_pv_table
+#endif
 	bl	__create_page_tables
 
 	/*
 	 * The following calls CPU specific code in a position independent
 	 * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
-	 * xxx_proc_info structure selected by __lookup_machine_type
+	 * xxx_proc_info structure selected by __lookup_processor_type
 	 * above.  On return, the CPU will be ready for the MMU to be
 	 * turned on, and r0 will hold the CPU control register value.
 	 */
@@ -118,22 +119,24 @@ ENTRY(stext)
 1:	b	__enable_mmu
 ENDPROC(stext)
 	.ltorg
+#ifndef CONFIG_XIP_KERNEL
+2:	.long	.
+	.long	PAGE_OFFSET
+#endif
 
 /*
  * Setup the initial page tables.  We only setup the barest
  * amount which are required to get the kernel running, which
  * generally means mapping in the kernel code.
  *
- * r8  = machinfo
- * r9  = cpuid
- * r10 = procinfo
+ * r8 = phys_offset, r9 = cpuid, r10 = procinfo
  *
  * Returns:
  *  r0, r3, r5-r7 corrupted
  *  r4 = physical page table address
  */
 __create_page_tables:
-	pgtbl	r4				@ page table address
+	pgtbl	r4, r8				@ page table address
 
 	/*
 	 * Clear the 16K level 1 swapper page table
@@ -189,10 +192,8 @@ __create_page_tables:
 	/*
 	 * Map some ram to cover our .data and .bss areas.
 	 */
-	orr	r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
-	.if	(KERNEL_RAM_PADDR & 0x00f00000)
-	orr	r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
-	.endif
+	add	r3, r8, #TEXT_OFFSET
+	orr	r3, r3, r7
 	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> 18
 	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
 	ldr	r6, =(_end - 1)
@@ -205,14 +206,17 @@ __create_page_tables:
 #endif
 
 	/*
-	 * Then map first 1MB of ram in case it contains our boot params.
+	 * Then map boot params address in r2 or
+	 * the first 1MB of ram if boot params address is not specified.
 	 */
-	add	r0, r4, #PAGE_OFFSET >> 18
-	orr	r6, r7, #(PHYS_OFFSET & 0xff000000)
-	.if	(PHYS_OFFSET & 0x00f00000)
-	orr	r6, r6, #(PHYS_OFFSET & 0x00f00000)
-	.endif
-	str	r6, [r0]
+	mov	r0, r2, lsr #20
+	movs	r0, r0, lsl #20
+	moveq	r0, r8
+	sub	r3, r0, r8
+	add	r3, r3, #PAGE_OFFSET
+	add	r3, r4, r3, lsr #18
+	orr	r6, r7, r0
+	str	r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
 #ifndef CONFIG_DEBUG_ICEDCC
@@ -457,4 +461,129 @@ ENTRY(fixup_smp)
 	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(fixup_smp)
 
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+
+/* __fixup_pv_table - patch the stub instructions with the delta between
+ * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
+ * can be expressed by an immediate shifter operand. The stub instruction
+ * has a form of '(add|sub) rd, rn, #imm'.
+ */
+	__HEAD
+__fixup_pv_table:
+	adr	r0, 1f
+	ldmia	r0, {r3-r5, r7}
+	sub	r3, r0, r3	@ PHYS_OFFSET - PAGE_OFFSET
+	add	r4, r4, r3	@ adjust table start address
+	add	r5, r5, r3	@ adjust table end address
+	add	r7, r7, r3	@ adjust __pv_phys_offset address
+	str	r8, [r7]	@ save computed PHYS_OFFSET to __pv_phys_offset
+#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	mov	r6, r3, lsr #24	@ constant for add/sub instructions
+	teq	r3, r6, lsl #24 @ must be 16MiB aligned
+#else
+	mov	r6, r3, lsr #16	@ constant for add/sub instructions
+	teq	r3, r6, lsl #16	@ must be 64kiB aligned
+#endif
+THUMB(	it	ne		@ cross section branch )
+	bne	__error
+	str	r6, [r7, #4]	@ save to __pv_offset
+	b	__fixup_a_pv_table
+ENDPROC(__fixup_pv_table)
+
+	.align
+1:	.long	.
+	.long	__pv_table_begin
+	.long	__pv_table_end
+2:	.long	__pv_phys_offset
+
+	.text
+__fixup_a_pv_table:
+#ifdef CONFIG_THUMB2_KERNEL
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	lsls	r0, r6, #24
+	lsr	r6, #8
+	beq	1f
+	clz	r7, r0
+	lsr	r0, #24
+	lsl	r0, r7
+	bic	r0, 0x0080
+	lsrs	r7, #1
+	orrcs   r0, #0x0080
+	orr	r0, r0, r7, lsl #12
+#endif
+1:	lsls	r6, #24
+	beq	4f
+	clz	r7, r6
+	lsr	r6, #24
+	lsl	r6, r7
+	bic	r6, #0x0080
+	lsrs	r7, #1
+	orrcs	r6, #0x0080
+	orr	r6, r6, r7, lsl #12
+	orr	r6, #0x4000
+	b	4f
+2:	@ at this point the C flag is always clear
+	add     r7, r3
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	ldrh	ip, [r7]
+	tst	ip, 0x0400	@ the i bit tells us LS or MS byte
+	beq	3f
+	cmp	r0, #0		@ set C flag, and ...
+	biceq	ip, 0x0400	@ immediate zero value has a special encoding
+	streqh	ip, [r7]	@ that requires the i bit cleared
+#endif
+3:	ldrh	ip, [r7, #2]
+	and	ip, 0x8f00
+	orrcc	ip, r6	@ mask in offset bits 31-24
+	orrcs	ip, r0	@ mask in offset bits 23-16
+	strh	ip, [r7, #2]
+4:	cmp	r4, r5
+	ldrcc	r7, [r4], #4	@ use branch for delay slot
+	bcc	2b
+	bx	lr
+#else
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	and	r0, r6, #255	@ offset bits 23-16
+	mov	r6, r6, lsr #8	@ offset bits 31-24
+#else
+	mov	r0, #0		@ just in case...
+#endif
+	b	3f
+2:	ldr	ip, [r7, r3]
+	bic	ip, ip, #0x000000ff
+	tst	ip, #0x400	@ rotate shift tells us LS or MS byte
+	orrne	ip, ip, r6	@ mask in offset bits 31-24
+	orreq	ip, ip, r0	@ mask in offset bits 23-16
+	str	ip, [r7, r3]
+3:	cmp	r4, r5
+	ldrcc	r7, [r4], #4	@ use branch for delay slot
+	bcc	2b
+	mov	pc, lr
+#endif
+ENDPROC(__fixup_a_pv_table)
+
+ENTRY(fixup_pv_table)
+	stmfd	sp!, {r4 - r7, lr}
+	ldr	r2, 2f			@ get address of __pv_phys_offset
+	mov	r3, #0			@ no offset
+	mov	r4, r0			@ r0 = table start
+	add	r5, r0, r1		@ r1 = table size
+	ldr	r6, [r2, #4]		@ get __pv_offset
+	bl	__fixup_a_pv_table
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(fixup_pv_table)
+
+	.align
+2:	.long	__pv_phys_offset
+
+	.data
+	.globl	__pv_phys_offset
+	.type	__pv_phys_offset, %object
+__pv_phys_offset:
+	.long	0
+	.size	__pv_phys_offset, . - __pv_phys_offset
+__pv_offset:
+	.long	0
+#endif
+
 #include "head-common.S"
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 28536e3..3535d37 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -179,14 +179,21 @@ int __init arch_probe_nr_irqs(void)
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
+static bool migrate_one_irq(struct irq_data *d)
 {
-	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->irq_data.node, cpu);
+	unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask);
+	bool ret = false;
 
-	raw_spin_lock_irq(&desc->lock);
-	desc->irq_data.chip->irq_set_affinity(&desc->irq_data,
-					      cpumask_of(cpu), false);
-	raw_spin_unlock_irq(&desc->lock);
+	if (cpu >= nr_cpu_ids) {
+		cpu = cpumask_any(cpu_online_mask);
+		ret = true;
+	}
+
+	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu);
+
+	d->chip->irq_set_affinity(d, cpumask_of(cpu), true);
+
+	return ret;
 }
 
 /*
@@ -198,25 +205,30 @@ void migrate_irqs(void)
 {
 	unsigned int i, cpu = smp_processor_id();
 	struct irq_desc *desc;
+	unsigned long flags;
+
+	local_irq_save(flags);
 
 	for_each_irq_desc(i, desc) {
 		struct irq_data *d = &desc->irq_data;
+		bool affinity_broken = false;
 
-		if (d->node == cpu) {
-			unsigned int newcpu = cpumask_any_and(d->affinity,
-							      cpu_online_mask);
-			if (newcpu >= nr_cpu_ids) {
-				if (printk_ratelimit())
-					printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
-					       i, cpu);
+		raw_spin_lock(&desc->lock);
+		do {
+			if (desc->action == NULL)
+				break;
 
-				cpumask_setall(d->affinity);
-				newcpu = cpumask_any_and(d->affinity,
-							 cpu_online_mask);
-			}
+			if (d->node != cpu)
+				break;
 
-			route_irq(desc, i, newcpu);
-		}
+			affinity_broken = migrate_one_irq(d);
+		} while (0);
+		raw_spin_unlock(&desc->lock);
+
+		if (affinity_broken && printk_ratelimit())
+			pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu);
 	}
+
+	local_irq_restore(flags);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index 30ead13..e59bbd4 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -75,6 +75,11 @@ void machine_crash_shutdown(struct pt_regs *regs)
 	printk(KERN_INFO "Loading crashdump kernel...\n");
 }
 
+/*
+ * Function pointer to optional machine-specific reinitialization
+ */
+void (*kexec_reinit)(void);
+
 void machine_kexec(struct kimage *image)
 {
 	unsigned long page_list;
@@ -104,6 +109,8 @@ void machine_kexec(struct kimage *image)
 			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
 	printk(KERN_INFO "Bye!\n");
 
+	if (kexec_reinit)
+		kexec_reinit();
 	local_irq_disable();
 	local_fiq_disable();
 	setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 6d4105e..fee7c36 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -76,6 +76,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
 		unsigned long loc;
 		Elf32_Sym *sym;
+		const char *symname;
 		s32 offset;
 #ifdef CONFIG_THUMB2_KERNEL
 		u32 upper, lower, sign, j1, j2;
@@ -83,18 +84,18 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 
 		offset = ELF32_R_SYM(rel->r_info);
 		if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
-			printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n",
+			pr_err("%s: section %u reloc %u: bad relocation sym offset\n",
 				module->name, relindex, i);
 			return -ENOEXEC;
 		}
 
 		sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
+		symname = strtab + sym->st_name;
 
 		if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) {
-			printk(KERN_ERR "%s: out of bounds relocation, "
-				"section %d reloc %d offset %d size %d\n",
-				module->name, relindex, i, rel->r_offset,
-				dstsec->sh_size);
+			pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n",
+			       module->name, relindex, i, symname,
+			       rel->r_offset, dstsec->sh_size);
 			return -ENOEXEC;
 		}
 
@@ -120,10 +121,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			if (offset & 3 ||
 			    offset <= (s32)0xfe000000 ||
 			    offset >= (s32)0x02000000) {
-				printk(KERN_ERR
-				       "%s: relocation out of range, section "
-				       "%d reloc %d sym '%s'\n", module->name,
-				       relindex, i, strtab + sym->st_name);
+				pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
+				       module->name, relindex, i, symname,
+				       ELF32_R_TYPE(rel->r_info), loc,
+				       sym->st_value);
 				return -ENOEXEC;
 			}
 
@@ -196,10 +197,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			if (!(offset & 1) ||
 			    offset <= (s32)0xff000000 ||
 			    offset >= (s32)0x01000000) {
-				printk(KERN_ERR
-				       "%s: relocation out of range, section "
-				       "%d reloc %d sym '%s'\n", module->name,
-				       relindex, i, strtab + sym->st_name);
+				pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
+				       module->name, relindex, i, symname,
+				       ELF32_R_TYPE(rel->r_info), loc,
+				       sym->st_value);
 				return -ENOEXEC;
 			}
 
@@ -282,12 +283,13 @@ static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr,
 	return NULL;
 }
 
+extern void fixup_pv_table(const void *, unsigned long);
 extern void fixup_smp(const void *, unsigned long);
 
 int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		    struct module *mod)
 {
-	const Elf_Shdr * __maybe_unused s = NULL;
+	const Elf_Shdr *s = NULL;
 #ifdef CONFIG_ARM_UNWIND
 	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 	const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum;
@@ -332,6 +334,11 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 					         maps[i].txt_sec->sh_addr,
 					         maps[i].txt_sec->sh_size);
 #endif
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+	s = find_mod_section(hdr, sechdrs, ".pv_table");
+	if (s)
+		fixup_pv_table((void *)s->sh_addr, s->sh_size);
+#endif
 	s = find_mod_section(hdr, sechdrs, ".alt.smp.init");
 	if (s && !is_smp())
 		fixup_smp((void *)s->sh_addr, s->sh_size);
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index d150ad1..22e194eb 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -377,9 +377,18 @@ validate_group(struct perf_event *event)
 	return 0;
 }
 
+static irqreturn_t armpmu_platform_irq(int irq, void *dev)
+{
+	struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
+
+	return plat->handle_irq(irq, dev, armpmu->handle_irq);
+}
+
 static int
 armpmu_reserve_hardware(void)
 {
+	struct arm_pmu_platdata *plat;
+	irq_handler_t handle_irq;
 	int i, err = -ENODEV, irq;
 
 	pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
@@ -390,6 +399,12 @@ armpmu_reserve_hardware(void)
 
 	init_pmu(ARM_PMU_DEVICE_CPU);
 
+	plat = dev_get_platdata(&pmu_device->dev);
+	if (plat && plat->handle_irq)
+		handle_irq = armpmu_platform_irq;
+	else
+		handle_irq = armpmu->handle_irq;
+
 	if (pmu_device->num_resources < 1) {
 		pr_err("no irqs for PMUs defined\n");
 		return -ENODEV;
@@ -400,7 +415,7 @@ armpmu_reserve_hardware(void)
 		if (irq < 0)
 			continue;
 
-		err = request_irq(irq, armpmu->handle_irq,
+		err = request_irq(irq, handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
 				  "armpmu", NULL);
 		if (err) {
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index c058bfc..6fc2d22 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -30,7 +30,7 @@
  * enable the interrupt.
  */
 
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 enum armv6_perf_types {
 	ARMV6_PERFCTR_ICACHE_MISS	    = 0x0,
 	ARMV6_PERFCTR_IBUF_STALL	    = 0x1,
@@ -669,4 +669,4 @@ static const struct arm_pmu *__init armv6mpcore_pmu_init(void)
 {
 	return NULL;
 }
-#endif	/* CONFIG_CPU_V6 */
+#endif	/* CONFIG_CPU_V6 || CONFIG_CPU_V6K */
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index b13e70f..2bf27f3 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -26,8 +26,6 @@
 #include <asm/system.h>
 #include <asm/traps.h>
 
-#include "ptrace.h"
-
 #define REG_PC	15
 #define REG_PSR	16
 /*
@@ -184,389 +182,12 @@ put_user_reg(struct task_struct *task, int offset, long data)
 	return ret;
 }
 
-static inline int
-read_u32(struct task_struct *task, unsigned long addr, u32 *res)
-{
-	int ret;
-
-	ret = access_process_vm(task, addr, res, sizeof(*res), 0);
-
-	return ret == sizeof(*res) ? 0 : -EIO;
-}
-
-static inline int
-read_instr(struct task_struct *task, unsigned long addr, u32 *res)
-{
-	int ret;
-
-	if (addr & 1) {
-		u16 val;
-		ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0);
-		ret = ret == sizeof(val) ? 0 : -EIO;
-		*res = val;
-	} else {
-		u32 val;
-		ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0);
-		ret = ret == sizeof(val) ? 0 : -EIO;
-		*res = val;
-	}
-	return ret;
-}
-
-/*
- * Get value of register `rn' (in the instruction)
- */
-static unsigned long
-ptrace_getrn(struct task_struct *child, unsigned long insn)
-{
-	unsigned int reg = (insn >> 16) & 15;
-	unsigned long val;
-
-	val = get_user_reg(child, reg);
-	if (reg == 15)
-		val += 8;
-
-	return val;
-}
-
-/*
- * Get value of operand 2 (in an ALU instruction)
- */
-static unsigned long
-ptrace_getaluop2(struct task_struct *child, unsigned long insn)
-{
-	unsigned long val;
-	int shift;
-	int type;
-
-	if (insn & 1 << 25) {
-		val = insn & 255;
-		shift = (insn >> 8) & 15;
-		type = 3;
-	} else {
-		val = get_user_reg (child, insn & 15);
-
-		if (insn & (1 << 4))
-			shift = (int)get_user_reg (child, (insn >> 8) & 15);
-		else
-			shift = (insn >> 7) & 31;
-
-		type = (insn >> 5) & 3;
-	}
-
-	switch (type) {
-	case 0:	val <<= shift;	break;
-	case 1:	val >>= shift;	break;
-	case 2:
-		val = (((signed long)val) >> shift);
-		break;
-	case 3:
- 		val = (val >> shift) | (val << (32 - shift));
-		break;
-	}
-	return val;
-}
-
-/*
- * Get value of operand 2 (in a LDR instruction)
- */
-static unsigned long
-ptrace_getldrop2(struct task_struct *child, unsigned long insn)
-{
-	unsigned long val;
-	int shift;
-	int type;
-
-	val = get_user_reg(child, insn & 15);
-	shift = (insn >> 7) & 31;
-	type = (insn >> 5) & 3;
-
-	switch (type) {
-	case 0:	val <<= shift;	break;
-	case 1:	val >>= shift;	break;
-	case 2:
-		val = (((signed long)val) >> shift);
-		break;
-	case 3:
- 		val = (val >> shift) | (val << (32 - shift));
-		break;
-	}
-	return val;
-}
-
-#define OP_MASK	0x01e00000
-#define OP_AND	0x00000000
-#define OP_EOR	0x00200000
-#define OP_SUB	0x00400000
-#define OP_RSB	0x00600000
-#define OP_ADD	0x00800000
-#define OP_ADC	0x00a00000
-#define OP_SBC	0x00c00000
-#define OP_RSC	0x00e00000
-#define OP_ORR	0x01800000
-#define OP_MOV	0x01a00000
-#define OP_BIC	0x01c00000
-#define OP_MVN	0x01e00000
-
-static unsigned long
-get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
-{
-	u32 alt = 0;
-
-	switch (insn & 0x0e000000) {
-	case 0x00000000:
-	case 0x02000000: {
-		/*
-		 * data processing
-		 */
-		long aluop1, aluop2, ccbit;
-
-	        if ((insn & 0x0fffffd0) == 0x012fff10) {
-		        /*
-			 * bx or blx
-			 */
-			alt = get_user_reg(child, insn & 15);
-			break;
-		}
-
-
-		if ((insn & 0xf000) != 0xf000)
-			break;
-
-		aluop1 = ptrace_getrn(child, insn);
-		aluop2 = ptrace_getaluop2(child, insn);
-		ccbit  = get_user_reg(child, REG_PSR) & PSR_C_BIT ? 1 : 0;
-
-		switch (insn & OP_MASK) {
-		case OP_AND: alt = aluop1 & aluop2;		break;
-		case OP_EOR: alt = aluop1 ^ aluop2;		break;
-		case OP_SUB: alt = aluop1 - aluop2;		break;
-		case OP_RSB: alt = aluop2 - aluop1;		break;
-		case OP_ADD: alt = aluop1 + aluop2;		break;
-		case OP_ADC: alt = aluop1 + aluop2 + ccbit;	break;
-		case OP_SBC: alt = aluop1 - aluop2 + ccbit;	break;
-		case OP_RSC: alt = aluop2 - aluop1 + ccbit;	break;
-		case OP_ORR: alt = aluop1 | aluop2;		break;
-		case OP_MOV: alt = aluop2;			break;
-		case OP_BIC: alt = aluop1 & ~aluop2;		break;
-		case OP_MVN: alt = ~aluop2;			break;
-		}
-		break;
-	}
-
-	case 0x04000000:
-	case 0x06000000:
-		/*
-		 * ldr
-		 */
-		if ((insn & 0x0010f000) == 0x0010f000) {
-			unsigned long base;
-
-			base = ptrace_getrn(child, insn);
-			if (insn & 1 << 24) {
-				long aluop2;
-
-				if (insn & 0x02000000)
-					aluop2 = ptrace_getldrop2(child, insn);
-				else
-					aluop2 = insn & 0xfff;
-
-				if (insn & 1 << 23)
-					base += aluop2;
-				else
-					base -= aluop2;
-			}
-			read_u32(child, base, &alt);
-		}
-		break;
-
-	case 0x08000000:
-		/*
-		 * ldm
-		 */
-		if ((insn & 0x00108000) == 0x00108000) {
-			unsigned long base;
-			unsigned int nr_regs;
-
-			if (insn & (1 << 23)) {
-				nr_regs = hweight16(insn & 65535) << 2;
-
-				if (!(insn & (1 << 24)))
-					nr_regs -= 4;
-			} else {
-				if (insn & (1 << 24))
-					nr_regs = -4;
-				else
-					nr_regs = 0;
-			}
-
-			base = ptrace_getrn(child, insn);
-
-			read_u32(child, base + nr_regs, &alt);
-			break;
-		}
-		break;
-
-	case 0x0a000000: {
-		/*
-		 * bl or b
-		 */
-		signed long displ;
-		/* It's a branch/branch link: instead of trying to
-		 * figure out whether the branch will be taken or not,
-		 * we'll put a breakpoint at both locations.  This is
-		 * simpler, more reliable, and probably not a whole lot
-		 * slower than the alternative approach of emulating the
-		 * branch.
-		 */
-		displ = (insn & 0x00ffffff) << 8;
-		displ = (displ >> 6) + 8;
-		if (displ != 0 && displ != 4)
-			alt = pc + displ;
-	    }
-	    break;
-	}
-
-	return alt;
-}
-
-static int
-swap_insn(struct task_struct *task, unsigned long addr,
-	  void *old_insn, void *new_insn, int size)
-{
-	int ret;
-
-	ret = access_process_vm(task, addr, old_insn, size, 0);
-	if (ret == size)
-		ret = access_process_vm(task, addr, new_insn, size, 1);
-	return ret;
-}
-
-static void
-add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr)
-{
-	int nr = dbg->nsaved;
-
-	if (nr < 2) {
-		u32 new_insn = BREAKINST_ARM;
-		int res;
-
-		res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4);
-
-		if (res == 4) {
-			dbg->bp[nr].address = addr;
-			dbg->nsaved += 1;
-		}
-	} else
-		printk(KERN_ERR "ptrace: too many breakpoints\n");
-}
-
-/*
- * Clear one breakpoint in the user program.  We copy what the hardware
- * does and use bit 0 of the address to indicate whether this is a Thumb
- * breakpoint or an ARM breakpoint.
- */
-static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp)
-{
-	unsigned long addr = bp->address;
-	union debug_insn old_insn;
-	int ret;
-
-	if (addr & 1) {
-		ret = swap_insn(task, addr & ~1, &old_insn.thumb,
-				&bp->insn.thumb, 2);
-
-		if (ret != 2 || old_insn.thumb != BREAKINST_THUMB)
-			printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at "
-				"0x%08lx (0x%04x)\n", task->comm,
-				task_pid_nr(task), addr, old_insn.thumb);
-	} else {
-		ret = swap_insn(task, addr & ~3, &old_insn.arm,
-				&bp->insn.arm, 4);
-
-		if (ret != 4 || old_insn.arm != BREAKINST_ARM)
-			printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at "
-				"0x%08lx (0x%08x)\n", task->comm,
-				task_pid_nr(task), addr, old_insn.arm);
-	}
-}
-
-void ptrace_set_bpt(struct task_struct *child)
-{
-	struct pt_regs *regs;
-	unsigned long pc;
-	u32 insn;
-	int res;
-
-	regs = task_pt_regs(child);
-	pc = instruction_pointer(regs);
-
-	if (thumb_mode(regs)) {
-		printk(KERN_WARNING "ptrace: can't handle thumb mode\n");
-		return;
-	}
-
-	res = read_instr(child, pc, &insn);
-	if (!res) {
-		struct debug_info *dbg = &child->thread.debug;
-		unsigned long alt;
-
-		dbg->nsaved = 0;
-
-		alt = get_branch_address(child, pc, insn);
-		if (alt)
-			add_breakpoint(child, dbg, alt);
-
-		/*
-		 * Note that we ignore the result of setting the above
-		 * breakpoint since it may fail.  When it does, this is
-		 * not so much an error, but a forewarning that we may
-		 * be receiving a prefetch abort shortly.
-		 *
-		 * If we don't set this breakpoint here, then we can
-		 * lose control of the thread during single stepping.
-		 */
-		if (!alt || predicate(insn) != PREDICATE_ALWAYS)
-			add_breakpoint(child, dbg, pc + 4);
-	}
-}
-
-/*
- * Ensure no single-step breakpoint is pending.  Returns non-zero
- * value if child was being single-stepped.
- */
-void ptrace_cancel_bpt(struct task_struct *child)
-{
-	int i, nsaved = child->thread.debug.nsaved;
-
-	child->thread.debug.nsaved = 0;
-
-	if (nsaved > 2) {
-		printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
-		nsaved = 2;
-	}
-
-	for (i = 0; i < nsaved; i++)
-		clear_breakpoint(child, &child->thread.debug.bp[i]);
-}
-
-void user_disable_single_step(struct task_struct *task)
-{
-	task->ptrace &= ~PT_SINGLESTEP;
-	ptrace_cancel_bpt(task);
-}
-
-void user_enable_single_step(struct task_struct *task)
-{
-	task->ptrace |= PT_SINGLESTEP;
-}
-
 /*
  * Called by kernel/ptrace.c when detaching..
  */
 void ptrace_disable(struct task_struct *child)
 {
-	user_disable_single_step(child);
+	/* Nothing to do. */
 }
 
 /*
@@ -576,8 +197,6 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
 {
 	siginfo_t info;
 
-	ptrace_cancel_bpt(tsk);
-
 	info.si_signo = SIGTRAP;
 	info.si_errno = 0;
 	info.si_code  = TRAP_BRKPT;
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h
deleted file mode 100644
index 3926605..0000000
--- a/arch/arm/kernel/ptrace.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  linux/arch/arm/kernel/ptrace.h
- *
- *  Copyright (C) 2000-2003 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/ptrace.h>
-
-extern void ptrace_cancel_bpt(struct task_struct *);
-extern void ptrace_set_bpt(struct task_struct *);
-extern void ptrace_break(struct task_struct *, struct pt_regs *);
-
-/*
- * Send SIGTRAP if we're single-stepping
- */
-static inline void single_step_trap(struct task_struct *task)
-{
-	if (task->ptrace & PT_SINGLESTEP) {
-		ptrace_cancel_bpt(task);
-		send_sig(SIGTRAP, task, 1);
-	}
-}
-
-static inline void single_step_clear(struct task_struct *task)
-{
-	if (task->ptrace & PT_SINGLESTEP)
-		ptrace_cancel_bpt(task);
-}
-
-static inline void single_step_set(struct task_struct *task)
-{
-	if (task->ptrace & PT_SINGLESTEP)
-		ptrace_set_bpt(task);
-}
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index df246da..0b13a72 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 #include <linux/module.h>
+#include <linux/ftrace.h>
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
 #include <linux/sched.h>
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 5ea4fb7..d1da921 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -308,7 +308,22 @@ static void __init cacheid_init(void)
  * already provide the required functionality.
  */
 extern struct proc_info_list *lookup_processor_type(unsigned int);
-extern struct machine_desc *lookup_machine_type(unsigned int);
+
+static void __init early_print(const char *str, ...)
+{
+	extern void printascii(const char *);
+	char buf[256];
+	va_list ap;
+
+	va_start(ap, str);
+	vsnprintf(buf, sizeof(buf), str, ap);
+	va_end(ap);
+
+#ifdef CONFIG_DEBUG_LL
+	printascii(buf);
+#endif
+	printk("%s", buf);
+}
 
 static void __init feat_v6_fixup(void)
 {
@@ -426,21 +441,29 @@ void cpu_init(void)
 
 static struct machine_desc * __init setup_machine(unsigned int nr)
 {
-	struct machine_desc *list;
+	extern struct machine_desc __arch_info_begin[], __arch_info_end[];
+	struct machine_desc *p;
 
 	/*
 	 * locate machine in the list of supported machines.
 	 */
-	list = lookup_machine_type(nr);
-	if (!list) {
-		printk("Machine configuration botched (nr %d), unable "
-		       "to continue.\n", nr);
-		while (1);
-	}
+	for (p = __arch_info_begin; p < __arch_info_end; p++)
+		if (nr == p->nr) {
+			printk("Machine: %s\n", p->name);
+			return p;
+		}
 
-	printk("Machine: %s\n", list->name);
+	early_print("\n"
+		"Error: unrecognized/unsupported machine ID (r1 = 0x%08x).\n\n"
+		"Available machine support:\n\nID (hex)\tNAME\n", nr);
 
-	return list;
+	for (p = __arch_info_begin; p < __arch_info_end; p++)
+		early_print("%08x\t%s\n", p->nr, p->name);
+
+	early_print("\nPlease check your kernel config and/or bootloader.\n");
+
+	while (true)
+		/* can't use cpu_relax() here as it may require MMU setup */;
 }
 
 static int __init arm_add_memory(unsigned long start, unsigned long size)
@@ -703,7 +726,7 @@ static struct init_tags {
 	{ tag_size(tag_core), ATAG_CORE },
 	{ 1, PAGE_SIZE, 0xff },
 	{ tag_size(tag_mem32), ATAG_MEM },
-	{ MEM_SIZE, PHYS_OFFSET },
+	{ MEM_SIZE },
 	{ 0, ATAG_NONE }
 };
 
@@ -802,6 +825,8 @@ void __init setup_arch(char **cmdline_p)
 	struct machine_desc *mdesc;
 	char *from = default_command_line;
 
+	init_tags.mem.start = PHYS_OFFSET;
+
 	unwind_init();
 
 	setup_processor();
@@ -814,8 +839,25 @@ void __init setup_arch(char **cmdline_p)
 
 	if (__atags_pointer)
 		tags = phys_to_virt(__atags_pointer);
-	else if (mdesc->boot_params)
-		tags = phys_to_virt(mdesc->boot_params);
+	else if (mdesc->boot_params) {
+#ifdef CONFIG_MMU
+		/*
+		 * We still are executing with a minimal MMU mapping created
+		 * with the presumption that the machine default for this
+		 * is located in the first MB of RAM.  Anything else will
+		 * fault and silently hang the kernel at this point.
+		 */
+		if (mdesc->boot_params < PHYS_OFFSET ||
+		    mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
+			printk(KERN_WARNING
+			       "Default boot params at physical 0x%08lx out of reach\n",
+			       mdesc->boot_params);
+		} else
+#endif
+		{
+			tags = phys_to_virt(mdesc->boot_params);
+		}
+	}
 
 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
 	/*
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index abaf844..cb83983 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -20,7 +20,6 @@
 #include <asm/unistd.h>
 #include <asm/vfp.h>
 
-#include "ptrace.h"
 #include "signal.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -348,8 +347,6 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
 	if (restore_sigframe(regs, frame))
 		goto badframe;
 
-	single_step_trap(current);
-
 	return regs->ARM_r0;
 
 badframe:
@@ -383,8 +380,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 
-	single_step_trap(current);
-
 	return regs->ARM_r0;
 
 badframe:
@@ -706,8 +701,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
 	if (try_to_freeze())
 		goto no_signal;
 
-	single_step_clear(current);
-
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		sigset_t *oldset;
@@ -726,7 +719,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
 				clear_thread_flag(TIF_RESTORE_SIGMASK);
 		}
-		single_step_set(current);
 		return;
 	}
 
@@ -772,7 +764,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
 			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 		}
 	}
-	single_step_set(current);
 }
 
 asmlinkage void
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
new file mode 100644
index 0000000..bfad698
--- /dev/null
+++ b/arch/arm/kernel/sleep.S
@@ -0,0 +1,134 @@
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/glue-cache.h>
+#include <asm/glue-proc.h>
+#include <asm/system.h>
+	.text
+
+/*
+ * Save CPU state for a suspend
+ *  r1 = v:p offset
+ *  r3 = virtual return function
+ * Note: sp is decremented to allocate space for CPU state on stack
+ * r0-r3,r9,r10,lr corrupted
+ */
+ENTRY(cpu_suspend)
+	mov	r9, lr
+#ifdef MULTI_CPU
+	ldr	r10, =processor
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
+	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
+	sub	sp, sp, r0		@ allocate CPU state on stack
+	mov	r0, sp			@ save pointer
+	add	ip, ip, r1		@ convert resume fn to phys
+	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+#ifdef CONFIG_SMP
+	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
+	ALT_UP(mov lr, #0)
+	and	lr, lr, #15
+	str	r2, [r3, lr, lsl #2]	@ save phys SP
+#else
+	str	r2, [r3]		@ save phys SP
+#endif
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
+#else
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, =cpu_suspend_size
+	sub	sp, sp, r0		@ allocate CPU state on stack
+	mov	r0, sp			@ save pointer
+	stmfd	sp!, {r1, r2, r3}	@ save v:p, virt SP, return fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+#ifdef CONFIG_SMP
+	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
+	ALT_UP(mov lr, #0)
+	and	lr, lr, #15
+	str	r2, [r3, lr, lsl #2]	@ save phys SP
+#else
+	str	r2, [r3]		@ save phys SP
+#endif
+	bl	cpu_do_suspend
+#endif
+
+	@ flush data cache
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	mov	lr, r9
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	mov	lr, r9
+	b	__cpuc_flush_kern_all
+#endif
+ENDPROC(cpu_suspend)
+	.ltorg
+
+/*
+ * r0 = control register value
+ * r1 = v:p offset (preserved by cpu_do_resume)
+ * r2 = phys page table base
+ * r3 = L1 section flags
+ */
+ENTRY(cpu_resume_mmu)
+	adr	r4, cpu_resume_turn_mmu_on
+	mov	r4, r4, lsr #20
+	orr	r3, r3, r4, lsl #20
+	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
+	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
+	sub	r2, r2, r1
+	ldr	r3, =cpu_resume_after_mmu
+	bic	r1, r0, #CR_C		@ ensure D-cache is disabled
+	b	cpu_resume_turn_mmu_on
+ENDPROC(cpu_resume_mmu)
+	.ltorg
+	.align	5
+cpu_resume_turn_mmu_on:
+	mcr	p15, 0, r1, c1, c0, 0	@ turn on MMU, I-cache, etc
+	mrc	p15, 0, r1, c0, c0, 0	@ read id reg
+	mov	r1, r1
+	mov	r1, r1
+	mov	pc, r3			@ jump to virtual address
+ENDPROC(cpu_resume_turn_mmu_on)
+cpu_resume_after_mmu:
+	str	r5, [r2, r4, lsl #2]	@ restore old mapping
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
+	mov	pc, lr
+ENDPROC(cpu_resume_after_mmu)
+
+/*
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+	.data
+	.align
+ENTRY(cpu_resume)
+#ifdef CONFIG_SMP
+	adr	r0, sleep_save_sp
+	ALT_SMP(mrc p15, 0, r1, c0, c0, 5)
+	ALT_UP(mov r1, #0)
+	and	r1, r1, #15
+	ldr	r0, [r0, r1, lsl #2]	@ stack phys addr
+#else
+	ldr	r0, sleep_save_sp	@ stack phys addr
+#endif
+	msr	cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE @ set SVC, irqs off
+#ifdef MULTI_CPU
+	ldmia	r0!, {r1, sp, lr, pc}	@ load v:p, stack, return fn, resume fn
+#else
+	ldmia	r0!, {r1, sp, lr}	@ load v:p, stack, return fn
+	b	cpu_do_resume
+#endif
+ENDPROC(cpu_resume)
+
+sleep_save_sp:
+	.rept	CONFIG_NR_CPUS
+	.long	0				@ preserve stack phys ptr here
+	.endr
diff --git a/arch/arm/kernel/smp_scu.c b/arch/arm/kernel/smp_scu.c
index 9ab4149..a1e757c 100644
--- a/arch/arm/kernel/smp_scu.c
+++ b/arch/arm/kernel/smp_scu.c
@@ -50,3 +50,26 @@ void __init scu_enable(void __iomem *scu_base)
 	 */
 	flush_cache_all();
 }
+
+/*
+ * Set the executing CPUs power mode as defined.  This will be in
+ * preparation for it executing a WFI instruction.
+ *
+ * This function must be called with preemption disabled, and as it
+ * has the side effect of disabling coherency, caches must have been
+ * flushed.  Interrupts must also have been disabled.
+ */
+int scu_power_mode(void __iomem *scu_base, unsigned int mode)
+{
+	unsigned int val;
+	int cpu = smp_processor_id();
+
+	if (mode > 3 || mode == 1 || cpu > 3)
+		return -EINVAL;
+
+	val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03;
+	val |= mode;
+	__raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu);
+
+	return 0;
+}
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c
index 26685c2..f5cf660 100644
--- a/arch/arm/kernel/tcm.c
+++ b/arch/arm/kernel/tcm.c
@@ -15,7 +15,7 @@
 #include <linux/string.h> /* memcpy */
 #include <asm/cputype.h>
 #include <asm/mach/map.h>
-#include <mach/memory.h>
+#include <asm/memory.h>
 #include "tcm.h"
 
 static struct gen_pool *tcm_pool;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 3d76bf2..1ff46ca 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -107,9 +107,7 @@ void timer_tick(void)
 {
 	profile_tick(CPU_PROFILING);
 	do_leds();
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
 #endif
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index ee57640..21ac43f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -23,6 +23,7 @@
 #include <linux/kexec.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -32,7 +33,6 @@
 #include <asm/unwind.h>
 #include <asm/tls.h>
 
-#include "ptrace.h"
 #include "signal.h"
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
@@ -256,7 +256,7 @@ static int __die(const char *str, int err, struct thread_info *thread, struct pt
 	return ret;
 }
 
-DEFINE_SPINLOCK(die_lock);
+static DEFINE_SPINLOCK(die_lock);
 
 /*
  * This function is protected against re-entrancy.
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 6146279..b4348e6 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -64,6 +64,10 @@ SECTIONS
 		__smpalt_end = .;
 #endif
 
+		__pv_table_begin = .;
+			*(.pv_table)
+		__pv_table_end = .;
+
 		INIT_SETUP(16)
 
 		INIT_CALLS
@@ -78,7 +82,7 @@ SECTIONS
 #endif
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(32, PAGE_SIZE)
 
 #ifndef CONFIG_XIP_KERNEL
 	. = ALIGN(PAGE_SIZE);
diff --git a/arch/arm/lib/bitops.h b/arch/arm/lib/bitops.h
index d422529..10d868a 100644
--- a/arch/arm/lib/bitops.h
+++ b/arch/arm/lib/bitops.h
@@ -1,44 +1,52 @@
-
-#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
+#if __LINUX_ARM_ARCH__ >= 6
 	.macro	bitop, instr
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
-	and	r3, r0, #7		@ Get bit offset
-	add	r1, r1, r0, lsr #3	@ Get byte offset
+	and	r3, r0, #31		@ Get bit offset
+	mov	r0, r0, lsr #5
+	add	r1, r1, r0, lsl #2	@ Get word offset
 	mov	r3, r2, lsl r3
-1:	ldrexb	r2, [r1]
+1:	ldrex	r2, [r1]
 	\instr	r2, r2, r3
-	strexb	r0, r2, [r1]
+	strex	r0, r2, [r1]
 	cmp	r0, #0
 	bne	1b
-	mov	pc, lr
+	bx	lr
 	.endm
 
 	.macro	testop, instr, store
-	and	r3, r0, #7		@ Get bit offset
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
-	add	r1, r1, r0, lsr #3	@ Get byte offset
+	and	r3, r0, #31		@ Get bit offset
+	mov	r0, r0, lsr #5
+	add	r1, r1, r0, lsl #2	@ Get word offset
 	mov	r3, r2, lsl r3		@ create mask
 	smp_dmb
-1:	ldrexb	r2, [r1]
+1:	ldrex	r2, [r1]
 	ands	r0, r2, r3		@ save old value of bit
-	\instr	r2, r2, r3			@ toggle bit
-	strexb	ip, r2, [r1]
+	\instr	r2, r2, r3		@ toggle bit
+	strex	ip, r2, [r1]
 	cmp	ip, #0
 	bne	1b
 	smp_dmb
 	cmp	r0, #0
 	movne	r0, #1
-2:	mov	pc, lr
+2:	bx	lr
 	.endm
 #else
 	.macro	bitop, instr
-	and	r2, r0, #7
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
+	and	r2, r0, #31
+	mov	r0, r0, lsr #5
 	mov	r3, #1
 	mov	r3, r3, lsl r2
 	save_and_disable_irqs ip
-	ldrb	r2, [r1, r0, lsr #3]
+	ldr	r2, [r1, r0, lsl #2]
 	\instr	r2, r2, r3
-	strb	r2, [r1, r0, lsr #3]
+	str	r2, [r1, r0, lsl #2]
 	restore_irqs ip
 	mov	pc, lr
 	.endm
@@ -52,11 +60,13 @@
  * to avoid dirtying the data cache.
  */
 	.macro	testop, instr, store
-	add	r1, r1, r0, lsr #3
-	and	r3, r0, #7
-	mov	r0, #1
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
+	and	r3, r0, #31
+	mov	r0, r0, lsr #5
 	save_and_disable_irqs ip
-	ldrb	r2, [r1]
+	ldr	r2, [r1, r0, lsl #2]!
+	mov	r0, #1
 	tst	r2, r0, lsl r3
 	\instr	r2, r2, r0, lsl r3
 	\store	r2, [r1]
diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S
index 80f3115..68ed5b6 100644
--- a/arch/arm/lib/changebit.S
+++ b/arch/arm/lib/changebit.S
@@ -12,12 +12,6 @@
 #include "bitops.h"
                 .text
 
-/* Purpose  : Function to change a bit
- * Prototype: int change_bit(int bit, void *addr)
- */
-ENTRY(_change_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_change_bit_le)
+ENTRY(_change_bit)
 	bitop	eor
-ENDPROC(_change_bit_be)
-ENDPROC(_change_bit_le)
+ENDPROC(_change_bit)
diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S
index 1a63e43..4c04c3b 100644
--- a/arch/arm/lib/clearbit.S
+++ b/arch/arm/lib/clearbit.S
@@ -12,13 +12,6 @@
 #include "bitops.h"
                 .text
 
-/*
- * Purpose  : Function to clear a bit
- * Prototype: int clear_bit(int bit, void *addr)
- */
-ENTRY(_clear_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_clear_bit_le)
+ENTRY(_clear_bit)
 	bitop	bic
-ENDPROC(_clear_bit_be)
-ENDPROC(_clear_bit_le)
+ENDPROC(_clear_bit)
diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S
index 1dd7176..bbee5c6 100644
--- a/arch/arm/lib/setbit.S
+++ b/arch/arm/lib/setbit.S
@@ -12,13 +12,6 @@
 #include "bitops.h"
 		.text
 
-/*
- * Purpose  : Function to set a bit
- * Prototype: int set_bit(int bit, void *addr)
- */
-ENTRY(_set_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_set_bit_le)
+ENTRY(_set_bit)
 	bitop	orr
-ENDPROC(_set_bit_be)
-ENDPROC(_set_bit_le)
+ENDPROC(_set_bit)
diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S
index 5c98dc5..15a4d43 100644
--- a/arch/arm/lib/testchangebit.S
+++ b/arch/arm/lib/testchangebit.S
@@ -12,9 +12,6 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_change_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_test_and_change_bit_le)
-	testop	eor, strb
-ENDPROC(_test_and_change_bit_be)
-ENDPROC(_test_and_change_bit_le)
+ENTRY(_test_and_change_bit)
+	testop	eor, str
+ENDPROC(_test_and_change_bit)
diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S
index 543d709..521b66b 100644
--- a/arch/arm/lib/testclearbit.S
+++ b/arch/arm/lib/testclearbit.S
@@ -12,9 +12,6 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_clear_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_test_and_clear_bit_le)
-	testop	bicne, strneb
-ENDPROC(_test_and_clear_bit_be)
-ENDPROC(_test_and_clear_bit_le)
+ENTRY(_test_and_clear_bit)
+	testop	bicne, strne
+ENDPROC(_test_and_clear_bit)
diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S
index 0b3f390..1c98cc2 100644
--- a/arch/arm/lib/testsetbit.S
+++ b/arch/arm/lib/testsetbit.S
@@ -12,9 +12,6 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_set_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_test_and_set_bit_le)
-	testop	orreq, streqb
-ENDPROC(_test_and_set_bit_be)
-ENDPROC(_test_and_set_bit_le)
+ENTRY(_test_and_set_bit)
+	testop	orreq, streq
+ENDPROC(_test_and_set_bit)
diff --git a/arch/arm/mach-aaec2000/Kconfig b/arch/arm/mach-aaec2000/Kconfig
deleted file mode 100644
index 5e4bef9..0000000
--- a/arch/arm/mach-aaec2000/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-if ARCH_AAEC2000
-
-menu "Agilent AAEC-2000 Implementations"
-
-config MACH_AAED2000
-	bool "Agilent AAED-2000 Development Platform"
-	select CPU_ARM920T
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile
deleted file mode 100644
index 20ec838..0000000
--- a/arch/arm/mach-aaec2000/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Common support (must be linked before board specific support)
-obj-y += core.o
-
-# Specific board support
-obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff --git a/arch/arm/mach-aaec2000/Makefile.boot b/arch/arm/mach-aaec2000/Makefile.boot
deleted file mode 100644
index 8f5a8b7..0000000
--- a/arch/arm/mach-aaec2000/Makefile.boot
+++ /dev/null
@@ -1 +0,0 @@
-	zreladdr-y := 0xf0008000
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
deleted file mode 100644
index 0eb3e3e..0000000
--- a/arch/arm/mach-aaec2000/aaed2000.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  linux/arch/arm/mach-aaec2000/aaed2000.c
- *
- *  Support for the Agilent AAED-2000 Development Platform.
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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/major.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/aaed2000.h>
-
-#include "core.h"
-
-static void aaed2000_clcd_disable(struct clcd_fb *fb)
-{
-	AAED_EXT_GPIO &= ~AAED_EGPIO_LCD_PWR_EN;
-}
-
-static void aaed2000_clcd_enable(struct clcd_fb *fb)
-{
-	AAED_EXT_GPIO |= AAED_EGPIO_LCD_PWR_EN;
-}
-
-struct aaec2000_clcd_info clcd_info = {
-	.enable = aaed2000_clcd_enable,
-	.disable = aaed2000_clcd_disable,
-	.panel = {
-		.mode	= {
-			.name		= "Sharp",
-			.refresh	= 60,
-			.xres		= 640,
-			.yres		= 480,
-			.pixclock	= 39721,
-			.left_margin	= 20,
-			.right_margin	= 44,
-			.upper_margin	= 21,
-			.lower_margin	= 34,
-			.hsync_len	= 96,
-			.vsync_len	= 2,
-			.sync		= 0,
-			.vmode	= FB_VMODE_NONINTERLACED,
-		},
-		.width	= -1,
-		.height	= -1,
-		.tim2	= TIM2_IVS | TIM2_IHS,
-		.cntl	= CNTL_LCDTFT,
-		.bpp	= 16,
-	},
-};
-
-static void __init aaed2000_init_irq(void)
-{
-	aaec2000_init_irq();
-}
-
-static void __init aaed2000_init(void)
-{
-	aaec2000_set_clcd_plat_data(&clcd_info);
-}
-
-static struct map_desc aaed2000_io_desc[] __initdata = {
-	{
-		.virtual	= EXT_GPIO_VBASE,
-		.pfn            = __phys_to_pfn(EXT_GPIO_PBASE),
-		.length         = EXT_GPIO_LENGTH,
-		.type           = MT_DEVICE
-	},
-};
-
-static void __init aaed2000_map_io(void)
-{
-	aaec2000_map_io();
-	iotable_init(aaed2000_io_desc, ARRAY_SIZE(aaed2000_io_desc));
-}
-
-MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
-	/* Maintainer: Nicolas Bellido Y Ortega */
-	.map_io		= aaed2000_map_io,
-	.init_irq	= aaed2000_init_irq,
-	.timer		= &aaec2000_timer,
-	.init_machine	= aaed2000_init,
-MACHINE_END
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
deleted file mode 100644
index f8465bd..0000000
--- a/arch/arm/mach-aaec2000/core.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- *  linux/arch/arm/mach-aaec2000/core.c
- *
- *  Code common to all AAEC-2000 machines
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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/platform_device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/signal.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/sizes.h>
-
-#include <asm/mach/flash.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include "core.h"
-
-/*
- * Common I/O mapping:
- *
- * Static virtual address mappings are as follow:
- *
- * 0xf8000000-0xf8001ffff: Devices connected to APB bus
- * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
- *
- * Below 0xe8000000 is reserved for vm allocation.
- *
- * The machine specific code must provide the extra mapping beside the
- * default mapping provided here.
- */
-static struct map_desc standard_io_desc[] __initdata = {
-	{
-		.virtual	= VIO_APB_BASE,
-		.pfn		= __phys_to_pfn(PIO_APB_BASE),
-		.length		= IO_APB_LENGTH,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= VIO_AHB_BASE,
-		.pfn		= __phys_to_pfn(PIO_AHB_BASE),
-		.length		= IO_AHB_LENGTH,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init aaec2000_map_io(void)
-{
-	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
-}
-
-/*
- * Interrupt handling routines
- */
-static void aaec2000_int_ack(struct irq_data *d)
-{
-	IRQ_INTSR = 1 << d->irq;
-}
-
-static void aaec2000_int_mask(struct irq_data *d)
-{
-	IRQ_INTENC |= (1 << d->irq);
-}
-
-static void aaec2000_int_unmask(struct irq_data *d)
-{
-	IRQ_INTENS |= (1 << d->irq);
-}
-
-static struct irq_chip aaec2000_irq_chip = {
-	.irq_ack	= aaec2000_int_ack,
-	.irq_mask	= aaec2000_int_mask,
-	.irq_unmask	= aaec2000_int_unmask,
-};
-
-void __init aaec2000_init_irq(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_handler(i, handle_level_irq);
-		set_irq_chip(i, &aaec2000_irq_chip);
-		set_irq_flags(i, IRQF_VALID);
-	}
-
-	/* Disable all interrupts */
-	IRQ_INTENC = 0xffffffff;
-
-	/* Clear any pending interrupts */
-	IRQ_INTSR = IRQ_INTSR;
-}
-
-/*
- * Time keeping
- */
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long aaec2000_gettimeoffset(void)
-{
-	unsigned long ticks_to_match, elapsed, usec;
-
-	/* Get ticks before next timer match */
-	ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
-
-	/* We need elapsed ticks since last match */
-	elapsed = LATCH - ticks_to_match;
-
-	/* Now, convert them to usec */
-	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
-
-	return usec;
-}
-
-/* We enter here with IRQs enabled */
-static irqreturn_t
-aaec2000_timer_interrupt(int irq, void *dev_id)
-{
-	/* TODO: Check timer accuracy */
-	timer_tick();
-	TIMER1_CLEAR = 1;
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction aaec2000_timer_irq = {
-	.name		= "AAEC-2000 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= aaec2000_timer_interrupt,
-};
-
-static void __init aaec2000_timer_init(void)
-{
-	/* Disable timer 1 */
-	TIMER1_CTRL = 0;
-
-	/* We have somehow to generate a 100Hz clock.
-	 * We then use the 508KHz timer in periodic mode.
-	 */
-	TIMER1_LOAD = LATCH;
-	TIMER1_CLEAR = 1; /* Clear interrupt */
-
-	setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
-
-	TIMER1_CTRL = TIMER_CTRL_ENABLE |
-	                TIMER_CTRL_PERIODIC |
-	                TIMER_CTRL_CLKSEL_508K;
-}
-
-struct sys_timer aaec2000_timer = {
-	.init		= aaec2000_timer_init,
-	.offset		= aaec2000_gettimeoffset,
-};
-
-static struct clcd_panel mach_clcd_panel;
-
-static int aaec2000_clcd_setup(struct clcd_fb *fb)
-{
-	dma_addr_t dma;
-
-	fb->panel = &mach_clcd_panel;
-
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, SZ_1M,
-			&dma, GFP_KERNEL);
-
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
-	}
-
-	fb->fb.fix.smem_start = dma;
-	fb->fb.fix.smem_len = SZ_1M;
-
-	return 0;
-}
-
-static int aaec2000_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-			fb->fb.screen_base,
-			fb->fb.fix.smem_start,
-			fb->fb.fix.smem_len);
-}
-
-static void aaec2000_clcd_remove(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-			fb->fb.screen_base, fb->fb.fix.smem_start);
-}
-
-static struct clcd_board clcd_plat_data = {
-	.name	= "AAEC-2000",
-	.check	= clcdfb_check,
-	.decode	= clcdfb_decode,
-	.setup	= aaec2000_clcd_setup,
-	.mmap	= aaec2000_clcd_mmap,
-	.remove	= aaec2000_clcd_remove,
-};
-
-static struct amba_device clcd_device = {
-	.dev		= {
-		.init_name		= "mb:16",
-		.coherent_dma_mask	= ~0,
-		.platform_data		= &clcd_plat_data,
-	},
-	.res		= {
-		.start			= AAEC_CLCD_PHYS,
-		.end			= AAEC_CLCD_PHYS + SZ_4K - 1,
-		.flags			= IORESOURCE_MEM,
-	},
-	.irq		= { INT_LCD, NO_IRQ },
-	.periphid	= 0x41110,
-};
-
-static struct amba_device *amba_devs[] __initdata = {
-	&clcd_device,
-};
-
-void clk_disable(struct clk *clk)
-{
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-int clk_enable(struct clk *clk)
-{
-	return 0;
-}
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	return dev && strcmp(dev_name(dev), "mb:16") == 0 ? NULL : ERR_PTR(-ENOENT);
-}
-
-void clk_put(struct clk *clk)
-{
-}
-
-void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *clcd)
-{
-	clcd_plat_data.enable = clcd->enable;
-	clcd_plat_data.disable = clcd->disable;
-	memcpy(&mach_clcd_panel, &clcd->panel, sizeof(struct clcd_panel));
-}
-
-static struct flash_platform_data aaec2000_flash_data = {
-	.map_name	= "cfi_probe",
-	.width		= 4,
-};
-
-static struct resource aaec2000_flash_resource = {
-	.start		= AAEC_FLASH_BASE,
-	.end		= AAEC_FLASH_BASE + AAEC_FLASH_SIZE,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device aaec2000_flash_device = {
-	.name		= "armflash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &aaec2000_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &aaec2000_flash_resource,
-};
-
-static int __init aaec2000_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		amba_device_register(d, &iomem_resource);
-	}
-
-	platform_device_register(&aaec2000_flash_device);
-
-	return 0;
-};
-arch_initcall(aaec2000_init);
-
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
deleted file mode 100644
index 59501b5..0000000
--- a/arch/arm/mach-aaec2000/core.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  linux/arch/arm/mach-aaec2000/core.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-struct sys_timer;
-
-extern struct sys_timer aaec2000_timer;
-extern void __init aaec2000_map_io(void);
-extern void __init aaec2000_init_irq(void);
-
-struct aaec2000_clcd_info {
-	struct clcd_panel panel;
-	void (*disable)(struct clcd_fb *);
-	void (*enable)(struct clcd_fb *);
-};
-
-extern void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *);
-
diff --git a/arch/arm/mach-aaec2000/include/mach/aaec2000.h b/arch/arm/mach-aaec2000/include/mach/aaec2000.h
deleted file mode 100644
index bc729c4..0000000
--- a/arch/arm/mach-aaec2000/include/mach/aaec2000.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/aaec2000.h
- *
- *  AAEC-2000 registers definition
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_AAEC2000_H
-#define __ASM_ARCH_AAEC2000_H
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#error You must include hardware.h not this file
-#endif /* __ASM_ARCH_HARDWARE_H */
-
-/* Chip selects */
-#define AAEC_CS0	0x00000000
-#define AAEC_CS1	0x10000000
-#define AAEC_CS2	0x20000000
-#define AAEC_CS3	0x30000000
-
-/* Flash */
-#define AAEC_FLASH_BASE	AAEC_CS0
-#define AAEC_FLASH_SIZE	SZ_64M
-
-/* Interrupt controller */
-#define IRQ_BASE	__REG(0x80000500)
-#define IRQ_INTSR	__REG(0x80000500)	/* Int Status Register */
-#define IRQ_INTRSR	__REG(0x80000504)	/* Int Raw (unmasked) Status */
-#define IRQ_INTENS	__REG(0x80000508)	/* Int Enable Set */
-#define IRQ_INTENC	__REG(0x8000050c)	/* Int Enable Clear */
-
-/* UART 1 */
-#define UART1_BASE	__REG(0x80000600)
-#define UART1_DR	__REG(0x80000600) /* Data/FIFO Register */
-#define UART1_LCR	__REG(0x80000604) /* Link Control Register */
-#define UART1_BRCR	__REG(0x80000608) /* Baud Rate Control Register */
-#define UART1_CR	__REG(0x8000060c) /* Control Register */
-#define UART1_SR	__REG(0x80000610) /* Status Register */
-#define UART1_INT	__REG(0x80000614) /* Interrupt Status Register */
-#define UART1_INTM	__REG(0x80000618) /* Interrupt Mask Register */
-#define UART1_INTRES	__REG(0x8000061c) /* Int Result (masked status) Register */
-
-/* UART 2 */
-#define UART2_BASE	__REG(0x80000700)
-#define UART2_DR	__REG(0x80000700) /* Data/FIFO Register */
-#define UART2_LCR	__REG(0x80000704) /* Link Control Register */
-#define UART2_BRCR	__REG(0x80000708) /* Baud Rate Control Register */
-#define UART2_CR	__REG(0x8000070c) /* Control Register */
-#define UART2_SR	__REG(0x80000710) /* Status Register */
-#define UART2_INT	__REG(0x80000714) /* Interrupt Status Register */
-#define UART2_INTM	__REG(0x80000718) /* Interrupt Mask Register */
-#define UART2_INTRES	__REG(0x8000071c) /* Int Result (masked status) Register */
-
-/* UART 3 */
-#define UART3_BASE	__REG(0x80000800)
-#define UART3_DR	__REG(0x80000800) /* Data/FIFO Register */
-#define UART3_LCR	__REG(0x80000804) /* Link Control Register */
-#define UART3_BRCR	__REG(0x80000808) /* Baud Rate Control Register */
-#define UART3_CR	__REG(0x8000080c) /* Control Register */
-#define UART3_SR	__REG(0x80000810) /* Status Register */
-#define UART3_INT	__REG(0x80000814) /* Interrupt Status Register */
-#define UART3_INTM	__REG(0x80000818) /* Interrupt Mask Register */
-#define UART3_INTRES	__REG(0x8000081c) /* Int Result (masked status) Register */
-
-/* These are used in some places */
-#define _UART1_BASE __PREG(UART1_BASE)
-#define _UART2_BASE __PREG(UART2_BASE)
-#define _UART3_BASE __PREG(UART3_BASE)
-
-/* UART Registers Offsets */
-#define UART_DR		0x00
-#define UART_LCR	0x04
-#define UART_BRCR	0x08
-#define UART_CR		0x0c
-#define UART_SR		0x10
-#define UART_INT	0x14
-#define UART_INTM	0x18
-#define UART_INTRES	0x1c
-
-/* UART_LCR Bitmask */
-#define UART_LCR_BRK	(1 << 0) /* Send Break */
-#define UART_LCR_PEN	(1 << 1) /* Parity Enable */
-#define UART_LCR_EP	(1 << 2) /* Even/Odd Parity */
-#define UART_LCR_S2	(1 << 3) /* One/Two Stop bits */
-#define UART_LCR_FIFO	(1 << 4) /* FIFO Enable */
-#define UART_LCR_WL5	(0 << 5) /* Word Length - 5 bits */
-#define UART_LCR_WL6	(1 << 5) /* Word Length - 6 bits */
-#define UART_LCR_WL7	(1 << 6) /* Word Length - 7 bits */
-#define UART_LCR_WL8	(1 << 7) /* Word Length - 8 bits */
-
-/* UART_CR Bitmask */
-#define UART_CR_EN	(1 << 0) /* UART Enable */
-#define UART_CR_SIR	(1 << 1) /* IrDA SIR Enable */
-#define UART_CR_SIRLP	(1 << 2) /* Low Power IrDA Enable */
-#define UART_CR_RXP	(1 << 3) /* Receive Pin Polarity */
-#define UART_CR_TXP	(1 << 4) /* Transmit Pin Polarity */
-#define UART_CR_MXP	(1 << 5) /* Modem Pin Polarity */
-#define UART_CR_LOOP	(1 << 6) /* Loopback Mode */
-
-/* UART_SR Bitmask */
-#define UART_SR_CTS	(1 << 0) /* Clear To Send Status */
-#define UART_SR_DSR	(1 << 1) /* Data Set Ready Status */
-#define UART_SR_DCD	(1 << 2) /* Data Carrier Detect Status */
-#define UART_SR_TxBSY	(1 << 3) /* Transmitter Busy Status */
-#define UART_SR_RxFE	(1 << 4) /* Receive FIFO Empty Status */
-#define UART_SR_TxFF	(1 << 5) /* Transmit FIFO Full Status */
-#define UART_SR_RxFF	(1 << 6) /* Receive FIFO Full Status */
-#define UART_SR_TxFE	(1 << 7) /* Transmit FIFO Empty Status */
-
-/* UART_INT Bitmask */
-#define UART_INT_RIS	(1 << 0) /* Rx Interrupt */
-#define UART_INT_TIS	(1 << 1) /* Tx Interrupt */
-#define UART_INT_MIS	(1 << 2) /* Modem Interrupt */
-#define UART_INT_RTIS	(1 << 3) /* Receive Timeout Interrupt */
-
-/* Timer 1 */
-#define TIMER1_BASE	__REG(0x80000c00)
-#define TIMER1_LOAD	__REG(0x80000c00)	/* Timer 1 Load Register */
-#define TIMER1_VAL	__REG(0x80000c04)	/* Timer 1 Value Register */
-#define TIMER1_CTRL	__REG(0x80000c08)	/* Timer 1 Control Register */
-#define TIMER1_CLEAR	__REG(0x80000c0c)	/* Timer 1 Clear Register */
-
-/* Timer 2 */
-#define TIMER2_BASE	__REG(0x80000d00)
-#define TIMER2_LOAD	__REG(0x80000d00)	/* Timer 2 Load Register */
-#define TIMER2_VAL	__REG(0x80000d04)	/* Timer 2 Value Register */
-#define TIMER2_CTRL	__REG(0x80000d08)	/* Timer 2 Control Register */
-#define TIMER2_CLEAR	__REG(0x80000d0c)	/* Timer 2 Clear Register */
-
-/* Timer 3 */
-#define TIMER3_BASE	__REG(0x80000e00)
-#define TIMER3_LOAD	__REG(0x80000e00)	/* Timer 3 Load Register */
-#define TIMER3_VAL	__REG(0x80000e04)	/* Timer 3 Value Register */
-#define TIMER3_CTRL	__REG(0x80000e08)	/* Timer 3 Control Register */
-#define TIMER3_CLEAR	__REG(0x80000e0c)	/* Timer 3 Clear Register */
-
-/* Timer Control register bits */
-#define TIMER_CTRL_ENABLE	(1 << 7) /* Enable (Start Timer) */
-#define TIMER_CTRL_PERIODIC	(1 << 6) /* Periodic Running Mode */
-#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
-#define TIMER_CTRL_CLKSEL_508K	(1 << 3) /* 508KHz Clock select (Timer 1, 2) */
-#define TIMER_CTRL_CLKSEL_2K	(0 << 3) /* 2KHz Clock Select (Timer 1, 2) */
-
-/* Power and State Control */
-#define POWER_BASE	__REG(0x80000400)
-#define POWER_PWRSR	__REG(0x80000400) /* Power Status Register */
-#define POWER_PWRCNT	__REG(0x80000404) /* Power/Clock control */
-#define POWER_HALT	__REG(0x80000408) /* Power Idle Mode */
-#define POWER_STDBY	__REG(0x8000040c) /* Power Standby Mode */
-#define POWER_BLEOI	__REG(0x80000410) /* Battery Low End of Interrupt */
-#define POWER_MCEOI	__REG(0x80000414) /* Media Changed EoI */
-#define POWER_TEOI	__REG(0x80000418) /* Tick EoI */
-#define POWER_STFCLR	__REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
-#define POWER_CLKSET	__REG(0x80000420) /* Clock Speed Control */
-
-/* GPIO Registers */
-#define AAEC_GPIO_PHYS	0x80000e00
-
-#define AAEC_GPIO_PADR		__REG(AAEC_GPIO_PHYS + 0x00)
-#define AAEC_GPIO_PBDR		__REG(AAEC_GPIO_PHYS + 0x04)
-#define AAEC_GPIO_PCDR		__REG(AAEC_GPIO_PHYS + 0x08)
-#define AAEC_GPIO_PDDR		__REG(AAEC_GPIO_PHYS + 0x0c)
-#define AAEC_GPIO_PADDR		__REG(AAEC_GPIO_PHYS + 0x10)
-#define AAEC_GPIO_PBDDR		__REG(AAEC_GPIO_PHYS + 0x14)
-#define AAEC_GPIO_PCDDR		__REG(AAEC_GPIO_PHYS + 0x18)
-#define AAEC_GPIO_PDDDR		__REG(AAEC_GPIO_PHYS + 0x1c)
-#define AAEC_GPIO_PEDR		__REG(AAEC_GPIO_PHYS + 0x20)
-#define AAEC_GPIO_PEDDR		__REG(AAEC_GPIO_PHYS + 0x24)
-#define AAEC_GPIO_KSCAN		__REG(AAEC_GPIO_PHYS + 0x28)
-#define AAEC_GPIO_PINMUX	__REG(AAEC_GPIO_PHYS + 0x2c)
-#define AAEC_GPIO_PFDR		__REG(AAEC_GPIO_PHYS + 0x30)
-#define AAEC_GPIO_PFDDR		__REG(AAEC_GPIO_PHYS + 0x34)
-#define AAEC_GPIO_PGDR		__REG(AAEC_GPIO_PHYS + 0x38)
-#define AAEC_GPIO_PGDDR		__REG(AAEC_GPIO_PHYS + 0x3c)
-#define AAEC_GPIO_PHDR		__REG(AAEC_GPIO_PHYS + 0x40)
-#define AAEC_GPIO_PHDDR		__REG(AAEC_GPIO_PHYS + 0x44)
-#define AAEC_GPIO_RAZ		__REG(AAEC_GPIO_PHYS + 0x48)
-#define AAEC_GPIO_INTTYPE1	__REG(AAEC_GPIO_PHYS + 0x4c)
-#define AAEC_GPIO_INTTYPE2	__REG(AAEC_GPIO_PHYS + 0x50)
-#define AAEC_GPIO_FEOI		__REG(AAEC_GPIO_PHYS + 0x54)
-#define AAEC_GPIO_INTEN		__REG(AAEC_GPIO_PHYS + 0x58)
-#define AAEC_GPIO_INTSTATUS	__REG(AAEC_GPIO_PHYS + 0x5c)
-#define AAEC_GPIO_RAWINTSTATUS	__REG(AAEC_GPIO_PHYS + 0x60)
-#define AAEC_GPIO_DB		__REG(AAEC_GPIO_PHYS + 0x64)
-#define AAEC_GPIO_PAPINDR	__REG(AAEC_GPIO_PHYS + 0x68)
-#define AAEC_GPIO_PBPINDR	__REG(AAEC_GPIO_PHYS + 0x6c)
-#define AAEC_GPIO_PCPINDR	__REG(AAEC_GPIO_PHYS + 0x70)
-#define AAEC_GPIO_PDPINDR	__REG(AAEC_GPIO_PHYS + 0x74)
-#define AAEC_GPIO_PEPINDR	__REG(AAEC_GPIO_PHYS + 0x78)
-#define AAEC_GPIO_PFPINDR	__REG(AAEC_GPIO_PHYS + 0x7c)
-#define AAEC_GPIO_PGPINDR	__REG(AAEC_GPIO_PHYS + 0x80)
-#define AAEC_GPIO_PHPINDR	__REG(AAEC_GPIO_PHYS + 0x84)
-
-#define AAEC_GPIO_PINMUX_PE0CON		(1 << 0)
-#define AAEC_GPIO_PINMUX_PD0CON		(1 << 1)
-#define AAEC_GPIO_PINMUX_CODECON	(1 << 2)
-#define AAEC_GPIO_PINMUX_UART3CON	(1 << 3)
-
-/* LCD Controller */
-#define AAEC_CLCD_PHYS	0x80003000
-
-#endif /* __ARM_ARCH_AAEC2000_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/aaed2000.h b/arch/arm/mach-aaec2000/include/mach/aaed2000.h
deleted file mode 100644
index f821295..0000000
--- a/arch/arm/mach-aaec2000/include/mach/aaed2000.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/aaed2000.h
- *
- *  AAED-2000 specific bits definition
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_AAED2000_H
-#define __ASM_ARCH_AAED2000_H
-
-/* External GPIOs. */
-
-#define EXT_GPIO_PBASE	AAEC_CS3
-#define EXT_GPIO_VBASE	0xf8100000
-#define EXT_GPIO_LENGTH	0x00001000
-
-#define __ext_gpio_p2v(x)	((x) - EXT_GPIO_PBASE + EXT_GPIO_VBASE)
-#define __ext_gpio_v2p(x)	((x) + EXT_GPIO_PBASE - EXT_GPIO_VBASE)
-
-#define __EXT_GPIO_REG(x)	(*((volatile u32 *)__ext_gpio_p2v(x)))
-#define __EXT_GPIO_PREG(x)	(__ext_gpio_v2p((u32)&(x)))
-
-#define AAED_EXT_GPIO	__EXT_GPIO_REG(EXT_GPIO_PBASE)
-
-#define AAED_EGPIO_KBD_SCAN	0x00003fff /* Keyboard scan data */
-#define AAED_EGPIO_PWR_INT	0x00008fff /* Smart battery charger interrupt */
-#define AAED_EGPIO_SWITCHED	0x000f0000 /* DIP Switches */
-#define AAED_EGPIO_USB_VBUS	0x00400000 /* USB Vbus sense */
-#define AAED_EGPIO_LCD_PWR_EN	0x02000000 /* LCD and backlight PWR enable */
-#define AAED_EGPIO_nLED0	0x20000000 /* LED 0 */
-#define AAED_EGPIO_nLED1	0x20000000 /* LED 1 */
-#define AAED_EGPIO_nLED2	0x20000000 /* LED 2 */
-
-
-#endif /* __ARM_ARCH_AAED2000_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/debug-macro.S b/arch/arm/mach-aaec2000/include/mach/debug-macro.S
deleted file mode 100644
index bc7ad55..0000000
--- a/arch/arm/mach-aaec2000/include/mach/debug-macro.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*  arch/arm/mach-aaec2000/include/mach/debug-macro.S
- *
- *  Debugging macro include header
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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 "hardware.h"
-		.macro	addruart, rp, rv
-		mov	\rp, 0x00000800
-		orr	\rv, \rp, #io_p2v(0x80000000)	@ virtual
-		orr	\rp, \rp, #0x80000000		@ physical
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #0x10]
-		tst	\rd, #(1 << 7)
-		beq	1002b
-		.endm
-
-		.macro	waituart,rd,rx
-#if 0
-1001:		ldr	\rd, [\rx, #0x10]
-		tst	\rd, #(1 << 5)
-		beq	1001b
-#endif
-		.endm
diff --git a/arch/arm/mach-aaec2000/include/mach/entry-macro.S b/arch/arm/mach-aaec2000/include/mach/entry-macro.S
deleted file mode 100644
index c8fb344..0000000
--- a/arch/arm/mach-aaec2000/include/mach/entry-macro.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/entry-macro.S
- *
- *  Low-level IRQ helper for aaec-2000 based platforms
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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/irqs.h>
-
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		mov	r4, #0xf8000000
-		add	r4, r4, #0x00000500
-		mov	\base, r4
-		ldr	\irqstat, [\base, #0]
-		cmp	\irqstat, #0
-		bne	1001f
-		ldr	\irqnr, =NR_IRQS+1
-		b       1003f
-1001:		mov	\irqnr, #0
-1002:		ands	\tmp, \irqstat, #1
-		mov	\irqstat, \irqstat, LSR #1
-		add	\irqnr, \irqnr, #1
-		beq	1002b
-		sub	\irqnr, \irqnr, #1
-1003:
-		.endm
diff --git a/arch/arm/mach-aaec2000/include/mach/hardware.h b/arch/arm/mach-aaec2000/include/mach/hardware.h
deleted file mode 100644
index 965a6f6..0000000
--- a/arch/arm/mach-aaec2000/include/mach/hardware.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/hardware.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/aaec2000.h>
-
-/* The kernel is loaded at physical address 0xf8000000.
- * We map the IO space a bit after
- */
-#define PIO_APB_BASE	0x80000000
-#define VIO_APB_BASE	0xf8000000
-#define IO_APB_LENGTH	0x2000
-#define PIO_AHB_BASE	0x80002000
-#define VIO_AHB_BASE	0xf8002000
-#define IO_AHB_LENGTH	0x2000
-
-#define VIO_BASE    VIO_APB_BASE
-#define PIO_BASE    PIO_APB_BASE
-
-#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
-#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
-
-#ifndef __ASSEMBLY__
-
-#include <asm/types.h>
-
-/* FIXME: Is it needed to optimize this a la pxa ?? */
-#define __REG(x)    (*((volatile u32 *)io_p2v(x)))
-#define __PREG(x)   (io_v2p((u32)&(x)))
-
-#else /* __ASSEMBLY__ */
-
-#define __REG(x)    io_p2v(x)
-#define __PREG(x)   io_v2p(x)
-
-#endif
-
-#include "aaec2000.h"
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/io.h b/arch/arm/mach-aaec2000/include/mach/io.h
deleted file mode 100644
index ab4fe5d..0000000
--- a/arch/arm/mach-aaec2000/include/mach/io.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/io.h
- *
- *  Copied from asm/arch/sa1100/io.h
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#endif
diff --git a/arch/arm/mach-aaec2000/include/mach/irqs.h b/arch/arm/mach-aaec2000/include/mach/irqs.h
deleted file mode 100644
index bf45c6d..0000000
--- a/arch/arm/mach-aaec2000/include/mach/irqs.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/irqs.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-
-#define INT_GPIOF0_FIQ	0  /* External GPIO Port F O Fast Interrupt Input */
-#define INT_BL_FIQ	1  /* Battery Low Fast Interrupt */
-#define INT_WE_FIQ	2  /* Watchdog Expired Fast Interrupt */
-#define INT_MV_FIQ	3  /* Media Changed Interrupt */
-#define INT_SC		4  /* Sound Codec Interrupt */
-#define INT_GPIO1	5  /* GPIO Port F Configurable Int 1 */
-#define INT_GPIO2	6  /* GPIO Port F Configurable Int 2 */
-#define INT_GPIO3	7  /* GPIO Port F Configurable Int 3 */
-#define INT_TMR1_OFL	8  /* Timer 1 Overflow Interrupt */
-#define INT_TMR2_OFL	9  /* Timer 2 Overflow Interrupt */
-#define INT_RTC_CM	10 /* RTC Compare Match Interrupt */
-#define INT_TICK	11 /* 64Hz Tick Interrupt */
-#define INT_UART1	12 /* UART1 Interrupt */
-#define INT_UART2	13 /* UART2 & Modem State Changed Interrupt */
-#define INT_LCD		14 /* LCD Interrupt */
-#define INT_SSI		15 /* SSI End of Transfer Interrupt */
-#define INT_UART3	16 /* UART3 Interrupt */
-#define INT_SCI		17 /* SCI Interrupt */
-#define INT_AAC		18 /* Advanced Audio Codec Interrupt */
-#define INT_MMC		19 /* MMC Interrupt */
-#define INT_USB		20 /* USB Interrupt */
-#define INT_DMA		21 /* DMA Interrupt */
-#define INT_TMR3_UOFL	22 /* Timer 3 Underflow Interrupt */
-#define INT_GPIO4	23 /* GPIO Port F Configurable Int 4 */
-#define INT_GPIO5	24 /* GPIO Port F Configurable Int 4 */
-#define INT_GPIO6	25 /* GPIO Port F Configurable Int 4 */
-#define INT_GPIO7	26 /* GPIO Port F Configurable Int 4 */
-#define INT_BMI		27 /* BMI Interrupt */
-
-#define NR_IRQS		(INT_BMI + 1)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/memory.h b/arch/arm/mach-aaec2000/include/mach/memory.h
deleted file mode 100644
index 4f93c56..0000000
--- a/arch/arm/mach-aaec2000/include/mach/memory.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/memory.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-
-#define PHYS_OFFSET	UL(0xf0000000)
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/system.h b/arch/arm/mach-aaec2000/include/mach/system.h
deleted file mode 100644
index fe08ca1..0000000
--- a/arch/arm/mach-aaec2000/include/mach/system.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  arch/arm/mach-aaed2000/include/mach/system.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle();
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset(0);
-}
-
-#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/timex.h b/arch/arm/mach-aaec2000/include/mach/timex.h
deleted file mode 100644
index 6c8edf4..0000000
--- a/arch/arm/mach-aaec2000/include/mach/timex.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/timex.h
- *
- *  AAEC-2000 Architecture timex specification
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE		508000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/uncompress.h b/arch/arm/mach-aaec2000/include/mach/uncompress.h
deleted file mode 100644
index 381ecad..0000000
--- a/arch/arm/mach-aaec2000/include/mach/uncompress.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/uncompress.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include "hardware.h"
-
-#define UART(x)         (*(volatile unsigned long *)(serial_port + (x)))
-
-static void putc(int c)
-{
-	unsigned long serial_port;
-        do {
-		serial_port = _UART3_BASE;
-		if (UART(UART_CR) & UART_CR_EN) break;
-		serial_port = _UART1_BASE;
-		if (UART(UART_CR) & UART_CR_EN) break;
-		serial_port = _UART2_BASE;
-		if (UART(UART_CR) & UART_CR_EN) break;
-		return;
-	} while (0);
-
-	/* wait for space in the UART's transmitter */
-	while ((UART(UART_SR) & UART_SR_TxFF))
-		barrier();
-
-	/* send the character out. */
-	UART(UART_DR) = c;
-}
-
-static inline void flush(void)
-{
-}
-
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
-
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-aaec2000/include/mach/vmalloc.h b/arch/arm/mach-aaec2000/include/mach/vmalloc.h
deleted file mode 100644
index a6299e8..0000000
--- a/arch/arm/mach-aaec2000/include/mach/vmalloc.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/vmalloc.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  This program is free software; you can 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_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END		0xd0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 0a99b3c..17f7d9b 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -153,6 +153,7 @@ static struct i2c_board_info __initdata snapper9260_i2c_devices[] = {
 	{
 		/* RTC */
 		I2C_BOARD_INFO("isl1208", 0x6f),
+		.irq = gpio_to_irq(AT91_PIN_PA31),
 	},
 };
 
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index bfdd8ab..ddeb645 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -220,15 +220,8 @@ extern void at91_gpio_resume(void);
 #define gpio_set_value	__gpio_set_value
 #define gpio_cansleep	__gpio_cansleep
 
-static inline int gpio_to_irq(unsigned gpio)
-{
-	return gpio;
-}
-
-static inline int irq_to_gpio(unsigned irq)
-{
-	return irq;
-}
+#define gpio_to_irq(gpio) (gpio)
+#define irq_to_gpio(irq)  (irq)
 
 #endif	/* __ASSEMBLY__ */
 
diff --git a/arch/arm/mach-at91/include/mach/memory.h b/arch/arm/mach-at91/include/mach/memory.h
index 14f4ef4..c2cfe50 100644
--- a/arch/arm/mach-at91/include/mach/memory.h
+++ b/arch/arm/mach-at91/include/mach/memory.h
@@ -23,6 +23,6 @@
 
 #include <mach/hardware.h>
 
-#define PHYS_OFFSET	(AT91_SDRAM_BASE)
+#define PLAT_PHYS_OFFSET	(AT91_SDRAM_BASE)
 
 #endif
diff --git a/arch/arm/mach-bcmring/include/mach/hardware.h b/arch/arm/mach-bcmring/include/mach/hardware.h
index 447eb34..8bf3564 100644
--- a/arch/arm/mach-bcmring/include/mach/hardware.h
+++ b/arch/arm/mach-bcmring/include/mach/hardware.h
@@ -31,7 +31,7 @@
  *  *_SIZE  is the size of the region
  *  *_BASE  is the virtual address
  */
-#define RAM_START               PHYS_OFFSET
+#define RAM_START               PLAT_PHYS_OFFSET
 
 #define RAM_SIZE                (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
 #define RAM_BASE                PAGE_OFFSET
diff --git a/arch/arm/mach-bcmring/include/mach/memory.h b/arch/arm/mach-bcmring/include/mach/memory.h
index 114f942..15162e4 100644
--- a/arch/arm/mach-bcmring/include/mach/memory.h
+++ b/arch/arm/mach-bcmring/include/mach/memory.h
@@ -23,7 +23,7 @@
  * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
  */
 
-#define PHYS_OFFSET CFG_GLOBAL_RAM_BASE
+#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE
 
 /*
  * Maximum DMA memory allowed is 14M
diff --git a/arch/arm/mach-clps711x/include/mach/memory.h b/arch/arm/mach-clps711x/include/mach/memory.h
index f45c8e8..3a032a6 100644
--- a/arch/arm/mach-clps711x/include/mach/memory.h
+++ b/arch/arm/mach-clps711x/include/mach/memory.h
@@ -23,7 +23,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0xc0000000)
+#define PLAT_PHYS_OFFSET	UL(0xc0000000)
 
 #if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12)
 
diff --git a/arch/arm/mach-clps711x/include/mach/time.h b/arch/arm/mach-clps711x/include/mach/time.h
index 8fe283c..61fef91 100644
--- a/arch/arm/mach-clps711x/include/mach/time.h
+++ b/arch/arm/mach-clps711x/include/mach/time.h
@@ -30,7 +30,7 @@ p720t_timer_interrupt(int irq, void *dev_id)
 {
 	struct pt_regs *regs = get_irq_regs();
 	do_leds();
-	do_timer(1);
+	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff --git a/arch/arm/mach-cns3xxx/include/mach/memory.h b/arch/arm/mach-cns3xxx/include/mach/memory.h
index 3b6b769..dc16c5c 100644
--- a/arch/arm/mach-cns3xxx/include/mach/memory.h
+++ b/arch/arm/mach-cns3xxx/include/mach/memory.h
@@ -13,7 +13,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #define __phys_to_bus(x)	((x) + PHYS_OFFSET)
 #define __bus_to_phys(x)	((x) - PHYS_OFFSET)
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index b52a3a1..8bc3701 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -20,6 +20,8 @@
 #include <linux/i2c/at24.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -30,6 +32,7 @@
 #include <mach/da8xx.h>
 #include <mach/usb.h>
 #include <mach/aemif.h>
+#include <mach/spi.h>
 
 #define DA830_EVM_PHY_ID		""
 /*
@@ -534,6 +537,64 @@ static struct edma_rsv_info da830_edma_rsv[] = {
 	},
 };
 
+static struct mtd_partition da830evm_spiflash_part[] = {
+	[0] = {
+		.name = "DSP-UBL",
+		.offset = 0,
+		.size = SZ_8K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[1] = {
+		.name = "ARM-UBL",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_16K + SZ_8K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[2] = {
+		.name = "U-Boot",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_256K - SZ_32K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[3] = {
+		.name = "U-Boot-Environment",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_16K,
+		.mask_flags = 0,
+	},
+	[4] = {
+		.name = "Kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+		.mask_flags = 0,
+	},
+};
+
+static struct flash_platform_data da830evm_spiflash_data = {
+	.name		= "m25p80",
+	.parts		= da830evm_spiflash_part,
+	.nr_parts	= ARRAY_SIZE(da830evm_spiflash_part),
+	.type		= "w25x32",
+};
+
+static struct davinci_spi_config da830evm_spiflash_cfg = {
+	.io_type	= SPI_IO_TYPE_DMA,
+	.c2tdelay	= 8,
+	.t2cdelay	= 8,
+};
+
+static struct spi_board_info da830evm_spi_info[] = {
+	{
+		.modalias		= "m25p80",
+		.platform_data		= &da830evm_spiflash_data,
+		.controller_data	= &da830evm_spiflash_cfg,
+		.mode			= SPI_MODE_0,
+		.max_speed_hz		= 30000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+	},
+};
+
 static __init void da830_evm_init(void)
 {
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
@@ -590,6 +651,12 @@ static __init void da830_evm_init(void)
 	ret = da8xx_register_rtc();
 	if (ret)
 		pr_warning("da830_evm_init: rtc setup failed: %d\n", ret);
+
+	ret = da8xx_register_spi(0, da830evm_spi_info,
+				 ARRAY_SIZE(da830evm_spi_info));
+	if (ret)
+		pr_warning("da830_evm_init: spi 0 registration failed: %d\n",
+			   ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index b01fb2a..a7b41bf 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -29,6 +29,8 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/tps6507x.h>
 #include <linux/input/tps6507x-ts.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -38,6 +40,7 @@
 #include <mach/nand.h>
 #include <mach/mux.h>
 #include <mach/aemif.h>
+#include <mach/spi.h>
 
 #define DA850_EVM_PHY_ID		"0:00"
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
@@ -48,6 +51,70 @@
 
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
+static struct mtd_partition da850evm_spiflash_part[] = {
+	[0] = {
+		.name = "UBL",
+		.offset = 0,
+		.size = SZ_64K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[1] = {
+		.name = "U-Boot",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_512K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[2] = {
+		.name = "U-Boot-Env",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_64K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[3] = {
+		.name = "Kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_2M + SZ_512K,
+		.mask_flags = 0,
+	},
+	[4] = {
+		.name = "Filesystem",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_4M,
+		.mask_flags = 0,
+	},
+	[5] = {
+		.name = "MAC-Address",
+		.offset = SZ_8M - SZ_64K,
+		.size = SZ_64K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+};
+
+static struct flash_platform_data da850evm_spiflash_data = {
+	.name		= "m25p80",
+	.parts		= da850evm_spiflash_part,
+	.nr_parts	= ARRAY_SIZE(da850evm_spiflash_part),
+	.type		= "m25p64",
+};
+
+static struct davinci_spi_config da850evm_spiflash_cfg = {
+	.io_type	= SPI_IO_TYPE_DMA,
+	.c2tdelay	= 8,
+	.t2cdelay	= 8,
+};
+
+static struct spi_board_info da850evm_spi_info[] = {
+	{
+		.modalias		= "m25p80",
+		.platform_data		= &da850evm_spiflash_data,
+		.controller_data	= &da850evm_spiflash_cfg,
+		.mode			= SPI_MODE_0,
+		.max_speed_hz		= 30000000,
+		.bus_num		= 1,
+		.chip_select		= 0,
+	},
+};
+
 static struct mtd_partition da850_evm_norflash_partition[] = {
 	{
 		.name           = "bootloaders + env",
@@ -231,8 +298,6 @@ static const short da850_evm_nor_pins[] = {
 	-1
 };
 
-static u32 ui_card_detected;
-
 #if defined(CONFIG_MMC_DAVINCI) || \
     defined(CONFIG_MMC_DAVINCI_MODULE)
 #define HAS_MMC 1
@@ -244,7 +309,7 @@ static inline void da850_evm_setup_nor_nand(void)
 {
 	int ret = 0;
 
-	if (ui_card_detected & !HAS_MMC) {
+	if (!HAS_MMC) {
 		ret = davinci_cfg_reg_list(da850_evm_nand_pins);
 		if (ret)
 			pr_warning("da850_evm_init: nand mux setup failed: "
@@ -394,7 +459,6 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
 		goto exp_setup_keys_fail;
 	}
 
-	ui_card_detected = 1;
 	pr_info("DA850/OMAP-L138 EVM UI card detected\n");
 
 	da850_evm_setup_nor_nand();
@@ -664,6 +728,13 @@ static struct snd_platform_data da850_evm_snd_data = {
 	.rxnumevt	= 1,
 };
 
+static const short da850_evm_mcasp_pins[] __initconst = {
+	DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
+	DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE,
+	DA850_AXR_11, DA850_AXR_12,
+	-1
+};
+
 static int da850_evm_mmc_get_ro(int index)
 {
 	return gpio_get_value(DA850_MMCSD_WP_PIN);
@@ -683,6 +754,13 @@ static struct davinci_mmc_config da850_mmc_config = {
 	.version	= MMC_CTLR_VERSION_2,
 };
 
+static const short da850_evm_mmcsd0_pins[] __initconst = {
+	DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
+	DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
+	DA850_GPIO4_0, DA850_GPIO4_1,
+	-1
+};
+
 static void da850_panel_power_ctrl(int val)
 {
 	/* lcd backlight */
@@ -1070,7 +1148,7 @@ static __init void da850_evm_init(void)
 				ret);
 
 	if (HAS_MMC) {
-		ret = davinci_cfg_reg_list(da850_mmcsd0_pins);
+		ret = davinci_cfg_reg_list(da850_evm_mmcsd0_pins);
 		if (ret)
 			pr_warning("da850_evm_init: mmcsd0 mux setup failed:"
 					" %d\n", ret);
@@ -1106,7 +1184,7 @@ static __init void da850_evm_init(void)
 	__raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30);
 	__raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30);
 
-	ret = davinci_cfg_reg_list(da850_mcasp_pins);
+	ret = davinci_cfg_reg_list(da850_evm_mcasp_pins);
 	if (ret)
 		pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
 				ret);
@@ -1153,6 +1231,12 @@ static __init void da850_evm_init(void)
 	if (ret)
 		pr_warning("da850_evm_init: suspend registration failed: %d\n",
 				ret);
+
+	ret = da8xx_register_spi(1, da850evm_spi_info,
+				 ARRAY_SIZE(da850evm_spi_info));
+	if (ret)
+		pr_warning("da850_evm_init: spi 1 registration failed: %d\n",
+				ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 0ca90b8..556bbd4 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -440,11 +440,6 @@ evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
 	gpio_request(gpio + 7, "nCF_SEL");
 	gpio_direction_output(gpio + 7, 1);
 
-	/* irlml6401 switches over 1A, in under 8 msec;
-	 * now it can be managed by nDRV_VBUS ...
-	 */
-	davinci_setup_usb(1000, 8);
-
 	return 0;
 }
 
@@ -705,6 +700,9 @@ static __init void davinci_evm_init(void)
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 
+	/* irlml6401 switches over 1A, in under 8 msec */
+	davinci_setup_usb(1000, 8);
+
 	soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 0bb5f0c..2aa79c5 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -17,6 +17,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/etherdevice.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,6 +27,7 @@
 #include <mach/da8xx.h>
 #include <mach/nand.h>
 #include <mach/mux.h>
+#include <mach/spi.h>
 
 #define MITYOMAPL138_PHY_ID		"0:03"
 
@@ -44,38 +47,109 @@ struct factory_config {
 
 static struct factory_config factory_config;
 
+struct part_no_info {
+	const char	*part_no;	/* part number string of interest */
+	int		max_freq;	/* khz */
+};
+
+static struct part_no_info mityomapl138_pn_info[] = {
+	{
+		.part_no	= "L138-C",
+		.max_freq	= 300000,
+	},
+	{
+		.part_no	= "L138-D",
+		.max_freq	= 375000,
+	},
+	{
+		.part_no	= "L138-F",
+		.max_freq	= 456000,
+	},
+	{
+		.part_no	= "1808-C",
+		.max_freq	= 300000,
+	},
+	{
+		.part_no	= "1808-D",
+		.max_freq	= 375000,
+	},
+	{
+		.part_no	= "1808-F",
+		.max_freq	= 456000,
+	},
+	{
+		.part_no	= "1810-D",
+		.max_freq	= 375000,
+	},
+};
+
+#ifdef CONFIG_CPU_FREQ
+static void mityomapl138_cpufreq_init(const char *partnum)
+{
+	int i, ret;
+
+	for (i = 0; partnum && i < ARRAY_SIZE(mityomapl138_pn_info); i++) {
+		/*
+		 * the part number has additional characters beyond what is
+		 * stored in the table.  This information is not needed for
+		 * determining the speed grade, and would require several
+		 * more table entries.  Only check the first N characters
+		 * for a match.
+		 */
+		if (!strncmp(partnum, mityomapl138_pn_info[i].part_no,
+			     strlen(mityomapl138_pn_info[i].part_no))) {
+			da850_max_speed = mityomapl138_pn_info[i].max_freq;
+			break;
+		}
+	}
+
+	ret = da850_register_cpufreq("pll0_sysclk3");
+	if (ret)
+		pr_warning("cpufreq registration failed: %d\n", ret);
+}
+#else
+static void mityomapl138_cpufreq_init(const char *partnum) { }
+#endif
+
 static void read_factory_config(struct memory_accessor *a, void *context)
 {
 	int ret;
+	const char *partnum = NULL;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
 	if (ret != sizeof(struct factory_config)) {
 		pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n",
 				ret);
-		return;
+		goto bad_config;
 	}
 
 	if (factory_config.magic != FACTORY_CONFIG_MAGIC) {
 		pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n",
 				factory_config.magic);
-		return;
+		goto bad_config;
 	}
 
 	if (factory_config.version != FACTORY_CONFIG_VERSION) {
 		pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n",
 				factory_config.version);
-		return;
+		goto bad_config;
 	}
 
 	pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac);
-	pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum);
 	if (is_valid_ether_addr(factory_config.mac))
 		memcpy(soc_info->emac_pdata->mac_addr,
 			factory_config.mac, ETH_ALEN);
 	else
 		pr_warning("MityOMAPL138: Invalid MAC found "
 				"in factory config block\n");
+
+	partnum = factory_config.partnum;
+	pr_info("MityOMAPL138: Part Number = %s\n", partnum);
+
+bad_config:
+	/* default maximum speed is valid for all platforms */
+	mityomapl138_cpufreq_init(partnum);
 }
 
 static struct at24_platform_data mityomapl138_fd_chip = {
@@ -223,6 +297,82 @@ static int __init pmic_tps65023_init(void)
 }
 
 /*
+ * SPI Devices:
+ *	SPI1_CS0: 8M Flash ST-M25P64-VME6G
+ */
+static struct mtd_partition spi_flash_partitions[] = {
+	[0] = {
+		.name		= "ubl",
+		.offset		= 0,
+		.size		= SZ_64K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[1] = {
+		.name		= "u-boot",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[2] = {
+		.name		= "u-boot-env",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_64K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[3] = {
+		.name		= "periph-config",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_64K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[4] = {
+		.name		= "reserved",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_256K + SZ_64K,
+	},
+	[5] = {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M + SZ_1M,
+	},
+	[6] = {
+		.name		= "fpga",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M,
+	},
+	[7] = {
+		.name		= "spare",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data mityomapl138_spi_flash_data = {
+	.name		= "m25p80",
+	.parts		= spi_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(spi_flash_partitions),
+	.type		= "m24p64",
+};
+
+static struct davinci_spi_config spi_eprom_config = {
+	.io_type	= SPI_IO_TYPE_DMA,
+	.c2tdelay	= 8,
+	.t2cdelay	= 8,
+};
+
+static struct spi_board_info mityomapl138_spi_flash_info[] = {
+	{
+		.modalias		= "m25p80",
+		.platform_data		= &mityomapl138_spi_flash_data,
+		.controller_data	= &spi_eprom_config,
+		.mode			= SPI_MODE_0,
+		.max_speed_hz		= 30000000,
+		.bus_num		= 1,
+		.chip_select		= 0,
+	},
+};
+
+/*
  * MityDSP-L138 includes a 256 MByte large-page NAND flash
  * (128K blocks).
  */
@@ -377,16 +527,17 @@ static void __init mityomapl138_init(void)
 
 	mityomapl138_setup_nand();
 
+	ret = da8xx_register_spi(1, mityomapl138_spi_flash_info,
+			       ARRAY_SIZE(mityomapl138_spi_flash_info));
+	if (ret)
+		pr_warning("spi 1 registration failed: %d\n", ret);
+
 	mityomapl138_config_emac();
 
 	ret = da8xx_register_rtc();
 	if (ret)
 		pr_warning("rtc setup failed: %d\n", ret);
 
-	ret = da850_register_cpufreq("pll0_sysclk3");
-	if (ret)
-		pr_warning("cpufreq registration failed: %d\n", ret);
-
 	ret = da8xx_register_cpuidle();
 	if (ret)
 		pr_warning("cpuidle registration failed: %d\n", ret);
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index 0b8dbdb..67c38d0 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -19,6 +19,279 @@
 
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
+#include <mach/mux.h>
+
+#define HAWKBOARD_PHY_ID		"0:07"
+#define DA850_HAWK_MMCSD_CD_PIN		GPIO_TO_PIN(3, 12)
+#define DA850_HAWK_MMCSD_WP_PIN		GPIO_TO_PIN(3, 13)
+
+#define DA850_USB1_VBUS_PIN		GPIO_TO_PIN(2, 4)
+#define DA850_USB1_OC_PIN		GPIO_TO_PIN(6, 13)
+
+static short omapl138_hawk_mii_pins[] __initdata = {
+	DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
+	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
+	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
+	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
+	DA850_MDIO_D,
+	-1
+};
+
+static __init void omapl138_hawk_config_emac(void)
+{
+	void __iomem *cfgchip3 = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
+	int ret;
+	u32 val;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	val = __raw_readl(cfgchip3);
+	val &= ~BIT(8);
+	ret = davinci_cfg_reg_list(omapl138_hawk_mii_pins);
+	if (ret) {
+		pr_warning("%s: cpgmac/mii mux setup failed: %d\n",
+			__func__, ret);
+		return;
+	}
+
+	/* configure the CFGCHIP3 register for MII */
+	__raw_writel(val, cfgchip3);
+	pr_info("EMAC: MII PHY configured\n");
+
+	soc_info->emac_pdata->phy_id = HAWKBOARD_PHY_ID;
+
+	ret = da8xx_register_emac();
+	if (ret)
+		pr_warning("%s: emac registration failed: %d\n",
+			__func__, ret);
+}
+
+/*
+ * The following EDMA channels/slots are not being used by drivers (for
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM/Hawkboard,
+ * hence they are being reserved for codecs on the DSP side.
+ */
+static const s16 da850_dma0_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 8,  6},
+	{24,  4},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da850_dma0_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 8,  6},
+	{24,  4},
+	{30, 50},
+	{-1, -1}
+};
+
+static const s16 da850_dma1_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 0, 28},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da850_dma1_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 0, 28},
+	{30, 90},
+	{-1, -1}
+};
+
+static struct edma_rsv_info da850_edma_cc0_rsv = {
+	.rsv_chans	= da850_dma0_rsv_chans,
+	.rsv_slots	= da850_dma0_rsv_slots,
+};
+
+static struct edma_rsv_info da850_edma_cc1_rsv = {
+	.rsv_chans	= da850_dma1_rsv_chans,
+	.rsv_slots	= da850_dma1_rsv_slots,
+};
+
+static struct edma_rsv_info *da850_edma_rsv[2] = {
+	&da850_edma_cc0_rsv,
+	&da850_edma_cc1_rsv,
+};
+
+static const short hawk_mmcsd0_pins[] = {
+	DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
+	DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
+	DA850_GPIO3_12, DA850_GPIO3_13,
+	-1
+};
+
+static int da850_hawk_mmc_get_ro(int index)
+{
+	return gpio_get_value(DA850_HAWK_MMCSD_WP_PIN);
+}
+
+static int da850_hawk_mmc_get_cd(int index)
+{
+	return !gpio_get_value(DA850_HAWK_MMCSD_CD_PIN);
+}
+
+static struct davinci_mmc_config da850_mmc_config = {
+	.get_ro		= da850_hawk_mmc_get_ro,
+	.get_cd		= da850_hawk_mmc_get_cd,
+	.wires		= 4,
+	.max_freq	= 50000000,
+	.caps		= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+	.version	= MMC_CTLR_VERSION_2,
+};
+
+static __init void omapl138_hawk_mmc_init(void)
+{
+	int ret;
+
+	ret = davinci_cfg_reg_list(hawk_mmcsd0_pins);
+	if (ret) {
+		pr_warning("%s: MMC/SD0 mux setup failed: %d\n",
+			__func__, ret);
+		return;
+	}
+
+	ret = gpio_request_one(DA850_HAWK_MMCSD_CD_PIN,
+			GPIOF_DIR_IN, "MMC CD");
+	if (ret < 0) {
+		pr_warning("%s: can not open GPIO %d\n",
+			__func__, DA850_HAWK_MMCSD_CD_PIN);
+		return;
+	}
+
+	ret = gpio_request_one(DA850_HAWK_MMCSD_WP_PIN,
+			GPIOF_DIR_IN, "MMC WP");
+	if (ret < 0) {
+		pr_warning("%s: can not open GPIO %d\n",
+			__func__, DA850_HAWK_MMCSD_WP_PIN);
+		goto mmc_setup_wp_fail;
+	}
+
+	ret = da8xx_register_mmcsd0(&da850_mmc_config);
+	if (ret) {
+		pr_warning("%s: MMC/SD0 registration failed: %d\n",
+			__func__, ret);
+		goto mmc_setup_mmcsd_fail;
+	}
+
+	return;
+
+mmc_setup_mmcsd_fail:
+	gpio_free(DA850_HAWK_MMCSD_WP_PIN);
+mmc_setup_wp_fail:
+	gpio_free(DA850_HAWK_MMCSD_CD_PIN);
+}
+
+static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id);
+static da8xx_ocic_handler_t hawk_usb_ocic_handler;
+
+static const short da850_hawk_usb11_pins[] = {
+	DA850_GPIO2_4, DA850_GPIO6_13,
+	-1
+};
+
+static int hawk_usb_set_power(unsigned port, int on)
+{
+	gpio_set_value(DA850_USB1_VBUS_PIN, on);
+	return 0;
+}
+
+static int hawk_usb_get_power(unsigned port)
+{
+	return gpio_get_value(DA850_USB1_VBUS_PIN);
+}
+
+static int hawk_usb_get_oci(unsigned port)
+{
+	return !gpio_get_value(DA850_USB1_OC_PIN);
+}
+
+static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler)
+{
+	int irq         = gpio_to_irq(DA850_USB1_OC_PIN);
+	int error       = 0;
+
+	if (handler != NULL) {
+		hawk_usb_ocic_handler = handler;
+
+		error = request_irq(irq, omapl138_hawk_usb_ocic_irq,
+					IRQF_DISABLED | IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING,
+					"OHCI over-current indicator", NULL);
+		if (error)
+			pr_err("%s: could not request IRQ to watch "
+				"over-current indicator changes\n", __func__);
+	} else {
+		free_irq(irq, NULL);
+	}
+	return error;
+}
+
+static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = {
+	.set_power      = hawk_usb_set_power,
+	.get_power      = hawk_usb_get_power,
+	.get_oci        = hawk_usb_get_oci,
+	.ocic_notify    = hawk_usb_ocic_notify,
+	/* TPS2087 switch @ 5V */
+	.potpgt         = (3 + 1) / 2,  /* 3 ms max */
+};
+
+static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
+{
+	hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1);
+	return IRQ_HANDLED;
+}
+
+static __init void omapl138_hawk_usb_init(void)
+{
+	int ret;
+	u32 cfgchip2;
+
+	ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
+	if (ret) {
+		pr_warning("%s: USB 1.1 PinMux setup failed: %d\n",
+			__func__, ret);
+		return;
+	}
+
+	/* Setup the Ref. clock frequency for the HAWK at 24 MHz. */
+
+	cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+	cfgchip2 &= ~CFGCHIP2_REFFREQ;
+	cfgchip2 |=  CFGCHIP2_REFFREQ_24MHZ;
+	__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	ret = gpio_request_one(DA850_USB1_VBUS_PIN,
+			GPIOF_DIR_OUT, "USB1 VBUS");
+	if (ret < 0) {
+		pr_err("%s: failed to request GPIO for USB 1.1 port "
+			"power control: %d\n", __func__, ret);
+		return;
+	}
+
+	ret = gpio_request_one(DA850_USB1_OC_PIN,
+			GPIOF_DIR_IN, "USB1 OC");
+	if (ret < 0) {
+		pr_err("%s: failed to request GPIO for USB 1.1 port "
+			"over-current indicator: %d\n", __func__, ret);
+		goto usb11_setup_oc_fail;
+	}
+
+	ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata);
+	if (ret) {
+		pr_warning("%s: USB 1.1 registration failed: %d\n",
+			__func__, ret);
+		goto usb11_setup_fail;
+	}
+
+	return;
+
+usb11_setup_fail:
+	gpio_free(DA850_USB1_OC_PIN);
+usb11_setup_oc_fail:
+	gpio_free(DA850_USB1_VBUS_PIN);
+}
 
 static struct davinci_uart_config omapl138_hawk_uart_config __initdata = {
 	.enabled_uarts = 0x7,
@@ -30,6 +303,17 @@ static __init void omapl138_hawk_init(void)
 
 	davinci_serial_init(&omapl138_hawk_uart_config);
 
+	omapl138_hawk_config_emac();
+
+	ret = da850_register_edma(da850_edma_rsv);
+	if (ret)
+		pr_warning("%s: EDMA registration failed: %d\n",
+			__func__, ret);
+
+	omapl138_hawk_mmc_init();
+
+	omapl138_hawk_usb_init();
+
 	ret = da8xx_register_watchdog();
 	if (ret)
 		pr_warning("omapl138_hawk_init: "
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index a6db854..1a656e8 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -25,6 +25,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/spi/spi.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -37,6 +38,7 @@
 
 #define EVM_MMC_WP_GPIO		21
 #define EVM_MMC_CD_GPIO		24
+#define EVM_SPI_CS_GPIO		54
 
 static int initialize_gpio(int gpio, char *desc)
 {
@@ -99,6 +101,12 @@ static const short uart1_pins[] __initdata = {
 	-1
 };
 
+static const short ssp_pins[] __initdata = {
+	TNETV107X_SSP0_0, TNETV107X_SSP0_1, TNETV107X_SSP0_2,
+	TNETV107X_SSP1_0, TNETV107X_SSP1_1, TNETV107X_SSP1_2,
+	TNETV107X_SSP1_3, -1
+};
+
 static struct mtd_partition nand_partitions[] = {
 	/* bootloader (U-Boot, etc) in first 12 sectors */
 	{
@@ -196,19 +204,68 @@ static struct matrix_keypad_platform_data keypad_config = {
 	.no_autorepeat	= 0,
 };
 
+static void spi_select_device(int cs)
+{
+	static int gpio;
+
+	if (!gpio) {
+		int ret;
+		ret = gpio_request(EVM_SPI_CS_GPIO, "spi chipsel");
+		if (ret < 0) {
+			pr_err("cannot open spi chipsel gpio\n");
+			gpio = -ENOSYS;
+			return;
+		} else {
+			gpio = EVM_SPI_CS_GPIO;
+			gpio_direction_output(gpio, 0);
+		}
+	}
+
+	if (gpio < 0)
+		return;
+
+	return gpio_set_value(gpio, cs ? 1 : 0);
+}
+
+static struct ti_ssp_spi_data spi_master_data = {
+	.num_cs	= 2,
+	.select	= spi_select_device,
+	.iosel	= SSP_PIN_SEL(0, SSP_CLOCK)	| SSP_PIN_SEL(1, SSP_DATA) |
+		  SSP_PIN_SEL(2, SSP_CHIPSEL)	| SSP_PIN_SEL(3, SSP_IN)   |
+		  SSP_INPUT_SEL(3),
+};
+
+static struct ti_ssp_data ssp_config = {
+	.out_clock	= 250 * 1000,
+	.dev_data	= {
+		[1] = {
+			.dev_name = "ti-ssp-spi",
+			.pdata = &spi_master_data,
+			.pdata_size = sizeof(spi_master_data),
+		},
+	},
+};
+
 static struct tnetv107x_device_info evm_device_info __initconst = {
 	.serial_config		= &serial_config,
 	.mmc_config[1]		= &mmc_config,	/* controller 1 */
 	.nand_config[0]		= &nand_config,	/* chip select 0 */
 	.keypad_config		= &keypad_config,
+	.ssp_config		= &ssp_config,
+};
+
+static struct spi_board_info spi_info[] __initconst = {
 };
 
 static __init void tnetv107x_evm_board_init(void)
 {
 	davinci_cfg_reg_list(sdio1_pins);
 	davinci_cfg_reg_list(uart1_pins);
+	davinci_cfg_reg_list(ssp_pins);
 
 	tnetv107x_devices_init(&evm_device_info);
+
+	spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index ec23ab4..2ed2f82 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -148,7 +148,7 @@ static struct clk scr2_ss_clk = {
 static struct clk dmax_clk = {
 	.name		= "dmax",
 	.parent		= &pll0_sysclk2,
-	.lpsc		= DA8XX_LPSC0_DMAX,
+	.lpsc		= DA8XX_LPSC0_PRUSS,
 	.flags		= ALWAYS_ENABLED,
 };
 
@@ -397,8 +397,8 @@ static struct clk_lookup da830_clks[] = {
 	CLK(NULL,		"uart0",	&uart0_clk),
 	CLK(NULL,		"uart1",	&uart1_clk),
 	CLK(NULL,		"uart2",	&uart2_clk),
-	CLK("dm_spi.0",		NULL,		&spi0_clk),
-	CLK("dm_spi.1",		NULL,		&spi1_clk),
+	CLK("spi_davinci.0",	NULL,		&spi0_clk),
+	CLK("spi_davinci.1",	NULL,		&spi1_clk),
 	CLK(NULL,		"ecap0",	&ecap0_clk),
 	CLK(NULL,		"ecap1",	&ecap1_clk),
 	CLK(NULL,		"ecap2",	&ecap2_clk),
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 78b5ae2..68fe4c2 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -345,6 +345,34 @@ static struct clk aemif_clk = {
 	.flags		= ALWAYS_ENABLED,
 };
 
+static struct clk usb11_clk = {
+	.name		= "usb11",
+	.parent		= &pll0_sysclk4,
+	.lpsc		= DA8XX_LPSC1_USB11,
+	.gpsc		= 1,
+};
+
+static struct clk usb20_clk = {
+	.name		= "usb20",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC1_USB20,
+	.gpsc		= 1,
+};
+
+static struct clk spi0_clk = {
+	.name		= "spi0",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC0_SPI0,
+};
+
+static struct clk spi1_clk = {
+	.name		= "spi1",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC1_SPI1,
+	.gpsc		= 1,
+	.flags		= DA850_CLK_ASYNC3,
+};
+
 static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"ref",		&ref_clk),
 	CLK(NULL,		"pll0",		&pll0_clk),
@@ -387,6 +415,10 @@ static struct clk_lookup da850_clks[] = {
 	CLK("davinci_mmc.0",	NULL,		&mmcsd0_clk),
 	CLK("davinci_mmc.1",	NULL,		&mmcsd1_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
+	CLK(NULL,		"usb11",	&usb11_clk),
+	CLK(NULL,		"usb20",	&usb20_clk),
+	CLK("spi_davinci.0",	NULL,		&spi0_clk),
+	CLK("spi_davinci.1",	NULL,		&spi1_clk),
 	CLK(NULL,		NULL,		NULL),
 };
 
@@ -543,30 +575,19 @@ static const struct mux_config da850_pins[] = {
 	MUX_CFG(DA850, EMA_WAIT_1,	6,	24,	15,	1,	false)
 	MUX_CFG(DA850, NEMA_CS_2,	7,	0,	15,	1,	false)
 	/* GPIO function */
+	MUX_CFG(DA850, GPIO2_4,		6,	12,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_6,		6,	4,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_8,		5,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_15,	5,	0,	15,	8,	false)
+	MUX_CFG(DA850, GPIO3_12,	7,	12,	15,	8,	false)
+	MUX_CFG(DA850, GPIO3_13,	7,	8,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_0,		10,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_1,		10,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_13,	13,	8,	15,	8,	false)
 	MUX_CFG(DA850, RTC_ALARM,	0,	28,	15,	2,	false)
 #endif
 };
 
-const short da850_uart0_pins[] __initdata = {
-	DA850_NUART0_CTS, DA850_NUART0_RTS, DA850_UART0_RXD, DA850_UART0_TXD,
-	-1
-};
-
-const short da850_uart1_pins[] __initdata = {
-	DA850_UART1_RXD, DA850_UART1_TXD,
-	-1
-};
-
-const short da850_uart2_pins[] __initdata = {
-	DA850_UART2_RXD, DA850_UART2_TXD,
-	-1
-};
-
 const short da850_i2c0_pins[] __initdata = {
 	DA850_I2C0_SDA, DA850_I2C0_SCL,
 	-1
@@ -577,24 +598,6 @@ const short da850_i2c1_pins[] __initdata = {
 	-1
 };
 
-const short da850_cpgmac_pins[] __initdata = {
-	DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
-	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
-	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
-	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
-	DA850_MDIO_D, DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
-	DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER,
-	DA850_RMII_MHZ_50_CLK,
-	-1
-};
-
-const short da850_mcasp_pins[] __initdata = {
-	DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
-	DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE,
-	DA850_AXR_11, DA850_AXR_12,
-	-1
-};
-
 const short da850_lcdcntl_pins[] __initdata = {
 	DA850_LCD_D_0, DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3,
 	DA850_LCD_D_4, DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7,
@@ -604,29 +607,6 @@ const short da850_lcdcntl_pins[] __initdata = {
 	-1
 };
 
-const short da850_mmcsd0_pins[] __initdata = {
-	DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
-	DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
-	DA850_GPIO4_0, DA850_GPIO4_1,
-	-1
-};
-
-const short da850_emif25_pins[] __initdata = {
-	DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
-	DA850_NEMA_CS_3, DA850_NEMA_CS_4, DA850_NEMA_WE, DA850_NEMA_OE,
-	DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
-	DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
-	DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
-	DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
-	DA850_EMA_A_0, DA850_EMA_A_1, DA850_EMA_A_2, DA850_EMA_A_3,
-	DA850_EMA_A_4, DA850_EMA_A_5, DA850_EMA_A_6, DA850_EMA_A_7,
-	DA850_EMA_A_8, DA850_EMA_A_9, DA850_EMA_A_10, DA850_EMA_A_11,
-	DA850_EMA_A_12, DA850_EMA_A_13, DA850_EMA_A_14, DA850_EMA_A_15,
-	DA850_EMA_A_16, DA850_EMA_A_17, DA850_EMA_A_18, DA850_EMA_A_19,
-	DA850_EMA_A_20, DA850_EMA_A_21, DA850_EMA_A_22, DA850_EMA_A_23,
-	-1
-};
-
 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 static u8 da850_default_priorities[DA850_N_CP_INTC_IRQ] = {
 	[IRQ_DA8XX_COMMTX]		= 7,
@@ -764,6 +744,13 @@ static struct davinci_id da850_ids[] = {
 		.cpu_id		= DAVINCI_CPU_ID_DA850,
 		.name		= "da850/omap-l138",
 	},
+	{
+		.variant	= 0x1,
+		.part_no	= 0xb7d1,
+		.manufacturer	= 0x017,	/* 0x02f >> 1 */
+		.cpu_id		= DAVINCI_CPU_ID_DA850,
+		.name		= "da850/omap-l138/am18x",
+	},
 };
 
 static struct davinci_timer_instance da850_timer_instance[4] = {
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index beda8a4..625d4b6 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -38,12 +38,23 @@
 #define DA8XX_EMAC_MDIO_BASE		0x01e24000
 #define DA8XX_GPIO_BASE			0x01e26000
 #define DA8XX_I2C1_BASE			0x01e28000
+#define DA8XX_SPI0_BASE			0x01c41000
+#define DA8XX_SPI1_BASE			0x01f0e000
 
 #define DA8XX_EMAC_CTRL_REG_OFFSET	0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET	0x2000
 #define DA8XX_EMAC_RAM_OFFSET		0x0000
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 
+#define DA8XX_DMA_SPI0_RX	EDMA_CTLR_CHAN(0, 14)
+#define DA8XX_DMA_SPI0_TX	EDMA_CTLR_CHAN(0, 15)
+#define DA8XX_DMA_MMCSD0_RX	EDMA_CTLR_CHAN(0, 16)
+#define DA8XX_DMA_MMCSD0_TX	EDMA_CTLR_CHAN(0, 17)
+#define DA8XX_DMA_SPI1_RX	EDMA_CTLR_CHAN(0, 18)
+#define DA8XX_DMA_SPI1_TX	EDMA_CTLR_CHAN(0, 19)
+#define DA850_DMA_MMCSD1_RX	EDMA_CTLR_CHAN(1, 28)
+#define DA850_DMA_MMCSD1_TX	EDMA_CTLR_CHAN(1, 29)
+
 void __iomem *da8xx_syscfg0_base;
 void __iomem *da8xx_syscfg1_base;
 
@@ -573,13 +584,13 @@ static struct resource da8xx_mmcsd0_resources[] = {
 		.flags	= IORESOURCE_IRQ,
 	},
 	{		/* DMA RX */
-		.start	= EDMA_CTLR_CHAN(0, 16),
-		.end	= EDMA_CTLR_CHAN(0, 16),
+		.start	= DA8XX_DMA_MMCSD0_RX,
+		.end	= DA8XX_DMA_MMCSD0_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 	{		/* DMA TX */
-		.start	= EDMA_CTLR_CHAN(0, 17),
-		.end	= EDMA_CTLR_CHAN(0, 17),
+		.start	= DA8XX_DMA_MMCSD0_TX,
+		.end	= DA8XX_DMA_MMCSD0_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
@@ -610,13 +621,13 @@ static struct resource da850_mmcsd1_resources[] = {
 		.flags	= IORESOURCE_IRQ,
 	},
 	{		/* DMA RX */
-		.start	= EDMA_CTLR_CHAN(1, 28),
-		.end	= EDMA_CTLR_CHAN(1, 28),
+		.start	= DA850_DMA_MMCSD1_RX,
+		.end	= DA850_DMA_MMCSD1_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 	{		/* DMA TX */
-		.start	= EDMA_CTLR_CHAN(1, 29),
-		.end	= EDMA_CTLR_CHAN(1, 29),
+		.start	= DA850_DMA_MMCSD1_TX,
+		.end	= DA850_DMA_MMCSD1_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
@@ -725,3 +736,101 @@ int __init da8xx_register_cpuidle(void)
 
 	return platform_device_register(&da8xx_cpuidle_device);
 }
+
+static struct resource da8xx_spi0_resources[] = {
+	[0] = {
+		.start	= DA8XX_SPI0_BASE,
+		.end	= DA8XX_SPI0_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DA8XX_SPINT0,
+		.end	= IRQ_DA8XX_SPINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= DA8XX_DMA_SPI0_RX,
+		.end	= DA8XX_DMA_SPI0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DA8XX_DMA_SPI0_TX,
+		.end	= DA8XX_DMA_SPI0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource da8xx_spi1_resources[] = {
+	[0] = {
+		.start	= DA8XX_SPI1_BASE,
+		.end	= DA8XX_SPI1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DA8XX_SPINT1,
+		.end	= IRQ_DA8XX_SPINT1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= DA8XX_DMA_SPI1_RX,
+		.end	= DA8XX_DMA_SPI1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DA8XX_DMA_SPI1_TX,
+		.end	= DA8XX_DMA_SPI1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct davinci_spi_platform_data da8xx_spi_pdata[] = {
+	[0] = {
+		.version	= SPI_VERSION_2,
+		.intr_line	= 1,
+		.dma_event_q	= EVENTQ_0,
+	},
+	[1] = {
+		.version	= SPI_VERSION_2,
+		.intr_line	= 1,
+		.dma_event_q	= EVENTQ_0,
+	},
+};
+
+static struct platform_device da8xx_spi_device[] = {
+	[0] = {
+		.name		= "spi_davinci",
+		.id		= 0,
+		.num_resources	= ARRAY_SIZE(da8xx_spi0_resources),
+		.resource	= da8xx_spi0_resources,
+		.dev		= {
+			.platform_data = &da8xx_spi_pdata[0],
+		},
+	},
+	[1] = {
+		.name		= "spi_davinci",
+		.id		= 1,
+		.num_resources	= ARRAY_SIZE(da8xx_spi1_resources),
+		.resource	= da8xx_spi1_resources,
+		.dev		= {
+			.platform_data = &da8xx_spi_pdata[1],
+		},
+	},
+};
+
+int __init da8xx_register_spi(int instance, struct spi_board_info *info,
+			      unsigned len)
+{
+	int ret;
+
+	if (instance < 0 || instance > 1)
+		return -EINVAL;
+
+	ret = spi_register_board_info(info, len);
+	if (ret)
+		pr_warning("%s: failed to register board info for spi %d :"
+			   " %d\n", __func__, instance, ret);
+
+	da8xx_spi_pdata[instance].num_chipselect = len;
+
+	return platform_device_register(&da8xx_spi_device[instance]);
+}
diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c
index 85503deb..6162cae 100644
--- a/arch/arm/mach-davinci/devices-tnetv107x.c
+++ b/arch/arm/mach-davinci/devices-tnetv107x.c
@@ -35,6 +35,7 @@
 #define TNETV107X_SDIO0_BASE			0x08088700
 #define TNETV107X_SDIO1_BASE			0x08088800
 #define TNETV107X_KEYPAD_BASE			0x08088a00
+#define TNETV107X_SSP_BASE			0x08088c00
 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE		0x08200000
 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE	0x30000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE	0x40000000
@@ -342,6 +343,25 @@ static struct platform_device tsc_device = {
 	.resource	= tsc_resources,
 };
 
+static struct resource ssp_resources[] = {
+	{
+		.start	= TNETV107X_SSP_BASE,
+		.end	= TNETV107X_SSP_BASE + 0x1ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_TNETV107X_SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ssp_device = {
+	.name		= "ti-ssp",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ssp_resources),
+	.resource	= ssp_resources,
+};
+
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
 	int i, error;
@@ -380,4 +400,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 		keypad_device.dev.platform_data = info->keypad_config;
 		platform_device_register(&keypad_device);
 	}
+
+	if (info->ssp_config) {
+		ssp_device.dev.platform_data = info->ssp_config;
+		platform_device_register(&ssp_device);
+	}
 }
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c
index a5f8a80..76364d1 100644
--- a/arch/arm/mach-davinci/dm355.c
+++ b/arch/arm/mach-davinci/dm355.c
@@ -403,16 +403,13 @@ static struct resource dm355_spi0_resources[] = {
 		.start = 16,
 		.flags = IORESOURCE_DMA,
 	},
-	{
-		.start = EVENTQ_1,
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct davinci_spi_platform_data dm355_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
 	.cshold_bug	= true,
+	.dma_event_q	= EVENTQ_1,
 };
 static struct platform_device dm355_spi0_device = {
 	.name = "spi_davinci",
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c
index 02d2cc3..4604e72 100644
--- a/arch/arm/mach-davinci/dm365.c
+++ b/arch/arm/mach-davinci/dm365.c
@@ -625,6 +625,7 @@ static u64 dm365_spi0_dma_mask = DMA_BIT_MASK(32);
 static struct davinci_spi_platform_data dm365_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
+	.dma_event_q	= EVENTQ_3,
 };
 
 static struct resource dm365_spi0_resources[] = {
@@ -645,10 +646,6 @@ static struct resource dm365_spi0_resources[] = {
 		.start = 16,
 		.flags = IORESOURCE_DMA,
 	},
-	{
-		.start = EVENTQ_3,
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device dm365_spi0_device = {
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index e7f9520..e4fc1af 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -15,6 +15,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/davinci_emac.h>
+#include <linux/spi/spi.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -23,6 +24,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 #include <mach/pm.h>
+#include <mach/spi.h>
 
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
@@ -77,6 +79,7 @@ void __init da850_init(void);
 int da830_register_edma(struct edma_rsv_info *rsv);
 int da850_register_edma(struct edma_rsv_info *rsv[2]);
 int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
+int da8xx_register_spi(int instance, struct spi_board_info *info, unsigned len);
 int da8xx_register_watchdog(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
@@ -95,6 +98,7 @@ extern struct platform_device da8xx_serial_device;
 extern struct emac_platform_data da8xx_emac_pdata;
 extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata;
 extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata;
+extern struct davinci_spi_platform_data da8xx_spi_pdata[];
 
 extern struct platform_device da8xx_wdt_device;
 
@@ -123,15 +127,8 @@ extern const short da830_ecap2_pins[];
 extern const short da830_eqep0_pins[];
 extern const short da830_eqep1_pins[];
 
-extern const short da850_uart0_pins[];
-extern const short da850_uart1_pins[];
-extern const short da850_uart2_pins[];
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
-extern const short da850_cpgmac_pins[];
-extern const short da850_mcasp_pins[];
 extern const short da850_lcdcntl_pins[];
-extern const short da850_mmcsd0_pins[];
-extern const short da850_emif25_pins[];
 
 #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */
diff --git a/arch/arm/mach-davinci/include/mach/edma.h b/arch/arm/mach-davinci/include/mach/edma.h
index dc10ef6..20c77f2 100644
--- a/arch/arm/mach-davinci/include/mach/edma.h
+++ b/arch/arm/mach-davinci/include/mach/edma.h
@@ -151,42 +151,6 @@ struct edmacc_param {
 #define DA830_DMACH2EVENT_MAP1		0x00000000u
 #define DA830_EDMA_ARM_OWN		0x30FFCCFFu
 
-/* DA830 specific EDMA3 Events Information */
-enum DA830_edma_ch {
-	DA830_DMACH_MCASP0_RX,
-	DA830_DMACH_MCASP0_TX,
-	DA830_DMACH_MCASP1_RX,
-	DA830_DMACH_MCASP1_TX,
-	DA830_DMACH_MCASP2_RX,
-	DA830_DMACH_MCASP2_TX,
-	DA830_DMACH_GPIO_BNK0INT,
-	DA830_DMACH_GPIO_BNK1INT,
-	DA830_DMACH_UART0_RX,
-	DA830_DMACH_UART0_TX,
-	DA830_DMACH_TMR64P0_EVTOUT12,
-	DA830_DMACH_TMR64P0_EVTOUT34,
-	DA830_DMACH_UART1_RX,
-	DA830_DMACH_UART1_TX,
-	DA830_DMACH_SPI0_RX,
-	DA830_DMACH_SPI0_TX,
-	DA830_DMACH_MMCSD_RX,
-	DA830_DMACH_MMCSD_TX,
-	DA830_DMACH_SPI1_RX,
-	DA830_DMACH_SPI1_TX,
-	DA830_DMACH_DMAX_EVTOUT6,
-	DA830_DMACH_DMAX_EVTOUT7,
-	DA830_DMACH_GPIO_BNK2INT,
-	DA830_DMACH_GPIO_BNK3INT,
-	DA830_DMACH_I2C0_RX,
-	DA830_DMACH_I2C0_TX,
-	DA830_DMACH_I2C1_RX,
-	DA830_DMACH_I2C1_TX,
-	DA830_DMACH_GPIO_BNK4INT,
-	DA830_DMACH_GPIO_BNK5INT,
-	DA830_DMACH_UART2_RX,
-	DA830_DMACH_UART2_TX
-};
-
 /*ch_status paramater of callback function possible values*/
 #define DMA_COMPLETE 1
 #define DMA_CC_ERROR 2
diff --git a/arch/arm/mach-davinci/include/mach/memory.h b/arch/arm/mach-davinci/include/mach/memory.h
index 22eb97c..7882272 100644
--- a/arch/arm/mach-davinci/include/mach/memory.h
+++ b/arch/arm/mach-davinci/include/mach/memory.h
@@ -26,9 +26,9 @@
 #if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx)
 #error Cannot enable DaVinci and DA8XX platforms concurrently
 #elif defined(CONFIG_ARCH_DAVINCI_DA8XX)
-#define PHYS_OFFSET DA8XX_DDR_BASE
+#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE
 #else
-#define PHYS_OFFSET DAVINCI_DDR_BASE
+#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE
 #endif
 
 #define DDR2_SDRCR_OFFSET	0xc
diff --git a/arch/arm/mach-davinci/include/mach/mux.h b/arch/arm/mach-davinci/include/mach/mux.h
index de11aac..5d4e0fe 100644
--- a/arch/arm/mach-davinci/include/mach/mux.h
+++ b/arch/arm/mach-davinci/include/mach/mux.h
@@ -908,11 +908,15 @@ enum davinci_da850_index {
 	DA850_NEMA_CS_2,
 
 	/* GPIO function */
+	DA850_GPIO2_4,
 	DA850_GPIO2_6,
 	DA850_GPIO2_8,
 	DA850_GPIO2_15,
+	DA850_GPIO3_12,
+	DA850_GPIO3_13,
 	DA850_GPIO4_0,
 	DA850_GPIO4_1,
+	DA850_GPIO6_13,
 	DA850_RTC_ALARM,
 };
 
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 62b0858..a47e6f2 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -150,7 +150,7 @@
 #define DA8XX_LPSC0_SCR0_SS		10
 #define DA8XX_LPSC0_SCR1_SS		11
 #define DA8XX_LPSC0_SCR2_SS		12
-#define DA8XX_LPSC0_DMAX		13
+#define DA8XX_LPSC0_PRUSS		13
 #define DA8XX_LPSC0_ARM			14
 #define DA8XX_LPSC0_GEM			15
 
diff --git a/arch/arm/mach-davinci/include/mach/spi.h b/arch/arm/mach-davinci/include/mach/spi.h
index 38f4da5..7af305b 100644
--- a/arch/arm/mach-davinci/include/mach/spi.h
+++ b/arch/arm/mach-davinci/include/mach/spi.h
@@ -19,6 +19,8 @@
 #ifndef __ARCH_ARM_DAVINCI_SPI_H
 #define __ARCH_ARM_DAVINCI_SPI_H
 
+#include <mach/edma.h>
+
 #define SPI_INTERN_CS	0xFF
 
 enum {
@@ -39,13 +41,16 @@ enum {
  *		to populate if all chip-selects are internal.
  * @cshold_bug:	set this to true if the SPI controller on your chip requires
  *		a write to CSHOLD bit in between transfers (like in DM355).
+ * @dma_event_q: DMA event queue to use if SPI_IO_TYPE_DMA is used for any
+ *		device on the bus.
  */
 struct davinci_spi_platform_data {
-	u8	version;
-	u8	num_chipselect;
-	u8	intr_line;
-	u8	*chip_sel;
-	bool	cshold_bug;
+	u8			version;
+	u8			num_chipselect;
+	u8			intr_line;
+	u8			*chip_sel;
+	bool			cshold_bug;
+	enum dma_event_q	dma_event_q;
 };
 
 /**
diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h
index 5a681d8..89c1fdc 100644
--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h
+++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h
@@ -34,6 +34,7 @@
 
 #include <linux/serial_8250.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/mfd/ti_ssp.h>
 
 #include <mach/mmc.h>
 #include <mach/nand.h>
@@ -44,6 +45,7 @@ struct tnetv107x_device_info {
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
 	struct davinci_nand_pdata	*nand_config[4]; /* 4 chipsels */
 	struct matrix_keypad_platform_data *keypad_config;
+	struct ti_ssp_data		*ssp_config;
 };
 
 extern struct platform_device tnetv107x_wdt_device;
diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c
index 6fcdece..1b28fdd 100644
--- a/arch/arm/mach-davinci/tnetv107x.c
+++ b/arch/arm/mach-davinci/tnetv107x.c
@@ -278,7 +278,7 @@ static struct clk_lookup clks[] = {
 	CLK(NULL,		"timer1",		&clk_timer1),
 	CLK("tnetv107x_wdt.0",	NULL,			&clk_wdt_arm),
 	CLK(NULL,		"clk_wdt_dsp",		&clk_wdt_dsp),
-	CLK("ti-ssp.0",		NULL,			&clk_ssp),
+	CLK("ti-ssp",		NULL,			&clk_ssp),
 	CLK(NULL,		"clk_tdm0",		&clk_tdm0),
 	CLK(NULL,		"clk_vlynq",		&clk_vlynq),
 	CLK(NULL,		"clk_mcdma",		&clk_mcdma),
diff --git a/arch/arm/mach-dove/Kconfig b/arch/arm/mach-dove/Kconfig
index a4ed390..dd937c5 100644
--- a/arch/arm/mach-dove/Kconfig
+++ b/arch/arm/mach-dove/Kconfig
@@ -9,7 +9,7 @@ config MACH_DOVE_DB
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell DB-MV88AP510 Development Board.
 
- config MACH_CM_A510
+config MACH_CM_A510
 	bool "CompuLab CM-A510 Board"
 	help
 	  Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c
index 96e0e94..03e11f9 100644
--- a/arch/arm/mach-dove/cm-a510.c
+++ b/arch/arm/mach-dove/cm-a510.c
@@ -90,6 +90,7 @@ MACHINE_START(CM_A510, "Compulab CM-A510 Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= cm_a510_init,
 	.map_io		= dove_map_io,
+	.init_early	= dove_init_early,
 	.init_irq	= dove_init_irq,
 	.timer		= &dove_timer,
 MACHINE_END
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index fe627ab..e06a88f 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -532,6 +532,11 @@ void __init dove_i2c_init(void)
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init dove_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 static int get_tclk(void)
 {
 	/* use DOVE_RESET_SAMPLE_HI/LO to detect tclk */
@@ -540,7 +545,8 @@ static int get_tclk(void)
 
 static void dove_timer_init(void)
 {
-	orion_time_init(IRQ_DOVE_BRIDGE, get_tclk());
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_DOVE_BRIDGE, get_tclk());
 }
 
 struct sys_timer dove_timer = {
diff --git a/arch/arm/mach-dove/common.h b/arch/arm/mach-dove/common.h
index a51517c..6a2046e 100644
--- a/arch/arm/mach-dove/common.h
+++ b/arch/arm/mach-dove/common.h
@@ -22,6 +22,7 @@ extern struct mbus_dram_target_info dove_mbus_dram_info;
  */
 void dove_map_io(void);
 void dove_init(void);
+void dove_init_early(void);
 void dove_init_irq(void);
 void dove_setup_cpu_mbus(void);
 void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data);
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index 95925aa..2ac34ec 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -97,6 +97,7 @@ MACHINE_START(DOVE_DB, "Marvell DB-MV88AP510-BP Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= dove_db_init,
 	.map_io		= dove_map_io,
+	.init_early	= dove_init_early,
 	.init_irq	= dove_init_irq,
 	.timer		= &dove_timer,
 MACHINE_END
diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h
index 214a4c3..226949d 100644
--- a/arch/arm/mach-dove/include/mach/bridge-regs.h
+++ b/arch/arm/mach-dove/include/mach/bridge-regs.h
@@ -26,10 +26,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define  SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define  BRIDGE_INT_TIMER0	0x0002
-#define  BRIDGE_INT_TIMER1	0x0004
 #define  BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/include/mach/dove.h
index 27b4145..e5fcdd3 100644
--- a/arch/arm/mach-dove/include/mach/dove.h
+++ b/arch/arm/mach-dove/include/mach/dove.h
@@ -130,7 +130,8 @@
 #define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
 #define DOVE_RESET_SAMPLE_LO	(DOVE_MPP_VIRT_BASE | 0x014)
 #define DOVE_RESET_SAMPLE_HI	(DOVE_MPP_VIRT_BASE | 0x018)
-#define DOVE_GPIO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO_LO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO_HI_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0420)
 #define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe8400)
 #define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe803c)
 #define  DOVE_AU1_SPDIFO_GPIO_EN	(1 << 1)
diff --git a/arch/arm/mach-dove/include/mach/gpio.h b/arch/arm/mach-dove/include/mach/gpio.h
index 340bb7a..e7e5101 100644
--- a/arch/arm/mach-dove/include/mach/gpio.h
+++ b/arch/arm/mach-dove/include/mach/gpio.h
@@ -6,46 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <asm/errno.h>
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define GPIO_MAX	72
-
-#define GPIO_BASE_LO		(DOVE_GPIO_VIRT_BASE + 0x00)
-#define GPIO_BASE_HI		(DOVE_GPIO_VIRT_BASE + 0x20)
-
-#define GPIO_BASE(pin)		((pin < 32) ? GPIO_BASE_LO :		\
-				 ((pin < 64) ? GPIO_BASE_HI :		\
-				  DOVE_GPIO2_VIRT_BASE))
-
-#define GPIO_OUT(pin)		(GPIO_BASE(pin) + 0x00)
-#define GPIO_IO_CONF(pin)	(GPIO_BASE(pin) + 0x04)
-#define GPIO_BLINK_EN(pin)	(GPIO_BASE(pin) + 0x08)
-#define GPIO_IN_POL(pin)	(GPIO_BASE(pin) + 0x0c)
-#define GPIO_DATA_IN(pin)	(GPIO_BASE(pin) + 0x10)
-#define GPIO_EDGE_CAUSE(pin)	(GPIO_BASE(pin) + 0x14)
-#define GPIO_EDGE_MASK(pin)	(GPIO_BASE(pin) + 0x18)
-#define GPIO_LEVEL_MASK(pin)	(GPIO_BASE(pin) + 0x1c)
-
-static inline int gpio_to_irq(int pin)
-{
-	if (pin < NR_GPIO_IRQS)
-		return pin + IRQ_DOVE_GPIO_START;
-
-	return -EINVAL;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	if (IRQ_DOVE_GPIO_START < irq && irq < NR_IRQS)
-		return irq - IRQ_DOVE_GPIO_START;
-
-	return -EINVAL;
-}
-
-#endif
diff --git a/arch/arm/mach-dove/include/mach/irqs.h b/arch/arm/mach-dove/include/mach/irqs.h
index 4668146..03d401d 100644
--- a/arch/arm/mach-dove/include/mach/irqs.h
+++ b/arch/arm/mach-dove/include/mach/irqs.h
@@ -92,10 +92,5 @@
 
 #define NR_IRQS			(IRQ_DOVE_PMU_START + NR_PMU_IRQS)
 
-/* Required for compatability with PXA AC97 driver.	*/
-#define IRQ_AC97		IRQ_DOVE_AC97
-/* Required for compatability with PXA DMA driver.	*/
-#define IRQ_DMA			IRQ_DOVE_PDMA
-/* Required for compatability with PXA NAND driver 	*/
-#define IRQ_NAND		IRQ_DOVE_NAND
+
 #endif
diff --git a/arch/arm/mach-dove/include/mach/memory.h b/arch/arm/mach-dove/include/mach/memory.h
index d668720..bbc93fe 100644
--- a/arch/arm/mach-dove/include/mach/memory.h
+++ b/arch/arm/mach-dove/include/mach/memory.h
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c
index 9317f05..101707f 100644
--- a/arch/arm/mach-dove/irq.c
+++ b/arch/arm/mach-dove/irq.c
@@ -99,11 +99,21 @@ void __init dove_init_irq(void)
 	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts.
+	 * Initialize gpiolib for GPIOs 0-71.
 	 */
-	writel(0, GPIO_LEVEL_MASK(0));
-	writel(0, GPIO_EDGE_MASK(0));
-	writel(0, GPIO_EDGE_CAUSE(0));
+	orion_gpio_init(0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
+			IRQ_DOVE_GPIO_START);
+	set_irq_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler);
+	set_irq_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler);
+	set_irq_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler);
+	set_irq_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler);
+
+	orion_gpio_init(32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
+			IRQ_DOVE_GPIO_START + 32);
+	set_irq_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
+
+	orion_gpio_init(64, 8, DOVE_GPIO2_VIRT_BASE, 0,
+			IRQ_DOVE_GPIO_START + 64);
 
 	/*
 	 * Mask and clear PMU interrupts
@@ -111,18 +121,6 @@ void __init dove_init_irq(void)
 	writel(0, PMU_INTERRUPT_MASK);
 	writel(0, PMU_INTERRUPT_CAUSE);
 
-	for (i = IRQ_DOVE_GPIO_START; i < IRQ_DOVE_PMU_START; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
-
 	for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) {
 		set_irq_chip(i, &pmu_irq_chip);
 		set_irq_handler(i, handle_level_irq);
diff --git a/arch/arm/mach-ebsa110/include/mach/memory.h b/arch/arm/mach-ebsa110/include/mach/memory.h
index 0ca66d0..8e49066 100644
--- a/arch/arm/mach-ebsa110/include/mach/memory.h
+++ b/arch/arm/mach-ebsa110/include/mach/memory.h
@@ -19,7 +19,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 /*
  * Cache flushing area - SRAM
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index 4b04316..9969bb1 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -30,8 +30,13 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+
+#include <sound/cs4271.h>
 
 #include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -93,6 +98,83 @@ static void __init edb93xx_register_i2c(void)
 
 
 /*************************************************************************
+ * EDB93xx SPI peripheral handling
+ *************************************************************************/
+static struct cs4271_platform_data edb93xx_cs4271_data = {
+	.gpio_nreset	= -EINVAL,	/* filled in later */
+};
+
+static int edb93xx_cs4271_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6,
+				GPIOF_OUT_INIT_HIGH, spi->modalias);
+}
+
+static void edb93xx_cs4271_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(EP93XX_GPIO_LINE_EGPIO6);
+}
+
+static void edb93xx_cs4271_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value);
+}
+
+static struct ep93xx_spi_chip_ops edb93xx_cs4271_hw = {
+	.setup		= edb93xx_cs4271_hw_setup,
+	.cleanup	= edb93xx_cs4271_hw_cleanup,
+	.cs_control	= edb93xx_cs4271_hw_cs_control,
+};
+
+static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
+	{
+		.modalias		= "cs4271",
+		.platform_data		= &edb93xx_cs4271_data,
+		.controller_data	= &edb93xx_cs4271_hw,
+		.max_speed_hz		= 6000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
+	.num_chipselect	= ARRAY_SIZE(edb93xx_spi_board_info),
+};
+
+static void __init edb93xx_register_spi(void)
+{
+	if (machine_is_edb9301() || machine_is_edb9302())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO1;
+	else if (machine_is_edb9302a() || machine_is_edb9307a())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_H(2);
+	else if (machine_is_edb9315a())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO14;
+
+	ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
+			    ARRAY_SIZE(edb93xx_spi_board_info));
+}
+
+
+/*************************************************************************
+ * EDB93xx I2S
+ *************************************************************************/
+static int __init edb93xx_has_audio(void)
+{
+	return (machine_is_edb9301() || machine_is_edb9302() ||
+		machine_is_edb9302a() || machine_is_edb9307a() ||
+		machine_is_edb9315a());
+}
+
+static void __init edb93xx_register_i2s(void)
+{
+	if (edb93xx_has_audio()) {
+		ep93xx_register_i2s();
+	}
+}
+
+
+/*************************************************************************
  * EDB93xx pwm
  *************************************************************************/
 static void __init edb93xx_register_pwm(void)
@@ -111,13 +193,47 @@ static void __init edb93xx_register_pwm(void)
 }
 
 
+/*************************************************************************
+ * EDB93xx framebuffer
+ *************************************************************************/
+static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
+	.num_modes	= EP93XXFB_USE_MODEDB,
+	.bpp		= 16,
+	.flags		= 0,
+};
+
+static int __init edb93xx_has_fb(void)
+{
+	/* These platforms have an ep93xx with video capability */
+	return machine_is_edb9307() || machine_is_edb9307a() ||
+	       machine_is_edb9312() || machine_is_edb9315() ||
+	       machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_fb(void)
+{
+	if (!edb93xx_has_fb())
+		return;
+
+	if (machine_is_edb9307a() || machine_is_edb9315a())
+		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
+	else
+		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;
+
+	ep93xx_register_fb(&edb93xxfb_info);
+}
+
+
 static void __init edb93xx_init_machine(void)
 {
 	ep93xx_init_devices();
 	edb93xx_register_flash();
 	ep93xx_register_eth(&edb93xx_eth_data, 1);
 	edb93xx_register_i2c();
+	edb93xx_register_spi();
+	edb93xx_register_i2s();
 	edb93xx_register_pwm();
+	edb93xx_register_fb();
 }
 
 
diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c
index bec34b8..a889fa7 100644
--- a/arch/arm/mach-ep93xx/gpio.c
+++ b/arch/arm/mach-ep93xx/gpio.c
@@ -61,7 +61,7 @@ static inline void ep93xx_gpio_int_mask(unsigned line)
 	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
 }
 
-void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
+static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
 {
 	int line = irq_to_gpio(irq);
 	int port = line >> 3;
@@ -75,7 +75,6 @@ void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
 	__raw_writeb(gpio_int_debounce[port],
 		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
 }
-EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
 
 static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
@@ -335,6 +334,20 @@ static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
 	local_irq_restore(flags);
 }
 
+static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
+				    unsigned offset, unsigned debounce)
+{
+	int gpio = chip->base + offset;
+	int irq = gpio_to_irq(gpio);
+
+	if (irq < 0)
+		return -EINVAL;
+
+	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
+
+	return 0;
+}
+
 static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
 	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
@@ -434,6 +447,18 @@ void __init ep93xx_gpio_init(void)
 				 EP93XX_SYSCON_DEVCFG_GONIDE |
 				 EP93XX_SYSCON_DEVCFG_HONIDE);
 
-	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
-		gpiochip_add(&ep93xx_gpio_banks[i].chip);
+	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
+		struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip;
+
+		/*
+		 * Ports A, B, and F support input debouncing when
+		 * used as interrupts.
+		 */
+		if (!strcmp(chip->label, "A") ||
+		    !strcmp(chip->label, "B") ||
+		    !strcmp(chip->label, "F"))
+			chip->set_debounce = ep93xx_gpio_set_debounce;
+
+		gpiochip_add(chip);
+	}
 }
diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h
index c991b14..c57152c 100644
--- a/arch/arm/mach-ep93xx/include/mach/gpio.h
+++ b/arch/arm/mach-ep93xx/include/mach/gpio.h
@@ -99,8 +99,6 @@
 /* maximum value for irq capable line identifiers */
 #define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
 
-extern void ep93xx_gpio_int_debounce(unsigned int irq, int enable);
-
 /* new generic GPIO API - see Documentation/gpio.txt */
 
 #include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h
index 554064e..c9400cf 100644
--- a/arch/arm/mach-ep93xx/include/mach/memory.h
+++ b/arch/arm/mach-ep93xx/include/mach/memory.h
@@ -6,15 +6,15 @@
 #define __ASM_ARCH_MEMORY_H
 
 #if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 #elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xc0000000)
+#define PLAT_PHYS_OFFSET		UL(0xc0000000)
 #elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xd0000000)
+#define PLAT_PHYS_OFFSET		UL(0xd0000000)
 #elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xe0000000)
+#define PLAT_PHYS_OFFSET		UL(0xe0000000)
 #elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xf0000000)
+#define PLAT_PHYS_OFFSET		UL(0xf0000000)
 #else
 #error "Kconfig bug: No EP93xx PHYS_OFFSET set"
 #endif
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
new file mode 100644
index 0000000..a021b52
--- /dev/null
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -0,0 +1,195 @@
+# arch/arm/mach-exynos4/Kconfig
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the EXYNOS4
+
+if ARCH_EXYNOS4
+
+config CPU_EXYNOS4210
+	bool
+	select S3C_PL330_DMA
+	help
+	  Enable EXYNOS4210 CPU support
+
+config EXYNOS4_MCT
+	bool "Kernel timer support by MCT"
+	help
+	  Use MCT (Multi Core Timer) as kernel timers
+
+config EXYNOS4_DEV_PD
+	bool
+	help
+	  Compile in platform device definitions for Power Domain
+
+config EXYNOS4_DEV_SYSMMU
+	bool
+	help
+	  Common setup code for SYSTEM MMU in EXYNOS4
+
+config EXYNOS4_SETUP_I2C1
+	bool
+	help
+	  Common setup code for i2c bus 1.
+
+config EXYNOS4_SETUP_I2C2
+	bool
+	help
+	  Common setup code for i2c bus 2.
+
+config EXYNOS4_SETUP_I2C3
+	bool
+	help
+	  Common setup code for i2c bus 3.
+
+config EXYNOS4_SETUP_I2C4
+	bool
+	help
+	  Common setup code for i2c bus 4.
+
+config EXYNOS4_SETUP_I2C5
+	bool
+	help
+	  Common setup code for i2c bus 5.
+
+config EXYNOS4_SETUP_I2C6
+	bool
+	help
+	  Common setup code for i2c bus 6.
+
+config EXYNOS4_SETUP_I2C7
+	bool
+	help
+	  Common setup code for i2c bus 7.
+
+config EXYNOS4_SETUP_KEYPAD
+	bool
+	help
+	  Common setup code for keypad.
+
+config EXYNOS4_SETUP_SDHCI
+	bool
+	select EXYNOS4_SETUP_SDHCI_GPIO
+	help
+	  Internal helper functions for EXYNOS4 based SDHCI systems.
+
+config EXYNOS4_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Common setup code for SDHCI gpio.
+
+config EXYNOS4_SETUP_FIMC
+	bool
+	help
+	  Common setup code for the camera interfaces.
+
+# machine support
+
+menu "EXYNOS4 Machines"
+
+config MACH_SMDKC210
+	bool "SMDKC210"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_I2C1
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDKC210
+
+config MACH_SMDKV310
+	bool "SMDKV310"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_I2C1
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select SAMSUNG_DEV_KEYPAD
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDKV310
+
+config MACH_ARMLEX4210
+	bool "ARMLEX4210"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_SDHCI
+	select SATA_AHCI_PLATFORM
+	help
+	  Machine support for Samsung ARMLEX4210 based on EXYNOS4210
+
+config MACH_UNIVERSAL_C210
+	bool "Mobile UNIVERSAL_C210 Board"
+	select CPU_EXYNOS4210
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C5
+	select S5P_DEV_ONENAND
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung Mobile Universal S5PC210 Reference
+	  Board.
+
+config MACH_NURI
+	bool "Mobile NURI Board"
+	select CPU_EXYNOS4210
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C5
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	select SAMSUNG_DEV_PWM
+	help
+	  Machine support for Samsung Mobile NURI Board.
+
+endmenu
+
+comment "Configuration for HSMMC bus width"
+
+menu "Use 8-bit bus width"
+
+config EXYNOS4_SDHCI_CH0_8BIT
+	bool "Channel 0 with 8-bit bus"
+	help
+	  Support HSMMC Channel 0 8-bit bus.
+	  If selected, Channel 1 is disabled.
+
+config EXYNOS4_SDHCI_CH2_8BIT
+	bool "Channel 2 with 8-bit bus"
+	help
+	  Support HSMMC Channel 2 8-bit bus.
+	  If selected, Channel 3 is disabled.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
new file mode 100644
index 0000000..b8f0e7d
--- /dev/null
+++ b/arch/arm/mach-exynos4/Makefile
@@ -0,0 +1,56 @@
+# arch/arm/mach-exynos4/Makefile
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for EXYNOS4 system
+
+obj-$(CONFIG_CPU_EXYNOS4210)	+= cpu.o init.o clock.o irq-combiner.o
+obj-$(CONFIG_CPU_EXYNOS4210)	+= setup-i2c0.o gpiolib.o irq-eint.o dma.o
+obj-$(CONFIG_PM)		+= pm.o sleep.o
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
+
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+
+ifeq ($(CONFIG_EXYNOS4_MCT),y)
+obj-y				+= mct.o
+else
+obj-y				+= time.o
+obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
+endif
+
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkc210.o
+obj-$(CONFIG_MACH_SMDKV310)		+= mach-smdkv310.o
+obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
+obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
+obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
+
+# device support
+
+obj-y					+= dev-audio.o
+obj-$(CONFIG_EXYNOS4_DEV_PD)		+= dev-pd.o
+obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)	+= dev-sysmmu.o
+
+obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C1)	+= setup-i2c1.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C2)	+= setup-i2c2.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C3)	+= setup-i2c3.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C4)	+= setup-i2c4.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C5)	+= setup-i2c5.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C6)	+= setup-i2c6.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C7)	+= setup-i2c7.o
+obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD)	+= setup-keypad.o
+obj-$(CONFIG_EXYNOS4_SETUP_SDHCI)	+= setup-sdhci.o
+obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
+obj-$(CONFIG_SATA_AHCI_PLATFORM)	+= dev-ahci.o
diff --git a/arch/arm/mach-exynos4/Makefile.boot b/arch/arm/mach-exynos4/Makefile.boot
new file mode 100644
index 0000000..d65956f
--- /dev/null
+++ b/arch/arm/mach-exynos4/Makefile.boot
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x40008000
+params_phys-y	:= 0x40000100
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
new file mode 100644
index 0000000..871f9d5
--- /dev/null
+++ b/arch/arm/mach-exynos4/clock.c
@@ -0,0 +1,1216 @@
+/* linux/arch/arm/mach-exynos4/clock.c
+ *
+ * Copyright (c) 2010-2011 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 <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 <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+
+static struct clk clk_sclk_hdmi27m = {
+	.name		= "sclk_hdmi27m",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+static struct clk clk_sclk_hdmiphy = {
+	.name		= "sclk_hdmiphy",
+	.id		= -1,
+};
+
+static struct clk clk_sclk_usbphy0 = {
+	.name		= "sclk_usbphy0",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+static struct clk clk_sclk_usbphy1 = {
+	.name		= "sclk_usbphy1",
+	.id		= -1,
+};
+
+static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
+}
+
+static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
+}
+
+static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
+}
+
+static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
+}
+
+static int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
+}
+
+static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
+}
+
+static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
+static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
+}
+
+static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
+}
+
+static int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
+}
+
+static int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
+}
+
+static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
+}
+
+static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
+}
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_apll = {
+	.clk	= {
+		.name		= "sclk_apll",
+		.id		= -1,
+		.parent		= &clk_mout_apll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_mpll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
+};
+
+static struct clk *clkset_moutcore_list[] = {
+	[0] = &clk_mout_apll.clk,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_moutcore = {
+	.sources	= clkset_moutcore_list,
+	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
+};
+
+static struct clksrc_clk clk_moutcore = {
+	.clk	= {
+		.name		= "moutcore",
+		.id		= -1,
+	},
+	.sources	= &clkset_moutcore,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk clk_coreclk = {
+	.clk	= {
+		.name		= "core_clk",
+		.id		= -1,
+		.parent		= &clk_moutcore.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+};
+
+static struct clksrc_clk clk_aclk_corem0 = {
+	.clk	= {
+		.name		= "aclk_corem0",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cores = {
+	.clk	= {
+		.name		= "aclk_cores",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corem1 = {
+	.clk	= {
+		.name		= "aclk_corem1",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_periphclk = {
+	.clk	= {
+		.name		= "periphclk",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+/* Core list of CMU_CORE side */
+
+static struct clk *clkset_corebus_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_corebus = {
+	.sources	= clkset_corebus_list,
+	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
+};
+
+static struct clksrc_clk clk_mout_corebus = {
+	.clk	= {
+		.name		= "mout_corebus",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_corebus,
+	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_dmc = {
+	.clk	= {
+		.name		= "sclk_dmc",
+		.id		= -1,
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cored = {
+	.clk	= {
+		.name		= "aclk_cored",
+		.id		= -1,
+		.parent		= &clk_sclk_dmc.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corep = {
+	.clk	= {
+		.name		= "aclk_corep",
+		.id		= -1,
+		.parent		= &clk_aclk_cored.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_acp = {
+	.clk	= {
+		.name		= "aclk_acp",
+		.id		= -1,
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_acp = {
+	.clk	= {
+		.name		= "pclk_acp",
+		.id		= -1,
+		.parent		= &clk_aclk_acp.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+static struct clk *clkset_aclk_top_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_aclk = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_200 = {
+	.clk	= {
+		.name		= "aclk_200",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_100 = {
+	.clk	= {
+		.name		= "aclk_100",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk clk_aclk_160 = {
+	.clk	= {
+		.name		= "aclk_160",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_133 = {
+	.clk	= {
+		.name		= "aclk_133",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
+};
+
+static struct clk *clkset_vpllsrc_list[] = {
+	[0] = &clk_fin_vpll,
+	[1] = &clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources clkset_vpllsrc = {
+	.sources	= clkset_vpllsrc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk clk_vpllsrc = {
+	.clk	= {
+		.name		= "vpll_src",
+		.id		= -1,
+		.enable		= exynos4_clksrc_mask_top_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources	= &clkset_vpllsrc,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_vpll_list[] = {
+	[0] = &clk_vpllsrc.clk,
+	[1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources clkset_sclk_vpll = {
+	.sources	= clkset_sclk_vpll_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
+};
+
+static struct clksrc_clk clk_sclk_vpll = {
+	.clk	= {
+		.name		= "sclk_vpll",
+		.id		= -1,
+	},
+	.sources	= &clkset_sclk_vpll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1<<24),
+	}, {
+		.name		= "csis",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "csis",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "fimc",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "fimc",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "fimc",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "fimc",
+		.id		= 3,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "fimd",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "fimd",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "sataphy",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "hsmmc",
+		.id		= 3,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "hsmmc",
+		.id		= 4,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "sata",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "pdma",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "pdma",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "keypad",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 14),
+	}, {
+		.name		= "usbhost",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_fsys_ctrl ,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "otg",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "spi",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "iis",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "iis",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "iis",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "ac97",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
+		.name		= "fimg2d",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "i2c",
+		.id		= 0,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "i2c",
+		.id		= 1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "i2c",
+		.id		= 2,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "i2c",
+		.id		= 3,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "i2c",
+		.id		= 4,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "i2c",
+		.id		= 5,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "i2c",
+		.id		= 6,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "i2c",
+		.id		= 7,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "SYSMMU_MDMA",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "SYSMMU_FIMC0",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "SYSMMU_FIMC1",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "SYSMMU_FIMC2",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "SYSMMU_FIMC3",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "SYSMMU_JPEG",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "SYSMMU_FIMD0",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_FIMD1",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_PCIe",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "SYSMMU_G2D",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "SYSMMU_ROTATOR",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_TV",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_MFC_L",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "SYSMMU_MFC_R",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 2),
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "uart",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "uart",
+		.id		= 4,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "uart",
+		.id		= 5,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 5),
+	}
+};
+
+static struct clk *clkset_group_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_xusbxti,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_group = {
+	.sources	= clkset_group_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group_list),
+};
+
+static struct clk *clkset_mout_g2d0_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d0 = {
+	.sources	= clkset_mout_g2d0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d0_list),
+};
+
+static struct clksrc_clk clk_mout_g2d0 = {
+	.clk	= {
+		.name		= "mout_g2d0",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_g2d0,
+	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d1 = {
+	.sources	= clkset_mout_g2d1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d1_list),
+};
+
+static struct clksrc_clk clk_mout_g2d1 = {
+	.clk	= {
+		.name		= "mout_g2d1",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_g2d1,
+	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d_list[] = {
+	[0] = &clk_mout_g2d0.clk,
+	[1] = &clk_mout_g2d1.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d = {
+	.sources	= clkset_mout_g2d_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
+};
+
+static struct clksrc_clk clk_dout_mmc0 = {
+	.clk		= {
+		.name		= "dout_mmc0",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc1 = {
+	.clk		= {
+		.name		= "dout_mmc1",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc2 = {
+	.clk		= {
+		.name		= "dout_mmc2",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc3 = {
+	.clk		= {
+		.name		= "dout_mmc3",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc4 = {
+	.clk		= {
+		.name		= "dout_mmc4",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "uclk1",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 2,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 3,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_pwm",
+			.id		= -1,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 28),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 2,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 3,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_sata",
+			.id		= -1,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_mout_corebus,
+		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 2,
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimg2d",
+			.id		= -1,
+		},
+		.sources = &clkset_mout_g2d,
+		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 0,
+			.parent		= &clk_dout_mmc0.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 1,
+			.parent         = &clk_dout_mmc1.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 2,
+			.parent         = &clk_dout_mmc2.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 3,
+			.parent         = &clk_dout_mmc3.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 4,
+			.parent         = &clk_dout_mmc4.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
+	}
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_apll,
+	&clk_sclk_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+	&clk_moutcore,
+	&clk_coreclk,
+	&clk_armclk,
+	&clk_aclk_corem0,
+	&clk_aclk_cores,
+	&clk_aclk_corem1,
+	&clk_periphclk,
+	&clk_mout_corebus,
+	&clk_sclk_dmc,
+	&clk_aclk_cored,
+	&clk_aclk_corep,
+	&clk_aclk_acp,
+	&clk_pclk_acp,
+	&clk_vpllsrc,
+	&clk_sclk_vpll,
+	&clk_aclk_200,
+	&clk_aclk_100,
+	&clk_aclk_160,
+	&clk_aclk_133,
+	&clk_dout_mmc0,
+	&clk_dout_mmc1,
+	&clk_dout_mmc2,
+	&clk_dout_mmc3,
+	&clk_dout_mmc4,
+};
+
+static int xtal_rate;
+
+static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
+{
+	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
+}
+
+static struct clk_ops exynos4_fout_apll_ops = {
+	.get_rate = exynos4_fout_apll_get_rate,
+};
+
+void __init_or_cpufreq exynos4_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned long vpll;
+	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);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
+	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+				__raw_readl(S5P_EPLL_CON1), pll_4600);
+
+	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+				__raw_readl(S5P_VPLL_CON1), pll_4650);
+
+	clk_fout_apll.ops = &exynos4_fout_apll_ops;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	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(&clk_armclk.clk);
+	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
+
+	aclk_200 = clk_get_rate(&clk_aclk_200.clk);
+	aclk_100 = clk_get_rate(&clk_aclk_100.clk);
+	aclk_160 = clk_get_rate(&clk_aclk_160.clk);
+	aclk_133 = clk_get_rate(&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(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	/* Nothing here yet */
+};
+
+void __init exynos4_register_clocks(void)
+{
+	int ptr;
+
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+	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, ARRAY_SIZE(init_clocks));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	s3c_pwmclk_init();
+}
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
new file mode 100644
index 0000000..7930113
--- /dev/null
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -0,0 +1,215 @@
+/* linux/arch/arm/mach-exynos4/cpu.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/sched.h>
+#include <linux/sysdev.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/exynos4.h>
+#include <plat/sdhci.h>
+#include <plat/devs.h>
+#include <plat/fimc-core.h>
+
+#include <mach/regs-irq.h>
+
+extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
+			 unsigned int irq_start);
+extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
+
+/* Initial IO mappings */
+static struct map_desc exynos4_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
+		.length		= SZ_4K,
+		.type	 	= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_CMU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
+		.length		= SZ_128K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_PMU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_PMU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_COMBINER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_COREPERI),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_L2CC,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_L2CC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO1,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO1),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO2,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO2),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO3,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO3),
+		.length		= SZ_256,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_DMC0,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_DMC0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_512K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_SROMC,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SROMC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void exynos4_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+/*
+ * exynos4_map_io
+ *
+ * register the standard cpu IO areas
+ */
+void __init exynos4_map_io(void)
+{
+	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
+
+	/* initialize device information early */
+	exynos4_default_sdhci0();
+	exynos4_default_sdhci1();
+	exynos4_default_sdhci2();
+	exynos4_default_sdhci3();
+
+	s3c_fimc_setname(0, "exynos4-fimc");
+	s3c_fimc_setname(1, "exynos4-fimc");
+	s3c_fimc_setname(2, "exynos4-fimc");
+	s3c_fimc_setname(3, "exynos4-fimc");
+}
+
+void __init exynos4_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	exynos4_register_clocks();
+	exynos4_setup_clocks();
+}
+
+void __init exynos4_init_irq(void)
+{
+	int irq;
+
+	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+
+	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+
+		/*
+		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
+		 * connected to the interrupt combiner. These irqs
+		 * should be initialized to support cascade interrupt.
+		 */
+		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
+			continue;
+
+		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
+				COMBINER_IRQ(irq, 0));
+		combiner_cascade_irq(irq, IRQ_SPI(irq));
+	}
+
+	/* The parameters of s5p_init_irq() are for VIC init.
+	 * Theses parameters should be NULL and 0 because EXYNOS4
+	 * uses GIC instead of VIC.
+	 */
+	s5p_init_irq(NULL, 0);
+}
+
+struct sysdev_class exynos4_sysclass = {
+	.name	= "exynos4-core",
+};
+
+static struct sys_device exynos4_sysdev = {
+	.cls	= &exynos4_sysclass,
+};
+
+static int __init exynos4_core_init(void)
+{
+	return sysdev_class_register(&exynos4_sysclass);
+}
+
+core_initcall(exynos4_core_init);
+
+#ifdef CONFIG_CACHE_L2X0
+static int __init exynos4_l2x0_cache_init(void)
+{
+	/* TAG, Data Latency Control: 2cycle */
+	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
+	__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+
+	/* L2X0 Prefetch Control */
+	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
+
+	/* L2X0 Power Control */
+	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
+		     S5P_VA_L2CC + L2X0_POWER_CTRL);
+
+	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
+
+	return 0;
+}
+
+early_initcall(exynos4_l2x0_cache_init);
+#endif
+
+int __init exynos4_init(void)
+{
+	printk(KERN_INFO "EXYNOS4: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = exynos4_idle;
+
+	return sysdev_register(&exynos4_sysdev);
+}
diff --git a/arch/arm/mach-exynos4/cpufreq.c b/arch/arm/mach-exynos4/cpufreq.c
new file mode 100644
index 0000000..a1bd258
--- /dev/null
+++ b/arch/arm/mach-exynos4/cpufreq.c
@@ -0,0 +1,569 @@
+/* linux/arch/arm/mach-exynos4/cpufreq.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - CPU frequency scaling support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+
+#include <plat/clock.h>
+#include <plat/pm.h>
+
+static struct clk *cpu_clk;
+static struct clk *moutcore;
+static struct clk *mout_mpll;
+static struct clk *mout_apll;
+
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+
+static struct cpufreq_freqs freqs;
+static unsigned int memtype;
+
+enum exynos4_memory_type {
+	DDR2 = 4,
+	LPDDR2,
+	DDR3,
+};
+
+enum cpufreq_level_index {
+	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+};
+
+static struct cpufreq_frequency_table exynos4_freq_table[] = {
+	{L0, 1000*1000},
+	{L1, 800*1000},
+	{L2, 400*1000},
+	{L3, 100*1000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
+	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
+	 */
+
+	/* ARM L0: 1000MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L1: 800MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L2: 400MHz */
+	{ 0, 1, 3, 1, 3, 0, 1 },
+
+	/* ARM L3: 100MHz */
+	{ 0, 0, 1, 0, 3, 1, 1 },
+};
+
+static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCOPY, DIVHPM }
+	 */
+
+	 /* ARM L0: 1000MHz */
+	{ 3, 0 },
+
+	/* ARM L1: 800MHz */
+	{ 3, 0 },
+
+	/* ARM L2: 400MHz */
+	{ 3, 0 },
+
+	/* ARM L3: 100MHz */
+	{ 3, 0 },
+};
+
+static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
+	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
+	 */
+
+	/* DMC L0: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L1: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L2: 266.7MHz */
+	{ 7, 1, 1, 2, 1, 1, 3, 1 },
+
+	/* DMC L3: 200MHz */
+	{ 7, 1, 1, 3, 1, 1, 3, 1 },
+};
+
+static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
+	 */
+
+	/* ACLK200 L0: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L1: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L2: 160MHz */
+	{ 4, 7, 5, 7, 1 },
+
+	/* ACLK200 L3: 133.3MHz */
+	{ 5, 7, 7, 7, 1 },
+};
+
+static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVGDL/R, DIVGPL/R }
+	 */
+
+	/* ACLK_GDL/R L0: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L1: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L2: 160MHz */
+	{ 4, 1 },
+
+	/* ACLK_GDL/R L3: 133.3MHz */
+	{ 5, 1 },
+};
+
+struct cpufreq_voltage_table {
+	unsigned int	index;		/* any */
+	unsigned int	arm_volt;	/* uV */
+	unsigned int	int_volt;
+};
+
+static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
+	{
+		.index		= L0,
+		.arm_volt	= 1200000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L1,
+		.arm_volt	= 1100000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L2,
+		.arm_volt	= 1000000,
+		.int_volt	= 1000000,
+	}, {
+		.index		= L3,
+		.arm_volt	= 900000,
+		.int_volt	= 1000000,
+	},
+};
+
+static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
+	/* APLL FOUT L0: 1000MHz */
+	((250 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L1: 800MHz */
+	((200 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L2 : 400MHz */
+	((200 << 16) | (6 << 8) | 2),
+
+	/* APLL FOUT L3: 100MHz */
+	((200 << 16) | (6 << 8) | 4),
+};
+
+int exynos4_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
+}
+
+unsigned int exynos4_getspeed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+void exynos4_set_clkdiv(unsigned int div_index)
+{
+	unsigned int tmp;
+
+	/* Change Divider - CPU0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU);
+
+	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
+		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
+		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+		S5P_CLKDIV_CPU0_APLL_MASK);
+
+	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
+	} while (tmp & 0x1111111);
+
+	/* Change Divider - CPU1 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU1);
+
+	tmp &= ~((0x7 << 4) | 0x7);
+
+	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
+		(clkdiv_cpu1[div_index][1] << 0));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU1);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
+	} while (tmp & 0x11);
+
+	/* Change Divider - DMC0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_DMC0);
+
+	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
+		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
+		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
+		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
+
+	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
+		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
+		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
+		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
+		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
+		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
+		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
+		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_DMC0);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
+	} while (tmp & 0x11111111);
+
+	/* Change Divider - TOP */
+
+	tmp = __raw_readl(S5P_CLKDIV_TOP);
+
+	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
+		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
+		S5P_CLKDIV_TOP_ONENAND_MASK);
+
+	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
+		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
+		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
+		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
+		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_TOP);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
+	} while (tmp & 0x11111);
+
+	/* Change Divider - LEFTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
+	} while (tmp & 0x11);
+
+	/* Change Divider - RIGHTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
+	} while (tmp & 0x11);
+}
+
+static void exynos4_set_apll(unsigned int index)
+{
+	unsigned int tmp;
+
+	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+	clk_set_parent(moutcore, mout_mpll);
+
+	do {
+		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
+			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
+		tmp &= 0x7;
+	} while (tmp != 0x2);
+
+	/* 2. Set APLL Lock time */
+	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
+
+	/* 3. Change PLL PMS values */
+	tmp = __raw_readl(S5P_APLL_CON0);
+	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
+	tmp |= exynos4_apll_pms_table[index];
+	__raw_writel(tmp, S5P_APLL_CON0);
+
+	/* 4. wait_lock_time */
+	do {
+		tmp = __raw_readl(S5P_APLL_CON0);
+	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
+
+	/* 5. MUX_CORE_SEL = APLL */
+	clk_set_parent(moutcore, mout_apll);
+
+	do {
+		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+}
+
+static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index)
+{
+	unsigned int tmp;
+
+	if (old_index > new_index) {
+		/* The frequency changing to L0 needs to change apll */
+		if (freqs.new == exynos4_freq_table[L0].frequency) {
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+
+			/* 2. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+		} else {
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+
+			/* 2. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+		}
+	}
+
+	else if (old_index < new_index) {
+		/* The frequency changing from L0 needs to change apll */
+		if (freqs.old == exynos4_freq_table[L0].frequency) {
+			/* 1. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+		} else {
+			/* 1. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+		}
+	}
+}
+
+static int exynos4_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq,
+			  unsigned int relation)
+{
+	unsigned int index, old_index;
+	unsigned int arm_volt, int_volt;
+
+	freqs.old = exynos4_getspeed(policy->cpu);
+
+	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
+					   freqs.old, relation, &old_index))
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
+					   target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.new = exynos4_freq_table[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.new == freqs.old)
+		return 0;
+
+	/* get the voltage value */
+	arm_volt = exynos4_volt_table[index].arm_volt;
+	int_volt = exynos4_volt_table[index].int_volt;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* control regulator */
+	if (freqs.new > freqs.old) {
+		/* Voltage up */
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+	}
+
+	/* Clock Configuration Procedure */
+	exynos4_set_frequency(old_index, index);
+
+	/* control regulator */
+	if (freqs.new < freqs.old) {
+		/* Voltage down */
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+
+static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+#endif
+
+static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
+
+	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
+
+	/* set the transition latency value */
+	policy->cpuinfo.transition_latency = 100000;
+
+	/*
+	 * EXYNOS4 multi-core processors has 2 cores
+	 * that the frequency cannot be set independently.
+	 * Each cpu is bound to the same speed.
+	 * So the affected cpu is all of the cpus.
+	 */
+	cpumask_setall(policy->cpus);
+
+	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+}
+
+static struct cpufreq_driver exynos4_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= exynos4_verify_speed,
+	.target		= exynos4_target,
+	.get		= exynos4_getspeed,
+	.init		= exynos4_cpufreq_cpu_init,
+	.name		= "exynos4_cpufreq",
+#ifdef CONFIG_PM
+	.suspend	= exynos4_cpufreq_suspend,
+	.resume		= exynos4_cpufreq_resume,
+#endif
+};
+
+static int __init exynos4_cpufreq_init(void)
+{
+	cpu_clk = clk_get(NULL, "armclk");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	moutcore = clk_get(NULL, "moutcore");
+	if (IS_ERR(moutcore))
+		goto out;
+
+	mout_mpll = clk_get(NULL, "mout_mpll");
+	if (IS_ERR(mout_mpll))
+		goto out;
+
+	mout_apll = clk_get(NULL, "mout_apll");
+	if (IS_ERR(mout_apll))
+		goto out;
+
+	arm_regulator = regulator_get(NULL, "vdd_arm");
+	if (IS_ERR(arm_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
+		goto out;
+	}
+
+	int_regulator = regulator_get(NULL, "vdd_int");
+	if (IS_ERR(int_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
+		goto out;
+	}
+
+	/*
+	 * Check DRAM type.
+	 * Because DVFS level is different according to DRAM type.
+	 */
+	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
+	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
+	memtype &= S5P_DMC0_MEMTYPE_MASK;
+
+	if ((memtype < DDR2) && (memtype > DDR3)) {
+		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
+		goto out;
+	} else {
+		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
+	}
+
+	return cpufreq_register_driver(&exynos4_driver);
+
+out:
+	if (!IS_ERR(cpu_clk))
+		clk_put(cpu_clk);
+
+	if (!IS_ERR(moutcore))
+		clk_put(moutcore);
+
+	if (!IS_ERR(mout_mpll))
+		clk_put(mout_mpll);
+
+	if (!IS_ERR(mout_apll))
+		clk_put(mout_apll);
+
+	if (!IS_ERR(arm_regulator))
+		regulator_put(arm_regulator);
+
+	if (!IS_ERR(int_regulator))
+		regulator_put(int_regulator);
+
+	printk(KERN_ERR "%s: failed initialization\n", __func__);
+
+	return -EINVAL;
+}
+late_initcall(exynos4_cpufreq_init);
diff --git a/arch/arm/mach-exynos4/dev-ahci.c b/arch/arm/mach-exynos4/dev-ahci.c
new file mode 100644
index 0000000..f57a3de
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-ahci.c
@@ -0,0 +1,263 @@
+/* linux/arch/arm/mach-exynos4/dev-ahci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - AHCI 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/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/ahci_platform.h>
+
+#include <plat/cpu.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <mach/regs-pmu.h>
+
+/* PHY Control Register */
+#define SATA_CTRL0		0x0
+/* PHY Link Control Register */
+#define SATA_CTRL1		0x4
+/* PHY Status Register */
+#define SATA_PHY_STATUS		0x8
+
+#define SATA_CTRL0_RX_DATA_VALID(x)	(x << 27)
+#define SATA_CTRL0_SPEED_MODE		(1 << 26)
+#define SATA_CTRL0_M_PHY_CAL		(1 << 19)
+#define SATA_CTRL0_PHY_CMU_RST_N	(1 << 10)
+#define SATA_CTRL0_M_PHY_LN_RST_N	(1 << 9)
+#define SATA_CTRL0_PHY_POR_N		(1 << 8)
+
+#define SATA_CTRL1_RST_PMALIVE_N	(1 << 8)
+#define SATA_CTRL1_RST_RXOOB_N		(1 << 7)
+#define SATA_CTRL1_RST_RX_N		(1 << 6)
+#define SATA_CTRL1_RST_TX_N		(1 << 5)
+
+#define SATA_PHY_STATUS_CMU_OK		(1 << 18)
+#define SATA_PHY_STATUS_LANE_OK		(1 << 16)
+
+#define LANE0		0x200
+#define COM_LANE	0xA00
+
+#define HOST_PORTS_IMPL	0xC
+#define SCLK_SATA_FREQ	(67 * MHZ)
+
+static void __iomem *phy_base, *phy_ctrl;
+
+struct phy_reg {
+	u8	reg;
+	u8	val;
+};
+
+/* SATA PHY setup */
+static const struct phy_reg exynos4_sataphy_cmu[] = {
+	{ 0x00, 0x06 }, { 0x02, 0x80 }, { 0x22, 0xa0 }, { 0x23, 0x42 },
+	{ 0x2e, 0x04 }, { 0x2f, 0x50 }, { 0x30, 0x70 }, { 0x31, 0x02 },
+	{ 0x32, 0x25 }, { 0x33, 0x40 }, { 0x34, 0x01 }, { 0x35, 0x40 },
+	{ 0x61, 0x2e }, { 0x63, 0x5e }, { 0x65, 0x42 }, { 0x66, 0xd1 },
+	{ 0x67, 0x20 }, { 0x68, 0x28 }, { 0x69, 0x78 }, { 0x6a, 0x04 },
+	{ 0x6b, 0xc8 }, { 0x6c, 0x06 },
+};
+
+static const struct phy_reg exynos4_sataphy_lane[] = {
+	{ 0x00, 0x02 }, { 0x05, 0x10 }, { 0x06, 0x84 }, { 0x07, 0x04 },
+	{ 0x08, 0xe0 }, { 0x10, 0x23 }, { 0x13, 0x05 }, { 0x14, 0x30 },
+	{ 0x15, 0x00 }, { 0x17, 0x70 }, { 0x18, 0xf2 }, { 0x19, 0x1e },
+	{ 0x1a, 0x18 }, { 0x1b, 0x0d }, { 0x1c, 0x08 }, { 0x50, 0x60 },
+	{ 0x51, 0x0f },
+};
+
+static const struct phy_reg exynos4_sataphy_comlane[] = {
+	{ 0x01, 0x20 }, { 0x03, 0x40 }, { 0x04, 0x3c }, { 0x05, 0x7d },
+	{ 0x06, 0x1d }, { 0x07, 0xcf }, { 0x08, 0x05 }, { 0x09, 0x63 },
+	{ 0x0a, 0x29 }, { 0x0b, 0xc4 }, { 0x0c, 0x01 }, { 0x0d, 0x03 },
+	{ 0x0e, 0x28 }, { 0x0f, 0x98 }, { 0x10, 0x19 }, { 0x13, 0x80 },
+	{ 0x14, 0xf0 }, { 0x15, 0xd0 }, { 0x39, 0xa0 }, { 0x3a, 0xa0 },
+	{ 0x3b, 0xa0 }, { 0x3c, 0xa0 }, { 0x3d, 0xa0 }, { 0x3e, 0xa0 },
+	{ 0x3f, 0xa0 }, { 0x40, 0x42 }, { 0x42, 0x80 }, { 0x43, 0x58 },
+	{ 0x45, 0x44 }, { 0x46, 0x5c }, { 0x47, 0x86 }, { 0x48, 0x8d },
+	{ 0x49, 0xd0 }, { 0x4a, 0x09 }, { 0x4b, 0x90 }, { 0x4c, 0x07 },
+	{ 0x4d, 0x40 }, { 0x51, 0x20 }, { 0x52, 0x32 }, { 0x7f, 0xd8 },
+	{ 0x80, 0x1a }, { 0x81, 0xff }, { 0x82, 0x11 }, { 0x83, 0x00 },
+	{ 0x87, 0xf0 }, { 0x87, 0xff }, { 0x87, 0xff }, { 0x87, 0xff },
+	{ 0x87, 0xff }, { 0x8c, 0x1c }, { 0x8d, 0xc2 }, { 0x8e, 0xc3 },
+	{ 0x8f, 0x3f }, { 0x90, 0x0a }, { 0x96, 0xf8 },
+};
+
+static int wait_for_phy_ready(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	/* wait for maximum of 3 sec */
+	timeout = jiffies + msecs_to_jiffies(3000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static int ahci_phy_init(void __iomem *mmio)
+{
+	int i, ctrl0;
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_cmu); i++)
+		__raw_writeb(exynos4_sataphy_cmu[i].val,
+		phy_base + (exynos4_sataphy_cmu[i].reg * 4));
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_lane); i++)
+		__raw_writeb(exynos4_sataphy_lane[i].val,
+		phy_base + (LANE0 + exynos4_sataphy_lane[i].reg) * 4);
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_comlane); i++)
+		__raw_writeb(exynos4_sataphy_comlane[i].val,
+		phy_base + (COM_LANE + exynos4_sataphy_comlane[i].reg) * 4);
+
+	__raw_writeb(0x07, phy_base);
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_PHY_CMU_RST_N;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
+				SATA_PHY_STATUS_CMU_OK) < 0) {
+		printk(KERN_ERR "PHY CMU not ready\n");
+		return -EBUSY;
+	}
+
+	__raw_writeb(0x03, phy_base + (COM_LANE * 4));
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_M_PHY_LN_RST_N;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
+				SATA_PHY_STATUS_LANE_OK) < 0) {
+		printk(KERN_ERR "PHY LANE not ready\n");
+		return -EBUSY;
+	}
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_M_PHY_CAL;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	return 0;
+}
+
+static int exynos4_ahci_init(struct device *dev, void __iomem *mmio)
+{
+	struct clk *clk_sata, *clk_sataphy, *clk_sclk_sata;
+	int val, ret;
+
+	phy_base = ioremap(EXYNOS4_PA_SATAPHY, SZ_64K);
+	if (!phy_base) {
+		dev_err(dev, "failed to allocate memory for SATA PHY\n");
+		return -ENOMEM;
+	}
+
+	phy_ctrl = ioremap(EXYNOS4_PA_SATAPHY_CTRL, SZ_16);
+	if (!phy_ctrl) {
+		dev_err(dev, "failed to allocate memory for SATA PHY CTRL\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	clk_sata = clk_get(dev, "sata");
+	if (IS_ERR(clk_sata)) {
+		dev_err(dev, "failed to get sata clock\n");
+		ret = PTR_ERR(clk_sata);
+		clk_sata = NULL;
+		goto err2;
+
+	}
+	clk_enable(clk_sata);
+
+	clk_sataphy = clk_get(dev, "sataphy");
+	if (IS_ERR(clk_sataphy)) {
+		dev_err(dev, "failed to get sataphy clock\n");
+		ret = PTR_ERR(clk_sataphy);
+		clk_sataphy = NULL;
+		goto err3;
+	}
+	clk_enable(clk_sataphy);
+
+	clk_sclk_sata = clk_get(dev, "sclk_sata");
+	if (IS_ERR(clk_sclk_sata)) {
+		dev_err(dev, "failed to get sclk_sata\n");
+		ret = PTR_ERR(clk_sclk_sata);
+		clk_sclk_sata = NULL;
+		goto err4;
+	}
+	clk_enable(clk_sclk_sata);
+	clk_set_rate(clk_sclk_sata, SCLK_SATA_FREQ);
+
+	__raw_writel(S5P_PMU_SATA_PHY_CONTROL_EN, S5P_PMU_SATA_PHY_CONTROL);
+
+	/* Enable PHY link control */
+	val = SATA_CTRL1_RST_PMALIVE_N | SATA_CTRL1_RST_RXOOB_N |
+			SATA_CTRL1_RST_RX_N | SATA_CTRL1_RST_TX_N;
+	__raw_writel(val, phy_ctrl + SATA_CTRL1);
+
+	/* Set communication speed as 3Gbps and enable PHY power */
+	val = SATA_CTRL0_RX_DATA_VALID(3) | SATA_CTRL0_SPEED_MODE |
+			SATA_CTRL0_PHY_POR_N;
+	__raw_writel(val, phy_ctrl + SATA_CTRL0);
+
+	/* Port0 is available */
+	__raw_writel(0x1, mmio + HOST_PORTS_IMPL);
+
+	return ahci_phy_init(mmio);
+
+err4:
+	clk_disable(clk_sataphy);
+	clk_put(clk_sataphy);
+err3:
+	clk_disable(clk_sata);
+	clk_put(clk_sata);
+err2:
+	iounmap(phy_ctrl);
+err1:
+	iounmap(phy_base);
+
+	return ret;
+}
+
+static struct ahci_platform_data exynos4_ahci_pdata = {
+	.init = exynos4_ahci_init,
+};
+
+static struct resource exynos4_ahci_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SATA,
+		.end	= EXYNOS4_PA_SATA + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SATA,
+		.end	= IRQ_SATA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ahci = {
+	.name		= "ahci",
+	.id		= -1,
+	.resource	= exynos4_ahci_resource,
+	.num_resources	= ARRAY_SIZE(exynos4_ahci_resource),
+	.dev		= {
+		.platform_data		= &exynos4_ahci_pdata,
+		.dma_mask		= &exynos4_ahci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff --git a/arch/arm/mach-exynos4/dev-audio.c b/arch/arm/mach-exynos4/dev-audio.c
new file mode 100644
index 0000000..1eed5f9
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-audio.c
@@ -0,0 +1,367 @@
+/* linux/arch/arm/mach-exynos4/dev-audio.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+static const char *rclksrc[] = {
+	[0] = "busclk",
+	[1] = "i2sclk",
+};
+
+static int exynos4_cfg_i2s(struct platform_device *pdev)
+{
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 7, S3C_GPIO_SFN(2));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(2));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(4));
+		break;
+	default:
+		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata i2sv5_pdata = {
+	.cfg_gpio = exynos4_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
+					 | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc,
+		},
+	},
+};
+
+static struct resource exynos4_i2s0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S0,
+		.end	= EXYNOS4_PA_I2S0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S0_TX,
+		.end	= DMACH_I2S0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S0_RX,
+		.end	= DMACH_I2S0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DMACH_I2S0S_TX,
+		.end	= DMACH_I2S0S_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s0 = {
+	.name = "samsung-i2s",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(exynos4_i2s0_resource),
+	.resource = exynos4_i2s0_resource,
+	.dev = {
+		.platform_data = &i2sv5_pdata,
+	},
+};
+
+static const char *rclksrc_v3[] = {
+	[0] = "sclk_i2s",
+	[1] = "no_such_clock",
+};
+
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = exynos4_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_NO_MUXPSR,
+			.src_clk = rclksrc_v3,
+		},
+	},
+};
+
+static struct resource exynos4_i2s1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S1,
+		.end	= EXYNOS4_PA_I2S1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S1_TX,
+		.end	= DMACH_I2S1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S1_RX,
+		.end	= DMACH_I2S1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s1 = {
+	.name = "samsung-i2s",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(exynos4_i2s1_resource),
+	.resource = exynos4_i2s1_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+static struct resource exynos4_i2s2_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S2,
+		.end	= EXYNOS4_PA_I2S2 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S2_TX,
+		.end	= DMACH_I2S2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S2_RX,
+		.end	= DMACH_I2S2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s2 = {
+	.name = "samsung-i2s",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(exynos4_i2s2_resource),
+	.resource = exynos4_i2s2_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+/* PCM Controller platform_devices */
+
+static int exynos4_pcm_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(3));
+		break;
+	default:
+		printk(KERN_DEBUG "Invalid PCM Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata s3c_pcm_pdata = {
+	.cfg_gpio = exynos4_pcm_cfg_gpio,
+};
+
+static struct resource exynos4_pcm0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM0,
+		.end	= EXYNOS4_PA_PCM0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM0_TX,
+		.end	= DMACH_PCM0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM0_RX,
+		.end	= DMACH_PCM0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm0 = {
+	.name = "samsung-pcm",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(exynos4_pcm0_resource),
+	.resource = exynos4_pcm0_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource exynos4_pcm1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM1,
+		.end	= EXYNOS4_PA_PCM1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM1_TX,
+		.end	= DMACH_PCM1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM1_RX,
+		.end	= DMACH_PCM1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm1 = {
+	.name = "samsung-pcm",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(exynos4_pcm1_resource),
+	.resource = exynos4_pcm1_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource exynos4_pcm2_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM2,
+		.end	= EXYNOS4_PA_PCM2 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM2_TX,
+		.end	= DMACH_PCM2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM2_RX,
+		.end	= DMACH_PCM2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm2 = {
+	.name = "samsung-pcm",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(exynos4_pcm2_resource),
+	.resource = exynos4_pcm2_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+/* AC97 Controller platform devices */
+
+static int exynos4_ac97_cfg_gpio(struct platform_device *pdev)
+{
+	return s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(4));
+}
+
+static struct resource exynos4_ac97_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_AC97,
+		.end	= EXYNOS4_PA_AC97 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_AC97_PCMOUT,
+		.end	= DMACH_AC97_PCMOUT,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_AC97_PCMIN,
+		.end	= DMACH_AC97_PCMIN,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DMACH_AC97_MICIN,
+		.end	= DMACH_AC97_MICIN,
+		.flags	= IORESOURCE_DMA,
+	},
+	[4] = {
+		.start	= IRQ_AC97,
+		.end	= IRQ_AC97,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_audio_pdata s3c_ac97_pdata = {
+	.cfg_gpio = exynos4_ac97_cfg_gpio,
+};
+
+static u64 exynos4_ac97_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ac97 = {
+	.name = "samsung-ac97",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(exynos4_ac97_resource),
+	.resource = exynos4_ac97_resource,
+	.dev = {
+		.platform_data = &s3c_ac97_pdata,
+		.dma_mask = &exynos4_ac97_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+/* S/PDIF Controller platform_device */
+
+static int exynos4_spdif_cfg_gpio(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 2, S3C_GPIO_SFN(3));
+
+	return 0;
+}
+
+static struct resource exynos4_spdif_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SPDIF,
+		.end	= EXYNOS4_PA_SPDIF + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_SPDIF,
+		.end	= DMACH_SPDIF,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata samsung_spdif_pdata = {
+	.cfg_gpio = exynos4_spdif_cfg_gpio,
+};
+
+static u64 exynos4_spdif_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_spdif = {
+	.name = "samsung-spdif",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(exynos4_spdif_resource),
+	.resource = exynos4_spdif_resource,
+	.dev = {
+		.platform_data = &samsung_spdif_pdata,
+		.dma_mask = &exynos4_spdif_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
diff --git a/arch/arm/mach-exynos4/dev-pd.c b/arch/arm/mach-exynos4/dev-pd.c
new file mode 100644
index 0000000..3273f25
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-pd.c
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-exynos4/dev-pd.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Power Domain support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/regs-pmu.h>
+
+#include <plat/pd.h>
+
+static int exynos4_pd_enable(struct device *dev)
+{
+	struct samsung_pd_info *pdata =  dev->platform_data;
+	u32 timeout;
+
+	__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
+
+	/* Wait max 1ms */
+	timeout = 10;
+	while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
+		!= S5P_INT_LOCAL_PWR_EN) {
+		if (timeout == 0) {
+			printk(KERN_ERR "Power domain %s enable failed.\n",
+				dev_name(dev));
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		udelay(100);
+	}
+
+	return 0;
+}
+
+static int exynos4_pd_disable(struct device *dev)
+{
+	struct samsung_pd_info *pdata =  dev->platform_data;
+	u32 timeout;
+
+	__raw_writel(0, pdata->base);
+
+	/* Wait max 1ms */
+	timeout = 10;
+	while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
+		if (timeout == 0) {
+			printk(KERN_ERR "Power domain %s disable failed.\n",
+				dev_name(dev));
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		udelay(100);
+	}
+
+	return 0;
+}
+
+struct platform_device exynos4_device_pd[] = {
+	{
+		.name		= "samsung-pd",
+		.id		= 0,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_MFC_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 1,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_G3D_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 2,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_LCD0_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 3,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_LCD1_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 4,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_TV_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 5,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_CAM_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 6,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_GPS_CONF,
+			},
+		},
+	},
+};
diff --git a/arch/arm/mach-exynos4/dev-sysmmu.c b/arch/arm/mach-exynos4/dev-sysmmu.c
new file mode 100644
index 0000000..3b7cae0
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-sysmmu.c
@@ -0,0 +1,232 @@
+/* linux/arch/arm/mach-exynos4/dev-sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - System MMU 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/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/sysmmu.h>
+#include <plat/s5p-clock.h>
+
+/* These names must be equal to the clock names in mach-exynos4/clock.c */
+const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
+	"SYSMMU_MDMA"	,
+	"SYSMMU_SSS"	,
+	"SYSMMU_FIMC0"	,
+	"SYSMMU_FIMC1"	,
+	"SYSMMU_FIMC2"	,
+	"SYSMMU_FIMC3"	,
+	"SYSMMU_JPEG"	,
+	"SYSMMU_FIMD0"	,
+	"SYSMMU_FIMD1"	,
+	"SYSMMU_PCIe"	,
+	"SYSMMU_G2D"	,
+	"SYSMMU_ROTATOR",
+	"SYSMMU_MDMA2"	,
+	"SYSMMU_TV"	,
+	"SYSMMU_MFC_L"	,
+	"SYSMMU_MFC_R"	,
+};
+
+static struct resource exynos4_sysmmu_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SYSMMU_MDMA,
+		.end	= EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SYSMMU_MDMA0_0,
+		.end	= IRQ_SYSMMU_MDMA0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= EXYNOS4_PA_SYSMMU_SSS,
+		.end	= EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		.start	= IRQ_SYSMMU_SSS_0,
+		.end	= IRQ_SYSMMU_SSS_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[4] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC0,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[5] = {
+		.start	= IRQ_SYSMMU_FIMC0_0,
+		.end	= IRQ_SYSMMU_FIMC0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[6] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC1,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[7] = {
+		.start	= IRQ_SYSMMU_FIMC1_0,
+		.end	= IRQ_SYSMMU_FIMC1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[8] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC2,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[9] = {
+		.start	= IRQ_SYSMMU_FIMC2_0,
+		.end	= IRQ_SYSMMU_FIMC2_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[10] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC3,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[11] = {
+		.start	= IRQ_SYSMMU_FIMC3_0,
+		.end	= IRQ_SYSMMU_FIMC3_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[12] = {
+		.start	= EXYNOS4_PA_SYSMMU_JPEG,
+		.end	= EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[13] = {
+		.start	= IRQ_SYSMMU_JPEG_0,
+		.end	= IRQ_SYSMMU_JPEG_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[14] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMD0,
+		.end	= EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[15] = {
+		.start	= IRQ_SYSMMU_LCD0_M0_0,
+		.end	= IRQ_SYSMMU_LCD0_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[16] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMD1,
+		.end	= EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[17] = {
+		.start	= IRQ_SYSMMU_LCD1_M1_0,
+		.end	= IRQ_SYSMMU_LCD1_M1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[18] = {
+		.start	= EXYNOS4_PA_SYSMMU_PCIe,
+		.end	= EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[19] = {
+		.start	= IRQ_SYSMMU_PCIE_0,
+		.end	= IRQ_SYSMMU_PCIE_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[20] = {
+		.start	= EXYNOS4_PA_SYSMMU_G2D,
+		.end	= EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[21] = {
+		.start	= IRQ_SYSMMU_2D_0,
+		.end	= IRQ_SYSMMU_2D_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[22] = {
+		.start	= EXYNOS4_PA_SYSMMU_ROTATOR,
+		.end	= EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[23] = {
+		.start	= IRQ_SYSMMU_ROTATOR_0,
+		.end	= IRQ_SYSMMU_ROTATOR_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[24] = {
+		.start	= EXYNOS4_PA_SYSMMU_MDMA2,
+		.end	= EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[25] = {
+		.start	= IRQ_SYSMMU_MDMA1_0,
+		.end	= IRQ_SYSMMU_MDMA1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[26] = {
+		.start	= EXYNOS4_PA_SYSMMU_TV,
+		.end	= EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[27] = {
+		.start	= IRQ_SYSMMU_TV_M0_0,
+		.end	= IRQ_SYSMMU_TV_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[28] = {
+		.start	= EXYNOS4_PA_SYSMMU_MFC_L,
+		.end	= EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[29] = {
+		.start	= IRQ_SYSMMU_MFC_M0_0,
+		.end	= IRQ_SYSMMU_MFC_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[30] = {
+		.start	= EXYNOS4_PA_SYSMMU_MFC_R,
+		.end	= EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[31] = {
+		.start	= IRQ_SYSMMU_MFC_M1_0,
+		.end	= IRQ_SYSMMU_MFC_M1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device exynos4_device_sysmmu = {
+	.name		= "s5p-sysmmu",
+	.id		= 32,
+	.num_resources	= ARRAY_SIZE(exynos4_sysmmu_resource),
+	.resource	= exynos4_sysmmu_resource,
+};
+EXPORT_SYMBOL(exynos4_device_sysmmu);
+
+static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
+{
+	sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
+	if (IS_ERR(sysmmu_clk[ips]))
+		sysmmu_clk[ips] = NULL;
+	else
+		clk_put(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_enable(sysmmu_ips ips)
+{
+	if (sysmmu_clk[ips])
+		clk_enable(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_disable(sysmmu_ips ips)
+{
+	if (sysmmu_clk[ips])
+		clk_disable(sysmmu_clk[ips]);
+}
diff --git a/arch/arm/mach-exynos4/dma.c b/arch/arm/mach-exynos4/dma.c
new file mode 100644
index 0000000..564bb53
--- /dev/null
+++ b/arch/arm/mach-exynos4/dma.c
@@ -0,0 +1,172 @@
+/* linux/arch/arm/mach-exynos4/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <plat/devs.h>
+#include <plat/irqs.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <plat/s3c-pl330-pdata.h>
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+static struct resource exynos4_pdma0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PDMA0,
+		.end	= EXYNOS4_PA_PDMA0 + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PDMA0,
+		.end	= IRQ_PDMA0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
+	.peri = {
+		[0] = DMACH_PCM0_RX,
+		[1] = DMACH_PCM0_TX,
+		[2] = DMACH_PCM2_RX,
+		[3] = DMACH_PCM2_TX,
+		[4] = DMACH_MSM_REQ0,
+		[5] = DMACH_MSM_REQ2,
+		[6] = DMACH_SPI0_RX,
+		[7] = DMACH_SPI0_TX,
+		[8] = DMACH_SPI2_RX,
+		[9] = DMACH_SPI2_TX,
+		[10] = DMACH_I2S0S_TX,
+		[11] = DMACH_I2S0_RX,
+		[12] = DMACH_I2S0_TX,
+		[13] = DMACH_I2S2_RX,
+		[14] = DMACH_I2S2_TX,
+		[15] = DMACH_UART0_RX,
+		[16] = DMACH_UART0_TX,
+		[17] = DMACH_UART2_RX,
+		[18] = DMACH_UART2_TX,
+		[19] = DMACH_UART4_RX,
+		[20] = DMACH_UART4_TX,
+		[21] = DMACH_SLIMBUS0_RX,
+		[22] = DMACH_SLIMBUS0_TX,
+		[23] = DMACH_SLIMBUS2_RX,
+		[24] = DMACH_SLIMBUS2_TX,
+		[25] = DMACH_SLIMBUS4_RX,
+		[26] = DMACH_SLIMBUS4_TX,
+		[27] = DMACH_AC97_MICIN,
+		[28] = DMACH_AC97_PCMIN,
+		[29] = DMACH_AC97_PCMOUT,
+		[30] = DMACH_MAX,
+		[31] = DMACH_MAX,
+	},
+};
+
+static struct platform_device exynos4_device_pdma0 = {
+	.name		= "s3c-pl330",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(exynos4_pdma0_resource),
+	.resource	= exynos4_pdma0_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma0_pdata,
+	},
+};
+
+static struct resource exynos4_pdma1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PDMA1,
+		.end	= EXYNOS4_PA_PDMA1 + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PDMA1,
+		.end	= IRQ_PDMA1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
+	.peri = {
+		[0] = DMACH_PCM0_RX,
+		[1] = DMACH_PCM0_TX,
+		[2] = DMACH_PCM1_RX,
+		[3] = DMACH_PCM1_TX,
+		[4] = DMACH_MSM_REQ1,
+		[5] = DMACH_MSM_REQ3,
+		[6] = DMACH_SPI1_RX,
+		[7] = DMACH_SPI1_TX,
+		[8] = DMACH_I2S0S_TX,
+		[9] = DMACH_I2S0_RX,
+		[10] = DMACH_I2S0_TX,
+		[11] = DMACH_I2S1_RX,
+		[12] = DMACH_I2S1_TX,
+		[13] = DMACH_UART0_RX,
+		[14] = DMACH_UART0_TX,
+		[15] = DMACH_UART1_RX,
+		[16] = DMACH_UART1_TX,
+		[17] = DMACH_UART3_RX,
+		[18] = DMACH_UART3_TX,
+		[19] = DMACH_SLIMBUS1_RX,
+		[20] = DMACH_SLIMBUS1_TX,
+		[21] = DMACH_SLIMBUS3_RX,
+		[22] = DMACH_SLIMBUS3_TX,
+		[23] = DMACH_SLIMBUS5_RX,
+		[24] = DMACH_SLIMBUS5_TX,
+		[25] = DMACH_SLIMBUS0AUX_RX,
+		[26] = DMACH_SLIMBUS0AUX_TX,
+		[27] = DMACH_SPDIF,
+		[28] = DMACH_MAX,
+		[29] = DMACH_MAX,
+		[30] = DMACH_MAX,
+		[31] = DMACH_MAX,
+	},
+};
+
+static struct platform_device exynos4_device_pdma1 = {
+	.name		= "s3c-pl330",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(exynos4_pdma1_resource),
+	.resource	= exynos4_pdma1_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma1_pdata,
+	},
+};
+
+static struct platform_device *exynos4_dmacs[] __initdata = {
+	&exynos4_device_pdma0,
+	&exynos4_device_pdma1,
+};
+
+static int __init exynos4_dma_init(void)
+{
+	platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
+
+	return 0;
+}
+arch_initcall(exynos4_dma_init);
diff --git a/arch/arm/mach-exynos4/gpiolib.c b/arch/arm/mach-exynos4/gpiolib.c
new file mode 100644
index 0000000..d54ca6a
--- /dev/null
+++ b/arch/arm/mach-exynos4/gpiolib.c
@@ -0,0 +1,365 @@
+/* linux/arch/arm/mach-exynos4/gpiolib.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIOlib support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/map.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+static struct s3c_gpio_cfg gpio_cfg = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_noint = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+/*
+ * Following are the gpio banks in v310.
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure gpio_cfg in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of s3c_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPA0(0),
+			.ngpio	= EXYNOS4_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPA1(0),
+			.ngpio	= EXYNOS4_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPB(0),
+			.ngpio	= EXYNOS4_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPC0(0),
+			.ngpio	= EXYNOS4_GPIO_C0_NR,
+			.label	= "GPC0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPC1(0),
+			.ngpio	= EXYNOS4_GPIO_C1_NR,
+			.label	= "GPC1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPD0(0),
+			.ngpio	= EXYNOS4_GPIO_D0_NR,
+			.label	= "GPD0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPD1(0),
+			.ngpio	= EXYNOS4_GPIO_D1_NR,
+			.label	= "GPD1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE0(0),
+			.ngpio	= EXYNOS4_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE1(0),
+			.ngpio	= EXYNOS4_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE2(0),
+			.ngpio	= EXYNOS4_GPIO_E2_NR,
+			.label	= "GPE2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE3(0),
+			.ngpio	= EXYNOS4_GPIO_E3_NR,
+			.label	= "GPE3",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE4(0),
+			.ngpio	= EXYNOS4_GPIO_E4_NR,
+			.label	= "GPE4",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF0(0),
+			.ngpio	= EXYNOS4_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF1(0),
+			.ngpio	= EXYNOS4_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF2(0),
+			.ngpio	= EXYNOS4_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF3(0),
+			.ngpio	= EXYNOS4_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	},
+};
+
+static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPJ0(0),
+			.ngpio	= EXYNOS4_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPJ1(0),
+			.ngpio	= EXYNOS4_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK0(0),
+			.ngpio	= EXYNOS4_GPIO_K0_NR,
+			.label	= "GPK0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK1(0),
+			.ngpio	= EXYNOS4_GPIO_K1_NR,
+			.label	= "GPK1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK2(0),
+			.ngpio	= EXYNOS4_GPIO_K2_NR,
+			.label	= "GPK2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK3(0),
+			.ngpio	= EXYNOS4_GPIO_K3_NR,
+			.label	= "GPK3",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL0(0),
+			.ngpio	= EXYNOS4_GPIO_L0_NR,
+			.label	= "GPL0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL1(0),
+			.ngpio	= EXYNOS4_GPIO_L1_NR,
+			.label	= "GPL1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL2(0),
+			.ngpio	= EXYNOS4_GPIO_L2_NR,
+			.label	= "GPL2",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY0(0),
+			.ngpio	= EXYNOS4_GPIO_Y0_NR,
+			.label	= "GPY0",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY1(0),
+			.ngpio	= EXYNOS4_GPIO_Y1_NR,
+			.label	= "GPY1",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY2(0),
+			.ngpio	= EXYNOS4_GPIO_Y2_NR,
+			.label	= "GPY2",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY3(0),
+			.ngpio	= EXYNOS4_GPIO_Y3_NR,
+			.label	= "GPY3",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY4(0),
+			.ngpio	= EXYNOS4_GPIO_Y4_NR,
+			.label	= "GPY4",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY5(0),
+			.ngpio	= EXYNOS4_GPIO_Y5_NR,
+			.label	= "GPY5",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY6(0),
+			.ngpio	= EXYNOS4_GPIO_Y6_NR,
+			.label	= "GPY6",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC00),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= EXYNOS4_GPX0(0),
+			.ngpio	= EXYNOS4_GPIO_X0_NR,
+			.label	= "GPX0",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC20),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= EXYNOS4_GPX1(0),
+			.ngpio	= EXYNOS4_GPIO_X1_NR,
+			.label	= "GPX1",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC40),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= EXYNOS4_GPX2(0),
+			.ngpio	= EXYNOS4_GPIO_X2_NR,
+			.label	= "GPX2",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC60),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= EXYNOS4_GPX3(0),
+			.ngpio	= EXYNOS4_GPIO_X3_NR,
+			.label	= "GPX3",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	},
+};
+
+static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPZ(0),
+			.ngpio	= EXYNOS4_GPIO_Z_NR,
+			.label	= "GPZ",
+		},
+	},
+};
+
+static __init int exynos4_gpiolib_init(void)
+{
+	struct s3c_gpio_chip *chip;
+	int i;
+	int group = 0;
+	int nr_chips;
+
+	/* GPIO part 1 */
+
+	chip = exynos4_gpio_part1_4bit;
+	nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL) {
+			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
+		if (chip->base == NULL)
+			chip->base = S5P_VA_GPIO1 + (i) * 0x20;
+	}
+
+	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
+
+	/* GPIO part 2 */
+
+	chip = exynos4_gpio_part2_4bit;
+	nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL) {
+			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
+		if (chip->base == NULL)
+			chip->base = S5P_VA_GPIO2 + (i) * 0x20;
+	}
+
+	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
+
+	/* GPIO part 3 */
+
+	chip = exynos4_gpio_part3_4bit;
+	nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL) {
+			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
+		if (chip->base == NULL)
+			chip->base = S5P_VA_GPIO3 + (i) * 0x20;
+	}
+
+	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+	s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+
+	return 0;
+}
+core_initcall(exynos4_gpiolib_init);
diff --git a/arch/arm/mach-exynos4/headsmp.S b/arch/arm/mach-exynos4/headsmp.S
new file mode 100644
index 0000000..6c6cfc5
--- /dev/null
+++ b/arch/arm/mach-exynos4/headsmp.S
@@ -0,0 +1,41 @@
+/*
+ *  linux/arch/arm/mach-exynos4/headsmp.S
+ *
+ *  Cloned from linux/arch/arm/mach-realview/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  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/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * exynos4 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(exynos4_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
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+1:	.long	.
+	.long	pen_release
diff --git a/arch/arm/mach-exynos4/hotplug.c b/arch/arm/mach-exynos4/hotplug.c
new file mode 100644
index 0000000..2b5909e
--- /dev/null
+++ b/arch/arm/mach-exynos4/hotplug.c
@@ -0,0 +1,130 @@
+/* linux arch/arm/mach-exynos4/hotplug.c
+ *
+ *  Cloned from 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>
+
+extern volatile int pen_release;
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	mcr	p15, 0, %1, c7, c10, 4\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, %3\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), "Ir" (0x40)
+	  : "cc");
+}
+
+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, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  : "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+	/*
+	 * there is no power-control hardware on this platform, so all
+	 * we can do is put the core into WFI; this is safe as the calling
+	 * code will have already disabled interrupts
+	 */
+	for (;;) {
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+
+		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)++;
+	}
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	int spurious = 0;
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_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);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff --git a/arch/arm/mach-exynos4/include/mach/debug-macro.S b/arch/arm/mach-exynos4/include/mach/debug-macro.S
new file mode 100644
index 0000000..58bbd04
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/debug-macro.S
@@ -0,0 +1,35 @@
+/* linux/arch/arm/mach-exynos4/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rp, rv
+		ldreq	\rp, = S3C_PA_UART
+		ldrne	\rv, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-exynos4/include/mach/dma.h b/arch/arm/mach-exynos4/include/mach/dma.h
new file mode 100644
index 0000000..81209eb
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/dma.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __MACH_DMA_H
+#define __MACH_DMA_H
+
+/* This platform uses the common S3C DMA API driver for PL330 */
+#include <plat/s3c-dma-pl330.h>
+
+#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
new file mode 100644
index 0000000..d8f38c2
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -0,0 +1,84 @@
+/* arch/arm/mach-exynos4/include/mach/entry-macro.S
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for EXYNOS4 platforms
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+*/
+
+#include <mach/hardware.h>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
+		/*
+		 * The interrupt numbering scheme is defined in the
+		 * interrupt controller spec.  To wit:
+		 *
+		 * Interrupts 0-15 are IPI
+		 * 16-28 are reserved
+		 * 29-31 are local.  We allow 30 to be used for the watchdog.
+		 * 32-1020 are global
+		 * 1021-1022 are reserved
+		 * 1023 is "spurious" (no interrupt)
+		 *
+		 * For now, we ignore all local interrupts so only return an interrupt if it's
+		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+		 *
+		 * A simple read from the controller will tell us the number of the highest
+                 * priority enabled interrupt.  We then just need to check whether it is in the
+		 * valid range for an IRQ (30-1020 inclusive).
+		 */
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
+
+		ldr	\tmp, =1021
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #29
+		cmpcc	\irqnr, \irqnr
+		cmpne	\irqnr, \tmp
+		cmpcs	\irqnr, \irqnr
+		addne	\irqnr, \irqnr, #32
+
+		.endm
+
+		/* We assume that irqstat (the raw value of the IRQ acknowledge
+		 * register) is preserved from the macro above.
+		 * If there is an IPI, we immediately signal end of interrupt on the
+		 * controller, since this requires the original irqstat value which
+		 * we won't easily be able to recreate later.
+		 */
+
+		.macro test_for_ipi, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		cmp	\irqnr, #16
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		cmpcs	\irqnr, \irqnr
+		.endm
+
+		/* As above, this assumes that irqstat and base are preserved.. */
+
+		.macro test_for_ltirq, irqnr, irqstat, base, tmp
+		bic	\irqnr, \irqstat, #0x1c00
+		mov	\tmp, #0
+		cmp	\irqnr, #29
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
diff --git a/arch/arm/mach-exynos4/include/mach/gpio.h b/arch/arm/mach-exynos4/include/mach/gpio.h
new file mode 100644
index 0000000..939728b
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/gpio.h
@@ -0,0 +1,156 @@
+/* linux/arch/arm/mach-exynos4/include/mach/gpio.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIO lib 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_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* Practically, GPIO banks upto GPZ are the configurable gpio banks */
+
+/* GPIO bank sizes */
+#define EXYNOS4_GPIO_A0_NR	(8)
+#define EXYNOS4_GPIO_A1_NR	(6)
+#define EXYNOS4_GPIO_B_NR	(8)
+#define EXYNOS4_GPIO_C0_NR	(5)
+#define EXYNOS4_GPIO_C1_NR	(5)
+#define EXYNOS4_GPIO_D0_NR	(4)
+#define EXYNOS4_GPIO_D1_NR	(4)
+#define EXYNOS4_GPIO_E0_NR	(5)
+#define EXYNOS4_GPIO_E1_NR	(8)
+#define EXYNOS4_GPIO_E2_NR	(6)
+#define EXYNOS4_GPIO_E3_NR	(8)
+#define EXYNOS4_GPIO_E4_NR	(8)
+#define EXYNOS4_GPIO_F0_NR	(8)
+#define EXYNOS4_GPIO_F1_NR	(8)
+#define EXYNOS4_GPIO_F2_NR	(8)
+#define EXYNOS4_GPIO_F3_NR	(6)
+#define EXYNOS4_GPIO_J0_NR	(8)
+#define EXYNOS4_GPIO_J1_NR	(5)
+#define EXYNOS4_GPIO_K0_NR	(7)
+#define EXYNOS4_GPIO_K1_NR	(7)
+#define EXYNOS4_GPIO_K2_NR	(7)
+#define EXYNOS4_GPIO_K3_NR	(7)
+#define EXYNOS4_GPIO_L0_NR	(8)
+#define EXYNOS4_GPIO_L1_NR	(3)
+#define EXYNOS4_GPIO_L2_NR	(8)
+#define EXYNOS4_GPIO_X0_NR	(8)
+#define EXYNOS4_GPIO_X1_NR	(8)
+#define EXYNOS4_GPIO_X2_NR	(8)
+#define EXYNOS4_GPIO_X3_NR	(8)
+#define EXYNOS4_GPIO_Y0_NR	(6)
+#define EXYNOS4_GPIO_Y1_NR	(4)
+#define EXYNOS4_GPIO_Y2_NR	(6)
+#define EXYNOS4_GPIO_Y3_NR	(8)
+#define EXYNOS4_GPIO_Y4_NR	(8)
+#define EXYNOS4_GPIO_Y5_NR	(8)
+#define EXYNOS4_GPIO_Y6_NR	(8)
+#define EXYNOS4_GPIO_Z_NR	(7)
+
+/* GPIO bank numbers */
+
+#define EXYNOS4_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	EXYNOS4_GPIO_A0_START	= 0,
+	EXYNOS4_GPIO_A1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A0),
+	EXYNOS4_GPIO_B_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A1),
+	EXYNOS4_GPIO_C0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_B),
+	EXYNOS4_GPIO_C1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C0),
+	EXYNOS4_GPIO_D0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C1),
+	EXYNOS4_GPIO_D1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D0),
+	EXYNOS4_GPIO_E0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D1),
+	EXYNOS4_GPIO_E1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E0),
+	EXYNOS4_GPIO_E2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E1),
+	EXYNOS4_GPIO_E3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E2),
+	EXYNOS4_GPIO_E4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E3),
+	EXYNOS4_GPIO_F0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E4),
+	EXYNOS4_GPIO_F1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F0),
+	EXYNOS4_GPIO_F2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F1),
+	EXYNOS4_GPIO_F3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F2),
+	EXYNOS4_GPIO_J0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F3),
+	EXYNOS4_GPIO_J1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J0),
+	EXYNOS4_GPIO_K0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J1),
+	EXYNOS4_GPIO_K1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K0),
+	EXYNOS4_GPIO_K2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K1),
+	EXYNOS4_GPIO_K3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K2),
+	EXYNOS4_GPIO_L0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K3),
+	EXYNOS4_GPIO_L1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L0),
+	EXYNOS4_GPIO_L2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L1),
+	EXYNOS4_GPIO_X0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L2),
+	EXYNOS4_GPIO_X1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X0),
+	EXYNOS4_GPIO_X2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X1),
+	EXYNOS4_GPIO_X3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X2),
+	EXYNOS4_GPIO_Y0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X3),
+	EXYNOS4_GPIO_Y1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y0),
+	EXYNOS4_GPIO_Y2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y1),
+	EXYNOS4_GPIO_Y3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y2),
+	EXYNOS4_GPIO_Y4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y3),
+	EXYNOS4_GPIO_Y5_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y4),
+	EXYNOS4_GPIO_Y6_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y5),
+	EXYNOS4_GPIO_Z_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y6),
+};
+
+/* EXYNOS4 GPIO number definitions */
+#define EXYNOS4_GPA0(_nr)	(EXYNOS4_GPIO_A0_START + (_nr))
+#define EXYNOS4_GPA1(_nr)	(EXYNOS4_GPIO_A1_START + (_nr))
+#define EXYNOS4_GPB(_nr)	(EXYNOS4_GPIO_B_START + (_nr))
+#define EXYNOS4_GPC0(_nr)	(EXYNOS4_GPIO_C0_START + (_nr))
+#define EXYNOS4_GPC1(_nr)	(EXYNOS4_GPIO_C1_START + (_nr))
+#define EXYNOS4_GPD0(_nr)	(EXYNOS4_GPIO_D0_START + (_nr))
+#define EXYNOS4_GPD1(_nr)	(EXYNOS4_GPIO_D1_START + (_nr))
+#define EXYNOS4_GPE0(_nr)	(EXYNOS4_GPIO_E0_START + (_nr))
+#define EXYNOS4_GPE1(_nr)	(EXYNOS4_GPIO_E1_START + (_nr))
+#define EXYNOS4_GPE2(_nr)	(EXYNOS4_GPIO_E2_START + (_nr))
+#define EXYNOS4_GPE3(_nr)	(EXYNOS4_GPIO_E3_START + (_nr))
+#define EXYNOS4_GPE4(_nr)	(EXYNOS4_GPIO_E4_START + (_nr))
+#define EXYNOS4_GPF0(_nr)	(EXYNOS4_GPIO_F0_START + (_nr))
+#define EXYNOS4_GPF1(_nr)	(EXYNOS4_GPIO_F1_START + (_nr))
+#define EXYNOS4_GPF2(_nr)	(EXYNOS4_GPIO_F2_START + (_nr))
+#define EXYNOS4_GPF3(_nr)	(EXYNOS4_GPIO_F3_START + (_nr))
+#define EXYNOS4_GPJ0(_nr)	(EXYNOS4_GPIO_J0_START + (_nr))
+#define EXYNOS4_GPJ1(_nr)	(EXYNOS4_GPIO_J1_START + (_nr))
+#define EXYNOS4_GPK0(_nr)	(EXYNOS4_GPIO_K0_START + (_nr))
+#define EXYNOS4_GPK1(_nr)	(EXYNOS4_GPIO_K1_START + (_nr))
+#define EXYNOS4_GPK2(_nr)	(EXYNOS4_GPIO_K2_START + (_nr))
+#define EXYNOS4_GPK3(_nr)	(EXYNOS4_GPIO_K3_START + (_nr))
+#define EXYNOS4_GPL0(_nr)	(EXYNOS4_GPIO_L0_START + (_nr))
+#define EXYNOS4_GPL1(_nr)	(EXYNOS4_GPIO_L1_START + (_nr))
+#define EXYNOS4_GPL2(_nr)	(EXYNOS4_GPIO_L2_START + (_nr))
+#define EXYNOS4_GPX0(_nr)	(EXYNOS4_GPIO_X0_START + (_nr))
+#define EXYNOS4_GPX1(_nr)	(EXYNOS4_GPIO_X1_START + (_nr))
+#define EXYNOS4_GPX2(_nr)	(EXYNOS4_GPIO_X2_START + (_nr))
+#define EXYNOS4_GPX3(_nr)	(EXYNOS4_GPIO_X3_START + (_nr))
+#define EXYNOS4_GPY0(_nr)	(EXYNOS4_GPIO_Y0_START + (_nr))
+#define EXYNOS4_GPY1(_nr)	(EXYNOS4_GPIO_Y1_START + (_nr))
+#define EXYNOS4_GPY2(_nr)	(EXYNOS4_GPIO_Y2_START + (_nr))
+#define EXYNOS4_GPY3(_nr)	(EXYNOS4_GPIO_Y3_START + (_nr))
+#define EXYNOS4_GPY4(_nr)	(EXYNOS4_GPIO_Y4_START + (_nr))
+#define EXYNOS4_GPY5(_nr)	(EXYNOS4_GPIO_Y5_START + (_nr))
+#define EXYNOS4_GPY6(_nr)	(EXYNOS4_GPIO_Y6_START + (_nr))
+#define EXYNOS4_GPZ(_nr)	(EXYNOS4_GPIO_Z_START + (_nr))
+
+/* the end of the EXYNOS4 specific gpios */
+#define EXYNOS4_GPIO_END	(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) + 1)
+#define S3C_GPIO_END		EXYNOS4_GPIO_END
+
+/* define the number of gpios we need to the one after the GPZ() range */
+#define ARCH_NR_GPIOS		(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-exynos4/include/mach/hardware.h b/arch/arm/mach-exynos4/include/mach/hardware.h
new file mode 100644
index 0000000..5109eb2
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/hardware.h
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-exynos4/include/mach/hardware.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Hardware 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_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-exynos4/include/mach/io.h b/arch/arm/mach-exynos4/include/mach/io.h
new file mode 100644
index 0000000..d5478d2
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/io.h
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-exynos4/include/mach/io.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/io.h
+ *
+ * Default IO routines for EXYNOS4
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H __FILE__
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
new file mode 100644
index 0000000..5d03730
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -0,0 +1,160 @@
+/* linux/arch/arm/mach-exynos4/include/mach/irqs.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* PPI: Private Peripheral Interrupt */
+
+#define IRQ_PPI(x)		S5P_IRQ(x+16)
+
+#define IRQ_LOCALTIMER		IRQ_PPI(13)
+
+/* SPI: Shared Peripheral Interrupt */
+
+#define IRQ_SPI(x)		S5P_IRQ(x+32)
+
+#define IRQ_MCT1		IRQ_SPI(35)
+
+#define IRQ_EINT0		IRQ_SPI(40)
+#define IRQ_EINT1		IRQ_SPI(41)
+#define IRQ_EINT2		IRQ_SPI(42)
+#define IRQ_EINT3		IRQ_SPI(43)
+#define IRQ_USB_HSOTG		IRQ_SPI(44)
+#define IRQ_USB_HOST		IRQ_SPI(45)
+#define IRQ_MODEM_IF		IRQ_SPI(46)
+#define IRQ_ROTATOR		IRQ_SPI(47)
+#define IRQ_JPEG		IRQ_SPI(48)
+#define IRQ_2D			IRQ_SPI(49)
+#define IRQ_PCIE		IRQ_SPI(50)
+#define IRQ_MCT0		IRQ_SPI(51)
+#define IRQ_MFC			IRQ_SPI(52)
+#define IRQ_AUDIO_SS		IRQ_SPI(54)
+#define IRQ_AC97		IRQ_SPI(55)
+#define IRQ_SPDIF		IRQ_SPI(56)
+#define IRQ_KEYPAD		IRQ_SPI(57)
+#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(58)
+#define IRQ_SLIMBUS		IRQ_SPI(59)
+#define IRQ_PMU			IRQ_SPI(60)
+#define IRQ_TSI			IRQ_SPI(61)
+#define IRQ_SATA		IRQ_SPI(62)
+#define IRQ_GPS			IRQ_SPI(63)
+
+#define MAX_IRQ_IN_COMBINER	8
+#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
+
+#define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
+#define IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
+#define IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
+#define IRQ_SYSMMU_FIMC1_0	COMBINER_IRQ(4, 3)
+#define IRQ_SYSMMU_FIMC2_0	COMBINER_IRQ(4, 4)
+#define IRQ_SYSMMU_FIMC3_0	COMBINER_IRQ(4, 5)
+#define IRQ_SYSMMU_JPEG_0	COMBINER_IRQ(4, 6)
+#define IRQ_SYSMMU_2D_0		COMBINER_IRQ(4, 7)
+
+#define IRQ_SYSMMU_ROTATOR_0	COMBINER_IRQ(5, 0)
+#define IRQ_SYSMMU_MDMA1_0	COMBINER_IRQ(5, 1)
+#define IRQ_SYSMMU_LCD0_M0_0	COMBINER_IRQ(5, 2)
+#define IRQ_SYSMMU_LCD1_M1_0	COMBINER_IRQ(5, 3)
+#define IRQ_SYSMMU_TV_M0_0	COMBINER_IRQ(5, 4)
+#define IRQ_SYSMMU_MFC_M0_0	COMBINER_IRQ(5, 5)
+#define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
+#define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
+
+#define IRQ_PDMA0		COMBINER_IRQ(21, 0)
+#define IRQ_PDMA1		COMBINER_IRQ(21, 1)
+
+#define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
+#define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
+#define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
+#define IRQ_TIMER3_VIC		COMBINER_IRQ(22, 3)
+#define IRQ_TIMER4_VIC		COMBINER_IRQ(22, 4)
+
+#define IRQ_RTC_ALARM		COMBINER_IRQ(23, 0)
+#define IRQ_RTC_TIC		COMBINER_IRQ(23, 1)
+
+#define IRQ_GPIO_XB		COMBINER_IRQ(24, 0)
+#define IRQ_GPIO_XA		COMBINER_IRQ(24, 1)
+
+#define IRQ_UART0		COMBINER_IRQ(26, 0)
+#define IRQ_UART1		COMBINER_IRQ(26, 1)
+#define IRQ_UART2		COMBINER_IRQ(26, 2)
+#define IRQ_UART3		COMBINER_IRQ(26, 3)
+#define IRQ_UART4		COMBINER_IRQ(26, 4)
+
+#define IRQ_IIC			COMBINER_IRQ(27, 0)
+#define IRQ_IIC1		COMBINER_IRQ(27, 1)
+#define IRQ_IIC2		COMBINER_IRQ(27, 2)
+#define IRQ_IIC3		COMBINER_IRQ(27, 3)
+#define IRQ_IIC4		COMBINER_IRQ(27, 4)
+#define IRQ_IIC5		COMBINER_IRQ(27, 5)
+#define IRQ_IIC6		COMBINER_IRQ(27, 6)
+#define IRQ_IIC7		COMBINER_IRQ(27, 7)
+
+#define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
+#define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
+#define IRQ_HSMMC2		COMBINER_IRQ(29, 2)
+#define IRQ_HSMMC3		COMBINER_IRQ(29, 3)
+
+#define IRQ_MIPI_CSIS0		COMBINER_IRQ(30, 0)
+#define IRQ_MIPI_CSIS1		COMBINER_IRQ(30, 1)
+
+#define IRQ_FIMC0		COMBINER_IRQ(32, 0)
+#define IRQ_FIMC1		COMBINER_IRQ(32, 1)
+#define IRQ_FIMC2		COMBINER_IRQ(33, 0)
+#define IRQ_FIMC3		COMBINER_IRQ(33, 1)
+
+#define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
+
+#define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
+
+#define IRQ_EINT4		COMBINER_IRQ(37, 0)
+#define IRQ_EINT5		COMBINER_IRQ(37, 1)
+#define IRQ_EINT6		COMBINER_IRQ(37, 2)
+#define IRQ_EINT7		COMBINER_IRQ(37, 3)
+#define IRQ_EINT8		COMBINER_IRQ(38, 0)
+
+#define IRQ_EINT9		COMBINER_IRQ(38, 1)
+#define IRQ_EINT10		COMBINER_IRQ(38, 2)
+#define IRQ_EINT11		COMBINER_IRQ(38, 3)
+#define IRQ_EINT12		COMBINER_IRQ(38, 4)
+#define IRQ_EINT13		COMBINER_IRQ(38, 5)
+#define IRQ_EINT14		COMBINER_IRQ(38, 6)
+#define IRQ_EINT15		COMBINER_IRQ(38, 7)
+
+#define IRQ_EINT16_31		COMBINER_IRQ(39, 0)
+
+#define IRQ_MCT_L0		COMBINER_IRQ(51, 0)
+
+#define IRQ_WDT			COMBINER_IRQ(53, 0)
+#define IRQ_MCT_G0		COMBINER_IRQ(53, 4)
+
+#define MAX_COMBINER_NR		54
+
+#define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
+
+#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
+#define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
+
+/* optional GPIO interrupts */
+#define S5P_GPIOINT_BASE	(S5P_IRQ_EINT_BASE + 32)
+#define IRQ_GPIO1_NR_GROUPS	16
+#define IRQ_GPIO2_NR_GROUPS	9
+#define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
+
+/* Set the default NR_IRQS */
+#define NR_IRQS			(IRQ_GPIO_END)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
new file mode 100644
index 0000000..6330b73
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -0,0 +1,162 @@
+/* linux/arch/arm/mach-exynos4/include/mach/map.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4 - Memory map definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+
+/*
+ * EXYNOS4 UART offset is 0x10000 but the older S5P SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET			(0x10000)
+
+#include <plat/map-s5p.h>
+
+#define EXYNOS4_PA_SYSRAM		0x02020000
+
+#define EXYNOS4_PA_FIMC0		0x11800000
+#define EXYNOS4_PA_FIMC1		0x11810000
+#define EXYNOS4_PA_FIMC2		0x11820000
+#define EXYNOS4_PA_FIMC3		0x11830000
+
+#define EXYNOS4_PA_I2S0			0x03830000
+#define EXYNOS4_PA_I2S1			0xE3100000
+#define EXYNOS4_PA_I2S2			0xE2A00000
+
+#define EXYNOS4_PA_PCM0			0x03840000
+#define EXYNOS4_PA_PCM1			0x13980000
+#define EXYNOS4_PA_PCM2			0x13990000
+
+#define EXYNOS4_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
+
+#define EXYNOS4_PA_ONENAND		0x0C000000
+#define EXYNOS4_PA_ONENAND_DMA		0x0C600000
+
+#define EXYNOS4_PA_CHIPID		0x10000000
+
+#define EXYNOS4_PA_SYSCON		0x10010000
+#define EXYNOS4_PA_PMU			0x10020000
+#define EXYNOS4_PA_CMU			0x10030000
+
+#define EXYNOS4_PA_SYSTIMER		0x10050000
+#define EXYNOS4_PA_WATCHDOG		0x10060000
+#define EXYNOS4_PA_RTC			0x10070000
+
+#define EXYNOS4_PA_KEYPAD		0x100A0000
+
+#define EXYNOS4_PA_DMC0			0x10400000
+
+#define EXYNOS4_PA_COMBINER		0x10448000
+
+#define EXYNOS4_PA_COREPERI		0x10500000
+#define EXYNOS4_PA_GIC_CPU		0x10500100
+#define EXYNOS4_PA_TWD			0x10500600
+#define EXYNOS4_PA_GIC_DIST		0x10501000
+#define EXYNOS4_PA_L2CC			0x10502000
+
+#define EXYNOS4_PA_MDMA			0x10810000
+#define EXYNOS4_PA_PDMA0		0x12680000
+#define EXYNOS4_PA_PDMA1		0x12690000
+
+#define EXYNOS4_PA_SYSMMU_MDMA		0x10A40000
+#define EXYNOS4_PA_SYSMMU_SSS		0x10A50000
+#define EXYNOS4_PA_SYSMMU_FIMC0		0x11A20000
+#define EXYNOS4_PA_SYSMMU_FIMC1		0x11A30000
+#define EXYNOS4_PA_SYSMMU_FIMC2		0x11A40000
+#define EXYNOS4_PA_SYSMMU_FIMC3		0x11A50000
+#define EXYNOS4_PA_SYSMMU_JPEG		0x11A60000
+#define EXYNOS4_PA_SYSMMU_FIMD0		0x11E20000
+#define EXYNOS4_PA_SYSMMU_FIMD1		0x12220000
+#define EXYNOS4_PA_SYSMMU_PCIe		0x12620000
+#define EXYNOS4_PA_SYSMMU_G2D		0x12A20000
+#define EXYNOS4_PA_SYSMMU_ROTATOR	0x12A30000
+#define EXYNOS4_PA_SYSMMU_MDMA2		0x12A40000
+#define EXYNOS4_PA_SYSMMU_TV		0x12E20000
+#define EXYNOS4_PA_SYSMMU_MFC_L		0x13620000
+#define EXYNOS4_PA_SYSMMU_MFC_R		0x13630000
+
+#define EXYNOS4_PA_GPIO1		0x11400000
+#define EXYNOS4_PA_GPIO2		0x11000000
+#define EXYNOS4_PA_GPIO3		0x03860000
+
+#define EXYNOS4_PA_MIPI_CSIS0		0x11880000
+#define EXYNOS4_PA_MIPI_CSIS1		0x11890000
+
+#define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
+
+#define EXYNOS4_PA_SATA			0x12560000
+#define EXYNOS4_PA_SATAPHY		0x125D0000
+#define EXYNOS4_PA_SATAPHY_CTRL		0x126B0000
+
+#define EXYNOS4_PA_SROMC		0x12570000
+
+#define EXYNOS4_PA_UART			0x13800000
+
+#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
+
+#define EXYNOS4_PA_AC97			0x139A0000
+
+#define EXYNOS4_PA_SPDIF		0x139B0000
+
+#define EXYNOS4_PA_TIMER		0x139D0000
+
+#define EXYNOS4_PA_SDRAM		0x40000000
+
+/* Compatibiltiy Defines */
+
+#define S3C_PA_HSMMC0			EXYNOS4_PA_HSMMC(0)
+#define S3C_PA_HSMMC1			EXYNOS4_PA_HSMMC(1)
+#define S3C_PA_HSMMC2			EXYNOS4_PA_HSMMC(2)
+#define S3C_PA_HSMMC3			EXYNOS4_PA_HSMMC(3)
+#define S3C_PA_IIC			EXYNOS4_PA_IIC(0)
+#define S3C_PA_IIC1			EXYNOS4_PA_IIC(1)
+#define S3C_PA_IIC2			EXYNOS4_PA_IIC(2)
+#define S3C_PA_IIC3			EXYNOS4_PA_IIC(3)
+#define S3C_PA_IIC4			EXYNOS4_PA_IIC(4)
+#define S3C_PA_IIC5			EXYNOS4_PA_IIC(5)
+#define S3C_PA_IIC6			EXYNOS4_PA_IIC(6)
+#define S3C_PA_IIC7			EXYNOS4_PA_IIC(7)
+#define S3C_PA_RTC			EXYNOS4_PA_RTC
+#define S3C_PA_WDT			EXYNOS4_PA_WATCHDOG
+
+#define S5P_PA_CHIPID			EXYNOS4_PA_CHIPID
+#define S5P_PA_FIMC0			EXYNOS4_PA_FIMC0
+#define S5P_PA_FIMC1			EXYNOS4_PA_FIMC1
+#define S5P_PA_FIMC2			EXYNOS4_PA_FIMC2
+#define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
+#define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
+#define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
+#define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
+#define S5P_PA_SDRAM			EXYNOS4_PA_SDRAM
+#define S5P_PA_SROMC			EXYNOS4_PA_SROMC
+#define S5P_PA_SYSCON			EXYNOS4_PA_SYSCON
+#define S5P_PA_TIMER			EXYNOS4_PA_TIMER
+
+#define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+
+/* UART */
+
+#define S3C_PA_UART			EXYNOS4_PA_UART
+
+#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_PA_UART0			S5P_PA_UART(0)
+#define S5P_PA_UART1			S5P_PA_UART(1)
+#define S5P_PA_UART2			S5P_PA_UART(2)
+#define S5P_PA_UART3			S5P_PA_UART(3)
+#define S5P_PA_UART4			S5P_PA_UART(4)
+
+#define S5P_SZ_UART			SZ_256
+
+#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-exynos4/include/mach/memory.h b/arch/arm/mach-exynos4/include/mach/memory.h
new file mode 100644
index 0000000..374ef2c
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/memory.h
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/memory.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Memory definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H __FILE__
+
+#define PLAT_PHYS_OFFSET		UL(0x40000000)
+
+/* Maximum of 256MiB in one bank */
+#define MAX_PHYSMEM_BITS	32
+#define SECTION_SIZE_BITS	28
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-exynos4/include/mach/pm-core.h b/arch/arm/mach-exynos4/include/mach/pm-core.h
new file mode 100644
index 0000000..f26e46b
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/pm-core.h
@@ -0,0 +1,49 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * EXYNOS4210 - PM core support for arch/arm/plat-s5p/pm.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 <mach/regs-pmu.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	/* nothing here yet */
+}
+
+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, S5P_EINT_WAKEUP_MASK);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+	/* nothing here yet */
+}
diff --git a/arch/arm/mach-exynos4/include/mach/pwm-clock.h b/arch/arm/mach-exynos4/include/mach/pwm-clock.h
new file mode 100644
index 0000000..8e12090
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/pwm-clock.h
@@ -0,0 +1,70 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pwm-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
+ *
+ * EXYNOS4 - pwm clock and 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.
+*/
+
+#ifndef __ASM_ARCH_PWMCLK_H
+#define __ASM_ARCH_PWMCLK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	return 1 << tcfg1;
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	return 1;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	return ilog2(div);
+}
+
+#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
+
+#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-clock.h b/arch/arm/mach-exynos4/include/mach/regs-clock.h
new file mode 100644
index 0000000..6e311c1
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-clock.h
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Clock register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
+
+#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
+#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
+#define S5P_CLKGATE_IP_LEFTBUS		S5P_CLKREG(0x04800)
+
+#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
+#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
+#define S5P_CLKGATE_IP_RIGHTBUS		S5P_CLKREG(0x08800)
+
+#define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
+#define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
+#define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
+#define S5P_VPLL_CON1			S5P_CLKREG(0x0C124)
+
+#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
+#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
+#define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
+#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
+#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
+#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
+#define S5P_CLKSRC_MAUDIO		S5P_CLKREG(0x0C23C)
+#define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
+#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
+#define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
+
+#define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
+#define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
+#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
+#define S5P_CLKDIV_MFC			S5P_CLKREG(0x0C528)
+#define S5P_CLKDIV_G3D			S5P_CLKREG(0x0C52C)
+#define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
+#define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
+#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
+#define S5P_CLKDIV_MAUDIO		S5P_CLKREG(0x0C53C)
+#define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
+#define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
+#define S5P_CLKDIV_FSYS2		S5P_CLKREG(0x0C548)
+#define S5P_CLKDIV_FSYS3		S5P_CLKREG(0x0C54C)
+#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x0C550)
+#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x0C554)
+#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x0C558)
+#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
+#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
+#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
+
+#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
+#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
+#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
+#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
+#define S5P_CLKSRC_MASK_MAUDIO		S5P_CLKREG(0x0C33C)
+#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
+#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
+#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
+
+#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
+
+#define S5P_CLKGATE_SCLKCAM		S5P_CLKREG(0x0C820)
+#define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
+#define S5P_CLKGATE_IP_MFC		S5P_CLKREG(0x0C928)
+#define S5P_CLKGATE_IP_G3D		S5P_CLKREG(0x0C92C)
+#define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
+#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
+#define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
+#define S5P_CLKGATE_IP_GPS		S5P_CLKREG(0x0C94C)
+#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
+#define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_BLOCK		S5P_CLKREG(0x0C970)
+
+#define S5P_CLKSRC_MASK_DMC		S5P_CLKREG(0x10300)
+#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
+#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
+#define S5P_CLKDIV_DMC1			S5P_CLKREG(0x10504)
+#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
+#define S5P_CLKGATE_IP_DMC		S5P_CLKREG(0x10900)
+
+#define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
+#define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
+#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
+#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
+#define S5P_MPLL_CON0			S5P_CLKREG(0x14108)
+#define S5P_MPLL_CON1			S5P_CLKREG(0x1410C)
+
+#define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
+#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
+
+#define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
+#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
+#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
+#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
+
+#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
+#define S5P_CLKGATE_IP_CPU		S5P_CLKREG(0x14900)
+
+#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
+
+#define S5P_APLLCON0_ENABLE_SHIFT	(31)
+#define S5P_APLLCON0_LOCKED_SHIFT	(29)
+#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
+#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
+
+#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
+#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
+
+#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
+#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
+#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
+#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
+#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
+#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
+#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
+#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
+#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
+#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
+#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
+#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
+
+#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
+#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
+#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
+#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
+#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
+#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
+#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
+#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
+#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
+#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
+#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
+#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
+#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
+#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
+
+#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
+#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
+#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
+#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
+#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
+#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
+#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
+
+#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
+#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
+#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
+#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
+
+/* Compatibility defines and inclusion */
+
+#include <mach/regs-pmu.h>
+
+#define S5P_EPLL_CON			S5P_EPLL_CON0
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-gpio.h b/arch/arm/mach-exynos4/include/mach/regs-gpio.h
new file mode 100644
index 0000000..1401b21
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-gpio.h
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-gpio.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIO (including EINT) register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_GPIO_H
+#define __ASM_ARCH_REGS_GPIO_H __FILE__
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#define EXYNOS4_EINT40CON		(S5P_VA_GPIO2 + 0xE00)
+#define S5P_EINT_CON(x)			(EXYNOS4_EINT40CON + ((x) * 0x4))
+
+#define EXYNOS4_EINT40FLTCON0		(S5P_VA_GPIO2 + 0xE80)
+#define S5P_EINT_FLTCON(x)		(EXYNOS4_EINT40FLTCON0 + ((x) * 0x4))
+
+#define EXYNOS4_EINT40MASK		(S5P_VA_GPIO2 + 0xF00)
+#define S5P_EINT_MASK(x)		(EXYNOS4_EINT40MASK + ((x) * 0x4))
+
+#define EXYNOS4_EINT40PEND		(S5P_VA_GPIO2 + 0xF40)
+#define S5P_EINT_PEND(x)		(EXYNOS4_EINT40PEND + ((x) * 0x4))
+
+#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
+
+#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
+
+#define EINT_MODE			S3C_GPIO_SFN(0xf)
+
+#define EINT_GPIO_0(x)			EXYNOS4_GPX0(x)
+#define EINT_GPIO_1(x)			EXYNOS4_GPX1(x)
+#define EINT_GPIO_2(x)			EXYNOS4_GPX2(x)
+#define EINT_GPIO_3(x)			EXYNOS4_GPX3(x)
+
+#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-irq.h b/arch/arm/mach-exynos4/include/mach/regs-irq.h
new file mode 100644
index 0000000..9c7b4bf
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-irq.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/gic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-mct.h b/arch/arm/mach-exynos4/include/mach/regs-mct.h
new file mode 100644
index 0000000..ca9c843
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-mct.h
@@ -0,0 +1,52 @@
+/* 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_L0_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L1_BASE		EXYNOS4_MCTREG(0x400)
+
+#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-exynos4/include/mach/regs-mem.h b/arch/arm/mach-exynos4/include/mach/regs-mem.h
new file mode 100644
index 0000000..0368b5a
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-mem.h
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-mem.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - SROMC and DMC register definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_REGS_MEM_H
+#define __ASM_ARCH_REGS_MEM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_DMC0_MEMCON_OFFSET		0x04
+
+#define S5P_DMC0_MEMTYPE_SHIFT		8
+#define S5P_DMC0_MEMTYPE_MASK		0xF
+
+#endif /* __ASM_ARCH_REGS_MEM_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-pmu.h b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
new file mode 100644
index 0000000..62b0014
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-pmu.h
@@ -0,0 +1,162 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Power management unit definition
+ *
+ * This program is free software; you can 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_PMU_H
+#define __ASM_ARCH_REGS_PMU_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_PMUREG(x)				(S5P_VA_PMU + (x))
+
+#define S5P_CENTRAL_SEQ_CONFIGURATION		S5P_PMUREG(0x0200)
+
+#define S5P_CENTRAL_LOWPWR_CFG			(1 << 16)
+
+#define S5P_CENTRAL_SEQ_OPTION			S5P_PMUREG(0x0208)
+
+#define S5P_USE_STANDBY_WFI0			(1 << 16)
+#define S5P_USE_STANDBY_WFI1			(1 << 17)
+#define S5P_USE_STANDBY_WFE0			(1 << 24)
+#define S5P_USE_STANDBY_WFE1			(1 << 25)
+#define S5P_USE_MASK				((0x3 << 16) | (0x3 << 24))
+
+#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
+#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
+#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
+
+#define S5P_MIPI_DPHY_CONTROL(n)		S5P_PMUREG(0x0710 + (n) * 4)
+#define S5P_MIPI_DPHY_ENABLE			(1 << 0)
+#define S5P_MIPI_DPHY_SRESETN			(1 << 1)
+#define S5P_MIPI_DPHY_MRESETN			(1 << 2)
+
+#define S5P_PMU_SATA_PHY_CONTROL		S5P_PMUREG(0x0720)
+#define S5P_INFORM0				S5P_PMUREG(0x0800)
+#define S5P_INFORM1				S5P_PMUREG(0x0804)
+#define S5P_INFORM2				S5P_PMUREG(0x0808)
+#define S5P_INFORM3				S5P_PMUREG(0x080C)
+#define S5P_INFORM4				S5P_PMUREG(0x0810)
+#define S5P_INFORM5				S5P_PMUREG(0x0814)
+#define S5P_INFORM6				S5P_PMUREG(0x0818)
+#define S5P_INFORM7				S5P_PMUREG(0x081C)
+
+#define S5P_ARM_CORE0_LOWPWR			S5P_PMUREG(0x1000)
+#define S5P_DIS_IRQ_CORE0			S5P_PMUREG(0x1004)
+#define S5P_DIS_IRQ_CENTRAL0			S5P_PMUREG(0x1008)
+#define S5P_ARM_CORE1_LOWPWR			S5P_PMUREG(0x1010)
+#define S5P_DIS_IRQ_CORE1			S5P_PMUREG(0x1014)
+#define S5P_DIS_IRQ_CENTRAL1			S5P_PMUREG(0x1018)
+#define S5P_ARM_COMMON_LOWPWR			S5P_PMUREG(0x1080)
+#define S5P_L2_0_LOWPWR				S5P_PMUREG(0x10C0)
+#define S5P_L2_1_LOWPWR				S5P_PMUREG(0x10C4)
+#define S5P_CMU_ACLKSTOP_LOWPWR			S5P_PMUREG(0x1100)
+#define S5P_CMU_SCLKSTOP_LOWPWR			S5P_PMUREG(0x1104)
+#define S5P_CMU_RESET_LOWPWR			S5P_PMUREG(0x110C)
+#define S5P_APLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1120)
+#define S5P_MPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1124)
+#define S5P_VPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1128)
+#define S5P_EPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x112C)
+#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	S5P_PMUREG(0x1138)
+#define S5P_CMU_RESET_GPSALIVE_LOWPWR		S5P_PMUREG(0x113C)
+#define S5P_CMU_CLKSTOP_CAM_LOWPWR		S5P_PMUREG(0x1140)
+#define S5P_CMU_CLKSTOP_TV_LOWPWR		S5P_PMUREG(0x1144)
+#define S5P_CMU_CLKSTOP_MFC_LOWPWR		S5P_PMUREG(0x1148)
+#define S5P_CMU_CLKSTOP_G3D_LOWPWR		S5P_PMUREG(0x114C)
+#define S5P_CMU_CLKSTOP_LCD0_LOWPWR		S5P_PMUREG(0x1150)
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR		S5P_PMUREG(0x1154)
+#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		S5P_PMUREG(0x1158)
+#define S5P_CMU_CLKSTOP_GPS_LOWPWR		S5P_PMUREG(0x115C)
+#define S5P_CMU_RESET_CAM_LOWPWR		S5P_PMUREG(0x1160)
+#define S5P_CMU_RESET_TV_LOWPWR			S5P_PMUREG(0x1164)
+#define S5P_CMU_RESET_MFC_LOWPWR		S5P_PMUREG(0x1168)
+#define S5P_CMU_RESET_G3D_LOWPWR		S5P_PMUREG(0x116C)
+#define S5P_CMU_RESET_LCD0_LOWPWR		S5P_PMUREG(0x1170)
+#define S5P_CMU_RESET_LCD1_LOWPWR		S5P_PMUREG(0x1174)
+#define S5P_CMU_RESET_MAUDIO_LOWPWR		S5P_PMUREG(0x1178)
+#define S5P_CMU_RESET_GPS_LOWPWR		S5P_PMUREG(0x117C)
+#define S5P_TOP_BUS_LOWPWR			S5P_PMUREG(0x1180)
+#define S5P_TOP_RETENTION_LOWPWR		S5P_PMUREG(0x1184)
+#define S5P_TOP_PWR_LOWPWR			S5P_PMUREG(0x1188)
+#define S5P_LOGIC_RESET_LOWPWR			S5P_PMUREG(0x11A0)
+#define S5P_ONENAND_MEM_LOWPWR			S5P_PMUREG(0x11C0)
+#define S5P_MODIMIF_MEM_LOWPWR			S5P_PMUREG(0x11C4)
+#define S5P_G2D_ACP_MEM_LOWPWR			S5P_PMUREG(0x11C8)
+#define S5P_USBOTG_MEM_LOWPWR			S5P_PMUREG(0x11CC)
+#define S5P_HSMMC_MEM_LOWPWR			S5P_PMUREG(0x11D0)
+#define S5P_CSSYS_MEM_LOWPWR			S5P_PMUREG(0x11D4)
+#define S5P_SECSS_MEM_LOWPWR			S5P_PMUREG(0x11D8)
+#define S5P_PCIE_MEM_LOWPWR			S5P_PMUREG(0x11E0)
+#define S5P_SATA_MEM_LOWPWR			S5P_PMUREG(0x11E4)
+#define S5P_PAD_RETENTION_DRAM_LOWPWR		S5P_PMUREG(0x1200)
+#define S5P_PAD_RETENTION_MAUDIO_LOWPWR		S5P_PMUREG(0x1204)
+#define S5P_PAD_RETENTION_GPIO_LOWPWR		S5P_PMUREG(0x1220)
+#define S5P_PAD_RETENTION_UART_LOWPWR		S5P_PMUREG(0x1224)
+#define S5P_PAD_RETENTION_MMCA_LOWPWR		S5P_PMUREG(0x1228)
+#define S5P_PAD_RETENTION_MMCB_LOWPWR		S5P_PMUREG(0x122C)
+#define S5P_PAD_RETENTION_EBIA_LOWPWR		S5P_PMUREG(0x1230)
+#define S5P_PAD_RETENTION_EBIB_LOWPWR		S5P_PMUREG(0x1234)
+#define S5P_PAD_RETENTION_ISOLATION_LOWPWR	S5P_PMUREG(0x1240)
+#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR	S5P_PMUREG(0x1260)
+#define S5P_XUSBXTI_LOWPWR			S5P_PMUREG(0x1280)
+#define S5P_XXTI_LOWPWR				S5P_PMUREG(0x1284)
+#define S5P_EXT_REGULATOR_LOWPWR		S5P_PMUREG(0x12C0)
+#define S5P_GPIO_MODE_LOWPWR			S5P_PMUREG(0x1300)
+#define S5P_GPIO_MODE_MAUDIO_LOWPWR		S5P_PMUREG(0x1340)
+#define S5P_CAM_LOWPWR				S5P_PMUREG(0x1380)
+#define S5P_TV_LOWPWR				S5P_PMUREG(0x1384)
+#define S5P_MFC_LOWPWR				S5P_PMUREG(0x1388)
+#define S5P_G3D_LOWPWR				S5P_PMUREG(0x138C)
+#define S5P_LCD0_LOWPWR				S5P_PMUREG(0x1390)
+#define S5P_LCD1_LOWPWR				S5P_PMUREG(0x1394)
+#define S5P_MAUDIO_LOWPWR			S5P_PMUREG(0x1398)
+#define S5P_GPS_LOWPWR				S5P_PMUREG(0x139C)
+#define S5P_GPS_ALIVE_LOWPWR			S5P_PMUREG(0x13A0)
+
+#define S5P_ARM_CORE0_CONFIGURATION		S5P_PMUREG(0x2000)
+#define S5P_ARM_CORE0_OPTION			S5P_PMUREG(0x2008)
+#define S5P_ARM_CORE1_CONFIGURATION		S5P_PMUREG(0x2080)
+#define S5P_ARM_CORE1_STATUS			S5P_PMUREG(0x2084)
+#define S5P_ARM_CORE1_OPTION			S5P_PMUREG(0x2088)
+
+#define S5P_ARM_COMMON_OPTION			S5P_PMUREG(0x2408)
+#define S5P_TOP_PWR_OPTION			S5P_PMUREG(0x2C48)
+#define S5P_CAM_OPTION				S5P_PMUREG(0x3C08)
+#define S5P_TV_OPTION				S5P_PMUREG(0x3C28)
+#define S5P_MFC_OPTION				S5P_PMUREG(0x3C48)
+#define S5P_G3D_OPTION				S5P_PMUREG(0x3C68)
+#define S5P_LCD0_OPTION				S5P_PMUREG(0x3C88)
+#define S5P_LCD1_OPTION				S5P_PMUREG(0x3CA8)
+#define S5P_MAUDIO_OPTION			S5P_PMUREG(0x3CC8)
+#define S5P_GPS_OPTION				S5P_PMUREG(0x3CE8)
+#define S5P_GPS_ALIVE_OPTION			S5P_PMUREG(0x3D08)
+
+#define S5P_PAD_RET_MAUDIO_OPTION		S5P_PMUREG(0x3028)
+#define S5P_PAD_RET_GPIO_OPTION			S5P_PMUREG(0x3108)
+#define S5P_PAD_RET_UART_OPTION			S5P_PMUREG(0x3128)
+#define S5P_PAD_RET_MMCA_OPTION			S5P_PMUREG(0x3148)
+#define S5P_PAD_RET_MMCB_OPTION			S5P_PMUREG(0x3168)
+#define S5P_PAD_RET_EBIA_OPTION			S5P_PMUREG(0x3188)
+#define S5P_PAD_RET_EBIB_OPTION			S5P_PMUREG(0x31A8)
+
+#define S5P_PMU_CAM_CONF			S5P_PMUREG(0x3C00)
+#define S5P_PMU_TV_CONF				S5P_PMUREG(0x3C20)
+#define S5P_PMU_MFC_CONF			S5P_PMUREG(0x3C40)
+#define S5P_PMU_G3D_CONF			S5P_PMUREG(0x3C60)
+#define S5P_PMU_LCD0_CONF			S5P_PMUREG(0x3C80)
+#define S5P_PMU_LCD1_CONF			S5P_PMUREG(0x3CA0)
+#define S5P_PMU_GPS_CONF			S5P_PMUREG(0x3CE0)
+
+#define S5P_PMU_SATA_PHY_CONTROL_EN		0x1
+#define S5P_INT_LOCAL_PWR_EN			0x7
+
+#define S5P_CHECK_SLEEP				0x00000BAD
+
+#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h b/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
new file mode 100644
index 0000000..68ff6ad
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
@@ -0,0 +1,28 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - System MMU register
+ *
+ * This program is free software; you can 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_SYSMMU_H
+#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
+
+#define S5P_MMU_CTRL			0x000
+#define S5P_MMU_CFG			0x004
+#define S5P_MMU_STATUS			0x008
+#define S5P_MMU_FLUSH			0x00C
+#define S5P_PT_BASE_ADDR		0x014
+#define S5P_INT_STATUS			0x018
+#define S5P_INT_CLEAR			0x01C
+#define S5P_PAGE_FAULT_ADDR		0x024
+#define S5P_AW_FAULT_ADDR		0x028
+#define S5P_AR_FAULT_ADDR		0x02C
+#define S5P_DEFAULT_SLAVE_ADDR		0x030
+
+#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/smp.h b/arch/arm/mach-exynos4/include/mach/smp.h
new file mode 100644
index 0000000..a463dce
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/smp.h
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-exynos4/include/mach/smp.h
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/smp.h
+*/
+
+#ifndef ASM_ARCH_SMP_H
+#define ASM_ARCH_SMP_H __FILE__
+
+#include <asm/hardware/gic.h>
+
+/*
+ * We use IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
+{
+	gic_raise_softirq(mask, ipi);
+}
+
+#endif
diff --git a/arch/arm/mach-exynos4/include/mach/sysmmu.h b/arch/arm/mach-exynos4/include/mach/sysmmu.h
new file mode 100644
index 0000000..6a5fbb5
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/sysmmu.h
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung sysmmu driver for EXYNOS4
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARM_ARCH_SYSMMU_H
+#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
+
+enum exynos4_sysmmu_ips {
+	SYSMMU_MDMA,
+	SYSMMU_SSS,
+	SYSMMU_FIMC0,
+	SYSMMU_FIMC1,
+	SYSMMU_FIMC2,
+	SYSMMU_FIMC3,
+	SYSMMU_JPEG,
+	SYSMMU_FIMD0,
+	SYSMMU_FIMD1,
+	SYSMMU_PCIe,
+	SYSMMU_G2D,
+	SYSMMU_ROTATOR,
+	SYSMMU_MDMA2,
+	SYSMMU_TV,
+	SYSMMU_MFC_L,
+	SYSMMU_MFC_R,
+	EXYNOS4_SYSMMU_TOTAL_IPNUM,
+};
+
+#define S5P_SYSMMU_TOTAL_IPNUM		EXYNOS4_SYSMMU_TOTAL_IPNUM
+
+extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
+
+typedef enum exynos4_sysmmu_ips sysmmu_ips;
+
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
+void sysmmu_clk_enable(sysmmu_ips ips);
+void sysmmu_clk_disable(sysmmu_ips ips);
+
+#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff --git a/arch/arm/mach-exynos4/include/mach/system.h b/arch/arm/mach-exynos4/include/mach/system.h
new file mode 100644
index 0000000..5e3220c
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/system.h
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/system.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - system support header
+ *
+ * This program is free software; you can 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_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+#include <plat/system-reset.h>
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-exynos4/include/mach/timex.h b/arch/arm/mach-exynos4/include/mach/timex.h
new file mode 100644
index 0000000..6d13875
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/timex.h
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-exynos4/include/mach/timex.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2003-2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/timex.h
+ *
+ * EXYNOS4 - time parameters
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H __FILE__
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-exynos4/include/mach/uncompress.h b/arch/arm/mach-exynos4/include/mach/uncompress.h
new file mode 100644
index 0000000..21d97bc
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/uncompress.h
@@ -0,0 +1,30 @@
+/* linux/arch/arm/mach-exynos4/include/mach/uncompress.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - uncompress 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.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H __FILE__
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+
+	/*
+	 * For preventing FIFO overrun or infinite loop of UART console,
+	 * fifo_max should be the minimum fifo size of all of the UART channels
+	 */
+	fifo_mask = S5PV210_UFSTAT_TXMASK;
+	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
+}
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-exynos4/include/mach/vmalloc.h b/arch/arm/mach-exynos4/include/mach/vmalloc.h
new file mode 100644
index 0000000..284330e
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/vmalloc.h
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * EXYNOS4 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H __FILE__
+
+#define VMALLOC_END	0xF6000000UL
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-exynos4/init.c b/arch/arm/mach-exynos4/init.c
new file mode 100644
index 0000000..cf91f50
--- /dev/null
+++ b/arch/arm/mach-exynos4/init.c
@@ -0,0 +1,41 @@
+/* linux/arch/arm/mach-exynos4/init.c
+ *
+ * Copyright (c) 2010 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.
+*/
+
+#include <linux/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = {
+	[0] = {
+		.name		= "uclk1",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->has_fracval = 1;
+			tcfg->clocks = exynos4_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
+		}
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}
diff --git a/arch/arm/mach-exynos4/irq-combiner.c b/arch/arm/mach-exynos4/irq-combiner.c
new file mode 100644
index 0000000..31618d9
--- /dev/null
+++ b/arch/arm/mach-exynos4/irq-combiner.c
@@ -0,0 +1,127 @@
+/* linux/arch/arm/mach-exynos4/irq-combiner.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/common/gic.c
+ *
+ * IRQ COMBINER 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 <asm/mach/irq.h>
+
+#define COMBINER_ENABLE_SET	0x0
+#define COMBINER_ENABLE_CLEAR	0x4
+#define COMBINER_INT_STATUS	0xC
+
+static DEFINE_SPINLOCK(irq_controller_lock);
+
+struct combiner_chip_data {
+	unsigned int irq_offset;
+	unsigned int irq_mask;
+	void __iomem *base;
+};
+
+static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+
+static inline void __iomem *combiner_base(struct irq_data *data)
+{
+	struct combiner_chip_data *combiner_data =
+		irq_data_get_irq_chip_data(data);
+
+	return combiner_data->base;
+}
+
+static void combiner_mask_irq(struct irq_data *data)
+{
+	u32 mask = 1 << (data->irq % 32);
+
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
+}
+
+static void combiner_unmask_irq(struct irq_data *data)
+{
+	u32 mask = 1 << (data->irq % 32);
+
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
+}
+
+static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct combiner_chip_data *chip_data = get_irq_data(irq);
+	struct irq_chip *chip = get_irq_chip(irq);
+	unsigned int cascade_irq, combiner_irq;
+	unsigned long status;
+
+	/* primary controller ack'ing */
+	chip->irq_ack(&desc->irq_data);
+
+	spin_lock(&irq_controller_lock);
+	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+	spin_unlock(&irq_controller_lock);
+	status &= chip_data->irq_mask;
+
+	if (status == 0)
+		goto out;
+
+	combiner_irq = __ffs(status);
+
+	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
+	if (unlikely(cascade_irq >= NR_IRQS))
+		do_bad_IRQ(cascade_irq, desc);
+	else
+		generic_handle_irq(cascade_irq);
+
+ out:
+	/* primary controller unmasking */
+	chip->irq_unmask(&desc->irq_data);
+}
+
+static struct irq_chip combiner_chip = {
+	.name		= "COMBINER",
+	.irq_mask	= combiner_mask_irq,
+	.irq_unmask	= combiner_unmask_irq,
+};
+
+void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+{
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+	if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0)
+		BUG();
+	set_irq_chained_handler(irq, combiner_handle_cascade_irq);
+}
+
+void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
+			  unsigned int irq_start)
+{
+	unsigned int i;
+
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+
+	combiner_data[combiner_nr].base = base;
+	combiner_data[combiner_nr].irq_offset = irq_start;
+	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
+
+	/* Disable all interrupts */
+
+	__raw_writel(combiner_data[combiner_nr].irq_mask,
+		     base + COMBINER_ENABLE_CLEAR);
+
+	/* Setup the Linux IRQ subsystem */
+
+	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
+				+ MAX_IRQ_IN_COMBINER; i++) {
+		set_irq_chip(i, &combiner_chip);
+		set_irq_chip_data(i, &combiner_data[combiner_nr]);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff --git a/arch/arm/mach-exynos4/irq-eint.c b/arch/arm/mach-exynos4/irq-eint.c
new file mode 100644
index 0000000..4f7ad4a
--- /dev/null
+++ b/arch/arm/mach-exynos4/irq-eint.c
@@ -0,0 +1,229 @@
+/* linux/arch/arm/mach-exynos4/irq-eint.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ EINT 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/gpio.h>
+
+#include <plat/pm.h>
+#include <plat/cpu.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+
+static DEFINE_SPINLOCK(eint_lock);
+
+static unsigned int eint0_15_data[16];
+
+static unsigned int exynos4_get_irq_nr(unsigned int number)
+{
+	u32 ret = 0;
+
+	switch (number) {
+	case 0 ... 3:
+		ret = (number + IRQ_EINT0);
+		break;
+	case 4 ... 7:
+		ret = (number + (IRQ_EINT4 - 4));
+		break;
+	case 8 ... 15:
+		ret = (number + (IRQ_EINT8 - 8));
+		break;
+	default:
+		printk(KERN_ERR "number available : %d\n", number);
+	}
+
+	return ret;
+}
+
+static inline void exynos4_irq_eint_mask(struct irq_data *data)
+{
+	u32 mask;
+
+	spin_lock(&eint_lock);
+	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	mask |= eint_irq_to_bit(data->irq);
+	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+}
+
+static void exynos4_irq_eint_unmask(struct irq_data *data)
+{
+	u32 mask;
+
+	spin_lock(&eint_lock);
+	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	mask &= ~(eint_irq_to_bit(data->irq));
+	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+}
+
+static inline void exynos4_irq_eint_ack(struct irq_data *data)
+{
+	__raw_writel(eint_irq_to_bit(data->irq),
+		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
+}
+
+static void exynos4_irq_eint_maskack(struct irq_data *data)
+{
+	exynos4_irq_eint_mask(data);
+	exynos4_irq_eint_ack(data);
+}
+
+static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+	int offs = EINT_OFFSET(data->irq);
+	int shift;
+	u32 ctrl, mask;
+	u32 newvalue = 0;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
+		break;
+
+	default:
+		printk(KERN_ERR "No such irq type %d", type);
+		return -EINVAL;
+	}
+
+	shift = (offs & 0x7) * 4;
+	mask = 0x7 << shift;
+
+	spin_lock(&eint_lock);
+	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
+	ctrl &= ~mask;
+	ctrl |= newvalue << shift;
+	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+
+	switch (offs) {
+	case 0 ... 7:
+		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
+		break;
+	case 8 ... 15:
+		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
+		break;
+	case 16 ... 23:
+		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
+		break;
+	case 24 ... 31:
+		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
+		break;
+	default:
+		printk(KERN_ERR "No such irq number %d", offs);
+	}
+
+	return 0;
+}
+
+static struct irq_chip exynos4_irq_eint = {
+	.name		= "exynos4-eint",
+	.irq_mask	= exynos4_irq_eint_mask,
+	.irq_unmask	= exynos4_irq_eint_unmask,
+	.irq_mask_ack	= exynos4_irq_eint_maskack,
+	.irq_ack	= exynos4_irq_eint_ack,
+	.irq_set_type	= exynos4_irq_eint_set_type,
+#ifdef CONFIG_PM
+	.irq_set_wake	= s3c_irqext_wake,
+#endif
+};
+
+/* exynos4_irq_demux_eint
+ *
+ * This function demuxes the IRQ from from EINTs 16 to 31.
+ * It is designed to be inlined into the specific handler
+ * s5p_irq_demux_eintX_Y.
+ *
+ * Each EINT pend/mask registers handle eight of them.
+ */
+static inline void exynos4_irq_demux_eint(unsigned int start)
+{
+	unsigned int irq;
+
+	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
+	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
+
+	status &= ~mask;
+	status &= 0xff;
+
+	while (status) {
+		irq = fls(status) - 1;
+		generic_handle_irq(irq + start);
+		status &= ~(1 << irq);
+	}
+}
+
+static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+{
+	exynos4_irq_demux_eint(IRQ_EINT(16));
+	exynos4_irq_demux_eint(IRQ_EINT(24));
+}
+
+static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+{
+	u32 *irq_data = get_irq_data(irq);
+	struct irq_chip *chip = get_irq_chip(irq);
+
+	chip->irq_mask(&desc->irq_data);
+
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
+
+	generic_handle_irq(*irq_data);
+
+	chip->irq_unmask(&desc->irq_data);
+}
+
+int __init exynos4_init_irq_eint(void)
+{
+	int irq;
+
+	for (irq = 0 ; irq <= 31 ; irq++) {
+		set_irq_chip(IRQ_EINT(irq), &exynos4_irq_eint);
+		set_irq_handler(IRQ_EINT(irq), handle_level_irq);
+		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
+	}
+
+	set_irq_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
+
+	for (irq = 0 ; irq <= 15 ; irq++) {
+		eint0_15_data[irq] = IRQ_EINT(irq);
+
+		set_irq_data(exynos4_get_irq_nr(irq), &eint0_15_data[irq]);
+		set_irq_chained_handler(exynos4_get_irq_nr(irq),
+					exynos4_irq_eint0_15);
+	}
+
+	return 0;
+}
+
+arch_initcall(exynos4_init_irq_eint);
diff --git a/arch/arm/mach-exynos4/localtimer.c b/arch/arm/mach-exynos4/localtimer.c
new file mode 100644
index 0000000..2a2993a
--- /dev/null
+++ b/arch/arm/mach-exynos4/localtimer.c
@@ -0,0 +1,25 @@
+/* linux/arch/arm/mach-exynos4/localtimer.c
+ *
+ * Cloned from linux/arch/arm/mach-realview/localtimer.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = IRQ_LOCALTIMER;
+	twd_timer_setup(evt);
+}
diff --git a/arch/arm/mach-exynos4/mach-armlex4210.c b/arch/arm/mach-exynos4/mach-armlex4210.c
new file mode 100644
index 0000000..b482c62
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-armlex4210.c
@@ -0,0 +1,215 @@
+/* linux/arch/arm/mach-exynos4/mach-armlex4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/smsc911x.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ARMLEX4210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define ARMLEX4210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define ARMLEX4210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg armlex4210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPX2(5),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+	.max_width		= 4,
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+	.max_width		= 4,
+};
+
+static void __init armlex4210_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&armlex4210_hsmmc0_pdata);
+	s3c_sdhci2_set_platdata(&armlex4210_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&armlex4210_hsmmc3_pdata);
+}
+
+static void __init armlex4210_wlan_init(void)
+{
+	/* enable */
+	s3c_gpio_cfgpin(EXYNOS4_GPX2(0), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX2(0), S3C_GPIO_PULL_UP);
+
+	/* reset */
+	s3c_gpio_cfgpin(EXYNOS4_GPX1(6), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX1(6), S3C_GPIO_PULL_UP);
+
+	/* wakeup */
+	s3c_gpio_cfgpin(EXYNOS4_GPX1(5), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX1(5), S3C_GPIO_PULL_UP);
+}
+
+static struct resource armlex4210_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(3),
+		.end	= EXYNOS4_PA_SROM_BANK(3) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(27),
+		.end	= IRQ_EINT(27),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device armlex4210_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(armlex4210_smsc911x_resources),
+	.resource	= armlex4210_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static struct platform_device *armlex4210_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&armlex4210_smsc911x,
+	&exynos4_device_ahci,
+};
+
+static void __init armlex4210_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(0 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__ADDRMODE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init armlex4210_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(armlex4210_uartcfgs,
+			   ARRAY_SIZE(armlex4210_uartcfgs));
+}
+
+static void __init armlex4210_machine_init(void)
+{
+	armlex4210_smsc911x_init();
+
+	armlex4210_sdhci_init();
+
+	armlex4210_wlan_init();
+
+	platform_add_devices(armlex4210_devices,
+			     ARRAY_SIZE(armlex4210_devices));
+}
+
+MACHINE_START(ARMLEX4210, "ARMLEX4210")
+	/* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= armlex4210_map_io,
+	.init_machine	= armlex4210_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
new file mode 100644
index 0000000..b79ad01
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -0,0 +1,305 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-nuri.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mmc/host.h>
+#include <linux/fb.h>
+#include <linux/pwm_backlight.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define NURI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define NURI_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define NURI_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+enum fixed_regulator_id {
+	FIXED_REG_ID_MMC = 0,
+};
+
+static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
+	{
+		.hwport		= 0,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 1,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 2,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 3,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+};
+
+/* eMMC */
+static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
+	.max_width		= 8,
+	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE | MMC_CAP_ERASE),
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply emmc_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+	REGULATOR_SUPPLY("vmmc", "dw_mmc"),
+};
+
+static struct regulator_init_data emmc_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "VMEM_VDD_2.8V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(emmc_supplies),
+	.consumer_supplies	= emmc_supplies,
+};
+
+static struct fixed_voltage_config emmc_fixed_voltage_config = {
+	.supply_name		= "MASSMEMORY_EN (inverted)",
+	.microvolts		= 2800000,
+	.gpio			= EXYNOS4_GPL1(1),
+	.enable_high		= false,
+	.init_data		= &emmc_fixed_voltage_init_data,
+};
+
+static struct platform_device emmc_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= FIXED_REG_ID_MMC,
+	.dev			= {
+		.platform_data	= &emmc_fixed_voltage_config,
+	},
+};
+
+/* SD */
+static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.ext_cd_gpio		= EXYNOS4_GPX3(3),	/* XEINT_27 */
+	.ext_cd_gpio_invert	= 1,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* WLAN */
+static struct s3c_sdhci_platdata nuri_hsmmc3_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static void __init nuri_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&nuri_hsmmc0_data);
+	s3c_sdhci2_set_platdata(&nuri_hsmmc2_data);
+	s3c_sdhci3_set_platdata(&nuri_hsmmc3_data);
+}
+
+/* GPIO KEYS */
+static struct gpio_keys_button nuri_gpio_keys_tables[] = {
+	{
+		.code			= KEY_VOLUMEUP,
+		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
+		.desc			= "gpio-keys: KEY_VOLUMEUP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_VOLUMEDOWN,
+		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
+		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_POWER,
+		.gpio			= EXYNOS4_GPX2(7),	/* XEINT23 */
+		.desc			= "gpio-keys: KEY_POWER",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data nuri_gpio_keys_data = {
+	.buttons		= nuri_gpio_keys_tables,
+	.nbuttons		= ARRAY_SIZE(nuri_gpio_keys_tables),
+};
+
+static struct platform_device nuri_gpio_keys = {
+	.name			= "gpio-keys",
+	.dev			= {
+		.platform_data	= &nuri_gpio_keys_data,
+	},
+};
+
+static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
+{
+	int gpio = EXYNOS4_GPE1(5);
+
+	gpio_request(gpio, "LVDS_nSHDN");
+	gpio_direction_output(gpio, power);
+	gpio_free(gpio);
+}
+
+static int nuri_bl_init(struct device *dev)
+{
+	int ret, gpio = EXYNOS4_GPE2(3);
+
+	ret = gpio_request(gpio, "LCD_LDO_EN");
+	if (!ret)
+		gpio_direction_output(gpio, 0);
+
+	return ret;
+}
+
+static int nuri_bl_notify(struct device *dev, int brightness)
+{
+	if (brightness < 1)
+		brightness = 0;
+
+	gpio_set_value(EXYNOS4_GPE2(3), 1);
+
+	return brightness;
+}
+
+static void nuri_bl_exit(struct device *dev)
+{
+	gpio_free(EXYNOS4_GPE2(3));
+}
+
+/* nuri pwm backlight */
+static struct platform_pwm_backlight_data nuri_backlight_data = {
+	.pwm_id			= 0,
+	.pwm_period_ns		= 30000,
+	.max_brightness		= 100,
+	.dft_brightness		= 50,
+	.init			= nuri_bl_init,
+	.notify			= nuri_bl_notify,
+	.exit			= nuri_bl_exit,
+};
+
+static struct platform_device nuri_backlight_device = {
+	.name			= "pwm-backlight",
+	.id			= -1,
+	.dev			= {
+		.parent		= &s3c_device_timer[0].dev,
+		.platform_data	= &nuri_backlight_data,
+	},
+};
+
+static struct plat_lcd_data nuri_lcd_platform_data = {
+	.set_power		= nuri_lcd_power_on,
+};
+
+static struct platform_device nuri_lcd_device = {
+	.name			= "platform-lcd",
+	.id			= -1,
+	.dev			= {
+		.platform_data	= &nuri_lcd_platform_data,
+	},
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+/* GPIO I2C 5 (PMIC) */
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	/* max8997, To be updated */
+};
+
+static struct platform_device *nuri_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&emmc_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_wdt,
+	&s3c_device_timer[0],
+
+	/* NURI Devices */
+	&nuri_gpio_keys,
+	&nuri_lcd_device,
+	&nuri_backlight_device,
+};
+
+static void __init nuri_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
+}
+
+static void __init nuri_machine_init(void)
+{
+	nuri_sdhci_init();
+
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+
+	/* Last */
+	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+}
+
+MACHINE_START(NURI, "NURI")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= nuri_map_io,
+	.init_machine	= nuri_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkc210.c b/arch/arm/mach-exynos4/mach-smdkc210.c
new file mode 100644
index 0000000..25a2568
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-smdkc210.c
@@ -0,0 +1,223 @@
+/* linux/arch/arm/mach-exynos4/mach-smdkc210.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDKC210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDKC210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct resource smdkc210_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(1),
+		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(5),
+		.end	= IRQ_EINT(5),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device smdkc210_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smdkc210_smsc911x_resources),
+	.resource	= smdkc210_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{I2C_BOARD_INFO("wm8994", 0x1a),},
+};
+
+static struct platform_device *smdkc210_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c1,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_ac97,
+	&exynos4_device_i2s0,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&smdkc210_smsc911x,
+};
+
+static void __init smdkc210_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init smdkc210_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
+}
+
+static void __init smdkc210_machine_init(void)
+{
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	smdkc210_smsc911x_init();
+
+	s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
+	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
+
+	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
+}
+
+MACHINE_START(SMDKC210, "SMDKC210")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkc210_map_io,
+	.init_machine	= smdkc210_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-exynos4/mach-smdkv310.c
new file mode 100644
index 0000000..88e0275
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-smdkv310.c
@@ -0,0 +1,248 @@
+/* linux/arch/arm/mach-exynos4/mach-smdkv310.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/keypad.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct resource smdkv310_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(1),
+		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(5),
+		.end	= IRQ_EINT(5),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device smdkv310_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smdkv310_smsc911x_resources),
+	.resource	= smdkv310_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static uint32_t smdkv310_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
+	KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
+	KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
+	KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
+};
+
+static struct matrix_keymap_data smdkv310_keymap_data __initdata = {
+	.keymap		= smdkv310_keymap,
+	.keymap_size	= ARRAY_SIZE(smdkv310_keymap),
+};
+
+static struct samsung_keypad_platdata smdkv310_keypad_data __initdata = {
+	.keymap_data	= &smdkv310_keymap_data,
+	.rows		= 2,
+	.cols		= 8,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{I2C_BOARD_INFO("wm8994", 0x1a),},
+};
+
+static struct platform_device *smdkv310_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c1,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_ac97,
+	&exynos4_device_i2s0,
+	&samsung_device_keypad,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&smdkv310_smsc911x,
+};
+
+static void __init smdkv310_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init smdkv310_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
+}
+
+static void __init smdkv310_machine_init(void)
+{
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	smdkv310_smsc911x_init();
+
+	s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
+	s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
+
+	samsung_keypad_set_platdata(&smdkv310_keypad_data);
+
+	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
+}
+
+MACHINE_START(SMDKV310, "SMDKV310")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mach-universal_c210.c b/arch/arm/mach-exynos4/mach-universal_c210.c
new file mode 100644
index 0000000..97d329f
--- /dev/null
+++ b/arch/arm/mach-exynos4/mach-universal_c210.c
@@ -0,0 +1,650 @@
+/* linux/arch/arm/mach-exynos4/mach-universal_c210.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/mfd/max8998.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/max8952.h>
+#include <linux/mmc/host.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/iic.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+};
+
+static struct regulator_consumer_supply max8952_consumer =
+	REGULATOR_SUPPLY("vddarm", NULL);
+
+static struct max8952_platform_data universal_max8952_pdata __initdata = {
+	.gpio_vid0	= EXYNOS4_GPX0(3),
+	.gpio_vid1	= EXYNOS4_GPX0(4),
+	.gpio_en	= -1, /* Not controllable, set "Always High" */
+	.default_mode	= 0, /* vid0 = 0, vid1 = 0 */
+	.dvs_mode	= { 48, 32, 28, 18 }, /* 1.25, 1.20, 1.05, 0.95V */
+	.sync_freq	= 0, /* default: fastest */
+	.ramp_speed	= 0, /* default: fastest */
+
+	.reg_data	= {
+		.constraints	= {
+			.name		= "VARM_1.2V",
+			.min_uV		= 770000,
+			.max_uV		= 1400000,
+			.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+			.always_on	= 1,
+			.boot_on	= 1,
+		},
+		.num_consumer_supplies	= 1,
+		.consumer_supplies	= &max8952_consumer,
+	},
+};
+
+static struct regulator_consumer_supply lp3974_buck1_consumer =
+	REGULATOR_SUPPLY("vddint", NULL);
+
+static struct regulator_consumer_supply lp3974_buck2_consumer =
+	REGULATOR_SUPPLY("vddg3d", NULL);
+
+static struct regulator_init_data lp3974_buck1_data = {
+	.constraints	= {
+		.name		= "VINT_1.1V",
+		.min_uV		= 750000,
+		.max_uV		= 1500000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck1_consumer,
+};
+
+static struct regulator_init_data lp3974_buck2_data = {
+	.constraints	= {
+		.name		= "VG3D_1.1V",
+		.min_uV		= 750000,
+		.max_uV		= 1500000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck2_consumer,
+};
+
+static struct regulator_init_data lp3974_buck3_data = {
+	.constraints	= {
+		.name		= "VCC_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_buck4_data = {
+	.constraints	= {
+		.name		= "VMEM_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo2_data = {
+	.constraints	= {
+		.name		= "VALIVE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo3_data = {
+	.constraints	= {
+		.name		= "VUSB+MIPI_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo4_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo5_data = {
+	.constraints	= {
+		.name		= "VTF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo6_data = {
+	.constraints	= {
+		.name		= "LDO6",
+		.min_uV		= 2000000,
+		.max_uV		= 2000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo7_data = {
+	.constraints	= {
+		.name		= "VLCD+VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo8_data = {
+	.constraints	= {
+		.name		= "VUSB+VDAC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo9_data = {
+	.constraints	= {
+		.name		= "VCC_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo10_data = {
+	.constraints	= {
+		.name		= "VPLL_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.boot_on	= 1,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo11_data = {
+	.constraints	= {
+		.name		= "CAM_AF_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo12_data = {
+	.constraints	= {
+		.name		= "PS_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo13_data = {
+	.constraints	= {
+		.name		= "VHIC_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo14_data = {
+	.constraints	= {
+		.name		= "CAM_I_HOST_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo15_data = {
+	.constraints	= {
+		.name		= "CAM_S_DIG+FM33_CORE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo16_data = {
+	.constraints	= {
+		.name		= "CAM_S_ANA_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo17_data = {
+	.constraints	= {
+		.name		= "VCC_3.0V_LCD",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_32khz_ap_data = {
+	.constraints	= {
+		.name		= "32KHz AP",
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_32khz_cp_data = {
+	.constraints	= {
+		.name		= "32KHz CP",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_vichg_data = {
+	.constraints	= {
+		.name		= "VICHG",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_esafeout1_data = {
+	.constraints	= {
+		.name		= "SAFEOUT1",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_esafeout2_data = {
+	.constraints	= {
+		.name		= "SAFEOUT2",
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct max8998_regulator_data lp3974_regulators[] = {
+	{ MAX8998_LDO2,  &lp3974_ldo2_data },
+	{ MAX8998_LDO3,  &lp3974_ldo3_data },
+	{ MAX8998_LDO4,  &lp3974_ldo4_data },
+	{ MAX8998_LDO5,  &lp3974_ldo5_data },
+	{ MAX8998_LDO6,  &lp3974_ldo6_data },
+	{ MAX8998_LDO7,  &lp3974_ldo7_data },
+	{ MAX8998_LDO8,  &lp3974_ldo8_data },
+	{ MAX8998_LDO9,  &lp3974_ldo9_data },
+	{ MAX8998_LDO10, &lp3974_ldo10_data },
+	{ MAX8998_LDO11, &lp3974_ldo11_data },
+	{ MAX8998_LDO12, &lp3974_ldo12_data },
+	{ MAX8998_LDO13, &lp3974_ldo13_data },
+	{ MAX8998_LDO14, &lp3974_ldo14_data },
+	{ MAX8998_LDO15, &lp3974_ldo15_data },
+	{ MAX8998_LDO16, &lp3974_ldo16_data },
+	{ MAX8998_LDO17, &lp3974_ldo17_data },
+	{ MAX8998_BUCK1, &lp3974_buck1_data },
+	{ MAX8998_BUCK2, &lp3974_buck2_data },
+	{ MAX8998_BUCK3, &lp3974_buck3_data },
+	{ MAX8998_BUCK4, &lp3974_buck4_data },
+	{ MAX8998_EN32KHZ_AP, &lp3974_32khz_ap_data },
+	{ MAX8998_EN32KHZ_CP, &lp3974_32khz_cp_data },
+	{ MAX8998_ENVICHG, &lp3974_vichg_data },
+	{ MAX8998_ESAFEOUT1, &lp3974_esafeout1_data },
+	{ MAX8998_ESAFEOUT2, &lp3974_esafeout2_data },
+};
+
+static struct max8998_platform_data universal_lp3974_pdata = {
+	.num_regulators		= ARRAY_SIZE(lp3974_regulators),
+	.regulators		= lp3974_regulators,
+	.buck1_voltage1		= 1100000,	/* INT */
+	.buck1_voltage2		= 1000000,
+	.buck1_voltage3		= 1100000,
+	.buck1_voltage4		= 1000000,
+	.buck1_set1		= EXYNOS4_GPX0(5),
+	.buck1_set2		= EXYNOS4_GPX0(6),
+	.buck2_voltage1		= 1200000,	/* G3D */
+	.buck2_voltage2		= 1100000,
+	.buck1_default_idx	= 0,
+	.buck2_set3		= EXYNOS4_GPE2(0),
+	.buck2_default_idx	= 0,
+	.wakeup			= true,
+};
+
+/* GPIO I2C 5 (PMIC) */
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8952", 0xC0 >> 1),
+		.platform_data	= &universal_max8952_pdata,
+	}, {
+		I2C_BOARD_INFO("lp3974", 0xCC >> 1),
+		.platform_data	= &universal_lp3974_pdata,
+	},
+};
+
+/* GPIO KEYS */
+static struct gpio_keys_button universal_gpio_keys_tables[] = {
+	{
+		.code			= KEY_VOLUMEUP,
+		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
+		.desc			= "gpio-keys: KEY_VOLUMEUP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_VOLUMEDOWN,
+		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
+		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_CONFIG,
+		.gpio			= EXYNOS4_GPX2(2),	/* XEINT18 */
+		.desc			= "gpio-keys: KEY_CONFIG",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_CAMERA,
+		.gpio			= EXYNOS4_GPX2(3),	/* XEINT19 */
+		.desc			= "gpio-keys: KEY_CAMERA",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_OK,
+		.gpio			= EXYNOS4_GPX3(5),	/* XEINT29 */
+		.desc			= "gpio-keys: KEY_OK",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data universal_gpio_keys_data = {
+	.buttons	= universal_gpio_keys_tables,
+	.nbuttons	= ARRAY_SIZE(universal_gpio_keys_tables),
+};
+
+static struct platform_device universal_gpio_keys = {
+	.name			= "gpio-keys",
+	.dev			= {
+		.platform_data	= &universal_gpio_keys_data,
+	},
+};
+
+/* eMMC */
+static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
+	.max_width		= 8,
+	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE),
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply mmc0_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+};
+
+static struct regulator_init_data mmc0_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "VMEM_VDD_2.8V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(mmc0_supplies),
+	.consumer_supplies	= mmc0_supplies,
+};
+
+static struct fixed_voltage_config mmc0_fixed_voltage_config = {
+	.supply_name		= "MASSMEMORY_EN",
+	.microvolts		= 2800000,
+	.gpio			= EXYNOS4_GPE1(3),
+	.enable_high		= true,
+	.init_data		= &mmc0_fixed_voltage_init_data,
+};
+
+static struct platform_device mmc0_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= 0,
+	.dev			= {
+		.platform_data	= &mmc0_fixed_voltage_config,
+	},
+};
+
+/* SD */
+static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.ext_cd_gpio		= EXYNOS4_GPX3(4),      /* XEINT_28 */
+	.ext_cd_gpio_invert	= 1,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* WiFi */
+static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
+};
+
+static void __init universal_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&universal_hsmmc0_data);
+	s3c_sdhci2_set_platdata(&universal_hsmmc2_data);
+	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
+}
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+	/* Camera, To be updated */
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+static struct platform_device *universal_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&mmc0_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c5,
+
+	/* Universal Devices */
+	&universal_gpio_keys,
+	&s5p_device_onenand,
+};
+
+static void __init universal_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
+}
+
+static void __init universal_machine_init(void)
+{
+	universal_sdhci_init();
+
+	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
+	s3c_i2c5_set_platdata(NULL);
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+
+	/* Last */
+	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+}
+
+MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= universal_map_io,
+	.init_machine	= universal_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff --git a/arch/arm/mach-exynos4/mct.c b/arch/arm/mach-exynos4/mct.c
new file mode 100644
index 0000000..af82a8f
--- /dev/null
+++ b/arch/arm/mach-exynos4/mct.c
@@ -0,0 +1,421 @@
+/* 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 <mach/map.h>
+#include <mach/regs-mct.h>
+#include <asm/mach/time.h>
+
+static unsigned long clk_cnt_per_tick;
+static unsigned long clk_rate;
+
+struct mct_clock_event_device {
+	struct clock_event_device *evt;
+	void __iomem *base;
+};
+
+struct mct_clock_event_device mct_tick[2];
+
+static void exynos4_mct_write(unsigned int value, void *addr)
+{
+	void __iomem *stat_addr;
+	u32 mask;
+	u32 i;
+
+	__raw_writel(value, addr);
+
+	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 write 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;
+	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
+		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 3;		/* L0_TCON write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
+		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 3;		/* L1_TCON write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 0;		/* L0_TCNTB write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 0;		/* L1_TCNTB write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 1;		/* L0_ICNTB write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 1;		/* L1_ICNTB 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;
+}
+
+struct clocksource mct_frc = {
+	.name		= "mct-frc",
+	.rating		= 400,
+	.read		= exynos4_frc_read,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+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)
+{
+	exynos4_mct_comp0_stop();
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_mct_comp0_start(mode, clk_cnt_per_tick);
+		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)
+{
+	clk_cnt_per_tick = clk_rate / 2	/ HZ;
+
+	clockevents_calc_mult_shift(&mct_comp_device, clk_rate / 2, 5);
+	mct_comp_device.max_delta_ns =
+		clockevent_delta2ns(0xffffffff, &mct_comp_device);
+	mct_comp_device.min_delta_ns =
+		clockevent_delta2ns(0xf, &mct_comp_device);
+	mct_comp_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&mct_comp_device);
+
+	setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+/* 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 interupt */
+	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 = &mct_tick[smp_processor_id()];
+
+	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 = &mct_tick[smp_processor_id()];
+
+	exynos4_mct_tick_stop(mevt);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+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;
+
+	/*
+	 * 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 */
+	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+
+	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 void exynos4_mct_tick_init(struct clock_event_device *evt)
+{
+	unsigned int cpu = smp_processor_id();
+
+	mct_tick[cpu].evt = evt;
+
+	if (cpu == 0) {
+		mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
+		evt->name = "mct_tick0";
+	} else {
+		mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
+		evt->name = "mct_tick1";
+	}
+
+	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_calc_mult_shift(evt, clk_rate / 2, 5);
+	evt->max_delta_ns =
+		clockevent_delta2ns(0x7fffffff, evt);
+	evt->min_delta_ns =
+		clockevent_delta2ns(0xf, evt);
+
+	clockevents_register_device(evt);
+
+	exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
+
+	if (cpu == 0) {
+		mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+	} else {
+		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+		irq_set_affinity(IRQ_MCT1, cpumask_of(1));
+		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+	}
+}
+
+/* Setup the local clock events for a CPU */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	exynos4_mct_tick_init(evt);
+}
+
+int local_timer_ack(void)
+{
+	return 0;
+}
+
+#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);
+}
+
+static void __init exynos4_timer_init(void)
+{
+	exynos4_timer_resources();
+	exynos4_clocksource_init();
+	exynos4_clockevent_init();
+}
+
+struct sys_timer exynos4_timer = {
+	.init		= exynos4_timer_init,
+};
diff --git a/arch/arm/mach-exynos4/platsmp.c b/arch/arm/mach-exynos4/platsmp.c
new file mode 100644
index 0000000..6d35878
--- /dev/null
+++ b/arch/arm/mach-exynos4/platsmp.c
@@ -0,0 +1,172 @@
+/* linux/arch/arm/mach-exynos4/platsmp.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.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/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-clock.h>
+
+extern void exynos4_secondary_startup(void);
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+
+volatile int __cpuinitdata pen_release = -1;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static void __iomem *scu_base_addr(void)
+{
+	return (void __iomem *)(S5P_VA_SCU);
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_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
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __cpuinit 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.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	smp_cross_call(cpumask_of(cpu), 1);
+
+	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.
+ */
+
+void __init smp_init_cpus(void)
+{
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
+
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+	/* sanity check */
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "EXYNOS4: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * Initialise the present map, which describes the set of CPUs
+	 * actually populated at the present time.
+	 */
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	scu_enable(scu_base_addr());
+
+	/*
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The boot monitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
+	 */
+	__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), S5P_VA_SYSRAM);
+}
diff --git a/arch/arm/mach-exynos4/pm.c b/arch/arm/mach-exynos4/pm.c
new file mode 100644
index 0000000..10d917d
--- /dev/null
+++ b/arch/arm/mach-exynos4/pm.c
@@ -0,0 +1,420 @@
+/* linux/arch/arm/mach-exynos4/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 - Power Management support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+#include <mach/pm-core.h>
+
+static struct sleep_save exynos4_sleep[] = {
+	{ .reg = S5P_ARM_CORE0_LOWPWR			, .val = 0x2, },
+	{ .reg = S5P_DIS_IRQ_CORE0			, .val = 0x0, },
+	{ .reg = S5P_DIS_IRQ_CENTRAL0			, .val = 0x0, },
+	{ .reg = S5P_ARM_CORE1_LOWPWR			, .val = 0x2, },
+	{ .reg = S5P_DIS_IRQ_CORE1			, .val = 0x0, },
+	{ .reg = S5P_DIS_IRQ_CENTRAL1			, .val = 0x0, },
+	{ .reg = S5P_ARM_COMMON_LOWPWR			, .val = 0x2, },
+	{ .reg = S5P_L2_0_LOWPWR			, .val = 0x3, },
+	{ .reg = S5P_L2_1_LOWPWR			, .val = 0x3, },
+	{ .reg = S5P_CMU_ACLKSTOP_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_SCLKSTOP_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_APLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_MPLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_VPLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_EPLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_TV_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_CAM_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_TV_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_MFC_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_G3D_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_LCD0_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_LCD1_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_MAUDIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_GPS_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_TOP_BUS_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_TOP_RETENTION_LOWPWR		, .val = 0x1, },
+	{ .reg = S5P_TOP_PWR_LOWPWR			, .val = 0x3, },
+	{ .reg = S5P_LOGIC_RESET_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_ONENAND_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_MODIMIF_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_G2D_ACP_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_USBOTG_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_HSMMC_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_CSSYS_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_SECSS_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_PCIE_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_SATA_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_DRAM_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_GPIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_UART_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_MMCA_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_MMCB_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_EBIA_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_EBIB_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_XUSBXTI_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_XXTI_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_EXT_REGULATOR_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_GPIO_MODE_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CAM_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_TV_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_MFC_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_G3D_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_LCD0_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_LCD1_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_MAUDIO_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_GPS_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_GPS_ALIVE_LOWPWR			, .val = 0x0, },
+};
+
+static struct sleep_save exynos4_set_clksrc[] = {
+	{ .reg = S5P_CLKSRC_MASK_TOP			, .val = 0x00000001, },
+	{ .reg = S5P_CLKSRC_MASK_CAM			, .val = 0x11111111, },
+	{ .reg = S5P_CLKSRC_MASK_TV			, .val = 0x00000111, },
+	{ .reg = S5P_CLKSRC_MASK_LCD0			, .val = 0x00001111, },
+	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
+	{ .reg = S5P_CLKSRC_MASK_MAUDIO			, .val = 0x00000001, },
+	{ .reg = S5P_CLKSRC_MASK_FSYS			, .val = 0x01011111, },
+	{ .reg = S5P_CLKSRC_MASK_PERIL0			, .val = 0x01111111, },
+	{ .reg = S5P_CLKSRC_MASK_PERIL1			, .val = 0x01110111, },
+	{ .reg = S5P_CLKSRC_MASK_DMC			, .val = 0x00010000, },
+};
+
+static struct sleep_save exynos4_core_save[] = {
+	/* CMU side */
+	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
+	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
+	SAVE_ITEM(S5P_EPLL_CON0),
+	SAVE_ITEM(S5P_EPLL_CON1),
+	SAVE_ITEM(S5P_VPLL_CON0),
+	SAVE_ITEM(S5P_VPLL_CON1),
+	SAVE_ITEM(S5P_CLKSRC_TOP0),
+	SAVE_ITEM(S5P_CLKSRC_TOP1),
+	SAVE_ITEM(S5P_CLKSRC_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MFC),
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKSRC_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_CAM),
+	SAVE_ITEM(S5P_CLKDIV_TV),
+	SAVE_ITEM(S5P_CLKDIV_MFC),
+	SAVE_ITEM(S5P_CLKDIV_G3D),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_LCD0),
+	SAVE_ITEM(S5P_CLKDIV_LCD1),
+	SAVE_ITEM(S5P_CLKDIV_MAUDIO),
+	SAVE_ITEM(S5P_CLKDIV_FSYS0),
+	SAVE_ITEM(S5P_CLKDIV_FSYS1),
+	SAVE_ITEM(S5P_CLKDIV_FSYS2),
+	SAVE_ITEM(S5P_CLKDIV_FSYS3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL0),
+	SAVE_ITEM(S5P_CLKDIV_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_PERIL2),
+	SAVE_ITEM(S5P_CLKDIV_PERIL3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL4),
+	SAVE_ITEM(S5P_CLKDIV_PERIL5),
+	SAVE_ITEM(S5P_CLKDIV_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_TV),
+	SAVE_ITEM(S5P_CLKGATE_IP_MFC),
+	SAVE_ITEM(S5P_CLKGATE_IP_G3D),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR),
+	SAVE_ITEM(S5P_CLKGATE_BLOCK),
+	SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
+	SAVE_ITEM(S5P_CLKSRC_DMC),
+	SAVE_ITEM(S5P_CLKDIV_DMC0),
+	SAVE_ITEM(S5P_CLKDIV_DMC1),
+	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
+	SAVE_ITEM(S5P_CLKSRC_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+	/* GIC side */
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
+
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
+
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
+
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+};
+
+static struct sleep_save exynos4_l2cc_save[] = {
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
+};
+
+void exynos4_cpu_suspend(void)
+{
+	unsigned long tmp;
+	unsigned long mask = 0xFFFFFFFF;
+
+	/* Setting Central Sequence Register for power down mode */
+
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
+	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+	/* Setting Central Sequence option Register */
+
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+	tmp &= ~(S5P_USE_MASK);
+	tmp |= S5P_USE_STANDBY_WFI0;
+	__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+
+	/* Clear all interrupt pending to avoid early wakeup */
+
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
+
+	/* Disable all interrupt */
+
+	__raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
+	__raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
+
+	outer_flush_all();
+
+	/* issue the standby signal into the pm unit. */
+	cpu_do_idle();
+
+	/* we should never get past here */
+	panic("sleep resumed to originator?");
+}
+
+static void exynos4_pm_prepare(void)
+{
+	u32 tmp;
+
+	s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+	s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+
+	tmp = __raw_readl(S5P_INFORM1);
+
+	/* Set value of power down register for sleep mode */
+
+	s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep));
+	__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+
+	/* ensure at least INFORM0 has the resume address */
+
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+
+	/* Before enter central sequence mode, clock src register have to set */
+
+	s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
+
+}
+
+static int exynos4_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = exynos4_pm_prepare;
+	pm_cpu_sleep = exynos4_cpu_suspend;
+
+	return 0;
+}
+
+/* This function copy from linux/arch/arm/kernel/smp_scu.c */
+
+void exynos4_scu_enable(void __iomem *scu_base)
+{
+	u32 scu_ctrl;
+
+	scu_ctrl = __raw_readl(scu_base);
+	/* already enabled? */
+	if (scu_ctrl & 1)
+		return;
+
+	scu_ctrl |= 1;
+	__raw_writel(scu_ctrl, scu_base);
+
+	/*
+	 * Ensure that the data accessed by CPU0 before the SCU was
+	 * initialised is visible to the other CPUs.
+	 */
+	flush_cache_all();
+}
+
+static int exynos4_pm_resume(struct sys_device *dev)
+{
+	/* For release retention */
+
+	__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+
+	s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+
+	exynos4_scu_enable(S5P_VA_SCU);
+
+#ifdef CONFIG_CACHE_L2X0
+	s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+	outer_inv_all();
+	/* enable L2X0*/
+	writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
+#endif
+
+	return 0;
+}
+
+static struct sysdev_driver exynos4_pm_driver = {
+	.add		= exynos4_pm_add,
+	.resume		= exynos4_pm_resume,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+	unsigned int tmp;
+
+	s3c_pm_init();
+
+	/* All wakeup disable */
+
+	tmp = __raw_readl(S5P_WAKEUP_MASK);
+	tmp |= ((0xFF << 8) | (0x1F << 1));
+	__raw_writel(tmp, S5P_WAKEUP_MASK);
+
+	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
diff --git a/arch/arm/mach-exynos4/setup-fimc.c b/arch/arm/mach-exynos4/setup-fimc.c
new file mode 100644
index 0000000..6a45078
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-fimc.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * Exynos4 camera interface GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <plat/camport.h>
+
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id)
+{
+	u32 gpio8, gpio5;
+	u32 sfn;
+	int ret;
+
+	switch (id) {
+	case S5P_CAMPORT_A:
+		gpio8 = EXYNOS4_GPJ0(0); /* PCLK, VSYNC, HREF, DATA[0:4] */
+		gpio5 = EXYNOS4_GPJ1(0); /* DATA[5:7], CLKOUT, FIELD */
+		sfn = S3C_GPIO_SFN(2);
+		break;
+
+	case S5P_CAMPORT_B:
+		gpio8 = EXYNOS4_GPE0(0); /* DATA[0:7] */
+		gpio5 = EXYNOS4_GPE1(0); /* PCLK, VSYNC, HREF, CLKOUT, FIELD */
+		sfn = S3C_GPIO_SFN(3);
+		break;
+
+	default:
+		WARN(1, "Wrong camport id: %d\n", id);
+		return -EINVAL;
+	}
+
+	ret = s3c_gpio_cfgall_range(gpio8, 8, sfn, S3C_GPIO_PULL_UP);
+	if (ret)
+		return ret;
+
+	return s3c_gpio_cfgall_range(gpio5, 5, sfn, S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c0.c b/arch/arm/mach-exynos4/setup-i2c0.c
new file mode 100644
index 0000000..d395bd1
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c0.c
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c0.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * I2C0 GPIO configuration.
+ *
+ * Based on plat-s3c64xx/setup-i2c0.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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD1(0), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c1.c b/arch/arm/mach-exynos4/setup-i2c1.c
new file mode 100644
index 0000000..fd7235a
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c1.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c1.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C1 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD1(2), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c2.c b/arch/arm/mach-exynos4/setup-i2c2.c
new file mode 100644
index 0000000..2694b19
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c2.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c2.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C2 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c2_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPA0(6), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c3.c b/arch/arm/mach-exynos4/setup-i2c3.c
new file mode 100644
index 0000000..379bd30
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c3.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c3.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C3 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c3_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPA1(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c4.c b/arch/arm/mach-exynos4/setup-i2c4.c
new file mode 100644
index 0000000..9f3c048
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c4.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c4.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C4 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c4_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c5.c b/arch/arm/mach-exynos4/setup-i2c5.c
new file mode 100644
index 0000000..77e1a1e
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c5.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c5.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C5 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c5_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c6.c b/arch/arm/mach-exynos4/setup-i2c6.c
new file mode 100644
index 0000000..284d12b
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c6.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c6.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C6 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c6_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
+			      S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-i2c7.c b/arch/arm/mach-exynos4/setup-i2c7.c
new file mode 100644
index 0000000..b7611ee
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-i2c7.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c7.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C7 GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c7_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD0(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-exynos4/setup-keypad.c b/arch/arm/mach-exynos4/setup-keypad.c
new file mode 100644
index 0000000..1ee0ebf
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-keypad.c
@@ -0,0 +1,35 @@
+/* linux/arch/arm/mach-exynos4/setup-keypad.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * GPIO configuration for Exynos4 KeyPad device
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+
+void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
+{
+	/* Keypads can be of various combinations, Just making sure */
+
+	if (rows > 8) {
+		/* Set all the necessary GPX2 pins: KP_ROW[0~7] */
+		s3c_gpio_cfgrange_nopull(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3));
+
+		/* Set all the necessary GPX3 pins: KP_ROW[8~] */
+		s3c_gpio_cfgrange_nopull(EXYNOS4_GPX3(0), (rows - 8),
+					 S3C_GPIO_SFN(3));
+	} else {
+		/* Set all the necessary GPX2 pins: KP_ROW[x] */
+		s3c_gpio_cfgrange_nopull(EXYNOS4_GPX2(0), rows,
+					 S3C_GPIO_SFN(3));
+	}
+
+	/* Set all the necessary GPX1 pins to special-function 3: KP_COL[x] */
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPX1(0), cols, S3C_GPIO_SFN(3));
+}
diff --git a/arch/arm/mach-exynos4/setup-sdhci-gpio.c b/arch/arm/mach-exynos4/setup-sdhci-gpio.c
new file mode 100644
index 0000000..1b3d3a2d
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-sdhci-gpio.c
@@ -0,0 +1,152 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci-gpio.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
+
+void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK0[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	switch (width) {
+	case 8:
+		for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+			/* Data pin GPK1[3:6] to special-funtion 3 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	case 4:
+		for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6); gpio++) {
+			/* Data pin GPK0[3:6] to special-funtion 2 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	default:
+		break;
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK0(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK0(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK1[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK1(0); gpio < EXYNOS4_GPK1(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+		/* Data pin GPK1[3:6] to special-function 2 */
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK1(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK1(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK2[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK2(0); gpio < EXYNOS4_GPK2(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	switch (width) {
+	case 8:
+		for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
+			/* Data pin GPK3[3:6] to special-function 3 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	case 4:
+		for (gpio = EXYNOS4_GPK2(3); gpio <= EXYNOS4_GPK2(6); gpio++) {
+			/* Data pin GPK2[3:6] to special-function 2 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	default:
+		break;
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK2(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK2(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK3[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK3(0); gpio < EXYNOS4_GPK3(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
+		/* Data pin GPK3[3:6] to special-function 2 */
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK3(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK3(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
diff --git a/arch/arm/mach-exynos4/setup-sdhci.c b/arch/arm/mach-exynos4/setup-sdhci.c
new file mode 100644
index 0000000..85f9433
--- /dev/null
+++ b/arch/arm/mach-exynos4/setup-sdhci.c
@@ -0,0 +1,69 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Helper functions for settign up SDHCI device(s) (HSMMC)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+
+#include <plat/regs-sdhci.h>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *exynos4_hsmmc_clksrcs[4] = {
+	[0] = NULL,
+	[1] = NULL,
+	[2] = "sclk_mmc",	/* mmc_bus */
+	[3] = NULL,
+};
+
+void exynos4_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
+				  struct mmc_ios *ios, struct mmc_card *card)
+{
+	u32 ctrl2, ctrl3;
+
+	/* don't need to alter anything acording to card-type */
+
+	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
+
+	/* select base clock source to HCLK */
+
+	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+
+	/*
+	 * clear async mode, enable conflict mask, rx feedback ctrl, SD
+	 * clk hold and no use debounce count
+	 */
+
+	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+		  S3C_SDHCI_CTRL2_ENFBCLKRX |
+		  S3C_SDHCI_CTRL2_DFCNT_NONE |
+		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+
+	/* Tx and Rx feedback clock delay control */
+
+	if (ios->clock < 25 * 1000000)
+		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
+			 S3C_SDHCI_CTRL3_FCSEL2 |
+			 S3C_SDHCI_CTRL3_FCSEL1 |
+			 S3C_SDHCI_CTRL3_FCSEL0);
+	else
+		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
+
+	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
+	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
+}
diff --git a/arch/arm/mach-exynos4/sleep.S b/arch/arm/mach-exynos4/sleep.S
new file mode 100644
index 0000000..6b62425
--- /dev/null
+++ b/arch/arm/mach-exynos4/sleep.S
@@ -0,0 +1,76 @@
+/* linux/arch/arm/mach-exynos4/sleep.S
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 power Manager (Suspend-To-RAM) support
+ * Based on S3C2410 sleep code by:
+ *	Ben Dooks, (c) 2004 Simtec Electronics
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/memory.h>
+
+	.text
+
+	/*
+	 * s3c_cpu_save
+	 *
+	 * entry:
+	 *	r1 = v:p offset
+	 */
+
+ENTRY(s3c_cpu_save)
+
+	stmfd	sp!, { r3 - r12, lr }
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
+
+	ldr	r0, =pm_cpu_sleep
+	ldr	r0, [ r0 ]
+	mov	pc, r0
+
+resume_with_mmu:
+	ldmfd	sp!, { r3 - r12, pc }
+
+	.ltorg
+
+	/*
+	 * sleep magic, to allow the bootloader to check for an valid
+	 * image to resume to. Must be the first word before the
+	 * s3c_cpu_resume entry.
+	 */
+
+	.word	0x2bedf00d
+
+	/*
+	 * s3c_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 *
+	 * we must put this code here in the data segment as we have no
+	 * other way of restoring the stack pointer after sleep, and we
+	 * must not write to the code segment (code is read-only)
+	 */
+
+ENTRY(s3c_cpu_resume)
+	b	cpu_resume
diff --git a/arch/arm/mach-exynos4/time.c b/arch/arm/mach-exynos4/time.c
new file mode 100644
index 0000000..86b9fa0
--- /dev/null
+++ b/arch/arm/mach-exynos4/time.c
@@ -0,0 +1,299 @@
+/* linux/arch/arm/mach-exynos4/time.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 (and compatible) HRT support
+ * PWM 2/4 is used for this feature
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+
+#include <mach/map.h>
+#include <plat/regs-timer.h>
+#include <asm/mach/time.h>
+
+static unsigned long clock_count_per_tick;
+
+static struct clk *tin2;
+static struct clk *tin4;
+static struct clk *tdiv2;
+static struct clk *tdiv4;
+static struct clk *timerclk;
+
+static void exynos4_pwm_stop(unsigned int pwm_id)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (pwm_id) {
+	case 2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+	case 4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+	default:
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void exynos4_pwm_init(unsigned int pwm_id, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	/* timers reload after counting zero, so reduce the count by 1 */
+	tcnt--;
+
+	/* ensure timer is stopped... */
+	switch (pwm_id) {
+	case 2:
+		tcon &= ~(0xf<<12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+
+		__raw_writel(tcnt, S3C2410_TCNTB(2));
+		__raw_writel(tcnt, S3C2410_TCMPB(2));
+		__raw_writel(tcon, S3C2410_TCON);
+
+		break;
+	case 4:
+		tcon &= ~(7<<20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+
+		__raw_writel(tcnt, S3C2410_TCNTB(4));
+		__raw_writel(tcnt, S3C2410_TCMPB(4));
+		__raw_writel(tcon, S3C2410_TCON);
+
+		break;
+	default:
+		break;
+	}
+}
+
+static inline void exynos4_pwm_start(unsigned int pwm_id, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (pwm_id) {
+	case 2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+	case 4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+	default:
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int exynos4_pwm_set_next_event(unsigned long cycles,
+					struct clock_event_device *evt)
+{
+	exynos4_pwm_init(2, cycles);
+	exynos4_pwm_start(2, 0);
+	return 0;
+}
+
+static void exynos4_pwm_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	exynos4_pwm_stop(2);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_pwm_init(2, clock_count_per_tick);
+		exynos4_pwm_start(2, 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device pwm_event_device = {
+	.name		= "pwm_timer2",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.shift		= 32,
+	.set_next_event	= exynos4_pwm_set_next_event,
+	.set_mode	= exynos4_pwm_set_mode,
+};
+
+irqreturn_t exynos4_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &pwm_event_device;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction exynos4_clock_event_irq = {
+	.name		= "pwm_timer2_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= exynos4_clock_event_isr,
+};
+
+static void __init exynos4_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	/* configure clock tick */
+
+	tscaler = clk_get_parent(tdiv2);
+
+	clk_set_rate(tscaler, pclk / 2);
+	clk_set_rate(tdiv2, pclk / 2);
+	clk_set_parent(tin2, tdiv2);
+
+	clock_rate = clk_get_rate(tin2);
+
+	clock_count_per_tick = clock_rate / HZ;
+
+	pwm_event_device.mult =
+		div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
+	pwm_event_device.max_delta_ns =
+		clockevent_delta2ns(-1, &pwm_event_device);
+	pwm_event_device.min_delta_ns =
+		clockevent_delta2ns(1, &pwm_event_device);
+
+	pwm_event_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&pwm_event_device);
+
+	setup_irq(IRQ_TIMER2, &exynos4_clock_event_irq);
+}
+
+static cycle_t exynos4_pwm4_read(struct clocksource *cs)
+{
+	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
+}
+
+static void exynos4_pwm4_resume(struct clocksource *cs)
+{
+	unsigned long pclk;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv4, pclk / 2);
+	clk_set_parent(tin4, tdiv4);
+
+	exynos4_pwm_init(4, ~0);
+	exynos4_pwm_start(4, 1);
+}
+
+struct clocksource pwm_clocksource = {
+	.name		= "pwm_timer4",
+	.rating		= 250,
+	.read		= exynos4_pwm4_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
+#ifdef CONFIG_PM
+	.resume		= exynos4_pwm4_resume,
+#endif
+};
+
+static void __init exynos4_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv4, pclk / 2);
+	clk_set_parent(tin4, tdiv4);
+
+	clock_rate = clk_get_rate(tin4);
+
+	exynos4_pwm_init(4, ~0);
+	exynos4_pwm_start(4, 1);
+
+	if (clocksource_register_hz(&pwm_clocksource, clock_rate))
+		panic("%s: can't register clocksource\n", pwm_clocksource.name);
+}
+
+static void __init exynos4_timer_resources(void)
+{
+	struct platform_device tmpdev;
+
+	tmpdev.dev.bus = &platform_bus_type;
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for system timer");
+
+	clk_enable(timerclk);
+
+	tmpdev.id = 2;
+	tin2 = clk_get(&tmpdev.dev, "pwm-tin");
+	if (IS_ERR(tin2))
+		panic("failed to get pwm-tin2 clock for system timer");
+
+	tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
+	if (IS_ERR(tdiv2))
+		panic("failed to get pwm-tdiv2 clock for system timer");
+	clk_enable(tin2);
+
+	tmpdev.id = 4;
+	tin4 = clk_get(&tmpdev.dev, "pwm-tin");
+	if (IS_ERR(tin4))
+		panic("failed to get pwm-tin4 clock for system timer");
+
+	tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
+	if (IS_ERR(tdiv4))
+		panic("failed to get pwm-tdiv4 clock for system timer");
+
+	clk_enable(tin4);
+}
+
+static void __init exynos4_timer_init(void)
+{
+#ifdef CONFIG_LOCAL_TIMERS
+	twd_base = S5P_VA_TWD;
+#endif
+
+	exynos4_timer_resources();
+	exynos4_clockevent_init();
+	exynos4_clocksource_init();
+}
+
+struct sys_timer exynos4_timer = {
+	.init		= exynos4_timer_init,
+};
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index bc5e83f..a921fe9 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -4,10 +4,11 @@
  *  Copyright (C) 1998 Russell King.
  *  Copyright (C) 1998 Phil Blundell
  */
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/spinlock.h>
 
 #include <asm/irq.h>
 
@@ -16,32 +17,76 @@
 
 #include "common.h"
 
-/*
- * Footbridge timer 1 support.
- */
-static unsigned long timer1_latch;
+static cycle_t cksrc_dc21285_read(struct clocksource *cs)
+{
+	return cs->mask - *CSR_TIMER2_VALUE;
+}
 
-static unsigned long timer1_gettimeoffset (void)
+static int cksrc_dc21285_enable(struct clocksource *cs)
 {
-	unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
+	*CSR_TIMER2_LOAD = cs->mask;
+	*CSR_TIMER2_CLR = 0;
+	*CSR_TIMER2_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
+	return 0;
+}
 
-	return ((tick_nsec / 1000) * value) / timer1_latch;
+static int cksrc_dc21285_disable(struct clocksource *cs)
+{
+	*CSR_TIMER2_CNTL = 0;
 }
 
-static irqreturn_t
-timer1_interrupt(int irq, void *dev_id)
+static struct clocksource cksrc_dc21285 = {
+	.name		= "dc21285_timer2",
+	.rating		= 200,
+	.read		= cksrc_dc21285_read,
+	.enable		= cksrc_dc21285_enable,
+	.disable	= cksrc_dc21285_disable,
+	.mask		= CLOCKSOURCE_MASK(24),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *c)
 {
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		*CSR_TIMER1_CLR = 0;
+		*CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+		*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD |
+				   TIMER_CNTL_DIV16;
+		break;
+
+	default:
+		*CSR_TIMER1_CNTL = 0;
+		break;
+	}
+}
+
+static struct clock_event_device ckevt_dc21285 = {
+	.name		= "dc21285_timer1",
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.rating		= 200,
+	.irq		= IRQ_TIMER1,
+	.set_mode	= ckevt_dc21285_set_mode,
+};
+
+static irqreturn_t timer1_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ce = dev_id;
+
 	*CSR_TIMER1_CLR = 0;
 
-	timer_tick();
+	ce->event_handler(ce);
 
 	return IRQ_HANDLED;
 }
 
 static struct irqaction footbridge_timer_irq = {
-	.name		= "Timer1 timer tick",
+	.name		= "dc21285_timer1",
 	.handler	= timer1_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.dev_id		= &ckevt_dc21285,
 };
 
 /*
@@ -49,16 +94,19 @@ static struct irqaction footbridge_timer_irq = {
  */
 static void __init footbridge_timer_init(void)
 {
-	timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+	struct clock_event_device *ce = &ckevt_dc21285;
+
+	clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
+
+	setup_irq(ce->irq, &footbridge_timer_irq);
 
-	*CSR_TIMER1_CLR  = 0;
-	*CSR_TIMER1_LOAD = timer1_latch;
-	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+	clockevents_calc_mult_shift(ce, mem_fclk_21285, 5);
+	ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce);
+	ce->min_delta_ns = clockevent_delta2ns(0x000004, ce);
 
-	setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
+	clockevents_register_device(ce);
 }
 
 struct sys_timer footbridge_timer = {
 	.init		= footbridge_timer_init,
-	.offset		= timer1_gettimeoffset,
 };
diff --git a/arch/arm/mach-footbridge/include/mach/hardware.h b/arch/arm/mach-footbridge/include/mach/hardware.h
index 51dd902..b6fdf23 100644
--- a/arch/arm/mach-footbridge/include/mach/hardware.h
+++ b/arch/arm/mach-footbridge/include/mach/hardware.h
@@ -23,26 +23,33 @@
  * 0xf9000000	0x50000000	1MB	Cache flush
  * 0xf0000000	0x80000000	16MB	ISA memory
  */
+
+#ifdef CONFIG_MMU
+#define MMU_IO(a, b)	(a)
+#else
+#define MMU_IO(a, b)	(b)
+#endif
+
 #define XBUS_SIZE		0x00100000
-#define XBUS_BASE		0xff800000
+#define XBUS_BASE		MMU_IO(0xff800000, 0x40000000)
 
 #define ARMCSR_SIZE		0x00100000
-#define ARMCSR_BASE		0xfe000000
+#define ARMCSR_BASE		MMU_IO(0xfe000000, 0x42000000)
 
 #define WFLUSH_SIZE		0x00100000
-#define WFLUSH_BASE		0xfd000000
+#define WFLUSH_BASE		MMU_IO(0xfd000000, 0x78000000)
 
 #define PCIIACK_SIZE		0x00100000
-#define PCIIACK_BASE		0xfc000000
+#define PCIIACK_BASE		MMU_IO(0xfc000000, 0x79000000)
 
 #define PCICFG1_SIZE		0x01000000
-#define PCICFG1_BASE		0xfb000000
+#define PCICFG1_BASE		MMU_IO(0xfb000000, 0x7a000000)
 
 #define PCICFG0_SIZE		0x01000000
-#define PCICFG0_BASE		0xfa000000
+#define PCICFG0_BASE		MMU_IO(0xfa000000, 0x7b000000)
 
 #define PCIMEM_SIZE		0x01000000
-#define PCIMEM_BASE		0xf0000000
+#define PCIMEM_BASE		MMU_IO(0xf0000000, 0x80000000)
 
 #define XBUS_LEDS		((volatile unsigned char *)(XBUS_BASE + 0x12000))
 #define XBUS_LED_AMBER		(1 << 0)
diff --git a/arch/arm/mach-footbridge/include/mach/io.h b/arch/arm/mach-footbridge/include/mach/io.h
index 101a4fe..32e4cc3 100644
--- a/arch/arm/mach-footbridge/include/mach/io.h
+++ b/arch/arm/mach-footbridge/include/mach/io.h
@@ -14,8 +14,14 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define PCIO_SIZE		0x00100000
-#define PCIO_BASE		0xff000000
+#ifdef CONFIG_MMU
+#define MMU_IO(a, b)	(a)
+#else
+#define MMU_IO(a, b)	(b)
+#endif
+
+#define PCIO_SIZE       0x00100000
+#define PCIO_BASE       MMU_IO(0xff000000, 0x7c000000)
 
 #define IO_SPACE_LIMIT 0xffff
 
diff --git a/arch/arm/mach-footbridge/include/mach/memory.h b/arch/arm/mach-footbridge/include/mach/memory.h
index 8d64f45..5c6df37 100644
--- a/arch/arm/mach-footbridge/include/mach/memory.h
+++ b/arch/arm/mach-footbridge/include/mach/memory.h
@@ -62,7 +62,7 @@ extern unsigned long __bus_to_pfn(unsigned long);
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #define FLUSH_BASE_PHYS		0x50000000
 
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index f488fa2..441c6ce 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -4,10 +4,13 @@
  *  Copyright (C) 1998 Russell King.
  *  Copyright (C) 1998 Phil Blundell
  */
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/timex.h>
 
 #include <asm/irq.h>
 
@@ -15,77 +18,115 @@
 
 #include "common.h"
 
-/*
- * ISA timer tick support
- */
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
+#define PIT_MODE	0x43
+#define PIT_CH0		0x40
+
+#define PIT_LATCH	((PIT_TICK_RATE + HZ / 2) / HZ)
 
-static unsigned long isa_gettimeoffset(void)
+static cycle_t pit_read(struct clocksource *cs)
 {
+	unsigned long flags;
+	static int old_count;
+	static u32 old_jifs;
 	int count;
+	u32 jifs;
 
-	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
-	static unsigned long jiffies_p = 0;
+	raw_local_irq_save(flags);
 
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off. 
-	 */
-	unsigned long jiffies_t;
+	jifs = jiffies;
+	outb_p(0x00, PIT_MODE);		/* latch the count */
+	count = inb_p(PIT_CH0);		/* read the latched count */
+	count |= inb_p(PIT_CH0) << 8;
 
-	/* timer count may underflow right here */
-	outb_p(0x00, 0x43);	/* latch the count ASAP */
+	if (count > old_count && jifs == old_jifs)
+		count = old_count;
 
-	count = inb_p(0x40);	/* read the latched count */
+	old_count = count;
+	old_jifs = jifs;
 
-	/*
-	 * We do this guaranteed double memory access instead of a _p 
-	 * postfix in the previous port access. Wheee, hackady hack
-	 */
- 	jiffies_t = jiffies;
+	raw_local_irq_restore(flags);
 
-	count |= inb_p(0x40) << 8;
+	count = (PIT_LATCH - 1) - count;
 
-	/* Detect timer underflows.  If we haven't had a timer tick since 
-	   the last time we were called, and time is apparently going
-	   backwards, the counter must have wrapped during this routine. */
-	if ((jiffies_t == jiffies_p) && (count > count_p))
-		count -= (mSEC_10_from_14/6);
-	else
-		jiffies_p = jiffies_t;
+	return (cycle_t)(jifs * PIT_LATCH) + count;
+}
 
-	count_p = count;
+static struct clocksource pit_cs = {
+	.name		= "pit",
+	.rating		= 110,
+	.read		= pit_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+};
 
-	count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
-	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+static void pit_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	unsigned long flags;
+
+	raw_local_irq_save(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		outb_p(0x34, PIT_MODE);
+		outb_p(PIT_LATCH & 0xff, PIT_CH0);
+		outb_p(PIT_LATCH >> 8, PIT_CH0);
+		break;
+
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		outb_p(0x30, PIT_MODE);
+		outb_p(0, PIT_CH0);
+		outb_p(0, PIT_CH0);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+	local_irq_restore(flags);
+}
 
-	return count;
+static int pit_set_next_event(unsigned long delta,
+	struct clock_event_device *evt)
+{
+	return 0;
 }
 
-static irqreturn_t
-isa_timer_interrupt(int irq, void *dev_id)
+static struct clock_event_device pit_ce = {
+	.name		= "pit",
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.set_mode	= pit_set_mode,
+	.set_next_event	= pit_set_next_event,
+	.shift		= 32,
+};
+
+static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
 {
-	timer_tick();
+	struct clock_event_device *ce = dev_id;
+	ce->event_handler(ce);
 	return IRQ_HANDLED;
 }
 
-static struct irqaction isa_timer_irq = {
-	.name		= "ISA timer tick",
-	.handler	= isa_timer_interrupt,
+static struct irqaction pit_timer_irq = {
+	.name		= "pit",
+	.handler	= pit_timer_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.dev_id		= &pit_ce,
 };
 
 static void __init isa_timer_init(void)
 {
-	/* enable PIT timer */
-	/* set for periodic (4) and LSB/MSB write (0x30) */
-	outb(0x34, 0x43);
-	outb((mSEC_10_from_14/6) & 0xFF, 0x40);
-	outb((mSEC_10_from_14/6) >> 8, 0x40);
+	pit_ce.cpumask = cpumask_of(smp_processor_id());
+	pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
+	pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce);
+	pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce);
+
+	clocksource_register_hz(&pit_cs, PIT_TICK_RATE);
 
-	setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+	setup_irq(pit_ce.irq, &pit_timer_irq);
+	clockevents_register_device(&pit_ce);
 }
 
 struct sys_timer isa_timer = {
 	.init		= isa_timer_init,
-	.offset		= isa_gettimeoffset,
 };
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 2ba096d..0cf7a07 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -98,6 +98,7 @@ static void __init ib4220b_init(void)
 	platform_register_pflash(SZ_16M, NULL, 0);
 	platform_device_register(&ib4220b_led_device);
 	platform_device_register(&ib4220b_key_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index a9a0d8b..4fa09af 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -82,6 +82,7 @@ static void __init rut1xx_init(void)
 	platform_register_pflash(SZ_8M, NULL, 0);
 	platform_device_register(&rut1xx_leds);
 	platform_device_register(&rut1xx_keys_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index 8b88d50..af7b68a 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -130,6 +130,7 @@ static void __init wbd111_init(void)
 				 wbd111_num_partitions);
 	platform_device_register(&wbd111_leds_device);
 	platform_device_register(&wbd111_keys_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index 1eebcec..99e5bbe 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -130,6 +130,7 @@ static void __init wbd222_init(void)
 		wbd222_num_partitions);
 	platform_device_register(&wbd222_leds_device);
 	platform_device_register(&wbd222_keys_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h
index 9392834..7670c39 100644
--- a/arch/arm/mach-gemini/common.h
+++ b/arch/arm/mach-gemini/common.h
@@ -18,6 +18,7 @@ extern void gemini_map_io(void);
 extern void gemini_init_irq(void);
 extern void gemini_timer_init(void);
 extern void gemini_gpio_init(void);
+extern void platform_register_rtc(void);
 
 /* Common platform devices registration functions */
 extern int platform_register_uart(void);
diff --git a/arch/arm/mach-gemini/devices.c b/arch/arm/mach-gemini/devices.c
index 6b52525..5cff298 100644
--- a/arch/arm/mach-gemini/devices.c
+++ b/arch/arm/mach-gemini/devices.c
@@ -90,3 +90,29 @@ int platform_register_pflash(unsigned int size, struct mtd_partition *parts,
 
 	return platform_device_register(&pflash_device);
 }
+
+static struct resource gemini_rtc_resources[] = {
+	[0] = {
+		.start  = GEMINI_RTC_BASE,
+		.end    = GEMINI_RTC_BASE + 0x24,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_RTC,
+		.end    = IRQ_RTC,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device gemini_rtc_device = {
+	.name		= "rtc-gemini",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(gemini_rtc_resources),
+	.resource	= gemini_rtc_resources,
+};
+
+int __init platform_register_rtc(void)
+{
+	return platform_device_register(&gemini_rtc_device);
+}
+
diff --git a/arch/arm/mach-gemini/include/mach/memory.h b/arch/arm/mach-gemini/include/mach/memory.h
index 2d14d5b..a50915f 100644
--- a/arch/arm/mach-gemini/include/mach/memory.h
+++ b/arch/arm/mach-gemini/include/mach/memory.h
@@ -11,9 +11,9 @@
 #define __MACH_MEMORY_H
 
 #ifdef CONFIG_GEMINI_MEM_SWAP
-# define PHYS_OFFSET	UL(0x00000000)
+# define PLAT_PHYS_OFFSET	UL(0x00000000)
 #else
-# define PHYS_OFFSET	UL(0x10000000)
+# define PLAT_PHYS_OFFSET	UL(0x10000000)
 #endif
 
 #endif /* __MACH_MEMORY_H */
diff --git a/arch/arm/mach-h720x/include/mach/memory.h b/arch/arm/mach-h720x/include/mach/memory.h
index ef4c1e2..9d36876 100644
--- a/arch/arm/mach-h720x/include/mach/memory.h
+++ b/arch/arm/mach-h720x/include/mach/memory.h
@@ -7,7 +7,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x40000000)
+#define PLAT_PHYS_OFFSET	UL(0x40000000)
 /*
  * This is the maximum DMA address that can be DMAd to.
  * There should not be more than (0xd0000000 - 0xc0000000)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 56684b5..5eec099 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -100,6 +100,7 @@ config MACH_MX25_3DS
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMXDI_RTC
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
@@ -238,6 +239,7 @@ config MACH_MX27_3DS
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -265,6 +267,7 @@ config MACH_IMX27LITE
 	bool "LogicPD MX27 LITEKIT platform"
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	help
 	  Include support for MX27 LITEKIT platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -300,4 +303,13 @@ config MACH_MXT_TD60
 	  Include support for i-MXT (aka td60) platform. This
 	  includes specific configurations for the module and its peripherals.
 
+config MACH_IMX27IPCAM
+	bool "IMX27 IPCAM platform"
+	select SOC_IMX27
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_UART
+	help
+	  Include support for IMX27 IPCAM platform. This includes specific
+	  configurations for the board and its peripherals.
+
 endif
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 77100bf..b85794d 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -9,10 +9,10 @@ obj-$(CONFIG_IMX_HAVE_DMA_V1) += dma-v1.o
 obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
 obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o
+obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
 
 obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o
+obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO)	+= mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -36,3 +36,4 @@ obj-$(CONFIG_MACH_CPUIMX27) += mach-cpuimx27.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
 obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
 obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o
+obj-$(CONFIG_MACH_IMX27IPCAM) += mach-imx27ipcam.o
diff --git a/arch/arm/mach-imx/clock-imx1.c b/arch/arm/mach-imx/clock-imx1.c
index 3938a56..dcc4172 100644
--- a/arch/arm/mach-imx/clock-imx1.c
+++ b/arch/arm/mach-imx/clock-imx1.c
@@ -592,6 +592,7 @@ static struct clk_lookup lookups[] __initdata = {
 	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
+	_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
 	_REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk)
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
 	_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c
index daa0165..a65838f 100644
--- a/arch/arm/mach-imx/clock-imx25.c
+++ b/arch/arm/mach-imx/clock-imx25.c
@@ -228,6 +228,7 @@ DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0,  3, get_rate_esdhc1,	 NULL,
 DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2,	 NULL, NULL);
 DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0,  4, get_rate_esdhc2,	 NULL,
 		&esdhc2_ahb_clk);
+DEFINE_CLOCK(sdma_ahb_clk, 0, CCM_CGCR0, 26, NULL,	 NULL, NULL);
 DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL,	 NULL, NULL);
 DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL,	 NULL, NULL);
 DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0,  7, NULL,	 NULL, &lcdc_ahb_clk);
@@ -253,6 +254,7 @@ DEFINE_CLOCK(lcdc_clk,	 0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
 DEFINE_CLOCK(wdt_clk,    0, CCM_CGCR2, 19, get_rate_ipg, NULL,  NULL);
 DEFINE_CLOCK(ssi1_clk,  0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
 DEFINE_CLOCK(ssi2_clk,  1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
+DEFINE_CLOCK(sdma_clk, 0, CCM_CGCR2,  6, get_rate_ipg, NULL, &sdma_ahb_clk);
 DEFINE_CLOCK(esdhc1_clk,  0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
 		&esdhc1_per_clk);
 DEFINE_CLOCK(esdhc2_clk,  1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
@@ -304,6 +306,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
 };
 
 int __init mx25_clocks_init(void)
diff --git a/arch/arm/mach-imx/devices-imx1.h b/arch/arm/mach-imx/devices-imx1.h
index 8197948..da59365 100644
--- a/arch/arm/mach-imx/devices-imx1.h
+++ b/arch/arm/mach-imx/devices-imx1.h
@@ -9,6 +9,10 @@
 #include <mach/mx1.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_imx_fb_data imx1_imx_fb_data __initconst;
+#define imx1_add_imx_fb(pdata) \
+    imx_add_imx_fb(&imx1_imx_fb_data, pdata)
+
 extern const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst;
 #define imx1_add_imx_i2c(pdata)		\
 	imx_add_imx_i2c(&imx1_imx_i2c_data, pdata)
@@ -18,3 +22,10 @@ extern const struct imx_imx_uart_3irq_data imx1_imx_uart_data[] __initconst;
 	imx_add_imx_uart_3irq(&imx1_imx_uart_data[id], pdata)
 #define imx1_add_imx_uart0(pdata)	imx1_add_imx_uart(0, pdata)
 #define imx1_add_imx_uart1(pdata)	imx1_add_imx_uart(1, pdata)
+
+extern const struct imx_spi_imx_data imx1_cspi_data[] __initconst;
+#define imx1_add_cspi(id, pdata)   \
+	imx_add_spi_imx(&imx1_cspi_data[id], pdata)
+
+#define imx1_add_spi_imx0(pdata) imx1_add_cspi(0, pdata)
+#define imx1_add_spi_imx1(pdata) imx1_add_cspi(1, pdata)
diff --git a/arch/arm/mach-imx/devices-imx25.h b/arch/arm/mach-imx/devices-imx25.h
index bde33ca..b591d72 100644
--- a/arch/arm/mach-imx/devices-imx25.h
+++ b/arch/arm/mach-imx/devices-imx25.h
@@ -81,7 +81,11 @@ imx25_sdhci_esdhc_imx_data[] __initconst;
 
 extern const struct imx_spi_imx_data imx25_cspi_data[] __initconst;
 #define imx25_add_spi_imx(id, pdata)	\
-	imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
+	imx_add_spi_imx(&imx25_cspi_data[id], pdata)
 #define imx25_add_spi_imx0(pdata)	imx25_add_spi_imx(0, pdata)
 #define imx25_add_spi_imx1(pdata)	imx25_add_spi_imx(1, pdata)
 #define imx25_add_spi_imx2(pdata)	imx25_add_spi_imx(2, pdata)
+
+extern struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst;
+#define imx25_add_mxc_pwm(id)	\
+	imx_add_mxc_pwm(&imx25_mxc_pwm_data[id])
diff --git a/arch/arm/mach-imx/dma-v1.c b/arch/arm/mach-imx/dma-v1.c
index e9f1769..236f149 100644
--- a/arch/arm/mach-imx/dma-v1.c
+++ b/arch/arm/mach-imx/dma-v1.c
@@ -699,7 +699,7 @@ int imx_dma_request(int channel, const char *name)
 		local_irq_restore(flags);
 		return -EBUSY;
 	}
-	memset(imxdma, 0, sizeof(imxdma));
+	memset(imxdma, 0, sizeof(*imxdma));
 	imxdma->name = name;
 	local_irq_restore(flags); /* request_irq() can block */
 
diff --git a/arch/arm/mach-imx/ehci-imx25.c b/arch/arm/mach-imx/ehci-imx25.c
new file mode 100644
index 0000000..865daf0
--- /dev/null
+++ b/arch/arm/mach-imx/ehci-imx25.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX25_OTG_SIC_SHIFT	29
+#define MX25_OTG_SIC_MASK	(0x3 << MX25_OTG_SIC_SHIFT)
+#define MX25_OTG_PM_BIT		(1 << 24)
+
+#define MX25_H1_SIC_SHIFT	21
+#define MX25_H1_SIC_MASK	(0x3 << MX25_H1_SIC_SHIFT)
+#define MX25_H1_PM_BIT		(1 << 8)
+#define MX25_H1_IPPUE_UP_BIT	(1 << 7)
+#define MX25_H1_IPPUE_DOWN_BIT	(1 << 6)
+#define MX25_H1_TLL_BIT		(1 << 5)
+#define MX25_H1_USBTE_BIT	(1 << 4)
+
+int mx25_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX25_OTG_PM_BIT;
+
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT |
+			MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX25_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX25_H1_TLL_BIT;
+
+		if (flags & MXC_EHCI_INTERNAL_PHY)
+			v |= MX25_H1_USBTE_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_DOWN)
+			v |= MX25_H1_IPPUE_DOWN_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_UP)
+			v |= MX25_H1_IPPUE_UP_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-imx/ehci-imx27.c b/arch/arm/mach-imx/ehci-imx27.c
new file mode 100644
index 0000000..fa69419
--- /dev/null
+++ b/arch/arm/mach-imx/ehci-imx27.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX27_OTG_SIC_SHIFT	29
+#define MX27_OTG_SIC_MASK	(0x3 << MX27_OTG_SIC_SHIFT)
+#define MX27_OTG_PM_BIT		(1 << 24)
+
+#define MX27_H2_SIC_SHIFT	21
+#define MX27_H2_SIC_MASK	(0x3 << MX27_H2_SIC_SHIFT)
+#define MX27_H2_PM_BIT		(1 << 16)
+#define MX27_H2_DT_BIT		(1 << 5)
+
+#define MX27_H1_SIC_SHIFT	13
+#define MX27_H1_SIC_MASK	(0x3 << MX27_H1_SIC_SHIFT)
+#define MX27_H1_PM_BIT		(1 << 8)
+#define MX27_H1_DT_BIT		(1 << 4)
+
+int mx27_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX27_OTG_SIC_MASK | MX27_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX27_OTG_PM_BIT;
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX27_H1_SIC_MASK | MX27_H1_PM_BIT | MX27_H1_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX27_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX27_H1_DT_BIT;
+
+		break;
+	case 2:	/* H2 port */
+		v &= ~(MX27_H2_SIC_MASK | MX27_H2_PM_BIT | MX27_H2_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H2_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX27_H2_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX27_H2_DT_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
index 275c858..fa5288018 100644
--- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
+++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
@@ -249,7 +249,7 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 
 #define ADS7846_PENDOWN (GPIO_PORTD | 25)
 
-static void ads7846_dev_init(void)
+static void __maybe_unused ads7846_dev_init(void)
 {
 	if (gpio_request(ADS7846_PENDOWN, "ADS7846 pendown") < 0) {
 		printk(KERN_ERR "can't get ads746 pen down GPIO\n");
@@ -268,7 +268,8 @@ static struct ads7846_platform_data ads7846_config __initdata = {
 	.keep_vref_on		= 1,
 };
 
-static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = {
+static struct spi_board_info __maybe_unused
+		eukrea_mbimx27_spi_board_info[] __initdata = {
 	[0] = {
 		.modalias	= "ads7846",
 		.bus_num	= 0,
@@ -357,13 +358,11 @@ void __init eukrea_mbimx27_baseboard_init(void)
 	ads7846_dev_init();
 #endif
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	/* SPI_CS0 init */
 	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
 	imx27_add_spi_imx0(&eukrea_mbimx27_spi0_data);
 	spi_register_board_info(eukrea_mbimx27_spi_board_info,
 			ARRAY_SIZE(eukrea_mbimx27_spi_board_info));
-#endif
 
 	/* Leds configuration */
 	mxc_gpio_mode(GPIO_PORTF | 16 | GPIO_GPIO | GPIO_OUT);
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 6cf04da..759299b 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -209,17 +209,25 @@ static struct platform_device serial_device = {
 };
 #endif
 
-#if defined(CONFIG_USB_ULPI)
+static int eukrea_cpuimx27_otg_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= eukrea_cpuimx27_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int eukrea_cpuimx27_usbh2_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init	= eukrea_cpuimx27_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -273,21 +281,19 @@ static void __init eukrea_cpuimx27_init(void)
 	platform_device_register(&serial_device);
 #endif
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx27_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx27_add_mxc_ehci_otg(&otg_pdata);
+	} else {
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 	}
 
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
-	if (!otg_mode_host)
-		imx27_add_fsl_usb2_udc(&otg_device_pdata);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD
 	eukrea_mbimx27_baseboard_init();
@@ -304,9 +310,10 @@ static struct sys_timer eukrea_cpuimx27_timer = {
 };
 
 MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = eukrea_cpuimx27_init,
-	.timer          = &eukrea_cpuimx27_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &eukrea_cpuimx27_timer,
+	.init_machine = eukrea_cpuimx27_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index eb395ab..9da8d18 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -84,15 +84,25 @@ static struct i2c_board_info eukrea_cpuimx25_i2c_devices[] = {
 	},
 };
 
+static int eukrea_cpuimx25_otg_init(struct platform_device *pdev)
+{
+	return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static const struct mxc_usbh_platform_data otg_pdata __initconst = {
+	.init	= eukrea_cpuimx25_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int eukrea_cpuimx25_usbh2_init(struct platform_device *pdev)
+{
+	return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
+}
+
 static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.init	= eukrea_cpuimx25_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
 };
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
@@ -153,9 +163,10 @@ static struct sys_timer eukrea_cpuimx25_timer = {
 
 MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params    = MX25_PHYS_OFFSET + 0x100,
-	.map_io         = mx25_map_io,
-	.init_irq       = mx25_init_irq,
-	.init_machine   = eukrea_cpuimx25_init,
-	.timer          = &eukrea_cpuimx25_timer,
+	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.map_io = mx25_map_io,
+	.init_early = imx25_init_early,
+	.init_irq = mx25_init_irq,
+	.timer = &eukrea_cpuimx25_timer,
+	.init_machine = eukrea_cpuimx25_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 40a3666..d7e0d21 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -30,6 +30,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -66,6 +67,11 @@ static const int visstrim_m10_pins[] __initconst = {
 	PD15_AOUT_FEC_COL,
 	PD16_AIN_FEC_TX_ER,
 	PF23_AIN_FEC_TX_EN,
+	/* SSI1 */
+	PC20_PF_SSI1_FS,
+	PC21_PF_SSI1_RXD,
+	PC22_PF_SSI1_TXD,
+	PC23_PF_SSI1_CLK,
 	/* SDHC1 */
 	PE18_PF_SD1_D0,
 	PE19_PF_SD1_D1,
@@ -204,20 +210,30 @@ static struct i2c_board_info visstrim_m10_i2c_devices[] = {
 		I2C_BOARD_INFO("pca9555", 0x20),
 		.platform_data = &visstrim_m10_pca9555_pdata,
 	},
+	{
+		I2C_BOARD_INFO("tlv320aic32x4", 0x18),
+	}
 };
 
 /* USB OTG */
 static int otg_phy_init(struct platform_device *pdev)
 {
 	gpio_set_value(OTG_PHY_CS_GPIO, 0);
-	return 0;
+
+	mdelay(10);
+
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
 }
 
 static const struct mxc_usbh_platform_data
 visstrim_m10_usbotg_pdata __initconst = {
 	.init = otg_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+/* SSI */
+static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = {
+	.flags			= IMX_SSI_DMA | IMX_SSI_SYN,
 };
 
 static void __init visstrim_m10_board_init(void)
@@ -229,6 +245,7 @@ static void __init visstrim_m10_board_init(void)
 	if (ret)
 		pr_err("Failed to setup pins (%d)\n", ret);
 
+	imx27_add_imx_ssi(0, &visstrim_m10_ssi_pdata);
 	imx27_add_imx_uart0(&uart_pdata);
 
 	i2c_register_board_info(0, visstrim_m10_i2c_devices,
@@ -251,9 +268,10 @@ static struct sys_timer visstrim_m10_timer = {
 };
 
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = visstrim_m10_board_init,
-	.timer          = &visstrim_m10_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &visstrim_m10_timer,
+	.init_machine = visstrim_m10_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
new file mode 100644
index 0000000..9be6cd6
--- /dev/null
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx27.h>
+
+#include "devices-imx27.h"
+
+static const int mx27ipcam_pins[] __initconst = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	/* FEC */
+	PD0_AIN_FEC_TXD0,
+	PD1_AIN_FEC_TXD1,
+	PD2_AIN_FEC_TXD2,
+	PD3_AIN_FEC_TXD3,
+	PD4_AOUT_FEC_RX_ER,
+	PD5_AOUT_FEC_RXD1,
+	PD6_AOUT_FEC_RXD2,
+	PD7_AOUT_FEC_RXD3,
+	PD8_AF_FEC_MDIO,
+	PD9_AIN_FEC_MDC,
+	PD10_AOUT_FEC_CRS,
+	PD11_AOUT_FEC_TX_CLK,
+	PD12_AOUT_FEC_RXD0,
+	PD13_AOUT_FEC_RX_DV,
+	PD14_AOUT_FEC_RX_CLK,
+	PD15_AOUT_FEC_COL,
+	PD16_AIN_FEC_TX_ER,
+	PF23_AIN_FEC_TX_EN,
+};
+
+static void __init mx27ipcam_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
+		"mx27ipcam");
+
+	imx27_add_imx_uart0(NULL);
+	imx27_add_fec(NULL);
+	imx27_add_imx2_wdt(NULL);
+}
+
+static void __init mx27ipcam_timer_init(void)
+{
+	mx27_clocks_init(25000000);
+}
+
+static struct sys_timer mx27ipcam_timer = {
+	.init	= mx27ipcam_timer_init,
+};
+
+MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27ipcam_timer,
+	.init_machine = mx27ipcam_init,
+MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index 3a1202e..8411405 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -75,9 +75,10 @@ static struct sys_timer mx27lite_timer = {
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27lite_init,
-	.timer          = &mx27lite_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27lite_timer,
+	.init_machine = mx27lite_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 1f446e5..47cf56a 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -144,17 +144,19 @@ struct sys_timer mx1ads_timer = {
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
-	.boot_params	= MX1_PHYS_OFFSET + 0x100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &mx1ads_timer,
-	.init_machine	= mx1ads_init,
+	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.map_io = mx1_map_io,
+	.init_early = imx1_init_early,
+	.init_irq = mx1_init_irq,
+	.timer = &mx1ads_timer,
+	.init_machine = mx1ads_init,
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-	.boot_params	= MX1_PHYS_OFFSET + 0x100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &mx1ads_timer,
-	.init_machine	= mx1ads_init,
+	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.map_io = mx1_map_io,
+	.init_early = imx1_init_early,
+	.init_irq = mx1_init_irq,
+	.timer = &mx1ads_timer,
+	.init_machine = mx1ads_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 0a37257..fa52a10 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -304,9 +304,10 @@ static struct sys_timer mx21ads_timer = {
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX21_PHYS_OFFSET + 0x100,
-	.map_io         = mx21ads_map_io,
-	.init_irq       = mx21_init_irq,
-	.init_machine   = mx21ads_board_init,
-	.timer          = &mx21ads_timer,
+	.boot_params = MX21_PHYS_OFFSET + 0x100,
+	.map_io = mx21ads_map_io,
+	.init_early = imx21_init_early,
+	.init_irq = mx21_init_irq,
+	.timer = &mx21ads_timer,
+	.init_machine = mx21ads_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index 8382e79..06da438 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -103,14 +103,18 @@ static iomux_v3_cfg_t mx25pdk_pads[] = {
 	MX25_PAD_SD1_DATA1__SD1_DATA1,
 	MX25_PAD_SD1_DATA2__SD1_DATA2,
 	MX25_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* I2C1 */
+	MX25_PAD_I2C1_CLK__I2C1_CLK,
+	MX25_PAD_I2C1_DAT__I2C1_DAT,
 };
 
 static const struct fec_platform_data mx25_fec_pdata __initconst = {
 	.phy    = PHY_INTERFACE_MODE_RMII,
 };
 
-#define FEC_ENABLE_GPIO		35
-#define FEC_RESET_B_GPIO	104
+#define FEC_ENABLE_GPIO		IMX_GPIO_NR(2, 3)
+#define FEC_RESET_B_GPIO	IMX_GPIO_NR(4, 8)
 
 static void __init mx25pdk_fec_reset(void)
 {
@@ -185,9 +189,14 @@ static const struct matrix_keymap_data mx25pdk_keymap_data __initconst = {
 	.keymap_size	= ARRAY_SIZE(mx25pdk_keymap),
 };
 
+static int mx25pdk_usbh2_init(struct platform_device *pdev)
+{
+	return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
 static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.init	= mx25pdk_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
@@ -195,6 +204,10 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.phy_mode       = FSL_USB2_PHY_UTMI,
 };
 
+static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
+
 static void __init mx25pdk_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
@@ -213,6 +226,7 @@ static void __init mx25pdk_init(void)
 	imx25_add_imx_keypad(&mx25pdk_keymap_data);
 
 	imx25_add_sdhci_esdhc_imx(0, NULL);
+	imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
 }
 
 static void __init mx25pdk_timer_init(void)
@@ -226,10 +240,10 @@ static struct sys_timer mx25pdk_timer = {
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX25_PHYS_OFFSET + 0x100,
-	.map_io         = mx25_map_io,
-	.init_irq       = mx25_init_irq,
-	.init_machine   = mx25pdk_init,
-	.timer          = &mx25pdk_timer,
+	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.map_io = mx25_map_io,
+	.init_early = imx25_init_early,
+	.init_irq = mx25_init_irq,
+	.timer = &mx25pdk_timer,
+	.init_machine = mx25pdk_init,
 MACHINE_END
-
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index 1643315..614b3c0 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -98,6 +98,9 @@ static const int mx27pdk_pins[] __initconst = {
 	PD22_PF_CSPI2_SCLK,
 	PD23_PF_CSPI2_MISO,
 	PD24_PF_CSPI2_MOSI,
+	/* I2C1 */
+	PD17_PF_I2C_DATA,
+	PD18_PF_I2C_CLK,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -159,13 +162,15 @@ static int otg_phy_init(void)
 	return 0;
 }
 
-#if defined(CONFIG_USB_ULPI)
+static int mx27_3ds_otg_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
 
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= mx27_3ds_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -216,7 +221,7 @@ static struct regulator_init_data vgen_init = {
 	.consumer_supplies = vgen_consumers,
 };
 
-static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
+static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
 	{
 		.id = MC13783_REG_VMMC1,
 		.init_data = &vmmc1_init,
@@ -227,10 +232,10 @@ static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
 };
 
 /* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
 	.regulators = mx27_3ds_regulators,
 	.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
-	.flags  = MC13783_USE_REGULATOR,
+	.flags  = MC13XXX_USE_REGULATOR,
 };
 
 /* SPI */
@@ -253,6 +258,9 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
 	},
 };
 
+static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
 
 static void __init mx27pdk_init(void)
 {
@@ -265,14 +273,15 @@ static void __init mx27pdk_init(void)
 	imx27_add_mxc_mmc(0, &sdhc1_pdata);
 	imx27_add_imx2_wdt(NULL);
 	otg_phy_init();
-#if defined(CONFIG_USB_ULPI)
+
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
 
-		imx27_add_mxc_ehci_otg(&otg_pdata);
+		if (otg_pdata.otg)
+			imx27_add_mxc_ehci_otg(&otg_pdata);
 	}
-#endif
+
 	if (!otg_mode_host)
 		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 
@@ -282,6 +291,7 @@ static void __init mx27pdk_init(void)
 
 	if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
+	imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
 }
 
 static void __init mx27pdk_timer_init(void)
@@ -295,9 +305,10 @@ static struct sys_timer mx27pdk_timer = {
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27pdk_init,
-	.timer          = &mx27pdk_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27pdk_timer,
+	.init_machine = mx27pdk_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index b832f96..367d1e4 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -344,9 +344,10 @@ static void __init mx27ads_map_io(void)
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27ads_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27ads_board_init,
-	.timer          = &mx27ads_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27ads_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27ads_timer,
+	.init_machine = mx27ads_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index 4ce71b0..69787c3 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -266,10 +266,10 @@ static struct sys_timer mxt_td60_timer = {
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	/* maintainer: Maxtrack Industrial */
-	.boot_params	= MX27_PHYS_OFFSET + 0x100,
-	.map_io		= mx27_map_io,
-	.init_irq	= mx27_init_irq,
-	.init_machine	= mxt_td60_board_init,
-	.timer		= &mxt_td60_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mxt_td60_timer,
+	.init_machine = mxt_td60_board_init,
 MACHINE_END
-
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index cccc0a0..63e1825 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -187,7 +187,6 @@ static struct i2c_board_info pca100_i2c_devices[] = {
 	}
 };
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 static struct spi_eeprom at25320 = {
 	.name		= "at25320an",
 	.byte_len	= 4096,
@@ -211,7 +210,6 @@ static const struct spi_imx_master pca100_spi0_data __initconst = {
 	.chipselect	= pca100_spi_cs,
 	.num_chipselect = ARRAY_SIZE(pca100_spi_cs),
 };
-#endif
 
 static void pca100_ac97_warm_reset(struct snd_ac97 *ac97)
 {
@@ -269,31 +267,33 @@ static const struct imxmmc_platform_data sdhc_pdata __initconst = {
 	.exit = pca100_sdhc2_exit,
 };
 
-#if defined(CONFIG_USB_ULPI)
 static int otg_phy_init(struct platform_device *pdev)
 {
 	gpio_set_value(OTG_PHY_CS_GPIO, 0);
-	return 0;
+
+	mdelay(10);
+
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
 }
 
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
 	.init	= otg_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
 static int usbh2_phy_init(struct platform_device *pdev)
 {
 	gpio_set_value(USBH2_PHY_CS_GPIO, 0);
-	return 0;
+
+	mdelay(10);
+
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
 }
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -389,36 +389,33 @@ static void __init pca100_init(void)
 
 	imx27_add_imx_i2c(1, &pca100_i2c1_data);
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_IN);
 	mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN);
 	spi_register_board_info(pca100_spi_board_info,
 				ARRAY_SIZE(pca100_spi_board_info));
 	imx27_add_spi_imx0(&pca100_spi0_data);
-#endif
 
 	gpio_request(OTG_PHY_CS_GPIO, "usb-otg-cs");
 	gpio_direction_output(OTG_PHY_CS_GPIO, 1);
 	gpio_request(USBH2_PHY_CS_GPIO, "usb-host2-cs");
 	gpio_direction_output(USBH2_PHY_CS_GPIO, 1);
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
 
-		imx27_add_mxc_ehci_otg(&otg_pdata);
+		if (otg_pdata.otg)
+			imx27_add_mxc_ehci_otg(&otg_pdata);
+	} else {
+		gpio_set_value(OTG_PHY_CS_GPIO, 0);
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
-	if (!otg_mode_host) {
-		gpio_set_value(OTG_PHY_CS_GPIO, 0);
-		imx27_add_fsl_usb2_udc(&otg_device_pdata);
-	}
+	if (usbh2_pdata.otg)
+		imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 	imx27_add_imx_fb(&pca100_fb_data);
 
@@ -437,10 +434,10 @@ static struct sys_timer pca100_timer = {
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = pca100_init,
-	.timer          = &pca100_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.init_machine = pca100_init,
+	.timer = &pca100_timer,
 MACHINE_END
-
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 5056148..38c7708 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -252,7 +252,7 @@ static struct regulator_init_data cam_data = {
 	.consumer_supplies = cam_consumers,
 };
 
-static struct mc13783_regulator_init_data pcm038_regulators[] = {
+static struct mc13xxx_regulator_init_data pcm038_regulators[] = {
 	{
 		.id = MC13783_REG_VCAM,
 		.init_data = &cam_data,
@@ -262,11 +262,11 @@ static struct mc13783_regulator_init_data pcm038_regulators[] = {
 	},
 };
 
-static struct mc13783_platform_data pcm038_pmic = {
+static struct mc13xxx_platform_data pcm038_pmic = {
 	.regulators = pcm038_regulators,
 	.num_regulators = ARRAY_SIZE(pcm038_regulators),
-	.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
-		 MC13783_USE_TOUCHSCREEN,
+	.flags = MC13XXX_USE_ADC | MC13XXX_USE_REGULATOR |
+		 MC13XXX_USE_TOUCHSCREEN,
 };
 
 static struct spi_board_info pcm038_spi_board_info[] __initdata = {
@@ -281,9 +281,15 @@ static struct spi_board_info pcm038_spi_board_info[] __initdata = {
 	}
 };
 
+static int pcm038_usbh2_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.init	= pcm038_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
 static void __init pcm038_init(void)
@@ -340,9 +346,10 @@ static struct sys_timer pcm038_timer = {
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = pcm038_init,
-	.timer          = &pcm038_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &pcm038_timer,
+	.init_machine = pcm038_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index eae878f..dcaee04 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -145,10 +145,11 @@ static struct sys_timer scb9328_timer = {
 };
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
-    /* Sascha Hauer */
-	.boot_params	= 0x08000100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &scb9328_timer,
-	.init_machine	= scb9328_init,
+	/* Sascha Hauer */
+	.boot_params = 0x08000100,
+	.map_io = mx1_map_io,
+	.init_early = imx1_init_early,
+	.init_irq = mx1_init_irq,
+	.timer = &scb9328_timer,
+	.init_machine = scb9328_init,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 729ae09..2e482ba 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -23,6 +23,9 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/iomux-v1.h>
 
 static struct map_desc imx_io_desc[] __initdata = {
 	imx_map_entry(MX1, IO, MT_DEVICE),
@@ -30,16 +33,26 @@ static struct map_desc imx_io_desc[] __initdata = {
 
 void __init mx1_map_io(void)
 {
+	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
+}
+
+void __init imx1_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX1);
 	mxc_arch_reset_init(MX1_IO_ADDRESS(MX1_WDT_BASE_ADDR));
-
-	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
+	imx_iomuxv1_init(MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR),
+			MX1_NUM_GPIO_PORT);
 }
 
-int imx1_register_gpios(void);
+static struct mxc_gpio_port imx1_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
+};
 
 void __init mx1_init_irq(void)
 {
 	mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR));
-	imx1_register_gpios();
+	mxc_gpio_init(imx1_gpio_ports,	ARRAY_SIZE(imx1_gpio_ports));
 }
diff --git a/arch/arm/mach-imx/mm-imx21.c b/arch/arm/mach-imx/mm-imx21.c
index e728af8..7a0c500 100644
--- a/arch/arm/mach-imx/mm-imx21.c
+++ b/arch/arm/mach-imx/mm-imx21.c
@@ -24,6 +24,9 @@
 #include <mach/common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/iomux-v1.h>
 
 /* MX21 memory map definition */
 static struct map_desc imx21_io_desc[] __initdata = {
@@ -56,16 +59,28 @@ static struct map_desc imx21_io_desc[] __initdata = {
  */
 void __init mx21_map_io(void)
 {
+	iotable_init(imx21_io_desc, ARRAY_SIZE(imx21_io_desc));
+}
+
+void __init imx21_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX21);
 	mxc_arch_reset_init(MX21_IO_ADDRESS(MX21_WDOG_BASE_ADDR));
-
-	iotable_init(imx21_io_desc, ARRAY_SIZE(imx21_io_desc));
+	imx_iomuxv1_init(MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR),
+			MX21_NUM_GPIO_PORT);
 }
 
-int imx21_register_gpios(void);
+static struct mxc_gpio_port imx21_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
+	DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
+	DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
+	DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
+	DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
+	DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
+};
 
 void __init mx21_init_irq(void)
 {
 	mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
-	imx21_register_gpios();
+	mxc_gpio_init(imx21_gpio_ports,	ARRAY_SIZE(imx21_gpio_ports));
 }
diff --git a/arch/arm/mach-imx/mm-imx25.c b/arch/arm/mach-imx/mm-imx25.c
index 2edec6c..02f7b5c 100644
--- a/arch/arm/mach-imx/mm-imx25.c
+++ b/arch/arm/mach-imx/mm-imx25.c
@@ -27,6 +27,8 @@
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/iomux-v3.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
 
 /*
  * This table defines static virtual address mappings for I/O regions.
@@ -45,18 +47,26 @@ static struct map_desc mx25_io_desc[] __initdata = {
  */
 void __init mx25_map_io(void)
 {
+	iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
+}
+
+void __init imx25_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX25);
 	mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
-
-	iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
 }
 
-int imx25_register_gpios(void);
+static struct mxc_gpio_port imx25_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
+};
 
 void __init mx25_init_irq(void)
 {
 	mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
-	imx25_register_gpios();
+	mxc_gpio_init(imx25_gpio_ports,	ARRAY_SIZE(imx25_gpio_ports));
 }
 
diff --git a/arch/arm/mach-imx/mm-imx27.c b/arch/arm/mach-imx/mm-imx27.c
index 374e48b..a6761a3 100644
--- a/arch/arm/mach-imx/mm-imx27.c
+++ b/arch/arm/mach-imx/mm-imx27.c
@@ -24,6 +24,9 @@
 #include <mach/common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/iomux-v1.h>
 
 /* MX27 memory map definition */
 static struct map_desc imx27_io_desc[] __initdata = {
@@ -56,16 +59,28 @@ static struct map_desc imx27_io_desc[] __initdata = {
  */
 void __init mx27_map_io(void)
 {
+	iotable_init(imx27_io_desc, ARRAY_SIZE(imx27_io_desc));
+}
+
+void __init imx27_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX27);
 	mxc_arch_reset_init(MX27_IO_ADDRESS(MX27_WDOG_BASE_ADDR));
-
-	iotable_init(imx27_io_desc, ARRAY_SIZE(imx27_io_desc));
+	imx_iomuxv1_init(MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR),
+			MX27_NUM_GPIO_PORT);
 }
 
-int imx27_register_gpios(void);
+static struct mxc_gpio_port imx27_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
+	DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
+	DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
+	DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
+	DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
+	DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
+};
 
 void __init mx27_init_irq(void)
 {
 	mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
-	imx27_register_gpios();
+	mxc_gpio_init(imx27_gpio_ports,	ARRAY_SIZE(imx27_gpio_ports));
 }
diff --git a/arch/arm/mach-integrator/include/mach/memory.h b/arch/arm/mach-integrator/include/mach/memory.h
index 991f24d..334d5e2 100644
--- a/arch/arm/mach-integrator/include/mach/memory.h
+++ b/arch/arm/mach-integrator/include/mach/memory.h
@@ -23,7 +23,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #define BUS_OFFSET	UL(0x80000000)
 #define __virt_to_bus(x)	((x) - PAGE_OFFSET + BUS_OFFSET)
diff --git a/arch/arm/mach-iop13xx/include/mach/memory.h b/arch/arm/mach-iop13xx/include/mach/memory.h
index 3ad4553..1afa99e 100644
--- a/arch/arm/mach-iop13xx/include/mach/memory.h
+++ b/arch/arm/mach-iop13xx/include/mach/memory.h
@@ -6,7 +6,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/mach-iop32x/include/mach/memory.h b/arch/arm/mach-iop32x/include/mach/memory.h
index c30f645..169cc23 100644
--- a/arch/arm/mach-iop32x/include/mach/memory.h
+++ b/arch/arm/mach-iop32x/include/mach/memory.h
@@ -8,6 +8,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0xa0000000)
+#define PLAT_PHYS_OFFSET	UL(0xa0000000)
 
 #endif
diff --git a/arch/arm/mach-iop33x/include/mach/memory.h b/arch/arm/mach-iop33x/include/mach/memory.h
index a30a96a..8e1daf7 100644
--- a/arch/arm/mach-iop33x/include/mach/memory.h
+++ b/arch/arm/mach-iop33x/include/mach/memory.h
@@ -8,6 +8,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-ixp2000/include/mach/memory.h b/arch/arm/mach-ixp2000/include/mach/memory.h
index 98e3471..5f0c4fd 100644
--- a/arch/arm/mach-ixp2000/include/mach/memory.h
+++ b/arch/arm/mach-ixp2000/include/mach/memory.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #include <mach/ixp2000-regs.h>
 
diff --git a/arch/arm/mach-ixp23xx/include/mach/memory.h b/arch/arm/mach-ixp23xx/include/mach/memory.h
index 6ef65d8..6cf0704 100644
--- a/arch/arm/mach-ixp23xx/include/mach/memory.h
+++ b/arch/arm/mach-ixp23xx/include/mach/memory.h
@@ -17,7 +17,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		(0x00000000)
+#define PLAT_PHYS_OFFSET		(0x00000000)
 
 #define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)
 
diff --git a/arch/arm/mach-ixp4xx/include/mach/memory.h b/arch/arm/mach-ixp4xx/include/mach/memory.h
index 0136eaa..6d388c9 100644
--- a/arch/arm/mach-ixp4xx/include/mach/memory.h
+++ b/arch/arm/mach-ixp4xx/include/mach/memory.h
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
 
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 3688123..20e71df 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -21,6 +21,7 @@
 #include <net/dsa.h>
 #include <asm/page.h>
 #include <asm/timex.h>
+#include <asm/kexec.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <mach/kirkwood.h>
@@ -846,9 +847,14 @@ static void __init kirkwood_wdt_init(void)
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init kirkwood_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 int kirkwood_tclk;
 
-int __init kirkwood_find_tclk(void)
+static int __init kirkwood_find_tclk(void)
 {
 	u32 dev, rev;
 
@@ -864,7 +870,9 @@ int __init kirkwood_find_tclk(void)
 static void __init kirkwood_timer_init(void)
 {
 	kirkwood_tclk = kirkwood_find_tclk();
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
 struct sys_timer kirkwood_timer = {
@@ -1003,6 +1011,10 @@ void __init kirkwood_init(void)
 	kirkwood_xor0_init();
 	kirkwood_xor1_init();
 	kirkwood_crypto_init();
+
+#ifdef CONFIG_KEXEC 
+	kexec_reinit = kirkwood_enable_pcie;
+#endif
 }
 
 static int __init kirkwood_clock_gate(void)
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index 95bb0a7..b9b0f09 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -27,11 +27,13 @@ struct kirkwood_asoc_platform_data;
  */
 void kirkwood_map_io(void);
 void kirkwood_init(void);
+void kirkwood_init_early(void);
 void kirkwood_init_irq(void);
 
 extern struct mbus_dram_target_info kirkwood_mbus_dram_info;
 void kirkwood_setup_cpu_mbus(void);
 
+void kirkwood_enable_pcie(void);
 void kirkwood_pcie_id(u32 *dev, u32 *rev);
 
 void kirkwood_ehci_init(void);
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
index a31c949..043cfd5 100644
--- a/arch/arm/mach-kirkwood/d2net_v2-setup.c
+++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c
@@ -224,6 +224,7 @@ MACHINE_START(D2NET_V2, "LaCie d2 Network v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index 9ea7118..bff04e0 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -100,6 +100,7 @@ MACHINE_START(DB88F6281_BP, "Marvell DB-88F6281-BP Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= db88f6281_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
index 433ea36..f14dfb8 100644
--- a/arch/arm/mach-kirkwood/dockstar-setup.c
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -105,6 +105,7 @@ MACHINE_START(DOCKSTAR, "Seagate FreeAgent DockStar")
 	.boot_params	= 0x00000100,
 	.init_machine	= dockstar_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
index 8f47dc0..41d1b40 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -124,6 +124,7 @@ MACHINE_START(GURUPLUG, "Marvell GuruPlug Reference Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= guruplug_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index aff0e13..957bd79 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -29,9 +29,6 @@
 #define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
 #define WDT_INT_REQ		0x0008
 
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-kirkwood/include/mach/gpio.h b/arch/arm/mach-kirkwood/include/mach/gpio.h
index 81b335e..84f340b 100644
--- a/arch/arm/mach-kirkwood/include/mach/gpio.h
+++ b/arch/arm/mach-kirkwood/include/mach/gpio.h
@@ -6,33 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define GPIO_MAX		50
-#define GPIO_OFF(pin)		(((pin) >> 5) ? 0x0140 : 0x0100)
-#define GPIO_OUT(pin)		(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x00)
-#define GPIO_IO_CONF(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x04)
-#define GPIO_BLINK_EN(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x08)
-#define GPIO_IN_POL(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x0c)
-#define GPIO_DATA_IN(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x10)
-#define GPIO_EDGE_CAUSE(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x14)
-#define GPIO_EDGE_MASK(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x18)
-#define GPIO_LEVEL_MASK(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x1c)
-
-static inline int gpio_to_irq(int pin)
-{
-	return pin + IRQ_KIRKWOOD_GPIO_START;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	return irq - IRQ_KIRKWOOD_GPIO_START;
-}
-
-
-#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index 6e924b3..010bdeb 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -69,6 +69,8 @@
 #define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x10000)
 #define  SAMPLE_AT_RESET	(DEV_BUS_VIRT_BASE | 0x0030)
 #define  DEVICE_ID		(DEV_BUS_VIRT_BASE | 0x0034)
+#define  GPIO_LOW_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x0100)
+#define  GPIO_HIGH_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x0140)
 #define  RTC_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0300)
 #define  SPI_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0600)
 #define  I2C_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x1000)
diff --git a/arch/arm/mach-kirkwood/include/mach/memory.h b/arch/arm/mach-kirkwood/include/mach/memory.h
index 45431e1..4600b44 100644
--- a/arch/arm/mach-kirkwood/include/mach/memory.h
+++ b/arch/arm/mach-kirkwood/include/mach/memory.h
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index 28020ab..cbdb586 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -27,31 +27,21 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 void __init kirkwood_init_irq(void)
 {
-	int i;
-
 	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
 	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts.
+	 * Initialize gpiolib for GPIOs 0-49.
 	 */
-	writel(0, GPIO_LEVEL_MASK(0));
-	writel(0, GPIO_EDGE_MASK(0));
-	writel(0, GPIO_EDGE_CAUSE(0));
-	writel(0, GPIO_LEVEL_MASK(32));
-	writel(0, GPIO_EDGE_MASK(32));
-	writel(0, GPIO_EDGE_CAUSE(32));
-
-	for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
+	orion_gpio_init(0, 32, GPIO_LOW_VIRT_BASE, 0,
+			IRQ_KIRKWOOD_GPIO_START);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
+
+	orion_gpio_init(32, 18, GPIO_HIGH_VIRT_BASE, 0,
+			IRQ_KIRKWOOD_GPIO_START + 32);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23, gpio_irq_handler);
diff --git a/arch/arm/mach-kirkwood/mpp.c b/arch/arm/mach-kirkwood/mpp.c
index 27901f7..7ce2018 100644
--- a/arch/arm/mach-kirkwood/mpp.c
+++ b/arch/arm/mach-kirkwood/mpp.c
@@ -49,9 +49,6 @@ void __init kirkwood_mpp_conf(unsigned int *mpp_list)
 	if (!variant_mask)
 		return;
 
-	/* Initialize gpiolib. */
-	orion_gpio_init();
-
 	printk(KERN_DEBUG "initial MPP regs:");
 	for (i = 0; i < MPP_NR_REGS; i++) {
 		mpp_ctrl[i] = readl(MPP_CTRL(i));
diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
index 1e5266f..00cca22 100644
--- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
@@ -166,6 +166,7 @@ MACHINE_START(MV88F6281GTW_GE, "Marvell 88F6281 GTW GE Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= mv88f6281gtw_ge_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index 65ee21f..7cdab57 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -261,6 +261,7 @@ MACHINE_START(NETSPACE_V2, "LaCie Network Space v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -271,6 +272,7 @@ MACHINE_START(INETSPACE_V2, "LaCie Internet Space v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -281,6 +283,7 @@ MACHINE_START(NETSPACE_MAX_V2, "LaCie Network Space Max v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index 93afd3c..6be627d 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -402,6 +402,7 @@ MACHINE_START(NET2BIG_V2, "LaCie 2Big Network v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -412,6 +413,7 @@ MACHINE_START(NET5BIG_V2, "LaCie 5Big Network v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index cfcca41..f69beef 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -217,6 +217,7 @@ MACHINE_START(OPENRD_BASE, "Marvell OpenRD Base Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -228,6 +229,7 @@ MACHINE_START(OPENRD_CLIENT, "Marvell OpenRD Client Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -239,6 +241,7 @@ MACHINE_START(OPENRD_ULTIMATE, "Marvell OpenRD Ultimate Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index 513ad31..ca294ff 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -18,8 +18,16 @@
 #include <mach/bridge-regs.h>
 #include "common.h"
 
+void kirkwood_enable_pcie(void)
+{
+	u32 curr = readl(CLOCK_GATING_CTRL);
+	if (!(curr & CGC_PEX0))
+		writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
+}
+
 void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
 {
+	kirkwood_enable_pcie();
 	*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
 	*rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
 }
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index 0049614..75c6601 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -82,6 +82,7 @@ MACHINE_START(RD88F6192_NAS, "Marvell RD-88F6192-NAS Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6192_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index 0998a08..0f75494 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -118,6 +118,7 @@ MACHINE_START(RD88F6281, "Marvell RD-88F6281 Reference Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6281_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index d2eec35..0a95063 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -134,6 +134,7 @@ MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -144,6 +145,7 @@ MACHINE_START(ESATA_SHEEVAPLUG, "Marvell eSATA SheevaPlug Reference Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index ce50e61a..e6b9b1b 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
+#include <sound/alc5623.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -134,6 +135,7 @@ static unsigned int hp_t5325_mpp_config[] __initdata = {
 	MPP33_GE1_TXCTL,
 	MPP39_AU_I2SBCLK,
 	MPP40_AU_I2SDO,
+	MPP43_AU_I2SDI,
 	MPP41_AU_I2SLRCLK,
 	MPP42_AU_I2SMCLK,
 	MPP45_GPIO,		/* Power button */
@@ -141,6 +143,18 @@ static unsigned int hp_t5325_mpp_config[] __initdata = {
 	0
 };
 
+static struct alc5623_platform_data alc5621_data = {
+	.add_ctrl = 0x3700,
+	.jack_det_ctrl = 0x4810,
+};
+
+static struct i2c_board_info i2c_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("alc5621", 0x1a),
+		.platform_data = &alc5621_data,
+	},
+};
+
 #define HP_T5325_GPIO_POWER_OFF		48
 
 static void hp_t5325_power_off(void)
@@ -166,6 +180,9 @@ static void __init hp_t5325_init(void)
 	kirkwood_ehci_init();
 	platform_device_register(&hp_t5325_button_device);
 
+	i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
+	kirkwood_audio_init();
+
 	if (gpio_request(HP_T5325_GPIO_POWER_OFF, "power-off") == 0 &&
 	    gpio_direction_output(HP_T5325_GPIO_POWER_OFF, 0) == 0)
 		pm_power_off = hp_t5325_power_off;
@@ -187,6 +204,7 @@ MACHINE_START(T5325, "HP t5325 Thin Client")
 	.boot_params	= 0x00000100,
 	.init_machine	= hp_t5325_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index dc999c4..68f32f2 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -135,6 +135,7 @@ MACHINE_START(TS219, "QNAP TS-119/TS-219")
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts219_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index 9a44029..d5d0099 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -154,6 +154,8 @@ static void __init qnap_ts41x_init(void)
 static int __init ts41x_pci_init(void)
 {
 	if (machine_is_ts41x()) {
+		u32 dev, rev;
+
 		/*
 		 * Without this explicit reset, the PCIe SATA controller
 		 * (Marvell 88sx7042/sata_mv) is known to stop working
@@ -161,7 +163,11 @@ static int __init ts41x_pci_init(void)
 		 */
 		orion_pcie_reset((void __iomem *)PCIE_VIRT_BASE);
 
-		kirkwood_pcie_init(KW_PCIE0);
+		kirkwood_pcie_id(&dev, &rev);
+		if (dev == MV88F6282_DEV_ID)
+			kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
+		else
+			kirkwood_pcie_init(KW_PCIE0);
 	}
 
    return 0;
@@ -173,6 +179,7 @@ MACHINE_START(TS41X, "QNAP TS-41x")
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts41x_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff --git a/arch/arm/mach-ks8695/include/mach/memory.h b/arch/arm/mach-ks8695/include/mach/memory.h
index bace9a6..f7e1b9b 100644
--- a/arch/arm/mach-ks8695/include/mach/memory.h
+++ b/arch/arm/mach-ks8695/include/mach/memory.h
@@ -18,7 +18,7 @@
 /*
  * Physical SRAM offset.
  */
-#define PHYS_OFFSET		KS8695_SDRAM_PA
+#define PLAT_PHYS_OFFSET		KS8695_SDRAM_PA
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
deleted file mode 100644
index 9be7466..0000000
--- a/arch/arm/mach-lh7a40x/Kconfig
+++ /dev/null
@@ -1,74 +0,0 @@
-if ARCH_LH7A40X
-
-menu "LH7A40X Implementations"
-
-config MACH_KEV7A400
-	bool "KEV7A400"
-	select ARCH_LH7A400
-	help
-	  Say Y here if you are using the Sharp KEV7A400 development
-	  board.  This hardware is discontinued, so I'd be very
-	  surprised if you wanted this option.
-
-config MACH_LPD7A400
-	bool "LPD7A400 Card Engine"
-	select ARCH_LH7A400
-#	select IDE_POLL
-#	select HAS_TOUCHSCREEN_ADS7843_LH7
-	help
-	  Say Y here if you are using Logic Product Development's
-	  LPD7A400 CardEngine.  For the time being, the LPD7A400 and
-	  LPD7A404 options are mutually exclusive.
-
-config MACH_LPD7A404
-	bool "LPD7A404 Card Engine"
-	select ARCH_LH7A404
-#	select IDE_POLL
-#	select HAS_TOUCHSCREEN_ADC_LH7
-	help
-	  Say Y here if you are using Logic Product Development's
-	  LPD7A404 CardEngine. For the time being, the LPD7A400 and
-	  LPD7A404 options are mutually exclusive.
-
-config ARCH_LH7A400
-	bool
-
-config ARCH_LH7A404
-	bool
-
-config LPD7A40X_CPLD_SSP
-	bool
-
-config LH7A40X_CONTIGMEM
-	bool "Disable NUMA/SparseMEM Support"
-	help
-	  Say Y here if your bootloader sets the SROMLL bit(s) in
-	  the SDRAM controller, organizing memory as a contiguous
-	  array.  This option will disable sparse memory support
-          and force the kernel to manage all memory in one node.
-
-	  Setting this option incorrectly may prevent the kernel
-	  from booting.  It is OK to leave it N.
-
-	  For more information, consult
-	    <file:Documentation/arm/Sharp-LH/SDRAM>.
-
-config LH7A40X_ONE_BANK_PER_NODE
-	bool "Optimize NUMA Node Tables for Size"
-	depends on !LH7A40X_CONTIGMEM
-	help
-	  Say Y here to produce compact memory node tables.  By
-	  default pairs of adjacent physical RAM banks are managed
-	  together in a single node, incurring some wasted overhead
-	  in the node tables, however also maintaining compatibility
-	  with systems where physical memory is truly contiguous.
-
-	  Setting this option incorrectly may prevent the kernel from
-	  booting.  It is OK to leave it N.
-
-	  For more information, consult
-	    <file:Documentation/arm/Sharp-LH/SDRAM>.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile
deleted file mode 100644
index 94b8615..0000000
--- a/arch/arm/mach-lh7a40x/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y				:= time.o clocks.o
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-obj-$(CONFIG_MACH_KEV7A400)	+= arch-kev7a400.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A400)	+= arch-lpd7a40x.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A404)	+= arch-lpd7a40x.o irq-lh7a404.o
-obj-$(CONFIG_LPD7A40X_CPLD_SSP)	+= ssp-cpld.o
-obj-$(CONFIG_FB_ARMCLCD)	+= clcd.o
-
diff --git a/arch/arm/mach-lh7a40x/Makefile.boot b/arch/arm/mach-lh7a40x/Makefile.boot
deleted file mode 100644
index af941be..0000000
--- a/arch/arm/mach-lh7a40x/Makefile.boot
+++ /dev/null
@@ -1,4 +0,0 @@
-   zreladdr-y	:= 0xc0008000
-params_phys-y	:= 0xc0000100
-initrd_phys-y	:= 0xc4000000
-
diff --git a/arch/arm/mach-lh7a40x/arch-kev7a400.c b/arch/arm/mach-lh7a40x/arch-kev7a400.c
deleted file mode 100644
index 71129c3..0000000
--- a/arch/arm/mach-lh7a40x/arch-kev7a400.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* arch/arm/mach-lh7a40x/arch-kev7a400.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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/tty.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-      /* This function calls the board specific IRQ initialization function. */
-
-static struct map_desc kev7a400_io_desc[] __initdata = {
-	{
-		.virtual	= IO_VIRT,
-		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD_VIRT,
-		.pfn		= __phys_to_pfn(CPLD_PHYS),
-		.length		= CPLD_SIZE,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init kev7a400_map_io(void)
-{
-	iotable_init (kev7a400_io_desc, ARRAY_SIZE (kev7a400_io_desc));
-}
-
-static u16 CPLD_IRQ_mask;	/* Mask for CPLD IRQs, 1 == unmasked */
-
-static void kev7a400_ack_cpld_irq(struct irq_data *d)
-{
-	CPLD_CL_INT = 1 << (d->irq - IRQ_KEV7A400_CPLD);
-}
-
-static void kev7a400_mask_cpld_irq(struct irq_data *d)
-{
-	CPLD_IRQ_mask &= ~(1 << (d->irq - IRQ_KEV7A400_CPLD));
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static void kev7a400_unmask_cpld_irq(struct irq_data *d)
-{
-	CPLD_IRQ_mask |= 1 << (d->irq - IRQ_KEV7A400_CPLD);
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static struct irq_chip kev7a400_cpld_chip = {
-	.name		= "CPLD",
-	.irq_ack	= kev7a400_ack_cpld_irq,
-	.irq_mask	= kev7a400_mask_cpld_irq,
-	.irq_unmask	= kev7a400_unmask_cpld_irq,
-};
-
-
-static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	u32 mask = CPLD_LATCHED_INTS;
-	irq = IRQ_KEV7A400_CPLD;
-	for (; mask; mask >>= 1, ++irq)
-		if (mask & 1)
-			generic_handle_irq(irq);
-}
-
-void __init lh7a40x_init_board_irq (void)
-{
-	int irq;
-
-	for (irq = IRQ_KEV7A400_CPLD;
-	     irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) {
-		set_irq_chip (irq, &kev7a400_cpld_chip);
-		set_irq_handler (irq, handle_edge_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-	set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
-
-		/* Clear all CPLD interrupts */
-	CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
-
-	GPIO_GPIOINTEN = 0;		/* Disable all GPIO interrupts */
-	barrier();
-
-#if 0
-	GPIO_INTTYPE1
-		= (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
-	GPIO_INTTYPE2 = 0;		/* Falling edge & low-level */
-	GPIO_GPIOFEOI = 0xff;		/* Clear all GPIO interrupts */
-	GPIO_GPIOINTEN = 0xff;		/* Enable all GPIO interrupts */
-
-	init_FIQ();
-#endif
-}
-
-MACHINE_START (KEV7A400, "Sharp KEV7a400")
-	/* Maintainer: Marc Singer */
-	.boot_params	= 0xc0000100,
-	.map_io		= kev7a400_map_io,
-	.init_irq	= lh7a400_init_irq,
-	.timer		= &lh7a40x_timer,
-MACHINE_END
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
deleted file mode 100644
index e735546..0000000
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/* arch/arm/mach-lh7a40x/arch-lpd7a40x.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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/tty.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-#define CPLD_INT_NETHERNET	(1<<0)
-#define CPLD_INTMASK_ETHERNET	(1<<2)
-#if defined (CONFIG_MACH_LPD7A400)
-# define CPLD_INT_NTOUCH		(1<<1)
-# define CPLD_INTMASK_TOUCH	(1<<3)
-# define CPLD_INT_PEN		(1<<4)
-# define CPLD_INTMASK_PEN	(1<<4)
-# define CPLD_INT_PIRQ		(1<<4)
-#endif
-#define CPLD_INTMASK_CPLD	(1<<7)
-#define CPLD_INT_CPLD		(1<<6)
-
-#define CPLD_CONTROL_SWINT		(1<<7) /* Disable all CPLD IRQs */
-#define CPLD_CONTROL_OCMSK		(1<<6) /* Mask USB1 connect IRQ */
-#define CPLD_CONTROL_PDRV		(1<<5) /* PCC_nDRV high */
-#define CPLD_CONTROL_USB1C		(1<<4) /* USB1 connect IRQ active */
-#define CPLD_CONTROL_USB1P		(1<<3) /* USB1 power disable */
-#define CPLD_CONTROL_AWKP		(1<<2) /* Auto-wakeup disabled  */
-#define CPLD_CONTROL_LCD_ENABLE		(1<<1) /* LCD Vee enable */
-#define CPLD_CONTROL_WRLAN_NENABLE	(1<<0) /* SMC91x power disable */
-
-
-static struct resource smc91x_resources[] = {
-	[0] = {
-		.start	= CPLD00_PHYS,
-		.end	= CPLD00_PHYS + CPLD00_SIZE - 1, /* Only needs 16B */
-		.flags	= IORESOURCE_MEM,
-	},
-
-	[1] = {
-		.start	= IRQ_LPD7A40X_ETH_INT,
-		.end	= IRQ_LPD7A40X_ETH_INT,
-		.flags	= IORESOURCE_IRQ,
-	},
-
-};
-
-static struct platform_device smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(smc91x_resources),
-	.resource	= smc91x_resources,
-};
-
-static struct resource lh7a40x_usbclient_resources[] = {
-	[0] = {
-		.start	= USB_PHYS,
-		.end	= (USB_PHYS + PAGE_SIZE),
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USB,
-		.end	= IRQ_USB,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
-
-static struct platform_device lh7a40x_usbclient_device = {
-//	.name		= "lh7a40x_udc",
-	.name		= "lh7-udc",
-	.id		= 0,
-	.dev		= {
-		.dma_mask = &lh7a40x_usbclient_dma_mask,
-		.coherent_dma_mask = 0xffffffffUL,
-	},
-	.num_resources	= ARRAY_SIZE (lh7a40x_usbclient_resources),
-	.resource	= lh7a40x_usbclient_resources,
-};
-
-#if defined (CONFIG_ARCH_LH7A404)
-
-static struct resource lh7a404_usbhost_resources [] = {
-	[0] = {
-		.start	= USBH_PHYS,
-		.end	= (USBH_PHYS + 0xFF),
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USHINTR,
-		.end	= IRQ_USHINTR,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 lh7a404_usbhost_dma_mask = 0xffffffffUL;
-
-static struct platform_device lh7a404_usbhost_device = {
-	.name		= "lh7a404-ohci",
-	.id		= 0,
-	.dev		= {
-		.dma_mask = &lh7a404_usbhost_dma_mask,
-		.coherent_dma_mask = 0xffffffffUL,
-	},
-	.num_resources	= ARRAY_SIZE (lh7a404_usbhost_resources),
-	.resource	= lh7a404_usbhost_resources,
-};
-
-#endif
-
-static struct platform_device* lpd7a40x_devs[] __initdata = {
-	&smc91x_device,
-	&lh7a40x_usbclient_device,
-#if defined (CONFIG_ARCH_LH7A404)
-	&lh7a404_usbhost_device,
-#endif
-};
-
-extern void lpd7a400_map_io (void);
-
-static void __init lpd7a40x_init (void)
-{
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_CONTROL |= 0
-		| CPLD_CONTROL_SWINT /* Disable software interrupt */
-		| CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
-	CPLD_CONTROL &= ~(0
-			  | CPLD_CONTROL_LCD_ENABLE	/* Disable LCD */
-			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
-		);
-#endif
-
-#if defined (CONFIG_MACH_LPD7A404)
-	CPLD_CONTROL &= ~(0
-			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
-		);
-#endif
-
-	platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
-#if defined (CONFIG_FB_ARMCLCD)
-        lh7a40x_clcd_init ();
-#endif
-}
-
-static void lh7a40x_ack_cpld_irq(struct irq_data *d)
-{
-	/* CPLD doesn't have ack capability, but some devices may */
-
-#if defined (CPLD_INTMASK_TOUCH)
-	/* The touch control *must* mask the interrupt because the
-	 * interrupt bit is read by the driver to determine if the pen
-	 * is still down. */
-	if (d->irq == IRQ_TOUCH)
-		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
-#endif
-}
-
-static void lh7a40x_mask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
-		break;
-#if defined (IRQ_TOUCH)
-	case IRQ_TOUCH:
-		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
-		break;
-#endif
-	}
-}
-
-static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
-		break;
-#if defined (IRQ_TOUCH)
-	case IRQ_TOUCH:
-		CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
-		break;
-#endif
-	}
-}
-
-static struct irq_chip lpd7a40x_cpld_chip = {
-	.name		= "CPLD",
-	.irq_ack	= lh7a40x_ack_cpld_irq,
-	.irq_mask	= lh7a40x_mask_cpld_irq,
-	.irq_unmask	= lh7a40x_unmask_cpld_irq,
-};
-
-static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int mask = CPLD_INTERRUPTS;
-
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-	if ((mask & (1<<0)) == 0)	/* WLAN */
-		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
-
-#if defined (IRQ_TOUCH)
-	if ((mask & (1<<1)) == 0)	/* Touch */
-		generic_handle_irq(IRQ_TOUCH);
-#endif
-
-	/* Level-triggered need this */
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-
-void __init lh7a40x_init_board_irq (void)
-{
-	int irq;
-
-		/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
-		                 PF7 supports the CPLD.
-		   Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
-		                 PF3 supports the CPLD.
-		   (Some) LPD7A404 prerelease boards report a version
-		   number of 0x16, but we force an override since the
-		   hardware is of the newer variety.
-		*/
-
-	unsigned char cpld_version = CPLD_REVISION;
-	int pinCPLD = (cpld_version == 0x28) ? 7 : 3;
-
-#if defined CONFIG_MACH_LPD7A404
-	cpld_version = 0x34;	/* Coerce LPD7A404 to RevB */
-#endif
-
-		/* First, configure user controlled GPIOF interrupts  */
-
-	GPIO_PFDD	&= ~0x0f; /* PF0-3 are inputs */
-	GPIO_INTTYPE1	&= ~0x0f; /* PF0-3 are level triggered */
-	GPIO_INTTYPE2	&= ~0x0f; /* PF0-3 are active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
-
-		/* Then, configure CPLD interrupt */
-
-			/* Disable all CPLD interrupts */
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_INTERRUPTS	= CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
-		| CPLD_INTMASK_ETHERNET;
-	/* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
-               and 4 is uncefined. */
-	// (1<<7)|(1<<4)|(1<<3)|(1<<2);
-#endif
-#if defined (CONFIG_MACH_LPD7A404)
-	CPLD_INTERRUPTS	= CPLD_INTMASK_ETHERNET;
-	/* *** FIXME: don't know why we need 6 and 5, neither is defined. */
-	// (1<<6)|(1<<5)|(1<<3);
-#endif
-	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
-	GPIO_INTTYPE1	&= ~(1 << pinCPLD); /* Level triggered */
-	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
-
-		/* Cascade CPLD interrupts */
-
-	for (irq = IRQ_BOARD_START;
-	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
-		set_irq_chip (irq, &lpd7a40x_cpld_chip);
-		set_irq_handler (irq, handle_level_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler ((cpld_version == 0x28)
-				 ? IRQ_CPLD_V28
-				 : IRQ_CPLD_V34,
-				 lpd7a40x_cpld_handler);
-}
-
-static struct map_desc lpd7a40x_io_desc[] __initdata = {
-	{
-		.virtual	= IO_VIRT,
-		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	},
-	{	/* Mapping added to work around chip select problems */
-		.virtual	= IOBARRIER_VIRT,
-		.pfn		= __phys_to_pfn(IOBARRIER_PHYS),
-		.length		= IOBARRIER_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CF_VIRT,
-		.pfn		= __phys_to_pfn(CF_PHYS),
-		.length		= CF_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD02_VIRT,
-		.pfn		= __phys_to_pfn(CPLD02_PHYS),
-		.length		= CPLD02_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD06_VIRT,
-		.pfn		= __phys_to_pfn(CPLD06_PHYS),
-		.length		= CPLD06_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD08_VIRT,
-		.pfn		= __phys_to_pfn(CPLD08_PHYS),
-		.length		= CPLD08_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD08_VIRT,
-		.pfn		= __phys_to_pfn(CPLD08_PHYS),
-		.length		= CPLD08_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD0A_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0A_PHYS),
-		.length		= CPLD0A_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD0C_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0C_PHYS),
-		.length		= CPLD0C_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD0E_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0E_PHYS),
-		.length		= CPLD0E_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD10_VIRT,
-		.pfn		= __phys_to_pfn(CPLD10_PHYS),
-		.length		= CPLD10_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD12_VIRT,
-		.pfn		= __phys_to_pfn(CPLD12_PHYS),
-		.length		= CPLD12_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD14_VIRT,
-		.pfn		= __phys_to_pfn(CPLD14_PHYS),
-		.length		= CPLD14_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD16_VIRT,
-		.pfn		= __phys_to_pfn(CPLD16_PHYS),
-		.length		= CPLD16_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD18_VIRT,
-		.pfn		= __phys_to_pfn(CPLD18_PHYS),
-		.length		= CPLD18_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD1A_VIRT,
-		.pfn		= __phys_to_pfn(CPLD1A_PHYS),
-		.length		= CPLD1A_SIZE,
-		.type		= MT_DEVICE
-	},
-};
-
-void __init
-lpd7a40x_map_io(void)
-{
-	iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
-}
-
-#ifdef CONFIG_MACH_LPD7A400
-
-MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
-	/* Maintainer: Marc Singer */
-	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a40x_map_io,
-	.init_irq	= lh7a400_init_irq,
-	.timer		= &lh7a40x_timer,
-	.init_machine	= lpd7a40x_init,
-MACHINE_END
-
-#endif
-
-#ifdef CONFIG_MACH_LPD7A404
-
-MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
-	/* Maintainer: Marc Singer */
-	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a40x_map_io,
-	.init_irq	= lh7a404_init_irq,
-	.timer		= &lh7a40x_timer,
-	.init_machine	= lpd7a40x_init,
-MACHINE_END
-
-#endif
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
deleted file mode 100644
index 7fe4fd3..0000000
--- a/arch/arm/mach-lh7a40x/clcd.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- *  arch/arm/mach-lh7a40x/clcd.c
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  This program is free software; you can 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/gfp.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-
-//#include <linux/module.h>
-//#include <linux/time.h>
-
-//#include <asm/mach/time.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <asm/system.h>
-#include <mach/hardware.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#define HRTFTC_HRSETUP		__REG(HRTFTC_PHYS + 0x00)
-#define HRTFTC_HRCON		__REG(HRTFTC_PHYS + 0x04)
-#define HRTFTC_HRTIMING1	__REG(HRTFTC_PHYS + 0x08)
-#define HRTFTC_HRTIMING2	__REG(HRTFTC_PHYS + 0x0c)
-
-#define ALI_SETUP		__REG(ALI_PHYS + 0x00)
-#define ALI_CONTROL		__REG(ALI_PHYS + 0x04)
-#define ALI_TIMING1		__REG(ALI_PHYS + 0x08)
-#define ALI_TIMING2		__REG(ALI_PHYS + 0x0c)
-
-#include "lcd-panel.h"
-
-static void lh7a40x_clcd_disable (struct clcd_fb *fb)
-{
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_CONTROL &= ~(1<<1);	/* Disable LCD Vee */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A404)
-	GPIO_PCD  &= ~(1<<3);		/* Disable LCD Vee */
-#endif
-
-#if defined (CONFIG_ARCH_LH7A400)
-	HRTFTC_HRSETUP &= ~(1<<13);	/* Disable HRTFT controller */
-#endif
-
-#if defined (CONFIG_ARCH_LH7A404)
-	ALI_SETUP &= ~(1<<13);		/* Disable ALI */
-#endif
-}
-
-static void lh7a40x_clcd_enable (struct clcd_fb *fb)
-{
-	struct clcd_panel_extra* extra
-		= (struct clcd_panel_extra*) fb->board_data;
-
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_CONTROL |= (1<<1);		/* Enable LCD Vee */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A404)
-	GPIO_PCDD &= ~(1<<3);		/* Enable LCD Vee */
-	GPIO_PCD  |=  (1<<3);
-#endif
-
-#if defined (CONFIG_ARCH_LH7A400)
-
-	if (extra) {
-		HRTFTC_HRSETUP
-			= (1 << 13)
-			| ((fb->fb.var.xres - 1) << 4)
-			| 0xc
-			| (extra->hrmode ? 1 : 0);
-		HRTFTC_HRCON
-			= ((extra->clsen ? 1 : 0) << 1)
-			| ((extra->spsen ? 1 : 0) << 0);
-		HRTFTC_HRTIMING1
-			= (extra->pcdel << 8)
-			| (extra->revdel << 4)
-			| (extra->lpdel << 0);
-		HRTFTC_HRTIMING2
-			= (extra->spldel << 9)
-			| (extra->pc2del << 0);
-	}
-	else
-		HRTFTC_HRSETUP
-			= (1 << 13)
-			| 0xc;
-#endif
-
-#if defined (CONFIG_ARCH_LH7A404)
-
-	if (extra) {
-		ALI_SETUP
-			= (1 << 13)
-			| ((fb->fb.var.xres - 1) << 4)
-			| 0xc
-			| (extra->hrmode ? 1 : 0);
-		ALI_CONTROL
-			= ((extra->clsen ? 1 : 0) << 1)
-			| ((extra->spsen ? 1 : 0) << 0);
-		ALI_TIMING1
-			= (extra->pcdel << 8)
-			| (extra->revdel << 4)
-			| (extra->lpdel << 0);
-		ALI_TIMING2
-			= (extra->spldel << 9)
-			| (extra->pc2del << 0);
-	}
-	else
-		ALI_SETUP
-			= (1 << 13)
-			| 0xc;
-#endif
-
-}
-
-#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
-
-static int lh7a40x_clcd_setup (struct clcd_fb *fb)
-{
-	dma_addr_t dma;
-	u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
-			     *(lcd_panel.bpp/8));
-
-	fb->panel = &lcd_panel;
-
-		/* Enforce the sync polarity defaults */
-	if (!(fb->panel->tim2 & TIM2_IHS))
-		fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (!(fb->panel->tim2 & TIM2_IVS))
-		fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
-
-#if defined (HAS_LCD_PANEL_EXTRA)
-	fb->board_data = &lcd_panel_extra;
-#endif
-
-	fb->fb.screen_base
-		= dma_alloc_writecombine (&fb->dev->dev, len,
-					  &dma, GFP_KERNEL);
-	printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
-		fb->fb.screen_base, (void*) dma, len,
-		(void*) io_p2v (CLCDC_PHYS));
-	printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
-
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
-	}
-
-#if defined (USE_RGB555)
-	fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
-#endif
-
-	fb->fb.fix.smem_start = dma;
-	fb->fb.fix.smem_len = len;
-
-		/* Drive PE4 high to prevent CPLD crash */
-	GPIO_PEDD |= (1<<4);
-	GPIO_PED  |= (1<<4);
-
-	GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
-
-//	fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
-//	fb->fb.fbops->fb_set_par (&fb->fb);
-
-	return 0;
-}
-
-static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-				     fb->fb.screen_base,
-				     fb->fb.fix.smem_start,
-				     fb->fb.fix.smem_len);
-}
-
-static void lh7a40x_clcd_remove (struct clcd_fb *fb)
-{
-	dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
-			       fb->fb.screen_base, fb->fb.fix.smem_start);
-}
-
-static struct clcd_board clcd_platform_data = {
-	.name		= "lh7a40x FB",
-	.check		= clcdfb_check,
-	.decode		= clcdfb_decode,
-	.enable		= lh7a40x_clcd_enable,
-	.setup		= lh7a40x_clcd_setup,
-	.mmap		= lh7a40x_clcd_mmap,
-	.remove		= lh7a40x_clcd_remove,
-	.disable	= lh7a40x_clcd_disable,
-};
-
-#define IRQ_CLCDC (IRQ_LCDINTR)
-
-#define AMBA_DEVICE(name,busid,base,plat,pid)			\
-static struct amba_device name##_device = {			\
-	.dev = {						\
-		.coherent_dma_mask = ~0,			\
-		.init_name = busid,				\
-		.platform_data = plat,				\
-		},						\
-	.res = {						\
-		.start	= base##_PHYS,				\
-		.end	= (base##_PHYS) + (4*1024) - 1,		\
-		.flags	= IORESOURCE_MEM,			\
-		},						\
-	.dma_mask	= ~0,					\
-	.irq		= { IRQ_##base, },			\
-	/* .dma		= base##_DMA,*/				\
-	.periphid = pid,					\
-}
-
-AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
-
-static struct amba_device *amba_devs[] __initdata = {
-	&clcd_device,
-};
-
-void __init lh7a40x_clcd_init (void)
-{
-	int i;
-	int result;
-	printk ("CLCD: registering amba devices\n");
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		result = amba_device_register(d, &iomem_resource);
-		printk ("  %d -> %d\n", i ,result);
-	}
-}
diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c
deleted file mode 100644
index 0651f96..0000000
--- a/arch/arm/mach-lh7a40x/clocks.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* arch/arm/mach-lh7a40x/clocks.c
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  version 2 as published by the Free Software Foundation.
- *
- */
-#include <mach/hardware.h>
-#include <mach/clocks.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/string.h>
-
-struct module;
-
-struct clk {
-	struct list_head node;
-	unsigned long rate;
-	struct module *owner;
-	const char *name;
-};
-
-/* ----- */
-
-#define MAINDIV1(c)	(((c) >>  7) & 0x0f)
-#define MAINDIV2(c)	(((c) >> 11) & 0x1f)
-#define PS(c)		(((c) >> 18) & 0x03)
-#define PREDIV(c)	(((c) >>  2) & 0x1f)
-#define HCLKDIV(c)	(((c) >>  0) & 0x02)
-#define PCLKDIV(c)	(((c) >> 16) & 0x03)
-
-unsigned int fclkfreq_get (void)
-{
-	unsigned int clkset = CSC_CLKSET;
-	unsigned int gclk
-		= XTAL_IN
-		/ (1 << PS(clkset))
-		* (MAINDIV1(clkset) + 2)
-		/ (PREDIV(clkset)   + 2)
-		* (MAINDIV2(clkset) + 2)
-		;
-	return gclk;
-}
-
-unsigned int hclkfreq_get (void)
-{
-	unsigned int clkset = CSC_CLKSET;
-	unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
-
-	return hclk;
-}
-
-unsigned int pclkfreq_get (void)
-{
-	unsigned int clkset = CSC_CLKSET;
-	int pclkdiv = PCLKDIV(clkset);
-	unsigned int pclk;
-	if (pclkdiv == 0x3)
-		pclkdiv = 0x2;
-	pclk = hclkfreq_get () / (1 << pclkdiv);
-
-	return pclk;
-}
-
-/* ----- */
-
-struct clk *clk_get (struct device *dev, const char *id)
-{
-	return dev && strcmp(dev_name(dev), "cldc-lh7a40x") == 0
-		 ? NULL : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put (struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-int clk_enable (struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable (struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate (struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-long clk_round_rate (struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate (struct clk *clk, unsigned long rate)
-{
-	return -EIO;
-}
-EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
deleted file mode 100644
index 6ed3f6b..0000000
--- a/arch/arm/mach-lh7a40x/common.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* arch/arm/mach-lh7a40x/common.h
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  version 2 as published by the Free Software Foundation.
- *
- */
-
-extern struct sys_timer lh7a40x_timer;
-
-extern void lh7a400_init_irq (void);
-extern void lh7a404_init_irq (void);
-extern void lh7a40x_clcd_init (void);
-extern void lh7a40x_init_board_irq (void);
-
diff --git a/arch/arm/mach-lh7a40x/include/mach/clocks.h b/arch/arm/mach-lh7a40x/include/mach/clocks.h
deleted file mode 100644
index fe2e025..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/clocks.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/clocks.h
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  This program is free software; you can 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_CLOCKS_H
-#define __ASM_ARCH_CLOCKS_H
-
-unsigned int fclkfreq_get (void);
-unsigned int hclkfreq_get (void);
-unsigned int pclkfreq_get (void);
-
-#endif  /* _ASM_ARCH_CLOCKS_H */
diff --git a/arch/arm/mach-lh7a40x/include/mach/constants.h b/arch/arm/mach-lh7a40x/include/mach/constants.h
deleted file mode 100644
index 55c6edb..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/constants.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/constants.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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_CONSTANTS_H
-#define __ASM_ARCH_CONSTANTS_H
-
-
-/* Addressing constants */
-
-	/* SoC CPU IO addressing */
-#define IO_PHYS			(0x80000000)
-#define IO_VIRT			(0xf8000000)
-#define IO_SIZE			(0x0000B000)
-
-#ifdef CONFIG_MACH_KEV7A400
-# define CPLD_PHYS		(0x20000000)
-# define CPLD_VIRT		(0xf2000000)
-# define CPLD_SIZE		PAGE_SIZE
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-
-# define IOBARRIER_PHYS		0x10000000 /* Second bank, fastest timing */
-# define IOBARRIER_VIRT		0xf0000000
-# define IOBARRIER_SIZE		PAGE_SIZE
-
-# define CF_PHYS		0x60200000
-# define CF_VIRT		0xf6020000
-# define CF_SIZE		(8*1024)
-
-	/* The IO mappings for the LPD CPLD are, unfortunately, sparse.  */
-# define CPLDX_PHYS(x)		(0x70000000 | ((x) << 20))
-# define CPLDX_VIRT(x)		(0xf7000000 | ((x) << 16))
-# define CPLD00_PHYS		CPLDX_PHYS (0x00) /* Wired LAN */
-# define CPLD00_VIRT		CPLDX_VIRT (0x00)
-# define CPLD00_SIZE		PAGE_SIZE
-# define CPLD02_PHYS		CPLDX_PHYS (0x02)
-# define CPLD02_VIRT		CPLDX_VIRT (0x02)
-# define CPLD02_SIZE		PAGE_SIZE
-# define CPLD06_PHYS		CPLDX_PHYS (0x06)
-# define CPLD06_VIRT		CPLDX_VIRT (0x06)
-# define CPLD06_SIZE		PAGE_SIZE
-# define CPLD08_PHYS		CPLDX_PHYS (0x08)
-# define CPLD08_VIRT		CPLDX_VIRT (0x08)
-# define CPLD08_SIZE		PAGE_SIZE
-# define CPLD0A_PHYS		CPLDX_PHYS (0x0a)
-# define CPLD0A_VIRT		CPLDX_VIRT (0x0a)
-# define CPLD0A_SIZE		PAGE_SIZE
-# define CPLD0C_PHYS		CPLDX_PHYS (0x0c)
-# define CPLD0C_VIRT		CPLDX_VIRT (0x0c)
-# define CPLD0C_SIZE		PAGE_SIZE
-# define CPLD0E_PHYS		CPLDX_PHYS (0x0e)
-# define CPLD0E_VIRT		CPLDX_VIRT (0x0e)
-# define CPLD0E_SIZE		PAGE_SIZE
-# define CPLD10_PHYS		CPLDX_PHYS (0x10)
-# define CPLD10_VIRT		CPLDX_VIRT (0x10)
-# define CPLD10_SIZE		PAGE_SIZE
-# define CPLD12_PHYS		CPLDX_PHYS (0x12)
-# define CPLD12_VIRT		CPLDX_VIRT (0x12)
-# define CPLD12_SIZE		PAGE_SIZE
-# define CPLD14_PHYS		CPLDX_PHYS (0x14)
-# define CPLD14_VIRT		CPLDX_VIRT (0x14)
-# define CPLD14_SIZE		PAGE_SIZE
-# define CPLD16_PHYS		CPLDX_PHYS (0x16)
-# define CPLD16_VIRT		CPLDX_VIRT (0x16)
-# define CPLD16_SIZE		PAGE_SIZE
-# define CPLD18_PHYS		CPLDX_PHYS (0x18)
-# define CPLD18_VIRT		CPLDX_VIRT (0x18)
-# define CPLD18_SIZE		PAGE_SIZE
-# define CPLD1A_PHYS		CPLDX_PHYS (0x1a)
-# define CPLD1A_VIRT		CPLDX_VIRT (0x1a)
-# define CPLD1A_SIZE		PAGE_SIZE
-#endif
-
-	/* Timing constants */
-
-#define	XTAL_IN			14745600	/* 14.7456 MHz crystal */
-#define PLL_CLOCK		(XTAL_IN * 21)	/* 309 MHz PLL clock */
-#define MAX_HCLK_KHZ		100000		/* HCLK max limit ~100MHz */
-#define HCLK			(99993600)
-//#define HCLK			(119808000)
-
-#endif /* __ASM_ARCH_CONSTANTS_H */
diff --git a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S b/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
deleted file mode 100644
index cff3362..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/* arch/arm/mach-lh7a40x/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.
- *
-*/
-
-	@ It is not known if this will be appropriate for every 40x
-	@ board.
-
-		.macro  addruart, rp, rv
-		mov     \rp, #0x00000700        @ offset from base
-		orr     \rv, \rp, #0xf8000000   @ virtual base
-		orr     \rp, \rp, #0x80000000   @ physical base
-		.endm
-
-		.macro  senduart,rd,rx
-		strb    \rd, [\rx]              @ DATA
-		.endm
-
-		.macro  busyuart,rd,rx          @ spin while busy
-1001:		ldr     \rd, [\rx, #0x10]       @ STATUS
-		tst     \rd, #1 << 3            @ BUSY (TX FIFO not empty)
-		bne     1001b                   @ yes, spin
-		.endm
-
-		.macro  waituart,rd,rx          @ wait for Tx FIFO room
-1001:		ldrb    \rd, [\rx, #0x10]       @ STATUS
-		tst     \rd, #1 << 5            @ TXFF (TX FIFO full)
-		bne     1001b                   @ yes, spin
-		.endm
diff --git a/arch/arm/mach-lh7a40x/include/mach/dma.h b/arch/arm/mach-lh7a40x/include/mach/dma.h
deleted file mode 100644
index baa3f8d..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/dma.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/dma.h
- *
- *  Copyright (C) 2005 Marc Singer
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  version 2 as published by the Free Software Foundation.
- *
- */
-
-typedef enum {
-	DMA_M2M0	= 0,
-	DMA_M2M1	= 1,
-	DMA_M2P0	= 2,	/* Tx */
-	DMA_M2P1	= 3,	/* Rx */
-	DMA_M2P2	= 4,	/* Tx */
-	DMA_M2P3	= 5,	/* Rx */
-	DMA_M2P4	= 6,	/* Tx - AC97 */
-	DMA_M2P5	= 7,	/* Rx - AC97 */
-	DMA_M2P6	= 8,	/* Tx */
-	DMA_M2P7	= 9,	/* Rx */
-} dma_device_t;
-
-#define DMA_LENGTH_MAX		((64*1024) - 4) /* bytes */
-
-#define DMAC_GCA		__REG(DMAC_PHYS + 0x2b80)
-#define DMAC_GIR		__REG(DMAC_PHYS + 0x2bc0)
-
-#define DMAC_GIR_MMI1		(1<<11)
-#define DMAC_GIR_MMI0		(1<<10)
-#define DMAC_GIR_MPI8		(1<<9)
-#define DMAC_GIR_MPI9		(1<<8)
-#define DMAC_GIR_MPI6		(1<<7)
-#define DMAC_GIR_MPI7		(1<<6)
-#define DMAC_GIR_MPI4		(1<<5)
-#define DMAC_GIR_MPI5		(1<<4)
-#define DMAC_GIR_MPI2		(1<<3)
-#define DMAC_GIR_MPI3		(1<<2)
-#define DMAC_GIR_MPI0		(1<<1)
-#define DMAC_GIR_MPI1		(1<<0)
-
-#define DMAC_M2P0		0x0000
-#define DMAC_M2P1		0x0040
-#define DMAC_M2P2		0x0080
-#define DMAC_M2P3		0x00c0
-#define DMAC_M2P4		0x0240
-#define DMAC_M2P5		0x0200
-#define DMAC_M2P6		0x02c0
-#define DMAC_M2P7		0x0280
-#define DMAC_M2P8		0x0340
-#define DMAC_M2P9		0x0300
-#define DMAC_M2M0		0x0100
-#define DMAC_M2M1		0x0140
-
-#define DMAC_P_PCONTROL(c)	__REG(DMAC_PHYS + (c) + 0x00)
-#define DMAC_P_PINTERRUPT(c)	__REG(DMAC_PHYS + (c) + 0x04)
-#define DMAC_P_PPALLOC(c)	__REG(DMAC_PHYS + (c) + 0x08)
-#define DMAC_P_PSTATUS(c)	__REG(DMAC_PHYS + (c) + 0x0c)
-#define DMAC_P_REMAIN(c)	__REG(DMAC_PHYS + (c) + 0x14)
-#define DMAC_P_MAXCNT0(c)	__REG(DMAC_PHYS + (c) + 0x20)
-#define DMAC_P_BASE0(c)		__REG(DMAC_PHYS + (c) + 0x24)
-#define DMAC_P_CURRENT0(c)	__REG(DMAC_PHYS + (c) + 0x28)
-#define DMAC_P_MAXCNT1(c)	__REG(DMAC_PHYS + (c) + 0x30)
-#define DMAC_P_BASE1(c)		__REG(DMAC_PHYS + (c) + 0x34)
-#define DMAC_P_CURRENT1(c)	__REG(DMAC_PHYS + (c) + 0x38)
-
-#define DMAC_PCONTROL_ENABLE	(1<<4)
-
-#define DMAC_PORT_USB		0
-#define DMAC_PORT_SDMMC		1
-#define DMAC_PORT_AC97_1	2
-#define DMAC_PORT_AC97_2	3
-#define DMAC_PORT_AC97_3	4
-#define DMAC_PORT_UART1		6
-#define DMAC_PORT_UART2		7
-#define DMAC_PORT_UART3		8
-
-#define DMAC_PSTATUS_CURRSTATE_SHIFT	4
-#define DMAC_PSTATUS_CURRSTATE_MASK	0x3
-
-#define DMAC_PSTATUS_NEXTBUF	 (1<<6)
-#define DMAC_PSTATUS_STALLRINT	 (1<<0)
-
-#define DMAC_INT_CHE		 (1<<3)
-#define DMAC_INT_NFB		 (1<<1)
-#define DMAC_INT_STALL		 (1<<0)
diff --git a/arch/arm/mach-lh7a40x/include/mach/entry-macro.S b/arch/arm/mach-lh7a40x/include/mach/entry-macro.S
deleted file mode 100644
index 069bb4c..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/entry-macro.S
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * arch/arm/mach-lh7a40x/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for LH7A40x platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-
-/* In order to allow there to be support for both of the processor
-   classes at the same time, we make a hack here that isn't very
-   pretty.  At startup, the link pointed to with the
-   branch_irq_lh7a400 symbol is replaced with a NOP when the CPU is
-   detected as a lh7a404.
-
-   *** FIXME: we should clean this up so that there is only one
-	      implementation for each CPU's design.
-
-*/
-
-#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-branch_irq_lh7a400: b 1000f
-
-@ Implementation of the LH7A404 get_irqnr_and_base.
-
-		mov	\irqnr, #0			@ VIC1 irq base
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		add	\base, \base, #0x8000
-		ldr	\tmp, [\base, #0x0030]		@ VIC1_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		tst	\tmp, #VA_VIC1DEFAULT		@ Default vectored VIC1
-		ldrne	\irqstat, [\base, #0]		@ VIC1_IRQSTATUS
-		bne	1001f
-		add	\base, \base, #(0xa000 - 0x8000)
-		ldr	\tmp, [\base, #0x0030]		@ VIC2_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		ldr	\irqstat, [\base, #0]		@ VIC2_IRQSTATUS
-		mov	\irqnr, #32			@ VIC2 irq base
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1002:		and	\irqnr, \tmp, #0x3f		@ Mask for valid bits
-1008:		movs	\irqstat, #1			@ Force !Z
-		str	\tmp, [\base, #0x0030]		@ Clear vector
-		b	1009f
-
-@ Implementation of the LH7A400 get_irqnr_and_base.
-
-1000:		mov	\irqnr, #0
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		ldr	\irqstat, [\base, #0x500]	@ PIC INTSR
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1008:		movs	\irqstat, #1			@ Force !Z
-
-1009:
-               .endm
-
-
-
-#elif defined (CONFIG_ARCH_LH7A400)
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		mov	\irqnr, #0
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		ldr	\irqstat, [\base, #0x500]	@ PIC INTSR
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1008:		movs	\irqstat, #1			@ Force !Z
-1009:
-               .endm
-
-#elif defined(CONFIG_ARCH_LH7A404)
-
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
-		mov	\irqnr, #0			@ VIC1 irq base
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		add	\base, \base, #0x8000
-		ldr	\tmp, [\base, #0x0030]		@ VIC1_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		tst	\tmp, #VA_VIC1DEFAULT		@ Default vectored VIC1
-		ldrne	\irqstat, [\base, #0]		@ VIC1_IRQSTATUS
-		bne	1001f
-		add	\base, \base, #(0xa000 - 0x8000)
-		ldr	\tmp, [\base, #0x0030]		@ VIC2_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		ldr	\irqstat, [\base, #0]		@ VIC2_IRQSTATUS
-		mov	\irqnr, #32			@ VIC2 irq base
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1002:		and	\irqnr, \tmp, #0x3f		@ Mask for valid bits
-1008:		movs	\irqstat, #1			@ Force !Z
-		str	\tmp, [\base, #0x0030]		@ Clear vector
-1009:
-               .endm
-#endif
-
-
diff --git a/arch/arm/mach-lh7a40x/include/mach/hardware.h b/arch/arm/mach-lh7a40x/include/mach/hardware.h
deleted file mode 100644
index 59d2ace..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/hardware.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/hardware.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  [ Substantially cribbed from arch/arm/mach-pxa/include/mach/hardware.h ]
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  version 2 as published by the Free Software Foundation.
- *
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>		/* Added for the sake of amba-clcd driver */
-
-#define io_p2v(x) (0xf0000000 | (((x) & 0xfff00000) >> 4) | ((x) & 0x0000ffff))
-#define io_v2p(x) (             (((x) & 0x0fff0000) << 4) | ((x) & 0x0000ffff))
-
-#ifdef __ASSEMBLY__
-
-# define __REG(x)	io_p2v(x)
-# define __PREG(x)	io_v2p(x)
-
-#else
-
-# if 0
-#  define __REG(x)	(*((volatile u32 *)io_p2v(x)))
-# else
-/*
- * This __REG() version gives the same results as the one above,  except
- * that we are fooling gcc somehow so it generates far better and smaller
- * assembly code for access to contiguous registers.  It's a shame that gcc
- * doesn't guess this by itself.
- */
-#include <asm/types.h>
-typedef struct { volatile u32 offset[4096]; } __regbase;
-# define __REGP(x)	((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
-# define __REG(x)	__REGP(io_p2v(x))
-typedef struct { volatile u16 offset[4096]; } __regbase16;
-# define __REGP16(x)	((__regbase16 *)((x)&~4095))->offset[((x)&4095)>>1]
-# define __REG16(x)	__REGP16(io_p2v(x))
-typedef struct { volatile u8 offset[4096]; } __regbase8;
-# define __REGP8(x)	((__regbase8 *)((x)&~4095))->offset[(x)&4095]
-# define __REG8(x)	__REGP8(io_p2v(x))
-#endif
-
-/* Let's kick gcc's ass again... */
-# define __REG2(x,y)	\
-	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
-				  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
-
-# define __PREG(x)	(io_v2p((u32)&(x)))
-
-#endif
-
-#define MASK_AND_SET(v,m,s)	(v) = ((v)&~(m))|(s)
-
-#include "registers.h"
-
-#endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-lh7a40x/include/mach/io.h b/arch/arm/mach-lh7a40x/include/mach/io.h
deleted file mode 100644
index 6ece459..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/io.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/io.h
- *
- *  Copyright (C) 2004 Coastal Environmental 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 __ASM_ARCH_IO_H
-#define __ASM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/* No ISA or PCI bus on this machine. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#endif /* __ASM_ARCH_IO_H */
diff --git a/arch/arm/mach-lh7a40x/include/mach/irqs.h b/arch/arm/mach-lh7a40x/include/mach/irqs.h
deleted file mode 100644
index 0f9b836..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/irqs.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/irqs.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  version 2 as published by the Free Software Foundation.
- *
- */
-
-/* It is to be seen whether or not we can build a kernel for more than
- * one board.  For the time being, these macros assume that we cannot.
- * Thus, it is OK to ifdef machine/board specific IRQ assignments.
- */
-
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-
-#define FIQ_START	80
-
-#if defined (CONFIG_ARCH_LH7A400)
-
-  /* FIQs */
-
-# define IRQ_GPIO0FIQ	0	/* GPIO External FIQ Interrupt on F0 */
-# define IRQ_BLINT	1	/* Battery Low */
-# define IRQ_WEINT	2	/* Watchdog Timer, WDT overflow	*/
-# define IRQ_MCINT	3	/* Media Change, MEDCHG pin rising */
-
-  /* IRQs */
-
-# define IRQ_CSINT	4	/* Audio Codec (ACI) */
-# define IRQ_GPIO1INTR	5	/* GPIO External IRQ Interrupt on F1 */
-# define IRQ_GPIO2INTR	6	/* GPIO External IRQ Interrupt on F2 */
-# define IRQ_GPIO3INTR	7	/* GPIO External IRQ Interrupt on F3 */
-# define IRQ_T1UI	8	/* Timer 1 underflow */
-# define IRQ_T2UI	9	/* Timer 2 underflow */
-# define IRQ_RTCMI	10
-# define IRQ_TINTR	11	/* Clock State Controller 64 Hz tick (CSC) */
-# define IRQ_UART1INTR	12
-# define IRQ_UART2INTR	13
-# define IRQ_LCDINTR	14
-# define IRQ_SSIEOT	15	/* Synchronous Serial Interface (SSI) */
-# define IRQ_UART3INTR	16
-# define IRQ_SCIINTR	17	/* Smart Card Interface (SCI) */
-# define IRQ_AACINTR	18	/* Advanced Audio Codec (AAC) */
-# define IRQ_MMCINTR	19	/* Multimedia Card (MMC) */
-# define IRQ_USBINTR	20
-# define IRQ_DMAINTR	21
-# define IRQ_T3UI	22	/* Timer 3 underflow */
-# define IRQ_GPIO4INTR	23	/* GPIO External IRQ Interrupt on F4 */
-# define IRQ_GPIO5INTR	24	/* GPIO External IRQ Interrupt on F5 */
-# define IRQ_GPIO6INTR	25	/* GPIO External IRQ Interrupt on F6 */
-# define IRQ_GPIO7INTR	26	/* GPIO External IRQ Interrupt on F7 */
-# define IRQ_BMIINTR	27	/* Battery Monitor Interface (BMI) */
-
-# define NR_IRQ_CPU	28	/* IRQs directly recognized by CPU */
-
-	/* Given IRQ, return GPIO interrupt number 0-7 */
-# define IRQ_TO_GPIO(i)  ((i) \
-	- (((i) > IRQ_GPIO3INTR) ? IRQ_GPIO4INTR - IRQ_GPIO3INTR - 1 : 0)\
-	- (((i) > IRQ_GPIO0INTR) ? IRQ_GPIO1INTR - IRQ_GPIO0INTR - 1 : 0))
-
-#endif
-
-#if defined (CONFIG_ARCH_LH7A404)
-
-# define IRQ_BROWN	0	/* Brownout */
-# define IRQ_WDTINTR	1	/* Watchdog Timer */
-# define IRQ_COMMRX	2	/* ARM Comm Rx for Debug */
-# define IRQ_COMMTX	3	/* ARM Comm Tx for Debug */
-# define IRQ_T1UI	4	/* Timer 1 underflow */
-# define IRQ_T2UI	5	/* Timer 2 underflow */
-# define IRQ_CSINT	6	/* Codec Interrupt (shared by AAC on 404) */
-# define IRQ_DMAM2P0	7	/* -- DMA Memory to Peripheral */
-# define IRQ_DMAM2P1	8
-# define IRQ_DMAM2P2	9
-# define IRQ_DMAM2P3	10
-# define IRQ_DMAM2P4	11
-# define IRQ_DMAM2P5	12
-# define IRQ_DMAM2P6	13
-# define IRQ_DMAM2P7	14
-# define IRQ_DMAM2P8	15
-# define IRQ_DMAM2P9	16
-# define IRQ_DMAM2M0	17	/* -- DMA Memory to Memory */
-# define IRQ_DMAM2M1	18
-# define IRQ_GPIO0INTR	19	/* -- GPIOF Interrupt */
-# define IRQ_GPIO1INTR	20
-# define IRQ_GPIO2INTR	21
-# define IRQ_GPIO3INTR	22
-# define IRQ_SOFT_V1_23	23	/* -- Unassigned */
-# define IRQ_SOFT_V1_24	24
-# define IRQ_SOFT_V1_25	25
-# define IRQ_SOFT_V1_26	26
-# define IRQ_SOFT_V1_27	27
-# define IRQ_SOFT_V1_28	28
-# define IRQ_SOFT_V1_29	29
-# define IRQ_SOFT_V1_30	30
-# define IRQ_SOFT_V1_31	31
-
-# define IRQ_BLINT	32	/* Battery Low */
-# define IRQ_BMIINTR	33	/* Battery Monitor */
-# define IRQ_MCINTR	34	/* Media Change */
-# define IRQ_TINTR	35	/* 64Hz Tick */
-# define IRQ_WEINT	36	/* Watchdog Expired */
-# define IRQ_RTCMI	37	/* Real-time Clock Match */
-# define IRQ_UART1INTR	38	/* UART1 Interrupt (including error) */
-# define IRQ_UART1ERR	39	/* UART1 Error */
-# define IRQ_UART2INTR	40	/* UART2 Interrupt (including error) */
-# define IRQ_UART2ERR	41	/* UART2 Error */
-# define IRQ_UART3INTR	42	/* UART3 Interrupt (including error) */
-# define IRQ_UART3ERR	43	/* UART3 Error */
-# define IRQ_SCIINTR	44	/* Smart Card */
-# define IRQ_TSCINTR	45	/* Touchscreen */
-# define IRQ_KMIINTR	46	/* Keyboard/Mouse (PS/2) */
-# define IRQ_GPIO4INTR	47	/* -- GPIOF Interrupt */
-# define IRQ_GPIO5INTR	48
-# define IRQ_GPIO6INTR	49
-# define IRQ_GPIO7INTR	50
-# define IRQ_T3UI	51	/* Timer 3 underflow */
-# define IRQ_LCDINTR	52	/* LCD Controller */
-# define IRQ_SSPINTR	53	/* Synchronous Serial Port */
-# define IRQ_SDINTR	54	/* Secure Digital Port (MMC) */
-# define IRQ_USBINTR	55	/* USB Device Port */
-# define IRQ_USHINTR	56	/* USB Host Port */
-# define IRQ_SOFT_V2_25	57	/* -- Unassigned */
-# define IRQ_SOFT_V2_26	58
-# define IRQ_SOFT_V2_27	59
-# define IRQ_SOFT_V2_28	60
-# define IRQ_SOFT_V2_29	61
-# define IRQ_SOFT_V2_30	62
-# define IRQ_SOFT_V2_31	63
-
-# define NR_IRQ_CPU	64	/* IRQs directly recognized by CPU */
-
-	/* Given IRQ, return GPIO interrupt number 0-7 */
-# define IRQ_TO_GPIO(i)  ((i) \
-	- (((i) > IRQ_GPIO3INTR) ? IRQ_GPIO4INTR - IRQ_GPIO3INTR - 1 : 0)\
-	- IRQ_GPIO0INTR)
-
-			/* Vector Address constants */
-# define VA_VECTORED	0x100	/* Set for vectored interrupt */
-# define VA_VIC1DEFAULT	0x200	/* Set as default VECTADDR for VIC1 */
-# define VA_VIC2DEFAULT	0x400	/* Set as default VECTADDR for VIC2 */
-
-#endif
-
-  /* IRQ aliases */
-
-#if !defined (IRQ_GPIO0INTR)
-# define IRQ_GPIO0INTR	IRQ_GPIO0FIQ
-#endif
-#define IRQ_TICK	IRQ_TINTR
-#define IRQ_PCC1_RDY	IRQ_GPIO6INTR	/* PCCard 1 ready */
-#define IRQ_PCC2_RDY	IRQ_GPIO7INTR	/* PCCard 2 ready */
-#define IRQ_USB		IRQ_USBINTR	/* USB device */
-
-#ifdef CONFIG_MACH_KEV7A400
-# define IRQ_TS		IRQ_GPIOFIQ	/* Touchscreen */
-# define IRQ_CPLD	IRQ_GPIO1INTR	/* CPLD cascade */
-# define IRQ_PCC1_CD	IRQ_GPIO_F2	/* PCCard 1 card detect */
-# define IRQ_PCC2_CD	IRQ_GPIO_F3	/* PCCard 2 card detect */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-# define IRQ_CPLD_V28	IRQ_GPIO7INTR	/* CPLD cascade through GPIO_PF7 */
-# define IRQ_CPLD_V34	IRQ_GPIO3INTR	/* CPLD cascade through GPIO_PF3 */
-#endif
-
-  /* System specific IRQs */
-
-#define IRQ_BOARD_START NR_IRQ_CPU
-
-#ifdef CONFIG_MACH_KEV7A400
-# define IRQ_KEV7A400_CPLD	IRQ_BOARD_START
-# define NR_IRQ_BOARD		5
-# define IRQ_KEV7A400_MMC_CD	IRQ_KEV7A400_CPLD + 0	/* MMC Card Detect */
-# define IRQ_KEV7A400_RI2	IRQ_KEV7A400_CPLD + 1	/* Ring Indicator 2 */
-# define IRQ_KEV7A400_IDE_CF	IRQ_KEV7A400_CPLD + 2	/* Compact Flash (?) */
-# define IRQ_KEV7A400_ETH_INT	IRQ_KEV7A400_CPLD + 3	/* Ethernet chip */
-# define IRQ_KEV7A400_INT	IRQ_KEV7A400_CPLD + 4
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-# define IRQ_LPD7A40X_CPLD	IRQ_BOARD_START
-# define NR_IRQ_BOARD		2
-# define IRQ_LPD7A40X_ETH_INT	IRQ_LPD7A40X_CPLD + 0	/* Ethernet chip */
-# define IRQ_LPD7A400_TS	IRQ_LPD7A40X_CPLD + 1	/* Touch screen */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400)
-# define IRQ_TOUCH		IRQ_LPD7A400_TS
-#endif
-
-#define NR_IRQS		(NR_IRQ_CPU + NR_IRQ_BOARD)
-
-#endif
diff --git a/arch/arm/mach-lh7a40x/include/mach/memory.h b/arch/arm/mach-lh7a40x/include/mach/memory.h
deleted file mode 100644
index edb8f5f..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/memory.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/memory.h
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- *
- *  Refer to <file:Documentation/arm/Sharp-LH/SDRAM> for more information.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET	UL(0xc0000000)
-
-/*
- * Sparsemem version of the above
- */
-#define MAX_PHYSMEM_BITS	32
-#define SECTION_SIZE_BITS	24
-
-#endif
diff --git a/arch/arm/mach-lh7a40x/include/mach/registers.h b/arch/arm/mach-lh7a40x/include/mach/registers.h
deleted file mode 100644
index ea44396..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/registers.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/registers.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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/constants.h>
-
-#ifndef __ASM_ARCH_REGISTERS_H
-#define __ASM_ARCH_REGISTERS_H
-
-
-	/* Physical register base addresses */
-
-#define AC97C_PHYS	(0x80000000)	/* AC97 Controller */
-#define MMC_PHYS	(0x80000100)	/* Multimedia Card Controller */
-#define USB_PHYS	(0x80000200)	/* USB Client */
-#define SCI_PHYS	(0x80000300)	/* Secure Card Interface */
-#define CSC_PHYS	(0x80000400)	/* Clock/State Controller  */
-#define INTC_PHYS	(0x80000500)	/* Interrupt Controller */
-#define UART1_PHYS	(0x80000600)	/* UART1 Controller */
-#define SIR_PHYS	(0x80000600)	/* IR Controller, same are UART1 */
-#define UART2_PHYS	(0x80000700)	/* UART2 Controller */
-#define UART3_PHYS	(0x80000800)	/* UART3 Controller */
-#define DCDC_PHYS	(0x80000900)	/* DC to DC Controller */
-#define ACI_PHYS	(0x80000a00)	/* Audio Codec Interface */
-#define SSP_PHYS	(0x80000b00)	/* Synchronous ... */
-#define TIMER_PHYS	(0x80000c00)	/* Timer Controller */
-#define RTC_PHYS	(0x80000d00)	/* Real-time Clock */
-#define GPIO_PHYS	(0x80000e00)	/* General Purpose IO */
-#define BMI_PHYS	(0x80000f00)	/* Battery Monitor Interface */
-#define HRTFTC_PHYS	(0x80001000)	/* High-res TFT Controller (LH7A400) */
-#define ALI_PHYS	(0x80001000)	/* Advanced LCD Interface (LH7A404) */
-#define WDT_PHYS	(0x80001400)	/* Watchdog Timer */
-#define SMC_PHYS	(0x80002000)	/* Static Memory Controller */
-#define SDRC_PHYS	(0x80002400)	/* SDRAM Controller */
-#define DMAC_PHYS	(0x80002800)	/* DMA Controller */
-#define CLCDC_PHYS	(0x80003000)	/* Color LCD Controller */
-
-	/* Physical registers of the LH7A404 */
-
-#define ADC_PHYS	(0x80001300)	/* A/D & Touchscreen Controller */
-#define VIC1_PHYS	(0x80008000)	/* Vectored Interrupt Controller 1 */
-#define USBH_PHYS	(0x80009000)	/* USB OHCI host controller */
-#define VIC2_PHYS	(0x8000a000)	/* Vectored Interrupt Controller 2 */
-
-/*#define KBD_PHYS	(0x80000e00) */
-/*#define LCDICP_PHYS	(0x80001000) */
-
-
-	/* Clock/State Controller register */
-
-#define CSC_PWRSR	__REG(CSC_PHYS + 0x00) /* Reset register & ID */
-#define CSC_PWRCNT	__REG(CSC_PHYS + 0x04) /* Power control */
-#define CSC_CLKSET	__REG(CSC_PHYS + 0x20) /* Clock speed control */
-#define CSC_USBDRESET	__REG(CSC_PHYS + 0x4c) /* USB Device resets */
-
-#define CSC_PWRCNT_USBH_EN	(1<<28)	/* USB Host power enable */
-#define CSC_PWRCNT_DMAC_M2M1_EN	(1<<27)
-#define CSC_PWRCNT_DMAC_M2M0_EN	(1<<26)
-#define CSC_PWRCNT_DMAC_M2P8_EN	(1<<25)
-#define CSC_PWRCNT_DMAC_M2P9_EN	(1<<24)
-#define CSC_PWRCNT_DMAC_M2P6_EN	(1<<23)
-#define CSC_PWRCNT_DMAC_M2P7_EN	(1<<22)
-#define CSC_PWRCNT_DMAC_M2P4_EN	(1<<21)
-#define CSC_PWRCNT_DMAC_M2P5_EN	(1<<20)
-#define CSC_PWRCNT_DMAC_M2P2_EN	(1<<19)
-#define CSC_PWRCNT_DMAC_M2P3_EN	(1<<18)
-#define CSC_PWRCNT_DMAC_M2P0_EN	(1<<17)
-#define CSC_PWRCNT_DMAC_M2P1_EN	(1<<16)
-
-#define CSC_PWRSR_CHIPMAN_SHIFT	(24)
-#define CSC_PWRSR_CHIPMAN_MASK	(0xff)
-#define CSC_PWRSR_CHIPID_SHIFT	(16)
-#define CSC_PWRSR_CHIPID_MASK	(0xff)
-
-#define CSC_USBDRESET_APBRESETREG	(1<<1)
-#define CSC_USBDRESET_IORESETREG	(1<<0)
-
-	/* Interrupt Controller registers */
-
-#define INTC_INTSR	__REG(INTC_PHYS + 0x00)	/* Status */
-#define INTC_INTRSR	__REG(INTC_PHYS + 0x04)	/* Raw Status */
-#define INTC_INTENS	__REG(INTC_PHYS + 0x08)	/* Enable Set */
-#define INTC_INTENC	__REG(INTC_PHYS + 0x0c)	/* Enable Clear */
-
-
-	/* Vectored Interrupted Controller registers */
-
-#define VIC1_IRQSTATUS	__REG(VIC1_PHYS + 0x00)
-#define VIC1_FIQSTATUS	__REG(VIC1_PHYS + 0x04)
-#define VIC1_RAWINTR	__REG(VIC1_PHYS + 0x08)
-#define VIC1_INTSEL	__REG(VIC1_PHYS + 0x0c)
-#define VIC1_INTEN	__REG(VIC1_PHYS + 0x10)
-#define VIC1_INTENCLR	__REG(VIC1_PHYS + 0x14)
-#define VIC1_SOFTINT	__REG(VIC1_PHYS + 0x18)
-#define VIC1_SOFTINTCLR	__REG(VIC1_PHYS + 0x1c)
-#define VIC1_PROTECT	__REG(VIC1_PHYS + 0x20)
-#define VIC1_VECTADDR	__REG(VIC1_PHYS + 0x30)
-#define VIC1_NVADDR	__REG(VIC1_PHYS + 0x34)
-#define VIC1_VAD0	__REG(VIC1_PHYS + 0x100)
-#define VIC1_VECTCNTL0	__REG(VIC1_PHYS + 0x200)
-#define VIC2_IRQSTATUS	__REG(VIC2_PHYS + 0x00)
-#define VIC2_FIQSTATUS	__REG(VIC2_PHYS + 0x04)
-#define VIC2_RAWINTR	__REG(VIC2_PHYS + 0x08)
-#define VIC2_INTSEL	__REG(VIC2_PHYS + 0x0c)
-#define VIC2_INTEN	__REG(VIC2_PHYS + 0x10)
-#define VIC2_INTENCLR	__REG(VIC2_PHYS + 0x14)
-#define VIC2_SOFTINT	__REG(VIC2_PHYS + 0x18)
-#define VIC2_SOFTINTCLR	__REG(VIC2_PHYS + 0x1c)
-#define VIC2_PROTECT	__REG(VIC2_PHYS + 0x20)
-#define VIC2_VECTADDR	__REG(VIC2_PHYS + 0x30)
-#define VIC2_NVADDR	__REG(VIC2_PHYS + 0x34)
-#define VIC2_VAD0	__REG(VIC2_PHYS + 0x100)
-#define VIC2_VECTCNTL0	__REG(VIC2_PHYS + 0x200)
-
-#define VIC_CNTL_ENABLE	(0x20)
-
-	/* USB Host registers (Open HCI compatible) */
-
-#define USBH_CMDSTATUS	__REG(USBH_PHYS + 0x08)
-
-
-	/* GPIO registers */
-
-#define GPIO_INTTYPE1	__REG(GPIO_PHYS + 0x4c)	/* Interrupt Type 1 (Edge) */
-#define GPIO_INTTYPE2	__REG(GPIO_PHYS + 0x50)	/* Interrupt Type 2 */
-#define GPIO_GPIOFEOI	__REG(GPIO_PHYS + 0x54)	/* GPIO End-of-Interrupt */
-#define GPIO_GPIOINTEN	__REG(GPIO_PHYS + 0x58)	/* GPIO Interrupt Enable */
-#define GPIO_INTSTATUS	__REG(GPIO_PHYS + 0x5c)	/* GPIO Interrupt Status */
-#define GPIO_PINMUX	__REG(GPIO_PHYS + 0x2c)
-#define GPIO_PADD	__REG(GPIO_PHYS + 0x10)
-#define GPIO_PAD	__REG(GPIO_PHYS + 0x00)
-#define GPIO_PCD	__REG(GPIO_PHYS + 0x08)
-#define GPIO_PCDD	__REG(GPIO_PHYS + 0x18)
-#define GPIO_PEDD	__REG(GPIO_PHYS + 0x24)
-#define GPIO_PED	__REG(GPIO_PHYS + 0x20)
-
-
-	/* Static Memory Controller registers */
-
-#define SMC_BCR0	__REG(SMC_PHYS + 0x00)	/* Bank 0 Configuration */
-#define SMC_BCR1	__REG(SMC_PHYS + 0x04)	/* Bank 1 Configuration */
-#define SMC_BCR2	__REG(SMC_PHYS + 0x08)	/* Bank 2 Configuration */
-#define SMC_BCR3	__REG(SMC_PHYS + 0x0C)	/* Bank 3 Configuration */
-#define SMC_BCR6	__REG(SMC_PHYS + 0x18)	/* Bank 6 Configuration */
-#define SMC_BCR7	__REG(SMC_PHYS + 0x1c)	/* Bank 7 Configuration */
-
-
-#ifdef CONFIG_MACH_KEV7A400
-# define CPLD_RD_OPT_DIP_SW	__REG16(CPLD_PHYS + 0x00) /* Read Option SW */
-# define CPLD_WR_IO_BRD_CTL	__REG16(CPLD_PHYS + 0x00) /* Write Control */
-# define CPLD_RD_PB_KEYS	__REG16(CPLD_PHYS + 0x02) /* Read Btn Keys */
-# define CPLD_LATCHED_INTS	__REG16(CPLD_PHYS + 0x04) /* Read INTR stat. */
-# define CPLD_CL_INT		__REG16(CPLD_PHYS + 0x04) /* Clear INTR stat */
-# define CPLD_BOOT_MMC_STATUS	__REG16(CPLD_PHYS + 0x06) /* R/O */
-# define CPLD_RD_KPD_ROW_SENSE	__REG16(CPLD_PHYS + 0x08)
-# define CPLD_WR_PB_INT_MASK	__REG16(CPLD_PHYS + 0x08)
-# define CPLD_RD_BRD_DISP_SW	__REG16(CPLD_PHYS + 0x0a)
-# define CPLD_WR_EXT_INT_MASK	__REG16(CPLD_PHYS + 0x0a)
-# define CPLD_LCD_PWR_CNTL	__REG16(CPLD_PHYS + 0x0c)
-# define CPLD_SEVEN_SEG		__REG16(CPLD_PHYS + 0x0e) /* 7 seg. LED mask */
-
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-
-# define CPLD_CONTROL		__REG16(CPLD02_PHYS)
-# define CPLD_SPI_DATA		__REG16(CPLD06_PHYS)
-# define CPLD_SPI_CONTROL	__REG16(CPLD08_PHYS)
-# define CPLD_SPI_EEPROM	__REG16(CPLD0A_PHYS)
-# define CPLD_INTERRUPTS	__REG16(CPLD0C_PHYS) /* IRQ mask/status */
-# define CPLD_BOOT_MODE		__REG16(CPLD0E_PHYS)
-# define CPLD_FLASH		__REG16(CPLD10_PHYS)
-# define CPLD_POWER_MGMT	__REG16(CPLD12_PHYS)
-# define CPLD_REVISION		__REG16(CPLD14_PHYS)
-# define CPLD_GPIO_EXT		__REG16(CPLD16_PHYS)
-# define CPLD_GPIO_DATA		__REG16(CPLD18_PHYS)
-# define CPLD_GPIO_DIR		__REG16(CPLD1A_PHYS)
-
-#endif
-
-	/* Timer registers */
-
-#define TIMER_LOAD1	__REG(TIMER_PHYS + 0x00) /* Timer 1 initial value */
-#define TIMER_VALUE1	__REG(TIMER_PHYS + 0x04) /* Timer 1 current value */
-#define TIMER_CONTROL1	__REG(TIMER_PHYS + 0x08) /* Timer 1 control word */
-#define TIMER_EOI1	__REG(TIMER_PHYS + 0x0c) /* Timer 1 interrupt clear */
-
-#define TIMER_LOAD2	__REG(TIMER_PHYS + 0x20) /* Timer 2 initial value */
-#define TIMER_VALUE2	__REG(TIMER_PHYS + 0x24) /* Timer 2 current value */
-#define TIMER_CONTROL2	__REG(TIMER_PHYS + 0x28) /* Timer 2 control word */
-#define TIMER_EOI2	__REG(TIMER_PHYS + 0x2c) /* Timer 2 interrupt clear */
-
-#define TIMER_BUZZCON	__REG(TIMER_PHYS + 0x40) /* Buzzer configuration */
-
-#define TIMER_LOAD3	__REG(TIMER_PHYS + 0x80) /* Timer 3 initial value */
-#define TIMER_VALUE3	__REG(TIMER_PHYS + 0x84) /* Timer 3 current value */
-#define TIMER_CONTROL3	__REG(TIMER_PHYS + 0x88) /* Timer 3 control word */
-#define TIMER_EOI3	__REG(TIMER_PHYS + 0x8c) /* Timer 3 interrupt clear */
-
-#define TIMER_C_ENABLE		(1<<7)
-#define TIMER_C_PERIODIC	(1<<6)
-#define TIMER_C_FREERUNNING	(0)
-#define TIMER_C_2KHZ		(0x00)		/* 1.986 kHz */
-#define TIMER_C_508KHZ		(0x08)
-
-	/* GPIO registers */
-
-#define GPIO_PFDD		__REG(GPIO_PHYS + 0x34)	/* PF direction */
-#define GPIO_INTTYPE1		__REG(GPIO_PHYS + 0x4c)	/* IRQ edge or lvl  */
-#define GPIO_INTTYPE2		__REG(GPIO_PHYS + 0x50)	/* IRQ activ hi/lo */
-#define GPIO_GPIOFEOI		__REG(GPIO_PHYS + 0x54)	/* GPIOF end of IRQ */
-#define GPIO_GPIOFINTEN		__REG(GPIO_PHYS + 0x58)	/* GPIOF IRQ enable */
-#define GPIO_INTSTATUS		__REG(GPIO_PHYS + 0x5c)	/* GPIOF IRQ latch */
-#define GPIO_RAWINTSTATUS	__REG(GPIO_PHYS + 0x60)	/* GPIOF IRQ raw */
-
-
-#endif  /* _ASM_ARCH_REGISTERS_H */
diff --git a/arch/arm/mach-lh7a40x/include/mach/ssp.h b/arch/arm/mach-lh7a40x/include/mach/ssp.h
deleted file mode 100644
index 5099161..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/ssp.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* ssp.h
-
-   written by Marc Singer
-   6 Dec 2004
-
-   Copyright (C) 2004 Marc Singer
-
-   -----------
-   DESCRIPTION
-   -----------
-
-   This SSP header is available throughout the kernel, for this
-   machine/architecture, because drivers that use it may be dispersed.
-
-   This file was cloned from the 7952x implementation.  It would be
-   better to share them, but we're taking an easier approach for the
-   time being.
-
-*/
-
-#if !defined (__SSP_H__)
-#    define   __SSP_H__
-
-/* ----- Includes */
-
-/* ----- Types */
-
-struct ssp_driver {
-	int  (*init)		(void);
-	void (*exit)		(void);
-	void (*acquire)		(void);
-	void (*release)		(void);
-	int  (*configure)	(int device, int mode, int speed,
-				 int frame_size_write, int frame_size_read);
-	void (*chip_select)	(int enable);
-	void (*set_callbacks)   (void* handle,
-				 irqreturn_t (*callback_tx)(void*),
-				 irqreturn_t (*callback_rx)(void*));
-	void (*enable)		(void);
-	void (*disable)		(void);
-//	int  (*save_state)	(void*);
-//	void (*restore_state)	(void*);
-	int  (*read)		(void);
-	int  (*write)		(u16 data);
-	int  (*write_read)	(u16 data);
-	void (*flush)		(void);
-	void (*write_async)	(void* pv, size_t cb);
-	size_t (*write_pos)	(void);
-};
-
-	/* These modes are only available on the LH79524 */
-#define SSP_MODE_SPI		(1)
-#define SSP_MODE_SSI		(2)
-#define SSP_MODE_MICROWIRE	(3)
-#define SSP_MODE_I2S		(4)
-
-	/* CPLD SPI devices */
-#define DEVICE_EEPROM	0	/* Configuration eeprom */
-#define DEVICE_MAC	1	/* MAC eeprom (LPD79524) */
-#define DEVICE_CODEC	2	/* Audio codec */
-#define DEVICE_TOUCH	3	/* Touch screen (LPD79520) */
-
-/* ----- Globals */
-
-/* ----- Prototypes */
-
-//extern struct ssp_driver lh79520_i2s_driver;
-extern struct ssp_driver lh7a400_cpld_ssp_driver;
-
-#endif  /* __SSP_H__ */
diff --git a/arch/arm/mach-lh7a40x/include/mach/system.h b/arch/arm/mach-lh7a40x/include/mach/system.h
deleted file mode 100644
index 45a56d3..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/system.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/system.h
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle ();
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset (0);
-}
diff --git a/arch/arm/mach-lh7a40x/include/mach/timex.h b/arch/arm/mach-lh7a40x/include/mach/timex.h
deleted file mode 100644
index 08028ce..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/timex.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/timex.h
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-
-#include <mach/constants.h>
-
-#define CLOCK_TICK_RATE		(PLL_CLOCK/6/16)
-
-/*
-#define CLOCK_TICK_RATE		3686400
-*/
diff --git a/arch/arm/mach-lh7a40x/include/mach/uncompress.h b/arch/arm/mach-lh7a40x/include/mach/uncompress.h
deleted file mode 100644
index 55b80d4..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/uncompress.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/uncompress.h
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-
-#include <mach/registers.h>
-
-#ifndef UART_R_DATA
-# define UART_R_DATA	(0x00)
-#endif
-#ifndef UART_R_STATUS
-# define UART_R_STATUS	(0x10)
-#endif
-#define nTxRdy		(0x20)	/* Not TxReady (literally Tx FIFO full) */
-
-	/* Access UART with physical addresses before MMU is setup */
-#define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
-#define UART_DATA   (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA))
-
-static inline void putc(int ch)
-{
-	while (UART_STATUS & nTxRdy)
-		barrier();
-	UART_DATA = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-	/* NULL functions; we don't presently need them */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-lh7a40x/include/mach/vmalloc.h b/arch/arm/mach-lh7a40x/include/mach/vmalloc.h
deleted file mode 100644
index d62da73..0000000
--- a/arch/arm/mach-lh7a40x/include/mach/vmalloc.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/vmalloc.h
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-#define VMALLOC_END       (0xe8000000UL)
diff --git a/arch/arm/mach-lh7a40x/irq-kev7a400.c b/arch/arm/mach-lh7a40x/irq-kev7a400.c
deleted file mode 100644
index c7433b3..0000000
--- a/arch/arm/mach-lh7a40x/irq-kev7a400.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-kev7a400.c
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-
-#include <linux/interrupt.h>
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/hardware.h>
-#include <asm/mach/irqs.h>
-
-#include "common.h"
-
-  /* KEV7a400 CPLD IRQ handling */
-
-static u16 CPLD_IRQ_mask;	/* Mask for CPLD IRQs, 1 == unmasked */
-
-static void
-lh7a400_ack_cpld_irq (u32 irq)
-{
-	CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
-}
-
-static void
-lh7a400_mask_cpld_irq (u32 irq)
-{
-	CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static void
-lh7a400_unmask_cpld_irq (u32 irq)
-{
-	CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static struct
-irq_chip lh7a400_cpld_chip = {
-	.name	= "CPLD",
-	.ack	= lh7a400_ack_cpld_irq,
-	.mask	= lh7a400_mask_cpld_irq,
-	.unmask	= lh7a400_unmask_cpld_irq,
-};
-
-static void
-lh7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	u32 mask = CPLD_LATCHED_INTS;
-	irq = IRQ_KEV_7A400_CPLD;
-	for (; mask; mask >>= 1, ++irq) {
-		if (mask & 1)
-			desc[irq].handle (irq, desc);
-	}
-}
-
-  /* IRQ initialization */
-
-void __init
-lh7a400_init_board_irq (void)
-{
-	int irq;
-
-	for (irq = IRQ_KEV7A400_CPLD;
-	     irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) {
-		set_irq_chip (irq, &lh7a400_cpld_chip);
-		set_irq_handler (irq, handle_edge_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-	set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
-
-		/* Clear all CPLD interrupts */
-	CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
-
-    /* *** FIXME CF enabled in ide-probe.c */
-
-	GPIO_GPIOINTEN = 0;		/* Disable all GPIO interrupts */
-	barrier();
-	GPIO_INTTYPE1
-		= (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
-	GPIO_INTTYPE2 = 0;		/* Falling edge & low-level */
-	GPIO_GPIOFEOI = 0xff;		/* Clear all GPIO interrupts */
-	GPIO_GPIOINTEN = 0xff;		/* Enable all GPIO interrupts */
-
-	init_FIQ();
-}
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a400.c b/arch/arm/mach-lh7a40x/irq-lh7a400.c
deleted file mode 100644
index f2e7e65..0000000
--- a/arch/arm/mach-lh7a40x/irq-lh7a400.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-lh7a400.c
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <mach/irqs.h>
-
-#include "common.h"
-
-  /* CPU IRQ handling */
-
-static void lh7a400_mask_irq(struct irq_data *d)
-{
-	INTC_INTENC = (1 << d->irq);
-}
-
-static void lh7a400_unmask_irq(struct irq_data *d)
-{
-	INTC_INTENS = (1 << d->irq);
-}
-
-static void lh7a400_ack_gpio_irq(struct irq_data *d)
-{
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
-	INTC_INTENC = (1 << d->irq);
-}
-
-static struct irq_chip lh7a400_internal_chip = {
-	.name		= "MPU",
-	.irq_ack	= lh7a400_mask_irq, /* Level triggering -> mask is ack */
-	.irq_mask	= lh7a400_mask_irq,
-	.irq_unmask	= lh7a400_unmask_irq,
-};
-
-static struct irq_chip lh7a400_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= lh7a400_ack_gpio_irq,
-	.irq_mask	= lh7a400_mask_irq,
-	.irq_unmask	= lh7a400_unmask_irq,
-};
-
-
-  /* IRQ initialization */
-
-void __init lh7a400_init_irq (void)
-{
-	int irq;
-
-	INTC_INTENC = 0xffffffff;	/* Disable all interrupts */
-	GPIO_GPIOFINTEN = 0x00;		/* Disable all GPIOF interrupts */
-	barrier ();
-
-	for (irq = 0; irq < NR_IRQS; ++irq) {
-		switch (irq) {
-		case IRQ_GPIO0INTR:
-		case IRQ_GPIO1INTR:
-		case IRQ_GPIO2INTR:
-		case IRQ_GPIO3INTR:
-		case IRQ_GPIO4INTR:
-		case IRQ_GPIO5INTR:
-		case IRQ_GPIO6INTR:
-		case IRQ_GPIO7INTR:
-			set_irq_chip (irq, &lh7a400_gpio_chip);
-			set_irq_handler (irq, handle_level_irq); /* OK default */
-			break;
-		default:
-			set_irq_chip (irq, &lh7a400_internal_chip);
-			set_irq_handler (irq, handle_level_irq);
-		}
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	lh7a40x_init_board_irq ();
-
-/* *** FIXME: the LH7a400 does use FIQ interrupts in some cases.  For
-   the time being, these are not initialized. */
-
-/*	init_FIQ(); */
-}
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
deleted file mode 100644
index 14b1733..0000000
--- a/arch/arm/mach-lh7a40x/irq-lh7a404.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-lh7a404.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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/module.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <mach/irqs.h>
-
-#include "common.h"
-
-#define USE_PRIORITIES
-
-/* See Documentation/arm/Sharp-LH/VectoredInterruptController for more
- * information on using the vectored interrupt controller's
- * prioritizing feature. */
-
-static unsigned char irq_pri_vic1[] = {
-#if defined (USE_PRIORITIES)
-	IRQ_GPIO3INTR,			/* CPLD */
-	IRQ_DMAM2P4, IRQ_DMAM2P5,	/* AC97 */
-#endif
-};
-static unsigned char irq_pri_vic2[] = {
-#if defined (USE_PRIORITIES)
-	IRQ_T3UI,			/* Timer */
-	IRQ_GPIO7INTR,			/* CPLD */
-	IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
-	IRQ_LCDINTR,			/* LCD */
-	IRQ_TSCINTR,			/* ADC/Touchscreen */
-#endif
-};
-
-  /* CPU IRQ handling */
-
-static void lh7a404_vic1_mask_irq(struct irq_data *d)
-{
-	VIC1_INTENCLR = (1 << d->irq);
-}
-
-static void lh7a404_vic1_unmask_irq(struct irq_data *d)
-{
-	VIC1_INTEN = (1 << d->irq);
-}
-
-static void lh7a404_vic2_mask_irq(struct irq_data *d)
-{
-	VIC2_INTENCLR = (1 << (d->irq - 32));
-}
-
-static void lh7a404_vic2_unmask_irq(struct irq_data *d)
-{
-	VIC2_INTEN = (1 << (d->irq - 32));
-}
-
-static void lh7a404_vic1_ack_gpio_irq(struct irq_data *d)
-{
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
-	VIC1_INTENCLR = (1 << d->irq);
-}
-
-static void lh7a404_vic2_ack_gpio_irq(struct irq_data *d)
-{
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
-	VIC2_INTENCLR = (1 << d->irq);
-}
-
-static struct irq_chip lh7a404_vic1_chip = {
-	.name		= "VIC1",
-	.irq_ack	= lh7a404_vic1_mask_irq, /* Because level-triggered */
-	.irq_mask	= lh7a404_vic1_mask_irq,
-	.irq_unmask	= lh7a404_vic1_unmask_irq,
-};
-
-static struct irq_chip lh7a404_vic2_chip = {
-	.name		= "VIC2",
-	.irq_ack	= lh7a404_vic2_mask_irq, /* Because level-triggered */
-	.irq_mask	= lh7a404_vic2_mask_irq,
-	.irq_unmask	= lh7a404_vic2_unmask_irq,
-};
-
-static struct irq_chip lh7a404_gpio_vic1_chip = {
-	.name		= "GPIO-VIC1",
-	.irq_ack	= lh7a404_vic1_ack_gpio_irq,
-	.irq_mask	= lh7a404_vic1_mask_irq,
-	.irq_unmask	= lh7a404_vic1_unmask_irq,
-};
-
-static struct irq_chip lh7a404_gpio_vic2_chip = {
-	.name		= "GPIO-VIC2",
-	.irq_ack	= lh7a404_vic2_ack_gpio_irq,
-	.irq_mask	= lh7a404_vic2_mask_irq,
-	.irq_unmask	= lh7a404_vic2_unmask_irq,
-};
-
-  /* IRQ initialization */
-
-#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-extern void* branch_irq_lh7a400;
-#endif
-
-void __init lh7a404_init_irq (void)
-{
-	int irq;
-
-#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-#define NOP 0xe1a00000			/* mov r0, r0 */
-	branch_irq_lh7a400 = NOP;
-#endif
-
-	VIC1_INTENCLR = 0xffffffff;
-	VIC2_INTENCLR = 0xffffffff;
-	VIC1_INTSEL = 0;		/* All IRQs */
-	VIC2_INTSEL = 0;		/* All IRQs */
-	VIC1_NVADDR = VA_VIC1DEFAULT;
-	VIC2_NVADDR = VA_VIC2DEFAULT;
-	VIC1_VECTADDR = 0;
-	VIC2_VECTADDR = 0;
-
-	GPIO_GPIOFINTEN = 0x00;		/* Disable all GPIOF interrupts */
-	barrier ();
-
-		/* Install prioritized interrupts, if there are any. */
-		/* The | 0x20*/
-	for (irq = 0; irq < 16; ++irq) {
-		(&VIC1_VAD0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic1))
-			? (irq_pri_vic1[irq] | VA_VECTORED) : 0;
-		(&VIC1_VECTCNTL0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic1))
-			? (irq_pri_vic1[irq] | VIC_CNTL_ENABLE) : 0;
-		(&VIC2_VAD0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic2))
-			? (irq_pri_vic2[irq] | VA_VECTORED) : 0;
-		(&VIC2_VECTCNTL0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic2))
-			? (irq_pri_vic2[irq] | VIC_CNTL_ENABLE) : 0;
-	}
-
-	for (irq = 0; irq < NR_IRQS; ++irq) {
-		switch (irq) {
-		case IRQ_GPIO0INTR:
-		case IRQ_GPIO1INTR:
-		case IRQ_GPIO2INTR:
-		case IRQ_GPIO3INTR:
-		case IRQ_GPIO4INTR:
-		case IRQ_GPIO5INTR:
-		case IRQ_GPIO6INTR:
-		case IRQ_GPIO7INTR:
-			set_irq_chip (irq, irq < 32
-				      ? &lh7a404_gpio_vic1_chip
-				      : &lh7a404_gpio_vic2_chip);
-			set_irq_handler (irq, handle_level_irq); /* OK default */
-			break;
-		default:
-			set_irq_chip (irq, irq < 32
-				      ? &lh7a404_vic1_chip
-				      : &lh7a404_vic2_chip);
-			set_irq_handler (irq, handle_level_irq);
-		}
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	lh7a40x_init_board_irq ();
-}
diff --git a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
deleted file mode 100644
index 1bfdcdd..0000000
--- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-lpd7a40x.c
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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/module.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <mach/irqs.h>
-
-#include "common.h"
-
-static void lh7a40x_ack_cpld_irq(struct irq_data *d)
-{
-	/* CPLD doesn't have ack capability */
-}
-
-static void lh7a40x_mask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
-		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
-		break;
-	}
-}
-
-static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
-		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
-		break;
-	}
-}
-
-static struct irq_chip lh7a40x_cpld_chip = {
-	.name		= "CPLD",
-	.irq_ack	= lh7a40x_ack_cpld_irq,
-	.irq_mask	= lh7a40x_mask_cpld_irq,
-	.irq_unmask	= lh7a40x_unmask_cpld_irq,
-};
-
-static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int mask = CPLD_INTERRUPTS;
-
-	desc->irq_data.chip->ack (irq);
-
-	if ((mask & 0x1) == 0)	/* WLAN */
-		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
-
-	if ((mask & 0x2) == 0)	/* Touch */
-		generic_handle_irq(IRQ_LPD7A400_TS);
-
-	desc->irq_data.chip->unmask (irq); /* Level-triggered need this */
-}
-
-
-  /* IRQ initialization */
-
-void __init lh7a40x_init_board_irq (void)
-{
-	int irq;
-
-		/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
-		                 PF7 supports the CPLD.
-		   Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
-		                 PF3 supports the CPLD.
-		   (Some) LPD7A404 prerelease boards report a version
-		   number of 0x16, but we force an override since the
-		   hardware is of the newer variety.
-		*/
-
-	unsigned char cpld_version = CPLD_REVISION;
-	int pinCPLD;
-
-#if defined CONFIG_MACH_LPD7A404
-	cpld_version = 0x34;	/* Override, for now */
-#endif
-	pinCPLD = (cpld_version == 0x28) ? 7 : 3;
-
-		/* First, configure user controlled GPIOF interrupts  */
-
-	GPIO_PFDD	&= ~0x0f; /* PF0-3 are inputs */
-	GPIO_INTTYPE1	&= ~0x0f; /* PF0-3 are level triggered */
-	GPIO_INTTYPE2	&= ~0x0f; /* PF0-3 are active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
-
-		/* Then, configure CPLD interrupt */
-
-	CPLD_INTERRUPTS	=   0x0c; /* Disable all CPLD interrupts */
-	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
-	GPIO_INTTYPE1	|=  (1 << pinCPLD); /* Edge triggered */
-	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
-
-		/* Cascade CPLD interrupts */
-
-	for (irq = IRQ_BOARD_START;
-	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
-		set_irq_chip (irq, &lh7a40x_cpld_chip);
-		set_irq_handler (irq, handle_edge_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler ((cpld_version == 0x28)
-				 ? IRQ_CPLD_V28
-				 : IRQ_CPLD_V34,
-				 lh7a40x_cpld_handler);
-}
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
deleted file mode 100644
index a7f5027..0000000
--- a/arch/arm/mach-lh7a40x/lcd-panel.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/* lcd-panel.h
-
-   written by Marc Singer
-   18 Jul 2005
-
-   Copyright (C) 2005 Marc Singer
-
-   -----------
-   DESCRIPTION
-   -----------
-
-   Only one panel may be defined at a time.
-
-   The pixel clock is calculated to be no greater than the target.
-
-   Each timing value is accompanied by a specification comment.
-
-     UNITS/MIN/TYP/MAX
-
-   Most of the units will be in clocks.
-
-   USE_RGB555
-
-     Define this macro to configure the AMBA LCD controller to use an
-     RGB555 encoding for the pels instead of the normal RGB565.
-
-   LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
-
-     These boards are best approximated by 555 for all panels.  Some
-     can use an extra low-order bit of blue in bit 16 of the color
-     value, but we don't have a way to communicate this non-linear
-     mapping to the kernel.
-
-*/
-
-#if !defined (__LCD_PANEL_H__)
-#    define   __LCD_PANEL_H__
-
-#if defined (MACH_LPD79520)\
- || defined (MACH_LPD79524)\
- || defined (MACH_LPD7A400)\
- || defined (MACH_LPD7A404)
-# define USE_RGB555
-#endif
-
-struct clcd_panel_extra {
-	unsigned int hrmode;
-	unsigned int clsen;
-	unsigned int spsen;
-	unsigned int pcdel;
-	unsigned int revdel;
-	unsigned int lpdel;
-	unsigned int spldel;
-	unsigned int pc2del;
-};
-
-#define NS_TO_CLOCK(ns,c)	((((ns)*((c)/1000) + (1000000 - 1))/1000000))
-#define CLOCK_TO_DIV(e,c)	(((c) + (e) - 1)/(e))
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
-
-	/* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
-	/* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
-
-#define PIX_CLOCK_TARGET	(6800000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "3.5in QVGA (LQ035Q7DB02)",
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 16,
-		.right_margin	= 21,
-		.upper_margin	= 8,			// line/8/8/8
-		.lower_margin	= 5,
-		.hsync_len	= 61,
-		.vsync_len	= NS_TO_CLOCK (60, PIX_CLOCK),
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#define HAS_LCD_PANEL_EXTRA
-
-static struct clcd_panel_extra lcd_panel_extra = {
-	.hrmode = 1,
-	.clsen = 1,
-	.spsen = 1,
-	.pcdel = 8,
-	.revdel = 7,
-	.lpdel = 13,
-	.spldel = 77,
-	.pc2del = 208,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
-
-	/* Logic Product Development LCD 5.7" QVGA -10 */
-	/* Sharp PN LQ057Q3DC02 */
-	/* QVGA mode, V/Q=LOW */
-
-/* From Sharp on 2006.1.3.  I believe some of the values are incorrect
- * based on the datasheet.
-
-    Timing0	TIMING1		TIMING2		CONTROL
-    0x140A0C4C	0x080504EF	0x013F380D	0x00000829
-    HBP= 20	VBP=  8		BCD=  0
-    HFP= 10	VFP=  5		CPL=319
-    HSW= 12	VSW=  1		IOE=  0
-    PPL= 19	LPP=239		IPC=  1
-				IHS=  1
-				IVS=  1
-				ACB=  0
-				CSEL= 0
-				PCD= 13
-
- */
-
-/* The full horizontal cycle (Th) is clock/360/400/450. */
-/* The full vertical   cycle (Tv) is line/251/262/280. */
-
-#define PIX_CLOCK_TARGET	(6300000) /* -/6.3/7 MHz */
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "5.7in QVGA (LQ057Q3DC02)",
-		.xres		= 320,
-		.yres		= 240,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 11,
-		.right_margin	= 400-11-320-2,
-		.upper_margin	= 7,			// line/7/7/7
-		.lower_margin	= 262-7-240-2,
-		.hsync_len	= 2,			// clk/2/96/200
-		.vsync_len	= 2,			// line/2/-/34
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
-
-	/* Logic Product Development LCD 6.4" VGA -10 */
-	/* Sharp PN LQ64D343 */
-
-/* The full horizontal cycle (Th) is clock/750/800/900. */
-/* The full vertical   cycle (Tv) is line/515/525/560. */
-
-#define PIX_CLOCK_TARGET	(28330000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "6.4in QVGA (LQ64D343)",
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 32,
-		.right_margin	= 800-32-640-96,
-		.upper_margin	= 32,			// line/34/34/34
-		.lower_margin	= 540-32-480-2,
-		.hsync_len	= 96,			// clk/2/96/200
-		.vsync_len	= 2,			// line/2/-/34
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
-
-	/* Logic Product Development LCD 10.4" VGA -10 */
-	/* Sharp PN LQ10D368 */
-
-#define PIX_CLOCK_TARGET	(28330000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "10.4in VGA (LQ10D368)",
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 21,
-		.right_margin	= 15,
-		.upper_margin	= 34,
-		.lower_margin	= 5,
-		.hsync_len	= 96,
-		.vsync_len	= 16,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
-
-	/* Logic Product Development LCD 12.1" SVGA -10 */
-	/* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
-
-/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
- * target clock frequency range of 35MHz to 42MHz. */
-
-/* If the target pixel clock is substantially lower than the panel
- * spec, this is done to prevent the LCD display from glitching when
- * the CPU is under load.  A pixel clock higher than 25MHz
- * (empirically determined) will compete with the CPU for bus cycles
- * for the Ethernet chip.  However, even a pixel clock of 10MHz
- * competes with Compact Flash interface during some operations
- * (fdisk, e2fsck).  And, at that speed the display may have a visible
- * flicker. */
-
-/* The full horizontal cycle (Th) is clock/832/1056/1395. */
-
-#define PIX_CLOCK_TARGET	(20000000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "12.1in SVGA (LQ121S1DG41)",
-		.xres		= 800,
-		.yres		= 600,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 89,		// ns/5/-/(1/PIX_CLOCK)-10
-		.right_margin	= 1056-800-89-128,
-		.upper_margin	= 23,		// line/23/23/23
-		.lower_margin	= 44,
-		.hsync_len	= 128,		// clk/2/128/200
-		.vsync_len	= 4,		// line/2/4/6
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_HITACHI
-
-	/* Hitachi*/
-	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
-
-#define PIX_CLOCK_TARGET	(49000000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "Hitachi 800x480",
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 88,
-		.right_margin	= 40,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 128,
-		.vsync_len	= 2,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-
-#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
-
-	/* AU Optotronics  A070VW01 7.0 Wide Screen color Display*/
-	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
-
-#define PIX_CLOCK_TARGET	(10000000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "7.0in Wide (A070VW01)",
-		.xres		= 480,
-		.yres		= 234,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 30,
-		.right_margin	= 25,
-		.upper_margin	= 14,
-		.lower_margin	= 12,
-		.hsync_len	= 100,
-		.vsync_len	= 1,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#undef NS_TO_CLOCK
-#undef CLOCK_TO_DIV
-
-#endif  /* __LCD_PANEL_H__ */
diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c
deleted file mode 100644
index 2901d49..0000000
--- a/arch/arm/mach-lh7a40x/ssp-cpld.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/* arch/arm/mach-lh7a40x/ssp-cpld.c
- *
- *  Copyright (C) 2004,2005 Marc Singer
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  version 2 as published by the Free Software Foundation.
- *
- * SSP/SPI driver for the CardEngine CPLD.
- *
- */
-
-/* NOTES
-   -----
-
-   o *** This driver is cribbed from the 7952x implementation.
-	 Some comments may not apply.
-
-   o This driver contains sufficient logic to control either the
-     serial EEPROMs or the audio codec.  It is included in the kernel
-     to support the codec.  The EEPROMs are really the responsibility
-     of the boot loader and should probably be left alone.
-
-   o The code must be augmented to cope with multiple, simultaneous
-     clients.
-     o The audio codec writes to the codec chip whenever playback
-       starts.
-     o The touchscreen driver writes to the ads chip every time it
-       samples.
-     o The audio codec must write 16 bits, but the touch chip writes
-       are 8 bits long.
-     o We need to be able to keep these configurations separate while
-       simultaneously active.
-
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-//#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-//#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <mach/ssp.h>
-
-//#define TALK
-
-#if defined (TALK)
-#define PRINTK(f...)		printk (f)
-#else
-#define PRINTK(f...)		do {} while (0)
-#endif
-
-#if defined (CONFIG_ARCH_LH7A400)
-# define CPLD_SPID		__REGP16(CPLD06_VIRT) /* SPI data */
-# define CPLD_SPIC		__REGP16(CPLD08_VIRT) /* SPI control */
-# define CPLD_SPIC_CS_CODEC	(1<<0)
-# define CPLD_SPIC_CS_TOUCH	(1<<1)
-# define CPLD_SPIC_WRITE	(0<<2)
-# define CPLD_SPIC_READ		(1<<2)
-# define CPLD_SPIC_DONE		(1<<3) /* r/o */
-# define CPLD_SPIC_LOAD		(1<<4)
-# define CPLD_SPIC_START	(1<<4)
-# define CPLD_SPIC_LOADED	(1<<5) /* r/o */
-#endif
-
-#define CPLD_SPI		__REGP16(CPLD0A_VIRT) /* SPI operation */
-#define CPLD_SPI_CS_EEPROM	(1<<3)
-#define CPLD_SPI_SCLK		(1<<2)
-#define CPLD_SPI_TX_SHIFT	(1)
-#define CPLD_SPI_TX		(1<<CPLD_SPI_TX_SHIFT)
-#define CPLD_SPI_RX_SHIFT	(0)
-#define CPLD_SPI_RX		(1<<CPLD_SPI_RX_SHIFT)
-
-/* *** FIXME: these timing values are substantially larger than the
-   *** chip requires. We may implement an nsleep () function. */
-#define T_SKH	1		/* Clock time high (us) */
-#define T_SKL	1		/* Clock time low (us) */
-#define T_CS	1		/* Minimum chip select low time (us)  */
-#define T_CSS	1		/* Minimum chip select setup time (us)  */
-#define T_DIS	1		/* Data setup time (us) */
-
-	 /* EEPROM SPI bits */
-#define P_START		(1<<9)
-#define P_WRITE		(1<<7)
-#define P_READ		(2<<7)
-#define P_ERASE		(3<<7)
-#define P_EWDS		(0<<7)
-#define P_WRAL		(0<<7)
-#define P_ERAL		(0<<7)
-#define P_EWEN		(0<<7)
-#define P_A_EWDS	(0<<5)
-#define P_A_WRAL	(1<<5)
-#define P_A_ERAL	(2<<5)
-#define P_A_EWEN	(3<<5)
-
-struct ssp_configuration {
-	int device;
-	int mode;
-	int speed;
-	int frame_size_write;
-	int frame_size_read;
-};
-
-static struct ssp_configuration ssp_configuration;
-static spinlock_t ssp_lock;
-
-static void enable_cs (void)
-{
-	switch (ssp_configuration.device) {
-	case DEVICE_EEPROM:
-		CPLD_SPI |= CPLD_SPI_CS_EEPROM;
-		break;
-	}
-	udelay (T_CSS);
-}
-
-static void disable_cs (void)
-{
-	switch (ssp_configuration.device) {
-	case DEVICE_EEPROM:
-		CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
-		break;
-	}
-	udelay (T_CS);
-}
-
-static void pulse_clock (void)
-{
-	CPLD_SPI |=  CPLD_SPI_SCLK;
-	udelay (T_SKH);
-	CPLD_SPI &= ~CPLD_SPI_SCLK;
-	udelay (T_SKL);
-}
-
-
-/* execute_spi_command
-
-   sends an spi command to a device.  It first sends cwrite bits from
-   v.  If cread is greater than zero it will read cread bits
-   (discarding the leading 0 bit) and return them.  If cread is less
-   than zero it will check for completetion status and return 0 on
-   success or -1 on timeout.  If cread is zero it does nothing other
-   than sending the command.
-
-   On the LPD7A400, we can only read or write multiples of 8 bits on
-   the codec and the touch screen device.  Here, we round up.
-
-*/
-
-static int execute_spi_command (int v, int cwrite, int cread)
-{
-	unsigned long l = 0;
-
-#if defined (CONFIG_MACH_LPD7A400)
-	/* The codec and touch devices cannot be bit-banged.  Instead,
-	 * the CPLD provides an eight-bit shift register and a crude
-	 * interface.  */
-	if (   ssp_configuration.device == DEVICE_CODEC
-	    || ssp_configuration.device == DEVICE_TOUCH) {
-		int select = 0;
-
-		PRINTK ("spi(%d %d.%d) 0x%04x",
-			ssp_configuration.device, cwrite, cread,
-			v);
-#if defined (TALK)
-		if (ssp_configuration.device == DEVICE_CODEC)
-			PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
-#endif
-		PRINTK ("\n");
-
-		if (ssp_configuration.device == DEVICE_CODEC)
-			select = CPLD_SPIC_CS_CODEC;
-		if (ssp_configuration.device == DEVICE_TOUCH)
-			select = CPLD_SPIC_CS_TOUCH;
-		if (cwrite) {
-			for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
-				CPLD_SPID = (v >> (8*cwrite)) & 0xff;
-				CPLD_SPIC = select | CPLD_SPIC_LOAD;
-				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
-					;
-				CPLD_SPIC = select;
-				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
-					;
-			}
-			v = 0;
-		}
-		if (cread) {
-			mdelay (2);	/* *** FIXME: required by ads7843? */
-			v = 0;
-			for (cread = (cread + 7)/8; cread-- > 0;) {
-				CPLD_SPID = 0;
-				CPLD_SPIC = select | CPLD_SPIC_READ
-					| CPLD_SPIC_START;
-				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
-					;
-				CPLD_SPIC = select | CPLD_SPIC_READ;
-				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
-					;
-				v = (v << 8) | CPLD_SPID;
-			}
-		}
-		return v;
-	}
-#endif
-
-	PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
-		v & 0x1ff, (v >> 9) & 0x7f);
-
-	enable_cs ();
-
-	v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
-	while (cwrite--) {
-		CPLD_SPI
-			= (CPLD_SPI & ~CPLD_SPI_TX)
-			| ((v >> cwrite) & CPLD_SPI_TX);
-		udelay (T_DIS);
-		pulse_clock ();
-	}
-
-	if (cread < 0) {
-		int delay = 10;
-		disable_cs ();
-		udelay (1);
-		enable_cs ();
-
-		l = -1;
-		do {
-			if (CPLD_SPI & CPLD_SPI_RX) {
-				l = 0;
-				break;
-			}
-		} while (udelay (1), --delay);
-	}
-	else
-	/* We pulse the clock before the data to skip the leading zero. */
-		while (cread-- > 0) {
-			pulse_clock ();
-			l = (l<<1)
-				| (((CPLD_SPI & CPLD_SPI_RX)
-				    >> CPLD_SPI_RX_SHIFT) & 0x1);
-		}
-
-	disable_cs ();
-	return l;
-}
-
-static int ssp_init (void)
-{
-	spin_lock_init (&ssp_lock);
-	memset (&ssp_configuration, 0, sizeof (ssp_configuration));
-	return 0;
-}
-
-
-/* ssp_chip_select
-
-   drops the chip select line for the CPLD shift-register controlled
-   devices.  It doesn't enable chip
-
-*/
-
-static void ssp_chip_select (int enable)
-{
-#if defined (CONFIG_MACH_LPD7A400)
-	int select;
-
-	if (ssp_configuration.device == DEVICE_CODEC)
-		select = CPLD_SPIC_CS_CODEC;
-	else if (ssp_configuration.device == DEVICE_TOUCH)
-		select = CPLD_SPIC_CS_TOUCH;
-	else
-		return;
-
-	if (enable)
-		CPLD_SPIC = select;
-	else
-		CPLD_SPIC = 0;
-#endif
-}
-
-static void ssp_acquire (void)
-{
-	spin_lock (&ssp_lock);
-}
-
-static void ssp_release (void)
-{
-	ssp_chip_select (0);	/* just in case */
-	spin_unlock (&ssp_lock);
-}
-
-static int ssp_configure (int device, int mode, int speed,
-			   int frame_size_write, int frame_size_read)
-{
-	ssp_configuration.device		= device;
-	ssp_configuration.mode			= mode;
-	ssp_configuration.speed			= speed;
-	ssp_configuration.frame_size_write	= frame_size_write;
-	ssp_configuration.frame_size_read	= frame_size_read;
-
-	return 0;
-}
-
-static int ssp_read (void)
-{
-	return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
-}
-
-static int ssp_write (u16 data)
-{
-	execute_spi_command (data, ssp_configuration.frame_size_write, 0);
-	return 0;
-}
-
-static int ssp_write_read (u16 data)
-{
-	return execute_spi_command (data, ssp_configuration.frame_size_write,
-				    ssp_configuration.frame_size_read);
-}
-
-struct ssp_driver lh7a40x_cpld_ssp_driver = {
-	.init		= ssp_init,
-	.acquire	= ssp_acquire,
-	.release	= ssp_release,
-	.configure	= ssp_configure,
-	.chip_select	= ssp_chip_select,
-	.read		= ssp_read,
-	.write		= ssp_write,
-	.write_read	= ssp_write_read,
-};
-
-
-MODULE_AUTHOR("Marc Singer");
-MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
deleted file mode 100644
index 4601e425..0000000
--- a/arch/arm/mach-lh7a40x/time.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  arch/arm/mach-lh7a40x/time.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  This program is free software; you can 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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/time.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/leds.h>
-
-#include <asm/mach/time.h>
-#include "common.h"
-
-#if HZ < 100
-# define TIMER_CONTROL	TIMER_CONTROL2
-# define TIMER_LOAD	TIMER_LOAD2
-# define TIMER_CONSTANT	(508469/HZ)
-# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
-# define TIMER_EOI	TIMER_EOI2
-# define TIMER_IRQ	IRQ_T2UI
-#else
-# define TIMER_CONTROL	TIMER_CONTROL3
-# define TIMER_LOAD	TIMER_LOAD3
-# define TIMER_CONSTANT	(3686400/HZ)
-# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC)
-# define TIMER_EOI	TIMER_EOI3
-# define TIMER_IRQ	IRQ_T3UI
-#endif
-
-static irqreturn_t
-lh7a40x_timer_interrupt(int irq, void *dev_id)
-{
-	TIMER_EOI = 0;
-	timer_tick();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction lh7a40x_timer_irq = {
-	.name		= "LHA740x Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= lh7a40x_timer_interrupt,
-};
-
-static void __init lh7a40x_timer_init (void)
-{
-				/* Stop/disable all timers */
-	TIMER_CONTROL1 = 0;
-	TIMER_CONTROL2 = 0;
-	TIMER_CONTROL3 = 0;
-
-	setup_irq (TIMER_IRQ, &lh7a40x_timer_irq);
-
-	TIMER_LOAD = TIMER_CONSTANT;
-	TIMER_CONTROL = TIMER_MODE;
-}
-
-struct sys_timer lh7a40x_timer = {
-	.init		= &lh7a40x_timer_init,
-};
diff --git a/arch/arm/mach-loki/common.c b/arch/arm/mach-loki/common.c
index 818f19d..e41e909 100644
--- a/arch/arm/mach-loki/common.c
+++ b/arch/arm/mach-loki/common.c
@@ -18,6 +18,7 @@
 #include <asm/timex.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <mach/bridge-regs.h>
 #include <mach/loki.h>
 #include <plat/orion_nand.h>
 #include <plat/time.h>
@@ -290,9 +291,15 @@ void __init loki_uart1_init(void)
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init loki_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 static void loki_timer_init(void)
 {
-	orion_time_init(IRQ_LOKI_BRIDGE, LOKI_TCLK);
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_LOKI_BRIDGE, LOKI_TCLK);
 }
 
 struct sys_timer loki_timer = {
diff --git a/arch/arm/mach-loki/common.h b/arch/arm/mach-loki/common.h
index 26054fd..a315dcf 100644
--- a/arch/arm/mach-loki/common.h
+++ b/arch/arm/mach-loki/common.h
@@ -18,6 +18,7 @@ struct mv643xx_eth_platform_data;
  */
 void loki_map_io(void);
 void loki_init(void);
+void loki_init_early(void);
 void loki_init_irq(void);
 
 extern struct mbus_dram_target_info loki_mbus_dram_info;
diff --git a/arch/arm/mach-loki/include/mach/bridge-regs.h b/arch/arm/mach-loki/include/mach/bridge-regs.h
index a3fabf7..fd87732 100644
--- a/arch/arm/mach-loki/include/mach/bridge-regs.h
+++ b/arch/arm/mach-loki/include/mach/bridge-regs.h
@@ -17,11 +17,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	0x0004
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-loki/include/mach/memory.h b/arch/arm/mach-loki/include/mach/memory.h
index 2ed7e6e..6636665 100644
--- a/arch/arm/mach-loki/include/mach/memory.h
+++ b/arch/arm/mach-loki/include/mach/memory.h
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-loki/lb88rc8480-setup.c b/arch/arm/mach-loki/lb88rc8480-setup.c
index a1e75e7..35eae4e 100644
--- a/arch/arm/mach-loki/lb88rc8480-setup.c
+++ b/arch/arm/mach-loki/lb88rc8480-setup.c
@@ -93,6 +93,7 @@ MACHINE_START(LB88RC8480, "Marvell LB88RC8480 Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= lb88rc8480_init,
 	.map_io		= loki_map_io,
+	.init_early	= loki_init_early,
 	.init_irq	= loki_init_irq,
 	.timer		= &loki_timer,
 MACHINE_END
diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-lpc32xx/include/mach/memory.h
index 044e1ac..a647dd6 100644
--- a/arch/arm/mach-lpc32xx/include/mach/memory.h
+++ b/arch/arm/mach-lpc32xx/include/mach/memory.h
@@ -22,6 +22,6 @@
 /*
  * Physical DRAM offset of bank 0
  */
-#define PHYS_OFFSET	UL(0x80000000)
+#define PLAT_PHYS_OFFSET	UL(0x80000000)
 
 #endif
diff --git a/arch/arm/mach-mmp/include/mach/memory.h b/arch/arm/mach-mmp/include/mach/memory.h
index bdb21d7..d68b50a 100644
--- a/arch/arm/mach-mmp/include/mach/memory.h
+++ b/arch/arm/mach-mmp/include/mach/memory.h
@@ -9,6 +9,6 @@
 #ifndef __ASM_MACH_MEMORY_H
 #define __ASM_MACH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif /* __ASM_MACH_MEMORY_H */
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
index 4aec493..2cbf6df 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -11,8 +11,8 @@ extern void __init mmp2_init_irq(void);
 extern void mmp2_clear_pmic_int(void);
 
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/i2c.h>
 
 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index 1801e42..a52b3d2 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -8,8 +8,8 @@ extern void __init pxa168_init_irq(void);
 extern void pxa168_clear_keypad_wakeup(void);
 
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 #include <video/pxa168fb.h>
 #include <plat/pxa27x_keypad.h>
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index f13c49d..91be755 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -7,8 +7,8 @@ extern struct sys_timer pxa910_timer;
 extern void __init pxa910_init_irq(void);
 
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 extern struct pxa_device_desc pxa910_device_uart1;
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 5d3d9ad..1516896 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -45,7 +45,16 @@ config ARCH_MSM8X60
 	select CPU_V7
 	select MSM_V2_TLMM
 	select MSM_GPIOMUX
-	select IOMMU_API
+	select MSM_SCM if SMP
+
+config ARCH_MSM8960
+	bool "MSM8960"
+	select ARCH_MSM_SCORPIONMP
+	select MACH_MSM8960_SIM if (!MACH_MSM8960_RUMI3)
+	select ARM_GIC
+	select CPU_V7
+	select MSM_V2_TLMM
+	select MSM_GPIOMUX
 	select MSM_SCM if SMP
 
 endchoice
@@ -125,11 +134,35 @@ config MACH_MSM8X60_FFA
 	help
 	  Support for the Qualcomm MSM8x60 FFA eval board.
 
+config MACH_MSM8960_SIM
+	depends on ARCH_MSM8960
+	bool "MSM8960 Simulator"
+	help
+	  Support for the Qualcomm MSM8960 simulator.
+
+config MACH_MSM8960_RUMI3
+	depends on ARCH_MSM8960
+	bool "MSM8960 RUMI3"
+	help
+	  Support for the Qualcomm MSM8960 RUMI3 emulator.
+
 endmenu
 
+config MSM_IOMMU
+	bool "MSM IOMMU Support"
+	depends on ARCH_MSM8X60 || ARCH_MSM8960
+	select IOMMU_API
+	default n
+	help
+	  Support for the IOMMUs found on certain Qualcomm SOCs.
+	  These IOMMUs allow virtualization of the address space used by most
+	  cores within the multimedia subsystem.
+
+	  If unsure, say N here.
+
 config IOMMU_PGTABLES_L2
 	def_bool y
-	depends on ARCH_MSM8X60 && MMU && SMP && CPU_DCACHE_DISABLE=n
+	depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
 
 config MSM_DEBUG_UART
 	int
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 94195c1..9519fd2 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,21 +1,16 @@
 obj-y += io.o idle.o timer.o
-ifndef CONFIG_ARCH_MSM8X60
-obj-y += acpuclock-arm11.o
-obj-y += dma.o
-endif
+obj-y += clock.o
+obj-$(CONFIG_DEBUG_FS) += clock-debug.o
 
-ifdef CONFIG_MSM_VIC
-obj-y += irq-vic.o
-else
-ifndef CONFIG_ARCH_MSM8X60
-obj-y += irq.o
-endif
-endif
+obj-$(CONFIG_MSM_VIC) += irq-vic.o
+obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o
+
+obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
+obj-$(CONFIG_ARCH_MSM7X30) += dma.o
+obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o
 
-obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o
 obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
-obj-$(CONFIG_MSM_PROC_COMM) += clock.o
-obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
+
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
@@ -29,12 +24,16 @@ obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
+obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
 
-obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
 ifdef CONFIG_MSM_V2_TLMM
+ifndef CONFIG_ARCH_MSM8960
+# TODO: TLMM Mapping issues need to be resolved
 obj-y	+= gpio-v2.o
+endif
 else
 obj-y	+= gpio.o
 endif
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 75dabb1..18a3c97 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -93,8 +93,6 @@ static void __init halibut_map_io(void)
 }
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
 	.boot_params	= 0x10000100,
 	.fixup		= halibut_fixup,
 	.map_io		= halibut_map_io,
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index ef3ebf2..7a9a03e 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -74,8 +74,6 @@ static void __init mahimahi_map_io(void)
 extern struct sys_timer msm_timer;
 
 MACHINE_START(MAHIMAHI, "mahimahi")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
 	.boot_params	= 0x20000100,
 	.fixup		= mahimahi_fixup,
 	.map_io		= mahimahi_map_io,
diff --git a/arch/arm/mach-msm/board-msm7x27.c b/arch/arm/mach-msm/board-msm7x27.c
index e7a76ef..c03f269 100644
--- a/arch/arm/mach-msm/board-msm7x27.c
+++ b/arch/arm/mach-msm/board-msm7x27.c
@@ -130,9 +130,7 @@ static void __init msm7x2x_map_io(void)
 }
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -140,9 +138,7 @@ MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
 MACHINE_END
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -150,9 +146,7 @@ MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
 MACHINE_END
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -160,9 +154,7 @@ MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
 MACHINE_END
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 6f3b973..b7a8496 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -23,19 +23,21 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/usb/msm_hsusb.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/memory.h>
 #include <asm/setup.h>
 
 #include <mach/gpio.h>
 #include <mach/board.h>
-#include <mach/memory.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
 
 #include <mach/vreg.h>
 #include "devices.h"
+#include "gpiomux.h"
 #include "proc_comm.h"
 
 extern struct sys_timer msm_timer;
@@ -52,6 +54,27 @@ static struct msm_otg_platform_data msm_otg_pdata = {
 	.otg_control		= OTG_PHY_CONTROL,
 };
 
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+#ifdef CONFIG_SERIAL_MSM_CONSOLE
+	[49] = { /* UART2 RFR */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+	[50] = { /* UART2 CTS */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+	[51] = { /* UART2 RX */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+	[52] = { /* UART2 TX */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+#endif
+};
+
 static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
         &msm_device_uart2,
@@ -83,9 +106,7 @@ static void __init msm7x30_map_io(void)
 }
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -93,9 +114,7 @@ MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -103,9 +122,7 @@ MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
diff --git a/arch/arm/mach-msm/board-msm8960.c b/arch/arm/mach-msm/board-msm8960.c
new file mode 100644
index 0000000..1993721
--- /dev/null
+++ b/arch/arm/mach-msm/board-msm8960.c
@@ -0,0 +1,91 @@
+/* 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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clkdev.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+
+#include "devices.h"
+
+static void __init msm8960_map_io(void)
+{
+	msm_map_msm8960_io();
+}
+
+static void __init msm8960_init_irq(void)
+{
+	unsigned int i;
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+		 (void *)MSM_QGIC_CPU_BASE);
+
+	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+	if (machine_is_msm8960_rumi3())
+		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+
+	/* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+	 * as they are configured as level, which does not play nice with
+	 * handle_percpu_irq.
+	 */
+	for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+		if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+			set_irq_handler(i, handle_percpu_irq);
+	}
+}
+
+static struct platform_device *sim_devices[] __initdata = {
+	&msm8960_device_uart_gsbi2,
+};
+
+static struct platform_device *rumi3_devices[] __initdata = {
+	&msm8960_device_uart_gsbi5,
+};
+
+static void __init msm8960_sim_init(void)
+{
+	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
+}
+
+static void __init msm8960_rumi3_init(void)
+{
+	platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
+}
+
+MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
+	.map_io = msm8960_map_io,
+	.init_irq = msm8960_init_irq,
+	.timer = &msm_timer,
+	.init_machine = msm8960_sim_init,
+MACHINE_END
+
+MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
+	.map_io = msm8960_map_io,
+	.init_irq = msm8960_init_irq,
+	.timer = &msm_timer,
+	.init_machine = msm8960_rumi3_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 9b5eb2b..b3c55f1 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -28,10 +28,6 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-unsigned long clk_get_max_axi_khz(void)
-{
-	return 0;
-}
 
 static void __init msm8x60_map_io(void)
 {
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 6dde818..7f56861 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* 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
@@ -21,6 +21,8 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/usb/msm_hsusb.h>
+#include <linux/err.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -31,6 +33,8 @@
 #include <mach/irqs.h>
 #include <mach/sirc.h>
 #include <mach/gpio.h>
+#include <mach/vreg.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
@@ -95,6 +99,81 @@ static struct platform_device *devices[] __initdata = {
 	&msm_device_hsusb_host,
 };
 
+static struct msm_mmc_gpio sdc1_gpio_cfg[] = {
+	{51, "sdc1_dat_3"},
+	{52, "sdc1_dat_2"},
+	{53, "sdc1_dat_1"},
+	{54, "sdc1_dat_0"},
+	{55, "sdc1_cmd"},
+	{56, "sdc1_clk"}
+};
+
+static struct vreg *vreg_mmc;
+static unsigned long vreg_sts;
+
+static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd)
+{
+	int rc = 0;
+	struct platform_device *pdev;
+
+	pdev = container_of(dv, struct platform_device, dev);
+
+	if (vdd == 0) {
+		if (!vreg_sts)
+			return 0;
+
+		clear_bit(pdev->id, &vreg_sts);
+
+		if (!vreg_sts) {
+			rc = vreg_disable(vreg_mmc);
+			if (rc)
+				pr_err("vreg_mmc disable failed for slot "
+						"%d: %d\n", pdev->id, rc);
+		}
+		return 0;
+	}
+
+	if (!vreg_sts) {
+		rc = vreg_set_level(vreg_mmc, 2900);
+		if (rc)
+			pr_err("vreg_mmc set level failed for slot %d: %d\n",
+					pdev->id, rc);
+		rc = vreg_enable(vreg_mmc);
+		if (rc)
+			pr_err("vreg_mmc enable failed for slot %d: %d\n",
+					pdev->id, rc);
+	}
+	set_bit(pdev->id, &vreg_sts);
+	return 0;
+}
+
+static struct msm_mmc_gpio_data sdc1_gpio = {
+	.gpio = sdc1_gpio_cfg,
+	.size = ARRAY_SIZE(sdc1_gpio_cfg),
+};
+
+static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
+	.ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
+	.translate_vdd	= msm_sdcc_setup_power,
+	.gpio_data = &sdc1_gpio,
+};
+
+static void __init qsd8x50_init_mmc(void)
+{
+	if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa())
+		vreg_mmc = vreg_get(NULL, "gp6");
+	else
+		vreg_mmc = vreg_get(NULL, "gp5");
+
+	if (IS_ERR(vreg_mmc)) {
+		pr_err("vreg get for vreg_mmc failed (%ld)\n",
+				PTR_ERR(vreg_mmc));
+		return;
+	}
+
+	msm_add_sdcc(1, &qsd8x50_sdc1_data, 0, 0);
+}
+
 static void __init qsd8x50_map_io(void)
 {
 	msm_map_qsd8x50_io();
@@ -113,12 +192,11 @@ static void __init qsd8x50_init(void)
 	msm_device_hsusb.dev.parent = &msm_device_otg.dev;
 	msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
 	platform_add_devices(devices, ARRAY_SIZE(devices));
+	qsd8x50_init_mmc();
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
@@ -126,9 +204,7 @@ MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index 8919ffb..68f930f 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -105,9 +105,7 @@ static void __init sapphire_map_io(void)
 
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params    = PHYS_OFFSET + 0x100,
+	.boot_params    = PLAT_PHYS_OFFSET + 0x100,
 	.fixup          = sapphire_fixup,
 	.map_io         = sapphire_map_io,
 	.init_irq       = sapphire_init_irq,
diff --git a/arch/arm/mach-msm/board-trout-gpio.c b/arch/arm/mach-msm/board-trout-gpio.c
index a604ec1..31117a4 100644
--- a/arch/arm/mach-msm/board-trout-gpio.c
+++ b/arch/arm/mach-msm/board-trout-gpio.c
@@ -74,8 +74,6 @@ static int msm_gpiolib_direction_output(struct gpio_chip *chip,
 
 static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
-
 	return TROUT_GPIO_TO_INT(offset + chip->base);
 }
 
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 73f1460..8143867 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -92,8 +93,6 @@ static void __init trout_map_io(void)
 }
 
 MACHINE_START(TROUT, "HTC Dream")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
 	.boot_params	= 0x10000100,
 	.fixup		= trout_fixup,
 	.map_io		= trout_map_io,
diff --git a/arch/arm/mach-msm/clock-7x30.h b/arch/arm/mach-msm/clock-7x30.h
index e16f72f..1410445 100644
--- a/arch/arm/mach-msm/clock-7x30.h
+++ b/arch/arm/mach-msm/clock-7x30.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 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 __ARCH_ARM_MACH_MSM_CLOCK_7X30_H
@@ -147,22 +130,26 @@ void pll_disable(uint32_t pll);
 extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable);
 
 #define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = L_7X30_##clk_id, \
-	.remote_id = P_##clk_id, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	.dbg_name = #clk_id, \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &(struct clk){ \
+		.id = L_7X30_##clk_id, \
+		.remote_id = P_##clk_id, \
+		.flags = clk_flags, \
+		.dbg_name = #clk_id, \
+	}, \
 	}
 
 #define CLK_7X30S(clk_name, l_id, r_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = L_7X30_##l_id, \
-	.remote_id = P_##r_id, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	.dbg_name = #l_id, \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &(struct clk){ \
+		.id = L_7X30_##l_id, \
+		.remote_id = P_##r_id, \
+		.flags = clk_flags, \
+		.dbg_name = #l_id, \
+		.ops = &clk_ops_pcom, \
+	}, \
 	}
 
 #endif
-
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
new file mode 100644
index 0000000..4886404
--- /dev/null
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/clk.h>
+#include "clock.h"
+
+static int clock_debug_rate_set(void *data, u64 val)
+{
+	struct clk *clock = data;
+	int ret;
+
+	/* Only increases to max rate will succeed, but that's actually good
+	 * for debugging purposes so we don't check for error. */
+	if (clock->flags & CLK_MAX)
+		clk_set_max_rate(clock, val);
+	if (clock->flags & CLK_MIN)
+		ret = clk_set_min_rate(clock, val);
+	else
+		ret = clk_set_rate(clock, val);
+	if (ret != 0)
+		printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
+			(clock->flags & CLK_MIN) ? "_min" : "", ret);
+	return ret;
+}
+
+static int clock_debug_rate_get(void *data, u64 *val)
+{
+	struct clk *clock = data;
+	*val = clk_get_rate(clock);
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
+			clock_debug_rate_set, "%llu\n");
+
+static int clock_debug_enable_set(void *data, u64 val)
+{
+	struct clk *clock = data;
+	int rc = 0;
+
+	if (val)
+		rc = clock->ops->enable(clock->id);
+	else
+		clock->ops->disable(clock->id);
+
+	return rc;
+}
+
+static int clock_debug_enable_get(void *data, u64 *val)
+{
+	struct clk *clock = data;
+
+	*val = clock->ops->is_enabled(clock->id);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
+			clock_debug_enable_set, "%llu\n");
+
+static int clock_debug_local_get(void *data, u64 *val)
+{
+	struct clk *clock = data;
+
+	*val = clock->ops->is_local(clock->id);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
+			NULL, "%llu\n");
+
+static struct dentry *debugfs_base;
+
+int __init clock_debug_init(void)
+{
+	debugfs_base = debugfs_create_dir("clk", NULL);
+	if (!debugfs_base)
+		return -ENOMEM;
+	return 0;
+}
+
+int __init clock_debug_add(struct clk *clock)
+{
+	char temp[50], *ptr;
+	struct dentry *clk_dir;
+
+	if (!debugfs_base)
+		return -ENOMEM;
+
+	strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
+	for (ptr = temp; *ptr; ptr++)
+		*ptr = tolower(*ptr);
+
+	clk_dir = debugfs_create_dir(temp, debugfs_base);
+	if (!clk_dir)
+		return -ENOMEM;
+
+	if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir,
+				clock, &clock_rate_fops))
+		goto error;
+
+	if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir,
+				clock, &clock_enable_fops))
+		goto error;
+
+	if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock,
+				&clock_local_fops))
+		goto error;
+	return 0;
+error:
+	debugfs_remove_recursive(clk_dir);
+	return -ENOMEM;
+}
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
deleted file mode 100644
index 1250d22..0000000
--- a/arch/arm/mach-msm/clock-dummy.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/module.h>
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	return ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get);
-
-int clk_enable(struct clk *clk)
-{
-	return -ENOENT;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return -ENOENT;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index a3b4562..63b7113 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -20,6 +20,7 @@
 
 #include "proc_comm.h"
 #include "clock.h"
+#include "clock-pcom.h"
 
 /*
  * glue for the proc_comm interface
@@ -116,6 +117,11 @@ long pc_clk_round_rate(unsigned id, unsigned rate)
 	return rate;
 }
 
+static bool pc_clk_is_local(unsigned id)
+{
+	return false;
+}
+
 struct clk_ops clk_ops_pcom = {
 	.enable = pc_clk_enable,
 	.disable = pc_clk_disable,
@@ -128,4 +134,5 @@ struct clk_ops clk_ops_pcom = {
 	.get_rate = pc_clk_get_rate,
 	.is_enabled = pc_clk_is_enabled,
 	.round_rate = pc_clk_round_rate,
+	.is_local = pc_clk_is_local,
 };
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
index 17d027b..974d003 100644
--- a/arch/arm/mach-msm/clock-pcom.h
+++ b/arch/arm/mach-msm/clock-pcom.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 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 __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H
@@ -132,8 +115,10 @@
 #define P_CSI1_P_CLK		97
 #define P_GSBI_CLK		98
 #define P_GSBI_P_CLK		99
+#define P_CE_CLK		100 /* Crypto engine */
+#define P_CODEC_SSBI_CLK	101
 
-#define P_NR_CLKS		100
+#define P_NR_CLKS		102
 
 struct clk_ops;
 extern struct clk_ops clk_ops_pcom;
@@ -141,13 +126,15 @@ extern struct clk_ops clk_ops_pcom;
 int pc_clk_reset(unsigned id, enum clk_reset_action action);
 
 #define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = P_##clk_id, \
-	.remote_id = P_##clk_id, \
-	.ops = &clk_ops_pcom, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	.dbg_name = #clk_id, \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &(struct clk){ \
+		.id = P_##clk_id, \
+		.remote_id = P_##clk_id, \
+		.ops = &clk_ops_pcom, \
+		.flags = clk_flags, \
+		.dbg_name = #clk_id, \
+	}, \
 	}
 
 #endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 2069bfa..22a5376 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -15,74 +15,32 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/list.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/ctype.h>
 #include <linux/pm_qos_params.h>
-#include <mach/clk.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/clkdev.h>
 
 #include "clock.h"
-#include "proc_comm.h"
-#include "clock-7x30.h"
 
 static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 static LIST_HEAD(clocks);
-struct clk *msm_clocks;
-unsigned msm_num_clocks;
-
-/*
- * Bitmap of enabled clocks, excluding ACPU which is always
- * enabled
- */
-static DECLARE_BITMAP(clock_map_enabled, NR_CLKS);
-static DEFINE_SPINLOCK(clock_map_lock);
 
 /*
  * Standard clock functions defined in include/linux/clk.h
  */
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *clk;
-
-	mutex_lock(&clocks_mutex);
-
-	list_for_each_entry(clk, &clocks, list)
-		if (!strcmp(id, clk->name) && clk->dev == dev)
-			goto found_it;
-
-	list_for_each_entry(clk, &clocks, list)
-		if (!strcmp(id, clk->name) && clk->dev == NULL)
-			goto found_it;
-
-	clk = ERR_PTR(-ENOENT);
-found_it:
-	mutex_unlock(&clocks_mutex);
-	return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&clocks_lock, flags);
 	clk->count++;
-	if (clk->count == 1) {
+	if (clk->count == 1)
 		clk->ops->enable(clk->id);
-		spin_lock(&clock_map_lock);
-		clock_map_enabled[BIT_WORD(clk->id)] |= BIT_MASK(clk->id);
-		spin_unlock(&clock_map_lock);
-	}
 	spin_unlock_irqrestore(&clocks_lock, flags);
 	return 0;
 }
@@ -94,20 +52,14 @@ void clk_disable(struct clk *clk)
 	spin_lock_irqsave(&clocks_lock, flags);
 	BUG_ON(clk->count == 0);
 	clk->count--;
-	if (clk->count == 0) {
+	if (clk->count == 0)
 		clk->ops->disable(clk->id);
-		spin_lock(&clock_map_lock);
-		clock_map_enabled[BIT_WORD(clk->id)] &= ~BIT_MASK(clk->id);
-		spin_unlock(&clock_map_lock);
-	}
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
 int clk_reset(struct clk *clk, enum clk_reset_action action)
 {
-	if (!clk->ops->reset)
-		clk->ops->reset = &pc_clk_reset;
 	return clk->ops->reset(clk->remote_id, action);
 }
 EXPORT_SYMBOL(clk_reset);
@@ -184,25 +136,14 @@ EXPORT_SYMBOL(clk_set_flags);
  */
 static struct clk *ebi1_clk;
 
-static void __init set_clock_ops(struct clk *clk)
-{
-	if (!clk->ops) {
-		clk->ops = &clk_ops_pcom;
-		clk->id = clk->remote_id;
-	}
-}
-
-void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
+void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks)
 {
 	unsigned n;
 
-	spin_lock_init(&clocks_lock);
 	mutex_lock(&clocks_mutex);
-	msm_clocks = clock_tbl;
-	msm_num_clocks = num_clocks;
-	for (n = 0; n < msm_num_clocks; n++) {
-		set_clock_ops(&msm_clocks[n]);
-		list_add_tail(&msm_clocks[n].list, &clocks);
+	for (n = 0; n < num_clocks; n++) {
+		clkdev_add(&clock_tbl[n]);
+		list_add_tail(&clock_tbl[n].clk->list, &clocks);
 	}
 	mutex_unlock(&clocks_mutex);
 
@@ -211,115 +152,6 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
 
 }
 
-#if defined(CONFIG_DEBUG_FS)
-static struct clk *msm_clock_get_nth(unsigned index)
-{
-	if (index < msm_num_clocks)
-		return msm_clocks + index;
-	else
-		return 0;
-}
-
-static int clock_debug_rate_set(void *data, u64 val)
-{
-	struct clk *clock = data;
-	int ret;
-
-	/* Only increases to max rate will succeed, but that's actually good
-	 * for debugging purposes. So we don't check for error. */
-	if (clock->flags & CLK_MAX)
-		clk_set_max_rate(clock, val);
-	if (clock->flags & CLK_MIN)
-		ret = clk_set_min_rate(clock, val);
-	else
-		ret = clk_set_rate(clock, val);
-	if (ret != 0)
-		printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
-			(clock->flags & CLK_MIN) ? "_min" : "", ret);
-	return ret;
-}
-
-static int clock_debug_rate_get(void *data, u64 *val)
-{
-	struct clk *clock = data;
-	*val = clk_get_rate(clock);
-	return 0;
-}
-
-static int clock_debug_enable_set(void *data, u64 val)
-{
-	struct clk *clock = data;
-	int rc = 0;
-
-	if (val)
-		rc = clock->ops->enable(clock->id);
-	else
-		clock->ops->disable(clock->id);
-
-	return rc;
-}
-
-static int clock_debug_enable_get(void *data, u64 *val)
-{
-	struct clk *clock = data;
-
-	*val = clock->ops->is_enabled(clock->id);
-
-	return 0;
-}
-
-static int clock_debug_local_get(void *data, u64 *val)
-{
-	struct clk *clock = data;
-
-	*val = clock->ops != &clk_ops_pcom;
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
-			clock_debug_rate_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
-			clock_debug_enable_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
-			NULL, "%llu\n");
-
-static int __init clock_debug_init(void)
-{
-	struct dentry *dent_rate, *dent_enable, *dent_local;
-	struct clk *clock;
-	unsigned n = 0;
-	char temp[50], *ptr;
-
-	dent_rate = debugfs_create_dir("clk_rate", 0);
-	if (IS_ERR(dent_rate))
-		return PTR_ERR(dent_rate);
-
-	dent_enable = debugfs_create_dir("clk_enable", 0);
-	if (IS_ERR(dent_enable))
-		return PTR_ERR(dent_enable);
-
-	dent_local = debugfs_create_dir("clk_local", NULL);
-	if (IS_ERR(dent_local))
-		return PTR_ERR(dent_local);
-
-	while ((clock = msm_clock_get_nth(n++)) != 0) {
-		strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
-		for (ptr = temp; *ptr; ptr++)
-			*ptr = tolower(*ptr);
-		debugfs_create_file(temp, 0644, dent_rate,
-				    clock, &clock_rate_fops);
-		debugfs_create_file(temp, 0644, dent_enable,
-				    clock, &clock_enable_fops);
-		debugfs_create_file(temp, S_IRUGO, dent_local,
-				    clock, &clock_local_fops);
-	}
-	return 0;
-}
-
-device_initcall(clock_debug_init);
-#endif
-
 /* The bootloader and/or AMSS may have left various clocks enabled.
  * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
  * not been explicitly enabled by a clk_enable() call.
@@ -330,8 +162,10 @@ static int __init clock_late_init(void)
 	struct clk *clk;
 	unsigned count = 0;
 
+	clock_debug_init();
 	mutex_lock(&clocks_mutex);
 	list_for_each_entry(clk, &clocks, list) {
+		clock_debug_add(clk);
 		if (clk->flags & CLKFLAG_AUTO_OFF) {
 			spin_lock_irqsave(&clocks_lock, flags);
 			if (!clk->count) {
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index c270b55..2c007f6 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -17,12 +17,10 @@
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
 #define __ARCH_ARM_MACH_MSM_CLOCK_H
 
+#include <linux/init.h>
 #include <linux/list.h>
 #include <mach/clk.h>
 
-#include "clock-pcom.h"
-#include "clock-7x30.h"
-
 #define CLKFLAG_INVERT			0x00000001
 #define CLKFLAG_NOINVERT		0x00000002
 #define CLKFLAG_NONEST			0x00000004
@@ -45,6 +43,7 @@ struct clk_ops {
 	unsigned (*get_rate)(unsigned id);
 	unsigned (*is_enabled)(unsigned id);
 	long (*round_rate)(unsigned id, unsigned rate);
+	bool (*is_local)(unsigned id);
 };
 
 struct clk {
@@ -52,58 +51,22 @@ struct clk {
 	uint32_t remote_id;
 	uint32_t count;
 	uint32_t flags;
-	const char *name;
 	struct clk_ops *ops;
 	const char *dbg_name;
 	struct list_head list;
-	struct device *dev;
 };
 
-#define A11S_CLK_CNTL_ADDR		(MSM_CSR_BASE + 0x100)
-#define A11S_CLK_SEL_ADDR		(MSM_CSR_BASE + 0x104)
-#define A11S_VDD_SVS_PLEVEL_ADDR	(MSM_CSR_BASE + 0x124)
-
-#ifdef CONFIG_DEBUG_FS
-#define CLOCK_DBG_NAME(x) .dbg_name = x,
-#else
-#define CLOCK_DBG_NAME(x)
-#endif
-
-#define CLOCK(clk_name, clk_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = clk_id, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	 CLOCK_DBG_NAME(#clk_id) \
-	}
-
 #define OFF CLKFLAG_AUTO_OFF
 #define CLK_MIN CLKFLAG_MIN
 #define CLK_MAX CLKFLAG_MAX
 #define CLK_MINMAX (CLK_MIN | CLK_MAX)
-#define NR_CLKS	P_NR_CLKS
-
-enum {
-	PLL_0 = 0,
-	PLL_1,
-	PLL_2,
-	PLL_3,
-	PLL_4,
-	PLL_5,
-	PLL_6,
-	NUM_PLL
-};
-
-enum clkvote_client {
-	CLKVOTE_ACPUCLK = 0,
-	CLKVOTE_PMQOS,
-	CLKVOTE_MAX,
-};
-
-int msm_clock_require_tcxo(unsigned long *reason, int nbits);
-int msm_clock_get_name(uint32_t id, char *name, uint32_t size);
-int ebi1_clk_set_min_rate(enum clkvote_client client, unsigned long rate);
-unsigned long clk_get_max_axi_khz(void);
 
+#ifdef CONFIG_DEBUG_FS
+int __init clock_debug_init(void);
+int __init clock_debug_add(struct clk *clock);
+#else
+static inline int __init clock_debug_init(void) { return 0; }
+static inline int __init clock_debug_add(struct clk *clock) { return 0; }
 #endif
 
+#endif
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
new file mode 100644
index 0000000..24030d0
--- /dev/null
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -0,0 +1,911 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <mach/irqs.h>
+#include <mach/iommu.h>
+
+static struct resource msm_iommu_jpegd_resources[] = {
+	{
+		.start = 0x07300000,
+		.end   = 0x07300000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+		.end   = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vpe_resources[] = {
+	{
+		.start = 0x07400000,
+		.end   = 0x07400000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VPE_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VPE_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_mdp0_resources[] = {
+	{
+		.start = 0x07500000,
+		.end   = 0x07500000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_MDP0_CB_SC_SECURE_IRQ,
+		.end   = SMMU_MDP0_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_mdp1_resources[] = {
+	{
+		.start = 0x07600000,
+		.end   = 0x07600000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_MDP1_CB_SC_SECURE_IRQ,
+		.end   = SMMU_MDP1_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_rot_resources[] = {
+	{
+		.start = 0x07700000,
+		.end   = 0x07700000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_ROT_CB_SC_SECURE_IRQ,
+		.end   = SMMU_ROT_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_ijpeg_resources[] = {
+	{
+		.start = 0x07800000,
+		.end   = 0x07800000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+		.end   = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vfe_resources[] = {
+	{
+		.start = 0x07900000,
+		.end   = 0x07900000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VFE_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VFE_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vcodec_a_resources[] = {
+	{
+		.start = 0x07A00000,
+		.end   = 0x07A00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vcodec_b_resources[] = {
+	{
+		.start = 0x07B00000,
+		.end   = 0x07B00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_gfx3d_resources[] = {
+	{
+		.start = 0x07C00000,
+		.end   = 0x07C00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_gfx2d0_resources[] = {
+	{
+		.start = 0x07D00000,
+		.end   = 0x07D00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_gfx2d1_resources[] = {
+	{
+		.start = 0x07E00000,
+		.end   = 0x07E00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm_root_iommu_dev = {
+	.name = "msm_iommu",
+	.id = -1,
+};
+
+static struct msm_iommu_dev jpegd_iommu = {
+	.name = "jpegd",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vpe_iommu = {
+	.name = "vpe",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev mdp0_iommu = {
+	.name = "mdp0",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev mdp1_iommu = {
+	.name = "mdp1",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev rot_iommu = {
+	.name = "rot",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev ijpeg_iommu = {
+	.name = "ijpeg",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vfe_iommu = {
+	.name = "vfe",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vcodec_a_iommu = {
+	.name = "vcodec_a",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vcodec_b_iommu = {
+	.name = "vcodec_b",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev gfx3d_iommu = {
+	.name = "gfx3d",
+	.ncb = 3,
+};
+
+static struct msm_iommu_dev gfx2d0_iommu = {
+	.name = "gfx2d0",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev gfx2d1_iommu = {
+	.name = "gfx2d1",
+	.ncb = 2,
+};
+
+static struct platform_device msm_device_iommu_jpegd = {
+	.name = "msm_iommu",
+	.id = 0,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
+	.resource = msm_iommu_jpegd_resources,
+};
+
+static struct platform_device msm_device_iommu_vpe = {
+	.name = "msm_iommu",
+	.id = 1,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
+	.resource = msm_iommu_vpe_resources,
+};
+
+static struct platform_device msm_device_iommu_mdp0 = {
+	.name = "msm_iommu",
+	.id = 2,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
+	.resource = msm_iommu_mdp0_resources,
+};
+
+static struct platform_device msm_device_iommu_mdp1 = {
+	.name = "msm_iommu",
+	.id = 3,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
+	.resource = msm_iommu_mdp1_resources,
+};
+
+static struct platform_device msm_device_iommu_rot = {
+	.name = "msm_iommu",
+	.id = 4,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
+	.resource = msm_iommu_rot_resources,
+};
+
+static struct platform_device msm_device_iommu_ijpeg = {
+	.name = "msm_iommu",
+	.id = 5,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
+	.resource = msm_iommu_ijpeg_resources,
+};
+
+static struct platform_device msm_device_iommu_vfe = {
+	.name = "msm_iommu",
+	.id = 6,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
+	.resource = msm_iommu_vfe_resources,
+};
+
+static struct platform_device msm_device_iommu_vcodec_a = {
+	.name = "msm_iommu",
+	.id = 7,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
+	.resource = msm_iommu_vcodec_a_resources,
+};
+
+static struct platform_device msm_device_iommu_vcodec_b = {
+	.name = "msm_iommu",
+	.id = 8,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
+	.resource = msm_iommu_vcodec_b_resources,
+};
+
+static struct platform_device msm_device_iommu_gfx3d = {
+	.name = "msm_iommu",
+	.id = 9,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
+	.resource = msm_iommu_gfx3d_resources,
+};
+
+static struct platform_device msm_device_iommu_gfx2d0 = {
+	.name = "msm_iommu",
+	.id = 10,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
+	.resource = msm_iommu_gfx2d0_resources,
+};
+
+struct platform_device msm_device_iommu_gfx2d1 = {
+	.name = "msm_iommu",
+	.id = 11,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
+	.resource = msm_iommu_gfx2d1_resources,
+};
+
+static struct msm_iommu_ctx_dev jpegd_src_ctx = {
+	.name = "jpegd_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
+	.name = "jpegd_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_src_ctx = {
+	.name = "vpe_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_dst_ctx = {
+	.name = "vpe_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
+	.name = "mdp_vg1",
+	.num = 0,
+	.mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
+	.name = "mdp_rgb1",
+	.num = 1,
+	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
+	.name = "mdp_vg2",
+	.num = 0,
+	.mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
+	.name = "mdp_rgb2",
+	.num = 1,
+	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_src_ctx = {
+	.name = "rot_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_dst_ctx = {
+	.name = "rot_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
+	.name = "ijpeg_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
+	.name = "ijpeg_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
+	.name = "vfe_imgwr",
+	.num = 0,
+	.mids = {2, 3, 4, 5, 6, 7, 8, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_misc_ctx = {
+	.name = "vfe_misc",
+	.num = 1,
+	.mids = {0, 1, 9, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
+	.name = "vcodec_a_stream",
+	.num = 0,
+	.mids = {2, 5, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
+	.name = "vcodec_a_mm1",
+	.num = 1,
+	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
+	.name = "vcodec_b_mm2",
+	.num = 0,
+	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_user_ctx = {
+	.name = "gfx3d_user",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_priv_ctx = {
+	.name = "gfx3d_priv",
+	.num = 1,
+	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+		 31, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
+	.name = "gfx2d0_2d0",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
+	.name = "gfx2d1_2d1",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct platform_device msm_device_jpegd_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 0,
+	.dev = {
+		.parent = &msm_device_iommu_jpegd.dev,
+	},
+};
+
+static struct platform_device msm_device_jpegd_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 1,
+	.dev = {
+		.parent = &msm_device_iommu_jpegd.dev,
+	},
+};
+
+static struct platform_device msm_device_vpe_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 2,
+	.dev = {
+		.parent = &msm_device_iommu_vpe.dev,
+	},
+};
+
+static struct platform_device msm_device_vpe_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 3,
+	.dev = {
+		.parent = &msm_device_iommu_vpe.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_vg1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 4,
+	.dev = {
+		.parent = &msm_device_iommu_mdp0.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_rgb1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 5,
+	.dev = {
+		.parent = &msm_device_iommu_mdp0.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_vg2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 6,
+	.dev = {
+		.parent = &msm_device_iommu_mdp1.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_rgb2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 7,
+	.dev = {
+		.parent = &msm_device_iommu_mdp1.dev,
+	},
+};
+
+static struct platform_device msm_device_rot_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 8,
+	.dev = {
+		.parent = &msm_device_iommu_rot.dev,
+	},
+};
+
+static struct platform_device msm_device_rot_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 9,
+	.dev = {
+		.parent = &msm_device_iommu_rot.dev,
+	},
+};
+
+static struct platform_device msm_device_ijpeg_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 10,
+	.dev = {
+		.parent = &msm_device_iommu_ijpeg.dev,
+	},
+};
+
+static struct platform_device msm_device_ijpeg_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 11,
+	.dev = {
+		.parent = &msm_device_iommu_ijpeg.dev,
+	},
+};
+
+static struct platform_device msm_device_vfe_imgwr_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 12,
+	.dev = {
+		.parent = &msm_device_iommu_vfe.dev,
+	},
+};
+
+static struct platform_device msm_device_vfe_misc_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 13,
+	.dev = {
+		.parent = &msm_device_iommu_vfe.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_a_stream_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 14,
+	.dev = {
+		.parent = &msm_device_iommu_vcodec_a.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_a_mm1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 15,
+	.dev = {
+		.parent = &msm_device_iommu_vcodec_a.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_b_mm2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 16,
+	.dev = {
+		.parent = &msm_device_iommu_vcodec_b.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_user_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 17,
+	.dev = {
+		.parent = &msm_device_iommu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_priv_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 18,
+	.dev = {
+		.parent = &msm_device_iommu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx2d0_2d0_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 19,
+	.dev = {
+		.parent = &msm_device_iommu_gfx2d0.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx2d1_2d1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 20,
+	.dev = {
+		.parent = &msm_device_iommu_gfx2d1.dev,
+	},
+};
+
+static struct platform_device *msm_iommu_devs[] = {
+	&msm_device_iommu_jpegd,
+	&msm_device_iommu_vpe,
+	&msm_device_iommu_mdp0,
+	&msm_device_iommu_mdp1,
+	&msm_device_iommu_rot,
+	&msm_device_iommu_ijpeg,
+	&msm_device_iommu_vfe,
+	&msm_device_iommu_vcodec_a,
+	&msm_device_iommu_vcodec_b,
+	&msm_device_iommu_gfx3d,
+	&msm_device_iommu_gfx2d0,
+	&msm_device_iommu_gfx2d1,
+};
+
+static struct msm_iommu_dev *msm_iommu_data[] = {
+	&jpegd_iommu,
+	&vpe_iommu,
+	&mdp0_iommu,
+	&mdp1_iommu,
+	&rot_iommu,
+	&ijpeg_iommu,
+	&vfe_iommu,
+	&vcodec_a_iommu,
+	&vcodec_b_iommu,
+	&gfx3d_iommu,
+	&gfx2d0_iommu,
+	&gfx2d1_iommu,
+};
+
+static struct platform_device *msm_iommu_ctx_devs[] = {
+	&msm_device_jpegd_src_ctx,
+	&msm_device_jpegd_dst_ctx,
+	&msm_device_vpe_src_ctx,
+	&msm_device_vpe_dst_ctx,
+	&msm_device_mdp_vg1_ctx,
+	&msm_device_mdp_rgb1_ctx,
+	&msm_device_mdp_vg2_ctx,
+	&msm_device_mdp_rgb2_ctx,
+	&msm_device_rot_src_ctx,
+	&msm_device_rot_dst_ctx,
+	&msm_device_ijpeg_src_ctx,
+	&msm_device_ijpeg_dst_ctx,
+	&msm_device_vfe_imgwr_ctx,
+	&msm_device_vfe_misc_ctx,
+	&msm_device_vcodec_a_stream_ctx,
+	&msm_device_vcodec_a_mm1_ctx,
+	&msm_device_vcodec_b_mm2_ctx,
+	&msm_device_gfx3d_user_ctx,
+	&msm_device_gfx3d_priv_ctx,
+	&msm_device_gfx2d0_2d0_ctx,
+	&msm_device_gfx2d1_2d1_ctx,
+};
+
+static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
+	&jpegd_src_ctx,
+	&jpegd_dst_ctx,
+	&vpe_src_ctx,
+	&vpe_dst_ctx,
+	&mdp_vg1_ctx,
+	&mdp_rgb1_ctx,
+	&mdp_vg2_ctx,
+	&mdp_rgb2_ctx,
+	&rot_src_ctx,
+	&rot_dst_ctx,
+	&ijpeg_src_ctx,
+	&ijpeg_dst_ctx,
+	&vfe_imgwr_ctx,
+	&vfe_misc_ctx,
+	&vcodec_a_stream_ctx,
+	&vcodec_a_mm1_ctx,
+	&vcodec_b_mm2_ctx,
+	&gfx3d_user_ctx,
+	&gfx3d_priv_ctx,
+	&gfx2d0_2d0_ctx,
+	&gfx2d1_2d1_ctx,
+};
+
+static int __init msm8x60_iommu_init(void)
+{
+	int ret, i;
+
+	ret = platform_device_register(&msm_root_iommu_dev);
+	if (ret != 0) {
+		pr_err("Failed to register root IOMMU device!\n");
+		goto failure;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
+		ret = platform_device_add_data(msm_iommu_devs[i],
+					       msm_iommu_data[i],
+					       sizeof(struct msm_iommu_dev));
+		if (ret != 0) {
+			pr_err("platform_device_add_data failed, "
+			       "i = %d\n", i);
+			goto failure_unwind;
+		}
+
+		ret = platform_device_register(msm_iommu_devs[i]);
+
+		if (ret != 0) {
+			pr_err("platform_device_register iommu failed, "
+			       "i = %d\n", i);
+			goto failure_unwind;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
+		ret = platform_device_add_data(msm_iommu_ctx_devs[i],
+					       msm_iommu_ctx_data[i],
+					       sizeof(*msm_iommu_ctx_devs[i]));
+		if (ret != 0) {
+			pr_err("platform_device_add_data iommu failed, "
+			       "i = %d\n", i);
+			goto failure_unwind2;
+		}
+
+		ret = platform_device_register(msm_iommu_ctx_devs[i]);
+		if (ret != 0) {
+			pr_err("platform_device_register ctx failed, "
+			       "i = %d\n", i);
+			goto failure_unwind2;
+		}
+	}
+	return 0;
+
+failure_unwind2:
+	while (--i >= 0)
+		platform_device_unregister(msm_iommu_ctx_devs[i]);
+failure_unwind:
+	while (--i >= 0)
+		platform_device_unregister(msm_iommu_devs[i]);
+
+	platform_device_unregister(&msm_root_iommu_dev);
+failure:
+	return ret;
+}
+
+static void __exit msm8x60_iommu_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
+		platform_device_unregister(msm_iommu_ctx_devs[i]);
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
+		platform_device_unregister(msm_iommu_devs[i]);
+
+	platform_device_unregister(&msm_root_iommu_dev);
+}
+
+subsys_initcall(msm8x60_iommu_init);
+module_exit(msm8x60_iommu_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index fb548a8..c4f5e26 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/clkdev.h>
 
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
@@ -24,8 +25,8 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
-
 #include "clock.h"
+#include "clock-pcom.h"
 #include <mach/mmc.h>
 
 static struct resource resources_uart1[] = {
@@ -38,6 +39,7 @@ static struct resource resources_uart1[] = {
 		.start	= MSM_UART1_PHYS,
 		.end	= MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -51,6 +53,7 @@ static struct resource resources_uart2[] = {
 		.start	= MSM_UART2_PHYS,
 		.end	= MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -64,6 +67,7 @@ static struct resource resources_uart3[] = {
 		.start	= MSM_UART3_PHYS,
 		.end	= MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -414,7 +418,7 @@ struct platform_device msm_device_mdp = {
 	.resource = resources_mdp,
 };
 
-struct clk msm_clocks_7x01a[] = {
+struct clk_lookup msm_clocks_7x01a[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, 0),
@@ -423,7 +427,7 @@ struct clk msm_clocks_7x01a[] = {
 	CLK_PCOM("emdh_clk",	EMDH_CLK,	NULL, OFF),
 	CLK_PCOM("gp_clk",		GP_CLK,		NULL, 0),
 	CLK_PCOM("grp_clk",	GRP_3D_CLK,	NULL, OFF),
-	CLK_PCOM("i2c_clk",	I2C_CLK,	&msm_device_i2c.dev, 0),
+	CLK_PCOM("i2c_clk",	I2C_CLK,	"msm_i2c.0", 0),
 	CLK_PCOM("icodec_rx_clk",	ICODEC_RX_CLK,	NULL, 0),
 	CLK_PCOM("icodec_tx_clk",	ICODEC_TX_CLK,	NULL, 0),
 	CLK_PCOM("imem_clk",	IMEM_CLK,	NULL, OFF),
@@ -433,25 +437,25 @@ struct clk msm_clocks_7x01a[] = {
 	CLK_PCOM("pcm_clk",	PCM_CLK,	NULL, 0),
 	CLK_PCOM("mddi_clk",	PMDH_CLK,	NULL, OFF | CLK_MINMAX),
 	CLK_PCOM("sdac_clk",	SDAC_CLK,	NULL, OFF),
-	CLK_PCOM("sdc_clk",	SDC1_CLK,	&msm_device_sdc1.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	&msm_device_sdc1.dev, OFF),
-	CLK_PCOM("sdc_clk",	SDC2_CLK,	&msm_device_sdc2.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC2_P_CLK,	&msm_device_sdc2.dev, OFF),
-	CLK_PCOM("sdc_clk",	SDC3_CLK,	&msm_device_sdc3.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC3_P_CLK,	&msm_device_sdc3.dev, OFF),
-	CLK_PCOM("sdc_clk",	SDC4_CLK,	&msm_device_sdc4.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC4_P_CLK,	&msm_device_sdc4.dev, OFF),
+	CLK_PCOM("sdc_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_pclk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_clk",	SDC3_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_pclk",	SDC3_P_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_clk",	SDC4_CLK,	"msm_sdcc.4", OFF),
+	CLK_PCOM("sdc_pclk",	SDC4_P_CLK,	"msm_sdcc.4", OFF),
 	CLK_PCOM("tsif_clk",	TSIF_CLK,	NULL, 0),
 	CLK_PCOM("tsif_ref_clk",	TSIF_REF_CLK,	NULL, 0),
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
-	CLK_PCOM("uart_clk",	UART1_CLK,	&msm_device_uart1.dev, OFF),
-	CLK_PCOM("uart_clk",	UART2_CLK,	&msm_device_uart2.dev, 0),
-	CLK_PCOM("uart_clk",	UART3_CLK,	&msm_device_uart3.dev, OFF),
+	CLK_PCOM("uart_clk",	UART1_CLK,	"msm_serial.0", OFF),
+	CLK_PCOM("uart_clk",	UART2_CLK,	"msm_serial.1", 0),
+	CLK_PCOM("uart_clk",	UART3_CLK,	"msm_serial.2", OFF),
 	CLK_PCOM("uart1dm_clk",	UART1DM_CLK,	NULL, OFF),
 	CLK_PCOM("uart2dm_clk",	UART2DM_CLK,	NULL, 0),
-	CLK_PCOM("usb_hs_clk",	USB_HS_CLK,	&msm_device_hsusb.dev, OFF),
-	CLK_PCOM("usb_hs_pclk",	USB_HS_P_CLK,	&msm_device_hsusb.dev, OFF),
+	CLK_PCOM("usb_hs_clk",	USB_HS_CLK,	"msm_hsusb", OFF),
+	CLK_PCOM("usb_hs_pclk",	USB_HS_P_CLK,	"msm_hsusb", OFF),
 	CLK_PCOM("usb_otg_clk",	USB_OTG_CLK,	NULL, 0),
 	CLK_PCOM("vdc_clk",	VDC_CLK,	NULL, OFF ),
 	CLK_PCOM("vfe_clk",	VFE_CLK,	NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 4e9a0ab..09b4f14 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/clkdev.h>
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
@@ -28,6 +29,7 @@
 #include <asm/mach/flash.h>
 
 #include "clock-pcom.h"
+#include "clock-7x30.h"
 
 #include <mach/mmc.h>
 
@@ -41,6 +43,7 @@ static struct resource resources_uart2[] = {
 		.start	= MSM_UART2_PHYS,
 		.end	= MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -127,11 +130,13 @@ struct platform_device msm_device_hsusb_host = {
 	},
 };
 
-struct clk msm_clocks_7x30[] = {
+struct clk_lookup msm_clocks_7x30[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
 	CLK_PCOM("cam_m_clk",	CAM_M_CLK,	NULL, 0),
 	CLK_PCOM("camif_pad_pclk",	CAMIF_PAD_P_CLK,	NULL, OFF),
+	CLK_PCOM("ce_clk",	CE_CLK,	NULL, 0),
+	CLK_PCOM("codec_ssbi_clk",	CODEC_SSBI_CLK,	NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, CLK_MIN),
 	CLK_PCOM("ecodec_clk",	ECODEC_CLK,	NULL, 0),
 	CLK_PCOM("emdh_clk",	EMDH_CLK,	NULL, OFF | CLK_MINMAX),
@@ -177,7 +182,7 @@ struct clk msm_clocks_7x30[] = {
 	CLK_7X30S("tv_src_clk",	TV_CLK, 	TV_ENC_CLK,	NULL, 0),
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
-	CLK_PCOM("uart_clk",	UART2_CLK,	&msm_device_uart2.dev, 0),
+	CLK_PCOM("uart_clk",	UART2_CLK,	"msm_serial.1", 0),
 	CLK_PCOM("usb_phy_clk",	USB_PHY_CLK,	NULL, 0),
 	CLK_PCOM("usb_hs_clk",		USB_HS_CLK,		NULL, OFF),
 	CLK_PCOM("usb_hs_pclk",		USB_HS_P_CLK,		NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-msm8960.c b/arch/arm/mach-msm/devices-msm8960.c
new file mode 100644
index 0000000..d9e1f26
--- /dev/null
+++ b/arch/arm/mach-msm/devices-msm8960.c
@@ -0,0 +1,85 @@
+/* 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <linux/dma-mapping.h>
+#include <mach/irqs-8960.h>
+#include <mach/board.h>
+
+#include "devices.h"
+
+#define MSM_GSBI2_PHYS		0x16100000
+#define MSM_UART2DM_PHYS	(MSM_GSBI2_PHYS + 0x40000)
+
+#define MSM_GSBI5_PHYS		0x16400000
+#define MSM_UART5DM_PHYS	(MSM_GSBI5_PHYS + 0x40000)
+
+static struct resource resources_uart_gsbi2[] = {
+	{
+		.start	= GSBI2_UARTDM_IRQ,
+		.end	= GSBI2_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART2DM_PHYS,
+		.end	= MSM_UART2DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uart_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI2_PHYS,
+		.end	= MSM_GSBI2_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_uart_gsbi2 = {
+	.name	= "msm_serial",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart_gsbi2),
+	.resource	= resources_uart_gsbi2,
+};
+
+static struct resource resources_uart_gsbi5[] = {
+	{
+		.start	= GSBI5_UARTDM_IRQ,
+		.end	= GSBI5_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART5DM_PHYS,
+		.end	= MSM_UART5DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uart_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI5_PHYS,
+		.end	= MSM_GSBI5_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_uart_gsbi5 = {
+	.name	= "msm_serial",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart_gsbi5),
+	.resource	= resources_uart_gsbi5,
+};
diff --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c
deleted file mode 100644
index f9e7bd3..0000000
--- a/arch/arm/mach-msm/devices-msm8x60-iommu.c
+++ /dev/null
@@ -1,906 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/bootmem.h>
-
-#include <mach/msm_iomap-8x60.h>
-#include <mach/irqs-8x60.h>
-#include <mach/iommu.h>
-
-static struct resource msm_iommu_jpegd_resources[] = {
-	{
-		.start = MSM_IOMMU_JPEGD_PHYS,
-		.end   = MSM_IOMMU_JPEGD_PHYS + MSM_IOMMU_JPEGD_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
-		.end   = SMMU_JPEGD_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vpe_resources[] = {
-	{
-		.start = MSM_IOMMU_VPE_PHYS,
-		.end   = MSM_IOMMU_VPE_PHYS + MSM_IOMMU_VPE_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VPE_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VPE_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_mdp0_resources[] = {
-	{
-		.start = MSM_IOMMU_MDP0_PHYS,
-		.end   = MSM_IOMMU_MDP0_PHYS + MSM_IOMMU_MDP0_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_MDP0_CB_SC_SECURE_IRQ,
-		.end   = SMMU_MDP0_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_mdp1_resources[] = {
-	{
-		.start = MSM_IOMMU_MDP1_PHYS,
-		.end   = MSM_IOMMU_MDP1_PHYS + MSM_IOMMU_MDP1_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_MDP1_CB_SC_SECURE_IRQ,
-		.end   = SMMU_MDP1_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_rot_resources[] = {
-	{
-		.start = MSM_IOMMU_ROT_PHYS,
-		.end   = MSM_IOMMU_ROT_PHYS + MSM_IOMMU_ROT_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_ROT_CB_SC_SECURE_IRQ,
-		.end   = SMMU_ROT_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_ijpeg_resources[] = {
-	{
-		.start = MSM_IOMMU_IJPEG_PHYS,
-		.end   = MSM_IOMMU_IJPEG_PHYS + MSM_IOMMU_IJPEG_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
-		.end   = SMMU_IJPEG_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vfe_resources[] = {
-	{
-		.start = MSM_IOMMU_VFE_PHYS,
-		.end   = MSM_IOMMU_VFE_PHYS + MSM_IOMMU_VFE_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VFE_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VFE_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vcodec_a_resources[] = {
-	{
-		.start = MSM_IOMMU_VCODEC_A_PHYS,
-		.end   = MSM_IOMMU_VCODEC_A_PHYS + MSM_IOMMU_VCODEC_A_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vcodec_b_resources[] = {
-	{
-		.start = MSM_IOMMU_VCODEC_B_PHYS,
-		.end   = MSM_IOMMU_VCODEC_B_PHYS + MSM_IOMMU_VCODEC_B_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx3d_resources[] = {
-	{
-		.start = MSM_IOMMU_GFX3D_PHYS,
-		.end   = MSM_IOMMU_GFX3D_PHYS + MSM_IOMMU_GFX3D_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX3D_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx2d0_resources[] = {
-	{
-		.start = MSM_IOMMU_GFX2D0_PHYS,
-		.end   = MSM_IOMMU_GFX2D0_PHYS + MSM_IOMMU_GFX2D0_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx2d1_resources[] = {
-	{
-		.start = MSM_IOMMU_GFX2D1_PHYS,
-		.end   = MSM_IOMMU_GFX2D1_PHYS + MSM_IOMMU_GFX2D1_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device msm_root_iommu_dev = {
-	.name = "msm_iommu",
-	.id = -1,
-};
-
-static struct msm_iommu_dev jpegd_iommu = {
-	.name = "jpegd",
-	.clk_rate = -1
-};
-
-static struct msm_iommu_dev vpe_iommu = {
-	.name = "vpe"
-};
-
-static struct msm_iommu_dev mdp0_iommu = {
-	.name = "mdp0"
-};
-
-static struct msm_iommu_dev mdp1_iommu = {
-	.name = "mdp1"
-};
-
-static struct msm_iommu_dev rot_iommu = {
-	.name = "rot"
-};
-
-static struct msm_iommu_dev ijpeg_iommu = {
-	.name = "ijpeg"
-};
-
-static struct msm_iommu_dev vfe_iommu = {
-	.name = "vfe",
-	.clk_rate = -1
-};
-
-static struct msm_iommu_dev vcodec_a_iommu = {
-	.name = "vcodec_a"
-};
-
-static struct msm_iommu_dev vcodec_b_iommu = {
-	.name = "vcodec_b"
-};
-
-static struct msm_iommu_dev gfx3d_iommu = {
-	.name = "gfx3d",
-	.clk_rate = 27000000
-};
-
-static struct msm_iommu_dev gfx2d0_iommu = {
-	.name = "gfx2d0",
-	.clk_rate = 27000000
-};
-
-static struct msm_iommu_dev gfx2d1_iommu = {
-	.name = "gfx2d1",
-	.clk_rate = 27000000
-};
-
-static struct platform_device msm_device_iommu_jpegd = {
-	.name = "msm_iommu",
-	.id = 0,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
-	.resource = msm_iommu_jpegd_resources,
-};
-
-static struct platform_device msm_device_iommu_vpe = {
-	.name = "msm_iommu",
-	.id = 1,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
-	.resource = msm_iommu_vpe_resources,
-};
-
-static struct platform_device msm_device_iommu_mdp0 = {
-	.name = "msm_iommu",
-	.id = 2,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
-	.resource = msm_iommu_mdp0_resources,
-};
-
-static struct platform_device msm_device_iommu_mdp1 = {
-	.name = "msm_iommu",
-	.id = 3,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
-	.resource = msm_iommu_mdp1_resources,
-};
-
-static struct platform_device msm_device_iommu_rot = {
-	.name = "msm_iommu",
-	.id = 4,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
-	.resource = msm_iommu_rot_resources,
-};
-
-static struct platform_device msm_device_iommu_ijpeg = {
-	.name = "msm_iommu",
-	.id = 5,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
-	.resource = msm_iommu_ijpeg_resources,
-};
-
-static struct platform_device msm_device_iommu_vfe = {
-	.name = "msm_iommu",
-	.id = 6,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
-	.resource = msm_iommu_vfe_resources,
-};
-
-static struct platform_device msm_device_iommu_vcodec_a = {
-	.name = "msm_iommu",
-	.id = 7,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
-	.resource = msm_iommu_vcodec_a_resources,
-};
-
-static struct platform_device msm_device_iommu_vcodec_b = {
-	.name = "msm_iommu",
-	.id = 8,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
-	.resource = msm_iommu_vcodec_b_resources,
-};
-
-static struct platform_device msm_device_iommu_gfx3d = {
-	.name = "msm_iommu",
-	.id = 9,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
-	.resource = msm_iommu_gfx3d_resources,
-};
-
-static struct platform_device msm_device_iommu_gfx2d0 = {
-	.name = "msm_iommu",
-	.id = 10,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
-	.resource = msm_iommu_gfx2d0_resources,
-};
-
-struct platform_device msm_device_iommu_gfx2d1 = {
-	.name = "msm_iommu",
-	.id = 11,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
-	.resource = msm_iommu_gfx2d1_resources,
-};
-
-static struct msm_iommu_ctx_dev jpegd_src_ctx = {
-	.name = "jpegd_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
-	.name = "jpegd_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev vpe_src_ctx = {
-	.name = "vpe_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev vpe_dst_ctx = {
-	.name = "vpe_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
-	.name = "mdp_vg1",
-	.num = 0,
-	.mids = {0, 2, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
-	.name = "mdp_rgb1",
-	.num = 1,
-	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
-	.name = "mdp_vg2",
-	.num = 0,
-	.mids = {0, 2, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
-	.name = "mdp_rgb2",
-	.num = 1,
-	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
-};
-
-static struct msm_iommu_ctx_dev rot_src_ctx = {
-	.name = "rot_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev rot_dst_ctx = {
-	.name = "rot_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
-	.name = "ijpeg_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
-	.name = "ijpeg_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
-	.name = "vfe_imgwr",
-	.num = 0,
-	.mids = {2, 3, 4, 5, 6, 7, 8, -1}
-};
-
-static struct msm_iommu_ctx_dev vfe_misc_ctx = {
-	.name = "vfe_misc",
-	.num = 1,
-	.mids = {0, 1, 9, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
-	.name = "vcodec_a_stream",
-	.num = 0,
-	.mids = {2, 5, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
-	.name = "vcodec_a_mm1",
-	.num = 1,
-	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
-	.name = "vcodec_b_mm2",
-	.num = 0,
-	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_user_ctx = {
-	.name = "gfx3d_user",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_priv_ctx = {
-	.name = "gfx3d_priv",
-	.num = 1,
-	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
-		 31, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
-	.name = "gfx2d0_2d0",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
-	.name = "gfx2d1_2d1",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct platform_device msm_device_jpegd_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 0,
-	.dev = {
-		.parent = &msm_device_iommu_jpegd.dev,
-	},
-};
-
-static struct platform_device msm_device_jpegd_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 1,
-	.dev = {
-		.parent = &msm_device_iommu_jpegd.dev,
-	},
-};
-
-static struct platform_device msm_device_vpe_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 2,
-	.dev = {
-		.parent = &msm_device_iommu_vpe.dev,
-	},
-};
-
-static struct platform_device msm_device_vpe_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 3,
-	.dev = {
-		.parent = &msm_device_iommu_vpe.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_vg1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 4,
-	.dev = {
-		.parent = &msm_device_iommu_mdp0.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_rgb1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 5,
-	.dev = {
-		.parent = &msm_device_iommu_mdp0.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_vg2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 6,
-	.dev = {
-		.parent = &msm_device_iommu_mdp1.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_rgb2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 7,
-	.dev = {
-		.parent = &msm_device_iommu_mdp1.dev,
-	},
-};
-
-static struct platform_device msm_device_rot_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 8,
-	.dev = {
-		.parent = &msm_device_iommu_rot.dev,
-	},
-};
-
-static struct platform_device msm_device_rot_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 9,
-	.dev = {
-		.parent = &msm_device_iommu_rot.dev,
-	},
-};
-
-static struct platform_device msm_device_ijpeg_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 10,
-	.dev = {
-		.parent = &msm_device_iommu_ijpeg.dev,
-	},
-};
-
-static struct platform_device msm_device_ijpeg_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 11,
-	.dev = {
-		.parent = &msm_device_iommu_ijpeg.dev,
-	},
-};
-
-static struct platform_device msm_device_vfe_imgwr_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 12,
-	.dev = {
-		.parent = &msm_device_iommu_vfe.dev,
-	},
-};
-
-static struct platform_device msm_device_vfe_misc_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 13,
-	.dev = {
-		.parent = &msm_device_iommu_vfe.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_a_stream_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 14,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_a.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_a_mm1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 15,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_a.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_b_mm2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 16,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_b.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx3d_user_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 17,
-	.dev = {
-		.parent = &msm_device_iommu_gfx3d.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx3d_priv_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 18,
-	.dev = {
-		.parent = &msm_device_iommu_gfx3d.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d0_2d0_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 19,
-	.dev = {
-		.parent = &msm_device_iommu_gfx2d0.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d1_2d1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 20,
-	.dev = {
-		.parent = &msm_device_iommu_gfx2d1.dev,
-	},
-};
-
-static struct platform_device *msm_iommu_devs[] = {
-	&msm_device_iommu_jpegd,
-	&msm_device_iommu_vpe,
-	&msm_device_iommu_mdp0,
-	&msm_device_iommu_mdp1,
-	&msm_device_iommu_rot,
-	&msm_device_iommu_ijpeg,
-	&msm_device_iommu_vfe,
-	&msm_device_iommu_vcodec_a,
-	&msm_device_iommu_vcodec_b,
-	&msm_device_iommu_gfx3d,
-	&msm_device_iommu_gfx2d0,
-	&msm_device_iommu_gfx2d1,
-};
-
-static struct msm_iommu_dev *msm_iommu_data[] = {
-	&jpegd_iommu,
-	&vpe_iommu,
-	&mdp0_iommu,
-	&mdp1_iommu,
-	&rot_iommu,
-	&ijpeg_iommu,
-	&vfe_iommu,
-	&vcodec_a_iommu,
-	&vcodec_b_iommu,
-	&gfx3d_iommu,
-	&gfx2d0_iommu,
-	&gfx2d1_iommu,
-};
-
-static struct platform_device *msm_iommu_ctx_devs[] = {
-	&msm_device_jpegd_src_ctx,
-	&msm_device_jpegd_dst_ctx,
-	&msm_device_vpe_src_ctx,
-	&msm_device_vpe_dst_ctx,
-	&msm_device_mdp_vg1_ctx,
-	&msm_device_mdp_rgb1_ctx,
-	&msm_device_mdp_vg2_ctx,
-	&msm_device_mdp_rgb2_ctx,
-	&msm_device_rot_src_ctx,
-	&msm_device_rot_dst_ctx,
-	&msm_device_ijpeg_src_ctx,
-	&msm_device_ijpeg_dst_ctx,
-	&msm_device_vfe_imgwr_ctx,
-	&msm_device_vfe_misc_ctx,
-	&msm_device_vcodec_a_stream_ctx,
-	&msm_device_vcodec_a_mm1_ctx,
-	&msm_device_vcodec_b_mm2_ctx,
-	&msm_device_gfx3d_user_ctx,
-	&msm_device_gfx3d_priv_ctx,
-	&msm_device_gfx2d0_2d0_ctx,
-	&msm_device_gfx2d1_2d1_ctx,
-};
-
-static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
-	&jpegd_src_ctx,
-	&jpegd_dst_ctx,
-	&vpe_src_ctx,
-	&vpe_dst_ctx,
-	&mdp_vg1_ctx,
-	&mdp_rgb1_ctx,
-	&mdp_vg2_ctx,
-	&mdp_rgb2_ctx,
-	&rot_src_ctx,
-	&rot_dst_ctx,
-	&ijpeg_src_ctx,
-	&ijpeg_dst_ctx,
-	&vfe_imgwr_ctx,
-	&vfe_misc_ctx,
-	&vcodec_a_stream_ctx,
-	&vcodec_a_mm1_ctx,
-	&vcodec_b_mm2_ctx,
-	&gfx3d_user_ctx,
-	&gfx3d_priv_ctx,
-	&gfx2d0_2d0_ctx,
-	&gfx2d1_2d1_ctx,
-};
-
-static int __init msm8x60_iommu_init(void)
-{
-	int ret, i;
-
-	ret = platform_device_register(&msm_root_iommu_dev);
-	if (ret != 0) {
-		pr_err("Failed to register root IOMMU device!\n");
-		goto failure;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_devs[i],
-					       msm_iommu_data[i],
-					       sizeof(struct msm_iommu_dev));
-		if (ret != 0) {
-			pr_err("platform_device_add_data failed, "
-			       "i = %d\n", i);
-			goto failure_unwind;
-		}
-
-		ret = platform_device_register(msm_iommu_devs[i]);
-
-		if (ret != 0) {
-			pr_err("platform_device_register iommu failed, "
-			       "i = %d\n", i);
-			goto failure_unwind;
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_ctx_devs[i],
-					       msm_iommu_ctx_data[i],
-					       sizeof(*msm_iommu_ctx_devs[i]));
-		if (ret != 0) {
-			pr_err("platform_device_add_data iommu failed, "
-			       "i = %d\n", i);
-			goto failure_unwind2;
-		}
-
-		ret = platform_device_register(msm_iommu_ctx_devs[i]);
-		if (ret != 0) {
-			pr_err("platform_device_register ctx failed, "
-			       "i = %d\n", i);
-			goto failure_unwind2;
-		}
-	}
-	return 0;
-
-failure_unwind2:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
-failure_unwind:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_devs[i]);
-
-	platform_device_unregister(&msm_root_iommu_dev);
-failure:
-	return ret;
-}
-
-static void __exit msm8x60_iommu_exit(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
-		platform_device_unregister(msm_iommu_devs[i]);
-
-	platform_device_unregister(&msm_root_iommu_dev);
-}
-
-subsys_initcall(msm8x60_iommu_init);
-module_exit(msm8x60_iommu_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index a4b798f..12d8deb 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -15,8 +15,9 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
-
+#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
+
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
@@ -27,6 +28,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/mmc.h>
+#include "clock-pcom.h"
 
 static struct resource resources_uart3[] = {
 	{
@@ -38,6 +40,7 @@ static struct resource resources_uart3[] = {
 		.start	= MSM_UART3_PHYS,
 		.end	= MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -124,14 +127,204 @@ struct platform_device msm_device_hsusb_host = {
 	},
 };
 
-struct clk msm_clocks_8x50[] = {
+static struct resource resources_sdc1[] = {
+	{
+		.start	= MSM_SDC1_PHYS,
+		.end	= MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC1_0,
+		.end	= INT_SDC1_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+	{
+		.start	= INT_SDC1_1,
+		.end	= INT_SDC1_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource resources_sdc2[] = {
+	{
+		.start	= MSM_SDC2_PHYS,
+		.end	= MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC2_0,
+		.end	= INT_SDC2_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+		{
+		.start	= INT_SDC2_1,
+		.end	= INT_SDC2_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource resources_sdc3[] = {
+	{
+		.start	= MSM_SDC3_PHYS,
+		.end	= MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC3_0,
+		.end	= INT_SDC3_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+		{
+		.start	= INT_SDC3_1,
+		.end	= INT_SDC3_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource resources_sdc4[] = {
+	{
+		.start	= MSM_SDC4_PHYS,
+		.end	= MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC4_0,
+		.end	= INT_SDC4_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+		{
+		.start	= INT_SDC4_1,
+		.end	= INT_SDC4_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device msm_device_sdc1 = {
+	.name		= "msm_sdcc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(resources_sdc1),
+	.resource	= resources_sdc1,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_sdc2 = {
+	.name		= "msm_sdcc",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(resources_sdc2),
+	.resource	= resources_sdc2,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_sdc3 = {
+	.name		= "msm_sdcc",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(resources_sdc3),
+	.resource	= resources_sdc3,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_sdc4 = {
+	.name		= "msm_sdcc",
+	.id		= 4,
+	.num_resources	= ARRAY_SIZE(resources_sdc4),
+	.resource	= resources_sdc4,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static struct platform_device *msm_sdcc_devices[] __initdata = {
+	&msm_device_sdc1,
+	&msm_device_sdc2,
+	&msm_device_sdc3,
+	&msm_device_sdc4,
+};
+
+int __init msm_add_sdcc(unsigned int controller,
+			struct msm_mmc_platform_data *plat,
+			unsigned int stat_irq, unsigned long stat_irq_flags)
+{
+	struct platform_device	*pdev;
+	struct resource *res;
+
+	if (controller < 1 || controller > 4)
+		return -EINVAL;
+
+	pdev = msm_sdcc_devices[controller-1];
+	pdev->dev.platform_data = plat;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
+	if (!res)
+		return -EINVAL;
+	else if (stat_irq) {
+		res->start = res->end = stat_irq;
+		res->flags &= ~IORESOURCE_DISABLED;
+		res->flags |= stat_irq_flags;
+	}
+
+	return platform_device_register(pdev);
+}
+
+struct clk_lookup msm_clocks_8x50[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
+	CLK_PCOM("ce_clk",	CE_CLK,		NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, CLK_MIN),
 	CLK_PCOM("ebi2_clk",	EBI2_CLK,	NULL, 0),
 	CLK_PCOM("ecodec_clk",	ECODEC_CLK,	NULL, 0),
 	CLK_PCOM("emdh_clk",	EMDH_CLK,	NULL, OFF | CLK_MINMAX),
 	CLK_PCOM("gp_clk",	GP_CLK,		NULL, 0),
 	CLK_PCOM("grp_clk",	GRP_3D_CLK,	NULL, 0),
+	CLK_PCOM("i2c_clk",	I2C_CLK,	NULL, 0),
 	CLK_PCOM("icodec_rx_clk",	ICODEC_RX_CLK,	NULL, 0),
 	CLK_PCOM("icodec_tx_clk",	ICODEC_TX_CLK,	NULL, 0),
 	CLK_PCOM("imem_clk",	IMEM_CLK,	NULL, OFF),
@@ -144,12 +337,24 @@ struct clk msm_clocks_8x50[] = {
 	CLK_PCOM("pbus_clk",	PBUS_CLK,	NULL, CLK_MIN),
 	CLK_PCOM("pcm_clk",	PCM_CLK,	NULL, 0),
 	CLK_PCOM("sdac_clk",	SDAC_CLK,	NULL, OFF),
+	CLK_PCOM("sdc_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_pclk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_clk",	SDC3_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_pclk",	SDC3_P_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_clk",	SDC4_CLK,	"msm_sdcc.4", OFF),
+	CLK_PCOM("sdc_pclk",	SDC4_P_CLK,	"msm_sdcc.4", OFF),
 	CLK_PCOM("spi_clk",	SPI_CLK,	NULL, 0),
 	CLK_PCOM("tsif_clk",	TSIF_CLK,	NULL, 0),
 	CLK_PCOM("tsif_ref_clk",	TSIF_REF_CLK,	NULL, 0),
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
-	CLK_PCOM("uart_clk",	UART3_CLK,	&msm_device_uart3.dev, OFF),
+	CLK_PCOM("uart_clk",	UART1_CLK,	NULL, OFF),
+	CLK_PCOM("uart_clk",	UART2_CLK,	NULL, 0),
+	CLK_PCOM("uart_clk",	UART3_CLK,	"msm_serial.2", OFF),
+	CLK_PCOM("uartdm_clk",	UART1DM_CLK,	NULL, OFF),
+	CLK_PCOM("uartdm_clk",	UART2DM_CLK,	NULL, 0),
 	CLK_PCOM("usb_hs_clk",	USB_HS_CLK,	NULL, OFF),
 	CLK_PCOM("usb_hs_pclk",	USB_HS_P_CLK,	NULL, OFF),
 	CLK_PCOM("usb_otg_clk",	USB_OTG_CLK,	NULL, 0),
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 87c70bf..9545c19 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -16,12 +16,17 @@
 #ifndef __ARCH_ARM_MACH_MSM_DEVICES_H
 #define __ARCH_ARM_MACH_MSM_DEVICES_H
 
+#include <linux/clkdev.h>
+
 #include "clock.h"
 
 extern struct platform_device msm_device_uart1;
 extern struct platform_device msm_device_uart2;
 extern struct platform_device msm_device_uart3;
 
+extern struct platform_device msm8960_device_uart_gsbi2;
+extern struct platform_device msm8960_device_uart_gsbi5;
+
 extern struct platform_device msm_device_sdc1;
 extern struct platform_device msm_device_sdc2;
 extern struct platform_device msm_device_sdc3;
@@ -41,13 +46,13 @@ extern struct platform_device msm_device_mddi0;
 extern struct platform_device msm_device_mddi1;
 extern struct platform_device msm_device_mdp;
 
-extern struct clk msm_clocks_7x01a[];
+extern struct clk_lookup msm_clocks_7x01a[];
 extern unsigned msm_num_clocks_7x01a;
 
-extern struct clk msm_clocks_7x30[];
+extern struct clk_lookup msm_clocks_7x30[];
 extern unsigned msm_num_clocks_7x30;
 
-extern struct clk msm_clocks_8x50[];
+extern struct clk_lookup msm_clocks_8x50[];
 extern unsigned msm_num_clocks_8x50;
 
 #endif
diff --git a/arch/arm/mach-msm/gpiomux-7x30.c b/arch/arm/mach-msm/gpiomux-7x30.c
deleted file mode 100644
index 6ce41c5..0000000
--- a/arch/arm/mach-msm/gpiomux-7x30.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-#include "gpiomux.h"
-
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-	[49] = { /* UART2 RFR */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-	[50] = { /* UART2 CTS */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-	[51] = { /* UART2 RX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-	[52] = { /* UART2 TX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-#endif
-};
diff --git a/arch/arm/mach-msm/gpiomux-8x50.c b/arch/arm/mach-msm/gpiomux-8x50.c
index 4406e0f..f7a4ea5 100644
--- a/arch/arm/mach-msm/gpiomux-8x50.c
+++ b/arch/arm/mach-msm/gpiomux-8x50.c
@@ -16,6 +16,19 @@
  */
 #include "gpiomux.h"
 
+#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
+	#define SDCC_DAT_0_3_CMD_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_UP\
+					| GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
+	#define SDCC_CLK_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\
+					| GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
+#else
+	#define SDCC_DAT_0_3_CMD_ACTV_CFG 0
+	#define SDCC_CLK_ACTV_CFG 0
+#endif
+
+#define SDC1_SUSPEND_CONFIG (GPIOMUX_VALID | GPIOMUX_PULL_DOWN\
+				| GPIOMUX_FUNC_GPIO | GPIOMUX_DRV_2MA)
+
 struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
 	[86] = { /* UART3 RX */
 		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
@@ -25,4 +38,14 @@ struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
 		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
 			     GPIOMUX_FUNC_1 | GPIOMUX_VALID,
 	},
+	/* SDC1 data[3:0] & CMD */
+	[51 ... 55] = {
+		.active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+		.suspended = SDC1_SUSPEND_CONFIG
+	},
+	/* SDC1 CLK */
+	[56] = {
+		.active = SDCC_CLK_ACTV_CFG,
+		.suspended = SDC1_SUSPEND_CONFIG
+	},
 };
diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S
index d0c2143..0c631a9 100644
--- a/arch/arm/mach-msm/headsmp.S
+++ b/arch/arm/mach-msm/headsmp.S
@@ -11,7 +11,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
-	__INIT
+	__CPUINIT
 
 /*
  * MSM specific entry point for secondary CPUs.  This provides
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 6abf4a6..2ce8f1f 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -31,7 +31,7 @@ struct msm_acpu_clock_platform_data
 	unsigned long wait_for_irq_khz;
 };
 
-struct clk;
+struct clk_lookup;
 
 extern struct sys_timer msm_timer;
 
@@ -41,7 +41,7 @@ void __init msm_add_devices(void);
 void __init msm_map_common_io(void);
 void __init msm_init_irq(void);
 void __init msm_init_gpio(void);
-void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks);
+void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks);
 void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *);
 int __init msm_add_sdcc(unsigned int controller,
 			struct msm_mmc_platform_data *plat,
diff --git a/arch/arm/mach-msm/include/mach/clk.h b/arch/arm/mach-msm/include/mach/clk.h
index c05ca40..e8d3842 100644
--- a/arch/arm/mach-msm/include/mach/clk.h
+++ b/arch/arm/mach-msm/include/mach/clk.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 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 __MACH_CLK_H
 #define __MACH_CLK_H
diff --git a/arch/arm/mach-msm/include/mach/clkdev.h b/arch/arm/mach-msm/include/mach/clkdev.h
new file mode 100644
index 0000000..f87a57b
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/clkdev.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef __ASM_ARCH_MSM_CLKDEV_H
+#define __ASM_ARCH_MSM_CLKDEV_H
+
+struct clk;
+
+static inline int __clk_get(struct clk *clk) { return 1; }
+static inline void __clk_put(struct clk *clk) { }
+#endif
diff --git a/arch/arm/mach-msm/include/mach/cpu.h b/arch/arm/mach-msm/include/mach/cpu.h
new file mode 100644
index 0000000..a9481b0
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/cpu.h
@@ -0,0 +1,54 @@
+/* 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/io.h b/arch/arm/mach-msm/include/mach/io.h
index 7386e73..dc1b928 100644
--- a/arch/arm/mach-msm/include/mach/io.h
+++ b/arch/arm/mach-msm/include/mach/io.h
@@ -29,6 +29,7 @@ void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int m
 void msm_map_qsd8x50_io(void);
 void msm_map_msm7x30_io(void);
 void msm_map_msm8x60_io(void);
+void msm_map_msm8960_io(void);
 
 extern unsigned int msm_shared_ram_phys;
 
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 296c0f1..5c7c955 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
 #define MSM_IOMMU_H
 
 #include <linux/interrupt.h>
+#include <linux/clk.h>
 
 /* Sharability attributes of MSM IOMMU mappings */
 #define MSM_IOMMU_ATTR_NON_SH		0x0
@@ -44,14 +45,11 @@
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
  * name		Human-readable name given to this IOMMU HW instance
- * clk_rate	Rate to set for this IOMMU's clock, if applicable to this
- *		particular IOMMU. 0 means don't set a rate.
- *		-1 means it is an AXI clock with no valid rate
- *
+ * ncb		Number of context banks present on this IOMMU HW instance
  */
 struct msm_iommu_dev {
 	const char *name;
-	int clk_rate;
+	int ncb;
 };
 
 /**
@@ -73,14 +71,20 @@ struct msm_iommu_ctx_dev {
 /**
  * struct msm_iommu_drvdata - A single IOMMU hardware instance
  * @base:	IOMMU config port base address (VA)
+ * @ncb		The number of contexts on this IOMMU
  * @irq:	Interrupt number
-  *
+ * @clk:	The bus clock for this IOMMU hardware instance
+ * @pclk:	The clock for the IOMMU bus interconnect
+ *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
  */
 struct msm_iommu_drvdata {
 	void __iomem *base;
 	int irq;
+	int ncb;
+	struct clk *clk;
+	struct clk *pclk;
 };
 
 /**
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
index c2c3da9..fc16010 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -68,6 +68,7 @@ do { \
 #define FL_CACHEABLE		(1 << 3)
 #define FL_TEX0			(1 << 12)
 #define FL_OFFSET(va)		(((va) & 0xFFF00000) >> 20)
+#define FL_NG			(1 << 17)
 
 /* Second-level page table bits */
 #define SL_BASE_MASK_LARGE	0xFFFF0000
@@ -81,6 +82,7 @@ do { \
 #define SL_CACHEABLE		(1 << 3)
 #define SL_TEX0			(1 << 6)
 #define SL_OFFSET(va)		(((va) & 0xFF000) >> 12)
+#define SL_NG			(1 << 11)
 
 /* Memory type and cache policy attributes */
 #define MT_SO			0
@@ -623,20 +625,6 @@ do { \
 #define SET_INDEX(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v)
 
 
-/* V2Pxx UW UR PW PR */
-#define SET_V2PUW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX, v)
-#define SET_V2PUW_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA, v)
-
-#define SET_V2PUR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX, v)
-#define SET_V2PUR_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA, v)
-
-#define SET_V2PPW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX, v)
-#define SET_V2PPW_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA, v)
-
-#define SET_V2PPR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX, v)
-#define SET_V2PPR_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA, v)
-
-
 /* Context Register getters */
 /* ACTLR */
 #define GET_CFERE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFERE)
@@ -824,20 +812,6 @@ do { \
 #define GET_INDEX(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, INDEX)
 
 
-/* V2Pxx UW UR PW PR */
-#define GET_V2PUW_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX)
-#define GET_V2PUW_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA)
-
-#define GET_V2PUR_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX)
-#define GET_V2PUR_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA)
-
-#define GET_V2PPW_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX)
-#define GET_V2PPW_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA)
-
-#define GET_V2PPR_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX)
-#define GET_V2PPR_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA)
-
-
 /* Global Registers */
 #define M2VCBR_N	(0xFF000)
 #define CBACR_N		(0xFF800)
diff --git a/arch/arm/mach-msm/include/mach/irqs-7x30.h b/arch/arm/mach-msm/include/mach/irqs-7x30.h
index 67c5396..1f15902 100644
--- a/arch/arm/mach-msm/include/mach/irqs-7x30.h
+++ b/arch/arm/mach-msm/include/mach/irqs-7x30.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __ASM_ARCH_MSM_IRQS_7X30_H
diff --git a/arch/arm/mach-msm/include/mach/irqs-8960.h b/arch/arm/mach-msm/include/mach/irqs-8960.h
new file mode 100644
index 0000000..81ab2a6
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/irqs-8960.h
@@ -0,0 +1,277 @@
+/* Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8960_H
+#define __ASM_ARCH_MSM_IRQS_8960_H
+
+/* MSM ACPU Interrupt Numbers */
+
+/* 0-15:  STI/SGI (software triggered/generated interrupts)
+   16-31: PPI (private peripheral interrupts)
+   32+:   SPI (shared peripheral interrupts) */
+
+#define GIC_PPI_START 16
+#define GIC_SPI_START 32
+
+#define INT_VGIC				(GIC_PPI_START + 0)
+#define INT_DEBUG_TIMER_EXP			(GIC_PPI_START + 1)
+#define INT_GP_TIMER_EXP			(GIC_PPI_START + 2)
+#define INT_GP_TIMER2_EXP			(GIC_PPI_START + 3)
+#define WDT0_ACCSCSSNBARK_INT			(GIC_PPI_START + 4)
+#define WDT1_ACCSCSSNBARK_INT			(GIC_PPI_START + 5)
+#define AVS_SVICINT				(GIC_PPI_START + 6)
+#define AVS_SVICINTSWDONE			(GIC_PPI_START + 7)
+#define CPU_DBGCPUXCOMMRXFULL			(GIC_PPI_START + 8)
+#define CPU_DBGCPUXCOMMTXEMPTY			(GIC_PPI_START + 9)
+#define CPU_SICCPUXPERFMONIRPTREQ		(GIC_PPI_START + 10)
+#define SC_AVSCPUXDOWN				(GIC_PPI_START + 11)
+#define SC_AVSCPUXUP				(GIC_PPI_START + 12)
+#define SC_SICCPUXACGIRPTREQ			(GIC_PPI_START + 13)
+#define SC_SICCPUXEXTFAULTIRPTREQ		(GIC_PPI_START + 14)
+/* PPI 15 is unused */
+
+#define SC_SICMPUIRPTREQ			(GIC_SPI_START + 0)
+#define SC_SICL2IRPTREQ				(GIC_SPI_START + 1)
+#define SC_SICL2PERFMONIRPTREQ			(GIC_SPI_START + 2)
+#define SC_SICAGCIRPTREQ			(GIC_SPI_START + 3)
+#define TLMM_APCC_DIR_CONN_IRQ_0		(GIC_SPI_START + 4)
+#define TLMM_APCC_DIR_CONN_IRQ_1		(GIC_SPI_START + 5)
+#define TLMM_APCC_DIR_CONN_IRQ_2		(GIC_SPI_START + 6)
+#define TLMM_APCC_DIR_CONN_IRQ_3		(GIC_SPI_START + 7)
+#define TLMM_APCC_DIR_CONN_IRQ_4		(GIC_SPI_START + 8)
+#define TLMM_APCC_DIR_CONN_IRQ_5		(GIC_SPI_START + 9)
+#define TLMM_APCC_DIR_CONN_IRQ_6		(GIC_SPI_START + 10)
+#define TLMM_APCC_DIR_CONN_IRQ_7		(GIC_SPI_START + 11)
+#define TLMM_APCC_DIR_CONN_IRQ_8		(GIC_SPI_START + 12)
+#define TLMM_APCC_DIR_CONN_IRQ_9		(GIC_SPI_START + 13)
+#define PM8921_SEC_IRQ_103			(GIC_SPI_START + 14)
+#define PM8018_SEC_IRQ_106			(GIC_SPI_START + 15)
+#define TLMM_APCC_SUMMARY_IRQ			(GIC_SPI_START + 16)
+#define SPDM_RT_1_IRQ				(GIC_SPI_START + 17)
+#define SPDM_DIAG_IRQ				(GIC_SPI_START + 18)
+#define RPM_APCC_CPU0_GP_HIGH_IRQ		(GIC_SPI_START + 19)
+#define RPM_APCC_CPU0_GP_MEDIUM_IRQ		(GIC_SPI_START + 20)
+#define RPM_APCC_CPU0_GP_LOW_IRQ		(GIC_SPI_START + 21)
+#define RPM_APCC_CPU0_WAKE_UP_IRQ		(GIC_SPI_START + 22)
+#define RPM_APCC_CPU1_GP_HIGH_IRQ		(GIC_SPI_START + 23)
+#define RPM_APCC_CPU1_GP_MEDIUM_IRQ		(GIC_SPI_START + 24)
+#define RPM_APCC_CPU1_GP_LOW_IRQ		(GIC_SPI_START + 25)
+#define RPM_APCC_CPU1_WAKE_UP_IRQ		(GIC_SPI_START + 26)
+#define SSBI2_2_SC_CPU0_SECURE_IRQ		(GIC_SPI_START + 27)
+#define SSBI2_2_SC_CPU0_NON_SECURE_IRQ		(GIC_SPI_START + 28)
+#define SSBI2_1_SC_CPU0_SECURE_IRQ		(GIC_SPI_START + 29)
+#define SSBI2_1_SC_CPU0_NON_SECURE_IRQ		(GIC_SPI_START + 30)
+#define MSMC_SC_SEC_CE_IRQ			(GIC_SPI_START + 31)
+#define MSMC_SC_PRI_CE_IRQ			(GIC_SPI_START + 32)
+#define SLIMBUS0_CORE_EE1_IRQ			(GIC_SPI_START + 33)
+#define SLIMBUS0_BAM_EE1_IRQ			(GIC_SPI_START + 34)
+#define Q6FW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 35)
+#define Q6SW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 36)
+#define MSS_TO_APPS_IRQ_0			(GIC_SPI_START + 37)
+#define MSS_TO_APPS_IRQ_1			(GIC_SPI_START + 38)
+#define MSS_TO_APPS_IRQ_2			(GIC_SPI_START + 39)
+#define MSS_TO_APPS_IRQ_3			(GIC_SPI_START + 40)
+#define MSS_TO_APPS_IRQ_4			(GIC_SPI_START + 41)
+#define MSS_TO_APPS_IRQ_5			(GIC_SPI_START + 42)
+#define MSS_TO_APPS_IRQ_6			(GIC_SPI_START + 43)
+#define MSS_TO_APPS_IRQ_7			(GIC_SPI_START + 44)
+#define MSS_TO_APPS_IRQ_8			(GIC_SPI_START + 45)
+#define MSS_TO_APPS_IRQ_9			(GIC_SPI_START + 46)
+#define VPE_IRQ					(GIC_SPI_START + 47)
+#define VFE_IRQ					(GIC_SPI_START + 48)
+#define VCODEC_IRQ				(GIC_SPI_START + 49)
+#define TV_ENC_IRQ				(GIC_SPI_START + 50)
+#define SMMU_VPE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 51)
+#define SMMU_VPE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 52)
+#define SMMU_VFE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 53)
+#define SMMU_VFE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 54)
+#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ		(GIC_SPI_START + 55)
+#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 56)
+#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ		(GIC_SPI_START + 57)
+#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 58)
+#define SMMU_ROT_CB_SC_SECURE_IRQ		(GIC_SPI_START + 59)
+#define SMMU_ROT_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 60)
+#define SMMU_MDP1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 61)
+#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 62)
+#define SMMU_MDP0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 63)
+#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 64)
+#define SMMU_JPEGD_CB_SC_SECURE_IRQ		(GIC_SPI_START + 65)
+#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 66)
+#define SMMU_IJPEG_CB_SC_SECURE_IRQ		(GIC_SPI_START + 67)
+#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 68)
+#define SMMU_GFX3D_CB_SC_SECURE_IRQ		(GIC_SPI_START + 69)
+#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 70)
+#define SMMU_GFX2D0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 71)
+#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 72)
+#define ROT_IRQ					(GIC_SPI_START + 73)
+#define MMSS_FABRIC_IRQ				(GIC_SPI_START + 74)
+#define MDP_IRQ					(GIC_SPI_START + 75)
+#define JPEGD_IRQ				(GIC_SPI_START + 76)
+#define JPEG_IRQ				(GIC_SPI_START + 77)
+#define MMSS_IMEM_IRQ				(GIC_SPI_START + 78)
+#define HDMI_IRQ				(GIC_SPI_START + 79)
+#define GFX3D_IRQ				(GIC_SPI_START + 80)
+#define GFX2D0_IRQ				(GIC_SPI_START + 81)
+#define DSI1_IRQ				(GIC_SPI_START + 82)
+#define CSI_1_IRQ				(GIC_SPI_START + 83)
+#define CSI_0_IRQ				(GIC_SPI_START + 84)
+#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ		(GIC_SPI_START + 85)
+#define LPASS_SCSS_MIDI_IRQ			(GIC_SPI_START + 86)
+#define LPASS_Q6SS_WDOG_EXPIRED			(GIC_SPI_START + 87)
+#define LPASS_SCSS_GP_LOW_IRQ			(GIC_SPI_START + 88)
+#define LPASS_SCSS_GP_MEDIUM_IRQ		(GIC_SPI_START + 89)
+#define LPASS_SCSS_GP_HIGH_IRQ			(GIC_SPI_START + 90)
+#define TOP_IMEM_IRQ				(GIC_SPI_START + 91)
+#define FABRIC_SYS_IRQ				(GIC_SPI_START + 92)
+#define FABRIC_APPS_IRQ				(GIC_SPI_START + 93)
+#define USB1_HS_BAM_IRQ				(GIC_SPI_START + 94)
+#define SDC4_BAM_IRQ				(GIC_SPI_START + 95)
+#define SDC3_BAM_IRQ				(GIC_SPI_START + 96)
+#define SDC2_BAM_IRQ				(GIC_SPI_START + 97)
+#define SDC1_BAM_IRQ				(GIC_SPI_START + 98)
+#define FABRIC_SPS_IRQ				(GIC_SPI_START + 99)
+#define USB1_HS_IRQ				(GIC_SPI_START + 100)
+#define SDC4_IRQ_0				(GIC_SPI_START + 101)
+#define SDC3_IRQ_0				(GIC_SPI_START + 102)
+#define SDC2_IRQ_0				(GIC_SPI_START + 103)
+#define SDC1_IRQ_0				(GIC_SPI_START + 104)
+#define SPS_BAM_DMA_IRQ				(GIC_SPI_START + 105)
+#define SPS_SEC_VIOL_IRQ			(GIC_SPI_START + 106)
+#define SPS_MTI_0				(GIC_SPI_START + 107)
+#define SPS_MTI_1				(GIC_SPI_START + 108)
+#define SPS_MTI_2				(GIC_SPI_START + 109)
+#define SPS_MTI_3				(GIC_SPI_START + 110)
+#define SPS_MTI_4				(GIC_SPI_START + 111)
+#define SPS_MTI_5				(GIC_SPI_START + 112)
+#define SPS_MTI_6				(GIC_SPI_START + 113)
+#define SPS_MTI_7				(GIC_SPI_START + 114)
+#define SPS_MTI_8				(GIC_SPI_START + 115)
+#define SPS_MTI_9				(GIC_SPI_START + 116)
+#define SPS_MTI_10				(GIC_SPI_START + 117)
+#define SPS_MTI_11				(GIC_SPI_START + 118)
+#define SPS_MTI_12				(GIC_SPI_START + 119)
+#define SPS_MTI_13				(GIC_SPI_START + 120)
+#define SPS_MTI_14				(GIC_SPI_START + 121)
+#define SPS_MTI_15				(GIC_SPI_START + 122)
+#define SPS_MTI_16				(GIC_SPI_START + 123)
+#define SPS_MTI_17				(GIC_SPI_START + 124)
+#define SPS_MTI_18				(GIC_SPI_START + 125)
+#define SPS_MTI_19				(GIC_SPI_START + 126)
+#define SPS_MTI_20				(GIC_SPI_START + 127)
+#define SPS_MTI_21				(GIC_SPI_START + 128)
+#define SPS_MTI_22				(GIC_SPI_START + 129)
+#define SPS_MTI_23				(GIC_SPI_START + 130)
+#define SPS_MTI_24				(GIC_SPI_START + 131)
+#define SPS_MTI_25				(GIC_SPI_START + 132)
+#define SPS_MTI_26				(GIC_SPI_START + 133)
+#define SPS_MTI_27				(GIC_SPI_START + 134)
+#define SPS_MTI_28				(GIC_SPI_START + 135)
+#define SPS_MTI_29				(GIC_SPI_START + 136)
+#define SPS_MTI_30				(GIC_SPI_START + 137)
+#define SPS_MTI_31				(GIC_SPI_START + 138)
+#define CSIPHY_4LN_IRQ				(GIC_SPI_START + 139)
+#define CSIPHY_2LN_IRQ				(GIC_SPI_START + 140)
+#define USB2_IRQ				(GIC_SPI_START + 141)
+#define USB1_IRQ				(GIC_SPI_START + 142)
+#define TSSC_SSBI_IRQ				(GIC_SPI_START + 143)
+#define TSSC_SAMPLE_IRQ				(GIC_SPI_START + 144)
+#define TSSC_PENUP_IRQ				(GIC_SPI_START + 145)
+#define GSBI1_UARTDM_IRQ			(GIC_SPI_START + 146)
+#define GSBI1_QUP_IRQ				(GIC_SPI_START + 147)
+#define GSBI2_UARTDM_IRQ			(GIC_SPI_START + 148)
+#define GSBI2_QUP_IRQ			        (GIC_SPI_START + 149)
+#define GSBI3_UARTDM_IRQ			(GIC_SPI_START + 150)
+#define GSBI3_QUP_IRQ				(GIC_SPI_START + 151)
+#define GSBI4_UARTDM_IRQ			(GIC_SPI_START + 152)
+#define GSBI4_QUP_IRQ				(GIC_SPI_START + 153)
+#define GSBI5_UARTDM_IRQ			(GIC_SPI_START + 154)
+#define GSBI5_QUP_IRQ				(GIC_SPI_START + 155)
+#define GSBI6_UARTDM_IRQ			(GIC_SPI_START + 156)
+#define GSBI6_QUP_IRQ				(GIC_SPI_START + 157)
+#define GSBI7_UARTDM_IRQ			(GIC_SPI_START + 158)
+#define GSBI7_QUP_IRQ				(GIC_SPI_START + 159)
+#define GSBI8_UARTDM_IRQ			(GIC_SPI_START + 160)
+#define GSBI8_QUP_IRQ				(GIC_SPI_START + 161)
+#define TSIF_TSPP_IRQ				(GIC_SPI_START + 162)
+#define TSIF_BAM_IRQ				(GIC_SPI_START + 163)
+#define TSIF2_IRQ				(GIC_SPI_START + 164)
+#define TSIF1_IRQ				(GIC_SPI_START + 165)
+#define DSI2_IRQ				(GIC_SPI_START + 166)
+#define ISPIF_IRQ				(GIC_SPI_START + 167)
+#define MSMC_SC_SEC_TMR_IRQ			(GIC_SPI_START + 168)
+#define MSMC_SC_SEC_WDOG_BARK_IRQ		(GIC_SPI_START + 169)
+#define INT_ADM0_SCSS_0_IRQ			(GIC_SPI_START + 170)
+#define INT_ADM0_SCSS_1_IRQ			(GIC_SPI_START + 171)
+#define INT_ADM0_SCSS_2_IRQ			(GIC_SPI_START + 172)
+#define INT_ADM0_SCSS_3_IRQ			(GIC_SPI_START + 173)
+#define CC_SCSS_WDT1CPU1BITEEXPIRED		(GIC_SPI_START + 174)
+#define CC_SCSS_WDT1CPU0BITEEXPIRED		(GIC_SPI_START + 175)
+#define CC_SCSS_WDT0CPU1BITEEXPIRED		(GIC_SPI_START + 176)
+#define CC_SCSS_WDT0CPU0BITEEXPIRED		(GIC_SPI_START + 177)
+#define TSENS_UPPER_LOWER_INT			(GIC_SPI_START + 178)
+#define SSBI2_2_SC_CPU1_SECURE_INT		(GIC_SPI_START + 179)
+#define SSBI2_2_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 180)
+#define SSBI2_1_SC_CPU1_SECURE_INT		(GIC_SPI_START + 181)
+#define SSBI2_1_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 182)
+#define XPU_SUMMARY_IRQ				(GIC_SPI_START + 183)
+#define BUS_EXCEPTION_SUMMARY_IRQ		(GIC_SPI_START + 184)
+#define HSDDRX_EBI1CH0_IRQ			(GIC_SPI_START + 185)
+#define HSDDRX_EBI1CH1_IRQ			(GIC_SPI_START + 186)
+#define SDC5_BAM_IRQ				(GIC_SPI_START + 187)
+#define SDC5_IRQ_0				(GIC_SPI_START + 188)
+#define GSBI9_UARTDM_IRQ			(GIC_SPI_START + 189)
+#define GSBI9_QUP_IRQ				(GIC_SPI_START + 190)
+#define GSBI10_UARTDM_IRQ			(GIC_SPI_START + 191)
+#define GSBI10_QUP_IRQ				(GIC_SPI_START + 192)
+#define GSBI11_UARTDM_IRQ			(GIC_SPI_START + 193)
+#define GSBI11_QUP_IRQ				(GIC_SPI_START + 194)
+#define GSBI12_UARTDM_IRQ			(GIC_SPI_START + 195)
+#define GSBI12_QUP_IRQ				(GIC_SPI_START + 196)
+#define RIVA_APSS_LTECOEX_IRQ			(GIC_SPI_START + 197)
+#define RIVA_APSS_SPARE_IRQ			(GIC_SPI_START + 198)
+#define RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ	(GIC_SPI_START + 199)
+#define RIVA_ASS_RESET_DONE_IRQ			(GIC_SPI_START + 200)
+#define RIVA_APSS_ASIC_IRQ			(GIC_SPI_START + 201)
+#define RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ	(GIC_SPI_START + 202)
+#define RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ	(GIC_SPI_START + 203)
+#define RIVA_APPS_WLAM_SMSM_IRQ			(GIC_SPI_START + 204)
+#define RIVA_APPS_LOG_CTRL_IRQ			(GIC_SPI_START + 205)
+#define RIVA_APPS_FM_CTRL_IRQ			(GIC_SPI_START + 206)
+#define RIVA_APPS_HCI_IRQ			(GIC_SPI_START + 207)
+#define RIVA_APPS_WLAN_CTRL_IRQ			(GIC_SPI_START + 208)
+#define A2_BAM_IRQ				(GIC_SPI_START + 209)
+#define SMMU_GFX2D1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 210)
+#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 211)
+#define GFX2D1_IRQ				(GIC_SPI_START + 212)
+#define PPSS_WDOG_TIMER_IRQ			(GIC_SPI_START + 213)
+#define SPS_SLIMBUS_CORE_EE0_IRQ		(GIC_SPI_START + 214)
+#define SPS_SLIMBUS_BAM_EE0_IRQ			(GIC_SPI_START + 215)
+#define QDSS_ETB_IRQ				(GIC_SPI_START + 216)
+#define QDSS_CTI2KPSS_CPU1_IRQ			(GIC_SPI_START + 217)
+#define QDSS_CTI2KPSS_CPU0_IRQ			(GIC_SPI_START + 218)
+#define TLMM_APCC_DIR_CONN_IRQ_16		(GIC_SPI_START + 219)
+#define TLMM_APCC_DIR_CONN_IRQ_17		(GIC_SPI_START + 220)
+#define TLMM_APCC_DIR_CONN_IRQ_18		(GIC_SPI_START + 221)
+#define TLMM_APCC_DIR_CONN_IRQ_19		(GIC_SPI_START + 222)
+#define TLMM_APCC_DIR_CONN_IRQ_20		(GIC_SPI_START + 223)
+#define TLMM_APCC_DIR_CONN_IRQ_21		(GIC_SPI_START + 224)
+#define PM8921_SEC_IRQ_104			(GIC_SPI_START + 225)
+#define PM8018_SEC_IRQ_107			(GIC_SPI_START + 226)
+
+/* For now, use the maximum number of interrupts until a pending GIC issue
+ * is sorted out */
+#define NR_MSM_IRQS 1020
+#define NR_BOARD_IRQS 0
+#define NR_GPIO_IRQS 0
+
+#endif
+
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x50.h b/arch/arm/mach-msm/include/mach/irqs-8x50.h
index de3d8fe..26adbe0 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8x50.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8x50.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __ASM_ARCH_MSM_IRQS_8XXX_H
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 8679a45..3cd78b1 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -26,6 +26,9 @@
 #include "sirc.h"
 #elif defined(CONFIG_ARCH_MSM8X60)
 #include "irqs-8x60.h"
+#elif defined(CONFIG_ARCH_MSM8960)
+/* TODO: Make these not generic. */
+#include "irqs-8960.h"
 #elif defined(CONFIG_ARCH_MSM_ARM11)
 #include "irqs-7x00.h"
 #else
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 070e17d..f2f8d29 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -18,15 +18,17 @@
 
 /* physical offset of RAM */
 #if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A)
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 #elif defined(CONFIG_ARCH_QSD8X50)
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #elif defined(CONFIG_ARCH_MSM7X30)
-#define PHYS_OFFSET		UL(0x00200000)
+#define PLAT_PHYS_OFFSET		UL(0x00200000)
 #elif defined(CONFIG_ARCH_MSM8X60)
-#define PHYS_OFFSET		UL(0x40200000)
+#define PLAT_PHYS_OFFSET		UL(0x40200000)
+#elif defined(CONFIG_ARCH_MSM8960)
+#define PLAT_PHYS_OFFSET		UL(0x40200000)
 #else
-#define PHYS_OFFSET		UL(0x10000000)
+#define PLAT_PHYS_OFFSET		UL(0x10000000)
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/mmc.h b/arch/arm/mach-msm/include/mach/mmc.h
index d54b6b0..5631b51 100644
--- a/arch/arm/mach-msm/include/mach/mmc.h
+++ b/arch/arm/mach-msm/include/mach/mmc.h
@@ -15,12 +15,23 @@ struct embedded_sdio_data {
 	int num_funcs;
 };
 
+struct msm_mmc_gpio {
+	unsigned no;
+	const char *name;
+};
+
+struct msm_mmc_gpio_data {
+	struct msm_mmc_gpio *gpio;
+	u8 size;
+};
+
 struct msm_mmc_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
 	u32 (*translate_vdd)(struct device *, unsigned int);
 	unsigned int (*status)(struct device *);
 	struct embedded_sdio_data *embedded_sdio;
 	int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
+	struct msm_mmc_gpio_data *gpio_data;
 };
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
index cfff0e7..8f99d97 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
@@ -1,6 +1,7 @@
 /* arch/arm/mach-msm/include/mach/msm_iomap.h
  *
  * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -47,13 +48,8 @@
 #define MSM_VIC_PHYS          0xC0000000
 #define MSM_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xE0001000)
-#define MSM_CSR_PHYS          0xC0100000
-#define MSM_CSR_SIZE          SZ_4K
-
-#define MSM_GPT_PHYS          MSM_CSR_PHYS
-#define MSM_GPT_BASE          MSM_CSR_BASE
-#define MSM_GPT_SIZE          SZ_4K
+#define MSM7X00_CSR_PHYS      0xC0100000
+#define MSM7X00_CSR_SIZE      SZ_4K
 
 #define MSM_DMOV_BASE         IOMEM(0xE0002000)
 #define MSM_DMOV_PHYS         0xA9700000
@@ -130,10 +126,4 @@
 #define MSM_AD5_SIZE          (SZ_1M*13)
 
 
-#if defined(CONFIG_ARCH_MSM7X30)
-#define MSM_GCC_BASE          IOMEM(0xF8009000)
-#define MSM_GCC_PHYS          0xC0182000
-#define MSM_GCC_SIZE          SZ_4K
-#endif
-
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
index 0fd7b68..4d84be1 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -39,16 +39,8 @@
 #define MSM_VIC_PHYS          0xC0080000
 #define MSM_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xE0001000)
-#define MSM_CSR_PHYS          0xC0100000
-#define MSM_CSR_SIZE          SZ_4K
-
-#define MSM_TMR_PHYS          MSM_CSR_PHYS
-#define MSM_TMR_BASE          MSM_CSR_BASE
-#define MSM_TMR_SIZE          SZ_4K
-
-#define MSM_GPT_BASE 	      (MSM_TMR_BASE + 0x4)
-#define MSM_DGT_BASE 	      (MSM_TMR_BASE + 0x24)
+#define MSM7X30_CSR_PHYS      0xC0100000
+#define MSM7X30_CSR_SIZE      SZ_4K
 
 #define MSM_DMOV_BASE         IOMEM(0xE0002000)
 #define MSM_DMOV_PHYS         0xAC400000
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8960.h b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
new file mode 100644
index 0000000..3c9d960
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Author: Brian Swetland <swetland@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.
+ *
+ *
+ * The MSM peripherals are spread all over across 768MB of physical
+ * space, which makes just having a simple IO_ADDRESS macro to slide
+ * them into the right virtual location rough.  Instead, we will
+ * provide a master phys->virt mapping for peripherals here.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_8960_H
+#define __ASM_ARCH_MSM_IOMAP_8960_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+
+#define MSM8960_QGIC_DIST_PHYS	0x02000000
+#define MSM8960_QGIC_DIST_SIZE	SZ_4K
+
+#define MSM8960_QGIC_CPU_PHYS	0x02002000
+#define MSM8960_QGIC_CPU_SIZE	SZ_4K
+
+#define MSM8960_TMR_PHYS	0x0200A000
+#define MSM8960_TMR_SIZE	SZ_4K
+
+#define MSM8960_TMR0_PHYS	0x0208A000
+#define MSM8960_TMR0_SIZE	SZ_4K
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
index acc819e..d414320 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -39,16 +39,8 @@
 #define MSM_VIC_PHYS          0xAC000000
 #define MSM_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xE0001000)
-#define MSM_CSR_PHYS          0xAC100000
-#define MSM_CSR_SIZE          SZ_4K
-
-#define MSM_TMR_PHYS          MSM_CSR_PHYS
-#define MSM_TMR_BASE          MSM_CSR_BASE
-#define MSM_TMR_SIZE          SZ_4K
-
-#define MSM_GPT_BASE          MSM_TMR_BASE
-#define MSM_DGT_BASE          (MSM_TMR_BASE + 0x10)
+#define QSD8X50_CSR_PHYS      0xAC100000
+#define QSD8X50_CSR_SIZE      SZ_4K
 
 #define MSM_DMOV_BASE         IOMEM(0xE0002000)
 #define MSM_DMOV_PHYS         0xA9700000
@@ -132,16 +124,16 @@
 #define MSM_UART2DM_PHYS      0xA0900000
 
 
-#define MSM_SDC1_PHYS          0xA0400000
+#define MSM_SDC1_PHYS          0xA0300000
 #define MSM_SDC1_SIZE          SZ_4K
 
-#define MSM_SDC2_PHYS          0xA0500000
+#define MSM_SDC2_PHYS          0xA0400000
 #define MSM_SDC2_SIZE          SZ_4K
 
-#define MSM_SDC3_PHYS          0xA0600000
+#define MSM_SDC3_PHYS          0xA0500000
 #define MSM_SDC3_SIZE           SZ_4K
 
-#define MSM_SDC4_PHYS          0xA0700000
+#define MSM_SDC4_PHYS          0xA0600000
 #define MSM_SDC4_SIZE          SZ_4K
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index a54e33b..3b19b8f 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -35,13 +35,11 @@
  *
  */
 
-#define MSM_QGIC_DIST_BASE	IOMEM(0xF0000000)
-#define MSM_QGIC_DIST_PHYS	0x02080000
-#define MSM_QGIC_DIST_SIZE	SZ_4K
+#define MSM8X60_QGIC_DIST_PHYS	0x02080000
+#define MSM8X60_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM_QGIC_CPU_BASE	IOMEM(0xF0001000)
-#define MSM_QGIC_CPU_PHYS	0x02081000
-#define MSM_QGIC_CPU_SIZE	SZ_4K
+#define MSM8X60_QGIC_CPU_PHYS	0x02081000
+#define MSM8X60_QGIC_CPU_SIZE	SZ_4K
 
 #define MSM_ACC_BASE		IOMEM(0xF0002000)
 #define MSM_ACC_PHYS		0x02001000
@@ -58,51 +56,10 @@
 #define MSM_SHARED_RAM_BASE	IOMEM(0xF0100000)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 
-#define MSM_TMR_BASE		IOMEM(0xF0200000)
-#define MSM_TMR_PHYS		0x02000000
-#define MSM_TMR_SIZE		SZ_4K
+#define MSM8X60_TMR_PHYS	0x02000000
+#define MSM8X60_TMR_SIZE	SZ_4K
 
-#define MSM_TMR0_BASE		IOMEM(0xF0201000)
-#define MSM_TMR0_PHYS		0x02040000
-#define MSM_TMR0_SIZE		SZ_4K
-
-#define MSM_GPT_BASE		(MSM_TMR_BASE + 0x4)
-#define MSM_DGT_BASE		(MSM_TMR_BASE + 0x24)
-
-#define MSM_IOMMU_JPEGD_PHYS	0x07300000
-#define MSM_IOMMU_JPEGD_SIZE	SZ_1M
-
-#define MSM_IOMMU_VPE_PHYS	0x07400000
-#define MSM_IOMMU_VPE_SIZE	SZ_1M
-
-#define MSM_IOMMU_MDP0_PHYS	0x07500000
-#define MSM_IOMMU_MDP0_SIZE	SZ_1M
-
-#define MSM_IOMMU_MDP1_PHYS	0x07600000
-#define MSM_IOMMU_MDP1_SIZE	SZ_1M
-
-#define MSM_IOMMU_ROT_PHYS	0x07700000
-#define MSM_IOMMU_ROT_SIZE	SZ_1M
-
-#define MSM_IOMMU_IJPEG_PHYS	0x07800000
-#define MSM_IOMMU_IJPEG_SIZE	SZ_1M
-
-#define MSM_IOMMU_VFE_PHYS	0x07900000
-#define MSM_IOMMU_VFE_SIZE	SZ_1M
-
-#define MSM_IOMMU_VCODEC_A_PHYS	0x07A00000
-#define MSM_IOMMU_VCODEC_A_SIZE	SZ_1M
-
-#define MSM_IOMMU_VCODEC_B_PHYS	0x07B00000
-#define MSM_IOMMU_VCODEC_B_SIZE	SZ_1M
-
-#define MSM_IOMMU_GFX3D_PHYS	0x07C00000
-#define MSM_IOMMU_GFX3D_SIZE	SZ_1M
-
-#define MSM_IOMMU_GFX2D0_PHYS	0x07D00000
-#define MSM_IOMMU_GFX2D0_SIZE	SZ_1M
-
-#define MSM_IOMMU_GFX2D1_PHYS	0x07E00000
-#define MSM_IOMMU_GFX2D1_SIZE	SZ_1M
+#define MSM8X60_TMR0_PHYS	0x02040000
+#define MSM8X60_TMR0_SIZE	SZ_4K
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 8e24dd8..c98c759 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -53,6 +53,13 @@
 #include "msm_iomap-7x00.h"
 #endif
 
+#include "msm_iomap-8960.h"
 
+/* Virtual addressses shared across all MSM targets. */
+#define MSM_CSR_BASE		IOMEM(0xE0001000)
+#define MSM_QGIC_DIST_BASE	IOMEM(0xF0000000)
+#define MSM_QGIC_CPU_BASE	IOMEM(0xF0001000)
+#define MSM_TMR_BASE		IOMEM(0xF0200000)
+#define MSM_TMR0_BASE		IOMEM(0xF0201000)
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/sirc.h b/arch/arm/mach-msm/include/mach/sirc.h
index 7281337..ef55868 100644
--- a/arch/arm/mach-msm/include/mach/sirc.h
+++ b/arch/arm/mach-msm/include/mach/sirc.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __ASM_ARCH_MSM_SIRC_H
diff --git a/arch/arm/mach-msm/include/mach/smp.h b/arch/arm/mach-msm/include/mach/smp.h
index a95f7b9..3c01000 100644
--- a/arch/arm/mach-msm/include/mach/smp.h
+++ b/arch/arm/mach-msm/include/mach/smp.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2010, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef __ASM_ARCH_MSM_SMP_H
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 1260007..cec6ed1 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -3,7 +3,7 @@
  * MSM7K, QSD io support
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -28,19 +28,20 @@
 
 #include <mach/board.h>
 
-#define MSM_DEVICE(name) { \
+#define MSM_CHIP_DEVICE(name, chip) {			      \
 		.virtual = (unsigned long) MSM_##name##_BASE, \
-		.pfn = __phys_to_pfn(MSM_##name##_PHYS), \
-		.length = MSM_##name##_SIZE, \
+		.pfn = __phys_to_pfn(chip##_##name##_PHYS), \
+		.length = chip##_##name##_SIZE, \
 		.type = MT_DEVICE_NONSHARED, \
 	 }
 
+#define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM)
+
 #if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X27) \
 	|| defined(CONFIG_ARCH_MSM7X25)
 static struct map_desc msm_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(GPT),
+	MSM_CHIP_DEVICE(CSR, MSM7X00),
 	MSM_DEVICE(DMOV),
 	MSM_DEVICE(GPIO1),
 	MSM_DEVICE(GPIO2),
@@ -73,8 +74,7 @@ void __init msm_map_common_io(void)
 #ifdef CONFIG_ARCH_QSD8X50
 static struct map_desc qsd8x50_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(TMR),
+	MSM_CHIP_DEVICE(CSR, QSD8X50),
 	MSM_DEVICE(DMOV),
 	MSM_DEVICE(GPIO1),
 	MSM_DEVICE(GPIO2),
@@ -102,10 +102,10 @@ void __init msm_map_qsd8x50_io(void)
 
 #ifdef CONFIG_ARCH_MSM8X60
 static struct map_desc msm8x60_io_desc[] __initdata = {
-	MSM_DEVICE(QGIC_DIST),
-	MSM_DEVICE(QGIC_CPU),
-	MSM_DEVICE(TMR),
-	MSM_DEVICE(TMR0),
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8X60),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8X60),
+	MSM_CHIP_DEVICE(TMR, MSM8X60),
+	MSM_CHIP_DEVICE(TMR0, MSM8X60),
 	MSM_DEVICE(ACC),
 	MSM_DEVICE(GCC),
 };
@@ -116,11 +116,24 @@ void __init msm_map_msm8x60_io(void)
 }
 #endif /* CONFIG_ARCH_MSM8X60 */
 
+#ifdef CONFIG_ARCH_MSM8960
+static struct map_desc msm8960_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8960),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8960),
+	MSM_CHIP_DEVICE(TMR, MSM8960),
+	MSM_CHIP_DEVICE(TMR0, MSM8960),
+};
+
+void __init msm_map_msm8960_io(void)
+{
+	iotable_init(msm8960_io_desc, ARRAY_SIZE(msm8960_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8960 */
+
 #ifdef CONFIG_ARCH_MSM7X30
 static struct map_desc msm7x30_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(TMR),
+	MSM_CHIP_DEVICE(CSR, MSM7X30),
 	MSM_DEVICE(DMOV),
 	MSM_DEVICE(GPIO1),
 	MSM_DEVICE(GPIO2),
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index e2d58e4..1a584e0 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/iommu.h>
+#include <linux/clk.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -50,6 +51,30 @@ struct msm_priv {
 	struct list_head list_attached;
 };
 
+static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+	int ret;
+
+	ret = clk_enable(drvdata->pclk);
+	if (ret)
+		goto fail;
+
+	if (drvdata->clk) {
+		ret = clk_enable(drvdata->clk);
+		if (ret)
+			clk_disable(drvdata->pclk);
+	}
+fail:
+	return ret;
+}
+
+static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+	if (drvdata->clk)
+		clk_disable(drvdata->clk);
+	clk_disable(drvdata->pclk);
+}
+
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = domain->priv;
@@ -77,9 +102,16 @@ static int __flush_iotlb(struct iommu_domain *domain)
 			BUG();
 
 		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+		BUG_ON(!iommu_drvdata);
+
+		ret = __enable_clocks(iommu_drvdata);
+		if (ret)
+			goto fail;
+
 		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+		__disable_clocks(iommu_drvdata);
 	}
-
+fail:
 	return ret;
 }
 
@@ -105,7 +137,6 @@ static void __reset_context(void __iomem *base, int ctx)
 	SET_TLBLKCR(base, ctx, 0);
 	SET_PRRR(base, ctx, 0);
 	SET_NMRR(base, ctx, 0);
-	SET_CONTEXTIDR(base, ctx, 0);
 }
 
 static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
@@ -265,9 +296,14 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 			goto fail;
 		}
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
 	__program_context(iommu_drvdata->base, ctx_dev->num,
 			  __pa(priv->pgtable));
 
+	__disable_clocks(iommu_drvdata);
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ret = __flush_iotlb(domain);
 
@@ -303,7 +339,12 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
 	if (ret)
 		goto fail;
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
 	__reset_context(iommu_drvdata->base, ctx_dev->num);
+	__disable_clocks(iommu_drvdata);
 	list_del_init(&ctx_drvdata->attached_elm);
 
 fail:
@@ -376,11 +417,11 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
 		for (i = 0; i < 16; i++)
 			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
 				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED | pgprot;
+				  FL_SHARED | FL_NG | pgprot;
 	}
 
 	if (len == SZ_1M)
-		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
+		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
 					    FL_TYPE_SECT | FL_SHARED | pgprot;
 
 	/* Need a 2nd level table */
@@ -405,7 +446,7 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
 
 
 	if (len == SZ_4K)
-		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
+		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
 					  SL_SHARED | SL_TYPE_SMALL | pgprot;
 
 	if (len == SZ_64K) {
@@ -413,7 +454,7 @@ static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
 
 		for (i = 0; i < 16; i++)
 			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-				SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
+			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
 	}
 
 	ret = __flush_iotlb(domain);
@@ -532,9 +573,13 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	base = iommu_drvdata->base;
 	ctx = ctx_drvdata->num;
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
 	/* Invalidate context TLB */
 	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
+	SET_V2PPR(base, ctx, va & V2Pxx_VA);
 
 	par = GET_PAR(base, ctx);
 
@@ -547,6 +592,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	if (GET_FAULT(base, ctx))
 		ret = 0;
 
+	__disable_clocks(iommu_drvdata);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -590,7 +636,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 	struct msm_iommu_drvdata *drvdata = dev_id;
 	void __iomem *base;
 	unsigned int fsr;
-	int ncb, i;
+	int i, ret;
 
 	spin_lock(&msm_iommu_lock);
 
@@ -604,8 +650,11 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 	pr_err("Unexpected IOMMU page fault!\n");
 	pr_err("base = %08x\n", (unsigned int) base);
 
-	ncb = GET_NCB(base)+1;
-	for (i = 0; i < ncb; i++) {
+	ret = __enable_clocks(drvdata);
+	if (ret)
+		goto fail;
+
+	for (i = 0; i < drvdata->ncb; i++) {
 		fsr = GET_FSR(base, i);
 		if (fsr) {
 			pr_err("Fault occurred in context %d.\n", i);
@@ -614,6 +663,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
 			SET_FSR(base, i, 0x4000000F);
 		}
 	}
+	__disable_clocks(drvdata);
 fail:
 	spin_unlock(&msm_iommu_lock);
 	return 0;
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index b83c73b..8e8fb07 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,6 +29,7 @@
 
 #include <mach/iommu_hw-8xxx.h>
 #include <mach/iommu.h>
+#include <mach/clk.h>
 
 struct iommu_ctx_iter_data {
 	/* input */
@@ -84,9 +85,9 @@ fail:
 }
 EXPORT_SYMBOL(msm_iommu_get_ctx);
 
-static void msm_iommu_reset(void __iomem *base)
+static void msm_iommu_reset(void __iomem *base, int ncb)
 {
-	int ctx, ncb;
+	int ctx;
 
 	SET_RPUE(base, 0);
 	SET_RPUEIE(base, 0);
@@ -99,7 +100,6 @@ static void msm_iommu_reset(void __iomem *base)
 	SET_GLOBAL_TLBIALL(base, 0);
 	SET_RPU_ACR(base, 0);
 	SET_TLBLKCRWE(base, 1);
-	ncb = GET_NCB(base)+1;
 
 	for (ctx = 0; ctx < ncb; ctx++) {
 		SET_BPRCOSH(base, ctx, 0);
@@ -130,117 +130,140 @@ static int msm_iommu_probe(struct platform_device *pdev)
 {
 	struct resource *r, *r2;
 	struct clk *iommu_clk;
+	struct clk *iommu_pclk;
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
 	void __iomem *regs_base;
 	resource_size_t	len;
-	int ret = 0, ncb, nm2v, irq;
+	int ret, irq, par;
 
-	if (pdev->id != -1) {
-		drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	if (pdev->id == -1) {
+		msm_iommu_root_dev = pdev;
+		return 0;
+	}
 
-		if (!drvdata) {
-			ret = -ENOMEM;
-			goto fail;
-		}
+	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
 
-		if (!iommu_dev) {
-			ret = -ENODEV;
-			goto fail;
-		}
+	if (!drvdata) {
+		ret = -ENOMEM;
+		goto fail;
+	}
 
-		if (iommu_dev->clk_rate != 0) {
-			iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
-			if (IS_ERR(iommu_clk)) {
-				ret = -ENODEV;
-				goto fail;
-			}
-
-			if (iommu_dev->clk_rate > 0) {
-				ret = clk_set_rate(iommu_clk,
-							iommu_dev->clk_rate);
-				if (ret) {
-					clk_put(iommu_clk);
-					goto fail;
-				}
-			}
-
-			ret = clk_enable(iommu_clk);
-			if (ret) {
-				clk_put(iommu_clk);
-				goto fail;
-			}
+	if (!iommu_dev) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	iommu_pclk = clk_get(NULL, "smmu_pclk");
+	if (IS_ERR(iommu_pclk)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	ret = clk_enable(iommu_pclk);
+	if (ret)
+		goto fail_enable;
+
+	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+	if (!IS_ERR(iommu_clk))	{
+		if (clk_get_rate(iommu_clk) == 0)
+			clk_set_min_rate(iommu_clk, 1);
+
+		ret = clk_enable(iommu_clk);
+		if (ret) {
 			clk_put(iommu_clk);
+			goto fail_pclk;
 		}
+	} else
+		iommu_clk = NULL;
 
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						 "physbase");
-		if (!r) {
-			ret = -ENODEV;
-			goto fail;
-		}
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
 
-		len = r->end - r->start + 1;
+	if (!r) {
+		ret = -ENODEV;
+		goto fail_clk;
+	}
 
-		r2 = request_mem_region(r->start, len, r->name);
-		if (!r2) {
-			pr_err("Could not request memory region: "
-			"start=%p, len=%d\n", (void *) r->start, len);
-			ret = -EBUSY;
-			goto fail;
-		}
+	len = resource_size(r);
 
-		regs_base = ioremap(r2->start, len);
+	r2 = request_mem_region(r->start, len, r->name);
+	if (!r2) {
+		pr_err("Could not request memory region: start=%p, len=%d\n",
+							(void *) r->start, len);
+		ret = -EBUSY;
+		goto fail_clk;
+	}
 
-		if (!regs_base) {
-			pr_err("Could not ioremap: start=%p, len=%d\n",
-				 (void *) r2->start, len);
-			ret = -EBUSY;
-			goto fail_mem;
-		}
+	regs_base = ioremap(r2->start, len);
 
-		irq = platform_get_irq_byname(pdev, "secure_irq");
-		if (irq < 0) {
-			ret = -ENODEV;
-			goto fail_io;
-		}
+	if (!regs_base) {
+		pr_err("Could not ioremap: start=%p, len=%d\n",
+			 (void *) r2->start, len);
+		ret = -EBUSY;
+		goto fail_mem;
+	}
 
-		mb();
+	irq = platform_get_irq_byname(pdev, "secure_irq");
+	if (irq < 0) {
+		ret = -ENODEV;
+		goto fail_io;
+	}
 
-		if (GET_IDR(regs_base) == 0) {
-			pr_err("Invalid IDR value detected\n");
-			ret = -ENODEV;
-			goto fail_io;
-		}
+	msm_iommu_reset(regs_base, iommu_dev->ncb);
 
-		ret = request_irq(irq, msm_iommu_fault_handler, 0,
-				"msm_iommu_secure_irpt_handler", drvdata);
-		if (ret) {
-			pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-			goto fail_io;
-		}
+	SET_M(regs_base, 0, 1);
+	SET_PAR(regs_base, 0, 0);
+	SET_V2PCFG(regs_base, 0, 1);
+	SET_V2PPR(regs_base, 0, 0);
+	par = GET_PAR(regs_base, 0);
+	SET_V2PCFG(regs_base, 0, 0);
+	SET_M(regs_base, 0, 0);
 
-		msm_iommu_reset(regs_base);
-		drvdata->base = regs_base;
-		drvdata->irq = irq;
+	if (!par) {
+		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
+		ret = -ENODEV;
+		goto fail_io;
+	}
 
-		nm2v = GET_NM2VCBMT((unsigned long) regs_base);
-		ncb = GET_NCB((unsigned long) regs_base);
+	ret = request_irq(irq, msm_iommu_fault_handler, 0,
+			"msm_iommu_secure_irpt_handler", drvdata);
+	if (ret) {
+		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+		goto fail_io;
+	}
 
-		pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-			iommu_dev->name, regs_base, irq, ncb+1);
 
-		platform_set_drvdata(pdev, drvdata);
-	} else
-		msm_iommu_root_dev = pdev;
+	drvdata->pclk = iommu_pclk;
+	drvdata->clk = iommu_clk;
+	drvdata->base = regs_base;
+	drvdata->irq = irq;
+	drvdata->ncb = iommu_dev->ncb;
 
-	return 0;
+	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	if (iommu_clk)
+		clk_disable(iommu_clk);
+
+	clk_disable(iommu_pclk);
 
+	return 0;
 fail_io:
 	iounmap(regs_base);
 fail_mem:
 	release_mem_region(r->start, len);
+fail_clk:
+	if (iommu_clk) {
+		clk_disable(iommu_clk);
+		clk_put(iommu_clk);
+	}
+fail_pclk:
+	clk_disable(iommu_pclk);
+fail_enable:
+	clk_put(iommu_pclk);
 fail:
 	kfree(drvdata);
 	return ret;
@@ -252,7 +275,10 @@ static int msm_iommu_remove(struct platform_device *pdev)
 
 	drv = platform_get_drvdata(pdev);
 	if (drv) {
-		memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+		if (drv->clk)
+			clk_put(drv->clk);
+		clk_put(drv->pclk);
+		memset(drv, 0, sizeof(*drv));
 		kfree(drv);
 		platform_set_drvdata(pdev, NULL);
 	}
@@ -264,7 +290,7 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
 	struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
-	int i, ret = 0;
+	int i, ret;
 	if (!c || !pdev->dev.parent) {
 		ret = -EINVAL;
 		goto fail;
@@ -288,6 +314,18 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
 	platform_set_drvdata(pdev, ctx_drvdata);
 
+	ret = clk_enable(drvdata->pclk);
+	if (ret)
+		goto fail;
+
+	if (drvdata->clk) {
+		ret = clk_enable(drvdata->clk);
+		if (ret) {
+			clk_disable(drvdata->pclk);
+			goto fail;
+		}
+	}
+
 	/* Program the M2V tables for this context */
 	for (i = 0; i < MAX_NUM_MIDS; i++) {
 		int mid = c->mids[i];
@@ -297,21 +335,27 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
 		SET_M2VCBR_N(drvdata->base, mid, 0);
 		SET_CBACR_N(drvdata->base, c->num, 0);
 
-		/* Set VMID = MID */
-		SET_VMID(drvdata->base, mid, mid);
+		/* Set VMID = 0 */
+		SET_VMID(drvdata->base, mid, 0);
 
 		/* Set the context number for that MID to this context */
 		SET_CBNDX(drvdata->base, mid, c->num);
 
-		/* Set MID associated with this context bank */
-		SET_CBVMID(drvdata->base, c->num, mid);
+		/* Set MID associated with this context bank to 0*/
+		SET_CBVMID(drvdata->base, c->num, 0);
+
+		/* Set the ASID for TLB tagging for this context */
+		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
 
 		/* Set security bit override to be Non-secure */
 		SET_NSCFG(drvdata->base, mid, 3);
 	}
 
-	pr_info("context device %s with bank index %d\n", c->name, c->num);
+	if (drvdata->clk)
+		clk_disable(drvdata->clk);
+	clk_disable(drvdata->pclk);
 
+	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
 	return 0;
 fail:
 	kfree(ctx_drvdata);
diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-msm/scm-boot.h
index 68f9b61..7be32ff 100644
--- a/arch/arm/mach-msm/scm-boot.h
+++ b/arch/arm/mach-msm/scm-boot.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2010, Code Aurora Forum. 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 of Code Aurora Forum, Inc. nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_SCM_BOOT_H
 #define __MACH_SCM_BOOT_H
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index f4b9bc9..cfa808d 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -174,15 +174,18 @@ static u32 smc(u32 cmd_addr)
 	register u32 r0 asm("r0") = 1;
 	register u32 r1 asm("r1") = (u32)&context_id;
 	register u32 r2 asm("r2") = cmd_addr;
-	asm(
-		__asmeq("%0", "r0")
-		__asmeq("%1", "r0")
-		__asmeq("%2", "r1")
-		__asmeq("%3", "r2")
-		"smc	#0	@ switch to secure world\n"
-		: "=r" (r0)
-		: "r" (r0), "r" (r1), "r" (r2)
-		: "r3");
+	do {
+		asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r0")
+			__asmeq("%2", "r1")
+			__asmeq("%3", "r2")
+			"smc	#0	@ switch to secure world\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2)
+			: "r3");
+	} while (r0 == SCM_INTERRUPTED);
+
 	return r0;
 }
 
@@ -197,13 +200,9 @@ static int __scm_call(const struct scm_command *cmd)
 	 * side in the buffer.
 	 */
 	flush_cache_all();
-	do {
-		ret = smc(cmd_addr);
-		if (ret < 0) {
-			ret = scm_remap_error(ret);
-			break;
-		}
-	} while (ret == SCM_INTERRUPTED);
+	ret = smc(cmd_addr);
+	if (ret < 0)
+		ret = scm_remap_error(ret);
 
 	return ret;
 }
@@ -264,21 +263,28 @@ u32 scm_get_version(void)
 {
 	int context_id;
 	static u32 version = -1;
-	register u32 r0 asm("r0") = 0x1 << 8;
-	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r0 asm("r0");
+	register u32 r1 asm("r1");
 
 	if (version != -1)
 		return version;
 
 	mutex_lock(&scm_lock);
-	asm(
-		__asmeq("%0", "r1")
-		__asmeq("%1", "r0")
-		__asmeq("%2", "r1")
-		"smc	#0	@ switch to secure world\n"
-		: "=r" (r1)
-		: "r" (r0), "r" (r1)
-		: "r2", "r3");
+
+	r0 = 0x1 << 8;
+	r1 = (u32)&context_id;
+	do {
+		asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r1")
+			__asmeq("%2", "r0")
+			__asmeq("%3", "r1")
+			"smc	#0	@ switch to secure world\n"
+			: "=r" (r0), "=r" (r1)
+			: "r" (r0), "r" (r1)
+			: "r2", "r3");
+	} while (r0 == SCM_INTERRUPTED);
+
 	version = r1;
 	mutex_unlock(&scm_lock);
 
diff --git a/arch/arm/mach-msm/scm.h b/arch/arm/mach-msm/scm.h
index 261786b..00b31ea 100644
--- a/arch/arm/mach-msm/scm.h
+++ b/arch/arm/mach-msm/scm.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2010, Code Aurora Forum. 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 of Code Aurora Forum, Inc. nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
+ * 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 SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_SCM_H
 #define __MACH_SCM_H
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index c105d28..e7f8e5a 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -24,10 +24,7 @@
 
 #include <asm/mach/time.h>
 #include <mach/msm_iomap.h>
-
-#ifndef MSM_DGT_BASE
-#define MSM_DGT_BASE (MSM_GPT_BASE + 0x10)
-#endif
+#include <mach/cpu.h>
 
 #define TIMER_MATCH_VAL         0x0000
 #define TIMER_COUNT_VAL         0x0004
@@ -52,18 +49,14 @@ enum timer_location {
 	GLOBAL_TIMER = 1,
 };
 
-#ifdef MSM_TMR0_BASE
-#define MSM_TMR_GLOBAL		(MSM_TMR0_BASE - MSM_TMR_BASE)
-#else
-#define MSM_TMR_GLOBAL		0
-#endif
-
 #define MSM_GLOBAL_TIMER MSM_CLOCK_DGT
 
+/* TODO: Remove these ifdefs */
 #if defined(CONFIG_ARCH_QSD8X50)
 #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
 #define MSM_DGT_SHIFT (0)
-#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
+#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \
+				      defined(CONFIG_ARCH_MSM8960)
 #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
 #define MSM_DGT_SHIFT (0)
 #else
@@ -177,11 +170,7 @@ static struct msm_clock msm_clocks[] = {
 			.dev_id  = &msm_clocks[0].clockevent,
 			.irq     = INT_GP_TIMER_EXP
 		},
-		.regbase = MSM_GPT_BASE,
 		.freq = GPT_HZ,
-		.local_counter = MSM_GPT_BASE + TIMER_COUNT_VAL,
-		.global_counter = MSM_GPT_BASE + TIMER_COUNT_VAL +
-			MSM_TMR_GLOBAL,
 	},
 	[MSM_CLOCK_DGT] = {
 		.clockevent = {
@@ -206,12 +195,8 @@ static struct msm_clock msm_clocks[] = {
 			.dev_id  = &msm_clocks[1].clockevent,
 			.irq     = INT_DEBUG_TIMER_EXP
 		},
-		.regbase = MSM_DGT_BASE,
 		.freq = DGT_HZ >> MSM_DGT_SHIFT,
 		.shift = MSM_DGT_SHIFT,
-		.local_counter = MSM_DGT_BASE + TIMER_COUNT_VAL,
-		.global_counter = MSM_DGT_BASE + TIMER_COUNT_VAL +
-			MSM_TMR_GLOBAL,
 	}
 };
 
@@ -219,6 +204,25 @@ static void __init msm_timer_init(void)
 {
 	int i;
 	int res;
+	int global_offset = 0;
+
+	if (cpu_is_msm7x01()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+	} else if (cpu_is_msm7x30()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24;
+	} else if (cpu_is_qsd8x50()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+	} else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24;
+
+		/* Use CPU0's timer as the global timer. */
+		global_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
+	} else
+		BUG();
 
 #ifdef CONFIG_ARCH_MSM_SCORPIONMP
 	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
@@ -228,6 +232,10 @@ static void __init msm_timer_init(void)
 		struct msm_clock *clock = &msm_clocks[i];
 		struct clock_event_device *ce = &clock->clockevent;
 		struct clocksource *cs = &clock->clocksource;
+
+		clock->local_counter = clock->regbase + TIMER_COUNT_VAL;
+		clock->global_counter = clock->local_counter + global_offset;
+
 		writel(0, clock->regbase + TIMER_ENABLE);
 		writel(0, clock->regbase + TIMER_CLEAR);
 		writel(~0, clock->regbase + TIMER_MATCH_VAL);
diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
index 29e390e..20f3f12 100644
--- a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
+++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
@@ -148,6 +148,7 @@ MACHINE_START(TERASTATION_WXL, "Buffalo Nas WXL")
 	.boot_params	= 0x00000100,
 	.init_machine	= wxl_init,
 	.map_io		= mv78xx0_map_io,
+	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
 	.timer		= &mv78xx0_timer,
 MACHINE_END
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index 08465eb..44fb4e5 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -818,9 +818,15 @@ void __init mv78xx0_uart3_init(void)
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init mv78xx0_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 static void mv78xx0_timer_init(void)
 {
-	orion_time_init(IRQ_MV78XX0_TIMER_1, get_tclk());
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_MV78XX0_TIMER_1, get_tclk());
 }
 
 struct sys_timer mv78xx0_timer = {
diff --git a/arch/arm/mach-mv78xx0/common.h b/arch/arm/mach-mv78xx0/common.h
index befc224..632e63d 100644
--- a/arch/arm/mach-mv78xx0/common.h
+++ b/arch/arm/mach-mv78xx0/common.h
@@ -20,6 +20,7 @@ struct mv_sata_platform_data;
 int mv78xx0_core_index(void);
 void mv78xx0_map_io(void);
 void mv78xx0_init(void);
+void mv78xx0_init_early(void);
 void mv78xx0_init_irq(void);
 
 extern struct mbus_dram_target_info mv78xx0_mbus_dram_info;
diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
index 207c95e..df5aebe 100644
--- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
+++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
@@ -96,6 +96,7 @@ MACHINE_START(DB78X00_BP, "Marvell DB-78x00-BP Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= db78x00_init,
 	.map_io		= mv78xx0_map_io,
+	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
 	.timer		= &mv78xx0_timer,
 MACHINE_END
diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
index 2d14c4f..c64dbb9 100644
--- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
+++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
@@ -20,10 +20,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff --git a/arch/arm/mach-mv78xx0/include/mach/gpio.h b/arch/arm/mach-mv78xx0/include/mach/gpio.h
index d9d1535..77e1b84 100644
--- a/arch/arm/mach-mv78xx0/include/mach/gpio.h
+++ b/arch/arm/mach-mv78xx0/include/mach/gpio.h
@@ -6,35 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-extern int mv78xx0_core_index(void);
-
-#define GPIO_MAX		32
-#define GPIO_OUT(pin)		(DEV_BUS_VIRT_BASE + 0x0100)
-#define GPIO_IO_CONF(pin)	(DEV_BUS_VIRT_BASE + 0x0104)
-#define GPIO_BLINK_EN(pin)	(DEV_BUS_VIRT_BASE + 0x0108)
-#define GPIO_IN_POL(pin)	(DEV_BUS_VIRT_BASE + 0x010c)
-#define GPIO_DATA_IN(pin)	(DEV_BUS_VIRT_BASE + 0x0110)
-#define GPIO_EDGE_CAUSE(pin)	(DEV_BUS_VIRT_BASE + 0x0114)
-#define GPIO_MASK_OFF		(mv78xx0_core_index() ? 0x18 : 0)
-#define GPIO_EDGE_MASK(pin)	(DEV_BUS_VIRT_BASE + 0x0118 + GPIO_MASK_OFF)
-#define GPIO_LEVEL_MASK(pin)	(DEV_BUS_VIRT_BASE + 0x011c + GPIO_MASK_OFF)
-
-static inline int gpio_to_irq(int pin)
-{
-	return pin + IRQ_MV78XX0_GPIO_START;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	return irq - IRQ_MV78XX0_GPIO_START;
-}
-
-
-#endif
diff --git a/arch/arm/mach-mv78xx0/include/mach/memory.h b/arch/arm/mach-mv78xx0/include/mach/memory.h
index e663042..a648c51 100644
--- a/arch/arm/mach-mv78xx0/include/mach/memory.h
+++ b/arch/arm/mach-mv78xx0/include/mach/memory.h
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
index 3eff399..3674497 100644
--- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
+++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
@@ -71,6 +71,7 @@
 #define DEV_BUS_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x10000)
 #define  SAMPLE_AT_RESET_LOW	(DEV_BUS_VIRT_BASE | 0x0030)
 #define  SAMPLE_AT_RESET_HIGH	(DEV_BUS_VIRT_BASE | 0x0034)
+#define  GPIO_VIRT_BASE		(DEV_BUS_VIRT_BASE | 0x0100)
 #define  I2C_0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x1000)
 #define  I2C_1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x1100)
 #define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c
index 22b4ff8..08da497 100644
--- a/arch/arm/mach-mv78xx0/irq.c
+++ b/arch/arm/mach-mv78xx0/irq.c
@@ -26,28 +26,18 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 void __init mv78xx0_init_irq(void)
 {
-	int i;
-
-	/* Initialize gpiolib. */
-	orion_gpio_init();
-
 	orion_irq_init(0, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF));
 	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
 	orion_irq_init(64, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF));
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts.
+	 * Initialize gpiolib for GPIOs 0-31.  (The GPIO interrupt mask
+	 * registers for core #1 are at an offset of 0x18 from those of
+	 * core #0.)
 	 */
-	writel(0, GPIO_LEVEL_MASK(0));
-	writel(0, GPIO_EDGE_MASK(0));
-	writel(0, GPIO_EDGE_CAUSE(0));
-
-	for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
+	orion_gpio_init(0, 32, GPIO_VIRT_BASE,
+			mv78xx0_core_index() ? 0x18 : 0,
+			IRQ_MV78XX0_GPIO_START);
 	set_irq_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
diff --git a/arch/arm/mach-mv78xx0/mpp.c b/arch/arm/mach-mv78xx0/mpp.c
index 84db2df..65b72c4 100644
--- a/arch/arm/mach-mv78xx0/mpp.c
+++ b/arch/arm/mach-mv78xx0/mpp.c
@@ -44,9 +44,6 @@ void __init mv78xx0_mpp_conf(unsigned int *mpp_list)
 	if (!variant_mask)
 		return;
 
-	/* Initialize gpiolib. */
-	orion_gpio_init();
-
 	printk(KERN_DEBUG "initial MPP regs:");
 	for (i = 0; i < MPP_NR_REGS; i++) {
 		mpp_ctrl[i] = readl(MPP_CTRL(i));
diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
index 3511ad4..d927f14 100644
--- a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
+++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
@@ -81,6 +81,7 @@ MACHINE_START(RD78X00_MASA, "Marvell RD-78x00-MASA Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd78x00_masa_init,
 	.map_io		= mv78xx0_map_io,
+	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
 	.timer		= &mv78xx0_timer,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 0717f88..340809a 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -94,6 +94,7 @@ config MACH_MX31_3DS
 	select MXC_DEBUG_BOARD
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -183,6 +184,7 @@ config MACH_MX35_3DS
 	select MXC_DEBUG_BOARD
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
@@ -199,6 +201,15 @@ config MACH_KZM_ARM11_01
 	  Include support for KZM-ARM11-01. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_BUG
+	bool "Support Buglabs BUGBase platform"
+	select SOC_IMX31
+	select IMX_HAVE_PLATFORM_IMX_UART
+	default y
+	help
+	  Include support for BUGBase 1.3 platform. This includes specific
+	  configurations for the board and its peripherals.
+
 config MACH_EUKREA_CPUIMX35
 	bool "Support Eukrea CPUIMX35 Platform"
 	select SOC_IMX35
@@ -229,4 +240,18 @@ config MACH_EUKREA_MBIMXSD35_BASEBOARD
 
 endchoice
 
+config MACH_VPR200
+	bool "Support VPR200 platform"
+	select SOC_IMX35
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	help
+	  Include support for VPR200 platform. This includes specific
+	  configurations for the board and its peripherals.
+
 endif
diff --git a/arch/arm/mach-mx3/Makefile b/arch/arm/mach-mx3/Makefile
index 8db1329..a54faf2 100644
--- a/arch/arm/mach-mx3/Makefile
+++ b/arch/arm/mach-mx3/Makefile
@@ -5,8 +5,8 @@
 # Object file lists.
 
 obj-y				:= mm.o devices.o cpu.o
-obj-$(CONFIG_SOC_IMX31)		+= clock-imx31.o iomux-imx31.o
-obj-$(CONFIG_SOC_IMX35)		+= clock-imx35.o
+obj-$(CONFIG_SOC_IMX31)		+= clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35)		+= clock-imx35.o ehci-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)	+= mach-mx31ads.o
 obj-$(CONFIG_MACH_MX31LILLY)	+= mach-mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)	+= mach-mx31lite.o mx31lite-db.o
@@ -20,5 +20,7 @@ obj-$(CONFIG_MACH_PCM043)	+= mach-pcm043.o
 obj-$(CONFIG_MACH_ARMADILLO5X0) += mach-armadillo5x0.o
 obj-$(CONFIG_MACH_MX35_3DS)	+= mach-mx35_3ds.o
 obj-$(CONFIG_MACH_KZM_ARM11_01)	+= mach-kzm_arm11_01.o
+obj-$(CONFIG_MACH_BUG)		+= mach-bug.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX35)	+= mach-cpuimx35.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD)	+= eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MACH_VPR200)	+= mach-vpr200.o
diff --git a/arch/arm/mach-mx3/devices-imx35.h b/arch/arm/mach-mx3/devices-imx35.h
index 677b18a..d545d86 100644
--- a/arch/arm/mach-mx3/devices-imx35.h
+++ b/arch/arm/mach-mx3/devices-imx35.h
@@ -35,7 +35,7 @@ extern const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst;
 #define imx35_add_imx_i2c2(pdata)	imx35_add_imx_i2c(2, pdata)
 
 extern const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst;
-#define imx31_add_imx_keypad(pdata)	\
+#define imx35_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx35_imx_keypad_data, pdata)
 
 extern const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst;
diff --git a/arch/arm/mach-mx3/ehci-imx31.c b/arch/arm/mach-mx3/ehci-imx31.c
new file mode 100644
index 0000000..314a983
--- /dev/null
+++ b/arch/arm/mach-mx3/ehci-imx31.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX31_OTG_SIC_SHIFT	29
+#define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT)
+#define MX31_OTG_PM_BIT		(1 << 24)
+
+#define MX31_H2_SIC_SHIFT	21
+#define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT)
+#define MX31_H2_PM_BIT		(1 << 16)
+#define MX31_H2_DT_BIT		(1 << 5)
+
+#define MX31_H1_SIC_SHIFT	13
+#define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT)
+#define MX31_H1_PM_BIT		(1 << 8)
+#define MX31_H1_DT_BIT		(1 << 4)
+
+int mx31_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX31_OTG_PM_BIT;
+
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX31_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX31_H1_DT_BIT;
+
+		break;
+	case 2:	/* H2 port */
+		v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX31_H2_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX31_H2_DT_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-mx3/ehci-imx35.c b/arch/arm/mach-mx3/ehci-imx35.c
new file mode 100644
index 0000000..33983a4
--- /dev/null
+++ b/arch/arm/mach-mx3/ehci-imx35.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX35_OTG_SIC_SHIFT	29
+#define MX35_OTG_SIC_MASK	(0x3 << MX35_OTG_SIC_SHIFT)
+#define MX35_OTG_PM_BIT		(1 << 24)
+
+#define MX35_H1_SIC_SHIFT	21
+#define MX35_H1_SIC_MASK	(0x3 << MX35_H1_SIC_SHIFT)
+#define MX35_H1_PM_BIT		(1 << 8)
+#define MX35_H1_IPPUE_UP_BIT	(1 << 7)
+#define MX35_H1_IPPUE_DOWN_BIT	(1 << 6)
+#define MX35_H1_TLL_BIT		(1 << 5)
+#define MX35_H1_USBTE_BIT	(1 << 4)
+
+int mx35_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX35_OTG_PM_BIT;
+
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
+			MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX35_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX35_H1_TLL_BIT;
+
+		if (flags & MXC_EHCI_INTERNAL_PHY)
+			v |= MX35_H1_USBTE_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_DOWN)
+			v |= MX35_H1_IPPUE_DOWN_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_UP)
+			v |= MX35_H1_IPPUE_UP_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
index 14a5ffc..8076147 100644
--- a/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
+++ b/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
@@ -165,8 +165,8 @@ static iomux_v3_cfg_t eukrea_mbimxsd_pads[] = {
 	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
 };
 
-#define GPIO_LED1	(2 * 32 + 29)
-#define GPIO_SWITCH1	(2 * 32 + 25)
+#define GPIO_LED1	IMX_GPIO_NR(3, 29)
+#define GPIO_SWITCH1	IMX_GPIO_NR(3, 25)
 #define GPIO_LCDPWR	(4)
 
 static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
diff --git a/arch/arm/mach-mx3/iomux-imx31.c b/arch/arm/mach-mx3/iomux-imx31.c
index a1d7fa5..cf8f809 100644
--- a/arch/arm/mach-mx3/iomux-imx31.c
+++ b/arch/arm/mach-mx3/iomux-imx31.c
@@ -97,7 +97,7 @@ EXPORT_SYMBOL(mxc_iomux_set_pad);
  * 	- reserves the pin so that it is not claimed by another driver
  * 	- setups the iomux according to the configuration
  */
-int mxc_iomux_alloc_pin(const unsigned int pin, const char *label)
+int mxc_iomux_alloc_pin(unsigned int pin, const char *label)
 {
 	unsigned pad = pin & IOMUX_PADNUM_MASK;
 
@@ -118,10 +118,10 @@ int mxc_iomux_alloc_pin(const unsigned int pin, const char *label)
 }
 EXPORT_SYMBOL(mxc_iomux_alloc_pin);
 
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 	int ret = -EINVAL;
 
@@ -139,7 +139,7 @@ setup_error:
 }
 EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
 
-void mxc_iomux_release_pin(const unsigned int pin)
+void mxc_iomux_release_pin(unsigned int pin)
 {
 	unsigned pad = pin & IOMUX_PADNUM_MASK;
 
@@ -148,9 +148,9 @@ void mxc_iomux_release_pin(const unsigned int pin)
 }
 EXPORT_SYMBOL(mxc_iomux_release_pin);
 
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 
 	for (i = 0; i < count; i++) {
diff --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
index 28b6f41..226829b 100644
--- a/arch/arm/mach-mx3/mach-armadillo5x0.c
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -133,7 +133,6 @@ static int armadillo5x0_pins[] = {
 };
 
 /* USB */
-#if defined(CONFIG_USB_ULPI)
 
 #define OTG_RESET IOMUX_TO_GPIO(MX31_PIN_STXD4)
 #define USBH2_RESET IOMUX_TO_GPIO(MX31_PIN_SCK6)
@@ -176,8 +175,10 @@ static int usbotg_init(struct platform_device *pdev)
 	gpio_set_value(OTG_RESET, 0/*LOW*/);
 	mdelay(5);
 	gpio_set_value(OTG_RESET, 1/*HIGH*/);
+	mdelay(10);
 
-	return 0;
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_DIFF_UNI);
 
 otg_free_reset:
 	gpio_free(OTG_RESET);
@@ -233,8 +234,10 @@ static int usbh2_init(struct platform_device *pdev)
 	gpio_set_value(USBH2_RESET, 0/*LOW*/);
 	mdelay(5);
 	gpio_set_value(USBH2_RESET, 1/*HIGH*/);
+	mdelay(10);
 
-	return 0;
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_DIFF_UNI);
 
 h2_free_reset:
 	gpio_free(USBH2_RESET);
@@ -246,15 +249,12 @@ h2_free_cs:
 static struct mxc_usbh_platform_data usbotg_pdata __initdata = {
 	.init	= usbotg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif /* CONFIG_USB_ULPI */
 
 /* RTC over I2C*/
 #define ARMADILLO5X0_RTC_GPIO	IOMUX_TO_GPIO(MX31_PIN_SRXD4)
@@ -547,15 +547,15 @@ static void __init armadillo5x0_init(void)
 	i2c_register_board_info(1, &armadillo5x0_i2c_rtc, 1);
 
 	/* USB */
-#if defined(CONFIG_USB_ULPI)
-	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-	imx31_add_mxc_ehci_otg(&usbotg_pdata);
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
+
+	usbotg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbotg_pdata.otg)
+		imx31_add_mxc_ehci_otg(&usbotg_pdata);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 }
 
 static void __init armadillo5x0_timer_init(void)
@@ -569,9 +569,10 @@ static struct sys_timer armadillo5x0_timer = {
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	/* Maintainer: Alberto Panizzo  */
-	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
-	.map_io		= mx31_map_io,
-	.init_irq	= mx31_init_irq,
-	.timer		= &armadillo5x0_timer,
-	.init_machine	= armadillo5x0_init,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &armadillo5x0_timer,
+	.init_machine = armadillo5x0_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-bug.c b/arch/arm/mach-mx3/mach-bug.c
new file mode 100644
index 0000000..d137d70
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-bug.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/iomux-mx3.h>
+#include <mach/imx-uart.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "devices-imx31.h"
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const unsigned int bug_pins[] __initconst = {
+	MX31_PIN_PC_RST__CTS5,
+	MX31_PIN_PC_VS2__RTS5,
+	MX31_PIN_PC_BVD2__TXD5,
+	MX31_PIN_PC_BVD1__RXD5,
+};
+
+static void __init bug_board_init(void)
+{
+	mxc_iomux_setup_multiple_pins(bug_pins,
+				      ARRAY_SIZE(bug_pins), "uart-4");
+	imx31_add_imx_uart4(&uart_pdata);
+}
+
+static void __init bug_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer bug_timer = {
+	.init = bug_timer_init,
+};
+
+MACHINE_START(BUG, "BugLabs BUGBase")
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &bug_timer,
+	.init_machine = bug_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-cpuimx35.c b/arch/arm/mach-mx3/mach-cpuimx35.c
index 26ae90f..ec63d99 100644
--- a/arch/arm/mach-mx3/mach-cpuimx35.c
+++ b/arch/arm/mach-mx3/mach-cpuimx35.c
@@ -60,7 +60,7 @@ static struct tsc2007_platform_data tsc2007_info = {
 	.x_plate_ohms		= 180,
 };
 
-#define TSC2007_IRQGPIO		(2 * 32 + 2)
+#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 2)
 static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
@@ -111,15 +111,25 @@ static const struct mxc_nand_platform_data
 	.flash_bbt	= 1,
 };
 
+static int eukrea_cpuimx35_otg_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static const struct mxc_usbh_platform_data otg_pdata __initconst = {
+	.init	= eukrea_cpuimx35_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int eukrea_cpuimx35_usbh1_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
+}
+
 static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
+	.init	= eukrea_cpuimx35_usbh1_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
 };
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
@@ -146,7 +156,7 @@ __setup("otg_mode=", eukrea_cpuimx35_otg_mode);
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init eukrea_cpuimx35_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
 			ARRAY_SIZE(eukrea_cpuimx35_pads));
@@ -184,9 +194,10 @@ struct sys_timer eukrea_cpuimx35_timer = {
 
 MACHINE_START(EUKREA_CPUIMX35, "Eukrea CPUIMX35")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &eukrea_cpuimx35_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &eukrea_cpuimx35_timer,
+	.init_machine = eukrea_cpuimx35_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-kzm_arm11_01.c b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
index a5f3eb2..d35621d 100644
--- a/arch/arm/mach-mx3/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-mx3/mach-kzm_arm11_01.c
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
+#include <asm/memory.h>
 #include <asm/setup.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -36,7 +37,6 @@
 #include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
-#include <mach/memory.h>
 
 #include "devices-imx31.h"
 #include "devices.h"
@@ -266,17 +266,14 @@ static void __init kzm_timer_init(void)
 }
 
 static struct sys_timer kzm_timer = {
-	.init   = kzm_timer_init,
+	.init = kzm_timer_init,
 };
 
-/*
- * The following uses standard kernel macros define in arch.h in order to
- * initialize __mach_desc_KZM_ARM11_01 data structure.
- */
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = kzm_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = kzm_board_init,
-	.timer          = &kzm_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = kzm_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &kzm_timer,
+	.init_machine = kzm_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c
index 0d65db8..544d3e4 100644
--- a/arch/arm/mach-mx3/mach-mx31_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx31_3ds.c
@@ -21,9 +21,13 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/l4f00242t03.h>
 #include <linux/regulator/machine.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
+#include <linux/memblock.h>
+
+#include <media/soc_camera.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -35,6 +39,10 @@
 #include <mach/iomux-mx3.h>
 #include <mach/3ds_debugboard.h>
 #include <mach/ulpi.h>
+#include <mach/mmc.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+#include <mach/mx3_camera.h>
 
 #include "devices-imx31.h"
 #include "devices.h"
@@ -42,10 +50,6 @@
 /* CPLD IRQ line for external uart, external ethernet etc */
 #define EXPIO_PARENT_INT	IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
 
-/*
- * This file contains the board-specific initialization routines.
- */
-
 static int mx31_3ds_pins[] = {
 	/* UART1 */
 	MX31_PIN_CTS1__CTS1,
@@ -53,6 +57,12 @@ static int mx31_3ds_pins[] = {
 	MX31_PIN_TXD1__TXD1,
 	MX31_PIN_RXD1__RXD1,
 	IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
+	/*SPI0*/
+	MX31_PIN_CSPI1_SCLK__SCLK,
+	MX31_PIN_CSPI1_MOSI__MOSI,
+	MX31_PIN_CSPI1_MISO__MISO,
+	MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI1_SS2__SS2, /* CS for LCD */
 	/* SPI 1 */
 	MX31_PIN_CSPI2_SCLK__SCLK,
 	MX31_PIN_CSPI2_MOSI__MOSI,
@@ -100,6 +110,252 @@ static int mx31_3ds_pins[] = {
 	IOMUX_MODE(MX31_PIN_PC_RW_B, IOMUX_CONFIG_ALT1),
 	/* USB Host2 reset */
 	IOMUX_MODE(MX31_PIN_USB_BYP, IOMUX_CONFIG_GPIO),
+	/* I2C1 */
+	MX31_PIN_I2C_CLK__I2C1_SCL,
+	MX31_PIN_I2C_DAT__I2C1_SDA,
+	/* SDHC1 */
+	MX31_PIN_SD1_DATA3__SD1_DATA3,
+	MX31_PIN_SD1_DATA2__SD1_DATA2,
+	MX31_PIN_SD1_DATA1__SD1_DATA1,
+	MX31_PIN_SD1_DATA0__SD1_DATA0,
+	MX31_PIN_SD1_CLK__SD1_CLK,
+	MX31_PIN_SD1_CMD__SD1_CMD,
+	MX31_PIN_GPIO3_1__GPIO3_1, /* Card detect */
+	MX31_PIN_GPIO3_0__GPIO3_0, /* OE */
+	/* Framebuffer */
+	MX31_PIN_LD0__LD0,
+	MX31_PIN_LD1__LD1,
+	MX31_PIN_LD2__LD2,
+	MX31_PIN_LD3__LD3,
+	MX31_PIN_LD4__LD4,
+	MX31_PIN_LD5__LD5,
+	MX31_PIN_LD6__LD6,
+	MX31_PIN_LD7__LD7,
+	MX31_PIN_LD8__LD8,
+	MX31_PIN_LD9__LD9,
+	MX31_PIN_LD10__LD10,
+	MX31_PIN_LD11__LD11,
+	MX31_PIN_LD12__LD12,
+	MX31_PIN_LD13__LD13,
+	MX31_PIN_LD14__LD14,
+	MX31_PIN_LD15__LD15,
+	MX31_PIN_LD16__LD16,
+	MX31_PIN_LD17__LD17,
+	MX31_PIN_VSYNC3__VSYNC3,
+	MX31_PIN_HSYNC__HSYNC,
+	MX31_PIN_FPSHIFT__FPSHIFT,
+	MX31_PIN_CONTRAST__CONTRAST,
+	/* CSI */
+	MX31_PIN_CSI_D6__CSI_D6,
+	MX31_PIN_CSI_D7__CSI_D7,
+	MX31_PIN_CSI_D8__CSI_D8,
+	MX31_PIN_CSI_D9__CSI_D9,
+	MX31_PIN_CSI_D10__CSI_D10,
+	MX31_PIN_CSI_D11__CSI_D11,
+	MX31_PIN_CSI_D12__CSI_D12,
+	MX31_PIN_CSI_D13__CSI_D13,
+	MX31_PIN_CSI_D14__CSI_D14,
+	MX31_PIN_CSI_D15__CSI_D15,
+	MX31_PIN_CSI_HSYNC__CSI_HSYNC,
+	MX31_PIN_CSI_MCLK__CSI_MCLK,
+	MX31_PIN_CSI_PIXCLK__CSI_PIXCLK,
+	MX31_PIN_CSI_VSYNC__CSI_VSYNC,
+	MX31_PIN_CSI_D5__GPIO3_5, /* CMOS PWDN */
+	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */
+};
+
+/*
+ * Camera support
+ */
+static phys_addr_t mx3_camera_base __initdata;
+#define MX31_3DS_CAMERA_BUF_SIZE SZ_8M
+
+#define MX31_3DS_GPIO_CAMERA_PW IOMUX_TO_GPIO(MX31_PIN_CSI_D5)
+#define MX31_3DS_GPIO_CAMERA_RST IOMUX_TO_GPIO(MX31_PIN_RI_DTE1)
+
+static struct gpio mx31_3ds_camera_gpios[] = {
+	{ MX31_3DS_GPIO_CAMERA_PW, GPIOF_OUT_INIT_HIGH, "camera-power" },
+	{ MX31_3DS_GPIO_CAMERA_RST, GPIOF_OUT_INIT_HIGH, "camera-reset" },
+};
+
+static int __init mx31_3ds_camera_alloc_dma(void)
+{
+	int dma;
+
+	if (!mx3_camera_base)
+		return -ENOMEM;
+
+	dma = dma_declare_coherent_memory(&mx3_camera.dev,
+					mx3_camera_base, mx3_camera_base,
+					MX31_3DS_CAMERA_BUF_SIZE,
+					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+	if (!(dma & DMA_MEMORY_MAP))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int mx31_3ds_camera_power(struct device *dev, int on)
+{
+	/* enable or disable the camera */
+	pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
+	gpio_set_value(MX31_3DS_GPIO_CAMERA_PW, on ? 0 : 1);
+
+	if (!on)
+		goto out;
+
+	/* If enabled, give a reset impulse */
+	gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 0);
+	msleep(20);
+	gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 1);
+	msleep(100);
+
+out:
+	return 0;
+}
+
+static struct i2c_board_info mx31_3ds_i2c_camera = {
+	I2C_BOARD_INFO("ov2640", 0x30),
+};
+
+static struct regulator_bulk_data mx31_3ds_camera_regs[] = {
+	{ .supply = "cmos_vcore" },
+	{ .supply = "cmos_2v8" },
+};
+
+static struct soc_camera_link iclink_ov2640 = {
+	.bus_id		= 0,
+	.board_info	= &mx31_3ds_i2c_camera,
+	.i2c_adapter_id	= 0,
+	.power		= mx31_3ds_camera_power,
+	.regulators	= mx31_3ds_camera_regs,
+	.num_regulators	= ARRAY_SIZE(mx31_3ds_camera_regs),
+};
+
+static struct platform_device mx31_3ds_ov2640 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_ov2640,
+	},
+};
+
+struct mx3_camera_pdata mx31_3ds_camera_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.flags		= MX3_CAMERA_DATAWIDTH_10,
+	.mclk_10khz	= 2600,
+};
+
+/*
+ * FB support
+ */
+static const struct fb_videomode fb_modedb[] = {
+	{	/* 480x640 @ 60 Hz */
+		.name		= "Epson-VGA",
+		.refresh	= 60,
+		.xres		= 480,
+		.yres		= 640,
+		.pixclock	= 41701,
+		.left_margin	= 20,
+		.right_margin	= 41,
+		.upper_margin	= 10,
+		.lower_margin	= 5,
+		.hsync_len	= 20,
+		.vsync_len	= 10,
+		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	},
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "Epson-VGA",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+/* LCD */
+static struct l4f00242t03_pdata mx31_3ds_l4f00242t03_pdata = {
+	.reset_gpio		= IOMUX_TO_GPIO(MX31_PIN_LCS1),
+	.data_enable_gpio	= IOMUX_TO_GPIO(MX31_PIN_SER_RS),
+	.core_supply		= "lcd_2v8",
+	.io_supply		= "vdd_lcdio",
+};
+
+/*
+ * Support for SD card slot in personality board
+ */
+#define MX31_3DS_GPIO_SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)
+#define MX31_3DS_GPIO_SDHC1_BE IOMUX_TO_GPIO(MX31_PIN_GPIO3_0)
+
+static struct gpio mx31_3ds_sdhc1_gpios[] = {
+	{ MX31_3DS_GPIO_SDHC1_CD, GPIOF_IN, "sdhc1-card-detect" },
+	{ MX31_3DS_GPIO_SDHC1_BE, GPIOF_OUT_INIT_LOW, "sdhc1-bus-en" },
+};
+
+static int mx31_3ds_sdhc1_init(struct device *dev,
+			       irq_handler_t detect_irq,
+			       void *data)
+{
+	int ret;
+
+	ret = gpio_request_array(mx31_3ds_sdhc1_gpios,
+				 ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
+	if (ret) {
+		pr_warning("Unable to request the SD/MMC GPIOs.\n");
+		return ret;
+	}
+
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+			  detect_irq, IRQF_DISABLED |
+			  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			  "sdhc1-detect", data);
+	if (ret) {
+		pr_warning("Unable to request the SD/MMC card-detect IRQ.\n");
+		goto gpio_free;
+	}
+
+	return 0;
+
+gpio_free:
+	gpio_free_array(mx31_3ds_sdhc1_gpios,
+			ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
+	return ret;
+}
+
+static void mx31_3ds_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), data);
+	gpio_free_array(mx31_3ds_sdhc1_gpios,
+			 ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
+}
+
+static void mx31_3ds_sdhc1_setpower(struct device *dev, unsigned int vdd)
+{
+	/*
+	 * While the voltage stuff is done by the driver, activate the
+	 * Buffer Enable Pin only if there is a card in slot to fix the card
+	 * voltage issue caused by bi-directional chip TXB0108 on 3Stack.
+	 * Done here because at this stage we have for sure a debounced value
+	 * of the presence of the card, showed by the value of vdd.
+	 * 7 == ilog2(MMC_VDD_165_195)
+	 */
+	if (vdd > 7)
+		gpio_set_value(MX31_3DS_GPIO_SDHC1_BE, 1);
+	else
+		gpio_set_value(MX31_3DS_GPIO_SDHC1_BE, 0);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.init		= mx31_3ds_sdhc1_init,
+	.exit		= mx31_3ds_sdhc1_exit,
+	.setpower	= mx31_3ds_sdhc1_setpower,
 };
 
 /*
@@ -138,7 +394,71 @@ static struct regulator_init_data gpo_init = {
 	}
 };
 
-static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
+static struct regulator_consumer_supply vmmc2_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "mxc-mmc.0"),
+};
+
+static struct regulator_init_data vmmc2_init = {
+	.constraints = {
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vmmc2_consumers),
+	.consumer_supplies = vmmc2_consumers,
+};
+
+static struct regulator_consumer_supply vmmc1_consumers[] = {
+	REGULATOR_SUPPLY("lcd_2v8", NULL),
+	REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
+};
+
+static struct regulator_init_data vmmc1_init = {
+	.constraints = {
+		.min_uV = 2800000,
+		.max_uV = 2800000,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vmmc1_consumers),
+	.consumer_supplies = vmmc1_consumers,
+};
+
+static struct regulator_consumer_supply vgen_consumers[] = {
+	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+};
+
+static struct regulator_init_data vgen_init = {
+	.constraints = {
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vgen_consumers),
+	.consumer_supplies = vgen_consumers,
+};
+
+static struct regulator_consumer_supply vvib_consumers[] = {
+	REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
+};
+
+static struct regulator_init_data vvib_init = {
+	.constraints = {
+		.min_uV = 1300000,
+		.max_uV = 1300000,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vvib_consumers),
+	.consumer_supplies = vvib_consumers,
+};
+
+static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
 	{
 		.id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
 		.init_data = &pwgtx_init,
@@ -152,17 +472,38 @@ static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
 	}, {
 		.id = MC13783_REG_GPO3, /* Turn on 3.3V */
 		.init_data = &gpo_init,
+	}, {
+		.id = MC13783_REG_VMMC2, /* Power MMC/SD, WiFi/Bluetooth. */
+		.init_data = &vmmc2_init,
+	}, {
+		.id = MC13783_REG_VMMC1, /* Power LCD, CMOS, FM, GPS, Accel. */
+		.init_data = &vmmc1_init,
+	}, {
+		.id = MC13783_REG_VGEN,  /* Power LCD */
+		.init_data = &vgen_init,
+	}, {
+		.id = MC13783_REG_VVIB,  /* Power CMOS */
+		.init_data = &vvib_init,
 	},
 };
 
 /* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
 	.regulators = mx31_3ds_regulators,
 	.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
-	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
+	.flags  = MC13XXX_USE_REGULATOR | MC13XXX_USE_TOUCHSCREEN
 };
 
 /* SPI */
+static int spi0_internal_chipselect[] = {
+	MXC_SPI_CS(2),
+};
+
+static const struct spi_imx_master spi0_pdata __initconst = {
+	.chipselect	= spi0_internal_chipselect,
+	.num_chipselect	= ARRAY_SIZE(spi0_internal_chipselect),
+};
+
 static int spi1_internal_chipselect[] = {
 	MXC_SPI_CS(0),
 	MXC_SPI_CS(2),
@@ -182,6 +523,12 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
 		.platform_data	= &mc13783_pdata,
 		.irq		= IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
 		.mode = SPI_CS_HIGH,
+	}, {
+		.modalias	= "l4f00242t03",
+		.max_speed_hz	= 5000000,
+		.bus_num	= 0,
+		.chip_select	= 0, /* SS2 */
+		.platform_data	= &mx31_3ds_l4f00242t03_pdata,
 	},
 };
 
@@ -245,6 +592,11 @@ usbotg_free_reset:
 	return err;
 }
 
+static int mx31_3ds_otg_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
+
 static int mx31_3ds_host2_init(struct platform_device *pdev)
 {
 	int err;
@@ -276,25 +628,25 @@ static int mx31_3ds_host2_init(struct platform_device *pdev)
 
 	mdelay(1);
 	gpio_set_value(USBH2_RST_B, 1);
-	return 0;
+
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
 
 usbotg_free_reset:
 	gpio_free(USBH2_RST_B);
 	return err;
 }
 
-#if defined(CONFIG_USB_ULPI)
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= mx31_3ds_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init = mx31_3ds_host2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
-#endif
 
 static const struct fsl_usb2_platform_data usbotg_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -320,19 +672,18 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-/*
- * Set up static virtual mappings.
- */
-static void __init mx31_3ds_map_io(void)
-{
-	mx31_map_io();
-}
+static const struct imxi2c_platform_data mx31_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
 
-/*!
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
+static struct platform_device *devices[] __initdata = {
+	&mx31_3ds_ov2640,
+};
+
+static void __init mx31_3ds_init(void)
 {
+	int ret;
+
 	mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
 				      "mx31_3ds");
 
@@ -343,20 +694,22 @@ static void __init mxc_board_init(void)
 	spi_register_board_info(mx31_3ds_spi_devs,
 						ARRAY_SIZE(mx31_3ds_spi_devs));
 
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
 	imx31_add_imx_keypad(&mx31_3ds_keymap_data);
 
 	mx31_3ds_usbotg_init();
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx31_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx31_add_mxc_ehci_otg(&otg_pdata);
 	}
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+
 	if (!otg_mode_host)
 		imx31_add_fsl_usb2_udc(&usbotg_pdata);
 
@@ -364,6 +717,26 @@ static void __init mxc_board_init(void)
 		printk(KERN_WARNING "Init of the debug board failed, all "
 				    "devices on the debug board are unusable.\n");
 	imx31_add_imx2_wdt(NULL);
+	imx31_add_imx_i2c0(&mx31_3ds_i2c0_data);
+	imx31_add_mxc_mmc(0, &sdhc1_pdata);
+
+	imx31_add_spi_imx0(&spi0_pdata);
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	/* CSI */
+	/* Camera power: default - off */
+	ret = gpio_request_array(mx31_3ds_camera_gpios,
+				 ARRAY_SIZE(mx31_3ds_camera_gpios));
+	if (ret) {
+		pr_err("Failed to request camera gpios");
+		iclink_ov2640.power = NULL;
+	}
+
+	if (!mx31_3ds_camera_alloc_dma())
+		mxc_register_device(&mx3_camera, &mx31_3ds_camera_pdata);
+	else
+		pr_err("Failed to allocate dma memory for camera");
 }
 
 static void __init mx31_3ds_timer_init(void)
@@ -375,15 +748,22 @@ static struct sys_timer mx31_3ds_timer = {
 	.init	= mx31_3ds_timer_init,
 };
 
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_MX31_3DS data structure.
- */
+static void __init mx31_3ds_reserve(void)
+{
+	/* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
+	mx3_camera_base = memblock_alloc(MX31_3DS_CAMERA_BUF_SIZE,
+					 MX31_3DS_CAMERA_BUF_SIZE);
+	memblock_free(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
+	memblock_remove(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
+}
+
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_3ds_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31_3ds_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31_3ds_timer,
+	.init_machine = mx31_3ds_init,
+	.reserve = mx31_3ds_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31ads.c b/arch/arm/mach-mx3/mach-mx31ads.c
index 88b97d6..4e4b780 100644
--- a/arch/arm/mach-mx3/mach-mx31ads.c
+++ b/arch/arm/mach-mx3/mach-mx31ads.c
@@ -69,12 +69,8 @@
 #define EXPIO_INT_XUART_INTB	(MXC_EXP_IO_BASE + 11)
 
 #define MXC_MAX_EXP_IO_LINES	16
-/*
- * This file contains the board-specific initialization routines.
- */
 
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-/*!
+/*
  * The serial port definition structure.
  */
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -110,14 +106,7 @@ static int __init mxc_init_extuart(void)
 {
 	return platform_device_register(&serial_device);
 }
-#else
-static inline int mxc_init_extuart(void)
-{
-	return 0;
-}
-#endif
 
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -134,11 +123,6 @@ static inline void mxc_init_imx_uart(void)
 	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
 	imx31_add_imx_uart0(&uart_pdata);
 }
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* !SERIAL_IMX */
 
 static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
 {
@@ -160,7 +144,7 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
 
 /*
  * Disable an expio pin's interrupt by setting the bit in the imr.
- * @param irq           an expio virtual irq number
+ * @param d	an expio virtual irq description
  */
 static void expio_mask_irq(struct irq_data *d)
 {
@@ -172,7 +156,7 @@ static void expio_mask_irq(struct irq_data *d)
 
 /*
  * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
- * @param irq           an expanded io virtual irq number
+ * @param d	an expio virtual irq description
  */
 static void expio_ack_irq(struct irq_data *d)
 {
@@ -183,7 +167,7 @@ static void expio_ack_irq(struct irq_data *d)
 
 /*
  * Enable a expio pin's interrupt by clearing the bit in the imr.
- * @param irq           a expio virtual irq number
+ * @param d	an expio virtual irq description
  */
 static void expio_unmask_irq(struct irq_data *d)
 {
@@ -476,7 +460,6 @@ static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
 };
 #endif
 
-#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
 static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
 	{
@@ -497,11 +480,6 @@ static void mxc_init_i2c(void)
 
 	imx31_add_imx_i2c1(NULL);
 }
-#else
-static void mxc_init_i2c(void)
-{
-}
-#endif
 
 static unsigned int ssi_pins[] = {
 	MX31_PIN_SFS5__SFS5,
@@ -516,9 +494,7 @@ static void mxc_init_audio(void)
 	mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
 }
 
-/*!
- * This structure defines static mappings for the i.MX31ADS board.
- */
+/* static mappings */
 static struct map_desc mx31ads_io_desc[] __initdata = {
 	{
 		.virtual	= MX31_CS4_BASE_ADDR_VIRT,
@@ -528,9 +504,6 @@ static struct map_desc mx31ads_io_desc[] __initdata = {
 	},
 };
 
-/*!
- * Set up static virtual mappings.
- */
 static void __init mx31ads_map_io(void)
 {
 	mx31_map_io();
@@ -543,10 +516,7 @@ static void __init mx31ads_init_irq(void)
 	mx31ads_init_expio();
 }
 
-/*!
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
+static void __init mx31ads_init(void)
 {
 	mxc_init_extuart();
 	mxc_init_imx_uart();
@@ -563,15 +533,12 @@ static struct sys_timer mx31ads_timer = {
 	.init	= mx31ads_timer_init,
 };
 
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_MX31ADS data structure.
- */
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31ads_map_io,
-	.init_irq       = mx31ads_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31ads_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31ads_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31ads_init_irq,
+	.timer = &mx31ads_timer,
+	.init_machine = mx31ads_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31lilly.c b/arch/arm/mach-mx3/mach-mx31lilly.c
index 2c59548..ed95745 100644
--- a/arch/arm/mach-mx3/mach-mx31lilly.c
+++ b/arch/arm/mach-mx3/mach-mx31lilly.c
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
@@ -110,55 +111,9 @@ static struct platform_device physmap_flash_device = {
 
 /* USB */
 
-#if defined(CONFIG_USB_ULPI)
-
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
-static int usbotg_init(struct platform_device *pdev)
-{
-	unsigned int pins[] = {
-		MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
-		MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
-		MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
-		MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
-		MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
-		MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
-		MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
-		MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
-		MX31_PIN_USBOTG_CLK__USBOTG_CLK,
-		MX31_PIN_USBOTG_DIR__USBOTG_DIR,
-		MX31_PIN_USBOTG_NXT__USBOTG_NXT,
-		MX31_PIN_USBOTG_STP__USBOTG_STP,
-	};
-
-	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB OTG");
-
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG);
-
-	mxc_iomux_set_gpr(MUX_PGP_USB_4WIRE, true);
-	mxc_iomux_set_gpr(MUX_PGP_USB_COMMON, true);
-
-	/* chip select */
-	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE2, IOMUX_CONFIG_GPIO),
-				"USBOTG_CS");
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), "USBH1 CS");
-	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), 0);
-
-	return 0;
-}
-
 static int usbh1_init(struct platform_device *pdev)
 {
 	int pins[] = {
@@ -183,7 +138,10 @@ static int usbh1_init(struct platform_device *pdev)
 
 	mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_SINGLE_UNI);
 }
 
 static int usbh2_init(struct platform_device *pdev)
@@ -220,41 +178,30 @@ static int usbh2_init(struct platform_device *pdev)
 	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
 	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
 
-	return 0;
-}
+	mdelay(10);
 
-static struct mxc_usbh_platform_data usbotg_pdata = {
-	.init	= usbotg_init,
-	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
-};
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
 
 static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
 	.init	= usbh1_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static void lilly1131_usb_init(void)
 {
-	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
 	imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-}
 
-#else
-static inline void lilly1131_usb_init(void) {}
-#endif /* CONFIG_USB_ULPI */
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+}
 
 /* SPI */
 
@@ -274,8 +221,8 @@ static const struct spi_imx_master spi1_pdata __initconst = {
 	.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
 };
 
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.flags = MC13783_USE_RTC | MC13783_USE_TOUCHSCREEN,
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
+	.flags = MC13XXX_USE_RTC | MC13XXX_USE_TOUCHSCREEN,
 };
 
 static struct spi_board_info mc13783_dev __initdata = {
@@ -347,10 +294,10 @@ static struct sys_timer mx31lilly_timer = {
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
-	.map_io		= mx31_map_io,
-	.init_irq	= mx31_init_irq,
-	.init_machine	= mx31lilly_board_init,
-	.timer		= &mx31lilly_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31lilly_timer,
+	.init_machine = mx31lilly_board_init,
 MACHINE_END
-
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index 9e64c66..24a21a3 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -27,6 +27,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/mtd/physmap.h>
+#include <linux/delay.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -111,9 +112,9 @@ static const struct spi_imx_master spi1_pdata __initconst = {
 	.num_chipselect	= ARRAY_SIZE(spi_internal_chipselect),
 };
 
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.flags  = MC13783_USE_RTC |
-		  MC13783_USE_REGULATOR,
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
+	.flags  = MC13XXX_USE_RTC |
+		  MC13XXX_USE_REGULATOR,
 };
 
 static struct spi_board_info mc13783_spi_dev __initdata = {
@@ -129,7 +130,6 @@ static struct spi_board_info mc13783_spi_dev __initdata = {
  * USB
  */
 
-#if defined(CONFIG_USB_ULPI)
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
@@ -167,15 +167,15 @@ static int usbh2_init(struct platform_device *pdev)
 	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
 	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
 }
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init   = usbh2_init,
 	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags  = MXC_EHCI_POWER_PINS_ENABLED,
 };
-#endif
 
 /*
  * NOR flash
@@ -227,7 +227,7 @@ void __init mx31lite_map_io(void)
 static int mx31lite_baseboard;
 core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444);
 
-static void __init mxc_board_init(void)
+static void __init mx31lite_init(void)
 {
 	int ret;
 
@@ -252,13 +252,11 @@ static void __init mxc_board_init(void)
 	imx31_add_spi_imx1(&spi1_pdata);
 	spi_register_board_info(&mc13783_spi_dev, 1);
 
-#if defined(CONFIG_USB_ULPI)
 	/* USB */
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 	/* SMSC9117 IRQ pin */
 	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
@@ -281,9 +279,10 @@ struct sys_timer mx31lite_timer = {
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31lite_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31lite_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31lite_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31lite_timer,
+	.init_machine = mx31lite_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index 1aa8d65..6f3692b 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -214,7 +214,7 @@ static struct regulator_init_data cam_vreg_data = {
 	.consumer_supplies = cam_consumers,
 };
 
-static struct mc13783_regulator_init_data moboard_regulators[] = {
+static struct mc13xxx_regulator_init_data moboard_regulators[] = {
 	{
 		.id = MC13783_REG_VMMC1,
 		.init_data = &sdhc_vreg_data,
@@ -267,12 +267,12 @@ static struct mc13783_leds_platform_data moboard_leds = {
 	.tc2_period = MC13783_LED_PERIOD_10MS,
 };
 
-static struct mc13783_platform_data moboard_pmic = {
+static struct mc13xxx_platform_data moboard_pmic = {
 	.regulators = moboard_regulators,
 	.num_regulators = ARRAY_SIZE(moboard_regulators),
 	.leds = &moboard_leds,
-	.flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
-		MC13783_USE_ADC | MC13783_USE_LED,
+	.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
+		MC13XXX_USE_ADC | MC13XXX_USE_LED,
 };
 
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
@@ -400,19 +400,24 @@ static void usb_xcvr_reset(void)
 	mdelay(1);
 }
 
-#if defined(CONFIG_USB_ULPI)
+static int moboard_usbh2_init_hw(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init	= moboard_usbh2_init_hw,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static int __init moboard_usbh2_init(void)
 {
 	struct platform_device *pdev;
 
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (!usbh2_pdata.otg)
+		return -ENODEV;
 
 	pdev = imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 	if (IS_ERR(pdev))
@@ -420,10 +425,6 @@ static int __init moboard_usbh2_init(void)
 
 	return 0;
 }
-#else
-static inline int moboard_usbh2_init(void) { return 0; }
-#endif
-
 
 static struct gpio_led mx31moboard_leds[] = {
 	{
@@ -503,7 +504,7 @@ core_param(mx31moboard_baseboard, mx31moboard_baseboard, int, 0444);
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx31moboard_init(void)
 {
 	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
 		"moboard");
@@ -564,10 +565,10 @@ struct sys_timer mx31moboard_timer = {
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
 	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31moboard_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31moboard_timer,
+	.init_machine = mx31moboard_init,
 MACHINE_END
-
diff --git a/arch/arm/mach-mx3/mach-mx35_3ds.c b/arch/arm/mach-mx3/mach-mx35_3ds.c
index b1963f2..ff5fe23 100644
--- a/arch/arm/mach-mx3/mach-mx35_3ds.c
+++ b/arch/arm/mach-mx3/mach-mx35_3ds.c
@@ -118,24 +118,42 @@ static iomux_v3_cfg_t mx35pdk_pads[] = {
 	MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
 	MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
 	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* I2C1 */
+	MX35_PAD_I2C1_CLK__I2C1_SCL,
+	MX35_PAD_I2C1_DAT__I2C1_SDA,
 };
 
+static int mx35_3ds_otg_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
 /* OTG config */
 static const struct fsl_usb2_platform_data usb_otg_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
+/*
+ * ENGCM09152 also requires a hardware change.
+ * Please check the MX35 Chip Errata document for details.
+ */
 };
 
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= mx35_3ds_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
+static int mx35_3ds_usbh_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			  MXC_EHCI_INTERNAL_PHY);
+}
+
 /* USB HOST config */
 static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
+	.init		= mx35_3ds_usbh_init,
 	.portsc		= MXC_EHCI_MODE_SERIAL,
-	.flags		= MXC_EHCI_INTERFACE_SINGLE_UNI |
-			  MXC_EHCI_INTERNAL_PHY,
 };
 
 static int otg_mode_host;
@@ -153,10 +171,14 @@ static int __init mx35_3ds_otg_mode(char *options)
 }
 __setup("otg_mode=", mx35_3ds_otg_mode);
 
+static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
+
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx35_3ds_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
@@ -180,6 +202,7 @@ static void __init mxc_board_init(void)
 	if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		pr_warn("Init of the debugboard failed, all "
 				"devices on the debugboard are unusable.\n");
+	imx35_add_imx_i2c0(&mx35_3ds_i2c0_data);
 }
 
 static void __init mx35pdk_timer_init(void)
@@ -193,9 +216,10 @@ struct sys_timer mx35pdk_timer = {
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
 	/* Maintainer: Freescale Semiconductor, Inc */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx35pdk_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &mx35pdk_timer,
+	.init_machine = mx35_3ds_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
index b752f6b..f07d3bd 100644
--- a/arch/arm/mach-mx3/mach-pcm037.c
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -533,17 +533,25 @@ static struct platform_device pcm970_sja1000 = {
 	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
 };
 
-#if defined(CONFIG_USB_ULPI)
+static int pcm037_otg_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= pcm037_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int pcm037_usbh2_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init	= pcm037_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -568,7 +576,7 @@ __setup("otg_mode=", pcm037_otg_mode);
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init pcm037_init(void)
 {
 	int ret;
 
@@ -646,19 +654,18 @@ static void __init mxc_board_init(void)
 
 	platform_device_register(&pcm970_sja1000);
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx31_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx31_add_mxc_ehci_otg(&otg_pdata);
 	}
 
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
 	if (!otg_mode_host)
 		imx31_add_fsl_usb2_udc(&otg_device_pdata);
 
@@ -675,9 +682,10 @@ struct sys_timer pcm037_timer = {
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
 	/* Maintainer: Pengutronix */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &pcm037_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &pcm037_timer,
+	.init_machine = pcm037_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-pcm037_eet.c b/arch/arm/mach-mx3/mach-pcm037_eet.c
index fda5654..df6fb07 100644
--- a/arch/arm/mach-mx3/mach-pcm037_eet.c
+++ b/arch/arm/mach-mx3/mach-pcm037_eet.c
@@ -180,9 +180,7 @@ static int __init eet_init_devices(void)
 
 	/* SPI */
 	spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	imx31_add_spi_imx0(&pcm037_spi1_pdata);
-#endif
 
 	platform_device_register(&pcm037_gpio_keys_device);
 
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index bcf83fc..b3ecfb2 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -115,7 +115,6 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
 static const struct imxi2c_platform_data pcm043_i2c0_data __initconst = {
 	.bitrate = 50000,
 };
@@ -134,7 +133,6 @@ static struct i2c_board_info pcm043_i2c_devices[] = {
 		I2C_BOARD_INFO("pcf8563", 0x51),
 	}
 };
-#endif
 
 static struct platform_device *devices[] __initdata = {
 	&pcm043_flash,
@@ -221,9 +219,9 @@ static iomux_v3_cfg_t pcm043_pads[] = {
 	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
 };
 
-#define AC97_GPIO_TXFS	(1 * 32 + 31)
-#define AC97_GPIO_TXD	(1 * 32 + 28)
-#define AC97_GPIO_RESET	(1 * 32 + 0)
+#define AC97_GPIO_TXFS	IMX_GPIO_NR(2, 31)
+#define AC97_GPIO_TXD	IMX_GPIO_NR(2, 28)
+#define AC97_GPIO_RESET	IMX_GPIO_NR(2, 0)
 
 static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97)
 {
@@ -307,18 +305,26 @@ pcm037_nand_board_info __initconst = {
 	.hw_ecc = 1,
 };
 
-#if defined(CONFIG_USB_ULPI)
+static int pcm043_otg_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= pcm043_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int pcm043_usbh1_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
+}
+
 static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
+	.init	= pcm043_usbh1_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -343,7 +349,7 @@ __setup("otg_mode=", pcm043_otg_mode);
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init pcm043_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
 
@@ -369,26 +375,22 @@ static void __init mxc_board_init(void)
 
 	imx35_add_imx_uart1(&uart_pdata);
 
-#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
 	i2c_register_board_info(0, pcm043_i2c_devices,
 			ARRAY_SIZE(pcm043_i2c_devices));
 
 	imx35_add_imx_i2c0(&pcm043_i2c0_data);
-#endif
 
 	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
 	mxc_register_device(&mx3_fb, &mx3fb_pdata);
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx35_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx35_add_mxc_ehci_otg(&otg_pdata);
 	}
-
 	imx35_add_mxc_ehci_hs(&usbh1_pdata);
-#endif
+
 	if (!otg_mode_host)
 		imx35_add_fsl_usb2_udc(&otg_device_pdata);
 
@@ -407,10 +409,10 @@ struct sys_timer pcm043_timer = {
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	/* Maintainer: Pengutronix */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &pcm043_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &pcm043_timer,
+	.init_machine = pcm043_init,
 MACHINE_END
-
diff --git a/arch/arm/mach-mx3/mach-qong.c b/arch/arm/mach-mx3/mach-qong.c
index fd1050c..17f758b 100644
--- a/arch/arm/mach-mx3/mach-qong.c
+++ b/arch/arm/mach-mx3/mach-qong.c
@@ -54,10 +54,6 @@
 
 #define QONG_FPGA_IRQ		IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
 
-/*
- * This file contains the board-specific initialization routines.
- */
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -247,7 +243,7 @@ static void __init qong_init_fpga(void)
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init qong_init(void)
 {
 	mxc_init_imx_uart();
 	qong_init_nor_mtd();
@@ -263,16 +259,12 @@ static struct sys_timer qong_timer = {
 	.init	= qong_timer_init,
 };
 
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_QONG data structure.
- */
-
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	/* Maintainer: DENX Software Engineering GmbH */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &qong_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &qong_timer,
+	.init_machine = qong_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx3/mach-vpr200.c b/arch/arm/mach-mx3/mach-vpr200.c
new file mode 100644
index 0000000..2cf390f
--- /dev/null
+++ b/arch/arm/mach-mx3/mach-vpr200.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Marc Kleine-Budde, Pengutronix
+ * Copyright 2010 Creative Product Design
+ *
+ * Derived from mx35 3stack.
+ * Original 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 as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/memory.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx35.h>
+#include <mach/irqs.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/mfd/mc13xxx.h>
+#include <linux/gpio_keys.h>
+
+#include "devices-imx35.h"
+#include "devices.h"
+
+#define GPIO_LCDPWR	IMX_GPIO_NR(1, 2)
+#define GPIO_PMIC_INT	IMX_GPIO_NR(2, 0)
+
+#define GPIO_BUTTON1	IMX_GPIO_NR(1, 4)
+#define GPIO_BUTTON2	IMX_GPIO_NR(1, 5)
+#define GPIO_BUTTON3	IMX_GPIO_NR(1, 7)
+#define GPIO_BUTTON4	IMX_GPIO_NR(1, 8)
+#define GPIO_BUTTON5	IMX_GPIO_NR(1, 9)
+#define GPIO_BUTTON6	IMX_GPIO_NR(1, 10)
+#define GPIO_BUTTON7	IMX_GPIO_NR(1, 11)
+#define GPIO_BUTTON8	IMX_GPIO_NR(1, 12)
+
+static const struct fb_videomode fb_modedb[] = {
+	{
+		/* 800x480 @ 60 Hz */
+		.name		= "PT0708048",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= KHZ2PICOS(33260),
+		.left_margin	= 50,
+		.right_margin	= 156,
+		.upper_margin	= 10,
+		.lower_margin	= 10,
+		.hsync_len	= 1,	/* note: DE only display */
+		.vsync_len	= 1,	/* note: DE only display */
+		.sync		= FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 800x480 @ 60 Hz */
+		.name		= "CTP-CLAA070LC0ACW",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= KHZ2PICOS(27000),
+		.left_margin	= 50,
+		.right_margin	= 50,	/* whole line should have 900 clocks */
+		.upper_margin	= 10,
+		.lower_margin	= 10,	/* whole frame should have 500 lines */
+		.hsync_len	= 1,	/* note: DE only display */
+		.vsync_len	= 1,	/* note: DE only display */
+		.sync		= FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}
+};
+
+static struct ipu_platform_data mx3_ipu_data = {
+	.irq_base = MXC_IPU_IRQ_START,
+};
+
+static struct mx3fb_platform_data mx3fb_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.name		= "PT0708048",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+static struct physmap_flash_data vpr200_flash_data = {
+	.width  = 2,
+};
+
+static struct resource vpr200_flash_resource = {
+	.start	= MX35_CS0_BASE_ADDR,
+	.end	= MX35_CS0_BASE_ADDR + SZ_64M - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device vpr200_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &vpr200_flash_data,
+	},
+	.resource = &vpr200_flash_resource,
+	.num_resources = 1,
+};
+
+static const struct mxc_nand_platform_data
+		vpr200_nand_board_info __initconst = {
+	.width = 1,
+	.hw_ecc = 1,
+	.flash_bbt = 1,
+};
+
+#define VPR_KEY_DEBOUNCE	500
+static struct gpio_keys_button vpr200_gpio_keys_table[] = {
+	{KEY_F2, GPIO_BUTTON1, 1, "vpr-keys: F2", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F3, GPIO_BUTTON2, 1, "vpr-keys: F3", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F4, GPIO_BUTTON3, 1, "vpr-keys: F4", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F5, GPIO_BUTTON4, 1, "vpr-keys: F5", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F6, GPIO_BUTTON5, 1, "vpr-keys: F6", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F7, GPIO_BUTTON6, 1, "vpr-keys: F7", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F8, GPIO_BUTTON7, 1, "vpr-keys: F8", 1, VPR_KEY_DEBOUNCE},
+	{KEY_F9, GPIO_BUTTON8, 1, "vpr-keys: F9", 1, VPR_KEY_DEBOUNCE},
+};
+
+static struct gpio_keys_platform_data vpr200_gpio_keys_data = {
+	.buttons = vpr200_gpio_keys_table,
+	.nbuttons = ARRAY_SIZE(vpr200_gpio_keys_table),
+};
+
+static struct platform_device vpr200_device_gpiokeys = {
+	.name = "gpio-keys",
+	.dev = {
+		.platform_data = &vpr200_gpio_keys_data,
+	}
+};
+
+static struct mc13xxx_platform_data vpr200_pmic = {
+	.flags = MC13XXX_USE_ADC | MC13XXX_USE_TOUCHSCREEN,
+};
+
+static const struct imxi2c_platform_data vpr200_i2c0_data __initconst = {
+	.bitrate = 50000,
+};
+
+static struct at24_platform_data vpr200_eeprom = {
+	.byte_len = 2048 / 8,
+	.page_size = 1,
+};
+
+static struct i2c_board_info vpr200_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("at24", 0x50), /* E0=0, E1=0, E2=0 */
+		.platform_data = &vpr200_eeprom,
+	}, {
+		I2C_BOARD_INFO("mc13892", 0x08),
+		.platform_data = &vpr200_pmic,
+		.irq = gpio_to_irq(GPIO_PMIC_INT),
+	}
+};
+
+static iomux_v3_cfg_t vpr200_pads[] = {
+	/* UART1 */
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	/* UART3 */
+	MX35_PAD_ATA_DATA10__UART3_RXD_MUX,
+	MX35_PAD_ATA_DATA11__UART3_TXD_MUX,
+	/* FEC */
+	MX35_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX35_PAD_FEC_RX_CLK__FEC_RX_CLK,
+	MX35_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX35_PAD_FEC_COL__FEC_COL,
+	MX35_PAD_FEC_RDATA0__FEC_RDATA_0,
+	MX35_PAD_FEC_TDATA0__FEC_TDATA_0,
+	MX35_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX35_PAD_FEC_MDC__FEC_MDC,
+	MX35_PAD_FEC_MDIO__FEC_MDIO,
+	MX35_PAD_FEC_TX_ERR__FEC_TX_ERR,
+	MX35_PAD_FEC_RX_ERR__FEC_RX_ERR,
+	MX35_PAD_FEC_CRS__FEC_CRS,
+	MX35_PAD_FEC_RDATA1__FEC_RDATA_1,
+	MX35_PAD_FEC_TDATA1__FEC_TDATA_1,
+	MX35_PAD_FEC_RDATA2__FEC_RDATA_2,
+	MX35_PAD_FEC_TDATA2__FEC_TDATA_2,
+	MX35_PAD_FEC_RDATA3__FEC_RDATA_3,
+	MX35_PAD_FEC_TDATA3__FEC_TDATA_3,
+	/* Display */
+	MX35_PAD_LD0__IPU_DISPB_DAT_0,
+	MX35_PAD_LD1__IPU_DISPB_DAT_1,
+	MX35_PAD_LD2__IPU_DISPB_DAT_2,
+	MX35_PAD_LD3__IPU_DISPB_DAT_3,
+	MX35_PAD_LD4__IPU_DISPB_DAT_4,
+	MX35_PAD_LD5__IPU_DISPB_DAT_5,
+	MX35_PAD_LD6__IPU_DISPB_DAT_6,
+	MX35_PAD_LD7__IPU_DISPB_DAT_7,
+	MX35_PAD_LD8__IPU_DISPB_DAT_8,
+	MX35_PAD_LD9__IPU_DISPB_DAT_9,
+	MX35_PAD_LD10__IPU_DISPB_DAT_10,
+	MX35_PAD_LD11__IPU_DISPB_DAT_11,
+	MX35_PAD_LD12__IPU_DISPB_DAT_12,
+	MX35_PAD_LD13__IPU_DISPB_DAT_13,
+	MX35_PAD_LD14__IPU_DISPB_DAT_14,
+	MX35_PAD_LD15__IPU_DISPB_DAT_15,
+	MX35_PAD_LD16__IPU_DISPB_DAT_16,
+	MX35_PAD_LD17__IPU_DISPB_DAT_17,
+	MX35_PAD_D3_FPSHIFT__IPU_DISPB_D3_CLK,
+	MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
+	MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
+	/* LCD Enable */
+	MX35_PAD_D3_VSYNC__GPIO1_2,
+	/* USBOTG */
+	MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
+	MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
+	/* SDCARD */
+	MX35_PAD_SD1_CMD__ESDHC1_CMD,
+	MX35_PAD_SD1_CLK__ESDHC1_CLK,
+	MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* PMIC */
+	MX35_PAD_GPIO2_0__GPIO2_0,
+	/* GPIO keys */
+	MX35_PAD_SCKR__GPIO1_4,
+	MX35_PAD_COMPARE__GPIO1_5,
+	MX35_PAD_SCKT__GPIO1_7,
+	MX35_PAD_FST__GPIO1_8,
+	MX35_PAD_HCKT__GPIO1_9,
+	MX35_PAD_TX5_RX0__GPIO1_10,
+	MX35_PAD_TX4_RX1__GPIO1_11,
+	MX35_PAD_TX3_RX2__GPIO1_12,
+};
+
+/* USB Device config */
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI,
+	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
+};
+
+/* USB HOST config */
+static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
+	.portsc		= MXC_EHCI_MODE_SERIAL,
+	.flags		= MXC_EHCI_INTERFACE_SINGLE_UNI |
+			  MXC_EHCI_INTERNAL_PHY,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&vpr200_flash,
+	&vpr200_device_gpiokeys,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init vpr200_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
+
+	imx35_add_fec(NULL);
+	imx35_add_imx2_wdt(NULL);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	if (0 != gpio_request(GPIO_LCDPWR, "LCDPWR"))
+		printk(KERN_WARNING "vpr200: Couldn't get LCDPWR gpio\n");
+	else
+		gpio_direction_output(GPIO_LCDPWR, 0);
+
+	if (0 != gpio_request(GPIO_PMIC_INT, "PMIC_INT"))
+		printk(KERN_WARNING "vpr200: Couldn't get PMIC_INT gpio\n");
+	else
+		gpio_direction_input(GPIO_PMIC_INT);
+
+	imx35_add_imx_uart0(NULL);
+	imx35_add_imx_uart2(NULL);
+
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	imx35_add_fsl_usb2_udc(&otg_device_pdata);
+	imx35_add_mxc_ehci_hs(&usb_host_pdata);
+
+	imx35_add_mxc_nand(&vpr200_nand_board_info);
+	imx35_add_sdhci_esdhc_imx(0, NULL);
+
+	i2c_register_board_info(0, vpr200_i2c_devices,
+			ARRAY_SIZE(vpr200_i2c_devices));
+
+	imx35_add_imx_i2c0(&vpr200_i2c0_data);
+}
+
+static void __init vpr200_timer_init(void)
+{
+	mx35_clocks_init();
+}
+
+struct sys_timer vpr200_timer = {
+	.init	= vpr200_timer_init,
+};
+
+MACHINE_START(VPR200, "VPR200")
+	/* Maintainer: Creative Product Design */
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &vpr200_timer,
+	.init_machine = vpr200_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-mx3/mm.c b/arch/arm/mach-mx3/mm.c
index 47118f7..54d7174 100644
--- a/arch/arm/mach-mx3/mm.c
+++ b/arch/arm/mach-mx3/mm.c
@@ -27,14 +27,8 @@
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
-
-/*!
- * @file mm.c
- *
- * @brief This file creates static virtual to physical mappings, common to all MX3 boards.
- *
- * @ingroup Memory
- */
+#include <mach/gpio.h>
+#include <mach/irqs.h>
 
 #ifdef CONFIG_SOC_IMX31
 static struct map_desc mx31_io_desc[] __initdata = {
@@ -52,17 +46,25 @@ static struct map_desc mx31_io_desc[] __initdata = {
  */
 void __init mx31_map_io(void)
 {
+	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
+}
+
+void __init imx31_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX31);
 	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-
-	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
 }
 
-int imx31_register_gpios(void);
+static struct mxc_gpio_port imx31_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
+};
+
 void __init mx31_init_irq(void)
 {
 	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-	imx31_register_gpios();
+	mxc_gpio_init(imx31_gpio_ports,	ARRAY_SIZE(imx31_gpio_ports));
 }
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
@@ -77,18 +79,26 @@ static struct map_desc mx35_io_desc[] __initdata = {
 
 void __init mx35_map_io(void)
 {
+	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx35_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX35);
 	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-
-	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
 }
 
-int imx35_register_gpios(void);
+static struct mxc_gpio_port imx35_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
+};
+
 void __init mx35_init_irq(void)
 {
 	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-	imx35_register_gpios();
+	mxc_gpio_init(imx35_gpio_ports,	ARRAY_SIZE(imx35_gpio_ports));
 }
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
@@ -129,4 +139,3 @@ static int mxc_init_l2x0(void)
 
 arch_initcall(mxc_init_l2x0);
 #endif
-
diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c
index 94a0b9e..6410b9c 100644
--- a/arch/arm/mach-mx3/mx31moboard-devboard.c
+++ b/arch/arm/mach-mx3/mx31moboard-devboard.c
@@ -15,6 +15,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
@@ -149,7 +150,10 @@ static int devboard_usbh1_hw_init(struct platform_device *pdev)
 	mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
 	mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_SINGLE_UNI);
 }
 
 #define USBH1_VBUSEN_B	IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
@@ -187,7 +191,6 @@ static int devboard_isp1105_set_vbus(struct otg_transceiver *otg, bool on)
 static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 	.init	= devboard_usbh1_hw_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
 static int __init devboard_usbh1_init(void)
diff --git a/arch/arm/mach-mx3/mx31moboard-marxbot.c b/arch/arm/mach-mx3/mx31moboard-marxbot.c
index f449a97..57f7b00 100644
--- a/arch/arm/mach-mx3/mx31moboard-marxbot.c
+++ b/arch/arm/mach-mx3/mx31moboard-marxbot.c
@@ -265,7 +265,10 @@ static int marxbot_usbh1_hw_init(struct platform_device *pdev)
 	mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
 	mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_SINGLE_UNI);
 }
 
 #define USBH1_VBUSEN_B	IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
@@ -303,7 +306,6 @@ static int marxbot_isp1105_set_vbus(struct otg_transceiver *otg, bool on)
 static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 	.init	= marxbot_usbh1_hw_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
 static int __init marxbot_usbh1_init(void)
diff --git a/arch/arm/mach-mx3/mx31moboard-smartbot.c b/arch/arm/mach-mx3/mx31moboard-smartbot.c
index bbec3c8..35f806e 100644
--- a/arch/arm/mach-mx3/mx31moboard-smartbot.c
+++ b/arch/arm/mach-mx3/mx31moboard-smartbot.c
@@ -123,17 +123,24 @@ static const struct fsl_usb2_platform_data usb_pdata __initconst = {
 
 #if defined(CONFIG_USB_ULPI)
 
+static int smartbot_otg_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
+
 static struct mxc_usbh_platform_data otg_host_pdata __initdata = {
+	.init	= smartbot_otg_init,
 	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static int __init smartbot_otg_host_init(void)
 {
 	struct platform_device *pdev;
 
-	otg_host_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	otg_host_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+		ULPI_OTG_DRVVBUS_EXT);
+	if (!otg_host_pdata.otg)
+		return -ENODEV;
 
 	pdev = imx31_add_mxc_ehci_otg(&otg_host_pdata);
 	if (IS_ERR(pdev))
diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index de4fa992f..83ee088 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -1,5 +1,6 @@
 if ARCH_MX5
-# ARCH_MX51 and ARCH_MX50 are left for compatibility
+# ARCH_MX50/51/53 are left to mark places where prevent multi-soc in single
+# image. So for most time, SOC_IMX50/51/53 should be used.
 
 config ARCH_MX50
 	bool
@@ -50,6 +51,7 @@ config MACH_MX51_BABBAGE
 config MACH_MX51_3DS
 	bool "Support MX51PDK (3DS)"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
@@ -112,19 +114,32 @@ config MACH_EUKREA_MBIMXSD51_BASEBOARD
 
 endchoice
 
-config MACH_MX51_EFIKAMX
-	bool "Support MX51 Genesi Efika MX nettop"
+config MX51_EFIKA_COMMON
+	bool
 	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select MXC_ULPI if USB_ULPI
+
+config MACH_MX51_EFIKAMX
+	bool "Support MX51 Genesi Efika MX nettop"
+	select MX51_EFIKA_COMMON
 	help
 	  Include support for Genesi Efika MX nettop. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MX51_EFIKASB
+	bool "Support MX51 Genesi Efika Smartbook"
+	select MX51_EFIKA_COMMON
+	help
+	  Include support for Genesi Efika Smartbook. This includes specific
+	  configurations for the board and its peripherals.
+
 config MACH_MX53_EVK
 	bool "Support MX53 EVK platforms"
 	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
@@ -136,6 +151,8 @@ config MACH_MX53_EVK
 config MACH_MX53_SMD
 	bool "Support MX53 SMD platforms"
 	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	help
 	  Include support for MX53 SMD platform. This includes specific
@@ -144,7 +161,10 @@ config MACH_MX53_SMD
 config MACH_MX53_LOCO
 	bool "Support MX53 LOCO platforms"
 	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	help
 	  Include support for MX53 LOCO platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -157,6 +177,7 @@ config MACH_MX50_RDP
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select IMX_HAVE_PLATFORM_FEC
 	help
 	  Include support for MX50 reference design platform (RDP) board. This
 	  includes specific configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0d43be9..4f63048 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
@@ -16,5 +16,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX51) += board-cpuimx51.o
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
+obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
diff --git a/arch/arm/mach-mx5/board-cpuimx51.c b/arch/arm/mach-mx5/board-cpuimx51.c
index f8652ef..d0296a9 100644
--- a/arch/arm/mach-mx5/board-cpuimx51.c
+++ b/arch/arm/mach-mx5/board-cpuimx51.c
@@ -60,7 +60,6 @@
 #define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
 #define	MX51_USB_PLL_DIV_24_MHZ		0x02
 
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
@@ -105,12 +104,9 @@ static struct platform_device serial_device = {
 		.platform_data = serial_platform_data,
 	},
 };
-#endif
 
 static struct platform_device *devices[] __initdata = {
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	&serial_device,
-#endif
 };
 
 static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
@@ -188,7 +184,10 @@ static int initialize_otg_port(struct platform_device *pdev)
 	v |= MX51_USB_PLL_DIV_19_2_MHZ;
 	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
 }
 
 static int initialize_usbh1_port(struct platform_device *pdev)
@@ -206,13 +205,16 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
 	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data dr_utmi_config = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static struct fsl_usb2_platform_data usb_pdata = {
@@ -223,7 +225,6 @@ static struct fsl_usb2_platform_data usb_pdata = {
 static struct mxc_usbh_platform_data usbh1_config = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
 };
 
 static int otg_mode_host;
@@ -298,7 +299,8 @@ MACHINE_START(EUKREA_CPUIMX51, "Eukrea CPUIMX51 Module")
 	/* Maintainer: Eric BĂŠnard <eric@eukrea.com> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = eukrea_cpuimx51_init,
 	.timer = &mxc_timer,
+	.init_machine = eukrea_cpuimx51_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-cpuimx51sd.c b/arch/arm/mach-mx5/board-cpuimx51sd.c
index ad93189..29b1808 100644
--- a/arch/arm/mach-mx5/board-cpuimx51sd.c
+++ b/arch/arm/mach-mx5/board-cpuimx51sd.c
@@ -42,6 +42,7 @@
 
 #include "devices-imx51.h"
 #include "devices.h"
+#include "cpu_op-mx51.h"
 
 #define USBH1_RST		IMX_GPIO_NR(2, 28)
 #define ETH_RST			IMX_GPIO_NR(2, 31)
@@ -109,7 +110,7 @@ static iomux_v3_cfg_t eukrea_cpuimx51sd_pads[] = {
 
 	/* Touchscreen */
 	/* IRQ */
-	_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
@@ -118,15 +119,9 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static int ts_get_pendown_state(void)
-{
-	return gpio_get_value(TSC2007_IRQGPIO) ? 0 : 1;
-}
-
 static struct tsc2007_platform_data tsc2007_info = {
 	.model			= 2007,
 	.x_plate_ohms		= 180,
-	.get_pendown_state	= ts_get_pendown_state,
 };
 
 static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
@@ -167,7 +162,10 @@ static int initialize_otg_port(struct platform_device *pdev)
 	v |= MX51_USB_PLL_DIV_19_2_MHZ;
 	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
 }
 
 static int initialize_usbh1_port(struct platform_device *pdev)
@@ -186,13 +184,16 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
 			usbother_base + MX51_USB_CTRL_1_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data dr_utmi_config = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static struct fsl_usb2_platform_data usb_pdata = {
@@ -203,7 +204,6 @@ static struct fsl_usb2_platform_data usb_pdata = {
 static struct mxc_usbh_platform_data usbh1_config = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
 };
 
 static int otg_mode_host;
@@ -242,7 +242,7 @@ static struct mcp251x_platform_data mcp251x_info = {
 static struct spi_board_info cpuimx51sd_spi_device[] = {
 	{
 		.modalias        = "mcp2515",
-		.max_speed_hz    = 6500000,
+		.max_speed_hz    = 10000000,
 		.bus_num         = 0,
 		.mode		= SPI_MODE_0,
 		.chip_select     = 0,
@@ -269,6 +269,10 @@ 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);
 
@@ -329,7 +333,8 @@ MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
 	/* Maintainer: Eric BĂŠnard <eric@eukrea.com> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = eukrea_cpuimx51sd_init,
 	.timer = &mxc_timer,
+	.init_machine = eukrea_cpuimx51sd_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx50_rdp.c b/arch/arm/mach-mx5/board-mx50_rdp.c
index fd32e4c..dedf7f2 100644
--- a/arch/arm/mach-mx5/board-mx50_rdp.c
+++ b/arch/arm/mach-mx5/board-mx50_rdp.c
@@ -35,7 +35,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include "devices-mx50.h"
+#include "devices-imx50.h"
+
+#define FEC_EN		IMX_GPIO_NR(6, 23)
+#define FEC_RESET_B	IMX_GPIO_NR(4, 12)
 
 static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
 	/* SD1 */
@@ -102,7 +105,7 @@ static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
 	MX50_PAD_I2C3_SCL__USBOTG_OC,
 
 	MX50_PAD_SSI_RXC__FEC_MDIO,
-	MX50_PAD_SSI_RXC__FEC_MDIO,
+	MX50_PAD_SSI_RXFS__FEC_MDC,
 	MX50_PAD_DISP_D0__FEC_TXCLK,
 	MX50_PAD_DISP_D1__FEC_RX_ER,
 	MX50_PAD_DISP_D2__FEC_RX_DV,
@@ -111,7 +114,6 @@ static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
 	MX50_PAD_DISP_D5__FEC_TX_EN,
 	MX50_PAD_DISP_D6__FEC_TXD1,
 	MX50_PAD_DISP_D7__FEC_TXD0,
-	MX50_PAD_SSI_RXFS__FEC_MDC,
 	MX50_PAD_I2C3_SDA__GPIO_6_23,
 	MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
 
@@ -168,6 +170,24 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
+static const struct fec_platform_data fec_data __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static inline void mx50_rdp_fec_reset(void)
+{
+	gpio_request(FEC_EN, "fec-en");
+	gpio_direction_output(FEC_EN, 0);
+	gpio_request(FEC_RESET_B, "fec-reset_b");
+	gpio_direction_output(FEC_RESET_B, 0);
+	msleep(1);
+	gpio_set_value(FEC_RESET_B, 1);
+}
+
+static const struct imxi2c_platform_data i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
 /*
  * Board specific initialization.
  */
@@ -178,6 +198,11 @@ static void __init mx50_rdp_board_init(void)
 
 	imx50_add_imx_uart(0, &uart_pdata);
 	imx50_add_imx_uart(1, &uart_pdata);
+	mx50_rdp_fec_reset();
+	imx50_add_fec(&fec_data);
+	imx50_add_imx_i2c(0, &i2c_data);
+	imx50_add_imx_i2c(1, &i2c_data);
+	imx50_add_imx_i2c(2, &i2c_data);
 }
 
 static void __init mx50_rdp_timer_init(void)
@@ -191,7 +216,8 @@ static struct sys_timer mx50_rdp_timer = {
 
 MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
 	.map_io = mx50_map_io,
+	.init_early = imx50_init_early,
 	.init_irq = mx50_init_irq,
-	.init_machine = mx50_rdp_board_init,
 	.timer = &mx50_rdp_timer,
+	.init_machine = mx50_rdp_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_3ds.c b/arch/arm/mach-mx5/board-mx51_3ds.c
index 49d6448..63dfbea 100644
--- a/arch/arm/mach-mx5/board-mx51_3ds.c
+++ b/arch/arm/mach-mx5/board-mx51_3ds.c
@@ -71,24 +71,10 @@ static iomux_v3_cfg_t mx51_3ds_pads[] = {
 };
 
 /* Serial ports */
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static inline void mxc_init_imx_uart(void)
-{
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* SERIAL_IMX */
-
-#if defined(CONFIG_KEYBOARD_IMX) || defined(CONFIG_KEYBOARD_IMX_MODULE)
 static int mx51_3ds_board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(0, 1, KEY_2),
@@ -124,16 +110,6 @@ static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
 	.keymap_size	= ARRAY_SIZE(mx51_3ds_board_keymap),
 };
 
-static void mxc_init_keypad(void)
-{
-	imx51_add_imx_keypad(&mx51_3ds_map_data);
-}
-#else
-static inline void mxc_init_keypad(void)
-{
-}
-#endif
-
 static int mx51_3ds_spi2_cs[] = {
 	MXC_SPI_CS(0),
 	MX51_3DS_ECSPI2_CS,
@@ -157,11 +133,14 @@ static struct spi_board_info mx51_3ds_spi_nor_device[] = {
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx51_3ds_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
 					ARRAY_SIZE(mx51_3ds_pads));
-	mxc_init_imx_uart();
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_imx_uart(1, &uart_pdata);
+	imx51_add_imx_uart(2, &uart_pdata);
 
 	imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
 	spi_register_board_info(mx51_3ds_spi_nor_device,
@@ -172,7 +151,8 @@ static void __init mxc_board_init(void)
 				    "devices on the board are unusable.\n");
 
 	imx51_add_sdhci_esdhc_imx(0, NULL);
-	mxc_init_keypad();
+	imx51_add_imx_keypad(&mx51_3ds_map_data);
+	imx51_add_imx2_wdt(0, NULL);
 }
 
 static void __init mx51_3ds_timer_init(void)
@@ -180,15 +160,16 @@ static void __init mx51_3ds_timer_init(void)
 	mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= mx51_3ds_timer_init,
+static struct sys_timer mx51_3ds_timer = {
+	.init = mx51_3ds_timer_init,
 };
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = mxc_board_init,
-	.timer = &mxc_timer,
+	.timer = &mx51_3ds_timer,
+	.init_machine = mx51_3ds_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index 1d231e8..b2ecd19 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -161,23 +161,10 @@ static iomux_v3_cfg_t mx51babbage_pads[] = {
 };
 
 /* Serial ports */
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static inline void mxc_init_imx_uart(void)
-{
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* SERIAL_IMX */
-
 static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
 	.bitrate = 100000,
 };
@@ -272,7 +259,10 @@ static int initialize_otg_port(struct platform_device *pdev)
 	v |= MX51_USB_PLL_DIV_19_2_MHZ;
 	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
 }
 
 static int initialize_usbh1_port(struct platform_device *pdev)
@@ -290,13 +280,16 @@ static int initialize_usbh1_port(struct platform_device *pdev)
 	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
 	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data dr_utmi_config = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static struct fsl_usb2_platform_data usb_pdata = {
@@ -307,7 +300,6 @@ static struct fsl_usb2_platform_data usb_pdata = {
 static struct mxc_usbh_platform_data usbh1_config = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
 };
 
 static int otg_mode_host;
@@ -349,7 +341,7 @@ static const struct spi_imx_master mx51_babbage_spi_pdata __initconst = {
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx51_babbage_init(void)
 {
 	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
 	iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
@@ -360,7 +352,11 @@ static void __init mxc_board_init(void)
 #endif
 	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
 					ARRAY_SIZE(mx51babbage_pads));
-	mxc_init_imx_uart();
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_imx_uart(1, &uart_pdata);
+	imx51_add_imx_uart(2, &uart_pdata);
+
 	babbage_fec_reset();
 	imx51_add_fec(NULL);
 
@@ -399,15 +395,16 @@ static void __init mx51_babbage_timer_init(void)
 	mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= mx51_babbage_timer_init,
+static struct sys_timer mx51_babbage_timer = {
+	.init = mx51_babbage_timer_init,
 };
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = mxc_board_init,
-	.timer = &mxc_timer,
+	.timer = &mx51_babbage_timer,
+	.init_machine = mx51_babbage_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikamx.c b/arch/arm/mach-mx5/board-mx51_efikamx.c
index b7946f8..acab191 100644
--- a/arch/arm/mach-mx5/board-mx51_efikamx.c
+++ b/arch/arm/mach-mx5/board-mx51_efikamx.c
@@ -25,6 +25,9 @@
 #include <linux/fsl_devices.h>
 #include <linux/spi/flash.h>
 #include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -40,8 +43,7 @@
 
 #include "devices-imx51.h"
 #include "devices.h"
-
-#define	MX51_USB_PLL_DIV_24_MHZ	0x01
+#include "efika.h"
 
 #define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
 #define EFIKAMX_PCBID1		IMX_GPIO_NR(3, 17)
@@ -53,13 +55,14 @@
 
 #define EFIKAMX_POWER_KEY	IMX_GPIO_NR(2, 31)
 
-#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
-#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
-
 /* board 1.1 doesn't have same reset gpio */
 #define EFIKAMX_RESET1_1	IMX_GPIO_NR(3, 2)
 #define EFIKAMX_RESET		IMX_GPIO_NR(1, 4)
 
+#define EFIKAMX_POWEROFF	IMX_GPIO_NR(4, 13)
+
+#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
+
 /* the pci ids pin have pull up. they're driven low according to board id */
 #define MX51_PAD_PCBID0	IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
 #define MX51_PAD_PCBID1	IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
@@ -67,38 +70,11 @@
 #define MX51_PAD_PWRKEY	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
 
 static iomux_v3_cfg_t mx51efikamx_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
 	/* board id */
 	MX51_PAD_PCBID0,
 	MX51_PAD_PCBID1,
 	MX51_PAD_PCBID2,
 
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-
-	/* SD/MMC WP/CD */
-	MX51_PAD_GPIO1_0__SD1_CD,
-	MX51_PAD_GPIO1_1__SD1_WP,
-	MX51_PAD_GPIO1_7__SD2_WP,
-	MX51_PAD_GPIO1_8__SD2_CD,
-
 	/* leds */
 	MX51_PAD_CSI1_D9__GPIO3_13,
 	MX51_PAD_CSI1_VSYNC__GPIO3_14,
@@ -107,64 +83,12 @@ static iomux_v3_cfg_t mx51efikamx_pads[] = {
 	/* power key */
 	MX51_PAD_PWRKEY,
 
-	/* spi */
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,
-	MX51_PAD_CSPI1_SS1__GPIO4_25,
-	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-
 	/* reset */
 	MX51_PAD_DI1_PIN13__GPIO3_2,
 	MX51_PAD_GPIO1_4__GPIO1_4,
-};
 
-/* Serial ports */
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static const struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mxc_init_imx_uart(void)
-{
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* SERIAL_IMX */
-
-/* This function is board specific as the bit mask for the plldiv will also
- * be different for other Freescale SoCs, thus a common bitmask is not
- * possible and cannot get place in /plat-mxc/ehci.c.
- */
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_24_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-	return 0;
-}
-
-static struct mxc_usbh_platform_data dr_utmi_config = {
-	.init   = initialize_otg_port,
-	.portsc = MXC_EHCI_UTMI_16BIT,
-	.flags  = MXC_EHCI_INTERNAL_PHY,
+	/* power off */
+	MX51_PAD_CSI2_VSYNC__GPIO4_13,
 };
 
 /*   PCBID2  PCBID1 PCBID0  STATE
@@ -265,47 +189,6 @@ static const struct gpio_keys_platform_data mx51_efikamx_powerkey_data __initcon
 	.nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
 };
 
-static struct mtd_partition mx51_efikamx_spi_nor_partitions[] = {
-	{
-	 .name = "u-boot",
-	 .offset = 0,
-	 .size = SZ_256K,
-	},
-	{
-	  .name = "config",
-	  .offset = MTDPART_OFS_APPEND,
-	  .size = SZ_64K,
-	},
-};
-
-static struct flash_platform_data mx51_efikamx_spi_flash_data = {
-	.name		= "spi_flash",
-	.parts		= mx51_efikamx_spi_nor_partitions,
-	.nr_parts	= ARRAY_SIZE(mx51_efikamx_spi_nor_partitions),
-	.type		= "sst25vf032b",
-};
-
-static struct spi_board_info mx51_efikamx_spi_board_info[] __initdata = {
-	{
-		.modalias = "m25p80",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.platform_data = &mx51_efikamx_spi_flash_data,
-		.irq = -1,
-	},
-};
-
-static int mx51_efikamx_spi_cs[] = {
-	EFIKAMX_SPI_CS0,
-	EFIKAMX_SPI_CS1,
-};
-
-static const struct spi_imx_master mx51_efikamx_spi_pdata __initconst = {
-	.chipselect     = mx51_efikamx_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx51_efikamx_spi_cs),
-};
-
 void mx51_efikamx_reset(void)
 {
 	if (system_rev == 0x11)
@@ -314,14 +197,53 @@ void mx51_efikamx_reset(void)
 		gpio_direction_output(EFIKAMX_RESET, 0);
 }
 
-static void __init mxc_board_init(void)
+static struct regulator *pwgt1, *pwgt2, *coincell;
+
+static void mx51_efikamx_power_off(void)
+{
+	if (!IS_ERR(coincell))
+		regulator_disable(coincell);
+
+	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+		regulator_disable(pwgt2);
+		regulator_disable(pwgt1);
+	}
+	gpio_direction_output(EFIKAMX_POWEROFF, 1);
+}
+
+static int __init mx51_efikamx_power_init(void)
+{
+	if (machine_is_mx51_efikamx()) {
+		pwgt1 = regulator_get(NULL, "pwgt1");
+		pwgt2 = regulator_get(NULL, "pwgt2");
+		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+			regulator_enable(pwgt1);
+			regulator_enable(pwgt2);
+		}
+		gpio_request(EFIKAMX_POWEROFF, "poweroff");
+		pm_power_off = mx51_efikamx_power_off;
+
+		/* enable coincell charger. maybe need a small power driver ? */
+		coincell = regulator_get(NULL, "coincell");
+		if (!IS_ERR(coincell)) {
+			regulator_set_voltage(coincell, 3000000, 3000000);
+			regulator_enable(coincell);
+		}
+
+		regulator_has_full_constraints();
+	}
+
+	return 0;
+}
+late_initcall(mx51_efikamx_power_init);
+
+static void __init mx51_efikamx_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
 					ARRAY_SIZE(mx51efikamx_pads));
+	efika_board_common_init();
+
 	mx51_efikamx_board_id();
-	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
-	mxc_init_imx_uart();
-	imx51_add_sdhci_esdhc_imx(0, NULL);
 
 	/* on < 1.2 boards both SD controllers are used */
 	if (system_rev < 0x12) {
@@ -332,10 +254,6 @@ static void __init mxc_board_init(void)
 	platform_device_register(&mx51_efikamx_leds_device);
 	imx51_add_gpio_keys(&mx51_efikamx_powerkey_data);
 
-	spi_register_board_info(mx51_efikamx_spi_board_info,
-		ARRAY_SIZE(mx51_efikamx_spi_board_info));
-	imx51_add_ecspi(0, &mx51_efikamx_spi_pdata);
-
 	if (system_rev == 0x11) {
 		gpio_request(EFIKAMX_RESET1_1, "reset");
 		gpio_direction_output(EFIKAMX_RESET1_1, 1);
@@ -343,6 +261,20 @@ static void __init mxc_board_init(void)
 		gpio_request(EFIKAMX_RESET, "reset");
 		gpio_direction_output(EFIKAMX_RESET, 1);
 	}
+
+	/*
+	 * enable wifi by default only on mx
+	 * sb and mx have same wlan pin but the value to enable it are
+	 * different :/
+	 */
+	gpio_request(EFIKA_WLAN_EN, "wlan_en");
+	gpio_direction_output(EFIKA_WLAN_EN, 0);
+	msleep(10);
+
+	gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
+	gpio_direction_output(EFIKA_WLAN_RESET, 0);
+	msleep(10);
+	gpio_set_value(EFIKA_WLAN_RESET, 1);
 }
 
 static void __init mx51_efikamx_timer_init(void)
@@ -350,15 +282,16 @@ static void __init mx51_efikamx_timer_init(void)
 	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= mx51_efikamx_timer_init,
+static struct sys_timer mx51_efikamx_timer = {
+	.init = mx51_efikamx_timer_init,
 };
 
 MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
 	/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine =  mxc_board_init,
-	.timer = &mxc_timer,
+	.timer = &mx51_efikamx_timer,
+	.init_machine = mx51_efikamx_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx51_efikasb.c b/arch/arm/mach-mx5/board-mx51_efikasb.c
new file mode 100644
index 0000000..db04ce8
--- /dev/null
+++ b/arch/arm/mach-mx5/board-mx51_efikasb.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_ehci.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+#include "efika.h"
+
+#define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
+#define EFIKASB_GREEN_LED	IMX_GPIO_NR(1, 3)
+#define EFIKASB_WHITE_LED	IMX_GPIO_NR(2, 25)
+#define EFIKASB_PCBID0		IMX_GPIO_NR(2, 28)
+#define EFIKASB_PCBID1		IMX_GPIO_NR(2, 29)
+#define EFIKASB_PWRKEY		IMX_GPIO_NR(2, 31)
+#define EFIKASB_LID		IMX_GPIO_NR(3, 14)
+#define EFIKASB_POWEROFF	IMX_GPIO_NR(4, 13)
+#define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
+
+#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+
+static iomux_v3_cfg_t mx51efikasb_pads[] = {
+	/* USB HOST2 */
+	MX51_PAD_EIM_D16__USBH2_DATA0,
+	MX51_PAD_EIM_D17__USBH2_DATA1,
+	MX51_PAD_EIM_D18__USBH2_DATA2,
+	MX51_PAD_EIM_D19__USBH2_DATA3,
+	MX51_PAD_EIM_D20__USBH2_DATA4,
+	MX51_PAD_EIM_D21__USBH2_DATA5,
+	MX51_PAD_EIM_D22__USBH2_DATA6,
+	MX51_PAD_EIM_D23__USBH2_DATA7,
+	MX51_PAD_EIM_A24__USBH2_CLK,
+	MX51_PAD_EIM_A25__USBH2_DIR,
+	MX51_PAD_EIM_A26__USBH2_STP,
+	MX51_PAD_EIM_A27__USBH2_NXT,
+
+	/* leds */
+	MX51_PAD_EIM_CS0__GPIO2_25,
+	MX51_PAD_GPIO1_3__GPIO1_3,
+
+	/* pcb id */
+	MX51_PAD_EIM_CS3__GPIO2_28,
+	MX51_PAD_EIM_CS4__GPIO2_29,
+
+	/* lid */
+	MX51_PAD_CSI1_VSYNC__GPIO3_14,
+
+	/* power key*/
+	MX51_PAD_PWRKEY,
+
+	/* wifi/bt button */
+	MX51_PAD_DI1_PIN12__GPIO3_1,
+
+	/* power off */
+	MX51_PAD_CSI2_VSYNC__GPIO4_13,
+
+	/* wdog reset */
+	MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
+
+	/* BT */
+	MX51_PAD_EIM_A17__GPIO2_11,
+};
+
+static int initialize_usbh2_port(struct platform_device *pdev)
+{
+	iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
+	iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
+
+	mxc_iomux_v3_setup_pad(usbh2gpio);
+	gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
+	gpio_direction_output(EFIKASB_USBH2_STP, 0);
+	msleep(1);
+	gpio_set_value(EFIKASB_USBH2_STP, 1);
+	msleep(1);
+
+	gpio_free(EFIKASB_USBH2_STP);
+	mxc_iomux_v3_setup_pad(usbh2stp);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh2_config = {
+	.init   = initialize_usbh2_port,
+	.portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void __init mx51_efikasb_usb(void)
+{
+	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+	if (usbh2_config.otg)
+		mxc_register_device(&mxc_usbh2_device, &usbh2_config);
+}
+
+static struct gpio_led mx51_efikasb_leds[] = {
+	{
+		.name = "efikasb:green",
+		.default_trigger = "default-on",
+		.gpio = EFIKASB_GREEN_LED,
+		.active_low = 1,
+	},
+	{
+		.name = "efikasb:white",
+		.default_trigger = "caps",
+		.gpio = EFIKASB_WHITE_LED,
+	},
+};
+
+static struct gpio_led_platform_data mx51_efikasb_leds_data = {
+	.leds = mx51_efikasb_leds,
+	.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
+};
+
+static struct platform_device mx51_efikasb_leds_device = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &mx51_efikasb_leds_data,
+	},
+};
+
+static struct gpio_keys_button mx51_efikasb_keys[] = {
+	{
+		.code = KEY_POWER,
+		.gpio = EFIKASB_PWRKEY,
+		.type = EV_PWR,
+		.desc = "Power Button",
+		.wakeup = 1,
+		.debounce_interval = 10, /* ms */
+	},
+	{
+		.code = SW_LID,
+		.gpio = EFIKASB_LID,
+		.type = EV_SW,
+		.desc = "Lid Switch",
+	},
+	{
+		/* SW_RFKILLALL vs KEY_RFKILL ? */
+		.code = SW_RFKILL_ALL,
+		.gpio = EFIKASB_RFKILL,
+		.type = EV_SW,
+		.desc = "rfkill",
+	},
+};
+
+static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
+	.buttons = mx51_efikasb_keys,
+	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
+};
+
+static struct regulator *pwgt1, *pwgt2;
+
+static void mx51_efikasb_power_off(void)
+{
+	gpio_set_value(EFIKA_USB_PHY_RESET, 0);
+
+	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+		regulator_disable(pwgt2);
+		regulator_disable(pwgt1);
+	}
+	gpio_direction_output(EFIKASB_POWEROFF, 1);
+}
+
+static int __init mx51_efikasb_power_init(void)
+{
+	if (machine_is_mx51_efikasb()) {
+		pwgt1 = regulator_get(NULL, "pwgt1");
+		pwgt2 = regulator_get(NULL, "pwgt2");
+		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+			regulator_enable(pwgt1);
+			regulator_enable(pwgt2);
+		}
+		gpio_request(EFIKASB_POWEROFF, "poweroff");
+		pm_power_off = mx51_efikasb_power_off;
+
+		regulator_has_full_constraints();
+	}
+
+	return 0;
+}
+late_initcall(mx51_efikasb_power_init);
+
+/* 01     R1.3 board
+   10     R2.0 board */
+static void __init mx51_efikasb_board_id(void)
+{
+	int id;
+
+	gpio_request(EFIKASB_PCBID0, "pcb id0");
+	gpio_direction_input(EFIKASB_PCBID0);
+	gpio_request(EFIKASB_PCBID1, "pcb id1");
+	gpio_direction_input(EFIKASB_PCBID1);
+
+	id = gpio_get_value(EFIKASB_PCBID0);
+	id |= gpio_get_value(EFIKASB_PCBID1) << 1;
+
+	switch (id) {
+	default:
+		break;
+	case 1:
+		system_rev = 0x13;
+		break;
+	case 2:
+		system_rev = 0x20;
+		break;
+	}
+}
+
+static void __init efikasb_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
+					ARRAY_SIZE(mx51efikasb_pads));
+	efika_board_common_init();
+
+	mx51_efikasb_board_id();
+	mx51_efikasb_usb();
+	imx51_add_sdhci_esdhc_imx(1, NULL);
+
+	platform_device_register(&mx51_efikasb_leds_device);
+	imx51_add_gpio_keys(&mx51_efikasb_keys_data);
+
+}
+
+static void __init mx51_efikasb_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikasb_timer = {
+	.init	= mx51_efikasb_timer_init,
+};
+
+MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
+	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.init_machine =  efikasb_board_init,
+	.timer = &mx51_efikasb_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_evk.c b/arch/arm/mach-mx5/board-mx53_evk.c
index caee04c..7b5735c 100644
--- a/arch/arm/mach-mx5/board-mx53_evk.c
+++ b/arch/arm/mach-mx5/board-mx53_evk.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
  */
 
@@ -42,28 +42,24 @@
 #include "devices-imx53.h"
 
 static iomux_v3_cfg_t mx53_evk_pads[] = {
-	MX53_PAD_CSI0_D10__UART1_TXD,
-	MX53_PAD_CSI0_D11__UART1_RXD,
-	MX53_PAD_ATA_DIOW__UART1_TXD,
-	MX53_PAD_ATA_DMACK__UART1_RXD,
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
 
-	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
-	MX53_PAD_ATA_DMARQ__UART2_TXD,
-	MX53_PAD_ATA_DIOR__UART2_RTS,
-	MX53_PAD_ATA_INTRQ__UART2_CTS,
+	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+	MX53_PAD_PATA_DIOR__UART2_RTS,
+	MX53_PAD_PATA_INTRQ__UART2_CTS,
 
-	MX53_PAD_ATA_CS_0__UART3_TXD,
-	MX53_PAD_ATA_CS_1__UART3_RXD,
-	MX53_PAD_ATA_DA_1__UART3_CTS,
-	MX53_PAD_ATA_DA_2__UART3_RTS,
+	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
 
-	MX53_PAD_EIM_D16__CSPI1_SCLK,
-	MX53_PAD_EIM_D17__CSPI1_MISO,
-	MX53_PAD_EIM_D18__CSPI1_MOSI,
+	MX53_PAD_EIM_D16__ECSPI1_SCLK,
+	MX53_PAD_EIM_D17__ECSPI1_MISO,
+	MX53_PAD_EIM_D18__ECSPI1_MOSI,
 
 	/* ecspi chip select lines */
-	MX53_PAD_EIM_EB2__GPIO_2_30,
-	MX53_PAD_EIM_D19__GPIO_3_19,
+	MX53_PAD_EIM_EB2__GPIO2_30,
+	MX53_PAD_EIM_D19__GPIO3_19,
 };
 
 static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
@@ -72,9 +68,9 @@ static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
 
 static inline void mx53_evk_init_uart(void)
 {
-	imx53_add_imx_uart(0, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(0, NULL);
 	imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
-	imx53_add_imx_uart(2, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(2, NULL);
 }
 
 static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
@@ -139,6 +135,7 @@ static void __init mx53_evk_board_init(void)
 	spi_register_board_info(mx53_evk_spi_board_info,
 		ARRAY_SIZE(mx53_evk_spi_board_info));
 	imx53_add_ecspi(0, &mx53_evk_spi_data);
+	imx53_add_imx2_wdt(0, NULL);
 }
 
 static void __init mx53_evk_timer_init(void)
@@ -152,7 +149,8 @@ static struct sys_timer mx53_evk_timer = {
 
 MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
 	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
-	.init_machine = mx53_evk_board_init,
 	.timer = &mx53_evk_timer,
+	.init_machine = mx53_evk_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index d1348e0..0a18f8d 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -39,33 +39,147 @@
 #define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
-	MX53_PAD_CSI0_D10__UART1_TXD,
-	MX53_PAD_CSI0_D11__UART1_RXD,
-	MX53_PAD_ATA_DIOW__UART1_TXD,
-	MX53_PAD_ATA_DMACK__UART1_RXD,
-
-	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
-	MX53_PAD_ATA_DMARQ__UART2_TXD,
-	MX53_PAD_ATA_DIOR__UART2_RTS,
-	MX53_PAD_ATA_INTRQ__UART2_CTS,
-
-	MX53_PAD_ATA_CS_0__UART3_TXD,
-	MX53_PAD_ATA_CS_1__UART3_RXD,
-	MX53_PAD_ATA_DA_1__UART3_CTS,
-	MX53_PAD_ATA_DA_2__UART3_RTS,
+	/* FEC */
+	MX53_PAD_FEC_MDC__FEC_MDC,
+	MX53_PAD_FEC_MDIO__FEC_MDIO,
+	MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
+	MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+	MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
+	MX53_PAD_FEC_RXD1__FEC_RDATA_1,
+	MX53_PAD_FEC_RXD0__FEC_RDATA_0,
+	MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX53_PAD_FEC_TXD1__FEC_TDATA_1,
+	MX53_PAD_FEC_TXD0__FEC_TDATA_0,
+	/* FEC_nRST */
+	MX53_PAD_PATA_DA_0__GPIO7_6,
+	/* FEC_nINT */
+	MX53_PAD_PATA_DATA4__GPIO2_4,
+	/* AUDMUX5 */
+	MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
+	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
+	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
+	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+	/* I2C2 */
+	MX53_PAD_KEY_COL3__I2C2_SCL,
+	MX53_PAD_KEY_ROW3__I2C2_SDA,
+	/* SD1 */
+	MX53_PAD_SD1_CMD__ESDHC1_CMD,
+	MX53_PAD_SD1_CLK__ESDHC1_CLK,
+	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* SD3 */
+	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+	/* SD3_CD */
+	MX53_PAD_EIM_DA11__GPIO3_11,
+	/* SD3_WP */
+	MX53_PAD_EIM_DA12__GPIO3_12,
+	/* VGA */
+	MX53_PAD_EIM_OE__IPU_DI1_PIN7,
+	MX53_PAD_EIM_RW__IPU_DI1_PIN8,
+	/* DISPLB */
+	MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
+	MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
+	MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
+	MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
+	/* DISP0_POWER_EN */
+	MX53_PAD_EIM_D24__GPIO3_24,
+	/* DISP0 DET INT */
+	MX53_PAD_EIM_D31__GPIO3_31,
+	/* LVDS */
+	MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+	MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+	MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+	MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+	MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+	MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+	MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+	MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+	MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+	MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	/* UART1 */
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+	/* CSI0 */
+	MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
+	MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
+	MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
+	MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
+	MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
+	MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
+	MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
+	MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
+	MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
+	MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
+	MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
+	/* DISPLAY */
+	MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+	MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+	MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+	MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+	MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+	MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+	MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+	MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+	MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+	MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+	MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+	MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+	MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+	MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+	MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+	MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+	MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+	MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+	MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+	MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+	MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+	MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+	MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+	MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+	MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+	/* Audio CLK*/
+	MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
+	/* PWM */
+	MX53_PAD_GPIO_1__PWM2_PWMO,
+	/* SPDIF */
+	MX53_PAD_GPIO_7__SPDIF_PLOCK,
+	MX53_PAD_GPIO_17__SPDIF_OUT1,
+	/* GPIO */
+	MX53_PAD_PATA_DA_1__GPIO7_7,
+	MX53_PAD_PATA_DA_2__GPIO7_8,
+	MX53_PAD_PATA_DATA5__GPIO2_5,
+	MX53_PAD_PATA_DATA6__GPIO2_6,
+	MX53_PAD_PATA_DATA14__GPIO2_14,
+	MX53_PAD_PATA_DATA15__GPIO2_15,
+	MX53_PAD_PATA_INTRQ__GPIO7_2,
+	MX53_PAD_EIM_WAIT__GPIO5_0,
+	MX53_PAD_NANDF_WP_B__GPIO6_9,
+	MX53_PAD_NANDF_RB0__GPIO6_10,
+	MX53_PAD_NANDF_CS1__GPIO6_14,
+	MX53_PAD_NANDF_CS2__GPIO6_15,
+	MX53_PAD_NANDF_CS3__GPIO6_16,
+	MX53_PAD_GPIO_5__GPIO1_5,
+	MX53_PAD_GPIO_16__GPIO7_11,
+	MX53_PAD_GPIO_8__GPIO1_8,
 };
 
-static const struct imxuart_platform_data mx53_loco_uart_data __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mx53_loco_init_uart(void)
-{
-	imx53_add_imx_uart(0, &mx53_loco_uart_data);
-	imx53_add_imx_uart(1, &mx53_loco_uart_data);
-	imx53_add_imx_uart(2, &mx53_loco_uart_data);
-}
-
 static inline void mx53_loco_fec_reset(void)
 {
 	int ret;
@@ -85,13 +199,22 @@ static struct fec_platform_data mx53_loco_fec_data = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
+static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
 static void __init mx53_loco_board_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
 					ARRAY_SIZE(mx53_loco_pads));
-	mx53_loco_init_uart();
+	imx53_add_imx_uart(0, NULL);
 	mx53_loco_fec_reset();
 	imx53_add_fec(&mx53_loco_fec_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
+	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
+	imx53_add_sdhci_esdhc_imx(0, NULL);
+	imx53_add_sdhci_esdhc_imx(2, NULL);
 }
 
 static void __init mx53_loco_timer_init(void)
@@ -105,7 +228,8 @@ static struct sys_timer mx53_loco_timer = {
 
 MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
 	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
-	.init_machine = mx53_loco_board_init,
 	.timer = &mx53_loco_timer,
+	.init_machine = mx53_loco_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/board-mx53_smd.c b/arch/arm/mach-mx5/board-mx53_smd.c
index 7970f7a..31e1732 100644
--- a/arch/arm/mach-mx5/board-mx53_smd.c
+++ b/arch/arm/mach-mx5/board-mx53_smd.c
@@ -39,20 +39,19 @@
 #define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
 
 static iomux_v3_cfg_t mx53_smd_pads[] = {
-	MX53_PAD_CSI0_D10__UART1_TXD,
-	MX53_PAD_CSI0_D11__UART1_RXD,
-	MX53_PAD_ATA_DIOW__UART1_TXD,
-	MX53_PAD_ATA_DMACK__UART1_RXD,
-
-	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
-	MX53_PAD_ATA_DMARQ__UART2_TXD,
-	MX53_PAD_ATA_DIOR__UART2_RTS,
-	MX53_PAD_ATA_INTRQ__UART2_CTS,
-
-	MX53_PAD_ATA_CS_0__UART3_TXD,
-	MX53_PAD_ATA_CS_1__UART3_RXD,
-	MX53_PAD_ATA_DA_1__UART3_CTS,
-	MX53_PAD_ATA_DA_2__UART3_RTS,
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+
+	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+	MX53_PAD_PATA_DA_1__UART3_CTS,
+	MX53_PAD_PATA_DA_2__UART3_RTS,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
 };
 
 static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
@@ -61,8 +60,8 @@ static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
 
 static inline void mx53_smd_init_uart(void)
 {
-	imx53_add_imx_uart(0, &mx53_smd_uart_data);
-	imx53_add_imx_uart(1, &mx53_smd_uart_data);
+	imx53_add_imx_uart(0, NULL);
+	imx53_add_imx_uart(1, NULL);
 	imx53_add_imx_uart(2, &mx53_smd_uart_data);
 }
 
@@ -85,6 +84,10 @@ static struct fec_platform_data mx53_smd_fec_data = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
+static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
 static void __init mx53_smd_board_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
@@ -92,6 +95,8 @@ static void __init mx53_smd_board_init(void)
 	mx53_smd_init_uart();
 	mx53_smd_fec_reset();
 	imx53_add_fec(&mx53_smd_fec_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
 }
 
 static void __init mx53_smd_timer_init(void)
@@ -105,7 +110,8 @@ static struct sys_timer mx53_smd_timer = {
 
 MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
 	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
-	.init_machine = mx53_smd_board_init,
 	.timer = &mx53_smd_timer,
+	.init_machine = mx53_smd_board_init,
 MACHINE_END
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 0a19e75..652ace4 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -42,6 +42,9 @@ static struct clk usboh3_clk;
 static struct clk emi_fast_clk;
 static struct clk ipu_clk;
 static struct clk mipi_hsc1_clk;
+static struct clk esdhc1_clk;
+static struct clk esdhc2_clk;
+static struct clk esdhc3_mx53_clk;
 
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
@@ -867,10 +870,6 @@ static struct clk gpt_32k_clk = {
 	.parent = &ckil_clk,
 };
 
-static struct clk kpp_clk = {
-	.id = 0,
-};
-
 static struct clk dummy_clk = {
 	.id = 0,
 };
@@ -1147,10 +1146,80 @@ CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
 CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
 CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
 
+/* mx51 specific */
 CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
 CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
 CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
 
+static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+	else if (parent == &esdhc2_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else if (parent == &esdhc2_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+/* mx53 specific */
+static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+	else if (parent == &esdhc3_mx53_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+
+static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else if (parent == &esdhc3_mx53_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
 #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
 	static struct clk name = {					\
 		.id		= i,					\
@@ -1255,9 +1324,62 @@ DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
 	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
 DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
 	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+
+/* mx51 specific */
 DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
 	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
 
+static struct clk esdhc3_clk = {
+	.id = 2,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc3_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc3_ipg_clk,
+};
+static struct clk esdhc4_clk = {
+	.id = 3,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc4_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc4_ipg_clk,
+};
+
+/* mx53 specific */
+static struct clk esdhc2_mx53_clk = {
+	.id = 2,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc2_mx53_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc3_ipg_clk,
+};
+
+DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
+	clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc4_mx53_clk = {
+	.id = 3,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc4_mx53_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc4_ipg_clk,
+};
+
 DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
@@ -1302,7 +1424,7 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
 	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
@@ -1316,6 +1438,8 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)
 	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
 	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
@@ -1336,10 +1460,14 @@ static struct clk_lookup mx53_lookups[] = {
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
 	_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
 	_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
 };
 
 static void clk_tree_init(void)
@@ -1427,6 +1555,14 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
 	mx53_revision();
 	clk_disable(&iim_clk);
 
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 200MHZ*/
+	clk_set_rate(&esdhc1_clk, 200000000);
+	clk_set_rate(&esdhc3_mx53_clk, 200000000);
+
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
 		MX53_INT_GPT);
diff --git a/arch/arm/mach-mx5/cpu.c b/arch/arm/mach-mx5/cpu.c
index d40671d..df46b5e 100644
--- a/arch/arm/mach-mx5/cpu.c
+++ b/arch/arm/mach-mx5/cpu.c
@@ -78,11 +78,16 @@ static int get_mx53_srev(void)
 	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	if (rev == 0x0)
+	switch (rev) {
+	case 0x0:
 		return IMX_CHIP_REVISION_1_0;
-	else if (rev == 0x10)
+	case 0x2:
 		return IMX_CHIP_REVISION_2_0;
-	return 0;
+	case 0x3:
+		return IMX_CHIP_REVISION_2_1;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
 }
 
 /*
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
index b462c22..87c0c58 100644
--- a/arch/arm/mach-mx5/crm_regs.h
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -217,9 +217,12 @@
 #define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
 #define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
 #define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL	(0x1 << 19)
 #define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
 #define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
 #define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET	(16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK		(0x3 << 16)
 #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
 #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
 #define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
@@ -271,6 +274,10 @@
 #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
 #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
 #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET	(22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK	(0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET	(19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK	(0x7 << 19)
 #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
 #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
 #define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
diff --git a/arch/arm/mach-mx5/devices-imx50.h b/arch/arm/mach-mx5/devices-imx50.h
new file mode 100644
index 0000000..c9e4282
--- /dev/null
+++ b/arch/arm/mach-mx5/devices-imx50.h
@@ -0,0 +1,34 @@
+/*
+ * 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 <mach/mx50.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst;
+#define imx50_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
+
+extern const struct imx_fec_data imx50_fec_data __initconst;
+#define imx50_add_fec(pdata)	\
+	imx_add_fec(&imx50_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst;
+#define imx50_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index 8639735..9251008 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -29,3 +29,7 @@ imx53_sdhci_esdhc_imx_data[] __initconst;
 extern const struct imx_spi_imx_data imx53_ecspi_data[] __initconst;
 #define imx53_add_ecspi(id, pdata)	\
 	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst;
+#define imx53_add_imx2_wdt(id, pdata)	\
+	imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
diff --git a/arch/arm/mach-mx5/devices-mx50.h b/arch/arm/mach-mx5/devices-mx50.h
deleted file mode 100644
index 98ab074..0000000
--- a/arch/arm/mach-mx5/devices-mx50.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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 <mach/mx50.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst;
-#define imx50_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
diff --git a/arch/arm/mach-mx5/efika.h b/arch/arm/mach-mx5/efika.h
new file mode 100644
index 0000000..014aa98
--- /dev/null
+++ b/arch/arm/mach-mx5/efika.h
@@ -0,0 +1,10 @@
+#ifndef _EFIKA_H
+#define _EFIKA_H
+
+#define EFIKA_WLAN_EN		IMX_GPIO_NR(2, 16)
+#define EFIKA_WLAN_RESET	IMX_GPIO_NR(2, 10)
+#define EFIKA_USB_PHY_RESET	IMX_GPIO_NR(2, 9)
+
+void __init efika_board_common_init(void);
+
+#endif
diff --git a/arch/arm/mach-mx5/ehci.c b/arch/arm/mach-mx5/ehci.c
new file mode 100644
index 0000000..7ce12c8
--- /dev/null
+++ b/arch/arm/mach-mx5/ehci.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT 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/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define MXC_OTG_OFFSET			0
+#define MXC_H1_OFFSET			0x200
+#define MXC_H2_OFFSET			0x400
+
+/* USB_CTRL */
+#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
+#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
+#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
+#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
+#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)		/* HOST1 power mask */
+
+/* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_DIS_BIT		(1 << 5)	/* UH1 Disable Overcurrent Event */
+
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
+
+#define MXC_USBCMD_OFFSET		0x140
+
+/* USBCMD */
+#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
+
+int mx51_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+	void __iomem *usb_base;
+	void __iomem *usbotg_base;
+	void __iomem *usbother_base;
+	int ret = 0;
+
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base) {
+		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	switch (port) {
+	case 0:	/* OTG port */
+		usbotg_base = usb_base + MXC_OTG_OFFSET;
+		break;
+	case 1:	/* Host 1 port */
+		usbotg_base = usb_base + MXC_H1_OFFSET;
+		break;
+	case 2: /* Host 2 port */
+		usbotg_base = usb_base + MXC_H2_OFFSET;
+		break;
+	default:
+		printk(KERN_ERR"%s no such port %d\n", __func__, port);
+		ret = -ENOENT;
+		goto error;
+	}
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	switch (port) {
+	case 0:	/*OTG port */
+		if (flags & MXC_EHCI_INTERNAL_PHY) {
+			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+				/* OC/USBPWR is not used */
+				v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+			} else {
+				/* OC/USBPWR is used */
+				v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+			}
+			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+			if (flags & MXC_EHCI_WAKEUP_ENABLED)
+				v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
+			else
+				v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+				v |= MXC_OTG_UCTRL_OPM_BIT;
+			else
+				v &= ~MXC_OTG_UCTRL_OPM_BIT;
+			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+		}
+		break;
+	case 1:	/* Host 1 */
+		/*Host ULPI */
+		v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+			/* HOST1 wakeup/ULPI intr enable */
+			v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+		} else {
+			/* HOST1 wakeup/ULPI intr disable */
+			v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+		}
+
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+		else
+			v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+		__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+
+		v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
+		else
+			v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
+		__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+		v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
+		if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
+			/* Interrupt Threshold Control:Immediate (no threshold) */
+			v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
+		__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
+		break;
+	case 2: /* Host 2 ULPI */
+		v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+			/* HOST1 wakeup/ULPI intr enable */
+			v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+		} else {
+			/* HOST1 wakeup/ULPI intr disable */
+			v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+		}
+
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+		else
+			v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+		__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+		break;
+	}
+
+error:
+	iounmap(usb_base);
+	return ret;
+}
+
diff --git a/arch/arm/mach-mx5/mm-mx50.c b/arch/arm/mach-mx5/mm-mx50.c
index 8c6540e..b9c363b 100644
--- a/arch/arm/mach-mx5/mm-mx50.c
+++ b/arch/arm/mach-mx5/mm-mx50.c
@@ -26,6 +26,8 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-v3.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
 
 /*
  * Define the MX50 memory map.
@@ -44,16 +46,27 @@ static struct map_desc mx50_io_desc[] __initdata = {
  */
 void __init mx50_map_io(void)
 {
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX50);
 	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
 }
 
-int imx50_register_gpios(void);
+static struct mxc_gpio_port imx50_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+};
 
 void __init mx50_init_irq(void)
 {
 	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-	imx50_register_gpios();
+	mxc_gpio_init(imx50_gpio_ports,	ARRAY_SIZE(imx50_gpio_ports));
 }
diff --git a/arch/arm/mach-mx5/mm.c b/arch/arm/mach-mx5/mm.c
index 457f9f9..ff55730 100644
--- a/arch/arm/mach-mx5/mm.c
+++ b/arch/arm/mach-mx5/mm.c
@@ -47,18 +47,26 @@ static struct map_desc mx53_io_desc[] __initdata = {
  */
 void __init mx51_map_io(void)
 {
+	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
+}
+
+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));
-	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
 }
 
 void __init mx53_map_io(void)
 {
+	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+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_WDOG_BASE_ADDR));
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
 int imx51_register_gpios(void);
diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c
new file mode 100644
index 0000000..51a67fc
--- /dev/null
+++ b/arch/arm/mach-mx5/mx51_efika.c
@@ -0,0 +1,636 @@
+/*
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, 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/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_ehci.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/mach-types.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+#include "efika.h"
+#include "cpu_op-mx51.h"
+
+#define MX51_USB_CTRL_1_OFFSET          0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+
+#define EFIKAMX_USB_HUB_RESET	IMX_GPIO_NR(1, 5)
+#define EFIKAMX_USBH1_STP	IMX_GPIO_NR(1, 27)
+
+#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
+#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
+
+#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
+
+static iomux_v3_cfg_t mx51efika_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* SD 1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* SD 2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+	/* SD/MMC WP/CD */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
+	MX51_PAD_GPIO1_7__SD2_WP,
+	MX51_PAD_GPIO1_8__SD2_CD,
+
+	/* spi */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
+	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_GPIO1_6__GPIO1_6,
+
+	/* USB HOST1 */
+	MX51_PAD_USBH1_CLK__USBH1_CLK,
+	MX51_PAD_USBH1_DIR__USBH1_DIR,
+	MX51_PAD_USBH1_NXT__USBH1_NXT,
+	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+	/* USB HUB RESET */
+	MX51_PAD_GPIO1_5__GPIO1_5,
+
+	/* WLAN */
+	MX51_PAD_EIM_A22__GPIO2_16,
+	MX51_PAD_EIM_A16__GPIO2_10,
+
+	/* USB PHY RESET */
+	MX51_PAD_EIM_D27__GPIO2_9,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+	/* Set the PHY clock to 19.2MHz */
+	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+	v |= MX51_USB_PLL_DIV_19_2_MHZ;
+	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
+static struct mxc_usbh_platform_data dr_utmi_config = {
+	.init   = initialize_otg_port,
+	.portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+	iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *socregs_base;
+
+	mxc_iomux_v3_setup_pad(usbh1gpio);
+	gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
+	gpio_direction_output(EFIKAMX_USBH1_STP, 0);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USBH1_STP, 1);
+	msleep(1);
+
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+	/* The clock for the USBH1 ULPI port will come externally */
+	/* from the PHY. */
+	v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
+	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+			socregs_base + MX51_USB_CTRL_1_OFFSET);
+
+	iounmap(usb_base);
+
+	gpio_free(EFIKAMX_USBH1_STP);
+	mxc_iomux_v3_setup_pad(usbh1stp);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh1_config = {
+	.init   = initialize_usbh1_port,
+	.portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void mx51_efika_hubreset(void)
+{
+	gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
+	gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
+}
+
+static void __init mx51_efika_usb(void)
+{
+	mx51_efika_hubreset();
+
+	/* pulling it low, means no USB at all... */
+	gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
+	gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
+	msleep(1);
+	gpio_set_value(EFIKA_USB_PHY_RESET, 1);
+
+	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+
+	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+	if (usbh1_config.otg)
+		mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+}
+
+static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
+	{
+	 .name = "u-boot",
+	 .offset = 0,
+	 .size = SZ_256K,
+	},
+	{
+	  .name = "config",
+	  .offset = MTDPART_OFS_APPEND,
+	  .size = SZ_64K,
+	},
+};
+
+static struct flash_platform_data mx51_efika_spi_flash_data = {
+	.name		= "spi_flash",
+	.parts		= mx51_efika_spi_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(mx51_efika_spi_nor_partitions),
+	.type		= "sst25vf032b",
+};
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+	{
+		.supply = "cpu_vcc",
+	}
+};
+
+static struct regulator_consumer_supply vdig_consumers[] = {
+	/* sgtl5000 */
+	REGULATOR_SUPPLY("VDDA", "1-000a"),
+	REGULATOR_SUPPLY("VDDD", "1-000a"),
+};
+
+static struct regulator_consumer_supply vvideo_consumers[] = {
+	/* sgtl5000 */
+	REGULATOR_SUPPLY("VDDIO", "1-000a"),
+};
+
+static struct regulator_consumer_supply vsd_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+};
+
+static struct regulator_consumer_supply pwgt1_consumer[] = {
+	{
+		.supply = "pwgt1",
+	}
+};
+
+static struct regulator_consumer_supply pwgt2_consumer[] = {
+	{
+		.supply = "pwgt2",
+	}
+};
+
+static struct regulator_consumer_supply coincell_consumer[] = {
+	{
+		.supply = "coincell",
+	}
+};
+
+static struct regulator_init_data sw1_init = {
+	.constraints = {
+		.name = "SW1",
+		.min_uV = 600000,
+		.max_uV = 1375000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.valid_modes_mask = 0,
+		.always_on = 1,
+		.boot_on = 1,
+		.state_mem = {
+			.uV = 850000,
+			.mode = REGULATOR_MODE_NORMAL,
+			.enabled = 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+	.consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+	.constraints = {
+		.name = "SW2",
+		.min_uV = 900000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+		.state_mem = {
+			.uV = 950000,
+			.mode = REGULATOR_MODE_NORMAL,
+			.enabled = 1,
+		},
+	}
+};
+
+static struct regulator_init_data sw3_init = {
+	.constraints = {
+		.name = "SW3",
+		.min_uV = 1100000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data sw4_init = {
+	.constraints = {
+		.name = "SW4",
+		.min_uV = 1100000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data viohi_init = {
+	.constraints = {
+		.name = "VIOHI",
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vusb_init = {
+	.constraints = {
+		.name = "VUSB",
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data swbst_init = {
+	.constraints = {
+		.name = "SWBST",
+	}
+};
+
+static struct regulator_init_data vdig_init = {
+	.constraints = {
+		.name = "VDIG",
+		.min_uV = 1050000,
+		.max_uV = 1800000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
+	.consumer_supplies = vdig_consumers,
+};
+
+static struct regulator_init_data vpll_init = {
+	.constraints = {
+		.name = "VPLL",
+		.min_uV = 1050000,
+		.max_uV = 1800000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vusb2_init = {
+	.constraints = {
+		.name = "VUSB2",
+		.min_uV = 2400000,
+		.max_uV = 2775000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vvideo_init = {
+	.constraints = {
+		.name = "VVIDEO",
+		.min_uV = 2775000,
+		.max_uV = 2775000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.apply_uV = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
+	.consumer_supplies = vvideo_consumers,
+};
+
+static struct regulator_init_data vaudio_init = {
+	.constraints = {
+		.name = "VAUDIO",
+		.min_uV = 2300000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data vsd_init = {
+	.constraints = {
+		.name = "VSD",
+		.min_uV = 1800000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
+	.consumer_supplies = vsd_consumers,
+};
+
+static struct regulator_init_data vcam_init = {
+	.constraints = {
+		.name = "VCAM",
+		.min_uV = 2500000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen1_init = {
+	.constraints = {
+		.name = "VGEN1",
+		.min_uV = 1200000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen2_init = {
+	.constraints = {
+		.name = "VGEN2",
+		.min_uV = 1200000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen3_init = {
+	.constraints = {
+		.name = "VGEN3",
+		.min_uV = 1800000,
+		.max_uV = 2900000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data gpo1_init = {
+	.constraints = {
+		.name = "GPO1",
+	}
+};
+
+static struct regulator_init_data gpo2_init = {
+	.constraints = {
+		.name = "GPO2",
+	}
+};
+
+static struct regulator_init_data gpo3_init = {
+	.constraints = {
+		.name = "GPO3",
+	}
+};
+
+static struct regulator_init_data gpo4_init = {
+	.constraints = {
+		.name = "GPO4",
+	}
+};
+
+static struct regulator_init_data pwgt1_init = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on        = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
+	.consumer_supplies = pwgt1_consumer,
+};
+
+static struct regulator_init_data pwgt2_init = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on        = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
+	.consumer_supplies = pwgt2_consumer,
+};
+
+static struct regulator_init_data vcoincell_init = {
+	.constraints = {
+		.name = "COINCELL",
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
+	.consumer_supplies = coincell_consumer,
+};
+
+static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
+	{ .id = MC13892_SW1,		.init_data =  &sw1_init },
+	{ .id = MC13892_SW2,		.init_data =  &sw2_init },
+	{ .id = MC13892_SW3,		.init_data =  &sw3_init },
+	{ .id = MC13892_SW4,		.init_data =  &sw4_init },
+	{ .id = MC13892_SWBST,		.init_data =  &swbst_init },
+	{ .id = MC13892_VIOHI,		.init_data =  &viohi_init },
+	{ .id = MC13892_VPLL,		.init_data =  &vpll_init },
+	{ .id = MC13892_VDIG,		.init_data =  &vdig_init },
+	{ .id = MC13892_VSD,		.init_data =  &vsd_init },
+	{ .id = MC13892_VUSB2,		.init_data =  &vusb2_init },
+	{ .id = MC13892_VVIDEO,		.init_data =  &vvideo_init },
+	{ .id = MC13892_VAUDIO,		.init_data =  &vaudio_init },
+	{ .id = MC13892_VCAM,		.init_data =  &vcam_init },
+	{ .id = MC13892_VGEN1,		.init_data =  &vgen1_init },
+	{ .id = MC13892_VGEN2,		.init_data =  &vgen2_init },
+	{ .id = MC13892_VGEN3,		.init_data =  &vgen3_init },
+	{ .id = MC13892_VUSB,		.init_data =  &vusb_init },
+	{ .id = MC13892_GPO1,		.init_data =  &gpo1_init },
+	{ .id = MC13892_GPO2,		.init_data =  &gpo2_init },
+	{ .id = MC13892_GPO3,		.init_data =  &gpo3_init },
+	{ .id = MC13892_GPO4,		.init_data =  &gpo4_init },
+	{ .id = MC13892_PWGT1SPI,	.init_data = &pwgt1_init },
+	{ .id = MC13892_PWGT2SPI,	.init_data = &pwgt2_init },
+	{ .id = MC13892_VCOINCELL,	.init_data = &vcoincell_init },
+};
+
+static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
+	.flags = MC13XXX_USE_RTC | MC13XXX_USE_REGULATOR,
+	.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
+	.regulators = mx51_efika_regulators,
+};
+
+static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &mx51_efika_spi_flash_data,
+		.irq = -1,
+	},
+	{
+		.modalias = "mc13892",
+		.max_speed_hz = 1000000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.platform_data = &mx51_efika_mc13892_data,
+		.irq = gpio_to_irq(EFIKAMX_PMIC),
+	},
+};
+
+static int mx51_efika_spi_cs[] = {
+	EFIKAMX_SPI_CS0,
+	EFIKAMX_SPI_CS1,
+};
+
+static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
+	.chipselect     = mx51_efika_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
+};
+
+void __init efika_board_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
+					ARRAY_SIZE(mx51efika_pads));
+	imx51_add_imx_uart(0, &uart_pdata);
+	mx51_efika_usb();
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+
+	/* FIXME: comes from original code. check this. */
+	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
+		sw2_init.constraints.state_mem.uV = 1100000;
+	else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
+		sw2_init.constraints.state_mem.uV = 1250000;
+		sw1_init.constraints.state_mem.uV = 1000000;
+	}
+	if (machine_is_mx51_efikasb())
+		vgen1_init.constraints.max_uV = 1200000;
+
+	gpio_request(EFIKAMX_PMIC, "pmic irq");
+	gpio_direction_input(EFIKAMX_PMIC);
+	spi_register_board_info(mx51_efika_spi_board_info,
+		ARRAY_SIZE(mx51_efika_spi_board_info));
+	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+	get_cpu_op = mx51_get_cpu_op;
+#endif
+}
+
diff --git a/arch/arm/mach-mxc91231/iomux.c b/arch/arm/mach-mxc91231/iomux.c
index 405d9b1..66fc41c 100644
--- a/arch/arm/mach-mxc91231/iomux.c
+++ b/arch/arm/mach-mxc91231/iomux.c
@@ -50,7 +50,7 @@ unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
 /*
  * set the mode for a IOMUX pin.
  */
-int mxc_iomux_mode(const unsigned int pin_mode)
+int mxc_iomux_mode(unsigned int pin_mode)
 {
 	u32 side, field, l, mode, ret = 0;
 	void __iomem *reg;
@@ -114,7 +114,7 @@ EXPORT_SYMBOL(mxc_iomux_set_pad);
  * 	- reserves the pin so that it is not claimed by another driver
  * 	- setups the iomux according to the configuration
  */
-int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label)
+int mxc_iomux_alloc_pin(unsigned int pin_mode, const char *label)
 {
 	unsigned pad = PIN_GLOBAL_NUM(pin_mode);
 	if (pad >= (PIN_MAX + 1)) {
@@ -134,10 +134,10 @@ int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label)
 }
 EXPORT_SYMBOL(mxc_iomux_alloc_pin);
 
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 	int ret = -EINVAL;
 
@@ -155,7 +155,7 @@ setup_error:
 }
 EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
 
-void mxc_iomux_release_pin(const unsigned int pin_mode)
+void mxc_iomux_release_pin(unsigned int pin_mode)
 {
 	unsigned pad = PIN_GLOBAL_NUM(pin_mode);
 
@@ -164,9 +164,9 @@ void mxc_iomux_release_pin(const unsigned int pin_mode)
 }
 EXPORT_SYMBOL(mxc_iomux_release_pin);
 
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 
 	for (i = 0; i < count; i++) {
diff --git a/arch/arm/mach-mxc91231/magx-zn5.c b/arch/arm/mach-mxc91231/magx-zn5.c
index 395d83b..f31a45e 100644
--- a/arch/arm/mach-mxc91231/magx-zn5.c
+++ b/arch/arm/mach-mxc91231/magx-zn5.c
@@ -53,9 +53,10 @@ struct sys_timer zn5_timer = {
 };
 
 MACHINE_START(MAGX_ZN5, "Motorola Zn5")
-	.boot_params	= MXC91231_PHYS_OFFSET + 0x100,
-	.map_io		= mxc91231_map_io,
-	.init_irq	= mxc91231_init_irq,
-	.timer		= &zn5_timer,
-	.init_machine	= zn5_init,
+	.boot_params = MXC91231_PHYS_OFFSET + 0x100,
+	.map_io = mxc91231_map_io,
+	.init_early = mxc91231_init_early,
+	.init_irq = mxc91231_init_irq,
+	.timer = &zn5_timer,
+	.init_machine = zn5_init,
 MACHINE_END
diff --git a/arch/arm/mach-mxc91231/mm.c b/arch/arm/mach-mxc91231/mm.c
index 7652c30..a77f6da 100644
--- a/arch/arm/mach-mxc91231/mm.c
+++ b/arch/arm/mach-mxc91231/mm.c
@@ -45,11 +45,14 @@ static struct map_desc mxc91231_io_desc[] __initdata = {
  */
 void __init mxc91231_map_io(void)
 {
-	mxc_set_cpu_type(MXC_CPU_MXC91231);
-
 	iotable_init(mxc91231_io_desc, ARRAY_SIZE(mxc91231_io_desc));
 }
 
+void __init mxc91231_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MXC91231);
+}
+
 int mxc91231_register_gpios(void);
 
 void __init mxc91231_init_irq(void)
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 8bfc8df..4f6f174 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -2,13 +2,18 @@ if ARCH_MXS
 
 source "arch/arm/mach-mxs/devices/Kconfig"
 
+config MXS_OCOTP
+	bool
+
 config SOC_IMX23
 	bool
 	select CPU_ARM926T
+	select HAVE_PWM
 
 config SOC_IMX28
 	bool
 	select CPU_ARM926T
+	select HAVE_PWM
 
 comment "MXS platforms:"
 
@@ -16,6 +21,8 @@ config MACH_MX23EVK
 	bool "Support MX23EVK Platform"
 	select SOC_IMX23
 	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_MXSFB
 	default y
 	help
 	  Include support for MX23EVK platform. This includes specific
@@ -25,10 +32,27 @@ config MACH_MX28EVK
 	bool "Support MX28EVK Platform"
 	select SOC_IMX28
 	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_FLEXCAN
+	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_OCOTP
 	default y
 	help
 	  Include support for MX28EVK platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MODULE_TX28
+	bool
+	select SOC_IMX28
+	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_MXS_PWM
+
+config MACH_TX28
+	bool "Ka-Ro TX28 module"
+	select MODULE_TX28
+
 endif
diff --git a/arch/arm/mach-mxs/Makefile b/arch/arm/mach-mxs/Makefile
index 39d3f9c..2f1f614 100644
--- a/arch/arm/mach-mxs/Makefile
+++ b/arch/arm/mach-mxs/Makefile
@@ -1,10 +1,15 @@
 # Common support
 obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
 
+obj-$(CONFIG_MXS_OCOTP) += ocotp.o
+obj-$(CONFIG_PM) += pm.o
+
 obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
 obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
 
 obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
 obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+obj-$(CONFIG_MODULE_TX28) += module-tx28.o
+obj-$(CONFIG_MACH_TX28)    += mach-tx28.o
 
 obj-y += devices/
diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index ca72a05..d133c7f 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -442,11 +442,18 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("duart", "apb_pclk", xbus_clk)
 	/* for amba-pl011 driver */
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
-	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
 	_REGISTER_CLOCK(NULL, "usb", usb_clk)
 	_REGISTER_CLOCK(NULL, "audio", audio_clk)
-	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
+	_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
 };
 
 static int clk_misc_init(void)
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index fd1c4c5..5e489a2 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -609,17 +609,30 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
 	_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
+	_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.3", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.4", NULL, uart_clk)
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
 	_REGISTER_CLOCK("pll2", NULL, pll2_clk)
-	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
-	_REGISTER_CLOCK(NULL, "xclk", xbus_clk)
-	_REGISTER_CLOCK(NULL, "can0", can0_clk)
-	_REGISTER_CLOCK(NULL, "can1", can1_clk)
+	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
+	_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
+	_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
 	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
 	_REGISTER_CLOCK(NULL, "usb1", usb1_clk)
-	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.5", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.6", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.7", NULL, pwm_clk)
 	_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
+	_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
 };
 
 static int clk_misc_init(void)
@@ -737,6 +750,8 @@ int __init mx28_clocks_init(void)
 	clk_enable(&emi_clk);
 	clk_enable(&uart_clk);
 
+	clk_set_parent(&lcdif_clk, &ref_pix_clk);
+
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
 	mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0);
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index 1256788..c7e14f4 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -10,7 +10,18 @@
  */
 #include <mach/mx23.h>
 #include <mach/devices-common.h>
+#include <mach/mxsfb.h>
 
 extern const struct amba_device mx23_duart_device __initconst;
 #define mx23_add_duart() \
 	mxs_add_duart(&mx23_duart_device)
+
+extern const struct mxs_auart_data mx23_auart_data[] __initconst;
+#define mx23_add_auart(id)	mxs_add_auart(&mx23_auart_data[id])
+#define mx23_add_auart0()		mx23_add_auart(0)
+#define mx23_add_auart1()		mx23_add_auart(1)
+
+#define mx23_add_mxs_pwm(id)		mxs_add_mxs_pwm(MX23_PWM_BASE_ADDR, id)
+
+struct platform_device *__init mx23_add_mxsfb(
+		const struct mxsfb_platform_data *pdata);
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 33773a6..9d08555 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -10,11 +10,34 @@
  */
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
+#include <mach/mxsfb.h>
 
 extern const struct amba_device mx28_duart_device __initconst;
 #define mx28_add_duart() \
 	mxs_add_duart(&mx28_duart_device)
 
+extern const struct mxs_auart_data mx28_auart_data[] __initconst;
+#define mx28_add_auart(id)	mxs_add_auart(&mx28_auart_data[id])
+#define mx28_add_auart0()		mx28_add_auart(0)
+#define mx28_add_auart1()		mx28_add_auart(1)
+#define mx28_add_auart2()		mx28_add_auart(2)
+#define mx28_add_auart3()		mx28_add_auart(3)
+#define mx28_add_auart4()		mx28_add_auart(4)
+
 extern const struct mxs_fec_data mx28_fec_data[] __initconst;
 #define mx28_add_fec(id, pdata) \
 	mxs_add_fec(&mx28_fec_data[id], pdata)
+
+extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
+#define mx28_add_flexcan(id, pdata)	\
+	mxs_add_flexcan(&mx28_flexcan_data[id], pdata)
+#define mx28_add_flexcan0(pdata)	mx28_add_flexcan(0, pdata)
+#define mx28_add_flexcan1(pdata)	mx28_add_flexcan(1, pdata)
+
+extern const struct mxs_i2c_data mx28_mxs_i2c_data[] __initconst;
+#define mx28_add_mxs_i2c(id)		mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id])
+
+#define mx28_add_mxs_pwm(id)		mxs_add_mxs_pwm(MX28_PWM_BASE_ADDR, id)
+
+struct platform_device *__init mx28_add_mxsfb(
+		const struct mxsfb_platform_data *pdata);
diff --git a/arch/arm/mach-mxs/devices.c b/arch/arm/mach-mxs/devices.c
index c20d547..cfdb6b2 100644
--- a/arch/arm/mach-mxs/devices.c
+++ b/arch/arm/mach-mxs/devices.c
@@ -66,6 +66,8 @@ struct platform_device *__init mxs_add_platform_device_dmamask(
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		if (dmamask)
+			kfree(pdev->dev.dma_mask);
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index cf7dc1a..1451ad0 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -2,5 +2,21 @@ config MXS_HAVE_AMBA_DUART
 	bool
 	select ARM_AMBA
 
+config MXS_HAVE_PLATFORM_AUART
+	bool
+
 config MXS_HAVE_PLATFORM_FEC
 	bool
+
+config MXS_HAVE_PLATFORM_FLEXCAN
+	select HAVE_CAN_FLEXCAN if CAN
+	bool
+
+config MXS_HAVE_PLATFORM_MXS_I2C
+	bool
+
+config MXS_HAVE_PLATFORM_MXS_PWM
+	bool
+
+config MXS_HAVE_PLATFORM_MXSFB
+	bool
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index d0a09f6..0d9bea3 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -1,2 +1,8 @@
 obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
+obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
diff --git a/arch/arm/mach-mxs/devices/platform-auart.c b/arch/arm/mach-mxs/devices/platform-auart.c
new file mode 100644
index 0000000..796606c
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-auart.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Sascha Hauer <s.hauer@pengutronix.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 <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_auart_data_entry_single(soc, _id, hwid)			\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _AUART ## hwid ## _BASE_ADDR,		\
+		.irq = soc ## _INT_AUART ## hwid,			\
+	}
+
+#define mxs_auart_data_entry(soc, _id, hwid)				\
+	[_id] = mxs_auart_data_entry_single(soc, _id, hwid)
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_auart_data mx23_auart_data[] __initconst = {
+#define mx23_auart_data_entry(_id, hwid)				\
+	mxs_auart_data_entry(MX23, _id, hwid)
+	mx23_auart_data_entry(0, 1),
+	mx23_auart_data_entry(1, 2),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_auart_data mx28_auart_data[] __initconst = {
+#define mx28_auart_data_entry(_id)					\
+	mxs_auart_data_entry(MX28, _id, _id)
+	mx28_auart_data_entry(0),
+	mx28_auart_data_entry(1),
+	mx28_auart_data_entry(2),
+	mx28_auart_data_entry(3),
+	mx28_auart_data_entry(4),
+};
+#endif
+
+struct platform_device *__init mxs_add_auart(
+		const struct mxs_auart_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device_dmamask("mxs-auart", data->id,
+					res, ARRAY_SIZE(res), NULL, 0,
+					DMA_BIT_MASK(32));
+}
+
diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c
new file mode 100644
index 0000000..295c442
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-dma.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+static struct platform_device *__init mxs_add_dma(const char *devid,
+						resource_size_t base)
+{
+	struct resource res[] = {
+		{
+			.start = base,
+			.end = base + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}
+	};
+
+	return mxs_add_platform_device_dmamask(devid, -1,
+				res, ARRAY_SIZE(res), NULL, 0,
+				DMA_BIT_MASK(32));
+}
+
+static int __init mxs_add_mxs_dma(void)
+{
+	char *apbh = "mxs-dma-apbh";
+	char *apbx = "mxs-dma-apbx";
+
+	if (cpu_is_mx23()) {
+		mxs_add_dma(apbh, MX23_APBH_DMA_BASE_ADDR);
+		mxs_add_dma(apbx, MX23_APBX_DMA_BASE_ADDR);
+	}
+
+	if (cpu_is_mx28()) {
+		mxs_add_dma(apbh, MX28_APBH_DMA_BASE_ADDR);
+		mxs_add_dma(apbx, MX28_APBX_DMA_BASE_ADDR);
+	}
+
+	return 0;
+}
+arch_initcall(mxs_add_mxs_dma);
diff --git a/arch/arm/mach-mxs/devices/platform-fec.c b/arch/arm/mach-mxs/devices/platform-fec.c
index c42dff7..9859cf2 100644
--- a/arch/arm/mach-mxs/devices/platform-fec.c
+++ b/arch/arm/mach-mxs/devices/platform-fec.c
@@ -45,6 +45,7 @@ struct platform_device *__init mxs_add_fec(
 		},
 	};
 
-	return mxs_add_platform_device("imx28-fec", data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+	return mxs_add_platform_device_dmamask("imx28-fec", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata),
+			DMA_BIT_MASK(32));
 }
diff --git a/arch/arm/mach-mxs/devices/platform-flexcan.c b/arch/arm/mach-mxs/devices/platform-flexcan.c
new file mode 100644
index 0000000..43a6b4b
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-flexcan.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010, 2011 Pengutronix,
+ *                          Marc Kleine-Budde <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 version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <asm/sizes.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_flexcan_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _CAN ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_CAN ## _hwid,			\
+	}
+
+#define mxs_flexcan_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = mxs_flexcan_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_flexcan_data mx28_flexcan_data[] __initconst = {
+#define mx28_flexcan_data_entry(_id, _hwid)				\
+	mxs_flexcan_data_entry_single(MX28, _id, _hwid, SZ_8K)
+	mx28_flexcan_data_entry(0, 0),
+	mx28_flexcan_data_entry(1, 1),
+};
+#endif /* ifdef CONFIG_SOC_IMX28 */
+
+struct platform_device *__init mxs_add_flexcan(
+		const struct mxs_flexcan_data *data,
+		const struct flexcan_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("flexcan", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-i2c.c b/arch/arm/mach-mxs/devices/platform-mxs-i2c.c
new file mode 100644
index 0000000..eab3a06
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mxs-i2c.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Pengutronix
+ * Wolfram Sang <w.sang@pengutronix.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 <asm/sizes.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_i2c_data_entry_single(soc, _id)				\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _I2C ## _id ## _BASE_ADDR,		\
+		.errirq = soc ## _INT_I2C ## _id ## _ERROR,		\
+		.dmairq = soc ## _INT_I2C ## _id ## _DMA,		\
+	}
+
+#define mxs_i2c_data_entry(soc, _id)					\
+	[_id] = mxs_i2c_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_i2c_data mx28_mxs_i2c_data[] __initconst = {
+	mxs_i2c_data_entry(MX28, 0),
+	mxs_i2c_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_mxs_i2c(const struct mxs_i2c_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->errirq,
+			.end = data->errirq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->dmairq,
+			.end = data->dmairq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-i2c", data->id, res,
+					ARRAY_SIZE(res), NULL, 0);
+}
diff --git a/arch/arm/mach-mxs/devices/platform-mxs-pwm.c b/arch/arm/mach-mxs/devices/platform-mxs-pwm.c
new file mode 100644
index 0000000..680f5a9
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mxs-pwm.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Sascha Hauer <s.hauer@pengutronix.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 <asm/sizes.h>
+#include <mach/devices-common.h>
+
+struct platform_device *__init mxs_add_mxs_pwm(resource_size_t iobase, int id)
+{
+	struct resource res = {
+		.flags = IORESOURCE_MEM,
+	};
+
+	res.start = iobase + 0x10 + 0x20 * id;
+	res.end = res.start + 0x1f;
+
+	return mxs_add_platform_device("mxs-pwm", id, &res, 1, NULL, 0);
+}
diff --git a/arch/arm/mach-mxs/devices/platform-mxsfb.c b/arch/arm/mach-mxs/devices/platform-mxsfb.c
new file mode 100644
index 0000000..bf72c9b
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-mxsfb.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Pengutronix, Sascha Hauer <s.hauer@pengutronix.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 <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+#include <mach/mxsfb.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_mxsfb(
+		const struct mxsfb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX23_LCDIF_BASE_ADDR,
+			.end = MX23_LCDIF_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return mxs_add_platform_device_dmamask("imx23-fb", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+#endif /* ifdef CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_mxsfb(
+		const struct mxsfb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_LCDIF_BASE_ADDR,
+			.end = MX28_LCDIF_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return mxs_add_platform_device_dmamask("imx28-fb", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+#endif /* ifdef CONFIG_SOC_IMX28 */
diff --git a/arch/arm/mach-mxs/gpio.c b/arch/arm/mach-mxs/gpio.c
index cb0c0e8..56fa2ed 100644
--- a/arch/arm/mach-mxs/gpio.c
+++ b/arch/arm/mach-mxs/gpio.c
@@ -68,29 +68,29 @@ static void set_gpio_irqenable(struct mxs_gpio_port *port, u32 index,
 	}
 }
 
-static void mxs_gpio_ack_irq(u32 irq)
+static void mxs_gpio_ack_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
 }
 
-static void mxs_gpio_mask_irq(u32 irq)
+static void mxs_gpio_mask_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
 }
 
-static void mxs_gpio_unmask_irq(u32 irq)
+static void mxs_gpio_unmask_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
 }
 
 static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
 
-static int mxs_gpio_set_irq_type(u32 irq, u32 type)
+static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	u32 pin_mask = 1 << (gpio & 31);
 	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
 	void __iomem *pin_addr;
@@ -160,9 +160,9 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
  * @param  enable       enable as wake-up if equal to non-zero
  * @return       This function returns 0 on success.
  */
-static int mxs_gpio_set_wake_irq(u32 irq, u32 enable)
+static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	u32 gpio_idx = gpio & 0x1f;
 	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
 
@@ -182,11 +182,12 @@ static int mxs_gpio_set_wake_irq(u32 irq, u32 enable)
 }
 
 static struct irq_chip gpio_irq_chip = {
-	.ack = mxs_gpio_ack_irq,
-	.mask = mxs_gpio_mask_irq,
-	.unmask = mxs_gpio_unmask_irq,
-	.set_type = mxs_gpio_set_irq_type,
-	.set_wake = mxs_gpio_set_wake_irq,
+	.name = "mxs gpio",
+	.irq_ack = mxs_gpio_ack_irq,
+	.irq_mask = mxs_gpio_mask_irq,
+	.irq_unmask = mxs_gpio_unmask_irq,
+	.irq_set_type = mxs_gpio_set_irq_type,
+	.irq_set_wake = mxs_gpio_set_wake_irq,
 };
 
 static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
@@ -289,39 +290,42 @@ int __init mxs_gpio_init(struct mxs_gpio_port *port, int cnt)
 	return 0;
 }
 
-#define DEFINE_MXS_GPIO_PORT(soc, _id)					\
+#define MX23_GPIO_BASE	MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR)
+#define MX28_GPIO_BASE	MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR)
+
+#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id)				\
 	{								\
 		.chip.label = "gpio-" #_id,				\
 		.id = _id,						\
-		.irq = soc ## _INT_GPIO ## _id,				\
-		.base = soc ## _IO_ADDRESS(				\
-				soc ## _PINCTRL ## _BASE_ADDR),		\
+		.irq = _irq,						\
+		.base = _base,						\
 		.virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32,	\
 	}
 
-#define DEFINE_REGISTER_FUNCTION(prefix)				\
-int __init prefix ## _register_gpios(void)				\
-{									\
-	return mxs_gpio_init(prefix ## _gpio_ports,			\
-			ARRAY_SIZE(prefix ## _gpio_ports));		\
-}
-
 #ifdef CONFIG_SOC_IMX23
 static struct mxs_gpio_port mx23_gpio_ports[] = {
-	DEFINE_MXS_GPIO_PORT(MX23, 0),
-	DEFINE_MXS_GPIO_PORT(MX23, 1),
-	DEFINE_MXS_GPIO_PORT(MX23, 2),
+	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
+	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
+	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
 };
-DEFINE_REGISTER_FUNCTION(mx23)
+
+int __init mx23_register_gpios(void)
+{
+	return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports));
+}
 #endif
 
 #ifdef CONFIG_SOC_IMX28
 static struct mxs_gpio_port mx28_gpio_ports[] = {
-	DEFINE_MXS_GPIO_PORT(MX28, 0),
-	DEFINE_MXS_GPIO_PORT(MX28, 1),
-	DEFINE_MXS_GPIO_PORT(MX28, 2),
-	DEFINE_MXS_GPIO_PORT(MX28, 3),
-	DEFINE_MXS_GPIO_PORT(MX28, 4),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
 };
-DEFINE_REGISTER_FUNCTION(mx28)
+
+int __init mx28_register_gpios(void)
+{
+	return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports));
+}
 #endif
diff --git a/arch/arm/mach-mxs/icoll.c b/arch/arm/mach-mxs/icoll.c
index 5dd43ba..0f4c120 100644
--- a/arch/arm/mach-mxs/icoll.c
+++ b/arch/arm/mach-mxs/icoll.c
@@ -34,7 +34,7 @@
 
 static void __iomem *icoll_base = MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR);
 
-static void icoll_ack_irq(unsigned int irq)
+static void icoll_ack_irq(struct irq_data *d)
 {
 	/*
 	 * The Interrupt Collector is able to prioritize irqs.
@@ -45,22 +45,22 @@ static void icoll_ack_irq(unsigned int irq)
 			icoll_base + HW_ICOLL_LEVELACK);
 }
 
-static void icoll_mask_irq(unsigned int irq)
+static void icoll_mask_irq(struct irq_data *d)
 {
 	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(irq));
+			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->irq));
 }
 
-static void icoll_unmask_irq(unsigned int irq)
+static void icoll_unmask_irq(struct irq_data *d)
 {
 	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(irq));
+			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->irq));
 }
 
 static struct irq_chip mxs_icoll_chip = {
-	.ack = icoll_ack_irq,
-	.mask = icoll_mask_irq,
-	.unmask = icoll_unmask_irq,
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = icoll_mask_irq,
+	.irq_unmask = icoll_unmask_irq,
 };
 
 void __init icoll_init_irq(void)
diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h
index 59133eb..635bb5d 100644
--- a/arch/arm/mach-mxs/include/mach/common.h
+++ b/arch/arm/mach-mxs/include/mach/common.h
@@ -13,6 +13,7 @@
 
 struct clk;
 
+extern const u32 *mxs_get_ocotp(void);
 extern int mxs_reset_block(void __iomem *);
 extern void mxs_timer_init(struct clk *, int);
 
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 6c3d1a1..71f2448 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -30,6 +30,16 @@ int __init mxs_add_amba_device(const struct amba_device *dev);
 /* duart */
 int __init mxs_add_duart(const struct amba_device *dev);
 
+/* auart */
+struct mxs_auart_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init mxs_add_auart(
+		const struct mxs_auart_data *data);
+
 /* fec */
 #include <linux/fec.h>
 struct mxs_fec_data {
@@ -41,3 +51,28 @@ struct mxs_fec_data {
 struct platform_device *__init mxs_add_fec(
 		const struct mxs_fec_data *data,
 		const struct fec_platform_data *pdata);
+
+/* flexcan */
+#include <linux/can/platform/flexcan.h>
+struct mxs_flexcan_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init mxs_add_flexcan(
+		const struct mxs_flexcan_data *data,
+		const struct flexcan_platform_data *pdata);
+
+/* i2c */
+struct mxs_i2c_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t errirq;
+	resource_size_t dmairq;
+};
+struct platform_device * __init mxs_add_mxs_i2c(const struct mxs_i2c_data *data);
+
+/* pwm */
+struct platform_device *__init mxs_add_mxs_pwm(
+		resource_size_t iobase, int id);
diff --git a/arch/arm/mach-mxs/include/mach/dma.h b/arch/arm/mach-mxs/include/mach/dma.h
new file mode 100644
index 0000000..7f4aeea
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/dma.h
@@ -0,0 +1,26 @@
+/*
+ * 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_MXS_DMA_H__
+#define __MACH_MXS_DMA_H__
+
+struct mxs_dma_data {
+	int chan_irq;
+};
+
+static inline int mxs_dma_is_apbh(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbh");
+}
+
+static inline int mxs_dma_is_apbx(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbx");
+}
+
+#endif /* __MACH_MXS_DMA_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/iomux-mx23.h b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
index 94e5dd8..b0190a4 100644
--- a/arch/arm/mach-mxs/include/mach/iomux-mx23.h
+++ b/arch/arm/mach-mxs/include/mach/iomux-mx23.h
@@ -254,102 +254,102 @@
 #define MX23_PAD_ROTARYB__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_2)
 
 /* MUXSEL_GPIO */
-#define MX23_PAD_GPMI_D00__GPO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D01__GPO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D02__GPO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D03__GPO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D04__GPO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D05__GPO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D06__GPO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D07__GPO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D08__GPO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D09__GPO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D10__GPO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D11__GPO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D12__GPO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D13__GPO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D14__GPO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D15__GPO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CLE__GPO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_ALE__GPO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE2N__GPO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY0__GPO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY1__GPO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY2__GPO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY3__GPO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WPN__GPO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WRN__GPO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDN__GPO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_CTS__GPO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RTS__GPO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RX__GPO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_TX__GPO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SCL__GPO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SDA__GPO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D00__GPIO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D01__GPIO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D02__GPIO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D03__GPIO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D04__GPIO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D05__GPIO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D06__GPIO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D07__GPIO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D08__GPIO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D09__GPIO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D10__GPIO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D11__GPIO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D12__GPIO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D13__GPIO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D14__GPIO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D15__GPIO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CLE__GPIO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_ALE__GPIO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE2N__GPIO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY0__GPIO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY1__GPIO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY2__GPIO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY3__GPIO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WPN__GPIO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WRN__GPIO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDN__GPIO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_CTS__GPIO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RTS__GPIO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RX__GPIO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_TX__GPIO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SCL__GPIO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SDA__GPIO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
 
-#define MX23_PAD_LCD_D00__GPO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D01__GPO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D02__GPO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D03__GPO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D04__GPO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D05__GPO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D06__GPO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D07__GPO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D08__GPO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D09__GPO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D10__GPO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D11__GPO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D12__GPO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D13__GPO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D14__GPO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D15__GPO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D16__GPO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D17__GPO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RESET__GPO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RS__GPO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_WR__GPO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_CS__GPO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_DOTCK__GPO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_ENABLE__GPO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_HSYNC__GPO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_VSYNC__GPO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM0__GPO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM1__GPO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM2__GPO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM3__GPO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM4__GPO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D00__GPIO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D01__GPIO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D02__GPIO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D03__GPIO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D04__GPIO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D05__GPIO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D06__GPIO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D07__GPIO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D08__GPIO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D09__GPIO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D10__GPIO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D11__GPIO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D12__GPIO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D13__GPIO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D14__GPIO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D15__GPIO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D16__GPIO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D17__GPIO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RESET__GPIO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RS__GPIO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_WR__GPIO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_CS__GPIO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_DOTCK__GPIO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_ENABLE__GPIO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_HSYNC__GPIO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_VSYNC__GPIO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM0__GPIO_1_26		MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM1__GPIO_1_27		MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM2__GPIO_1_28		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM3__GPIO_1_29		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM4__GPIO_1_30		MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
 
-#define MX23_PAD_SSP1_CMD__GPO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DETECT__GPO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA0__GPO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA1__GPO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA2__GPO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA3__GPO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_SCK__GPO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYA__GPO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYB__GPO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A00__GPO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A01__GPO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A02__GPO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A03__GPO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A04__GPO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A05__GPO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A06__GPO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A07__GPO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A08__GPO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A09__GPO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A10__GPO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A11__GPO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A12__GPO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA0__GPO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA1__GPO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CASN__GPO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE0N__GPO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE1N__GPO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE1N__GPO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE0N__GPO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CKE__GPO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_RASN__GPO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_WEN__GPO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_CMD__GPIO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DETECT__GPIO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA0__GPIO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA1__GPIO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA2__GPIO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA3__GPIO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_SCK__GPIO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYA__GPIO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYB__GPIO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A00__GPIO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A01__GPIO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A02__GPIO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A03__GPIO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A04__GPIO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A05__GPIO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A06__GPIO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A07__GPIO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A08__GPIO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A09__GPIO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A10__GPIO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A11__GPIO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A12__GPIO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA0__GPIO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA1__GPIO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CASN__GPIO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE0N__GPIO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE1N__GPIO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE1N__GPIO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE0N__GPIO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CKE__GPIO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_RASN__GPIO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_WEN__GPIO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
 
 #endif /* __MACH_IOMUX_MX23_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/iomux.h b/arch/arm/mach-mxs/include/mach/iomux.h
index fe558e3..7abdf58 100644
--- a/arch/arm/mach-mxs/include/mach/iomux.h
+++ b/arch/arm/mach-mxs/include/mach/iomux.h
@@ -91,6 +91,9 @@ typedef u32 iomux_cfg_t;
 #define MXS_PAD_PULLUP	((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \
 					MXS_PAD_PULL_VALID_MASK)
 
+/* generic pad control used in most cases */
+#define MXS_PAD_CTRL	(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+
 #define MXS_IOMUX_PAD(_bank, _pin, _muxsel, _ma, _vol, _pull)		\
 		(((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) |		\
 		((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) |		\
diff --git a/arch/arm/mach-mxs/include/mach/mmc.h b/arch/arm/mach-mxs/include/mach/mmc.h
new file mode 100644
index 0000000..211547a
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/mmc.h
@@ -0,0 +1,18 @@
+/*
+ * 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_MXS_MMC_H__
+#define __MACH_MXS_MMC_H__
+
+struct mxs_mmc_platform_data {
+	int wp_gpio;	/* write protect pin */
+	unsigned int flags;
+#define SLOTF_4_BIT_CAPABLE	(1 << 0)
+#define SLOTF_8_BIT_CAPABLE	(1 << 1)
+};
+#endif /* __MACH_MXS_MMC_H__ */
diff --git a/arch/arm/mach-mxs/include/mach/mx23.h b/arch/arm/mach-mxs/include/mach/mx23.h
index 9edd02e..c0a18c2 100644
--- a/arch/arm/mach-mxs/include/mach/mx23.h
+++ b/arch/arm/mach-mxs/include/mach/mx23.h
@@ -93,7 +93,7 @@
 #define MX23_INT_USB_WAKEUP		12
 #define MX23_INT_GPMI_DMA		13
 #define MX23_INT_SSP1_DMA		14
-#define MX23_INT_SSP_ERROR		15
+#define MX23_INT_SSP1_ERROR		15
 #define MX23_INT_GPIO0			16
 #define MX23_INT_GPIO1			17
 #define MX23_INT_GPIO2			18
@@ -101,9 +101,9 @@
 #define MX23_INT_SSP2_DMA		20
 #define MX23_INT_ECC8_IRQ		21
 #define MX23_INT_RTC_ALARM		22
-#define MX23_INT_UARTAPP_TX_DMA		23
-#define MX23_INT_UARTAPP_INTERNAL	24
-#define MX23_INT_UARTAPP_RX_DMA		25
+#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
@@ -135,11 +135,35 @@
 #define MX23_INT_DCP			54
 #define MX23_INT_BCH			56
 #define MX23_INT_PXP			57
-#define MX23_INT_UARTAPP2_TX_DMA	58
-#define MX23_INT_UARTAPP2_INTERNAL	59
-#define MX23_INT_UARTAPP2_RX_DMA	60
+#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
index 0716745..75d8611 100644
--- a/arch/arm/mach-mxs/include/mach/mx28.h
+++ b/arch/arm/mach-mxs/include/mach/mx28.h
@@ -163,10 +163,10 @@
 #define MX28_INT_USB0			93
 #define MX28_INT_USB1_WAKEUP		94
 #define MX28_INT_USB0_WAKEUP		95
-#define MX28_INT_SSP0			96
-#define MX28_INT_SSP1			97
-#define MX28_INT_SSP2			98
-#define MX28_INT_SSP3			99
+#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
@@ -185,4 +185,41 @@
 #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
index f186c08..35a89dd 100644
--- a/arch/arm/mach-mxs/include/mach/mxs.h
+++ b/arch/arm/mach-mxs/include/mach/mxs.h
@@ -28,8 +28,13 @@
 /*
  * MXS CPU types
  */
-#define cpu_is_mx23()		(machine_is_mx23evk())
-#define cpu_is_mx28()		(machine_is_mx28evk())
+#define cpu_is_mx23()		(					\
+		machine_is_mx23evk() ||					\
+		0)
+#define cpu_is_mx28()		(					\
+		machine_is_mx28evk() ||					\
+		machine_is_tx28() ||					\
+		0)
 
 /*
  * IO addresses common to MXS-based
diff --git a/arch/arm/mach-mxs/include/mach/mxsfb.h b/arch/arm/mach-mxs/include/mach/mxsfb.h
new file mode 100644
index 0000000..e4d7979
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/mxsfb.h
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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_FB_H
+#define __MACH_FB_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 FB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
+#define FB_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.
+				 */
+};
+
+#endif /* __MACH_FB_H */
diff --git a/arch/arm/mach-mxs/include/mach/uncompress.h b/arch/arm/mach-mxs/include/mach/uncompress.h
index a005e76..f12a173 100644
--- a/arch/arm/mach-mxs/include/mach/uncompress.h
+++ b/arch/arm/mach-mxs/include/mach/uncompress.h
@@ -63,6 +63,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 		mxs_duart_base = MX23_DUART_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX28EVK:
+	case MACH_TYPE_TX28:
 		mxs_duart_base = MX28_DUART_BASE_ADDR;
 		break;
 	default:
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index aa06400..a66994f 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -26,17 +26,103 @@
 
 #include "devices-mx23.h"
 
+#define MX23EVK_LCD_ENABLE	MXS_GPIO_NR(1, 18)
+#define MX23EVK_BL_ENABLE	MXS_GPIO_NR(1, 28)
+
 static const iomux_cfg_t mx23evk_pads[] __initconst = {
 	/* duart */
-	MX23_PAD_PWM0__DUART_RX | MXS_PAD_4MA,
-	MX23_PAD_PWM1__DUART_TX | MXS_PAD_4MA,
+	MX23_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
+	MX23_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
+
+	/* auart */
+	MX23_PAD_AUART1_RX__AUART1_RX | MXS_PAD_CTRL,
+	MX23_PAD_AUART1_TX__AUART1_TX | MXS_PAD_CTRL,
+	MX23_PAD_AUART1_CTS__AUART1_CTS | MXS_PAD_CTRL,
+	MX23_PAD_AUART1_RTS__AUART1_RTS | MXS_PAD_CTRL,
+
+	/* mxsfb (lcdif) */
+	MX23_PAD_LCD_D00__LCD_D00 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D01__LCD_D01 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D02__LCD_D02 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D03__LCD_D03 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D04__LCD_D04 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D05__LCD_D05 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D06__LCD_D06 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D07__LCD_D07 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D08__LCD_D08 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D09__LCD_D09 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D08__LCD_D18 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D09__LCD_D19 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D10__LCD_D20 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D11__LCD_D21 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D12__LCD_D22 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D13__LCD_D23 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_VSYNC__LCD_VSYNC | MXS_PAD_CTRL,
+	MX23_PAD_LCD_HSYNC__LCD_HSYNC | MXS_PAD_CTRL,
+	MX23_PAD_LCD_DOTCK__LCD_DOTCK | MXS_PAD_CTRL,
+	MX23_PAD_LCD_ENABLE__LCD_ENABLE | MXS_PAD_CTRL,
+	/* LCD panel enable */
+	MX23_PAD_LCD_RESET__GPIO_1_18 | MXS_PAD_CTRL,
+	/* backlight control */
+	MX23_PAD_PWM2__GPIO_1_28 | MXS_PAD_CTRL,
+};
+
+/* mxsfb (lcdif) */
+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,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
+				  FB_SYNC_DOTCLK_FAILING_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data mx23evk_mxsfb_pdata __initconst = {
+	.mode_list	= mx23evk_video_modes,
+	.mode_count	= ARRAY_SIZE(mx23evk_video_modes),
+	.default_bpp	= 32,
+	.ld_intf_width	= STMLCDIF_24BIT,
 };
 
 static void __init mx23evk_init(void)
 {
+	int ret;
+
 	mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
 
 	mx23_add_duart();
+	mx23_add_auart0();
+
+	ret = gpio_request_one(MX23EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	if (ret)
+		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+	else
+		gpio_set_value(MX23EVK_LCD_ENABLE, 1);
+
+	ret = gpio_request_one(MX23EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
+	if (ret)
+		pr_warn("failed to request gpio bl-enable: %d\n", ret);
+	else
+		gpio_set_value(MX23EVK_BL_ENABLE, 1);
+
+	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
 }
 
 static void __init mx23evk_timer_init(void)
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index 8e2c597..08002d0 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -28,54 +28,93 @@
 #include "devices-mx28.h"
 #include "gpio.h"
 
+#define MX28EVK_FLEXCAN_SWITCH	MXS_GPIO_NR(2, 13)
 #define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15)
+#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
+#define MX28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 30)
 #define MX28EVK_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
 
 static const iomux_cfg_t mx28evk_pads[] __initconst = {
 	/* duart */
-	MX28_PAD_PWM0__DUART_RX |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_PWM1__DUART_TX |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
+	MX28_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
 
+	/* auart0 */
+	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_CTS__AUART0_CTS | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_RTS__AUART0_RTS | MXS_PAD_CTRL,
+	/* auart3 */
+	MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
+
+#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
 	/* fec0 */
-	MX28_PAD_ENET0_MDC__ENET0_MDC |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_MDIO__ENET0_MDIO |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD0__ENET0_RXD0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD1__ENET0_RXD1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD0__ENET0_TXD0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD1__ENET0_TXD1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET_CLK__CLKCTRL_ENET |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
 	/* fec1 */
-	MX28_PAD_ENET0_CRS__ENET1_RX_EN |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD2__ENET1_RXD0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD3__ENET1_RXD1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_COL__ENET1_TX_EN |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD2__ENET1_TXD0 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD3__ENET1_TXD1 |
-		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
 	/* phy power line */
-	MX28_PAD_SSP1_DATA3__GPIO_2_15 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP1_DATA3__GPIO_2_15 | MXS_PAD_CTRL,
 	/* phy reset line */
-	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 | MXS_PAD_CTRL,
+
+	/* flexcan0 */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+	/* flexcan1 */
+	MX28_PAD_GPMI_CE2N__CAN1_TX,
+	MX28_PAD_GPMI_CE3N__CAN1_RX,
+	/* transceiver power control */
+	MX28_PAD_SSP1_CMD__GPIO_2_13,
+
+	/* mxsfb (lcdif) */
+	MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MXS_PAD_CTRL,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MXS_PAD_CTRL,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MXS_PAD_CTRL,
+	MX28_PAD_LCD_CS__LCD_ENABLE | MXS_PAD_CTRL,
+	/* LCD panel enable */
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MXS_PAD_CTRL,
+	/* backlight control */
+	MX28_PAD_PWM2__GPIO_3_18 | MXS_PAD_CTRL,
 };
 
 /* fec */
@@ -119,7 +158,7 @@ static void __init mx28evk_fec_reset(void)
 	gpio_set_value(MX28EVK_FEC_PHY_RESET, 1);
 }
 
-static struct fec_platform_data mx28_fec_pdata[] = {
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
 	{
 		/* fec0 */
 		.phy = PHY_INTERFACE_MODE_RMII,
@@ -129,15 +168,135 @@ static struct fec_platform_data mx28_fec_pdata[] = {
 	},
 };
 
+static int __init mx28evk_fec_get_mac(void)
+{
+	int i;
+	u32 val;
+	const u32 *ocotp = mxs_get_ocotp();
+
+	if (!ocotp)
+		goto error;
+
+	/*
+	 * OCOTP only stores the last 4 octets for each mac address,
+	 * so hard-code Freescale OUI (00:04:9f) here.
+	 */
+	for (i = 0; i < 2; i++) {
+		val = ocotp[i * 4];
+		mx28_fec_pdata[i].mac[0] = 0x00;
+		mx28_fec_pdata[i].mac[1] = 0x04;
+		mx28_fec_pdata[i].mac[2] = 0x9f;
+		mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+		mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+		mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+	}
+
+	return 0;
+
+error:
+	pr_err("%s: timeout when reading fec mac from OCOTP\n", __func__);
+	return -ETIMEDOUT;
+}
+
+/*
+ * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers
+ */
+static int flexcan0_en, flexcan1_en;
+
+static void mx28evk_flexcan_switch(void)
+{
+	if (flexcan0_en || flexcan1_en)
+		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1);
+	else
+		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0);
+}
+
+static void mx28evk_flexcan0_switch(int enable)
+{
+	flexcan0_en = enable;
+	mx28evk_flexcan_switch();
+}
+
+static void mx28evk_flexcan1_switch(int enable)
+{
+	flexcan1_en = enable;
+	mx28evk_flexcan_switch();
+}
+
+static const struct flexcan_platform_data
+		mx28evk_flexcan_pdata[] __initconst = {
+	{
+		.transceiver_switch = mx28evk_flexcan0_switch,
+	}, {
+		.transceiver_switch = mx28evk_flexcan1_switch,
+	}
+};
+
+/* mxsfb (lcdif) */
+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,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
+				  FB_SYNC_DOTCLK_FAILING_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data mx28evk_mxsfb_pdata __initconst = {
+	.mode_list	= mx28evk_video_modes,
+	.mode_count	= ARRAY_SIZE(mx28evk_video_modes),
+	.default_bpp	= 32,
+	.ld_intf_width	= STMLCDIF_24BIT,
+};
+
 static void __init mx28evk_init(void)
 {
+	int ret;
+
 	mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
 
 	mx28_add_duart();
+	mx28_add_auart0();
+	mx28_add_auart3();
+
+	if (mx28evk_fec_get_mac())
+		pr_warn("%s: failed on fec mac setup\n", __func__);
 
 	mx28evk_fec_reset();
 	mx28_add_fec(0, &mx28_fec_pdata[0]);
 	mx28_add_fec(1, &mx28_fec_pdata[1]);
+
+	ret = gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT,
+				"flexcan-switch");
+	if (ret) {
+		pr_err("failed to request gpio flexcan-switch: %d\n", ret);
+	} else {
+		mx28_add_flexcan(0, &mx28evk_flexcan_pdata[0]);
+		mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
+	}
+
+	ret = gpio_request_one(MX28EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	if (ret)
+		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+	else
+		gpio_set_value(MX28EVK_LCD_ENABLE, 1);
+
+	ret = gpio_request_one(MX28EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
+	if (ret)
+		pr_warn("failed to request gpio bl-enable: %d\n", ret);
+	else
+		gpio_set_value(MX28EVK_BL_ENABLE, 1);
+
+	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 }
 
 static void __init mx28evk_timer_init(void)
diff --git a/arch/arm/mach-mxs/mach-tx28.c b/arch/arm/mach-mxs/mach-tx28.c
new file mode 100644
index 0000000..b65e371
--- /dev/null
+++ b/arch/arm/mach-mxs/mach-tx28.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2010 <LW@KARO-electronics.de>
+ *
+ * based on: mach-mx28_evk.c
+ * 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
+ * version 2 as published by the Free Software Foundation
+ */
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/i2c.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+#include "module-tx28.h"
+
+#define TX28_STK5_GPIO_LED		MXS_GPIO_NR(4, 10)
+
+static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 |
+		MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL,
+
+	/* framebuffer */
+#define LCD_MODE (MXS_PAD_3V3 | MXS_PAD_4MA)
+	MX28_PAD_LCD_D00__LCD_D0 | LCD_MODE,
+	MX28_PAD_LCD_D01__LCD_D1 | LCD_MODE,
+	MX28_PAD_LCD_D02__LCD_D2 | LCD_MODE,
+	MX28_PAD_LCD_D03__LCD_D3 | LCD_MODE,
+	MX28_PAD_LCD_D04__LCD_D4 | LCD_MODE,
+	MX28_PAD_LCD_D05__LCD_D5 | LCD_MODE,
+	MX28_PAD_LCD_D06__LCD_D6 | LCD_MODE,
+	MX28_PAD_LCD_D07__LCD_D7 | LCD_MODE,
+	MX28_PAD_LCD_D08__LCD_D8 | LCD_MODE,
+	MX28_PAD_LCD_D09__LCD_D9 | LCD_MODE,
+	MX28_PAD_LCD_D10__LCD_D10 | LCD_MODE,
+	MX28_PAD_LCD_D11__LCD_D11 | LCD_MODE,
+	MX28_PAD_LCD_D12__LCD_D12 | LCD_MODE,
+	MX28_PAD_LCD_D13__LCD_D13 | LCD_MODE,
+	MX28_PAD_LCD_D14__LCD_D14 | LCD_MODE,
+	MX28_PAD_LCD_D15__LCD_D15 | LCD_MODE,
+	MX28_PAD_LCD_D16__LCD_D16 | LCD_MODE,
+	MX28_PAD_LCD_D17__LCD_D17 | LCD_MODE,
+	MX28_PAD_LCD_D18__LCD_D18 | LCD_MODE,
+	MX28_PAD_LCD_D19__LCD_D19 | LCD_MODE,
+	MX28_PAD_LCD_D20__LCD_D20 | LCD_MODE,
+	MX28_PAD_LCD_D21__LCD_D21 | LCD_MODE,
+	MX28_PAD_LCD_D22__LCD_D22 | LCD_MODE,
+	MX28_PAD_LCD_D23__LCD_D23 | LCD_MODE,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | LCD_MODE,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | LCD_MODE,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | LCD_MODE,
+	MX28_PAD_LCD_CS__LCD_CS | LCD_MODE,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | LCD_MODE,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | LCD_MODE,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | LCD_MODE,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | LCD_MODE,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | LCD_MODE,
+	MX28_PAD_PWM0__PWM_0 | LCD_MODE,
+
+	/* UART1 */
+	MX28_PAD_AUART0_CTS__DUART_RX,
+	MX28_PAD_AUART0_RTS__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA1__SSP0_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA2__SSP0_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA3__SSP0_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA4__SSP0_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA5__SSP0_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA6__SSP0_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA7__SSP0_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_CMD__SSP0_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+};
+
+static struct gpio_led tx28_stk5v3_leds[] = {
+	{
+		.name = "GPIO-LED",
+		.default_trigger = "heartbeat",
+		.gpio = TX28_STK5_GPIO_LED,
+	},
+};
+
+static const struct gpio_led_platform_data tx28_stk5v3_led_data __initconst = {
+	.leds = tx28_stk5v3_leds,
+	.num_leds = ARRAY_SIZE(tx28_stk5v3_leds),
+};
+
+static struct spi_board_info tx28_spi_board_info[] = {
+	{
+		.modalias = "spidev",
+		.max_speed_hz = 20000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.controller_data = (void *)SPI_GPIO_NO_CHIPSELECT,
+		.mode = SPI_MODE_0,
+	},
+};
+
+static struct i2c_board_info tx28_stk5v3_i2c_boardinfo[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1339", 0x68),
+	},
+};
+
+static void __init tx28_stk5v3_init(void)
+{
+	mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
+			ARRAY_SIZE(tx28_stk5v3_pads));
+
+	mx28_add_duart(); /* UART1 */
+	mx28_add_auart(1); /* UART2 */
+
+	tx28_add_fec0();
+	/* spi via ssp will be added when available */
+	spi_register_board_info(tx28_spi_board_info,
+			ARRAY_SIZE(tx28_spi_board_info));
+	mxs_add_platform_device("leds-gpio", 0, NULL, 0,
+			&tx28_stk5v3_led_data, sizeof(tx28_stk5v3_led_data));
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
+			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
+}
+
+static void __init tx28_timer_init(void)
+{
+	mx28_clocks_init();
+}
+
+static struct sys_timer tx28_timer = {
+	.init = tx28_timer_init,
+};
+
+MACHINE_START(TX28, "Ka-Ro electronics TX28 module")
+	.map_io = mx28_map_io,
+	.init_irq = mx28_init_irq,
+	.init_machine = tx28_stk5v3_init,
+	.timer = &tx28_timer,
+MACHINE_END
diff --git a/arch/arm/mach-mxs/module-tx28.c b/arch/arm/mach-mxs/module-tx28.c
new file mode 100644
index 0000000..fa0b154
--- /dev/null
+++ b/arch/arm/mach-mxs/module-tx28.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2010 <LW@KARO-electronics.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/fec.h>
+#include <linux/gpio.h>
+
+#include <mach/iomux-mx28.h>
+#include "../devices-mx28.h"
+
+#include "module-tx28.h"
+
+#define TX28_FEC_PHY_POWER	MXS_GPIO_NR(3, 29)
+#define TX28_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
+
+static const iomux_cfg_t tx28_fec_gpio_pads[] __initconst = {
+	/* PHY POWER */
+	MX28_PAD_PWM4__GPIO_3_29 |
+		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
+	/* PHY RESET */
+	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
+		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
+	/* Mode strap pins 0-2 */
+	MX28_PAD_ENET0_RXD0__GPIO_4_3 |
+		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
+	MX28_PAD_ENET0_RXD1__GPIO_4_4 |
+		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
+	MX28_PAD_ENET0_RX_EN__GPIO_4_2 |
+		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
+	/* nINT */
+	MX28_PAD_ENET0_TX_CLK__GPIO_4_5 |
+		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
+
+	MX28_PAD_ENET0_MDC__GPIO_4_0,
+	MX28_PAD_ENET0_MDIO__GPIO_4_1,
+	MX28_PAD_ENET0_TX_EN__GPIO_4_6,
+	MX28_PAD_ENET0_TXD0__GPIO_4_7,
+	MX28_PAD_ENET0_TXD1__GPIO_4_8,
+	MX28_PAD_ENET_CLK__GPIO_4_16,
+};
+
+#define FEC_MODE (MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3)
+static const iomux_cfg_t tx28_fec_pads[] __initconst = {
+	MX28_PAD_ENET0_MDC__ENET0_MDC | FEC_MODE,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | FEC_MODE,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | FEC_MODE,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | FEC_MODE,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | FEC_MODE,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | FEC_MODE,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | FEC_MODE,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | FEC_MODE,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | FEC_MODE,
+};
+
+static const struct fec_platform_data tx28_fec_data __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+int __init tx28_add_fec0(void)
+{
+	int i, ret;
+
+	pr_debug("%s: Switching FEC PHY power off\n", __func__);
+	ret = mxs_iomux_setup_multiple_pads(tx28_fec_gpio_pads,
+			ARRAY_SIZE(tx28_fec_gpio_pads));
+	for (i = 0; i < ARRAY_SIZE(tx28_fec_gpio_pads); i++) {
+		unsigned int gpio = MXS_GPIO_NR(PAD_BANK(tx28_fec_gpio_pads[i]),
+			PAD_PIN(tx28_fec_gpio_pads[i]));
+
+		ret = gpio_request(gpio, "FEC");
+		if (ret) {
+			pr_err("Failed to request GPIO_%d_%d: %d\n",
+				PAD_BANK(tx28_fec_gpio_pads[i]),
+				PAD_PIN(tx28_fec_gpio_pads[i]), ret);
+			goto free_gpios;
+		}
+		ret = gpio_direction_output(gpio, 0);
+		if (ret) {
+			pr_err("Failed to set direction of GPIO_%d_%d to output: %d\n",
+					gpio / 32 + 1, gpio % 32, ret);
+			goto free_gpios;
+		}
+	}
+
+	/* Power up fec phy */
+	pr_debug("%s: Switching FEC PHY power on\n", __func__);
+	ret = gpio_direction_output(TX28_FEC_PHY_POWER, 1);
+	if (ret) {
+		pr_err("Failed to power on PHY: %d\n", ret);
+		goto free_gpios;
+	}
+	mdelay(26); /* 25ms according to data sheet */
+
+	/* nINT */
+	gpio_direction_input(MXS_GPIO_NR(4, 5));
+	/* Mode strap pins */
+	gpio_direction_output(MXS_GPIO_NR(4, 2), 1);
+	gpio_direction_output(MXS_GPIO_NR(4, 3), 1);
+	gpio_direction_output(MXS_GPIO_NR(4, 4), 1);
+
+	udelay(100); /* minimum assertion time for nRST */
+
+	pr_debug("%s: Deasserting FEC PHY RESET\n", __func__);
+	gpio_set_value(TX28_FEC_PHY_RESET, 1);
+
+	ret = mxs_iomux_setup_multiple_pads(tx28_fec_pads,
+			ARRAY_SIZE(tx28_fec_pads));
+	if (ret) {
+		pr_debug("%s: mxs_iomux_setup_multiple_pads() failed with rc: %d\n",
+				__func__, ret);
+		goto free_gpios;
+	}
+	pr_debug("%s: Registering FEC device\n", __func__);
+	mx28_add_fec(0, &tx28_fec_data);
+	return 0;
+
+free_gpios:
+	while (--i >= 0) {
+		unsigned int gpio = MXS_GPIO_NR(PAD_BANK(tx28_fec_gpio_pads[i]),
+			PAD_PIN(tx28_fec_gpio_pads[i]));
+
+		gpio_free(gpio);
+	}
+
+	return ret;
+}
diff --git a/arch/arm/mach-mxs/module-tx28.h b/arch/arm/mach-mxs/module-tx28.h
new file mode 100644
index 0000000..df9e1b6
--- /dev/null
+++ b/arch/arm/mach-mxs/module-tx28.h
@@ -0,0 +1,9 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ *   Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
+ */
+int __init tx28_add_fec0(void);
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
new file mode 100644
index 0000000..65157a3
--- /dev/null
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -0,0 +1,90 @@
+/*
+ * 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 <mach/mxs.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
new file mode 100644
index 0000000..fb042da
--- /dev/null
+++ b/arch/arm/mach-mxs/pm.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/suspend.h>
+#include <linux/io.h>
+#include <mach/system.h>
+
+static int mxs_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		arch_idle();
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct platform_suspend_ops mxs_suspend_ops = {
+	.enter = mxs_suspend_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __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/regs-clkctrl-mx23.h b/arch/arm/mach-mxs/regs-clkctrl-mx23.h
index dbc0474..0ea5c9d 100644
--- a/arch/arm/mach-mxs/regs-clkctrl-mx23.h
+++ b/arch/arm/mach-mxs/regs-clkctrl-mx23.h
@@ -33,10 +33,6 @@
 #define HW_CLKCTRL_PLLCTRL0_CLR	(0x00000008)
 #define HW_CLKCTRL_PLLCTRL0_TOG	(0x0000000c)
 
-#define BP_CLKCTRL_PLLCTRL0_RSRVD6	30
-#define BM_CLKCTRL_PLLCTRL0_RSRVD6	0xC0000000
-#define BF_CLKCTRL_PLLCTRL0_RSRVD6(v) \
-		(((v) << 30) & BM_CLKCTRL_PLLCTRL0_RSRVD6)
 #define BP_CLKCTRL_PLLCTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLLCTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLLCTRL0_LFR_SEL(v)  \
@@ -45,10 +41,6 @@
 #define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLLCTRL0_LFR_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLLCTRL0_RSRVD5	26
-#define BM_CLKCTRL_PLLCTRL0_RSRVD5	0x0C000000
-#define BF_CLKCTRL_PLLCTRL0_RSRVD5(v)  \
-		(((v) << 26) & BM_CLKCTRL_PLLCTRL0_RSRVD5)
 #define BP_CLKCTRL_PLLCTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLLCTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLLCTRL0_CP_SEL(v)  \
@@ -57,10 +49,6 @@
 #define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLLCTRL0_CP_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLLCTRL0_RSRVD4	22
-#define BM_CLKCTRL_PLLCTRL0_RSRVD4	0x00C00000
-#define BF_CLKCTRL_PLLCTRL0_RSRVD4(v)  \
-		(((v) << 22) & BM_CLKCTRL_PLLCTRL0_RSRVD4)
 #define BP_CLKCTRL_PLLCTRL0_DIV_SEL	20
 #define BM_CLKCTRL_PLLCTRL0_DIV_SEL	0x00300000
 #define BF_CLKCTRL_PLLCTRL0_DIV_SEL(v)  \
@@ -69,23 +57,13 @@
 #define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWER     0x1
 #define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWEST    0x2
 #define BV_CLKCTRL_PLLCTRL0_DIV_SEL__UNDEFINED 0x3
-#define BM_CLKCTRL_PLLCTRL0_RSRVD3	0x00080000
 #define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS	0x00040000
-#define BM_CLKCTRL_PLLCTRL0_RSRVD2	0x00020000
 #define BM_CLKCTRL_PLLCTRL0_POWER	0x00010000
-#define BP_CLKCTRL_PLLCTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLLCTRL0_RSRVD1	0x0000FFFF
-#define BF_CLKCTRL_PLLCTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLLCTRL0_RSRVD1)
 
 #define HW_CLKCTRL_PLLCTRL1	(0x00000010)
 
 #define BM_CLKCTRL_PLLCTRL1_LOCK	0x80000000
 #define BM_CLKCTRL_PLLCTRL1_FORCE_LOCK	0x40000000
-#define BP_CLKCTRL_PLLCTRL1_RSRVD1	16
-#define BM_CLKCTRL_PLLCTRL1_RSRVD1	0x3FFF0000
-#define BF_CLKCTRL_PLLCTRL1_RSRVD1(v)  \
-		(((v) << 16) & BM_CLKCTRL_PLLCTRL1_RSRVD1)
 #define BP_CLKCTRL_PLLCTRL1_LOCK_COUNT	0
 #define BM_CLKCTRL_PLLCTRL1_LOCK_COUNT	0x0000FFFF
 #define BF_CLKCTRL_PLLCTRL1_LOCK_COUNT(v)  \
@@ -96,29 +74,15 @@
 #define HW_CLKCTRL_CPU_CLR	(0x00000028)
 #define HW_CLKCTRL_CPU_TOG	(0x0000002c)
 
-#define BP_CLKCTRL_CPU_RSRVD5	30
-#define BM_CLKCTRL_CPU_RSRVD5	0xC0000000
-#define BF_CLKCTRL_CPU_RSRVD5(v) \
-		(((v) << 30) & BM_CLKCTRL_CPU_RSRVD5)
 #define BM_CLKCTRL_CPU_BUSY_REF_XTAL	0x20000000
 #define BM_CLKCTRL_CPU_BUSY_REF_CPU	0x10000000
-#define BM_CLKCTRL_CPU_RSRVD4	0x08000000
 #define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN	0x04000000
 #define BP_CLKCTRL_CPU_DIV_XTAL	16
 #define BM_CLKCTRL_CPU_DIV_XTAL	0x03FF0000
 #define BF_CLKCTRL_CPU_DIV_XTAL(v)  \
 		(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
-#define BP_CLKCTRL_CPU_RSRVD3	13
-#define BM_CLKCTRL_CPU_RSRVD3	0x0000E000
-#define BF_CLKCTRL_CPU_RSRVD3(v)  \
-		(((v) << 13) & BM_CLKCTRL_CPU_RSRVD3)
 #define BM_CLKCTRL_CPU_INTERRUPT_WAIT	0x00001000
-#define BM_CLKCTRL_CPU_RSRVD2	0x00000800
 #define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN	0x00000400
-#define BP_CLKCTRL_CPU_RSRVD1	6
-#define BM_CLKCTRL_CPU_RSRVD1	0x000003C0
-#define BF_CLKCTRL_CPU_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_CPU_RSRVD1)
 #define BP_CLKCTRL_CPU_DIV_CPU	0
 #define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
 #define BF_CLKCTRL_CPU_DIV_CPU(v)  \
@@ -129,10 +93,6 @@
 #define HW_CLKCTRL_HBUS_CLR	(0x00000038)
 #define HW_CLKCTRL_HBUS_TOG	(0x0000003c)
 
-#define BP_CLKCTRL_HBUS_RSRVD4	30
-#define BM_CLKCTRL_HBUS_RSRVD4	0xC0000000
-#define BF_CLKCTRL_HBUS_RSRVD4(v) \
-		(((v) << 30) & BM_CLKCTRL_HBUS_RSRVD4)
 #define BM_CLKCTRL_HBUS_BUSY	0x20000000
 #define BM_CLKCTRL_HBUS_DCP_AS_ENABLE	0x10000000
 #define BM_CLKCTRL_HBUS_PXP_AS_ENABLE	0x08000000
@@ -143,7 +103,6 @@
 #define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE	0x00400000
 #define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	0x00200000
 #define BM_CLKCTRL_HBUS_AUTO_SLOW_MODE	0x00100000
-#define BM_CLKCTRL_HBUS_RSRVD2	0x00080000
 #define BP_CLKCTRL_HBUS_SLOW_DIV	16
 #define BM_CLKCTRL_HBUS_SLOW_DIV	0x00070000
 #define BF_CLKCTRL_HBUS_SLOW_DIV(v)  \
@@ -154,10 +113,6 @@
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY8  0x3
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
-#define BP_CLKCTRL_HBUS_RSRVD1	6
-#define BM_CLKCTRL_HBUS_RSRVD1	0x0000FFC0
-#define BF_CLKCTRL_HBUS_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_HBUS_RSRVD1)
 #define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
 #define BP_CLKCTRL_HBUS_DIV	0
 #define BM_CLKCTRL_HBUS_DIV	0x0000001F
@@ -167,10 +122,6 @@
 #define HW_CLKCTRL_XBUS	(0x00000040)
 
 #define BM_CLKCTRL_XBUS_BUSY	0x80000000
-#define BP_CLKCTRL_XBUS_RSRVD1	11
-#define BM_CLKCTRL_XBUS_RSRVD1	0x7FFFF800
-#define BF_CLKCTRL_XBUS_RSRVD1(v)  \
-		(((v) << 11) & BM_CLKCTRL_XBUS_RSRVD1)
 #define BM_CLKCTRL_XBUS_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_XBUS_DIV	0
 #define BM_CLKCTRL_XBUS_DIV	0x000003FF
@@ -192,10 +143,6 @@
 #define BM_CLKCTRL_XTAL_DIGCTRL_CLK1M_GATE	0x08000000
 #define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	26
 #define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	0x04000000
-#define BP_CLKCTRL_XTAL_RSRVD1	2
-#define BM_CLKCTRL_XTAL_RSRVD1	0x03FFFFFC
-#define BF_CLKCTRL_XTAL_RSRVD1(v)  \
-		(((v) << 2) & BM_CLKCTRL_XTAL_RSRVD1)
 #define BP_CLKCTRL_XTAL_DIV_UART	0
 #define BM_CLKCTRL_XTAL_DIV_UART	0x00000003
 #define BF_CLKCTRL_XTAL_DIV_UART(v)  \
@@ -205,12 +152,7 @@
 
 #define BP_CLKCTRL_PIX_CLKGATE	31
 #define BM_CLKCTRL_PIX_CLKGATE	0x80000000
-#define BM_CLKCTRL_PIX_RSRVD2	0x40000000
 #define BM_CLKCTRL_PIX_BUSY	0x20000000
-#define BP_CLKCTRL_PIX_RSRVD1	13
-#define BM_CLKCTRL_PIX_RSRVD1	0x1FFFE000
-#define BF_CLKCTRL_PIX_RSRVD1(v)  \
-		(((v) << 13) & BM_CLKCTRL_PIX_RSRVD1)
 #define BM_CLKCTRL_PIX_DIV_FRAC_EN	0x00001000
 #define BP_CLKCTRL_PIX_DIV	0
 #define BM_CLKCTRL_PIX_DIV	0x00000FFF
@@ -221,12 +163,7 @@
 
 #define BP_CLKCTRL_SSP_CLKGATE	31
 #define BM_CLKCTRL_SSP_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP_BUSY	0x20000000
-#define BP_CLKCTRL_SSP_RSRVD1	10
-#define BM_CLKCTRL_SSP_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP_RSRVD1)
 #define BM_CLKCTRL_SSP_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP_DIV	0
 #define BM_CLKCTRL_SSP_DIV	0x000001FF
@@ -237,12 +174,7 @@
 
 #define BP_CLKCTRL_GPMI_CLKGATE	31
 #define BM_CLKCTRL_GPMI_CLKGATE	0x80000000
-#define BM_CLKCTRL_GPMI_RSRVD2	0x40000000
 #define BM_CLKCTRL_GPMI_BUSY	0x20000000
-#define BP_CLKCTRL_GPMI_RSRVD1	11
-#define BM_CLKCTRL_GPMI_RSRVD1	0x1FFFF800
-#define BF_CLKCTRL_GPMI_RSRVD1(v)  \
-		(((v) << 11) & BM_CLKCTRL_GPMI_RSRVD1)
 #define BM_CLKCTRL_GPMI_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_GPMI_DIV	0
 #define BM_CLKCTRL_GPMI_DIV	0x000003FF
@@ -252,10 +184,6 @@
 #define HW_CLKCTRL_SPDIF	(0x00000090)
 
 #define BM_CLKCTRL_SPDIF_CLKGATE	0x80000000
-#define BP_CLKCTRL_SPDIF_RSRVD	0
-#define BM_CLKCTRL_SPDIF_RSRVD	0x7FFFFFFF
-#define BF_CLKCTRL_SPDIF_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_SPDIF_RSRVD)
 
 #define HW_CLKCTRL_EMI	(0x000000a0)
 
@@ -266,24 +194,12 @@
 #define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
 #define BM_CLKCTRL_EMI_BUSY_REF_CPU	0x08000000
 #define BM_CLKCTRL_EMI_BUSY_SYNC_MODE	0x04000000
-#define BP_CLKCTRL_EMI_RSRVD3	18
-#define BM_CLKCTRL_EMI_RSRVD3	0x03FC0000
-#define BF_CLKCTRL_EMI_RSRVD3(v)  \
-		(((v) << 18) & BM_CLKCTRL_EMI_RSRVD3)
 #define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
 #define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
-#define BP_CLKCTRL_EMI_RSRVD2	12
-#define BM_CLKCTRL_EMI_RSRVD2	0x0000F000
-#define BF_CLKCTRL_EMI_RSRVD2(v)  \
-		(((v) << 12) & BM_CLKCTRL_EMI_RSRVD2)
 #define BP_CLKCTRL_EMI_DIV_XTAL	8
 #define BM_CLKCTRL_EMI_DIV_XTAL	0x00000F00
 #define BF_CLKCTRL_EMI_DIV_XTAL(v)  \
 		(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
-#define BP_CLKCTRL_EMI_RSRVD1	6
-#define BM_CLKCTRL_EMI_RSRVD1	0x000000C0
-#define BF_CLKCTRL_EMI_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_EMI_RSRVD1)
 #define BP_CLKCTRL_EMI_DIV_EMI	0
 #define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
 #define BF_CLKCTRL_EMI_DIV_EMI(v)  \
@@ -292,22 +208,13 @@
 #define HW_CLKCTRL_IR	(0x000000b0)
 
 #define BM_CLKCTRL_IR_CLKGATE	0x80000000
-#define BM_CLKCTRL_IR_RSRVD3	0x40000000
 #define BM_CLKCTRL_IR_AUTO_DIV	0x20000000
 #define BM_CLKCTRL_IR_IR_BUSY	0x10000000
 #define BM_CLKCTRL_IR_IROV_BUSY	0x08000000
-#define BP_CLKCTRL_IR_RSRVD2	25
-#define BM_CLKCTRL_IR_RSRVD2	0x06000000
-#define BF_CLKCTRL_IR_RSRVD2(v)  \
-		(((v) << 25) & BM_CLKCTRL_IR_RSRVD2)
 #define BP_CLKCTRL_IR_IROV_DIV	16
 #define BM_CLKCTRL_IR_IROV_DIV	0x01FF0000
 #define BF_CLKCTRL_IR_IROV_DIV(v)  \
 		(((v) << 16) & BM_CLKCTRL_IR_IROV_DIV)
-#define BP_CLKCTRL_IR_RSRVD1	10
-#define BM_CLKCTRL_IR_RSRVD1	0x0000FC00
-#define BF_CLKCTRL_IR_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_IR_RSRVD1)
 #define BP_CLKCTRL_IR_IR_DIV	0
 #define BM_CLKCTRL_IR_IR_DIV	0x000003FF
 #define BF_CLKCTRL_IR_IR_DIV(v)  \
@@ -316,12 +223,7 @@
 #define HW_CLKCTRL_SAIF	(0x000000c0)
 
 #define BM_CLKCTRL_SAIF_CLKGATE	0x80000000
-#define BM_CLKCTRL_SAIF_RSRVD2	0x40000000
 #define BM_CLKCTRL_SAIF_BUSY	0x20000000
-#define BP_CLKCTRL_SAIF_RSRVD1	17
-#define BM_CLKCTRL_SAIF_RSRVD1	0x1FFE0000
-#define BF_CLKCTRL_SAIF_RSRVD1(v)  \
-		(((v) << 17) & BM_CLKCTRL_SAIF_RSRVD1)
 #define BM_CLKCTRL_SAIF_DIV_FRAC_EN	0x00010000
 #define BP_CLKCTRL_SAIF_DIV	0
 #define BM_CLKCTRL_SAIF_DIV	0x0000FFFF
@@ -332,20 +234,11 @@
 
 #define BM_CLKCTRL_TV_CLK_TV108M_GATE	0x80000000
 #define BM_CLKCTRL_TV_CLK_TV_GATE	0x40000000
-#define BP_CLKCTRL_TV_RSRVD	0
-#define BM_CLKCTRL_TV_RSRVD	0x3FFFFFFF
-#define BF_CLKCTRL_TV_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_TV_RSRVD)
 
 #define HW_CLKCTRL_ETM	(0x000000e0)
 
 #define BM_CLKCTRL_ETM_CLKGATE	0x80000000
-#define BM_CLKCTRL_ETM_RSRVD2	0x40000000
 #define BM_CLKCTRL_ETM_BUSY	0x20000000
-#define BP_CLKCTRL_ETM_RSRVD1	7
-#define BM_CLKCTRL_ETM_RSRVD1	0x1FFFFF80
-#define BF_CLKCTRL_ETM_RSRVD1(v)  \
-		(((v) << 7) & BM_CLKCTRL_ETM_RSRVD1)
 #define BM_CLKCTRL_ETM_DIV_FRAC_EN	0x00000040
 #define BP_CLKCTRL_ETM_DIV	0
 #define BM_CLKCTRL_ETM_DIV	0x0000003F
@@ -393,36 +286,23 @@
 
 #define BM_CLKCTRL_FRAC1_CLKGATEVID	0x80000000
 #define BM_CLKCTRL_FRAC1_VID_STABLE	0x40000000
-#define BP_CLKCTRL_FRAC1_RSRVD1	0
-#define BM_CLKCTRL_FRAC1_RSRVD1	0x3FFFFFFF
-#define BF_CLKCTRL_FRAC1_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_FRAC1_RSRVD1)
 
 #define HW_CLKCTRL_CLKSEQ	(0x00000110)
 #define HW_CLKCTRL_CLKSEQ_SET	(0x00000114)
 #define HW_CLKCTRL_CLKSEQ_CLR	(0x00000118)
 #define HW_CLKCTRL_CLKSEQ_TOG	(0x0000011c)
 
-#define BP_CLKCTRL_CLKSEQ_RSRVD1	9
-#define BM_CLKCTRL_CLKSEQ_RSRVD1	0xFFFFFE00
-#define BF_CLKCTRL_CLKSEQ_RSRVD1(v) \
-		(((v) << 9) & BM_CLKCTRL_CLKSEQ_RSRVD1)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_ETM	0x00000100
 #define BM_CLKCTRL_CLKSEQ_BYPASS_CPU	0x00000080
 #define BM_CLKCTRL_CLKSEQ_BYPASS_EMI	0x00000040
 #define BM_CLKCTRL_CLKSEQ_BYPASS_SSP	0x00000020
 #define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI	0x00000010
 #define BM_CLKCTRL_CLKSEQ_BYPASS_IR	0x00000008
-#define BM_CLKCTRL_CLKSEQ_RSRVD0	0x00000004
 #define BM_CLKCTRL_CLKSEQ_BYPASS_PIX	0x00000002
 #define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF	0x00000001
 
 #define HW_CLKCTRL_RESET	(0x00000120)
 
-#define BP_CLKCTRL_RESET_RSRVD	2
-#define BM_CLKCTRL_RESET_RSRVD	0xFFFFFFFC
-#define BF_CLKCTRL_RESET_RSRVD(v) \
-		(((v) << 2) & BM_CLKCTRL_RESET_RSRVD)
 #define BM_CLKCTRL_RESET_CHIP	0x00000002
 #define BM_CLKCTRL_RESET_DIG	0x00000001
 
@@ -432,10 +312,6 @@
 #define BM_CLKCTRL_STATUS_CPU_LIMIT	0xC0000000
 #define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
 		(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
-#define BP_CLKCTRL_STATUS_RSRVD	0
-#define BM_CLKCTRL_STATUS_RSRVD	0x3FFFFFFF
-#define BF_CLKCTRL_STATUS_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_STATUS_RSRVD)
 
 #define HW_CLKCTRL_VERSION	(0x00000140)
 
diff --git a/arch/arm/mach-mxs/regs-clkctrl-mx28.h b/arch/arm/mach-mxs/regs-clkctrl-mx28.h
index 661df18..7d1b061 100644
--- a/arch/arm/mach-mxs/regs-clkctrl-mx28.h
+++ b/arch/arm/mach-mxs/regs-clkctrl-mx28.h
@@ -31,10 +31,6 @@
 #define HW_CLKCTRL_PLL0CTRL0_CLR	(0x00000008)
 #define HW_CLKCTRL_PLL0CTRL0_TOG	(0x0000000c)
 
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD6	30
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD6	0xC0000000
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD6(v) \
-		(((v) << 30) & BM_CLKCTRL_PLL0CTRL0_RSRVD6)
 #define BP_CLKCTRL_PLL0CTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLL0CTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLL0CTRL0_LFR_SEL(v)  \
@@ -43,10 +39,6 @@
 #define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD5	26
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD5	0x0C000000
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD5(v)  \
-		(((v) << 26) & BM_CLKCTRL_PLL0CTRL0_RSRVD5)
 #define BP_CLKCTRL_PLL0CTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLL0CTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLL0CTRL0_CP_SEL(v)  \
@@ -55,10 +47,6 @@
 #define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL0CTRL0_CP_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD4	22
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD4	0x00C00000
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD4(v)  \
-		(((v) << 22) & BM_CLKCTRL_PLL0CTRL0_RSRVD4)
 #define BP_CLKCTRL_PLL0CTRL0_DIV_SEL	20
 #define BM_CLKCTRL_PLL0CTRL0_DIV_SEL	0x00300000
 #define BF_CLKCTRL_PLL0CTRL0_DIV_SEL(v)  \
@@ -67,22 +55,13 @@
 #define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWER     0x1
 #define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWEST    0x2
 #define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__UNDEFINED 0x3
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD3	0x00080000
 #define BM_CLKCTRL_PLL0CTRL0_EN_USB_CLKS	0x00040000
 #define BM_CLKCTRL_PLL0CTRL0_POWER	0x00020000
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD1	0x0001FFFF
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLL0CTRL0_RSRVD1)
 
 #define HW_CLKCTRL_PLL0CTRL1	(0x00000010)
 
 #define BM_CLKCTRL_PLL0CTRL1_LOCK	0x80000000
 #define BM_CLKCTRL_PLL0CTRL1_FORCE_LOCK	0x40000000
-#define BP_CLKCTRL_PLL0CTRL1_RSRVD1	16
-#define BM_CLKCTRL_PLL0CTRL1_RSRVD1	0x3FFF0000
-#define BF_CLKCTRL_PLL0CTRL1_RSRVD1(v)  \
-		(((v) << 16) & BM_CLKCTRL_PLL0CTRL1_RSRVD1)
 #define BP_CLKCTRL_PLL0CTRL1_LOCK_COUNT	0
 #define BM_CLKCTRL_PLL0CTRL1_LOCK_COUNT	0x0000FFFF
 #define BF_CLKCTRL_PLL0CTRL1_LOCK_COUNT(v)  \
@@ -94,7 +73,6 @@
 #define HW_CLKCTRL_PLL1CTRL0_TOG	(0x0000002c)
 
 #define BM_CLKCTRL_PLL1CTRL0_CLKGATEEMI	0x80000000
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD6	0x40000000
 #define BP_CLKCTRL_PLL1CTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLL1CTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLL1CTRL0_LFR_SEL(v)  \
@@ -103,10 +81,6 @@
 #define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL1CTRL0_RSRVD5	26
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD5	0x0C000000
-#define BF_CLKCTRL_PLL1CTRL0_RSRVD5(v)  \
-		(((v) << 26) & BM_CLKCTRL_PLL1CTRL0_RSRVD5)
 #define BP_CLKCTRL_PLL1CTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLL1CTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLL1CTRL0_CP_SEL(v)  \
@@ -115,10 +89,6 @@
 #define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL1CTRL0_CP_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL1CTRL0_RSRVD4	22
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD4	0x00C00000
-#define BF_CLKCTRL_PLL1CTRL0_RSRVD4(v)  \
-		(((v) << 22) & BM_CLKCTRL_PLL1CTRL0_RSRVD4)
 #define BP_CLKCTRL_PLL1CTRL0_DIV_SEL	20
 #define BM_CLKCTRL_PLL1CTRL0_DIV_SEL	0x00300000
 #define BF_CLKCTRL_PLL1CTRL0_DIV_SEL(v)  \
@@ -127,22 +97,13 @@
 #define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWER     0x1
 #define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWEST    0x2
 #define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__UNDEFINED 0x3
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD3	0x00080000
 #define BM_CLKCTRL_PLL1CTRL0_EN_USB_CLKS	0x00040000
 #define BM_CLKCTRL_PLL1CTRL0_POWER	0x00020000
-#define BP_CLKCTRL_PLL1CTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD1	0x0001FFFF
-#define BF_CLKCTRL_PLL1CTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLL1CTRL0_RSRVD1)
 
 #define HW_CLKCTRL_PLL1CTRL1	(0x00000030)
 
 #define BM_CLKCTRL_PLL1CTRL1_LOCK	0x80000000
 #define BM_CLKCTRL_PLL1CTRL1_FORCE_LOCK	0x40000000
-#define BP_CLKCTRL_PLL1CTRL1_RSRVD1	16
-#define BM_CLKCTRL_PLL1CTRL1_RSRVD1	0x3FFF0000
-#define BF_CLKCTRL_PLL1CTRL1_RSRVD1(v)  \
-		(((v) << 16) & BM_CLKCTRL_PLL1CTRL1_RSRVD1)
 #define BP_CLKCTRL_PLL1CTRL1_LOCK_COUNT	0
 #define BM_CLKCTRL_PLL1CTRL1_LOCK_COUNT	0x0000FFFF
 #define BF_CLKCTRL_PLL1CTRL1_LOCK_COUNT(v)  \
@@ -154,51 +115,31 @@
 #define HW_CLKCTRL_PLL2CTRL0_TOG	(0x0000004c)
 
 #define BM_CLKCTRL_PLL2CTRL0_CLKGATE	0x80000000
-#define BM_CLKCTRL_PLL2CTRL0_RSRVD3	0x40000000
 #define BP_CLKCTRL_PLL2CTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLL2CTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLL2CTRL0_LFR_SEL(v)  \
 		(((v) << 28) & BM_CLKCTRL_PLL2CTRL0_LFR_SEL)
-#define BM_CLKCTRL_PLL2CTRL0_RSRVD2	0x08000000
 #define BM_CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	0x04000000
 #define BP_CLKCTRL_PLL2CTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLL2CTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLL2CTRL0_CP_SEL(v)  \
 		(((v) << 24) & BM_CLKCTRL_PLL2CTRL0_CP_SEL)
 #define BM_CLKCTRL_PLL2CTRL0_POWER	0x00800000
-#define BP_CLKCTRL_PLL2CTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLL2CTRL0_RSRVD1	0x007FFFFF
-#define BF_CLKCTRL_PLL2CTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLL2CTRL0_RSRVD1)
 
 #define HW_CLKCTRL_CPU	(0x00000050)
 #define HW_CLKCTRL_CPU_SET	(0x00000054)
 #define HW_CLKCTRL_CPU_CLR	(0x00000058)
 #define HW_CLKCTRL_CPU_TOG	(0x0000005c)
 
-#define BP_CLKCTRL_CPU_RSRVD5	30
-#define BM_CLKCTRL_CPU_RSRVD5	0xC0000000
-#define BF_CLKCTRL_CPU_RSRVD5(v) \
-		(((v) << 30) & BM_CLKCTRL_CPU_RSRVD5)
 #define BM_CLKCTRL_CPU_BUSY_REF_XTAL	0x20000000
 #define BM_CLKCTRL_CPU_BUSY_REF_CPU	0x10000000
-#define BM_CLKCTRL_CPU_RSRVD4	0x08000000
 #define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN	0x04000000
 #define BP_CLKCTRL_CPU_DIV_XTAL	16
 #define BM_CLKCTRL_CPU_DIV_XTAL	0x03FF0000
 #define BF_CLKCTRL_CPU_DIV_XTAL(v)  \
 		(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
-#define BP_CLKCTRL_CPU_RSRVD3	13
-#define BM_CLKCTRL_CPU_RSRVD3	0x0000E000
-#define BF_CLKCTRL_CPU_RSRVD3(v)  \
-		(((v) << 13) & BM_CLKCTRL_CPU_RSRVD3)
 #define BM_CLKCTRL_CPU_INTERRUPT_WAIT	0x00001000
-#define BM_CLKCTRL_CPU_RSRVD2	0x00000800
 #define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN	0x00000400
-#define BP_CLKCTRL_CPU_RSRVD1	6
-#define BM_CLKCTRL_CPU_RSRVD1	0x000003C0
-#define BF_CLKCTRL_CPU_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_CPU_RSRVD1)
 #define BP_CLKCTRL_CPU_DIV_CPU	0
 #define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
 #define BF_CLKCTRL_CPU_DIV_CPU(v)  \
@@ -212,7 +153,6 @@
 #define BM_CLKCTRL_HBUS_ASM_BUSY	0x80000000
 #define BM_CLKCTRL_HBUS_DCP_AS_ENABLE	0x40000000
 #define BM_CLKCTRL_HBUS_PXP_AS_ENABLE	0x20000000
-#define BM_CLKCTRL_HBUS_RSRVD2	0x10000000
 #define BM_CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	0x08000000
 #define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE	0x04000000
 #define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE	0x02000000
@@ -232,10 +172,6 @@
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY8  0x3
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
-#define BP_CLKCTRL_HBUS_RSRVD1	6
-#define BM_CLKCTRL_HBUS_RSRVD1	0x0000FFC0
-#define BF_CLKCTRL_HBUS_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_HBUS_RSRVD1)
 #define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
 #define BP_CLKCTRL_HBUS_DIV	0
 #define BM_CLKCTRL_HBUS_DIV	0x0000001F
@@ -245,10 +181,6 @@
 #define HW_CLKCTRL_XBUS	(0x00000070)
 
 #define BM_CLKCTRL_XBUS_BUSY	0x80000000
-#define BP_CLKCTRL_XBUS_RSRVD1	12
-#define BM_CLKCTRL_XBUS_RSRVD1	0x7FFFF000
-#define BF_CLKCTRL_XBUS_RSRVD1(v)  \
-		(((v) << 12) & BM_CLKCTRL_XBUS_RSRVD1)
 #define BM_CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	0x00000800
 #define BM_CLKCTRL_XBUS_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_XBUS_DIV	0
@@ -263,19 +195,10 @@
 
 #define BP_CLKCTRL_XTAL_UART_CLK_GATE	31
 #define BM_CLKCTRL_XTAL_UART_CLK_GATE	0x80000000
-#define BM_CLKCTRL_XTAL_RSRVD3	0x40000000
 #define BP_CLKCTRL_XTAL_PWM_CLK24M_GATE	29
 #define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE	0x20000000
-#define BP_CLKCTRL_XTAL_RSRVD2	27
-#define BM_CLKCTRL_XTAL_RSRVD2	0x18000000
-#define BF_CLKCTRL_XTAL_RSRVD2(v)  \
-		(((v) << 27) & BM_CLKCTRL_XTAL_RSRVD2)
 #define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	26
 #define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	0x04000000
-#define BP_CLKCTRL_XTAL_RSRVD1	2
-#define BM_CLKCTRL_XTAL_RSRVD1	0x03FFFFFC
-#define BF_CLKCTRL_XTAL_RSRVD1(v)  \
-		(((v) << 2) & BM_CLKCTRL_XTAL_RSRVD1)
 #define BP_CLKCTRL_XTAL_DIV_UART	0
 #define BM_CLKCTRL_XTAL_DIV_UART	0x00000003
 #define BF_CLKCTRL_XTAL_DIV_UART(v)  \
@@ -285,12 +208,7 @@
 
 #define BP_CLKCTRL_SSP0_CLKGATE	31
 #define BM_CLKCTRL_SSP0_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP0_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP0_BUSY	0x20000000
-#define BP_CLKCTRL_SSP0_RSRVD1	10
-#define BM_CLKCTRL_SSP0_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP0_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP0_RSRVD1)
 #define BM_CLKCTRL_SSP0_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP0_DIV	0
 #define BM_CLKCTRL_SSP0_DIV	0x000001FF
@@ -301,12 +219,7 @@
 
 #define BP_CLKCTRL_SSP1_CLKGATE	31
 #define BM_CLKCTRL_SSP1_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP1_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP1_BUSY	0x20000000
-#define BP_CLKCTRL_SSP1_RSRVD1	10
-#define BM_CLKCTRL_SSP1_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP1_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP1_RSRVD1)
 #define BM_CLKCTRL_SSP1_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP1_DIV	0
 #define BM_CLKCTRL_SSP1_DIV	0x000001FF
@@ -317,12 +230,7 @@
 
 #define BP_CLKCTRL_SSP2_CLKGATE	31
 #define BM_CLKCTRL_SSP2_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP2_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP2_BUSY	0x20000000
-#define BP_CLKCTRL_SSP2_RSRVD1	10
-#define BM_CLKCTRL_SSP2_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP2_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP2_RSRVD1)
 #define BM_CLKCTRL_SSP2_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP2_DIV	0
 #define BM_CLKCTRL_SSP2_DIV	0x000001FF
@@ -333,12 +241,7 @@
 
 #define BP_CLKCTRL_SSP3_CLKGATE	31
 #define BM_CLKCTRL_SSP3_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP3_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP3_BUSY	0x20000000
-#define BP_CLKCTRL_SSP3_RSRVD1	10
-#define BM_CLKCTRL_SSP3_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP3_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP3_RSRVD1)
 #define BM_CLKCTRL_SSP3_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP3_DIV	0
 #define BM_CLKCTRL_SSP3_DIV	0x000001FF
@@ -349,12 +252,7 @@
 
 #define BP_CLKCTRL_GPMI_CLKGATE	31
 #define BM_CLKCTRL_GPMI_CLKGATE	0x80000000
-#define BM_CLKCTRL_GPMI_RSRVD2	0x40000000
 #define BM_CLKCTRL_GPMI_BUSY	0x20000000
-#define BP_CLKCTRL_GPMI_RSRVD1	11
-#define BM_CLKCTRL_GPMI_RSRVD1	0x1FFFF800
-#define BF_CLKCTRL_GPMI_RSRVD1(v)  \
-		(((v) << 11) & BM_CLKCTRL_GPMI_RSRVD1)
 #define BM_CLKCTRL_GPMI_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_GPMI_DIV	0
 #define BM_CLKCTRL_GPMI_DIV	0x000003FF
@@ -365,10 +263,6 @@
 
 #define BP_CLKCTRL_SPDIF_CLKGATE	31
 #define BM_CLKCTRL_SPDIF_CLKGATE	0x80000000
-#define BP_CLKCTRL_SPDIF_RSRVD	0
-#define BM_CLKCTRL_SPDIF_RSRVD	0x7FFFFFFF
-#define BF_CLKCTRL_SPDIF_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_SPDIF_RSRVD)
 
 #define HW_CLKCTRL_EMI	(0x000000f0)
 
@@ -379,24 +273,12 @@
 #define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
 #define BM_CLKCTRL_EMI_BUSY_REF_CPU	0x08000000
 #define BM_CLKCTRL_EMI_BUSY_SYNC_MODE	0x04000000
-#define BP_CLKCTRL_EMI_RSRVD3	18
-#define BM_CLKCTRL_EMI_RSRVD3	0x03FC0000
-#define BF_CLKCTRL_EMI_RSRVD3(v)  \
-		(((v) << 18) & BM_CLKCTRL_EMI_RSRVD3)
 #define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
 #define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
-#define BP_CLKCTRL_EMI_RSRVD2	12
-#define BM_CLKCTRL_EMI_RSRVD2	0x0000F000
-#define BF_CLKCTRL_EMI_RSRVD2(v)  \
-		(((v) << 12) & BM_CLKCTRL_EMI_RSRVD2)
 #define BP_CLKCTRL_EMI_DIV_XTAL	8
 #define BM_CLKCTRL_EMI_DIV_XTAL	0x00000F00
 #define BF_CLKCTRL_EMI_DIV_XTAL(v)  \
 		(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
-#define BP_CLKCTRL_EMI_RSRVD1	6
-#define BM_CLKCTRL_EMI_RSRVD1	0x000000C0
-#define BF_CLKCTRL_EMI_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_EMI_RSRVD1)
 #define BP_CLKCTRL_EMI_DIV_EMI	0
 #define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
 #define BF_CLKCTRL_EMI_DIV_EMI(v)  \
@@ -406,12 +288,7 @@
 
 #define BP_CLKCTRL_SAIF0_CLKGATE	31
 #define BM_CLKCTRL_SAIF0_CLKGATE	0x80000000
-#define BM_CLKCTRL_SAIF0_RSRVD2	0x40000000
 #define BM_CLKCTRL_SAIF0_BUSY	0x20000000
-#define BP_CLKCTRL_SAIF0_RSRVD1	17
-#define BM_CLKCTRL_SAIF0_RSRVD1	0x1FFE0000
-#define BF_CLKCTRL_SAIF0_RSRVD1(v)  \
-		(((v) << 17) & BM_CLKCTRL_SAIF0_RSRVD1)
 #define BM_CLKCTRL_SAIF0_DIV_FRAC_EN	0x00010000
 #define BP_CLKCTRL_SAIF0_DIV	0
 #define BM_CLKCTRL_SAIF0_DIV	0x0000FFFF
@@ -422,12 +299,7 @@
 
 #define BP_CLKCTRL_SAIF1_CLKGATE	31
 #define BM_CLKCTRL_SAIF1_CLKGATE	0x80000000
-#define BM_CLKCTRL_SAIF1_RSRVD2	0x40000000
 #define BM_CLKCTRL_SAIF1_BUSY	0x20000000
-#define BP_CLKCTRL_SAIF1_RSRVD1	17
-#define BM_CLKCTRL_SAIF1_RSRVD1	0x1FFE0000
-#define BF_CLKCTRL_SAIF1_RSRVD1(v)  \
-		(((v) << 17) & BM_CLKCTRL_SAIF1_RSRVD1)
 #define BM_CLKCTRL_SAIF1_DIV_FRAC_EN	0x00010000
 #define BP_CLKCTRL_SAIF1_DIV	0
 #define BM_CLKCTRL_SAIF1_DIV	0x0000FFFF
@@ -438,12 +310,7 @@
 
 #define BP_CLKCTRL_DIS_LCDIF_CLKGATE	31
 #define BM_CLKCTRL_DIS_LCDIF_CLKGATE	0x80000000
-#define BM_CLKCTRL_DIS_LCDIF_RSRVD2	0x40000000
 #define BM_CLKCTRL_DIS_LCDIF_BUSY	0x20000000
-#define BP_CLKCTRL_DIS_LCDIF_RSRVD1	14
-#define BM_CLKCTRL_DIS_LCDIF_RSRVD1	0x1FFFC000
-#define BF_CLKCTRL_DIS_LCDIF_RSRVD1(v)  \
-		(((v) << 14) & BM_CLKCTRL_DIS_LCDIF_RSRVD1)
 #define BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN	0x00002000
 #define BP_CLKCTRL_DIS_LCDIF_DIV	0
 #define BM_CLKCTRL_DIS_LCDIF_DIV	0x00001FFF
@@ -453,12 +320,7 @@
 #define HW_CLKCTRL_ETM	(0x00000130)
 
 #define BM_CLKCTRL_ETM_CLKGATE	0x80000000
-#define BM_CLKCTRL_ETM_RSRVD2	0x40000000
 #define BM_CLKCTRL_ETM_BUSY	0x20000000
-#define BP_CLKCTRL_ETM_RSRVD1	8
-#define BM_CLKCTRL_ETM_RSRVD1	0x1FFFFF00
-#define BF_CLKCTRL_ETM_RSRVD1(v)  \
-		(((v) << 8) & BM_CLKCTRL_ETM_RSRVD1)
 #define BM_CLKCTRL_ETM_DIV_FRAC_EN	0x00000080
 #define BP_CLKCTRL_ETM_DIV	0
 #define BM_CLKCTRL_ETM_DIV	0x0000007F
@@ -471,7 +333,6 @@
 #define BP_CLKCTRL_ENET_DISABLE	30
 #define BM_CLKCTRL_ENET_DISABLE	0x40000000
 #define BM_CLKCTRL_ENET_STATUS	0x20000000
-#define BM_CLKCTRL_ENET_RSRVD1	0x10000000
 #define BM_CLKCTRL_ENET_BUSY_TIME	0x08000000
 #define BP_CLKCTRL_ENET_DIV_TIME	21
 #define BM_CLKCTRL_ENET_DIV_TIME	0x07E00000
@@ -493,37 +354,23 @@
 #define BM_CLKCTRL_ENET_CLK_OUT_EN	0x00040000
 #define BM_CLKCTRL_ENET_RESET_BY_SW_CHIP	0x00020000
 #define BM_CLKCTRL_ENET_RESET_BY_SW	0x00010000
-#define BP_CLKCTRL_ENET_RSRVD0	0
-#define BM_CLKCTRL_ENET_RSRVD0	0x0000FFFF
-#define BF_CLKCTRL_ENET_RSRVD0(v)  \
-		(((v) << 0) & BM_CLKCTRL_ENET_RSRVD0)
 
 #define HW_CLKCTRL_HSADC	(0x00000150)
 
-#define BM_CLKCTRL_HSADC_RSRVD2	0x80000000
 #define BM_CLKCTRL_HSADC_RESETB	0x40000000
 #define BP_CLKCTRL_HSADC_FREQDIV	28
 #define BM_CLKCTRL_HSADC_FREQDIV	0x30000000
 #define BF_CLKCTRL_HSADC_FREQDIV(v)  \
 		(((v) << 28) & BM_CLKCTRL_HSADC_FREQDIV)
-#define BP_CLKCTRL_HSADC_RSRVD1	0
-#define BM_CLKCTRL_HSADC_RSRVD1	0x0FFFFFFF
-#define BF_CLKCTRL_HSADC_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_HSADC_RSRVD1)
 
 #define HW_CLKCTRL_FLEXCAN	(0x00000160)
 
-#define BM_CLKCTRL_FLEXCAN_RSRVD2	0x80000000
 #define BP_CLKCTRL_FLEXCAN_STOP_CAN0	30
 #define BM_CLKCTRL_FLEXCAN_STOP_CAN0	0x40000000
 #define BM_CLKCTRL_FLEXCAN_CAN0_STATUS	0x20000000
 #define BP_CLKCTRL_FLEXCAN_STOP_CAN1	28
 #define BM_CLKCTRL_FLEXCAN_STOP_CAN1	0x10000000
 #define BM_CLKCTRL_FLEXCAN_CAN1_STATUS	0x08000000
-#define BP_CLKCTRL_FLEXCAN_RSRVD1	0
-#define BM_CLKCTRL_FLEXCAN_RSRVD1	0x07FFFFFF
-#define BF_CLKCTRL_FLEXCAN_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_FLEXCAN_RSRVD1)
 
 #define HW_CLKCTRL_FRAC0	(0x000001b0)
 #define HW_CLKCTRL_FRAC0_SET	(0x000001b4)
@@ -564,10 +411,6 @@
 #define HW_CLKCTRL_FRAC1_CLR	(0x000001c8)
 #define HW_CLKCTRL_FRAC1_TOG	(0x000001cc)
 
-#define BP_CLKCTRL_FRAC1_RSRVD2	24
-#define BM_CLKCTRL_FRAC1_RSRVD2	0xFF000000
-#define BF_CLKCTRL_FRAC1_RSRVD2(v) \
-		(((v) << 24) & BM_CLKCTRL_FRAC1_RSRVD2)
 #define BP_CLKCTRL_FRAC1_CLKGATEGPMI	23
 #define BM_CLKCTRL_FRAC1_CLKGATEGPMI	0x00800000
 #define BM_CLKCTRL_FRAC1_GPMI_STABLE	0x00400000
@@ -595,22 +438,10 @@
 #define HW_CLKCTRL_CLKSEQ_CLR	(0x000001d8)
 #define HW_CLKCTRL_CLKSEQ_TOG	(0x000001dc)
 
-#define BP_CLKCTRL_CLKSEQ_RSRVD0	19
-#define BM_CLKCTRL_CLKSEQ_RSRVD0	0xFFF80000
-#define BF_CLKCTRL_CLKSEQ_RSRVD0(v) \
-		(((v) << 19) & BM_CLKCTRL_CLKSEQ_RSRVD0)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_CPU	0x00040000
-#define BP_CLKCTRL_CLKSEQ_RSRVD1	15
-#define BM_CLKCTRL_CLKSEQ_RSRVD1	0x00038000
-#define BF_CLKCTRL_CLKSEQ_RSRVD1(v)  \
-		(((v) << 15) & BM_CLKCTRL_CLKSEQ_RSRVD1)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF	0x00004000
 #define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__BYPASS 0x1
 #define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__PFD    0x0
-#define BP_CLKCTRL_CLKSEQ_RSRVD2	9
-#define BM_CLKCTRL_CLKSEQ_RSRVD2	0x00003E00
-#define BF_CLKCTRL_CLKSEQ_RSRVD2(v)  \
-		(((v) << 9) & BM_CLKCTRL_CLKSEQ_RSRVD2)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_ETM	0x00000100
 #define BM_CLKCTRL_CLKSEQ_BYPASS_EMI	0x00000080
 #define BM_CLKCTRL_CLKSEQ_BYPASS_SSP3	0x00000040
@@ -623,10 +454,6 @@
 
 #define HW_CLKCTRL_RESET	(0x000001e0)
 
-#define BP_CLKCTRL_RESET_RSRVD	6
-#define BM_CLKCTRL_RESET_RSRVD	0xFFFFFFC0
-#define BF_CLKCTRL_RESET_RSRVD(v) \
-		(((v) << 6) & BM_CLKCTRL_RESET_RSRVD)
 #define BM_CLKCTRL_RESET_WDOG_POR_DISABLE	0x00000020
 #define BM_CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	0x00000010
 #define BM_CLKCTRL_RESET_THERMAL_RESET_ENABLE	0x00000008
@@ -640,10 +467,6 @@
 #define BM_CLKCTRL_STATUS_CPU_LIMIT	0xC0000000
 #define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
 		(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
-#define BP_CLKCTRL_STATUS_RSRVD	0
-#define BM_CLKCTRL_STATUS_RSRVD	0x3FFFFFFF
-#define BF_CLKCTRL_STATUS_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_STATUS_RSRVD)
 
 #define HW_CLKCTRL_VERSION	(0x00000200)
 
diff --git a/arch/arm/mach-mxs/system.c b/arch/arm/mach-mxs/system.c
index 9343d7e..20ec3bd 100644
--- a/arch/arm/mach-mxs/system.c
+++ b/arch/arm/mach-mxs/system.c
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/proc-fns.h>
 #include <asm/system.h>
@@ -135,3 +136,4 @@ 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-netx/include/mach/memory.h b/arch/arm/mach-netx/include/mach/memory.h
index 9a363f2..5956149 100644
--- a/arch/arm/mach-netx/include/mach/memory.h
+++ b/arch/arm/mach-netx/include/mach/memory.h
@@ -20,7 +20,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET UL(0x80000000)
+#define PLAT_PHYS_OFFSET UL(0x80000000)
 
 #endif
 
diff --git a/arch/arm/mach-nomadik/include/mach/memory.h b/arch/arm/mach-nomadik/include/mach/memory.h
index 1e5689d..d332521 100644
--- a/arch/arm/mach-nomadik/include/mach/memory.h
+++ b/arch/arm/mach-nomadik/include/mach/memory.h
@@ -23,6 +23,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-ns9xxx/include/mach/memory.h b/arch/arm/mach-ns9xxx/include/mach/memory.h
index 6107193..5c65aee 100644
--- a/arch/arm/mach-ns9xxx/include/mach/memory.h
+++ b/arch/arm/mach-ns9xxx/include/mach/memory.h
@@ -19,6 +19,6 @@
 #define NS9XXX_CS2STAT_LENGTH	UL(0x1000)
 #define NS9XXX_CS3STAT_LENGTH	UL(0x1000)
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-nuc93x/include/mach/memory.h b/arch/arm/mach-nuc93x/include/mach/memory.h
index 323ab0d..ef9864b 100644
--- a/arch/arm/mach-nuc93x/include/mach/memory.h
+++ b/arch/arm/mach-nuc93x/include/mach/memory.h
@@ -16,6 +16,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index ba6009f..af98117 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o
+obj-y += clock.o clock_data.o opp_data.o reset.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 22cc8c8..de88c92 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -165,7 +165,7 @@ static struct map_desc ams_delta_io_desc[] __initdata = {
 	}
 };
 
-static struct omap_lcd_config ams_delta_lcd_config __initdata = {
+static struct omap_lcd_config ams_delta_lcd_config = {
 	.ctrl_name	= "internal",
 };
 
@@ -175,7 +175,7 @@ static struct omap_usb_config ams_delta_usb_config __initdata = {
 	.pins[0]	= 2,
 };
 
-static struct omap_board_config_kernel ams_delta_config[] = {
+static struct omap_board_config_kernel ams_delta_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&ams_delta_lcd_config },
 };
 
@@ -208,14 +208,14 @@ static const struct matrix_keymap_data ams_delta_keymap_data = {
 	.keymap_size	= ARRAY_SIZE(ams_delta_keymap),
 };
 
-static struct omap_kp_platform_data ams_delta_kp_data = {
+static struct omap_kp_platform_data ams_delta_kp_data __initdata = {
 	.rows		= 8,
 	.cols		= 8,
 	.keymap_data	= &ams_delta_keymap_data,
 	.delay		= 9,
 };
 
-static struct platform_device ams_delta_kp_device = {
+static struct platform_device ams_delta_kp_device __initdata = {
 	.name		= "omap-keypad",
 	.id		= -1,
 	.dev		= {
@@ -225,12 +225,12 @@ static struct platform_device ams_delta_kp_device = {
 	.resource	= ams_delta_kp_resources,
 };
 
-static struct platform_device ams_delta_lcd_device = {
+static struct platform_device ams_delta_lcd_device __initdata = {
 	.name	= "lcd_ams_delta",
 	.id	= -1,
 };
 
-static struct platform_device ams_delta_led_device = {
+static struct platform_device ams_delta_led_device __initdata = {
 	.name	= "ams-delta-led",
 	.id	= -1
 };
@@ -259,7 +259,7 @@ static int ams_delta_camera_power(struct device *dev, int power)
 #define ams_delta_camera_power	NULL
 #endif
 
-static struct soc_camera_link __initdata ams_delta_iclink = {
+static struct soc_camera_link ams_delta_iclink = {
 	.bus_id         = 0,	/* OMAP1 SoC camera bus */
 	.i2c_adapter_id = 1,
 	.board_info     = &ams_delta_camera_board_info[0],
@@ -267,7 +267,7 @@ static struct soc_camera_link __initdata ams_delta_iclink = {
 	.power		= ams_delta_camera_power,
 };
 
-static struct platform_device ams_delta_camera_device = {
+static struct platform_device ams_delta_camera_device __initdata = {
 	.name   = "soc-camera-pdrv",
 	.id     = 0,
 	.dev    = {
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 0efb9db..87f173d 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -287,11 +287,11 @@ static struct platform_device *devices[] __initdata = {
 	&lcd_device,
 };
 
-static struct omap_lcd_config fsample_lcd_config __initdata = {
+static struct omap_lcd_config fsample_lcd_config = {
 	.ctrl_name	= "internal",
 };
 
-static struct omap_board_config_kernel fsample_config[] = {
+static struct omap_board_config_kernel fsample_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&fsample_lcd_config },
 };
 
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 28b84aa..ba3bd09 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -202,7 +202,7 @@ static int h2_nand_dev_ready(struct mtd_info *mtd)
 
 static const char *h2_part_probes[] = { "cmdlinepart", NULL };
 
-struct platform_nand_data h2_nand_platdata = {
+static struct platform_nand_data h2_nand_platdata = {
 	.chip	= {
 		.nr_chips		= 1,
 		.chip_offset		= 0,
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index dbc8b8d..ac48677 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -204,7 +204,7 @@ static int nand_dev_ready(struct mtd_info *mtd)
 
 static const char *part_probes[] = { "cmdlinepart", NULL };
 
-struct platform_nand_data nand_platdata = {
+static struct platform_nand_data nand_platdata = {
 	.chip	= {
 		.nr_chips		= 1,
 		.chip_offset		= 0,
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index f2c5c58..ba05a51 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -331,7 +331,7 @@ static struct resource htcpld_resources[] = {
 	},
 };
 
-struct htcpld_chip_platform_data htcpld_chips[] = {
+static struct htcpld_chip_platform_data htcpld_chips[] = {
 	[0] = {
 		.addr		= 0x03,
 		.reset		= 0x04,
@@ -366,7 +366,7 @@ struct htcpld_chip_platform_data htcpld_chips[] = {
 	},
 };
 
-struct htcpld_core_platform_data htcpld_pfdata = {
+static struct htcpld_core_platform_data htcpld_pfdata = {
 	.int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
 	.int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
 	.i2c_adapter_id	   = 1,
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index a36e674..2d9b8cb 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -365,7 +365,7 @@ static struct omap_mmc_platform_data mmc1_data = {
 
 static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
 
-void __init innovator_mmc_init(void)
+static void __init innovator_mmc_init(void)
 {
 	mmc_data[0] = &mmc1_data;
 	omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index d21f09d..cfd0849 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -115,7 +115,7 @@ static struct mipid_platform_data nokia770_mipid_platform_data = {
 	.shutdown = mipid_shutdown,
 };
 
-static void mipid_dev_init(void)
+static void __init mipid_dev_init(void)
 {
 	const struct omap_lcd_config *conf;
 
@@ -126,7 +126,7 @@ static void mipid_dev_init(void)
 	}
 }
 
-static void ads7846_dev_init(void)
+static void __init ads7846_dev_init(void)
 {
 	if (gpio_request(ADS7846_PENDOWN_GPIO, "ADS7846 pendown") < 0)
 		printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
@@ -170,7 +170,7 @@ static struct hwa742_platform_data nokia770_hwa742_platform_data = {
 	.te_connected		= 1,
 };
 
-static void hwa742_dev_init(void)
+static void __init hwa742_dev_init(void)
 {
 	clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL);
 	omapfb_set_ctrl_platform_data(&nokia770_hwa742_platform_data);
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index fb51ce6..c9d38f4 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -230,19 +230,6 @@ static struct spi_board_info palmte_spi_info[] __initdata = {
 	},
 };
 
-static void palmte_headphones_detect(void *data, int state)
-{
-	if (state) {
-		/* Headphones connected, disable speaker */
-		gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
-		printk(KERN_INFO "PM: speaker off\n");
-	} else {
-		/* Headphones unplugged, re-enable speaker */
-		gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
-		printk(KERN_INFO "PM: speaker on\n");
-	}
-}
-
 static void __init palmte_misc_gpio_setup(void)
 {
 	/* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index 815a69c..bdc0ac8 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -26,10 +26,12 @@
 #include <linux/smc91x.h>
 
 #include <mach/hardware.h>
+#include <mach/system.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <plat/board-voiceblue.h>
 #include <plat/common.h>
 #include <mach/gpio.h>
 #include <plat/flash.h>
@@ -163,52 +165,6 @@ static void __init voiceblue_init_irq(void)
 	omap_init_irq();
 }
 
-static void __init voiceblue_init(void)
-{
-	/* mux pins for uarts */
-	omap_cfg_reg(UART1_TX);
-	omap_cfg_reg(UART1_RTS);
-	omap_cfg_reg(UART2_TX);
-	omap_cfg_reg(UART2_RTS);
-	omap_cfg_reg(UART3_TX);
-	omap_cfg_reg(UART3_RX);
-
-	/* Watchdog */
-	gpio_request(0, "Watchdog");
-	/* smc91x reset */
-	gpio_request(7, "SMC91x reset");
-	gpio_direction_output(7, 1);
-	udelay(2);	/* wait at least 100ns */
-	gpio_set_value(7, 0);
-	mdelay(50);	/* 50ms until PHY ready */
-	/* smc91x interrupt pin */
-	gpio_request(8, "SMC91x irq");
-	/* 16C554 reset*/
-	gpio_request(6, "16C554 reset");
-	gpio_direction_output(6, 0);
-	/* 16C554 interrupt pins */
-	gpio_request(12, "16C554 irq");
-	gpio_request(13, "16C554 irq");
-	gpio_request(14, "16C554 irq");
-	gpio_request(15, "16C554 irq");
-	set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
-
-	platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
-	omap_board_config = voiceblue_config;
-	omap_board_config_size = ARRAY_SIZE(voiceblue_config);
-	omap_serial_init();
-	omap1_usb_init(&voiceblue_usb_config);
-	omap_register_i2c_bus(1, 100, NULL, 0);
-
-	/* There is a good chance board is going up, so enable power LED
-	 * (it is connected through invertor) */
-	omap_writeb(0x00, OMAP_LPG1_LCR);
-	omap_writeb(0x00, OMAP_LPG1_PMR);	/* Disable clock */
-}
-
 static void __init voiceblue_map_io(void)
 {
 	omap1_map_common_io();
@@ -275,8 +231,17 @@ void voiceblue_wdt_ping(void)
 	gpio_set_value(0, wdt_gpio_state);
 }
 
-void voiceblue_reset(void)
+static void voiceblue_reset(char mode, const char *cmd)
 {
+	/*
+	 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
+	 * "Global Software Reset Affects Traffic Controller Frequency".
+	 */
+	if (cpu_is_omap5912()) {
+		omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL);
+		omap_writew(0x8, ARM_RSTCT1);
+	}
+
 	set_bit(MACHINE_REBOOT, &machine_state);
 	voiceblue_wdt_enable();
 	while (1) ;
@@ -286,6 +251,54 @@ EXPORT_SYMBOL(voiceblue_wdt_enable);
 EXPORT_SYMBOL(voiceblue_wdt_disable);
 EXPORT_SYMBOL(voiceblue_wdt_ping);
 
+static void __init voiceblue_init(void)
+{
+	/* mux pins for uarts */
+	omap_cfg_reg(UART1_TX);
+	omap_cfg_reg(UART1_RTS);
+	omap_cfg_reg(UART2_TX);
+	omap_cfg_reg(UART2_RTS);
+	omap_cfg_reg(UART3_TX);
+	omap_cfg_reg(UART3_RX);
+
+	/* Watchdog */
+	gpio_request(0, "Watchdog");
+	/* smc91x reset */
+	gpio_request(7, "SMC91x reset");
+	gpio_direction_output(7, 1);
+	udelay(2);	/* wait at least 100ns */
+	gpio_set_value(7, 0);
+	mdelay(50);	/* 50ms until PHY ready */
+	/* smc91x interrupt pin */
+	gpio_request(8, "SMC91x irq");
+	/* 16C554 reset*/
+	gpio_request(6, "16C554 reset");
+	gpio_direction_output(6, 0);
+	/* 16C554 interrupt pins */
+	gpio_request(12, "16C554 irq");
+	gpio_request(13, "16C554 irq");
+	gpio_request(14, "16C554 irq");
+	gpio_request(15, "16C554 irq");
+	set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
+	set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+	set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
+	set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
+
+	platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
+	omap_board_config = voiceblue_config;
+	omap_board_config_size = ARRAY_SIZE(voiceblue_config);
+	omap_serial_init();
+	omap1_usb_init(&voiceblue_usb_config);
+	omap_register_i2c_bus(1, 100, NULL, 0);
+
+	/* There is a good chance board is going up, so enable power LED
+	 * (it is connected through invertor) */
+	omap_writeb(0x00, OMAP_LPG1_LCR);
+	omap_writeb(0x00, OMAP_LPG1_PMR);	/* Disable clock */
+
+	arch_reset = voiceblue_reset;
+}
+
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	/* Maintainer: Ladislav Michl <michl@2n.cz> */
 	.boot_params	= 0x10000100,
diff --git a/arch/arm/mach-omap1/include/mach/debug-macro.S b/arch/arm/mach-omap1/include/mach/debug-macro.S
index 6a0fa04..6285604 100644
--- a/arch/arm/mach-omap1/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap1/include/mach/debug-macro.S
@@ -17,6 +17,9 @@
 
 #include <plat/serial.h>
 
+#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 omap_uart_phys:	.word	0x0
 omap_uart_virt:	.word	0x0
@@ -33,7 +36,7 @@ omap_uart_virt:	.word	0x0
 		/* Use omap_uart_phys/virt if already configured */
 9:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rp, =omap_uart_phys	@ MMU enabled
 		add	\rv, \rp, #4		@ omap_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -46,7 +49,7 @@ omap_uart_virt:	.word	0x0
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =__phys_to_virt(OMAP_UART_INFO)	@ MMU enabled
+		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
 		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
@@ -73,7 +76,7 @@ omap_uart_virt:	.word	0x0
 98:		add	\rp, \rp, #0xff000000	@ phys base
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		sub	\rp, \rp, #0xff000000	@ phys base
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 8209736..d9af981 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -10,6 +10,7 @@
  *
  * Multichannel mode not supported.
  */
+#include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -78,100 +79,294 @@ static struct omap_mcbsp_ops omap1_mcbsp_ops = {
 };
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+struct resource omap7xx_mcbsp_res[][6] = {
+	{
+		{
+			.start = OMAP7XX_MCBSP1_BASE,
+			.end   = OMAP7XX_MCBSP1_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_7XX_McBSP1RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_7XX_McBSP1TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP1_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP1_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP7XX_MCBSP2_BASE,
+			.end   = OMAP7XX_MCBSP2_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_7XX_McBSP2RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_7XX_McBSP2TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP3_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP3_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+};
+
+#define omap7xx_mcbsp_res_0		omap7xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
 	{
-		.phys_base	= OMAP7XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
-		.rx_irq		= INT_7XX_McBSP1RX,
-		.tx_irq		= INT_7XX_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP7XX_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
-		.rx_irq		= INT_7XX_McBSP2RX,
-		.tx_irq		= INT_7XX_McBSP2TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 };
-#define OMAP7XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap7xx_mcbsp_pdata)
-#define OMAP7XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
+#define OMAP7XX_MCBSP_RES_SZ		ARRAY_SIZE(omap7xx_mcbsp_res[1])
+#define OMAP7XX_MCBSP_COUNT		ARRAY_SIZE(omap7xx_mcbsp_res)
 #else
+#define omap7xx_mcbsp_res_0		NULL
 #define omap7xx_mcbsp_pdata		NULL
-#define OMAP7XX_MCBSP_PDATA_SZ		0
-#define OMAP7XX_MCBSP_REG_NUM		0
+#define OMAP7XX_MCBSP_RES_SZ		0
+#define OMAP7XX_MCBSP_COUNT		0
 #endif
 
 #ifdef CONFIG_ARCH_OMAP15XX
+struct resource omap15xx_mcbsp_res[][6] = {
+	{
+		{
+			.start = OMAP1510_MCBSP1_BASE,
+			.end   = OMAP1510_MCBSP1_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP1RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP1TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP1_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP1_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1510_MCBSP2_BASE,
+			.end   = OMAP1510_MCBSP2_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_1510_SPI_RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_1510_SPI_TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP2_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP2_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1510_MCBSP3_BASE,
+			.end   = OMAP1510_MCBSP3_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP3RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP3TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP3_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP3_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+};
+
+#define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 	{
-		.phys_base	= OMAP1510_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
-		.rx_irq		= INT_McBSP1RX,
-		.tx_irq		= INT_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1510_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
-		.rx_irq		= INT_1510_SPI_RX,
-		.tx_irq		= INT_1510_SPI_TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1510_MCBSP3_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
-		.rx_irq		= INT_McBSP3RX,
-		.tx_irq		= INT_McBSP3TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 };
-#define OMAP15XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap15xx_mcbsp_pdata)
-#define OMAP15XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
+#define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
+#define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
 #else
+#define omap15xx_mcbsp_res_0		NULL
 #define omap15xx_mcbsp_pdata		NULL
-#define OMAP15XX_MCBSP_PDATA_SZ		0
-#define OMAP15XX_MCBSP_REG_NUM		0
+#define OMAP15XX_MCBSP_RES_SZ		0
+#define OMAP15XX_MCBSP_COUNT		0
 #endif
 
 #ifdef CONFIG_ARCH_OMAP16XX
+struct resource omap16xx_mcbsp_res[][6] = {
+	{
+		{
+			.start = OMAP1610_MCBSP1_BASE,
+			.end   = OMAP1610_MCBSP1_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP1RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP1TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP1_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP1_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1610_MCBSP2_BASE,
+			.end   = OMAP1610_MCBSP2_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_1610_McBSP2_RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_1610_McBSP2_TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP2_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP2_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1610_MCBSP3_BASE,
+			.end   = OMAP1610_MCBSP3_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP3RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP3TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP3_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP3_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+};
+
+#define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 	{
-		.phys_base	= OMAP1610_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
-		.rx_irq		= INT_McBSP1RX,
-		.tx_irq		= INT_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1610_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
-		.rx_irq		= INT_1610_McBSP2_RX,
-		.tx_irq		= INT_1610_McBSP2_TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1610_MCBSP3_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
-		.rx_irq		= INT_McBSP3RX,
-		.tx_irq		= INT_McBSP3TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 };
-#define OMAP16XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap16xx_mcbsp_pdata)
-#define OMAP16XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
+#define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
+#define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
 #else
+#define omap16xx_mcbsp_res_0		NULL
 #define omap16xx_mcbsp_pdata		NULL
-#define OMAP16XX_MCBSP_PDATA_SZ		0
-#define OMAP16XX_MCBSP_REG_NUM		0
+#define OMAP16XX_MCBSP_RES_SZ		0
+#define OMAP16XX_MCBSP_COUNT		0
 #endif
 
 static int __init omap1_mcbsp_init(void)
@@ -179,16 +374,12 @@ static int __init omap1_mcbsp_init(void)
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
-	if (cpu_is_omap7xx()) {
-		omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP7XX_MCBSP_REG_NUM * sizeof(u16);
-	} else if (cpu_is_omap15xx()) {
-		omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP15XX_MCBSP_REG_NUM * sizeof(u16);
-	} else if (cpu_is_omap16xx()) {
-		omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP16XX_MCBSP_REG_NUM * sizeof(u16);
-	}
+	if (cpu_is_omap7xx())
+		omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
+	else if (cpu_is_omap15xx())
+		omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
+	else if (cpu_is_omap16xx())
+		omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
 
 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
 								GFP_KERNEL);
@@ -196,16 +387,22 @@ static int __init omap1_mcbsp_init(void)
 		return -ENOMEM;
 
 	if (cpu_is_omap7xx())
-		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_pdata,
-						OMAP7XX_MCBSP_PDATA_SZ);
+		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
+					OMAP7XX_MCBSP_RES_SZ,
+					omap7xx_mcbsp_pdata,
+					OMAP7XX_MCBSP_COUNT);
 
 	if (cpu_is_omap15xx())
-		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
-						OMAP15XX_MCBSP_PDATA_SZ);
+		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
+					OMAP15XX_MCBSP_RES_SZ,
+					omap15xx_mcbsp_pdata,
+					OMAP15XX_MCBSP_COUNT);
 
 	if (cpu_is_omap16xx())
-		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
-						OMAP16XX_MCBSP_PDATA_SZ);
+		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
+					OMAP16XX_MCBSP_RES_SZ,
+					omap16xx_mcbsp_pdata,
+					OMAP16XX_MCBSP_COUNT);
 
 	return omap_mcbsp_init();
 }
diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h
index 56a6479..cd926dc 100644
--- a/arch/arm/mach-omap1/pm.h
+++ b/arch/arm/mach-omap1/pm.h
@@ -123,9 +123,9 @@ extern void allow_idle_sleep(void);
 extern void omap1_pm_idle(void);
 extern void omap1_pm_suspend(void);
 
-extern void omap7xx_cpu_suspend(unsigned short, unsigned short);
-extern void omap1510_cpu_suspend(unsigned short, unsigned short);
-extern void omap1610_cpu_suspend(unsigned short, unsigned short);
+extern void omap7xx_cpu_suspend(unsigned long, unsigned long);
+extern void omap1510_cpu_suspend(unsigned long, unsigned long);
+extern void omap1610_cpu_suspend(unsigned long, unsigned long);
 extern void omap7xx_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
diff --git a/arch/arm/mach-omap1/reset.c b/arch/arm/mach-omap1/reset.c
new file mode 100644
index 0000000..ad951ee
--- /dev/null
+++ b/arch/arm/mach-omap1/reset.c
@@ -0,0 +1,25 @@
+/*
+ * OMAP1 reset support
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <plat/prcm.h>
+
+void omap1_arch_reset(char mode, const char *cmd)
+{
+	/*
+	 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
+	 * "Global Software Reset Affects Traffic Controller Frequency".
+	 */
+	if (cpu_is_omap5912()) {
+		omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL);
+		omap_writew(0x8, ARM_RSTCT1);
+	}
+
+	omap_writew(1, ARM_RSTCT1);
+}
+
+void (*arch_reset)(char, const char *) = omap1_arch_reset;
diff --git a/arch/arm/mach-omap1/sleep.S b/arch/arm/mach-omap1/sleep.S
index ef771ce..c875bdc 100644
--- a/arch/arm/mach-omap1/sleep.S
+++ b/arch/arm/mach-omap1/sleep.S
@@ -58,6 +58,7 @@
  */
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+	.align	3
 ENTRY(omap7xx_cpu_suspend)
 
 	@ save registers on stack
@@ -137,6 +138,7 @@ ENTRY(omap7xx_cpu_suspend_sz)
 #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
 
 #ifdef CONFIG_ARCH_OMAP15XX
+	.align	3
 ENTRY(omap1510_cpu_suspend)
 
 	@ save registers on stack
@@ -211,6 +213,7 @@ ENTRY(omap1510_cpu_suspend_sz)
 #endif /* CONFIG_ARCH_OMAP15XX */
 
 #if defined(CONFIG_ARCH_OMAP16XX)
+	.align	3
 ENTRY(omap1610_cpu_suspend)
 
 	@ save registers on stack
diff --git a/arch/arm/mach-omap1/sram.S b/arch/arm/mach-omap1/sram.S
index 7724e52..692587d 100644
--- a/arch/arm/mach-omap1/sram.S
+++ b/arch/arm/mach-omap1/sram.S
@@ -18,6 +18,7 @@
 /*
  * Reprograms ULPD and CKCTL.
  */
+	.align	3
 ENTRY(omap1_sram_reprogram_clock)
 	stmfd	sp!, {r0 - r12, lr}		@ save registers on stack
 
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 1a2cf62..eeab35d 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -45,6 +45,7 @@ config ARCH_OMAP4
 	select CPU_V7
 	select ARM_GIC
 	select PL310_ERRATA_588369
+	select PL310_ERRATA_727915
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
@@ -53,25 +54,30 @@ config ARCH_OMAP4
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
 
-config ARCH_OMAP2420
+config SOC_OMAP2420
 	bool "OMAP2420 support"
 	depends on ARCH_OMAP2
 	default y
 	select OMAP_DM_TIMER
 	select ARCH_OMAP_OTG
 
-config ARCH_OMAP2430
+config SOC_OMAP2430
 	bool "OMAP2430 support"
 	depends on ARCH_OMAP2
 	default y
 	select ARCH_OMAP_OTG
 
-config ARCH_OMAP3430
+config SOC_OMAP3430
 	bool "OMAP3430 support"
 	depends on ARCH_OMAP3
 	default y
 	select ARCH_OMAP_OTG
 
+config SOC_OMAPTI816X
+	bool "TI816X support"
+	depends on ARCH_OMAP3
+	default y
+
 config OMAP_PACKAGE_ZAF
        bool
 
@@ -106,25 +112,25 @@ config MACH_OMAP_GENERIC
 
 config MACH_OMAP2_TUSB6010
 	bool
-	depends on ARCH_OMAP2 && ARCH_OMAP2420
+	depends on ARCH_OMAP2 && SOC_OMAP2420
 	default y if MACH_NOKIA_N8X0
 
 config MACH_OMAP_H4
 	bool "OMAP 2420 H4 board"
-	depends on ARCH_OMAP2420
+	depends on SOC_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAF
 	select OMAP_DEBUG_DEVICES
 
 config MACH_OMAP_APOLLON
 	bool "OMAP 2420 Apollon board"
-	depends on ARCH_OMAP2420
+	depends on SOC_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAC
 
 config MACH_OMAP_2430SDP
 	bool "OMAP 2430 SDP board"
-	depends on ARCH_OMAP2430
+	depends on SOC_OMAP2430
 	default y
 	select OMAP_PACKAGE_ZAC
 
@@ -219,7 +225,7 @@ config MACH_NOKIA_N810_WIMAX
 
 config MACH_NOKIA_N8X0
 	bool "Nokia N800/N810"
-	depends on ARCH_OMAP2420
+	depends on SOC_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAC
 	select MACH_NOKIA_N800
@@ -294,12 +300,18 @@ config MACH_OMAP_3630SDP
 	default y
 	select OMAP_PACKAGE_CBP
 
+config MACH_TI8168EVM
+	bool "TI8168 Evaluation Module"
+	depends on SOC_OMAPTI816X
+	default y
+
 config MACH_OMAP_4430SDP
 	bool "OMAP 4430 SDP board"
 	default y
 	depends on ARCH_OMAP4
 	select OMAP_PACKAGE_CBL
 	select OMAP_PACKAGE_CBS
+	select REGULATOR_FIXED_VOLTAGE
 
 config MACH_OMAP4_PANDA
 	bool "OMAP4 Panda Board"
@@ -307,6 +319,7 @@ config MACH_OMAP4_PANDA
 	depends on ARCH_OMAP4
 	select OMAP_PACKAGE_CBL
 	select OMAP_PACKAGE_CBS
+	select REGULATOR_FIXED_VOLTAGE
 
 config OMAP3_EMU
 	bool "OMAP3 debugging peripherals"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 1c0c2b0..a45cd64 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -31,8 +31,8 @@ AFLAGS_omap-headsmp.o			:=-Wa,-march=armv7-a$(plus_sec)
 AFLAGS_omap44xx-smc.o			:=-Wa,-march=armv7-a$(plus_sec)
 
 # Functions loaded to SRAM
-obj-$(CONFIG_ARCH_OMAP2420)		+= sram242x.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= sram243x.o
+obj-$(CONFIG_SOC_OMAP2420)		+= sram242x.o
+obj-$(CONFIG_SOC_OMAP2430)		+= sram243x.o
 obj-$(CONFIG_ARCH_OMAP3)		+= sram34xx.o
 
 AFLAGS_sram242x.o			:=-Wa,-march=armv6
@@ -40,8 +40,8 @@ AFLAGS_sram243x.o			:=-Wa,-march=armv6
 AFLAGS_sram34xx.o			:=-Wa,-march=armv7-a
 
 # Pin multiplexing
-obj-$(CONFIG_ARCH_OMAP2420)		+= mux2420.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= mux2430.o
+obj-$(CONFIG_SOC_OMAP2420)		+= mux2420.o
+obj-$(CONFIG_SOC_OMAP2430)		+= mux2430.o
 obj-$(CONFIG_ARCH_OMAP3)		+= mux34xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= mux44xx.o
 
@@ -59,10 +59,10 @@ endif
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o voltage.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
+obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o \
 					   cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o voltage.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
 obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
@@ -78,13 +78,25 @@ endif
 
 # PRCM
 obj-$(CONFIG_ARCH_OMAP2)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
+					   vc3xxx_data.o vp3xxx_data.o
 # XXX The presence of cm2xxx_3xxx.o on the line below is temporary and
 # will be removed once the OMAP4 part of the codebase is converted to
 # use OMAP4-specific PRCM functions.
 obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
 					   cm44xx.o prcm_mpu44xx.o \
-					   prminst44xx.o
+					   prminst44xx.o vc44xx_data.o \
+					   vp44xx_data.o
+
+# OMAP voltage domains
+ifeq ($(CONFIG_PM),y)
+voltagedomain-common			:= voltage.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
+obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common) \
+					   voltagedomains3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common) \
+					   voltagedomains44xx_data.o
+endif
 
 # OMAP powerdomain framework
 powerdomain-common			+= powerdomain.o powerdomain-common.o
@@ -102,39 +114,49 @@ obj-$(CONFIG_ARCH_OMAP4)		+= $(powerdomain-common) \
 
 # PRCM clockdomain control
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
+					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
+					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
+					   clockdomain44xx.o \
 					   clockdomains44xx_data.o
+
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o \
 					   clkt2xxx_sys.o \
 					   clkt2xxx_dpllcore.o \
 					   clkt2xxx_virt_prcm_set.o \
-					   clkt2xxx_apll.o clkt2xxx_osc.o
-obj-$(CONFIG_ARCH_OMAP2420)		+= clock2420_data.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= clock2430.o clock2430_data.o
+					   clkt2xxx_apll.o clkt2xxx_osc.o \
+					   clkt2xxx_dpll.o clkt_iclk.o
+obj-$(CONFIG_SOC_OMAP2420)		+= clock2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o clock2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(clock-common) clock3xxx.o \
 					   clock34xx.o clkt34xx_dpll3m2.o \
 					   clock3517.o clock36xx.o \
-					   dpll3xxx.o clock3xxx_data.o
+					   dpll3xxx.o clock3xxx_data.o \
+					   clkt_iclk.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common) clock44xx_data.o \
-					   dpll3xxx.o
+					   dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
-obj-$(CONFIG_ARCH_OMAP2420)		+= opp2420_data.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= opp2430_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= opp2430_data.o
 
 # hwmod data
-obj-$(CONFIG_ARCH_OMAP2420)		+= omap_hwmod_2420_data.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= omap_hwmod_2430_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)			+= emu.o
 
+# L3 interconnect
+obj-$(CONFIG_ARCH_OMAP3)		+= omap_l3_smx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= omap_l3_noc.o
+
 obj-$(CONFIG_OMAP_MBOX_FWK)		+= mailbox_mach.o
 mailbox_mach-objs			:= mailbox.o
 
@@ -218,18 +240,20 @@ obj-$(CONFIG_MACH_OMAP4_PANDA)		+= board-omap4panda.o \
 					   hsmmc.o \
 					   omap_phy_internal.o
 
-obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
+obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o \
+					   omap_phy_internal.o \
 
 obj-$(CONFIG_MACH_CRANEBOARD)		+= board-am3517crane.o
 
 obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o \
 					   hsmmc.o
+obj-$(CONFIG_MACH_TI8168EVM)		+= board-ti8168evm.o
 # Platform specific device init code
 usbfs-$(CONFIG_ARCH_OMAP_OTG)		:= usb-fs.o
 obj-y					+= $(usbfs-m) $(usbfs-y)
 obj-y					+= usb-musb.o
 obj-$(CONFIG_MACH_OMAP2_TUSB6010)	+= usb-tusb6010.o
-obj-y					+= usb-ehci.o
+obj-y					+= usb-host.o
 
 onenand-$(CONFIG_MTD_ONENAND_OMAP2)	:= gpmc-onenand.o
 obj-y					+= $(onenand-m) $(onenand-y)
@@ -242,3 +266,7 @@ obj-y					+= $(smc91x-m) $(smc91x-y)
 
 smsc911x-$(CONFIG_SMSC911X)		:= gpmc-smsc911x.o
 obj-y					+= $(smsc911x-m) $(smsc911x-y)
+obj-$(CONFIG_ARCH_OMAP4)		+= hwspinlock.o
+
+disp-$(CONFIG_OMAP2_DSS)		:= display.o
+obj-y					+= $(disp-m) $(disp-y)
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index e066177..1fa6bb8 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -22,6 +22,7 @@
 #include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/i2c/twl.h>
+#include <linux/regulator/machine.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -139,15 +140,31 @@ static struct omap_board_config_kernel sdp2430_config[] __initdata = {
 	{OMAP_TAG_LCD, &sdp2430_lcd_config},
 };
 
-static void __init omap_2430sdp_init_irq(void)
+static void __init omap_2430sdp_init_early(void)
 {
-	omap_board_config = sdp2430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
+static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data sdp2430_vmmc1 = {
+	.constraints = {
+		.min_uV			= 1850000,
+		.max_uV			= 3150000,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_VOLTAGE
+					| REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(sdp2430_vmmc1_supplies),
+	.consumer_supplies	= &sdp2430_vmmc1_supplies[0],
+};
+
 static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -160,6 +177,7 @@ static struct twl4030_platform_data sdp2430_twldata = {
 
 	/* platform_data for children goes here */
 	.gpio		= &sdp2430_gpio_data,
+	.vmmc1		= &sdp2430_vmmc1,
 };
 
 static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
@@ -226,6 +244,9 @@ static void __init omap_2430sdp_init(void)
 
 	omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
+	omap_board_config = sdp2430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
+
 	omap2430_i2c_init();
 
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
@@ -253,9 +274,10 @@ static void __init omap_2430sdp_map_io(void)
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_2430sdp_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_2430sdp_init_irq,
+	.map_io		= omap_2430sdp_map_io,
+	.init_early	= omap_2430sdp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_2430sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index d4e41ef..c06eb42 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -307,34 +307,16 @@ static struct omap_dss_board_info sdp3430_dss_data = {
 	.default_device	= &sdp3430_lcd_device,
 };
 
-static struct platform_device sdp3430_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &sdp3430_dss_data,
-	},
-};
-
-static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &sdp3430_dss_device.dev,
-};
-
-static struct platform_device *sdp3430_devices[] __initdata = {
-	&sdp3430_dss_device,
-};
+static struct regulator_consumer_supply sdp3430_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 };
 
-static void __init omap_3430sdp_init_irq(void)
+static void __init omap_3430sdp_init_early(void)
 {
-	omap_board_config = sdp3430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
-	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
-	omap_init_irq();
 }
 
 static int sdp3430_batt_table[] = {
@@ -370,18 +352,6 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static struct regulator_consumer_supply sdp3430_vmmc1_supply = {
-	.supply			= "vmmc",
-};
-
-static struct regulator_consumer_supply sdp3430_vsim_supply = {
-	.supply			= "vmmc_aux",
-};
-
-static struct regulator_consumer_supply sdp3430_vmmc2_supply = {
-	.supply			= "vmmc",
-};
-
 static int sdp3430_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
@@ -392,13 +362,6 @@ static int sdp3430_twl_gpio_setup(struct device *dev,
 	mmc[1].gpio_cd = gpio + 1;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters ... we "know" the
-	 * regulators will be set up only *after* we return.
-	 */
-	sdp3430_vmmc1_supply.dev = mmc[0].dev;
-	sdp3430_vsim_supply.dev = mmc[0].dev;
-	sdp3430_vmmc2_supply.dev = mmc[1].dev;
-
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request(gpio + 7, "sub_lcd_en_bkl");
 	gpio_direction_output(gpio + 7, 0);
@@ -427,6 +390,34 @@ static struct twl4030_madc_platform_data sdp3430_madc_data = {
 	.irq_line	= 1,
 };
 
+/* regulator consumer mappings */
+
+/* ads7846 on SPI */
+static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = {
+	REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
+
+static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = {
+	REGULATOR_SUPPLY("vdda_dac", "omapdss"),
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+};
+
+static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+static struct regulator_consumer_supply sdp3430_vsim_supplies[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
+};
+
+static struct regulator_consumer_supply sdp3430_vmmc2_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
+
 /*
  * Apply all the fixed voltages since most versions of U-Boot
  * don't bother with that initialization.
@@ -469,6 +460,8 @@ static struct regulator_init_data sdp3430_vaux3 = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies		= ARRAY_SIZE(sdp3430_vaux3_supplies),
+	.consumer_supplies		= sdp3430_vaux3_supplies,
 };
 
 /* VAUX4 for OMAP VDD_CSI2 (camera) */
@@ -495,8 +488,8 @@ static struct regulator_init_data sdp3430_vmmc1 = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vmmc1_supplies),
+	.consumer_supplies	= sdp3430_vmmc1_supplies,
 };
 
 /* VMMC2 for MMC2 card */
@@ -510,8 +503,8 @@ static struct regulator_init_data sdp3430_vmmc2 = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vmmc2_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vmmc2_supplies),
+	.consumer_supplies	= sdp3430_vmmc2_supplies,
 };
 
 /* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
@@ -525,8 +518,8 @@ static struct regulator_init_data sdp3430_vsim = {
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vsim_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vsim_supplies),
+	.consumer_supplies	= sdp3430_vsim_supplies,
 };
 
 /* VDAC for DSS driving S-Video */
@@ -540,16 +533,8 @@ static struct regulator_init_data sdp3430_vdac = {
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
-	{
-		.supply		= "vdds_dsi",
-		.dev		= &sdp3430_dss_device.dev,
-	}
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vdda_dac_supplies),
+	.consumer_supplies	= sdp3430_vdda_dac_supplies,
 };
 
 static struct regulator_init_data sdp3430_vpll2 = {
@@ -567,9 +552,7 @@ static struct regulator_init_data sdp3430_vpll2 = {
 	.consumer_supplies	= sdp3430_vpll2_supplies,
 };
 
-static struct twl4030_codec_audio_data sdp3430_audio = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data sdp3430_audio;
 
 static struct twl4030_codec_data sdp3430_codec = {
 	.audio_mclk = 26000000,
@@ -653,11 +636,11 @@ static void enable_board_wakeup_source(void)
 		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 57,
@@ -669,6 +652,106 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial1_pads[] __initdata = {
+	/*
+	 * Note that off output enable is an active low
+	 * signal. So setting this means pin is a
+	 * input enabled in off mode
+	 */
+	OMAP_MUX_STATIC("uart1_cts.uart1_cts",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart1_rts.uart1_rts",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart1_rx.uart1_rx",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart1_tx.uart1_tx",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+			 OMAP_PIN_INPUT_PULLUP |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+			 OMAP_PIN_INPUT_PULLDOWN |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial1_data = {
+	.id		= 0,
+	.pads		= serial1_pads,
+	.pads_cnt	= ARRAY_SIZE(serial1_pads),
+};
+
+static struct omap_board_data serial2_data = {
+	.id		= 1,
+	.pads		= serial2_pads,
+	.pads_cnt	= ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data = {
+	.id		= 2,
+	.pads		= serial3_pads,
+	.pads_cnt	= ARRAY_SIZE(serial3_pads),
+};
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init_port(&serial1_data);
+	omap_serial_init_port(&serial2_data);
+	omap_serial_init_port(&serial3_data);
+}
+#else
+#define board_mux	NULL
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
 #endif
 
 /*
@@ -800,8 +883,11 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init omap_3430sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = sdp3430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
 	omap3430_i2c_init();
-	platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices));
+	omap_display_init(&sdp3430_dss_data);
 	if (omap_rev() > OMAP3430_REV_ES1_0)
 		ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV2;
 	else
@@ -810,21 +896,22 @@ static void __init omap_3430sdp_init(void)
 	spi_register_board_info(sdp3430_spi_board_info,
 				ARRAY_SIZE(sdp3430_spi_board_info));
 	ads7846_dev_init();
-	omap_serial_init();
+	board_serial_init();
 	usb_musb_init(&musb_board_data);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430);
+	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
 	sdp3430_display_init();
 	enable_board_wakeup_source();
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_3430sdp_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_3430sdp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_3430sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 6264564..a5933cc 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -54,11 +55,11 @@ static void enable_board_wakeup_source(void)
 		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 126,
@@ -69,14 +70,11 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
 static struct omap_board_config_kernel sdp_config[] __initdata = {
 };
 
-static void __init omap_sdp_init_irq(void)
+static void __init omap_sdp_init_early(void)
 {
-	omap_board_config = sdp_config;
-	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -206,19 +204,22 @@ static struct flash_partitions sdp_flash_partitions[] = {
 static void __init omap_sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
+	omap_board_config = sdp_config;
+	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	zoom_peripherals_init();
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
 	enable_board_wakeup_source();
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_sdp_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_sdp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 07d1b20..333ceb2 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -35,6 +35,7 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include <plat/omap4-keypad.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -44,10 +45,93 @@
 #define ETH_KS8851_IRQ			34
 #define ETH_KS8851_POWER_ON		48
 #define ETH_KS8851_QUART		138
-#define OMAP4SDP_MDM_PWR_EN_GPIO	157
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO	184
 #define OMAP4_SFH7741_ENABLE_GPIO		188
 
+static const int sdp4430_keymap[] = {
+	KEY(0, 0, KEY_E),
+	KEY(0, 1, KEY_R),
+	KEY(0, 2, KEY_T),
+	KEY(0, 3, KEY_HOME),
+	KEY(0, 4, KEY_F5),
+	KEY(0, 5, KEY_UNKNOWN),
+	KEY(0, 6, KEY_I),
+	KEY(0, 7, KEY_LEFTSHIFT),
+
+	KEY(1, 0, KEY_D),
+	KEY(1, 1, KEY_F),
+	KEY(1, 2, KEY_G),
+	KEY(1, 3, KEY_SEND),
+	KEY(1, 4, KEY_F6),
+	KEY(1, 5, KEY_UNKNOWN),
+	KEY(1, 6, KEY_K),
+	KEY(1, 7, KEY_ENTER),
+
+	KEY(2, 0, KEY_X),
+	KEY(2, 1, KEY_C),
+	KEY(2, 2, KEY_V),
+	KEY(2, 3, KEY_END),
+	KEY(2, 4, KEY_F7),
+	KEY(2, 5, KEY_UNKNOWN),
+	KEY(2, 6, KEY_DOT),
+	KEY(2, 7, KEY_CAPSLOCK),
+
+	KEY(3, 0, KEY_Z),
+	KEY(3, 1, KEY_KPPLUS),
+	KEY(3, 2, KEY_B),
+	KEY(3, 3, KEY_F1),
+	KEY(3, 4, KEY_F8),
+	KEY(3, 5, KEY_UNKNOWN),
+	KEY(3, 6, KEY_O),
+	KEY(3, 7, KEY_SPACE),
+
+	KEY(4, 0, KEY_W),
+	KEY(4, 1, KEY_Y),
+	KEY(4, 2, KEY_U),
+	KEY(4, 3, KEY_F2),
+	KEY(4, 4, KEY_VOLUMEUP),
+	KEY(4, 5, KEY_UNKNOWN),
+	KEY(4, 6, KEY_L),
+	KEY(4, 7, KEY_LEFT),
+
+	KEY(5, 0, KEY_S),
+	KEY(5, 1, KEY_H),
+	KEY(5, 2, KEY_J),
+	KEY(5, 3, KEY_F3),
+	KEY(5, 4, KEY_F9),
+	KEY(5, 5, KEY_VOLUMEDOWN),
+	KEY(5, 6, KEY_M),
+	KEY(5, 7, KEY_RIGHT),
+
+	KEY(6, 0, KEY_Q),
+	KEY(6, 1, KEY_A),
+	KEY(6, 2, KEY_N),
+	KEY(6, 3, KEY_BACK),
+	KEY(6, 4, KEY_BACKSPACE),
+	KEY(6, 5, KEY_UNKNOWN),
+	KEY(6, 6, KEY_P),
+	KEY(6, 7, KEY_UP),
+
+	KEY(7, 0, KEY_PROG1),
+	KEY(7, 1, KEY_PROG2),
+	KEY(7, 2, KEY_PROG3),
+	KEY(7, 3, KEY_PROG4),
+	KEY(7, 4, KEY_F4),
+	KEY(7, 5, KEY_UNKNOWN),
+	KEY(7, 6, KEY_OK),
+	KEY(7, 7, KEY_DOWN),
+};
+
+static struct matrix_keymap_data sdp4430_keymap_data = {
+	.keymap			= sdp4430_keymap,
+	.keymap_size		= ARRAY_SIZE(sdp4430_keymap),
+};
+
+static struct omap4_keypad_platform_data sdp4430_keypad_data = {
+	.keymap_data		= &sdp4430_keymap_data,
+	.rows			= 8,
+	.cols			= 8,
+};
 static struct gpio_led sdp4430_gpio_leds[] = {
 	{
 		.name	= "omap4:green:debug0",
@@ -239,28 +323,15 @@ static struct omap_board_config_kernel sdp4430_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&sdp4430_lcd_config },
 };
 
-static void __init omap_4430sdp_init_irq(void)
+static void __init omap_4430sdp_init_early(void)
 {
-	omap_board_config = sdp4430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(1);
 #endif
-	gic_init_irq();
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0]	= EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1]	= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2]	= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.phy_reset	= false,
-	.reset_gpio_port[0]  = -EINVAL,
-	.reset_gpio_port[1]  = -EINVAL,
-	.reset_gpio_port[2]  = -EINVAL,
-};
-
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
 	.mode			= MUSB_OTG,
@@ -272,15 +343,11 @@ static struct twl4030_usb_data omap4_usbphy_data = {
 	.phy_exit	= omap4430_phy_exit,
 	.phy_power	= omap4430_phy_power,
 	.phy_set_clock	= omap4430_phy_set_clk,
+	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct omap2_hsmmc_info mmc[] = {
 	{
-		.mmc		= 1,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-		.gpio_wp	= -EINVAL,
-	},
-	{
 		.mmc		= 2,
 		.caps		=  MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_cd	= -EINVAL,
@@ -288,19 +355,24 @@ static struct omap2_hsmmc_info mmc[] = {
 		.nonremovable   = true,
 		.ocr_mask	= MMC_VDD_29_30,
 	},
+	{
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+		.gpio_wp	= -EINVAL,
+	},
 	{}	/* Terminator */
 };
 
 static struct regulator_consumer_supply sdp4430_vaux_supply[] = {
 	{
 		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.1",
+		.dev_name = "omap_hsmmc.1",
 	},
 };
 static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
 	{
 		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.0",
+		.dev_name = "omap_hsmmc.0",
 	},
 };
 
@@ -434,7 +506,6 @@ static struct regulator_init_data sdp4430_vana = {
 	.constraints = {
 		.min_uV			= 2100000,
 		.max_uV			= 2100000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -446,7 +517,6 @@ static struct regulator_init_data sdp4430_vcxio = {
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -458,7 +528,6 @@ static struct regulator_init_data sdp4430_vdac = {
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -557,9 +626,76 @@ static struct omap_board_mux board_mux[] __initdata = {
 	OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial4_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart4_rx.uart4_rx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart4_tx.uart4_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial2_data = {
+	.id		= 1,
+	.pads		= serial2_pads,
+	.pads_cnt	= ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data = {
+	.id		= 2,
+	.pads		= serial3_pads,
+	.pads_cnt	= ARRAY_SIZE(serial3_pads),
+};
+
+static struct omap_board_data serial4_data = {
+	.id		= 3,
+	.pads		= serial4_pads,
+	.pads_cnt	= ARRAY_SIZE(serial4_pads),
+};
+
+static inline void board_serial_init(void)
+{
+	struct omap_board_data bdata;
+	bdata.flags	= 0;
+	bdata.pads	= NULL;
+	bdata.pads_cnt	= 0;
+	bdata.id	= 0;
+	/* pass dummy data for UART1 */
+	omap_serial_init_port(&bdata);
+
+	omap_serial_init_port(&serial2_data);
+	omap_serial_init_port(&serial3_data);
+	omap_serial_init_port(&serial4_data);
+}
 #else
 #define board_mux	NULL
-#endif
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
+ #endif
 
 static void __init omap_4430sdp_init(void)
 {
@@ -570,20 +706,15 @@ static void __init omap_4430sdp_init(void)
 		package = OMAP_PACKAGE_CBL;
 	omap4_mux_init(board_mux, package);
 
+	omap_board_config = sdp4430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
+
 	omap4_i2c_init();
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
-	omap_serial_init();
+	board_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
-	/* Power on the ULPI PHY */
-	status = gpio_request(OMAP4SDP_MDM_PWR_EN_GPIO, "USBB1 PHY VMDM_3V3");
-	if (status)
-		pr_err("%s: Could not get USBB1 PHY GPIO\n", __func__);
-	else
-		gpio_direction_output(OMAP4SDP_MDM_PWR_EN_GPIO, 1);
-
-	usb_ehci_init(&ehci_pdata);
 	usb_musb_init(&musb_board_data);
 
 	status = omap_ethernet_init();
@@ -594,6 +725,10 @@ static void __init omap_4430sdp_init(void)
 		spi_register_board_info(sdp4430_spi_board_info,
 				ARRAY_SIZE(sdp4430_spi_board_info));
 	}
+
+	status = omap4_keyboard_init(&sdp4430_keypad_data);
+	if (status)
+		pr_err("Keypad initialization failed: %d\n", status);
 }
 
 static void __init omap_4430sdp_map_io(void)
@@ -605,9 +740,10 @@ static void __init omap_4430sdp_map_io(void)
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_4430sdp_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_4430sdp_init_irq,
+	.map_io		= omap_4430sdp_map_io,
+	.init_early	= omap_4430sdp_init_early,
+	.init_irq	= gic_init_irq,
 	.init_machine	= omap_4430sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 71acb5a..a890d24 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -49,20 +49,16 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux	NULL
 #endif
 
-static void __init am3517_crane_init_irq(void)
+static void __init am3517_crane_init_early(void)
 {
-	omap_board_config = am3517_crane_config;
-	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
-
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = GPIO_USB_NRESET,
@@ -77,6 +73,9 @@ static void __init am3517_crane_init(void)
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
 
+	omap_board_config = am3517_crane_config;
+	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
+
 	/* Configure GPIO for EHCI port */
 	if (omap_mux_init_gpio(GPIO_USB_NRESET, OMAP_PIN_OUTPUT)) {
 		pr_err("Can not configure mux for GPIO_USB_NRESET %d\n",
@@ -103,14 +102,15 @@ static void __init am3517_crane_init(void)
 		return;
 	}
 
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= am3517_crane_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= am3517_crane_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= am3517_crane_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index 10d60b7..ce7d5e6 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -200,6 +200,9 @@ static struct pca953x_platform_data am3517evm_gpio_expander_info_0 = {
 };
 static struct i2c_board_info __initdata am3517evm_i2c2_boardinfo[] = {
 	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1A),
+	},
+	{
 		I2C_BOARD_INFO("tca6416", 0x21),
 		.platform_data = &am3517evm_gpio_expander_info_0,
 	},
@@ -378,37 +381,23 @@ static struct omap_dss_board_info am3517_evm_dss_data = {
 	.default_device	= &am3517_evm_lcd_device,
 };
 
-static struct platform_device am3517_evm_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &am3517_evm_dss_data,
-	},
-};
-
 /*
  * Board initialization
  */
-static struct omap_board_config_kernel am3517_evm_config[] __initdata = {
-};
-
-static struct platform_device *am3517_evm_devices[] __initdata = {
-	&am3517_evm_dss_device,
-};
-
-static void __init am3517_evm_init_irq(void)
+static void __init am3517_evm_init_early(void)
 {
-	omap_board_config = am3517_evm_config;
-	omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type         = MUSB_INTERFACE_ULPI,
 	.mode                   = MUSB_OTG,
 	.power                  = 500,
+	.set_phy_power		= am35x_musb_phy_power,
+	.clear_irq		= am35x_musb_clear_irq,
+	.set_mode		= am35x_musb_set_mode,
+	.reset			= am35x_musb_reset,
 };
 
 static __init void am3517_evm_musb_init(void)
@@ -430,15 +419,15 @@ static __init void am3517_evm_musb_init(void)
 	usb_musb_init(&musb_board_data);
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
 		defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE)
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
 #else
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 #endif
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 57,
@@ -490,19 +479,22 @@ static void am3517_evm_hecc_init(struct ti_hecc_platform_data *pdata)
 	platform_device_register(&am3517_hecc_device);
 }
 
+static struct omap_board_config_kernel am3517_evm_config[] __initdata = {
+};
+
 static void __init am3517_evm_init(void)
 {
+	omap_board_config = am3517_evm_config;
+	omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 
 	am3517_evm_i2c_init();
-	platform_add_devices(am3517_evm_devices,
-				ARRAY_SIZE(am3517_evm_devices));
-
+	omap_display_init(&am3517_evm_dss_data);
 	omap_serial_init();
 
 	/* Configure GPIO for EHCI port */
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	am3517_evm_hecc_init(&am3517_evm_hecc_pdata);
 	/* DSS */
 	am3517_evm_display_init();
@@ -521,9 +513,10 @@ static void __init am3517_evm_init(void)
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= am3517_evm_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= am3517_evm_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= am3517_evm_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 9f55b68..f4f8374 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -274,13 +274,10 @@ static struct omap_board_config_kernel apollon_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&apollon_lcd_config },
 };
 
-static void __init omap_apollon_init_irq(void)
+static void __init omap_apollon_init_early(void)
 {
-	omap_board_config = apollon_config;
-	omap_board_config_size = ARRAY_SIZE(apollon_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static void __init apollon_led_init(void)
@@ -320,6 +317,8 @@ static void __init omap_apollon_init(void)
 	u32 v;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
+	omap_board_config = apollon_config;
+	omap_board_config_size = ARRAY_SIZE(apollon_config);
 
 	apollon_init_smc91x();
 	apollon_led_init();
@@ -355,9 +354,10 @@ static void __init omap_apollon_map_io(void)
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_apollon_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_apollon_init_irq,
+	.map_io		= omap_apollon_map_io,
+	.init_early	= omap_apollon_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_apollon_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index dac1416..7b56479 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -401,14 +401,6 @@ static struct omap_dss_board_info cm_t35_dss_data = {
 	.default_device	= &cm_t35_dvi_device,
 };
 
-static struct platform_device cm_t35_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &cm_t35_dss_data,
-	},
-};
-
 static struct omap2_mcspi_device_config tdo24m_mcspi_config = {
 	.turbo_mode	= 0,
 	.single_channel	= 1,	/* 0: slave, 1: master */
@@ -468,7 +460,7 @@ static void __init cm_t35_init_display(void)
 	msleep(50);
 	gpio_set_value(lcd_en_gpio, 1);
 
-	err = platform_device_register(&cm_t35_dss_device);
+	err = omap_display_init(&cm_t35_dss_data);
 	if (err) {
 		pr_err("CM-T35: failed to register DSS device\n");
 		goto err_dev_reg;
@@ -495,15 +487,11 @@ static struct regulator_consumer_supply cm_t35_vsim_supply = {
 	.supply			= "vmmc_aux",
 };
 
-static struct regulator_consumer_supply cm_t35_vdac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &cm_t35_dss_device.dev,
-};
+static struct regulator_consumer_supply cm_t35_vdac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
-static struct regulator_consumer_supply cm_t35_vdvi_supply = {
-	.supply		= "vdvi",
-	.dev		= &cm_t35_dss_device.dev,
-};
+static struct regulator_consumer_supply cm_t35_vdvi_supply =
+	REGULATOR_SUPPLY("vdvi", "omapdss");
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
 static struct regulator_init_data cm_t35_vmmc1 = {
@@ -605,10 +593,10 @@ static struct omap2_hsmmc_info mmc[] = {
 	{}	/* Terminator */
 };
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = OMAP_MAX_GPIO_LINES + 6,
@@ -680,20 +668,14 @@ static void __init cm_t35_init_i2c(void)
 			      ARRAY_SIZE(cm_t35_i2c_boardinfo));
 }
 
-static struct omap_board_config_kernel cm_t35_config[] __initdata = {
-};
-
-static void __init cm_t35_init_irq(void)
+static void __init cm_t35_init_early(void)
 {
-	omap_board_config = cm_t35_config;
-	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
-
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
 }
 
+#ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for CM-T35 ethernet */
 	OMAP3_MUX(GPMC_NCS5, OMAP_MUX_MODE0),
@@ -791,6 +773,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#endif
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_ULPI,
@@ -798,8 +781,13 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
+static struct omap_board_config_kernel cm_t35_config[] __initdata = {
+};
+
 static void __init cm_t35_init(void)
 {
+	omap_board_config = cm_t35_config;
+	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
 	cm_t35_init_i2c();
@@ -810,14 +798,15 @@ static void __init cm_t35_init(void)
 	cm_t35_init_display();
 
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= cm_t35_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= cm_t35_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= cm_t35_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index 8f9a64d..a27e3ee 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -167,10 +167,10 @@ static inline void cm_t3517_init_rtc(void) {}
 #define HSUSB2_RESET_GPIO	(147)
 #define USB_HUB_RESET_GPIO	(152)
 
-static struct ehci_hcd_omap_platform_data cm_t3517_ehci_pdata __initdata = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = HSUSB1_RESET_GPIO,
@@ -192,7 +192,7 @@ static int cm_t3517_init_usbh(void)
 		msleep(1);
 	}
 
-	usb_ehci_init(&cm_t3517_ehci_pdata);
+	usbhs_init(&cm_t3517_ehci_pdata);
 
 	return 0;
 }
@@ -254,16 +254,13 @@ static inline void cm_t3517_init_nand(void) {}
 static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
 };
 
-static void __init cm_t3517_init_irq(void)
+static void __init cm_t3517_init_early(void)
 {
-	omap_board_config = cm_t3517_config;
-	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
-
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
+#ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
 	OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -289,11 +286,14 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#endif
 
 static void __init cm_t3517_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_board_config = cm_t3517_config;
+	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
 	cm_t3517_init_rtc();
@@ -303,9 +303,10 @@ static void __init cm_t3517_init(void)
 
 MACHINE_START(CM_T3517, "Compulab CM-T3517")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve        = omap_reserve,
-	.init_irq	= cm_t3517_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= cm_t3517_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= cm_t3517_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 9a2a31e..aa27483 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -140,7 +140,7 @@ static void devkit8000_panel_disable_dvi(struct omap_dss_device *dssdev)
 }
 
 static struct regulator_consumer_supply devkit8000_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 
 /* ads7846 on SPI */
@@ -195,14 +195,6 @@ static struct omap_dss_board_info devkit8000_dss_data = {
 	.default_device = &devkit8000_lcd_device,
 };
 
-static struct platform_device devkit8000_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &devkit8000_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
 	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
@@ -350,9 +342,7 @@ static struct twl4030_usb_data devkit8000_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data devkit8000_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data devkit8000_audio_data;
 
 static struct twl4030_codec_data devkit8000_codec_data = {
 	.audio_mclk = 26000000,
@@ -456,11 +446,15 @@ static struct platform_device keys_gpio = {
 };
 
 
-static void __init devkit8000_init_irq(void)
+static void __init devkit8000_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
+}
+
+static void __init devkit8000_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -575,7 +569,6 @@ static void __init omap_dm9000_init(void)
 }
 
 static struct platform_device *devkit8000_devices[] __initdata = {
-	&devkit8000_dss_device,
 	&leds_gpio,
 	&keys_gpio,
 	&omap_dm9000_dev,
@@ -620,11 +613,11 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -632,6 +625,7 @@ static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
 	.reset_gpio_port[2]  = -EINVAL
 };
 
+#ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for Devkit8000 ethernet */
 	OMAP3_MUX(GPMC_NCS6, OMAP_MUX_MODE0),
@@ -785,6 +779,7 @@ static struct omap_board_mux board_mux[] __initdata = {
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#endif
 
 static void __init devkit8000_init(void)
 {
@@ -797,13 +792,14 @@ static void __init devkit8000_init(void)
 	platform_add_devices(devkit8000_devices,
 			ARRAY_SIZE(devkit8000_devices));
 
+	omap_display_init(&devkit8000_dss_data);
 	spi_register_board_info(devkit8000_spi_board_info,
 	ARRAY_SIZE(devkit8000_spi_board_info));
 
 	devkit8000_ads7846_init();
 
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	devkit8000_flash_init();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -813,8 +809,9 @@ static void __init devkit8000_init(void)
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= devkit8000_init_early,
 	.init_irq	= devkit8000_init_irq,
 	.init_machine	= devkit8000_init,
 	.timer		= &omap_timer,
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index fd38c05..729892f 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -1,5 +1,5 @@
 /*
- * board-sdp-flash.c
+ * board-flash.c
  * Modified from mach-omap2/board-3430sdp-flash.c
  *
  * Copyright (C) 2009 Nokia Corporation
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
+#include <plat/irqs.h>
 
 #include <plat/gpmc.h>
 #include <plat/nand.h>
@@ -73,11 +74,11 @@ __init board_nor_init(struct mtd_partition *nor_parts, u8 nr_parts, u8 cs)
 					+ FLASH_SIZE_SDPV1 - 1;
 	}
 	if (err < 0) {
-		printk(KERN_ERR "NOR: Can't request GPMC CS\n");
+		pr_err("NOR: Can't request GPMC CS\n");
 		return;
 	}
 	if (platform_device_register(&board_nor_device) < 0)
-		printk(KERN_ERR	"Unable to register NOR device\n");
+		pr_err("Unable to register NOR device\n");
 }
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -139,17 +140,21 @@ static struct omap_nand_platform_data board_nand_data = {
 };
 
 void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
+__init board_nand_init(struct mtd_partition *nand_parts,
+			u8 nr_parts, u8 cs, int nand_type)
 {
 	board_nand_data.cs		= cs;
 	board_nand_data.parts		= nand_parts;
-	board_nand_data.nr_parts		= nr_parts;
+	board_nand_data.nr_parts	= nr_parts;
+	board_nand_data.devsize		= nand_type;
 
+	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
+	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
 	gpmc_nand_init(&board_nand_data);
 }
 #else
 void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, int nand_type)
 {
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
@@ -189,12 +194,12 @@ unmap:
 }
 
 /**
- * sdp3430_flash_init - Identify devices connected to GPMC and register.
+ * board_flash_init - Identify devices connected to GPMC and register.
  *
  * @return - void.
  */
 void board_flash_init(struct flash_partitions partition_info[],
-					char chip_sel_board[][GPMC_CS_NUM])
+			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
 {
 	u8		cs = 0;
 	u8		norcs = GPMC_CS_NUM + 1;
@@ -208,7 +213,7 @@ void board_flash_init(struct flash_partitions partition_info[],
 	 */
 	idx = get_gpmc0_type();
 	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
-		printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs);
+		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
 		return;
 	}
 	config_sel = (unsigned char *)(chip_sel_board[idx]);
@@ -232,23 +237,20 @@ void board_flash_init(struct flash_partitions partition_info[],
 	}
 
 	if (norcs > GPMC_CS_NUM)
-		printk(KERN_INFO "NOR: Unable to find configuration "
-				"in GPMC\n");
+		pr_err("NOR: Unable to find configuration in GPMC\n");
 	else
 		board_nor_init(partition_info[0].parts,
 				partition_info[0].nr_parts, norcs);
 
 	if (onenandcs > GPMC_CS_NUM)
-		printk(KERN_INFO "OneNAND: Unable to find configuration "
-				"in GPMC\n");
+		pr_err("OneNAND: Unable to find configuration in GPMC\n");
 	else
 		board_onenand_init(partition_info[1].parts,
 					partition_info[1].nr_parts, onenandcs);
 
 	if (nandcs > GPMC_CS_NUM)
-		printk(KERN_INFO "NAND: Unable to find configuration "
-				"in GPMC\n");
+		pr_err("NAND: Unable to find configuration in GPMC\n");
 	else
 		board_nand_init(partition_info[2].parts,
-				partition_info[2].nr_parts, nandcs);
+			partition_info[2].nr_parts, nandcs, nand_type);
 }
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
index 69befe0..c240a3f 100644
--- a/arch/arm/mach-omap2/board-flash.h
+++ b/arch/arm/mach-omap2/board-flash.h
@@ -25,6 +25,6 @@ struct flash_partitions {
 };
 
 extern void board_flash_init(struct flash_partitions [],
-				char chip_sel[][GPMC_CS_NUM]);
+				char chip_sel[][GPMC_CS_NUM], int nand_type);
 extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs);
+					u8 nr_parts, u8 cs, int nand_type);
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 0e3d81e..73e3c31 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -33,18 +33,17 @@
 static struct omap_board_config_kernel generic_config[] = {
 };
 
-static void __init omap_generic_init_irq(void)
+static void __init omap_generic_init_early(void)
 {
-	omap_board_config = generic_config;
-	omap_board_config_size = ARRAY_SIZE(generic_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static void __init omap_generic_init(void)
 {
 	omap_serial_init();
+	omap_board_config = generic_config;
+	omap_board_config_size = ARRAY_SIZE(generic_config);
 }
 
 static void __init omap_generic_map_io(void)
@@ -68,9 +67,10 @@ static void __init omap_generic_map_io(void)
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_generic_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_generic_init_irq,
+	.map_io		= omap_generic_map_io,
+	.init_early	= omap_generic_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 25cc9da..bac7933 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -290,14 +290,15 @@ static struct omap_board_config_kernel h4_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&h4_lcd_config },
 };
 
-static void __init omap_h4_init_irq(void)
+static void __init omap_h4_init_early(void)
 {
-	omap_board_config = h4_config;
-	omap_board_config_size = ARRAY_SIZE(h4_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
+}
+
+static void __init omap_h4_init_irq(void)
+{
 	omap_init_irq();
-	h4_init_flash();
 }
 
 static struct at24_platform_data m24c01 = {
@@ -330,6 +331,9 @@ static void __init omap_h4_init(void)
 {
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF);
 
+	omap_board_config = h4_config;
+	omap_board_config_size = ARRAY_SIZE(h4_config);
+
 	/*
 	 * Make sure the serial ports are muxed on at this point.
 	 * You have to mux them off in device drivers later on
@@ -367,6 +371,7 @@ static void __init omap_h4_init(void)
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
+	h4_init_flash();
 }
 
 static void __init omap_h4_map_io(void)
@@ -378,8 +383,9 @@ static void __init omap_h4_map_io(void)
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_h4_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap_h4_map_io,
+	.init_early	= omap_h4_init_early,
 	.init_irq	= omap_h4_init_irq,
 	.init_machine	= omap_h4_init,
 	.timer		= &omap_timer,
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 3be85a1..d3199b4 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -250,7 +250,7 @@ static inline void __init igep2_init_smsc911x(void) { }
 #endif
 
 static struct regulator_consumer_supply igep2_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
@@ -268,7 +268,7 @@ static struct regulator_init_data igep2_vmmc1 = {
 };
 
 static struct regulator_consumer_supply igep2_vio_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
 
 static struct regulator_init_data igep2_vio = {
 	.constraints = {
@@ -286,7 +286,7 @@ static struct regulator_init_data igep2_vio = {
 };
 
 static struct regulator_consumer_supply igep2_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_init_data igep2_vmmc2 = {
 	.constraints		= {
@@ -485,18 +485,8 @@ static struct omap_dss_board_info igep2_dss_data = {
 	.default_device	= &igep2_dvi_device,
 };
 
-static struct platform_device igep2_dss_device = {
-	.name	= "omapdss",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &igep2_dss_data,
-	},
-};
-
-static struct regulator_consumer_supply igep2_vpll2_supply = {
-	.supply	= "vdds_dsi",
-	.dev	= &igep2_dss_device.dev,
-};
+static struct regulator_consumer_supply igep2_vpll2_supply =
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
 
 static struct regulator_init_data igep2_vpll2 = {
 	.constraints = {
@@ -521,21 +511,17 @@ static void __init igep2_display_init(void)
 }
 
 static struct platform_device *igep2_devices[] __initdata = {
-	&igep2_dss_device,
 	&igep2_vwlan_device,
 };
 
-static void __init igep2_init_irq(void)
+static void __init igep2_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(m65kxxxxam_sdrc_params,
 				  m65kxxxxam_sdrc_params);
-	omap_init_irq();
 }
 
-static struct twl4030_codec_audio_data igep2_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data igep2_audio_data;
 
 static struct twl4030_codec_data igep2_codec_data = {
 	.audio_mclk = 26000000,
@@ -627,10 +613,10 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset = true,
 	.reset_gpio_port[0] = IGEP2_GPIO_USBH_NRESET,
@@ -697,9 +683,10 @@ static void __init igep2_init(void)
 	/* Register I2C busses and drivers */
 	igep2_i2c_init();
 	platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
+	omap_display_init(&igep2_dss_data);
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 
 	igep2_flash_init();
 	igep2_leds_init();
@@ -716,9 +703,10 @@ static void __init igep2_init(void)
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= igep2_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= igep2_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= igep2_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
index 4dc62a9..b10db0e 100644
--- a/arch/arm/mach-omap2/board-igep0030.c
+++ b/arch/arm/mach-omap2/board-igep0030.c
@@ -142,7 +142,7 @@ static void __init igep3_flash_init(void) {}
 #endif
 
 static struct regulator_consumer_supply igep3_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep3_vmmc1 = {
@@ -160,7 +160,7 @@ static struct regulator_init_data igep3_vmmc1 = {
 };
 
 static struct regulator_consumer_supply igep3_vio_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
 
 static struct regulator_init_data igep3_vio = {
 	.constraints = {
@@ -178,7 +178,7 @@ static struct regulator_init_data igep3_vio = {
 };
 
 static struct regulator_consumer_supply igep3_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_init_data igep3_vmmc2 = {
 	.constraints	= {
@@ -331,12 +331,11 @@ static struct platform_device *igep3_devices[] __initdata = {
 	&igep3_vwlan_device,
 };
 
-static void __init igep3_init_irq(void)
+static void __init igep3_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(m65kxxxxam_sdrc_params,
 				  m65kxxxxam_sdrc_params);
-	omap_init_irq();
 }
 
 static struct twl4030_platform_data igep3_twl4030_pdata = {
@@ -408,10 +407,10 @@ static void __init igep3_wifi_bt_init(void)
 void __init igep3_wifi_bt_init(void) {}
 #endif
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset = true,
 	.reset_gpio_port[0] = -EINVAL,
@@ -435,7 +434,7 @@ static void __init igep3_init(void)
 	platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices));
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 
 	igep3_flash_init();
 	igep3_leds_init();
@@ -452,7 +451,8 @@ MACHINE_START(IGEP0030, "IGEP OMAP3 module")
 	.boot_params	= 0x80000100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_irq	= igep3_init_irq,
+	.init_early	= igep3_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= igep3_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index e5dc748..e2ba779 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -288,13 +288,10 @@ static struct omap_board_config_kernel ldp_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&ldp_lcd_config },
 };
 
-static void __init omap_ldp_init_irq(void)
+static void __init omap_ldp_init_early(void)
 {
-	omap_board_config = ldp_config;
-	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static struct twl4030_usb_data ldp_usb_data = {
@@ -330,6 +327,26 @@ static struct regulator_init_data ldp_vmmc1 = {
 	.consumer_supplies	= &ldp_vmmc1_supply,
 };
 
+/* ads7846 on SPI */
+static struct regulator_consumer_supply ldp_vaux1_supplies[] = {
+	REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
+
+/* VAUX1 */
+static struct regulator_init_data ldp_vaux1 = {
+	.constraints = {
+		.min_uV			= 3000000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies		= ARRAY_SIZE(ldp_vaux1_supplies),
+	.consumer_supplies		= ldp_vaux1_supplies,
+};
+
 static struct twl4030_platform_data ldp_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
@@ -338,6 +355,7 @@ static struct twl4030_platform_data ldp_twldata = {
 	.madc		= &ldp_madc_data,
 	.usb		= &ldp_usb_data,
 	.vmmc1		= &ldp_vmmc1,
+	.vaux1		= &ldp_vaux1,
 	.gpio		= &ldp_gpio_data,
 	.keypad		= &ldp_kp_twl4030_data,
 };
@@ -423,6 +441,8 @@ static struct mtd_partition ldp_nand_partitions[] = {
 static void __init omap_ldp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = ldp_config;
+	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	ldp_init_smsc911x();
 	omap_i2c_init();
 	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
@@ -434,7 +454,7 @@ static void __init omap_ldp_init(void)
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
 	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS);
+		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
 	omap2_hsmmc_init(mmc);
 	/* link regulators to MMC adapters */
@@ -443,9 +463,10 @@ static void __init omap_ldp_init(void)
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_ldp_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_ldp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_ldp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index f396756..e710cd9 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -536,7 +536,7 @@ static void __init n8x0_mmc_init(void)
 	}
 
 	mmc_data[0] = &mmc1_data;
-	omap2_init_mmc(mmc_data, OMAP24XX_NR_MMC);
+	omap242x_init_mmc(mmc_data);
 }
 #else
 
@@ -628,11 +628,10 @@ static void __init n8x0_map_io(void)
 	omap242x_map_common_io();
 }
 
-static void __init n8x0_init_irq(void)
+static void __init n8x0_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -703,27 +702,30 @@ static void __init n8x0_init_machine(void)
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
 	.boot_params	= 0x80000100,
-	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= n8x0_init_irq,
+	.map_io		= n8x0_map_io,
+	.init_early	= n8x0_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
 	.boot_params	= 0x80000100,
-	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= n8x0_init_irq,
+	.map_io		= n8x0_map_io,
+	.init_early	= n8x0_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
 	.boot_params	= 0x80000100,
-	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= n8x0_init_irq,
+	.map_io		= n8x0_map_io,
+	.init_early	= n8x0_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 46d814a..7640c05 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
+#include <linux/opp.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -45,10 +46,12 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
+#include <plat/omap_device.h>
 
 #include "mux.h"
 #include "hsmmc.h"
 #include "timer-gp.h"
+#include "pm.h"
 
 #define NAND_BLOCK_SIZE		SZ_128K
 
@@ -228,14 +231,6 @@ static struct omap_dss_board_info beagle_dss_data = {
 	.default_device = &beagle_dvi_device,
 };
 
-static struct platform_device beagle_dss_device = {
-	.name          = "omapdss",
-	.id            = -1,
-	.dev            = {
-		.platform_data = &beagle_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply beagle_vdac_supply =
 	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
@@ -435,9 +430,7 @@ static struct twl4030_usb_data beagle_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data beagle_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data beagle_audio_data;
 
 static struct twl4030_codec_data beagle_codec_data = {
 	.audio_mclk = 26000000,
@@ -536,11 +529,15 @@ static struct platform_device keys_gpio = {
 	},
 };
 
-static void __init omap3_beagle_init_irq(void)
+static void __init omap3_beagle_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
+}
+
+static void __init omap3_beagle_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -550,7 +547,6 @@ static void __init omap3_beagle_init_irq(void)
 static struct platform_device *omap3_beagle_devices[] __initdata = {
 	&leds_gpio,
 	&keys_gpio,
-	&beagle_dss_device,
 };
 
 static void __init omap3beagle_flash_init(void)
@@ -586,11 +582,11 @@ static void __init omap3beagle_flash_init(void)
 	}
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -610,6 +606,52 @@ static struct omap_musb_board_data musb_board_data = {
 	.power			= 100,
 };
 
+static void __init beagle_opp_init(void)
+{
+	int r = 0;
+
+	/* Initialize the omap3 opp table */
+	if (omap3_opp_init()) {
+		pr_err("%s: opp default init failed\n", __func__);
+		return;
+	}
+
+	/* Custom OPP enabled for XM */
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+		struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
+		struct omap_hwmod *dh = omap_hwmod_lookup("iva");
+		struct device *dev;
+
+		if (!mh || !dh) {
+			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
+				__func__, mh, dh);
+			return;
+		}
+		/* Enable MPU 1GHz and lower opps */
+		dev = &mh->od->pdev.dev;
+		r = opp_enable(dev, 800000000);
+		/* TODO: MPU 1GHz needs SR and ABB */
+
+		/* Enable IVA 800MHz and lower opps */
+		dev = &dh->od->pdev.dev;
+		r |= opp_enable(dev, 660000000);
+		/* TODO: DSP 800MHz needs SR and ABB */
+		if (r) {
+			pr_err("%s: failed to enable higher opp %d\n",
+				__func__, r);
+			/*
+			 * Cleanup - disable the higher freqs - we dont care
+			 * about the results
+			 */
+			dev = &mh->od->pdev.dev;
+			opp_disable(dev, 800000000);
+			dev = &dh->od->pdev.dev;
+			opp_disable(dev, 660000000);
+		}
+	}
+	return;
+}
+
 static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -617,6 +659,7 @@ static void __init omap3_beagle_init(void)
 	omap3_beagle_i2c_init();
 	platform_add_devices(omap3_beagle_devices,
 			ARRAY_SIZE(omap3_beagle_devices));
+	omap_display_init(&beagle_dss_data);
 	omap_serial_init();
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
@@ -625,7 +668,7 @@ static void __init omap3_beagle_init(void)
 	gpio_direction_output(170, true);
 
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	omap3beagle_flash_init();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -633,13 +676,15 @@ static void __init omap3_beagle_init(void)
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
 
 	beagle_display_init();
+	beagle_opp_init();
 }
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3_beagle_init_early,
 	.init_irq	= omap3_beagle_init_irq,
 	.init_machine	= omap3_beagle_init,
 	.timer		= &omap_timer,
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 323c380..0fa2c7b 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -30,6 +30,8 @@
 #include <linux/usb/otg.h>
 #include <linux/smsc911x.h>
 
+#include <linux/wl12xx.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
 
@@ -58,6 +60,13 @@
 #define OMAP3EVM_ETHR_ID_REV	0x50
 #define OMAP3EVM_ETHR_GPIO_IRQ	176
 #define OMAP3EVM_SMSC911X_CS	5
+/*
+ * Eth Reset signal
+ *	64 = Generation 1 (<=RevD)
+ *	7 = Generation 2 (>=RevE)
+ */
+#define OMAP3EVM_GEN1_ETHR_GPIO_RST	64
+#define OMAP3EVM_GEN2_ETHR_GPIO_RST	7
 
 static u8 omap3_evm_version;
 
@@ -124,10 +133,15 @@ static struct platform_device omap3evm_smsc911x_device = {
 
 static inline void __init omap3evm_init_smsc911x(void)
 {
-	int eth_cs;
+	int eth_cs, eth_rst;
 	struct clk *l3ck;
 	unsigned int rate;
 
+	if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1)
+		eth_rst = OMAP3EVM_GEN1_ETHR_GPIO_RST;
+	else
+		eth_rst = OMAP3EVM_GEN2_ETHR_GPIO_RST;
+
 	eth_cs = OMAP3EVM_SMSC911X_CS;
 
 	l3ck = clk_get(NULL, "l3_ck");
@@ -136,6 +150,27 @@ static inline void __init omap3evm_init_smsc911x(void)
 	else
 		rate = clk_get_rate(l3ck);
 
+	/* Configure ethernet controller reset gpio */
+	if (cpu_is_omap3430()) {
+		if (gpio_request(eth_rst, "SMSC911x gpio") < 0) {
+			pr_err(KERN_ERR "Failed to request %d for smsc911x\n",
+					eth_rst);
+			return;
+		}
+
+		if (gpio_direction_output(eth_rst, 1) < 0) {
+			pr_err(KERN_ERR "Failed to set direction of %d for" \
+					" smsc911x\n", eth_rst);
+			return;
+		}
+		/* reset pulse to ethernet controller*/
+		usleep_range(150, 220);
+		gpio_set_value(eth_rst, 0);
+		usleep_range(150, 220);
+		gpio_set_value(eth_rst, 1);
+		usleep_range(1, 2);
+	}
+
 	if (gpio_request(OMAP3EVM_ETHR_GPIO_IRQ, "SMSC911x irq") < 0) {
 		printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
 			OMAP3EVM_ETHR_GPIO_IRQ);
@@ -235,9 +270,9 @@ static int omap3_evm_enable_lcd(struct omap_dss_device *dssdev)
 	gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0);
 
 	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
 	else
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
 
 	lcd_enabled = 1;
 	return 0;
@@ -248,9 +283,9 @@ 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(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
 	else
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
 
 	lcd_enabled = 0;
 }
@@ -289,7 +324,7 @@ static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev)
 		return -EINVAL;
 	}
 
-	gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 1);
+	gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 1);
 
 	dvi_enabled = 1;
 	return 0;
@@ -297,7 +332,7 @@ static int omap3_evm_enable_dvi(struct omap_dss_device *dssdev)
 
 static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)
 {
-	gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 0);
+	gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 0);
 
 	dvi_enabled = 0;
 }
@@ -328,14 +363,6 @@ static struct omap_dss_board_info omap3_evm_dss_data = {
 	.default_device	= &omap3_evm_lcd_device,
 };
 
-static struct platform_device omap3_evm_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &omap3_evm_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply omap3evm_vmmc1_supply = {
 	.supply			= "vmmc",
 };
@@ -381,6 +408,16 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
 	},
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	{
+		.name		= "wl1271",
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.nonremovable	= true,
+	},
+#endif
 	{}	/* Terminator */
 };
 
@@ -411,6 +448,8 @@ static struct platform_device leds_gpio = {
 static int omap3evm_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
+	int r;
+
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
@@ -426,8 +465,12 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 	 */
 
 	/* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */
-	gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL");
-	gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+	r = gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL");
+	if (!r)
+		r = gpio_direction_output(gpio + TWL4030_GPIO_MAX,
+			(get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) ? 1 : 0);
+	if (r)
+		printk(KERN_ERR "failed to get/set lcd_bkl gpio\n");
 
 	/* gpio + 7 == DVI Enable */
 	gpio_request(gpio + 7, "EN_DVI");
@@ -491,19 +534,15 @@ static struct twl4030_madc_platform_data omap3evm_madc_data = {
 	.irq_line	= 1,
 };
 
-static struct twl4030_codec_audio_data omap3evm_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data omap3evm_audio_data;
 
 static struct twl4030_codec_data omap3evm_codec_data = {
 	.audio_mclk = 26000000,
 	.audio = &omap3evm_audio_data,
 };
 
-static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &omap3_evm_dss_device.dev,
-};
+static struct regulator_consumer_supply omap3_evm_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
 /* VDAC for DSS driving S-Video */
 static struct regulator_init_data omap3_evm_vdac = {
@@ -538,6 +577,66 @@ static struct regulator_init_data omap3_evm_vpll2 = {
 	.consumer_supplies	= &omap3_evm_vpll2_supply,
 };
 
+/* ads7846 on SPI */
+static struct regulator_consumer_supply omap3evm_vio_supply =
+	REGULATOR_SUPPLY("vcc", "spi1.0");
+
+/* VIO for ads7846 */
+static struct regulator_init_data omap3evm_vio = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &omap3evm_vio_supply,
+};
+
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+
+#define OMAP3EVM_WLAN_PMENA_GPIO	(150)
+#define OMAP3EVM_WLAN_IRQ_GPIO		(149)
+
+static struct regulator_consumer_supply omap3evm_vmmc2_supply =
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+
+/* VMMC2 for driving the WL12xx module */
+static struct regulator_init_data omap3evm_vmmc2 = {
+	.constraints = {
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies = &omap3evm_vmmc2_supply,
+};
+
+static struct fixed_voltage_config omap3evm_vwlan = {
+	.supply_name		= "vwl1271",
+	.microvolts		= 1800000, /* 1.80V */
+	.gpio			= OMAP3EVM_WLAN_PMENA_GPIO,
+	.startup_delay		= 70000, /* 70ms */
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &omap3evm_vmmc2,
+};
+
+static struct platform_device omap3evm_wlan_regulator = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &omap3evm_vwlan,
+	},
+};
+
+struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
+	.irq = OMAP_GPIO_IRQ(OMAP3EVM_WLAN_IRQ_GPIO),
+	.board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
+};
+#endif
+
 static struct twl4030_platform_data omap3evm_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
@@ -550,6 +649,7 @@ static struct twl4030_platform_data omap3evm_twldata = {
 	.codec		= &omap3evm_codec_data,
 	.vdac		= &omap3_evm_vdac,
 	.vpll2		= &omap3_evm_vpll2,
+	.vio		= &omap3evm_vio,
 };
 
 static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
@@ -625,24 +725,17 @@ static struct spi_board_info omap3evm_spi_board_info[] = {
 static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 };
 
-static void __init omap3_evm_init_irq(void)
+static void __init omap3_evm_init_early(void)
 {
-	omap_board_config = omap3_evm_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-	omap_init_irq();
 }
 
-static struct platform_device *omap3_evm_devices[] __initdata = {
-	&omap3_evm_dss_device,
-};
+static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
-
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	/* PHY reset GPIO will be runtime programmed based on EVM version */
@@ -652,14 +745,76 @@ static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
 };
 
 #ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
+static struct omap_board_mux omap35x_board_mux[] __initdata = {
+	OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+				OMAP_PIN_OFF_WAKEUPENABLE),
+	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+				OMAP_PIN_OFF_WAKEUPENABLE),
+	OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_NONE),
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	/* WLAN IRQ - GPIO 149 */
+	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+
+	/* WLAN POWER ENABLE - GPIO 150 */
+	OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+	/* MMC2 SDIO pin muxes for WL12xx */
+	OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+#endif
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static struct omap_board_mux omap36x_board_mux[] __initdata = {
 	OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
 				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
 				OMAP_PIN_OFF_WAKEUPENABLE),
 	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW),
+				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+				OMAP_PIN_OFF_WAKEUPENABLE),
+	/* AM/DM37x EVM: DSS data bus muxed with sys_boot */
+	OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT0, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT1, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT3, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	/* WLAN IRQ - GPIO 149 */
+	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+
+	/* WLAN POWER ENABLE - GPIO 150 */
+	OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+	/* MMC2 SDIO pin muxes for WL12xx */
+	OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+#endif
+
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#else
+#define omap35x_board_mux	NULL
+#define omap36x_board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
@@ -671,11 +826,18 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init omap3_evm_init(void)
 {
 	omap3_evm_get_revision();
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+	if (cpu_is_omap3630())
+		omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB);
+	else
+		omap3_mux_init(omap35x_board_mux, OMAP_PACKAGE_CBB);
+
+	omap_board_config = omap3_evm_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
 	omap3_evm_i2c_init();
 
-	platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices));
+	omap_display_init(&omap3_evm_dss_data);
 
 	spi_register_board_info(omap3evm_spi_board_info,
 				ARRAY_SIZE(omap3evm_spi_board_info));
@@ -700,7 +862,7 @@ static void __init omap3_evm_init(void)
 
 		/* setup EHCI phy reset config */
 		omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP);
-		ehci_pdata.reset_gpio_port[1] = 21;
+		usbhs_bdata.reset_gpio_port[1] = 21;
 
 		/* EVM REV >= E can supply 500mA with EXTVBUS programming */
 		musb_board_data.power = 500;
@@ -708,21 +870,29 @@ static void __init omap3_evm_init(void)
 	} else {
 		/* setup EHCI phy reset on MDC */
 		omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
-		ehci_pdata.reset_gpio_port[1] = 135;
+		usbhs_bdata.reset_gpio_port[1] = 135;
 	}
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	ads7846_dev_init();
 	omap3evm_init_smsc911x();
 	omap3_evm_display_init();
+
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	/* WL12xx WLAN Init */
+	if (wl12xx_set_platform_data(&omap3evm_wlan_data))
+		pr_err("error setting wl12xx data\n");
+	platform_device_register(&omap3evm_wlan_regulator);
+#endif
 }
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap3_evm_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3_evm_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3_evm_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 15e4b08..b726943 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -195,11 +195,10 @@ static inline void __init board_smsc911x_init(void)
 	gpmc_smsc911x_init(&board_smsc911x_data);
 }
 
-static void __init omap3logic_init_irq(void)
+static void __init omap3logic_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -225,7 +224,8 @@ static void __init omap3logic_init(void)
 MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
-	.init_irq	= omap3logic_init_irq,
+	.init_early	= omap3logic_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap_timer,
 MACHINE_END
@@ -233,7 +233,8 @@ MACHINE_END
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
-	.init_irq	= omap3logic_init_irq,
+	.init_early	= omap3logic_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index 0b34bed..2e5dc21 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -253,14 +253,6 @@ static struct omap_dss_board_info pandora_dss_data = {
 	.default_device	= &pandora_lcd_device,
 };
 
-static struct platform_device pandora_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &pandora_dss_data,
-	},
-};
-
 static void pandora_wl1251_init_card(struct mmc_card *card)
 {
 	/*
@@ -341,13 +333,13 @@ static struct twl4030_gpio_platform_data omap3pandora_gpio_data = {
 };
 
 static struct regulator_consumer_supply pandora_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 static struct regulator_consumer_supply pandora_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_consumer_supply pandora_vmmc3_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.2");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2");
 
 static struct regulator_consumer_supply pandora_vdda_dac_supply =
 	REGULATOR_SUPPLY("vdda_dac", "omapdss");
@@ -524,9 +516,7 @@ static struct twl4030_usb_data omap3pandora_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data omap3pandora_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data omap3pandora_audio_data;
 
 static struct twl4030_codec_data omap3pandora_codec_data = {
 	.audio_mclk = 26000000,
@@ -634,12 +624,11 @@ static struct spi_board_info omap3pandora_spi_board_info[] __initdata = {
 	}
 };
 
-static void __init omap3pandora_init_irq(void)
+static void __init omap3pandora_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
 }
 
 static void __init pandora_wl1251_init(void)
@@ -677,15 +666,14 @@ fail:
 static struct platform_device *omap3pandora_devices[] __initdata = {
 	&pandora_leds_gpio,
 	&pandora_keys_gpio,
-	&pandora_dss_device,
 	&pandora_vwlan_device,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 16,
@@ -712,11 +700,12 @@ static void __init omap3pandora_init(void)
 	pandora_wl1251_init();
 	platform_add_devices(omap3pandora_devices,
 			ARRAY_SIZE(omap3pandora_devices));
+	omap_display_init(&pandora_dss_data);
 	omap_serial_init();
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap3pandora_ads7846_init();
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	usb_musb_init(&musb_board_data);
 	gpmc_nand_init(&pandora_nand_data);
 
@@ -727,9 +716,10 @@ static void __init omap3pandora_init(void)
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap3pandora_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3pandora_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3pandora_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 2a2dad4..8ebdbc3 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -240,14 +240,6 @@ static struct omap_dss_board_info omap3_stalker_dss_data = {
 	.default_device	= &omap3_stalker_dvi_device,
 };
 
-static struct platform_device omap3_stalker_dss_device = {
-	.name	= "omapdss",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &omap3_stalker_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply omap3stalker_vmmc1_supply = {
 	.supply		= "vmmc",
 };
@@ -439,19 +431,15 @@ static struct twl4030_madc_platform_data omap3stalker_madc_data = {
 	.irq_line	= 1,
 };
 
-static struct twl4030_codec_audio_data omap3stalker_audio_data = {
-	.audio_mclk	= 26000000,
-};
+static struct twl4030_codec_audio_data omap3stalker_audio_data;
 
 static struct twl4030_codec_data omap3stalker_codec_data = {
 	.audio_mclk	= 26000000,
 	.audio		= &omap3stalker_audio_data,
 };
 
-static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &omap3_stalker_dss_device.dev,
-};
+static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
 /* VDAC for DSS driving S-Video */
 static struct regulator_init_data omap3_stalker_vdac = {
@@ -469,10 +457,8 @@ static struct regulator_init_data omap3_stalker_vdac = {
 };
 
 /* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_stalker_vpll2_supply = {
-	.supply		= "vdds_dsi",
-	.dev		= &omap3_stalker_lcd_device.dev,
-};
+static struct regulator_consumer_supply omap3_stalker_vpll2_supply =
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
 
 static struct regulator_init_data omap3_stalker_vpll2 = {
 	.constraints		= {
@@ -591,12 +577,14 @@ static struct spi_board_info omap3stalker_spi_board_info[] = {
 static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
 };
 
-static void __init omap3_stalker_init_irq(void)
+static void __init omap3_stalker_init_early(void)
 {
-	omap_board_config = omap3_stalker_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
+}
+
+static void __init omap3_stalker_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -604,14 +592,13 @@ static void __init omap3_stalker_init_irq(void)
 }
 
 static struct platform_device *omap3_stalker_devices[] __initdata = {
-	&omap3_stalker_dss_device,
 	&keys_gpio,
 };
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset = true,
 	.reset_gpio_port[0] = -EINVAL,
@@ -638,18 +625,21 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init omap3_stalker_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
+	omap_board_config = omap3_stalker_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
 			     ARRAY_SIZE(omap3_stalker_devices));
 
+	omap_display_init(&omap3_stalker_dss_data);
 	spi_register_board_info(omap3stalker_spi_board_info,
 				ARRAY_SIZE(omap3stalker_spi_board_info));
 
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	ads7846_dev_init();
 
 	omap_mux_init_gpio(21, OMAP_PIN_OUTPUT);
@@ -666,6 +656,7 @@ MACHINE_START(SBC3530, "OMAP3 STALKER")
 	/* Maintainer: Jason Lam -lzg@ema-tech.com */
 	.boot_params		= 0x80000100,
 	.map_io			= omap3_map_io,
+	.init_early		= omap3_stalker_init_early,
 	.init_irq		= omap3_stalker_init_irq,
 	.init_machine		= omap3_stalker_init,
 	.timer			= &omap_timer,
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index db1f74f..127cb17 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -252,9 +252,7 @@ static struct twl4030_usb_data touchbook_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data touchbook_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data touchbook_audio_data;
 
 static struct twl4030_codec_data touchbook_codec_data = {
 	.audio_mclk = 26000000,
@@ -415,14 +413,15 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init omap3_touchbook_init_irq(void)
+static void __init omap3_touchbook_init_early(void)
 {
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_board_config = omap3_touchbook_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
+}
+
+static void __init omap3_touchbook_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -468,11 +467,11 @@ static void __init omap3touchbook_flash_init(void)
 	}
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -510,6 +509,10 @@ static struct omap_musb_board_data musb_board_data = {
 
 static void __init omap3_touchbook_init(void)
 {
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = omap3_touchbook_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
+
 	pm_power_off = omap3_touchbook_poweroff;
 
 	omap3_touchbook_i2c_init();
@@ -527,7 +530,7 @@ static void __init omap3_touchbook_init(void)
 				ARRAY_SIZE(omap3_ads7846_spi_board_info));
 	omap3_ads7846_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	omap3touchbook_flash_init();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -538,8 +541,9 @@ static void __init omap3_touchbook_init(void)
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3_touchbook_init_early,
 	.init_irq	= omap3_touchbook_init_irq,
 	.init_machine	= omap3_touchbook_init,
 	.timer		= &omap_timer,
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index e944025..0f4d8a7 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -26,6 +26,8 @@
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
 
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
@@ -45,6 +47,18 @@
 
 #define GPIO_HUB_POWER		1
 #define GPIO_HUB_NRESET		62
+#define GPIO_WIFI_PMENA		43
+#define GPIO_WIFI_IRQ		53
+
+/* wl127x BT, FM, GPS connectivity chip */
+static int wl1271_gpios[] = {46, -1, -1};
+static struct platform_device wl1271_device = {
+	.name	= "kim",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &wl1271_gpios,
+	},
+};
 
 static struct gpio_led gpio_leds[] = {
 	{
@@ -74,19 +88,19 @@ static struct platform_device leds_gpio = {
 
 static struct platform_device *panda_devices[] __initdata = {
 	&leds_gpio,
+	&wl1271_device,
 };
 
-static void __init omap4_panda_init_irq(void)
+static void __init omap4_panda_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	gic_init_irq();
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.phy_reset  = false,
 	.reset_gpio_port[0]  = -EINVAL,
 	.reset_gpio_port[1]  = -EINVAL,
@@ -128,7 +142,7 @@ static void __init omap4_ehci_init(void)
 	gpio_set_value(GPIO_HUB_NRESET, 0);
 	gpio_set_value(GPIO_HUB_NRESET, 1);
 
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 
 	/* enable power to hub */
 	gpio_set_value(GPIO_HUB_POWER, 1);
@@ -153,6 +167,7 @@ static struct twl4030_usb_data omap4_usbphy_data = {
 	.phy_exit	= omap4430_phy_exit,
 	.phy_power	= omap4430_phy_power,
 	.phy_set_clock	= omap4430_phy_set_clk,
+	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct omap2_hsmmc_info mmc[] = {
@@ -162,16 +177,62 @@ static struct omap2_hsmmc_info mmc[] = {
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 	},
+	{
+		.name		= "wl1271",
+		.mmc		= 5,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.nonremovable	= true,
+	},
 	{}	/* Terminator */
 };
 
 static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
 	{
 		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.0",
+		.dev_name = "omap_hsmmc.0",
 	},
 };
 
+static struct regulator_consumer_supply omap4_panda_vmmc5_supply = {
+	.supply = "vmmc",
+	.dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data panda_vmmc5 = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &omap4_panda_vmmc5_supply,
+};
+
+static struct fixed_voltage_config panda_vwlan = {
+	.supply_name = "vwl1271",
+	.microvolts = 1800000, /* 1.8V */
+	.gpio = GPIO_WIFI_PMENA,
+	.startup_delay = 70000, /* 70msec */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &panda_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &panda_vwlan,
+	},
+};
+
+struct wl12xx_platform_data omap_panda_wlan_data  __initdata = {
+	.irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
+	/* PANDA ref clock is 38.4 MHz */
+	.board_ref_clock = 2,
+};
+
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
 	int ret = 0;
@@ -305,7 +366,6 @@ static struct regulator_init_data omap4_panda_vana = {
 	.constraints = {
 		.min_uV			= 2100000,
 		.max_uV			= 2100000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -317,7 +377,6 @@ static struct regulator_init_data omap4_panda_vcxio = {
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -329,7 +388,6 @@ static struct regulator_init_data omap4_panda_vdac = {
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -391,10 +449,90 @@ static int __init omap4_panda_i2c_init(void)
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* WLAN IRQ - GPIO 53 */
+	OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+	/* WLAN POWER ENABLE - GPIO 43 */
+	OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC5 CMD */
+	OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 CLK */
+	OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 DAT[0-3] */
+	OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial4_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart4_rx.uart4_rx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart4_tx.uart4_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial2_data = {
+	.id             = 1,
+	.pads           = serial2_pads,
+	.pads_cnt       = ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data = {
+	.id             = 2,
+	.pads           = serial3_pads,
+	.pads_cnt       = ARRAY_SIZE(serial3_pads),
+};
+
+static struct omap_board_data serial4_data = {
+	.id             = 3,
+	.pads           = serial4_pads,
+	.pads_cnt       = ARRAY_SIZE(serial4_pads),
+};
+
+static inline void board_serial_init(void)
+{
+	struct omap_board_data bdata;
+	bdata.flags     = 0;
+	bdata.pads      = NULL;
+	bdata.pads_cnt  = 0;
+	bdata.id        = 0;
+	/* pass dummy data for UART1 */
+	omap_serial_init_port(&bdata);
+
+	omap_serial_init_port(&serial2_data);
+	omap_serial_init_port(&serial3_data);
+	omap_serial_init_port(&serial4_data);
+}
 #else
 #define board_mux	NULL
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
 #endif
 
 static void __init omap4_panda_init(void)
@@ -405,9 +543,13 @@ static void __init omap4_panda_init(void)
 		package = OMAP_PACKAGE_CBL;
 	omap4_mux_init(board_mux, package);
 
+	if (wl12xx_set_platform_data(&omap_panda_wlan_data))
+		pr_err("error setting wl12xx data\n");
+
 	omap4_panda_i2c_init();
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
-	omap_serial_init();
+	platform_device_register(&omap_vwlan_device);
+	board_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
 	usb_musb_init(&musb_board_data);
@@ -424,7 +566,8 @@ MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
 	.boot_params	= 0x80000100,
 	.reserve	= omap_reserve,
 	.map_io		= omap4_panda_map_io,
-	.init_irq	= omap4_panda_init_irq,
+	.init_early	= omap4_panda_init_early,
+	.init_irq	= gic_init_irq,
 	.init_machine	= omap4_panda_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index cb26e5d..d096194 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -358,9 +358,7 @@ static struct regulator_init_data overo_vmmc1 = {
 	.consumer_supplies	= &overo_vmmc1_supply,
 };
 
-static struct twl4030_codec_audio_data overo_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data overo_audio_data;
 
 static struct twl4030_codec_data overo_codec_data = {
 	.audio_mclk = 26000000,
@@ -409,24 +407,21 @@ static struct omap_board_config_kernel overo_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&overo_lcd_config },
 };
 
-static void __init overo_init_irq(void)
+static void __init overo_init_early(void)
 {
-	omap_board_config = overo_config;
-	omap_board_config_size = ARRAY_SIZE(overo_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
 }
 
 static struct platform_device *overo_devices[] __initdata = {
 	&overo_lcd_device,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -449,12 +444,14 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init overo_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = overo_config;
+	omap_board_config_size = ARRAY_SIZE(overo_config);
 	overo_i2c_init();
 	platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices));
 	omap_serial_init();
 	overo_flash_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	overo_ads7846_init();
 	overo_init_smsc911x();
 
@@ -501,9 +498,10 @@ static void __init overo_init(void)
 
 MACHINE_START(OVERO, "Gumstix Overo")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= overo_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= overo_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= overo_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 39a71bb..2af8b05 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -33,7 +33,7 @@
 #include "sdram-nokia.h"
 
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"),
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
 
 /* Fixed regulator for internal eMMC */
@@ -138,14 +138,13 @@ static void __init rm680_peripherals_init(void)
 	omap2_hsmmc_init(mmc);
 }
 
-static void __init rm680_init_irq(void)
+static void __init rm680_init_early(void)
 {
 	struct omap_sdrc_params *sdrc_params;
 
 	omap2_init_common_infrastructure();
 	sdrc_params = nokia_get_sdram_timings();
 	omap2_init_common_devices(sdrc_params, sdrc_params);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -176,9 +175,10 @@ static void __init rm680_map_io(void)
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
 	.boot_params	= 0x80000100,
-	.map_io		= rm680_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= rm680_init_irq,
+	.map_io		= rm680_map_io,
+	.init_early	= rm680_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= rm680_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index e75e240..5f1900c 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -36,6 +36,8 @@
 
 #include <sound/tlv320aic3x.h>
 #include <sound/tpa6130a2-plat.h>
+#include <media/radio-si4713.h>
+#include <media/si4713.h>
 
 #include <../drivers/staging/iio/light/tsl2563.h>
 
@@ -47,6 +49,8 @@
 
 #define RX51_WL1251_POWER_GPIO		87
 #define RX51_WL1251_IRQ_GPIO		42
+#define RX51_FMTX_RESET_GPIO		163
+#define RX51_FMTX_IRQ			53
 
 /* list all spi devices here */
 enum {
@@ -331,13 +335,13 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
 };
 
 static struct regulator_consumer_supply rx51_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 static struct regulator_consumer_supply rx51_vaux3_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_consumer_supply rx51_vsim_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
 
 static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
 	/* tlv320aic3x analog supplies */
@@ -348,7 +352,7 @@ static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
 	/* tpa6130a2 */
 	REGULATOR_SUPPLY("Vdd", "2-0060"),
 	/* Keep vmmc as last item. It is not iterated for newer boards */
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"),
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
 
 static struct regulator_consumer_supply rx51_vio_supplies[] = {
@@ -357,10 +361,14 @@ static struct regulator_consumer_supply rx51_vio_supplies[] = {
 	REGULATOR_SUPPLY("DVDD", "2-0018"),
 	REGULATOR_SUPPLY("IOVDD", "2-0019"),
 	REGULATOR_SUPPLY("DVDD", "2-0019"),
+	/* Si4713 IO supply */
+	REGULATOR_SUPPLY("vio", "2-0063"),
 };
 
 static struct regulator_consumer_supply rx51_vaux1_consumers[] = {
 	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
+	/* Si4713 supply */
+	REGULATOR_SUPPLY("vdd", "2-0063"),
 };
 
 static struct regulator_consumer_supply rx51_vdac_supply[] = {
@@ -511,6 +519,41 @@ static struct regulator_init_data rx51_vio = {
 	.consumer_supplies	= rx51_vio_supplies,
 };
 
+static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = {
+	.gpio_reset	= RX51_FMTX_RESET_GPIO,
+};
+
+static struct i2c_board_info rx51_si4713_board_info __initdata_or_module = {
+	I2C_BOARD_INFO("si4713", SI4713_I2C_ADDR_BUSEN_HIGH),
+	.platform_data	= &rx51_si4713_i2c_data,
+};
+
+static struct radio_si4713_platform_data rx51_si4713_data __initdata_or_module = {
+	.i2c_bus	= 2,
+	.subdev_board_info = &rx51_si4713_board_info,
+};
+
+static struct platform_device rx51_si4713_dev __initdata_or_module = {
+	.name	= "radio-si4713",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &rx51_si4713_data,
+	},
+};
+
+static __init void rx51_init_si4713(void)
+{
+	int err;
+
+	err = gpio_request_one(RX51_FMTX_IRQ, GPIOF_DIR_IN, "si4713 irq");
+	if (err) {
+		printk(KERN_ERR "Cannot request si4713 irq gpio. %d\n", err);
+		return;
+	}
+	rx51_si4713_board_info.irq = gpio_to_irq(RX51_FMTX_IRQ);
+	platform_device_register(&rx51_si4713_dev);
+}
+
 static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
 {
 	/* FIXME this gpio setup is just a placeholder for now */
@@ -699,6 +742,14 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
 	.resource_config = twl4030_rconfig,
 };
 
+struct twl4030_codec_vibra_data rx51_vibra_data __initdata = {
+	.coexist	= 0,
+};
+
+struct twl4030_codec_data rx51_codec_data __initdata = {
+	.audio_mclk	= 26000000,
+	.vibra		= &rx51_vibra_data,
+};
 
 static struct twl4030_platform_data rx51_twldata __initdata = {
 	.irq_base		= TWL4030_IRQ_BASE,
@@ -710,6 +761,7 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
 	.madc			= &rx51_madc_data,
 	.usb			= &rx51_usb_data,
 	.power			= &rx51_t2scripts_data,
+	.codec			= &rx51_codec_data,
 
 	.vaux1			= &rx51_vaux1,
 	.vaux2			= &rx51_vaux2,
@@ -921,6 +973,7 @@ void __init rx51_peripherals_init(void)
 	board_smc91x_init();
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
+	rx51_init_si4713();
 	spi_register_board_info(rx51_peripherals_spi_board_info,
 				ARRAY_SIZE(rx51_peripherals_spi_board_info));
 
diff --git a/arch/arm/mach-omap2/board-rx51-video.c b/arch/arm/mach-omap2/board-rx51-video.c
index acd6700..89a66db 100644
--- a/arch/arm/mach-omap2/board-rx51-video.c
+++ b/arch/arm/mach-omap2/board-rx51-video.c
@@ -66,18 +66,6 @@ static struct omap_dss_board_info rx51_dss_board_info = {
 	.default_device	= &rx51_lcd_device,
 };
 
-struct platform_device rx51_display_device = {
-	.name	= "omapdss",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &rx51_dss_board_info,
-	},
-};
-
-static struct platform_device *rx51_video_devices[] __initdata = {
-	&rx51_display_device,
-};
-
 static int __init rx51_video_init(void)
 {
 	if (!machine_is_nokia_rx51())
@@ -95,8 +83,7 @@ static int __init rx51_video_init(void)
 
 	gpio_direction_output(RX51_LCD_RESET_GPIO, 1);
 
-	platform_add_devices(rx51_video_devices,
-				ARRAY_SIZE(rx51_video_devices));
+	omap_display_init(&rx51_dss_board_info);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index f53fc55..e964895 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -98,17 +98,13 @@ static struct omap_board_config_kernel rx51_config[] = {
 	{ OMAP_TAG_LCD,		&rx51_lcd_config },
 };
 
-static void __init rx51_init_irq(void)
+static void __init rx51_init_early(void)
 {
 	struct omap_sdrc_params *sdrc_params;
 
-	omap_board_config = rx51_config;
-	omap_board_config_size = ARRAY_SIZE(rx51_config);
-	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	omap2_init_common_infrastructure();
 	sdrc_params = nokia_get_sdram_timings();
 	omap2_init_common_devices(sdrc_params, sdrc_params);
-	omap_init_irq();
 }
 
 extern void __init rx51_peripherals_init(void);
@@ -128,6 +124,9 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init rx51_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = rx51_config;
+	omap_board_config_size = ARRAY_SIZE(rx51_config);
+	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
@@ -149,9 +148,10 @@ static void __init rx51_map_io(void)
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= rx51_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= rx51_init_irq,
+	.map_io		= rx51_map_io,
+	.init_early	= rx51_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= rx51_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
new file mode 100644
index 0000000..09fa7bf
--- /dev/null
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -0,0 +1,62 @@
+/*
+ * Code for TI8168 EVM.
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc. - 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 version 2.
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/irqs.h>
+#include <plat/board.h>
+#include <plat/common.h>
+
+static struct omap_board_config_kernel ti8168_evm_config[] __initdata = {
+};
+
+static void __init ti8168_init_early(void)
+{
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
+}
+
+static void __init ti8168_evm_init_irq(void)
+{
+	omap_init_irq();
+}
+
+static void __init ti8168_evm_init(void)
+{
+	omap_serial_init();
+	omap_board_config = ti8168_evm_config;
+	omap_board_config_size = ARRAY_SIZE(ti8168_evm_config);
+}
+
+static void __init ti8168_evm_map_io(void)
+{
+	omap2_set_globals_ti816x();
+	omapti816x_map_common_io();
+}
+
+MACHINE_START(TI8168EVM, "ti8168evm")
+	/* Maintainer: Texas Instruments */
+	.boot_params	= 0x80000100,
+	.map_io		= ti8168_evm_map_io,
+	.init_early	= ti8168_init_early,
+	.init_irq	= ti8168_evm_init_irq,
+	.timer		= &omap_timer,
+	.init_machine	= ti8168_evm_init,
+MACHINE_END
diff --git a/arch/arm/mach-omap2/board-zoom-display.c b/arch/arm/mach-omap2/board-zoom-display.c
index 6bcd436..37b84c2 100644
--- a/arch/arm/mach-omap2/board-zoom-display.c
+++ b/arch/arm/mach-omap2/board-zoom-display.c
@@ -130,14 +130,6 @@ static struct omap_dss_board_info zoom_dss_data = {
 	.default_device		= &zoom_lcd_device,
 };
 
-static struct platform_device zoom_dss_device = {
-	.name				= "omapdss",
-	.id				= -1,
-	.dev				= {
-		.platform_data		= &zoom_dss_data,
-	},
-};
-
 static struct omap2_mcspi_device_config dss_lcd_mcspi_config = {
 	.turbo_mode		= 1,
 	.single_channel	= 1,  /* 0: slave, 1: master */
@@ -153,14 +145,9 @@ static struct spi_board_info nec_8048_spi_board_info[] __initdata = {
 	},
 };
 
-static struct platform_device *zoom_display_devices[] __initdata = {
-	&zoom_dss_device,
-};
-
 void __init zoom_display_init(void)
 {
-	platform_add_devices(zoom_display_devices,
-				ARRAY_SIZE(zoom_display_devices));
+	omap_display_init(&zoom_dss_data);
 	spi_register_board_info(nec_8048_spi_board_info,
 				ARRAY_SIZE(nec_8048_spi_board_info));
 	zoom_lcd_panel_init();
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index e0e040f..448ab60 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -118,7 +118,7 @@ static struct regulator_consumer_supply zoom_vmmc2_supply = {
 
 static struct regulator_consumer_supply zoom_vmmc3_supply = {
 	.supply		= "vmmc",
-	.dev_name	= "mmci-omap-hs.2",
+	.dev_name	= "omap_hsmmc.2",
 };
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
@@ -322,9 +322,7 @@ static struct twl4030_madc_platform_data zoom_madc_data = {
 	.irq_line	= 1,
 };
 
-static struct twl4030_codec_audio_data zoom_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data zoom_audio_data;
 
 static struct twl4030_codec_data zoom_codec_data = {
 	.audio_mclk = 26000000,
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index e26754c..4b133d7 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -16,6 +16,7 @@
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -33,7 +34,7 @@
 
 #define ZOOM3_EHCI_RESET_GPIO		64
 
-static void __init omap_zoom_init_irq(void)
+static void __init omap_zoom_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	if (machine_is_omap_zoom2())
@@ -42,14 +43,12 @@ static void __init omap_zoom_init_irq(void)
 	else if (machine_is_omap_zoom3())
 		omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
 					  h8mbx00u0mer0em_sdrc_params);
-
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* WLAN IRQ - GPIO 162 */
-	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
 	/* WLAN POWER ENABLE - GPIO 101 */
 	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
 	/* WLAN SDIO: MMC3 CMD */
@@ -106,10 +105,10 @@ static struct mtd_partition zoom_nand_partitions[] = {
 	},
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1]		= EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0]		= OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1]		= OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2]		= OMAP_USBHS_PORT_MODE_UNUSED,
 	.phy_reset		= true,
 	.reset_gpio_port[0]	= -EINVAL,
 	.reset_gpio_port[1]	= ZOOM3_EHCI_RESET_GPIO,
@@ -123,11 +122,11 @@ static void __init omap_zoom_init(void)
 	} else if (machine_is_omap_zoom3()) {
 		omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
 		omap_mux_init_gpio(ZOOM3_EHCI_RESET_GPIO, OMAP_PIN_OUTPUT);
-		usb_ehci_init(&ehci_pdata);
+		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions,
-			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
+	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
+						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 	zoom_display_init();
@@ -135,18 +134,20 @@ static void __init omap_zoom_init(void)
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_zoom_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_zoom_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap_timer,
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_zoom_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_zoom_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/clkt2xxx_apll.c b/arch/arm/mach-omap2/clkt2xxx_apll.c
index f51cffd..b19a1f7 100644
--- a/arch/arm/mach-omap2/clkt2xxx_apll.c
+++ b/arch/arm/mach-omap2/clkt2xxx_apll.c
@@ -78,6 +78,26 @@ static int omap2_clk_apll54_enable(struct clk *clk)
 	return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK);
 }
 
+static void _apll96_allow_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll96_auto_low_power_stop();
+}
+
+static void _apll96_deny_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll96_disable_autoidle();
+}
+
+static void _apll54_allow_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll54_auto_low_power_stop();
+}
+
+static void _apll54_deny_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll54_disable_autoidle();
+}
+
 /* Stop APLL */
 static void omap2_clk_apll_disable(struct clk *clk)
 {
@@ -93,11 +113,15 @@ static void omap2_clk_apll_disable(struct clk *clk)
 const struct clkops clkops_apll96 = {
 	.enable		= omap2_clk_apll96_enable,
 	.disable	= omap2_clk_apll_disable,
+	.allow_idle	= _apll96_allow_idle,
+	.deny_idle	= _apll96_deny_idle,
 };
 
 const struct clkops clkops_apll54 = {
 	.enable		= omap2_clk_apll54_enable,
 	.disable	= omap2_clk_apll_disable,
+	.allow_idle	= _apll54_allow_idle,
+	.deny_idle	= _apll54_deny_idle,
 };
 
 /* Public functions */
diff --git a/arch/arm/mach-omap2/clkt2xxx_dpll.c b/arch/arm/mach-omap2/clkt2xxx_dpll.c
new file mode 100644
index 0000000..1502a7b
--- /dev/null
+++ b/arch/arm/mach-omap2/clkt2xxx_dpll.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP2-specific DPLL control functions
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+#include "clock.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+
+/* Private functions */
+
+/**
+ * _allow_idle - enable DPLL autoidle bits
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Enable DPLL automatic idle control.  The DPLL will enter low-power
+ * stop when its downstream clocks are gated.  No return value.
+ * REVISIT: DPLL can optionally enter low-power bypass by writing 0x1
+ * instead.  Add some mechanism to optionally enter this mode.
+ */
+static void _allow_idle(struct clk *clk)
+{
+	if (!clk || !clk->dpll_data)
+		return;
+
+	omap2xxx_cm_set_dpll_auto_low_power_stop();
+}
+
+/**
+ * _deny_idle - prevent DPLL from automatically idling
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Disable DPLL automatic idle control.  No return value.
+ */
+static void _deny_idle(struct clk *clk)
+{
+	if (!clk || !clk->dpll_data)
+		return;
+
+	omap2xxx_cm_set_dpll_disable_autoidle();
+}
+
+
+/* Public data */
+
+const struct clkops clkops_omap2xxx_dpll_ops = {
+	.allow_idle	= _allow_idle,
+	.deny_idle	= _deny_idle,
+};
+
diff --git a/arch/arm/mach-omap2/clkt2xxx_osc.c b/arch/arm/mach-omap2/clkt2xxx_osc.c
index df7b805..c346092 100644
--- a/arch/arm/mach-omap2/clkt2xxx_osc.c
+++ b/arch/arm/mach-omap2/clkt2xxx_osc.c
@@ -30,6 +30,13 @@
 #include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
+/*
+ * XXX This does not actually enable the osc_ck, since the osc_ck must
+ * be running for this function to be called.  Instead, this function
+ * is used to disable an autoidle mode on the osc_ck.  The existing
+ * clk_enable/clk_disable()-based usecounting for osc_ck should be
+ * replaced with autoidle-based usecounting.
+ */
 static int omap2_enable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
@@ -41,6 +48,13 @@ static int omap2_enable_osc_ck(struct clk *clk)
 	return 0;
 }
 
+/*
+ * XXX This does not actually disable the osc_ck, since doing so would
+ * immediately halt the system.  Instead, this function is used to
+ * enable an autoidle mode on the osc_ck.  The existing
+ * clk_enable/clk_disable()-based usecounting for osc_ck should be
+ * replaced with autoidle-based usecounting.
+ */
 static void omap2_disable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
diff --git a/arch/arm/mach-omap2/clkt_clksel.c b/arch/arm/mach-omap2/clkt_clksel.c
index a781cd6..e25364d 100644
--- a/arch/arm/mach-omap2/clkt_clksel.c
+++ b/arch/arm/mach-omap2/clkt_clksel.c
@@ -97,7 +97,7 @@ static u8 _get_div_and_fieldval(struct clk *src_clk, struct clk *clk,
 				u32 *field_val)
 {
 	const struct clksel *clks;
-	const struct clksel_rate *clkr, *max_clkr;
+	const struct clksel_rate *clkr, *max_clkr = NULL;
 	u8 max_div = 0;
 
 	clks = _get_clksel_by_parent(clk, src_clk);
diff --git a/arch/arm/mach-omap2/clkt_dpll.c b/arch/arm/mach-omap2/clkt_dpll.c
index acb7ae5..bcffee0 100644
--- a/arch/arm/mach-omap2/clkt_dpll.c
+++ b/arch/arm/mach-omap2/clkt_dpll.c
@@ -178,12 +178,11 @@ void omap2_init_dpll_parent(struct clk *clk)
 	if (!dd)
 		return;
 
-	/* Return bypass rate if DPLL is bypassed */
 	v = __raw_readl(dd->control_reg);
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
-	/* Reparent in case the dpll is in bypass */
+	/* Reparent the struct clk in case the dpll is in bypass */
 	if (cpu_is_omap24xx()) {
 		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
@@ -260,50 +259,22 @@ u32 omap2_get_dpll_rate(struct clk *clk)
 /* DPLL rate rounding code */
 
 /**
- * omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding
- * @clk: struct clk * of the DPLL
- * @tolerance: maximum rate error tolerance
- *
- * Set the maximum DPLL rate error tolerance for the rate rounding
- * algorithm.  The rate tolerance is an attempt to balance DPLL power
- * saving (the least divider value "n") vs. rate fidelity (the least
- * difference between the desired DPLL target rate and the rounded
- * rate out of the algorithm).  So, increasing the tolerance is likely
- * to decrease DPLL power consumption and increase DPLL rate error.
- * Returns -EINVAL if provided a null clock ptr or a clk that is not a
- * DPLL; or 0 upon success.
- */
-int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance)
-{
-	if (!clk || !clk->dpll_data)
-		return -EINVAL;
-
-	clk->dpll_data->rate_tolerance = tolerance;
-
-	return 0;
-}
-
-/**
  * omap2_dpll_round_rate - round a target rate for an OMAP DPLL
  * @clk: struct clk * for a DPLL
  * @target_rate: desired DPLL clock rate
  *
- * Given a DPLL, a desired target rate, and a rate tolerance, round
- * the target rate to a possible, programmable rate for this DPLL.
- * Rate tolerance is assumed to be set by the caller before this
- * function is called.  Attempts to select the minimum possible n
- * within the tolerance to reduce power consumption.  Stores the
- * computed (m, n) in the DPLL's dpll_data structure so set_rate()
- * will not need to call this (expensive) function again.  Returns ~0
- * if the target rate cannot be rounded, either because the rate is
- * too low or because the rate tolerance is set too tightly; or the
- * rounded rate upon success.
+ * Given a DPLL and a desired target rate, round the target rate to a
+ * possible, programmable rate for this DPLL.  Attempts to select the
+ * minimum possible n.  Stores the computed (m, n) in the DPLL's
+ * dpll_data structure so set_rate() will not need to call this
+ * (expensive) function again.  Returns ~0 if the target rate cannot
+ * be rounded, or the rounded rate upon success.
  */
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 {
-	int m, n, r, e, scaled_max_m;
-	unsigned long scaled_rt_rp, new_rate;
-	int min_e = -1, min_e_m = -1, min_e_n = -1;
+	int m, n, r, scaled_max_m;
+	unsigned long scaled_rt_rp;
+	unsigned long new_rate = 0;
 	struct dpll_data *dd;
 
 	if (!clk || !clk->dpll_data)
@@ -311,8 +282,8 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 
 	dd = clk->dpll_data;
 
-	pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
-		 "%ld\n", clk->name, target_rate);
+	pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
+		 clk->name, target_rate);
 
 	scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
 	scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
@@ -347,39 +318,23 @@ long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 		if (r == DPLL_MULT_UNDERFLOW)
 			continue;
 
-		e = target_rate - new_rate;
-		pr_debug("clock: n = %d: m = %d: rate error is %d "
-			 "(new_rate = %ld)\n", n, m, e, new_rate);
-
-		if (min_e == -1 ||
-		    min_e >= (int)(abs(e) - dd->rate_tolerance)) {
-			min_e = e;
-			min_e_m = m;
-			min_e_n = n;
-
-			pr_debug("clock: found new least error %d\n", min_e);
+		pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
+			 clk->name, m, n, new_rate);
 
-			/* We found good settings -- bail out now */
-			if (min_e <= dd->rate_tolerance)
-				break;
+		if (target_rate == new_rate) {
+			dd->last_rounded_m = m;
+			dd->last_rounded_n = n;
+			dd->last_rounded_rate = target_rate;
+			break;
 		}
 	}
 
-	if (min_e < 0) {
-		pr_debug("clock: error: target rate or tolerance too low\n");
+	if (target_rate != new_rate) {
+		pr_debug("clock: %s: cannot round to rate %ld\n", clk->name,
+			 target_rate);
 		return ~0;
 	}
 
-	dd->last_rounded_m = min_e_m;
-	dd->last_rounded_n = min_e_n;
-	dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate,
-						       min_e_m,  min_e_n);
-
-	pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
-		 min_e, min_e_m, min_e_n);
-	pr_debug("clock: final rate: %ld  (target rate: %ld)\n",
-		 dd->last_rounded_rate, target_rate);
-
-	return dd->last_rounded_rate;
+	return target_rate;
 }
 
diff --git a/arch/arm/mach-omap2/clkt_iclk.c b/arch/arm/mach-omap2/clkt_iclk.c
new file mode 100644
index 0000000..3d43fba
--- /dev/null
+++ b/arch/arm/mach-omap2/clkt_iclk.c
@@ -0,0 +1,82 @@
+/*
+ * OMAP2/3 interface clock control
+ *
+ * Copyright (C) 2011 Nokia Corporation
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+#include <plat/prcm.h>
+
+#include "clock.h"
+#include "clock2xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+
+/* Private functions */
+
+/* XXX */
+void omap2_clkt_iclk_allow_idle(struct clk *clk)
+{
+	u32 v, r;
+
+	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+	v = __raw_readl((__force void __iomem *)r);
+	v |= (1 << clk->enable_bit);
+	__raw_writel(v, (__force void __iomem *)r);
+}
+
+/* XXX */
+void omap2_clkt_iclk_deny_idle(struct clk *clk)
+{
+	u32 v, r;
+
+	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+	v = __raw_readl((__force void __iomem *)r);
+	v &= ~(1 << clk->enable_bit);
+	__raw_writel(v, (__force void __iomem *)r);
+}
+
+/* Public data */
+
+const struct clkops clkops_omap2_iclk_dflt_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_companion	= omap2_clk_dflt_find_companion,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_iclk_dflt = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_iclk_idle_only = {
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_mdmclk_dflt_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_companion	= omap2_clk_dflt_find_companion,
+	.find_idlest	= omap2_clk_dflt_find_idlest,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index 2a2f152..180299e 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -22,7 +22,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <trace/events/power.h>
 
+#include <asm/cpu.h>
 #include <plat/clock.h>
 #include "clockdomain.h"
 #include <plat/cpu.h>
@@ -261,10 +263,13 @@ void omap2_clk_disable(struct clk *clk)
 
 	pr_debug("clock: %s: disabling in hardware\n", clk->name);
 
-	clk->ops->disable(clk);
+	if (clk->ops && clk->ops->disable) {
+		trace_clock_disable(clk->name, 0, smp_processor_id());
+		clk->ops->disable(clk);
+	}
 
 	if (clk->clkdm)
-		omap2_clkdm_clk_disable(clk->clkdm, clk);
+		clkdm_clk_disable(clk->clkdm, clk);
 
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
@@ -304,7 +309,7 @@ int omap2_clk_enable(struct clk *clk)
 	}
 
 	if (clk->clkdm) {
-		ret = omap2_clkdm_clk_enable(clk->clkdm, clk);
+		ret = clkdm_clk_enable(clk->clkdm, clk);
 		if (ret) {
 			WARN(1, "clock: %s: could not enable clockdomain %s: "
 			     "%d\n", clk->name, clk->clkdm->name, ret);
@@ -312,17 +317,21 @@ int omap2_clk_enable(struct clk *clk)
 		}
 	}
 
-	ret = clk->ops->enable(clk);
-	if (ret) {
-		WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret);
-		goto oce_err3;
+	if (clk->ops && clk->ops->enable) {
+		trace_clock_enable(clk->name, 1, smp_processor_id());
+		ret = clk->ops->enable(clk);
+		if (ret) {
+			WARN(1, "clock: %s: could not enable: %d\n",
+			     clk->name, ret);
+			goto oce_err3;
+		}
 	}
 
 	return 0;
 
 oce_err3:
 	if (clk->clkdm)
-		omap2_clkdm_clk_disable(clk->clkdm, clk);
+		clkdm_clk_disable(clk->clkdm, clk);
 oce_err2:
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
@@ -349,8 +358,10 @@ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
 	pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
 
 	/* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
-	if (clk->set_rate)
+	if (clk->set_rate) {
+		trace_clock_set_rate(clk->name, rate, smp_processor_id());
 		ret = clk->set_rate(clk, rate);
+	}
 
 	return ret;
 }
@@ -373,10 +384,16 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
 const struct clkops clkops_omap3_noncore_dpll_ops = {
 	.enable		= omap3_noncore_dpll_enable,
 	.disable	= omap3_noncore_dpll_disable,
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
 };
 
-#endif
+const struct clkops clkops_omap3_core_dpll_ops = {
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
+};
 
+#endif
 
 /*
  * OMAP2+ clock reset and init functions
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 896584e..e10ff2b 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -2,7 +2,7 @@
  *  linux/arch/arm/mach-omap2/clock.h
  *
  *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2009 Nokia Corporation
+ *  Copyright (C) 2004-2011 Nokia Corporation
  *
  *  Contacts:
  *  Richard Woodruff <r-woodruff2@ti.com>
@@ -18,9 +18,6 @@
 
 #include <plat/clock.h>
 
-/* The maximum error between a target DPLL rate and the rounded rate in Hz */
-#define DEFAULT_DPLL_RATE_TOLERANCE	50000
-
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K		0x0
 #define CORE_CLK_SRC_DPLL		0x1
@@ -55,7 +52,6 @@ void omap2_clk_disable(struct clk *clk);
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
-int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance);
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
 unsigned long omap3_dpll_recalc(struct clk *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk *clk);
@@ -65,6 +61,9 @@ u32 omap3_dpll_autoidle_read(struct clk *clk);
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
 int omap3_noncore_dpll_enable(struct clk *clk);
 void omap3_noncore_dpll_disable(struct clk *clk);
+int omap4_dpllmx_gatectrl_read(struct clk *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk *clk);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
@@ -83,6 +82,10 @@ long omap2_clksel_round_rate(struct clk *clk, unsigned long target_rate);
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
 
+/* clkt_iclk.c public functions */
+extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
+extern void omap2_clkt_iclk_deny_idle(struct clk *clk);
+
 u32 omap2_get_dpll_rate(struct clk *clk);
 void omap2_init_dpll_parent(struct clk *clk);
 
@@ -136,6 +139,7 @@ extern struct clk *vclk, *sclk;
 extern const struct clksel_rate gpt_32k_rates[];
 extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
+extern const struct clksel_rate dsp_ick_rates[];
 
 #if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
 extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
@@ -145,6 +149,13 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
 #define omap2_clk_exit_cpufreq_table	0
 #endif
 
+extern const struct clkops clkops_omap2_iclk_dflt_wait;
+extern const struct clkops clkops_omap2_iclk_dflt;
+extern const struct clkops clkops_omap2_iclk_idle_only;
+extern const struct clkops clkops_omap2_mdmclk_dflt_wait;
+extern const struct clkops clkops_omap2xxx_dpll_ops;
 extern const struct clkops clkops_omap3_noncore_dpll_ops;
+extern const struct clkops clkops_omap3_core_dpll_ops;
+extern const struct clkops clkops_omap4_dpllmx_ops;
 
 #endif
diff --git a/arch/arm/mach-omap2/clock2420_data.c b/arch/arm/mach-omap2/clock2420_data.c
index 0a992bc..b6f65d4 100644
--- a/arch/arm/mach-omap2/clock2420_data.c
+++ b/arch/arm/mach-omap2/clock2420_data.c
@@ -1,12 +1,12 @@
 /*
- *  linux/arch/arm/mach-omap2/clock2420_data.c
+ * OMAP2420 clock data
  *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2010 Nokia Corporation
+ * Copyright (C) 2005-2009 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
  *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -34,18 +34,15 @@
 /*
  * 2420 clock tree.
  *
- * NOTE:In many cases here we are assigning a 'default' parent.	In many
- *	cases the parent is selectable.	The get/set parent calls will also
- *	switch sources.
- *
- *	Many some clocks say always_enabled, but they can be auto idled for
- *	power savings. They will always be available upon clock request.
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
  *
  *	Several sources are given initial rates which may be wrong, this will
  *	be fixed up in the init func.
  *
  *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most periferals have dependencies on multiple clock
+ *	noteworthy that most peripherals have dependencies on multiple clock
  *	domains. Many get their interface clocks from the L4 domain, but get
  *	functional clocks from fixed sources or other core domain derived
  *	clocks.
@@ -55,7 +52,7 @@
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.ops		= &clkops_null,
-	.rate		= 32000,
+	.rate		= 32768,
 	.clkdm_name	= "wkup_clkdm",
 };
 
@@ -116,7 +113,6 @@ static struct dpll_data dpll_dd = {
 	.max_multiplier		= 1023,
 	.min_divider		= 1,
 	.max_divider		= 16,
-	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 /*
@@ -125,7 +121,7 @@ static struct dpll_data dpll_dd = {
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2xxx_dpll_ops,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
 	.clkdm_name	= "wkup_clkdm",
@@ -455,36 +451,22 @@ static struct clk dsp_fck = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* DSP interface clock */
-static const struct clksel_rate dsp_irate_ick_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_irate_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
 	{ .parent = NULL }
 };
 
-/* This clock does not exist as such in the TRM. */
-static struct clk dsp_irate_ick = {
-	.name		= "dsp_irate_ick",
-	.ops		= &clkops_null,
-	.parent		= &dsp_fck,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_irate_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* 2420 only */
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_irate_ick,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &dsp_fck,
+	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /*
@@ -579,7 +561,7 @@ static const struct clksel usb_l4_ick_clksel[] = {
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -661,7 +643,7 @@ static struct clk ssi_ssr_sst_fck = {
  */
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -716,6 +698,7 @@ static struct clk gfx_2d_fck = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
 	.ops		= &clkops_omap2_dflt_wait,
@@ -763,7 +746,7 @@ static const struct clksel dss1_fck_clksel[] = {
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -825,6 +808,14 @@ static struct clk dss_54m_fck = {	/* Alt clk used in power management */
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk wu_l4_ick = {
+	.name		= "wu_l4_ick",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
+	.clkdm_name	= "wkup_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /*
  * CORE power domain ICLK & FCLK defines.
  * Many of the these can have more than one possible parent. Entries
@@ -845,9 +836,9 @@ static const struct clksel omap24xx_gpt_clksel[] = {
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -871,7 +862,7 @@ static struct clk gpt1_fck = {
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -895,7 +886,7 @@ static struct clk gpt2_fck = {
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -919,7 +910,7 @@ static struct clk gpt3_fck = {
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -943,7 +934,7 @@ static struct clk gpt4_fck = {
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -967,7 +958,7 @@ static struct clk gpt5_fck = {
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -991,8 +982,9 @@ static struct clk gpt6_fck = {
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1014,7 +1006,7 @@ static struct clk gpt7_fck = {
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1038,7 +1030,7 @@ static struct clk gpt8_fck = {
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1062,7 +1054,7 @@ static struct clk gpt9_fck = {
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1086,7 +1078,7 @@ static struct clk gpt10_fck = {
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1110,7 +1102,7 @@ static struct clk gpt11_fck = {
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1134,7 +1126,7 @@ static struct clk gpt12_fck = {
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1174,7 +1166,7 @@ static struct clk mcbsp1_fck = {
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1198,7 +1190,7 @@ static struct clk mcbsp2_fck = {
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1218,7 +1210,7 @@ static struct clk mcspi1_fck = {
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1238,7 +1230,7 @@ static struct clk mcspi2_fck = {
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1258,7 +1250,7 @@ static struct clk uart1_fck = {
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1278,7 +1270,7 @@ static struct clk uart2_fck = {
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1298,9 +1290,9 @@ static struct clk uart3_fck = {
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1318,9 +1310,9 @@ static struct clk gpios_fck = {
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1338,10 +1330,10 @@ static struct clk mpu_wdt_fck = {
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1349,9 +1341,9 @@ static struct clk sync_32k_ick = {
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1359,10 +1351,10 @@ static struct clk wdt1_ick = {
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1370,7 +1362,7 @@ static struct clk omapctrl_ick = {
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1395,7 +1387,7 @@ static struct clk cam_fck = {
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1405,7 +1397,7 @@ static struct clk mailboxes_ick = {
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1425,7 +1417,7 @@ static struct clk wdt4_fck = {
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1445,7 +1437,7 @@ static struct clk wdt3_fck = {
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1465,7 +1457,7 @@ static struct clk mspro_fck = {
 
 static struct clk mmc_ick = {
 	.name		= "mmc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1485,7 +1477,7 @@ static struct clk mmc_fck = {
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1505,7 +1497,7 @@ static struct clk fac_fck = {
 
 static struct clk eac_ick = {
 	.name		= "eac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1525,7 +1517,7 @@ static struct clk eac_fck = {
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1545,7 +1537,7 @@ static struct clk hdq_fck = {
 
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1565,7 +1557,7 @@ static struct clk i2c2_fck = {
 
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1583,12 +1575,18 @@ static struct clk i2c1_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
+	.ops		= &clkops_omap2_iclk_idle_only,
 	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1600,17 +1598,38 @@ static struct clk sdma_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
+	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
+	.recalc		= &followparent_recalc,
+};
+
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
+static struct clk sdrc_ick = {
+	.name		= "sdrc_ick",
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
+	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk vlynq_ick = {
 	.name		= "vlynq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1659,7 +1678,7 @@ static struct clk vlynq_fck = {
 
 static struct clk des_ick = {
 	.name		= "des_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1669,7 +1688,7 @@ static struct clk des_ick = {
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1679,7 +1698,7 @@ static struct clk sha_ick = {
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1689,7 +1708,7 @@ static struct clk rng_ick = {
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1699,7 +1718,7 @@ static struct clk aes_ick = {
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1777,7 +1796,6 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_242X),
 	/* dsp domain clocks */
 	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_242X),
-	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_242X),
 	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
 	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
 	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
@@ -1797,6 +1815,7 @@ static struct omap_clk omap2420_clks[] = {
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_242X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_242X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_242X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -1869,6 +1888,7 @@ static struct omap_clk omap2420_clks[] = {
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_242X),
 	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
 	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
 	CLK(NULL,	"des_ick",	&des_ick,	CK_242X),
@@ -1913,6 +1933,9 @@ int __init omap2420_clk_init(void)
 		omap2_init_clk_clkdm(c->lk.clk);
 	}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
diff --git a/arch/arm/mach-omap2/clock2430_data.c b/arch/arm/mach-omap2/clock2430_data.c
index c047dcd..bba0183 100644
--- a/arch/arm/mach-omap2/clock2430_data.c
+++ b/arch/arm/mach-omap2/clock2430_data.c
@@ -1,12 +1,12 @@
 /*
- *  linux/arch/arm/mach-omap2/clock2430_data.c
+ * OMAP2430 clock data
  *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2010 Nokia Corporation
+ * Copyright (C) 2005-2009 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
  *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
+ * Contacts:
+ * Richard Woodruff <r-woodruff2@ti.com>
+ * Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -34,18 +34,15 @@
 /*
  * 2430 clock tree.
  *
- * NOTE:In many cases here we are assigning a 'default' parent.	In many
- *	cases the parent is selectable.	The get/set parent calls will also
- *	switch sources.
- *
- *	Many some clocks say always_enabled, but they can be auto idled for
- *	power savings. They will always be available upon clock request.
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
  *
  *	Several sources are given initial rates which may be wrong, this will
  *	be fixed up in the init func.
  *
  *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most periferals have dependencies on multiple clock
+ *	noteworthy that most peripherals have dependencies on multiple clock
  *	domains. Many get their interface clocks from the L4 domain, but get
  *	functional clocks from fixed sources or other core domain derived
  *	clocks.
@@ -55,7 +52,7 @@
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.ops		= &clkops_null,
-	.rate		= 32000,
+	.rate		= 32768,
 	.clkdm_name	= "wkup_clkdm",
 };
 
@@ -116,7 +113,6 @@ static struct dpll_data dpll_dd = {
 	.max_multiplier		= 1023,
 	.min_divider		= 1,
 	.max_divider		= 16,
-	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 /*
@@ -125,7 +121,7 @@ static struct dpll_data dpll_dd = {
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2xxx_dpll_ops,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
 	.clkdm_name	= "wkup_clkdm",
@@ -434,37 +430,23 @@ static struct clk dsp_fck = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* DSP interface clock */
-static const struct clksel_rate dsp_irate_ick_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_irate_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
 	{ .parent = NULL }
 };
 
-/* This clock does not exist as such in the TRM. */
-static struct clk dsp_irate_ick = {
-	.name		= "dsp_irate_ick",
-	.ops		= &clkops_null,
-	.parent		= &dsp_fck,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_irate_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
 /* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_irate_ick,
+	.parent		= &dsp_fck,
+	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /*
@@ -525,7 +507,7 @@ static const struct clksel usb_l4_ick_clksel[] = {
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -606,7 +588,7 @@ static struct clk ssi_ssr_sst_fck = {
  */
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -661,6 +643,7 @@ static struct clk gfx_2d_fck = {
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
 	.ops		= &clkops_omap2_dflt_wait,
@@ -693,7 +676,7 @@ static const struct clksel mdm_ick_clksel[] = {
 
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_ck,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
@@ -706,7 +689,7 @@ static struct clk mdm_ick = {		/* used both as a ick and fck */
 
 static struct clk mdm_osc_ck = {
 	.name		= "mdm_osc_ck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_mdmclk_dflt_wait,
 	.parent		= &osc_ck,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
@@ -751,7 +734,7 @@ static const struct clksel dss1_fck_clksel[] = {
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -813,6 +796,14 @@ static struct clk dss_54m_fck = {	/* Alt clk used in power management */
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk wu_l4_ick = {
+	.name		= "wu_l4_ick",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
+	.clkdm_name	= "wkup_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /*
  * CORE power domain ICLK & FCLK defines.
  * Many of the these can have more than one possible parent. Entries
@@ -833,9 +824,9 @@ static const struct clksel omap24xx_gpt_clksel[] = {
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -859,7 +850,7 @@ static struct clk gpt1_fck = {
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -883,7 +874,7 @@ static struct clk gpt2_fck = {
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -907,7 +898,7 @@ static struct clk gpt3_fck = {
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -931,7 +922,7 @@ static struct clk gpt4_fck = {
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -955,7 +946,7 @@ static struct clk gpt5_fck = {
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -979,8 +970,9 @@ static struct clk gpt6_fck = {
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1002,7 +994,7 @@ static struct clk gpt7_fck = {
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1026,7 +1018,7 @@ static struct clk gpt8_fck = {
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1050,7 +1042,7 @@ static struct clk gpt9_fck = {
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1074,7 +1066,7 @@ static struct clk gpt10_fck = {
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1098,7 +1090,7 @@ static struct clk gpt11_fck = {
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1122,7 +1114,7 @@ static struct clk gpt12_fck = {
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1162,7 +1154,7 @@ static struct clk mcbsp1_fck = {
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1186,7 +1178,7 @@ static struct clk mcbsp2_fck = {
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1210,7 +1202,7 @@ static struct clk mcbsp3_fck = {
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1234,7 +1226,7 @@ static struct clk mcbsp4_fck = {
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1258,7 +1250,7 @@ static struct clk mcbsp5_fck = {
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1278,7 +1270,7 @@ static struct clk mcspi1_fck = {
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1298,7 +1290,7 @@ static struct clk mcspi2_fck = {
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1318,7 +1310,7 @@ static struct clk mcspi3_fck = {
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1338,7 +1330,7 @@ static struct clk uart1_fck = {
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1358,7 +1350,7 @@ static struct clk uart2_fck = {
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1378,9 +1370,9 @@ static struct clk uart3_fck = {
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1398,9 +1390,9 @@ static struct clk gpios_fck = {
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1418,10 +1410,10 @@ static struct clk mpu_wdt_fck = {
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1429,9 +1421,9 @@ static struct clk sync_32k_ick = {
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1439,10 +1431,10 @@ static struct clk wdt1_ick = {
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1450,9 +1442,9 @@ static struct clk omapctrl_ick = {
 
 static struct clk icr_ick = {
 	.name		= "icr_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1460,7 +1452,7 @@ static struct clk icr_ick = {
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1485,7 +1477,7 @@ static struct clk cam_fck = {
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1495,7 +1487,7 @@ static struct clk mailboxes_ick = {
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1515,7 +1507,7 @@ static struct clk wdt4_fck = {
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1535,7 +1527,7 @@ static struct clk mspro_fck = {
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1555,7 +1547,7 @@ static struct clk fac_fck = {
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1579,7 +1571,7 @@ static struct clk hdq_fck = {
  */
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1603,7 +1595,7 @@ static struct clk i2chs2_fck = {
  */
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1621,12 +1613,18 @@ static struct clk i2chs1_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
+	.ops		= &clkops_omap2_iclk_idle_only,
 	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1638,20 +1636,26 @@ static struct clk sdma_fck = {
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1659,7 +1663,7 @@ static struct clk sdrc_ick = {
 
 static struct clk des_ick = {
 	.name		= "des_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1669,7 +1673,7 @@ static struct clk des_ick = {
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1679,7 +1683,7 @@ static struct clk sha_ick = {
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1689,7 +1693,7 @@ static struct clk rng_ick = {
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1699,7 +1703,7 @@ static struct clk aes_ick = {
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1719,7 +1723,7 @@ static struct clk usb_fck = {
 
 static struct clk usbhs_ick = {
 	.name		= "usbhs_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1729,7 +1733,7 @@ static struct clk usbhs_ick = {
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1741,7 +1745,7 @@ static struct clk mmchs1_fck = {
 	.name		= "mmchs1_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l3_clkdm",
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1749,7 +1753,7 @@ static struct clk mmchs1_fck = {
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1761,6 +1765,7 @@ static struct clk mmchs2_fck = {
 	.name		= "mmchs2_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1768,7 +1773,7 @@ static struct clk mmchs2_fck = {
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1788,7 +1793,7 @@ static struct clk gpio5_fck = {
 
 static struct clk mdm_intc_ick = {
 	.name		= "mdm_intc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1880,7 +1885,6 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X),
 	/* dsp domain clocks */
 	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X),
-	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_243X),
 	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
 	/* GFX domain clocks */
 	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X),
@@ -1901,6 +1905,7 @@ static struct omap_clk omap2430_clks[] = {
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_243X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -1984,15 +1989,15 @@ static struct omap_clk omap2430_clks[] = {
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
 	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
-	CLK("mmci-omap-hs.0", "ick",	&mmchs1_ick,	CK_243X),
-	CLK("mmci-omap-hs.0", "fck",	&mmchs1_fck,	CK_243X),
-	CLK("mmci-omap-hs.1", "ick",	&mmchs2_ick,	CK_243X),
-	CLK("mmci-omap-hs.1", "fck",	&mmchs2_fck,	CK_243X),
+	CLK("omap_hsmmc.0", "ick",	&mmchs1_ick,	CK_243X),
+	CLK("omap_hsmmc.0", "fck",	&mmchs1_fck,	CK_243X),
+	CLK("omap_hsmmc.1", "ick",	&mmchs2_ick,	CK_243X),
+	CLK("omap_hsmmc.1", "fck",	&mmchs2_fck,	CK_243X),
 	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
 	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
-	CLK("mmci-omap-hs.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
-	CLK("mmci-omap-hs.1", "mmchsdb_fck", 	&mmchsdb2_fck,	CK_243X),
+	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
+	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
 };
 
 /*
@@ -2028,6 +2033,9 @@ int __init omap2430_clk_init(void)
 		omap2_init_clk_clkdm(c->lk.clk);
 	}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h
index 6a658b8..cb6df8c 100644
--- a/arch/arm/mach-omap2/clock2xxx.h
+++ b/arch/arm/mach-omap2/clock2xxx.h
@@ -20,16 +20,16 @@ u32 omap2xxx_get_apll_clkin(void);
 u32 omap2xxx_get_sysclkdiv(void);
 void omap2xxx_clk_prepare_for_reboot(void);
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 int omap2420_clk_init(void);
 #else
-#define omap2420_clk_init()	0
+#define omap2420_clk_init()	do { } while(0)
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 int omap2430_clk_init(void);
 #else
-#define omap2430_clk_init()	0
+#define omap2430_clk_init()	do { } while(0)
 #endif
 
 extern void __iomem *prcm_clksrc_ctrl, *cm_idlest_pll;
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
index 287abc4..1fc96b9 100644
--- a/arch/arm/mach-omap2/clock34xx.c
+++ b/arch/arm/mach-omap2/clock34xx.c
@@ -2,7 +2,7 @@
  * OMAP3-specific clock framework functions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley
  * Jouni HĂśgander
@@ -59,6 +59,15 @@ const struct clkops clkops_omap3430es2_ssi_wait = {
 	.find_companion = omap2_clk_dflt_find_companion,
 };
 
+const struct clkops clkops_omap3430es2_iclk_ssi_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_ssi_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
 /**
  * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
  * @clk: struct clk * being enabled
@@ -94,6 +103,15 @@ const struct clkops clkops_omap3430es2_dss_usbhost_wait = {
 	.find_companion = omap2_clk_dflt_find_companion,
 };
 
+const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_dss_usbhost_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
 /**
  * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
  * @clk: struct clk * being enabled
@@ -124,3 +142,12 @@ const struct clkops clkops_omap3430es2_hsotgusb_wait = {
 	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
 	.find_companion = omap2_clk_dflt_find_companion,
 };
+
+const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
+	.find_companion = omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h
index 628e8de..084ba71 100644
--- a/arch/arm/mach-omap2/clock34xx.h
+++ b/arch/arm/mach-omap2/clock34xx.h
@@ -2,14 +2,17 @@
  * OMAP34xx clock function prototypes and macros
  *
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 
 extern const struct clkops clkops_omap3430es2_ssi_wait;
+extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
 extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
+extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
 extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
+extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
 
 #endif
diff --git a/arch/arm/mach-omap2/clock3517.c b/arch/arm/mach-omap2/clock3517.c
index 74116a3..2e97d08 100644
--- a/arch/arm/mach-omap2/clock3517.c
+++ b/arch/arm/mach-omap2/clock3517.c
@@ -2,7 +2,7 @@
  * OMAP3517/3505-specific clock framework functions
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
  *
  * Ranjith Lohithakshan
  * Paul Walmsley
@@ -119,6 +119,8 @@ const struct clkops clkops_am35xx_ipss_wait = {
 	.disable	= omap2_dflt_clk_disable,
 	.find_idlest	= am35xx_clk_ipss_find_idlest,
 	.find_companion	= omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
 };
 
 
diff --git a/arch/arm/mach-omap2/clock3xxx.c b/arch/arm/mach-omap2/clock3xxx.c
index e9f66b6..952c3e0 100644
--- a/arch/arm/mach-omap2/clock3xxx.c
+++ b/arch/arm/mach-omap2/clock3xxx.c
@@ -65,9 +65,6 @@ void __init omap3_clk_lock_dpll5(void)
 	clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
 	clk_enable(dpll5_clk);
 
-	/* Enable autoidle to allow it to enter low power bypass */
-	omap3_dpll_allow_idle(dpll5_clk);
-
 	/* Program dpll5_m2_clk divider for no division */
 	dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
 	clk_enable(dpll5_m2_clk);
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 403a4a1..fcb321a 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP3 clock data
  *
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
  * With many device clock fixes by Kevin Hilman and Jouni HĂśgander
@@ -291,12 +291,11 @@ static struct dpll_data dpll1_dd = {
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll1_ck = {
 	.name		= "dpll1_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_noncore_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll1_dd,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -364,7 +363,6 @@ static struct dpll_data dpll2_dd = {
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll2_ck = {
@@ -424,12 +422,11 @@ static struct dpll_data dpll3_dd = {
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll3_ck = {
 	.name		= "dpll3_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_core_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll3_dd,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -583,7 +580,6 @@ static struct dpll_data dpll4_dd_34xx __initdata = {
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct dpll_data dpll4_dd_3630 __initdata = {
@@ -607,7 +603,6 @@ static struct dpll_data dpll4_dd_3630 __initdata = {
 	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE,
 	.flags		= DPLL_J_TYPE
 };
 
@@ -939,7 +934,6 @@ static struct dpll_data dpll5_dd = {
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll5_ck = {
@@ -1205,7 +1199,10 @@ static const struct clksel gfx_l3_clksel[] = {
 	{ .parent = NULL }
 };
 
-/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */
+/*
+ * Virtual parent clock for gfx_l3_ick and gfx_l3_fck
+ * This interface clock does not have a CM_AUTOIDLE bit
+ */
 static struct clk gfx_l3_ck = {
 	.name		= "gfx_l3_ck",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1304,6 +1301,7 @@ static struct clk sgx_fck = {
 	.round_rate	= &omap2_clksel_round_rate
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk sgx_ick = {
 	.name		= "sgx_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1328,7 +1326,7 @@ static struct clk d2d_26m_fck = {
 
 static struct clk modem_fck = {
 	.name		= "modem_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_mdmclk_dflt_wait,
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
@@ -1338,7 +1336,7 @@ static struct clk modem_fck = {
 
 static struct clk sad2d_ick = {
 	.name		= "sad2d_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
@@ -1348,7 +1346,7 @@ static struct clk sad2d_ick = {
 
 static struct clk mad2d_ick = {
 	.name		= "mad2d_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
@@ -1718,7 +1716,7 @@ static struct clk core_l3_ick = {
 
 static struct clk hsotgusb_ick_3430es1 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1728,7 +1726,7 @@ static struct clk hsotgusb_ick_3430es1 = {
 
 static struct clk hsotgusb_ick_3430es2 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap3430es2_hsotgusb_wait,
+	.ops		= &clkops_omap3430es2_iclk_hsotgusb_wait,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1736,6 +1734,7 @@ static struct clk hsotgusb_ick_3430es2 = {
 	.recalc		= &followparent_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1767,7 +1766,7 @@ static struct clk security_l3_ick = {
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
@@ -1786,7 +1785,7 @@ static struct clk core_l4_ick = {
 
 static struct clk usbtll_ick = {
 	.name		= "usbtll_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
@@ -1796,7 +1795,7 @@ static struct clk usbtll_ick = {
 
 static struct clk mmchs3_ick = {
 	.name		= "mmchs3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
@@ -1807,7 +1806,7 @@ static struct clk mmchs3_ick = {
 /* Intersystem Communication Registers - chassis mode only */
 static struct clk icr_ick = {
 	.name		= "icr_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
@@ -1817,7 +1816,7 @@ static struct clk icr_ick = {
 
 static struct clk aes2_ick = {
 	.name		= "aes2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
@@ -1827,7 +1826,7 @@ static struct clk aes2_ick = {
 
 static struct clk sha12_ick = {
 	.name		= "sha12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
@@ -1837,7 +1836,7 @@ static struct clk sha12_ick = {
 
 static struct clk des2_ick = {
 	.name		= "des2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
@@ -1847,7 +1846,7 @@ static struct clk des2_ick = {
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
@@ -1857,7 +1856,7 @@ static struct clk mmchs2_ick = {
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
@@ -1867,7 +1866,7 @@ static struct clk mmchs1_ick = {
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
@@ -1877,7 +1876,7 @@ static struct clk mspro_ick = {
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
@@ -1887,7 +1886,7 @@ static struct clk hdq_ick = {
 
 static struct clk mcspi4_ick = {
 	.name		= "mcspi4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
@@ -1897,7 +1896,7 @@ static struct clk mcspi4_ick = {
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
@@ -1907,7 +1906,7 @@ static struct clk mcspi3_ick = {
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
@@ -1917,7 +1916,7 @@ static struct clk mcspi2_ick = {
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
@@ -1927,7 +1926,7 @@ static struct clk mcspi1_ick = {
 
 static struct clk i2c3_ick = {
 	.name		= "i2c3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
@@ -1937,7 +1936,7 @@ static struct clk i2c3_ick = {
 
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
@@ -1947,7 +1946,7 @@ static struct clk i2c2_ick = {
 
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
@@ -1957,7 +1956,7 @@ static struct clk i2c1_ick = {
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
@@ -1967,7 +1966,7 @@ static struct clk uart2_ick = {
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
@@ -1977,7 +1976,7 @@ static struct clk uart1_ick = {
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
@@ -1987,7 +1986,7 @@ static struct clk gpt11_ick = {
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
@@ -1997,7 +1996,7 @@ static struct clk gpt10_ick = {
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
@@ -2007,7 +2006,7 @@ static struct clk mcbsp5_ick = {
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
@@ -2017,7 +2016,7 @@ static struct clk mcbsp1_ick = {
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
@@ -2027,7 +2026,7 @@ static struct clk fac_ick = {
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
@@ -2037,7 +2036,7 @@ static struct clk mailboxes_ick = {
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
@@ -2057,7 +2056,7 @@ static struct clk ssi_l4_ick = {
 
 static struct clk ssi_ick_3430es1 = {
 	.name		= "ssi_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
@@ -2067,7 +2066,7 @@ static struct clk ssi_ick_3430es1 = {
 
 static struct clk ssi_ick_3430es2 = {
 	.name		= "ssi_ick",
-	.ops		= &clkops_omap3430es2_ssi_wait,
+	.ops		= &clkops_omap3430es2_iclk_ssi_wait,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
@@ -2085,7 +2084,7 @@ static const struct clksel usb_l4_clksel[] = {
 
 static struct clk usb_l4_ick = {
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -2107,7 +2106,7 @@ static struct clk security_l4_ick2 = {
 
 static struct clk aes1_ick = {
 	.name		= "aes1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
@@ -2116,7 +2115,7 @@ static struct clk aes1_ick = {
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
@@ -2125,7 +2124,7 @@ static struct clk rng_ick = {
 
 static struct clk sha11_ick = {
 	.name		= "sha11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
@@ -2134,7 +2133,7 @@ static struct clk sha11_ick = {
 
 static struct clk des1_ick = {
 	.name		= "des1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
@@ -2195,7 +2194,7 @@ static struct clk dss2_alwon_fck = {
 static struct clk dss_ick_3430es1 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
@@ -2206,7 +2205,7 @@ static struct clk dss_ick_3430es1 = {
 static struct clk dss_ick_3430es2 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
@@ -2229,7 +2228,7 @@ static struct clk cam_mclk = {
 static struct clk cam_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
@@ -2272,7 +2271,7 @@ static struct clk usbhost_48m_fck = {
 static struct clk usbhost_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "usbhost_ick",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
@@ -2372,7 +2371,7 @@ static struct clk wkup_l4_ick = {
 /* Never specifically named in the TRM, so we have to infer a likely name */
 static struct clk usim_ick = {
 	.name		= "usim_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
@@ -2382,7 +2381,7 @@ static struct clk usim_ick = {
 
 static struct clk wdt2_ick = {
 	.name		= "wdt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
@@ -2392,7 +2391,7 @@ static struct clk wdt2_ick = {
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
@@ -2402,7 +2401,7 @@ static struct clk wdt1_ick = {
 
 static struct clk gpio1_ick = {
 	.name		= "gpio1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
@@ -2412,7 +2411,7 @@ static struct clk gpio1_ick = {
 
 static struct clk omap_32ksync_ick = {
 	.name		= "omap_32ksync_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
@@ -2423,7 +2422,7 @@ static struct clk omap_32ksync_ick = {
 /* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
@@ -2433,7 +2432,7 @@ static struct clk gpt12_ick = {
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
@@ -2663,7 +2662,7 @@ static struct clk per_l4_ick = {
 
 static struct clk gpio6_ick = {
 	.name		= "gpio6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
@@ -2673,7 +2672,7 @@ static struct clk gpio6_ick = {
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
@@ -2683,7 +2682,7 @@ static struct clk gpio5_ick = {
 
 static struct clk gpio4_ick = {
 	.name		= "gpio4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
@@ -2693,7 +2692,7 @@ static struct clk gpio4_ick = {
 
 static struct clk gpio3_ick = {
 	.name		= "gpio3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
@@ -2703,7 +2702,7 @@ static struct clk gpio3_ick = {
 
 static struct clk gpio2_ick = {
 	.name		= "gpio2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
@@ -2713,7 +2712,7 @@ static struct clk gpio2_ick = {
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
@@ -2723,7 +2722,7 @@ static struct clk wdt3_ick = {
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
@@ -2733,7 +2732,7 @@ static struct clk uart3_ick = {
 
 static struct clk uart4_ick = {
 	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
@@ -2743,7 +2742,7 @@ static struct clk uart4_ick = {
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
@@ -2753,7 +2752,7 @@ static struct clk gpt9_ick = {
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
@@ -2763,7 +2762,7 @@ static struct clk gpt8_ick = {
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
@@ -2773,7 +2772,7 @@ static struct clk gpt7_ick = {
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
@@ -2783,7 +2782,7 @@ static struct clk gpt6_ick = {
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
@@ -2793,7 +2792,7 @@ static struct clk gpt5_ick = {
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
@@ -2803,7 +2802,7 @@ static struct clk gpt4_ick = {
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
@@ -2813,7 +2812,7 @@ static struct clk gpt3_ick = {
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
@@ -2823,7 +2822,7 @@ static struct clk gpt2_ick = {
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
@@ -2833,7 +2832,7 @@ static struct clk mcbsp2_ick = {
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
@@ -2843,7 +2842,7 @@ static struct clk mcbsp3_ick = {
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
@@ -3186,7 +3185,7 @@ static struct clk vpfe_fck = {
  */
 static struct clk uart4_ick_am35xx = {
 	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= AM35XX_EN_UART4_SHIFT,
@@ -3286,14 +3285,14 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("omap-mcbsp.1",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK("omap-mcbsp.5",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
-	CLK("mmci-omap-hs.2",	"fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("mmci-omap-hs.1",	"fck",	&mmchs2_fck,	CK_3XXX),
+	CLK("omap_hsmmc.2",	"fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omap_hsmmc.1",	"fck",	&mmchs2_fck,	CK_3XXX),
 	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_34XX | CK_36XX),
-	CLK("mmci-omap-hs.0",	"fck",	&mmchs1_fck,	CK_3XXX),
+	CLK("omap_hsmmc.0",	"fck",	&mmchs1_fck,	CK_3XXX),
 	CLK("omap_i2c.3", "fck",	&i2c3_fck,	CK_3XXX),
 	CLK("omap_i2c.2", "fck",	&i2c2_fck,	CK_3XXX),
 	CLK("omap_i2c.1", "fck",	&i2c1_fck,	CK_3XXX),
@@ -3322,14 +3321,14 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"core_l4_ick",	&core_l4_ick,	CK_3XXX),
 	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("mmci-omap-hs.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omap_hsmmc.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"icr_ick",	&icr_ick,	CK_34XX | CK_36XX),
 	CLK("omap-aes",	"ick",	&aes2_ick,	CK_34XX | CK_36XX),
 	CLK("omap-sham",	"ick",	&sha12_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"des2_ick",	&des2_ick,	CK_34XX | CK_36XX),
-	CLK("mmci-omap-hs.1",	"ick",	&mmchs2_ick,	CK_3XXX),
-	CLK("mmci-omap-hs.0",	"ick",	&mmchs1_ick,	CK_3XXX),
+	CLK("omap_hsmmc.1",	"ick",	&mmchs2_ick,	CK_3XXX),
+	CLK("omap_hsmmc.0",	"ick",	&mmchs1_ick,	CK_3XXX),
 	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_34XX | CK_36XX),
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_3XXX),
 	CLK("omap2_mcspi.4", "ick",	&mcspi4_ick,	CK_3XXX),
@@ -3368,11 +3367,20 @@ static struct omap_clk omap3xxx_clks[] = {
 	CLK(NULL,	"cam_ick",	&cam_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_34XX | CK_36XX),
 	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"utmi_p1_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"utmi_p2_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"xclk60mhsp1_ck",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"xclk60mhsp2_ck",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_host_hs_utmi_p1_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_host_hs_utmi_p2_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"init_60m_fclk",	&dummy_ck,	CK_3XXX),
 	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
@@ -3471,6 +3479,9 @@ int __init omap3xxx_clk_init(void)
 	} else if (cpu_is_omap3630()) {
 		cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
 		cpu_clkflg = CK_36XX;
+	} else if (cpu_is_ti816x()) {
+		cpu_mask = RATE_IN_TI816X;
+		cpu_clkflg = CK_TI816X;
 	} else if (cpu_is_omap34xx()) {
 		if (omap_rev() == OMAP3430_REV_ES1_0) {
 			cpu_mask = RATE_IN_3430ES1;
@@ -3535,6 +3546,9 @@ int __init omap3xxx_clk_init(void)
 			omap2_init_clk_clkdm(c->lk.clk);
 		}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	recalculate_root_clocks();
 
 	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
@@ -3548,9 +3562,10 @@ int __init omap3xxx_clk_init(void)
 	clk_enable_init_clocks();
 
 	/*
-	 * Lock DPLL5 and put it in autoidle.
+	 * Lock DPLL5 -- here only until other device init code can
+	 * handle this
 	 */
-	if (omap_rev() >= OMAP3430_REV_ES2_0)
+	if (!cpu_is_ti816x() && (omap_rev() >= OMAP3430_REV_ES2_0))
 		omap3_clk_lock_dpll5();
 
 	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index de9ec8d..d32ed97 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -278,8 +278,10 @@ static struct clk dpll_abe_ck = {
 static struct clk dpll_abe_x2_ck = {
 	.name		= "dpll_abe_x2_ck",
 	.parent		= &dpll_abe_ck,
-	.ops		= &clkops_null,
+	.flags		= CLOCK_CLKOUTX2,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 };
 
 static const struct clksel_rate div31_1to31_rates[] = {
@@ -328,7 +330,7 @@ static struct clk dpll_abe_m2x2_ck = {
 	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -395,7 +397,7 @@ static struct clk dpll_abe_m3x2_ck = {
 	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -443,13 +445,14 @@ static struct clk dpll_core_ck = {
 	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_core_dd,
 	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_core_dpll_ops,
 	.recalc		= &omap3_dpll_recalc,
 };
 
 static struct clk dpll_core_x2_ck = {
 	.name		= "dpll_core_x2_ck",
 	.parent		= &dpll_core_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -465,7 +468,7 @@ static struct clk dpll_core_m6x2_ck = {
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -495,7 +498,7 @@ static struct clk dpll_core_m2_ck = {
 	.clksel		= dpll_core_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_CORE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -515,7 +518,7 @@ static struct clk dpll_core_m5x2_ck = {
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -581,7 +584,7 @@ static struct clk dpll_core_m4x2_ck = {
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -606,7 +609,7 @@ static struct clk dpll_abe_m2_ck = {
 	.clksel		= dpll_abe_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -632,7 +635,7 @@ static struct clk dpll_core_m7x2_ck = {
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -689,6 +692,7 @@ static struct clk dpll_iva_ck = {
 static struct clk dpll_iva_x2_ck = {
 	.name		= "dpll_iva_x2_ck",
 	.parent		= &dpll_iva_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -704,7 +708,7 @@ static struct clk dpll_iva_m4x2_ck = {
 	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -716,7 +720,7 @@ static struct clk dpll_iva_m5x2_ck = {
 	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -764,7 +768,7 @@ static struct clk dpll_mpu_m2_ck = {
 	.clksel		= dpll_mpu_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_MPU,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -837,7 +841,7 @@ static struct clk dpll_per_m2_ck = {
 	.clksel		= dpll_per_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -846,8 +850,10 @@ static struct clk dpll_per_m2_ck = {
 static struct clk dpll_per_x2_ck = {
 	.name		= "dpll_per_x2_ck",
 	.parent		= &dpll_per_ck,
-	.ops		= &clkops_null,
+	.flags		= CLOCK_CLKOUTX2,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 };
 
 static const struct clksel dpll_per_m2x2_div[] = {
@@ -861,7 +867,7 @@ static struct clk dpll_per_m2x2_ck = {
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -887,7 +893,7 @@ static struct clk dpll_per_m4x2_ck = {
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -899,7 +905,7 @@ static struct clk dpll_per_m5x2_ck = {
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -911,7 +917,7 @@ static struct clk dpll_per_m6x2_ck = {
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -923,7 +929,7 @@ static struct clk dpll_per_m7x2_ck = {
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -964,6 +970,7 @@ static struct clk dpll_unipro_ck = {
 static struct clk dpll_unipro_x2_ck = {
 	.name		= "dpll_unipro_x2_ck",
 	.parent		= &dpll_unipro_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -979,7 +986,7 @@ static struct clk dpll_unipro_m2x2_ck = {
 	.clksel		= dpll_unipro_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -1028,7 +1035,8 @@ static struct clk dpll_usb_ck = {
 static struct clk dpll_usb_clkdcoldo_ck = {
 	.name		= "dpll_usb_clkdcoldo_ck",
 	.parent		= &dpll_usb_ck,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
+	.clksel_reg	= OMAP4430_CM_CLKDCOLDO_DPLL_USB,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1043,7 +1051,7 @@ static struct clk dpll_usb_m2_ck = {
 	.clksel		= dpll_usb_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_USB,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -3158,11 +3166,11 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK("omap2_mcspi.2",	"fck",				&mcspi2_fck,	CK_443X),
 	CLK("omap2_mcspi.3",	"fck",				&mcspi3_fck,	CK_443X),
 	CLK("omap2_mcspi.4",	"fck",				&mcspi4_fck,	CK_443X),
-	CLK("mmci-omap-hs.0",	"fck",				&mmc1_fck,	CK_443X),
-	CLK("mmci-omap-hs.1",	"fck",				&mmc2_fck,	CK_443X),
-	CLK("mmci-omap-hs.2",	"fck",				&mmc3_fck,	CK_443X),
-	CLK("mmci-omap-hs.3",	"fck",				&mmc4_fck,	CK_443X),
-	CLK("mmci-omap-hs.4",	"fck",				&mmc5_fck,	CK_443X),
+	CLK("omap_hsmmc.0",	"fck",				&mmc1_fck,	CK_443X),
+	CLK("omap_hsmmc.1",	"fck",				&mmc2_fck,	CK_443X),
+	CLK("omap_hsmmc.2",	"fck",				&mmc3_fck,	CK_443X),
+	CLK("omap_hsmmc.3",	"fck",				&mmc4_fck,	CK_443X),
+	CLK("omap_hsmmc.4",	"fck",				&mmc5_fck,	CK_443X),
 	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
 	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
 	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
@@ -3197,7 +3205,7 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
 	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
 	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
-	CLK("ehci-omap.0",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
+	CLK("usbhs-omap.0",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
 	CLK(NULL,	"utmi_p2_gfclk",		&utmi_p2_gfclk,	CK_443X),
@@ -3209,8 +3217,8 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK("ehci-omap.0",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK("ehci-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
+	CLK("usbhs-omap.0",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
 	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
 	CLK("musb-omap2430",	"ick",				&usb_otg_hs_ick,	CK_443X),
@@ -3219,8 +3227,8 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("ehci-omap.0",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("ehci-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
+	CLK("usbhs-omap.0",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
 	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
 	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
@@ -3245,11 +3253,11 @@ static struct omap_clk omap44xx_clks[] = {
 	CLK("omap_i2c.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_i2c.3",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_i2c.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.0",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.4",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.0",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.1",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.2",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.3",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.4",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.1",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.3",	"ick",				&dummy_ck,	CK_443X),
@@ -3301,6 +3309,9 @@ int __init omap4xxx_clk_init(void)
 			omap2_init_clk_clkdm(c->lk.clk);
 		}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	recalculate_root_clocks();
 
 	/*
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index 1cf8131..6424d46 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -37,3 +37,9 @@ const struct clksel_rate gfx_l3_rates[] = {
 	{ .div = 0 }
 };
 
+const struct clksel_rate dsp_ick_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
+	{ .div = 0 },
+};
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 58e42f7..ab87854 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -26,17 +26,8 @@
 
 #include <linux/bitops.h>
 
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
-#include "cminst44xx.h"
-#include "prcm44xx.h"
-
 #include <plat/clock.h>
-#include "powerdomain.h"
 #include "clockdomain.h"
-#include <plat/prcm.h>
 
 /* clkdm_list contains all registered struct clockdomains */
 static LIST_HEAD(clkdm_list);
@@ -44,6 +35,7 @@ static LIST_HEAD(clkdm_list);
 /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
 static struct clkdm_autodep *autodeps;
 
+static struct clkdm_ops *arch_clkdm;
 
 /* Private functions */
 
@@ -177,11 +169,11 @@ static void _autodep_lookup(struct clkdm_autodep *autodep)
  * XXX autodeps are deprecated and should be removed at the earliest
  * opportunity
  */
-static void _clkdm_add_autodeps(struct clockdomain *clkdm)
+void _clkdm_add_autodeps(struct clockdomain *clkdm)
 {
 	struct clkdm_autodep *autodep;
 
-	if (!autodeps)
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
@@ -211,11 +203,11 @@ static void _clkdm_add_autodeps(struct clockdomain *clkdm)
  * XXX autodeps are deprecated and should be removed at the earliest
  * opportunity
  */
-static void _clkdm_del_autodeps(struct clockdomain *clkdm)
+void _clkdm_del_autodeps(struct clockdomain *clkdm)
 {
 	struct clkdm_autodep *autodep;
 
-	if (!autodeps)
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
@@ -235,55 +227,29 @@ static void _clkdm_del_autodeps(struct clockdomain *clkdm)
 }
 
 /**
- * _enable_hwsup - place a clockdomain into hardware-supervised idle
- * @clkdm: struct clockdomain *
- *
- * Place the clockdomain into hardware-supervised idle mode.  No return
- * value.
+ * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
+ * @clkdm: clockdomain that we are resolving dependencies for
+ * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
  *
- * XXX Should this return an error if the clockdomain does not support
- * hardware-supervised idle mode?
- */
-static void _enable_hwsup(struct clockdomain *clkdm)
-{
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap44xx())
-		return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-	else
-		BUG();
-}
-
-/**
- * _disable_hwsup - place a clockdomain into software-supervised idle
- * @clkdm: struct clockdomain *
- *
- * Place the clockdomain @clkdm into software-supervised idle mode.
+ * Iterates through @clkdm_deps, looking up the struct clockdomain named by
+ * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
  * No return value.
- *
- * XXX Should this return an error if the clockdomain does not support
- * software-supervised idle mode?
  */
-static void _disable_hwsup(struct clockdomain *clkdm)
+static void _resolve_clkdm_deps(struct clockdomain *clkdm,
+				struct clkdm_dep *clkdm_deps)
 {
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap44xx())
-		return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
-							clkdm->cm_inst,
-							clkdm->clkdm_offs);
-	else
-		BUG();
+	struct clkdm_dep *cd;
+
+	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (cd->clkdm)
+			continue;
+		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
+		     clkdm->name, cd->clkdm_name);
+	}
 }
 
 /* Public functions */
@@ -292,6 +258,7 @@ static void _disable_hwsup(struct clockdomain *clkdm)
  * clkdm_init - set up the clockdomain layer
  * @clkdms: optional pointer to an array of clockdomains to register
  * @init_autodeps: optional pointer to an array of autodeps to register
+ * @custom_funcs: func pointers for arch specfic implementations
  *
  * Set up internal state.  If a pointer to an array of clockdomains
  * @clkdms was supplied, loop through the list of clockdomains,
@@ -300,12 +267,18 @@ static void _disable_hwsup(struct clockdomain *clkdm)
  * @init_autodeps was provided, register those.  No return value.
  */
 void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_autodep *init_autodeps)
+		struct clkdm_autodep *init_autodeps,
+		struct clkdm_ops *custom_funcs)
 {
 	struct clockdomain **c = NULL;
 	struct clockdomain *clkdm;
 	struct clkdm_autodep *autodep = NULL;
 
+	if (!custom_funcs)
+		WARN(1, "No custom clkdm functions registered\n");
+	else
+		arch_clkdm = custom_funcs;
+
 	if (clkdms)
 		for (c = clkdms; *c; c++)
 			_clkdm_register(*c);
@@ -321,11 +294,14 @@ void clkdm_init(struct clockdomain **clkdms,
 	 */
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap2_clkdm_wakeup(clkdm);
+			clkdm_wakeup(clkdm);
 		else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
-			omap2_clkdm_deny_idle(clkdm);
+			clkdm_deny_idle(clkdm);
 
+		_resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
 		clkdm_clear_all_wkdeps(clkdm);
+
+		_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
 		clkdm_clear_all_sleepdeps(clkdm);
 	}
 }
@@ -422,32 +398,32 @@ struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm)
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
 		pr_debug("clockdomain: hardware will wake up %s when %s wakes "
 			 "up\n", clkdm1->name, clkdm2->name);
 
-		omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -463,32 +439,32 @@ int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
 		pr_debug("clockdomain: hardware will no longer wake up %s "
 			 "after %s wakes up\n", clkdm1->name, clkdm2->name);
 
-		omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -508,26 +484,26 @@ int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
-
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	/* XXX It's faster to return the atomic wkdep_usecount */
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
-				       (1 << clkdm2->dep_bit));
+	return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
 }
 
 /**
@@ -542,33 +518,13 @@ int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 {
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s: %s: not yet implemented\n",
-		       clkdm->name, __func__);
-		return -EINVAL;
-	}
-
 	if (!clkdm)
 		return -EINVAL;
 
-	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
-
-		if (!cd->clkdm && cd->clkdm_name)
-			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
+		return -EINVAL;
 
-	return 0;
+	return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
 }
 
 /**
@@ -586,31 +542,33 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
 		pr_debug("clockdomain: will prevent %s from sleeping if %s "
 			 "is active\n", clkdm1->name, clkdm2->name);
 
-		omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				    clkdm1->pwrdm.ptr->prcm_offs,
-				    OMAP3430_CM_SLEEPDEP);
+		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -628,19 +586,23 @@ int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
@@ -648,12 +610,10 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 			 "sleeping if %s is active\n", clkdm1->name,
 			 clkdm2->name);
 
-		omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				      clkdm1->pwrdm.ptr->prcm_offs,
-				      OMAP3430_CM_SLEEPDEP);
+		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -675,25 +635,27 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	/* XXX It's faster to return the atomic sleepdep_usecount */
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
-				       OMAP3430_CM_SLEEPDEP,
-				       (1 << clkdm2->dep_bit));
+	return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
 }
 
 /**
@@ -708,35 +670,17 @@ int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
  */
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 {
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
-
 	if (!clkdm)
 		return -EINVAL;
 
-	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
-
-		if (!cd->clkdm && cd->clkdm_name)
-			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
-			       OMAP3430_CM_SLEEPDEP);
+	if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
+		return -EINVAL;
 
-	return 0;
+	return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
 }
 
 /**
- * omap2_clkdm_sleep - force clockdomain sleep transition
+ * clkdm_sleep - force clockdomain sleep transition
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a sleep transition on the specified
@@ -744,7 +688,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
  * clockdomain does not support software-initiated sleep; 0 upon
  * success.
  */
-int omap2_clkdm_sleep(struct clockdomain *clkdm)
+int clkdm_sleep(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return -EINVAL;
@@ -755,33 +699,16 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm)
 		return -EINVAL;
 	}
 
-	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
-
-	if (cpu_is_omap24xx()) {
-
-		omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-			    clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	} else if (cpu_is_omap34xx()) {
-
-		omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
-					      clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
-					       clkdm->cm_inst,
-					       clkdm->clkdm_offs);
+	if (!arch_clkdm || !arch_clkdm->clkdm_sleep)
+		return -EINVAL;
 
-	} else {
-		BUG();
-	};
+	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-	return 0;
+	return arch_clkdm->clkdm_sleep(clkdm);
 }
 
 /**
- * omap2_clkdm_wakeup - force clockdomain wakeup transition
+ * clkdm_wakeup - force clockdomain wakeup transition
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a wakeup transition on the specified
@@ -789,7 +716,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm)
  * clockdomain does not support software-controlled wakeup; 0 upon
  * success.
  */
-int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+int clkdm_wakeup(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return -EINVAL;
@@ -800,33 +727,16 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
 		return -EINVAL;
 	}
 
-	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
-
-	if (cpu_is_omap24xx()) {
-
-		omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-			      clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	} else if (cpu_is_omap34xx()) {
-
-		omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
-						clkdm->cm_inst,
-						clkdm->clkdm_offs);
+	if (!arch_clkdm || !arch_clkdm->clkdm_wakeup)
+		return -EINVAL;
 
-	} else {
-		BUG();
-	};
+	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-	return 0;
+	return arch_clkdm->clkdm_wakeup(clkdm);
 }
 
 /**
- * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
  * Allow the hardware to automatically switch the clockdomain @clkdm into
@@ -835,7 +745,7 @@ int omap2_clkdm_wakeup(struct clockdomain *clkdm)
  * framework, wkdep/sleepdep autodependencies are added; this is so
  * device drivers can read and write to the device.  No return value.
  */
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+void clkdm_allow_idle(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return;
@@ -846,27 +756,18 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
 		return;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
+		return;
+
 	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	/*
-	 * XXX This should be removed once TI adds wakeup/sleep
-	 * dependency code and data for OMAP4.
-	 */
-	if (cpu_is_omap44xx()) {
-		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
-	} else {
-		if (atomic_read(&clkdm->usecount) > 0)
-			_clkdm_add_autodeps(clkdm);
-	}
-
-	_enable_hwsup(clkdm);
-
+	arch_clkdm->clkdm_allow_idle(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
 }
 
 /**
- * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
+ * clkdm_deny_idle - disable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
  * Prevent the hardware from automatically switching the clockdomain
@@ -874,7 +775,7 @@ void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
  * downstream clocks enabled in the clock framework, wkdep/sleepdep
  * autodependencies are removed.  No return value.
  */
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+void clkdm_deny_idle(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return;
@@ -885,28 +786,20 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
 		return;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
+		return;
+
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	_disable_hwsup(clkdm);
-
-	/*
-	 * XXX This should be removed once TI adds wakeup/sleep
-	 * dependency code and data for OMAP4.
-	 */
-	if (cpu_is_omap44xx()) {
-		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
-	} else {
-		if (atomic_read(&clkdm->usecount) > 0)
-			_clkdm_del_autodeps(clkdm);
-	}
+	arch_clkdm->clkdm_deny_idle(clkdm);
 }
 
 
 /* Clockdomain-to-clock framework interface code */
 
 /**
- * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
+ * clkdm_clk_enable - add an enabled downstream clock to this clkdm
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the enabled downstream clock
  *
@@ -919,10 +812,8 @@ void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
  * by on-chip processors.  Returns -EINVAL if passed null pointers;
  * returns 0 upon success or if the clockdomain is in hwsup idle mode.
  */
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
+int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 {
-	bool hwsup = false;
-
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
 	 * downstream clocks for debugging purposes?
@@ -931,6 +822,9 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 	if (!clkdm || !clk)
 		return -EINVAL;
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+		return -EINVAL;
+
 	if (atomic_inc_return(&clkdm->usecount) > 1)
 		return 0;
 
@@ -939,31 +833,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
 		 clk->name);
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-
-		if (!clkdm->clktrctrl_mask)
-			return 0;
-
-		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						   clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-
-	}
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_add_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		omap2_clkdm_wakeup(clkdm);
-	}
-
+	arch_clkdm->clkdm_clk_enable(clkdm);
 	pwrdm_wait_transition(clkdm->pwrdm.ptr);
 	pwrdm_clkdm_state_switch(clkdm);
 
@@ -971,7 +841,7 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 }
 
 /**
- * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
+ * clkdm_clk_disable - remove an enabled downstream clock from this clkdm
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the disabled downstream clock
  *
@@ -984,10 +854,8 @@ int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
  * is enabled; or returns 0 upon success or if the clockdomain is in
  * hwsup idle mode.
  */
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
+int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-	bool hwsup = false;
-
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
 	 * downstream clocks for debugging purposes?
@@ -996,6 +864,9 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 	if (!clkdm || !clk)
 		return -EINVAL;
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+		return -EINVAL;
+
 #ifdef DEBUG
 	if (atomic_read(&clkdm->usecount) == 0) {
 		WARN_ON(1); /* underflow */
@@ -1011,31 +882,7 @@ int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
 		 clk->name);
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-
-		if (!clkdm->clktrctrl_mask)
-			return 0;
-
-		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						   clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-
-	}
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_del_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		omap2_clkdm_sleep(clkdm);
-	}
-
+	arch_clkdm->clkdm_clk_disable(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
 
 	return 0;
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 9b459c2..85b3dce 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -4,7 +4,7 @@
  * OMAP2/3 clockdomain framework functions
  *
  * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2011 Nokia Corporation
  *
  * Paul Walmsley
  *
@@ -22,11 +22,19 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
-/* Clockdomain capability flags */
+/*
+ * Clockdomain flags
+ *
+ * XXX Document CLKDM_CAN_* flags
+ *
+ * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this
+ *     clockdomain.  (Currently, this applies to OMAP3 clockdomains only.)
+ */
 #define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
 #define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
 #define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
+#define CLKDM_NO_AUTODEPS			(1 << 4)
 
 #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
@@ -116,7 +124,42 @@ struct clockdomain {
 	struct list_head node;
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
+/**
+ * struct clkdm_ops - Arch specfic function implementations
+ * @clkdm_add_wkdep: Add a wakeup dependency between clk domains
+ * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains
+ * @clkdm_read_wkdep: Read wakeup dependency state between clk domains
+ * @clkdm_clear_all_wkdeps: Remove all wakeup dependencies from the clk domain
+ * @clkdm_add_sleepdep: Add a sleep dependency between clk domains
+ * @clkdm_del_sleepdep: Delete a sleep dependency between clk domains
+ * @clkdm_read_sleepdep: Read sleep dependency state between clk domains
+ * @clkdm_clear_all_sleepdeps: Remove all sleep dependencies from the clk domain
+ * @clkdm_sleep: Force a clockdomain to sleep
+ * @clkdm_wakeup: Force a clockdomain to wakeup
+ * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
+ * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
+ * @clkdm_clk_enable: Put the clkdm in right state for a clock enable
+ * @clkdm_clk_disable: Put the clkdm in right state for a clock disable
+ */
+struct clkdm_ops {
+	int	(*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_del_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_read_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_clear_all_wkdeps)(struct clockdomain *clkdm);
+	int	(*clkdm_add_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_del_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_read_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_clear_all_sleepdeps)(struct clockdomain *clkdm);
+	int	(*clkdm_sleep)(struct clockdomain *clkdm);
+	int	(*clkdm_wakeup)(struct clockdomain *clkdm);
+	void	(*clkdm_allow_idle)(struct clockdomain *clkdm);
+	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
+	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
+	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
+};
+
+void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
+			struct clkdm_ops *custom_funcs);
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -132,16 +175,23 @@ int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
+void clkdm_allow_idle(struct clockdomain *clkdm);
+void clkdm_deny_idle(struct clockdomain *clkdm);
 
-int omap2_clkdm_wakeup(struct clockdomain *clkdm);
-int omap2_clkdm_sleep(struct clockdomain *clkdm);
+int clkdm_wakeup(struct clockdomain *clkdm);
+int clkdm_sleep(struct clockdomain *clkdm);
 
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
 
-extern void __init omap2_clockdomains_init(void);
+extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap3xxx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
+extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
+extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
+
+extern struct clkdm_ops omap2_clkdm_operations;
+extern struct clkdm_ops omap3_clkdm_operations;
+extern struct clkdm_ops omap4_clkdm_operations;
 
 #endif
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
new file mode 100644
index 0000000..48d0db7
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
@@ -0,0 +1,274 @@
+/*
+ * OMAP2 and OMAP3 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@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/types.h>
+#include <plat/prcm.h>
+#include "prm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-24xx.h"
+#include "clockdomain.h"
+
+static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
+						struct clockdomain *clkdm2)
+{
+	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				PM_WKDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				 PM_WKDEP);
+	return 0;
+}
+
+static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->sleepdep_usecount, 0);
+	}
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap2_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				clkdm->pwrdm.ptr->prcm_offs,
+				OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				clkdm->pwrdm.ptr->prcm_offs,
+				OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
+static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+static void _enable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+}
+
+static void _disable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+}
+
+
+static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		_disable_hwsup(clkdm);
+		_clkdm_add_autodeps(clkdm);
+		_enable_hwsup(clkdm);
+	} else {
+		clkdm_wakeup(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		_disable_hwsup(clkdm);
+		_clkdm_del_autodeps(clkdm);
+		_enable_hwsup(clkdm);
+	} else {
+		clkdm_sleep(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap3_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
+static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+struct clkdm_ops omap2_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_sleep		= omap2_clkdm_sleep,
+	.clkdm_wakeup		= omap2_clkdm_wakeup,
+	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
+};
+
+struct clkdm_ops omap3_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
+	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
+	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
+	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
+	.clkdm_sleep		= omap3_clkdm_sleep,
+	.clkdm_wakeup		= omap3_clkdm_wakeup,
+	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
+};
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
new file mode 100644
index 0000000..a1a4ecd
--- /dev/null
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
@@ -0,0 +1,137 @@
+/*
+ * OMAP4 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@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/kernel.h>
+#include "clockdomain.h"
+#include "cminst44xx.h"
+#include "cm44xx.h"
+
+static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
+					clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
+					clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP,
+					(1 << clkdm2->dep_bit));
+}
+
+static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup)
+		clkdm_wakeup(clkdm);
+
+	return 0;
+}
+
+static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup)
+		clkdm_sleep(clkdm);
+
+	return 0;
+}
+
+struct clkdm_ops omap4_clkdm_operations = {
+	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_sleep		= omap4_clkdm_sleep,
+	.clkdm_wakeup		= omap4_clkdm_wakeup,
+	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
+};
diff --git a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
index e4a7133..13bde95 100644
--- a/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
@@ -89,6 +89,8 @@ static struct clkdm_dep gfx_sgx_wkdeps[] = {
 
 /* 24XX-specific possible dependencies */
 
+#ifdef CONFIG_ARCH_OMAP2
+
 /* Wakeup dependency source arrays */
 
 /* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
@@ -168,10 +170,11 @@ static struct clkdm_dep core_24xx_wkdeps[] = {
 	{ NULL },
 };
 
+#endif /* CONFIG_ARCH_OMAP2 */
 
 /* 2430-specific possible wakeup dependencies */
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 
 /* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
 static struct clkdm_dep mdm_2430_wkdeps[] = {
@@ -194,7 +197,7 @@ static struct clkdm_dep mdm_2430_wkdeps[] = {
 	{ NULL },
 };
 
-#endif /* CONFIG_ARCH_OMAP2430 */
+#endif /* CONFIG_SOC_OMAP2430 */
 
 
 /* OMAP3-specific possible dependencies */
@@ -450,7 +453,7 @@ static struct clockdomain cm_clkdm = {
  * 2420-only clockdomains
  */
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 
 static struct clockdomain mpu_2420_clkdm = {
 	.name		= "mpu_clkdm",
@@ -514,14 +517,14 @@ static struct clockdomain dss_2420_clkdm = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
-#endif   /* CONFIG_ARCH_OMAP2420 */
+#endif   /* CONFIG_SOC_OMAP2420 */
 
 
 /*
  * 2430-only clockdomains
  */
 
-#if defined(CONFIG_ARCH_OMAP2430)
+#if defined(CONFIG_SOC_OMAP2430)
 
 static struct clockdomain mpu_2430_clkdm = {
 	.name		= "mpu_clkdm",
@@ -600,7 +603,7 @@ static struct clockdomain dss_2430_clkdm = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-#endif    /* CONFIG_ARCH_OMAP2430 */
+#endif    /* CONFIG_SOC_OMAP2430 */
 
 
 /*
@@ -811,7 +814,7 @@ static struct clockdomain *clockdomains_omap2[] __initdata = {
 	&cm_clkdm,
 	&prm_clkdm,
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 	&mpu_2420_clkdm,
 	&iva1_2420_clkdm,
 	&dsp_2420_clkdm,
@@ -821,7 +824,7 @@ static struct clockdomain *clockdomains_omap2[] __initdata = {
 	&dss_2420_clkdm,
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 	&mpu_2430_clkdm,
 	&mdm_clkdm,
 	&dsp_2430_clkdm,
@@ -854,7 +857,12 @@ static struct clockdomain *clockdomains_omap2[] __initdata = {
 	NULL,
 };
 
-void __init omap2_clockdomains_init(void)
+void __init omap2xxx_clockdomains_init(void)
+{
+	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
+}
+
+void __init omap3xxx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap2, clkdm_autodeps);
+	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
 }
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index 10622c9..a607ec1 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -18,11 +18,6 @@
  * published by the Free Software Foundation.
  */
 
-/*
- * To-Do List
- * -> Populate the Sleep/Wakeup dependencies for the domains
- */
-
 #include <linux/kernel.h>
 #include <linux/io.h>
 
@@ -35,6 +30,355 @@
 #include "prcm44xx.h"
 #include "prcm_mpu44xx.h"
 
+/* Static Dependencies for OMAP4 Clock Domains */
+
+static struct clkdm_dep ducati_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_gfx_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "tesla_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep iss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_dma_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ducati_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_dss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_init_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep mpuss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ducati_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_gfx_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "tesla_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep tesla_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
 
 static struct clockdomain l4_cefuse_44xx_clkdm = {
 	.name		  = "l4_cefuse_clkdm",
@@ -52,6 +396,7 @@ static struct clockdomain l4_cfg_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
+	.dep_bit	  = OMAP4430_L4CFG_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -62,6 +407,9 @@ static struct clockdomain tesla_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_TESLA_INST,
 	.clkdm_offs	  = OMAP4430_CM1_TESLA_TESLA_CDOFFS,
+	.dep_bit	  = OMAP4430_TESLA_STATDEP_SHIFT,
+	.wkdep_srcs	  = tesla_wkup_sleep_deps,
+	.sleepdep_srcs	  = tesla_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -72,6 +420,9 @@ static struct clockdomain l3_gfx_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_GFX_INST,
 	.clkdm_offs	  = OMAP4430_CM2_GFX_GFX_CDOFFS,
+	.dep_bit	  = OMAP4430_GFX_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_gfx_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -82,6 +433,9 @@ static struct clockdomain ivahd_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_IVAHD_INST,
 	.clkdm_offs	  = OMAP4430_CM2_IVAHD_IVAHD_CDOFFS,
+	.dep_bit	  = OMAP4430_IVAHD_STATDEP_SHIFT,
+	.wkdep_srcs	  = ivahd_wkup_sleep_deps,
+	.sleepdep_srcs	  = ivahd_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -92,6 +446,9 @@ static struct clockdomain l4_secure_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4SEC_CDOFFS,
+	.dep_bit	  = OMAP4430_L4SEC_STATDEP_SHIFT,
+	.wkdep_srcs	  = l4_secure_wkup_sleep_deps,
+	.sleepdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -102,6 +459,7 @@ static struct clockdomain l4_per_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
+	.dep_bit	  = OMAP4430_L4PER_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -112,6 +470,7 @@ static struct clockdomain abe_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_ABE_INST,
 	.clkdm_offs	  = OMAP4430_CM1_ABE_ABE_CDOFFS,
+	.dep_bit	  = OMAP4430_ABE_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -131,6 +490,9 @@ static struct clockdomain l3_init_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L3INIT_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L3INIT_L3INIT_CDOFFS,
+	.dep_bit	  = OMAP4430_L3INIT_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_init_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_init_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -141,6 +503,8 @@ static struct clockdomain mpuss_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_MPU_INST,
 	.clkdm_offs	  = OMAP4430_CM1_MPU_MPU_CDOFFS,
+	.wkdep_srcs	  = mpuss_wkup_sleep_deps,
+	.sleepdep_srcs	  = mpuss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -150,7 +514,7 @@ static struct clockdomain mpu0_44xx_clkdm = {
 	.pwrdm		  = { .name = "cpu0_pwrdm" },
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
-	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -160,7 +524,7 @@ static struct clockdomain mpu1_44xx_clkdm = {
 	.pwrdm		  = { .name = "cpu1_pwrdm" },
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
-	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -171,6 +535,7 @@ static struct clockdomain l3_emif_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
+	.dep_bit	  = OMAP4430_MEMIF_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -191,6 +556,9 @@ static struct clockdomain ducati_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_DUCATI_CDOFFS,
+	.dep_bit	  = OMAP4430_DUCATI_STATDEP_SHIFT,
+	.wkdep_srcs	  = ducati_wkup_sleep_deps,
+	.sleepdep_srcs	  = ducati_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -201,6 +569,7 @@ static struct clockdomain l3_2_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_2_CDOFFS,
+	.dep_bit	  = OMAP4430_L3_2_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -211,6 +580,7 @@ static struct clockdomain l3_1_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_1_CDOFFS,
+	.dep_bit	  = OMAP4430_L3_1_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -221,6 +591,8 @@ static struct clockdomain l3_d2d_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_D2D_CDOFFS,
+	.wkdep_srcs	  = l3_d2d_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -231,6 +603,8 @@ static struct clockdomain iss_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CAM_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CAM_CAM_CDOFFS,
+	.wkdep_srcs	  = iss_wkup_sleep_deps,
+	.sleepdep_srcs	  = iss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -241,6 +615,9 @@ static struct clockdomain l3_dss_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_DSS_INST,
 	.clkdm_offs	  = OMAP4430_CM2_DSS_DSS_CDOFFS,
+	.dep_bit	  = OMAP4430_DSS_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_dss_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -251,6 +628,7 @@ static struct clockdomain l4_wkup_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.cm_inst	  = OMAP4430_PRM_WKUP_CM_INST,
 	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
+	.dep_bit	  = OMAP4430_L4WKUP_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -271,6 +649,8 @@ static struct clockdomain l3_dma_44xx_clkdm = {
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_SDMA_CDOFFS,
+	.wkdep_srcs	  = l3_dma_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -305,5 +685,5 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
 
 void __init omap44xx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap44xx, NULL);
+	clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
 }
diff --git a/arch/arm/mach-omap2/cm-regbits-24xx.h b/arch/arm/mach-omap2/cm-regbits-24xx.h
index d70660e..6862904 100644
--- a/arch/arm/mach-omap2/cm-regbits-24xx.h
+++ b/arch/arm/mach-omap2/cm-regbits-24xx.h
@@ -210,8 +210,11 @@
 #define OMAP24XX_AUTO_USB_MASK				(1 << 0)
 
 /* CM_AUTOIDLE3_CORE */
+#define OMAP24XX_AUTO_SDRC_SHIFT			2
 #define OMAP24XX_AUTO_SDRC_MASK				(1 << 2)
+#define OMAP24XX_AUTO_GPMC_SHIFT			1
 #define OMAP24XX_AUTO_GPMC_MASK				(1 << 1)
+#define OMAP24XX_AUTO_SDMA_SHIFT			0
 #define OMAP24XX_AUTO_SDMA_MASK				(1 << 0)
 
 /* CM_AUTOIDLE4_CORE */
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.c b/arch/arm/mach-omap2/cm2xxx_3xxx.c
index 96954aa..9d0dec8 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.c
@@ -25,6 +25,14 @@
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
+#define DPLL_AUTOIDLE_DISABLE				0x0
+#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
+#define OMAP2XXX_APLL_AUTOIDLE_DISABLE			0x0
+#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
 static const u8 cm_idlest_offs[] = {
 	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
 };
@@ -125,6 +133,67 @@ void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask)
 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
 }
 
+/*
+ * DPLL autoidle control
+ */
+
+static void _omap2xxx_set_dpll_autoidle(u8 m)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~OMAP24XX_AUTO_DPLL_MASK;
+	v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_dpll_disable_autoidle(void)
+{
+	_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
+}
+
+void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
+{
+	_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
+}
+
+/*
+ * APLL autoidle control
+ */
+
+static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~mask;
+	v |= m << __ffs(mask);
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_apll54_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_96M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_96M_MASK);
+}
 
 /*
  *
diff --git a/arch/arm/mach-omap2/cm2xxx_3xxx.h b/arch/arm/mach-omap2/cm2xxx_3xxx.h
index 5e9ea5b..088bbad 100644
--- a/arch/arm/mach-omap2/cm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/cm2xxx_3xxx.h
@@ -122,6 +122,14 @@ extern void omap3xxx_cm_clkdm_disable_hwsup(s16 module, u32 mask);
 extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
 extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
 
+extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
+extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
+
+extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
+extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
+
 #endif
 
 /* CM register bits shared between 24XX and 3430 */
diff --git a/arch/arm/mach-omap2/cm44xx.h b/arch/arm/mach-omap2/cm44xx.h
index 48fc3f4..0b87ec8 100644
--- a/arch/arm/mach-omap2/cm44xx.h
+++ b/arch/arm/mach-omap2/cm44xx.h
@@ -21,6 +21,7 @@
 #include "cm.h"
 
 #define OMAP4_CM_CLKSTCTRL				0x0000
+#define OMAP4_CM_STATICDEP				0x0004
 
 /* Function prototypes */
 # ifndef __ASSEMBLER__
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index c04bbbe..a482bfa 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -73,6 +73,27 @@ u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part, s16 inst,
 	return v;
 }
 
+u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+{
+	return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
+}
+
+u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+{
+	return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
+}
+
+u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, idx);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
 /*
  *
  */
diff --git a/arch/arm/mach-omap2/cminst44xx.h b/arch/arm/mach-omap2/cminst44xx.h
index a6abd0a..2b32c18 100644
--- a/arch/arm/mach-omap2/cminst44xx.h
+++ b/arch/arm/mach-omap2/cminst44xx.h
@@ -25,6 +25,12 @@ extern u32 omap4_cminst_read_inst_reg(u8 part, s16 inst, u16 idx);
 extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
 extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
 					   s16 inst, s16 idx);
+extern u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst,
+					   s16 idx);
+extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
+					   s16 idx);
+extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
+					   u32 mask);
 
 extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
 
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
index 778929f..3f20cbb 100644
--- a/arch/arm/mach-omap2/common.c
+++ b/arch/arm/mach-omap2/common.c
@@ -40,7 +40,7 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 
 static struct omap_globals omap242x_globals = {
 	.class	= OMAP242X_CLASS,
@@ -50,9 +50,6 @@ static struct omap_globals omap242x_globals = {
 	.ctrl	= OMAP242X_CTRL_BASE,
 	.prm	= OMAP2420_PRM_BASE,
 	.cm	= OMAP2420_CM_BASE,
-	.uart1_phys	= OMAP2_UART1_BASE,
-	.uart2_phys	= OMAP2_UART2_BASE,
-	.uart3_phys	= OMAP2_UART3_BASE,
 };
 
 void __init omap2_set_globals_242x(void)
@@ -61,7 +58,7 @@ void __init omap2_set_globals_242x(void)
 }
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2430)
+#if defined(CONFIG_SOC_OMAP2430)
 
 static struct omap_globals omap243x_globals = {
 	.class	= OMAP243X_CLASS,
@@ -71,9 +68,6 @@ static struct omap_globals omap243x_globals = {
 	.ctrl	= OMAP243X_CTRL_BASE,
 	.prm	= OMAP2430_PRM_BASE,
 	.cm	= OMAP2430_CM_BASE,
-	.uart1_phys	= OMAP2_UART1_BASE,
-	.uart2_phys	= OMAP2_UART2_BASE,
-	.uart3_phys	= OMAP2_UART3_BASE,
 };
 
 void __init omap2_set_globals_243x(void)
@@ -92,10 +86,6 @@ static struct omap_globals omap3_globals = {
 	.ctrl	= OMAP343X_CTRL_BASE,
 	.prm	= OMAP3430_PRM_BASE,
 	.cm	= OMAP3430_CM_BASE,
-	.uart1_phys	= OMAP3_UART1_BASE,
-	.uart2_phys	= OMAP3_UART2_BASE,
-	.uart3_phys	= OMAP3_UART3_BASE,
-	.uart4_phys	= OMAP3_UART4_BASE,	/* Only on 3630 */
 };
 
 void __init omap2_set_globals_3xxx(void)
@@ -108,6 +98,27 @@ void __init omap3_map_io(void)
 	omap2_set_globals_3xxx();
 	omap34xx_map_common_io();
 }
+
+/*
+ * Adjust TAP register base such that omap3_check_revision accesses the correct
+ * TI816X register for checking device ID (it adds 0x204 to tap base while
+ * TI816X DEVICE ID register is at offset 0x600 from control base).
+ */
+#define TI816X_TAP_BASE		(TI816X_CTRL_BASE + \
+				TI816X_CONTROL_DEVICE_ID - 0x204)
+
+static struct omap_globals ti816x_globals = {
+	.class  = OMAP343X_CLASS,
+	.tap    = OMAP2_L4_IO_ADDRESS(TI816X_TAP_BASE),
+	.ctrl   = TI816X_CTRL_BASE,
+	.prm    = TI816X_PRCM_BASE,
+	.cm     = TI816X_PRCM_BASE,
+};
+
+void __init omap2_set_globals_ti816x(void)
+{
+	__omap2_set_globals(&ti816x_globals);
+}
 #endif
 
 #if defined(CONFIG_ARCH_OMAP4)
@@ -119,10 +130,6 @@ static struct omap_globals omap4_globals = {
 	.prm	= OMAP4430_PRM_BASE,
 	.cm	= OMAP4430_CM_BASE,
 	.cm2	= OMAP4430_CM2_BASE,
-	.uart1_phys	= OMAP4_UART1_BASE,
-	.uart2_phys	= OMAP4_UART2_BASE,
-	.uart3_phys	= OMAP4_UART3_BASE,
-	.uart4_phys	= OMAP4_UART4_BASE,
 };
 
 void __init omap2_set_globals_443x(void)
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index f0629ae..c2804c1 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -52,6 +52,9 @@
 #define OMAP343X_CONTROL_PADCONFS_WKUP	0xa00
 #define OMAP343X_CONTROL_GENERAL_WKUP	0xa60
 
+/* TI816X spefic control submodules */
+#define TI816X_CONTROL_DEVCONF		0x600
+
 /* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
 
 #define OMAP2_CONTROL_SYSCONFIG		(OMAP2_CONTROL_INTERFACE + 0x10)
@@ -241,6 +244,9 @@
 #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
 #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
 
+/* TI816X CONTROL_DEVCONF register offsets */
+#define TI816X_CONTROL_DEVICE_ID	(TI816X_CONTROL_DEVCONF + 0x000)
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index f7b22a1..a44c523 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -58,6 +58,7 @@ struct omap3_processor_cx {
 	u32 core_state;
 	u32 threshold;
 	u32 flags;
+	const char *desc;
 };
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
@@ -99,14 +100,14 @@ static int omap3_idle_bm_check(void)
 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
 				struct clockdomain *clkdm)
 {
-	omap2_clkdm_allow_idle(clkdm);
+	clkdm_allow_idle(clkdm);
 	return 0;
 }
 
 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 				struct clockdomain *clkdm)
 {
-	omap2_clkdm_deny_idle(clkdm);
+	clkdm_deny_idle(clkdm);
 	return 0;
 }
 
@@ -365,6 +366,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
+	omap3_power_states[OMAP3_STATE_C1].desc = "MPU ON + CORE ON";
 
 	/* C2 . MPU WFI + Core inactive */
 	omap3_power_states[OMAP3_STATE_C2].valid =
@@ -380,6 +382,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C2].desc = "MPU ON + CORE ON";
 
 	/* C3 . MPU CSWR + Core inactive */
 	omap3_power_states[OMAP3_STATE_C3].valid =
@@ -395,6 +398,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C3].desc = "MPU RET + CORE ON";
 
 	/* C4 . MPU OFF + Core inactive */
 	omap3_power_states[OMAP3_STATE_C4].valid =
@@ -410,6 +414,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C4].desc = "MPU OFF + CORE ON";
 
 	/* C5 . MPU CSWR + Core CSWR*/
 	omap3_power_states[OMAP3_STATE_C5].valid =
@@ -425,6 +430,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
 	omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C5].desc = "MPU RET + CORE RET";
 
 	/* C6 . MPU OFF + Core CSWR */
 	omap3_power_states[OMAP3_STATE_C6].valid =
@@ -440,6 +446,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET;
 	omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C6].desc = "MPU OFF + CORE RET";
 
 	/* C7 . MPU OFF + Core OFF */
 	omap3_power_states[OMAP3_STATE_C7].valid =
@@ -455,6 +462,7 @@ void omap_init_power_states(void)
 	omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
 	omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C7].desc = "MPU OFF + CORE OFF";
 
 	/*
 	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
@@ -464,7 +472,7 @@ void omap_init_power_states(void)
 	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
 		omap3_power_states[OMAP3_STATE_C7].valid = 0;
 		cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
-		WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n",
+		pr_warn("%s: core off state C7 disabled due to i583\n",
 				__func__);
 	}
 }
@@ -512,6 +520,7 @@ int __init omap3_idle_init(void)
 		if (cx->type == OMAP3_STATE_C1)
 			dev->safe_state = state;
 		sprintf(state->name, "C%d", count+1);
+		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
 		count++;
 	}
 
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 2c9c912..0d2d6a9 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -30,10 +31,75 @@
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap4-keypad.h>
 
 #include "mux.h"
 #include "control.h"
 
+#define L3_MODULES_MAX_LEN 12
+#define L3_MODULES 3
+
+static int __init omap3_l3_init(void)
+{
+	int l;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	char oh_name[L3_MODULES_MAX_LEN];
+
+	/*
+	 * To avoid code running on other OMAPs in
+	 * multi-omap builds
+	 */
+	if (!(cpu_is_omap34xx()))
+		return -ENODEV;
+
+	l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
+
+	oh = omap_hwmod_lookup(oh_name);
+
+	if (!oh)
+		pr_err("could not look up %s\n", oh_name);
+
+	od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+							   NULL, 0, 0);
+
+	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+
+	return PTR_ERR(od);
+}
+postcore_initcall(omap3_l3_init);
+
+static int __init omap4_l3_init(void)
+{
+	int l, i;
+	struct omap_hwmod *oh[3];
+	struct omap_device *od;
+	char oh_name[L3_MODULES_MAX_LEN];
+
+	/*
+	 * To avoid code running on other OMAPs in
+	 * multi-omap builds
+	 */
+	if (!(cpu_is_omap44xx()))
+		return -ENODEV;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
+
+		oh[i] = omap_hwmod_lookup(oh_name);
+		if (!(oh[i]))
+			pr_err("could not look up %s\n", oh_name);
+	}
+
+	od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+						     0, NULL, 0, 0);
+
+	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+
+	return PTR_ERR(od);
+}
+postcore_initcall(omap4_l3_init);
+
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
 static struct resource cam_resources[] = {
@@ -141,96 +207,70 @@ static inline void omap_init_camera(void)
 }
 #endif
 
-#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
-
-#define MBOX_REG_SIZE   0x120
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct resource omap2_mbox_resources[] = {
-	{
-		.start		= OMAP24XX_MAILBOX_BASE,
-		.end		= OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= INT_24XX_MAIL_U0_MPU,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "dsp",
-	},
+struct omap_device_pm_latency omap_keyboard_latency[] = {
 	{
-		.start		= INT_24XX_MAIL_U3_MPU,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "iva",
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
 };
-static int omap2_mbox_resources_sz = ARRAY_SIZE(omap2_mbox_resources);
-#else
-#define omap2_mbox_resources		NULL
-#define omap2_mbox_resources_sz		0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct resource omap3_mbox_resources[] = {
-	{
-		.start		= OMAP34XX_MAILBOX_BASE,
-		.end		= OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= INT_24XX_MAIL_U0_MPU,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "dsp",
-	},
-};
-static int omap3_mbox_resources_sz = ARRAY_SIZE(omap3_mbox_resources);
-#else
-#define omap3_mbox_resources		NULL
-#define omap3_mbox_resources_sz		0
-#endif
+int __init omap4_keyboard_init(struct omap4_keypad_platform_data
+						*sdp4430_keypad_data)
+{
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct omap4_keypad_platform_data *keypad_data;
+	unsigned int id = -1;
+	char *oh_name = "kbd";
+	char *name = "omap4-keypad";
 
-#ifdef CONFIG_ARCH_OMAP4
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
 
-#define OMAP4_MBOX_REG_SIZE	0x130
-static struct resource omap4_mbox_resources[] = {
-	{
-		.start          = OMAP44XX_MAILBOX_BASE,
-		.end            = OMAP44XX_MAILBOX_BASE +
-					OMAP4_MBOX_REG_SIZE - 1,
-		.flags          = IORESOURCE_MEM,
-	},
-	{
-		.start          = OMAP44XX_IRQ_MAIL_U0,
-		.flags          = IORESOURCE_IRQ,
-		.name		= "mbox",
-	},
-};
-static int omap4_mbox_resources_sz = ARRAY_SIZE(omap4_mbox_resources);
-#else
-#define omap4_mbox_resources		NULL
-#define omap4_mbox_resources_sz		0
-#endif
+	keypad_data = sdp4430_keypad_data;
 
-static struct platform_device mbox_device = {
-	.name		= "omap-mailbox",
-	.id		= -1,
+	od = omap_device_build(name, id, oh, keypad_data,
+			sizeof(struct omap4_keypad_platform_data),
+			omap_keyboard_latency,
+			ARRAY_SIZE(omap_keyboard_latency), 0);
+
+	if (IS_ERR(od)) {
+		WARN(1, "Cant build omap_device for %s:%s.\n",
+						name, oh->name);
+		return PTR_ERR(od);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
+static struct omap_device_pm_latency mbox_latencies[] = {
+	[0] = {
+		.activate_func = omap_device_enable_hwmods,
+		.deactivate_func = omap_device_idle_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
 };
 
 static inline void omap_init_mbox(void)
 {
-	if (cpu_is_omap24xx()) {
-		mbox_device.resource = omap2_mbox_resources;
-		mbox_device.num_resources = omap2_mbox_resources_sz;
-	} else if (cpu_is_omap34xx()) {
-		mbox_device.resource = omap3_mbox_resources;
-		mbox_device.num_resources = omap3_mbox_resources_sz;
-	} else if (cpu_is_omap44xx()) {
-		mbox_device.resource = omap4_mbox_resources;
-		mbox_device.num_resources = omap4_mbox_resources_sz;
-	} else {
-		pr_err("%s: platform not supported\n", __func__);
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+
+	oh = omap_hwmod_lookup("mailbox");
+	if (!oh) {
+		pr_err("%s: unable to find hwmod\n", __func__);
 		return;
 	}
-	platform_device_register(&mbox_device);
+
+	od = omap_device_build("omap-mailbox", -1, oh, NULL, 0,
+				mbox_latencies, ARRAY_SIZE(mbox_latencies), 0);
+	WARN(IS_ERR(od), "%s: could not build device, err %ld\n",
+						__func__, PTR_ERR(od));
 }
 #else
 static inline void omap_init_mbox(void) { }
@@ -279,163 +319,55 @@ static inline void omap_init_audio(void) {}
 
 #include <plat/mcspi.h>
 
-#define OMAP2_MCSPI1_BASE		0x48098000
-#define OMAP2_MCSPI2_BASE		0x4809a000
-#define OMAP2_MCSPI3_BASE		0x480b8000
-#define OMAP2_MCSPI4_BASE		0x480ba000
-
-#define OMAP4_MCSPI1_BASE		0x48098100
-#define OMAP4_MCSPI2_BASE		0x4809a100
-#define OMAP4_MCSPI3_BASE		0x480b8100
-#define OMAP4_MCSPI4_BASE		0x480ba100
-
-static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
-	.num_cs		= 4,
-};
-
-static struct resource omap2_mcspi1_resources[] = {
-	{
-		.start		= OMAP2_MCSPI1_BASE,
-		.end		= OMAP2_MCSPI1_BASE + 0xff,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi1 = {
-	.name		= "omap2_mcspi",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi1_resources),
-	.resource	= omap2_mcspi1_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi1_config,
-	},
-};
-
-static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
-	.num_cs		= 2,
-};
-
-static struct resource omap2_mcspi2_resources[] = {
-	{
-		.start		= OMAP2_MCSPI2_BASE,
-		.end		= OMAP2_MCSPI2_BASE + 0xff,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi2 = {
-	.name		= "omap2_mcspi",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi2_resources),
-	.resource	= omap2_mcspi2_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi2_config,
-	},
-};
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-	defined(CONFIG_ARCH_OMAP4)
-static struct omap2_mcspi_platform_config omap2_mcspi3_config = {
-	.num_cs		= 2,
-};
-
-static struct resource omap2_mcspi3_resources[] = {
-	{
-	.start		= OMAP2_MCSPI3_BASE,
-	.end		= OMAP2_MCSPI3_BASE + 0xff,
-	.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi3 = {
-	.name		= "omap2_mcspi",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi3_resources),
-	.resource	= omap2_mcspi3_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi3_config,
-	},
-};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static struct omap2_mcspi_platform_config omap2_mcspi4_config = {
-	.num_cs		= 1,
-};
-
-static struct resource omap2_mcspi4_resources[] = {
-	{
-		.start		= OMAP2_MCSPI4_BASE,
-		.end		= OMAP2_MCSPI4_BASE + 0xff,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi4 = {
-	.name		= "omap2_mcspi",
-	.id		= 4,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi4_resources),
-	.resource	= omap2_mcspi4_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi4_config,
+struct omap_device_pm_latency omap_mcspi_latency[] = {
+	[0] = {
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
 };
-#endif
 
-#ifdef CONFIG_ARCH_OMAP4
-static inline void omap4_mcspi_fixup(void)
+static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 {
-	omap2_mcspi1_resources[0].start	= OMAP4_MCSPI1_BASE;
-	omap2_mcspi1_resources[0].end	= OMAP4_MCSPI1_BASE + 0xff;
-	omap2_mcspi2_resources[0].start	= OMAP4_MCSPI2_BASE;
-	omap2_mcspi2_resources[0].end	= OMAP4_MCSPI2_BASE + 0xff;
-	omap2_mcspi3_resources[0].start	= OMAP4_MCSPI3_BASE;
-	omap2_mcspi3_resources[0].end	= OMAP4_MCSPI3_BASE + 0xff;
-	omap2_mcspi4_resources[0].start	= OMAP4_MCSPI4_BASE;
-	omap2_mcspi4_resources[0].end	= OMAP4_MCSPI4_BASE + 0xff;
-}
-#else
-static inline void omap4_mcspi_fixup(void)
-{
-}
-#endif
+	struct omap_device *od;
+	char *name = "omap2_mcspi";
+	struct omap2_mcspi_platform_config *pdata;
+	static int spi_num;
+	struct omap2_mcspi_dev_attr *mcspi_attrib = oh->dev_attr;
+
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("Memory allocation for McSPI device failed\n");
+		return -ENOMEM;
+	}
 
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-	defined(CONFIG_ARCH_OMAP4)
-static inline void omap2_mcspi3_init(void)
-{
-	platform_device_register(&omap2_mcspi3);
-}
-#else
-static inline void omap2_mcspi3_init(void)
-{
-}
-#endif
+	pdata->num_cs = mcspi_attrib->num_chipselect;
+	switch (oh->class->rev) {
+	case OMAP2_MCSPI_REV:
+	case OMAP3_MCSPI_REV:
+			pdata->regs_offset = 0;
+			break;
+	case OMAP4_MCSPI_REV:
+			pdata->regs_offset = OMAP4_MCSPI_REG_OFFSET;
+			break;
+	default:
+			pr_err("Invalid McSPI Revision value\n");
+			return -EINVAL;
+	}
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static inline void omap2_mcspi4_init(void)
-{
-	platform_device_register(&omap2_mcspi4);
-}
-#else
-static inline void omap2_mcspi4_init(void)
-{
+	spi_num++;
+	od = omap_device_build(name, spi_num, oh, pdata,
+				sizeof(*pdata),	omap_mcspi_latency,
+				ARRAY_SIZE(omap_mcspi_latency), 0);
+	WARN(IS_ERR(od), "Cant build omap_device for %s:%s\n",
+				name, oh->name);
+	kfree(pdata);
+	return 0;
 }
-#endif
 
 static void omap_init_mcspi(void)
 {
-	if (cpu_is_omap44xx())
-		omap4_mcspi_fixup();
-
-	platform_device_register(&omap2_mcspi1);
-	platform_device_register(&omap2_mcspi2);
-
-	if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx())
-		omap2_mcspi3_init();
-
-	if (cpu_is_omap343x() || cpu_is_omap44xx())
-		omap2_mcspi4_init();
+	omap_hwmod_for_each_by_class("mcspi", omap_mcspi_init, NULL);
 }
 
 #else
@@ -610,117 +542,10 @@ static inline void omap_init_aes(void) { }
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-
-#define MMCHS_SYSCONFIG			0x0010
-#define MMCHS_SYSCONFIG_SWRESET		(1 << 1)
-#define MMCHS_SYSSTATUS			0x0014
-#define MMCHS_SYSSTATUS_RESETDONE	(1 << 0)
-
-static struct platform_device dummy_pdev = {
-	.dev = {
-		.bus = &platform_bus_type,
-	},
-};
-
-/**
- * omap_hsmmc_reset() - Full reset of each HS-MMC controller
- *
- * Ensure that each MMC controller is fully reset.  Controllers
- * left in an unknown state (by bootloader) may prevent retention
- * or OFF-mode.  This is especially important in cases where the
- * MMC driver is not enabled, _or_ built as a module.
- *
- * In order for reset to work, interface, functional and debounce
- * clocks must be enabled.  The debounce clock comes from func_32k_clk
- * and is not under SW control, so we only enable i- and f-clocks.
- **/
-static void __init omap_hsmmc_reset(void)
-{
-	u32 i, nr_controllers;
-	struct clk *iclk, *fclk;
-
-	if (cpu_is_omap242x())
-		return;
-
-	nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC :
-		(cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC);
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
-	for (i = 0; i < nr_controllers; i++) {
-		u32 v, base = 0;
-		struct device *dev = &dummy_pdev.dev;
-
-		switch (i) {
-		case 0:
-			base = OMAP2_MMC1_BASE;
-			break;
-		case 1:
-			base = OMAP2_MMC2_BASE;
-			break;
-		case 2:
-			base = OMAP3_MMC3_BASE;
-			break;
-		case 3:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC4_BASE;
-			break;
-		case 4:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC5_BASE;
-			break;
-		}
-
-		if (cpu_is_omap44xx())
-			base += OMAP4_MMC_REG_OFFSET;
-
-		dummy_pdev.id = i;
-		dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
-		iclk = clk_get(dev, "ick");
-		if (IS_ERR(iclk))
-			goto err1;
-		if (clk_enable(iclk))
-			goto err2;
-
-		fclk = clk_get(dev, "fck");
-		if (IS_ERR(fclk))
-			goto err3;
-		if (clk_enable(fclk))
-			goto err4;
-
-		omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
-		v = omap_readl(base + MMCHS_SYSSTATUS);
-		while (!(omap_readl(base + MMCHS_SYSSTATUS) &
-			 MMCHS_SYSSTATUS_RESETDONE))
-			cpu_relax();
-
-		clk_disable(fclk);
-		clk_put(fclk);
-		clk_disable(iclk);
-		clk_put(iclk);
-	}
-	return;
-
-err4:
-	clk_put(fclk);
-err3:
-	clk_disable(iclk);
-err2:
-	clk_put(iclk);
-err1:
-	printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, "
-			    "cannot reset.\n",  __func__, i);
-}
-#else
-static inline void omap_hsmmc_reset(void) {}
-#endif
-
-#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
-	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
-
-static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
-			int controller_nr)
+static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
+							*mmc_controller)
 {
 	if ((mmc_controller->slots[0].switch_pin > 0) && \
 		(mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
@@ -731,163 +556,44 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
 		omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
 					OMAP_PIN_INPUT_PULLUP);
 
-	if (cpu_is_omap2420() && controller_nr == 0) {
-		omap_mux_init_signal("sdmmc_cmd", 0);
-		omap_mux_init_signal("sdmmc_clki", 0);
-		omap_mux_init_signal("sdmmc_clko", 0);
-		omap_mux_init_signal("sdmmc_dat0", 0);
-		omap_mux_init_signal("sdmmc_dat_dir0", 0);
-		omap_mux_init_signal("sdmmc_cmd_dir", 0);
-		if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
-			omap_mux_init_signal("sdmmc_dat1", 0);
-			omap_mux_init_signal("sdmmc_dat2", 0);
-			omap_mux_init_signal("sdmmc_dat3", 0);
-			omap_mux_init_signal("sdmmc_dat_dir1", 0);
-			omap_mux_init_signal("sdmmc_dat_dir2", 0);
-			omap_mux_init_signal("sdmmc_dat_dir3", 0);
-		}
-
-		/*
-		 * Use internal loop-back in MMC/SDIO Module Input Clock
-		 * selection
-		 */
-		if (mmc_controller->slots[0].internal_clock) {
-			u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-			v |= (1 << 24);
-			omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-		}
+	omap_mux_init_signal("sdmmc_cmd", 0);
+	omap_mux_init_signal("sdmmc_clki", 0);
+	omap_mux_init_signal("sdmmc_clko", 0);
+	omap_mux_init_signal("sdmmc_dat0", 0);
+	omap_mux_init_signal("sdmmc_dat_dir0", 0);
+	omap_mux_init_signal("sdmmc_cmd_dir", 0);
+	if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
+		omap_mux_init_signal("sdmmc_dat1", 0);
+		omap_mux_init_signal("sdmmc_dat2", 0);
+		omap_mux_init_signal("sdmmc_dat3", 0);
+		omap_mux_init_signal("sdmmc_dat_dir1", 0);
+		omap_mux_init_signal("sdmmc_dat_dir2", 0);
+		omap_mux_init_signal("sdmmc_dat_dir3", 0);
 	}
 
-	if (cpu_is_omap34xx()) {
-		if (controller_nr == 0) {
-			omap_mux_init_signal("sdmmc1_clk",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc1_cmd",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc1_dat0",
-				OMAP_PIN_INPUT_PULLUP);
-			if (mmc_controller->slots[0].caps &
-				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
-				omap_mux_init_signal("sdmmc1_dat1",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat2",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat3",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-			if (mmc_controller->slots[0].caps &
-						MMC_CAP_8_BIT_DATA) {
-				omap_mux_init_signal("sdmmc1_dat4",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat5",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat6",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat7",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-		}
-		if (controller_nr == 1) {
-			/* MMC2 */
-			omap_mux_init_signal("sdmmc2_clk",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc2_cmd",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc2_dat0",
-				OMAP_PIN_INPUT_PULLUP);
-
-			/*
-			 * For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed
-			 * in the board-*.c files
-			 */
-			if (mmc_controller->slots[0].caps &
-				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
-				omap_mux_init_signal("sdmmc2_dat1",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat2",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat3",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-			if (mmc_controller->slots[0].caps &
-							MMC_CAP_8_BIT_DATA) {
-				omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-		}
-
-		/*
-		 * For MMC3 the pins need to be muxed in the board-*.c files
-		 */
+	/*
+	 * Use internal loop-back in MMC/SDIO Module Input Clock
+	 * selection
+	 */
+	if (mmc_controller->slots[0].internal_clock) {
+		u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+		v |= (1 << 24);
+		omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
 	}
 }
 
-void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
-			int nr_controllers)
+void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
 {
-	int i;
-	char *name;
+	char *name = "mmci-omap";
 
-	for (i = 0; i < nr_controllers; i++) {
-		unsigned long base, size;
-		unsigned int irq = 0;
-
-		if (!mmc_data[i])
-			continue;
-
-		omap2_mmc_mux(mmc_data[i], i);
+	if (!mmc_data[0]) {
+		pr_err("%s fails: Incomplete platform data\n", __func__);
+		return;
+	}
 
-		switch (i) {
-		case 0:
-			base = OMAP2_MMC1_BASE;
-			irq = INT_24XX_MMC_IRQ;
-			break;
-		case 1:
-			base = OMAP2_MMC2_BASE;
-			irq = INT_24XX_MMC2_IRQ;
-			break;
-		case 2:
-			if (!cpu_is_omap44xx() && !cpu_is_omap34xx())
-				return;
-			base = OMAP3_MMC3_BASE;
-			irq = INT_34XX_MMC3_IRQ;
-			break;
-		case 3:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC4_BASE;
-			irq = OMAP44XX_IRQ_MMC4;
-			break;
-		case 4:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC5_BASE;
-			irq = OMAP44XX_IRQ_MMC5;
-			break;
-		default:
-			continue;
-		}
-
-		if (cpu_is_omap2420()) {
-			size = OMAP2420_MMC_SIZE;
-			name = "mmci-omap";
-		} else if (cpu_is_omap44xx()) {
-			if (i < 3)
-				irq += OMAP44XX_IRQ_GIC_START;
-			size = OMAP4_HSMMC_SIZE;
-			name = "mmci-omap-hs";
-		} else {
-			size = OMAP3_HSMMC_SIZE;
-			name = "mmci-omap-hs";
-		}
-		omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
-	};
+	omap242x_mmc_mux(mmc_data[0]);
+	omap_mmc_add(name, 0, OMAP2_MMC1_BASE, OMAP2420_MMC_SIZE,
+					INT_24XX_MMC_IRQ, mmc_data[0]);
 }
 
 #endif
@@ -895,7 +601,7 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
 #define OMAP_HDQ_BASE	0x480B2000
 #endif
 static struct resource omap_hdq_resources[] = {
@@ -961,7 +667,6 @@ static int __init omap2_init_devices(void)
 	 * please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	omap_hsmmc_reset();
 	omap_init_audio();
 	omap_init_camera();
 	omap_init_mbox();
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
new file mode 100644
index 0000000..b18db84
--- /dev/null
+++ b/arch/arm/mach-omap2/display.c
@@ -0,0 +1,45 @@
+/*
+ * OMAP2plus display device setup / initialization.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Senthilvadivu Guruswamy
+ *	Sumit Semwal
+ *
+ * This program is free software; you can 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/display.h>
+
+static struct platform_device omap_display_device = {
+	.name          = "omapdss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = NULL,
+	},
+};
+
+int __init omap_display_init(struct omap_dss_board_info *board_data)
+{
+	int r = 0;
+	omap_display_device.dev.platform_data = board_data;
+
+	r = platform_device_register(&omap_display_device);
+	if (r < 0)
+		printk(KERN_ERR "Unable to register OMAP-Display device\n");
+
+	return r;
+}
diff --git a/arch/arm/mach-omap2/dpll44xx.c b/arch/arm/mach-omap2/dpll44xx.c
new file mode 100644
index 0000000..4e4da61
--- /dev/null
+++ b/arch/arm/mach-omap2/dpll44xx.c
@@ -0,0 +1,84 @@
+/*
+ * OMAP4-specific DPLL control functions
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Rajendra Nayak
+ *
+ * This program is free software; you can 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/clk.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+
+#include "clock.h"
+#include "cm-regbits-44xx.h"
+
+/* Supported only on OMAP4 */
+int omap4_dpllmx_gatectrl_read(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return -EINVAL;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	/* Clear the bit to allow gatectrl */
+	v &= ~mask;
+	__raw_writel(v, clk->clksel_reg);
+}
+
+void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	/* Set the bit to deny gatectrl */
+	v |= mask;
+	__raw_writel(v, clk->clksel_reg);
+}
+
+const struct clkops clkops_omap4_dpllmx_ops = {
+	.allow_idle	= omap4_dpllmx_allow_gatectrl,
+	.deny_idle	= omap4_dpllmx_deny_gatectrl,
+};
+
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index 2bb29c1..c1791d0 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach/flash.h>
 
@@ -69,8 +70,10 @@ static int omap2_nand_gpmc_retime(void)
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
 	/* Configure GPMC */
-	gpmc_cs_configure(gpmc_nand_data->cs,
-				GPMC_CONFIG_DEV_SIZE, gpmc_nand_data->devsize);
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
+	else
+		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
 	gpmc_cs_configure(gpmc_nand_data->cs,
 			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
 	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c
index 3a7d25f..d776ded 100644
--- a/arch/arm/mach-omap2/gpmc-onenand.c
+++ b/arch/arm/mach-omap2/gpmc-onenand.c
@@ -94,7 +94,7 @@ static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base)
 }
 
 static void set_onenand_cfg(void __iomem *onenand_base, int latency,
-				int sync_read, int sync_write, int hf)
+				int sync_read, int sync_write, int hf, int vhf)
 {
 	u32 reg;
 
@@ -114,12 +114,57 @@ static void set_onenand_cfg(void __iomem *onenand_base, int latency,
 		reg |= ONENAND_SYS_CFG1_HF;
 	else
 		reg &= ~ONENAND_SYS_CFG1_HF;
+	if (vhf)
+		reg |= ONENAND_SYS_CFG1_VHF;
+	else
+		reg &= ~ONENAND_SYS_CFG1_VHF;
 	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 }
 
+static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
+				  void __iomem *onenand_base, bool *clk_dep)
+{
+	u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
+	int freq = 0;
+
+	if (cfg->get_freq) {
+		struct onenand_freq_info fi;
+
+		fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID);
+		fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID);
+		fi.ver_id = ver;
+		freq = cfg->get_freq(&fi, clk_dep);
+		if (freq)
+			return freq;
+	}
+
+	switch ((ver >> 4) & 0xf) {
+	case 0:
+		freq = 40;
+		break;
+	case 1:
+		freq = 54;
+		break;
+	case 2:
+		freq = 66;
+		break;
+	case 3:
+		freq = 83;
+		break;
+	case 4:
+		freq = 104;
+		break;
+	default:
+		freq = 54;
+		break;
+	}
+
+	return freq;
+}
+
 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					void __iomem *onenand_base,
-					int freq)
+					int *freq_ptr)
 {
 	struct gpmc_timings t;
 	const int t_cer  = 15;
@@ -130,10 +175,11 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	const int t_wph  = 30;
 	int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
 	int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency;
-	int first_time = 0, hf = 0, sync_read = 0, sync_write = 0;
+	int first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
 	int err, ticks_cez;
-	int cs = cfg->cs;
+	int cs = cfg->cs, freq = *freq_ptr;
 	u32 reg;
+	bool clk_dep = false;
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
 		sync_read = 1;
@@ -148,27 +194,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 		err = omap2_onenand_set_async_mode(cs, onenand_base);
 		if (err)
 			return err;
-		reg = readw(onenand_base + ONENAND_REG_VERSION_ID);
-		switch ((reg >> 4) & 0xf) {
-		case 0:
-			freq = 40;
-			break;
-		case 1:
-			freq = 54;
-			break;
-		case 2:
-			freq = 66;
-			break;
-		case 3:
-			freq = 83;
-			break;
-		case 4:
-			freq = 104;
-			break;
-		default:
-			freq = 54;
-			break;
-		}
+		freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
 		first_time = 1;
 	}
 
@@ -180,7 +206,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 		t_avdh  = 2;
 		t_ach   = 3;
 		t_aavdh = 6;
-		t_rdyo  = 9;
+		t_rdyo  = 6;
 		break;
 	case 83:
 		min_gpmc_clk_period = 12000; /* 83 MHz */
@@ -217,16 +243,36 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	gpmc_clk_ns = gpmc_ticks_to_ns(div);
 	if (gpmc_clk_ns < 15) /* >66Mhz */
 		hf = 1;
-	if (hf)
+	if (gpmc_clk_ns < 12) /* >83Mhz */
+		vhf = 1;
+	if (vhf)
+		latency = 8;
+	else if (hf)
 		latency = 6;
 	else if (gpmc_clk_ns >= 25) /* 40 MHz*/
 		latency = 3;
 	else
 		latency = 4;
 
+	if (clk_dep) {
+		if (gpmc_clk_ns < 12) { /* >83Mhz */
+			t_ces   = 3;
+			t_avds  = 4;
+		} else if (gpmc_clk_ns < 15) { /* >66Mhz */
+			t_ces   = 5;
+			t_avds  = 4;
+		} else if (gpmc_clk_ns < 25) { /* >40Mhz */
+			t_ces   = 6;
+			t_avds  = 5;
+		} else {
+			t_ces   = 7;
+			t_avds  = 7;
+		}
+	}
+
 	if (first_time)
 		set_onenand_cfg(onenand_base, latency,
-					sync_read, sync_write, hf);
+					sync_read, sync_write, hf, vhf);
 
 	if (div == 1) {
 		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
@@ -264,6 +310,9 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	/* Read */
 	t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh));
 	t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach));
+	/* Force at least 1 clk between AVD High to OE Low */
+	if (t.oe_on <= t.adv_rd_off)
+		t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
 	t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div);
 	t.oe_off = t.access + gpmc_round_ns_to_ticks(1);
 	t.cs_rd_off = t.oe_off;
@@ -317,18 +366,20 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 	if (err)
 		return err;
 
-	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf);
+	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
+
+	*freq_ptr = freq;
 
 	return 0;
 }
 
-static int gpmc_onenand_setup(void __iomem *onenand_base, int freq)
+static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
 	struct device *dev = &gpmc_onenand_device.dev;
 
 	/* Set sync timings in GPMC */
 	if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base,
-			freq) < 0) {
+			freq_ptr) < 0) {
 		dev_err(dev, "Unable to set synchronous mode\n");
 		return -EINVAL;
 	}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 1b7b3e7..6741743 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -14,6 +14,7 @@
  */
 #undef DEBUG
 
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -22,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
@@ -58,7 +60,6 @@
 #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
 #define GPMC_SECTION_SHIFT	28		/* 128 MB */
 
-#define PREFETCH_FIFOTHRESHOLD	(0x40 << 8)
 #define CS_NUM_SHIFT		24
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
@@ -100,6 +101,8 @@ static void __iomem *gpmc_base;
 
 static struct clk *gpmc_l3_clk;
 
+static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+
 static void gpmc_write_reg(int idx, u32 val)
 {
 	__raw_writel(val, gpmc_base + idx);
@@ -497,6 +500,10 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
 	u32 regval = 0;
 
 	switch (cmd) {
+	case GPMC_ENABLE_IRQ:
+		gpmc_write_reg(GPMC_IRQENABLE, wval);
+		break;
+
 	case GPMC_SET_IRQ_STATUS:
 		gpmc_write_reg(GPMC_IRQSTATUS, wval);
 		break;
@@ -598,15 +605,19 @@ EXPORT_SYMBOL(gpmc_nand_write);
 /**
  * gpmc_prefetch_enable - configures and starts prefetch transfer
  * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
  * @dma_mode: dma mode enable (1) or disable (0)
  * @u32_count: number of bytes to be transferred
  * @is_write: prefetch read(0) or write post(1) mode
  */
-int gpmc_prefetch_enable(int cs, int dma_mode,
+int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 				unsigned int u32_count, int is_write)
 {
 
-	if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+		pr_err("gpmc: fifo threshold is not supported\n");
+		return -1;
+	} else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
 		/* Set the amount of bytes to be prefetched */
 		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
 
@@ -614,7 +625,7 @@ int gpmc_prefetch_enable(int cs, int dma_mode,
 		 * enable the engine. Set which cs is has requested for.
 		 */
 		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
-					PREFETCH_FIFOTHRESHOLD |
+					PREFETCH_FIFOTHRESHOLD(fifo_th) |
 					ENABLE_PREFETCH |
 					(dma_mode << DMA_MPU_MODE) |
 					(0x1 & is_write)));
@@ -678,9 +689,10 @@ static void __init gpmc_mem_init(void)
 	}
 }
 
-void __init gpmc_init(void)
+static int __init gpmc_init(void)
 {
-	u32 l;
+	u32 l, irq;
+	int cs, ret = -EINVAL;
 	char *ck = NULL;
 
 	if (cpu_is_omap24xx()) {
@@ -698,7 +710,7 @@ void __init gpmc_init(void)
 	}
 
 	if (WARN_ON(!ck))
-		return;
+		return ret;
 
 	gpmc_l3_clk = clk_get(NULL, ck);
 	if (IS_ERR(gpmc_l3_clk)) {
@@ -723,6 +735,36 @@ void __init gpmc_init(void)
 	l |= (0x02 << 3) | (1 << 0);
 	gpmc_write_reg(GPMC_SYSCONFIG, l);
 	gpmc_mem_init();
+
+	/* initalize the irq_chained */
+	irq = OMAP_GPMC_IRQ_BASE;
+	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+		set_irq_handler(irq, handle_simple_irq);
+		set_irq_flags(irq, IRQF_VALID);
+		irq++;
+	}
+
+	ret = request_irq(INT_34XX_GPMC_IRQ,
+			gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base);
+	if (ret)
+		pr_err("gpmc: irq-%d could not claim: err %d\n",
+						INT_34XX_GPMC_IRQ, ret);
+	return ret;
+}
+postcore_initcall(gpmc_init);
+
+static irqreturn_t gpmc_handle_irq(int irq, void *dev)
+{
+	u8 cs;
+
+	if (irq != INT_34XX_GPMC_IRQ)
+		return IRQ_HANDLED;
+	/* check cs to invoke the irq */
+	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
+	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
+		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+
+	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_ARCH_OMAP3
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 34272e4..137e1a5 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -16,7 +16,10 @@
 #include <mach/hardware.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
+#include <plat/mux.h>
+#include <plat/omap_device.h>
 
+#include "mux.h"
 #include "hsmmc.h"
 #include "control.h"
 
@@ -28,10 +31,6 @@ static u16 control_mmc1;
 
 #define HSMMC_NAME_LEN	9
 
-static struct hsmmc_controller {
-	char				name[HSMMC_NAME_LEN + 1];
-} hsmmc[OMAP34XX_NR_MMC];
-
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 
 static int hsmmc_get_context_loss(struct device *dev)
@@ -204,174 +203,312 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on,
 	return 0;
 }
 
-static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
-
-void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
+			int controller_nr)
 {
-	struct omap2_hsmmc_info *c;
-	int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
-	int i;
-	u32 reg;
-
-	if (!cpu_is_omap44xx()) {
-		if (cpu_is_omap2430()) {
-			control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
-			control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
-		} else {
-			control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
-			control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
-		}
-	} else {
-		control_pbias_offset =
-			OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
-		control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
-		reg = omap4_ctrl_pad_readl(control_mmc1);
-		reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
-			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
-		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
-			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
-		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
-			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
-			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
-		omap4_ctrl_pad_writel(reg, control_mmc1);
-	}
-
-	for (c = controllers; c->mmc; c++) {
-		struct hsmmc_controller *hc = hsmmc + c->mmc - 1;
-		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
-
-		if (!c->mmc || c->mmc > nr_hsmmc) {
-			pr_debug("MMC%d: no such controller\n", c->mmc);
-			continue;
-		}
-		if (mmc) {
-			pr_debug("MMC%d: already configured\n", c->mmc);
-			continue;
+	if ((mmc_controller->slots[0].switch_pin > 0) && \
+		(mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
+		omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
+					OMAP_PIN_INPUT_PULLUP);
+	if ((mmc_controller->slots[0].gpio_wp > 0) && \
+		(mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
+		omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
+					OMAP_PIN_INPUT_PULLUP);
+	if (cpu_is_omap34xx()) {
+		if (controller_nr == 0) {
+			omap_mux_init_signal("sdmmc1_clk",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc1_cmd",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc1_dat0",
+				OMAP_PIN_INPUT_PULLUP);
+			if (mmc_controller->slots[0].caps &
+				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
+				omap_mux_init_signal("sdmmc1_dat1",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat2",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat3",
+					OMAP_PIN_INPUT_PULLUP);
+			}
+			if (mmc_controller->slots[0].caps &
+						MMC_CAP_8_BIT_DATA) {
+				omap_mux_init_signal("sdmmc1_dat4",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat5",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat6",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat7",
+					OMAP_PIN_INPUT_PULLUP);
+			}
 		}
-
-		mmc = kzalloc(sizeof(struct omap_mmc_platform_data),
-			      GFP_KERNEL);
-		if (!mmc) {
-			pr_err("Cannot allocate memory for mmc device!\n");
-			goto done;
+		if (controller_nr == 1) {
+			/* MMC2 */
+			omap_mux_init_signal("sdmmc2_clk",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc2_cmd",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc2_dat0",
+				OMAP_PIN_INPUT_PULLUP);
+
+			/*
+			 * For 8 wire configurations, Lines DAT4, 5, 6 and 7
+			 * need to be muxed in the board-*.c files
+			 */
+			if (mmc_controller->slots[0].caps &
+				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
+				omap_mux_init_signal("sdmmc2_dat1",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat2",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat3",
+					OMAP_PIN_INPUT_PULLUP);
+			}
+			if (mmc_controller->slots[0].caps &
+							MMC_CAP_8_BIT_DATA) {
+				omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7",
+					OMAP_PIN_INPUT_PULLUP);
+			}
 		}
 
-		if (c->name)
-			strncpy(hc->name, c->name, HSMMC_NAME_LEN);
-		else
-			snprintf(hc->name, ARRAY_SIZE(hc->name),
-				"mmc%islot%i", c->mmc, 1);
-		mmc->slots[0].name = hc->name;
-		mmc->nr_slots = 1;
-		mmc->slots[0].caps = c->caps;
-		mmc->slots[0].internal_clock = !c->ext_clock;
-		mmc->dma_mask = 0xffffffff;
-		if (cpu_is_omap44xx())
-			mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
-		else
-			mmc->reg_offset = 0;
+		/*
+		 * For MMC3 the pins need to be muxed in the board-*.c files
+		 */
+	}
+}
 
-		mmc->get_context_loss_count = hsmmc_get_context_loss;
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+					struct omap_mmc_platform_data *mmc)
+{
+	char *hc_name;
 
-		mmc->slots[0].switch_pin = c->gpio_cd;
-		mmc->slots[0].gpio_wp = c->gpio_wp;
+	hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL);
+	if (!hc_name) {
+		pr_err("Cannot allocate memory for controller slot name\n");
+		kfree(hc_name);
+		return -ENOMEM;
+	}
 
-		mmc->slots[0].remux = c->remux;
-		mmc->slots[0].init_card = c->init_card;
+	if (c->name)
+		strncpy(hc_name, c->name, HSMMC_NAME_LEN);
+	else
+		snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i",
+								c->mmc, 1);
+	mmc->slots[0].name = hc_name;
+	mmc->nr_slots = 1;
+	mmc->slots[0].caps = c->caps;
+	mmc->slots[0].internal_clock = !c->ext_clock;
+	mmc->dma_mask = 0xffffffff;
+	if (cpu_is_omap44xx())
+		mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
+	else
+		mmc->reg_offset = 0;
 
-		if (c->cover_only)
-			mmc->slots[0].cover = 1;
+	mmc->get_context_loss_count = hsmmc_get_context_loss;
 
-		if (c->nonremovable)
-			mmc->slots[0].nonremovable = 1;
+	mmc->slots[0].switch_pin = c->gpio_cd;
+	mmc->slots[0].gpio_wp = c->gpio_wp;
 
-		if (c->power_saving)
-			mmc->slots[0].power_saving = 1;
+	mmc->slots[0].remux = c->remux;
+	mmc->slots[0].init_card = c->init_card;
 
-		if (c->no_off)
-			mmc->slots[0].no_off = 1;
+	if (c->cover_only)
+		mmc->slots[0].cover = 1;
 
-		if (c->vcc_aux_disable_is_sleep)
-			mmc->slots[0].vcc_aux_disable_is_sleep = 1;
+	if (c->nonremovable)
+		mmc->slots[0].nonremovable = 1;
 
-		/* NOTE:  MMC slots should have a Vcc regulator set up.
-		 * This may be from a TWL4030-family chip, another
-		 * controllable regulator, or a fixed supply.
-		 *
-		 * temporary HACK: ocr_mask instead of fixed supply
-		 */
-		mmc->slots[0].ocr_mask = c->ocr_mask;
+	if (c->power_saving)
+		mmc->slots[0].power_saving = 1;
 
-		if (cpu_is_omap3517() || cpu_is_omap3505())
-			mmc->slots[0].set_power = nop_mmc_set_power;
-		else
-			mmc->slots[0].features |= HSMMC_HAS_PBIAS;
+	if (c->no_off)
+		mmc->slots[0].no_off = 1;
 
-		if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
-			mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+	if (c->vcc_aux_disable_is_sleep)
+		mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
-		switch (c->mmc) {
-		case 1:
-			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
-				/* on-chip level shifting via PBIAS0/PBIAS1 */
-				if (cpu_is_omap44xx()) {
-					mmc->slots[0].before_set_reg =
+	/*
+	 * NOTE:  MMC slots should have a Vcc regulator set up.
+	 * This may be from a TWL4030-family chip, another
+	 * controllable regulator, or a fixed supply.
+	 *
+	 * temporary HACK: ocr_mask instead of fixed supply
+	 */
+	mmc->slots[0].ocr_mask = c->ocr_mask;
+
+	if (cpu_is_omap3517() || cpu_is_omap3505())
+		mmc->slots[0].set_power = nop_mmc_set_power;
+	else
+		mmc->slots[0].features |= HSMMC_HAS_PBIAS;
+
+	if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
+		mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
+	switch (c->mmc) {
+	case 1:
+		if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
+			/* on-chip level shifting via PBIAS0/PBIAS1 */
+			if (cpu_is_omap44xx()) {
+				mmc->slots[0].before_set_reg =
 						omap4_hsmmc1_before_set_reg;
-					mmc->slots[0].after_set_reg =
+				mmc->slots[0].after_set_reg =
 						omap4_hsmmc1_after_set_reg;
-				} else {
-					mmc->slots[0].before_set_reg =
+			} else {
+				mmc->slots[0].before_set_reg =
 						omap_hsmmc1_before_set_reg;
-					mmc->slots[0].after_set_reg =
+				mmc->slots[0].after_set_reg =
 						omap_hsmmc1_after_set_reg;
-				}
 			}
+		}
 
-			/* Omap3630 HSMMC1 supports only 4-bit */
-			if (cpu_is_omap3630() &&
-					(c->caps & MMC_CAP_8_BIT_DATA)) {
-				c->caps &= ~MMC_CAP_8_BIT_DATA;
-				c->caps |= MMC_CAP_4_BIT_DATA;
-				mmc->slots[0].caps = c->caps;
-			}
-			break;
-		case 2:
-			if (c->ext_clock)
-				c->transceiver = 1;
-			if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
-				c->caps &= ~MMC_CAP_8_BIT_DATA;
-				c->caps |= MMC_CAP_4_BIT_DATA;
-			}
-			/* FALLTHROUGH */
-		case 3:
-			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
-				/* off-chip level shifting, or none */
-				mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
-				mmc->slots[0].after_set_reg = NULL;
-			}
-			break;
-		default:
-			pr_err("MMC%d configuration not supported!\n", c->mmc);
-			kfree(mmc);
-			continue;
+		/* OMAP3630 HSMMC1 supports only 4-bit */
+		if (cpu_is_omap3630() &&
+				(c->caps & MMC_CAP_8_BIT_DATA)) {
+			c->caps &= ~MMC_CAP_8_BIT_DATA;
+			c->caps |= MMC_CAP_4_BIT_DATA;
+			mmc->slots[0].caps = c->caps;
+		}
+		break;
+	case 2:
+		if (c->ext_clock)
+			c->transceiver = 1;
+		if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
+			c->caps &= ~MMC_CAP_8_BIT_DATA;
+			c->caps |= MMC_CAP_4_BIT_DATA;
 		}
-		hsmmc_data[c->mmc - 1] = mmc;
+		/* FALLTHROUGH */
+	case 3:
+		if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
+			/* off-chip level shifting, or none */
+			mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+			mmc->slots[0].after_set_reg = NULL;
+		}
+		break;
+	case 4:
+	case 5:
+		mmc->slots[0].before_set_reg = NULL;
+		mmc->slots[0].after_set_reg = NULL;
+		break;
+	default:
+		pr_err("MMC%d configuration not supported!\n", c->mmc);
+		kfree(hc_name);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static struct omap_device_pm_latency omap_hsmmc_latency[] = {
+	[0] = {
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func	 = omap_device_enable_hwmods,
+		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+	/*
+	 * XXX There should also be an entry here to power off/on the
+	 * MMC regulators/PBIAS cells, etc.
+	 */
+};
+
+#define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
+
+void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+{
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	struct omap_device_pm_latency *ohl;
+	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
+	struct omap_mmc_platform_data *mmc_data;
+	struct omap_mmc_dev_attr *mmc_dev_attr;
+	char *name;
+	int l;
+	int ohl_cnt = 0;
+
+	mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
+	if (!mmc_data) {
+		pr_err("Cannot allocate memory for mmc device!\n");
+		goto done;
 	}
 
-	omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
+	if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
+		pr_err("%s fails!\n", __func__);
+		goto done;
+	}
+	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
+
+	name = "omap_hsmmc";
+	ohl = omap_hsmmc_latency;
+	ohl_cnt = ARRAY_SIZE(omap_hsmmc_latency);
+
+	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+		     "mmc%d", ctrl_nr);
+	WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	     "String buffer overflow in MMC%d device setup\n", ctrl_nr);
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		kfree(mmc_data->slots[0].name);
+		goto done;
+	}
 
-	/* pass the device nodes back to board setup code */
-	for (c = controllers; c->mmc; c++) {
-		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
+	if (oh->dev_attr != NULL) {
+		mmc_dev_attr = oh->dev_attr;
+		mmc_data->controller_flags = mmc_dev_attr->flags;
+	}
 
-		if (!c->mmc || c->mmc > nr_hsmmc)
-			continue;
-		c->dev = mmc->dev;
+	od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
+		sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false);
+	if (IS_ERR(od)) {
+		WARN(1, "Cant build omap_device for %s:%s.\n", name, oh->name);
+		kfree(mmc_data->slots[0].name);
+		goto done;
 	}
+	/*
+	 * return device handle to board setup code
+	 * required to populate for regulator framework structure
+	 */
+	hsmmcinfo->dev = &od->pdev.dev;
 
 done:
-	for (i = 0; i < nr_hsmmc; i++)
-		kfree(hsmmc_data[i]);
+	kfree(mmc_data);
+}
+
+void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+{
+	u32 reg;
+
+	if (!cpu_is_omap44xx()) {
+		if (cpu_is_omap2430()) {
+			control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
+			control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
+		} else {
+			control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+			control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
+		}
+	} else {
+		control_pbias_offset =
+			OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
+		control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
+		reg = omap4_ctrl_pad_readl(control_mmc1);
+		reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
+			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
+		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
+			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
+		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
+			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
+		omap4_ctrl_pad_writel(reg, control_mmc1);
+	}
+
+	for (; controllers->mmc; controllers++)
+		omap_init_hsmmc(controllers, controllers->mmc);
+
 }
 
 #endif
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
new file mode 100644
index 0000000..06d4a80
--- /dev/null
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP hardware spinlock device initialization
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Simon Que <sque@ti.com>
+ *          Hari Kanigeri <h-kanigeri2@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+
+struct omap_device_pm_latency omap_spinlock_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
+int __init hwspinlocks_init(void)
+{
+	int retval = 0;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	const char *oh_name = "spinlock";
+	const char *dev_name = "omap_hwspinlock";
+
+	/*
+	 * Hwmod lookup will fail in case our platform doesn't support the
+	 * hardware spinlock module, so it is safe to run this initcall
+	 * on all omaps
+	 */
+	oh = omap_hwmod_lookup(oh_name);
+	if (oh == NULL)
+		return -EINVAL;
+
+	od = omap_device_build(dev_name, 0, oh, NULL, 0,
+				omap_spinlock_latency,
+				ARRAY_SIZE(omap_spinlock_latency), false);
+	if (IS_ERR(od)) {
+		pr_err("Can't build omap_device for %s:%s\n", dev_name,
+								oh_name);
+		retval = PTR_ERR(od);
+	}
+
+	return retval;
+}
+/* early board code might need to reserve specific hwspinlock instances */
+postcore_initcall(hwspinlocks_init);
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index 5f9086c..2537090 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -6,7 +6,7 @@
  * Copyright (C) 2005 Nokia Corporation
  * Written by Tony Lindgren <tony@atomide.com>
  *
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009-11 Texas Instruments
  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -84,6 +84,11 @@ EXPORT_SYMBOL(omap_type);
 #define OMAP_TAP_DIE_ID_2	0x0220
 #define OMAP_TAP_DIE_ID_3	0x0224
 
+#define OMAP_TAP_DIE_ID_44XX_0	0x0200
+#define OMAP_TAP_DIE_ID_44XX_1	0x0208
+#define OMAP_TAP_DIE_ID_44XX_2	0x020c
+#define OMAP_TAP_DIE_ID_44XX_3	0x0210
+
 #define read_tap_reg(reg)	__raw_readl(tap_base  + (reg))
 
 struct omap_id {
@@ -107,6 +112,14 @@ static u16 tap_prod_id;
 
 void omap_get_die_id(struct omap_die_id *odi)
 {
+	if (cpu_is_omap44xx()) {
+		odi->id_0 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_0);
+		odi->id_1 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_1);
+		odi->id_2 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_2);
+		odi->id_3 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_3);
+
+		return;
+	}
 	odi->id_0 = read_tap_reg(OMAP_TAP_DIE_ID_0);
 	odi->id_1 = read_tap_reg(OMAP_TAP_DIE_ID_1);
 	odi->id_2 = read_tap_reg(OMAP_TAP_DIE_ID_2);
@@ -191,12 +204,19 @@ static void __init omap3_check_features(void)
 	if (!cpu_is_omap3505() && !cpu_is_omap3517())
 		omap3_features |= OMAP3_HAS_IO_WAKEUP;
 
+	omap3_features |= OMAP3_HAS_SDRC;
+
 	/*
 	 * TODO: Get additional info (where applicable)
 	 *       e.g. Size of L2 cache.
 	 */
 }
 
+static void __init ti816x_check_features(void)
+{
+	omap3_features = OMAP3_HAS_NEON;
+}
+
 static void __init omap3_check_revision(void)
 {
 	u32 cpuid, idcode;
@@ -287,6 +307,20 @@ static void __init omap3_check_revision(void)
 			omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
 		}
 		break;
+	case 0xb81e:
+		omap_chip.oc = CHIP_IS_TI816X;
+
+		switch (rev) {
+		case 0:
+			omap_revision = TI8168_REV_ES1_0;
+			break;
+		case 1:
+			omap_revision = TI8168_REV_ES1_1;
+			break;
+		default:
+			omap_revision =  TI8168_REV_ES1_1;
+		}
+		break;
 	default:
 		/* Unknown default to latest silicon rev as default*/
 		omap_revision =  OMAP3630_REV_ES1_2;
@@ -307,7 +341,7 @@ static void __init omap4_check_revision(void)
 	 */
 	idcode = read_tap_reg(OMAP_TAP_IDCODE);
 	hawkeye = (idcode >> 12) & 0xffff;
-	rev = (idcode >> 28) & 0xff;
+	rev = (idcode >> 28) & 0xf;
 
 	/*
 	 * Few initial ES2.0 samples IDCODE is same as ES1.0
@@ -326,22 +360,31 @@ static void __init omap4_check_revision(void)
 			omap_chip.oc |= CHIP_IS_OMAP4430ES1;
 			break;
 		case 1:
+		default:
 			omap_revision = OMAP4430_REV_ES2_0;
 			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+		}
+		break;
+	case 0xb95c:
+		switch (rev) {
+		case 3:
+			omap_revision = OMAP4430_REV_ES2_1;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES2_1;
 			break;
+		case 4:
 		default:
-			omap_revision = OMAP4430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
-	}
-	break;
+			omap_revision = OMAP4430_REV_ES2_2;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
+		}
+		break;
 	default:
-		/* Unknown default to latest silicon rev as default*/
-		omap_revision = OMAP4430_REV_ES2_0;
-		omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+		/* Unknown default to latest silicon rev as default */
+		omap_revision = OMAP4430_REV_ES2_2;
+		omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 	}
 
-	pr_info("OMAP%04x ES%d.0\n",
-			omap_rev() >> 16, ((omap_rev() >> 12) & 0xf) + 1);
+	pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16,
+		((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf));
 }
 
 #define OMAP3_SHOW_FEATURE(feat)		\
@@ -372,6 +415,8 @@ static void __init omap3_cpuinfo(void)
 			/* Already set in omap3_check_revision() */
 			strcpy(cpu_name, "AM3505");
 		}
+	} else if (cpu_is_ti816x()) {
+		strcpy(cpu_name, "TI816X");
 	} else if (omap3_has_iva() && omap3_has_sgx()) {
 		/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
 		strcpy(cpu_name, "OMAP3430/3530");
@@ -386,7 +431,7 @@ static void __init omap3_cpuinfo(void)
 		strcpy(cpu_name, "OMAP3503");
 	}
 
-	if (cpu_is_omap3630()) {
+	if (cpu_is_omap3630() || cpu_is_ti816x()) {
 		switch (rev) {
 		case OMAP_REVBITS_00:
 			strcpy(cpu_rev, "1.0");
@@ -462,7 +507,13 @@ void __init omap2_check_revision(void)
 		omap24xx_check_revision();
 	} else if (cpu_is_omap34xx()) {
 		omap3_check_revision();
-		omap3_check_features();
+
+		/* TI816X doesn't have feature register */
+		if (!cpu_is_ti816x())
+			omap3_check_features();
+		else
+			ti816x_check_features();
+
 		omap3_cpuinfo();
 		return;
 	} else if (cpu_is_omap44xx()) {
diff --git a/arch/arm/mach-omap2/include/mach/debug-macro.S b/arch/arm/mach-omap2/include/mach/debug-macro.S
index 6a4d413..48adfe9 100644
--- a/arch/arm/mach-omap2/include/mach/debug-macro.S
+++ b/arch/arm/mach-omap2/include/mach/debug-macro.S
@@ -19,6 +19,9 @@
 
 #define UART_OFFSET(addr)	((addr) & 0x00ffffff)
 
+#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 omap_uart_phys:	.word	0
 omap_uart_virt:	.word	0
@@ -36,7 +39,7 @@ omap_uart_lsr:	.word	0
 		/* Use omap_uart_phys/virt if already configured */
 10:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rp, =omap_uart_phys	@ MMU enabled
 		add	\rv, \rp, #4		@ omap_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -49,7 +52,7 @@ omap_uart_lsr:	.word	0
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =__phys_to_virt(OMAP_UART_INFO)	@ MMU enabled
+		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
 		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
@@ -69,6 +72,12 @@ omap_uart_lsr:	.word	0
 		beq	34f			@ configure OMAP3UART4
 		cmp	\rp, #OMAP4UART4	@ only on 44xx
 		beq	44f			@ configure OMAP4UART4
+		cmp	\rp, #TI816XUART1	@ ti816x UART offsets different
+		beq	81f			@ configure UART1
+		cmp	\rp, #TI816XUART2	@ ti816x UART offsets different
+		beq	82f			@ configure UART2
+		cmp	\rp, #TI816XUART3	@ ti816x UART offsets different
+		beq	83f			@ configure UART3
 		cmp	\rp, #ZOOM_UART		@ only on zoom2/3
 		beq	95f			@ configure ZOOM_UART
 
@@ -91,10 +100,16 @@ omap_uart_lsr:	.word	0
 		b	98f
 44:		mov	\rp, #UART_OFFSET(OMAP4_UART4_BASE)
 		b	98f
+81:		mov	\rp, #UART_OFFSET(TI816X_UART1_BASE)
+		b	98f
+82:		mov	\rp, #UART_OFFSET(TI816X_UART2_BASE)
+		b	98f
+83:		mov	\rp, #UART_OFFSET(TI816X_UART3_BASE)
+		b	98f
 95:		ldr	\rp, =ZOOM_UART_BASE
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		ldr	\rp, =ZOOM_UART_VIRT
@@ -109,7 +124,7 @@ omap_uart_lsr:	.word	0
 98:		add	\rp, \rp, #0x48000000	@ phys base
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		sub	\rp, \rp, #0x48000000	@ phys base
@@ -131,7 +146,7 @@ omap_uart_lsr:	.word	0
 		.macro	busyuart,rd,rx
 1001:		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1			@ MMU enabled?
-		ldreq	\rd, =__virt_to_phys(omap_uart_lsr)	@ MMU not enabled
+		ldreq	\rd, =omap_uart_v2p(omap_uart_lsr)	@ MMU disabled
 		ldrne	\rd, =omap_uart_lsr	@ MMU enabled
 		ldr	\rd, [\rd, #0]
 		ldrb	\rd, [\rx, \rd]
diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S
index 81985a6..a48690b 100644
--- a/arch/arm/mach-omap2/include/mach/entry-macro.S
+++ b/arch/arm/mach-omap2/include/mach/entry-macro.S
@@ -61,6 +61,14 @@
 		bne	9998f
 		ldr	\irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
 		cmp	\irqnr, #0x0
+		bne	9998f
+
+		/*
+		 * ti816x has additional IRQ pending register. Checking this
+		 * register on omap2 & omap3 has no effect (read as 0).
+		 */
+		ldr	\irqnr, [\base, #0xf8] /* IRQ pending reg 4 */
+		cmp	\irqnr, #0x0
 9998:
 		ldrne	\irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
 		and	\irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
@@ -133,6 +141,11 @@
 		bne	9999f
 		ldr	\irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
 		cmp	\irqnr, #0x0
+#ifdef CONFIG_SOC_OMAPTI816X
+		bne	9999f
+		ldr	\irqnr, [\base, #0xf8] /* IRQ pending reg 4 */
+		cmp	\irqnr, #0x0
+#endif
 9999:
 		ldrne	\irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
 		and	\irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
diff --git a/arch/arm/mach-omap2/include/mach/omap4-common.h b/arch/arm/mach-omap2/include/mach/omap4-common.h
index 5b0270b..de441c0 100644
--- a/arch/arm/mach-omap2/include/mach/omap4-common.h
+++ b/arch/arm/mach-omap2/include/mach/omap4-common.h
@@ -17,8 +17,12 @@
  * wfi used in low power code. Directly opcode is used instead
  * of instruction to avoid mulit-omap build break
  */
+#ifdef CONFIG_THUMB2_KERNEL
+#define do_wfi() __asm__ __volatile__ ("wfi" : : : "memory")
+#else
 #define do_wfi()			\
 		__asm__ __volatile__ (".word	0xe320f003" : : : "memory")
+#endif
 
 #ifdef CONFIG_CACHE_L2X0
 extern void __iomem *l2cache_base;
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index c203204..441e79d 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -30,7 +30,6 @@
 
 #include <plat/sram.h>
 #include <plat/sdrc.h>
-#include <plat/gpmc.h>
 #include <plat/serial.h>
 
 #include "clock2xxx.h"
@@ -66,7 +65,7 @@ static struct map_desc omap24xx_io_desc[] __initdata = {
 	},
 };
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 static struct map_desc omap242x_io_desc[] __initdata = {
 	{
 		.virtual	= DSP_MEM_2420_VIRT,
@@ -90,7 +89,7 @@ static struct map_desc omap242x_io_desc[] __initdata = {
 
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 static struct map_desc omap243x_io_desc[] __initdata = {
 	{
 		.virtual	= L4_WK_243X_VIRT,
@@ -175,6 +174,18 @@ static struct map_desc omap34xx_io_desc[] __initdata = {
 #endif
 };
 #endif
+
+#ifdef CONFIG_SOC_OMAPTI816X
+static struct map_desc omapti816x_io_desc[] __initdata = {
+	{
+		.virtual	= L4_34XX_VIRT,
+		.pfn		= __phys_to_pfn(L4_34XX_PHYS),
+		.length		= L4_34XX_SIZE,
+		.type		= MT_DEVICE
+	},
+};
+#endif
+
 #ifdef	CONFIG_ARCH_OMAP4
 static struct map_desc omap44xx_io_desc[] __initdata = {
 	{
@@ -241,7 +252,7 @@ static void __init _omap2_map_common_io(void)
 	omap_sram_init();
 }
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
@@ -250,7 +261,7 @@ void __init omap242x_map_common_io(void)
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 void __init omap243x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
@@ -267,6 +278,14 @@ void __init omap34xx_map_common_io(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAPTI816X
+void __init omapti816x_map_common_io(void)
+{
+	iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
+	_omap2_map_common_io();
+}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP4
 void __init omap44xx_map_common_io(void)
 {
@@ -337,15 +356,15 @@ void __init omap2_init_common_infrastructure(void)
 
 	if (cpu_is_omap242x()) {
 		omap2xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap2xxx_clockdomains_init();
 		omap2420_hwmod_init();
 	} else if (cpu_is_omap243x()) {
 		omap2xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap2xxx_clockdomains_init();
 		omap2430_hwmod_init();
 	} else if (cpu_is_omap34xx()) {
 		omap3xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap3xxx_clockdomains_init();
 		omap3xxx_hwmod_init();
 	} else if (cpu_is_omap44xx()) {
 		omap44xx_powerdomains_init();
@@ -398,15 +417,10 @@ void __init omap2_init_common_infrastructure(void)
 void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1)
 {
-	omap_serial_early_init();
-
-	omap_hwmod_late_init();
-
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+	if (cpu_is_omap24xx() || omap3_has_sdrc()) {
 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
 		_omap2_init_reprogram_sdrc();
 	}
-	gpmc_init();
 
 	omap_irq_base_init();
 }
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 14ee686..adb083e 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -145,35 +145,32 @@ static void omap2_iommu_set_twl(struct iommu *obj, bool on)
 
 static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
 {
-	int i;
 	u32 stat, da;
-	const char *err_msg[] =	{
-		"tlb miss",
-		"translation fault",
-		"emulation miss",
-		"table walk fault",
-		"multi hit fault",
-	};
+	u32 errs = 0;
 
 	stat = iommu_read_reg(obj, MMU_IRQSTATUS);
 	stat &= MMU_IRQ_MASK;
-	if (!stat)
+	if (!stat) {
+		*ra = 0;
 		return 0;
+	}
 
 	da = iommu_read_reg(obj, MMU_FAULT_AD);
 	*ra = da;
 
-	dev_err(obj->dev, "%s:\tda:%08x ", __func__, da);
-
-	for (i = 0; i < ARRAY_SIZE(err_msg); i++) {
-		if (stat & (1 << i))
-			printk("%s ", err_msg[i]);
-	}
-	printk("\n");
-
+	if (stat & MMU_IRQ_TLBMISS)
+		errs |= OMAP_IOMMU_ERR_TLB_MISS;
+	if (stat & MMU_IRQ_TRANSLATIONFAULT)
+		errs |= OMAP_IOMMU_ERR_TRANS_FAULT;
+	if (stat & MMU_IRQ_EMUMISS)
+		errs |= OMAP_IOMMU_ERR_EMU_MISS;
+	if (stat & MMU_IRQ_TABLEWALKFAULT)
+		errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
+	if (stat & MMU_IRQ_MULTIHITFAULT)
+		errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
 	iommu_write_reg(obj, stat, MMU_IRQSTATUS);
 
-	return stat;
+	return errs;
 }
 
 static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c
index 23049c4..bc524b9 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/arch/arm/mach-omap2/irq.c
@@ -61,8 +61,6 @@ struct omap3_intc_regs {
 	u32 mir[INTCPS_NR_MIR_REGS];
 };
 
-static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
-
 /* INTC bank register get/set */
 
 static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
@@ -110,7 +108,7 @@ static void omap_mask_irq(struct irq_data *d)
 	unsigned int irq = d->irq;
 	int offset = irq & (~(IRQ_BITS_PER_REG - 1));
 
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
 		int spurious = 0;
 
 		/*
@@ -205,6 +203,9 @@ void __init omap_init_irq(void)
 
 		BUG_ON(!base);
 
+		if (cpu_is_ti816x())
+			bank->nr_irqs = 128;
+
 		/* Static mapping, never released */
 		bank->base_reg = ioremap(base, SZ_4K);
 		if (!bank->base_reg) {
@@ -229,6 +230,8 @@ void __init omap_init_irq(void)
 }
 
 #ifdef CONFIG_ARCH_OMAP3
+static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
+
 void omap_intc_save_context(void)
 {
 	int ind = 0, i = 0;
diff --git a/arch/arm/mach-omap2/mailbox.c b/arch/arm/mach-omap2/mailbox.c
index 24b8850..86d564a 100644
--- a/arch/arm/mach-omap2/mailbox.c
+++ b/arch/arm/mach-omap2/mailbox.c
@@ -14,12 +14,11 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/pm_runtime.h>
 #include <plat/mailbox.h>
 #include <mach/irqs.h>
 
 #define MAILBOX_REVISION		0x000
-#define MAILBOX_SYSCONFIG		0x010
-#define MAILBOX_SYSSTATUS		0x014
 #define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
 #define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
 #define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
@@ -33,17 +32,6 @@
 #define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
 #define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
 
-/* SYSCONFIG: register bit definition */
-#define AUTOIDLE	(1 << 0)
-#define SOFTRESET	(1 << 1)
-#define SMARTIDLE	(2 << 3)
-#define OMAP4_SOFTRESET	(1 << 0)
-#define OMAP4_NOIDLE	(1 << 2)
-#define OMAP4_SMARTIDLE	(2 << 2)
-
-/* SYSSTATUS: register bit definition */
-#define RESETDONE	(1 << 0)
-
 #define MBOX_REG_SIZE			0x120
 
 #define OMAP4_MBOX_REG_SIZE		0x130
@@ -70,8 +58,6 @@ struct omap_mbox2_priv {
 	unsigned long irqdisable;
 };
 
-static struct clk *mbox_ick_handle;
-
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
 				  omap_mbox_type_t irq);
 
@@ -89,53 +75,13 @@ static inline void mbox_write_reg(u32 val, size_t ofs)
 static int omap2_mbox_startup(struct omap_mbox *mbox)
 {
 	u32 l;
-	unsigned long timeout;
 
-	mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
-	if (IS_ERR(mbox_ick_handle)) {
-		printk(KERN_ERR "Could not get mailboxes_ick: %ld\n",
-			PTR_ERR(mbox_ick_handle));
-		return PTR_ERR(mbox_ick_handle);
-	}
-	clk_enable(mbox_ick_handle);
-
-	if (cpu_is_omap44xx()) {
-		mbox_write_reg(OMAP4_SOFTRESET, MAILBOX_SYSCONFIG);
-		timeout = jiffies + msecs_to_jiffies(20);
-		do {
-			l = mbox_read_reg(MAILBOX_SYSCONFIG);
-			if (!(l & OMAP4_SOFTRESET))
-				break;
-		} while (!time_after(jiffies, timeout));
-
-		if (l & OMAP4_SOFTRESET) {
-			pr_err("Can't take mailbox out of reset\n");
-			return -ENODEV;
-		}
-	} else {
-		mbox_write_reg(SOFTRESET, MAILBOX_SYSCONFIG);
-		timeout = jiffies + msecs_to_jiffies(20);
-		do {
-			l = mbox_read_reg(MAILBOX_SYSSTATUS);
-			if (l & RESETDONE)
-				break;
-		} while (!time_after(jiffies, timeout));
-
-		if (!(l & RESETDONE)) {
-			pr_err("Can't take mailbox out of reset\n");
-			return -ENODEV;
-		}
-	}
+	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));
 
-	if (cpu_is_omap44xx())
-		l = OMAP4_SMARTIDLE;
-	else
-		l = SMARTIDLE | AUTOIDLE;
-	mbox_write_reg(l, MAILBOX_SYSCONFIG);
-
 	omap2_mbox_enable_irq(mbox, IRQ_RX);
 
 	return 0;
@@ -143,9 +89,8 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
 
 static void omap2_mbox_shutdown(struct omap_mbox *mbox)
 {
-	clk_disable(mbox_ick_handle);
-	clk_put(mbox_ick_handle);
-	mbox_ick_handle = NULL;
+	pm_runtime_put_sync(mbox->dev->parent);
+	pm_runtime_disable(mbox->dev->parent);
 }
 
 /* Mailbox FIFO handle functions */
@@ -312,7 +257,7 @@ struct omap_mbox mbox_dsp_info = {
 struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 /* IVA */
 static struct omap_mbox2_priv omap2_mbox_iva_priv = {
 	.tx_fifo = {
@@ -400,14 +345,14 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
 	else if (cpu_is_omap34xx()) {
 		list = omap3_mboxes;
 
-		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+		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_byname(pdev, "dsp");
+		list[0]->irq = platform_get_irq(pdev, 0);
 	} else if (cpu_is_omap2420()) {
 		list = omap2_mboxes;
 
@@ -419,8 +364,7 @@ static int __devinit omap2_mbox_probe(struct platform_device *pdev)
 	else if (cpu_is_omap44xx()) {
 		list = omap4_mboxes;
 
-		list[0]->irq = list[1]->irq =
-			platform_get_irq_byname(pdev, "mbox");
+		list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0);
 	}
 #endif
 	else {
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index f9c9df5..565b906 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -22,10 +22,11 @@
 #include <plat/dma.h>
 #include <plat/cpu.h>
 #include <plat/mcbsp.h>
+#include <plat/omap_device.h>
+#include <linux/pm_runtime.h>
 
 #include "control.h"
 
-
 /* McBSP internal signal muxing functions */
 
 void omap2_mcbsp1_mux_clkr_src(u8 mux)
@@ -83,7 +84,7 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 		return -EINVAL;
 	}
 
-	clk_disable(mcbsp->fclk);
+	pm_runtime_put_sync(mcbsp->dev);
 
 	r = clk_set_parent(mcbsp->fclk, fck_src);
 	if (IS_ERR_VALUE(r)) {
@@ -93,7 +94,7 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 		return -EINVAL;
 	}
 
-	clk_enable(mcbsp->fclk);
+	pm_runtime_get_sync(mcbsp->dev);
 
 	clk_put(fck_src);
 
@@ -101,196 +102,70 @@ int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
 }
 EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
-
-/* Platform data */
-
-#ifdef CONFIG_ARCH_OMAP2420
-static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
+struct omap_device_pm_latency omap2_mcbsp_latency[] = {
 	{
-		.phys_base	= OMAP24XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
-		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP24XX_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
-		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
 };
-#define OMAP2420_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2420_mcbsp_pdata)
-#define OMAP2420_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
-#else
-#define omap2420_mcbsp_pdata		NULL
-#define OMAP2420_MCBSP_PDATA_SZ		0
-#define OMAP2420_MCBSP_REG_NUM		0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP2430
-static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
-	{
-		.phys_base	= OMAP24XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
-		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP24XX_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
-		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP2430_MCBSP3_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
-		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP2430_MCBSP4_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
-		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP2430_MCBSP5_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
-		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
-	},
-};
-#define OMAP2430_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2430_mcbsp_pdata)
-#define OMAP2430_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
-#else
-#define omap2430_mcbsp_pdata		NULL
-#define OMAP2430_MCBSP_PDATA_SZ		0
-#define OMAP2430_MCBSP_REG_NUM		0
-#endif
+static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
+{
+	int id, count = 1;
+	char *name = "omap-mcbsp";
+	struct omap_hwmod *oh_device[2];
+	struct omap_mcbsp_platform_data *pdata = NULL;
+	struct omap_device *od;
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
-	{
-		.phys_base	= OMAP34XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
-		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP2_BASE,
-		.phys_base_st	= OMAP34XX_MCBSP2_ST_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
-		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-		.buffer_size	= 0x500, /* The FIFO has 1024 + 256 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP3_BASE,
-		.phys_base_st	= OMAP34XX_MCBSP3_ST_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
-		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP4_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
-		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP5_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
-		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-};
-#define OMAP34XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap34xx_mcbsp_pdata)
-#define OMAP34XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
-#else
-#define omap34xx_mcbsp_pdata		NULL
-#define OMAP34XX_MCBSP_PDATA_SZ		0
-#define OMAP34XX_MCBSP_REG_NUM		0
-#endif
+	sscanf(oh->name, "mcbsp%d", &id);
 
-static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
-	{
-		.phys_base      = OMAP44XX_MCBSP1_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP1_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP1_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP1,
-	},
-	{
-		.phys_base      = OMAP44XX_MCBSP2_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP2_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP2_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP2,
-	},
-	{
-		.phys_base      = OMAP44XX_MCBSP3_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP3_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP3_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP3,
-	},
-	{
-		.phys_base      = OMAP44XX_MCBSP4_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP4_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP4_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP4,
-	},
-};
-#define OMAP44XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap44xx_mcbsp_pdata)
-#define OMAP44XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
+	pdata = kzalloc(sizeof(struct omap_mcbsp_platform_data), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for mcbsp\n", __func__);
+		return -ENOMEM;
+	}
+
+	pdata->mcbsp_config_type = oh->class->rev;
+
+	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
+		if (id == 2)
+			/* The FIFO has 1024 + 256 locations */
+			pdata->buffer_size = 0x500;
+		else
+			/* The FIFO has 128 locations */
+			pdata->buffer_size = 0x80;
+	}
+
+	oh_device[0] = oh;
+
+	if (oh->dev_attr) {
+		oh_device[1] = omap_hwmod_lookup((
+		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
+		count++;
+	}
+	od = omap_device_build_ss(name, id, oh_device, count, pdata,
+				sizeof(*pdata), omap2_mcbsp_latency,
+				ARRAY_SIZE(omap2_mcbsp_latency), false);
+	kfree(pdata);
+	if (IS_ERR(od))  {
+		pr_err("%s: Cant build omap_device for %s:%s.\n", __func__,
+					name, oh->name);
+		return PTR_ERR(od);
+	}
+	omap_mcbsp_count++;
+	return 0;
+}
 
 static int __init omap2_mcbsp_init(void)
 {
-	if (cpu_is_omap2420()) {
-		omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP2420_MCBSP_REG_NUM * sizeof(u16);
-	} else if (cpu_is_omap2430()) {
-		omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP2430_MCBSP_REG_NUM * sizeof(u32);
-	} else if (cpu_is_omap34xx()) {
-		omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP34XX_MCBSP_REG_NUM * sizeof(u32);
-	} else if (cpu_is_omap44xx()) {
-		omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP44XX_MCBSP_REG_NUM * sizeof(u32);
-	}
+	omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
 
 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
 								GFP_KERNEL);
 	if (!mcbsp_ptr)
 		return -ENOMEM;
 
-	if (cpu_is_omap2420())
-		omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
-						OMAP2420_MCBSP_PDATA_SZ);
-	if (cpu_is_omap2430())
-		omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
-						OMAP2430_MCBSP_PDATA_SZ);
-	if (cpu_is_omap34xx())
-		omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
-						OMAP34XX_MCBSP_PDATA_SZ);
-	if (cpu_is_omap44xx())
-		omap_mcbsp_register_board_cfg(omap44xx_mcbsp_pdata,
-						OMAP44XX_MCBSP_PDATA_SZ);
-
 	return omap_mcbsp_init();
 }
 arch_initcall(omap2_mcbsp_init);
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 6c84659..bb043cb 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -258,7 +258,7 @@ struct omap_hwmod_mux_info * __init
 omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
 {
 	struct omap_hwmod_mux_info *hmux;
-	int i;
+	int i, nr_pads_dynamic = 0;
 
 	if (!bpads || nr_pads < 1)
 		return NULL;
@@ -302,9 +302,40 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
 		pad->enable = bpad->enable;
 		pad->idle = bpad->idle;
 		pad->off = bpad->off;
+
+		if (pad->flags & OMAP_DEVICE_PAD_REMUX)
+			nr_pads_dynamic++;
+
 		pr_debug("%s: Initialized %s\n", __func__, pad->name);
 	}
 
+	if (!nr_pads_dynamic)
+		return hmux;
+
+	/*
+	 * Add pads that need dynamic muxing into a separate list
+	 */
+
+	hmux->nr_pads_dynamic = nr_pads_dynamic;
+	hmux->pads_dynamic = kzalloc(sizeof(struct omap_device_pad *) *
+					nr_pads_dynamic, GFP_KERNEL);
+	if (!hmux->pads_dynamic) {
+		pr_err("%s: Could not allocate dynamic pads\n", __func__);
+		return hmux;
+	}
+
+	nr_pads_dynamic = 0;
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+
+		if (pad->flags & OMAP_DEVICE_PAD_REMUX) {
+			pr_debug("%s: pad %s tagged dynamic\n",
+					__func__, pad->name);
+			hmux->pads_dynamic[nr_pads_dynamic] = pad;
+			nr_pads_dynamic++;
+		}
+	}
+
 	return hmux;
 
 err3:
@@ -322,6 +353,36 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 {
 	int i;
 
+	/* Runtime idling of dynamic pads */
+	if (state == _HWMOD_STATE_IDLE && hmux->enabled) {
+		for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+			struct omap_device_pad *pad = hmux->pads_dynamic[i];
+			int val = -EINVAL;
+
+			val = pad->idle;
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+		}
+
+		return;
+	}
+
+	/* Runtime enabling of dynamic pads */
+	if ((state == _HWMOD_STATE_ENABLED) && hmux->pads_dynamic
+					&& hmux->enabled) {
+		for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+			struct omap_device_pad *pad = hmux->pads_dynamic[i];
+			int val = -EINVAL;
+
+			val = pad->enable;
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+		}
+
+		return;
+	}
+
+	/* Enabling or disabling of all pads */
 	for (i = 0; i < hmux->nr_pads; i++) {
 		struct omap_device_pad *pad = &hmux->pads[i];
 		int flags, val = -EINVAL;
@@ -330,31 +391,22 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 
 		switch (state) {
 		case _HWMOD_STATE_ENABLED:
-			if (flags & OMAP_DEVICE_PAD_ENABLED)
-				break;
-			flags |= OMAP_DEVICE_PAD_ENABLED;
 			val = pad->enable;
 			pr_debug("%s: Enabling %s %x\n", __func__,
 					pad->name, val);
 			break;
-		case _HWMOD_STATE_IDLE:
-			if (!(flags & OMAP_DEVICE_PAD_REMUX))
-				break;
-			flags &= ~OMAP_DEVICE_PAD_ENABLED;
-			val = pad->idle;
-			pr_debug("%s: Idling %s %x\n", __func__,
-					pad->name, val);
-			break;
 		case _HWMOD_STATE_DISABLED:
-		default:
 			/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
 			if (flags & OMAP_DEVICE_PAD_REMUX)
 				val = pad->off;
 			else
 				val = OMAP_MUX_MODE7;
-			flags &= ~OMAP_DEVICE_PAD_ENABLED;
 			pr_debug("%s: Disabling %s %x\n", __func__,
 					pad->name, val);
+			break;
+		default:
+			/* Nothing to be done */
+			break;
 		};
 
 		if (val >= 0) {
@@ -363,6 +415,11 @@ void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 			pad->flags = flags;
 		}
 	}
+
+	if (state == _HWMOD_STATE_ENABLED)
+		hmux->enabled = true;
+	else
+		hmux->enabled = false;
 }
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index a4ab17a..137f321 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -159,7 +159,6 @@ struct omap_board_mux {
 	u16	value;
 };
 
-#define OMAP_DEVICE_PAD_ENABLED		BIT(7)	/* Not needed for board-*.c */
 #define OMAP_DEVICE_PAD_REMUX		BIT(1)	/* Dynamically remux a pad,
 						   needs enable, idle and off
 						   values */
@@ -187,6 +186,12 @@ struct omap_device_pad {
 
 struct omap_hwmod_mux_info;
 
+#define OMAP_MUX_STATIC(signal, mode)					\
+{									\
+	.name	= (signal),						\
+	.enable	= (mode),						\
+}
+
 #if defined(CONFIG_OMAP_MUX)
 
 /**
diff --git a/arch/arm/mach-omap2/mux44xx.c b/arch/arm/mach-omap2/mux44xx.c
index c322e7b..9a66445 100644
--- a/arch/arm/mach-omap2/mux44xx.c
+++ b/arch/arm/mach-omap2/mux44xx.c
@@ -755,25 +755,9 @@ static struct omap_ball __initdata omap4_core_cbl_ball[] = {
 #endif
 
 /*
- * Superset of all mux modes for omap4 ES2.0
+ * Signals different on ES2.0 compared to superset
  */
-static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
-	_OMAP4_MUXENTRY(GPMC_AD0, 0, "gpmc_ad0", "sdmmc2_dat0", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD1, 0, "gpmc_ad1", "sdmmc2_dat1", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD2, 0, "gpmc_ad2", "sdmmc2_dat2", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD3, 0, "gpmc_ad3", "sdmmc2_dat3", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD4, 0, "gpmc_ad4", "sdmmc2_dat4",
-			"sdmmc2_dir_dat0", NULL, NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD5, 0, "gpmc_ad5", "sdmmc2_dat5",
-			"sdmmc2_dir_dat1", NULL, NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD6, 0, "gpmc_ad6", "sdmmc2_dat6",
-			"sdmmc2_dir_cmd", NULL, NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD7, 0, "gpmc_ad7", "sdmmc2_dat7",
-			"sdmmc2_clk_fdbk", NULL, NULL, NULL, NULL, NULL),
+static struct omap_mux __initdata omap4_es2_core_subset[] = {
 	_OMAP4_MUXENTRY(GPMC_AD8, 32, "gpmc_ad8", "kpd_row0", "c2c_data15",
 			"gpio_32", NULL, "sdmmc1_dat0", NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_AD9, 33, "gpmc_ad9", "kpd_row1", "c2c_data14",
@@ -792,52 +776,15 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 			"gpio_39", NULL, "sdmmc1_dat7", NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_A16, 40, "gpmc_a16", "kpd_row4", "c2c_datain0",
 			"gpio_40", "venc_656_data0", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A17, 41, "gpmc_a17", "kpd_row5", "c2c_datain1",
-			"gpio_41", "venc_656_data1", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A18, 42, "gpmc_a18", "kpd_row6", "c2c_datain2",
-			"gpio_42", "venc_656_data2", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A19, 43, "gpmc_a19", "kpd_row7", "c2c_datain3",
-			"gpio_43", "venc_656_data3", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A20, 44, "gpmc_a20", "kpd_col4", "c2c_datain4",
-			"gpio_44", "venc_656_data4", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A21, 45, "gpmc_a21", "kpd_col5", "c2c_datain5",
-			"gpio_45", "venc_656_data5", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A22, 46, "gpmc_a22", "kpd_col6", "c2c_datain6",
-			"gpio_46", "venc_656_data6", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A23, 47, "gpmc_a23", "kpd_col7", "c2c_datain7",
-			"gpio_47", "venc_656_data7", NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(GPMC_A24, 48, "gpmc_a24", "kpd_col8", "c2c_clkout0",
 			"gpio_48", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A25, 49, "gpmc_a25", NULL, "c2c_clkout1",
-			"gpio_49", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_NCS0, 50, "gpmc_ncs0", NULL, NULL, "gpio_50",
-			"sys_ndmareq0", NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NCS1, 51, "gpmc_ncs1", NULL, "c2c_dataout6",
-			"gpio_51", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(GPMC_NCS2, 52, "gpmc_ncs2", "kpd_row8",
 			"c2c_dataout7", "gpio_52", NULL, NULL, NULL,
 			"safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_NCS3, 53, "gpmc_ncs3", "gpmc_dir",
-			"c2c_dataout4", "gpio_53", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_NWP, 54, "gpmc_nwp", "dsi1_te0", NULL, "gpio_54",
-			"sys_ndmareq1", NULL, NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_CLK, 55, "gpmc_clk", NULL, NULL, "gpio_55",
 			"sys_ndmareq2", "sdmmc1_cmd", NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_NADV_ALE, 56, "gpmc_nadv_ale", "dsi1_te1", NULL,
 			"gpio_56", "sys_ndmareq3", "sdmmc1_clk", NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NOE, 0, "gpmc_noe", "sdmmc2_clk", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NWE, 0, "gpmc_nwe", "sdmmc2_cmd", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NBE0_CLE, 59, "gpmc_nbe0_cle", "dsi2_te0", NULL,
-			"gpio_59", NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NBE1, 60, "gpmc_nbe1", NULL, "c2c_dataout5",
-			"gpio_60", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_WAIT0, 61, "gpmc_wait0", "dsi2_te1", NULL,
-			"gpio_61", NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_WAIT1, 62, "gpmc_wait1", NULL, "c2c_dataout2",
-			"gpio_62", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(GPMC_WAIT2, 100, "gpmc_wait2", "usbc1_icusb_txen",
 			"c2c_dataout3", "gpio_100", "sys_ndmareq0", NULL,
 			NULL, "safe_mode"),
@@ -851,62 +798,6 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 	_OMAP4_MUXENTRY(GPMC_NCS7, 104, "gpmc_ncs7", "dsi2_te1",
 			"c2c_dataout1", "gpio_104", NULL, NULL, NULL,
 			"safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_HPD, 63, "hdmi_hpd", NULL, NULL, "gpio_63", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_CEC, 64, "hdmi_cec", NULL, NULL, "gpio_64", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_DDC_SCL, 65, "hdmi_ddc_scl", NULL, NULL,
-			"gpio_65", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_DDC_SDA, 66, "hdmi_ddc_sda", NULL, NULL,
-			"gpio_66", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX0, 0, "csi21_dx0", NULL, NULL, "gpi_67", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY0, 0, "csi21_dy0", NULL, NULL, "gpi_68", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX1, 0, "csi21_dx1", NULL, NULL, "gpi_69", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY1, 0, "csi21_dy1", NULL, NULL, "gpi_70", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX2, 0, "csi21_dx2", NULL, NULL, "gpi_71", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY2, 0, "csi21_dy2", NULL, NULL, "gpi_72", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX3, 0, "csi21_dx3", NULL, NULL, "gpi_73", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY3, 0, "csi21_dy3", NULL, NULL, "gpi_74", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX4, 0, "csi21_dx4", NULL, NULL, "gpi_75", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY4, 0, "csi21_dy4", NULL, NULL, "gpi_76", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DX0, 0, "csi22_dx0", NULL, NULL, "gpi_77", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DY0, 0, "csi22_dy0", NULL, NULL, "gpi_78", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DX1, 0, "csi22_dx1", NULL, NULL, "gpi_79", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DY1, 0, "csi22_dy1", NULL, NULL, "gpi_80", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CAM_SHUTTER, 81, "cam_shutter", NULL, NULL, "gpio_81",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CAM_STROBE, 82, "cam_strobe", NULL, NULL, "gpio_82",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CAM_GLOBALRESET, 83, "cam_globalreset", NULL, NULL,
-			"gpio_83", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_CLK, 84, "usbb1_ulpitll_clk",
-			"hsi1_cawake", NULL, "gpio_84", "usbb1_ulpiphy_clk",
-			NULL, "hw_dbg20", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_STP, 85, "usbb1_ulpitll_stp",
-			"hsi1_cadata", "mcbsp4_clkr", "gpio_85",
-			"usbb1_ulpiphy_stp", "usbb1_mm_rxdp", "hw_dbg21",
-			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DIR, 86, "usbb1_ulpitll_dir",
-			"hsi1_caflag", "mcbsp4_fsr", "gpio_86",
-			"usbb1_ulpiphy_dir", NULL, "hw_dbg22", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_NXT, 87, "usbb1_ulpitll_nxt",
-			"hsi1_acready", "mcbsp4_fsx", "gpio_87",
-			"usbb1_ulpiphy_nxt", "usbb1_mm_rxdm", "hw_dbg23",
-			"safe_mode"),
 	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT0, 88, "usbb1_ulpitll_dat0",
 			"hsi1_acwake", "mcbsp4_clkx", "gpio_88",
 			"usbb1_ulpiphy_dat0", "usbb1_mm_txen", "hw_dbg24",
@@ -922,84 +813,6 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT3, 91, "usbb1_ulpitll_dat3",
 			"hsi1_caready", NULL, "gpio_91", "usbb1_ulpiphy_dat3",
 			"usbb1_mm_rxrcv", "hw_dbg27", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT4, 92, "usbb1_ulpitll_dat4",
-			"dmtimer8_pwm_evt", "abe_mcbsp3_dr", "gpio_92",
-			"usbb1_ulpiphy_dat4", NULL, "hw_dbg28", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT5, 93, "usbb1_ulpitll_dat5",
-			"dmtimer9_pwm_evt", "abe_mcbsp3_dx", "gpio_93",
-			"usbb1_ulpiphy_dat5", NULL, "hw_dbg29", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT6, 94, "usbb1_ulpitll_dat6",
-			"dmtimer10_pwm_evt", "abe_mcbsp3_clkx", "gpio_94",
-			"usbb1_ulpiphy_dat6", "abe_dmic_din3", "hw_dbg30",
-			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT7, 95, "usbb1_ulpitll_dat7",
-			"dmtimer11_pwm_evt", "abe_mcbsp3_fsx", "gpio_95",
-			"usbb1_ulpiphy_dat7", "abe_dmic_clk3", "hw_dbg31",
-			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_HSIC_DATA, 96, "usbb1_hsic_data", NULL, NULL,
-			"gpio_96", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_HSIC_STROBE, 97, "usbb1_hsic_strobe", NULL,
-			NULL, "gpio_97", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBC1_ICUSB_DP, 98, "usbc1_icusb_dp", NULL, NULL,
-			"gpio_98", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBC1_ICUSB_DM, 99, "usbc1_icusb_dm", NULL, NULL,
-			"gpio_99", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_CLK, 100, "sdmmc1_clk", NULL, "dpm_emu19",
-			"gpio_100", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_CMD, 101, "sdmmc1_cmd", NULL, "uart1_rx",
-			"gpio_101", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT0, 102, "sdmmc1_dat0", NULL, "dpm_emu18",
-			"gpio_102", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT1, 103, "sdmmc1_dat1", NULL, "dpm_emu17",
-			"gpio_103", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT2, 104, "sdmmc1_dat2", NULL, "dpm_emu16",
-			"gpio_104", "jtag_tms_tmsc", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT3, 105, "sdmmc1_dat3", NULL, "dpm_emu15",
-			"gpio_105", "jtag_tck", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT4, 106, "sdmmc1_dat4", NULL, NULL,
-			"gpio_106", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT5, 107, "sdmmc1_dat5", NULL, NULL,
-			"gpio_107", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT6, 108, "sdmmc1_dat6", NULL, NULL,
-			"gpio_108", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT7, 109, "sdmmc1_dat7", NULL, NULL,
-			"gpio_109", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_CLKX, 110, "abe_mcbsp2_clkx", "mcspi2_clk",
-			"abe_mcasp_ahclkx", "gpio_110", "usbb2_mm_rxdm",
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_DR, 111, "abe_mcbsp2_dr", "mcspi2_somi",
-			"abe_mcasp_axr", "gpio_111", "usbb2_mm_rxdp", NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_DX, 112, "abe_mcbsp2_dx", "mcspi2_simo",
-			"abe_mcasp_amute", "gpio_112", "usbb2_mm_rxrcv", NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_FSX, 113, "abe_mcbsp2_fsx", "mcspi2_cs0",
-			"abe_mcasp_afsx", "gpio_113", "usbb2_mm_txen", NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_CLKX, 114, "abe_mcbsp1_clkx",
-			"abe_slimbus1_clock", NULL, "gpio_114", NULL, NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_DR, 115, "abe_mcbsp1_dr",
-			"abe_slimbus1_data", NULL, "gpio_115", NULL, NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_DX, 116, "abe_mcbsp1_dx", "sdmmc3_dat2",
-			"abe_mcasp_aclkx", "gpio_116", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_FSX, 117, "abe_mcbsp1_fsx", "sdmmc3_dat3",
-			"abe_mcasp_amutein", "gpio_117", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_UL_DATA, 0, "abe_pdm_ul_data",
-			"abe_mcbsp3_dr", NULL, NULL, NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_DL_DATA, 0, "abe_pdm_dl_data",
-			"abe_mcbsp3_dx", NULL, NULL, NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_FRAME, 0, "abe_pdm_frame", "abe_mcbsp3_clkx",
-			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_LB_CLK, 0, "abe_pdm_lb_clk", "abe_mcbsp3_fsx",
-			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_CLKS, 118, "abe_clks", NULL, NULL, "gpio_118",
-			NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(ABE_DMIC_CLK1, 119, "abe_dmic_clk1", NULL, NULL,
 			"gpio_119", "usbb2_mm_txse0", "uart4_cts", NULL,
 			"safe_mode"),
@@ -1012,58 +825,6 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 	_OMAP4_MUXENTRY(ABE_DMIC_DIN3, 122, "abe_dmic_din3", "slimbus2_data",
 			"abe_dmic_clk2", "gpio_122", NULL, "dmtimer9_pwm_evt",
 			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_CTS, 123, "uart2_cts", "sdmmc3_clk", NULL,
-			"gpio_123", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_RTS, 124, "uart2_rts", "sdmmc3_cmd", NULL,
-			"gpio_124", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_RX, 125, "uart2_rx", "sdmmc3_dat0", NULL,
-			"gpio_125", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_TX, 126, "uart2_tx", "sdmmc3_dat1", NULL,
-			"gpio_126", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDQ_SIO, 127, "hdq_sio", "i2c3_sccb", "i2c2_sccb",
-			"gpio_127", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C1_SCL, 0, "i2c1_scl", NULL, NULL, NULL, NULL, NULL,
-			NULL, NULL),
-	_OMAP4_MUXENTRY(I2C1_SDA, 0, "i2c1_sda", NULL, NULL, NULL, NULL, NULL,
-			NULL, NULL),
-	_OMAP4_MUXENTRY(I2C2_SCL, 128, "i2c2_scl", "uart1_rx", NULL,
-			"gpio_128", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C2_SDA, 129, "i2c2_sda", "uart1_tx", NULL,
-			"gpio_129", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C3_SCL, 130, "i2c3_scl", NULL, NULL, "gpio_130",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C3_SDA, 131, "i2c3_sda", NULL, NULL, "gpio_131",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C4_SCL, 132, "i2c4_scl", NULL, NULL, "gpio_132",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C4_SDA, 133, "i2c4_sda", NULL, NULL, "gpio_133",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CLK, 134, "mcspi1_clk", NULL, NULL, "gpio_134",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_SOMI, 135, "mcspi1_somi", NULL, NULL,
-			"gpio_135", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_SIMO, 136, "mcspi1_simo", NULL, NULL,
-			"gpio_136", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS0, 137, "mcspi1_cs0", NULL, NULL, "gpio_137",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS1, 138, "mcspi1_cs1", "uart1_rx", NULL,
-			"gpio_138", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS2, 139, "mcspi1_cs2", "uart1_cts",
-			"slimbus2_clock", "gpio_139", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS3, 140, "mcspi1_cs3", "uart1_rts",
-			"slimbus2_data", "gpio_140", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(UART3_CTS_RCTX, 141, "uart3_cts_rctx", "uart1_tx",
-			NULL, "gpio_141", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART3_RTS_SD, 142, "uart3_rts_sd", NULL, NULL,
-			"gpio_142", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART3_RX_IRRX, 143, "uart3_rx_irrx",
-			"dmtimer8_pwm_evt", NULL, "gpio_143", NULL, NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART3_TX_IRTX, 144, "uart3_tx_irtx",
-			"dmtimer9_pwm_evt", NULL, "gpio_144", NULL, NULL,
-			NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(SDMMC5_CLK, 145, "sdmmc5_clk", "mcspi2_clk",
 			"usbc1_icusb_dp", "gpio_145", NULL, "sdmmc2_clk",
 			NULL, "safe_mode"),
@@ -1096,9 +857,6 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 			"gpio_155", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(UART4_TX, 156, "uart4_tx", "sdmmc4_dat1", "kpd_col8",
 			"gpio_156", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB2_ULPITLL_CLK, 157, "usbb2_ulpitll_clk",
-			"usbb2_ulpiphy_clk", "sdmmc4_cmd", "gpio_157",
-			"hsi2_cawake", NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(USBB2_ULPITLL_STP, 158, "usbb2_ulpitll_stp",
 			"usbb2_ulpiphy_stp", "sdmmc4_clk", "gpio_158",
 			"hsi2_cadata", "dispc2_data23", NULL, "safe_mode"),
@@ -1140,10 +898,6 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 			"usbb2_ulpiphy_dat7", "sdmmc3_clk", "gpio_168",
 			"mcspi3_clk", "dispc2_data11", "rfbi_data11",
 			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB2_HSIC_DATA, 169, "usbb2_hsic_data", NULL, NULL,
-			"gpio_169", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB2_HSIC_STROBE, 170, "usbb2_hsic_strobe", NULL,
-			NULL, "gpio_170", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(KPD_COL3, 171, "kpd_col3", "kpd_col0", NULL,
 			"gpio_171", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(KPD_COL4, 172, "kpd_col4", "kpd_col1", NULL,
@@ -1168,36 +922,10 @@ static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
 			NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(KPD_ROW2, 3, "kpd_row2", "kpd_row5", NULL, "gpio_3",
 			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBA0_OTG_CE, 0, "usba0_otg_ce", NULL, NULL, NULL,
-			NULL, NULL, NULL, NULL),
 	_OMAP4_MUXENTRY(USBA0_OTG_DP, 0, "usba0_otg_dp", "uart3_rx_irrx",
 			"uart2_rx", NULL, NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(USBA0_OTG_DM, 0, "usba0_otg_dm", "uart3_tx_irtx",
 			"uart2_tx", NULL, NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(FREF_CLK1_OUT, 181, "fref_clk1_out", NULL, NULL,
-			"gpio_181", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(FREF_CLK2_OUT, 182, "fref_clk2_out", NULL, NULL,
-			"gpio_182", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_NIRQ1, 0, "sys_nirq1", NULL, NULL, NULL, NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_NIRQ2, 183, "sys_nirq2", NULL, NULL, "gpio_183",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT0, 184, "sys_boot0", NULL, NULL, "gpio_184",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT1, 185, "sys_boot1", NULL, NULL, "gpio_185",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT2, 186, "sys_boot2", NULL, NULL, "gpio_186",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT3, 187, "sys_boot3", NULL, NULL, "gpio_187",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT4, 188, "sys_boot4", NULL, NULL, "gpio_188",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT5, 189, "sys_boot5", NULL, NULL, "gpio_189",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(DPM_EMU0, 11, "dpm_emu0", NULL, NULL, "gpio_11", NULL,
-			NULL, "hw_dbg0", "safe_mode"),
-	_OMAP4_MUXENTRY(DPM_EMU1, 12, "dpm_emu1", NULL, NULL, "gpio_12", NULL,
-			NULL, "hw_dbg1", "safe_mode"),
 	_OMAP4_MUXENTRY(DPM_EMU2, 13, "dpm_emu2", "usba0_ulpiphy_clk", NULL,
 			"gpio_13", NULL, "dispc2_fid", "hw_dbg2",
 			"safe_mode"),
@@ -1586,6 +1314,7 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
 	struct omap_ball *package_balls_core;
 	struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball;
 	struct omap_mux *core_muxmodes;
+	struct omap_mux *core_subset = NULL;
 	int ret;
 
 	switch (flags & OMAP_PACKAGE_MASK) {
@@ -1597,7 +1326,8 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
 	case OMAP_PACKAGE_CBS:
 		pr_debug("%s: OMAP4430 ES2.X -> OMAP_PACKAGE_CBS\n", __func__);
 		package_balls_core = omap4_core_cbs_ball;
-		core_muxmodes = omap4_es2_core_muxmodes;
+		core_muxmodes = omap4_core_muxmodes;
+		core_subset = omap4_es2_core_subset;
 		break;
 	default:
 		pr_err("%s: Unknown omap package, mux disabled\n", __func__);
@@ -1608,7 +1338,7 @@ int __init omap4_mux_init(struct omap_board_mux *board_subset, int flags)
 			    OMAP_MUX_GPIO_IN_MODE3,
 			    OMAP4_CTRL_MODULE_PAD_CORE_MUX_PBASE,
 			    OMAP4_CTRL_MODULE_PAD_CORE_MUX_SIZE,
-			    core_muxmodes, NULL, board_subset,
+			    core_muxmodes, core_subset, board_subset,
 			    package_balls_core);
 	if (ret)
 		return ret;
diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S
index 6ae937a..4ee6aec 100644
--- a/arch/arm/mach-omap2/omap-headsmp.S
+++ b/arch/arm/mach-omap2/omap-headsmp.S
@@ -45,5 +45,5 @@ hold:	ldr	r12,=0x103
 	 * should now contain the SVC stack for this core
 	 */
 	b	secondary_startup
-END(omap_secondary_startup)
+ENDPROC(omap_secondary_startup)
 
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 1926864..9ef8c29 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -52,6 +52,12 @@ static void omap4_l2x0_disable(void)
 	omap_smc1(0x102, 0x0);
 }
 
+static void omap4_l2x0_set_debug(unsigned long val)
+{
+	/* Program PL310 L2 Cache controller debug register */
+	omap_smc1(0x100, val);
+}
+
 static int __init omap_l2_cache_init(void)
 {
 	u32 aux_ctrl = 0;
@@ -99,6 +105,7 @@ static int __init omap_l2_cache_init(void)
 	 * specific one
 	*/
 	outer_cache.disable = omap4_l2x0_disable;
+	outer_cache.set_debug = omap4_l2x0_set_debug;
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/omap44xx-smc.S b/arch/arm/mach-omap2/omap44xx-smc.S
index 1980dc3..e69d37d 100644
--- a/arch/arm/mach-omap2/omap44xx-smc.S
+++ b/arch/arm/mach-omap2/omap44xx-smc.S
@@ -29,7 +29,7 @@ ENTRY(omap_smc1)
 	dsb
 	smc	#0
 	ldmfd   sp!, {r2-r12, pc}
-END(omap_smc1)
+ENDPROC(omap_smc1)
 
 ENTRY(omap_modify_auxcoreboot0)
 	stmfd   sp!, {r1-r12, lr}
@@ -37,7 +37,7 @@ ENTRY(omap_modify_auxcoreboot0)
 	dsb
 	smc	#0
 	ldmfd   sp!, {r1-r12, pc}
-END(omap_modify_auxcoreboot0)
+ENDPROC(omap_modify_auxcoreboot0)
 
 ENTRY(omap_auxcoreboot_addr)
 	stmfd   sp!, {r2-r12, lr}
@@ -45,7 +45,7 @@ ENTRY(omap_auxcoreboot_addr)
 	dsb
 	smc	#0
 	ldmfd   sp!, {r2-r12, pc}
-END(omap_auxcoreboot_addr)
+ENDPROC(omap_auxcoreboot_addr)
 
 ENTRY(omap_read_auxcoreboot0)
 	stmfd   sp!, {r2-r12, lr}
@@ -54,4 +54,4 @@ ENTRY(omap_read_auxcoreboot0)
 	smc	#0
 	mov	r0, r0, lsr #9
 	ldmfd   sp!, {r2-r12, pc}
-END(omap_read_auxcoreboot0)
+ENDPROC(omap_read_auxcoreboot0)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e282e35..e034294 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod implementation for OMAP2/3/4
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Paul Walmsley, BenoĂŽt Cousson, Kevin Hilman
  *
@@ -162,9 +162,6 @@ static LIST_HEAD(omap_hwmod_list);
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
-/* inited: 0 if omap_hwmod_init() has not yet been called; 1 otherwise */
-static u8 inited;
-
 
 /* Private functions */
 
@@ -373,7 +370,7 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
 	}
 
 	autoidle_shift = oh->class->sysc->sysc_fields->autoidle_shift;
-	autoidle_mask = (0x3 << autoidle_shift);
+	autoidle_mask = (0x1 << autoidle_shift);
 
 	*v &= ~autoidle_mask;
 	*v |= autoidle << autoidle_shift;
@@ -460,14 +457,18 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
  * will be accessed by a particular initiator (e.g., if a module will
  * be accessed by the IVA, there should be a sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
- * mode.  Returns -EINVAL upon error or passes along
- * clkdm_add_sleepdep() value upon success.
+ * mode.  If the clockdomain is marked as not needing autodeps, return
+ * 0 without doing anything.  Otherwise, returns -EINVAL upon error or
+ * passes along clkdm_add_sleepdep() value upon success.
  */
 static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
+	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+		return 0;
+
 	return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
@@ -480,14 +481,18 @@ static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
  * be accessed by a particular initiator (e.g., if a module will not
  * be accessed by the IVA, there should be no sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
- * mode.  Returns -EINVAL upon error or passes along
- * clkdm_del_sleepdep() value upon success.
+ * mode.  If the clockdomain is marked as not needing autodeps, return
+ * 0 without doing anything.  Returns -EINVAL upon error or passes
+ * along clkdm_del_sleepdep() value upon success.
  */
 static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
+	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+		return 0;
+
 	return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
@@ -904,18 +909,16 @@ static struct omap_hwmod *_lookup(const char *name)
  * @oh: struct omap_hwmod *
  * @data: not used; pass NULL
  *
- * Called by omap_hwmod_late_init() (after omap2_clk_init()).
- * Resolves all clock names embedded in the hwmod.  Returns -EINVAL if
- * the omap_hwmod has not yet been registered or if the clocks have
- * already been initialized, 0 on success, or a non-zero error on
- * failure.
+ * Called by omap_hwmod_setup_*() (after omap2_clk_init()).
+ * Resolves all clock names embedded in the hwmod.  Returns 0 on
+ * success, or a negative error code on failure.
  */
 static int _init_clocks(struct omap_hwmod *oh, void *data)
 {
 	int ret = 0;
 
-	if (!oh || (oh->_state != _HWMOD_STATE_REGISTERED))
-		return -EINVAL;
+	if (oh->_state != _HWMOD_STATE_REGISTERED)
+		return 0;
 
 	pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
 
@@ -926,7 +929,7 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
 	if (!ret)
 		oh->_state = _HWMOD_STATE_CLKS_INITED;
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -972,25 +975,29 @@ static int _wait_target_ready(struct omap_hwmod *oh)
 }
 
 /**
- * _lookup_hardreset - return the register bit shift for this hwmod/reset line
+ * _lookup_hardreset - fill register bit info for this hwmod/reset line
  * @oh: struct omap_hwmod *
  * @name: name of the reset line in the context of this hwmod
+ * @ohri: struct omap_hwmod_rst_info * that this function will fill in
  *
  * Return the bit position of the reset line that match the
  * input name. Return -ENOENT if not found.
  */
-static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
+static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
+			    struct omap_hwmod_rst_info *ohri)
 {
 	int i;
 
 	for (i = 0; i < oh->rst_lines_cnt; i++) {
 		const char *rst_line = oh->rst_lines[i].name;
 		if (!strcmp(rst_line, name)) {
-			u8 shift = oh->rst_lines[i].rst_shift;
-			pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
-				 oh->name, rst_line, shift);
+			ohri->rst_shift = oh->rst_lines[i].rst_shift;
+			ohri->st_shift = oh->rst_lines[i].st_shift;
+			pr_debug("omap_hwmod: %s: %s: %s: rst %d st %d\n",
+				 oh->name, __func__, rst_line, ohri->rst_shift,
+				 ohri->st_shift);
 
-			return shift;
+			return 0;
 		}
 	}
 
@@ -1009,21 +1016,22 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
  */
 static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
 {
-	u8 shift;
+	struct omap_hwmod_rst_info ohri;
+	u8 ret;
 
 	if (!oh)
 		return -EINVAL;
 
-	shift = _lookup_hardreset(oh, name);
-	if (IS_ERR_VALUE(shift))
-		return shift;
+	ret = _lookup_hardreset(oh, name, &ohri);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (cpu_is_omap24xx() || cpu_is_omap34xx())
 		return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
-						  shift);
+						  ohri.rst_shift);
 	else if (cpu_is_omap44xx())
 		return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
-						  shift);
+						  ohri.rst_shift);
 	else
 		return -EINVAL;
 }
@@ -1040,29 +1048,34 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
  */
 static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 {
-	u8 shift;
-	int r;
+	struct omap_hwmod_rst_info ohri;
+	int ret;
 
 	if (!oh)
 		return -EINVAL;
 
-	shift = _lookup_hardreset(oh, name);
-	if (IS_ERR_VALUE(shift))
-		return shift;
+	ret = _lookup_hardreset(oh, name, &ohri);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
-						 shift);
-	else if (cpu_is_omap44xx())
-		r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
-						 shift);
-	else
+	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+						   ohri.rst_shift,
+						   ohri.st_shift);
+	} else if (cpu_is_omap44xx()) {
+		if (ohri.st_shift)
+			pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
+			       oh->name, name);
+		ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
+						   ohri.rst_shift);
+	} else {
 		return -EINVAL;
+	}
 
-	if (r == -EBUSY)
+	if (ret == -EBUSY)
 		pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
 
-	return r;
+	return ret;
 }
 
 /**
@@ -1075,21 +1088,22 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
  */
 static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 {
-	u8 shift;
+	struct omap_hwmod_rst_info ohri;
+	u8 ret;
 
 	if (!oh)
 		return -EINVAL;
 
-	shift = _lookup_hardreset(oh, name);
-	if (IS_ERR_VALUE(shift))
-		return shift;
+	ret = _lookup_hardreset(oh, name, &ohri);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 		return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
-						       shift);
+						       ohri.st_shift);
 	} else if (cpu_is_omap44xx()) {
 		return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
-						       shift);
+						       ohri.rst_shift);
 	} else {
 		return -EINVAL;
 	}
@@ -1230,7 +1244,9 @@ static int _enable(struct omap_hwmod *oh)
 		_deassert_hardreset(oh, oh->rst_lines[0].name);
 
 	/* Mux pins for device runtime if populated */
-	if (oh->mux)
+	if (oh->mux && (!oh->mux->enabled ||
+			((oh->_state == _HWMOD_STATE_IDLE) &&
+			 oh->mux->pads_dynamic)))
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
@@ -1279,7 +1295,7 @@ static int _idle(struct omap_hwmod *oh)
 	_disable_clocks(oh);
 
 	/* Mux pins for device idle if populated */
-	if (oh->mux)
+	if (oh->mux && oh->mux->pads_dynamic)
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
 
 	oh->_state = _HWMOD_STATE_IDLE;
@@ -1288,6 +1304,42 @@ static int _idle(struct omap_hwmod *oh)
 }
 
 /**
+ * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit
+ * @oh: struct omap_hwmod *
+ * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
+ *
+ * Sets the IP block's OCP autoidle bit in hardware, and updates our
+ * local copy. Intended to be used by drivers that require
+ * direct manipulation of the AUTOIDLE bits.
+ * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes
+ * along the return value from _set_module_autoidle().
+ *
+ * Any users of this function should be scrutinized carefully.
+ */
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
+{
+	u32 v;
+	int retval = 0;
+	unsigned long flags;
+
+	if (!oh || oh->_state != _HWMOD_STATE_ENABLED)
+		return -EINVAL;
+
+	spin_lock_irqsave(&oh->_lock, flags);
+
+	v = oh->_sysc_cache;
+
+	retval = _set_module_autoidle(oh, autoidle, &v);
+
+	if (!retval)
+		_write_sysconfig(v, oh);
+
+	spin_unlock_irqrestore(&oh->_lock, flags);
+
+	return retval;
+}
+
+/**
  * _shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -1354,14 +1406,16 @@ static int _shutdown(struct omap_hwmod *oh)
  * @oh: struct omap_hwmod *
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the
- * wrong state or returns 0.
+ * OCP_SYSCONFIG register.  Returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
 	int i, r;
 	u8 postsetup_state;
 
+	if (oh->_state != _HWMOD_STATE_CLKS_INITED)
+		return 0;
+
 	/* Set iclk autoidle mode */
 	if (oh->slaves_cnt > 0) {
 		for (i = 0; i < oh->slaves_cnt; i++) {
@@ -1455,7 +1509,7 @@ static int _setup(struct omap_hwmod *oh, void *data)
  */
 static int __init _register(struct omap_hwmod *oh)
 {
-	int ret, ms_id;
+	int ms_id;
 
 	if (!oh || !oh->name || !oh->class || !oh->class->name ||
 	    (oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -1467,12 +1521,10 @@ static int __init _register(struct omap_hwmod *oh)
 		return -EEXIST;
 
 	ms_id = _find_mpu_port_index(oh);
-	if (!IS_ERR_VALUE(ms_id)) {
+	if (!IS_ERR_VALUE(ms_id))
 		oh->_mpu_port_index = ms_id;
-		oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
-	} else {
+	else
 		oh->_int_flags |= _HWMOD_NO_MPU_PORT;
-	}
 
 	list_add_tail(&oh->node, &omap_hwmod_list);
 
@@ -1480,9 +1532,14 @@ static int __init _register(struct omap_hwmod *oh)
 
 	oh->_state = _HWMOD_STATE_REGISTERED;
 
-	ret = 0;
+	/*
+	 * XXX Rather than doing a strcmp(), this should test a flag
+	 * set in the hwmod data, inserted by the autogenerator code.
+	 */
+	if (!strcmp(oh->name, MPU_INITIATOR_NAME))
+		mpu_oh = oh;
 
-	return ret;
+	return 0;
 }
 
 
@@ -1585,65 +1642,132 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
 	return ret;
 }
 
-
 /**
- * omap_hwmod_init - init omap_hwmod code and register hwmods
+ * omap_hwmod_register - register an array of hwmods
  * @ohs: pointer to an array of omap_hwmods to register
  *
  * Intended to be called early in boot before the clock framework is
  * initialized.  If @ohs is not null, will register all omap_hwmods
- * listed in @ohs that are valid for this chip.  Returns -EINVAL if
- * omap_hwmod_init() has already been called or 0 otherwise.
+ * listed in @ohs that are valid for this chip.  Returns 0.
  */
-int __init omap_hwmod_init(struct omap_hwmod **ohs)
+int __init omap_hwmod_register(struct omap_hwmod **ohs)
+{
+	int r, i;
+
+	if (!ohs)
+		return 0;
+
+	i = 0;
+	do {
+		if (!omap_chip_is(ohs[i]->omap_chip))
+			continue;
+
+		r = _register(ohs[i]);
+		WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
+		     r);
+	} while (ohs[++i]);
+
+	return 0;
+}
+
+/*
+ * _populate_mpu_rt_base - populate the virtual address for a hwmod
+ *
+ * Must be called only from omap_hwmod_setup_*() so ioremap works properly.
+ * Assumes the caller takes care of locking if needed.
+ */
+static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
+{
+	if (oh->_state != _HWMOD_STATE_REGISTERED)
+		return 0;
+
+	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+		return 0;
+
+	oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
+	if (!oh->_mpu_rt_va)
+		pr_warning("omap_hwmod: %s found no _mpu_rt_va for %s\n",
+				__func__, oh->name);
+
+	return 0;
+}
+
+/**
+ * omap_hwmod_setup_one - set up a single hwmod
+ * @oh_name: const char * name of the already-registered hwmod to set up
+ *
+ * Must be called after omap2_clk_init().  Resolves the struct clk
+ * names to struct clk pointers for each registered omap_hwmod.  Also
+ * calls _setup() on each hwmod.  Returns -EINVAL upon error or 0 upon
+ * success.
+ */
+int __init omap_hwmod_setup_one(const char *oh_name)
 {
 	struct omap_hwmod *oh;
 	int r;
 
-	if (inited)
+	pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__);
+
+	if (!mpu_oh) {
+		pr_err("omap_hwmod: %s: cannot setup_one: MPU initiator hwmod %s not yet registered\n",
+		       oh_name, MPU_INITIATOR_NAME);
 		return -EINVAL;
+	}
 
-	inited = 1;
+	oh = _lookup(oh_name);
+	if (!oh) {
+		WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name);
+		return -EINVAL;
+	}
 
-	if (!ohs)
-		return 0;
+	if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh)
+		omap_hwmod_setup_one(MPU_INITIATOR_NAME);
 
-	oh = *ohs;
-	while (oh) {
-		if (omap_chip_is(oh->omap_chip)) {
-			r = _register(oh);
-			WARN(r, "omap_hwmod: %s: _register returned "
-			     "%d\n", oh->name, r);
-		}
-		oh = *++ohs;
+	r = _populate_mpu_rt_base(oh, NULL);
+	if (IS_ERR_VALUE(r)) {
+		WARN(1, "omap_hwmod: %s: couldn't set mpu_rt_base\n", oh_name);
+		return -EINVAL;
 	}
 
+	r = _init_clocks(oh, NULL);
+	if (IS_ERR_VALUE(r)) {
+		WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh_name);
+		return -EINVAL;
+	}
+
+	_setup(oh, NULL);
+
 	return 0;
 }
 
 /**
- * omap_hwmod_late_init - do some post-clock framework initialization
+ * omap_hwmod_setup - do some post-clock framework initialization
  *
  * Must be called after omap2_clk_init().  Resolves the struct clk names
  * to struct clk pointers for each registered omap_hwmod.  Also calls
- * _setup() on each hwmod.  Returns 0.
+ * _setup() on each hwmod.  Returns 0 upon success.
  */
-int omap_hwmod_late_init(void)
+static int __init omap_hwmod_setup_all(void)
 {
 	int r;
 
-	/* XXX check return value */
-	r = omap_hwmod_for_each(_init_clocks, NULL);
-	WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n");
+	if (!mpu_oh) {
+		pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n",
+		       __func__, MPU_INITIATOR_NAME);
+		return -EINVAL;
+	}
 
-	mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME);
-	WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
-	     MPU_INITIATOR_NAME);
+	r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL);
+
+	r = omap_hwmod_for_each(_init_clocks, NULL);
+	WARN(IS_ERR_VALUE(r),
+	     "omap_hwmod: %s: _init_clocks failed\n", __func__);
 
 	omap_hwmod_for_each(_setup, NULL);
 
 	return 0;
 }
+core_initcall(omap_hwmod_setup_all);
 
 /**
  * omap_hwmod_enable - enable an omap_hwmod
@@ -1862,6 +1986,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
 		os = oh->slaves[i];
 
 		for (j = 0; j < os->addr_cnt; j++) {
+			(res + r)->name = (os->addr + j)->name;
 			(res + r)->start = (os->addr + j)->pa_start;
 			(res + r)->end = (os->addr + j)->pa_end;
 			(res + r)->flags = IORESOURCE_MEM;
@@ -2162,11 +2287,11 @@ int omap_hwmod_for_each_by_class(const char *classname,
  * @oh: struct omap_hwmod *
  * @state: state that _setup() should leave the hwmod in
  *
- * Sets the hwmod state that @oh will enter at the end of _setup() (called by
- * omap_hwmod_late_init()).  Only valid to call between calls to
- * omap_hwmod_init() and omap_hwmod_late_init().  Returns 0 upon success or
- * -EINVAL if there is a problem with the arguments or if the hwmod is
- * in the wrong state.
+ * Sets the hwmod state that @oh will enter at the end of _setup()
+ * (called by omap_hwmod_setup_*()).  Only valid to call between
+ * calling omap_hwmod_register() and omap_hwmod_setup_*().  Returns
+ * 0 upon success or -EINVAL if there is a problem with the arguments
+ * or if the hwmod is in the wrong state.
  */
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
 {
@@ -2218,3 +2343,29 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh)
 
 	return ret;
 }
+
+/**
+ * omap_hwmod_no_setup_reset - prevent a hwmod from being reset upon setup
+ * @oh: struct omap_hwmod *
+ *
+ * Prevent the hwmod @oh from being reset during the setup process.
+ * Intended for use by board-*.c files on boards with devices that
+ * cannot tolerate being reset.  Must be called before the hwmod has
+ * been set up.  Returns 0 upon success or negative error code upon
+ * failure.
+ */
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
+{
+	if (!oh)
+		return -EINVAL;
+
+	if (oh->_state != _HWMOD_STATE_REGISTERED) {
+		pr_err("omap_hwmod: %s: cannot prevent setup reset; in wrong state\n",
+			oh->name);
+		return -EINVAL;
+	}
+
+	oh->flags |= HWMOD_INIT_NO_RESET;
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index b85c630..6282346 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -18,6 +18,10 @@
 #include <plat/serial.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
+#include <plat/mcspi.h>
+#include <plat/dmtimer.h>
+#include <plat/l3_2xxx.h>
+#include <plat/l4_2xxx.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -38,12 +42,18 @@ static struct omap_hwmod omap2420_mpu_hwmod;
 static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_dss_core_hwmod;
+static struct omap_hwmod omap2420_dss_dispc_hwmod;
+static struct omap_hwmod omap2420_dss_rfbi_hwmod;
+static struct omap_hwmod omap2420_dss_venc_hwmod;
 static struct omap_hwmod omap2420_wd_timer2_hwmod;
 static struct omap_hwmod omap2420_gpio1_hwmod;
 static struct omap_hwmod omap2420_gpio2_hwmod;
 static struct omap_hwmod omap2420_gpio3_hwmod;
 static struct omap_hwmod omap2420_gpio4_hwmod;
 static struct omap_hwmod omap2420_dma_system_hwmod;
+static struct omap_hwmod omap2420_mcspi1_hwmod;
+static struct omap_hwmod omap2420_mcspi2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -64,6 +74,19 @@ static struct omap_hwmod_ocp_if *omap2420_l3_main_slaves[] = {
 	&omap2420_mpu__l3_main,
 };
 
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap2420_dss__l3 = {
+	.master		= &omap2420_dss_core_hwmod,
+	.slave		= &omap2420_l3_main_hwmod,
+	.fw = {
+		.omap2 = {
+			.l3_perm_bit  = OMAP2_L3_CORE_FW_CONNID_DSS,
+			.flags	= OMAP_FIREWALL_L3,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Master interfaces on the L3 interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l3_main_masters[] = {
 	&omap2420_l3_main__l4_core,
@@ -87,6 +110,44 @@ static struct omap_hwmod omap2420_uart2_hwmod;
 static struct omap_hwmod omap2420_uart3_hwmod;
 static struct omap_hwmod omap2420_i2c1_hwmod;
 static struct omap_hwmod omap2420_i2c2_hwmod;
+static struct omap_hwmod omap2420_mcbsp1_hwmod;
+static struct omap_hwmod omap2420_mcbsp2_hwmod;
+
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_addr_space omap2420_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480980ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi1 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcspi1_hwmod,
+	.clk		= "mcspi1_ick",
+	.addr		= omap2420_mcspi1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcspi1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_addr_space omap2420_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcspi2_hwmod,
+	.clk		= "mcspi2_ick",
+	.addr		= omap2420_mcspi2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcspi2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
@@ -279,6 +340,625 @@ static struct omap_hwmod omap2420_iva_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
+/* Timer Common */
+static struct omap_hwmod_class_sysconfig omap2420_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_timer_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap2420_timer_sysc,
+	.rev = OMAP_TIMER_IP_VERSION_1,
+};
+
+/* timer1 */
+static struct omap_hwmod omap2420_timer1_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
+	{
+		.pa_start	= 0x48028000,
+		.pa_end		= 0x48028000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__timer1 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_timer1_hwmod,
+	.clk		= "gpt1_ick",
+	.addr		= omap2420_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer1_slaves[] = {
+	&omap2420_l4_wkup__timer1,
+};
+
+/* timer1 hwmod */
+static struct omap_hwmod omap2420_timer1_hwmod = {
+	.name		= "timer1",
+	.mpu_irqs	= omap2420_timer1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer1_mpu_irqs),
+	.main_clk	= "gpt1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer2 */
+static struct omap_hwmod omap2420_timer2_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4802a000,
+		.pa_end		= 0x4802a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer2 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer2_hwmod,
+	.clk		= "gpt2_ick",
+	.addr		= omap2420_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer2 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer2_slaves[] = {
+	&omap2420_l4_core__timer2,
+};
+
+/* timer2 hwmod */
+static struct omap_hwmod omap2420_timer2_hwmod = {
+	.name		= "timer2",
+	.mpu_irqs	= omap2420_timer2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer2_mpu_irqs),
+	.main_clk	= "gpt2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT2_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer3 */
+static struct omap_hwmod omap2420_timer3_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer3_addrs[] = {
+	{
+		.pa_start	= 0x48078000,
+		.pa_end		= 0x48078000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer3 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer3 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer3_hwmod,
+	.clk		= "gpt3_ick",
+	.addr		= omap2420_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer3 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer3_slaves[] = {
+	&omap2420_l4_core__timer3,
+};
+
+/* timer3 hwmod */
+static struct omap_hwmod omap2420_timer3_hwmod = {
+	.name		= "timer3",
+	.mpu_irqs	= omap2420_timer3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer3_mpu_irqs),
+	.main_clk	= "gpt3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT3_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer4 */
+static struct omap_hwmod omap2420_timer4_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer4_addrs[] = {
+	{
+		.pa_start	= 0x4807a000,
+		.pa_end		= 0x4807a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer4 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer4 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer4_hwmod,
+	.clk		= "gpt4_ick",
+	.addr		= omap2420_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer4 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer4_slaves[] = {
+	&omap2420_l4_core__timer4,
+};
+
+/* timer4 hwmod */
+static struct omap_hwmod omap2420_timer4_hwmod = {
+	.name		= "timer4",
+	.mpu_irqs	= omap2420_timer4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer4_mpu_irqs),
+	.main_clk	= "gpt4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT4_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer5 */
+static struct omap_hwmod omap2420_timer5_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer5_addrs[] = {
+	{
+		.pa_start	= 0x4807c000,
+		.pa_end		= 0x4807c000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer5 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer5 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer5_hwmod,
+	.clk		= "gpt5_ick",
+	.addr		= omap2420_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer5 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer5_slaves[] = {
+	&omap2420_l4_core__timer5,
+};
+
+/* timer5 hwmod */
+static struct omap_hwmod omap2420_timer5_hwmod = {
+	.name		= "timer5",
+	.mpu_irqs	= omap2420_timer5_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer5_mpu_irqs),
+	.main_clk	= "gpt5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+
+/* timer6 */
+static struct omap_hwmod omap2420_timer6_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4807e000,
+		.pa_end		= 0x4807e000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer6 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer6 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer6_hwmod,
+	.clk		= "gpt6_ick",
+	.addr		= omap2420_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer6 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer6_slaves[] = {
+	&omap2420_l4_core__timer6,
+};
+
+/* timer6 hwmod */
+static struct omap_hwmod omap2420_timer6_hwmod = {
+	.name		= "timer6",
+	.mpu_irqs	= omap2420_timer6_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer6_mpu_irqs),
+	.main_clk	= "gpt6_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT6_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer7 */
+static struct omap_hwmod omap2420_timer7_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer7_addrs[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer7 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer7 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer7_hwmod,
+	.clk		= "gpt7_ick",
+	.addr		= omap2420_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer7_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer7 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer7_slaves[] = {
+	&omap2420_l4_core__timer7,
+};
+
+/* timer7 hwmod */
+static struct omap_hwmod omap2420_timer7_hwmod = {
+	.name		= "timer7",
+	.mpu_irqs	= omap2420_timer7_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer7_mpu_irqs),
+	.main_clk	= "gpt7_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT7_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer8 */
+static struct omap_hwmod omap2420_timer8_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer8_addrs[] = {
+	{
+		.pa_start	= 0x48082000,
+		.pa_end		= 0x48082000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer8 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer8 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer8_hwmod,
+	.clk		= "gpt8_ick",
+	.addr		= omap2420_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer8_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer8 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer8_slaves[] = {
+	&omap2420_l4_core__timer8,
+};
+
+/* timer8 hwmod */
+static struct omap_hwmod omap2420_timer8_hwmod = {
+	.name		= "timer8",
+	.mpu_irqs	= omap2420_timer8_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer8_mpu_irqs),
+	.main_clk	= "gpt8_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT8_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer9 */
+static struct omap_hwmod omap2420_timer9_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer9_addrs[] = {
+	{
+		.pa_start	= 0x48084000,
+		.pa_end		= 0x48084000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer9 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer9 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer9_hwmod,
+	.clk		= "gpt9_ick",
+	.addr		= omap2420_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer9_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer9 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer9_slaves[] = {
+	&omap2420_l4_core__timer9,
+};
+
+/* timer9 hwmod */
+static struct omap_hwmod omap2420_timer9_hwmod = {
+	.name		= "timer9",
+	.mpu_irqs	= omap2420_timer9_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer9_mpu_irqs),
+	.main_clk	= "gpt9_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT9_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer10 */
+static struct omap_hwmod omap2420_timer10_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer10_addrs[] = {
+	{
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer10 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer10_hwmod,
+	.clk		= "gpt10_ick",
+	.addr		= omap2420_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer10_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer10 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer10_slaves[] = {
+	&omap2420_l4_core__timer10,
+};
+
+/* timer10 hwmod */
+static struct omap_hwmod omap2420_timer10_hwmod = {
+	.name		= "timer10",
+	.mpu_irqs	= omap2420_timer10_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer10_mpu_irqs),
+	.main_clk	= "gpt10_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT10_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer11 */
+static struct omap_hwmod omap2420_timer11_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer11_addrs[] = {
+	{
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer11 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer11_hwmod,
+	.clk		= "gpt11_ick",
+	.addr		= omap2420_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer11_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer11 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer11_slaves[] = {
+	&omap2420_l4_core__timer11,
+};
+
+/* timer11 hwmod */
+static struct omap_hwmod omap2420_timer11_hwmod = {
+	.name		= "timer11",
+	.mpu_irqs	= omap2420_timer11_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer11_mpu_irqs),
+	.main_clk	= "gpt11_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT11_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer12 */
+static struct omap_hwmod omap2420_timer12_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer12_mpu_irqs[] = {
+	{ .irq = 48, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer12_addrs[] = {
+	{
+		.pa_start	= 0x4808a000,
+		.pa_end		= 0x4808a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer12 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer12_hwmod,
+	.clk		= "gpt12_ick",
+	.addr		= omap2420_timer12_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer12_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer12 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer12_slaves[] = {
+	&omap2420_l4_core__timer12,
+};
+
+/* timer12 hwmod */
+static struct omap_hwmod omap2420_timer12_hwmod = {
+	.name		= "timer12",
+	.mpu_irqs	= omap2420_timer12_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer12_mpu_irqs),
+	.main_clk	= "gpt12_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT12_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer12_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
 /* l4_wkup -> wd_timer2 */
 static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
 	{
@@ -308,7 +988,7 @@ static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -349,125 +1029,411 @@ static struct omap_hwmod_class_sysconfig uart_sysc = {
 	.syss_offs	= 0x58,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_class uart_class = {
-	.name = "uart",
-	.sysc = &uart_sysc,
+static struct omap_hwmod_class uart_class = {
+	.name = "uart",
+	.sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
+	&omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2420_uart1_hwmod = {
+	.name		= "uart1",
+	.mpu_irqs	= uart1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
+	.sdma_reqs	= uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
+	&omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2420_uart2_hwmod = {
+	.name		= "uart2",
+	.mpu_irqs	= uart2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
+	.sdma_reqs	= uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
+	&omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2420_uart3_hwmod = {
+	.name		= "uart3",
+	.mpu_irqs	= uart3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
+	.sdma_reqs	= uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit = OMAP24XX_EN_UART3_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+		},
+	},
+	.slaves		= omap2420_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dss_hwmod_class = {
+	.name = "dss",
+	.sysc = &omap2420_dss_sysc,
+};
+
+/* dss */
+static struct omap_hwmod_irq_info omap2420_dss_irqs[] = {
+	{ .irq = 25 },
+};
+
+static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_masters[] = {
+	&omap2420_dss__l3,
+};
+
+static struct omap_hwmod_addr_space omap2420_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x480503FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2420_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
+	&omap2420_l4_core__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+	{ .role = "sys_clk", .clk = "dss2_fck" },
+};
+
+static struct omap_hwmod omap2420_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap2420_dss_hwmod_class,
+	.main_clk	= "dss1_fck", /* instead of dss_fck */
+	.mpu_irqs	= omap2420_dss_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dss_irqs),
+	.sdma_reqs	= omap2420_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_dss_sdma_chs),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap2420_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_slaves),
+	.masters	= omap2420_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2420_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dispc_hwmod_class = {
+	.name = "dispc",
+	.sysc = &omap2420_dispc_sysc,
 };
 
-/* UART1 */
-
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
+static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x480507FF,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss_dispc = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_dispc_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2420_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_dispc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
-	&omap2_l4_core__uart1,
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
+	&omap2420_l4_core__dss_dispc,
 };
 
-static struct omap_hwmod omap2420_uart1_hwmod = {
-	.name		= "uart1",
-	.mpu_irqs	= uart1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
-	.sdma_reqs	= uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
-	.main_clk	= "uart1_fck",
+static struct omap_hwmod omap2420_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap2420_dispc_hwmod_class,
+	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_UART1_SHIFT,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
 		},
 	},
-	.slaves		= omap2420_uart1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2420_uart1_slaves),
-	.class		= &uart_class,
+	.slaves		= omap2420_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
 };
 
-/* UART2 */
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
 
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
+static struct omap_hwmod_class_sysconfig omap2420_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+static struct omap_hwmod_class omap2420_rfbi_hwmod_class = {
+	.name = "rfbi",
+	.sysc = &omap2420_rfbi_sysc,
 };
 
-static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
-	&omap2_l4_core__uart2,
+static struct omap_hwmod_addr_space omap2420_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050BFF,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod omap2420_uart2_hwmod = {
-	.name		= "uart2",
-	.mpu_irqs	= uart2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
-	.sdma_reqs	= uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
-	.main_clk	= "uart2_fck",
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss_rfbi = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_rfbi_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2420_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
+	&omap2420_l4_core__dss_rfbi,
+};
+
+static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap2420_rfbi_hwmod_class,
+	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_UART2_SHIFT,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
 		},
 	},
-	.slaves		= omap2420_uart2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2420_uart2_slaves),
-	.class		= &uart_class,
+	.slaves		= omap2420_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
 };
 
-/* UART3 */
+/*
+ * 'venc' class
+ * video encoder
+ */
 
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
+static struct omap_hwmod_class omap2420_venc_hwmod_class = {
+	.name = "venc",
 };
 
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+/* dss_venc */
+static struct omap_hwmod_addr_space omap2420_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050FFF,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
-	&omap2_l4_core__uart3,
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_venc_hwmod,
+	.clk		= "dss_54m_fck",
+	.addr		= omap2420_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_venc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.flags		= OCPIF_SWSUP_IDLE,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod omap2420_uart3_hwmod = {
-	.name		= "uart3",
-	.mpu_irqs	= uart3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
-	.sdma_reqs	= uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
-	.main_clk	= "uart3_fck",
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
+	&omap2420_l4_core__dss_venc,
+};
+
+static struct omap_hwmod omap2420_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap2420_venc_hwmod_class,
+	.main_clk	= "dss1_fck",
 	.prcm		= {
 		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
 			.module_offs = CORE_MOD,
-			.prcm_reg_id = 2,
-			.module_bit = OMAP24XX_EN_UART3_SHIFT,
-			.idlest_reg_id = 2,
-			.idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
 		},
 	},
-	.slaves		= omap2420_uart3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2420_uart3_slaves),
-	.class		= &uart_class,
+	.slaves		= omap2420_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_venc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
 };
 
 /* I2C common */
@@ -475,7 +1441,7 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
 	.rev_offs	= 0x00,
 	.sysc_offs	= 0x20,
 	.syss_offs	= 0x10,
-	.sysc_flags	= SYSC_HAS_SOFTRESET,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -647,7 +1613,8 @@ static struct omap_hwmod_class_sysconfig omap242x_gpio_sysc = {
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -789,7 +1756,7 @@ static struct omap_hwmod_class_sysconfig omap2420_dma_sysc = {
 	.syss_offs	= 0x0028,
 	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
 			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
@@ -864,16 +1831,342 @@ static struct omap_hwmod omap2420_dma_system_hwmod = {
 	.flags		= HWMOD_NO_IDLEST,
 };
 
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_mailbox_hwmod_class = {
+	.name = "mailbox",
+	.sysc = &omap2420_mailbox_sysc,
+};
+
+/* mailbox */
+static struct omap_hwmod omap2420_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
+	{ .name = "dsp", .irq = 26 },
+	{ .name = "iva", .irq = 34 },
+};
+
+static struct omap_hwmod_addr_space omap2420_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x480941ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap2420_l4_core__mailbox = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mailbox_hwmod,
+	.addr		= omap2420_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap2420_mailbox_slaves[] = {
+	&omap2420_l4_core__mailbox,
+};
+
+static struct omap_hwmod omap2420_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap2420_mailbox_hwmod_class,
+	.mpu_irqs	= omap2420_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mailbox_irqs),
+	.main_clk	= "mailboxes_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_mcspi_class = {
+	.name = "mcspi",
+	.sysc = &omap2420_mcspi_sysc,
+	.rev = OMAP2_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod_irq_info omap2420_mcspi1_mpu_irqs[] = {
+	{ .irq = 65 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_mcspi1_slaves[] = {
+	&omap2420_l4_core__mcspi1,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+	.num_chipselect = 4,
+};
+
+static struct omap_hwmod omap2420_mcspi1_hwmod = {
+	.name		= "mcspi1_hwmod",
+	.mpu_irqs	= omap2420_mcspi1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcspi1_mpu_irqs),
+	.sdma_reqs	= omap2420_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi1_slaves),
+	.class		= &omap2420_mcspi_class,
+	.dev_attr       = &omap_mcspi1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* mcspi2 */
+static struct omap_hwmod_irq_info omap2420_mcspi2_mpu_irqs[] = {
+	{ .irq = 66 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_mcspi2_slaves[] = {
+	&omap2420_l4_core__mcspi2,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap2420_mcspi2_hwmod = {
+	.name		= "mcspi2_hwmod",
+	.mpu_irqs	= omap2420_mcspi2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcspi2_mpu_irqs),
+	.sdma_reqs	= omap2420_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi2_slaves),
+	.class		= &omap2420_mcspi_class,
+	.dev_attr       = &omap_mcspi2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
+	.name = "mcbsp",
+};
+
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
+	{ .name = "tx", .irq = 59 },
+	{ .name = "rx", .irq = 60 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcbsp1_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
+};
+
+static struct omap_hwmod_addr_space omap2420_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp1 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcbsp1_hwmod,
+	.clk		= "mcbsp1_ick",
+	.addr		= omap2420_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcbsp1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap2420_mcbsp1_slaves[] = {
+	&omap2420_l4_core__mcbsp1,
+};
+
+static struct omap_hwmod omap2420_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap2420_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2420_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcbsp1_irqs),
+	.sdma_reqs	= omap2420_mcbsp1_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcbsp1_sdma_chs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCBSP1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
+	{ .name = "tx", .irq = 62 },
+	{ .name = "rx", .irq = 63 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcbsp2_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
+};
+
+static struct omap_hwmod_addr_space omap2420_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48076000,
+		.pa_end		= 0x480760ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcbsp2_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap2420_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcbsp2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap2420_mcbsp2_slaves[] = {
+	&omap2420_l4_core__mcbsp2,
+};
+
+static struct omap_hwmod omap2420_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap2420_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2420_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcbsp2_irqs),
+	.sdma_reqs	= omap2420_mcbsp2_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcbsp2_sdma_chs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCBSP2_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
 	&omap2420_l4_wkup_hwmod,
 	&omap2420_mpu_hwmod,
 	&omap2420_iva_hwmod,
+
+	&omap2420_timer1_hwmod,
+	&omap2420_timer2_hwmod,
+	&omap2420_timer3_hwmod,
+	&omap2420_timer4_hwmod,
+	&omap2420_timer5_hwmod,
+	&omap2420_timer6_hwmod,
+	&omap2420_timer7_hwmod,
+	&omap2420_timer8_hwmod,
+	&omap2420_timer9_hwmod,
+	&omap2420_timer10_hwmod,
+	&omap2420_timer11_hwmod,
+	&omap2420_timer12_hwmod,
+
 	&omap2420_wd_timer2_hwmod,
 	&omap2420_uart1_hwmod,
 	&omap2420_uart2_hwmod,
 	&omap2420_uart3_hwmod,
+	/* dss class */
+	&omap2420_dss_core_hwmod,
+	&omap2420_dss_dispc_hwmod,
+	&omap2420_dss_rfbi_hwmod,
+	&omap2420_dss_venc_hwmod,
+	/* i2c class */
 	&omap2420_i2c1_hwmod,
 	&omap2420_i2c2_hwmod,
 
@@ -885,10 +2178,21 @@ static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 
 	/* dma_system class*/
 	&omap2420_dma_system_hwmod,
+
+	/* mailbox class */
+	&omap2420_mailbox_hwmod,
+
+	/* mcbsp class */
+	&omap2420_mcbsp1_hwmod,
+	&omap2420_mcbsp2_hwmod,
+
+	/* mcspi class */
+	&omap2420_mcspi1_hwmod,
+	&omap2420_mcspi2_hwmod,
 	NULL,
 };
 
 int __init omap2420_hwmod_init(void)
 {
-	return omap_hwmod_init(omap2420_hwmods);
+	return omap_hwmod_register(omap2420_hwmods);
 }
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 8ecfbcd..0fdf2ca 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -18,6 +18,11 @@
 #include <plat/serial.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
+#include <plat/mcbsp.h>
+#include <plat/mcspi.h>
+#include <plat/dmtimer.h>
+#include <plat/mmc.h>
+#include <plat/l3_2xxx.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -38,6 +43,10 @@ static struct omap_hwmod omap2430_mpu_hwmod;
 static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_dss_core_hwmod;
+static struct omap_hwmod omap2430_dss_dispc_hwmod;
+static struct omap_hwmod omap2430_dss_rfbi_hwmod;
+static struct omap_hwmod omap2430_dss_venc_hwmod;
 static struct omap_hwmod omap2430_wd_timer2_hwmod;
 static struct omap_hwmod omap2430_gpio1_hwmod;
 static struct omap_hwmod omap2430_gpio2_hwmod;
@@ -45,6 +54,16 @@ static struct omap_hwmod omap2430_gpio3_hwmod;
 static struct omap_hwmod omap2430_gpio4_hwmod;
 static struct omap_hwmod omap2430_gpio5_hwmod;
 static struct omap_hwmod omap2430_dma_system_hwmod;
+static struct omap_hwmod omap2430_mcbsp1_hwmod;
+static struct omap_hwmod omap2430_mcbsp2_hwmod;
+static struct omap_hwmod omap2430_mcbsp3_hwmod;
+static struct omap_hwmod omap2430_mcbsp4_hwmod;
+static struct omap_hwmod omap2430_mcbsp5_hwmod;
+static struct omap_hwmod omap2430_mcspi1_hwmod;
+static struct omap_hwmod omap2430_mcspi2_hwmod;
+static struct omap_hwmod omap2430_mcspi3_hwmod;
+static struct omap_hwmod omap2430_mmc1_hwmod;
+static struct omap_hwmod omap2430_mmc2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -65,6 +84,19 @@ static struct omap_hwmod_ocp_if *omap2430_l3_main_slaves[] = {
 	&omap2430_mpu__l3_main,
 };
 
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap2430_dss__l3 = {
+	.master		= &omap2430_dss_core_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.fw = {
+		.omap2 = {
+			.l3_perm_bit  = OMAP2_L3_CORE_FW_CONNID_DSS,
+			.flags	= OMAP_FIREWALL_L3,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Master interfaces on the L3 interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l3_main_masters[] = {
 	&omap2430_l3_main__l4_core,
@@ -89,6 +121,16 @@ static struct omap_hwmod omap2430_uart3_hwmod;
 static struct omap_hwmod omap2430_i2c1_hwmod;
 static struct omap_hwmod omap2430_i2c2_hwmod;
 
+static struct omap_hwmod omap2430_usbhsotg_hwmod;
+
+/* l3_core -> usbhsotg  interface */
+static struct omap_hwmod_ocp_if omap2430_usbhsotg__l3 = {
+	.master		= &omap2430_usbhsotg_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.clk		= "core_l3_ck",
+	.user		= OCP_USER_MPU,
+};
+
 /* I2C IP block address space length (in bytes) */
 #define OMAP2_I2C_AS_LEN		128
 
@@ -189,6 +231,71 @@ static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/*
+* usbhsotg interface data
+*/
+static struct omap_hwmod_addr_space omap2430_usbhsotg_addrs[] = {
+	{
+		.pa_start	= OMAP243X_HS_BASE,
+		.pa_end		= OMAP243X_HS_BASE + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/*  l4_core ->usbhsotg  interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__usbhsotg = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_usbhsotg_hwmod,
+	.clk		= "usb_l4_ick",
+	.addr		= omap2430_usbhsotg_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_usbhsotg_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if *omap2430_usbhsotg_masters[] = {
+	&omap2430_usbhsotg__l3,
+};
+
+static struct omap_hwmod_ocp_if *omap2430_usbhsotg_slaves[] = {
+	&omap2430_l4_core__usbhsotg,
+};
+
+/* L4 CORE -> MMC1 interface */
+static struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mmc1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mmc1_hwmod,
+	.clk		= "mmchs1_ick",
+	.addr		= omap2430_mmc1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mmc1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> MMC2 interface */
+static struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b41ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mmc2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mmc2_hwmod,
+	.addr		= omap2430_mmc2_addr_space,
+	.clk		= "mmchs2_ick",
+	.addr_cnt	= ARRAY_SIZE(omap2430_mmc2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
 	&omap2430_l3_main__l4_core,
@@ -197,6 +304,8 @@ static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_masters[] = {
 	&omap2430_l4_core__l4_wkup,
+	&omap2430_l4_core__mmc1,
+	&omap2430_l4_core__mmc2,
 };
 
 /* L4 CORE */
@@ -223,6 +332,60 @@ static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = {
 static struct omap_hwmod_ocp_if *omap2430_l4_wkup_masters[] = {
 };
 
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_addr_space omap2430_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480980ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcspi1_hwmod,
+	.clk		= "mcspi1_ick",
+	.addr		= omap2430_mcspi1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_addr_space omap2430_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcspi2_hwmod,
+	.clk		= "mcspi2_ick",
+	.addr		= omap2430_mcspi2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi3 interface */
+static struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b80ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcspi3_hwmod,
+	.clk		= "mcspi3_ick",
+	.addr		= omap2430_mcspi3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* L4 WKUP */
 static struct omap_hwmod omap2430_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
@@ -278,645 +441,2227 @@ static struct omap_hwmod omap2430_iva_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
-	{
-		.pa_start	= 0x49016000,
-		.pa_end		= 0x4901607f,
-		.flags		= ADDR_TYPE_RT
-	},
+/* Timer Common */
+static struct omap_hwmod_class_sysconfig omap2430_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
-	.master		= &omap2430_l4_wkup_hwmod,
-	.slave		= &omap2430_wd_timer2_hwmod,
-	.clk		= "mpu_wdt_ick",
-	.addr		= omap2430_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_wd_timer2_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_class omap2430_timer_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap2430_timer_sysc,
+	.rev = OMAP_TIMER_IP_VERSION_1,
 };
 
-/*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
- */
+/* timer1 */
+static struct omap_hwmod omap2430_timer1_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
+};
 
-static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
-	.rev_offs	= 0x0,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
+	{
+		.pa_start	= 0x49018000,
+		.pa_end		= 0x49018000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
-	.name		= "wd_timer",
-	.sysc		= &omap2430_wd_timer_sysc,
-	.pre_shutdown	= &omap2_wd_timer_disable
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__timer1 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_timer1_hwmod,
+	.clk		= "gpt1_ick",
+	.addr		= omap2430_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* wd_timer2 */
-static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
-	&omap2430_l4_wkup__wd_timer2,
+/* timer1 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer1_slaves[] = {
+	&omap2430_l4_wkup__timer1,
 };
 
-static struct omap_hwmod omap2430_wd_timer2_hwmod = {
-	.name		= "wd_timer2",
-	.class		= &omap2430_wd_timer_hwmod_class,
-	.main_clk	= "mpu_wdt_fck",
+/* timer1 hwmod */
+static struct omap_hwmod omap2430_timer1_hwmod = {
+	.name		= "timer1",
+	.mpu_irqs	= omap2430_timer1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer1_mpu_irqs),
+	.main_clk	= "gpt1_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+			.module_bit = OMAP24XX_EN_GPT1_SHIFT,
 			.module_offs = WKUP_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
 		},
 	},
-	.slaves		= omap2430_wd_timer2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-};
-
-/* UART */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
-	.rev_offs	= 0x50,
-	.sysc_offs	= 0x54,
-	.syss_offs	= 0x58,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+	.slaves		= omap2430_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-static struct omap_hwmod_class uart_class = {
-	.name = "uart",
-	.sysc = &uart_sysc,
+/* timer2 */
+static struct omap_hwmod omap2430_timer2_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
 };
 
-/* UART1 */
-
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
+static struct omap_hwmod_addr_space omap2430_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4802a000,
+		.pa_end		= 0x4802a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+/* l4_core -> timer2 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer2_hwmod,
+	.clk		= "gpt2_ick",
+	.addr		= omap2430_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
-	&omap2_l4_core__uart1,
+/* timer2 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer2_slaves[] = {
+	&omap2430_l4_core__timer2,
 };
 
-static struct omap_hwmod omap2430_uart1_hwmod = {
-	.name		= "uart1",
-	.mpu_irqs	= uart1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
-	.sdma_reqs	= uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
-	.main_clk	= "uart1_fck",
+/* timer2 hwmod */
+static struct omap_hwmod omap2430_timer2_hwmod = {
+	.name		= "timer2",
+	.mpu_irqs	= omap2430_timer2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer2_mpu_irqs),
+	.main_clk	= "gpt2_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_UART1_SHIFT,
+			.module_bit = OMAP24XX_EN_GPT2_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
 		},
 	},
-	.slaves		= omap2430_uart1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.slaves		= omap2430_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* UART2 */
+/* timer3 */
+static struct omap_hwmod omap2430_timer3_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+};
 
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
+static struct omap_hwmod_addr_space omap2430_timer3_addrs[] = {
+	{
+		.pa_start	= 0x48078000,
+		.pa_end		= 0x48078000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+/* l4_core -> timer3 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer3_hwmod,
+	.clk		= "gpt3_ick",
+	.addr		= omap2430_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
-	&omap2_l4_core__uart2,
+/* timer3 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer3_slaves[] = {
+	&omap2430_l4_core__timer3,
 };
 
-static struct omap_hwmod omap2430_uart2_hwmod = {
-	.name		= "uart2",
-	.mpu_irqs	= uart2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
-	.sdma_reqs	= uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
-	.main_clk	= "uart2_fck",
+/* timer3 hwmod */
+static struct omap_hwmod omap2430_timer3_hwmod = {
+	.name		= "timer3",
+	.mpu_irqs	= omap2430_timer3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer3_mpu_irqs),
+	.main_clk	= "gpt3_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_UART2_SHIFT,
+			.module_bit = OMAP24XX_EN_GPT3_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
 		},
 	},
-	.slaves		= omap2430_uart2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.slaves		= omap2430_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* UART3 */
+/* timer4 */
+static struct omap_hwmod omap2430_timer4_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+};
 
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
+static struct omap_hwmod_addr_space omap2430_timer4_addrs[] = {
+	{
+		.pa_start	= 0x4807a000,
+		.pa_end		= 0x4807a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+/* l4_core -> timer4 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer4 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer4_hwmod,
+	.clk		= "gpt4_ick",
+	.addr		= omap2430_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
-	&omap2_l4_core__uart3,
+/* timer4 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer4_slaves[] = {
+	&omap2430_l4_core__timer4,
 };
 
-static struct omap_hwmod omap2430_uart3_hwmod = {
-	.name		= "uart3",
-	.mpu_irqs	= uart3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
-	.sdma_reqs	= uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
-	.main_clk	= "uart3_fck",
+/* timer4 hwmod */
+static struct omap_hwmod omap2430_timer4_hwmod = {
+	.name		= "timer4",
+	.mpu_irqs	= omap2430_timer4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer4_mpu_irqs),
+	.main_clk	= "gpt4_fck",
 	.prcm		= {
 		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT4_SHIFT,
 			.module_offs = CORE_MOD,
-			.prcm_reg_id = 2,
-			.module_bit = OMAP24XX_EN_UART3_SHIFT,
-			.idlest_reg_id = 2,
-			.idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
 		},
 	},
-	.slaves		= omap2430_uart3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.slaves		= omap2430_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* I2C common */
-static struct omap_hwmod_class_sysconfig i2c_sysc = {
-	.rev_offs	= 0x00,
-	.sysc_offs	= 0x20,
-	.syss_offs	= 0x10,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
+/* timer5 */
+static struct omap_hwmod omap2430_timer5_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
 };
 
-static struct omap_hwmod_class i2c_class = {
-	.name		= "i2c",
-	.sysc		= &i2c_sysc,
+static struct omap_hwmod_addr_space omap2430_timer5_addrs[] = {
+	{
+		.pa_start	= 0x4807c000,
+		.pa_end		= 0x4807c000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_i2c_dev_attr i2c_dev_attr = {
-	.fifo_depth	= 8, /* bytes */
+/* l4_core -> timer5 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer5 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer5_hwmod,
+	.clk		= "gpt5_ick",
+	.addr		= omap2430_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* I2C1 */
-
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C1_IRQ, },
+/* timer5 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer5_slaves[] = {
+	&omap2430_l4_core__timer5,
 };
 
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+/* timer5 hwmod */
+static struct omap_hwmod omap2430_timer5_hwmod = {
+	.name		= "timer5",
+	.mpu_irqs	= omap2430_timer5_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer5_mpu_irqs),
+	.main_clk	= "gpt5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
-	&omap2430_l4_core__i2c1,
+/* timer6 */
+static struct omap_hwmod omap2430_timer6_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
 };
 
-static struct omap_hwmod omap2430_i2c1_hwmod = {
-	.name		= "i2c1",
-	.mpu_irqs	= i2c1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
-	.sdma_reqs	= i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
-	.main_clk	= "i2chs1_fck",
+static struct omap_hwmod_addr_space omap2430_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4807e000,
+		.pa_end		= 0x4807e000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer6 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer6 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer6_hwmod,
+	.clk		= "gpt6_ick",
+	.addr		= omap2430_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer6 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer6_slaves[] = {
+	&omap2430_l4_core__timer6,
+};
+
+/* timer6 hwmod */
+static struct omap_hwmod omap2430_timer6_hwmod = {
+	.name		= "timer6",
+	.mpu_irqs	= omap2430_timer6_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer6_mpu_irqs),
+	.main_clk	= "gpt6_fck",
 	.prcm		= {
 		.omap2 = {
-			/*
-			 * NOTE: The CM_FCLKEN* and CM_ICLKEN* for
-			 * I2CHS IP's do not follow the usual pattern.
-			 * prcm_reg_id alone cannot be used to program
-			 * the iclk and fclk. Needs to be handled using
-			 * additonal flags when clk handling is moved
-			 * to hwmod framework.
-			 */
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP2430_EN_I2CHS1_SHIFT,
+			.module_bit = OMAP24XX_EN_GPT6_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP2430_ST_I2CHS1_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
 		},
 	},
-	.slaves		= omap2430_i2c1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c1_slaves),
-	.class		= &i2c_class,
-	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.slaves		= omap2430_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* I2C2 */
+/* timer7 */
+static struct omap_hwmod omap2430_timer7_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
+};
 
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C2_IRQ, },
+static struct omap_hwmod_addr_space omap2430_timer7_addrs[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+/* l4_core -> timer7 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer7 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer7_hwmod,
+	.clk		= "gpt7_ick",
+	.addr		= omap2430_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer7_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
-	&omap2430_l4_core__i2c2,
+/* timer7 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer7_slaves[] = {
+	&omap2430_l4_core__timer7,
 };
 
-static struct omap_hwmod omap2430_i2c2_hwmod = {
-	.name		= "i2c2",
-	.mpu_irqs	= i2c2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
-	.sdma_reqs	= i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
-	.main_clk	= "i2chs2_fck",
+/* timer7 hwmod */
+static struct omap_hwmod omap2430_timer7_hwmod = {
+	.name		= "timer7",
+	.mpu_irqs	= omap2430_timer7_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer7_mpu_irqs),
+	.main_clk	= "gpt7_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP2430_EN_I2CHS2_SHIFT,
+			.module_bit = OMAP24XX_EN_GPT7_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP2430_ST_I2CHS2_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
 		},
 	},
-	.slaves		= omap2430_i2c2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c2_slaves),
-	.class		= &i2c_class,
-	.dev_attr	= &i2c_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.slaves		= omap2430_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
+/* timer8 */
+static struct omap_hwmod omap2430_timer8_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer8_addrs[] = {
 	{
-		.pa_start	= 0x4900C000,
-		.pa_end		= 0x4900C1ff,
+		.pa_start	= 0x48082000,
+		.pa_end		= 0x48082000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
-	.master		= &omap2430_l4_wkup_hwmod,
-	.slave		= &omap2430_gpio1_hwmod,
-	.clk		= "gpios_ick",
-	.addr		= omap2430_gpio1_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio1_addr_space),
+/* l4_core -> timer8 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer8 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer8_hwmod,
+	.clk		= "gpt8_ick",
+	.addr		= omap2430_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer8_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_wkup -> gpio2 */
-static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
+/* timer8 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer8_slaves[] = {
+	&omap2430_l4_core__timer8,
+};
+
+/* timer8 hwmod */
+static struct omap_hwmod omap2430_timer8_hwmod = {
+	.name		= "timer8",
+	.mpu_irqs	= omap2430_timer8_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer8_mpu_irqs),
+	.main_clk	= "gpt8_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT8_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer9 */
+static struct omap_hwmod omap2430_timer9_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer9_addrs[] = {
 	{
-		.pa_start	= 0x4900E000,
-		.pa_end		= 0x4900E1ff,
+		.pa_start	= 0x48084000,
+		.pa_end		= 0x48084000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
-	.master		= &omap2430_l4_wkup_hwmod,
-	.slave		= &omap2430_gpio2_hwmod,
-	.clk		= "gpios_ick",
-	.addr		= omap2430_gpio2_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio2_addr_space),
+/* l4_core -> timer9 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer9 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer9_hwmod,
+	.clk		= "gpt9_ick",
+	.addr		= omap2430_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer9_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_wkup -> gpio3 */
-static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
+/* timer9 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer9_slaves[] = {
+	&omap2430_l4_core__timer9,
+};
+
+/* timer9 hwmod */
+static struct omap_hwmod omap2430_timer9_hwmod = {
+	.name		= "timer9",
+	.mpu_irqs	= omap2430_timer9_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer9_mpu_irqs),
+	.main_clk	= "gpt9_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT9_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer10 */
+static struct omap_hwmod omap2430_timer10_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer10_addrs[] = {
 	{
-		.pa_start	= 0x49010000,
-		.pa_end		= 0x490101ff,
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
-	.master		= &omap2430_l4_wkup_hwmod,
-	.slave		= &omap2430_gpio3_hwmod,
-	.clk		= "gpios_ick",
-	.addr		= omap2430_gpio3_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio3_addr_space),
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer10 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer10_hwmod,
+	.clk		= "gpt10_ick",
+	.addr		= omap2430_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer10_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_wkup -> gpio4 */
-static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
+/* timer10 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer10_slaves[] = {
+	&omap2430_l4_core__timer10,
+};
+
+/* timer10 hwmod */
+static struct omap_hwmod omap2430_timer10_hwmod = {
+	.name		= "timer10",
+	.mpu_irqs	= omap2430_timer10_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer10_mpu_irqs),
+	.main_clk	= "gpt10_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT10_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer11 */
+static struct omap_hwmod omap2430_timer11_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer11_addrs[] = {
 	{
-		.pa_start	= 0x49012000,
-		.pa_end		= 0x490121ff,
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
-	.master		= &omap2430_l4_wkup_hwmod,
-	.slave		= &omap2430_gpio4_hwmod,
-	.clk		= "gpios_ick",
-	.addr		= omap2430_gpio4_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio4_addr_space),
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer11 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer11_hwmod,
+	.clk		= "gpt11_ick",
+	.addr		= omap2430_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer11_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_core -> gpio5 */
-static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
+/* timer11 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer11_slaves[] = {
+	&omap2430_l4_core__timer11,
+};
+
+/* timer11 hwmod */
+static struct omap_hwmod omap2430_timer11_hwmod = {
+	.name		= "timer11",
+	.mpu_irqs	= omap2430_timer11_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer11_mpu_irqs),
+	.main_clk	= "gpt11_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT11_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer12 */
+static struct omap_hwmod omap2430_timer12_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer12_mpu_irqs[] = {
+	{ .irq = 48, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer12_addrs[] = {
 	{
-		.pa_start	= 0x480B6000,
-		.pa_end		= 0x480B61ff,
+		.pa_start	= 0x4808a000,
+		.pa_end		= 0x4808a000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer12 = {
 	.master		= &omap2430_l4_core_hwmod,
-	.slave		= &omap2430_gpio5_hwmod,
-	.clk		= "gpio5_ick",
-	.addr		= omap2430_gpio5_addr_space,
-	.addr_cnt	= ARRAY_SIZE(omap2430_gpio5_addr_space),
+	.slave		= &omap2430_timer12_hwmod,
+	.clk		= "gpt12_ick",
+	.addr		= omap2430_timer12_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer12_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer12 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer12_slaves[] = {
+	&omap2430_l4_core__timer12,
+};
+
+/* timer12 hwmod */
+static struct omap_hwmod omap2430_timer12_hwmod = {
+	.name		= "timer12",
+	.mpu_irqs	= omap2430_timer12_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer12_mpu_irqs),
+	.main_clk	= "gpt12_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT12_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer12_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x49016000,
+		.pa_end		= 0x4901607f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_wd_timer2_hwmod,
+	.clk		= "mpu_wdt_ick",
+	.addr		= omap2430_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_wd_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* gpio dev_attr */
-static struct omap_gpio_dev_attr gpio_dev_attr = {
-	.bank_width = 32,
-	.dbck_flag = false,
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
+	.rev_offs	= 0x0,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
+	.name		= "wd_timer",
+	.sysc		= &omap2430_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
+	&omap2430_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2430_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap2430_wd_timer_hwmod_class,
+	.main_clk	= "mpu_wdt_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+		},
+	},
+	.slaves		= omap2430_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_wd_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+	.name = "uart",
+	.sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
+	&omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2430_uart1_hwmod = {
+	.name		= "uart1",
+	.mpu_irqs	= uart1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
+	.sdma_reqs	= uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_uart1_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
+	&omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2430_uart2_hwmod = {
+	.name		= "uart2",
+	.mpu_irqs	= uart2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
+	.sdma_reqs	= uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_UART2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_uart2_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
+	&omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2430_uart3_hwmod = {
+	.name		= "uart3",
+	.mpu_irqs	= uart3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
+	.sdma_reqs	= uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit = OMAP24XX_EN_UART3_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+		},
+	},
+	.slaves		= omap2430_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_uart3_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dss_hwmod_class = {
+	.name = "dss",
+	.sysc = &omap2430_dss_sysc,
+};
+
+/* dss */
+static struct omap_hwmod_irq_info omap2430_dss_irqs[] = {
+	{ .irq = 25 },
+};
+static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_masters[] = {
+	&omap2430_dss__l3,
+};
+
+static struct omap_hwmod_addr_space omap2430_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x480503FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2430_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
+	&omap2430_l4_core__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+	{ .role = "sys_clk", .clk = "dss2_fck" },
+};
+
+static struct omap_hwmod omap2430_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap2430_dss_hwmod_class,
+	.main_clk	= "dss1_fck", /* instead of dss_fck */
+	.mpu_irqs	= omap2430_dss_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dss_irqs),
+	.sdma_reqs	= omap2430_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_dss_sdma_chs),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap2430_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_slaves),
+	.masters	= omap2430_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dispc_hwmod_class = {
+	.name = "dispc",
+	.sysc = &omap2430_dispc_sysc,
+};
+
+static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x480507FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss_dispc = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_dispc_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2430_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_dispc_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
+	&omap2430_l4_core__dss_dispc,
+};
+
+static struct omap_hwmod omap2430_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap2430_dispc_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_dispc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_rfbi_hwmod_class = {
+	.name = "rfbi",
+	.sysc = &omap2430_rfbi_sysc,
+};
+
+static struct omap_hwmod_addr_space omap2430_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050BFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss_rfbi = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_rfbi_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2430_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
+	&omap2430_l4_core__dss_rfbi,
+};
+
+static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap2430_rfbi_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+		},
+	},
+	.slaves		= omap2430_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap2430_venc_hwmod_class = {
+	.name = "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod_addr_space omap2430_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_venc_hwmod,
+	.clk		= "dss_54m_fck",
+	.addr		= omap2430_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_venc_addrs),
+	.flags		= OCPIF_SWSUP_IDLE,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
+	&omap2430_l4_core__dss_venc,
+};
+
+static struct omap_hwmod omap2430_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap2430_venc_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+		},
+	},
+	.slaves		= omap2430_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/* I2C common */
+static struct omap_hwmod_class_sysconfig i2c_sysc = {
+	.rev_offs	= 0x00,
+	.sysc_offs	= 0x20,
+	.syss_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class i2c_class = {
+	.name		= "i2c",
+	.sysc		= &i2c_sysc,
+};
+
+static struct omap_i2c_dev_attr i2c_dev_attr = {
+	.fifo_depth	= 8, /* bytes */
+};
+
+/* I2C1 */
+
+static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_i2c1_slaves[] = {
+	&omap2430_l4_core__i2c1,
+};
+
+static struct omap_hwmod omap2430_i2c1_hwmod = {
+	.name		= "i2c1",
+	.mpu_irqs	= i2c1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
+	.sdma_reqs	= i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.main_clk	= "i2chs1_fck",
+	.prcm		= {
+		.omap2 = {
+			/*
+			 * NOTE: The CM_FCLKEN* and CM_ICLKEN* for
+			 * I2CHS IP's do not follow the usual pattern.
+			 * prcm_reg_id alone cannot be used to program
+			 * the iclk and fclk. Needs to be handled using
+			 * additonal flags when clk handling is moved
+			 * to hwmod framework.
+			 */
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_I2CHS1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2430_ST_I2CHS1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_i2c1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c1_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* I2C2 */
+
+static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_i2c2_slaves[] = {
+	&omap2430_l4_core__i2c2,
+};
+
+static struct omap_hwmod omap2430_i2c2_hwmod = {
+	.name		= "i2c2",
+	.mpu_irqs	= i2c2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
+	.sdma_reqs	= i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.main_clk	= "i2chs2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_I2CHS2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2430_ST_I2CHS2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_i2c2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_i2c2_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_addr_space omap2430_gpio1_addr_space[] = {
+	{
+		.pa_start	= 0x4900C000,
+		.pa_end		= 0x4900C1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio1 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio1_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio2 */
+static struct omap_hwmod_addr_space omap2430_gpio2_addr_space[] = {
+	{
+		.pa_start	= 0x4900E000,
+		.pa_end		= 0x4900E1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio2 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio2_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio3 */
+static struct omap_hwmod_addr_space omap2430_gpio3_addr_space[] = {
+	{
+		.pa_start	= 0x49010000,
+		.pa_end		= 0x490101ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio3 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio3_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup -> gpio4 */
+static struct omap_hwmod_addr_space omap2430_gpio4_addr_space[] = {
+	{
+		.pa_start	= 0x49012000,
+		.pa_end		= 0x490121ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__gpio4 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_gpio4_hwmod,
+	.clk		= "gpios_ick",
+	.addr		= omap2430_gpio4_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio4_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_core -> gpio5 */
+static struct omap_hwmod_addr_space omap2430_gpio5_addr_space[] = {
+	{
+		.pa_start	= 0x480B6000,
+		.pa_end		= 0x480B61ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__gpio5 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_gpio5_hwmod,
+	.clk		= "gpio5_ick",
+	.addr		= omap2430_gpio5_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_gpio5_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio dev_attr */
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width = 32,
+	.dbck_flag = false,
+};
+
+static struct omap_hwmod_class_sysconfig omap243x_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+static struct omap_hwmod_class omap243x_gpio_hwmod_class = {
+	.name = "gpio",
+	.sysc = &omap243x_gpio_sysc,
+	.rev = 0,
+};
+
+/* gpio1 */
+static struct omap_hwmod_irq_info omap243x_gpio1_irqs[] = {
+	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
+	&omap2430_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod omap2430_gpio1_hwmod = {
+	.name		= "gpio1",
+	.mpu_irqs	= omap243x_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio1_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_EN_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio2 */
+static struct omap_hwmod_irq_info omap243x_gpio2_irqs[] = {
+	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
+	&omap2430_l4_wkup__gpio2,
+};
+
+static struct omap_hwmod omap2430_gpio2_hwmod = {
+	.name		= "gpio2",
+	.mpu_irqs	= omap243x_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio2_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio3 */
+static struct omap_hwmod_irq_info omap243x_gpio3_irqs[] = {
+	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
+	&omap2430_l4_wkup__gpio3,
+};
+
+static struct omap_hwmod omap2430_gpio3_hwmod = {
+	.name		= "gpio3",
+	.mpu_irqs	= omap243x_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio3_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio4 */
+static struct omap_hwmod_irq_info omap243x_gpio4_irqs[] = {
+	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
+	&omap2430_l4_wkup__gpio4,
+};
+
+static struct omap_hwmod omap2430_gpio4_hwmod = {
+	.name		= "gpio4",
+	.mpu_irqs	= omap243x_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio4_irqs),
+	.main_clk	= "gpios_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* gpio5 */
+static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
+	{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
+	&omap2430_l4_core__gpio5,
+};
+
+static struct omap_hwmod omap2430_gpio5_hwmod = {
+	.name		= "gpio5",
+	.mpu_irqs	= omap243x_gpio5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio5_irqs),
+	.main_clk	= "gpio5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 2,
+			.module_bit = OMAP2430_EN_GPIO5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_GPIO5_SHIFT,
+		},
+	},
+	.slaves		= omap2430_gpio5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
+	.class		= &omap243x_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* dma_system */
+static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap2430_dma_sysc,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
+	.master		= &omap2430_dma_system_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.clk		= "core_l3_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = {
+	&omap2430_dma_system__l3,
+};
+
+/* l4_core -> dma_system */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dma_system_hwmod,
+	.clk		= "sdma_ick",
+	.addr		= omap2430_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
+	&omap2430_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap2430_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap2430_dma_hwmod_class,
+	.mpu_irqs	= omap2430_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dma_system_irqs),
+	.main_clk	= "core_l3_ck",
+	.slaves		= omap2430_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
+	.masters	= omap2430_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mailbox_hwmod_class = {
+	.name = "mailbox",
+	.sysc = &omap2430_mailbox_sysc,
+};
+
+/* mailbox */
+static struct omap_hwmod omap2430_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
+	{ .irq = 26 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x480941ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mailbox = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mailbox_hwmod,
+	.addr		= omap2430_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mailbox_slaves[] = {
+	&omap2430_l4_core__mailbox,
+};
+
+static struct omap_hwmod omap2430_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap2430_mailbox_hwmod_class,
+	.mpu_irqs	= omap2430_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mailbox_irqs),
+	.main_clk	= "mailboxes_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mcspi_class = {
+	.name = "mcspi",
+	.sysc = &omap2430_mcspi_sysc,
+	.rev = OMAP2_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod_irq_info omap2430_mcspi1_mpu_irqs[] = {
+	{ .irq = 65 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mcspi1_slaves[] = {
+	&omap2430_l4_core__mcspi1,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+	.num_chipselect = 4,
+};
+
+static struct omap_hwmod omap2430_mcspi1_hwmod = {
+	.name		= "mcspi1_hwmod",
+	.mpu_irqs	= omap2430_mcspi1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi1_mpu_irqs),
+	.sdma_reqs	= omap2430_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi1_slaves),
+	.class		= &omap2430_mcspi_class,
+	.dev_attr       = &omap_mcspi1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcspi2 */
+static struct omap_hwmod_irq_info omap2430_mcspi2_mpu_irqs[] = {
+	{ .irq = 66 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mcspi2_slaves[] = {
+	&omap2430_l4_core__mcspi2,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap2430_mcspi2_hwmod = {
+	.name		= "mcspi2_hwmod",
+	.mpu_irqs	= omap2430_mcspi2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi2_mpu_irqs),
+	.sdma_reqs	= omap2430_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi2_slaves),
+	.class		= &omap2430_mcspi_class,
+	.dev_attr       = &omap_mcspi2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcspi3 */
+static struct omap_hwmod_irq_info omap2430_mcspi3_mpu_irqs[] = {
+	{ .irq = 91 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 15 }, /* DMA_SPI3_TX0 */
+	{ .name = "rx0", .dma_req = 16 }, /* DMA_SPI3_RX0 */
+	{ .name = "tx1", .dma_req = 23 }, /* DMA_SPI3_TX1 */
+	{ .name = "rx1", .dma_req = 24 }, /* DMA_SPI3_RX1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mcspi3_slaves[] = {
+	&omap2430_l4_core__mcspi3,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap2430_mcspi3_hwmod = {
+	.name		= "mcspi3_hwmod",
+	.mpu_irqs	= omap2430_mcspi3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi3_mpu_irqs),
+	.sdma_reqs	= omap2430_mcspi3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi3_sdma_reqs),
+	.main_clk	= "mcspi3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit = OMAP2430_EN_MCSPI3_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCSPI3_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcspi3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi3_slaves),
+	.class		= &omap2430_mcspi_class,
+	.dev_attr       = &omap_mcspi3_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/*
+ * usbhsotg
+ */
+static struct omap_hwmod_class_sysconfig omap2430_usbhsotg_sysc = {
+	.rev_offs	= 0x0400,
+	.sysc_offs	= 0x0404,
+	.syss_offs	= 0x0408,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE|
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class usbotg_class = {
+	.name = "usbotg",
+	.sysc = &omap2430_usbhsotg_sysc,
+};
+
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info omap2430_usbhsotg_mpu_irqs[] = {
+
+	{ .name = "mc", .irq = 92 },
+	{ .name = "dma", .irq = 93 },
+};
+
+static struct omap_hwmod omap2430_usbhsotg_hwmod = {
+	.name		= "usb_otg_hs",
+	.mpu_irqs	= omap2430_usbhsotg_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_usbhsotg_mpu_irqs),
+	.main_clk	= "usbhs_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_USBHS_MASK,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2430_ST_USBHS_SHIFT,
+		},
+	},
+	.masters	= omap2430_usbhsotg_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_usbhsotg_masters),
+	.slaves		= omap2430_usbhsotg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_usbhsotg_slaves),
+	.class		= &usbotg_class,
+	/*
+	 * Erratum ID: i479  idle_req / idle_ack mechanism potentially
+	 * broken when autoidle is enabled
+	 * workaround is to disable the autoidle bit at module level.
+	 */
+	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
+				| HWMOD_SWSUP_MSTANDBY,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_mcbsp_sysc = {
+	.rev_offs	= 0x007C,
+	.sysc_offs	= 0x008C,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mcbsp_hwmod_class = {
+	.name = "mcbsp",
+	.sysc = &omap2430_mcbsp_sysc,
+	.rev  = MCBSP_CONFIG_TYPE2,
+};
+
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
+	{ .name = "tx",		.irq = 59 },
+	{ .name = "rx",		.irq = 60 },
+	{ .name = "ovr",	.irq = 61 },
+	{ .name = "common",	.irq = 64 },
 };
 
-static struct omap_hwmod_class_sysconfig omap243x_gpio_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+static struct omap_hwmod_dma_info omap2430_mcbsp1_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
 };
 
-/*
- * 'gpio' class
- * general purpose io module
- */
-static struct omap_hwmod_class omap243x_gpio_hwmod_class = {
-	.name = "gpio",
-	.sysc = &omap243x_gpio_sysc,
-	.rev = 0,
+static struct omap_hwmod_addr_space omap2430_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-/* gpio1 */
-static struct omap_hwmod_irq_info omap243x_gpio1_irqs[] = {
-	{ .irq = 29 }, /* INT_24XX_GPIO_BANK1 */
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp1_hwmod,
+	.clk		= "mcbsp1_ick",
+	.addr		= omap2430_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
-	&omap2430_l4_wkup__gpio1,
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp1_slaves[] = {
+	&omap2430_l4_core__mcbsp1,
 };
 
-static struct omap_hwmod omap2430_gpio1_hwmod = {
-	.name		= "gpio1",
-	.mpu_irqs	= omap243x_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio1_irqs),
-	.main_clk	= "gpios_fck",
+static struct omap_hwmod omap2430_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp1_irqs),
+	.sdma_reqs	= omap2430_mcbsp1_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp1_sdma_chs),
+	.main_clk	= "mcbsp1_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
-			.module_offs = WKUP_MOD,
+			.module_bit = OMAP24XX_EN_MCBSP1_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_EN_GPIOS_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
 		},
 	},
-	.slaves		= omap2430_gpio1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio1_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap2430_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* gpio2 */
-static struct omap_hwmod_irq_info omap243x_gpio2_irqs[] = {
-	{ .irq = 30 }, /* INT_24XX_GPIO_BANK2 */
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap2430_mcbsp2_irqs[] = {
+	{ .name = "tx",		.irq = 62 },
+	{ .name = "rx",		.irq = 63 },
+	{ .name = "common",	.irq = 16 },
 };
 
-static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
-	&omap2430_l4_wkup__gpio2,
+static struct omap_hwmod_dma_info omap2430_mcbsp2_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
 };
 
-static struct omap_hwmod omap2430_gpio2_hwmod = {
-	.name		= "gpio2",
-	.mpu_irqs	= omap243x_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio2_irqs),
-	.main_clk	= "gpios_fck",
+static struct omap_hwmod_addr_space omap2430_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48076000,
+		.pa_end		= 0x480760ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp2_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap2430_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp2_slaves[] = {
+	&omap2430_l4_core__mcbsp2,
+};
+
+static struct omap_hwmod omap2430_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp2_irqs),
+	.sdma_reqs	= omap2430_mcbsp2_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp2_sdma_chs),
+	.main_clk	= "mcbsp2_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
-			.module_offs = WKUP_MOD,
+			.module_bit = OMAP24XX_EN_MCBSP2_SHIFT,
+			.module_offs = CORE_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
 		},
 	},
-	.slaves		= omap2430_gpio2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio2_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap2430_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* gpio3 */
-static struct omap_hwmod_irq_info omap243x_gpio3_irqs[] = {
-	{ .irq = 31 }, /* INT_24XX_GPIO_BANK3 */
+/* mcbsp3 */
+static struct omap_hwmod_irq_info omap2430_mcbsp3_irqs[] = {
+	{ .name = "tx",		.irq = 89 },
+	{ .name = "rx",		.irq = 90 },
+	{ .name = "common",	.irq = 17 },
 };
 
-static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
-	&omap2430_l4_wkup__gpio3,
+static struct omap_hwmod_dma_info omap2430_mcbsp3_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 18 },
+	{ .name = "tx", .dma_req = 17 },
 };
 
-static struct omap_hwmod omap2430_gpio3_hwmod = {
-	.name		= "gpio3",
-	.mpu_irqs	= omap243x_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio3_irqs),
-	.main_clk	= "gpios_fck",
+static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x4808C000,
+		.pa_end		= 0x4808C0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp3_hwmod,
+	.clk		= "mcbsp3_ick",
+	.addr		= omap2430_mcbsp3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp3 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp3_slaves[] = {
+	&omap2430_l4_core__mcbsp3,
+};
+
+static struct omap_hwmod omap2430_mcbsp3_hwmod = {
+	.name		= "mcbsp3",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp3_irqs),
+	.sdma_reqs	= omap2430_mcbsp3_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp3_sdma_chs),
+	.main_clk	= "mcbsp3_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
-			.module_offs = WKUP_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+			.module_bit = OMAP2430_EN_MCBSP3_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCBSP3_SHIFT,
 		},
 	},
-	.slaves		= omap2430_gpio3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio3_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap2430_mcbsp3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp3_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* gpio4 */
-static struct omap_hwmod_irq_info omap243x_gpio4_irqs[] = {
-	{ .irq = 32 }, /* INT_24XX_GPIO_BANK4 */
+/* mcbsp4 */
+static struct omap_hwmod_irq_info omap2430_mcbsp4_irqs[] = {
+	{ .name = "tx",		.irq = 54 },
+	{ .name = "rx",		.irq = 55 },
+	{ .name = "common",	.irq = 18 },
 };
 
-static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
-	&omap2430_l4_wkup__gpio4,
+static struct omap_hwmod_dma_info omap2430_mcbsp4_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 20 },
+	{ .name = "tx", .dma_req = 19 },
 };
 
-static struct omap_hwmod omap2430_gpio4_hwmod = {
-	.name		= "gpio4",
-	.mpu_irqs	= omap243x_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio4_irqs),
-	.main_clk	= "gpios_fck",
+static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x4808E000,
+		.pa_end		= 0x4808E0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp4 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp4_hwmod,
+	.clk		= "mcbsp4_ick",
+	.addr		= omap2430_mcbsp4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp4 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp4_slaves[] = {
+	&omap2430_l4_core__mcbsp4,
+};
+
+static struct omap_hwmod omap2430_mcbsp4_hwmod = {
+	.name		= "mcbsp4",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp4_irqs),
+	.sdma_reqs	= omap2430_mcbsp4_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp4_sdma_chs),
+	.main_clk	= "mcbsp4_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP24XX_EN_GPIOS_SHIFT,
-			.module_offs = WKUP_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP24XX_ST_GPIOS_SHIFT,
+			.module_bit = OMAP2430_EN_MCBSP4_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCBSP4_SHIFT,
 		},
 	},
-	.slaves		= omap2430_gpio4_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio4_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap2430_mcbsp4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp4_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* gpio5 */
-static struct omap_hwmod_irq_info omap243x_gpio5_irqs[] = {
-	{ .irq = 33 }, /* INT_24XX_GPIO_BANK5 */
+/* mcbsp5 */
+static struct omap_hwmod_irq_info omap2430_mcbsp5_irqs[] = {
+	{ .name = "tx",		.irq = 81 },
+	{ .name = "rx",		.irq = 82 },
+	{ .name = "common",	.irq = 19 },
 };
 
-static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
-	&omap2430_l4_core__gpio5,
+static struct omap_hwmod_dma_info omap2430_mcbsp5_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 22 },
+	{ .name = "tx", .dma_req = 21 },
 };
 
-static struct omap_hwmod omap2430_gpio5_hwmod = {
-	.name		= "gpio5",
-	.mpu_irqs	= omap243x_gpio5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio5_irqs),
-	.main_clk	= "gpio5_fck",
+static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48096000,
+		.pa_end		= 0x480960ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp5 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp5_hwmod,
+	.clk		= "mcbsp5_ick",
+	.addr		= omap2430_mcbsp5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp5 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp5_slaves[] = {
+	&omap2430_l4_core__mcbsp5,
+};
+
+static struct omap_hwmod omap2430_mcbsp5_hwmod = {
+	.name		= "mcbsp5",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp5_irqs),
+	.sdma_reqs	= omap2430_mcbsp5_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp5_sdma_chs),
+	.main_clk	= "mcbsp5_fck",
 	.prcm		= {
 		.omap2 = {
-			.prcm_reg_id = 2,
-			.module_bit = OMAP2430_EN_GPIO5_SHIFT,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_MCBSP5_SHIFT,
 			.module_offs = CORE_MOD,
 			.idlest_reg_id = 2,
-			.idlest_idle_bit = OMAP2430_ST_GPIO5_SHIFT,
+			.idlest_idle_bit = OMAP2430_ST_MCBSP5_SHIFT,
 		},
 	},
-	.slaves		= omap2430_gpio5_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_gpio5_slaves),
-	.class		= &omap243x_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap2430_mcbsp5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp5_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* dma_system */
-static struct omap_hwmod_class_sysconfig omap2430_dma_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x002c,
-	.syss_offs	= 0x0028,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
-			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
+/* MMC/SD/SDIO common */
+
+static struct omap_hwmod_class_sysconfig omap2430_mmc_sysc = {
+	.rev_offs	= 0x1fc,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_class omap2430_dma_hwmod_class = {
-	.name = "dma",
-	.sysc = &omap2430_dma_sysc,
+static struct omap_hwmod_class omap2430_mmc_class = {
+	.name = "mmc",
+	.sysc = &omap2430_mmc_sysc,
 };
 
-/* dma attributes */
-static struct omap_dma_dev_attr dma_dev_attr = {
-	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
-				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
-	.lch_count = 32,
+/* MMC/SD/SDIO1 */
+
+static struct omap_hwmod_irq_info omap2430_mmc1_mpu_irqs[] = {
+	{ .irq = 83 },
 };
 
-static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
-	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
-	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
-	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+static struct omap_hwmod_dma_info omap2430_mmc1_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 61 }, /* DMA_MMC1_TX */
+	{ .name = "rx",	.dma_req = 62 }, /* DMA_MMC1_RX */
 };
 
-static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
-	{
-		.pa_start	= 0x48056000,
-		.pa_end		= 0x4a0560ff,
-		.flags		= ADDR_TYPE_RT
+static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = {
+	{ .role = "dbck", .clk = "mmchsdb1_fck" },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mmc1_slaves[] = {
+	&omap2430_l4_core__mmc1,
+};
+
+static struct omap_mmc_dev_attr mmc1_dev_attr = {
+	.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod omap2430_mmc1_hwmod = {
+	.name		= "mmc1",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap2430_mmc1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mmc1_mpu_irqs),
+	.sdma_reqs	= omap2430_mmc1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mmc1_sdma_reqs),
+	.opt_clks	= omap2430_mmc1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap2430_mmc1_opt_clks),
+	.main_clk	= "mmchs1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit  = OMAP2430_EN_MMCHS1_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MMCHS1_SHIFT,
+		},
 	},
+	.dev_attr	= &mmc1_dev_attr,
+	.slaves		= omap2430_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc1_slaves),
+	.class		= &omap2430_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-/* dma_system -> L3 */
-static struct omap_hwmod_ocp_if omap2430_dma_system__l3 = {
-	.master		= &omap2430_dma_system_hwmod,
-	.slave		= &omap2430_l3_main_hwmod,
-	.clk		= "core_l3_ck",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* MMC/SD/SDIO2 */
+
+static struct omap_hwmod_irq_info omap2430_mmc2_mpu_irqs[] = {
+	{ .irq = 86 },
 };
 
-/* dma_system master ports */
-static struct omap_hwmod_ocp_if *omap2430_dma_system_masters[] = {
-	&omap2430_dma_system__l3,
+static struct omap_hwmod_dma_info omap2430_mmc2_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 47 }, /* DMA_MMC2_TX */
+	{ .name = "rx",	.dma_req = 48 }, /* DMA_MMC2_RX */
 };
 
-/* l4_core -> dma_system */
-static struct omap_hwmod_ocp_if omap2430_l4_core__dma_system = {
-	.master		= &omap2430_l4_core_hwmod,
-	.slave		= &omap2430_dma_system_hwmod,
-	.clk		= "sdma_ick",
-	.addr		= omap2430_dma_system_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap2430_dma_system_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_opt_clk omap2430_mmc2_opt_clks[] = {
+	{ .role = "dbck", .clk = "mmchsdb2_fck" },
 };
 
-/* dma_system slave ports */
-static struct omap_hwmod_ocp_if *omap2430_dma_system_slaves[] = {
-	&omap2430_l4_core__dma_system,
+static struct omap_hwmod_ocp_if *omap2430_mmc2_slaves[] = {
+	&omap2430_l4_core__mmc2,
 };
 
-static struct omap_hwmod omap2430_dma_system_hwmod = {
-	.name		= "dma",
-	.class		= &omap2430_dma_hwmod_class,
-	.mpu_irqs	= omap2430_dma_system_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dma_system_irqs),
-	.main_clk	= "core_l3_ck",
-	.slaves		= omap2430_dma_system_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap2430_dma_system_slaves),
-	.masters	= omap2430_dma_system_masters,
-	.masters_cnt	= ARRAY_SIZE(omap2430_dma_system_masters),
-	.dev_attr	= &dma_dev_attr,
+static struct omap_hwmod omap2430_mmc2_hwmod = {
+	.name		= "mmc2",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap2430_mmc2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mmc2_mpu_irqs),
+	.sdma_reqs	= omap2430_mmc2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mmc2_sdma_reqs),
+	.opt_clks	= omap2430_mmc2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap2430_mmc2_opt_clks),
+	.main_clk	= "mmchs2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit  = OMAP2430_EN_MMCHS2_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MMCHS2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc2_slaves),
+	.class		= &omap2430_mmc_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
-	.flags		= HWMOD_NO_IDLEST,
 };
 
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
@@ -925,12 +2670,34 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l4_wkup_hwmod,
 	&omap2430_mpu_hwmod,
 	&omap2430_iva_hwmod,
+
+	&omap2430_timer1_hwmod,
+	&omap2430_timer2_hwmod,
+	&omap2430_timer3_hwmod,
+	&omap2430_timer4_hwmod,
+	&omap2430_timer5_hwmod,
+	&omap2430_timer6_hwmod,
+	&omap2430_timer7_hwmod,
+	&omap2430_timer8_hwmod,
+	&omap2430_timer9_hwmod,
+	&omap2430_timer10_hwmod,
+	&omap2430_timer11_hwmod,
+	&omap2430_timer12_hwmod,
+
 	&omap2430_wd_timer2_hwmod,
 	&omap2430_uart1_hwmod,
 	&omap2430_uart2_hwmod,
 	&omap2430_uart3_hwmod,
+	/* dss class */
+	&omap2430_dss_core_hwmod,
+	&omap2430_dss_dispc_hwmod,
+	&omap2430_dss_rfbi_hwmod,
+	&omap2430_dss_venc_hwmod,
+	/* i2c class */
 	&omap2430_i2c1_hwmod,
 	&omap2430_i2c2_hwmod,
+	&omap2430_mmc1_hwmod,
+	&omap2430_mmc2_hwmod,
 
 	/* gpio class */
 	&omap2430_gpio1_hwmod,
@@ -941,10 +2708,29 @@ static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 
 	/* dma_system class*/
 	&omap2430_dma_system_hwmod,
+
+	/* mcbsp class */
+	&omap2430_mcbsp1_hwmod,
+	&omap2430_mcbsp2_hwmod,
+	&omap2430_mcbsp3_hwmod,
+	&omap2430_mcbsp4_hwmod,
+	&omap2430_mcbsp5_hwmod,
+
+	/* mailbox class */
+	&omap2430_mailbox_hwmod,
+
+	/* mcspi class */
+	&omap2430_mcspi1_hwmod,
+	&omap2430_mcspi2_hwmod,
+	&omap2430_mcspi3_hwmod,
+
+	/* usbotg class*/
+	&omap2430_usbhsotg_hwmod,
+
 	NULL,
 };
 
 int __init omap2430_hwmod_init(void)
 {
-	return omap_hwmod_init(omap2430_hwmods);
+	return omap_hwmod_register(omap2430_hwmods);
 }
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 8d81813..c819c30 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -18,16 +18,21 @@
 #include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
+#include <plat/l3_3xxx.h>
 #include <plat/l4_3xxx.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
-#include <plat/smartreflex.h>
+#include <plat/mmc.h>
+#include <plat/mcbsp.h>
+#include <plat/mcspi.h>
+#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
 #include "wd_timer.h"
+#include <mach/am35xx.h>
 
 /*
  * OMAP3xxx hardware module integration data
@@ -44,6 +49,12 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod;
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
 static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
+static struct omap_hwmod omap3430es1_dss_core_hwmod;
+static struct omap_hwmod omap3xxx_dss_core_hwmod;
+static struct omap_hwmod omap3xxx_dss_dispc_hwmod;
+static struct omap_hwmod omap3xxx_dss_dsi1_hwmod;
+static struct omap_hwmod omap3xxx_dss_rfbi_hwmod;
+static struct omap_hwmod omap3xxx_dss_venc_hwmod;
 static struct omap_hwmod omap3xxx_i2c1_hwmod;
 static struct omap_hwmod omap3xxx_i2c2_hwmod;
 static struct omap_hwmod omap3xxx_i2c3_hwmod;
@@ -55,9 +66,25 @@ static struct omap_hwmod omap3xxx_gpio5_hwmod;
 static struct omap_hwmod omap3xxx_gpio6_hwmod;
 static struct omap_hwmod omap34xx_sr1_hwmod;
 static struct omap_hwmod omap34xx_sr2_hwmod;
+static struct omap_hwmod omap34xx_mcspi1;
+static struct omap_hwmod omap34xx_mcspi2;
+static struct omap_hwmod omap34xx_mcspi3;
+static struct omap_hwmod omap34xx_mcspi4;
+static struct omap_hwmod omap3xxx_mmc1_hwmod;
+static struct omap_hwmod omap3xxx_mmc2_hwmod;
+static struct omap_hwmod omap3xxx_mmc3_hwmod;
+static struct omap_hwmod am35xx_usbhsotg_hwmod;
 
 static struct omap_hwmod omap3xxx_dma_system_hwmod;
 
+static struct omap_hwmod omap3xxx_mcbsp1_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp2_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp3_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp4_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp5_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod;
+
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
 	.master	= &omap3xxx_l3_main_hwmod,
@@ -72,10 +99,26 @@ static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_per = {
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L3 taret configuration and error log registers */
+static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
+	{ .irq = INT_34XX_L3_DBG_IRQ },
+	{ .irq = INT_34XX_L3_APP_IRQ },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
+	{
+		.pa_start       = 0x68000000,
+		.pa_end         = 0x6800ffff,
+		.flags          = ADDR_TYPE_RT,
+	},
+};
+
 /* MPU -> L3 interface */
 static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
-	.master = &omap3xxx_mpu_hwmod,
-	.slave	= &omap3xxx_l3_main_hwmod,
+	.master   = &omap3xxx_mpu_hwmod,
+	.slave    = &omap3xxx_l3_main_hwmod,
+	.addr     = omap3xxx_l3_main_addrs,
+	.addr_cnt = ARRAY_SIZE(omap3xxx_l3_main_addrs),
 	.user	= OCP_USER_MPU,
 };
 
@@ -84,6 +127,19 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_slaves[] = {
 	&omap3xxx_mpu__l3_main,
 };
 
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap3xxx_dss__l3 = {
+	.master		= &omap3xxx_dss_core_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.fw = {
+		.omap2 = {
+			.l3_perm_bit  = OMAP3_L3_CORE_FW_INIT_ID_DSS,
+			.flags	= OMAP_FIREWALL_L3,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Master interfaces on the L3 interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
 	&omap3xxx_l3_main__l4_core,
@@ -94,6 +150,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.name		= "l3_main",
 	.class		= &l3_hwmod_class,
+	.mpu_irqs       = omap3xxx_l3_main_irqs,
+	.mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_l3_main_irqs),
 	.masters	= omap3xxx_l3_main_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
@@ -107,7 +165,23 @@ static struct omap_hwmod omap3xxx_uart1_hwmod;
 static struct omap_hwmod omap3xxx_uart2_hwmod;
 static struct omap_hwmod omap3xxx_uart3_hwmod;
 static struct omap_hwmod omap3xxx_uart4_hwmod;
+static struct omap_hwmod omap3xxx_usbhsotg_hwmod;
+
+/* l3_core -> usbhsotg interface */
+static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
+	.master		= &omap3xxx_usbhsotg_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU,
+};
 
+/* l3_core -> am35xx_usbhsotg interface */
+static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
+	.master		= &am35xx_usbhsotg_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU,
+};
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
 	.master	= &omap3xxx_l4_core_hwmod,
@@ -115,6 +189,63 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> MMC1 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mmc1_hwmod,
+	.clk		= "mmchs1_ick",
+	.addr		= omap3xxx_mmc1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.flags		= OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> MMC2 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b41ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mmc2_hwmod,
+	.clk		= "mmchs2_ick",
+	.addr		= omap3xxx_mmc2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.flags		= OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> MMC3 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
+	{
+		.pa_start	= 0x480ad000,
+		.pa_end		= 0x480ad1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mmc3_hwmod,
+	.clk		= "mmchs3_ick",
+	.addr		= omap3xxx_mmc3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.flags		= OMAP_FIREWALL_L4
+};
+
 /* L4 CORE -> UART1 interface */
 static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
 	{
@@ -301,29 +432,70 @@ static struct omap_hwmod_ocp_if omap3_l4_core__sr2 = {
 	.user		= OCP_USER_MPU,
 };
 
+/*
+* usbhsotg interface data
+*/
+
+static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
+	{
+		.pa_start	= OMAP34XX_HSUSB_OTG_BASE,
+		.pa_end		= OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> usbhsotg  */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_usbhsotg_hwmod,
+	.clk		= "l4_ick",
+	.addr		= omap3xxx_usbhsotg_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_usbhsotg_masters[] = {
+	&omap3xxx_usbhsotg__l3,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_usbhsotg_slaves[] = {
+	&omap3xxx_l4_core__usbhsotg,
+};
+
+static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
+	{
+		.pa_start	= AM35XX_IPSS_USBOTGSS_BASE,
+		.pa_end		= AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> usbhsotg  */
+static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &am35xx_usbhsotg_hwmod,
+	.clk		= "l4_ick",
+	.addr		= am35xx_usbhsotg_addrs,
+	.addr_cnt	= ARRAY_SIZE(am35xx_usbhsotg_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if *am35xx_usbhsotg_masters[] = {
+	&am35xx_usbhsotg__l3,
+};
+
+static struct omap_hwmod_ocp_if *am35xx_usbhsotg_slaves[] = {
+	&am35xx_l4_core__usbhsotg,
+};
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 	&omap3xxx_l3_main__l4_core,
-	&omap3_l4_core__sr1,
-	&omap3_l4_core__sr2,
-};
-
-/* Master interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
-	&omap3xxx_l4_core__l4_wkup,
-	&omap3_l4_core__uart1,
-	&omap3_l4_core__uart2,
-	&omap3_l4_core__i2c1,
-	&omap3_l4_core__i2c2,
-	&omap3_l4_core__i2c3,
 };
 
 /* L4 CORE */
 static struct omap_hwmod omap3xxx_l4_core_hwmod = {
 	.name		= "l4_core",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_core_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_core_masters),
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -335,18 +507,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
 	&omap3xxx_l3_main__l4_per,
 };
 
-/* Master interfaces on the L4_PER interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
-	&omap3_l4_per__uart3,
-	&omap3_l4_per__uart4,
-};
-
 /* L4 PER */
 static struct omap_hwmod omap3xxx_l4_per_hwmod = {
 	.name		= "l4_per",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_per_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_per_masters),
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -358,16 +522,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_slaves[] = {
 	&omap3xxx_l4_core__l4_wkup,
 };
 
-/* Master interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_masters[] = {
-};
-
 /* L4 WKUP */
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_wkup_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_masters),
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -417,943 +575,2994 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* l4_wkup -> wd_timer2 */
-static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
-	{
-		.pa_start	= 0x48314000,
-		.pa_end		= 0x4831407f,
-		.flags		= ADDR_TYPE_RT
-	},
+/* timer class */
+static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
-	.master		= &omap3xxx_l4_wkup_hwmod,
-	.slave		= &omap3xxx_wd_timer2_hwmod,
-	.clk		= "wdt2_ick",
-	.addr		= omap3xxx_wd_timer2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+static struct omap_hwmod_class omap3xxx_timer_1ms_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap3xxx_timer_1ms_sysc,
+	.rev = OMAP_TIMER_IP_VERSION_1,
 };
 
-/*
- * 'wd_timer' class
- * 32-bit watchdog upward counter that generates a pulse on the reset pin on
- * overflow condition
- */
-
-static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = {
+static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
 	.rev_offs	= 0x0000,
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY),
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-/* I2C common */
-static struct omap_hwmod_class_sysconfig i2c_sysc = {
-	.rev_offs	= 0x00,
-	.sysc_offs	= 0x20,
-	.syss_offs	= 0x10,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap3xxx_timer_sysc,
+	.rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
-static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
-	.name		= "wd_timer",
-	.sysc		= &omap3xxx_wd_timer_sysc,
-	.pre_shutdown	= &omap2_wd_timer_disable
+/* timer1 */
+static struct omap_hwmod omap3xxx_timer1_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
 };
 
-/* wd_timer2 */
-static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
-	&omap3xxx_l4_wkup__wd_timer2,
+static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
+	{
+		.pa_start	= 0x48318000,
+		.pa_end		= 0x48318000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
-	.name		= "wd_timer2",
-	.class		= &omap3xxx_wd_timer_hwmod_class,
-	.main_clk	= "wdt2_fck",
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
+	.master		= &omap3xxx_l4_wkup_hwmod,
+	.slave		= &omap3xxx_timer1_hwmod,
+	.clk		= "gpt1_ick",
+	.addr		= omap3xxx_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
+	&omap3xxx_l4_wkup__timer1,
+};
+
+/* timer1 hwmod */
+static struct omap_hwmod omap3xxx_timer1_hwmod = {
+	.name		= "timer1",
+	.mpu_irqs	= omap3xxx_timer1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer1_mpu_irqs),
+	.main_clk	= "gpt1_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_WDT2_SHIFT,
+			.module_bit = OMAP3430_EN_GPT1_SHIFT,
 			.module_offs = WKUP_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_WDT2_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_wd_timer2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-};
-
-/* UART common */
-
-static struct omap_hwmod_class_sysconfig uart_sysc = {
-	.rev_offs	= 0x50,
-	.sysc_offs	= 0x54,
-	.syss_offs	= 0x58,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+	.slaves		= omap3xxx_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer1_slaves),
+	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-static struct omap_hwmod_class uart_class = {
-	.name = "uart",
-	.sysc = &uart_sysc,
+/* timer2 */
+static struct omap_hwmod omap3xxx_timer2_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
 };
 
-/* UART1 */
-
-static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART1_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
+	{
+		.pa_start	= 0x49032000,
+		.pa_end		= 0x49032000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+/* l4_per -> timer2 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer2_hwmod,
+	.clk		= "gpt2_ick",
+	.addr		= omap3xxx_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
-	&omap3_l4_core__uart1,
+/* timer2 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
+	&omap3xxx_l4_per__timer2,
 };
 
-static struct omap_hwmod omap3xxx_uart1_hwmod = {
-	.name		= "uart1",
-	.mpu_irqs	= uart1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
-	.sdma_reqs	= uart1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
-	.main_clk	= "uart1_fck",
+/* timer2 hwmod */
+static struct omap_hwmod omap3xxx_timer2_hwmod = {
+	.name		= "timer2",
+	.mpu_irqs	= omap3xxx_timer2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer2_mpu_irqs),
+	.main_clk	= "gpt2_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_UART1_SHIFT,
+			.module_bit = OMAP3430_EN_GPT2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_UART1_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_uart1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.slaves		= omap3xxx_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer2_slaves),
+	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* UART2 */
+/* timer3 */
+static struct omap_hwmod omap3xxx_timer3_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+};
 
-static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART2_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
+	{
+		.pa_start	= 0x49034000,
+		.pa_end		= 0x49034000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
+/* l4_per -> timer3 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer3_hwmod,
+	.clk		= "gpt3_ick",
+	.addr		= omap3xxx_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
-	&omap3_l4_core__uart2,
+/* timer3 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
+	&omap3xxx_l4_per__timer3,
 };
 
-static struct omap_hwmod omap3xxx_uart2_hwmod = {
-	.name		= "uart2",
-	.mpu_irqs	= uart2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
-	.sdma_reqs	= uart2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
-	.main_clk	= "uart2_fck",
+/* timer3 hwmod */
+static struct omap_hwmod omap3xxx_timer3_hwmod = {
+	.name		= "timer3",
+	.mpu_irqs	= omap3xxx_timer3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer3_mpu_irqs),
+	.main_clk	= "gpt3_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_UART2_SHIFT,
+			.module_bit = OMAP3430_EN_GPT3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_UART2_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_uart2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.slaves		= omap3xxx_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer3_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* UART3 */
+/* timer4 */
+static struct omap_hwmod omap3xxx_timer4_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+};
 
-static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
-	{ .irq = INT_24XX_UART3_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
+	{
+		.pa_start	= 0x49036000,
+		.pa_end		= 0x49036000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
-	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
-	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+/* l4_per -> timer4 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer4_hwmod,
+	.clk		= "gpt4_ick",
+	.addr		= omap3xxx_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
-	&omap3_l4_per__uart3,
+/* timer4 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
+	&omap3xxx_l4_per__timer4,
 };
 
-static struct omap_hwmod omap3xxx_uart3_hwmod = {
-	.name		= "uart3",
-	.mpu_irqs	= uart3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
-	.sdma_reqs	= uart3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
-	.main_clk	= "uart3_fck",
+/* timer4 hwmod */
+static struct omap_hwmod omap3xxx_timer4_hwmod = {
+	.name		= "timer4",
+	.mpu_irqs	= omap3xxx_timer4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer4_mpu_irqs),
+	.main_clk	= "gpt4_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = OMAP3430_PER_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_UART3_SHIFT,
+			.module_bit = OMAP3430_EN_GPT4_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_UART3_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_uart3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.slaves		= omap3xxx_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer4_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* UART4 */
+/* timer5 */
+static struct omap_hwmod omap3xxx_timer5_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
+};
 
-static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
-	{ .irq = INT_36XX_UART4_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
+	{
+		.pa_start	= 0x49038000,
+		.pa_end		= 0x49038000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
-	{ .name = "rx",	.dma_req = OMAP36XX_DMA_UART4_RX, },
-	{ .name = "tx",	.dma_req = OMAP36XX_DMA_UART4_TX, },
+/* l4_per -> timer5 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer5_hwmod,
+	.clk		= "gpt5_ick",
+	.addr		= omap3xxx_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
-	&omap3_l4_per__uart4,
+/* timer5 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
+	&omap3xxx_l4_per__timer5,
 };
 
-static struct omap_hwmod omap3xxx_uart4_hwmod = {
-	.name		= "uart4",
-	.mpu_irqs	= uart4_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
-	.sdma_reqs	= uart4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(uart4_sdma_reqs),
-	.main_clk	= "uart4_fck",
+/* timer5 hwmod */
+static struct omap_hwmod omap3xxx_timer5_hwmod = {
+	.name		= "timer5",
+	.mpu_irqs	= omap3xxx_timer5_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer5_mpu_irqs),
+	.main_clk	= "gpt5_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = OMAP3430_PER_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3630_EN_UART4_SHIFT,
+			.module_bit = OMAP3430_EN_GPT5_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3630_EN_UART4_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_uart4_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
-	.class		= &uart_class,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
-};
-
-static struct omap_hwmod_class i2c_class = {
-	.name = "i2c",
-	.sysc = &i2c_sysc,
+	.slaves		= omap3xxx_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer5_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* I2C1 */
-
-static struct omap_i2c_dev_attr i2c1_dev_attr = {
-	.fifo_depth	= 8, /* bytes */
+/* timer6 */
+static struct omap_hwmod omap3xxx_timer6_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
 };
 
-static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C1_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4903A000,
+		.pa_end		= 0x4903A000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+/* l4_per -> timer6 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer6_hwmod,
+	.clk		= "gpt6_ick",
+	.addr		= omap3xxx_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
-	&omap3_l4_core__i2c1,
+/* timer6 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
+	&omap3xxx_l4_per__timer6,
 };
 
-static struct omap_hwmod omap3xxx_i2c1_hwmod = {
-	.name		= "i2c1",
-	.mpu_irqs	= i2c1_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
-	.sdma_reqs	= i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
-	.main_clk	= "i2c1_fck",
+/* timer6 hwmod */
+static struct omap_hwmod omap3xxx_timer6_hwmod = {
+	.name		= "timer6",
+	.mpu_irqs	= omap3xxx_timer6_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer6_mpu_irqs),
+	.main_clk	= "gpt6_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_I2C1_SHIFT,
+			.module_bit = OMAP3430_EN_GPT6_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_I2C1_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_i2c1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c1_slaves),
-	.class		= &i2c_class,
-	.dev_attr	= &i2c1_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.slaves		= omap3xxx_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer6_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* I2C2 */
-
-static struct omap_i2c_dev_attr i2c2_dev_attr = {
-	.fifo_depth	= 8, /* bytes */
+/* timer7 */
+static struct omap_hwmod omap3xxx_timer7_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
 };
 
-static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
-	{ .irq = INT_24XX_I2C2_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
+	{
+		.pa_start	= 0x4903C000,
+		.pa_end		= 0x4903C000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
-	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+/* l4_per -> timer7 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer7_hwmod,
+	.clk		= "gpt7_ick",
+	.addr		= omap3xxx_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer7_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
-	&omap3_l4_core__i2c2,
+/* timer7 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
+	&omap3xxx_l4_per__timer7,
 };
 
-static struct omap_hwmod omap3xxx_i2c2_hwmod = {
-	.name		= "i2c2",
-	.mpu_irqs	= i2c2_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
-	.sdma_reqs	= i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
-	.main_clk	= "i2c2_fck",
+/* timer7 hwmod */
+static struct omap_hwmod omap3xxx_timer7_hwmod = {
+	.name		= "timer7",
+	.mpu_irqs	= omap3xxx_timer7_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer7_mpu_irqs),
+	.main_clk	= "gpt7_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_I2C2_SHIFT,
+			.module_bit = OMAP3430_EN_GPT7_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_I2C2_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_i2c2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c2_slaves),
-	.class		= &i2c_class,
-	.dev_attr	= &i2c2_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.slaves		= omap3xxx_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer7_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* I2C3 */
-
-static struct omap_i2c_dev_attr i2c3_dev_attr = {
-	.fifo_depth	= 64, /* bytes */
+/* timer8 */
+static struct omap_hwmod omap3xxx_timer8_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
 };
 
-static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
-	{ .irq = INT_34XX_I2C3_IRQ, },
+static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
+	{
+		.pa_start	= 0x4903E000,
+		.pa_end		= 0x4903E000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = OMAP34XX_DMA_I2C3_TX },
-	{ .name = "rx", .dma_req = OMAP34XX_DMA_I2C3_RX },
+/* l4_per -> timer8 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer8_hwmod,
+	.clk		= "gpt8_ick",
+	.addr		= omap3xxx_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer8_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
-	&omap3_l4_core__i2c3,
+/* timer8 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
+	&omap3xxx_l4_per__timer8,
 };
 
-static struct omap_hwmod omap3xxx_i2c3_hwmod = {
-	.name		= "i2c3",
-	.mpu_irqs	= i2c3_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(i2c3_mpu_irqs),
-	.sdma_reqs	= i2c3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(i2c3_sdma_reqs),
-	.main_clk	= "i2c3_fck",
+/* timer8 hwmod */
+static struct omap_hwmod omap3xxx_timer8_hwmod = {
+	.name		= "timer8",
+	.mpu_irqs	= omap3xxx_timer8_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer8_mpu_irqs),
+	.main_clk	= "gpt8_fck",
 	.prcm		= {
 		.omap2 = {
-			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_I2C3_SHIFT,
+			.module_bit = OMAP3430_EN_GPT8_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_I2C3_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_i2c3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c3_slaves),
-	.class		= &i2c_class,
-	.dev_attr	= &i2c3_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.slaves		= omap3xxx_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer8_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
+/* timer9 */
+static struct omap_hwmod omap3xxx_timer9_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
 	{
-		.pa_start	= 0x48310000,
-		.pa_end		= 0x483101ff,
+		.pa_start	= 0x49040000,
+		.pa_end		= 0x49040000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
-	.master		= &omap3xxx_l4_wkup_hwmod,
-	.slave		= &omap3xxx_gpio1_hwmod,
-	.addr		= omap3xxx_gpio1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio1_addrs),
+/* l4_per -> timer9 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer9_hwmod,
+	.clk		= "gpt9_ick",
+	.addr		= omap3xxx_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer9_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> gpio2 */
-static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
-	{
-		.pa_start	= 0x49050000,
-		.pa_end		= 0x490501ff,
-		.flags		= ADDR_TYPE_RT
+/* timer9 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
+	&omap3xxx_l4_per__timer9,
+};
+
+/* timer9 hwmod */
+static struct omap_hwmod omap3xxx_timer9_hwmod = {
+	.name		= "timer9",
+	.mpu_irqs	= omap3xxx_timer9_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer9_mpu_irqs),
+	.main_clk	= "gpt9_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT9_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
+		},
 	},
+	.slaves		= omap3xxx_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer9_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
-	.master		= &omap3xxx_l4_per_hwmod,
-	.slave		= &omap3xxx_gpio2_hwmod,
-	.addr		= omap3xxx_gpio2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio2_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* timer10 */
+static struct omap_hwmod omap3xxx_timer10_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
 };
 
-/* l4_per -> gpio3 */
-static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
+static struct omap_hwmod_addr_space omap3xxx_timer10_addrs[] = {
 	{
-		.pa_start	= 0x49052000,
-		.pa_end		= 0x490521ff,
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
-	.master		= &omap3xxx_l4_per_hwmod,
-	.slave		= &omap3xxx_gpio3_hwmod,
-	.addr		= omap3xxx_gpio3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio3_addrs),
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer10 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_timer10_hwmod,
+	.clk		= "gpt10_ick",
+	.addr		= omap3xxx_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer10_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> gpio4 */
-static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
-	{
-		.pa_start	= 0x49054000,
-		.pa_end		= 0x490541ff,
-		.flags		= ADDR_TYPE_RT
+/* timer10 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
+	&omap3xxx_l4_core__timer10,
+};
+
+/* timer10 hwmod */
+static struct omap_hwmod omap3xxx_timer10_hwmod = {
+	.name		= "timer10",
+	.mpu_irqs	= omap3xxx_timer10_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer10_mpu_irqs),
+	.main_clk	= "gpt10_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT10_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
+		},
 	},
+	.slaves		= omap3xxx_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer10_slaves),
+	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
-	.master		= &omap3xxx_l4_per_hwmod,
-	.slave		= &omap3xxx_gpio4_hwmod,
-	.addr		= omap3xxx_gpio4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio4_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* timer11 */
+static struct omap_hwmod omap3xxx_timer11_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
 };
 
-/* l4_per -> gpio5 */
-static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
+static struct omap_hwmod_addr_space omap3xxx_timer11_addrs[] = {
 	{
-		.pa_start	= 0x49056000,
-		.pa_end		= 0x490561ff,
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
-	.master		= &omap3xxx_l4_per_hwmod,
-	.slave		= &omap3xxx_gpio5_hwmod,
-	.addr		= omap3xxx_gpio5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio5_addrs),
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer11 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_timer11_hwmod,
+	.clk		= "gpt11_ick",
+	.addr		= omap3xxx_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer11_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* l4_per -> gpio6 */
-static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
+/* timer11 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
+	&omap3xxx_l4_core__timer11,
+};
+
+/* timer11 hwmod */
+static struct omap_hwmod omap3xxx_timer11_hwmod = {
+	.name		= "timer11",
+	.mpu_irqs	= omap3xxx_timer11_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer11_mpu_irqs),
+	.main_clk	= "gpt11_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT11_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer11_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer12*/
+static struct omap_hwmod omap3xxx_timer12_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
+	{ .irq = 95, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
 	{
-		.pa_start	= 0x49058000,
-		.pa_end		= 0x490581ff,
+		.pa_start	= 0x48304000,
+		.pa_end		= 0x48304000 + SZ_1K - 1,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
-	.master		= &omap3xxx_l4_per_hwmod,
-	.slave		= &omap3xxx_gpio6_hwmod,
-	.addr		= omap3xxx_gpio6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio6_addrs),
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer12 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_timer12_hwmod,
+	.clk		= "gpt12_ick",
+	.addr		= omap3xxx_timer12_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer12_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/*
- * 'gpio' class
- * general purpose io module
- */
+/* timer12 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
+	&omap3xxx_l4_core__timer12,
+};
 
-static struct omap_hwmod_class_sysconfig omap3xxx_gpio_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0014,
-	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_fields    = &omap_hwmod_sysc_type1,
+/* timer12 hwmod */
+static struct omap_hwmod omap3xxx_timer12_hwmod = {
+	.name		= "timer12",
+	.mpu_irqs	= omap3xxx_timer12_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer12_mpu_irqs),
+	.main_clk	= "gpt12_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT12_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer12_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer12_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-static struct omap_hwmod_class omap3xxx_gpio_hwmod_class = {
-	.name = "gpio",
-	.sysc = &omap3xxx_gpio_sysc,
-	.rev = 1,
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
+	{
+		.pa_start	= 0x48314000,
+		.pa_end		= 0x4831407f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-/* gpio_dev_attr*/
-static struct omap_gpio_dev_attr gpio_dev_attr = {
-	.bank_width = 32,
-	.dbck_flag = true,
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
+	.master		= &omap3xxx_l4_wkup_hwmod,
+	.slave		= &omap3xxx_wd_timer2_hwmod,
+	.clk		= "wdt2_ick",
+	.addr		= omap3xxx_wd_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* gpio1 */
-static struct omap_hwmod_irq_info omap3xxx_gpio1_irqs[] = {
-	{ .irq = 29 }, /* INT_34XX_GPIO_BANK1 */
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio1_dbck", },
+/* I2C common */
+static struct omap_hwmod_class_sysconfig i2c_sysc = {
+	.rev_offs	= 0x00,
+	.sysc_offs	= 0x20,
+	.syss_offs	= 0x10,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
-	&omap3xxx_l4_wkup__gpio1,
+static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
+	.name		= "wd_timer",
+	.sysc		= &omap3xxx_wd_timer_sysc,
+	.pre_shutdown	= &omap2_wd_timer_disable
 };
 
-static struct omap_hwmod omap3xxx_gpio1_hwmod = {
-	.name		= "gpio1",
-	.mpu_irqs	= omap3xxx_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
-	.main_clk	= "gpio1_ick",
-	.opt_clks	= gpio1_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
+	&omap3xxx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
+	.name		= "wd_timer2",
+	.class		= &omap3xxx_wd_timer_hwmod_class,
+	.main_clk	= "wdt2_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_GPIO1_SHIFT,
+			.module_bit = OMAP3430_EN_WDT2_SHIFT,
 			.module_offs = WKUP_MOD,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_GPIO1_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_WDT2_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_gpio1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio1_slaves),
-	.class		= &omap3xxx_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap3xxx_wd_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	/*
+	 * XXX: Use software supervised mode, HW supervised smartidle seems to
+	 * block CORE power domain idle transitions. Maybe a HW bug in wdt2?
+	 */
+	.flags		= HWMOD_SWSUP_SIDLE,
 };
 
-/* gpio2 */
-static struct omap_hwmod_irq_info omap3xxx_gpio2_irqs[] = {
-	{ .irq = 30 }, /* INT_34XX_GPIO_BANK2 */
+/* UART common */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+	.rev_offs	= 0x50,
+	.sysc_offs	= 0x54,
+	.syss_offs	= 0x58,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio2_dbck", },
+static struct omap_hwmod_class uart_class = {
+	.name = "uart",
+	.sysc = &uart_sysc,
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
-	&omap3xxx_l4_per__gpio2,
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART1_IRQ, },
 };
 
-static struct omap_hwmod omap3xxx_gpio2_hwmod = {
-	.name		= "gpio2",
-	.mpu_irqs	= omap3xxx_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
-	.main_clk	= "gpio2_ick",
-	.opt_clks	= gpio2_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART1_TX, },
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART1_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
+	&omap3_l4_core__uart1,
+};
+
+static struct omap_hwmod omap3xxx_uart1_hwmod = {
+	.name		= "uart1",
+	.mpu_irqs	= uart1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart1_mpu_irqs),
+	.sdma_reqs	= uart1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart1_sdma_reqs),
+	.main_clk	= "uart1_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_GPIO2_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
+			.module_bit = OMAP3430_EN_UART1_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_GPIO2_SHIFT,
+			.idlest_idle_bit = OMAP3430_EN_UART1_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_gpio2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio2_slaves),
-	.class		= &omap3xxx_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap3xxx_uart1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart1_slaves),
+	.class		= &uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-/* gpio3 */
-static struct omap_hwmod_irq_info omap3xxx_gpio3_irqs[] = {
-	{ .irq = 31 }, /* INT_34XX_GPIO_BANK3 */
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART2_IRQ, },
 };
 
-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio3_dbck", },
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART2_TX, },
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART2_RX, },
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
-	&omap3xxx_l4_per__gpio3,
+static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
+	&omap3_l4_core__uart2,
 };
 
-static struct omap_hwmod omap3xxx_gpio3_hwmod = {
-	.name		= "gpio3",
-	.mpu_irqs	= omap3xxx_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
-	.main_clk	= "gpio3_ick",
-	.opt_clks	= gpio3_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+static struct omap_hwmod omap3xxx_uart2_hwmod = {
+	.name		= "uart2",
+	.mpu_irqs	= uart2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart2_mpu_irqs),
+	.sdma_reqs	= uart2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart2_sdma_reqs),
+	.main_clk	= "uart2_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_GPIO3_SHIFT,
+			.module_bit = OMAP3430_EN_UART2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_UART2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_uart2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart2_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+	{ .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = OMAP24XX_DMA_UART3_TX, },
+	{ .name = "rx",	.dma_req = OMAP24XX_DMA_UART3_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
+	&omap3_l4_per__uart3,
+};
+
+static struct omap_hwmod omap3xxx_uart3_hwmod = {
+	.name		= "uart3",
+	.mpu_irqs	= uart3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart3_mpu_irqs),
+	.sdma_reqs	= uart3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart3_sdma_reqs),
+	.main_clk	= "uart3_fck",
+	.prcm		= {
+		.omap2 = {
 			.module_offs = OMAP3430_PER_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_UART3_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_GPIO3_SHIFT,
+			.idlest_idle_bit = OMAP3430_EN_UART3_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_gpio3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio3_slaves),
-	.class		= &omap3xxx_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap3xxx_uart3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart3_slaves),
+	.class		= &uart_class,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-/* gpio4 */
-static struct omap_hwmod_irq_info omap3xxx_gpio4_irqs[] = {
-	{ .irq = 32 }, /* INT_34XX_GPIO_BANK4 */
+/* UART4 */
+
+static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
+	{ .irq = INT_36XX_UART4_IRQ, },
 };
 
-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio4_dbck", },
+static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
+	{ .name = "rx",	.dma_req = OMAP36XX_DMA_UART4_RX, },
+	{ .name = "tx",	.dma_req = OMAP36XX_DMA_UART4_TX, },
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
-	&omap3xxx_l4_per__gpio4,
+static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
+	&omap3_l4_per__uart4,
 };
 
-static struct omap_hwmod omap3xxx_gpio4_hwmod = {
-	.name		= "gpio4",
-	.mpu_irqs	= omap3xxx_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
-	.main_clk	= "gpio4_ick",
-	.opt_clks	= gpio4_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
+static struct omap_hwmod omap3xxx_uart4_hwmod = {
+	.name		= "uart4",
+	.mpu_irqs	= uart4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(uart4_mpu_irqs),
+	.sdma_reqs	= uart4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(uart4_sdma_reqs),
+	.main_clk	= "uart4_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = OMAP3430_PER_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3630_EN_UART4_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3630_EN_UART4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_uart4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_uart4_slaves),
+	.class		= &uart_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
+static struct omap_hwmod_class i2c_class = {
+	.name = "i2c",
+	.sysc = &i2c_sysc,
+};
+
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dss_hwmod_class = {
+	.name = "dss",
+	.sysc = &omap3xxx_dss_sysc,
+};
+
+/* dss */
+static struct omap_hwmod_irq_info omap3xxx_dss_irqs[] = {
+	{ .irq = 25 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+	{ .name = "dsi1", .dma_req = 74 },
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_masters[] = {
+	&omap3xxx_dss__l3,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x480503FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3430es1_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap3430es1_dss_slaves[] = {
+	&omap3430es1_l4_core__dss,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
+	&omap3xxx_l4_core__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	{ .role = "dssclk", .clk = "dss_96m_fck" },
+	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
+static struct omap_hwmod omap3430es1_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap3xxx_dss_hwmod_class,
+	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
+	.mpu_irqs	= omap3xxx_dss_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dss_irqs),
+	.sdma_reqs	= omap3xxx_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
+
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP3430ES1_ST_DSS_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap3430es1_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3430es1_dss_slaves),
+	.masters	= omap3xxx_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+static struct omap_hwmod omap3xxx_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap3xxx_dss_hwmod_class,
+	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
+	.mpu_irqs	= omap3xxx_dss_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dss_irqs),
+	.sdma_reqs	= omap3xxx_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
+
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT,
+			.idlest_stdby_bit = OMAP3430ES2_ST_DSS_STDBY_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap3xxx_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_slaves),
+	.masters	= omap3xxx_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2 |
+				CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = {
+	.name = "dispc",
+	.sysc = &omap3xxx_dispc_sysc,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x480507FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_dispc_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
+	&omap3xxx_l4_core__dss_dispc,
+};
+
+static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap3xxx_dispc_hwmod_class,
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'dsi' class
+ * display serial interface controller
+ */
+
+static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
+	.name = "dsi",
+};
+
+/* dss_dsi1 */
+static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
+	{
+		.pa_start	= 0x4804FC00,
+		.pa_end		= 0x4804FFFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_dsi1_hwmod,
+	.addr		= omap3xxx_dss_dsi1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dsi1 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
+	&omap3xxx_l4_core__dss_dsi1,
+};
+
+static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
+	.name		= "dss_dsi1",
+	.class		= &omap3xxx_dsi_hwmod_class,
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_dsi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_rfbi_hwmod_class = {
+	.name = "rfbi",
+	.sysc = &omap3xxx_rfbi_sysc,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050BFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_rfbi_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP ,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
+	&omap3xxx_l4_core__dss_rfbi,
+};
+
+static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap3xxx_rfbi_hwmod_class,
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap3xxx_venc_hwmod_class = {
+	.name = "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod_addr_space omap3xxx_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_venc_hwmod,
+	.clk		= "dss_tv_fck",
+	.addr		= omap3xxx_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.flags		= OCPIF_SWSUP_IDLE,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
+	&omap3xxx_l4_core__dss_venc,
+};
+
+static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap3xxx_venc_hwmod_class,
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/* I2C1 */
+
+static struct omap_i2c_dev_attr i2c1_dev_attr = {
+	.fifo_depth	= 8, /* bytes */
+};
+
+static struct omap_hwmod_irq_info i2c1_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C1_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C1_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_i2c1_slaves[] = {
+	&omap3_l4_core__i2c1,
+};
+
+static struct omap_hwmod omap3xxx_i2c1_hwmod = {
+	.name		= "i2c1",
+	.mpu_irqs	= i2c1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c1_mpu_irqs),
+	.sdma_reqs	= i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c1_sdma_reqs),
+	.main_clk	= "i2c1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_I2C1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_I2C1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_i2c1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c1_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* I2C2 */
+
+static struct omap_i2c_dev_attr i2c2_dev_attr = {
+	.fifo_depth	= 8, /* bytes */
+};
+
+static struct omap_hwmod_irq_info i2c2_mpu_irqs[] = {
+	{ .irq = INT_24XX_I2C2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP24XX_DMA_I2C2_TX },
+	{ .name = "rx", .dma_req = OMAP24XX_DMA_I2C2_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_i2c2_slaves[] = {
+	&omap3_l4_core__i2c2,
+};
+
+static struct omap_hwmod omap3xxx_i2c2_hwmod = {
+	.name		= "i2c2",
+	.mpu_irqs	= i2c2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c2_mpu_irqs),
+	.sdma_reqs	= i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c2_sdma_reqs),
+	.main_clk	= "i2c2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_I2C2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_I2C2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_i2c2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c2_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* I2C3 */
+
+static struct omap_i2c_dev_attr i2c3_dev_attr = {
+	.fifo_depth	= 64, /* bytes */
+};
+
+static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
+	{ .irq = INT_34XX_I2C3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info i2c3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = OMAP34XX_DMA_I2C3_TX },
+	{ .name = "rx", .dma_req = OMAP34XX_DMA_I2C3_RX },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_i2c3_slaves[] = {
+	&omap3_l4_core__i2c3,
+};
+
+static struct omap_hwmod omap3xxx_i2c3_hwmod = {
+	.name		= "i2c3",
+	.mpu_irqs	= i2c3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(i2c3_mpu_irqs),
+	.sdma_reqs	= i2c3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(i2c3_sdma_reqs),
+	.main_clk	= "i2c3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_I2C3_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_I2C3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_i2c3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_i2c3_slaves),
+	.class		= &i2c_class,
+	.dev_attr	= &i2c3_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_addr_space omap3xxx_gpio1_addrs[] = {
+	{
+		.pa_start	= 0x48310000,
+		.pa_end		= 0x483101ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__gpio1 = {
+	.master		= &omap3xxx_l4_wkup_hwmod,
+	.slave		= &omap3xxx_gpio1_hwmod,
+	.addr		= omap3xxx_gpio1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio2 */
+static struct omap_hwmod_addr_space omap3xxx_gpio2_addrs[] = {
+	{
+		.pa_start	= 0x49050000,
+		.pa_end		= 0x490501ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio2 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio2_hwmod,
+	.addr		= omap3xxx_gpio2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio3 */
+static struct omap_hwmod_addr_space omap3xxx_gpio3_addrs[] = {
+	{
+		.pa_start	= 0x49052000,
+		.pa_end		= 0x490521ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio3_hwmod,
+	.addr		= omap3xxx_gpio3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio4 */
+static struct omap_hwmod_addr_space omap3xxx_gpio4_addrs[] = {
+	{
+		.pa_start	= 0x49054000,
+		.pa_end		= 0x490541ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio4_hwmod,
+	.addr		= omap3xxx_gpio4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio5 */
+static struct omap_hwmod_addr_space omap3xxx_gpio5_addrs[] = {
+	{
+		.pa_start	= 0x49056000,
+		.pa_end		= 0x490561ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio5 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio5_hwmod,
+	.addr		= omap3xxx_gpio5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per -> gpio6 */
+static struct omap_hwmod_addr_space omap3xxx_gpio6_addrs[] = {
+	{
+		.pa_start	= 0x49058000,
+		.pa_end		= 0x490581ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__gpio6 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_gpio6_hwmod,
+	.addr		= omap3xxx_gpio6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_gpio6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_gpio_hwmod_class = {
+	.name = "gpio",
+	.sysc = &omap3xxx_gpio_sysc,
+	.rev = 1,
+};
+
+/* gpio_dev_attr*/
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width = 32,
+	.dbck_flag = true,
+};
+
+/* gpio1 */
+static struct omap_hwmod_irq_info omap3xxx_gpio1_irqs[] = {
+	{ .irq = 29 }, /* INT_34XX_GPIO_BANK1 */
+};
+
+static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio1_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
+	&omap3xxx_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod omap3xxx_gpio1_hwmod = {
+	.name		= "gpio1",
+	.mpu_irqs	= omap3xxx_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
+	.main_clk	= "gpio1_ick",
+	.opt_clks	= gpio1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio1_slaves),
+	.class		= &omap3xxx_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* gpio2 */
+static struct omap_hwmod_irq_info omap3xxx_gpio2_irqs[] = {
+	{ .irq = 30 }, /* INT_34XX_GPIO_BANK2 */
+};
+
+static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio2_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
+	&omap3xxx_l4_per__gpio2,
+};
+
+static struct omap_hwmod omap3xxx_gpio2_hwmod = {
+	.name		= "gpio2",
+	.mpu_irqs	= omap3xxx_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
+	.main_clk	= "gpio2_ick",
+	.opt_clks	= gpio2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio2_slaves),
+	.class		= &omap3xxx_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* gpio3 */
+static struct omap_hwmod_irq_info omap3xxx_gpio3_irqs[] = {
+	{ .irq = 31 }, /* INT_34XX_GPIO_BANK3 */
+};
+
+static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio3_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
+	&omap3xxx_l4_per__gpio3,
+};
+
+static struct omap_hwmod omap3xxx_gpio3_hwmod = {
+	.name		= "gpio3",
+	.mpu_irqs	= omap3xxx_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
+	.main_clk	= "gpio3_ick",
+	.opt_clks	= gpio3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio3_slaves),
+	.class		= &omap3xxx_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* gpio4 */
+static struct omap_hwmod_irq_info omap3xxx_gpio4_irqs[] = {
+	{ .irq = 32 }, /* INT_34XX_GPIO_BANK4 */
+};
+
+static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio4_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
+	&omap3xxx_l4_per__gpio4,
+};
+
+static struct omap_hwmod omap3xxx_gpio4_hwmod = {
+	.name		= "gpio4",
+	.mpu_irqs	= omap3xxx_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
+	.main_clk	= "gpio4_ick",
+	.opt_clks	= gpio4_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO4_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio4_slaves),
+	.class		= &omap3xxx_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* gpio5 */
+static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
+	{ .irq = 33 }, /* INT_34XX_GPIO_BANK5 */
+};
+
+static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio5_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
+	&omap3xxx_l4_per__gpio5,
+};
+
+static struct omap_hwmod omap3xxx_gpio5_hwmod = {
+	.name		= "gpio5",
+	.mpu_irqs	= omap3xxx_gpio5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
+	.main_clk	= "gpio5_ick",
+	.opt_clks	= gpio5_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO5_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO5_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio5_slaves),
+	.class		= &omap3xxx_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* gpio6 */
+static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
+	{ .irq = 34 }, /* INT_34XX_GPIO_BANK6 */
+};
+
+static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio6_dbck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
+	&omap3xxx_l4_per__gpio6,
+};
+
+static struct omap_hwmod omap3xxx_gpio6_hwmod = {
+	.name		= "gpio6",
+	.mpu_irqs	= omap3xxx_gpio6_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
+	.main_clk	= "gpio6_ick",
+	.opt_clks	= gpio6_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPIO6_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPIO6_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_gpio6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio6_slaves),
+	.class		= &omap3xxx_gpio_hwmod_class,
+	.dev_attr	= &gpio_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* dma_system -> L3 */
+static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
+	.master		= &omap3xxx_dma_system_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma attributes */
+static struct omap_dma_dev_attr dma_dev_attr = {
+	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
+				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
+	.lch_count = 32,
+};
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x002c,
+	.syss_offs	= 0x0028,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
+	.name = "dma",
+	.sysc = &omap3xxx_dma_sysc,
+};
+
+/* dma_system */
+static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
+	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
+	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
+	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
+	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
+	{
+		.pa_start	= 0x48056000,
+		.pa_end		= 0x4a0560ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* dma_system master ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = {
+	&omap3xxx_dma_system__l3,
+};
+
+/* l4_cfg -> dma_system */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dma_system_hwmod,
+	.clk		= "core_l4_ick",
+	.addr		= omap3xxx_dma_system_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dma_system_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dma_system slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
+	&omap3xxx_l4_core__dma_system,
+};
+
+static struct omap_hwmod omap3xxx_dma_system_hwmod = {
+	.name		= "dma",
+	.class		= &omap3xxx_dma_hwmod_class,
+	.mpu_irqs	= omap3xxx_dma_system_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
+	.main_clk	= "core_l3_ick",
+	.prcm = {
+		.omap2 = {
+			.module_offs		= CORE_MOD,
+			.prcm_reg_id		= 1,
+			.module_bit		= OMAP3430_ST_SDMA_SHIFT,
+			.idlest_reg_id		= 1,
+			.idlest_idle_bit	= OMAP3430_ST_SDMA_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_dma_system_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
+	.masters	= omap3xxx_dma_system_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
+	.dev_attr	= &dma_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = {
+	.sysc_offs	= 0x008c,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+	.clockact	= 0x2,
+};
+
+static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = {
+	.name = "mcbsp",
+	.sysc = &omap3xxx_mcbsp_sysc,
+	.rev  = MCBSP_CONFIG_TYPE3,
+};
+
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
+	{ .name = "irq", .irq = 16 },
+	{ .name = "tx", .irq = 59 },
+	{ .name = "rx", .irq = 60 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp1_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mcbsp1_hwmod,
+	.clk		= "mcbsp1_ick",
+	.addr		= omap3xxx_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp1_slaves[] = {
+	&omap3xxx_l4_core__mcbsp1,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp1_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_sdma_chs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
+	{ .name = "irq", .irq = 17 },
+	{ .name = "tx", .irq = 62 },
+	{ .name = "rx", .irq = 63 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp2_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x49022000,
+		.pa_end		= 0x490220ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp2_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap3xxx_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_slaves[] = {
+	&omap3xxx_l4_per__mcbsp2,
+};
+
+static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
+	.sidetone	= "mcbsp2_sidetone",
+};
+
+static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp2_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sdma_chs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_slaves),
+	.dev_attr	= &omap34xx_mcbsp2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp3 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
+	{ .name = "irq", .irq = 22 },
+	{ .name = "tx", .irq = 89 },
+	{ .name = "rx", .irq = 90 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp3_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 18 },
+	{ .name = "tx", .dma_req = 17 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x49024000,
+		.pa_end		= 0x490240ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp3_hwmod,
+	.clk		= "mcbsp3_ick",
+	.addr		= omap3xxx_mcbsp3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp3 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_slaves[] = {
+	&omap3xxx_l4_per__mcbsp3,
+};
+
+static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
+	.sidetone       = "mcbsp3_sidetone",
+};
+
+static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
+	.name		= "mcbsp3",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp3_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sdma_chs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_slaves),
+	.dev_attr	= &omap34xx_mcbsp3_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp4 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
+	{ .name = "irq", .irq = 23 },
+	{ .name = "tx", .irq = 54 },
+	{ .name = "rx", .irq = 55 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 20 },
+	{ .name = "tx", .dma_req = 19 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x49026000,
+		.pa_end		= 0x490260ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp4_hwmod,
+	.clk		= "mcbsp4_ick",
+	.addr		= omap3xxx_mcbsp4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp4 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp4_slaves[] = {
+	&omap3xxx_l4_per__mcbsp4,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
+	.name		= "mcbsp4",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp4_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_sdma_chs),
+	.main_clk	= "mcbsp4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP4_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp5 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
+	{ .name = "irq", .irq = 27 },
+	{ .name = "tx", .irq = 81 },
+	{ .name = "rx", .irq = 82 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 22 },
+	{ .name = "tx", .dma_req = 21 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48096000,
+		.pa_end		= 0x480960ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp5 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mcbsp5_hwmod,
+	.clk		= "mcbsp5_ick",
+	.addr		= omap3xxx_mcbsp5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp5 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp5_slaves[] = {
+	&omap3xxx_l4_core__mcbsp5,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
+	.name		= "mcbsp5",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp5_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_sdma_chs),
+	.main_clk	= "mcbsp5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP5_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+/* 'mcbsp sidetone' class */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sidetone_sysc = {
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= SYSC_HAS_AUTOIDLE,
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_mcbsp_sidetone_hwmod_class = {
+	.name = "mcbsp_sidetone",
+	.sysc = &omap3xxx_mcbsp_sidetone_sysc,
+};
+
+/* mcbsp2_sidetone */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
+	{ .name = "irq", .irq = 4 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
+	{
+		.name		= "sidetone",
+		.pa_start	= 0x49028000,
+		.pa_end		= 0x490280ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp2_sidetone */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp2_sidetone_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap3xxx_mcbsp2_sidetone_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* mcbsp2_sidetone slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_sidetone_slaves[] = {
+	&omap3xxx_l4_per__mcbsp2_sidetone,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
+	.name		= "mcbsp2_sidetone",
+	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_irqs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			 .module_bit = OMAP3430_EN_MCBSP2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp2_sidetone_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp3_sidetone */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
+	{ .name = "irq", .irq = 5 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
+	{
+		.name		= "sidetone",
+		.pa_start	= 0x4902A000,
+		.pa_end		= 0x4902A0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp3_sidetone */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp3_sidetone_hwmod,
+	.clk		= "mcbsp3_ick",
+	.addr		= omap3xxx_mcbsp3_sidetone_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* mcbsp3_sidetone slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_sidetone_slaves[] = {
+	&omap3xxx_l4_per__mcbsp3_sidetone,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
+	.name		= "mcbsp3_sidetone",
+	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_irqs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp3_sidetone_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+
+/* SR common */
+static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
+	.clkact_shift	= 20,
+};
+
+static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
+	.sysc_offs	= 0x24,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
+	.clockact	= CLOCKACT_TEST_ICLK,
+	.sysc_fields	= &omap34xx_sr_sysc_fields,
+};
+
+static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
+	.name = "smartreflex",
+	.sysc = &omap34xx_sr_sysc,
+	.rev  = 1,
+};
+
+static struct omap_hwmod_sysc_fields omap36xx_sr_sysc_fields = {
+	.sidle_shift	= 24,
+	.enwkup_shift	= 26
+};
+
+static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
+	.sysc_offs	= 0x38,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			SYSC_NO_CACHE),
+	.sysc_fields	= &omap36xx_sr_sysc_fields,
+};
+
+static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = {
+	.name = "smartreflex",
+	.sysc = &omap36xx_sr_sysc,
+	.rev  = 2,
+};
+
+/* SR1 */
+static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
+	&omap3_l4_core__sr1,
+};
+
+static struct omap_hwmod omap34xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.vdd_name	= "mpu",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
+					CHIP_IS_OMAP3430ES3_0 |
+					CHIP_IS_OMAP3430ES3_1),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+static struct omap_hwmod omap36xx_sr1_hwmod = {
+	.name		= "sr1_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr1_fck",
+	.vdd_name	= "mpu",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
+/* SR2 */
+static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
+	&omap3_l4_core__sr2,
+};
+
+static struct omap_hwmod omap34xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap34xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.vdd_name	= "core",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
+					CHIP_IS_OMAP3430ES3_0 |
+					CHIP_IS_OMAP3430ES3_1),
+	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+};
+
+static struct omap_hwmod omap36xx_sr2_hwmod = {
+	.name		= "sr2_hwmod",
+	.class		= &omap36xx_smartreflex_hwmod_class,
+	.main_clk	= "sr2_fck",
+	.vdd_name	= "core",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_SR2_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+		},
+	},
+	.slaves		= omap3_sr2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
+	.name = "mailbox",
+	.sysc = &omap3xxx_mailbox_sysc,
+};
+
+static struct omap_hwmod omap3xxx_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
+	{ .irq = 26 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x480941ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mailbox = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mailbox_hwmod,
+	.addr		= omap3xxx_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mailbox_slaves[] = {
+	&omap3xxx_l4_core__mailbox,
+};
+
+static struct omap_hwmod omap3xxx_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap3xxx_mailbox_hwmod_class,
+	.mpu_irqs	= omap3xxx_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mailbox_irqs),
+	.main_clk	= "mailboxes_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MAILBOXES_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480980ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi1,
+	.clk		= "mcspi1_ick",
+	.addr		= omap34xx_mcspi1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi2,
+	.clk		= "mcspi2_ick",
+	.addr		= omap34xx_mcspi2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi3 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi3_addr_space[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b80ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi3 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi3,
+	.clk		= "mcspi3_ick",
+	.addr		= omap34xx_mcspi3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi4 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
+	{
+		.pa_start	= 0x480ba000,
+		.pa_end		= 0x480ba0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi4,
+	.clk		= "mcspi4_ick",
+	.addr		= omap34xx_mcspi4_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi4_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap34xx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap34xx_mcspi_class = {
+	.name = "mcspi",
+	.sysc = &omap34xx_mcspi_sysc,
+	.rev = OMAP3_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod_irq_info omap34xx_mcspi1_mpu_irqs[] = {
+	{ .name = "irq", .irq = 65 },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 },
+	{ .name = "rx0", .dma_req = 36 },
+	{ .name = "tx1", .dma_req = 37 },
+	{ .name = "rx1", .dma_req = 38 },
+	{ .name = "tx2", .dma_req = 39 },
+	{ .name = "rx2", .dma_req = 40 },
+	{ .name = "tx3", .dma_req = 41 },
+	{ .name = "rx3", .dma_req = 42 },
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_mcspi1_slaves[] = {
+	&omap34xx_l4_core__mcspi1,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+	.num_chipselect = 4,
+};
+
+static struct omap_hwmod omap34xx_mcspi1 = {
+	.name		= "mcspi1",
+	.mpu_irqs	= omap34xx_mcspi1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCSPI1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI1_SHIFT,
+		},
+	},
+	.slaves		= omap34xx_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi1_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcspi2 */
+static struct omap_hwmod_irq_info omap34xx_mcspi2_mpu_irqs[] = {
+	{ .name = "irq", .irq = 66 },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 },
+	{ .name = "rx0", .dma_req = 44 },
+	{ .name = "tx1", .dma_req = 45 },
+	{ .name = "rx1", .dma_req = 46 },
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_mcspi2_slaves[] = {
+	&omap34xx_l4_core__mcspi2,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap34xx_mcspi2 = {
+	.name		= "mcspi2",
+	.mpu_irqs	= omap34xx_mcspi2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_GPIO4_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
+			.module_bit = OMAP3430_EN_MCSPI2_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_GPIO4_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI2_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_gpio4_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio4_slaves),
-	.class		= &omap3xxx_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap34xx_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi2_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi2_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-/* gpio5 */
-static struct omap_hwmod_irq_info omap3xxx_gpio5_irqs[] = {
-	{ .irq = 33 }, /* INT_34XX_GPIO_BANK5 */
+/* mcspi3 */
+static struct omap_hwmod_irq_info omap34xx_mcspi3_mpu_irqs[] = {
+	{ .name = "irq", .irq = 91 }, /* 91 */
 };
 
-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio5_dbck", },
+static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 15 },
+	{ .name = "rx0", .dma_req = 16 },
+	{ .name = "tx1", .dma_req = 23 },
+	{ .name = "rx1", .dma_req = 24 },
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
-	&omap3xxx_l4_per__gpio5,
+static struct omap_hwmod_ocp_if *omap34xx_mcspi3_slaves[] = {
+	&omap34xx_l4_core__mcspi3,
 };
 
-static struct omap_hwmod omap3xxx_gpio5_hwmod = {
-	.name		= "gpio5",
-	.mpu_irqs	= omap3xxx_gpio5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
-	.main_clk	= "gpio5_ick",
-	.opt_clks	= gpio5_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
+static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap34xx_mcspi3 = {
+	.name		= "mcspi3",
+	.mpu_irqs	= omap34xx_mcspi3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_sdma_reqs),
+	.main_clk	= "mcspi3_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_GPIO5_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
+			.module_bit = OMAP3430_EN_MCSPI3_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_GPIO5_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI3_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_gpio5_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio5_slaves),
-	.class		= &omap3xxx_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap34xx_mcspi3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi3_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi3_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-/* gpio6 */
-static struct omap_hwmod_irq_info omap3xxx_gpio6_irqs[] = {
-	{ .irq = 34 }, /* INT_34XX_GPIO_BANK6 */
+/* SPI4 */
+static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
+	{ .name = "irq", .irq = INT_34XX_SPI4_IRQ }, /* 48 */
 };
 
-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio6_dbck", },
+static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 70 }, /* DMA_SPI4_TX0 */
+	{ .name = "rx0", .dma_req = 71 }, /* DMA_SPI4_RX0 */
 };
 
-static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
-	&omap3xxx_l4_per__gpio6,
+static struct omap_hwmod_ocp_if *omap34xx_mcspi4_slaves[] = {
+	&omap34xx_l4_core__mcspi4,
 };
 
-static struct omap_hwmod omap3xxx_gpio6_hwmod = {
-	.name		= "gpio6",
-	.mpu_irqs	= omap3xxx_gpio6_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
-	.main_clk	= "gpio6_ick",
-	.opt_clks	= gpio6_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
+static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
+	.num_chipselect = 1,
+};
+
+static struct omap_hwmod omap34xx_mcspi4 = {
+	.name		= "mcspi4",
+	.mpu_irqs	= omap34xx_mcspi4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_sdma_reqs),
+	.main_clk	= "mcspi4_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_GPIO6_SHIFT,
-			.module_offs = OMAP3430_PER_MOD,
+			.module_bit = OMAP3430_EN_MCSPI4_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_ST_GPIO6_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI4_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_gpio6_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_gpio6_slaves),
-	.class		= &omap3xxx_gpio_hwmod_class,
-	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap34xx_mcspi4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi4_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi4_dev_attr,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-/* dma_system -> L3 */
-static struct omap_hwmod_ocp_if omap3xxx_dma_system__l3 = {
-	.master		= &omap3xxx_dma_system_hwmod,
-	.slave		= &omap3xxx_l3_main_hwmod,
-	.clk		= "core_l3_ick",
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
-};
-
-/* dma attributes */
-static struct omap_dma_dev_attr dma_dev_attr = {
-	.dev_caps  = RESERVE_CHANNEL | DMA_LINKED_LCH | GLOBAL_PRIORITY |
-				IS_CSSA_32 | IS_CDSA_32 | IS_RW_PRIORITY,
-	.lch_count = 32,
-};
-
-static struct omap_hwmod_class_sysconfig omap3xxx_dma_sysc = {
-	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x002c,
-	.syss_offs	= 0x0028,
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+/*
+ * usbhsotg
+ */
+static struct omap_hwmod_class_sysconfig omap3xxx_usbhsotg_sysc = {
+	.rev_offs	= 0x0400,
+	.sysc_offs	= 0x0404,
+	.syss_offs	= 0x0408,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE|
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_AUTOIDLE),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+			  MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_class omap3xxx_dma_hwmod_class = {
-	.name = "dma",
-	.sysc = &omap3xxx_dma_sysc,
+static struct omap_hwmod_class usbotg_class = {
+	.name = "usbotg",
+	.sysc = &omap3xxx_usbhsotg_sysc,
 };
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
 
-/* dma_system */
-static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
-	{ .name = "0", .irq = 12 }, /* INT_24XX_SDMA_IRQ0 */
-	{ .name = "1", .irq = 13 }, /* INT_24XX_SDMA_IRQ1 */
-	{ .name = "2", .irq = 14 }, /* INT_24XX_SDMA_IRQ2 */
-	{ .name = "3", .irq = 15 }, /* INT_24XX_SDMA_IRQ3 */
+	{ .name = "mc", .irq = 92 },
+	{ .name = "dma", .irq = 93 },
 };
 
-static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
-	{
-		.pa_start	= 0x48056000,
-		.pa_end		= 0x4a0560ff,
-		.flags		= ADDR_TYPE_RT
+static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
+	.name		= "usb_otg_hs",
+	.mpu_irqs	= omap3xxx_usbhsotg_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_mpu_irqs),
+	.main_clk	= "hsotgusb_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT,
+			.idlest_stdby_bit = OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT
+		},
 	},
+	.masters	= omap3xxx_usbhsotg_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_masters),
+	.slaves		= omap3xxx_usbhsotg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_slaves),
+	.class		= &usbotg_class,
+
+	/*
+	 * Erratum ID: i479  idle_req / idle_ack mechanism potentially
+	 * broken when autoidle is enabled
+	 * workaround is to disable the autoidle bit at module level.
+	 */
+	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
+				| HWMOD_SWSUP_MSTANDBY,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
-/* dma_system master ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dma_system_masters[] = {
-	&omap3xxx_dma_system__l3,
-};
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
 
-/* l4_cfg -> dma_system */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__dma_system = {
-	.master		= &omap3xxx_l4_core_hwmod,
-	.slave		= &omap3xxx_dma_system_hwmod,
-	.clk		= "core_l4_ick",
-	.addr		= omap3xxx_dma_system_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap3xxx_dma_system_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	{ .name = "mc", .irq = 71 },
 };
 
-/* dma_system slave ports */
-static struct omap_hwmod_ocp_if *omap3xxx_dma_system_slaves[] = {
-	&omap3xxx_l4_core__dma_system,
+static struct omap_hwmod_class am35xx_usbotg_class = {
+	.name = "am35xx_usbotg",
+	.sysc = NULL,
 };
 
-static struct omap_hwmod omap3xxx_dma_system_hwmod = {
-	.name		= "dma",
-	.class		= &omap3xxx_dma_hwmod_class,
-	.mpu_irqs	= omap3xxx_dma_system_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dma_system_irqs),
-	.main_clk	= "core_l3_ick",
+static struct omap_hwmod am35xx_usbhsotg_hwmod = {
+	.name		= "am35x_otg_hs",
+	.mpu_irqs	= am35xx_usbhsotg_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(am35xx_usbhsotg_mpu_irqs),
+	.main_clk	= NULL,
 	.prcm = {
 		.omap2 = {
-			.module_offs		= CORE_MOD,
-			.prcm_reg_id		= 1,
-			.module_bit		= OMAP3430_ST_SDMA_SHIFT,
-			.idlest_reg_id		= 1,
-			.idlest_idle_bit	= OMAP3430_ST_SDMA_SHIFT,
 		},
 	},
-	.slaves		= omap3xxx_dma_system_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dma_system_slaves),
-	.masters	= omap3xxx_dma_system_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_dma_system_masters),
-	.dev_attr	= &dma_dev_attr,
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
-	.flags		= HWMOD_NO_IDLEST,
+	.masters	= am35xx_usbhsotg_masters,
+	.masters_cnt	= ARRAY_SIZE(am35xx_usbhsotg_masters),
+	.slaves		= am35xx_usbhsotg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(am35xx_usbhsotg_slaves),
+	.class		= &am35xx_usbotg_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1)
 };
 
-/* SR common */
-static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
-	.clkact_shift	= 20,
+/* MMC/SD/SDIO common */
+
+static struct omap_hwmod_class_sysconfig omap34xx_mmc_sysc = {
+	.rev_offs	= 0x1fc,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
-	.sysc_offs	= 0x24,
-	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
-	.clockact	= CLOCKACT_TEST_ICLK,
-	.sysc_fields	= &omap34xx_sr_sysc_fields,
+static struct omap_hwmod_class omap34xx_mmc_class = {
+	.name = "mmc",
+	.sysc = &omap34xx_mmc_sysc,
 };
 
-static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
-	.name = "smartreflex",
-	.sysc = &omap34xx_sr_sysc,
-	.rev  = 1,
+/* MMC/SD/SDIO1 */
+
+static struct omap_hwmod_irq_info omap34xx_mmc1_mpu_irqs[] = {
+	{ .irq = 83, },
 };
 
-static struct omap_hwmod_sysc_fields omap36xx_sr_sysc_fields = {
-	.sidle_shift	= 24,
-	.enwkup_shift	= 26
+static struct omap_hwmod_dma_info omap34xx_mmc1_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 61, },
+	{ .name = "rx",	.dma_req = 62, },
 };
 
-static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
-	.sysc_offs	= 0x38,
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
-			SYSC_NO_CACHE),
-	.sysc_fields	= &omap36xx_sr_sysc_fields,
+static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
+	{ .role = "dbck", .clk = "omap_32k_fck", },
 };
 
-static struct omap_hwmod_class omap36xx_smartreflex_hwmod_class = {
-	.name = "smartreflex",
-	.sysc = &omap36xx_sr_sysc,
-	.rev  = 2,
+static struct omap_hwmod_ocp_if *omap3xxx_mmc1_slaves[] = {
+	&omap3xxx_l4_core__mmc1,
 };
 
-/* SR1 */
-static struct omap_hwmod_ocp_if *omap3_sr1_slaves[] = {
-	&omap3_l4_core__sr1,
+static struct omap_mmc_dev_attr mmc1_dev_attr = {
+	.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
 };
 
-static struct omap_hwmod omap34xx_sr1_hwmod = {
-	.name		= "sr1_hwmod",
-	.class		= &omap34xx_smartreflex_hwmod_class,
-	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
+static struct omap_hwmod omap3xxx_mmc1_hwmod = {
+	.name		= "mmc1",
+	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_mpu_irqs),
+	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_sdma_reqs),
+	.opt_clks	= omap34xx_mmc1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc1_opt_clks),
+	.main_clk	= "mmchs1_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_SR1_SHIFT,
-			.module_offs = WKUP_MOD,
+			.module_bit = OMAP3430_EN_MMC1_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_MMC1_SHIFT,
 		},
 	},
-	.slaves		= omap3_sr1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
-	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+	.dev_attr	= &mmc1_dev_attr,
+	.slaves		= omap3xxx_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc1_slaves),
+	.class		= &omap34xx_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-static struct omap_hwmod omap36xx_sr1_hwmod = {
-	.name		= "sr1_hwmod",
-	.class		= &omap36xx_smartreflex_hwmod_class,
-	.main_clk	= "sr1_fck",
-	.vdd_name	= "mpu",
-	.prcm		= {
-		.omap2 = {
-			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_SR1_SHIFT,
-			.module_offs = WKUP_MOD,
-			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_SR1_SHIFT,
-		},
-	},
-	.slaves		= omap3_sr1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3_sr1_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+/* MMC/SD/SDIO2 */
+
+static struct omap_hwmod_irq_info omap34xx_mmc2_mpu_irqs[] = {
+	{ .irq = INT_24XX_MMC2_IRQ, },
 };
 
-/* SR2 */
-static struct omap_hwmod_ocp_if *omap3_sr2_slaves[] = {
-	&omap3_l4_core__sr2,
+static struct omap_hwmod_dma_info omap34xx_mmc2_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 47, },
+	{ .name = "rx",	.dma_req = 48, },
 };
 
-static struct omap_hwmod omap34xx_sr2_hwmod = {
-	.name		= "sr2_hwmod",
-	.class		= &omap34xx_smartreflex_hwmod_class,
-	.main_clk	= "sr2_fck",
-	.vdd_name	= "core",
+static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
+	{ .role = "dbck", .clk = "omap_32k_fck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
+	&omap3xxx_l4_core__mmc2,
+};
+
+static struct omap_hwmod omap3xxx_mmc2_hwmod = {
+	.name		= "mmc2",
+	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_mpu_irqs),
+	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_sdma_reqs),
+	.opt_clks	= omap34xx_mmc2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc2_opt_clks),
+	.main_clk	= "mmchs2_fck",
 	.prcm		= {
 		.omap2 = {
+			.module_offs = CORE_MOD,
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_SR2_SHIFT,
-			.module_offs = WKUP_MOD,
+			.module_bit = OMAP3430_EN_MMC2_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_MMC2_SHIFT,
 		},
 	},
-	.slaves		= omap3_sr2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2 |
-					CHIP_IS_OMAP3430ES3_0 |
-					CHIP_IS_OMAP3430ES3_1),
-	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
+	.slaves		= omap3xxx_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc2_slaves),
+	.class		= &omap34xx_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
-static struct omap_hwmod omap36xx_sr2_hwmod = {
-	.name		= "sr2_hwmod",
-	.class		= &omap36xx_smartreflex_hwmod_class,
-	.main_clk	= "sr2_fck",
-	.vdd_name	= "core",
+/* MMC/SD/SDIO3 */
+
+static struct omap_hwmod_irq_info omap34xx_mmc3_mpu_irqs[] = {
+	{ .irq = 94, },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mmc3_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 77, },
+	{ .name = "rx",	.dma_req = 78, },
+};
+
+static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = {
+	{ .role = "dbck", .clk = "omap_32k_fck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
+	&omap3xxx_l4_core__mmc3,
+};
+
+static struct omap_hwmod omap3xxx_mmc3_hwmod = {
+	.name		= "mmc3",
+	.mpu_irqs	= omap34xx_mmc3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_mpu_irqs),
+	.sdma_reqs	= omap34xx_mmc3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_sdma_reqs),
+	.opt_clks	= omap34xx_mmc3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc3_opt_clks),
+	.main_clk	= "mmchs3_fck",
 	.prcm		= {
 		.omap2 = {
 			.prcm_reg_id = 1,
-			.module_bit = OMAP3430_EN_SR2_SHIFT,
-			.module_offs = WKUP_MOD,
+			.module_bit = OMAP3430_EN_MMC3_SHIFT,
 			.idlest_reg_id = 1,
-			.idlest_idle_bit = OMAP3430_EN_SR2_SHIFT,
+			.idlest_idle_bit = OMAP3430_ST_MMC3_SHIFT,
 		},
 	},
-	.slaves		= omap3_sr2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap3_sr2_slaves),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+	.slaves		= omap3xxx_mmc3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc3_slaves),
+	.class		= &omap34xx_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 };
 
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
@@ -1361,13 +3570,39 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l4_core_hwmod,
 	&omap3xxx_l4_per_hwmod,
 	&omap3xxx_l4_wkup_hwmod,
+	&omap3xxx_mmc1_hwmod,
+	&omap3xxx_mmc2_hwmod,
+	&omap3xxx_mmc3_hwmod,
 	&omap3xxx_mpu_hwmod,
 	&omap3xxx_iva_hwmod,
+
+	&omap3xxx_timer1_hwmod,
+	&omap3xxx_timer2_hwmod,
+	&omap3xxx_timer3_hwmod,
+	&omap3xxx_timer4_hwmod,
+	&omap3xxx_timer5_hwmod,
+	&omap3xxx_timer6_hwmod,
+	&omap3xxx_timer7_hwmod,
+	&omap3xxx_timer8_hwmod,
+	&omap3xxx_timer9_hwmod,
+	&omap3xxx_timer10_hwmod,
+	&omap3xxx_timer11_hwmod,
+	&omap3xxx_timer12_hwmod,
+
 	&omap3xxx_wd_timer2_hwmod,
 	&omap3xxx_uart1_hwmod,
 	&omap3xxx_uart2_hwmod,
 	&omap3xxx_uart3_hwmod,
 	&omap3xxx_uart4_hwmod,
+	/* dss class */
+	&omap3430es1_dss_core_hwmod,
+	&omap3xxx_dss_core_hwmod,
+	&omap3xxx_dss_dispc_hwmod,
+	&omap3xxx_dss_dsi1_hwmod,
+	&omap3xxx_dss_rfbi_hwmod,
+	&omap3xxx_dss_venc_hwmod,
+
+	/* i2c class */
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
@@ -1387,10 +3622,35 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 
 	/* dma_system class*/
 	&omap3xxx_dma_system_hwmod,
+
+	/* mcbsp class */
+	&omap3xxx_mcbsp1_hwmod,
+	&omap3xxx_mcbsp2_hwmod,
+	&omap3xxx_mcbsp3_hwmod,
+	&omap3xxx_mcbsp4_hwmod,
+	&omap3xxx_mcbsp5_hwmod,
+	&omap3xxx_mcbsp2_sidetone_hwmod,
+	&omap3xxx_mcbsp3_sidetone_hwmod,
+
+	/* mailbox class */
+	&omap3xxx_mailbox_hwmod,
+
+	/* mcspi class */
+	&omap34xx_mcspi1,
+	&omap34xx_mcspi2,
+	&omap34xx_mcspi3,
+	&omap34xx_mcspi4,
+
+	/* usbotg class */
+	&omap3xxx_usbhsotg_hwmod,
+
+	/* usbotg for am35x */
+	&am35xx_usbhsotg_hwmod,
+
 	NULL,
 };
 
 int __init omap3xxx_hwmod_init(void)
 {
-	return omap_hwmod_init(omap3xxx_hwmods);
+	return omap_hwmod_register(omap3xxx_hwmods);
 }
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index c2806bd..3e88dd3 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1,7 +1,7 @@
 /*
  * Hardware modules present on the OMAP44xx chips
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley
@@ -24,6 +24,9 @@
 #include <plat/cpu.h>
 #include <plat/gpio.h>
 #include <plat/dma.h>
+#include <plat/mcspi.h>
+#include <plat/mcbsp.h>
+#include <plat/mmc.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -40,10 +43,15 @@
 #define OMAP44XX_DMA_REQ_START  1
 
 /* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_aess_hwmod;
 static struct omap_hwmod omap44xx_dma_system_hwmod;
 static struct omap_hwmod omap44xx_dmm_hwmod;
 static struct omap_hwmod omap44xx_dsp_hwmod;
+static struct omap_hwmod omap44xx_dss_hwmod;
 static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_hsi_hwmod;
+static struct omap_hwmod omap44xx_ipu_hwmod;
+static struct omap_hwmod omap44xx_iss_hwmod;
 static struct omap_hwmod omap44xx_iva_hwmod;
 static struct omap_hwmod omap44xx_l3_instr_hwmod;
 static struct omap_hwmod omap44xx_l3_main_1_hwmod;
@@ -53,8 +61,11 @@ static struct omap_hwmod omap44xx_l4_abe_hwmod;
 static struct omap_hwmod omap44xx_l4_cfg_hwmod;
 static struct omap_hwmod omap44xx_l4_per_hwmod;
 static struct omap_hwmod omap44xx_l4_wkup_hwmod;
+static struct omap_hwmod omap44xx_mmc1_hwmod;
+static struct omap_hwmod omap44xx_mmc2_hwmod;
 static struct omap_hwmod omap44xx_mpu_hwmod;
 static struct omap_hwmod omap44xx_mpu_private_hwmod;
+static struct omap_hwmod omap44xx_usb_otg_hs_hwmod;
 
 /*
  * Interconnects omap_hwmod structures
@@ -213,6 +224,14 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__l3_main_1 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* dss -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = {
+	.master		= &omap44xx_dss_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_2 -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
@@ -229,25 +248,62 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* mmc1 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mmc1__l3_main_1 = {
+	.master		= &omap44xx_mmc1_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
+	.master		= &omap44xx_mmc2_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L3 target configuration and error log registers */
+static struct omap_hwmod_irq_info omap44xx_l3_targ_irqs[] = {
+	{ .irq = 9  + OMAP44XX_IRQ_GIC_START },
+	{ .irq = 10 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
+	{
+		.pa_start	= 0x44000000,
+		.pa_end		= 0x44000fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* mpu -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
 	.master		= &omap44xx_mpu_hwmod,
 	.slave		= &omap44xx_l3_main_1_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l3_main_1 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
 	&omap44xx_dsp__l3_main_1,
+	&omap44xx_dss__l3_main_1,
 	&omap44xx_l3_main_2__l3_main_1,
 	&omap44xx_l4_cfg__l3_main_1,
+	&omap44xx_mmc1__l3_main_1,
+	&omap44xx_mmc2__l3_main_1,
 	&omap44xx_mpu__l3_main_1,
 };
 
 static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	.name		= "l3_main_1",
 	.class		= &omap44xx_l3_hwmod_class,
+	.mpu_irqs	= omap44xx_l3_targ_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_l3_targ_irqs),
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -262,6 +318,30 @@ static struct omap_hwmod_ocp_if omap44xx_dma_system__l3_main_2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* hsi -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_hsi__l3_main_2 = {
+	.master		= &omap44xx_hsi_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ipu -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = {
+	.master		= &omap44xx_ipu_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iss -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = {
+	.master		= &omap44xx_iss_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* iva -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
 	.master		= &omap44xx_iva_hwmod,
@@ -270,11 +350,21 @@ static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
+	{
+		.pa_start	= 0x44800000,
+		.pa_end		= 0x44801fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* l3_main_1 -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -286,12 +376,24 @@ static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* usb_otg_hs -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_usb_otg_hs__l3_main_2 = {
+	.master		= &omap44xx_usb_otg_hs_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_2 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
 	&omap44xx_dma_system__l3_main_2,
+	&omap44xx_hsi__l3_main_2,
+	&omap44xx_ipu__l3_main_2,
+	&omap44xx_iss__l3_main_2,
 	&omap44xx_iva__l3_main_2,
 	&omap44xx_l3_main_1__l3_main_2,
 	&omap44xx_l4_cfg__l3_main_2,
+	&omap44xx_usb_otg_hs__l3_main_2,
 };
 
 static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
@@ -303,11 +405,21 @@ static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
 };
 
 /* l3_main_3 interface data */
+static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
+	{
+		.pa_start	= 0x45000000,
+		.pa_end		= 0x45000fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* l3_main_1 -> l3_main_3 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_l3_main_3_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -351,6 +463,14 @@ static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
 };
 
 /* l4_abe interface data */
+/* aess -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_aess__l4_abe = {
+	.master		= &omap44xx_aess_hwmod,
+	.slave		= &omap44xx_l4_abe_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* dsp -> l4_abe */
 static struct omap_hwmod_ocp_if omap44xx_dsp__l4_abe = {
 	.master		= &omap44xx_dsp_hwmod,
@@ -377,6 +497,7 @@ static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
 
 /* l4_abe slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+	&omap44xx_aess__l4_abe,
 	&omap44xx_dsp__l4_abe,
 	&omap44xx_l3_main_1__l4_abe,
 	&omap44xx_mpu__l4_abe,
@@ -494,26 +615,15 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
  * - They still need to be validated with the driver
  *   properly adapted to omap_hwmod / omap_device
  *
- *  aess
- *  bandgap
  *  c2c
  *  c2c_target_fw
  *  cm_core
  *  cm_core_aon
- *  counter_32k
  *  ctrl_module_core
  *  ctrl_module_pad_core
  *  ctrl_module_pad_wkup
  *  ctrl_module_wkup
  *  debugss
- *  dmic
- *  dss
- *  dss_dispc
- *  dss_dsi1
- *  dss_dsi2
- *  dss_hdmi
- *  dss_rfbi
- *  dss_venc
  *  efuse_ctrl_cust
  *  efuse_ctrl_std
  *  elm
@@ -524,58 +634,211 @@ static struct omap_hwmod omap44xx_mpu_private_hwmod = {
  *  gpu
  *  hdq1w
  *  hsi
- *  ipu
- *  iss
- *  kbd
- *  mailbox
- *  mcasp
- *  mcbsp1
- *  mcbsp2
- *  mcbsp3
- *  mcbsp4
- *  mcpdm
- *  mcspi1
- *  mcspi2
- *  mcspi3
- *  mcspi4
- *  mmc1
- *  mmc2
- *  mmc3
- *  mmc4
- *  mmc5
- *  mpu_c0
- *  mpu_c1
  *  ocmc_ram
  *  ocp2scp_usb_phy
  *  ocp_wp_noc
- *  prcm
  *  prcm_mpu
  *  prm
  *  scrm
  *  sl2if
  *  slimbus1
  *  slimbus2
- *  spinlock
- *  timer1
- *  timer10
- *  timer11
- *  timer2
- *  timer3
- *  timer4
- *  timer5
- *  timer6
- *  timer7
- *  timer8
- *  timer9
  *  usb_host_fs
  *  usb_host_hs
- *  usb_otg_hs
  *  usb_phy_cm
  *  usb_tll_hs
  *  usim
  */
 
 /*
+ * 'aess' class
+ * audio engine sub system
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_aess_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_aess_hwmod_class = {
+	.name	= "aess",
+	.sysc	= &omap44xx_aess_sysc,
+};
+
+/* aess */
+static struct omap_hwmod_irq_info omap44xx_aess_irqs[] = {
+	{ .irq = 99 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
+	{ .name = "fifo0", .dma_req = 100 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo1", .dma_req = 101 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo2", .dma_req = 102 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo3", .dma_req = 103 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo4", .dma_req = 104 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo5", .dma_req = 105 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo6", .dma_req = 106 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo7", .dma_req = 107 + OMAP44XX_DMA_REQ_START },
+};
+
+/* aess master ports */
+static struct omap_hwmod_ocp_if *omap44xx_aess_masters[] = {
+	&omap44xx_aess__l4_abe,
+};
+
+static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = {
+	{
+		.pa_start	= 0x401f1000,
+		.pa_end		= 0x401f13ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> aess */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_aess_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_aess_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_aess_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = {
+	{
+		.pa_start	= 0x490f1000,
+		.pa_end		= 0x490f13ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> aess (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_aess_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_aess_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_aess_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* aess slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_aess_slaves[] = {
+	&omap44xx_l4_abe__aess,
+	&omap44xx_l4_abe__aess_dma,
+};
+
+static struct omap_hwmod omap44xx_aess_hwmod = {
+	.name		= "aess",
+	.class		= &omap44xx_aess_hwmod_class,
+	.mpu_irqs	= omap44xx_aess_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_aess_irqs),
+	.sdma_reqs	= omap44xx_aess_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_aess_sdma_reqs),
+	.main_clk	= "aess_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_aess_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_aess_slaves),
+	.masters	= omap44xx_aess_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_aess_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'bandgap' class
+ * bangap reference for ldo regulators
+ */
+
+static struct omap_hwmod_class omap44xx_bandgap_hwmod_class = {
+	.name	= "bandgap",
+};
+
+/* bandgap */
+static struct omap_hwmod_opt_clk bandgap_opt_clks[] = {
+	{ .role = "fclk", .clk = "bandgap_fclk" },
+};
+
+static struct omap_hwmod omap44xx_bandgap_hwmod = {
+	.name		= "bandgap",
+	.class		= &omap44xx_bandgap_hwmod_class,
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+		},
+	},
+	.opt_clks	= bandgap_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(bandgap_opt_clks),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'counter' class
+ * 32-bit ordinary counter, clocked by the falling edge of the 32 khz clock
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_counter_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0004,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_counter_hwmod_class = {
+	.name	= "counter",
+	.sysc	= &omap44xx_counter_sysc,
+};
+
+/* counter_32k */
+static struct omap_hwmod omap44xx_counter_32k_hwmod;
+static struct omap_hwmod_addr_space omap44xx_counter_32k_addrs[] = {
+	{
+		.pa_start	= 0x4a304000,
+		.pa_end		= 0x4a30401f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> counter_32k */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__counter_32k = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_counter_32k_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_counter_32k_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_counter_32k_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* counter_32k slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_counter_32k_slaves[] = {
+	&omap44xx_l4_wkup__counter_32k,
+};
+
+static struct omap_hwmod omap44xx_counter_32k_hwmod = {
+	.name		= "counter_32k",
+	.class		= &omap44xx_counter_hwmod_class,
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.main_clk	= "sys_32k_ck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_counter_32k_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_counter_32k_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'dma' class
  * dma controller for data exchange between memory to memory (i.e. internal or
  * external memory) and gp peripherals to memory or memory to gp peripherals
@@ -662,6 +925,96 @@ static struct omap_hwmod omap44xx_dma_system_hwmod = {
 };
 
 /*
+ * 'dmic' class
+ * digital microphone controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dmic_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_dmic_hwmod_class = {
+	.name	= "dmic",
+	.sysc	= &omap44xx_dmic_sysc,
+};
+
+/* dmic */
+static struct omap_hwmod omap44xx_dmic_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dmic_irqs[] = {
+	{ .irq = 114 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
+	{ .dma_req = 66 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
+	{
+		.pa_start	= 0x4012e000,
+		.pa_end		= 0x4012e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> dmic */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_dmic_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_dmic_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dmic_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
+	{
+		.pa_start	= 0x4902e000,
+		.pa_end		= 0x4902e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> dmic (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_dmic_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_dmic_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dmic_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* dmic slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dmic_slaves[] = {
+	&omap44xx_l4_abe__dmic,
+	&omap44xx_l4_abe__dmic_dma,
+};
+
+static struct omap_hwmod omap44xx_dmic_hwmod = {
+	.name		= "dmic",
+	.class		= &omap44xx_dmic_hwmod_class,
+	.mpu_irqs	= omap44xx_dmic_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dmic_irqs),
+	.sdma_reqs	= omap44xx_dmic_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dmic_sdma_reqs),
+	.main_clk	= "dmic_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dmic_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmic_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'dsp' class
  * dsp sub-system
  */
@@ -747,894 +1100,3485 @@ static struct omap_hwmod omap44xx_dsp_hwmod = {
 };
 
 /*
- * 'gpio' class
- * general purpose io module
+ * 'dss' class
+ * display sub-system
  */
 
-static struct omap_hwmod_class_sysconfig omap44xx_gpio_sysc = {
+static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = {
 	.rev_offs	= 0x0000,
-	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0114,
-	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
-			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
-			   SYSS_HAS_RESET_STATUS),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
 };
 
-static struct omap_hwmod_class omap44xx_gpio_hwmod_class = {
-	.name	= "gpio",
-	.sysc	= &omap44xx_gpio_sysc,
-	.rev	= 2,
+static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
+	.name	= "dss",
+	.sysc	= &omap44xx_dss_sysc,
 };
 
-/* gpio dev_attr */
-static struct omap_gpio_dev_attr gpio_dev_attr = {
-	.bank_width	= 32,
-	.dbck_flag	= true,
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_masters[] = {
+	&omap44xx_dss__l3_main_1,
 };
 
-/* gpio1 */
-static struct omap_hwmod omap44xx_gpio1_hwmod;
-static struct omap_hwmod_irq_info omap44xx_gpio1_irqs[] = {
-	{ .irq = 29 + OMAP44XX_IRQ_GIC_START },
+static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
+	{
+		.pa_start	= 0x58000000,
+		.pa_end		= 0x5800007f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
+/* l3_main_2 -> dss */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = {
 	{
-		.pa_start	= 0x4a310000,
-		.pa_end		= 0x4a3101ff,
+		.pa_start	= 0x48040000,
+		.pa_end		= 0x4804007f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_wkup -> gpio1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
-	.master		= &omap44xx_l4_wkup_hwmod,
-	.slave		= &omap44xx_gpio1_hwmod,
-	.clk		= "l4_wkup_clk_mux_ck",
-	.addr		= omap44xx_gpio1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio1_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* l4_per -> dss */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-/* gpio1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio1_slaves[] = {
-	&omap44xx_l4_wkup__gpio1,
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
+	&omap44xx_l3_main_2__dss,
+	&omap44xx_l4_per__dss,
 };
 
-static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio1_dbclk" },
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+	{ .role = "dss_clk", .clk = "dss_dss_clk" },
+	{ .role = "video_clk", .clk = "dss_48mhz_clk" },
 };
 
-static struct omap_hwmod omap44xx_gpio1_hwmod = {
-	.name		= "gpio1",
-	.class		= &omap44xx_gpio_hwmod_class,
-	.mpu_irqs	= omap44xx_gpio1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio1_irqs),
-	.main_clk	= "gpio1_ick",
+static struct omap_hwmod omap44xx_dss_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap44xx_dss_hwmod_class,
+	.main_clk	= "dss_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
-	.opt_clks	= gpio1_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-	.slaves		= omap44xx_gpio1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio1_slaves),
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap44xx_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_slaves),
+	.masters	= omap44xx_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_dss_masters),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* gpio2 */
-static struct omap_hwmod omap44xx_gpio2_hwmod;
-static struct omap_hwmod_irq_info omap44xx_gpio2_irqs[] = {
-	{ .irq = 30 + OMAP44XX_IRQ_GIC_START },
-};
+/*
+ * 'dispc' class
+ * display controller
+ */
 
-static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
-	{
-		.pa_start	= 0x48055000,
-		.pa_end		= 0x480551ff,
+static struct omap_hwmod_class_sysconfig omap44xx_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_dispc_hwmod_class = {
+	.name	= "dispc",
+	.sysc	= &omap44xx_dispc_sysc,
+};
+
+/* dss_dispc */
+static struct omap_hwmod omap44xx_dss_dispc_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_dispc_irqs[] = {
+	{ .irq = 25 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_dispc_sdma_reqs[] = {
+	{ .dma_req = 5 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
+	{
+		.pa_start	= 0x58001000,
+		.pa_end		= 0x58001fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> gpio2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
-	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_gpio2_hwmod,
-	.clk		= "l4_div_ck",
-	.addr		= omap44xx_gpio2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio2_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* l3_main_2 -> dss_dispc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_dispc_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dispc_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* gpio2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio2_slaves[] = {
-	&omap44xx_l4_per__gpio2,
+static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48041000,
+		.pa_end		= 0x48041fff,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio2_dbclk" },
+/* l4_per -> dss_dispc */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_dispc_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod omap44xx_gpio2_hwmod = {
-	.name		= "gpio2",
-	.class		= &omap44xx_gpio_hwmod_class,
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap44xx_gpio2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio2_irqs),
-	.main_clk	= "gpio2_ick",
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
+	&omap44xx_l3_main_2__dss_dispc,
+	&omap44xx_l4_per__dss_dispc,
+};
+
+static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap44xx_dispc_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
+	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
+	.main_clk	= "dss_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
-	.opt_clks	= gpio2_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-	.slaves		= omap44xx_gpio2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio2_slaves),
+	.slaves		= omap44xx_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* gpio3 */
-static struct omap_hwmod omap44xx_gpio3_hwmod;
-static struct omap_hwmod_irq_info omap44xx_gpio3_irqs[] = {
-	{ .irq = 31 + OMAP44XX_IRQ_GIC_START },
+/*
+ * 'dsi' class
+ * display serial interface controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dsi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
+static struct omap_hwmod_class omap44xx_dsi_hwmod_class = {
+	.name	= "dsi",
+	.sysc	= &omap44xx_dsi_sysc,
+};
+
+/* dss_dsi1 */
+static struct omap_hwmod omap44xx_dss_dsi1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_dsi1_irqs[] = {
+	{ .irq = 53 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_dsi1_sdma_reqs[] = {
+	{ .dma_req = 74 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
 	{
-		.pa_start	= 0x48057000,
-		.pa_end		= 0x480571ff,
+		.pa_start	= 0x58004000,
+		.pa_end		= 0x580041ff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> gpio3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
-	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_gpio3_hwmod,
-	.clk		= "l4_div_ck",
-	.addr		= omap44xx_gpio3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio3_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* l3_main_2 -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_dsi1_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dsi1_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* gpio3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio3_slaves[] = {
-	&omap44xx_l4_per__gpio3,
+static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = {
+	{
+		.pa_start	= 0x48044000,
+		.pa_end		= 0x480441ff,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio3_dbclk" },
+/* l4_per -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_dsi1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_dsi1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod omap44xx_gpio3_hwmod = {
-	.name		= "gpio3",
-	.class		= &omap44xx_gpio_hwmod_class,
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap44xx_gpio3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio3_irqs),
-	.main_clk	= "gpio3_ick",
+/* dss_dsi1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
+	&omap44xx_l3_main_2__dss_dsi1,
+	&omap44xx_l4_per__dss_dsi1,
+};
+
+static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
+	.name		= "dss_dsi1",
+	.class		= &omap44xx_dsi_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_dsi1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
+	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
+	.main_clk	= "dss_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
-	.opt_clks	= gpio3_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-	.slaves		= omap44xx_gpio3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio3_slaves),
+	.slaves		= omap44xx_dss_dsi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* gpio4 */
-static struct omap_hwmod omap44xx_gpio4_hwmod;
-static struct omap_hwmod_irq_info omap44xx_gpio4_irqs[] = {
-	{ .irq = 32 + OMAP44XX_IRQ_GIC_START },
+/* dss_dsi2 */
+static struct omap_hwmod omap44xx_dss_dsi2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_dsi2_irqs[] = {
+	{ .irq = 84 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
+static struct omap_hwmod_dma_info omap44xx_dss_dsi2_sdma_reqs[] = {
+	{ .dma_req = 83 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
 	{
-		.pa_start	= 0x48059000,
-		.pa_end		= 0x480591ff,
+		.pa_start	= 0x58005000,
+		.pa_end		= 0x580051ff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> gpio4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
-	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_gpio4_hwmod,
-	.clk		= "l4_div_ck",
-	.addr		= omap44xx_gpio4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio4_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* l3_main_2 -> dss_dsi2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_dsi2_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dsi2_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* gpio4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio4_slaves[] = {
-	&omap44xx_l4_per__gpio4,
+static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = {
+	{
+		.pa_start	= 0x48045000,
+		.pa_end		= 0x480451ff,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio4_dbclk" },
+/* l4_per -> dss_dsi2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_dsi2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_dsi2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod omap44xx_gpio4_hwmod = {
-	.name		= "gpio4",
-	.class		= &omap44xx_gpio_hwmod_class,
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap44xx_gpio4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio4_irqs),
-	.main_clk	= "gpio4_ick",
+/* dss_dsi2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
+	&omap44xx_l3_main_2__dss_dsi2,
+	&omap44xx_l4_per__dss_dsi2,
+};
+
+static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
+	.name		= "dss_dsi2",
+	.class		= &omap44xx_dsi_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_dsi2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
+	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
+	.main_clk	= "dss_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
-	.opt_clks	= gpio4_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-	.slaves		= omap44xx_gpio4_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio4_slaves),
+	.slaves		= omap44xx_dss_dsi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* gpio5 */
-static struct omap_hwmod omap44xx_gpio5_hwmod;
-static struct omap_hwmod_irq_info omap44xx_gpio5_irqs[] = {
-	{ .irq = 33 + OMAP44XX_IRQ_GIC_START },
+/*
+ * 'hdmi' class
+ * hdmi controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_hdmi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
 };
 
-static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
+static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = {
+	.name	= "hdmi",
+	.sysc	= &omap44xx_hdmi_sysc,
+};
+
+/* dss_hdmi */
+static struct omap_hwmod omap44xx_dss_hdmi_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_hdmi_irqs[] = {
+	{ .irq = 101 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = {
+	{ .dma_req = 75 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
 	{
-		.pa_start	= 0x4805b000,
-		.pa_end		= 0x4805b1ff,
+		.pa_start	= 0x58006000,
+		.pa_end		= 0x58006fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> gpio5 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
-	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_gpio5_hwmod,
-	.clk		= "l4_div_ck",
-	.addr		= omap44xx_gpio5_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio5_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* l3_main_2 -> dss_hdmi */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_hdmi_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_hdmi_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* gpio5 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio5_slaves[] = {
-	&omap44xx_l4_per__gpio5,
+static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = {
+	{
+		.pa_start	= 0x48046000,
+		.pa_end		= 0x48046fff,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio5_dbclk" },
+/* l4_per -> dss_hdmi */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_hdmi_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_hdmi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod omap44xx_gpio5_hwmod = {
-	.name		= "gpio5",
-	.class		= &omap44xx_gpio_hwmod_class,
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap44xx_gpio5_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio5_irqs),
-	.main_clk	= "gpio5_ick",
+/* dss_hdmi slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
+	&omap44xx_l3_main_2__dss_hdmi,
+	&omap44xx_l4_per__dss_hdmi,
+};
+
+static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
+	.name		= "dss_hdmi",
+	.class		= &omap44xx_hdmi_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
+	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
+	.main_clk	= "dss_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
 		},
 	},
-	.opt_clks	= gpio5_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-	.slaves		= omap44xx_gpio5_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio5_slaves),
+	.slaves		= omap44xx_dss_hdmi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* gpio6 */
-static struct omap_hwmod omap44xx_gpio6_hwmod;
-static struct omap_hwmod_irq_info omap44xx_gpio6_irqs[] = {
-	{ .irq = 34 + OMAP44XX_IRQ_GIC_START },
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
-static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
+static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = {
+	.name	= "rfbi",
+	.sysc	= &omap44xx_rfbi_sysc,
+};
+
+/* dss_rfbi */
+static struct omap_hwmod omap44xx_dss_rfbi_hwmod;
+static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = {
+	{ .dma_req = 13 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
+	{
+		.pa_start	= 0x58002000,
+		.pa_end		= 0x580020ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_rfbi_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_rfbi_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48042000,
+		.pa_end		= 0x480420ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_rfbi_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
+	&omap44xx_l3_main_2__dss_rfbi,
+	&omap44xx_l4_per__dss_rfbi,
+};
+
+static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap44xx_rfbi_hwmod_class,
+	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap44xx_venc_hwmod_class = {
+	.name	= "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod omap44xx_dss_venc_hwmod;
+static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
+	{
+		.pa_start	= 0x58003000,
+		.pa_end		= 0x580030ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_venc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_venc_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_venc_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48043000,
+		.pa_end		= 0x480430ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_venc */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_venc_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
+	&omap44xx_l3_main_2__dss_venc,
+	&omap44xx_l4_per__dss_venc,
+};
+
+static struct omap_hwmod omap44xx_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap44xx_venc_hwmod_class,
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'gpio' class
+ * general purpose io module
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_gpio_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0114,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_gpio_hwmod_class = {
+	.name	= "gpio",
+	.sysc	= &omap44xx_gpio_sysc,
+	.rev	= 2,
+};
+
+/* gpio dev_attr */
+static struct omap_gpio_dev_attr gpio_dev_attr = {
+	.bank_width	= 32,
+	.dbck_flag	= true,
+};
+
+/* gpio1 */
+static struct omap_hwmod omap44xx_gpio1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio1_irqs[] = {
+	{ .irq = 29 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio1_addrs[] = {
+	{
+		.pa_start	= 0x4a310000,
+		.pa_end		= 0x4a3101ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> gpio1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__gpio1 = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_gpio1_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_gpio1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio1_slaves[] = {
+	&omap44xx_l4_wkup__gpio1,
+};
+
+static struct omap_hwmod_opt_clk gpio1_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio1_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio1_hwmod = {
+	.name		= "gpio1",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.mpu_irqs	= omap44xx_gpio1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio1_irqs),
+	.main_clk	= "gpio1_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio1_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* gpio2 */
+static struct omap_hwmod omap44xx_gpio2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio2_irqs[] = {
+	{ .irq = 30 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio2_addrs[] = {
+	{
+		.pa_start	= 0x48055000,
+		.pa_end		= 0x480551ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio2_slaves[] = {
+	&omap44xx_l4_per__gpio2,
+};
+
+static struct omap_hwmod_opt_clk gpio2_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio2_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio2_hwmod = {
+	.name		= "gpio2",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio2_irqs),
+	.main_clk	= "gpio2_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio2_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* gpio3 */
+static struct omap_hwmod omap44xx_gpio3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio3_irqs[] = {
+	{ .irq = 31 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio3_addrs[] = {
+	{
+		.pa_start	= 0x48057000,
+		.pa_end		= 0x480571ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio3_slaves[] = {
+	&omap44xx_l4_per__gpio3,
+};
+
+static struct omap_hwmod_opt_clk gpio3_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio3_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio3_hwmod = {
+	.name		= "gpio3",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio3_irqs),
+	.main_clk	= "gpio3_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio3_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* gpio4 */
+static struct omap_hwmod omap44xx_gpio4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio4_irqs[] = {
+	{ .irq = 32 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio4_addrs[] = {
+	{
+		.pa_start	= 0x48059000,
+		.pa_end		= 0x480591ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio4_slaves[] = {
+	&omap44xx_l4_per__gpio4,
+};
+
+static struct omap_hwmod_opt_clk gpio4_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio4_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio4_hwmod = {
+	.name		= "gpio4",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio4_irqs),
+	.main_clk	= "gpio4_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio4_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio4_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* gpio5 */
+static struct omap_hwmod omap44xx_gpio5_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio5_irqs[] = {
+	{ .irq = 33 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio5_addrs[] = {
+	{
+		.pa_start	= 0x4805b000,
+		.pa_end		= 0x4805b1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio5 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio5_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio5 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio5_slaves[] = {
+	&omap44xx_l4_per__gpio5,
+};
+
+static struct omap_hwmod_opt_clk gpio5_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio5_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio5_hwmod = {
+	.name		= "gpio5",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio5_irqs),
+	.main_clk	= "gpio5_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio5_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio5_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* gpio6 */
+static struct omap_hwmod omap44xx_gpio6_hwmod;
+static struct omap_hwmod_irq_info omap44xx_gpio6_irqs[] = {
+	{ .irq = 34 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_gpio6_addrs[] = {
+	{
+		.pa_start	= 0x4805d000,
+		.pa_end		= 0x4805d1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> gpio6 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_gpio6_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_gpio6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* gpio6 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_gpio6_slaves[] = {
+	&omap44xx_l4_per__gpio6,
+};
+
+static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
+	{ .role = "dbclk", .clk = "gpio6_dbclk" },
+};
+
+static struct omap_hwmod omap44xx_gpio6_hwmod = {
+	.name		= "gpio6",
+	.class		= &omap44xx_gpio_hwmod_class,
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap44xx_gpio6_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio6_irqs),
+	.main_clk	= "gpio6_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+		},
+	},
+	.opt_clks	= gpio6_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
+	.dev_attr	= &gpio_dev_attr,
+	.slaves		= omap44xx_gpio6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'hsi' class
+ * mipi high-speed synchronous serial interface (multichannel and full-duplex
+ * serial if)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_hsi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_hsi_hwmod_class = {
+	.name	= "hsi",
+	.sysc	= &omap44xx_hsi_sysc,
+};
+
+/* hsi */
+static struct omap_hwmod_irq_info omap44xx_hsi_irqs[] = {
+	{ .name = "mpu_p1", .irq = 67 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "mpu_p2", .irq = 68 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "mpu_dma", .irq = 71 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* hsi master ports */
+static struct omap_hwmod_ocp_if *omap44xx_hsi_masters[] = {
+	&omap44xx_hsi__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_hsi_addrs[] = {
+	{
+		.pa_start	= 0x4a058000,
+		.pa_end		= 0x4a05bfff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> hsi */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_hsi_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_hsi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_hsi_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* hsi slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_hsi_slaves[] = {
+	&omap44xx_l4_cfg__hsi,
+};
+
+static struct omap_hwmod omap44xx_hsi_hwmod = {
+	.name		= "hsi",
+	.class		= &omap44xx_hsi_hwmod_class,
+	.mpu_irqs	= omap44xx_hsi_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_hsi_irqs),
+	.main_clk	= "hsi_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_hsi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_hsi_slaves),
+	.masters	= omap44xx_hsi_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_hsi_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'i2c' class
+ * multimaster high-speed i2c controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0090,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
+	.name	= "i2c",
+	.sysc	= &omap44xx_i2c_sysc,
+};
+
+/* i2c1 */
+static struct omap_hwmod omap44xx_i2c1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c1_irqs[] = {
+	{ .irq = 56 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 26 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 27 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
+	{
+		.pa_start	= 0x48070000,
+		.pa_end		= 0x480700ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
+	&omap44xx_l4_per__i2c1,
+};
+
+static struct omap_hwmod omap44xx_i2c1_hwmod = {
+	.name		= "i2c1",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_irqs),
+	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_sdma_reqs),
+	.main_clk	= "i2c1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* i2c2 */
+static struct omap_hwmod omap44xx_i2c2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c2_irqs[] = {
+	{ .irq = 57 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 28 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 29 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
+	{
+		.pa_start	= 0x48072000,
+		.pa_end		= 0x480720ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
+	&omap44xx_l4_per__i2c2,
+};
+
+static struct omap_hwmod omap44xx_i2c2_hwmod = {
+	.name		= "i2c2",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_irqs),
+	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_sdma_reqs),
+	.main_clk	= "i2c2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* i2c3 */
+static struct omap_hwmod omap44xx_i2c3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c3_irqs[] = {
+	{ .irq = 61 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 24 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 25 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
+	{
+		.pa_start	= 0x48060000,
+		.pa_end		= 0x480600ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
+	&omap44xx_l4_per__i2c3,
+};
+
+static struct omap_hwmod omap44xx_i2c3_hwmod = {
+	.name		= "i2c3",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_irqs),
+	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_sdma_reqs),
+	.main_clk	= "i2c3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* i2c4 */
+static struct omap_hwmod omap44xx_i2c4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_i2c4_irqs[] = {
+	{ .irq = 62 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_i2c4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 123 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 124 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
+	{
+		.pa_start	= 0x48350000,
+		.pa_end		= 0x483500ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> i2c4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_i2c4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_i2c4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* i2c4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
+	&omap44xx_l4_per__i2c4,
+};
+
+static struct omap_hwmod omap44xx_i2c4_hwmod = {
+	.name		= "i2c4",
+	.class		= &omap44xx_i2c_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.mpu_irqs	= omap44xx_i2c4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_irqs),
+	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_sdma_reqs),
+	.main_clk	= "i2c4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_i2c4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'ipu' class
+ * imaging processor unit
+ */
+
+static struct omap_hwmod_class omap44xx_ipu_hwmod_class = {
+	.name	= "ipu",
+};
+
+/* ipu */
+static struct omap_hwmod_irq_info omap44xx_ipu_irqs[] = {
+	{ .irq = 100 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_rst_info omap44xx_ipu_c0_resets[] = {
+	{ .name = "cpu0", .rst_shift = 0 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_ipu_c1_resets[] = {
+	{ .name = "cpu1", .rst_shift = 1 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = {
+	{ .name = "mmu_cache", .rst_shift = 2 },
+};
+
+/* ipu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_ipu_masters[] = {
+	&omap44xx_ipu__l3_main_2,
+};
+
+/* l3_main_2 -> ipu */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_ipu_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ipu slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_ipu_slaves[] = {
+	&omap44xx_l3_main_2__ipu,
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
+	.name		= "ipu_c0",
+	.class		= &omap44xx_ipu_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_ipu_c0_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_c0_resets),
+	.prcm		= {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
+	.name		= "ipu_c1",
+	.class		= &omap44xx_ipu_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_ipu_c1_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_c1_resets),
+	.prcm		= {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct omap_hwmod omap44xx_ipu_hwmod = {
+	.name		= "ipu",
+	.class		= &omap44xx_ipu_hwmod_class,
+	.mpu_irqs	= omap44xx_ipu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_ipu_irqs),
+	.rst_lines	= omap44xx_ipu_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_resets),
+	.main_clk	= "ipu_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+		},
+	},
+	.slaves		= omap44xx_ipu_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_ipu_slaves),
+	.masters	= omap44xx_ipu_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_ipu_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'iss' class
+ * external images sensor pixel data processor
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_iss_hwmod_class = {
+	.name	= "iss",
+	.sysc	= &omap44xx_iss_sysc,
+};
+
+/* iss */
+static struct omap_hwmod_irq_info omap44xx_iss_irqs[] = {
+	{ .irq = 24 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
+	{ .name = "1", .dma_req = 8 + OMAP44XX_DMA_REQ_START },
+	{ .name = "2", .dma_req = 9 + OMAP44XX_DMA_REQ_START },
+	{ .name = "3", .dma_req = 11 + OMAP44XX_DMA_REQ_START },
+	{ .name = "4", .dma_req = 12 + OMAP44XX_DMA_REQ_START },
+};
+
+/* iss master ports */
+static struct omap_hwmod_ocp_if *omap44xx_iss_masters[] = {
+	&omap44xx_iss__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_iss_addrs[] = {
+	{
+		.pa_start	= 0x52000000,
+		.pa_end		= 0x520000ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> iss */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_iss_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_iss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_iss_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iss slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_iss_slaves[] = {
+	&omap44xx_l3_main_2__iss,
+};
+
+static struct omap_hwmod_opt_clk iss_opt_clks[] = {
+	{ .role = "ctrlclk", .clk = "iss_ctrlclk" },
+};
+
+static struct omap_hwmod omap44xx_iss_hwmod = {
+	.name		= "iss",
+	.class		= &omap44xx_iss_hwmod_class,
+	.mpu_irqs	= omap44xx_iss_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iss_irqs),
+	.sdma_reqs	= omap44xx_iss_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_iss_sdma_reqs),
+	.main_clk	= "iss_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
+		},
+	},
+	.opt_clks	= iss_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(iss_opt_clks),
+	.slaves		= omap44xx_iss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_iss_slaves),
+	.masters	= omap44xx_iss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_iss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'iva' class
+ * multi-standard video encoder/decoder hardware accelerator
+ */
+
+static struct omap_hwmod_class omap44xx_iva_hwmod_class = {
+	.name	= "iva",
+};
+
+/* iva */
+static struct omap_hwmod_irq_info omap44xx_iva_irqs[] = {
+	{ .name = "sync_1", .irq = 103 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "sync_0", .irq = 104 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "mailbox_0", .irq = 107 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
+	{ .name = "logic", .rst_shift = 2 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_iva_seq0_resets[] = {
+	{ .name = "seq0", .rst_shift = 0 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_iva_seq1_resets[] = {
+	{ .name = "seq1", .rst_shift = 1 },
+};
+
+/* iva master ports */
+static struct omap_hwmod_ocp_if *omap44xx_iva_masters[] = {
+	&omap44xx_iva__l3_main_2,
+	&omap44xx_iva__l3_instr,
+};
+
+static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
+	{
+		.pa_start	= 0x5a000000,
+		.pa_end		= 0x5a07ffff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> iva */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_iva_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_iva_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_iva_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* iva slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
+	&omap44xx_dsp__iva,
+	&omap44xx_l3_main_2__iva,
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
+	.name		= "iva_seq0",
+	.class		= &omap44xx_iva_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_iva_seq0_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq0_resets),
+	.prcm = {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
+	.name		= "iva_seq1",
+	.class		= &omap44xx_iva_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_iva_seq1_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq1_resets),
+	.prcm = {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct omap_hwmod omap44xx_iva_hwmod = {
+	.name		= "iva",
+	.class		= &omap44xx_iva_hwmod_class,
+	.mpu_irqs	= omap44xx_iva_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iva_irqs),
+	.rst_lines	= omap44xx_iva_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
+	.main_clk	= "iva_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
+			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+		},
+	},
+	.slaves		= omap44xx_iva_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_iva_slaves),
+	.masters	= omap44xx_iva_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_iva_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'kbd' class
+ * keyboard controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_kbd_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_kbd_hwmod_class = {
+	.name	= "kbd",
+	.sysc	= &omap44xx_kbd_sysc,
+};
+
+/* kbd */
+static struct omap_hwmod omap44xx_kbd_hwmod;
+static struct omap_hwmod_irq_info omap44xx_kbd_irqs[] = {
+	{ .irq = 120 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
+	{
+		.pa_start	= 0x4a31c000,
+		.pa_end		= 0x4a31c07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> kbd */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_kbd_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_kbd_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_kbd_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* kbd slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_kbd_slaves[] = {
+	&omap44xx_l4_wkup__kbd,
+};
+
+static struct omap_hwmod omap44xx_kbd_hwmod = {
+	.name		= "kbd",
+	.class		= &omap44xx_kbd_hwmod_class,
+	.mpu_irqs	= omap44xx_kbd_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_kbd_irqs),
+	.main_clk	= "kbd_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_kbd_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_kbd_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors using a
+ * queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mailbox_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = {
+	.name	= "mailbox",
+	.sysc	= &omap44xx_mailbox_sysc,
+};
+
+/* mailbox */
+static struct omap_hwmod omap44xx_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
+	{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x4a0f4000,
+		.pa_end		= 0x4a0f41ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> mailbox */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_mailbox_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mailbox_slaves[] = {
+	&omap44xx_l4_cfg__mailbox,
+};
+
+static struct omap_hwmod omap44xx_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap44xx_mailbox_hwmod_class,
+	.mpu_irqs	= omap44xx_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mailbox_irqs),
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcbsp_sysc = {
+	.sysc_offs	= 0x008c,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_mcbsp_hwmod_class = {
+	.name	= "mcbsp",
+	.sysc	= &omap44xx_mcbsp_sysc,
+	.rev	= MCBSP_CONFIG_TYPE4,
+};
+
+/* mcbsp1 */
+static struct omap_hwmod omap44xx_mcbsp1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp1_irqs[] = {
+	{ .irq = 17 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 32 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 33 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x40122000,
+		.pa_end		= 0x401220ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp1_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp1_dma_addrs[] = {
+	{
+		.name		= "dma",
+		.pa_start	= 0x49022000,
+		.pa_end		= 0x490220ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp1 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp1_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp1_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
+	&omap44xx_l4_abe__mcbsp1,
+	&omap44xx_l4_abe__mcbsp1_dma,
+};
+
+static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_irqs),
+	.sdma_reqs	= omap44xx_mcbsp1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_sdma_reqs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod omap44xx_mcbsp2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp2_irqs[] = {
+	{ .irq = 22 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 16 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 17 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x40124000,
+		.pa_end		= 0x401240ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp2_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp2_dma_addrs[] = {
+	{
+		.name		= "dma",
+		.pa_start	= 0x49024000,
+		.pa_end		= 0x490240ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp2 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp2_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp2_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
+	&omap44xx_l4_abe__mcbsp2,
+	&omap44xx_l4_abe__mcbsp2_dma,
+};
+
+static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_irqs),
+	.sdma_reqs	= omap44xx_mcbsp2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_sdma_reqs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcbsp3 */
+static struct omap_hwmod omap44xx_mcbsp3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp3_irqs[] = {
+	{ .irq = 23 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 18 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 19 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x40126000,
+		.pa_end		= 0x401260ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp3_dma_addrs[] = {
+	{
+		.name		= "dma",
+		.pa_start	= 0x49026000,
+		.pa_end		= 0x490260ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp3 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp3_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcbsp3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
+	&omap44xx_l4_abe__mcbsp3,
+	&omap44xx_l4_abe__mcbsp3_dma,
+};
+
+static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
+	.name		= "mcbsp3",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_irqs),
+	.sdma_reqs	= omap44xx_mcbsp3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_sdma_reqs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcbsp4 */
+static struct omap_hwmod omap44xx_mcbsp4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp4_irqs[] = {
+	{ .irq = 16 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 30 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 31 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
+	{
+		.pa_start	= 0x48096000,
+		.pa_end		= 0x480960ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcbsp4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcbsp4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
+	&omap44xx_l4_per__mcbsp4,
+};
+
+static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
+	.name		= "mcbsp4",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_irqs),
+	.sdma_reqs	= omap44xx_mcbsp4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_sdma_reqs),
+	.main_clk	= "mcbsp4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mcpdm' class
+ * multi channel pdm controller (proprietary interface with phoenix power
+ * ic)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcpdm_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mcpdm_hwmod_class = {
+	.name	= "mcpdm",
+	.sysc	= &omap44xx_mcpdm_sysc,
+};
+
+/* mcpdm */
+static struct omap_hwmod omap44xx_mcpdm_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcpdm_irqs[] = {
+	{ .irq = 112 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcpdm_sdma_reqs[] = {
+	{ .name = "up_link", .dma_req = 64 + OMAP44XX_DMA_REQ_START },
+	{ .name = "dn_link", .dma_req = 65 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
+	{
+		.pa_start	= 0x40132000,
+		.pa_end		= 0x4013207f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcpdm */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcpdm_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcpdm_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcpdm_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
+	{
+		.pa_start	= 0x49032000,
+		.pa_end		= 0x4903207f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcpdm (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcpdm_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcpdm_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcpdm_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcpdm slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcpdm_slaves[] = {
+	&omap44xx_l4_abe__mcpdm,
+	&omap44xx_l4_abe__mcpdm_dma,
+};
+
+static struct omap_hwmod omap44xx_mcpdm_hwmod = {
+	.name		= "mcpdm",
+	.class		= &omap44xx_mcpdm_hwmod_class,
+	.mpu_irqs	= omap44xx_mcpdm_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcpdm_irqs),
+	.sdma_reqs	= omap44xx_mcpdm_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcpdm_sdma_reqs),
+	.main_clk	= "mcpdm_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcpdm_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcpdm_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mcspi_hwmod_class = {
+	.name	= "mcspi",
+	.sysc	= &omap44xx_mcspi_sysc,
+	.rev	= OMAP4_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod omap44xx_mcspi1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi1_irqs[] = {
+	{ .irq = 65 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 34 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 35 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx1", .dma_req = 36 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx1", .dma_req = 37 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx2", .dma_req = 38 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx2", .dma_req = 39 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx3", .dma_req = 40 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx3", .dma_req = 41 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480981ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi1_slaves[] = {
+	&omap44xx_l4_per__mcspi1,
+};
+
+/* mcspi1 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi1_dev_attr = {
+	.num_chipselect	= 4,
+};
+
+static struct omap_hwmod omap44xx_mcspi1_hwmod = {
+	.name		= "mcspi1",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi1_irqs),
+	.sdma_reqs	= omap44xx_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi1_dev_attr,
+	.slaves		= omap44xx_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcspi2 */
+static struct omap_hwmod omap44xx_mcspi2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi2_irqs[] = {
+	{ .irq = 66 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 42 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 43 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx1", .dma_req = 44 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx1", .dma_req = 45 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi2_slaves[] = {
+	&omap44xx_l4_per__mcspi2,
+};
+
+/* mcspi2 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi2_dev_attr = {
+	.num_chipselect	= 2,
+};
+
+static struct omap_hwmod omap44xx_mcspi2_hwmod = {
+	.name		= "mcspi2",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi2_irqs),
+	.sdma_reqs	= omap44xx_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi2_dev_attr,
+	.slaves		= omap44xx_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcspi3 */
+static struct omap_hwmod omap44xx_mcspi3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi3_irqs[] = {
+	{ .irq = 91 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 14 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 15 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx1", .dma_req = 22 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx1", .dma_req = 23 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b81ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi3_slaves[] = {
+	&omap44xx_l4_per__mcspi3,
+};
+
+/* mcspi3 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi3_dev_attr = {
+	.num_chipselect	= 2,
+};
+
+static struct omap_hwmod omap44xx_mcspi3_hwmod = {
+	.name		= "mcspi3",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi3_irqs),
+	.sdma_reqs	= omap44xx_mcspi3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi3_sdma_reqs),
+	.main_clk	= "mcspi3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi3_dev_attr,
+	.slaves		= omap44xx_mcspi3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcspi4 */
+static struct omap_hwmod omap44xx_mcspi4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi4_irqs[] = {
+	{ .irq = 48 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi4_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 69 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 70 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
+	{
+		.pa_start	= 0x480ba000,
+		.pa_end		= 0x480ba1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi4_slaves[] = {
+	&omap44xx_l4_per__mcspi4,
+};
+
+/* mcspi4 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi4_dev_attr = {
+	.num_chipselect	= 1,
+};
+
+static struct omap_hwmod omap44xx_mcspi4_hwmod = {
+	.name		= "mcspi4",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi4_irqs),
+	.sdma_reqs	= omap44xx_mcspi4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi4_sdma_reqs),
+	.main_clk	= "mcspi4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi4_dev_attr,
+	.slaves		= omap44xx_mcspi4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mmc' class
+ * multimedia card high-speed/sd/sdio (mmc/sd/sdio) host controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mmc_hwmod_class = {
+	.name	= "mmc",
+	.sysc	= &omap44xx_mmc_sysc,
+};
+
+/* mmc1 */
+
+static struct omap_hwmod_irq_info omap44xx_mmc1_irqs[] = {
+	{ .irq = 83 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 60 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 61 + OMAP44XX_DMA_REQ_START },
+};
+
+/* mmc1 master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc1_masters[] = {
+	&omap44xx_mmc1__l3_main_1,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc1_addrs[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c3ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc1_slaves[] = {
+	&omap44xx_l4_per__mmc1,
+};
+
+/* mmc1 dev_attr */
+static struct omap_mmc_dev_attr mmc1_dev_attr = {
+	.flags	= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod omap44xx_mmc1_hwmod = {
+	.name		= "mmc1",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc1_irqs),
+	.sdma_reqs	= omap44xx_mmc1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc1_sdma_reqs),
+	.main_clk	= "mmc1_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mmc1_dev_attr,
+	.slaves		= omap44xx_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc1_slaves),
+	.masters	= omap44xx_mmc1_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc1_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc2 */
+static struct omap_hwmod_irq_info omap44xx_mmc2_irqs[] = {
+	{ .irq = 86 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 46 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 47 + OMAP44XX_DMA_REQ_START },
+};
+
+/* mmc2 master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc2_masters[] = {
+	&omap44xx_mmc2__l3_main_1,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc2_addrs[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b43ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc2_slaves[] = {
+	&omap44xx_l4_per__mmc2,
+};
+
+static struct omap_hwmod omap44xx_mmc2_hwmod = {
+	.name		= "mmc2",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc2_irqs),
+	.sdma_reqs	= omap44xx_mmc2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc2_sdma_reqs),
+	.main_clk	= "mmc2_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc2_slaves),
+	.masters	= omap44xx_mmc2_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc2_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc3 */
+static struct omap_hwmod omap44xx_mmc3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmc3_irqs[] = {
+	{ .irq = 94 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 76 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 77 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
+	{
+		.pa_start	= 0x480ad000,
+		.pa_end		= 0x480ad3ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc3_slaves[] = {
+	&omap44xx_l4_per__mmc3,
+};
+
+static struct omap_hwmod omap44xx_mmc3_hwmod = {
+	.name		= "mmc3",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc3_irqs),
+	.sdma_reqs	= omap44xx_mmc3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc3_sdma_reqs),
+	.main_clk	= "mmc3_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc4 */
+static struct omap_hwmod omap44xx_mmc4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmc4_irqs[] = {
+	{ .irq = 96 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 56 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 57 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
+	{
+		.pa_start	= 0x480d1000,
+		.pa_end		= 0x480d13ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc4_slaves[] = {
+	&omap44xx_l4_per__mmc4,
+};
+
+static struct omap_hwmod omap44xx_mmc4_hwmod = {
+	.name		= "mmc4",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc4_irqs),
+	.sdma_reqs	= omap44xx_mmc4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc4_sdma_reqs),
+	.main_clk	= "mmc4_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc5 */
+static struct omap_hwmod omap44xx_mmc5_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmc5_irqs[] = {
+	{ .irq = 59 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc5_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 58 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 59 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
+	{
+		.pa_start	= 0x480d5000,
+		.pa_end		= 0x480d53ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc5_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc5 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc5_slaves[] = {
+	&omap44xx_l4_per__mmc5,
+};
+
+static struct omap_hwmod omap44xx_mmc5_hwmod = {
+	.name		= "mmc5",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc5_irqs),
+	.sdma_reqs	= omap44xx_mmc5_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc5_sdma_reqs),
+	.main_clk	= "mmc5_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu' class
+ * mpu sub-system
+ */
+
+static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
+	.name	= "mpu",
+};
+
+/* mpu */
+static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
+	{ .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* mpu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
+	&omap44xx_mpu__l3_main_1,
+	&omap44xx_mpu__l4_abe,
+	&omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod omap44xx_mpu_hwmod = {
+	.name		= "mpu",
+	.class		= &omap44xx_mpu_hwmod_class,
+	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+	.mpu_irqs	= omap44xx_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mpu_irqs),
+	.main_clk	= "dpll_mpu_m2_ck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+		},
+	},
+	.masters	= omap44xx_mpu_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_mpu_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'smartreflex' class
+ * smartreflex module (monitor silicon performance and outputs a measure of
+ * performance error)
+ */
+
+/* The IP is not compliant to type1 / type2 scheme */
+static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_smartreflex = {
+	.sidle_shift	= 24,
+	.enwkup_shift	= 26,
+};
+
+static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = {
+	.sysc_offs	= 0x0038,
+	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type_smartreflex,
+};
+
+static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
+	.name	= "smartreflex",
+	.sysc	= &omap44xx_smartreflex_sysc,
+	.rev	= 2,
+};
+
+/* smartreflex_core */
+static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
+static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
+	{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
+	{
+		.pa_start	= 0x4a0dd000,
+		.pa_end		= 0x4a0dd03f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> smartreflex_core */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_smartreflex_core_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_smartreflex_core_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* smartreflex_core slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
+	&omap44xx_l4_cfg__smartreflex_core,
+};
+
+static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
+	.name		= "smartreflex_core",
+	.class		= &omap44xx_smartreflex_hwmod_class,
+	.mpu_irqs	= omap44xx_smartreflex_core_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_irqs),
+	.main_clk	= "smartreflex_core_fck",
+	.vdd_name	= "core",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_smartreflex_core_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* smartreflex_iva */
+static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
+static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
+	{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
+	{
+		.pa_start	= 0x4a0db000,
+		.pa_end		= 0x4a0db03f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> smartreflex_iva */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_smartreflex_iva_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_smartreflex_iva_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* smartreflex_iva slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
+	&omap44xx_l4_cfg__smartreflex_iva,
+};
+
+static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
+	.name		= "smartreflex_iva",
+	.class		= &omap44xx_smartreflex_hwmod_class,
+	.mpu_irqs	= omap44xx_smartreflex_iva_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_irqs),
+	.main_clk	= "smartreflex_iva_fck",
+	.vdd_name	= "iva",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_smartreflex_iva_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* smartreflex_mpu */
+static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
+static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
+	{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
+	{
+		.pa_start	= 0x4a0d9000,
+		.pa_end		= 0x4a0d903f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> smartreflex_mpu */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_smartreflex_mpu_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_smartreflex_mpu_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* smartreflex_mpu slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
+	&omap44xx_l4_cfg__smartreflex_mpu,
+};
+
+static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
+	.name		= "smartreflex_mpu",
+	.class		= &omap44xx_smartreflex_hwmod_class,
+	.mpu_irqs	= omap44xx_smartreflex_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs),
+	.main_clk	= "smartreflex_mpu_fck",
+	.vdd_name	= "mpu",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_smartreflex_mpu_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'spinlock' class
+ * spinlock provides hardware assistance for synchronizing the processes
+ * running on multiple processors
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_spinlock_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_spinlock_hwmod_class = {
+	.name	= "spinlock",
+	.sysc	= &omap44xx_spinlock_sysc,
+};
+
+/* spinlock */
+static struct omap_hwmod omap44xx_spinlock_hwmod;
+static struct omap_hwmod_addr_space omap44xx_spinlock_addrs[] = {
 	{
-		.pa_start	= 0x4805d000,
-		.pa_end		= 0x4805d1ff,
+		.pa_start	= 0x4a0f6000,
+		.pa_end		= 0x4a0f6fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> gpio6 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__gpio6 = {
-	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_gpio6_hwmod,
+/* l4_cfg -> spinlock */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__spinlock = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_spinlock_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_gpio6_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_gpio6_addrs),
+	.addr		= omap44xx_spinlock_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_spinlock_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* gpio6 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_gpio6_slaves[] = {
-	&omap44xx_l4_per__gpio6,
-};
-
-static struct omap_hwmod_opt_clk gpio6_opt_clks[] = {
-	{ .role = "dbclk", .clk = "gpio6_dbclk" },
+/* spinlock slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_spinlock_slaves[] = {
+	&omap44xx_l4_cfg__spinlock,
 };
 
-static struct omap_hwmod omap44xx_gpio6_hwmod = {
-	.name		= "gpio6",
-	.class		= &omap44xx_gpio_hwmod_class,
-	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
-	.mpu_irqs	= omap44xx_gpio6_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_gpio6_irqs),
-	.main_clk	= "gpio6_ick",
+static struct omap_hwmod omap44xx_spinlock_hwmod = {
+	.name		= "spinlock",
+	.class		= &omap44xx_spinlock_hwmod_class,
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL,
 		},
 	},
-	.opt_clks	= gpio6_opt_clks,
-	.opt_clks_cnt	= ARRAY_SIZE(gpio6_opt_clks),
-	.dev_attr	= &gpio_dev_attr,
-	.slaves		= omap44xx_gpio6_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_gpio6_slaves),
+	.slaves		= omap44xx_spinlock_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_spinlock_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
 /*
- * 'i2c' class
- * multimaster high-speed i2c controller
+ * 'timer' class
+ * general purpose timer module with accurate 1ms tick
+ * This class contains several variants: ['timer_1ms', 'timer']
  */
 
-static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
+static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
+	.rev_offs	= 0x0000,
 	.sysc_offs	= 0x0010,
-	.syss_offs	= 0x0090,
+	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+			   SYSC_HAS_EMUFREE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_timer_1ms_hwmod_class = {
+	.name	= "timer",
+	.sysc	= &omap44xx_timer_1ms_sysc,
+};
+
+static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
 			   SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type1,
+	.sysc_fields	= &omap_hwmod_sysc_type2,
 };
 
-static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
-	.name	= "i2c",
-	.sysc	= &omap44xx_i2c_sysc,
+static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
+	.name	= "timer",
+	.sysc	= &omap44xx_timer_sysc,
 };
 
-/* i2c1 */
-static struct omap_hwmod omap44xx_i2c1_hwmod;
-static struct omap_hwmod_irq_info omap44xx_i2c1_irqs[] = {
-	{ .irq = 56 + OMAP44XX_IRQ_GIC_START },
+/* timer1 */
+static struct omap_hwmod omap44xx_timer1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
+	{ .irq = 37 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_dma_info omap44xx_i2c1_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 26 + OMAP44XX_DMA_REQ_START },
-	{ .name = "rx", .dma_req = 27 + OMAP44XX_DMA_REQ_START },
+static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
+	{
+		.pa_start	= 0x4a318000,
+		.pa_end		= 0x4a31807f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_addr_space omap44xx_i2c1_addrs[] = {
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__timer1 = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_timer1_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer1_slaves[] = {
+	&omap44xx_l4_wkup__timer1,
+};
+
+static struct omap_hwmod omap44xx_timer1_hwmod = {
+	.name		= "timer1",
+	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.mpu_irqs	= omap44xx_timer1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer1_irqs),
+	.main_clk	= "timer1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer2 */
+static struct omap_hwmod omap44xx_timer2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer2_irqs[] = {
+	{ .irq = 38 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
 	{
-		.pa_start	= 0x48070000,
-		.pa_end		= 0x480700ff,
+		.pa_start	= 0x48032000,
+		.pa_end		= 0x4803207f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> i2c1 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c1 = {
+/* l4_per -> timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer2 = {
 	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_i2c1_hwmod,
+	.slave		= &omap44xx_timer2_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_i2c1_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c1_addrs),
+	.addr		= omap44xx_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* i2c1 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c1_slaves[] = {
-	&omap44xx_l4_per__i2c1,
+/* timer2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer2_slaves[] = {
+	&omap44xx_l4_per__timer2,
 };
 
-static struct omap_hwmod omap44xx_i2c1_hwmod = {
-	.name		= "i2c1",
-	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
-	.mpu_irqs	= omap44xx_i2c1_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_irqs),
-	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c1_sdma_reqs),
-	.main_clk	= "i2c1_fck",
+static struct omap_hwmod omap44xx_timer2_hwmod = {
+	.name		= "timer2",
+	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.mpu_irqs	= omap44xx_timer2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer2_irqs),
+	.main_clk	= "timer2_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_i2c1_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c1_slaves),
+	.slaves		= omap44xx_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* i2c2 */
-static struct omap_hwmod omap44xx_i2c2_hwmod;
-static struct omap_hwmod_irq_info omap44xx_i2c2_irqs[] = {
-	{ .irq = 57 + OMAP44XX_IRQ_GIC_START },
-};
-
-static struct omap_hwmod_dma_info omap44xx_i2c2_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 28 + OMAP44XX_DMA_REQ_START },
-	{ .name = "rx", .dma_req = 29 + OMAP44XX_DMA_REQ_START },
+/* timer3 */
+static struct omap_hwmod omap44xx_timer3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer3_irqs[] = {
+	{ .irq = 39 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_addr_space omap44xx_i2c2_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
 	{
-		.pa_start	= 0x48072000,
-		.pa_end		= 0x480720ff,
+		.pa_start	= 0x48034000,
+		.pa_end		= 0x4803407f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> i2c2 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c2 = {
+/* l4_per -> timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer3 = {
 	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_i2c2_hwmod,
+	.slave		= &omap44xx_timer3_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_i2c2_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c2_addrs),
+	.addr		= omap44xx_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* i2c2 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c2_slaves[] = {
-	&omap44xx_l4_per__i2c2,
+/* timer3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer3_slaves[] = {
+	&omap44xx_l4_per__timer3,
 };
 
-static struct omap_hwmod omap44xx_i2c2_hwmod = {
-	.name		= "i2c2",
-	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
-	.mpu_irqs	= omap44xx_i2c2_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_irqs),
-	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c2_sdma_reqs),
-	.main_clk	= "i2c2_fck",
+static struct omap_hwmod omap44xx_timer3_hwmod = {
+	.name		= "timer3",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer3_irqs),
+	.main_clk	= "timer3_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_i2c2_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c2_slaves),
+	.slaves		= omap44xx_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* i2c3 */
-static struct omap_hwmod omap44xx_i2c3_hwmod;
-static struct omap_hwmod_irq_info omap44xx_i2c3_irqs[] = {
-	{ .irq = 61 + OMAP44XX_IRQ_GIC_START },
-};
-
-static struct omap_hwmod_dma_info omap44xx_i2c3_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 24 + OMAP44XX_DMA_REQ_START },
-	{ .name = "rx", .dma_req = 25 + OMAP44XX_DMA_REQ_START },
+/* timer4 */
+static struct omap_hwmod omap44xx_timer4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer4_irqs[] = {
+	{ .irq = 40 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_addr_space omap44xx_i2c3_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
 	{
-		.pa_start	= 0x48060000,
-		.pa_end		= 0x480600ff,
+		.pa_start	= 0x48036000,
+		.pa_end		= 0x4803607f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> i2c3 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c3 = {
+/* l4_per -> timer4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer4 = {
 	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_i2c3_hwmod,
+	.slave		= &omap44xx_timer4_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_i2c3_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c3_addrs),
+	.addr		= omap44xx_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer4_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* i2c3 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c3_slaves[] = {
-	&omap44xx_l4_per__i2c3,
+/* timer4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer4_slaves[] = {
+	&omap44xx_l4_per__timer4,
 };
 
-static struct omap_hwmod omap44xx_i2c3_hwmod = {
-	.name		= "i2c3",
-	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
-	.mpu_irqs	= omap44xx_i2c3_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_irqs),
-	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c3_sdma_reqs),
-	.main_clk	= "i2c3_fck",
+static struct omap_hwmod omap44xx_timer4_hwmod = {
+	.name		= "timer4",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer4_irqs),
+	.main_clk	= "timer4_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_i2c3_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c3_slaves),
+	.slaves		= omap44xx_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* i2c4 */
-static struct omap_hwmod omap44xx_i2c4_hwmod;
-static struct omap_hwmod_irq_info omap44xx_i2c4_irqs[] = {
-	{ .irq = 62 + OMAP44XX_IRQ_GIC_START },
+/* timer5 */
+static struct omap_hwmod omap44xx_timer5_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer5_irqs[] = {
+	{ .irq = 41 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_dma_info omap44xx_i2c4_sdma_reqs[] = {
-	{ .name = "tx", .dma_req = 123 + OMAP44XX_DMA_REQ_START },
-	{ .name = "rx", .dma_req = 124 + OMAP44XX_DMA_REQ_START },
+static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
+	{
+		.pa_start	= 0x40138000,
+		.pa_end		= 0x4013807f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_addr_space omap44xx_i2c4_addrs[] = {
+/* l4_abe -> timer5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer5_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer5_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer5_dma_addrs[] = {
 	{
-		.pa_start	= 0x48350000,
-		.pa_end		= 0x483500ff,
+		.pa_start	= 0x49038000,
+		.pa_end		= 0x4903807f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_per -> i2c4 */
-static struct omap_hwmod_ocp_if omap44xx_l4_per__i2c4 = {
-	.master		= &omap44xx_l4_per_hwmod,
-	.slave		= &omap44xx_i2c4_hwmod,
-	.clk		= "l4_div_ck",
-	.addr		= omap44xx_i2c4_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_i2c4_addrs),
-	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+/* l4_abe -> timer5 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer5_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer5_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer5_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* i2c4 slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_i2c4_slaves[] = {
-	&omap44xx_l4_per__i2c4,
+/* timer5 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer5_slaves[] = {
+	&omap44xx_l4_abe__timer5,
+	&omap44xx_l4_abe__timer5_dma,
 };
 
-static struct omap_hwmod omap44xx_i2c4_hwmod = {
-	.name		= "i2c4",
-	.class		= &omap44xx_i2c_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
-	.mpu_irqs	= omap44xx_i2c4_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_irqs),
-	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
-	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_i2c4_sdma_reqs),
-	.main_clk	= "i2c4_fck",
+static struct omap_hwmod omap44xx_timer5_hwmod = {
+	.name		= "timer5",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer5_irqs),
+	.main_clk	= "timer5_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_i2c4_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_i2c4_slaves),
+	.slaves		= omap44xx_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/*
- * 'iva' class
- * multi-standard video encoder/decoder hardware accelerator
- */
+/* timer6 */
+static struct omap_hwmod omap44xx_timer6_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer6_irqs[] = {
+	{ .irq = 42 + OMAP44XX_IRQ_GIC_START },
+};
 
-static struct omap_hwmod_class omap44xx_iva_hwmod_class = {
-	.name	= "iva",
+static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4013a000,
+		.pa_end		= 0x4013a07f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-/* iva */
-static struct omap_hwmod_irq_info omap44xx_iva_irqs[] = {
-	{ .name = "sync_1", .irq = 103 + OMAP44XX_IRQ_GIC_START },
-	{ .name = "sync_0", .irq = 104 + OMAP44XX_IRQ_GIC_START },
-	{ .name = "mailbox_0", .irq = 107 + OMAP44XX_IRQ_GIC_START },
+/* l4_abe -> timer6 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer6_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer6_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_rst_info omap44xx_iva_resets[] = {
-	{ .name = "logic", .rst_shift = 2 },
+static struct omap_hwmod_addr_space omap44xx_timer6_dma_addrs[] = {
+	{
+		.pa_start	= 0x4903a000,
+		.pa_end		= 0x4903a07f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-static struct omap_hwmod_rst_info omap44xx_iva_seq0_resets[] = {
-	{ .name = "seq0", .rst_shift = 0 },
+/* l4_abe -> timer6 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer6_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer6_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer6_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-static struct omap_hwmod_rst_info omap44xx_iva_seq1_resets[] = {
-	{ .name = "seq1", .rst_shift = 1 },
+/* timer6 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer6_slaves[] = {
+	&omap44xx_l4_abe__timer6,
+	&omap44xx_l4_abe__timer6_dma,
 };
 
-/* iva master ports */
-static struct omap_hwmod_ocp_if *omap44xx_iva_masters[] = {
-	&omap44xx_iva__l3_main_2,
-	&omap44xx_iva__l3_instr,
+static struct omap_hwmod omap44xx_timer6_hwmod = {
+	.name		= "timer6",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer6_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer6_irqs),
+	.main_clk	= "timer6_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer7 */
+static struct omap_hwmod omap44xx_timer7_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer7_irqs[] = {
+	{ .irq = 43 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
+	{
+		.pa_start	= 0x4013c000,
+		.pa_end		= 0x4013c07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer7 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer7_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer7_addrs),
+	.user		= OCP_USER_MPU,
 };
 
-static struct omap_hwmod_addr_space omap44xx_iva_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_timer7_dma_addrs[] = {
 	{
-		.pa_start	= 0x5a000000,
-		.pa_end		= 0x5a07ffff,
+		.pa_start	= 0x4903c000,
+		.pa_end		= 0x4903c07f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l3_main_2 -> iva */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iva = {
-	.master		= &omap44xx_l3_main_2_hwmod,
-	.slave		= &omap44xx_iva_hwmod,
-	.clk		= "l3_div_ck",
-	.addr		= omap44xx_iva_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_iva_addrs),
-	.user		= OCP_USER_MPU,
+/* l4_abe -> timer7 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer7_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer7_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer7_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* iva slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_iva_slaves[] = {
-	&omap44xx_dsp__iva,
-	&omap44xx_l3_main_2__iva,
+/* timer7 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer7_slaves[] = {
+	&omap44xx_l4_abe__timer7,
+	&omap44xx_l4_abe__timer7_dma,
 };
 
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_iva_seq0_hwmod = {
-	.name		= "iva_seq0",
-	.class		= &omap44xx_iva_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
-	.rst_lines	= omap44xx_iva_seq0_resets,
-	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq0_resets),
+static struct omap_hwmod omap44xx_timer7_hwmod = {
+	.name		= "timer7",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer7_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer7_irqs),
+	.main_clk	= "timer7_fck",
 	.prcm = {
 		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
 		},
 	},
+	.slaves		= omap44xx_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* Pseudo hwmod for reset control purpose only */
-static struct omap_hwmod omap44xx_iva_seq1_hwmod = {
-	.name		= "iva_seq1",
-	.class		= &omap44xx_iva_hwmod_class,
-	.flags		= HWMOD_INIT_NO_RESET,
-	.rst_lines	= omap44xx_iva_seq1_resets,
-	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_seq1_resets),
-	.prcm = {
-		.omap4 = {
-			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
-		},
-	},
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+/* timer8 */
+static struct omap_hwmod omap44xx_timer8_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer8_irqs[] = {
+	{ .irq = 44 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod omap44xx_iva_hwmod = {
-	.name		= "iva",
-	.class		= &omap44xx_iva_hwmod_class,
-	.mpu_irqs	= omap44xx_iva_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iva_irqs),
-	.rst_lines	= omap44xx_iva_resets,
-	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
-	.main_clk	= "iva_fck",
-	.prcm = {
-		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
-			.rstctrl_reg = OMAP4430_RM_IVAHD_RSTCTRL,
-		},
+static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
+	{
+		.pa_start	= 0x4013e000,
+		.pa_end		= 0x4013e07f,
+		.flags		= ADDR_TYPE_RT
 	},
-	.slaves		= omap44xx_iva_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_iva_slaves),
-	.masters	= omap44xx_iva_masters,
-	.masters_cnt	= ARRAY_SIZE(omap44xx_iva_masters),
-	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/*
- * 'mpu' class
- * mpu sub-system
- */
+/* l4_abe -> timer8 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer8_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer8_addrs),
+	.user		= OCP_USER_MPU,
+};
 
-static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
-	.name	= "mpu",
+static struct omap_hwmod_addr_space omap44xx_timer8_dma_addrs[] = {
+	{
+		.pa_start	= 0x4903e000,
+		.pa_end		= 0x4903e07f,
+		.flags		= ADDR_TYPE_RT
+	},
 };
 
-/* mpu */
-static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
-	{ .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
-	{ .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
-	{ .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+/* l4_abe -> timer8 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer8_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer8_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer8_dma_addrs),
+	.user		= OCP_USER_SDMA,
 };
 
-/* mpu master ports */
-static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
-	&omap44xx_mpu__l3_main_1,
-	&omap44xx_mpu__l4_abe,
-	&omap44xx_mpu__dmm,
+/* timer8 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer8_slaves[] = {
+	&omap44xx_l4_abe__timer8,
+	&omap44xx_l4_abe__timer8_dma,
 };
 
-static struct omap_hwmod omap44xx_mpu_hwmod = {
-	.name		= "mpu",
-	.class		= &omap44xx_mpu_hwmod_class,
-	.flags		= (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
-	.mpu_irqs	= omap44xx_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mpu_irqs),
-	.main_clk	= "dpll_mpu_m2_ck",
+static struct omap_hwmod omap44xx_timer8_hwmod = {
+	.name		= "timer8",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer8_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer8_irqs),
+	.main_clk	= "timer8_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
 		},
 	},
-	.masters	= omap44xx_mpu_masters,
-	.masters_cnt	= ARRAY_SIZE(omap44xx_mpu_masters),
+	.slaves		= omap44xx_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/*
- * 'smartreflex' class
- * smartreflex module (monitor silicon performance and outputs a measure of
- * performance error)
- */
-
-/* The IP is not compliant to type1 / type2 scheme */
-static struct omap_hwmod_sysc_fields omap_hwmod_sysc_type_smartreflex = {
-	.sidle_shift	= 24,
-	.enwkup_shift	= 26,
-};
-
-static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = {
-	.sysc_offs	= 0x0038,
-	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
-	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
-			   SIDLE_SMART_WKUP),
-	.sysc_fields	= &omap_hwmod_sysc_type_smartreflex,
-};
-
-static struct omap_hwmod_class omap44xx_smartreflex_hwmod_class = {
-	.name	= "smartreflex",
-	.sysc	= &omap44xx_smartreflex_sysc,
-	.rev	= 2,
-};
-
-/* smartreflex_core */
-static struct omap_hwmod omap44xx_smartreflex_core_hwmod;
-static struct omap_hwmod_irq_info omap44xx_smartreflex_core_irqs[] = {
-	{ .irq = 19 + OMAP44XX_IRQ_GIC_START },
+/* timer9 */
+static struct omap_hwmod omap44xx_timer9_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer9_irqs[] = {
+	{ .irq = 45 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_addr_space omap44xx_smartreflex_core_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
 	{
-		.pa_start	= 0x4a0dd000,
-		.pa_end		= 0x4a0dd03f,
+		.pa_start	= 0x4803e000,
+		.pa_end		= 0x4803e07f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_cfg -> smartreflex_core */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_core = {
-	.master		= &omap44xx_l4_cfg_hwmod,
-	.slave		= &omap44xx_smartreflex_core_hwmod,
+/* l4_per -> timer9 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer9 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer9_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_smartreflex_core_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_addrs),
+	.addr		= omap44xx_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer9_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* smartreflex_core slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_smartreflex_core_slaves[] = {
-	&omap44xx_l4_cfg__smartreflex_core,
+/* timer9 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer9_slaves[] = {
+	&omap44xx_l4_per__timer9,
 };
 
-static struct omap_hwmod omap44xx_smartreflex_core_hwmod = {
-	.name		= "smartreflex_core",
-	.class		= &omap44xx_smartreflex_hwmod_class,
-	.mpu_irqs	= omap44xx_smartreflex_core_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_irqs),
-	.main_clk	= "smartreflex_core_fck",
-	.vdd_name	= "core",
+static struct omap_hwmod omap44xx_timer9_hwmod = {
+	.name		= "timer9",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer9_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer9_irqs),
+	.main_clk	= "timer9_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_smartreflex_core_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_core_slaves),
+	.slaves		= omap44xx_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* smartreflex_iva */
-static struct omap_hwmod omap44xx_smartreflex_iva_hwmod;
-static struct omap_hwmod_irq_info omap44xx_smartreflex_iva_irqs[] = {
-	{ .irq = 102 + OMAP44XX_IRQ_GIC_START },
+/* timer10 */
+static struct omap_hwmod omap44xx_timer10_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer10_irqs[] = {
+	{ .irq = 46 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_addr_space omap44xx_smartreflex_iva_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
 	{
-		.pa_start	= 0x4a0db000,
-		.pa_end		= 0x4a0db03f,
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x4808607f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_cfg -> smartreflex_iva */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_iva = {
-	.master		= &omap44xx_l4_cfg_hwmod,
-	.slave		= &omap44xx_smartreflex_iva_hwmod,
+/* l4_per -> timer10 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer10 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer10_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_smartreflex_iva_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_addrs),
+	.addr		= omap44xx_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer10_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* smartreflex_iva slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_smartreflex_iva_slaves[] = {
-	&omap44xx_l4_cfg__smartreflex_iva,
+/* timer10 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer10_slaves[] = {
+	&omap44xx_l4_per__timer10,
 };
 
-static struct omap_hwmod omap44xx_smartreflex_iva_hwmod = {
-	.name		= "smartreflex_iva",
-	.class		= &omap44xx_smartreflex_hwmod_class,
-	.mpu_irqs	= omap44xx_smartreflex_iva_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_irqs),
-	.main_clk	= "smartreflex_iva_fck",
-	.vdd_name	= "iva",
+static struct omap_hwmod omap44xx_timer10_hwmod = {
+	.name		= "timer10",
+	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.mpu_irqs	= omap44xx_timer10_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer10_irqs),
+	.main_clk	= "timer10_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_smartreflex_iva_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_iva_slaves),
+	.slaves		= omap44xx_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
-/* smartreflex_mpu */
-static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod;
-static struct omap_hwmod_irq_info omap44xx_smartreflex_mpu_irqs[] = {
-	{ .irq = 18 + OMAP44XX_IRQ_GIC_START },
+/* timer11 */
+static struct omap_hwmod omap44xx_timer11_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer11_irqs[] = {
+	{ .irq = 47 + OMAP44XX_IRQ_GIC_START },
 };
 
-static struct omap_hwmod_addr_space omap44xx_smartreflex_mpu_addrs[] = {
+static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
 	{
-		.pa_start	= 0x4a0d9000,
-		.pa_end		= 0x4a0d903f,
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x4808807f,
 		.flags		= ADDR_TYPE_RT
 	},
 };
 
-/* l4_cfg -> smartreflex_mpu */
-static struct omap_hwmod_ocp_if omap44xx_l4_cfg__smartreflex_mpu = {
-	.master		= &omap44xx_l4_cfg_hwmod,
-	.slave		= &omap44xx_smartreflex_mpu_hwmod,
+/* l4_per -> timer11 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer11_hwmod,
 	.clk		= "l4_div_ck",
-	.addr		= omap44xx_smartreflex_mpu_addrs,
-	.addr_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_addrs),
+	.addr		= omap44xx_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer11_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
-/* smartreflex_mpu slave ports */
-static struct omap_hwmod_ocp_if *omap44xx_smartreflex_mpu_slaves[] = {
-	&omap44xx_l4_cfg__smartreflex_mpu,
+/* timer11 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer11_slaves[] = {
+	&omap44xx_l4_per__timer11,
 };
 
-static struct omap_hwmod omap44xx_smartreflex_mpu_hwmod = {
-	.name		= "smartreflex_mpu",
-	.class		= &omap44xx_smartreflex_hwmod_class,
-	.mpu_irqs	= omap44xx_smartreflex_mpu_irqs,
-	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_irqs),
-	.main_clk	= "smartreflex_mpu_fck",
-	.vdd_name	= "mpu",
+static struct omap_hwmod omap44xx_timer11_hwmod = {
+	.name		= "timer11",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer11_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer11_irqs),
+	.main_clk	= "timer11_fck",
 	.prcm = {
 		.omap4 = {
-			.clkctrl_reg = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
 		},
 	},
-	.slaves		= omap44xx_smartreflex_mpu_slaves,
-	.slaves_cnt	= ARRAY_SIZE(omap44xx_smartreflex_mpu_slaves),
+	.slaves		= omap44xx_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer11_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
 
@@ -1870,6 +4814,88 @@ static struct omap_hwmod omap44xx_uart4_hwmod = {
 };
 
 /*
+ * 'usb_otg_hs' class
+ * high-speed on-the-go universal serial bus (usb_otg_hs) controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_usb_otg_hs_sysc = {
+	.rev_offs	= 0x0400,
+	.sysc_offs	= 0x0404,
+	.syss_offs	= 0x0408,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_usb_otg_hs_hwmod_class = {
+	.name = "usb_otg_hs",
+	.sysc = &omap44xx_usb_otg_hs_sysc,
+};
+
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info omap44xx_usb_otg_hs_irqs[] = {
+	{ .name = "mc", .irq = 92 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "dma", .irq = 93 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* usb_otg_hs master ports */
+static struct omap_hwmod_ocp_if *omap44xx_usb_otg_hs_masters[] = {
+	&omap44xx_usb_otg_hs__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
+	{
+		.pa_start	= 0x4a0ab000,
+		.pa_end		= 0x4a0ab003,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> usb_otg_hs */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_otg_hs = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_usb_otg_hs_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_usb_otg_hs_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* usb_otg_hs slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_usb_otg_hs_slaves[] = {
+	&omap44xx_l4_cfg__usb_otg_hs,
+};
+
+static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = {
+	{ .role = "xclk", .clk = "usb_otg_hs_xclk" },
+};
+
+static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
+	.name		= "usb_otg_hs",
+	.class		= &omap44xx_usb_otg_hs_hwmod_class,
+	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.mpu_irqs	= omap44xx_usb_otg_hs_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_irqs),
+	.main_clk	= "usb_otg_hs_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+		},
+	},
+	.opt_clks	= usb_otg_hs_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks),
+	.slaves		= omap44xx_usb_otg_hs_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
+	.masters	= omap44xx_usb_otg_hs_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'wd_timer' class
  * 32-bit watchdog upward counter that generates a pulse on the reset pin on
  * overflow condition
@@ -2024,13 +5050,34 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	/* mpu_bus class */
 	&omap44xx_mpu_private_hwmod,
 
+	/* aess class */
+/*	&omap44xx_aess_hwmod, */
+
+	/* bandgap class */
+	&omap44xx_bandgap_hwmod,
+
+	/* counter class */
+/*	&omap44xx_counter_32k_hwmod, */
+
 	/* dma class */
 	&omap44xx_dma_system_hwmod,
 
+	/* dmic class */
+	&omap44xx_dmic_hwmod,
+
 	/* dsp class */
 	&omap44xx_dsp_hwmod,
 	&omap44xx_dsp_c0_hwmod,
 
+	/* dss class */
+	&omap44xx_dss_hwmod,
+	&omap44xx_dss_dispc_hwmod,
+	&omap44xx_dss_dsi1_hwmod,
+	&omap44xx_dss_dsi2_hwmod,
+	&omap44xx_dss_hdmi_hwmod,
+	&omap44xx_dss_rfbi_hwmod,
+	&omap44xx_dss_venc_hwmod,
+
 	/* gpio class */
 	&omap44xx_gpio1_hwmod,
 	&omap44xx_gpio2_hwmod,
@@ -2039,17 +5086,56 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	&omap44xx_gpio5_hwmod,
 	&omap44xx_gpio6_hwmod,
 
+	/* hsi class */
+/*	&omap44xx_hsi_hwmod, */
+
 	/* i2c class */
 	&omap44xx_i2c1_hwmod,
 	&omap44xx_i2c2_hwmod,
 	&omap44xx_i2c3_hwmod,
 	&omap44xx_i2c4_hwmod,
 
+	/* ipu class */
+	&omap44xx_ipu_hwmod,
+	&omap44xx_ipu_c0_hwmod,
+	&omap44xx_ipu_c1_hwmod,
+
+	/* iss class */
+/*	&omap44xx_iss_hwmod, */
+
 	/* iva class */
 	&omap44xx_iva_hwmod,
 	&omap44xx_iva_seq0_hwmod,
 	&omap44xx_iva_seq1_hwmod,
 
+	/* kbd class */
+/*	&omap44xx_kbd_hwmod, */
+
+	/* mailbox class */
+	&omap44xx_mailbox_hwmod,
+
+	/* mcbsp class */
+	&omap44xx_mcbsp1_hwmod,
+	&omap44xx_mcbsp2_hwmod,
+	&omap44xx_mcbsp3_hwmod,
+	&omap44xx_mcbsp4_hwmod,
+
+	/* mcpdm class */
+/*	&omap44xx_mcpdm_hwmod, */
+
+	/* mcspi class */
+	&omap44xx_mcspi1_hwmod,
+	&omap44xx_mcspi2_hwmod,
+	&omap44xx_mcspi3_hwmod,
+	&omap44xx_mcspi4_hwmod,
+
+	/* mmc class */
+	&omap44xx_mmc1_hwmod,
+	&omap44xx_mmc2_hwmod,
+	&omap44xx_mmc3_hwmod,
+	&omap44xx_mmc4_hwmod,
+	&omap44xx_mmc5_hwmod,
+
 	/* mpu class */
 	&omap44xx_mpu_hwmod,
 
@@ -2058,12 +5144,31 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 	&omap44xx_smartreflex_iva_hwmod,
 	&omap44xx_smartreflex_mpu_hwmod,
 
+	/* spinlock class */
+	&omap44xx_spinlock_hwmod,
+
+	/* timer class */
+	&omap44xx_timer1_hwmod,
+	&omap44xx_timer2_hwmod,
+	&omap44xx_timer3_hwmod,
+	&omap44xx_timer4_hwmod,
+	&omap44xx_timer5_hwmod,
+	&omap44xx_timer6_hwmod,
+	&omap44xx_timer7_hwmod,
+	&omap44xx_timer8_hwmod,
+	&omap44xx_timer9_hwmod,
+	&omap44xx_timer10_hwmod,
+	&omap44xx_timer11_hwmod,
+
 	/* uart class */
 	&omap44xx_uart1_hwmod,
 	&omap44xx_uart2_hwmod,
 	&omap44xx_uart3_hwmod,
 	&omap44xx_uart4_hwmod,
 
+	/* usb_otg_hs class */
+	&omap44xx_usb_otg_hs_hwmod,
+
 	/* wd_timer class */
 	&omap44xx_wd_timer2_hwmod,
 	&omap44xx_wd_timer3_hwmod,
@@ -2073,6 +5178,6 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
 
 int __init omap44xx_hwmod_init(void)
 {
-	return omap_hwmod_init(omap44xx_hwmods);
+	return omap_hwmod_register(omap44xx_hwmods);
 }
 
diff --git a/arch/arm/mach-omap2/omap_l3_noc.c b/arch/arm/mach-omap2/omap_l3_noc.c
new file mode 100644
index 0000000..82632c2
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_noc.c
@@ -0,0 +1,253 @@
+/*
+  * OMAP4XXX L3 Interconnect error handling driver
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	Sricharan <r.sricharan@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  * USA
+  */
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "omap_l3_noc.h"
+
+/*
+ * Interrupt Handler for L3 error detection.
+ *	1) Identify the L3 clockdomain partition to which the error belongs to.
+ *	2) Identify the slave where the error information is logged
+ *	3) Print the logged information.
+ *	4) Add dump stack to provide kernel trace.
+ *
+ * Two Types of errors :
+ *	1) Custom errors in L3 :
+ *		Target like DMM/FW/EMIF generates SRESP=ERR error
+ *	2) Standard L3 error:
+ *		- Unsupported CMD.
+ *			L3 tries to access target while it is idle
+ *		- OCP disconnect.
+ *		- Address hole error:
+ *			If DSS/ISS/FDIF/USBHOSTFS access a target where they
+ *			do not have connectivity, the error is logged in
+ *			their default target which is DMM2.
+ *
+ *	On High Secure devices, firewall errors are possible and those
+ *	can be trapped as well. But the trapping is implemented as part
+ *	secure software and hence need not be implemented here.
+ */
+static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+{
+
+	struct omap4_l3		*l3 = _l3;
+	int inttype, i, j;
+	int err_src = 0;
+	u32 std_err_main_addr, std_err_main, err_reg;
+	u32 base, slave_addr, clear;
+	char *source_name;
+
+	/* Get the Type of interrupt */
+	if (irq == l3->app_irq)
+		inttype = L3_APPLICATION_ERROR;
+	else
+		inttype = L3_DEBUG_ERROR;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		/*
+		 * Read the regerr register of the clock domain
+		 * to determine the source
+		 */
+		base = (u32)l3->l3_base[i];
+		err_reg =  readl(base + l3_flagmux[i] + (inttype << 3));
+
+		/* Get the corresponding error and analyse */
+		if (err_reg) {
+			/* Identify the source from control status register */
+			for (j = 0; !(err_reg & (1 << j)); j++)
+									;
+
+			err_src = j;
+			/* Read the stderrlog_main_source from clk domain */
+			std_err_main_addr = base + (*(l3_targ[i] + err_src));
+			std_err_main =  readl(std_err_main_addr);
+
+			switch ((std_err_main & CUSTOM_ERROR)) {
+			case STANDARD_ERROR:
+				source_name =
+				l3_targ_stderrlog_main_name[i][err_src];
+
+				slave_addr = std_err_main_addr +
+						L3_SLAVE_ADDRESS_OFFSET;
+				WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
+					source_name, readl(slave_addr));
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, std_err_main_addr);
+				break;
+
+			case CUSTOM_ERROR:
+				source_name =
+				l3_targ_stderrlog_main_name[i][err_src];
+
+				WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
+							source_name);
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, std_err_main_addr);
+				break;
+
+			default:
+				/* Nothing to be handled here as of now */
+				break;
+			}
+		/* Error found so break the for loop */
+		break;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init omap4_l3_probe(struct platform_device *pdev)
+{
+	static struct omap4_l3		*l3;
+	struct resource		*res;
+	int			ret;
+	int			irq;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3)
+		ret = -ENOMEM;
+
+	platform_set_drvdata(pdev, l3);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 0\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	l3->l3_base[0] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[0])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 1\n");
+		ret = -ENODEV;
+		goto err3;
+	}
+
+	l3->l3_base[1] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[1])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err4;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 2\n");
+		ret = -ENODEV;
+		goto err5;
+	}
+
+	l3->l3_base[2] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[2])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err6;
+	}
+
+	/*
+	 * Setup interrupt Handlers
+	 */
+	irq = platform_get_irq(pdev, 0);
+	ret = request_irq(irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-dbg-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+					 OMAP44XX_IRQ_L3_DBG);
+		goto err7;
+	}
+	l3->debug_irq = irq;
+
+	irq = platform_get_irq(pdev, 1);
+	ret = request_irq(irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-app-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+					 OMAP44XX_IRQ_L3_APP);
+		goto err8;
+	}
+	l3->app_irq = irq;
+
+	goto err0;
+err8:
+err7:
+	iounmap(l3->l3_base[2]);
+err6:
+err5:
+	iounmap(l3->l3_base[1]);
+err4:
+err3:
+	iounmap(l3->l3_base[0]);
+err2:
+err1:
+	kfree(l3);
+err0:
+	return ret;
+}
+
+static int __exit omap4_l3_remove(struct platform_device *pdev)
+{
+	struct omap4_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->l3_base[0]);
+	iounmap(l3->l3_base[1]);
+	iounmap(l3->l3_base[2]);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap4_l3_driver = {
+	.remove		= __exit_p(omap4_l3_remove),
+	.driver		= {
+	.name		= "omap_l3_noc",
+	},
+};
+
+static int __init omap4_l3_init(void)
+{
+	return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+}
+postcore_initcall_sync(omap4_l3_init);
+
+static void __exit omap4_l3_exit(void)
+{
+	platform_driver_unregister(&omap4_l3_driver);
+}
+module_exit(omap4_l3_exit);
diff --git a/arch/arm/mach-omap2/omap_l3_noc.h b/arch/arm/mach-omap2/omap_l3_noc.h
new file mode 100644
index 0000000..359b833
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_noc.h
@@ -0,0 +1,132 @@
+ /*
+  * OMAP4XXX L3 Interconnect  error handling driver header
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	sricharan <r.sricharan@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  * USA
+  */
+#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/*
+ * L3 register offsets
+ */
+#define L3_MODULES			3
+#define CLEAR_STDERR_LOG		(1 << 31)
+#define CUSTOM_ERROR			0x2
+#define STANDARD_ERROR			0x0
+#define INBAND_ERROR			0x0
+#define EMIF_KERRLOG_OFFSET		0x10
+#define L3_SLAVE_ADDRESS_OFFSET		0x14
+#define LOGICAL_ADDR_ERRORLOG		0x4
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+u32 l3_flagmux[L3_MODULES] = {
+	0x50C,
+	0x100C,
+	0X020C
+};
+
+/*
+ * L3 Target standard Error register offsets
+ */
+u32 l3_targ_stderrlog_main_clk1[] = {
+	0x148, /* DMM1 */
+	0x248, /* DMM2 */
+	0x348, /* ABE */
+	0x448, /* L4CFG */
+	0x648  /* CLK2 PWR DISC */
+};
+
+u32 l3_targ_stderrlog_main_clk2[] = {
+	0x548,		/* CORTEX M3 */
+	0x348,		/* DSS */
+	0x148,		/* GPMC */
+	0x448,		/* ISS */
+	0x748,		/* IVAHD */
+	0xD48,		/* missing in TRM  corresponds to AES1*/
+	0x948,		/* L4 PER0*/
+	0x248,		/* OCMRAM */
+	0x148,		/* missing in TRM corresponds to GPMC sERROR*/
+	0x648,		/* SGX */
+	0x848,		/* SL2 */
+	0x1648,		/* C2C */
+	0x1148,		/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF48,		/* missing in TRM corrsponds to SHA1*/
+	0xE48,		/* missing in TRM corresponds to AES2*/
+	0xC48,		/* L4 PER3 */
+	0xA48,		/* L4 PER1*/
+	0xB48		/* L4 PER2*/
+};
+
+u32 l3_targ_stderrlog_main_clk3[] = {
+	0x0148	/* EMUSS */
+};
+
+char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+	{
+	"DMM1",
+	"DMM2",
+	"ABE",
+	"L4CFG",
+	"CLK2 PWR DISC",
+	},
+	{
+	"CORTEX M3" ,
+	"DSS ",
+	"GPMC ",
+	"ISS ",
+	"IVAHD ",
+	"AES1",
+	"L4 PER0",
+	"OCMRAM ",
+	"GPMC sERROR",
+	"SGX ",
+	"SL2 ",
+	"C2C ",
+	"PWR DISC CLK1",
+	"SHA1",
+	"AES2",
+	"L4 PER3",
+	"L4 PER1",
+	"L4 PER2",
+	},
+	{
+	"EMUSS",
+	},
+};
+
+u32 *l3_targ[L3_MODULES] = {
+	l3_targ_stderrlog_main_clk1,
+	l3_targ_stderrlog_main_clk2,
+	l3_targ_stderrlog_main_clk3,
+};
+
+struct omap4_l3 {
+	struct device	*dev;
+	struct clk	*ick;
+
+	/* memory base */
+	void __iomem *l3_base[4];
+
+	int		debug_irq;
+	int		app_irq;
+};
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_l3_smx.c b/arch/arm/mach-omap2/omap_l3_smx.c
new file mode 100644
index 0000000..265bff3
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_smx.c
@@ -0,0 +1,314 @@
+ /*
+  * OMAP3XXX L3 Interconnect Driver
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Felipe Balbi <balbi@ti.com>
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	Sricharan <r.sricharan@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  * USA
+  */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include "omap_l3_smx.h"
+
+static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
+{
+	return __raw_readll(base + reg);
+}
+
+static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
+{
+	__raw_writell(value, base + reg);
+}
+
+static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
+{
+	return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
+}
+
+static inline u32 omap3_l3_decode_addr(u64 error_addr)
+{
+	return error_addr & 0xffffffff;
+}
+
+static inline unsigned omap3_l3_decode_cmd(u64 error)
+{
+	return (error & 0x07) >> L3_ERROR_LOG_CMD;
+}
+
+static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
+{
+	return (error & 0xff00) >> L3_ERROR_LOG_INITID;
+}
+
+static inline unsigned omap3_l3_decode_req_info(u64 error)
+{
+	return (error >> 32) & 0xffff;
+}
+
+static char *omap3_l3_code_string(u8 code)
+{
+	switch (code) {
+	case OMAP_L3_CODE_NOERROR:
+		return "No Error";
+	case OMAP_L3_CODE_UNSUP_CMD:
+		return "Unsupported Command";
+	case OMAP_L3_CODE_ADDR_HOLE:
+		return "Address Hole";
+	case OMAP_L3_CODE_PROTECT_VIOLATION:
+		return "Protection Violation";
+	case OMAP_L3_CODE_IN_BAND_ERR:
+		return "In-band Error";
+	case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
+		return "Request Timeout Not Accepted";
+	case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
+		return "Request Timeout, no response";
+	default:
+		return "UNKNOWN error";
+	}
+}
+
+static char *omap3_l3_initiator_string(u8 initid)
+{
+	switch (initid) {
+	case OMAP_L3_LCD:
+		return "LCD";
+	case OMAP_L3_SAD2D:
+		return "SAD2D";
+	case OMAP_L3_IA_MPU_SS_1:
+	case OMAP_L3_IA_MPU_SS_2:
+	case OMAP_L3_IA_MPU_SS_3:
+	case OMAP_L3_IA_MPU_SS_4:
+	case OMAP_L3_IA_MPU_SS_5:
+		return "MPU";
+	case OMAP_L3_IA_IVA_SS_1:
+	case OMAP_L3_IA_IVA_SS_2:
+	case OMAP_L3_IA_IVA_SS_3:
+		return "IVA_SS";
+	case OMAP_L3_IA_IVA_SS_DMA_1:
+	case OMAP_L3_IA_IVA_SS_DMA_2:
+	case OMAP_L3_IA_IVA_SS_DMA_3:
+	case OMAP_L3_IA_IVA_SS_DMA_4:
+	case OMAP_L3_IA_IVA_SS_DMA_5:
+	case OMAP_L3_IA_IVA_SS_DMA_6:
+		return "IVA_SS_DMA";
+	case OMAP_L3_IA_SGX:
+		return "SGX";
+	case OMAP_L3_IA_CAM_1:
+	case OMAP_L3_IA_CAM_2:
+	case OMAP_L3_IA_CAM_3:
+		return "CAM";
+	case OMAP_L3_IA_DAP:
+		return "DAP";
+	case OMAP_L3_SDMA_WR_1:
+	case OMAP_L3_SDMA_WR_2:
+		return "SDMA_WR";
+	case OMAP_L3_SDMA_RD_1:
+	case OMAP_L3_SDMA_RD_2:
+	case OMAP_L3_SDMA_RD_3:
+	case OMAP_L3_SDMA_RD_4:
+		return "SDMA_RD";
+	case OMAP_L3_USBOTG:
+		return "USB_OTG";
+	case OMAP_L3_USBHOST:
+		return "USB_HOST";
+	default:
+		return "UNKNOWN Initiator";
+	}
+}
+
+/**
+ * omap3_l3_block_irq - handles a register block's irq
+ * @l3: struct omap3_l3 *
+ * @base: register block base address
+ * @error: L3_ERROR_LOG register of our block
+ *
+ * Called in hard-irq context. Caller should take care of locking
+ *
+ * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
+ * Analysis Sequence, we are following that sequence here, please
+ * refer to that Figure for more information on the subject.
+ */
+static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
+					u64 error, int error_addr)
+{
+	u8                      code = omap3_l3_decode_error_code(error);
+	u8                      initid = omap3_l3_decode_initid(error);
+	u8                      multi = error & L3_ERROR_LOG_MULTI;
+	u32			address = omap3_l3_decode_addr(error_addr);
+
+	WARN(true, "%s Error seen by %s %s at address %x\n",
+				 omap3_l3_code_string(code),
+			  omap3_l3_initiator_string(initid),
+			     multi ? "Multiple Errors" : "",
+						   address);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
+{
+	struct omap3_l3         *l3 = _l3;
+
+	u64                     status, clear;
+	u64                     error;
+	u64			error_addr;
+	u64			err_source = 0;
+	void			__iomem *base;
+	int			int_type;
+
+	irqreturn_t             ret = IRQ_NONE;
+
+	if (irq == l3->app_irq)
+		int_type = L3_APPLICATION_ERROR;
+	else
+		int_type = L3_DEBUG_ERROR;
+
+	if (!int_type) {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
+		/*
+		 * if we have a timeout error, there's nothing we can
+		 * do besides rebooting the board. So let's BUG on any
+		 * of such errors and handle the others. timeout error
+		 * is severe and not expected to occur.
+		 */
+		BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
+	} else {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
+		/* No timeout error for debug sources */
+	}
+
+	base = ((l3->rt) + (*(omap3_l3_bases[int_type] + err_source)));
+
+	/* identify the error source */
+	for (err_source = 0; !(status & (1 << err_source)); err_source++)
+									;
+	error = omap3_l3_readll(base, L3_ERROR_LOG);
+
+	if (error) {
+		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
+
+		ret |= omap3_l3_block_irq(l3, error, error_addr);
+	}
+
+	/* Clear the status register */
+	clear = ((L3_AGENT_STATUS_CLEAR_IA << int_type) |
+		 (L3_AGENT_STATUS_CLEAR_TA));
+
+	omap3_l3_writell(base, L3_AGENT_STATUS, clear);
+
+	/* clear the error log register */
+	omap3_l3_writell(base, L3_ERROR_LOG, error);
+
+	return ret;
+}
+
+static int __init omap3_l3_probe(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3;
+	struct resource         *res;
+	int                     ret;
+	int                     irq;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3) {
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, l3);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+	l3->rt = ioremap(res->start, resource_size(res));
+	if (!(l3->rt)) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	ret = request_irq(irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-debug-irq", l3);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request debug irq\n");
+		goto err3;
+	}
+	l3->debug_irq = irq;
+
+	irq = platform_get_irq(pdev, 1);
+	ret = request_irq(irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-app-irq", l3);
+
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request app irq\n");
+		goto err4;
+	}
+
+	l3->app_irq = irq;
+	goto err0;
+
+err4:
+err3:
+	iounmap(l3->rt);
+err2:
+err1:
+	kfree(l3);
+err0:
+	return ret;
+}
+
+static int __exit omap3_l3_remove(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->rt);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap3_l3_driver = {
+	.remove         = __exit_p(omap3_l3_remove),
+	.driver         = {
+	.name   = "omap_l3_smx",
+	},
+};
+
+static int __init omap3_l3_init(void)
+{
+	return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
+}
+postcore_initcall_sync(omap3_l3_init);
+
+static void __exit omap3_l3_exit(void)
+{
+	platform_driver_unregister(&omap3_l3_driver);
+}
+module_exit(omap3_l3_exit);
diff --git a/arch/arm/mach-omap2/omap_l3_smx.h b/arch/arm/mach-omap2/omap_l3_smx.h
new file mode 100644
index 0000000..ba2ed9a
--- /dev/null
+++ b/arch/arm/mach-omap2/omap_l3_smx.h
@@ -0,0 +1,338 @@
+ /*
+  * OMAP3XXX L3 Interconnect Driver header
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Felipe Balbi <balbi@ti.com>
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	sricharan <r.sricharan@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  * USA
+  */
+#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/* Register definitions. All 64-bit wide */
+#define L3_COMPONENT			0x000
+#define L3_CORE				0x018
+#define L3_AGENT_CONTROL		0x020
+#define L3_AGENT_STATUS			0x028
+#define L3_ERROR_LOG			0x058
+
+#define L3_ERROR_LOG_MULTI		(1 << 31)
+#define L3_ERROR_LOG_SECONDARY		(1 << 30)
+
+#define L3_ERROR_LOG_ADDR		0x060
+
+/* Register definitions for Sideband Interconnect */
+#define L3_SI_CONTROL			0x020
+#define L3_SI_FLAG_STATUS_0		0x510
+
+const u64 shift = 1;
+
+#define L3_STATUS_0_MPUIA_BRST		(shift << 0)
+#define L3_STATUS_0_MPUIA_RSP		(shift << 1)
+#define L3_STATUS_0_MPUIA_INBAND	(shift << 2)
+#define L3_STATUS_0_IVAIA_BRST		(shift << 6)
+#define L3_STATUS_0_IVAIA_RSP		(shift << 7)
+#define L3_STATUS_0_IVAIA_INBAND	(shift << 8)
+#define L3_STATUS_0_SGXIA_BRST		(shift << 9)
+#define L3_STATUS_0_SGXIA_RSP		(shift << 10)
+#define L3_STATUS_0_SGXIA_MERROR	(shift << 11)
+#define L3_STATUS_0_CAMIA_BRST		(shift << 12)
+#define L3_STATUS_0_CAMIA_RSP		(shift << 13)
+#define L3_STATUS_0_CAMIA_INBAND	(shift << 14)
+#define L3_STATUS_0_DISPIA_BRST		(shift << 15)
+#define L3_STATUS_0_DISPIA_RSP		(shift << 16)
+#define L3_STATUS_0_DMARDIA_BRST	(shift << 18)
+#define L3_STATUS_0_DMARDIA_RSP		(shift << 19)
+#define L3_STATUS_0_DMAWRIA_BRST	(shift << 21)
+#define L3_STATUS_0_DMAWRIA_RSP		(shift << 22)
+#define L3_STATUS_0_USBOTGIA_BRST	(shift << 24)
+#define L3_STATUS_0_USBOTGIA_RSP	(shift << 25)
+#define L3_STATUS_0_USBOTGIA_INBAND	(shift << 26)
+#define L3_STATUS_0_USBHOSTIA_BRST	(shift << 27)
+#define L3_STATUS_0_USBHOSTIA_INBAND	(shift << 28)
+#define L3_STATUS_0_SMSTA_REQ		(shift << 48)
+#define L3_STATUS_0_GPMCTA_REQ		(shift << 49)
+#define L3_STATUS_0_OCMRAMTA_REQ	(shift << 50)
+#define L3_STATUS_0_OCMROMTA_REQ	(shift << 51)
+#define L3_STATUS_0_IVATA_REQ		(shift << 54)
+#define L3_STATUS_0_SGXTA_REQ		(shift << 55)
+#define L3_STATUS_0_SGXTA_SERROR	(shift << 56)
+#define L3_STATUS_0_GPMCTA_SERROR	(shift << 57)
+#define L3_STATUS_0_L4CORETA_REQ	(shift << 58)
+#define L3_STATUS_0_L4PERTA_REQ		(shift << 59)
+#define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
+#define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
+
+#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST         \
+					| L3_STATUS_0_MPUIA_RSP         \
+					| L3_STATUS_0_IVAIA_BRST        \
+					| L3_STATUS_0_IVAIA_RSP         \
+					| L3_STATUS_0_SGXIA_BRST        \
+					| L3_STATUS_0_SGXIA_RSP         \
+					| L3_STATUS_0_CAMIA_BRST        \
+					| L3_STATUS_0_CAMIA_RSP         \
+					| L3_STATUS_0_DISPIA_BRST       \
+					| L3_STATUS_0_DISPIA_RSP        \
+					| L3_STATUS_0_DMARDIA_BRST      \
+					| L3_STATUS_0_DMARDIA_RSP       \
+					| L3_STATUS_0_DMAWRIA_BRST      \
+					| L3_STATUS_0_DMAWRIA_RSP       \
+					| L3_STATUS_0_USBOTGIA_BRST     \
+					| L3_STATUS_0_USBOTGIA_RSP      \
+					| L3_STATUS_0_USBHOSTIA_BRST    \
+					| L3_STATUS_0_SMSTA_REQ         \
+					| L3_STATUS_0_GPMCTA_REQ        \
+					| L3_STATUS_0_OCMRAMTA_REQ      \
+					| L3_STATUS_0_OCMROMTA_REQ      \
+					| L3_STATUS_0_IVATA_REQ         \
+					| L3_STATUS_0_SGXTA_REQ         \
+					| L3_STATUS_0_L4CORETA_REQ      \
+					| L3_STATUS_0_L4PERTA_REQ       \
+					| L3_STATUS_0_L4EMUTA_REQ       \
+					| L3_STATUS_0_MAD2DTA_REQ)
+
+#define L3_SI_FLAG_STATUS_1		0x530
+
+#define L3_STATUS_1_MPU_DATAIA		(1 << 0)
+#define L3_STATUS_1_DAPIA0		(1 << 3)
+#define L3_STATUS_1_DAPIA1		(1 << 4)
+#define L3_STATUS_1_IVAIA		(1 << 6)
+
+#define L3_PM_ERROR_LOG			0x020
+#define L3_PM_CONTROL			0x028
+#define L3_PM_ERROR_CLEAR_SINGLE	0x030
+#define L3_PM_ERROR_CLEAR_MULTI		0x038
+#define L3_PM_REQ_INFO_PERMISSION(n)	(0x048 + (0x020 * n))
+#define L3_PM_READ_PERMISSION(n)	(0x050 + (0x020 * n))
+#define L3_PM_WRITE_PERMISSION(n)	(0x058 + (0x020 * n))
+#define L3_PM_ADDR_MATCH(n)		(0x060 + (0x020 * n))
+
+/* L3 error log bit fields. Common for IA and TA */
+#define L3_ERROR_LOG_CODE		24
+#define L3_ERROR_LOG_INITID		8
+#define L3_ERROR_LOG_CMD		0
+
+/* L3 agent status bit fields. */
+#define L3_AGENT_STATUS_CLEAR_IA	0x10000000
+#define L3_AGENT_STATUS_CLEAR_TA	0x01000000
+
+#define OMAP34xx_IRQ_L3_APP		10
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+enum omap3_l3_initiator_id {
+	/* LCD has 1 ID */
+	OMAP_L3_LCD	        = 29,
+	/* SAD2D has 1 ID */
+	OMAP_L3_SAD2D		= 28,
+	/* MPU has 5 IDs */
+	OMAP_L3_IA_MPU_SS_1     = 27,
+	OMAP_L3_IA_MPU_SS_2     = 26,
+	OMAP_L3_IA_MPU_SS_3     = 25,
+	OMAP_L3_IA_MPU_SS_4     = 24,
+	OMAP_L3_IA_MPU_SS_5     = 23,
+	/* IVA2.2 SS has 3 IDs*/
+	OMAP_L3_IA_IVA_SS_1     = 22,
+	OMAP_L3_IA_IVA_SS_2     = 21,
+	OMAP_L3_IA_IVA_SS_3     = 20,
+	/* IVA 2.2 SS DMA has 6 IDS */
+	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
+	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
+	OMAP_L3_IA_IVA_SS_DMA_3 = 17,
+	OMAP_L3_IA_IVA_SS_DMA_4 = 16,
+	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
+	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
+	/* SGX has 1 ID */
+	OMAP_L3_IA_SGX		= 13,
+	/* CAM has 3 ID */
+	OMAP_L3_IA_CAM_1	= 12,
+	OMAP_L3_IA_CAM_2	= 11,
+	OMAP_L3_IA_CAM_3	= 10,
+	/* DAP has 1 ID */
+	OMAP_L3_IA_DAP		= 9,
+	/* SDMA WR has 2 IDs */
+	OMAP_L3_SDMA_WR_1	= 8,
+	OMAP_L3_SDMA_WR_2	= 7,
+	/* SDMA RD has 4 IDs */
+	OMAP_L3_SDMA_RD_1	= 6,
+	OMAP_L3_SDMA_RD_2	= 5,
+	OMAP_L3_SDMA_RD_3	= 4,
+	OMAP_L3_SDMA_RD_4	= 3,
+	/* HSUSB OTG has 1 ID */
+	OMAP_L3_USBOTG		= 2,
+	/* HSUSB HOST has 1 ID */
+	OMAP_L3_USBHOST		= 1,
+};
+
+enum omap3_l3_code {
+	OMAP_L3_CODE_NOERROR = 0,
+	OMAP_L3_CODE_UNSUP_CMD = 1,
+	OMAP_L3_CODE_ADDR_HOLE = 2,
+	OMAP_L3_CODE_PROTECT_VIOLATION = 3,
+	OMAP_L3_CODE_IN_BAND_ERR = 4,
+	/* codes 5 and 6 are reserved */
+	OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT = 7,
+	OMAP_L3_CODE_REQ_TOUT_NO_RESP = 8,
+	/* codes 9 - 15 are also reserved */
+};
+
+struct omap3_l3 {
+	struct device   *dev;
+	struct clk      *ick;
+
+	/* memory base*/
+	void __iomem    *rt;
+
+	int             debug_irq;
+	int             app_irq;
+
+	/* true when and inband functional error occurs */
+	unsigned        inband:1;
+};
+
+/* offsets for l3 agents in order with the Flag status register */
+unsigned int __iomem omap3_l3_app_bases[] = {
+	/* MPU IA */
+	0x1400,
+	0x1400,
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	0x1800,
+	0x1800,
+	/* SGX IA */
+	0x1c00,
+	0x1c00,
+	/* RESERVED */
+	0,
+	/* CAMERA IA */
+	0x5800,
+	0x5800,
+	0x5800,
+	/* DISPLAY IA */
+	0x5400,
+	0x5400,
+	/* RESERVED */
+	0,
+	/*SDMA RD IA */
+	0x4c00,
+	0x4c00,
+	/* RESERVED */
+	0,
+	/* SDMA WR IA */
+	0x5000,
+	0x5000,
+	/* RESERVED */
+	0,
+	/* USB OTG IA */
+	0x4400,
+	0x4400,
+	0x4400,
+	/* USB HOST IA */
+	0x4000,
+	0x4000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	/* SAD2D IA */
+	0x3000,
+	0x3000,
+	0x3000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	/* SMA TA */
+	0x2000,
+	/* GPMC TA */
+	0x2400,
+	/* OCM RAM TA */
+	0x2800,
+	/* OCM ROM TA */
+	0x2C00,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* IVA 2.2 TA */
+	0x6000,
+	/* SGX TA */
+	0x6400,
+	/* L4 EMU TA */
+	0x7000,
+	/* GPMC TA */
+	0x2400,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* L4 EMU TA */
+	0x7000,
+	/* MAD2D TA */
+	0x3400,
+	/* RESERVED */
+	0,
+	0,
+};
+
+unsigned int __iomem omap3_l3_debug_bases[] = {
+	/* MPU DATA IA */
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	/* DAP IA */
+	0x5c00,
+	0x5c00,
+	/* RESERVED */
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	/* REST RESERVED */
+};
+
+u32 *omap3_l3_bases[] = {
+	omap3_l3_app_bases,
+	omap3_l3_debug_bases,
+};
+
+/*
+ * REVISIT define __raw_readll/__raw_writell here, but move them to
+ * <asm/io.h> at some point
+ */
+#define __raw_writell(v, a)	(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a) = (v))
+#define __raw_readll(a)		(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a))
+
+#endif
diff --git a/arch/arm/mach-omap2/omap_opp_data.h b/arch/arm/mach-omap2/omap_opp_data.h
index 46ac27d..c784c12 100644
--- a/arch/arm/mach-omap2/omap_opp_data.h
+++ b/arch/arm/mach-omap2/omap_opp_data.h
@@ -21,6 +21,8 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "voltage.h"
+
 /*
  * *BIG FAT WARNING*:
  * USE the following ONLY in opp data initialization common to an SoC.
@@ -65,8 +67,30 @@ struct omap_opp_def {
 	.u_volt		= _uv,					\
 }
 
+/*
+ * Initialization wrapper used to define SmartReflex process data
+ * XXX Is this needed?  Just use C99 initializers in data files?
+ */
+#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)  \
+{								       \
+	.volt_nominal	= _v_nom,				       \
+	.sr_efuse_offs	= _efuse_offs,				       \
+	.sr_errminlimit = _errminlimit,				       \
+	.vp_errgain	= _errgain				       \
+}
+
 /* Use this to initialize the default table */
 extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
 		u32 opp_def_size);
 
+
+extern struct omap_volt_data omap34xx_vddmpu_volt_data[];
+extern struct omap_volt_data omap34xx_vddcore_volt_data[];
+extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
+extern struct omap_volt_data omap36xx_vddcore_volt_data[];
+
+extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
+extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+
 #endif		/* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c
index 745252c..e2e605f 100644
--- a/arch/arm/mach-omap2/omap_phy_internal.c
+++ b/arch/arm/mach-omap2/omap_phy_internal.c
@@ -29,6 +29,7 @@
 #include <linux/usb.h>
 
 #include <plat/usb.h>
+#include "control.h"
 
 /* OMAP control module register for UTMI PHY */
 #define CONTROL_DEV_CONF		0x300
@@ -43,6 +44,7 @@
 
 static struct clk *phyclk, *clk48m, *clk32k;
 static void __iomem *ctrl_base;
+static int usbotghs_control;
 
 int omap4430_phy_init(struct device *dev)
 {
@@ -103,13 +105,6 @@ int omap4430_phy_set_clk(struct device *dev, int on)
 int omap4430_phy_power(struct device *dev, int ID, int on)
 {
 	if (on) {
-		/* enabled the clocks */
-		omap4430_phy_set_clk(dev, 1);
-		/* power on the phy */
-		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
-			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-			mdelay(200);
-		}
 		if (ID)
 			/* enable VBUS valid, IDDIG groung */
 			__raw_writel(AVALID | VBUSVALID, ctrl_base +
@@ -125,10 +120,31 @@ int omap4430_phy_power(struct device *dev, int ID, int on)
 		/* Enable session END and IDIG to high impedence. */
 		__raw_writel(SESSEND | IDDIG, ctrl_base +
 					USBOTGHS_CONTROL);
+	}
+	return 0;
+}
+
+int omap4430_phy_suspend(struct device *dev, int suspend)
+{
+	if (suspend) {
 		/* Disable the clocks */
 		omap4430_phy_set_clk(dev, 0);
 		/* Power down the phy */
 		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+
+		/* save the context */
+		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
+	} else {
+		/* Enable the internel phy clcoks */
+		omap4430_phy_set_clk(dev, 1);
+		/* power on the phy */
+		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
+			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+			mdelay(200);
+		}
+
+		/* restore the context */
+		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
 	}
 
 	return 0;
@@ -147,3 +163,95 @@ int omap4430_phy_exit(struct device *dev)
 
 	return 0;
 }
+
+void am35x_musb_reset(void)
+{
+	u32	regval;
+
+	/* Reset the musb interface */
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+	regval |= AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval &= ~AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+}
+
+void am35x_musb_phy_power(u8 on)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+	u32 devconf2;
+
+	if (on) {
+		/*
+		 * Start the on-chip PHY and its PLL.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
+		devconf2 |= CONF2_PHY_PLLON;
+
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
+		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+				& CONF2_PHYCLKGD)) {
+			cpu_relax();
+
+			if (time_after(jiffies, timeout)) {
+				pr_err(KERN_ERR "musb PHY clock good timed out\n");
+				break;
+			}
+		}
+	} else {
+		/*
+		 * Power down the on-chip PHY.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~CONF2_PHY_PLLON;
+		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+	}
+}
+
+void am35x_musb_clear_irq(void)
+{
+	u32 regval;
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval |= AM35XX_USBOTGSS_INT_CLR;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+}
+
+void am35x_musb_set_mode(u8 musb_mode)
+{
+	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~CONF2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		devconf2 |= CONF2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		devconf2 |= CONF2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		devconf2 |= CONF2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
+	}
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+}
diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 00e1d2b..0a8e74e 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/i2c/twl.h>
 
-#include <plat/voltage.h>
+#include "voltage.h"
 
 #include "pm.h"
 
@@ -59,8 +59,15 @@
 
 static bool is_offset_valid;
 static u8 smps_offset;
+/*
+ * Flag to ensure Smartreflex bit in TWL
+ * being cleared in board file is not overwritten.
+ */
+static bool __initdata twl_sr_enable_autoinit;
 
+#define TWL4030_DCDC_GLOBAL_CFG        0x06
 #define REG_SMPS_OFFSET         0xE0
+#define SMARTREFLEX_ENABLE     BIT(3)
 
 static unsigned long twl4030_vsel_to_uv(const u8 vsel)
 {
@@ -269,6 +276,18 @@ int __init omap3_twl_init(void)
 		omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
 	}
 
+	/*
+	 * The smartreflex bit on twl4030 specifies if the setting of voltage
+	 * is done over the I2C_SR path. Since this setting is independent of
+	 * the actual usage of smartreflex AVS module, we enable TWL SR bit
+	 * by default irrespective of whether smartreflex AVS module is enabled
+	 * on the OMAP side or not. This is because without this bit enabled,
+	 * the voltage scaling through vp forceupdate/bypass mechanism of
+	 * voltage scaling will not function on TWL over I2C_SR.
+	 */
+	if (!twl_sr_enable_autoinit)
+		omap3_twl_set_sr_bit(true);
+
 	voltdm = omap_voltage_domain_lookup("mpu");
 	omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
 
@@ -277,3 +296,44 @@ int __init omap3_twl_init(void)
 
 	return 0;
 }
+
+/**
+ * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL
+ * @enable: enable SR mode in twl or not
+ *
+ * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure
+ * voltage scaling through OMAP SR works. Else, the smartreflex bit
+ * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but
+ * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct
+ * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages,
+ * in those scenarios this bit is to be cleared (enable = false).
+ *
+ * Returns 0 on sucess, error is returned if I2C read/write fails.
+ */
+int __init omap3_twl_set_sr_bit(bool enable)
+{
+	u8 temp;
+	int ret;
+	if (twl_sr_enable_autoinit)
+		pr_warning("%s: unexpected multiple calls\n", __func__);
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
+					TWL4030_DCDC_GLOBAL_CFG);
+	if (ret)
+		goto err;
+
+	if (enable)
+		temp |= SMARTREFLEX_ENABLE;
+	else
+		temp &= ~SMARTREFLEX_ENABLE;
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
+				TWL4030_DCDC_GLOBAL_CFG);
+	if (!ret) {
+		twl_sr_enable_autoinit = true;
+		return 0;
+	}
+err:
+	pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/opp2xxx.h b/arch/arm/mach-omap2/opp2xxx.h
index 38b7305..8affc66 100644
--- a/arch/arm/mach-omap2/opp2xxx.h
+++ b/arch/arm/mach-omap2/opp2xxx.h
@@ -418,7 +418,7 @@ struct prcm_config {
 
 extern const struct prcm_config omap2420_rate_table[];
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 extern const struct prcm_config omap2430_rate_table[];
 #else
 #define omap2430_rate_table	NULL
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index 0486fce..d95f3f9 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -4,8 +4,9 @@
  * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
  *	Nishanth Menon
  *	Kevin Hilman
- * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2010-2011 Nokia Corporation.
  *      Eduardo Valentin
+ *      Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -20,19 +21,83 @@
 
 #include <plat/cpu.h>
 
+#include "control.h"
 #include "omap_opp_data.h"
+#include "pm.h"
+
+/* 34xx */
+
+/* VDD1 */
+
+#define OMAP3430_VDD_MPU_OPP1_UV		975000
+#define OMAP3430_VDD_MPU_OPP2_UV		1075000
+#define OMAP3430_VDD_MPU_OPP3_UV		1200000
+#define OMAP3430_VDD_MPU_OPP4_UV		1270000
+#define OMAP3430_VDD_MPU_OPP5_UV		1350000
+
+struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+
+#define OMAP3430_VDD_CORE_OPP1_UV		975000
+#define OMAP3430_VDD_CORE_OPP2_UV		1050000
+#define OMAP3430_VDD_CORE_OPP3_UV		1150000
+
+struct omap_volt_data omap34xx_vddcore_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* 36xx */
+
+/* VDD1 */
+
+#define OMAP3630_VDD_MPU_OPP50_UV		1012500
+#define OMAP3630_VDD_MPU_OPP100_UV		1200000
+#define OMAP3630_VDD_MPU_OPP120_UV		1325000
+#define OMAP3630_VDD_MPU_OPP1G_UV		1375000
+
+struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+
+#define OMAP3630_VDD_CORE_OPP50_UV		1000000
+#define OMAP3630_VDD_CORE_OPP100_UV		1200000
+
+struct omap_volt_data omap36xx_vddcore_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* OPP data */
 
 static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
 	/* MPU OPP1 */
-	OPP_INITIALIZER("mpu", true, 125000000, 975000),
+	OPP_INITIALIZER("mpu", true, 125000000, OMAP3430_VDD_MPU_OPP1_UV),
 	/* MPU OPP2 */
-	OPP_INITIALIZER("mpu", true, 250000000, 1075000),
+	OPP_INITIALIZER("mpu", true, 250000000, OMAP3430_VDD_MPU_OPP2_UV),
 	/* MPU OPP3 */
-	OPP_INITIALIZER("mpu", true, 500000000, 1200000),
+	OPP_INITIALIZER("mpu", true, 500000000, OMAP3430_VDD_MPU_OPP3_UV),
 	/* MPU OPP4 */
-	OPP_INITIALIZER("mpu", true, 550000000, 1270000),
+	OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV),
 	/* MPU OPP5 */
-	OPP_INITIALIZER("mpu", true, 600000000, 1350000),
+	OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV),
 
 	/*
 	 * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
@@ -42,53 +107,53 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
 	 * impact that frequency will do to the MPU and the whole system in
 	 * general.
 	 */
-	OPP_INITIALIZER("l3_main", false, 41500000, 975000),
+	OPP_INITIALIZER("l3_main", false, 41500000, OMAP3430_VDD_CORE_OPP1_UV),
 	/* L3 OPP2 */
-	OPP_INITIALIZER("l3_main", true, 83000000, 1050000),
+	OPP_INITIALIZER("l3_main", true, 83000000, OMAP3430_VDD_CORE_OPP2_UV),
 	/* L3 OPP3 */
-	OPP_INITIALIZER("l3_main", true, 166000000, 1150000),
+	OPP_INITIALIZER("l3_main", true, 166000000, OMAP3430_VDD_CORE_OPP3_UV),
 
 	/* DSP OPP1 */
-	OPP_INITIALIZER("iva", true, 90000000, 975000),
+	OPP_INITIALIZER("iva", true, 90000000, OMAP3430_VDD_MPU_OPP1_UV),
 	/* DSP OPP2 */
-	OPP_INITIALIZER("iva", true, 180000000, 1075000),
+	OPP_INITIALIZER("iva", true, 180000000, OMAP3430_VDD_MPU_OPP2_UV),
 	/* DSP OPP3 */
-	OPP_INITIALIZER("iva", true, 360000000, 1200000),
+	OPP_INITIALIZER("iva", true, 360000000, OMAP3430_VDD_MPU_OPP3_UV),
 	/* DSP OPP4 */
-	OPP_INITIALIZER("iva", true, 400000000, 1270000),
+	OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV),
 	/* DSP OPP5 */
-	OPP_INITIALIZER("iva", true, 430000000, 1350000),
+	OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV),
 };
 
 static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
 	/* MPU OPP1 - OPP50 */
-	OPP_INITIALIZER("mpu", true,  300000000, 1012500),
+	OPP_INITIALIZER("mpu", true,  300000000, OMAP3630_VDD_MPU_OPP50_UV),
 	/* MPU OPP2 - OPP100 */
-	OPP_INITIALIZER("mpu", true,  600000000, 1200000),
+	OPP_INITIALIZER("mpu", true,  600000000, OMAP3630_VDD_MPU_OPP100_UV),
 	/* MPU OPP3 - OPP-Turbo */
-	OPP_INITIALIZER("mpu", false, 800000000, 1325000),
+	OPP_INITIALIZER("mpu", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV),
 	/* MPU OPP4 - OPP-SB */
-	OPP_INITIALIZER("mpu", false, 1000000000, 1375000),
+	OPP_INITIALIZER("mpu", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV),
 
 	/* L3 OPP1 - OPP50 */
-	OPP_INITIALIZER("l3_main", true, 100000000, 1000000),
+	OPP_INITIALIZER("l3_main", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV),
 	/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
-	OPP_INITIALIZER("l3_main", true, 200000000, 1200000),
+	OPP_INITIALIZER("l3_main", true, 200000000, OMAP3630_VDD_CORE_OPP100_UV),
 
 	/* DSP OPP1 - OPP50 */
-	OPP_INITIALIZER("iva", true,  260000000, 1012500),
+	OPP_INITIALIZER("iva", true,  260000000, OMAP3630_VDD_MPU_OPP50_UV),
 	/* DSP OPP2 - OPP100 */
-	OPP_INITIALIZER("iva", true,  520000000, 1200000),
+	OPP_INITIALIZER("iva", true,  520000000, OMAP3630_VDD_MPU_OPP100_UV),
 	/* DSP OPP3 - OPP-Turbo */
-	OPP_INITIALIZER("iva", false, 660000000, 1325000),
+	OPP_INITIALIZER("iva", false, 660000000, OMAP3630_VDD_MPU_OPP120_UV),
 	/* DSP OPP4 - OPP-SB */
-	OPP_INITIALIZER("iva", false, 800000000, 1375000),
+	OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV),
 };
 
 /**
  * omap3_opp_init() - initialize omap3 opp table
  */
-static int __init omap3_opp_init(void)
+int __init omap3_opp_init(void)
 {
 	int r = -ENODEV;
 
diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c
index a11fa56..2293ba2 100644
--- a/arch/arm/mach-omap2/opp4xxx_data.c
+++ b/arch/arm/mach-omap2/opp4xxx_data.c
@@ -5,8 +5,9 @@
  *	Nishanth Menon
  *	Kevin Hilman
  *	Thara Gopinath
- * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2010-2011 Nokia Corporation.
  *      Eduardo Valentin
+ *      Paul Walmsley
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -21,28 +22,75 @@
 
 #include <plat/cpu.h>
 
+#include "control.h"
 #include "omap_opp_data.h"
+#include "pm.h"
+
+/*
+ * Structures containing OMAP4430 voltage supported and various
+ * voltage dependent data for each VDD.
+ */
+
+#define OMAP4430_VDD_MPU_OPP50_UV		1025000
+#define OMAP4430_VDD_MPU_OPP100_UV		1200000
+#define OMAP4430_VDD_MPU_OPPTURBO_UV		1313000
+#define OMAP4430_VDD_MPU_OPPNITRO_UV		1375000
+
+struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4430_VDD_IVA_OPP50_UV		1013000
+#define OMAP4430_VDD_IVA_OPP100_UV		1188000
+#define OMAP4430_VDD_IVA_OPPTURBO_UV		1300000
+
+struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4430_VDD_CORE_OPP50_UV		1025000
+#define OMAP4430_VDD_CORE_OPP100_UV		1200000
+
+struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
 
 static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
 	/* MPU OPP1 - OPP50 */
-	OPP_INITIALIZER("mpu", true, 300000000, 1100000),
+	OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
 	/* MPU OPP2 - OPP100 */
-	OPP_INITIALIZER("mpu", true, 600000000, 1200000),
+	OPP_INITIALIZER("mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV),
 	/* MPU OPP3 - OPP-Turbo */
-	OPP_INITIALIZER("mpu", false, 800000000, 1260000),
+	OPP_INITIALIZER("mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV),
 	/* MPU OPP4 - OPP-SB */
-	OPP_INITIALIZER("mpu", false, 1008000000, 1350000),
+	OPP_INITIALIZER("mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV),
 	/* L3 OPP1 - OPP50 */
-	OPP_INITIALIZER("l3_main_1", true, 100000000, 930000),
+	OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV),
 	/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
-	OPP_INITIALIZER("l3_main_1", true, 200000000, 1100000),
-	/* TODO: add IVA, DSP, aess, fdif, gpu */
+	OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV),
+	/* IVA OPP1 - OPP50 */
+	OPP_INITIALIZER("iva", true, 133000000, OMAP4430_VDD_IVA_OPP50_UV),
+	/* IVA OPP2 - OPP100 */
+	OPP_INITIALIZER("iva", true, 266100000, OMAP4430_VDD_IVA_OPP100_UV),
+	/* IVA OPP3 - OPP-Turbo */
+	OPP_INITIALIZER("iva", false, 332000000, OMAP4430_VDD_IVA_OPPTURBO_UV),
+	/* TODO: add DSP, aess, fdif, gpu */
 };
 
 /**
  * omap4_opp_init() - initialize omap4 opp table
  */
-static int __init omap4_opp_init(void)
+int __init omap4_opp_init(void)
 {
 	int r = -ENODEV;
 
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index d5a102c..30af335 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -18,8 +18,8 @@
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
-#include <plat/voltage.h>
 
+#include "voltage.h"
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
@@ -83,7 +83,9 @@ static int _init_omap_device(char *name, struct device **new_dev)
 static void omap2_init_processor_devices(void)
 {
 	_init_omap_device("mpu", &mpu_dev);
-	_init_omap_device("iva", &iva_dev);
+	if (omap3_has_iva())
+		_init_omap_device("iva", &iva_dev);
+
 	if (cpu_is_omap44xx()) {
 		_init_omap_device("l3_main_1", &l3_dev);
 		_init_omap_device("dsp", &dsp_dev);
@@ -124,7 +126,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
 			sleep_switch = LOWPOWERSTATE_SWITCH;
 		} else {
-			omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
 			pwrdm_wait_transition(pwrdm);
 			sleep_switch = FORCEWAKEUP_SWITCH;
 		}
@@ -140,9 +142,9 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
 		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
-			omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
 		else
-			omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
 		break;
 	case LOWPOWERSTATE_SWITCH:
 		pwrdm_set_lowpwrstchange(pwrdm);
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 1c1b0ab..797bfd1 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -92,7 +92,7 @@ extern void omap24xx_idle_loop_suspend(void);
 extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
 					void __iomem *sdrc_power);
 extern void omap34xx_cpu_suspend(u32 *addr, int save_state);
-extern void save_secure_ram_context(u32 *addr);
+extern int save_secure_ram_context(u32 *addr);
 extern void omap3_save_scratchpad_contents(void);
 
 extern unsigned int omap24xx_idle_loop_suspend_sz;
@@ -127,6 +127,7 @@ static inline void omap_enable_smartreflex_on_init(void) {}
 #ifdef CONFIG_TWL4030_CORE
 extern int omap3_twl_init(void);
 extern int omap4_twl_init(void);
+extern int omap3_twl_set_sr_bit(bool enable);
 #else
 static inline int omap3_twl_init(void)
 {
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index 97feb3a..df3ded6 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -363,14 +363,11 @@ static const struct platform_suspend_ops __initdata omap_pm_ops;
 /* XXX This function should be shareable between OMAP2xxx and OMAP3 */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-	clkdm_clear_all_wkdeps(clkdm);
-	clkdm_clear_all_sleepdeps(clkdm);
-
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
-		omap2_clkdm_allow_idle(clkdm);
+		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
 		 atomic_read(&clkdm->usecount) == 0)
-		omap2_clkdm_sleep(clkdm);
+		clkdm_sleep(clkdm);
 	return 0;
 }
 
@@ -379,7 +376,10 @@ static void __init prcm_setup_regs(void)
 	int i, num_mem_banks;
 	struct powerdomain *pwrdm;
 
-	/* Enable autoidle */
+	/*
+	 * Enable autoidle
+	 * XXX This should be handled by hwmod code or PRCM init code
+	 */
 	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
 			  OMAP2_PRCM_SYSCONFIG_OFFSET);
 
@@ -405,83 +405,16 @@ static void __init prcm_setup_regs(void)
 
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	omap2_clkdm_sleep(dsp_clkdm);
+	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	omap2_clkdm_sleep(gfx_clkdm);
+	clkdm_sleep(gfx_clkdm);
 
-	/*
-	 * Clear clockdomain wakeup dependencies and enable
-	 * hardware-supervised idle for all clkdms
-	 */
+	/* Enable hardware-supervised idle for all clkdms */
 	clkdm_for_each(clkdms_setup, NULL);
 	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
 
-	/* Enable clock autoidle for all domains */
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK |
-			       OMAP24XX_AUTO_MAILBOXES_MASK |
-			       OMAP24XX_AUTO_WDT4_MASK |
-			       OMAP2420_AUTO_WDT3_MASK |
-			       OMAP24XX_AUTO_MSPRO_MASK |
-			       OMAP2420_AUTO_MMC_MASK |
-			       OMAP24XX_AUTO_FAC_MASK |
-			       OMAP2420_AUTO_EAC_MASK |
-			       OMAP24XX_AUTO_HDQ_MASK |
-			       OMAP24XX_AUTO_UART2_MASK |
-			       OMAP24XX_AUTO_UART1_MASK |
-			       OMAP24XX_AUTO_I2C2_MASK |
-			       OMAP24XX_AUTO_I2C1_MASK |
-			       OMAP24XX_AUTO_MCSPI2_MASK |
-			       OMAP24XX_AUTO_MCSPI1_MASK |
-			       OMAP24XX_AUTO_MCBSP2_MASK |
-			       OMAP24XX_AUTO_MCBSP1_MASK |
-			       OMAP24XX_AUTO_GPT12_MASK |
-			       OMAP24XX_AUTO_GPT11_MASK |
-			       OMAP24XX_AUTO_GPT10_MASK |
-			       OMAP24XX_AUTO_GPT9_MASK |
-			       OMAP24XX_AUTO_GPT8_MASK |
-			       OMAP24XX_AUTO_GPT7_MASK |
-			       OMAP24XX_AUTO_GPT6_MASK |
-			       OMAP24XX_AUTO_GPT5_MASK |
-			       OMAP24XX_AUTO_GPT4_MASK |
-			       OMAP24XX_AUTO_GPT3_MASK |
-			       OMAP24XX_AUTO_GPT2_MASK |
-			       OMAP2420_AUTO_VLYNQ_MASK |
-			       OMAP24XX_AUTO_DSS_MASK,
-			       CORE_MOD, CM_AUTOIDLE1);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK |
-			       OMAP24XX_AUTO_SSI_MASK |
-			       OMAP24XX_AUTO_USB_MASK,
-			       CORE_MOD, CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK |
-			       OMAP24XX_AUTO_GPMC_MASK |
-			       OMAP24XX_AUTO_SDMA_MASK,
-			       CORE_MOD, CM_AUTOIDLE3);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK |
-			       OMAP24XX_AUTO_AES_MASK |
-			       OMAP24XX_AUTO_RNG_MASK |
-			       OMAP24XX_AUTO_SHA_MASK |
-			       OMAP24XX_AUTO_DES_MASK,
-			       CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
-
-	omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
-			       CM_AUTOIDLE);
-
-	/* Put DPLL and both APLLs into autoidle mode */
-	omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
-			       (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
-			       (0x03 << OMAP24XX_AUTO_54M_SHIFT),
-			       PLL_MOD, CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
-			       OMAP24XX_AUTO_WDT1_MASK |
-			       OMAP24XX_AUTO_MPU_WDT_MASK |
-			       OMAP24XX_AUTO_GPIOS_MASK |
-			       OMAP24XX_AUTO_32KSYNC_MASK |
-			       OMAP24XX_AUTO_GPT1_MASK,
-			       WKUP_MOD, CM_AUTOIDLE);
-
 	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
 	 * stabilisation */
 	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 2f864e4..0c5e3a4 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/console.h>
+#include <trace/events/power.h>
 
 #include <plat/sram.h>
 #include "clockdomain.h"
@@ -311,11 +312,6 @@ static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static void restore_control_register(u32 val)
-{
-	__asm__ __volatile__ ("mcr p15, 0, %0, c1, c0, 0" : : "r" (val));
-}
-
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
@@ -337,7 +333,7 @@ static void restore_table_entry(void)
 	control_reg_value = __raw_readl(scratchpad_address
 					+ OMAP343X_CONTROL_REG_VALUE_OFFSET);
 	/* This will enable caches and prediction */
-	restore_control_register(control_reg_value);
+	set_cr(control_reg_value);
 }
 
 void omap_sram_idle(void)
@@ -496,7 +492,7 @@ console_still_active:
 
 	pwrdm_post_transition();
 
-	omap2_clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -519,8 +515,14 @@ static void omap3_pm_idle(void)
 	if (omap_irq_pending() || need_resched())
 		goto out;
 
+	trace_power_start(POWER_CSTATE, 1, smp_processor_id());
+	trace_cpu_idle(1, smp_processor_id());
+
 	omap_sram_idle();
 
+	trace_power_end(smp_processor_id());
+	trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
+
 out:
 	local_fiq_enable();
 	local_irq_enable();
@@ -688,149 +690,15 @@ static void __init omap3_d2d_idle(void)
 
 static void __init prcm_setup_regs(void)
 {
-	u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_AUTO_UART4_MASK : 0;
 	u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
 					OMAP3630_EN_UART4_MASK : 0;
 	u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
 					OMAP3630_GRPSEL_UART4_MASK : 0;
 
-
-	/* XXX Reset all wkdeps. This should be done when initializing
-	 * powerdomains */
-	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
-		omap2_prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
-	} else
-		omap2_prm_write_mod_reg(0, GFX_MOD, PM_WKDEP);
-
-	/*
-	 * Enable interface clock autoidle for all modules.
-	 * Note that in the long run this should be done by clockfw
-	 */
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_MODEM_MASK |
-		OMAP3430ES2_AUTO_MMC3_MASK |
-		OMAP3430ES2_AUTO_ICR_MASK |
-		OMAP3430_AUTO_AES2_MASK |
-		OMAP3430_AUTO_SHA12_MASK |
-		OMAP3430_AUTO_DES2_MASK |
-		OMAP3430_AUTO_MMC2_MASK |
-		OMAP3430_AUTO_MMC1_MASK |
-		OMAP3430_AUTO_MSPRO_MASK |
-		OMAP3430_AUTO_HDQ_MASK |
-		OMAP3430_AUTO_MCSPI4_MASK |
-		OMAP3430_AUTO_MCSPI3_MASK |
-		OMAP3430_AUTO_MCSPI2_MASK |
-		OMAP3430_AUTO_MCSPI1_MASK |
-		OMAP3430_AUTO_I2C3_MASK |
-		OMAP3430_AUTO_I2C2_MASK |
-		OMAP3430_AUTO_I2C1_MASK |
-		OMAP3430_AUTO_UART2_MASK |
-		OMAP3430_AUTO_UART1_MASK |
-		OMAP3430_AUTO_GPT11_MASK |
-		OMAP3430_AUTO_GPT10_MASK |
-		OMAP3430_AUTO_MCBSP5_MASK |
-		OMAP3430_AUTO_MCBSP1_MASK |
-		OMAP3430ES1_AUTO_FAC_MASK | /* This is es1 only */
-		OMAP3430_AUTO_MAILBOXES_MASK |
-		OMAP3430_AUTO_OMAPCTRL_MASK |
-		OMAP3430ES1_AUTO_FSHOSTUSB_MASK |
-		OMAP3430_AUTO_HSOTGUSB_MASK |
-		OMAP3430_AUTO_SAD2D_MASK |
-		OMAP3430_AUTO_SSI_MASK,
-		CORE_MOD, CM_AUTOIDLE1);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_PKA_MASK |
-		OMAP3430_AUTO_AES1_MASK |
-		OMAP3430_AUTO_RNG_MASK |
-		OMAP3430_AUTO_SHA11_MASK |
-		OMAP3430_AUTO_DES1_MASK,
-		CORE_MOD, CM_AUTOIDLE2);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_cm_write_mod_reg(
-			OMAP3430_AUTO_MAD2D_MASK |
-			OMAP3430ES2_AUTO_USBTLL_MASK,
-			CORE_MOD, CM_AUTOIDLE3);
-	}
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_WDT2_MASK |
-		OMAP3430_AUTO_WDT1_MASK |
-		OMAP3430_AUTO_GPIO1_MASK |
-		OMAP3430_AUTO_32KSYNC_MASK |
-		OMAP3430_AUTO_GPT12_MASK |
-		OMAP3430_AUTO_GPT1_MASK,
-		WKUP_MOD, CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_DSS_MASK,
-		OMAP3430_DSS_MOD,
-		CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_CAM_MASK,
-		OMAP3430_CAM_MOD,
-		CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		omap3630_auto_uart4_mask |
-		OMAP3430_AUTO_GPIO6_MASK |
-		OMAP3430_AUTO_GPIO5_MASK |
-		OMAP3430_AUTO_GPIO4_MASK |
-		OMAP3430_AUTO_GPIO3_MASK |
-		OMAP3430_AUTO_GPIO2_MASK |
-		OMAP3430_AUTO_WDT3_MASK |
-		OMAP3430_AUTO_UART3_MASK |
-		OMAP3430_AUTO_GPT9_MASK |
-		OMAP3430_AUTO_GPT8_MASK |
-		OMAP3430_AUTO_GPT7_MASK |
-		OMAP3430_AUTO_GPT6_MASK |
-		OMAP3430_AUTO_GPT5_MASK |
-		OMAP3430_AUTO_GPT4_MASK |
-		OMAP3430_AUTO_GPT3_MASK |
-		OMAP3430_AUTO_GPT2_MASK |
-		OMAP3430_AUTO_MCBSP4_MASK |
-		OMAP3430_AUTO_MCBSP3_MASK |
-		OMAP3430_AUTO_MCBSP2_MASK,
-		OMAP3430_PER_MOD,
-		CM_AUTOIDLE);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_cm_write_mod_reg(
-			OMAP3430ES2_AUTO_USBHOST_MASK,
-			OMAP3430ES2_USBHOST_MOD,
-			CM_AUTOIDLE);
-	}
-
+	/* XXX This should be handled by hwmod code or SCM init code */
 	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
 
 	/*
-	 * Set all plls to autoidle. This is needed until autoidle is
-	 * enabled by clockfw
-	 */
-	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
-			 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
-			 MPU_MOD,
-			 CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
-			 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
-			 PLL_MOD,
-			 CM_AUTOIDLE);
-	omap2_cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT,
-			 PLL_MOD,
-			 CM_AUTOIDLE2);
-
-	/*
 	 * Enable control of expternal oscillator through
 	 * sys_clkreq. In the long run clock framework should
 	 * take care of this.
@@ -928,8 +796,7 @@ void omap3_pm_off_mode_enable(int enable)
 				pwrst->pwrdm == core_pwrdm &&
 				state == PWRDM_POWER_OFF) {
 			pwrst->next_state = PWRDM_POWER_RET;
-			WARN_ONCE(1,
-				"%s: Core OFF disabled due to errata i583\n",
+			pr_warn("%s: Core OFF disabled due to errata i583\n",
 				__func__);
 		} else {
 			pwrst->next_state = state;
@@ -990,10 +857,10 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
-		omap2_clkdm_allow_idle(clkdm);
+		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
 		 atomic_read(&clkdm->usecount) == 0)
-		omap2_clkdm_sleep(clkdm);
+		clkdm_sleep(clkdm);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index eaed0df..49c6513 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -2,7 +2,7 @@
  * OMAP powerdomain control
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -19,12 +19,15 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <trace/events/power.h>
+
 #include "cm2xxx_3xxx.h"
 #include "prcm44xx.h"
 #include "cm44xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
 
+#include <asm/cpu.h>
 #include <plat/cpu.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
@@ -32,6 +35,8 @@
 
 #include "pm.h"
 
+#define PWRDM_TRACE_STATES_FLAG	(1<<31)
+
 enum {
 	PWRDM_STATE_NOW = 0,
 	PWRDM_STATE_PREV,
@@ -130,8 +135,7 @@ static void _update_logic_membank_counters(struct powerdomain *pwrdm)
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-	int prev;
-	int state;
+	int prev, state, trace_state = 0;
 
 	if (pwrdm == NULL)
 		return -EINVAL;
@@ -148,6 +152,17 @@ static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 			pwrdm->state_counter[prev]++;
 		if (prev == PWRDM_POWER_RET)
 			_update_logic_membank_counters(pwrdm);
+		/*
+		 * If the power domain did not hit the desired state,
+		 * generate a trace event with both the desired and hit states
+		 */
+		if (state != prev) {
+			trace_state = (PWRDM_TRACE_STATES_FLAG |
+				       ((state & OMAP_POWERSTATE_MASK) << 8) |
+				       ((prev & OMAP_POWERSTATE_MASK) << 0));
+			trace_power_domain_target(pwrdm->name, trace_state,
+						  smp_processor_id());
+		}
 		break;
 	default:
 		return -EINVAL;
@@ -406,8 +421,13 @@ int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
 	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
 		 pwrdm->name, pwrst);
 
-	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
+		/* Trace the pwrdm desired target state */
+		trace_power_domain_target(pwrdm->name, pwrst,
+					  smp_processor_id());
+		/* Program the pwrdm desired target state */
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
+	}
 
 	return ret;
 }
@@ -938,3 +958,44 @@ u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm)
 
 	return count;
 }
+
+/**
+ * pwrdm_can_ever_lose_context - can this powerdomain ever lose context?
+ * @pwrdm: struct powerdomain *
+ *
+ * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain
+ * can lose either memory or logic context or if @pwrdm is invalid, or
+ * returns 0 otherwise.  This function is not concerned with how the
+ * powerdomain registers are programmed (i.e., to go off or not); it's
+ * concerned with whether it's ever possible for this powerdomain to
+ * go off while some other part of the chip is active.  This function
+ * assumes that every powerdomain can go to either ON or INACTIVE.
+ */
+bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
+{
+	int i;
+
+	if (IS_ERR_OR_NULL(pwrdm)) {
+		pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
+			 __func__);
+		return 1;
+	}
+
+	if (pwrdm->pwrsts & PWRSTS_OFF)
+		return 1;
+
+	if (pwrdm->pwrsts & PWRSTS_RET) {
+		if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF)
+			return 1;
+
+		for (i = 0; i < pwrdm->banks; i++)
+			if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF)
+				return 1;
+	}
+
+	for (i = 0; i < pwrdm->banks; i++)
+		if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF)
+			return 1;
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index c66431e..027f40b 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -2,7 +2,7 @@
  * OMAP2/3/4 powerdomain control
  *
  * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley
  *
@@ -34,17 +34,14 @@
 
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_ON		(1 << PWRDM_POWER_ON)
+#define PWRSTS_INACTIVE		(1 << PWRDM_POWER_INACTIVE)
+#define PWRSTS_RET		(1 << PWRDM_POWER_RET)
 #define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
-#define PWRSTS_OFF_ON		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_ON))
 
-#define PWRSTS_OFF_RET		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_RET))
-
-#define PWRSTS_RET_ON		((1 << PWRDM_POWER_RET) | \
-				 (1 << PWRDM_POWER_ON))
-
-#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
+#define PWRSTS_OFF_ON		(PWRSTS_OFF | PWRSTS_ON)
+#define PWRSTS_OFF_RET		(PWRSTS_OFF | PWRSTS_RET)
+#define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
+#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
 
 /* Powerdomain flags */
@@ -165,7 +162,6 @@ struct pwrdm_ops {
 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
 };
 
-void pwrdm_fw_init(void);
 void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
 
 struct powerdomain *pwrdm_lookup(const char *name);
@@ -212,6 +208,7 @@ int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
 extern void omap2xxx_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
index 5b4dd97..4210c33 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP2/3 common powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HĂśgander
  *
@@ -62,13 +62,13 @@ struct powerdomain gfx_omap2_pwrdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 					   CHIP_IS_OMAP3430ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -76,4 +76,5 @@ struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+	.pwrsts		= PWRSTS_ON,
 };
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index 9b1a335..cc389fb 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP2XXX powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HĂśgander
  *
@@ -30,13 +30,13 @@ static struct powerdomain dsp_pwrdm = {
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
+		[0] = PWRSTS_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
 	},
 };
 
@@ -48,10 +48,10 @@ static struct powerdomain mpu_24xx_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
+		[0] = PWRSTS_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
 	},
 };
 
@@ -78,7 +78,7 @@ static struct powerdomain core_24xx_pwrdm = {
  * 2430-specific powerdomains
  */
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 
 /* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 
@@ -87,17 +87,17 @@ static struct powerdomain mdm_pwrdm = {
 	.prcm_offs	  = OMAP2430_MDM_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
-#endif     /* CONFIG_ARCH_OMAP2430 */
+#endif     /* CONFIG_SOC_OMAP2430 */
 
 /* As powerdomains are added or removed above, this list must also be changed */
 static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
@@ -111,7 +111,7 @@ static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
 	&core_24xx_pwrdm,
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 	&mdm_pwrdm,
 #endif
 	NULL
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index e1bec56..9c9c113 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -2,7 +2,7 @@
  * OMAP3 powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HĂśgander
  *
@@ -47,10 +47,10 @@ static struct powerdomain iva2_pwrdm = {
 		[3] = PWRSTS_OFF_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
-		[1] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
+		[1] = PWRSTS_ON,
 		[2] = PWRSTS_OFF_ON,
-		[3] = PWRDM_POWER_ON,
+		[3] = PWRSTS_ON,
 	},
 };
 
@@ -128,13 +128,13 @@ static struct powerdomain dss_pwrdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -149,13 +149,13 @@ static struct powerdomain sgx_pwrdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -164,13 +164,13 @@ static struct powerdomain cam_pwrdm = {
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -182,10 +182,10 @@ static struct powerdomain per_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -200,7 +200,7 @@ static struct powerdomain neon_pwrdm = {
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 };
 
 static struct powerdomain usbhost_pwrdm = {
@@ -208,7 +208,7 @@ static struct powerdomain usbhost_pwrdm = {
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	/*
 	 * REVISIT: Enabling usb host save and restore mechanism seems to
 	 * leave the usb host domain permanently in ACTIVE mode after
@@ -218,10 +218,10 @@ static struct powerdomain usbhost_pwrdm = {
 	/*.flags	  = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
diff --git a/arch/arm/mach-omap2/powerdomains44xx_data.c b/arch/arm/mach-omap2/powerdomains44xx_data.c
index 26d7641..c4222c7 100644
--- a/arch/arm/mach-omap2/powerdomains44xx_data.c
+++ b/arch/arm/mach-omap2/powerdomains44xx_data.c
@@ -2,7 +2,7 @@
  * OMAP4 Power domains framework
  *
  * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Abhijit Pagare (abhijitpagare@ti.com)
  * Benoit Cousson (b-cousson@ti.com)
@@ -40,18 +40,18 @@ static struct powerdomain core_44xx_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* core_nret_bank */
+		[0] = PWRSTS_OFF,	/* core_nret_bank */
 		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_RET,	/* core_other_bank */
+		[2] = PWRSTS_RET,	/* core_other_bank */
 		[3] = PWRSTS_OFF_RET,	/* ducati_l2ram */
 		[4] = PWRSTS_OFF_RET,	/* ducati_unicache */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* core_nret_bank */
+		[0] = PWRSTS_ON,	/* core_nret_bank */
 		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_ON,	/* core_other_bank */
-		[3] = PWRDM_POWER_ON,	/* ducati_l2ram */
-		[4] = PWRDM_POWER_ON,	/* ducati_unicache */
+		[2] = PWRSTS_ON,	/* core_other_bank */
+		[3] = PWRSTS_ON,	/* ducati_l2ram */
+		[4] = PWRSTS_ON,	/* ducati_unicache */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -65,10 +65,10 @@ static struct powerdomain gfx_44xx_pwrdm = {
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* gfx_mem */
+		[0] = PWRSTS_OFF,	/* gfx_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* gfx_mem */
+		[0] = PWRSTS_ON,	/* gfx_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -80,15 +80,15 @@ static struct powerdomain abe_44xx_pwrdm = {
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* aessmem */
-		[1] = PWRDM_POWER_OFF,	/* periphmem */
+		[0] = PWRSTS_RET,	/* aessmem */
+		[1] = PWRSTS_OFF,	/* periphmem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* aessmem */
-		[1] = PWRDM_POWER_ON,	/* periphmem */
+		[0] = PWRSTS_ON,	/* aessmem */
+		[1] = PWRSTS_ON,	/* periphmem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -103,10 +103,10 @@ static struct powerdomain dss_44xx_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* dss_mem */
+		[0] = PWRSTS_OFF,	/* dss_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* dss_mem */
+		[0] = PWRSTS_ON,	/* dss_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -121,14 +121,14 @@ static struct powerdomain tesla_44xx_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* tesla_edma */
+		[0] = PWRSTS_RET,	/* tesla_edma */
 		[1] = PWRSTS_OFF_RET,	/* tesla_l1 */
 		[2] = PWRSTS_OFF_RET,	/* tesla_l2 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* tesla_edma */
-		[1] = PWRDM_POWER_ON,	/* tesla_l1 */
-		[2] = PWRDM_POWER_ON,	/* tesla_l2 */
+		[0] = PWRSTS_ON,	/* tesla_edma */
+		[1] = PWRSTS_ON,	/* tesla_l1 */
+		[2] = PWRSTS_ON,	/* tesla_l2 */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -142,10 +142,10 @@ static struct powerdomain wkup_44xx_pwrdm = {
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* wkup_bank */
+		[0] = PWRSTS_OFF,	/* wkup_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* wkup_bank */
+		[0] = PWRSTS_ON,	/* wkup_bank */
 	},
 };
 
@@ -162,7 +162,7 @@ static struct powerdomain cpu0_44xx_pwrdm = {
 		[0] = PWRSTS_OFF_RET,	/* cpu0_l1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu0_l1 */
+		[0] = PWRSTS_ON,	/* cpu0_l1 */
 	},
 };
 
@@ -179,7 +179,7 @@ static struct powerdomain cpu1_44xx_pwrdm = {
 		[0] = PWRSTS_OFF_RET,	/* cpu1_l1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu1_l1 */
+		[0] = PWRSTS_ON,	/* cpu1_l1 */
 	},
 };
 
@@ -192,10 +192,10 @@ static struct powerdomain emu_44xx_pwrdm = {
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* emu_bank */
+		[0] = PWRSTS_OFF,	/* emu_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* emu_bank */
+		[0] = PWRSTS_ON,	/* emu_bank */
 	},
 };
 
@@ -211,12 +211,12 @@ static struct powerdomain mpu_44xx_pwrdm = {
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* mpu_l1 */
 		[1] = PWRSTS_OFF_RET,	/* mpu_l2 */
-		[2] = PWRDM_POWER_RET,	/* mpu_ram */
+		[2] = PWRSTS_RET,	/* mpu_ram */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* mpu_l1 */
-		[1] = PWRDM_POWER_ON,	/* mpu_l2 */
-		[2] = PWRDM_POWER_ON,	/* mpu_ram */
+		[0] = PWRSTS_ON,	/* mpu_l1 */
+		[1] = PWRSTS_ON,	/* mpu_l2 */
+		[2] = PWRSTS_ON,	/* mpu_ram */
 	},
 };
 
@@ -227,19 +227,19 @@ static struct powerdomain ivahd_44xx_pwrdm = {
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* hwa_mem */
+		[0] = PWRSTS_OFF,	/* hwa_mem */
 		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
 		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
 		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* hwa_mem */
-		[1] = PWRDM_POWER_ON,	/* sl2_mem */
-		[2] = PWRDM_POWER_ON,	/* tcm1_mem */
-		[3] = PWRDM_POWER_ON,	/* tcm2_mem */
+		[0] = PWRSTS_ON,	/* hwa_mem */
+		[1] = PWRSTS_ON,	/* sl2_mem */
+		[2] = PWRSTS_ON,	/* tcm1_mem */
+		[3] = PWRSTS_ON,	/* tcm2_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -253,10 +253,10 @@ static struct powerdomain cam_44xx_pwrdm = {
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* cam_mem */
+		[0] = PWRSTS_OFF,	/* cam_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cam_mem */
+		[0] = PWRSTS_ON,	/* cam_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -271,10 +271,10 @@ static struct powerdomain l3init_44xx_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* l3init_bank1 */
+		[0] = PWRSTS_OFF,	/* l3init_bank1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* l3init_bank1 */
+		[0] = PWRSTS_ON,	/* l3init_bank1 */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -289,12 +289,12 @@ static struct powerdomain l4per_44xx_pwrdm = {
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* nonretained_bank */
-		[1] = PWRDM_POWER_RET,	/* retained_bank */
+		[0] = PWRSTS_OFF,	/* nonretained_bank */
+		[1] = PWRSTS_RET,	/* retained_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* nonretained_bank */
-		[1] = PWRDM_POWER_ON,	/* retained_bank */
+		[0] = PWRSTS_ON,	/* nonretained_bank */
+		[1] = PWRSTS_ON,	/* retained_bank */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h
index 87486f5..0363dcb 100644
--- a/arch/arm/mach-omap2/prcm-common.h
+++ b/arch/arm/mach-omap2/prcm-common.h
@@ -121,6 +121,10 @@
 #define OMAP24XX_ST_MCSPI2_MASK				(1 << 18)
 #define OMAP24XX_ST_MCSPI1_SHIFT			17
 #define OMAP24XX_ST_MCSPI1_MASK				(1 << 17)
+#define OMAP24XX_ST_MCBSP2_SHIFT			16
+#define OMAP24XX_ST_MCBSP2_MASK				(1 << 16)
+#define OMAP24XX_ST_MCBSP1_SHIFT			15
+#define OMAP24XX_ST_MCBSP1_MASK				(1 << 15)
 #define OMAP24XX_ST_GPT12_SHIFT				14
 #define OMAP24XX_ST_GPT12_MASK				(1 << 14)
 #define OMAP24XX_ST_GPT11_SHIFT				13
@@ -191,6 +195,8 @@
 #define OMAP3430_AUTOIDLE_MASK				(1 << 0)
 
 /* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
+#define OMAP3430_EN_MMC3_MASK				(1 << 30)
+#define OMAP3430_EN_MMC3_SHIFT				30
 #define OMAP3430_EN_MMC2_MASK				(1 << 25)
 #define OMAP3430_EN_MMC2_SHIFT				25
 #define OMAP3430_EN_MMC1_MASK				(1 << 24)
@@ -231,6 +237,8 @@
 #define OMAP3430_EN_HSOTGUSB_SHIFT			4
 
 /* PM_WKST1_CORE, CM_IDLEST1_CORE shared bits */
+#define OMAP3430_ST_MMC3_SHIFT				30
+#define OMAP3430_ST_MMC3_MASK				(1 << 30)
 #define OMAP3430_ST_MMC2_SHIFT				25
 #define OMAP3430_ST_MMC2_MASK				(1 << 25)
 #define OMAP3430_ST_MMC1_SHIFT				24
diff --git a/arch/arm/mach-omap2/prcm.c b/arch/arm/mach-omap2/prcm.c
index 679bcd2..6be1438 100644
--- a/arch/arm/mach-omap2/prcm.c
+++ b/arch/arm/mach-omap2/prcm.c
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
+#include <mach/system.h>
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
@@ -57,7 +58,7 @@ u32 omap_prcm_get_reset_sources(void)
 EXPORT_SYMBOL(omap_prcm_get_reset_sources);
 
 /* Resets clock rates and reboots the system. Only called from system.h */
-void omap_prcm_arch_reset(char mode, const char *cmd)
+static void omap_prcm_arch_reset(char mode, const char *cmd)
 {
 	s16 prcm_offs = 0;
 
@@ -108,6 +109,8 @@ void omap_prcm_arch_reset(char mode, const char *cmd)
 	omap2_prm_read_mod_reg(prcm_offs, OMAP2_RM_RSTCTRL); /* OCP barrier */
 }
 
+void (*arch_reset)(char, const char *) = omap_prcm_arch_reset;
+
 /**
  * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
  * @reg: physical address of module IDLEST register
diff --git a/arch/arm/mach-omap2/prcm_mpu44xx.h b/arch/arm/mach-omap2/prcm_mpu44xx.h
index 3300ff6..d22d1b4 100644
--- a/arch/arm/mach-omap2/prcm_mpu44xx.h
+++ b/arch/arm/mach-omap2/prcm_mpu44xx.h
@@ -38,8 +38,8 @@
 #define OMAP4430_PRCM_MPU_CPU1_INST		0x0800
 
 /* PRCM_MPU clockdomain register offsets (from instance start) */
-#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS	0x0018
-#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS	0x0018
 
 
 /*
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index ec03625..051213f 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -118,7 +118,8 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
 /**
  * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
  * @prm_mod: PRM submodule base (e.g. CORE_MOD)
- * @shift: register bit shift corresponding to the reset line to deassert
+ * @rst_shift: register bit shift corresponding to the reset line to deassert
+ * @st_shift: register bit shift for the status of the deasserted submodule
  *
  * Some IPs like dsp or iva contain processors that require an HW
  * reset line to be asserted / deasserted in order to fully enable the
@@ -129,27 +130,28 @@ int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
  * of reset, or -EBUSY if the submodule did not exit reset promptly.
  */
-int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
 {
-	u32 mask;
+	u32 rst, st;
 	int c;
 
 	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
 		return -EINVAL;
 
-	mask = 1 << shift;
+	rst = 1 << rst_shift;
+	st = 1 << st_shift;
 
 	/* Check the current status to avoid de-asserting the line twice */
-	if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+	if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0)
 		return -EEXIST;
 
 	/* Clear the reset status by writing 1 to the status bit */
-	omap2_prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+	omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST);
 	/* de-assert the reset control line */
-	omap2_prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+	omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL);
 	/* wait the status to be set */
 	omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
-						  mask),
+						  st),
 			  MAX_MODULE_HARDRESET_WAIT, c);
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.h b/arch/arm/mach-omap2/prm2xxx_3xxx.h
index 49654c8..a1fc62a 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.h
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.h
@@ -282,7 +282,8 @@ static inline int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
 		"not suppose to be used on omap4\n");
 	return 0;
 }
-static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
+						u8 st_shift)
 {
 	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
 		"not suppose to be used on omap4\n");
@@ -300,7 +301,7 @@ extern u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
 /* These omap2_ PRM functions apply to both OMAP2 and 3 */
 extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
 extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
-extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 
 #endif	/* CONFIG_ARCH_OMAP4 */
 #endif
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 32e91a9..1ac361b 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -486,7 +486,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
 		mod_timer(&uart->timer, jiffies + uart->timeout);
 	omap_uart_smart_idle_enable(uart, 0);
 
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
 		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
 		u32 padconf = 0;
@@ -655,7 +655,7 @@ static void serial_out_override(struct uart_port *up, int offset, int value)
 }
 #endif
 
-void __init omap_serial_early_init(void)
+static int __init omap_serial_early_init(void)
 {
 	int i = 0;
 
@@ -672,7 +672,7 @@ void __init omap_serial_early_init(void)
 
 		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
 		if (WARN_ON(!uart))
-			return;
+			return -ENODEV;
 
 		uart->oh = oh;
 		uart->num = i++;
@@ -680,7 +680,7 @@ void __init omap_serial_early_init(void)
 		num_uarts++;
 
 		/*
-		 * NOTE: omap_hwmod_init() has not yet been called,
+		 * NOTE: omap_hwmod_setup*() has not yet been called,
 		 *       so no hwmod functions will work yet.
 		 */
 
@@ -691,7 +691,10 @@ void __init omap_serial_early_init(void)
 		 */
 		uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
 	} while (1);
+
+	return 0;
 }
+core_initcall(omap_serial_early_init);
 
 /**
  * omap_serial_init_port() - initialize single serial port
@@ -759,13 +762,13 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	p->private_data = uart;
 
 	/*
-	 * omap44xx: Never read empty UART fifo
+	 * omap44xx, ti816x: Never read empty UART fifo
 	 * omap3xxx: Never read empty UART fifo on UARTs
 	 * with IP rev >=0x52
 	 */
 	uart->regshift = p->regshift;
 	uart->membase = p->membase;
-	if (cpu_is_omap44xx())
+	if (cpu_is_omap44xx() || cpu_is_ti816x())
 		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
 	else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
 			>= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
@@ -847,7 +850,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
 	}
 
 	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx() && !cpu_is_ti816x())
 		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 }
 
diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S
index c7780cc..b5071a4 100644
--- a/arch/arm/mach-omap2/sleep24xx.S
+++ b/arch/arm/mach-omap2/sleep24xx.S
@@ -47,6 +47,7 @@
  * Note: This code get's copied to internal SRAM at boot. When the OMAP
  *	 wakes up it continues execution at the point it went to sleep.
  */
+	.align	3
 ENTRY(omap24xx_idle_loop_suspend)
 	stmfd	sp!, {r0, lr}		@ save registers on stack
 	mov	r0, #0			@ clear for mcr setup
@@ -82,6 +83,7 @@ ENTRY(omap24xx_idle_loop_suspend_sz)
  * The DLL load value is not kept in RETENTION or OFF.	It needs to be restored
  * at wake
  */
+	.align	3
 ENTRY(omap24xx_cpu_suspend)
 	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
 	mov	r3, #0x0		@ clear for mcr call
diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S
index 98d8232..63f1066 100644
--- a/arch/arm/mach-omap2/sleep34xx.S
+++ b/arch/arm/mach-omap2/sleep34xx.S
@@ -64,6 +64,11 @@
 #define SDRC_DLLA_STATUS_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 #define SDRC_DLLA_CTRL_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 
+/*
+ * This file needs be built unconditionally as ARM to interoperate correctly
+ * with non-Thumb-2-capable firmware.
+ */
+	.arm
 
 /*
  * API functions
@@ -82,6 +87,8 @@ ENTRY(get_restore_pointer)
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(get_restore_pointer)
+	.align
 ENTRY(get_restore_pointer_sz)
 	.word	. - get_restore_pointer
 
@@ -91,6 +98,8 @@ ENTRY(get_omap3630_restore_pointer)
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore_3630
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(get_omap3630_restore_pointer)
+	.align
 ENTRY(get_omap3630_restore_pointer_sz)
 	.word	. - get_omap3630_restore_pointer
 
@@ -100,6 +109,8 @@ ENTRY(get_es3_restore_pointer)
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore_es3
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(get_es3_restore_pointer)
+	.align
 ENTRY(get_es3_restore_pointer_sz)
 	.word	. - get_es3_restore_pointer
 
@@ -113,11 +124,14 @@ ENTRY(enable_omap3630_toggle_l2_on_restore)
 	stmfd	sp!, {lr}	@ save registers on stack
 	/* Setup so that we will disable and enable l2 */
 	mov	r1, #0x1
-	str	r1, l2dis_3630
+	adrl	r2, l2dis_3630	@ may be too distant for plain adr
+	str	r1, [r2]
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(enable_omap3630_toggle_l2_on_restore)
 
 	.text
 /* Function to call rom code to save secure ram context */
+	.align	3
 ENTRY(save_secure_ram_context)
 	stmfd	sp!, {r1-r12, lr}	@ save registers on stack
 	adr	r3, api_params		@ r3 points to parameters
@@ -131,20 +145,22 @@ ENTRY(save_secure_ram_context)
 	mov	r1, #0			@ set task id for ROM code in r1
 	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 	nop
 	nop
 	nop
 	nop
 	ldmfd	sp!, {r1-r12, pc}
+	.align
 sram_phy_addr_mask:
 	.word	SRAM_BASE_P
 high_mask:
 	.word	0xffff
 api_params:
 	.word	0x4, 0x0, 0x0, 0x1, 0x1
+ENDPROC(save_secure_ram_context)
 ENTRY(save_secure_ram_context_sz)
 	.word	. - save_secure_ram_context
 
@@ -169,16 +185,17 @@ ENTRY(save_secure_ram_context_sz)
  *   depending on the low power mode (non-OFF vs OFF modes),
  *   cf. 'Resume path for xxx mode' comments.
  */
+	.align	3
 ENTRY(omap34xx_cpu_suspend)
 	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
 
 	/*
-	 * r0 contains restore pointer in sdram
+	 * r0 contains CPU context save/restore pointer in sdram
 	 * r1 contains information about saving context:
 	 *   0 - No context lost
 	 *   1 - Only L1 and logic lost
-	 *   2 - Only L2 lost
-	 *   3 - Both L1 and L2 lost
+	 *   2 - Only L2 lost (Even L1 is retained we clean it along with L2)
+	 *   3 - Both L1 and L2 lost and logic lost
 	 */
 
 	/* Directly jump to WFI is the context save is not required */
@@ -199,89 +216,74 @@ save_context_wfi:
 	beq	clean_caches
 
 l1_logic_lost:
-	/* Store sp and spsr to SDRAM */
-	mov	r4, sp
-	mrs	r5, spsr
-	mov	r6, lr
+	mov	r4, sp			@ Store sp
+	mrs	r5, spsr		@ Store spsr
+	mov	r6, lr			@ Store lr
 	stmia	r8!, {r4-r6}
-	/* Save all ARM registers */
-	/* Coprocessor access control register */
-	mrc	p15, 0, r6, c1, c0, 2
-	stmia	r8!, {r6}
-	/* TTBR0, TTBR1 and Translation table base control */
-	mrc	p15, 0, r4, c2, c0, 0
-	mrc	p15, 0, r5, c2, c0, 1
-	mrc	p15, 0, r6, c2, c0, 2
-	stmia	r8!, {r4-r6}
-	/*
-	 * Domain access control register, data fault status register,
-	 * and instruction fault status register
-	 */
-	mrc	p15, 0, r4, c3, c0, 0
-	mrc	p15, 0, r5, c5, c0, 0
-	mrc	p15, 0, r6, c5, c0, 1
-	stmia	r8!, {r4-r6}
-	/*
-	 * Data aux fault status register, instruction aux fault status,
-	 * data fault address register and instruction fault address register
-	 */
-	mrc	p15, 0, r4, c5, c1, 0
-	mrc	p15, 0, r5, c5, c1, 1
-	mrc	p15, 0, r6, c6, c0, 0
-	mrc	p15, 0, r7, c6, c0, 2
-	stmia	r8!, {r4-r7}
-	/*
-	 * user r/w thread and process ID, user r/o thread and process ID,
-	 * priv only thread and process ID, cache size selection
-	 */
-	mrc	p15, 0, r4, c13, c0, 2
-	mrc	p15, 0, r5, c13, c0, 3
-	mrc	p15, 0, r6, c13, c0, 4
-	mrc	p15, 2, r7, c0, c0, 0
+
+	mrc	p15, 0, r4, c1, c0, 2	@ Coprocessor access control register
+	mrc	p15, 0, r5, c2, c0, 0	@ TTBR0
+	mrc	p15, 0, r6, c2, c0, 1	@ TTBR1
+	mrc	p15, 0, r7, c2, c0, 2	@ TTBCR
 	stmia	r8!, {r4-r7}
-	/* Data TLB lockdown, instruction TLB lockdown registers */
-	mrc	p15, 0, r5, c10, c0, 0
-	mrc	p15, 0, r6, c10, c0, 1
-	stmia	r8!, {r5-r6}
-	/* Secure or non secure vector base address, FCSE PID, Context PID*/
-	mrc	p15, 0, r4, c12, c0, 0
-	mrc	p15, 0, r5, c13, c0, 0
-	mrc	p15, 0, r6, c13, c0, 1
-	stmia	r8!, {r4-r6}
-	/* Primary remap, normal remap registers */
-	mrc	p15, 0, r4, c10, c2, 0
-	mrc	p15, 0, r5, c10, c2, 1
-	stmia	r8!,{r4-r5}
 
-	/* Store current cpsr*/
-	mrs	r2, cpsr
-	stmia	r8!, {r2}
+	mrc	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
+	mrc	p15, 0, r5, c10, c2, 0	@ PRRR
+	mrc	p15, 0, r6, c10, c2, 1	@ NMRR
+	stmia	r8!,{r4-r6}
 
-	mrc	p15, 0, r4, c1, c0, 0
-	/* save control register */
+	mrc	p15, 0, r4, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
+	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
+	mrs	r7, cpsr		@ Store current cpsr
+	stmia	r8!, {r4-r7}
+
+	mrc	p15, 0, r4, c1, c0, 0	@ save control register
 	stmia	r8!, {r4}
 
 clean_caches:
 	/*
-	 * Clean Data or unified cache to POU
-	 * How to invalidate only L1 cache???? - #FIX_ME#
-	 * mcr	p15, 0, r11, c7, c11, 1
-	 */
-	cmp	r1, #0x1 		@ Check whether L2 inval is required
-	beq	omap3_do_wfi
-
-clean_l2:
-	/*
 	 * jump out to kernel flush routine
 	 *  - reuse that code is better
 	 *  - it executes in a cached space so is faster than refetch per-block
 	 *  - should be faster and will change with kernel
 	 *  - 'might' have to copy address, load and jump to it
+	 * Flush all data from the L1 data cache before disabling
+	 * SCTLR.C bit.
 	 */
 	ldr	r1, kernel_flush
 	mov	lr, pc
 	bx	r1
 
+	/*
+	 * Clear the SCTLR.C bit to prevent further data cache
+	 * allocation. Clearing SCTLR.C would make all the data accesses
+	 * strongly ordered and would not hit the cache.
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 2)	@ Disable the C bit
+	mcr	p15, 0, r0, c1, c0, 0
+	isb
+
+	/*
+	 * Invalidate L1 data cache. Even though only invalidate is
+	 * necessary exported flush API is used here. Doing clean
+	 * on already clean cache would be almost NOP.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+	/*
+	 * The kernel doesn't interwork: v7_flush_dcache_all in particluar will
+	 * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
+	 * This sequence switches back to ARM.  Note that .align may insert a
+	 * nop: bx pc needs to be word-aligned in order to work.
+	 */
+ THUMB(	.thumb		)
+ THUMB(	.align		)
+ THUMB(	bx	pc	)
+ THUMB(	nop		)
+	.arm
+
 omap3_do_wfi:
 	ldr	r4, sdrc_power		@ read the SDRC_POWER register
 	ldr	r5, [r4]		@ read the contents of SDRC_POWER
@@ -289,9 +291,8 @@ omap3_do_wfi:
 	str	r5, [r4]		@ write back to SDRC_POWER register
 
 	/* Data memory barrier and Data sync barrier */
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c10, 4
-	mcr	p15, 0, r1, c7, c10, 5
+	dsb
+	dmb
 
 /*
  * ===================================
@@ -317,6 +318,12 @@ omap3_do_wfi:
 	nop
 	bl wait_sdrc_ok
 
+	mrc	p15, 0, r0, c1, c0, 0
+	tst	r0, #(1 << 2)		@ Check C bit enabled?
+	orreq	r0, r0, #(1 << 2)	@ Enable the C bit if cleared
+	mcreq	p15, 0, r0, c1, c0, 0
+	isb
+
 /*
  * ===================================
  * == Exit point from non-OFF modes ==
@@ -406,9 +413,9 @@ skipl2dis:
 	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
 	adr	r3, l2_inv_api_params	@ r3 points to dummy parameters
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 	/* Write to Aux control register to set some bits */
 	mov	r0, #42			@ set service ID for PPA
 	mov	r12, r0			@ copy secure Service ID in r12
@@ -417,9 +424,9 @@ skipl2dis:
 	mov	r6, #0xff
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4, #0xBC]		@ r3 points to parameters
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 
 #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
 	/* Restore L2 aux control register */
@@ -432,29 +439,30 @@ skipl2dis:
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4, #0xBC]
 	adds	r3, r3, #8		@ r3 points to parameters
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 #endif
 	b	logic_l1_restore
 
+	.align
 l2_inv_api_params:
 	.word	0x1, 0x00
 l2_inv_gp:
 	/* Execute smi to invalidate L2 cache */
 	mov r12, #0x1			@ set up to invalidate L2
-	.word 0xE1600070		@ Call SMI monitor (smieq)
+	smc	#0			@ Call SMI monitor (smieq)
 	/* Write to Aux control register to set some bits */
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	ldr	r0, [r3,#4]
 	mov	r12, #0x3
-	.word	0xE1600070		@ Call SMI monitor (smieq)
+	smc	#0			@ Call SMI monitor (smieq)
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	ldr	r0, [r3,#12]
 	mov	r12, #0x2
-	.word	0xE1600070		@ Call SMI monitor (smieq)
+	smc	#0			@ Call SMI monitor (smieq)
 logic_l1_restore:
 	ldr	r1, l2dis_3630
 	cmp	r1, #0x1		@ Test if L2 re-enable needed on 3630
@@ -473,68 +481,29 @@ skipl2reen:
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	adds	r3, r3, #16
+
 	ldmia	r3!, {r4-r6}
-	mov	sp, r4
-	msr	spsr_cxsf, r5
-	mov	lr, r6
-
-	ldmia	r3!, {r4-r9}
-	/* Coprocessor access Control Register */
-	mcr p15, 0, r4, c1, c0, 2
-
-	/* TTBR0 */
-	MCR p15, 0, r5, c2, c0, 0
-	/* TTBR1 */
-	MCR p15, 0, r6, c2, c0, 1
-	/* Translation table base control register */
-	MCR p15, 0, r7, c2, c0, 2
-	/* Domain access Control Register */
-	MCR p15, 0, r8, c3, c0, 0
-	/* Data fault status Register */
-	MCR p15, 0, r9, c5, c0, 0
-
-	ldmia	r3!,{r4-r8}
-	/* Instruction fault status Register */
-	MCR p15, 0, r4, c5, c0, 1
-	/* Data Auxiliary Fault Status Register */
-	MCR p15, 0, r5, c5, c1, 0
-	/* Instruction Auxiliary Fault Status Register*/
-	MCR p15, 0, r6, c5, c1, 1
-	/* Data Fault Address Register */
-	MCR p15, 0, r7, c6, c0, 0
-	/* Instruction Fault Address Register*/
-	MCR p15, 0, r8, c6, c0, 2
-	ldmia	r3!,{r4-r7}
+	mov	sp, r4			@ Restore sp
+	msr	spsr_cxsf, r5		@ Restore spsr
+	mov	lr, r6			@ Restore lr
+
+	ldmia	r3!, {r4-r7}
+	mcr	p15, 0, r4, c1, c0, 2	@ Coprocessor access Control Register
+	mcr	p15, 0, r5, c2, c0, 0	@ TTBR0
+	mcr	p15, 0, r6, c2, c0, 1	@ TTBR1
+	mcr	p15, 0, r7, c2, c0, 2	@ TTBCR
+
+	ldmia	r3!,{r4-r6}
+	mcr	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
+	mcr	p15, 0, r5, c10, c2, 0	@ PRRR
+	mcr	p15, 0, r6, c10, c2, 1	@ NMRR
+
 
-	/* User r/w thread and process ID */
-	MCR p15, 0, r4, c13, c0, 2
-	/* User ro thread and process ID */
-	MCR p15, 0, r5, c13, c0, 3
-	/* Privileged only thread and process ID */
-	MCR p15, 0, r6, c13, c0, 4
-	/* Cache size selection */
-	MCR p15, 2, r7, c0, c0, 0
-	ldmia	r3!,{r4-r8}
-	/* Data TLB lockdown registers */
-	MCR p15, 0, r4, c10, c0, 0
-	/* Instruction TLB lockdown registers */
-	MCR p15, 0, r5, c10, c0, 1
-	/* Secure or Nonsecure Vector Base Address */
-	MCR p15, 0, r6, c12, c0, 0
-	/* FCSE PID */
-	MCR p15, 0, r7, c13, c0, 0
-	/* Context PID */
-	MCR p15, 0, r8, c13, c0, 1
-
-	ldmia	r3!,{r4-r5}
-	/* Primary memory remap register */
-	MCR p15, 0, r4, c10, c2, 0
-	/* Normal memory remap register */
-	MCR p15, 0, r5, c10, c2, 1
-
-	/* Restore cpsr */
-	ldmia	r3!,{r4}		@ load CPSR from SDRAM
-	msr	cpsr, r4		@ store cpsr
+	ldmia	r3!,{r4-r7}
+	mcr	p15, 0, r4, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
+	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
+	msr	cpsr, r7		@ store cpsr
 
 	/* Enabling MMU here */
 	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl
@@ -592,12 +561,17 @@ usettbr0:
 	ldr	r2, cache_pred_disable_mask
 	and	r4, r2
 	mcr	p15, 0, r4, c1, c0, 0
+	dsb
+	isb
+	ldr     r0, =restoremmu_on
+	bx      r0
 
 /*
  * ==============================
  * == Exit point from OFF mode ==
  * ==============================
  */
+restoremmu_on:
 	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
 
 
@@ -607,6 +581,7 @@ usettbr0:
 
 /* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
 	.text
+	.align	3
 ENTRY(es3_sdrc_fix)
 	ldr	r4, sdrc_syscfg		@ get config addr
 	ldr	r5, [r4]		@ get value
@@ -634,6 +609,7 @@ ENTRY(es3_sdrc_fix)
 	str	r5, [r4]		@ kick off refreshes
 	bx	lr
 
+	.align
 sdrc_syscfg:
 	.word	SDRC_SYSCONFIG_P
 sdrc_mr_0:
@@ -648,6 +624,7 @@ sdrc_emr2_1:
 	.word	SDRC_EMR2_1_P
 sdrc_manual_1:
 	.word	SDRC_MANUAL_1_P
+ENDPROC(es3_sdrc_fix)
 ENTRY(es3_sdrc_fix_sz)
 	.word	. - es3_sdrc_fix
 
@@ -682,6 +659,12 @@ wait_sdrc_ready:
 	bic	r5, r5, #0x40
 	str	r5, [r4]
 
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
 is_dll_in_lock_mode:
 	/* Is dll in lock mode? */
 	ldr	r4, sdrc_dlla_ctrl
@@ -689,10 +672,11 @@ is_dll_in_lock_mode:
 	tst	r5, #0x4
 	bxne	lr			@ Return if locked
 	/* wait till dll locks */
+	adr	r7, kick_counter
 wait_dll_lock_timed:
 	ldr	r4, wait_dll_lock_counter
 	add	r4, r4, #1
-	str	r4, wait_dll_lock_counter
+	str	r4, [r7, #wait_dll_lock_counter - kick_counter]
 	ldr	r4, sdrc_dlla_status
 	/* Wait 20uS for lock */
 	mov	r6, #8
@@ -718,9 +702,10 @@ kick_dll:
 	dsb
 	ldr	r4, kick_counter
 	add	r4, r4, #1
-	str	r4, kick_counter
+	str	r4, [r7]		@ kick_counter
 	b	wait_dll_lock_timed
 
+	.align
 cm_idlest1_core:
 	.word	CM_IDLEST1_CORE_V
 cm_idlest_ckgen:
@@ -763,6 +748,7 @@ kick_counter:
 	.word	0
 wait_dll_lock_counter:
 	.word	0
+ENDPROC(omap34xx_cpu_suspend)
 
 ENTRY(omap34xx_cpu_suspend_sz)
 	.word	. - omap34xx_cpu_suspend
diff --git a/arch/arm/mach-omap2/smartreflex-class3.c b/arch/arm/mach-omap2/smartreflex-class3.c
index 60e7055..f438cf4 100644
--- a/arch/arm/mach-omap2/smartreflex-class3.c
+++ b/arch/arm/mach-omap2/smartreflex-class3.c
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <plat/smartreflex.h>
+#include "smartreflex.h"
 
 static int sr_class3_enable(struct voltagedomain *voltdm)
 {
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 1a777e3..8f674c9 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -26,9 +26,9 @@
 #include <linux/pm_runtime.h>
 
 #include <plat/common.h>
-#include <plat/smartreflex.h>
 
 #include "pm.h"
+#include "smartreflex.h"
 
 #define SMARTREFLEX_NAME_LEN	16
 #define NVALUE_NAME_LEN		40
@@ -54,6 +54,7 @@ struct omap_sr {
 	struct list_head		node;
 	struct omap_sr_nvalue_table	*nvalue_table;
 	struct voltagedomain		*voltdm;
+	struct dentry			*dbg_dir;
 };
 
 /* sr_list contains all the instances of smartreflex module */
@@ -260,9 +261,11 @@ static int sr_late_init(struct omap_sr *sr_info)
 	if (sr_class->class_type == SR_CLASS2 &&
 		sr_class->notify_flags && sr_info->irq) {
 
-		name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
-		strcpy(name, "sr_");
-		strcat(name, sr_info->voltdm->name);
+		name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+		if (name == NULL) {
+			ret = -ENOMEM;
+			goto error;
+		}
 		ret = request_irq(sr_info->irq, sr_interrupt,
 				0, name, (void *)sr_info);
 		if (ret)
@@ -821,7 +824,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct resource *mem, *irq;
-	struct dentry *vdd_dbg_dir, *dbg_dir, *nvalue_dir;
+	struct dentry *vdd_dbg_dir, *nvalue_dir;
 	struct omap_volt_data *volt_data;
 	int i, ret = 0;
 
@@ -896,24 +899,24 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 		goto err_release_region;
 	}
 
-	dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
-	if (IS_ERR(dbg_dir)) {
+	sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+	if (IS_ERR(sr_info->dbg_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
 			__func__);
-		ret = PTR_ERR(dbg_dir);
+		ret = PTR_ERR(sr_info->dbg_dir);
 		goto err_release_region;
 	}
 
-	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir,
-				(void *)sr_info, &pm_sr_fops);
-	(void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir,
+	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
+			sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops);
+	(void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir,
 			&sr_info->err_weight);
-	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, dbg_dir,
+	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
 			&sr_info->err_maxlimit);
-	(void) debugfs_create_x32("errminlimit", S_IRUGO, dbg_dir,
+	(void) debugfs_create_x32("errminlimit", S_IRUGO, sr_info->dbg_dir,
 			&sr_info->err_minlimit);
 
-	nvalue_dir = debugfs_create_dir("nvalue", dbg_dir);
+	nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
 	if (IS_ERR(nvalue_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
 			"for n-values\n", __func__);
@@ -970,6 +973,8 @@ static int __devexit omap_sr_remove(struct platform_device *pdev)
 
 	if (sr_info->autocomp_active)
 		sr_stop_vddautocomp(sr_info);
+	if (sr_info->dbg_dir)
+		debugfs_remove_recursive(sr_info->dbg_dir);
 
 	list_del(&sr_info->node);
 	iounmap(sr_info->base);
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
new file mode 100644
index 0000000..5f35b9e
--- /dev/null
+++ b/arch/arm/mach-omap2/smartreflex.h
@@ -0,0 +1,246 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@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 __ASM_ARM_OMAP_SMARTREFLEX_H
+#define __ASM_ARM_OMAP_SMARTREFLEX_H
+
+#include <linux/platform_device.h>
+
+#include "voltage.h"
+
+/*
+ * Different Smartreflex IPs version. The v1 is the 65nm version used in
+ * OMAP3430. The v2 is the update for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+#define SR_TYPE_V1	1
+#define SR_TYPE_V2	2
+
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG		0x00
+#define SRSTATUS		0x04
+#define SENVAL			0x08
+#define SENMIN			0x0C
+#define SENMAX			0x10
+#define SENAVG			0x14
+#define AVGWEIGHT		0x18
+#define NVALUERECIPROCAL	0x1c
+#define SENERROR_V1		0x20
+#define ERRCONFIG_V1		0x24
+#define IRQ_EOI			0x20
+#define IRQSTATUS_RAW		0x24
+#define IRQSTATUS		0x28
+#define IRQENABLE_SET		0x2C
+#define IRQENABLE_CLR		0x30
+#define SENERROR_V2		0x34
+#define ERRCONFIG_V2		0x38
+
+/* Bit/Shift Positions */
+
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT	22
+#define SRCONFIG_SRCLKLENGTH_SHIFT	12
+#define SRCONFIG_SENNENABLE_V1_SHIFT	5
+#define SRCONFIG_SENPENABLE_V1_SHIFT	3
+#define SRCONFIG_SENNENABLE_V2_SHIFT	1
+#define SRCONFIG_SENPENABLE_V2_SHIFT	0
+#define SRCONFIG_CLKCTRL_SHIFT		0
+
+#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
+
+#define SRCONFIG_SRENABLE		BIT(11)
+#define SRCONFIG_SENENABLE		BIT(10)
+#define SRCONFIG_ERRGEN_EN		BIT(9)
+#define SRCONFIG_MINMAXAVG_EN		BIT(8)
+#define SRCONFIG_DELAYCTRL		BIT(2)
+
+/* AVGWEIGHT */
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
+
+/* NVALUERECIPROCAL */
+#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
+#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
+#define NVALUERECIPROCAL_RNSENP_SHIFT	8
+#define NVALUERECIPROCAL_RNSENN_SHIFT	0
+
+/* ERRCONFIG */
+#define ERRCONFIG_ERRWEIGHT_SHIFT	16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
+#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
+
+#define SR_ERRWEIGHT_MASK		(0x07 << 16)
+#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
+#define SR_ERRMINLIMIT_MASK		(0xff << 0)
+
+#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
+#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
+#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
+#define ERRCONFIG_MCUACCUMINTST		BIT(28)
+#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
+#define ERRCONFIG_MCUVALIDINTST		BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
+#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
+#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
+#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
+#define ERRCONFIG_MCUDISACKINTST	BIT(22)
+#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
+
+#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
+					ERRCONFIG_MCUACCUMINTST | \
+					ERRCONFIG_MCUVALIDINTST | \
+					ERRCONFIG_MCUBOUNDINTST | \
+					ERRCONFIG_MCUDISACKINTST)
+/* IRQSTATUS */
+#define IRQSTATUS_MCUACCUMINT		BIT(3)
+#define IRQSTATUS_MCVALIDINT		BIT(2)
+#define IRQSTATUS_MCBOUNDSINT		BIT(1)
+#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
+
+/* IRQENABLE_SET and IRQENABLE_CLEAR */
+#define IRQENABLE_MCUACCUMINT		BIT(3)
+#define IRQENABLE_MCUVALIDINT		BIT(2)
+#define IRQENABLE_MCUBOUNDSINT		BIT(1)
+#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
+
+/* Common Bit values */
+
+#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
+#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
+
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1f4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
+
+#define OMAP3430_SR_ERRWEIGHT		0x04
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/**
+ * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
+ *				pmic specific info to smartreflex driver
+ *
+ * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
+ */
+struct omap_sr_pmic_data {
+	void (*sr_pmic_init) (void);
+};
+
+#ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
+#define SR_CLASS1	0x1
+#define SR_CLASS2	0x2
+#define SR_CLASS3	0x3
+
+/**
+ * struct omap_sr_class_data - Smartreflex class driver info
+ *
+ * @enable:		API to enable a particular class smaartreflex.
+ * @disable:		API to disable a particular class smartreflex.
+ * @configure:		API to configure a particular class smartreflex.
+ * @notify:		API to notify the class driver about an event in SR.
+ *			Not needed for class3.
+ * @notify_flags:	specify the events to be notified to the class driver
+ * @class_type:		specify which smartreflex class.
+ *			Can be used by the SR driver to take any class
+ *			based decisions.
+ */
+struct omap_sr_class_data {
+	int (*enable)(struct voltagedomain *voltdm);
+	int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
+	int (*configure)(struct voltagedomain *voltdm);
+	int (*notify)(struct voltagedomain *voltdm, u32 status);
+	u8 notify_flags;
+	u8 class_type;
+};
+
+/**
+ * struct omap_sr_nvalue_table	- Smartreflex n-target value info
+ *
+ * @efuse_offs:	The offset of the efuse where n-target values are stored.
+ * @nvalue:	The n-target value.
+ */
+struct omap_sr_nvalue_table {
+	u32 efuse_offs;
+	u32 nvalue;
+};
+
+/**
+ * struct omap_sr_data - Smartreflex platform data.
+ *
+ * @ip_type:		Smartreflex IP type.
+ * @senp_mod:		SENPENABLE value for the sr
+ * @senn_mod:		SENNENABLE value for sr
+ * @nvalue_count:	Number of distinct nvalues in the nvalue table
+ * @enable_on_init:	whether this sr module needs to enabled at
+ *			boot up or not.
+ * @nvalue_table:	table containing the  efuse offsets and nvalues
+ *			corresponding to them.
+ * @voltdm:		Pointer to the voltage domain associated with the SR
+ */
+struct omap_sr_data {
+	int				ip_type;
+	u32				senp_mod;
+	u32				senn_mod;
+	int				nvalue_count;
+	bool				enable_on_init;
+	struct omap_sr_nvalue_table	*nvalue_table;
+	struct voltagedomain		*voltdm;
+};
+
+/* Smartreflex module enable/disable interface */
+void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_disable(struct voltagedomain *voltdm);
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+
+/* API to register the pmic specific data with the smartreflex driver. */
+void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
+
+/* Smartreflex driver hooks to be called from Smartreflex class driver */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+void sr_disable(struct voltagedomain *voltdm);
+int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_configure_minmax(struct voltagedomain *voltdm);
+
+/* API to register the smartreflex class driver with the smartreflex driver */
+int sr_register_class(struct omap_sr_class_data *class_data);
+#else
+static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable_reset_volt(
+		struct voltagedomain *voltdm) {}
+static inline void omap_sr_register_pmic(
+		struct omap_sr_pmic_data *pmic_data) {}
+#endif
+#endif
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index b1e0af1..10d3c5e 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -23,9 +23,9 @@
 #include <linux/io.h>
 
 #include <plat/omap_device.h>
-#include <plat/smartreflex.h>
-#include <plat/voltage.h>
 
+#include "smartreflex.h"
+#include "voltage.h"
 #include "control.h"
 #include "pm.h"
 
diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S
index 055310c..ff9b9db 100644
--- a/arch/arm/mach-omap2/sram242x.S
+++ b/arch/arm/mach-omap2/sram242x.S
@@ -39,6 +39,7 @@
 
 	.text
 
+	.align	3
 ENTRY(omap242x_sram_ddr_init)
 	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
 
@@ -143,6 +144,7 @@ ENTRY(omap242x_sram_ddr_init_sz)
  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
  */
+	.align	3
 ENTRY(omap242x_sram_reprogram_sdrc)
 	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
 	mov	r3, #0x0		@ clear for mrc call
@@ -238,6 +240,7 @@ ENTRY(omap242x_sram_reprogram_sdrc_sz)
 /*
  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
  */
+	.align	3
 ENTRY(omap242x_sram_set_prcm)
 	stmfd	sp!, {r0-r12, lr}	@ regs to stack
 	adr	r4, pbegin		@ addr of preload start
diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S
index f900758..7673020 100644
--- a/arch/arm/mach-omap2/sram243x.S
+++ b/arch/arm/mach-omap2/sram243x.S
@@ -39,6 +39,7 @@
 
 	.text
 
+	.align	3
 ENTRY(omap243x_sram_ddr_init)
 	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
 
@@ -143,6 +144,7 @@ ENTRY(omap243x_sram_ddr_init_sz)
  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
  */
+	.align	3
 ENTRY(omap243x_sram_reprogram_sdrc)
 	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
 	mov	r3, #0x0		@ clear for mrc call
@@ -238,6 +240,7 @@ ENTRY(omap243x_sram_reprogram_sdrc_sz)
 /*
  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
  */
+	.align	3
 ENTRY(omap243x_sram_set_prcm)
 	stmfd	sp!, {r0-r12, lr}	@ regs to stack
 	adr	r4, pbegin		@ addr of preload start
diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S
index 7f893a2..6f5849a 100644
--- a/arch/arm/mach-omap2/sram34xx.S
+++ b/arch/arm/mach-omap2/sram34xx.S
@@ -34,6 +34,12 @@
 #include "sdrc.h"
 #include "cm2xxx_3xxx.h"
 
+/*
+ * This file needs be built unconditionally as ARM to interoperate correctly
+ * with non-Thumb-2-capable firmware.
+ */
+	.arm
+
 	.text
 
 /* r1 parameters */
@@ -111,29 +117,42 @@
  * since it will cause the ARM MMU to attempt to walk the page tables.
  * These crashes may be intermittent.
  */
+	.align	3
 ENTRY(omap3_sram_configure_core_dpll)
 	stmfd	sp!, {r1-r12, lr}	@ store regs to stack
 
 					@ pull the extra args off the stack
 					@  and store them in SRAM
+
+/*
+ * PC-relative stores are deprecated in ARMv7 and lead to undefined behaviour
+ * in Thumb-2: use a r7 as a base instead.
+ * Be careful not to clobber r7 when maintaing this file.
+ */
+ THUMB(	adr	r7, omap3_sram_configure_core_dpll			)
+	.macro strtext Rt:req, label:req
+ ARM(	str	\Rt, \label						)
+ THUMB(	str	\Rt, [r7, \label - omap3_sram_configure_core_dpll]	)
+	.endm
+
 	ldr	r4, [sp, #52]
-	str     r4, omap_sdrc_rfr_ctrl_0_val
+	strtext	r4, omap_sdrc_rfr_ctrl_0_val
 	ldr	r4, [sp, #56]
-	str     r4, omap_sdrc_actim_ctrl_a_0_val
+	strtext	r4, omap_sdrc_actim_ctrl_a_0_val
 	ldr	r4, [sp, #60]
-	str     r4, omap_sdrc_actim_ctrl_b_0_val
+	strtext	r4, omap_sdrc_actim_ctrl_b_0_val
 	ldr	r4, [sp, #64]
-	str     r4, omap_sdrc_mr_0_val
+	strtext	r4, omap_sdrc_mr_0_val
 	ldr	r4, [sp, #68]
-	str     r4, omap_sdrc_rfr_ctrl_1_val
+	strtext	r4, omap_sdrc_rfr_ctrl_1_val
 	cmp	r4, #0			@ if SDRC_RFR_CTRL_1 is 0,
 	beq	skip_cs1_params		@  do not use cs1 params
 	ldr	r4, [sp, #72]
-	str     r4, omap_sdrc_actim_ctrl_a_1_val
+	strtext	r4, omap_sdrc_actim_ctrl_a_1_val
 	ldr	r4, [sp, #76]
-	str     r4, omap_sdrc_actim_ctrl_b_1_val
+	strtext	r4, omap_sdrc_actim_ctrl_b_1_val
 	ldr	r4, [sp, #80]
-	str     r4, omap_sdrc_mr_1_val
+	strtext	r4, omap_sdrc_mr_1_val
 skip_cs1_params:
 	mrc	p15, 0, r8, c1, c0, 0	@ read ctrl register
 	bic	r10, r8, #0x800		@ clear Z-bit, disable branch prediction
@@ -271,6 +290,7 @@ skip_cs1_prog:
 	ldr	r12, [r11]		@ posted-write barrier for SDRC
 	bx	lr
 
+	.align
 omap3_sdrc_power:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_POWER)
 omap3_cm_clksel1_pll:
@@ -319,6 +339,7 @@ omap3_sdrc_dlla_ctrl:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 core_m2_mask_val:
 	.word 0x07FFFFFF
+ENDPROC(omap3_sram_configure_core_dpll)
 
 ENTRY(omap3_sram_configure_core_dpll_sz)
 	.word	. - omap3_sram_configure_core_dpll
diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c
index 0fc550e..3b9cf85 100644
--- a/arch/arm/mach-omap2/timer-gp.c
+++ b/arch/arm/mach-omap2/timer-gp.c
@@ -40,10 +40,11 @@
 #include <plat/dmtimer.h>
 #include <asm/localtimer.h>
 #include <asm/sched_clock.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
 
 #include "timer-gp.h"
 
-#include <plat/common.h>
 
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
@@ -133,9 +134,13 @@ static void __init omap2_gp_clockevent_init(void)
 {
 	u32 tick_rate;
 	int src;
+	char clockevent_hwmod_name[8]; /* 8 = sizeof("timerXX0") */
 
 	inited = 1;
 
+	sprintf(clockevent_hwmod_name, "timer%d", gptimer_id);
+	omap_hwmod_setup_one(clockevent_hwmod_name);
+
 	gptimer = omap_dm_timer_request_specific(gptimer_id);
 	BUG_ON(gptimer == NULL);
 	gptimer_wakeup = gptimer;
diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
deleted file mode 100644
index 25eeada..0000000
--- a/arch/arm/mach-omap2/usb-ehci.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/usb-ehci.c
- *
- * This file will contain the board specific details for the
- * Synopsys EHCI host controller on OMAP3430
- *
- * Copyright (C) 2007 Texas Instruments
- * Author: Vikram Pandita <vikram.pandita@ti.com>
- *
- * Generalization by:
- * 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/io.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <plat/usb.h>
-
-#include "mux.h"
-
-#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
-
-static struct resource ehci_resources[] = {
-	{
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.flags	= IORESOURCE_MEM,
-	},
-	{         /* general IRQ */
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-static u64 ehci_dmamask = ~(u32)0;
-static struct platform_device ehci_device = {
-	.name           = "ehci-omap",
-	.id             = 0,
-	.dev = {
-		.dma_mask               = &ehci_dmamask,
-		.coherent_dma_mask      = 0xffffffff,
-		.platform_data          = NULL,
-	},
-	.num_resources  = ARRAY_SIZE(ehci_resources),
-	.resource       = ehci_resources,
-};
-
-/* MUX settings for EHCI pins */
-/*
- * setup_ehci_io_mux - initialize IO pad mux for USBHOST
- */
-static void setup_ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("hsusb1_stp", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb1_clk", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb1_dir", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_nxt", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data0", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data1", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data2", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data3", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data4", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data5", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data6", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data7", OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("hsusb1_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb1_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	switch (port_mode[1]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("hsusb2_stp", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb2_clk", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb2_dir", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_nxt", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("hsusb2_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb2_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	switch (port_mode[2]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		printk(KERN_WARNING "Port3 can't be used in PHY mode\n");
-		break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("hsusb3_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb3_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	return;
-}
-
-static void setup_4430ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("usbb1_ulpiphy_stp",
-			OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("usbb1_ulpiphy_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("usbb1_ulpitll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("usbb1_ulpitll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-	default:
-			break;
-	}
-	switch (port_mode[1]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("usbb2_ulpiphy_stp",
-			OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("usbb2_ulpiphy_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("usbb2_ulpitll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("usbb2_ulpitll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-	default:
-			break;
-	}
-}
-
-void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
-{
-	platform_device_add_data(&ehci_device, pdata, sizeof(*pdata));
-
-	/* Setup Pin IO MUX for EHCI */
-	if (cpu_is_omap34xx()) {
-		ehci_resources[0].start	= OMAP34XX_EHCI_BASE;
-		ehci_resources[0].end	= OMAP34XX_EHCI_BASE + SZ_1K - 1;
-		ehci_resources[1].start	= OMAP34XX_UHH_CONFIG_BASE;
-		ehci_resources[1].end	= OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
-		ehci_resources[2].start	= OMAP34XX_USBTLL_BASE;
-		ehci_resources[2].end	= OMAP34XX_USBTLL_BASE + SZ_4K - 1;
-		ehci_resources[3].start = INT_34XX_EHCI_IRQ;
-		setup_ehci_io_mux(pdata->port_mode);
-	} else if (cpu_is_omap44xx()) {
-		ehci_resources[0].start	= OMAP44XX_HSUSB_EHCI_BASE;
-		ehci_resources[0].end	= OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
-		ehci_resources[1].start	= OMAP44XX_UHH_CONFIG_BASE;
-		ehci_resources[1].end	= OMAP44XX_UHH_CONFIG_BASE + SZ_2K - 1;
-		ehci_resources[2].start	= OMAP44XX_USBTLL_BASE;
-		ehci_resources[2].end	= OMAP44XX_USBTLL_BASE + SZ_4K - 1;
-		ehci_resources[3].start = OMAP44XX_IRQ_EHCI;
-		setup_4430ehci_io_mux(pdata->port_mode);
-	}
-
-	if (platform_device_register(&ehci_device) < 0) {
-		printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
-		return;
-	}
-}
-
-#else
-
-void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
-
-{
-}
-
-#endif /* CONFIG_USB_EHCI_HCD */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-
-static struct resource ohci_resources[] = {
-	{
-		.start	= OMAP34XX_OHCI_BASE,
-		.end	= OMAP34XX_OHCI_BASE + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= OMAP34XX_UHH_CONFIG_BASE,
-		.end	= OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= OMAP34XX_USBTLL_BASE,
-		.end	= OMAP34XX_USBTLL_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{	/* general IRQ */
-		.start	= INT_34XX_OHCI_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device ohci_device = {
-	.name		= "ohci-omap3",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &ohci_dmamask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(ohci_resources),
-	.resource	= ohci_resources,
-};
-
-static void setup_ohci_io_mux(const enum ohci_omap3_port_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm1_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm1_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm1_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm1_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm1_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm1_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	switch (port_mode[1]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm2_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm2_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm2_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm2_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm2_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm2_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	switch (port_mode[2]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm3_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm3_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm3_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm3_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm3_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm3_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-}
-
-void __init usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata)
-{
-	platform_device_add_data(&ohci_device, pdata, sizeof(*pdata));
-
-	/* Setup Pin IO MUX for OHCI */
-	if (cpu_is_omap34xx())
-		setup_ohci_io_mux(pdata->port_mode);
-
-	if (platform_device_register(&ohci_device) < 0) {
-		pr_err("Unable to register FS-USB (OHCI) device\n");
-		return;
-	}
-}
-
-#else
-
-void __init usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata)
-{
-}
-
-#endif /* CONFIG_USB_OHCI_HCD */
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
new file mode 100644
index 0000000..89ae298
--- /dev/null
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -0,0 +1,574 @@
+/*
+ * usb-host.c - OMAP USB Host
+ *
+ * This file will contain the board specific details for the
+ * Synopsys EHCI/OHCI host controller on OMAP3430 and onwards
+ *
+ * Copyright (C) 2007-2011 Texas Instruments
+ * Author: Vikram Pandita <vikram.pandita@ti.com>
+ * Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ *
+ * Generalization by:
+ * Felipe Balbi <balbi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <plat/usb.h>
+
+#include "mux.h"
+
+#ifdef CONFIG_MFD_OMAP_USB_HOST
+
+#define OMAP_USBHS_DEVICE	"usbhs-omap"
+
+static struct resource usbhs_resources[] = {
+	{
+		.name	= "uhh",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "tll",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "ehci",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "ehci-irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "ohci",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "ohci-irq",
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device usbhs_device = {
+	.name		= OMAP_USBHS_DEVICE,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(usbhs_resources),
+	.resource	= usbhs_resources,
+};
+
+static struct usbhs_omap_platform_data		usbhs_data;
+static struct ehci_hcd_omap_platform_data	ehci_data;
+static struct ohci_hcd_omap_platform_data	ohci_data;
+
+/* MUX settings for EHCI pins */
+/*
+ * setup_ehci_io_mux - initialize IO pad mux for USBHOST
+ */
+static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("hsusb1_stp", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb1_clk", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb1_dir", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_nxt", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data0", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data1", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data2", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data3", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data4", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data5", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data6", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data7", OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("hsusb1_tll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("hsusb1_tll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	switch (port_mode[1]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("hsusb2_stp", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb2_clk", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb2_dir", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_nxt", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("hsusb2_tll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("hsusb2_tll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	switch (port_mode[2]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		printk(KERN_WARNING "Port3 can't be used in PHY mode\n");
+		break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("hsusb3_tll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("hsusb3_tll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	return;
+}
+
+static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("usbb1_ulpiphy_stp",
+			OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("usbb1_ulpiphy_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("usbb1_ulpitll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("usbb1_ulpitll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+			break;
+	}
+	switch (port_mode[1]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("usbb2_ulpiphy_stp",
+			OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("usbb2_ulpiphy_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("usbb2_ulpitll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("usbb2_ulpitll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+			break;
+	}
+}
+
+static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("mm1_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm1_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("mm1_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("mm1_txen_n", OMAP_PIN_OUTPUT);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("mm1_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm1_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+	switch (port_mode[1]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("mm2_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm2_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("mm2_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("mm2_txen_n", OMAP_PIN_OUTPUT);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("mm2_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm2_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+	switch (port_mode[2]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("mm3_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm3_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("mm3_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("mm3_txen_n", OMAP_PIN_OUTPUT);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("mm3_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm3_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+}
+
+static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("usbb1_mm_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_mm_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("usbb1_mm_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("usbb1_mm_txen",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("usbb1_mm_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_mm_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+		break;
+	}
+
+	switch (port_mode[1]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("usbb2_mm_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_mm_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("usbb2_mm_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("usbb2_mm_txen",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("usbb2_mm_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_mm_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+		break;
+	}
+}
+
+void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
+{
+	int	i;
+
+	for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
+		usbhs_data.port_mode[i] = pdata->port_mode[i];
+		ohci_data.port_mode[i] = pdata->port_mode[i];
+		ehci_data.port_mode[i] = pdata->port_mode[i];
+		ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
+		ehci_data.regulator[i] = pdata->regulator[i];
+	}
+	ehci_data.phy_reset = pdata->phy_reset;
+	ohci_data.es2_compatibility = pdata->es2_compatibility;
+	usbhs_data.ehci_data = &ehci_data;
+	usbhs_data.ohci_data = &ohci_data;
+
+	if (cpu_is_omap34xx()) {
+		usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE;
+		usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
+		usbhs_resources[1].start = OMAP34XX_USBTLL_BASE;
+		usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1;
+		usbhs_resources[2].start	= OMAP34XX_EHCI_BASE;
+		usbhs_resources[2].end	= OMAP34XX_EHCI_BASE + SZ_1K - 1;
+		usbhs_resources[3].start = INT_34XX_EHCI_IRQ;
+		usbhs_resources[4].start	= OMAP34XX_OHCI_BASE;
+		usbhs_resources[4].end	= OMAP34XX_OHCI_BASE + SZ_1K - 1;
+		usbhs_resources[5].start = INT_34XX_OHCI_IRQ;
+		setup_ehci_io_mux(pdata->port_mode);
+		setup_ohci_io_mux(pdata->port_mode);
+	} else if (cpu_is_omap44xx()) {
+		usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE;
+		usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1;
+		usbhs_resources[1].start = OMAP44XX_USBTLL_BASE;
+		usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1;
+		usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE;
+		usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
+		usbhs_resources[3].start = OMAP44XX_IRQ_EHCI;
+		usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE;
+		usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1;
+		usbhs_resources[5].start = OMAP44XX_IRQ_OHCI;
+		setup_4430ehci_io_mux(pdata->port_mode);
+		setup_4430ohci_io_mux(pdata->port_mode);
+	}
+
+	if (platform_device_add_data(&usbhs_device,
+				&usbhs_data, sizeof(usbhs_data)) < 0) {
+		printk(KERN_ERR "USBHS platform_device_add_data failed\n");
+		goto init_end;
+	}
+
+	if (platform_device_register(&usbhs_device) < 0)
+		printk(KERN_ERR "USBHS platform_device_register failed\n");
+
+init_end:
+	return;
+}
+
+#else
+
+void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
+{
+}
+
+#endif
+
+
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 5298949..35559f7 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -30,118 +30,11 @@
 #include <mach/irqs.h>
 #include <mach/am35xx.h>
 #include <plat/usb.h>
-#include "control.h"
+#include <plat/omap_device.h>
+#include "mux.h"
 
 #if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
 
-static void am35x_musb_reset(void)
-{
-	u32	regval;
-
-	/* Reset the musb interface */
-	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-
-	regval |= AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
-
-	regval &= ~AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
-
-	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-}
-
-static void am35x_musb_phy_power(u8 on)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-	u32 devconf2;
-
-	if (on) {
-		/*
-		 * Start the on-chip PHY and its PLL.
-		 */
-		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
-		devconf2 |= CONF2_PHY_PLLON;
-
-		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-
-		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
-		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
-				& CONF2_PHYCLKGD)) {
-			cpu_relax();
-
-			if (time_after(jiffies, timeout)) {
-				pr_err(KERN_ERR "musb PHY clock good timed out\n");
-				break;
-			}
-		}
-	} else {
-		/*
-		 * Power down the on-chip PHY.
-		 */
-		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-		devconf2 &= ~CONF2_PHY_PLLON;
-		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
-		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-	}
-}
-
-static void am35x_musb_clear_irq(void)
-{
-	u32 regval;
-
-	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-	regval |= AM35XX_USBOTGSS_INT_CLR;
-	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
-	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-}
-
-static void am35x_musb_set_mode(u8 musb_mode)
-{
-	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-	devconf2 &= ~CONF2_OTGMODE;
-	switch (musb_mode) {
-#ifdef	CONFIG_USB_MUSB_HDRC_HCD
-	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
-		devconf2 |= CONF2_FORCE_HOST;
-		break;
-#endif
-#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
-	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
-		devconf2 |= CONF2_FORCE_DEVICE;
-		break;
-#endif
-#ifdef	CONFIG_USB_MUSB_OTG
-	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
-		devconf2 |= CONF2_NO_OVERRIDE;
-		break;
-#endif
-	default:
-		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
-	}
-
-	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-}
-
-static struct resource musb_resources[] = {
-	[0] = { /* start and end set dynamically */
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {	/* general IRQ */
-		.start	= INT_243X_HS_USB_MC,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "mc",
-	},
-	[2] = {	/* DMA IRQ */
-		.start	= INT_243X_HS_USB_DMA,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "dma",
-	},
-};
-
 static struct musb_hdrc_config musb_config = {
 	.multipoint	= 1,
 	.dyn_fifo	= 1,
@@ -169,38 +62,65 @@ static struct musb_hdrc_platform_data musb_plat = {
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static struct platform_device musb_device = {
-	.name		= "musb-omap2430",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &musb_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= &musb_plat,
+static struct omap_device_pm_latency omap_musb_latency[] = {
+	{
+		.deactivate_func	= omap_device_idle_hwmods,
+		.activate_func		= omap_device_enable_hwmods,
+		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
-	.num_resources	= ARRAY_SIZE(musb_resources),
-	.resource	= musb_resources,
 };
 
+static void usb_musb_mux_init(struct omap_musb_board_data *board_data)
+{
+	switch (board_data->interface_type) {
+	case MUSB_INTERFACE_UTMI:
+		omap_mux_init_signal("usba0_otg_dp", OMAP_PIN_INPUT);
+		omap_mux_init_signal("usba0_otg_dm", OMAP_PIN_INPUT);
+		break;
+	case MUSB_INTERFACE_ULPI:
+		omap_mux_init_signal("usba0_ulpiphy_clk",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_stp",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dir",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_nxt",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat0",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat1",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat2",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat3",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat4",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat5",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat6",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat7",
+						OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	default:
+		break;
+	}
+}
+
 void __init usb_musb_init(struct omap_musb_board_data *board_data)
 {
-	if (cpu_is_omap243x()) {
-		musb_resources[0].start = OMAP243X_HS_BASE;
-	} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
-		musb_device.name = "musb-am35x";
-		musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
-		musb_resources[1].start = INT_35XX_USBOTG_IRQ;
-		board_data->set_phy_power = am35x_musb_phy_power;
-		board_data->clear_irq = am35x_musb_clear_irq;
-		board_data->set_mode = am35x_musb_set_mode;
-		board_data->reset = am35x_musb_reset;
-	} else if (cpu_is_omap34xx()) {
-		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
+	struct omap_hwmod		*oh;
+	struct omap_device		*od;
+	struct platform_device		*pdev;
+	struct device			*dev;
+	int				bus_id = -1;
+	const char			*oh_name, *name;
+
+	if (cpu_is_omap3517() || cpu_is_omap3505()) {
 	} else if (cpu_is_omap44xx()) {
-		musb_resources[0].start = OMAP44XX_HSUSB_OTG_BASE;
-		musb_resources[1].start = OMAP44XX_IRQ_HS_USB_MC_N;
-		musb_resources[2].start = OMAP44XX_IRQ_HS_USB_DMA_N;
+		usb_musb_mux_init(board_data);
 	}
-	musb_resources[0].end = musb_resources[0].start + SZ_4K - 1;
 
 	/*
 	 * REVISIT: This line can be removed once all the platforms using
@@ -212,8 +132,38 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data)
 	musb_plat.mode = board_data->mode;
 	musb_plat.extvbus = board_data->extvbus;
 
-	if (platform_device_register(&musb_device) < 0)
-		printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
+	if (cpu_is_omap44xx())
+		omap4430_phy_init(dev);
+
+	if (cpu_is_omap3517() || cpu_is_omap3505()) {
+		oh_name = "am35x_otg_hs";
+		name = "musb-am35x";
+	} else {
+		oh_name = "usb_otg_hs";
+		name = "musb-omap2430";
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return;
+	}
+
+	od = omap_device_build(name, bus_id, oh, &musb_plat,
+			       sizeof(musb_plat), omap_musb_latency,
+			       ARRAY_SIZE(omap_musb_latency), false);
+	if (IS_ERR(od)) {
+		pr_err("Could not build omap_device for %s %s\n",
+						name, oh_name);
+		return;
+	}
+
+	pdev = &od->pdev;
+	dev = &pdev->dev;
+	get_device(dev);
+	dev->dma_mask = &musb_dmamask;
+	dev->coherent_dma_mask = musb_dmamask;
+	put_device(dev);
 }
 
 #else
diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
new file mode 100644
index 0000000..e776777
--- /dev/null
+++ b/arch/arm/mach-omap2/vc.h
@@ -0,0 +1,83 @@
+/*
+ * OMAP3/4 Voltage Controller (VC) structure and macro definitions
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_VC_H
+#define __ARCH_ARM_MACH_OMAP2_VC_H
+
+#include <linux/kernel.h>
+
+/**
+ * struct omap_vc_common_data - per-VC register/bitfield data
+ * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
+ * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
+ * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
+ * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
+ * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
+ * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
+ * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
+ * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register
+ * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
+ *
+ * XXX One of cmd_on_mask and cmd_on_shift are not needed
+ * XXX VALID should probably be a shift, not a mask
+ */
+struct omap_vc_common_data {
+	u32 cmd_on_mask;
+	u32 valid;
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 bypass_val_reg;
+	u8 data_shift;
+	u8 slaveaddr_shift;
+	u8 regaddr_shift;
+	u8 cmd_on_shift;
+	u8 cmd_onlp_shift;
+	u8 cmd_ret_shift;
+	u8 cmd_off_shift;
+};
+
+/**
+ * struct omap_vc_instance_data - VC per-instance data
+ * @vc_common: pointer to VC common data for this platform
+ * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register
+ * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register
+ *
+ * XXX It is not necessary to have both a *_mask and a *_shift -
+ *     remove one
+ */
+struct omap_vc_instance_data {
+	const struct omap_vc_common_data *vc_common;
+	u32 smps_sa_mask;
+	u32 smps_volra_mask;
+	u8 cmdval_reg;
+	u8 smps_sa_shift;
+	u8 smps_volra_shift;
+};
+
+extern struct omap_vc_instance_data omap3_vc1_data;
+extern struct omap_vc_instance_data omap3_vc2_data;
+
+extern struct omap_vc_instance_data omap4_vc_mpu_data;
+extern struct omap_vc_instance_data omap4_vc_iva_data;
+extern struct omap_vc_instance_data omap4_vc_core_data;
+
+#endif
+
diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
new file mode 100644
index 0000000..f37dc4b
--- /dev/null
+++ b/arch/arm/mach-omap2/vc3xxx_data.c
@@ -0,0 +1,63 @@
+/*
+ * OMAP3 Voltage Controller (VC) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#include "vc.h"
+
+/*
+ * VC data common to 34xx/36xx chips
+ * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
+ */
+static struct omap_vc_common_data omap3_vc_common = {
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.bypass_val_reg	 = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
+	.data_shift	 = OMAP3430_DATA_SHIFT,
+	.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
+	.regaddr_shift	 = OMAP3430_REGADDR_SHIFT,
+	.valid		 = OMAP3430_VALID_MASK,
+	.cmd_on_shift	 = OMAP3430_VC_CMD_ON_SHIFT,
+	.cmd_on_mask	 = OMAP3430_VC_CMD_ON_MASK,
+	.cmd_onlp_shift	 = OMAP3430_VC_CMD_ONLP_SHIFT,
+	.cmd_ret_shift	 = OMAP3430_VC_CMD_RET_SHIFT,
+	.cmd_off_shift	 = OMAP3430_VC_CMD_OFF_SHIFT,
+};
+
+struct omap_vc_instance_data omap3_vc1_data = {
+	.vc_common = &omap3_vc_common,
+	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
+	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
+	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
+	.smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
+	.smps_volra_mask = OMAP3430_VOLRA0_MASK,
+};
+
+struct omap_vc_instance_data omap3_vc2_data = {
+	.vc_common = &omap3_vc_common,
+	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
+	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
+	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
+	.smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
+	.smps_volra_mask = OMAP3430_VOLRA1_MASK,
+};
diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
new file mode 100644
index 0000000..a98da8d
--- /dev/null
+++ b/arch/arm/mach-omap2/vc44xx_data.c
@@ -0,0 +1,75 @@
+/*
+ * OMAP4 Voltage Controller (VC) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "voltage.h"
+
+#include "vc.h"
+
+/*
+ * VC data common to 44xx chips
+ * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
+ */
+static const struct omap_vc_common_data omap4_vc_common = {
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
+	.data_shift = OMAP4430_DATA_SHIFT,
+	.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
+	.regaddr_shift = OMAP4430_REGADDR_SHIFT,
+	.valid = OMAP4430_VALID_MASK,
+	.cmd_on_shift = OMAP4430_ON_SHIFT,
+	.cmd_on_mask = OMAP4430_ON_MASK,
+	.cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
+	.cmd_ret_shift = OMAP4430_RET_SHIFT,
+	.cmd_off_shift = OMAP4430_OFF_SHIFT,
+};
+
+/* VC instance data for each controllable voltage line */
+struct omap_vc_instance_data omap4_vc_mpu_data = {
+	.vc_common = &omap4_vc_common,
+	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
+	.smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
+	.smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
+	.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
+	.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
+};
+
+struct omap_vc_instance_data omap4_vc_iva_data = {
+	.vc_common = &omap4_vc_common,
+	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
+	.smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
+	.smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
+	.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
+	.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
+};
+
+struct omap_vc_instance_data omap4_vc_core_data = {
+	.vc_common = &omap4_vc_common,
+	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
+	.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
+	.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
+	.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
+	.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
+};
+
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
index 12be525..c6facf7 100644
--- a/arch/arm/mach-omap2/voltage.c
+++ b/arch/arm/mach-omap2/voltage.c
@@ -7,8 +7,9 @@
  * Rajendra Nayak <rnayak@ti.com>
  * Lesly A M <x0080970@ti.com>
  *
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008, 2011 Nokia Corporation
  * Kalle Jokiniemi
+ * Paul Walmsley
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
  * Thara Gopinath <thara@ti.com>
@@ -26,7 +27,6 @@
 #include <linux/slab.h>
 
 #include <plat/common.h>
-#include <plat/voltage.h>
 
 #include "prm-regbits-34xx.h"
 #include "prm-regbits-44xx.h"
@@ -35,284 +35,30 @@
 #include "prminst44xx.h"
 #include "control.h"
 
-#define VP_IDLE_TIMEOUT		200
-#define VP_TRANXDONE_TIMEOUT	300
+#include "voltage.h"
+
+#include "vc.h"
+#include "vp.h"
+
 #define VOLTAGE_DIR_SIZE	16
 
-/* Voltage processor register offsets */
-struct vp_reg_offs {
-	u8 vpconfig;
-	u8 vstepmin;
-	u8 vstepmax;
-	u8 vlimitto;
-	u8 vstatus;
-	u8 voltage;
-};
-
-/* Voltage Processor bit field values, shifts and masks */
-struct vp_reg_val {
-	/* PRM module */
-	u16 prm_mod;
-	/* VPx_VPCONFIG */
-	u32 vpconfig_erroroffset;
-	u16 vpconfig_errorgain;
-	u32 vpconfig_errorgain_mask;
-	u8 vpconfig_errorgain_shift;
-	u32 vpconfig_initvoltage_mask;
-	u8 vpconfig_initvoltage_shift;
-	u32 vpconfig_timeouten;
-	u32 vpconfig_initvdd;
-	u32 vpconfig_forceupdate;
-	u32 vpconfig_vpenable;
-	/* VPx_VSTEPMIN */
-	u8 vstepmin_stepmin;
-	u16 vstepmin_smpswaittimemin;
-	u8 vstepmin_stepmin_shift;
-	u8 vstepmin_smpswaittimemin_shift;
-	/* VPx_VSTEPMAX */
-	u8 vstepmax_stepmax;
-	u16 vstepmax_smpswaittimemax;
-	u8 vstepmax_stepmax_shift;
-	u8 vstepmax_smpswaittimemax_shift;
-	/* VPx_VLIMITTO */
-	u8 vlimitto_vddmin;
-	u8 vlimitto_vddmax;
-	u16 vlimitto_timeout;
-	u8 vlimitto_vddmin_shift;
-	u8 vlimitto_vddmax_shift;
-	u8 vlimitto_timeout_shift;
-	/* PRM_IRQSTATUS*/
-	u32 tranxdone_status;
-};
-
-/* Voltage controller registers and offsets */
-struct vc_reg_info {
-	/* PRM module */
-	u16 prm_mod;
-	/* VC register offsets */
-	u8 smps_sa_reg;
-	u8 smps_volra_reg;
-	u8 bypass_val_reg;
-	u8 cmdval_reg;
-	u8 voltsetup_reg;
-	/*VC_SMPS_SA*/
-	u8 smps_sa_shift;
-	u32 smps_sa_mask;
-	/* VC_SMPS_VOL_RA */
-	u8 smps_volra_shift;
-	u32 smps_volra_mask;
-	/* VC_BYPASS_VAL */
-	u8 data_shift;
-	u8 slaveaddr_shift;
-	u8 regaddr_shift;
-	u32 valid;
-	/* VC_CMD_VAL */
-	u8 cmd_on_shift;
-	u8 cmd_onlp_shift;
-	u8 cmd_ret_shift;
-	u8 cmd_off_shift;
-	u32 cmd_on_mask;
-	/* PRM_VOLTSETUP */
-	u8 voltsetup_shift;
-	u32 voltsetup_mask;
-};
 
-/**
- * omap_vdd_info - Per Voltage Domain info
- *
- * @volt_data		: voltage table having the distinct voltages supported
- *			  by the domain and other associated per voltage data.
- * @pmic_info		: pmic specific parameters which should be populted by
- *			  the pmic drivers.
- * @vp_offs		: structure containing the offsets for various
- *			  vp registers
- * @vp_reg		: the register values, shifts, masks for various
- *			  vp registers
- * @vc_reg		: structure containing various various vc registers,
- *			  shifts, masks etc.
- * @voltdm		: pointer to the voltage domain structure
- * @debug_dir		: debug directory for this voltage domain.
- * @curr_volt		: current voltage for this vdd.
- * @ocp_mod		: The prm module for accessing the prm irqstatus reg.
- * @prm_irqst_reg	: prm irqstatus register.
- * @vp_enabled		: flag to keep track of whether vp is enabled or not
- * @volt_scale		: API to scale the voltage of the vdd.
- */
-struct omap_vdd_info {
-	struct omap_volt_data *volt_data;
-	struct omap_volt_pmic_info *pmic_info;
-	struct vp_reg_offs vp_offs;
-	struct vp_reg_val vp_reg;
-	struct vc_reg_info vc_reg;
-	struct voltagedomain voltdm;
-	struct dentry *debug_dir;
-	u32 curr_volt;
-	u16 ocp_mod;
-	u8 prm_irqst_reg;
-	bool vp_enabled;
-	u32 (*read_reg) (u16 mod, u8 offset);
-	void (*write_reg) (u32 val, u16 mod, u8 offset);
-	int (*volt_scale) (struct omap_vdd_info *vdd,
-		unsigned long target_volt);
-};
-
-static struct omap_vdd_info *vdd_info;
+static struct omap_vdd_info **vdd_info;
+
 /*
  * Number of scalable voltage domains.
  */
 static int nr_scalable_vdd;
 
-/* OMAP3 VDD sturctures */
-static struct omap_vdd_info omap3_vdd_info[] = {
-	{
-		.vp_offs = {
-			.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
-			.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
-			.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
-			.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "mpu",
-		},
-	},
-	{
-		.vp_offs = {
-			.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
-			.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
-			.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
-			.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "core",
-		},
-	},
-};
-
-#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info)
-
-/* OMAP4 VDD sturctures */
-static struct omap_vdd_info omap4_vdd_info[] = {
-	{
-		.vp_offs = {
-			.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
-			.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
-			.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
-			.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "mpu",
-		},
-	},
-	{
-		.vp_offs = {
-			.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
-			.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
-			.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
-			.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "iva",
-		},
-	},
-	{
-		.vp_offs = {
-			.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
-			.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
-			.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
-			.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "core",
-		},
-	},
-};
-
-#define OMAP4_NR_SCALABLE_VDD ARRAY_SIZE(omap4_vdd_info)
-
-/*
- * Structures containing OMAP3430/OMAP3630 voltage supported and various
- * voltage dependent data for each VDD.
- */
-#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)	\
-{									\
-	.volt_nominal	= _v_nom,					\
-	.sr_efuse_offs	= _efuse_offs,					\
-	.sr_errminlimit	= _errminlimit,					\
-	.vp_errgain	= _errgain					\
-}
-
-/* VDD1 */
-static struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-/* VDD2 */
-static struct omap_volt_data omap34xx_vddcore_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap36xx_vddcore_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-/*
- * Structures containing OMAP4430 voltage supported and various
- * voltage dependent data for each VDD.
- */
-static struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
+/* XXX document */
+static s16 prm_mod_offs;
+static s16 prm_irqst_ocp_mod_offs;
 
 static struct dentry *voltage_dir;
 
 /* Init function pointers */
-static void (*vc_init) (struct omap_vdd_info *vdd);
-static int (*vdd_data_configure) (struct omap_vdd_info *vdd);
+static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
+					unsigned long target_volt);
 
 static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
 {
@@ -335,6 +81,62 @@ static void omap4_voltage_write_reg(u32 val, u16 mod, u8 offset)
 	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
 }
 
+static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
+{
+	char *sys_ck_name;
+	struct clk *sys_ck;
+	u32 sys_clk_speed, timeout_val, waittime;
+
+	/*
+	 * XXX Clockfw should handle this, or this should be in a
+	 * struct record
+	 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		sys_ck_name = "sys_ck";
+	else if (cpu_is_omap44xx())
+		sys_ck_name = "sys_clkin_ck";
+	else
+		return -EINVAL;
+
+	/*
+	 * Sys clk rate is require to calculate vp timeout value and
+	 * smpswaittimemin and smpswaittimemax.
+	 */
+	sys_ck = clk_get(NULL, sys_ck_name);
+	if (IS_ERR(sys_ck)) {
+		pr_warning("%s: Could not get the sys clk to calculate"
+			"various vdd_%s params\n", __func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+	sys_clk_speed = clk_get_rate(sys_ck);
+	clk_put(sys_ck);
+	/* Divide to avoid overflow */
+	sys_clk_speed /= 1000;
+
+	/* Generic voltage parameters */
+	vdd->curr_volt = 1200000;
+	vdd->volt_scale = vp_forceupdate_scale_voltage;
+	vdd->vp_enabled = false;
+
+	vdd->vp_rt_data.vpconfig_erroroffset =
+		(vdd->pmic_info->vp_erroroffset <<
+		 vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
+
+	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
+	vdd->vp_rt_data.vlimitto_timeout = timeout_val;
+	vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
+	vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
+
+	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
+				sys_clk_speed) / 1000;
+	vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
+	vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
+	vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
+	vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
+
+	return 0;
+}
+
 /* Voltage debugfs support */
 static int vp_volt_debug_get(void *data, u64 *val)
 {
@@ -346,7 +148,7 @@ static int vp_volt_debug_get(void *data, u64 *val)
 		return -EINVAL;
 	}
 
-	vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage);
+	vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
 	pr_notice("curr_vsel = %x\n", vsel);
 
 	if (!vdd->pmic_info->vsel_to_uv) {
@@ -379,7 +181,6 @@ DEFINE_SIMPLE_ATTRIBUTE(nom_volt_debug_fops, nom_volt_debug_get, NULL,
 static void vp_latch_vsel(struct omap_vdd_info *vdd)
 {
 	u32 vpconfig;
-	u16 mod;
 	unsigned long uvdc;
 	char vsel;
 
@@ -396,30 +197,27 @@ static void vp_latch_vsel(struct omap_vdd_info *vdd)
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
 	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
 
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask |
-			vdd->vp_reg.vpconfig_initvdd);
-	vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift;
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
+			vdd->vp_data->vp_common->vpconfig_initvdd);
+	vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
 
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Trigger initVDD value copy to voltage processor */
-	vdd->write_reg((vpconfig | vdd->vp_reg.vpconfig_initvdd), mod,
-			vdd->vp_offs.vpconfig);
+	vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
+		       prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Clear initVDD copy trigger bit */
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 }
 
 /* Generic voltage init functions */
 static void __init vp_init(struct omap_vdd_info *vdd)
 {
 	u32 vp_val;
-	u16 mod;
 
 	if (!vdd->read_reg || !vdd->write_reg) {
 		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
@@ -427,33 +225,31 @@ static void __init vp_init(struct omap_vdd_info *vdd)
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
-	vp_val = vdd->vp_reg.vpconfig_erroroffset |
-		(vdd->vp_reg.vpconfig_errorgain <<
-		vdd->vp_reg.vpconfig_errorgain_shift) |
-		vdd->vp_reg.vpconfig_timeouten;
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vpconfig);
-
-	vp_val = ((vdd->vp_reg.vstepmin_smpswaittimemin <<
-		vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
-		(vdd->vp_reg.vstepmin_stepmin <<
-		vdd->vp_reg.vstepmin_stepmin_shift));
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmin);
-
-	vp_val = ((vdd->vp_reg.vstepmax_smpswaittimemax <<
-		vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
-		(vdd->vp_reg.vstepmax_stepmax <<
-		vdd->vp_reg.vstepmax_stepmax_shift));
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmax);
-
-	vp_val = ((vdd->vp_reg.vlimitto_vddmax <<
-		vdd->vp_reg.vlimitto_vddmax_shift) |
-		(vdd->vp_reg.vlimitto_vddmin <<
-		vdd->vp_reg.vlimitto_vddmin_shift) |
-		(vdd->vp_reg.vlimitto_timeout <<
-		vdd->vp_reg.vlimitto_timeout_shift));
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vlimitto);
+	vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
+		(vdd->vp_rt_data.vpconfig_errorgain <<
+		vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
+		vdd->vp_data->vp_common->vpconfig_timeouten;
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
+
+	vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
+		vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
+		(vdd->vp_rt_data.vstepmin_stepmin <<
+		vdd->vp_data->vp_common->vstepmin_stepmin_shift));
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
+
+	vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
+		vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
+		(vdd->vp_rt_data.vstepmax_stepmax <<
+		vdd->vp_data->vp_common->vstepmax_stepmax_shift));
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
+
+	vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
+		vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
+		(vdd->vp_rt_data.vlimitto_vddmin <<
+		vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
+		(vdd->vp_rt_data.vlimitto_timeout <<
+		vdd->vp_data->vp_common->vlimitto_timeout_shift));
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
 }
 
 static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
@@ -480,23 +276,23 @@ static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
 	}
 
 	(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vpconfig_errorgain));
+				&(vdd->vp_rt_data.vpconfig_errorgain));
 	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
 				vdd->debug_dir,
-				&(vdd->vp_reg.vstepmin_smpswaittimemin));
+				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
 	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vstepmin_stepmin));
+				&(vdd->vp_rt_data.vstepmin_stepmin));
 	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
 				vdd->debug_dir,
-				&(vdd->vp_reg.vstepmax_smpswaittimemax));
+				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
 	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vstepmax_stepmax));
+				&(vdd->vp_rt_data.vstepmax_stepmax));
 	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vlimitto_vddmax));
+				&(vdd->vp_rt_data.vlimitto_vddmax));
 	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vlimitto_vddmin));
+				&(vdd->vp_rt_data.vlimitto_vddmin));
 	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vlimitto_timeout));
+				&(vdd->vp_rt_data.vlimitto_timeout));
 	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
 				(void *) vdd, &vp_volt_debug_fops);
 	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
@@ -509,8 +305,12 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,
 		unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
 {
 	struct omap_volt_data *volt_data;
+	const struct omap_vc_common_data *vc_common;
+	const struct omap_vp_common_data *vp_common;
 	u32 vc_cmdval, vp_errgain_val;
-	u16 vp_mod, vc_mod;
+
+	vc_common = vdd->vc_data->vc_common;
+	vp_common = vdd->vp_data->vp_common;
 
 	/* Check if suffiecient pmic info is available for this vdd */
 	if (!vdd->pmic_info) {
@@ -532,33 +332,30 @@ static int _pre_volt_scale(struct omap_vdd_info *vdd,
 		return -EINVAL;
 	}
 
-	vp_mod = vdd->vp_reg.prm_mod;
-	vc_mod = vdd->vc_reg.prm_mod;
-
 	/* Get volt_data corresponding to target_volt */
 	volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
 	if (IS_ERR(volt_data))
 		volt_data = NULL;
 
 	*target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
-	*current_vsel = vdd->read_reg(vp_mod, vdd->vp_offs.voltage);
+	*current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
 
 	/* Setting the ON voltage to the new target voltage */
-	vc_cmdval = vdd->read_reg(vc_mod, vdd->vc_reg.cmdval_reg);
-	vc_cmdval &= ~vdd->vc_reg.cmd_on_mask;
-	vc_cmdval |= (*target_vsel << vdd->vc_reg.cmd_on_shift);
-	vdd->write_reg(vc_cmdval, vc_mod, vdd->vc_reg.cmdval_reg);
+	vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
+	vc_cmdval &= ~vc_common->cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
+	vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
 
 	/* Setting vp errorgain based on the voltage */
 	if (volt_data) {
-		vp_errgain_val = vdd->read_reg(vp_mod,
-				vdd->vp_offs.vpconfig);
-		vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
-		vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
-		vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain <<
-				vdd->vp_reg.vpconfig_errorgain_shift;
-		vdd->write_reg(vp_errgain_val, vp_mod,
-				vdd->vp_offs.vpconfig);
+		vp_errgain_val = vdd->read_reg(prm_mod_offs,
+					       vdd->vp_data->vpconfig);
+		vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
+		vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
+		vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
+			vp_common->vpconfig_errorgain_shift;
+		vdd->write_reg(vp_errgain_val, prm_mod_offs,
+			       vdd->vp_data->vpconfig);
 	}
 
 	return 0;
@@ -584,7 +381,6 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
 {
 	u32 loop_cnt = 0, retries_cnt = 0;
 	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
-	u16 mod;
 	u8 target_vsel, current_vsel;
 	int ret;
 
@@ -592,20 +388,19 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
 	if (ret)
 		return ret;
 
-	mod = vdd->vc_reg.prm_mod;
-
-	vc_valid = vdd->vc_reg.valid;
-	vc_bypass_val_reg = vdd->vc_reg.bypass_val_reg;
-	vc_bypass_value = (target_vsel << vdd->vc_reg.data_shift) |
+	vc_valid = vdd->vc_data->vc_common->valid;
+	vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
+	vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
 			(vdd->pmic_info->pmic_reg <<
-			vdd->vc_reg.regaddr_shift) |
+			vdd->vc_data->vc_common->regaddr_shift) |
 			(vdd->pmic_info->i2c_slave_addr <<
-			vdd->vc_reg.slaveaddr_shift);
+			vdd->vc_data->vc_common->slaveaddr_shift);
 
-	vdd->write_reg(vc_bypass_value, mod, vc_bypass_val_reg);
-	vdd->write_reg(vc_bypass_value | vc_valid, mod, vc_bypass_val_reg);
+	vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
+	vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
+		       vc_bypass_val_reg);
 
-	vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg);
+	vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
 	/*
 	 * Loop till the bypass command is acknowledged from the SMPS.
 	 * NOTE: This is legacy code. The loop count and retry count needs
@@ -624,7 +419,8 @@ static int vc_bypass_scale_voltage(struct omap_vdd_info *vdd,
 			loop_cnt = 0;
 			udelay(10);
 		}
-		vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg);
+		vc_bypass_value = vdd->read_reg(prm_mod_offs,
+						vc_bypass_val_reg);
 	}
 
 	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
@@ -636,7 +432,6 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
 		unsigned long target_volt)
 {
 	u32 vpconfig;
-	u16 mod, ocp_mod;
 	u8 target_vsel, current_vsel, prm_irqst_reg;
 	int ret, timeout = 0;
 
@@ -644,20 +439,18 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
 	if (ret)
 		return ret;
 
-	mod = vdd->vp_reg.prm_mod;
-	ocp_mod = vdd->ocp_mod;
-	prm_irqst_reg = vdd->prm_irqst_reg;
+	prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
 
 	/*
 	 * Clear all pending TransactionDone interrupt/status. Typical latency
 	 * is <3us
 	 */
 	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_reg.tranxdone_status,
-				ocp_mod, prm_irqst_reg);
-		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
-				vdd->vp_reg.tranxdone_status))
-				break;
+		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
+			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
+		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+		      vdd->vp_data->prm_irqst_data->tranxdone_status))
+			break;
 		udelay(1);
 	}
 	if (timeout >= VP_TRANXDONE_TIMEOUT) {
@@ -667,30 +460,30 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
 	}
 
 	/* Configure for VP-Force Update */
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig &= ~(vdd->vp_reg.vpconfig_initvdd |
-			vdd->vp_reg.vpconfig_forceupdate |
-			vdd->vp_reg.vpconfig_initvoltage_mask);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
+			vdd->vp_data->vp_common->vpconfig_forceupdate |
+			vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
 	vpconfig |= ((target_vsel <<
-			vdd->vp_reg.vpconfig_initvoltage_shift));
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+			vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Trigger initVDD value copy to voltage processor */
-	vpconfig |= vdd->vp_reg.vpconfig_initvdd;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Force update of voltage */
-	vpconfig |= vdd->vp_reg.vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/*
 	 * Wait for TransactionDone. Typical latency is <200us.
 	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
 	 */
 	timeout = 0;
-	omap_test_timeout((vdd->read_reg(ocp_mod, prm_irqst_reg) &
-			vdd->vp_reg.tranxdone_status),
-			VP_TRANXDONE_TIMEOUT, timeout);
+	omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+			   vdd->vp_data->prm_irqst_data->tranxdone_status),
+			  VP_TRANXDONE_TIMEOUT, timeout);
 	if (timeout >= VP_TRANXDONE_TIMEOUT)
 		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
 			"TRANXDONE never got set after the voltage update\n",
@@ -704,11 +497,11 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
 	 */
 	timeout = 0;
 	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_reg.tranxdone_status,
-				ocp_mod, prm_irqst_reg);
-		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
-				vdd->vp_reg.tranxdone_status))
-				break;
+		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
+			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
+		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+		      vdd->vp_data->prm_irqst_data->tranxdone_status))
+			break;
 		udelay(1);
 	}
 
@@ -717,222 +510,95 @@ static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
 			"to clear the TRANXDONE status\n",
 			__func__, vdd->voltdm.name);
 
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
 	/* Clear initVDD copy trigger bit */
-	vpconfig &= ~vdd->vp_reg.vpconfig_initvdd;;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 	/* Clear force bit */
-	vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	return 0;
 }
 
-/* OMAP3 specific voltage init functions */
+static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
+{
+	/*
+	 * Voltage Manager FSM parameters init
+	 * XXX This data should be passed in from the board file
+	 */
+	vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
+	vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
+		       OMAP3_PRM_VOLTOFFSET_OFFSET);
+	vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
+		       OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
 
-/*
- * Intializes the voltage controller registers with the PMIC and board
- * specific parameters and voltage setup times for OMAP3.
- */
 static void __init omap3_vc_init(struct omap_vdd_info *vdd)
 {
-	u32 vc_val;
-	u16 mod;
-	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
 	static bool is_initialized;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	u32 vc_val;
 
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC info requried to configure vc for"
-			"vdd_%s not populated.Hence cannot initialize vc\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
+	if (is_initialized)
 		return;
-	}
-
-	mod = vdd->vc_reg.prm_mod;
-
-	/* Set up the SMPS_SA(i2c slave address in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
-	vc_val &= ~vdd->vc_reg.smps_sa_mask;
-	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
-
-	/* Setup the VOLRA(pmic reg addr) in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
-	vc_val &= ~vdd->vc_reg.smps_volra_mask;
-	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
-
-	/*Configure the setup times */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.voltsetup_reg);
-	vc_val &= ~vdd->vc_reg.voltsetup_mask;
-	vc_val |= vdd->pmic_info->volt_setup_time <<
-			vdd->vc_reg.voltsetup_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.voltsetup_reg);
 
 	/* Set up the on, inactive, retention and off voltage */
 	on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
 	onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
 	ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
 	off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
-	vc_val	= ((on_vsel << vdd->vc_reg.cmd_on_shift) |
-		(onlp_vsel << vdd->vc_reg.cmd_onlp_shift) |
-		(ret_vsel << vdd->vc_reg.cmd_ret_shift) |
-		(off_vsel << vdd->vc_reg.cmd_off_shift));
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.cmdval_reg);
-
-	if (is_initialized)
-		return;
+	vc_val	= ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
+		(onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
+		(ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
+		(off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
+	vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
 
-	/* Generic VC parameters init */
-	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, mod,
+	/*
+	 * Generic VC parameters init
+	 * XXX This data should be abstracted out
+	 */
+	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
 			OMAP3_PRM_VC_CH_CONF_OFFSET);
-	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, mod,
+	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
 			OMAP3_PRM_VC_I2C_CFG_OFFSET);
-	vdd->write_reg(OMAP3_CLKSETUP, mod, OMAP3_PRM_CLKSETUP_OFFSET);
-	vdd->write_reg(OMAP3_VOLTOFFSET, mod, OMAP3_PRM_VOLTOFFSET_OFFSET);
-	vdd->write_reg(OMAP3_VOLTSETUP2, mod, OMAP3_PRM_VOLTSETUP2_OFFSET);
+
+	omap3_vfsm_init(vdd);
+
 	is_initialized = true;
 }
 
-/* Sets up all the VDD related info for OMAP3 */
-static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
+
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init(struct omap_vdd_info *vdd)
 {
-	struct clk *sys_ck;
-	u32 sys_clk_speed, timeout_val, waittime;
+	static bool is_initialized;
+	u32 vc_val;
 
-	if (!vdd->pmic_info) {
-		pr_err("%s: PMIC info requried to configure vdd_%s not"
-			"populated.Hence cannot initialize vdd_%s\n",
-			__func__, vdd->voltdm.name, vdd->voltdm.name);
-		return -EINVAL;
-	}
+	if (is_initialized)
+		return;
 
-	if (!strcmp(vdd->voltdm.name, "mpu")) {
-		if (cpu_is_omap3630())
-			vdd->volt_data = omap36xx_vddmpu_volt_data;
-		else
-			vdd->volt_data = omap34xx_vddmpu_volt_data;
-
-		vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET;
-		vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT;
-		vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA0_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA0_MASK;
-		vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT;
-		vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK;
-	} else if (!strcmp(vdd->voltdm.name, "core")) {
-		if (cpu_is_omap3630())
-			vdd->volt_data = omap36xx_vddcore_volt_data;
-		else
-			vdd->volt_data = omap34xx_vddcore_volt_data;
-
-		vdd->vp_reg.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET;
-		vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT;
-		vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA1_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA1_MASK;
-		vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT;
-		vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK;
-	} else {
-		pr_warning("%s: vdd_%s does not exisit in OMAP3\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
+	/* TODO: Configure setup times and CMD_VAL values*/
 
 	/*
-	 * Sys clk rate is require to calculate vp timeout value and
-	 * smpswaittimemin and smpswaittimemax.
+	 * Generic VC parameters init
+	 * XXX This data should be abstracted out
 	 */
-	sys_ck = clk_get(NULL, "sys_ck");
-	if (IS_ERR(sys_ck)) {
-		pr_warning("%s: Could not get the sys clk to calculate"
-			"various vdd_%s params\n", __func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
-	/* Divide to avoid overflow */
-	sys_clk_speed /= 1000;
-
-	/* Generic voltage parameters */
-	vdd->curr_volt = 1200000;
-	vdd->ocp_mod = OCP_MOD;
-	vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET;
-	vdd->read_reg = omap3_voltage_read_reg;
-	vdd->write_reg = omap3_voltage_write_reg;
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
-	vdd->vp_enabled = false;
+	vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
+		  OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
+		  OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
+	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
 
-	/* VC parameters */
-	vdd->vc_reg.prm_mod = OMAP3430_GR_MOD;
-	vdd->vc_reg.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET;
-	vdd->vc_reg.smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET;
-	vdd->vc_reg.bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET;
-	vdd->vc_reg.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET;
-	vdd->vc_reg.data_shift = OMAP3430_DATA_SHIFT;
-	vdd->vc_reg.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT;
-	vdd->vc_reg.regaddr_shift = OMAP3430_REGADDR_SHIFT;
-	vdd->vc_reg.valid = OMAP3430_VALID_MASK;
-	vdd->vc_reg.cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT;
-	vdd->vc_reg.cmd_on_mask = OMAP3430_VC_CMD_ON_MASK;
-	vdd->vc_reg.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT;
-	vdd->vc_reg.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT;
-	vdd->vc_reg.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT;
-
-	vdd->vp_reg.prm_mod = OMAP3430_GR_MOD;
-
-	/* VPCONFIG bit fields */
-	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
-				 OMAP3430_ERROROFFSET_SHIFT);
-	vdd->vp_reg.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK;
-	vdd->vp_reg.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK;
-	vdd->vp_reg.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK;
-	vdd->vp_reg.vpconfig_initvdd = OMAP3430_INITVDD_MASK;
-	vdd->vp_reg.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK;
-	vdd->vp_reg.vpconfig_vpenable = OMAP3430_VPENABLE_MASK;
-
-	/* VSTEPMIN VSTEPMAX bit fields */
-	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
-				sys_clk_speed) / 1000;
-	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
-	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
-	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
-	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
-				OMAP3430_SMPSWAITTIMEMIN_SHIFT;
-	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
-				OMAP3430_SMPSWAITTIMEMAX_SHIFT;
-	vdd->vp_reg.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT;
-	vdd->vp_reg.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT;
-
-	/* VLIMITTO bit fields */
-	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
-	vdd->vp_reg.vlimitto_timeout = timeout_val;
-	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
-	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-	vdd->vp_reg.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT;
-	vdd->vp_reg.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT;
-	vdd->vp_reg.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT;
+	/* XXX These are magic numbers and do not belong! */
+	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
 
-	return 0;
+	is_initialized = true;
 }
 
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
+static void __init omap_vc_init(struct omap_vdd_info *vdd)
 {
 	u32 vc_val;
-	u16 mod;
-	static bool is_initialized;
 
 	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
 		pr_err("%s: PMIC info requried to configure vc for"
@@ -947,173 +613,61 @@ static void __init omap4_vc_init(struct omap_vdd_info *vdd)
 		return;
 	}
 
-	mod = vdd->vc_reg.prm_mod;
-
 	/* Set up the SMPS_SA(i2c slave address in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
-	vc_val &= ~vdd->vc_reg.smps_sa_mask;
-	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
+	vc_val = vdd->read_reg(prm_mod_offs,
+			       vdd->vc_data->vc_common->smps_sa_reg);
+	vc_val &= ~vdd->vc_data->smps_sa_mask;
+	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
+	vdd->write_reg(vc_val, prm_mod_offs,
+		       vdd->vc_data->vc_common->smps_sa_reg);
 
 	/* Setup the VOLRA(pmic reg addr) in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
-	vc_val &= ~vdd->vc_reg.smps_volra_mask;
-	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
-
-	/* TODO: Configure setup times and CMD_VAL values*/
-
-	if (is_initialized)
-		return;
-
-	/* Generic VC parameters init */
-	vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
-		OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
-		OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
-	vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
-
-	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
-	vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+	vc_val = vdd->read_reg(prm_mod_offs,
+			       vdd->vc_data->vc_common->smps_volra_reg);
+	vc_val &= ~vdd->vc_data->smps_volra_mask;
+	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
+	vdd->write_reg(vc_val, prm_mod_offs,
+		       vdd->vc_data->vc_common->smps_volra_reg);
+
+	/* Configure the setup times */
+	vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
+	vc_val &= ~vdd->vfsm->voltsetup_mask;
+	vc_val |= vdd->pmic_info->volt_setup_time <<
+			vdd->vfsm->voltsetup_shift;
+	vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
 
-	is_initialized = true;
+	if (cpu_is_omap34xx())
+		omap3_vc_init(vdd);
+	else if (cpu_is_omap44xx())
+		omap4_vc_init(vdd);
 }
 
-/* Sets up all the VDD related info for OMAP4 */
-static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
+static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
 {
-	struct clk *sys_ck;
-	u32 sys_clk_speed, timeout_val, waittime;
+	int ret = -EINVAL;
 
 	if (!vdd->pmic_info) {
 		pr_err("%s: PMIC info requried to configure vdd_%s not"
 			"populated.Hence cannot initialize vdd_%s\n",
 			__func__, vdd->voltdm.name, vdd->voltdm.name);
-		return -EINVAL;
+		goto ovdc_out;
 	}
 
-	if (!strcmp(vdd->voltdm.name, "mpu")) {
-		vdd->volt_data = omap44xx_vdd_mpu_volt_data;
-		vdd->vp_reg.tranxdone_status =
-				OMAP4430_VP_MPU_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET;
-		vdd->vc_reg.smps_sa_shift =
-				OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT;
-		vdd->vc_reg.smps_sa_mask =
-				OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK;
-		vdd->vc_reg.voltsetup_reg =
-				OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET;
-		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET;
-	} else if (!strcmp(vdd->voltdm.name, "core")) {
-		vdd->volt_data = omap44xx_vdd_core_volt_data;
-		vdd->vp_reg.tranxdone_status =
-				OMAP4430_VP_CORE_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg =
-				OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET;
-		vdd->vc_reg.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT;
-		vdd->vc_reg.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK;
-		vdd->vc_reg.voltsetup_reg =
-				OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET;
-		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
-	} else if (!strcmp(vdd->voltdm.name, "iva")) {
-		vdd->volt_data = omap44xx_vdd_iva_volt_data;
-		vdd->vp_reg.tranxdone_status =
-				OMAP4430_VP_IVA_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET;
-		vdd->vc_reg.smps_sa_shift =
-				OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT;
-		vdd->vc_reg.smps_sa_mask =
-				OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK;
-		vdd->vc_reg.voltsetup_reg =
-				OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET;
-		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
-	} else {
-		pr_warning("%s: vdd_%s does not exisit in OMAP4\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
+	if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
+		goto ovdc_out;
 
-	/*
-	 * Sys clk rate is require to calculate vp timeout value and
-	 * smpswaittimemin and smpswaittimemax.
-	 */
-	sys_ck = clk_get(NULL, "sys_clkin_ck");
-	if (IS_ERR(sys_ck)) {
-		pr_warning("%s: Could not get the sys clk to calculate"
-			"various vdd_%s params\n", __func__, vdd->voltdm.name);
-		return -EINVAL;
+	if (cpu_is_omap34xx()) {
+		vdd->read_reg = omap3_voltage_read_reg;
+		vdd->write_reg = omap3_voltage_write_reg;
+		ret = 0;
+	} else if (cpu_is_omap44xx()) {
+		vdd->read_reg = omap4_voltage_read_reg;
+		vdd->write_reg = omap4_voltage_write_reg;
+		ret = 0;
 	}
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
-	/* Divide to avoid overflow */
-	sys_clk_speed /= 1000;
-
-	/* Generic voltage parameters */
-	vdd->curr_volt = 1200000;
-	vdd->ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
-	vdd->read_reg = omap4_voltage_read_reg;
-	vdd->write_reg = omap4_voltage_write_reg;
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
-	vdd->vp_enabled = false;
 
-	/* VC parameters */
-	vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
-	vdd->vc_reg.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET;
-	vdd->vc_reg.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET;
-	vdd->vc_reg.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET;
-	vdd->vc_reg.data_shift = OMAP4430_DATA_SHIFT;
-	vdd->vc_reg.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT;
-	vdd->vc_reg.regaddr_shift = OMAP4430_REGADDR_SHIFT;
-	vdd->vc_reg.valid = OMAP4430_VALID_MASK;
-	vdd->vc_reg.cmd_on_shift = OMAP4430_ON_SHIFT;
-	vdd->vc_reg.cmd_on_mask = OMAP4430_ON_MASK;
-	vdd->vc_reg.cmd_onlp_shift = OMAP4430_ONLP_SHIFT;
-	vdd->vc_reg.cmd_ret_shift = OMAP4430_RET_SHIFT;
-	vdd->vc_reg.cmd_off_shift = OMAP4430_OFF_SHIFT;
-
-	vdd->vp_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
-
-	/* VPCONFIG bit fields */
-	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
-				 OMAP4430_ERROROFFSET_SHIFT);
-	vdd->vp_reg.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK;
-	vdd->vp_reg.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK;
-	vdd->vp_reg.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK;
-	vdd->vp_reg.vpconfig_initvdd = OMAP4430_INITVDD_MASK;
-	vdd->vp_reg.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK;
-	vdd->vp_reg.vpconfig_vpenable = OMAP4430_VPENABLE_MASK;
-
-	/* VSTEPMIN VSTEPMAX bit fields */
-	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
-				sys_clk_speed) / 1000;
-	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
-	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
-	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
-	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
-			OMAP4430_SMPSWAITTIMEMIN_SHIFT;
-	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
-			OMAP4430_SMPSWAITTIMEMAX_SHIFT;
-	vdd->vp_reg.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT;
-	vdd->vp_reg.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT;
-
-	/* VLIMITTO bit fields */
-	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
-	vdd->vp_reg.vlimitto_timeout = timeout_val;
-	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
-	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-	vdd->vp_reg.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT;
-	vdd->vp_reg.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT;
-	vdd->vp_reg.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT;
-
-	return 0;
+ovdc_out:
+	return ret;
 }
 
 /* Public functions */
@@ -1161,8 +715,7 @@ unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm)
 		return 0;
 	}
 
-	curr_vsel = vdd->read_reg(vdd->vp_reg.prm_mod,
-			vdd->vp_offs.voltage);
+	curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
 
 	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
 		pr_warning("%s: PMIC function to convert vsel to voltage"
@@ -1184,7 +737,6 @@ void omap_vp_enable(struct voltagedomain *voltdm)
 {
 	struct omap_vdd_info *vdd;
 	u32 vpconfig;
-	u16 mod;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
@@ -1198,8 +750,6 @@ void omap_vp_enable(struct voltagedomain *voltdm)
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
 	/* If VP is already enabled, do nothing. Return */
 	if (vdd->vp_enabled)
 		return;
@@ -1207,9 +757,9 @@ void omap_vp_enable(struct voltagedomain *voltdm)
 	vp_latch_vsel(vdd);
 
 	/* Enable VP */
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig |= vdd->vp_reg.vpconfig_vpenable;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 	vdd->vp_enabled = true;
 }
 
@@ -1224,7 +774,6 @@ void omap_vp_disable(struct voltagedomain *voltdm)
 {
 	struct omap_vdd_info *vdd;
 	u32 vpconfig;
-	u16 mod;
 	int timeout;
 
 	if (!voltdm || IS_ERR(voltdm)) {
@@ -1239,8 +788,6 @@ void omap_vp_disable(struct voltagedomain *voltdm)
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
 	/* If VP is already disabled, do nothing. Return */
 	if (!vdd->vp_enabled) {
 		pr_warning("%s: Trying to disable VP for vdd_%s when"
@@ -1249,14 +796,14 @@ void omap_vp_disable(struct voltagedomain *voltdm)
 	}
 
 	/* Disable VP */
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig &= ~vdd->vp_reg.vpconfig_vpenable;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/*
 	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
 	 */
-	omap_test_timeout((vdd->read_reg(mod, vdd->vp_offs.vstatus)),
+	omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
 				VP_IDLE_TIMEOUT, timeout);
 
 	if (timeout >= VP_IDLE_TIMEOUT)
@@ -1509,8 +1056,8 @@ struct voltagedomain *omap_voltage_domain_lookup(char *name)
 	}
 
 	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (!(strcmp(name, vdd_info[i].voltdm.name)))
-			return &vdd_info[i].voltdm;
+		if (!(strcmp(name, vdd_info[i]->voltdm.name)))
+			return &vdd_info[i]->voltdm;
 	}
 
 	return ERR_PTR(-EINVAL);
@@ -1538,35 +1085,24 @@ int __init omap_voltage_late_init(void)
 		pr_err("%s: Unable to create voltage debugfs main dir\n",
 			__func__);
 	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (vdd_data_configure(&vdd_info[i]))
+		if (omap_vdd_data_configure(vdd_info[i]))
 			continue;
-		vc_init(&vdd_info[i]);
-		vp_init(&vdd_info[i]);
-		vdd_debugfs_init(&vdd_info[i]);
+		omap_vc_init(vdd_info[i]);
+		vp_init(vdd_info[i]);
+		vdd_debugfs_init(vdd_info[i]);
 	}
 
 	return 0;
 }
 
-/**
- * omap_voltage_early_init()- Volatage driver early init
- */
-static int __init omap_voltage_early_init(void)
+/* XXX document */
+int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
+				   struct omap_vdd_info *omap_vdd_array[],
+				   u8 omap_vdd_count)
 {
-	if (cpu_is_omap34xx()) {
-		vdd_info = omap3_vdd_info;
-		nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
-		vc_init = omap3_vc_init;
-		vdd_data_configure = omap3_vdd_data_configure;
-	} else if (cpu_is_omap44xx()) {
-		vdd_info = omap4_vdd_info;
-		nr_scalable_vdd = OMAP4_NR_SCALABLE_VDD;
-		vc_init = omap4_vc_init;
-		vdd_data_configure = omap4_vdd_data_configure;
-	} else {
-		pr_warning("%s: voltage driver support not added\n", __func__);
-	}
-
+	prm_mod_offs = prm_mod;
+	prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod;
+	vdd_info = omap_vdd_array;
+	nr_scalable_vdd = omap_vdd_count;
 	return 0;
 }
-core_initcall(omap_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
new file mode 100644
index 0000000..e9f5408
--- /dev/null
+++ b/arch/arm/mach-omap2/voltage.h
@@ -0,0 +1,184 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * Thara Gopinath <thara@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 __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+
+#include <linux/err.h>
+
+#include "vc.h"
+#include "vp.h"
+
+/* XXX document */
+#define VOLTSCALE_VPFORCEUPDATE		1
+#define VOLTSCALE_VCBYPASS		2
+
+/*
+ * OMAP3 GENERIC setup times. Revisit to see if these needs to be
+ * passed from board or PMIC file
+ */
+#define OMAP3_CLKSETUP		0xff
+#define OMAP3_VOLTOFFSET	0xff
+#define OMAP3_VOLTSETUP2	0xff
+
+/**
+ * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * data
+ * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
+ * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
+ * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
+ *
+ * XXX What about VOLTOFFSET/VOLTCTRL?
+ * XXX It is not necessary to have both a _mask and a _shift for the same
+ *     bitfield - remove one!
+ */
+struct omap_vfsm_instance_data {
+	u32 voltsetup_mask;
+	u8 voltsetup_reg;
+	u8 voltsetup_shift;
+};
+
+/**
+ * struct voltagedomain - omap voltage domain global structure.
+ * @name:	Name of the voltage domain which can be used as a unique
+ *		identifier.
+ */
+struct voltagedomain {
+	char *name;
+};
+
+/**
+ * struct omap_volt_data - Omap voltage specific data.
+ * @voltage_nominal:	The possible voltage value in uV
+ * @sr_efuse_offs:	The offset of the efuse register(from system
+ *			control module base address) from where to read
+ *			the n-target value for the smartreflex module.
+ * @sr_errminlimit:	Error min limit value for smartreflex. This value
+ *			differs at differnet opp and thus is linked
+ *			with voltage.
+ * @vp_errorgain:	Error gain value for the voltage processor. This
+ *			field also differs according to the voltage/opp.
+ */
+struct omap_volt_data {
+	u32	volt_nominal;
+	u32	sr_efuse_offs;
+	u8	sr_errminlimit;
+	u8	vp_errgain;
+};
+
+/**
+ * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * @slew_rate:	PMIC slew rate (in uv/us)
+ * @step_size:	PMIC voltage step size (in uv)
+ * @vsel_to_uv:	PMIC API to convert vsel value to actual voltage in uV.
+ * @uv_to_vsel:	PMIC API to convert voltage in uV to vsel value.
+ */
+struct omap_volt_pmic_info {
+	int slew_rate;
+	int step_size;
+	u32 on_volt;
+	u32 onlp_volt;
+	u32 ret_volt;
+	u32 off_volt;
+	u16 volt_setup_time;
+	u8 vp_erroroffset;
+	u8 vp_vstepmin;
+	u8 vp_vstepmax;
+	u8 vp_vddmin;
+	u8 vp_vddmax;
+	u8 vp_timeout_us;
+	u8 i2c_slave_addr;
+	u8 pmic_reg;
+	unsigned long (*vsel_to_uv) (const u8 vsel);
+	u8 (*uv_to_vsel) (unsigned long uV);
+};
+
+/**
+ * omap_vdd_info - Per Voltage Domain info
+ *
+ * @volt_data		: voltage table having the distinct voltages supported
+ *			  by the domain and other associated per voltage data.
+ * @pmic_info		: pmic specific parameters which should be populted by
+ *			  the pmic drivers.
+ * @vp_data		: the register values, shifts, masks for various
+ *			  vp registers
+ * @vp_rt_data          : VP data derived at runtime, not predefined
+ * @vc_data		: structure containing various various vc registers,
+ *			  shifts, masks etc.
+ * @vfsm                : voltage manager FSM data
+ * @voltdm		: pointer to the voltage domain structure
+ * @debug_dir		: debug directory for this voltage domain.
+ * @curr_volt		: current voltage for this vdd.
+ * @vp_enabled		: flag to keep track of whether vp is enabled or not
+ * @volt_scale		: API to scale the voltage of the vdd.
+ */
+struct omap_vdd_info {
+	struct omap_volt_data *volt_data;
+	struct omap_volt_pmic_info *pmic_info;
+	struct omap_vp_instance_data *vp_data;
+	struct omap_vp_runtime_data vp_rt_data;
+	struct omap_vc_instance_data *vc_data;
+	const struct omap_vfsm_instance_data *vfsm;
+	struct voltagedomain voltdm;
+	struct dentry *debug_dir;
+	u32 curr_volt;
+	bool vp_enabled;
+	u32 (*read_reg) (u16 mod, u8 offset);
+	void (*write_reg) (u32 val, u16 mod, u8 offset);
+	int (*volt_scale) (struct omap_vdd_info *vdd,
+		unsigned long target_volt);
+};
+
+unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
+		unsigned long target_volt);
+void omap_voltage_reset(struct voltagedomain *voltdm);
+void omap_voltage_get_volttable(struct voltagedomain *voltdm,
+		struct omap_volt_data **volt_data);
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
+		unsigned long volt);
+unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
+struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
+int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
+				   struct omap_vdd_info *omap_vdd_array[],
+				   u8 omap_vdd_count);
+#ifdef CONFIG_PM
+int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info);
+void omap_change_voltscale_method(struct voltagedomain *voltdm,
+		int voltscale_method);
+/* API to get the voltagedomain pointer */
+struct voltagedomain *omap_voltage_domain_lookup(char *name);
+
+int omap_voltage_late_init(void);
+#else
+static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info)
+{
+	return -EINVAL;
+}
+static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
+		int voltscale_method) {}
+static inline int omap_voltage_late_init(void)
+{
+	return -EINVAL;
+}
+static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-omap2/voltagedomains3xxx_data.c b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
new file mode 100644
index 0000000..def230f
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains3xxx_data.c
@@ -0,0 +1,95 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+
+#include "prm-regbits-34xx.h"
+#include "omap_opp_data.h"
+#include "voltage.h"
+#include "vc.h"
+#include "vp.h"
+
+/*
+ * VDD data
+ */
+
+static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
+	.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
+	.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
+};
+
+static struct omap_vdd_info omap3_vdd1_info = {
+	.vp_data = &omap3_vp1_data,
+	.vc_data = &omap3_vc1_data,
+	.vfsm = &omap3_vdd1_vfsm_data,
+	.voltdm = {
+		.name = "mpu",
+	},
+};
+
+static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
+	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
+	.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
+	.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
+};
+
+static struct omap_vdd_info omap3_vdd2_info = {
+	.vp_data = &omap3_vp2_data,
+	.vc_data = &omap3_vc2_data,
+	.vfsm = &omap3_vdd2_vfsm_data,
+	.voltdm = {
+		.name = "core",
+	},
+};
+
+/* OMAP3 VDD structures */
+static struct omap_vdd_info *omap3_vdd_info[] = {
+	&omap3_vdd1_info,
+	&omap3_vdd2_info,
+};
+
+/* OMAP3 specific voltage init functions */
+static int __init omap3xxx_voltage_early_init(void)
+{
+	s16 prm_mod = OMAP3430_GR_MOD;
+	s16 prm_irqst_ocp_mod = OCP_MOD;
+
+	if (!cpu_is_omap34xx())
+		return 0;
+
+	/*
+	 * XXX Will depend on the process, validation, and binning
+	 * for the currently-running IC
+	 */
+	if (cpu_is_omap3630()) {
+		omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data;
+		omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data;
+	} else {
+		omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data;
+		omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data;
+	}
+
+	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
+				       omap3_vdd_info,
+				       ARRAY_SIZE(omap3_vdd_info));
+};
+core_initcall(omap3xxx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/voltagedomains44xx_data.c b/arch/arm/mach-omap2/voltagedomains44xx_data.c
new file mode 100644
index 0000000..cb64996
--- /dev/null
+++ b/arch/arm/mach-omap2/voltagedomains44xx_data.c
@@ -0,0 +1,102 @@
+/*
+ * OMAP3/OMAP4 Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@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/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
+#include "voltage.h"
+#include "omap_opp_data.h"
+#include "vc.h"
+#include "vp.h"
+
+static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_mpu_info = {
+	.vp_data = &omap4_vp_mpu_data,
+	.vc_data = &omap4_vc_mpu_data,
+	.vfsm = &omap4_vdd_mpu_vfsm_data,
+	.voltdm = {
+		.name = "mpu",
+	},
+};
+
+static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_iva_info = {
+	.vp_data = &omap4_vp_iva_data,
+	.vc_data = &omap4_vc_iva_data,
+	.vfsm = &omap4_vdd_iva_vfsm_data,
+	.voltdm = {
+		.name = "iva",
+	},
+};
+
+static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_core_info = {
+	.vp_data = &omap4_vp_core_data,
+	.vc_data = &omap4_vc_core_data,
+	.vfsm = &omap4_vdd_core_vfsm_data,
+	.voltdm = {
+		.name = "core",
+	},
+};
+
+/* OMAP4 VDD structures */
+static struct omap_vdd_info *omap4_vdd_info[] = {
+	&omap4_vdd_mpu_info,
+	&omap4_vdd_iva_info,
+	&omap4_vdd_core_info,
+};
+
+/* OMAP4 specific voltage init functions */
+static int __init omap44xx_voltage_early_init(void)
+{
+	s16 prm_mod = OMAP4430_PRM_DEVICE_INST;
+	s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+
+	if (!cpu_is_omap44xx())
+		return 0;
+
+	/*
+	 * XXX Will depend on the process, validation, and binning
+	 * for the currently-running IC
+	 */
+	omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
+	omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
+	omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+
+	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
+				       omap4_vdd_info,
+				       ARRAY_SIZE(omap4_vdd_info));
+};
+core_initcall(omap44xx_voltage_early_init);
diff --git a/arch/arm/mach-omap2/vp.h b/arch/arm/mach-omap2/vp.h
new file mode 100644
index 0000000..7ce134f
--- /dev/null
+++ b/arch/arm/mach-omap2/vp.h
@@ -0,0 +1,143 @@
+/*
+ * OMAP3/4 Voltage Processor (VP) structure and macro definitions
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ */
+#ifndef __ARCH_ARM_MACH_OMAP2_VP_H
+#define __ARCH_ARM_MACH_OMAP2_VP_H
+
+#include <linux/kernel.h>
+
+/* XXX document */
+#define VP_IDLE_TIMEOUT		200
+#define VP_TRANXDONE_TIMEOUT	300
+
+
+/**
+ * struct omap_vp_common_data - register data common to all VDDs
+ * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ *
+ * XXX It it not necessary to have both a mask and a shift for the same
+ *     bitfield - remove one
+ * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
+ */
+struct omap_vp_common_data {
+	u32 vpconfig_errorgain_mask;
+	u32 vpconfig_initvoltage_mask;
+	u32 vpconfig_timeouten;
+	u32 vpconfig_initvdd;
+	u32 vpconfig_forceupdate;
+	u32 vpconfig_vpenable;
+	u8 vpconfig_erroroffset_shift;
+	u8 vpconfig_errorgain_shift;
+	u8 vpconfig_initvoltage_shift;
+	u8 vstepmin_stepmin_shift;
+	u8 vstepmin_smpswaittimemin_shift;
+	u8 vstepmax_stepmax_shift;
+	u8 vstepmax_smpswaittimemax_shift;
+	u8 vlimitto_vddmin_shift;
+	u8 vlimitto_vddmax_shift;
+	u8 vlimitto_timeout_shift;
+};
+
+/**
+ * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
+ * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ *
+ * XXX prm_irqst_reg does not belong here
+ * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
+ *     hardware bug
+ * XXX This structure is probably not needed
+ */
+struct omap_vp_prm_irqst_data {
+	u8 prm_irqst_reg;
+	u32 tranxdone_status;
+};
+
+/**
+ * struct omap_vp_instance_data - VP register offsets (per-VDD)
+ * @vp_common: pointer to struct omap_vp_common_data * for this SoC
+ * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
+ * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
+ * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
+ * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
+ * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
+ * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
+ *
+ * XXX vp_common is probably not needed since it is per-SoC
+ */
+struct omap_vp_instance_data {
+	const struct omap_vp_common_data *vp_common;
+	const struct omap_vp_prm_irqst_data *prm_irqst_data;
+	u8 vpconfig;
+	u8 vstepmin;
+	u8 vstepmax;
+	u8 vlimitto;
+	u8 vstatus;
+	u8 voltage;
+};
+
+/**
+ * struct omap_vp_runtime_data - VP data populated at runtime by code
+ * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
+ * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
+ * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
+ * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
+ * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
+ * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
+ * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
+ * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
+ * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
+ *
+ * XXX Is this structure really needed?  Why not just program the
+ * device directly?  They are in PRM space, therefore in the WKUP
+ * powerdomain, so register contents should not be lost in off-mode.
+ * XXX Some of these fields are incorrectly named, e.g., vstep*
+ */
+struct omap_vp_runtime_data {
+	u32 vpconfig_erroroffset;
+	u16 vpconfig_errorgain;
+	u16 vstepmin_smpswaittimemin;
+	u16 vstepmax_smpswaittimemax;
+	u16 vlimitto_timeout;
+	u8 vstepmin_stepmin;
+	u8 vstepmax_stepmax;
+	u8 vlimitto_vddmin;
+	u8 vlimitto_vddmax;
+};
+
+extern struct omap_vp_instance_data omap3_vp1_data;
+extern struct omap_vp_instance_data omap3_vp2_data;
+
+extern struct omap_vp_instance_data omap4_vp_mpu_data;
+extern struct omap_vp_instance_data omap4_vp_iva_data;
+extern struct omap_vp_instance_data omap4_vp_core_data;
+
+#endif
diff --git a/arch/arm/mach-omap2/vp3xxx_data.c b/arch/arm/mach-omap2/vp3xxx_data.c
new file mode 100644
index 0000000..6452170
--- /dev/null
+++ b/arch/arm/mach-omap2/vp3xxx_data.c
@@ -0,0 +1,82 @@
+/*
+ * OMAP3 Voltage Processor (VP) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#include "vp.h"
+
+/*
+ * VP data common to 34xx/36xx chips
+ * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
+ */
+static const struct omap_vp_common_data omap3_vp_common = {
+	.vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT,
+	.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
+	.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
+	.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
+	.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
+	.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
+	.vpconfig_initvdd = OMAP3430_INITVDD_MASK,
+	.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK,
+	.vpconfig_vpenable = OMAP3430_VPENABLE_MASK,
+	.vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT,
+	.vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT,
+	.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT,
+	.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT,
+	.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
+	.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
+	.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
+};
+
+static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = {
+	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap3_vp1_data = {
+	.vp_common = &omap3_vp_common,
+	.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
+	.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
+	.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
+	.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap3_vp1_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
+	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap3_vp2_data = {
+	.vp_common = &omap3_vp_common,
+	.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
+	.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
+	.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
+	.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap3_vp2_prm_irqst_data,
+};
diff --git a/arch/arm/mach-omap2/vp44xx_data.c b/arch/arm/mach-omap2/vp44xx_data.c
new file mode 100644
index 0000000..65d1ad6
--- /dev/null
+++ b/arch/arm/mach-omap2/vp44xx_data.c
@@ -0,0 +1,100 @@
+/*
+ * OMAP3 Voltage Processor (VP) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "voltage.h"
+
+#include "vp.h"
+
+/*
+ * VP data common to 44xx chips
+ * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
+ */
+static const struct omap_vp_common_data omap4_vp_common = {
+	.vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT,
+	.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
+	.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
+	.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
+	.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
+	.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
+	.vpconfig_initvdd = OMAP4430_INITVDD_MASK,
+	.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK,
+	.vpconfig_vpenable = OMAP4430_VPENABLE_MASK,
+	.vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT,
+	.vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT,
+	.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT,
+	.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT,
+	.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
+	.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
+	.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = {
+	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+	.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_mpu_data = {
+	.vp_common = &omap4_vp_common,
+	.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
+	.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
+	.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
+	.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = {
+	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_iva_data = {
+	.vp_common = &omap4_vp_common,
+	.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
+	.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
+	.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
+	.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
+	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_core_data = {
+	.vp_common = &omap4_vp_common,
+	.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
+	.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
+	.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
+	.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap4_vp_core_prm_irqst_data,
+};
+
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 8dc2c76..986c3bf 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -26,6 +26,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <mach/bridge-regs.h>
 #include <mach/hardware.h>
 #include <mach/orion5x.h>
 #include <plat/ehci-orion.h>
@@ -599,6 +600,11 @@ void __init orion5x_wdt_init(void)
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init orion5x_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 int orion5x_tclk;
 
 int __init orion5x_find_tclk(void)
@@ -616,7 +622,9 @@ int __init orion5x_find_tclk(void)
 static void orion5x_timer_init(void)
 {
 	orion5x_tclk = orion5x_find_tclk();
-	orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk);
+
+	orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_ORION5X_BRIDGE, orion5x_tclk);
 }
 
 struct sys_timer orion5x_timer = {
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 8f00450..f2b2b35 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -9,6 +9,7 @@ struct mv_sata_platform_data;
  * Basic Orion init functions used early by machine-setup.
  */
 void orion5x_map_io(void);
+void orion5x_init_early(void);
 void orion5x_init_irq(void);
 void orion5x_init(void);
 extern int orion5x_tclk;
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index b1c451f..4258075 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -339,6 +339,7 @@ MACHINE_START(D2NET, "LaCie d2 Network")
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
@@ -350,6 +351,7 @@ MACHINE_START(BIGDISK, "LaCie Big Disk Network")
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index df1083f..c10a117 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -361,6 +361,7 @@ MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
 	.boot_params	= 0x00000100,
 	.init_machine	= db88f5281_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index 3a7bc0e..90ab022 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -733,6 +733,7 @@ MACHINE_START(DNS323, "D-Link DNS-323")
 	.boot_params	= 0x00000100,
 	.init_machine	= dns323_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/edmini_v2-setup.c b/arch/arm/mach-orion5x/edmini_v2-setup.c
index ba98459..d037a90 100644
--- a/arch/arm/mach-orion5x/edmini_v2-setup.c
+++ b/arch/arm/mach-orion5x/edmini_v2-setup.c
@@ -254,6 +254,7 @@ MACHINE_START(EDMINI_V2, "LaCie Ethernet Disk mini V2")
 	.boot_params	= 0x00000100,
 	.init_machine	= edmini_v2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
index 5c9744c..96484bc 100644
--- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h
+++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h
@@ -22,14 +22,12 @@
 
 #define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE | 0x10c)
 
+#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x110)
+
 #define POWER_MNG_CTRL_REG	(ORION5X_BRIDGE_VIRT_BASE | 0x11C)
 
-#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x110)
 #define WDT_INT_REQ		0x0008
 
-#define BRIDGE_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define MAIN_IRQ_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x200)
diff --git a/arch/arm/mach-orion5x/include/mach/gpio.h b/arch/arm/mach-orion5x/include/mach/gpio.h
index d8182e8..a1d0b78 100644
--- a/arch/arm/mach-orion5x/include/mach/gpio.h
+++ b/arch/arm/mach-orion5x/include/mach/gpio.h
@@ -6,32 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define GPIO_MAX		32
-#define GPIO_OUT(pin)		ORION5X_DEV_BUS_REG(0x100)
-#define GPIO_IO_CONF(pin)	ORION5X_DEV_BUS_REG(0x104)
-#define GPIO_BLINK_EN(pin)	ORION5X_DEV_BUS_REG(0x108)
-#define GPIO_IN_POL(pin)	ORION5X_DEV_BUS_REG(0x10c)
-#define GPIO_DATA_IN(pin)	ORION5X_DEV_BUS_REG(0x110)
-#define GPIO_EDGE_CAUSE(pin)	ORION5X_DEV_BUS_REG(0x114)
-#define GPIO_EDGE_MASK(pin)	ORION5X_DEV_BUS_REG(0x118)
-#define GPIO_LEVEL_MASK(pin)	ORION5X_DEV_BUS_REG(0x11c)
-
-static inline int gpio_to_irq(int pin)
-{
-	return pin + IRQ_ORION5X_GPIO_START;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	return irq - IRQ_ORION5X_GPIO_START;
-}
-
-
-#endif
diff --git a/arch/arm/mach-orion5x/include/mach/memory.h b/arch/arm/mach-orion5x/include/mach/memory.h
index 52a2955..6769917 100644
--- a/arch/arm/mach-orion5x/include/mach/memory.h
+++ b/arch/arm/mach-orion5x/include/mach/memory.h
@@ -7,6 +7,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h
index 2d87665..0a28bbc 100644
--- a/arch/arm/mach-orion5x/include/mach/orion5x.h
+++ b/arch/arm/mach-orion5x/include/mach/orion5x.h
@@ -73,6 +73,7 @@
 #define ORION5X_DEV_BUS_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x10000)
 #define ORION5X_DEV_BUS_VIRT_BASE	(ORION5X_REGS_VIRT_BASE | 0x10000)
 #define ORION5X_DEV_BUS_REG(x)		(ORION5X_DEV_BUS_VIRT_BASE | (x))
+#define  GPIO_VIRT_BASE			ORION5X_DEV_BUS_REG(0x0100)
 #define  SPI_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x0600)
 #define  I2C_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x1000)
 #define  UART0_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE | 0x2000)
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index d7512b9..ed85891 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -28,27 +28,12 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 void __init orion5x_init_irq(void)
 {
-	int i;
-
 	orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts
-	 */
-	writel(0x0, GPIO_LEVEL_MASK(0));
-	writel(0x0, GPIO_EDGE_MASK(0));
-	writel(0x0, GPIO_EDGE_CAUSE(0));
-
-	/*
-	 * Register chained level handlers for GPIO IRQs by default.
-	 * User can use set_type() if he wants to use edge types handlers.
+	 * Initialize gpiolib for GPIOs 0-31.
 	 */
-	for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
+	orion_gpio_init(0, 32, GPIO_VIRT_BASE, 0, IRQ_ORION5X_GPIO_START);
 	set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
 	set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index 4be9aa0..47497c7 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -382,6 +382,7 @@ MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
 	.boot_params	= 0x00000100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
@@ -394,6 +395,7 @@ MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live")
 	.boot_params	= 0x00000100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
index 20a9b66..6ae12aa 100644
--- a/arch/arm/mach-orion5x/ls-chl-setup.c
+++ b/arch/arm/mach-orion5x/ls-chl-setup.c
@@ -321,6 +321,7 @@ MACHINE_START(LINKSTATION_LSCHL, "Buffalo Linkstation LiveV3 (LS-CHL)")
 	.boot_params	= 0x00000100,
 	.init_machine	= lschl_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index 437364b..7adafd7 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -268,6 +268,7 @@ MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL")
 	.boot_params	= 0x00000100,
 	.init_machine	= ls_hgl_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index ab9b0cf..869958f 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -270,6 +270,7 @@ MACHINE_START(LINKSTATION_MINI, "Buffalo Linkstation Mini")
 	.boot_params	= 0x00000100,
 	.init_machine	= lsmini_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c
index db485d3..2288207 100644
--- a/arch/arm/mach-orion5x/mpp.c
+++ b/arch/arm/mach-orion5x/mpp.c
@@ -124,9 +124,6 @@ void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode)
 	u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL);
 	u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL);
 
-	/* Initialize gpiolib. */
-	orion_gpio_init();
-
 	for ( ; mode->mpp >= 0; mode++) {
 		u32 *reg;
 		int num_type;
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 2f0e16c..b43b208 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -264,6 +264,7 @@ MACHINE_START(MSS2, "Maxtor Shared Storage II")
 	.boot_params	= 0x00000100,
 	.init_machine	= mss2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index b3d90f2..c55d071 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -232,6 +232,7 @@ MACHINE_START(MV2120, "HP Media Vault mv2120")
 	.boot_params	= 0x00000100,
 	.init_machine	= mv2120_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index d6665b3..429ecaf 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -422,6 +422,7 @@ MACHINE_START(NET2BIG, "LaCie 2Big Network")
 	.boot_params	= 0x00000100,
 	.init_machine	= net2big_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index f4c26fd..34310ab 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -172,6 +172,7 @@ MACHINE_START(RD88F5181L_FXO, "Marvell Orion-VoIP FXO Reference Design")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5181l_fxo_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index b594290..c1f79fa 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -184,6 +184,7 @@ MACHINE_START(RD88F5181L_GE, "Marvell Orion-VoIP GE Reference Design")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5181l_ge_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index 165ed87..67ec695 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -308,6 +308,7 @@ MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5182_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index 02ff45f..b080c69 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -126,6 +126,7 @@ MACHINE_START(RD88F6183AP_GE, "Marvell Orion-1-90 AP GE Reference Design")
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6183ap_ge_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index 4403fae..5653ee6 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -361,6 +361,7 @@ MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
 	.boot_params	= 0x00000100,
 	.init_machine	= tsp2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index 1e19612..8bbd27e 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -325,6 +325,7 @@ MACHINE_START(TS209, "QNAP TS-109/TS-209")
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts209_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index 428af20..92f393f 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -314,6 +314,7 @@ MACHINE_START(TS409, "QNAP TS-409")
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts409_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h
index 37b3d48..151e89e 100644
--- a/arch/arm/mach-orion5x/ts78xx-fpga.h
+++ b/arch/arm/mach-orion5x/ts78xx-fpga.h
@@ -1,3 +1,4 @@
+#define TS7800_FPGA_MAGIC 0x00b480
 #define FPGAID(_magic, _rev) ((_magic << 8) + _rev)
 
 /*
@@ -6,11 +7,15 @@
  */
 enum fpga_ids {
 	/* Technologic Systems */
-	TS7800_REV_1	= FPGAID(0x00b480, 0x01),
-	TS7800_REV_2	= FPGAID(0x00b480, 0x02),
-	TS7800_REV_3	= FPGAID(0x00b480, 0x03),
-	TS7800_REV_4	= FPGAID(0x00b480, 0x04),
-	TS7800_REV_5	= FPGAID(0x00b480, 0x05),
+	TS7800_REV_1	= FPGAID(TS7800_FPGA_MAGIC, 0x01),
+	TS7800_REV_2	= FPGAID(TS7800_FPGA_MAGIC, 0x02),
+	TS7800_REV_3	= FPGAID(TS7800_FPGA_MAGIC, 0x03),
+	TS7800_REV_4	= FPGAID(TS7800_FPGA_MAGIC, 0x04),
+	TS7800_REV_5	= FPGAID(TS7800_FPGA_MAGIC, 0x05),
+	TS7800_REV_6	= FPGAID(TS7800_FPGA_MAGIC, 0x06),
+	TS7800_REV_7	= FPGAID(TS7800_FPGA_MAGIC, 0x07),
+	TS7800_REV_8	= FPGAID(TS7800_FPGA_MAGIC, 0x08),
+	TS7800_REV_9	= FPGAID(TS7800_FPGA_MAGIC, 0x09),
 
 	/* Unaffordable & Expensive */
 	UAE_DUMMY	= FPGAID(0xffffff, 0x01),
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index c1c1cd0..8554707 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -191,6 +191,60 @@ static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd)
 	return readb(TS_NAND_CTRL) & 0x20;
 }
 
+static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
+			const uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	void __iomem *io_base = chip->IO_ADDR_W;
+	unsigned long off = ((unsigned long)buf & 3);
+	int sz;
+
+	if (off) {
+		sz = min_t(int, 4 - off, len);
+		writesb(io_base, buf, sz);
+		buf += sz;
+		len -= sz;
+	}
+
+	sz = len >> 2;
+	if (sz) {
+		u32 *buf32 = (u32 *)buf;
+		writesl(io_base, buf32, sz);
+		buf += sz << 2;
+		len -= sz << 2;
+	}
+
+	if (len)
+		writesb(io_base, buf, len);
+}
+
+static void ts78xx_ts_nand_read_buf(struct mtd_info *mtd,
+			uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	void __iomem *io_base = chip->IO_ADDR_R;
+	unsigned long off = ((unsigned long)buf & 3);
+	int sz;
+
+	if (off) {
+		sz = min_t(int, 4 - off, len);
+		readsb(io_base, buf, sz);
+		buf += sz;
+		len -= sz;
+	}
+
+	sz = len >> 2;
+	if (sz) {
+		u32 *buf32 = (u32 *)buf;
+		readsl(io_base, buf32, sz);
+		buf += sz << 2;
+		len -= sz << 2;
+	}
+
+	if (len)
+		readsb(io_base, buf, len);
+}
+
 const char *ts_nand_part_probes[] = { "cmdlinepart", NULL };
 
 static struct mtd_partition ts78xx_ts_nand_parts[] = {
@@ -233,6 +287,8 @@ static struct platform_nand_data ts78xx_ts_nand_data = {
 		 */
 		.cmd_ctrl		= ts78xx_ts_nand_cmd_ctrl,
 		.dev_ready		= ts78xx_ts_nand_dev_ready,
+		.write_buf		= ts78xx_ts_nand_write_buf,
+		.read_buf		= ts78xx_ts_nand_read_buf,
 	},
 };
 
@@ -334,14 +390,29 @@ static void ts78xx_fpga_supports(void)
 	case TS7800_REV_3:
 	case TS7800_REV_4:
 	case TS7800_REV_5:
+	case TS7800_REV_6:
+	case TS7800_REV_7:
+	case TS7800_REV_8:
+	case TS7800_REV_9:
 		ts78xx_fpga.supports.ts_rtc.present = 1;
 		ts78xx_fpga.supports.ts_nand.present = 1;
 		ts78xx_fpga.supports.ts_rng.present = 1;
 		break;
 	default:
-		ts78xx_fpga.supports.ts_rtc.present = 0;
-		ts78xx_fpga.supports.ts_nand.present = 0;
-		ts78xx_fpga.supports.ts_rng.present = 0;
+		/* enable devices if magic matches */
+		switch ((ts78xx_fpga.id >> 8) & 0xffffff) {
+		case TS7800_FPGA_MAGIC:
+			printk(KERN_WARNING "TS-7800 FPGA: unrecognized revision 0x%.2x\n",
+					ts78xx_fpga.id & 0xff);
+			ts78xx_fpga.supports.ts_rtc.present = 1;
+			ts78xx_fpga.supports.ts_nand.present = 1;
+			ts78xx_fpga.supports.ts_rng.present = 1;
+			break;
+		default:
+			ts78xx_fpga.supports.ts_rtc.present = 0;
+			ts78xx_fpga.supports.ts_nand.present = 0;
+			ts78xx_fpga.supports.ts_rng.present = 0;
+		}
 	}
 }
 
@@ -553,6 +624,7 @@ MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
 	.boot_params	= 0x00000100,
 	.init_machine	= ts78xx_init,
 	.map_io		= ts78xx_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 7994d6e..4e5216b 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -175,6 +175,7 @@ MACHINE_START(WNR854T, "Netgear WNR854T")
 	.boot_params	= 0x00000100,
 	.init_machine	= wnr854t_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index a5989b7..fab79d0 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -263,6 +263,7 @@ MACHINE_START(WRT350N_V2, "Linksys WRT350N v2")
 	.boot_params	= 0x00000100,
 	.init_machine	= wrt350n_v2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff --git a/arch/arm/mach-pnx4008/include/mach/memory.h b/arch/arm/mach-pnx4008/include/mach/memory.h
index 0e87700..1275db6 100644
--- a/arch/arm/mach-pnx4008/include/mach/memory.h
+++ b/arch/arm/mach-pnx4008/include/mach/memory.h
@@ -16,6 +16,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x80000000)
+#define PLAT_PHYS_OFFSET	UL(0x80000000)
 
 #endif
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index a134a14..d2af733 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -27,6 +27,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/types.h>
 #include <linux/i2c/pcf857x.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/max1586.h>
@@ -51,8 +52,6 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
@@ -829,5 +828,5 @@ MACHINE_START(BALLOON3, "Balloon3")
 	.init_irq	= balloon3_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= balloon3_init,
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index 7984268..bfca7ed 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -29,6 +29,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <linux/mfd/da903x.h>
 #include <linux/regulator/machine.h>
@@ -48,7 +49,6 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 #include <mach/audio.h>
 #include <mach/pxa3xx-u2d.h>
diff --git a/arch/arm/mach-pxa/colibri-evalboard.c b/arch/arm/mach-pxa/colibri-evalboard.c
index 28f667e..81c3c43 100644
--- a/arch/arm/mach-pxa/colibri-evalboard.c
+++ b/arch/arm/mach-pxa/colibri-evalboard.c
@@ -20,6 +20,7 @@
 #include <mach/hardware.h>
 #include <asm/mach/arch.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <mach/pxa27x.h>
 #include <mach/colibri.h>
@@ -27,8 +28,6 @@
 #include <mach/ohci.h>
 #include <mach/pxa27x-udc.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
index 07b62a0..ee79739 100644
--- a/arch/arm/mach-pxa/colibri-pxa270-income.c
+++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/sysdev.h>
 
 #include <asm/irq.h>
@@ -33,8 +34,6 @@
 #include <mach/pxa27x-udc.h>
 #include <mach/pxafb.h>
 
-#include <plat/i2c.h>
-
 #include "devices.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index a5452a3..d4e705c 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -24,6 +24,7 @@
 #include <linux/gpio.h>
 #include <linux/backlight.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/io.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -45,7 +46,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa25x.h>
-#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index a305424..0481c29 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -17,12 +17,12 @@
 #include <linux/mtd/partitions.h>
 #include <linux/sm501.h>
 #include <linux/smsc911x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
 #include <mach/mfp-pxa27x.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 4c766e3..c4bf08b 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -4,6 +4,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/pxa2xx_spi.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/pmu.h>
 #include <mach/udc.h>
@@ -16,7 +17,6 @@
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <mach/hardware.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index a78bb30..b411d7c 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -31,6 +31,7 @@
 #include <linux/apm-emulation.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/regulator/userspace-consumer.h>
 
 #include <media/soc_camera.h>
@@ -45,7 +46,6 @@
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
-#include <plat/i2c.h>
 #include <mach/camera.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index 87cec0a..93f05e0 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds-lp3944.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <media/soc_camera.h>
 
@@ -30,7 +31,6 @@
 #include <mach/pxa27x.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
-#include <plat/i2c.h>
 #include <mach/hardware.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/camera.h>
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index a908e0a..6de0ad0 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -35,6 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -42,7 +43,6 @@
 
 #include <mach/pxa27x.h>
 #include <mach/hx4700.h>
-#include <plat/i2c.h>
 #include <mach/irda.h>
 
 #include <video/platform_lcd.h>
diff --git a/arch/arm/mach-pxa/include/mach/memory.h b/arch/arm/mach-pxa/include/mach/memory.h
index 92361a6..7f68724 100644
--- a/arch/arm/mach-pxa/include/mach/memory.h
+++ b/arch/arm/mach-pxa/include/mach/memory.h
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0xa0000000)
+#define PLAT_PHYS_OFFSET	UL(0xa0000000)
 
 #if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
 void cmx2xx_pci_adjust_zones(unsigned long *size, unsigned long *holes);
diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h
index fd8360c..f15afe0 100644
--- a/arch/arm/mach-pxa/include/mach/pm.h
+++ b/arch/arm/mach-pxa/include/mach/pm.h
@@ -22,9 +22,8 @@ struct pxa_cpu_pm_fns {
 extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
 
 /* sleep.S */
-extern void pxa25x_cpu_suspend(unsigned int);
-extern void pxa27x_cpu_suspend(unsigned int);
-extern void pxa_cpu_resume(void);
+extern void pxa25x_cpu_suspend(unsigned int, long);
+extern void pxa27x_cpu_suspend(unsigned int, long);
 
 extern int pxa_pm_enter(suspend_state_t state);
 extern int pxa_pm_prepare(void);
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index ccb7bfa..87c1ed9 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -28,6 +28,7 @@
 #include <linux/leds.h>
 #include <linux/mfd/da903x.h>
 #include <linux/i2c/max732x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -45,7 +46,6 @@
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/littleton.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index 41198f0..5535991 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -28,6 +28,7 @@
 #include <linux/regulator/bq24022.h>
 #include <linux/regulator/machine.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -36,7 +37,6 @@
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index d4b6f23..f954222 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -27,6 +27,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/pwm_backlight.h>
 #include <linux/smc91x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -46,7 +47,6 @@
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index faafea3..78d98a8 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -39,6 +39,7 @@
 #include <linux/usb/gpio_vbus.h>
 #include <linux/regulator/max1586.h>
 #include <linux/slab.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -50,7 +51,6 @@
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
-#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <media/soc_camera.h>
diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index cdf7f41..b5a8fd3 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -22,8 +22,8 @@
 #include <linux/serial_8250.h>
 #include <linux/dm9000.h>
 #include <linux/gpio.h>
+#include <linux/i2c/pxa-i2c.h>
 
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include <mach/pxafb.h>
diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
index 35572c4..72adb3a 100644
--- a/arch/arm/mach-pxa/palm27x.c
+++ b/arch/arm/mach-pxa/palm27x.c
@@ -22,6 +22,7 @@
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/regulator/max1586.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -36,8 +37,6 @@
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 7bf4017..3010193 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -212,7 +212,7 @@ static unsigned long store_ptr;
 static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
 {
 	/* setup the resume_info struct for the original bootloader */
-	palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume;
+	palmz72_resume_info.resume_addr = (u32) cpu_resume;
 
 	/* Storing memory touched by ROM */
 	store_ptr = *PALMZ72_SAVE_DWORD;
diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
index 90820fa..9dbf3cc 100644
--- a/arch/arm/mach-pxa/pcm990-baseboard.c
+++ b/arch/arm/mach-pxa/pcm990-baseboard.c
@@ -23,12 +23,12 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/pwm_backlight.h>
 
 #include <media/soc_camera.h>
 
 #include <asm/gpio.h>
-#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 1807c9a..51e1583 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -67,11 +67,6 @@ int pxa_pm_enter(suspend_state_t state)
 
 EXPORT_SYMBOL_GPL(pxa_pm_enter);
 
-unsigned long sleep_phys_sp(void *sp)
-{
-	return virt_to_phys(sp);
-}
-
 static int pxa_pm_valid(suspend_state_t state)
 {
 	if (pxa_cpu_pm_fns)
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 4f0ff1a..35353af 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -23,6 +23,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/pxa2xx_spi.h>
@@ -44,7 +45,6 @@
 #include <mach/irda.h>
 #include <mach/poodle.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/hardware/locomo.h>
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index b166b1d..6bde595 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -244,7 +244,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
-		pxa25x_cpu_suspend(PWRMODE_SLEEP);
+		pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 		break;
 	}
 }
@@ -252,7 +252,7 @@ static void pxa25x_cpu_pm_enter(suspend_state_t state)
 static int pxa25x_cpu_pm_prepare(void)
 {
 	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 	return 0;
 }
 
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 987301f..1cb5d0f 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -19,6 +19,7 @@
 #include <linux/sysdev.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
@@ -32,8 +33,6 @@
 #include <mach/dma.h>
 #include <mach/smemc.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 #include "clock.h"
@@ -300,7 +299,7 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(pwrmode);
+		pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 		break;
 	}
 }
@@ -313,7 +312,7 @@ static int pxa27x_cpu_pm_valid(suspend_state_t state)
 static int pxa27x_cpu_pm_prepare(void)
 {
 	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 	return 0;
 }
 
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index a7a19e1..f374247 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -21,6 +21,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
@@ -32,7 +33,6 @@
 #include <mach/dma.h>
 #include <mach/regs-intc.h>
 #include <mach/smemc.h>
-#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -142,8 +142,7 @@ static void pxa3xx_cpu_pm_suspend(void)
 	volatile unsigned long *p = (volatile void *)0xc0000000;
 	unsigned long saved_data = *p;
 
-	extern void pxa3xx_cpu_suspend(void);
-	extern void pxa3xx_cpu_resume(void);
+	extern void pxa3xx_cpu_suspend(long);
 
 	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
 	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
@@ -161,9 +160,9 @@ static void pxa3xx_cpu_pm_suspend(void)
 	PSPR = 0x5c014000;
 
 	/* overwrite with the resume address */
-	*p = virt_to_phys(pxa3xx_cpu_resume);
+	*p = virt_to_phys(cpu_resume);
 
-	pxa3xx_cpu_suspend();
+	pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
 	*p = saved_data;
 
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index 437980f..23b229b 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
@@ -27,7 +28,6 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/regs-intc.h>
-#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 8361151..4709418 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 #include <linux/pwm_backlight.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
 #include <linux/lis3lv02d.h>
@@ -53,7 +54,6 @@
 #include <mach/ohci.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index c1ca8cb..eb83c89 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/smc91x.h>
 #include <linux/mfd/da903x.h>
 #include <linux/mtd/mtd.h>
@@ -31,7 +32,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa930.h>
-#include <plat/i2c.h>
 #include <mach/pxafb.h>
 
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/saarb.c b/arch/arm/mach-pxa/saarb.c
index e497922..9322fe5 100644
--- a/arch/arm/mach-pxa/saarb.c
+++ b/arch/arm/mach-pxa/saarb.c
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/mfd/88pm860x.h>
 
 #include <asm/mach-types.h>
@@ -24,8 +25,6 @@
 #include <mach/mfp-pxa930.h>
 #include <mach/gpio.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 
 #define SAARB_NR_IRQS	(IRQ_BOARD_START + 40)
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index c551da8..6f53688 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -22,133 +22,26 @@
 
 		.text
 
-pxa_cpu_save_cp:
-	@ get coprocessor registers
-	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
-	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mrc	p15, 0, r5, c13, c0, 0		@ PID
-	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
-	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
-
-	bic	r3, r3, #2			@ clear frequency change bit
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r10, sp
-	stmfd	sp!, {r3 - r10}
-
-	mov	pc, lr
-
-pxa_cpu_save_sp:
-	@ preserve phys address of stack
-	mov	r0, sp
-	str	lr, [sp, #-4]!
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-	ldr	pc, [sp], #4
-
 #ifdef CONFIG_PXA3xx
 /*
  * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
  *
- * NOTE:  unfortunately, pxa_cpu_save_cp can not be reused here since
- * the auxiliary control register address is different between pxa3xx
- * and pxa{25x,27x}
+ * r0 = v:p offset
  */
-
 ENTRY(pxa3xx_cpu_suspend)
 
 #ifndef CONFIG_IWMMXT
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
-
-	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
-	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mrc	p15, 0, r5, c13, c0, 0		@ PID
-	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
-	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
-
-	bic	r3, r3, #2			@ clear frequency change bit
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r10, sp
-	stmfd	sp!, {r3 - r10}
-
-	@ store physical address of stack pointer
-	mov	r0, sp
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-
-	@ clean data cache
-	bl	xsc3_flush_kern_cache_all
+	mov	r1, r0
+	ldr	r3, =pxa_cpu_resume	@ resume function
+	bl	cpu_suspend
 
 	mov	r0, #0x06		@ S2D3C4 mode
 	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
 
 20:	b	20b			@ waiting for sleep
-
-	.data
-	.align 5
-/*
- * pxa3xx_cpu_resume
- */
-
-ENTRY(pxa3xx_cpu_resume)
-
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
-	msr	cpsr_c, r0
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
-	mcr	p15, 0, r1, c7, c10, 4		@ drain write (&fill) buffer
-	mcr	p15, 0, r1, c7, c5, 4		@ flush prefetch buffer
-	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
-
-	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
-
-	@ temporarily map resume_turn_on_mmu into the page table,
-	@ otherwise prefetch abort occurs after MMU is turned on
-	mov	r1, r7
-	bic	r1, r1, #0x00ff
-	bic	r1, r1, #0x3f00
-	ldr	r2, =0x542e
-
-	adr	r3, resume_turn_on_mmu
-	mov	r3, r3, lsr #20
-	orr	r4, r2, r3, lsl #20
-	ldr	r5, [r1, r3, lsl #2]
-	str     r4, [r1, r3, lsl #2]
-
-	@ Mapping page table address in the page table
-	mov	r6, r1, lsr #20
-	orr	r7, r2, r6, lsl #20
-	ldr	r8, [r1, r6, lsl #2]
-	str	r7, [r1, r6, lsl #2]
-
-	ldr	r2, =pxa3xx_resume_after_mmu	@ absolute virtual address
-	b	resume_turn_on_mmu		@ cache align execution
-
-	.text
-pxa3xx_resume_after_mmu:
-	/* restore the temporary mapping */
-	str	r5, [r1, r3, lsl #2]
-	str	r8, [r1, r6, lsl #2]
-	b	resume_after_mmu
-
 #endif /* CONFIG_PXA3xx */
 
 #ifdef CONFIG_PXA27x
@@ -158,28 +51,23 @@ pxa3xx_resume_after_mmu:
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
+ * r1 = v:p offset
  */
-
 ENTRY(pxa27x_cpu_suspend)
 
 #ifndef CONFIG_IWMMXT
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-
-	bl	pxa_cpu_save_cp
-
-	mov	r5, r0				@ save sleep mode
-	bl	pxa_cpu_save_sp
-
-	@ clean data cache
-	bl	xscale_flush_kern_cache_all
+	mov	r4, r0				@ save sleep mode
+	ldr	r3, =pxa_cpu_resume		@ resume function
+	bl	cpu_suspend
 
 	@ Put the processor to sleep
 	@ (also workaround for sighting 28071)
 
 	@ prepare value for sleep mode
-	mov	r1, r5				@ sleep mode
+	mov	r1, r4				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -216,21 +104,16 @@ ENTRY(pxa27x_cpu_suspend)
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
+ * r1 = v:p offset
  */
 
 ENTRY(pxa25x_cpu_suspend)
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-
-	bl	pxa_cpu_save_cp
-
-	mov	r5, r0				@ save sleep mode
-	bl	pxa_cpu_save_sp
-
-	@ clean data cache
-	bl	xscale_flush_kern_cache_all
-
+	mov	r4, r0				@ save sleep mode
+	ldr	r3, =pxa_cpu_resume		@ resume function
+	bl	cpu_suspend
 	@ prepare value for sleep mode
-	mov	r1, r5				@ sleep mode
+	mov	r1, r4				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -317,53 +200,9 @@ pxa_cpu_do_suspend:
  * pxa_cpu_resume()
  *
  * entry point from bootloader into kernel during resume
- *
- * Note: Yes, part of the following code is located into the .data section.
- *       This is to allow sleep_save_sp to be accessed with a relative load
- *       while we can't rely on any MMU translation.  We could have put
- *       sleep_save_sp in the .text section as well, but some setups might
- *       insist on it to be truly read-only.
  */
-
-	.data
-	.align 5
-ENTRY(pxa_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
-	msr	cpsr_c, r0
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldr	r2, =resume_after_mmu		@ its absolute virtual address
-	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
-
-	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
-	b	resume_turn_on_mmu		@ cache align execution
-
 	.align 5
-resume_turn_on_mmu:
-	mcr 	p15, 0, r9, c1, c0, 0		@ turn on MMU, caches, etc.
-
-	@ Let us ensure we jump to resume_after_mmu only when the mcr above
-	@ actually took effect.  They call it the "cpwait" operation.
-	mrc	p15, 0, r0, c2, c0, 0		@ queue a dependency on CP15
-	sub	pc, r2, r0, lsr #32		@ jump to virtual addr
-	nop
-	nop
-	nop
-
-sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
-
-	.text
-resume_after_mmu:
+pxa_cpu_resume:
 	ldmfd	sp!, {r2, r3}
 #ifndef CONFIG_IWMMXT
 	mar	acc0, r2, r3
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index b49a2c2..38e2c09 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/leds.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -47,8 +48,6 @@
 #include <mach/sharpsl_pm.h>
 #include <mach/smemc.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 9a14fdb..cb5611d 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -25,6 +25,7 @@
 #include <linux/mtd/plat-ram.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/i2c/at24.h>
 #include <linux/smc91x.h>
@@ -43,7 +44,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
diff --git a/arch/arm/mach-pxa/tavorevb3.c b/arch/arm/mach-pxa/tavorevb3.c
index 70191a9..79f4422 100644
--- a/arch/arm/mach-pxa/tavorevb3.c
+++ b/arch/arm/mach-pxa/tavorevb3.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/gpio.h>
 #include <linux/mfd/88pm860x.h>
 
@@ -23,8 +24,6 @@
 
 #include <mach/pxa930.h>
 
-#include <plat/i2c.h>
-
 #include "devices.h"
 #include "generic.h"
 
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index f2582ec..5ad3807 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -34,6 +34,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -41,7 +42,6 @@
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/irda.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index 423261d..857bb2e 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -26,6 +26,7 @@
 #include <linux/dm9000.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -47,7 +48,6 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 #include <mach/smemc.h>
-#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 49eeeab..1227921 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -36,6 +36,7 @@
 #include <linux/gpio.h>
 #include <linux/jiffies.h>
 #include <linux/i2c-gpio.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/serial_8250.h>
 #include <linux/smc91x.h>
 #include <linux/pwm_backlight.h>
@@ -47,7 +48,6 @@
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 #include <mach/regs-uart.h>
 #include <mach/arcom-pcmcia.h>
 #include <mach/viper.h>
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index b9b5797..e709fd4 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -26,6 +26,7 @@
 #include <linux/ucb1400.h>
 #include <linux/ata_platform.h>
 #include <linux/regulator/max1586.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -40,8 +41,6 @@
 #include <mach/udc.h>
 #include <mach/pata_pxa.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index 51c0281..f55f8f2 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -16,6 +16,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/smc91x.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -26,8 +27,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include <plat/i2c.h>
-
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index a323e07..aaf8837 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -29,6 +29,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
 #include <linux/regulator/machine.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -40,8 +41,6 @@
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index f4b053b..730f51e 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -25,6 +25,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/apm-emulation.h>
 #include <linux/can/platform/mcp251x.h>
@@ -33,8 +34,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/i2c.h>
-
 #include <mach/pxa2xx-regs.h>
 #include <mach/regs-uart.h>
 #include <mach/ohci.h>
@@ -676,7 +675,7 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
 static void zeus_power_off(void)
 {
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP);
+	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 }
 #else
 #define zeus_power_off   NULL
diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c
index 3aa73b3..93c64d8 100644
--- a/arch/arm/mach-pxa/zylonite_pxa300.c
+++ b/arch/arm/mach-pxa/zylonite_pxa300.c
@@ -17,11 +17,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/gpio.h>
 
 #include <mach/pxa300.h>
-#include <plat/i2c.h>
 #include <mach/zylonite.h>
 
 #include "generic.h"
diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
index 7ca138a..b9a9805 100644
--- a/arch/arm/mach-realview/Kconfig
+++ b/arch/arm/mach-realview/Kconfig
@@ -19,7 +19,7 @@ config REALVIEW_EB_A9MP
 config REALVIEW_EB_ARM11MP
 	bool "Support ARM11MPCore Tile"
 	depends on MACH_REALVIEW_EB
-	select CPU_V6
+	select CPU_V6K
 	select ARCH_HAS_BARRIERS if SMP
 	help
 	  Enable support for the ARM11MPCore tile fitted to the Realview(R)
@@ -36,7 +36,7 @@ config REALVIEW_EB_ARM11MP_REVB
 
 config MACH_REALVIEW_PB11MP
 	bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
-	select CPU_V6
+	select CPU_V6K
 	select ARM_GIC
 	select HAVE_PATA_PLATFORM
 	select ARCH_HAS_BARRIERS if SMP
@@ -45,6 +45,7 @@ config MACH_REALVIEW_PB11MP
 	  the ARM11MPCore.  This platform has an on-board ARM11MPCore and has
 	  support for PCI-E and Compact Flash.
 
+# ARMv6 CPU without K extensions, but does have the new exclusive ops
 config MACH_REALVIEW_PB1176
 	bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
 	select CPU_V6
diff --git a/arch/arm/mach-realview/include/mach/memory.h b/arch/arm/mach-realview/include/mach/memory.h
index 5dafc15..e05fc2c 100644
--- a/arch/arm/mach-realview/include/mach/memory.h
+++ b/arch/arm/mach-realview/include/mach/memory.h
@@ -24,9 +24,9 @@
  * Physical DRAM offset.
  */
 #ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
-#define PHYS_OFFSET		UL(0x70000000)
+#define PLAT_PHYS_OFFSET		UL(0x70000000)
 #else
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 #endif
 
 #if !defined(__ASSEMBLY__) && defined(CONFIG_ZONE_DMA)
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 6ef5c5e..8ede983 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -484,7 +484,7 @@ static void __init realview_eb_init(void)
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_eb_map_io,
 	.init_irq	= gic_init_irq,
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index cbdc97a..9f26369 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -379,7 +379,7 @@ static void __init realview_pb1176_init(void)
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_pb1176_fixup,
 	.map_io		= realview_pb1176_map_io,
 	.init_irq	= gic_init_irq,
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 8e8ab7d..dea06b2 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -381,7 +381,7 @@ static void __init realview_pb11mp_init(void)
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pb11mp_map_io,
 	.init_irq	= gic_init_irq,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 841118e..7d0f173 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -331,7 +331,7 @@ static void __init realview_pba8_init(void)
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pba8_map_io,
 	.init_irq	= gic_init_irq,
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 02b755b..b89e28f 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -414,7 +414,7 @@ static void __init realview_pbx_init(void)
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_pbx_fixup,
 	.map_io		= realview_pbx_map_io,
 	.init_irq	= gic_init_irq,
diff --git a/arch/arm/mach-rpc/include/mach/memory.h b/arch/arm/mach-rpc/include/mach/memory.h
index 78191bf..18a2210 100644
--- a/arch/arm/mach-rpc/include/mach/memory.h
+++ b/arch/arm/mach-rpc/include/mach/memory.h
@@ -21,7 +21,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x10000000)
+#define PLAT_PHYS_OFFSET	UL(0x10000000)
 
 /*
  * Cache flushing area - ROM
diff --git a/arch/arm/mach-s3c2400/include/mach/memory.h b/arch/arm/mach-s3c2400/include/mach/memory.h
index cf5901f..3f33670 100644
--- a/arch/arm/mach-s3c2400/include/mach/memory.h
+++ b/arch/arm/mach-s3c2400/include/mach/memory.h
@@ -15,6 +15,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x0C000000)
+#define PLAT_PHYS_OFFSET	UL(0x0C000000)
 
 #endif
diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c
index 6b86a72..2c126bb 100644
--- a/arch/arm/mach-s3c2410/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c
@@ -18,12 +18,14 @@
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/rfkill.h>
+#include <linux/leds.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
 #include <mach/h1940-latch.h>
+#include <mach/h1940.h>
 
-#define DRV_NAME              "h1940-bt"
+#define DRV_NAME "h1940-bt"
 
 /* Bluetooth control */
 static void h1940bt_enable(int on)
@@ -37,6 +39,8 @@ static void h1940bt_enable(int on)
 		gpio_set_value(S3C2410_GPH(1), 1);
 		mdelay(10);
 		gpio_set_value(S3C2410_GPH(1), 0);
+
+		h1940_led_blink_set(-EINVAL, GPIO_LED_BLINK, NULL, NULL);
 	}
 	else {
 		gpio_set_value(S3C2410_GPH(1), 1);
@@ -44,6 +48,8 @@ static void h1940bt_enable(int on)
 		gpio_set_value(S3C2410_GPH(1), 0);
 		mdelay(10);
 		gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 0);
+
+		h1940_led_blink_set(-EINVAL, GPIO_LED_NO_BLINK_LOW, NULL, NULL);
 	}
 }
 
@@ -85,7 +91,6 @@ static int __devinit h1940bt_probe(struct platform_device *pdev)
 	s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
 	s3c_gpio_setpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
 
-
 	rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
 			&h1940bt_rfkill_ops, NULL);
 	if (!rfk) {
@@ -93,8 +98,6 @@ static int __devinit h1940bt_probe(struct platform_device *pdev)
 		goto err_rfk_alloc;
 	}
 
-	rfkill_set_led_trigger_name(rfk, "h1940-bluetooth");
-
 	ret = rfkill_register(rfk);
 	if (ret)
 		goto err_rfkill;
diff --git a/arch/arm/mach-s3c2410/include/mach/h1940.h b/arch/arm/mach-s3c2410/include/mach/h1940.h
index 4559784..2aa683c 100644
--- a/arch/arm/mach-s3c2410/include/mach/h1940.h
+++ b/arch/arm/mach-s3c2410/include/mach/h1940.h
@@ -17,5 +17,8 @@
 #define H1940_SUSPEND_CHECK		(0x30080000)
 
 extern void h1940_pm_return(void);
+extern int h1940_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off);
+
 
 #endif /* __ASM_ARCH_H1940_H */
diff --git a/arch/arm/mach-s3c2410/include/mach/memory.h b/arch/arm/mach-s3c2410/include/mach/memory.h
index 6f1e587..f92b97b 100644
--- a/arch/arm/mach-s3c2410/include/mach/memory.h
+++ b/arch/arm/mach-s3c2410/include/mach/memory.h
@@ -11,6 +11,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x30000000)
+#define PLAT_PHYS_OFFSET	UL(0x30000000)
 
 #endif
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 1a81fe1..2a2fa06 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -23,8 +23,15 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
 #include <linux/pwm_backlight.h>
 #include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/pda_power.h>
+#include <linux/s3c_adc_battery.h>
+#include <linux/delay.h>
+
 #include <video/platform_lcd.h>
 
 #include <linux/mmc/host.h>
@@ -162,29 +169,10 @@ struct gpio_chip h1940_latch_gpiochip = {
 	.get			= h1940_gpiolib_latch_get,
 };
 
-static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
-
-	switch (cmd)
-	{
-		case S3C2410_UDC_P_ENABLE :
-			gpio_set_value(H1940_LATCH_USB_DP, 1);
-			break;
-		case S3C2410_UDC_P_DISABLE :
-			gpio_set_value(H1940_LATCH_USB_DP, 0);
-			break;
-		case S3C2410_UDC_P_RESET :
-			break;
-		default:
-			break;
-	}
-}
-
 static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
-	.udc_command		= h1940_udc_pullup,
 	.vbus_pin		= S3C2410_GPG(5),
 	.vbus_pin_inverted	= 1,
+	.pullup_pin		= H1940_LATCH_USB_DP,
 };
 
 static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
@@ -222,20 +210,239 @@ static struct s3c2410fb_mach_info h1940_fb_info __initdata = {
 	.num_displays = 1,
 	.default_display = 0,
 
-	.lpcsel=	0x02,
-	.gpccon=	0xaa940659,
-	.gpccon_mask=	0xffffffff,
-	.gpcup=		0x0000ffff,
-	.gpcup_mask=	0xffffffff,
-	.gpdcon=	0xaa84aaa0,
-	.gpdcon_mask=	0xffffffff,
-	.gpdup=		0x0000faff,
-	.gpdup_mask=	0xffffffff,
+	.lpcsel =	0x02,
+	.gpccon =	0xaa940659,
+	.gpccon_mask =	0xffffc0f0,
+	.gpcup =	0x0000ffff,
+	.gpcup_mask =	0xffffffff,
+	.gpdcon =	0xaa84aaa0,
+	.gpdcon_mask =	0xffffffff,
+	.gpdup =	0x0000faff,
+	.gpdup_mask =	0xffffffff,
 };
 
-static struct platform_device h1940_device_leds = {
-	.name             = "h1940-leds",
+static int power_supply_init(struct device *dev)
+{
+	return gpio_request(S3C2410_GPF(2), "cable plugged");
+}
+
+static int h1940_is_ac_online(void)
+{
+	return !gpio_get_value(S3C2410_GPF(2));
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(S3C2410_GPF(2));
+}
+
+static char *h1940_supplicants[] = {
+	"main-battery",
+	"backup-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init			= power_supply_init,
+	.is_ac_online		= h1940_is_ac_online,
+	.exit			= power_supply_exit,
+	.supplied_to		= h1940_supplicants,
+	.num_supplicants	= ARRAY_SIZE(h1940_supplicants),
+};
+
+static struct resource power_supply_resources[] = {
+	[0] = {
+			.name	= "ac",
+			.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE |
+					  IORESOURCE_IRQ_HIGHEDGE,
+			.start	= IRQ_EINT2,
+			.end	= IRQ_EINT2,
+	},
+};
+
+static struct platform_device power_supply = {
+	.name		= "pda-power",
+	.id		= -1,
+	.dev		= {
+				.platform_data =
+					&power_supply_info,
+	},
+	.resource	= power_supply_resources,
+	.num_resources	= ARRAY_SIZE(power_supply_resources),
+};
+
+static const struct s3c_adc_bat_thresh bat_lut_noac[] = {
+	{ .volt = 4070, .cur = 162, .level = 100},
+	{ .volt = 4040, .cur = 165, .level = 95},
+	{ .volt = 4016, .cur = 164, .level = 90},
+	{ .volt = 3996, .cur = 166, .level = 85},
+	{ .volt = 3971, .cur = 168, .level = 80},
+	{ .volt = 3951, .cur = 168, .level = 75},
+	{ .volt = 3931, .cur = 170, .level = 70},
+	{ .volt = 3903, .cur = 172, .level = 65},
+	{ .volt = 3886, .cur = 172, .level = 60},
+	{ .volt = 3858, .cur = 176, .level = 55},
+	{ .volt = 3842, .cur = 176, .level = 50},
+	{ .volt = 3818, .cur = 176, .level = 45},
+	{ .volt = 3789, .cur = 180, .level = 40},
+	{ .volt = 3769, .cur = 180, .level = 35},
+	{ .volt = 3749, .cur = 184, .level = 30},
+	{ .volt = 3732, .cur = 184, .level = 25},
+	{ .volt = 3716, .cur = 184, .level = 20},
+	{ .volt = 3708, .cur = 184, .level = 15},
+	{ .volt = 3716, .cur = 96, .level = 10},
+	{ .volt = 3700, .cur = 96, .level = 5},
+	{ .volt = 3684, .cur = 96, .level = 0},
+};
+
+static const struct s3c_adc_bat_thresh bat_lut_acin[] = {
+	{ .volt = 4130, .cur = 0, .level = 100},
+	{ .volt = 3982, .cur = 0, .level = 50},
+	{ .volt = 3854, .cur = 0, .level = 10},
+	{ .volt = 3841, .cur = 0, .level = 0},
+};
+
+int h1940_bat_init(void)
+{
+	int ret;
+
+	ret = gpio_request(H1940_LATCH_SM803_ENABLE, "h1940-charger-enable");
+	if (ret)
+		return ret;
+	gpio_direction_output(H1940_LATCH_SM803_ENABLE, 0);
+
+	return 0;
+
+}
+
+void h1940_bat_exit(void)
+{
+	gpio_free(H1940_LATCH_SM803_ENABLE);
+}
+
+void h1940_enable_charger(void)
+{
+	gpio_set_value(H1940_LATCH_SM803_ENABLE, 1);
+}
+
+void h1940_disable_charger(void)
+{
+	gpio_set_value(H1940_LATCH_SM803_ENABLE, 0);
+}
+
+static struct s3c_adc_bat_pdata h1940_bat_cfg = {
+	.init = h1940_bat_init,
+	.exit = h1940_bat_exit,
+	.enable_charger = h1940_enable_charger,
+	.disable_charger = h1940_disable_charger,
+	.gpio_charge_finished = S3C2410_GPF(3),
+	.gpio_inverted = 1,
+	.lut_noac = bat_lut_noac,
+	.lut_noac_cnt = ARRAY_SIZE(bat_lut_noac),
+	.lut_acin = bat_lut_acin,
+	.lut_acin_cnt = ARRAY_SIZE(bat_lut_acin),
+	.volt_channel = 0,
+	.current_channel = 1,
+	.volt_mult = 4056,
+	.current_mult = 1893,
+	.internal_impedance = 200,
+	.backup_volt_channel = 3,
+	/* TODO Check backup volt multiplier */
+	.backup_volt_mult = 4056,
+	.backup_volt_min = 0,
+	.backup_volt_max = 4149288
+};
+
+static struct platform_device h1940_battery = {
+	.name             = "s3c-adc-battery",
 	.id               = -1,
+	.dev = {
+		.parent = &s3c_device_adc.dev,
+		.platform_data = &h1940_bat_cfg,
+	},
+};
+
+DEFINE_SPINLOCK(h1940_blink_spin);
+
+int h1940_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off)
+{
+	int blink_gpio, check_gpio1, check_gpio2;
+
+	switch (gpio) {
+	case H1940_LATCH_LED_GREEN:
+		blink_gpio = S3C2410_GPA(7);
+		check_gpio1 = S3C2410_GPA(1);
+		check_gpio2 = S3C2410_GPA(3);
+		break;
+	case H1940_LATCH_LED_RED:
+		blink_gpio = S3C2410_GPA(1);
+		check_gpio1 = S3C2410_GPA(7);
+		check_gpio2 = S3C2410_GPA(3);
+		break;
+	default:
+		blink_gpio = S3C2410_GPA(3);
+		check_gpio1 = S3C2410_GPA(1);
+		check_gpio1 = S3C2410_GPA(7);
+		break;
+	}
+
+	if (delay_on && delay_off && !*delay_on && !*delay_off)
+		*delay_on = *delay_off = 500;
+
+	spin_lock(&h1940_blink_spin);
+
+	switch (state) {
+	case GPIO_LED_NO_BLINK_LOW:
+	case GPIO_LED_NO_BLINK_HIGH:
+		if (!gpio_get_value(check_gpio1) &&
+		    !gpio_get_value(check_gpio2))
+			gpio_set_value(H1940_LATCH_LED_FLASH, 0);
+		gpio_set_value(blink_gpio, 0);
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, state);
+		break;
+	case GPIO_LED_BLINK:
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, 0);
+		gpio_set_value(H1940_LATCH_LED_FLASH, 1);
+		gpio_set_value(blink_gpio, 1);
+		break;
+	}
+
+	spin_unlock(&h1940_blink_spin);
+
+	return 0;
+}
+EXPORT_SYMBOL(h1940_led_blink_set);
+
+static struct gpio_led h1940_leds_desc[] = {
+	{
+		.name			= "Green",
+		.default_trigger	= "main-battery-full",
+		.gpio			= H1940_LATCH_LED_GREEN,
+		.retain_state_suspended	= 1,
+	},
+	{
+		.name			= "Red",
+		.default_trigger
+			= "main-battery-charging-blink-full-solid",
+		.gpio			= H1940_LATCH_LED_RED,
+		.retain_state_suspended	= 1,
+	},
+};
+
+static struct gpio_led_platform_data h1940_leds_pdata = {
+	.num_leds	= ARRAY_SIZE(h1940_leds_desc),
+	.leds		= h1940_leds_desc,
+	.gpio_blink_set	= h1940_led_blink_set,
+};
+
+static struct platform_device h1940_device_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+			.platform_data = &h1940_leds_pdata,
+	},
 };
 
 static struct platform_device h1940_device_bluetooth = {
@@ -321,14 +528,14 @@ static struct platform_device h1940_backlight = {
 static void h1940_lcd_power_set(struct plat_lcd_data *pd,
 					unsigned int power)
 {
-	int value;
+	int value, retries = 100;
 
 	if (!power) {
 		gpio_set_value(S3C2410_GPC(0), 0);
 		/* wait for 3ac */
 		do {
 			value = gpio_get_value(S3C2410_GPC(6));
-		} while (value);
+		} while (value && retries--);
 
 		gpio_set_value(H1940_LATCH_LCD_P2, 0);
 		gpio_set_value(H1940_LATCH_LCD_P3, 0);
@@ -346,6 +553,9 @@ static void h1940_lcd_power_set(struct plat_lcd_data *pd,
 		gpio_set_value(H1940_LATCH_LCD_P0, 1);
 		gpio_set_value(H1940_LATCH_LCD_P1, 1);
 
+		gpio_direction_input(S3C2410_GPC(1));
+		gpio_direction_input(S3C2410_GPC(4));
+		mdelay(10);
 		s3c_gpio_cfgpin(S3C2410_GPC(1), S3C_GPIO_SFN(2));
 		s3c_gpio_cfgpin(S3C2410_GPC(4), S3C_GPIO_SFN(2));
 
@@ -381,7 +591,44 @@ static struct i2c_board_info h1940_i2c_devices[] = {
 	},
 };
 
+#define DECLARE_BUTTON(p, k, n, w)	\
+	{				\
+		.gpio		= p,	\
+		.code		= k,	\
+		.desc		= n,	\
+		.wakeup		= w,	\
+		.active_low	= 1,	\
+	}
+
+static struct gpio_keys_button h1940_buttons[] = {
+	DECLARE_BUTTON(S3C2410_GPF(0),       KEY_POWER,          "Power", 1),
+	DECLARE_BUTTON(S3C2410_GPF(6),       KEY_ENTER,         "Select", 1),
+	DECLARE_BUTTON(S3C2410_GPF(7),      KEY_RECORD,         "Record", 0),
+	DECLARE_BUTTON(S3C2410_GPG(0),         KEY_F11,       "Calendar", 0),
+	DECLARE_BUTTON(S3C2410_GPG(2),         KEY_F12,       "Contacts", 0),
+	DECLARE_BUTTON(S3C2410_GPG(3),        KEY_MAIL,           "Mail", 0),
+	DECLARE_BUTTON(S3C2410_GPG(6),        KEY_LEFT,     "Left_arrow", 0),
+	DECLARE_BUTTON(S3C2410_GPG(7),    KEY_HOMEPAGE,           "Home", 0),
+	DECLARE_BUTTON(S3C2410_GPG(8),       KEY_RIGHT,    "Right_arrow", 0),
+	DECLARE_BUTTON(S3C2410_GPG(9),          KEY_UP,       "Up_arrow", 0),
+	DECLARE_BUTTON(S3C2410_GPG(10),       KEY_DOWN,     "Down_arrow", 0),
+};
+
+static struct gpio_keys_platform_data h1940_buttons_data = {
+	.buttons	= h1940_buttons,
+	.nbuttons	= ARRAY_SIZE(h1940_buttons),
+};
+
+static struct platform_device h1940_dev_buttons = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data  = &h1940_buttons_data,
+	}
+};
+
 static struct platform_device *h1940_devices[] __initdata = {
+	&h1940_dev_buttons,
 	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
@@ -398,6 +645,8 @@ static struct platform_device *h1940_devices[] __initdata = {
 	&h1940_lcd_powerdev,
 	&s3c_device_adc,
 	&s3c_device_ts,
+	&power_supply,
+	&h1940_battery,
 };
 
 static void __init h1940_map_io(void)
@@ -475,14 +724,20 @@ static void __init h1940_init(void)
 	gpio_direction_output(H1940_LATCH_LCD_P4, 0);
 	gpio_direction_output(H1940_LATCH_MAX1698_nSHUTDOWN, 0);
 
-	gpio_request(H1940_LATCH_USB_DP, "USB pullup");
-	gpio_direction_output(H1940_LATCH_USB_DP, 0);
-
 	gpio_request(H1940_LATCH_SD_POWER, "SD power");
 	gpio_direction_output(H1940_LATCH_SD_POWER, 0);
 
 	platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 
+	gpio_request(S3C2410_GPA(1), "Red LED blink");
+	gpio_request(S3C2410_GPA(3), "Blue LED blink");
+	gpio_request(S3C2410_GPA(7), "Green LED blink");
+	gpio_request(H1940_LATCH_LED_FLASH, "LED blink");
+	gpio_direction_output(S3C2410_GPA(1), 0);
+	gpio_direction_output(S3C2410_GPA(3), 0);
+	gpio_direction_output(S3C2410_GPA(7), 0);
+	gpio_direction_output(H1940_LATCH_LED_FLASH, 0);
+
 	i2c_register_board_info(0, h1940_i2c_devices,
 		ARRAY_SIZE(h1940_i2c_devices));
 }
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
index 271b9aa..66f4444 100644
--- a/arch/arm/mach-s3c2410/mach-n30.c
+++ b/arch/arm/mach-s3c2410/mach-n30.c
@@ -84,26 +84,10 @@ static struct s3c2410_uartcfg n30_uartcfgs[] = {
 	},
 };
 
-static void n30_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	switch (cmd) {
-	case S3C2410_UDC_P_ENABLE :
-		gpio_set_value(S3C2410_GPB(3), 1);
-		break;
-	case S3C2410_UDC_P_DISABLE :
-		gpio_set_value(S3C2410_GPB(3), 0);
-		break;
-	case S3C2410_UDC_P_RESET :
-		break;
-	default:
-		break;
-	}
-}
-
 static struct s3c2410_udc_mach_info n30_udc_cfg __initdata = {
-	.udc_command		= n30_udc_pullup,
 	.vbus_pin		= S3C2410_GPG(1),
 	.vbus_pin_inverted	= 0,
+	.pullup_pin		= S3C2410_GPB(3),
 };
 
 static struct gpio_keys_button n30_buttons[] = {
@@ -596,9 +580,6 @@ static void __init n30_init(void)
 
 		platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices));
 	}
-
-	WARN_ON(gpio_request(S3C2410_GPB(3), "udc pup"));
-	gpio_direction_output(S3C2410_GPB(3), 0);
 }
 
 MACHINE_START(N30, "Acer-N30")
diff --git a/arch/arm/mach-s3c2412/mach-smdk2413.c b/arch/arm/mach-s3c2412/mach-smdk2413.c
index 8e5758b..834cfb6 100644
--- a/arch/arm/mach-s3c2412/mach-smdk2413.c
+++ b/arch/arm/mach-s3c2412/mach-smdk2413.c
@@ -78,28 +78,9 @@ static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
 	}
 };
 
-static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
-
-	switch (cmd)
-	{
-		case S3C2410_UDC_P_ENABLE :
-			gpio_set_value(S3C2410_GPF(2), 1);
-			break;
-		case S3C2410_UDC_P_DISABLE :
-			gpio_set_value(S3C2410_GPF(2), 0);
-			break;
-		case S3C2410_UDC_P_RESET :
-			break;
-		default:
-			break;
-	}
-}
-
 
 static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
-	.udc_command		= smdk2413_udc_pullup,
+	.pullup_pin = S3C2410_GPF(2),
 };
 
 
@@ -133,9 +114,6 @@ static void __init smdk2413_machine_init(void)
 {	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 
-	WARN_ON(gpio_request(S3C2410_GPF(2), "udc pull"));
-	gpio_direction_output(S3C2410_GPF(2), 0);
-
 	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 			      S3C2410_MISCCR_USBSUSPND0 |
 			      S3C2410_MISCCR_USBSUSPND1, 0x0);
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
index 9f2c14e..0db2411 100644
--- a/arch/arm/mach-s3c2440/mach-gta02.c
+++ b/arch/arm/mach-s3c2440/mach-gta02.c
@@ -58,6 +58,9 @@
 #include <linux/mfd/pcf50633/pmic.h>
 #include <linux/mfd/pcf50633/backlight.h>
 
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -86,6 +89,8 @@
 #include <plat/udc.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
+#include <plat/ts.h>
+
 
 static struct pcf50633 *gta02_pcf;
 
@@ -280,9 +285,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
 				.always_on = 1,
 				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_DOWN1] = {
@@ -301,9 +303,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
 				.apply_uV = 1,
 				.always_on = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_HCLDO] = {
@@ -311,8 +310,8 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.min_uV = 2000000,
 				.max_uV = 3300000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-				.always_on = 1,
+				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+						REGULATOR_CHANGE_STATUS,
 			},
 		},
 		[PCF50633_REGULATOR_LDO1] = {
@@ -320,10 +319,8 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.min_uV = 3300000,
 				.max_uV = 3300000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 0,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_LDO2] = {
@@ -347,6 +344,7 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.min_uV = 3200000,
 				.max_uV = 3200000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 				.apply_uV = 1,
 			},
 		},
@@ -355,10 +353,8 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.min_uV = 3000000,
 				.max_uV = 3000000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_LDO6] = {
@@ -373,9 +369,6 @@ struct pcf50633_platform_data gta02_pcf_pdata = {
 				.min_uV = 1800000,
 				.max_uV = 1800000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 
@@ -455,28 +448,10 @@ static struct s3c2410_platform_nand __initdata gta02_nand_info = {
 };
 
 
-static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd)
-{
-	switch (cmd) {
-	case S3C2410_UDC_P_ENABLE:
-		pr_debug("%s S3C2410_UDC_P_ENABLE\n", __func__);
-		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 1);
-		break;
-	case S3C2410_UDC_P_DISABLE:
-		pr_debug("%s S3C2410_UDC_P_DISABLE\n", __func__);
-		gpio_direction_output(GTA02_GPIO_USB_PULLUP, 0);
-		break;
-	case S3C2410_UDC_P_RESET:
-		pr_debug("%s S3C2410_UDC_P_RESET\n", __func__);
-		/* FIXME: Do something here. */
-	}
-}
-
 /* Get PMU to set USB current limit accordingly. */
-static struct s3c2410_udc_mach_info gta02_udc_cfg = {
+static struct s3c2410_udc_mach_info gta02_udc_cfg __initdata = {
 	.vbus_draw	= gta02_udc_vbus_draw,
-	.udc_command	= gta02_udc_command,
-
+	.pullup_pin = GTA02_GPIO_USB_PULLUP,
 };
 
 /* USB */
@@ -489,6 +464,43 @@ static struct s3c2410_hcd_info gta02_usb_info __initdata = {
 	},
 };
 
+/* Touchscreen */
+static struct s3c2410_ts_mach_info gta02_ts_info = {
+	.delay			= 10000,
+	.presc			= 0xff, /* slow as we can go */
+	.oversampling_shift	= 2,
+};
+
+/* Buttons */
+static struct gpio_keys_button gta02_buttons[] = {
+	{
+		.gpio = GTA02_GPIO_AUX_KEY,
+		.code = KEY_PHONE,
+		.desc = "Aux",
+		.type = EV_KEY,
+		.debounce_interval = 100,
+	},
+	{
+		.gpio = GTA02_GPIO_HOLD_KEY,
+		.code = KEY_PAUSE,
+		.desc = "Hold",
+		.type = EV_KEY,
+		.debounce_interval = 100,
+	},
+};
+
+static struct gpio_keys_platform_data gta02_buttons_pdata = {
+	.buttons = gta02_buttons,
+	.nbuttons = ARRAY_SIZE(gta02_buttons),
+};
+
+static struct platform_device gta02_buttons_device = {
+	.name = "gpio-keys",
+	.id = -1,
+	.dev = {
+		.platform_data = &gta02_buttons_pdata,
+	},
+};
 
 static void __init gta02_map_io(void)
 {
@@ -509,7 +521,11 @@ static struct platform_device *gta02_devices[] __initdata = {
 	&gta02_nor_flash,
 	&s3c24xx_pwm_device,
 	&s3c_device_iis,
+	&samsung_asoc_dma,
 	&s3c_device_i2c0,
+	&gta02_buttons_device,
+	&s3c_device_adc,
+	&s3c_device_ts,
 };
 
 /* These guys DO need to be children of PMU. */
@@ -559,6 +575,7 @@ static void __init gta02_machine_init(void)
 #endif
 
 	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
+	s3c24xx_ts_set_platdata(&gta02_ts_info);
 	s3c_ohci_set_platdata(&gta02_usb_info);
 	s3c_nand_set_platdata(&gta02_nand_info);
 	s3c_i2c0_set_platdata(NULL);
@@ -567,6 +584,8 @@ static void __init gta02_machine_init(void)
 
 	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
 	pm_power_off = gta02_poweroff;
+
+	regulator_has_full_constraints();
 }
 
 
diff --git a/arch/arm/mach-s3c2440/mach-mini2440.c b/arch/arm/mach-s3c2440/mach-mini2440.c
index f62bb4c..dfedc9c 100644
--- a/arch/arm/mach-s3c2440/mach-mini2440.c
+++ b/arch/arm/mach-s3c2440/mach-mini2440.c
@@ -97,26 +97,8 @@ static struct s3c2410_uartcfg mini2440_uartcfgs[] __initdata = {
 
 /* USB device UDC support */
 
-static void mini2440_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	pr_debug("udc: pullup(%d)\n", cmd);
-
-	switch (cmd) {
-		case S3C2410_UDC_P_ENABLE :
-			gpio_set_value(S3C2410_GPC(5), 1);
-			break;
-		case S3C2410_UDC_P_DISABLE :
-			gpio_set_value(S3C2410_GPC(5), 0);
-			break;
-		case S3C2410_UDC_P_RESET :
-			break;
-		default:
-			break;
-	}
-}
-
 static struct s3c2410_udc_mach_info mini2440_udc_cfg __initdata = {
-	.udc_command		= mini2440_udc_pullup,
+	.pullup_pin = S3C2410_GPC(5),
 };
 
 
@@ -506,6 +488,11 @@ static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
 	},
 };
 
+static struct platform_device uda1340_codec = {
+		.name = "uda134x-codec",
+		.id = -1,
+};
+
 static struct platform_device *mini2440_devices[] __initdata = {
 	&s3c_device_ohci,
 	&s3c_device_wdt,
@@ -521,7 +508,9 @@ static struct platform_device *mini2440_devices[] __initdata = {
 	&s3c_device_nand,
 	&s3c_device_sdi,
 	&s3c_device_iis,
+	&uda1340_codec,
 	&mini2440_audio,
+	&samsung_asoc_dma,
 };
 
 static void __init mini2440_map_io(void)
@@ -644,10 +633,6 @@ static void __init mini2440_init(void)
 	s3c2410_gpio_setpin(S3C2410_GPB(1), 0);
 	s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
 
-	/* Make sure the D+ pullup pin is output */
-	WARN_ON(gpio_request(S3C2410_GPC(5), "udc pup"));
-	gpio_direction_output(S3C2410_GPC(5), 0);
-
 	/* mark the key as input, without pullups (there is one on the board) */
 	for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
 		s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);
diff --git a/arch/arm/mach-s3c2440/mach-rx1950.c b/arch/arm/mach-s3c2440/mach-rx1950.c
index eab6ae5..27ea950 100644
--- a/arch/arm/mach-s3c2440/mach-rx1950.c
+++ b/arch/arm/mach-s3c2440/mach-rx1950.c
@@ -263,27 +263,78 @@ void rx1950_disable_charger(void)
 	gpio_direction_output(S3C2410_GPJ(3), 0);
 }
 
+DEFINE_SPINLOCK(rx1950_blink_spin);
+
+static int rx1950_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off)
+{
+	int blink_gpio, check_gpio;
+
+	switch (gpio) {
+	case S3C2410_GPA(6):
+		blink_gpio = S3C2410_GPA(4);
+		check_gpio = S3C2410_GPA(3);
+		break;
+	case S3C2410_GPA(7):
+		blink_gpio = S3C2410_GPA(3);
+		check_gpio = S3C2410_GPA(4);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	if (delay_on && delay_off && !*delay_on && !*delay_off)
+		*delay_on = *delay_off = 500;
+
+	spin_lock(&rx1950_blink_spin);
+
+	switch (state) {
+	case GPIO_LED_NO_BLINK_LOW:
+	case GPIO_LED_NO_BLINK_HIGH:
+		if (!gpio_get_value(check_gpio))
+			gpio_set_value(S3C2410_GPJ(6), 0);
+		gpio_set_value(blink_gpio, 0);
+		gpio_set_value(gpio, state);
+		break;
+	case GPIO_LED_BLINK:
+		gpio_set_value(gpio, 0);
+		gpio_set_value(S3C2410_GPJ(6), 1);
+		gpio_set_value(blink_gpio, 1);
+		break;
+	}
+
+	spin_unlock(&rx1950_blink_spin);
+
+	return 0;
+}
+
 static struct gpio_led rx1950_leds_desc[] = {
 	{
-		.name				= "Green",
-		.default_trigger	= "main-battery-charging-or-full",
-		.gpio				= S3C2410_GPA(6),
+		.name			= "Green",
+		.default_trigger	= "main-battery-full",
+		.gpio			= S3C2410_GPA(6),
+		.retain_state_suspended	= 1,
 	},
 	{
-		.name				= "Red",
-		.default_trigger	= "main-battery-full",
-		.gpio				= S3C2410_GPA(7),
+		.name			= "Red",
+		.default_trigger
+			= "main-battery-charging-blink-full-solid",
+		.gpio			= S3C2410_GPA(7),
+		.retain_state_suspended	= 1,
 	},
 	{
-		.name				= "Blue",
+		.name			= "Blue",
 		.default_trigger	= "rx1950-acx-mem",
-		.gpio				= S3C2410_GPA(11),
+		.gpio			= S3C2410_GPA(11),
+		.retain_state_suspended	= 1,
 	},
 };
 
 static struct gpio_led_platform_data rx1950_leds_pdata = {
 	.num_leds	= ARRAY_SIZE(rx1950_leds_desc),
 	.leds		= rx1950_leds_desc,
+	.gpio_blink_set	= rx1950_led_blink_set,
 };
 
 static struct platform_device rx1950_leds = {
@@ -566,26 +617,10 @@ static struct s3c2410_platform_nand rx1950_nand_info = {
 	.sets = rx1950_nand_sets,
 };
 
-static void rx1950_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	switch (cmd) {
-	case S3C2410_UDC_P_ENABLE:
-		gpio_direction_output(S3C2410_GPJ(5), 1);
-		break;
-	case S3C2410_UDC_P_DISABLE:
-		gpio_direction_output(S3C2410_GPJ(5), 0);
-		break;
-	case S3C2410_UDC_P_RESET:
-		break;
-	default:
-		break;
-	}
-}
-
 static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
-	.udc_command = rx1950_udc_pullup,
 	.vbus_pin = S3C2410_GPG(5),
 	.vbus_pin_inverted = 1,
+	.pullup_pin = S3C2410_GPJ(5),
 };
 
 static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
@@ -750,9 +785,6 @@ static void __init rx1950_init_machine(void)
 						S3C2410_MISCCR_USBSUSPND0 |
 						S3C2410_MISCCR_USBSUSPND1, 0x0);
 
-	WARN_ON(gpio_request(S3C2410_GPJ(5), "UDC pullup"));
-	gpio_direction_output(S3C2410_GPJ(5), 0);
-
 	/* mmc power is disabled by default */
 	WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
 	gpio_direction_output(S3C2410_GPJ(1), 0);
@@ -771,6 +803,13 @@ static void __init rx1950_init_machine(void)
 
 	WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));
 
+	WARN_ON(gpio_request(S3C2410_GPA(3), "Red blink"));
+	WARN_ON(gpio_request(S3C2410_GPA(4), "Green blink"));
+	WARN_ON(gpio_request(S3C2410_GPJ(6), "LED blink"));
+	gpio_direction_output(S3C2410_GPA(3), 0);
+	gpio_direction_output(S3C2410_GPA(4), 0);
+	gpio_direction_output(S3C2410_GPJ(6), 0);
+
 	platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
 
 	i2c_register_board_info(0, rx1950_i2c_devices,
diff --git a/arch/arm/mach-s3c24a0/include/mach/memory.h b/arch/arm/mach-s3c24a0/include/mach/memory.h
index 7d74fd5..7d208a7 100644
--- a/arch/arm/mach-s3c24a0/include/mach/memory.h
+++ b/arch/arm/mach-s3c24a0/include/mach/memory.h
@@ -11,7 +11,7 @@
 #ifndef __ASM_ARCH_24A0_MEMORY_H
 #define __ASM_ARCH_24A0_MEMORY_H __FILE__
 
-#define PHYS_OFFSET UL(0x10000000)
+#define PLAT_PHYS_OFFSET UL(0x10000000)
 
 #define __virt_to_bus(x) __virt_to_phys(x)
 #define __bus_to_virt(x) __phys_to_virt(x)
diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig
index 579d2f0..e4177e2 100644
--- a/arch/arm/mach-s3c64xx/Kconfig
+++ b/arch/arm/mach-s3c64xx/Kconfig
@@ -143,6 +143,7 @@ config MACH_SMDK6410
 	select S3C_DEV_USB_HSOTG
 	select S3C_DEV_WDT
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_I2C1
@@ -231,7 +232,7 @@ config MACH_HMT
 	select S3C_DEV_NAND
 	select S3C_DEV_USB_HOST
 	select S3C64XX_SETUP_FB_24BPP
-	select HAVE_PWM
+	select SAMSUNG_DEV_PWM
 	help
 	  Machine support for the Airgoo HMT
 
@@ -249,8 +250,8 @@ config MACH_SMARTQ
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_FB_24BPP
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
-	select HAVE_PWM
 	help
 	    Shared machine support for SmartQ 5/7
 
diff --git a/arch/arm/mach-s3c64xx/cpufreq.c b/arch/arm/mach-s3c64xx/cpufreq.c
index 74c0e83..4375b97 100644
--- a/arch/arm/mach-s3c64xx/cpufreq.c
+++ b/arch/arm/mach-s3c64xx/cpufreq.c
@@ -181,7 +181,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
 }
 #endif
 
-static int __init s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
+static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
 	int ret;
 	struct cpufreq_frequency_table *freq;
diff --git a/arch/arm/mach-s3c64xx/include/mach/memory.h b/arch/arm/mach-s3c64xx/include/mach/memory.h
index 42cc54e..4760cda 100644
--- a/arch/arm/mach-s3c64xx/include/mach/memory.h
+++ b/arch/arm/mach-s3c64xx/include/mach/memory.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET     UL(0x50000000)
+#define PLAT_PHYS_OFFSET     UL(0x50000000)
 
 #define CONSISTENT_DMA_SIZE	SZ_8M
 
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index a80a316..686a4f2 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -29,6 +29,7 @@
 #include <linux/smsc911x.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
+#include <linux/pwm_backlight.h>
 
 #ifdef CONFIG_SMDK6410_WM1190_EV1
 #include <linux/mfd/wm8350/core.h>
@@ -49,6 +50,7 @@
 #include <mach/hardware.h>
 #include <mach/regs-fb.h>
 #include <mach/map.h>
+#include <mach/gpio-bank-f.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -119,7 +121,6 @@ static void smdk6410_lcd_power_set(struct plat_lcd_data *pd,
 {
 	if (power) {
 		gpio_direction_output(S3C64XX_GPF(13), 1);
-		gpio_direction_output(S3C64XX_GPF(15), 1);
 
 		/* fire nRESET on power up */
 		gpio_direction_output(S3C64XX_GPN(5), 0);
@@ -127,7 +128,6 @@ static void smdk6410_lcd_power_set(struct plat_lcd_data *pd,
 		gpio_direction_output(S3C64XX_GPN(5), 1);
 		msleep(1);
 	} else {
-		gpio_direction_output(S3C64XX_GPF(15), 0);
 		gpio_direction_output(S3C64XX_GPF(13), 0);
 	}
 }
@@ -270,6 +270,45 @@ static struct samsung_keypad_platdata smdk6410_keypad_data __initdata = {
 	.cols		= 8,
 };
 
+static int smdk6410_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S3C64XX_GPF(15), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S3C64XX_GPF15_PWM_TOUT1 */
+	s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdk6410_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_OUTPUT);
+	gpio_free(S3C64XX_GPF(15));
+}
+
+static struct platform_pwm_backlight_data smdk6410_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdk6410_backlight_init,
+	.exit		= smdk6410_backlight_exit,
+};
+
+static struct platform_device smdk6410_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[1].dev,
+		.platform_data	= &smdk6410_backlight_data,
+	},
+};
+
 static struct map_desc smdk6410_iodesc[] = {};
 
 static struct platform_device *smdk6410_devices[] __initdata = {
@@ -299,6 +338,8 @@ static struct platform_device *smdk6410_devices[] __initdata = {
 	&s3c_device_rtc,
 	&s3c_device_ts,
 	&s3c_device_wdt,
+	&s3c_device_timer[1],
+	&smdk6410_backlight_device,
 };
 
 #ifdef CONFIG_REGULATOR
@@ -694,7 +735,6 @@ static void __init smdk6410_machine_init(void)
 
 	gpio_request(S3C64XX_GPN(5), "LCD power");
 	gpio_request(S3C64XX_GPF(13), "LCD power");
-	gpio_request(S3C64XX_GPF(15), "LCD power");
 
 	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
 	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
diff --git a/arch/arm/mach-s3c64xx/sleep.S b/arch/arm/mach-s3c64xx/sleep.S
index b2ef443..afe5a76 100644
--- a/arch/arm/mach-s3c64xx/sleep.S
+++ b/arch/arm/mach-s3c64xx/sleep.S
@@ -32,25 +32,13 @@
 	 * code after resume.
 	 *
 	 * entry:
-	 *	r0 = pointer to the save block
+	 *	r1 = v:p offset
 	*/
 
 ENTRY(s3c_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
-
-	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
-	mrc	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
-	mrc	p15, 0, r8, c2, c0, 2	@ Translation Table Control
-	mrc	p15, 0, r9, c1, c0, 0	@ Control register
-	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
-
-	stmia	r0, { r4 - r13 }	@ Save CP registers and SP
-
-	@@ save our state to ram
-	bl	s3c_pm_cb_flushcache
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
 
 	@@ call final suspend code
 	ldr	r0, =pm_cpu_sleep
@@ -61,18 +49,6 @@ ENTRY(s3c_cpu_save)
 resume_with_mmu:
 	ldmfd	sp!, { r4 - r12, pc }	@ return, from sp from s3c_cpu_save
 
-	.data
-
-	/* the next bit is code, but it requires easy access to the
-	 * s3c_sleep_save_phys data before the MMU is switched on, so
-	 * we store the code that needs this variable in the .data where
-	 * the value can be written to (the .text segment is RO).
-	*/
-
-	.global	s3c_sleep_save_phys
-s3c_sleep_save_phys:
-	.word	0
-
 	/* Sleep magic, the word before the resume entry point so that the
 	 * bootloader can check for a resumeable image. */
 
@@ -110,35 +86,4 @@ ENTRY(s3c_cpu_resume)
 	orr	r0, r0, #1 << 15			@ GPN15
 	str	r0, [ r3, #S3C64XX_GPNDAT ]
 #endif
-
-	/* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
-	 * are thoroughly cleaned just in case the bootloader didn't do it
-	 * for us. */
-	mov	r0, #0
-	mcr	p15, 0, r0, c7, c14, 0		@ clean+invalidate D cache
-	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
-	mcr	p15, 0, r0, c7, c15, 0		@ clean+invalidate cache
-	mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer
-	@@mcr	p15, 0, r0, c8, c7, 0		@ invalidate I + D TLBs
-	@@mcr	p15, 0, r0, c7, c7, 0		@ Invalidate I + D caches
-
-	ldr	r0, s3c_sleep_save_phys
-	ldmia	r0, { r4 - r13 }
-
-	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
-	mcr	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
-	mcr	p15, 0, r8, c2, c0, 2	@ Translation Table Control
-	mcr	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-
-	mov	r0, #0			@ restore copro access controls
-	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
-	mcr 	p15, 0, r0, c7, c5, 4
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r9, c1, c0, 0		/* turn mmu back on */
-	nop
-	mov	pc, r2				/* jump back */
-
-	.end
+	b	cpu_resume
diff --git a/arch/arm/mach-s5p6442/include/mach/memory.h b/arch/arm/mach-s5p6442/include/mach/memory.h
index 9ddd877..cfe259d 100644
--- a/arch/arm/mach-s5p6442/include/mach/memory.h
+++ b/arch/arm/mach-s5p6442/include/mach/memory.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #define CONSISTENT_DMA_SIZE	SZ_8M
 
 #endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p64x0/Kconfig b/arch/arm/mach-s5p64x0/Kconfig
index 164d278..017af4c 100644
--- a/arch/arm/mach-s5p64x0/Kconfig
+++ b/arch/arm/mach-s5p64x0/Kconfig
@@ -10,12 +10,14 @@ if ARCH_S5P64X0
 config CPU_S5P6440
 	bool
 	select S3C_PL330_DMA
+	select S5P_HRT
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
 	select S3C_PL330_DMA
+	select S5P_HRT
 	help
 	  Enable S5P6450 CPU support
 
@@ -34,6 +36,7 @@ config MACH_SMDK6440
 	select S3C_DEV_WDT
 	select S3C64XX_DEV_SPI
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5P64X0_SETUP_I2C1
 	help
@@ -47,6 +50,7 @@ config MACH_SMDK6450
 	select S3C_DEV_WDT
 	select S3C64XX_DEV_SPI
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5P64X0_SETUP_I2C1
 	help
diff --git a/arch/arm/mach-s5p64x0/include/mach/memory.h b/arch/arm/mach-s5p64x0/include/mach/memory.h
index 1b036b0..365a6eb 100644
--- a/arch/arm/mach-s5p64x0/include/mach/memory.h
+++ b/arch/arm/mach-s5p64x0/include/mach/memory.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H __FILE__
 
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #define CONSISTENT_DMA_SIZE	SZ_8M
 
 #endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index e5beb84..2d559f1 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -32,6 +33,7 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/i2c.h>
+#include <mach/regs-gpio.h>
 
 #include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
@@ -43,6 +45,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <plat/ts.h>
+#include <plat/s5p-time.h>
 
 #define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -88,6 +91,45 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
 	},
 };
 
+static int smdk6440_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5P6440_GPF(15), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5P6440_GPF15_PWM_TOUT1 */
+	s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdk6440_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_OUTPUT);
+	gpio_free(S5P6440_GPF(15));
+}
+
+static struct platform_pwm_backlight_data smdk6440_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdk6440_backlight_init,
+	.exit		= smdk6440_backlight_exit,
+};
+
+static struct platform_device smdk6440_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[1].dev,
+		.platform_data	= &smdk6440_backlight_data,
+	},
+};
+
 static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -97,6 +139,8 @@ static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6440_device_iis,
+	&s3c_device_timer[1],
+	&smdk6440_backlight_device,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -136,6 +180,7 @@ static void __init smdk6440_map_io(void)
 	s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init smdk6440_machine_init(void)
@@ -159,5 +204,5 @@ MACHINE_START(SMDK6440, "SMDK6440")
 	.init_irq	= s5p6440_init_irq,
 	.map_io		= smdk6440_map_io,
 	.init_machine	= smdk6440_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index 3a20de0..d19c469 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -32,6 +33,7 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/i2c.h>
+#include <mach/regs-gpio.h>
 
 #include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
@@ -43,6 +45,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <plat/ts.h>
+#include <plat/s5p-time.h>
 
 #define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -106,6 +109,45 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
 #endif
 };
 
+static int smdk6450_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5P6450_GPF(15), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5P6450_GPF15_PWM_TOUT1 */
+	s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdk6450_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_OUTPUT);
+	gpio_free(S5P6450_GPF(15));
+}
+
+static struct platform_pwm_backlight_data smdk6450_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdk6450_backlight_init,
+	.exit		= smdk6450_backlight_exit,
+};
+
+static struct platform_device smdk6450_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[1].dev,
+		.platform_data	= &smdk6450_backlight_data,
+	},
+};
+
 static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -115,6 +157,8 @@ static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6450_device_iis0,
+	&s3c_device_timer[1],
+	&smdk6450_backlight_device,
 	/* s5p6450_device_spi0 will be added */
 };
 
@@ -155,6 +199,7 @@ static void __init smdk6450_map_io(void)
 	s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
 	s3c24xx_init_clocks(19200000);
 	s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init smdk6450_machine_init(void)
@@ -178,5 +223,5 @@ MACHINE_START(SMDK6450, "SMDK6450")
 	.init_irq	= s5p6450_init_irq,
 	.map_io		= smdk6450_map_io,
 	.init_machine	= smdk6450_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5pc100/Kconfig b/arch/arm/mach-s5pc100/Kconfig
index b8fbf2f..608722f 100644
--- a/arch/arm/mach-s5pc100/Kconfig
+++ b/arch/arm/mach-s5pc100/Kconfig
@@ -58,6 +58,7 @@ config MACH_SMDKC100
 	select SAMSUNG_DEV_ADC
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5PC100_SETUP_FB_24BPP
 	select S5PC100_SETUP_I2C1
diff --git a/arch/arm/mach-s5pc100/gpiolib.c b/arch/arm/mach-s5pc100/gpiolib.c
index 20856eb..2842394 100644
--- a/arch/arm/mach-s5pc100/gpiolib.c
+++ b/arch/arm/mach-s5pc100/gpiolib.c
@@ -348,6 +348,7 @@ static __init int s5pc100_gpiolib_init(void)
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 
 	return 0;
 }
diff --git a/arch/arm/mach-s5pc100/include/mach/memory.h b/arch/arm/mach-s5pc100/include/mach/memory.h
index 4b60d18..bda4e79 100644
--- a/arch/arm/mach-s5pc100/include/mach/memory.h
+++ b/arch/arm/mach-s5pc100/include/mach/memory.h
@@ -13,6 +13,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET     	UL(0x20000000)
+#define PLAT_PHYS_OFFSET     	UL(0x20000000)
 
 #endif
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index dd192a2..0525cb3 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -23,12 +23,15 @@
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include <mach/map.h>
 #include <mach/regs-fb.h>
+#include <mach/regs-gpio.h>
+
 #include <video/platform_lcd.h>
 
 #include <asm/irq.h>
@@ -107,9 +110,6 @@ static struct i2c_board_info i2c_devs1[] __initdata = {
 static void smdkc100_lcd_power_set(struct plat_lcd_data *pd,
 				   unsigned int power)
 {
-	/* backlight */
-	gpio_direction_output(S5PC100_GPD(0), power);
-
 	if (power) {
 		/* module reset */
 		gpio_direction_output(S5PC100_GPH0(6), 1);
@@ -179,6 +179,45 @@ static struct samsung_keypad_platdata smdkc100_keypad_data __initdata = {
 	.cols		= 8,
 };
 
+static int smdkc100_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5PC100_GPD(0), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT0\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5PC100_GPD_TOUT_0 */
+	s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdkc100_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_OUTPUT);
+	gpio_free(S5PC100_GPD(0));
+}
+
+static struct platform_pwm_backlight_data smdkc100_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdkc100_backlight_init,
+	.exit		= smdkc100_backlight_exit,
+};
+
+static struct platform_device smdkc100_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[0].dev,
+		.platform_data	= &smdkc100_backlight_data,
+	},
+};
+
 static struct platform_device *smdkc100_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_cfcon,
@@ -200,6 +239,8 @@ static struct platform_device *smdkc100_devices[] __initdata = {
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
 	&s5pc100_device_spdif,
+	&s3c_device_timer[0],
+	&smdkc100_backlight_device,
 };
 
 static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
@@ -233,7 +274,6 @@ static void __init smdkc100_machine_init(void)
 	s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD);
 
 	/* LCD init */
-	gpio_request(S5PC100_GPD(0), "GPD");
 	gpio_request(S5PC100_GPH0(6), "GPH0");
 	smdkc100_lcd_power_set(&smdkc100_lcd_power_data, 0);
 	platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
diff --git a/arch/arm/mach-s5pv210/Kconfig b/arch/arm/mach-s5pv210/Kconfig
index 53aabef..37b5a97 100644
--- a/arch/arm/mach-s5pv210/Kconfig
+++ b/arch/arm/mach-s5pv210/Kconfig
@@ -13,6 +13,7 @@ config CPU_S5PV210
 	bool
 	select S3C_PL330_DMA
 	select S5P_EXT_INT
+	select S5P_HRT
 	select S5PV210_PM if PM
 	help
 	  Enable S5PV210 CPU support
@@ -53,6 +54,11 @@ config S5PV210_SETUP_SDHCI_GPIO
 	help
 	  Common setup code for SDHCI gpio.
 
+config S5PV210_SETUP_FIMC
+	bool
+	help
+	  Common setup code for the camera interfaces.
+
 menu "S5PC110 Machines"
 
 config MACH_AQUILA
@@ -130,6 +136,7 @@ config MACH_SMDKV210
 	select SAMSUNG_DEV_ADC
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_I2C1
diff --git a/arch/arm/mach-s5pv210/Makefile b/arch/arm/mach-s5pv210/Makefile
index ff1a0db..11f1790 100644
--- a/arch/arm/mach-s5pv210/Makefile
+++ b/arch/arm/mach-s5pv210/Makefile
@@ -31,6 +31,7 @@ obj-y				+= dev-audio.o
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
 
 obj-$(CONFIG_S5PV210_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC)	+= setup-fimc.o
 obj-$(CONFIG_S5PV210_SETUP_I2C1) 	+= setup-i2c1.o
 obj-$(CONFIG_S5PV210_SETUP_I2C2) 	+= setup-i2c2.o
 obj-$(CONFIG_S5PV210_SETUP_IDE)		+= setup-ide.o
diff --git a/arch/arm/mach-s5pv210/cpufreq.c b/arch/arm/mach-s5pv210/cpufreq.c
index a6f2292..22046e2 100644
--- a/arch/arm/mach-s5pv210/cpufreq.c
+++ b/arch/arm/mach-s5pv210/cpufreq.c
@@ -390,8 +390,7 @@ static int s5pv210_target(struct cpufreq_policy *policy,
 }
 
 #ifdef CONFIG_PM
-static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy,
-				   pm_message_t pmsg)
+static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	return 0;
 }
diff --git a/arch/arm/mach-s5pv210/gpiolib.c b/arch/arm/mach-s5pv210/gpiolib.c
index ab673ef..1ba20a7 100644
--- a/arch/arm/mach-s5pv210/gpiolib.c
+++ b/arch/arm/mach-s5pv210/gpiolib.c
@@ -281,6 +281,7 @@ static __init int s5pv210_gpiolib_init(void)
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 
 	return 0;
 }
diff --git a/arch/arm/mach-s5pv210/include/mach/memory.h b/arch/arm/mach-s5pv210/include/mach/memory.h
index d503e0c..7b5fcf0 100644
--- a/arch/arm/mach-s5pv210/include/mach/memory.h
+++ b/arch/arm/mach-s5pv210/include/mach/memory.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #define CONSISTENT_DMA_SIZE	(SZ_8M + SZ_4M + SZ_2M)
 
 /*
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 4c45b74..78925c5 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -146,6 +146,10 @@
 #define S5P_OM_STAT		S5P_CLKREG(0xE100)
 #define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
 #define S5P_DAC_CONTROL		S5P_CLKREG(0xE810)
+#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
+#define S5P_MIPI_DPHY_ENABLE	(1 << 0)
+#define S5P_MIPI_DPHY_SRESETN	(1 << 1)
+#define S5P_MIPI_DPHY_MRESETN	(1 << 2)
 
 #define S5P_INFORM0		S5P_CLKREG(0xF000)
 #define S5P_INFORM1		S5P_CLKREG(0xF004)
@@ -161,7 +165,6 @@
 #define S5P_MDNIE_SEL		S5P_CLKREG(0x7008)
 #define S5P_MIPI_PHY_CON0	S5P_CLKREG(0x7200)
 #define S5P_MIPI_PHY_CON1	S5P_CLKREG(0x7204)
-#define S5P_MIPI_DPHY_CONTROL	S5P_CLKREG(0xE814)
 
 #define S5P_IDLE_CFG_TL_MASK	(3 << 30)
 #define S5P_IDLE_CFG_TM_MASK	(3 << 28)
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 557add4..4e1d8ff 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -39,6 +39,7 @@
 #include <plat/fb.h>
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define AQUILA_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -296,13 +297,11 @@ static struct regulator_init_data aquila_ldo17_data = {
 };
 
 /* BUCK */
-static struct regulator_consumer_supply buck1_consumer[] = {
-	{	.supply	= "vddarm", },
-};
+static struct regulator_consumer_supply buck1_consumer =
+	REGULATOR_SUPPLY("vddarm", NULL);
 
-static struct regulator_consumer_supply buck2_consumer[] = {
-	{	.supply	= "vddint", },
-};
+static struct regulator_consumer_supply buck2_consumer =
+	REGULATOR_SUPPLY("vddint", NULL);
 
 static struct regulator_init_data aquila_buck1_data = {
 	.constraints	= {
@@ -313,8 +312,8 @@ static struct regulator_init_data aquila_buck1_data = {
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck1_consumer),
-	.consumer_supplies	= buck1_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck1_consumer,
 };
 
 static struct regulator_init_data aquila_buck2_data = {
@@ -326,8 +325,8 @@ static struct regulator_init_data aquila_buck2_data = {
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck2_consumer),
-	.consumer_supplies	= buck2_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck2_consumer,
 };
 
 static struct regulator_init_data aquila_buck3_data = {
@@ -391,26 +390,14 @@ static struct max8998_platform_data aquila_max8998_pdata = {
 #endif
 
 static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "DBVDD",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "AVDD2",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "CPVDD",
-	},
+	REGULATOR_SUPPLY("DBVDD", "5-001a"),
+	REGULATOR_SUPPLY("AVDD2", "5-001a"),
+	REGULATOR_SUPPLY("CPVDD", "5-001a"),
 };
 
 static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD1",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD2",
-	},
+	REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
+	REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
 };
 
 static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
@@ -459,15 +446,11 @@ static struct platform_device wm8994_fixed_voltage1 = {
 	},
 };
 
-static struct regulator_consumer_supply wm8994_avdd1_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "AVDD1",
-};
+static struct regulator_consumer_supply wm8994_avdd1_supply =
+	REGULATOR_SUPPLY("AVDD1", "5-001a");
 
-static struct regulator_consumer_supply wm8994_dcvdd_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "DCVDD",
-};
+static struct regulator_consumer_supply wm8994_dcvdd_supply =
+	REGULATOR_SUPPLY("DCVDD", "5-001a");
 
 static struct regulator_init_data wm8994_ldo1_data = {
 	.constraints	= {
@@ -664,6 +647,7 @@ static void __init aquila_map_io(void)
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init aquila_machine_init(void)
@@ -698,5 +682,5 @@ MACHINE_START(AQUILA, "Aquila")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= aquila_map_io,
 	.init_machine	= aquila_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 056f5c7..31d5aa7 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -15,7 +15,7 @@
 #include <linux/fb.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
-#include <linux/i2c/qt602240_ts.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/mfd/max8998.h>
 #include <linux/mfd/wm8994/pdata.h>
 #include <linux/regulator/fixed.h>
@@ -25,6 +25,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -45,6 +46,7 @@
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/clock.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -108,6 +110,8 @@ static struct s3c_fb_pd_win goni_fb_win0 = {
 	},
 	.max_bpp	= 32,
 	.default_bpp	= 16,
+	.virtual_x	= 480,
+	.virtual_y	= 2 * 800,
 };
 
 static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
@@ -222,7 +226,7 @@ static void __init goni_radio_init(void)
 }
 
 /* TSP */
-static struct qt602240_platform_data qt602240_platform_data = {
+static struct mxt_platform_data qt602240_platform_data = {
 	.x_line		= 17,
 	.y_line		= 11,
 	.x_size		= 800,
@@ -230,7 +234,8 @@ static struct qt602240_platform_data qt602240_platform_data = {
 	.blen		= 0x21,
 	.threshold	= 0x28,
 	.voltage	= 2800000,              /* 2.8V */
-	.orient		= QT602240_DIAGONAL,
+	.orient		= MXT_DIAGONAL,
+	.irqflags	= IRQF_TRIGGER_FALLING,
 };
 
 static struct s3c2410_platform_i2c i2c2_data __initdata = {
@@ -269,10 +274,30 @@ static void __init goni_tsp_init(void)
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
+static struct regulator_consumer_supply goni_ldo3_consumers[] = {
+	REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
+};
+
 static struct regulator_consumer_supply goni_ldo5_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
 };
 
+static struct regulator_consumer_supply goni_ldo8_consumers[] = {
+	REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+};
+
+static struct regulator_consumer_supply goni_ldo11_consumers[] = {
+	REGULATOR_SUPPLY("vddio", "0-0030"), /* "CAM_IO_2.8V" */
+};
+
+static struct regulator_consumer_supply goni_ldo13_consumers[] = {
+	REGULATOR_SUPPLY("vdda", "0-0030"), /* "CAM_A_2.8V" */
+};
+
+static struct regulator_consumer_supply goni_ldo14_consumers[] = {
+	REGULATOR_SUPPLY("vdd_core", "0-0030"), /* "CAM_CIF_1.8V" */
+};
+
 static struct regulator_init_data goni_ldo2_data = {
 	.constraints	= {
 		.name		= "VALIVE_1.1V",
@@ -292,8 +317,10 @@ static struct regulator_init_data goni_ldo3_data = {
 		.min_uV		= 1100000,
 		.max_uV		= 1100000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies = ARRAY_SIZE(goni_ldo3_consumers),
+	.consumer_supplies = goni_ldo3_consumers,
 };
 
 static struct regulator_init_data goni_ldo4_data = {
@@ -311,6 +338,7 @@ static struct regulator_init_data goni_ldo5_data = {
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
 	.num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
 	.consumer_supplies = goni_ldo5_consumers,
@@ -341,8 +369,10 @@ static struct regulator_init_data goni_ldo8_data = {
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies = ARRAY_SIZE(goni_ldo8_consumers),
+	.consumer_supplies = goni_ldo8_consumers,
 };
 
 static struct regulator_init_data goni_ldo9_data = {
@@ -351,7 +381,6 @@ static struct regulator_init_data goni_ldo9_data = {
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -371,8 +400,10 @@ static struct regulator_init_data goni_ldo11_data = {
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo11_consumers),
+	.consumer_supplies	= goni_ldo11_consumers,
 };
 
 static struct regulator_init_data goni_ldo12_data = {
@@ -381,7 +412,6 @@ static struct regulator_init_data goni_ldo12_data = {
 		.min_uV		= 1200000,
 		.max_uV		= 1200000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -391,8 +421,10 @@ static struct regulator_init_data goni_ldo13_data = {
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo13_consumers),
+	.consumer_supplies	= goni_ldo13_consumers,
 };
 
 static struct regulator_init_data goni_ldo14_data = {
@@ -401,8 +433,10 @@ static struct regulator_init_data goni_ldo14_data = {
 		.min_uV		= 1800000,
 		.max_uV		= 1800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo14_consumers),
+	.consumer_supplies	= goni_ldo14_consumers,
 };
 
 static struct regulator_init_data goni_ldo15_data = {
@@ -411,7 +445,6 @@ static struct regulator_init_data goni_ldo15_data = {
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -421,7 +454,6 @@ static struct regulator_init_data goni_ldo16_data = {
 		.min_uV		= 1800000,
 		.max_uV		= 1800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -436,13 +468,11 @@ static struct regulator_init_data goni_ldo17_data = {
 };
 
 /* BUCK */
-static struct regulator_consumer_supply buck1_consumer[] = {
-	{	.supply	= "vddarm", },
-};
+static struct regulator_consumer_supply buck1_consumer =
+	REGULATOR_SUPPLY("vddarm", NULL);
 
-static struct regulator_consumer_supply buck2_consumer[] = {
-	{	.supply	= "vddint", },
-};
+static struct regulator_consumer_supply buck2_consumer =
+	REGULATOR_SUPPLY("vddint", NULL);
 
 static struct regulator_init_data goni_buck1_data = {
 	.constraints	= {
@@ -453,8 +483,8 @@ static struct regulator_init_data goni_buck1_data = {
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck1_consumer),
-	.consumer_supplies	= buck1_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck1_consumer,
 };
 
 static struct regulator_init_data goni_buck2_data = {
@@ -466,8 +496,8 @@ static struct regulator_init_data goni_buck2_data = {
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck2_consumer),
-	.consumer_supplies	= buck2_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck2_consumer,
 };
 
 static struct regulator_init_data goni_buck3_data = {
@@ -531,26 +561,14 @@ static struct max8998_platform_data goni_max8998_pdata = {
 #endif
 
 static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "DBVDD",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "AVDD2",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "CPVDD",
-	},
+	REGULATOR_SUPPLY("DBVDD", "5-001a"),
+	REGULATOR_SUPPLY("AVDD2", "5-001a"),
+	REGULATOR_SUPPLY("CPVDD", "5-001a"),
 };
 
 static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD1",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD2",
-	},
+	REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
+	REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
 };
 
 static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
@@ -599,15 +617,11 @@ static struct platform_device wm8994_fixed_voltage1 = {
 	},
 };
 
-static struct regulator_consumer_supply wm8994_avdd1_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "AVDD1",
-};
+static struct regulator_consumer_supply wm8994_avdd1_supply =
+	REGULATOR_SUPPLY("AVDD1", "5-001a");
 
-static struct regulator_consumer_supply wm8994_dcvdd_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "DCVDD",
-};
+static struct regulator_consumer_supply wm8994_dcvdd_supply =
+	REGULATOR_SUPPLY("DCVDD", "5-001a");
 
 static struct regulator_init_data wm8994_ldo1_data = {
 	.constraints	= {
@@ -794,6 +808,7 @@ static struct platform_device *goni_devices[] __initdata = {
 	&goni_i2c_gpio5,
 	&mmc2_fixed_voltage,
 	&goni_device_gpiokeys,
+	&s3c_device_i2c0,
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
@@ -823,6 +838,7 @@ static void __init goni_map_io(void)
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init goni_machine_init(void)
@@ -830,6 +846,9 @@ static void __init goni_machine_init(void)
 	/* Radio: call before I2C 1 registeration */
 	goni_radio_init();
 
+	/* I2C0 */
+	s3c_i2c0_set_platdata(NULL);
+
 	/* I2C1 */
 	s3c_i2c1_set_platdata(NULL);
 	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
@@ -873,5 +892,5 @@ MACHINE_START(GONI, "GONI")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index ce11a02..6c412c8 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -30,6 +30,7 @@
 #include <plat/ata.h>
 #include <plat/iic.h>
 #include <plat/pm.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKC110_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -111,6 +112,7 @@ static void __init smdkc110_map_io(void)
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init smdkc110_machine_init(void)
@@ -138,5 +140,5 @@ MACHINE_START(SMDKC110, "SMDKC110")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkc110_map_io,
 	.init_machine	= smdkc110_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index bc9fdb5..bc08ac4 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -18,6 +18,7 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -43,6 +44,8 @@
 #include <plat/keypad.h>
 #include <plat/pm.h>
 #include <plat/fb.h>
+#include <plat/gpio-cfg.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -208,6 +211,45 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
 	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
 };
 
+static int smdkv210_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5PV210_GPD0(3), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPD for PWM-OUT 3\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5PV210_GPD_0_3_TOUT_3 */
+	s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdkv210_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_OUTPUT);
+	gpio_free(S5PV210_GPD0(3));
+}
+
+static struct platform_pwm_backlight_data smdkv210_backlight_data = {
+	.pwm_id		= 3,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdkv210_backlight_init,
+	.exit		= smdkv210_backlight_exit,
+};
+
+static struct platform_device smdkv210_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[3].dev,
+		.platform_data	= &smdkv210_backlight_data,
+	},
+};
+
 static struct platform_device *smdkv210_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_cfcon,
@@ -229,6 +271,8 @@ static struct platform_device *smdkv210_devices[] __initdata = {
 	&samsung_device_keypad,
 	&smdkv210_dm9000,
 	&smdkv210_lcd_lte480wv,
+	&s3c_device_timer[3],
+	&smdkv210_backlight_device,
 };
 
 static void __init smdkv210_dm9000_init(void)
@@ -272,6 +316,7 @@ static void __init smdkv210_map_io(void)
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
+	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
 
 static void __init smdkv210_machine_init(void)
@@ -306,5 +351,5 @@ MACHINE_START(SMDKV210, "SMDKV210")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkv210_map_io,
 	.init_machine	= smdkv210_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
index 043c938..925fc0d 100644
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -27,6 +27,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/iic.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define TORBRECK_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -104,6 +105,7 @@ static void __init torbreck_map_io(void)
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init torbreck_machine_init(void)
@@ -127,5 +129,5 @@ MACHINE_START(TORBRECK, "TORBRECK")
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= torbreck_map_io,
 	.init_machine	= torbreck_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/setup-fimc.c b/arch/arm/mach-s5pv210/setup-fimc.c
new file mode 100644
index 0000000..54cc5b1
--- /dev/null
+++ b/arch/arm/mach-s5pv210/setup-fimc.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5PV210 camera interface GPIO configuration.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gpio.h>
+#include <plat/gpio-cfg.h>
+#include <plat/camport.h>
+
+int s5pv210_fimc_setup_gpio(enum s5p_camport_id id)
+{
+	u32 gpio8, gpio5;
+	int ret;
+
+	switch (id) {
+	case S5P_CAMPORT_A:
+		gpio8 = S5PV210_GPE0(0);
+		gpio5 = S5PV210_GPE1(0);
+		break;
+
+	case S5P_CAMPORT_B:
+		gpio8 = S5PV210_GPJ0(0);
+		gpio5 = S5PV210_GPJ1(0);
+		break;
+
+	default:
+		WARN(1, "Wrong camport id: %d\n", id);
+		return -EINVAL;
+	}
+
+	ret = s3c_gpio_cfgall_range(gpio8, 8, S3C_GPIO_SFN(2),
+				    S3C_GPIO_PULL_UP);
+	if (ret)
+		return ret;
+
+	return s3c_gpio_cfgall_range(gpio5, 5, S3C_GPIO_SFN(2),
+				     S3C_GPIO_PULL_UP);
+}
diff --git a/arch/arm/mach-s5pv210/sleep.S b/arch/arm/mach-s5pv210/sleep.S
index d4d222b..a3d6494 100644
--- a/arch/arm/mach-s5pv210/sleep.S
+++ b/arch/arm/mach-s5pv210/sleep.S
@@ -35,50 +35,24 @@
 	/* s3c_cpu_save
 	 *
 	 * entry:
-	 *	r0 = save address (virtual addr of s3c_sleep_save_phys)
+	 *	r1 = v:p offset
 	*/
 
 ENTRY(s3c_cpu_save)
 
 	stmfd	sp!, { r3 - r12, lr }
-
-	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
-	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ Translation Table BASE0
-	mrc	p15, 0, r7, c2, c0, 1	@ Translation Table BASE1
-	mrc	p15, 0, r8, c2, c0, 2	@ Translation Table Control
-	mrc	p15, 0, r9, c1, c0, 0	@ Control register
-	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
-	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access controls
-	mrc	p15, 0, r12, c10, c2, 0	@ Read PRRR
-	mrc	p15, 0, r3, c10, c2, 1	@ READ NMRR
-
-	stmia	r0, { r3 - r13 }
-
-	bl	s3c_pm_cb_flushcache
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
 
 	ldr	r0, =pm_cpu_sleep
 	ldr	r0, [ r0 ]
 	mov	pc, r0
 
 resume_with_mmu:
-	/*
-	 * After MMU is turned on, restore the previous MMU table.
-	 */
-	ldr	r9 , =(PAGE_OFFSET - PHYS_OFFSET)
-	add	r4, r4, r9
-	str	r12, [r4]
-
 	ldmfd	sp!, { r3 - r12, pc }
 
 	.ltorg
 
-	.data
-
-	.global	s3c_sleep_save_phys
-s3c_sleep_save_phys:
-	.word	0
-
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
@@ -96,75 +70,4 @@ s3c_sleep_save_phys:
 	*/
 
 ENTRY(s3c_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
-	msr	cpsr_c, r0
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0		@ invalidate TLBs
-	mcr	p15, 0, r1, c7, c5, 0		@ invalidate I Cache
-
-	ldr	r0, s3c_sleep_save_phys		@ address of restore block
-	ldmia	r0, { r3 - r13 }
-
-	mcr	p15, 0, r4, c13, c0, 0		@ FCSE/PID
-	mcr	p15, 0, r5, c3, c0, 0		@ Domain ID
-
-	mcr	p15, 0, r8, c2, c0, 2		@ Translation Table Control
-	mcr	p15, 0, r7, c2, c0, 1		@ Translation Table BASE1
-	mcr	p15, 0, r6, c2, c0, 0		@ Translation Table BASE0
-
-	mcr	p15, 0, r10, c1, c0, 1		@ Auxiliary control register
-
-	mov	r0, #0
-	mcr	p15, 0, r0, c8, c7, 0		@ Invalidate I & D TLB
-
-	mov	r0, #0				@ restore copro access
-	mcr	p15, 0, r11, c1, c0, 2		@ Co-processor access
-	mcr 	p15, 0, r0, c7, c5, 4
-
-	mcr	p15, 0, r12, c10, c2, 0		@ write PRRR
-	mcr	p15, 0, r3, c10, c2, 1		@ write NMRR
-
-	/*
-	 * In Cortex-A8, when MMU is turned on, the pipeline is flushed.
-	 * And there are no valid entries in the MMU table at this point.
-	 * So before turning on the MMU, the MMU entry for the DRAM address
-	 * range is added. After the MMU is turned on, the other entries
-	 * in the MMU table will be restored.
-	*/
-
-	/* r6 = Translation Table BASE0 */
-	mov	r4, r6
-	mov	r4, r4, LSR #14
-	mov	r4, r4, LSL #14
-
-	/* Load address for adding to MMU table list */
-	ldr	r11, =0xE010F000		@ INFORM0 reg.
-	ldr	r10, [r11, #0]
-	mov	r10, r10, LSR #18
-	bic	r10, r10, #0x3
-	orr	r4, r4, r10
-
-	/* Calculate MMU table entry */
-	mov 	r10, r10, LSL #18
-	ldr	r5, =0x40E
-	orr	r10, r10, r5
-
-	/* Back up originally data */
-	ldr	r12, [r4]
-
-	/* Add calculated MMU table entry into MMU table list */
-	str	r10, [r4]
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r9, c1, c0, 0		@ turn on MMU, etc
-
-	nop
-	nop
-	nop
-	nop
-	nop					@ second-to-last before mmu
-
-	mov	pc, r2				@ go back to virtual address
-
-	.ltorg
+	b	cpu_resume
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
deleted file mode 100644
index b2a9acc..0000000
--- a/arch/arm/mach-s5pv310/Kconfig
+++ /dev/null
@@ -1,151 +0,0 @@
-# arch/arm/mach-s5pv310/Kconfig
-#
-# Copyright (c) 2010 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-# Configuration options for the S5PV310
-
-if ARCH_S5PV310
-
-config CPU_S5PV310
-	bool
-	select S3C_PL330_DMA
-	help
-	  Enable S5PV310 CPU support
-
-config S5PV310_DEV_PD
-	bool
-	help
-	  Compile in platform device definitions for Power Domain
-
-config S5PV310_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config S5PV310_SETUP_I2C2
-	bool
-	help
-	  Common setup code for i2c bus 2.
-
-config S5PV310_SETUP_I2C3
-	bool
-	help
-	  Common setup code for i2c bus 3.
-
-config S5PV310_SETUP_I2C4
-	bool
-	help
-	  Common setup code for i2c bus 4.
-
-config S5PV310_SETUP_I2C5
-	bool
-	help
-	  Common setup code for i2c bus 5.
-
-config S5PV310_SETUP_I2C6
-	bool
-	help
-	  Common setup code for i2c bus 6.
-
-config S5PV310_SETUP_I2C7
-	bool
-	help
-	  Common setup code for i2c bus 7.
-
-config S5PV310_SETUP_SDHCI
-	bool
-	select S5PV310_SETUP_SDHCI_GPIO
-	help
-	  Internal helper functions for S5PV310 based SDHCI systems.
-
-config S5PV310_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for SDHCI gpio.
-
-config S5PV310_DEV_SYSMMU
-	bool
-	help
-	  Common setup code for SYSTEM MMU in S5PV310
-
-# machine support
-
-menu "S5PC210 Machines"
-
-config MACH_SMDKC210
-	bool "SMDKC210"
-	select CPU_S5PV310
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S5PV310_DEV_PD
-	select S5PV310_SETUP_I2C1
-	select S5PV310_SETUP_SDHCI
-	select S5PV310_DEV_SYSMMU
-	help
-	  Machine support for Samsung SMDKC210
-	  S5PC210(MCP) is one of package option of S5PV310
-
-config MACH_UNIVERSAL_C210
-	bool "Mobile UNIVERSAL_C210 Board"
-	select CPU_S5PV310
-	select S5P_DEV_ONENAND
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S5PV310_SETUP_SDHCI
-	select S3C_DEV_I2C1
-	select S5PV310_SETUP_I2C1
-	help
-	  Machine support for Samsung Mobile Universal S5PC210 Reference
-	  Board. S5PC210(MCP) is one of package option of S5PV310
-
-endmenu
-
-menu "S5PV310 Machines"
-
-config MACH_SMDKV310
-	bool "SMDKV310"
-	select CPU_S5PV310
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S5PV310_DEV_PD
-	select S5PV310_DEV_SYSMMU
-	select S5PV310_SETUP_I2C1
-	select S5PV310_SETUP_SDHCI
-	help
-	  Machine support for Samsung SMDKV310
-
-endmenu
-
-comment "Configuration for HSMMC bus width"
-
-menu "Use 8-bit bus width"
-
-config S5PV310_SDHCI_CH0_8BIT
-	bool "Channel 0 with 8-bit bus"
-	help
-	  Support HSMMC Channel 0 8-bit bus.
-	  If selected, Channel 1 is disabled.
-
-config S5PV310_SDHCI_CH2_8BIT
-	bool "Channel 2 with 8-bit bus"
-	help
-	  Support HSMMC Channel 2 8-bit bus.
-	  If selected, Channel 3 is disabled.
-
-endmenu
-
-endif
diff --git a/arch/arm/mach-s5pv310/Makefile b/arch/arm/mach-s5pv310/Makefile
deleted file mode 100644
index 036fb38..0000000
--- a/arch/arm/mach-s5pv310/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-# arch/arm/mach-s5pv310/Makefile
-#
-# Copyright (c) 2010 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for S5PV310 system
-
-obj-$(CONFIG_CPU_S5PV310)	+= cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o gpiolib.o irq-eint.o dma.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
-
-obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
-obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDKC210)	+= mach-smdkc210.o
-obj-$(CONFIG_MACH_SMDKV310)	+= mach-smdkv310.o
-obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
-
-# device support
-
-obj-y					+= dev-audio.o
-obj-$(CONFIG_S5PV310_DEV_PD)		+= dev-pd.o
-obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
-
-obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
-obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o
-obj-$(CONFIG_S5PV310_SETUP_I2C3)	+= setup-i2c3.o
-obj-$(CONFIG_S5PV310_SETUP_I2C4)	+= setup-i2c4.o
-obj-$(CONFIG_S5PV310_SETUP_I2C5)	+= setup-i2c5.o
-obj-$(CONFIG_S5PV310_SETUP_I2C6)	+= setup-i2c6.o
-obj-$(CONFIG_S5PV310_SETUP_I2C7)	+= setup-i2c7.o
-obj-$(CONFIG_S5PV310_SETUP_SDHCI)	+= setup-sdhci.o
-obj-$(CONFIG_S5PV310_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
diff --git a/arch/arm/mach-s5pv310/Makefile.boot b/arch/arm/mach-s5pv310/Makefile.boot
deleted file mode 100644
index d65956f..0000000
--- a/arch/arm/mach-s5pv310/Makefile.boot
+++ /dev/null
@@ -1,2 +0,0 @@
-   zreladdr-y	:= 0x40008000
-params_phys-y	:= 0x40000100
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
deleted file mode 100644
index fc7c2f8..0000000
--- a/arch/arm/mach-s5pv310/clock.c
+++ /dev/null
@@ -1,1122 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - 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 <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 <mach/map.h>
-#include <mach/regs-clock.h>
-
-static struct clk clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.id		= -1,
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-	.id		= -1,
-};
-
-static struct clk clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.id		= -1,
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-	.id		= -1,
-};
-
-static int s5pv310_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int s5pv310_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int s5pv310_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
-}
-
-static int s5pv310_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
-}
-
-static int s5pv310_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_apll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.id		= -1,
-		.parent		= &clk_mout_apll.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_epll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_mpll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
-};
-
-static struct clk *clkset_moutcore_list[] = {
-	[0] = &clk_mout_apll.clk,
-	[1] = &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_moutcore = {
-	.sources	= clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
-};
-
-static struct clksrc_clk clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-		.id		= -1,
-	},
-	.sources	= &clkset_moutcore,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.id		= -1,
-		.parent		= &clk_moutcore.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *clkset_corebus_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_corebus = {
-	.sources	= clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
-};
-
-static struct clksrc_clk clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-		.id		= -1,
-	},
-	.sources	= &clkset_mout_corebus,
-	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.id		= -1,
-		.parent		= &clk_mout_corebus.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.id		= -1,
-		.parent		= &clk_sclk_dmc.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.id		= -1,
-		.parent		= &clk_aclk_cored.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.id		= -1,
-		.parent		= &clk_mout_corebus.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.id		= -1,
-		.parent		= &clk_aclk_acp.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-static struct clk *clkset_aclk_top_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_aclk = {
-	.sources	= clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
-};
-
-static struct clksrc_clk clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources clkset_vpllsrc = {
-	.sources	= clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.id		= -1,
-		.enable		= s5pv310_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources	= &clkset_vpllsrc,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_sclk_vpll_list[] = {
-	[0] = &clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources clkset_sclk_vpll = {
-	.sources	= clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-		.id		= -1,
-	},
-	.sources	= &clkset_sclk_vpll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "fimc",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.id		= 3,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimd",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimd",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hsmmc",
-		.id		= 0,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.id		= 1,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.id		= 2,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.id		= 3,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "hsmmc",
-		.id		= 4,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "sata",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "pdma",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "ac97",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "fimg2d",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.id		= 0,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.id		= 1,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.id		= 2,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.id		= 3,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.id		= 4,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.id		= 5,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.id		= 6,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.id		= 7,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	},
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "uart",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.id		= 3,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.id		= 4,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.id		= 5,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk *clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group = {
-	.sources	= clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group_list),
-};
-
-static struct clk *clkset_mout_g2d0_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d0 = {
-	.sources	= clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d0_list),
-};
-
-static struct clksrc_clk clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-		.id		= -1,
-	},
-	.sources	= &clkset_mout_g2d0,
-	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_mout_g2d1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d1 = {
-	.sources	= clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d1_list),
-};
-
-static struct clksrc_clk clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-		.id		= -1,
-	},
-	.sources	= &clkset_mout_g2d1,
-	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_mout_g2d_list[] = {
-	[0] = &clk_mout_g2d0.clk,
-	[1] = &clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d = {
-	.sources	= clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk clk_dout_mmc0 = {
-	.clk		= {
-		.name		= "dout_mmc0",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc1 = {
-	.clk		= {
-		.name		= "dout_mmc1",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc2 = {
-	.clk		= {
-		.name		= "dout_mmc2",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc3 = {
-	.clk		= {
-		.name		= "dout_mmc3",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "uclk1",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.id		= 2,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.id		= 3,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_pwm",
-			.id		= -1,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 2,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 3,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_sata",
-			.id		= -1,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_mout_corebus,
-		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.id		= 2,
-			.enable		= s5pv310_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimg2d",
-			.id		= -1,
-		},
-		.sources = &clkset_mout_g2d,
-		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 0,
-			.parent		= &clk_dout_mmc0.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 1,
-			.parent         = &clk_dout_mmc1.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 2,
-			.parent         = &clk_dout_mmc2.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 3,
-			.parent         = &clk_dout_mmc3.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 4,
-			.parent         = &clk_dout_mmc4.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_sclk_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_moutcore,
-	&clk_coreclk,
-	&clk_armclk,
-	&clk_aclk_corem0,
-	&clk_aclk_cores,
-	&clk_aclk_corem1,
-	&clk_periphclk,
-	&clk_mout_corebus,
-	&clk_sclk_dmc,
-	&clk_aclk_cored,
-	&clk_aclk_corep,
-	&clk_aclk_acp,
-	&clk_pclk_acp,
-	&clk_vpllsrc,
-	&clk_sclk_vpll,
-	&clk_aclk_200,
-	&clk_aclk_100,
-	&clk_aclk_160,
-	&clk_aclk_133,
-	&clk_dout_mmc0,
-	&clk_dout_mmc1,
-	&clk_dout_mmc2,
-	&clk_dout_mmc3,
-	&clk_dout_mmc4,
-};
-
-static int xtal_rate;
-
-static unsigned long s5pv310_fout_apll_get_rate(struct clk *clk)
-{
-	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
-}
-
-static struct clk_ops s5pv310_fout_apll_ops = {
-	.get_rate = s5pv310_fout_apll_get_rate,
-};
-
-void __init_or_cpufreq s5pv310_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long vpll;
-	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);
-
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
-	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
-				__raw_readl(S5P_EPLL_CON1), pll_4600);
-
-	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
-	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
-				__raw_readl(S5P_VPLL_CON1), pll_4650);
-
-	clk_fout_apll.ops = &s5pv310_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&clk_aclk_133.clk);
-
-	printk(KERN_INFO "S5PV310: 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(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-	/* Nothing here yet */
-};
-
-void __init s5pv310_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	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, ARRAY_SIZE(init_clocks));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
deleted file mode 100644
index 0db0fb6..0000000
--- a/arch/arm/mach-s5pv310/cpu.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/cpu.c
- *
- * Copyright (c) 2010 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.
-*/
-
-#include <linux/sched.h>
-#include <linux/sysdev.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/proc-fns.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/s5pv310.h>
-#include <plat/sdhci.h>
-
-#include <mach/regs-irq.h>
-
-extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
-			 unsigned int irq_start);
-extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
-
-/* Initial IO mappings */
-static struct map_desc s5pv310_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_SYSRAM,
-		.pfn		= __phys_to_pfn(S5PV310_PA_SYSRAM),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_CMU,
-		.pfn		= __phys_to_pfn(S5PV310_PA_CMU),
-		.length		= SZ_128K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_PMU,
-		.pfn		= __phys_to_pfn(S5PV310_PA_PMU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
-		.pfn		= __phys_to_pfn(S5PV310_PA_COMBINER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
-		.pfn		= __phys_to_pfn(S5PV310_PA_COREPERI),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_L2CC,
-		.pfn		= __phys_to_pfn(S5PV310_PA_L2CC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO1,
-		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO1),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO2,
-		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO2),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO3,
-		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO3),
-		.length		= SZ_256,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_DMC0,
-		.pfn		= __phys_to_pfn(S5PV310_PA_DMC0),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(S5PV310_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static void s5pv310_idle(void)
-{
-	if (!need_resched())
-		cpu_do_idle();
-
-	local_irq_enable();
-}
-
-/* s5pv310_map_io
- *
- * register the standard cpu IO areas
-*/
-void __init s5pv310_map_io(void)
-{
-	iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc));
-
-	/* initialize device information early */
-	s5pv310_default_sdhci0();
-	s5pv310_default_sdhci1();
-	s5pv310_default_sdhci2();
-	s5pv310_default_sdhci3();
-}
-
-void __init s5pv310_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5pv310_register_clocks();
-	s5pv310_setup_clocks();
-}
-
-void __init s5pv310_init_irq(void)
-{
-	int irq;
-
-	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-
-	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
-
-		/*
-		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
-		 * connected to the interrupt combiner. These irqs
-		 * should be initialized to support cascade interrupt.
-		 */
-		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
-			continue;
-
-		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
-				COMBINER_IRQ(irq, 0));
-		combiner_cascade_irq(irq, IRQ_SPI(irq));
-	}
-
-	/* The parameters of s5p_init_irq() are for VIC init.
-	 * Theses parameters should be NULL and 0 because S5PV310
-	 * uses GIC instead of VIC.
-	 */
-	s5p_init_irq(NULL, 0);
-}
-
-struct sysdev_class s5pv310_sysclass = {
-	.name	= "s5pv310-core",
-};
-
-static struct sys_device s5pv310_sysdev = {
-	.cls	= &s5pv310_sysclass,
-};
-
-static int __init s5pv310_core_init(void)
-{
-	return sysdev_class_register(&s5pv310_sysclass);
-}
-
-core_initcall(s5pv310_core_init);
-
-#ifdef CONFIG_CACHE_L2X0
-static int __init s5pv310_l2x0_cache_init(void)
-{
-	/* TAG, Data Latency Control: 2cycle */
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
-
-	/* L2X0 Prefetch Control */
-	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
-
-	/* L2X0 Power Control */
-	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
-		     S5P_VA_L2CC + L2X0_POWER_CTRL);
-
-	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
-
-	return 0;
-}
-
-early_initcall(s5pv310_l2x0_cache_init);
-#endif
-
-int __init s5pv310_init(void)
-{
-	printk(KERN_INFO "S5PV310: Initializing architecture\n");
-
-	/* set idle function */
-	pm_idle = s5pv310_idle;
-
-	return sysdev_register(&s5pv310_sysdev);
-}
diff --git a/arch/arm/mach-s5pv310/cpufreq.c b/arch/arm/mach-s5pv310/cpufreq.c
deleted file mode 100644
index b04cbc7..0000000
--- a/arch/arm/mach-s5pv310/cpufreq.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/cpufreq.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - CPU frequency scaling support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <linux/cpufreq.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-mem.h>
-
-#include <plat/clock.h>
-#include <plat/pm.h>
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-#ifdef CONFIG_REGULATOR
-static struct regulator *arm_regulator;
-static struct regulator *int_regulator;
-#endif
-
-static struct cpufreq_freqs freqs;
-static unsigned int memtype;
-
-enum s5pv310_memory_type {
-	DDR2 = 4,
-	LPDDR2,
-	DDR3,
-};
-
-enum cpufreq_level_index {
-	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
-};
-
-static struct cpufreq_frequency_table s5pv310_freq_table[] = {
-	{L0, 1000*1000},
-	{L1, 800*1000},
-	{L2, 400*1000},
-	{L3, 100*1000},
-	{0, CPUFREQ_TABLE_END},
-};
-
-static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
-	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
-	 */
-
-	/* ARM L0: 1000MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
-
-	/* ARM L1: 800MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
-
-	/* ARM L2: 400MHz */
-	{ 0, 1, 3, 1, 3, 0, 1 },
-
-	/* ARM L3: 100MHz */
-	{ 0, 0, 1, 0, 3, 1, 1 },
-};
-
-static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVCOPY, DIVHPM }
-	 */
-
-	 /* ARM L0: 1000MHz */
-	{ 3, 0 },
-
-	/* ARM L1: 800MHz */
-	{ 3, 0 },
-
-	/* ARM L2: 400MHz */
-	{ 3, 0 },
-
-	/* ARM L3: 100MHz */
-	{ 3, 0 },
-};
-
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
-	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
-	 */
-
-	/* DMC L0: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L1: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L2: 266.7MHz */
-	{ 7, 1, 1, 2, 1, 1, 3, 1 },
-
-	/* DMC L3: 200MHz */
-	{ 7, 1, 1, 3, 1, 1, 3, 1 },
-};
-
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
-	 */
-
-	/* ACLK200 L0: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L1: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L2: 160MHz */
-	{ 4, 7, 5, 7, 1 },
-
-	/* ACLK200 L3: 133.3MHz */
-	{ 5, 7, 7, 7, 1 },
-};
-
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVGDL/R, DIVGPL/R }
-	 */
-
-	/* ACLK_GDL/R L0: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L1: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L2: 160MHz */
-	{ 4, 1 },
-
-	/* ACLK_GDL/R L3: 133.3MHz */
-	{ 5, 1 },
-};
-
-struct cpufreq_voltage_table {
-	unsigned int	index;		/* any */
-	unsigned int	arm_volt;	/* uV */
-	unsigned int	int_volt;
-};
-
-static struct cpufreq_voltage_table s5pv310_volt_table[CPUFREQ_LEVEL_END] = {
-	{
-		.index		= L0,
-		.arm_volt	= 1200000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L1,
-		.arm_volt	= 1100000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L2,
-		.arm_volt	= 1000000,
-		.int_volt	= 1000000,
-	}, {
-		.index		= L3,
-		.arm_volt	= 900000,
-		.int_volt	= 1000000,
-	},
-};
-
-static unsigned int s5pv310_apll_pms_table[CPUFREQ_LEVEL_END] = {
-	/* APLL FOUT L0: 1000MHz */
-	((250 << 16) | (6 << 8) | 1),
-
-	/* APLL FOUT L1: 800MHz */
-	((200 << 16) | (6 << 8) | 1),
-
-	/* APLL FOUT L2 : 400MHz */
-	((200 << 16) | (6 << 8) | 2),
-
-	/* APLL FOUT L3: 100MHz */
-	((200 << 16) | (6 << 8) | 4),
-};
-
-int s5pv310_verify_speed(struct cpufreq_policy *policy)
-{
-	return cpufreq_frequency_table_verify(policy, s5pv310_freq_table);
-}
-
-unsigned int s5pv310_getspeed(unsigned int cpu)
-{
-	return clk_get_rate(cpu_clk) / 1000;
-}
-
-void s5pv310_set_clkdiv(unsigned int div_index)
-{
-	unsigned int tmp;
-
-	/* Change Divider - CPU0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_CPU);
-
-	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
-		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
-		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
-		S5P_CLKDIV_CPU0_APLL_MASK);
-
-	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
-		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
-		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
-		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
-		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
-		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
-		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_CPU);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
-	} while (tmp & 0x1111111);
-
-	/* Change Divider - CPU1 */
-
-	tmp = __raw_readl(S5P_CLKDIV_CPU1);
-
-	tmp &= ~((0x7 << 4) | 0x7);
-
-	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
-		(clkdiv_cpu1[div_index][1] << 0));
-
-	__raw_writel(tmp, S5P_CLKDIV_CPU1);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
-	} while (tmp & 0x11);
-
-	/* Change Divider - DMC0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_DMC0);
-
-	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
-		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
-		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
-		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
-
-	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
-		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
-		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
-		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
-		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
-		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
-		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
-		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_DMC0);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
-	} while (tmp & 0x11111111);
-
-	/* Change Divider - TOP */
-
-	tmp = __raw_readl(S5P_CLKDIV_TOP);
-
-	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
-		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
-		S5P_CLKDIV_TOP_ONENAND_MASK);
-
-	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
-		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
-		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
-		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
-		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_TOP);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
-	} while (tmp & 0x11111);
-
-	/* Change Divider - LEFTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - RIGHTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
-	} while (tmp & 0x11);
-}
-
-static void s5pv310_set_apll(unsigned int index)
-{
-	unsigned int tmp;
-
-	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
-	clk_set_parent(moutcore, mout_mpll);
-
-	do {
-		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
-			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
-		tmp &= 0x7;
-	} while (tmp != 0x2);
-
-	/* 2. Set APLL Lock time */
-	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
-
-	/* 3. Change PLL PMS values */
-	tmp = __raw_readl(S5P_APLL_CON0);
-	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-	tmp |= s5pv310_apll_pms_table[index];
-	__raw_writel(tmp, S5P_APLL_CON0);
-
-	/* 4. wait_lock_time */
-	do {
-		tmp = __raw_readl(S5P_APLL_CON0);
-	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
-
-	/* 5. MUX_CORE_SEL = APLL */
-	clk_set_parent(moutcore, mout_apll);
-
-	do {
-		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
-		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
-	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void s5pv310_set_frequency(unsigned int old_index, unsigned int new_index)
-{
-	unsigned int tmp;
-
-	if (old_index > new_index) {
-		/* The frequency changing to L0 needs to change apll */
-		if (freqs.new == s5pv310_freq_table[L0].frequency) {
-			/* 1. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-
-			/* 2. Change the apll m,p,s value */
-			s5pv310_set_apll(new_index);
-		} else {
-			/* 1. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-
-			/* 2. Change just s value in apll m,p,s value */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp &= ~(0x7 << 0);
-			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
-			__raw_writel(tmp, S5P_APLL_CON0);
-		}
-	}
-
-	else if (old_index < new_index) {
-		/* The frequency changing from L0 needs to change apll */
-		if (freqs.old == s5pv310_freq_table[L0].frequency) {
-			/* 1. Change the apll m,p,s value */
-			s5pv310_set_apll(new_index);
-
-			/* 2. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-		} else {
-			/* 1. Change just s value in apll m,p,s value */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp &= ~(0x7 << 0);
-			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
-			__raw_writel(tmp, S5P_APLL_CON0);
-
-			/* 2. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-		}
-	}
-}
-
-static int s5pv310_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq,
-			  unsigned int relation)
-{
-	unsigned int index, old_index;
-	unsigned int arm_volt, int_volt;
-
-	freqs.old = s5pv310_getspeed(policy->cpu);
-
-	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
-					   freqs.old, relation, &old_index))
-		return -EINVAL;
-
-	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
-					   target_freq, relation, &index))
-		return -EINVAL;
-
-	freqs.new = s5pv310_freq_table[index].frequency;
-	freqs.cpu = policy->cpu;
-
-	if (freqs.new == freqs.old)
-		return 0;
-
-	/* get the voltage value */
-	arm_volt = s5pv310_volt_table[index].arm_volt;
-	int_volt = s5pv310_volt_table[index].int_volt;
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	/* control regulator */
-	if (freqs.new > freqs.old) {
-		/* Voltage up */
-#ifdef CONFIG_REGULATOR
-		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-#endif
-	}
-
-	/* Clock Configuration Procedure */
-	s5pv310_set_frequency(old_index, index);
-
-	/* control regulator */
-	if (freqs.new < freqs.old) {
-		/* Voltage down */
-#ifdef CONFIG_REGULATOR
-		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-#endif
-	}
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s5pv310_cpufreq_suspend(struct cpufreq_policy *policy,
-				   pm_message_t pmsg)
-{
-	return 0;
-}
-
-static int s5pv310_cpufreq_resume(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-#endif
-
-static int s5pv310_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
-	policy->cur = policy->min = policy->max = s5pv310_getspeed(policy->cpu);
-
-	cpufreq_frequency_table_get_attr(s5pv310_freq_table, policy->cpu);
-
-	/* set the transition latency value */
-	policy->cpuinfo.transition_latency = 100000;
-
-	/*
-	 * S5PV310 multi-core processors has 2 cores
-	 * that the frequency cannot be set independently.
-	 * Each cpu is bound to the same speed.
-	 * So the affected cpu is all of the cpus.
-	 */
-	cpumask_setall(policy->cpus);
-
-	return cpufreq_frequency_table_cpuinfo(policy, s5pv310_freq_table);
-}
-
-static struct cpufreq_driver s5pv310_driver = {
-	.flags		= CPUFREQ_STICKY,
-	.verify		= s5pv310_verify_speed,
-	.target		= s5pv310_target,
-	.get		= s5pv310_getspeed,
-	.init		= s5pv310_cpufreq_cpu_init,
-	.name		= "s5pv310_cpufreq",
-#ifdef CONFIG_PM
-	.suspend	= s5pv310_cpufreq_suspend,
-	.resume		= s5pv310_cpufreq_resume,
-#endif
-};
-
-static int __init s5pv310_cpufreq_init(void)
-{
-	cpu_clk = clk_get(NULL, "armclk");
-	if (IS_ERR(cpu_clk))
-		return PTR_ERR(cpu_clk);
-
-	moutcore = clk_get(NULL, "moutcore");
-	if (IS_ERR(moutcore))
-		goto out;
-
-	mout_mpll = clk_get(NULL, "mout_mpll");
-	if (IS_ERR(mout_mpll))
-		goto out;
-
-	mout_apll = clk_get(NULL, "mout_apll");
-	if (IS_ERR(mout_apll))
-		goto out;
-
-#ifdef CONFIG_REGULATOR
-	arm_regulator = regulator_get(NULL, "vdd_arm");
-	if (IS_ERR(arm_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
-		goto out;
-	}
-
-	int_regulator = regulator_get(NULL, "vdd_int");
-	if (IS_ERR(int_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
-		goto out;
-	}
-#endif
-
-	/*
-	 * Check DRAM type.
-	 * Because DVFS level is different according to DRAM type.
-	 */
-	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
-	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
-	memtype &= S5P_DMC0_MEMTYPE_MASK;
-
-	if ((memtype < DDR2) && (memtype > DDR3)) {
-		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
-		goto out;
-	} else {
-		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
-	}
-
-	return cpufreq_register_driver(&s5pv310_driver);
-
-out:
-	if (!IS_ERR(cpu_clk))
-		clk_put(cpu_clk);
-
-	if (!IS_ERR(moutcore))
-		clk_put(moutcore);
-
-	if (!IS_ERR(mout_mpll))
-		clk_put(mout_mpll);
-
-	if (!IS_ERR(mout_apll))
-		clk_put(mout_apll);
-
-#ifdef CONFIG_REGULATOR
-	if (!IS_ERR(arm_regulator))
-		regulator_put(arm_regulator);
-
-	if (!IS_ERR(int_regulator))
-		regulator_put(int_regulator);
-#endif
-
-	printk(KERN_ERR "%s: failed initialization\n", __func__);
-
-	return -EINVAL;
-}
-late_initcall(s5pv310_cpufreq_init);
diff --git a/arch/arm/mach-s5pv310/dev-audio.c b/arch/arm/mach-s5pv310/dev-audio.c
deleted file mode 100644
index a196424..0000000
--- a/arch/arm/mach-s5pv310/dev-audio.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/audio.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static const char *rclksrc[] = {
-	[0] = "busclk",
-	[1] = "i2sclk",
-};
-
-static int s5pv310_cfg_i2s(struct platform_device *pdev)
-{
-	/* configure GPIO for i2s port */
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 7, S3C_GPIO_SFN(2));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(2));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 5, S3C_GPIO_SFN(4));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
-	.cfg_gpio = s5pv310_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
-					 | QUIRK_NEED_RSTCLR,
-			.src_clk = rclksrc,
-		},
-	},
-};
-
-static struct resource s5pv310_i2s0_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_I2S0,
-		.end	= S5PV310_PA_I2S0 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S0_TX,
-		.end	= DMACH_I2S0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S0_RX,
-		.end	= DMACH_I2S0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DMACH_I2S0S_TX,
-		.end	= DMACH_I2S0S_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_i2s0 = {
-	.name = "samsung-i2s",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(s5pv310_i2s0_resource),
-	.resource = s5pv310_i2s0_resource,
-	.dev = {
-		.platform_data = &i2sv5_pdata,
-	},
-};
-
-static const char *rclksrc_v3[] = {
-	[0] = "sclk_i2s",
-	[1] = "no_such_clock",
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
-	.cfg_gpio = s5pv310_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_NO_MUXPSR,
-			.src_clk = rclksrc_v3,
-		},
-	},
-};
-
-static struct resource s5pv310_i2s1_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_I2S1,
-		.end	= S5PV310_PA_I2S1 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S1_TX,
-		.end	= DMACH_I2S1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S1_RX,
-		.end	= DMACH_I2S1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_i2s1 = {
-	.name = "samsung-i2s",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(s5pv310_i2s1_resource),
-	.resource = s5pv310_i2s1_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-static struct resource s5pv310_i2s2_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_I2S2,
-		.end	= S5PV310_PA_I2S2 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S2_TX,
-		.end	= DMACH_I2S2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S2_RX,
-		.end	= DMACH_I2S2_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_i2s2 = {
-	.name = "samsung-i2s",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(s5pv310_i2s2_resource),
-	.resource = s5pv310_i2s2_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int s5pv310_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 5, S3C_GPIO_SFN(3));
-		break;
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-	.cfg_gpio = s5pv310_pcm_cfg_gpio,
-};
-
-static struct resource s5pv310_pcm0_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PCM0,
-		.end	= S5PV310_PA_PCM0 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM0_TX,
-		.end	= DMACH_PCM0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM0_RX,
-		.end	= DMACH_PCM0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_pcm0 = {
-	.name = "samsung-pcm",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(s5pv310_pcm0_resource),
-	.resource = s5pv310_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pv310_pcm1_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PCM1,
-		.end	= S5PV310_PA_PCM1 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM1_TX,
-		.end	= DMACH_PCM1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM1_RX,
-		.end	= DMACH_PCM1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_pcm1 = {
-	.name = "samsung-pcm",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(s5pv310_pcm1_resource),
-	.resource = s5pv310_pcm1_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pv310_pcm2_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PCM2,
-		.end	= S5PV310_PA_PCM2 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM2_TX,
-		.end	= DMACH_PCM2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM2_RX,
-		.end	= DMACH_PCM2_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_pcm2 = {
-	.name = "samsung-pcm",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(s5pv310_pcm2_resource),
-	.resource = s5pv310_pcm2_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-/* AC97 Controller platform devices */
-
-static int s5pv310_ac97_cfg_gpio(struct platform_device *pdev)
-{
-	return s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource s5pv310_ac97_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_AC97,
-		.end	= S5PV310_PA_AC97 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_AC97_PCMOUT,
-		.end	= DMACH_AC97_PCMOUT,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_AC97_PCMIN,
-		.end	= DMACH_AC97_PCMIN,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DMACH_AC97_MICIN,
-		.end	= DMACH_AC97_MICIN,
-		.flags	= IORESOURCE_DMA,
-	},
-	[4] = {
-		.start	= IRQ_AC97,
-		.end	= IRQ_AC97,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
-	.cfg_gpio = s5pv310_ac97_cfg_gpio,
-};
-
-static u64 s5pv310_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv310_device_ac97 = {
-	.name = "samsung-ac97",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(s5pv310_ac97_resource),
-	.resource = s5pv310_ac97_resource,
-	.dev = {
-		.platform_data = &s3c_ac97_pdata,
-		.dma_mask = &s5pv310_ac97_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-/* S/PDIF Controller platform_device */
-
-static int s5pv310_spdif_cfg_gpio(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 2, S3C_GPIO_SFN(3));
-
-	return 0;
-}
-
-static struct resource s5pv310_spdif_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_SPDIF,
-		.end	= S5PV310_PA_SPDIF + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_SPDIF,
-		.end	= DMACH_SPDIF,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-static struct s3c_audio_pdata samsung_spdif_pdata = {
-	.cfg_gpio = s5pv310_spdif_cfg_gpio,
-};
-
-static u64 s5pv310_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv310_device_spdif = {
-	.name = "samsung-spdif",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(s5pv310_spdif_resource),
-	.resource = s5pv310_spdif_resource,
-	.dev = {
-		.platform_data = &samsung_spdif_pdata,
-		.dma_mask = &s5pv310_spdif_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff --git a/arch/arm/mach-s5pv310/dev-pd.c b/arch/arm/mach-s5pv310/dev-pd.c
deleted file mode 100644
index 58a50c2..0000000
--- a/arch/arm/mach-s5pv310/dev-pd.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/dev-pd.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - Power Domain support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-
-#include <mach/regs-pmu.h>
-
-#include <plat/pd.h>
-
-static int s5pv310_pd_enable(struct device *dev)
-{
-	struct samsung_pd_info *pdata =  dev->platform_data;
-	u32 timeout;
-
-	__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
-
-	/* Wait max 1ms */
-	timeout = 10;
-	while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
-		!= S5P_INT_LOCAL_PWR_EN) {
-		if (timeout == 0) {
-			printk(KERN_ERR "Power domain %s enable failed.\n",
-				dev_name(dev));
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		udelay(100);
-	}
-
-	return 0;
-}
-
-static int s5pv310_pd_disable(struct device *dev)
-{
-	struct samsung_pd_info *pdata =  dev->platform_data;
-	u32 timeout;
-
-	__raw_writel(0, pdata->base);
-
-	/* Wait max 1ms */
-	timeout = 10;
-	while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
-		if (timeout == 0) {
-			printk(KERN_ERR "Power domain %s disable failed.\n",
-				dev_name(dev));
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		udelay(100);
-	}
-
-	return 0;
-}
-
-struct platform_device s5pv310_device_pd[] = {
-	{
-		.name		= "samsung-pd",
-		.id		= 0,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_MFC_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 1,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_G3D_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 2,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_LCD0_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 3,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_LCD1_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 4,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_TV_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 5,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_CAM_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 6,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_GPS_CONF,
-			},
-		},
-	},
-};
diff --git a/arch/arm/mach-s5pv310/dev-sysmmu.c b/arch/arm/mach-s5pv310/dev-sysmmu.c
deleted file mode 100644
index e1bb200..0000000
--- a/arch/arm/mach-s5pv310/dev-sysmmu.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/dev-sysmmu.c
- *
- * Copyright (c) 2010 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.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-static struct resource s5pv310_sysmmu_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_SYSMMU_MDMA,
-		.end	= S5PV310_PA_SYSMMU_MDMA + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_SYSMMU_MDMA0_0,
-		.end	= IRQ_SYSMMU_MDMA0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= S5PV310_PA_SYSMMU_SSS,
-		.end	= S5PV310_PA_SYSMMU_SSS + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[3] = {
-		.start	= IRQ_SYSMMU_SSS_0,
-		.end	= IRQ_SYSMMU_SSS_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[4] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC0,
-		.end	= S5PV310_PA_SYSMMU_FIMC0 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[5] = {
-		.start	= IRQ_SYSMMU_FIMC0_0,
-		.end	= IRQ_SYSMMU_FIMC0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[6] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC1,
-		.end	= S5PV310_PA_SYSMMU_FIMC1 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[7] = {
-		.start	= IRQ_SYSMMU_FIMC1_0,
-		.end	= IRQ_SYSMMU_FIMC1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[8] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC2,
-		.end	= S5PV310_PA_SYSMMU_FIMC2 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[9] = {
-		.start	= IRQ_SYSMMU_FIMC2_0,
-		.end	= IRQ_SYSMMU_FIMC2_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[10] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC3,
-		.end	= S5PV310_PA_SYSMMU_FIMC3 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[11] = {
-		.start	= IRQ_SYSMMU_FIMC3_0,
-		.end	= IRQ_SYSMMU_FIMC3_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[12] = {
-		.start	= S5PV310_PA_SYSMMU_JPEG,
-		.end	= S5PV310_PA_SYSMMU_JPEG + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[13] = {
-		.start	= IRQ_SYSMMU_JPEG_0,
-		.end	= IRQ_SYSMMU_JPEG_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[14] = {
-		.start	= S5PV310_PA_SYSMMU_FIMD0,
-		.end	= S5PV310_PA_SYSMMU_FIMD0 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[15] = {
-		.start	= IRQ_SYSMMU_LCD0_M0_0,
-		.end	= IRQ_SYSMMU_LCD0_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[16] = {
-		.start	= S5PV310_PA_SYSMMU_FIMD1,
-		.end	= S5PV310_PA_SYSMMU_FIMD1 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[17] = {
-		.start	= IRQ_SYSMMU_LCD1_M1_0,
-		.end	= IRQ_SYSMMU_LCD1_M1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[18] = {
-		.start	= S5PV310_PA_SYSMMU_PCIe,
-		.end	= S5PV310_PA_SYSMMU_PCIe + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[19] = {
-		.start	= IRQ_SYSMMU_PCIE_0,
-		.end	= IRQ_SYSMMU_PCIE_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[20] = {
-		.start	= S5PV310_PA_SYSMMU_G2D,
-		.end	= S5PV310_PA_SYSMMU_G2D + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[21] = {
-		.start	= IRQ_SYSMMU_2D_0,
-		.end	= IRQ_SYSMMU_2D_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[22] = {
-		.start	= S5PV310_PA_SYSMMU_ROTATOR,
-		.end	= S5PV310_PA_SYSMMU_ROTATOR + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[23] = {
-		.start	= IRQ_SYSMMU_ROTATOR_0,
-		.end	= IRQ_SYSMMU_ROTATOR_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[24] = {
-		.start	= S5PV310_PA_SYSMMU_MDMA2,
-		.end	= S5PV310_PA_SYSMMU_MDMA2 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[25] = {
-		.start	= IRQ_SYSMMU_MDMA1_0,
-		.end	= IRQ_SYSMMU_MDMA1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[26] = {
-		.start	= S5PV310_PA_SYSMMU_TV,
-		.end	= S5PV310_PA_SYSMMU_TV + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[27] = {
-		.start	= IRQ_SYSMMU_TV_M0_0,
-		.end	= IRQ_SYSMMU_TV_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[28] = {
-		.start	= S5PV310_PA_SYSMMU_MFC_L,
-		.end	= S5PV310_PA_SYSMMU_MFC_L + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[29] = {
-		.start	= IRQ_SYSMMU_MFC_M0_0,
-		.end	= IRQ_SYSMMU_MFC_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[30] = {
-		.start	= S5PV310_PA_SYSMMU_MFC_R,
-		.end	= S5PV310_PA_SYSMMU_MFC_R + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[31] = {
-		.start	= IRQ_SYSMMU_MFC_M1_0,
-		.end	= IRQ_SYSMMU_MFC_M1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5pv310_device_sysmmu = {
-	.name		= "s5p-sysmmu",
-	.id		= 32,
-	.num_resources	= ARRAY_SIZE(s5pv310_sysmmu_resource),
-	.resource	= s5pv310_sysmmu_resource,
-};
-
-EXPORT_SYMBOL(s5pv310_device_sysmmu);
diff --git a/arch/arm/mach-s5pv310/dma.c b/arch/arm/mach-s5pv310/dma.c
deleted file mode 100644
index 20066c7..0000000
--- a/arch/arm/mach-s5pv310/dma.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
-static struct resource s5pv310_pdma0_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PDMA0,
-		.end	= S5PV310_PA_PDMA0 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata s5pv310_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM2_RX,
-		[3] = DMACH_PCM2_TX,
-		[4] = DMACH_MSM_REQ0,
-		[5] = DMACH_MSM_REQ2,
-		[6] = DMACH_SPI0_RX,
-		[7] = DMACH_SPI0_TX,
-		[8] = DMACH_SPI2_RX,
-		[9] = DMACH_SPI2_TX,
-		[10] = DMACH_I2S0S_TX,
-		[11] = DMACH_I2S0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S2_RX,
-		[14] = DMACH_I2S2_TX,
-		[15] = DMACH_UART0_RX,
-		[16] = DMACH_UART0_TX,
-		[17] = DMACH_UART2_RX,
-		[18] = DMACH_UART2_TX,
-		[19] = DMACH_UART4_RX,
-		[20] = DMACH_UART4_TX,
-		[21] = DMACH_SLIMBUS0_RX,
-		[22] = DMACH_SLIMBUS0_TX,
-		[23] = DMACH_SLIMBUS2_RX,
-		[24] = DMACH_SLIMBUS2_TX,
-		[25] = DMACH_SLIMBUS4_RX,
-		[26] = DMACH_SLIMBUS4_TX,
-		[27] = DMACH_AC97_MICIN,
-		[28] = DMACH_AC97_PCMIN,
-		[29] = DMACH_AC97_PCMOUT,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device s5pv310_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pv310_pdma0_resource),
-	.resource	= s5pv310_pdma0_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &s5pv310_pdma0_pdata,
-	},
-};
-
-static struct resource s5pv310_pdma1_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PDMA1,
-		.end	= S5PV310_PA_PDMA1 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata s5pv310_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM1_RX,
-		[3] = DMACH_PCM1_TX,
-		[4] = DMACH_MSM_REQ1,
-		[5] = DMACH_MSM_REQ3,
-		[6] = DMACH_SPI1_RX,
-		[7] = DMACH_SPI1_TX,
-		[8] = DMACH_I2S0S_TX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S1_RX,
-		[12] = DMACH_I2S1_TX,
-		[13] = DMACH_UART0_RX,
-		[14] = DMACH_UART0_TX,
-		[15] = DMACH_UART1_RX,
-		[16] = DMACH_UART1_TX,
-		[17] = DMACH_UART3_RX,
-		[18] = DMACH_UART3_TX,
-		[19] = DMACH_SLIMBUS1_RX,
-		[20] = DMACH_SLIMBUS1_TX,
-		[21] = DMACH_SLIMBUS3_RX,
-		[22] = DMACH_SLIMBUS3_TX,
-		[23] = DMACH_SLIMBUS5_RX,
-		[24] = DMACH_SLIMBUS5_TX,
-		[25] = DMACH_SLIMBUS0AUX_RX,
-		[26] = DMACH_SLIMBUS0AUX_TX,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device s5pv310_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pv310_pdma1_resource),
-	.resource	= s5pv310_pdma1_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &s5pv310_pdma1_pdata,
-	},
-};
-
-static struct platform_device *s5pv310_dmacs[] __initdata = {
-	&s5pv310_device_pdma0,
-	&s5pv310_device_pdma1,
-};
-
-static int __init s5pv310_dma_init(void)
-{
-	platform_add_devices(s5pv310_dmacs, ARRAY_SIZE(s5pv310_dmacs));
-
-	return 0;
-}
-arch_initcall(s5pv310_dma_init);
diff --git a/arch/arm/mach-s5pv310/gpiolib.c b/arch/arm/mach-s5pv310/gpiolib.c
deleted file mode 100644
index 55217b8..0000000
--- a/arch/arm/mach-s5pv310/gpiolib.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/gpiolib.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - GPIOlib support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-/*
- * Following are the gpio banks in v310.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pv310_gpio_part1_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV310_GPA0(0),
-			.ngpio	= S5PV310_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPA1(0),
-			.ngpio	= S5PV310_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPB(0),
-			.ngpio	= S5PV310_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPC0(0),
-			.ngpio	= S5PV310_GPIO_C0_NR,
-			.label	= "GPC0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPC1(0),
-			.ngpio	= S5PV310_GPIO_C1_NR,
-			.label	= "GPC1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPD0(0),
-			.ngpio	= S5PV310_GPIO_D0_NR,
-			.label	= "GPD0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPD1(0),
-			.ngpio	= S5PV310_GPIO_D1_NR,
-			.label	= "GPD1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE0(0),
-			.ngpio	= S5PV310_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE1(0),
-			.ngpio	= S5PV310_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE2(0),
-			.ngpio	= S5PV310_GPIO_E2_NR,
-			.label	= "GPE2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE3(0),
-			.ngpio	= S5PV310_GPIO_E3_NR,
-			.label	= "GPE3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE4(0),
-			.ngpio	= S5PV310_GPIO_E4_NR,
-			.label	= "GPE4",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF0(0),
-			.ngpio	= S5PV310_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF1(0),
-			.ngpio	= S5PV310_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF2(0),
-			.ngpio	= S5PV310_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF3(0),
-			.ngpio	= S5PV310_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV310_GPJ0(0),
-			.ngpio	= S5PV310_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPJ1(0),
-			.ngpio	= S5PV310_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK0(0),
-			.ngpio	= S5PV310_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK1(0),
-			.ngpio	= S5PV310_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK2(0),
-			.ngpio	= S5PV310_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK3(0),
-			.ngpio	= S5PV310_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPL0(0),
-			.ngpio	= S5PV310_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPL1(0),
-			.ngpio	= S5PV310_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPL2(0),
-			.ngpio	= S5PV310_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC00),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PV310_GPX0(0),
-			.ngpio	= S5PV310_GPIO_X0_NR,
-			.label	= "GPX0",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC20),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PV310_GPX1(0),
-			.ngpio	= S5PV310_GPIO_X1_NR,
-			.label	= "GPX1",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC40),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PV310_GPX2(0),
-			.ngpio	= S5PV310_GPIO_X2_NR,
-			.label	= "GPX2",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC60),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PV310_GPX3(0),
-			.ngpio	= S5PV310_GPIO_X3_NR,
-			.label	= "GPX3",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5pv310_gpio_part3_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV310_GPZ(0),
-			.ngpio	= S5PV310_GPIO_Z_NR,
-			.label	= "GPZ",
-		},
-	},
-};
-
-static __init int s5pv310_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip;
-	int i;
-	int nr_chips;
-
-	/* GPIO part 1 */
-
-	chip = s5pv310_gpio_part1_4bit;
-	nr_chips = ARRAY_SIZE(s5pv310_gpio_part1_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
-			chip->config = &gpio_cfg;
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO1 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part1_4bit, nr_chips);
-
-	/* GPIO part 2 */
-
-	chip = s5pv310_gpio_part2_4bit;
-	nr_chips = ARRAY_SIZE(s5pv310_gpio_part2_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
-			chip->config = &gpio_cfg;
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO2 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part2_4bit, nr_chips);
-
-	/* GPIO part 3 */
-
-	chip = s5pv310_gpio_part3_4bit;
-	nr_chips = ARRAY_SIZE(s5pv310_gpio_part3_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
-			chip->config = &gpio_cfg;
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO3 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part3_4bit, nr_chips);
-
-	return 0;
-}
-core_initcall(s5pv310_gpiolib_init);
diff --git a/arch/arm/mach-s5pv310/headsmp.S b/arch/arm/mach-s5pv310/headsmp.S
deleted file mode 100644
index 164b7b0..0000000
--- a/arch/arm/mach-s5pv310/headsmp.S
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  linux/arch/arm/mach-s5pv310/headsmp.S
- *
- *  Cloned from linux/arch/arm/mach-realview/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  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/linkage.h>
-#include <linux/init.h>
-
-	__INIT
-
-/*
- * s5pv310 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(s5pv310_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
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-1:	.long	.
-	.long	pen_release
diff --git a/arch/arm/mach-s5pv310/hotplug.c b/arch/arm/mach-s5pv310/hotplug.c
deleted file mode 100644
index c24235c..0000000
--- a/arch/arm/mach-s5pv310/hotplug.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* linux arch/arm/mach-s5pv310/hotplug.c
- *
- *  Cloned from 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>
-
-extern volatile int pen_release;
-
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
-
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	mcr	p15, 0, %1, c7, c10, 4\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");
-}
-
-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 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 (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-
-		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)++;
-	}
-}
-
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void platform_cpu_die(unsigned int cpu)
-{
-	int spurious = 0;
-
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_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);
-}
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff --git a/arch/arm/mach-s5pv310/include/mach/debug-macro.S b/arch/arm/mach-s5pv310/include/mach/debug-macro.S
deleted file mode 100644
index b0d920c..0000000
--- a/arch/arm/mach-s5pv310/include/mach/debug-macro.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/debug-macro.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-
-	/* note, for the boot process to work we have to keep the UART
-	 * virtual address aligned to an 1MiB boundary for the L1
-	 * mapping the head code makes. We keep the UART virtual address
-	 * aligned and add in the offset when we load the value here.
-	 */
-
-	.macro addruart, rp, rv
-		ldreq	\rp, = S3C_PA_UART
-		ldrne	\rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-#define fifo_full fifo_full_s5pv210
-#define fifo_level fifo_level_s5pv210
-
-#include <plat/debug-macro.S>
diff --git a/arch/arm/mach-s5pv310/include/mach/dma.h b/arch/arm/mach-s5pv310/include/mach/dma.h
deleted file mode 100644
index 81209eb..0000000
--- a/arch/arm/mach-s5pv310/include/mach/dma.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
-
-#endif /* __MACH_DMA_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/entry-macro.S b/arch/arm/mach-s5pv310/include/mach/entry-macro.S
deleted file mode 100644
index e600e1d..0000000
--- a/arch/arm/mach-s5pv310/include/mach/entry-macro.S
+++ /dev/null
@@ -1,84 +0,0 @@
-/* arch/arm/mach-s5pv310/include/mach/entry-macro.S
- *
- * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for S5PV310 platforms
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
-*/
-
-#include <mach/hardware.h>
-#include <asm/hardware/gic.h>
-
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		/*
-		 * The interrupt numbering scheme is defined in the
-		 * interrupt controller spec.  To wit:
-		 *
-		 * Interrupts 0-15 are IPI
-		 * 16-28 are reserved
-		 * 29-31 are local.  We allow 30 to be used for the watchdog.
-		 * 32-1020 are global
-		 * 1021-1022 are reserved
-		 * 1023 is "spurious" (no interrupt)
-		 *
-		 * For now, we ignore all local interrupts so only return an interrupt if it's
-		 * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-		 *
-		 * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-		 * valid range for an IRQ (30-1020 inclusive).
-		 */
-
-		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-		ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-		addne	\irqnr, \irqnr, #32
-
-		.endm
-
-		/* We assume that irqstat (the raw value of the IRQ acknowledge
-		 * register) is preserved from the macro above.
-		 * If there is an IPI, we immediately signal end of interrupt on the
-		 * controller, since this requires the original irqstat value which
-		 * we won't easily be able to recreate later.
-		 */
-
-		.macro test_for_ipi, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		cmp	\irqnr, #16
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		cmpcs	\irqnr, \irqnr
-		.endm
-
-		/* As above, this assumes that irqstat and base are preserved.. */
-
-		.macro test_for_ltirq, irqnr, irqstat, base, tmp
-		bic	\irqnr, \irqstat, #0x1c00
-		mov	\tmp, #0
-		cmp	\irqnr, #29
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff --git a/arch/arm/mach-s5pv310/include/mach/gpio.h b/arch/arm/mach-s5pv310/include/mach/gpio.h
deleted file mode 100644
index 20cb80c..0000000
--- a/arch/arm/mach-s5pv310/include/mach/gpio.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - GPIO lib 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_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
-/* Practically, GPIO banks upto GPZ are the configurable gpio banks */
-
-/* GPIO bank sizes */
-#define S5PV310_GPIO_A0_NR	(8)
-#define S5PV310_GPIO_A1_NR	(6)
-#define S5PV310_GPIO_B_NR	(8)
-#define S5PV310_GPIO_C0_NR	(5)
-#define S5PV310_GPIO_C1_NR	(5)
-#define S5PV310_GPIO_D0_NR	(4)
-#define S5PV310_GPIO_D1_NR	(4)
-#define S5PV310_GPIO_E0_NR	(5)
-#define S5PV310_GPIO_E1_NR	(8)
-#define S5PV310_GPIO_E2_NR	(6)
-#define S5PV310_GPIO_E3_NR	(8)
-#define S5PV310_GPIO_E4_NR	(8)
-#define S5PV310_GPIO_F0_NR	(8)
-#define S5PV310_GPIO_F1_NR	(8)
-#define S5PV310_GPIO_F2_NR	(8)
-#define S5PV310_GPIO_F3_NR	(6)
-#define S5PV310_GPIO_J0_NR	(8)
-#define S5PV310_GPIO_J1_NR	(5)
-#define S5PV310_GPIO_K0_NR	(7)
-#define S5PV310_GPIO_K1_NR	(7)
-#define S5PV310_GPIO_K2_NR	(7)
-#define S5PV310_GPIO_K3_NR	(7)
-#define S5PV310_GPIO_L0_NR	(8)
-#define S5PV310_GPIO_L1_NR	(3)
-#define S5PV310_GPIO_L2_NR	(8)
-#define S5PV310_GPIO_X0_NR	(8)
-#define S5PV310_GPIO_X1_NR	(8)
-#define S5PV310_GPIO_X2_NR	(8)
-#define S5PV310_GPIO_X3_NR	(8)
-#define S5PV310_GPIO_Z_NR	(7)
-
-/* GPIO bank numbers */
-
-#define S5PV310_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-	S5PV310_GPIO_A0_START	= 0,
-	S5PV310_GPIO_A1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A0),
-	S5PV310_GPIO_B_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A1),
-	S5PV310_GPIO_C0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_B),
-	S5PV310_GPIO_C1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C0),
-	S5PV310_GPIO_D0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C1),
-	S5PV310_GPIO_D1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D0),
-	S5PV310_GPIO_E0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D1),
-	S5PV310_GPIO_E1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E0),
-	S5PV310_GPIO_E2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E1),
-	S5PV310_GPIO_E3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E2),
-	S5PV310_GPIO_E4_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E3),
-	S5PV310_GPIO_F0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E4),
-	S5PV310_GPIO_F1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F0),
-	S5PV310_GPIO_F2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F1),
-	S5PV310_GPIO_F3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F2),
-	S5PV310_GPIO_J0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F3),
-	S5PV310_GPIO_J1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J0),
-	S5PV310_GPIO_K0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J1),
-	S5PV310_GPIO_K1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K0),
-	S5PV310_GPIO_K2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K1),
-	S5PV310_GPIO_K3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K2),
-	S5PV310_GPIO_L0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K3),
-	S5PV310_GPIO_L1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L0),
-	S5PV310_GPIO_L2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L1),
-	S5PV310_GPIO_X0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L2),
-	S5PV310_GPIO_X1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
-	S5PV310_GPIO_X2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
-	S5PV310_GPIO_X3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
-	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
-};
-
-/* S5PV310 GPIO number definitions */
-#define S5PV310_GPA0(_nr)	(S5PV310_GPIO_A0_START + (_nr))
-#define S5PV310_GPA1(_nr)	(S5PV310_GPIO_A1_START + (_nr))
-#define S5PV310_GPB(_nr)	(S5PV310_GPIO_B_START + (_nr))
-#define S5PV310_GPC0(_nr)	(S5PV310_GPIO_C0_START + (_nr))
-#define S5PV310_GPC1(_nr)	(S5PV310_GPIO_C1_START + (_nr))
-#define S5PV310_GPD0(_nr)	(S5PV310_GPIO_D0_START + (_nr))
-#define S5PV310_GPD1(_nr)	(S5PV310_GPIO_D1_START + (_nr))
-#define S5PV310_GPE0(_nr)	(S5PV310_GPIO_E0_START + (_nr))
-#define S5PV310_GPE1(_nr)	(S5PV310_GPIO_E1_START + (_nr))
-#define S5PV310_GPE2(_nr)	(S5PV310_GPIO_E2_START + (_nr))
-#define S5PV310_GPE3(_nr)	(S5PV310_GPIO_E3_START + (_nr))
-#define S5PV310_GPE4(_nr)	(S5PV310_GPIO_E4_START + (_nr))
-#define S5PV310_GPF0(_nr)	(S5PV310_GPIO_F0_START + (_nr))
-#define S5PV310_GPF1(_nr)	(S5PV310_GPIO_F1_START + (_nr))
-#define S5PV310_GPF2(_nr)	(S5PV310_GPIO_F2_START + (_nr))
-#define S5PV310_GPF3(_nr)	(S5PV310_GPIO_F3_START + (_nr))
-#define S5PV310_GPJ0(_nr)	(S5PV310_GPIO_J0_START + (_nr))
-#define S5PV310_GPJ1(_nr)	(S5PV310_GPIO_J1_START + (_nr))
-#define S5PV310_GPK0(_nr)	(S5PV310_GPIO_K0_START + (_nr))
-#define S5PV310_GPK1(_nr)	(S5PV310_GPIO_K1_START + (_nr))
-#define S5PV310_GPK2(_nr)	(S5PV310_GPIO_K2_START + (_nr))
-#define S5PV310_GPK3(_nr)	(S5PV310_GPIO_K3_START + (_nr))
-#define S5PV310_GPL0(_nr)	(S5PV310_GPIO_L0_START + (_nr))
-#define S5PV310_GPL1(_nr)	(S5PV310_GPIO_L1_START + (_nr))
-#define S5PV310_GPL2(_nr)	(S5PV310_GPIO_L2_START + (_nr))
-#define S5PV310_GPX0(_nr)	(S5PV310_GPIO_X0_START + (_nr))
-#define S5PV310_GPX1(_nr)	(S5PV310_GPIO_X1_START + (_nr))
-#define S5PV310_GPX2(_nr)	(S5PV310_GPIO_X2_START + (_nr))
-#define S5PV310_GPX3(_nr)	(S5PV310_GPIO_X3_START + (_nr))
-#define S5PV310_GPZ(_nr)	(S5PV310_GPIO_Z_START + (_nr))
-
-/* the end of the S5PV310 specific gpios */
-#define S5PV310_GPIO_END	(S5PV310_GPZ(S5PV310_GPIO_Z_NR) + 1)
-#define S3C_GPIO_END		S5PV310_GPIO_END
-
-/* define the number of gpios we need to the one after the GPZ() range */
-#define ARCH_NR_GPIOS		(S5PV310_GPZ(S5PV310_GPIO_Z_NR) +	\
-				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/hardware.h b/arch/arm/mach-s5pv310/include/mach/hardware.h
deleted file mode 100644
index 28ff988..0000000
--- a/arch/arm/mach-s5pv310/include/mach/hardware.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/hardware.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Hardware 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_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/io.h b/arch/arm/mach-s5pv310/include/mach/io.h
deleted file mode 100644
index 8a7f912..0000000
--- a/arch/arm/mach-s5pv310/include/mach/io.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/io.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/io.h
- *
- * Default IO routines for S5PV310
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H __FILE__
-
-/* No current ISA/PCI bus support. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
deleted file mode 100644
index 536b0b5..0000000
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/irqs.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - IRQ definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* PPI: Private Peripheral Interrupt */
-
-#define IRQ_PPI(x)		S5P_IRQ(x+16)
-
-#define IRQ_LOCALTIMER		IRQ_PPI(13)
-
-/* SPI: Shared Peripheral Interrupt */
-
-#define IRQ_SPI(x)		S5P_IRQ(x+32)
-
-#define IRQ_MCT1		IRQ_SPI(35)
-
-#define IRQ_EINT0		IRQ_SPI(40)
-#define IRQ_EINT1		IRQ_SPI(41)
-#define IRQ_EINT2		IRQ_SPI(42)
-#define IRQ_EINT3		IRQ_SPI(43)
-#define IRQ_USB_HSOTG		IRQ_SPI(44)
-#define IRQ_USB_HOST		IRQ_SPI(45)
-#define IRQ_MODEM_IF		IRQ_SPI(46)
-#define IRQ_ROTATOR		IRQ_SPI(47)
-#define IRQ_JPEG		IRQ_SPI(48)
-#define IRQ_2D			IRQ_SPI(49)
-#define IRQ_PCIE		IRQ_SPI(50)
-#define IRQ_MCT0		IRQ_SPI(51)
-#define IRQ_MFC			IRQ_SPI(52)
-#define IRQ_AUDIO_SS		IRQ_SPI(54)
-#define IRQ_AC97		IRQ_SPI(55)
-#define IRQ_SPDIF		IRQ_SPI(56)
-#define IRQ_KEYPAD		IRQ_SPI(57)
-#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(58)
-#define IRQ_SLIMBUS		IRQ_SPI(59)
-#define IRQ_PMU			IRQ_SPI(60)
-#define IRQ_TSI			IRQ_SPI(61)
-#define IRQ_SATA		IRQ_SPI(62)
-#define IRQ_GPS			IRQ_SPI(63)
-
-#define MAX_IRQ_IN_COMBINER	8
-#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
-#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
-
-#define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
-#define IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
-#define IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
-#define IRQ_SYSMMU_FIMC1_0	COMBINER_IRQ(4, 3)
-#define IRQ_SYSMMU_FIMC2_0	COMBINER_IRQ(4, 4)
-#define IRQ_SYSMMU_FIMC3_0	COMBINER_IRQ(4, 5)
-#define IRQ_SYSMMU_JPEG_0	COMBINER_IRQ(4, 6)
-#define IRQ_SYSMMU_2D_0		COMBINER_IRQ(4, 7)
-
-#define IRQ_SYSMMU_ROTATOR_0	COMBINER_IRQ(5, 0)
-#define IRQ_SYSMMU_MDMA1_0	COMBINER_IRQ(5, 1)
-#define IRQ_SYSMMU_LCD0_M0_0	COMBINER_IRQ(5, 2)
-#define IRQ_SYSMMU_LCD1_M1_0	COMBINER_IRQ(5, 3)
-#define IRQ_SYSMMU_TV_M0_0	COMBINER_IRQ(5, 4)
-#define IRQ_SYSMMU_MFC_M0_0	COMBINER_IRQ(5, 5)
-#define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
-#define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
-
-#define IRQ_PDMA0		COMBINER_IRQ(21, 0)
-#define IRQ_PDMA1		COMBINER_IRQ(21, 1)
-
-#define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
-#define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
-#define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
-#define IRQ_TIMER3_VIC		COMBINER_IRQ(22, 3)
-#define IRQ_TIMER4_VIC		COMBINER_IRQ(22, 4)
-
-#define IRQ_RTC_ALARM		COMBINER_IRQ(23, 0)
-#define IRQ_RTC_TIC		COMBINER_IRQ(23, 1)
-
-#define IRQ_UART0		COMBINER_IRQ(26, 0)
-#define IRQ_UART1		COMBINER_IRQ(26, 1)
-#define IRQ_UART2		COMBINER_IRQ(26, 2)
-#define IRQ_UART3		COMBINER_IRQ(26, 3)
-#define IRQ_UART4		COMBINER_IRQ(26, 4)
-
-#define IRQ_IIC			COMBINER_IRQ(27, 0)
-#define IRQ_IIC1		COMBINER_IRQ(27, 1)
-#define IRQ_IIC2		COMBINER_IRQ(27, 2)
-#define IRQ_IIC3		COMBINER_IRQ(27, 3)
-#define IRQ_IIC4		COMBINER_IRQ(27, 4)
-#define IRQ_IIC5		COMBINER_IRQ(27, 5)
-#define IRQ_IIC6		COMBINER_IRQ(27, 6)
-#define IRQ_IIC7		COMBINER_IRQ(27, 7)
-
-#define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
-#define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
-#define IRQ_HSMMC2		COMBINER_IRQ(29, 2)
-#define IRQ_HSMMC3		COMBINER_IRQ(29, 3)
-
-#define IRQ_MIPI_CSIS0		COMBINER_IRQ(30, 0)
-#define IRQ_MIPI_CSIS1		COMBINER_IRQ(30, 1)
-
-#define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
-
-#define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
-
-#define IRQ_EINT4		COMBINER_IRQ(37, 0)
-#define IRQ_EINT5		COMBINER_IRQ(37, 1)
-#define IRQ_EINT6		COMBINER_IRQ(37, 2)
-#define IRQ_EINT7		COMBINER_IRQ(37, 3)
-#define IRQ_EINT8		COMBINER_IRQ(38, 0)
-
-#define IRQ_EINT9		COMBINER_IRQ(38, 1)
-#define IRQ_EINT10		COMBINER_IRQ(38, 2)
-#define IRQ_EINT11		COMBINER_IRQ(38, 3)
-#define IRQ_EINT12		COMBINER_IRQ(38, 4)
-#define IRQ_EINT13		COMBINER_IRQ(38, 5)
-#define IRQ_EINT14		COMBINER_IRQ(38, 6)
-#define IRQ_EINT15		COMBINER_IRQ(38, 7)
-
-#define IRQ_EINT16_31		COMBINER_IRQ(39, 0)
-
-#define IRQ_MCT_L0		COMBINER_IRQ(51, 0)
-
-#define IRQ_WDT			COMBINER_IRQ(53, 0)
-
-#define MAX_COMBINER_NR		54
-
-#define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
-#define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
-
-/* Set the default NR_IRQS */
-
-#define NR_IRQS			(S5P_IRQ_EINT_BASE + 32)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
deleted file mode 100644
index 901657f..0000000
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/map.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Memory map definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-
-/*
- * S5PV310 UART offset is 0x10000 but the older S5P SoCs are 0x400.
- * So need to define it, and here is to avoid redefinition warning.
- */
-#define S3C_UART_OFFSET			(0x10000)
-
-#include <plat/map-s5p.h>
-
-#define S5PV310_PA_SYSRAM		0x02025000
-
-#define S5PV310_PA_I2S0			0x03830000
-#define S5PV310_PA_I2S1			0xE3100000
-#define S5PV310_PA_I2S2			0xE2A00000
-
-#define S5PV310_PA_PCM0			0x03840000
-#define S5PV310_PA_PCM1			0x13980000
-#define S5PV310_PA_PCM2			0x13990000
-
-#define S5PV310_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
-
-#define S5PC210_PA_ONENAND		0x0C000000
-#define S5PC210_PA_ONENAND_DMA		0x0C600000
-
-#define S5PV310_PA_CHIPID		0x10000000
-
-#define S5PV310_PA_SYSCON		0x10010000
-#define S5PV310_PA_PMU			0x10020000
-#define S5PV310_PA_CMU			0x10030000
-
-#define S5PV310_PA_WATCHDOG		0x10060000
-#define S5PV310_PA_RTC			0x10070000
-
-#define S5PV310_PA_DMC0			0x10400000
-
-#define S5PV310_PA_COMBINER		0x10448000
-
-#define S5PV310_PA_COREPERI		0x10500000
-#define S5PV310_PA_GIC_CPU		0x10500100
-#define S5PV310_PA_TWD			0x10500600
-#define S5PV310_PA_GIC_DIST		0x10501000
-#define S5PV310_PA_L2CC			0x10502000
-
-#define S5PV310_PA_MDMA			0x10810000
-#define S5PV310_PA_PDMA0		0x12680000
-#define S5PV310_PA_PDMA1		0x12690000
-
-#define S5PV310_PA_SYSMMU_MDMA		0x10A40000
-#define S5PV310_PA_SYSMMU_SSS		0x10A50000
-#define S5PV310_PA_SYSMMU_FIMC0		0x11A20000
-#define S5PV310_PA_SYSMMU_FIMC1		0x11A30000
-#define S5PV310_PA_SYSMMU_FIMC2		0x11A40000
-#define S5PV310_PA_SYSMMU_FIMC3		0x11A50000
-#define S5PV310_PA_SYSMMU_JPEG		0x11A60000
-#define S5PV310_PA_SYSMMU_FIMD0		0x11E20000
-#define S5PV310_PA_SYSMMU_FIMD1		0x12220000
-#define S5PV310_PA_SYSMMU_PCIe		0x12620000
-#define S5PV310_PA_SYSMMU_G2D		0x12A20000
-#define S5PV310_PA_SYSMMU_ROTATOR	0x12A30000
-#define S5PV310_PA_SYSMMU_MDMA2		0x12A40000
-#define S5PV310_PA_SYSMMU_TV		0x12E20000
-#define S5PV310_PA_SYSMMU_MFC_L		0x13620000
-#define S5PV310_PA_SYSMMU_MFC_R		0x13630000
-
-#define S5PV310_PA_GPIO1		0x11400000
-#define S5PV310_PA_GPIO2		0x11000000
-#define S5PV310_PA_GPIO3		0x03860000
-
-#define S5PV310_PA_MIPI_CSIS0		0x11880000
-#define S5PV310_PA_MIPI_CSIS1		0x11890000
-
-#define S5PV310_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
-
-#define S5PV310_PA_SROMC		0x12570000
-
-#define S5PV310_PA_UART			0x13800000
-
-#define S5PV310_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
-
-#define S5PV310_PA_AC97			0x139A0000
-
-#define S5PV310_PA_TIMER		0x139D0000
-
-#define S5PV310_PA_SDRAM		0x40000000
-
-#define S5PV310_PA_SPDIF		0xE1100000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_HSMMC0			S5PV310_PA_HSMMC(0)
-#define S3C_PA_HSMMC1			S5PV310_PA_HSMMC(1)
-#define S3C_PA_HSMMC2			S5PV310_PA_HSMMC(2)
-#define S3C_PA_HSMMC3			S5PV310_PA_HSMMC(3)
-#define S3C_PA_IIC			S5PV310_PA_IIC(0)
-#define S3C_PA_IIC1			S5PV310_PA_IIC(1)
-#define S3C_PA_IIC2			S5PV310_PA_IIC(2)
-#define S3C_PA_IIC3			S5PV310_PA_IIC(3)
-#define S3C_PA_IIC4			S5PV310_PA_IIC(4)
-#define S3C_PA_IIC5			S5PV310_PA_IIC(5)
-#define S3C_PA_IIC6			S5PV310_PA_IIC(6)
-#define S3C_PA_IIC7			S5PV310_PA_IIC(7)
-#define S3C_PA_RTC			S5PV310_PA_RTC
-#define S3C_PA_WDT			S5PV310_PA_WATCHDOG
-
-#define S5P_PA_CHIPID			S5PV310_PA_CHIPID
-#define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
-#define S5P_PA_MIPI_CSIS1		S5PV310_PA_MIPI_CSIS1
-#define S5P_PA_ONENAND			S5PC210_PA_ONENAND
-#define S5P_PA_ONENAND_DMA		S5PC210_PA_ONENAND_DMA
-#define S5P_PA_SDRAM			S5PV310_PA_SDRAM
-#define S5P_PA_SROMC			S5PV310_PA_SROMC
-#define S5P_PA_SYSCON			S5PV310_PA_SYSCON
-#define S5P_PA_TIMER			S5PV310_PA_TIMER
-
-/* UART */
-
-#define S3C_PA_UART			S5PV310_PA_UART
-
-#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0			S5P_PA_UART(0)
-#define S5P_PA_UART1			S5P_PA_UART(1)
-#define S5P_PA_UART2			S5P_PA_UART(2)
-#define S5P_PA_UART3			S5P_PA_UART(3)
-#define S5P_PA_UART4			S5P_PA_UART(4)
-
-#define S5P_SZ_UART			SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/memory.h b/arch/arm/mach-s5pv310/include/mach/memory.h
deleted file mode 100644
index 1dffb48..0000000
--- a/arch/arm/mach-s5pv310/include/mach/memory.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/memory.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Memory definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H __FILE__
-
-#define PHYS_OFFSET		UL(0x40000000)
-
-/* Maximum of 256MiB in one bank */
-#define MAX_PHYSMEM_BITS	32
-#define SECTION_SIZE_BITS	28
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/pwm-clock.h b/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
deleted file mode 100644
index 7e6da27..0000000
--- a/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * S5PV310 - pwm clock and 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.
-*/
-
-#ifndef __ASM_ARCH_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
deleted file mode 100644
index b5c4ada..0000000
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-clock.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Clock register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
-
-#define S5P_INFORM0			S5P_CLKREG(0x800)
-
-#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
-#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
-
-#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
-#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
-
-#define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
-#define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
-#define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
-#define S5P_VPLL_CON1			S5P_CLKREG(0x0C124)
-
-#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
-#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
-#define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
-#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
-#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
-#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
-#define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
-#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
-#define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
-
-#define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
-#define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
-#define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
-#define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
-#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
-#define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
-#define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
-#define S5P_CLKDIV_FSYS2		S5P_CLKREG(0x0C548)
-#define S5P_CLKDIV_FSYS3		S5P_CLKREG(0x0C54C)
-#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x0C550)
-#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x0C554)
-#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x0C558)
-#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
-#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
-#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
-
-#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
-#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
-#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
-#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
-#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
-#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
-#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
-
-#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
-
-#define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
-#define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
-#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
-#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
-#define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
-#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
-#define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
-
-#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
-#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
-#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
-
-#define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
-#define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
-#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
-#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
-#define S5P_MPLL_CON0			S5P_CLKREG(0x14108)
-#define S5P_MPLL_CON1			S5P_CLKREG(0x1410C)
-
-#define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
-#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
-
-#define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
-#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
-#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
-#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
-
-#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
-
-/* APLL_LOCK */
-#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
-
-/* APLL_CON0 */
-#define S5P_APLLCON0_ENABLE_SHIFT	(31)
-#define S5P_APLLCON0_LOCKED_SHIFT	(29)
-#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
-#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
-
-/* CLK_SRC_CPU */
-#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
-#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
-
-/* CLKDIV_CPU0 */
-#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
-#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
-#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
-#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
-#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
-#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
-#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
-#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
-#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
-#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
-#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
-#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
-#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
-#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
-
-/* CLKDIV_DMC0 */
-#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
-#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
-#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
-#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
-#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
-#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
-#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
-#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
-#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
-#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
-#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
-#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
-#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
-#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
-#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
-#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
-
-/* CLKDIV_TOP */
-#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
-#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
-#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
-#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
-#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
-#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
-#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
-
-/* CLKDIV_LEFTBUS / CLKDIV_RIGHTBUS*/
-#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
-#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
-#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
-#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
-
-/* Compatibility defines */
-
-#define S5P_EPLL_CON			S5P_EPLL_CON0
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-gpio.h b/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
deleted file mode 100644
index 82e9e0c..0000000
--- a/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - GPIO (including EINT) register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#define S5PV310_EINT40CON		(S5P_VA_GPIO2 + 0xE00)
-#define S5P_EINT_CON(x)			(S5PV310_EINT40CON + ((x) * 0x4))
-
-#define S5PV310_EINT40FLTCON0		(S5P_VA_GPIO2 + 0xE80)
-#define S5P_EINT_FLTCON(x)		(S5PV310_EINT40FLTCON0 + ((x) * 0x4))
-
-#define S5PV310_EINT40MASK		(S5P_VA_GPIO2 + 0xF00)
-#define S5P_EINT_MASK(x)		(S5PV310_EINT40MASK + ((x) * 0x4))
-
-#define S5PV310_EINT40PEND		(S5P_VA_GPIO2 + 0xF40)
-#define S5P_EINT_PEND(x)		(S5PV310_EINT40PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE			S3C_GPIO_SFN(0xf)
-
-#define EINT_GPIO_0(x)			S5PV310_GPX0(x)
-#define EINT_GPIO_1(x)			S5PV310_GPX1(x)
-#define EINT_GPIO_2(x)			S5PV310_GPX2(x)
-#define EINT_GPIO_3(x)			S5PV310_GPX3(x)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-irq.h b/arch/arm/mach-s5pv310/include/mach/regs-irq.h
deleted file mode 100644
index c6e09c7..0000000
--- a/arch/arm/mach-s5pv310/include/mach/regs-irq.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-irq.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - IRQ register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <asm/hardware/gic.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-mem.h b/arch/arm/mach-s5pv310/include/mach/regs-mem.h
deleted file mode 100644
index 8342271..0000000
--- a/arch/arm/mach-s5pv310/include/mach/regs-mem.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-mem.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - SROMC and DMC register definitions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_REGS_MEM_H
-#define __ASM_ARCH_REGS_MEM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_DMC0_MEMCON_OFFSET		0x04
-
-#define S5P_DMC0_MEMTYPE_SHIFT		8
-#define S5P_DMC0_MEMTYPE_MASK		0xF
-
-#endif /* __ASM_ARCH_REGS_MEM_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-pmu.h b/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
deleted file mode 100644
index fb333d0..0000000
--- a/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - Power management unit definition
- *
- * This program is free software; you can 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_PMU_H
-#define __ASM_ARCH_REGS_PMU_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_PMUREG(x)			(S5P_VA_PMU + (x))
-
-#define S5P_PMU_CAM_CONF		S5P_PMUREG(0x3C00)
-#define S5P_PMU_TV_CONF		S5P_PMUREG(0x3C20)
-#define S5P_PMU_MFC_CONF		S5P_PMUREG(0x3C40)
-#define S5P_PMU_G3D_CONF		S5P_PMUREG(0x3C60)
-#define S5P_PMU_LCD0_CONF		S5P_PMUREG(0x3C80)
-#define S5P_PMU_LCD1_CONF		S5P_PMUREG(0x3CA0)
-#define S5P_PMU_GPS_CONF		S5P_PMUREG(0x3CE0)
-
-#define S5P_INT_LOCAL_PWR_EN		0x7
-
-#endif /* __ASM_ARCH_REGS_PMU_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h b/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
deleted file mode 100644
index 0b28e81..0000000
--- a/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - System MMU register
- *
- * This program is free software; you can 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_SYSMMU_H
-#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
-
-#define S5P_MMU_CTRL			0x000
-#define S5P_MMU_CFG			0x004
-#define S5P_MMU_STATUS			0x008
-#define S5P_MMU_FLUSH			0x00C
-#define S5P_PT_BASE_ADDR		0x014
-#define S5P_INT_STATUS			0x018
-#define S5P_PAGE_FAULT_ADDR		0x024
-
-#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/smp.h b/arch/arm/mach-s5pv310/include/mach/smp.h
deleted file mode 100644
index 393ccbd..0000000
--- a/arch/arm/mach-s5pv310/include/mach/smp.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/smp.h
- *
- * Cloned from arch/arm/mach-realview/include/mach/smp.h
-*/
-
-#ifndef ASM_ARCH_SMP_H
-#define ASM_ARCH_SMP_H __FILE__
-
-#include <asm/hardware/gic.h>
-
-/*
- * We use IRQ1 as the IPI
- */
-static inline void smp_cross_call(const struct cpumask *mask, int ipi)
-{
-	gic_raise_softirq(mask, ipi);
-}
-
-#endif
diff --git a/arch/arm/mach-s5pv310/include/mach/sysmmu.h b/arch/arm/mach-s5pv310/include/mach/sysmmu.h
deleted file mode 100644
index 598fc5c..0000000
--- a/arch/arm/mach-s5pv310/include/mach/sysmmu.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/sysmmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Samsung sysmmu driver for S5PV310
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-#define S5PV310_SYSMMU_TOTAL_IPNUM	16
-#define S5P_SYSMMU_TOTAL_IPNUM		S5PV310_SYSMMU_TOTAL_IPNUM
-
-enum s5pv310_sysmmu_ips {
-	SYSMMU_MDMA,
-	SYSMMU_SSS,
-	SYSMMU_FIMC0,
-	SYSMMU_FIMC1,
-	SYSMMU_FIMC2,
-	SYSMMU_FIMC3,
-	SYSMMU_JPEG,
-	SYSMMU_FIMD0,
-	SYSMMU_FIMD1,
-	SYSMMU_PCIe,
-	SYSMMU_G2D,
-	SYSMMU_ROTATOR,
-	SYSMMU_MDMA2,
-	SYSMMU_TV,
-	SYSMMU_MFC_L,
-	SYSMMU_MFC_R,
-};
-
-static char *sysmmu_ips_name[S5PV310_SYSMMU_TOTAL_IPNUM] = {
-	"SYSMMU_MDMA"	,
-	"SYSMMU_SSS"	,
-	"SYSMMU_FIMC0"	,
-	"SYSMMU_FIMC1"	,
-	"SYSMMU_FIMC2"	,
-	"SYSMMU_FIMC3"	,
-	"SYSMMU_JPEG"	,
-	"SYSMMU_FIMD0"	,
-	"SYSMMU_FIMD1"	,
-	"SYSMMU_PCIe"	,
-	"SYSMMU_G2D"	,
-	"SYSMMU_ROTATOR",
-	"SYSMMU_MDMA2"	,
-	"SYSMMU_TV"	,
-	"SYSMMU_MFC_L"	,
-	"SYSMMU_MFC_R"	,
-};
-
-typedef enum s5pv310_sysmmu_ips sysmmu_ips;
-
-struct sysmmu_tt_info {
-	unsigned long *pgd;
-	unsigned long pgd_paddr;
-	unsigned long *pte;
-};
-
-struct sysmmu_controller {
-	const char		*name;
-
-	/* channels registers */
-	void __iomem		*regs;
-
-	/* channel irq */
-	unsigned int		irq;
-
-	sysmmu_ips		ips;
-
-	/* Translation Table Info. */
-	struct sysmmu_tt_info	*tt_info;
-
-	struct resource		*mem;
-	struct device		*dev;
-
-	/* SysMMU controller enable - true : enable */
-	bool			enable;
-};
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_enable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/system.h b/arch/arm/mach-s5pv310/include/mach/system.h
deleted file mode 100644
index d10c009..0000000
--- a/arch/arm/mach-s5pv310/include/mach/system.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/system.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - system support header
- *
- * This program is free software; you can 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_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H __FILE__
-
-#include <plat/system-reset.h>
-
-static void arch_idle(void)
-{
-	/* nothing here yet */
-}
-#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/timex.h b/arch/arm/mach-s5pv310/include/mach/timex.h
deleted file mode 100644
index bd2359b..0000000
--- a/arch/arm/mach-s5pv310/include/mach/timex.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/timex.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright (c) 2003-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/timex.h
- *
- * S5PV310 - time parameters
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_TIMEX_H
-#define __ASM_ARCH_TIMEX_H __FILE__
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/uncompress.h b/arch/arm/mach-s5pv310/include/mach/uncompress.h
deleted file mode 100644
index 59593c1..0000000
--- a/arch/arm/mach-s5pv310/include/mach/uncompress.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/uncompress.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - uncompress 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.
-*/
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H __FILE__
-
-#include <mach/map.h>
-#include <plat/uncompress.h>
-
-static void arch_detect_cpu(void)
-{
-	/* we do not need to do any cpu detection here at the moment. */
-
-	/*
-	 * For preventing FIFO overrun or infinite loop of UART console,
-	 * fifo_max should be the minimum fifo size of all of the UART channels
-	 */
-	fifo_mask = S5PV210_UFSTAT_TXMASK;
-	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
-}
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/vmalloc.h b/arch/arm/mach-s5pv310/include/mach/vmalloc.h
deleted file mode 100644
index 65759fb..0000000
--- a/arch/arm/mach-s5pv310/include/mach/vmalloc.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/vmalloc.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * S5PV310 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H __FILE__
-
-#define VMALLOC_END	0xF6000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/arch/arm/mach-s5pv310/init.c b/arch/arm/mach-s5pv310/init.c
deleted file mode 100644
index 182dcf4..0000000
--- a/arch/arm/mach-s5pv310/init.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/init.c
- *
- * Copyright (c) 2010 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.
-*/
-
-#include <linux/serial_core.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/regs-serial.h>
-
-static struct s3c24xx_uart_clksrc s5pv310_serial_clocks[] = {
-	[0] = {
-		.name		= "uclk1",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-};
-
-/* uart registration process */
-void __init s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	struct s3c2410_uartcfg *tcfg = cfg;
-	u32 ucnt;
-
-	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
-		if (!tcfg->clocks) {
-			tcfg->has_fracval = 1;
-			tcfg->clocks = s5pv310_serial_clocks;
-			tcfg->clocks_size = ARRAY_SIZE(s5pv310_serial_clocks);
-		}
-	}
-
-	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
-}
diff --git a/arch/arm/mach-s5pv310/irq-combiner.c b/arch/arm/mach-s5pv310/irq-combiner.c
deleted file mode 100644
index 1ea4a9e..0000000
--- a/arch/arm/mach-s5pv310/irq-combiner.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/irq-combiner.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/common/gic.c
- *
- * IRQ COMBINER 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 <asm/mach/irq.h>
-
-#define COMBINER_ENABLE_SET	0x0
-#define COMBINER_ENABLE_CLEAR	0x4
-#define COMBINER_INT_STATUS	0xC
-
-static DEFINE_SPINLOCK(irq_controller_lock);
-
-struct combiner_chip_data {
-	unsigned int irq_offset;
-	unsigned int irq_mask;
-	void __iomem *base;
-};
-
-static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
-
-static inline void __iomem *combiner_base(struct irq_data *data)
-{
-	struct combiner_chip_data *combiner_data =
-		irq_data_get_irq_chip_data(data);
-
-	return combiner_data->base;
-}
-
-static void combiner_mask_irq(struct irq_data *data)
-{
-	u32 mask = 1 << (data->irq % 32);
-
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
-}
-
-static void combiner_unmask_irq(struct irq_data *data)
-{
-	u32 mask = 1 << (data->irq % 32);
-
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
-}
-
-static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
-{
-	struct combiner_chip_data *chip_data = get_irq_data(irq);
-	struct irq_chip *chip = get_irq_chip(irq);
-	unsigned int cascade_irq, combiner_irq;
-	unsigned long status;
-
-	/* primary controller ack'ing */
-	chip->irq_ack(&desc->irq_data);
-
-	spin_lock(&irq_controller_lock);
-	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
-	spin_unlock(&irq_controller_lock);
-	status &= chip_data->irq_mask;
-
-	if (status == 0)
-		goto out;
-
-	combiner_irq = __ffs(status);
-
-	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
-	if (unlikely(cascade_irq >= NR_IRQS))
-		do_bad_IRQ(cascade_irq, desc);
-	else
-		generic_handle_irq(cascade_irq);
-
- out:
-	/* primary controller unmasking */
-	chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip combiner_chip = {
-	.name		= "COMBINER",
-	.irq_mask	= combiner_mask_irq,
-	.irq_unmask	= combiner_unmask_irq,
-};
-
-void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
-{
-	if (combiner_nr >= MAX_COMBINER_NR)
-		BUG();
-	if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0)
-		BUG();
-	set_irq_chained_handler(irq, combiner_handle_cascade_irq);
-}
-
-void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
-			  unsigned int irq_start)
-{
-	unsigned int i;
-
-	if (combiner_nr >= MAX_COMBINER_NR)
-		BUG();
-
-	combiner_data[combiner_nr].base = base;
-	combiner_data[combiner_nr].irq_offset = irq_start;
-	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
-
-	/* Disable all interrupts */
-
-	__raw_writel(combiner_data[combiner_nr].irq_mask,
-		     base + COMBINER_ENABLE_CLEAR);
-
-	/* Setup the Linux IRQ subsystem */
-
-	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
-				+ MAX_IRQ_IN_COMBINER; i++) {
-		set_irq_chip(i, &combiner_chip);
-		set_irq_chip_data(i, &combiner_data[combiner_nr]);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-}
diff --git a/arch/arm/mach-s5pv310/irq-eint.c b/arch/arm/mach-s5pv310/irq-eint.c
deleted file mode 100644
index 477bd9e..0000000
--- a/arch/arm/mach-s5pv310/irq-eint.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/irq-eint.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - IRQ EINT 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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/gpio.h>
-
-#include <plat/pm.h>
-#include <plat/cpu.h>
-#include <plat/gpio-cfg.h>
-
-#include <mach/regs-gpio.h>
-
-static DEFINE_SPINLOCK(eint_lock);
-
-static unsigned int eint0_15_data[16];
-
-static unsigned int s5pv310_get_irq_nr(unsigned int number)
-{
-	u32 ret = 0;
-
-	switch (number) {
-	case 0 ... 3:
-		ret = (number + IRQ_EINT0);
-		break;
-	case 4 ... 7:
-		ret = (number + (IRQ_EINT4 - 4));
-		break;
-	case 8 ... 15:
-		ret = (number + (IRQ_EINT8 - 8));
-		break;
-	default:
-		printk(KERN_ERR "number available : %d\n", number);
-	}
-
-	return ret;
-}
-
-static inline void s5pv310_irq_eint_mask(struct irq_data *data)
-{
-	u32 mask;
-
-	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask |= eint_irq_to_bit(data->irq);
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-}
-
-static void s5pv310_irq_eint_unmask(struct irq_data *data)
-{
-	u32 mask;
-
-	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask &= ~(eint_irq_to_bit(data->irq));
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-}
-
-static inline void s5pv310_irq_eint_ack(struct irq_data *data)
-{
-	__raw_writel(eint_irq_to_bit(data->irq),
-		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void s5pv310_irq_eint_maskack(struct irq_data *data)
-{
-	s5pv310_irq_eint_mask(data);
-	s5pv310_irq_eint_ack(data);
-}
-
-static int s5pv310_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
-	int offs = EINT_OFFSET(data->irq);
-	int shift;
-	u32 ctrl, mask;
-	u32 newvalue = 0;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
-		break;
-
-	default:
-		printk(KERN_ERR "No such irq type %d", type);
-		return -EINVAL;
-	}
-
-	shift = (offs & 0x7) * 4;
-	mask = 0x7 << shift;
-
-	spin_lock(&eint_lock);
-	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	ctrl &= ~mask;
-	ctrl |= newvalue << shift;
-	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-
-	switch (offs) {
-	case 0 ... 7:
-		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
-		break;
-	case 8 ... 15:
-		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
-		break;
-	case 16 ... 23:
-		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
-		break;
-	case 24 ... 31:
-		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
-		break;
-	default:
-		printk(KERN_ERR "No such irq number %d", offs);
-	}
-
-	return 0;
-}
-
-static struct irq_chip s5pv310_irq_eint = {
-	.name		= "s5pv310-eint",
-	.irq_mask	= s5pv310_irq_eint_mask,
-	.irq_unmask	= s5pv310_irq_eint_unmask,
-	.irq_mask_ack	= s5pv310_irq_eint_maskack,
-	.irq_ack	= s5pv310_irq_eint_ack,
-	.irq_set_type	= s5pv310_irq_eint_set_type,
-#ifdef CONFIG_PM
-	.irq_set_wake	= s3c_irqext_wake,
-#endif
-};
-
-/* s5pv310_irq_demux_eint
- *
- * This function demuxes the IRQ from from EINTs 16 to 31.
- * It is designed to be inlined into the specific handler
- * s5p_irq_demux_eintX_Y.
- *
- * Each EINT pend/mask registers handle eight of them.
- */
-static inline void s5pv310_irq_demux_eint(unsigned int start)
-{
-	unsigned int irq;
-
-	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
-	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
-
-	status &= ~mask;
-	status &= 0xff;
-
-	while (status) {
-		irq = fls(status) - 1;
-		generic_handle_irq(irq + start);
-		status &= ~(1 << irq);
-	}
-}
-
-static void s5pv310_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
-{
-	s5pv310_irq_demux_eint(IRQ_EINT(16));
-	s5pv310_irq_demux_eint(IRQ_EINT(24));
-}
-
-static void s5pv310_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
-{
-	u32 *irq_data = get_irq_data(irq);
-	struct irq_chip *chip = get_irq_chip(irq);
-
-	chip->irq_mask(&desc->irq_data);
-
-	if (chip->irq_ack)
-		chip->irq_ack(&desc->irq_data);
-
-	generic_handle_irq(*irq_data);
-
-	chip->irq_unmask(&desc->irq_data);
-}
-
-int __init s5pv310_init_irq_eint(void)
-{
-	int irq;
-
-	for (irq = 0 ; irq <= 31 ; irq++) {
-		set_irq_chip(IRQ_EINT(irq), &s5pv310_irq_eint);
-		set_irq_handler(IRQ_EINT(irq), handle_level_irq);
-		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
-	}
-
-	set_irq_chained_handler(IRQ_EINT16_31, s5pv310_irq_demux_eint16_31);
-
-	for (irq = 0 ; irq <= 15 ; irq++) {
-		eint0_15_data[irq] = IRQ_EINT(irq);
-
-		set_irq_data(s5pv310_get_irq_nr(irq), &eint0_15_data[irq]);
-		set_irq_chained_handler(s5pv310_get_irq_nr(irq),
-					s5pv310_irq_eint0_15);
-	}
-
-	return 0;
-}
-
-arch_initcall(s5pv310_init_irq_eint);
diff --git a/arch/arm/mach-s5pv310/localtimer.c b/arch/arm/mach-s5pv310/localtimer.c
deleted file mode 100644
index 2784036..0000000
--- a/arch/arm/mach-s5pv310/localtimer.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/localtimer.c
- *
- * Cloned from linux/arch/arm/mach-realview/localtimer.c
- *
- *  Copyright (C) 2002 ARM Ltd.
- *  All Rights Reserved
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/clockchips.h>
-
-#include <asm/irq.h>
-#include <asm/localtimer.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-	evt->irq = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
-}
diff --git a/arch/arm/mach-s5pv310/mach-smdkc210.c b/arch/arm/mach-s5pv310/mach-smdkc210.c
deleted file mode 100644
index d9cab02..0000000
--- a/arch/arm/mach-s5pv310/mach-smdkc210.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/mach-smdkc210.c
- *
- * Copyright (c) 2010 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.
-*/
-
-#include <linux/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/s5pv310.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC210_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKC210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct resource smdkc210_smsc911x_resources[] = {
-	[0] = {
-		.start	= S5PV310_PA_SROM_BANK(1),
-		.end	= S5PV310_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkc210_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkc210_smsc911x_resources),
-	.resource	= smdkc210_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkc210_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&s5pv310_device_ac97,
-	&s5pv310_device_i2s0,
-	&s5pv310_device_pd[PD_MFC],
-	&s5pv310_device_pd[PD_G3D],
-	&s5pv310_device_pd[PD_LCD0],
-	&s5pv310_device_pd[PD_LCD1],
-	&s5pv310_device_pd[PD_CAM],
-	&s5pv310_device_pd[PD_TV],
-	&s5pv310_device_pd[PD_GPS],
-	&s5pv310_device_sysmmu,
-	&samsung_asoc_dma,
-	&smdkc210_smsc911x,
-};
-
-static void __init smdkc210_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-static void __init smdkc210_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
-}
-
-static void __init smdkc210_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkc210_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
-
-	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
-}
-
-MACHINE_START(SMDKC210, "SMDKC210")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= s5pv310_init_irq,
-	.map_io		= smdkc210_map_io,
-	.init_machine	= smdkc210_machine_init,
-	.timer		= &s5pv310_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv310/mach-smdkv310.c b/arch/arm/mach-s5pv310/mach-smdkv310.c
deleted file mode 100644
index b1cddbf..0000000
--- a/arch/arm/mach-s5pv310/mach-smdkv310.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/mach-smdkv310.c
- *
- * Copyright (c) 2010 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.
-*/
-
-#include <linux/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/s5pv310.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct resource smdkv310_smsc911x_resources[] = {
-	[0] = {
-		.start	= S5PV310_PA_SROM_BANK(1),
-		.end	= S5PV310_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkv310_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkv310_smsc911x_resources),
-	.resource	= smdkv310_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkv310_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&s5pv310_device_ac97,
-	&s5pv310_device_i2s0,
-	&s5pv310_device_pd[PD_MFC],
-	&s5pv310_device_pd[PD_G3D],
-	&s5pv310_device_pd[PD_LCD0],
-	&s5pv310_device_pd[PD_LCD1],
-	&s5pv310_device_pd[PD_CAM],
-	&s5pv310_device_pd[PD_TV],
-	&s5pv310_device_pd[PD_GPS],
-	&s5pv310_device_sysmmu,
-	&samsung_asoc_dma,
-	&smdkv310_smsc911x,
-};
-
-static void __init smdkv310_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-static void __init smdkv310_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
-}
-
-static void __init smdkv310_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkv310_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
-
-	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
-}
-
-MACHINE_START(SMDKV310, "SMDKV310")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= s5pv310_init_irq,
-	.map_io		= smdkv310_map_io,
-	.init_machine	= smdkv310_machine_init,
-	.timer		= &s5pv310_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
deleted file mode 100644
index 36bc3cf..0000000
--- a/arch/arm/mach-s5pv310/mach-universal_c210.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/mach-universal_c210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/platform_device.h>
-#include <linux/serial_core.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/gpio_keys.h>
-#include <linux/gpio.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/mmc/host.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/s5pv310.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG256 |	\
-				 S5PV210_UFCON_RXTRIG256)
-
-static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-};
-
-static struct gpio_keys_button universal_gpio_keys_tables[] = {
-	{
-		.code			= KEY_VOLUMEUP,
-		.gpio			= S5PV310_GPX2(0),	/* XEINT16 */
-		.desc			= "gpio-keys: KEY_VOLUMEUP",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_VOLUMEDOWN,
-		.gpio			= S5PV310_GPX2(1),	/* XEINT17 */
-		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_CONFIG,
-		.gpio			= S5PV310_GPX2(2),	/* XEINT18 */
-		.desc			= "gpio-keys: KEY_CONFIG",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_CAMERA,
-		.gpio			= S5PV310_GPX2(3),	/* XEINT19 */
-		.desc			= "gpio-keys: KEY_CAMERA",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_OK,
-		.gpio			= S5PV310_GPX3(5),	/* XEINT29 */
-		.desc			= "gpio-keys: KEY_OK",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data universal_gpio_keys_data = {
-	.buttons	= universal_gpio_keys_tables,
-	.nbuttons	= ARRAY_SIZE(universal_gpio_keys_tables),
-};
-
-static struct platform_device universal_gpio_keys = {
-	.name			= "gpio-keys",
-	.dev			= {
-		.platform_data	= &universal_gpio_keys_data,
-	},
-};
-
-/* eMMC */
-static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
-	.max_width		= 8,
-	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE),
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct regulator_consumer_supply mmc0_supplies[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
-};
-
-static struct regulator_init_data mmc0_fixed_voltage_init_data = {
-	.constraints		= {
-		.name		= "VMEM_VDD_2.8V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(mmc0_supplies),
-	.consumer_supplies	= mmc0_supplies,
-};
-
-static struct fixed_voltage_config mmc0_fixed_voltage_config = {
-	.supply_name		= "MASSMEMORY_EN",
-	.microvolts		= 2800000,
-	.gpio			= S5PV310_GPE1(3),
-	.enable_high		= true,
-	.init_data		= &mmc0_fixed_voltage_init_data,
-};
-
-static struct platform_device mmc0_fixed_voltage = {
-	.name			= "reg-fixed-voltage",
-	.id			= 0,
-	.dev			= {
-		.platform_data	= &mmc0_fixed_voltage_config,
-	},
-};
-
-/* SD */
-static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.ext_cd_gpio		= S5PV310_GPX3(4),      /* XEINT_28 */
-	.ext_cd_gpio_invert	= 1,
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-/* WiFi */
-static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-};
-
-static void __init universal_sdhci_init(void)
-{
-	s3c_sdhci0_set_platdata(&universal_hsmmc0_data);
-	s3c_sdhci2_set_platdata(&universal_hsmmc2_data);
-	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
-}
-
-/* I2C0 */
-static struct i2c_board_info i2c0_devs[] __initdata = {
-	/* Camera, To be updated */
-};
-
-/* I2C1 */
-static struct i2c_board_info i2c1_devs[] __initdata = {
-	/* Gyro, To be updated */
-};
-
-static struct platform_device *universal_devices[] __initdata = {
-	/* Samsung Platform Devices */
-	&mmc0_fixed_voltage,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-
-	/* Universal Devices */
-	&universal_gpio_keys,
-	&s5p_device_onenand,
-};
-
-static void __init universal_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
-}
-
-static void __init universal_machine_init(void)
-{
-	universal_sdhci_init();
-
-	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
-	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-
-	/* Last */
-	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
-}
-
-MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
-	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= s5pv310_init_irq,
-	.map_io		= universal_map_io,
-	.init_machine	= universal_machine_init,
-	.timer		= &s5pv310_timer,
-MACHINE_END
diff --git a/arch/arm/mach-s5pv310/platsmp.c b/arch/arm/mach-s5pv310/platsmp.c
deleted file mode 100644
index 34093b0..0000000
--- a/arch/arm/mach-s5pv310/platsmp.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/platsmp.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Cloned from linux/arch/arm/mach-vexpress/platsmp.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/init.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-#include <asm/smp_scu.h>
-#include <asm/unified.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-
-extern void s5pv310_secondary_startup(void);
-
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-
-volatile int __cpuinitdata pen_release = -1;
-
-/*
- * Write pen_release in a way that is guaranteed to be visible to all
- * observers, irrespective of whether they're taking part in coherency
- * or not.  This is necessary for the hotplug code to work reliably.
- */
-static void write_pen_release(int val)
-{
-	pen_release = val;
-	smp_wmb();
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
-}
-
-static void __iomem *scu_base_addr(void)
-{
-	return (void __iomem *)(S5P_VA_SCU);
-}
-
-static DEFINE_SPINLOCK(boot_lock);
-
-void __cpuinit platform_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
-	 */
-	write_pen_release(-1);
-
-	/*
-	 * Synchronise with the boot thread.
-	 */
-	spin_lock(&boot_lock);
-	spin_unlock(&boot_lock);
-}
-
-int __cpuinit 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.
-	 */
-	write_pen_release(cpu);
-
-	/*
-	 * Send the secondary CPU a soft interrupt, thereby causing
-	 * the boot monitor to read the system wide flags register,
-	 * and branch to the address found there.
-	 */
-	smp_cross_call(cpumask_of(cpu), 1);
-
-	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.
- */
-
-void __init smp_init_cpus(void)
-{
-	void __iomem *scu_base = scu_base_addr();
-	unsigned int i, ncores;
-
-	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-
-	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "S5PV310: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
-{
-	int i;
-
-	/*
-	 * Initialise the present map, which describes the set of CPUs
-	 * actually populated at the present time.
-	 */
-	for (i = 0; i < max_cpus; i++)
-		set_cpu_present(i, true);
-
-	scu_enable(scu_base_addr());
-
-	/*
-	 * Write the address of secondary startup into the
-	 * system-wide flags register. The boot monitor waits
-	 * until it receives a soft interrupt, and then the
-	 * secondary CPU branches to this address.
-	 */
-	__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c0.c b/arch/arm/mach-s5pv310/setup-i2c0.c
deleted file mode 100644
index f47f8f3..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c0.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPD1(0), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c1.c b/arch/arm/mach-s5pv310/setup-i2c1.c
deleted file mode 100644
index 9d07e4e..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c1.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c1.c
- *
- * Copyright (C) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C1 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPD1(2), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c2.c b/arch/arm/mach-s5pv310/setup-i2c2.c
deleted file mode 100644
index 4163b12..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c2.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c2.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *
- * I2C2 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c2_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPA0(6), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c3.c b/arch/arm/mach-s5pv310/setup-i2c3.c
deleted file mode 100644
index 180f153..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c3.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C3 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c3_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPA1(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c4.c b/arch/arm/mach-s5pv310/setup-i2c4.c
deleted file mode 100644
index 909e8df..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c4.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c4.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C4 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c4_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPB(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c5.c b/arch/arm/mach-s5pv310/setup-i2c5.c
deleted file mode 100644
index 5d0fa4a..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c5.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c5.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C5 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c5_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPB(6), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c6.c b/arch/arm/mach-s5pv310/setup-i2c6.c
deleted file mode 100644
index 34aafab..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c6.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c6.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C6 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c6_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPC1(3), 2,
-			      S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-i2c7.c b/arch/arm/mach-s5pv310/setup-i2c7.c
deleted file mode 100644
index 9b25b8d..0000000
--- a/arch/arm/mach-s5pv310/setup-i2c7.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c7.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C7 GPIO configuration.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c7_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPD0(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff --git a/arch/arm/mach-s5pv310/setup-sdhci-gpio.c b/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
deleted file mode 100644
index 86d38cc..0000000
--- a/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Helper functions for setting up SDHCI device(s) GPIO (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
-
-void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK0[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK0(0); gpio < S5PV310_GPK0(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	switch (width) {
-	case 8:
-		for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) {
-			/* Data pin GPK1[3:6] to special-funtion 3 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	case 4:
-		for (gpio = S5PV310_GPK0(3); gpio <= S5PV310_GPK0(6); gpio++) {
-			/* Data pin GPK0[3:6] to special-funtion 2 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK0(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK0(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK1[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK1(0); gpio < S5PV310_GPK1(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) {
-		/* Data pin GPK1[3:6] to special-function 2 */
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK1(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK1(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK2[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK2(0); gpio < S5PV310_GPK2(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	switch (width) {
-	case 8:
-		for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) {
-			/* Data pin GPK3[3:6] to special-function 3 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	case 4:
-		for (gpio = S5PV310_GPK2(3); gpio <= S5PV310_GPK2(6); gpio++) {
-			/* Data pin GPK2[3:6] to special-function 2 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK2(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK2(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK3[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK3(0); gpio < S5PV310_GPK3(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) {
-		/* Data pin GPK3[3:6] to special-function 2 */
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK3(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK3(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
diff --git a/arch/arm/mach-s5pv310/setup-sdhci.c b/arch/arm/mach-s5pv310/setup-sdhci.c
deleted file mode 100644
index db8358f..0000000
--- a/arch/arm/mach-s5pv310/setup-sdhci.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/setup-sdhci.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Helper functions for settign up SDHCI device(s) (HSMMC)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-
-#include <plat/regs-sdhci.h>
-
-/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
-
-char *s5pv310_hsmmc_clksrcs[4] = {
-	[0] = NULL,
-	[1] = NULL,
-	[2] = "sclk_mmc",	/* mmc_bus */
-	[3] = NULL,
-};
-
-void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
-				  struct mmc_ios *ios, struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	/* don't need to alter anything acording to card-type */
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-
-	/* select base clock source to HCLK */
-
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-
-	/*
-	 * clear async mode, enable conflict mask, rx feedback ctrl, SD
-	 * clk hold and no use debounce count
-	 */
-
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	/* Tx and Rx feedback clock delay control */
-
-	if (ios->clock < 25 * 1000000)
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL3 |
-			 S3C_SDHCI_CTRL3_FCSEL2 |
-			 S3C_SDHCI_CTRL3_FCSEL1 |
-			 S3C_SDHCI_CTRL3_FCSEL0);
-	else
-		ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff --git a/arch/arm/mach-s5pv310/time.c b/arch/arm/mach-s5pv310/time.c
deleted file mode 100644
index b262d46..0000000
--- a/arch/arm/mach-s5pv310/time.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/time.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 (and compatible) HRT support
- * PWM 2/4 is used for this feature
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <asm/mach/time.h>
-
-static unsigned long clock_count_per_tick;
-
-static struct clk *tin2;
-static struct clk *tin4;
-static struct clk *tdiv2;
-static struct clk *tdiv4;
-static struct clk *timerclk;
-
-static void s5pv310_pwm_stop(unsigned int pwm_id)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (pwm_id) {
-	case 2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-	case 4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-	default:
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void s5pv310_pwm_init(unsigned int pwm_id, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	/* timers reload after counting zero, so reduce the count by 1 */
-	tcnt--;
-
-	/* ensure timer is stopped... */
-	switch (pwm_id) {
-	case 2:
-		tcon &= ~(0xf<<12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-
-		__raw_writel(tcnt, S3C2410_TCNTB(2));
-		__raw_writel(tcnt, S3C2410_TCMPB(2));
-		__raw_writel(tcon, S3C2410_TCON);
-
-		break;
-	case 4:
-		tcon &= ~(7<<20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-
-		__raw_writel(tcnt, S3C2410_TCNTB(4));
-		__raw_writel(tcnt, S3C2410_TCMPB(4));
-		__raw_writel(tcon, S3C2410_TCON);
-
-		break;
-	default:
-		break;
-	}
-}
-
-static inline void s5pv310_pwm_start(unsigned int pwm_id, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (pwm_id) {
-	case 2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-	case 4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-	default:
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static int s5pv310_pwm_set_next_event(unsigned long cycles,
-					struct clock_event_device *evt)
-{
-	s5pv310_pwm_init(2, cycles);
-	s5pv310_pwm_start(2, 0);
-	return 0;
-}
-
-static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	s5pv310_pwm_stop(2);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		s5pv310_pwm_init(2, clock_count_per_tick);
-		s5pv310_pwm_start(2, 1);
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device pwm_event_device = {
-	.name		= "pwm_timer2",
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.shift		= 32,
-	.set_next_event	= s5pv310_pwm_set_next_event,
-	.set_mode	= s5pv310_pwm_set_mode,
-};
-
-irqreturn_t s5pv310_clock_event_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &pwm_event_device;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction s5pv310_clock_event_irq = {
-	.name		= "pwm_timer2_irq",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= s5pv310_clock_event_isr,
-};
-
-static void __init s5pv310_clockevent_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-	struct clk *tscaler;
-
-	pclk = clk_get_rate(timerclk);
-
-	/* configure clock tick */
-
-	tscaler = clk_get_parent(tdiv2);
-
-	clk_set_rate(tscaler, pclk / 2);
-	clk_set_rate(tdiv2, pclk / 2);
-	clk_set_parent(tin2, tdiv2);
-
-	clock_rate = clk_get_rate(tin2);
-
-	clock_count_per_tick = clock_rate / HZ;
-
-	pwm_event_device.mult =
-		div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
-	pwm_event_device.max_delta_ns =
-		clockevent_delta2ns(-1, &pwm_event_device);
-	pwm_event_device.min_delta_ns =
-		clockevent_delta2ns(1, &pwm_event_device);
-
-	pwm_event_device.cpumask = cpumask_of(0);
-	clockevents_register_device(&pwm_event_device);
-
-	setup_irq(IRQ_TIMER2, &s5pv310_clock_event_irq);
-}
-
-static cycle_t s5pv310_pwm4_read(struct clocksource *cs)
-{
-	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
-}
-
-struct clocksource pwm_clocksource = {
-	.name		= "pwm_timer4",
-	.rating		= 250,
-	.read		= s5pv310_pwm4_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
-};
-
-static void __init s5pv310_clocksource_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv4, pclk / 2);
-	clk_set_parent(tin4, tdiv4);
-
-	clock_rate = clk_get_rate(tin4);
-
-	s5pv310_pwm_init(4, ~0);
-	s5pv310_pwm_start(4, 1);
-
-	if (clocksource_register_hz(&pwm_clocksource, clock_rate))
-		panic("%s: can't register clocksource\n", pwm_clocksource.name);
-}
-
-static void __init s5pv310_timer_resources(void)
-{
-	struct platform_device tmpdev;
-
-	tmpdev.dev.bus = &platform_bus_type;
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get timers clock for system timer");
-
-	clk_enable(timerclk);
-
-	tmpdev.id = 2;
-	tin2 = clk_get(&tmpdev.dev, "pwm-tin");
-	if (IS_ERR(tin2))
-		panic("failed to get pwm-tin2 clock for system timer");
-
-	tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
-	if (IS_ERR(tdiv2))
-		panic("failed to get pwm-tdiv2 clock for system timer");
-	clk_enable(tin2);
-
-	tmpdev.id = 4;
-	tin4 = clk_get(&tmpdev.dev, "pwm-tin");
-	if (IS_ERR(tin4))
-		panic("failed to get pwm-tin4 clock for system timer");
-
-	tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
-	if (IS_ERR(tdiv4))
-		panic("failed to get pwm-tdiv4 clock for system timer");
-
-	clk_enable(tin4);
-}
-
-static void __init s5pv310_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	twd_base = S5P_VA_TWD;
-#endif
-
-	s5pv310_timer_resources();
-	s5pv310_clockevent_init();
-	s5pv310_clocksource_init();
-}
-
-struct sys_timer s5pv310_timer = {
-	.init		= s5pv310_timer_init,
-};
diff --git a/arch/arm/mach-sa1100/include/mach/memory.h b/arch/arm/mach-sa1100/include/mach/memory.h
index 128a1df..a44da6a 100644
--- a/arch/arm/mach-sa1100/include/mach/memory.h
+++ b/arch/arm/mach-sa1100/include/mach/memory.h
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset is 0xc0000000 on the SA1100
  */
-#define PHYS_OFFSET	UL(0xc0000000)
+#define PLAT_PHYS_OFFSET	UL(0xc0000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index ab9fc44..c4661aa 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -32,8 +32,7 @@
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
-extern void sa1100_cpu_suspend(void);
-extern void sa1100_cpu_resume(void);
+extern void sa1100_cpu_suspend(long);
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
@@ -73,10 +72,10 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
 
 	/* set resume return address */
-	PSPR = virt_to_phys(sa1100_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 
 	/* go zzz */
-	sa1100_cpu_suspend();
+	sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
 	cpu_init();
 
@@ -115,11 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state)
 	return 0;
 }
 
-unsigned long sleep_phys_sp(void *sp)
-{
-	return virt_to_phys(sp);
-}
-
 static const struct platform_suspend_ops sa11x0_pm_ops = {
 	.enter		= sa11x0_pm_enter,
 	.valid		= suspend_valid_only_mem,
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S
index 80f31ba..04f2a61 100644
--- a/arch/arm/mach-sa1100/sleep.S
+++ b/arch/arm/mach-sa1100/sleep.S
@@ -20,12 +20,7 @@
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 
-
-
 		.text
-
-
-
 /*
  * sa1100_cpu_suspend()
  *
@@ -34,27 +29,10 @@
  */
 
 ENTRY(sa1100_cpu_suspend)
-
 	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack
-
-	@ get coprocessor registers
-	mrc 	p15, 0, r4, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r6, c13, c0, 0		@ PID
-	mrc 	p15, 0, r7, c1, c0, 0		@ control reg
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r8, sp
-	stmfd	sp!, {r4 - r8}
-
-	@ preserve phys address of stack
-	mov	r0, sp
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-
-	@ clean data cache and invalidate WB
-	bl	v4wb_flush_kern_cache_all
+	mov	r1, r0
+	ldr	r3, =sa1100_cpu_resume		@ return function
+	bl	cpu_suspend
 
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
@@ -166,50 +144,8 @@ sa1110_sdram_controller_fix:
  * cpu_sa1100_resume()
  *
  * entry point from bootloader into kernel during resume
- *
- * Note: Yes, part of the following code is located into the .data section.
- *       This is to allow sleep_save_sp to be accessed with a relative load
- *       while we can't rely on any MMU translation.  We could have put
- *       sleep_save_sp in the .text section as well, but some setups might
- *       insist on it to be truly read-only.
  */
-
-	.data
-	.align 5
-ENTRY(sa1100_cpu_resume)
-	mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
-	msr	cpsr_c, r0			@ set SVC, irqs off
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldr	r2, =resume_after_mmu		@ its absolute virtual address
-	ldmfd	r0, {r4 - r7, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0   	@ flush I+D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
-	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
-	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
-
-	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
-	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r6, c13, c0, 0		@ PID
-	b	resume_turn_on_mmu		@ cache align execution
-
 	.align 5
-resume_turn_on_mmu:
-	mcr 	p15, 0, r7, c1, c0, 0		@ turn on MMU, caches, etc.
-	nop
-	mov	pc, r2				@ jump to virtual addr
-	nop
-	nop
-	nop
-
-sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
-
-	.text
-resume_after_mmu:
+sa1100_cpu_resume:
 	mcr	p15, 0, r1, c15, c1, 2		@ enable clock switching
 	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
-
-
diff --git a/arch/arm/mach-shark/include/mach/memory.h b/arch/arm/mach-shark/include/mach/memory.h
index d9c4812..9afb170 100644
--- a/arch/arm/mach-shark/include/mach/memory.h
+++ b/arch/arm/mach-shark/include/mach/memory.h
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET     UL(0x08000000)
+#define PLAT_PHYS_OFFSET     UL(0x08000000)
 
 #ifndef __ASSEMBLY__
 
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 4303a86..3e6f0aa 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -119,13 +119,6 @@ static struct platform_device keysc_device = {
 };
 
 /* FSI A */
-static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_OUT_SLAVE_MODE	|
-		       SH_FSI_IN_SLAVE_MODE	|
-		       SH_FSI_OFMT(I2S)		|
-		       SH_FSI_IFMT(I2S),
-};
-
 static struct resource fsi_resources[] = {
 	[0] = {
 		.name	= "FSI",
@@ -144,9 +137,6 @@ static struct platform_device fsi_device = {
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(fsi_resources),
 	.resource	= fsi_resources,
-	.dev	= {
-		.platform_data	= &fsi_info,
-	},
 };
 
 static struct resource sh_mmcif_resources[] = {
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 81d6536..1a8118c 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -673,16 +673,12 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OUT_SLAVE_MODE |
-		       SH_FSI_IN_SLAVE_MODE |
-		       SH_FSI_OFMT(PCM) |
-		       SH_FSI_IFMT(PCM),
+	.porta_flags = SH_FSI_BRS_INV,
 
 	.portb_flags = SH_FSI_BRS_INV |
 		       SH_FSI_BRM_INV |
 		       SH_FSI_LRS_INV |
-		       SH_FSI_OFMT(SPDIF),
+		       SH_FSI_FMT_SPDIF,
 	.set_rate = fsi_set_rate,
 };
 
@@ -783,6 +779,10 @@ static struct platform_device hdmi_device = {
 	},
 };
 
+static struct platform_device fsi_hdmi_device = {
+	.name		= "sh_fsi2_b_hdmi",
+};
+
 static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
 				unsigned long *parent_freq)
 {
@@ -936,6 +936,7 @@ static struct platform_device *ap4evb_devices[] __initdata = {
 	&usb1_host_device,
 	&fsi_device,
 	&fsi_ak4643_device,
+	&fsi_hdmi_device,
 	&sh_mmcif_device,
 	&lcdc1_device,
 	&lcdc_device,
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 1657eac..1a63c21 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -399,6 +399,10 @@ static struct platform_device hdmi_device = {
 	},
 };
 
+static struct platform_device fsi_hdmi_device = {
+	.name		= "sh_fsi2_b_hdmi",
+};
+
 static int __init hdmi_init_pm_clock(void)
 {
 	struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
@@ -609,16 +613,12 @@ fsi_set_rate_end:
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags =	SH_FSI_BRS_INV		|
-			SH_FSI_OUT_SLAVE_MODE	|
-			SH_FSI_IN_SLAVE_MODE	|
-			SH_FSI_OFMT(PCM)	|
-			SH_FSI_IFMT(PCM),
+	.porta_flags =	SH_FSI_BRS_INV,
 
 	.portb_flags =	SH_FSI_BRS_INV	|
 			SH_FSI_BRM_INV	|
 			SH_FSI_LRS_INV	|
-			SH_FSI_OFMT(SPDIF),
+			SH_FSI_FMT_SPDIF,
 
 	.set_rate = fsi_set_rate,
 };
@@ -921,6 +921,7 @@ static struct platform_device *mackerel_devices[] __initdata = {
 	&leds_device,
 	&fsi_device,
 	&fsi_ak4643_device,
+	&fsi_hdmi_device,
 	&sdhi0_device,
 #if !defined(CONFIG_MMC_SH_MMCIF)
 	&sdhi1_device,
diff --git a/arch/arm/mach-shmobile/include/mach/memory.h b/arch/arm/mach-shmobile/include/mach/memory.h
index 377584e..ad00c3c 100644
--- a/arch/arm/mach-shmobile/include/mach/memory.h
+++ b/arch/arm/mach-shmobile/include/mach/memory.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_MEMORY_H
 #define __ASM_MACH_MEMORY_H
 
-#define PHYS_OFFSET	UL(CONFIG_MEMORY_START)
+#define PLAT_PHYS_OFFSET	UL(CONFIG_MEMORY_START)
 #define MEM_SIZE	UL(CONFIG_MEMORY_SIZE)
 
 /* DMA memory at 0xf6000000 - 0xffdfffff */
diff --git a/arch/arm/mach-shmobile/include/mach/mmcif-ap4eb.h b/arch/arm/mach-shmobile/include/mach/mmcif-ap4eb.h
new file mode 100644
index 0000000..a8d02be
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/mmcif-ap4eb.h
@@ -0,0 +1,29 @@
+#ifndef MMCIF_AP4EB_H
+#define MMCIF_AP4EB_H
+
+#define PORT185CR      (void __iomem *)0xe60520b9
+#define PORT186CR      (void __iomem *)0xe60520ba
+#define PORT187CR      (void __iomem *)0xe60520bb
+#define PORT188CR      (void __iomem *)0xe60520bc
+
+#define PORTR191_160DR (void __iomem *)0xe6056014
+
+static inline void mmcif_init_progress(void)
+{
+       /* Initialise LEDS1-4
+        * registers: PORT185CR-PORT188CR (LED1-LED4 Control)
+        * value:     0x10 - enable output
+        */
+       __raw_writeb(0x10, PORT185CR);
+       __raw_writeb(0x10, PORT186CR);
+       __raw_writeb(0x10, PORT187CR);
+       __raw_writeb(0x10, PORT188CR);
+}
+
+static inline void mmcif_update_progress(int n)
+{
+	__raw_writel((__raw_readl(PORTR191_160DR) & ~(0xf << 25)) |
+		     (1 << (25 + n)), PORTR191_160DR);
+}
+
+#endif /* MMCIF_AP4EB_H */
diff --git a/arch/arm/mach-shmobile/include/mach/mmcif-mackerel.h b/arch/arm/mach-shmobile/include/mach/mmcif-mackerel.h
new file mode 100644
index 0000000..4b4f694
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/mmcif-mackerel.h
@@ -0,0 +1,39 @@
+#ifndef MMCIF_MACKEREL_H
+#define MMCIF_MACKEREL_H
+
+#define PORT0CR      (void __iomem *)0xe6051000
+#define PORT1CR      (void __iomem *)0xe6051001
+#define PORT2CR      (void __iomem *)0xe6051002
+#define PORT159CR    (void __iomem *)0xe605009f
+
+#define PORTR031_000DR (void __iomem *)0xe6055000
+#define PORTL159_128DR (void __iomem *)0xe6054010
+
+static inline void mmcif_init_progress(void)
+{
+       /* Initialise LEDS0-3
+        * registers: PORT0CR-PORT2CR,PORT159CR (LED0-LED3 Control)
+        * value:     0x10 - enable output
+        */
+       __raw_writeb(0x10, PORT0CR);
+       __raw_writeb(0x10, PORT1CR);
+       __raw_writeb(0x10, PORT2CR);
+       __raw_writeb(0x10, PORT159CR);
+}
+
+static inline void mmcif_update_progress(int n)
+{
+	unsigned a = 0, b = 0;
+
+	if (n < 3)
+		a = 1 << n;
+	else
+		b = 1 << 31;
+
+	__raw_writel((__raw_readl(PORTR031_000DR) & ~0x7) | a,
+		     PORTR031_000DR);
+	__raw_writel((__raw_readl(PORTL159_128DR) & ~(1 << 31)) | b,
+		     PORTL159_128DR);
+}
+
+#endif /* MMCIF_MACKEREL_H */
diff --git a/arch/arm/mach-shmobile/include/mach/mmcif.h b/arch/arm/mach-shmobile/include/mach/mmcif.h
new file mode 100644
index 0000000..f4dc327
--- /dev/null
+++ b/arch/arm/mach-shmobile/include/mach/mmcif.h
@@ -0,0 +1,18 @@
+#ifndef MMCIF_H
+#define MMCIF_H
+
+/**************************************************
+ *
+ *		board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_AP4EVB
+#include "mach/mmcif-ap4eb.h"
+#elif CONFIG_MACH_MACKEREL
+#include "mach/mmcif-mackerel.h"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* MMCIF_H */
diff --git a/arch/arm/mach-spear3xx/clock.c b/arch/arm/mach-spear3xx/clock.c
index 18febf9..98bc7ed 100644
--- a/arch/arm/mach-spear3xx/clock.c
+++ b/arch/arm/mach-spear3xx/clock.c
@@ -13,8 +13,8 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <mach/misc_regs.h>
 #include <plat/clock.h>
+#include <mach/misc_regs.h>
 
 /* root clks */
 /* 32 KHz oscillator clock */
@@ -39,18 +39,43 @@ static struct clk rtc_clk = {
 };
 
 /* clock derived from 24 MHz osc clk */
+/* pll masks structure */
+static struct pll_clk_masks pll1_masks = {
+	.mode_mask = PLL_MODE_MASK,
+	.mode_shift = PLL_MODE_SHIFT,
+	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
+	.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
+	.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
+	.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
+	.div_p_mask = PLL_DIV_P_MASK,
+	.div_p_shift = PLL_DIV_P_SHIFT,
+	.div_n_mask = PLL_DIV_N_MASK,
+	.div_n_shift = PLL_DIV_N_SHIFT,
+};
+
 /* pll1 configuration structure */
 static struct pll_clk_config pll1_config = {
 	.mode_reg = PLL1_CTR,
 	.cfg_reg = PLL1_FRQ,
+	.masks = &pll1_masks,
+};
+
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
 /* PLL1 clock */
 static struct clk pll1_clk = {
+	.flags = ENABLED_ON_INIT,
 	.pclk = &osc_24m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
-	.recalc = &pll1_clk_recalc,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
 	.private_data = &pll1_config,
 };
 
@@ -76,36 +101,83 @@ static struct clk cpu_clk = {
 	.recalc = &follow_parent,
 };
 
+/* ahb masks structure */
+static struct bus_clk_masks ahb_masks = {
+	.mask = PLL_HCLK_RATIO_MASK,
+	.shift = PLL_HCLK_RATIO_SHIFT,
+};
+
 /* ahb configuration structure */
 static struct bus_clk_config ahb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = PLL_HCLK_RATIO_MASK,
-	.shift = PLL_HCLK_RATIO_SHIFT,
+	.masks = &ahb_masks,
+};
+
+/* ahb rate configuration table, in ascending order of rates */
+struct bus_rate_tbl bus_rtbl[] = {
+	{.div = 3}, /* == parent divided by 4 */
+	{.div = 2}, /* == parent divided by 3 */
+	{.div = 1}, /* == parent divided by 2 */
+	{.div = 0}, /* == parent divided by 1 */
 };
 
 /* ahb clock */
 static struct clk ahb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &pll1_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &ahb_config,
 };
 
-/* uart configurations */
-static struct aux_clk_config uart_config = {
+/* auxiliary synthesizers masks */
+static struct aux_clk_masks aux_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = AUX_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = AUX_XSCALE_MASK,
+	.xscale_sel_shift = AUX_XSCALE_SHIFT,
+	.yscale_sel_mask = AUX_YSCALE_MASK,
+	.yscale_sel_shift = AUX_YSCALE_SHIFT,
+};
+
+/* uart synth configurations */
+static struct aux_clk_config uart_synth_config = {
 	.synth_reg = UART_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+	/* For PLL1 = 332 MHz */
+	{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
+	{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+	.en_reg = UART_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
+	.private_data = &uart_synth_config,
 };
 
 /* uart parents */
 static struct pclk_info uart_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &uart_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -123,25 +195,35 @@ static struct clk uart_clk = {
 	.en_reg_bit = UART_CLK_ENB,
 	.pclk_sel = &uart_pclk_sel,
 	.pclk_sel_shift = UART_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &uart_config,
+	.recalc = &follow_parent,
 };
 
 /* firda configurations */
-static struct aux_clk_config firda_config = {
+static struct aux_clk_config firda_synth_config = {
 	.synth_reg = FIRDA_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* firda synth clock */
+static struct clk firda_synth_clk = {
+	.en_reg = FIRDA_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
+	.private_data = &firda_synth_config,
 };
 
 /* firda parents */
 static struct pclk_info firda_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &firda_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -159,73 +241,155 @@ static struct clk firda_clk = {
 	.en_reg_bit = FIRDA_CLK_ENB,
 	.pclk_sel = &firda_pclk_sel,
 	.pclk_sel_shift = FIRDA_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &firda_config,
+	.recalc = &follow_parent,
+};
+
+/* gpt synthesizer masks */
+static struct gpt_clk_masks gpt_masks = {
+	.mscale_sel_mask = GPT_MSCALE_MASK,
+	.mscale_sel_shift = GPT_MSCALE_SHIFT,
+	.nscale_sel_mask = GPT_NSCALE_MASK,
+	.nscale_sel_shift = GPT_NSCALE_SHIFT,
+};
+
+/* gpt rate configuration table, in ascending order of rates */
+struct gpt_rate_tbl gpt_rtbl[] = {
+	/* For pll1 = 332 MHz */
+	{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+	{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+	{.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* gpt0 synth clk config*/
+static struct gpt_clk_config gpt0_synth_config = {
+	.synth_reg = PRSC1_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt0_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt0_synth_config,
 };
 
 /* gpt parents */
-static struct pclk_info gpt_pclk_info[] = {
+static struct pclk_info gpt0_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &gpt0_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
 /* gpt parent select structure */
-static struct pclk_sel gpt_pclk_sel = {
-	.pclk_info = gpt_pclk_info,
-	.pclk_count = ARRAY_SIZE(gpt_pclk_info),
+static struct pclk_sel gpt0_pclk_sel = {
+	.pclk_info = gpt0_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
 	.pclk_sel_reg = PERIP_CLK_CFG,
 	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
-/* gpt0 configurations */
-static struct aux_clk_config gpt0_config = {
-	.synth_reg = PRSC1_CLK_CFG,
-};
-
 /* gpt0 timer clock */
 static struct clk gpt0_clk = {
 	.flags = ALWAYS_ENABLED,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt0_pclk_sel,
 	.pclk_sel_shift = GPT0_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt0_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt1 configurations */
-static struct aux_clk_config gpt1_config = {
+/* gpt1 synth clk configurations */
+static struct gpt_clk_config gpt1_synth_config = {
 	.synth_reg = PRSC2_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt1 synth clock */
+static struct clk gpt1_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt1_synth_config,
+};
+
+static struct pclk_info gpt1_pclk_info[] = {
+	{
+		.pclk = &gpt1_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt1_pclk_sel = {
+	.pclk_info = gpt1_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt1_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt1 timer clock */
 static struct clk gpt1_clk = {
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = GPT1_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt1_pclk_sel,
 	.pclk_sel_shift = GPT1_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt1_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt2 configurations */
-static struct aux_clk_config gpt2_config = {
+/* gpt2 synth clk configurations */
+static struct gpt_clk_config gpt2_synth_config = {
 	.synth_reg = PRSC3_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt1 synth clock */
+static struct clk gpt2_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt2_synth_config,
+};
+
+static struct pclk_info gpt2_pclk_info[] = {
+	{
+		.pclk = &gpt2_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt2_pclk_sel = {
+	.pclk_info = gpt2_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt2 timer clock */
 static struct clk gpt2_clk = {
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = GPT2_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt2_pclk_sel,
 	.pclk_sel_shift = GPT2_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt2_config,
+	.recalc = &follow_parent,
 };
 
 /* clock derived from pll3 clk */
@@ -245,26 +409,27 @@ static struct clk usbd_clk = {
 	.recalc = &follow_parent,
 };
 
-/* clcd clock */
-static struct clk clcd_clk = {
-	.flags = ALWAYS_ENABLED,
-	.pclk = &pll3_48m_clk,
-	.recalc = &follow_parent,
+/* clock derived from ahb clk */
+/* apb masks structure */
+static struct bus_clk_masks apb_masks = {
+	.mask = HCLK_PCLK_RATIO_MASK,
+	.shift = HCLK_PCLK_RATIO_SHIFT,
 };
 
-/* clock derived from ahb clk */
 /* apb configuration structure */
 static struct bus_clk_config apb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = HCLK_PCLK_RATIO_MASK,
-	.shift = HCLK_PCLK_RATIO_SHIFT,
+	.masks = &apb_masks,
 };
 
 /* apb clock */
 static struct clk apb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &ahb_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &apb_config,
 };
 
@@ -325,8 +490,17 @@ static struct clk adc_clk = {
 	.recalc = &follow_parent,
 };
 
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+/* emi clock */
+static struct clk emi_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
 /* ssp clock */
-static struct clk ssp_clk = {
+static struct clk ssp0_clk = {
 	.pclk = &apb_clk,
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = SSP_CLK_ENB,
@@ -343,14 +517,145 @@ static struct clk gpio_clk = {
 
 static struct clk dummy_apb_pclk;
 
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
+	defined(CONFIG_MACH_SPEAR320)
+/* fsmc clock */
+static struct clk fsmc_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
+/* common clocks to spear310 and spear320 */
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+/* uart1 clock */
+static struct clk uart1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart2 clock */
+static struct clk uart2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
+
+/* common clocks to spear300 and spear320 */
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
+/* clcd clock */
+static struct clk clcd_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll3_48m_clk,
+	.recalc = &follow_parent,
+};
+
+/* sdhci clock */
+static struct clk sdhci_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+
+/* spear300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR300
+/* gpio1 clock */
+static struct clk gpio1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* keyboard clock */
+static struct clk kbd_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+#endif
+
+/* spear310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR310
+/* uart3 clock */
+static struct clk uart3_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart4 clock */
+static struct clk uart4_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart5 clock */
+static struct clk uart5_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
+/* spear320 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR320
+/* can0 clock */
+static struct clk can0_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* can1 clock */
+static struct clk can1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* i2c1 clock */
+static struct clk i2c1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+
+/* ssp1 clock */
+static struct clk ssp1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* ssp2 clock */
+static struct clk ssp2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* pwm clock */
+static struct clk pwm_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
 /* array of all spear 3xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
-	{ .con_id = "apb_pclk",	.clk = &dummy_apb_pclk},
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{ .con_id = "osc_32k_clk",	.clk = &osc_32k_clk},
 	{ .con_id = "osc_24m_clk",	.clk = &osc_24m_clk},
 	/* clock derived from 32 KHz osc clk */
-	{ .dev_id = "rtc",		.clk = &rtc_clk},
+	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 24 MHz osc clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
@@ -358,18 +663,22 @@ static struct clk_lookup spear_clk_lookups[] = {
 	/* clock derived from pll1 clk */
 	{ .con_id = "cpu_clk",		.clk = &cpu_clk},
 	{ .con_id = "ahb_clk",		.clk = &ahb_clk},
+	{ .con_id = "uart_synth_clk",	.clk = &uart_synth_clk},
+	{ .con_id = "firda_synth_clk",	.clk = &firda_synth_clk},
+	{ .con_id = "gpt0_synth_clk",	.clk = &gpt0_synth_clk},
+	{ .con_id = "gpt1_synth_clk",	.clk = &gpt1_synth_clk},
+	{ .con_id = "gpt2_synth_clk",	.clk = &gpt2_synth_clk},
 	{ .dev_id = "uart",		.clk = &uart_clk},
 	{ .dev_id = "firda",		.clk = &firda_clk},
 	{ .dev_id = "gpt0",		.clk = &gpt0_clk},
 	{ .dev_id = "gpt1",		.clk = &gpt1_clk},
 	{ .dev_id = "gpt2",		.clk = &gpt2_clk},
 	/* clock derived from pll3 clk */
-	{ .dev_id = "usbh",		.clk = &usbh_clk},
-	{ .dev_id = "usbd",		.clk = &usbd_clk},
-	{ .dev_id = "clcd",		.clk = &clcd_clk},
+	{ .dev_id = "designware_udc",   .clk = &usbd_clk},
+	{ .con_id = "usbh_clk",		.clk = &usbh_clk},
 	/* clock derived from ahb clk */
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
-	{ .dev_id = "i2c",		.clk = &i2c_clk},
+	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
 	{ .dev_id = "jpeg",		.clk = &jpeg_clk},
 	{ .dev_id = "gmac",		.clk = &gmac_clk},
@@ -377,8 +686,50 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "c3",		.clk = &c3_clk},
 	/* clock derived from apb clk */
 	{ .dev_id = "adc",		.clk = &adc_clk},
-	{ .dev_id = "ssp",		.clk = &ssp_clk},
+	{ .dev_id = "ssp-pl022.0",	.clk = &ssp0_clk},
 	{ .dev_id = "gpio",		.clk = &gpio_clk},
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+	{ .dev_id = "physmap-flash",	.clk = &emi_clk},
+#endif
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
+	defined(CONFIG_MACH_SPEAR320)
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
+#endif
+
+/* common clocks to spear310 and spear320 */
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+	{ .dev_id = "uart1",		.clk = &uart1_clk},
+	{ .dev_id = "uart2",		.clk = &uart2_clk},
+#endif
+
+	/* common clock to spear300 and spear320 */
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
+	{ .dev_id = "clcd",		.clk = &clcd_clk},
+	{ .dev_id = "sdhci",		.clk = &sdhci_clk},
+#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+
+	/* spear300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR300
+	{ .dev_id = "gpio1",		.clk = &gpio1_clk},
+	{ .dev_id = "keyboard",		.clk = &kbd_clk},
+#endif
+
+	/* spear310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR310
+	{ .dev_id = "uart3",		.clk = &uart3_clk},
+	{ .dev_id = "uart4",		.clk = &uart4_clk},
+	{ .dev_id = "uart5",		.clk = &uart5_clk},
+
+#endif
+	/* spear320 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR320
+	{ .dev_id = "c_can_platform.0",	.clk = &can0_clk},
+	{ .dev_id = "c_can_platform.1",	.clk = &can1_clk},
+	{ .dev_id = "i2c_designware.1",	.clk = &i2c1_clk},
+	{ .dev_id = "ssp-pl022.1",	.clk = &ssp1_clk},
+	{ .dev_id = "ssp-pl022.2",	.clk = &ssp2_clk},
+	{ .dev_id = "pwm",		.clk = &pwm_clk},
+#endif
 };
 
 void __init clk_init(void)
diff --git a/arch/arm/mach-spear3xx/include/mach/entry-macro.S b/arch/arm/mach-spear3xx/include/mach/entry-macro.S
index 947625d..53da422 100644
--- a/arch/arm/mach-spear3xx/include/mach/entry-macro.S
+++ b/arch/arm/mach-spear3xx/include/mach/entry-macro.S
@@ -11,9 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <mach/hardware.h>
-#include <mach/spear.h>
 #include <asm/hardware/vic.h>
+#include <mach/hardware.h>
 
 		.macro	disable_fiq
 		.endm
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index af7e02c..8e30636 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -14,11 +14,11 @@
 #ifndef __MACH_GENERIC_H
 #define __MACH_GENERIC_H
 
-#include <asm/mach/time.h>
-#include <asm/mach/map.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>
 #include <plat/padmux.h>
 
 /* spear3xx declarations */
@@ -33,14 +33,14 @@
 /* Add spear3xx family device structure declarations here */
 extern struct amba_device gpio_device;
 extern struct amba_device uart_device;
-extern struct sys_timer spear_sys_timer;
+extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
 void __init clk_init(void);
+void __init spear_setup_timer(void);
 void __init spear3xx_map_io(void);
 void __init spear3xx_init_irq(void);
 void __init spear3xx_init(void);
-void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size);
 
 /* pad mux declarations */
 #define PMX_FIRDA_MASK		(1 << 14)
@@ -129,12 +129,10 @@ extern struct pmx_dev pmx_telecom_camera;
 extern struct pmx_dev pmx_telecom_dac;
 extern struct pmx_dev pmx_telecom_i2s;
 extern struct pmx_dev pmx_telecom_boot_pins;
-extern struct pmx_dev pmx_telecom_sdio_4bit;
-extern struct pmx_dev pmx_telecom_sdio_8bit;
+extern struct pmx_dev pmx_telecom_sdhci_4bit;
+extern struct pmx_dev pmx_telecom_sdhci_8bit;
 extern struct pmx_dev pmx_gpio1;
 
-void spear300_pmx_init(void);
-
 /* Add spear300 machine function declarations here */
 void __init spear300_init(void);
 
@@ -154,8 +152,6 @@ extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_rs485_0_1;
 extern struct pmx_dev pmx_tdm0;
 
-void spear310_pmx_init(void);
-
 /* Add spear310 machine function declarations here */
 void __init spear310_init(void);
 
@@ -176,14 +172,14 @@ extern struct pmx_dev pmx_clcd;
 extern struct pmx_dev pmx_emi;
 extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_spp;
-extern struct pmx_dev pmx_sdio;
+extern struct pmx_dev pmx_sdhci;
 extern struct pmx_dev pmx_i2s;
 extern struct pmx_dev pmx_uart1;
 extern struct pmx_dev pmx_uart1_modem;
 extern struct pmx_dev pmx_uart2;
 extern struct pmx_dev pmx_touchscreen;
 extern struct pmx_dev pmx_can;
-extern struct pmx_dev pmx_sdio_led;
+extern struct pmx_dev pmx_sdhci_led;
 extern struct pmx_dev pmx_pwm0;
 extern struct pmx_dev pmx_pwm1;
 extern struct pmx_dev pmx_pwm2;
@@ -195,8 +191,6 @@ extern struct pmx_dev pmx_smii0;
 extern struct pmx_dev pmx_smii1;
 extern struct pmx_dev pmx_i2c1;
 
-void spear320_pmx_init(void);
-
 /* Add spear320 machine function declarations here */
 void __init spear320_init(void);
 
diff --git a/arch/arm/mach-spear3xx/include/mach/hardware.h b/arch/arm/mach-spear3xx/include/mach/hardware.h
index 4a86e6a..4660c0d 100644
--- a/arch/arm/mach-spear3xx/include/mach/hardware.h
+++ b/arch/arm/mach-spear3xx/include/mach/hardware.h
@@ -14,6 +14,9 @@
 #ifndef __MACH_HARDWARE_H
 #define __MACH_HARDWARE_H
 
+#include <plat/hardware.h>
+#include <mach/spear.h>
+
 /* Vitual to physical translation of statically mapped space */
 #define IO_ADDRESS(x)		(x | 0xF0000000)
 
diff --git a/arch/arm/mach-spear3xx/include/mach/irqs.h b/arch/arm/mach-spear3xx/include/mach/irqs.h
index 7f940b8..a1a7f48 100644
--- a/arch/arm/mach-spear3xx/include/mach/irqs.h
+++ b/arch/arm/mach-spear3xx/include/mach/irqs.h
@@ -69,7 +69,7 @@
 #define IRQ_CLCD				IRQ_GEN_RAS_3
 
 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define IRQ_SDIO				IRQ_INTRCOMM_RAS_ARM
+#define IRQ_SDHCI				IRQ_INTRCOMM_RAS_ARM
 
 /* GPIO pins virtual irqs */
 #define SPEAR_GPIO_INT_BASE			(VIRQ_START + 9)
@@ -115,7 +115,7 @@
 #define VIRQ_SPP				(VIRQ_START + 2)
 
 /* IRQs sharing IRQ_GEN_RAS_2 */
-#define IRQ_SDIO				IRQ_GEN_RAS_2
+#define IRQ_SDHCI				IRQ_GEN_RAS_2
 
 /* IRQs sharing IRQ_GEN_RAS_3 */
 #define VIRQ_PLGPIO				(VIRQ_START + 3)
diff --git a/arch/arm/mach-spear3xx/include/mach/misc_regs.h b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
index 38d767a..5bd8cd8 100644
--- a/arch/arm/mach-spear3xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear3xx/include/mach/misc_regs.h
@@ -14,16 +14,16 @@
 #ifndef __MACH_MISC_REGS_H
 #define __MACH_MISC_REGS_H
 
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
-#define MISC_BASE		VA_SPEAR3XX_ICM3_MISC_REG_BASE
+#define MISC_BASE		IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE)
 
-#define SOC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x000))
-#define DIAG_CFG_CTR		((unsigned int *)(MISC_BASE + 0x004))
-#define PLL1_CTR		((unsigned int *)(MISC_BASE + 0x008))
-#define PLL1_FRQ		((unsigned int *)(MISC_BASE + 0x00C))
-#define PLL1_MOD		((unsigned int *)(MISC_BASE + 0x010))
-#define PLL2_CTR		((unsigned int *)(MISC_BASE + 0x014))
+#define SOC_CFG_CTR		(MISC_BASE + 0x000)
+#define DIAG_CFG_CTR		(MISC_BASE + 0x004)
+#define PLL1_CTR		(MISC_BASE + 0x008)
+#define PLL1_FRQ		(MISC_BASE + 0x00C)
+#define PLL1_MOD		(MISC_BASE + 0x010)
+#define PLL2_CTR		(MISC_BASE + 0x014)
 /* PLL_CTR register masks */
 #define PLL_ENABLE		2
 #define PLL_MODE_SHIFT		4
@@ -33,7 +33,7 @@
 #define PLL_MODE_DITH_DSB	2
 #define PLL_MODE_DITH_SSB	3
 
-#define PLL2_FRQ		((unsigned int *)(MISC_BASE + 0x018))
+#define PLL2_FRQ		(MISC_BASE + 0x018)
 /* PLL FRQ register masks */
 #define PLL_DIV_N_SHIFT		0
 #define PLL_DIV_N_MASK		0xFF
@@ -44,16 +44,16 @@
 #define PLL_DITH_FDBK_M_SHIFT	16
 #define PLL_DITH_FDBK_M_MASK	0xFFFF
 
-#define PLL2_MOD		((unsigned int *)(MISC_BASE + 0x01C))
-#define PLL_CLK_CFG		((unsigned int *)(MISC_BASE + 0x020))
-#define CORE_CLK_CFG		((unsigned int *)(MISC_BASE + 0x024))
+#define PLL2_MOD		(MISC_BASE + 0x01C)
+#define PLL_CLK_CFG		(MISC_BASE + 0x020)
+#define CORE_CLK_CFG		(MISC_BASE + 0x024)
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
 #define PLL_HCLK_RATIO_MASK	0x3
 #define HCLK_PCLK_RATIO_SHIFT	8
 #define HCLK_PCLK_RATIO_MASK	0x3
 
-#define PERIP_CLK_CFG		((unsigned int *)(MISC_BASE + 0x028))
+#define PERIP_CLK_CFG		(MISC_BASE + 0x028)
 /* PERIP_CLK_CFG register masks */
 #define UART_CLK_SHIFT		4
 #define UART_CLK_MASK		0x1
@@ -63,10 +63,10 @@
 #define GPT1_CLK_SHIFT		11
 #define GPT2_CLK_SHIFT		12
 #define GPT_CLK_MASK		0x1
-#define AUX_CLK_PLL3_MASK	0
-#define AUX_CLK_PLL1_MASK	1
+#define AUX_CLK_PLL3_VAL	0
+#define AUX_CLK_PLL1_VAL	1
 
-#define PERIP1_CLK_ENB		((unsigned int *)(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
@@ -85,34 +85,35 @@
 #define USBH_CLK_ENB		25
 #define C3_CLK_ENB		31
 
-#define SOC_CORE_ID		((unsigned int *)(MISC_BASE + 0x030))
-#define RAS_CLK_ENB		((unsigned int *)(MISC_BASE + 0x034))
-#define PERIP1_SOF_RST		((unsigned int *)(MISC_BASE + 0x038))
+#define SOC_CORE_ID		(MISC_BASE + 0x030)
+#define RAS_CLK_ENB		(MISC_BASE + 0x034)
+#define PERIP1_SOF_RST		(MISC_BASE + 0x038)
 /* PERIP1_SOF_RST register masks */
 #define JPEG_SOF_RST		8
 
-#define SOC_USER_ID		((unsigned int *)(MISC_BASE + 0x03C))
-#define RAS_SOF_RST		((unsigned int *)(MISC_BASE + 0x040))
-#define PRSC1_CLK_CFG		((unsigned int *)(MISC_BASE + 0x044))
-#define PRSC2_CLK_CFG		((unsigned int *)(MISC_BASE + 0x048))
-#define PRSC3_CLK_CFG		((unsigned int *)(MISC_BASE + 0x04C))
+#define SOC_USER_ID		(MISC_BASE + 0x03C)
+#define RAS_SOF_RST		(MISC_BASE + 0x040)
+#define PRSC1_CLK_CFG		(MISC_BASE + 0x044)
+#define PRSC2_CLK_CFG		(MISC_BASE + 0x048)
+#define PRSC3_CLK_CFG		(MISC_BASE + 0x04C)
 /* gpt synthesizer register masks */
 #define GPT_MSCALE_SHIFT	0
 #define GPT_MSCALE_MASK		0xFFF
 #define GPT_NSCALE_SHIFT	12
 #define GPT_NSCALE_MASK		0xF
 
-#define AMEM_CLK_CFG		((unsigned int *)(MISC_BASE + 0x050))
-#define EXPI_CLK_CFG		((unsigned int *)(MISC_BASE + 0x054))
-#define CLCD_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x05C))
-#define FIRDA_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x060))
-#define UART_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x064))
-#define GMAC_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x068))
-#define RAS1_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x06C))
-#define RAS2_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x070))
-#define RAS3_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x074))
-#define RAS4_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x078))
+#define AMEM_CLK_CFG		(MISC_BASE + 0x050)
+#define EXPI_CLK_CFG		(MISC_BASE + 0x054)
+#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 RAS1_CLK_SYNT		(MISC_BASE + 0x06C)
+#define RAS2_CLK_SYNT		(MISC_BASE + 0x070)
+#define RAS3_CLK_SYNT		(MISC_BASE + 0x074)
+#define RAS4_CLK_SYNT		(MISC_BASE + 0x078)
 /* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB		31
 #define AUX_EQ_SEL_SHIFT	30
 #define AUX_EQ_SEL_MASK		1
 #define AUX_EQ1_SEL		0
@@ -122,42 +123,42 @@
 #define AUX_YSCALE_SHIFT	0
 #define AUX_YSCALE_MASK		0xFFF
 
-#define ICM1_ARB_CFG		((unsigned int *)(MISC_BASE + 0x07C))
-#define ICM2_ARB_CFG		((unsigned int *)(MISC_BASE + 0x080))
-#define ICM3_ARB_CFG		((unsigned int *)(MISC_BASE + 0x084))
-#define ICM4_ARB_CFG		((unsigned int *)(MISC_BASE + 0x088))
-#define ICM5_ARB_CFG		((unsigned int *)(MISC_BASE + 0x08C))
-#define ICM6_ARB_CFG		((unsigned int *)(MISC_BASE + 0x090))
-#define ICM7_ARB_CFG		((unsigned int *)(MISC_BASE + 0x094))
-#define ICM8_ARB_CFG		((unsigned int *)(MISC_BASE + 0x098))
-#define ICM9_ARB_CFG		((unsigned int *)(MISC_BASE + 0x09C))
-#define DMA_CHN_CFG		((unsigned int *)(MISC_BASE + 0x0A0))
-#define USB2_PHY_CFG		((unsigned int *)(MISC_BASE + 0x0A4))
-#define GMAC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0A8))
-#define EXPI_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0AC))
-#define PRC1_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C0))
-#define PRC2_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C4))
-#define PRC3_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C8))
-#define PRC4_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0CC))
-#define PRC1_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D0))
-#define PRC2_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D4))
-#define PRC3_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D8))
-#define PRC4_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0DC))
-#define PWRDOWN_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0E0))
-#define COMPSSTL_1V8_CFG	((unsigned int *)(MISC_BASE + 0x0E4))
-#define COMPSSTL_2V5_CFG	((unsigned int *)(MISC_BASE + 0x0E8))
-#define COMPCOR_3V3_CFG		((unsigned int *)(MISC_BASE + 0x0EC))
-#define SSTLPAD_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F0))
-#define BIST1_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F4))
-#define BIST2_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F8))
-#define BIST3_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0FC))
-#define BIST4_CFG_CTR		((unsigned int *)(MISC_BASE + 0x100))
-#define BIST5_CFG_CTR		((unsigned int *)(MISC_BASE + 0x104))
-#define BIST1_STS_RES		((unsigned int *)(MISC_BASE + 0x108))
-#define BIST2_STS_RES		((unsigned int *)(MISC_BASE + 0x10C))
-#define BIST3_STS_RES		((unsigned int *)(MISC_BASE + 0x110))
-#define BIST4_STS_RES		((unsigned int *)(MISC_BASE + 0x114))
-#define BIST5_STS_RES		((unsigned int *)(MISC_BASE + 0x118))
-#define SYSERR_CFG_CTR		((unsigned int *)(MISC_BASE + 0x11C))
+#define ICM1_ARB_CFG		(MISC_BASE + 0x07C)
+#define ICM2_ARB_CFG		(MISC_BASE + 0x080)
+#define ICM3_ARB_CFG		(MISC_BASE + 0x084)
+#define ICM4_ARB_CFG		(MISC_BASE + 0x088)
+#define ICM5_ARB_CFG		(MISC_BASE + 0x08C)
+#define ICM6_ARB_CFG		(MISC_BASE + 0x090)
+#define ICM7_ARB_CFG		(MISC_BASE + 0x094)
+#define ICM8_ARB_CFG		(MISC_BASE + 0x098)
+#define ICM9_ARB_CFG		(MISC_BASE + 0x09C)
+#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
+#define USB2_PHY_CFG		(MISC_BASE + 0x0A4)
+#define GMAC_CFG_CTR		(MISC_BASE + 0x0A8)
+#define EXPI_CFG_CTR		(MISC_BASE + 0x0AC)
+#define PRC1_LOCK_CTR		(MISC_BASE + 0x0C0)
+#define PRC2_LOCK_CTR		(MISC_BASE + 0x0C4)
+#define PRC3_LOCK_CTR		(MISC_BASE + 0x0C8)
+#define PRC4_LOCK_CTR		(MISC_BASE + 0x0CC)
+#define PRC1_IRQ_CTR		(MISC_BASE + 0x0D0)
+#define PRC2_IRQ_CTR		(MISC_BASE + 0x0D4)
+#define PRC3_IRQ_CTR		(MISC_BASE + 0x0D8)
+#define PRC4_IRQ_CTR		(MISC_BASE + 0x0DC)
+#define PWRDOWN_CFG_CTR		(MISC_BASE + 0x0E0)
+#define COMPSSTL_1V8_CFG	(MISC_BASE + 0x0E4)
+#define COMPSSTL_2V5_CFG	(MISC_BASE + 0x0E8)
+#define COMPCOR_3V3_CFG		(MISC_BASE + 0x0EC)
+#define SSTLPAD_CFG_CTR		(MISC_BASE + 0x0F0)
+#define BIST1_CFG_CTR		(MISC_BASE + 0x0F4)
+#define BIST2_CFG_CTR		(MISC_BASE + 0x0F8)
+#define BIST3_CFG_CTR		(MISC_BASE + 0x0FC)
+#define BIST4_CFG_CTR		(MISC_BASE + 0x100)
+#define BIST5_CFG_CTR		(MISC_BASE + 0x104)
+#define BIST1_STS_RES		(MISC_BASE + 0x108)
+#define BIST2_STS_RES		(MISC_BASE + 0x10C)
+#define BIST3_STS_RES		(MISC_BASE + 0x110)
+#define BIST4_STS_RES		(MISC_BASE + 0x114)
+#define BIST5_STS_RES		(MISC_BASE + 0x118)
+#define SYSERR_CFG_CTR		(MISC_BASE + 0x11C)
 
 #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
index dcca856..63fd983 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear.h
@@ -14,124 +14,61 @@
 #ifndef __MACH_SPEAR3XX_H
 #define __MACH_SPEAR3XX_H
 
-#include <mach/hardware.h>
+#include <asm/memory.h>
 #include <mach/spear300.h>
 #include <mach/spear310.h>
 #include <mach/spear320.h>
 
-#define SPEAR3XX_ML_SDRAM_BASE		0x00000000
-#define SPEAR3XX_ML_SDRAM_SIZE		0x40000000
+#define SPEAR3XX_ML_SDRAM_BASE		UL(0x00000000)
 
-#define SPEAR3XX_ICM9_BASE		0xC0000000
-#define SPEAR3XX_ICM9_SIZE		0x10000000
+#define SPEAR3XX_ICM9_BASE		UL(0xC0000000)
 
 /* ICM1 - Low speed connection */
-#define SPEAR3XX_ICM1_2_BASE		0xD0000000
-#define SPEAR3XX_ICM1_2_SIZE		0x10000000
-
-#define SPEAR3XX_ICM1_UART_BASE		0xD0000000
+#define SPEAR3XX_ICM1_2_BASE		UL(0xD0000000)
+#define SPEAR3XX_ICM1_UART_BASE		UL(0xD0000000)
 #define VA_SPEAR3XX_ICM1_UART_BASE	IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE)
-#define SPEAR3XX_ICM1_UART_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_ADC_BASE		0xD0080000
-#define SPEAR3XX_ICM1_ADC_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_SSP_BASE		0xD0100000
-#define SPEAR3XX_ICM1_SSP_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_I2C_BASE		0xD0180000
-#define SPEAR3XX_ICM1_I2C_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_JPEG_BASE		0xD0800000
-#define SPEAR3XX_ICM1_JPEG_SIZE		0x00800000
-
-#define SPEAR3XX_ICM1_IRDA_BASE		0xD1000000
-#define SPEAR3XX_ICM1_IRDA_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_SRAM_BASE		0xD2800000
-#define SPEAR3XX_ICM1_SRAM_SIZE		0x05800000
+#define SPEAR3XX_ICM1_ADC_BASE		UL(0xD0080000)
+#define SPEAR3XX_ICM1_SSP_BASE		UL(0xD0100000)
+#define SPEAR3XX_ICM1_I2C_BASE		UL(0xD0180000)
+#define SPEAR3XX_ICM1_JPEG_BASE		UL(0xD0800000)
+#define SPEAR3XX_ICM1_IRDA_BASE		UL(0xD1000000)
+#define SPEAR3XX_ICM1_SRAM_BASE		UL(0xD2800000)
 
 /* ICM2 - Application Subsystem */
-#define SPEAR3XX_ICM2_HWACCEL0_BASE	0xD8800000
-#define SPEAR3XX_ICM2_HWACCEL0_SIZE	0x00800000
-
-#define SPEAR3XX_ICM2_HWACCEL1_BASE	0xD9000000
-#define SPEAR3XX_ICM2_HWACCEL1_SIZE	0x00800000
+#define SPEAR3XX_ICM2_HWACCEL0_BASE	UL(0xD8800000)
+#define SPEAR3XX_ICM2_HWACCEL1_BASE	UL(0xD9000000)
 
 /* ICM4 - High Speed Connection */
-#define SPEAR3XX_ICM4_BASE		0xE0000000
-#define SPEAR3XX_ICM4_SIZE		0x08000000
-
-#define SPEAR3XX_ICM4_MII_BASE		0xE0800000
-#define SPEAR3XX_ICM4_MII_SIZE		0x00800000
-
-#define SPEAR3XX_ICM4_USBD_FIFO_BASE	0xE1000000
-#define SPEAR3XX_ICM4_USBD_FIFO_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USBD_CSR_BASE	0xE1100000
-#define SPEAR3XX_ICM4_USBD_CSR_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USBD_PLDT_BASE	0xE1200000
-#define SPEAR3XX_ICM4_USBD_PLDT_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE	0xE1800000
-#define SPEAR3XX_ICM4_USB_EHCI0_1_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_OHCI0_BASE	0xE1900000
-#define SPEAR3XX_ICM4_USB_OHCI0_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_OHCI1_BASE	0xE2100000
-#define SPEAR3XX_ICM4_USB_OHCI1_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_ARB_BASE	0xE2800000
-#define SPEAR3XX_ICM4_USB_ARB_SIZE	0x00010000
+#define SPEAR3XX_ICM4_BASE		UL(0xE0000000)
+#define SPEAR3XX_ICM4_MII_BASE		UL(0xE0800000)
+#define SPEAR3XX_ICM4_USBD_FIFO_BASE	UL(0xE1000000)
+#define SPEAR3XX_ICM4_USBD_CSR_BASE	UL(0xE1100000)
+#define SPEAR3XX_ICM4_USBD_PLDT_BASE	UL(0xE1200000)
+#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE	UL(0xE1800000)
+#define SPEAR3XX_ICM4_USB_OHCI0_BASE	UL(0xE1900000)
+#define SPEAR3XX_ICM4_USB_OHCI1_BASE	UL(0xE2100000)
+#define SPEAR3XX_ICM4_USB_ARB_BASE	UL(0xE2800000)
 
 /* ML1 - Multi Layer CPU Subsystem */
-#define SPEAR3XX_ICM3_ML1_2_BASE	0xF0000000
-#define SPEAR3XX_ICM3_ML1_2_SIZE	0x0F000000
-
-#define SPEAR3XX_ML1_TMR_BASE		0xF0000000
-#define SPEAR3XX_ML1_TMR_SIZE		0x00100000
-
-#define SPEAR3XX_ML1_VIC_BASE		0xF1100000
+#define SPEAR3XX_ICM3_ML1_2_BASE	UL(0xF0000000)
+#define SPEAR3XX_ML1_TMR_BASE		UL(0xF0000000)
+#define SPEAR3XX_ML1_VIC_BASE		UL(0xF1100000)
 #define VA_SPEAR3XX_ML1_VIC_BASE	IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE)
-#define SPEAR3XX_ML1_VIC_SIZE		0x00100000
 
 /* ICM3 - Basic Subsystem */
-#define SPEAR3XX_ICM3_SMEM_BASE		0xF8000000
-#define SPEAR3XX_ICM3_SMEM_SIZE		0x04000000
-
-#define SPEAR3XX_ICM3_SMI_CTRL_BASE	0xFC000000
-#define SPEAR3XX_ICM3_SMI_CTRL_SIZE	0x00200000
-
-#define SPEAR3XX_ICM3_DMA_BASE		0xFC400000
-#define SPEAR3XX_ICM3_DMA_SIZE		0x00200000
-
-#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE	0xFC600000
-#define SPEAR3XX_ICM3_SDRAM_CTRL_SIZE	0x00200000
-
-#define SPEAR3XX_ICM3_TMR0_BASE		0xFC800000
-#define SPEAR3XX_ICM3_TMR0_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_WDT_BASE		0xFC880000
-#define SPEAR3XX_ICM3_WDT_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_RTC_BASE		0xFC900000
-#define SPEAR3XX_ICM3_RTC_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_GPIO_BASE		0xFC980000
-#define SPEAR3XX_ICM3_GPIO_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_SYS_CTRL_BASE	0xFCA00000
+#define SPEAR3XX_ICM3_SMEM_BASE		UL(0xF8000000)
+#define SPEAR3XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define SPEAR3XX_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE	UL(0xFC600000)
+#define SPEAR3XX_ICM3_TMR0_BASE		UL(0xFC800000)
+#define SPEAR3XX_ICM3_WDT_BASE		UL(0xFC880000)
+#define SPEAR3XX_ICM3_RTC_BASE		UL(0xFC900000)
+#define SPEAR3XX_ICM3_GPIO_BASE		UL(0xFC980000)
+#define SPEAR3XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
 #define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE	IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR3XX_ICM3_SYS_CTRL_SIZE	0x00080000
-
-#define SPEAR3XX_ICM3_MISC_REG_BASE	0xFCA80000
+#define SPEAR3XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
 #define VA_SPEAR3XX_ICM3_MISC_REG_BASE	IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE)
-#define SPEAR3XX_ICM3_MISC_REG_SIZE	0x00080000
-
-#define SPEAR3XX_ICM3_TMR1_BASE		0xFCB00000
-#define SPEAR3XX_ICM3_TMR1_SIZE		0x00080000
+#define SPEAR3XX_ICM3_TMR1_BASE		UL(0xFCB00000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR3XX_ICM1_UART_BASE
diff --git a/arch/arm/mach-spear3xx/include/mach/spear300.h b/arch/arm/mach-spear3xx/include/mach/spear300.h
index ccaa765..c723515 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear300.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear300.h
@@ -17,11 +17,9 @@
 #define __MACH_SPEAR300_H
 
 /* Base address of various IPs */
-#define SPEAR300_TELECOM_BASE		0x50000000
-#define SPEAR300_TELECOM_SIZE		0x10000000
+#define SPEAR300_TELECOM_BASE		UL(0x50000000)
 
 /* Interrupt registers offsets and masks */
-#define SPEAR300_TELECOM_REG_SIZE	0x00010000
 #define INT_ENB_MASK_REG		0x54
 #define INT_STS_MASK_REG		0x58
 #define IT_PERS_S_IRQ_MASK		(1 << 0)
@@ -36,47 +34,20 @@
 
 #define SHIRQ_RAS1_MASK			0x1FF
 
-#define SPEAR300_CLCD_BASE		0x60000000
-#define SPEAR300_CLCD_SIZE		0x10000000
-
-#define SPEAR300_SDIO_BASE		0x70000000
-#define SPEAR300_SDIO_SIZE		0x10000000
-
-#define SPEAR300_NAND_0_BASE		0x80000000
-#define SPEAR300_NAND_0_SIZE		0x04000000
-
-#define SPEAR300_NAND_1_BASE		0x84000000
-#define SPEAR300_NAND_1_SIZE		0x04000000
-
-#define SPEAR300_NAND_2_BASE		0x88000000
-#define SPEAR300_NAND_2_SIZE		0x04000000
-
-#define SPEAR300_NAND_3_BASE		0x8c000000
-#define SPEAR300_NAND_3_SIZE		0x04000000
-
-#define SPEAR300_NOR_0_BASE		0x90000000
-#define SPEAR300_NOR_0_SIZE		0x01000000
-
-#define SPEAR300_NOR_1_BASE		0x91000000
-#define SPEAR300_NOR_1_SIZE		0x01000000
-
-#define SPEAR300_NOR_2_BASE		0x92000000
-#define SPEAR300_NOR_2_SIZE		0x01000000
-
-#define SPEAR300_NOR_3_BASE		0x93000000
-#define SPEAR300_NOR_3_SIZE		0x01000000
-
-#define SPEAR300_FSMC_BASE		0x94000000
-#define SPEAR300_FSMC_SIZE		0x05000000
-
-#define SPEAR300_SOC_CONFIG_BASE	0x99000000
-#define SPEAR300_SOC_CONFIG_SIZE	0x00000008
-
-#define SPEAR300_KEYBOARD_BASE		0xA0000000
-#define SPEAR300_KEYBOARD_SIZE		0x09000000
-
-#define SPEAR300_GPIO_BASE		0xA9000000
-#define SPEAR300_GPIO_SIZE		0x07000000
+#define SPEAR300_CLCD_BASE		UL(0x60000000)
+#define SPEAR300_SDHCI_BASE		UL(0x70000000)
+#define SPEAR300_NAND_0_BASE		UL(0x80000000)
+#define SPEAR300_NAND_1_BASE		UL(0x84000000)
+#define SPEAR300_NAND_2_BASE		UL(0x88000000)
+#define SPEAR300_NAND_3_BASE		UL(0x8c000000)
+#define SPEAR300_NOR_0_BASE		UL(0x90000000)
+#define SPEAR300_NOR_1_BASE		UL(0x91000000)
+#define SPEAR300_NOR_2_BASE		UL(0x92000000)
+#define SPEAR300_NOR_3_BASE		UL(0x93000000)
+#define SPEAR300_FSMC_BASE		UL(0x94000000)
+#define SPEAR300_SOC_CONFIG_BASE	UL(0x99000000)
+#define SPEAR300_KEYBOARD_BASE		UL(0xA0000000)
+#define SPEAR300_GPIO_BASE		UL(0xA9000000)
 
 #endif /* __MACH_SPEAR300_H */
 
diff --git a/arch/arm/mach-spear3xx/include/mach/spear310.h b/arch/arm/mach-spear3xx/include/mach/spear310.h
index b27bb8a..1e85347 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear310.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear310.h
@@ -16,30 +16,18 @@
 #ifndef __MACH_SPEAR310_H
 #define __MACH_SPEAR310_H
 
-#define SPEAR310_NAND_BASE		0x40000000
-#define SPEAR310_NAND_SIZE		0x04000000
+#define SPEAR310_NAND_BASE		UL(0x40000000)
+#define SPEAR310_FSMC_BASE		UL(0x44000000)
+#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)
+#define SPEAR310_HDLC_BASE		UL(0xB2800000)
+#define SPEAR310_RS485_0_BASE		UL(0xB3000000)
+#define SPEAR310_RS485_1_BASE		UL(0xB3800000)
+#define SPEAR310_SOC_CONFIG_BASE	UL(0xB4000000)
 
-#define SPEAR310_FSMC_BASE		0x44000000
-#define SPEAR310_FSMC_SIZE		0x01000000
-
-#define SPEAR310_UART1_BASE		0xB2000000
-#define SPEAR310_UART2_BASE		0xB2080000
-#define SPEAR310_UART3_BASE		0xB2100000
-#define SPEAR310_UART4_BASE		0xB2180000
-#define SPEAR310_UART5_BASE		0xB2200000
-#define SPEAR310_UART_SIZE		0x00080000
-
-#define SPEAR310_HDLC_BASE		0xB2800000
-#define SPEAR310_HDLC_SIZE		0x00800000
-
-#define SPEAR310_RS485_0_BASE		0xB3000000
-#define SPEAR310_RS485_0_SIZE		0x00800000
-
-#define SPEAR310_RS485_1_BASE		0xB3800000
-#define SPEAR310_RS485_1_SIZE		0x00800000
-
-#define SPEAR310_SOC_CONFIG_BASE	0xB4000000
-#define SPEAR310_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
 #define SMII0_IRQ_MASK			(1 << 0)
diff --git a/arch/arm/mach-spear3xx/include/mach/spear320.h b/arch/arm/mach-spear3xx/include/mach/spear320.h
index 53677e4..940f0d8 100644
--- a/arch/arm/mach-spear3xx/include/mach/spear320.h
+++ b/arch/arm/mach-spear3xx/include/mach/spear320.h
@@ -16,54 +16,25 @@
 #ifndef __MACH_SPEAR320_H
 #define __MACH_SPEAR320_H
 
-#define SPEAR320_EMI_CTRL_BASE		0x40000000
-#define SPEAR320_EMI_CTRL_SIZE		0x08000000
+#define SPEAR320_EMI_CTRL_BASE		UL(0x40000000)
+#define SPEAR320_FSMC_BASE		UL(0x4C000000)
+#define SPEAR320_NAND_BASE		UL(0x50000000)
+#define SPEAR320_I2S_BASE		UL(0x60000000)
+#define SPEAR320_SDHCI_BASE		UL(0x70000000)
+#define SPEAR320_CLCD_BASE		UL(0x90000000)
+#define SPEAR320_PAR_PORT_BASE		UL(0xA0000000)
+#define SPEAR320_CAN0_BASE		UL(0xA1000000)
+#define SPEAR320_CAN1_BASE		UL(0xA2000000)
+#define SPEAR320_UART1_BASE		UL(0xA3000000)
+#define SPEAR320_UART2_BASE		UL(0xA4000000)
+#define SPEAR320_SSP0_BASE		UL(0xA5000000)
+#define SPEAR320_SSP1_BASE		UL(0xA6000000)
+#define SPEAR320_I2C_BASE		UL(0xA7000000)
+#define SPEAR320_PWM_BASE		UL(0xA8000000)
+#define SPEAR320_SMII0_BASE		UL(0xAA000000)
+#define SPEAR320_SMII1_BASE		UL(0xAB000000)
+#define SPEAR320_SOC_CONFIG_BASE	UL(0xB3000000)
 
-#define SPEAR320_FSMC_BASE		0x4C000000
-#define SPEAR320_FSMC_SIZE		0x01000000
-
-#define SPEAR320_I2S_BASE		0x60000000
-#define SPEAR320_I2S_SIZE		0x10000000
-
-#define SPEAR320_SDIO_BASE		0x70000000
-#define SPEAR320_SDIO_SIZE		0x10000000
-
-#define SPEAR320_CLCD_BASE		0x90000000
-#define SPEAR320_CLCD_SIZE		0x10000000
-
-#define SPEAR320_PAR_PORT_BASE		0xA0000000
-#define SPEAR320_PAR_PORT_SIZE		0x01000000
-
-#define SPEAR320_CAN0_BASE		0xA1000000
-#define SPEAR320_CAN0_SIZE		0x01000000
-
-#define SPEAR320_CAN1_BASE		0xA2000000
-#define SPEAR320_CAN1_SIZE		0x01000000
-
-#define SPEAR320_UART1_BASE		0xA3000000
-#define SPEAR320_UART2_BASE		0xA4000000
-#define SPEAR320_UART_SIZE		0x01000000
-
-#define SPEAR320_SSP0_BASE		0xA5000000
-#define SPEAR320_SSP0_SIZE		0x01000000
-
-#define SPEAR320_SSP1_BASE		0xA6000000
-#define SPEAR320_SSP1_SIZE		0x01000000
-
-#define SPEAR320_I2C_BASE		0xA7000000
-#define SPEAR320_I2C_SIZE		0x01000000
-
-#define SPEAR320_PWM_BASE		0xA8000000
-#define SPEAR320_PWM_SIZE		0x01000000
-
-#define SPEAR320_SMII0_BASE		0xAA000000
-#define SPEAR320_SMII0_SIZE		0x01000000
-
-#define SPEAR320_SMII1_BASE		0xAB000000
-#define SPEAR320_SMII1_SIZE		0x01000000
-
-#define SPEAR320_SOC_CONFIG_BASE	0xB3000000
-#define SPEAR320_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
 #define INT_CLR_MASK_REG		0x04
@@ -74,7 +45,7 @@
 #define EMI_IRQ_MASK			(1 << 7)
 #define CLCD_IRQ_MASK			(1 << 8)
 #define SPP_IRQ_MASK			(1 << 9)
-#define SDIO_IRQ_MASK			(1 << 10)
+#define SDHCI_IRQ_MASK			(1 << 10)
 #define CAN_U_IRQ_MASK			(1 << 11)
 #define CAN_L_IRQ_MASK			(1 << 12)
 #define UART1_IRQ_MASK			(1 << 13)
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index 5aa2d54..2697e65 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -15,9 +15,9 @@
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
 #include <plat/shirq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
 
 /* pad multiplexing support */
 /* muxing registers */
@@ -310,7 +310,7 @@ struct pmx_dev pmx_telecom_boot_pins = {
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = {
+struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
@@ -323,14 +323,14 @@ struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_sdio_4bit = {
-	.name = "telecom_sdio_4bit",
-	.modes = pmx_telecom_sdio_4bit_modes,
-	.mode_count = ARRAY_SIZE(pmx_telecom_sdio_4bit_modes),
+struct pmx_dev pmx_telecom_sdhci_4bit = {
+	.name = "telecom_sdhci_4bit",
+	.modes = pmx_telecom_sdhci_4bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = {
+struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
@@ -342,10 +342,10 @@ struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_telecom_sdio_8bit = {
-	.name = "telecom_sdio_8bit",
-	.modes = pmx_telecom_sdio_8bit_modes,
-	.mode_count = ARRAY_SIZE(pmx_telecom_sdio_8bit_modes),
+struct pmx_dev pmx_telecom_sdhci_8bit = {
+	.name = "telecom_sdhci_8bit",
+	.modes = pmx_telecom_sdhci_8bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
 	.enb_on_reset = 1,
 };
 
@@ -370,26 +370,6 @@ struct pmx_driver pmx_driver = {
 	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
-/* Add spear300 specific devices here */
-/* arm gpio1 device registration */
-static struct pl061_platform_data gpio1_plat_data = {
-	.gpio_base	= 8,
-	.irq_base	= SPEAR_GPIO1_INT_BASE,
-};
-
-struct amba_device gpio1_device = {
-	.dev = {
-		.init_name = "gpio1",
-		.platform_data = &gpio1_plat_data,
-	},
-	.res = {
-		.start = SPEAR300_GPIO_BASE,
-		.end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	.irq = {VIRQ_GPIO1, NO_IRQ},
-};
-
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -443,6 +423,26 @@ struct spear_shirq shirq_ras1 = {
 	},
 };
 
+/* Add spear300 specific devices here */
+/* arm gpio1 device registration */
+static struct pl061_platform_data gpio1_plat_data = {
+	.gpio_base	= 8,
+	.irq_base	= SPEAR_GPIO1_INT_BASE,
+};
+
+struct amba_device gpio1_device = {
+	.dev = {
+		.init_name = "gpio1",
+		.platform_data = &gpio1_plat_data,
+	},
+	.res = {
+		.start = SPEAR300_GPIO_BASE,
+		.end = SPEAR300_GPIO_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_GPIO1, NO_IRQ},
+};
+
 /* spear300 routines */
 void __init spear300_init(void)
 {
@@ -452,17 +452,21 @@ void __init spear300_init(void)
 	spear3xx_init();
 
 	/* shared irq registration */
-	shirq_ras1.regs.base =
-		ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE);
+	shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
 	if (shirq_ras1.regs.base) {
 		ret = spear_shirq_register(&shirq_ras1);
 		if (ret)
 			printk(KERN_ERR "Error registering Shared IRQ\n");
 	}
-}
 
-void spear300_pmx_init(void)
-{
-	spear_pmx_init(&pmx_driver, SPEAR300_SOC_CONFIG_BASE,
-			SPEAR300_SOC_CONFIG_SIZE);
+	/* pmx initialization */
+	pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
+	if (pmx_driver.base) {
+		ret = pmx_register(&pmx_driver);
+		if (ret)
+			printk(KERN_ERR "padmux: registeration failed. err no"
+					": %d\n", ret);
+		/* Free Mapping, device selection already done */
+		iounmap(pmx_driver.base);
+	}
 }
diff --git a/arch/arm/mach-spear3xx/spear300_evb.c b/arch/arm/mach-spear3xx/spear300_evb.c
index bb21db1..42d2253 100644
--- a/arch/arm/mach-spear3xx/spear300_evb.c
+++ b/arch/arm/mach-spear3xx/spear300_evb.c
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -28,7 +28,7 @@ static struct pmx_dev *pmx_devs[] = {
 	/* spear300 specific devices */
 	&pmx_fsmc_2_chips,
 	&pmx_clcd,
-	&pmx_telecom_sdio_4bit,
+	&pmx_telecom_sdhci_4bit,
 	&pmx_gpio1,
 };
 
@@ -51,14 +51,13 @@ static void __init spear300_evb_init(void)
 {
 	unsigned int i;
 
-	/* call spear300 machine init function */
-	spear300_init();
-
-	/* padmux initialization */
+	/* padmux initialization, must be done before spear300_init */
 	pmx_driver.mode = &photo_frame_mode;
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-	spear300_pmx_init();
+
+	/* call spear300 machine init function */
+	spear300_init();
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -72,6 +71,6 @@ MACHINE_START(SPEAR300, "ST-SPEAR300-EVB")
 	.boot_params	=	0x00000100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear3xx_timer,
 	.init_machine	=	spear300_evb_init,
 MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index 53b41b5..5c0a67b 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -13,9 +13,9 @@
 
 #include <linux/ptrace.h>
 #include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
 #include <plat/shirq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
 
 /* pad multiplexing support */
 /* muxing registers */
@@ -139,8 +139,6 @@ struct pmx_driver pmx_driver = {
 	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
-/* Add spear310 specific devices here */
-
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -257,6 +255,8 @@ struct spear_shirq shirq_intrcomm_ras = {
 	},
 };
 
+/* Add spear310 specific devices here */
+
 /* spear310 routines */
 void __init spear310_init(void)
 {
@@ -267,7 +267,7 @@ void __init spear310_init(void)
 	spear3xx_init();
 
 	/* shared irq registration */
-	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE);
+	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
 	if (base) {
 		/* shirq 1 */
 		shirq_ras1.regs.base = base;
@@ -293,10 +293,11 @@ void __init spear310_init(void)
 		if (ret)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
-}
 
-void spear310_pmx_init(void)
-{
-	spear_pmx_init(&pmx_driver, SPEAR310_SOC_CONFIG_BASE,
-			SPEAR310_SOC_CONFIG_SIZE);
+	/* pmx initialization */
+	pmx_driver.base = base;
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
+				ret);
 }
diff --git a/arch/arm/mach-spear3xx/spear310_evb.c b/arch/arm/mach-spear3xx/spear310_evb.c
index 7facf66..2d7f333 100644
--- a/arch/arm/mach-spear3xx/spear310_evb.c
+++ b/arch/arm/mach-spear3xx/spear310_evb.c
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -58,14 +58,13 @@ static void __init spear310_evb_init(void)
 {
 	unsigned int i;
 
-	/* call spear310 machine init function */
-	spear310_init();
-
-	/* padmux initialization */
+	/* padmux initialization, must be done before spear310_init */
 	pmx_driver.mode = NULL;
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-	spear310_pmx_init();
+
+	/* call spear310 machine init function */
+	spear310_init();
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -79,6 +78,6 @@ MACHINE_START(SPEAR310, "ST-SPEAR310-EVB")
 	.boot_params	=	0x00000100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear3xx_timer,
 	.init_machine	=	spear310_evb_init,
 MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 88b4652..741c1f4 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -13,9 +13,9 @@
 
 #include <linux/ptrace.h>
 #include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
 #include <plat/shirq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
 
 /* pad multiplexing support */
 /* muxing registers */
@@ -110,7 +110,7 @@ struct pmx_dev pmx_spp = {
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdio_modes[] = {
+struct pmx_dev_mode pmx_sdhci_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE |
 			SMALL_PRINTERS_MODE,
@@ -118,10 +118,10 @@ struct pmx_dev_mode pmx_sdio_modes[] = {
 	},
 };
 
-struct pmx_dev pmx_sdio = {
-	.name = "sdio",
-	.modes = pmx_sdio_modes,
-	.mode_count = ARRAY_SIZE(pmx_sdio_modes),
+struct pmx_dev pmx_sdhci = {
+	.name = "sdhci",
+	.modes = pmx_sdhci_modes,
+	.mode_count = ARRAY_SIZE(pmx_sdhci_modes),
 	.enb_on_reset = 1,
 };
 
@@ -215,17 +215,17 @@ struct pmx_dev pmx_can = {
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdio_led_modes[] = {
+struct pmx_dev_mode pmx_sdhci_led_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
 		.mask = PMX_SSP_CS_MASK,
 	},
 };
 
-struct pmx_dev pmx_sdio_led = {
-	.name = "sdio_led",
-	.modes = pmx_sdio_led_modes,
-	.mode_count = ARRAY_SIZE(pmx_sdio_led_modes),
+struct pmx_dev pmx_sdhci_led = {
+	.name = "sdhci_led",
+	.modes = pmx_sdhci_led_modes,
+	.mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
 	.enb_on_reset = 1,
 };
 
@@ -384,8 +384,6 @@ struct pmx_driver pmx_driver = {
 	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
-/* Add spear320 specific devices here */
-
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -510,6 +508,8 @@ struct spear_shirq shirq_intrcomm_ras = {
 	},
 };
 
+/* Add spear320 specific devices here */
+
 /* spear320 routines */
 void __init spear320_init(void)
 {
@@ -520,7 +520,7 @@ void __init spear320_init(void)
 	spear3xx_init();
 
 	/* shared irq registration */
-	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE);
+	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
 	if (base) {
 		/* shirq 1 */
 		shirq_ras1.regs.base = base;
@@ -540,10 +540,11 @@ void __init spear320_init(void)
 		if (ret)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
-}
 
-void spear320_pmx_init(void)
-{
-	spear_pmx_init(&pmx_driver, SPEAR320_SOC_CONFIG_BASE,
-			SPEAR320_SOC_CONFIG_SIZE);
+	/* pmx initialization */
+	pmx_driver.base = base;
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
+				ret);
 }
diff --git a/arch/arm/mach-spear3xx/spear320_evb.c b/arch/arm/mach-spear3xx/spear320_evb.c
index 62ac685..8213e4b 100644
--- a/arch/arm/mach-spear3xx/spear320_evb.c
+++ b/arch/arm/mach-spear3xx/spear320_evb.c
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -26,7 +26,7 @@ static struct pmx_dev *pmx_devs[] = {
 
 	/* spear320 specific devices */
 	&pmx_fsmc,
-	&pmx_sdio,
+	&pmx_sdhci,
 	&pmx_i2s,
 	&pmx_uart1,
 	&pmx_uart2,
@@ -55,14 +55,13 @@ static void __init spear320_evb_init(void)
 {
 	unsigned int i;
 
-	/* call spear320 machine init function */
-	spear320_init();
-
-	/* padmux initialization */
+	/* padmux initialization, must be done before spear320_init */
 	pmx_driver.mode = &auto_net_mii_mode;
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-	spear320_pmx_init();
+
+	/* call spear320 machine init function */
+	spear320_init();
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -76,6 +75,6 @@ MACHINE_START(SPEAR320, "ST-SPEAR320-EVB")
 	.boot_params	=	0x00000100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear3xx_timer,
 	.init_machine	=	spear320_evb_init,
 MACHINE_END
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 52f553c..d3ba8ca 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -19,7 +19,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* Add spear3xx machines common devices here */
 /* gpio device registration */
@@ -35,7 +35,7 @@ struct amba_device gpio_device = {
 	},
 	.res = {
 		.start = SPEAR3XX_ICM3_GPIO_BASE,
-		.end = SPEAR3XX_ICM3_GPIO_BASE + SPEAR3XX_ICM3_GPIO_SIZE - 1,
+		.end = SPEAR3XX_ICM3_GPIO_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.irq = {IRQ_BASIC_GPIO, NO_IRQ},
@@ -48,7 +48,7 @@ struct amba_device uart_device = {
 	},
 	.res = {
 		.start = SPEAR3XX_ICM1_UART_BASE,
-		.end = SPEAR3XX_ICM1_UART_BASE + SPEAR3XX_ICM1_UART_SIZE - 1,
+		.end = SPEAR3XX_ICM1_UART_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.irq = {IRQ_UART, NO_IRQ},
@@ -71,22 +71,22 @@ struct map_desc spear3xx_io_desc[] __initdata = {
 	{
 		.virtual	= VA_SPEAR3XX_ICM1_UART_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE),
-		.length		= SPEAR3XX_ICM1_UART_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ML1_VIC_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE),
-		.length		= SPEAR3XX_ML1_VIC_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ICM3_SYS_CTRL_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE),
-		.length		= SPEAR3XX_ICM3_SYS_CTRL_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ICM3_MISC_REG_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
-		.length		= SPEAR3XX_ICM3_MISC_REG_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	},
 };
@@ -523,26 +523,35 @@ struct pmx_dev pmx_plgpio_45_46_49_50 = {
 	.mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes),
 	.enb_on_reset = 1,
 };
+#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
 
-#endif
-
-/* spear padmux initialization function */
-void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size)
+static void __init spear3xx_timer_init(void)
 {
-	int ret = 0;
+	char pclk_name[] = "pll3_48m_clk";
+	struct clk *gpt_clk, *pclk;
+
+	/* 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();
+	}
 
-	/* pad mux initialization */
-	pmx_driver->base = ioremap(base, size);
-	if (!pmx_driver->base) {
-		ret = -ENOMEM;
-		goto pmx_fail;
+	/* 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();
 	}
 
-	ret = pmx_register(pmx_driver);
-	iounmap(pmx_driver->base);
+	clk_set_parent(gpt_clk, pclk);
+	clk_put(gpt_clk);
+	clk_put(pclk);
 
-pmx_fail:
-	if (ret)
-		printk(KERN_ERR "padmux: registration failed. err no: %d\n",
-				ret);
+	spear_setup_timer();
 }
+
+struct sys_timer spear3xx_timer = {
+	.init = spear3xx_timer_init,
+};
diff --git a/arch/arm/mach-spear6xx/clock.c b/arch/arm/mach-spear6xx/clock.c
index 36ff056..88b748b 100644
--- a/arch/arm/mach-spear6xx/clock.c
+++ b/arch/arm/mach-spear6xx/clock.c
@@ -13,8 +13,8 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <mach/misc_regs.h>
 #include <plat/clock.h>
+#include <mach/misc_regs.h>
 
 /* root clks */
 /* 32 KHz oscillator clock */
@@ -39,18 +39,43 @@ static struct clk rtc_clk = {
 };
 
 /* clock derived from 30 MHz osc clk */
+/* pll masks structure */
+static struct pll_clk_masks pll1_masks = {
+	.mode_mask = PLL_MODE_MASK,
+	.mode_shift = PLL_MODE_SHIFT,
+	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
+	.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
+	.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
+	.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
+	.div_p_mask = PLL_DIV_P_MASK,
+	.div_p_shift = PLL_DIV_P_SHIFT,
+	.div_n_mask = PLL_DIV_N_MASK,
+	.div_n_shift = PLL_DIV_N_SHIFT,
+};
+
 /* pll1 configuration structure */
 static struct pll_clk_config pll1_config = {
 	.mode_reg = PLL1_CTR,
 	.cfg_reg = PLL1_FRQ,
+	.masks = &pll1_masks,
+};
+
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
 /* PLL1 clock */
 static struct clk pll1_clk = {
+	.flags = ENABLED_ON_INIT,
 	.pclk = &osc_30m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
-	.recalc = &pll1_clk_recalc,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
 	.private_data = &pll1_config,
 };
 
@@ -76,31 +101,83 @@ static struct clk cpu_clk = {
 	.recalc = &follow_parent,
 };
 
+/* ahb masks structure */
+static struct bus_clk_masks ahb_masks = {
+	.mask = PLL_HCLK_RATIO_MASK,
+	.shift = PLL_HCLK_RATIO_SHIFT,
+};
+
 /* ahb configuration structure */
 static struct bus_clk_config ahb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = PLL_HCLK_RATIO_MASK,
-	.shift = PLL_HCLK_RATIO_SHIFT,
+	.masks = &ahb_masks,
+};
+
+/* ahb rate configuration table, in ascending order of rates */
+struct bus_rate_tbl bus_rtbl[] = {
+	{.div = 3}, /* == parent divided by 4 */
+	{.div = 2}, /* == parent divided by 3 */
+	{.div = 1}, /* == parent divided by 2 */
+	{.div = 0}, /* == parent divided by 1 */
 };
 
 /* ahb clock */
 static struct clk ahb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &pll1_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &ahb_config,
 };
 
+/* auxiliary synthesizers masks */
+static struct aux_clk_masks aux_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = AUX_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = AUX_XSCALE_MASK,
+	.xscale_sel_shift = AUX_XSCALE_SHIFT,
+	.yscale_sel_mask = AUX_YSCALE_MASK,
+	.yscale_sel_shift = AUX_YSCALE_SHIFT,
+};
+
+/* uart configurations */
+static struct aux_clk_config uart_synth_config = {
+	.synth_reg = UART_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+	/* For PLL1 = 332 MHz */
+	{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
+	{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+	.en_reg = UART_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.private_data = &uart_synth_config,
+};
+
 /* uart parents */
 static struct pclk_info uart_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &uart_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -112,19 +189,13 @@ static struct pclk_sel uart_pclk_sel = {
 	.pclk_sel_mask = UART_CLK_MASK,
 };
 
-/* uart configurations */
-static struct aux_clk_config uart_config = {
-	.synth_reg = UART_CLK_SYNT,
-};
-
 /* uart0 clock */
 static struct clk uart0_clk = {
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = UART0_CLK_ENB,
 	.pclk_sel = &uart_pclk_sel,
 	.pclk_sel_shift = UART_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &uart_config,
+	.recalc = &follow_parent,
 };
 
 /* uart1 clock */
@@ -133,25 +204,35 @@ static struct clk uart1_clk = {
 	.en_reg_bit = UART1_CLK_ENB,
 	.pclk_sel = &uart_pclk_sel,
 	.pclk_sel_shift = UART_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &uart_config,
+	.recalc = &follow_parent,
 };
 
 /* firda configurations */
-static struct aux_clk_config firda_config = {
+static struct aux_clk_config firda_synth_config = {
 	.synth_reg = FIRDA_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* firda synth clock */
+static struct clk firda_synth_clk = {
+	.en_reg = FIRDA_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.private_data = &firda_synth_config,
 };
 
 /* firda parents */
 static struct pclk_info firda_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &firda_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -169,25 +250,35 @@ static struct clk firda_clk = {
 	.en_reg_bit = FIRDA_CLK_ENB,
 	.pclk_sel = &firda_pclk_sel,
 	.pclk_sel_shift = FIRDA_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &firda_config,
+	.recalc = &follow_parent,
 };
 
 /* clcd configurations */
-static struct aux_clk_config clcd_config = {
+static struct aux_clk_config clcd_synth_config = {
 	.synth_reg = CLCD_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* firda synth clock */
+static struct clk clcd_synth_clk = {
+	.en_reg = CLCD_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.private_data = &clcd_synth_config,
 };
 
 /* clcd parents */
 static struct pclk_info clcd_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &clcd_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -205,82 +296,173 @@ static struct clk clcd_clk = {
 	.en_reg_bit = CLCD_CLK_ENB,
 	.pclk_sel = &clcd_pclk_sel,
 	.pclk_sel_shift = CLCD_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &clcd_config,
+	.recalc = &follow_parent,
+};
+
+/* gpt synthesizer masks */
+static struct gpt_clk_masks gpt_masks = {
+	.mscale_sel_mask = GPT_MSCALE_MASK,
+	.mscale_sel_shift = GPT_MSCALE_SHIFT,
+	.nscale_sel_mask = GPT_NSCALE_MASK,
+	.nscale_sel_shift = GPT_NSCALE_SHIFT,
+};
+
+/* gpt rate configuration table, in ascending order of rates */
+struct gpt_rate_tbl gpt_rtbl[] = {
+	/* For pll1 = 332 MHz */
+	{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+	{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+	{.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* gpt0 synth clk config*/
+static struct gpt_clk_config gpt0_synth_config = {
+	.synth_reg = PRSC1_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt0_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt0_synth_config,
 };
 
 /* gpt parents */
-static struct pclk_info gpt_pclk_info[] = {
+static struct pclk_info gpt0_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &gpt0_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
 /* gpt parent select structure */
-static struct pclk_sel gpt_pclk_sel = {
-	.pclk_info = gpt_pclk_info,
-	.pclk_count = ARRAY_SIZE(gpt_pclk_info),
+static struct pclk_sel gpt0_pclk_sel = {
+	.pclk_info = gpt0_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
 	.pclk_sel_reg = PERIP_CLK_CFG,
 	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
-/* gpt0_1 configurations */
-static struct aux_clk_config gpt0_1_config = {
-	.synth_reg = PRSC1_CLK_CFG,
-};
-
 /* gpt0 ARM1 subsystem timer clock */
 static struct clk gpt0_clk = {
 	.flags = ALWAYS_ENABLED,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt0_pclk_sel,
 	.pclk_sel_shift = GPT0_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt0_1_config,
+	.recalc = &follow_parent,
+};
+
+
+/* Note: gpt0 and gpt1 share same parent clocks */
+/* gpt parent select structure */
+static struct pclk_sel gpt1_pclk_sel = {
+	.pclk_info = gpt0_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt1 timer clock */
 static struct clk gpt1_clk = {
 	.flags = ALWAYS_ENABLED,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt1_pclk_sel,
 	.pclk_sel_shift = GPT1_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt0_1_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt2 configurations */
-static struct aux_clk_config gpt2_config = {
+/* gpt2 synth clk config*/
+static struct gpt_clk_config gpt2_synth_config = {
 	.synth_reg = PRSC2_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt2_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt2_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt2_pclk_info[] = {
+	{
+		.pclk = &gpt2_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt2_pclk_sel = {
+	.pclk_info = gpt2_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt2 timer clock */
 static struct clk gpt2_clk = {
-	.en_reg = PERIP1_CLK_ENB,
-	.en_reg_bit = GPT2_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &gpt2_pclk_sel,
 	.pclk_sel_shift = GPT2_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt2_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt3 configurations */
-static struct aux_clk_config gpt3_config = {
+/* gpt3 synth clk config*/
+static struct gpt_clk_config gpt3_synth_config = {
 	.synth_reg = PRSC3_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt3_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt3_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt3_pclk_info[] = {
+	{
+		.pclk = &gpt3_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt3_pclk_sel = {
+	.pclk_info = gpt3_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt3_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt3 timer clock */
 static struct clk gpt3_clk = {
-	.en_reg = PERIP1_CLK_ENB,
-	.en_reg_bit = GPT3_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &gpt3_pclk_sel,
 	.pclk_sel_shift = GPT3_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt3_config,
+	.recalc = &follow_parent,
 };
 
 /* clock derived from pll3 clk */
@@ -309,18 +491,26 @@ static struct clk usbd_clk = {
 };
 
 /* clock derived from ahb clk */
+/* apb masks structure */
+static struct bus_clk_masks apb_masks = {
+	.mask = HCLK_PCLK_RATIO_MASK,
+	.shift = HCLK_PCLK_RATIO_SHIFT,
+};
+
 /* apb configuration structure */
 static struct bus_clk_config apb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = HCLK_PCLK_RATIO_MASK,
-	.shift = HCLK_PCLK_RATIO_SHIFT,
+	.masks = &apb_masks,
 };
 
 /* apb clock */
 static struct clk apb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &ahb_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &apb_config,
 };
 
@@ -432,12 +622,12 @@ static struct clk dummy_apb_pclk;
 
 /* array of all spear 6xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
-	{ .con_id = "apb_pclk",	.clk = &dummy_apb_pclk},
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{ .con_id = "osc_32k_clk",	.clk = &osc_32k_clk},
 	{ .con_id = "osc_30m_clk",	.clk = &osc_30m_clk},
 	/* clock derived from 32 KHz os		 clk */
-	{ .dev_id = "rtc",		.clk = &rtc_clk},
+	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 30 MHz os		 clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
@@ -445,6 +635,12 @@ static struct clk_lookup spear_clk_lookups[] = {
 	/* clock derived from pll1 clk */
 	{ .con_id = "cpu_clk",		.clk = &cpu_clk},
 	{ .con_id = "ahb_clk",		.clk = &ahb_clk},
+	{ .con_id = "uart_synth_clk",	.clk = &uart_synth_clk},
+	{ .con_id = "firda_synth_clk",	.clk = &firda_synth_clk},
+	{ .con_id = "clcd_synth_clk",	.clk = &clcd_synth_clk},
+	{ .con_id = "gpt0_synth_clk",	.clk = &gpt0_synth_clk},
+	{ .con_id = "gpt2_synth_clk",	.clk = &gpt2_synth_clk},
+	{ .con_id = "gpt3_synth_clk",	.clk = &gpt3_synth_clk},
 	{ .dev_id = "uart0",		.clk = &uart0_clk},
 	{ .dev_id = "uart1",		.clk = &uart1_clk},
 	{ .dev_id = "firda",		.clk = &firda_clk},
@@ -454,22 +650,22 @@ static struct clk_lookup spear_clk_lookups[] = {
 	{ .dev_id = "gpt2",		.clk = &gpt2_clk},
 	{ .dev_id = "gpt3",		.clk = &gpt3_clk},
 	/* clock derived from pll3 clk */
-	{ .dev_id = "usbh0",		.clk = &usbh0_clk},
-	{ .dev_id = "usbh1",		.clk = &usbh1_clk},
-	{ .dev_id = "usbd",		.clk = &usbd_clk},
+	{ .dev_id = "designware_udc",	.clk = &usbd_clk},
+	{ .con_id = "usbh.0_clk",	.clk = &usbh0_clk},
+	{ .con_id = "usbh.1_clk",	.clk = &usbh1_clk},
 	/* clock derived from ahb clk */
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
-	{ .dev_id = "i2c",		.clk = &i2c_clk},
+	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
 	{ .dev_id = "jpeg",		.clk = &jpeg_clk},
 	{ .dev_id = "gmac",		.clk = &gmac_clk},
 	{ .dev_id = "smi",		.clk = &smi_clk},
-	{ .dev_id = "fsmc",		.clk = &fsmc_clk},
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
 	/* clock derived from apb clk */
 	{ .dev_id = "adc",		.clk = &adc_clk},
-	{ .dev_id = "ssp0",		.clk = &ssp0_clk},
-	{ .dev_id = "ssp1",		.clk = &ssp1_clk},
-	{ .dev_id = "ssp2",		.clk = &ssp2_clk},
+	{ .dev_id = "ssp-pl022.0",	.clk = &ssp0_clk},
+	{ .dev_id = "ssp-pl022.1",	.clk = &ssp1_clk},
+	{ .dev_id = "ssp-pl022.2",	.clk = &ssp2_clk},
 	{ .dev_id = "gpio0",		.clk = &gpio0_clk},
 	{ .dev_id = "gpio1",		.clk = &gpio1_clk},
 	{ .dev_id = "gpio2",		.clk = &gpio2_clk},
diff --git a/arch/arm/mach-spear6xx/include/mach/entry-macro.S b/arch/arm/mach-spear6xx/include/mach/entry-macro.S
index 9eaecae..8a0b0ed 100644
--- a/arch/arm/mach-spear6xx/include/mach/entry-macro.S
+++ b/arch/arm/mach-spear6xx/include/mach/entry-macro.S
@@ -11,9 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <mach/hardware.h>
-#include <mach/spear.h>
 #include <asm/hardware/vic.h>
+#include <mach/hardware.h>
 
 		.macro	disable_fiq
 		.endm
diff --git a/arch/arm/mach-spear6xx/include/mach/generic.h b/arch/arm/mach-spear6xx/include/mach/generic.h
index 16205a5..94cf4a6 100644
--- a/arch/arm/mach-spear6xx/include/mach/generic.h
+++ b/arch/arm/mach-spear6xx/include/mach/generic.h
@@ -14,11 +14,11 @@
 #ifndef __MACH_GENERIC_H
 #define __MACH_GENERIC_H
 
-#include <asm/mach/time.h>
-#include <asm/mach/map.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>
 
 /*
  * Each GPT has 2 timer channels
@@ -31,9 +31,10 @@
 /* Add spear6xx family device structure declarations here */
 extern struct amba_device gpio_device[];
 extern struct amba_device uart_device[];
-extern struct sys_timer spear_sys_timer;
+extern struct sys_timer spear6xx_timer;
 
 /* Add spear6xx family function declarations here */
+void __init spear_setup_timer(void);
 void __init spear6xx_map_io(void);
 void __init spear6xx_init_irq(void);
 void __init spear6xx_init(void);
diff --git a/arch/arm/mach-spear6xx/include/mach/hardware.h b/arch/arm/mach-spear6xx/include/mach/hardware.h
index 7545116..0b3f96a 100644
--- a/arch/arm/mach-spear6xx/include/mach/hardware.h
+++ b/arch/arm/mach-spear6xx/include/mach/hardware.h
@@ -14,8 +14,10 @@
 #ifndef __MACH_HARDWARE_H
 #define __MACH_HARDWARE_H
 
+#include <plat/hardware.h>
+#include <mach/spear.h>
+
 /* Vitual to physical translation of statically mapped space */
 #define IO_ADDRESS(x)		(x | 0xF0000000)
 
 #endif /* __MACH_HARDWARE_H */
-
diff --git a/arch/arm/mach-spear6xx/include/mach/misc_regs.h b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
index 0390803..68c20a0 100644
--- a/arch/arm/mach-spear6xx/include/mach/misc_regs.h
+++ b/arch/arm/mach-spear6xx/include/mach/misc_regs.h
@@ -14,16 +14,16 @@
 #ifndef __MACH_MISC_REGS_H
 #define __MACH_MISC_REGS_H
 
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
-#define MISC_BASE		VA_SPEAR6XX_ICM3_MISC_REG_BASE
+#define MISC_BASE		IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE)
 
-#define SOC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x000))
-#define DIAG_CFG_CTR		((unsigned int *)(MISC_BASE + 0x004))
-#define PLL1_CTR		((unsigned int *)(MISC_BASE + 0x008))
-#define PLL1_FRQ		((unsigned int *)(MISC_BASE + 0x00C))
-#define PLL1_MOD		((unsigned int *)(MISC_BASE + 0x010))
-#define PLL2_CTR		((unsigned int *)(MISC_BASE + 0x014))
+#define SOC_CFG_CTR		(MISC_BASE + 0x000)
+#define DIAG_CFG_CTR		(MISC_BASE + 0x004)
+#define PLL1_CTR		(MISC_BASE + 0x008)
+#define PLL1_FRQ		(MISC_BASE + 0x00C)
+#define PLL1_MOD		(MISC_BASE + 0x010)
+#define PLL2_CTR		(MISC_BASE + 0x014)
 /* PLL_CTR register masks */
 #define PLL_ENABLE		2
 #define PLL_MODE_SHIFT		4
@@ -33,7 +33,7 @@
 #define PLL_MODE_DITH_DSB	2
 #define PLL_MODE_DITH_SSB	3
 
-#define PLL2_FRQ		((unsigned int *)(MISC_BASE + 0x018))
+#define PLL2_FRQ		(MISC_BASE + 0x018)
 /* PLL FRQ register masks */
 #define PLL_DIV_N_SHIFT		0
 #define PLL_DIV_N_MASK		0xFF
@@ -44,16 +44,16 @@
 #define PLL_DITH_FDBK_M_SHIFT	16
 #define PLL_DITH_FDBK_M_MASK	0xFFFF
 
-#define PLL2_MOD		((unsigned int *)(MISC_BASE + 0x01C))
-#define PLL_CLK_CFG		((unsigned int *)(MISC_BASE + 0x020))
-#define CORE_CLK_CFG		((unsigned int *)(MISC_BASE + 0x024))
+#define PLL2_MOD		(MISC_BASE + 0x01C)
+#define PLL_CLK_CFG		(MISC_BASE + 0x020)
+#define CORE_CLK_CFG		(MISC_BASE + 0x024)
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
 #define PLL_HCLK_RATIO_MASK	0x3
 #define HCLK_PCLK_RATIO_SHIFT	8
 #define HCLK_PCLK_RATIO_MASK	0x3
 
-#define PERIP_CLK_CFG		((unsigned int *)(MISC_BASE + 0x028))
+#define PERIP_CLK_CFG		(MISC_BASE + 0x028)
 /* PERIP_CLK_CFG register masks */
 #define CLCD_CLK_SHIFT		2
 #define CLCD_CLK_MASK		0x3
@@ -66,10 +66,10 @@
 #define GPT2_CLK_SHIFT		11
 #define GPT3_CLK_SHIFT		12
 #define GPT_CLK_MASK		0x1
-#define AUX_CLK_PLL3_MASK	0
-#define AUX_CLK_PLL1_MASK	1
+#define AUX_CLK_PLL3_VAL	0
+#define AUX_CLK_PLL1_VAL	1
 
-#define PERIP1_CLK_ENB		((unsigned int *)(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
@@ -95,34 +95,35 @@
 #define USBH0_CLK_ENB		25
 #define USBH1_CLK_ENB		26
 
-#define SOC_CORE_ID		((unsigned int *)(MISC_BASE + 0x030))
-#define RAS_CLK_ENB		((unsigned int *)(MISC_BASE + 0x034))
-#define PERIP1_SOF_RST		((unsigned int *)(MISC_BASE + 0x038))
+#define SOC_CORE_ID		(MISC_BASE + 0x030)
+#define RAS_CLK_ENB		(MISC_BASE + 0x034)
+#define PERIP1_SOF_RST		(MISC_BASE + 0x038)
 /* PERIP1_SOF_RST register masks */
 #define JPEG_SOF_RST		8
 
-#define SOC_USER_ID		((unsigned int *)(MISC_BASE + 0x03C))
-#define RAS_SOF_RST		((unsigned int *)(MISC_BASE + 0x040))
-#define PRSC1_CLK_CFG		((unsigned int *)(MISC_BASE + 0x044))
-#define PRSC2_CLK_CFG		((unsigned int *)(MISC_BASE + 0x048))
-#define PRSC3_CLK_CFG		((unsigned int *)(MISC_BASE + 0x04C))
+#define SOC_USER_ID		(MISC_BASE + 0x03C)
+#define RAS_SOF_RST		(MISC_BASE + 0x040)
+#define PRSC1_CLK_CFG		(MISC_BASE + 0x044)
+#define PRSC2_CLK_CFG		(MISC_BASE + 0x048)
+#define PRSC3_CLK_CFG		(MISC_BASE + 0x04C)
 /* gpt synthesizer register masks */
 #define GPT_MSCALE_SHIFT	0
 #define GPT_MSCALE_MASK		0xFFF
 #define GPT_NSCALE_SHIFT	12
 #define GPT_NSCALE_MASK		0xF
 
-#define AMEM_CLK_CFG		((unsigned int *)(MISC_BASE + 0x050))
-#define EXPI_CLK_CFG		((unsigned int *)(MISC_BASE + 0x054))
-#define CLCD_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x05C))
-#define FIRDA_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x060))
-#define UART_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x064))
-#define GMAC_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x068))
-#define RAS1_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x06C))
-#define RAS2_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x070))
-#define RAS3_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x074))
-#define RAS4_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x078))
+#define AMEM_CLK_CFG		(MISC_BASE + 0x050)
+#define EXPI_CLK_CFG		(MISC_BASE + 0x054)
+#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 RAS1_CLK_SYNT		(MISC_BASE + 0x06C)
+#define RAS2_CLK_SYNT		(MISC_BASE + 0x070)
+#define RAS3_CLK_SYNT		(MISC_BASE + 0x074)
+#define RAS4_CLK_SYNT		(MISC_BASE + 0x078)
 /* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB		31
 #define AUX_EQ_SEL_SHIFT	30
 #define AUX_EQ_SEL_MASK		1
 #define AUX_EQ1_SEL		0
@@ -132,42 +133,42 @@
 #define AUX_YSCALE_SHIFT	0
 #define AUX_YSCALE_MASK		0xFFF
 
-#define ICM1_ARB_CFG		((unsigned int *)(MISC_BASE + 0x07C))
-#define ICM2_ARB_CFG		((unsigned int *)(MISC_BASE + 0x080))
-#define ICM3_ARB_CFG		((unsigned int *)(MISC_BASE + 0x084))
-#define ICM4_ARB_CFG		((unsigned int *)(MISC_BASE + 0x088))
-#define ICM5_ARB_CFG		((unsigned int *)(MISC_BASE + 0x08C))
-#define ICM6_ARB_CFG		((unsigned int *)(MISC_BASE + 0x090))
-#define ICM7_ARB_CFG		((unsigned int *)(MISC_BASE + 0x094))
-#define ICM8_ARB_CFG		((unsigned int *)(MISC_BASE + 0x098))
-#define ICM9_ARB_CFG		((unsigned int *)(MISC_BASE + 0x09C))
-#define DMA_CHN_CFG		((unsigned int *)(MISC_BASE + 0x0A0))
-#define USB2_PHY_CFG		((unsigned int *)(MISC_BASE + 0x0A4))
-#define GMAC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0A8))
-#define EXPI_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0AC))
-#define PRC1_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C0))
-#define PRC2_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C4))
-#define PRC3_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C8))
-#define PRC4_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0CC))
-#define PRC1_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D0))
-#define PRC2_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D4))
-#define PRC3_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D8))
-#define PRC4_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0DC))
-#define PWRDOWN_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0E0))
-#define COMPSSTL_1V8_CFG	((unsigned int *)(MISC_BASE + 0x0E4))
-#define COMPSSTL_2V5_CFG	((unsigned int *)(MISC_BASE + 0x0E8))
-#define COMPCOR_3V3_CFG		((unsigned int *)(MISC_BASE + 0x0EC))
-#define SSTLPAD_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F0))
-#define BIST1_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F4))
-#define BIST2_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F8))
-#define BIST3_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0FC))
-#define BIST4_CFG_CTR		((unsigned int *)(MISC_BASE + 0x100))
-#define BIST5_CFG_CTR		((unsigned int *)(MISC_BASE + 0x104))
-#define BIST1_STS_RES		((unsigned int *)(MISC_BASE + 0x108))
-#define BIST2_STS_RES		((unsigned int *)(MISC_BASE + 0x10C))
-#define BIST3_STS_RES		((unsigned int *)(MISC_BASE + 0x110))
-#define BIST4_STS_RES		((unsigned int *)(MISC_BASE + 0x114))
-#define BIST5_STS_RES		((unsigned int *)(MISC_BASE + 0x118))
-#define SYSERR_CFG_CTR		((unsigned int *)(MISC_BASE + 0x11C))
+#define ICM1_ARB_CFG		(MISC_BASE + 0x07C)
+#define ICM2_ARB_CFG		(MISC_BASE + 0x080)
+#define ICM3_ARB_CFG		(MISC_BASE + 0x084)
+#define ICM4_ARB_CFG		(MISC_BASE + 0x088)
+#define ICM5_ARB_CFG		(MISC_BASE + 0x08C)
+#define ICM6_ARB_CFG		(MISC_BASE + 0x090)
+#define ICM7_ARB_CFG		(MISC_BASE + 0x094)
+#define ICM8_ARB_CFG		(MISC_BASE + 0x098)
+#define ICM9_ARB_CFG		(MISC_BASE + 0x09C)
+#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
+#define USB2_PHY_CFG		(MISC_BASE + 0x0A4)
+#define GMAC_CFG_CTR		(MISC_BASE + 0x0A8)
+#define EXPI_CFG_CTR		(MISC_BASE + 0x0AC)
+#define PRC1_LOCK_CTR		(MISC_BASE + 0x0C0)
+#define PRC2_LOCK_CTR		(MISC_BASE + 0x0C4)
+#define PRC3_LOCK_CTR		(MISC_BASE + 0x0C8)
+#define PRC4_LOCK_CTR		(MISC_BASE + 0x0CC)
+#define PRC1_IRQ_CTR		(MISC_BASE + 0x0D0)
+#define PRC2_IRQ_CTR		(MISC_BASE + 0x0D4)
+#define PRC3_IRQ_CTR		(MISC_BASE + 0x0D8)
+#define PRC4_IRQ_CTR		(MISC_BASE + 0x0DC)
+#define PWRDOWN_CFG_CTR		(MISC_BASE + 0x0E0)
+#define COMPSSTL_1V8_CFG	(MISC_BASE + 0x0E4)
+#define COMPSSTL_2V5_CFG	(MISC_BASE + 0x0E8)
+#define COMPCOR_3V3_CFG		(MISC_BASE + 0x0EC)
+#define SSTLPAD_CFG_CTR		(MISC_BASE + 0x0F0)
+#define BIST1_CFG_CTR		(MISC_BASE + 0x0F4)
+#define BIST2_CFG_CTR		(MISC_BASE + 0x0F8)
+#define BIST3_CFG_CTR		(MISC_BASE + 0x0FC)
+#define BIST4_CFG_CTR		(MISC_BASE + 0x100)
+#define BIST5_CFG_CTR		(MISC_BASE + 0x104)
+#define BIST1_STS_RES		(MISC_BASE + 0x108)
+#define BIST2_STS_RES		(MISC_BASE + 0x10C)
+#define BIST3_STS_RES		(MISC_BASE + 0x110)
+#define BIST4_STS_RES		(MISC_BASE + 0x114)
+#define BIST5_STS_RES		(MISC_BASE + 0x118)
+#define SYSERR_CFG_CTR		(MISC_BASE + 0x11C)
 
 #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
index a835f5b..7fd6215 100644
--- a/arch/arm/mach-spear6xx/include/mach/spear.h
+++ b/arch/arm/mach-spear6xx/include/mach/spear.h
@@ -14,153 +14,70 @@
 #ifndef __MACH_SPEAR6XX_H
 #define __MACH_SPEAR6XX_H
 
-#include <mach/hardware.h>
+#include <asm/memory.h>
 #include <mach/spear600.h>
 
-#define SPEAR6XX_ML_SDRAM_BASE		0x00000000
-#define SPEAR6XX_ML_SDRAM_SIZE		0x40000000
-
+#define SPEAR6XX_ML_SDRAM_BASE		UL(0x00000000)
 /* ICM1 - Low speed connection */
-#define SPEAR6XX_ICM1_BASE		0xD0000000
-#define SPEAR6XX_ICM1_SIZE		0x08000000
+#define SPEAR6XX_ICM1_BASE		UL(0xD0000000)
 
-#define SPEAR6XX_ICM1_UART0_BASE	0xD0000000
+#define SPEAR6XX_ICM1_UART0_BASE	UL(0xD0000000)
 #define VA_SPEAR6XX_ICM1_UART0_BASE	IO_ADDRESS(SPEAR6XX_ICM1_UART0_BASE)
-#define SPEAR6XX_ICM1_UART0_SIZE	0x00080000
-
-#define SPEAR6XX_ICM1_UART1_BASE	0xD0080000
-#define SPEAR6XX_ICM1_UART1_SIZE	0x00080000
-
-#define SPEAR6XX_ICM1_SSP0_BASE		0xD0100000
-#define SPEAR6XX_ICM1_SSP0_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_SSP1_BASE		0xD0180000
-#define SPEAR6XX_ICM1_SSP1_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_I2C_BASE		0xD0200000
-#define SPEAR6XX_ICM1_I2C_SIZE		0x00080000
 
-#define SPEAR6XX_ICM1_JPEG_BASE		0xD0800000
-#define SPEAR6XX_ICM1_JPEG_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_IRDA_BASE		0xD1000000
-#define SPEAR6XX_ICM1_IRDA_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_FSMC_BASE		0xD1800000
-#define SPEAR6XX_ICM1_FSMC_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_NAND_BASE		0xD2000000
-#define SPEAR6XX_ICM1_NAND_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_SRAM_BASE		0xD2800000
-#define SPEAR6XX_ICM1_SRAM_SIZE		0x00800000
+#define SPEAR6XX_ICM1_UART1_BASE	UL(0xD0080000)
+#define SPEAR6XX_ICM1_SSP0_BASE		UL(0xD0100000)
+#define SPEAR6XX_ICM1_SSP1_BASE		UL(0xD0180000)
+#define SPEAR6XX_ICM1_I2C_BASE		UL(0xD0200000)
+#define SPEAR6XX_ICM1_JPEG_BASE		UL(0xD0800000)
+#define SPEAR6XX_ICM1_IRDA_BASE		UL(0xD1000000)
+#define SPEAR6XX_ICM1_FSMC_BASE		UL(0xD1800000)
+#define SPEAR6XX_ICM1_NAND_BASE		UL(0xD2000000)
+#define SPEAR6XX_ICM1_SRAM_BASE		UL(0xD2800000)
 
 /* ICM2 - Application Subsystem */
-#define SPEAR6XX_ICM2_BASE		0xD8000000
-#define SPEAR6XX_ICM2_SIZE		0x08000000
-
-#define SPEAR6XX_ICM2_TMR0_BASE		0xD8000000
-#define SPEAR6XX_ICM2_TMR0_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_TMR1_BASE		0xD8080000
-#define SPEAR6XX_ICM2_TMR1_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_GPIO_BASE		0xD8100000
-#define SPEAR6XX_ICM2_GPIO_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_SPI2_BASE		0xD8180000
-#define SPEAR6XX_ICM2_SPI2_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_ADC_BASE		0xD8200000
-#define SPEAR6XX_ICM2_ADC_SIZE		0x00080000
+#define SPEAR6XX_ICM2_BASE		UL(0xD8000000)
+#define SPEAR6XX_ICM2_TMR0_BASE		UL(0xD8000000)
+#define SPEAR6XX_ICM2_TMR1_BASE		UL(0xD8080000)
+#define SPEAR6XX_ICM2_GPIO_BASE		UL(0xD8100000)
+#define SPEAR6XX_ICM2_SSP2_BASE		UL(0xD8180000)
+#define SPEAR6XX_ICM2_ADC_BASE		UL(0xD8200000)
 
 /* ML-1, 2 - Multi Layer CPU Subsystem */
-#define SPEAR6XX_ML_CPU_BASE		0xF0000000
-#define SPEAR6XX_ML_CPU_SIZE		0x08000000
-
-#define SPEAR6XX_CPU_TMR_BASE		0xF0000000
-#define SPEAR6XX_CPU_TMR_SIZE		0x00100000
-
-#define SPEAR6XX_CPU_GPIO_BASE		0xF0100000
-#define SPEAR6XX_CPU_GPIO_SIZE		0x00100000
-
-#define SPEAR6XX_CPU_VIC_SEC_BASE	0xF1000000
+#define SPEAR6XX_ML_CPU_BASE		UL(0xF0000000)
+#define SPEAR6XX_CPU_TMR_BASE		UL(0xF0000000)
+#define SPEAR6XX_CPU_GPIO_BASE		UL(0xF0100000)
+#define SPEAR6XX_CPU_VIC_SEC_BASE	UL(0xF1000000)
 #define VA_SPEAR6XX_CPU_VIC_SEC_BASE	IO_ADDRESS(SPEAR6XX_CPU_VIC_SEC_BASE)
-#define SPEAR6XX_CPU_VIC_SEC_SIZE	0x00100000
-
-#define SPEAR6XX_CPU_VIC_PRI_BASE	0xF1100000
+#define SPEAR6XX_CPU_VIC_PRI_BASE	UL(0xF1100000)
 #define VA_SPEAR6XX_CPU_VIC_PRI_BASE	IO_ADDRESS(SPEAR6XX_CPU_VIC_PRI_BASE)
-#define SPEAR6XX_CPU_VIC_PRI_SIZE	0x00100000
 
 /* ICM3 - Basic Subsystem */
-#define SPEAR6XX_ICM3_BASE		0xF8000000
-#define SPEAR6XX_ICM3_SIZE		0x08000000
-
-#define SPEAR6XX_ICM3_SMEM_BASE		0xF8000000
-#define SPEAR6XX_ICM3_SMEM_SIZE		0x04000000
-
-#define SPEAR6XX_ICM3_SMI_CTRL_BASE	0xFC000000
-#define SPEAR6XX_ICM3_SMI_CTRL_SIZE	0x00200000
-
-#define SPEAR6XX_ICM3_CLCD_BASE		0xFC200000
-#define SPEAR6XX_ICM3_CLCD_SIZE		0x00200000
-
-#define SPEAR6XX_ICM3_DMA_BASE		0xFC400000
-#define SPEAR6XX_ICM3_DMA_SIZE		0x00200000
-
-#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE	0xFC600000
-#define SPEAR6XX_ICM3_SDRAM_CTRL_SIZE	0x00200000
-
-#define SPEAR6XX_ICM3_TMR_BASE		0xFC800000
-#define SPEAR6XX_ICM3_TMR_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_WDT_BASE		0xFC880000
-#define SPEAR6XX_ICM3_WDT_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_RTC_BASE		0xFC900000
-#define SPEAR6XX_ICM3_RTC_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_GPIO_BASE		0xFC980000
-#define SPEAR6XX_ICM3_GPIO_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_SYS_CTRL_BASE	0xFCA00000
+#define SPEAR6XX_ICM3_BASE		UL(0xF8000000)
+#define SPEAR6XX_ICM3_SMEM_BASE		UL(0xF8000000)
+#define SPEAR6XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define SPEAR6XX_ICM3_CLCD_BASE		UL(0xFC200000)
+#define SPEAR6XX_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE	UL(0xFC600000)
+#define SPEAR6XX_ICM3_TMR_BASE		UL(0xFC800000)
+#define SPEAR6XX_ICM3_WDT_BASE		UL(0xFC880000)
+#define SPEAR6XX_ICM3_RTC_BASE		UL(0xFC900000)
+#define SPEAR6XX_ICM3_GPIO_BASE		UL(0xFC980000)
+#define SPEAR6XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
 #define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE	IO_ADDRESS(SPEAR6XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR6XX_ICM3_SYS_CTRL_SIZE	0x00080000
-
-#define SPEAR6XX_ICM3_MISC_REG_BASE	0xFCA80000
+#define SPEAR6XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
 #define VA_SPEAR6XX_ICM3_MISC_REG_BASE	IO_ADDRESS(SPEAR6XX_ICM3_MISC_REG_BASE)
-#define SPEAR6XX_ICM3_MISC_REG_SIZE	0x00080000
 
 /* ICM4 - High Speed Connection */
-#define SPEAR6XX_ICM4_BASE		0xE0000000
-#define SPEAR6XX_ICM4_SIZE		0x08000000
-
-#define SPEAR6XX_ICM4_GMAC_BASE		0xE0800000
-#define SPEAR6XX_ICM4_GMAC_SIZE		0x00800000
-
-#define SPEAR6XX_ICM4_USBD_FIFO_BASE	0xE1000000
-#define SPEAR6XX_ICM4_USBD_FIFO_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USBD_CSR_BASE	0xE1100000
-#define SPEAR6XX_ICM4_USBD_CSR_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USBD_PLDT_BASE	0xE1200000
-#define SPEAR6XX_ICM4_USBD_PLDT_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_EHCI0_BASE	0xE1800000
-#define SPEAR6XX_ICM4_USB_EHCI0_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_OHCI0_BASE	0xE1900000
-#define SPEAR6XX_ICM4_USB_OHCI0_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_EHCI1_BASE	0xE2000000
-#define SPEAR6XX_ICM4_USB_EHCI1_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_OHCI1_BASE	0xE2100000
-#define SPEAR6XX_ICM4_USB_OHCI1_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_ARB_BASE	0xE2800000
-#define SPEAR6XX_ICM4_USB_ARB_SIZE	0x00010000
+#define SPEAR6XX_ICM4_BASE		UL(0xE0000000)
+#define SPEAR6XX_ICM4_GMAC_BASE		UL(0xE0800000)
+#define SPEAR6XX_ICM4_USBD_FIFO_BASE	UL(0xE1000000)
+#define SPEAR6XX_ICM4_USBD_CSR_BASE	UL(0xE1100000)
+#define SPEAR6XX_ICM4_USBD_PLDT_BASE	UL(0xE1200000)
+#define SPEAR6XX_ICM4_USB_EHCI0_BASE	UL(0xE1800000)
+#define SPEAR6XX_ICM4_USB_OHCI0_BASE	UL(0xE1900000)
+#define SPEAR6XX_ICM4_USB_EHCI1_BASE	UL(0xE2000000)
+#define SPEAR6XX_ICM4_USB_OHCI1_BASE	UL(0xE2100000)
+#define SPEAR6XX_ICM4_USB_ARB_BASE	UL(0xE2800000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR6XX_ICM1_UART0_BASE
diff --git a/arch/arm/mach-spear6xx/spear600.c b/arch/arm/mach-spear6xx/spear600.c
index 5c484c4..d0e6eea 100644
--- a/arch/arm/mach-spear6xx/spear600.c
+++ b/arch/arm/mach-spear6xx/spear600.c
@@ -14,7 +14,7 @@
 #include <linux/ptrace.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* Add spear600 specific devices here */
 
diff --git a/arch/arm/mach-spear6xx/spear600_evb.c b/arch/arm/mach-spear6xx/spear600_evb.c
index daff8d0..f19cefe 100644
--- a/arch/arm/mach-spear6xx/spear600_evb.c
+++ b/arch/arm/mach-spear6xx/spear600_evb.c
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 static struct amba_device *amba_devs[] __initdata = {
 	&gpio_device[0],
@@ -46,6 +46,6 @@ MACHINE_START(SPEAR600, "ST-SPEAR600-EVB")
 	.boot_params	=	0x00000100,
 	.map_io		=	spear6xx_map_io,
 	.init_irq	=	spear6xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear6xx_timer,
 	.init_machine	=	spear600_evb_init,
 MACHINE_END
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index f2fe14e..9818129 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -18,9 +18,9 @@
 #include <asm/hardware/vic.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
-#include <mach/irqs.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
 
 /* Add spear6xx machines common devices here */
 /* uart device registration */
@@ -31,8 +31,7 @@ struct amba_device uart_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_ICM1_UART0_BASE,
-			.end = SPEAR6XX_ICM1_UART0_BASE +
-				SPEAR6XX_ICM1_UART0_SIZE - 1,
+			.end = SPEAR6XX_ICM1_UART0_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_UART_0, NO_IRQ},
@@ -42,8 +41,7 @@ struct amba_device uart_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_ICM1_UART1_BASE,
-			.end = SPEAR6XX_ICM1_UART1_BASE +
-				SPEAR6XX_ICM1_UART1_SIZE - 1,
+			.end = SPEAR6XX_ICM1_UART1_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_UART_1, NO_IRQ},
@@ -72,8 +70,7 @@ struct amba_device gpio_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_CPU_GPIO_BASE,
-			.end = SPEAR6XX_CPU_GPIO_BASE +
-				SPEAR6XX_CPU_GPIO_SIZE - 1,
+			.end = SPEAR6XX_CPU_GPIO_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_LOCAL_GPIO, NO_IRQ},
@@ -84,8 +81,7 @@ struct amba_device gpio_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_ICM3_GPIO_BASE,
-			.end = SPEAR6XX_ICM3_GPIO_BASE +
-				SPEAR6XX_ICM3_GPIO_SIZE - 1,
+			.end = SPEAR6XX_ICM3_GPIO_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_BASIC_GPIO, NO_IRQ},
@@ -96,8 +92,7 @@ struct amba_device gpio_device[] = {
 		},
 		.res = {
 			.start = SPEAR6XX_ICM2_GPIO_BASE,
-			.end = SPEAR6XX_ICM2_GPIO_BASE +
-				SPEAR6XX_ICM2_GPIO_SIZE - 1,
+			.end = SPEAR6XX_ICM2_GPIO_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_APPL_GPIO, NO_IRQ},
@@ -122,27 +117,27 @@ static struct map_desc spear6xx_io_desc[] __initdata = {
 	{
 		.virtual	= VA_SPEAR6XX_ICM1_UART0_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM1_UART0_BASE),
-		.length		= SPEAR6XX_ICM1_UART0_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_CPU_VIC_PRI_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_CPU_VIC_PRI_BASE),
-		.length		= SPEAR6XX_CPU_VIC_PRI_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_CPU_VIC_SEC_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_CPU_VIC_SEC_BASE),
-		.length		= SPEAR6XX_CPU_VIC_SEC_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_ICM3_SYS_CTRL_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_SYS_CTRL_BASE),
-		.length		= SPEAR6XX_ICM3_MISC_REG_BASE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_ICM3_MISC_REG_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE),
-		.length		= SPEAR6XX_ICM3_MISC_REG_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	},
 };
@@ -155,3 +150,34 @@ void __init spear6xx_map_io(void)
 	/* This will initialize clock framework */
 	clk_init();
 }
+
+static void __init spear6xx_timer_init(void)
+{
+	char pclk_name[] = "pll3_48m_clk";
+	struct clk *gpt_clk, *pclk;
+
+	/* 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_timer();
+}
+
+struct sys_timer spear6xx_timer = {
+	.init = spear6xx_timer_init,
+};
diff --git a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
index 7991415..4cb3c2d 100644
--- a/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
+++ b/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -17,6 +18,8 @@
 #include <asm/mach/time.h>
 
 #include <mach/clock.h>
+#include <mach/tcc-nand.h>
+#include <mach/tcc8k-regs.h>
 
 #include "common.h"
 
@@ -51,10 +54,26 @@ static struct sys_timer tcc8k_timer = {
 static void __init tcc8k_map_io(void)
 {
 	tcc8k_map_common_io();
+
+	/* set PLL0 clock to 96MHz, adapt UART0 divisor */
+	__raw_writel(0x00026003, CKC_BASE + PLL0CFG_OFFS);
+	__raw_writel(0x10000001, CKC_BASE + ACLKUART0_OFFS);
+
+	/* set PLL1 clock to 192MHz */
+	__raw_writel(0x00016003, CKC_BASE + PLL1CFG_OFFS);
+
+	/* set PLL2 clock to 48MHz */
+	__raw_writel(0x00036003, CKC_BASE + PLL2CFG_OFFS);
+
+	/* with CPU freq higher than 150 MHz, need extra DTCM wait */
+	__raw_writel(0x00000001, SCFG_BASE + DTCMWAIT_OFFS);
+
+	/* PLL locking time as specified */
+	udelay(300);
 }
 
 MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.map_io		= tcc8k_map_io,
 	.init_irq	= tcc8k_init_irq,
 	.init_machine	= tcc8k_init,
diff --git a/arch/arm/mach-tcc8k/clock.c b/arch/arm/mach-tcc8k/clock.c
index 3970a9c..e7cdae5 100644
--- a/arch/arm/mach-tcc8k/clock.c
+++ b/arch/arm/mach-tcc8k/clock.c
@@ -45,11 +45,12 @@
 #define ACLKGSB1	(CKC_BASE + ACLKGSB1_OFFS)
 #define ACLKGSB2	(CKC_BASE + ACLKGSB2_OFFS)
 #define ACLKGSB3	(CKC_BASE + ACLKGSB3_OFFS)
-#define ACLKUSBH	(CKC_BASE + ACLKUSBH_OFFS)
 #define ACLKTCT		(CKC_BASE + ACLKTCT_OFFS)
 #define ACLKTCX		(CKC_BASE + ACLKTCX_OFFS)
 #define ACLKTCZ		(CKC_BASE + ACLKTCZ_OFFS)
 
+#define ACLK_MAX_DIV	(0xfff + 1)
+
 /* Crystal frequencies */
 static unsigned long xi_rate, xti_rate;
 
@@ -106,9 +107,9 @@ static int root_clk_enable(enum root_clks src)
 	return 0;
 }
 
-static int root_clk_disable(enum root_clks root_src)
+static int root_clk_disable(enum root_clks src)
 {
-	switch (root_src) {
+	switch (src) {
 	case CLK_SRC_PLL0: return pll_enable(0, 0);
 	case CLK_SRC_PLL1: return pll_enable(1, 0);
 	case CLK_SRC_PLL2: return pll_enable(2, 0);
@@ -197,7 +198,7 @@ static unsigned long get_rate_pll_div(int pll)
 		addr = CKC_BASE + CLKDIVC1_OFFS;
 		reg = __raw_readl(addr);
 		if (reg & CLKDIVC1_P2E)
-			div = __raw_readl(addr) & 0x3f;
+			div = reg & 0x3f;
 		break;
 	}
 	return get_rate_pll(pll) / (div + 1);
@@ -258,14 +259,19 @@ static unsigned long aclk_best_div(struct clk *clk, unsigned long rate)
 {
 	unsigned long div, src, freq, r1, r2;
 
+	if (!rate)
+		return ACLK_MAX_DIV;
+
 	src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
 	src &= CLK_SRC_MASK;
 	freq = root_clk_get_rate(src);
-	div = freq / rate + 1;
+	div = freq / rate;
+	if (!div)
+		return 1;
+	if (div >= ACLK_MAX_DIV)
+		return ACLK_MAX_DIV;
 	r1 = freq / div;
 	r2 = freq / (div + 1);
-	if (r2 >= rate)
-		return div + 1;
 	if ((rate - r2) < (r1 - rate))
 		return div + 1;
 
@@ -287,7 +293,8 @@ static int aclk_set_rate(struct clk *clk, unsigned long rate)
 	u32 reg;
 
 	reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK;
-	reg |= aclk_best_div(clk, rate);
+	reg |= aclk_best_div(clk, rate) - 1;
+	__raw_writel(reg, clk->aclkreg);
 	return 0;
 }
 
@@ -296,15 +303,22 @@ static unsigned long get_rate_sys(struct clk *clk)
 	unsigned int src;
 
 	src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK;
-		return root_clk_get_rate(src);
+	return root_clk_get_rate(src);
 }
 
 static unsigned long get_rate_bus(struct clk *clk)
 {
-	unsigned int div;
+	unsigned int reg, sdiv, bdiv, rate;
 
-	div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff;
-	return get_rate_sys(clk) / (div + 1);
+	reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+	rate = get_rate_sys(clk);
+	sdiv = (reg >> 20) & 3;
+	if (sdiv)
+		rate /= sdiv + 1;
+	bdiv = (reg >> 4) & 0xff;
+	if (bdiv)
+		rate /= bdiv + 1;
+	return rate;
 }
 
 static unsigned long get_rate_cpu(struct clk *clk)
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index acd9552..622a9ec 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -10,6 +10,9 @@ config ARCH_TEGRA_2x_SOC
 	select CPU_V7
 	select ARM_GIC
 	select ARCH_REQUIRE_GPIOLIB
+	select USB_ARCH_HAS_EHCI if USB_SUPPORT
+	select USB_ULPI if USB_SUPPORT
+	select USB_ULPI_VIEWPORT if USB_SUPPORT
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -27,6 +30,31 @@ config MACH_HARMONY
        help
          Support for nVidia Harmony development platform
 
+config MACH_KAEN
+       bool "Kaen board"
+       select MACH_SEABOARD
+       help
+         Support for the Kaen version of Seaboard
+
+config MACH_SEABOARD
+       bool "Seaboard board"
+       help
+         Support for nVidia Seaboard development platform. It will
+	 also be included for some of the derivative boards that
+	 have large similarities with the seaboard design.
+
+config MACH_TRIMSLICE
+       bool "TrimSlice board"
+       select TEGRA_PCI
+       help
+         Support for CompuLab TrimSlice platform
+
+config MACH_WARIO
+       bool "Wario board"
+       select MACH_SEABOARD
+       help
+         Support for the Wario version of Seaboard
+
 choice
         prompt "Low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
@@ -58,4 +86,7 @@ config TEGRA_SYSTEM_DMA
 	  Adds system DMA functionality for NVIDIA Tegra SoCs, used by
 	  several Tegra device drivers
 
+config TEGRA_EMC_SCALING_ENABLE
+	bool "Enable scaling the memory frequency"
+
 endif
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index cdbc68e..9f7a7e1 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,21 +1,30 @@
 obj-y                                   += common.o
+obj-y                                   += devices.o
 obj-y                                   += io.o
 obj-y                                   += irq.o legacy_irq.o
 obj-y                                   += clock.o
 obj-y                                   += timer.o
 obj-y                                   += gpio.o
 obj-y                                   += pinmux.o
+obj-y                                   += powergate.o
 obj-y					+= fuse.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_dvfs.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pinmux-t2-tables.o
 obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 obj-$(CONFIG_TEGRA_SYSTEM_DMA)		+= dma.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
+obj-$(CONFIG_USB_SUPPORT)		+= usb_phy.o
 
 obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pcie.o
+
+obj-${CONFIG_MACH_SEABOARD}             += board-seaboard.o
+obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
+
+obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
+obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 50b15d5..98368d9 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -15,8 +15,10 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/gpio.h>
 #include <mach/pinmux.h>
 
+#include "gpio-names.h"
 #include "board-harmony.h"
 
 static struct tegra_pingroup_config harmony_pinmux[] = {
@@ -34,10 +36,10 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
 	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
-	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -138,7 +140,18 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct tegra_gpio_table gpio_table[] = {
+	{ .gpio = TEGRA_GPIO_PI5,	.enable = true	}, /* mmc2 cd	*/
+	{ .gpio = TEGRA_GPIO_PH1,	.enable = true	}, /* mmc2 wp	*/
+	{ .gpio = TEGRA_GPIO_PT3,	.enable = true	}, /* mmc2 pwr	*/
+	{ .gpio = TEGRA_GPIO_PH2,	.enable = true	}, /* mmc4 cd	*/
+	{ .gpio = TEGRA_GPIO_PH3,	.enable = true	}, /* mmc4 wp	*/
+	{ .gpio = TEGRA_GPIO_PI6,	.enable = true	}, /* mmc4 pwr	*/
+};
+
 void harmony_pinmux_init(void)
 {
 	tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
+
+	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c
index b9dbdb1..49224e9 100644
--- a/arch/arm/mach-tegra/board-harmony.c
+++ b/arch/arm/mach-tegra/board-harmony.c
@@ -30,35 +30,13 @@
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/sdhci.h>
 
 #include "board.h"
 #include "board-harmony.h"
 #include "clock.h"
-
-/* NVidia bootloader tags */
-#define ATAG_NVIDIA		0x41000801
-
-#define ATAG_NVIDIA_RM			0x1
-#define ATAG_NVIDIA_DISPLAY		0x2
-#define ATAG_NVIDIA_FRAMEBUFFER		0x3
-#define ATAG_NVIDIA_CHIPSHMOO		0x4
-#define ATAG_NVIDIA_CHIPSHMOOPHYS	0x5
-#define ATAG_NVIDIA_PRESERVED_MEM_0	0x10000
-#define ATAG_NVIDIA_PRESERVED_MEM_N	2
-#define ATAG_NVIDIA_FORCE_32		0x7fffffff
-
-struct tag_tegra {
-	__u32 bootarg_key;
-	__u32 bootarg_len;
-	char bootarg[1];
-};
-
-static int __init parse_tag_nvidia(const struct tag *tag)
-{
-
-	return 0;
-}
-__tagtable(ATAG_NVIDIA, parse_tag_nvidia);
+#include "devices.h"
+#include "gpio-names.h"
 
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
@@ -84,6 +62,9 @@ static struct platform_device debug_uart = {
 
 static struct platform_device *harmony_devices[] __initdata = {
 	&debug_uart,
+	&tegra_sdhci_device1,
+	&tegra_sdhci_device2,
+	&tegra_sdhci_device4,
 };
 
 static void __init tegra_harmony_fixup(struct machine_desc *desc,
@@ -102,22 +83,45 @@ static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
 	{ NULL,		NULL,		0,		0},
 };
 
+
+static struct tegra_sdhci_platform_data sdhci_pdata1 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata2 = {
+	.cd_gpio	= TEGRA_GPIO_PI5,
+	.wp_gpio	= TEGRA_GPIO_PH1,
+	.power_gpio	= TEGRA_GPIO_PT3,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
+	.cd_gpio	= TEGRA_GPIO_PH2,
+	.wp_gpio	= TEGRA_GPIO_PH3,
+	.power_gpio	= TEGRA_GPIO_PI6,
+	.is_8bit	= 1,
+};
+
 static void __init tegra_harmony_init(void)
 {
-	tegra_common_init();
-
 	tegra_clk_init_from_table(harmony_clk_init_table);
 
 	harmony_pinmux_init();
 
+	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
+	tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
+	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
+
 	platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
 }
 
 MACHINE_START(HARMONY, "harmony")
 	.boot_params  = 0x00000100,
 	.fixup		= tegra_harmony_fixup,
-	.init_irq       = tegra_init_irq,
-	.init_machine   = tegra_harmony_init,
 	.map_io         = tegra_map_common_io,
+	.init_early	= tegra_init_early,
+	.init_irq       = tegra_init_irq,
 	.timer          = &tegra_timer,
+	.init_machine   = tegra_harmony_init,
 MACHINE_END
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
new file mode 100644
index 0000000..2d6ad83
--- /dev/null
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2010 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/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <mach/pinmux.h>
+#include <mach/pinmux-t2.h>
+
+#include "gpio-names.h"
+#include "board-seaboard.h"
+
+#define DEFAULT_DRIVE(_name)					\
+	{							\
+		.pingroup = TEGRA_DRIVE_PINGROUP_##_name,	\
+		.hsm = TEGRA_HSM_DISABLE,			\
+		.schmitt = TEGRA_SCHMITT_ENABLE,		\
+		.drive = TEGRA_DRIVE_DIV_1,			\
+		.pull_down = TEGRA_PULL_31,			\
+		.pull_up = TEGRA_PULL_31,			\
+		.slew_rising = TEGRA_SLEW_SLOWEST,		\
+		.slew_falling = TEGRA_SLEW_SLOWEST,		\
+	}
+
+static __initdata struct tegra_drive_pingroup_config seaboard_drive_pinmux[] = {
+	DEFAULT_DRIVE(SDIO1),
+};
+
+static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
+	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMB,   TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GMC,   TEGRA_MUX_UARTD,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,   TEGRA_MUX_SFLASH,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GME,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCB,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCD,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LCSN,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDC,   TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM0,   TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM1,   TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW0,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW1,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW2,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSCK,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDI,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVP0,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_OWC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PTA,   TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDB,   TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDC,   TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDD,   TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+};
+
+
+
+
+static struct tegra_gpio_table gpio_table[] = {
+	{ .gpio = TEGRA_GPIO_PI5,	.enable = true	}, /* mmc2 cd	 */
+	{ .gpio = TEGRA_GPIO_PH1,	.enable = true	}, /* mmc2 wp	 */
+	{ .gpio = TEGRA_GPIO_PI6,	.enable = true	}, /* mmc2 pwr	 */
+	{ .gpio = TEGRA_GPIO_LIDSWITCH,	.enable = true	}, /* lid switch */
+	{ .gpio = TEGRA_GPIO_POWERKEY,	.enable = true	}, /* power key	 */
+};
+
+void __init seaboard_pinmux_init(void)
+{
+	tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
+
+	tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
+					ARRAY_SIZE(seaboard_drive_pinmux));
+
+	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+}
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
new file mode 100644
index 0000000..6ca9e61
--- /dev/null
+++ b/arch/arm/mach-tegra/board-seaboard.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2010, 2011 NVIDIA Corporation.
+ * Copyright (C) 2010, 2011 Google, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/gpio_keys.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/sdhci.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "board.h"
+#include "board-seaboard.h"
+#include "clock.h"
+#include "devices.h"
+#include "gpio-names.h"
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+	{
+		/* Memory and IRQ filled in before registration */
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		.flags		= 0,
+	}
+};
+
+static struct platform_device debug_uart = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = debug_uart_platform_data,
+	},
+};
+
+static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uartb",	"pll_p",	216000000,	true},
+	{ "uartd",	"pll_p",	216000000,	true},
+	{ NULL,		NULL,		0,		0},
+};
+
+static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
+	{
+		.code		= SW_LID,
+		.gpio		= TEGRA_GPIO_LIDSWITCH,
+		.active_low	= 0,
+		.desc		= "Lid",
+		.type		= EV_SW,
+		.wakeup		= 1,
+		.debounce_interval = 1,
+	},
+	{
+		.code		= KEY_POWER,
+		.gpio		= TEGRA_GPIO_POWERKEY,
+		.active_low	= 1,
+		.desc		= "Power",
+		.type		= EV_KEY,
+		.wakeup		= 1,
+	},
+};
+
+static struct gpio_keys_platform_data seaboard_gpio_keys = {
+	.buttons	= seaboard_gpio_keys_buttons,
+	.nbuttons	= ARRAY_SIZE(seaboard_gpio_keys_buttons),
+};
+
+static struct platform_device seaboard_gpio_keys_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &seaboard_gpio_keys,
+	}
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata1 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata3 = {
+	.cd_gpio	= TEGRA_GPIO_PI5,
+	.wp_gpio	= TEGRA_GPIO_PH1,
+	.power_gpio	= TEGRA_GPIO_PI6,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+	.is_8bit	= 1,
+};
+
+static struct platform_device *seaboard_devices[] __initdata = {
+	&debug_uart,
+	&tegra_pmu_device,
+	&tegra_sdhci_device1,
+	&tegra_sdhci_device3,
+	&tegra_sdhci_device4,
+	&seaboard_gpio_keys_device,
+};
+
+static void __init __tegra_seaboard_init(void)
+{
+	seaboard_pinmux_init();
+
+	tegra_clk_init_from_table(seaboard_clk_init_table);
+
+	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
+	tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3;
+	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
+
+	platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
+}
+
+static void __init tegra_seaboard_init(void)
+{
+	/* Seaboard uses UARTD for the debug port. */
+	debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE);
+	debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE;
+	debug_uart_platform_data[0].irq = INT_UARTD;
+
+	__tegra_seaboard_init();
+}
+
+static void __init tegra_kaen_init(void)
+{
+	/* Kaen uses UARTB for the debug port. */
+	debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
+	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
+	debug_uart_platform_data[0].irq = INT_UARTB;
+
+	__tegra_seaboard_init();
+}
+
+static void __init tegra_wario_init(void)
+{
+	/* Wario uses UARTB for the debug port. */
+	debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
+	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
+	debug_uart_platform_data[0].irq = INT_UARTB;
+
+	__tegra_seaboard_init();
+}
+
+
+MACHINE_START(SEABOARD, "seaboard")
+	.boot_params    = 0x00000100,
+	.map_io         = tegra_map_common_io,
+	.init_early     = tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_seaboard_init,
+MACHINE_END
+
+MACHINE_START(KAEN, "kaen")
+	.boot_params    = 0x00000100,
+	.map_io         = tegra_map_common_io,
+	.init_early     = tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_kaen_init,
+MACHINE_END
+
+MACHINE_START(WARIO, "wario")
+	.boot_params    = 0x00000100,
+	.map_io         = tegra_map_common_io,
+	.init_early     = tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_wario_init,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h
new file mode 100644
index 0000000..a098e35
--- /dev/null
+++ b/arch/arm/mach-tegra/board-seaboard.h
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-tegra/board-seaboard.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_SEABOARD_H
+#define _MACH_TEGRA_BOARD_SEABOARD_H
+
+#define TEGRA_GPIO_LIDSWITCH		TEGRA_GPIO_PC7
+#define TEGRA_GPIO_USB1			TEGRA_GPIO_PD0
+#define TEGRA_GPIO_POWERKEY		TEGRA_GPIO_PV2
+#define TEGRA_GPIO_BACKLIGHT		TEGRA_GPIO_PD4
+#define TEGRA_GPIO_LVDS_SHUTDOWN	TEGRA_GPIO_PB2
+#define TEGRA_GPIO_BACKLIGHT_PWM	TEGRA_GPIO_PU5
+#define TEGRA_GPIO_BACKLIGHT_VDD	TEGRA_GPIO_PW0
+#define TEGRA_GPIO_EN_VDD_PNL		TEGRA_GPIO_PC6
+#define TEGRA_GPIO_MAGNETOMETER		TEGRA_GPIO_PN5
+#define TEGRA_GPIO_ISL29018_IRQ		TEGRA_GPIO_PZ2
+#define TEGRA_GPIO_AC_ONLINE		TEGRA_GPIO_PV3
+
+#define TPS_GPIO_BASE			TEGRA_NR_GPIOS
+
+#define TPS_GPIO_WWAN_PWR		(TPS_GPIO_BASE + 2)
+
+void seaboard_pinmux_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
new file mode 100644
index 0000000..6d4fc9f
--- /dev/null
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -0,0 +1,145 @@
+/*
+ * arch/arm/mach-tegra/board-trimslice-pinmux.c
+ *
+ * Copyright (C) 2011 CompuLab, 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/kernel.h>
+#include <linux/init.h>
+#include <mach/pinmux.h>
+
+#include "board-trimslice.h"
+
+static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
+	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,	TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMB,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GMC,   TEGRA_MUX_SFLASH,        TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,   TEGRA_MUX_SFLASH,        TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GME,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GPU,   TEGRA_MUX_UARTA,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCB,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCD,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LCSN,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDC,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSCK,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_OWC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PTA,   TEGRA_MUX_RSVD3,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDB,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDC,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDD,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_SPI2,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_SPI2,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_SPI2,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+};
+
+void __init trimslice_pinmux_init(void)
+{
+	tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
+}
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c
new file mode 100644
index 0000000..7be7d4a
--- /dev/null
+++ b/arch/arm/mach-tegra/board-trimslice.c
@@ -0,0 +1,106 @@
+/*
+ * arch/arm/mach-tegra/board-trimslice.c
+ *
+ * Copyright (C) 2011 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on board-harmony.c
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+
+#include "board.h"
+#include "clock.h"
+
+#include "board-trimslice.h"
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+	{
+		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
+		.mapbase	= TEGRA_UARTA_BASE,
+		.irq		= INT_UARTA,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		.flags		= 0
+	}
+};
+
+static struct platform_device debug_uart = {
+	.name	= "serial8250",
+	.id	= PLAT8250_DEV_PLATFORM,
+	.dev	= {
+		.platform_data	= debug_uart_platform_data,
+	},
+};
+
+static struct platform_device *trimslice_devices[] __initdata = {
+	&debug_uart,
+};
+
+static void __init tegra_trimslice_fixup(struct machine_desc *desc,
+	struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks = 2;
+	mi->bank[0].start = PHYS_OFFSET;
+	mi->bank[0].size = 448 * SZ_1M;
+	mi->bank[1].start = SZ_512M;
+	mi->bank[1].size = SZ_512M;
+}
+
+static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uarta",	"pll_p",	216000000,	true },
+	{ NULL,		NULL,		0,		0},
+};
+
+static int __init tegra_trimslice_pci_init(void)
+{
+	if (!machine_is_trimslice())
+		return 0;
+
+	return tegra_pcie_init(true, true);
+}
+subsys_initcall(tegra_trimslice_pci_init);
+
+static void __init tegra_trimslice_init(void)
+{
+	tegra_clk_init_from_table(trimslice_clk_init_table);
+
+	trimslice_pinmux_init();
+
+	platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
+}
+
+MACHINE_START(TRIMSLICE, "trimslice")
+	.boot_params	= 0x00000100,
+	.fixup		= tegra_trimslice_fixup,
+	.map_io         = tegra_map_common_io,
+	.init_early	= tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_trimslice_init,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h
new file mode 100644
index 0000000..16ec0f0
--- /dev/null
+++ b/arch/arm/mach-tegra/board-trimslice.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-tegra/board-trimslice.h
+ *
+ * Copyright (C) 2011 CompuLab, 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.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
+#define _MACH_TEGRA_BOARD_TRIMSLICE_H
+
+void trimslice_pinmux_init(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 0de565c..1d14df7 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -23,7 +23,9 @@
 
 #include <linux/types.h>
 
-void __init tegra_common_init(void);
+void tegra_assert_system_reset(char mode, const char *cmd);
+
+void __init tegra_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_init_clock(void);
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 77948e0..e028320 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -18,238 +18,177 @@
 
 #include <linux/kernel.h>
 #include <linux/clk.h>
-#include <linux/list.h>
+#include <linux/clkdev.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
-#include <linux/regulator/consumer.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+
+#include <mach/clk.h>
 
-#include "clock.h"
 #include "board.h"
-#include "fuse.h"
+#include "clock.h"
 
+/*
+ * Locking:
+ *
+ * Each struct clk has a spinlock.
+ *
+ * To avoid AB-BA locking problems, locks must always be traversed from child
+ * clock to parent clock.  For example, when enabling a clock, the clock's lock
+ * is taken, and then clk_enable is called on the parent, which take's the
+ * parent clock's lock.  There is one exceptions to this ordering: When dumping
+ * the clock tree through debugfs.  In this case, clk_lock_all is called,
+ * which attemps to iterate through the entire list of clocks and take every
+ * clock lock.  If any call to spin_trylock fails, all locked clocks are
+ * unlocked, and the process is retried.  When all the locks are held,
+ * the only clock operation that can be called is clk_get_rate_all_locked.
+ *
+ * Within a single clock, no clock operation can call another clock operation
+ * on itself, except for clk_get_rate_locked and clk_set_rate_locked.  Any
+ * clock operation can call any other clock operation on any of it's possible
+ * parents.
+ *
+ * An additional mutex, clock_list_lock, is used to protect the list of all
+ * clocks.
+ *
+ * The clock operations must lock internally to protect against
+ * read-modify-write on registers that are shared by multiple clocks
+ */
+static DEFINE_MUTEX(clock_list_lock);
 static LIST_HEAD(clocks);
 
-static DEFINE_SPINLOCK(clock_lock);
-static DEFINE_MUTEX(dvfs_lock);
-
-static int clk_is_dvfs(struct clk *c)
-{
-	return (c->dvfs != NULL);
-};
-
-static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
-{
-	struct dvfs_table *t;
-
-	if (d->table == NULL)
-		return -ENODEV;
-
-	for (t = d->table; t->rate != 0; t++) {
-		if (rate <= t->rate) {
-			if (!d->reg)
-				return 0;
-
-			return regulator_set_voltage(d->reg,
-				t->millivolts * 1000,
-				d->max_millivolts * 1000);
-		}
-	}
-
-	return -EINVAL;
-}
-
-static void dvfs_init(struct clk *c)
-{
-	int process_id;
-	int i;
-	struct dvfs_table *table;
-
-	process_id = c->dvfs->cpu ? tegra_core_process_id() :
-		tegra_cpu_process_id();
-
-	for (i = 0; i < c->dvfs->process_id_table_length; i++)
-		if (process_id == c->dvfs->process_id_table[i].process_id)
-			c->dvfs->table = c->dvfs->process_id_table[i].table;
-
-	if (c->dvfs->table == NULL) {
-		pr_err("Failed to find dvfs table for clock %s process %d\n",
-			c->name, process_id);
-		return;
-	}
-
-	c->dvfs->max_millivolts = 0;
-	for (table = c->dvfs->table; table->rate != 0; table++)
-		if (c->dvfs->max_millivolts < table->millivolts)
-			c->dvfs->max_millivolts = table->millivolts;
-
-	c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
-
-	if (IS_ERR(c->dvfs->reg)) {
-		pr_err("Failed to get regulator %s for clock %s\n",
-			c->dvfs->reg_id, c->name);
-		c->dvfs->reg = NULL;
-		return;
-	}
-
-	if (c->refcnt > 0)
-		dvfs_set_rate(c->dvfs, c->rate);
-}
-
 struct clk *tegra_get_clock_by_name(const char *name)
 {
 	struct clk *c;
 	struct clk *ret = NULL;
-	unsigned long flags;
-	spin_lock_irqsave(&clock_lock, flags);
+	mutex_lock(&clock_list_lock);
 	list_for_each_entry(c, &clocks, node) {
 		if (strcmp(c->name, name) == 0) {
 			ret = c;
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&clock_lock, flags);
+	mutex_unlock(&clock_list_lock);
 	return ret;
 }
 
-static void clk_recalculate_rate(struct clk *c)
+/* Must be called with c->spinlock held */
+static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p)
 {
 	u64 rate;
 
-	if (!c->parent)
-		return;
-
-	rate = c->parent->rate;
+	rate = clk_get_rate(p);
 
 	if (c->mul != 0 && c->div != 0) {
-		rate = rate * c->mul;
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
 		do_div(rate, c->div);
 	}
 
-	if (rate > c->max_rate)
-		pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
-			c->name, rate, c->max_rate);
-
-	c->rate = rate;
+	return rate;
 }
 
-int clk_reparent(struct clk *c, struct clk *parent)
+/* Must be called with c->spinlock held */
+unsigned long clk_get_rate_locked(struct clk *c)
 {
-	pr_debug("%s: %s\n", __func__, c->name);
-	c->parent = parent;
-	list_del(&c->sibling);
-	list_add_tail(&c->sibling, &parent->children);
-	return 0;
-}
+	unsigned long rate;
 
-static void propagate_rate(struct clk *c)
-{
-	struct clk *clkp;
-	pr_debug("%s: %s\n", __func__, c->name);
-	list_for_each_entry(clkp, &c->children, sibling) {
-		pr_debug("   %s\n", clkp->name);
-		clk_recalculate_rate(clkp);
-		propagate_rate(clkp);
-	}
+	if (c->parent)
+		rate = clk_predict_rate_from_parent(c, c->parent);
+	else
+		rate = c->rate;
+
+	return rate;
 }
 
-void clk_init(struct clk *c)
+unsigned long clk_get_rate(struct clk *c)
 {
 	unsigned long flags;
+	unsigned long rate;
+
+	spin_lock_irqsave(&c->spinlock, flags);
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	rate = clk_get_rate_locked(c);
 
-	spin_lock_irqsave(&clock_lock, flags);
+	spin_unlock_irqrestore(&c->spinlock, flags);
 
-	INIT_LIST_HEAD(&c->children);
-	INIT_LIST_HEAD(&c->sibling);
+	return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_reparent(struct clk *c, struct clk *parent)
+{
+	c->parent = parent;
+	return 0;
+}
+
+void clk_init(struct clk *c)
+{
+	spin_lock_init(&c->spinlock);
 
 	if (c->ops && c->ops->init)
 		c->ops->init(c);
 
-	clk_recalculate_rate(c);
+	if (!c->ops || !c->ops->enable) {
+		c->refcnt++;
+		c->set = true;
+		if (c->parent)
+			c->state = c->parent->state;
+		else
+			c->state = ON;
+	}
 
+	mutex_lock(&clock_list_lock);
 	list_add(&c->node, &clocks);
-
-	if (c->parent)
-		list_add_tail(&c->sibling, &c->parent->children);
-
-	spin_unlock_irqrestore(&clock_lock, flags);
+	mutex_unlock(&clock_list_lock);
 }
 
-int clk_enable_locked(struct clk *c)
+int clk_enable(struct clk *c)
 {
-	int ret;
-	pr_debug("%s: %s\n", __func__, c->name);
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->spinlock, flags);
+
 	if (c->refcnt == 0) {
 		if (c->parent) {
-			ret = clk_enable_locked(c->parent);
+			ret = clk_enable(c->parent);
 			if (ret)
-				return ret;
+				goto out;
 		}
 
 		if (c->ops && c->ops->enable) {
 			ret = c->ops->enable(c);
 			if (ret) {
 				if (c->parent)
-					clk_disable_locked(c->parent);
-				return ret;
+					clk_disable(c->parent);
+				goto out;
 			}
 			c->state = ON;
-#ifdef CONFIG_DEBUG_FS
-			c->set = 1;
-#endif
+			c->set = true;
 		}
 	}
 	c->refcnt++;
-
-	return 0;
-}
-
-int clk_enable_cansleep(struct clk *c)
-{
-	int ret;
-	unsigned long flags;
-
-	mutex_lock(&dvfs_lock);
-
-	if (clk_is_dvfs(c) && c->refcnt > 0)
-		dvfs_set_rate(c->dvfs, c->rate);
-
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_enable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
-
-	mutex_unlock(&dvfs_lock);
-
+out:
+	spin_unlock_irqrestore(&c->spinlock, flags);
 	return ret;
 }
-EXPORT_SYMBOL(clk_enable_cansleep);
+EXPORT_SYMBOL(clk_enable);
 
-int clk_enable(struct clk *c)
+void clk_disable(struct clk *c)
 {
-	int ret;
 	unsigned long flags;
 
-	if (clk_is_dvfs(c))
-		BUG();
-
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_enable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_enable);
+	spin_lock_irqsave(&c->spinlock, flags);
 
-void clk_disable_locked(struct clk *c)
-{
-	pr_debug("%s: %s\n", __func__, c->name);
 	if (c->refcnt == 0) {
 		WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
+		spin_unlock_irqrestore(&c->spinlock, flags);
 		return;
 	}
 	if (c->refcnt == 1) {
@@ -257,71 +196,39 @@ void clk_disable_locked(struct clk *c)
 			c->ops->disable(c);
 
 		if (c->parent)
-			clk_disable_locked(c->parent);
+			clk_disable(c->parent);
 
 		c->state = OFF;
 	}
 	c->refcnt--;
-}
-
-void clk_disable_cansleep(struct clk *c)
-{
-	unsigned long flags;
-
-	mutex_lock(&dvfs_lock);
-
-	spin_lock_irqsave(&clock_lock, flags);
-	clk_disable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
 
-	if (clk_is_dvfs(c) && c->refcnt == 0)
-		dvfs_set_rate(c->dvfs, c->rate);
-
-	mutex_unlock(&dvfs_lock);
-}
-EXPORT_SYMBOL(clk_disable_cansleep);
-
-void clk_disable(struct clk *c)
-{
-	unsigned long flags;
-
-	if (clk_is_dvfs(c))
-		BUG();
-
-	spin_lock_irqsave(&clock_lock, flags);
-	clk_disable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
+	spin_unlock_irqrestore(&c->spinlock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
-int clk_set_parent_locked(struct clk *c, struct clk *parent)
+int clk_set_parent(struct clk *c, struct clk *parent)
 {
 	int ret;
+	unsigned long flags;
+	unsigned long new_rate;
+	unsigned long old_rate;
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	spin_lock_irqsave(&c->spinlock, flags);
 
-	if (!c->ops || !c->ops->set_parent)
-		return -ENOSYS;
+	if (!c->ops || !c->ops->set_parent) {
+		ret = -ENOSYS;
+		goto out;
+	}
 
-	ret = c->ops->set_parent(c, parent);
+	new_rate = clk_predict_rate_from_parent(c, parent);
+	old_rate = clk_get_rate_locked(c);
 
+	ret = c->ops->set_parent(c, parent);
 	if (ret)
-		return ret;
-
-	clk_recalculate_rate(c);
-
-	propagate_rate(c);
-
-	return 0;
-}
+		goto out;
 
-int clk_set_parent(struct clk *c, struct clk *parent)
-{
-	int ret;
-	unsigned long flags;
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_set_parent_locked(c, parent);
-	spin_unlock_irqrestore(&clock_lock, flags);
+out:
+	spin_unlock_irqrestore(&c->spinlock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(clk_set_parent);
@@ -334,100 +241,86 @@ EXPORT_SYMBOL(clk_get_parent);
 
 int clk_set_rate_locked(struct clk *c, unsigned long rate)
 {
-	int ret;
-
-	if (rate > c->max_rate)
-		rate = c->max_rate;
+	long new_rate;
 
 	if (!c->ops || !c->ops->set_rate)
 		return -ENOSYS;
 
-	ret = c->ops->set_rate(c, rate);
-
-	if (ret)
-		return ret;
-
-	clk_recalculate_rate(c);
-
-	propagate_rate(c);
-
-	return 0;
-}
-
-int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	pr_debug("%s: %s\n", __func__, c->name);
-
-	mutex_lock(&dvfs_lock);
-
-	if (rate > c->rate)
-		ret = dvfs_set_rate(c->dvfs, rate);
-	if (ret)
-		goto out;
+	if (rate > c->max_rate)
+		rate = c->max_rate;
 
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_set_rate_locked(c, rate);
-	spin_unlock_irqrestore(&clock_lock, flags);
+	if (c->ops && c->ops->round_rate) {
+		new_rate = c->ops->round_rate(c, rate);
 
-	if (ret)
-		goto out;
+		if (new_rate < 0)
+			return new_rate;
 
-	ret = dvfs_set_rate(c->dvfs, rate);
+		rate = new_rate;
+	}
 
-out:
-	mutex_unlock(&dvfs_lock);
-	return ret;
+	return c->ops->set_rate(c, rate);
 }
-EXPORT_SYMBOL(clk_set_rate_cansleep);
 
 int clk_set_rate(struct clk *c, unsigned long rate)
 {
-	int ret = 0;
+	int ret;
 	unsigned long flags;
 
-	pr_debug("%s: %s\n", __func__, c->name);
-
-	if (clk_is_dvfs(c))
-		BUG();
+	spin_lock_irqsave(&c->spinlock, flags);
 
-	spin_lock_irqsave(&clock_lock, flags);
 	ret = clk_set_rate_locked(c, rate);
-	spin_unlock_irqrestore(&clock_lock, flags);
+
+	spin_unlock_irqrestore(&c->spinlock, flags);
 
 	return ret;
 }
 EXPORT_SYMBOL(clk_set_rate);
 
-unsigned long clk_get_rate(struct clk *c)
-{
-	unsigned long flags;
-	unsigned long ret;
-
-	spin_lock_irqsave(&clock_lock, flags);
 
-	pr_debug("%s: %s\n", __func__, c->name);
+/* Must be called with clocks lock and all indvidual clock locks held */
+unsigned long clk_get_rate_all_locked(struct clk *c)
+{
+	u64 rate;
+	int mul = 1;
+	int div = 1;
+	struct clk *p = c;
+
+	while (p) {
+		c = p;
+		if (c->mul != 0 && c->div != 0) {
+			mul *= c->mul;
+			div *= c->div;
+		}
+		p = c->parent;
+	}
 
-	ret = c->rate;
+	rate = c->rate;
+	rate *= mul;
+	do_div(rate, div);
 
-	spin_unlock_irqrestore(&clock_lock, flags);
-	return ret;
+	return rate;
 }
-EXPORT_SYMBOL(clk_get_rate);
 
 long clk_round_rate(struct clk *c, unsigned long rate)
 {
-	pr_debug("%s: %s\n", __func__, c->name);
+	unsigned long flags;
+	long ret;
 
-	if (!c->ops || !c->ops->round_rate)
-		return -ENOSYS;
+	spin_lock_irqsave(&c->spinlock, flags);
+
+	if (!c->ops || !c->ops->round_rate) {
+		ret = -ENOSYS;
+		goto out;
+	}
 
 	if (rate > c->max_rate)
 		rate = c->max_rate;
 
-	return c->ops->round_rate(c, rate);
+	ret = c->ops->round_rate(c, rate);
+
+out:
+	spin_unlock_irqrestore(&c->spinlock, flags);
+	return ret;
 }
 EXPORT_SYMBOL(clk_round_rate);
 
@@ -509,31 +402,90 @@ void __init tegra_init_clock(void)
 	tegra2_init_clocks();
 }
 
-int __init tegra_init_dvfs(void)
+/*
+ * The SDMMC controllers have extra bits in the clock source register that
+ * adjust the delay between the clock and data to compenstate for delays
+ * on the PCB.
+ */
+void tegra_sdmmc_tap_delay(struct clk *c, int delay)
 {
-	struct clk *c, *safe;
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->spinlock, flags);
+	tegra2_sdmmc_tap_delay(c, delay);
+	spin_unlock_irqrestore(&c->spinlock, flags);
+}
 
-	mutex_lock(&dvfs_lock);
+#ifdef CONFIG_DEBUG_FS
 
-	list_for_each_entry_safe(c, safe, &clocks, node)
-		if (c->dvfs)
-			dvfs_init(c);
+static int __clk_lock_all_spinlocks(void)
+{
+	struct clk *c;
 
-	mutex_unlock(&dvfs_lock);
+	list_for_each_entry(c, &clocks, node)
+		if (!spin_trylock(&c->spinlock))
+			goto unlock_spinlocks;
 
 	return 0;
+
+unlock_spinlocks:
+	list_for_each_entry_continue_reverse(c, &clocks, node)
+		spin_unlock(&c->spinlock);
+
+	return -EAGAIN;
 }
 
-late_initcall(tegra_init_dvfs);
+static void __clk_unlock_all_spinlocks(void)
+{
+	struct clk *c;
+
+	list_for_each_entry_reverse(c, &clocks, node)
+		spin_unlock(&c->spinlock);
+}
+
+/*
+ * This function retries until it can take all locks, and may take
+ * an arbitrarily long time to complete.
+ * Must be called with irqs enabled, returns with irqs disabled
+ * Must be called with clock_list_lock held
+ */
+static void clk_lock_all(void)
+{
+	int ret;
+retry:
+	local_irq_disable();
+
+	ret = __clk_lock_all_spinlocks();
+	if (ret)
+		goto failed_spinlocks;
+
+	/* All locks taken successfully, return */
+	return;
+
+failed_spinlocks:
+	local_irq_enable();
+	yield();
+	goto retry;
+}
+
+/*
+ * Unlocks all clocks after a clk_lock_all
+ * Must be called with irqs disabled, returns with irqs enabled
+ * Must be called with clock_list_lock held
+ */
+static void clk_unlock_all(void)
+{
+	__clk_unlock_all_spinlocks();
+
+	local_irq_enable();
+}
 
-#ifdef CONFIG_DEBUG_FS
 static struct dentry *clk_debugfs_root;
 
 
 static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
 {
 	struct clk *child;
-	struct clk *safe;
 	const char *state = "uninit";
 	char div[8] = {0};
 
@@ -564,8 +516,12 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
 		c->rate > c->max_rate ? '!' : ' ',
 		!c->set ? '*' : ' ',
 		30 - level * 3, c->name,
-		state, c->refcnt, div, c->rate);
-	list_for_each_entry_safe(child, safe, &c->children, sibling) {
+		state, c->refcnt, div, clk_get_rate_all_locked(c));
+
+	list_for_each_entry(child, &clocks, node) {
+		if (child->parent != c)
+			continue;
+
 		clock_tree_show_one(s, child, level + 1);
 	}
 }
@@ -573,14 +529,20 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
 static int clock_tree_show(struct seq_file *s, void *data)
 {
 	struct clk *c;
-	unsigned long flags;
 	seq_printf(s, "   clock                          state  ref div      rate\n");
 	seq_printf(s, "--------------------------------------------------------------\n");
-	spin_lock_irqsave(&clock_lock, flags);
+
+	mutex_lock(&clock_list_lock);
+
+	clk_lock_all();
+
 	list_for_each_entry(c, &clocks, node)
 		if (c->parent == NULL)
 			clock_tree_show_one(s, c, 0);
-	spin_unlock_irqrestore(&clock_lock, flags);
+
+	clk_unlock_all();
+
+	mutex_unlock(&clock_list_lock);
 	return 0;
 }
 
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index 083a4cf..688316a 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -20,8 +20,9 @@
 #ifndef __MACH_TEGRA_CLOCK_H
 #define __MACH_TEGRA_CLOCK_H
 
-#include <linux/list.h>
 #include <linux/clkdev.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
 
 #define DIV_BUS			(1 << 0)
 #define DIV_U71			(1 << 1)
@@ -41,36 +42,13 @@
 #define ENABLE_ON_INIT		(1 << 28)
 
 struct clk;
-struct regulator;
-
-struct dvfs_table {
-	unsigned long rate;
-	int millivolts;
-};
-
-struct dvfs_process_id_table {
-	int process_id;
-	struct dvfs_table *table;
-};
-
-
-struct dvfs {
-	struct regulator *reg;
-	struct dvfs_table *table;
-	int max_millivolts;
-
-	int process_id_table_length;
-	const char *reg_id;
-	bool cpu;
-	struct dvfs_process_id_table process_id_table[];
-};
 
 struct clk_mux_sel {
 	struct clk	*input;
 	u32		value;
 };
 
-struct clk_pll_table {
+struct clk_pll_freq_table {
 	unsigned long	input_rate;
 	unsigned long	output_rate;
 	u16		n;
@@ -86,6 +64,7 @@ struct clk_ops {
 	int		(*set_parent)(struct clk *, struct clk *);
 	int		(*set_rate)(struct clk *, unsigned long);
 	long		(*round_rate)(struct clk *, unsigned long);
+	void		(*reset)(struct clk *, bool);
 };
 
 enum clk_state {
@@ -96,55 +75,64 @@ enum clk_state {
 
 struct clk {
 	/* node for master clocks list */
-	struct list_head		node;
-	struct list_head		children;	/* list of children */
-	struct list_head		sibling;	/* node for children */
-#ifdef CONFIG_DEBUG_FS
-	struct dentry			*dent;
-	struct dentry			*parent_dent;
-#endif
-	struct clk_ops			*ops;
-	struct clk			*parent;
-	struct clk_lookup		lookup;
-	unsigned long			rate;
-	unsigned long			max_rate;
-	u32				flags;
-	u32				refcnt;
-	const char			*name;
-	u32				reg;
-	u32				reg_shift;
-	unsigned int			clk_num;
-	enum clk_state			state;
+	struct list_head	node;		/* node for list of all clocks */
+	struct clk_lookup	lookup;
+
 #ifdef CONFIG_DEBUG_FS
-	bool				set;
+	struct dentry		*dent;
 #endif
+	bool			set;
+	struct clk_ops		*ops;
+	unsigned long		rate;
+	unsigned long		max_rate;
+	unsigned long		min_rate;
+	u32			flags;
+	const char		*name;
+
+	u32			refcnt;
+	enum clk_state		state;
+	struct clk		*parent;
+	u32			div;
+	u32			mul;
 
-	/* PLL */
-	unsigned long			input_min;
-	unsigned long			input_max;
-	unsigned long			cf_min;
-	unsigned long			cf_max;
-	unsigned long			vco_min;
-	unsigned long			vco_max;
-	const struct clk_pll_table	*pll_table;
-
-	/* DIV */
-	u32				div;
-	u32				mul;
-
-	/* MUX */
 	const struct clk_mux_sel	*inputs;
-	u32				sel;
-	u32				reg_mask;
-
-	/* Virtual cpu clock */
-	struct clk			*main;
-	struct clk			*backup;
+	u32				reg;
+	u32				reg_shift;
 
-	struct dvfs			*dvfs;
+	struct list_head		shared_bus_list;
+
+	union {
+		struct {
+			unsigned int			clk_num;
+		} periph;
+		struct {
+			unsigned long			input_min;
+			unsigned long			input_max;
+			unsigned long			cf_min;
+			unsigned long			cf_max;
+			unsigned long			vco_min;
+			unsigned long			vco_max;
+			const struct clk_pll_freq_table	*freq_table;
+			int				lock_delay;
+		} pll;
+		struct {
+			u32				sel;
+			u32				reg_mask;
+		} mux;
+		struct {
+			struct clk			*main;
+			struct clk			*backup;
+		} cpu;
+		struct {
+			struct list_head		node;
+			bool				enabled;
+			unsigned long			rate;
+		} shared_bus_user;
+	} u;
+
+	spinlock_t spinlock;
 };
 
-
 struct clk_duplicate {
 	const char *name;
 	struct clk_lookup lookup;
@@ -163,11 +151,10 @@ void tegra2_periph_reset_assert(struct clk *c);
 void clk_init(struct clk *clk);
 struct clk *tegra_get_clock_by_name(const char *name);
 unsigned long clk_measure_input_freq(void);
-void clk_disable_locked(struct clk *c);
-int clk_enable_locked(struct clk *c);
-int clk_set_parent_locked(struct clk *c, struct clk *parent);
-int clk_set_rate_locked(struct clk *c, unsigned long rate);
 int clk_reparent(struct clk *c, struct clk *parent);
 void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
+unsigned long clk_get_rate_locked(struct clk *c);
+int clk_set_rate_locked(struct clk *c, unsigned long rate);
+void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
 
 #endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index 7c91e2b..d5e3f89 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -25,12 +25,25 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/iomap.h>
-#include <mach/dma.h>
+#include <mach/system.h>
 
 #include "board.h"
 #include "clock.h"
 #include "fuse.h"
 
+void (*arch_reset)(char mode, const char *cmd) = tegra_assert_system_reset;
+
+void tegra_assert_system_reset(char mode, const char *cmd)
+{
+	void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
+	u32 reg;
+
+	/* use *_related to avoid spinlock since caches are off */
+	reg = readl_relaxed(reset);
+	reg |= 0x04;
+	writel_relaxed(reg, reset);
+}
+
 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "clk_m",	NULL,		0,		true },
@@ -42,6 +55,9 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
 	{ "sclk",	"pll_p_out4",	108000000,	true },
 	{ "hclk",	"sclk",		108000000,	true },
 	{ "pclk",	"hclk",		54000000,	true },
+	{ "csite",	NULL,		0,		true },
+	{ "emc",	NULL,		0,		true },
+	{ "cpu",	NULL,		0,		true },
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -50,21 +66,18 @@ void __init tegra_init_cache(void)
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
 
-	writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
-	writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
+	writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL);
+	writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL);
 
 	l2x0_init(p, 0x6C080001, 0x8200c3fe);
 #endif
 
 }
 
-void __init tegra_common_init(void)
+void __init tegra_init_early(void)
 {
 	tegra_init_fuse();
 	tegra_init_clock();
 	tegra_clk_init_from_table(common_clk_init_table);
 	tegra_init_cache();
-#ifdef CONFIG_TEGRA_SYSTEM_DMA
-	tegra_dma_init();
-#endif
 }
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index fea5719..0e1016a 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -28,6 +28,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/suspend.h>
 
 #include <asm/system.h>
 
@@ -36,21 +37,25 @@
 
 /* Frequency table index must be sequential starting at 0 */
 static struct cpufreq_frequency_table freq_table[] = {
-	{ 0, 312000 },
-	{ 1, 456000 },
-	{ 2, 608000 },
-	{ 3, 760000 },
-	{ 4, 816000 },
-	{ 5, 912000 },
-	{ 6, 1000000 },
-	{ 7, CPUFREQ_TABLE_END },
+	{ 0, 216000 },
+	{ 1, 312000 },
+	{ 2, 456000 },
+	{ 3, 608000 },
+	{ 4, 760000 },
+	{ 5, 816000 },
+	{ 6, 912000 },
+	{ 7, 1000000 },
+	{ 8, CPUFREQ_TABLE_END },
 };
 
 #define NUM_CPUS	2
 
 static struct clk *cpu_clk;
+static struct clk *emc_clk;
 
 static unsigned long target_cpu_speed[NUM_CPUS];
+static DEFINE_MUTEX(tegra_cpu_lock);
+static bool is_suspended;
 
 int tegra_verify_speed(struct cpufreq_policy *policy)
 {
@@ -68,22 +73,28 @@ unsigned int tegra_getspeed(unsigned int cpu)
 	return rate;
 }
 
-static int tegra_update_cpu_speed(void)
+static int tegra_update_cpu_speed(unsigned long rate)
 {
-	int i;
-	unsigned long rate = 0;
 	int ret = 0;
 	struct cpufreq_freqs freqs;
 
-	for_each_online_cpu(i)
-		rate = max(rate, target_cpu_speed[i]);
-
 	freqs.old = tegra_getspeed(0);
 	freqs.new = rate;
 
 	if (freqs.old == freqs.new)
 		return ret;
 
+	/*
+	 * Vote on memory bus frequency based on cpu frequency
+	 * This sets the minimum frequency, display or avp may request higher
+	 */
+	if (rate >= 816000)
+		clk_set_rate(emc_clk, 600000000); /* cpu 816 MHz, emc max */
+	else if (rate >= 456000)
+		clk_set_rate(emc_clk, 300000000); /* cpu 456 MHz, emc 150Mhz */
+	else
+		clk_set_rate(emc_clk, 100000000);  /* emc 50Mhz */
+
 	for_each_online_cpu(freqs.cpu)
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
@@ -92,7 +103,7 @@ static int tegra_update_cpu_speed(void)
 	       freqs.old, freqs.new);
 #endif
 
-	ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000);
+	ret = clk_set_rate(cpu_clk, freqs.new * 1000);
 	if (ret) {
 		pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
 			freqs.new);
@@ -105,12 +116,30 @@ static int tegra_update_cpu_speed(void)
 	return 0;
 }
 
+static unsigned long tegra_cpu_highest_speed(void)
+{
+	unsigned long rate = 0;
+	int i;
+
+	for_each_online_cpu(i)
+		rate = max(rate, target_cpu_speed[i]);
+	return rate;
+}
+
 static int tegra_target(struct cpufreq_policy *policy,
 		       unsigned int target_freq,
 		       unsigned int relation)
 {
 	int idx;
 	unsigned int freq;
+	int ret = 0;
+
+	mutex_lock(&tegra_cpu_lock);
+
+	if (is_suspended) {
+		ret = -EBUSY;
+		goto out;
+	}
 
 	cpufreq_frequency_table_target(policy, freq_table, target_freq,
 		relation, &idx);
@@ -119,9 +148,34 @@ static int tegra_target(struct cpufreq_policy *policy,
 
 	target_cpu_speed[policy->cpu] = freq;
 
-	return tegra_update_cpu_speed();
+	ret = tegra_update_cpu_speed(tegra_cpu_highest_speed());
+
+out:
+	mutex_unlock(&tegra_cpu_lock);
+	return ret;
 }
 
+static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
+	void *dummy)
+{
+	mutex_lock(&tegra_cpu_lock);
+	if (event == PM_SUSPEND_PREPARE) {
+		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);
+	} else if (event == PM_POST_SUSPEND) {
+		is_suspended = false;
+	}
+	mutex_unlock(&tegra_cpu_lock);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block tegra_cpu_pm_notifier = {
+	.notifier_call = tegra_pm_notify,
+};
+
 static int tegra_cpu_init(struct cpufreq_policy *policy)
 {
 	if (policy->cpu >= NUM_CPUS)
@@ -131,6 +185,15 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
 
+	emc_clk = clk_get_sys("cpu", "emc");
+	if (IS_ERR(emc_clk)) {
+		clk_put(cpu_clk);
+		return PTR_ERR(emc_clk);
+	}
+
+	clk_enable(emc_clk);
+	clk_enable(cpu_clk);
+
 	cpufreq_frequency_table_cpuinfo(policy, freq_table);
 	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 	policy->cur = tegra_getspeed(policy->cpu);
@@ -142,12 +205,17 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 	policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 	cpumask_copy(policy->related_cpus, cpu_possible_mask);
 
+	if (policy->cpu == 0)
+		register_pm_notifier(&tegra_cpu_pm_notifier);
+
 	return 0;
 }
 
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 {
 	cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	clk_disable(emc_clk);
+	clk_put(emc_clk);
 	clk_put(cpu_clk);
 	return 0;
 }
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
new file mode 100644
index 0000000..682e6d3
--- /dev/null
+++ b/arch/arm/mach-tegra/devices.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2010,2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *	Erik Gilling <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.
+ *
+ */
+
+
+#include <linux/resource.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/serial_8250.h>
+#include <asm/pmu.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+#include <mach/dma.h>
+
+static struct resource i2c_resource1[] = {
+	[0] = {
+		.start	= INT_I2C,
+		.end	= INT_I2C,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_I2C_BASE,
+		.end	= TEGRA_I2C_BASE + TEGRA_I2C_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c_resource2[] = {
+	[0] = {
+		.start	= INT_I2C2,
+		.end	= INT_I2C2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_I2C2_BASE,
+		.end	= TEGRA_I2C2_BASE + TEGRA_I2C2_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c_resource3[] = {
+	[0] = {
+		.start	= INT_I2C3,
+		.end	= INT_I2C3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_I2C3_BASE,
+		.end	= TEGRA_I2C3_BASE + TEGRA_I2C3_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c_resource4[] = {
+	[0] = {
+		.start	= INT_DVC,
+		.end	= INT_DVC,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_DVC_BASE,
+		.end	= TEGRA_DVC_BASE + TEGRA_DVC_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_i2c_device1 = {
+	.name		= "tegra-i2c",
+	.id		= 0,
+	.resource	= i2c_resource1,
+	.num_resources	= ARRAY_SIZE(i2c_resource1),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+struct platform_device tegra_i2c_device2 = {
+	.name		= "tegra-i2c",
+	.id		= 1,
+	.resource	= i2c_resource2,
+	.num_resources	= ARRAY_SIZE(i2c_resource2),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+struct platform_device tegra_i2c_device3 = {
+	.name		= "tegra-i2c",
+	.id		= 2,
+	.resource	= i2c_resource3,
+	.num_resources	= ARRAY_SIZE(i2c_resource3),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+struct platform_device tegra_i2c_device4 = {
+	.name		= "tegra-i2c",
+	.id		= 3,
+	.resource	= i2c_resource4,
+	.num_resources	= ARRAY_SIZE(i2c_resource4),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+static struct resource spi_resource1[] = {
+	[0] = {
+		.start	= INT_S_LINK1,
+		.end	= INT_S_LINK1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI1_BASE,
+		.end	= TEGRA_SPI1_BASE + TEGRA_SPI1_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource spi_resource2[] = {
+	[0] = {
+		.start	= INT_SPI_2,
+		.end	= INT_SPI_2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI2_BASE,
+		.end	= TEGRA_SPI2_BASE + TEGRA_SPI2_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource spi_resource3[] = {
+	[0] = {
+		.start	= INT_SPI_3,
+		.end	= INT_SPI_3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI3_BASE,
+		.end	= TEGRA_SPI3_BASE + TEGRA_SPI3_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource spi_resource4[] = {
+	[0] = {
+		.start	= INT_SPI_4,
+		.end	= INT_SPI_4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI4_BASE,
+		.end	= TEGRA_SPI4_BASE + TEGRA_SPI4_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_spi_device1 = {
+	.name		= "spi_tegra",
+	.id		= 0,
+	.resource	= spi_resource1,
+	.num_resources	= ARRAY_SIZE(spi_resource1),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device tegra_spi_device2 = {
+	.name		= "spi_tegra",
+	.id		= 1,
+	.resource	= spi_resource2,
+	.num_resources	= ARRAY_SIZE(spi_resource2),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device tegra_spi_device3 = {
+	.name		= "spi_tegra",
+	.id		= 2,
+	.resource	= spi_resource3,
+	.num_resources	= ARRAY_SIZE(spi_resource3),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device tegra_spi_device4 = {
+	.name		= "spi_tegra",
+	.id		= 3,
+	.resource	= spi_resource4,
+	.num_resources	= ARRAY_SIZE(spi_resource4),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+
+static struct resource sdhci_resource1[] = {
+	[0] = {
+		.start	= INT_SDMMC1,
+		.end	= INT_SDMMC1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC1_BASE,
+		.end	= TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sdhci_resource2[] = {
+	[0] = {
+		.start	= INT_SDMMC2,
+		.end	= INT_SDMMC2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC2_BASE,
+		.end	= TEGRA_SDMMC2_BASE + TEGRA_SDMMC2_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sdhci_resource3[] = {
+	[0] = {
+		.start	= INT_SDMMC3,
+		.end	= INT_SDMMC3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC3_BASE,
+		.end	= TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sdhci_resource4[] = {
+	[0] = {
+		.start	= INT_SDMMC4,
+		.end	= INT_SDMMC4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC4_BASE,
+		.end	= TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+/* board files should fill in platform_data register the devices themselvs.
+ * See board-harmony.c for an example
+ */
+struct platform_device tegra_sdhci_device1 = {
+	.name		= "sdhci-tegra",
+	.id		= 0,
+	.resource	= sdhci_resource1,
+	.num_resources	= ARRAY_SIZE(sdhci_resource1),
+};
+
+struct platform_device tegra_sdhci_device2 = {
+	.name		= "sdhci-tegra",
+	.id		= 1,
+	.resource	= sdhci_resource2,
+	.num_resources	= ARRAY_SIZE(sdhci_resource2),
+};
+
+struct platform_device tegra_sdhci_device3 = {
+	.name		= "sdhci-tegra",
+	.id		= 2,
+	.resource	= sdhci_resource3,
+	.num_resources	= ARRAY_SIZE(sdhci_resource3),
+};
+
+struct platform_device tegra_sdhci_device4 = {
+	.name		= "sdhci-tegra",
+	.id		= 3,
+	.resource	= sdhci_resource4,
+	.num_resources	= ARRAY_SIZE(sdhci_resource4),
+};
+
+static struct resource tegra_usb1_resources[] = {
+	[0] = {
+		.start	= TEGRA_USB_BASE,
+		.end	= TEGRA_USB_BASE + TEGRA_USB_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_USB,
+		.end	= INT_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_usb2_resources[] = {
+	[0] = {
+		.start	= TEGRA_USB2_BASE,
+		.end	= TEGRA_USB2_BASE + TEGRA_USB2_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_USB2,
+		.end	= INT_USB2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_usb3_resources[] = {
+	[0] = {
+		.start	= TEGRA_USB3_BASE,
+		.end	= TEGRA_USB3_BASE + TEGRA_USB3_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_USB3,
+		.end	= INT_USB3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device tegra_ehci1_device = {
+	.name	= "tegra-ehci",
+	.id	= 0,
+	.dev	= {
+		.dma_mask	= &tegra_ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = tegra_usb1_resources,
+	.num_resources = ARRAY_SIZE(tegra_usb1_resources),
+};
+
+struct platform_device tegra_ehci2_device = {
+	.name	= "tegra-ehci",
+	.id	= 1,
+	.dev	= {
+		.dma_mask	= &tegra_ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = tegra_usb2_resources,
+	.num_resources = ARRAY_SIZE(tegra_usb2_resources),
+};
+
+struct platform_device tegra_ehci3_device = {
+	.name	= "tegra-ehci",
+	.id	= 2,
+	.dev	= {
+		.dma_mask	= &tegra_ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = tegra_usb3_resources,
+	.num_resources = ARRAY_SIZE(tegra_usb3_resources),
+};
+
+static struct resource tegra_pmu_resources[] = {
+	[0] = {
+		.start	= INT_CPU0_PMU_INTR,
+		.end	= INT_CPU0_PMU_INTR,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= INT_CPU1_PMU_INTR,
+		.end	= INT_CPU1_PMU_INTR,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.num_resources	= ARRAY_SIZE(tegra_pmu_resources),
+	.resource	= tegra_pmu_resources,
+};
+
+static struct resource tegra_uarta_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTA_BASE,
+		.end	= TEGRA_UARTA_BASE + TEGRA_UARTA_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTA,
+		.end	= INT_UARTA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uartb_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTB_BASE,
+		.end	= TEGRA_UARTB_BASE + TEGRA_UARTB_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTB,
+		.end	= INT_UARTB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uartc_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTC_BASE,
+		.end	= TEGRA_UARTC_BASE + TEGRA_UARTC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTC,
+		.end	= INT_UARTC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uartd_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTD_BASE,
+		.end	= TEGRA_UARTD_BASE + TEGRA_UARTD_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTD,
+		.end	= INT_UARTD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uarte_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTE_BASE,
+		.end	= TEGRA_UARTE_BASE + TEGRA_UARTE_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTE,
+		.end	= INT_UARTE,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_uarta_device = {
+	.name	= "tegra_uart",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(tegra_uarta_resources),
+	.resource	= tegra_uarta_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uartb_device = {
+	.name	= "tegra_uart",
+	.id	= 1,
+	.num_resources	= ARRAY_SIZE(tegra_uartb_resources),
+	.resource	= tegra_uartb_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uartc_device = {
+	.name	= "tegra_uart",
+	.id	= 2,
+	.num_resources	= ARRAY_SIZE(tegra_uartc_resources),
+	.resource	= tegra_uartc_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uartd_device = {
+	.name	= "tegra_uart",
+	.id	= 3,
+	.num_resources	= ARRAY_SIZE(tegra_uartd_resources),
+	.resource	= tegra_uartd_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uarte_device = {
+	.name	= "tegra_uart",
+	.id	= 4,
+	.num_resources	= ARRAY_SIZE(tegra_uarte_resources),
+	.resource	= tegra_uarte_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
new file mode 100644
index 0000000..888810c
--- /dev/null
+++ b/arch/arm/mach-tegra/devices.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010,2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *	Erik Gilling <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 __MACH_TEGRA_DEVICES_H
+#define __MACH_TEGRA_DEVICES_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device tegra_sdhci_device1;
+extern struct platform_device tegra_sdhci_device2;
+extern struct platform_device tegra_sdhci_device3;
+extern struct platform_device tegra_sdhci_device4;
+extern struct platform_device tegra_i2c_device1;
+extern struct platform_device tegra_i2c_device2;
+extern struct platform_device tegra_i2c_device3;
+extern struct platform_device tegra_i2c_device4;
+extern struct platform_device tegra_spi_device1;
+extern struct platform_device tegra_spi_device2;
+extern struct platform_device tegra_spi_device3;
+extern struct platform_device tegra_spi_device4;
+extern struct platform_device tegra_ehci1_device;
+extern struct platform_device tegra_ehci2_device;
+extern struct platform_device tegra_ehci3_device;
+extern struct platform_device tegra_uarta_device;
+extern struct platform_device tegra_uartb_device;
+extern struct platform_device tegra_uartc_device;
+extern struct platform_device tegra_uartd_device;
+extern struct platform_device tegra_uarte_device;
+extern struct platform_device tegra_pmu_device;
+
+#endif
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
index edda6ec..e945ae2 100644
--- a/arch/arm/mach-tegra/dma.c
+++ b/arch/arm/mach-tegra/dma.c
@@ -27,9 +27,11 @@
 #include <linux/err.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
 #include <mach/iomap.h>
+#include <mach/suspend.h>
 
 #define APB_DMA_GEN				0x000
 #define GEN_ENABLE				(1<<31)
@@ -120,17 +122,14 @@ struct tegra_dma_channel {
 	void  __iomem		*addr;
 	int			mode;
 	int			irq;
-
-	/* Register shadow */
-	u32			csr;
-	u32			ahb_seq;
-	u32			ahb_ptr;
-	u32			apb_seq;
-	u32			apb_ptr;
+	int			req_transfer_count;
 };
 
 #define  NV_DMA_MAX_CHANNELS  32
 
+static bool tegra_dma_initialized;
+static DEFINE_MUTEX(tegra_dma_lock);
+
 static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
 static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
 
@@ -138,7 +137,6 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
 	struct tegra_dma_req *req);
 static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
 	struct tegra_dma_req *req);
-static void tegra_dma_init_hw(struct tegra_dma_channel *ch);
 static void tegra_dma_stop(struct tegra_dma_channel *ch);
 
 void tegra_dma_flush(struct tegra_dma_channel *ch)
@@ -150,6 +148,9 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)
 {
 	struct tegra_dma_req *req;
 
+	if (tegra_dma_is_empty(ch))
+		return;
+
 	req = list_entry(ch->list.next, typeof(*req), node);
 
 	tegra_dma_dequeue_req(ch, req);
@@ -158,10 +159,10 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)
 
 void tegra_dma_stop(struct tegra_dma_channel *ch)
 {
-	unsigned int csr;
-	unsigned int status;
+	u32 csr;
+	u32 status;
 
-	csr = ch->csr;
+	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
 	csr &= ~CSR_IE_EOC;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
@@ -175,19 +176,16 @@ void tegra_dma_stop(struct tegra_dma_channel *ch)
 
 int tegra_dma_cancel(struct tegra_dma_channel *ch)
 {
-	unsigned int csr;
+	u32 csr;
 	unsigned long irq_flags;
 
 	spin_lock_irqsave(&ch->lock, irq_flags);
 	while (!list_empty(&ch->list))
 		list_del(ch->list.next);
 
-	csr = ch->csr;
+	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
 	csr &= ~CSR_REQ_SEL_MASK;
 	csr |= CSR_REQ_SEL_INVALID;
-
-	/* Set the enable as that is not shadowed */
-	csr |= CSR_ENB;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
 	tegra_dma_stop(ch);
@@ -229,18 +227,15 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
 	 *  - Finally stop or program the DMA to the next buffer in the
 	 *    list.
 	 */
-	csr = ch->csr;
+	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
 	csr &= ~CSR_REQ_SEL_MASK;
 	csr |= CSR_REQ_SEL_INVALID;
-
-	/* Set the enable as that is not shadowed */
-	csr |= CSR_ENB;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
 	/* Get the transfer count */
 	status = readl(ch->addr + APB_DMA_CHAN_STA);
 	to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
-	req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+	req_transfer_count = ch->req_transfer_count;
 	req_transfer_count += 1;
 	to_transfer += 1;
 
@@ -318,6 +313,7 @@ int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
 	struct tegra_dma_req *req)
 {
 	unsigned long irq_flags;
+	struct tegra_dma_req *_req;
 	int start_dma = 0;
 
 	if (req->size > NV_DMA_MAX_TRASFER_SIZE ||
@@ -328,6 +324,13 @@ int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
 
 	spin_lock_irqsave(&ch->lock, irq_flags);
 
+	list_for_each_entry(_req, &ch->list, node) {
+		if (req == _req) {
+		    spin_unlock_irqrestore(&ch->lock, irq_flags);
+		    return -EEXIST;
+		}
+	}
+
 	req->bytes_transferred = 0;
 	req->status = 0;
 	req->buffer_status = 0;
@@ -348,7 +351,12 @@ EXPORT_SYMBOL(tegra_dma_enqueue_req);
 struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
 {
 	int channel;
-	struct tegra_dma_channel *ch;
+	struct tegra_dma_channel *ch = NULL;
+
+	if (WARN_ON(!tegra_dma_initialized))
+		return NULL;
+
+	mutex_lock(&tegra_dma_lock);
 
 	/* first channel is the shared channel */
 	if (mode & TEGRA_DMA_SHARED) {
@@ -357,11 +365,14 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
 		channel = find_first_zero_bit(channel_usage,
 			ARRAY_SIZE(dma_channels));
 		if (channel >= ARRAY_SIZE(dma_channels))
-			return NULL;
+			goto out;
 	}
 	__set_bit(channel, channel_usage);
 	ch = &dma_channels[channel];
 	ch->mode = mode;
+
+out:
+	mutex_unlock(&tegra_dma_lock);
 	return ch;
 }
 EXPORT_SYMBOL(tegra_dma_allocate_channel);
@@ -371,22 +382,27 @@ void tegra_dma_free_channel(struct tegra_dma_channel *ch)
 	if (ch->mode & TEGRA_DMA_SHARED)
 		return;
 	tegra_dma_cancel(ch);
+	mutex_lock(&tegra_dma_lock);
 	__clear_bit(ch->id, channel_usage);
+	mutex_unlock(&tegra_dma_lock);
 }
 EXPORT_SYMBOL(tegra_dma_free_channel);
 
 static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
 	struct tegra_dma_req *req)
 {
+	u32 apb_ptr;
+	u32 ahb_ptr;
+
 	if (req->to_memory) {
-		ch->apb_ptr = req->source_addr;
-		ch->ahb_ptr = req->dest_addr;
+		apb_ptr = req->source_addr;
+		ahb_ptr = req->dest_addr;
 	} else {
-		ch->apb_ptr = req->dest_addr;
-		ch->ahb_ptr = req->source_addr;
+		apb_ptr = req->dest_addr;
+		ahb_ptr = req->source_addr;
 	}
-	writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
-	writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+	writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+	writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
 
 	req->status = TEGRA_DMA_REQ_INFLIGHT;
 	return;
@@ -400,38 +416,39 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
 	int ahb_bus_width;
 	int apb_bus_width;
 	int index;
-	unsigned long csr;
 
+	u32 ahb_seq;
+	u32 apb_seq;
+	u32 ahb_ptr;
+	u32 apb_ptr;
+	u32 csr;
+
+	csr = CSR_IE_EOC | CSR_FLOW;
+	ahb_seq = AHB_SEQ_INTR_ENB | AHB_SEQ_BURST_1;
+	apb_seq = 0;
 
-	ch->csr |= CSR_FLOW;
-	ch->csr &= ~CSR_REQ_SEL_MASK;
-	ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
-	ch->ahb_seq &= ~AHB_SEQ_BURST_MASK;
-	ch->ahb_seq |= AHB_SEQ_BURST_1;
+	csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
 
 	/* One shot mode is always single buffered,
 	 * continuous mode is always double buffered
 	 * */
 	if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
-		ch->csr |= CSR_ONCE;
-		ch->ahb_seq &= ~AHB_SEQ_DBL_BUF;
-		ch->csr &= ~CSR_WCOUNT_MASK;
-		ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT;
+		csr |= CSR_ONCE;
+		ch->req_transfer_count = (req->size >> 2) - 1;
 	} else {
-		ch->csr &= ~CSR_ONCE;
-		ch->ahb_seq |= AHB_SEQ_DBL_BUF;
+		ahb_seq |= AHB_SEQ_DBL_BUF;
 
 		/* In double buffered mode, we set the size to half the
 		 * requested size and interrupt when half the buffer
 		 * is full */
-		ch->csr &= ~CSR_WCOUNT_MASK;
-		ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT;
+		ch->req_transfer_count = (req->size >> 3) - 1;
 	}
 
+	csr |= ch->req_transfer_count << CSR_WCOUNT_SHIFT;
+
 	if (req->to_memory) {
-		ch->csr &= ~CSR_DIR;
-		ch->apb_ptr = req->source_addr;
-		ch->ahb_ptr = req->dest_addr;
+		apb_ptr = req->source_addr;
+		ahb_ptr = req->dest_addr;
 
 		apb_addr_wrap = req->source_wrap;
 		ahb_addr_wrap = req->dest_wrap;
@@ -439,9 +456,9 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
 		ahb_bus_width = req->dest_bus_width;
 
 	} else {
-		ch->csr |= CSR_DIR;
-		ch->apb_ptr = req->dest_addr;
-		ch->ahb_ptr = req->source_addr;
+		csr |= CSR_DIR;
+		apb_ptr = req->dest_addr;
+		ahb_ptr = req->source_addr;
 
 		apb_addr_wrap = req->dest_wrap;
 		ahb_addr_wrap = req->source_wrap;
@@ -460,8 +477,7 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
 		index++;
 	} while (index < ARRAY_SIZE(apb_addr_wrap_table));
 	BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
-	ch->apb_seq &= ~APB_SEQ_WRAP_MASK;
-	ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT;
+	apb_seq |= index << APB_SEQ_WRAP_SHIFT;
 
 	/* set address wrap for AHB size */
 	index = 0;
@@ -471,55 +487,42 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
 		index++;
 	} while (index < ARRAY_SIZE(ahb_addr_wrap_table));
 	BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
-	ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK;
-	ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
+	ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
 
 	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
 		if (bus_width_table[index] == ahb_bus_width)
 			break;
 	}
 	BUG_ON(index == ARRAY_SIZE(bus_width_table));
-	ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK;
-	ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
+	ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
 
 	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
 		if (bus_width_table[index] == apb_bus_width)
 			break;
 	}
 	BUG_ON(index == ARRAY_SIZE(bus_width_table));
-	ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK;
-	ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
-
-	ch->csr |= CSR_IE_EOC;
+	apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
 
-	/* update hw registers with the shadow */
-	writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR);
-	writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
-	writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
-	writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
-	writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+	writel(apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
+	writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+	writel(ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
+	writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
 
-	csr = ch->csr | CSR_ENB;
+	csr |= CSR_ENB;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
 	req->status = TEGRA_DMA_REQ_INFLIGHT;
 }
 
-static void tegra_dma_init_hw(struct tegra_dma_channel *ch)
-{
-	/* One shot with an interrupt to CPU after transfer */
-	ch->csr = CSR_ONCE | CSR_IE_EOC;
-	ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB;
-	ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT;
-}
-
 static void handle_oneshot_dma(struct tegra_dma_channel *ch)
 {
 	struct tegra_dma_req *req;
+	unsigned long irq_flags;
 
-	spin_lock(&ch->lock);
+	spin_lock_irqsave(&ch->lock, irq_flags);
 	if (list_empty(&ch->list)) {
-		spin_unlock(&ch->lock);
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		return;
 	}
 
@@ -527,8 +530,7 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)
 	if (req) {
 		int bytes_transferred;
 
-		bytes_transferred =
-			(ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+		bytes_transferred = ch->req_transfer_count;
 		bytes_transferred += 1;
 		bytes_transferred <<= 2;
 
@@ -536,12 +538,12 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)
 		req->bytes_transferred = bytes_transferred;
 		req->status = TEGRA_DMA_REQ_SUCCESS;
 
-		spin_unlock(&ch->lock);
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		/* Callback should be called without any lock */
 		pr_debug("%s: transferred %d bytes\n", __func__,
 			req->bytes_transferred);
 		req->complete(req);
-		spin_lock(&ch->lock);
+		spin_lock_irqsave(&ch->lock, irq_flags);
 	}
 
 	if (!list_empty(&ch->list)) {
@@ -551,22 +553,55 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)
 		if (req->status != TEGRA_DMA_REQ_INFLIGHT)
 			tegra_dma_update_hw(ch, req);
 	}
-	spin_unlock(&ch->lock);
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
 }
 
 static void handle_continuous_dma(struct tegra_dma_channel *ch)
 {
 	struct tegra_dma_req *req;
+	unsigned long irq_flags;
 
-	spin_lock(&ch->lock);
+	spin_lock_irqsave(&ch->lock, irq_flags);
 	if (list_empty(&ch->list)) {
-		spin_unlock(&ch->lock);
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		return;
 	}
 
 	req = list_entry(ch->list.next, typeof(*req), node);
 	if (req) {
 		if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
+			bool is_dma_ping_complete;
+			is_dma_ping_complete = (readl(ch->addr + APB_DMA_CHAN_STA)
+						& STA_PING_PONG) ? true : false;
+			if (req->to_memory)
+				is_dma_ping_complete = !is_dma_ping_complete;
+			/* Out of sync - Release current buffer */
+			if (!is_dma_ping_complete) {
+				int bytes_transferred;
+
+				bytes_transferred = ch->req_transfer_count;
+				bytes_transferred += 1;
+				bytes_transferred <<= 3;
+				req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
+				req->bytes_transferred = bytes_transferred;
+				req->status = TEGRA_DMA_REQ_SUCCESS;
+				tegra_dma_stop(ch);
+
+				if (!list_is_last(&req->node, &ch->list)) {
+					struct tegra_dma_req *next_req;
+
+					next_req = list_entry(req->node.next,
+						typeof(*next_req), node);
+					tegra_dma_update_hw(ch, next_req);
+				}
+
+				list_del(&req->node);
+
+				/* DMA lock is NOT held when callbak is called */
+				spin_unlock_irqrestore(&ch->lock, irq_flags);
+				req->complete(req);
+				return;
+			}
 			/* Load the next request into the hardware, if available
 			 * */
 			if (!list_is_last(&req->node, &ch->list)) {
@@ -579,7 +614,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
 			req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
 			req->status = TEGRA_DMA_REQ_SUCCESS;
 			/* DMA lock is NOT held when callback is called */
-			spin_unlock(&ch->lock);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			if (likely(req->threshold))
 				req->threshold(req);
 			return;
@@ -590,8 +625,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
 			 * the second  interrupt */
 			int bytes_transferred;
 
-			bytes_transferred =
-				(ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+			bytes_transferred = ch->req_transfer_count;
 			bytes_transferred += 1;
 			bytes_transferred <<= 3;
 
@@ -601,7 +635,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
 			list_del(&req->node);
 
 			/* DMA lock is NOT held when callbak is called */
-			spin_unlock(&ch->lock);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			req->complete(req);
 			return;
 
@@ -609,7 +643,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)
 			BUG();
 		}
 	}
-	spin_unlock(&ch->lock);
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
 }
 
 static irqreturn_t dma_isr(int irq, void *data)
@@ -646,6 +680,21 @@ int __init tegra_dma_init(void)
 	int i;
 	unsigned int irq;
 	void __iomem *addr;
+	struct clk *c;
+
+	bitmap_fill(channel_usage, NV_DMA_MAX_CHANNELS);
+
+	c = clk_get_sys("tegra-dma", NULL);
+	if (IS_ERR(c)) {
+		pr_err("Unable to get clock for APB DMA\n");
+		ret = PTR_ERR(c);
+		goto fail;
+	}
+	ret = clk_enable(c);
+	if (ret != 0) {
+		pr_err("Unable to enable clock for APB DMA\n");
+		goto fail;
+	}
 
 	addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
 	writel(GEN_ENABLE, addr + APB_DMA_GEN);
@@ -653,18 +702,9 @@ int __init tegra_dma_init(void)
 	writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX),
 	       addr + APB_DMA_IRQ_MASK_SET);
 
-	memset(channel_usage, 0, sizeof(channel_usage));
-	memset(dma_channels, 0, sizeof(dma_channels));
-
-	/* Reserve all the channels we are not supposed to touch */
-	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++)
-		__set_bit(i, channel_usage);
-
 	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
 		struct tegra_dma_channel *ch = &dma_channels[i];
 
-		__clear_bit(i, channel_usage);
-
 		ch->id = i;
 		snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i);
 
@@ -673,7 +713,6 @@ int __init tegra_dma_init(void)
 
 		spin_lock_init(&ch->lock);
 		INIT_LIST_HEAD(&ch->list);
-		tegra_dma_init_hw(ch);
 
 		irq = INT_APB_DMA_CH0 + i;
 		ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
@@ -684,14 +723,15 @@ int __init tegra_dma_init(void)
 			goto fail;
 		}
 		ch->irq = irq;
+
+		__clear_bit(i, channel_usage);
 	}
 	/* mark the shared channel allocated */
 	__set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage);
 
-	for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++)
-		__set_bit(i, channel_usage);
+	tegra_dma_initialized = true;
 
-	return ret;
+	return 0;
 fail:
 	writel(0, addr + APB_DMA_GEN);
 	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
@@ -701,6 +741,7 @@ fail:
 	}
 	return ret;
 }
+postcore_initcall(tegra_dma_init);
 
 #ifdef CONFIG_PM
 static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3];
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c
index ad80488..12090a2 100644
--- a/arch/arm/mach-tegra/gpio.c
+++ b/arch/arm/mach-tegra/gpio.c
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 
 #include <mach/iomap.h>
+#include <mach/suspend.h>
 
 #define GPIO_BANK(x)		((x) >> 5)
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
@@ -380,6 +381,20 @@ static int __init tegra_gpio_init(void)
 
 postcore_initcall(tegra_gpio_init);
 
+void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		int gpio = table[i].gpio;
+
+		if (table[i].enable)
+			tegra_gpio_enable(gpio);
+		else
+			tegra_gpio_disable(gpio);
+	}
+}
+
 #ifdef	CONFIG_DEBUG_FS
 
 #include <linux/debugfs.h>
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index a217f68..c8baf8f 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -25,9 +25,7 @@ struct clk;
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
-int clk_enable_cansleep(struct clk *clk);
-void clk_disable_cansleep(struct clk *clk);
-int clk_set_rate_cansleep(struct clk *clk, unsigned long rate);
-int clk_set_parent_cansleep(struct clk *clk, struct clk *parent);
+unsigned long clk_get_rate_all_locked(struct clk *c);
+void tegra_sdmmc_tap_delay(struct clk *c, int delay);
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S
index a0e7c12..e0ebe65 100644
--- a/arch/arm/mach-tegra/include/mach/debug-macro.S
+++ b/arch/arm/mach-tegra/include/mach/debug-macro.S
@@ -19,30 +19,15 @@
  */
 
 #include <mach/io.h>
+#include <mach/iomap.h>
 
 	.macro  addruart, rp, rv
         ldr     \rp, =IO_APB_PHYS       @ physical
         ldr     \rv, =IO_APB_VIRT        @ virtual
-#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
-#error "A debug UART must be selected in the kernel config to use DEBUG_LL"
-#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
-        orr     \rp, \rp, #0x6000
-        orr     \rv, \rv, #0x6000
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-        orr     \rp, \rp, #0x6000
-	orr	\rp, \rp, #0x40
-        orr     \rv, \rv, #0x6000
-	orr	\rv, \rv, #0x40
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-        orr     \rp, \rp, #0x6200
-        orr     \rv, \rv, #0x6200
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-        orr     \rp, \rp, #0x6300
-        orr     \rv, \rv, #0x6300
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-        orr     \rp, \rp, #0x6400
-        orr     \rv, \rv, #0x6400
-#endif
+	orr	\rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
+	orr	\rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
+	orr	\rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF)
+	orr	\rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
 	.endm
 
 #define UART_SHIFT	2
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h
index e31f486..196f114 100644
--- a/arch/arm/mach-tegra/include/mach/gpio.h
+++ b/arch/arm/mach-tegra/include/mach/gpio.h
@@ -20,6 +20,7 @@
 #ifndef __MACH_TEGRA_GPIO_H
 #define __MACH_TEGRA_GPIO_H
 
+#include <linux/init.h>
 #include <mach/irqs.h>
 
 #define TEGRA_NR_GPIOS		INT_GPIO_NR
@@ -31,7 +32,7 @@
 #define gpio_cansleep		__gpio_cansleep
 
 #define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
-#define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE)
+#define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE)
 
 static inline int gpio_to_irq(unsigned int gpio)
 {
@@ -47,6 +48,12 @@ static inline int irq_to_gpio(unsigned int irq)
 	return -EINVAL;
 }
 
+struct tegra_gpio_table {
+	int	gpio;	/* GPIO number */
+	bool	enable;	/* Enable for GPIO at init? */
+};
+
+void tegra_gpio_config(struct tegra_gpio_table *table, int num);
 void tegra_gpio_enable(int gpio);
 void tegra_gpio_disable(int gpio);
 
diff --git a/arch/arm/mach-tegra/include/mach/harmony_audio.h b/arch/arm/mach-tegra/include/mach/harmony_audio.h
new file mode 100644
index 0000000..af08650
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/harmony_audio.h
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-tegra/include/mach/harmony_audio.h
+ *
+ * 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.
+ *
+ */
+
+struct harmony_audio_platform_data {
+	int gpio_spkr_en;
+	int gpio_hp_det;
+	int gpio_int_mic_en;
+	int gpio_ext_mic_en;
+};
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h
index 44a4f4b..691cdab 100644
--- a/arch/arm/mach-tegra/include/mach/iomap.h
+++ b/arch/arm/mach-tegra/include/mach/iomap.h
@@ -26,6 +26,9 @@
 #define TEGRA_IRAM_BASE			0x40000000
 #define TEGRA_IRAM_SIZE			SZ_256K
 
+#define TEGRA_HOST1X_BASE		0x50000000
+#define TEGRA_HOST1X_SIZE		0x24000
+
 #define TEGRA_ARM_PERIF_BASE		0x50040000
 #define TEGRA_ARM_PERIF_SIZE		SZ_8K
 
@@ -35,12 +38,30 @@
 #define TEGRA_ARM_INT_DIST_BASE		0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE		SZ_4K
 
+#define TEGRA_MPE_BASE			0x54040000
+#define TEGRA_MPE_SIZE			SZ_256K
+
+#define TEGRA_VI_BASE			0x54080000
+#define TEGRA_VI_SIZE			SZ_256K
+
+#define TEGRA_ISP_BASE			0x54100000
+#define TEGRA_ISP_SIZE			SZ_256K
+
 #define TEGRA_DISPLAY_BASE		0x54200000
 #define TEGRA_DISPLAY_SIZE		SZ_256K
 
 #define TEGRA_DISPLAY2_BASE		0x54240000
 #define TEGRA_DISPLAY2_SIZE		SZ_256K
 
+#define TEGRA_HDMI_BASE			0x54280000
+#define TEGRA_HDMI_SIZE			SZ_256K
+
+#define TEGRA_GART_BASE			0x58000000
+#define TEGRA_GART_SIZE			SZ_32M
+
+#define TEGRA_RES_SEMA_BASE		0x60001000
+#define TEGRA_RES_SEMA_SIZE		SZ_4K
+
 #define TEGRA_PRIMARY_ICTLR_BASE	0x60004000
 #define TEGRA_PRIMARY_ICTLR_SIZE	SZ_64
 
@@ -140,6 +161,18 @@
 #define TEGRA_PWFM_BASE			0x7000A000
 #define TEGRA_PWFM_SIZE			SZ_256
 
+#define TEGRA_PWFM0_BASE		0x7000A000
+#define TEGRA_PWFM0_SIZE		4
+
+#define TEGRA_PWFM1_BASE		0x7000A010
+#define TEGRA_PWFM1_SIZE		4
+
+#define TEGRA_PWFM2_BASE		0x7000A020
+#define TEGRA_PWFM2_SIZE		4
+
+#define TEGRA_PWFM3_BASE		0x7000A030
+#define TEGRA_PWFM3_SIZE		4
+
 #define TEGRA_MIPI_BASE			0x7000B000
 #define TEGRA_MIPI_SIZE			SZ_256
 
@@ -221,4 +254,18 @@
 #define TEGRA_SDMMC4_BASE		0xC8000600
 #define TEGRA_SDMMC4_SIZE		SZ_512
 
+#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
+# define TEGRA_DEBUG_UART_BASE 0
+#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
+#endif
+
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h
index 71bbf34..73265af 100644
--- a/arch/arm/mach-tegra/include/mach/irqs.h
+++ b/arch/arm/mach-tegra/include/mach/irqs.h
@@ -88,7 +88,7 @@
 #define INT_SYS_STATS_MON		(INT_SEC_BASE + 22)
 #define INT_GPIO5			(INT_SEC_BASE + 23)
 #define INT_CPU0_PMU_INTR		(INT_SEC_BASE + 24)
-#define INT_CPU2_PMU_INTR		(INT_SEC_BASE + 25)
+#define INT_CPU1_PMU_INTR		(INT_SEC_BASE + 25)
 #define INT_SEC_RES_26			(INT_SEC_BASE + 26)
 #define INT_S_LINK1			(INT_SEC_BASE + 27)
 #define INT_APB_DMA_COP			(INT_SEC_BASE + 28)
@@ -166,10 +166,18 @@
 #define INT_QUAD_RES_30			(INT_QUAD_BASE + 30)
 #define INT_QUAD_RES_31			(INT_QUAD_BASE + 31)
 
-#define INT_GPIO_BASE			(INT_QUAD_BASE + 32)
+#define INT_MAIN_NR			(INT_QUAD_BASE + 32 - INT_PRI_BASE)
+
+#define INT_GPIO_BASE			(INT_PRI_BASE + INT_MAIN_NR)
+
 #define INT_GPIO_NR			(28 * 8)
 
-#define NR_IRQS				(INT_GPIO_BASE + INT_GPIO_NR)
+#define TEGRA_NR_IRQS			(INT_GPIO_BASE + INT_GPIO_NR)
+
+#define INT_BOARD_BASE			TEGRA_NR_IRQS
+#define NR_BOARD_IRQS			32
+
+#define NR_IRQS				(INT_BOARD_BASE + NR_BOARD_IRQS)
 #endif
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h
index db1eb3d..d898c0e 100644
--- a/arch/arm/mach-tegra/include/mach/legacy_irq.h
+++ b/arch/arm/mach-tegra/include/mach/legacy_irq.h
@@ -27,5 +27,9 @@ int tegra_legacy_force_irq_status(unsigned int irq);
 void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
 unsigned long tegra_legacy_vfiq(int nr);
 unsigned long tegra_legacy_class(int nr);
+int tegra_legacy_irq_set_wake(int irq, int enable);
+void tegra_legacy_irq_set_lp1_wake_mask(void);
+void tegra_legacy_irq_restore_mask(void);
+void tegra_init_legacy_irq(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/memory.h
index 6151bab..537db3a 100644
--- a/arch/arm/mach-tegra/include/mach/memory.h
+++ b/arch/arm/mach-tegra/include/mach/memory.h
@@ -22,7 +22,7 @@
 #define __MACH_TEGRA_MEMORY_H
 
 /* physical offset of RAM */
-#define PHYS_OFFSET		UL(0)
+#define PLAT_PHYS_OFFSET		UL(0)
 
 #endif
 
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-t2.h b/arch/arm/mach-tegra/include/mach/pinmux-t2.h
index e5b9d74..4c26263 100644
--- a/arch/arm/mach-tegra/include/mach/pinmux-t2.h
+++ b/arch/arm/mach-tegra/include/mach/pinmux-t2.h
@@ -167,6 +167,16 @@ enum tegra_drive_pingroup {
 	TEGRA_DRIVE_PINGROUP_XM2D,
 	TEGRA_DRIVE_PINGROUP_XM2CLK,
 	TEGRA_DRIVE_PINGROUP_MEMCOMP,
+	TEGRA_DRIVE_PINGROUP_SDIO1,
+	TEGRA_DRIVE_PINGROUP_CRT,
+	TEGRA_DRIVE_PINGROUP_DDC,
+	TEGRA_DRIVE_PINGROUP_GMA,
+	TEGRA_DRIVE_PINGROUP_GMB,
+	TEGRA_DRIVE_PINGROUP_GMC,
+	TEGRA_DRIVE_PINGROUP_GMD,
+	TEGRA_DRIVE_PINGROUP_GME,
+	TEGRA_DRIVE_PINGROUP_OWR,
+	TEGRA_DRIVE_PINGROUP_UAD,
 	TEGRA_MAX_DRIVE_PINGROUP,
 };
 
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h
new file mode 100644
index 0000000..401d1b7
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/powergate.h
@@ -0,0 +1,40 @@
+/*
+ * 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_
+
+#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_NUM_POWERGATE	7
+
+int tegra_powergate_power_on(int id);
+int tegra_powergate_power_off(int id);
+bool tegra_powergate_is_powered(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/suspend.h b/arch/arm/mach-tegra/include/mach/suspend.h
new file mode 100644
index 0000000..5af8715
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/suspend.h
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-tegra/include/mach/suspend.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#ifndef _MACH_TEGRA_SUSPEND_H_
+#define _MACH_TEGRA_SUSPEND_H_
+
+void tegra_pinmux_suspend(void);
+void tegra_irq_suspend(void);
+void tegra_gpio_suspend(void);
+void tegra_clk_suspend(void);
+void tegra_dma_suspend(void);
+void tegra_timer_suspend(void);
+
+void tegra_pinmux_resume(void);
+void tegra_irq_resume(void);
+void tegra_gpio_resume(void);
+void tegra_clk_resume(void);
+void tegra_dma_resume(void);
+void tegra_timer_resume(void);
+
+#endif /* _MACH_TEGRA_SUSPEND_H_ */
diff --git a/arch/arm/mach-tegra/include/mach/system.h b/arch/arm/mach-tegra/include/mach/system.h
index 84d5d46..d0183d8 100644
--- a/arch/arm/mach-tegra/include/mach/system.h
+++ b/arch/arm/mach-tegra/include/mach/system.h
@@ -24,16 +24,10 @@
 #include <mach/hardware.h>
 #include <mach/iomap.h>
 
-static inline void arch_idle(void)
-{
-}
+extern void (*arch_reset)(char mode, const char *cmd);
 
-static inline void arch_reset(char mode, const char *cmd)
+static inline void arch_idle(void)
 {
-	void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
-	u32 reg = readl(reset);
-	reg |= 0x04;
-	writel(reg, reset);
 }
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h
index 6c4dd81..4e83237 100644
--- a/arch/arm/mach-tegra/include/mach/uncompress.h
+++ b/arch/arm/mach-tegra/include/mach/uncompress.h
@@ -26,23 +26,9 @@
 
 #include <mach/iomap.h>
 
-#if defined(CONFIG_TEGRA_DEBUG_UARTA)
-#define DEBUG_UART_BASE TEGRA_UARTA_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-#define DEBUG_UART_BASE TEGRA_UARTB_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-#define DEBUG_UART_BASE TEGRA_UARTC_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-#define DEBUG_UART_BASE TEGRA_UARTD_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-#define DEBUG_UART_BASE TEGRA_UARTE_BASE
-#else
-#define DEBUG_UART_BASE NULL
-#endif
-
 static void putc(int c)
 {
-	volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+	volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
 	int shift = 2;
 
 	if (uart == NULL)
@@ -59,7 +45,7 @@ static inline void flush(void)
 
 static inline void arch_decomp_setup(void)
 {
-	volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+	volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
 	int shift = 2;
 
 	if (uart == NULL)
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h
new file mode 100644
index 0000000..d4b8f9e
--- /dev/null
+++ b/arch/arm/mach-tegra/include/mach/usb_phy.h
@@ -0,0 +1,86 @@
+/*
+ * arch/arm/mach-tegra/include/mach/usb_phy.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef __MACH_USB_PHY_H
+#define __MACH_USB_PHY_H
+
+#include <linux/clk.h>
+#include <linux/usb/otg.h>
+
+struct tegra_utmip_config {
+	u8 hssync_start_delay;
+	u8 elastic_limit;
+	u8 idle_wait_delay;
+	u8 term_range_adj;
+	u8 xcvr_setup;
+	u8 xcvr_lsfslew;
+	u8 xcvr_lsrslew;
+};
+
+struct tegra_ulpi_config {
+	int reset_gpio;
+	const char *clk;
+};
+
+enum tegra_usb_phy_port_speed {
+	TEGRA_USB_PHY_PORT_SPEED_FULL = 0,
+	TEGRA_USB_PHY_PORT_SPEED_LOW,
+	TEGRA_USB_PHY_PORT_SPEED_HIGH,
+};
+
+enum tegra_usb_phy_mode {
+	TEGRA_USB_PHY_MODE_DEVICE,
+	TEGRA_USB_PHY_MODE_HOST,
+};
+
+struct tegra_xtal_freq;
+
+struct tegra_usb_phy {
+	int instance;
+	const struct tegra_xtal_freq *freq;
+	void __iomem *regs;
+	void __iomem *pad_regs;
+	struct clk *clk;
+	struct clk *pll_u;
+	struct clk *pad_clk;
+	enum tegra_usb_phy_mode mode;
+	void *config;
+	struct otg_transceiver *ulpi;
+};
+
+struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
+			void *config, enum tegra_usb_phy_mode phy_mode);
+
+int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_power_off(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_preresume(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_postresume(struct tegra_usb_phy *phy);
+
+void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
+				 enum tegra_usb_phy_port_speed port_speed);
+
+void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_close(struct tegra_usb_phy *phy);
+
+#endif /* __MACH_USB_PHY_H */
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 17c74d2..dfbc219 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -26,73 +27,119 @@
 #include <asm/hardware/gic.h>
 
 #include <mach/iomap.h>
+#include <mach/legacy_irq.h>
+#include <mach/suspend.h>
 
 #include "board.h"
 
-#define INT_SYS_NR	(INT_GPIO_BASE - INT_PRI_BASE)
-#define INT_SYS_SZ	(INT_SEC_BASE - INT_PRI_BASE)
-#define PPI_NR		((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+#define PMC_CTRL		0x0
+#define PMC_CTRL_LATCH_WAKEUPS	(1 << 5)
+#define PMC_WAKE_MASK		0xc
+#define PMC_WAKE_LEVEL		0x10
+#define PMC_WAKE_STATUS		0x14
+#define PMC_SW_WAKE_STATUS	0x18
+#define PMC_DPD_SAMPLE		0x20
 
-#define APBDMA_IRQ_STA_CPU  0x14
-#define APBDMA_IRQ_MASK_SET 0x20
-#define APBDMA_IRQ_MASK_CLR 0x24
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
 
-#define ICTLR_CPU_IER		0x20
-#define ICTLR_CPU_IER_SET	0x24
-#define ICTLR_CPU_IER_CLR	0x28
-#define ICTLR_CPU_IEP_CLASS	0x2c
-#define ICTLR_COP_IER		0x30
-#define ICTLR_COP_IER_SET	0x34
-#define ICTLR_COP_IER_CLR	0x38
-#define ICTLR_COP_IEP_CLASS	0x3c
+static u32 tegra_lp0_wake_enb;
+static u32 tegra_lp0_wake_level;
+static u32 tegra_lp0_wake_level_any;
 
 static void (*tegra_gic_mask_irq)(struct irq_data *d);
 static void (*tegra_gic_unmask_irq)(struct irq_data *d);
+static void (*tegra_gic_ack_irq)(struct irq_data *d);
 
-#define irq_to_ictlr(irq) (((irq) - 32) >> 5)
-static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
-#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100)
+/* ensures that sufficient time is passed for a register write to
+ * serialize into the 32KHz domain */
+static void pmc_32kwritel(u32 val, unsigned long offs)
+{
+	writel(val, pmc + offs);
+	udelay(130);
+}
+
+int tegra_set_lp1_wake(int irq, int enable)
+{
+	return tegra_legacy_irq_set_wake(irq, enable);
+}
+
+void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
+{
+	u32 temp;
+	u32 status;
+	u32 lvl;
+
+	wake_level &= wake_enb;
+	wake_any &= wake_enb;
+
+	wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb);
+	wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb);
+
+	wake_enb |= tegra_lp0_wake_enb;
+
+	pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
+	temp = readl(pmc + PMC_CTRL);
+	temp |= PMC_CTRL_LATCH_WAKEUPS;
+	pmc_32kwritel(temp, PMC_CTRL);
+	temp &= ~PMC_CTRL_LATCH_WAKEUPS;
+	pmc_32kwritel(temp, PMC_CTRL);
+	status = readl(pmc + PMC_SW_WAKE_STATUS);
+	lvl = readl(pmc + PMC_WAKE_LEVEL);
+
+	/* flip the wakeup trigger for any-edge triggered pads
+	 * which are currently asserting as wakeups */
+	lvl ^= status;
+	lvl &= wake_any;
+
+	wake_level |= lvl;
+
+	writel(wake_level, pmc + PMC_WAKE_LEVEL);
+	/* Enable DPD sample to trigger sampling pads data and direction
+	 * in which pad will be driven during lp0 mode*/
+	writel(0x1, pmc + PMC_DPD_SAMPLE);
+
+	writel(wake_enb, pmc + PMC_WAKE_MASK);
+}
 
 static void tegra_mask(struct irq_data *d)
 {
-	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
 	tegra_gic_mask_irq(d);
-	writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR);
+	tegra_legacy_mask_irq(d->irq);
 }
 
 static void tegra_unmask(struct irq_data *d)
 {
-	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
 	tegra_gic_unmask_irq(d);
-	writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET);
+	tegra_legacy_unmask_irq(d->irq);
 }
 
-#ifdef CONFIG_PM
+static void tegra_ack(struct irq_data *d)
+{
+	tegra_legacy_force_irq_clr(d->irq);
+	tegra_gic_ack_irq(d);
+}
 
-static int tegra_set_wake(struct irq_data *d, unsigned int on)
+static int tegra_retrigger(struct irq_data *d)
 {
-	return 0;
+	tegra_legacy_force_irq_set(d->irq);
+	return 1;
 }
-#endif
 
 static struct irq_chip tegra_irq = {
-	.name		= "PPI",
-	.irq_mask	= tegra_mask,
-	.irq_unmask	= tegra_unmask,
-#ifdef CONFIG_PM
-	.irq_set_wake	= tegra_set_wake,
-#endif
+	.name			= "PPI",
+	.irq_ack		= tegra_ack,
+	.irq_mask		= tegra_mask,
+	.irq_unmask		= tegra_unmask,
+	.irq_retrigger		= tegra_retrigger,
 };
 
 void __init tegra_init_irq(void)
 {
 	struct irq_chip *gic;
 	unsigned int i;
+	int irq;
 
-	for (i = 0; i < PPI_NR; i++) {
-		writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR);
-		writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
-	}
+	tegra_init_legacy_irq();
 
 	gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
 		 IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
@@ -100,72 +147,15 @@ void __init tegra_init_irq(void)
 	gic = get_irq_chip(29);
 	tegra_gic_unmask_irq = gic->irq_unmask;
 	tegra_gic_mask_irq = gic->irq_mask;
-	tegra_irq.irq_ack = gic->irq_ack;
+	tegra_gic_ack_irq = gic->irq_ack;
 #ifdef CONFIG_SMP
 	tegra_irq.irq_set_affinity = gic->irq_set_affinity;
 #endif
 
-	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
-		set_irq_chip(i, &tegra_irq);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
+	for (i = 0; i < INT_MAIN_NR; i++) {
+		irq = INT_PRI_BASE + i;
+		set_irq_chip(irq, &tegra_irq);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
 	}
 }
-
-#ifdef CONFIG_PM
-static u32 cop_ier[PPI_NR];
-static u32 cpu_ier[PPI_NR];
-static u32 cpu_iep[PPI_NR];
-
-void tegra_irq_suspend(void)
-{
-	unsigned long flags;
-	int i;
-
-	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-		if (!desc)
-			continue;
-		if (desc->status & IRQ_WAKEUP) {
-			pr_debug("irq %d is wakeup\n", i);
-			continue;
-		}
-		disable_irq(i);
-	}
-
-	local_irq_save(flags);
-	for (i = 0; i < PPI_NR; i++) {
-		void __iomem *ictlr = ictlr_to_virt(i);
-		cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
-		cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
-		cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
-		writel(~0, ictlr + ICTLR_COP_IER_CLR);
-	}
-	local_irq_restore(flags);
-}
-
-void tegra_irq_resume(void)
-{
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	for (i = 0; i < PPI_NR; i++) {
-		void __iomem *ictlr = ictlr_to_virt(i);
-		writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
-		writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-		writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
-		writel(0, ictlr + ICTLR_COP_IEP_CLASS);
-		writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
-		writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
-	}
-	local_irq_restore(flags);
-
-	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-		if (!desc || (desc->status & IRQ_WAKEUP))
-			continue;
-		enable_irq(i);
-	}
-}
-#endif
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c
index 7cc8601..38eb719 100644
--- a/arch/arm/mach-tegra/legacy_irq.c
+++ b/arch/arm/mach-tegra/legacy_irq.c
@@ -18,17 +18,30 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <mach/iomap.h>
+#include <mach/irqs.h>
 #include <mach/legacy_irq.h>
 
-#define ICTLR_CPU_IER		0x20
-#define ICTLR_CPU_IER_SET	0x24
-#define ICTLR_CPU_IER_CLR	0x28
-#define ICTLR_CPU_IEP_CLASS	0x2C
+#define INT_SYS_NR	(INT_GPIO_BASE - INT_PRI_BASE)
+#define INT_SYS_SZ	(INT_SEC_BASE - INT_PRI_BASE)
+#define PPI_NR		((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+
 #define ICTLR_CPU_IEP_VFIQ	0x08
 #define ICTLR_CPU_IEP_FIR	0x14
 #define ICTLR_CPU_IEP_FIR_SET	0x18
 #define ICTLR_CPU_IEP_FIR_CLR	0x1c
 
+#define ICTLR_CPU_IER		0x20
+#define ICTLR_CPU_IER_SET	0x24
+#define ICTLR_CPU_IER_CLR	0x28
+#define ICTLR_CPU_IEP_CLASS	0x2C
+
+#define ICTLR_COP_IER		0x30
+#define ICTLR_COP_IER_SET	0x34
+#define ICTLR_COP_IER_CLR	0x38
+#define ICTLR_COP_IEP_CLASS	0x3c
+
+#define NUM_ICTLRS 4
+
 static void __iomem *ictlr_reg_base[] = {
 	IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
 	IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
@@ -36,6 +49,9 @@ static void __iomem *ictlr_reg_base[] = {
 	IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
 };
 
+static u32 tegra_legacy_wake_mask[4];
+static u32 tegra_legacy_saved_mask[4];
+
 /* When going into deep sleep, the CPU is powered down, taking the GIC with it
    In order to wake, the wake interrupts need to be enabled in the legacy
    interrupt controller. */
@@ -112,3 +128,88 @@ unsigned long tegra_legacy_class(int nr)
 	base = ictlr_reg_base[nr];
 	return readl(base + ICTLR_CPU_IEP_CLASS);
 }
+
+int tegra_legacy_irq_set_wake(int irq, int enable)
+{
+	irq -= 32;
+	if (enable)
+		tegra_legacy_wake_mask[irq >> 5] |= 1 << (irq & 31);
+	else
+		tegra_legacy_wake_mask[irq >> 5] &= ~(1 << (irq & 31));
+
+	return 0;
+}
+
+void tegra_legacy_irq_set_lp1_wake_mask(void)
+{
+	void __iomem *base;
+	int i;
+
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		base = ictlr_reg_base[i];
+		tegra_legacy_saved_mask[i] = readl(base + ICTLR_CPU_IER);
+		writel(tegra_legacy_wake_mask[i], base + ICTLR_CPU_IER);
+	}
+}
+
+void tegra_legacy_irq_restore_mask(void)
+{
+	void __iomem *base;
+	int i;
+
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		base = ictlr_reg_base[i];
+		writel(tegra_legacy_saved_mask[i], base + ICTLR_CPU_IER);
+	}
+}
+
+void tegra_init_legacy_irq(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		void __iomem *ictlr = ictlr_reg_base[i];
+		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
+		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
+	}
+}
+
+#ifdef CONFIG_PM
+static u32 cop_ier[NUM_ICTLRS];
+static u32 cpu_ier[NUM_ICTLRS];
+static u32 cpu_iep[NUM_ICTLRS];
+
+void tegra_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];
+		cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
+		cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
+		cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
+		writel(~0, ictlr + ICTLR_COP_IER_CLR);
+	}
+	local_irq_restore(flags);
+}
+
+void tegra_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(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+		writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+		writel(0, ictlr + ICTLR_COP_IEP_CLASS);
+		writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+	}
+	local_irq_restore(flags);
+}
+#endif
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index 53f5fa3..2941212 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -39,6 +39,7 @@
 #include <mach/pinmux.h>
 #include <mach/iomap.h>
 #include <mach/clk.h>
+#include <mach/powergate.h>
 
 /* register definitions */
 #define AFI_OFFSET	0x3800
@@ -682,24 +683,41 @@ static void tegra_pcie_xclk_clamp(bool clamp)
 	pmc_writel(reg, PMC_SCRATCH42);
 }
 
-static int tegra_pcie_power_on(void)
+static void tegra_pcie_power_off(void)
 {
-	tegra_pcie_xclk_clamp(true);
 	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
-	tegra_pcie_xclk_clamp(false);
+	tegra_periph_reset_assert(tegra_pcie.afi_clk);
+	tegra_periph_reset_assert(tegra_pcie.pex_clk);
 
-	clk_enable(tegra_pcie.afi_clk);
-	clk_enable(tegra_pcie.pex_clk);
-	return clk_enable(tegra_pcie.pll_e);
+	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+	tegra_pcie_xclk_clamp(true);
 }
 
-static void tegra_pcie_power_off(void)
+static int tegra_pcie_power_regate(void)
 {
+	int err;
+
+	tegra_pcie_power_off();
+
+	tegra_pcie_xclk_clamp(true);
+
 	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
 	tegra_periph_reset_assert(tegra_pcie.afi_clk);
-	tegra_periph_reset_assert(tegra_pcie.pex_clk);
 
-	tegra_pcie_xclk_clamp(true);
+	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
+						tegra_pcie.pex_clk);
+	if (err) {
+		pr_err("PCIE: powerup sequence failed: %d\n", err);
+		return err;
+	}
+
+	tegra_periph_reset_deassert(tegra_pcie.afi_clk);
+
+	tegra_pcie_xclk_clamp(false);
+
+	clk_enable(tegra_pcie.afi_clk);
+	clk_enable(tegra_pcie.pex_clk);
+	return clk_enable(tegra_pcie.pll_e);
 }
 
 static int tegra_pcie_clocks_get(void)
@@ -759,7 +777,7 @@ static int __init tegra_pcie_get_resources(void)
 		return err;
 	}
 
-	err = tegra_pcie_power_on();
+	err = tegra_pcie_power_regate();
 	if (err) {
 		pr_err("PCIE: failed to power up: %d\n", err);
 		goto err_pwr_on;
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
index a6ea34e..a475367 100644
--- a/arch/arm/mach-tegra/pinmux-t2-tables.c
+++ b/arch/arm/mach-tegra/pinmux-t2-tables.c
@@ -29,6 +29,7 @@
 
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
+#include <mach/suspend.h>
 
 #define DRIVE_PINGROUP(pg_name, r)				\
 	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
@@ -65,6 +66,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE
 	DRIVE_PINGROUP(XM2D,		0x8cc),
 	DRIVE_PINGROUP(XM2CLK,		0x8d0),
 	DRIVE_PINGROUP(MEMCOMP,		0x8d4),
+	DRIVE_PINGROUP(SDIO1,		0x8e0),
+	DRIVE_PINGROUP(CRT,		0x8ec),
+	DRIVE_PINGROUP(DDC,		0x8f0),
+	DRIVE_PINGROUP(GMA,		0x8f4),
+	DRIVE_PINGROUP(GMB,		0x8f8),
+	DRIVE_PINGROUP(GMC,		0x8fc),
+	DRIVE_PINGROUP(GMD,		0x900),
+	DRIVE_PINGROUP(GME,		0x904),
+	DRIVE_PINGROUP(OWR,		0x908),
+	DRIVE_PINGROUP(UAD,		0x90c),
 };
 
 #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe,		\
@@ -216,7 +227,8 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
 #define PULLUPDOWN_REG_NUM     5
 
 static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
-		     PULLUPDOWN_REG_NUM];
+		      PULLUPDOWN_REG_NUM +
+		      ARRAY_SIZE(tegra_soc_drive_pingroups)];
 
 static inline unsigned long pg_readl(unsigned long offset)
 {
@@ -233,14 +245,17 @@ void tegra_pinmux_suspend(void)
 	unsigned int i;
 	u32 *ctx = pinmux_reg;
 
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
-
 	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
 		*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
 
 	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
 		*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
+
+	for (i = 0; i < TRISTATE_REG_NUM; i++)
+		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
+		*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
 }
 
 void tegra_pinmux_resume(void)
@@ -256,5 +271,8 @@ void tegra_pinmux_resume(void)
 
 	for (i = 0; i < TRISTATE_REG_NUM; i++)
 		pg_writel(*ctx++, TRISTATE_REG_A + i*4);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
+		pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
 }
 #endif
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
new file mode 100644
index 0000000..3cee9aa
--- /dev/null
+++ b/arch/arm/mach-tegra/powergate.c
@@ -0,0 +1,212 @@
+/*
+ * drivers/powergate/tegra-powergate.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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <mach/clk.h>
+#include <mach/iomap.h>
+#include <mach/powergate.h>
+
+#define PWRGATE_TOGGLE		0x30
+#define  PWRGATE_TOGGLE_START	(1 << 8)
+
+#define REMOVE_CLAMPING		0x34
+
+#define PWRGATE_STATUS		0x38
+
+static DEFINE_SPINLOCK(tegra_powergate_lock);
+
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+
+static u32 pmc_read(unsigned long reg)
+{
+	return readl(pmc + reg);
+}
+
+static void pmc_write(u32 val, unsigned long reg)
+{
+	writel(val, pmc + reg);
+}
+
+static int tegra_powergate_set(int id, bool new_state)
+{
+	bool status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tegra_powergate_lock, flags);
+
+	status = pmc_read(PWRGATE_STATUS) & (1 << id);
+
+	if (status == new_state) {
+		spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+		return -EINVAL;
+	}
+
+	pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
+
+	spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+
+	return 0;
+}
+
+int tegra_powergate_power_on(int id)
+{
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	return tegra_powergate_set(id, true);
+}
+
+int tegra_powergate_power_off(int id)
+{
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	return tegra_powergate_set(id, false);
+}
+
+bool tegra_powergate_is_powered(int id)
+{
+	u32 status;
+
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	status = pmc_read(PWRGATE_STATUS) & (1 << id);
+	return !!status;
+}
+
+int tegra_powergate_remove_clamping(int id)
+{
+	u32 mask;
+
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	/*
+	 * Tegra 2 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);
+
+	pmc_write(mask, REMOVE_CLAMPING);
+
+	return 0;
+}
+
+/* Must be called with clk disabled, and returns with clk enabled */
+int tegra_powergate_sequence_power_up(int id, struct clk *clk)
+{
+	int ret;
+
+	tegra_periph_reset_assert(clk);
+
+	ret = tegra_powergate_power_on(id);
+	if (ret)
+		goto err_power;
+
+	ret = clk_enable(clk);
+	if (ret)
+		goto err_clk;
+
+	udelay(10);
+
+	ret = tegra_powergate_remove_clamping(id);
+	if (ret)
+		goto err_clamp;
+
+	udelay(10);
+	tegra_periph_reset_deassert(clk);
+
+	return 0;
+
+err_clamp:
+	clk_disable(clk);
+err_clk:
+	tegra_powergate_power_off(id);
+err_power:
+	return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static const char * const powergate_name[] = {
+	[TEGRA_POWERGATE_CPU]	= "cpu",
+	[TEGRA_POWERGATE_3D]	= "3d",
+	[TEGRA_POWERGATE_VENC]	= "venc",
+	[TEGRA_POWERGATE_VDEC]	= "vdec",
+	[TEGRA_POWERGATE_PCIE]	= "pcie",
+	[TEGRA_POWERGATE_L2]	= "l2",
+	[TEGRA_POWERGATE_MPE]	= "mpe",
+};
+
+static int powergate_show(struct seq_file *s, void *data)
+{
+	int i;
+
+	seq_printf(s, " powergate powered\n");
+	seq_printf(s, "------------------\n");
+
+	for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
+		seq_printf(s, " %9s %7s\n", powergate_name[i],
+			tegra_powergate_is_powered(i) ? "yes" : "no");
+	return 0;
+}
+
+static int powergate_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, powergate_show, inode->i_private);
+}
+
+static const struct file_operations powergate_fops = {
+	.open		= powergate_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init powergate_debugfs_init(void)
+{
+	struct dentry *d;
+	int err = -ENOMEM;
+
+	d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
+		&powergate_fops);
+	if (!d)
+		return -ENOMEM;
+
+	return err;
+}
+
+late_initcall(powergate_debugfs_init);
+
+#endif
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index f0dae6d..6d7c4ee 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -23,14 +23,15 @@
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/hrtimer.h>
 #include <linux/clkdev.h>
+#include <linux/clk.h>
 
 #include <mach/iomap.h>
+#include <mach/suspend.h>
 
 #include "clock.h"
 #include "fuse.h"
-#include "tegra2_dvfs.h"
+#include "tegra2_emc.h"
 
 #define RST_DEVICES			0x004
 #define RST_DEVICES_SET			0x300
@@ -51,7 +52,7 @@
 #define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
 #define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
 #define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
-#define OSC_CTRL_MASK			0x3f2
+#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
 
 #define OSC_FREQ_DET			0x58
 #define OSC_FREQ_DET_TRIG		(1<<31)
@@ -73,12 +74,15 @@
 #define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
 #define PERIPH_CLK_SOURCE_DIV_SHIFT	0
 
+#define SDMMC_CLK_INT_FB_SEL		(1 << 23)
+#define SDMMC_CLK_INT_FB_DLY_SHIFT	16
+#define SDMMC_CLK_INT_FB_DLY_MASK	(0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
+
 #define PLL_BASE			0x0
 #define PLL_BASE_BYPASS			(1<<31)
 #define PLL_BASE_ENABLE			(1<<30)
 #define PLL_BASE_REF_ENABLE		(1<<29)
 #define PLL_BASE_OVERRIDE		(1<<28)
-#define PLL_BASE_LOCK			(1<<27)
 #define PLL_BASE_DIVP_MASK		(0x7<<20)
 #define PLL_BASE_DIVP_SHIFT		20
 #define PLL_BASE_DIVN_MASK		(0x3FF<<8)
@@ -93,7 +97,6 @@
 #define PLL_OUT_RESET_DISABLE		(1<<0)
 
 #define PLL_MISC(c)			(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
-#define PLL_MISC_LOCK_ENABLE(c)		(((c)->flags & PLLU) ? (1<<22) : (1<<18))
 
 #define PLL_MISC_DCCON_SHIFT		20
 #define PLL_MISC_CPCON_SHIFT		8
@@ -111,9 +114,9 @@
 
 #define PLLE_MISC_READY			(1 << 15)
 
-#define PERIPH_CLK_TO_ENB_REG(c)	((c->clk_num / 32) * 4)
-#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->clk_num / 32) * 8)
-#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->clk_num % 32))
+#define PERIPH_CLK_TO_ENB_REG(c)	((c->u.periph.clk_num / 32) * 4)
+#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->u.periph.clk_num / 32) * 8)
+#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->u.periph.clk_num % 32))
 
 #define SUPER_CLK_MUX			0x00
 #define SUPER_STATE_SHIFT		28
@@ -134,12 +137,42 @@
 #define BUS_CLK_DISABLE			(1<<3)
 #define BUS_CLK_DIV_MASK		0x3
 
+#define PMC_CTRL			0x0
+ #define PMC_CTRL_BLINK_ENB		(1 << 7)
+
+#define PMC_DPD_PADS_ORIDE		0x1c
+ #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
+
+#define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
+#define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
+#define PMC_BLINK_TIMER_ENB		(1 << 15)
+#define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
+#define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
+
 static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+/*
+ * Some clocks share a register with other clocks.  Any clock op that
+ * non-atomically modifies a register used by another clock must lock
+ * clock_register_lock first.
+ */
+static DEFINE_SPINLOCK(clock_register_lock);
+
+/*
+ * Some peripheral clocks share an enable bit, so refcount the enable bits
+ * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
+ */
+static int tegra_periph_clk_enable_refcount[3 * 32];
 
 #define clk_writel(value, reg) \
 	__raw_writel(value, (u32)reg_clk_base + (reg))
 #define clk_readl(reg) \
 	__raw_readl((u32)reg_clk_base + (reg))
+#define pmc_writel(value, reg) \
+	__raw_writel(value, (u32)reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+	__raw_readl((u32)reg_pmc_base + (reg))
 
 unsigned long clk_measure_input_freq(void)
 {
@@ -245,6 +278,18 @@ static struct clk_ops tegra_clk_m_ops = {
 	.disable	= tegra2_clk_m_disable,
 };
 
+void tegra2_periph_reset_assert(struct clk *c)
+{
+	BUG_ON(!c->ops->reset);
+	c->ops->reset(c, true);
+}
+
+void tegra2_periph_reset_deassert(struct clk *c)
+{
+	BUG_ON(!c->ops->reset);
+	c->ops->reset(c, false);
+}
+
 /* super clock functions */
 /* "super clocks" on tegra have two-stage muxes and a clock skipping
  * super divider.  We will ignore the clock skipping divider, since we
@@ -303,12 +348,12 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
 			val |= sel->value << shift;
 
 			if (c->refcnt)
-				clk_enable_locked(p);
+				clk_enable(p);
 
 			clk_writel(val, c->reg);
 
 			if (c->refcnt && c->parent)
-				clk_disable_locked(c->parent);
+				clk_disable(c->parent);
 
 			clk_reparent(c, p);
 			return 0;
@@ -317,11 +362,24 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
 	return -EINVAL;
 }
 
+/*
+ * Super clocks have "clock skippers" instead of dividers.  Dividing using
+ * a clock skipper does not allow the voltage to be scaled down, so instead
+ * adjust the rate of the parent clock.  This requires that the parent of a
+ * super clock have no other children, otherwise the rate will change
+ * underneath the other children.
+ */
+static int tegra2_super_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	return clk_set_rate(c->parent, rate);
+}
+
 static struct clk_ops tegra_super_ops = {
 	.init			= tegra2_super_clk_init,
 	.enable			= tegra2_super_clk_enable,
 	.disable		= tegra2_super_clk_disable,
 	.set_parent		= tegra2_super_clk_set_parent,
+	.set_rate		= tegra2_super_clk_set_rate,
 };
 
 /* virtual cpu clock functions */
@@ -351,25 +409,36 @@ static void tegra2_cpu_clk_disable(struct clk *c)
 static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	int ret;
-	ret = clk_set_parent_locked(c->parent, c->backup);
+	/*
+	 * Take an extra reference to the main pll so it doesn't turn
+	 * off when we move the cpu off of it
+	 */
+	clk_enable(c->u.cpu.main);
+
+	ret = clk_set_parent(c->parent, c->u.cpu.backup);
 	if (ret) {
-		pr_err("Failed to switch cpu to clock %s\n", c->backup->name);
-		return ret;
+		pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name);
+		goto out;
 	}
 
-	ret = clk_set_rate_locked(c->main, rate);
+	if (rate == clk_get_rate(c->u.cpu.backup))
+		goto out;
+
+	ret = clk_set_rate(c->u.cpu.main, rate);
 	if (ret) {
 		pr_err("Failed to change cpu pll to %lu\n", rate);
-		return ret;
+		goto out;
 	}
 
-	ret = clk_set_parent_locked(c->parent, c->main);
+	ret = clk_set_parent(c->parent, c->u.cpu.main);
 	if (ret) {
-		pr_err("Failed to switch cpu to clock %s\n", c->main->name);
-		return ret;
+		pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name);
+		goto out;
 	}
 
-	return 0;
+out:
+	clk_disable(c->u.cpu.main);
+	return ret;
 }
 
 static struct clk_ops tegra_cpu_ops = {
@@ -379,6 +448,20 @@ static struct clk_ops tegra_cpu_ops = {
 	.set_rate = tegra2_cpu_clk_set_rate,
 };
 
+/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
+ * reset the COP block (i.e. AVP) */
+static void tegra2_cop_clk_reset(struct clk *c, bool assert)
+{
+	unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+	pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
+	clk_writel(1 << 1, reg);
+}
+
+static struct clk_ops tegra_cop_ops = {
+	.reset    = tegra2_cop_clk_reset,
+};
+
 /* bus clock functions */
 static void tegra2_bus_clk_init(struct clk *c)
 {
@@ -390,24 +473,45 @@ static void tegra2_bus_clk_init(struct clk *c)
 
 static int tegra2_bus_clk_enable(struct clk *c)
 {
-	u32 val = clk_readl(c->reg);
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
 	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
 	clk_writel(val, c->reg);
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
 	return 0;
 }
 
 static void tegra2_bus_clk_disable(struct clk *c)
 {
-	u32 val = clk_readl(c->reg);
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
 	val |= BUS_CLK_DISABLE << c->reg_shift;
 	clk_writel(val, c->reg);
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
 }
 
 static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
 {
-	u32 val = clk_readl(c->reg);
-	unsigned long parent_rate = c->parent->rate;
+	u32 val;
+	unsigned long parent_rate = clk_get_rate(c->parent);
+	unsigned long flags;
+	int ret = -EINVAL;
 	int i;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
 	for (i = 1; i <= 4; i++) {
 		if (rate == parent_rate / i) {
 			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
@@ -415,10 +519,14 @@ static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
 			clk_writel(val, c->reg);
 			c->div = i;
 			c->mul = 1;
-			return 0;
+			ret = 0;
+			break;
 		}
 	}
-	return -EINVAL;
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
+	return ret;
 }
 
 static struct clk_ops tegra_bus_ops = {
@@ -428,24 +536,96 @@ static struct clk_ops tegra_bus_ops = {
 	.set_rate		= tegra2_bus_clk_set_rate,
 };
 
-/* PLL Functions */
-static int tegra2_pll_clk_wait_for_lock(struct clk *c)
+/* Blink output functions */
+
+static void tegra2_blink_clk_init(struct clk *c)
 {
-	ktime_t before;
+	u32 val;
 
-	before = ktime_get();
+	val = pmc_readl(PMC_CTRL);
+	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
+	c->mul = 1;
+	val = pmc_readl(c->reg);
+
+	if (val & PMC_BLINK_TIMER_ENB) {
+		unsigned int on_off;
+
+		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
+			PMC_BLINK_TIMER_DATA_ON_MASK;
+		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off += val;
+		/* each tick in the blink timer is 4 32KHz clocks */
+		c->div = on_off * 4;
+	} else {
+		c->div = 1;
+	}
+}
 
-	while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
-		if (ktime_us_delta(ktime_get(), before) > 5000) {
-			pr_err("Timed out waiting for lock bit on pll %s",
-				c->name);
-			return -1;
-		}
+static int tegra2_blink_clk_enable(struct clk *c)
+{
+	u32 val;
+
+	val = pmc_readl(PMC_DPD_PADS_ORIDE);
+	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+
+	val = pmc_readl(PMC_CTRL);
+	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+	return 0;
+}
+
+static void tegra2_blink_clk_disable(struct clk *c)
+{
+	u32 val;
+
+	val = pmc_readl(PMC_CTRL);
+	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+	val = pmc_readl(PMC_DPD_PADS_ORIDE);
+	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+}
+
+static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(c->parent);
+	if (rate >= parent_rate) {
+		c->div = 1;
+		pmc_writel(0, c->reg);
+	} else {
+		unsigned int on_off;
+		u32 val;
+
+		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
+		c->div = on_off * 8;
+
+		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
+			PMC_BLINK_TIMER_DATA_ON_SHIFT;
+		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val |= on_off;
+		val |= PMC_BLINK_TIMER_ENB;
+		pmc_writel(val, c->reg);
 	}
 
 	return 0;
 }
 
+static struct clk_ops tegra_blink_clk_ops = {
+	.init			= &tegra2_blink_clk_init,
+	.enable			= &tegra2_blink_clk_enable,
+	.disable		= &tegra2_blink_clk_disable,
+	.set_rate		= &tegra2_blink_clk_set_rate,
+};
+
+/* PLL Functions */
+static int tegra2_pll_clk_wait_for_lock(struct clk *c)
+{
+	udelay(c->u.pll.lock_delay);
+
+	return 0;
+}
+
 static void tegra2_pll_clk_init(struct clk *c)
 {
 	u32 val = clk_readl(c->reg + PLL_BASE);
@@ -479,10 +659,6 @@ static int tegra2_pll_clk_enable(struct clk *c)
 	val |= PLL_BASE_ENABLE;
 	clk_writel(val, c->reg + PLL_BASE);
 
-	val = clk_readl(c->reg + PLL_MISC(c));
-	val |= PLL_MISC_LOCK_ENABLE(c);
-	clk_writel(val, c->reg + PLL_MISC(c));
-
 	tegra2_pll_clk_wait_for_lock(c);
 
 	return 0;
@@ -502,13 +678,12 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	u32 val;
 	unsigned long input_rate;
-	const struct clk_pll_table *sel;
+	const struct clk_pll_freq_table *sel;
 
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-	BUG_ON(c->refcnt != 0);
 
-	input_rate = c->parent->rate;
-	for (sel = c->pll_table; sel->input_rate != 0; sel++) {
+	input_rate = clk_get_rate(c->parent);
+	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
 		if (sel->input_rate == input_rate && sel->output_rate == rate) {
 			c->mul = sel->n;
 			c->div = sel->m * sel->p;
@@ -620,9 +795,11 @@ static int tegra2_pll_div_clk_enable(struct clk *c)
 {
 	u32 val;
 	u32 new_val;
+	unsigned long flags;
 
 	pr_debug("%s: %s\n", __func__, c->name);
 	if (c->flags & DIV_U71) {
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		new_val = val >> c->reg_shift;
 		new_val &= 0xFFFF;
@@ -632,12 +809,15 @@ static int tegra2_pll_div_clk_enable(struct clk *c)
 		val &= ~(0xFFFF << c->reg_shift);
 		val |= new_val << c->reg_shift;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 		return 0;
 	} else if (c->flags & DIV_2) {
 		BUG_ON(!(c->flags & PLLD));
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		val &= ~PLLD_MISC_DIV_RST;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 		return 0;
 	}
 	return -EINVAL;
@@ -647,9 +827,11 @@ static void tegra2_pll_div_clk_disable(struct clk *c)
 {
 	u32 val;
 	u32 new_val;
+	unsigned long flags;
 
 	pr_debug("%s: %s\n", __func__, c->name);
 	if (c->flags & DIV_U71) {
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		new_val = val >> c->reg_shift;
 		new_val &= 0xFFFF;
@@ -659,11 +841,14 @@ static void tegra2_pll_div_clk_disable(struct clk *c)
 		val &= ~(0xFFFF << c->reg_shift);
 		val |= new_val << c->reg_shift;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 	} else if (c->flags & DIV_2) {
 		BUG_ON(!(c->flags & PLLD));
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		val |= PLLD_MISC_DIV_RST;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 	}
 }
 
@@ -672,10 +857,14 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
 	u32 val;
 	u32 new_val;
 	int divider_u71;
+	unsigned long parent_rate = clk_get_rate(c->parent);
+	unsigned long flags;
+
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(c->parent->rate, rate);
+		divider_u71 = clk_div71_get_divider(parent_rate, rate);
 		if (divider_u71 >= 0) {
+			spin_lock_irqsave(&clock_register_lock, flags);
 			val = clk_readl(c->reg);
 			new_val = val >> c->reg_shift;
 			new_val &= 0xFFFF;
@@ -689,10 +878,11 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
 			clk_writel(val, c->reg);
 			c->div = divider_u71 + 2;
 			c->mul = 2;
+			spin_unlock_irqrestore(&clock_register_lock, flags);
 			return 0;
 		}
 	} else if (c->flags & DIV_2) {
-		if (c->parent->rate == rate * 2)
+		if (parent_rate == rate * 2)
 			return 0;
 	}
 	return -EINVAL;
@@ -701,15 +891,16 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
 static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
 {
 	int divider;
+	unsigned long parent_rate = clk_get_rate(c->parent);
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 
 	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(c->parent->rate, rate);
+		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
-		return c->parent->rate * 2 / (divider + 2);
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 	} else if (c->flags & DIV_2) {
-		return c->parent->rate / 2;
+		return DIV_ROUND_UP(parent_rate, 2);
 	}
 	return -EINVAL;
 }
@@ -755,9 +946,14 @@ static void tegra2_periph_clk_init(struct clk *c)
 	}
 
 	c->state = ON;
+
+	if (!c->u.periph.clk_num)
+		return;
+
 	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
 			PERIPH_CLK_TO_ENB_BIT(c)))
 		c->state = OFF;
+
 	if (!(c->flags & PERIPH_NO_RESET))
 		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
 				PERIPH_CLK_TO_ENB_BIT(c))
@@ -767,8 +963,20 @@ static void tegra2_periph_clk_init(struct clk *c)
 static int tegra2_periph_clk_enable(struct clk *c)
 {
 	u32 val;
+	unsigned long flags;
+	int refcount;
 	pr_debug("%s on clock %s\n", __func__, c->name);
 
+	if (!c->u.periph.clk_num)
+		return 0;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
+
+	if (refcount > 1)
+		goto out;
+
 	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
 		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
 	if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
@@ -781,34 +989,48 @@ static int tegra2_periph_clk_enable(struct clk *c)
 		val |= 0x3 << 24;
 		clk_writel(val, c->reg);
 	}
+
+out:
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
 	return 0;
 }
 
 static void tegra2_periph_clk_disable(struct clk *c)
 {
+	unsigned long flags;
+
 	pr_debug("%s on clock %s\n", __func__, c->name);
 
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-}
+	if (!c->u.periph.clk_num)
+		return;
 
-void tegra2_periph_reset_deassert(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	if (!(c->flags & PERIPH_NO_RESET))
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	if (c->refcnt)
+		tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
 		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+			CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
 }
 
-void tegra2_periph_reset_assert(struct clk *c)
+static void tegra2_periph_clk_reset(struct clk *c, bool assert)
 {
-	pr_debug("%s on clock %s\n", __func__, c->name);
+	unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+	pr_debug("%s %s on clock %s\n", __func__,
+		 assert ? "assert" : "deassert", c->name);
+
+	BUG_ON(!c->u.periph.clk_num);
+
 	if (!(c->flags & PERIPH_NO_RESET))
 		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			RST_DEVICES_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+			   base + PERIPH_CLK_TO_ENB_SET_REG(c));
 }
 
-
 static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
 {
 	u32 val;
@@ -821,12 +1043,12 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
 			val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
 
 			if (c->refcnt)
-				clk_enable_locked(p);
+				clk_enable(p);
 
 			clk_writel(val, c->reg);
 
 			if (c->refcnt && c->parent)
-				clk_disable_locked(c->parent);
+				clk_disable(c->parent);
 
 			clk_reparent(c, p);
 			return 0;
@@ -840,9 +1062,10 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	u32 val;
 	int divider;
-	pr_debug("%s: %lu\n", __func__, rate);
+	unsigned long parent_rate = clk_get_rate(c->parent);
+
 	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(c->parent->rate, rate);
+		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider >= 0) {
 			val = clk_readl(c->reg);
 			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
@@ -853,7 +1076,7 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
 			return 0;
 		}
 	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(c->parent->rate, rate);
+		divider = clk_div16_get_divider(parent_rate, rate);
 		if (divider >= 0) {
 			val = clk_readl(c->reg);
 			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
@@ -863,7 +1086,7 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
 			c->mul = 1;
 			return 0;
 		}
-	} else if (c->parent->rate <= rate) {
+	} else if (parent_rate <= rate) {
 		c->div = 1;
 		c->mul = 1;
 		return 0;
@@ -875,19 +1098,20 @@ static long tegra2_periph_clk_round_rate(struct clk *c,
 	unsigned long rate)
 {
 	int divider;
+	unsigned long parent_rate = clk_get_rate(c->parent);
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 
 	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(c->parent->rate, rate);
+		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
 
-		return c->parent->rate * 2 / (divider + 2);
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(c->parent->rate, rate);
+		divider = clk_div16_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
-		return c->parent->rate / (divider + 1);
+		return DIV_ROUND_UP(parent_rate, divider + 1);
 	}
 	return -EINVAL;
 }
@@ -899,6 +1123,71 @@ static struct clk_ops tegra_periph_clk_ops = {
 	.set_parent		= &tegra2_periph_clk_set_parent,
 	.set_rate		= &tegra2_periph_clk_set_rate,
 	.round_rate		= &tegra2_periph_clk_round_rate,
+	.reset			= &tegra2_periph_clk_reset,
+};
+
+/* The SDMMC controllers have extra bits in the clock source register that
+ * adjust the delay between the clock and data to compenstate for delays
+ * on the PCB. */
+void tegra2_sdmmc_tap_delay(struct clk *c, int delay)
+{
+	u32 reg;
+
+	delay = clamp(delay, 0, 15);
+	reg = clk_readl(c->reg);
+	reg &= ~SDMMC_CLK_INT_FB_DLY_MASK;
+	reg |= SDMMC_CLK_INT_FB_SEL;
+	reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT;
+	clk_writel(reg, c->reg);
+}
+
+/* External memory controller clock ops */
+static void tegra2_emc_clk_init(struct clk *c)
+{
+	tegra2_periph_clk_init(c);
+	c->max_rate = clk_get_rate_locked(c);
+}
+
+static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	long new_rate = rate;
+
+	new_rate = tegra_emc_round_rate(new_rate);
+	if (new_rate < 0)
+		return c->max_rate;
+
+	BUG_ON(new_rate != tegra2_periph_clk_round_rate(c, new_rate));
+
+	return new_rate;
+}
+
+static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+	/*
+	 * The Tegra2 memory controller has an interlock with the clock
+	 * block that allows memory shadowed registers to be updated,
+	 * and then transfer them to the main registers at the same
+	 * time as the clock update without glitches.
+	 */
+	ret = tegra_emc_set_rate(rate);
+	if (ret < 0)
+		return ret;
+
+	ret = tegra2_periph_clk_set_rate(c, rate);
+	udelay(1);
+
+	return ret;
+}
+
+static struct clk_ops tegra_emc_clk_ops = {
+	.init			= &tegra2_emc_clk_init,
+	.enable			= &tegra2_periph_clk_enable,
+	.disable		= &tegra2_periph_clk_disable,
+	.set_parent		= &tegra2_periph_clk_set_parent,
+	.set_rate		= &tegra2_emc_clk_set_rate,
+	.round_rate		= &tegra2_emc_clk_round_rate,
+	.reset			= &tegra2_periph_clk_reset,
 };
 
 /* Clock doubler ops */
@@ -907,6 +1196,10 @@ static void tegra2_clk_double_init(struct clk *c)
 	c->mul = 2;
 	c->div = 1;
 	c->state = ON;
+
+	if (!c->u.periph.clk_num)
+		return;
+
 	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
 			PERIPH_CLK_TO_ENB_BIT(c)))
 		c->state = OFF;
@@ -914,7 +1207,7 @@ static void tegra2_clk_double_init(struct clk *c)
 
 static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
 {
-	if (rate != 2 * c->parent->rate)
+	if (rate != 2 * clk_get_rate(c->parent))
 		return -EINVAL;
 	c->mul = 2;
 	c->div = 1;
@@ -928,6 +1221,7 @@ static struct clk_ops tegra_clk_double_ops = {
 	.set_rate		= &tegra2_clk_double_set_rate,
 };
 
+/* Audio sync clock ops */
 static void tegra2_audio_sync_clk_init(struct clk *c)
 {
 	int source;
@@ -964,12 +1258,12 @@ static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
 			val |= sel->value;
 
 			if (c->refcnt)
-				clk_enable_locked(p);
+				clk_enable(p);
 
 			clk_writel(val, c->reg);
 
 			if (c->refcnt && c->parent)
-				clk_disable_locked(c->parent);
+				clk_disable(c->parent);
 
 			clk_reparent(c, p);
 			return 0;
@@ -979,33 +1273,153 @@ static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
 	return -EINVAL;
 }
 
-static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	unsigned long parent_rate;
-	if (!c->parent) {
-		pr_err("%s: clock has no parent\n", __func__);
-		return -EINVAL;
-	}
-	parent_rate = c->parent->rate;
-	if (rate != parent_rate) {
-		pr_err("%s: %s/%ld differs from parent %s/%ld\n",
-			__func__,
-			c->name, rate,
-			c->parent->name, parent_rate);
-		return -EINVAL;
-	}
-	c->rate = parent_rate;
-	return 0;
-}
-
 static struct clk_ops tegra_audio_sync_clk_ops = {
 	.init       = tegra2_audio_sync_clk_init,
 	.enable     = tegra2_audio_sync_clk_enable,
 	.disable    = tegra2_audio_sync_clk_disable,
-	.set_rate   = tegra2_audio_sync_clk_set_rate,
 	.set_parent = tegra2_audio_sync_clk_set_parent,
 };
 
+/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
+
+static void tegra2_cdev_clk_init(struct clk *c)
+{
+	/* We could un-tristate the cdev1 or cdev2 pingroup here; this is
+	 * currently done in the pinmux code. */
+	c->state = ON;
+
+	BUG_ON(!c->u.periph.clk_num);
+
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+}
+
+static int tegra2_cdev_clk_enable(struct clk *c)
+{
+	BUG_ON(!c->u.periph.clk_num);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+	return 0;
+}
+
+static void tegra2_cdev_clk_disable(struct clk *c)
+{
+	BUG_ON(!c->u.periph.clk_num);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+static struct clk_ops tegra_cdev_clk_ops = {
+	.init			= &tegra2_cdev_clk_init,
+	.enable			= &tegra2_cdev_clk_enable,
+	.disable		= &tegra2_cdev_clk_disable,
+};
+
+/* shared bus ops */
+/*
+ * Some clocks may have multiple downstream users that need to request a
+ * higher clock rate.  Shared bus clocks provide a unique shared_bus_user
+ * clock to each user.  The frequency of the bus is set to the highest
+ * enabled shared_bus_user clock, with a minimum value set by the
+ * shared bus.
+ */
+static int tegra_clk_shared_bus_update(struct clk *bus)
+{
+	struct clk *c;
+	unsigned long rate = bus->min_rate;
+
+	list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node)
+		if (c->u.shared_bus_user.enabled)
+			rate = max(c->u.shared_bus_user.rate, rate);
+
+	if (rate == clk_get_rate_locked(bus))
+		return 0;
+
+	return clk_set_rate_locked(bus, rate);
+};
+
+static void tegra_clk_shared_bus_init(struct clk *c)
+{
+	unsigned long flags;
+
+	c->max_rate = c->parent->max_rate;
+	c->u.shared_bus_user.rate = c->parent->max_rate;
+	c->state = OFF;
+	c->set = true;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	list_add_tail(&c->u.shared_bus_user.node,
+		&c->parent->shared_bus_list);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+}
+
+static int tegra_clk_shared_bus_set_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long flags;
+	int ret;
+
+	rate = clk_round_rate(c->parent, rate);
+	if (rate < 0)
+		return rate;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	c->u.shared_bus_user.rate = rate;
+	ret = tegra_clk_shared_bus_update(c->parent);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+
+	return ret;
+}
+
+static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate)
+{
+	return clk_round_rate(c->parent, rate);
+}
+
+static int tegra_clk_shared_bus_enable(struct clk *c)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	c->u.shared_bus_user.enabled = true;
+	ret = tegra_clk_shared_bus_update(c->parent);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+
+	return ret;
+}
+
+static void tegra_clk_shared_bus_disable(struct clk *c)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	c->u.shared_bus_user.enabled = false;
+	ret = tegra_clk_shared_bus_update(c->parent);
+	WARN_ON_ONCE(ret);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+}
+
+static struct clk_ops tegra_clk_shared_bus_ops = {
+	.init = tegra_clk_shared_bus_init,
+	.enable = tegra_clk_shared_bus_enable,
+	.disable = tegra_clk_shared_bus_disable,
+	.set_rate = tegra_clk_shared_bus_set_rate,
+	.round_rate = tegra_clk_shared_bus_round_rate,
+};
+
+
 /* Clock definitions */
 static struct clk tegra_clk_32k = {
 	.name = "clk_32k",
@@ -1014,7 +1428,7 @@ static struct clk tegra_clk_32k = {
 	.max_rate = 32768,
 };
 
-static struct clk_pll_table tegra_pll_s_table[] = {
+static struct clk_pll_freq_table tegra_pll_s_freq_table[] = {
 	{32768, 12000000, 366, 1, 1, 0},
 	{32768, 13000000, 397, 1, 1, 0},
 	{32768, 19200000, 586, 1, 1, 0},
@@ -1026,16 +1440,19 @@ static struct clk tegra_pll_s = {
 	.name      = "pll_s",
 	.flags     = PLL_ALT_MISC_REG,
 	.ops       = &tegra_pll_ops,
-	.reg       = 0xf0,
-	.input_min = 32768,
-	.input_max = 32768,
 	.parent    = &tegra_clk_32k,
-	.cf_min    = 0, /* FIXME */
-	.cf_max    = 0, /* FIXME */
-	.vco_min   = 12000000,
-	.vco_max   = 26000000,
-	.pll_table = tegra_pll_s_table,
 	.max_rate  = 26000000,
+	.reg       = 0xf0,
+	.u.pll = {
+		.input_min = 32768,
+		.input_max = 32768,
+		.cf_min    = 0, /* FIXME */
+		.cf_max    = 0, /* FIXME */
+		.vco_min   = 12000000,
+		.vco_max   = 26000000,
+		.freq_table = tegra_pll_s_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk_mux_sel tegra_clk_m_sel[] = {
@@ -1043,18 +1460,18 @@ static struct clk_mux_sel tegra_clk_m_sel[] = {
 	{ .input = &tegra_pll_s,  .value = 1},
 	{ 0, 0},
 };
+
 static struct clk tegra_clk_m = {
 	.name      = "clk_m",
 	.flags     = ENABLE_ON_INIT,
 	.ops       = &tegra_clk_m_ops,
 	.inputs    = tegra_clk_m_sel,
 	.reg       = 0x1fc,
-	.reg_mask  = (1<<28),
 	.reg_shift = 28,
 	.max_rate  = 26000000,
 };
 
-static struct clk_pll_table tegra_pll_c_table[] = {
+static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -1063,15 +1480,18 @@ static struct clk tegra_pll_c = {
 	.flags	   = PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0x80,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1400000000,
-	.pll_table = tegra_pll_c_table,
 	.max_rate  = 600000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1400000000,
+		.freq_table = tegra_pll_c_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_c_out1 = {
@@ -1084,7 +1504,7 @@ static struct clk tegra_pll_c_out1 = {
 	.max_rate  = 600000000,
 };
 
-static struct clk_pll_table tegra_pll_m_table[] = {
+static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
 	{ 12000000, 666000000, 666, 12, 1, 8},
 	{ 13000000, 666000000, 666, 13, 1, 8},
 	{ 19200000, 666000000, 555, 16, 1, 8},
@@ -1101,15 +1521,18 @@ static struct clk tegra_pll_m = {
 	.flags     = PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0x90,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1200000000,
-	.pll_table = tegra_pll_m_table,
 	.max_rate  = 800000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1200000000,
+		.freq_table = tegra_pll_m_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_m_out1 = {
@@ -1122,7 +1545,7 @@ static struct clk tegra_pll_m_out1 = {
 	.max_rate  = 600000000,
 };
 
-static struct clk_pll_table tegra_pll_p_table[] = {
+static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
 	{ 12000000, 216000000, 432, 12, 2, 8},
 	{ 13000000, 216000000, 432, 13, 2, 8},
 	{ 19200000, 216000000, 90,   4, 2, 1},
@@ -1139,15 +1562,18 @@ static struct clk tegra_pll_p = {
 	.flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xa0,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1400000000,
-	.pll_table = tegra_pll_p_table,
 	.max_rate  = 432000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1400000000,
+		.freq_table = tegra_pll_p_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_p_out1 = {
@@ -1190,11 +1616,9 @@ static struct clk tegra_pll_p_out4 = {
 	.max_rate  = 432000000,
 };
 
-static struct clk_pll_table tegra_pll_a_table[] = {
+static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
 	{ 28800000, 56448000, 49, 25, 1, 1},
 	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 11289600, 49, 25, 1, 1},
-	{ 28800000, 12288000, 64, 25, 1, 1},
 	{ 28800000, 24000000,  5,  6, 1, 1},
 	{ 0, 0, 0, 0, 0, 0 },
 };
@@ -1204,15 +1628,18 @@ static struct clk tegra_pll_a = {
 	.flags     = PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xb0,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_pll_p_out1,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1400000000,
-	.pll_table = tegra_pll_a_table,
-	.max_rate  = 56448000,
+	.max_rate  = 73728000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1400000000,
+		.freq_table = tegra_pll_a_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_a_out0 = {
@@ -1222,14 +1649,25 @@ static struct clk tegra_pll_a_out0 = {
 	.parent    = &tegra_pll_a,
 	.reg       = 0xb4,
 	.reg_shift = 0,
-	.max_rate  = 56448000,
+	.max_rate  = 73728000,
 };
 
-static struct clk_pll_table tegra_pll_d_table[] = {
+static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
+	{ 12000000, 216000000, 216, 12, 1, 4},
+	{ 13000000, 216000000, 216, 13, 1, 4},
+	{ 19200000, 216000000, 135, 12, 1, 3},
+	{ 26000000, 216000000, 216, 26, 1, 4},
+
+	{ 12000000, 594000000, 594, 12, 1, 8},
+	{ 13000000, 594000000, 594, 13, 1, 8},
+	{ 19200000, 594000000, 495, 16, 1, 8},
+	{ 26000000, 594000000, 594, 26, 1, 8},
+
 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 	{ 13000000, 1000000000, 1000, 13, 1, 12},
 	{ 19200000, 1000000000, 625,  12, 1, 8},
 	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -1238,15 +1676,18 @@ static struct clk tegra_pll_d = {
 	.flags     = PLL_HAS_CPCON | PLLD,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xd0,
-	.input_min = 2000000,
-	.input_max = 40000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 40000000,
-	.vco_max   = 1000000000,
-	.pll_table = tegra_pll_d_table,
 	.max_rate  = 1000000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 40000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 40000000,
+		.vco_max   = 1000000000,
+		.freq_table = tegra_pll_d_freq_table,
+		.lock_delay = 1000,
+	},
 };
 
 static struct clk tegra_pll_d_out0 = {
@@ -1257,7 +1698,7 @@ static struct clk tegra_pll_d_out0 = {
 	.max_rate  = 500000000,
 };
 
-static struct clk_pll_table tegra_pll_u_table[] = {
+static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
 	{ 12000000, 480000000, 960, 12, 2, 0},
 	{ 13000000, 480000000, 960, 13, 2, 0},
 	{ 19200000, 480000000, 200, 4,  2, 0},
@@ -1270,18 +1711,21 @@ static struct clk tegra_pll_u = {
 	.flags     = PLLU,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xc0,
-	.input_min = 2000000,
-	.input_max = 40000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 480000000,
-	.vco_max   = 960000000,
-	.pll_table = tegra_pll_u_table,
 	.max_rate  = 480000000,
-};
-
-static struct clk_pll_table tegra_pll_x_table[] = {
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 40000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 480000000,
+		.vco_max   = 960000000,
+		.freq_table = tegra_pll_u_freq_table,
+		.lock_delay = 1000,
+	},
+};
+
+static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
 	/* 1 GHz */
 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 	{ 13000000, 1000000000, 1000, 13, 1, 12},
@@ -1307,10 +1751,10 @@ static struct clk_pll_table tegra_pll_x_table[] = {
 	{ 26000000, 760000000,  760,  26, 1, 12},
 
 	/* 608 MHz */
-	{ 12000000, 608000000,  760,  12, 1, 12},
-	{ 13000000, 608000000,  760,  13, 1, 12},
+	{ 12000000, 608000000,  608,  12, 1, 12},
+	{ 13000000, 608000000,  608,  13, 1, 12},
 	{ 19200000, 608000000,  380,  12, 1, 8},
-	{ 26000000, 608000000,  760,  26, 1, 12},
+	{ 26000000, 608000000,  608,  26, 1, 12},
 
 	/* 456 MHz */
 	{ 12000000, 456000000,  456,  12, 1, 12},
@@ -1332,18 +1776,21 @@ static struct clk tegra_pll_x = {
 	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
 	.ops       = &tegra_pllx_ops,
 	.reg       = 0xe0,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1200000000,
-	.pll_table = tegra_pll_x_table,
 	.max_rate  = 1000000000,
-};
-
-static struct clk_pll_table tegra_pll_e_table[] = {
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1200000000,
+		.freq_table = tegra_pll_x_freq_table,
+		.lock_delay = 300,
+	},
+};
+
+static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
 	{ 12000000, 100000000,  200,  24, 1, 0 },
 	{ 0, 0, 0, 0, 0, 0 },
 };
@@ -1352,23 +1799,49 @@ static struct clk tegra_pll_e = {
 	.name      = "pll_e",
 	.flags	   = PLL_ALT_MISC_REG,
 	.ops       = &tegra_plle_ops,
-	.input_min = 12000000,
-	.input_max = 12000000,
-	.max_rate  = 100000000,
 	.parent    = &tegra_clk_m,
 	.reg       = 0xe8,
-	.pll_table = tegra_pll_e_table,
+	.max_rate  = 100000000,
+	.u.pll = {
+		.input_min = 12000000,
+		.input_max = 12000000,
+		.freq_table = tegra_pll_e_freq_table,
+	},
 };
 
 static struct clk tegra_clk_d = {
 	.name      = "clk_d",
 	.flags     = PERIPH_NO_RESET,
 	.ops       = &tegra_clk_double_ops,
-	.clk_num   = 90,
 	.reg       = 0x34,
 	.reg_shift = 12,
 	.parent    = &tegra_clk_m,
 	.max_rate  = 52000000,
+	.u.periph  = {
+		.clk_num = 90,
+	},
+};
+
+/* dap_mclk1, belongs to the cdev1 pingroup. */
+static struct clk tegra_clk_cdev1 = {
+	.name      = "cdev1",
+	.ops       = &tegra_cdev_clk_ops,
+	.rate      = 26000000,
+	.max_rate  = 26000000,
+	.u.periph  = {
+		.clk_num = 94,
+	},
+};
+
+/* dap_mclk2, belongs to the cdev2 pingroup. */
+static struct clk tegra_clk_cdev2 = {
+	.name      = "cdev2",
+	.ops       = &tegra_cdev_clk_ops,
+	.rate      = 26000000,
+	.max_rate  = 26000000,
+	.u.periph  = {
+		.clk_num   = 93,
+	},
 };
 
 /* initialized before peripheral clocks */
@@ -1394,7 +1867,7 @@ static struct clk tegra_clk_audio = {
 	.name      = "audio",
 	.inputs    = mux_audio_sync_clk,
 	.reg       = 0x38,
-	.max_rate  = 24000000,
+	.max_rate  = 73728000,
 	.ops       = &tegra_audio_sync_clk_ops
 };
 
@@ -1403,10 +1876,12 @@ static struct clk tegra_clk_audio_2x = {
 	.flags     = PERIPH_NO_RESET,
 	.max_rate  = 48000000,
 	.ops       = &tegra_clk_double_ops,
-	.clk_num   = 89,
 	.reg       = 0x34,
 	.reg_shift = 8,
 	.parent    = &tegra_clk_audio,
+	.u.periph = {
+		.clk_num = 89,
+	},
 };
 
 struct clk_lookup tegra_audio_clk_lookups[] = {
@@ -1478,17 +1953,26 @@ static struct clk tegra_clk_sclk = {
 	.inputs	= mux_sclk,
 	.reg	= 0x28,
 	.ops	= &tegra_super_ops,
-	.max_rate = 600000000,
+	.max_rate = 240000000,
+	.min_rate = 120000000,
 };
 
 static struct clk tegra_clk_virtual_cpu = {
 	.name      = "cpu",
 	.parent    = &tegra_clk_cclk,
-	.main      = &tegra_pll_x,
-	.backup    = &tegra_clk_m,
 	.ops       = &tegra_cpu_ops,
 	.max_rate  = 1000000000,
-	.dvfs      = &tegra_dvfs_virtual_cpu_dvfs,
+	.u.cpu = {
+		.main      = &tegra_pll_x,
+		.backup    = &tegra_pll_p,
+	},
+};
+
+static struct clk tegra_clk_cop = {
+	.name      = "cop",
+	.parent    = &tegra_clk_sclk,
+	.ops       = &tegra_cop_ops,
+	.max_rate  = 240000000,
 };
 
 static struct clk tegra_clk_hclk = {
@@ -1508,7 +1992,15 @@ static struct clk tegra_clk_pclk = {
 	.reg		= 0x30,
 	.reg_shift	= 0,
 	.ops		= &tegra_bus_ops,
-	.max_rate       = 108000000,
+	.max_rate       = 120000000,
+};
+
+static struct clk tegra_clk_blink = {
+	.name		= "blink",
+	.parent		= &tegra_clk_32k,
+	.reg		= 0x40,
+	.ops		= &tegra_blink_clk_ops,
+	.max_rate	= 32768,
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
@@ -1587,6 +2079,23 @@ static struct clk_mux_sel mux_clk_32k[] = {
 	{ 0, 0},
 };
 
+static struct clk_mux_sel mux_pclk[] = {
+	{ .input = &tegra_clk_pclk, .value = 0},
+	{ 0, 0},
+};
+
+static struct clk tegra_clk_emc = {
+	.name = "emc",
+	.ops = &tegra_emc_clk_ops,
+	.reg = 0x19c,
+	.max_rate = 800000000,
+	.inputs = mux_pllm_pllc_pllp_clkm,
+	.flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
+	.u.periph = {
+		.clk_num = 57,
+	},
+};
+
 #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
 	{						\
 		.name      = _name,			\
@@ -1595,19 +2104,32 @@ static struct clk_mux_sel mux_clk_32k[] = {
 			.con_id	   = _con,		\
 		},					\
 		.ops       = &tegra_periph_clk_ops,	\
-		.clk_num   = _clk_num,			\
 		.reg       = _reg,			\
 		.inputs    = _inputs,			\
 		.flags     = _flags,			\
 		.max_rate  = _max,			\
+		.u.periph = {				\
+			.clk_num   = _clk_num,		\
+		},					\
+	}
+
+#define SHARED_CLK(_name, _dev, _con, _parent)		\
+	{						\
+		.name      = _name,			\
+		.lookup    = {				\
+			.dev_id    = _dev,		\
+			.con_id    = _con,		\
+		},					\
+		.ops       = &tegra_clk_shared_bus_ops,	\
+		.parent = _parent,			\
 	}
 
-struct clk tegra_periph_clks[] = {
+struct clk tegra_list_clks[] = {
+	PERIPH_CLK("apbdma",	"tegra-dma",		NULL,	34,	0,	108000000, mux_pclk,			0),
 	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET),
 	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("i2s1",	"i2s.0",		NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2s2",	"i2s.1",		NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	/* FIXME: spdif has 2 clocks but 1 enable */
+	PERIPH_CLK("i2s1",	"tegra-i2s.0",		NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2s2",	"tegra-i2s.1",		NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("spdif_out",	"spdif_out",		NULL,	10,	0x108,	100000000, mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("spdif_in",	"spdif_in",		NULL,	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71),
 	PERIPH_CLK("pwm",	"pwm",			NULL,	17,	0x110,	432000000, mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71),
@@ -1620,13 +2142,15 @@ struct clk tegra_periph_clks[] = {
 	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("ide",	"ide",			NULL,	25,	0x144,	100000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("ndflash",	"tegra_nand",		NULL,	13,	0x160,	164000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	/* FIXME: vfir shares an enable with uartb */
 	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x160,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x164,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("vcp",	"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0),
+	PERIPH_CLK("bsea",	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0),
+	PERIPH_CLK("bsev",	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0),
+	PERIPH_CLK("vde",	"tegra-avp",		"vde",	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* max rate ??? */
 	/* FIXME: what is la? */
 	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
@@ -1641,37 +2165,46 @@ struct clk tegra_periph_clks[] = {
 	PERIPH_CLK("i2c2_i2c",	"tegra-i2c.1",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
 	PERIPH_CLK("i2c3_i2c",	"tegra-i2c.2",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
 	PERIPH_CLK("dvc_i2c",	"tegra-i2c.3",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
-	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
 	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
 	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	/* FIXME: vi and vi_sensor share an enable */
-	PERIPH_CLK("vi",	"vi",			NULL,	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("vi_sensor",	"vi_sensor",		NULL,	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
+	PERIPH_CLK("vi",	"tegra_camera",		"vi",	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("vi_sensor",	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
 	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	250000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	166000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	/* FIXME: cve and tvo share an enable	*/
 	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("disp1",	"tegrafb.0",		NULL,	27,	0x138,	190000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("disp2",	"tegrafb.1",		NULL,	26,	0x13c,	190000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("emc",	"emc",			NULL,	57,	0x19c,	800000000, mux_pllm_pllc_pllp_clkm,	MUX | DIV_U71 | PERIPH_EMC_ENB),
 	PERIPH_CLK("dsi",	"dsi",			NULL,	48,	0,	500000000, mux_plld,			0), /* scales with voltage */
-	PERIPH_CLK("csi",	"csi",			NULL,	52,	0,	72000000,  mux_pllp_out3,		0),
-	PERIPH_CLK("isp",	"isp",			NULL,	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
-	PERIPH_CLK("csus",	"csus",			NULL,	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
+	PERIPH_CLK("csi",	"tegra_camera",		"csi",	52,	0,	72000000,  mux_pllp_out3,		0),
+	PERIPH_CLK("isp",	"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
+	PERIPH_CLK("csus",	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
 	PERIPH_CLK("pex",       NULL,			"pex",  70,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
 	PERIPH_CLK("afi",       NULL,			"afi",  72,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
 	PERIPH_CLK("pcie_xclk", NULL,		  "pcie_xclk",  74,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
+
+	SHARED_CLK("avp.sclk",	"tegra-avp",		"sclk",	&tegra_clk_sclk),
+	SHARED_CLK("avp.emc",	"tegra-avp",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("cpu.emc",	"cpu",			"emc",	&tegra_clk_emc),
+	SHARED_CLK("disp1.emc",	"tegradc.0",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("disp2.emc",	"tegradc.1",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("hdmi.emc",	"hdmi",			"emc",	&tegra_clk_emc),
+	SHARED_CLK("host.emc",	"tegra_grhost",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("usbd.emc",	"fsl-tegra-udc",	"emc",	&tegra_clk_emc),
+	SHARED_CLK("usb1.emc",	"tegra-ehci.0",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("usb2.emc",	"tegra-ehci.1",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("usb3.emc",	"tegra-ehci.2",		"emc",	&tegra_clk_emc),
 };
 
 #define CLK_DUPLICATE(_name, _dev, _con)		\
@@ -1693,9 +2226,22 @@ struct clk_duplicate tegra_clk_duplicates[] = {
 	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
 	CLK_DUPLICATE("uartd",	"tegra_uart.3",	NULL),
 	CLK_DUPLICATE("uarte",	"tegra_uart.4",	NULL),
-	CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"),
-	CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"),
+	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
 	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
+	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
+	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
+	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
+	CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL),
+	CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
+	CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
+	CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL),
+	CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"),
+	CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"),
+	CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"),
+	CLK_DUPLICATE("epp", "tegra_grhost", "epp"),
+	CLK_DUPLICATE("mpe", "tegra_grhost", "mpe"),
+	CLK_DUPLICATE("cop", "tegra-avp", "cop"),
+	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
 };
 
 #define CLK(dev, con, ck)	\
@@ -1705,68 +2251,70 @@ struct clk_duplicate tegra_clk_duplicates[] = {
 		.clk = ck,	\
 	}
 
-struct clk_lookup tegra_clk_lookups[] = {
-	/* external root sources */
-	CLK(NULL,	"32k_clk",	&tegra_clk_32k),
-	CLK(NULL,	"pll_s",	&tegra_pll_s),
-	CLK(NULL,	"clk_m",	&tegra_clk_m),
-	CLK(NULL,	"pll_m",	&tegra_pll_m),
-	CLK(NULL,	"pll_m_out1",	&tegra_pll_m_out1),
-	CLK(NULL,	"pll_c",	&tegra_pll_c),
-	CLK(NULL,	"pll_c_out1",	&tegra_pll_c_out1),
-	CLK(NULL,	"pll_p",	&tegra_pll_p),
-	CLK(NULL,	"pll_p_out1",	&tegra_pll_p_out1),
-	CLK(NULL,	"pll_p_out2",	&tegra_pll_p_out2),
-	CLK(NULL,	"pll_p_out3",	&tegra_pll_p_out3),
-	CLK(NULL,	"pll_p_out4",	&tegra_pll_p_out4),
-	CLK(NULL,	"pll_a",	&tegra_pll_a),
-	CLK(NULL,	"pll_a_out0",	&tegra_pll_a_out0),
-	CLK(NULL,	"pll_d",	&tegra_pll_d),
-	CLK(NULL,	"pll_d_out0",	&tegra_pll_d_out0),
-	CLK(NULL,	"pll_u",	&tegra_pll_u),
-	CLK(NULL,	"pll_x",	&tegra_pll_x),
-	CLK(NULL,	"pll_e",	&tegra_pll_e),
-	CLK(NULL,	"cclk",		&tegra_clk_cclk),
-	CLK(NULL,	"sclk",		&tegra_clk_sclk),
-	CLK(NULL,	"hclk",		&tegra_clk_hclk),
-	CLK(NULL,	"pclk",		&tegra_clk_pclk),
-	CLK(NULL,	"clk_d",	&tegra_clk_d),
-	CLK(NULL,	"cpu",		&tegra_clk_virtual_cpu),
-};
+struct clk *tegra_ptr_clks[] = {
+	&tegra_clk_32k,
+	&tegra_pll_s,
+	&tegra_clk_m,
+	&tegra_pll_m,
+	&tegra_pll_m_out1,
+	&tegra_pll_c,
+	&tegra_pll_c_out1,
+	&tegra_pll_p,
+	&tegra_pll_p_out1,
+	&tegra_pll_p_out2,
+	&tegra_pll_p_out3,
+	&tegra_pll_p_out4,
+	&tegra_pll_a,
+	&tegra_pll_a_out0,
+	&tegra_pll_d,
+	&tegra_pll_d_out0,
+	&tegra_pll_u,
+	&tegra_pll_x,
+	&tegra_pll_e,
+	&tegra_clk_cclk,
+	&tegra_clk_sclk,
+	&tegra_clk_hclk,
+	&tegra_clk_pclk,
+	&tegra_clk_d,
+	&tegra_clk_cdev1,
+	&tegra_clk_cdev2,
+	&tegra_clk_virtual_cpu,
+	&tegra_clk_blink,
+	&tegra_clk_cop,
+	&tegra_clk_emc,
+};
+
+static void tegra2_init_one_clock(struct clk *c)
+{
+	clk_init(c);
+	INIT_LIST_HEAD(&c->shared_bus_list);
+	if (!c->lookup.dev_id && !c->lookup.con_id)
+		c->lookup.con_id = c->name;
+	c->lookup.clk = c;
+	clkdev_add(&c->lookup);
+}
 
 void __init tegra2_init_clocks(void)
 {
 	int i;
-	struct clk_lookup *cl;
 	struct clk *c;
-	struct clk_duplicate *cd;
-
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_lookups); i++) {
-		cl = &tegra_clk_lookups[i];
-		clk_init(cl->clk);
-		clkdev_add(cl);
-	}
 
-	for (i = 0; i < ARRAY_SIZE(tegra_periph_clks); i++) {
-		c = &tegra_periph_clks[i];
-		cl = &c->lookup;
-		cl->clk = c;
+	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
+		tegra2_init_one_clock(tegra_ptr_clks[i]);
 
-		clk_init(cl->clk);
-		clkdev_add(cl);
-	}
+	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
+		tegra2_init_one_clock(&tegra_list_clks[i]);
 
 	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
-		cd = &tegra_clk_duplicates[i];
-		c = tegra_get_clock_by_name(cd->name);
-		if (c) {
-			cl = &cd->lookup;
-			cl->clk = c;
-			clkdev_add(cl);
-		} else {
+		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
+		if (!c) {
 			pr_err("%s: Unknown duplicate clock %s\n", __func__,
-				cd->name);
+				tegra_clk_duplicates[i].name);
+			continue;
 		}
+
+		tegra_clk_duplicates[i].lookup.clk = c;
+		clkdev_add(&tegra_clk_duplicates[i].lookup);
 	}
 
 	init_audio_sync_clock_mux();
@@ -1774,7 +2322,7 @@ void __init tegra2_init_clocks(void)
 
 #ifdef CONFIG_PM
 static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
-			   PERIPH_CLK_SOURCE_NUM + 3];
+			   PERIPH_CLK_SOURCE_NUM + 22];
 
 void tegra_clk_suspend(void)
 {
@@ -1782,6 +2330,29 @@ void tegra_clk_suspend(void)
 	u32 *ctx = clk_rst_suspend;
 
 	*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+	*ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
+	*ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
+	*ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+	*ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+	*ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
+
+	*ctx++ = clk_readl(tegra_pll_m_out1.reg);
+	*ctx++ = clk_readl(tegra_pll_a_out0.reg);
+	*ctx++ = clk_readl(tegra_pll_c_out1.reg);
+
+	*ctx++ = clk_readl(tegra_clk_cclk.reg);
+	*ctx++ = clk_readl(tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
+
+	*ctx++ = clk_readl(tegra_clk_sclk.reg);
+	*ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
+	*ctx++ = clk_readl(tegra_clk_pclk.reg);
+
+	*ctx++ = clk_readl(tegra_clk_audio.reg);
 
 	for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
 			off += 4) {
@@ -1800,6 +2371,8 @@ void tegra_clk_suspend(void)
 
 	*ctx++ = clk_readl(MISC_CLK_ENB);
 	*ctx++ = clk_readl(CLK_MASK_ARM);
+
+	BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend));
 }
 
 void tegra_clk_resume(void)
@@ -1812,6 +2385,31 @@ void tegra_clk_resume(void)
 	val |= *ctx++;
 	clk_writel(val, OSC_CTRL);
 
+	clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
+	clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
+	clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+	clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+	clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
+	udelay(1000);
+
+	clk_writel(*ctx++, tegra_pll_m_out1.reg);
+	clk_writel(*ctx++, tegra_pll_a_out0.reg);
+	clk_writel(*ctx++, tegra_pll_c_out1.reg);
+
+	clk_writel(*ctx++, tegra_clk_cclk.reg);
+	clk_writel(*ctx++, tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
+
+	clk_writel(*ctx++, tegra_clk_sclk.reg);
+	clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
+	clk_writel(*ctx++, tegra_clk_pclk.reg);
+
+	clk_writel(*ctx++, tegra_clk_audio.reg);
+
 	/* enable all clocks before configuring clock sources */
 	clk_writel(0xbffffff9ul, CLK_OUT_ENB);
 	clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c
deleted file mode 100644
index 5529c23..0000000
--- a/arch/arm/mach-tegra/tegra2_dvfs.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra2_dvfs.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.
- *
- */
-
-#include <linux/kernel.h>
-
-#include "clock.h"
-#include "tegra2_dvfs.h"
-
-static struct dvfs_table virtual_cpu_process_0[] = {
-	{314000000,  750},
-	{456000000,  825},
-	{608000000,  900},
-	{760000000,  975},
-	{817000000,  1000},
-	{912000000,  1050},
-	{1000000000, 1100},
-	{0, 0},
-};
-
-static struct dvfs_table virtual_cpu_process_1[] = {
-	{314000000,  750},
-	{456000000,  825},
-	{618000000,  900},
-	{770000000,  975},
-	{827000000,  1000},
-	{922000000,  1050},
-	{1000000000, 1100},
-	{0, 0},
-};
-
-static struct dvfs_table virtual_cpu_process_2[] = {
-	{494000000,  750},
-	{675000000,  825},
-	{817000000,  875},
-	{922000000,  925},
-	{1000000000, 975},
-	{0, 0},
-};
-
-static struct dvfs_table virtual_cpu_process_3[] = {
-	{730000000,  750},
-	{760000000,  775},
-	{845000000,  800},
-	{1000000000, 875},
-	{0, 0},
-};
-
-struct dvfs tegra_dvfs_virtual_cpu_dvfs = {
-	.reg_id = "vdd_cpu",
-	.process_id_table = {
-		{
-			.process_id = 0,
-			.table = virtual_cpu_process_0,
-		},
-		{
-			.process_id = 1,
-			.table = virtual_cpu_process_1,
-		},
-		{
-			.process_id = 2,
-			.table = virtual_cpu_process_2,
-		},
-		{
-			.process_id = 3,
-			.table = virtual_cpu_process_3,
-		},
-	},
-	.process_id_table_length = 4,
-	.cpu = 1,
-};
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/tegra2_dvfs.h
deleted file mode 100644
index f8c1adb..0000000
--- a/arch/arm/mach-tegra/tegra2_dvfs.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra2_dvfs.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-extern struct dvfs tegra_dvfs_virtual_cpu_dvfs;
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c
new file mode 100644
index 0000000..0f7ae6e
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_emc.c
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2011 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <mach/iomap.h>
+
+#include "tegra2_emc.h"
+
+#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
+static bool emc_enable = true;
+#else
+static bool emc_enable;
+#endif
+module_param(emc_enable, bool, 0644);
+
+static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE);
+static const struct tegra_emc_table *tegra_emc_table;
+static int tegra_emc_table_size;
+
+static inline void emc_writel(u32 val, unsigned long addr)
+{
+	writel(val, emc + addr);
+}
+
+static inline u32 emc_readl(unsigned long addr)
+{
+	return readl(emc + addr);
+}
+
+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+	0x2c,	/* RC */
+	0x30,	/* RFC */
+	0x34,	/* RAS */
+	0x38,	/* RP */
+	0x3c,	/* R2W */
+	0x40,	/* W2R */
+	0x44,	/* R2P */
+	0x48,	/* W2P */
+	0x4c,	/* RD_RCD */
+	0x50,	/* WR_RCD */
+	0x54,	/* RRD */
+	0x58,	/* REXT */
+	0x5c,	/* WDV */
+	0x60,	/* QUSE */
+	0x64,	/* QRST */
+	0x68,	/* QSAFE */
+	0x6c,	/* RDV */
+	0x70,	/* REFRESH */
+	0x74,	/* BURST_REFRESH_NUM */
+	0x78,	/* PDEX2WR */
+	0x7c,	/* PDEX2RD */
+	0x80,	/* PCHG2PDEN */
+	0x84,	/* ACT2PDEN */
+	0x88,	/* AR2PDEN */
+	0x8c,	/* RW2PDEN */
+	0x90,	/* TXSR */
+	0x94,	/* TCKE */
+	0x98,	/* TFAW */
+	0x9c,	/* TRPAB */
+	0xa0,	/* TCLKSTABLE */
+	0xa4,	/* TCLKSTOP */
+	0xa8,	/* TREFBW */
+	0xac,	/* QUSE_EXTRA */
+	0x114,	/* FBIO_CFG6 */
+	0xb0,	/* ODT_WRITE */
+	0xb4,	/* ODT_READ */
+	0x104,	/* FBIO_CFG5 */
+	0x2bc,	/* CFG_DIG_DLL */
+	0x2c0,	/* DLL_XFORM_DQS */
+	0x2c4,	/* DLL_XFORM_QUSE */
+	0x2e0,	/* ZCAL_REF_CNT */
+	0x2e4,	/* ZCAL_WAIT_CNT */
+	0x2a8,	/* AUTO_CAL_INTERVAL */
+	0x2d0,	/* CFG_CLKTRIM_0 */
+	0x2d4,	/* CFG_CLKTRIM_1 */
+	0x2d8,	/* CFG_CLKTRIM_2 */
+};
+
+/* Select the closest EMC rate that is higher than the requested rate */
+long tegra_emc_round_rate(unsigned long rate)
+{
+	int i;
+	int best = -1;
+	unsigned long distance = ULONG_MAX;
+
+	if (!tegra_emc_table)
+		return -EINVAL;
+
+	if (!emc_enable)
+		return -EINVAL;
+
+	pr_debug("%s: %lu\n", __func__, rate);
+
+	/*
+	 * The EMC clock rate is twice the bus rate, and the bus rate is
+	 * measured in kHz
+	 */
+	rate = rate / 2 / 1000;
+
+	for (i = 0; i < tegra_emc_table_size; i++) {
+		if (tegra_emc_table[i].rate >= rate &&
+		    (tegra_emc_table[i].rate - rate) < distance) {
+			distance = tegra_emc_table[i].rate - rate;
+			best = i;
+		}
+	}
+
+	if (best < 0)
+		return -EINVAL;
+
+	pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate);
+
+	return tegra_emc_table[best].rate * 2 * 1000;
+}
+
+/*
+ * The EMC registers have shadow registers.  When the EMC clock is updated
+ * in the clock controller, the shadow registers are copied to the active
+ * registers, allowing glitchless memory bus frequency changes.
+ * This function updates the shadow registers for a new clock frequency,
+ * and relies on the clock lock on the emc clock to avoid races between
+ * multiple frequency changes
+ */
+int tegra_emc_set_rate(unsigned long rate)
+{
+	int i;
+	int j;
+
+	if (!tegra_emc_table)
+		return -EINVAL;
+
+	/*
+	 * The EMC clock rate is twice the bus rate, and the bus rate is
+	 * measured in kHz
+	 */
+	rate = rate / 2 / 1000;
+
+	for (i = 0; i < tegra_emc_table_size; i++)
+		if (tegra_emc_table[i].rate == rate)
+			break;
+
+	if (i >= tegra_emc_table_size)
+		return -EINVAL;
+
+	pr_debug("%s: setting to %lu\n", __func__, rate);
+
+	for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
+		emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]);
+
+	emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]);
+
+	return 0;
+}
+
+void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
+{
+	tegra_emc_table = table;
+	tegra_emc_table_size = table_size;
+}
diff --git a/arch/arm/mach-tegra/tegra2_emc.h b/arch/arm/mach-tegra/tegra2_emc.h
new file mode 100644
index 0000000..19f08cb
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra2_emc.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 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.
+ *
+ */
+
+#define TEGRA_EMC_NUM_REGS 46
+
+struct tegra_emc_table {
+	unsigned long rate;
+	u32 regs[TEGRA_EMC_NUM_REGS];
+};
+
+int tegra_emc_set_rate(unsigned long rate);
+long tegra_emc_round_rate(unsigned long rate);
+void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c
index 7b8ad1f..0fcb1eb 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/arch/arm/mach-tegra/timer.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
@@ -33,10 +34,15 @@
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/suspend.h>
 
 #include "board.h"
 #include "clock.h"
 
+#define RTC_SECONDS            0x08
+#define RTC_SHADOW_SECONDS     0x0c
+#define RTC_MILLISECONDS       0x10
+
 #define TIMERUS_CNTR_1US 0x10
 #define TIMERUS_USEC_CFG 0x14
 #define TIMERUS_CNTR_FREEZE 0x4c
@@ -49,9 +55,11 @@
 #define TIMER_PTV 0x0
 #define TIMER_PCR 0x4
 
-struct tegra_timer;
-
 static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
+static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE);
+
+static struct timespec persistent_ts;
+static u64 persistent_ms, last_persistent_ms;
 
 #define timer_writel(value, reg) \
 	__raw_writel(value, (u32)timer_reg_base + (reg))
@@ -132,6 +140,42 @@ static void notrace tegra_update_sched_clock(void)
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
+/*
+ * tegra_rtc_read - Reads the Tegra RTC registers
+ * Care must be taken that this funciton is not called while the
+ * tegra_rtc driver could be executing to avoid race conditions
+ * on the RTC shadow register
+ */
+u64 tegra_rtc_read_ms(void)
+{
+	u32 ms = readl(rtc_base + RTC_MILLISECONDS);
+	u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
+	return (u64)s * MSEC_PER_SEC + ms;
+}
+
+/*
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
+ * Care must be taken that this funciton is not called while the
+ * tegra_rtc driver could be executing to avoid race conditions
+ * on the RTC shadow register
+ */
+void read_persistent_clock(struct timespec *ts)
+{
+	u64 delta;
+	struct timespec *tsp = &persistent_ts;
+
+	last_persistent_ms = persistent_ms;
+	persistent_ms = tegra_rtc_read_ms();
+	delta = persistent_ms - last_persistent_ms;
+
+	timespec_add_ns(tsp, delta * NSEC_PER_MSEC);
+	*ts = *tsp;
+}
+
 static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -150,9 +194,22 @@ static struct irqaction tegra_timer_irq = {
 
 static void __init tegra_init_timer(void)
 {
+	struct clk *clk;
 	unsigned long rate = clk_measure_input_freq();
 	int ret;
 
+	clk = clk_get_sys("timer", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_enable(clk);
+
+	/*
+	 * rtc registers are used by read_persistent_clock, keep the rtc clock
+	 * enabled
+	 */
+	clk = clk_get_sys("rtc-tegra", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_enable(clk);
+
 #ifdef CONFIG_HAVE_ARM_TWD
 	twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
 #endif
@@ -196,10 +253,22 @@ static void __init tegra_init_timer(void)
 	tegra_clockevent.cpumask = cpu_all_mask;
 	tegra_clockevent.irq = tegra_timer_irq.irq;
 	clockevents_register_device(&tegra_clockevent);
-
-	return;
 }
 
 struct sys_timer tegra_timer = {
 	.init = tegra_init_timer,
 };
+
+#ifdef CONFIG_PM
+static u32 usec_config;
+
+void tegra_timer_suspend(void)
+{
+	usec_config = timer_readl(TIMERUS_USEC_CFG);
+}
+
+void tegra_timer_resume(void)
+{
+	timer_writel(usec_config, TIMERUS_USEC_CFG);
+}
+#endif
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c
new file mode 100644
index 0000000..88081bb
--- /dev/null
+++ b/arch/arm/mach-tegra/usb_phy.c
@@ -0,0 +1,795 @@
+/*
+ * arch/arm/mach-tegra/usb_phy.c
+ *
+ * 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/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <asm/mach-types.h>
+#include <mach/usb_phy.h>
+#include <mach/iomap.h>
+
+#define ULPI_VIEWPORT		0x170
+
+#define USB_PORTSC1		0x184
+#define   USB_PORTSC1_PTS(x)	(((x) & 0x3) << 30)
+#define   USB_PORTSC1_PSPD(x)	(((x) & 0x3) << 26)
+#define   USB_PORTSC1_PHCD	(1 << 23)
+#define   USB_PORTSC1_WKOC	(1 << 22)
+#define   USB_PORTSC1_WKDS	(1 << 21)
+#define   USB_PORTSC1_WKCN	(1 << 20)
+#define   USB_PORTSC1_PTC(x)	(((x) & 0xf) << 16)
+#define   USB_PORTSC1_PP	(1 << 12)
+#define   USB_PORTSC1_SUSP	(1 << 7)
+#define   USB_PORTSC1_PE	(1 << 2)
+#define   USB_PORTSC1_CCS	(1 << 0)
+
+#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 inline bool phy_is_ulpi(struct tegra_usb_phy *phy)
+{
+	return (phy->instance == 1);
+}
+
+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->instance == 0) {
+		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->instance != 0)
+		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_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(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_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(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->instance == 0) {
+		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);
+	}
+
+	if (phy->instance == 2) {
+		val = readl(base + USB_PORTSC1);
+		val |= USB_PORTSC1_PHCD;
+		writel(val, base + USB_PORTSC1);
+	}
+
+	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->instance == 0) {
+		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);
+	}
+
+	if (phy->instance == 2) {
+		val = readl(base + USB_PORTSC1);
+		val &= ~USB_PORTSC1_PHCD;
+		writel(val, base + USB_PORTSC1);
+	}
+
+	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->instance == 0) {
+		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->instance == 0) {
+		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);
+	}
+
+	if (phy->instance == 2) {
+		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->instance == 0) {
+		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->instance == 2) {
+		val = readl(base + USB_PORTSC1);
+		val &= ~USB_PORTSC1_PTS(~0);
+		writel(val, base + USB_PORTSC1);
+	}
+
+	return 0;
+}
+
+static void 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);
+
+	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_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 = otg_io_write(phy->ulpi, 0x40, 0x08);
+	if (ret) {
+		pr_err("%s: ulpi write failed\n", __func__);
+		return ret;
+	}
+
+	ret = otg_io_write(phy->ulpi, 0x80, 0x0B);
+	if (ret) {
+		pr_err("%s: ulpi write failed\n", __func__);
+		return ret;
+	}
+
+	val = readl(base + USB_PORTSC1);
+	val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
+	writel(val, base + USB_PORTSC1);
+
+	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 void ulpi_phy_power_off(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+	struct tegra_ulpi_config *config = phy->config;
+
+	/* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
+	 * Controller to immediately bring the ULPI PHY out of low power
+	 */
+	val = readl(base + USB_PORTSC1);
+	val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
+	writel(val, base + USB_PORTSC1);
+
+	gpio_direction_output(config->reset_gpio, 0);
+	clk_disable(phy->clk);
+}
+
+struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
+			void *config, enum tegra_usb_phy_mode phy_mode)
+{
+	struct tegra_usb_phy *phy;
+	struct tegra_ulpi_config *ulpi_config;
+	unsigned long parent_rate;
+	int i;
+	int err;
+
+	phy = kmalloc(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;
+
+	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_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;
+	}
+
+	if (phy_is_ulpi(phy)) {
+		ulpi_config = 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;
+		}
+		tegra_gpio_enable(ulpi_config->reset_gpio);
+		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 = regs + ULPI_VIEWPORT;
+	} else {
+		err = utmip_pad_open(phy);
+		if (err < 0)
+			goto err1;
+	}
+
+	return phy;
+
+err1:
+	clk_disable(phy->pll_u);
+	clk_put(phy->pll_u);
+err0:
+	kfree(phy);
+	return ERR_PTR(err);
+}
+
+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);
+}
+
+void tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		ulpi_phy_power_off(phy);
+	else
+		utmi_phy_power_off(phy);
+}
+
+void tegra_usb_phy_preresume(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_preresume(phy);
+}
+
+void tegra_usb_phy_postresume(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_postresume(phy);
+}
+
+void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
+				 enum tegra_usb_phy_port_speed port_speed)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_restore_start(phy, port_speed);
+}
+
+void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_restore_end(phy);
+}
+
+void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_clk_disable(phy);
+}
+
+void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_clk_enable(phy);
+}
+
+void tegra_usb_phy_close(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		clk_put(phy->clk);
+	else
+		utmip_pad_close(phy);
+	clk_disable(phy->pll_u);
+	clk_put(phy->pll_u);
+	kfree(phy);
+}
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index aa53ee2..513d6ab 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -3,7 +3,7 @@
  * arch/arm/mach-u300/core.c
  *
  *
- * Copyright (C) 2007-2010 ST-Ericsson AB
+ * Copyright (C) 2007-2010 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  * Core platform support, IRQ handling and device definitions.
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -16,7 +16,9 @@
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
+#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
@@ -96,10 +98,20 @@ void __init u300_map_io(void)
  * Declaration of devices found on the U300 board and
  * their respective memory locations.
  */
+
+static struct amba_pl011_data uart0_plat_data = {
+#ifdef CONFIG_COH901318
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_UART0_RX,
+	.dma_tx_param = (void *) U300_DMA_UART0_TX,
+#endif
+};
+
 static struct amba_device uart0_device = {
 	.dev = {
+		.coherent_dma_mask = ~0,
 		.init_name = "uart0", /* Slow device at 0x3000 offset */
-		.platform_data = NULL,
+		.platform_data = &uart0_plat_data,
 	},
 	.res = {
 		.start = U300_UART0_BASE,
@@ -111,10 +123,19 @@ static struct amba_device uart0_device = {
 
 /* The U335 have an additional UART1 on the APP CPU */
 #ifdef CONFIG_MACH_U300_BS335
+static struct amba_pl011_data uart1_plat_data = {
+#ifdef CONFIG_COH901318
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_UART1_RX,
+	.dma_tx_param = (void *) U300_DMA_UART1_TX,
+#endif
+};
+
 static struct amba_device uart1_device = {
 	.dev = {
+		.coherent_dma_mask = ~0,
 		.init_name = "uart1", /* Fast device at 0x7000 offset */
-		.platform_data = NULL,
+		.platform_data = &uart1_plat_data,
 	},
 	.res = {
 		.start = U300_UART1_BASE,
@@ -960,42 +981,37 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
 		.priority_high = 0,
 		.dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220,
 	},
+	/*
+	 * Don't set up device address, burst count or size of src
+	 * or dst bus for this peripheral - handled by PrimeCell
+	 * DMA extension.
+	 */
 	{
 		.number = U300_DMA_MMCSD_RX_TX,
 		.name = "MMCSD RX TX",
 		.priority_high = 0,
-		.dev_addr =  U300_MMCSD_BASE + 0x080,
 		.param.config = COH901318_CX_CFG_CH_DISABLE |
 				COH901318_CX_CFG_LCR_DISABLE |
 				COH901318_CX_CFG_TC_IRQ_ENABLE |
 				COH901318_CX_CFG_BE_IRQ_ENABLE,
 		.param.ctrl_lli_chained = 0 |
 				COH901318_CX_CTRL_TC_ENABLE |
-				COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_ENABLE |
-				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
 				COH901318_CX_CTRL_HSP_ENABLE |
 				COH901318_CX_CTRL_HSS_DISABLE |
 				COH901318_CX_CTRL_DDMA_LEGACY,
 		.param.ctrl_lli = 0 |
 				COH901318_CX_CTRL_TC_ENABLE |
-				COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_ENABLE |
-				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
 				COH901318_CX_CTRL_HSP_ENABLE |
 				COH901318_CX_CTRL_HSS_DISABLE |
 				COH901318_CX_CTRL_DDMA_LEGACY,
 		.param.ctrl_lli_last = 0 |
 				COH901318_CX_CTRL_TC_ENABLE |
-				COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_DISABLE |
 				COH901318_CX_CTRL_TC_IRQ_ENABLE |
@@ -1014,15 +1030,76 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
 		.name = "MSPRO RX",
 		.priority_high = 0,
 	},
+	/*
+	 * Don't set up device address, burst count or size of src
+	 * or dst bus for this peripheral - handled by PrimeCell
+	 * DMA extension.
+	 */
 	{
 		.number = U300_DMA_UART0_TX,
 		.name = "UART0 TX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
 	},
 	{
 		.number = U300_DMA_UART0_RX,
 		.name = "UART0 RX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
 	},
 	{
 		.number = U300_DMA_APEX_TX,
@@ -1080,7 +1157,7 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
 				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_ENABLE |
-				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
 				COH901318_CX_CTRL_HSP_ENABLE |
 				COH901318_CX_CTRL_HSS_DISABLE |
 				COH901318_CX_CTRL_DDMA_LEGACY |
@@ -1252,15 +1329,77 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
 		.name = "XGAM PDI",
 		.priority_high = 0,
 	},
+	/*
+	 * Don't set up device address, burst count or size of src
+	 * or dst bus for this peripheral - handled by PrimeCell
+	 * DMA extension.
+	 */
 	{
 		.number = U300_DMA_SPI_TX,
 		.name = "SPI TX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
 	},
 	{
 		.number = U300_DMA_SPI_RX,
 		.name = "SPI RX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+
 	},
 	{
 		.number = U300_DMA_GENERAL_PURPOSE_0,
@@ -1617,7 +1756,7 @@ static void __init u300_init_check_chip(void)
 #endif
 #ifdef CONFIG_MACH_U300_BS335
 	if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
-		printk(KERN_ERR "Platform configured for BS365 " \
+		printk(KERN_ERR "Platform configured for BS335 " \
 		       " with DB3350 but %s detected, expect problems!",
 		       chipname);
 	}
@@ -1692,12 +1831,12 @@ void __init u300_init_devices(void)
 	/* Register subdevices on the I2C buses */
 	u300_i2c_register_board_devices();
 
-	/* Register subdevices on the SPI bus */
-	u300_spi_register_board_devices();
-
 	/* Register the platform devices */
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
+	/* Register subdevices on the SPI bus */
+	u300_spi_register_board_devices();
+
 #ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
 	/*
 	 * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
diff --git a/arch/arm/mach-u300/include/mach/coh901318.h b/arch/arm/mach-u300/include/mach/coh901318.h
index 6193aaa..7c3b2b2 100644
--- a/arch/arm/mach-u300/include/mach/coh901318.h
+++ b/arch/arm/mach-u300/include/mach/coh901318.h
@@ -102,6 +102,7 @@ struct coh901318_platform {
 	const int max_channels;
 };
 
+#ifdef CONFIG_COH901318
 /**
  * coh901318_filter_id() - DMA channel filter function
  * @chan: dma channel handle
@@ -110,6 +111,12 @@ struct coh901318_platform {
  * In dma_request_channel() it specifies what channel id to be requested
  */
 bool coh901318_filter_id(struct dma_chan *chan, void *chan_id);
+#else
+static inline bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
+{
+	return false;
+}
+#endif
 
 /*
  * DMA Controller - this access the static mappings of the coh901318 dma.
diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h
index bf134bc..888e2e3 100644
--- a/arch/arm/mach-u300/include/mach/memory.h
+++ b/arch/arm/mach-u300/include/mach/memory.h
@@ -15,17 +15,17 @@
 
 #ifdef CONFIG_MACH_U300_DUAL_RAM
 
-#define PHYS_OFFSET		UL(0x48000000)
+#define PLAT_PHYS_OFFSET		UL(0x48000000)
 #define BOOT_PARAMS_OFFSET	(PHYS_OFFSET + 0x100)
 
 #else
 
 #ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PHYS_OFFSET (0x28000000 + \
+#define PLAT_PHYS_OFFSET (0x28000000 + \
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
 #else
-#define PHYS_OFFSET (0x28000000 + \
+#define PLAT_PHYS_OFFSET (0x28000000 + \
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE +	\
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
 #endif
diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c
index de1ac9a..677ccef 100644
--- a/arch/arm/mach-u300/mmc.c
+++ b/arch/arm/mach-u300/mmc.c
@@ -3,159 +3,52 @@
  * arch/arm/mach-u300/mmc.c
  *
  *
- * Copyright (C) 2009 ST-Ericsson AB
+ * Copyright (C) 2009 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  *
  * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Johan Lundin <johan.lundin@stericsson.com>
+ * Author: Johan Lundin
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  */
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/mmc/host.h>
-#include <linux/input.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/regulator/consumer.h>
-#include <linux/regulator/machine.h>
 #include <linux/gpio.h>
+#include <linux/dmaengine.h>
 #include <linux/amba/mmci.h>
 #include <linux/slab.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
 
 #include "mmc.h"
 #include "padmux.h"
 
-struct mmci_card_event {
-	struct input_dev *mmc_input;
-	int mmc_inserted;
-	struct work_struct workq;
-	struct mmci_platform_data mmc0_plat_data;
+static struct mmci_platform_data mmc0_plat_data = {
+	/*
+	 * Do not set ocr_mask or voltage translation function,
+	 * we have a regulator we can control instead.
+	 */
+	/* Nominally 2.85V on our platform */
+	.f_max = 24000000,
+	.gpio_wp = -1,
+	.gpio_cd = U300_GPIO_PIN_MMC_CD,
+	.cd_invert = true,
+	.capabilities = MMC_CAP_MMC_HIGHSPEED |
+	MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+#ifdef CONFIG_COH901318
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_MMCSD_RX_TX,
+	/* Don't specify a TX channel, this RX channel is bidirectional */
+#endif
 };
 
-static unsigned int mmc_status(struct device *dev)
-{
-	struct mmci_card_event *mmci_card = container_of(
-		dev->platform_data,
-		struct mmci_card_event, mmc0_plat_data);
-
-	return mmci_card->mmc_inserted;
-}
-
-static int mmci_callback(void *data)
-{
-	struct mmci_card_event *mmci_card = data;
-
-	disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
-	schedule_work(&mmci_card->workq);
-
-	return 0;
-}
-
-
-static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
-		  char *buf)
-{
-	struct mmci_card_event *mmci_card = container_of(
-		dev->platform_data,
-		struct mmci_card_event, mmc0_plat_data);
-
-
-	return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
-}
-
-static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
-
-static void _mmci_callback(struct work_struct *ws)
-{
-
-	struct mmci_card_event *mmci_card = container_of(
-		ws,
-		struct mmci_card_event, workq);
-
-	mdelay(20);
-
-	mmci_card->mmc_inserted = !gpio_get_value(U300_GPIO_PIN_MMC_CD);
-
-	input_report_switch(mmci_card->mmc_input, KEY_INSERT,
-			    mmci_card->mmc_inserted);
-	input_sync(mmci_card->mmc_input);
-
-	pr_debug("MMC/SD card was %s\n",
-		 mmci_card->mmc_inserted ? "inserted" : "removed");
-
-	enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, mmci_card->mmc_inserted);
-}
-
 int __devinit mmc_init(struct amba_device *adev)
 {
-	struct mmci_card_event *mmci_card;
 	struct device *mmcsd_device = &adev->dev;
 	struct pmx *pmx;
 	int ret = 0;
 
-	mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
-	if (!mmci_card)
-		return -ENOMEM;
-
-	/*
-	 * Do not set ocr_mask or voltage translation function,
-	 * we have a regulator we can control instead.
-	 */
-	/* Nominally 2.85V on our platform */
-	mmci_card->mmc0_plat_data.f_max = 24000000;
-	mmci_card->mmc0_plat_data.status = mmc_status;
-	mmci_card->mmc0_plat_data.gpio_wp = -1;
-	mmci_card->mmc0_plat_data.gpio_cd = -1;
-	mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED |
-		MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-
-	mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
-
-	INIT_WORK(&mmci_card->workq, _mmci_callback);
-
-	ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
-	if (ret) {
-		printk(KERN_CRIT "Could not allocate MMC card detection " \
-		       "GPIO pin\n");
-		goto out;
-	}
-
-	ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
-	if (ret) {
-		printk(KERN_CRIT "Invalid GPIO pin requested\n");
-		goto out;
-	}
-
-	ret = sysfs_create_file(&mmcsd_device->kobj,
-			       &dev_attr_mmc_inserted.attr);
-	if (ret)
-		goto out;
-
-	mmci_card->mmc_input = input_allocate_device();
-	if (!mmci_card->mmc_input) {
-		printk(KERN_CRIT "Could not allocate MMC input device\n");
-		return -ENOMEM;
-	}
-
-	mmci_card->mmc_input->name = "MMC insert notification";
-	mmci_card->mmc_input->id.bustype = BUS_HOST;
-	mmci_card->mmc_input->id.vendor = 0;
-	mmci_card->mmc_input->id.product = 0;
-	mmci_card->mmc_input->id.version = 0x0100;
-	mmci_card->mmc_input->dev.parent = mmcsd_device;
-	input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
-
-	/*
-	 * Since this must always be compiled into the kernel, this input
-	 * is never unregistered or free:ed.
-	 */
-	ret = input_register_device(mmci_card->mmc_input);
-	if (ret) {
-		input_free_device(mmci_card->mmc_input);
-		goto out;
-	}
-
-	input_set_drvdata(mmci_card->mmc_input, mmci_card);
+	mmcsd_device->platform_data = &mmc0_plat_data;
 
 	/*
 	 * Setup padmuxing for MMC. Since this must always be
@@ -171,12 +64,5 @@ int __devinit mmc_init(struct amba_device *adev)
 			pr_warning("Could not activate padmuxing\n");
 	}
 
-	ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
-				     mmci_card);
-
-	schedule_work(&mmci_card->workq);
-
-	printk(KERN_INFO "Registered MMC insert/remove notification\n");
-out:
 	return ret;
 }
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index 00869de..5767208 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -11,6 +11,9 @@
 #include <linux/spi/spi.h>
 #include <linux/amba/pl022.h>
 #include <linux/err.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
+
 #include "padmux.h"
 
 /*
@@ -30,11 +33,8 @@ static void select_dummy_chip(u32 chipselect)
 }
 
 struct pl022_config_chip dummy_chip_info = {
-	/*
-	 * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
-	 * DMA_TRANSFER does not work
-	 */
-	.com_mode = INTERRUPT_TRANSFER,
+	/* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
+	.com_mode = DMA_TRANSFER,
 	.iface = SSP_INTERFACE_MOTOROLA_SPI,
 	/* We can only act as master but SSP_SLAVE is possible in theory */
 	.hierarchy = SSP_MASTER,
@@ -75,8 +75,6 @@ static struct spi_board_info u300_spi_devices[] = {
 static struct pl022_ssp_controller ssp_platform_data = {
 	/* If you have several SPI buses this varies, we have only bus 0 */
 	.bus_id = 0,
-	/* Set this to 1 when we think we got DMA working */
-	.enable_dma = 0,
 	/*
 	 * On the APP CPU GPIO 4, 5 and 6 are connected as generic
 	 * chip selects for SPI. (Same on U330, U335 and U365.)
@@ -84,6 +82,14 @@ static struct pl022_ssp_controller ssp_platform_data = {
 	 * and do padmuxing accordingly too.
 	 */
 	.num_chipselect = 3,
+#ifdef CONFIG_COH901318
+	.enable_dma = 1,
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_SPI_RX,
+	.dma_tx_param = (void *) U300_DMA_SPI_TX,
+#else
+	.enable_dma = 0,
+#endif
 };
 
 
@@ -109,6 +115,7 @@ void __init u300_spi_init(struct amba_device *adev)
 	}
 
 }
+
 void __init u300_spi_register_board_devices(void)
 {
 	/* Register any SPI devices */
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
index 07c35a8..48b3b7f 100644
--- a/arch/arm/mach-u300/u300.c
+++ b/arch/arm/mach-u300/u300.c
@@ -19,9 +19,9 @@
 #include <linux/io.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <mach/memory.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/memory.h>
 
 static void __init u300_reserve(void)
 {
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 247caa3..203b986 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -6,6 +6,7 @@ config UX500_SOC_COMMON
 	select ARM_GIC
 	select HAS_MTU
 	select NOMADIK_GPIO
+	select ARM_ERRATA_753970
 
 menu "Ux500 SoC"
 
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 53ebb42..b549a8f 100644
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -3,16 +3,18 @@
 #
 
 obj-y				:= clock.o cpu.o devices.o devices-common.o \
-				   id.o
+				   id.o usb.o
 obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o prcmu.o
 obj-$(CONFIG_MACH_U8500)	+= board-mop500.o board-mop500-sdi.o \
-				board-mop500-keypads.o
+				board-mop500-regulators.o \
+				board-mop500-uib.o board-mop500-stuib.o \
+				board-mop500-u8500uib.o \
+				board-mop500-pins.o
 obj-$(CONFIG_MACH_U5500)	+= board-u5500.o board-u5500-sdi.o
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-obj-$(CONFIG_REGULATOR_AB8500)	+= board-mop500-regulators.o
 obj-$(CONFIG_U5500_MODEM_IRQ)	+= modem-irq-db5500.o
 obj-$(CONFIG_U5500_MBOX)	+= mbox-db5500.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c
deleted file mode 100644
index 70318c3..0000000
--- a/arch/arm/mach-ux500/board-mop500-keypads.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- *
- * Keypad layouts for various boards
- */
-
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/stmpe.h>
-#include <linux/mfd/tc3589x.h>
-#include <linux/input/matrix_keypad.h>
-
-#include <plat/pincfg.h>
-#include <plat/ske.h>
-
-#include <mach/devices.h>
-#include <mach/hardware.h>
-
-#include "devices-db8500.h"
-#include "board-mop500.h"
-
-/* STMPE/SKE keypad use this key layout */
-static const unsigned int mop500_keymap[] = {
-	KEY(2, 5, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(3, 5, KEY_VOLUMEDOWN),
-	KEY(1, 3, KEY_3),
-	KEY(5, 2, KEY_RIGHT),
-	KEY(5, 0, KEY_9),
-
-	KEY(0, 5, KEY_MENU),
-	KEY(7, 6, KEY_ENTER),
-	KEY(4, 5, KEY_0),
-	KEY(6, 7, KEY_2),
-	KEY(3, 4, KEY_UP),
-	KEY(3, 3, KEY_DOWN),
-
-	KEY(6, 4, KEY_SEND),
-	KEY(6, 2, KEY_BACK),
-	KEY(4, 2, KEY_VOLUMEUP),
-	KEY(5, 5, KEY_1),
-	KEY(4, 3, KEY_LEFT),
-	KEY(3, 2, KEY_7),
-};
-
-static const struct matrix_keymap_data mop500_keymap_data = {
-	.keymap		= mop500_keymap,
-	.keymap_size    = ARRAY_SIZE(mop500_keymap),
-};
-
-/*
- * Nomadik SKE keypad
- */
-#define ROW_PIN_I0      164
-#define ROW_PIN_I1      163
-#define ROW_PIN_I2      162
-#define ROW_PIN_I3      161
-#define ROW_PIN_I4      156
-#define ROW_PIN_I5      155
-#define ROW_PIN_I6      154
-#define ROW_PIN_I7      153
-#define COL_PIN_O0      168
-#define COL_PIN_O1      167
-#define COL_PIN_O2      166
-#define COL_PIN_O3      165
-#define COL_PIN_O4      160
-#define COL_PIN_O5      159
-#define COL_PIN_O6      158
-#define COL_PIN_O7      157
-
-#define SKE_KPD_MAX_ROWS	8
-#define SKE_KPD_MAX_COLS	8
-
-static int ske_kp_rows[] = {
-	ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
-	ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
-};
-
-/*
- * ske_set_gpio_row: request and set gpio rows
- */
-static int ske_set_gpio_row(int gpio)
-{
-	int ret;
-
-	ret = gpio_request(gpio, "ske-kp");
-	if (ret < 0) {
-		pr_err("ske_set_gpio_row: gpio request failed\n");
-		return ret;
-	}
-
-	ret = gpio_direction_output(gpio, 1);
-	if (ret < 0) {
-		pr_err("ske_set_gpio_row: gpio direction failed\n");
-		gpio_free(gpio);
-	}
-
-	return ret;
-}
-
-/*
- * ske_kp_init - enable the gpio configuration
- */
-static int ske_kp_init(void)
-{
-	int ret, i;
-
-	for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
-		ret = ske_set_gpio_row(ske_kp_rows[i]);
-		if (ret < 0) {
-			pr_err("ske_kp_init: failed init\n");
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static struct ske_keypad_platform_data ske_keypad_board = {
-	.init		= ske_kp_init,
-	.keymap_data    = &mop500_keymap_data,
-	.no_autorepeat  = true,
-	.krow		= SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
-	.kcol		= SKE_KPD_MAX_COLS,
-	.debounce_ms    = 40,			/* in millisecs */
-};
-
-/*
- * STMPE1601
- */
-static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
-	.debounce_ms    = 64,
-	.scan_count     = 8,
-	.no_autorepeat  = true,
-	.keymap_data    = &mop500_keymap_data,
-};
-
-static struct stmpe_platform_data stmpe1601_data = {
-	.id             = 1,
-	.blocks         = STMPE_BLOCK_KEYPAD,
-	.irq_trigger    = IRQF_TRIGGER_FALLING,
-	.irq_base       = MOP500_STMPE1601_IRQ(0),
-	.keypad         = &stmpe1601_keypad_data,
-	.autosleep      = true,
-	.autosleep_timeout = 1024,
-};
-
-static struct i2c_board_info mop500_i2c0_devices_stuib[] = {
-	{
-		I2C_BOARD_INFO("stmpe1601", 0x40),
-		.irq = NOMADIK_GPIO_TO_IRQ(218),
-		.platform_data = &stmpe1601_data,
-		.flags = I2C_CLIENT_WAKE,
-	},
-};
-
-/*
- * TC35893
- */
-
-static const unsigned int uib_keymap[] = {
-	KEY(3, 1, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(6, 4, KEY_VOLUMEDOWN),
-	KEY(4, 2, KEY_EMAIL),
-	KEY(3, 3, KEY_RIGHT),
-	KEY(2, 5, KEY_BACKSPACE),
-
-	KEY(6, 7, KEY_MENU),
-	KEY(5, 0, KEY_ENTER),
-	KEY(4, 3, KEY_0),
-	KEY(3, 4, KEY_DOT),
-	KEY(5, 2, KEY_UP),
-	KEY(3, 5, KEY_DOWN),
-
-	KEY(4, 5, KEY_SEND),
-	KEY(0, 5, KEY_BACK),
-	KEY(6, 2, KEY_VOLUMEUP),
-	KEY(1, 3, KEY_SPACE),
-	KEY(7, 6, KEY_LEFT),
-	KEY(5, 5, KEY_SEARCH),
-};
-
-static struct matrix_keymap_data uib_keymap_data = {
-	.keymap         = uib_keymap,
-	.keymap_size    = ARRAY_SIZE(uib_keymap),
-};
-
-static struct tc3589x_keypad_platform_data tc35893_data = {
-	.krow = TC_KPD_ROWS,
-	.kcol = TC_KPD_COLUMNS,
-	.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
-	.settle_time = TC_KPD_SETTLE_TIME,
-	.irqtype = IRQF_TRIGGER_FALLING,
-	.enable_wakeup = true,
-	.keymap_data    = &uib_keymap_data,
-	.no_autorepeat  = true,
-};
-
-static struct tc3589x_platform_data tc3589x_keypad_data = {
-	.block = TC3589x_BLOCK_KEYPAD,
-	.keypad = &tc35893_data,
-	.irq_base = MOP500_EGPIO_IRQ_BASE,
-};
-
-static struct i2c_board_info mop500_i2c0_devices_uib[] = {
-	{
-		I2C_BOARD_INFO("tc3589x", 0x44),
-		.platform_data = &tc3589x_keypad_data,
-		.irq = NOMADIK_GPIO_TO_IRQ(218),
-		.flags = I2C_CLIENT_WAKE,
-	},
-};
-
-void mop500_keypad_init(void)
-{
-	db8500_add_ske_keypad(&ske_keypad_board);
-
-	i2c_register_board_info(0, mop500_i2c0_devices_stuib,
-			ARRAY_SIZE(mop500_i2c0_devices_stuib));
-
-	i2c_register_board_info(0, mop500_i2c0_devices_uib,
-			ARRAY_SIZE(mop500_i2c0_devices_uib));
-
-}
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
new file mode 100644
index 0000000..fd4cf1c
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <plat/pincfg.h>
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+
+static pin_cfg_t mop500_pins_common[] = {
+	/* I2C */
+	GPIO147_I2C0_SCL,
+	GPIO148_I2C0_SDA,
+	GPIO16_I2C1_SCL,
+	GPIO17_I2C1_SDA,
+	GPIO10_I2C2_SDA,
+	GPIO11_I2C2_SCL,
+	GPIO229_I2C3_SDA,
+	GPIO230_I2C3_SCL,
+
+	/* MSP0 */
+	GPIO12_MSP0_TXD,
+	GPIO13_MSP0_TFS,
+	GPIO14_MSP0_TCK,
+	GPIO15_MSP0_RXD,
+
+	/* MSP2: HDMI */
+	GPIO193_MSP2_TXD,
+	GPIO194_MSP2_TCK,
+	GPIO195_MSP2_TFS,
+	GPIO196_MSP2_RXD | PIN_OUTPUT_LOW,
+
+	/* Touch screen INTERFACE */
+	GPIO84_GPIO	| PIN_INPUT_PULLUP, /* TOUCH_INT1 */
+
+	/* STMPE1601/tc35893 keypad  IRQ */
+	GPIO218_GPIO	| PIN_INPUT_PULLUP,
+
+	/* MMC0 (MicroSD card) */
+	GPIO18_MC0_CMDDIR	| PIN_OUTPUT_HIGH,
+	GPIO19_MC0_DAT0DIR	| PIN_OUTPUT_HIGH,
+	GPIO20_MC0_DAT2DIR	| PIN_OUTPUT_HIGH,
+
+	GPIO22_MC0_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO23_MC0_CLK		| PIN_OUTPUT_LOW,
+	GPIO24_MC0_CMD		| PIN_INPUT_PULLUP,
+	GPIO25_MC0_DAT0		| PIN_INPUT_PULLUP,
+	GPIO26_MC0_DAT1		| PIN_INPUT_PULLUP,
+	GPIO27_MC0_DAT2		| PIN_INPUT_PULLUP,
+	GPIO28_MC0_DAT3		| PIN_INPUT_PULLUP,
+
+	/* SDI1 (SDIO) */
+	GPIO208_MC1_CLK		| PIN_OUTPUT_LOW,
+	GPIO209_MC1_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO210_MC1_CMD		| PIN_INPUT_PULLUP,
+	GPIO211_MC1_DAT0	| PIN_INPUT_PULLUP,
+	GPIO212_MC1_DAT1	| PIN_INPUT_PULLUP,
+	GPIO213_MC1_DAT2	| PIN_INPUT_PULLUP,
+	GPIO214_MC1_DAT3	| PIN_INPUT_PULLUP,
+
+	/* MMC2 (On-board DATA INTERFACE eMMC) */
+	GPIO128_MC2_CLK		| PIN_OUTPUT_LOW,
+	GPIO129_MC2_CMD		| PIN_INPUT_PULLUP,
+	GPIO130_MC2_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO131_MC2_DAT0	| PIN_INPUT_PULLUP,
+	GPIO132_MC2_DAT1	| PIN_INPUT_PULLUP,
+	GPIO133_MC2_DAT2	| PIN_INPUT_PULLUP,
+	GPIO134_MC2_DAT3	| PIN_INPUT_PULLUP,
+	GPIO135_MC2_DAT4	| PIN_INPUT_PULLUP,
+	GPIO136_MC2_DAT5	| PIN_INPUT_PULLUP,
+	GPIO137_MC2_DAT6	| PIN_INPUT_PULLUP,
+	GPIO138_MC2_DAT7	| PIN_INPUT_PULLUP,
+
+	/* MMC4 (On-board STORAGE INTERFACE eMMC) */
+	GPIO197_MC4_DAT3	| PIN_INPUT_PULLUP,
+	GPIO198_MC4_DAT2	| PIN_INPUT_PULLUP,
+	GPIO199_MC4_DAT1	| PIN_INPUT_PULLUP,
+	GPIO200_MC4_DAT0	| PIN_INPUT_PULLUP,
+	GPIO201_MC4_CMD		| PIN_INPUT_PULLUP,
+	GPIO202_MC4_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO203_MC4_CLK		| PIN_OUTPUT_LOW,
+	GPIO204_MC4_DAT7	| PIN_INPUT_PULLUP,
+	GPIO205_MC4_DAT6	| PIN_INPUT_PULLUP,
+	GPIO206_MC4_DAT5	| PIN_INPUT_PULLUP,
+	GPIO207_MC4_DAT4	| PIN_INPUT_PULLUP,
+
+	/* SKE keypad */
+	GPIO153_KP_I7,
+	GPIO154_KP_I6,
+	GPIO155_KP_I5,
+	GPIO156_KP_I4,
+	GPIO157_KP_O7,
+	GPIO158_KP_O6,
+	GPIO159_KP_O5,
+	GPIO160_KP_O4,
+	GPIO161_KP_I3,
+	GPIO162_KP_I2,
+	GPIO163_KP_I1,
+	GPIO164_KP_I0,
+	GPIO165_KP_O3,
+	GPIO166_KP_O2,
+	GPIO167_KP_O1,
+	GPIO168_KP_O0,
+
+	/* UART */
+	GPIO0_U0_CTSn	| PIN_INPUT_PULLUP,
+	GPIO1_U0_RTSn	| PIN_OUTPUT_HIGH,
+	GPIO2_U0_RXD	| PIN_INPUT_PULLUP,
+	GPIO3_U0_TXD	| PIN_OUTPUT_HIGH,
+
+	GPIO29_U2_RXD	| PIN_INPUT_PULLUP,
+	GPIO30_U2_TXD	| PIN_OUTPUT_HIGH,
+	GPIO31_U2_CTSn	| PIN_INPUT_PULLUP,
+	GPIO32_U2_RTSn	| PIN_OUTPUT_HIGH,
+
+	/* Display & HDMI HW sync */
+	GPIO68_LCD_VSI0	| PIN_INPUT_PULLUP,
+	GPIO69_LCD_VSI1	| PIN_INPUT_PULLUP,
+};
+
+static pin_cfg_t mop500_pins_default[] = {
+	/* SSP0 */
+	GPIO143_SSP0_CLK,
+	GPIO144_SSP0_FRM,
+	GPIO145_SSP0_RXD | PIN_PULL_DOWN,
+	GPIO146_SSP0_TXD,
+
+
+	GPIO217_GPIO	| PIN_INPUT_PULLUP, /* TC35892 IRQ */
+
+	/* SDI0 (MicroSD card) */
+	GPIO21_MC0_DAT31DIR	| PIN_OUTPUT_HIGH,
+
+	/* UART */
+	GPIO4_U1_RXD	| PIN_INPUT_PULLUP,
+	GPIO5_U1_TXD	| PIN_OUTPUT_HIGH,
+	GPIO6_U1_CTSn	| PIN_INPUT_PULLUP,
+	GPIO7_U1_RTSn	| PIN_OUTPUT_HIGH,
+};
+
+static pin_cfg_t mop500_pins_hrefv60[] = {
+	/* WLAN */
+	GPIO4_GPIO		| PIN_INPUT_PULLUP,/* WLAN_IRQ */
+	GPIO85_GPIO		| PIN_OUTPUT_LOW,/* WLAN_ENA */
+
+	/* XENON Flashgun INTERFACE */
+	GPIO6_IP_GPIO0	| PIN_INPUT_PULLUP,/* XENON_FLASH_ID */
+	GPIO7_IP_GPIO1	| PIN_INPUT_PULLUP,/* XENON_READY */
+	GPIO170_GPIO	| PIN_OUTPUT_LOW, /* XENON_CHARGE */
+
+	/* Assistant LED INTERFACE */
+	GPIO21_GPIO | PIN_OUTPUT_LOW,  /* XENON_EN1 */
+	GPIO64_IP_GPIO4 | PIN_OUTPUT_LOW,  /* XENON_EN2 */
+
+	/* Magnetometer */
+	GPIO31_GPIO | PIN_INPUT_PULLUP,  /* magnetometer_INT */
+	GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */
+
+	/* Display Interface */
+	GPIO65_GPIO		| PIN_OUTPUT_LOW, /* DISP1 RST */
+	GPIO66_GPIO		| PIN_OUTPUT_LOW, /* DISP2 RST */
+
+	/* Touch screen INTERFACE */
+	GPIO143_GPIO	| PIN_OUTPUT_LOW,/*TOUCH_RST1 */
+
+	/* Touch screen INTERFACE 2 */
+	GPIO67_GPIO	| PIN_INPUT_PULLUP, /* TOUCH_INT2 */
+	GPIO146_GPIO	| PIN_OUTPUT_LOW,/*TOUCH_RST2 */
+
+	/* ETM_PTM_TRACE INTERFACE */
+	GPIO70_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA23 */
+	GPIO71_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA22 */
+	GPIO72_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA21 */
+	GPIO73_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA20 */
+	GPIO74_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA19 */
+
+	/* NAHJ INTERFACE */
+	GPIO76_GPIO	| PIN_OUTPUT_LOW,/* NAHJ_CTRL */
+	GPIO216_GPIO	| PIN_OUTPUT_HIGH,/* NAHJ_CTRL_INV */
+
+	/* NFC INTERFACE */
+	GPIO77_GPIO	| PIN_OUTPUT_LOW, /* NFC_ENA */
+	GPIO144_GPIO	| PIN_INPUT_PULLDOWN, /* NFC_IRQ */
+	GPIO142_GPIO	| PIN_OUTPUT_LOW, /* NFC_RESET */
+
+	/* Keyboard MATRIX INTERFACE */
+	GPIO90_MC5_CMD	| PIN_OUTPUT_LOW, /* KP_O_1 */
+	GPIO87_MC5_DAT1	| PIN_OUTPUT_LOW, /* KP_O_2 */
+	GPIO86_MC5_DAT0	| PIN_OUTPUT_LOW, /* KP_O_3 */
+	GPIO96_KP_O6	| PIN_OUTPUT_LOW, /* KP_O_6 */
+	GPIO94_KP_O7	| PIN_OUTPUT_LOW, /* KP_O_7 */
+	GPIO93_MC5_DAT4	| PIN_INPUT_PULLUP, /* KP_I_0 */
+	GPIO89_MC5_DAT3	| PIN_INPUT_PULLUP, /* KP_I_2 */
+	GPIO88_MC5_DAT2	| PIN_INPUT_PULLUP, /* KP_I_3 */
+	GPIO91_GPIO	| PIN_INPUT_PULLUP, /* FORCE_SENSING_INT */
+	GPIO92_GPIO	| PIN_OUTPUT_LOW, /* FORCE_SENSING_RST */
+	GPIO97_GPIO	| PIN_OUTPUT_LOW, /* FORCE_SENSING_WU */
+
+	/* DiPro Sensor Interface */
+	GPIO139_GPIO	| PIN_INPUT_PULLUP, /* DIPRO_INT */
+
+	/* HAL SWITCH INTERFACE */
+	GPIO145_GPIO	| PIN_INPUT_PULLDOWN,/* HAL_SW */
+
+	/* Audio Amplifier Interface */
+	GPIO149_GPIO	| PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */
+
+	/* GBF INTERFACE */
+	GPIO171_GPIO	| PIN_OUTPUT_LOW, /* GBF_ENA_RESET */
+
+	/* MSP : HDTV INTERFACE */
+	GPIO192_GPIO	| PIN_INPUT_PULLDOWN,
+
+	/* ACCELEROMETER_INTERFACE */
+	GPIO82_GPIO		| PIN_INPUT_PULLUP, /* ACC_INT1 */
+	GPIO83_GPIO		| PIN_INPUT_PULLUP, /* ACC_INT2 */
+
+	/* Proximity Sensor */
+	GPIO217_GPIO		| PIN_INPUT_PULLUP,
+
+
+};
+
+void __init mop500_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+				ARRAY_SIZE(mop500_pins_common));
+	if (machine_is_hrefv60())
+		nmk_config_pins(mop500_pins_hrefv60,
+				ARRAY_SIZE(mop500_pins_hrefv60));
+	else
+		nmk_config_pins(mop500_pins_default,
+				ARRAY_SIZE(mop500_pins_default));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c
index 533967c..875c91b 100644
--- a/arch/arm/mach-ux500/board-mop500-regulators.c
+++ b/arch/arm/mach-ux500/board-mop500-regulators.c
@@ -11,6 +11,56 @@
 #include <linux/kernel.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
+#include "board-mop500-regulators.h"
+
+static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
+	/* External displays, connector on board 2v5 power supply */
+	REGULATOR_SUPPLY("vaux12v5", "mcde.0"),
+	/* 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"),
+	/* lsm303dlh magnetometer */
+	REGULATOR_SUPPLY("vdd", "3-001e"),
+	/* Rohm BU21013 Touchscreen devices */
+	REGULATOR_SUPPLY("avdd", "3-005c"),
+	REGULATOR_SUPPLY("avdd", "3-005d"),
+	/* Synaptics RMI4 Touchscreen device */
+	REGULATOR_SUPPLY("vdd", "3-004b"),
+};
+
+static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
+	/* On-board eMMC power */
+	REGULATOR_SUPPLY("vmmc", "sdi4"),
+	/* AB8500 audio codec */
+	REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
+	/* External MMC slot power */
+	REGULATOR_SUPPLY("vmmc", "sdi0"),
+};
+
+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"),
+};
+
+static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
+	/* SoC core supply, no device */
+	REGULATOR_SUPPLY("v-intcore", NULL),
+	/* USB Transciever */
+	REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vana_consumers[] = {
+	/* External displays, connector on board, 1v8 power supply */
+	REGULATOR_SUPPLY("vsmps2", "mcde.0"),
+};
 
 /* AB8500 regulators */
 struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
@@ -23,6 +73,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
+		.consumer_supplies = ab8500_vaux1_consumers,
 	},
 	/* supplies to the on-board eMMC */
 	[AB8500_LDO_AUX2] = {
@@ -33,6 +85,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
+		.consumer_supplies = ab8500_vaux2_consumers,
 	},
 	/* supply for VAUX3, supplies to SDcard slots */
 	[AB8500_LDO_AUX3] = {
@@ -43,6 +97,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
+		.consumer_supplies = ab8500_vaux3_consumers,
 	},
 	/* supply for tvout, gpadc, TVOUT LDO */
 	[AB8500_LDO_TVOUT] = {
@@ -50,6 +106,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.name = "V-TVOUT",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
+		.consumer_supplies = ab8500_vtvout_consumers,
 	},
 	/* supply for ab8500-vaudio, VAUDIO LDO */
 	[AB8500_LDO_AUDIO] = {
@@ -85,6 +143,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.name = "V-INTCORE",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
+		.consumer_supplies = ab8500_vintcore_consumers,
 	},
 	/* supply for U8500 CSI/DSI, VANA LDO */
 	[AB8500_LDO_ANA] = {
@@ -92,5 +152,7 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
 			.name = "V-CSI/DSI",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
+		.consumer_supplies = ab8500_vana_consumers,
 	},
 };
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 4b99667..bf0b024 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -12,56 +12,14 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 
-#include <plat/pincfg.h>
+#include <asm/mach-types.h>
+#include <plat/ste_dma40.h>
 #include <mach/devices.h>
 #include <mach/hardware.h>
 
 #include "devices-db8500.h"
-#include "pins-db8500.h"
 #include "board-mop500.h"
-
-static pin_cfg_t mop500_sdi_pins[] = {
-	/* SDI0 (MicroSD slot) */
-	GPIO18_MC0_CMDDIR,
-	GPIO19_MC0_DAT0DIR,
-	GPIO20_MC0_DAT2DIR,
-	GPIO21_MC0_DAT31DIR,
-	GPIO22_MC0_FBCLK,
-	GPIO23_MC0_CLK,
-	GPIO24_MC0_CMD,
-	GPIO25_MC0_DAT0,
-	GPIO26_MC0_DAT1,
-	GPIO27_MC0_DAT2,
-	GPIO28_MC0_DAT3,
-
-	/* SDI4 (on-board eMMC) */
-	GPIO197_MC4_DAT3,
-	GPIO198_MC4_DAT2,
-	GPIO199_MC4_DAT1,
-	GPIO200_MC4_DAT0,
-	GPIO201_MC4_CMD,
-	GPIO202_MC4_FBCLK,
-	GPIO203_MC4_CLK,
-	GPIO204_MC4_DAT7,
-	GPIO205_MC4_DAT6,
-	GPIO206_MC4_DAT5,
-	GPIO207_MC4_DAT4,
-};
-
-static pin_cfg_t mop500_sdi2_pins[] = {
-	/* SDI2 (POP eMMC) */
-	GPIO128_MC2_CLK,
-	GPIO129_MC2_CMD,
-	GPIO130_MC2_FBCLK,
-	GPIO131_MC2_DAT0,
-	GPIO132_MC2_DAT1,
-	GPIO133_MC2_DAT2,
-	GPIO134_MC2_DAT3,
-	GPIO135_MC2_DAT4,
-	GPIO136_MC2_DAT5,
-	GPIO137_MC2_DAT6,
-	GPIO138_MC2_DAT7,
-};
+#include "ste-dma40-db8500.h"
 
 /*
  * SDI 0 (MicroSD slot)
@@ -86,48 +44,134 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
 	       MCI_DATA2DIREN | MCI_DATA31DIREN;
 }
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data mop500_sdi0_data = {
 	.vdd_handler	= mop500_sdi0_vdd_handler,
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 100000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA,
-	.gpio_cd	= GPIO_SDMMC_CD,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &mop500_sdi0_dma_cfg_rx,
+	.dma_tx_param	= &mop500_sdi0_dma_cfg_tx,
+#endif
 };
 
-void mop500_sdi_tc35892_init(void)
+/* GPIO pins used by the sdi0 level shifter */
+static int sdi0_en = -1;
+static int sdi0_vsel = -1;
+
+static void sdi0_configure(void)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
+	ret = gpio_request(sdi0_en, "level shifter enable");
 	if (!ret)
-		ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
-				   "GPIO_SDMMC_1V8_3V_SEL");
-	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;
+	}
 
-	gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
-	gpio_direction_output(GPIO_SDMMC_EN, 0);
+	/* Select the default 2.9V and enable level shifter */
+	gpio_direction_output(sdi0_vsel, 0);
+	gpio_direction_output(sdi0_en, 1);
 
+	/* Add the device */
 	db8500_add_sdi0(&mop500_sdi0_data);
 }
 
+void mop500_sdi_tc35892_init(void)
+{
+	mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
+	sdi0_en = GPIO_SDMMC_EN;
+	sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
+	sdi0_configure();
+}
+
 /*
  * SDI 2 (POP eMMC, not on DB8500ed)
  */
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV28_SD_MM2_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data mop500_sdi2_data = {
 	.ocr_mask	= MMC_VDD_165_195,
 	.f_max		= 100000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &mop500_sdi2_dma_cfg_rx,
+	.dma_tx_param	= &mop500_sdi2_dma_cfg_tx,
+#endif
 };
 
 /*
  * SDI 4 (on-board eMMC)
  */
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV42_SD_MM4_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data mop500_sdi4_data = {
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 100000000,
@@ -135,26 +179,32 @@ static struct mmci_platform_data mop500_sdi4_data = {
 			  MMC_CAP_MMC_HIGHSPEED,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &mop500_sdi4_dma_cfg_rx,
+	.dma_tx_param	= &mop500_sdi4_dma_cfg_tx,
+#endif
 };
 
 void __init mop500_sdi_init(void)
 {
-	nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
+	/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
+	if (!cpu_is_u8500v10())
+		mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+	db8500_add_sdi2(&mop500_sdi2_data);
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data);
 
+	if (machine_is_hrefv60()) {
+		mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+		sdi0_en = HREFV60_SDMMC_EN_GPIO;
+		sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+		sdi0_configure();
+	}
 	/*
-	 * sdi0 will finally be added when the TC35892 initializes and calls
+	 * On boards with the TC35892 GPIO expander, sdi0 will finally
+	 * be added when the TC35892 initializes and calls
 	 * mop500_sdi_tc35892_init() above.
 	 */
-
-	/* PoP:ed eMMC */
-	if (!cpu_is_u8500ed()) {
-		nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
-		/* POP eMMC on v1.0 has problems with high speed */
-		if (!cpu_is_u8500v10())
-			mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
-		db8500_add_sdi2(&mop500_sdi2_data);
-	}
-
-	/* On-board eMMC */
-	db8500_add_sdi4(&mop500_sdi4_data);
 }
diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c
new file mode 100644
index 0000000..8c97977
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-stuib.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/input/bu21013.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/input/matrix_keypad.h>
+#include <asm/mach-types.h>
+
+#include "board-mop500.h"
+
+/* STMPE/SKE keypad use this key layout */
+static const unsigned int mop500_keymap[] = {
+	KEY(2, 5, KEY_END),
+	KEY(4, 1, KEY_POWER),
+	KEY(3, 5, KEY_VOLUMEDOWN),
+	KEY(1, 3, KEY_3),
+	KEY(5, 2, KEY_RIGHT),
+	KEY(5, 0, KEY_9),
+
+	KEY(0, 5, KEY_MENU),
+	KEY(7, 6, KEY_ENTER),
+	KEY(4, 5, KEY_0),
+	KEY(6, 7, KEY_2),
+	KEY(3, 4, KEY_UP),
+	KEY(3, 3, KEY_DOWN),
+
+	KEY(6, 4, KEY_SEND),
+	KEY(6, 2, KEY_BACK),
+	KEY(4, 2, KEY_VOLUMEUP),
+	KEY(5, 5, KEY_1),
+	KEY(4, 3, KEY_LEFT),
+	KEY(3, 2, KEY_7),
+};
+
+static const struct matrix_keymap_data mop500_keymap_data = {
+	.keymap		= mop500_keymap,
+	.keymap_size    = ARRAY_SIZE(mop500_keymap),
+};
+/*
+ * STMPE1601
+ */
+static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
+	.debounce_ms    = 64,
+	.scan_count     = 8,
+	.no_autorepeat  = true,
+	.keymap_data    = &mop500_keymap_data,
+};
+
+static struct stmpe_platform_data stmpe1601_data = {
+	.id		= 1,
+	.blocks		= STMPE_BLOCK_KEYPAD,
+	.irq_trigger    = IRQF_TRIGGER_FALLING,
+	.irq_base       = MOP500_STMPE1601_IRQ(0),
+	.keypad		= &stmpe1601_keypad_data,
+	.autosleep      = true,
+	.autosleep_timeout = 1024,
+};
+
+static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = {
+	{
+		I2C_BOARD_INFO("stmpe1601", 0x40),
+		.irq = NOMADIK_GPIO_TO_IRQ(218),
+		.platform_data = &stmpe1601_data,
+		.flags = I2C_CLIENT_WAKE,
+	},
+};
+
+/*
+ * BU21013 ROHM touchscreen interface on the STUIBs
+ */
+
+/* tracks number of bu21013 devices being enabled */
+static int bu21013_devices;
+
+#define TOUCH_GPIO_PIN  84
+
+#define TOUCH_XMAX	384
+#define TOUCH_YMAX	704
+
+#define PRCMU_CLOCK_OCR		0x1CC
+#define TSC_EXT_CLOCK_9_6MHZ	0x840000
+
+/**
+ * bu21013_gpio_board_init : configures the touch panel.
+ * @reset_pin: reset pin number
+ * This function can be used to configures
+ * the voltage and reset the touch panel controller.
+ */
+static int bu21013_gpio_board_init(int reset_pin)
+{
+	int retval = 0;
+
+	bu21013_devices++;
+	if (bu21013_devices == 1) {
+		retval = gpio_request(reset_pin, "touchp_reset");
+		if (retval) {
+			printk(KERN_ERR "Unable to request gpio reset_pin");
+			return retval;
+		}
+		retval = gpio_direction_output(reset_pin, 1);
+		if (retval < 0) {
+			printk(KERN_ERR "%s: gpio direction failed\n",
+					__func__);
+			return retval;
+		}
+	}
+
+	return retval;
+}
+
+/**
+ * bu21013_gpio_board_exit : deconfigures the touch panel controller
+ * @reset_pin: reset pin number
+ * This function can be used to deconfigures the chip selection
+ * for touch panel controller.
+ */
+static int bu21013_gpio_board_exit(int reset_pin)
+{
+	int retval = 0;
+
+	if (bu21013_devices == 1) {
+		retval = gpio_direction_output(reset_pin, 0);
+		if (retval < 0) {
+			printk(KERN_ERR "%s: gpio direction failed\n",
+					__func__);
+			return retval;
+		}
+		gpio_set_value(reset_pin, 0);
+	}
+	bu21013_devices--;
+
+	return retval;
+}
+
+/**
+ * bu21013_read_pin_val : get the interrupt pin value
+ * This function can be used to get the interrupt pin value for touch panel
+ * controller.
+ */
+static int bu21013_read_pin_val(void)
+{
+	return gpio_get_value(TOUCH_GPIO_PIN);
+}
+
+static struct bu21013_platform_device tsc_plat_device = {
+	.cs_en = bu21013_gpio_board_init,
+	.cs_dis = bu21013_gpio_board_exit,
+	.irq_read_val = bu21013_read_pin_val,
+	.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+	.touch_x_max = TOUCH_XMAX,
+	.touch_y_max = TOUCH_YMAX,
+	.ext_clk = false,
+	.x_flip = false,
+	.y_flip = true,
+};
+
+static struct bu21013_platform_device tsc_plat2_device = {
+	.cs_en = bu21013_gpio_board_init,
+	.cs_dis = bu21013_gpio_board_exit,
+	.irq_read_val = bu21013_read_pin_val,
+	.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+	.touch_x_max = TOUCH_XMAX,
+	.touch_y_max = TOUCH_YMAX,
+	.ext_clk = false,
+	.x_flip = false,
+	.y_flip = true,
+};
+
+static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
+	{
+		I2C_BOARD_INFO("bu21013_tp", 0x5C),
+		.platform_data = &tsc_plat_device,
+	},
+	{
+		I2C_BOARD_INFO("bu21013_tp", 0x5D),
+		.platform_data = &tsc_plat2_device,
+	},
+
+};
+
+void __init mop500_stuib_init(void)
+{
+	if (machine_is_hrefv60()) {
+		tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
+		tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
+	} else {
+		tsc_plat_device.cs_pin = GPIO_BU21013_CS;
+		tsc_plat2_device.cs_pin = GPIO_BU21013_CS;
+
+	}
+
+	mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
+			ARRAY_SIZE(mop500_i2c0_devices_stuib));
+
+	mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib,
+			ARRAY_SIZE(u8500_i2c3_devices_stuib));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
new file mode 100644
index 0000000..d8a8734
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Board data for the U8500 UIB, also known as the New UIB
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+#include <linux/input/matrix_keypad.h>
+#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h>
+
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+
+#include "board-mop500.h"
+
+/*
+ * Synaptics RMI4 touchscreen interface on the U8500 UIB
+ */
+
+/*
+ * Descriptor structure.
+ * Describes the number of i2c devices on the bus that speak RMI.
+ */
+static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
+	.irq_number     = NOMADIK_GPIO_TO_IRQ(84),
+	.irq_type       = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
+	.x_flip		= false,
+	.y_flip		= true,
+	.regulator_en   = false,
+};
+
+static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
+	{
+		I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
+		.platform_data = &rmi4_i2c_dev_platformdata,
+	},
+};
+
+/*
+ * TC35893
+ */
+static const unsigned int u8500_keymap[] = {
+	KEY(3, 1, KEY_END),
+	KEY(4, 1, KEY_POWER),
+	KEY(6, 4, KEY_VOLUMEDOWN),
+	KEY(4, 2, KEY_EMAIL),
+	KEY(3, 3, KEY_RIGHT),
+	KEY(2, 5, KEY_BACKSPACE),
+
+	KEY(6, 7, KEY_MENU),
+	KEY(5, 0, KEY_ENTER),
+	KEY(4, 3, KEY_0),
+	KEY(3, 4, KEY_DOT),
+	KEY(5, 2, KEY_UP),
+	KEY(3, 5, KEY_DOWN),
+
+	KEY(4, 5, KEY_SEND),
+	KEY(0, 5, KEY_BACK),
+	KEY(6, 2, KEY_VOLUMEUP),
+	KEY(1, 3, KEY_SPACE),
+	KEY(7, 6, KEY_LEFT),
+	KEY(5, 5, KEY_SEARCH),
+};
+
+static struct matrix_keymap_data u8500_keymap_data = {
+	.keymap		= u8500_keymap,
+	.keymap_size    = ARRAY_SIZE(u8500_keymap),
+};
+
+static struct tc3589x_keypad_platform_data tc35893_data = {
+	.krow = TC_KPD_ROWS,
+	.kcol = TC_KPD_COLUMNS,
+	.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
+	.settle_time = TC_KPD_SETTLE_TIME,
+	.irqtype = IRQF_TRIGGER_FALLING,
+	.enable_wakeup = true,
+	.keymap_data    = &u8500_keymap_data,
+	.no_autorepeat  = true,
+};
+
+static struct tc3589x_platform_data tc3589x_keypad_data = {
+	.block = TC3589x_BLOCK_KEYPAD,
+	.keypad = &tc35893_data,
+	.irq_base = MOP500_EGPIO_IRQ_BASE,
+};
+
+static struct i2c_board_info __initdata mop500_i2c0_devices_u8500[] = {
+	{
+		I2C_BOARD_INFO("tc3589x", 0x44),
+		.platform_data = &tc3589x_keypad_data,
+		.irq = NOMADIK_GPIO_TO_IRQ(218),
+		.flags = I2C_CLIENT_WAKE,
+	},
+};
+
+
+void __init mop500_u8500uib_init(void)
+{
+	mop500_uib_i2c_add(3, mop500_i2c3_devices_u8500,
+			ARRAY_SIZE(mop500_i2c3_devices_u8500));
+
+	mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500,
+			ARRAY_SIZE(mop500_i2c0_devices_u8500));
+
+}
diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
new file mode 100644
index 0000000..69cce41
--- /dev/null
+++ b/arch/arm/mach-ux500/board-mop500-uib.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#define pr_fmt(fmt)	"mop500-uib: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <mach/hardware.h>
+#include "board-mop500.h"
+
+enum mop500_uib {
+	STUIB,
+	U8500UIB,
+};
+
+struct uib {
+	const char *name;
+	const char *option;
+	void (*init)(void);
+};
+
+static struct __initdata uib mop500_uibs[] = {
+	[STUIB] = {
+		.name	= "ST-UIB",
+		.option	= "stuib",
+		.init	= mop500_stuib_init,
+	},
+	[U8500UIB] = {
+		.name	= "U8500-UIB",
+		.option	= "u8500uib",
+		.init	= mop500_u8500uib_init,
+	},
+};
+
+static struct uib *mop500_uib;
+
+static int __init mop500_uib_setup(char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
+		struct uib *uib = &mop500_uibs[i];
+
+		if (!strcmp(str, uib->option)) {
+			mop500_uib = uib;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(mop500_uibs))
+		pr_err("invalid uib= option (%s)\n", str);
+
+	return 1;
+}
+__setup("uib=", mop500_uib_setup);
+
+/*
+ * The UIBs are detected after the I2C host controllers are registered, so
+ * i2c_register_board_info() can't be used.
+ */
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
+		unsigned n)
+{
+	struct i2c_adapter *adap;
+	struct i2c_client *client;
+	int i;
+
+	adap = i2c_get_adapter(busnum);
+	if (!adap) {
+		pr_err("failed to get adapter i2c%d\n", busnum);
+		return;
+	}
+
+	for (i = 0; i < n; i++) {
+		client = i2c_new_device(adap, &info[i]);
+		if (!client)
+			pr_err("failed to register %s to i2c%d\n",
+					info[i].type, busnum);
+	}
+
+	i2c_put_adapter(adap);
+}
+
+static void __init __mop500_uib_init(struct uib *uib, const char *why)
+{
+	pr_info("%s (%s)\n", uib->name, why);
+	uib->init();
+}
+
+/*
+ * Detect the UIB attached based on the presence or absence of i2c devices.
+ */
+static int __init mop500_uib_init(void)
+{
+	struct uib *uib = mop500_uib;
+	struct i2c_adapter *i2c0;
+	int ret;
+
+	if (!cpu_is_u8500())
+		return -ENODEV;
+
+	if (uib) {
+		__mop500_uib_init(uib, "from uib= boot argument");
+		return 0;
+	}
+
+	i2c0 = i2c_get_adapter(0);
+	if (!i2c0) {
+		__mop500_uib_init(&mop500_uibs[STUIB],
+				"fallback, could not get i2c0");
+		return -ENODEV;
+	}
+
+	/* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
+	ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
+			I2C_SMBUS_QUICK, NULL);
+	i2c_put_adapter(i2c0);
+
+	if (ret == 0)
+		uib = &mop500_uibs[U8500UIB];
+	else
+		uib = &mop500_uibs[STUIB];
+
+	__mop500_uib_init(uib, "detected");
+
+	return 0;
+}
+
+module_init(mop500_uib_init);
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index a393f57..8790d98 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -17,68 +17,30 @@
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
+#include <linux/amba/serial.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
 #include <linux/mfd/tc3589x.h>
+#include <linux/leds-lp5521.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/ste_dma40.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/irqs.h>
 
+#include "ste-dma40-db8500.h"
 #include "devices-db8500.h"
-#include "pins-db8500.h"
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
 
-static pin_cfg_t mop500_pins[] = {
-	/* SSP0 */
-	GPIO143_SSP0_CLK,
-	GPIO144_SSP0_FRM,
-	GPIO145_SSP0_RXD,
-	GPIO146_SSP0_TXD,
-
-	/* I2C */
-	GPIO147_I2C0_SCL,
-	GPIO148_I2C0_SDA,
-	GPIO16_I2C1_SCL,
-	GPIO17_I2C1_SDA,
-	GPIO10_I2C2_SDA,
-	GPIO11_I2C2_SCL,
-	GPIO229_I2C3_SDA,
-	GPIO230_I2C3_SCL,
-
-	/* SKE keypad */
-	GPIO153_KP_I7,
-	GPIO154_KP_I6,
-	GPIO155_KP_I5,
-	GPIO156_KP_I4,
-	GPIO157_KP_O7,
-	GPIO158_KP_O6,
-	GPIO159_KP_O5,
-	GPIO160_KP_O4,
-	GPIO161_KP_I3,
-	GPIO162_KP_I2,
-	GPIO163_KP_I1,
-	GPIO164_KP_I0,
-	GPIO165_KP_O3,
-	GPIO166_KP_O2,
-	GPIO167_KP_O1,
-	GPIO168_KP_O0,
-
-	/* GPIO_EXP_INT */
-	GPIO217_GPIO,
-
-	/* STMPE1601 IRQ */
-	GPIO218_GPIO    | PIN_INPUT_PULLUP,
-};
-
 static struct ab8500_platform_data ab8500_platdata = {
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
 	.regulator	= ab8500_regulators,
@@ -103,16 +65,6 @@ struct platform_device ab8500_device = {
 	.resource = ab8500_resources,
 };
 
-static struct pl022_ssp_controller ssp0_platform_data = {
-	.bus_id = 0,
-	/* pl022 not yet supports dma */
-	.enable_dma = 0,
-	/* on this platform, gpio 31,142,144,214 &
-	 * 224 are connected as chip selects
-	 */
-	.num_chipselect = 5,
-};
-
 /*
  * TC35892
  */
@@ -133,14 +85,81 @@ static struct tc3589x_platform_data mop500_tc35892_data = {
 	.irq_base	= MOP500_EGPIO_IRQ_BASE,
 };
 
+static struct lp5521_led_config lp5521_pri_led[] = {
+       [0] = {
+	       .chan_nr = 0,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [1] = {
+	       .chan_nr = 1,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [2] = {
+	       .chan_nr = 2,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+};
+
+static struct lp5521_platform_data __initdata lp5521_pri_data = {
+       .label = "lp5521_pri",
+       .led_config     = &lp5521_pri_led[0],
+       .num_channels   = 3,
+       .clock_mode     = LP5521_CLOCK_EXT,
+};
+
+static struct lp5521_led_config lp5521_sec_led[] = {
+       [0] = {
+	       .chan_nr = 0,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [1] = {
+	       .chan_nr = 1,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [2] = {
+	       .chan_nr = 2,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+};
+
+static struct lp5521_platform_data __initdata lp5521_sec_data = {
+       .label = "lp5521_sec",
+       .led_config     = &lp5521_sec_led[0],
+       .num_channels   = 3,
+       .clock_mode     = LP5521_CLOCK_EXT,
+};
+
 static struct i2c_board_info mop500_i2c0_devices[] = {
 	{
 		I2C_BOARD_INFO("tc3589x", 0x42),
-		.irq            = NOMADIK_GPIO_TO_IRQ(217),
+		.irq		= NOMADIK_GPIO_TO_IRQ(217),
 		.platform_data  = &mop500_tc35892_data,
 	},
 };
 
+static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
+	{
+		/* lp5521 LED driver, 1st device */
+		I2C_BOARD_INFO("lp5521", 0x33),
+		.platform_data = &lp5521_pri_data,
+	},
+	{
+		/* lp5521 LED driver, 2st device */
+		I2C_BOARD_INFO("lp5521", 0x34),
+		.platform_data = &lp5521_sec_data,
+	},
+	{
+		/* Light sensor Rohm BH1780GLI */
+		I2C_BOARD_INFO("bh1780", 0x29),
+	},
+};
+
 #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
 static struct nmk_i2c_controller u8500_i2c##id##_data = { \
 	/*				\
@@ -178,8 +197,93 @@ static void __init mop500_i2c_init(void)
 	db8500_add_i2c3(&u8500_i2c3_data);
 }
 
+static struct gpio_keys_button mop500_gpio_keys[] = {
+	{
+		.desc			= "SFH7741 Proximity Sensor",
+		.type			= EV_SW,
+		.code			= SW_FRONT_PROXIMITY,
+		.active_low		= 0,
+		.can_disable		= 1,
+	}
+};
+
+static struct regulator *prox_regulator;
+static int mop500_prox_activate(struct device *dev);
+static void mop500_prox_deactivate(struct device *dev);
+
+static struct gpio_keys_platform_data mop500_gpio_keys_data = {
+	.buttons	= mop500_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(mop500_gpio_keys),
+	.enable		= mop500_prox_activate,
+	.disable	= mop500_prox_deactivate,
+};
+
+static struct platform_device mop500_gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= 0,
+	.dev	= {
+		.platform_data	= &mop500_gpio_keys_data,
+	},
+};
+
+static int mop500_prox_activate(struct device *dev)
+{
+	prox_regulator = regulator_get(&mop500_gpio_keys_device.dev,
+						"vcc");
+	if (IS_ERR(prox_regulator)) {
+		dev_err(&mop500_gpio_keys_device.dev,
+			"no regulator\n");
+		return PTR_ERR(prox_regulator);
+	}
+	regulator_enable(prox_regulator);
+	return 0;
+}
+
+static void mop500_prox_deactivate(struct device *dev)
+{
+	regulator_disable(prox_regulator);
+	regulator_put(prox_regulator);
+}
+
 /* add any platform devices here - TODO */
 static struct platform_device *platform_devs[] __initdata = {
+	&mop500_gpio_keys_device,
+};
+
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV8_SSP0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV8_SSP0_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+#endif
+
+static struct pl022_ssp_controller ssp0_platform_data = {
+	.bus_id = 0,
+#ifdef CONFIG_STE_DMA40
+	.enable_dma = 1,
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &ssp0_dma_cfg_rx,
+	.dma_tx_param = &ssp0_dma_cfg_tx,
+#else
+	.enable_dma = 0,
+#endif
+	/* on this platform, gpio 31,142,144,214 &
+	 * 224 are connected as chip selects
+	 */
+	.num_chipselect = 5,
 };
 
 static void __init mop500_spi_init(void)
@@ -187,18 +291,108 @@ static void __init mop500_spi_init(void)
 	db8500_add_ssp0(&ssp0_platform_data);
 }
 
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg uart0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV13_UART0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV13_UART0_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart1_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV12_UART1_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart1_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV12_UART1_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart2_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV11_UART2_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV11_UART2_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+#endif
+
+static struct amba_pl011_data uart0_plat = {
+#ifdef CONFIG_STE_DMA40
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &uart0_dma_cfg_rx,
+	.dma_tx_param = &uart0_dma_cfg_tx,
+#endif
+};
+
+static struct amba_pl011_data uart1_plat = {
+#ifdef CONFIG_STE_DMA40
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &uart1_dma_cfg_rx,
+	.dma_tx_param = &uart1_dma_cfg_tx,
+#endif
+};
+
+static struct amba_pl011_data uart2_plat = {
+#ifdef CONFIG_STE_DMA40
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &uart2_dma_cfg_rx,
+	.dma_tx_param = &uart2_dma_cfg_tx,
+#endif
+};
+
 static void __init mop500_uart_init(void)
 {
-	db8500_add_uart0();
-	db8500_add_uart1();
-	db8500_add_uart2();
+	db8500_add_uart0(&uart0_plat);
+	db8500_add_uart1(&uart1_plat);
+	db8500_add_uart2(&uart2_plat);
 }
 
-static void __init u8500_init_machine(void)
+static void __init mop500_init_machine(void)
 {
+	/*
+	 * The HREFv60 board removed a GPIO expander and routed
+	 * all these GPIO pins to the internal GPIO controller
+	 * instead.
+	 */
+	if (machine_is_hrefv60())
+		mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
+	else
+		mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+
 	u8500_init_devices();
 
-	nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
+	mop500_pins_init();
 
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
@@ -207,12 +401,12 @@ static void __init u8500_init_machine(void)
 	mop500_spi_init();
 	mop500_uart_init();
 
-	mop500_keypad_init();
-
 	platform_device_register(&ab8500_device);
 
 	i2c_register_board_info(0, mop500_i2c0_devices,
 				ARRAY_SIZE(mop500_i2c0_devices));
+	i2c_register_board_info(2, mop500_i2c2_devices,
+				ARRAY_SIZE(mop500_i2c2_devices));
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -222,5 +416,13 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
-	.init_machine	= u8500_init_machine,
+	.init_machine	= mop500_init_machine,
+MACHINE_END
+
+MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
+	.boot_params	= 0x100,
+	.map_io		= u8500_map_io,
+	.init_irq	= ux500_init_irq,
+	.timer		= &ux500_timer,
+	.init_machine	= mop500_init_machine,
 MACHINE_END
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index 3104ae2..56722f4 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -7,15 +7,36 @@
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
-#define MOP500_EGPIO(x)			(NOMADIK_NR_GPIO + (x))
+/* HREFv60-specific GPIO assignments, this board has no GPIO expander */
+#define HREFV60_TOUCH_RST_GPIO		143
+#define HREFV60_PROX_SENSE_GPIO		217
+#define HREFV60_HAL_SW_GPIO		145
+#define HREFV60_SDMMC_EN_GPIO		169
+#define HREFV60_SDMMC_1V8_3V_GPIO	5
+#define HREFV60_SDMMC_CD_GPIO		95
+#define HREFV60_ACCEL_INT1_GPIO		82
+#define HREFV60_ACCEL_INT2_GPIO		83
+#define HREFV60_MAGNET_DRDY_GPIO	32
+#define HREFV60_DISP1_RST_GPIO		65
+#define HREFV60_DISP2_RST_GPIO		66
 
 /* GPIOs on the TC35892 expander */
+#define MOP500_EGPIO(x)			(NOMADIK_NR_GPIO + (x))
 #define GPIO_SDMMC_CD			MOP500_EGPIO(3)
+#define GPIO_PROX_SENSOR		MOP500_EGPIO(7)
+#define GPIO_BU21013_CS			MOP500_EGPIO(13)
 #define GPIO_SDMMC_EN			MOP500_EGPIO(17)
 #define GPIO_SDMMC_1V8_3V_SEL		MOP500_EGPIO(18)
 
+struct i2c_board_info;
+
 extern void mop500_sdi_init(void);
 extern void mop500_sdi_tc35892_init(void);
-extern void mop500_keypad_init(void);
+void __init mop500_u8500uib_init(void);
+void __init mop500_stuib_init(void);
+void __init mop500_pins_init(void);
+
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
+		unsigned n);
 
 #endif
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c
index 54712ac..739fb4c 100644
--- a/arch/arm/mach-ux500/board-u5500-sdi.c
+++ b/arch/arm/mach-ux500/board-u5500-sdi.c
@@ -31,6 +31,26 @@ static pin_cfg_t u5500_sdi_pins[] = {
 	GPIO14_MC0_CLK		| PIN_DIR_OUTPUT | PIN_VAL_LOW,
 };
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg u5500_sdi0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB5500_DMA_DEV24_SDMMC0_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data u5500_sdi0_data = {
 	.ocr_mask	= MMC_VDD_165_195,
 	.f_max		= 50000000,
@@ -39,6 +59,11 @@ static struct mmci_platform_data u5500_sdi0_data = {
 				MMC_CAP_MMC_HIGHSPEED,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &u5500_sdi0_dma_cfg_rx,
+	.dma_tx_param	= &u5500_sdi0_dma_cfg_tx,
+#endif
 };
 
 void __init u5500_sdi_init(void)
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c
index 39d370c..44fd3b5 100644
--- a/arch/arm/mach-ux500/board-u5500.c
+++ b/arch/arm/mach-ux500/board-u5500.c
@@ -22,9 +22,9 @@
 
 static void __init u5500_uart_init(void)
 {
-	db5500_add_uart0();
-	db5500_add_uart1();
-	db5500_add_uart2();
+	db5500_add_uart0(NULL);
+	db5500_add_uart1(NULL);
+	db5500_add_uart2(NULL);
 }
 
 static void __init u5500_init_machine(void)
diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c
index b2b0a3b..32ce908 100644
--- a/arch/arm/mach-ux500/clock.c
+++ b/arch/arm/mach-ux500/clock.c
@@ -313,7 +313,7 @@ static DEFINE_PRCMU_CLK_RATE(uartclk,	0x0, 5, UARTCLK, 38400000);
 static DEFINE_PRCMU_CLK(msp02clk,	0x0, 6, MSP02CLK);
 static DEFINE_PRCMU_CLK(msp1clk,	0x0, 7, MSP1CLK); /* v1 */
 static DEFINE_PRCMU_CLK_RATE(i2cclk,	0x0, 8, I2CCLK, 48000000);
-static DEFINE_PRCMU_CLK_RATE(sdmmcclk,	0x0, 9, SDMMCCLK, 50000000);
+static DEFINE_PRCMU_CLK_RATE(sdmmcclk,	0x0, 9, SDMMCCLK, 100000000);
 static DEFINE_PRCMU_CLK(slimclk,	0x0, 10, SLIMCLK);
 static DEFINE_PRCMU_CLK(per1clk,	0x0, 11, PER1CLK);
 static DEFINE_PRCMU_CLK(per2clk,	0x0, 12, PER2CLK);
@@ -520,7 +520,7 @@ static struct clk_lookup u8500_ed_clks[] = {
 	CLK(ssp0_ed,	"ssp0",		NULL),
 
 	/* Peripheral Cluster #5 */
-	CLK(usb_ed,	"musb_hdrc.0",	"usb"),
+	CLK(usb_ed,	"musb-ux500.0",	"usb"),
 
 	/* Peripheral Cluster #6 */
 	CLK(dmc_ed,	"dmc",		NULL),
@@ -561,7 +561,7 @@ static struct clk_lookup u8500_v1_clks[] = {
 	CLK(ssp0_v1,	"ssp0",		NULL),
 
 	/* Peripheral Cluster #5 */
-	CLK(usb_v1,	"musb_hdrc.0",	"usb"),
+	CLK(usb_v1,	"musb-ux500.0",	"usb"),
 
 	/* Peripheral Cluster #6 */
 	CLK(mtu1_v1,	"mtu1",		NULL),
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index af04e08..c9dc2ef 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 
 #include <asm/mach/map.h>
+#include <asm/pmu.h>
 
 #include <plat/gpio.h>
 
@@ -18,8 +19,10 @@
 #include <mach/devices.h>
 #include <mach/setup.h>
 #include <mach/irqs.h>
+#include <mach/usb.h>
 
 #include "devices-db5500.h"
+#include "ste-dma40-db5500.h"
 
 static struct map_desc u5500_uart_io_desc[] __initdata = {
 	__IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
@@ -43,6 +46,26 @@ static struct map_desc u5500_io_desc[] __initdata = {
 	__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
 };
 
+static struct resource db5500_pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_DB5500_PMU0,
+		.end		= IRQ_DB5500_PMU0,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start		= IRQ_DB5500_PMU1,
+		.end		= IRQ_DB5500_PMU1,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device db5500_pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(db5500_pmu_resources),
+	.resource		= db5500_pmu_resources,
+};
+
 static struct resource mbox0_resources[] = {
 	{
 		.name = "mbox_peer",
@@ -127,7 +150,8 @@ static struct platform_device mbox2_device = {
 	.num_resources = ARRAY_SIZE(mbox2_resources),
 };
 
-static struct platform_device *u5500_platform_devs[] __initdata = {
+static struct platform_device *db5500_platform_devs[] __initdata = {
+	&db5500_pmu_device,
 	&mbox0_device,
 	&mbox1_device,
 	&mbox2_device,
@@ -166,12 +190,35 @@ void __init u5500_map_io(void)
 	iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
 }
 
+static int usb_db5500_rx_dma_cfg[] = {
+	DB5500_DMA_DEV4_USB_OTG_IEP_1_9,
+	DB5500_DMA_DEV5_USB_OTG_IEP_2_10,
+	DB5500_DMA_DEV6_USB_OTG_IEP_3_11,
+	DB5500_DMA_DEV20_USB_OTG_IEP_4_12,
+	DB5500_DMA_DEV21_USB_OTG_IEP_5_13,
+	DB5500_DMA_DEV22_USB_OTG_IEP_6_14,
+	DB5500_DMA_DEV23_USB_OTG_IEP_7_15,
+	DB5500_DMA_DEV38_USB_OTG_IEP_8
+};
+
+static int usb_db5500_tx_dma_cfg[] = {
+	DB5500_DMA_DEV4_USB_OTG_OEP_1_9,
+	DB5500_DMA_DEV5_USB_OTG_OEP_2_10,
+	DB5500_DMA_DEV6_USB_OTG_OEP_3_11,
+	DB5500_DMA_DEV20_USB_OTG_OEP_4_12,
+	DB5500_DMA_DEV21_USB_OTG_OEP_5_13,
+	DB5500_DMA_DEV22_USB_OTG_OEP_6_14,
+	DB5500_DMA_DEV23_USB_OTG_OEP_7_15,
+	DB5500_DMA_DEV38_USB_OTG_OEP_8
+};
+
 void __init u5500_init_devices(void)
 {
 	db5500_add_gpios();
 	db5500_dma_init();
 	db5500_add_rtc();
+	db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg);
 
-	platform_add_devices(u5500_platform_devs,
-			     ARRAY_SIZE(u5500_platform_devs));
+	platform_add_devices(db5500_platform_devs,
+			     ARRAY_SIZE(db5500_platform_devs));
 }
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 1748fbc..516126c 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -12,21 +12,21 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
+#include <asm/pmu.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/usb.h>
 
 #include "devices-db8500.h"
-
-static struct platform_device *platform_devs[] __initdata = {
-	&u8500_dma40_device,
-};
+#include "ste-dma40-db8500.h"
 
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_uart_io_desc[] __initdata = {
@@ -89,6 +89,51 @@ void __init u8500_map_io(void)
 		iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
 }
 
+static struct resource db8500_pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_DB8500_PMU,
+		.end		= IRQ_DB8500_PMU,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+/*
+ * The PMU IRQ lines of two cores are wired together into a single interrupt.
+ * Bounce the interrupt to the other core if it's not ours.
+ */
+static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
+{
+	irqreturn_t ret = handler(irq, dev);
+	int other = !smp_processor_id();
+
+	if (ret == IRQ_NONE && cpu_online(other))
+		irq_set_affinity(irq, cpumask_of(other));
+
+	/*
+	 * We should be able to get away with the amount of IRQ_NONEs we give,
+	 * while still having the spurious IRQ detection code kick in if the
+	 * interrupt really starts hitting spuriously.
+	 */
+	return ret;
+}
+
+static struct arm_pmu_platdata db8500_pmu_platdata = {
+	.handle_irq		= db8500_pmu_handler,
+};
+
+static struct platform_device db8500_pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(db8500_pmu_resources),
+	.resource		= db8500_pmu_resources,
+	.dev.platform_data	= &db8500_pmu_platdata,
+};
+
+static struct platform_device *platform_devs[] __initdata = {
+	&u8500_dma40_device,
+	&db8500_pmu_device,
+};
+
 static resource_size_t __initdata db8500_gpio_base[] = {
 	U8500_GPIOBANK0_BASE,
 	U8500_GPIOBANK1_BASE,
@@ -111,6 +156,28 @@ static void __init db8500_add_gpios(void)
 			 IRQ_DB8500_GPIO0, &pdata);
 }
 
+static int usb_db8500_rx_dma_cfg[] = {
+	DB8500_DMA_DEV38_USB_OTG_IEP_1_9,
+	DB8500_DMA_DEV37_USB_OTG_IEP_2_10,
+	DB8500_DMA_DEV36_USB_OTG_IEP_3_11,
+	DB8500_DMA_DEV19_USB_OTG_IEP_4_12,
+	DB8500_DMA_DEV18_USB_OTG_IEP_5_13,
+	DB8500_DMA_DEV17_USB_OTG_IEP_6_14,
+	DB8500_DMA_DEV16_USB_OTG_IEP_7_15,
+	DB8500_DMA_DEV39_USB_OTG_IEP_8
+};
+
+static int usb_db8500_tx_dma_cfg[] = {
+	DB8500_DMA_DEV38_USB_OTG_OEP_1_9,
+	DB8500_DMA_DEV37_USB_OTG_OEP_2_10,
+	DB8500_DMA_DEV36_USB_OTG_OEP_3_11,
+	DB8500_DMA_DEV19_USB_OTG_OEP_4_12,
+	DB8500_DMA_DEV18_USB_OTG_OEP_5_13,
+	DB8500_DMA_DEV17_USB_OTG_OEP_6_14,
+	DB8500_DMA_DEV16_USB_OTG_OEP_7_15,
+	DB8500_DMA_DEV39_USB_OTG_OEP_8
+};
+
 /*
  * This function is called from the board init
  */
@@ -121,6 +188,7 @@ void __init u8500_init_devices(void)
 
 	db8500_add_rtc();
 	db8500_add_gpios();
+	db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
 	platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c
index fe69f5f..13a4ce0 100644
--- a/arch/arm/mach-ux500/devices-common.c
+++ b/arch/arm/mach-ux500/devices-common.c
@@ -139,6 +139,7 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq,
 	for (i = 0; i < num; i++, first += 32, irq++) {
 		pdata->first_gpio = first;
 		pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
+		pdata->num_gpio = 32;
 
 		dbx500_add_gpio(i, base[i], irq, pdata);
 	}
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h
index cbadc11..c719b5a1 100644
--- a/arch/arm/mach-ux500/devices-common.h
+++ b/arch/arm/mach-ux500/devices-common.h
@@ -42,10 +42,13 @@ dbx500_add_sdi(const char *name, resource_size_t base, int irq,
 	return dbx500_add_amba_device(name, base, irq, pdata, 0);
 }
 
+struct amba_pl011_data;
+
 static inline struct amba_device *
-dbx500_add_uart(const char *name, resource_size_t base, int irq)
+dbx500_add_uart(const char *name, resource_size_t base, int irq,
+		struct amba_pl011_data *pdata)
 {
-	return dbx500_add_amba_device(name, base, irq, NULL, 0);
+	return dbx500_add_amba_device(name, base, irq, pdata, 0);
 }
 
 struct nmk_i2c_controller;
diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h
index c8d7901..94627f7 100644
--- a/arch/arm/mach-ux500/devices-db5500.h
+++ b/arch/arm/mach-ux500/devices-db5500.h
@@ -34,6 +34,9 @@
 #define db5500_add_rtc() \
 	dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
 
+#define db5500_add_usb(rx_cfg, tx_cfg) \
+	ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg)
+
 #define db5500_add_sdi0(pdata) \
 	dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
 #define db5500_add_sdi1(pdata) \
@@ -54,13 +57,13 @@
 #define db5500_add_spi3(pdata) \
 	dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
 
-#define db5500_add_uart0() \
-	dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0)
-#define db5500_add_uart1() \
-	dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1)
-#define db5500_add_uart2() \
-	dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2)
-#define db5500_add_uart3() \
-	dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3)
+#define db5500_add_uart0(plat) \
+	dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat)
+#define db5500_add_uart1(plat) \
+	dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat)
+#define db5500_add_uart2(plat) \
+	dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat)
+#define db5500_add_uart3(plat) \
+	dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat)
 
 #endif
diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c
index 23c695d5..73b1740 100644
--- a/arch/arm/mach-ux500/devices-db8500.c
+++ b/arch/arm/mach-ux500/devices-db8500.c
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/pl022.h>
 
 #include <plat/ste_dma40.h>
 
@@ -67,12 +68,72 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = {
 
 /*
  * Mapping between destination event lines and physical device address.
- * The event line is tied to a device and therefor the address is constant.
+ * The event line is tied to a device and therefore the address is constant.
+ * When the address comes from a primecell it will be configured in runtime
+ * and we set the address to -1 as a placeholder.
  */
-static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV];
+static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = {
+	/* MUSB - these will be runtime-reconfigured */
+	[DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1,
+	[DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1,
+	[DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1,
+	[DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1,
+	[DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1,
+	[DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1,
+	[DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1,
+	[DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1,
+	/* PrimeCells - run-time configured */
+	[DB8500_DMA_DEV0_SPI0_TX] = -1,
+	[DB8500_DMA_DEV1_SD_MMC0_TX] = -1,
+	[DB8500_DMA_DEV2_SD_MMC1_TX] = -1,
+	[DB8500_DMA_DEV3_SD_MMC2_TX] = -1,
+	[DB8500_DMA_DEV8_SSP0_TX] = -1,
+	[DB8500_DMA_DEV9_SSP1_TX] = -1,
+	[DB8500_DMA_DEV11_UART2_TX] = -1,
+	[DB8500_DMA_DEV12_UART1_TX] = -1,
+	[DB8500_DMA_DEV13_UART0_TX] = -1,
+	[DB8500_DMA_DEV28_SD_MM2_TX] = -1,
+	[DB8500_DMA_DEV29_SD_MM0_TX] = -1,
+	[DB8500_DMA_DEV32_SD_MM1_TX] = -1,
+	[DB8500_DMA_DEV33_SPI2_TX] = -1,
+	[DB8500_DMA_DEV35_SPI1_TX] = -1,
+	[DB8500_DMA_DEV40_SPI3_TX] = -1,
+	[DB8500_DMA_DEV41_SD_MM3_TX] = -1,
+	[DB8500_DMA_DEV42_SD_MM4_TX] = -1,
+	[DB8500_DMA_DEV43_SD_MM5_TX] = -1,
+};
 
 /* Mapping between source event lines and physical device address */
-static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV];
+static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = {
+	/* MUSB - these will be runtime-reconfigured */
+	[DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1,
+	[DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1,
+	[DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1,
+	[DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1,
+	[DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1,
+	[DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1,
+	[DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1,
+	[DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1,
+	/* PrimeCells */
+	[DB8500_DMA_DEV0_SPI0_RX] = -1,
+	[DB8500_DMA_DEV1_SD_MMC0_RX] = -1,
+	[DB8500_DMA_DEV2_SD_MMC1_RX] = -1,
+	[DB8500_DMA_DEV3_SD_MMC2_RX] = -1,
+	[DB8500_DMA_DEV8_SSP0_RX] = -1,
+	[DB8500_DMA_DEV9_SSP1_RX] = -1,
+	[DB8500_DMA_DEV11_UART2_RX] = -1,
+	[DB8500_DMA_DEV12_UART1_RX] = -1,
+	[DB8500_DMA_DEV13_UART0_RX] = -1,
+	[DB8500_DMA_DEV28_SD_MM2_RX] = -1,
+	[DB8500_DMA_DEV29_SD_MM0_RX] = -1,
+	[DB8500_DMA_DEV32_SD_MM1_RX] = -1,
+	[DB8500_DMA_DEV33_SPI2_RX] = -1,
+	[DB8500_DMA_DEV35_SPI1_RX] = -1,
+	[DB8500_DMA_DEV40_SPI3_RX] = -1,
+	[DB8500_DMA_DEV41_SD_MM3_RX] = -1,
+	[DB8500_DMA_DEV42_SD_MM4_RX] = -1,
+	[DB8500_DMA_DEV43_SD_MM5_RX] = -1,
+};
 
 /* Reserved event lines for memcpy only */
 static int dma40_memcpy_event[] = {
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h
index 3a770c7..9cc6f8f 100644
--- a/arch/arm/mach-ux500/devices-db8500.h
+++ b/arch/arm/mach-ux500/devices-db8500.h
@@ -61,6 +61,9 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq,
 #define db8500_add_rtc() \
 	dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
 
+#define db8500_add_usb(rx_cfg, tx_cfg) \
+	ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg)
+
 #define db8500_add_sdi0(pdata) \
 	dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
 #define db8500_add_sdi1(pdata) \
@@ -88,11 +91,11 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq,
 #define db8500_add_spi3(pdata) \
 	dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
 
-#define db8500_add_uart0() \
-	dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0)
-#define db8500_add_uart1() \
-	dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1)
-#define db8500_add_uart2() \
-	dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2)
+#define db8500_add_uart0(pdata) \
+	dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata)
+#define db8500_add_uart1(pdata) \
+	dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata)
+#define db8500_add_uart2(pdata) \
+	dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata)
 
 #endif
diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c
index 32a061f..1cfab68 100644
--- a/arch/arm/mach-ux500/dma-db5500.c
+++ b/arch/arm/mach-ux500/dma-db5500.c
@@ -73,11 +73,27 @@ static struct stedma40_chan_cfg dma40_memcpy_conf_log = {
  */
 static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
 	[DB5500_DMA_DEV24_SDMMC0_RX] = -1,
+	[DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1,
+	[DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1,
+	[DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1,
+	[DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1,
+	[DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1,
+	[DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1,
+	[DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1,
+	[DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -1,
 };
 
 /* Mapping between destination event lines and physical device address */
 static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
 	[DB5500_DMA_DEV24_SDMMC0_TX] = -1,
+	[DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1,
+	[DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1,
+	[DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1,
+	[DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1,
+	[DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1,
+	[DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1,
+	[DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1,
+	[DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -1,
 };
 
 static int dma40_memcpy_event[] = {
diff --git a/arch/arm/mach-ux500/include/mach/memory.h b/arch/arm/mach-ux500/include/mach/memory.h
index 510571a..2ef697a 100644
--- a/arch/arm/mach-ux500/include/mach/memory.h
+++ b/arch/arm/mach-ux500/include/mach/memory.h
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 #define BUS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h
index 9a6614c..ab0fe14 100644
--- a/arch/arm/mach-ux500/include/mach/uncompress.h
+++ b/arch/arm/mach-ux500/include/mach/uncompress.h
@@ -50,7 +50,11 @@ static void flush(void)
 
 static inline void arch_decomp_setup(void)
 {
-	if (machine_is_u8500())
+	/* Check in run time if we run on an U8500 or U5500 */
+	if (machine_is_u8500() ||
+	    machine_is_svp8500v1() ||
+	    machine_is_svp8500v2() ||
+	    machine_is_hrefv60())
 		ux500_uart_base = U8500_UART2_BASE;
 	else if (machine_is_u5500())
 		ux500_uart_base = U5500_UART0_BASE;
diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h
new file mode 100644
index 0000000..d3739d4
--- /dev/null
+++ b/arch/arm/mach-ux500/include/mach/usb.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __ASM_ARCH_USB_H
+#define __ASM_ARCH_USB_H
+
+#include <linux/dmaengine.h>
+
+#define UX500_MUSB_DMA_NUM_RX_CHANNELS 8
+#define UX500_MUSB_DMA_NUM_TX_CHANNELS 8
+
+struct ux500_musb_board_data {
+	void	**dma_rx_param_array;
+	void	**dma_tx_param_array;
+	u32	num_rx_channels;
+	u32	num_tx_channels;
+	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+};
+
+void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
+	int *dma_tx_cfg);
+#endif
diff --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c
index cbf1571..a4ffb9f 100644
--- a/arch/arm/mach-ux500/mbox-db5500.c
+++ b/arch/arm/mach-ux500/mbox-db5500.c
@@ -498,7 +498,7 @@ struct mbox *mbox_setup(u8 mbox_id, mbox_recv_cb_t *mbox_cb, void *priv)
 #endif
 
 	dev_info(&(mbox->pdev->dev),
-		 "Mailbox driver with index %d initated!\n", mbox_id);
+		 "Mailbox driver with index %d initiated!\n", mbox_id);
 
 exit:
 	return mbox;
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
new file mode 100644
index 0000000..82e5359
--- /dev/null
+++ b/arch/arm/mach-ux500/usb.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/musb.h>
+#include <plat/ste_dma40.h>
+#include <mach/hardware.h>
+#include <mach/usb.h>
+
+#define MUSB_DMA40_RX_CH { \
+		.mode = STEDMA40_MODE_LOGICAL, \
+		.dir = STEDMA40_PERIPH_TO_MEM, \
+		.dst_dev_type = STEDMA40_DEV_DST_MEMORY, \
+		.src_info.data_width = STEDMA40_WORD_WIDTH, \
+		.dst_info.data_width = STEDMA40_WORD_WIDTH, \
+		.src_info.psize = STEDMA40_PSIZE_LOG_16, \
+		.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
+	}
+
+#define MUSB_DMA40_TX_CH { \
+		.mode = STEDMA40_MODE_LOGICAL, \
+		.dir = STEDMA40_MEM_TO_PERIPH, \
+		.src_dev_type = STEDMA40_DEV_SRC_MEMORY, \
+		.src_info.data_width = STEDMA40_WORD_WIDTH, \
+		.dst_info.data_width = STEDMA40_WORD_WIDTH, \
+		.src_info.psize = STEDMA40_PSIZE_LOG_16, \
+		.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
+	}
+
+static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS]
+	= {
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH
+};
+
+static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS]
+	= {
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+};
+
+static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = {
+	&musb_dma_rx_ch[0],
+	&musb_dma_rx_ch[1],
+	&musb_dma_rx_ch[2],
+	&musb_dma_rx_ch[3],
+	&musb_dma_rx_ch[4],
+	&musb_dma_rx_ch[5],
+	&musb_dma_rx_ch[6],
+	&musb_dma_rx_ch[7]
+};
+
+static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = {
+	&musb_dma_tx_ch[0],
+	&musb_dma_tx_ch[1],
+	&musb_dma_tx_ch[2],
+	&musb_dma_tx_ch[3],
+	&musb_dma_tx_ch[4],
+	&musb_dma_tx_ch[5],
+	&musb_dma_tx_ch[6],
+	&musb_dma_tx_ch[7]
+};
+
+static struct ux500_musb_board_data musb_board_data = {
+	.dma_rx_param_array = ux500_dma_rx_param_array,
+	.dma_tx_param_array = ux500_dma_tx_param_array,
+	.num_rx_channels = UX500_MUSB_DMA_NUM_RX_CHANNELS,
+	.num_tx_channels = UX500_MUSB_DMA_NUM_TX_CHANNELS,
+	.dma_filter = stedma40_filter,
+};
+
+static u64 ux500_musb_dmamask = DMA_BIT_MASK(32);
+
+static struct musb_hdrc_config musb_hdrc_config = {
+	.multipoint	= true,
+	.dyn_fifo	= true,
+	.num_eps	= 16,
+	.ram_bits	= 16,
+};
+
+static struct musb_hdrc_platform_data musb_platform_data = {
+#if defined(CONFIG_USB_MUSB_OTG)
+	.mode = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
+	.mode = MUSB_PERIPHERAL,
+#else /* defined(CONFIG_USB_MUSB_HOST) */
+	.mode = MUSB_HOST,
+#endif
+	.config = &musb_hdrc_config,
+	.board_data = &musb_board_data,
+};
+
+static struct resource usb_resources[] = {
+	[0] = {
+		.name	= "usb-mem",
+		.flags	=  IORESOURCE_MEM,
+	},
+
+	[1] = {
+		.name   = "mc", /* hard-coded in musb */
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device ux500_musb_device = {
+	.name = "musb-ux500",
+	.id = 0,
+	.dev = {
+		.platform_data = &musb_platform_data,
+		.dma_mask = &ux500_musb_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources = ARRAY_SIZE(usb_resources),
+	.resource = usb_resources,
+};
+
+static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type)
+{
+	u32 idx;
+
+	for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++)
+		musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx];
+}
+
+static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type)
+{
+	u32 idx;
+
+	for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++)
+		musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx];
+}
+
+void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
+	int *dma_tx_cfg)
+{
+	ux500_musb_device.resource[0].start = base;
+	ux500_musb_device.resource[0].end = base + SZ_64K - 1;
+	ux500_musb_device.resource[1].start = irq;
+	ux500_musb_device.resource[1].end = irq;
+
+	ux500_usb_dma_update_rx_ch_config(dma_rx_cfg);
+	ux500_usb_dma_update_tx_ch_config(dma_tx_cfg);
+
+	platform_device_register(&ux500_musb_device);
+}
diff --git a/arch/arm/mach-versatile/include/mach/memory.h b/arch/arm/mach-versatile/include/mach/memory.h
index 79aeab8..dacc9d8 100644
--- a/arch/arm/mach-versatile/include/mach/memory.h
+++ b/arch/arm/mach-versatile/include/mach/memory.h
@@ -23,6 +23,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index e628402..e9bccc5 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -243,7 +243,7 @@ static void __init ct_ca9x4_init(void)
 }
 
 MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.map_io		= ct_ca9x4_map_io,
 	.init_irq	= ct_ca9x4_init_irq,
 #if 0
diff --git a/arch/arm/mach-vexpress/include/mach/memory.h b/arch/arm/mach-vexpress/include/mach/memory.h
index be28232..5b7fcd4 100644
--- a/arch/arm/mach-vexpress/include/mach/memory.h
+++ b/arch/arm/mach-vexpress/include/mach/memory.h
@@ -20,6 +20,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x60000000)
+#define PLAT_PHYS_OFFSET		UL(0x60000000)
 
 #endif
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
new file mode 100644
index 0000000..2c20a34
--- /dev/null
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -0,0 +1,73 @@
+if ARCH_VT8500
+
+config VTWM_VERSION_VT8500
+	bool
+
+config VTWM_VERSION_WM8505
+	bool
+
+config MACH_BV07
+	bool "Benign BV07-8500 Mini Netbook"
+	depends on ARCH_VT8500
+	select VTWM_VERSION_VT8500
+	help
+	  Add support for the inexpensive 7-inch netbooks sold by many
+	  Chinese distributors under various names. Note that there are
+	  many hardware implementations in identical exterior, make sure
+	  that yours is indeed based on a VIA VT8500 chip.
+
+config MACH_WM8505_7IN_NETBOOK
+	bool "WM8505 7-inch generic netbook"
+	depends on ARCH_VT8500
+	select VTWM_VERSION_WM8505
+	help
+	  Add support for the inexpensive 7-inch netbooks sold by many
+	  Chinese distributors under various names. Note that there are
+	  many hardware implementations in identical exterior, make sure
+	  that yours is indeed based on a WonderMedia WM8505 chip.
+
+comment "LCD panel size"
+
+config WMT_PANEL_800X480
+	bool "7-inch with 800x480 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	default y
+	help
+	  These are found in most of the netbooks in generic cases, as
+	  well as in Eken M001 tablets and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=800x480' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+config WMT_PANEL_800X600
+	bool "8-inch with 800x600 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	help
+	  These are found in Eken M003 tablets and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=800x600' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+config WMT_PANEL_1024X576
+	bool "10-inch with 1024x576 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	help
+	  These are found in CherryPal netbooks and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=1024x576' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+config WMT_PANEL_1024X600
+	bool "10-inch with 1024x600 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	help
+	  These are found in Eken M006 tablets and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=1024x600' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+endif
diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
new file mode 100644
index 0000000..81aedb7
--- /dev/null
+++ b/arch/arm/mach-vt8500/Makefile
@@ -0,0 +1,9 @@
+obj-y += devices.o gpio.o irq.o timer.o
+
+obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
+obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
+
+obj-$(CONFIG_MACH_BV07) += bv07.o
+obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o
+
+obj-$(CONFIG_HAVE_PWM) += pwm.o
diff --git a/arch/arm/mach-vt8500/Makefile.boot b/arch/arm/mach-vt8500/Makefile.boot
new file mode 100644
index 0000000..a8acc4e
--- /dev/null
+++ b/arch/arm/mach-vt8500/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x01000000
diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c
new file mode 100644
index 0000000..94a261d
--- /dev/null
+++ b/arch/arm/mach-vt8500/bv07.c
@@ -0,0 +1,77 @@
+/*
+ *  arch/arm/mach-vt8500/bv07.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "devices.h"
+
+static void __iomem *pmc_hiber;
+
+static struct platform_device *devices[] __initdata = {
+	&vt8500_device_uart0,
+	&vt8500_device_lcdc,
+	&vt8500_device_ehci,
+	&vt8500_device_ge_rops,
+	&vt8500_device_pwm,
+	&vt8500_device_pwmbl,
+	&vt8500_device_rtc,
+};
+
+static void vt8500_power_off(void)
+{
+	local_irq_disable();
+	writew(5, pmc_hiber);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init bv07_init(void)
+{
+#ifdef CONFIG_FB_VT8500
+	void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
+	if (gpio_mux_reg) {
+		writel(readl(gpio_mux_reg) | 1, gpio_mux_reg);
+		iounmap(gpio_mux_reg);
+	} else {
+		printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
+	}
+#endif
+	pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
+	if (pmc_hiber)
+		pm_power_off = &vt8500_power_off;
+	else
+		printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
+
+	vt8500_set_resources();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	vt8500_gpio_init();
+}
+
+MACHINE_START(BV07, "Benign BV07 Mini Netbook")
+	.boot_params	= 0x00000100,
+	.reserve	= vt8500_reserve_mem,
+	.map_io		= vt8500_map_io,
+	.init_irq	= vt8500_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= bv07_init,
+MACHINE_END
diff --git a/arch/arm/mach-vt8500/devices-vt8500.c b/arch/arm/mach-vt8500/devices-vt8500.c
new file mode 100644
index 0000000..19519ae
--- /dev/null
+++ b/arch/arm/mach-vt8500/devices-vt8500.c
@@ -0,0 +1,91 @@
+/* linux/arch/arm/mach-vt8500/devices-vt8500.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@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.
+ *
+ */
+
+#include <linux/platform_device.h>
+
+#include <mach/vt8500_regs.h>
+#include <mach/vt8500_irqs.h>
+#include <mach/i8042.h>
+#include "devices.h"
+
+void __init vt8500_set_resources(void)
+{
+	struct resource tmp[3];
+
+	tmp[0] = wmt_mmio_res(VT8500_LCDC_BASE, SZ_1K);
+	tmp[1] = wmt_irq_res(IRQ_LCDC);
+	wmt_res_add(&vt8500_device_lcdc, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART0_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART0);
+	wmt_res_add(&vt8500_device_uart0, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART1_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART1);
+	wmt_res_add(&vt8500_device_uart1, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART2_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART2);
+	wmt_res_add(&vt8500_device_uart2, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART3_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART3);
+	wmt_res_add(&vt8500_device_uart3, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_EHCI_BASE, SZ_512);
+	tmp[1] = wmt_irq_res(IRQ_EHCI);
+	wmt_res_add(&vt8500_device_ehci, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256);
+	wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(VT8500_PWM_BASE, 0x44);
+	wmt_res_add(&vt8500_device_pwm, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(VT8500_RTC_BASE, 0x2c);
+	tmp[1] = wmt_irq_res(IRQ_RTC);
+	tmp[2] = wmt_irq_res(IRQ_RTCSM);
+	wmt_res_add(&vt8500_device_rtc, tmp, 3);
+}
+
+static void __init vt8500_set_externs(void)
+{
+	/* Non-resource-aware stuff */
+	wmt_ic_base = VT8500_IC_BASE;
+	wmt_gpio_base = VT8500_GPIO_BASE;
+	wmt_pmc_base = VT8500_PMC_BASE;
+	wmt_i8042_base = VT8500_PS2_BASE;
+
+	wmt_nr_irqs = VT8500_NR_IRQS;
+	wmt_timer_irq = IRQ_PMCOS0;
+	wmt_gpio_ext_irq[0] = IRQ_EXT0;
+	wmt_gpio_ext_irq[1] = IRQ_EXT1;
+	wmt_gpio_ext_irq[2] = IRQ_EXT2;
+	wmt_gpio_ext_irq[3] = IRQ_EXT3;
+	wmt_gpio_ext_irq[4] = IRQ_EXT4;
+	wmt_gpio_ext_irq[5] = IRQ_EXT5;
+	wmt_gpio_ext_irq[6] = IRQ_EXT6;
+	wmt_gpio_ext_irq[7] = IRQ_EXT7;
+	wmt_i8042_kbd_irq = IRQ_PS2KBD;
+	wmt_i8042_aux_irq = IRQ_PS2MOUSE;
+}
+
+void __init vt8500_map_io(void)
+{
+	iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
+
+	/* Should be done before interrupts and timers are initialized */
+	vt8500_set_externs();
+}
diff --git a/arch/arm/mach-vt8500/devices-wm8505.c b/arch/arm/mach-vt8500/devices-wm8505.c
new file mode 100644
index 0000000..db4594e
--- /dev/null
+++ b/arch/arm/mach-vt8500/devices-wm8505.c
@@ -0,0 +1,99 @@
+/* linux/arch/arm/mach-vt8500/devices-wm8505.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@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.
+ *
+ */
+
+#include <linux/platform_device.h>
+
+#include <mach/wm8505_regs.h>
+#include <mach/wm8505_irqs.h>
+#include <mach/i8042.h>
+#include "devices.h"
+
+void __init wm8505_set_resources(void)
+{
+	struct resource tmp[3];
+
+	tmp[0] = wmt_mmio_res(WM8505_GOVR_BASE, SZ_512);
+	wmt_res_add(&vt8500_device_wm8505_fb, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART0_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART0);
+	wmt_res_add(&vt8500_device_uart0, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART1_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART1);
+	wmt_res_add(&vt8500_device_uart1, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART2_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART2);
+	wmt_res_add(&vt8500_device_uart2, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART3_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART3);
+	wmt_res_add(&vt8500_device_uart3, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART4_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART4);
+	wmt_res_add(&vt8500_device_uart4, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART5_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART5);
+	wmt_res_add(&vt8500_device_uart5, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_EHCI_BASE, SZ_512);
+	tmp[1] = wmt_irq_res(IRQ_EHCI);
+	wmt_res_add(&vt8500_device_ehci, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256);
+	wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(WM8505_PWM_BASE, 0x44);
+	wmt_res_add(&vt8500_device_pwm, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(WM8505_RTC_BASE, 0x2c);
+	tmp[1] = wmt_irq_res(IRQ_RTC);
+	tmp[2] = wmt_irq_res(IRQ_RTCSM);
+	wmt_res_add(&vt8500_device_rtc, tmp, 3);
+}
+
+static void __init wm8505_set_externs(void)
+{
+	/* Non-resource-aware stuff */
+	wmt_ic_base = WM8505_IC_BASE;
+	wmt_sic_base = WM8505_SIC_BASE;
+	wmt_gpio_base = WM8505_GPIO_BASE;
+	wmt_pmc_base = WM8505_PMC_BASE;
+	wmt_i8042_base = WM8505_PS2_BASE;
+
+	wmt_nr_irqs = WM8505_NR_IRQS;
+	wmt_timer_irq = IRQ_PMCOS0;
+	wmt_gpio_ext_irq[0] = IRQ_EXT0;
+	wmt_gpio_ext_irq[1] = IRQ_EXT1;
+	wmt_gpio_ext_irq[2] = IRQ_EXT2;
+	wmt_gpio_ext_irq[3] = IRQ_EXT3;
+	wmt_gpio_ext_irq[4] = IRQ_EXT4;
+	wmt_gpio_ext_irq[5] = IRQ_EXT5;
+	wmt_gpio_ext_irq[6] = IRQ_EXT6;
+	wmt_gpio_ext_irq[7] = IRQ_EXT7;
+	wmt_i8042_kbd_irq = IRQ_PS2KBD;
+	wmt_i8042_aux_irq = IRQ_PS2MOUSE;
+}
+
+void __init wm8505_map_io(void)
+{
+	iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
+
+	/* Should be done before interrupts and timers are initialized */
+	wm8505_set_externs();
+}
diff --git a/arch/arm/mach-vt8500/devices.c b/arch/arm/mach-vt8500/devices.c
new file mode 100644
index 0000000..1fcdc36
--- /dev/null
+++ b/arch/arm/mach-vt8500/devices.c
@@ -0,0 +1,270 @@
+/* linux/arch/arm/mach-vt8500/devices.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/memblock.h>
+
+#include <asm/mach/arch.h>
+
+#include <mach/vt8500fb.h>
+#include <mach/i8042.h>
+#include "devices.h"
+
+/* These can't use resources currently */
+unsigned long wmt_ic_base __initdata;
+unsigned long wmt_sic_base __initdata;
+unsigned long wmt_gpio_base __initdata;
+unsigned long wmt_pmc_base __initdata;
+unsigned long wmt_i8042_base __initdata;
+
+int wmt_nr_irqs __initdata;
+int wmt_timer_irq __initdata;
+int wmt_gpio_ext_irq[8] __initdata;
+
+/* Should remain accessible after init.
+ * i8042 driver desperately calls for attention...
+ */
+int wmt_i8042_kbd_irq;
+int wmt_i8042_aux_irq;
+
+static u64 fb_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device vt8500_device_lcdc = {
+	.name           = "vt8500-lcd",
+	.id             = 0,
+	.dev		= {
+		.dma_mask	= &fb_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device vt8500_device_wm8505_fb = {
+	.name           = "wm8505-fb",
+	.id             = 0,
+};
+
+/* Smallest to largest */
+static struct vt8500fb_platform_data panels[] = {
+#ifdef CONFIG_WMT_PANEL_800X480
+{
+	.xres_virtual	= 800,
+	.yres_virtual	= 480 * 2,
+	.mode		= {
+		.name		= "800x480",
+		.xres		= 800,
+		.yres		= 480,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 1,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+#ifdef CONFIG_WMT_PANEL_800X600
+{
+	.xres_virtual	= 800,
+	.yres_virtual	= 600 * 2,
+	.mode		= {
+		.name		= "800x600",
+		.xres		= 800,
+		.yres		= 600,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 1,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+#ifdef CONFIG_WMT_PANEL_1024X576
+{
+	.xres_virtual	= 1024,
+	.yres_virtual	= 576 * 2,
+	.mode		= {
+		.name		= "1024x576",
+		.xres		= 1024,
+		.yres		= 576,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+#ifdef CONFIG_WMT_PANEL_1024X600
+{
+	.xres_virtual	= 1024,
+	.yres_virtual	= 600 * 2,
+	.mode		= {
+		.name		= "1024x600",
+		.xres		= 1024,
+		.yres		= 600,
+		.left_margin	= 66,
+		.right_margin	= 2,
+		.upper_margin	= 19,
+		.lower_margin	= 1,
+		.hsync_len	= 23,
+		.vsync_len	= 8,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+};
+
+static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1;
+
+static int __init panel_setup(char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(panels); i++) {
+		if (strcmp(panels[i].mode.name, str) == 0) {
+			current_panel_idx = i;
+			break;
+		}
+	}
+	return 0;
+}
+
+early_param("panel", panel_setup);
+
+static inline void preallocate_fb(struct vt8500fb_platform_data *p,
+				  unsigned long align) {
+	p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >>
+			(p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 :
+					(8 / p->bpp) + 1));
+	p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len,
+							  align);
+	p->video_mem_virt = phys_to_virt(p->video_mem_phys);
+}
+
+struct platform_device vt8500_device_uart0 = {
+	.name		= "vt8500_serial",
+	.id		= 0,
+};
+
+struct platform_device vt8500_device_uart1 = {
+	.name		= "vt8500_serial",
+	.id		= 1,
+};
+
+struct platform_device vt8500_device_uart2 = {
+	.name		= "vt8500_serial",
+	.id		= 2,
+};
+
+struct platform_device vt8500_device_uart3 = {
+	.name		= "vt8500_serial",
+	.id		= 3,
+};
+
+struct platform_device vt8500_device_uart4 = {
+	.name		= "vt8500_serial",
+	.id		= 4,
+};
+
+struct platform_device vt8500_device_uart5 = {
+	.name		= "vt8500_serial",
+	.id		= 5,
+};
+
+static u64 ehci_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device vt8500_device_ehci = {
+	.name		= "vt8500-ehci",
+	.id		= 0,
+	.dev		= {
+		.dma_mask	= &ehci_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device vt8500_device_ge_rops = {
+	.name		= "wmt_ge_rops",
+	.id		= -1,
+};
+
+struct platform_device vt8500_device_pwm = {
+	.name		= "vt8500-pwm",
+	.id		= 0,
+};
+
+static struct platform_pwm_backlight_data vt8500_pwmbl_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 128,
+	.dft_brightness = 70,
+	.pwm_period_ns	= 250000, /* revisit when clocks are implemented */
+};
+
+struct platform_device vt8500_device_pwmbl = {
+	.name		= "pwm-backlight",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &vt8500_pwmbl_data,
+	},
+};
+
+struct platform_device vt8500_device_rtc = {
+	.name		= "vt8500-rtc",
+	.id		= 0,
+};
+
+struct map_desc wmt_io_desc[] __initdata = {
+	/* SoC MMIO registers */
+	[0] = {
+		.virtual	= 0xf8000000,
+		.pfn		= __phys_to_pfn(0xd8000000),
+		.length		= 0x00390000, /* max of all chip variants */
+		.type		= MT_DEVICE
+	},
+	/* PCI I/O space, numbers tied to those in <mach/io.h> */
+	[1] = {
+		.virtual	= 0xf0000000,
+		.pfn		= __phys_to_pfn(0xc0000000),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init vt8500_reserve_mem(void)
+{
+#ifdef CONFIG_FB_VT8500
+	panels[current_panel_idx].bpp = 16; /* Always use RGB565 */
+	preallocate_fb(&panels[current_panel_idx], SZ_4M);
+	vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx];
+#endif
+}
+
+void __init wm8505_reserve_mem(void)
+{
+#if defined CONFIG_FB_WM8505
+	panels[current_panel_idx].bpp = 32; /* Always use RGB888 */
+	preallocate_fb(&panels[current_panel_idx], 32);
+	vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx];
+#endif
+}
diff --git a/arch/arm/mach-vt8500/devices.h b/arch/arm/mach-vt8500/devices.h
new file mode 100644
index 0000000..188d4e1
--- /dev/null
+++ b/arch/arm/mach-vt8500/devices.h
@@ -0,0 +1,88 @@
+/* linux/arch/arm/mach-vt8500/devices.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@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 __ARCH_ARM_MACH_VT8500_DEVICES_H
+#define __ARCH_ARM_MACH_VT8500_DEVICES_H
+
+#include <linux/platform_device.h>
+#include <asm/mach/map.h>
+
+void __init vt8500_init_irq(void);
+void __init wm8505_init_irq(void);
+void __init vt8500_map_io(void);
+void __init wm8505_map_io(void);
+void __init vt8500_reserve_mem(void);
+void __init wm8505_reserve_mem(void);
+void __init vt8500_gpio_init(void);
+void __init vt8500_set_resources(void);
+void __init wm8505_set_resources(void);
+
+extern unsigned long wmt_ic_base __initdata;
+extern unsigned long wmt_sic_base __initdata;
+extern unsigned long wmt_gpio_base __initdata;
+extern unsigned long wmt_pmc_base __initdata;
+
+extern int wmt_nr_irqs __initdata;
+extern int wmt_timer_irq __initdata;
+extern int wmt_gpio_ext_irq[8] __initdata;
+
+extern struct map_desc wmt_io_desc[2] __initdata;
+
+static inline struct resource wmt_mmio_res(u32 start, u32 size)
+{
+	struct resource tmp = {
+		.flags = IORESOURCE_MEM,
+		.start = start,
+		.end = start + size - 1,
+	};
+
+	return tmp;
+}
+
+static inline struct resource wmt_irq_res(int irq)
+{
+	struct resource tmp = {
+		.flags = IORESOURCE_IRQ,
+		.start = irq,
+		.end = irq,
+	};
+
+	return tmp;
+}
+
+static inline void wmt_res_add(struct platform_device *pdev,
+			       const struct resource *res, unsigned int num)
+{
+	if (unlikely(platform_device_add_resources(pdev, res, num)))
+		pr_err("Failed to assign resources\n");
+}
+
+extern struct sys_timer vt8500_timer;
+
+extern struct platform_device vt8500_device_uart0;
+extern struct platform_device vt8500_device_uart1;
+extern struct platform_device vt8500_device_uart2;
+extern struct platform_device vt8500_device_uart3;
+extern struct platform_device vt8500_device_uart4;
+extern struct platform_device vt8500_device_uart5;
+
+extern struct platform_device vt8500_device_lcdc;
+extern struct platform_device vt8500_device_wm8505_fb;
+extern struct platform_device vt8500_device_ehci;
+extern struct platform_device vt8500_device_ge_rops;
+extern struct platform_device vt8500_device_pwm;
+extern struct platform_device vt8500_device_pwmbl;
+extern struct platform_device vt8500_device_rtc;
+#endif
diff --git a/arch/arm/mach-vt8500/gpio.c b/arch/arm/mach-vt8500/gpio.c
new file mode 100644
index 0000000..2bcc0ec
--- /dev/null
+++ b/arch/arm/mach-vt8500/gpio.c
@@ -0,0 +1,240 @@
+/* linux/arch/arm/mach-vt8500/gpio.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@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.
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include "devices.h"
+
+#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
+
+#define ENABLE_REGS	0x0
+#define DIRECTION_REGS	0x20
+#define OUTVALUE_REGS	0x40
+#define INVALUE_REGS	0x60
+
+#define EXT_REGOFF	0x1c
+
+static void __iomem *regbase;
+
+struct vt8500_gpio_chip {
+	struct gpio_chip	chip;
+	unsigned int		shift;
+	unsigned int		regoff;
+};
+
+static int gpio_to_irq_map[8];
+
+static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
+				     unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
+
+	val |= (1 << vt8500_chip->shift << offset);
+	writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
+
+	return 0;
+}
+
+static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
+				   unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
+
+	val &= ~(1 << vt8500_chip->shift << offset);
+	writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
+}
+
+static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	val &= ~(1 << vt8500_chip->shift << offset);
+	writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	return 0;
+}
+
+static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	val |= (1 << vt8500_chip->shift << offset);
+	writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	if (value) {
+		val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
+		val |= (1 << vt8500_chip->shift << offset);
+		writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff);
+	}
+	return 0;
+}
+
+static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
+		>> vt8500_chip->shift >> offset) & 1;
+}
+
+static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
+
+	if (value)
+		val |= (1 << vt8500_chip->shift << offset);
+	else
+		val &= ~(1 << vt8500_chip->shift << offset);
+
+	writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
+}
+
+#define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num)		\
+{									\
+	.chip = {							\
+		.label			= __name,			\
+		.request		= vt8500_muxed_gpio_request,	\
+		.free			= vt8500_muxed_gpio_free,	\
+		.direction_input  = vt8500_muxed_gpio_direction_input,	\
+		.direction_output = vt8500_muxed_gpio_direction_output,	\
+		.get			= vt8500_muxed_gpio_get_value,	\
+		.set			= vt8500_muxed_gpio_set_value,	\
+		.can_sleep		= 0,				\
+		.base			= __base,			\
+		.ngpio			= __num,			\
+	},								\
+	.shift		= __shift,					\
+	.regoff		= __off,					\
+}
+
+static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
+	VT8500_GPIO_BANK("uart0",	0,	0x0,	8,	4),
+	VT8500_GPIO_BANK("uart1",	4,	0x0,	12,	4),
+	VT8500_GPIO_BANK("spi0",	8,	0x0,	16,	4),
+	VT8500_GPIO_BANK("spi1",	12,	0x0,	20,	4),
+	VT8500_GPIO_BANK("spi2",	16,	0x0,	24,	4),
+	VT8500_GPIO_BANK("pwmout",	24,	0x0,	28,	2),
+
+	VT8500_GPIO_BANK("sdmmc",	0,	0x4,	30,	11),
+	VT8500_GPIO_BANK("ms",		16,	0x4,	41,	7),
+	VT8500_GPIO_BANK("i2c0",	24,	0x4,	48,	2),
+	VT8500_GPIO_BANK("i2c1",	26,	0x4,	50,	2),
+
+	VT8500_GPIO_BANK("mii",		0,	0x8,	52,	20),
+	VT8500_GPIO_BANK("see",		20,	0x8,	72,	4),
+	VT8500_GPIO_BANK("ide",		24,	0x8,	76,	7),
+
+	VT8500_GPIO_BANK("ccir",	0,	0xc,	83,	19),
+
+	VT8500_GPIO_BANK("ts",		8,	0x10,	102,	11),
+
+	VT8500_GPIO_BANK("lcd",		0,	0x14,	113,	23),
+};
+
+static int vt8500_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
+
+	val &= ~(1 << offset);
+	writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
+	return 0;
+}
+
+static int vt8500_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
+
+	val |= (1 << offset);
+	writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
+
+	if (value) {
+		val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
+		val |= (1 << offset);
+		writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
+	}
+	return 0;
+}
+
+static int vt8500_gpio_get_value(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
+}
+
+static void vt8500_gpio_set_value(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
+
+	if (value)
+		val |= (1 << offset);
+	else
+		val &= ~(1 << offset);
+
+	writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
+}
+
+static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 7)
+		return -EINVAL;
+
+	return gpio_to_irq_map[offset];
+}
+
+static struct gpio_chip vt8500_external_gpios = {
+	.label			= "extgpio",
+	.direction_input	= vt8500_gpio_direction_input,
+	.direction_output	= vt8500_gpio_direction_output,
+	.get			= vt8500_gpio_get_value,
+	.set			= vt8500_gpio_set_value,
+	.to_irq			= vt8500_gpio_to_irq,
+	.can_sleep		= 0,
+	.base			= 0,
+	.ngpio			= 8,
+};
+
+void __init vt8500_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < 8; i++)
+		gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
+
+	regbase = ioremap(wmt_gpio_base, SZ_64K);
+	if (!regbase) {
+		printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
+		return;
+	}
+
+	gpiochip_add(&vt8500_external_gpios);
+
+	for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
+		gpiochip_add(&vt8500_muxed_gpios[i].chip);
+}
diff --git a/arch/arm/mach-vt8500/include/mach/debug-macro.S b/arch/arm/mach-vt8500/include/mach/debug-macro.S
new file mode 100644
index 0000000..f119162
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/debug-macro.S
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/debug-macro.S
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Debugging macro include header
+ *
+ * This program is free software; you can 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
+	mov	\rp,      #0x00200000
+	orr	\rv, \rp, #0xf8000000
+	orr	\rp, \rp, #0xd8000000
+	.endm
+
+	.macro	senduart,rd,rx
+	strb	\rd, [\rx, #0]
+	.endm
+
+	.macro	busyuart,rd,rx
+1001:	ldr	\rd, [\rx, #0x1c]
+	ands	\rd, \rd, #0x2
+	bne	1001b
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S
new file mode 100644
index 0000000..92684c7
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/entry-macro.S
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for VIA VT8500
+ *
+ * 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	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	@ physical 0xd8140000 is virtual 0xf8140000
+	mov	\base, #0xf8000000
+	orr	\base, \base, #0x00140000
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\irqnr, [\base]
+	cmp	\irqnr, #63 @ may be false positive, check interrupt status
+	bne	1001f
+	ldr	\irqstat, [\base, #0x84]
+	ands	\irqstat, #0x80000000
+	moveq	\irqnr, #0
+1001:
+	.endm
+
diff --git a/arch/arm/mach-vt8500/include/mach/gpio.h b/arch/arm/mach-vt8500/include/mach/gpio.h
new file mode 100644
index 0000000..94ff276
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/gpio.h
@@ -0,0 +1,6 @@
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
diff --git a/arch/arm/mach-vt8500/include/mach/hardware.h b/arch/arm/mach-vt8500/include/mach/hardware.h
new file mode 100644
index 0000000..db4163f
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/hardware.h
@@ -0,0 +1,12 @@
+/* arch/arm/mach-vt8500/include/mach/hardware.h
+ *
+ * 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.
+ *
+ */
diff --git a/arch/arm/mach-vt8500/include/mach/i8042.h b/arch/arm/mach-vt8500/include/mach/i8042.h
new file mode 100644
index 0000000..cd7143c
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/i8042.h
@@ -0,0 +1,18 @@
+/* arch/arm/mach-vt8500/include/mach/i8042.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@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.
+ *
+ */
+
+extern unsigned long wmt_i8042_base __initdata;
+extern int wmt_i8042_kbd_irq;
+extern int wmt_i8042_aux_irq;
diff --git a/arch/arm/mach-vt8500/include/mach/io.h b/arch/arm/mach-vt8500/include/mach/io.h
new file mode 100644
index 0000000..9077239
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/io.h
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/io.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffff
+
+#define __io(a)		__typesafe_io((a) + 0xf0000000)
+#define __mem_pci(a)	(a)
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/arch/arm/mach-vt8500/include/mach/irqs.h
new file mode 100644
index 0000000..a129fd1
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/irqs.h
@@ -0,0 +1,22 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* This value is just to make the core happy, never used otherwise */
+#define NR_IRQS 128
diff --git a/arch/arm/mach-vt8500/include/mach/memory.h b/arch/arm/mach-vt8500/include/mach/memory.h
new file mode 100644
index 0000000..175f914
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/memory.h
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/memory.h
+ *
+ *  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.
+ *
+ * You 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_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0x00000000)
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/system.h b/arch/arm/mach-vt8500/include/mach/system.h
new file mode 100644
index 0000000..d6c757e
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/system.h
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/system.h
+ *
+ */
+#include <asm/io.h>
+
+/* PM Software Reset request register */
+#define VT8500_PMSR_VIRT	0xf8130060
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	writel(1, VT8500_PMSR_VIRT);
+}
diff --git a/arch/arm/mach-vt8500/include/mach/timex.h b/arch/arm/mach-vt8500/include/mach/timex.h
new file mode 100644
index 0000000..8487e4c
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/timex.h
@@ -0,0 +1,26 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/timex.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef MACH_TIMEX_H
+#define MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		(3000000)
+
+#endif /* MACH_TIMEX_H */
diff --git a/arch/arm/mach-vt8500/include/mach/uncompress.h b/arch/arm/mach-vt8500/include/mach/uncompress.h
new file mode 100644
index 0000000..bb9e2d2
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/uncompress.h
@@ -0,0 +1,37 @@
+/* arch/arm/mach-vt8500/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on arch/arm/mach-dove/include/mach/uncompress.h
+ *
+ * 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.
+ *
+ */
+
+#define UART0_PHYS 0xd8200000
+#include <asm/io.h>
+
+static void putc(const char c)
+{
+	while (readb(UART0_PHYS + 0x1c) & 0x2)
+		/* Tx busy, wait and poll */;
+
+	writeb(c, UART0_PHYS);
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-vt8500/include/mach/vmalloc.h b/arch/arm/mach-vt8500/include/mach/vmalloc.h
new file mode 100644
index 0000000..4642290
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define VMALLOC_END	0xd0000000UL
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h b/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
new file mode 100644
index 0000000..ecfee91
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
@@ -0,0 +1,88 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* VT8500 Interrupt Sources */
+
+#define IRQ_JPEGENC	0	/* JPEG Encoder */
+#define IRQ_JPEGDEC	1	/* JPEG Decoder */
+				/* Reserved */
+#define IRQ_PATA	3	/* PATA Controller */
+				/* Reserved */
+#define IRQ_DMA		5	/* DMA Controller */
+#define IRQ_EXT0	6	/* External Interrupt 0 */
+#define IRQ_EXT1	7	/* External Interrupt 1 */
+#define IRQ_GE		8	/* Graphic Engine */
+#define IRQ_GOV		9	/* Graphic Overlay Engine */
+#define IRQ_ETHER	10	/* Ethernet MAC */
+#define IRQ_MPEGTS	11	/* Transport Stream Interface */
+#define IRQ_LCDC	12	/* LCD Controller */
+#define IRQ_EXT2	13	/* External Interrupt 2 */
+#define IRQ_EXT3	14	/* External Interrupt 3 */
+#define IRQ_EXT4	15	/* External Interrupt 4 */
+#define IRQ_CIPHER	16	/* Cipher */
+#define IRQ_VPP		17	/* Video Post-Processor */
+#define IRQ_I2C1	18	/* I2C 1 */
+#define IRQ_I2C0	19	/* I2C 0 */
+#define IRQ_SDMMC	20	/* SD/MMC Controller */
+#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
+#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
+				/* Reserved */
+#define IRQ_SPI0	24	/* SPI 0 */
+#define IRQ_SPI1	25	/* SPI 1 */
+#define IRQ_SPI2	26	/* SPI 2 */
+#define IRQ_LCDDF	27	/* LCD Data Formatter */
+#define IRQ_NAND	28	/* NAND Flash Controller */
+#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
+#define IRQ_MS		30	/* MemoryStick Controller */
+#define IRQ_MS_DMA	31	/* MemoryStick Controller DMA */
+#define IRQ_UART0	32	/* UART 0 */
+#define IRQ_UART1	33	/* UART 1 */
+#define IRQ_I2S		34	/* I2S */
+#define IRQ_PCM		35	/* PCM */
+#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
+#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
+#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
+#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
+#define IRQ_VPU		40	/* Video Processing Unit */
+#define IRQ_VID		41	/* Video Digital Input Interface */
+#define IRQ_AC97	42	/* AC97 Interface */
+#define IRQ_EHCI	43	/* USB */
+#define IRQ_NOR		44	/* NOR Flash Controller */
+#define IRQ_PS2MOUSE	45	/* PS/2 Mouse */
+#define IRQ_PS2KBD	46	/* PS/2 Keyboard */
+#define IRQ_UART2	47	/* UART 2 */
+#define IRQ_RTC		48	/* RTC Interrupt */
+#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
+#define IRQ_UART3	50	/* UART 3 */
+#define IRQ_ADC		51	/* ADC */
+#define IRQ_EXT5	52	/* External Interrupt 5 */
+#define IRQ_EXT6	53	/* External Interrupt 6 */
+#define IRQ_EXT7	54	/* External Interrupt 7 */
+#define IRQ_CIR		55	/* CIR */
+#define IRQ_DMA0	56	/* DMA Channel 0 */
+#define IRQ_DMA1	57	/* DMA Channel 1 */
+#define IRQ_DMA2	58	/* DMA Channel 2 */
+#define IRQ_DMA3	59	/* DMA Channel 3 */
+#define IRQ_DMA4	60	/* DMA Channel 4 */
+#define IRQ_DMA5	61	/* DMA Channel 5 */
+#define IRQ_DMA6	62	/* DMA Channel 6 */
+#define IRQ_DMA7	63	/* DMA Channel 7 */
+
+#define VT8500_NR_IRQS		64
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_regs.h b/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
new file mode 100644
index 0000000..29c63ec
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
@@ -0,0 +1,79 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vt8500_regs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_VT8500_REGS_H
+#define __ASM_ARM_ARCH_VT8500_REGS_H
+
+/* VT8500 Registers Map */
+
+#define VT8500_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
+#define VT8500_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
+
+#define VT8500_DDR_BASE		0xd8000000	/* 1k	DDR/DDR2 Memory
+							Controller */
+#define VT8500_DMA_BASE		0xd8001000	/* 1k	DMA Controller */
+#define VT8500_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
+							Controller */
+#define VT8500_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
+#define VT8500_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
+#define VT8500_USB_BASE		0xd8007800	/* 2k	USB OTG */
+# define VT8500_EHCI_BASE	0xd8007900	/*	EHCI */
+# define VT8500_UHCI_BASE	0xd8007b01	/*	UHCI */
+#define VT8500_PATA_BASE	0xd8008000	/* 512	PATA */
+#define VT8500_PS2_BASE		0xd8008800	/* 1k	PS/2 */
+#define VT8500_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
+#define VT8500_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
+#define VT8500_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
+#define VT8500_MS_BASE		0xd800b000	/* 1k	MS/MSPRO Controller */
+#define VT8500_LCDC_BASE	0xd800e400	/* 1k	LCD Controller */
+#define VT8500_VPU_BASE		0xd8050000	/* 256	VPU */
+#define VT8500_GOV_BASE		0xd8050300	/* 256	GOV */
+#define VT8500_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
+#define VT8500_LCDF_BASE	0xd8050900	/* 256	LCD Formatter */
+#define VT8500_VID_BASE		0xd8050a00	/* 256	VID */
+#define VT8500_VPP_BASE		0xd8050b00	/* 256	VPP */
+#define VT8500_TSBK_BASE	0xd80f4000	/* 4k	TSBK */
+#define VT8500_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
+#define VT8500_JPEGENC_BASE	0xd80ff000	/* 4k	JPEG Encoder */
+#define VT8500_RTC_BASE		0xd8100000	/* 64k	RTC */
+#define VT8500_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
+#define VT8500_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
+#define VT8500_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
+#define VT8500_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
+#define VT8500_UART0_BASE	0xd8200000	/* 64k	UART 0 */
+#define VT8500_UART2_BASE	0xd8210000	/* 64k	UART 2 */
+#define VT8500_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
+#define VT8500_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
+#define VT8500_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
+#define VT8500_CIR_BASE		0xd8270000	/* 64k	CIR */
+#define VT8500_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
+#define VT8500_AC97_BASE	0xd8290000	/* 64k	AC97 */
+#define VT8500_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
+#define VT8500_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
+#define VT8500_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
+#define VT8500_PCM_BASE		0xd82d0000	/* 64k	PCM */
+#define VT8500_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
+#define VT8500_I2S_BASE		0xd8330000	/* 64k	I2S */
+#define VT8500_ADC_BASE		0xd8340000	/* 64k	ADC */
+
+#define VT8500_REGS_END_PHYS	0xd834ffff	/* End of MMIO registers */
+#define VT8500_REGS_LENGTH	(VT8500_REGS_END_PHYS \
+				- VT8500_REGS_START_PHYS + 1)
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500fb.h b/arch/arm/mach-vt8500/include/mach/vt8500fb.h
new file mode 100644
index 0000000..7f399c3
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vt8500fb.h
@@ -0,0 +1,31 @@
+/*
+ *  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/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h b/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
new file mode 100644
index 0000000..6128627
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
@@ -0,0 +1,115 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* WM8505 Interrupt Sources */
+
+#define IRQ_UHCI	0	/* UHC FS (UHCI?) */
+#define IRQ_EHCI	1	/* UHC HS */
+#define IRQ_UDCDMA	2	/* UDC DMA */
+				/* Reserved */
+#define IRQ_PS2MOUSE	4	/* PS/2 Mouse */
+#define IRQ_UDC		5	/* UDC */
+#define IRQ_EXT0	6	/* External Interrupt 0 */
+#define IRQ_EXT1	7	/* External Interrupt 1 */
+#define IRQ_KEYPAD	8	/* Keypad */
+#define IRQ_DMA		9	/* DMA Controller */
+#define IRQ_ETHER	10	/* Ethernet MAC */
+				/* Reserved */
+				/* Reserved */
+#define IRQ_EXT2	13	/* External Interrupt 2 */
+#define IRQ_EXT3	14	/* External Interrupt 3 */
+#define IRQ_EXT4	15	/* External Interrupt 4 */
+#define IRQ_APB		16	/* APB Bridge */
+#define IRQ_DMA0	17	/* DMA Channel 0 */
+#define IRQ_I2C1	18	/* I2C 1 */
+#define IRQ_I2C0	19	/* I2C 0 */
+#define IRQ_SDMMC	20	/* SD/MMC Controller */
+#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
+#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
+#define IRQ_PS2KBD	23	/* PS/2 Keyboard */
+#define IRQ_SPI0	24	/* SPI 0 */
+#define IRQ_SPI1	25	/* SPI 1 */
+#define IRQ_SPI2	26	/* SPI 2 */
+#define IRQ_DMA1	27	/* DMA Channel 1 */
+#define IRQ_NAND	28	/* NAND Flash Controller */
+#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
+#define IRQ_UART5	30	/* UART 5 */
+#define IRQ_UART4	31	/* UART 4 */
+#define IRQ_UART0	32	/* UART 0 */
+#define IRQ_UART1	33	/* UART 1 */
+#define IRQ_DMA2	34	/* DMA Channel 2 */
+#define IRQ_I2S		35	/* I2S */
+#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
+#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
+#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
+#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
+#define IRQ_DMA3	40	/* DMA Channel 3 */
+#define IRQ_DMA4	41	/* DMA Channel 4 */
+#define IRQ_AC97	42	/* AC97 Interface */
+				/* Reserved */
+#define IRQ_NOR		44	/* NOR Flash Controller */
+#define IRQ_DMA5	45	/* DMA Channel 5 */
+#define IRQ_DMA6	46	/* DMA Channel 6 */
+#define IRQ_UART2	47	/* UART 2 */
+#define IRQ_RTC		48	/* RTC Interrupt */
+#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
+#define IRQ_UART3	50	/* UART 3 */
+#define IRQ_DMA7	51	/* DMA Channel 7 */
+#define IRQ_EXT5	52	/* External Interrupt 5 */
+#define IRQ_EXT6	53	/* External Interrupt 6 */
+#define IRQ_EXT7	54	/* External Interrupt 7 */
+#define IRQ_CIR		55	/* CIR */
+#define IRQ_SIC0	56	/* SIC IRQ0 */
+#define IRQ_SIC1	57	/* SIC IRQ1 */
+#define IRQ_SIC2	58	/* SIC IRQ2 */
+#define IRQ_SIC3	59	/* SIC IRQ3 */
+#define IRQ_SIC4	60	/* SIC IRQ4 */
+#define IRQ_SIC5	61	/* SIC IRQ5 */
+#define IRQ_SIC6	62	/* SIC IRQ6 */
+#define IRQ_SIC7	63	/* SIC IRQ7 */
+				/* Reserved */
+#define IRQ_JPEGDEC	65	/* JPEG Decoder */
+#define IRQ_SAE		66	/* SAE (?) */
+				/* Reserved */
+#define IRQ_VPU		79	/* Video Processing Unit */
+#define IRQ_VPP		80	/* Video Post-Processor */
+#define IRQ_VID		81	/* Video Digital Input Interface */
+#define IRQ_SPU		82	/* SPU (?) */
+#define IRQ_PIP		83	/* PIP Error */
+#define IRQ_GE		84	/* Graphic Engine */
+#define IRQ_GOV		85	/* Graphic Overlay Engine */
+#define IRQ_DVO		86	/* Digital Video Output */
+				/* Reserved */
+#define IRQ_DMA8	92	/* DMA Channel 8 */
+#define IRQ_DMA9	93	/* DMA Channel 9 */
+#define IRQ_DMA10	94	/* DMA Channel 10 */
+#define IRQ_DMA11	95	/* DMA Channel 11 */
+#define IRQ_DMA12	96	/* DMA Channel 12 */
+#define IRQ_DMA13	97	/* DMA Channel 13 */
+#define IRQ_DMA14	98	/* DMA Channel 14 */
+#define IRQ_DMA15	99	/* DMA Channel 15 */
+				/* Reserved */
+#define IRQ_GOVW	111	/* GOVW (?) */
+#define IRQ_GOVRSDSCD	112	/* GOVR SDSCD (?) */
+#define IRQ_GOVRSDMIF	113	/* GOVR SDMIF (?) */
+#define IRQ_GOVRHDSCD	114	/* GOVR HDSCD (?) */
+#define IRQ_GOVRHDMIF	115	/* GOVR HDMIF (?) */
+
+#define WM8505_NR_IRQS		116
diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_regs.h b/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
new file mode 100644
index 0000000..df15509
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
@@ -0,0 +1,78 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/wm8505_regs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_WM8505_REGS_H
+#define __ASM_ARM_ARCH_WM8505_REGS_H
+
+/* WM8505 Registers Map */
+
+#define WM8505_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
+#define WM8505_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
+
+#define WM8505_DDR_BASE		0xd8000400	/* 1k	DDR/DDR2 Memory
+							Controller */
+#define WM8505_DMA_BASE		0xd8001800	/* 1k	DMA Controller */
+#define WM8505_VDMA_BASE	0xd8001c00	/* 1k	VDMA */
+#define WM8505_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
+							Controller */
+#define WM8505_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
+#define WM8505_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
+#define WM8505_USB_BASE		0xd8007000	/* 2k	USB 2.0 Host */
+# define WM8505_EHCI_BASE	0xd8007100	/*	EHCI */
+# define WM8505_UHCI_BASE	0xd8007301	/*	UHCI */
+#define WM8505_PS2_BASE		0xd8008800	/* 1k	PS/2 */
+#define WM8505_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
+#define WM8505_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
+#define WM8505_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
+#define WM8505_VPU_BASE		0xd8050000	/* 256	VPU */
+#define WM8505_GOV_BASE		0xd8050300	/* 256	GOV */
+#define WM8505_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
+#define WM8505_GOVR_BASE	0xd8050800	/* 512	GOVR (frambuffer) */
+#define WM8505_VID_BASE		0xd8050a00	/* 256	VID */
+#define WM8505_SCL_BASE		0xd8050d00	/* 256	SCL */
+#define WM8505_VPP_BASE		0xd8050f00	/* 256	VPP */
+#define WM8505_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
+#define WM8505_RTC_BASE		0xd8100000	/* 64k	RTC */
+#define WM8505_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
+#define WM8505_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
+#define WM8505_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
+#define WM8505_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
+#define WM8505_SIC_BASE		0xd8150000	/* 64k	Secondary IC */
+#define WM8505_UART0_BASE	0xd8200000	/* 64k	UART 0 */
+#define WM8505_UART2_BASE	0xd8210000	/* 64k	UART 2 */
+#define WM8505_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
+#define WM8505_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
+#define WM8505_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
+#define WM8505_KEYPAD_BASE	0xd8260000	/* 64k	Keypad control */
+#define WM8505_CIR_BASE		0xd8270000	/* 64k	CIR */
+#define WM8505_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
+#define WM8505_AC97_BASE	0xd8290000	/* 64k	AC97 */
+#define WM8505_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
+#define WM8505_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
+#define WM8505_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
+#define WM8505_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
+#define WM8505_I2S_BASE		0xd8330000	/* 64k	I2S */
+#define WM8505_UART4_BASE	0xd8370000	/* 64k	UART 4 */
+#define WM8505_UART5_BASE	0xd8380000	/* 64k	UART 5 */
+
+#define WM8505_REGS_END_PHYS	0xd838ffff	/* End of MMIO registers */
+#define WM8505_REGS_LENGTH	(WM8505_REGS_END_PHYS \
+				- WM8505_REGS_START_PHYS + 1)
+
+#endif
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
new file mode 100644
index 0000000..5f4ddde
--- /dev/null
+++ b/arch/arm/mach-vt8500/irq.c
@@ -0,0 +1,177 @@
+/*
+ *  arch/arm/mach-vt8500/irq.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+
+#include "devices.h"
+
+#define VT8500_IC_DCTR		0x40		/* Destination control
+						register, 64*u8 */
+#define VT8500_INT_ENABLE	(1 << 3)
+#define VT8500_TRIGGER_HIGH	(0 << 4)
+#define VT8500_TRIGGER_RISING	(1 << 4)
+#define VT8500_TRIGGER_FALLING	(2 << 4)
+#define VT8500_EDGE		( VT8500_TRIGGER_RISING \
+				| VT8500_TRIGGER_FALLING)
+#define VT8500_IC_STATUS	0x80		/* Interrupt status, 2*u32 */
+
+static void __iomem *ic_regbase;
+static void __iomem *sic_regbase;
+
+static void vt8500_irq_mask(unsigned int irq)
+{
+	void __iomem *base = ic_regbase;
+	u8 edge;
+
+	if (irq >= 64) {
+		base = sic_regbase;
+		irq -= 64;
+	}
+	edge = readb(base + VT8500_IC_DCTR + irq) & VT8500_EDGE;
+	if (edge) {
+		void __iomem *stat_reg = base + VT8500_IC_STATUS
+						+ (irq < 32 ? 0 : 4);
+		unsigned status = readl(stat_reg);
+
+		status |= (1 << (irq & 0x1f));
+		writel(status, stat_reg);
+	} else {
+		u8 dctr = readb(base + VT8500_IC_DCTR + irq);
+
+		dctr &= ~VT8500_INT_ENABLE;
+		writeb(dctr, base + VT8500_IC_DCTR + irq);
+	}
+}
+
+static void vt8500_irq_unmask(unsigned int irq)
+{
+	void __iomem *base = ic_regbase;
+	u8 dctr;
+
+	if (irq >= 64) {
+		base = sic_regbase;
+		irq -= 64;
+	}
+	dctr = readb(base + VT8500_IC_DCTR + irq);
+	dctr |= VT8500_INT_ENABLE;
+	writeb(dctr, base + VT8500_IC_DCTR + irq);
+}
+
+static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	void __iomem *base = ic_regbase;
+	unsigned int orig_irq = irq;
+	u8 dctr;
+
+	if (irq >= 64) {
+		base = sic_regbase;
+		irq -= 64;
+	}
+
+	dctr = readb(base + VT8500_IC_DCTR + irq);
+	dctr &= ~VT8500_EDGE;
+
+	switch (flow_type) {
+	case IRQF_TRIGGER_LOW:
+		return -EINVAL;
+	case IRQF_TRIGGER_HIGH:
+		dctr |= VT8500_TRIGGER_HIGH;
+		irq_desc[orig_irq].handle_irq = handle_level_irq;
+		break;
+	case IRQF_TRIGGER_FALLING:
+		dctr |= VT8500_TRIGGER_FALLING;
+		irq_desc[orig_irq].handle_irq = handle_edge_irq;
+		break;
+	case IRQF_TRIGGER_RISING:
+		dctr |= VT8500_TRIGGER_RISING;
+		irq_desc[orig_irq].handle_irq = handle_edge_irq;
+		break;
+	}
+	writeb(dctr, base + VT8500_IC_DCTR + irq);
+
+	return 0;
+}
+
+static struct irq_chip vt8500_irq_chip = {
+	.name      = "vt8500",
+	.ack       = vt8500_irq_mask,
+	.mask      = vt8500_irq_mask,
+	.unmask    = vt8500_irq_unmask,
+	.set_type  = vt8500_irq_set_type,
+};
+
+void __init vt8500_init_irq(void)
+{
+	unsigned int i;
+
+	ic_regbase = ioremap(wmt_ic_base, SZ_64K);
+
+	if (ic_regbase) {
+		/* Enable rotating priority for IRQ */
+		writel((1 << 6), ic_regbase + 0x20);
+		writel(0, ic_regbase + 0x24);
+
+		for (i = 0; i < wmt_nr_irqs; i++) {
+			/* Disable all interrupts and route them to IRQ */
+			writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
+
+			set_irq_chip(i, &vt8500_irq_chip);
+			set_irq_handler(i, handle_level_irq);
+			set_irq_flags(i, IRQF_VALID);
+		}
+	} else {
+		printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
+	}
+}
+
+void __init wm8505_init_irq(void)
+{
+	unsigned int i;
+
+	ic_regbase = ioremap(wmt_ic_base, SZ_64K);
+	sic_regbase = ioremap(wmt_sic_base, SZ_64K);
+
+	if (ic_regbase && sic_regbase) {
+		/* Enable rotating priority for IRQ */
+		writel((1 << 6), ic_regbase + 0x20);
+		writel(0, ic_regbase + 0x24);
+		writel((1 << 6), sic_regbase + 0x20);
+		writel(0, sic_regbase + 0x24);
+
+		for (i = 0; i < wmt_nr_irqs; i++) {
+			/* Disable all interrupts and route them to IRQ */
+			if (i < 64)
+				writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
+			else
+				writeb(0x00, sic_regbase + VT8500_IC_DCTR
+								+ i - 64);
+
+			set_irq_chip(i, &vt8500_irq_chip);
+			set_irq_handler(i, handle_level_irq);
+			set_irq_flags(i, IRQF_VALID);
+		}
+	} else {
+		printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
+	}
+}
diff --git a/arch/arm/mach-vt8500/pwm.c b/arch/arm/mach-vt8500/pwm.c
new file mode 100644
index 0000000..8ad825e
--- /dev/null
+++ b/arch/arm/mach-vt8500/pwm.c
@@ -0,0 +1,265 @@
+/*
+ * arch/arm/mach-vt8500/pwm.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#include <asm/div64.h>
+
+#define VT8500_NR_PWMS 4
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device	*pdev;
+
+	const char	*label;
+
+	void __iomem	*regbase;
+
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask)
+{
+	int loops = msecs_to_loops(10);
+	while ((readb(reg) & bitmask) && --loops)
+		cpu_relax();
+
+	if (unlikely(!loops))
+		pr_warning("Waiting for status bits 0x%x to clear timed out\n",
+			   bitmask);
+}
+
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+
+	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	c = 25000000/2; /* wild guess --- need to implement clocks */
+	c = c * period_ns;
+	do_div(c, 1000000000);
+	period_cycles = c;
+
+	if (period_cycles < 1)
+		period_cycles = 1;
+	prescale = (period_cycles - 1) / 4096;
+	pv = period_cycles / (prescale + 1) - 1;
+	if (pv > 4095)
+		pv = 4095;
+
+	if (prescale > 1023)
+		return -EINVAL;
+
+	c = (unsigned long long)pv * duty_ns;
+	do_div(c, period_ns);
+	dc = c;
+
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 1));
+	writel(prescale, pwm->regbase + 0x4 + (pwm->pwm_id << 4));
+
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 2));
+	writel(pv, pwm->regbase + 0x8 + (pwm->pwm_id << 4));
+
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 3));
+	writel(dc, pwm->regbase + 0xc + (pwm->pwm_id << 4));
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0));
+	writel(5, pwm->regbase + (pwm->pwm_id << 4));
+	return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0));
+	writel(0, pwm->regbase + (pwm->pwm_id << 4));
+}
+EXPORT_SYMBOL(pwm_disable);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm;
+	int found = 0;
+
+	mutex_lock(&pwm_lock);
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->pwm_id == pwm_id) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		if (pwm->use_count == 0) {
+			pwm->use_count++;
+			pwm->label = label;
+		} else {
+			pwm = ERR_PTR(-EBUSY);
+		}
+	} else {
+		pwm = ERR_PTR(-ENOENT);
+	}
+
+	mutex_unlock(&pwm_lock);
+	return pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+
+	if (pwm->use_count) {
+		pwm->use_count--;
+		pwm->label = NULL;
+	} else {
+		pr_warning("PWM device already freed\n");
+	}
+
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+static inline void __add_pwm(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+	list_add_tail(&pwm->node, &pwm_list);
+	mutex_unlock(&pwm_lock);
+}
+
+static int __devinit pwm_probe(struct platform_device *pdev)
+{
+	struct pwm_device *pwms;
+	struct resource *r;
+	int ret = 0;
+	int i;
+
+	pwms = kzalloc(sizeof(struct pwm_device) * VT8500_NR_PWMS, GFP_KERNEL);
+	if (pwms == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < VT8500_NR_PWMS; i++) {
+		pwms[i].use_count = 0;
+		pwms[i].pwm_id = i;
+		pwms[i].pdev = pdev;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	r = request_mem_region(r->start, resource_size(r), pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	pwms[0].regbase = ioremap(r->start, resource_size(r));
+	if (pwms[0].regbase == NULL) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -ENODEV;
+		goto err_free_mem;
+	}
+
+	for (i = 1; i < VT8500_NR_PWMS; i++)
+		pwms[i].regbase = pwms[0].regbase;
+
+	for (i = 0; i < VT8500_NR_PWMS; i++)
+		__add_pwm(&pwms[i]);
+
+	platform_set_drvdata(pdev, pwms);
+	return 0;
+
+err_free_mem:
+	release_mem_region(r->start, resource_size(r));
+err_free:
+	kfree(pwms);
+	return ret;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+	struct pwm_device *pwms;
+	struct resource *r;
+	int i;
+
+	pwms = platform_get_drvdata(pdev);
+	if (pwms == NULL)
+		return -ENODEV;
+
+	mutex_lock(&pwm_lock);
+
+	for (i = 0; i < VT8500_NR_PWMS; i++)
+		list_del(&pwms[i].node);
+	mutex_unlock(&pwm_lock);
+
+	iounmap(pwms[0].regbase);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	kfree(pwms);
+	return 0;
+}
+
+static struct platform_driver pwm_driver = {
+	.driver		= {
+		.name	= "vt8500-pwm",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pwm_probe,
+	.remove		= __devexit_p(pwm_remove),
+};
+
+static int __init pwm_init(void)
+{
+	return platform_driver_register(&pwm_driver);
+}
+arch_initcall(pwm_init);
+
+static void __exit pwm_exit(void)
+{
+	platform_driver_unregister(&pwm_driver);
+}
+module_exit(pwm_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c
new file mode 100644
index 0000000..d5376c5
--- /dev/null
+++ b/arch/arm/mach-vt8500/timer.c
@@ -0,0 +1,155 @@
+/*
+ *  arch/arm/mach-vt8500/timer.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/delay.h>
+
+#include <asm/mach/time.h>
+
+#include "devices.h"
+
+#define VT8500_TIMER_OFFSET	0x0100
+#define TIMER_MATCH_VAL		0x0000
+#define TIMER_COUNT_VAL		0x0010
+#define TIMER_STATUS_VAL	0x0014
+#define TIMER_IER_VAL		0x001c		/* interrupt enable */
+#define TIMER_CTRL_VAL		0x0020
+#define TIMER_AS_VAL		0x0024		/* access status */
+#define TIMER_COUNT_R_ACTIVE	(1 << 5)	/* not ready for read */
+#define TIMER_COUNT_W_ACTIVE	(1 << 4)	/* not ready for write */
+#define TIMER_MATCH_W_ACTIVE	(1 << 0)	/* not ready for write */
+#define VT8500_TIMER_HZ		3000000
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+static void __iomem *regbase;
+
+static cycle_t vt8500_timer_read(struct clocksource *cs)
+{
+	int loops = msecs_to_loops(10);
+	writel(3, regbase + TIMER_CTRL_VAL);
+	while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE)
+						&& --loops)
+		cpu_relax();
+	return readl(regbase + TIMER_COUNT_VAL);
+}
+
+struct clocksource clocksource = {
+	.name           = "vt8500_timer",
+	.rating         = 200,
+	.read           = vt8500_timer_read,
+	.mask           = CLOCKSOURCE_MASK(32),
+	.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int vt8500_timer_set_next_event(unsigned long cycles,
+				    struct clock_event_device *evt)
+{
+	int loops = msecs_to_loops(10);
+	cycle_t alarm = clocksource.read(&clocksource) + cycles;
+	while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE)
+						&& --loops)
+		cpu_relax();
+	writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL);
+
+	if ((signed)(alarm - clocksource.read(&clocksource)) <= 16)
+		return -ETIME;
+
+	writel(1, regbase + TIMER_IER_VAL);
+
+	return 0;
+}
+
+static void vt8500_timer_set_mode(enum clock_event_mode mode,
+			      struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel(readl(regbase + TIMER_CTRL_VAL) | 1,
+			regbase + TIMER_CTRL_VAL);
+		writel(0, regbase + TIMER_IER_VAL);
+		break;
+	}
+}
+
+struct clock_event_device clockevent = {
+	.name           = "vt8500_timer",
+	.features       = CLOCK_EVT_FEAT_ONESHOT,
+	.rating         = 200,
+	.set_next_event = vt8500_timer_set_next_event,
+	.set_mode       = vt8500_timer_set_mode,
+};
+
+static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	writel(0xf, regbase + TIMER_STATUS_VAL);
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+struct irqaction irq = {
+	.name    = "vt8500_timer",
+	.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler = vt8500_timer_interrupt,
+	.dev_id  = &clockevent,
+};
+
+static void __init vt8500_timer_init(void)
+{
+	regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28);
+	if (!regbase)
+		printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n");
+
+	writel(1, regbase + TIMER_CTRL_VAL);
+	writel(0xf, regbase + TIMER_STATUS_VAL);
+	writel(~0, regbase + TIMER_MATCH_VAL);
+
+	if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ))
+		printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n",
+					clocksource.name);
+
+	clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4);
+
+	/* copy-pasted from mach-msm; no idea */
+	clockevent.max_delta_ns =
+		clockevent_delta2ns(0xf0000000, &clockevent);
+	clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent);
+	clockevent.cpumask = cpumask_of(0);
+
+	if (setup_irq(wmt_timer_irq, &irq))
+		printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n",
+					clockevent.name);
+	clockevents_register_device(&clockevent);
+}
+
+struct sys_timer vt8500_timer = {
+	.init = vt8500_timer_init
+};
diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c
new file mode 100644
index 0000000..e73aadb
--- /dev/null
+++ b/arch/arm/mach-vt8500/wm8505_7in.c
@@ -0,0 +1,77 @@
+/*
+ *  arch/arm/mach-vt8500/wm8505_7in.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "devices.h"
+
+static void __iomem *pmc_hiber;
+
+static struct platform_device *devices[] __initdata = {
+	&vt8500_device_uart0,
+	&vt8500_device_ehci,
+	&vt8500_device_wm8505_fb,
+	&vt8500_device_ge_rops,
+	&vt8500_device_pwm,
+	&vt8500_device_pwmbl,
+	&vt8500_device_rtc,
+};
+
+static void vt8500_power_off(void)
+{
+	local_irq_disable();
+	writew(5, pmc_hiber);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init wm8505_7in_init(void)
+{
+#ifdef CONFIG_FB_WM8505
+	void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
+	if (gpio_mux_reg) {
+		writel(readl(gpio_mux_reg) | 0x80000000, gpio_mux_reg);
+		iounmap(gpio_mux_reg);
+	} else {
+		printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
+	}
+#endif
+	pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
+	if (pmc_hiber)
+		pm_power_off = &vt8500_power_off;
+	else
+		printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
+
+	wm8505_set_resources();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	vt8500_gpio_init();
+}
+
+MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
+	.boot_params	= 0x00000100,
+	.reserve	= wm8505_reserve_mem,
+	.map_io		= wm8505_map_io,
+	.init_irq	= wm8505_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= wm8505_7in_init,
+MACHINE_END
diff --git a/arch/arm/mach-w90x900/include/mach/memory.h b/arch/arm/mach-w90x900/include/mach/memory.h
index 971b807..f02905b 100644
--- a/arch/arm/mach-w90x900/include/mach/memory.h
+++ b/arch/arm/mach-w90x900/include/mach/memory.h
@@ -18,6 +18,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index e4509ba..0074b8d 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -390,7 +390,7 @@ config CPU_PJ4
 
 # ARMv6
 config CPU_V6
-	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_DOVE
+	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 	select CPU_32v6
 	select CPU_ABRT_EV6
 	select CPU_PABRT_V6
@@ -402,16 +402,18 @@ config CPU_V6
 	select CPU_TLB_V6 if MMU
 
 # ARMv6k
-config CPU_32v6K
-	bool "Support ARM V6K processor extensions" if !SMP
-	depends on CPU_V6 || CPU_V7
-	default y if SMP
-	help
-	  Say Y here if your ARMv6 processor supports the 'K' extension.
-	  This enables the kernel to use some instructions not present
-	  on previous processors, and as such a kernel build with this
-	  enabled will not boot on processors with do not support these
-	  instructions.
+config CPU_V6K
+	bool "Support ARM V6K processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+	select CPU_32v6
+	select CPU_32v6K
+	select CPU_ABRT_EV6
+	select CPU_PABRT_V6
+	select CPU_CACHE_V6
+	select CPU_CACHE_VIPT
+	select CPU_CP15_MMU
+	select CPU_HAS_ASID if MMU
+	select CPU_COPY_V6 if MMU
+	select CPU_TLB_V6 if MMU
 
 # ARMv7
 config CPU_V7
@@ -433,25 +435,33 @@ config CPU_32v3
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v4
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v4T
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v5
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v6
 	bool
 	select TLS_REG_EMUL if !CPU_32v6K && !MMU
+	select CPU_USE_DOMAINS if CPU_V6 && MMU
+
+config CPU_32v6K
+	bool
 
 config CPU_32v7
 	bool
@@ -607,8 +617,6 @@ config CPU_CP15_MPU
 
 config CPU_USE_DOMAINS
 	bool
-	depends on MMU
-	default y if !CPU_32v6K
 	help
 	  This option enables or disables the use of domain switching
 	  via the set_fs() function.
@@ -623,7 +631,7 @@ comment "Processor Features"
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	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_V7 || CPU_FEROCEON
+	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
 	  Say Y if you want to include kernel support for running user space
@@ -644,7 +652,7 @@ config ARM_THUMBEE
 
 config SWP_EMULATE
 	bool "Emulate SWP/SWPB instructions"
-	depends on !CPU_USE_DOMAINS && CPU_V7 && !CPU_V6
+	depends on !CPU_USE_DOMAINS && CPU_V7
 	select HAVE_PROC_CPU if PROC_FS
 	default y if SMP
 	help
@@ -681,7 +689,7 @@ config CPU_BIG_ENDIAN
 config CPU_ENDIAN_BE8
 	bool
 	depends on CPU_BIG_ENDIAN
-	default CPU_V6 || CPU_V7
+	default CPU_V6 || CPU_V6K || CPU_V7
 	help
 	  Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors.
 
@@ -747,7 +755,7 @@ config CPU_CACHE_ROUND_ROBIN
 
 config CPU_BPREDICT_DISABLE
 	bool "Disable branch prediction"
-	depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526
+	depends on CPU_ARM1020 || CPU_V6 || CPU_V6K || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526
 	help
 	  Say Y here to disable branch prediction.  If unsure, say N.
 
@@ -767,7 +775,7 @@ config NEEDS_SYSCALL_FOR_CMPXCHG
 
 config DMA_CACHE_RWFO
 	bool "Enable read/write for ownership DMA cache maintenance"
-	depends on CPU_V6 && SMP
+	depends on CPU_V6K && SMP
 	default y
 	help
 	  The Snoop Control Unit on ARM11MPCore does not detect the
@@ -811,8 +819,8 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
 config CACHE_L2X0
 	bool "Enable the L2x0 outer cache controller"
 	depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
-		   REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || \
-		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_S5PV310 || ARCH_TEGRA || \
+		   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
+		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
 		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
 	default y
 	select OUTER_CACHE
@@ -823,7 +831,7 @@ config CACHE_L2X0
 config CACHE_PL310
 	bool
 	depends on CACHE_L2X0
-	default y if CPU_V7 && !CPU_V6
+	default y if CPU_V7 && !(CPU_V6 || CPU_V6K)
 	help
 	  This option enables optimisations for the PL310 cache
 	  controller.
@@ -845,16 +853,21 @@ config CACHE_XSC3L2
 	help
 	  This option enables the L2 cache on XScale3.
 
+config ARM_L1_CACHE_SHIFT_6
+	bool
+	help
+	  Setting ARM L1 cache line size to 64 Bytes.
+
 config ARM_L1_CACHE_SHIFT
 	int
 	default 6 if ARM_L1_CACHE_SHIFT_6
 	default 5
 
 config ARM_DMA_MEM_BUFFERABLE
-	bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7
+	bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7
 	depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \
 		     MACH_REALVIEW_PB11MP)
-	default y if CPU_V6 || CPU_V7
+	default y if CPU_V6 || CPU_V6K || CPU_V7
 	help
 	  Historically, the kernel has used strongly ordered mappings to
 	  provide DMA coherent memory.  With the advent of ARMv7, mapping
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 00d74a0..bca7e61 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_CPU_XSC3)		+= proc-xsc3.o
 obj-$(CONFIG_CPU_MOHAWK)	+= proc-mohawk.o
 obj-$(CONFIG_CPU_FEROCEON)	+= proc-feroceon.o
 obj-$(CONFIG_CPU_V6)		+= proc-v6.o
+obj-$(CONFIG_CPU_V6K)		+= proc-v6.o
 obj-$(CONFIG_CPU_V7)		+= proc-v7.o
 
 AFLAGS_proc-v6.o	:=-Wa,-march=armv6
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index f332df7..1478aa5 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -20,11 +20,11 @@
  */
 	.align	5
 ENTRY(v6_early_abort)
-#ifdef CONFIG_CPU_32v6K
-	clrex
-#else
+#ifdef CONFIG_CPU_V6
 	sub	r1, sp, #4			@ Get unused stack location
 	strex	r0, r1, [r1]			@ Clear the exclusive monitor
+#elif defined(CONFIG_CPU_32v6K)
+	clrex
 #endif
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index f2ce38e..ef59099 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -73,18 +73,24 @@ static inline void l2x0_inv_line(unsigned long addr)
 	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
 }
 
-#ifdef CONFIG_PL310_ERRATA_588369
-static void debug_writel(unsigned long val)
-{
-	extern void omap_smc1(u32 fn, u32 arg);
+#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
 
-	/*
-	 * Texas Instrument secure monitor api to modify the
-	 * PL310 Debug Control Register.
-	 */
-	omap_smc1(0x100, val);
+#define debug_writel(val)	outer_cache.set_debug(val)
+
+static void l2x0_set_debug(unsigned long val)
+{
+	writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
 }
+#else
+/* Optimised out for non-errata case */
+static inline void debug_writel(unsigned long val)
+{
+}
+
+#define l2x0_set_debug	NULL
+#endif
 
+#ifdef CONFIG_PL310_ERRATA_588369
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
@@ -97,11 +103,6 @@ static inline void l2x0_flush_line(unsigned long addr)
 }
 #else
 
-/* Optimised out for non-errata case */
-static inline void debug_writel(unsigned long val)
-{
-}
-
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
@@ -125,9 +126,11 @@ static void l2x0_flush_all(void)
 
 	/* clean all ways */
 	spin_lock_irqsave(&l2x0_lock, flags);
+	debug_writel(0x03);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
 	cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
 	cache_sync();
+	debug_writel(0x00);
 	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
@@ -335,6 +338,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
 	outer_cache.flush_all = l2x0_flush_all;
 	outer_cache.inv_all = l2x0_inv_all;
 	outer_cache.disable = l2x0_disable;
+	outer_cache.set_debug = l2x0_set_debug;
 
 	printk(KERN_INFO "%s cache controller enabled\n", type);
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index b0a9830..afe209e 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -31,7 +31,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long start_addr;
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 	unsigned int cache_type;
 	int do_align = 0, aliasing = 0;
 
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 3c67e92..ff7b43b 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -827,16 +827,6 @@ static void __init sanity_check_meminfo(void)
 			 * rather difficult.
 			 */
 			reason = "with VIPT aliasing cache";
-		} else if (is_smp() && tlb_ops_need_broadcast()) {
-			/*
-			 * kmap_high needs to occasionally flush TLB entries,
-			 * however, if the TLB entries need to be broadcast
-			 * we may deadlock:
-			 *  kmap_high(irqs off)->flush_all_zero_pkmaps->
-			 *  flush_tlb_kernel_range->smp_call_function_many
-			 *   (must not be called with irqs off)
-			 */
-			reason = "without hardware TLB ops broadcasting";
 		}
 		if (reason) {
 			printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S
index bcf748d..226e3d8 100644
--- a/arch/arm/mm/proc-arm1020.S
+++ b/arch/arm/mm/proc-arm1020.S
@@ -493,6 +493,9 @@ arm1020_processor_functions:
 	.word	cpu_arm1020_dcache_clean_area
 	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S
index ab7ec26..86d9c2c 100644
--- a/arch/arm/mm/proc-arm1020e.S
+++ b/arch/arm/mm/proc-arm1020e.S
@@ -474,6 +474,9 @@ arm1020e_processor_functions:
 	.word	cpu_arm1020e_dcache_clean_area
 	.word	cpu_arm1020e_switch_mm
 	.word	cpu_arm1020e_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S
index 831c5e5..83d3dd3 100644
--- a/arch/arm/mm/proc-arm1022.S
+++ b/arch/arm/mm/proc-arm1022.S
@@ -457,6 +457,9 @@ arm1022_processor_functions:
 	.word	cpu_arm1022_dcache_clean_area
 	.word	cpu_arm1022_switch_mm
 	.word	cpu_arm1022_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1022_processor_functions, . - arm1022_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S
index e3f7e9a..686043e 100644
--- a/arch/arm/mm/proc-arm1026.S
+++ b/arch/arm/mm/proc-arm1026.S
@@ -452,6 +452,9 @@ arm1026_processor_functions:
 	.word	cpu_arm1026_dcache_clean_area
 	.word	cpu_arm1026_switch_mm
 	.word	cpu_arm1026_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1026_processor_functions, . - arm1026_processor_functions
 
 	.section .rodata
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S
index 6a7be18..5f79dc4 100644
--- a/arch/arm/mm/proc-arm6_7.S
+++ b/arch/arm/mm/proc-arm6_7.S
@@ -284,6 +284,9 @@ ENTRY(arm6_processor_functions)
 		.word	cpu_arm6_dcache_clean_area
 		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -301,6 +304,9 @@ ENTRY(arm7_processor_functions)
 		.word	cpu_arm7_dcache_clean_area
 		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S
index c285395..665266d 100644
--- a/arch/arm/mm/proc-arm720.S
+++ b/arch/arm/mm/proc-arm720.S
@@ -185,6 +185,9 @@ ENTRY(arm720_processor_functions)
 		.word	cpu_arm720_dcache_clean_area
 		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index 38b27dc..6f9d12e 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -130,6 +130,9 @@ ENTRY(arm740_processor_functions)
 	.word	cpu_arm740_dcache_clean_area
 	.word	cpu_arm740_switch_mm
 	.word	0			@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm740_processor_functions, . - arm740_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm7tdmi.S b/arch/arm/mm/proc-arm7tdmi.S
index 0c9786d..e4c165c 100644
--- a/arch/arm/mm/proc-arm7tdmi.S
+++ b/arch/arm/mm/proc-arm7tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm7tdmi_processor_functions)
 		.word	cpu_arm7tdmi_dcache_clean_area
 		.word	cpu_arm7tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 6109f27..219980e 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -387,6 +387,40 @@ ENTRY(cpu_arm920_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	cpu_arm920_suspend_size
+.equ	cpu_arm920_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(cpu_arm920_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_arm920_do_suspend)
+
+ENTRY(cpu_arm920_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_arm920_do_resume)
+#else
+#define cpu_arm920_do_suspend	0
+#define cpu_arm920_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm920_setup, #function
@@ -432,6 +466,9 @@ arm920_processor_functions:
 	.word	cpu_arm920_dcache_clean_area
 	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte_ext
+	.word	cpu_arm920_suspend_size
+	.word	cpu_arm920_do_suspend
+	.word	cpu_arm920_do_resume
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S
index bb2f0f4..36154b1 100644
--- a/arch/arm/mm/proc-arm922.S
+++ b/arch/arm/mm/proc-arm922.S
@@ -436,6 +436,9 @@ arm922_processor_functions:
 	.word	cpu_arm922_dcache_clean_area
 	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S
index c13e01a..89c5e000 100644
--- a/arch/arm/mm/proc-arm925.S
+++ b/arch/arm/mm/proc-arm925.S
@@ -503,6 +503,9 @@ arm925_processor_functions:
 	.word	cpu_arm925_dcache_clean_area
 	.word	cpu_arm925_switch_mm
 	.word	cpu_arm925_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm925_processor_functions, . - arm925_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index 42eb431..6a4bdb2 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -401,6 +401,40 @@ ENTRY(cpu_arm926_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	cpu_arm926_suspend_size
+.equ	cpu_arm926_suspend_size, 4 * 3
+#ifdef CONFIG_PM
+ENTRY(cpu_arm926_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_arm926_do_suspend)
+
+ENTRY(cpu_arm926_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_arm926_do_resume)
+#else
+#define cpu_arm926_do_suspend	0
+#define cpu_arm926_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm926_setup, #function
@@ -456,6 +490,9 @@ arm926_processor_functions:
 	.word	cpu_arm926_dcache_clean_area
 	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte_ext
+	.word	cpu_arm926_suspend_size
+	.word	cpu_arm926_do_suspend
+	.word	cpu_arm926_do_resume
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S
index 7b11cdb..26aea3f 100644
--- a/arch/arm/mm/proc-arm940.S
+++ b/arch/arm/mm/proc-arm940.S
@@ -363,6 +363,9 @@ ENTRY(arm940_processor_functions)
 	.word	cpu_arm940_dcache_clean_area
 	.word	cpu_arm940_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm940_processor_functions, . - arm940_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S
index 1a5bbf0..8063345 100644
--- a/arch/arm/mm/proc-arm946.S
+++ b/arch/arm/mm/proc-arm946.S
@@ -419,6 +419,9 @@ ENTRY(arm946_processor_functions)
 	.word	cpu_arm946_dcache_clean_area
 	.word	cpu_arm946_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm946_processor_functions, . - arm946_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-arm9tdmi.S b/arch/arm/mm/proc-arm9tdmi.S
index db67e31..7b7ebd4 100644
--- a/arch/arm/mm/proc-arm9tdmi.S
+++ b/arch/arm/mm/proc-arm9tdmi.S
@@ -70,6 +70,9 @@ ENTRY(arm9tdmi_processor_functions)
 		.word	cpu_arm9tdmi_dcache_clean_area
 		.word	cpu_arm9tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
 
 		.section ".rodata"
diff --git a/arch/arm/mm/proc-fa526.S b/arch/arm/mm/proc-fa526.S
index 7c9ad62..fc2a4ae 100644
--- a/arch/arm/mm/proc-fa526.S
+++ b/arch/arm/mm/proc-fa526.S
@@ -195,6 +195,9 @@ fa526_processor_functions:
 	.word	cpu_fa526_dcache_clean_area
 	.word	cpu_fa526_switch_mm
 	.word	cpu_fa526_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	fa526_processor_functions, . - fa526_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
index b4597ed..d3883ee 100644
--- a/arch/arm/mm/proc-feroceon.S
+++ b/arch/arm/mm/proc-feroceon.S
@@ -554,6 +554,9 @@ feroceon_processor_functions:
 	.word	cpu_feroceon_dcache_clean_area
 	.word	cpu_feroceon_switch_mm
 	.word	cpu_feroceon_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	feroceon_processor_functions, . - feroceon_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 4458ee6..9d4f2ae 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -388,6 +388,9 @@ mohawk_processor_functions:
 	.word	cpu_mohawk_dcache_clean_area
 	.word	cpu_mohawk_switch_mm
 	.word	cpu_mohawk_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	mohawk_processor_functions, . - mohawk_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S
index 5aa8d59..46f09ed 100644
--- a/arch/arm/mm/proc-sa110.S
+++ b/arch/arm/mm/proc-sa110.S
@@ -203,6 +203,9 @@ ENTRY(sa110_processor_functions)
 	.word	cpu_sa110_dcache_clean_area
 	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 2ac4e6f..74483d1 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -169,6 +169,42 @@ ENTRY(cpu_sa1100_set_pte_ext)
 #endif
 	mov	pc, lr
 
+.globl	cpu_sa1100_suspend_size
+.equ	cpu_sa1100_suspend_size, 4*4
+#ifdef CONFIG_PM
+ENTRY(cpu_sa1100_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
+	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r6, c13, c0, 0		@ PID
+	mrc	p15, 0, r7, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r7}			@ store cp regs
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_sa1100_do_suspend)
+
+ENTRY(cpu_sa1100_do_resume)
+	ldmia	r0, {r4 - r7}			@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@ flush I+D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
+	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
+
+	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
+	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r6, c13, c0, 0		@ PID
+	mov	r0, r7				@ control register
+	mov	r2, r5, lsr #14			@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_sa1100_do_resume)
+#else
+#define cpu_sa1100_do_suspend	0
+#define cpu_sa1100_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__sa1100_setup, #function
@@ -218,6 +254,9 @@ ENTRY(sa1100_processor_functions)
 	.word	cpu_sa1100_dcache_clean_area
 	.word	cpu_sa1100_switch_mm
 	.word	cpu_sa1100_set_pte_ext
+	.word	cpu_sa1100_suspend_size
+	.word	cpu_sa1100_do_suspend
+	.word	cpu_sa1100_do_resume
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 59a7e1f..832b6bd 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -121,6 +121,53 @@ ENTRY(cpu_v6_set_pte_ext)
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
+.globl	cpu_v6_suspend_size
+.equ	cpu_v6_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_v6_do_suspend)
+	stmfd	sp!, {r4 - r11, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ Translation table base 0
+	mrc	p15, 0, r8, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r9, c1, c0, 1	@ auxillary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r11, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r11}
+	ldmfd	sp!, {r4- r11, pc}
+ENDPROC(cpu_v6_do_suspend)
+
+ENTRY(cpu_v6_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
+	ldmia	r0, {r4 - r11}
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0	@ Translation table base 0
+	mcr	p15, 0, r8, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r9, c1, c0, 1	@ auxillary control register
+	mcr	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, ip, c7, c5, 4	@ ISB
+	mov	r0, r11			@ control register
+	mov	r2, r7, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v6_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v6_do_suspend 0
+#define cpu_v6_do_resume 0
+#endif
 
 
 	.type	cpu_v6_name, #object
@@ -206,6 +253,9 @@ ENTRY(v6_processor_functions)
 	.word	cpu_v6_dcache_clean_area
 	.word	cpu_v6_switch_mm
 	.word	cpu_v6_set_pte_ext
+	.word	cpu_v6_suspend_size
+	.word	cpu_v6_do_suspend
+	.word	cpu_v6_do_resume
 	.size	v6_processor_functions, . - v6_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 8e33562..262fa88 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -108,10 +108,16 @@ ENTRY(cpu_v7_switch_mm)
 #ifdef CONFIG_ARM_ERRATA_430973
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 #endif
+#ifdef CONFIG_ARM_ERRATA_754322
+	dsb
+#endif
 	mcr	p15, 0, r2, c13, c0, 1		@ set reserved context ID
 	isb
 1:	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
 	isb
+#ifdef CONFIG_ARM_ERRATA_754322
+	dsb
+#endif
 	mcr	p15, 0, r1, c13, c0, 1		@ set context ID
 	isb
 #endif
@@ -171,6 +177,87 @@ cpu_v7_name:
 	.ascii	"ARMv7 Processor"
 	.align
 
+	/*
+	 * Memory region attributes with SCTLR.TRE=1
+	 *
+	 *   n = TEX[0],C,B
+	 *   TR = PRRR[2n+1:2n]		- memory type
+	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
+	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
+	 *
+	 *			n	TR	IR	OR
+	 *   UNCACHED		000	00
+	 *   BUFFERABLE		001	10	00	00
+	 *   WRITETHROUGH	010	10	10	10
+	 *   WRITEBACK		011	10	11	11
+	 *   reserved		110
+	 *   WRITEALLOC		111	10	01	01
+	 *   DEV_SHARED		100	01
+	 *   DEV_NONSHARED	100	01
+	 *   DEV_WC		001	10
+	 *   DEV_CACHED		011	10
+	 *
+	 * Other attributes:
+	 *
+	 *   DS0 = PRRR[16] = 0		- device shareable property
+	 *   DS1 = PRRR[17] = 1		- device shareable property
+	 *   NS0 = PRRR[18] = 0		- normal shareable property
+	 *   NS1 = PRRR[19] = 1		- normal shareable property
+	 *   NOS = PRRR[24+n] = 1	- not outer shareable
+	 */
+.equ	PRRR,	0xff0a81a8
+.equ	NMRR,	0x40e040e0
+
+/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
+.globl	cpu_v7_suspend_size
+.equ	cpu_v7_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_v7_do_suspend)
+	stmfd	sp!, {r4 - r11, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ TTB 0
+	mrc	p15, 0, r8, c2, c0, 1	@ TTB 1
+	mrc	p15, 0, r9, c1, c0, 0	@ Control register
+	mrc	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
+	mrc	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	stmia	r0, {r4 - r11}
+	ldmfd	sp!, {r4 - r11, pc}
+ENDPROC(cpu_v7_do_suspend)
+
+ENTRY(cpu_v7_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate TLBs
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	ldmia	r0, {r4 - r11}
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0	@ TTB 0
+	mcr	p15, 0, r8, c2, c0, 1	@ TTB 1
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, r10, c1, c0, 1	@ Auxillary control register
+	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	ldr	r4, =PRRR		@ PRRR
+	ldr	r5, =NMRR		@ NMRR
+	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
+	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
+	isb
+	mov	r0, r9			@ control register
+	mov	r2, r7, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v7_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v7_do_suspend	0
+#define cpu_v7_do_resume	0
+#endif
+
 	__CPUINIT
 
 /*
@@ -282,36 +369,8 @@ __v7_setup:
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	/*
-	 * Memory region attributes with SCTLR.TRE=1
-	 *
-	 *   n = TEX[0],C,B
-	 *   TR = PRRR[2n+1:2n]		- memory type
-	 *   IR = NMRR[2n+1:2n]		- inner cacheable property
-	 *   OR = NMRR[2n+17:2n+16]	- outer cacheable property
-	 *
-	 *			n	TR	IR	OR
-	 *   UNCACHED		000	00
-	 *   BUFFERABLE		001	10	00	00
-	 *   WRITETHROUGH	010	10	10	10
-	 *   WRITEBACK		011	10	11	11
-	 *   reserved		110
-	 *   WRITEALLOC		111	10	01	01
-	 *   DEV_SHARED		100	01
-	 *   DEV_NONSHARED	100	01
-	 *   DEV_WC		001	10
-	 *   DEV_CACHED		011	10
-	 *
-	 * Other attributes:
-	 *
-	 *   DS0 = PRRR[16] = 0		- device shareable property
-	 *   DS1 = PRRR[17] = 1		- device shareable property
-	 *   NS0 = PRRR[18] = 0		- normal shareable property
-	 *   NS1 = PRRR[19] = 1		- normal shareable property
-	 *   NOS = PRRR[24+n] = 1	- not outer shareable
-	 */
-	ldr	r5, =0xff0a81a8			@ PRRR
-	ldr	r6, =0x40e040e0			@ NMRR
+	ldr	r5, =PRRR			@ PRRR
+	ldr	r6, =NMRR			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
@@ -357,6 +416,9 @@ ENTRY(v7_processor_functions)
 	.word	cpu_v7_dcache_clean_area
 	.word	cpu_v7_switch_mm
 	.word	cpu_v7_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	v7_processor_functions, . - v7_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index ec26355..63d8b20 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -413,9 +413,52 @@ ENTRY(cpu_xsc3_set_pte_ext)
 	mov	pc, lr
 
 	.ltorg
-
 	.align
 
+.globl	cpu_xsc3_suspend_size
+.equ	cpu_xsc3_suspend_size, 4 * 8
+#ifdef CONFIG_PM
+ENTRY(cpu_xsc3_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r1, r4 - r10}	@ store v:p offset + cp regs
+	ldmia	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xsc3_do_suspend)
+
+ENTRY(cpu_xsc3_do_resume)
+	ldmia	r0, {r1, r4 - r10}	@ load v:p offset + cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, ip, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =0x542e		@ section flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_xsc3_do_resume)
+#else
+#define cpu_xsc3_do_suspend	0
+#define cpu_xsc3_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xsc3_setup, #function
@@ -476,6 +519,9 @@ ENTRY(xsc3_processor_functions)
 	.word	cpu_xsc3_dcache_clean_area
 	.word	cpu_xsc3_switch_mm
 	.word	cpu_xsc3_set_pte_ext
+	.word	cpu_xsc3_suspend_size
+	.word	cpu_xsc3_do_suspend
+	.word	cpu_xsc3_do_resume
 	.size	xsc3_processor_functions, . - xsc3_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 5a37c5e..086038c 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -513,11 +513,49 @@ ENTRY(cpu_xscale_set_pte_ext)
 	xscale_set_pte_ext_epilogue
 	mov	pc, lr
 
-
 	.ltorg
-
 	.align
 
+.globl	cpu_xscale_suspend_size
+.equ	cpu_xscale_suspend_size, 4 * 7
+#ifdef CONFIG_PM
+ENTRY(cpu_xscale_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xscale_do_suspend)
+
+ENTRY(cpu_xscale_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_xscale_do_resume)
+#else
+#define cpu_xscale_do_suspend	0
+#define cpu_xscale_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xscale_setup, #function
@@ -565,6 +603,9 @@ ENTRY(xscale_processor_functions)
 	.word	cpu_xscale_dcache_clean_area
 	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte_ext
+	.word	cpu_xscale_suspend_size
+	.word	cpu_xscale_do_suspend
+	.word	cpu_xscale_do_resume
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
 	.section ".rodata"
diff --git a/arch/arm/mm/vmregion.c b/arch/arm/mm/vmregion.c
index 935993e..036fdbf 100644
--- a/arch/arm/mm/vmregion.c
+++ b/arch/arm/mm/vmregion.c
@@ -38,7 +38,7 @@ struct arm_vmregion *
 arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
 		   size_t size, gfp_t gfp)
 {
-	unsigned long addr = head->vm_start, end = head->vm_end - size;
+	unsigned long start = head->vm_start, addr = head->vm_end;
 	unsigned long flags;
 	struct arm_vmregion *c, *new;
 
@@ -54,21 +54,20 @@ arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
 
 	spin_lock_irqsave(&head->vm_lock, flags);
 
-	list_for_each_entry(c, &head->vm_list, vm_list) {
-		if ((addr + size) < addr)
-			goto nospc;
-		if ((addr + size) <= c->vm_start)
+	addr = rounddown(addr - size, align);
+	list_for_each_entry_reverse(c, &head->vm_list, vm_list) {
+		if (addr >= c->vm_end)
 			goto found;
-		addr = ALIGN(c->vm_end, align);
-		if (addr > end)
+		addr = rounddown(c->vm_start - size, align);
+		if (addr < start)
 			goto nospc;
 	}
 
  found:
 	/*
-	 * Insert this entry _before_ the one we found.
+	 * Insert this entry after the one we found.
 	 */
-	list_add_tail(&new->vm_list, &c->vm_list);
+	list_add(&new->vm_list, &c->vm_list);
 	new->vm_start = addr;
 	new->vm_end = addr + size;
 	new->vm_active = 1;
diff --git a/arch/arm/plat-mxc/Kconfig b/arch/arm/plat-mxc/Kconfig
index 389f217..b0cb425 100644
--- a/arch/arm/plat-mxc/Kconfig
+++ b/arch/arm/plat-mxc/Kconfig
@@ -33,6 +33,7 @@ config ARCH_MX3
 config ARCH_MXC91231
 	bool "MXC91231-based"
 	select CPU_V6
+	select MXC_AVIC
 	help
 	  This enables support for systems based on the Freescale MXC91231 family
 
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index 5fd20e9..a138787 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
 obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
-obj-$(CONFIG_USB_EHCI_MXC) += ehci.o
 obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
diff --git a/arch/arm/plat-mxc/devices.c b/arch/arm/plat-mxc/devices.c
index e9bcefe..eee1b60 100644
--- a/arch/arm/plat-mxc/devices.c
+++ b/arch/arm/plat-mxc/devices.c
@@ -81,6 +81,8 @@ struct platform_device *__init imx_add_platform_device_dmamask(
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		if (dmamask)
+			kfree(pdev->dev.dma_mask);
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
diff --git a/arch/arm/plat-mxc/devices/platform-fec.c b/arch/arm/plat-mxc/devices/platform-fec.c
index b50c351..6561c9d 100644
--- a/arch/arm/plat-mxc/devices/platform-fec.c
+++ b/arch/arm/plat-mxc/devices/platform-fec.c
@@ -31,6 +31,11 @@ const struct imx_fec_data imx35_fec_data __initconst =
 	imx_fec_data_entry_single(MX35);
 #endif
 
+#ifdef CONFIG_SOC_IMX50
+const struct imx_fec_data imx50_fec_data __initconst =
+	imx_fec_data_entry_single(MX50);
+#endif
+
 #ifdef CONFIG_SOC_IMX51
 const struct imx_fec_data imx51_fec_data __initconst =
 	imx_fec_data_entry_single(MX51);
@@ -57,7 +62,7 @@ struct platform_device *__init imx_add_fec(
 		},
 	};
 
-	return imx_add_platform_device("fec", 0 /* -1? */,
+	return imx_add_platform_device_dmamask("fec", 0,
 			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dma.c b/arch/arm/plat-mxc/devices/platform-imx-dma.c
index 33530d2..3538b85 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-dma.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-dma.c
@@ -94,7 +94,7 @@ static struct sdma_script_start_addrs addr_imx25_to1 = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 static struct sdma_script_start_addrs addr_imx31_to1 = {
 	.per_2_per_addr = 1677,
 };
@@ -106,7 +106,7 @@ static struct sdma_script_start_addrs addr_imx31_to2 = {
 };
 #endif
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 static struct sdma_script_start_addrs addr_imx35_to1 = {
 	.ap_2_ap_addr = 642,
 	.uart_2_mcu_addr = 817,
@@ -194,7 +194,7 @@ static int __init imxXX_add_imx_dma(void)
 	} else
 #endif
 
-#if defined(CONFIG_ARCH_MX51)
+#if defined(CONFIG_SOC_IMX51)
 	if (cpu_is_mx51()) {
 		imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1;
 		ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
diff --git a/arch/arm/plat-mxc/devices/platform-imx-fb.c b/arch/arm/plat-mxc/devices/platform-imx-fb.c
index 6100a7d..79a1cb1 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-fb.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-fb.c
@@ -16,6 +16,11 @@
 		.irq = soc ## _INT_LCDC,				\
 	}
 
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_fb_data imx1_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX1, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
 #ifdef CONFIG_SOC_IMX21
 const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
 	imx_imx_fb_data_entry_single(MX21, SZ_4K);
diff --git a/arch/arm/plat-mxc/devices/platform-imx-i2c.c b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
index 7ba94e1..2ab74f0 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-i2c.c
@@ -69,6 +69,16 @@ const struct imx_imx_i2c_data imx35_imx_i2c_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX50
+const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
+#define imx50_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX50, _id, _hwid, SZ_4K)
+	imx50_imx_i2c_data_entry(0, 1),
+	imx50_imx_i2c_data_entry(1, 2),
+	imx50_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
 #ifdef CONFIG_SOC_IMX51
 const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 #define imx51_imx_i2c_data_entry(_id, _hwid)				\
diff --git a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
index e0aec61..5e07ef2 100644
--- a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
+++ b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
@@ -53,6 +53,15 @@ const struct imx_imx2_wdt_data imx51_imx2_wdt_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst = {
+#define imx53_imx2_wdt_data_entry(_id, _hwid)				\
+	imx_imx2_wdt_data_entry(MX53, _id, _hwid, SZ_16K)
+	imx53_imx2_wdt_data_entry(0, 1),
+	imx53_imx2_wdt_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_imx2_wdt(
 		const struct imx_imx2_wdt_data *data)
 {
diff --git a/arch/arm/plat-mxc/devices/platform-spi_imx.c b/arch/arm/plat-mxc/devices/platform-spi_imx.c
index 013c85f..f4a60ab 100644
--- a/arch/arm/plat-mxc/devices/platform-spi_imx.c
+++ b/arch/arm/plat-mxc/devices/platform-spi_imx.c
@@ -21,6 +21,15 @@
 #define imx_spi_imx_data_entry(soc, type, devid, id, hwid, size)	\
 	[id] = imx_spi_imx_data_entry_single(soc, type, devid, id, hwid, size)
 
+#ifdef CONFIG_SOC_IMX1
+const struct imx_spi_imx_data imx1_cspi_data[] __initconst = {
+#define imx1_cspi_data_entry(_id, _hwid) \
+	imx_spi_imx_data_entry(MX1, CSPI, "imx1-cspi", _id, _hwid, SZ_4K)
+	imx1_cspi_data_entry(0, 1),
+	imx1_cspi_data_entry(1, 2),
+};
+#endif
+
 #ifdef CONFIG_SOC_IMX21
 const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
 #define imx21_cspi_data_entry(_id, _hwid)                            \
diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
deleted file mode 100644
index 8772ce3..0000000
--- a/arch/arm/plat-mxc/ehci.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 Freescale Semiconductor, Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT 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/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
-
-#define USBCTRL_OTGBASE_OFFSET	0x600
-
-#define MX31_OTG_SIC_SHIFT	29
-#define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT)
-#define MX31_OTG_PM_BIT		(1 << 24)
-
-#define MX31_H2_SIC_SHIFT	21
-#define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT)
-#define MX31_H2_PM_BIT		(1 << 16)
-#define MX31_H2_DT_BIT		(1 << 5)
-
-#define MX31_H1_SIC_SHIFT	13
-#define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT)
-#define MX31_H1_PM_BIT		(1 << 8)
-#define MX31_H1_DT_BIT		(1 << 4)
-
-#define MX35_OTG_SIC_SHIFT	29
-#define MX35_OTG_SIC_MASK	(0x3 << MX35_OTG_SIC_SHIFT)
-#define MX35_OTG_PM_BIT		(1 << 24)
-
-#define MX35_H1_SIC_SHIFT	21
-#define MX35_H1_SIC_MASK	(0x3 << MX35_H1_SIC_SHIFT)
-#define MX35_H1_PM_BIT		(1 << 8)
-#define MX35_H1_IPPUE_UP_BIT	(1 << 7)
-#define MX35_H1_IPPUE_DOWN_BIT	(1 << 6)
-#define MX35_H1_TLL_BIT		(1 << 5)
-#define MX35_H1_USBTE_BIT	(1 << 4)
-
-#define MXC_OTG_OFFSET		0
-#define MXC_H1_OFFSET		0x200
-#define MXC_H2_OFFSET		0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)		/* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_DIS_BIT			(1 << 5)	/* UH1 Disable Overcurrent Event */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
-
-#define MXC_USBCMD_OFFSET			0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
-
-int mxc_initialize_usb_hw(int port, unsigned int flags)
-{
-	unsigned int v;
-#if defined(CONFIG_SOC_IMX25)
-	if (cpu_is_mx25()) {
-		v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX35_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_OTG_PM_BIT;
-
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX35_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX35_H1_TLL_BIT;
-
-			if (flags & MXC_EHCI_INTERNAL_PHY)
-				v |= MX35_H1_USBTE_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_DOWN)
-				v |= MX35_H1_IPPUE_DOWN_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_UP)
-				v |= MX35_H1_IPPUE_UP_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-#endif /* if defined(CONFIG_SOC_IMX25) */
-#if defined(CONFIG_ARCH_MX3)
-	if (cpu_is_mx31()) {
-		v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX31_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_OTG_PM_BIT;
-
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H1_DT_BIT;
-
-			break;
-		case 2:	/* H2 port */
-			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H2_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H2_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H2_DT_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-
-	if (cpu_is_mx35()) {
-		v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX35_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_OTG_PM_BIT;
-
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX35_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX35_H1_TLL_BIT;
-
-			if (flags & MXC_EHCI_INTERNAL_PHY)
-				v |= MX35_H1_USBTE_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_DOWN)
-				v |= MX35_H1_IPPUE_DOWN_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_UP)
-				v |= MX35_H1_IPPUE_UP_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-#endif /* CONFIG_ARCH_MX3 */
-#ifdef CONFIG_MACH_MX27
-	if (cpu_is_mx27()) {
-		/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
-		 * are identical
-		 */
-		v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX31_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_OTG_PM_BIT;
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H1_DT_BIT;
-
-			break;
-		case 2:	/* H2 port */
-			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H2_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H2_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H2_DT_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-		writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-#endif /* CONFIG_MACH_MX27 */
-#ifdef CONFIG_SOC_IMX51
-	if (cpu_is_mx51()) {
-		void __iomem *usb_base;
-		void __iomem *usbotg_base;
-		void __iomem *usbother_base;
-		int ret = 0;
-
-		usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
-		if (!usb_base) {
-			printk(KERN_ERR "%s(): ioremap failed\n", __func__);
-			return -ENOMEM;
-		}
-
-		switch (port) {
-		case 0:	/* OTG port */
-			usbotg_base = usb_base + MXC_OTG_OFFSET;
-			break;
-		case 1:	/* Host 1 port */
-			usbotg_base = usb_base + MXC_H1_OFFSET;
-			break;
-		case 2: /* Host 2 port */
-			usbotg_base = usb_base + MXC_H2_OFFSET;
-			break;
-		default:
-			printk(KERN_ERR"%s no such port %d\n", __func__, port);
-			ret = -ENOENT;
-			goto error;
-		}
-		usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-		switch (port) {
-		case 0:	/*OTG port */
-			if (flags & MXC_EHCI_INTERNAL_PHY) {
-				v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-				if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-					/* OC/USBPWR is not used */
-					v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-				} else {
-					/* OC/USBPWR is used */
-					v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
-				}
-				__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-				v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-				if (flags & MXC_EHCI_WAKEUP_ENABLED)
-					v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
-				else
-					v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
-				if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-					v |= MXC_OTG_UCTRL_OPM_BIT;
-				else
-					v &= ~MXC_OTG_UCTRL_OPM_BIT;
-				__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-			}
-			break;
-		case 1:	/* Host 1 */
-			/*Host ULPI */
-			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-				/* HOST1 wakeup/ULPI intr enable */
-				v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-			} else {
-				/* HOST1 wakeup/ULPI intr disable */
-				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-			}
-
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-			else
-				v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
-			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
-			else
-				v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
-			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-			v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
-			if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
-				/* Interrupt Threshold Control:Immediate (no threshold) */
-				v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
-			__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
-			break;
-		case 2: /* Host 2 ULPI */
-			v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-				/* HOST1 wakeup/ULPI intr enable */
-				v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-			} else {
-				/* HOST1 wakeup/ULPI intr disable */
-				v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-			}
-
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-			else
-				v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-			__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
-			break;
-		}
-
-error:
-		iounmap(usb_base);
-		return ret;
-	}
-#endif
-	printk(KERN_WARNING
-		"%s() unable to setup USBCONTROL for this CPU\n", __func__);
-	return -EINVAL;
-}
-EXPORT_SYMBOL(mxc_initialize_usb_hw);
-
diff --git a/arch/arm/plat-mxc/gpio.c b/arch/arm/plat-mxc/gpio.c
index d17b3c9..57d5985 100644
--- a/arch/arm/plat-mxc/gpio.c
+++ b/arch/arm/plat-mxc/gpio.c
@@ -233,6 +233,7 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
 }
 
 static struct irq_chip gpio_irq_chip = {
+	.name = "GPIO",
 	.irq_ack = gpio_ack_irq,
 	.irq_mask = gpio_mask_irq,
 	.irq_unmask = gpio_unmask_irq,
@@ -349,113 +350,3 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 
 	return 0;
 }
-
-#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\
-	{								\
-		.chip.label = "gpio-" #_id,				\
-		.irq = _irq,						\
-		.irq_high = _irq_high,					\
-		.base = soc ## _IO_ADDRESS(				\
-				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\
-		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\
-	}
-
-#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
-#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\
-	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
-
-#define DEFINE_REGISTER_FUNCTION(prefix)				\
-int __init prefix ## _register_gpios(void)				\
-{									\
-	return mxc_gpio_init(prefix ## _gpio_ports,			\
-			ARRAY_SIZE(prefix ## _gpio_ports));		\
-}
-
-#if defined(CONFIG_SOC_IMX1)
-static struct mxc_gpio_port imx1_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
-};
-
-DEFINE_REGISTER_FUNCTION(imx1)
-
-#endif /* if defined(CONFIG_SOC_IMX1) */
-
-#if defined(CONFIG_SOC_IMX21)
-static struct mxc_gpio_port imx21_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
-	DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
-	DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
-	DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
-	DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
-	DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
-};
-
-DEFINE_REGISTER_FUNCTION(imx21)
-
-#endif /* if defined(CONFIG_SOC_IMX21) */
-
-#if defined(CONFIG_SOC_IMX25)
-static struct mxc_gpio_port imx25_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
-};
-
-DEFINE_REGISTER_FUNCTION(imx25)
-
-#endif /* if defined(CONFIG_SOC_IMX25) */
-
-#if defined(CONFIG_SOC_IMX27)
-static struct mxc_gpio_port imx27_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
-	DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
-	DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
-	DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
-	DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
-	DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
-};
-
-DEFINE_REGISTER_FUNCTION(imx27)
-
-#endif /* if defined(CONFIG_SOC_IMX27) */
-
-#if defined(CONFIG_SOC_IMX31)
-static struct mxc_gpio_port imx31_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
-};
-
-DEFINE_REGISTER_FUNCTION(imx31)
-
-#endif /* if defined(CONFIG_SOC_IMX31) */
-
-#if defined(CONFIG_SOC_IMX35)
-static struct mxc_gpio_port imx35_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
-};
-
-DEFINE_REGISTER_FUNCTION(imx35)
-
-#endif /* if defined(CONFIG_SOC_IMX35) */
-
-#if defined(CONFIG_SOC_IMX50)
-static struct mxc_gpio_port imx50_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-};
-
-DEFINE_REGISTER_FUNCTION(imx50)
-
-#endif /* if defined(CONFIG_SOC_IMX50) */
diff --git a/arch/arm/plat-mxc/include/mach/common.h b/arch/arm/plat-mxc/include/mach/common.h
index aea2cd3..a22ebe1 100644
--- a/arch/arm/plat-mxc/include/mach/common.h
+++ b/arch/arm/plat-mxc/include/mach/common.h
@@ -24,6 +24,16 @@ extern void mx50_map_io(void);
 extern void mx51_map_io(void);
 extern void mx53_map_io(void);
 extern void mxc91231_map_io(void);
+extern void imx1_init_early(void);
+extern void imx21_init_early(void);
+extern void imx25_init_early(void);
+extern void imx27_init_early(void);
+extern void imx31_init_early(void);
+extern void imx35_init_early(void);
+extern void imx50_init_early(void);
+extern void imx51_init_early(void);
+extern void imx53_init_early(void);
+extern void mxc91231_init_early(void);
 extern void mxc_init_irq(void __iomem *);
 extern void tzic_init_irq(void __iomem *);
 extern void mx1_init_irq(void);
diff --git a/arch/arm/plat-mxc/include/mach/esdhc.h b/arch/arm/plat-mxc/include/mach/esdhc.h
index a48a9aa..86003f4 100644
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ b/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -10,7 +10,17 @@
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio:	gpio for write_protect (-EINVAL if unused)
+ * @cd_gpio:	gpio for card_detect interrupt (-EINVAL if unused)
+ */
+
 struct esdhc_platform_data {
-	unsigned int wp_gpio;	/* write protect pin */
+	unsigned int wp_gpio;
+	unsigned int cd_gpio;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
diff --git a/arch/arm/plat-mxc/include/mach/gpio.h b/arch/arm/plat-mxc/include/mach/gpio.h
index 0044e2f..a2747f1 100644
--- a/arch/arm/plat-mxc/include/mach/gpio.h
+++ b/arch/arm/plat-mxc/include/mach/gpio.h
@@ -46,6 +46,21 @@ struct mxc_gpio_port {
 	spinlock_t lock;
 };
 
+#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\
+	{								\
+		.chip.label = "gpio-" #_id,				\
+		.irq = _irq,						\
+		.irq_high = _irq_high,					\
+		.base = soc ## _IO_ADDRESS(				\
+				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\
+		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\
+	}
+
+#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
+#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\
+	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
+
 int mxc_gpio_init(struct mxc_gpio_port*, int);
 
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx3.h b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
index cbaed29..c92f0b1 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx3.h
@@ -112,12 +112,12 @@ enum iomux_gp_func {
  * 	- setups the iomux according to the configuration
  * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
  */
-int mxc_iomux_alloc_pin(const unsigned int pin, const char *label);
+int mxc_iomux_alloc_pin(unsigned int pin, const char *label);
 /*
  * setups mutliple pins
  * convenient way to call the above function with tables
  */
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label);
 
 /*
@@ -126,12 +126,12 @@ int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
  * 	- frees the GPIO if the pin was configured as GPIO
  * 	- DOES NOT reconfigure the IOMUX in its reset state
  */
-void mxc_iomux_release_pin(const unsigned int pin);
+void mxc_iomux_release_pin(unsigned int pin);
 /*
  * releases multiple pins
  * convenvient way to call the above function with tables
  */
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count);
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
 
 /*
  * This function enables/disables the general purpose function for a particular
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx35.h b/arch/arm/plat-mxc/include/mach/iomux-mx35.h
index 2a24bae..3117c18 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx35.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx35.h
@@ -989,13 +989,13 @@
 #define MX35_PAD_ATA_DATA2__IPU_DIAGB_9				IOMUX_PAD(0x6e8, 0x284, 6, 0x0,   0, NO_PAD_CTRL)
 #define MX35_PAD_ATA_DATA2__ARM11P_TOP_TRACE_28			IOMUX_PAD(0x6e8, 0x284, 7, 0x0,   0, NO_PAD_CTRL)
 
-#define MX35_PAD_ATA_DATA3__ATA_DATA_3				IOMUX_PAD(0x6e8, 0x288, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				IOMUX_PAD(0x6e8, 0x288, 1, 0x814, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		IOMUX_PAD(0x6e8, 0x288, 2, 0x9b8, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				IOMUX_PAD(0x6e8, 0x288, 4, 0x7e0, 2, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__GPIO2_16				IOMUX_PAD(0x6e8, 0x288, 5, 0x884, 1, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			IOMUX_PAD(0x6e8, 0x288, 6, 0x0,   0, NO_PAD_CTRL)
-#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			IOMUX_PAD(0x6e8, 0x288, 7, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ATA_DATA_3				IOMUX_PAD(0x6ec, 0x288, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				IOMUX_PAD(0x6ec, 0x288, 1, 0x814, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		IOMUX_PAD(0x6ec, 0x288, 2, 0x9b8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				IOMUX_PAD(0x6ec, 0x288, 4, 0x7e0, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__GPIO2_16				IOMUX_PAD(0x6ec, 0x288, 5, 0x884, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			IOMUX_PAD(0x6ec, 0x288, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			IOMUX_PAD(0x6ec, 0x288, 7, 0x0,   0, NO_PAD_CTRL)
 
 #define MX35_PAD_ATA_DATA4__ATA_DATA_4				IOMUX_PAD(0x6f0, 0x28c, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX35_PAD_ATA_DATA4__ESDHC3_CMD				IOMUX_PAD(0x6f0, 0x28c, 1, 0x818, 1, NO_PAD_CTRL)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx50.h b/arch/arm/plat-mxc/include/mach/iomux-mx50.h
index 058a922..98e7fd0 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx50.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx50.h
@@ -86,7 +86,7 @@
 #define MX50_PAD_I2C1_SCL__I2C1_SCL	IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \
 							MX50_I2C_PAD_CTRL)
 #define MX50_PAD_I2C1_SCL__GPIO_6_18	IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x7cc, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 
 #define MX50_PAD_I2C1_SDA__I2C1_SDA	IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \
 							MX50_I2C_PAD_CTRL)
@@ -96,7 +96,7 @@
 #define MX50_PAD_I2C2_SCL__I2C2_SCL	IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \
 							MX50_I2C_PAD_CTRL)
 #define MX50_PAD_I2C2_SCL__GPIO_6_20	IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x7c8, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_I2C2_SCL__DCDC_OK	IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL)
 
 #define MX50_PAD_I2C2_SDA__I2C2_SDA	IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \
@@ -172,7 +172,7 @@
 
 #define MX50_PAD_SSI_RXFS__AUD3_RXFS	IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_SSI_RXFS__GPIO_6_4	IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x7e4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_SSI_RXFS__WEIM_D6	IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL)
 #define MX50_PAD_SSI_RXFS__CSPI_SS2	IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD)
 #define MX50_PAD_SSI_RXFS__FEC_COL	IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH)
@@ -186,25 +186,25 @@
 #define MX50_PAD_SSI_RXC__FEC_RX_CLK	IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL)
 #define MX50_PAD_SSI_RXC__FEC_MDIO	IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL)
 
-#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x7c4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_TXD__GPIO_6_6	IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL)
 
 #define MX50_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_RXD__GPIO_6_7	IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL)
 
-#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x7c0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_CTS__GPIO_6_8	IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x7e4, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_CTS__SD4_D4	IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART1_CTS__SD4_CMD	IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL)
 
 #define MX50_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_RTS__GPIO_6_9	IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART1_RTS__UART5_RXD	IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x0, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x0, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x764, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x748, 0, MX50_SD_PAD_CTRL)
 
-#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x7cc, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART2_TXD__GPIO_6_10	IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART2_TXD__SD4_D6	IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_TXD__SD4_D4	IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL)
@@ -214,7 +214,7 @@
 #define MX50_PAD_UART2_RXD__SD4_D7	IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_RXD__SD4_D5	IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL)
 
-#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x7c8, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART2_CTS__GPIO_6_12	IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART2_CTS__SD4_CMD	IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_CTS__SD4_D6	IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL)
@@ -224,7 +224,7 @@
 #define MX50_PAD_UART2_RTS__SD4_CLK	IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_RTS__SD4_D7	IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL)
 
-#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x7d4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART3_TXD__GPIO_6_14	IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART3_TXD__SD1_D4	IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART3_TXD__SD4_D0	IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL)
@@ -238,9 +238,9 @@
 #define MX50_PAD_UART3_RXD__SD2_CD	IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART3_RXD__WEIM_D13	IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL)
 
-#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x7dc, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__GPIO_6_16	IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x7d0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__SD1_D6	IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__SD4_D2	IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__SD2_LCTL	IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL)
@@ -278,7 +278,7 @@
 #define MX50_PAD_ECSPI1_MOSI__GPIO_4_13		IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI1_MOSI__CSPI_SS1		IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD)
 #define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1	IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x7d0, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7	IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI1_MOSI__WEIM_D9		IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL)
 
@@ -294,7 +294,7 @@
 #define MX50_PAD_ECSPI1_SS0__GPIO_4_15		IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
 #define MX50_PAD_ECSPI1_SS0__CSPI_SS3		IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD)
 #define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3		IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x7d8, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9		IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI1_SS0__WEIM_D11		IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL)
 
@@ -311,17 +311,17 @@
 #define MX50_PAD_ECSPI2_MOSI__GPIO_4_17		IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD		IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1	IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x7e0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN		IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5	IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__WEIM_D9		IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL)
 
-#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x73c, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__GPIO_4_18		IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
 #define MX50_PAD_ECSPI2_MISO__ELCDIF_RS		IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2	IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x7e4, 4, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x73c, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__NANDF_CEN6	IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__WEIM_D10		IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL)
 
@@ -503,7 +503,7 @@
 #define MX50_PAD_DISP_RD__ELCDIF_EN	IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
 #define MX50_PAD_DISP_RD__WEIM_A25	IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
 
-#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
 #define MX50_PAD_DISP_RS__GPIO_2_17	IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_DISP_RS__ELCDIF_VSYNC	IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
 #define MX50_PAD_DISP_RS__WEIM_A26	IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
@@ -691,8 +691,8 @@
 
 #define MX50_PAD_EPDC_D9__EPDC_D9	IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_EPDC_D9__GPIO_3_9	IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x810, 2, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x810, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
 
 #define MX50_PAD_EPDC_D10__EPDC_D10	IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_EPDC_D10__GPIO_3_10	IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index b6767f9..df6acc0 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -473,7 +473,7 @@
 #define _MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x09ec, 2, 0)
 #define _MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, 0x0000, 0, 0)
 #define _MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x09ec, 3, 0)
+#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, 0x0000, 0, 0)
@@ -528,7 +528,7 @@
 #define _MX51_PAD_USBH1_DATA1__UART2_RXD	IOMUX_PAD(0x68c, 0x28c, 1, 0x09ec, 4, 0)
 #define _MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
+#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA3__UART2_RTS	IOMUX_PAD(0x694, 0x294, 1, 0x09e8, 5, 0)
@@ -985,11 +985,11 @@
 #define MX51_PAD_NANDF_WE_B__GPIO3_3		(_MX51_PAD_NANDF_WE_B__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_WE_B__NANDF_WE_B		(_MX51_PAD_NANDF_WE_B__NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_WE_B__PATA_DIOW		(_MX51_PAD_NANDF_WE_B__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0		(_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0		(_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RE_B__GPIO3_4		(_MX51_PAD_NANDF_RE_B__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RE_B__NANDF_RE_B		(_MX51_PAD_NANDF_RE_B__NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RE_B__PATA_DIOR		(_MX51_PAD_NANDF_RE_B__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1		(_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1		(_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_ALE__GPIO3_5		(_MX51_PAD_NANDF_ALE__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_ALE__NANDF_ALE		(_MX51_PAD_NANDF_ALE__NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	(_MX51_PAD_NANDF_ALE__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -999,18 +999,18 @@
 #define MX51_PAD_NANDF_WP_B__GPIO3_7		(_MX51_PAD_NANDF_WP_B__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_WP_B__NANDF_WP_B		(_MX51_PAD_NANDF_WP_B__NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_WP_B__PATA_DMACK		(_MX51_PAD_NANDF_WP_B__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2		(_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2		(_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__ECSPI2_SS1		(_MX51_PAD_NANDF_RB0__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__GPIO3_8		(_MX51_PAD_NANDF_RB0__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__NANDF_RB0		(_MX51_PAD_NANDF_RB0__NANDF_RB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__PATA_DMARQ		(_MX51_PAD_NANDF_RB0__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__SD3_DATA3		(_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RB0__SD3_DATA3		(_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__CSPI_MOSI		(_MX51_PAD_NANDF_RB1__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__ECSPI2_RDY		(_MX51_PAD_NANDF_RB1__ECSPI2_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__GPIO3_9		(_MX51_PAD_NANDF_RB1__GPIO3_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__NANDF_RB1		(_MX51_PAD_NANDF_RB1__NANDF_RB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__PATA_IORDY		(_MX51_PAD_NANDF_RB1__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__SD4_CMD		(_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RB1__SD4_CMD		(_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB2__DISP2_WAIT		(_MX51_PAD_NANDF_RB2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		(_MX51_PAD_NANDF_RB2__ECSPI2_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB2__FEC_COL		(_MX51_PAD_NANDF_RB2__FEC_COL | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
@@ -1036,41 +1036,41 @@
 #define MX51_PAD_NANDF_CS2__GPIO3_18		(_MX51_PAD_NANDF_CS2__GPIO3_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS2__NANDF_CS2		(_MX51_PAD_NANDF_CS2__NANDF_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS2__PATA_CS_0		(_MX51_PAD_NANDF_CS2__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__SD4_CLK		(_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS2__SD4_CLK		(_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_NANDF_CS2__USBH3_H1_DP		(_MX51_PAD_NANDF_CS2__USBH3_H1_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__FEC_MDC		(_MX51_PAD_NANDF_CS3__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS3__GPIO3_19		(_MX51_PAD_NANDF_CS3__GPIO3_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__NANDF_CS3		(_MX51_PAD_NANDF_CS3__NANDF_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__PATA_CS_1		(_MX51_PAD_NANDF_CS3__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__SD4_DAT0		(_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS3__SD4_DAT0		(_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__USBH3_H1_DM		(_MX51_PAD_NANDF_CS3__USBH3_H1_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__FEC_TDATA1		(_MX51_PAD_NANDF_CS4__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS4__GPIO3_20		(_MX51_PAD_NANDF_CS4__GPIO3_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__NANDF_CS4		(_MX51_PAD_NANDF_CS4__NANDF_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__PATA_DA_0		(_MX51_PAD_NANDF_CS4__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__SD4_DAT1		(_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS4__SD4_DAT1		(_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__USBH3_STP		(_MX51_PAD_NANDF_CS4__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__FEC_TDATA2		(_MX51_PAD_NANDF_CS5__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS5__GPIO3_21		(_MX51_PAD_NANDF_CS5__GPIO3_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__NANDF_CS5		(_MX51_PAD_NANDF_CS5__NANDF_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__PATA_DA_1		(_MX51_PAD_NANDF_CS5__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__SD4_DAT2		(_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS5__SD4_DAT2		(_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__USBH3_DIR		(_MX51_PAD_NANDF_CS5__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__CSPI_SS3		(_MX51_PAD_NANDF_CS6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__FEC_TDATA3		(_MX51_PAD_NANDF_CS6__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS6__GPIO3_22		(_MX51_PAD_NANDF_CS6__GPIO3_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__NANDF_CS6		(_MX51_PAD_NANDF_CS6__NANDF_CS6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__PATA_DA_2		(_MX51_PAD_NANDF_CS6__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__SD4_DAT3		(_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS6__SD4_DAT3		(_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS7__FEC_TX_EN		(_MX51_PAD_NANDF_CS7__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS7__GPIO3_23		(_MX51_PAD_NANDF_CS7__GPIO3_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS7__NANDF_CS7		(_MX51_PAD_NANDF_CS7__NANDF_CS7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__SD3_CLK		(_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS7__SD3_CLK		(_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	(_MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	(_MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
 #define MX51_PAD_NANDF_RDY_INT__GPIO3_24	(_MX51_PAD_NANDF_RDY_INT__GPIO3_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	(_MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		(_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		(_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_D15__ECSPI2_MOSI		(_MX51_PAD_NANDF_D15__ECSPI2_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_D15__GPIO3_25		(_MX51_PAD_NANDF_D15__GPIO3_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_D15__NANDF_D15		(_MX51_PAD_NANDF_D15__NANDF_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1479,26 +1479,26 @@
 #define MX51_PAD_SD1_CLK__SD1_CLK		(_MX51_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_SD1_DATA0__AUD5_TXD		(_MX51_PAD_SD1_DATA0__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA0__CSPI_MISO		(_MX51_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		(_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		(_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_EIM_DA0__EIM_DA0		(_MX51_PAD_EIM_DA0__EIM_DA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA1__EIM_DA1		(_MX51_PAD_EIM_DA1__EIM_DA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA2__EIM_DA2		(_MX51_PAD_EIM_DA2__EIM_DA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA3__EIM_DA3		(_MX51_PAD_EIM_DA3__EIM_DA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA1__AUD5_RXD		(_MX51_PAD_SD1_DATA1__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		(_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		(_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_EIM_DA4__EIM_DA4		(_MX51_PAD_EIM_DA4__EIM_DA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA5__EIM_DA5		(_MX51_PAD_EIM_DA5__EIM_DA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA6__EIM_DA6		(_MX51_PAD_EIM_DA6__EIM_DA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA7__EIM_DA7		(_MX51_PAD_EIM_DA7__EIM_DA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA2__AUD5_TXC		(_MX51_PAD_SD1_DATA2__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		(_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		(_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_EIM_DA10__EIM_DA10		(_MX51_PAD_EIM_DA10__EIM_DA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA11__EIM_DA11		(_MX51_PAD_EIM_DA11__EIM_DA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA8__EIM_DA8		(_MX51_PAD_EIM_DA8__EIM_DA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA9__EIM_DA9		(_MX51_PAD_EIM_DA9__EIM_DA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA3__AUD5_TXFS		(_MX51_PAD_SD1_DATA3__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA3__CSPI_SS1		(_MX51_PAD_SD1_DATA3__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		(_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		(_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_GPIO1_0__CSPI_SS2		(_MX51_PAD_GPIO1_0__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_GPIO1_0__GPIO1_0		(_MX51_PAD_GPIO1_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_GPIO1_0__SD1_CD		(_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
@@ -1517,16 +1517,16 @@
 #define MX51_PAD_SD2_CLK__SD2_CLK		(_MX51_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_SD2_DATA0__CSPI_MISO		(_MX51_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA0__SD1_DAT4		(_MX51_PAD_SD2_DATA0__SD1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		(_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		(_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA1__SD1_DAT5		(_MX51_PAD_SD2_DATA1__SD1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		(_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		(_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA1__USBH3_H2_DP		(_MX51_PAD_SD2_DATA1__USBH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD2_DATA2__SD1_DAT6		(_MX51_PAD_SD2_DATA2__SD1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		(_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		(_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA2__USBH3_H2_DM		(_MX51_PAD_SD2_DATA2__USBH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD2_DATA3__CSPI_SS2		(_MX51_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA3__SD1_DAT7		(_MX51_PAD_SD2_DATA3__SD1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		(_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		(_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_GPIO1_2__CCM_OUT_2		(_MX51_PAD_GPIO1_2__CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_GPIO1_2__GPIO1_2		(_MX51_PAD_GPIO1_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_GPIO1_2__I2C2_SCL		(_MX51_PAD_GPIO1_2__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx53.h b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
index 68e11d7..e95d9cb 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx53.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx53.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,305 +21,2358 @@
 
 #include <mach/iomux-v3.h>
 
-/*
- * various IOMUX alternate output functions (1-7)
- */
-typedef enum iomux_config {
-	IOMUX_CONFIG_ALT0,
-	IOMUX_CONFIG_ALT1,
-	IOMUX_CONFIG_ALT2,
-	IOMUX_CONFIG_ALT3,
-	IOMUX_CONFIG_ALT4,
-	IOMUX_CONFIG_ALT5,
-	IOMUX_CONFIG_ALT6,
-	IOMUX_CONFIG_ALT7,
-	IOMUX_CONFIG_GPIO, /* added to help user use GPIO mode */
-} iomux_pin_cfg_t;
-
 /* These 2 defines are for pins that may not have a mux register, but could
  * have a pad setting register, and vice-versa. */
-#define NON_MUX_I	0x00
 #define NON_PAD_I	0x00
 
 #define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
 		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
-/* UART1 */
-#define MX53_PAD_CSI0_D10__UART1_TXD	IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_D11__UART1_RXD	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DIOW__UART1_TXD	IOMUX_PAD(0x5F0, 0x270, 3, 0x0,	0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DMACK__UART1_RXD	IOMUX_PAD(0x5F4, 0x274, 3, 0x880, 3, MX53_UART_PAD_CTRL)
-
-/* UART2 */
-#define MX53_PAD_ATA_BUFFER_EN__UART2_RXD	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DMARQ__UART2_TXD	IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DIOR__UART2_RTS	IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_INTRQ__UART2_CTS	IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, MX53_UART_PAD_CTRL)
+#define MX53_SDHC_PAD_CTRL 	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+				PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_SRE_FAST)
 
-/* UART3 */
-#define MX53_PAD_ATA_CS_0__UART3_TXD	IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_CS_1__UART3_RXD	IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DA_1__UART3_CTS	IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DA_2__UART3_RTS	IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+#define _MX53_PAD_GPIO_19__KPP_COL_5		IOMUX_PAD(0x348, 0x20, 0, 0x840, 0, 0)
+#define _MX53_PAD_GPIO_19__GPIO4_5		IOMUX_PAD(0x348, 0x20, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__CCM_CLKO		IOMUX_PAD(0x348, 0x20, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__SPDIF_OUT1	IOMUX_PAD(0x348, 0x20, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2	IOMUX_PAD(0x348, 0x20, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__ECSPI1_RDY	IOMUX_PAD(0x348, 0x20, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__FEC_TDATA_3	IOMUX_PAD(0x348, 0x20, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__SRC_INT_BOOT	IOMUX_PAD(0x348, 0x20,7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__KPP_COL_0	IOMUX_PAD(0x34C, 0x24, o, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__GPIO4_6		IOMUX_PAD(0x34C, 0x24, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	IOMUX_PAD(0x34C, 0x24, 2, 0x758, 0, 0)
+#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX	IOMUX_PAD(0x34C, 0x24, 4, 0x890, 0, 0)
+#define _MX53_PAD_KEY_COL0__ECSPI1_SCLK	IOMUX_PAD(0x34C, 0x24, 5, 0x79C, 0, 0)
+#define _MX53_PAD_KEY_COL0__FEC_RDATA_3	IOMUX_PAD(0x34C, 0x24, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__SRC_ANY_PU_RST	IOMUX_PAD(0x34C, 0x24, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW0__KPP_ROW_0	IOMUX_PAD(0x350, 0x28, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW0__GPIO4_7		IOMUX_PAD(0x350, 0x28, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	IOMUX_PAD(0x350, 0x28, 2, 0x74C, 0, 0)
+#define _MX53_PAD_KEY_ROW0__UART4_RXD_MUX	IOMUX_PAD(0x350, 0x28, 4, 0x890, 1, 0)
+#define _MX53_PAD_KEY_ROW0__ECSPI1_MOSI	IOMUX_PAD(0x350, 0x28, 5, 0x7A4, 0, 0)
+#define _MX53_PAD_KEY_ROW0__FEC_TX_ER	IOMUX_PAD(0x350, 0x28, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL1__KPP_COL_1	IOMUX_PAD(0x354, 0x2C, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL1__GPIO4_8		IOMUX_PAD(0x354, 0x2C, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x354, 0x2C, 2, 0x75C, 0, 0)
+#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX	IOMUX_PAD(0x354, 0x2C, 4, 0x898, 0, 0)
+#define _MX53_PAD_KEY_COL1__ECSPI1_MISO	IOMUX_PAD(0x354, 0x2C, 5, 0x7A0, 0, 0)
+#define _MX53_PAD_KEY_COL1__FEC_RX_CLK	IOMUX_PAD(0x354, 0x2C, 6, 0x808, 0, 0)
+#define _MX53_PAD_KEY_COL1__USBPHY1_TXREADY	IOMUX_PAD(0x354, 0x2C, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW1__KPP_ROW_1	IOMUX_PAD(0x358, 0x30, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW1__GPIO4_9		IOMUX_PAD(0x358, 0x30, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	IOMUX_PAD(0x358, 0x30, 2, 0x748, 0, 0)
+#define _MX53_PAD_KEY_ROW1__UART5_RXD_MUX	IOMUX_PAD(0x358, 0x30, 4, 0x898, 1, 0)
+#define _MX53_PAD_KEY_ROW1__ECSPI1_SS0	IOMUX_PAD(0x358, 0x30, 5, 0x7A8, 0, 0)
+#define _MX53_PAD_KEY_ROW1__FEC_COL		IOMUX_PAD(0x358, 0x30, 6, 0x800, 0, 0)
+#define _MX53_PAD_KEY_ROW1__USBPHY1_RXVALID	IOMUX_PAD(0x358, 0x30, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__KPP_COL_2	IOMUX_PAD(0x35C, 0x34, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__GPIO4_10		IOMUX_PAD(0x35C, 0x34, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__CAN1_TXCAN	IOMUX_PAD(0x35C, 0x34, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__FEC_MDIO		IOMUX_PAD(0x35C, 0x34, 4, 0x804, 0, 0)
+#define _MX53_PAD_KEY_COL2__ECSPI1_SS1	IOMUX_PAD(0x35C, 0x34, 5, 0x7AC, 0, 0)
+#define _MX53_PAD_KEY_COL2__FEC_RDATA_2	IOMUX_PAD(0x35C, 0x34, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE	IOMUX_PAD(0x35C, 0x34, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__KPP_ROW_2	IOMUX_PAD(0x360, 0x38, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__GPIO4_11	IOMUX_PAD(0x360, 0x38, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__CAN1_RXCAN	IOMUX_PAD(0x360, 0x38, 2, 0x760, 0, 0)
+#define _MX53_PAD_KEY_ROW2__FEC_MDC		IOMUX_PAD(0x360, 0x38, 4, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__ECSPI1_SS2	IOMUX_PAD(0x360, 0x38, 5, 0x7B0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__FEC_TDATA_2	IOMUX_PAD(0x360, 0x38, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__USBPHY1_RXERROR	IOMUX_PAD(0x360, 0x38, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__KPP_COL_3	IOMUX_PAD(0x364, 0x3C, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__GPIO4_12		IOMUX_PAD(0x364, 0x3C, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__USBOH3_H2_DP	IOMUX_PAD(0x364, 0x3C, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__SPDIF_IN1	IOMUX_PAD(0x364, 0x3C, 3, 0x870, 0, 0)
+#define _MX53_PAD_KEY_COL3__I2C2_SCL		IOMUX_PAD(0x364, 0x3C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, 0)
+#define _MX53_PAD_KEY_COL3__ECSPI1_SS3	IOMUX_PAD(0x364, 0x3C, 5, 0x7B4, 0, 0)
+#define _MX53_PAD_KEY_COL3__FEC_CRS		IOMUX_PAD(0x364, 0x3C, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK	IOMUX_PAD(0x364, 0x3C, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__KPP_ROW_3	IOMUX_PAD(0x368, 0x40, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__GPIO4_13	IOMUX_PAD(0x368, 0x40, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__USBOH3_H2_DM	IOMUX_PAD(0x368, 0x40, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x368, 0x40, 3, 0x768, 0, 0)
+#define _MX53_PAD_KEY_ROW3__I2C2_SDA	IOMUX_PAD(0x368, 0x40, 4 | IOMUX_CONFIG_SION, 0x820, 0, 0)
+#define _MX53_PAD_KEY_ROW3__OSC32K_32K_OUT	IOMUX_PAD(0x368, 0x40, 5, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__CCM_PLL4_BYP	IOMUX_PAD(0x368, 0x40, 6, 0x77C, 0, 0)
+#define _MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0	IOMUX_PAD(0x368, 0x40, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__KPP_COL_4	IOMUX_PAD(0x36C, 0x44, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__GPIO4_14		IOMUX_PAD(0x36C, 0x44, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__CAN2_TXCAN	IOMUX_PAD(0x36C, 0x44, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__IPU_SISG_4	IOMUX_PAD(0x36C, 0x44, 3, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__UART5_RTS	IOMUX_PAD(0x36C, 0x44, 4, 0x894, 0, 0)
+#define _MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC	IOMUX_PAD(0x36C, 0x44, 5, 0x89C, 0, 0)
+#define _MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1	IOMUX_PAD(0x36C, 0x44, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__KPP_ROW_4	IOMUX_PAD(0x370, 0x48, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__GPIO4_15	IOMUX_PAD(0x370, 0x48, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__CAN2_RXCAN	IOMUX_PAD(0x370, 0x48, 2, 0x764, 0, 0)
+#define _MX53_PAD_KEY_ROW4__IPU_SISG_5	IOMUX_PAD(0x370, 0x48, 3, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__UART5_CTS	IOMUX_PAD(0x370, 0x48, 4, 0x894, 1, 0)
+#define _MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR	IOMUX_PAD(0x370, 0x48, 5, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID	IOMUX_PAD(0x370, 0x48, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	IOMUX_PAD(0x378, 0x4C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__GPIO4_16		IOMUX_PAD(0x378, 0x4C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR	IOMUX_PAD(0x378, 0x4C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x4C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0	IOMUX_PAD(0x378, 0x4C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID	IOMUX_PAD(0x378, 0x4C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x50, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__GPIO4_17		IOMUX_PAD(0x37C, 0x50, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC	IOMUX_PAD(0x37C, 0x50, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x50, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1	IOMUX_PAD(0x37C, 0x50, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x50, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		IOMUX_PAD(0x380, 0x54, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x54, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD	IOMUX_PAD(0x380, 0x54, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x54, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x54, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION	IOMUX_PAD(0x380, 0x54, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		IOMUX_PAD(0x384, 0x58, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x58, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS	IOMUX_PAD(0x384, 0x58, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x58, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x58, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x58, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		IOMUX_PAD(0x388, 0x5C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x5C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD	IOMUX_PAD(0x388, 0x5C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__ESDHC1_WP		IOMUX_PAD(0x388, 0x5C, 3, 0x7FC, 0, 0)
+#define _MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD	IOMUX_PAD(0x388, 0x5C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x5C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x5C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0	IOMUX_PAD(0x38C, 0x60, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__GPIO4_21		IOMUX_PAD(0x38C, 0x60, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__CSPI_SCLK		IOMUX_PAD(0x38C, 0x60, 2, 0x780, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x60, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x60, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5	IOMUX_PAD(0x38C, 0x60, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY	IOMUX_PAD(0x38C, 0x60, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1	IOMUX_PAD(0x390, 0x64, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__GPIO4_22		IOMUX_PAD(0x390, 0x64, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__CSPI_MOSI		IOMUX_PAD(0x390, 0x64, 2, 0x788, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x64, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	IOMUX_PAD(0x390, 0x64, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6	IOMUX_PAD(0x390, 0x64, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID	IOMUX_PAD(0x390, 0x64, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2	IOMUX_PAD(0x394, 0x68, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__GPIO4_23		IOMUX_PAD(0x394, 0x68, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__CSPI_MISO		IOMUX_PAD(0x394, 0x68, 2, 0x784, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x68, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE	IOMUX_PAD(0x394, 0x68, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7	IOMUX_PAD(0x394, 0x68, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE	IOMUX_PAD(0x394, 0x68, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3	IOMUX_PAD(0x398, 0x6C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__GPIO4_24		IOMUX_PAD(0x398, 0x6C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__CSPI_SS0		IOMUX_PAD(0x398, 0x6C, 2, 0x78C, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x6C, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x6C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8	IOMUX_PAD(0x398, 0x6C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR	IOMUX_PAD(0x398, 0x6C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4	IOMUX_PAD(0x39C, 0x70, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__GPIO4_25		IOMUX_PAD(0x39C, 0x70, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__CSPI_SS1		IOMUX_PAD(0x39C, 0x70, 2, 0x790, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x70, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB	IOMUX_PAD(0x39C, 0x70, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9	IOMUX_PAD(0x39C, 0x70, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK	IOMUX_PAD(0x39C, 0x70, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5	IOMUX_PAD(0x3A0, 0x74, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__GPIO4_26		IOMUX_PAD(0x3A0, 0x74, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__CSPI_SS2		IOMUX_PAD(0x3A0, 0x74, 2, 0x794, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x74, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x74, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10	IOMUX_PAD(0x3A0, 0x74, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x74, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6	IOMUX_PAD(0x3A4, 0x78, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__GPIO4_27		IOMUX_PAD(0x3A4, 0x78, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__CSPI_SS3		IOMUX_PAD(0x3A4, 0x78, 2, 0x798, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x78, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x78, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11	IOMUX_PAD(0x3A4, 0x78, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x78, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7	IOMUX_PAD(0x3A8, 0x7C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__GPIO4_28		IOMUX_PAD(0x3A8, 0x7C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__CSPI_RDY		IOMUX_PAD(0x3A8, 0x7C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x7C, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x7C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12	IOMUX_PAD(0x3A8, 0x7C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID	IOMUX_PAD(0x3A8, 0x7C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8	IOMUX_PAD(0x3AC, 0x80, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__GPIO4_29		IOMUX_PAD(0x3AC, 0x80, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__PWM1_PWMO		IOMUX_PAD(0x3AC, 0x80, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B	IOMUX_PAD(0x3AC, 0x80, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x80, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13	IOMUX_PAD(0x3AC, 0x80, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__USBPHY2_AVALID	IOMUX_PAD(0x3AC, 0x80, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9	IOMUX_PAD(0x3B0, 0x84, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__GPIO4_30		IOMUX_PAD(0x3B0, 0x84, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__PWM2_PWMO		IOMUX_PAD(0x3B0, 0x84, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B	IOMUX_PAD(0x3B0, 0x84, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x3B0, 0x84, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14	IOMUX_PAD(0x3B0, 0x84, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0	IOMUX_PAD(0x3B0, 0x84, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10	IOMUX_PAD(0x3B4, 0x88, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__GPIO4_31		IOMUX_PAD(0x3B4, 0x88, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP	IOMUX_PAD(0x3B4, 0x88, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	IOMUX_PAD(0x3B4, 0x88, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15	IOMUX_PAD(0x3B4, 0x88, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1	IOMUX_PAD(0x3B4, 0x88, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11	IOMUX_PAD(0x3B8, 0x8C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__GPIO5_5		IOMUX_PAD(0x3B8, 0x8C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT	IOMUX_PAD(0x3B8, 0x8C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	IOMUX_PAD(0x3B8, 0x8C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16	IOMUX_PAD(0x3B8, 0x8C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2	IOMUX_PAD(0x3B8, 0x8C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12	IOMUX_PAD(0x3BC, 0x90, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__GPIO5_6		IOMUX_PAD(0x3BC, 0x90, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK	IOMUX_PAD(0x3BC, 0x90, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	IOMUX_PAD(0x3BC, 0x90, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17	IOMUX_PAD(0x3BC, 0x90, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3	IOMUX_PAD(0x3BC, 0x90, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13	IOMUX_PAD(0x3C0, 0x94, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__GPIO5_7		IOMUX_PAD(0x3C0, 0x94, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x3C0, 0x94, 3, 0x754, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	IOMUX_PAD(0x3C0, 0x94, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18	IOMUX_PAD(0x3C0, 0x94, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4	IOMUX_PAD(0x3C0, 0x94, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14	IOMUX_PAD(0x3C4, 0x98, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__GPIO5_8		IOMUX_PAD(0x3C4, 0x98, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC	IOMUX_PAD(0x3C4, 0x98, 3, 0x750, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	IOMUX_PAD(0x3C4, 0x98, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19	IOMUX_PAD(0x3C4, 0x98, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5	IOMUX_PAD(0x3C4, 0x98, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15	IOMUX_PAD(0x3C8, 0x9C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__GPIO5_9		IOMUX_PAD(0x3C8, 0x9C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x9C, 2, 0x7AC, 1, 0)
+#define _MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x9C, 3, 0x7C8, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	IOMUX_PAD(0x3C8, 0x9C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20	IOMUX_PAD(0x3C8, 0x9C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6	IOMUX_PAD(0x3C8, 0x9C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16	IOMUX_PAD(0x3CC, 0xA0, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__GPIO5_10		IOMUX_PAD(0x3CC, 0xA0, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0xA0, 2, 0x7C0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC	IOMUX_PAD(0x3CC, 0xA0, 3, 0x758, 1, 0)
+#define _MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0	IOMUX_PAD(0x3CC, 0xA0, 4, 0x868, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	IOMUX_PAD(0x3CC, 0xA0, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21	IOMUX_PAD(0x3CC, 0xA0, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7	IOMUX_PAD(0x3CC, 0xA0, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17	IOMUX_PAD(0x3D0, 0xA4, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__GPIO5_11		IOMUX_PAD(0x3D0, 0xA4, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0xA4, 2, 0x7BC, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD	IOMUX_PAD(0x3D0, 0xA4, 3, 0x74C, 1, 0)
+#define _MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1	IOMUX_PAD(0x3D0, 0xA4, 4, 0x86C, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	IOMUX_PAD(0x3D0, 0xA4, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22	IOMUX_PAD(0x3D0, 0xA4, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18	IOMUX_PAD(0x3D4, 0xA8, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__GPIO5_12		IOMUX_PAD(0x3D4, 0xA8, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0xA8, 2, 0x7C4, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x3D4, 0xA8, 3, 0x75C, 1, 0)
+#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x3D4, 0xA8, 4, 0x73C, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	IOMUX_PAD(0x3D4, 0xA8, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23	IOMUX_PAD(0x3D4, 0xA8, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2	IOMUX_PAD(0x3D4, 0xA8, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19	IOMUX_PAD(0x3D8, 0xAC, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__GPIO5_13		IOMUX_PAD(0x3D8, 0xAC, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0xAC, 2, 0x7B8, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD	IOMUX_PAD(0x3D8, 0xAC, 3, 0x748, 1, 0)
+#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC	IOMUX_PAD(0x3D8, 0xAC, 4, 0x738, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	IOMUX_PAD(0x3D8, 0xAC, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24	IOMUX_PAD(0x3D8, 0xAC, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3	IOMUX_PAD(0x3D8, 0xAC, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20	IOMUX_PAD(0x3DC, 0xB0, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__GPIO5_14		IOMUX_PAD(0x3DC, 0xB0, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0xB0, 2, 0x79C, 1, 0)
+#define _MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC	IOMUX_PAD(0x3DC, 0xB0, 3, 0x740, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	IOMUX_PAD(0x3DC, 0xB0, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25	IOMUX_PAD(0x3DC, 0xB0, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0xB0, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21	IOMUX_PAD(0x3E0, 0xB4, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__GPIO5_15		IOMUX_PAD(0x3E0, 0xB4, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0xB4, 2, 0x7A4, 1, 0)
+#define _MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD	IOMUX_PAD(0x3E0, 0xB4, 3, 0x734, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0xB4, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26	IOMUX_PAD(0x3E0, 0xB4, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__SATA_PHY_TDO	IOMUX_PAD(0x3E0, 0xB4, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22	IOMUX_PAD(0x3E4, 0xB8, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__GPIO5_16		IOMUX_PAD(0x3E4, 0xB8, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0xB8, 2, 0x7A0, 1, 0)
+#define _MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x3E4, 0xB8, 3, 0x744, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0xB8, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27	IOMUX_PAD(0x3E4, 0xB8, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__SATA_PHY_TCK	IOMUX_PAD(0x3E4, 0xB8, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23	IOMUX_PAD(0x3E8, 0xBC, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__GPIO5_17		IOMUX_PAD(0x3E8, 0xBC, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0xBC, 2, 0x7A8, 1, 0)
+#define _MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD	IOMUX_PAD(0x3E8, 0xBC, 3, 0x730, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0xBC, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28	IOMUX_PAD(0x3E8, 0xBC, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__SATA_PHY_TMS	IOMUX_PAD(0x3E8, 0xBC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK	IOMUX_PAD(0x3EC, 0xC0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__GPIO5_18		IOMUX_PAD(0x3EC, 0xC0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0	IOMUX_PAD(0x3EC, 0xC0, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29	IOMUX_PAD(0x3EC, 0xC0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0xC4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__GPIO5_19		IOMUX_PAD(0x3F0, 0xC4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0xC4, 2, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1	IOMUX_PAD(0x3F0, 0xC4, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30	IOMUX_PAD(0x3F0, 0xC4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__TPIU_TRCTL		IOMUX_PAD(0x3F0, 0xC4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN	IOMUX_PAD(0x3F4, 0xC8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__GPIO5_20		IOMUX_PAD(0x3F4, 0xC8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2	IOMUX_PAD(0x3F4, 0xC8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31	IOMUX_PAD(0x3F4, 0xC8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0xC8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC	IOMUX_PAD(0x3F8, 0xCC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__GPIO5_21		IOMUX_PAD(0x3F8, 0xCC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3	IOMUX_PAD(0x3F8, 0xCC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32	IOMUX_PAD(0x3F8, 0xCC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0xCC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0xD0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__GPIO5_22		IOMUX_PAD(0x3FC, 0xD0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__KPP_COL_5		IOMUX_PAD(0x3FC, 0xD0, 2, 0x840, 1, 0)
+#define _MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		IOMUX_PAD(0x3FC, 0xD0, 3, 0x79C, 2, 0)
+#define _MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP	IOMUX_PAD(0x3FC, 0xD0, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC	IOMUX_PAD(0x3FC, 0xD0, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33	IOMUX_PAD(0x3FC, 0xD0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0xD0, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0xD4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__GPIO5_23		IOMUX_PAD(0x400, 0xD4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__KPP_ROW_5		IOMUX_PAD(0x400, 0xD4, 2, 0x84C, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		IOMUX_PAD(0x400, 0xD4, 3, 0x7A4, 2, 0)
+#define _MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT	IOMUX_PAD(0x400, 0xD4, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD	IOMUX_PAD(0x400, 0xD4, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34	IOMUX_PAD(0x400, 0xD4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0xD4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0xD8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__GPIO5_24		IOMUX_PAD(0x404, 0xD8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__KPP_COL_6		IOMUX_PAD(0x404, 0xD8, 2, 0x844, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__ECSPI1_MISO		IOMUX_PAD(0x404, 0xD8, 3, 0x7A0, 2, 0)
+#define _MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK	IOMUX_PAD(0x404, 0xD8, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS	IOMUX_PAD(0x404, 0xD8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35	IOMUX_PAD(0x404, 0xD8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0xD8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0xDC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__GPIO5_25		IOMUX_PAD(0x408, 0xDC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__KPP_ROW_6		IOMUX_PAD(0x408, 0xDC, 2, 0x850, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__ECSPI1_SS0		IOMUX_PAD(0x408, 0xDC, 3, 0x7A8, 2, 0)
+#define _MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR	IOMUX_PAD(0x408, 0xDC, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD	IOMUX_PAD(0x408, 0xDC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36	IOMUX_PAD(0x408, 0xDC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0xDC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0xE0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__GPIO5_26		IOMUX_PAD(0x40C, 0xE0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__KPP_COL_7		IOMUX_PAD(0x40C, 0xE0, 2, 0x848, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		IOMUX_PAD(0x40C, 0xE0, 3, 0x7B8, 1, 0)
+#define _MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC	IOMUX_PAD(0x40C, 0xE0, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__I2C1_SDA		IOMUX_PAD(0x40C, 0xE0, 5 | IOMUX_CONFIG_SION, 0x818, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37	IOMUX_PAD(0x40C, 0xE0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0xE0, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0xE4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__GPIO5_27		IOMUX_PAD(0x410, 0xE4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__KPP_ROW_7		IOMUX_PAD(0x410, 0xE4, 2, 0x854, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		IOMUX_PAD(0x410, 0xE4, 3, 0x7C0, 1, 0)
+#define _MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR	IOMUX_PAD(0x410, 0xE4, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__I2C1_SCL		IOMUX_PAD(0x410, 0xE4, 5 | IOMUX_CONFIG_SION, 0x814, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38	IOMUX_PAD(0x410, 0xE4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0xE4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0xE8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__GPIO5_28		IOMUX_PAD(0x414, 0xE8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	IOMUX_PAD(0x414, 0xE8, 2, 0x878, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0xE8, 3, 0x7BC, 1, 0)
+#define _MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC	IOMUX_PAD(0x414, 0xE8, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4	IOMUX_PAD(0x414, 0xE8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39	IOMUX_PAD(0x414, 0xE8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0xE8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0xEC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__GPIO5_29		IOMUX_PAD(0x418, 0xEC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, 0)
+#define _MX53_PAD_CSI0_DAT11__ECSPI2_SS0		IOMUX_PAD(0x418, 0xEC, 3, 0x7C4, 1, 0)
+#define _MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS	IOMUX_PAD(0x418, 0xEC, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5	IOMUX_PAD(0x418, 0xEC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40	IOMUX_PAD(0x418, 0xEC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0xEC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0xF0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__GPIO5_30		IOMUX_PAD(0x41C, 0xF0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX	IOMUX_PAD(0x41C, 0xF0, 2, 0x890, 2, 0)
+#define _MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0xF0, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6	IOMUX_PAD(0x41C, 0xF0, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41	IOMUX_PAD(0x41C, 0xF0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0xF0, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0xF4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__GPIO5_31		IOMUX_PAD(0x420, 0xF4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__UART4_RXD_MUX	IOMUX_PAD(0x420, 0xF4, 2, 0x890, 3, 0)
+#define _MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0xF4, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7	IOMUX_PAD(0x420, 0xF4, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42	IOMUX_PAD(0x420, 0xF4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0xF4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0xF8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__GPIO6_0		IOMUX_PAD(0x424, 0xF8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX	IOMUX_PAD(0x424, 0xF8, 2, 0x898, 2, 0)
+#define _MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0xF8, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8	IOMUX_PAD(0x424, 0xF8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43	IOMUX_PAD(0x424, 0xF8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0xF8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0xFC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__GPIO6_1		IOMUX_PAD(0x428, 0xFC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__UART5_RXD_MUX	IOMUX_PAD(0x428, 0xFC, 2, 0x898, 3, 0)
+#define _MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0xFC, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9	IOMUX_PAD(0x428, 0xFC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44	IOMUX_PAD(0x428, 0xFC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0xFC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__GPIO6_2		IOMUX_PAD(0x42C, 0x100, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__UART4_RTS		IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10	IOMUX_PAD(0x42C, 0x100, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45	IOMUX_PAD(0x42C, 0x100, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__GPIO6_3		IOMUX_PAD(0x430, 0x104, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__UART4_CTS		IOMUX_PAD(0x430, 0x104, 2, 0x88C, 1, 0)
+#define _MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11	IOMUX_PAD(0x430, 0x104, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46	IOMUX_PAD(0x430, 0x104, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__GPIO6_4		IOMUX_PAD(0x434, 0x108, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__UART5_RTS		IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, 0)
+#define _MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12	IOMUX_PAD(0x434, 0x108, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47	IOMUX_PAD(0x434, 0x108, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__GPIO6_5		IOMUX_PAD(0x438, 0x10C, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__UART5_CTS		IOMUX_PAD(0x438, 0x10C, 2, 0x894, 3, 0)
+#define _MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13	IOMUX_PAD(0x438, 0x10C, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48	IOMUX_PAD(0x438, 0x10C, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK	IOMUX_PAD(0x438, 0x10C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__EMI_WEIM_A_25		IOMUX_PAD(0x458, 0x110, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__ECSPI2_RDY		IOMUX_PAD(0x458, 0x110, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__IPU_DI1_PIN12		IOMUX_PAD(0x458, 0x110, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, 0)
+#define _MX53_PAD_EIM_A25__IPU_DI0_D1_CS		IOMUX_PAD(0x458, 0x110, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		IOMUX_PAD(0x45C, 0x114, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, 0)
+#define _MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__ECSPI1_SS0		IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, 0)
+#define _MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, 0)
+#define _MX53_PAD_EIM_D16__EMI_WEIM_D_16		IOMUX_PAD(0x460, 0x118, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__IPU_DI0_PIN5		IOMUX_PAD(0x460, 0x118, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK	IOMUX_PAD(0x460, 0x118, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__ECSPI1_SCLK		IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, 0)
+#define _MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5, 0x820, 1, 0)
+#define _MX53_PAD_EIM_D17__EMI_WEIM_D_17		IOMUX_PAD(0x464, 0x11C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D17__IPU_DI0_PIN6		IOMUX_PAD(0x464, 0x11C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN	IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, 0)
+#define _MX53_PAD_EIM_D17__ECSPI1_MISO		IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, 0)
+#define _MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5, 0x824, 0, 0)
+#define _MX53_PAD_EIM_D18__EMI_WEIM_D_18		IOMUX_PAD(0x468, 0x120, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D18__IPU_DI0_PIN7		IOMUX_PAD(0x468, 0x120, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO	IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, 0)
+#define _MX53_PAD_EIM_D18__ECSPI1_MOSI		IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, 0)
+#define _MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5, 0x828, 0, 0)
+#define _MX53_PAD_EIM_D18__IPU_DI1_D0_CS		IOMUX_PAD(0x468, 0x120, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__EMI_WEIM_D_19		IOMUX_PAD(0x46C, 0x124, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__IPU_DI0_PIN8		IOMUX_PAD(0x46C, 0x124, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS	IOMUX_PAD(0x46C, 0x124, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__ECSPI1_SS1		IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, 0)
+#define _MX53_PAD_EIM_D19__EPIT1_EPITO		IOMUX_PAD(0x46C, 0x124, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, 0x874, 0, 0)
+#define _MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, 0)
+#define _MX53_PAD_EIM_D20__EMI_WEIM_D_20		IOMUX_PAD(0x470, 0x128, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__IPU_DI0_PIN16		IOMUX_PAD(0x470, 0x128, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, 0)
+#define _MX53_PAD_EIM_D20__EPIT2_EPITO		IOMUX_PAD(0x470, 0x128, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, 0)
+#define _MX53_PAD_EIM_D20__USBOH3_USBH2_PWR	IOMUX_PAD(0x470, 0x128, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__EMI_WEIM_D_21		IOMUX_PAD(0x474, 0x12C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__IPU_DI0_PIN17		IOMUX_PAD(0x474, 0x12C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK	IOMUX_PAD(0x474, 0x12C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, 0)
+#define _MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5, 0x814, 1, 0)
+#define _MX53_PAD_EIM_D21__USBOH3_USBOTG_OC	IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, 0)
+#define _MX53_PAD_EIM_D22__EMI_WEIM_D_22		IOMUX_PAD(0x478, 0x130, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D22__IPU_DI0_PIN1		IOMUX_PAD(0x478, 0x130, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN	IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, 0)
+#define _MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, 0)
+#define _MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR	IOMUX_PAD(0x478, 0x130, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__EMI_WEIM_D_23		IOMUX_PAD(0x47C, 0x134, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, 0x884, 0, 0)
+#define _MX53_PAD_EIM_D23__UART1_DCD		IOMUX_PAD(0x47C, 0x134, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_DI0_D0_CS		IOMUX_PAD(0x47C, 0x134, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_DI1_PIN2		IOMUX_PAD(0x47C, 0x134, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_DI1_PIN14		IOMUX_PAD(0x47C, 0x134, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		IOMUX_PAD(0x480, 0x138, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, 0)
+#define _MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN3		IOMUX_PAD(0x480, 0x138, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, 0)
+#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN16		IOMUX_PAD(0x480, 0x138, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__EMI_WEIM_D_24		IOMUX_PAD(0x484, 0x13C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__UART3_TXD_MUX		IOMUX_PAD(0x484, 0x13C, 2, 0x888, 0, 0)
+#define _MX53_PAD_EIM_D24__ECSPI1_SS2		IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, 0)
+#define _MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, 0)
+#define _MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, 0)
+#define _MX53_PAD_EIM_D24__ECSPI2_SS2		IOMUX_PAD(0x484, 0x13C, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__UART1_DTR		IOMUX_PAD(0x484, 0x13C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__EMI_WEIM_D_25		IOMUX_PAD(0x488, 0x140, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__UART3_RXD_MUX		IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, 0)
+#define _MX53_PAD_EIM_D25__ECSPI1_SS3		IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, 0)
+#define _MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, 0)
+#define _MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, 0)
+#define _MX53_PAD_EIM_D25__ECSPI2_SS3		IOMUX_PAD(0x488, 0x140, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__UART1_DSR		IOMUX_PAD(0x488, 0x140, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__EMI_WEIM_D_26		IOMUX_PAD(0x48C, 0x144, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__UART2_TXD_MUX		IOMUX_PAD(0x48C, 0x144, 2, 0x880, 0, 0)
+#define _MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_CSI0_D_1		IOMUX_PAD(0x48C, 0x144, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_DI1_PIN11		IOMUX_PAD(0x48C, 0x144, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_SISG_2		IOMUX_PAD(0x48C, 0x144, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__EMI_WEIM_D_27		IOMUX_PAD(0x490, 0x148, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__UART2_RXD_MUX		IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, 0)
+#define _MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_CSI0_D_0		IOMUX_PAD(0x490, 0x148, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_DI1_PIN13		IOMUX_PAD(0x490, 0x148, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_SISG_3		IOMUX_PAD(0x490, 0x148, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__EMI_WEIM_D_28		IOMUX_PAD(0x494, 0x14C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, 0x87C, 0, 0)
+#define _MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO	IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, 0)
+#define _MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, 0)
+#define _MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5, 0x818, 1, 0)
+#define _MX53_PAD_EIM_D28__IPU_EXT_TRIG		IOMUX_PAD(0x494, 0x14C, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__IPU_DI0_PIN13		IOMUX_PAD(0x494, 0x14C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__EMI_WEIM_D_29		IOMUX_PAD(0x498, 0x150, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, 0)
+#define _MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS	IOMUX_PAD(0x498, 0x150, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, 0)
+#define _MX53_PAD_EIM_D29__IPU_DI1_PIN15		IOMUX_PAD(0x498, 0x150, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, 0)
+#define _MX53_PAD_EIM_D29__IPU_DI0_PIN14		IOMUX_PAD(0x498, 0x150, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__EMI_WEIM_D_30		IOMUX_PAD(0x49C, 0x154, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, 0x884, 2, 0)
+#define _MX53_PAD_EIM_D30__IPU_CSI0_D_3		IOMUX_PAD(0x49C, 0x154, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__IPU_DI0_PIN11		IOMUX_PAD(0x49C, 0x154, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, 0)
+#define _MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, 0)
+#define _MX53_PAD_EIM_D31__EMI_WEIM_D_31		IOMUX_PAD(0x4A0, 0x158, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, 0)
+#define _MX53_PAD_EIM_D31__IPU_CSI0_D_2		IOMUX_PAD(0x4A0, 0x158, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__IPU_DI0_PIN12		IOMUX_PAD(0x4A0, 0x158, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__USBOH3_USBH1_PWR	IOMUX_PAD(0x4A0, 0x158, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__USBOH3_USBH2_PWR	IOMUX_PAD(0x4A0, 0x158, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__EMI_WEIM_A_24		IOMUX_PAD(0x4A8, 0x15C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__IPU_CSI1_D_19		IOMUX_PAD(0x4A8, 0x15C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__IPU_SISG_2		IOMUX_PAD(0x4A8, 0x15C, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__EMI_WEIM_A_23		IOMUX_PAD(0x4AC, 0x160, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__IPU_CSI1_D_18		IOMUX_PAD(0x4AC, 0x160, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__IPU_SISG_3		IOMUX_PAD(0x4AC, 0x160, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__USBPHY2_ENDSESSION	IOMUX_PAD(0x4AC, 0x160, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__EMI_WEIM_A_22		IOMUX_PAD(0x4B0, 0x164, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__IPU_CSI1_D_17		IOMUX_PAD(0x4B0, 0x164, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__SRC_BT_CFG1_7		IOMUX_PAD(0x4B0, 0x164, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__EMI_WEIM_A_21		IOMUX_PAD(0x4B4, 0x168, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__IPU_CSI1_D_16		IOMUX_PAD(0x4B4, 0x168, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__SRC_BT_CFG1_6		IOMUX_PAD(0x4B4, 0x168, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__EMI_WEIM_A_20		IOMUX_PAD(0x4B8, 0x16C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__IPU_CSI1_D_15		IOMUX_PAD(0x4B8, 0x16C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__SRC_BT_CFG1_5		IOMUX_PAD(0x4B8, 0x16C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__EMI_WEIM_A_19		IOMUX_PAD(0x4BC, 0x170, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__IPU_CSI1_D_14		IOMUX_PAD(0x4BC, 0x170, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__SRC_BT_CFG1_4		IOMUX_PAD(0x4BC, 0x170, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__EMI_WEIM_A_18		IOMUX_PAD(0x4C0, 0x174, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__IPU_CSI1_D_13		IOMUX_PAD(0x4C0, 0x174, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__SRC_BT_CFG1_3		IOMUX_PAD(0x4C0, 0x174, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__EMI_WEIM_A_17		IOMUX_PAD(0x4C4, 0x178, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__IPU_CSI1_D_12		IOMUX_PAD(0x4C4, 0x178, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__SRC_BT_CFG1_2		IOMUX_PAD(0x4C4, 0x178, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__EMI_WEIM_A_16		IOMUX_PAD(0x4C8, 0x17C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__SRC_BT_CFG1_1		IOMUX_PAD(0x4C8, 0x17C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		IOMUX_PAD(0x4CC, 0x180, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS0__ECSPI2_SCLK		IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, 0)
+#define _MX53_PAD_EIM_CS0__IPU_DI1_PIN5		IOMUX_PAD(0x4CC, 0x180, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		IOMUX_PAD(0x4D0, 0x184, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS1__ECSPI2_MOSI		IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, 0)
+#define _MX53_PAD_EIM_CS1__IPU_DI1_PIN6		IOMUX_PAD(0x4D0, 0x184, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__EMI_WEIM_OE		IOMUX_PAD(0x4D4, 0x188, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__ECSPI2_MISO		IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, 0)
+#define _MX53_PAD_EIM_OE__IPU_DI1_PIN7		IOMUX_PAD(0x4D4, 0x188, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__USBPHY2_IDDIG		IOMUX_PAD(0x4D4, 0x188, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__EMI_WEIM_RW		IOMUX_PAD(0x4D8, 0x18C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, 0)
+#define _MX53_PAD_EIM_RW__IPU_DI1_PIN8		IOMUX_PAD(0x4D8, 0x18C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT	IOMUX_PAD(0x4D8, 0x18C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__EMI_WEIM_LBA		IOMUX_PAD(0x4DC, 0x190, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__ECSPI2_SS1		IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, 0)
+#define _MX53_PAD_EIM_LBA__IPU_DI1_PIN17		IOMUX_PAD(0x4DC, 0x190, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		IOMUX_PAD(0x4DC, 0x190, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		IOMUX_PAD(0x4E4, 0x194, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__IPU_CSI1_D_11		IOMUX_PAD(0x4E4, 0x194, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__GPC_PMIC_RDY		IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, 0)
+#define _MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		IOMUX_PAD(0x4E4, 0x194, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		IOMUX_PAD(0x4E8, 0x198, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__IPU_CSI1_D_10		IOMUX_PAD(0x4E8, 0x198, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		IOMUX_PAD(0x4E8, 0x198, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0	IOMUX_PAD(0x4EC, 0x19C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__IPU_CSI1_D_9		IOMUX_PAD(0x4EC, 0x19C, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		IOMUX_PAD(0x4EC, 0x19C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1	IOMUX_PAD(0x4F0, 0x1A0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__IPU_CSI1_D_8		IOMUX_PAD(0x4F0, 0x1A0, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		IOMUX_PAD(0x4F0, 0x1A0, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2	IOMUX_PAD(0x4F4, 0x1A4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__IPU_CSI1_D_7		IOMUX_PAD(0x4F4, 0x1A4, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		IOMUX_PAD(0x4F4, 0x1A4, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3	IOMUX_PAD(0x4F8, 0x1A8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__IPU_CSI1_D_6		IOMUX_PAD(0x4F8, 0x1A8, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		IOMUX_PAD(0x4F8, 0x1A8, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4	IOMUX_PAD(0x4FC, 0x1AC, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__IPU_CSI1_D_5		IOMUX_PAD(0x4FC, 0x1AC, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		IOMUX_PAD(0x4FC, 0x1AC, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5	IOMUX_PAD(0x500, 0x1B0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__IPU_CSI1_D_4		IOMUX_PAD(0x500, 0x1B0, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		IOMUX_PAD(0x500, 0x1B0, 17, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6	IOMUX_PAD(0x504, 0x1B4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__IPU_CSI1_D_3		IOMUX_PAD(0x504, 0x1B4, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		IOMUX_PAD(0x504, 0x1B4, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7	IOMUX_PAD(0x508, 0x1B8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__IPU_CSI1_D_2		IOMUX_PAD(0x508, 0x1B8, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		IOMUX_PAD(0x508, 0x1B8, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8	IOMUX_PAD(0x50C, 0x1BC, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__IPU_CSI1_D_1		IOMUX_PAD(0x50C, 0x1BC, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		IOMUX_PAD(0x50C, 0x1BC, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9	IOMUX_PAD(0x510, 0x1C0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__IPU_CSI1_D_0		IOMUX_PAD(0x510, 0x1C0, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		IOMUX_PAD(0x510, 0x1C0, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10	IOMUX_PAD(0x514, 0x1C4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN	IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, 0)
+#define _MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11	IOMUX_PAD(0x518, 0x1C8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__IPU_DI1_PIN2		IOMUX_PAD(0x518, 0x1C8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, 0)
+#define _MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12	IOMUX_PAD(0x51C, 0x1CC, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA12__IPU_DI1_PIN3		IOMUX_PAD(0x51C, 0x1CC, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, 0)
+#define _MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13	IOMUX_PAD(0x520, 0x1D0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, 0)
+#define _MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14	IOMUX_PAD(0x524, 0x1D4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15	IOMUX_PAD(0x528, 0x1D8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN1		IOMUX_PAD(0x528, 0x1D8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN4		IOMUX_PAD(0x528, 0x1D8, 4, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	IOMUX_PAD(0x52C, 0x1DC, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WE_B__GPIO6_12		IOMUX_PAD(0x52C, 0x1DC, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	IOMUX_PAD(0x530, 0x1E0, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RE_B__GPIO6_13		IOMUX_PAD(0x530, 0x1E0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B	IOMUX_PAD(0x534, 0x1E4, 2, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX3_P__GPIO6_22		IOMUX_PAD(NON_PAD_I, 0x1EC, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3	IOMUX_PAD(NON_PAD_I, 0x1EC, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX2_P__GPIO6_24		IOMUX_PAD(NON_PAD_I, 0x1F0, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2	IOMUX_PAD(NON_PAD_I, 0x1F0, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_CLK_P__GPIO6_26		IOMUX_PAD(NON_PAD_I, 0x1F4, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK	IOMUX_PAD(NON_PAD_I, 0x1F4, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX1_P__GPIO6_28		IOMUX_PAD(NON_PAD_I, 0x1F8, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1	IOMUX_PAD(NON_PAD_I, 0x1F8, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX0_P__GPIO6_30		IOMUX_PAD(NON_PAD_I, 0x1FC, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0	IOMUX_PAD(NON_PAD_I, 0x1FC, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX3_P__GPIO7_22		IOMUX_PAD(NON_PAD_I, 0x200, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3	IOMUX_PAD(NON_PAD_I, 0x200, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_CLK_P__GPIO7_24		IOMUX_PAD(NON_PAD_I, 0x204, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK	IOMUX_PAD(NON_PAD_I, 0x204, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX2_P__GPIO7_26		IOMUX_PAD(NON_PAD_I, 0x208, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2	IOMUX_PAD(NON_PAD_I, 0x208, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX1_P__GPIO7_28		IOMUX_PAD(NON_PAD_I, 0x20C, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1	IOMUX_PAD(NON_PAD_I, 0x20C, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX0_P__GPIO7_30		IOMUX_PAD(NON_PAD_I, 0x210, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0	IOMUX_PAD(NON_PAD_I, 0x210, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0	IOMUX_PAD(0x5A0, 0x228, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_ALE__GPIO6_8		IOMUX_PAD(0x5A4, 0x22C, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1	IOMUX_PAD(0x5A4, 0x22C, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	IOMUX_PAD(0x5A8, 0x230, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WP_B__GPIO6_9		IOMUX_PAD(0x5A8, 0x230, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2	IOMUX_PAD(0x5A8, 0x230, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	IOMUX_PAD(0x5AC, 0x234, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RB0__GPIO6_10		IOMUX_PAD(0x5AC, 0x234, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3	IOMUX_PAD(0x5AC, 0x234, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	IOMUX_PAD(0x5B0, 0x238, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS0__GPIO6_11		IOMUX_PAD(0x5B0, 0x238, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4	IOMUX_PAD(0x5B0, 0x238, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1	IOMUX_PAD(0x5B4, 0x23C, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS1__GPIO6_14		IOMUX_PAD(0x5B4, 0x23C, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS1__MLB_MLBCLK		IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, 0)
+#define _MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5	IOMUX_PAD(0x5B4, 0x23C, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2	IOMUX_PAD(0x5B8, 0x240, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__GPIO6_15		IOMUX_PAD(0x5B8, 0x240, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__IPU_SISG_0		IOMUX_PAD(0x5B8, 0x240, 2, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__ESAI1_TX0		IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, 0)
+#define _MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__MLB_MLBSIG		IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, 0)
+#define _MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6	IOMUX_PAD(0x5B8, 0x240, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3	IOMUX_PAD(0x5BC, 0x244, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__GPIO6_16		IOMUX_PAD(0x5BC, 0x244, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__IPU_SISG_1		IOMUX_PAD(0x5BC, 0x244, 2, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__ESAI1_TX1		IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, 0)
+#define _MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__MLB_MLBDAT		IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, 0)
+#define _MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7	IOMUX_PAD(0x5BC, 0x244, 7, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__FEC_MDIO		IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, 0)
+#define _MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__ESAI1_SCKR		IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, 0)
+#define _MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, 0)
+#define _MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49	IOMUX_PAD(0x5C4, 0x248, 6, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__GPIO1_23		IOMUX_PAD(0x5C8, 0x24C, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__ESAI1_FSR		IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50	IOMUX_PAD(0x5C8, 0x24C, 6, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__FEC_RX_ER		IOMUX_PAD(0x5CC, 0x250, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__GPIO1_24		IOMUX_PAD(0x5CC, 0x250, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__ESAI1_HCKR		IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__FEC_RX_CLK		IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, 0)
+#define _MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_CRS_DV__FEC_RX_DV		IOMUX_PAD(0x5D0, 0x254, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_CRS_DV__GPIO1_25		IOMUX_PAD(0x5D0, 0x254, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__FEC_RDATA_1		IOMUX_PAD(0x5D4, 0x258, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__ESAI1_FST		IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__MLB_MLBSIG		IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, 0)
+#define _MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD0__FEC_RDATA_0		IOMUX_PAD(0x5D8, 0x25C, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD0__ESAI1_HCKT		IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, 0)
+#define _MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TX_EN__FEC_TX_EN		IOMUX_PAD(0x5DC, 0x260, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TX_EN__GPIO1_28		IOMUX_PAD(0x5DC, 0x260, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, 0)
+#define _MX53_PAD_FEC_TXD1__FEC_TDATA_1		IOMUX_PAD(0x5E0, 0x264, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, 0)
+#define _MX53_PAD_FEC_TXD1__MLB_MLBCLK		IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, 0)
+#define _MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK	IOMUX_PAD(0x5E0, 0x264, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD0__FEC_TDATA_0		IOMUX_PAD(0x5E4, 0x268, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, 0)
+#define _MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0	IOMUX_PAD(0x5E4, 0x268, 7, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, 0)
+#define _MX53_PAD_FEC_MDC__MLB_MLBDAT		IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, 0)
+#define _MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1	IOMUX_PAD(0x5E8, 0x26C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOW__PATA_DIOW		IOMUX_PAD(0x5F0, 0x270, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOW__GPIO6_17		IOMUX_PAD(0x5F0, 0x270, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX	IOMUX_PAD(0x5F0, 0x270, 3, 0x878, 2, 0)
+#define _MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2	IOMUX_PAD(0x5F0, 0x270, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMACK__PATA_DMACK		IOMUX_PAD(0x5F4, 0x274, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMACK__GPIO6_18		IOMUX_PAD(0x5F4, 0x274, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMACK__UART1_RXD_MUX	IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, 0)
+#define _MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3	IOMUX_PAD(0x5F4, 0x274, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__PATA_DMARQ		IOMUX_PAD(0x5F8, 0x278, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__GPIO7_0		IOMUX_PAD(0x5F8, 0x278, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	IOMUX_PAD(0x5F8, 0x278, 3, 0x880, 2, 0)
+#define _MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0	IOMUX_PAD(0x5F8, 0x278, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4	IOMUX_PAD(0x5F8, 0x278, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN	IOMUX_PAD(0x5FC, 0x27C, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1	IOMUX_PAD(0x5FC, 0x27C, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__PATA_INTRQ		IOMUX_PAD(0x600, 0x280, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__GPIO7_2		IOMUX_PAD(0x600, 0x280, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__UART2_CTS		IOMUX_PAD(0x600, 0x280, 3, 0x87C, 2, 0)
+#define _MX53_PAD_PATA_INTRQ__CAN1_TXCAN		IOMUX_PAD(0x600, 0x280, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2	IOMUX_PAD(0x600, 0x280, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6	IOMUX_PAD(0x600, 0x280, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOR__PATA_DIOR		IOMUX_PAD(0x604, 0x284, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOR__UART2_RTS		IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, 0)
+#define _MX53_PAD_PATA_DIOR__CAN1_RXCAN		IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, 0)
+#define _MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7	IOMUX_PAD(0x604, 0x284, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__GPIO7_4		IOMUX_PAD(0x608, 0x288, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, 0x874, 2, 0)
+#define _MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__PATA_IORDY		IOMUX_PAD(0x60C, 0x28C, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__GPIO7_5		IOMUX_PAD(0x60C, 0x28C, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__ESDHC3_CLK		IOMUX_PAD(0x60C, 0x28C, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__UART1_RTS		IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, 0)
+#define _MX53_PAD_PATA_IORDY__CAN2_RXCAN		IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, 0)
+#define _MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1	IOMUX_PAD(0x60C, 0x28C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__PATA_DA_0		IOMUX_PAD(0x610, 0x290, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__GPIO7_6		IOMUX_PAD(0x610, 0x290, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__ESDHC3_RST		IOMUX_PAD(0x610, 0x290, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__OWIRE_LINE		IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, 0)
+#define _MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2	IOMUX_PAD(0x610, 0x290, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__PATA_DA_1		IOMUX_PAD(0x614, 0x294, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__GPIO7_7		IOMUX_PAD(0x614, 0x294, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__ESDHC4_CMD		IOMUX_PAD(0x614, 0x294, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__UART3_CTS		IOMUX_PAD(0x614, 0x294, 4, 0x884, 4, 0)
+#define _MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3	IOMUX_PAD(0x614, 0x294, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__PATA_DA_2		IOMUX_PAD(0x618, 0x298, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__GPIO7_8		IOMUX_PAD(0x618, 0x298, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__ESDHC4_CLK		IOMUX_PAD(0x618, 0x298, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__UART3_RTS		IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, 0)
+#define _MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4	IOMUX_PAD(0x618, 0x298, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_0__PATA_CS_0		IOMUX_PAD(0x61C, 0x29C, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, 0x888, 2, 0)
+#define _MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5	IOMUX_PAD(0x61C, 0x29C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_1__PATA_CS_1		IOMUX_PAD(0x620, 0x2A0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_1__GPIO7_10		IOMUX_PAD(0x620, 0x2A0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, 0)
+#define _MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6	IOMUX_PAD(0x620, 0x2A0, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__GPIO2_0		IOMUX_PAD(0x628, 0x2A4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	IOMUX_PAD(0x628, 0x2A4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0	IOMUX_PAD(0x628, 0x2A4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7	IOMUX_PAD(0x628, 0x2A4, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__GPIO2_1		IOMUX_PAD(0x62C, 0x2A8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	IOMUX_PAD(0x62C, 0x2A8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1	IOMUX_PAD(0x62C, 0x2A8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__GPIO2_2		IOMUX_PAD(0x630, 0x2AC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	IOMUX_PAD(0x630, 0x2AC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2	IOMUX_PAD(0x630, 0x2AC, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__GPIO2_3		IOMUX_PAD(0x634, 0x2B0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	IOMUX_PAD(0x634, 0x2B0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3	IOMUX_PAD(0x634, 0x2B0, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__GPIO2_4		IOMUX_PAD(0x638, 0x2B4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	IOMUX_PAD(0x638, 0x2B4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4	IOMUX_PAD(0x638, 0x2B4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__PATA_DATA_5	IOMUX_PAD(0x63C, 0x2B8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__GPIO2_5		IOMUX_PAD(0x63C, 0x2B8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	IOMUX_PAD(0x63C, 0x2B8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5	IOMUX_PAD(0x63C, 0x2B8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__PATA_DATA_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__GPIO2_6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__GPIO2_7		IOMUX_PAD(0x644, 0x2C0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	IOMUX_PAD(0x644, 0x2C0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7	IOMUX_PAD(0x644, 0x2C0, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__GPIO2_8		IOMUX_PAD(0x648, 0x2C4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__EMI_NANDF_D_8	IOMUX_PAD(0x648, 0x2C4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8	IOMUX_PAD(0x648, 0x2C4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__GPIO2_9		IOMUX_PAD(0x64C, 0x2C8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__EMI_NANDF_D_9	IOMUX_PAD(0x64C, 0x2C8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9	IOMUX_PAD(0x64C, 0x2C8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__PATA_DATA_10	IOMUX_PAD(0x650, 0x2CC, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__GPIO2_10		IOMUX_PAD(0x650, 0x2CC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__EMI_NANDF_D_10	IOMUX_PAD(0x650, 0x2CC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10	IOMUX_PAD(0x650, 0x2CC, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__PATA_DATA_11	IOMUX_PAD(0x654, 0x2D0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__GPIO2_11		IOMUX_PAD(0x654, 0x2D0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__EMI_NANDF_D_11	IOMUX_PAD(0x654, 0x2D0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11	IOMUX_PAD(0x654, 0x2D0, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__PATA_DATA_12	IOMUX_PAD(0x658, 0x2D4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__GPIO2_12		IOMUX_PAD(0x658, 0x2D4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__EMI_NANDF_D_12	IOMUX_PAD(0x658, 0x2D4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12	IOMUX_PAD(0x658, 0x2D4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__PATA_DATA_13	IOMUX_PAD(0x65C, 0x2D8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__GPIO2_13		IOMUX_PAD(0x65C, 0x2D8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__EMI_NANDF_D_13	IOMUX_PAD(0x65C, 0x2D8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13	IOMUX_PAD(0x65C, 0x2D8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__PATA_DATA_14	IOMUX_PAD(0x660, 0x2DC, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__GPIO2_14		IOMUX_PAD(0x660, 0x2DC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__EMI_NANDF_D_14	IOMUX_PAD(0x660, 0x2DC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14	IOMUX_PAD(0x660, 0x2DC, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__PATA_DATA_15	IOMUX_PAD(0x664, 0x2E0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__GPIO2_15		IOMUX_PAD(0x664, 0x2E0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__EMI_NANDF_D_15	IOMUX_PAD(0x664, 0x2E0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15	IOMUX_PAD(0x664, 0x2E0, 6, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__ESDHC1_DAT0	IOMUX_PAD(0x66C, 0x2E4, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__GPIO1_16	IOMUX_PAD(0x66C, 0x2E4, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__GPT_CAPIN1	IOMUX_PAD(0x66C, 0x2E4, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__CSPI_MISO	IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, 0)
+#define _MX53_PAD_SD1_DATA0__CCM_PLL3_BYP	IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, 0)
+#define _MX53_PAD_SD1_DATA1__ESDHC1_DAT1	IOMUX_PAD(0x670, 0x2E8, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA1__GPIO1_17	IOMUX_PAD(0x670, 0x2E8, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA1__GPT_CAPIN2	IOMUX_PAD(0x670, 0x2E8, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA1__CSPI_SS0	IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, 0)
+#define _MX53_PAD_SD1_DATA1__CCM_PLL4_BYP	IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, 0)
+#define _MX53_PAD_SD1_CMD__ESDHC1_CMD	IOMUX_PAD(0x674, 0x2EC, IOMUX_CONFIG_SION, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CMD__GPIO1_18		IOMUX_PAD(0x674, 0x2EC, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CMD__GPT_CMPOUT1	IOMUX_PAD(0x674, 0x2EC, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, 0)
+#define _MX53_PAD_SD1_CMD__CCM_PLL1_BYP	IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, 0)
+#define _MX53_PAD_SD1_DATA2__ESDHC1_DAT2		IOMUX_PAD(0x678, 0x2F0, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__GPIO1_19		IOMUX_PAD(0x678, 0x2F0, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__GPT_CMPOUT2		IOMUX_PAD(0x678, 0x2F0, 2, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__PWM2_PWMO		IOMUX_PAD(0x678, 0x2F0, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__CSPI_SS1		IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, 0)
+#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, 0)
+#define _MX53_PAD_SD1_CLK__ESDHC1_CLK	IOMUX_PAD(0x67C, 0x2F4, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__GPIO1_20		IOMUX_PAD(0x67C, 0x2F4, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__OSC32k_32K_OUT	IOMUX_PAD(0x67C, 0x2F4, 2, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__GPT_CLKIN		IOMUX_PAD(0x67C, 0x2F4, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, 0)
+#define _MX53_PAD_SD1_CLK__SATA_PHY_DTB_0	IOMUX_PAD(0x67C, 0x2F4, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__ESDHC1_DAT3	IOMUX_PAD(0x680, 0x2F8, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__GPIO1_21	IOMUX_PAD(0x680, 0x2F8, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__GPT_CMPOUT3	IOMUX_PAD(0x680, 0x2F8, 2, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__PWM1_PWMO	IOMUX_PAD(0x680, 0x2F8, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_B	IOMUX_PAD(0x680, 0x2F8, 4, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__CSPI_SS2	IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, 0)
+#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1	IOMUX_PAD(0x680, 0x2F8, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CLK__ESDHC2_CLK	IOMUX_PAD(0x688, 0x2FC, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CLK__GPIO1_10		IOMUX_PAD(0x688, 0x2FC, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CLK__KPP_COL_5		IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, 0)
+#define _MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, 0)
+#define _MX53_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, 0)
+#define _MX53_PAD_SD2_CLK__SCC_RANDOM_V	IOMUX_PAD(0x688, 0x2FC, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CMD__ESDHC2_CMD	IOMUX_PAD(0x68C, 0x300, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CMD__GPIO1_11		IOMUX_PAD(0x68C, 0x300, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CMD__KPP_ROW_5	IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, 0)
+#define _MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC	IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, 0)
+#define _MX53_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, 0)
+#define _MX53_PAD_SD2_CMD__SCC_RANDOM	IOMUX_PAD(0x68C, 0x300, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA3__ESDHC2_DAT3	IOMUX_PAD(0x690, 0x304, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA3__GPIO1_12	IOMUX_PAD(0x690, 0x304, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA3__KPP_COL_6	IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, 0)
+#define _MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC	IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, 0)
+#define _MX53_PAD_SD2_DATA3__CSPI_SS2	IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, 0)
+#define _MX53_PAD_SD2_DATA3__SJC_DONE	IOMUX_PAD(0x690, 0x304, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA2__ESDHC2_DAT2	IOMUX_PAD(0x694, 0x308, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA2__GPIO1_13	IOMUX_PAD(0x694, 0x308, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA2__KPP_ROW_6	IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, 0)
+#define _MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD	IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, 0)
+#define _MX53_PAD_SD2_DATA2__CSPI_SS1	IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, 0)
+#define _MX53_PAD_SD2_DATA2__SJC_FAIL	IOMUX_PAD(0x694, 0x308, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA1__ESDHC2_DAT1	IOMUX_PAD(0x698, 0x30C, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA1__GPIO1_14	IOMUX_PAD(0x698, 0x30C, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA1__KPP_COL_7	IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, 0)
+#define _MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, 0)
+#define _MX53_PAD_SD2_DATA1__CSPI_SS0	IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, 0)
+#define _MX53_PAD_SD2_DATA1__RTIC_SEC_VIO	IOMUX_PAD(0x698, 0x30C, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA0__ESDHC2_DAT0	IOMUX_PAD(0x69C, 0x310, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA0__GPIO1_15	IOMUX_PAD(0x69C, 0x310, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA0__KPP_ROW_7	IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, 0)
+#define _MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD	IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, 0)
+#define _MX53_PAD_SD2_DATA0__CSPI_MISO	IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, 0)
+#define _MX53_PAD_SD2_DATA0__RTIC_DONE_INT	IOMUX_PAD(0x69C, 0x310, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__CCM_CLKO		IOMUX_PAD(0x6A4, 0x314, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__GPIO1_0		IOMUX_PAD(0x6A4, 0x314, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__KPP_COL_5		IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, 0)
+#define _MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	IOMUX_PAD(0x6A4, 0x314, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__EPIT1_EPITO	IOMUX_PAD(0x6A4, 0x314, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__SRTC_ALARM_DEB	IOMUX_PAD(0x6A4, 0x314, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__USBOH3_USBH1_PWR	IOMUX_PAD(0x6A4, 0x314, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__CSU_TD		IOMUX_PAD(0x6A4, 0x314, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__ESAI1_SCKR		IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, 0)
+#define _MX53_PAD_GPIO_1__GPIO1_1		IOMUX_PAD(0x6A8, 0x318, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__KPP_ROW_5		IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, 0)
+#define _MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK	IOMUX_PAD(0x6A8, 0x318, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__PWM2_PWMO	IOMUX_PAD(0x6A8, 0x318, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__WDOG2_WDOG_B	IOMUX_PAD(0x6A8, 0x318, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__ESDHC1_CD		IOMUX_PAD(0x6A8, 0x318, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__SRC_TESTER_ACK	IOMUX_PAD(0x6A8, 0x318, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__ESAI1_FSR		IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, 0)
+#define _MX53_PAD_GPIO_9__GPIO1_9		IOMUX_PAD(0x6AC, 0x31C, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__KPP_COL_6		IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, 0)
+#define _MX53_PAD_GPIO_9__CCM_REF_EN_B	IOMUX_PAD(0x6AC, 0x31C, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__PWM1_PWMO	IOMUX_PAD(0x6AC, 0x31C, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__WDOG1_WDOG_B	IOMUX_PAD(0x6AC, 0x31C, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__ESDHC1_WP		IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, 0)
+#define _MX53_PAD_GPIO_9__SCC_FAIL_STATE	IOMUX_PAD(0x6AC, 0x31C, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__ESAI1_HCKR		IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, 0)
+#define _MX53_PAD_GPIO_3__GPIO1_3		IOMUX_PAD(0x6B0, 0x320, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__I2C3_SCL		IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, 0)
+#define _MX53_PAD_GPIO_3__DPLLIP1_TOG_EN	IOMUX_PAD(0x6B0, 0x320, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__CCM_CLKO2		IOMUX_PAD(0x6B0, 0x320, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__USBOH3_USBH1_OC	IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, 0)
+#define _MX53_PAD_GPIO_3__MLB_MLBCLK		IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, 0)
+#define _MX53_PAD_GPIO_6__ESAI1_SCKT		IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, 0)
+#define _MX53_PAD_GPIO_6__GPIO1_6		IOMUX_PAD(0x6B4, 0x324, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__I2C3_SDA		IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, 0)
+#define _MX53_PAD_GPIO_6__CCM_CCM_OUT_0	IOMUX_PAD(0x6B4, 0x324, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__CSU_CSU_INT_DEB	IOMUX_PAD(0x6B4, 0x324, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__ESDHC2_LCTL	IOMUX_PAD(0x6B4, 0x324, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__MLB_MLBSIG		IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, 0)
+#define _MX53_PAD_GPIO_2__ESAI1_FST		IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, 0)
+#define _MX53_PAD_GPIO_2__GPIO1_2		IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__KPP_ROW_6		IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, 0)
+#define _MX53_PAD_GPIO_2__CCM_CCM_OUT_1	IOMUX_PAD(0x6B8, 0x328, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0	IOMUX_PAD(0x6B8, 0x328, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__ESDHC2_WP		IOMUX_PAD(0x6B8, 0x328, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__MLB_MLBDAT	IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, 0)
+#define _MX53_PAD_GPIO_4__ESAI1_HCKT		IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, 0)
+#define _MX53_PAD_GPIO_4__GPIO1_4		IOMUX_PAD(0x6BC, 0x32C, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__KPP_COL_7		IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, 0)
+#define _MX53_PAD_GPIO_4__CCM_CCM_OUT_2	IOMUX_PAD(0x6BC, 0x32C, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1	IOMUX_PAD(0x6BC, 0x32C, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__ESDHC2_CD		IOMUX_PAD(0x6BC, 0x32C, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__SCC_SEC_STATE	IOMUX_PAD(0x6BC, 0x32C, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__ESAI1_TX2_RX3	IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, 0)
+#define _MX53_PAD_GPIO_5__GPIO1_5		IOMUX_PAD(0x6C0, 0x330, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__KPP_ROW_7		IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, 0)
+#define _MX53_PAD_GPIO_5__CCM_CLKO		IOMUX_PAD(0x6C0, 0x330, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2	IOMUX_PAD(0x6C0, 0x330, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__I2C3_SCL		IOMUX_PAD(0x6C0, 0x330, 6, 0x824, 2, 0)
+#define _MX53_PAD_GPIO_5__CCM_PLL1_BYP	IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, 0)
+#define _MX53_PAD_GPIO_7__ESAI1_TX4_RX1	IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, 0)
+#define _MX53_PAD_GPIO_7__GPIO1_7		IOMUX_PAD(0x6C4, 0x334, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__EPIT1_EPITO	IOMUX_PAD(0x6C4, 0x334, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__CAN1_TXCAN	IOMUX_PAD(0x6C4, 0x334, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__UART2_TXD_MUX	IOMUX_PAD(0x6C4, 0x334, 4, 0x880, 4, 0)
+#define _MX53_PAD_GPIO_7__FIRI_RXD		IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, 0)
+#define _MX53_PAD_GPIO_7__SPDIF_PLOCK	IOMUX_PAD(0x6C4, 0x334, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__CCM_PLL2_BYP	IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, 0)
+#define _MX53_PAD_GPIO_8__ESAI1_TX5_RX0	IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, 0)
+#define _MX53_PAD_GPIO_8__GPIO1_8		IOMUX_PAD(0x6C8, 0x338, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__EPIT2_EPITO	IOMUX_PAD(0x6C8, 0x338, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__CAN1_RXCAN	IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, 0)
+#define _MX53_PAD_GPIO_8__UART2_RXD_MUX	IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, 0)
+#define _MX53_PAD_GPIO_8__FIRI_TXD		IOMUX_PAD(0x6C8, 0x338, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__SPDIF_SRCLK	IOMUX_PAD(0x6C8, 0x338, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__CCM_PLL3_BYP	IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, 0)
+#define _MX53_PAD_GPIO_16__ESAI1_TX3_RX2	IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, 0)
+#define _MX53_PAD_GPIO_16__GPIO7_11		IOMUX_PAD(0x6CC, 0x33C, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT	IOMUX_PAD(0x6CC, 0x33C, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1	IOMUX_PAD(0x6CC, 0x33C, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_16__SPDIF_IN1		IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, 0)
+#define _MX53_PAD_GPIO_16__I2C3_SDA		IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, 0)
+#define _MX53_PAD_GPIO_16__SJC_DE_B		IOMUX_PAD(0x6CC, 0x33C, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__ESAI1_TX0		IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, 0)
+#define _MX53_PAD_GPIO_17__GPIO7_12		IOMUX_PAD(0x6D0, 0x340, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0	IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, 0)
+#define _MX53_PAD_GPIO_17__GPC_PMIC_RDY	IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, 0)
+#define _MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG	IOMUX_PAD(0x6D0, 0x340, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__SPDIF_OUT1	IOMUX_PAD(0x6D0, 0x340, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__IPU_SNOOP2	IOMUX_PAD(0x6D0, 0x340, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__SJC_JTAG_ACT	IOMUX_PAD(0x6D0, 0x340, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__ESAI1_TX1		IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, 0)
+#define _MX53_PAD_GPIO_18__GPIO7_13		IOMUX_PAD(0x6D4, 0x344, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1	IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, 0)
+#define _MX53_PAD_GPIO_18__OWIRE_LINE	IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, 0)
+#define _MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, 0)
+#define _MX53_PAD_GPIO_18__ESDHC1_LCTL	IOMUX_PAD(0x6D4, 0x344, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__SRC_SYSTEM_RST	IOMUX_PAD(0x6D4, 0x344, 7, 0x0, 0, 0)
 
-#define MX53_PAD_GPIO_19__GPIO_4_5		IOMUX_PAD(0x348, 0x20,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__GPIO_4_6		IOMUX_PAD(0x34C, 0x24,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__GPIO_4_7		IOMUX_PAD(0x350, 0x28,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__GPIO_4_8		IOMUX_PAD(0x354, 0x2C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__GPIO_4_9		IOMUX_PAD(0x358, 0x30,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__GPIO_4_10		IOMUX_PAD(0x35C, 0x34,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__GPIO_4_11	IOMUX_PAD(0x360, 0x38,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__GPIO_4_12		IOMUX_PAD(0x364, 0x3C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__GPIO_4_13	IOMUX_PAD(0x368, 0x40,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__GPIO_4_14		IOMUX_PAD(0x36C, 0x44,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__GPIO_4_15	IOMUX_PAD(0x370, 0x48,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_KEYPAD__NVCC_KEYPAD	IOMUX_PAD(0x374, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__GPIO_4_16	IOMUX_PAD(0x378, 0x4C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__GPIO_4_17	IOMUX_PAD(0x37C, 0x50,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__GPIO_4_18		IOMUX_PAD(0x380, 0x54,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__GPIO_4_19		IOMUX_PAD(0x384, 0x58,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__GPIO_4_20		IOMUX_PAD(0x388, 0x5C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__GPIO_4_21	IOMUX_PAD(0x38C, 0x60,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__GPIO_4_22	IOMUX_PAD(0x390, 0x64,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__GPIO_4_23	IOMUX_PAD(0x394, 0x68,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__GPIO_4_24	IOMUX_PAD(0x398, 0x6C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__GPIO_4_25	IOMUX_PAD(0x39C, 0x70,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__GPIO_4_26	IOMUX_PAD(0x3A0, 0x74,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__GPIO_4_27	IOMUX_PAD(0x3A4, 0x78,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__GPIO_4_28	IOMUX_PAD(0x3A8, 0x7C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__GPIO_4_29	IOMUX_PAD(0x3AC, 0x80,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__GPIO_4_30	IOMUX_PAD(0x3B0, 0x84,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__GPIO_4_31	IOMUX_PAD(0x3B4, 0x88,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__GPIO_5_5	IOMUX_PAD(0x3B8, 0x8C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__GPIO_5_6	IOMUX_PAD(0x3BC, 0x90,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__GPIO_5_7	IOMUX_PAD(0x3C0, 0x94,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__GPIO_5_8	IOMUX_PAD(0x3C4, 0x98,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__GPIO_5_9	IOMUX_PAD(0x3C8, 0x9C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__GPIO_5_10	IOMUX_PAD(0x3CC, 0xA0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__GPIO_5_11	IOMUX_PAD(0x3D0, 0xA4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__GPIO_5_12	IOMUX_PAD(0x3D4, 0xA8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__GPIO_5_13	IOMUX_PAD(0x3D8, 0xAC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__GPIO_5_14	IOMUX_PAD(0x3DC, 0xB0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__GPIO_5_15	IOMUX_PAD(0x3E0, 0xB4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__GPIO_5_16	IOMUX_PAD(0x3E4, 0xB8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__GPIO_5_17	IOMUX_PAD(0x3E8, 0xBC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_PIXCLK__GPIO_5_18	IOMUX_PAD(0x3EC, 0xC0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__GPIO_5_19	IOMUX_PAD(0x3F0, 0xC4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__GPIO_5_20	IOMUX_PAD(0x3F4, 0xC8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__GPIO_5_21	IOMUX_PAD(0x3F8, 0xCC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D4__GPIO_5_22		IOMUX_PAD(0x3FC, 0xD0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D5__GPIO_5_23		IOMUX_PAD(0x400, 0xD4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D6__GPIO_5_24		IOMUX_PAD(0x404, 0xD8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D7__GPIO_5_25		IOMUX_PAD(0x408, 0xDC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D8__GPIO_5_26		IOMUX_PAD(0x40C, 0xE0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D9__GPIO_5_27		IOMUX_PAD(0x410, 0xE4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D10__GPIO_5_28		IOMUX_PAD(0x414, 0xE8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D11__GPIO_5_29		IOMUX_PAD(0x418, 0xEC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D12__GPIO_5_30		IOMUX_PAD(0x41C, 0xF0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D13__GPIO_5_31		IOMUX_PAD(0x420, 0xF4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D14__GPIO_6_0		IOMUX_PAD(0x424, 0xF8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D15__GPIO_6_1		IOMUX_PAD(0x428, 0xFC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D16__GPIO_6_2		IOMUX_PAD(0x42C, 0x100,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D17__GPIO_6_3		IOMUX_PAD(0x430, 0x104,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D18__GPIO_6_4		IOMUX_PAD(0x434, 0x108,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D19__GPIO_6_5		IOMUX_PAD(0x438, 0x10C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_CSI0__NVCC_CSI0	IOMUX_PAD(0x43C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TMS__JTAG_TMS		IOMUX_PAD(0x440, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_MOD__JTAG_MOD		IOMUX_PAD(0x444, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TRSTB__JTAG_TRSTB	IOMUX_PAD(0x448, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TDI__JTAG_TDI		IOMUX_PAD(0x44C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TCK__JTAG_TCK		IOMUX_PAD(0x450, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TDO__JTAG_TDO		IOMUX_PAD(0x454, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__GPIO_5_2		IOMUX_PAD(0x458, 0x110,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__GPIO_2_30		IOMUX_PAD(0x45C, 0x114,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__GPIO_3_16		IOMUX_PAD(0x460, 0x118,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__GPIO_3_17		IOMUX_PAD(0x464, 0x11C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__GPIO_3_18		IOMUX_PAD(0x468, 0x120,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__CSPI1_SCLK		IOMUX_PAD(0x460, 0x118,IOMUX_CONFIG_ALT4, 0x79c, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__CSPI1_MISO		IOMUX_PAD(0x464, 0x11C,IOMUX_CONFIG_ALT4, 0x7a0, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__CSPI1_MOSI		IOMUX_PAD(0x468, 0x120,IOMUX_CONFIG_ALT4, 0x7a4, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__GPIO_3_19		IOMUX_PAD(0x46C, 0x124,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__GPIO_3_20		IOMUX_PAD(0x470, 0x128,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__GPIO_3_21		IOMUX_PAD(0x474, 0x12C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__GPIO_3_22		IOMUX_PAD(0x478, 0x130,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__GPIO_3_23		IOMUX_PAD(0x47C, 0x134,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__GPIO_2_31		IOMUX_PAD(0x480, 0x138,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__GPIO_3_24		IOMUX_PAD(0x484, 0x13C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__GPIO_3_25		IOMUX_PAD(0x488, 0x140,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__GPIO_3_26		IOMUX_PAD(0x48C, 0x144,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__GPIO_3_27		IOMUX_PAD(0x490, 0x148,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__GPIO_3_28		IOMUX_PAD(0x494, 0x14C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__GPIO_3_29		IOMUX_PAD(0x498, 0x150,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__GPIO_3_30		IOMUX_PAD(0x49C, 0x154,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__GPIO_3_31		IOMUX_PAD(0x4A0, 0x158,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_EIM1__NVCC_EIM1	IOMUX_PAD(0x4A4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__GPIO_5_4		IOMUX_PAD(0x4A8, 0x15C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__GPIO_6_6		IOMUX_PAD(0x4AC, 0x160,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__GPIO_2_16		IOMUX_PAD(0x4B0, 0x164,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__GPIO_2_17		IOMUX_PAD(0x4B4, 0x168,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__GPIO_2_18		IOMUX_PAD(0x4B8, 0x16C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__GPIO_2_19		IOMUX_PAD(0x4BC, 0x170,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__GPIO_2_20		IOMUX_PAD(0x4C0, 0x174,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__GPIO_2_21		IOMUX_PAD(0x4C4, 0x178,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__GPIO_2_22		IOMUX_PAD(0x4C8, 0x17C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS0__GPIO_2_23		IOMUX_PAD(0x4CC, 0x180,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS1__GPIO_2_24		IOMUX_PAD(0x4D0, 0x184,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__GPIO_2_25		IOMUX_PAD(0x4D4, 0x188,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__GPIO_2_26		IOMUX_PAD(0x4D8, 0x18C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__GPIO_2_27		IOMUX_PAD(0x4DC, 0x190,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_EIM4__NVCC_EIM4	IOMUX_PAD(0x4E0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__GPIO_2_28		IOMUX_PAD(0x4E4, 0x194,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__GPIO_2_29		IOMUX_PAD(0x4E8, 0x198,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__GPIO_3_0		IOMUX_PAD(0x4EC, 0x19C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__GPIO_3_1		IOMUX_PAD(0x4F0, 0x1A0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__GPIO_3_2		IOMUX_PAD(0x4F4, 0x1A4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__GPIO_3_3		IOMUX_PAD(0x4F8, 0x1A8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__GPIO_3_4		IOMUX_PAD(0x4FC, 0x1AC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__GPIO_3_5		IOMUX_PAD(0x500, 0x1B0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__GPIO_3_6		IOMUX_PAD(0x504, 0x1B4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__GPIO_3_7		IOMUX_PAD(0x508, 0x1B8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__GPIO_3_8		IOMUX_PAD(0x50C, 0x1BC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__GPIO_3_9		IOMUX_PAD(0x510, 0x1C0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__GPIO_3_10		IOMUX_PAD(0x514, 0x1C4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA11__GPIO_3_11		IOMUX_PAD(0x518, 0x1C8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA12__GPIO_3_12		IOMUX_PAD(0x51C, 0x1CC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA13__GPIO_3_13		IOMUX_PAD(0x520, 0x1D0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA14__GPIO_3_14		IOMUX_PAD(0x524, 0x1D4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA15__GPIO_3_15		IOMUX_PAD(0x528, 0x1D8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WE_B__GPIO_6_12	IOMUX_PAD(0x52C, 0x1DC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RE_B__GPIO_6_13	IOMUX_PAD(0x530, 0x1E0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_WAIT__GPIO_5_0		IOMUX_PAD(0x534, 0x1E4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_BCLK__EIM_BCLK		IOMUX_PAD(0x538, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_EIM7__NVCC_EIM7	IOMUX_PAD(0x53C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX3_P__GPIO_6_22	IOMUX_PAD(NON_PAD_I, 0x1EC, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX2_P__GPIO_6_24	IOMUX_PAD(NON_PAD_I, 0x1F0, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_CLK_P__GPIO_6_26	IOMUX_PAD(NON_PAD_I, 0x1F4, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX1_P__GPIO_6_28	IOMUX_PAD(NON_PAD_I, 0x1F8, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX0_P__GPIO_6_30	IOMUX_PAD(NON_PAD_I, 0x1FC, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX3_P__GPIO_7_22	IOMUX_PAD(NON_PAD_I, 0x200, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_CLK_P__GPIO_7_24	IOMUX_PAD(NON_PAD_I, 0x204, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX2_P__GPIO_7_26	IOMUX_PAD(NON_PAD_I, 0x208, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX1_P__GPIO_7_28	IOMUX_PAD(NON_PAD_I, 0x20C, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX0_P__GPIO_7_30	IOMUX_PAD(NON_PAD_I, 0x210, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_10__GPIO_4_0		IOMUX_PAD(0x540, 0x214, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_11__GPIO_4_1		IOMUX_PAD(0x544, 0x218, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_12__GPIO_4_2		IOMUX_PAD(0x548, 0x21C, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_13__GPIO_4_3		IOMUX_PAD(0x54C, 0x220, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_14__GPIO_4_4		IOMUX_PAD(0x550, 0x224, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM3__DRAM_DQM3	IOMUX_PAD(0x554, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS3__DRAM_SDQS3	IOMUX_PAD(0x558, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCKE1__DRAM_SDCKE1	IOMUX_PAD(0x55C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM2__DRAM_DQM2	IOMUX_PAD(0x560, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDODT1__DRAM_SDODT1	IOMUX_PAD(0x564, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS2__DRAM_SDQS2	IOMUX_PAD(0x568, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_RESET__DRAM_RESET	IOMUX_PAD(0x56C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCLK1__DRAM_SDCLK1	IOMUX_PAD(0x570, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_CAS__DRAM_CAS		IOMUX_PAD(0x574, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCLK0__DRAM_SDCLK0	IOMUX_PAD(0x578, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS0__DRAM_SDQS0	IOMUX_PAD(0x57C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDODT0__DRAM_SDODT0	IOMUX_PAD(0x580, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM0__DRAM_DQM0	IOMUX_PAD(0x584, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_RAS__DRAM_RAS		IOMUX_PAD(0x588, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCKE0__DRAM_SDCKE0	IOMUX_PAD(0x58C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS1__DRAM_SDQS1	IOMUX_PAD(0x590, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM1__DRAM_DQM1	IOMUX_PAD(0x594, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x598, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x59C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CLE__GPIO_6_7		IOMUX_PAD(0x5A0, 0x228,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_ALE__GPIO_6_8	IOMUX_PAD(0x5A4, 0x22C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WP_B__GPIO_6_9	IOMUX_PAD(0x5A8, 0x230,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RB0__GPIO_6_10	IOMUX_PAD(0x5AC, 0x234,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS0__GPIO_6_11	IOMUX_PAD(0x5B0, 0x238,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS1__GPIO_6_14	IOMUX_PAD(0x5B4, 0x23C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__GPIO_6_15	IOMUX_PAD(0x5B8, 0x240,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__GPIO_6_16	IOMUX_PAD(0x5BC, 0x244,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_NANDF__NVCC_NANDF	IOMUX_PAD(0x5C0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__GPIO_1_22		IOMUX_PAD(0x5C4, 0x248,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__GPIO_1_23	IOMUX_PAD(0x5C8, 0x24C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__GPIO_1_24	IOMUX_PAD(0x5CC, 0x250,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_CRS_DV__GPIO_1_25	IOMUX_PAD(0x5D0, 0x254,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__GPIO_1_26		IOMUX_PAD(0x5D4, 0x258,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD0__GPIO_1_27		IOMUX_PAD(0x5D8, 0x25C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TX_EN__GPIO_1_28	IOMUX_PAD(0x5DC, 0x260,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__GPIO_1_29		IOMUX_PAD(0x5E0, 0x264,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD0__GPIO_1_30		IOMUX_PAD(0x5E4, 0x268,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__GPIO_1_31		IOMUX_PAD(0x5E8, 0x26C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_FEC__NVCC_FEC		IOMUX_PAD(0x5EC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DIOW__GPIO_6_17	IOMUX_PAD(0x5F0, 0x270,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DMACK__GPIO_6_18	IOMUX_PAD(0x5F4, 0x274,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DMARQ__GPIO_7_0	IOMUX_PAD(0x5F8, 0x278,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_BUFFER_EN__GPIO_7_1	IOMUX_PAD(0x5FC, 0x27C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_INTRQ__GPIO_7_2		IOMUX_PAD(0x600, 0x280,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DIOR__GPIO_7_3		IOMUX_PAD(0x604, 0x284,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_RESET_B__GPIO_7_4	IOMUX_PAD(0x608, 0x288,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_IORDY__GPIO_7_5		IOMUX_PAD(0x60C, 0x28C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DA_0__GPIO_7_6		IOMUX_PAD(0x610, 0x290,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DA_1__GPIO_7_7		IOMUX_PAD(0x614, 0x294,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DA_2__GPIO_7_8		IOMUX_PAD(0x618, 0x298,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_CS_0__GPIO_7_9		IOMUX_PAD(0x61C, 0x29C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_CS_1__GPIO_7_10		IOMUX_PAD(0x620, 0x2A0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_ATA2__NVCC_ATA2	IOMUX_PAD(0x624, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA0__GPIO_2_0	IOMUX_PAD(0x628, 0x2A4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA1__GPIO_2_1	IOMUX_PAD(0x62C, 0x2A8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA2__GPIO_2_2	IOMUX_PAD(0x630, 0x2AC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA3__GPIO_2_3	IOMUX_PAD(0x634, 0x2B0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA4__GPIO_2_4	IOMUX_PAD(0x638, 0x2B4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA5__GPIO_2_5	IOMUX_PAD(0x63C, 0x2B8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA6__GPIO_2_6	IOMUX_PAD(0x640, 0x2BC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA7__GPIO_2_7	IOMUX_PAD(0x644, 0x2C0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA8__GPIO_2_8	IOMUX_PAD(0x648, 0x2C4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA9__GPIO_2_9	IOMUX_PAD(0x64C, 0x2C8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA10__GPIO_2_10	IOMUX_PAD(0x650, 0x2CC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA11__GPIO_2_11	IOMUX_PAD(0x654, 0x2D0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA12__GPIO_2_12	IOMUX_PAD(0x658, 0x2D4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA13__GPIO_2_13	IOMUX_PAD(0x65C, 0x2D8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA14__GPIO_2_14	IOMUX_PAD(0x660, 0x2DC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA15__GPIO_2_15	IOMUX_PAD(0x664, 0x2E0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_ATA0__NVCC_ATA0	IOMUX_PAD(0x668, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__GPIO_1_16	IOMUX_PAD(0x66C, 0x2E4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__GPIO_1_17	IOMUX_PAD(0x670, 0x2E8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__GPIO_1_18		IOMUX_PAD(0x674, 0x2EC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__GPIO_1_19	IOMUX_PAD(0x678, 0x2F0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__GPIO_1_20		IOMUX_PAD(0x67C, 0x2F4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__GPIO_1_21	IOMUX_PAD(0x680, 0x2F8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_SD1__NVCC_SD1		IOMUX_PAD(0x684, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__GPIO_1_10		IOMUX_PAD(0x688, 0x2FC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__GPIO_1_11		IOMUX_PAD(0x68C, 0x300,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__GPIO_1_12	IOMUX_PAD(0x690, 0x304,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__GPIO_1_13	IOMUX_PAD(0x694, 0x308,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__GPIO_1_14	IOMUX_PAD(0x698, 0x30C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__GPIO_1_15	IOMUX_PAD(0x69C, 0x310,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_SD2__NVCC_SD2		IOMUX_PAD(0x6A0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__GPIO_1_0		IOMUX_PAD(0x6A4, 0x314,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__GPIO_1_1		IOMUX_PAD(0x6A8, 0x318,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__GPIO_1_9		IOMUX_PAD(0x6AC, 0x31C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__GPIO_1_3		IOMUX_PAD(0x6B0, 0x320,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__GPIO_1_6		IOMUX_PAD(0x6B4, 0x324,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__GPIO_1_2		IOMUX_PAD(0x6B8, 0x328,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__GPIO_1_4		IOMUX_PAD(0x6BC, 0x32C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__GPIO_1_5		IOMUX_PAD(0x6C0, 0x330,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__GPIO_1_7		IOMUX_PAD(0x6C4, 0x334,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__GPIO_1_8		IOMUX_PAD(0x6C8, 0x338,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__GPIO_7_11		IOMUX_PAD(0x6CC, 0x33C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__GPIO_7_12		IOMUX_PAD(0x6D0, 0x340,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__GPIO_7_13		IOMUX_PAD(0x6D4, 0x344,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_GPIO__NVCC_GPIO	IOMUX_PAD(0x6D8, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_POR_B__POR_B			IOMUX_PAD(0x6DC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_BOOT_MODE1__BOOT_MODE1	IOMUX_PAD(0x6E0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_RESET_IN_B__RESET_IN_B	IOMUX_PAD(0x6E4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_BOOT_MODE0__BOOT_MODE0	IOMUX_PAD(0x6E8, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_TEST_MODE__TEST_MODE	IOMUX_PAD(0x6EC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_ADDDS__GRP_ADDDS	IOMUX_PAD(0x6F0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRMODE_CTL__GRP_DDRMODE_CTL	IOMUX_PAD(0x6F4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRPKE__GRP_DDRPKE	IOMUX_PAD(0x6FC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRPK__GRP_DDRPK	IOMUX_PAD(0x708, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_TERM_CTL3__GRP_TERM_CTL3	IOMUX_PAD(0x70C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRHYS__GRP_DDRHYS	IOMUX_PAD(0x710, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRMODE__GRP_DDRMODE	IOMUX_PAD(0x714, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B0DS__GRP_B0DS		IOMUX_PAD(0x718, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B1DS__GRP_B1DS		IOMUX_PAD(0x71C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_CTLDS__GRP_CTLDS	IOMUX_PAD(0x720, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDR_TYPE__GRP_DDR_TYPE	IOMUX_PAD(0x724, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B2DS__GRP_B2DS		IOMUX_PAD(0x728, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B3DS__GRP_B3DS		IOMUX_PAD(0x72C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__KPP_COL_5		(_MX53_PAD_GPIO_19__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__GPIO4_5		(_MX53_PAD_GPIO_19__GPIO4_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__CCM_CLKO		(_MX53_PAD_GPIO_19__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__SPDIF_OUT1		(_MX53_PAD_GPIO_19__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		(_MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__ECSPI1_RDY		(_MX53_PAD_GPIO_19__ECSPI1_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__FEC_TDATA_3		(_MX53_PAD_GPIO_19__FEC_TDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT		(_MX53_PAD_GPIO_19__SRC_INT_BOOT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__KPP_COL_0		(_MX53_PAD_KEY_COL0__KPP_COL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__GPIO4_6		(_MX53_PAD_KEY_COL0__GPIO4_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		(_MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		(_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK		(_MX53_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3		(_MX53_PAD_KEY_COL0__FEC_RDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		(_MX53_PAD_KEY_COL0__SRC_ANY_PU_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0		(_MX53_PAD_KEY_ROW0__KPP_ROW_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__GPIO4_7		(_MX53_PAD_KEY_ROW0__GPIO4_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		(_MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		(_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI		(_MX53_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER		(_MX53_PAD_KEY_ROW0__FEC_TX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__KPP_COL_1		(_MX53_PAD_KEY_COL1__KPP_COL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__GPIO4_8		(_MX53_PAD_KEY_COL1__GPIO4_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		(_MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		(_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO		(_MX53_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK		(_MX53_PAD_KEY_COL1__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		(_MX53_PAD_KEY_COL1__USBPHY1_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1		(_MX53_PAD_KEY_ROW1__KPP_ROW_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__GPIO4_9		(_MX53_PAD_KEY_ROW1__GPIO4_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		(_MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		(_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0		(_MX53_PAD_KEY_ROW1__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__FEC_COL		(_MX53_PAD_KEY_ROW1__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		(_MX53_PAD_KEY_ROW1__USBPHY1_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__KPP_COL_2		(_MX53_PAD_KEY_COL2__KPP_COL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__GPIO4_10		(_MX53_PAD_KEY_COL2__GPIO4_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN		(_MX53_PAD_KEY_COL2__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__FEC_MDIO		(_MX53_PAD_KEY_COL2__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1		(_MX53_PAD_KEY_COL2__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2		(_MX53_PAD_KEY_COL2__FEC_RDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		(_MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2		(_MX53_PAD_KEY_ROW2__KPP_ROW_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__GPIO4_11		(_MX53_PAD_KEY_ROW2__GPIO4_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN		(_MX53_PAD_KEY_ROW2__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__FEC_MDC		(_MX53_PAD_KEY_ROW2__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2		(_MX53_PAD_KEY_ROW2__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2		(_MX53_PAD_KEY_ROW2__FEC_TDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		(_MX53_PAD_KEY_ROW2__USBPHY1_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__KPP_COL_3		(_MX53_PAD_KEY_COL3__KPP_COL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__GPIO4_12		(_MX53_PAD_KEY_COL3__GPIO4_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP		(_MX53_PAD_KEY_COL3__USBOH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__SPDIF_IN1		(_MX53_PAD_KEY_COL3__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__I2C2_SCL		(_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3		(_MX53_PAD_KEY_COL3__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__FEC_CRS		(_MX53_PAD_KEY_COL3__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		(_MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3		(_MX53_PAD_KEY_ROW3__KPP_ROW_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__GPIO4_13		(_MX53_PAD_KEY_ROW3__GPIO4_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM		(_MX53_PAD_KEY_ROW3__USBOH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		(_MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__I2C2_SDA		(_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		(_MX53_PAD_KEY_ROW3__OSC32K_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP		(_MX53_PAD_KEY_ROW3__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		(_MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__KPP_COL_4		(_MX53_PAD_KEY_COL4__KPP_COL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__GPIO4_14		(_MX53_PAD_KEY_COL4__GPIO4_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN		(_MX53_PAD_KEY_COL4__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__IPU_SISG_4		(_MX53_PAD_KEY_COL4__IPU_SISG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__UART5_RTS		(_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		(_MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		(_MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4		(_MX53_PAD_KEY_ROW4__KPP_ROW_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__GPIO4_15		(_MX53_PAD_KEY_ROW4__GPIO4_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN		(_MX53_PAD_KEY_ROW4__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5		(_MX53_PAD_KEY_ROW4__IPU_SISG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__UART5_CTS		(_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		(_MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		(_MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		(_MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16		(_MX53_PAD_DI0_DISP_CLK__GPIO4_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		(_MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0		(_MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		(_MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		(_MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		(_MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__GPIO4_17		(_MX53_PAD_DI0_PIN15__GPIO4_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		(_MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1		(_MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		(_MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		(_MX53_PAD_DI0_PIN15__USBPHY1_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		(_MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__GPIO4_18		(_MX53_PAD_DI0_PIN2__GPIO4_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		(_MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2		(_MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		(_MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		(_MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		(_MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__GPIO4_19		(_MX53_PAD_DI0_PIN3__GPIO4_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		(_MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3		(_MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		(_MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		(_MX53_PAD_DI0_PIN3__USBPHY1_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		(_MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__GPIO4_20		(_MX53_PAD_DI0_PIN4__GPIO4_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		(_MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP		(_MX53_PAD_DI0_PIN4__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		(_MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		(_MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT		(_MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		(_MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__GPIO4_21		(_MX53_PAD_DISP0_DAT0__GPIO4_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK		(_MX53_PAD_DISP0_DAT0__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0		(_MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN		(_MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		(_MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		(_MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		(_MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__GPIO4_22		(_MX53_PAD_DISP0_DAT1__GPIO4_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI		(_MX53_PAD_DISP0_DAT1__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1		(_MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL		(_MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		(_MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		(_MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		(_MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__GPIO4_23		(_MX53_PAD_DISP0_DAT2__GPIO4_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO		(_MX53_PAD_DISP0_DAT2__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2		(_MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		(_MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		(_MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		(_MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		(_MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__GPIO4_24		(_MX53_PAD_DISP0_DAT3__GPIO4_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0		(_MX53_PAD_DISP0_DAT3__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3		(_MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR		(_MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		(_MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		(_MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		(_MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__GPIO4_25		(_MX53_PAD_DISP0_DAT4__GPIO4_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1		(_MX53_PAD_DISP0_DAT4__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4		(_MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		(_MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		(_MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		(_MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		(_MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__GPIO4_26		(_MX53_PAD_DISP0_DAT5__GPIO4_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2		(_MX53_PAD_DISP0_DAT5__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5		(_MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS		(_MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		(_MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0		(_MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		(_MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__GPIO4_27		(_MX53_PAD_DISP0_DAT6__GPIO4_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3		(_MX53_PAD_DISP0_DAT6__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6		(_MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE		(_MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		(_MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1		(_MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		(_MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__GPIO4_28		(_MX53_PAD_DISP0_DAT7__GPIO4_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY		(_MX53_PAD_DISP0_DAT7__CSPI_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7		(_MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0		(_MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		(_MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		(_MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		(_MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__GPIO4_29		(_MX53_PAD_DISP0_DAT8__GPIO4_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO		(_MX53_PAD_DISP0_DAT8__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		(_MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1		(_MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		(_MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		(_MX53_PAD_DISP0_DAT8__USBPHY2_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		(_MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__GPIO4_30		(_MX53_PAD_DISP0_DAT9__GPIO4_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO		(_MX53_PAD_DISP0_DAT9__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		(_MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		(_MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		(_MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		(_MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		(_MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__GPIO4_31		(_MX53_PAD_DISP0_DAT10__GPIO4_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		(_MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3		(_MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		(_MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		(_MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		(_MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__GPIO5_5		(_MX53_PAD_DISP0_DAT11__GPIO5_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		(_MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4		(_MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		(_MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		(_MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		(_MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__GPIO5_6		(_MX53_PAD_DISP0_DAT12__GPIO5_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		(_MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5		(_MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		(_MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		(_MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		(_MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__GPIO5_7		(_MX53_PAD_DISP0_DAT13__GPIO5_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		(_MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0		(_MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		(_MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		(_MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		(_MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__GPIO5_8		(_MX53_PAD_DISP0_DAT14__GPIO5_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		(_MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1		(_MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		(_MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		(_MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		(_MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__GPIO5_9		(_MX53_PAD_DISP0_DAT15__GPIO5_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2		(_MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		(_MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		(_MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		(_MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__GPIO5_10		(_MX53_PAD_DISP0_DAT16__GPIO5_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		(_MX53_PAD_DISP0_DAT16__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		(_MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		(_MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3		(_MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		(_MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		(_MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		(_MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__GPIO5_11		(_MX53_PAD_DISP0_DAT17__GPIO5_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		(_MX53_PAD_DISP0_DAT17__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		(_MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		(_MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4		(_MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		(_MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		(_MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__GPIO5_12		(_MX53_PAD_DISP0_DAT18__GPIO5_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		(_MX53_PAD_DISP0_DAT18__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5		(_MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		(_MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		(_MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		(_MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__GPIO5_13		(_MX53_PAD_DISP0_DAT19__GPIO5_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		(_MX53_PAD_DISP0_DAT19__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6		(_MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		(_MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		(_MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		(_MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__GPIO5_14		(_MX53_PAD_DISP0_DAT20__GPIO5_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		(_MX53_PAD_DISP0_DAT20__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		(_MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7		(_MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		(_MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		(_MX53_PAD_DISP0_DAT20__SATA_PHY_TDI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		(_MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__GPIO5_15		(_MX53_PAD_DISP0_DAT21__GPIO5_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		(_MX53_PAD_DISP0_DAT21__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		(_MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0		(_MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		(_MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		(_MX53_PAD_DISP0_DAT21__SATA_PHY_TDO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		(_MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__GPIO5_16		(_MX53_PAD_DISP0_DAT22__GPIO5_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		(_MX53_PAD_DISP0_DAT22__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		(_MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1		(_MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		(_MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		(_MX53_PAD_DISP0_DAT22__SATA_PHY_TCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		(_MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__GPIO5_17		(_MX53_PAD_DISP0_DAT23__GPIO5_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		(_MX53_PAD_DISP0_DAT23__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		(_MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2		(_MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		(_MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		(_MX53_PAD_DISP0_DAT23__SATA_PHY_TMS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		(_MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18		(_MX53_PAD_CSI0_PIXCLK__GPIO5_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		(_MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		(_MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		(_MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__GPIO5_19		(_MX53_PAD_CSI0_MCLK__GPIO5_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		(_MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		(_MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		(_MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL		(_MX53_PAD_CSI0_MCLK__TPIU_TRCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		(_MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20		(_MX53_PAD_CSI0_DATA_EN__GPIO5_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		(_MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		(_MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		(_MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		(_MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21		(_MX53_PAD_CSI0_VSYNC__GPIO5_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		(_MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		(_MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		(_MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		(_MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__GPIO5_22		(_MX53_PAD_CSI0_DAT4__GPIO5_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5		(_MX53_PAD_CSI0_DAT4__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		(_MX53_PAD_CSI0_DAT4__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		(_MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		(_MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		(_MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		(_MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		(_MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__GPIO5_23		(_MX53_PAD_CSI0_DAT5__GPIO5_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5		(_MX53_PAD_CSI0_DAT5__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		(_MX53_PAD_CSI0_DAT5__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		(_MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		(_MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		(_MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		(_MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		(_MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__GPIO5_24		(_MX53_PAD_CSI0_DAT6__GPIO5_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6		(_MX53_PAD_CSI0_DAT6__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO		(_MX53_PAD_CSI0_DAT6__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		(_MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		(_MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		(_MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		(_MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		(_MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__GPIO5_25		(_MX53_PAD_CSI0_DAT7__GPIO5_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6		(_MX53_PAD_CSI0_DAT7__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0		(_MX53_PAD_CSI0_DAT7__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		(_MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		(_MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		(_MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		(_MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		(_MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__GPIO5_26		(_MX53_PAD_CSI0_DAT8__GPIO5_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7		(_MX53_PAD_CSI0_DAT8__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		(_MX53_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		(_MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA		(_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		(_MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		(_MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		(_MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__GPIO5_27		(_MX53_PAD_CSI0_DAT9__GPIO5_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7		(_MX53_PAD_CSI0_DAT9__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		(_MX53_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		(_MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL		(_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		(_MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		(_MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		(_MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__GPIO5_28		(_MX53_PAD_CSI0_DAT10__GPIO5_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		(_MX53_PAD_CSI0_DAT10__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		(_MX53_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		(_MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		(_MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		(_MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		(_MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		(_MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__GPIO5_29		(_MX53_PAD_CSI0_DAT11__GPIO5_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		(_MX53_PAD_CSI0_DAT11__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0		(_MX53_PAD_CSI0_DAT11__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		(_MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		(_MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		(_MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		(_MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		(_MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__GPIO5_30		(_MX53_PAD_CSI0_DAT12__GPIO5_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		(_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		(_MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		(_MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		(_MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		(_MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		(_MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__GPIO5_31		(_MX53_PAD_CSI0_DAT13__GPIO5_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		(_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		(_MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		(_MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		(_MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		(_MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		(_MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__GPIO6_0		(_MX53_PAD_CSI0_DAT14__GPIO6_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		(_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		(_MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		(_MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		(_MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		(_MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		(_MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__GPIO6_1		(_MX53_PAD_CSI0_DAT15__GPIO6_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		(_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		(_MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		(_MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		(_MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		(_MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		(_MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__GPIO6_2		(_MX53_PAD_CSI0_DAT16__GPIO6_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__UART4_RTS		(_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		(_MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		(_MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		(_MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		(_MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		(_MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__GPIO6_3		(_MX53_PAD_CSI0_DAT17__GPIO6_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__UART4_CTS		(_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		(_MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		(_MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		(_MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		(_MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		(_MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__GPIO6_4		(_MX53_PAD_CSI0_DAT18__GPIO6_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__UART5_RTS		(_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		(_MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		(_MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		(_MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		(_MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		(_MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__GPIO6_5		(_MX53_PAD_CSI0_DAT19__GPIO6_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__UART5_CTS		(_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		(_MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		(_MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		(_MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		(_MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25		(_MX53_PAD_EIM_A25__EMI_WEIM_A_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__GPIO5_2		(_MX53_PAD_EIM_A25__GPIO5_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__ECSPI2_RDY		(_MX53_PAD_EIM_A25__ECSPI2_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12		(_MX53_PAD_EIM_A25__IPU_DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__CSPI_SS1		(_MX53_PAD_EIM_A25__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS		(_MX53_PAD_EIM_A25__IPU_DI0_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		(_MX53_PAD_EIM_A25__USBPHY1_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		(_MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__GPIO2_30		(_MX53_PAD_EIM_EB2__GPIO2_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		(_MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0		(_MX53_PAD_EIM_EB2__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__I2C2_SCL		(_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16		(_MX53_PAD_EIM_D16__EMI_WEIM_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__GPIO3_16		(_MX53_PAD_EIM_D16__GPIO3_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5		(_MX53_PAD_EIM_D16__IPU_DI0_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		(_MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK		(_MX53_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__I2C2_SDA		(_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17		(_MX53_PAD_EIM_D17__EMI_WEIM_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__GPIO3_17		(_MX53_PAD_EIM_D17__GPIO3_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6		(_MX53_PAD_EIM_D17__IPU_DI0_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		(_MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__ECSPI1_MISO		(_MX53_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__I2C3_SCL		(_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18		(_MX53_PAD_EIM_D18__EMI_WEIM_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__GPIO3_18		(_MX53_PAD_EIM_D18__GPIO3_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7		(_MX53_PAD_EIM_D18__IPU_DI0_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		(_MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI		(_MX53_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__I2C3_SDA		(_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS		(_MX53_PAD_EIM_D18__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19		(_MX53_PAD_EIM_D19__EMI_WEIM_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__GPIO3_19		(_MX53_PAD_EIM_D19__GPIO3_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8		(_MX53_PAD_EIM_D19__IPU_DI0_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		(_MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__ECSPI1_SS1		(_MX53_PAD_EIM_D19__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__EPIT1_EPITO		(_MX53_PAD_EIM_D19__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__UART1_CTS		(_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D19__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20		(_MX53_PAD_EIM_D20__EMI_WEIM_D_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__GPIO3_20		(_MX53_PAD_EIM_D20__GPIO3_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16		(_MX53_PAD_EIM_D20__IPU_DI0_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		(_MX53_PAD_EIM_D20__IPU_SER_DISP0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__CSPI_SS0		(_MX53_PAD_EIM_D20__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__EPIT2_EPITO		(_MX53_PAD_EIM_D20__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__UART1_RTS		(_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D20__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21		(_MX53_PAD_EIM_D21__EMI_WEIM_D_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__GPIO3_21		(_MX53_PAD_EIM_D21__GPIO3_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17		(_MX53_PAD_EIM_D21__IPU_DI0_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		(_MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__CSPI_SCLK		(_MX53_PAD_EIM_D21__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__I2C1_SCL		(_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		(_MX53_PAD_EIM_D21__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22		(_MX53_PAD_EIM_D22__EMI_WEIM_D_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__GPIO3_22		(_MX53_PAD_EIM_D22__GPIO3_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1		(_MX53_PAD_EIM_D22__IPU_DI0_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		(_MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__CSPI_MISO		(_MX53_PAD_EIM_D22__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		(_MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23		(_MX53_PAD_EIM_D23__EMI_WEIM_D_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__GPIO3_23		(_MX53_PAD_EIM_D23__GPIO3_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__UART3_CTS		(_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__UART1_DCD		(_MX53_PAD_EIM_D23__UART1_DCD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS		(_MX53_PAD_EIM_D23__IPU_DI0_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2		(_MX53_PAD_EIM_D23__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14		(_MX53_PAD_EIM_D23__IPU_DI1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		(_MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__GPIO2_31		(_MX53_PAD_EIM_EB3__GPIO2_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__UART3_RTS		(_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__UART1_RI		(_MX53_PAD_EIM_EB3__UART1_RI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24		(_MX53_PAD_EIM_D24__EMI_WEIM_D_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__GPIO3_24		(_MX53_PAD_EIM_D24__GPIO3_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX		(_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__ECSPI1_SS2		(_MX53_PAD_EIM_D24__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__CSPI_SS2		(_MX53_PAD_EIM_D24__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		(_MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__ECSPI2_SS2		(_MX53_PAD_EIM_D24__ECSPI2_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__UART1_DTR		(_MX53_PAD_EIM_D24__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25		(_MX53_PAD_EIM_D25__EMI_WEIM_D_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__GPIO3_25		(_MX53_PAD_EIM_D25__GPIO3_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX		(_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__ECSPI1_SS3		(_MX53_PAD_EIM_D25__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__CSPI_SS3		(_MX53_PAD_EIM_D25__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		(_MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__ECSPI2_SS3		(_MX53_PAD_EIM_D25__ECSPI2_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__UART1_DSR		(_MX53_PAD_EIM_D25__UART1_DSR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26		(_MX53_PAD_EIM_D26__EMI_WEIM_D_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__GPIO3_26		(_MX53_PAD_EIM_D26__GPIO3_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX		(_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__FIRI_RXD		(_MX53_PAD_EIM_D26__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1		(_MX53_PAD_EIM_D26__IPU_CSI0_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11		(_MX53_PAD_EIM_D26__IPU_DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_SISG_2		(_MX53_PAD_EIM_D26__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		(_MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27		(_MX53_PAD_EIM_D27__EMI_WEIM_D_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__GPIO3_27		(_MX53_PAD_EIM_D27__GPIO3_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX		(_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__FIRI_TXD		(_MX53_PAD_EIM_D27__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0		(_MX53_PAD_EIM_D27__IPU_CSI0_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13		(_MX53_PAD_EIM_D27__IPU_DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_SISG_3		(_MX53_PAD_EIM_D27__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		(_MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28		(_MX53_PAD_EIM_D28__EMI_WEIM_D_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__GPIO3_28		(_MX53_PAD_EIM_D28__GPIO3_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__UART2_CTS		(_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		(_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__CSPI_MOSI		(_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__I2C1_SDA		(_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG		(_MX53_PAD_EIM_D28__IPU_EXT_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13		(_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29		(_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__GPIO3_29		(_MX53_PAD_EIM_D29__GPIO3_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__UART2_RTS		(_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		(_MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__CSPI_SS0		(_MX53_PAD_EIM_D29__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15		(_MX53_PAD_EIM_D29__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_D29__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14		(_MX53_PAD_EIM_D29__IPU_DI0_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30		(_MX53_PAD_EIM_D30__EMI_WEIM_D_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__GPIO3_30		(_MX53_PAD_EIM_D30__GPIO3_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__UART3_CTS		(_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3		(_MX53_PAD_EIM_D30__IPU_CSI0_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11		(_MX53_PAD_EIM_D30__IPU_DI0_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		(_MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31		(_MX53_PAD_EIM_D31__EMI_WEIM_D_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__GPIO3_31		(_MX53_PAD_EIM_D31__GPIO3_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__UART3_RTS		(_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2		(_MX53_PAD_EIM_D31__IPU_CSI0_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12		(_MX53_PAD_EIM_D31__IPU_DI0_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		(_MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24		(_MX53_PAD_EIM_A24__EMI_WEIM_A_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__GPIO5_4		(_MX53_PAD_EIM_A24__GPIO5_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		(_MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19		(_MX53_PAD_EIM_A24__IPU_CSI1_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__IPU_SISG_2		(_MX53_PAD_EIM_A24__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID		(_MX53_PAD_EIM_A24__USBPHY2_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23		(_MX53_PAD_EIM_A23__EMI_WEIM_A_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__GPIO6_6		(_MX53_PAD_EIM_A23__GPIO6_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		(_MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18		(_MX53_PAD_EIM_A23__IPU_CSI1_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__IPU_SISG_3		(_MX53_PAD_EIM_A23__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		(_MX53_PAD_EIM_A23__USBPHY2_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22		(_MX53_PAD_EIM_A22__EMI_WEIM_A_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__GPIO2_16		(_MX53_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		(_MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17		(_MX53_PAD_EIM_A22__IPU_CSI1_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7		(_MX53_PAD_EIM_A22__SRC_BT_CFG1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21		(_MX53_PAD_EIM_A21__EMI_WEIM_A_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__GPIO2_17		(_MX53_PAD_EIM_A21__GPIO2_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		(_MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16		(_MX53_PAD_EIM_A21__IPU_CSI1_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6		(_MX53_PAD_EIM_A21__SRC_BT_CFG1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20		(_MX53_PAD_EIM_A20__EMI_WEIM_A_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__GPIO2_18		(_MX53_PAD_EIM_A20__GPIO2_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		(_MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15		(_MX53_PAD_EIM_A20__IPU_CSI1_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5		(_MX53_PAD_EIM_A20__SRC_BT_CFG1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19		(_MX53_PAD_EIM_A19__EMI_WEIM_A_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__GPIO2_19		(_MX53_PAD_EIM_A19__GPIO2_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		(_MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14		(_MX53_PAD_EIM_A19__IPU_CSI1_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4		(_MX53_PAD_EIM_A19__SRC_BT_CFG1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18		(_MX53_PAD_EIM_A18__EMI_WEIM_A_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__GPIO2_20		(_MX53_PAD_EIM_A18__GPIO2_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		(_MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13		(_MX53_PAD_EIM_A18__IPU_CSI1_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3		(_MX53_PAD_EIM_A18__SRC_BT_CFG1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17		(_MX53_PAD_EIM_A17__EMI_WEIM_A_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__GPIO2_21		(_MX53_PAD_EIM_A17__GPIO2_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		(_MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12		(_MX53_PAD_EIM_A17__IPU_CSI1_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2		(_MX53_PAD_EIM_A17__SRC_BT_CFG1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16		(_MX53_PAD_EIM_A16__EMI_WEIM_A_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__GPIO2_22		(_MX53_PAD_EIM_A16__GPIO2_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		(_MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		(_MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1		(_MX53_PAD_EIM_A16__SRC_BT_CFG1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		(_MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__GPIO2_23		(_MX53_PAD_EIM_CS0__GPIO2_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK		(_MX53_PAD_EIM_CS0__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5		(_MX53_PAD_EIM_CS0__IPU_DI1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		(_MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__GPIO2_24		(_MX53_PAD_EIM_CS1__GPIO2_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI		(_MX53_PAD_EIM_CS1__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6		(_MX53_PAD_EIM_CS1__IPU_DI1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE		(_MX53_PAD_EIM_OE__EMI_WEIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__GPIO2_25		(_MX53_PAD_EIM_OE__GPIO2_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__ECSPI2_MISO		(_MX53_PAD_EIM_OE__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7		(_MX53_PAD_EIM_OE__IPU_DI1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG		(_MX53_PAD_EIM_OE__USBPHY2_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW		(_MX53_PAD_EIM_RW__EMI_WEIM_RW | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__GPIO2_26		(_MX53_PAD_EIM_RW__GPIO2_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__ECSPI2_SS0		(_MX53_PAD_EIM_RW__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8		(_MX53_PAD_EIM_RW__IPU_DI1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		(_MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA		(_MX53_PAD_EIM_LBA__EMI_WEIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__GPIO2_27		(_MX53_PAD_EIM_LBA__GPIO2_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1		(_MX53_PAD_EIM_LBA__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17		(_MX53_PAD_EIM_LBA__IPU_DI1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		(_MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		(_MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__GPIO2_28		(_MX53_PAD_EIM_EB0__GPIO2_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		(_MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11		(_MX53_PAD_EIM_EB0__IPU_CSI1_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY		(_MX53_PAD_EIM_EB0__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		(_MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		(_MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__GPIO2_29		(_MX53_PAD_EIM_EB1__GPIO2_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		(_MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10		(_MX53_PAD_EIM_EB1__IPU_CSI1_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		(_MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		(_MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__GPIO3_0		(_MX53_PAD_EIM_DA0__GPIO3_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		(_MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9		(_MX53_PAD_EIM_DA0__IPU_CSI1_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		(_MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		(_MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__GPIO3_1		(_MX53_PAD_EIM_DA1__GPIO3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		(_MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8		(_MX53_PAD_EIM_DA1__IPU_CSI1_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		(_MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		(_MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__GPIO3_2		(_MX53_PAD_EIM_DA2__GPIO3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		(_MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7		(_MX53_PAD_EIM_DA2__IPU_CSI1_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		(_MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		(_MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__GPIO3_3		(_MX53_PAD_EIM_DA3__GPIO3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		(_MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6		(_MX53_PAD_EIM_DA3__IPU_CSI1_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		(_MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		(_MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__GPIO3_4		(_MX53_PAD_EIM_DA4__GPIO3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		(_MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5		(_MX53_PAD_EIM_DA4__IPU_CSI1_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		(_MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		(_MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__GPIO3_5		(_MX53_PAD_EIM_DA5__GPIO3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		(_MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4		(_MX53_PAD_EIM_DA5__IPU_CSI1_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		(_MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		(_MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__GPIO3_6		(_MX53_PAD_EIM_DA6__GPIO3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		(_MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3		(_MX53_PAD_EIM_DA6__IPU_CSI1_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		(_MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		(_MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__GPIO3_7		(_MX53_PAD_EIM_DA7__GPIO3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		(_MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2		(_MX53_PAD_EIM_DA7__IPU_CSI1_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		(_MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		(_MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__GPIO3_8		(_MX53_PAD_EIM_DA8__GPIO3_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		(_MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1		(_MX53_PAD_EIM_DA8__IPU_CSI1_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		(_MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		(_MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__GPIO3_9		(_MX53_PAD_EIM_DA9__GPIO3_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		(_MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0		(_MX53_PAD_EIM_DA9__IPU_CSI1_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		(_MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		(_MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__GPIO3_10		(_MX53_PAD_EIM_DA10__GPIO3_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		(_MX53_PAD_EIM_DA10__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		(_MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		(_MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__GPIO3_11		(_MX53_PAD_EIM_DA11__GPIO3_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2		(_MX53_PAD_EIM_DA11__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		(_MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__GPIO3_12		(_MX53_PAD_EIM_DA12__GPIO3_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3		(_MX53_PAD_EIM_DA12__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		(_MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__GPIO3_13		(_MX53_PAD_EIM_DA13__GPIO3_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		(_MX53_PAD_EIM_DA13__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		(_MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__GPIO3_14		(_MX53_PAD_EIM_DA14__GPIO3_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		(_MX53_PAD_EIM_DA14__IPU_DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		(_MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		(_MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__GPIO3_15		(_MX53_PAD_EIM_DA15__GPIO3_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		(_MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WE_B__GPIO6_12		(_MX53_PAD_NANDF_WE_B__GPIO6_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		(_MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RE_B__GPIO6_13		(_MX53_PAD_NANDF_RE_B__GPIO6_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		(_MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_WAIT__GPIO5_0		(_MX53_PAD_EIM_WAIT__GPIO5_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		(_MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22		(_MX53_PAD_LVDS1_TX3_P__GPIO6_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		(_MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24		(_MX53_PAD_LVDS1_TX2_P__GPIO6_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		(_MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26		(_MX53_PAD_LVDS1_CLK_P__GPIO6_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		(_MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28		(_MX53_PAD_LVDS1_TX1_P__GPIO6_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		(_MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30		(_MX53_PAD_LVDS1_TX0_P__GPIO6_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		(_MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22		(_MX53_PAD_LVDS0_TX3_P__GPIO7_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		(_MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24		(_MX53_PAD_LVDS0_CLK_P__GPIO7_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		(_MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26		(_MX53_PAD_LVDS0_TX2_P__GPIO7_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		(_MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28		(_MX53_PAD_LVDS0_TX1_P__GPIO7_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		(_MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30		(_MX53_PAD_LVDS0_TX0_P__GPIO7_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		(_MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_10__GPIO4_0		(_MX53_PAD_GPIO_10__GPIO4_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		(_MX53_PAD_GPIO_10__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_11__GPIO4_1		(_MX53_PAD_GPIO_11__GPIO4_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_12__GPIO4_2		(_MX53_PAD_GPIO_12__GPIO4_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_13__GPIO4_3		(_MX53_PAD_GPIO_13__GPIO4_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_14__GPIO4_4		(_MX53_PAD_GPIO_14__GPIO4_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		(_MX53_PAD_NANDF_CLE__EMI_NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CLE__GPIO6_7		(_MX53_PAD_NANDF_CLE__GPIO6_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		(_MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		(_MX53_PAD_NANDF_ALE__EMI_NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_ALE__GPIO6_8		(_MX53_PAD_NANDF_ALE__GPIO6_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		(_MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		(_MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WP_B__GPIO6_9		(_MX53_PAD_NANDF_WP_B__GPIO6_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		(_MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		(_MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RB0__GPIO6_10		(_MX53_PAD_NANDF_RB0__GPIO6_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		(_MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		(_MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS0__GPIO6_11		(_MX53_PAD_NANDF_CS0__GPIO6_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		(_MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		(_MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__GPIO6_14		(_MX53_PAD_NANDF_CS1__GPIO6_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK		(_MX53_PAD_NANDF_CS1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		(_MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		(_MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__GPIO6_15		(_MX53_PAD_NANDF_CS2__GPIO6_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0		(_MX53_PAD_NANDF_CS2__IPU_SISG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0		(_MX53_PAD_NANDF_CS2__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		(_MX53_PAD_NANDF_CS2__EMI_WEIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		(_MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG		(_MX53_PAD_NANDF_CS2__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		(_MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		(_MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__GPIO6_16		(_MX53_PAD_NANDF_CS3__GPIO6_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1		(_MX53_PAD_NANDF_CS3__IPU_SISG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1		(_MX53_PAD_NANDF_CS3__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		(_MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT		(_MX53_PAD_NANDF_CS3__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		(_MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__FEC_MDIO		(_MX53_PAD_FEC_MDIO__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__GPIO1_22		(_MX53_PAD_FEC_MDIO__GPIO1_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR		(_MX53_PAD_FEC_MDIO__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__FEC_COL		(_MX53_PAD_FEC_MDIO__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		(_MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3		(_MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		(_MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		(_MX53_PAD_FEC_REF_CLK__FEC_TX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23		(_MX53_PAD_FEC_REF_CLK__GPIO1_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR		(_MX53_PAD_FEC_REF_CLK__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4		(_MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		(_MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER		(_MX53_PAD_FEC_RX_ER__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__GPIO1_24		(_MX53_PAD_FEC_RX_ER__GPIO1_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR		(_MX53_PAD_FEC_RX_ER__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK		(_MX53_PAD_FEC_RX_ER__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		(_MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV		(_MX53_PAD_FEC_CRS_DV__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25		(_MX53_PAD_FEC_CRS_DV__GPIO1_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		(_MX53_PAD_FEC_CRS_DV__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1		(_MX53_PAD_FEC_RXD1__FEC_RDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__GPIO1_26		(_MX53_PAD_FEC_RXD1__GPIO1_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__ESAI1_FST		(_MX53_PAD_FEC_RXD1__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG		(_MX53_PAD_FEC_RXD1__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		(_MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0		(_MX53_PAD_FEC_RXD0__FEC_RDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__GPIO1_27		(_MX53_PAD_FEC_RXD0__GPIO1_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT		(_MX53_PAD_FEC_RXD0__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		(_MX53_PAD_FEC_RXD0__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN		(_MX53_PAD_FEC_TX_EN__FEC_TX_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TX_EN__GPIO1_28		(_MX53_PAD_FEC_TX_EN__GPIO1_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		(_MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1		(_MX53_PAD_FEC_TXD1__FEC_TDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__GPIO1_29		(_MX53_PAD_FEC_TXD1__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		(_MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK		(_MX53_PAD_FEC_TXD1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		(_MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0		(_MX53_PAD_FEC_TXD0__FEC_TDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__GPIO1_30		(_MX53_PAD_FEC_TXD0__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		(_MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		(_MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__FEC_MDC		(_MX53_PAD_FEC_MDC__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__GPIO1_31		(_MX53_PAD_FEC_MDC__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		(_MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT		(_MX53_PAD_FEC_MDC__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG		(_MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		(_MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__PATA_DIOW		(_MX53_PAD_PATA_DIOW__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__GPIO6_17		(_MX53_PAD_PATA_DIOW__GPIO6_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		(_MX53_PAD_PATA_DIOW__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		(_MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__PATA_DMACK		(_MX53_PAD_PATA_DMACK__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__GPIO6_18		(_MX53_PAD_PATA_DMACK__GPIO6_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		(_MX53_PAD_PATA_DMACK__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		(_MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ		(_MX53_PAD_PATA_DMARQ__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__GPIO7_0		(_MX53_PAD_PATA_DMARQ__GPIO7_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		(_MX53_PAD_PATA_DMARQ__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		(_MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		(_MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		(_MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		(_MX53_PAD_PATA_BUFFER_EN__GPIO7_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		(_MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		(_MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5		(_MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ		(_MX53_PAD_PATA_INTRQ__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__GPIO7_2		(_MX53_PAD_PATA_INTRQ__GPIO7_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__UART2_CTS		(_MX53_PAD_PATA_INTRQ__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN		(_MX53_PAD_PATA_INTRQ__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		(_MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		(_MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__PATA_DIOR		(_MX53_PAD_PATA_DIOR__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__GPIO7_3		(_MX53_PAD_PATA_DIOR__GPIO7_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__UART2_RTS		(_MX53_PAD_PATA_DIOR__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN		(_MX53_PAD_PATA_DIOR__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		(_MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		(_MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__GPIO7_4		(_MX53_PAD_PATA_RESET_B__GPIO7_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		(_MX53_PAD_PATA_RESET_B__ESDHC3_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__UART1_CTS		(_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		(_MX53_PAD_PATA_RESET_B__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		(_MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__PATA_IORDY		(_MX53_PAD_PATA_IORDY__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__GPIO7_5		(_MX53_PAD_PATA_IORDY__GPIO7_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK		(_MX53_PAD_PATA_IORDY__ESDHC3_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__UART1_RTS		(_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN		(_MX53_PAD_PATA_IORDY__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		(_MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__PATA_DA_0		(_MX53_PAD_PATA_DA_0__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__GPIO7_6		(_MX53_PAD_PATA_DA_0__GPIO7_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST		(_MX53_PAD_PATA_DA_0__ESDHC3_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE		(_MX53_PAD_PATA_DA_0__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		(_MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__PATA_DA_1		(_MX53_PAD_PATA_DA_1__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__GPIO7_7		(_MX53_PAD_PATA_DA_1__GPIO7_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD		(_MX53_PAD_PATA_DA_1__ESDHC4_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__UART3_CTS		(_MX53_PAD_PATA_DA_1__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		(_MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__PATA_DA_2		(_MX53_PAD_PATA_DA_2__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__GPIO7_8		(_MX53_PAD_PATA_DA_2__GPIO7_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK		(_MX53_PAD_PATA_DA_2__ESDHC4_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__UART3_RTS		(_MX53_PAD_PATA_DA_2__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		(_MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__PATA_CS_0		(_MX53_PAD_PATA_CS_0__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__GPIO7_9		(_MX53_PAD_PATA_CS_0__GPIO7_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		(_MX53_PAD_PATA_CS_0__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		(_MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__PATA_CS_1		(_MX53_PAD_PATA_CS_1__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__GPIO7_10		(_MX53_PAD_PATA_CS_1__GPIO7_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		(_MX53_PAD_PATA_CS_1__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		(_MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0		(_MX53_PAD_PATA_DATA0__PATA_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__GPIO2_0		(_MX53_PAD_PATA_DATA0__GPIO2_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		(_MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		(_MX53_PAD_PATA_DATA0__ESDHC3_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0		(_MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		(_MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		(_MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1		(_MX53_PAD_PATA_DATA1__PATA_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__GPIO2_1		(_MX53_PAD_PATA_DATA1__GPIO2_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		(_MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		(_MX53_PAD_PATA_DATA1__ESDHC3_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1		(_MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		(_MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2		(_MX53_PAD_PATA_DATA2__PATA_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__GPIO2_2		(_MX53_PAD_PATA_DATA2__GPIO2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		(_MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		(_MX53_PAD_PATA_DATA2__ESDHC3_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2		(_MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		(_MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3		(_MX53_PAD_PATA_DATA3__PATA_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__GPIO2_3		(_MX53_PAD_PATA_DATA3__GPIO2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		(_MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		(_MX53_PAD_PATA_DATA3__ESDHC3_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3		(_MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		(_MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4		(_MX53_PAD_PATA_DATA4__PATA_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__GPIO2_4		(_MX53_PAD_PATA_DATA4__GPIO2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		(_MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		(_MX53_PAD_PATA_DATA4__ESDHC4_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4		(_MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		(_MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5		(_MX53_PAD_PATA_DATA5__PATA_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__GPIO2_5		(_MX53_PAD_PATA_DATA5__GPIO2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		(_MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		(_MX53_PAD_PATA_DATA5__ESDHC4_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5		(_MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		(_MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6		(_MX53_PAD_PATA_DATA6__PATA_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__GPIO2_6		(_MX53_PAD_PATA_DATA6__GPIO2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		(_MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		(_MX53_PAD_PATA_DATA6__ESDHC4_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6		(_MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		(_MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7		(_MX53_PAD_PATA_DATA7__PATA_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__GPIO2_7		(_MX53_PAD_PATA_DATA7__GPIO2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		(_MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		(_MX53_PAD_PATA_DATA7__ESDHC4_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7		(_MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		(_MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8		(_MX53_PAD_PATA_DATA8__PATA_DATA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__GPIO2_8		(_MX53_PAD_PATA_DATA8__GPIO2_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		(_MX53_PAD_PATA_DATA8__ESDHC1_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		(_MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		(_MX53_PAD_PATA_DATA8__ESDHC3_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8		(_MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		(_MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9		(_MX53_PAD_PATA_DATA9__PATA_DATA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__GPIO2_9		(_MX53_PAD_PATA_DATA9__GPIO2_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		(_MX53_PAD_PATA_DATA9__ESDHC1_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		(_MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		(_MX53_PAD_PATA_DATA9__ESDHC3_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9		(_MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		(_MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10		(_MX53_PAD_PATA_DATA10__PATA_DATA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__GPIO2_10		(_MX53_PAD_PATA_DATA10__GPIO2_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		(_MX53_PAD_PATA_DATA10__ESDHC1_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		(_MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		(_MX53_PAD_PATA_DATA10__ESDHC3_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10		(_MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		(_MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11		(_MX53_PAD_PATA_DATA11__PATA_DATA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__GPIO2_11		(_MX53_PAD_PATA_DATA11__GPIO2_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		(_MX53_PAD_PATA_DATA11__ESDHC1_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		(_MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		(_MX53_PAD_PATA_DATA11__ESDHC3_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11		(_MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		(_MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12		(_MX53_PAD_PATA_DATA12__PATA_DATA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__GPIO2_12		(_MX53_PAD_PATA_DATA12__GPIO2_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		(_MX53_PAD_PATA_DATA12__ESDHC2_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		(_MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		(_MX53_PAD_PATA_DATA12__ESDHC4_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12		(_MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		(_MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13		(_MX53_PAD_PATA_DATA13__PATA_DATA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__GPIO2_13		(_MX53_PAD_PATA_DATA13__GPIO2_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		(_MX53_PAD_PATA_DATA13__ESDHC2_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		(_MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		(_MX53_PAD_PATA_DATA13__ESDHC4_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13		(_MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		(_MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14		(_MX53_PAD_PATA_DATA14__PATA_DATA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__GPIO2_14		(_MX53_PAD_PATA_DATA14__GPIO2_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		(_MX53_PAD_PATA_DATA14__ESDHC2_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		(_MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		(_MX53_PAD_PATA_DATA14__ESDHC4_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14		(_MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		(_MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15		(_MX53_PAD_PATA_DATA15__PATA_DATA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__GPIO2_15		(_MX53_PAD_PATA_DATA15__GPIO2_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		(_MX53_PAD_PATA_DATA15__ESDHC2_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		(_MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		(_MX53_PAD_PATA_DATA15__ESDHC4_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15		(_MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		(_MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0		(_MX53_PAD_SD1_DATA0__ESDHC1_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__GPIO1_16		(_MX53_PAD_SD1_DATA0__GPIO1_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1		(_MX53_PAD_SD1_DATA0__GPT_CAPIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__CSPI_MISO		(_MX53_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		(_MX53_PAD_SD1_DATA0__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1		(_MX53_PAD_SD1_DATA1__ESDHC1_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__GPIO1_17		(_MX53_PAD_SD1_DATA1__GPIO1_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2		(_MX53_PAD_SD1_DATA1__GPT_CAPIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__CSPI_SS0		(_MX53_PAD_SD1_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		(_MX53_PAD_SD1_DATA1__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD		(_MX53_PAD_SD1_CMD__ESDHC1_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__GPIO1_18		(_MX53_PAD_SD1_CMD__GPIO1_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1		(_MX53_PAD_SD1_CMD__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__CSPI_MOSI		(_MX53_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP		(_MX53_PAD_SD1_CMD__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2		(_MX53_PAD_SD1_DATA2__ESDHC1_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__GPIO1_19		(_MX53_PAD_SD1_DATA2__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2		(_MX53_PAD_SD1_DATA2__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO		(_MX53_PAD_SD1_DATA2__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__CSPI_SS1		(_MX53_PAD_SD1_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		(_MX53_PAD_SD1_DATA2__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK		(_MX53_PAD_SD1_CLK__ESDHC1_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__GPIO1_20		(_MX53_PAD_SD1_CLK__GPIO1_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		(_MX53_PAD_SD1_CLK__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__GPT_CLKIN		(_MX53_PAD_SD1_CLK__GPT_CLKIN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__CSPI_SCLK		(_MX53_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		(_MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3		(_MX53_PAD_SD1_DATA3__ESDHC1_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__GPIO1_21		(_MX53_PAD_SD1_DATA3__GPIO1_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3		(_MX53_PAD_SD1_DATA3__GPT_CMPOUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO		(_MX53_PAD_SD1_DATA3__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__CSPI_SS2		(_MX53_PAD_SD1_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		(_MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK		(_MX53_PAD_SD2_CLK__ESDHC2_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__GPIO1_10		(_MX53_PAD_SD2_CLK__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__KPP_COL_5		(_MX53_PAD_SD2_CLK__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		(_MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__CSPI_SCLK		(_MX53_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V		(_MX53_PAD_SD2_CLK__SCC_RANDOM_V | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD		(_MX53_PAD_SD2_CMD__ESDHC2_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__GPIO1_11		(_MX53_PAD_SD2_CMD__GPIO1_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__KPP_ROW_5		(_MX53_PAD_SD2_CMD__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		(_MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__CSPI_MOSI		(_MX53_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__SCC_RANDOM		(_MX53_PAD_SD2_CMD__SCC_RANDOM | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3		(_MX53_PAD_SD2_DATA3__ESDHC2_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__GPIO1_12		(_MX53_PAD_SD2_DATA3__GPIO1_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__KPP_COL_6		(_MX53_PAD_SD2_DATA3__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		(_MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__CSPI_SS2		(_MX53_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__SJC_DONE		(_MX53_PAD_SD2_DATA3__SJC_DONE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2		(_MX53_PAD_SD2_DATA2__ESDHC2_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__GPIO1_13		(_MX53_PAD_SD2_DATA2__GPIO1_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6		(_MX53_PAD_SD2_DATA2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		(_MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__CSPI_SS1		(_MX53_PAD_SD2_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__SJC_FAIL		(_MX53_PAD_SD2_DATA2__SJC_FAIL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1		(_MX53_PAD_SD2_DATA1__ESDHC2_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__GPIO1_14		(_MX53_PAD_SD2_DATA1__GPIO1_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__KPP_COL_7		(_MX53_PAD_SD2_DATA1__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		(_MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__CSPI_SS0		(_MX53_PAD_SD2_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		(_MX53_PAD_SD2_DATA1__RTIC_SEC_VIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0		(_MX53_PAD_SD2_DATA0__ESDHC2_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__GPIO1_15		(_MX53_PAD_SD2_DATA0__GPIO1_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7		(_MX53_PAD_SD2_DATA0__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		(_MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__CSPI_MISO		(_MX53_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		(_MX53_PAD_SD2_DATA0__RTIC_DONE_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__CCM_CLKO		(_MX53_PAD_GPIO_0__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__GPIO1_0		(_MX53_PAD_GPIO_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__KPP_COL_5		(_MX53_PAD_GPIO_0__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		(_MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__EPIT1_EPITO		(_MX53_PAD_GPIO_0__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB		(_MX53_PAD_GPIO_0__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		(_MX53_PAD_GPIO_0__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__CSU_TD		(_MX53_PAD_GPIO_0__CSU_TD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__ESAI1_SCKR		(_MX53_PAD_GPIO_1__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__GPIO1_1		(_MX53_PAD_GPIO_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__KPP_ROW_5		(_MX53_PAD_GPIO_1__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		(_MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__PWM2_PWMO		(_MX53_PAD_GPIO_1__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B		(_MX53_PAD_GPIO_1__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__ESDHC1_CD		(_MX53_PAD_GPIO_1__ESDHC1_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK		(_MX53_PAD_GPIO_1__SRC_TESTER_ACK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__ESAI1_FSR		(_MX53_PAD_GPIO_9__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__GPIO1_9		(_MX53_PAD_GPIO_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__KPP_COL_6		(_MX53_PAD_GPIO_9__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B		(_MX53_PAD_GPIO_9__CCM_REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__PWM1_PWMO		(_MX53_PAD_GPIO_9__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B		(_MX53_PAD_GPIO_9__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__ESDHC1_WP		(_MX53_PAD_GPIO_9__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE		(_MX53_PAD_GPIO_9__SCC_FAIL_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__ESAI1_HCKR		(_MX53_PAD_GPIO_3__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__GPIO1_3		(_MX53_PAD_GPIO_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__I2C3_SCL		(_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN		(_MX53_PAD_GPIO_3__DPLLIP1_TOG_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__CCM_CLKO2		(_MX53_PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0		(_MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		(_MX53_PAD_GPIO_3__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__MLB_MLBCLK		(_MX53_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__ESAI1_SCKT		(_MX53_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__GPIO1_6		(_MX53_PAD_GPIO_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__I2C3_SDA		(_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0		(_MX53_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		(_MX53_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1		(_MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL		(_MX53_PAD_GPIO_6__ESDHC2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__MLB_MLBSIG		(_MX53_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__ESAI1_FST		(_MX53_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__GPIO1_2		(_MX53_PAD_GPIO_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__KPP_ROW_6		(_MX53_PAD_GPIO_2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1		(_MX53_PAD_GPIO_2__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		(_MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2		(_MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__ESDHC2_WP		(_MX53_PAD_GPIO_2__ESDHC2_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__MLB_MLBDAT		(_MX53_PAD_GPIO_2__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__ESAI1_HCKT		(_MX53_PAD_GPIO_4__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__GPIO1_4		(_MX53_PAD_GPIO_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__KPP_COL_7		(_MX53_PAD_GPIO_4__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2		(_MX53_PAD_GPIO_4__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		(_MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3		(_MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__ESDHC2_CD		(_MX53_PAD_GPIO_4__ESDHC2_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE		(_MX53_PAD_GPIO_4__SCC_SEC_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3		(_MX53_PAD_GPIO_5__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__GPIO1_5		(_MX53_PAD_GPIO_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__KPP_ROW_7		(_MX53_PAD_GPIO_5__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__CCM_CLKO		(_MX53_PAD_GPIO_5__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		(_MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4		(_MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__I2C3_SCL		(_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP		(_MX53_PAD_GPIO_5__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1		(_MX53_PAD_GPIO_7__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__GPIO1_7		(_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__EPIT1_EPITO		(_MX53_PAD_GPIO_7__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__CAN1_TXCAN		(_MX53_PAD_GPIO_7__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX		(_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__FIRI_RXD		(_MX53_PAD_GPIO_7__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK		(_MX53_PAD_GPIO_7__SPDIF_PLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP		(_MX53_PAD_GPIO_7__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0		(_MX53_PAD_GPIO_8__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__GPIO1_8		(_MX53_PAD_GPIO_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__EPIT2_EPITO		(_MX53_PAD_GPIO_8__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__CAN1_RXCAN		(_MX53_PAD_GPIO_8__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX		(_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__FIRI_TXD		(_MX53_PAD_GPIO_8__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK		(_MX53_PAD_GPIO_8__SPDIF_SRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP		(_MX53_PAD_GPIO_8__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2		(_MX53_PAD_GPIO_16__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__GPIO7_11		(_MX53_PAD_GPIO_16__GPIO7_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		(_MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		(_MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__SPDIF_IN1		(_MX53_PAD_GPIO_16__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__I2C3_SDA		(_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__SJC_DE_B		(_MX53_PAD_GPIO_16__SJC_DE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__ESAI1_TX0		(_MX53_PAD_GPIO_17__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__GPIO7_12		(_MX53_PAD_GPIO_17__GPIO7_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		(_MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY		(_MX53_PAD_GPIO_17__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		(_MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__SPDIF_OUT1		(_MX53_PAD_GPIO_17__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__IPU_SNOOP2		(_MX53_PAD_GPIO_17__IPU_SNOOP2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT		(_MX53_PAD_GPIO_17__SJC_JTAG_ACT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__ESAI1_TX1		(_MX53_PAD_GPIO_18__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__GPIO7_13		(_MX53_PAD_GPIO_18__GPIO7_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		(_MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__OWIRE_LINE		(_MX53_PAD_GPIO_18__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG		(_MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		(_MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL		(_MX53_PAD_GPIO_18__ESDHC1_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		(_MX53_PAD_GPIO_18__SRC_SYSTEM_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
 
 #endif	/* __MACH_IOMUX_MX53_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h b/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h
index 15d5951..bf28df0 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h
@@ -46,12 +46,12 @@
  * 	- setups the iomux according to the configuration
  * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
  */
-int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label);
+int mxc_iomux_alloc_pin(unsigned int pin_mode, const char *label);
 /*
  * setups mutliple pins
  * convenient way to call the above function with tables
  */
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label);
 
 /*
@@ -60,12 +60,12 @@ int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
  * 	- frees the GPIO if the pin was configured as GPIO
  * 	- DOES NOT reconfigure the IOMUX in its reset state
  */
-void mxc_iomux_release_pin(const unsigned int pin_mode);
+void mxc_iomux_release_pin(unsigned int pin_mode);
 /*
  * releases multiple pins
  * convenvient way to call the above function with tables
  */
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count);
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
 
 #define MUX_SIDE_AP		(0)
 #define MUX_SIDE_SP		(1)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h
index 884f575..c07d302 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v1.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h
@@ -100,4 +100,6 @@ extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
 		const char *label);
 extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
 
+extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
+
 #endif /* __MACH_IOMUX_V1_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index ba65c92..a3d930d 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -23,17 +23,17 @@
 #define MXC_GPIO_IRQ_START	MXC_INTERNAL_IRQS
 
 /* these are ordered by size to support multi-SoC kernels */
-#if defined CONFIG_ARCH_MX53
+#if defined CONFIG_SOC_IMX53
 #define MXC_GPIO_IRQS		(32 * 7)
 #elif defined CONFIG_ARCH_MX2
 #define MXC_GPIO_IRQS		(32 * 6)
-#elif defined CONFIG_ARCH_MX50
+#elif defined CONFIG_SOC_IMX50
 #define MXC_GPIO_IRQS		(32 * 6)
 #elif defined CONFIG_ARCH_MX1
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MX25
 #define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_ARCH_MX51
+#elif defined CONFIG_SOC_IMX51
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MXC91231
 #define MXC_GPIO_IRQS		(32 * 4)
diff --git a/arch/arm/plat-mxc/include/mach/memory.h b/arch/arm/plat-mxc/include/mach/memory.h
index 8386140..5d51cbb 100644
--- a/arch/arm/plat-mxc/include/mach/memory.h
+++ b/arch/arm/plat-mxc/include/mach/memory.h
@@ -23,23 +23,23 @@
 
 #if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
 # if defined CONFIG_ARCH_MX1
-#  define PHYS_OFFSET		MX1_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX1_PHYS_OFFSET
 # elif defined CONFIG_MACH_MX21
-#  define PHYS_OFFSET		MX21_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX21_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX25
-#  define PHYS_OFFSET		MX25_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX25_PHYS_OFFSET
 # elif defined CONFIG_MACH_MX27
-#  define PHYS_OFFSET		MX27_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX27_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX3
-#  define PHYS_OFFSET		MX3x_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX3x_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MXC91231
-#  define PHYS_OFFSET		MXC91231_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MXC91231_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX50
-#  define PHYS_OFFSET		MX50_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX50_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX51
-#  define PHYS_OFFSET		MX51_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX51_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX53
-#  define PHYS_OFFSET		MX53_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX53_PHYS_OFFSET
 # endif
 #endif
 
diff --git a/arch/arm/plat-mxc/include/mach/mx1.h b/arch/arm/plat-mxc/include/mach/mx1.h
index 75d9621..97b19e7 100644
--- a/arch/arm/plat-mxc/include/mach/mx1.h
+++ b/arch/arm/plat-mxc/include/mach/mx1.h
@@ -54,13 +54,13 @@
 #define MX1_AIPI2_BASE_ADDR		(0x10000 + MX1_IO_BASE_ADDR)
 #define MX1_SIM_BASE_ADDR		(0x11000 + MX1_IO_BASE_ADDR)
 #define MX1_USBD_BASE_ADDR		(0x12000 + MX1_IO_BASE_ADDR)
-#define MX1_SPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
+#define MX1_CSPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
 #define MX1_MMC_BASE_ADDR		(0x14000 + MX1_IO_BASE_ADDR)
 #define MX1_ASP_BASE_ADDR		(0x15000 + MX1_IO_BASE_ADDR)
 #define MX1_BTA_BASE_ADDR		(0x16000 + MX1_IO_BASE_ADDR)
 #define MX1_I2C_BASE_ADDR		(0x17000 + MX1_IO_BASE_ADDR)
 #define MX1_SSI_BASE_ADDR		(0x18000 + MX1_IO_BASE_ADDR)
-#define MX1_SPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
+#define MX1_CSPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
 #define MX1_MSHC_BASE_ADDR		(0x1A000 + MX1_IO_BASE_ADDR)
 #define MX1_CCM_BASE_ADDR		(0x1B000 + MX1_IO_BASE_ADDR)
 #define MX1_SCM_BASE_ADDR		(0x1B804 + MX1_IO_BASE_ADDR)
@@ -89,7 +89,7 @@
 #define MX1_GPIO_INT_PORTA	11
 #define MX1_GPIO_INT_PORTB	12
 #define MX1_GPIO_INT_PORTC	13
-#define MX1_LCDC_INT		14
+#define MX1_INT_LCDC		14
 #define MX1_SIM_INT		15
 #define MX1_SIM_DATA_INT	16
 #define MX1_RTC_INT		17
@@ -112,7 +112,8 @@
 #define MX1_PWM_INT		34
 #define MX1_SDHC_INT		35
 #define MX1_INT_I2C		39
-#define MX1_CSPI_INT		41
+#define MX1_INT_CSPI2		40
+#define MX1_INT_CSPI1		41
 #define MX1_SSI_TX_INT		42
 #define MX1_SSI_TX_ERR_INT	43
 #define MX1_SSI_RX_INT		44
diff --git a/arch/arm/plat-mxc/include/mach/mx53.h b/arch/arm/plat-mxc/include/mach/mx53.h
index d7a8e52..ace1786 100644
--- a/arch/arm/plat-mxc/include/mach/mx53.h
+++ b/arch/arm/plat-mxc/include/mach/mx53.h
@@ -79,7 +79,7 @@
 #define MX53_GPIO3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0008C000)
 #define MX53_GPIO4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00090000)
 #define MX53_KPP_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00094000)
-#define MX53_WDOG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
+#define MX53_WDOG1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
 #define MX53_WDOG2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0009C000)
 #define MX53_GPT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A0000)
 #define MX53_SRTC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A4000)
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 04c7a26..7e07263 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -103,7 +103,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx27()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -115,7 +115,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx31()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -127,7 +127,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx35()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX50
+#ifdef CONFIG_SOC_IMX50
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -139,7 +139,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx50()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -151,7 +151,7 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx51()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX53
+#ifdef CONFIG_SOC_IMX53
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
index a523a40..2c159dc 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
@@ -44,11 +44,14 @@ struct mxc_usbh_platform_data {
 	int (*exit)(struct platform_device *pdev);
 
 	unsigned int		 portsc;
-	unsigned int		 flags;
 	struct otg_transceiver	*otg;
 };
 
-int mxc_initialize_usb_hw(int port, unsigned int flags);
+int mx51_initialize_usb_hw(int port, unsigned int flags);
+int mx25_initialize_usb_hw(int port, unsigned int flags);
+int mx31_initialize_usb_hw(int port, unsigned int flags);
+int mx35_initialize_usb_hw(int port, unsigned int flags);
+int mx27_initialize_usb_hw(int port, unsigned int flags);
 
 #endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */
 
diff --git a/arch/arm/plat-mxc/include/mach/ulpi.h b/arch/arm/plat-mxc/include/mach/ulpi.h
index 96b6ab4..f9161c9 100644
--- a/arch/arm/plat-mxc/include/mach/ulpi.h
+++ b/arch/arm/plat-mxc/include/mach/ulpi.h
@@ -1,6 +1,15 @@
 #ifndef __MACH_ULPI_H
 #define __MACH_ULPI_H
 
+#ifdef CONFIG_USB_ULPI
+struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags);
+#else
+static inline struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags)
+{
+	return NULL;
+}
+#endif
+
 extern struct otg_io_access_ops mxc_ulpi_access_ops;
 
 #endif /* __MACH_ULPI_H */
diff --git a/arch/arm/plat-mxc/include/mach/uncompress.h b/arch/arm/plat-mxc/include/mach/uncompress.h
index ff469c4..4864b0a 100644
--- a/arch/arm/plat-mxc/include/mach/uncompress.h
+++ b/arch/arm/plat-mxc/include/mach/uncompress.h
@@ -62,6 +62,7 @@ static inline void flush(void)
 #define MX2X_UART1_BASE_ADDR	0x1000a000
 #define MX3X_UART1_BASE_ADDR	0x43F90000
 #define MX3X_UART2_BASE_ADDR	0x43F94000
+#define MX3X_UART5_BASE_ADDR	0x43FB4000
 #define MX51_UART1_BASE_ADDR	0x73fbc000
 #define MX50_UART1_BASE_ADDR	0x53fbc000
 #define MX53_UART1_BASE_ADDR	0x53fbc000
@@ -83,6 +84,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 	case MACH_TYPE_MX21ADS:
 	case MACH_TYPE_PCA100:
 	case MACH_TYPE_MXT_TD60:
+	case MACH_TYPE_IMX27IPCAM:
 		uart_base = MX2X_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX31LITE:
@@ -101,6 +103,9 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 	case MACH_TYPE_MAGX_ZN5:
 		uart_base = MX3X_UART2_BASE_ADDR;
 		break;
+	case MACH_TYPE_BUG:
+		uart_base = MX3X_UART5_BASE_ADDR;
+		break;
 	case MACH_TYPE_MX51_BABBAGE:
 	case MACH_TYPE_EUKREA_CPUIMX51SD:
 	case MACH_TYPE_MX51_3DS:
@@ -110,6 +115,8 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
 		uart_base = MX50_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX53_EVK:
+	case MACH_TYPE_MX53_LOCO:
+	case MACH_TYPE_MX53_SMD:
 		uart_base = MX53_UART1_BASE_ADDR;
 		break;
 	default:
diff --git a/arch/arm/plat-mxc/iomux-v1.c b/arch/arm/plat-mxc/iomux-v1.c
index 960a02c..3238c10 100644
--- a/arch/arm/plat-mxc/iomux-v1.c
+++ b/arch/arm/plat-mxc/iomux-v1.c
@@ -211,28 +211,10 @@ void mxc_gpio_release_multiple_pins(const int *pin_list, int count)
 }
 EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
 
-static int imx_iomuxv1_init(void)
+int __init imx_iomuxv1_init(void __iomem *base, int numports)
 {
-#ifdef CONFIG_ARCH_MX1
-	if (cpu_is_mx1()) {
-		imx_iomuxv1_baseaddr = MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR);
-		imx_iomuxv1_numports = MX1_NUM_GPIO_PORT;
-	} else
-#endif
-#ifdef CONFIG_MACH_MX21
-	if (cpu_is_mx21()) {
-		imx_iomuxv1_baseaddr = MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR);
-		imx_iomuxv1_numports = MX21_NUM_GPIO_PORT;
-	} else
-#endif
-#ifdef CONFIG_MACH_MX27
-	if (cpu_is_mx27()) {
-		imx_iomuxv1_baseaddr = MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR);
-		imx_iomuxv1_numports = MX27_NUM_GPIO_PORT;
-	} else
-#endif
-		return -ENODEV;
+	imx_iomuxv1_baseaddr = base;
+	imx_iomuxv1_numports = numports;
 
 	return 0;
 }
-pure_initcall(imx_iomuxv1_init);
diff --git a/arch/arm/plat-mxc/ulpi.c b/arch/arm/plat-mxc/ulpi.c
index 582c6df..477e45b 100644
--- a/arch/arm/plat-mxc/ulpi.c
+++ b/arch/arm/plat-mxc/ulpi.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
 
 #include <mach/ulpi.h>
 
@@ -111,3 +112,7 @@ struct otg_io_access_ops mxc_ulpi_access_ops = {
 };
 EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops);
 
+struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags)
+{
+	return otg_ulpi_create(&mxc_ulpi_access_ops, flags);
+}
diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c
index 1e88ecb..7062042 100644
--- a/arch/arm/plat-nomadik/gpio.c
+++ b/arch/arm/plat-nomadik/gpio.c
@@ -30,23 +30,39 @@
 /*
  * The GPIO module in the Nomadik family of Systems-on-Chip is an
  * AMBA device, managing 32 pins and alternate functions.  The logic block
- * is currently only used in the Nomadik.
+ * is currently used in the Nomadik and ux500.
  *
  * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
  */
 
-#define NMK_GPIO_PER_CHIP 32
+#define NMK_GPIO_PER_CHIP	32
+
 struct nmk_gpio_chip {
 	struct gpio_chip chip;
 	void __iomem *addr;
 	struct clk *clk;
+	unsigned int bank;
 	unsigned int parent_irq;
+	int secondary_parent_irq;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
 	spinlock_t lock;
 	/* Keep track of configured edges */
 	u32 edge_rising;
 	u32 edge_falling;
+	u32 real_wake;
+	u32 rwimsc;
+	u32 fwimsc;
+	u32 slpm;
 };
 
+static struct nmk_gpio_chip *
+nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
+
+static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
+
+#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
+
 static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
 				unsigned offset, int gpio_mode)
 {
@@ -118,8 +134,35 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip,
 	__nmk_gpio_set_output(nmk_chip, offset, val);
 }
 
+static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
+				     unsigned offset, int gpio_mode,
+				     bool glitch)
+{
+	u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
+	u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+	if (glitch && nmk_chip->set_ioforce) {
+		u32 bit = BIT(offset);
+
+		/* Prevent spurious wakeups */
+		writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
+		writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+		nmk_chip->set_ioforce(true);
+	}
+
+	__nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
+
+	if (glitch && nmk_chip->set_ioforce) {
+		nmk_chip->set_ioforce(false);
+
+		writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
+		writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
+	}
+}
+
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
-			     pin_cfg_t cfg, bool sleep)
+			     pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
 {
 	static const char *afnames[] = {
 		[NMK_GPIO_ALT_GPIO]	= "GPIO",
@@ -144,6 +187,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
 	int slpm = PIN_SLPM(cfg);
 	int output = PIN_DIR(cfg);
 	int val = PIN_VAL(cfg);
+	bool glitch = af == NMK_GPIO_ALT_C;
 
 	dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
 		pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
@@ -155,6 +199,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
 		int slpm_output = PIN_SLPM_DIR(cfg);
 		int slpm_val = PIN_SLPM_VAL(cfg);
 
+		af = NMK_GPIO_ALT_GPIO;
+
 		/*
 		 * The SLPM_* values are normal values + 1 to allow zero to
 		 * mean "same as normal".
@@ -180,8 +226,116 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
 		__nmk_gpio_set_pull(nmk_chip, offset, pull);
 	}
 
-	__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
-	__nmk_gpio_set_mode(nmk_chip, offset, af);
+	/*
+	 * If we've backed up the SLPM registers (glitch workaround), modify
+	 * the backups since they will be restored.
+	 */
+	if (slpmregs) {
+		if (slpm == NMK_GPIO_SLPM_NOCHANGE)
+			slpmregs[nmk_chip->bank] |= BIT(offset);
+		else
+			slpmregs[nmk_chip->bank] &= ~BIT(offset);
+	} else
+		__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
+
+	__nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
+}
+
+/*
+ * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
+ *  - Save SLPM registers
+ *  - Set SLPM=0 for the IOs you want to switch and others to 1
+ *  - Configure the GPIO registers for the IOs that are being switched
+ *  - Set IOFORCE=1
+ *  - Modify the AFLSA/B registers for the IOs that are being switched
+ *  - Set IOFORCE=0
+ *  - Restore SLPM registers
+ *  - Any spurious wake up event during switch sequence to be ignored and
+ *    cleared
+ */
+static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+		unsigned int temp = slpm[i];
+
+		if (!chip)
+			break;
+
+		slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
+		writel(temp, chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
+static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
+static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
+{
+	static unsigned int slpm[NUM_BANKS];
+	unsigned long flags;
+	bool glitch = false;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
+			glitch = true;
+			break;
+		}
+	}
+
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+
+	if (glitch) {
+		memset(slpm, 0xff, sizeof(slpm));
+
+		for (i = 0; i < num; i++) {
+			int pin = PIN_NUM(cfgs[i]);
+			int offset = pin % NMK_GPIO_PER_CHIP;
+
+			if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
+				slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
+		}
+
+		nmk_gpio_glitch_slpm_init(slpm);
+	}
+
+	for (i = 0; i < num; i++) {
+		struct nmk_gpio_chip *nmk_chip;
+		int pin = PIN_NUM(cfgs[i]);
+
+		nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
+		if (!nmk_chip) {
+			ret = -EINVAL;
+			break;
+		}
+
+		spin_lock(&nmk_chip->lock);
+		__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
+				 cfgs[i], sleep, glitch ? slpm : NULL);
+		spin_unlock(&nmk_chip->lock);
+	}
+
+	if (glitch)
+		nmk_gpio_glitch_slpm_restore(slpm);
+
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+
+	return ret;
 }
 
 /**
@@ -200,19 +354,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
  */
 int nmk_config_pin(pin_cfg_t cfg, bool sleep)
 {
-	struct nmk_gpio_chip *nmk_chip;
-	int gpio = PIN_NUM(cfg);
-	unsigned long flags;
-
-	nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
-	if (!nmk_chip)
-		return -EINVAL;
-
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
-
-	return 0;
+	return __nmk_config_pins(&cfg, 1, sleep);
 }
 EXPORT_SYMBOL(nmk_config_pin);
 
@@ -226,31 +368,13 @@ EXPORT_SYMBOL(nmk_config_pin);
  */
 int nmk_config_pins(pin_cfg_t *cfgs, int num)
 {
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < num; i++) {
-		ret = nmk_config_pin(cfgs[i], false);
-		if (ret)
-			break;
-	}
-
-	return ret;
+	return __nmk_config_pins(cfgs, num, false);
 }
 EXPORT_SYMBOL(nmk_config_pins);
 
 int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
 {
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < num; i++) {
-		ret = nmk_config_pin(cfgs[i], true);
-		if (ret)
-			break;
-	}
-
-	return ret;
+	return __nmk_config_pins(cfgs, num, true);
 }
 EXPORT_SYMBOL(nmk_config_pins_sleep);
 
@@ -277,9 +401,13 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode)
 	if (!nmk_chip)
 		return -EINVAL;
 
-	spin_lock_irqsave(&nmk_chip->lock, flags);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
 	__nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 
 	return 0;
 }
@@ -314,6 +442,15 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull)
 }
 
 /* Mode functions */
+/**
+ * nmk_gpio_set_mode() - set the mux mode of a gpio pin
+ * @gpio: pin number
+ * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
+ *	       NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
+ *
+ * Sets the mode of the specified pin to one of the alternate functions or
+ * plain GPIO.
+ */
 int nmk_gpio_set_mode(int gpio, int gpio_mode)
 {
 	struct nmk_gpio_chip *nmk_chip;
@@ -401,8 +538,20 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip,
 	}
 }
 
-static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
-			       bool enable)
+static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
+				int gpio, bool on)
+{
+#ifdef CONFIG_ARCH_U8500
+	if (cpu_is_u8500v2()) {
+		__nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base,
+				    on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
+				       : NMK_GPIO_SLPM_WAKEUP_DISABLE);
+	}
+#endif
+	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+}
+
+static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 {
 	int gpio;
 	struct nmk_gpio_chip *nmk_chip;
@@ -415,44 +564,58 @@ static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
 	if (!nmk_chip)
 		return -EINVAL;
 
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_gpio_irq_modify(nmk_chip, gpio, which, enable);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
+	__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
+
+	if (!(nmk_chip->real_wake & bitmask))
+		__nmk_gpio_set_wake(nmk_chip, gpio, enable);
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 
 	return 0;
 }
 
 static void nmk_gpio_irq_mask(struct irq_data *d)
 {
-	nmk_gpio_irq_modify(d, NORMAL, false);
+	nmk_gpio_irq_maskunmask(d, false);
 }
 
 static void nmk_gpio_irq_unmask(struct irq_data *d)
 {
-	nmk_gpio_irq_modify(d, NORMAL, true);
+	nmk_gpio_irq_maskunmask(d, true);
 }
 
 static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
+	struct irq_desc *desc = irq_to_desc(d->irq);
+	bool enabled = !(desc->status & IRQ_DISABLED);
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
+	u32 bitmask;
 	int gpio;
 
 	gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 		return -EINVAL;
+	bitmask = nmk_gpio_get_bitmask(gpio);
 
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-#ifdef CONFIG_ARCH_U8500
-	if (cpu_is_u8500v2()) {
-		__nmk_gpio_set_slpm(nmk_chip, gpio,
-				    on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
-				       : NMK_GPIO_SLPM_WAKEUP_DISABLE);
-	}
-#endif
-	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
+	if (!enabled)
+		__nmk_gpio_set_wake(nmk_chip, gpio, on);
+
+	if (on)
+		nmk_chip->real_wake |= bitmask;
+	else
+		nmk_chip->real_wake &= ~bitmask;
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 
 	return 0;
 }
@@ -483,7 +646,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	if (enabled)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
 
-	if (wake)
+	if (enabled || wake)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
 
 	nmk_chip->edge_rising &= ~bitmask;
@@ -497,7 +660,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 	if (enabled)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
 
-	if (wake)
+	if (enabled || wake)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
 
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
@@ -514,12 +677,11 @@ static struct irq_chip nmk_gpio_irq_chip = {
 	.irq_set_wake	= nmk_gpio_irq_set_wake,
 };
 
-static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
+				   u32 status)
 {
 	struct nmk_gpio_chip *nmk_chip;
 	struct irq_chip *host_chip = get_irq_chip(irq);
-	unsigned int gpio_irq;
-	u32 pending;
 	unsigned int first_irq;
 
 	if (host_chip->irq_mask_ack)
@@ -532,29 +694,56 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 	nmk_chip = get_irq_data(irq);
 	first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-	while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) {
-		gpio_irq = first_irq + __ffs(pending);
-		generic_handle_irq(gpio_irq);
+	while (status) {
+		int bit = __ffs(status);
+
+		generic_handle_irq(first_irq + bit);
+		status &= ~BIT(bit);
 	}
 
 	host_chip->irq_unmask(&desc->irq_data);
 }
 
+static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
+	u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
+
+	__nmk_gpio_irq_handler(irq, desc, status);
+}
+
+static void nmk_gpio_secondary_irq_handler(unsigned int irq,
+					   struct irq_desc *desc)
+{
+	struct nmk_gpio_chip *nmk_chip = get_irq_data(irq);
+	u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
+
+	__nmk_gpio_irq_handler(irq, desc, status);
+}
+
 static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
 {
 	unsigned int first_irq;
 	int i;
 
 	first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-	for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) {
+	for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
 		set_irq_chip(i, &nmk_gpio_irq_chip);
 		set_irq_handler(i, handle_edge_irq);
 		set_irq_flags(i, IRQF_VALID);
 		set_irq_chip_data(i, nmk_chip);
 		set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
 	}
+
 	set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
 	set_irq_data(nmk_chip->parent_irq, nmk_chip);
+
+	if (nmk_chip->secondary_parent_irq >= 0) {
+		set_irq_chained_handler(nmk_chip->secondary_parent_irq,
+					nmk_gpio_secondary_irq_handler);
+		set_irq_data(nmk_chip->secondary_parent_irq, nmk_chip);
+	}
+
 	return 0;
 }
 
@@ -605,6 +794,97 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 	return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
 }
 
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int mode;
+	unsigned		i;
+	unsigned		gpio = chip->base;
+	int			is_out;
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+	const char *modes[] = {
+		[NMK_GPIO_ALT_GPIO]	= "gpio",
+		[NMK_GPIO_ALT_A]	= "altA",
+		[NMK_GPIO_ALT_B]	= "altB",
+		[NMK_GPIO_ALT_C]	= "altC",
+	};
+
+	for (i = 0; i < chip->ngpio; i++, gpio++) {
+		const char *label = gpiochip_is_requested(chip, i);
+		bool pull;
+		u32 bit = 1 << i;
+
+		if (!label)
+			continue;
+
+		is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
+		pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
+		mode = nmk_gpio_get_mode(gpio);
+		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
+			gpio, label,
+			is_out ? "out" : "in ",
+			chip->get
+				? (chip->get(chip, i) ? "hi" : "lo")
+				: "?  ",
+			(mode < 0) ? "unknown" : modes[mode],
+			pull ? "pull" : "none");
+
+		if (!is_out) {
+			int		irq = gpio_to_irq(gpio);
+			struct irq_desc	*desc = irq_to_desc(irq);
+
+			/* This races with request_irq(), set_irq_type(),
+			 * and set_irq_wake() ... but those are "rare".
+			 *
+			 * More significantly, trigger type flags aren't
+			 * currently maintained by genirq.
+			 */
+			if (irq >= 0 && desc->action) {
+				char *trigger;
+
+				switch (desc->status & IRQ_TYPE_SENSE_MASK) {
+				case IRQ_TYPE_NONE:
+					trigger = "(default)";
+					break;
+				case IRQ_TYPE_EDGE_FALLING:
+					trigger = "edge-falling";
+					break;
+				case IRQ_TYPE_EDGE_RISING:
+					trigger = "edge-rising";
+					break;
+				case IRQ_TYPE_EDGE_BOTH:
+					trigger = "edge-both";
+					break;
+				case IRQ_TYPE_LEVEL_HIGH:
+					trigger = "level-high";
+					break;
+				case IRQ_TYPE_LEVEL_LOW:
+					trigger = "level-low";
+					break;
+				default:
+					trigger = "?trigger?";
+					break;
+				}
+
+				seq_printf(s, " irq-%d %s%s",
+					irq, trigger,
+					(desc->status & IRQ_WAKEUP)
+						? " wakeup" : "");
+			}
+		}
+
+		seq_printf(s, "\n");
+	}
+}
+
+#else
+#define nmk_gpio_dbg_show	NULL
+#endif
+
 /* This structure is replicated for each GPIO block allocated at probe time */
 static struct gpio_chip nmk_gpio_template = {
 	.direction_input	= nmk_gpio_make_input,
@@ -612,10 +892,64 @@ static struct gpio_chip nmk_gpio_template = {
 	.direction_output	= nmk_gpio_make_output,
 	.set			= nmk_gpio_set_output,
 	.to_irq			= nmk_gpio_to_irq,
-	.ngpio			= NMK_GPIO_PER_CHIP,
+	.dbg_show		= nmk_gpio_dbg_show,
 	.can_sleep		= 0,
 };
 
+/*
+ * Called from the suspend/resume path to only keep the real wakeup interrupts
+ * (those that have had set_irq_wake() called on them) as wakeup interrupts,
+ * and not the rest of the interrupts which we needed to have as wakeups for
+ * cpuidle.
+ *
+ * PM ops are not used since this needs to be done at the end, after all the
+ * other drivers are done with their suspend callbacks.
+ */
+void nmk_gpio_wakeups_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
+		chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
+
+		writel(chip->rwimsc & chip->real_wake,
+		       chip->addr + NMK_GPIO_RWIMSC);
+		writel(chip->fwimsc & chip->real_wake,
+		       chip->addr + NMK_GPIO_FWIMSC);
+
+		if (cpu_is_u8500v2()) {
+			chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
+
+			/* 0 -> wakeup enable */
+			writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
+		}
+	}
+}
+
+void nmk_gpio_wakeups_resume(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
+		writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
+
+		if (cpu_is_u8500v2())
+			writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
 static int __devinit nmk_gpio_probe(struct platform_device *dev)
 {
 	struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
@@ -623,6 +957,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 	struct gpio_chip *chip;
 	struct resource *res;
 	struct clk *clk;
+	int secondary_irq;
 	int irq;
 	int ret;
 
@@ -641,6 +976,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 		goto out;
 	}
 
+	secondary_irq = platform_get_irq(dev, 1);
+	if (secondary_irq >= 0 && !pdata->get_secondary_status) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	if (request_mem_region(res->start, resource_size(res),
 			       dev_name(&dev->dev)) == NULL) {
 		ret = -EBUSY;
@@ -664,14 +1005,19 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 	 * The virt address in nmk_chip->addr is in the nomadik register space,
 	 * so we can simply convert the resource address, without remapping
 	 */
+	nmk_chip->bank = dev->id;
 	nmk_chip->clk = clk;
 	nmk_chip->addr = io_p2v(res->start);
 	nmk_chip->chip = nmk_gpio_template;
 	nmk_chip->parent_irq = irq;
+	nmk_chip->secondary_parent_irq = secondary_irq;
+	nmk_chip->get_secondary_status = pdata->get_secondary_status;
+	nmk_chip->set_ioforce = pdata->set_ioforce;
 	spin_lock_init(&nmk_chip->lock);
 
 	chip = &nmk_chip->chip;
 	chip->base = pdata->first_gpio;
+	chip->ngpio = pdata->num_gpio;
 	chip->label = pdata->name ?: dev_name(&dev->dev);
 	chip->dev = &dev->dev;
 	chip->owner = THIS_MODULE;
@@ -680,6 +1026,9 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 	if (ret)
 		goto out_free;
 
+	BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
+
+	nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
 	platform_set_drvdata(dev, nmk_chip);
 
 	nmk_gpio_init_irq(nmk_chip);
@@ -705,10 +1054,8 @@ static struct platform_driver nmk_gpio_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "gpio",
-		},
+	},
 	.probe = nmk_gpio_probe,
-	.suspend = NULL, /* to be done */
-	.resume = NULL,
 };
 
 static int __init nmk_gpio_init(void)
diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h
index 67b113d..1b9f6f0 100644
--- a/arch/arm/plat-nomadik/include/plat/gpio.h
+++ b/arch/arm/plat-nomadik/include/plat/gpio.h
@@ -75,6 +75,9 @@ extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull);
 extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
 extern int nmk_gpio_get_mode(int gpio);
 
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
 /*
  * Platform data to register a block: only the initial gpio/irq number.
  */
@@ -82,6 +85,9 @@ struct nmk_gpio_platform_data {
 	char *name;
 	int first_gpio;
 	int first_irq;
+	int num_gpio;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
 };
 
 #endif /* __ASM_PLAT_GPIO_H */
diff --git a/arch/arm/plat-nomadik/include/plat/ste_dma40.h b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
index 4d6dd4c..c448860 100644
--- a/arch/arm/plat-nomadik/include/plat/ste_dma40.h
+++ b/arch/arm/plat-nomadik/include/plat/ste_dma40.h
@@ -104,6 +104,8 @@ struct stedma40_half_channel_info {
  *
  * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH
  * @high_priority: true if high-priority
+ * @realtime: true if realtime mode is to be enabled.  Only available on DMA40
+ * version 3+, i.e DB8500v2+
  * @mode: channel mode: physical, logical, or operation
  * @mode_opt: options for the chosen channel mode
  * @src_dev_type: Src device type
@@ -119,6 +121,7 @@ struct stedma40_half_channel_info {
 struct stedma40_chan_cfg {
 	enum stedma40_xfer_dir			 dir;
 	bool					 high_priority;
+	bool					 realtime;
 	enum stedma40_mode			 mode;
 	enum stedma40_mode_opt			 mode_opt;
 	int					 src_dev_type;
@@ -169,25 +172,6 @@ struct stedma40_platform_data {
 bool stedma40_filter(struct dma_chan *chan, void *data);
 
 /**
- * stedma40_memcpy_sg() - extension of the dma framework, memcpy to/from
- * scattergatter lists.
- *
- * @chan: dmaengine handle
- * @sgl_dst: Destination scatter list
- * @sgl_src: Source scatter list
- * @sgl_len: The length of each scatterlist. Both lists must be of equal length
- * and each element must match the corresponding element in the other scatter
- * list.
- * @flags: is actually enum dma_ctrl_flags. See dmaengine.h
- */
-
-struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan,
-						   struct scatterlist *sgl_dst,
-						   struct scatterlist *sgl_src,
-						   unsigned int sgl_len,
-						   unsigned long flags);
-
-/**
  * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave
  * (=device)
  *
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index b6333ae..cd5f993 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -54,7 +54,7 @@ config OMAP_SMARTREFLEX
 	  user must write 1 to
 		/debug/voltage/vdd_<X>/smartreflex/autocomp,
 	  where X is mpu or core for OMAP3.
-	  Optionallly autocompensation can be enabled in the kernel
+	  Optionally autocompensation can be enabled in the kernel
 	  by default during system init via the enable_on_init flag
 	  which an be passed as platform data to the smartreflex driver.
 
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index fc62fb5..c9122dd 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -37,14 +37,16 @@ static struct clk_functions *arch_clock;
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret;
 
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
+	if (!arch_clock || !arch_clock->clk_enable)
+		return -EINVAL;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_enable)
-		ret = arch_clock->clk_enable(clk);
+	ret = arch_clock->clk_enable(clk);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -58,6 +60,9 @@ void clk_disable(struct clk *clk)
 	if (clk == NULL || IS_ERR(clk))
 		return;
 
+	if (!arch_clock || !arch_clock->clk_disable)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
 		pr_err("Trying disable clock %s with 0 usecount\n",
@@ -66,8 +71,7 @@ void clk_disable(struct clk *clk)
 		goto out;
 	}
 
-	if (arch_clock->clk_disable)
-		arch_clock->clk_disable(clk);
+	arch_clock->clk_disable(clk);
 
 out:
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -77,7 +81,7 @@ EXPORT_SYMBOL(clk_disable);
 unsigned long clk_get_rate(struct clk *clk)
 {
 	unsigned long flags;
-	unsigned long ret = 0;
+	unsigned long ret;
 
 	if (clk == NULL || IS_ERR(clk))
 		return 0;
@@ -97,14 +101,16 @@ EXPORT_SYMBOL(clk_get_rate);
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
-	long ret = 0;
+	long ret;
 
 	if (clk == NULL || IS_ERR(clk))
-		return ret;
+		return 0;
+
+	if (!arch_clock || !arch_clock->clk_round_rate)
+		return 0;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_round_rate)
-		ret = arch_clock->clk_round_rate(clk, rate);
+	ret = arch_clock->clk_round_rate(clk, rate);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -119,14 +125,13 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	if (clk == NULL || IS_ERR(clk))
 		return ret;
 
+	if (!arch_clock || !arch_clock->clk_set_rate)
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_set_rate)
-		ret = arch_clock->clk_set_rate(clk, rate);
-	if (ret == 0) {
-		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
+	ret = arch_clock->clk_set_rate(clk, rate);
+	if (ret == 0)
 		propagate_rate(clk);
-	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -141,15 +146,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
 		return ret;
 
+	if (!arch_clock || !arch_clock->clk_set_parent)
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
-		if (arch_clock->clk_set_parent)
-			ret = arch_clock->clk_set_parent(clk, parent);
-		if (ret == 0) {
-			if (clk->recalc)
-				clk->rate = clk->recalc(clk);
+		ret = arch_clock->clk_set_parent(clk, parent);
+		if (ret == 0)
 			propagate_rate(clk);
-		}
 	} else
 		ret = -EBUSY;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -335,6 +339,38 @@ struct clk *omap_clk_get_by_name(const char *name)
 	return ret;
 }
 
+int omap_clk_enable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->allow_idle)
+			c->ops->allow_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
+int omap_clk_disable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->deny_idle)
+			c->ops->deny_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
 /*
  * Low level helpers
  */
@@ -367,9 +403,11 @@ void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
 {
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_init_cpufreq_table)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_init_cpufreq_table)
-		arch_clock->clk_init_cpufreq_table(table);
+	arch_clock->clk_init_cpufreq_table(table);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 
@@ -377,9 +415,11 @@ void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
 {
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_exit_cpufreq_table)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_exit_cpufreq_table)
-		arch_clock->clk_exit_cpufreq_table(table);
+	arch_clock->clk_exit_cpufreq_table(table);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 #endif
@@ -397,6 +437,9 @@ static int __init clk_disable_unused(void)
 	struct clk *ck;
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_disable_unused)
+		return 0;
+
 	pr_info("clock: disabling unused clocks to save power\n");
 	list_for_each_entry(ck, &clocks, node) {
 		if (ck->ops == &clkops_null)
@@ -406,14 +449,14 @@ static int __init clk_disable_unused(void)
 			continue;
 
 		spin_lock_irqsave(&clockfw_lock, flags);
-		if (arch_clock->clk_disable_unused)
-			arch_clock->clk_disable_unused(ck);
+		arch_clock->clk_disable_unused(ck);
 		spin_unlock_irqrestore(&clockfw_lock, flags);
 	}
 
 	return 0;
 }
 late_initcall(clk_disable_unused);
+late_initcall(omap_clk_enable_autoidle_all);
 #endif
 
 int __init clk_init(struct clk_functions * custom_clocks)
diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c
index f047318..d9f10a3 100644
--- a/arch/arm/plat-omap/common.c
+++ b/arch/arm/plat-omap/common.c
@@ -24,10 +24,11 @@
 
 #define NO_LENGTH_CHECK 0xffffffff
 
-struct omap_board_config_kernel *omap_board_config;
+struct omap_board_config_kernel *omap_board_config __initdata;
 int omap_board_config_size;
 
-static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
+static const void *__init get_config(u16 tag, size_t len,
+		int skip, size_t *len_out)
 {
 	struct omap_board_config_kernel *kinfo = NULL;
 	int i;
@@ -49,17 +50,15 @@ static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
 	return kinfo->data;
 }
 
-const void *__omap_get_config(u16 tag, size_t len, int nr)
+const void *__init __omap_get_config(u16 tag, size_t len, int nr)
 {
         return get_config(tag, len, nr, NULL);
 }
-EXPORT_SYMBOL(__omap_get_config);
 
-const void *omap_get_var_config(u16 tag, size_t *len)
+const void *__init omap_get_var_config(u16 tag, size_t *len)
 {
         return get_config(tag, NO_LENGTH_CHECK, 0, len);
 }
-EXPORT_SYMBOL(omap_get_var_config);
 
 void __init omap_reserve(void)
 {
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 862dda9..f7fed60 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -54,7 +54,7 @@ static cycle_t notrace omap16xx_32k_read(struct clocksource *cs)
 #define omap16xx_32k_read	NULL
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
@@ -63,7 +63,7 @@ static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
 #define omap2420_32k_read	NULL
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
index 11c54ec..da4f68d 100644
--- a/arch/arm/plat-omap/cpu-omap.c
+++ b/arch/arm/plat-omap/cpu-omap.c
@@ -101,7 +101,7 @@ static int omap_target(struct cpufreq_policy *policy,
 	return ret;
 }
 
-static int __init omap_cpu_init(struct cpufreq_policy *policy)
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
 {
 	int result = 0;
 
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index 10245b8..7d9f815 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -35,8 +35,8 @@
 
 static struct platform_device **omap_mcbsp_devices;
 
-void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
-					int size)
+void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
 {
 	int i;
 
@@ -54,6 +54,8 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
 		if (!new_mcbsp)
 			continue;
+		platform_device_add_resources(new_mcbsp, &res[i * res_count],
+					res_count);
 		new_mcbsp->dev.platform_data = &config[i];
 		ret = platform_device_add(new_mcbsp);
 		if (ret) {
@@ -65,8 +67,8 @@ void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
 }
 
 #else
-void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
-					int size)
+void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
 {  }
 #endif
 
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index 8536308..2ec3b5d 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -134,7 +134,7 @@ static inline void omap_enable_channel_irq(int lch);
 
 #ifdef CONFIG_ARCH_OMAP15XX
 /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
-int omap_dma_in_1510_mode(void)
+static int omap_dma_in_1510_mode(void)
 {
 	return enable_1510_mode;
 }
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 1d706cf..ee9f6eb 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -342,6 +342,10 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 
+	/* Enable autoidle on OMAP2 / OMAP3 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		l |= 0x1 << 0;
+
 	/*
 	 * Enable wake-up on OMAP2 CPUs.
 	 */
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index a4f8003..3341ca4 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -112,6 +112,7 @@ static inline int omap1_i2c_add_bus(int bus_id)
 }
 
 
+#ifdef CONFIG_ARCH_OMAP2PLUS
 /*
  * XXX This function is a temporary compatibility wrapper - only
  * needed until the I2C driver can be converted to call
@@ -130,7 +131,6 @@ static struct omap_device_pm_latency omap_i2c_latency[] = {
 	},
 };
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
 static inline int omap2_i2c_add_bus(int bus_id)
 {
 	int l;
diff --git a/arch/arm/plat-omap/include/plat/board.h b/arch/arm/plat-omap/include/plat/board.h
index 3cf4fa2..97126df 100644
--- a/arch/arm/plat-omap/include/plat/board.h
+++ b/arch/arm/plat-omap/include/plat/board.h
@@ -151,14 +151,14 @@ struct omap_board_config_kernel {
 	const void *data;
 };
 
-extern const void *__omap_get_config(u16 tag, size_t len, int nr);
+extern const void *__init __omap_get_config(u16 tag, size_t len, int nr);
 
 #define omap_get_config(tag, type) \
 	((const type *) __omap_get_config((tag), sizeof(type), 0))
 #define omap_get_nr_config(tag, type, nr) \
 	((const type *) __omap_get_config((tag), sizeof(type), (nr)))
 
-extern const void *omap_get_var_config(u16 tag, size_t *len);
+extern const void *__init omap_get_var_config(u16 tag, size_t *len);
 
 extern struct omap_board_config_kernel *omap_board_config;
 extern int omap_board_config_size;
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
index 256ab3f..f1899a3 100644
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
@@ -38,6 +38,7 @@ struct omap_clk {
 #define CK_3517		(1 << 9)
 #define CK_36XX		(1 << 10)	/* 36xx/37xx-specific clocks */
 #define CK_443X		(1 << 11)
+#define CK_TI816X	(1 << 12)
 
 
 #define CK_34XX		(CK_3430ES1 | CK_3430ES2PLUS)
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 8eb0ada..006e599 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -25,6 +25,8 @@ struct clockdomain;
  * @disable: fn ptr that enables the current clock in hardware
  * @find_idlest: function returning the IDLEST register for the clock's IP blk
  * @find_companion: function returning the "companion" clk reg for the clock
+ * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
+ * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
  *
  * A "companion" clk is an accompanying clock to the one being queried
  * that must be enabled for the IP module connected to the clock to
@@ -42,6 +44,8 @@ struct clkops {
 					       u8 *, u8 *);
 	void			(*find_companion)(struct clk *, void __iomem **,
 						  u8 *);
+	void			(*allow_idle)(struct clk *);
+	void			(*deny_idle)(struct clk *);
 };
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
@@ -53,6 +57,7 @@ struct clkops {
 #define RATE_IN_3430ES2PLUS	(1 << 3)	/* 3430 ES >= 2 rates only */
 #define RATE_IN_36XX		(1 << 4)
 #define RATE_IN_4430		(1 << 5)
+#define RATE_IN_TI816X		(1 << 6)
 
 #define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
 #define RATE_IN_34XX		(RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
@@ -104,7 +109,6 @@ struct clksel {
  * @clk_ref: struct clk pointer to the clock's reference clock input
  * @control_reg: register containing the DPLL mode bitfield
  * @enable_mask: mask of the DPLL mode bitfield in @control_reg
- * @rate_tolerance: maximum variance allowed from target rate (in Hz)
  * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
  * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
  * @max_multiplier: maximum valid non-bypass multiplier value (actual)
@@ -130,12 +134,9 @@ struct clksel {
  * XXX Some DPLLs have multiple bypass inputs, so it's not technically
  * correct to only have one @clk_bypass pointer.
  *
- * XXX @rate_tolerance should probably be deprecated - currently there
- * don't seem to be any usecases for DPLL rounding that is not exact.
- *
  * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
  * @last_rounded_n) should be separated from the runtime-fixed fields
- * and placed into a differenct structure, so that the runtime-fixed data
+ * and placed into a different structure, so that the runtime-fixed data
  * can be placed into read-only space.
  */
 struct dpll_data {
@@ -146,7 +147,6 @@ struct dpll_data {
 	struct clk		*clk_ref;
 	void __iomem		*control_reg;
 	u32			enable_mask;
-	unsigned int		rate_tolerance;
 	unsigned long		last_rounded_rate;
 	u16			last_rounded_m;
 	u16			max_multiplier;
@@ -171,12 +171,24 @@ struct dpll_data {
 
 #endif
 
-/* struct clk.flags possibilities */
+/*
+ * struct clk.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ */
 #define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
 #define CLOCK_IDLE_CONTROL	(1 << 1)
 #define CLOCK_NO_IDLE_PARENT	(1 << 2)
 #define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
 #define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2		(1 << 5)
 
 /**
  * struct clk - OMAP struct clk
@@ -292,6 +304,8 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
 extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
 #endif
 extern struct clk *omap_clk_get_by_name(const char *name);
+extern int omap_clk_enable_autoidle_all(void);
+extern int omap_clk_disable_autoidle_all(void);
 
 extern const struct clkops clkops_null;
 
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 29b2afb..5288130 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -56,16 +56,13 @@ struct omap_globals {
 	unsigned long   prm;            /* Power and Reset Management */
 	unsigned long   cm;             /* Clock Management */
 	unsigned long   cm2;
-	unsigned long	uart1_phys;
-	unsigned long	uart2_phys;
-	unsigned long	uart3_phys;
-	unsigned long	uart4_phys;
 };
 
 void omap2_set_globals_242x(void);
 void omap2_set_globals_243x(void);
 void omap2_set_globals_3xxx(void);
 void omap2_set_globals_443x(void);
+void omap2_set_globals_ti816x(void);
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
 void omap2_set_globals_tap(struct omap_globals *);
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 3fd8b40..8198bb6 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2004, 2008 Nokia Corporation
  *
- * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2009-11 Texas Instruments.
  *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
@@ -105,6 +105,12 @@ static inline int is_omap ##subclass (void)		\
 	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
 }
 
+#define IS_TI_SUBCLASS(subclass, id)			\
+static inline int is_ti ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
 IS_OMAP_CLASS(7xx, 0x07)
 IS_OMAP_CLASS(15xx, 0x15)
 IS_OMAP_CLASS(16xx, 0x16)
@@ -118,6 +124,8 @@ IS_OMAP_SUBCLASS(343x, 0x343)
 IS_OMAP_SUBCLASS(363x, 0x363)
 IS_OMAP_SUBCLASS(443x, 0x443)
 
+IS_TI_SUBCLASS(816x, 0x816)
+
 #define cpu_is_omap7xx()		0
 #define cpu_is_omap15xx()		0
 #define cpu_is_omap16xx()		0
@@ -126,6 +134,7 @@ IS_OMAP_SUBCLASS(443x, 0x443)
 #define cpu_is_omap243x()		0
 #define cpu_is_omap34xx()		0
 #define cpu_is_omap343x()		0
+#define cpu_is_ti816x()			0
 #define cpu_is_omap44xx()		0
 #define cpu_is_omap443x()		0
 
@@ -170,11 +179,11 @@ IS_OMAP_SUBCLASS(443x, 0x443)
 #  undef  cpu_is_omap24xx
 #  define cpu_is_omap24xx()		is_omap24xx()
 # endif
-# if defined (CONFIG_ARCH_OMAP2420)
+# if defined (CONFIG_SOC_OMAP2420)
 #  undef  cpu_is_omap242x
 #  define cpu_is_omap242x()		is_omap242x()
 # endif
-# if defined (CONFIG_ARCH_OMAP2430)
+# if defined (CONFIG_SOC_OMAP2430)
 #  undef  cpu_is_omap243x
 #  define cpu_is_omap243x()		is_omap243x()
 # endif
@@ -189,11 +198,11 @@ IS_OMAP_SUBCLASS(443x, 0x443)
 #  undef  cpu_is_omap24xx
 #  define cpu_is_omap24xx()		1
 # endif
-# if defined(CONFIG_ARCH_OMAP2420)
+# if defined(CONFIG_SOC_OMAP2420)
 #  undef  cpu_is_omap242x
 #  define cpu_is_omap242x()		1
 # endif
-# if defined(CONFIG_ARCH_OMAP2430)
+# if defined(CONFIG_SOC_OMAP2430)
 #  undef  cpu_is_omap243x
 #  define cpu_is_omap243x()		1
 # endif
@@ -201,7 +210,7 @@ IS_OMAP_SUBCLASS(443x, 0x443)
 #  undef  cpu_is_omap34xx
 #  define cpu_is_omap34xx()		1
 # endif
-# if defined(CONFIG_ARCH_OMAP3430)
+# if defined(CONFIG_SOC_OMAP3430)
 #  undef  cpu_is_omap343x
 #  define cpu_is_omap343x()		1
 # endif
@@ -330,6 +339,7 @@ IS_OMAP_TYPE(3517, 0x3517)
 # undef cpu_is_omap3530
 # undef cpu_is_omap3505
 # undef cpu_is_omap3517
+# undef cpu_is_ti816x
 # define cpu_is_omap3430()		is_omap3430()
 # define cpu_is_omap3503()		(cpu_is_omap3430() &&		\
 						(!omap3_has_iva()) &&	\
@@ -345,6 +355,7 @@ IS_OMAP_TYPE(3517, 0x3517)
 # define cpu_is_omap3517()		is_omap3517()
 # undef cpu_is_omap3630
 # define cpu_is_omap3630()		is_omap363x()
+# define cpu_is_ti816x()		is_ti816x()
 #endif
 
 # if defined(CONFIG_ARCH_OMAP4)
@@ -389,9 +400,15 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP3505_REV(v)		(OMAP35XX_CLASS | (0x3505 << 16) | (v << 8))
 #define OMAP3517_REV(v)		(OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
 
+#define TI816X_CLASS		0x81600034
+#define TI8168_REV_ES1_0	TI816X_CLASS
+#define TI8168_REV_ES1_1	(TI816X_CLASS | (OMAP_REVBITS_01 << 8))
+
 #define OMAP443X_CLASS		0x44300044
-#define OMAP4430_REV_ES1_0	OMAP443X_CLASS
-#define OMAP4430_REV_ES2_0	0x44301044
+#define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
+#define OMAP4430_REV_ES2_0	(OMAP443X_CLASS | (0x20 << 8))
+#define OMAP4430_REV_ES2_1	(OMAP443X_CLASS | (0x21 << 8))
+#define OMAP4430_REV_ES2_2	(OMAP443X_CLASS | (0x22 << 8))
 
 /*
  * omap_chip bits
@@ -419,11 +436,16 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define CHIP_IS_OMAP3630ES1_1           (1 << 9)
 #define CHIP_IS_OMAP3630ES1_2           (1 << 10)
 #define CHIP_IS_OMAP4430ES2		(1 << 11)
+#define CHIP_IS_OMAP4430ES2_1		(1 << 12)
+#define CHIP_IS_OMAP4430ES2_2		(1 << 13)
+#define CHIP_IS_TI816X			(1 << 14)
 
 #define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
-#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 | \
-						 CHIP_IS_OMAP4430ES2)
+#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 |		\
+					 CHIP_IS_OMAP4430ES2 |		\
+					 CHIP_IS_OMAP4430ES2_1 |	\
+					 CHIP_IS_OMAP4430ES2_2)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
@@ -455,6 +477,7 @@ extern u32 omap3_features;
 #define OMAP3_HAS_ISP			BIT(4)
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
+#define OMAP3_HAS_SDRC			BIT(7)
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
 static inline unsigned int omap3_has_ ##feat(void)	\
@@ -469,5 +492,6 @@ OMAP3_HAS_FEATURE(neon, NEON)
 OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
+OMAP3_HAS_FEATURE(sdrc, SDRC)
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/display.h b/arch/arm/plat-omap/include/plat/display.h
index 537f4e4..0f140ec 100644
--- a/arch/arm/plat-omap/include/plat/display.h
+++ b/arch/arm/plat-omap/include/plat/display.h
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
+#include <linux/platform_device.h>
 #include <asm/atomic.h>
 
 #define DISPC_IRQ_FRAMEDONE		(1 << 0)
@@ -226,6 +227,16 @@ struct omap_dss_board_info {
 	struct omap_dss_device *default_device;
 };
 
+#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
+/* Init with the board info */
+extern int omap_display_init(struct omap_dss_board_info *board_data);
+#else
+static inline int omap_display_init(struct omap_dss_board_info *board_data)
+{
+	return 0;
+}
+#endif
+
 struct omap_video_timings {
 	/* Unit: pixels */
 	u16 x_res;
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index dfa3aff..d6c70d2 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -3,6 +3,12 @@
  *
  * OMAP Dual-Mode Timers
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Platform device conversion and hwmod support.
+ *
  * Copyright (C) 2005 Nokia Corporation
  * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
  * PWM and clock framwork support by Timo Teras.
@@ -44,6 +50,11 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
 
+/*
+ * IP revision identifier so that Highlander IP
+ * in OMAP4 can be distinguished.
+ */
+#define OMAP_TIMER_IP_VERSION_1                        0x1
 struct omap_dm_timer;
 extern struct omap_dm_timer *gptimer_wakeup;
 extern struct sys_timer omap_timer;
diff --git a/arch/arm/plat-omap/include/plat/fpga.h b/arch/arm/plat-omap/include/plat/fpga.h
index ae39bcb..bd3c632 100644
--- a/arch/arm/plat-omap/include/plat/fpga.h
+++ b/arch/arm/plat-omap/include/plat/fpga.h
@@ -30,18 +30,18 @@ extern void omap1510_fpga_init_irq(void);
  * ---------------------------------------------------------------------------
  */
 /* maps in the FPGA registers and the ETHR registers */
-#define H2P2_DBG_FPGA_BASE		IOMEM(0xE8000000)	/* VA */
+#define H2P2_DBG_FPGA_BASE		0xE8000000		/* VA */
 #define H2P2_DBG_FPGA_SIZE		SZ_4K			/* SIZE */
 #define H2P2_DBG_FPGA_START		0x04000000		/* PA */
 
 #define H2P2_DBG_FPGA_ETHR_START	(H2P2_DBG_FPGA_START + 0x300)
-#define H2P2_DBG_FPGA_FPGA_REV		(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
-#define H2P2_DBG_FPGA_BOARD_REV		(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
-#define H2P2_DBG_FPGA_GPIO		(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
-#define H2P2_DBG_FPGA_LEDS		(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
-#define H2P2_DBG_FPGA_MISC_INPUTS	(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
-#define H2P2_DBG_FPGA_LAN_STATUS	(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
-#define H2P2_DBG_FPGA_LAN_RESET		(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
+#define H2P2_DBG_FPGA_FPGA_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
+#define H2P2_DBG_FPGA_GPIO		IOMEM(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS		IOMEM(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS	IOMEM(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS	IOMEM(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET		IOMEM(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
 
 /* NOTE:  most boards don't have a static mapping for the FPGA ... */
 struct h2p2_dbg_fpga {
@@ -81,55 +81,55 @@ struct h2p2_dbg_fpga {
  *  OMAP-1510 FPGA
  * ---------------------------------------------------------------------------
  */
-#define OMAP1510_FPGA_BASE		IOMEM(0xE8000000)	/* VA */
+#define OMAP1510_FPGA_BASE		0xE8000000		/* VA */
 #define OMAP1510_FPGA_SIZE		SZ_4K
 #define OMAP1510_FPGA_START		0x08000000		/* PA */
 
 /* Revision */
-#define OMAP1510_FPGA_REV_LOW			(OMAP1510_FPGA_BASE + 0x0)
-#define OMAP1510_FPGA_REV_HIGH			(OMAP1510_FPGA_BASE + 0x1)
+#define OMAP1510_FPGA_REV_LOW			IOMEM(OMAP1510_FPGA_BASE + 0x0)
+#define OMAP1510_FPGA_REV_HIGH			IOMEM(OMAP1510_FPGA_BASE + 0x1)
 
-#define OMAP1510_FPGA_LCD_PANEL_CONTROL		(OMAP1510_FPGA_BASE + 0x2)
-#define OMAP1510_FPGA_LED_DIGIT			(OMAP1510_FPGA_BASE + 0x3)
-#define INNOVATOR_FPGA_HID_SPI			(OMAP1510_FPGA_BASE + 0x4)
-#define OMAP1510_FPGA_POWER			(OMAP1510_FPGA_BASE + 0x5)
+#define OMAP1510_FPGA_LCD_PANEL_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x2)
+#define OMAP1510_FPGA_LED_DIGIT			IOMEM(OMAP1510_FPGA_BASE + 0x3)
+#define INNOVATOR_FPGA_HID_SPI			IOMEM(OMAP1510_FPGA_BASE + 0x4)
+#define OMAP1510_FPGA_POWER			IOMEM(OMAP1510_FPGA_BASE + 0x5)
 
 /* Interrupt status */
-#define OMAP1510_FPGA_ISR_LO			(OMAP1510_FPGA_BASE + 0x6)
-#define OMAP1510_FPGA_ISR_HI			(OMAP1510_FPGA_BASE + 0x7)
+#define OMAP1510_FPGA_ISR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x6)
+#define OMAP1510_FPGA_ISR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x7)
 
 /* Interrupt mask */
-#define OMAP1510_FPGA_IMR_LO			(OMAP1510_FPGA_BASE + 0x8)
-#define OMAP1510_FPGA_IMR_HI			(OMAP1510_FPGA_BASE + 0x9)
+#define OMAP1510_FPGA_IMR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x8)
+#define OMAP1510_FPGA_IMR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x9)
 
 /* Reset registers */
-#define OMAP1510_FPGA_HOST_RESET		(OMAP1510_FPGA_BASE + 0xa)
-#define OMAP1510_FPGA_RST			(OMAP1510_FPGA_BASE + 0xb)
-
-#define OMAP1510_FPGA_AUDIO			(OMAP1510_FPGA_BASE + 0xc)
-#define OMAP1510_FPGA_DIP			(OMAP1510_FPGA_BASE + 0xe)
-#define OMAP1510_FPGA_FPGA_IO			(OMAP1510_FPGA_BASE + 0xf)
-#define OMAP1510_FPGA_UART1			(OMAP1510_FPGA_BASE + 0x14)
-#define OMAP1510_FPGA_UART2			(OMAP1510_FPGA_BASE + 0x15)
-#define OMAP1510_FPGA_OMAP1510_STATUS		(OMAP1510_FPGA_BASE + 0x16)
-#define OMAP1510_FPGA_BOARD_REV			(OMAP1510_FPGA_BASE + 0x18)
-#define OMAP1510P1_PPT_DATA			(OMAP1510_FPGA_BASE + 0x100)
-#define OMAP1510P1_PPT_STATUS			(OMAP1510_FPGA_BASE + 0x101)
-#define OMAP1510P1_PPT_CONTROL			(OMAP1510_FPGA_BASE + 0x102)
-
-#define OMAP1510_FPGA_TOUCHSCREEN		(OMAP1510_FPGA_BASE + 0x204)
-
-#define INNOVATOR_FPGA_INFO			(OMAP1510_FPGA_BASE + 0x205)
-#define INNOVATOR_FPGA_LCD_BRIGHT_LO		(OMAP1510_FPGA_BASE + 0x206)
-#define INNOVATOR_FPGA_LCD_BRIGHT_HI		(OMAP1510_FPGA_BASE + 0x207)
-#define INNOVATOR_FPGA_LED_GRN_LO		(OMAP1510_FPGA_BASE + 0x208)
-#define INNOVATOR_FPGA_LED_GRN_HI		(OMAP1510_FPGA_BASE + 0x209)
-#define INNOVATOR_FPGA_LED_RED_LO		(OMAP1510_FPGA_BASE + 0x20a)
-#define INNOVATOR_FPGA_LED_RED_HI		(OMAP1510_FPGA_BASE + 0x20b)
-#define INNOVATOR_FPGA_CAM_USB_CONTROL		(OMAP1510_FPGA_BASE + 0x20c)
-#define INNOVATOR_FPGA_EXP_CONTROL		(OMAP1510_FPGA_BASE + 0x20d)
-#define INNOVATOR_FPGA_ISR2			(OMAP1510_FPGA_BASE + 0x20e)
-#define INNOVATOR_FPGA_IMR2			(OMAP1510_FPGA_BASE + 0x210)
+#define OMAP1510_FPGA_HOST_RESET		IOMEM(OMAP1510_FPGA_BASE + 0xa)
+#define OMAP1510_FPGA_RST			IOMEM(OMAP1510_FPGA_BASE + 0xb)
+
+#define OMAP1510_FPGA_AUDIO			IOMEM(OMAP1510_FPGA_BASE + 0xc)
+#define OMAP1510_FPGA_DIP			IOMEM(OMAP1510_FPGA_BASE + 0xe)
+#define OMAP1510_FPGA_FPGA_IO			IOMEM(OMAP1510_FPGA_BASE + 0xf)
+#define OMAP1510_FPGA_UART1			IOMEM(OMAP1510_FPGA_BASE + 0x14)
+#define OMAP1510_FPGA_UART2			IOMEM(OMAP1510_FPGA_BASE + 0x15)
+#define OMAP1510_FPGA_OMAP1510_STATUS		IOMEM(OMAP1510_FPGA_BASE + 0x16)
+#define OMAP1510_FPGA_BOARD_REV			IOMEM(OMAP1510_FPGA_BASE + 0x18)
+#define OMAP1510P1_PPT_DATA			IOMEM(OMAP1510_FPGA_BASE + 0x100)
+#define OMAP1510P1_PPT_STATUS			IOMEM(OMAP1510_FPGA_BASE + 0x101)
+#define OMAP1510P1_PPT_CONTROL			IOMEM(OMAP1510_FPGA_BASE + 0x102)
+
+#define OMAP1510_FPGA_TOUCHSCREEN		IOMEM(OMAP1510_FPGA_BASE + 0x204)
+
+#define INNOVATOR_FPGA_INFO			IOMEM(OMAP1510_FPGA_BASE + 0x205)
+#define INNOVATOR_FPGA_LCD_BRIGHT_LO		IOMEM(OMAP1510_FPGA_BASE + 0x206)
+#define INNOVATOR_FPGA_LCD_BRIGHT_HI		IOMEM(OMAP1510_FPGA_BASE + 0x207)
+#define INNOVATOR_FPGA_LED_GRN_LO		IOMEM(OMAP1510_FPGA_BASE + 0x208)
+#define INNOVATOR_FPGA_LED_GRN_HI		IOMEM(OMAP1510_FPGA_BASE + 0x209)
+#define INNOVATOR_FPGA_LED_RED_LO		IOMEM(OMAP1510_FPGA_BASE + 0x20a)
+#define INNOVATOR_FPGA_LED_RED_HI		IOMEM(OMAP1510_FPGA_BASE + 0x20b)
+#define INNOVATOR_FPGA_CAM_USB_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20c)
+#define INNOVATOR_FPGA_EXP_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20d)
+#define INNOVATOR_FPGA_ISR2			IOMEM(OMAP1510_FPGA_BASE + 0x20e)
+#define INNOVATOR_FPGA_IMR2			IOMEM(OMAP1510_FPGA_BASE + 0x210)
 
 #define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
 
diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h
index 85ded59..12b3161 100644
--- a/arch/arm/plat-omap/include/plat/gpmc.h
+++ b/arch/arm/plat-omap/include/plat/gpmc.h
@@ -41,6 +41,8 @@
 #define GPMC_NAND_ADDRESS	0x0000000b
 #define GPMC_NAND_DATA		0x0000000c
 
+#define GPMC_ENABLE_IRQ		0x0000000d
+
 /* ECC commands */
 #define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
 #define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
@@ -78,6 +80,19 @@
 #define WR_RD_PIN_MONITORING		0x00600000
 #define GPMC_PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
 #define GPMC_PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
+#define GPMC_IRQ_FIFOEVENTENABLE	0x01
+#define GPMC_IRQ_COUNT_EVENT		0x02
+
+#define PREFETCH_FIFOTHRESHOLD_MAX	0x40
+#define PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
+
+enum omap_ecc {
+		/* 1-bit ecc: stored at end of spare area */
+	OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
+	OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
+		/* 1-bit ecc: stored at begining of spare area as romcode */
+	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
+};
 
 /*
  * Note that all values in this struct are in nanoseconds except sync_clk
@@ -130,12 +145,11 @@ extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
 extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
-extern int gpmc_prefetch_enable(int cs, int dma_mode,
+extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 					unsigned int u32_count, int is_write);
 extern int gpmc_prefetch_reset(int cs);
 extern void omap3_gpmc_save_context(void);
 extern void omap3_gpmc_restore_context(void);
-extern void gpmc_init(void);
 extern int gpmc_read_status(int cmd);
 extern int gpmc_cs_configure(int cs, int cmd, int wval);
 extern int gpmc_nand_read(int cs, int cmd);
diff --git a/arch/arm/plat-omap/include/plat/hardware.h b/arch/arm/plat-omap/include/plat/hardware.h
index d5b26ad..e87efe1 100644
--- a/arch/arm/plat-omap/include/plat/hardware.h
+++ b/arch/arm/plat-omap/include/plat/hardware.h
@@ -286,5 +286,6 @@
 #include <plat/omap24xx.h>
 #include <plat/omap34xx.h>
 #include <plat/omap44xx.h>
+#include <plat/ti816x.h>
 
 #endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h
index ef4106c..d72ec85 100644
--- a/arch/arm/plat-omap/include/plat/io.h
+++ b/arch/arm/plat-omap/include/plat/io.h
@@ -259,7 +259,7 @@ struct omap_sdrc_params;
 extern void omap1_map_common_io(void);
 extern void omap1_init_common_hw(void);
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 extern void omap242x_map_common_io(void);
 #else
 static inline void omap242x_map_common_io(void)
@@ -267,7 +267,7 @@ static inline void omap242x_map_common_io(void)
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 extern void omap243x_map_common_io(void);
 #else
 static inline void omap243x_map_common_io(void)
@@ -283,6 +283,14 @@ static inline void omap34xx_map_common_io(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAPTI816X
+extern void omapti816x_map_common_io(void);
+#else
+static inline void omapti816x_map_common_io(void)
+{
+}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP4
 extern void omap44xx_map_common_io(void);
 #else
diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h
index 69230d6..174f1b9 100644
--- a/arch/arm/plat-omap/include/plat/iommu.h
+++ b/arch/arm/plat-omap/include/plat/iommu.h
@@ -31,6 +31,7 @@ struct iommu {
 	struct clk	*clk;
 	void __iomem	*regbase;
 	struct device	*dev;
+	void		*isr_priv;
 
 	unsigned int	refcount;
 	struct mutex	iommu_lock;	/* global for this whole object */
@@ -47,7 +48,7 @@ struct iommu {
 	struct list_head	mmap;
 	struct mutex		mmap_lock; /* protect mmap */
 
-	int (*isr)(struct iommu *obj);
+	int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
 
 	void *ctx; /* iommu context: registres saved area */
 	u32 da_start;
@@ -109,6 +110,13 @@ struct iommu_platform_data {
 	u32 da_end;
 };
 
+/* IOMMU errors */
+#define OMAP_IOMMU_ERR_TLB_MISS		(1 << 0)
+#define OMAP_IOMMU_ERR_TRANS_FAULT	(1 << 1)
+#define OMAP_IOMMU_ERR_EMU_MISS		(1 << 2)
+#define OMAP_IOMMU_ERR_TBLWALK_FAULT	(1 << 3)
+#define OMAP_IOMMU_ERR_MULTIHIT_FAULT	(1 << 4)
+
 #if defined(CONFIG_ARCH_OMAP1)
 #error "iommu for this processor not implemented yet"
 #else
@@ -154,11 +162,17 @@ extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end);
 extern void flush_iotlb_all(struct iommu *obj);
 
 extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
+extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd,
+				   u32 **ppte);
 extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
 
 extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
 extern struct iommu *iommu_get(const char *name);
 extern void iommu_put(struct iommu *obj);
+extern int iommu_set_isr(const char *name,
+			 int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
+				    void *priv),
+			 void *isr_priv);
 
 extern void iommu_save_ctx(struct iommu *obj);
 extern void iommu_restore_ctx(struct iommu *obj);
diff --git a/arch/arm/plat-omap/include/plat/iovmm.h b/arch/arm/plat-omap/include/plat/iovmm.h
index bdc7ce5..32a2f6c 100644
--- a/arch/arm/plat-omap/include/plat/iovmm.h
+++ b/arch/arm/plat-omap/include/plat/iovmm.h
@@ -71,8 +71,6 @@ struct iovm_struct {
 #define IOVMF_LINEAR_MASK	(3 << (2 + IOVMF_SW_SHIFT))
 
 #define IOVMF_DA_FIXED		(1 << (4 + IOVMF_SW_SHIFT))
-#define IOVMF_DA_ANON		(2 << (4 + IOVMF_SW_SHIFT))
-#define IOVMF_DA_MASK		(3 << (4 + IOVMF_SW_SHIFT))
 
 
 extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da);
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 2910de9..d779283 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -315,9 +315,12 @@
 #define INT_34XX_SSM_ABORT_IRQ	6
 #define INT_34XX_SYS_NIRQ	7
 #define INT_34XX_D2D_FW_IRQ	8
+#define INT_34XX_L3_DBG_IRQ     9
+#define INT_34XX_L3_APP_IRQ     10
 #define INT_34XX_PRCM_MPU_IRQ	11
 #define INT_34XX_MCBSP1_IRQ	16
 #define INT_34XX_MCBSP2_IRQ	17
+#define INT_34XX_GPMC_IRQ	20
 #define INT_34XX_MCBSP3_IRQ	22
 #define INT_34XX_MCBSP4_IRQ	23
 #define INT_34XX_CAM_IRQ	24
@@ -411,7 +414,13 @@
 #define TWL_IRQ_END		TWL6030_IRQ_END
 #endif
 
-#define NR_IRQS			TWL_IRQ_END
+/* GPMC related */
+#define OMAP_GPMC_IRQ_BASE	(TWL_IRQ_END)
+#define OMAP_GPMC_NR_IRQS	7
+#define OMAP_GPMC_IRQ_END	(OMAP_GPMC_IRQ_BASE + OMAP_GPMC_NR_IRQS)
+
+
+#define NR_IRQS			OMAP_GPMC_IRQ_END
 
 #define OMAP_IRQ_BIT(irq)	(1 << ((irq) % 32))
 
diff --git a/arch/arm/plat-omap/include/plat/l3_2xxx.h b/arch/arm/plat-omap/include/plat/l3_2xxx.h
new file mode 100644
index 0000000..b8b5641
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/l3_2xxx.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-omap/include/plat/l3_2xxx.h - L3 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
+
+/* L3 CONNIDs */
+/* Display Sub system (DSS) */
+#define OMAP2_L3_CORE_FW_CONNID_DSS			8
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/l3_3xxx.h b/arch/arm/plat-omap/include/plat/l3_3xxx.h
new file mode 100644
index 0000000..cde1938
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/l3_3xxx.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-omap/include/plat/l3_3xxx.h - L3 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
+
+/* L3 Initiator IDs */
+/* Display Sub system (DSS) */
+#define OMAP3_L3_CORE_FW_INIT_ID_DSS			29
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/l4_2xxx.h b/arch/arm/plat-omap/include/plat/l4_2xxx.h
new file mode 100644
index 0000000..3f39cf8
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/l4_2xxx.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/plat-omap/include/plat/l4_2xxx.h - L4 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
+
+/* L4 CORE */
+/* Display Sub system (DSS) */
+#define OMAP2420_L4_CORE_FW_DSS_CORE_REGION			28
+#define OMAP2420_L4_CORE_FW_DSS_DISPC_REGION			29
+#define OMAP2420_L4_CORE_FW_DSS_RFBI_REGION			30
+#define OMAP2420_L4_CORE_FW_DSS_VENC_REGION			31
+#define OMAP2420_L4_CORE_FW_DSS_TA_REGION			32
+
+#endif
diff --git a/arch/arm/plat-omap/include/plat/l4_3xxx.h b/arch/arm/plat-omap/include/plat/l4_3xxx.h
index 5e19493..881a858 100644
--- a/arch/arm/plat-omap/include/plat/l4_3xxx.h
+++ b/arch/arm/plat-omap/include/plat/l4_3xxx.h
@@ -21,4 +21,14 @@
 #define OMAP3_L4_CORE_FW_I2C3_REGION				73
 #define OMAP3_L4_CORE_FW_I2C3_TA_REGION				74
 
+/* Display Sub system (DSS) */
+#define OMAP3_L4_CORE_FW_DSS_PROT_GROUP				2
+
+#define OMAP3_L4_CORE_FW_DSS_DSI_REGION				104
+#define OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION			3
+#define OMAP3_L4_CORE_FW_DSS_CORE_REGION			4
+#define OMAP3_L4_CORE_FW_DSS_DISPC_REGION			4
+#define OMAP3_L4_CORE_FW_DSS_RFBI_REGION			5
+#define OMAP3_L4_CORE_FW_DSS_VENC_REGION			6
+#define OMAP3_L4_CORE_FW_DSS_TA_REGION				7
 #endif
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index b87d83c..f8f690a 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -37,6 +37,10 @@ static struct platform_device omap_mcbsp##port_nr = {	\
 	.id	= OMAP_MCBSP##port_nr,			\
 }
 
+#define MCBSP_CONFIG_TYPE2	0x2
+#define MCBSP_CONFIG_TYPE3	0x3
+#define MCBSP_CONFIG_TYPE4	0x4
+
 #define OMAP7XX_MCBSP1_BASE	0xfffb1000
 #define OMAP7XX_MCBSP2_BASE	0xfffb1800
 
@@ -48,32 +52,14 @@ static struct platform_device omap_mcbsp##port_nr = {	\
 #define OMAP1610_MCBSP2_BASE	0xfffb1000
 #define OMAP1610_MCBSP3_BASE	0xe1017000
 
-#define OMAP24XX_MCBSP1_BASE	0x48074000
-#define OMAP24XX_MCBSP2_BASE	0x48076000
-#define OMAP2430_MCBSP3_BASE	0x4808c000
-#define OMAP2430_MCBSP4_BASE	0x4808e000
-#define OMAP2430_MCBSP5_BASE	0x48096000
-
-#define OMAP34XX_MCBSP1_BASE	0x48074000
-#define OMAP34XX_MCBSP2_BASE	0x49022000
-#define OMAP34XX_MCBSP2_ST_BASE	0x49028000
-#define OMAP34XX_MCBSP3_BASE	0x49024000
-#define OMAP34XX_MCBSP3_ST_BASE	0x4902A000
-#define OMAP34XX_MCBSP3_BASE	0x49024000
-#define OMAP34XX_MCBSP4_BASE	0x49026000
-#define OMAP34XX_MCBSP5_BASE	0x48096000
-
-#define OMAP44XX_MCBSP1_BASE	0x49022000
-#define OMAP44XX_MCBSP2_BASE	0x49024000
-#define OMAP44XX_MCBSP3_BASE	0x49026000
-#define OMAP44XX_MCBSP4_BASE	0x48096000
-
-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+#ifdef CONFIG_ARCH_OMAP1
 
 #define OMAP_MCBSP_REG_DRR2	0x00
 #define OMAP_MCBSP_REG_DRR1	0x02
 #define OMAP_MCBSP_REG_DXR2	0x04
 #define OMAP_MCBSP_REG_DXR1	0x06
+#define OMAP_MCBSP_REG_DRR	0x02
+#define OMAP_MCBSP_REG_DXR	0x06
 #define OMAP_MCBSP_REG_SPCR2	0x08
 #define OMAP_MCBSP_REG_SPCR1	0x0a
 #define OMAP_MCBSP_REG_RCR2	0x0c
@@ -106,13 +92,6 @@ static struct platform_device omap_mcbsp##port_nr = {	\
 #define OMAP_MCBSP_REG_XCCR	0x00
 #define OMAP_MCBSP_REG_RCCR	0x00
 
-#define AUDIO_MCBSP_DATAWRITE	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
-#define AUDIO_MCBSP_DATAREAD	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
-
-#define AUDIO_MCBSP		OMAP_MCBSP1
-#define AUDIO_DMA_TX		OMAP_DMA_MCBSP1_TX
-#define AUDIO_DMA_RX		OMAP_DMA_MCBSP1_RX
-
 #else
 
 #define OMAP_MCBSP_REG_DRR2	0x00
@@ -168,13 +147,6 @@ static struct platform_device omap_mcbsp##port_nr = {	\
 #define OMAP_ST_REG_SFIRCR	0x28
 #define OMAP_ST_REG_SSELCR	0x2C
 
-#define AUDIO_MCBSP_DATAWRITE	(OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
-#define AUDIO_MCBSP_DATAREAD	(OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
-
-#define AUDIO_MCBSP		OMAP_MCBSP2
-#define AUDIO_DMA_TX		OMAP24XX_DMA_MCBSP2_TX
-#define AUDIO_DMA_RX		OMAP24XX_DMA_MCBSP2_RX
-
 #endif
 
 /************************** McBSP SPCR1 bit definitions ***********************/
@@ -428,8 +400,9 @@ struct omap_mcbsp_platform_data {
 #ifdef CONFIG_ARCH_OMAP3
 	/* Sidetone block for McBSP 2 and 3 */
 	unsigned long phys_base_st;
-	u16 buffer_size;
 #endif
+	u16 buffer_size;
+	unsigned int mcbsp_config_type;
 };
 
 struct omap_mcbsp_st_data {
@@ -445,6 +418,7 @@ struct omap_mcbsp_st_data {
 struct omap_mcbsp {
 	struct device *dev;
 	unsigned long phys_base;
+	unsigned long phys_dma_base;
 	void __iomem *io_base;
 	u8 id;
 	u8 free;
@@ -471,7 +445,6 @@ struct omap_mcbsp {
 	/* Protect the field .free, while checking if the mcbsp is in use */
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
-	struct clk *iclk;
 	struct clk *fclk;
 #ifdef CONFIG_ARCH_OMAP3
 	struct omap_mcbsp_st_data *st_data;
@@ -480,7 +453,17 @@ struct omap_mcbsp {
 	u16 max_rx_thres;
 #endif
 	void *reg_cache;
+	unsigned int mcbsp_config_type;
 };
+
+/**
+ * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
+ * @sidetone: name of the sidetone device
+ */
+struct omap_mcbsp_dev_attr {
+	const char *sidetone;
+};
+
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count, omap_mcbsp_cache_size;
 
@@ -488,8 +471,8 @@ extern int omap_mcbsp_count, omap_mcbsp_cache_size;
 #define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
 
 int omap_mcbsp_init(void);
-void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
-					int size);
+void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size);
 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
 #ifdef CONFIG_ARCH_OMAP3
 void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
@@ -539,6 +522,9 @@ int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
 void omap2_mcbsp1_mux_clkr_src(u8 mux);
 void omap2_mcbsp1_mux_fsr_src(u8 mux);
 
+int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
+int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
+
 #ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
diff --git a/arch/arm/plat-omap/include/plat/mcspi.h b/arch/arm/plat-omap/include/plat/mcspi.h
index 1254e49..3d51b18 100644
--- a/arch/arm/plat-omap/include/plat/mcspi.h
+++ b/arch/arm/plat-omap/include/plat/mcspi.h
@@ -1,8 +1,19 @@
 #ifndef _OMAP2_MCSPI_H
 #define _OMAP2_MCSPI_H
 
+#define OMAP2_MCSPI_REV 0
+#define OMAP3_MCSPI_REV 1
+#define OMAP4_MCSPI_REV 2
+
+#define OMAP4_MCSPI_REG_OFFSET 0x100
+
 struct omap2_mcspi_platform_config {
 	unsigned short	num_cs;
+	unsigned int regs_offset;
+};
+
+struct omap2_mcspi_dev_attr {
+	unsigned short num_chipselect;
 };
 
 struct omap2_mcspi_device_config {
diff --git a/arch/arm/plat-omap/include/plat/memory.h b/arch/arm/plat-omap/include/plat/memory.h
index f8d922f..e6720aa 100644
--- a/arch/arm/plat-omap/include/plat/memory.h
+++ b/arch/arm/plat-omap/include/plat/memory.h
@@ -37,9 +37,9 @@
  * Physical DRAM offset.
  */
 #if defined(CONFIG_ARCH_OMAP1)
-#define PHYS_OFFSET		UL(0x10000000)
+#define PLAT_PHYS_OFFSET		UL(0x10000000)
 #else
-#define PHYS_OFFSET		UL(0x80000000)
+#define PLAT_PHYS_OFFSET		UL(0x80000000)
 #endif
 
 /*
diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
index f57f36a..f38fef9 100644
--- a/arch/arm/plat-omap/include/plat/mmc.h
+++ b/arch/arm/plat-omap/include/plat/mmc.h
@@ -24,25 +24,19 @@
 #define OMAP1_MMC2_BASE		0xfffb7c00	/* omap16xx only */
 
 #define OMAP24XX_NR_MMC		2
-#define OMAP34XX_NR_MMC		3
-#define OMAP44XX_NR_MMC		5
 #define OMAP2420_MMC_SIZE	OMAP1_MMC_SIZE
-#define OMAP3_HSMMC_SIZE	0x200
-#define OMAP4_HSMMC_SIZE	0x1000
 #define OMAP2_MMC1_BASE		0x4809c000
-#define OMAP2_MMC2_BASE		0x480b4000
-#define OMAP3_MMC3_BASE		0x480ad000
-#define OMAP4_MMC4_BASE		0x480d1000
-#define OMAP4_MMC5_BASE		0x480d5000
+
 #define OMAP4_MMC_REG_OFFSET	0x100
-#define HSMMC5			(1 << 4)
-#define HSMMC4			(1 << 3)
-#define HSMMC3			(1 << 2)
-#define HSMMC2			(1 << 1)
-#define HSMMC1			(1 << 0)
 
 #define OMAP_MMC_MAX_SLOTS	2
 
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT	BIT(1)
+
+struct omap_mmc_dev_attr {
+	u8 flags;
+};
+
 struct omap_mmc_platform_data {
 	/* back-link to device */
 	struct device *dev;
@@ -71,6 +65,9 @@ struct omap_mmc_platform_data {
 
 	u64 dma_mask;
 
+	/* Integrating attributes from the omap_hwmod layer */
+	u8 controller_flags;
+
 	/* Register offset deviation */
 	u16 reg_offset;
 
@@ -159,8 +156,7 @@ extern void omap_mmc_notify_cover_event(struct device *dev, int slot,
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
 				int nr_controllers);
-void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
-				int nr_controllers);
+void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data);
 int omap_mmc_add(const char *name, int id, unsigned long base,
 				unsigned long size, unsigned int irq,
 				struct omap_mmc_platform_data *data);
@@ -169,8 +165,7 @@ static inline void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
 				int nr_controllers)
 {
 }
-static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
-				int nr_controllers)
+static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
 {
 }
 static inline int omap_mmc_add(const char *name, int id, unsigned long base,
diff --git a/arch/arm/plat-omap/include/plat/multi.h b/arch/arm/plat-omap/include/plat/multi.h
index ffd909f..999ffba 100644
--- a/arch/arm/plat-omap/include/plat/multi.h
+++ b/arch/arm/plat-omap/include/plat/multi.h
@@ -66,7 +66,7 @@
 #  error "OMAP1 and OMAP2PLUS can't be selected at the same time"
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP2
 #  define MULTI_OMAP2
@@ -74,7 +74,7 @@
 #  define OMAP_NAME omap2420
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP2
 #  define MULTI_OMAP2
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 6562cd0..d86d1ec 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -8,8 +8,16 @@
  * published by the Free Software Foundation.
  */
 
+#include <plat/gpmc.h>
 #include <linux/mtd/partitions.h>
 
+enum nand_io {
+	NAND_OMAP_PREFETCH_POLLED = 0,	/* prefetch polled mode, default */
+	NAND_OMAP_POLLED,		/* polled mode, without prefetch */
+	NAND_OMAP_PREFETCH_DMA,		/* prefetch enabled sDMA mode */
+	NAND_OMAP_PREFETCH_IRQ		/* prefetch enabled irq mode */
+};
+
 struct omap_nand_platform_data {
 	unsigned int		options;
 	int			cs;
@@ -20,8 +28,11 @@ struct omap_nand_platform_data {
 	int			(*nand_setup)(void);
 	int			(*dev_ready)(struct omap_nand_platform_data *);
 	int			dma_channel;
+	int			gpmc_irq;
+	enum nand_io		xfer_type;
 	unsigned long		phys_base;
 	int			devsize;
+	enum omap_ecc           ecc_opt;
 };
 
 /* minimum size for IO mapping */
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 1eee85a..1adea9c 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod macros, structures
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  * Paul Walmsley
  *
  * Created in collaboration with (alphabetical order): BenoĂŽt Cousson,
@@ -30,11 +30,11 @@
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
 
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <plat/cpu.h>
-#include <plat/voltage.h>
 
 struct omap_device;
 
@@ -90,6 +90,9 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
 struct omap_hwmod_mux_info {
 	int				nr_pads;
 	struct omap_device_pad		*pads;
+	int				nr_pads_dynamic;
+	struct omap_device_pad		**pads_dynamic;
+	bool				enabled;
 };
 
 /**
@@ -124,6 +127,7 @@ struct omap_hwmod_dma_info {
  * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
  * @name: name of the reset line (module local name)
  * @rst_shift: Offset of the reset bit
+ * @st_shift: Offset of the reset status bit (OMAP2/3 only)
  *
  * @name should be something short, e.g., "cpu0" or "rst". It is defined
  * locally to the hwmod.
@@ -131,6 +135,7 @@ struct omap_hwmod_dma_info {
 struct omap_hwmod_rst_info {
 	const char	*name;
 	u8		rst_shift;
+	u8		st_shift;
 };
 
 /**
@@ -178,7 +183,8 @@ struct omap_hwmod_omap2_firewall {
 #define ADDR_TYPE_RT		(1 << 1)
 
 /**
- * struct omap_hwmod_addr_space - MPU address space handled by the hwmod
+ * struct omap_hwmod_addr_space - address space handled by the hwmod
+ * @name: name of the address space
  * @pa_start: starting physical address
  * @pa_end: ending physical address
  * @flags: (see omap_hwmod_addr_space.flags macros above)
@@ -187,6 +193,7 @@ struct omap_hwmod_omap2_firewall {
  * structure.  GPMC is one example.
  */
 struct omap_hwmod_addr_space {
+	const char *name;
 	u32 pa_start;
 	u32 pa_end;
 	u8 flags;
@@ -370,9 +377,11 @@ struct omap_hwmod_omap4_prcm {
  *     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
  * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
  *     controller, etc. XXX probably belongs outside the main hwmod file
- * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
+ *     XXX Should be HWMOD_SETUP_NO_IDLE
+ * HWMOD_NO_OCP_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
  *     when module is enabled, rather than the default, which is to
  *     enable autoidle
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
@@ -535,11 +544,12 @@ struct omap_hwmod {
 	const struct omap_chip_id	omap_chip;
 };
 
-int omap_hwmod_init(struct omap_hwmod **ohs);
+int omap_hwmod_register(struct omap_hwmod **ohs);
 struct omap_hwmod *omap_hwmod_lookup(const char *name);
 int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
 			void *data);
-int omap_hwmod_late_init(void);
+
+int __init omap_hwmod_setup_one(const char *name);
 
 int omap_hwmod_enable(struct omap_hwmod *oh);
 int _omap_hwmod_enable(struct omap_hwmod *oh);
@@ -555,6 +565,7 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
 int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
 
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
@@ -589,6 +600,8 @@ int omap_hwmod_for_each_by_class(const char *classname,
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
 u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
diff --git a/arch/arm/plat-omap/include/plat/onenand.h b/arch/arm/plat-omap/include/plat/onenand.h
index affe87e..cbe897c 100644
--- a/arch/arm/plat-omap/include/plat/onenand.h
+++ b/arch/arm/plat-omap/include/plat/onenand.h
@@ -15,12 +15,20 @@
 #define ONENAND_SYNC_READ	(1 << 0)
 #define ONENAND_SYNC_READWRITE	(1 << 1)
 
+struct onenand_freq_info {
+	u16			maf_id;
+	u16			dev_id;
+	u16			ver_id;
+};
+
 struct omap_onenand_platform_data {
 	int			cs;
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	int			nr_parts;
-	int                     (*onenand_setup)(void __iomem *, int freq);
+	int			(*onenand_setup)(void __iomem *, int *freq_ptr);
+	int		(*get_freq)(const struct onenand_freq_info *freq_info,
+				    bool *clk_dep);
 	int			dma_channel;
 	u8			flags;
 	u8			regulator_can_sleep;
diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h
index 2fdf8c8..267f43b 100644
--- a/arch/arm/plat-omap/include/plat/prcm.h
+++ b/arch/arm/plat-omap/include/plat/prcm.h
@@ -28,7 +28,6 @@
 #define __ASM_ARM_ARCH_OMAP_PRCM_H
 
 u32 omap_prcm_get_reset_sources(void);
-void omap_prcm_arch_reset(char mode, const char *cmd);
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);
 
diff --git a/arch/arm/plat-omap/include/plat/sdrc.h b/arch/arm/plat-omap/include/plat/sdrc.h
index efd87c8..925b12b 100644
--- a/arch/arm/plat-omap/include/plat/sdrc.h
+++ b/arch/arm/plat-omap/include/plat/sdrc.h
@@ -124,8 +124,14 @@ struct omap_sdrc_params {
 	u32 mr;
 };
 
-void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+void omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 			    struct omap_sdrc_params *sdrc_cs1);
+#else
+static inline void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+					  struct omap_sdrc_params *sdrc_cs1) {};
+#endif
+
 int omap2_sdrc_get_params(unsigned long r,
 			  struct omap_sdrc_params **sdrc_cs0,
 			  struct omap_sdrc_params **sdrc_cs1);
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index cec5d56..2723f91 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -27,7 +27,7 @@
  * 2. We assume printascii is called at least once before paging_init,
  *    and addruart has a chance to read OMAP_UART_INFO
  */
-#define OMAP_UART_INFO		(PHYS_OFFSET + 0x3ffc)
+#define OMAP_UART_INFO		(PLAT_PHYS_OFFSET + 0x3ffc)
 
 /* OMAP1 serial ports */
 #define OMAP1_UART1_BASE	0xfffb0000
@@ -51,6 +51,11 @@
 #define OMAP4_UART3_BASE	0x48020000
 #define OMAP4_UART4_BASE	0x4806e000
 
+/* TI816X serial ports */
+#define TI816X_UART1_BASE	0x48020000
+#define TI816X_UART2_BASE	0x48022000
+#define TI816X_UART3_BASE	0x48024000
+
 /* External port on Zoom2/3 */
 #define ZOOM_UART_BASE		0x10000000
 #define ZOOM_UART_VIRT		0xfa400000
@@ -81,6 +86,9 @@
 #define OMAP4UART2		OMAP2UART2
 #define OMAP4UART3		43
 #define OMAP4UART4		44
+#define TI816XUART1		81
+#define TI816XUART2		82
+#define TI816XUART3		83
 #define ZOOM_UART		95		/* Only on zoom2/3 */
 
 /* This is only used by 8250.c for omap1510 */
@@ -96,7 +104,6 @@
 
 struct omap_board_data;
 
-extern void __init omap_serial_early_init(void);
 extern void omap_serial_init(void);
 extern void omap_serial_init_port(struct omap_board_data *bdata);
 extern int omap_uart_can_sleep(void);
diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h
deleted file mode 100644
index 6568c88..0000000
--- a/arch/arm/plat-omap/include/plat/smartreflex.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * OMAP Smartreflex Defines and Routines
- *
- * Author: Thara Gopinath	<thara@ti.com>
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2008 Nokia Corporation
- * Kalle Jokiniemi
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Lesly A M <x0080970@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 __ASM_ARM_OMAP_SMARTREFLEX_H
-#define __ASM_ARM_OMAP_SMARTREFLEX_H
-
-#include <linux/platform_device.h>
-#include <plat/voltage.h>
-
-/*
- * Different Smartreflex IPs version. The v1 is the 65nm version used in
- * OMAP3430. The v2 is the update for the 45nm version of the IP
- * used in OMAP3630 and OMAP4430
- */
-#define SR_TYPE_V1	1
-#define SR_TYPE_V2	2
-
-/* SMART REFLEX REG ADDRESS OFFSET */
-#define SRCONFIG		0x00
-#define SRSTATUS		0x04
-#define SENVAL			0x08
-#define SENMIN			0x0C
-#define SENMAX			0x10
-#define SENAVG			0x14
-#define AVGWEIGHT		0x18
-#define NVALUERECIPROCAL	0x1c
-#define SENERROR_V1		0x20
-#define ERRCONFIG_V1		0x24
-#define IRQ_EOI			0x20
-#define IRQSTATUS_RAW		0x24
-#define IRQSTATUS		0x28
-#define IRQENABLE_SET		0x2C
-#define IRQENABLE_CLR		0x30
-#define SENERROR_V2		0x34
-#define ERRCONFIG_V2		0x38
-
-/* Bit/Shift Positions */
-
-/* SRCONFIG */
-#define SRCONFIG_ACCUMDATA_SHIFT	22
-#define SRCONFIG_SRCLKLENGTH_SHIFT	12
-#define SRCONFIG_SENNENABLE_V1_SHIFT	5
-#define SRCONFIG_SENPENABLE_V1_SHIFT	3
-#define SRCONFIG_SENNENABLE_V2_SHIFT	1
-#define SRCONFIG_SENPENABLE_V2_SHIFT	0
-#define SRCONFIG_CLKCTRL_SHIFT		0
-
-#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
-
-#define SRCONFIG_SRENABLE		BIT(11)
-#define SRCONFIG_SENENABLE		BIT(10)
-#define SRCONFIG_ERRGEN_EN		BIT(9)
-#define SRCONFIG_MINMAXAVG_EN		BIT(8)
-#define SRCONFIG_DELAYCTRL		BIT(2)
-
-/* AVGWEIGHT */
-#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
-#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
-
-/* NVALUERECIPROCAL */
-#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
-#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
-#define NVALUERECIPROCAL_RNSENP_SHIFT	8
-#define NVALUERECIPROCAL_RNSENN_SHIFT	0
-
-/* ERRCONFIG */
-#define ERRCONFIG_ERRWEIGHT_SHIFT	16
-#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
-#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
-
-#define SR_ERRWEIGHT_MASK		(0x07 << 16)
-#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
-#define SR_ERRMINLIMIT_MASK		(0xff << 0)
-
-#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
-#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
-#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
-#define ERRCONFIG_MCUACCUMINTST		BIT(28)
-#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
-#define ERRCONFIG_MCUVALIDINTST		BIT(26)
-#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
-#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
-#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
-#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
-#define ERRCONFIG_MCUDISACKINTST	BIT(22)
-#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
-
-#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
-					ERRCONFIG_MCUACCUMINTST | \
-					ERRCONFIG_MCUVALIDINTST | \
-					ERRCONFIG_MCUBOUNDINTST | \
-					ERRCONFIG_MCUDISACKINTST)
-/* IRQSTATUS */
-#define IRQSTATUS_MCUACCUMINT		BIT(3)
-#define IRQSTATUS_MCVALIDINT		BIT(2)
-#define IRQSTATUS_MCBOUNDSINT		BIT(1)
-#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
-
-/* IRQENABLE_SET and IRQENABLE_CLEAR */
-#define IRQENABLE_MCUACCUMINT		BIT(3)
-#define IRQENABLE_MCUVALIDINT		BIT(2)
-#define IRQENABLE_MCUBOUNDSINT		BIT(1)
-#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
-
-/* Common Bit values */
-
-#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
-#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
-#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
-#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
-#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
-
-/*
- * 3430 specific values. Maybe these should be passed from board file or
- * pmic structures.
- */
-#define OMAP3430_SR_ACCUMDATA		0x1f4
-
-#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
-#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
-
-#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
-#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
-
-#define OMAP3430_SR_ERRWEIGHT		0x04
-#define OMAP3430_SR_ERRMAXLIMIT		0x02
-
-/**
- * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
- *				pmic specific info to smartreflex driver
- *
- * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
- */
-struct omap_sr_pmic_data {
-	void (*sr_pmic_init) (void);
-};
-
-#ifdef CONFIG_OMAP_SMARTREFLEX
-/*
- * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
- * The smartreflex class driver should pass the class type.
- * Should be used to populate the class_type field of the
- * omap_smartreflex_class_data structure.
- */
-#define SR_CLASS1	0x1
-#define SR_CLASS2	0x2
-#define SR_CLASS3	0x3
-
-/**
- * struct omap_sr_class_data - Smartreflex class driver info
- *
- * @enable:		API to enable a particular class smaartreflex.
- * @disable:		API to disable a particular class smartreflex.
- * @configure:		API to configure a particular class smartreflex.
- * @notify:		API to notify the class driver about an event in SR.
- *			Not needed for class3.
- * @notify_flags:	specify the events to be notified to the class driver
- * @class_type:		specify which smartreflex class.
- *			Can be used by the SR driver to take any class
- *			based decisions.
- */
-struct omap_sr_class_data {
-	int (*enable)(struct voltagedomain *voltdm);
-	int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
-	int (*configure)(struct voltagedomain *voltdm);
-	int (*notify)(struct voltagedomain *voltdm, u32 status);
-	u8 notify_flags;
-	u8 class_type;
-};
-
-/**
- * struct omap_sr_nvalue_table	- Smartreflex n-target value info
- *
- * @efuse_offs:	The offset of the efuse where n-target values are stored.
- * @nvalue:	The n-target value.
- */
-struct omap_sr_nvalue_table {
-	u32 efuse_offs;
-	u32 nvalue;
-};
-
-/**
- * struct omap_sr_data - Smartreflex platform data.
- *
- * @ip_type:		Smartreflex IP type.
- * @senp_mod:		SENPENABLE value for the sr
- * @senn_mod:		SENNENABLE value for sr
- * @nvalue_count:	Number of distinct nvalues in the nvalue table
- * @enable_on_init:	whether this sr module needs to enabled at
- *			boot up or not.
- * @nvalue_table:	table containing the  efuse offsets and nvalues
- *			corresponding to them.
- * @voltdm:		Pointer to the voltage domain associated with the SR
- */
-struct omap_sr_data {
-	int				ip_type;
-	u32				senp_mod;
-	u32				senn_mod;
-	int				nvalue_count;
-	bool				enable_on_init;
-	struct omap_sr_nvalue_table	*nvalue_table;
-	struct voltagedomain		*voltdm;
-};
-
-/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct voltagedomain *voltdm);
-void omap_sr_disable(struct voltagedomain *voltdm);
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
-
-/* API to register the pmic specific data with the smartreflex driver. */
-void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
-
-/* Smartreflex driver hooks to be called from Smartreflex class driver */
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
-void sr_disable(struct voltagedomain *voltdm);
-int sr_configure_errgen(struct voltagedomain *voltdm);
-int sr_configure_minmax(struct voltagedomain *voltdm);
-
-/* API to register the smartreflex class driver with the smartreflex driver */
-int sr_register_class(struct omap_sr_class_data *class_data);
-#else
-static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable_reset_volt(
-		struct voltagedomain *voltdm) {}
-static inline void omap_sr_register_pmic(
-		struct omap_sr_pmic_data *pmic_data) {}
-#endif
-#endif
diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h
index 9967d5e..f500fc3 100644
--- a/arch/arm/plat-omap/include/plat/sram.h
+++ b/arch/arm/plat-omap/include/plat/sram.h
@@ -12,7 +12,19 @@
 #define __ARCH_ARM_OMAP_SRAM_H
 
 #ifndef __ASSEMBLY__
-extern void * omap_sram_push(void * start, unsigned long size);
+#include <asm/fncpy.h>
+
+extern void *omap_sram_push_address(unsigned long size);
+
+/* Macro to push a function to the internal SRAM, using the fncpy API */
+#define omap_sram_push(funcp, size) ({				\
+	typeof(&(funcp)) _res = NULL;				\
+	void *_sram_address = omap_sram_push_address(size);	\
+	if (_sram_address)					\
+		_res = fncpy(_sram_address, &(funcp), size);	\
+	_res;							\
+})
+
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
 extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
diff --git a/arch/arm/plat-omap/include/plat/system.h b/arch/arm/plat-omap/include/plat/system.h
index d0a119f..c5fa9e9 100644
--- a/arch/arm/plat-omap/include/plat/system.h
+++ b/arch/arm/plat-omap/include/plat/system.h
@@ -4,48 +4,14 @@
  */
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
-#include <linux/clk.h>
 
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-
-#include <plat/prcm.h>
-
-#ifndef CONFIG_MACH_VOICEBLUE
-#define voiceblue_reset()		do {} while (0)
-#else
-extern void voiceblue_reset(void);
-#endif
+#include <asm/proc-fns.h>
 
 static inline void arch_idle(void)
 {
 	cpu_do_idle();
 }
 
-static inline void omap1_arch_reset(char mode, const char *cmd)
-{
-	/*
-	 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
-	 * "Global Software Reset Affects Traffic Controller Frequency".
-	 */
-	if (cpu_is_omap5912()) {
-		omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4),
-				 DPLL_CTL);
-		omap_writew(0x8, ARM_RSTCT1);
-	}
-
-	if (machine_is_voiceblue())
-		voiceblue_reset();
-	else
-		omap_writew(1, ARM_RSTCT1);
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	if (!cpu_class_is_omap2())
-		omap1_arch_reset(mode, cmd);
-	else
-		omap_prcm_arch_reset(mode, cmd);
-}
+extern void (*arch_reset)(char, const char *);
 
 #endif
diff --git a/arch/arm/plat-omap/include/plat/ti816x.h b/arch/arm/plat-omap/include/plat/ti816x.h
new file mode 100644
index 0000000..50510f5
--- /dev/null
+++ b/arch/arm/plat-omap/include/plat/ti816x.h
@@ -0,0 +1,27 @@
+/*
+ * This file contains the address data for various TI816X modules.
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc. - 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 version 2.
+ *
+ * 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 __ASM_ARCH_TI816X_H
+#define __ASM_ARCH_TI816X_H
+
+#define L4_SLOW_TI816X_BASE	0x48000000
+
+#define TI816X_SCM_BASE		0x48140000
+#define TI816X_CTRL_BASE	TI816X_SCM_BASE
+#define TI816X_PRCM_BASE	0x48180000
+
+#define TI816X_ARM_INTC_BASE	0x48200000
+
+#endif /* __ASM_ARCH_TI816X_H */
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index ad98b85..30b891c 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -93,6 +93,10 @@ static inline void flush(void)
 #define DEBUG_LL_ZOOM(mach)						\
 	_DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
 
+#define DEBUG_LL_TI816X(p, mach)					\
+	_DEBUG_LL_ENTRY(mach, TI816X_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		TI816XUART##p)
+
 static inline void __arch_decomp_setup(unsigned long arch_id)
 {
 	int port = 0;
@@ -166,6 +170,9 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 		DEBUG_LL_ZOOM(omap_zoom2);
 		DEBUG_LL_ZOOM(omap_zoom3);
 
+		/* TI8168 base boards using UART3 */
+		DEBUG_LL_TI816X(3, ti8168evm);
+
 	} while (0);
 }
 
diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 450a332..02b96c8 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -7,15 +7,12 @@
 #include <plat/board.h>
 
 #define OMAP3_HS_USB_PORTS	3
-enum ehci_hcd_omap_mode {
-	EHCI_HCD_OMAP_MODE_UNKNOWN,
-	EHCI_HCD_OMAP_MODE_PHY,
-	EHCI_HCD_OMAP_MODE_TLL,
-	EHCI_HCD_OMAP_MODE_HSIC,
-};
 
-enum ohci_omap3_port_mode {
-	OMAP_OHCI_PORT_MODE_UNUSED,
+enum usbhs_omap_port_mode {
+	OMAP_USBHS_PORT_MODE_UNUSED,
+	OMAP_EHCI_PORT_MODE_PHY,
+	OMAP_EHCI_PORT_MODE_TLL,
+	OMAP_EHCI_PORT_MODE_HSIC,
 	OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0,
 	OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM,
 	OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0,
@@ -25,24 +22,45 @@ enum ohci_omap3_port_mode {
 	OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0,
 	OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM,
 	OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM,
+	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM
 };
 
-struct ehci_hcd_omap_platform_data {
-	enum ehci_hcd_omap_mode		port_mode[OMAP3_HS_USB_PORTS];
-	unsigned			phy_reset:1;
+struct usbhs_omap_board_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
 
 	/* have to be valid if phy_reset is true and portx is in phy mode */
 	int	reset_gpio_port[OMAP3_HS_USB_PORTS];
+
+	/* Set this to true for ES2.x silicon */
+	unsigned			es2_compatibility:1;
+
+	unsigned			phy_reset:1;
+
+	/*
+	 * Regulators for USB PHYs.
+	 * Each PHY can have a separate regulator.
+	 */
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
 };
 
-struct ohci_hcd_omap_platform_data {
-	enum ohci_omap3_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+struct ehci_hcd_omap_platform_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+	int				reset_gpio_port[OMAP3_HS_USB_PORTS];
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
+	unsigned			phy_reset:1;
+};
 
-	/* Set this to true for ES2.x silicon */
+struct ohci_hcd_omap_platform_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
 	unsigned			es2_compatibility:1;
 };
 
+struct usbhs_omap_platform_data {
+	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+
+	struct ehci_hcd_omap_platform_data	*ehci_data;
+	struct ohci_hcd_omap_platform_data	*ohci_data;
+};
 /*-------------------------------------------------------------------------*/
 
 #define OMAP1_OTG_BASE			0xfffb0400
@@ -80,17 +98,22 @@ enum musb_interface    {MUSB_INTERFACE_ULPI, MUSB_INTERFACE_UTMI};
 
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 
-extern void usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata);
+extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
 
-extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata);
+extern int omap_usbhs_enable(struct device *dev);
+extern void omap_usbhs_disable(struct device *dev);
 
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);
 extern int omap4430_phy_init(struct device *dev);
 extern int omap4430_phy_exit(struct device *dev);
-
+extern int omap4430_phy_suspend(struct device *dev, int suspend);
 #endif
 
+extern void am35x_musb_reset(void);
+extern void am35x_musb_phy_power(u8 on);
+extern void am35x_musb_clear_irq(void);
+extern void am35x_musb_set_mode(u8 musb_mode);
 
 /*
  * FIXME correct answer depends on hmc_mode,
diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h
deleted file mode 100644
index 5bd204e..0000000
--- a/arch/arm/plat-omap/include/plat/voltage.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * OMAP Voltage Management Routines
- *
- * Author: Thara Gopinath	<thara@ti.com>
- *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Thara Gopinath <thara@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 __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
-#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
-
-#include <linux/err.h>
-
-#define VOLTSCALE_VPFORCEUPDATE		1
-#define VOLTSCALE_VCBYPASS		2
-
-/*
- * OMAP3 GENERIC setup times. Revisit to see if these needs to be
- * passed from board or PMIC file
- */
-#define OMAP3_CLKSETUP		0xff
-#define OMAP3_VOLTOFFSET	0xff
-#define OMAP3_VOLTSETUP2	0xff
-
-/* Voltage value defines */
-#define OMAP3430_VDD_MPU_OPP1_UV		975000
-#define OMAP3430_VDD_MPU_OPP2_UV		1075000
-#define OMAP3430_VDD_MPU_OPP3_UV		1200000
-#define OMAP3430_VDD_MPU_OPP4_UV		1270000
-#define OMAP3430_VDD_MPU_OPP5_UV		1350000
-
-#define OMAP3430_VDD_CORE_OPP1_UV		975000
-#define OMAP3430_VDD_CORE_OPP2_UV		1050000
-#define OMAP3430_VDD_CORE_OPP3_UV		1150000
-
-#define OMAP3630_VDD_MPU_OPP50_UV		1012500
-#define OMAP3630_VDD_MPU_OPP100_UV		1200000
-#define OMAP3630_VDD_MPU_OPP120_UV		1325000
-#define OMAP3630_VDD_MPU_OPP1G_UV		1375000
-
-#define OMAP3630_VDD_CORE_OPP50_UV		1000000
-#define OMAP3630_VDD_CORE_OPP100_UV		1200000
-
-#define OMAP4430_VDD_MPU_OPP50_UV		930000
-#define OMAP4430_VDD_MPU_OPP100_UV		1100000
-#define OMAP4430_VDD_MPU_OPPTURBO_UV		1260000
-#define OMAP4430_VDD_MPU_OPPNITRO_UV		1350000
-
-#define OMAP4430_VDD_IVA_OPP50_UV		930000
-#define OMAP4430_VDD_IVA_OPP100_UV		1100000
-#define OMAP4430_VDD_IVA_OPPTURBO_UV		1260000
-
-#define OMAP4430_VDD_CORE_OPP50_UV		930000
-#define OMAP4430_VDD_CORE_OPP100_UV		1100000
-
-/**
- * struct voltagedomain - omap voltage domain global structure.
- * @name:	Name of the voltage domain which can be used as a unique
- *		identifier.
- */
-struct voltagedomain {
-	char *name;
-};
-
-/**
- * struct omap_volt_data - Omap voltage specific data.
- * @voltage_nominal:	The possible voltage value in uV
- * @sr_efuse_offs:	The offset of the efuse register(from system
- *			control module base address) from where to read
- *			the n-target value for the smartreflex module.
- * @sr_errminlimit:	Error min limit value for smartreflex. This value
- *			differs at differnet opp and thus is linked
- *			with voltage.
- * @vp_errorgain:	Error gain value for the voltage processor. This
- *			field also differs according to the voltage/opp.
- */
-struct omap_volt_data {
-	u32	volt_nominal;
-	u32	sr_efuse_offs;
-	u8	sr_errminlimit;
-	u8	vp_errgain;
-};
-
-/**
- * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
- * @slew_rate:	PMIC slew rate (in uv/us)
- * @step_size:	PMIC voltage step size (in uv)
- * @vsel_to_uv:	PMIC API to convert vsel value to actual voltage in uV.
- * @uv_to_vsel:	PMIC API to convert voltage in uV to vsel value.
- */
-struct omap_volt_pmic_info {
-	int slew_rate;
-	int step_size;
-	u32 on_volt;
-	u32 onlp_volt;
-	u32 ret_volt;
-	u32 off_volt;
-	u16 volt_setup_time;
-	u8 vp_erroroffset;
-	u8 vp_vstepmin;
-	u8 vp_vstepmax;
-	u8 vp_vddmin;
-	u8 vp_vddmax;
-	u8 vp_timeout_us;
-	u8 i2c_slave_addr;
-	u8 pmic_reg;
-	unsigned long (*vsel_to_uv) (const u8 vsel);
-	u8 (*uv_to_vsel) (unsigned long uV);
-};
-
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt);
-void omap_voltage_reset(struct voltagedomain *voltdm);
-void omap_voltage_get_volttable(struct voltagedomain *voltdm,
-		struct omap_volt_data **volt_data);
-struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
-		unsigned long volt);
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
-#ifdef CONFIG_PM
-int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info);
-void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method);
-/* API to get the voltagedomain pointer */
-struct voltagedomain *omap_voltage_domain_lookup(char *name);
-
-int omap_voltage_late_init(void);
-#else
-static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
-{
-	return -EINVAL;
-}
-static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method) {}
-static inline int omap_voltage_late_init(void)
-{
-	return -EINVAL;
-}
-static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
-{
-	return ERR_PTR(-EINVAL);
-}
-#endif
-
-#endif
diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c
index f1295fa..f1ecfa9 100644
--- a/arch/arm/plat-omap/io.c
+++ b/arch/arm/plat-omap/io.c
@@ -85,7 +85,10 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP3
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_ti816x()) {
+		if (BETWEEN(p, L4_34XX_PHYS, L4_34XX_SIZE))
+			return XLATE(p, L4_34XX_PHYS, L4_34XX_VIRT);
+	} else if (cpu_is_omap34xx()) {
 		if (BETWEEN(p, L3_34XX_PHYS, L3_34XX_SIZE))
 			return XLATE(p, L3_34XX_PHYS, L3_34XX_VIRT);
 		if (BETWEEN(p, L4_34XX_PHYS, L4_34XX_SIZE))
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index b1107c0..8a51fd5 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -104,6 +104,9 @@ static int iommu_enable(struct iommu *obj)
 	if (!obj)
 		return -EINVAL;
 
+	if (!arch_iommu)
+		return -ENODEV;
+
 	clk_enable(obj->clk);
 
 	err = arch_iommu->enable(obj);
@@ -780,25 +783,19 @@ static void iopgtable_clear_entry_all(struct iommu *obj)
  */
 static irqreturn_t iommu_fault_handler(int irq, void *data)
 {
-	u32 stat, da;
+	u32 da, errs;
 	u32 *iopgd, *iopte;
-	int err = -EIO;
 	struct iommu *obj = data;
 
 	if (!obj->refcount)
 		return IRQ_NONE;
 
-	/* Dynamic loading TLB or PTE */
-	if (obj->isr)
-		err = obj->isr(obj);
-
-	if (!err)
-		return IRQ_HANDLED;
-
 	clk_enable(obj->clk);
-	stat = iommu_report_fault(obj, &da);
+	errs = iommu_report_fault(obj, &da);
 	clk_disable(obj->clk);
-	if (!stat)
+
+	/* Fault callback or TLB/PTE Dynamic loading */
+	if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
 		return IRQ_HANDLED;
 
 	iommu_disable(obj);
@@ -806,15 +803,16 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
 	iopgd = iopgd_offset(obj, da);
 
 	if (!iopgd_is_table(*iopgd)) {
-		dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
-			da, iopgd, *iopgd);
+		dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p "
+			"*pgd:px%08x\n", obj->name, errs, da, iopgd, *iopgd);
 		return IRQ_NONE;
 	}
 
 	iopte = iopte_offset(iopgd, da);
 
-	dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n",
-		__func__, da, iopgd, *iopgd, iopte, *iopte);
+	dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x "
+		"pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd,
+		iopte, *iopte);
 
 	return IRQ_NONE;
 }
@@ -917,6 +915,33 @@ void iommu_put(struct iommu *obj)
 }
 EXPORT_SYMBOL_GPL(iommu_put);
 
+int iommu_set_isr(const char *name,
+		  int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
+			     void *priv),
+		  void *isr_priv)
+{
+	struct device *dev;
+	struct iommu *obj;
+
+	dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
+				 device_match_by_alias);
+	if (!dev)
+		return -ENODEV;
+
+	obj = to_iommu(dev);
+	mutex_lock(&obj->iommu_lock);
+	if (obj->refcount != 0) {
+		mutex_unlock(&obj->iommu_lock);
+		return -EBUSY;
+	}
+	obj->isr = isr;
+	obj->isr_priv = isr_priv;
+	mutex_unlock(&obj->iommu_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_set_isr);
+
 /*
  *	OMAP Device MMU(IOMMU) detection
  */
@@ -957,11 +982,6 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
 		err = -ENODEV;
 		goto err_mem;
 	}
-	obj->regbase = ioremap(res->start, resource_size(res));
-	if (!obj->regbase) {
-		err = -ENOMEM;
-		goto err_mem;
-	}
 
 	res = request_mem_region(res->start, resource_size(res),
 				 dev_name(&pdev->dev));
@@ -970,6 +990,12 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
 		goto err_mem;
 	}
 
+	obj->regbase = ioremap(res->start, resource_size(res));
+	if (!obj->regbase) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		err = -ENODEV;
@@ -998,8 +1024,9 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev)
 err_pgd:
 	free_irq(irq, obj);
 err_irq:
-	release_mem_region(res->start, resource_size(res));
 	iounmap(obj->regbase);
+err_ioremap:
+	release_mem_region(res->start, resource_size(res));
 err_mem:
 	clk_put(obj->clk);
 err_clk:
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index 6dc1296..51ef43e 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -271,20 +271,21 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
 					   size_t bytes, u32 flags)
 {
 	struct iovm_struct *new, *tmp;
-	u32 start, prev_end, alignement;
+	u32 start, prev_end, alignment;
 
 	if (!obj || !bytes)
 		return ERR_PTR(-EINVAL);
 
 	start = da;
-	alignement = PAGE_SIZE;
+	alignment = PAGE_SIZE;
 
-	if (flags & IOVMF_DA_ANON) {
-		start = obj->da_start;
+	if (~flags & IOVMF_DA_FIXED) {
+		/* Don't map address 0 */
+		start = obj->da_start ? obj->da_start : alignment;
 
 		if (flags & IOVMF_LINEAR)
-			alignement = iopgsz_max(bytes);
-		start = roundup(start, alignement);
+			alignment = iopgsz_max(bytes);
+		start = roundup(start, alignment);
 	} else if (start < obj->da_start || start > obj->da_end ||
 					obj->da_end - start < bytes) {
 		return ERR_PTR(-EINVAL);
@@ -303,8 +304,8 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
 		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
 			goto found;
 
-		if (tmp->da_end >= start && flags & IOVMF_DA_ANON)
-			start = roundup(tmp->da_end + 1, alignement);
+		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
+			start = roundup(tmp->da_end + 1, alignment);
 
 		prev_end = tmp->da_end;
 	}
@@ -650,7 +651,6 @@ u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt,
 	flags &= IOVMF_HW_MASK;
 	flags |= IOVMF_DISCONT;
 	flags |= IOVMF_MMIO;
-	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
 
 	da = __iommu_vmap(obj, da, sgt, va, bytes, flags);
 	if (IS_ERR_VALUE(da))
@@ -690,7 +690,7 @@ EXPORT_SYMBOL_GPL(iommu_vunmap);
  * @flags:	iovma and page property
  *
  * Allocate @bytes linearly and creates 1-n-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
+ * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
  */
 u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
 {
@@ -709,7 +709,6 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
 	flags &= IOVMF_HW_MASK;
 	flags |= IOVMF_DISCONT;
 	flags |= IOVMF_ALLOC;
-	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
 
 	sgt = sgtable_alloc(bytes, flags, da, 0);
 	if (IS_ERR(sgt)) {
@@ -780,7 +779,7 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va,
  * @flags:	iovma and page property
  *
  * Creates 1-1-1 mapping and returns @da again, which can be
- * adjusted if 'IOVMF_DA_ANON' is set.
+ * adjusted if 'IOVMF_DA_FIXED' is not set.
  */
 u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
 		 u32 flags)
@@ -799,7 +798,6 @@ u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
 	flags &= IOVMF_HW_MASK;
 	flags |= IOVMF_LINEAR;
 	flags |= IOVMF_MMIO;
-	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
 
 	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
 	if (IS_ERR_VALUE(da))
@@ -838,7 +836,7 @@ EXPORT_SYMBOL_GPL(iommu_kunmap);
  * @flags:	iovma and page property
  *
  * Allocate @bytes linearly and creates 1-1-1 mapping and returns
- * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set.
+ * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
  */
 u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
 {
@@ -858,7 +856,6 @@ u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
 	flags &= IOVMF_HW_MASK;
 	flags |= IOVMF_LINEAR;
 	flags |= IOVMF_ALLOC;
-	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
 
 	da = __iommu_kmap(obj, da, pa, va, bytes, flags);
 	if (IS_ERR_VALUE(da))
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 49d3208..69ddc9f 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -32,7 +32,6 @@
 
 #include <plat/mailbox.h>
 
-static struct workqueue_struct *mboxd;
 static struct omap_mbox **mboxes;
 
 static int mbox_configured;
@@ -197,7 +196,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
 	/* no more messages in the fifo. clear IRQ source. */
 	ack_mbox_irq(mbox, IRQ_RX);
 nomem:
-	queue_work(mboxd, &mbox->rxq->work);
+	schedule_work(&mbox->rxq->work);
 }
 
 static irqreturn_t mbox_interrupt(int irq, void *p)
@@ -307,7 +306,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
 	if (!--mbox->use_count) {
 		free_irq(mbox->irq, mbox);
 		tasklet_kill(&mbox->txq->tasklet);
-		flush_work(&mbox->rxq->work);
+	flush_work_sync(&mbox->rxq->work);
 		mbox_queue_free(mbox->txq);
 		mbox_queue_free(mbox->rxq);
 	}
@@ -409,10 +408,6 @@ static int __init omap_mbox_init(void)
 	if (err)
 		return err;
 
-	mboxd = create_workqueue("mboxd");
-	if (!mboxd)
-		return -ENOMEM;
-
 	/* 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,
@@ -424,7 +419,6 @@ subsys_initcall(omap_mbox_init);
 
 static void __exit omap_mbox_exit(void)
 {
-	destroy_workqueue(mboxd);
 	class_unregister(&omap_mbox_class);
 }
 module_exit(omap_mbox_exit);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index b5a6e17..d598d9f 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -27,6 +27,8 @@
 
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
+#include <plat/omap_device.h>
+#include <linux/pm_runtime.h>
 
 /* XXX These "sideways" includes are a sign that something is wrong */
 #include "../mach-omap2/cm2xxx_3xxx.h"
@@ -227,10 +229,83 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config)
 }
 EXPORT_SYMBOL(omap_mcbsp_config);
 
+/**
+ * omap_mcbsp_dma_params - returns the dma channel number
+ * @id - mcbsp id
+ * @stream - indicates the direction of data flow (rx or tx)
+ *
+ * Returns the dma channel number for the rx channel or tx channel
+ * based on the value of @stream for the requested mcbsp given by @id
+ */
+int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream)
+{
+	struct omap_mcbsp *mcbsp;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+		return -ENODEV;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	if (stream)
+		return mcbsp->dma_rx_sync;
+	else
+		return mcbsp->dma_tx_sync;
+}
+EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
+
+/**
+ * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
+ * @id - mcbsp id
+ * @stream - indicates the direction of data flow (rx or tx)
+ *
+ * Returns the address of mcbsp data transmit register or data receive register
+ * to be used by DMA for transferring/receiving data based on the value of
+ * @stream for the requested mcbsp given by @id
+ */
+int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
+{
+	struct omap_mcbsp *mcbsp;
+	int data_reg;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+		return -ENODEV;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	data_reg = mcbsp->phys_dma_base;
+
+	if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) {
+		if (stream)
+			data_reg += OMAP_MCBSP_REG_DRR1;
+		else
+			data_reg += OMAP_MCBSP_REG_DXR1;
+	} else {
+		if (stream)
+			data_reg += OMAP_MCBSP_REG_DRR;
+		else
+			data_reg += OMAP_MCBSP_REG_DXR;
+	}
+
+	return data_reg;
+}
+EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
+
 #ifdef CONFIG_ARCH_OMAP3
+static struct omap_device *find_omap_device_by_dev(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev,
+					struct platform_device, dev);
+	return container_of(pdev, struct omap_device, pdev);
+}
+
 static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	/*
 	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
@@ -244,9 +319,6 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
 
-	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE));
-
 	/* Enable Sidetone from Sidetone Core */
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 	MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
@@ -255,13 +327,13 @@ static void omap_st_on(struct omap_mcbsp *mcbsp)
 static void omap_st_off(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 	MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
 
-	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE);
-
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
@@ -273,9 +345,9 @@ static void omap_st_off(struct omap_mcbsp *mcbsp)
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
 {
 	u16 val, i;
+	struct omap_device *od;
 
-	val = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, val & ~(ST_AUTOIDLE));
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	val = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -303,9 +375,9 @@ static void omap_st_chgain(struct omap_mcbsp *mcbsp)
 {
 	u16 w;
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	struct omap_device *od;
 
-	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE));
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -648,48 +720,33 @@ EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode);
 
 static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
 {
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
 	/*
 	 * Enable wakup behavior, smart idle and all wakeups
 	 * REVISIT: some wakeups may be unnecessary
 	 */
 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		u16 syscon;
-
-		syscon = MCBSP_READ(mcbsp, SYSCON);
-		syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
-
-		if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
-			syscon |= (ENAWAKEUP | SIDLEMODE(0x02) |
-					CLOCKACTIVITY(0x02));
-			MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
-		} else {
-			syscon |= SIDLEMODE(0x01);
-		}
-
-		MCBSP_WRITE(mcbsp, SYSCON, syscon);
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
 	}
 }
 
 static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
 {
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
+
 	/*
 	 * Disable wakup behavior, smart idle and all wakeups
 	 */
 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		u16 syscon;
-
-		syscon = MCBSP_READ(mcbsp, SYSCON);
-		syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
 		/*
 		 * HW bug workaround - If no_idle mode is taken, we need to
 		 * go to smart_idle before going to always_idle, or the
 		 * device will not hit retention anymore.
 		 */
-		syscon |= SIDLEMODE(0x02);
-		MCBSP_WRITE(mcbsp, SYSCON, syscon);
-
-		syscon &= ~(SIDLEMODE(0x03));
-		MCBSP_WRITE(mcbsp, SYSCON, syscon);
 
 		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 	}
@@ -764,8 +821,7 @@ int omap_mcbsp_request(unsigned int id)
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
 		mcbsp->pdata->ops->request(id);
 
-	clk_enable(mcbsp->iclk);
-	clk_enable(mcbsp->fclk);
+	pm_runtime_get_sync(mcbsp->dev);
 
 	/* Do procedure specific to omap34xx arch, if applicable */
 	omap34xx_mcbsp_request(mcbsp);
@@ -813,8 +869,7 @@ err_clk_disable:
 	/* Do procedure specific to omap34xx arch, if applicable */
 	omap34xx_mcbsp_free(mcbsp);
 
-	clk_disable(mcbsp->fclk);
-	clk_disable(mcbsp->iclk);
+	pm_runtime_put_sync(mcbsp->dev);
 
 	spin_lock(&mcbsp->lock);
 	mcbsp->free = true;
@@ -844,8 +899,7 @@ void omap_mcbsp_free(unsigned int id)
 	/* Do procedure specific to omap34xx arch, if applicable */
 	omap34xx_mcbsp_free(mcbsp);
 
-	clk_disable(mcbsp->fclk);
-	clk_disable(mcbsp->iclk);
+	pm_runtime_put_sync(mcbsp->dev);
 
 	if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
 		/* Free IRQs */
@@ -1649,7 +1703,8 @@ static const struct attribute_group sidetone_attr_group = {
 
 static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp_platform_data *pdata = mcbsp->pdata;
+	struct platform_device *pdev;
+	struct resource *res;
 	struct omap_mcbsp_st_data *st_data;
 	int err;
 
@@ -1659,7 +1714,10 @@ static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 		goto err1;
 	}
 
-	st_data->io_base_st = ioremap(pdata->phys_base_st, SZ_4K);
+	pdev = container_of(mcbsp->dev, struct platform_device, dev);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+	st_data->io_base_st = ioremap(res->start, resource_size(res));
 	if (!st_data->io_base_st) {
 		err = -ENOMEM;
 		goto err2;
@@ -1748,6 +1806,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 	struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
 	struct omap_mcbsp *mcbsp;
 	int id = pdev->id - 1;
+	struct resource *res;
 	int ret = 0;
 
 	if (!pdata) {
@@ -1777,47 +1836,78 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
 	mcbsp->dma_tx_lch = -1;
 	mcbsp->dma_rx_lch = -1;
 
-	mcbsp->phys_base = pdata->phys_base;
-	mcbsp->io_base = ioremap(pdata->phys_base, SZ_4K);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+	if (!res) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			dev_err(&pdev->dev, "%s:mcbsp%d has invalid memory"
+					"resource\n", __func__, pdev->id);
+			ret = -ENOMEM;
+			goto exit;
+		}
+	}
+	mcbsp->phys_base = res->start;
+	omap_mcbsp_cache_size = resource_size(res);
+	mcbsp->io_base = ioremap(res->start, resource_size(res));
 	if (!mcbsp->io_base) {
 		ret = -ENOMEM;
 		goto err_ioremap;
 	}
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+	if (!res)
+		mcbsp->phys_dma_base = mcbsp->phys_base;
+	else
+		mcbsp->phys_dma_base = res->start;
+
 	/* Default I/O is IRQ based */
 	mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
-	mcbsp->tx_irq = pdata->tx_irq;
-	mcbsp->rx_irq = pdata->rx_irq;
-	mcbsp->dma_rx_sync = pdata->dma_rx_sync;
-	mcbsp->dma_tx_sync = pdata->dma_tx_sync;
 
-	mcbsp->iclk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(mcbsp->iclk)) {
-		ret = PTR_ERR(mcbsp->iclk);
-		dev_err(&pdev->dev, "unable to get ick: %d\n", ret);
-		goto err_iclk;
+	mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
+	mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
+
+	/* From OMAP4 there will be a single irq line */
+	if (mcbsp->tx_irq == -ENXIO)
+		mcbsp->tx_irq = platform_get_irq(pdev, 0);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+	if (!res) {
+		dev_err(&pdev->dev, "%s:mcbsp%d has invalid rx DMA channel\n",
+					__func__, pdev->id);
+		ret = -ENODEV;
+		goto err_res;
+	}
+	mcbsp->dma_rx_sync = res->start;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+	if (!res) {
+		dev_err(&pdev->dev, "%s:mcbsp%d has invalid tx DMA channel\n",
+					__func__, pdev->id);
+		ret = -ENODEV;
+		goto err_res;
 	}
+	mcbsp->dma_tx_sync = res->start;
 
 	mcbsp->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(mcbsp->fclk)) {
 		ret = PTR_ERR(mcbsp->fclk);
 		dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
-		goto err_fclk;
+		goto err_res;
 	}
 
 	mcbsp->pdata = pdata;
 	mcbsp->dev = &pdev->dev;
 	mcbsp_ptr[id] = mcbsp;
+	mcbsp->mcbsp_config_type = pdata->mcbsp_config_type;
 	platform_set_drvdata(pdev, mcbsp);
+	pm_runtime_enable(mcbsp->dev);
 
 	/* Initialize mcbsp properties for OMAP34XX if needed / applicable */
 	omap34xx_device_init(mcbsp);
 
 	return 0;
 
-err_fclk:
-	clk_put(mcbsp->iclk);
-err_iclk:
+err_res:
 	iounmap(mcbsp->io_base);
 err_ioremap:
 	kfree(mcbsp);
@@ -1839,7 +1929,6 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev)
 		omap34xx_device_exit(mcbsp);
 
 		clk_put(mcbsp->fclk);
-		clk_put(mcbsp->iclk);
 
 		iounmap(mcbsp->io_base);
 		kfree(mcbsp);
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 57adb27..9bbda9a 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -83,9 +83,11 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
+#include <plat/clock.h>
 
 /* These parameters are passed to _omap_device_{de,}activate() */
 #define USE_WAKEUP_LAT			0
@@ -239,12 +241,12 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
 }
 
 /**
- * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
  * @od: struct omap_device *od
  *
  * For every optional clock present per hwmod per omap_device, this function
- * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
- * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
+ * if it does not exist already.
  *
  * The function is called from inside omap_device_build_ss(), after
  * omap_device_register.
@@ -254,25 +256,39 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
  *
  * No return value.
  */
-static void _add_optional_clock_alias(struct omap_device *od,
+static void _add_optional_clock_clkdev(struct omap_device *od,
 				      struct omap_hwmod *oh)
 {
 	int i;
 
 	for (i = 0; i < oh->opt_clks_cnt; i++) {
 		struct omap_hwmod_opt_clk *oc;
-		int r;
+		struct clk *r;
+		struct clk_lookup *l;
 
 		oc = &oh->opt_clks[i];
 
 		if (!oc->_clk)
 			continue;
 
-		r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
-				  (char *)oc->clk, &od->pdev.dev);
-		if (r)
-			pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+		r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
+		if (!IS_ERR(r))
+			continue; /* clkdev entry exists */
+
+		r = omap_clk_get_by_name((char *)oc->clk);
+		if (IS_ERR(r)) {
+			pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
+			       dev_name(&od->pdev.dev), oc->clk);
+			continue;
+		}
+
+		l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
+		if (!l) {
+			pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
 			       dev_name(&od->pdev.dev), oc->role);
+			return;
+		}
+		clkdev_add(l);
 	}
 }
 
@@ -480,7 +496,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 
 	for (i = 0; i < oh_cnt; i++) {
 		hwmods[i]->od = od;
-		_add_optional_clock_alias(od, hwmods[i]);
+		_add_optional_clock_clkdev(od, hwmods[i]);
 	}
 
 	if (ret)
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index e26e504..a3f50b3 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -242,7 +242,14 @@ static void __init omap_map_sram(void)
 	       omap_sram_size - SRAM_BOOTLOADER_SZ);
 }
 
-void * omap_sram_push(void * start, unsigned long size)
+/*
+ * Memory allocator for SRAM: calculates the new ceiling address
+ * for pushing a function using the fncpy API.
+ *
+ * Note that fncpy requires the returned address to be aligned
+ * to an 8-byte boundary.
+ */
+void *omap_sram_push_address(unsigned long size)
 {
 	if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
 		printk(KERN_ERR "Not enough space in SRAM\n");
@@ -250,10 +257,7 @@ void * omap_sram_push(void * start, unsigned long size)
 	}
 
 	omap_sram_ceil -= size;
-	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
-	memcpy((void *)omap_sram_ceil, start, size);
-	flush_icache_range((unsigned long)omap_sram_ceil,
-		(unsigned long)(omap_sram_ceil + size));
+	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
 
 	return (void *)omap_sram_ceil;
 }
@@ -312,7 +316,7 @@ u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 static int __init omap242x_sram_init(void)
 {
 	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
@@ -333,7 +337,7 @@ static inline int omap242x_sram_init(void)
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 static int __init omap243x_sram_init(void)
 {
 	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
@@ -405,20 +409,6 @@ static inline int omap34xx_sram_init(void)
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP4
-static int __init omap44xx_sram_init(void)
-{
-	printk(KERN_ERR "FIXME: %s not implemented\n", __func__);
-
-	return -ENODEV;
-}
-#else
-static inline int omap44xx_sram_init(void)
-{
-	return 0;
-}
-#endif
-
 int __init omap_sram_init(void)
 {
 	omap_detect_sram();
@@ -432,8 +422,6 @@ int __init omap_sram_init(void)
 		omap243x_sram_init();
 	else if (cpu_is_omap34xx())
 		omap34xx_sram_init();
-	else if (cpu_is_omap44xx())
-		omap44xx_sram_init();
 
 	return 0;
 }
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index 5f35223..078894b 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -17,55 +17,123 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-static DEFINE_SPINLOCK(gpio_lock);
-static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
-static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
+/*
+ * GPIO unit register offsets.
+ */
+#define GPIO_OUT_OFF		0x0000
+#define GPIO_IO_CONF_OFF	0x0004
+#define GPIO_BLINK_EN_OFF	0x0008
+#define GPIO_IN_POL_OFF		0x000c
+#define GPIO_DATA_IN_OFF	0x0010
+#define GPIO_EDGE_CAUSE_OFF	0x0014
+#define GPIO_EDGE_MASK_OFF	0x0018
+#define GPIO_LEVEL_MASK_OFF	0x001c
+
+struct orion_gpio_chip {
+	struct gpio_chip	chip;
+	spinlock_t		lock;
+	void __iomem		*base;
+	unsigned long		valid_input;
+	unsigned long		valid_output;
+	int			mask_offset;
+	int			secondary_irq_base;
+};
+
+static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_OUT_OFF;
+}
+
+static void __iomem *GPIO_IO_CONF(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_IO_CONF_OFF;
+}
+
+static void __iomem *GPIO_BLINK_EN(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_BLINK_EN_OFF;
+}
+
+static void __iomem *GPIO_IN_POL(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_IN_POL_OFF;
+}
+
+static void __iomem *GPIO_DATA_IN(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_DATA_IN_OFF;
+}
+
+static void __iomem *GPIO_EDGE_CAUSE(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_EDGE_CAUSE_OFF;
+}
+
+static void __iomem *GPIO_EDGE_MASK(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + ochip->mask_offset + GPIO_EDGE_MASK_OFF;
+}
+
+static void __iomem *GPIO_LEVEL_MASK(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
+}
+
 
-static inline void __set_direction(unsigned pin, int input)
+static struct orion_gpio_chip orion_gpio_chips[2];
+static int orion_gpio_chip_count;
+
+static inline void
+__set_direction(struct orion_gpio_chip *ochip, unsigned pin, int input)
 {
 	u32 u;
 
-	u = readl(GPIO_IO_CONF(pin));
+	u = readl(GPIO_IO_CONF(ochip));
 	if (input)
-		u |= 1 << (pin & 31);
+		u |= 1 << pin;
 	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_IO_CONF(pin));
+		u &= ~(1 << pin);
+	writel(u, GPIO_IO_CONF(ochip));
 }
 
-static void __set_level(unsigned pin, int high)
+static void __set_level(struct orion_gpio_chip *ochip, unsigned pin, int high)
 {
 	u32 u;
 
-	u = readl(GPIO_OUT(pin));
+	u = readl(GPIO_OUT(ochip));
 	if (high)
-		u |= 1 << (pin & 31);
+		u |= 1 << pin;
 	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_OUT(pin));
+		u &= ~(1 << pin);
+	writel(u, GPIO_OUT(ochip));
 }
 
-static inline void __set_blinking(unsigned pin, int blink)
+static inline void
+__set_blinking(struct orion_gpio_chip *ochip, unsigned pin, int blink)
 {
 	u32 u;
 
-	u = readl(GPIO_BLINK_EN(pin));
+	u = readl(GPIO_BLINK_EN(ochip));
 	if (blink)
-		u |= 1 << (pin & 31);
+		u |= 1 << pin;
 	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_BLINK_EN(pin));
+		u &= ~(1 << pin);
+	writel(u, GPIO_BLINK_EN(ochip));
 }
 
-static inline int orion_gpio_is_valid(unsigned pin, int mode)
+static inline int
+orion_gpio_is_valid(struct orion_gpio_chip *ochip, unsigned pin, int mode)
 {
-	if (pin < GPIO_MAX) {
-		if ((mode & GPIO_INPUT_OK) && !test_bit(pin, gpio_valid_input))
-			goto err_out;
-		if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, gpio_valid_output))
-			goto err_out;
-		return true;
-	}
+	if (pin >= ochip->chip.ngpio)
+		goto err_out;
+
+	if ((mode & GPIO_INPUT_OK) && !test_bit(pin, &ochip->valid_input))
+		goto err_out;
+
+	if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, &ochip->valid_output))
+		goto err_out;
+
+	return 1;
 
 err_out:
 	pr_debug("%s: invalid GPIO %d\n", __func__, pin);
@@ -75,134 +143,155 @@ err_out:
 /*
  * GENERIC_GPIO primitives.
  */
+static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
+
+	if (orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK) ||
+	    orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK))
+		return 0;
+
+	return -EINVAL;
+}
+
 static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	unsigned long flags;
 
-	if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK))
+	if (!orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK))
 		return -EINVAL;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Configure GPIO direction. */
-	__set_direction(pin, 1);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_direction(ochip, pin, 1);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 
 	return 0;
 }
 
-static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin)
+static int orion_gpio_get(struct gpio_chip *chip, unsigned pin)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	int val;
 
-	if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
-		val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
-	else
-		val = readl(GPIO_OUT(pin));
+	if (readl(GPIO_IO_CONF(ochip)) & (1 << pin)) {
+		val = readl(GPIO_DATA_IN(ochip)) ^ readl(GPIO_IN_POL(ochip));
+	} else {
+		val = readl(GPIO_OUT(ochip));
+	}
 
-	return (val >> (pin & 31)) & 1;
+	return (val >> pin) & 1;
 }
 
-static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
-	int value)
+static int
+orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	unsigned long flags;
 
-	if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+	if (!orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK))
 		return -EINVAL;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Disable blinking. */
-	__set_blinking(pin, 0);
-
-	/* Configure GPIO output value. */
-	__set_level(pin, value);
-
-	/* Configure GPIO direction. */
-	__set_direction(pin, 0);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_blinking(ochip, pin, 0);
+	__set_level(ochip, pin, value);
+	__set_direction(ochip, pin, 0);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 
 	return 0;
 }
 
-static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin,
-	int value)
+static void orion_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	unsigned long flags;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Configure GPIO output value. */
-	__set_level(pin, value);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_level(ochip, pin, value);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 }
 
-static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
+static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
 {
-	if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) ||
-	    orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
-		return 0;
-	return -EINVAL;
-}
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 
-static struct gpio_chip orion_gpiochip = {
-	.label			= "orion_gpio",
-	.direction_input	= orion_gpio_direction_input,
-	.get			= orion_gpio_get_value,
-	.direction_output	= orion_gpio_direction_output,
-	.set			= orion_gpio_set_value,
-	.request		= orion_gpio_request,
-	.base			= 0,
-	.ngpio			= GPIO_MAX,
-	.can_sleep		= 0,
-};
-
-void __init orion_gpio_init(void)
-{
-	gpiochip_add(&orion_gpiochip);
+	return ochip->secondary_irq_base + pin;
 }
 
+
 /*
  * Orion-specific GPIO API extensions.
  */
+static struct orion_gpio_chip *orion_gpio_chip_find(int pin)
+{
+	int i;
+
+	for (i = 0; i < orion_gpio_chip_count; i++) {
+		struct orion_gpio_chip *ochip = orion_gpio_chips + i;
+		struct gpio_chip *chip = &ochip->chip;
+
+		if (pin >= chip->base && pin < chip->base + chip->ngpio)
+			return ochip;
+	}
+
+	return NULL;
+}
+
 void __init orion_gpio_set_unused(unsigned pin)
 {
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+
+	if (ochip == NULL)
+		return;
+
+	pin -= ochip->chip.base;
+
 	/* Configure as output, drive low. */
-	__set_level(pin, 0);
-	__set_direction(pin, 0);
+	__set_level(ochip, pin, 0);
+	__set_direction(ochip, pin, 0);
 }
 
 void __init orion_gpio_set_valid(unsigned pin, int mode)
 {
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+
+	if (ochip == NULL)
+		return;
+
+	pin -= ochip->chip.base;
+
 	if (mode == 1)
 		mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
+
 	if (mode & GPIO_INPUT_OK)
-		__set_bit(pin, gpio_valid_input);
+		__set_bit(pin, &ochip->valid_input);
 	else
-		__clear_bit(pin, gpio_valid_input);
+		__clear_bit(pin, &ochip->valid_input);
+
 	if (mode & GPIO_OUTPUT_OK)
-		__set_bit(pin, gpio_valid_output);
+		__set_bit(pin, &ochip->valid_output);
 	else
-		__clear_bit(pin, gpio_valid_output);
+		__clear_bit(pin, &ochip->valid_output);
 }
 
 void orion_gpio_set_blink(unsigned pin, int blink)
 {
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
 	unsigned long flags;
 
-	spin_lock_irqsave(&gpio_lock, flags);
+	if (ochip == NULL)
+		return;
 
-	/* Set output value to zero. */
-	__set_level(pin, 0);
-
-	/* Set blinking. */
-	__set_blinking(pin, blink);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_level(ochip, pin, 0);
+	__set_blinking(ochip, pin, blink);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 }
 EXPORT_SYMBOL(orion_gpio_set_blink);
 
@@ -234,59 +323,78 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
  ****************************************************************************/
 static void gpio_irq_ack(struct irq_data *d)
 {
-	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int type;
+
+	type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-		int pin = irq_to_gpio(d->irq);
-		writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
+		int pin = d->irq - ochip->secondary_irq_base;
+
+		writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip));
 	}
 }
 
 static void gpio_irq_mask(struct irq_data *d)
 {
-	int pin = irq_to_gpio(d->irq);
-	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
-	u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
-		GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
-	u32 u = readl(reg);
-	u &= ~(1 << (pin & 31));
-	writel(u, reg);
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int type;
+	void __iomem *reg;
+	int pin;
+
+	type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		reg = GPIO_EDGE_MASK(ochip);
+	else
+		reg = GPIO_LEVEL_MASK(ochip);
+
+	pin = d->irq - ochip->secondary_irq_base;
+
+	writel(readl(reg) & ~(1 << pin), reg);
 }
 
 static void gpio_irq_unmask(struct irq_data *d)
 {
-	int pin = irq_to_gpio(d->irq);
-	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
-	u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
-		GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
-	u32 u = readl(reg);
-	u |= 1 << (pin & 31);
-	writel(u, reg);
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int type;
+	void __iomem *reg;
+	int pin;
+
+	type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		reg = GPIO_EDGE_MASK(ochip);
+	else
+		reg = GPIO_LEVEL_MASK(ochip);
+
+	pin = d->irq - ochip->secondary_irq_base;
+
+	writel(readl(reg) | (1 << pin), reg);
 }
 
 static int gpio_irq_set_type(struct irq_data *d, u32 type)
 {
-	int pin = irq_to_gpio(d->irq);
-	struct irq_desc *desc;
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int pin;
 	u32 u;
 
-	u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31));
+	pin = d->irq - ochip->secondary_irq_base;
+
+	u = readl(GPIO_IO_CONF(ochip)) & (1 << pin);
 	if (!u) {
 		printk(KERN_ERR "orion gpio_irq_set_type failed "
 				"(irq %d, pin %d).\n", d->irq, pin);
 		return -EINVAL;
 	}
 
-	desc = irq_desc + d->irq;
-
 	/*
 	 * Set edge/level type.
 	 */
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-		desc->handle_irq = handle_edge_irq;
+		set_irq_handler(d->irq, handle_edge_irq);
 	} else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-		desc->handle_irq = handle_level_irq;
+		set_irq_handler(d->irq, handle_level_irq);
 	} else {
-		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", d->irq, type);
+		printk(KERN_ERR "failed to set irq=%d (type=%d)\n",
+		       d->irq, type);
 		return -EINVAL;
 	}
 
@@ -294,31 +402,29 @@ static int gpio_irq_set_type(struct irq_data *d, u32 type)
 	 * Configure interrupt polarity.
 	 */
 	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) {
-		u = readl(GPIO_IN_POL(pin));
-		u &= ~(1 << (pin & 31));
-		writel(u, GPIO_IN_POL(pin));
+		u = readl(GPIO_IN_POL(ochip));
+		u &= ~(1 << pin);
+		writel(u, GPIO_IN_POL(ochip));
 	} else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) {
-		u = readl(GPIO_IN_POL(pin));
-		u |= 1 << (pin & 31);
-		writel(u, GPIO_IN_POL(pin));
+		u = readl(GPIO_IN_POL(ochip));
+		u |= 1 << pin;
+		writel(u, GPIO_IN_POL(ochip));
 	} else if (type == IRQ_TYPE_EDGE_BOTH) {
 		u32 v;
 
-		v = readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin));
+		v = readl(GPIO_IN_POL(ochip)) ^ readl(GPIO_DATA_IN(ochip));
 
 		/*
 		 * set initial polarity based on current input level
 		 */
-		u = readl(GPIO_IN_POL(pin));
-		if (v & (1 << (pin & 31)))
-			u |= 1 << (pin & 31);		/* falling */
+		u = readl(GPIO_IN_POL(ochip));
+		if (v & (1 << pin))
+			u |= 1 << pin;		/* falling */
 		else
-			u &= ~(1 << (pin & 31));	/* rising */
-		writel(u, GPIO_IN_POL(pin));
+			u &= ~(1 << pin);	/* rising */
+		writel(u, GPIO_IN_POL(ochip));
 	}
 
-	desc->status = (desc->status & ~IRQ_TYPE_SENSE_MASK) | type;
-
 	return 0;
 }
 
@@ -330,29 +436,87 @@ struct irq_chip orion_gpio_irq_chip = {
 	.irq_set_type	= gpio_irq_set_type,
 };
 
+void __init orion_gpio_init(int gpio_base, int ngpio,
+			    u32 base, int mask_offset, int secondary_irq_base)
+{
+	struct orion_gpio_chip *ochip;
+	int i;
+
+	if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
+		return;
+
+	ochip = orion_gpio_chips + orion_gpio_chip_count;
+	ochip->chip.label = "orion_gpio";
+	ochip->chip.request = orion_gpio_request;
+	ochip->chip.direction_input = orion_gpio_direction_input;
+	ochip->chip.get = orion_gpio_get;
+	ochip->chip.direction_output = orion_gpio_direction_output;
+	ochip->chip.set = orion_gpio_set;
+	ochip->chip.to_irq = orion_gpio_to_irq;
+	ochip->chip.base = gpio_base;
+	ochip->chip.ngpio = ngpio;
+	ochip->chip.can_sleep = 0;
+	spin_lock_init(&ochip->lock);
+	ochip->base = (void __iomem *)base;
+	ochip->valid_input = 0;
+	ochip->valid_output = 0;
+	ochip->mask_offset = mask_offset;
+	ochip->secondary_irq_base = secondary_irq_base;
+
+	gpiochip_add(&ochip->chip);
+
+	orion_gpio_chip_count++;
+
+	/*
+	 * Mask and clear GPIO interrupts.
+	 */
+	writel(0, GPIO_EDGE_CAUSE(ochip));
+	writel(0, GPIO_EDGE_MASK(ochip));
+	writel(0, GPIO_LEVEL_MASK(ochip));
+
+	for (i = 0; i < ngpio; i++) {
+		unsigned int irq = secondary_irq_base + i;
+
+		set_irq_chip(irq, &orion_gpio_irq_chip);
+		set_irq_handler(irq, handle_level_irq);
+		set_irq_chip_data(irq, ochip);
+		irq_desc[irq].status |= IRQ_LEVEL;
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
+
 void orion_gpio_irq_handler(int pinoff)
 {
+	struct orion_gpio_chip *ochip;
 	u32 cause;
-	int pin;
+	int i;
 
-	cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff));
-	cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff));
+	ochip = orion_gpio_chip_find(pinoff);
+	if (ochip == NULL)
+		return;
 
-	for (pin = pinoff; pin < pinoff + 8; pin++) {
-		int irq = gpio_to_irq(pin);
-		struct irq_desc *desc = irq_desc + irq;
+	cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip));
+	cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip));
 
-		if (!(cause & (1 << (pin & 31))))
+	for (i = 0; i < ochip->chip.ngpio; i++) {
+		int irq;
+		struct irq_desc *desc;
+
+		irq = ochip->secondary_irq_base + i;
+
+		if (!(cause & (1 << i)))
 			continue;
 
+		desc = irq_desc + irq;
 		if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
 			/* Swap polarity (race with GPIO line) */
 			u32 polarity;
 
-			polarity = readl(GPIO_IN_POL(pin));
-			polarity ^= 1 << (pin & 31);
-			writel(polarity, GPIO_IN_POL(pin));
+			polarity = readl(GPIO_IN_POL(ochip));
+			polarity ^= 1 << i;
+			writel(polarity, GPIO_IN_POL(ochip));
 		}
+
 		desc_handle_irq(irq, desc);
 	}
 }
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index 07c430f..5578b98 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -12,6 +12,7 @@
 #define __PLAT_GPIO_H
 
 #include <linux/init.h>
+#include <asm-generic/gpio.h>
 
 /*
  * GENERIC_GPIO primitives.
@@ -19,6 +20,7 @@
 #define gpio_get_value  __gpio_get_value
 #define gpio_set_value  __gpio_set_value
 #define gpio_cansleep   __gpio_cansleep
+#define gpio_to_irq     __gpio_to_irq
 
 /*
  * Orion-specific GPIO API extensions.
@@ -31,7 +33,8 @@ void orion_gpio_set_blink(unsigned pin, int blink);
 void orion_gpio_set_valid(unsigned pin, int mode);
 
 /* Initialize gpiolib. */
-void __init orion_gpio_init(void);
+void __init orion_gpio_init(int gpio_base, int ngpio,
+			    u32 base, int mask_offset, int secondary_irq_base);
 
 /*
  * GPIO interrupt handling.
diff --git a/arch/arm/plat-orion/include/plat/time.h b/arch/arm/plat-orion/include/plat/time.h
index c06ca35..4d5f1f6 100644
--- a/arch/arm/plat-orion/include/plat/time.h
+++ b/arch/arm/plat-orion/include/plat/time.h
@@ -11,7 +11,10 @@
 #ifndef __PLAT_TIME_H
 #define __PLAT_TIME_H
 
-void orion_time_init(unsigned int irq, unsigned int tclk);
+void orion_time_set_base(u32 timer_base);
+
+void orion_time_init(u32 bridge_base, u32 bridge_timer1_clr_mask,
+		     unsigned int irq, unsigned int tclk);
 
 
 #endif
diff --git a/arch/arm/plat-orion/time.c b/arch/arm/plat-orion/time.c
index c3da247..742b032 100644
--- a/arch/arm/plat-orion/time.c
+++ b/arch/arm/plat-orion/time.c
@@ -18,28 +18,42 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/sched_clock.h>
-#include <asm/mach/time.h>
-#include <mach/bridge-regs.h>
-#include <mach/hardware.h>
 
 /*
- * Number of timer ticks per jiffy.
+ * MBus bridge block registers.
  */
-static u32 ticks_per_jiffy;
+#define BRIDGE_CAUSE_OFF	0x0110
+#define BRIDGE_MASK_OFF		0x0114
+#define  BRIDGE_INT_TIMER0	 0x0002
+#define  BRIDGE_INT_TIMER1	 0x0004
 
 
 /*
  * Timer block registers.
  */
-#define TIMER_CTRL		(TIMER_VIRT_BASE + 0x0000)
-#define  TIMER0_EN		0x0001
-#define  TIMER0_RELOAD_EN	0x0002
-#define  TIMER1_EN		0x0004
-#define  TIMER1_RELOAD_EN	0x0008
-#define TIMER0_RELOAD		(TIMER_VIRT_BASE + 0x0010)
-#define TIMER0_VAL		(TIMER_VIRT_BASE + 0x0014)
-#define TIMER1_RELOAD		(TIMER_VIRT_BASE + 0x0018)
-#define TIMER1_VAL		(TIMER_VIRT_BASE + 0x001c)
+#define TIMER_CTRL_OFF		0x0000
+#define  TIMER0_EN		 0x0001
+#define  TIMER0_RELOAD_EN	 0x0002
+#define  TIMER1_EN		 0x0004
+#define  TIMER1_RELOAD_EN	 0x0008
+#define TIMER0_RELOAD_OFF	0x0010
+#define TIMER0_VAL_OFF		0x0014
+#define TIMER1_RELOAD_OFF	0x0018
+#define TIMER1_VAL_OFF		0x001c
+
+
+/*
+ * SoC-specific data.
+ */
+static void __iomem *bridge_base;
+static u32 bridge_timer1_clr_mask;
+static void __iomem *timer_base;
+
+
+/*
+ * Number of timer ticks per jiffy.
+ */
+static u32 ticks_per_jiffy;
 
 
 /*
@@ -50,14 +64,14 @@ static DEFINE_CLOCK_DATA(cd);
 
 unsigned long long notrace sched_clock(void)
 {
-	u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+	u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF);
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
 
 static void notrace orion_update_sched_clock(void)
 {
-	u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+	u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF);
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
@@ -71,7 +85,7 @@ static void __init setup_sched_clock(unsigned long tclk)
  */
 static cycle_t orion_clksrc_read(struct clocksource *cs)
 {
-	return 0xffffffff - readl(TIMER0_VAL);
+	return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
 }
 
 static struct clocksource orion_clksrc = {
@@ -101,23 +115,23 @@ orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
 	/*
 	 * Clear and enable clockevent timer interrupt.
 	 */
-	writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 
-	u = readl(BRIDGE_MASK);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
 	u |= BRIDGE_INT_TIMER1;
-	writel(u, BRIDGE_MASK);
+	writel(u, bridge_base + BRIDGE_MASK_OFF);
 
 	/*
 	 * Setup new clockevent timer value.
 	 */
-	writel(delta, TIMER1_VAL);
+	writel(delta, timer_base + TIMER1_VAL_OFF);
 
 	/*
 	 * Enable the timer.
 	 */
-	u = readl(TIMER_CTRL);
+	u = readl(timer_base + TIMER_CTRL_OFF);
 	u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
-	writel(u, TIMER_CTRL);
+	writel(u, timer_base + TIMER_CTRL_OFF);
 
 	local_irq_restore(flags);
 
@@ -135,37 +149,38 @@ orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
 		/*
 		 * Setup timer to fire at 1/HZ intervals.
 		 */
-		writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
-		writel(ticks_per_jiffy - 1, TIMER1_VAL);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
 
 		/*
 		 * Enable timer interrupt.
 		 */
-		u = readl(BRIDGE_MASK);
-		writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
+		u = readl(bridge_base + BRIDGE_MASK_OFF);
+		writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
 
 		/*
 		 * Enable timer.
 		 */
-		u = readl(TIMER_CTRL);
-		writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
+		u = readl(timer_base + TIMER_CTRL_OFF);
+		writel(u | TIMER1_EN | TIMER1_RELOAD_EN,
+		       timer_base + TIMER_CTRL_OFF);
 	} else {
 		/*
 		 * Disable timer.
 		 */
-		u = readl(TIMER_CTRL);
-		writel(u & ~TIMER1_EN, TIMER_CTRL);
+		u = readl(timer_base + TIMER_CTRL_OFF);
+		writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
 
 		/*
 		 * Disable timer interrupt.
 		 */
-		u = readl(BRIDGE_MASK);
-		writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
+		u = readl(bridge_base + BRIDGE_MASK_OFF);
+		writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
 
 		/*
 		 * ACK pending timer interrupt.
 		 */
-		writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+		writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 
 	}
 	local_irq_restore(flags);
@@ -185,7 +200,7 @@ static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
 	/*
 	 * ACK timer interrupt and call event handler.
 	 */
-	writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 	orion_clkevt.event_handler(&orion_clkevt);
 
 	return IRQ_HANDLED;
@@ -197,31 +212,45 @@ static struct irqaction orion_timer_irq = {
 	.handler	= orion_timer_interrupt
 };
 
-void __init orion_time_init(unsigned int irq, unsigned int tclk)
+void __init
+orion_time_set_base(u32 _timer_base)
+{
+	timer_base = (void __iomem *)_timer_base;
+}
+
+void __init
+orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
+		unsigned int irq, unsigned int tclk)
 {
 	u32 u;
 
+	/*
+	 * Set SoC-specific data.
+	 */
+	bridge_base = (void __iomem *)_bridge_base;
+	bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
+
 	ticks_per_jiffy = (tclk + HZ/2) / HZ;
 
 	/*
-	 * Set scale and timer for sched_clock
+	 * Set scale and timer for sched_clock.
 	 */
 	setup_sched_clock(tclk);
 
 	/*
 	 * Setup free-running clocksource timer (interrupts
-	 * disabled.)
+	 * disabled).
 	 */
-	writel(0xffffffff, TIMER0_VAL);
-	writel(0xffffffff, TIMER0_RELOAD);
-	u = readl(BRIDGE_MASK);
-	writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
-	u = readl(TIMER_CTRL);
-	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
+	writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+	writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
 	clocksource_register_hz(&orion_clksrc, tclk);
 
 	/*
-	 * Setup clockevent timer (interrupt-driven.)
+	 * Setup clockevent timer (interrupt-driven).
 	 */
 	setup_irq(irq, &orion_timer_irq);
 	orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
diff --git a/arch/arm/plat-pxa/include/plat/i2c.h b/arch/arm/plat-pxa/include/plat/i2c.h
deleted file mode 100644
index 1a9f65e..0000000
--- a/arch/arm/plat-pxa/include/plat/i2c.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  i2c_pxa.h
- *
- *  Copyright (C) 2002 Intrinsyc Software Inc.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- *
- */
-#ifndef _I2C_PXA_H_
-#define _I2C_PXA_H_
-
-#if 0
-#define DEF_TIMEOUT             3
-#else
-/* need a longer timeout if we're dealing with the fact we may well be
- * looking at a multi-master environment
-*/
-#define DEF_TIMEOUT             32
-#endif
-
-#define BUS_ERROR               (-EREMOTEIO)
-#define XFER_NAKED              (-ECONNREFUSED)
-#define I2C_RETRY               (-2000) /* an error has occurred retry transmit */
-
-/* ICR initialize bit values
-*
-*  15. FM       0 (100 Khz operation)
-*  14. UR       0 (No unit reset)
-*  13. SADIE    0 (Disables the unit from interrupting on slave addresses
-*                                       matching its slave address)
-*  12. ALDIE    0 (Disables the unit from interrupt when it loses arbitration
-*                                       in master mode)
-*  11. SSDIE    0 (Disables interrupts from a slave stop detected, in slave mode)
-*  10. BEIE     1 (Enable interrupts from detected bus errors, no ACK sent)
-*  9.  IRFIE    1 (Enable interrupts from full buffer received)
-*  8.  ITEIE    1 (Enables the I2C unit to interrupt when transmit buffer empty)
-*  7.  GCD      1 (Disables i2c unit response to general call messages as a slave)
-*  6.  IUE      0 (Disable unit until we change settings)
-*  5.  SCLE     1 (Enables the i2c clock output for master mode (drives SCL)
-*  4.  MA       0 (Only send stop with the ICR stop bit)
-*  3.  TB       0 (We are not transmitting a byte initially)
-*  2.  ACKNAK   0 (Send an ACK after the unit receives a byte)
-*  1.  STOP     0 (Do not send a STOP)
-*  0.  START    0 (Do not send a START)
-*
-*/
-#define I2C_ICR_INIT	(ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
-
-/* I2C status register init values
- *
- * 10. BED      1 (Clear bus error detected)
- * 9.  SAD      1 (Clear slave address detected)
- * 7.  IRF      1 (Clear IDBR Receive Full)
- * 6.  ITE      1 (Clear IDBR Transmit Empty)
- * 5.  ALD      1 (Clear Arbitration Loss Detected)
- * 4.  SSD      1 (Clear Slave Stop Detected)
- */
-#define I2C_ISR_INIT	0x7FF  /* status register init */
-
-struct i2c_slave_client;
-
-struct i2c_pxa_platform_data {
-	unsigned int		slave_addr;
-	struct i2c_slave_client	*slave;
-	unsigned int		class;
-	unsigned int		use_pio :1;
-	unsigned int		fast_mode :1;
-};
-
-extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
-
-#ifdef CONFIG_PXA27x
-extern void pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info);
-#endif
-
-#ifdef CONFIG_PXA3xx
-extern void pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info);
-#endif
-
-#endif
diff --git a/arch/arm/plat-s3c24xx/Kconfig b/arch/arm/plat-s3c24xx/Kconfig
index eb105e6..d9c4096 100644
--- a/arch/arm/plat-s3c24xx/Kconfig
+++ b/arch/arm/plat-s3c24xx/Kconfig
@@ -56,13 +56,6 @@ config S3C24XX_DCLK
 	help
 	  Clock code for supporting DCLK/CLKOUT on S3C24XX architectures
 
-config S3C24XX_PWM
-	bool "PWM device support"
-	select HAVE_PWM
-	help
-	  Support for exporting the PWM timer blocks via the pwm device
-	  system.
-
 # gpio configurations
 
 config S3C24XX_GPIO_EXTRA
diff --git a/arch/arm/plat-s3c24xx/cpu-freq.c b/arch/arm/plat-s3c24xx/cpu-freq.c
index 25a8fc7..eea75ff 100644
--- a/arch/arm/plat-s3c24xx/cpu-freq.c
+++ b/arch/arm/plat-s3c24xx/cpu-freq.c
@@ -433,7 +433,7 @@ static int s3c_cpufreq_verify(struct cpufreq_policy *policy)
 static struct cpufreq_frequency_table suspend_pll;
 static unsigned int suspend_freq;
 
-static int s3c_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
+static int s3c_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	suspend_pll.frequency = clk_get_rate(_clk_mpll);
 	suspend_pll.index = __raw_readl(S3C2410_MPLLCON);
diff --git a/arch/arm/plat-s3c24xx/include/plat/udc.h b/arch/arm/plat-s3c24xx/include/plat/udc.h
index 546bb40..80457c6 100644
--- a/arch/arm/plat-s3c24xx/include/plat/udc.h
+++ b/arch/arm/plat-s3c24xx/include/plat/udc.h
@@ -27,6 +27,10 @@ enum s3c2410_udc_cmd_e {
 struct s3c2410_udc_mach_info {
 	void	(*udc_command)(enum s3c2410_udc_cmd_e);
  	void	(*vbus_draw)(unsigned int ma);
+
+	unsigned int pullup_pin;
+	unsigned int pullup_pin_inverted;
+
 	unsigned int vbus_pin;
 	unsigned char vbus_pin_inverted;
 };
diff --git a/arch/arm/plat-s3c24xx/sleep.S b/arch/arm/plat-s3c24xx/sleep.S
index e73e3b6..fd7032f 100644
--- a/arch/arm/plat-s3c24xx/sleep.S
+++ b/arch/arm/plat-s3c24xx/sleep.S
@@ -44,23 +44,13 @@
 	/* s3c_cpu_save
 	 *
 	 * entry:
-	 *	r0 = save address (virtual addr of s3c_sleep_save_phys)
+	 *	r1 = v:p offset
 	*/
 
 ENTRY(s3c_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
-
-	@@ store co-processor registers
-
-	mrc	p15, 0, r4, c13, c0, 0	@ PID
-	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ translation table base address
-	mrc	p15, 0, r7, c1, c0, 0	@ control register
-
-	stmia	r0, { r4 - r13 }
-
-	@@ write our state back to RAM
-	bl	s3c_pm_cb_flushcache
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
 
 	@@ jump to final code to send system to sleep
 	ldr	r0, =pm_cpu_sleep
@@ -76,20 +66,6 @@ resume_with_mmu:
 
 	.ltorg
 
-	@@ the next bits sit in the .data segment, even though they
-	@@ happen to be code... the s3c_sleep_save_phys needs to be
-	@@ accessed by the resume code before it can restore the MMU.
-	@@ This means that the variable has to be close enough for the
-	@@ code to read it... since the .text segment needs to be RO,
-	@@ the data segment can be the only place to put this code.
-
-	.data
-
-	.global	s3c_sleep_save_phys
-s3c_sleep_save_phys:
-	.word	0
-
-
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
@@ -100,10 +76,6 @@ s3c_sleep_save_phys:
 	/* s3c_cpu_resume
 	 *
 	 * resume code entry for bootloader to call
-	 *
-	 * we must put this code here in the data segment as we have no
-	 * other way of restoring the stack pointer after sleep, and we
-	 * must not write to the code segment (code is read-only)
 	*/
 
 ENTRY(s3c_cpu_resume)
@@ -134,25 +106,4 @@ ENTRY(s3c_cpu_resume)
 	beq	1001b
 #endif /* CONFIG_DEBUG_RESUME */
 
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
-
-	ldr	r0, s3c_sleep_save_phys		@ address of restore block
-	ldmia	r0, { r4 - r13 }
-
-	mcr	p15, 0, r4, c13, c0, 0		@ PID
-	mcr	p15, 0, r5, c3, c0, 0		@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0		@ translation table base
-
-#ifdef CONFIG_DEBUG_RESUME
-	mov	r3, #'R'
-	strb	r3, [ r2, #S3C2410_UTXH ]
-#endif
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r7, c1, c0, 0		@ turn on MMU, etc
-	nop					@ second-to-last before mmu
-	mov	pc, r2				@ go back to virtual address
-
-	.ltorg
+	b	cpu_resume
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 557f8c5..8492297 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -7,10 +7,10 @@
 
 config PLAT_S5P
 	bool
-	depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
+	depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4)
 	default y
-	select ARM_VIC if !ARCH_S5PV310
-	select ARM_GIC if ARCH_S5PV310
+	select ARM_VIC if !ARCH_EXYNOS4
+	select ARM_GIC if ARCH_EXYNOS4
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select S3C_GPIO_TRACK
@@ -37,11 +37,16 @@ config S5P_GPIO_INT
 	help
 	  Common code for the GPIO interrupts (other than external interrupts.)
 
+config S5P_HRT
+	bool
+	help
+	  Use the High Resolution timer support
+
 comment "System MMU"
 
 config S5P_SYSTEM_MMU
 	bool "S5P SYSTEM MMU"
-	depends on ARCH_S5PV310
+	depends on ARCH_EXYNOS4
 	help
 	  Say Y here if you want to enable System MMU
 
@@ -60,6 +65,11 @@ config S5P_DEV_FIMC2
 	help
 	  Compile in platform device definitions for FIMC controller 2
 
+config S5P_DEV_FIMC3
+	bool
+	help
+	  Compile in platform device definitions for FIMC controller 3
+
 config S5P_DEV_ONENAND
 	bool
 	help
@@ -74,3 +84,8 @@ config S5P_DEV_CSIS1
 	bool
 	help
 	  Compile in platform device definitions for MIPI-CSIS channel 1
+
+config S5P_SETUP_MIPIPHY
+	bool
+	help
+	  Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index 4bd5cf9..42afff7 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -22,12 +22,15 @@ obj-$(CONFIG_S5P_GPIO_INT)	+= irq-gpioint.o
 obj-$(CONFIG_S5P_SYSTEM_MMU)	+= sysmmu.o
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM)		+= irq-pm.o
+obj-$(CONFIG_S5P_HRT) 		+= s5p-time.o
 
 # devices
 
 obj-$(CONFIG_S5P_DEV_FIMC0)	+= dev-fimc0.o
 obj-$(CONFIG_S5P_DEV_FIMC1)	+= dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)	+= dev-fimc2.o
+obj-$(CONFIG_S5P_DEV_FIMC3)	+= dev-fimc3.o
 obj-$(CONFIG_S5P_DEV_ONENAND)	+= dev-onenand.o
 obj-$(CONFIG_S5P_DEV_CSIS0)	+= dev-csis0.o
 obj-$(CONFIG_S5P_DEV_CSIS1)	+= dev-csis1.o
+obj-$(CONFIG_S5P_SETUP_MIPIPHY)	+= setup-mipiphy.o
diff --git a/arch/arm/plat-s5p/cpu.c b/arch/arm/plat-s5p/cpu.c
index 047d31c..c3bfe9b 100644
--- a/arch/arm/plat-s5p/cpu.c
+++ b/arch/arm/plat-s5p/cpu.c
@@ -1,7 +1,7 @@
 /* linux/arch/arm/plat-s5p/cpu.c
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
  *
  * S5P CPU Support
  *
@@ -12,17 +12,20 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <mach/map.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+
+#include <mach/map.h>
 #include <mach/regs-clock.h>
+
 #include <plat/cpu.h>
 #include <plat/s5p6440.h>
 #include <plat/s5p6442.h>
 #include <plat/s5p6450.h>
 #include <plat/s5pc100.h>
 #include <plat/s5pv210.h>
-#include <plat/s5pv310.h>
+#include <plat/exynos4.h>
 
 /* table of supported CPUs */
 
@@ -31,7 +34,7 @@ static const char name_s5p6442[] = "S5P6442";
 static const char name_s5p6450[] = "S5P6450";
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
-static const char name_s5pv310[] = "S5PV310";
+static const char name_exynos4210[] = "EXYNOS4210";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
@@ -75,13 +78,13 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.init		= s5pv210_init,
 		.name		= name_s5pv210,
 	}, {
-		.idcode		= 0x43200000,
+		.idcode		= 0x43210000,
 		.idmask		= 0xfffff000,
-		.map_io		= s5pv310_map_io,
-		.init_clocks	= s5pv310_init_clocks,
-		.init_uarts	= s5pv310_init_uarts,
-		.init		= s5pv310_init,
-		.name		= name_s5pv310,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos4_init,
+		.name		= name_exynos4210,
 	},
 };
 
diff --git a/arch/arm/plat-s5p/dev-csis0.c b/arch/arm/plat-s5p/dev-csis0.c
index dfab1c8..e3aabef 100644
--- a/arch/arm/plat-s5p/dev-csis0.c
+++ b/arch/arm/plat-s5p/dev-csis0.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
  *
  * S5P series device definition for MIPI-CSIS channel 0
  *
diff --git a/arch/arm/plat-s5p/dev-csis1.c b/arch/arm/plat-s5p/dev-csis1.c
index e3053f2..08b91b5 100644
--- a/arch/arm/plat-s5p/dev-csis1.c
+++ b/arch/arm/plat-s5p/dev-csis1.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
  *
  * S5P series device definition for MIPI-CSIS channel 1
  *
diff --git a/arch/arm/plat-s5p/dev-fimc3.c b/arch/arm/plat-s5p/dev-fimc3.c
new file mode 100644
index 0000000..ef31bec
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimc3.c
@@ -0,0 +1,43 @@
+/* linux/arch/arm/plat-s5p/dev-fimc3.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Base S5P FIMC3 resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <mach/map.h>
+
+static struct resource s5p_fimc3_resource[] = {
+	[0] = {
+		.start	= S5P_PA_FIMC3,
+		.end	= S5P_PA_FIMC3 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_FIMC3,
+		.end	= IRQ_FIMC3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimc3 = {
+	.name		= "s5p-fimc",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s5p_fimc3_resource),
+	.resource	= s5p_fimc3_resource,
+	.dev		= {
+		.dma_mask		= &s5p_fimc3_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff --git a/arch/arm/plat-s5p/include/plat/camport.h b/arch/arm/plat-s5p/include/plat/camport.h
new file mode 100644
index 0000000..71688c8
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/camport.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series camera interface helper functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef PLAT_S5P_CAMPORT_H_
+#define PLAT_S5P_CAMPORT_H_ __FILE__
+
+enum s5p_camport_id {
+	S5P_CAMPORT_A,
+	S5P_CAMPORT_B,
+};
+
+/*
+ * The helper functions to configure GPIO for the camera parallel bus.
+ * The camera port can be multiplexed with any FIMC entity, even multiple
+ * FIMC entities are allowed to be attached to a single port simultaneously.
+ * These functions are to be used in the board setup code.
+ */
+int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
+
+#endif
diff --git a/arch/arm/plat-s5p/include/plat/csis.h b/arch/arm/plat-s5p/include/plat/csis.h
deleted file mode 100644
index 51e308c..0000000
--- a/arch/arm/plat-s5p/include/plat/csis.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics
- *
- * S5P series MIPI CSI slave device 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 PLAT_S5P_CSIS_H_
-#define PLAT_S5P_CSIS_H_ __FILE__
-
-/**
- * struct s5p_platform_mipi_csis - platform data for MIPI-CSIS
- * @clk_rate: bus clock frequency
- * @lanes: number of data lanes used
- * @alignment: data alignment in bits
- * @hs_settle: HS-RX settle time
- */
-struct s5p_platform_mipi_csis {
-	unsigned long clk_rate;
-	u8 lanes;
-	u8 alignment;
-	u8 hs_settle;
-};
-
-#endif /* PLAT_S5P_CSIS_H_ */
diff --git a/arch/arm/plat-s5p/include/plat/exynos4.h b/arch/arm/plat-s5p/include/plat/exynos4.h
new file mode 100644
index 0000000..907caab
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/exynos4.h
@@ -0,0 +1,34 @@
+/* linux/arch/arm/plat-s5p/include/plat/exynos4.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for exynos4 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.
+*/
+
+/* Common init code for EXYNOS4 related SoCs */
+
+extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void exynos4_register_clocks(void);
+extern void exynos4_setup_clocks(void);
+
+#ifdef CONFIG_CPU_EXYNOS4210
+
+extern  int exynos4_init(void);
+extern void exynos4_init_irq(void);
+extern void exynos4_map_io(void);
+extern void exynos4_init_clocks(int xtal);
+extern struct sys_timer exynos4_timer;
+
+#define exynos4_init_uarts exynos4_common_init_uarts
+
+#else
+#define exynos4_init_clocks NULL
+#define exynos4_init_uarts NULL
+#define exynos4_map_io NULL
+#define exynos4_init NULL
+#endif
diff --git a/arch/arm/plat-s5p/include/plat/mipi_csis.h b/arch/arm/plat-s5p/include/plat/mipi_csis.h
new file mode 100644
index 0000000..9bd254c
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/mipi_csis.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series MIPI CSI slave device 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 PLAT_S5P_MIPI_CSIS_H_
+#define PLAT_S5P_MIPI_CSIS_H_ __FILE__
+
+struct platform_device;
+
+/**
+ * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
+ * @clk_rate: bus clock frequency
+ * @lanes: number of data lanes used
+ * @alignment: data alignment in bits
+ * @hs_settle: HS-RX settle time
+ * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
+ *		   driver or true in case this regulator has no enable function
+ * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ */
+struct s5p_platform_mipi_csis {
+	unsigned long clk_rate;
+	u8 lanes;
+	u8 alignment;
+	u8 hs_settle;
+	bool fixed_phy_vdd;
+	int (*phy_enable)(struct platform_device *pdev, bool on);
+};
+
+/**
+ * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
+ * @pdev: MIPI-CSIS platform device
+ * @on: true to enable D-PHY and deassert its reset
+ *	false to disable D-PHY
+ */
+int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
+
+#endif /* PLAT_S5P_MIPI_CSIS_H_ */
diff --git a/arch/arm/plat-s5p/include/plat/s5p-time.h b/arch/arm/plat-s5p/include/plat/s5p-time.h
new file mode 100644
index 0000000..575e881
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/s5p-time.h
@@ -0,0 +1,40 @@
+/* linux/arch/arm/plat-s5p/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	struct sys_timer s5p_timer;
+#endif /* __ASM_PLAT_S5P_TIME_H */
diff --git a/arch/arm/plat-s5p/include/plat/s5pv310.h b/arch/arm/plat-s5p/include/plat/s5pv310.h
deleted file mode 100644
index 769c991..0000000
--- a/arch/arm/plat-s5p/include/plat/s5pv310.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5pv310.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5pv310 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.
-*/
-
-/* Common init code for S5PV310 related SoCs */
-
-extern void s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s5pv310_register_clocks(void);
-extern void s5pv310_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5PV310
-
-extern  int s5pv310_init(void);
-extern void s5pv310_init_irq(void);
-extern void s5pv310_map_io(void);
-extern void s5pv310_init_clocks(int xtal);
-extern struct sys_timer s5pv310_timer;
-
-#define s5pv310_init_uarts s5pv310_common_init_uarts
-
-#else
-#define s5pv310_init_clocks NULL
-#define s5pv310_init_uarts NULL
-#define s5pv310_map_io NULL
-#define s5pv310_init NULL
-#endif
diff --git a/arch/arm/plat-s5p/include/plat/sysmmu.h b/arch/arm/plat-s5p/include/plat/sysmmu.h
new file mode 100644
index 0000000..bf5283c
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/sysmmu.h
@@ -0,0 +1,95 @@
+/* linux/arch/arm/plat-s5p/include/plat/sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung System MMU driver for S5P platform
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifndef __ASM__PLAT_SYSMMU_H
+#define __ASM__PLAT_SYSMMU_H __FILE__
+
+enum S5P_SYSMMU_INTERRUPT_TYPE {
+	SYSMMU_PAGEFAULT,
+	SYSMMU_AR_MULTIHIT,
+	SYSMMU_AW_MULTIHIT,
+	SYSMMU_BUSERROR,
+	SYSMMU_AR_SECURITY,
+	SYSMMU_AR_ACCESS,
+	SYSMMU_AW_SECURITY,
+	SYSMMU_AW_PROTECTION, /* 7 */
+	SYSMMU_FAULTS_NUM
+};
+
+#ifdef CONFIG_S5P_SYSTEM_MMU
+
+#include <mach/sysmmu.h>
+
+/**
+ * s5p_sysmmu_enable() - enable system mmu of ip
+ * @ips: The ip connected system mmu.
+ * #pgd: Base physical address of the 1st level page table
+ *
+ * This function enable system mmu to transfer address
+ * from virtual address to physical address
+ */
+void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
+
+/**
+ * s5p_sysmmu_disable() - disable sysmmu mmu of ip
+ * @ips: The ip connected system mmu.
+ *
+ * This function disable system mmu to transfer address
+ * from virtual address to physical address
+ */
+void s5p_sysmmu_disable(sysmmu_ips ips);
+
+/**
+ * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
+ * @ips: The ip connected system mmu.
+ * @pgd: The page table base address.
+ *
+ * This function set page table base address
+ * When system mmu transfer address from virtaul address to physical address,
+ * system mmu refer address information from page table
+ */
+void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
+
+/**
+ * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
+ * @ips: The ip connected system mmu.
+ *
+ * This function flush all TLB entry in system mmu
+ */
+void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
+
+/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
+ * @itype: type of fault.
+ * @pgtable_base: the physical address of page table base. This is 0 if @ips is
+ *               SYSMMU_BUSERROR.
+ * @fault_addr: the device (virtual) address that the System MMU tried to
+ *             translated. This is 0 if @ips is SYSMMU_BUSERROR.
+ * Called when interrupt occurred by the System MMUs
+ * The device drivers of peripheral devices that has a System MMU can implement
+ * a fault handler to resolve address translation fault by System MMU.
+ * The meanings of return value and parameters are described below.
+
+ * return value: non-zero if the fault is correctly resolved.
+ *         zero if the fault is not handled.
+ */
+void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
+			int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+					unsigned long pgtable_base,
+					unsigned long fault_addr));
+#else
+#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
+#define s5p_sysmmu_disable(ips) do { } while (0)
+#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
+#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
+#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
+#endif
+#endif /* __ASM_PLAT_SYSMMU_H */
diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c
index 3b6bf89..cd87d32 100644
--- a/arch/arm/plat-s5p/irq-gpioint.c
+++ b/arch/arm/plat-s5p/irq-gpioint.c
@@ -17,82 +17,79 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/slab.h>
 
 #include <mach/map.h>
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 
-#define S5P_GPIOREG(x)			(S5P_VA_GPIO + (x))
+#define GPIO_BASE(chip)		(((unsigned long)(chip)->base) & 0xFFFFF000u)
 
-#define GPIOINT_CON_OFFSET		0x700
-#define GPIOINT_MASK_OFFSET		0x900
-#define GPIOINT_PEND_OFFSET		0xA00
+#define CON_OFFSET		0x700
+#define MASK_OFFSET		0x900
+#define PEND_OFFSET		0xA00
+#define REG_OFFSET(x)		((x) << 2)
 
-static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
-
-static int s5p_gpioint_get_group(struct irq_data *data)
-{
-	struct gpio_chip *chip = irq_data_get_irq_data(data);
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-	int group;
-
-	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++)
-		if (s3c_chip == irq_chips[group])
-			break;
+struct s5p_gpioint_bank {
+	struct list_head	list;
+	int			start;
+	int			nr_groups;
+	int			irq;
+	struct s3c_gpio_chip	**chips;
+	void			(*handler)(unsigned int, struct irq_desc *);
+};
 
-	return group;
-}
+LIST_HEAD(banks);
 
 static int s5p_gpioint_get_offset(struct irq_data *data)
 {
-	struct gpio_chip *chip = irq_data_get_irq_data(data);
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-
-	return data->irq - s3c_chip->irq_base;
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
+	return data->irq - chip->irq_base;
 }
 
 static void s5p_gpioint_ack(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, pend_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	pend_offset = group << 2;
+	pend_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
-	value |= 1 << offset;
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
+	value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
+	value |= BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
 }
 
 static void s5p_gpioint_mask(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	mask_offset = group << 2;
+	mask_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
-	value |= 1 << offset;
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
+	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
+	value |= BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 }
 
 static void s5p_gpioint_unmask(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	mask_offset = group << 2;
+	mask_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
-	value &= ~(1 << offset);
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
+	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
+	value &= ~BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 }
 
 static void s5p_gpioint_mask_ack(struct irq_data *data)
@@ -103,12 +100,13 @@ static void s5p_gpioint_mask_ack(struct irq_data *data)
 
 static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_data(data);
 	int group, offset, con_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	con_offset = group << 2;
+	con_offset = REG_OFFSET(group);
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -132,15 +130,15 @@ static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 		return -EINVAL;
 	}
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
+	value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset);
 	value &= ~(0x7 << (offset * 0x4));
 	value |= (type << (offset * 0x4));
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
+	__raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);
 
 	return 0;
 }
 
-struct irq_chip s5p_gpioint = {
+static struct irq_chip s5p_gpioint = {
 	.name		= "s5p_gpioint",
 	.irq_ack	= s5p_gpioint_ack,
 	.irq_mask	= s5p_gpioint_mask,
@@ -151,30 +149,29 @@ struct irq_chip s5p_gpioint = {
 
 static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 {
-	int group, offset, pend_offset, mask_offset;
-	int real_irq;
+	struct s5p_gpioint_bank *bank = get_irq_data(irq);
+	int group, pend_offset, mask_offset;
 	unsigned int pend, mask;
 
-	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
-		pend_offset = group << 2;
-		pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) +
-				pend_offset);
+	for (group = 0; group < bank->nr_groups; group++) {
+		struct s3c_gpio_chip *chip = bank->chips[group];
+		if (!chip)
+			continue;
+
+		pend_offset = REG_OFFSET(group);
+		pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
 		if (!pend)
 			continue;
 
-		mask_offset = group << 2;
-		mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) +
-				mask_offset);
+		mask_offset = REG_OFFSET(group);
+		mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 		pend &= ~mask;
 
-		for (offset = 0; offset < 8; offset++) {
-			if (pend & (1 << offset)) {
-				struct s3c_gpio_chip *chip = irq_chips[group];
-				if (chip) {
-					real_irq = chip->irq_base + offset;
-					generic_handle_irq(real_irq);
-				}
-			}
+		while (pend) {
+			int offset = fls(pend) - 1;
+			int real_irq = chip->irq_base + offset;
+			generic_handle_irq(real_irq);
+			pend &= ~BIT(offset);
 		}
 	}
 }
@@ -182,27 +179,48 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
 {
 	static int used_gpioint_groups = 0;
-	static bool handler_registered = 0;
 	int irq, group = chip->group;
 	int i;
+	struct s5p_gpioint_bank *bank = NULL;
 
 	if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
 		return -ENOMEM;
 
+	list_for_each_entry(bank, &banks, list) {
+		if (group >= bank->start &&
+		    group < bank->start + bank->nr_groups)
+			break;
+	}
+	if (!bank)
+		return -EINVAL;
+
+	if (!bank->handler) {
+		bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+				      bank->nr_groups, GFP_KERNEL);
+		if (!bank->chips)
+			return -ENOMEM;
+
+		set_irq_chained_handler(bank->irq, s5p_gpioint_handler);
+		set_irq_data(bank->irq, bank);
+		bank->handler = s5p_gpioint_handler;
+		printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
+		       bank->irq);
+	}
+
+	/*
+	 * chained GPIO irq has been sucessfully registered, allocate new gpio
+	 * int group and assign irq nubmers
+	 */
+
 	chip->irq_base = S5P_GPIOINT_BASE +
 			 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
 	used_gpioint_groups++;
 
-	if (!handler_registered) {
-		set_irq_chained_handler(IRQ_GPIOINT, s5p_gpioint_handler);
-		handler_registered = 1;
-	}
-
-	irq_chips[group] = chip;
+	bank->chips[group - bank->start] = chip;
 	for (i = 0; i < chip->chip.ngpio; i++) {
 		irq = chip->irq_base + i;
 		set_irq_chip(irq, &s5p_gpioint);
-		set_irq_data(irq, &chip->chip);
+		set_irq_data(irq, chip);
 		set_irq_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
@@ -235,3 +253,19 @@ int __init s5p_register_gpio_interrupt(int pin)
 	}
 	return ret;
 }
+
+int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
+{
+	struct s5p_gpioint_bank *bank;
+
+	bank = kzalloc(sizeof(*bank), GFP_KERNEL);
+	if (!bank)
+		return -ENOMEM;
+
+	bank->start = start;
+	bank->nr_groups = nr_groups;
+	bank->irq = chain_irq;
+
+	list_add_tail(&bank->list, &banks);
+	return 0;
+}
diff --git a/arch/arm/plat-s5p/s5p-time.c b/arch/arm/plat-s5p/s5p-time.c
new file mode 100644
index 0000000..8090403
--- /dev/null
+++ b/arch/arm/plat-s5p/s5p-time.c
@@ -0,0 +1,448 @@
+/* linux/arch/arm/plat-s5p/s5p-time.c
+ *
+ * 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/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+#include <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;
+
+	clockevents_calc_mult_shift(&time_event_device,
+				    clock_rate, S5PTIMER_MIN_RANGE);
+	time_event_device.max_delta_ns =
+		clockevent_delta2ns(-1, &time_event_device);
+	time_event_device.min_delta_ns =
+		clockevent_delta2ns(1, &time_event_device);
+
+	time_event_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&time_event_device);
+
+	irq_number = timer_source.event_id + IRQ_TIMER0;
+	setup_irq(irq_number, &s5p_clock_event_irq);
+}
+
+static cycle_t s5p_timer_read(struct clocksource *cs)
+{
+	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 0;
+	}
+
+	return (cycle_t) ~__raw_readl(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 DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc;
+	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 0;
+	}
+
+	cyc = ~__raw_readl(S3C_TIMERREG(offset));
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace s5p_update_sched_clock(void)
+{
+	u32 cyc;
+	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);
+	}
+
+	cyc = ~__raw_readl(S3C_TIMERREG(offset));
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+struct clocksource time_clocksource = {
+	.name		= "s5p_clocksource_timer",
+	.rating		= 250,
+	.read		= s5p_timer_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init s5p_clocksource_init(void)
+{
+	unsigned long pclk;
+	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);
+
+	init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate);
+
+	s5p_time_setup(timer_source.source_id, TCNT_MAX);
+	s5p_time_start(timer_source.source_id, PERIODIC);
+
+	if (clocksource_register_hz(&time_clocksource, clock_rate))
+		panic("%s: can't register clocksource\n", time_clocksource.name);
+}
+
+static void __init s5p_timer_resources(void)
+{
+
+	unsigned long event_id = timer_source.event_id;
+	unsigned long source_id = timer_source.source_id;
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for timer");
+
+	clk_enable(timerclk);
+
+	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);
+
+	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);
+}
+
+static void __init s5p_timer_init(void)
+{
+	s5p_timer_resources();
+	s5p_clockevent_init();
+	s5p_clocksource_init();
+}
+
+struct sys_timer s5p_timer = {
+	.init		= s5p_timer_init,
+};
diff --git a/arch/arm/plat-s5p/setup-mipiphy.c b/arch/arm/plat-s5p/setup-mipiphy.c
new file mode 100644
index 0000000..683c466
--- /dev/null
+++ b/arch/arm/plat-s5p/setup-mipiphy.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control
+ *
+ * This program is free software; you can 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/io.h>
+#include <linux/spinlock.h>
+#include <mach/regs-clock.h>
+
+static int __s5p_mipi_phy_control(struct platform_device *pdev,
+				  bool on, u32 reset)
+{
+	static DEFINE_SPINLOCK(lock);
+	void __iomem *addr;
+	unsigned long flags;
+	int pid;
+	u32 cfg;
+
+	if (!pdev)
+		return -EINVAL;
+
+	pid = (pdev->id == -1) ? 0 : pdev->id;
+
+	if (pid != 0 && pid != 1)
+		return -EINVAL;
+
+	addr = S5P_MIPI_DPHY_CONTROL(pid);
+
+	spin_lock_irqsave(&lock, flags);
+
+	cfg = __raw_readl(addr);
+	cfg = on ? (cfg | reset) : (cfg & ~reset);
+	__raw_writel(cfg, addr);
+
+	if (on) {
+		cfg |= S5P_MIPI_DPHY_ENABLE;
+	} else if (!(cfg & (S5P_MIPI_DPHY_SRESETN |
+			    S5P_MIPI_DPHY_MRESETN) & ~reset)) {
+		cfg &= ~S5P_MIPI_DPHY_ENABLE;
+	}
+
+	__raw_writel(cfg, addr);
+	spin_unlock_irqrestore(&lock, flags);
+
+	return 0;
+}
+
+int s5p_csis_phy_enable(struct platform_device *pdev, bool on)
+{
+	return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN);
+}
+
+int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
+{
+	return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN);
+}
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
index ffe8a48..54f5edd 100644
--- a/arch/arm/plat-s5p/sysmmu.c
+++ b/arch/arm/plat-s5p/sysmmu.c
@@ -12,280 +12,266 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
+#include <asm/pgtable.h>
+
 #include <mach/map.h>
 #include <mach/regs-sysmmu.h>
-#include <mach/sysmmu.h>
+#include <plat/sysmmu.h>
+
+#define CTRL_ENABLE	0x5
+#define CTRL_BLOCK	0x7
+#define CTRL_DISABLE	0x0
+
+static struct device *dev;
+
+static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
+	S5P_PAGE_FAULT_ADDR,
+	S5P_AR_FAULT_ADDR,
+	S5P_AW_FAULT_ADDR,
+	S5P_DEFAULT_SLAVE_ADDR,
+	S5P_AR_FAULT_ADDR,
+	S5P_AR_FAULT_ADDR,
+	S5P_AW_FAULT_ADDR,
+	S5P_AW_FAULT_ADDR
+};
+
+static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
+	"PAGE FAULT",
+	"AR MULTI-HIT FAULT",
+	"AW MULTI-HIT FAULT",
+	"BUS ERROR",
+	"AR SECURITY PROTECTION FAULT",
+	"AR ACCESS PROTECTION FAULT",
+	"AW SECURITY PROTECTION FAULT",
+	"AW ACCESS PROTECTION FAULT"
+};
 
-struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM];
+static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])(
+		enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+		unsigned long pgtable_base,
+		unsigned long fault_addr);
 
-void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp)
+/*
+ * If adjacent 2 bits are true, the system MMU is enabled.
+ * The system MMU is disabled, otherwise.
+ */
+static unsigned long sysmmu_states;
+
+static inline void set_sysmmu_active(sysmmu_ips ips)
 {
-	unsigned int reg_mmu_ctrl;
-	unsigned int reg_mmu_status;
-	unsigned int reg_pt_base_addr;
-	unsigned int reg_int_status;
-	unsigned int reg_page_ft_addr;
-
-	reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
-	reg_mmu_ctrl = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg_mmu_status = __raw_readl(sysmmuconp->regs + S5P_MMU_STATUS);
-	reg_pt_base_addr = __raw_readl(sysmmuconp->regs + S5P_PT_BASE_ADDR);
-	reg_page_ft_addr = __raw_readl(sysmmuconp->regs + S5P_PAGE_FAULT_ADDR);
-
-	printk(KERN_INFO "%s: ips:%s\n", __func__, sysmmuconp->name);
-	printk(KERN_INFO "%s: MMU_CTRL:0x%X, ", __func__, reg_mmu_ctrl);
-	printk(KERN_INFO "MMU_STATUS:0x%X, PT_BASE_ADDR:0x%X\n", reg_mmu_status, reg_pt_base_addr);
-	printk(KERN_INFO "%s: INT_STATUS:0x%X, PAGE_FAULT_ADDR:0x%X\n", __func__, reg_int_status, reg_page_ft_addr);
-
-	switch (reg_int_status & 0xFF) {
-	case 0x1:
-		printk(KERN_INFO "%s: Page fault\n", __func__);
-		printk(KERN_INFO "%s: Virtual address causing last page fault or bus error : 0x%x\n", __func__ , reg_page_ft_addr);
-		break;
-	case 0x2:
-		printk(KERN_INFO "%s: AR multi-hit fault\n", __func__);
-		break;
-	case 0x4:
-		printk(KERN_INFO "%s: AW multi-hit fault\n", __func__);
-		break;
-	case 0x8:
-		printk(KERN_INFO "%s: Bus error\n", __func__);
-		break;
-	case 0x10:
-		printk(KERN_INFO "%s: AR Security protection fault\n", __func__);
-		break;
-	case 0x20:
-		printk(KERN_INFO "%s: AR Access protection fault\n", __func__);
-		break;
-	case 0x40:
-		printk(KERN_INFO "%s: AW Security protection fault\n", __func__);
-		break;
-	case 0x80:
-		printk(KERN_INFO "%s: AW Access protection fault\n", __func__);
-		break;
-	}
+	sysmmu_states |= 3 << (ips * 2);
 }
 
-static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
+static inline void set_sysmmu_inactive(sysmmu_ips ips)
 {
-	unsigned int i;
-	unsigned int reg_int_status;
-	struct sysmmu_controller *sysmmuconp;
-
-	for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
-		sysmmuconp = &s5p_sysmmu_cntlrs[i];
-
-		if (sysmmuconp->enable == true) {
-			reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
-
-			if (reg_int_status & 0xFF)
-				s5p_sysmmu_register(sysmmuconp);
-		}
-	}
-	return IRQ_HANDLED;
+	sysmmu_states &= ~(3 << (ips * 2));
 }
 
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
+static inline int is_sysmmu_active(sysmmu_ips ips)
 {
-	struct sysmmu_controller *sysmmuconp = NULL;
-
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
-	}
-
-	/* Set sysmmu page table base address */
-	__raw_writel(pgd, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+	return sysmmu_states & (3 << (ips * 2));
+}
 
-	if (s5p_sysmmu_tlb_invalidate(ips) != 0)
-		printk(KERN_ERR "failed s5p_sysmmu_tlb_invalidate\n");
+static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM];
 
-	return 0;
+static inline void sysmmu_block(sysmmu_ips ips)
+{
+	__raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL);
+	dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]);
 }
 
-static int s5p_sysmmu_set_tablebase(sysmmu_ips ips)
+static inline void sysmmu_unblock(sysmmu_ips ips)
 {
-	unsigned int pg;
-	struct sysmmu_controller *sysmmuconp;
+	__raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
+	dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]);
+}
 
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips)
+{
+	__raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH);
+	dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]);
+}
 
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
+static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd)
+{
+	if (unlikely(pgd == 0)) {
+		pgd = (unsigned long)ZERO_PAGE(0);
+		__raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */
+	} else {
+		__raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */
 	}
 
-	__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
-		: "=r" (pg) : : "cc");		\
-		pg &= ~0x3fff;
+	__raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
 
-	printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg);
-
-	/* Set sysmmu page table base address */
-	__raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+	dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n",
+						sysmmu_ips_name[ips], pgd);
+	__sysmmu_tlb_invalidate(ips);
+}
 
-	return 0;
+void sysmmu_set_fault_handler(sysmmu_ips ips,
+			int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+					unsigned long pgtable_base,
+					unsigned long fault_addr))
+{
+	BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM)));
+	fault_handlers[ips] = handler;
 }
 
-int s5p_sysmmu_enable(sysmmu_ips ips)
+static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
 {
-	unsigned int reg;
+	/* SYSMMU is in blocked when interrupt occurred. */
+	unsigned long base = 0;
+	sysmmu_ips ips = (sysmmu_ips)dev_id;
+	enum S5P_SYSMMU_INTERRUPT_TYPE itype;
 
-	struct sysmmu_controller *sysmmuconp;
+	itype = (enum S5P_SYSMMU_INTERRUPT_TYPE)
+		__ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS));
 
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+	BUG_ON(!((itype >= 0) && (itype < 8)));
 
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
-	}
+	dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype],
+							sysmmu_ips_name[ips]);
 
-	s5p_sysmmu_set_tablebase(ips);
+	if (fault_handlers[ips]) {
+		unsigned long addr;
 
-	/* replacement policy : LRU */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
-	reg |= 0x1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
+		base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
+		addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]);
 
-	/* Enable interrupt, Enable MMU */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg |= (0x1 << 2) | (0x1 << 0);
+		if (fault_handlers[ips](itype, base, addr)) {
+			__raw_writel(1 << itype,
+					sysmmusfrs[ips] + S5P_INT_CLEAR);
+			dev_notice(dev, "%s from %s is resolved."
+					" Retrying translation.\n",
+				sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
+		} else {
+			base = 0;
+		}
+	}
 
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+	sysmmu_unblock(ips);
 
-	sysmmuconp->enable = true;
+	if (!base)
+		dev_notice(dev, "%s from %s is not handled.\n",
+			sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
 
-	return 0;
+	return IRQ_HANDLED;
 }
 
-int s5p_sysmmu_disable(sysmmu_ips ips)
+void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
 {
-	unsigned int reg;
-
-	struct sysmmu_controller *sysmmuconp = NULL;
-
-	if (ips > S5P_SYSMMU_TOTAL_IPNUM)
-		printk(KERN_ERR "failed to get ips parameter\n");
-
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
+	if (is_sysmmu_active(ips)) {
+		sysmmu_block(ips);
+		__sysmmu_set_ptbase(ips, pgd);
+		sysmmu_unblock(ips);
+	} else {
+		dev_dbg(dev, "%s is disabled. "
+			"Skipping initializing page table base.\n",
+						sysmmu_ips_name[ips]);
 	}
+}
 
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
-
-	/* replacement policy : LRU */
-	reg |= 0x1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
-
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd)
+{
+	if (!is_sysmmu_active(ips)) {
+		sysmmu_clk_enable(ips);
 
-	/* Disable MMU */
-	reg &= ~0x1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+		__sysmmu_set_ptbase(ips, pgd);
 
-	sysmmuconp->enable = false;
+		__raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
 
-	return 0;
+		set_sysmmu_active(ips);
+		dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]);
+	} else {
+		dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]);
+	}
 }
 
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
+void s5p_sysmmu_disable(sysmmu_ips ips)
 {
-	unsigned int reg;
-	struct sysmmu_controller *sysmmuconp = NULL;
-
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
+	if (is_sysmmu_active(ips)) {
+		__raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
+		set_sysmmu_inactive(ips);
+		sysmmu_clk_disable(ips);
+		dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]);
+	} else {
+		dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]);
 	}
+}
 
-	/* set Block MMU for flush TLB */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg |= 0x1 << 1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
-	/* flush all TLB entry */
-	__raw_writel(0x1, sysmmuconp->regs + S5P_MMU_FLUSH);
-
-	/* set Un-block MMU after flush TLB */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg &= ~(0x1 << 1);
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
-	return 0;
+void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
+{
+	if (is_sysmmu_active(ips)) {
+		sysmmu_block(ips);
+		__sysmmu_tlb_invalidate(ips);
+		sysmmu_unblock(ips);
+	} else {
+		dev_dbg(dev, "%s is disabled. "
+			"Skipping invalidating TLB.\n", sysmmu_ips_name[ips]);
+	}
 }
 
 static int s5p_sysmmu_probe(struct platform_device *pdev)
 {
-	int i;
-	int ret;
-	struct resource *res;
-	struct sysmmu_controller *sysmmuconp;
-	sysmmu_ips ips;
+	int i, ret;
+	struct resource *res, *mem;
+
+	dev = &pdev->dev;
 
 	for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
-		sysmmuconp = &s5p_sysmmu_cntlrs[i];
-		if (sysmmuconp == NULL) {
-			printk(KERN_ERR "failed to get ip's sysmmu info\n");
-			ret = -ENOENT;
-			goto err_res;
-		}
+		int irq;
 
-		sysmmuconp->name = sysmmu_ips_name[i];
+		sysmmu_clk_init(dev, i);
+		sysmmu_clk_disable(i);
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 		if (!res) {
-			printk(KERN_ERR "failed to get sysmmu resource\n");
+			dev_err(dev, "Failed to get the resource of %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENODEV;
 			goto err_res;
 		}
 
-		sysmmuconp->mem = request_mem_region(res->start,
+		mem = request_mem_region(res->start,
 				((res->end) - (res->start)) + 1, pdev->name);
-		if (!sysmmuconp->mem) {
-			pr_err("failed to request sysmmu memory region\n");
+		if (!mem) {
+			dev_err(dev, "Failed to request the memory region of %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -EBUSY;
 			goto err_res;
 		}
 
-		sysmmuconp->regs = ioremap(res->start, res->end - res->start + 1);
-		if (!sysmmuconp->regs) {
-			pr_err("failed to sysmmu ioremap\n");
+		sysmmusfrs[i] = ioremap(res->start, res->end - res->start + 1);
+		if (!sysmmusfrs[i]) {
+			dev_err(dev, "Failed to ioremap() for %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENXIO;
 			goto err_reg;
 		}
 
-		sysmmuconp->irq = platform_get_irq(pdev, i);
-		if (sysmmuconp->irq <= 0) {
-			pr_err("failed to get sysmmu irq resource\n");
+		irq = platform_get_irq(pdev, i);
+		if (irq <= 0) {
+			dev_err(dev, "Failed to get the IRQ resource of %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENOENT;
 			goto err_map;
 		}
 
-		ret = request_irq(sysmmuconp->irq, s5p_sysmmu_irq, IRQF_DISABLED, pdev->name, sysmmuconp);
-		if (ret) {
-			pr_err("failed to request irq\n");
+		if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED,
+						pdev->name, (void *)i)) {
+			dev_err(dev, "Failed to request IRQ for %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENOENT;
 			goto err_map;
 		}
-
-		ips = (sysmmu_ips)i;
-
-		sysmmuconp->ips = ips;
 	}
 
 	return 0;
 
-err_reg:
-	release_mem_region((resource_size_t)sysmmuconp->mem, (resource_size_t)((res->end) - (res->start) + 1));
 err_map:
-	iounmap(sysmmuconp->regs);
+	iounmap(sysmmusfrs[i]);
+err_reg:
+	release_mem_region(mem->start, resource_size(mem));
 err_res:
 	return ret;
 }
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 32be05c..be72100 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -273,6 +273,19 @@ config SAMSUNG_DEV_KEYPAD
 	help
 	  Compile in platform device definitions for keypad
 
+config SAMSUNG_DEV_PWM
+	bool
+	default y if ARCH_S3C2410
+	help
+	  Compile in platform device definition for PWM Timer
+
+config S3C24XX_PWM
+	bool "PWM device support"
+	select HAVE_PWM
+	help
+	  Support for exporting the PWM timer blocks via the pwm device
+	  system
+
 # DMA
 
 config S3C_DMA
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 29932f8..e9de58a 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_SAMSUNG_DEV_ADC)	+= dev-adc.o
 obj-$(CONFIG_SAMSUNG_DEV_IDE)	+= dev-ide.o
 obj-$(CONFIG_SAMSUNG_DEV_TS)	+= dev-ts.o
 obj-$(CONFIG_SAMSUNG_DEV_KEYPAD)	+= dev-keypad.o
+obj-$(CONFIG_SAMSUNG_DEV_PWM)	+= dev-pwm.o
 
 # DMA support
 
diff --git a/arch/arm/plat-samsung/dev-pwm.c b/arch/arm/plat-samsung/dev-pwm.c
new file mode 100644
index 0000000..dab47b0
--- /dev/null
+++ b/arch/arm/plat-samsung/dev-pwm.c
@@ -0,0 +1,53 @@
+/* linux/arch/arm/plat-samsung/dev-pwm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2007 Ben Dooks
+ * Copyright (c) 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
+ *
+ * S3C series device definition for the PWM timer
+ *
+ * This program is free software; you can 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 <mach/irqs.h>
+
+#include <plat/devs.h>
+
+#define TIMER_RESOURCE_SIZE (1)
+
+#define TIMER_RESOURCE(_tmr, _irq)			\
+	(struct resource [TIMER_RESOURCE_SIZE]) {	\
+		[0] = {					\
+			.start	= _irq,			\
+			.end	= _irq,			\
+			.flags	= IORESOURCE_IRQ	\
+		}					\
+	}
+
+#define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
+	.name		= "s3c24xx-pwm",		\
+	.id		= _tmr_no,			\
+	.num_resources	= TIMER_RESOURCE_SIZE,		\
+	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
+
+/*
+ * since we already have an static mapping for the timer,
+ * we do not bother setting any IO resource for the base.
+ */
+
+struct platform_device s3c_device_timer[] = {
+	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
+	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
+	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
+	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
+	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+};
+EXPORT_SYMBOL(s3c_device_timer);
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 9addb3d..cedfff5 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -82,6 +82,7 @@ extern struct sysdev_class s3c64xx_sysclass;
 extern struct sysdev_class s5p64x0_sysclass;
 extern struct sysdev_class s5p6442_sysclass;
 extern struct sysdev_class s5pv210_sysclass;
+extern struct sysdev_class exynos4_sysclass;
 
 extern void (*s5pc1xx_idle)(void);
 
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index b4d208b..f0da6b7 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -1,5 +1,8 @@
 /* arch/arm/plat-samsung/include/plat/devs.h
  *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (c) 2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
  *
@@ -96,15 +99,16 @@ extern struct platform_device s5pv210_device_iis1;
 extern struct platform_device s5pv210_device_iis2;
 extern struct platform_device s5pv210_device_spdif;
 
-extern struct platform_device s5pv310_device_ac97;
-extern struct platform_device s5pv310_device_pcm0;
-extern struct platform_device s5pv310_device_pcm1;
-extern struct platform_device s5pv310_device_pcm2;
-extern struct platform_device s5pv310_device_i2s0;
-extern struct platform_device s5pv310_device_i2s1;
-extern struct platform_device s5pv310_device_i2s2;
-extern struct platform_device s5pv310_device_spdif;
-extern struct platform_device s5pv310_device_pd[];
+extern struct platform_device exynos4_device_ac97;
+extern struct platform_device exynos4_device_pcm0;
+extern struct platform_device exynos4_device_pcm1;
+extern struct platform_device exynos4_device_pcm2;
+extern struct platform_device exynos4_device_i2s0;
+extern struct platform_device exynos4_device_i2s1;
+extern struct platform_device exynos4_device_i2s2;
+extern struct platform_device exynos4_device_spdif;
+extern struct platform_device exynos4_device_pd[];
+extern struct platform_device exynos4_device_ahci;
 
 extern struct platform_device s5p6442_device_pcm0;
 extern struct platform_device s5p6442_device_pcm1;
@@ -133,11 +137,12 @@ extern struct platform_device samsung_device_keypad;
 extern struct platform_device s5p_device_fimc0;
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
+extern struct platform_device s5p_device_fimc3;
 
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
 
-extern struct platform_device s5pv310_device_sysmmu;
+extern struct platform_device exynos4_device_sysmmu;
 
 /* s3c2440 specific devices */
 
diff --git a/arch/arm/plat-samsung/include/plat/fimc-core.h b/arch/arm/plat-samsung/include/plat/fimc-core.h
index 81a3bfe..945a99d 100644
--- a/arch/arm/plat-samsung/include/plat/fimc-core.h
+++ b/arch/arm/plat-samsung/include/plat/fimc-core.h
@@ -38,6 +38,11 @@ static inline void s3c_fimc_setname(int id, char *name)
 		s5p_device_fimc2.name = name;
 		break;
 #endif
+#ifdef CONFIG_S5P_DEV_FIMC3
+	case 3:
+		s5p_device_fimc3.name = name;
+		break;
+#endif
 	}
 }
 
diff --git a/arch/arm/plat-samsung/include/plat/gpio-cfg.h b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
index e4b5cf1..5e04fa6 100644
--- a/arch/arm/plat-samsung/include/plat/gpio-cfg.h
+++ b/arch/arm/plat-samsung/include/plat/gpio-cfg.h
@@ -225,4 +225,20 @@ extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
  */
 extern int s5p_register_gpio_interrupt(int pin);
 
+/** s5p_register_gpioint_bank() - add gpio bank for further gpio interrupt
+ * registration (see s5p_register_gpio_interrupt function)
+ * @chain_irq: chained irq number for the gpio int handler for this bank
+ * @start: start gpio group number of this bank
+ * @nr_groups: number of gpio groups handled by this bank
+ *
+ * This functions registers initial information about gpio banks that
+ * can be later used by the s5p_register_gpio_interrupt() function to
+ * enable support for gpio interrupt for particular gpio group.
+ */
+#ifdef CONFIG_S5P_GPIO_INT
+extern int s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups);
+#else
+#define s5p_register_gpioint_bank(chain_irq, start, nr_groups) do { } while (0)
+#endif
+
 #endif /* __PLAT_GPIO_CFG_H */
diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h
index 5f0ad85..abb4bc3 100644
--- a/arch/arm/plat-samsung/include/plat/pd.h
+++ b/arch/arm/plat-samsung/include/plat/pd.h
@@ -1,6 +1,6 @@
 /* linux/arch/arm/plat-samsung/include/plat/pd.h
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,7 +17,7 @@ struct samsung_pd_info {
 	void __iomem *base;
 };
 
-enum s5pv310_pd_block {
+enum exynos4_pd_block {
 	PD_MFC,
 	PD_G3D,
 	PD_LCD0,
diff --git a/arch/arm/plat-samsung/include/plat/pm.h b/arch/arm/plat-samsung/include/plat/pm.h
index 30518cc..937cc2a 100644
--- a/arch/arm/plat-samsung/include/plat/pm.h
+++ b/arch/arm/plat-samsung/include/plat/pm.h
@@ -52,13 +52,11 @@ extern unsigned char pm_uart_udivslot;  /* true to save UART UDIVSLOT */
 
 /* from sleep.S */
 
-extern int  s3c_cpu_save(unsigned long *saveblk);
+extern int  s3c_cpu_save(unsigned long *saveblk, long);
 extern void s3c_cpu_resume(void);
 
 extern void s3c2410_cpu_suspend(void);
 
-extern unsigned long s3c_sleep_save_phys;
-
 /* sleep save info */
 
 /**
@@ -181,13 +179,5 @@ extern void s3c_pm_restore_gpios(void);
  */
 extern void s3c_pm_save_gpios(void);
 
-/**
- * s3c_pm_cb_flushcache - callback for assembly code
- *
- * Callback to issue flush_cache_all() as this call is
- * not a directly callable object.
- */
-extern void s3c_pm_cb_flushcache(void);
-
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 5a41a0b..b0bdf16 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -1,4 +1,7 @@
-/* linux/arch/arm/plat-s3c/include/plat/sdhci.h
+/* linux/arch/arm/plat-samsung/include/plat/sdhci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
@@ -119,10 +122,10 @@ extern void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
 extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
 extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
 extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
 
 /* S3C2416 SDHCI setup */
 
@@ -334,57 +337,57 @@ static inline void s5pv210_default_sdhci3(void) { }
 
 #endif /* CONFIG_S5PV210_SETUP_SDHCI */
 
-/* S5PV310 SDHCI setup */
-#ifdef CONFIG_S5PV310_SETUP_SDHCI
-extern char *s5pv310_hsmmc_clksrcs[4];
+/* EXYNOS4 SDHCI setup */
+#ifdef CONFIG_EXYNOS4_SETUP_SDHCI
+extern char *exynos4_hsmmc_clksrcs[4];
 
-extern void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev,
+extern void exynos4_setup_sdhci_cfg_card(struct platform_device *dev,
 					   void __iomem *r,
 					   struct mmc_ios *ios,
 					   struct mmc_card *card);
 
-static inline void s5pv310_default_sdhci0(void)
+static inline void exynos4_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
-	s3c_hsmmc0_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc0_def_platdata.cfg_gpio = s5pv310_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc0_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
-static inline void s5pv310_default_sdhci1(void)
+static inline void exynos4_default_sdhci1(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC1
-	s3c_hsmmc1_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc1_def_platdata.cfg_gpio = s5pv310_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc1_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
-static inline void s5pv310_default_sdhci2(void)
+static inline void exynos4_default_sdhci2(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC2
-	s3c_hsmmc2_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5pv310_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc2_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio;
+	s3c_hsmmc2_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
-static inline void s5pv310_default_sdhci3(void)
+static inline void exynos4_default_sdhci3(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC3
-	s3c_hsmmc3_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc3_def_platdata.cfg_gpio = s5pv310_setup_sdhci3_cfg_gpio;
-	s3c_hsmmc3_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc3_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio;
+	s3c_hsmmc3_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
 #else
-static inline void s5pv310_default_sdhci0(void) { }
-static inline void s5pv310_default_sdhci1(void) { }
-static inline void s5pv310_default_sdhci2(void) { }
-static inline void s5pv310_default_sdhci3(void) { }
+static inline void exynos4_default_sdhci0(void) { }
+static inline void exynos4_default_sdhci1(void) { }
+static inline void exynos4_default_sdhci2(void) { }
+static inline void exynos4_default_sdhci3(void) { }
 
-#endif /* CONFIG_S5PV310_SETUP_SDHCI */
+#endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
 
 #endif /* __PLAT_S3C_SDHCI_H */
diff --git a/arch/arm/plat-samsung/pm.c b/arch/arm/plat-samsung/pm.c
index 02d531f..d5b58d3 100644
--- a/arch/arm/plat-samsung/pm.c
+++ b/arch/arm/plat-samsung/pm.c
@@ -241,8 +241,6 @@ void (*pm_cpu_sleep)(void);
 
 static int s3c_pm_enter(suspend_state_t state)
 {
-	static unsigned long regs_save[16];
-
 	/* ensure the debug is initialised (if enabled) */
 
 	s3c_pm_debug_init();
@@ -266,12 +264,6 @@ static int s3c_pm_enter(suspend_state_t state)
 		return -EINVAL;
 	}
 
-	/* store the physical address of the register recovery block */
-
-	s3c_sleep_save_phys = virt_to_phys(regs_save);
-
-	S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
-
 	/* save all necessary core registers not covered by the drivers */
 
 	s3c_pm_save_gpios();
@@ -305,7 +297,7 @@ static int s3c_pm_enter(suspend_state_t state)
 	 * we resume as it saves its own register state and restores it
 	 * during the resume.  */
 
-	s3c_cpu_save(regs_save);
+	s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
 	/* restore the cpu state using the kernel's cpu init code. */
 
@@ -336,12 +328,6 @@ static int s3c_pm_enter(suspend_state_t state)
 	return 0;
 }
 
-/* callback from assembly code */
-void s3c_pm_cb_flushcache(void)
-{
-	flush_cache_all();
-}
-
 static int s3c_pm_prepare(void)
 {
 	/* prepare check area if configured */
diff --git a/arch/arm/plat-samsung/pwm.c b/arch/arm/plat-samsung/pwm.c
index 2eeb49f..f37457c 100644
--- a/arch/arm/plat-samsung/pwm.c
+++ b/arch/arm/plat-samsung/pwm.c
@@ -20,10 +20,8 @@
 #include <linux/io.h>
 #include <linux/pwm.h>
 
-#include <mach/irqs.h>
 #include <mach/map.h>
 
-#include <plat/devs.h>
 #include <plat/regs-timer.h>
 
 struct pwm_device {
@@ -47,37 +45,6 @@ struct pwm_device {
 
 static struct clk *clk_scaler[2];
 
-/* Standard setup for a timer block. */
-
-#define TIMER_RESOURCE_SIZE (1)
-
-#define TIMER_RESOURCE(_tmr, _irq)			\
-	(struct resource [TIMER_RESOURCE_SIZE]) {	\
-		[0] = {					\
-			.start	= _irq,			\
-			.end	= _irq,			\
-			.flags	= IORESOURCE_IRQ	\
-		}					\
-	}
-
-#define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
-	.name		= "s3c24xx-pwm",		\
-	.id		= _tmr_no,			\
-	.num_resources	= TIMER_RESOURCE_SIZE,		\
-	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
-
-/* since we already have an static mapping for the timer, we do not
- * bother setting any IO resource for the base.
- */
-
-struct platform_device s3c_device_timer[] = {
-	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
-	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
-	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
-	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
-	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
-};
-
 static inline int pwm_is_tdiv(struct pwm_device *pwm)
 {
 	return clk_get_parent(pwm->clk) == pwm->clk_div;
diff --git a/arch/arm/plat-spear/Makefile b/arch/arm/plat-spear/Makefile
index eb89540..b4f340b 100644
--- a/arch/arm/plat-spear/Makefile
+++ b/arch/arm/plat-spear/Makefile
@@ -3,6 +3,6 @@
 #
 
 # Common support
-obj-y	:= clock.o padmux.o time.o
+obj-y	:= clock.o time.o
 
-obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
diff --git a/arch/arm/plat-spear/clock.c b/arch/arm/plat-spear/clock.c
index ee4f90e..bdbd7ec 100644
--- a/arch/arm/plat-spear/clock.c
+++ b/arch/arm/plat-spear/clock.c
@@ -12,18 +12,25 @@
  */
 
 #include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <mach/misc_regs.h>
 #include <plat/clock.h>
 
 static DEFINE_SPINLOCK(clocks_lock);
 static LIST_HEAD(root_clks);
+#ifdef CONFIG_DEBUG_FS
+static LIST_HEAD(clocks);
+#endif
 
-static void propagate_rate(struct list_head *);
+static void propagate_rate(struct clk *, int on_init);
+#ifdef CONFIG_DEBUG_FS
+static int clk_debugfs_reparent(struct clk *);
+#endif
 
 static int generic_clk_enable(struct clk *clk)
 {
@@ -65,6 +72,104 @@ static struct clkops generic_clkops = {
 	.disable = generic_clk_disable,
 };
 
+/* returns current programmed clocks clock info structure */
+static struct pclk_info *pclk_info_get(struct clk *clk)
+{
+	unsigned int val, i;
+	struct pclk_info *info = NULL;
+
+	val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
+		& clk->pclk_sel->pclk_sel_mask;
+
+	for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
+		if (clk->pclk_sel->pclk_info[i].pclk_val == val)
+			info = &clk->pclk_sel->pclk_info[i];
+	}
+
+	return info;
+}
+
+/*
+ * Set Update pclk, and pclk_info of clk and add clock sibling node to current
+ * parents children list
+ */
+static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	list_del(&clk->sibling);
+	list_add(&clk->sibling, &pclk_info->pclk->children);
+
+	clk->pclk = pclk_info->pclk;
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+#ifdef CONFIG_DEBUG_FS
+	clk_debugfs_reparent(clk);
+#endif
+}
+
+static void do_clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	if (!clk->usage_count) {
+		WARN_ON(1);
+		return;
+	}
+
+	clk->usage_count--;
+
+	if (clk->usage_count == 0) {
+		/*
+		 * Surely, there are no active childrens or direct users
+		 * of this clock
+		 */
+		if (clk->pclk)
+			do_clk_disable(clk->pclk);
+
+		if (clk->ops && clk->ops->disable)
+			clk->ops->disable(clk);
+	}
+}
+
+static int do_clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		return -EFAULT;
+
+	if (clk->usage_count == 0) {
+		if (clk->pclk) {
+			ret = do_clk_enable(clk->pclk);
+			if (ret)
+				goto err;
+		}
+		if (clk->ops && clk->ops->enable) {
+			ret = clk->ops->enable(clk);
+			if (ret) {
+				if (clk->pclk)
+					do_clk_disable(clk->pclk);
+				goto err;
+			}
+		}
+		/*
+		 * Since the clock is going to be used for the first
+		 * time please reclac
+		 */
+		if (clk->recalc) {
+			ret = clk->recalc(clk);
+			if (ret)
+				goto err;
+		}
+	}
+	clk->usage_count++;
+err:
+	return ret;
+}
+
 /*
  * clk_enable - inform the system when the clock source should be running.
  * @clk: clock source
@@ -78,17 +183,9 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
-	if (!clk || IS_ERR(clk))
-		return -EFAULT;
-
 	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->usage_count == 0) {
-		if (clk->ops && clk->ops->enable)
-			ret = clk->ops->enable(clk);
-	}
-	clk->usage_count++;
+	ret = do_clk_enable(clk);
 	spin_unlock_irqrestore(&clocks_lock, flags);
-
 	return ret;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -109,17 +206,8 @@ void clk_disable(struct clk *clk)
 {
 	unsigned long flags;
 
-	if (!clk || IS_ERR(clk))
-		return;
-
-	WARN_ON(clk->usage_count == 0);
-
 	spin_lock_irqsave(&clocks_lock, flags);
-	clk->usage_count--;
-	if (clk->usage_count == 0) {
-		if (clk->ops && clk->ops->disable)
-			clk->ops->disable(clk);
-	}
+	do_clk_disable(clk);
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
@@ -153,15 +241,14 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	int i, found = 0, val = 0;
 	unsigned long flags;
 
-	if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent))
+	if (!clk || !parent)
 		return -EFAULT;
-	if (clk->usage_count)
-		return -EBUSY;
-	if (!clk->pclk_sel)
-		return -EPERM;
 	if (clk->pclk == parent)
 		return 0;
+	if (!clk->pclk_sel)
+		return -EPERM;
 
+	/* check if requested parent is in clk parent list */
 	for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
 		if (clk->pclk_sel->pclk_info[i].pclk == parent) {
 			found = 1;
@@ -176,25 +263,58 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
 	/* reflect parent change in hardware */
 	val = readl(clk->pclk_sel->pclk_sel_reg);
 	val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift);
-	val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift;
+	val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift;
 	writel(val, clk->pclk_sel->pclk_sel_reg);
 	spin_unlock_irqrestore(&clocks_lock, flags);
 
 	/* reflect parent change in software */
-	clk->recalc(clk);
-	propagate_rate(&clk->children);
+	clk_reparent(clk, &clk->pclk_sel->pclk_info[i]);
+
+	propagate_rate(clk, 0);
 	return 0;
 }
 EXPORT_SYMBOL(clk_set_parent);
 
+/**
+ * clk_set_rate - set the clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (!clk || !rate)
+		return -EFAULT;
+
+	if (clk->set_rate) {
+		spin_lock_irqsave(&clocks_lock, flags);
+		ret = clk->set_rate(clk, rate);
+		if (!ret)
+			/* if successful -> propagate */
+			propagate_rate(clk, 0);
+		spin_unlock_irqrestore(&clocks_lock, flags);
+	} else if (clk->pclk) {
+		u32 mult = clk->div_factor ? clk->div_factor : 1;
+		ret = clk_set_rate(clk->pclk, mult * rate);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
 /* registers clock in platform clock framework */
 void clk_register(struct clk_lookup *cl)
 {
-	struct clk *clk = cl->clk;
+	struct clk *clk;
 	unsigned long flags;
 
-	if (!clk || IS_ERR(clk))
+	if (!cl || !cl->clk)
 		return;
+	clk = cl->clk;
 
 	spin_lock_irqsave(&clocks_lock, flags);
 
@@ -207,71 +327,173 @@ void clk_register(struct clk_lookup *cl)
 	/* root clock don't have any parents */
 	if (!clk->pclk && !clk->pclk_sel) {
 		list_add(&clk->sibling, &root_clks);
-		/* add clocks with only one parent to parent's children list */
 	} else if (clk->pclk && !clk->pclk_sel) {
+		/* add clocks with only one parent to parent's children list */
 		list_add(&clk->sibling, &clk->pclk->children);
 	} else {
-		/* add clocks with > 1 parent to 1st parent's children list */
-		list_add(&clk->sibling,
-			 &clk->pclk_sel->pclk_info[0].pclk->children);
+		/* clocks with more than one parent */
+		struct pclk_info *pclk_info;
+
+		pclk_info = pclk_info_get(clk);
+		if (!pclk_info) {
+			pr_err("CLKDEV: invalid pclk info of clk with"
+					" %s dev_id and %s con_id\n",
+					cl->dev_id, cl->con_id);
+		} else {
+			clk->pclk = pclk_info->pclk;
+			list_add(&clk->sibling, &pclk_info->pclk->children);
+		}
 	}
+
 	spin_unlock_irqrestore(&clocks_lock, flags);
 
+	/* debugfs specific */
+#ifdef CONFIG_DEBUG_FS
+	list_add(&clk->node, &clocks);
+	clk->cl = cl;
+#endif
+
 	/* add clock to arm clockdev framework */
 	clkdev_add(cl);
 }
 
 /**
- * propagate_rate - recalculate and propagate all clocks in list head
+ * propagate_rate - recalculate and propagate all clocks to children
+ * @pclk: parent clock required to be propogated
+ * @on_init: flag for enabling clocks which are ENABLED_ON_INIT.
  *
- * Recalculates all root clocks in list head, which if the clock's .recalc is
- * set correctly, should also propagate their rates.
+ * Recalculates all children clocks
  */
-static void propagate_rate(struct list_head *lhead)
+void propagate_rate(struct clk *pclk, int on_init)
 {
-	struct clk *clkp, *_temp;
+	struct clk *clk, *_temp;
+	int ret = 0;
 
-	list_for_each_entry_safe(clkp, _temp, lhead, sibling) {
-		if (clkp->recalc)
-			clkp->recalc(clkp);
-		propagate_rate(&clkp->children);
+	list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
+		if (clk->recalc) {
+			ret = clk->recalc(clk);
+			/*
+			 * recalc will return error if clk out is not programmed
+			 * In this case configure default rate.
+			 */
+			if (ret && clk->set_rate)
+				clk->set_rate(clk, 0);
+		}
+		propagate_rate(clk, on_init);
+
+		if (!on_init)
+			continue;
+
+		/* Enable clks enabled on init, in software view */
+		if (clk->flags & ENABLED_ON_INIT)
+			do_clk_enable(clk);
 	}
 }
 
-/* returns current programmed clocks clock info structure */
-static struct pclk_info *pclk_info_get(struct clk *clk)
+/**
+ * round_rate_index - return closest programmable rate index in rate_config tbl
+ * @clk: ptr to clock structure
+ * @drate: desired rate
+ * @rate: final rate will be returned in this variable only.
+ *
+ * Finds index in rate_config for highest clk rate which is less than
+ * requested rate. If there is no clk rate lesser than requested rate then
+ * -EINVAL is returned. This routine assumes that rate_config is written
+ * in incrementing order of clk rates.
+ * If drate passed is zero then default rate is programmed.
+ */
+static int
+round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
 {
-	unsigned int mask, i;
-	unsigned long flags;
-	struct pclk_info *info = NULL;
+	unsigned long tmp = 0, prev_rate = 0;
+	int index;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
-			& clk->pclk_sel->pclk_sel_mask;
+	if (!clk->calc_rate)
+		return -EFAULT;
 
-	for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
-		if (clk->pclk_sel->pclk_info[i].pclk_mask == mask)
-			info = &clk->pclk_sel->pclk_info[i];
+	if (!drate)
+		return -EINVAL;
+
+	/*
+	 * This loops ends on two conditions:
+	 * - as soon as clk is found with rate greater than requested rate.
+	 * - if all clks in rate_config are smaller than requested rate.
+	 */
+	for (index = 0; index < clk->rate_config.count; index++) {
+		prev_rate = tmp;
+		tmp = clk->calc_rate(clk, index);
+		if (drate < tmp) {
+			index--;
+			break;
+		}
 	}
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	/* return if can't find suitable clock */
+	if (index < 0) {
+		index = -EINVAL;
+		*rate = 0;
+	} else if (index == clk->rate_config.count) {
+		/* program with highest clk rate possible */
+		index = clk->rate_config.count - 1;
+		*rate = tmp;
+	} else
+		*rate = prev_rate;
 
-	return info;
+	return index;
 }
 
-/*
- * Set pclk as cclk's parent and add clock sibling node to current parents
- * children list
+/**
+ * clk_round_rate - adjust a rate to the exact rate a clock can provide
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns rounded clock rate in Hz, or negative errno.
  */
-static void change_parent(struct clk *cclk, struct clk *pclk)
+long clk_round_rate(struct clk *clk, unsigned long drate)
 {
-	unsigned long flags;
+	long rate = 0;
+	int index;
+
+	/*
+	 * propagate call to parent who supports calc_rate. Similar approach is
+	 * used in clk_set_rate.
+	 */
+	if (!clk->calc_rate) {
+		u32 mult;
+		if (!clk->pclk)
+			return clk->rate;
+
+		mult = clk->div_factor ? clk->div_factor : 1;
+		return clk_round_rate(clk->pclk, mult * drate) / mult;
+	}
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	list_del(&cclk->sibling);
-	list_add(&cclk->sibling, &pclk->children);
+	index = round_rate_index(clk, drate, &rate);
+	if (index >= 0)
+		return rate;
+	else
+		return index;
+}
+EXPORT_SYMBOL(clk_round_rate);
 
-	cclk->pclk = pclk;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+/*All below functions are called with lock held */
+
+/*
+ * Calculates pll clk rate for specific value of mode, m, n and p
+ *
+ * In normal mode
+ * rate = (2 * M[15:8] * Fin)/(N * 2^P)
+ *
+ * In Dithered mode
+ * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
+ */
+unsigned long pll_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct pll_rate_tbl *tbls = clk->rate_config.tbls;
+	unsigned int mode;
+
+	mode = tbls[index].mode ? 256 : 1;
+	return (((2 * rate / 10000) * tbls[index].m) /
+			(mode * tbls[index].n * (1 << tbls[index].p))) * 10000;
 }
 
 /*
@@ -283,47 +505,146 @@ static void change_parent(struct clk *cclk, struct clk *pclk)
  * In Dithered mode
  * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
  */
-void pll1_clk_recalc(struct clk *clk)
+int pll_clk_recalc(struct clk *clk)
 {
 	struct pll_clk_config *config = clk->private_data;
 	unsigned int num = 2, den = 0, val, mode = 0;
-	unsigned long flags;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) &
-		PLL_MODE_MASK;
+	mode = (readl(config->mode_reg) >> config->masks->mode_shift) &
+		config->masks->mode_mask;
 
 	val = readl(config->cfg_reg);
 	/* calculate denominator */
-	den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK;
+	den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask;
 	den = 1 << den;
-	den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK;
+	den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask;
 
 	/* calculate numerator & denominator */
 	if (!mode) {
 		/* Normal mode */
-		num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK;
+		num *= (val >> config->masks->norm_fdbk_m_shift) &
+			config->masks->norm_fdbk_m_mask;
 	} else {
 		/* Dithered mode */
-		num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK;
+		num *= (val >> config->masks->dith_fdbk_m_shift) &
+			config->masks->dith_fdbk_m_mask;
 		den *= 256;
 	}
 
+	if (!den)
+		return -EINVAL;
+
 	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+/*
+ * Configures new clock rate of pll
+ */
+int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct pll_rate_tbl *tbls = clk->rate_config.tbls;
+	struct pll_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->mode_reg) &
+		~(config->masks->mode_mask << config->masks->mode_shift);
+	val |= (tbls[i].mode & config->masks->mode_mask) <<
+		config->masks->mode_shift;
+	writel(val, config->mode_reg);
+
+	val = readl(config->cfg_reg) &
+		~(config->masks->div_p_mask << config->masks->div_p_shift);
+	val |= (tbls[i].p & config->masks->div_p_mask) <<
+		config->masks->div_p_shift;
+	val &= ~(config->masks->div_n_mask << config->masks->div_n_shift);
+	val |= (tbls[i].n & config->masks->div_n_mask) <<
+		config->masks->div_n_shift;
+	val &= ~(config->masks->dith_fdbk_m_mask <<
+			config->masks->dith_fdbk_m_shift);
+	if (tbls[i].mode)
+		val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) <<
+			config->masks->dith_fdbk_m_shift;
+	else
+		val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) <<
+			config->masks->norm_fdbk_m_shift;
+
+	writel(val, config->cfg_reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * Calculates ahb, apb clk rate for specific value of div
+ */
+unsigned long bus_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct bus_rate_tbl *tbls = clk->rate_config.tbls;
+
+	return rate / (tbls[index].div + 1);
 }
 
 /* calculates current programmed rate of ahb or apb bus */
-void bus_clk_recalc(struct clk *clk)
+int bus_clk_recalc(struct clk *clk)
 {
 	struct bus_clk_config *config = clk->private_data;
 	unsigned int div;
-	unsigned long flags;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	div = ((readl(config->reg) >> config->shift) & config->mask) + 1;
+	div = ((readl(config->reg) >> config->masks->shift) &
+			config->masks->mask) + 1;
+
+	if (!div)
+		return -EINVAL;
+
 	clk->rate = (unsigned long)clk->pclk->rate / div;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+/* Configures new clock rate of AHB OR APB bus */
+int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct bus_rate_tbl *tbls = clk->rate_config.tbls;
+	struct bus_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->reg) &
+		~(config->masks->mask << config->masks->shift);
+	val |= (tbls[i].div & config->masks->mask) << config->masks->shift;
+	writel(val, config->reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * gives rate for different values of eq, x and y
+ *
+ * Fout from synthesizer can be given from two equations:
+ * Fout1 = (Fin * X/Y)/2		EQ1
+ * Fout2 = Fin * X/Y			EQ2
+ */
+unsigned long aux_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct aux_rate_tbl *tbls = clk->rate_config.tbls;
+	u8 eq = tbls[index].eq ? 1 : 2;
+
+	return (((rate/10000) * tbls[index].xscale) /
+			(tbls[index].yscale * eq)) * 10000;
 }
 
 /*
@@ -336,44 +657,76 @@ void bus_clk_recalc(struct clk *clk)
  *
  * Selection of eqn 1 or 2 is programmed in register
  */
-void aux_clk_recalc(struct clk *clk)
+int aux_clk_recalc(struct clk *clk)
 {
 	struct aux_clk_config *config = clk->private_data;
-	struct pclk_info *pclk_info = NULL;
 	unsigned int num = 1, den = 1, val, eqn;
-	unsigned long flags;
 
-	/* get current programmed parent */
-	pclk_info = pclk_info_get(clk);
-	if (!pclk_info) {
-		spin_lock_irqsave(&clocks_lock, flags);
-		clk->pclk = NULL;
-		clk->rate = 0;
-		spin_unlock_irqrestore(&clocks_lock, flags);
-		return;
-	}
+	val = readl(config->synth_reg);
 
-	change_parent(clk, pclk_info->pclk);
+	eqn = (val >> config->masks->eq_sel_shift) &
+		config->masks->eq_sel_mask;
+	if (eqn == config->masks->eq1_mask)
+		den *= 2;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (pclk_info->scalable) {
-		val = readl(config->synth_reg);
+	/* calculate numerator */
+	num = (val >> config->masks->xscale_sel_shift) &
+		config->masks->xscale_sel_mask;
 
-		eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK;
-		if (eqn == AUX_EQ1_SEL)
-			den *= 2;
+	/* calculate denominator */
+	den *= (val >> config->masks->yscale_sel_shift) &
+		config->masks->yscale_sel_mask;
 
-		/* calculate numerator */
-		num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK;
+	if (!den)
+		return -EINVAL;
 
-		/* calculate denominator */
-		den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK;
-		val = (((clk->pclk->rate/10000) * num) / den) * 10000;
-	} else
-		val = clk->pclk->rate;
+	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+	return 0;
+}
 
-	clk->rate = val;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
+int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct aux_rate_tbl *tbls = clk->rate_config.tbls;
+	struct aux_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->synth_reg) &
+		~(config->masks->eq_sel_mask << config->masks->eq_sel_shift);
+	val |= (tbls[i].eq & config->masks->eq_sel_mask) <<
+		config->masks->eq_sel_shift;
+	val &= ~(config->masks->xscale_sel_mask <<
+			config->masks->xscale_sel_shift);
+	val |= (tbls[i].xscale & config->masks->xscale_sel_mask) <<
+		config->masks->xscale_sel_shift;
+	val &= ~(config->masks->yscale_sel_mask <<
+			config->masks->yscale_sel_shift);
+	val |= (tbls[i].yscale & config->masks->yscale_sel_mask) <<
+		config->masks->yscale_sel_shift;
+	writel(val, config->synth_reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * Calculates gpt clk rate for different values of mscale and nscale
+ *
+ * Fout= Fin/((2 ^ (N+1)) * (M+1))
+ */
+unsigned long gpt_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
+
+	return rate / ((1 << (tbls[index].nscale + 1)) *
+			(tbls[index].mscale + 1));
 }
 
 /*
@@ -381,46 +734,142 @@ void aux_clk_recalc(struct clk *clk)
  * Fout from synthesizer can be given from below equations:
  * Fout= Fin/((2 ^ (N+1)) * (M+1))
  */
-void gpt_clk_recalc(struct clk *clk)
+int gpt_clk_recalc(struct clk *clk)
 {
-	struct aux_clk_config *config = clk->private_data;
-	struct pclk_info *pclk_info = NULL;
+	struct gpt_clk_config *config = clk->private_data;
 	unsigned int div = 1, val;
-	unsigned long flags;
 
-	pclk_info = pclk_info_get(clk);
-	if (!pclk_info) {
-		spin_lock_irqsave(&clocks_lock, flags);
-		clk->pclk = NULL;
-		clk->rate = 0;
-		spin_unlock_irqrestore(&clocks_lock, flags);
-		return;
-	}
-
-	change_parent(clk, pclk_info->pclk);
+	val = readl(config->synth_reg);
+	div += (val >> config->masks->mscale_sel_shift) &
+		config->masks->mscale_sel_mask;
+	div *= 1 << (((val >> config->masks->nscale_sel_shift) &
+				config->masks->nscale_sel_mask) + 1);
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (pclk_info->scalable) {
-		val = readl(config->synth_reg);
-		div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK;
-		div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1);
-	}
+	if (!div)
+		return -EINVAL;
 
 	clk->rate = (unsigned long)clk->pclk->rate / div;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+/* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/
+int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
+	struct gpt_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask <<
+			config->masks->mscale_sel_shift);
+	val |= (tbls[i].mscale & config->masks->mscale_sel_mask) <<
+		config->masks->mscale_sel_shift;
+	val &= ~(config->masks->nscale_sel_mask <<
+			config->masks->nscale_sel_shift);
+	val |= (tbls[i].nscale & config->masks->nscale_sel_mask) <<
+		config->masks->nscale_sel_shift;
+	writel(val, config->synth_reg);
+
+	clk->rate = rate;
+
+	return 0;
 }
 
 /*
- * Used for clocks that always have same value as the parent clock divided by a
+ * Calculates clcd clk rate for different values of div
+ *
+ * Fout from synthesizer can be given from below equation:
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ *	0-13 (fractional part)
+ *	14-16 (integer part)
+ * To calculate Fout we left shift val by 14 bits and divide Fin by
+ * complete div (including fractional part) and then right shift the
+ * result by 14 places.
+ */
+unsigned long clcd_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
+
+	rate /= 1000;
+	rate <<= 12;
+	rate /= (2 * tbls[index].div);
+	rate >>= 12;
+	rate *= 1000;
+
+	return rate;
+}
+
+/*
+ * calculates current programmed rate of clcd synthesizer
+ * Fout from synthesizer can be given from below equation:
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ *	0-13 (fractional part)
+ *	14-16 (integer part)
+ * To calculate Fout we left shift val by 14 bits and divide Fin by
+ * complete div (including fractional part) and then right shift the
+ * result by 14 places.
+ */
+int clcd_clk_recalc(struct clk *clk)
+{
+	struct clcd_clk_config *config = clk->private_data;
+	unsigned int div = 1;
+	unsigned long prate;
+	unsigned int val;
+
+	val = readl(config->synth_reg);
+	div = (val >> config->masks->div_factor_shift) &
+		config->masks->div_factor_mask;
+
+	if (!div)
+		return -EINVAL;
+
+	prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
+
+	clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
+	clk->rate *= 1000;
+	return 0;
+}
+
+/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
+int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
+	struct clcd_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->synth_reg) & ~(config->masks->div_factor_mask <<
+			config->masks->div_factor_shift);
+	val |= (tbls[i].div & config->masks->div_factor_mask) <<
+		config->masks->div_factor_shift;
+	writel(val, config->synth_reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * Used for clocks that always have value as the parent clock divided by a
  * fixed divisor
  */
-void follow_parent(struct clk *clk)
+int follow_parent(struct clk *clk)
 {
-	unsigned long flags;
+	unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	clk->rate = clk->pclk->rate;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	clk->rate = clk->pclk->rate/div_factor;
+	return 0;
 }
 
 /**
@@ -431,5 +880,124 @@ void follow_parent(struct clk *clk)
  */
 void recalc_root_clocks(void)
 {
-	propagate_rate(&root_clks);
+	struct clk *pclk;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	list_for_each_entry(pclk, &root_clks, sibling) {
+		if (pclk->recalc) {
+			ret = pclk->recalc(pclk);
+			/*
+			 * recalc will return error if clk out is not programmed
+			 * In this case configure default clock.
+			 */
+			if (ret && pclk->set_rate)
+				pclk->set_rate(pclk, 0);
+		}
+		propagate_rate(pclk, 1);
+		/* Enable clks enabled on init, in software view */
+		if (pclk->flags & ENABLED_ON_INIT)
+			do_clk_enable(pclk);
+	}
+	spin_unlock_irqrestore(&clocks_lock, flags);
+}
+
+#ifdef CONFIG_DEBUG_FS
+/*
+ *	debugfs support to trace clock tree hierarchy and attributes
+ */
+static struct dentry *clk_debugfs_root;
+static int clk_debugfs_register_one(struct clk *c)
+{
+	int err;
+	struct dentry *d, *child;
+	struct clk *pa = c->pclk;
+	char s[255];
+	char *p = s;
+
+	if (c) {
+		if (c->cl->con_id)
+			p += sprintf(p, "%s", c->cl->con_id);
+		if (c->cl->dev_id)
+			p += sprintf(p, "%s", c->cl->dev_id);
+	}
+	d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+	c->dent = d;
+
+	d = debugfs_create_u32("usage_count", S_IRUGO, c->dent,
+			(u32 *)&c->usage_count);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	return 0;
+
+err_out:
+	d = c->dent;
+	list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(c->dent);
+	return err;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->pclk;
+
+	if (pa && !pa->dent) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (!c->dent) {
+		err = clk_debugfs_register_one(c);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+	struct clk *c;
+	struct dentry *d;
+	int err;
+
+	d = debugfs_create_dir("clock", NULL);
+	if (!d)
+		return -ENOMEM;
+	clk_debugfs_root = d;
+
+	list_for_each_entry(c, &clocks, node) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+err_out:
+	debugfs_remove_recursive(clk_debugfs_root);
+	return err;
+}
+late_initcall(clk_debugfs_init);
+
+static int clk_debugfs_reparent(struct clk *c)
+{
+	debugfs_remove(c->dent);
+	return clk_debugfs_register_one(c);
 }
+#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/arm/plat-spear/include/plat/clock.h b/arch/arm/plat-spear/include/plat/clock.h
index 2572260..2ae6606 100644
--- a/arch/arm/plat-spear/include/plat/clock.h
+++ b/arch/arm/plat-spear/include/plat/clock.h
@@ -21,6 +21,7 @@
 /* clk structure flags */
 #define	ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
 #define	RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */
+#define	ENABLED_ON_INIT		(1 << 2) /* clocks enabled at init */
 
 /**
  * struct clkops - clock operations
@@ -35,13 +36,11 @@ struct clkops {
 /**
  * struct pclk_info - parents info
  * @pclk: pointer to parent clk
- * @pclk_mask: value to be written for selecting this parent
- * @scalable: Is parent scalable (1 - YES, 0 - NO)
+ * @pclk_val: value to be written for selecting this parent
  */
 struct pclk_info {
 	struct clk *pclk;
-	u8 pclk_mask;
-	u8 scalable;
+	u8 pclk_val;
 };
 
 /**
@@ -54,11 +53,23 @@ struct pclk_info {
 struct pclk_sel {
 	struct pclk_info *pclk_info;
 	u8 pclk_count;
-	unsigned int *pclk_sel_reg;
+	void __iomem *pclk_sel_reg;
 	unsigned int pclk_sel_mask;
 };
 
 /**
+ * struct rate_config - clk rate configurations
+ * @tbls: array of device specific clk rate tables, in ascending order of rates
+ * @count: size of tbls array
+ * @default_index: default setting when originally disabled
+ */
+struct rate_config {
+	void *tbls;
+	u8 count;
+	u8 default_index;
+};
+
+/**
  * struct clk - clock structure
  * @usage_count: num of users who enabled this clock
  * @flags: flags for clock properties
@@ -67,21 +78,32 @@ struct pclk_sel {
  * @en_reg_bit: clk enable/disable bit
  * @ops: clk enable/disable ops - generic_clkops selected if NULL
  * @recalc: pointer to clock rate recalculate function
+ * @set_rate: pointer to clock set rate function
+ * @calc_rate: pointer to clock get rate function for index
+ * @rate_config: rate configuration information, used by set_rate
+ * @div_factor: division factor to parent clock.
  * @pclk: current parent clk
  * @pclk_sel: pointer to parent selection structure
  * @pclk_sel_shift: register shift for selecting parent of this clock
  * @children: list for childrens or this clock
  * @sibling: node for list of clocks having same parents
  * @private_data: clock specific private data
+ * @node: list to maintain clocks linearly
+ * @cl: clocklook up assoicated with this clock
+ * @dent: object for debugfs
  */
 struct clk {
 	unsigned int usage_count;
 	unsigned int flags;
 	unsigned long rate;
-	unsigned int *en_reg;
+	void __iomem *en_reg;
 	u8 en_reg_bit;
 	const struct clkops *ops;
-	void (*recalc) (struct clk *);
+	int (*recalc) (struct clk *);
+	int (*set_rate) (struct clk *, unsigned long rate);
+	unsigned long (*calc_rate)(struct clk *, int index);
+	struct rate_config rate_config;
+	unsigned int div_factor;
 
 	struct clk *pclk;
 	struct pclk_sel *pclk_sel;
@@ -90,37 +112,137 @@ struct clk {
 	struct list_head children;
 	struct list_head sibling;
 	void *private_data;
+#ifdef CONFIG_DEBUG_FS
+	struct list_head node;
+	struct clk_lookup *cl;
+	struct dentry *dent;
+#endif
 };
 
 /* pll configuration structure */
+struct pll_clk_masks {
+	u32 mode_mask;
+	u32 mode_shift;
+
+	u32 norm_fdbk_m_mask;
+	u32 norm_fdbk_m_shift;
+	u32 dith_fdbk_m_mask;
+	u32 dith_fdbk_m_shift;
+	u32 div_p_mask;
+	u32 div_p_shift;
+	u32 div_n_mask;
+	u32 div_n_shift;
+};
+
 struct pll_clk_config {
-	unsigned int *mode_reg;
-	unsigned int *cfg_reg;
+	void __iomem *mode_reg;
+	void __iomem *cfg_reg;
+	struct pll_clk_masks *masks;
+};
+
+/* pll clk rate config structure */
+struct pll_rate_tbl {
+	u8 mode;
+	u16 m;
+	u8 n;
+	u8 p;
 };
 
 /* ahb and apb bus configuration structure */
+struct bus_clk_masks {
+	u32 mask;
+	u32 shift;
+};
+
 struct bus_clk_config {
-	unsigned int *reg;
-	unsigned int mask;
-	unsigned int shift;
+	void __iomem *reg;
+	struct bus_clk_masks *masks;
+};
+
+/* ahb and apb clk bus rate config structure */
+struct bus_rate_tbl {
+	u8 div;
+};
+
+/* Aux clk configuration structure: applicable to UART and FIRDA */
+struct aux_clk_masks {
+	u32 eq_sel_mask;
+	u32 eq_sel_shift;
+	u32 eq1_mask;
+	u32 eq2_mask;
+	u32 xscale_sel_mask;
+	u32 xscale_sel_shift;
+	u32 yscale_sel_mask;
+	u32 yscale_sel_shift;
 };
 
-/*
- * Aux clk configuration structure: applicable to GPT, UART and FIRDA
- */
 struct aux_clk_config {
-	unsigned int *synth_reg;
+	void __iomem *synth_reg;
+	struct aux_clk_masks *masks;
+};
+
+/* aux clk rate config structure */
+struct aux_rate_tbl {
+	u16 xscale;
+	u16 yscale;
+	u8 eq;
+};
+
+/* GPT clk configuration structure */
+struct gpt_clk_masks {
+	u32 mscale_sel_mask;
+	u32 mscale_sel_shift;
+	u32 nscale_sel_mask;
+	u32 nscale_sel_shift;
+};
+
+struct gpt_clk_config {
+	void __iomem *synth_reg;
+	struct gpt_clk_masks *masks;
+};
+
+/* gpt clk rate config structure */
+struct gpt_rate_tbl {
+	u16 mscale;
+	u16 nscale;
+};
+
+/* clcd clk configuration structure */
+struct clcd_synth_masks {
+	u32 div_factor_mask;
+	u32 div_factor_shift;
+};
+
+struct clcd_clk_config {
+	void __iomem *synth_reg;
+	struct clcd_synth_masks *masks;
+};
+
+/* clcd clk rate config structure */
+struct clcd_rate_tbl {
+	u16 div;
 };
 
 /* platform specific clock functions */
 void clk_register(struct clk_lookup *cl);
 void recalc_root_clocks(void);
 
-/* clock recalc functions */
-void follow_parent(struct clk *clk);
-void pll1_clk_recalc(struct clk *clk);
-void bus_clk_recalc(struct clk *clk);
-void gpt_clk_recalc(struct clk *clk);
-void aux_clk_recalc(struct clk *clk);
+/* clock recalc & set rate functions */
+int follow_parent(struct clk *clk);
+unsigned long pll_calc_rate(struct clk *clk, int index);
+int pll_clk_recalc(struct clk *clk);
+int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long bus_calc_rate(struct clk *clk, int index);
+int bus_clk_recalc(struct clk *clk);
+int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long gpt_calc_rate(struct clk *clk, int index);
+int gpt_clk_recalc(struct clk *clk);
+int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long aux_calc_rate(struct clk *clk, int index);
+int aux_clk_recalc(struct clk *clk);
+int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long clcd_calc_rate(struct clk *clk, int index);
+int clcd_clk_recalc(struct clk *clk);
+int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 
 #endif /* __PLAT_CLOCK_H */
diff --git a/arch/arm/plat-spear/include/plat/debug-macro.S b/arch/arm/plat-spear/include/plat/debug-macro.S
index e91270e..8501bbf 100644
--- a/arch/arm/plat-spear/include/plat/debug-macro.S
+++ b/arch/arm/plat-spear/include/plat/debug-macro.S
@@ -12,7 +12,7 @@
  */
 
 #include <linux/amba/serial.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 		.macro	addruart, rp, rv
 		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
diff --git a/arch/arm/plat-spear/include/plat/hardware.h b/arch/arm/plat-spear/include/plat/hardware.h
new file mode 100644
index 0000000..66d6772
--- /dev/null
+++ b/arch/arm/plat-spear/include/plat/hardware.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/plat-spear/include/plat/hardware.h
+ *
+ * Hardware definitions for SPEAr
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Viresh Kumar<viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_HARDWARE_H
+#define __PLAT_HARDWARE_H
+
+#ifndef __ASSEMBLY__
+#define IOMEM(x)	((void __iomem __force *)(x))
+#else
+#define IOMEM(x)	(x)
+#endif
+
+#endif /* __PLAT_HARDWARE_H */
diff --git a/arch/arm/plat-spear/include/plat/memory.h b/arch/arm/plat-spear/include/plat/memory.h
index 27a4aba..7e3599e 100644
--- a/arch/arm/plat-spear/include/plat/memory.h
+++ b/arch/arm/plat-spear/include/plat/memory.h
@@ -15,6 +15,6 @@
 #define __PLAT_MEMORY_H
 
 /* Physical DRAM offset */
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif /* __PLAT_MEMORY_H */
diff --git a/arch/arm/plat-spear/include/plat/system.h b/arch/arm/plat-spear/include/plat/system.h
index 55a4e40..a235fa0 100644
--- a/arch/arm/plat-spear/include/plat/system.h
+++ b/arch/arm/plat-spear/include/plat/system.h
@@ -14,9 +14,9 @@
 #ifndef __PLAT_SYSTEM_H
 #define __PLAT_SYSTEM_H
 
-#include <asm/hardware/sp810.h>
 #include <linux/io.h>
-#include <mach/spear.h>
+#include <asm/hardware/sp810.h>
+#include <mach/hardware.h>
 
 static inline void arch_idle(void)
 {
diff --git a/arch/arm/plat-spear/include/plat/uncompress.h b/arch/arm/plat-spear/include/plat/uncompress.h
index 6dd455b..1bf8452 100644
--- a/arch/arm/plat-spear/include/plat/uncompress.h
+++ b/arch/arm/plat-spear/include/plat/uncompress.h
@@ -13,7 +13,7 @@
 
 #include <linux/io.h>
 #include <linux/amba/serial.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 #ifndef __PLAT_UNCOMPRESS_H
 #define __PLAT_UNCOMPRESS_H
diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c
index 839c88d..dbb6e4f 100644
--- a/arch/arm/plat-spear/time.c
+++ b/arch/arm/plat-spear/time.c
@@ -1,7 +1,7 @@
 /*
  * arch/arm/plat-spear/time.c
  *
- * Copyright (C) 2009 ST Microelectronics
+ * Copyright (C) 2010 ST Microelectronics
  * Shiraz Hashim<shiraz.hashim@st.com>
  *
  * This file is licensed under the terms of the GNU General Public
@@ -20,10 +20,9 @@
 #include <linux/time.h>
 #include <linux/irq.h>
 #include <asm/mach/time.h>
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <mach/spear.h>
 #include <mach/generic.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
 
 /*
  * We would use TIMER0 and TIMER1 as clockevent and clocksource.
@@ -211,7 +210,7 @@ static void __init spear_clockevent_init(void)
 
 void __init spear_setup_timer(void)
 {
-	struct clk *pll3_clk;
+	int ret;
 
 	if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) {
 		pr_err("%s:cannot get IO addr\n", __func__);
@@ -230,26 +229,21 @@ void __init spear_setup_timer(void)
 		goto err_iomap;
 	}
 
-	pll3_clk = clk_get(NULL, "pll3_48m_clk");
-	if (!pll3_clk) {
-		pr_err("%s:couldn't get PLL3 as parent for gpt\n", __func__);
-		goto err_iomap;
+	ret = clk_enable(gpt_clk);
+	if (ret < 0) {
+		pr_err("%s:couldn't enable gpt clock\n", __func__);
+		goto err_clk;
 	}
 
-	clk_set_parent(gpt_clk, pll3_clk);
-
 	spear_clockevent_init();
 	spear_clocksource_init();
 
 	return;
 
+err_clk:
+	clk_put(gpt_clk);
 err_iomap:
 	iounmap(gpt_base);
-
 err_mem:
 	release_mem_region(SPEAR_GPT0_BASE, SZ_1K);
 }
-
-struct sys_timer spear_sys_timer = {
-	.init = spear_setup_timer,
-};
diff --git a/arch/arm/plat-stmp3xxx/include/mach/memory.h b/arch/arm/plat-stmp3xxx/include/mach/memory.h
index 7b875a0..61fa548 100644
--- a/arch/arm/plat-stmp3xxx/include/mach/memory.h
+++ b/arch/arm/plat-stmp3xxx/include/mach/memory.h
@@ -17,6 +17,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x40000000)
+#define PLAT_PHYS_OFFSET	UL(0x40000000)
 
 #endif
diff --git a/arch/arm/plat-tcc/include/mach/memory.h b/arch/arm/plat-tcc/include/mach/memory.h
index cd91ba8..28a6e0c 100644
--- a/arch/arm/plat-tcc/include/mach/memory.h
+++ b/arch/arm/plat-tcc/include/mach/memory.h
@@ -13,6 +13,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 
 #endif
diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile
index 39f6d8e..6de73aa 100644
--- a/arch/arm/vfp/Makefile
+++ b/arch/arm/vfp/Makefile
@@ -4,8 +4,8 @@
 # Copyright (C) 2001 ARM Limited
 #
 
-# EXTRA_CFLAGS := -DDEBUG
-# EXTRA_AFLAGS := -DDEBUG
+# ccflags-y := -DDEBUG
+# asflags-y := -DDEBUG
 
 KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
 LDFLAGS		+=--no-warn-mismatch
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 0797cb5..bbf3da0 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -153,7 +153,7 @@ static struct notifier_block vfp_notifier_block = {
  * Raise a SIGFPE for the current process.
  * sicode describes the signal being raised.
  */
-void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
+static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
 {
 	siginfo_t info;
 
@@ -489,8 +489,11 @@ void vfp_flush_hwstate(struct thread_info *thread)
 
 /*
  * VFP hardware can lose all context when a CPU goes offline.
- * Safely clear our held state when a CPU has been killed, and
- * re-enable access to VFP when the CPU comes back online.
+ * As we will be running in SMP mode with CPU hotplug, we will save the
+ * hardware state at every thread switch.  We clear our held state when
+ * a CPU has been killed, indicating that the VFP hardware doesn't contain
+ * a threads VFP state.  When a CPU starts up, we re-enable access to the
+ * VFP hardware.
  *
  * Both CPU_DYING and CPU_STARTING are called on the CPU which
  * is being offlined/onlined.
diff --git a/arch/avr32/include/asm/types.h b/arch/avr32/include/asm/types.h
index 9cefda6..72667a3 100644
--- a/arch/avr32/include/asm/types.h
+++ b/arch/avr32/include/asm/types.h
@@ -23,14 +23,6 @@ typedef unsigned short umode_t;
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c
index e67c999..bfc9d07 100644
--- a/arch/avr32/mach-at32ap/at32ap700x.c
+++ b/arch/avr32/mach-at32ap/at32ap700x.c
@@ -2048,6 +2048,11 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,
 		rx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT;
 		rx_dws->cfg_hi = DWC_CFGH_SRC_PER(3);
 		rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
+		rx_dws->src_master = 0;
+		rx_dws->dst_master = 1;
+		rx_dws->src_msize = DW_DMA_MSIZE_1;
+		rx_dws->dst_msize = DW_DMA_MSIZE_1;
+		rx_dws->fc = DW_DMA_FC_D_P2M;
 	}
 
 	/* Check if DMA slave interface for playback should be configured. */
@@ -2056,6 +2061,11 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data,
 		tx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT;
 		tx_dws->cfg_hi = DWC_CFGH_DST_PER(4);
 		tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
+		tx_dws->src_master = 0;
+		tx_dws->dst_master = 1;
+		tx_dws->src_msize = DW_DMA_MSIZE_1;
+		tx_dws->dst_msize = DW_DMA_MSIZE_1;
+		tx_dws->fc = DW_DMA_FC_D_M2P;
 	}
 
 	if (platform_device_add_data(pdev, data,
@@ -2128,6 +2138,11 @@ at32_add_device_abdac(unsigned int id, struct atmel_abdac_pdata *data)
 	dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
 	dws->cfg_hi = DWC_CFGH_DST_PER(2);
 	dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
+	dws->src_master = 0;
+	dws->dst_master = 1;
+	dws->src_msize = DW_DMA_MSIZE_1;
+	dws->dst_msize = DW_DMA_MSIZE_1;
+	dws->fc = DW_DMA_FC_D_M2P;
 
 	if (platform_device_add_data(pdev, data,
 				sizeof(struct atmel_abdac_pdata)))
diff --git a/arch/avr32/mm/cache.c b/arch/avr32/mm/cache.c
index 24a74d1..6a46ecd 100644
--- a/arch/avr32/mm/cache.c
+++ b/arch/avr32/mm/cache.c
@@ -113,7 +113,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
 }
 
 /*
- * This one is called from do_no_page(), do_swap_page() and install_page().
+ * This one is called from __do_fault() and do_swap_page().
  */
 void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index c09577d..01615d4 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -33,6 +33,7 @@ config BLACKFIN
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select IRQ_PER_CPU if SMP
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config GENERIC_CSUM
 	def_bool y
@@ -690,13 +691,13 @@ endmenu
 
 
 menu "Blackfin Kernel Optimizations"
-	depends on !SMP
 
 comment "Memory Optimizations"
 
 config I_ENTRY_L1
 	bool "Locate interrupt entry code in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, interrupt entry code (STORE/RESTORE CONTEXT) is linked
 	  into L1 instruction memory. (less latency)
@@ -704,6 +705,7 @@ config I_ENTRY_L1
 config EXCPT_IRQ_SYSC_L1
 	bool "Locate entire ASM lowlevel exception / interrupt - Syscall and CPLB handler code in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the entire ASM lowlevel exception and interrupt entry code
 	  (STORE/RESTORE CONTEXT) is linked into L1 instruction memory.
@@ -712,6 +714,7 @@ config EXCPT_IRQ_SYSC_L1
 config DO_IRQ_L1
 	bool "Locate frequently called do_irq dispatcher function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called do_irq dispatcher function is linked
 	  into L1 instruction memory. (less latency)
@@ -719,6 +722,7 @@ config DO_IRQ_L1
 config CORE_TIMER_IRQ_L1
 	bool "Locate frequently called timer_interrupt() function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called timer_interrupt() function is linked
 	  into L1 instruction memory. (less latency)
@@ -726,6 +730,7 @@ config CORE_TIMER_IRQ_L1
 config IDLE_L1
 	bool "Locate frequently idle function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called idle function is linked
 	  into L1 instruction memory. (less latency)
@@ -733,6 +738,7 @@ config IDLE_L1
 config SCHEDULE_L1
 	bool "Locate kernel schedule function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called kernel schedule is linked
 	  into L1 instruction memory. (less latency)
@@ -740,6 +746,7 @@ config SCHEDULE_L1
 config ARITHMETIC_OPS_L1
 	bool "Locate kernel owned arithmetic functions in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, arithmetic functions are linked
 	  into L1 instruction memory. (less latency)
@@ -747,6 +754,7 @@ config ARITHMETIC_OPS_L1
 config ACCESS_OK_L1
 	bool "Locate access_ok function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the access_ok function is linked
 	  into L1 instruction memory. (less latency)
@@ -754,6 +762,7 @@ config ACCESS_OK_L1
 config MEMSET_L1
 	bool "Locate memset function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the memset function is linked
 	  into L1 instruction memory. (less latency)
@@ -761,6 +770,7 @@ config MEMSET_L1
 config MEMCPY_L1
 	bool "Locate memcpy function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the memcpy function is linked
 	  into L1 instruction memory. (less latency)
@@ -768,6 +778,7 @@ config MEMCPY_L1
 config STRCMP_L1
 	bool "locate strcmp function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strcmp function is linked
 	  into L1 instruction memory (less latency).
@@ -775,6 +786,7 @@ config STRCMP_L1
 config STRNCMP_L1
 	bool "locate strncmp function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strncmp function is linked
 	  into L1 instruction memory (less latency).
@@ -782,6 +794,7 @@ config STRNCMP_L1
 config STRCPY_L1
 	bool "locate strcpy function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strcpy function is linked
 	  into L1 instruction memory (less latency).
@@ -789,6 +802,7 @@ config STRCPY_L1
 config STRNCPY_L1
 	bool "locate strncpy function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strncpy function is linked
 	  into L1 instruction memory (less latency).
@@ -796,6 +810,7 @@ config STRNCPY_L1
 config SYS_BFIN_SPINLOCK_L1
 	bool "Locate sys_bfin_spinlock function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, sys_bfin_spinlock function is linked
 	  into L1 instruction memory. (less latency)
@@ -803,6 +818,7 @@ config SYS_BFIN_SPINLOCK_L1
 config IP_CHECKSUM_L1
 	bool "Locate IP Checksum function in L1 Memory"
 	default n
+	depends on !SMP
 	help
 	  If enabled, the IP Checksum function is linked
 	  into L1 instruction memory. (less latency)
@@ -811,7 +827,7 @@ config CACHELINE_ALIGNED_L1
 	bool "Locate cacheline_aligned data to L1 Data Memory"
 	default y if !BF54x
 	default n if BF54x
-	depends on !BF531
+	depends on !SMP && !BF531
 	help
 	  If enabled, cacheline_aligned data is linked
 	  into L1 data memory. (less latency)
@@ -819,7 +835,7 @@ config CACHELINE_ALIGNED_L1
 config SYSCALL_TAB_L1
 	bool "Locate Syscall Table L1 Data Memory"
 	default n
-	depends on !BF531
+	depends on !SMP && !BF531
 	help
 	  If enabled, the Syscall LUT is linked
 	  into L1 data memory. (less latency)
@@ -827,16 +843,16 @@ config SYSCALL_TAB_L1
 config CPLB_SWITCH_TAB_L1
 	bool "Locate CPLB Switch Tables L1 Data Memory"
 	default n
-	depends on !BF531
+	depends on !SMP && !BF531
 	help
 	  If enabled, the CPLB Switch Tables are linked
 	  into L1 data memory. (less latency)
 
-config CACHE_FLUSH_L1
-	bool "Locate cache flush funcs in L1 Inst Memory"
+config ICACHE_FLUSH_L1
+	bool "Locate icache flush funcs in L1 Inst Memory"
 	default y
 	help
-	  If enabled, the Blackfin cache flushing functions are linked
+	  If enabled, the Blackfin icache flushing functions are linked
 	  into L1 instruction memory.
 
 	  Note that this might be required to address anomalies, but
@@ -844,9 +860,18 @@ config CACHE_FLUSH_L1
 	  If you are using a processor affected by an anomaly, the build
 	  system will double check for you and prevent it.
 
+config DCACHE_FLUSH_L1
+	bool "Locate dcache flush funcs in L1 Inst Memory"
+	default y
+	depends on !SMP
+	help
+	  If enabled, the Blackfin dcache flushing functions are linked
+	  into L1 instruction memory.
+
 config APP_STACK_L1
 	bool "Support locating application stack in L1 Scratch Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled the application stack can be located in L1
 	  scratch memory (less latency).
@@ -856,7 +881,7 @@ config APP_STACK_L1
 config EXCEPTION_L1_SCRATCH
 	bool "Locate exception stack in L1 Scratch Memory"
 	default n
-	depends on !APP_STACK_L1
+	depends on !SMP && !APP_STACK_L1
 	help
 	  Whenever an exception occurs, use the L1 Scratch memory for
 	  stack storage.  You cannot place the stacks of FLAT binaries
@@ -868,6 +893,7 @@ comment "Speed Optimizations"
 config BFIN_INS_LOWOVERHEAD
 	bool "ins[bwl] low overhead, higher interrupt latency"
 	default y
+	depends on !SMP
 	help
 	  Reads on the Blackfin are speculative. In Blackfin terms, this means
 	  they can be interrupted at any time (even after they have been issued
diff --git a/arch/blackfin/configs/BF518F-EZBRD_defconfig b/arch/blackfin/configs/BF518F-EZBRD_defconfig
index db8d38a..5edcb58 100644
--- a/arch/blackfin/configs/BF518F-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF518F-EZBRD_defconfig
@@ -115,6 +115,7 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 3e50d78..2e54957 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -153,6 +153,7 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff --git a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
index 023ff0d..95cf2ba 100644
--- a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
@@ -183,5 +183,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 4e5a121..8be8e33 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -175,5 +175,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF533-EZKIT_defconfig b/arch/blackfin/configs/BF533-EZKIT_defconfig
index 9f8fc84..a7eb54b 100644
--- a/arch/blackfin/configs/BF533-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF533-EZKIT_defconfig
@@ -108,5 +108,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF533-STAMP_defconfig b/arch/blackfin/configs/BF533-STAMP_defconfig
index ccc432b..0aafde6 100644
--- a/arch/blackfin/configs/BF533-STAMP_defconfig
+++ b/arch/blackfin/configs/BF533-STAMP_defconfig
@@ -122,5 +122,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF537-STAMP_defconfig b/arch/blackfin/configs/BF537-STAMP_defconfig
index 5666954..c9077fb 100644
--- a/arch/blackfin/configs/BF537-STAMP_defconfig
+++ b/arch/blackfin/configs/BF537-STAMP_defconfig
@@ -133,5 +133,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF538-EZKIT_defconfig b/arch/blackfin/configs/BF538-EZKIT_defconfig
index ac22124..6883803 100644
--- a/arch/blackfin/configs/BF538-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF538-EZKIT_defconfig
@@ -131,5 +131,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index 944404b..56151b5 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -205,5 +205,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig b/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
index 7e67ba3..f5ed34e 100644
--- a/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
@@ -109,5 +109,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/configs/BF561-EZKIT_defconfig b/arch/blackfin/configs/BF561-EZKIT_defconfig
index 141e593..1c0a82a 100644
--- a/arch/blackfin/configs/BF561-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF561-EZKIT_defconfig
@@ -111,5 +111,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/blackfin/include/asm/def_LPBlackfin.h b/arch/blackfin/include/asm/def_LPBlackfin.h
index e3f0f4c..7600fe0 100644
--- a/arch/blackfin/include/asm/def_LPBlackfin.h
+++ b/arch/blackfin/include/asm/def_LPBlackfin.h
@@ -58,14 +58,26 @@
     ({ BUG(); 0; }); \
 })
 #define bfin_write(addr, val) \
-({ \
+do { \
 	switch (sizeof(*(addr))) { \
 	case 1: bfin_write8(addr, val);  break; \
 	case 2: bfin_write16(addr, val); break; \
 	case 4: bfin_write32(addr, val); break; \
 	default: BUG(); \
 	} \
-})
+} while (0)
+
+#define bfin_write_or(addr, bits) \
+do { \
+	void *__addr = (void *)(addr); \
+	bfin_write(__addr, bfin_read(__addr) | (bits)); \
+} while (0)
+
+#define bfin_write_and(addr, bits) \
+do { \
+	void *__addr = (void *)(addr); \
+	bfin_write(__addr, bfin_read(__addr) & (bits)); \
+} while (0)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/blackfin/include/asm/dpmc.h b/arch/blackfin/include/asm/dpmc.h
index 3047120..edf2a2a 100644
--- a/arch/blackfin/include/asm/dpmc.h
+++ b/arch/blackfin/include/asm/dpmc.h
@@ -125,6 +125,9 @@ void unset_dram_srfs(void);
 
 #define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
 
+#ifdef CONFIG_CPU_FREQ
+#define CPUFREQ_CPU 0
+#endif
 struct bfin_dpmc_platform_data {
 	const unsigned int *tuple_tab;
 	unsigned short tabsize;
diff --git a/arch/blackfin/include/asm/ipipe.h b/arch/blackfin/include/asm/ipipe.h
index 40f94a7..9e0cc0e 100644
--- a/arch/blackfin/include/asm/ipipe.h
+++ b/arch/blackfin/include/asm/ipipe.h
@@ -34,11 +34,12 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 #include <asm/traps.h>
+#include <asm/bitsperlong.h>
 
-#define IPIPE_ARCH_STRING     "1.12-00"
+#define IPIPE_ARCH_STRING     "1.16-01"
 #define IPIPE_MAJOR_NUMBER    1
-#define IPIPE_MINOR_NUMBER    12
-#define IPIPE_PATCH_NUMBER    0
+#define IPIPE_MINOR_NUMBER    16
+#define IPIPE_PATCH_NUMBER    1
 
 #ifdef CONFIG_SMP
 #error "I-pipe/blackfin: SMP not implemented"
@@ -55,25 +56,19 @@ do {						\
 #define task_hijacked(p)						\
 	({								\
 		int __x__ = __ipipe_root_domain_p;			\
-		__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
 		if (__x__)						\
-			hard_local_irq_enable();				\
+			hard_local_irq_enable();			\
 		!__x__;							\
 	})
 
 struct ipipe_domain;
 
 struct ipipe_sysinfo {
-
-	int ncpus;		/* Number of CPUs on board */
-	u64 cpufreq;		/* CPU frequency (in Hz) */
-
-	/* Arch-dependent block */
-
-	struct {
-		unsigned tmirq;	/* Timer tick IRQ */
-		u64 tmfreq;	/* Timer frequency */
-	} archdep;
+	int sys_nr_cpus;	/* Number of CPUs on board */
+	int sys_hrtimer_irq;	/* hrtimer device IRQ */
+	u64 sys_hrtimer_freq;	/* hrtimer device frequency */
+	u64 sys_hrclock_freq;	/* hrclock device frequency */
+	u64 sys_cpu_freq;	/* CPU frequency (Hz) */
 };
 
 #define ipipe_read_tsc(t)					\
@@ -115,9 +110,19 @@ void __ipipe_enable_irqdesc(struct ipipe_domain *ipd,
 void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
 			     unsigned irq);
 
-#define __ipipe_enable_irq(irq)		(irq_desc[irq].chip->unmask(irq))
+#define __ipipe_enable_irq(irq)						\
+	do {								\
+		struct irq_desc *desc = irq_to_desc(irq);		\
+		struct irq_chip *chip = get_irq_desc_chip(desc);	\
+		chip->irq_unmask(&desc->irq_data);			\
+	} while (0)
 
-#define __ipipe_disable_irq(irq)	(irq_desc[irq].chip->mask(irq))
+#define __ipipe_disable_irq(irq)					\
+	do {								\
+		struct irq_desc *desc = irq_to_desc(irq);		\
+		struct irq_chip *chip = get_irq_desc_chip(desc);	\
+		chip->irq_mask(&desc->irq_data);			\
+	} while (0)
 
 static inline int __ipipe_check_tickdev(const char *devname)
 {
@@ -128,12 +133,11 @@ void __ipipe_enable_pipeline(void);
 
 #define __ipipe_hook_critical_ipi(ipd) do { } while (0)
 
-#define __ipipe_sync_pipeline  ___ipipe_sync_pipeline
-void ___ipipe_sync_pipeline(unsigned long syncmask);
+void ___ipipe_sync_pipeline(void);
 
 void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
 
-int __ipipe_get_irq_priority(unsigned irq);
+int __ipipe_get_irq_priority(unsigned int irq);
 
 void __ipipe_serial_debug(const char *fmt, ...);
 
@@ -152,7 +156,10 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
 	return ffs(ul) - 1;
 }
 
-#define __ipipe_run_irqtail()  /* Must be a macro */			\
+#define __ipipe_do_root_xirq(ipd, irq)					\
+	((ipd)->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)))
+
+#define __ipipe_run_irqtail(irq)  /* Must be a macro */			\
 	do {								\
 		unsigned long __pending;				\
 		CSYNC();						\
@@ -164,42 +171,8 @@ static inline unsigned long __ipipe_ffnz(unsigned long ul)
 		}							\
 	} while (0)
 
-#define __ipipe_run_isr(ipd, irq)					\
-	do {								\
-		if (!__ipipe_pipeline_head_p(ipd))			\
-			hard_local_irq_enable();				\
-		if (ipd == ipipe_root_domain) {				\
-			if (unlikely(ipipe_virtual_irq_p(irq))) {	\
-				irq_enter();				\
-				ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-				irq_exit();				\
-			} else 						\
-				ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
-		} else {						\
-			__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-			ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-			/* Attempt to exit the outer interrupt level before \
-			 * starting the deferred IRQ processing. */	\
-			__ipipe_run_irqtail();				\
-			__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-		}							\
-		hard_local_irq_disable();					\
-	} while (0)
-
 #define __ipipe_syscall_watched_p(p, sc)	\
-	(((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls)
-
-void ipipe_init_irq_threads(void);
-
-int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
-
-#ifdef CONFIG_TICKSOURCE_CORETMR
-#define IRQ_SYSTMR		IRQ_CORETMR
-#define IRQ_PRIOTMR		IRQ_CORETMR
-#else
-#define IRQ_SYSTMR		IRQ_TIMER0
-#define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
-#endif
+	(ipipe_notifier_enabled_p(p) || (unsigned long)sc >= NR_syscalls)
 
 #ifdef CONFIG_BF561
 #define bfin_write_TIMER_DISABLE(val)	bfin_write_TMRS8_DISABLE(val)
@@ -219,11 +192,11 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
 
 #define task_hijacked(p)		0
 #define ipipe_trap_notify(t, r)  	0
+#define __ipipe_root_tick_p(regs)	1
 
-#define ipipe_init_irq_threads()		do { } while (0)
-#define ipipe_start_irq_thread(irq, desc)	0
+#endif /* !CONFIG_IPIPE */
 
-#ifndef CONFIG_TICKSOURCE_GPTMR0
+#ifdef CONFIG_TICKSOURCE_CORETMR
 #define IRQ_SYSTMR		IRQ_CORETMR
 #define IRQ_PRIOTMR		IRQ_CORETMR
 #else
@@ -231,10 +204,6 @@ int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
 #define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
 #endif
 
-#define __ipipe_root_tick_p(regs)	1
-
-#endif /* !CONFIG_IPIPE */
-
 #define ipipe_update_tick_evtdev(evtdev)	do { } while (0)
 
 #endif	/* !__ASM_BLACKFIN_IPIPE_H */
diff --git a/arch/blackfin/include/asm/ipipe_base.h b/arch/blackfin/include/asm/ipipe_base.h
index 0040920..84a4ffd 100644
--- a/arch/blackfin/include/asm/ipipe_base.h
+++ b/arch/blackfin/include/asm/ipipe_base.h
@@ -24,8 +24,10 @@
 
 #ifdef CONFIG_IPIPE
 
+#include <asm/bitsperlong.h>
+#include <mach/irq.h>
+
 #define IPIPE_NR_XIRQS		NR_IRQS
-#define IPIPE_IRQ_ISHIFT	5	/* 2^5 for 32bits arch. */
 
 /* Blackfin-specific, per-cpu pipeline status */
 #define IPIPE_SYNCDEFER_FLAG	15
@@ -42,11 +44,14 @@
 #define IPIPE_EVENT_INIT	(IPIPE_FIRST_EVENT + 4)
 #define IPIPE_EVENT_EXIT	(IPIPE_FIRST_EVENT + 5)
 #define IPIPE_EVENT_CLEANUP	(IPIPE_FIRST_EVENT + 6)
-#define IPIPE_LAST_EVENT	IPIPE_EVENT_CLEANUP
+#define IPIPE_EVENT_RETURN	(IPIPE_FIRST_EVENT + 7)
+#define IPIPE_LAST_EVENT	IPIPE_EVENT_RETURN
 #define IPIPE_NR_EVENTS		(IPIPE_LAST_EVENT + 1)
 
 #define IPIPE_TIMER_IRQ		IRQ_CORETMR
 
+#define __IPIPE_FEATURE_SYSINFO_V2	1
+
 #ifndef __ASSEMBLY__
 
 extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
@@ -63,6 +68,8 @@ void __ipipe_unlock_root(void);
 
 #endif /* !__ASSEMBLY__ */
 
+#define __IPIPE_FEATURE_SYSINFO_V2	1
+
 #endif /* CONFIG_IPIPE */
 
 #endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */
diff --git a/arch/blackfin/include/asm/irqflags.h b/arch/blackfin/include/asm/irqflags.h
index 3365cb9..b4bbb75 100644
--- a/arch/blackfin/include/asm/irqflags.h
+++ b/arch/blackfin/include/asm/irqflags.h
@@ -89,15 +89,33 @@ static inline void __hard_local_irq_restore(unsigned long flags)
 #ifdef CONFIG_IPIPE
 
 #include <linux/compiler.h>
-#include <linux/ipipe_base.h>
 #include <linux/ipipe_trace.h>
+/*
+ * Way too many inter-deps between low-level headers in this port, so
+ * we redeclare the required bits we cannot pick from
+ * <asm/ipipe_base.h> to prevent circular dependencies.
+ */
+void __ipipe_stall_root(void);
+void __ipipe_unstall_root(void);
+unsigned long __ipipe_test_root(void);
+unsigned long __ipipe_test_and_stall_root(void);
+void __ipipe_restore_root(unsigned long flags);
+
+#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
+struct ipipe_domain;
+extern struct ipipe_domain ipipe_root;
+void ipipe_check_context(struct ipipe_domain *ipd);
+#define __check_irqop_context(ipd)  ipipe_check_context(&ipipe_root)
+#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */
+#define __check_irqop_context(ipd)  do { } while (0)
+#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */
 
 /*
  * Interrupt pipe interface to linux/irqflags.h.
  */
 static inline void arch_local_irq_disable(void)
 {
-	ipipe_check_context(ipipe_root_domain);
+	__check_irqop_context();
 	__ipipe_stall_root();
 	barrier();
 }
@@ -105,7 +123,7 @@ static inline void arch_local_irq_disable(void)
 static inline void arch_local_irq_enable(void)
 {
 	barrier();
-	ipipe_check_context(ipipe_root_domain);
+	__check_irqop_context();
 	__ipipe_unstall_root();
 }
 
@@ -119,16 +137,21 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 	return flags == bfin_no_irqs;
 }
 
-static inline void arch_local_irq_save_ptr(unsigned long *_flags)
+static inline unsigned long arch_local_irq_save(void)
 {
-	x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
+	unsigned long flags;
+
+	__check_irqop_context();
+	flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
 	barrier();
+
+	return flags;
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
-	ipipe_check_context(ipipe_root_domain);
-	return __hard_local_irq_save();
+	__check_irqop_context();
+	__ipipe_restore_root(flags == bfin_no_irqs);
 }
 
 static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
@@ -192,7 +215,10 @@ static inline void hard_local_irq_restore(unsigned long flags)
 # define hard_local_irq_restore(flags)	__hard_local_irq_restore(flags)
 #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 
-#else /* CONFIG_IPIPE */
+#define hard_local_irq_save_cond()		hard_local_irq_save()
+#define hard_local_irq_restore_cond(flags)	hard_local_irq_restore(flags)
+
+#else /* !CONFIG_IPIPE */
 
 /*
  * Direct interface to linux/irqflags.h.
@@ -212,7 +238,48 @@ static inline void hard_local_irq_restore(unsigned long flags)
 #define hard_local_irq_restore(flags)	__hard_local_irq_restore(flags)
 #define hard_local_irq_enable()		__hard_local_irq_enable()
 #define hard_local_irq_disable()	__hard_local_irq_disable()
-
+#define hard_local_irq_save_cond()		hard_local_save_flags()
+#define hard_local_irq_restore_cond(flags)	do { (void)(flags); } while (0)
 
 #endif /* !CONFIG_IPIPE */
+
+#ifdef CONFIG_SMP
+#define hard_local_irq_save_smp()		hard_local_irq_save()
+#define hard_local_irq_restore_smp(flags)	hard_local_irq_restore(flags)
+#else
+#define hard_local_irq_save_smp()		hard_local_save_flags()
+#define hard_local_irq_restore_smp(flags)	do { (void)(flags); } while (0)
+#endif
+
+/*
+ * Remap the arch-neutral IRQ state manipulation macros to the
+ * blackfin-specific hard_local_irq_* API.
+ */
+#define local_irq_save_hw(flags)			\
+	do {						\
+		(flags) = hard_local_irq_save();	\
+	} while (0)
+#define local_irq_restore_hw(flags)		\
+	do {					\
+		hard_local_irq_restore(flags);	\
+	} while (0)
+#define local_irq_disable_hw()			\
+	do {					\
+		hard_local_irq_disable();	\
+	} while (0)
+#define local_irq_enable_hw()			\
+	do {					\
+		hard_local_irq_enable();	\
+	} while (0)
+#define local_irq_save_hw_notrace(flags)		\
+	do {						\
+		(flags) = __hard_local_irq_save();	\
+	} while (0)
+#define local_irq_restore_hw_notrace(flags)		\
+	do {						\
+		__hard_local_irq_restore(flags);	\
+	} while (0)
+
+#define irqs_disabled_hw()	hard_irqs_disabled()
+
 #endif
diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h
index f5b5379..af6c0aa 100644
--- a/arch/blackfin/include/asm/smp.h
+++ b/arch/blackfin/include/asm/smp.h
@@ -17,7 +17,12 @@
 
 #define raw_smp_processor_id()  blackfin_core_id()
 
-extern char coreb_trampoline_start, coreb_trampoline_end;
+extern void bfin_relocate_coreb_l1_mem(void);
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
+asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
+extern unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
 
 struct corelock_slot {
 	int lock;
@@ -34,7 +39,7 @@ extern unsigned long dcache_invld_count[NR_CPUS];
 void smp_icache_flush_range_others(unsigned long start,
 				   unsigned long end);
 #ifdef CONFIG_HOTPLUG_CPU
-void coreb_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
+void coreb_die(void);
 void cpu_die(void);
 void platform_cpu_die(void);
 int __cpu_disable(void);
diff --git a/arch/blackfin/include/asm/unistd.h b/arch/blackfin/include/asm/unistd.h
index 928ae97..c97497d 100644
--- a/arch/blackfin/include/asm/unistd.h
+++ b/arch/blackfin/include/asm/unistd.h
@@ -393,8 +393,11 @@
 #define __NR_fanotify_mark	372
 #define __NR_prlimit64		373
 #define __NR_cacheflush		374
+#define __NR_name_to_handle_at	375
+#define __NR_open_by_handle_at	376
+#define __NR_clock_adjtime	377
 
-#define __NR_syscall		375
+#define __NR_syscall		378
 #define NR_syscalls		__NR_syscall
 
 /* Old optional stuff no one actually uses */
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 1e485df..6ce8dce 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -84,6 +84,24 @@ static int __init proc_dma_init(void)
 late_initcall(proc_dma_init);
 #endif
 
+static void set_dma_peripheral_map(unsigned int channel, const char *device_id)
+{
+#ifdef CONFIG_BF54x
+	unsigned int per_map;
+
+	switch (channel) {
+		case CH_UART2_RX: per_map = 0xC << 12; break;
+		case CH_UART2_TX: per_map = 0xD << 12; break;
+		case CH_UART3_RX: per_map = 0xE << 12; break;
+		case CH_UART3_TX: per_map = 0xF << 12; break;
+		default:          return;
+	}
+
+	if (strncmp(device_id, "BFIN_UART", 9) == 0)
+		dma_ch[channel].regs->peripheral_map = per_map;
+#endif
+}
+
 /**
  *	request_dma - request a DMA channel
  *
@@ -111,19 +129,7 @@ int request_dma(unsigned int channel, const char *device_id)
 		return -EBUSY;
 	}
 
-#ifdef CONFIG_BF54x
-	if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
-		unsigned int per_map;
-		per_map = dma_ch[channel].regs->peripheral_map & 0xFFF;
-		if (strncmp(device_id, "BFIN_UART", 9) == 0)
-			dma_ch[channel].regs->peripheral_map = per_map |
-				((channel - CH_UART2_RX + 0xC)<<12);
-		else
-			dma_ch[channel].regs->peripheral_map = per_map |
-				((channel - CH_UART2_RX + 0x6)<<12);
-	}
-#endif
-
+	set_dma_peripheral_map(channel, device_id);
 	dma_ch[channel].device_id = device_id;
 	dma_ch[channel].irq = 0;
 
diff --git a/arch/blackfin/kernel/ipipe.c b/arch/blackfin/kernel/ipipe.c
index 3b1da4a..f37019c 100644
--- a/arch/blackfin/kernel/ipipe.c
+++ b/arch/blackfin/kernel/ipipe.c
@@ -154,7 +154,7 @@ void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs)
 	 * pending for it.
 	 */
 	if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) &&
-	    ipipe_head_cpudom_var(irqpend_himask) == 0)
+	    !__ipipe_ipending_p(ipipe_head_cpudom_ptr()))
 		goto out;
 
 	__ipipe_walk_pipeline(head);
@@ -185,25 +185,21 @@ void __ipipe_disable_irqdesc(struct ipipe_domain *ipd, unsigned irq)
 }
 EXPORT_SYMBOL(__ipipe_disable_irqdesc);
 
-int __ipipe_syscall_root(struct pt_regs *regs)
+asmlinkage int __ipipe_syscall_root(struct pt_regs *regs)
 {
 	struct ipipe_percpu_domain_data *p;
-	unsigned long flags;
+	void (*hook)(void);
 	int ret;
 
+	WARN_ON_ONCE(irqs_disabled_hw());
+
 	/*
-	 * We need to run the IRQ tail hook whenever we don't
-	 * propagate a syscall to higher domains, because we know that
-	 * important operations might be pending there (e.g. Xenomai
-	 * deferred rescheduling).
+	 * We need to run the IRQ tail hook each time we intercept a
+	 * syscall, because we know that important operations might be
+	 * pending there (e.g. Xenomai deferred rescheduling).
 	 */
-
-	if (regs->orig_p0 < NR_syscalls) {
-		void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
-		hook();
-		if ((current->flags & PF_EVNOTIFY) == 0)
-			return 0;
-	}
+	hook = (__typeof__(hook))__ipipe_irq_tail_hook;
+	hook();
 
 	/*
 	 * This routine either returns:
@@ -214,51 +210,47 @@ int __ipipe_syscall_root(struct pt_regs *regs)
 	 * tail work has to be performed (for handling signals etc).
 	 */
 
-	if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
+	if (!__ipipe_syscall_watched_p(current, regs->orig_p0) ||
+	    !__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
 		return 0;
 
 	ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
 
-	flags = hard_local_irq_save();
+	hard_local_irq_disable();
 
-	if (!__ipipe_root_domain_p) {
-		hard_local_irq_restore(flags);
-		return 1;
+	/*
+	 * This is the end of the syscall path, so we may
+	 * safely assume a valid Linux task stack here.
+	 */
+	if (current->ipipe_flags & PF_EVTRET) {
+		current->ipipe_flags &= ~PF_EVTRET;
+		__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
 	}
 
-	p = ipipe_root_cpudom_ptr();
-	if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
-		__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
+	if (!__ipipe_root_domain_p)
+		ret = -1;
+	else {
+		p = ipipe_root_cpudom_ptr();
+		if (__ipipe_ipending_p(p))
+			__ipipe_sync_pipeline();
+	}
 
-	hard_local_irq_restore(flags);
+	hard_local_irq_enable();
 
 	return -ret;
 }
 
-unsigned long ipipe_critical_enter(void (*syncfn) (void))
-{
-	unsigned long flags;
-
-	flags = hard_local_irq_save();
-
-	return flags;
-}
-
-void ipipe_critical_exit(unsigned long flags)
-{
-	hard_local_irq_restore(flags);
-}
-
 static void __ipipe_no_irqtail(void)
 {
 }
 
 int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
 {
-	info->ncpus = num_online_cpus();
-	info->cpufreq = ipipe_cpu_freq();
-	info->archdep.tmirq = IPIPE_TIMER_IRQ;
-	info->archdep.tmfreq = info->cpufreq;
+	info->sys_nr_cpus = num_online_cpus();
+	info->sys_cpu_freq = ipipe_cpu_freq();
+	info->sys_hrtimer_irq = IPIPE_TIMER_IRQ;
+	info->sys_hrtimer_freq = __ipipe_core_clock;
+	info->sys_hrclock_freq = __ipipe_core_clock;
 
 	return 0;
 }
@@ -289,6 +281,7 @@ int ipipe_trigger_irq(unsigned irq)
 asmlinkage void __ipipe_sync_root(void)
 {
 	void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
+	struct ipipe_percpu_domain_data *p;
 	unsigned long flags;
 
 	BUG_ON(irqs_disabled());
@@ -300,19 +293,20 @@ asmlinkage void __ipipe_sync_root(void)
 
 	clear_thread_flag(TIF_IRQ_SYNC);
 
-	if (ipipe_root_cpudom_var(irqpend_himask) != 0)
-		__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
+	p = ipipe_root_cpudom_ptr();
+	if (__ipipe_ipending_p(p))
+		__ipipe_sync_pipeline();
 
 	hard_local_irq_restore(flags);
 }
 
-void ___ipipe_sync_pipeline(unsigned long syncmask)
+void ___ipipe_sync_pipeline(void)
 {
 	if (__ipipe_root_domain_p &&
 	    test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
 		return;
 
-	__ipipe_sync_stage(syncmask);
+	__ipipe_sync_stage();
 }
 
 void __ipipe_disable_root_irqs_hw(void)
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c
index 64cff54..8f07939 100644
--- a/arch/blackfin/kernel/irqchip.c
+++ b/arch/blackfin/kernel/irqchip.c
@@ -39,21 +39,23 @@ int show_interrupts(struct seq_file *p, void *v)
 	unsigned long flags;
 
 	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_to_desc(i);
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-		seq_printf(p, " %8s", irq_desc[i].chip->name);
+		seq_printf(p, " %8s", get_irq_desc_chip(desc)->name);
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, "  %s", action->name);
 
 		seq_putc(p, '\n');
  skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c
index eb92592..b8cfe34 100644
--- a/arch/blackfin/kernel/kgdb.c
+++ b/arch/blackfin/kernel/kgdb.c
@@ -422,11 +422,7 @@ int kgdb_arch_handle_exception(int vector, int signo,
 
 struct kgdb_arch arch_kgdb_ops = {
 	.gdb_bpt_instr = {0xa1},
-#ifdef CONFIG_SMP
-	.flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
-#else
 	.flags = KGDB_HW_BREAKPOINT,
-#endif
 	.set_hw_breakpoint = bfin_set_hw_break,
 	.remove_hw_breakpoint = bfin_remove_hw_break,
 	.disable_hw_break = bfin_disable_hw_debug,
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index ac71dc1..805c613 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -215,11 +215,48 @@ void __init bfin_relocate_l1_mem(void)
 
 	early_dma_memcpy_done();
 
+#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
+	blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1;
+#endif
+
 	/* if necessary, copy L2 text/data to L2 SRAM */
 	if (L2_LENGTH && l2_len)
 		memcpy(_stext_l2, _l2_lma, l2_len);
 }
 
+#ifdef CONFIG_SMP
+void __init bfin_relocate_coreb_l1_mem(void)
+{
+	unsigned long text_l1_len = (unsigned long)_text_l1_len;
+	unsigned long data_l1_len = (unsigned long)_data_l1_len;
+	unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len;
+
+	blackfin_dma_early_init();
+
+	/* if necessary, copy L1 text to L1 instruction SRAM */
+	if (L1_CODE_LENGTH && text_l1_len)
+		early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma,
+				text_l1_len);
+
+	/* if necessary, copy L1 data to L1 data bank A SRAM */
+	if (L1_DATA_A_LENGTH && data_l1_len)
+		early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma,
+				data_l1_len);
+
+	/* if necessary, copy L1 data B to L1 data bank B SRAM */
+	if (L1_DATA_B_LENGTH && data_b_l1_len)
+		early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma,
+				data_b_l1_len);
+
+	early_dma_memcpy_done();
+
+#ifdef CONFIG_ICACHE_FLUSH_L1
+	blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 -
+			(unsigned long)_stext_l1 + COREB_L1_CODE_START;
+#endif
+}
+#endif
+
 #ifdef CONFIG_ROMKERNEL
 void __init bfin_relocate_xip_data(void)
 {
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index c911361..8d73724 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -114,16 +114,14 @@ u32 arch_gettimeoffset(void)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 #ifdef CONFIG_CORE_TIMER_IRQ_L1
 __attribute__((l1_text))
 #endif
 irqreturn_t timer_interrupt(int irq, void *dummy)
 {
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 
 #ifdef CONFIG_IPIPE
 	update_root_process_times(get_irq_regs());
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 4122678..854fa49 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -136,7 +136,7 @@ SECTIONS
 
 	. = ALIGN(16);
 	INIT_DATA_SECTION(16)
-	PERCPU(4)
+	PERCPU(32, PAGE_SIZE)
 
 	.exit.data :
 	{
@@ -176,6 +176,7 @@ SECTIONS
 	{
 		. = ALIGN(4);
 		__stext_l1 = .;
+		*(.l1.text.head)
 		*(.l1.text)
 #ifdef CONFIG_SCHEDULE_L1
 		SCHED_TEXT
diff --git a/arch/blackfin/mach-bf518/include/mach/defBF512.h b/arch/blackfin/mach-bf518/include/mach/defBF512.h
index 2728582..cb1172f 100644
--- a/arch/blackfin/mach-bf518/include/mach/defBF512.h
+++ b/arch/blackfin/mach-bf518/include/mach/defBF512.h
@@ -1201,25 +1201,6 @@
 #define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
 #define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
 
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
-#define	REP			0x0002	/* HDMA Request Polarity					*/
-#define	UTE			0x0004	/* Urgency Threshold Enable					*/
-#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
-#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
-#define	DRQ			0x0300	/* HDMA Request Type						*/
-#define	DRQ_NONE	0x0000	/* 		No Request							*/
-#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
-#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
-#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
-#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
-#define	PS			0x2000	/* HDMA Pin Status							*/
-#define	OI			0x4000	/* Overflow Interrupt Generated				*/
-#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000
diff --git a/arch/blackfin/mach-bf527/include/mach/defBF522.h b/arch/blackfin/mach-bf527/include/mach/defBF522.h
index 89f5420..84ef11e 100644
--- a/arch/blackfin/mach-bf527/include/mach/defBF522.h
+++ b/arch/blackfin/mach-bf527/include/mach/defBF522.h
@@ -1204,25 +1204,6 @@
 #define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
 #define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
 
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
-#define	REP			0x0002	/* HDMA Request Polarity					*/
-#define	UTE			0x0004	/* Urgency Threshold Enable					*/
-#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
-#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
-#define	DRQ			0x0300	/* HDMA Request Type						*/
-#define	DRQ_NONE	0x0000	/* 		No Request							*/
-#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
-#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
-#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
-#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
-#define	PS			0x2000	/* HDMA Pin Status							*/
-#define	OI			0x4000	/* Overflow Interrupt Generated				*/
-#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000
diff --git a/arch/blackfin/mach-bf533/boards/ip0x.c b/arch/blackfin/mach-bf533/boards/ip0x.c
index f869a37..a377d8a 100644
--- a/arch/blackfin/mach-bf533/boards/ip0x.c
+++ b/arch/blackfin/mach-bf533/boards/ip0x.c
@@ -289,8 +289,6 @@ static struct platform_device *ip0x_devices[] __initdata = {
 
 static int __init ip0x_init(void)
 {
-	int i;
-
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
 	platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
 
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537e.c b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
index 2c776e1..d582b81 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537e.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537e.c
@@ -775,7 +775,7 @@ static int __init cm_bf537e_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537u.c b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
index 0856611..cbb8098 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537u.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537u.c
@@ -740,7 +740,7 @@ static int __init cm_bf537u_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf537/boards/dnp5370.c b/arch/blackfin/mach-bf537/boards/dnp5370.c
index e1e9ea0..6b4ff46 100644
--- a/arch/blackfin/mach-bf537/boards/dnp5370.c
+++ b/arch/blackfin/mach-bf537/boards/dnp5370.c
@@ -128,30 +128,11 @@ static struct platform_device asmb_flash_device = {
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 
-#define MMC_SPI_CARD_DETECT_INT IRQ_PF5
-
-static int bfin_mmc_spi_init(struct device *dev,
-	irqreturn_t (*detect_int)(int, void *), void *data)
-{
-	return request_irq(MMC_SPI_CARD_DETECT_INT, detect_int,
-		IRQF_TRIGGER_FALLING, "mmc-spi-detect", data);
-}
-
-static void bfin_mmc_spi_exit(struct device *dev, void *data)
-{
-	free_irq(MMC_SPI_CARD_DETECT_INT, data);
-}
-
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma    = 0,	 /* use no dma transfer with this chip*/
 	.bits_per_word = 8,
 };
 
-static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
-	.init = bfin_mmc_spi_init,
-	.exit = bfin_mmc_spi_exit,
-	.detect_delay = 100, /* msecs */
-};
 #endif
 
 #if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
@@ -192,7 +173,6 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
 		.max_speed_hz    = 20000000,
 		.bus_num	 = 0,
 		.chip_select     = 1,
-		.platform_data   = &bfin_mmc_spi_pdata,
 		.controller_data = &mmc_spi_chip_info,
 		.mode	         = SPI_MODE_3,
 	},
diff --git a/arch/blackfin/mach-bf537/boards/tcm_bf537.c b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
index 0761b20..164a7e0 100644
--- a/arch/blackfin/mach-bf537/boards/tcm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/tcm_bf537.c
@@ -742,7 +742,7 @@ static int __init tcm_bf537_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf537/include/mach/defBF534.h b/arch/blackfin/mach-bf537/include/mach/defBF534.h
index 725bb35..4a031dd 100644
--- a/arch/blackfin/mach-bf537/include/mach/defBF534.h
+++ b/arch/blackfin/mach-bf537/include/mach/defBF534.h
@@ -1520,24 +1520,6 @@
 #define	PGTE_PPI		0x0000	/*              Enable PPI D15:13                       */
 #define	PGTE_SPORT		0x0800	/*              Enable DT1PRI/TFS1/TSCLK1       */
 
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1                                     */
-#define	REP			0x0002	/* HDMA Request Polarity                                        */
-#define	UTE			0x0004	/* Urgency Threshold Enable                                     */
-#define	OIE			0x0010	/* Overflow Interrupt Enable                            */
-#define	BDIE		0x0020	/* Block Done Interrupt Enable                          */
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT          */
-#define	DRQ			0x0300	/* HDMA Request Type                                            */
-#define	DRQ_NONE	0x0000	/*              No Request                                                      */
-#define	DRQ_SINGLE	0x0100	/*              Channels Request Single                         */
-#define	DRQ_MULTI	0x0200	/*              Channels Request Multi (Default)        */
-#define	DRQ_URGENT	0x0300	/*              Channels Request Multi Urgent           */
-#define	RBC			0x1000	/* Reload BCNT With IBCNT                                       */
-#define	PS			0x2000	/* HDMA Pin Status                                                      */
-#define	OI			0x4000	/* Overflow Interrupt Generated                         */
-#define	BDI			0x8000	/* Block Done Interrupt Generated                       */
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000 
diff --git a/arch/blackfin/mach-bf548/Kconfig b/arch/blackfin/mach-bf548/Kconfig
index 70189a0..94acb58 100644
--- a/arch/blackfin/mach-bf548/Kconfig
+++ b/arch/blackfin/mach-bf548/Kconfig
@@ -42,6 +42,65 @@ config BF548_ATAPI_ALTERNATIVE_PORT
 	  async address or GPIO port F and G. Select y to route it
 	  to GPIO.
 
+choice
+	prompt "UART2 DMA channel selection"
+	depends on SERIAL_BFIN_UART2
+	default UART2_DMA_RX_ON_DMA18
+	help
+		UART2 DMA channel selection
+		RX -> DMA18
+		TX -> DMA19
+		or
+		RX -> DMA13
+		TX -> DMA14
+
+config UART2_DMA_RX_ON_DMA18
+	bool "UART2 DMA RX -> DMA18 TX -> DMA19"
+	help
+		UART2 DMA channel assignment
+		RX -> DMA18
+		TX -> DMA19
+		use SPORT2 default DMA channel
+
+config UART2_DMA_RX_ON_DMA13
+	bool "UART2 DMA RX -> DMA13 TX -> DMA14"
+	help
+		UART2 DMA channel assignment
+		RX -> DMA13
+		TX -> DMA14
+		use EPPI1 EPPI2 default DMA channel
+endchoice
+
+choice
+	prompt "UART3 DMA channel selection"
+	depends on SERIAL_BFIN_UART3
+	default UART3_DMA_RX_ON_DMA20
+	help
+		UART3 DMA channel selection
+		RX -> DMA20
+		TX -> DMA21
+		or
+		RX -> DMA15
+		TX -> DMA16
+
+config UART3_DMA_RX_ON_DMA20
+	bool "UART3 DMA RX -> DMA20 TX -> DMA21"
+	help
+		UART3 DMA channel assignment
+		RX -> DMA20
+		TX -> DMA21
+		use SPORT3 default DMA channel
+
+config UART3_DMA_RX_ON_DMA15
+	bool "UART3 DMA RX -> DMA15 TX -> DMA16"
+	help
+		UART3 DMA channel assignment
+		RX -> DMA15
+		TX -> DMA16
+		use PIXC default DMA channel
+
+endchoice
+
 comment "Interrupt Priority Assignment"
 menu "Priority"
 
diff --git a/arch/blackfin/mach-bf548/boards/ezkit.c b/arch/blackfin/mach-bf548/boards/ezkit.c
index ce5a2bb..93e19a5 100644
--- a/arch/blackfin/mach-bf548/boards/ezkit.c
+++ b/arch/blackfin/mach-bf548/boards/ezkit.c
@@ -778,11 +778,12 @@ static struct platform_device bfin_sport3_uart_device = {
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-static unsigned short bfin_can_peripherals[] = {
+
+static unsigned short bfin_can0_peripherals[] = {
 	P_CAN0_RX, P_CAN0_TX, 0
 };
 
-static struct resource bfin_can_resources[] = {
+static struct resource bfin_can0_resources[] = {
 	{
 		.start = 0xFFC02A00,
 		.end = 0xFFC02FFF,
@@ -805,14 +806,53 @@ static struct resource bfin_can_resources[] = {
 	},
 };
 
-static struct platform_device bfin_can_device = {
+static struct platform_device bfin_can0_device = {
 	.name = "bfin_can",
-	.num_resources = ARRAY_SIZE(bfin_can_resources),
-	.resource = bfin_can_resources,
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_can0_resources),
+	.resource = bfin_can0_resources,
 	.dev = {
-		.platform_data = &bfin_can_peripherals, /* Passed to driver */
+		.platform_data = &bfin_can0_peripherals, /* Passed to driver */
 	},
 };
+
+static unsigned short bfin_can1_peripherals[] = {
+	P_CAN1_RX, P_CAN1_TX, 0
+};
+
+static struct resource bfin_can1_resources[] = {
+	{
+		.start = 0xFFC03200,
+		.end = 0xFFC037FF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_CAN1_RX,
+		.end = IRQ_CAN1_RX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN1_TX,
+		.end = IRQ_CAN1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN1_ERROR,
+		.end = IRQ_CAN1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_can1_device = {
+	.name = "bfin_can",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_can1_resources),
+	.resource = bfin_can1_resources,
+	.dev = {
+		.platform_data = &bfin_can1_peripherals, /* Passed to driver */
+	},
+};
+
 #endif
 
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
@@ -1366,7 +1406,8 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-	&bfin_can_device,
+	&bfin_can0_device,
+	&bfin_can1_device,
 #endif
 
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF544.h b/arch/blackfin/mach-bf548/include/mach/defBF544.h
index 642468c..bcccab3 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF544.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF544.h
@@ -657,22 +657,4 @@
 
 /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
 
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
 #endif /* _DEF_BF544_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/defBF547.h b/arch/blackfin/mach-bf548/include/mach/defBF547.h
index 2f3337c..1cbba11 100644
--- a/arch/blackfin/mach-bf548/include/mach/defBF547.h
+++ b/arch/blackfin/mach-bf548/include/mach/defBF547.h
@@ -1063,23 +1063,4 @@
 
 #define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
 
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
-
 #endif /* _DEF_BF547_H */
diff --git a/arch/blackfin/mach-bf548/include/mach/dma.h b/arch/blackfin/mach-bf548/include/mach/dma.h
index a30d242..1a1091b 100644
--- a/arch/blackfin/mach-bf548/include/mach/dma.h
+++ b/arch/blackfin/mach-bf548/include/mach/dma.h
@@ -27,17 +27,37 @@
 #define CH_PIXC_OVERLAY		16
 #define CH_PIXC_OUTPUT		17
 #define CH_SPORT2_RX		18
-#define CH_UART2_RX		18
 #define CH_SPORT2_TX		19
-#define CH_UART2_TX		19
 #define CH_SPORT3_RX		20
-#define CH_UART3_RX		20
 #define CH_SPORT3_TX		21
-#define CH_UART3_TX		21
 #define CH_SDH			22
 #define CH_NFC			22
 #define CH_SPI2			23
 
+#if defined(CONFIG_UART2_DMA_RX_ON_DMA13)
+#define CH_UART2_RX		13
+#define IRQ_UART2_RX		BFIN_IRQ(37)	/* UART2 RX USE EPP1 (DMA13) Interrupt */
+#define CH_UART2_TX		14
+#define IRQ_UART2_TX		BFIN_IRQ(38)	/* UART2 RX USE EPP1 (DMA14) Interrupt */
+#else						/* Default USE SPORT2's DMA Channel */
+#define CH_UART2_RX		18
+#define IRQ_UART2_RX		BFIN_IRQ(33)	/* UART2 RX (DMA18) Interrupt */
+#define CH_UART2_TX		19
+#define IRQ_UART2_TX		BFIN_IRQ(34)	/* UART2 TX (DMA19) Interrupt */
+#endif
+
+#if defined(CONFIG_UART3_DMA_RX_ON_DMA15)
+#define CH_UART3_RX		15
+#define IRQ_UART3_RX		BFIN_IRQ(64)	/* UART3 RX USE PIXC IN0 (DMA15) Interrupt */
+#define CH_UART3_TX		16
+#define IRQ_UART3_TX		BFIN_IRQ(65)	/* UART3 TX USE PIXC IN1 (DMA16) Interrupt */
+#else						/* Default USE SPORT3's DMA Channel */
+#define CH_UART3_RX		20
+#define IRQ_UART3_RX		BFIN_IRQ(35)	/* UART3 RX (DMA20) Interrupt */
+#define CH_UART3_TX		21
+#define IRQ_UART3_TX		BFIN_IRQ(36)	/* UART3 TX (DMA21) Interrupt */
+#endif
+
 #define CH_MEM_STREAM0_DEST	24
 #define CH_MEM_STREAM0_SRC	25
 #define CH_MEM_STREAM1_DEST	26
diff --git a/arch/blackfin/mach-bf548/include/mach/irq.h b/arch/blackfin/mach-bf548/include/mach/irq.h
index 99fd1b2..7f87787 100644
--- a/arch/blackfin/mach-bf548/include/mach/irq.h
+++ b/arch/blackfin/mach-bf548/include/mach/irq.h
@@ -74,13 +74,9 @@ Events         (highest priority)  EMU         0
 #define IRQ_UART2_ERROR		BFIN_IRQ(31)	/* UART2 Status (Error) Interrupt */
 #define IRQ_CAN0_ERROR		BFIN_IRQ(32)	/* CAN0 Status (Error) Interrupt */
 #define IRQ_SPORT2_RX		BFIN_IRQ(33)	/* SPORT2 RX (DMA18) Interrupt */
-#define IRQ_UART2_RX		BFIN_IRQ(33)	/* UART2 RX (DMA18) Interrupt */
 #define IRQ_SPORT2_TX		BFIN_IRQ(34)	/* SPORT2 TX (DMA19) Interrupt */
-#define IRQ_UART2_TX		BFIN_IRQ(34)	/* UART2 TX (DMA19) Interrupt */
 #define IRQ_SPORT3_RX		BFIN_IRQ(35)	/* SPORT3 RX (DMA20) Interrupt */
-#define IRQ_UART3_RX		BFIN_IRQ(35)	/* UART3 RX (DMA20) Interrupt */
 #define IRQ_SPORT3_TX		BFIN_IRQ(36)	/* SPORT3 TX (DMA21) Interrupt */
-#define IRQ_UART3_TX		BFIN_IRQ(36)	/* UART3 TX (DMA21) Interrupt */
 #define IRQ_EPPI1		BFIN_IRQ(37)	/* EPP1 (DMA13) Interrupt */
 #define IRQ_EPPI2		BFIN_IRQ(38)	/* EPP2 (DMA14) Interrupt */
 #define IRQ_SPI1		BFIN_IRQ(39)	/* SPI1 (DMA5) Interrupt */
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index 3b67929..87595cd 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -541,7 +541,7 @@ static int __init cm_bf561_init(void)
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff --git a/arch/blackfin/mach-bf561/hotplug.c b/arch/blackfin/mach-bf561/hotplug.c
index 4cd3b28..42fc085 100644
--- a/arch/blackfin/mach-bf561/hotplug.c
+++ b/arch/blackfin/mach-bf561/hotplug.c
@@ -5,30 +5,27 @@
  * Licensed under the GPL-2 or later.
  */
 
+#include <linux/smp.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/smp.h>
-
-#define SIC_SYSIRQ(irq)	(irq - (IRQ_CORETMR + 1))
+#include <mach/pll.h>
 
 int hotplug_coreb;
 
 void platform_cpu_die(void)
 {
-	unsigned long iwr[2] = {0, 0};
-	unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32;
-	unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32);
-
+	unsigned long iwr;
 	hotplug_coreb = 1;
 
-	iwr[bank] = bit;
-
 	/* disable core timer */
 	bfin_write_TCNTL(0);
 
-	/* clear ipi interrupt IRQ_SUPPLE_0 */
+	/* clear ipi interrupt IRQ_SUPPLE_0 of CoreB */
 	bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1)));
 	SSYNC();
 
-	coreb_sleep(iwr[0], iwr[1], 0);
+	/* set CoreB wakeup by ipi0, iwr will be discarded */
+	bfin_iwr_set_sup0(&iwr, &iwr, &iwr);
+	SSYNC();
+
+	coreb_die();
 }
diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S
index 4624eeb..4c46283 100644
--- a/arch/blackfin/mach-bf561/secondary.S
+++ b/arch/blackfin/mach-bf561/secondary.S
@@ -13,7 +13,11 @@
 #include <asm/asm-offsets.h>
 #include <asm/trace.h>
 
-__INIT
+/*
+ * This code must come first as CoreB is hardcoded (in hardware)
+ * to start at the beginning of its L1 instruction memory.
+ */
+.section .l1.text.head
 
 /* Lay the initial stack into the L1 scratch area of Core B */
 #define INITIAL_STACK	(COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
@@ -160,43 +164,34 @@ ENTRY(_coreb_trampoline_start)
 .LWAIT_HERE:
 	jump .LWAIT_HERE;
 ENDPROC(_coreb_trampoline_start)
-ENTRY(_coreb_trampoline_end)
 
+#ifdef CONFIG_HOTPLUG_CPU
 .section ".text"
-ENTRY(_set_sicb_iwr)
-	P0.H = hi(SICB_IWR0);
-	P0.L = lo(SICB_IWR0);
-	P1.H = hi(SICB_IWR1);
-	P1.L = lo(SICB_IWR1);
-	[P0] = R0;
-	[P1] = R1;
-	SSYNC;
-	RTS;
-ENDPROC(_set_sicb_iwr)
-
-ENTRY(_coreb_sleep)
+ENTRY(_coreb_die)
 	sp.l = lo(INITIAL_STACK);
 	sp.h = hi(INITIAL_STACK);
 	fp = sp;
 	usp = sp;
 
-	call _set_sicb_iwr;
-
 	CLI R2;
 	SSYNC;
 	IDLE;
 	STI R2;
 
 	R0 = IWR_DISABLE_ALL;
-	R1 = IWR_DISABLE_ALL;
-	call _set_sicb_iwr;
+	P0.H = hi(SYSMMR_BASE);
+	P0.L = lo(SYSMMR_BASE);
+	[P0 + (SICB_IWR0 - SYSMMR_BASE)] = R0;
+	[P0 + (SICB_IWR1 - SYSMMR_BASE)] = R0;
+	SSYNC;
 
 	p0.h = hi(COREB_L1_CODE_START);
 	p0.l = lo(COREB_L1_CODE_START);
 	jump (p0);
-ENDPROC(_coreb_sleep)
+ENDPROC(_coreb_die)
+#endif
 
-__CPUINIT
+__INIT
 ENTRY(_coreb_start)
 	[--sp] = reti;
 
diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c
index 1074a7e..5d68bf6 100644
--- a/arch/blackfin/mach-bf561/smp.c
+++ b/arch/blackfin/mach-bf561/smp.c
@@ -30,18 +30,11 @@ void __init platform_init_cpus(void)
 
 void __init platform_prepare_cpus(unsigned int max_cpus)
 {
-	int len;
-
-	len = &coreb_trampoline_end - &coreb_trampoline_start + 1;
-	BUG_ON(len > L1_CODE_LENGTH);
-
-	dma_memcpy((void *)COREB_L1_CODE_START, &coreb_trampoline_start, len);
+	bfin_relocate_coreb_l1_mem();
 
 	/* Both cores ought to be present on a bf561! */
 	cpu_set(0, cpu_present_map); /* CoreA */
 	cpu_set(1, cpu_present_map); /* CoreB */
-
-	printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_L1_CODE_START);
 }
 
 int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
@@ -161,9 +154,13 @@ void platform_clear_ipi(unsigned int cpu, int irq)
 void __cpuinit bfin_local_timer_setup(void)
 {
 #if defined(CONFIG_TICKSOURCE_CORETMR)
+	struct irq_chip *chip = get_irq_chip(IRQ_CORETMR);
+	struct irq_desc *desc = irq_to_desc(IRQ_CORETMR);
+
 	bfin_coretmr_init();
 	bfin_coretmr_clockevent_init();
-	get_irq_chip(IRQ_CORETMR)->unmask(IRQ_CORETMR);
+
+	chip->irq_unmask(&desc->irq_data);
 #else
 	/* Power down the core timer, just to play safe. */
 	bfin_write_TCNTL(0);
diff --git a/arch/blackfin/mach-common/arch_checks.c b/arch/blackfin/mach-common/arch_checks.c
index bceb981..d8643fd 100644
--- a/arch/blackfin/mach-common/arch_checks.c
+++ b/arch/blackfin/mach-common/arch_checks.c
@@ -61,6 +61,6 @@
 # error "Anomaly 05000220 does not allow you to use Write Back cache with L2 or External Memory"
 #endif
 
-#if ANOMALY_05000491 && !defined(CONFIG_CACHE_FLUSH_L1)
+#if ANOMALY_05000491 && !defined(CONFIG_ICACHE_FLUSH_L1)
 # error You need IFLUSH in L1 inst while Anomaly 05000491 applies
 #endif
diff --git a/arch/blackfin/mach-common/cache.S b/arch/blackfin/mach-common/cache.S
index ab4a925..9f4dd35 100644
--- a/arch/blackfin/mach-common/cache.S
+++ b/arch/blackfin/mach-common/cache.S
@@ -11,12 +11,6 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 
-#ifdef CONFIG_CACHE_FLUSH_L1
-.section .l1.text
-#else
-.text
-#endif
-
 /* 05000443 - IFLUSH cannot be last instruction in hardware loop */
 #if ANOMALY_05000443
 # define BROK_FLUSH_INST "IFLUSH"
@@ -68,11 +62,43 @@
 	RTS;
 .endm
 
+#ifdef CONFIG_ICACHE_FLUSH_L1
+.section .l1.text
+#else
+.text
+#endif
+
 /* Invalidate all instruction cache lines assocoiated with this memory area */
+#ifdef CONFIG_SMP
+# define _blackfin_icache_flush_range _blackfin_icache_flush_range_l1
+#endif
 ENTRY(_blackfin_icache_flush_range)
 	do_flush IFLUSH
 ENDPROC(_blackfin_icache_flush_range)
 
+#ifdef CONFIG_SMP
+.text
+# undef _blackfin_icache_flush_range
+ENTRY(_blackfin_icache_flush_range)
+	p0.L = LO(DSPID);
+	p0.H = HI(DSPID);
+	r3 = [p0];
+	r3 = r3.b (z);
+	p2 = r3;
+	p0.L = _blackfin_iflush_l1_entry;
+	p0.H = _blackfin_iflush_l1_entry;
+	p0 = p0 + (p2 << 2);
+	p1 = [p0];
+	jump (p1);
+ENDPROC(_blackfin_icache_flush_range)
+#endif
+
+#ifdef CONFIG_DCACHE_FLUSH_L1
+.section .l1.text
+#else
+.text
+#endif
+
 /* Throw away all D-cached data in specified region without any obligation to
  * write them back.  Since the Blackfin ISA does not have an "invalidate"
  * instruction, we use flush/invalidate.  Perhaps as a speed optimization we
diff --git a/arch/blackfin/mach-common/cpufreq.c b/arch/blackfin/mach-common/cpufreq.c
index f4cf11d..85dc6d6 100644
--- a/arch/blackfin/mach-common/cpufreq.c
+++ b/arch/blackfin/mach-common/cpufreq.c
@@ -1,7 +1,7 @@
 /*
  * Blackfin core clock scaling
  *
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -16,10 +16,8 @@
 #include <asm/time.h>
 #include <asm/dpmc.h>
 
-#define CPUFREQ_CPU 0
-
 /* this is the table of CCLK frequencies, in Hz */
-/* .index is the entry in the auxillary dpm_state_table[] */
+/* .index is the entry in the auxiliary dpm_state_table[] */
 static struct cpufreq_frequency_table bfin_freq_table[] = {
 	{
 		.frequency = CPUFREQ_TABLE_END,
@@ -46,7 +44,7 @@ static struct bfin_dpm_state {
 
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
 /*
- * normalized to maximum frequncy offset for CYCLES,
+ * normalized to maximum frequency offset for CYCLES,
  * used in time-ts cycles clock source, but could be used
  * somewhere also.
  */
diff --git a/arch/blackfin/mach-common/dpmc.c b/arch/blackfin/mach-common/dpmc.c
index 02c7efd..382099f 100644
--- a/arch/blackfin/mach-common/dpmc.c
+++ b/arch/blackfin/mach-common/dpmc.c
@@ -61,17 +61,63 @@ err_out:
 }
 
 #ifdef CONFIG_CPU_FREQ
+# ifdef CONFIG_SMP
+static void bfin_idle_this_cpu(void *info)
+{
+	unsigned long flags = 0;
+	unsigned long iwr0, iwr1, iwr2;
+	unsigned int cpu = smp_processor_id();
+
+	local_irq_save_hw(flags);
+	bfin_iwr_set_sup0(&iwr0, &iwr1, &iwr2);
+
+	platform_clear_ipi(cpu, IRQ_SUPPLE_0);
+	SSYNC();
+	asm("IDLE;");
+	bfin_iwr_restore(iwr0, iwr1, iwr2);
+
+	local_irq_restore_hw(flags);
+}
+
+static void bfin_idle_cpu(void)
+{
+	smp_call_function(bfin_idle_this_cpu, NULL, 0);
+}
+
+static void bfin_wakeup_cpu(void)
+{
+	unsigned int cpu;
+	unsigned int this_cpu = smp_processor_id();
+	cpumask_t mask = cpu_online_map;
+
+	cpu_clear(this_cpu, mask);
+	for_each_cpu_mask(cpu, mask)
+		platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+}
+
+# else
+static void bfin_idle_cpu(void) {}
+static void bfin_wakeup_cpu(void) {}
+# endif
+
 static int
 vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
 	struct cpufreq_freqs *freq = data;
 
+	if (freq->cpu != CPUFREQ_CPU)
+		return 0;
+
 	if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) {
+		bfin_idle_cpu();
 		bfin_set_vlev(bfin_get_vlev(freq->new));
 		udelay(pdata->vr_settling_time); /* Wait until Volatge settled */
-
-	} else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)
+		bfin_wakeup_cpu();
+	} else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) {
+		bfin_idle_cpu();
 		bfin_set_vlev(bfin_get_vlev(freq->new));
+		bfin_wakeup_cpu();
+	}
 
 	return 0;
 }
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index bc08c98..757943f 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -952,8 +952,17 @@ ENDPROC(_evt_up_evt14)
 #ifdef CONFIG_IPIPE
 
 _resume_kernel_from_int:
+	r1 = LO(~0x8000) (Z);
+	r1 = r0 & r1;
+	r0 = 1;
+	r0 = r1 - r0;
+	r2 = r1 & r0;
+	cc = r2 == 0;
+	/* Sync the root stage only from the outer interrupt level. */
+	if !cc jump .Lnosync;
 	r0.l = ___ipipe_sync_root;
 	r0.h = ___ipipe_sync_root;
+	[--sp] = reti;
 	[--sp] = rets;
 	[--sp] = ( r7:4, p5:3 );
 	SP += -12;
@@ -961,6 +970,8 @@ _resume_kernel_from_int:
 	SP += 12;
 	( r7:4, p5:3 ) = [sp++];
 	rets = [sp++];
+	reti = [sp++];
+.Lnosync:
 	rts
 #elif defined(CONFIG_PREEMPT)
 
@@ -1738,6 +1749,9 @@ ENTRY(_sys_call_table)
 	.long _sys_fanotify_mark
 	.long _sys_prlimit64
 	.long _sys_cacheflush
+	.long _sys_name_to_handle_at	/* 375 */
+	.long _sys_open_by_handle_at
+	.long _sys_clock_adjtime
 
 	.rept NR_syscalls-(.-_sys_call_table)/4
 	.long _sys_ni_syscall
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index 4391621..581e2b0 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -31,6 +31,7 @@ ENDPROC(__init_clear_bss)
 ENTRY(__start)
 	/* R0: argument of command line string, passed from uboot, save it */
 	R7 = R0;
+
 	/* Enable Cycle Counter and Nesting Of Interrupts */
 #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
 	R0 = SYSCFG_SNEN;
@@ -38,76 +39,49 @@ ENTRY(__start)
 	R0 = SYSCFG_SNEN | SYSCFG_CCEN;
 #endif
 	SYSCFG = R0;
-	R0 = 0;
-
-	/* Clear Out All the data and pointer Registers */
-	R1 = R0;
-	R2 = R0;
-	R3 = R0;
-	R4 = R0;
-	R5 = R0;
-	R6 = R0;
-
-	P0 = R0;
-	P1 = R0;
-	P2 = R0;
-	P3 = R0;
-	P4 = R0;
-	P5 = R0;
-
-	LC0 = r0;
-	LC1 = r0;
-	L0 = r0;
-	L1 = r0;
-	L2 = r0;
-	L3 = r0;
-
-	/* Clear Out All the DAG Registers */
-	B0 = r0;
-	B1 = r0;
-	B2 = r0;
-	B3 = r0;
-
-	I0 = r0;
-	I1 = r0;
-	I2 = r0;
-	I3 = r0;
-
-	M0 = r0;
-	M1 = r0;
-	M2 = r0;
-	M3 = r0;
+
+	/* Optimization register tricks: keep a base value in the
+	 * reserved P registers so we use the load/store with an
+	 * offset syntax.  R0 = [P5 + <constant>];
+	 *   P5 - core MMR base
+	 *   R6 - 0
+	 */
+	r6 = 0;
+	p5.l = 0;
+	p5.h = hi(COREMMR_BASE);
+
+	/* Zero out registers required by Blackfin ABI */
+
+	/* Disable circular buffers */
+	L0 = r6;
+	L1 = r6;
+	L2 = r6;
+	L3 = r6;
+
+	/* Disable hardware loops in case we were started by 'go' */
+	LC0 = r6;
+	LC1 = r6;
 
 	/*
 	 * Clear ITEST_COMMAND and DTEST_COMMAND registers,
 	 * Leaving these as non-zero can confuse the emulator
 	 */
-	p0.L = LO(DTEST_COMMAND);
-	p0.H = HI(DTEST_COMMAND);
-	[p0] = R0;
-	[p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0;
+	[p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6;
+	[p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6;
 	CSYNC;
 
 	trace_buffer_init(p0,r0);
-	P0 = R1;
-	R0 = R1;
 
 	/* Turn off the icache */
-	p0.l = LO(IMEM_CONTROL);
-	p0.h = HI(IMEM_CONTROL);
-	R1 = [p0];
-	R0 = ~ENICPLB;
-	R0 = R0 & R1;
-	[p0] = R0;
+	r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)];
+	BITCLR (r1, ENICPLB_P);
+	[p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1;
 	SSYNC;
 
 	/* Turn off the dcache */
-	p0.l = LO(DMEM_CONTROL);
-	p0.h = HI(DMEM_CONTROL);
-	R1 = [p0];
-	R0 = ~ENDCPLB;
-	R0 = R0 & R1;
-	[p0] = R0;
+	r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)];
+	BITCLR (r1, ENDCPLB_P);
+	[p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1;
 	SSYNC;
 
 	/* in case of double faults, save a few things */
@@ -122,25 +96,25 @@ ENTRY(__start)
 	 * below
 	 */
 	GET_PDA(p0, r0);
-	r6 = [p0 + PDA_DF_RETX];
+	r5 = [p0 + PDA_DF_RETX];
 	p1.l = _init_saved_retx;
 	p1.h = _init_saved_retx;
-	[p1] = r6;
+	[p1] = r5;
 
-	r6 = [p0 + PDA_DF_DCPLB];
+	r5 = [p0 + PDA_DF_DCPLB];
 	p1.l = _init_saved_dcplb_fault_addr;
 	p1.h = _init_saved_dcplb_fault_addr;
-	[p1] = r6;
+	[p1] = r5;
 
-	r6 = [p0 + PDA_DF_ICPLB];
+	r5 = [p0 + PDA_DF_ICPLB];
 	p1.l = _init_saved_icplb_fault_addr;
 	p1.h = _init_saved_icplb_fault_addr;
-	[p1] = r6;
+	[p1] = r5;
 
-	r6 = [p0 + PDA_DF_SEQSTAT];
+	r5 = [p0 + PDA_DF_SEQSTAT];
 	p1.l = _init_saved_seqstat;
 	p1.h = _init_saved_seqstat;
-	[p1] = r6;
+	[p1] = r5;
 #endif
 
 	/* Initialize stack pointer */
@@ -155,7 +129,7 @@ ENTRY(__start)
 	sti r0;
 #endif
 
-	r0 = 0 (x);
+	r0 = r6;
 	/* Zero out all of the fun bss regions */
 #if L1_DATA_A_LENGTH > 0
 	r1.l = __sbss_l1;
@@ -210,11 +184,9 @@ ENTRY(__start)
 
 	/* EVT15 = _real_start */
 
-	p0.l = lo(EVT15);
-	p0.h = hi(EVT15);
 	p1.l = _real_start;
 	p1.h = _real_start;
-	[p0] = p1;
+	[p5 + (EVT15 - COREMMR_BASE)] = p1;
 	csync;
 
 #ifdef CONFIG_EARLY_PRINTK
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 2df37db..469ce72 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -274,16 +274,16 @@ ENDPROC(_evt_system_call)
  * level to EVT14 to prepare the caller for a normal interrupt
  * return through RTI.
  *
- * We currently use this facility in two occasions:
+ * We currently use this feature in two occasions:
  *
- * - to branch to __ipipe_irq_tail_hook as requested by a high
+ * - before branching to __ipipe_irq_tail_hook as requested by a high
  *   priority domain after the pipeline delivered an interrupt,
  *   e.g. such as Xenomai, in order to start its rescheduling
  *   procedure, since we may not switch tasks when IRQ levels are
  *   nested on the Blackfin, so we have to fake an interrupt return
  *   so that we may reschedule immediately.
  *
- * - to branch to sync_root_irqs, in order to play any interrupt
+ * - before branching to __ipipe_sync_root(), in order to play any interrupt
  *   pending for the root domain (i.e. the Linux kernel). This lowers
  *   the core priority level enough so that Linux IRQ handlers may
  *   never delay interrupts handled by high priority domains; we defer
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index a604f19..6cd5239 100644
--- a/arch/blackfin/mach-common/ints-priority.c
+++ b/arch/blackfin/mach-common/ints-priority.c
@@ -15,6 +15,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
+#include <linux/sched.h>
 #ifdef CONFIG_IPIPE
 #include <linux/ipipe.h>
 #endif
@@ -124,21 +125,21 @@ static void __init search_IAR(void)
  * This is for core internal IRQs
  */
 
-static void bfin_ack_noop(unsigned int irq)
+static void bfin_ack_noop(struct irq_data *d)
 {
 	/* Dummy function.  */
 }
 
-static void bfin_core_mask_irq(unsigned int irq)
+static void bfin_core_mask_irq(struct irq_data *d)
 {
-	bfin_irq_flags &= ~(1 << irq);
+	bfin_irq_flags &= ~(1 << d->irq);
 	if (!hard_irqs_disabled())
 		hard_local_irq_enable();
 }
 
-static void bfin_core_unmask_irq(unsigned int irq)
+static void bfin_core_unmask_irq(struct irq_data *d)
 {
-	bfin_irq_flags |= 1 << irq;
+	bfin_irq_flags |= 1 << d->irq;
 	/*
 	 * If interrupts are enabled, IMASK must contain the same value
 	 * as bfin_irq_flags.  Make sure that invariant holds.  If interrupts
@@ -176,6 +177,11 @@ static void bfin_internal_mask_irq(unsigned int irq)
 	hard_local_irq_restore(flags);
 }
 
+static void bfin_internal_mask_irq_chip(struct irq_data *d)
+{
+	bfin_internal_mask_irq(d->irq);
+}
+
 #ifdef CONFIG_SMP
 static void bfin_internal_unmask_irq_affinity(unsigned int irq,
 		const struct cpumask *affinity)
@@ -211,19 +217,24 @@ static void bfin_internal_unmask_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_SMP
-static void bfin_internal_unmask_irq(unsigned int irq)
+static void bfin_internal_unmask_irq_chip(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	bfin_internal_unmask_irq_affinity(irq, desc->affinity);
+	bfin_internal_unmask_irq_affinity(d->irq, d->affinity);
 }
 
-static int bfin_internal_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bfin_internal_set_affinity(struct irq_data *d,
+				      const struct cpumask *mask, bool force)
 {
-	bfin_internal_mask_irq(irq);
-	bfin_internal_unmask_irq_affinity(irq, mask);
+	bfin_internal_mask_irq(d->irq);
+	bfin_internal_unmask_irq_affinity(d->irq, mask);
 
 	return 0;
 }
+#else
+static void bfin_internal_unmask_irq_chip(struct irq_data *d)
+{
+	bfin_internal_unmask_irq(d->irq);
+}
 #endif
 
 #ifdef CONFIG_PM
@@ -279,28 +290,33 @@ int bfin_internal_set_wake(unsigned int irq, unsigned int state)
 
 	return 0;
 }
+
+static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)
+{
+	return bfin_internal_set_wake(d->irq, state);
+}
 #endif
 
 static struct irq_chip bfin_core_irqchip = {
 	.name = "CORE",
-	.ack = bfin_ack_noop,
-	.mask = bfin_core_mask_irq,
-	.unmask = bfin_core_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask = bfin_core_mask_irq,
+	.irq_unmask = bfin_core_unmask_irq,
 };
 
 static struct irq_chip bfin_internal_irqchip = {
 	.name = "INTN",
-	.ack = bfin_ack_noop,
-	.mask = bfin_internal_mask_irq,
-	.unmask = bfin_internal_unmask_irq,
-	.mask_ack = bfin_internal_mask_irq,
-	.disable = bfin_internal_mask_irq,
-	.enable = bfin_internal_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask = bfin_internal_mask_irq_chip,
+	.irq_unmask = bfin_internal_unmask_irq_chip,
+	.irq_mask_ack = bfin_internal_mask_irq_chip,
+	.irq_disable = bfin_internal_mask_irq_chip,
+	.irq_enable = bfin_internal_unmask_irq_chip,
 #ifdef CONFIG_SMP
-	.set_affinity = bfin_internal_set_affinity,
+	.irq_set_affinity = bfin_internal_set_affinity,
 #endif
 #ifdef CONFIG_PM
-	.set_wake = bfin_internal_set_wake,
+	.irq_set_wake = bfin_internal_set_wake_chip,
 #endif
 };
 
@@ -312,33 +328,32 @@ static void bfin_handle_irq(unsigned irq)
 	__ipipe_handle_irq(irq, &regs);
 	ipipe_trace_irq_exit(irq);
 #else /* !CONFIG_IPIPE */
-	struct irq_desc *desc = irq_desc + irq;
-	desc->handle_irq(irq, desc);
+	generic_handle_irq(irq);
 #endif  /* !CONFIG_IPIPE */
 }
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 static int error_int_mask;
 
-static void bfin_generic_error_mask_irq(unsigned int irq)
+static void bfin_generic_error_mask_irq(struct irq_data *d)
 {
-	error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));
+	error_int_mask &= ~(1L << (d->irq - IRQ_PPI_ERROR));
 	if (!error_int_mask)
 		bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
 }
 
-static void bfin_generic_error_unmask_irq(unsigned int irq)
+static void bfin_generic_error_unmask_irq(struct irq_data *d)
 {
 	bfin_internal_unmask_irq(IRQ_GENERIC_ERROR);
-	error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
+	error_int_mask |= 1L << (d->irq - IRQ_PPI_ERROR);
 }
 
 static struct irq_chip bfin_generic_error_irqchip = {
 	.name = "ERROR",
-	.ack = bfin_ack_noop,
-	.mask_ack = bfin_generic_error_mask_irq,
-	.mask = bfin_generic_error_mask_irq,
-	.unmask = bfin_generic_error_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask_ack = bfin_generic_error_mask_irq,
+	.irq_mask = bfin_generic_error_mask_irq,
+	.irq_unmask = bfin_generic_error_unmask_irq,
 };
 
 static void bfin_demux_error_irq(unsigned int int_err_irq,
@@ -448,8 +463,10 @@ static void bfin_mac_status_ack_irq(unsigned int irq)
 	}
 }
 
-static void bfin_mac_status_mask_irq(unsigned int irq)
+static void bfin_mac_status_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT));
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	switch (irq) {
@@ -466,8 +483,10 @@ static void bfin_mac_status_mask_irq(unsigned int irq)
 	bfin_mac_status_ack_irq(irq);
 }
 
-static void bfin_mac_status_unmask_irq(unsigned int irq)
+static void bfin_mac_status_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	switch (irq) {
 	case IRQ_MAC_PHYINT:
@@ -484,7 +503,7 @@ static void bfin_mac_status_unmask_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_PM
-int bfin_mac_status_set_wake(unsigned int irq, unsigned int state)
+int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state)
 {
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state);
@@ -496,12 +515,12 @@ int bfin_mac_status_set_wake(unsigned int irq, unsigned int state)
 
 static struct irq_chip bfin_mac_status_irqchip = {
 	.name = "MACST",
-	.ack = bfin_ack_noop,
-	.mask_ack = bfin_mac_status_mask_irq,
-	.mask = bfin_mac_status_mask_irq,
-	.unmask = bfin_mac_status_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask_ack = bfin_mac_status_mask_irq,
+	.irq_mask = bfin_mac_status_mask_irq,
+	.irq_unmask = bfin_mac_status_unmask_irq,
 #ifdef CONFIG_PM
-	.set_wake = bfin_mac_status_set_wake,
+	.irq_set_wake = bfin_mac_status_set_wake,
 #endif
 };
 
@@ -538,13 +557,9 @@ static void bfin_demux_mac_status_irq(unsigned int int_err_irq,
 static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 {
 #ifdef CONFIG_IPIPE
-	_set_irq_handler(irq, handle_level_irq);
-#else
-	struct irq_desc *desc = irq_desc + irq;
-	/* May not call generic set_irq_handler() due to spinlock
-	   recursion. */
-	desc->handle_irq = handle;
+	handle = handle_level_irq;
 #endif
+	__set_irq_handler_unlocked(irq, handle);
 }
 
 static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
@@ -552,17 +567,18 @@ extern void bfin_gpio_irq_prepare(unsigned gpio);
 
 #if !defined(CONFIG_BF54x)
 
-static void bfin_gpio_ack_irq(unsigned int irq)
+static void bfin_gpio_ack_irq(struct irq_data *d)
 {
 	/* AFAIK ack_irq in case mask_ack is provided
 	 * get's only called for edge sense irqs
 	 */
-	set_gpio_data(irq_to_gpio(irq), 0);
+	set_gpio_data(irq_to_gpio(d->irq), 0);
 }
 
-static void bfin_gpio_mask_ack_irq(unsigned int irq)
+static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_desc + irq;
+	unsigned int irq = d->irq;
+	struct irq_desc *desc = irq_to_desc(irq);
 	u32 gpionr = irq_to_gpio(irq);
 
 	if (desc->handle_irq == handle_edge_irq)
@@ -571,39 +587,40 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq)
 	set_gpio_maska(gpionr, 0);
 }
 
-static void bfin_gpio_mask_irq(unsigned int irq)
+static void bfin_gpio_mask_irq(struct irq_data *d)
 {
-	set_gpio_maska(irq_to_gpio(irq), 0);
+	set_gpio_maska(irq_to_gpio(d->irq), 0);
 }
 
-static void bfin_gpio_unmask_irq(unsigned int irq)
+static void bfin_gpio_unmask_irq(struct irq_data *d)
 {
-	set_gpio_maska(irq_to_gpio(irq), 1);
+	set_gpio_maska(irq_to_gpio(d->irq), 1);
 }
 
-static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+static unsigned int bfin_gpio_irq_startup(struct irq_data *d)
 {
-	u32 gpionr = irq_to_gpio(irq);
+	u32 gpionr = irq_to_gpio(d->irq);
 
 	if (__test_and_set_bit(gpionr, gpio_enabled))
 		bfin_gpio_irq_prepare(gpionr);
 
-	bfin_gpio_unmask_irq(irq);
+	bfin_gpio_unmask_irq(d);
 
 	return 0;
 }
 
-static void bfin_gpio_irq_shutdown(unsigned int irq)
+static void bfin_gpio_irq_shutdown(struct irq_data *d)
 {
-	u32 gpionr = irq_to_gpio(irq);
+	u32 gpionr = irq_to_gpio(d->irq);
 
-	bfin_gpio_mask_irq(irq);
+	bfin_gpio_mask_irq(d);
 	__clear_bit(gpionr, gpio_enabled);
 	bfin_gpio_irq_free(gpionr);
 }
 
-static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
+	unsigned int irq = d->irq;
 	int ret;
 	char buf[16];
 	u32 gpionr = irq_to_gpio(irq);
@@ -664,9 +681,9 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 }
 
 #ifdef CONFIG_PM
-int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
-	return gpio_pm_wakeup_ctrl(irq_to_gpio(irq), state);
+	return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state);
 }
 #endif
 
@@ -818,10 +835,10 @@ void init_pint_lut(void)
 	}
 }
 
-static void bfin_gpio_ack_irq(unsigned int irq)
+static void bfin_gpio_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_desc + irq;
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	struct irq_desc *desc = irq_to_desc(d->irq);
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
@@ -835,10 +852,10 @@ static void bfin_gpio_ack_irq(unsigned int irq)
 
 }
 
-static void bfin_gpio_mask_ack_irq(unsigned int irq)
+static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_desc + irq;
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	struct irq_desc *desc = irq_to_desc(d->irq);
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
@@ -853,24 +870,25 @@ static void bfin_gpio_mask_ack_irq(unsigned int irq)
 	pint[bank]->mask_clear = pintbit;
 }
 
-static void bfin_gpio_mask_irq(unsigned int irq)
+static void bfin_gpio_mask_irq(struct irq_data *d)
 {
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 
 	pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
 }
 
-static void bfin_gpio_unmask_irq(unsigned int irq)
+static void bfin_gpio_unmask_irq(struct irq_data *d)
 {
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
 	pint[bank]->mask_set = pintbit;
 }
 
-static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+static unsigned int bfin_gpio_irq_startup(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	u32 gpionr = irq_to_gpio(irq);
 	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
 
@@ -884,22 +902,23 @@ static unsigned int bfin_gpio_irq_startup(unsigned int irq)
 	if (__test_and_set_bit(gpionr, gpio_enabled))
 		bfin_gpio_irq_prepare(gpionr);
 
-	bfin_gpio_unmask_irq(irq);
+	bfin_gpio_unmask_irq(d);
 
 	return 0;
 }
 
-static void bfin_gpio_irq_shutdown(unsigned int irq)
+static void bfin_gpio_irq_shutdown(struct irq_data *d)
 {
-	u32 gpionr = irq_to_gpio(irq);
+	u32 gpionr = irq_to_gpio(d->irq);
 
-	bfin_gpio_mask_irq(irq);
+	bfin_gpio_mask_irq(d);
 	__clear_bit(gpionr, gpio_enabled);
 	bfin_gpio_irq_free(gpionr);
 }
 
-static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
+	unsigned int irq = d->irq;
 	int ret;
 	char buf[16];
 	u32 gpionr = irq_to_gpio(irq);
@@ -961,10 +980,10 @@ static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
 u32 pint_saved_masks[NR_PINT_SYS_IRQS];
 u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
 
-int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
 	u32 pint_irq;
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 bank = PINT_2_BANK(pint_val);
 	u32 pintbit = PINT_BIT(pint_val);
 
@@ -1066,17 +1085,17 @@ static void bfin_demux_gpio_irq(unsigned int inta_irq,
 
 static struct irq_chip bfin_gpio_irqchip = {
 	.name = "GPIO",
-	.ack = bfin_gpio_ack_irq,
-	.mask = bfin_gpio_mask_irq,
-	.mask_ack = bfin_gpio_mask_ack_irq,
-	.unmask = bfin_gpio_unmask_irq,
-	.disable = bfin_gpio_mask_irq,
-	.enable = bfin_gpio_unmask_irq,
-	.set_type = bfin_gpio_irq_type,
-	.startup = bfin_gpio_irq_startup,
-	.shutdown = bfin_gpio_irq_shutdown,
+	.irq_ack = bfin_gpio_ack_irq,
+	.irq_mask = bfin_gpio_mask_irq,
+	.irq_mask_ack = bfin_gpio_mask_ack_irq,
+	.irq_unmask = bfin_gpio_unmask_irq,
+	.irq_disable = bfin_gpio_mask_irq,
+	.irq_enable = bfin_gpio_unmask_irq,
+	.irq_set_type = bfin_gpio_irq_type,
+	.irq_startup = bfin_gpio_irq_startup,
+	.irq_shutdown = bfin_gpio_irq_shutdown,
 #ifdef CONFIG_PM
-	.set_wake = bfin_gpio_set_wake,
+	.irq_set_wake = bfin_gpio_set_wake,
 #endif
 };
 
@@ -1373,7 +1392,7 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
 	struct ipipe_domain *this_domain = __ipipe_current_domain;
 	struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
 	struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
-	int irq, s;
+	int irq, s = 0;
 
 	if (likely(vec == EVT_IVTMR_P))
 		irq = IRQ_CORETMR;
@@ -1423,6 +1442,21 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
 			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
 	}
 
+	/*
+	 * We don't want Linux interrupt handlers to run at the
+	 * current core priority level (i.e. < EVT15), since this
+	 * might delay other interrupts handled by a high priority
+	 * domain. Here is what we do instead:
+	 *
+	 * - we raise the SYNCDEFER bit to prevent
+	 * __ipipe_handle_irq() to sync the pipeline for the root
+	 * stage for the incoming interrupt. Upon return, that IRQ is
+	 * pending in the interrupt log.
+	 *
+	 * - we raise the TIF_IRQ_SYNC bit for the current thread, so
+	 * that _schedule_and_signal_from_int will eventually sync the
+	 * pipeline from EVT15.
+	 */
 	if (this_domain == ipipe_root_domain) {
 		s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
 		barrier();
@@ -1432,6 +1466,24 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
 	__ipipe_handle_irq(irq, regs);
 	ipipe_trace_irq_exit(irq);
 
+	if (user_mode(regs) &&
+	    !ipipe_test_foreign_stack() &&
+	    (current->ipipe_flags & PF_EVTRET) != 0) {
+		/*
+		 * Testing for user_regs() does NOT fully eliminate
+		 * foreign stack contexts, because of the forged
+		 * interrupt returns we do through
+		 * __ipipe_call_irqtail. In that case, we might have
+		 * preempted a foreign stack context in a high
+		 * priority domain, with a single interrupt level now
+		 * pending after the irqtail unwinding is done. In
+		 * which case user_mode() is now true, and the event
+		 * gets dispatched spuriously.
+		 */
+		current->ipipe_flags &= ~PF_EVTRET;
+		__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
+	}
+
 	if (this_domain == ipipe_root_domain) {
 		set_thread_flag(TIF_IRQ_SYNC);
 		if (!s) {
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c
index 9f25140..6e17a26 100644
--- a/arch/blackfin/mach-common/smp.c
+++ b/arch/blackfin/mach-common/smp.c
@@ -40,6 +40,10 @@
  */
 struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
 
+#ifdef CONFIG_ICACHE_FLUSH_L1
+unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
+
 void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
 	*init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
 	*init_saved_dcplb_fault_addr_coreb;
@@ -105,10 +109,10 @@ static void ipi_flush_icache(void *info)
 	struct blackfin_flush_data *fdata = info;
 
 	/* Invalidate the memory holding the bounds of the flushed region. */
-	blackfin_dcache_invalidate_range((unsigned long)fdata,
-					 (unsigned long)fdata + sizeof(*fdata));
+	invalidate_dcache_range((unsigned long)fdata,
+		(unsigned long)fdata + sizeof(*fdata));
 
-	blackfin_icache_flush_range(fdata->start, fdata->end);
+	flush_icache_range(fdata->start, fdata->end);
 }
 
 static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
@@ -244,12 +248,13 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
 {
 	cpumask_t callmap;
 
+	preempt_disable();
 	callmap = cpu_online_map;
 	cpu_clear(smp_processor_id(), callmap);
-	if (cpus_empty(callmap))
-		return 0;
+	if (!cpus_empty(callmap))
+		smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
 
-	smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
+	preempt_enable();
 
 	return 0;
 }
@@ -286,12 +291,13 @@ void smp_send_stop(void)
 {
 	cpumask_t callmap;
 
+	preempt_disable();
 	callmap = cpu_online_map;
 	cpu_clear(smp_processor_id(), callmap);
-	if (cpus_empty(callmap))
-		return;
+	if (!cpus_empty(callmap))
+		smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
 
-	smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
+	preempt_enable();
 
 	return;
 }
@@ -361,8 +367,6 @@ void __cpuinit secondary_start_kernel(void)
 	 */
 	init_exception_vectors();
 
-	bfin_setup_caches(cpu);
-
 	local_irq_disable();
 
 	/* Attach the new idle task to the global mm. */
@@ -381,6 +385,8 @@ void __cpuinit secondary_start_kernel(void)
 
 	local_irq_enable();
 
+	bfin_setup_caches(cpu);
+
 	/*
 	 * Calibrate loops per jiffy value.
 	 * IRQs need to be enabled here - D-cache can be invalidated
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 0a7a4c1..4db5b46 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -56,6 +56,7 @@ config CRIS
 	select HAVE_IDE
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select GENERIC_IRQ_SHOW
 
 config HZ
 	int
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index 7328a7c..907cfb5 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -199,7 +199,7 @@ init_IRQ(void)
 
 	/* Initialize IRQ handler descriptors. */
 	for(i = 2; i < NR_IRQS; i++) {
-		set_irq_desc_and_handler(i, &crisv10_irq_type,
+		irq_set_chip_and_handler(i, &crisv10_irq_type,
 					 handle_simple_irq);
 		set_int_vector(i, interrupt[i]);
 	}
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index 00eb36f..20c85b5 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -140,7 +140,7 @@ stop_watchdog(void)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 
 //static unsigned short myjiff; /* used by our debug routine print_timestamp */
@@ -176,7 +176,7 @@ timer_interrupt(int irq, void *dev_id)
 
 	/* call the real timer interrupt handler */
 
-	do_timer(1);
+	xtime_update(1);
 	
         cris_do_profile(regs); /* Save profiling information */
         return IRQ_HANDLED;
diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c
index baa746c..e7f8066 100644
--- a/arch/cris/arch-v10/mm/init.c
+++ b/arch/cris/arch-v10/mm/init.c
@@ -241,7 +241,7 @@ flush_etrax_cacherange(void *startadr, int length)
 }
 
 /* Due to a bug in Etrax100(LX) all versions, receiving DMA buffers
- * will occationally corrupt certain CPU writes if the DMA buffers
+ * will occasionally corrupt certain CPU writes if the DMA buffers
  * happen to be hot in the cache.
  * 
  * As a workaround, we have to flush the relevant parts of the cache
diff --git a/arch/cris/arch-v32/kernel/irq.c b/arch/cris/arch-v32/kernel/irq.c
index 0ad9db5..8023176 100644
--- a/arch/cris/arch-v32/kernel/irq.c
+++ b/arch/cris/arch-v32/kernel/irq.c
@@ -451,16 +451,16 @@ init_IRQ(void)
 
 	/* Point all IRQ's to bad handlers. */
 	for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
-		set_irq_chip_and_handler(j, &crisv32_irq_type,
+		irq_set_chip_and_handler(j, &crisv32_irq_type,
 					 handle_simple_irq);
 		set_exception_vector(i, interrupt[j]);
 	}
 
-        /* Mark Timer and IPI IRQs as CPU local */
+	/* Mark Timer and IPI IRQs as CPU local */
 	irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
-	irq_desc[TIMER0_INTR_VECT].status |= IRQ_PER_CPU;
+	irq_set_status_flags(TIMER0_INTR_VECT, IRQ_PER_CPU);
 	irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
-	irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU;
+	irq_set_status_flags(IPI_INTR_VECT, IRQ_PER_CPU);
 
 	set_exception_vector(0x00, nmi_interrupt);
 	set_exception_vector(0x30, multiple_interrupt);
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c
index 84fed3b..4c9e3e1 100644
--- a/arch/cris/arch-v32/kernel/smp.c
+++ b/arch/cris/arch-v32/kernel/smp.c
@@ -26,7 +26,9 @@
 #define FLUSH_ALL (void*)0xffffffff
 
 /* Vector of locks used for various atomic operations */
-spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
+spinlock_t cris_atomic_locks[] = {
+	[0 ... LOCK_COUNT - 1] = __SPIN_LOCK_UNLOCKED(cris_atomic_locks)
+};
 
 /* CPU masks */
 cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
diff --git a/arch/cris/arch-v32/kernel/time.c b/arch/cris/arch-v32/kernel/time.c
index a545211..bb978ed 100644
--- a/arch/cris/arch-v32/kernel/time.c
+++ b/arch/cris/arch-v32/kernel/time.c
@@ -183,7 +183,7 @@ void handle_watchdog_bite(struct pt_regs *regs)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick.
+ * as well as call the "xtime_update()" routine every clocktick.
  */
 extern void cris_do_profile(struct pt_regs *regs);
 
@@ -216,9 +216,7 @@ static inline irqreturn_t timer_interrupt(int irq, void *dev_id)
 		return IRQ_HANDLED;
 
 	/* Call the real timer interrupt handler */
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
         return IRQ_HANDLED;
 }
 
diff --git a/arch/cris/include/asm/thread_info.h b/arch/cris/include/asm/thread_info.h
index 9177606..29b74a1 100644
--- a/arch/cris/include/asm/thread_info.h
+++ b/arch/cris/include/asm/thread_info.h
@@ -68,7 +68,7 @@ struct thread_info {
 #define init_thread_info	(init_thread_union.thread_info)
 
 /* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define alloc_thread_info(tsk, node) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
 #define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/cris/include/asm/types.h b/arch/cris/include/asm/types.h
index 5790262..4405508 100644
--- a/arch/cris/include/asm/types.h
+++ b/arch/cris/include/asm/types.h
@@ -18,9 +18,6 @@ typedef unsigned short umode_t;
 
 #ifndef __ASSEMBLY__
 
-/* Dma addresses are 32-bits wide, just like our other addresses.  */
- 
-typedef u32 dma_addr_t;
 typedef u32 dma64_addr_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c
index c346952..788eb22 100644
--- a/arch/cris/kernel/irq.c
+++ b/arch/cris/kernel/irq.c
@@ -37,45 +37,6 @@
 
 #include <asm/io.h>
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	return 0;
-}
-
-
 /* called by the assembler IRQ entry functions defined in irq.h
  * to dispatch the interrupts to registered handlers
  * interrupts are disabled upon entry - depending on if the
diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S
index c49be84..728bbd9 100644
--- a/arch/cris/kernel/vmlinux.lds.S
+++ b/arch/cris/kernel/vmlinux.lds.S
@@ -102,7 +102,7 @@ SECTIONS
 #endif
 	__vmlinux_end = .;		/* Last address of the physical file. */
 #ifdef CONFIG_ETRAX_ARCH_V32
-	PERCPU(PAGE_SIZE)
+	PERCPU(32, PAGE_SIZE)
 
 	.init.ramfs : {
 		INIT_RAM_FS
diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h
index 08b3d1d..4bea27f 100644
--- a/arch/frv/include/asm/futex.h
+++ b/arch/frv/include/asm/futex.h
@@ -7,10 +7,11 @@
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
-extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h
index 3744f2e..4b789ab 100644
--- a/arch/frv/include/asm/processor.h
+++ b/arch/frv/include/asm/processor.h
@@ -137,7 +137,7 @@ unsigned long get_wchan(struct task_struct *p);
 #define	KSTK_ESP(tsk)	((tsk)->thread.frame0->sp)
 
 /* Allocation and freeing of basic task resources. */
-extern struct task_struct *alloc_task_struct(void);
+extern struct task_struct *alloc_task_struct_node(int node);
 extern void free_task_struct(struct task_struct *p);
 
 #define cpu_relax()    barrier()
diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h
index 11f33ea..8582e9c 100644
--- a/arch/frv/include/asm/thread_info.h
+++ b/arch/frv/include/asm/thread_info.h
@@ -84,16 +84,11 @@ register struct thread_info *__current_thread_info asm("gr15");
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-	({							\
-		struct thread_info *ret;			\
-								\
-		ret = kzalloc(THREAD_SIZE, GFP_KERNEL);		\
-								\
-		ret;						\
-	})
+#define alloc_thread_info_node(tsk, node)			\
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk)	kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk)				\
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(info)	kfree(info)
diff --git a/arch/frv/include/asm/types.h b/arch/frv/include/asm/types.h
index 613bf1e..aa3e7fd 100644
--- a/arch/frv/include/asm/types.h
+++ b/arch/frv/include/asm/types.h
@@ -27,14 +27,6 @@ typedef unsigned short umode_t;
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TYPES_H */
diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c
index 14f64b0..d155ca9 100644
--- a/arch/frv/kernel/futex.c
+++ b/arch/frv/kernel/futex.c
@@ -18,7 +18,7 @@
  * the various futex operations; MMU fault checking is ignored under no-MMU
  * conditions
  */
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o
 /*
  * do the futex operations
  */
-int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -197,7 +197,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index efad120..9d35975 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -44,9 +44,10 @@ asmlinkage void ret_from_fork(void);
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-struct task_struct *alloc_task_struct(void)
+struct task_struct *alloc_task_struct_node(int node)
 {
-	struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL);
+	struct task_struct *p = kmalloc_node(THREAD_SIZE, GFP_KERNEL, node);
+
 	if (p)
 		atomic_set((atomic_t *)(p+1), 1);
 	return p;
diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c
index 0ddbbae..b457de4 100644
--- a/arch/frv/kernel/time.c
+++ b/arch/frv/kernel/time.c
@@ -50,21 +50,13 @@ static struct irqaction timer_irq  = {
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	profile_tick(CPU_PROFILING);
-	/*
-	 * Here we are in the timer irq handler. We just have irqs locally
-	 * disabled but we don't know if the timer_bh is running on the other
-	 * CPU. We need to avoid to SMP race with it. NOTE: we don't need
-	 * the irq version of write_lock because as just said we have irq
-	 * locally disabled. -arca
-	 */
-	write_seqlock(&xtime_lock);
 
-	do_timer(1);
+	xtime_update(1);
 
 #ifdef CONFIG_HEARTBEAT
 	static unsigned short n;
@@ -72,8 +64,6 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
 	__set_LEDS(n);
 #endif /* CONFIG_HEARTBEAT */
 
-	write_sequnlock(&xtime_lock);
-
 	update_process_times(user_mode(get_irq_regs()));
 
 	return IRQ_HANDLED;
diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
index 8b973f3..0daae8a 100644
--- a/arch/frv/kernel/vmlinux.lds.S
+++ b/arch/frv/kernel/vmlinux.lds.S
@@ -37,7 +37,7 @@ SECTIONS
   _einittext = .;
 
   INIT_DATA_SECTION(8)
-  PERCPU(4096)
+  PERCPU(L1_CACHE_BYTES, 4096)
 
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile
index d6189e0..6745cb1 100644
--- a/arch/h8300/boot/compressed/Makefile
+++ b/arch/h8300/boot/compressed/Makefile
@@ -5,7 +5,7 @@
 #
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS	:= -traditional
+asflags-y	:= -traditional
 
 OBJECTS = $(obj)/head.o $(obj)/misc.o
 
diff --git a/arch/h8300/include/asm/types.h b/arch/h8300/include/asm/types.h
index 1287519..bb2c91a 100644
--- a/arch/h8300/include/asm/types.h
+++ b/arch/h8300/include/asm/types.h
@@ -22,10 +22,6 @@ typedef unsigned short umode_t;
 
 #define BITS_PER_LONG 32
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c
index 165005a..32263a1 100644
--- a/arch/h8300/kernel/time.c
+++ b/arch/h8300/kernel/time.c
@@ -35,9 +35,7 @@ void h8300_timer_tick(void)
 {
 	if (current->pid)
 		profile_tick(CPU_PROFILING);
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 	update_process_times(user_mode(get_irq_regs()));
 }
 
diff --git a/arch/h8300/kernel/timer/timer8.c b/arch/h8300/kernel/timer/timer8.c
index 3946c0f..7a1533f 100644
--- a/arch/h8300/kernel/timer/timer8.c
+++ b/arch/h8300/kernel/timer/timer8.c
@@ -61,7 +61,7 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index 3ded8fe..1d7bca0 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -233,3 +233,4 @@ CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_T10DIF=y
+CONFIG_MISC_DEVICES=y
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index 3a98b2d..b11fa88 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -208,3 +208,4 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_CRYPTO_MD5=y
+CONFIG_MISC_DEVICES=y
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
index 13633da..bff0824 100644
--- a/arch/ia64/hp/sim/simserial.c
+++ b/arch/ia64/hp/sim/simserial.c
@@ -390,8 +390,7 @@ static void rs_unthrottle(struct tty_struct * tty)
 }
 
 
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
+static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 {
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index a2e7368..4336d08 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -12,6 +12,8 @@
 
 #define ARCH_HAS_DMA_GET_REQUIRED_MASK
 
+#define DMA_ERROR_CODE 0
+
 extern struct dma_map_ops *dma_ops;
 extern struct ia64_machine_vector ia64_mv;
 extern void set_iommu_machvec(void);
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index c7f0f06..8428525 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -46,7 +46,7 @@ do {									\
 } while (0)
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -56,7 +56,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -100,23 +100,26 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
+		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
 			"	mov ar.ccv=%3;;				\n"
 			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8)
+			: "=r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
+		*uval = prev;
 		return r8;
 	}
 }
diff --git a/arch/ia64/include/asm/perfmon.h b/arch/ia64/include/asm/perfmon.h
index 7f3333d..d551183 100644
--- a/arch/ia64/include/asm/perfmon.h
+++ b/arch/ia64/include/asm/perfmon.h
@@ -7,7 +7,7 @@
 #define _ASM_IA64_PERFMON_H
 
 /*
- * perfmon comamnds supported on all CPU models
+ * perfmon commands supported on all CPU models
  */
 #define PFM_WRITE_PMCS		0x01
 #define PFM_WRITE_PMDS		0x02
diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h
index 215d545..3027e75 100644
--- a/arch/ia64/include/asm/rwsem.h
+++ b/arch/ia64/include/asm/rwsem.h
@@ -25,20 +25,8 @@
 #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
 #endif
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
 #include <asm/intrinsics.h>
 
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	signed long		count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-};
-
 #define RWSEM_UNLOCKED_VALUE		__IA64_UL_CONST(0x0000000000000000)
 #define RWSEM_ACTIVE_BIAS		(1L)
 #define RWSEM_ACTIVE_MASK		(0xffffffffL)
@@ -46,26 +34,6 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-	  LIST_HEAD_INIT((name).wait_list) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-static inline void
-init_rwsem (struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
-
 /*
  * lock for reading
  */
@@ -174,9 +142,4 @@ __downgrade_write (struct rw_semaphore *sem)
 #define rwsem_atomic_add(delta, sem)	atomic64_add(delta, (atomic64_t *)(&(sem)->count))
 #define rwsem_atomic_update(delta, sem)	atomic64_add_return(delta, (atomic64_t *)(&(sem)->count))
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* _ASM_IA64_RWSEM_H */
diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h
index b6a5ba2..6392908 100644
--- a/arch/ia64/include/asm/thread_info.h
+++ b/arch/ia64/include/asm/thread_info.h
@@ -59,11 +59,12 @@ struct thread_info {
 #ifndef ASM_OFFSETS_C
 /* how to get the thread information struct from C */
 #define current_thread_info()	((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
-#define alloc_thread_info(tsk)	((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#define alloc_thread_info_node(tsk, node)	\
+		((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
 #define task_thread_info(tsk)	((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
 #else
 #define current_thread_info()	((struct thread_info *) 0)
-#define alloc_thread_info(tsk)	((struct thread_info *) 0)
+#define alloc_thread_info_node(tsk, node)	((struct thread_info *) 0)
 #define task_thread_info(tsk)	((struct thread_info *) 0)
 #endif
 #define free_thread_info(ti)	/* nothing */
@@ -84,7 +85,14 @@ struct thread_info {
 #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
 
 #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-#define alloc_task_struct()	((struct task_struct *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER))
+#define alloc_task_struct_node(node)						\
+({										\
+	struct page *page = alloc_pages_node(node, GFP_KERNEL | __GFP_COMP,	\
+					     KERNEL_STACK_SIZE_ORDER);		\
+	struct task_struct *ret = page ? page_address(page) : NULL;		\
+										\
+	ret;
+})
 #define free_task_struct(tsk)	free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
 
 #endif /* !__ASSEMBLY */
diff --git a/arch/ia64/include/asm/types.h b/arch/ia64/include/asm/types.h
index 93773fd..82b3939 100644
--- a/arch/ia64/include/asm/types.h
+++ b/arch/ia64/include/asm/types.h
@@ -40,9 +40,6 @@ struct fnptr {
 	unsigned long gp;
 };
 
-/* DMA addresses are 64-bits wide, in general.  */
-typedef u64 dma_addr_t;
-
 # endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY__ */
 
diff --git a/arch/ia64/include/asm/xen/hypercall.h b/arch/ia64/include/asm/xen/hypercall.h
index 96fc623..ed28bcd 100644
--- a/arch/ia64/include/asm/xen/hypercall.h
+++ b/arch/ia64/include/asm/xen/hypercall.h
@@ -107,7 +107,7 @@ extern unsigned long __hypercall(unsigned long a1, unsigned long a2,
 static inline int
 xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg)
 {
-	return _hypercall2(int, sched_op_new, cmd, arg);
+	return _hypercall2(int, sched_op, cmd, arg);
 }
 
 static inline long
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 1753f6a..80d50b8 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -582,6 +582,8 @@ out:
 	/* Get the CPE error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
 
+	local_irq_disable();
+
 	return IRQ_HANDLED;
 }
 
@@ -1859,7 +1861,8 @@ ia64_mca_cpu_init(void *cpu_data)
 			data = mca_bootmem();
 			first_time = 0;
 		} else
-			data = __get_free_pages(GFP_KERNEL, get_order(sz));
+			data = (void *)__get_free_pages(GFP_KERNEL,
+							get_order(sz));
 		if (!data)
 			panic("Could not allocate MCA memory for cpu %d\n",
 					cpu);
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 9702fa9..156ad80 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -190,19 +190,10 @@ timer_interrupt (int irq, void *dev_id)
 
 		new_itm += local_cpu_data->itm_delta;
 
-		if (smp_processor_id() == time_keeper_id) {
-			/*
-			 * Here we are in the timer irq handler. We have irqs locally
-			 * disabled, but we don't know if the timer_bh is running on
-			 * another CPU. We need to avoid to SMP race by acquiring the
-			 * xtime_lock.
-			 */
-			write_seqlock(&xtime_lock);
-			do_timer(1);
-			local_cpu_data->itm_next = new_itm;
-			write_sequnlock(&xtime_lock);
-		} else
-			local_cpu_data->itm_next = new_itm;
+		if (smp_processor_id() == time_keeper_id)
+			xtime_update(1);
+
+		local_cpu_data->itm_next = new_itm;
 
 		if (time_after(new_itm, ia64_get_itc()))
 			break;
@@ -222,7 +213,7 @@ skip_process_time_accounting:
 		 * comfort, we increase the safety margin by
 		 * intentionally dropping the next tick(s).  We do NOT
 		 * update itm.next because that would force us to call
-		 * do_timer() which in turn would let our clock run
+		 * xtime_update() which in turn would let our clock run
 		 * too fast (with the potentially devastating effect
 		 * of losing monotony of time).
 		 */
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index 5a4d044..787de4a 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -198,7 +198,7 @@ SECTIONS {
 
 	/* Per-cpu data: */
 	. = ALIGN(PERCPU_PAGE_SIZE);
-	PERCPU_VADDR(PERCPU_ADDR, :percpu)
+	PERCPU_VADDR(SMP_CACHE_BYTES, PERCPU_ADDR, :percpu)
 	__phys_per_cpu_start = __per_cpu_load;
 	/*
 	 * ensure percpu data fits
diff --git a/arch/ia64/kvm/Makefile b/arch/ia64/kvm/Makefile
index 1089b3e..db3d7c5 100644
--- a/arch/ia64/kvm/Makefile
+++ b/arch/ia64/kvm/Makefile
@@ -45,8 +45,8 @@ FORCE : $(obj)/$(offsets-file)
 # Makefile for Kernel-based Virtual Machine module
 #
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
-EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
+ccflags-y := -Ivirt/kvm -Iarch/ia64/kvm/
+asflags-y := -Ivirt/kvm -Iarch/ia64/kvm/
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
 		coalesced_mmio.o irq_comm.o assigned-dev.o)
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 70d224d..8213efe 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -662,6 +662,7 @@ again:
 		goto vcpu_run_fail;
 
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
+	vcpu->mode = IN_GUEST_MODE;
 	kvm_guest_enter();
 
 	/*
@@ -683,6 +684,7 @@ again:
 	 */
 	barrier();
 	kvm_guest_exit();
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	preempt_enable();
 
 	idx = srcu_read_lock(&vcpu->kvm->srcu);
diff --git a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile
index 0591038..d27df1d 100644
--- a/arch/ia64/sn/kernel/Makefile
+++ b/arch/ia64/sn/kernel/Makefile
@@ -7,7 +7,7 @@
 # Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y				+= setup.o bte.o bte_error.o irq.o mca.o idle.o \
 				   huberror.o io_acpi_init.o io_common.o \
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index dbc4cbe..77db0b5 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -592,7 +592,7 @@ void __cpuinit sn_cpu_init(void)
 	/*
 	 * Don't check status. The SAL call is not supported on all PROMs
 	 * but a failure is harmless.
-	 * Architechtuallly, cpu_init is always called twice on cpu 0. We
+	 * Architecturally, cpu_init is always called twice on cpu 0. We
 	 * should set cpu_number on cpu 0 once.
 	 */
 	if (cpuid == 0) {
diff --git a/arch/ia64/sn/kernel/sn2/Makefile b/arch/ia64/sn/kernel/sn2/Makefile
index 08e6565..3d09108 100644
--- a/arch/ia64/sn/kernel/sn2/Makefile
+++ b/arch/ia64/sn/kernel/sn2/Makefile
@@ -9,7 +9,7 @@
 # sn2 specific kernel files
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
 	 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile
index ad4ef34..df2a901 100644
--- a/arch/ia64/sn/pci/Makefile
+++ b/arch/ia64/sn/pci/Makefile
@@ -7,6 +7,6 @@
 #
 # Makefile for the sn pci general routines.
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff --git a/arch/ia64/sn/pci/pcibr/Makefile b/arch/ia64/sn/pci/pcibr/Makefile
index 01192d3..396bcae 100644
--- a/arch/ia64/sn/pci/pcibr/Makefile
+++ b/arch/ia64/sn/pci/pcibr/Makefile
@@ -7,7 +7,7 @@
 #
 # Makefile for the sn2 io routines.
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y				+=  pcibr_dma.o pcibr_reg.o \
 				    pcibr_ate.o pcibr_provider.o
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 4d4536e..9c271be 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -509,7 +509,7 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir)
  * use the GART mapped mode.
  */
 static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
 {
 	u64 mapaddr;
 
diff --git a/arch/ia64/uv/kernel/Makefile b/arch/ia64/uv/kernel/Makefile
index 8d92b46..124e441 100644
--- a/arch/ia64/uv/kernel/Makefile
+++ b/arch/ia64/uv/kernel/Makefile
@@ -7,7 +7,7 @@
 # Copyright (C) 2008 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y				+= setup.o
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
diff --git a/arch/ia64/xen/suspend.c b/arch/ia64/xen/suspend.c
index fd66b04..419c862 100644
--- a/arch/ia64/xen/suspend.c
+++ b/arch/ia64/xen/suspend.c
@@ -37,19 +37,14 @@ xen_mm_unpin_all(void)
 	/* nothing */
 }
 
-void xen_pre_device_suspend(void)
-{
-	/* nothing */
-}
-
 void
-xen_pre_suspend()
+xen_arch_pre_suspend()
 {
 	/* nothing */
 }
 
 void
-xen_post_suspend(int suspend_cancelled)
+xen_arch_post_suspend(int suspend_cancelled)
 {
 	if (suspend_cancelled)
 		return;
diff --git a/arch/ia64/xen/time.c b/arch/ia64/xen/time.c
index c1c5445..1f8244a 100644
--- a/arch/ia64/xen/time.c
+++ b/arch/ia64/xen/time.c
@@ -139,14 +139,11 @@ consider_steal_time(unsigned long new_itm)
 		run_posix_cpu_timers(p);
 		delta_itm += local_cpu_data->itm_delta * (stolen + blocked);
 
-		if (cpu == time_keeper_id) {
-			write_seqlock(&xtime_lock);
-			do_timer(stolen + blocked);
-			local_cpu_data->itm_next = delta_itm + new_itm;
-			write_sequnlock(&xtime_lock);
-		} else {
-			local_cpu_data->itm_next = delta_itm + new_itm;
-		}
+		if (cpu == time_keeper_id)
+			xtime_update(stolen + blocked);
+
+		local_cpu_data->itm_next = delta_itm + new_itm;
+
 		per_cpu(xen_stolen_time, cpu) += NS_PER_TICK * stolen;
 		per_cpu(xen_blocked_time, cpu) += NS_PER_TICK * blocked;
 	}
diff --git a/arch/m32r/include/asm/thread_info.h b/arch/m32r/include/asm/thread_info.h
index 71faff5..0227dba 100644
--- a/arch/m32r/include/asm/thread_info.h
+++ b/arch/m32r/include/asm/thread_info.h
@@ -96,16 +96,11 @@ static inline struct thread_info *current_thread_info(void)
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-	({							\
-		struct thread_info *ret;			\
-	 							\
-	 	ret = kzalloc(THREAD_SIZE, GFP_KERNEL);		\
-								\
-	 	ret;						\
-	 })
+#define alloc_thread_info_node(tsk, node)			\
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(info) kfree(info)
diff --git a/arch/m32r/include/asm/types.h b/arch/m32r/include/asm/types.h
index bc9f7ff..fd84b48 100644
--- a/arch/m32r/include/asm/types.h
+++ b/arch/m32r/include/asm/types.h
@@ -18,9 +18,6 @@ typedef unsigned short umode_t;
 
 #ifndef __ASSEMBLY__
 
-/* DMA addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
 typedef u64 dma64_addr_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index bda8682..84dd040 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -107,15 +107,14 @@ u32 arch_gettimeoffset(void)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 #ifndef CONFIG_SMP
 	profile_tick(CPU_PROFILING);
 #endif
-	/* XXX FIXME. Uh, the xtime_lock should be held here, no? */
-	do_timer(1);
+	xtime_update(1);
 
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
index 7da94ea..c194d64 100644
--- a/arch/m32r/kernel/vmlinux.lds.S
+++ b/arch/m32r/kernel/vmlinux.lds.S
@@ -53,7 +53,7 @@ SECTIONS
   __init_begin = .;
   INIT_TEXT_SECTION(PAGE_SIZE)
   INIT_DATA_SECTION(16)
-  PERCPU(PAGE_SIZE)
+  PERCPU(32, PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index bc9271b..525174d 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -18,11 +18,9 @@ config RWSEM_XCHGADD_ALGORITHM
 
 config ARCH_HAS_ILOG2_U32
 	bool
-	default n
 
 config ARCH_HAS_ILOG2_U64
 	bool
-	default n
 
 config GENERIC_HWEIGHT
 	bool
@@ -242,6 +240,37 @@ config SUN3
 
 	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
 
+config NATFEAT
+	bool "ARAnyM emulator support"
+	depends on ATARI
+	help
+	  This option enables support for ARAnyM native features, such as
+	  access to a disk image as /dev/hda.
+
+config NFBLOCK
+	tristate "NatFeat block device support"
+	depends on BLOCK && NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat block device
+	  which allows direct access to the hard drives without using
+	  the hardware emulation.
+
+config NFCON
+	tristate "NatFeat console driver"
+	depends on NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat console driver
+	  which allows the console output to be redirected to the stderr
+	  output of ARAnyM.
+
+config NFETH
+	tristate "NatFeat Ethernet support"
+	depends on NET_ETHERNET && NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat network device
+	  which will emulate a regular ethernet device while presenting an
+	  ethertap device to the host system.
+
 comment "Processor type"
 
 config M68020
@@ -554,14 +583,6 @@ config MVME147_SCC
 	  This is the driver for the serial ports on the Motorola MVME147
 	  boards.  Everyone using one of these boards should say Y here.
 
-config SERIAL167
-	bool "CD2401 support for MVME166/7 serial ports"
-	depends on MVME16x
-	help
-	  This is the driver for the serial ports on the Motorola MVME166,
-	  167, and 172 boards.  Everyone using one of these boards should say
-	  Y here.
-
 config MVME162_SCC
 	bool "SCC support for MVME162 serial ports"
 	depends on MVME16x && BROKEN
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index b06a7e3..b793163 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -76,6 +76,7 @@ core-$(CONFIG_MVME16x)		+= arch/m68k/mvme16x/
 core-$(CONFIG_BVME6000)		+= arch/m68k/bvme6000/
 core-$(CONFIG_SUN3X)		+= arch/m68k/sun3x/	arch/m68k/sun3/
 core-$(CONFIG_SUN3)		+= arch/m68k/sun3/	arch/m68k/sun3/prom/
+core-$(CONFIG_NATFEAT)		+= arch/m68k/emu/
 core-$(CONFIG_M68040)		+= arch/m68k/fpsp040/
 core-$(CONFIG_M68060)		+= arch/m68k/ifpsp060/
 core-$(CONFIG_M68KFPU_EMU)	+= arch/m68k/math-emu/
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
index 61df1d3..dd0447d 100644
--- a/arch/m68k/amiga/chipram.c
+++ b/arch/m68k/amiga/chipram.c
@@ -33,10 +33,6 @@ void __init amiga_chip_init(void)
     if (!AMIGAHW_PRESENT(CHIP_RAM))
 	return;
 
-    /*
-     *  Remove the first 4 pages where PPC exception handlers will be located
-     */
-    amiga_chip_size -= 0x4000;
     chipram_res.end = amiga_chip_size-1;
     request_resource(&iomem_resource, &chipram_res);
 
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 9fe6fef..1edd950 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -45,8 +45,8 @@ extern int bvme6000_set_clock_mmss (unsigned long);
 extern void bvme6000_reset (void);
 void bvme6000_set_vectors (void);
 
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c, called via bvme6000_process_int() */
+/* Save tick handler routine pointer, will point to xtime_update() in
+ * kernel/timer/timekeeping.c, called via bvme6000_process_int() */
 
 static irq_handler_t tick_handler;
 
diff --git a/arch/m68k/emu/Makefile b/arch/m68k/emu/Makefile
new file mode 100644
index 0000000..7dc2010
--- /dev/null
+++ b/arch/m68k/emu/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for Linux arch/m68k/emu source directory
+#
+
+obj-y			+= natfeat.o
+
+obj-$(CONFIG_NFBLOCK)	+= nfblock.o
+obj-$(CONFIG_NFCON)	+= nfcon.o
+obj-$(CONFIG_NFETH)	+= nfeth.o
diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c
new file mode 100644
index 0000000..2291a7d
--- /dev/null
+++ b/arch/m68k/emu/natfeat.c
@@ -0,0 +1,78 @@
+/*
+ * natfeat.c - ARAnyM hardware support via Native Features (natfeats)
+ *
+ * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
+ *
+ * Reworked for Linux by Roman Zippel <zippel@linux-m68k.org>
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/natfeat.h>
+
+asm("\n"
+"	.global nf_get_id,nf_call\n"
+"nf_get_id:\n"
+"	.short	0x7300\n"
+"	rts\n"
+"nf_call:\n"
+"	.short	0x7301\n"
+"	rts\n"
+"1:	moveq.l	#0,%d0\n"
+"	rts\n"
+"	.section __ex_table,\"a\"\n"
+"	.long	nf_get_id,1b\n"
+"	.long	nf_call,1b\n"
+"	.previous");
+EXPORT_SYMBOL_GPL(nf_get_id);
+EXPORT_SYMBOL_GPL(nf_call);
+
+void nfprint(const char *fmt, ...)
+{
+	static char buf[256];
+	va_list ap;
+	int n;
+
+	va_start(ap, fmt);
+	n = vsnprintf(buf, 256, fmt, ap);
+	nf_call(nf_get_id("NF_STDERR"), buf);
+	va_end(ap);
+}
+
+static void nf_poweroff(void)
+{
+	long id = nf_get_id("NF_SHUTDOWN");
+
+	if (id)
+		nf_call(id);
+}
+
+void nf_init(void)
+{
+	unsigned long id, version;
+	char buf[256];
+
+	id = nf_get_id("NF_VERSION");
+	if (!id)
+		return;
+	version = nf_call(id);
+
+	id = nf_get_id("NF_NAME");
+	if (!id)
+		return;
+	nf_call(id, buf, 256);
+	buf[255] = 0;
+
+	pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16,
+		version & 0xffff);
+
+	mach_power_off = nf_poweroff;
+}
diff --git a/arch/m68k/emu/nfblock.c b/arch/m68k/emu/nfblock.c
new file mode 100644
index 0000000..48e50f8
--- /dev/null
+++ b/arch/m68k/emu/nfblock.c
@@ -0,0 +1,195 @@
+/*
+ * ARAnyM block device driver
+ *
+ * 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/moduleparam.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/slab.h>
+
+#include <asm/natfeat.h>
+
+static long nfhd_id;
+
+enum {
+	/* emulation entry points */
+	NFHD_READ_WRITE = 10,
+	NFHD_GET_CAPACITY = 14,
+
+	/* skip ACSI devices */
+	NFHD_DEV_OFFSET = 8,
+};
+
+static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno,
+				  u32 count, u32 buf)
+{
+	return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno,
+		       count, buf);
+}
+
+static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks,
+				    u32 *blocksize)
+{
+	return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor, blocks,
+		       blocksize);
+}
+
+static LIST_HEAD(nfhd_list);
+
+static int major_num;
+module_param(major_num, int, 0);
+
+struct nfhd_device {
+	struct list_head list;
+	int id;
+	u32 blocks, bsize;
+	int bshift;
+	struct request_queue *queue;
+	struct gendisk *disk;
+};
+
+static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
+{
+	struct nfhd_device *dev = queue->queuedata;
+	struct bio_vec *bvec;
+	int i, dir, len, shift;
+	sector_t sec = bio->bi_sector;
+
+	dir = bio_data_dir(bio);
+	shift = dev->bshift;
+	bio_for_each_segment(bvec, bio, i) {
+		len = bvec->bv_len;
+		len >>= 9;
+		nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
+				bvec_to_phys(bvec));
+		sec += len;
+	}
+	bio_endio(bio, 0);
+	return 0;
+}
+
+static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+	struct nfhd_device *dev = bdev->bd_disk->private_data;
+
+	geo->cylinders = dev->blocks >> (6 - dev->bshift);
+	geo->heads = 4;
+	geo->sectors = 16;
+
+	return 0;
+}
+
+static const struct block_device_operations nfhd_ops = {
+	.owner	= THIS_MODULE,
+	.getgeo	= nfhd_getgeo,
+};
+
+static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
+{
+	struct nfhd_device *dev;
+	int dev_id = id - NFHD_DEV_OFFSET;
+
+	pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id,
+		blocks, bsize);
+
+	if (bsize < 512 || (bsize & (bsize - 1))) {
+		pr_warn("nfhd%u: invalid block size\n", dev_id);
+		return -EINVAL;
+	}
+
+	dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL);
+	if (!dev)
+		goto out;
+
+	dev->id = id;
+	dev->blocks = blocks;
+	dev->bsize = bsize;
+	dev->bshift = ffs(bsize) - 10;
+
+	dev->queue = blk_alloc_queue(GFP_KERNEL);
+	if (dev->queue == NULL)
+		goto free_dev;
+
+	dev->queue->queuedata = dev;
+	blk_queue_make_request(dev->queue, nfhd_make_request);
+	blk_queue_logical_block_size(dev->queue, bsize);
+
+	dev->disk = alloc_disk(16);
+	if (!dev->disk)
+		goto free_queue;
+
+	dev->disk->major = major_num;
+	dev->disk->first_minor = dev_id * 16;
+	dev->disk->fops = &nfhd_ops;
+	dev->disk->private_data = dev;
+	sprintf(dev->disk->disk_name, "nfhd%u", dev_id);
+	set_capacity(dev->disk, (sector_t)blocks * (bsize / 512));
+	dev->disk->queue = dev->queue;
+
+	add_disk(dev->disk);
+
+	list_add_tail(&dev->list, &nfhd_list);
+
+	return 0;
+
+free_queue:
+	blk_cleanup_queue(dev->queue);
+free_dev:
+	kfree(dev);
+out:
+	return -ENOMEM;
+}
+
+static int __init nfhd_init(void)
+{
+	u32 blocks, bsize;
+	int i;
+
+	nfhd_id = nf_get_id("XHDI");
+	if (!nfhd_id)
+		return -ENODEV;
+
+	major_num = register_blkdev(major_num, "nfhd");
+	if (major_num <= 0) {
+		pr_warn("nfhd: unable to get major number\n");
+		return major_num;
+	}
+
+	for (i = NFHD_DEV_OFFSET; i < 24; i++) {
+		if (nfhd_get_capacity(i, 0, &blocks, &bsize))
+			continue;
+		nfhd_init_one(i, blocks, bsize);
+	}
+
+	return 0;
+}
+
+static void __exit nfhd_exit(void)
+{
+	struct nfhd_device *dev, *next;
+
+	list_for_each_entry_safe(dev, next, &nfhd_list, list) {
+		list_del(&dev->list);
+		del_gendisk(dev->disk);
+		put_disk(dev->disk);
+		blk_cleanup_queue(dev->queue);
+		kfree(dev);
+	}
+	unregister_blkdev(major_num, "nfhd");
+}
+
+module_init(nfhd_init);
+module_exit(nfhd_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
new file mode 100644
index 0000000..ab20dc0
--- /dev/null
+++ b/arch/m68k/emu/nfcon.c
@@ -0,0 +1,162 @@
+/*
+ * ARAnyM console driver
+ *
+ * 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/init.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+
+#include <asm/natfeat.h>
+
+static int stderr_id;
+static struct tty_driver *nfcon_tty_driver;
+
+static void nfputs(const char *str, unsigned int count)
+{
+	char buf[68];
+
+	buf[64] = 0;
+	while (count > 64) {
+		memcpy(buf, str, 64);
+		nf_call(stderr_id, buf);
+		str += 64;
+		count -= 64;
+	}
+	memcpy(buf, str, count);
+	buf[count] = 0;
+	nf_call(stderr_id, buf);
+}
+
+static void nfcon_write(struct console *con, const char *str,
+			unsigned int count)
+{
+	nfputs(str, count);
+}
+
+static struct tty_driver *nfcon_device(struct console *con, int *index)
+{
+	*index = 0;
+	return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL;
+}
+
+static struct console nf_console = {
+	.name	= "nfcon",
+	.write	= nfcon_write,
+	.device	= nfcon_device,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+
+static int nfcon_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	return 0;
+}
+
+static void nfcon_tty_close(struct tty_struct *tty, struct file *filp)
+{
+}
+
+static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf,
+			   int count)
+{
+	nfputs(buf, count);
+	return count;
+}
+
+static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	char temp[2] = { ch, 0 };
+
+	nf_call(stderr_id, temp);
+	return 1;
+}
+
+static int nfcon_tty_write_room(struct tty_struct *tty)
+{
+	return 64;
+}
+
+static const struct tty_operations nfcon_tty_ops = {
+	.open		= nfcon_tty_open,
+	.close		= nfcon_tty_close,
+	.write		= nfcon_tty_write,
+	.put_char	= nfcon_tty_put_char,
+	.write_room	= nfcon_tty_write_room,
+};
+
+#ifndef MODULE
+
+static int __init nf_debug_setup(char *arg)
+{
+	if (strcmp(arg, "nfcon"))
+		return 0;
+
+	stderr_id = nf_get_id("NF_STDERR");
+	if (stderr_id) {
+		nf_console.flags |= CON_ENABLED;
+		register_console(&nf_console);
+	}
+
+	return 0;
+}
+
+early_param("debug", nf_debug_setup);
+
+#endif /* !MODULE */
+
+static int __init nfcon_init(void)
+{
+	int res;
+
+	stderr_id = nf_get_id("NF_STDERR");
+	if (!stderr_id)
+		return -ENODEV;
+
+	nfcon_tty_driver = alloc_tty_driver(1);
+	if (!nfcon_tty_driver)
+		return -ENOMEM;
+
+	nfcon_tty_driver->owner = THIS_MODULE;
+	nfcon_tty_driver->driver_name = "nfcon";
+	nfcon_tty_driver->name = "nfcon";
+	nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
+	nfcon_tty_driver->init_termios = tty_std_termios;
+	nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
+
+	tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
+	res = tty_register_driver(nfcon_tty_driver);
+	if (res) {
+		pr_err("failed to register nfcon tty driver\n");
+		put_tty_driver(nfcon_tty_driver);
+		return res;
+	}
+
+	if (!(nf_console.flags & CON_ENABLED))
+		register_console(&nf_console);
+
+	return 0;
+}
+
+static void __exit nfcon_exit(void)
+{
+	unregister_console(&nf_console);
+	tty_unregister_driver(nfcon_tty_driver);
+	put_tty_driver(nfcon_tty_driver);
+}
+
+module_init(nfcon_init);
+module_exit(nfcon_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/m68k/emu/nfeth.c b/arch/m68k/emu/nfeth.c
new file mode 100644
index 0000000..8b6e201
--- /dev/null
+++ b/arch/m68k/emu/nfeth.c
@@ -0,0 +1,270 @@
+/*
+ * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
+ *
+ * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
+ *
+ * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#define DRV_VERSION	"0.3"
+#define DRV_RELDATE	"10/12/2005"
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <asm/natfeat.h>
+#include <asm/virtconvert.h>
+
+enum {
+	GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
+	XIF_INTLEVEL,	/* no parameters, return Interrupt Level in d0 */
+	XIF_IRQ,	/* acknowledge interrupt from host */
+	XIF_START,	/* (ethX), called on 'ifup', start receiver thread */
+	XIF_STOP,	/* (ethX), called on 'ifdown', stop the thread */
+	XIF_READLENGTH,	/* (ethX), return size of network data block to read */
+	XIF_READBLOCK,	/* (ethX, buffer, size), read block of network data */
+	XIF_WRITEBLOCK,	/* (ethX, buffer, size), write block of network data */
+	XIF_GET_MAC,	/* (ethX, buffer, size), return MAC HW addr in buffer */
+	XIF_GET_IPHOST,	/* (ethX, buffer, size), return IP address of host */
+	XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
+	XIF_GET_NETMASK	/* (ethX, buffer, size), return IP netmask */
+};
+
+#define MAX_UNIT	8
+
+/* These identify the driver base version and may not be removed. */
+static const char version[] __devinitdata =
+	KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
+	" S.Opichal, M.Jurik, P.Stehlik\n"
+	KERN_INFO " http://aranym.org/\n";
+
+MODULE_AUTHOR("Milan Jurik");
+MODULE_DESCRIPTION("Atari NFeth driver");
+MODULE_LICENSE("GPL");
+/*
+MODULE_PARM(nfeth_debug, "i");
+MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
+*/
+
+
+static long nfEtherID;
+static int nfEtherIRQ;
+
+struct nfeth_private {
+	int ethX;
+};
+
+static struct net_device *nfeth_dev[MAX_UNIT];
+
+static int nfeth_open(struct net_device *dev)
+{
+	struct nfeth_private *priv = netdev_priv(dev);
+	int res;
+
+	res = nf_call(nfEtherID + XIF_START, priv->ethX);
+	netdev_dbg(dev, "%s: %d\n", __func__, res);
+
+	/* Ready for data */
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int nfeth_stop(struct net_device *dev)
+{
+	struct nfeth_private *priv = netdev_priv(dev);
+
+	/* No more data */
+	netif_stop_queue(dev);
+
+	nf_call(nfEtherID + XIF_STOP, priv->ethX);
+
+	return 0;
+}
+
+/*
+ * Read a packet out of the adapter and pass it to the upper layers
+ */
+static inline void recv_packet(struct net_device *dev)
+{
+	struct nfeth_private *priv = netdev_priv(dev);
+	unsigned short pktlen;
+	struct sk_buff *skb;
+
+	/* read packet length (excluding 32 bit crc) */
+	pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
+
+	netdev_dbg(dev, "%s: %u\n", __func__, pktlen);
+
+	if (!pktlen) {
+		netdev_dbg(dev, "%s: pktlen == 0\n", __func__);
+		dev->stats.rx_errors++;
+		return;
+	}
+
+	skb = dev_alloc_skb(pktlen + 2);
+	if (!skb) {
+		netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n",
+			   __func__);
+		dev->stats.rx_dropped++;
+		return;
+	}
+
+	skb->dev = dev;
+	skb_reserve(skb, 2);		/* 16 Byte align  */
+	skb_put(skb, pktlen);		/* make room */
+	nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
+		pktlen);
+
+	skb->protocol = eth_type_trans(skb, dev);
+	netif_rx(skb);
+	dev->last_rx = jiffies;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += pktlen;
+
+	/* and enqueue packet */
+	return;
+}
+
+static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
+{
+	int i, m, mask;
+
+	mask = nf_call(nfEtherID + XIF_IRQ, 0);
+	for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
+		if (mask & m && nfeth_dev[i]) {
+			recv_packet(nfeth_dev[i]);
+			nf_call(nfEtherID + XIF_IRQ, m);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	unsigned int len;
+	char *data, shortpkt[ETH_ZLEN];
+	struct nfeth_private *priv = netdev_priv(dev);
+
+	data = skb->data;
+	len = skb->len;
+	if (len < ETH_ZLEN) {
+		memset(shortpkt, 0, ETH_ZLEN);
+		memcpy(shortpkt, data, len);
+		data = shortpkt;
+		len = ETH_ZLEN;
+	}
+
+	netdev_dbg(dev, "%s: send %u bytes\n", __func__, len);
+	nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
+		len);
+
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += len;
+
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+static void nfeth_tx_timeout(struct net_device *dev)
+{
+	dev->stats.tx_errors++;
+	netif_wake_queue(dev);
+}
+
+static const struct net_device_ops nfeth_netdev_ops = {
+	.ndo_open		= nfeth_open,
+	.ndo_stop		= nfeth_stop,
+	.ndo_start_xmit		= nfeth_xmit,
+	.ndo_tx_timeout		= nfeth_tx_timeout,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static struct net_device * __init nfeth_probe(int unit)
+{
+	struct net_device *dev;
+	struct nfeth_private *priv;
+	char mac[ETH_ALEN], host_ip[32], local_ip[32];
+	int err;
+
+	if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
+		return NULL;
+
+	dev = alloc_etherdev(sizeof(struct nfeth_private));
+	if (!dev)
+		return NULL;
+
+	dev->irq = nfEtherIRQ;
+	dev->netdev_ops = &nfeth_netdev_ops;
+
+	dev->flags |= NETIF_F_NO_CSUM;
+	memcpy(dev->dev_addr, mac, ETH_ALEN);
+
+	priv = netdev_priv(dev);
+	priv->ethX = unit;
+
+	err = register_netdev(dev);
+	if (err) {
+		free_netdev(dev);
+		return NULL;
+	}
+
+	nf_call(nfEtherID + XIF_GET_IPHOST, unit,
+		host_ip, sizeof(host_ip));
+	nf_call(nfEtherID + XIF_GET_IPATARI, unit,
+		local_ip, sizeof(local_ip));
+
+	netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip,
+		    local_ip, mac);
+
+	return dev;
+}
+
+static int __init nfeth_init(void)
+{
+	long ver;
+	int error, i;
+
+	nfEtherID = nf_get_id("ETHERNET");
+	if (!nfEtherID)
+		return -ENODEV;
+
+	ver = nf_call(nfEtherID + GET_VERSION);
+	pr_info("API %lu\n", ver);
+
+	nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
+	error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
+			    "eth emu", nfeth_interrupt);
+	if (error) {
+		pr_err("request for irq %d failed %d", nfEtherIRQ, error);
+		return error;
+	}
+
+	for (i = 0; i < MAX_UNIT; i++)
+		nfeth_dev[i] = nfeth_probe(i);
+
+	return 0;
+}
+
+static void __exit nfeth_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_UNIT; i++) {
+		if (nfeth_dev[i]) {
+			unregister_netdev(nfeth_dev[0]);
+			free_netdev(nfeth_dev[0]);
+		}
+	}
+	free_irq(nfEtherIRQ, nfeth_interrupt);
+}
+
+module_init(nfeth_init);
+module_exit(nfeth_cleanup);
diff --git a/arch/m68k/include/asm/coldfire.h b/arch/m68k/include/asm/coldfire.h
index 213028c..c94557b 100644
--- a/arch/m68k/include/asm/coldfire.h
+++ b/arch/m68k/include/asm/coldfire.h
@@ -14,39 +14,35 @@
 
 
 /*
- *	Define master clock frequency. This is essentially done at config
- *	time now. No point enumerating dozens of possible clock options
- *	here. Also the peripheral clock (bus clock) divide ratio is set
- *	at config time too.
+ *	Define master clock frequency. This is done at config time now.
+ *	No point enumerating dozens of possible clock options here. And
+ *	in any case new boards come along from time to time that have yet
+ *	another different clocking frequency.
  */
 #ifdef CONFIG_CLOCK_SET
 #define	MCF_CLK		CONFIG_CLOCK_FREQ
-#define	MCF_BUSCLK	(CONFIG_CLOCK_FREQ / CONFIG_CLOCK_DIV)
 #else
 #error "Don't know what your ColdFire CPU clock frequency is??"
 #endif
 
 /*
- *	Define the processor support peripherals base address.
- *	This is generally setup by the boards start up code.
+ *	Define the processor internal peripherals base address.
+ *
+ *	The majority of ColdFire parts use an MBAR register to set
+ *	the base address. Some have an IPSBAR register instead, and it
+ *	has slightly different rules on its size and alignment. Some
+ *	parts have fixed addresses and the internal peripherals cannot
+ *	be relocated in the CPU address space.
+ *
+ *	The value of MBAR or IPSBAR is config time selectable, we no
+ *	longer hard define it here. No MBAR or IPSBAR will be defined if
+ *	this part has a fixed peripheral address map.
  */
-#define	MCF_MBAR	0x10000000
-#define	MCF_MBAR2	0x80000000
-#if defined(CONFIG_M54xx)
-#define	MCF_IPSBAR	MCF_MBAR
-#elif defined(CONFIG_M520x)
-#define	MCF_IPSBAR	0xFC000000
-#else
-#define	MCF_IPSBAR	0x40000000
+#ifdef CONFIG_MBAR
+#define	MCF_MBAR	CONFIG_MBAR
 #endif
-
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x)
-#undef MCF_MBAR
-#define	MCF_MBAR	MCF_IPSBAR
-#elif defined(CONFIG_M532x)
-#undef MCF_MBAR
-#define MCF_MBAR	0x00000000
+#ifdef CONFIG_IPSBAR
+#define	MCF_IPSBAR	CONFIG_IPSBAR
 #endif
 
 /****************************************************************************/
diff --git a/arch/m68k/include/asm/m5206sim.h b/arch/m68k/include/asm/m5206sim.h
index 561b03b..9015ead 100644
--- a/arch/m68k/include/asm/m5206sim.h
+++ b/arch/m68k/include/asm/m5206sim.h
@@ -14,6 +14,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5206)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		MCF_CLK
 
 #include <asm/m52xxacr.h>
 
@@ -48,14 +49,14 @@
 #define	MCFSIM_SWIVR		0x42		/* SW Watchdog intr reg (r/w) */
 #define	MCFSIM_SWSR		0x43		/* SW Watchdog service (r/w) */
 
-#define	MCFSIM_DCRR		0x46		/* DRAM Refresh reg (r/w) */
-#define	MCFSIM_DCTR		0x4a		/* DRAM Timing reg (r/w) */
-#define	MCFSIM_DAR0		0x4c		/* DRAM 0 Address reg(r/w) */
-#define	MCFSIM_DMR0		0x50		/* DRAM 0 Mask reg (r/w) */
-#define	MCFSIM_DCR0		0x57		/* DRAM 0 Control reg (r/w) */
-#define	MCFSIM_DAR1		0x58		/* DRAM 1 Address reg (r/w) */
-#define	MCFSIM_DMR1		0x5c		/* DRAM 1 Mask reg (r/w) */
-#define	MCFSIM_DCR1		0x63		/* DRAM 1 Control reg (r/w) */
+#define	MCFSIM_DCRR		(MCF_MBAR + 0x46) /* DRAM Refresh reg (r/w) */
+#define	MCFSIM_DCTR		(MCF_MBAR + 0x4a) /* DRAM Timing reg (r/w) */
+#define	MCFSIM_DAR0		(MCF_MBAR + 0x4c) /* DRAM 0 Address reg(r/w) */
+#define	MCFSIM_DMR0		(MCF_MBAR + 0x50) /* DRAM 0 Mask reg (r/w) */
+#define	MCFSIM_DCR0		(MCF_MBAR + 0x57) /* DRAM 0 Control reg (r/w) */
+#define	MCFSIM_DAR1		(MCF_MBAR + 0x58) /* DRAM 1 Address reg (r/w) */
+#define	MCFSIM_DMR1		(MCF_MBAR + 0x5c) /* DRAM 1 Mask reg (r/w) */
+#define	MCFSIM_DCR1		(MCF_MBAR + 0x63) /* DRAM 1 Control reg (r/w) */
 
 #define	MCFSIM_CSAR0		0x64		/* CS 0 Address 0 reg (r/w) */
 #define	MCFSIM_CSMR0		0x68		/* CS 0 Mask 0 reg (r/w) */
@@ -89,9 +90,15 @@
 #define	MCFSIM_PAR		0xcb		/* Pin Assignment reg (r/w) */
 #endif
 
+#define	MCFTIMER_BASE1		(MCF_MBAR + 0x100)	/* Base of TIMER1 */
+#define	MCFTIMER_BASE2		(MCF_MBAR + 0x120)	/* Base of TIMER2 */
+
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x1c5)	/* Parallel Direction (r/w) */
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x1c9)	/* Parallel Port Value (r/w) */
 
+#define	MCFDMA_BASE0		(MCF_MBAR + 0x200)	/* Base address DMA 0 */
+#define	MCFDMA_BASE1		(MCF_MBAR + 0x240)	/* Base address DMA 1 */
+
 #if defined(CONFIG_NETtel)
 #define	MCFUART_BASE1		0x180		/* Base address of UART1 */
 #define	MCFUART_BASE2		0x140		/* Base address of UART2 */
diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h
index 88ed823..55d5a4c5 100644
--- a/arch/m68k/include/asm/m520xsim.h
+++ b/arch/m68k/include/asm/m520xsim.h
@@ -13,13 +13,14 @@
 
 #define	CPU_NAME		"COLDFIRE(m520x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
  *  Define the 520x SIM register set addresses.
  */
-#define MCFICM_INTC0        0x48000     /* Base for Interrupt Ctrl 0 */
+#define MCFICM_INTC0        0xFC048000  /* Base for Interrupt Ctrl 0 */
 #define MCFINTC_IPRH        0x00        /* Interrupt pending 32-63 */
 #define MCFINTC_IPRL        0x04        /* Interrupt pending 1-31 */
 #define MCFINTC_IMRH        0x08        /* Interrupt mask 32-63 */
@@ -35,9 +36,9 @@
  *  address to the SIMR and CIMR registers (not offsets into IPSBAR).
  *  The 520x family only has a single INTC unit.
  */
-#define MCFINTC0_SIMR       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_SIMR)
-#define MCFINTC0_CIMR       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_CIMR)
-#define	MCFINTC0_ICR0       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0)
+#define MCFINTC0_SIMR       (MCFICM_INTC0 + MCFINTC_SIMR)
+#define MCFINTC0_CIMR       (MCFICM_INTC0 + MCFINTC_CIMR)
+#define	MCFINTC0_ICR0       (MCFICM_INTC0 + MCFINTC_ICR0)
 #define MCFINTC1_SIMR       (0)
 #define MCFINTC1_CIMR       (0)
 #define	MCFINTC1_ICR0       (0)
@@ -52,19 +53,22 @@
 /*
  *  SDRAM configuration registers.
  */
-#define MCFSIM_SDMR         0x000a8000	/* SDRAM Mode/Extended Mode Register */
-#define MCFSIM_SDCR         0x000a8004	/* SDRAM Control Register */
-#define MCFSIM_SDCFG1       0x000a8008	/* SDRAM Configuration Register 1 */
-#define MCFSIM_SDCFG2       0x000a800c	/* SDRAM Configuration Register 2 */
-#define MCFSIM_SDCS0        0x000a8110	/* SDRAM Chip Select 0 Configuration */
-#define MCFSIM_SDCS1        0x000a8114	/* SDRAM Chip Select 1 Configuration */
+#define MCFSIM_SDMR         0xFC0a8000	/* SDRAM Mode/Extended Mode Register */
+#define MCFSIM_SDCR         0xFC0a8004	/* SDRAM Control Register */
+#define MCFSIM_SDCFG1       0xFC0a8008	/* SDRAM Configuration Register 1 */
+#define MCFSIM_SDCFG2       0xFC0a800c	/* SDRAM Configuration Register 2 */
+#define MCFSIM_SDCS0        0xFC0a8110	/* SDRAM Chip Select 0 Configuration */
+#define MCFSIM_SDCS1        0xFC0a8114	/* SDRAM Chip Select 1 Configuration */
 
 /*
  * EPORT and GPIO registers.
  */
+#define MCFEPORT_EPPAR			0xFC088000
 #define MCFEPORT_EPDDR			0xFC088002
+#define MCFEPORT_EPIER			0xFC088003
 #define MCFEPORT_EPDR			0xFC088004
 #define MCFEPORT_EPPDR			0xFC088005
+#define MCFEPORT_EPFR			0xFC088006
 
 #define MCFGPIO_PODR_BUSCTL		0xFC0A4000
 #define MCFGPIO_PODR_BE			0xFC0A4001
@@ -119,10 +123,10 @@
 #define MCFGPIO_IRQ_MAX			8
 #define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
 
-#define MCF_GPIO_PAR_UART                   (0xA4036)
-#define MCF_GPIO_PAR_FECI2C                 (0xA4033)
-#define MCF_GPIO_PAR_QSPI                   (0xA4034)
-#define MCF_GPIO_PAR_FEC                    (0xA4038)
+#define MCF_GPIO_PAR_UART		0xFC0A4036
+#define MCF_GPIO_PAR_FECI2C		0xFC0A4033
+#define MCF_GPIO_PAR_QSPI		0xFC0A4034
+#define MCF_GPIO_PAR_FEC		0xFC0A4038
 
 #define MCF_GPIO_PAR_UART_PAR_URXD0         (0x0001)
 #define MCF_GPIO_PAR_UART_PAR_UTXD0         (0x0002)
@@ -134,11 +138,23 @@
 #define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2   (0x04)
 
 /*
+ *  PIT timer module.
+ */
+#define	MCFPIT_BASE1		0xFC080000	/* Base address of TIMER1 */
+#define	MCFPIT_BASE2		0xFC084000	/* Base address of TIMER2 */
+
+/*
  *  UART module.
  */
-#define MCFUART_BASE1		0x60000		/* Base address of UART1 */
-#define MCFUART_BASE2		0x64000		/* Base address of UART2 */
-#define MCFUART_BASE3		0x68000		/* Base address of UART2 */
+#define MCFUART_BASE1		0xFC060000	/* Base address of UART1 */
+#define MCFUART_BASE2		0xFC064000	/* Base address of UART2 */
+#define MCFUART_BASE3		0xFC068000	/* Base address of UART2 */
+
+/*
+ *  FEC module.
+ */
+#define	MCFFEC_BASE		0xFC030000	/* Base of FEC ethernet */
+#define	MCFFEC_SIZE		0x800		/* Register set size */
 
 /*
  *  Reset Controll Unit.
diff --git a/arch/m68k/include/asm/m523xsim.h b/arch/m68k/include/asm/m523xsim.h
index 4ad7a00..8996df6 100644
--- a/arch/m68k/include/asm/m523xsim.h
+++ b/arch/m68k/include/asm/m523xsim.h
@@ -13,14 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m523x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
  *	Define the 523x SIM register set addresses.
  */
-#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
-#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC0		(MCF_IPSBAR + 0x0c00)	/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		(MCF_IPSBAR + 0x0d00)	/* Base for Interrupt Ctrl 0 */
+
 #define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -39,11 +41,11 @@
 /*
  *	SDRAM configuration registers.
  */
-#define	MCFSIM_DCR		0x44		/* SDRAM control */
-#define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
-#define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x44)	/* Control */
+#define	MCFSIM_DACR0		(MCF_IPSBAR + 0x48)	/* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x4c)	/* Address mask 0 */
+#define	MCFSIM_DACR1		(MCF_IPSBAR + 0x50)	/* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x54)	/* Address mask 1 */
 
 /*
  *  Reset Controll Unit (relative to IPSBAR).
@@ -57,10 +59,19 @@
 /*
  *  UART module.
  */
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+#define MCFUART_BASE1		(MCF_IPSBAR + 0x200)
+#define MCFUART_BASE2		(MCF_IPSBAR + 0x240)
+#define MCFUART_BASE3		(MCF_IPSBAR + 0x280)
+
+/*
+ *  FEC ethernet module.
+ */
+#define	MCFFEC_BASE		(MCF_IPSBAR + 0x1000)
+#define	MCFFEC_SIZE		0x800
 
+/*
+ *  GPIO module.
+ */
 #define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
 #define MCFGPIO_PODR_DATAH	(MCF_IPSBAR + 0x100001)
 #define MCFGPIO_PODR_DATAL	(MCF_IPSBAR + 0x100002)
@@ -118,12 +129,22 @@
 #define MCFGPIO_PCLRR_ETPU	(MCF_IPSBAR + 0x10003C)
 
 /*
- * EPort
+ * PIT timer base addresses.
  */
+#define	MCFPIT_BASE1		(MCF_IPSBAR + 0x150000)
+#define	MCFPIT_BASE2		(MCF_IPSBAR + 0x160000)
+#define	MCFPIT_BASE3		(MCF_IPSBAR + 0x170000)
+#define	MCFPIT_BASE4		(MCF_IPSBAR + 0x180000)
 
+/*
+ * EPort
+ */
+#define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x130000)
 #define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x130002)
+#define MCFEPORT_EPIER		(MCF_IPSBAR + 0x130003)
 #define MCFEPORT_EPDR		(MCF_IPSBAR + 0x130004)
 #define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x130005)
+#define MCFEPORT_EPFR		(MCF_IPSBAR + 0x130006)
 
 /*
  * Generic GPIO support
@@ -143,5 +164,14 @@
 */
 #define	MCFGPIO_PAR_QSPI	(MCF_IPSBAR + 0x10004A)
 #define	MCFGPIO_PAR_TIMER	(MCF_IPSBAR + 0x10004C)
+
+/*
+ * DMA unit base addresses.
+ */
+#define	MCFDMA_BASE0		(MCF_IPSBAR + 0x100)
+#define	MCFDMA_BASE1		(MCF_IPSBAR + 0x140)
+#define	MCFDMA_BASE2		(MCF_IPSBAR + 0x180)
+#define	MCFDMA_BASE3		(MCF_IPSBAR + 0x1C0)
+
 /****************************************************************************/
 #endif	/* m523xsim_h */
diff --git a/arch/m68k/include/asm/m5249sim.h b/arch/m68k/include/asm/m5249sim.h
index 4908b11..805714c 100644
--- a/arch/m68k/include/asm/m5249sim.h
+++ b/arch/m68k/include/asm/m5249sim.h
@@ -13,10 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m5249)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
+ *	The 5249 has a second MBAR region, define its address.
+ */
+#define MCF_MBAR2		0x80000000
+
+/*
  *	Define the 5249 SIM register set addresses.
  */
 #define	MCFSIM_RSR		0x00		/* Reset Status reg (r/w) */
@@ -55,11 +61,17 @@
 #define MCFSIM_CSMR3		0xa8		/* CS 3 Mask reg (r/w) */
 #define MCFSIM_CSCR3		0xae		/* CS 3 Control reg (r/w) */
 
-#define MCFSIM_DCR		0x100		/* DRAM Control reg (r/w) */
-#define MCFSIM_DACR0		0x108		/* DRAM 0 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR0		0x10c		/* DRAM 0 Mask reg (r/w) */
-#define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
+#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
+#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM 0 Addr/Ctrl */
+#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM 0 Mask */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM 1 Addr/Ctrl */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM 1 Mask */
+
+/*
+ *	Timer module.
+ */
+#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
+#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
 
 /*
  *	UART module.
@@ -68,6 +80,14 @@
 #define MCFUART_BASE2		0x200           /* Base address of UART2 */
 
 /*
+ *	DMA unit base addresses.
+ */
+#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
+#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
+#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
+#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
+
+/*
  *	Some symbol defines for the above...
  */
 #define	MCFSIM_SWDICR		MCFSIM_ICR0	/* Watchdog timer ICR */
diff --git a/arch/m68k/include/asm/m5272sim.h b/arch/m68k/include/asm/m5272sim.h
index b7cc50a..759c2b0 100644
--- a/arch/m68k/include/asm/m5272sim.h
+++ b/arch/m68k/include/asm/m5272sim.h
@@ -14,6 +14,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5272)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		MCF_CLK
 
 #include <asm/m52xxacr.h>
 
@@ -80,6 +81,13 @@
 #define	MCFSIM_PCDAT		(MCF_MBAR + 0x96) /* Port C Data (r/w) */
 #define	MCFSIM_PDCNT		(MCF_MBAR + 0x98) /* Port D Control (r/w) */
 
+#define	MCFDMA_BASE0		(MCF_MBAR + 0xe0) /* Base address DMA 0 */
+
+#define	MCFTIMER_BASE1		(MCF_MBAR + 0x200) /* Base address TIMER1 */
+#define	MCFTIMER_BASE2		(MCF_MBAR + 0x220) /* Base address TIMER2 */
+#define	MCFTIMER_BASE3		(MCF_MBAR + 0x240) /* Base address TIMER4 */
+#define	MCFTIMER_BASE4		(MCF_MBAR + 0x260) /* Base address TIMER3 */
+
 /*
  *	Define system peripheral IRQ usage.
  */
diff --git a/arch/m68k/include/asm/m527xsim.h b/arch/m68k/include/asm/m527xsim.h
index e8042e8..74855a6 100644
--- a/arch/m68k/include/asm/m527xsim.h
+++ b/arch/m68k/include/asm/m527xsim.h
@@ -13,14 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m527x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
  *	Define the 5270/5271 SIM register set addresses.
  */
-#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
-#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 1 */
+#define	MCFICM_INTC0		(MCF_IPSBAR + 0x0c00)	/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		(MCF_IPSBAR + 0x0d00)	/* Base for Interrupt Ctrl 1 */
+
 #define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -42,29 +44,45 @@
  *	SDRAM configuration registers.
  */
 #ifdef CONFIG_M5271
-#define	MCFSIM_DCR		0x40		/* SDRAM control */
-#define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
-#define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x40)	/* Control */
+#define	MCFSIM_DACR0		(MCF_IPSBAR + 0x48)	/* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x4c)	/* Address mask 0 */
+#define	MCFSIM_DACR1		(MCF_IPSBAR + 0x50)	/* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x54)	/* Address mask 1 */
 #endif
 #ifdef CONFIG_M5275
-#define	MCFSIM_DMR		0x40		/* SDRAM mode */
-#define	MCFSIM_DCR		0x44		/* SDRAM control */
-#define	MCFSIM_DCFG1		0x48		/* SDRAM configuration 1 */
-#define	MCFSIM_DCFG2		0x4c		/* SDRAM configuration 2 */
-#define	MCFSIM_DBAR0		0x50		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x54		/* SDRAM address mask 0 */
-#define	MCFSIM_DBAR1		0x58		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x5c		/* SDRAM address mask 1 */
+#define	MCFSIM_DMR		(MCF_IPSBAR + 0x40)	/* Mode */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x44)	/* Control */
+#define	MCFSIM_DCFG1		(MCF_IPSBAR + 0x48)	/* Configuration 1 */
+#define	MCFSIM_DCFG2		(MCF_IPSBAR + 0x4c)	/* Configuration 2 */
+#define	MCFSIM_DBAR0		(MCF_IPSBAR + 0x50)	/* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x54)	/* Address mask 0 */
+#define	MCFSIM_DBAR1		(MCF_IPSBAR + 0x58)	/* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x5c)	/* Address mask 1 */
 #endif
 
 /*
+ *	DMA unit base addresses.
+ */
+#define	MCFDMA_BASE0		(MCF_IPSBAR + 0x100)
+#define	MCFDMA_BASE1		(MCF_IPSBAR + 0x140)
+#define	MCFDMA_BASE2		(MCF_IPSBAR + 0x180)
+#define	MCFDMA_BASE3		(MCF_IPSBAR + 0x1C0)
+
+/*
  *	UART module.
  */
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+#define MCFUART_BASE1		(MCF_IPSBAR + 0x200)
+#define MCFUART_BASE2		(MCF_IPSBAR + 0x240)
+#define MCFUART_BASE3		(MCF_IPSBAR + 0x280)
+
+/*
+ *	FEC ethernet module.
+ */
+#define	MCFFEC_BASE0		(MCF_IPSBAR + 0x1000)
+#define	MCFFEC_SIZE0		0x800
+#define	MCFFEC_BASE1		(MCF_IPSBAR + 0x1800)
+#define	MCFFEC_SIZE1		0x800
 
 #ifdef CONFIG_M5271
 #define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
@@ -231,14 +249,22 @@
 #endif
 
 /*
- * EPort
+ * PIT timer base addresses.
  */
+#define	MCFPIT_BASE1		(MCF_IPSBAR + 0x150000)
+#define	MCFPIT_BASE2		(MCF_IPSBAR + 0x160000)
+#define	MCFPIT_BASE3		(MCF_IPSBAR + 0x170000)
+#define	MCFPIT_BASE4		(MCF_IPSBAR + 0x180000)
 
+/*
+ * EPort
+ */
+#define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x130000)
 #define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x130002)
+#define MCFEPORT_EPIER		(MCF_IPSBAR + 0x130003)
 #define MCFEPORT_EPDR		(MCF_IPSBAR + 0x130004)
 #define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x130005)
-
-
+#define MCFEPORT_EPFR		(MCF_IPSBAR + 0x130006)
 
 /*
  *	GPIO pins setups to enable the UARTs.
diff --git a/arch/m68k/include/asm/m528xsim.h b/arch/m68k/include/asm/m528xsim.h
index a6d2f4d..d798bd5 100644
--- a/arch/m68k/include/asm/m528xsim.h
+++ b/arch/m68k/include/asm/m528xsim.h
@@ -13,14 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m528x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		MCF_CLK
 
 #include <asm/m52xxacr.h>
 
 /*
  *	Define the 5280/5282 SIM register set addresses.
  */
-#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
-#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC0		(MCF_IPSBAR + 0x0c00)	/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		(MCF_IPSBAR + 0x0d00)	/* Base for Interrupt Ctrl 0 */
+
 #define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -39,18 +41,32 @@
 /*
  *	SDRAM configuration registers.
  */
-#define	MCFSIM_DCR		0x44		/* SDRAM control */
-#define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
-#define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x00000044) /* Control */
+#define	MCFSIM_DACR0		(MCF_IPSBAR + 0x00000048) /* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x0000004c) /* Address mask 0 */
+#define	MCFSIM_DACR1		(MCF_IPSBAR + 0x00000050) /* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x00000054) /* Address mask 1 */
+
+/*
+ *	DMA unit base addresses.
+ */
+#define	MCFDMA_BASE0		(MCF_IPSBAR + 0x00000100)
+#define	MCFDMA_BASE1		(MCF_IPSBAR + 0x00000140)
+#define	MCFDMA_BASE2		(MCF_IPSBAR + 0x00000180)
+#define	MCFDMA_BASE3		(MCF_IPSBAR + 0x000001C0)
 
 /*
  *	UART module.
  */
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+#define	MCFUART_BASE1		(MCF_IPSBAR + 0x00000200)
+#define	MCFUART_BASE2		(MCF_IPSBAR + 0x00000240)
+#define	MCFUART_BASE3		(MCF_IPSBAR + 0x00000280)
+
+/*
+ *	FEC ethernet module.
+ */
+#define	MCFFEC_BASE		(MCF_IPSBAR + 0x00001000)
+#define	MCFFEC_SIZE		0x800
 
 /*
  * 	GPIO registers
@@ -163,6 +179,14 @@
 #define MCFGPIO_PUAPAR		(MCF_IPSBAR + 0x0010005C)
 
 /*
+ * PIT timer base addresses.
+ */
+#define	MCFPIT_BASE1		(MCF_IPSBAR + 0x00150000)
+#define	MCFPIT_BASE2		(MCF_IPSBAR + 0x00160000)
+#define	MCFPIT_BASE3		(MCF_IPSBAR + 0x00170000)
+#define	MCFPIT_BASE4		(MCF_IPSBAR + 0x00180000)
+
+/*
  * 	Edge Port registers
  */
 #define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x00130000)
diff --git a/arch/m68k/include/asm/m5307sim.h b/arch/m68k/include/asm/m5307sim.h
index 0bf5739..4c94c01 100644
--- a/arch/m68k/include/asm/m5307sim.h
+++ b/arch/m68k/include/asm/m5307sim.h
@@ -16,6 +16,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5307)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m53xxacr.h>
 
@@ -89,16 +90,30 @@
 #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
 #endif /* CONFIG_OLDMASK */
 
-#define MCFSIM_DCR		0x100		/* DRAM Control reg (r/w) */
-#define MCFSIM_DACR0		0x108		/* DRAM 0 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR0		0x10c		/* DRAM 0 Mask reg (r/w) */
-#define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
+#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
+#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM Addr/Ctrl 0 */
+#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM Mask 0 */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM Addr/Ctrl 1 */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM Mask 1 */
+
+/*
+ *  Timer module.
+ */
+#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
+#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
 
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x244)
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
 /*
+ *  DMA unit base addresses.
+ */
+#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
+#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
+#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
+#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
+
+/*
  *  UART module.
  */
 #if defined(CONFIG_NETtel) || defined(CONFIG_SECUREEDGEMP3)
diff --git a/arch/m68k/include/asm/m532xsim.h b/arch/m68k/include/asm/m532xsim.h
index e6470f8..ba4cc78 100644
--- a/arch/m68k/include/asm/m532xsim.h
+++ b/arch/m68k/include/asm/m532xsim.h
@@ -11,6 +11,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m532x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 3)
 
 #include <asm/m53xxacr.h>
 
@@ -85,6 +86,14 @@
 #define MCFUART_BASE2		0xFC064000	/* Base address of UART2 */
 #define MCFUART_BASE3		0xFC068000	/* Base address of UART3 */
 
+/*
+ *  Timer module.
+ */
+#define MCFTIMER_BASE1		0xFC070000	/* Base address of TIMER1 */
+#define MCFTIMER_BASE2		0xFC074000	/* Base address of TIMER2 */
+#define MCFTIMER_BASE3		0xFC078000	/* Base address of TIMER3 */
+#define MCFTIMER_BASE4		0xFC07C000	/* Base address of TIMER4 */
+
 /*********************************************************************
  *
  * Reset Controller Module
diff --git a/arch/m68k/include/asm/m5407sim.h b/arch/m68k/include/asm/m5407sim.h
index 75f5c28..762c58c 100644
--- a/arch/m68k/include/asm/m5407sim.h
+++ b/arch/m68k/include/asm/m5407sim.h
@@ -16,6 +16,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5407)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m54xxacr.h>
 
@@ -72,11 +73,17 @@
 #define MCFSIM_CSMR7		0xd8		/* CS 7 Mask reg (r/w) */
 #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
 
-#define MCFSIM_DCR		0x100		/* DRAM Control reg (r/w) */
-#define MCFSIM_DACR0		0x108		/* DRAM 0 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR0		0x10c		/* DRAM 0 Mask reg (r/w) */
-#define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
+#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
+#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM 0 Addr/Ctrl */
+#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM 0 Mask */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM 1 Addr/Ctrl */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM 1 Mask */
+
+/*
+ *	Timer module.
+ */
+#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
+#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
 
 #define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
 #define MCFUART_BASE2		0x200           /* Base address of UART2 */
@@ -85,6 +92,14 @@
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
 /*
+ *	DMA unit base addresses.
+ */
+#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
+#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
+#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
+#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
+
+/*
  * Generic GPIO support
  */
 #define MCFGPIO_PIN_MAX			16
diff --git a/arch/m68k/include/asm/m54xxsim.h b/arch/m68k/include/asm/m54xxsim.h
index 462ae53..1ed8bfb 100644
--- a/arch/m68k/include/asm/m54xxsim.h
+++ b/arch/m68k/include/asm/m54xxsim.h
@@ -7,6 +7,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m54xx)"
 #define	CPU_INSTR_PER_JIFFY	2
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m54xxacr.h>
 
@@ -15,7 +16,8 @@
 /*
  *      Interrupt Controller Registers
  */
-#define MCFICM_INTC0		0x0700		/* Base for Interrupt Ctrl 0 */
+#define MCFICM_INTC0		(MCF_MBAR + 0x700) 	/* Base for Interrupt Ctrl 0 */
+
 #define MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -48,6 +50,16 @@
 #define MCFGPIO_IRQ_VECBASE	-1
 
 /*
+ *	EDGE Port support.
+ */
+#define	MCFEPORT_EPPAR		(MCF_MBAR + 0xf00)	/* Pin assignment */
+#define	MCFEPORT_EPDDR		(MCF_MBAR + 0xf04)	/* Data direction */
+#define	MCFEPORT_EPIER		(MCF_MBAR + 0xf05)	/* Interrupt enable */
+#define	MCFEPORT_EPDR		(MCF_MBAR + 0xf08)	/* Port data (w) */
+#define	MCFEPORT_EPPDR		(MCF_MBAR + 0xf09)	/* Port data (r) */
+#define	MCFEPORT_EPFR		(MCF_MBAR + 0xf0c)	/* Flags */
+
+/*
  *	Some PSC related definitions
  */
 #define MCF_PAR_PSC(x)		(0x000A4F-((x)&0x3))
diff --git a/arch/m68k/include/asm/mcfdma.h b/arch/m68k/include/asm/mcfdma.h
index 705c52c..10bc7e3 100644
--- a/arch/m68k/include/asm/mcfdma.h
+++ b/arch/m68k/include/asm/mcfdma.h
@@ -11,29 +11,6 @@
 #define	mcfdma_h
 /****************************************************************************/
 
-
-/*
- *	Get address specific defines for this Coldfire member.
- */
-#if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
-#define	MCFDMA_BASE0		0x200		/* Base address of DMA 0 */
-#define	MCFDMA_BASE1		0x240		/* Base address of DMA 1 */
-#elif defined(CONFIG_M5272)
-#define	MCFDMA_BASE0		0x0e0		/* Base address of DMA 0 */
-#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
-/* These are relative to the IPSBAR, not MBAR */
-#define	MCFDMA_BASE0		0x100		/* Base address of DMA 0 */
-#define	MCFDMA_BASE1		0x140		/* Base address of DMA 1 */
-#define	MCFDMA_BASE2		0x180		/* Base address of DMA 2 */
-#define	MCFDMA_BASE3		0x1C0		/* Base address of DMA 3 */
-#elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
-#define	MCFDMA_BASE0		0x300		/* Base address of DMA 0 */
-#define	MCFDMA_BASE1		0x340		/* Base address of DMA 1 */
-#define	MCFDMA_BASE2		0x380		/* Base address of DMA 2 */
-#define	MCFDMA_BASE3		0x3C0		/* Base address of DMA 3 */
-#endif
-
-
 #if !defined(CONFIG_M5272)
 
 /*
diff --git a/arch/m68k/include/asm/mcfpit.h b/arch/m68k/include/asm/mcfpit.h
index f570cf6..9fd321c 100644
--- a/arch/m68k/include/asm/mcfpit.h
+++ b/arch/m68k/include/asm/mcfpit.h
@@ -11,22 +11,8 @@
 #define	mcfpit_h
 /****************************************************************************/
 
-
-/*
- *	Get address specific defines for the 5270/5271, 5280/5282, and 5208.
- */
-#if defined(CONFIG_M520x)
-#define	MCFPIT_BASE1		0x00080000	/* Base address of TIMER1 */
-#define	MCFPIT_BASE2		0x00084000	/* Base address of TIMER2 */
-#else
-#define	MCFPIT_BASE1		0x00150000	/* Base address of TIMER1 */
-#define	MCFPIT_BASE2		0x00160000	/* Base address of TIMER2 */
-#define	MCFPIT_BASE3		0x00170000	/* Base address of TIMER3 */
-#define	MCFPIT_BASE4		0x00180000	/* Base address of TIMER4 */
-#endif
-
 /*
- *	Define the PIT timer register set addresses.
+ *	Define the PIT timer register address offsets.
  */
 #define	MCFPIT_PCSR		0x0		/* PIT control register */
 #define	MCFPIT_PMR		0x2		/* PIT modulus register */
diff --git a/arch/m68k/include/asm/mcftimer.h b/arch/m68k/include/asm/mcftimer.h
index 0f90f6d..92b276f 100644
--- a/arch/m68k/include/asm/mcftimer.h
+++ b/arch/m68k/include/asm/mcftimer.h
@@ -12,29 +12,6 @@
 #define	mcftimer_h
 /****************************************************************************/
 
-
-/*
- *	Get address specific defines for this ColdFire member.
- */
-#if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
-#define	MCFTIMER_BASE1		0x100		/* Base address of TIMER1 */
-#define	MCFTIMER_BASE2		0x120		/* Base address of TIMER2 */
-#elif defined(CONFIG_M5272)
-#define MCFTIMER_BASE1		0x200           /* Base address of TIMER1 */
-#define MCFTIMER_BASE2		0x220           /* Base address of TIMER2 */
-#define MCFTIMER_BASE3		0x240           /* Base address of TIMER4 */
-#define MCFTIMER_BASE4		0x260           /* Base address of TIMER3 */
-#elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
-#define MCFTIMER_BASE1		0x140           /* Base address of TIMER1 */
-#define MCFTIMER_BASE2		0x180           /* Base address of TIMER2 */
-#elif defined(CONFIG_M532x)
-#define MCFTIMER_BASE1		0xfc070000	/* Base address of TIMER1 */
-#define MCFTIMER_BASE2		0xfc074000	/* Base address of TIMER2 */
-#define MCFTIMER_BASE3		0xfc078000	/* Base address of TIMER3 */
-#define MCFTIMER_BASE4		0xfc07c000	/* Base address of TIMER4 */
-#endif
-
-
 /*
  *	Define the TIMER register set addresses.
  */
diff --git a/arch/m68k/include/asm/natfeat.h b/arch/m68k/include/asm/natfeat.h
new file mode 100644
index 0000000..a3521b8
--- /dev/null
+++ b/arch/m68k/include/asm/natfeat.h
@@ -0,0 +1,22 @@
+/*
+ * ARAnyM hardware support via Native Features (natfeats)
+ *
+ * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#ifndef _NATFEAT_H
+#define _NATFEAT_H
+
+long nf_get_id(const char *feature_name);
+long nf_call(long id, ...);
+
+void nf_init(void);
+void nf_shutdown(void);
+
+void nfprint(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
+
+# endif /* _NATFEAT_H */
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h
index 278c69b..f111b02 100644
--- a/arch/m68k/include/asm/processor.h
+++ b/arch/m68k/include/asm/processor.h
@@ -113,6 +113,8 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 	wrusp(usp);
 }
 
+extern int handle_kernel_fault(struct pt_regs *regs);
+
 #else
 
 /*
diff --git a/arch/m68k/include/asm/types.h b/arch/m68k/include/asm/types.h
index 6441cb5..10ad92f 100644
--- a/arch/m68k/include/asm/types.h
+++ b/arch/m68k/include/asm/types.h
@@ -25,9 +25,6 @@ typedef unsigned short umode_t;
 
 #ifndef __ASSEMBLY__
 
-/* DMA addresses are always 32-bits wide */
-
-typedef u32 dma_addr_t;
 typedef u32 dma64_addr_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index b3963ab..334d836 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -42,6 +42,7 @@
 #ifdef CONFIG_SUN3X
 #include <asm/dvma.h>
 #endif
+#include <asm/natfeat.h>
 
 #if !FPSTATESIZE || !NR_IRQS
 #warning No CPU/platform type selected, your kernel will not work!
@@ -324,6 +325,10 @@ void __init setup_arch(char **cmdline_p)
 		panic("No configuration setup");
 	}
 
+#ifdef CONFIG_NATFEAT
+	nf_init();
+#endif
+
 	paging_init();
 
 #ifndef CONFIG_SUN3
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index d12c3b0..a0afc23 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -42,6 +42,7 @@
 #include <linux/personality.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
+#include <linux/module.h>
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
@@ -51,7 +52,7 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-const int frame_extra_sizes[16] = {
+static const int frame_extra_sizes[16] = {
   [1]	= -1, /* sizeof(((struct frame *)0)->un.fmt1), */
   [2]	= sizeof(((struct frame *)0)->un.fmt2),
   [3]	= sizeof(((struct frame *)0)->un.fmt3),
@@ -69,6 +70,27 @@ const int frame_extra_sizes[16] = {
   [15]	= -1, /* sizeof(((struct frame *)0)->un.fmtf), */
 };
 
+int handle_kernel_fault(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+	struct pt_regs *tregs;
+
+	/* Are we prepared to handle this kernel fault? */
+	fixup = search_exception_tables(regs->pc);
+	if (!fixup)
+		return 0;
+
+	/* Create a new four word stack frame, discarding the old one. */
+	regs->stkadj = frame_extra_sizes[regs->format];
+	tregs =	(struct pt_regs *)((long)regs + regs->stkadj);
+	tregs->vector = regs->vector;
+	tregs->format = 0;
+	tregs->pc = fixup->fixup;
+	tregs->sr = regs->sr;
+
+	return 1;
+}
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 06438da..18b34ee 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -37,11 +37,11 @@ static inline int set_rtc_mmss(unsigned long nowtime)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
-	do_timer(1);
+	xtime_update(1);
 	update_process_times(user_mode(get_irq_regs()));
 	profile_tick(CPU_PROFILING);
 
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index ada4f4c..4022bbc 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -48,10 +48,7 @@ asmlinkage void nmihandler(void);
 asmlinkage void fpu_emu(void);
 #endif
 
-e_vector vectors[256] = {
-	[VEC_BUSERR]	= buserr,
-	[VEC_SYS]	= system_call,
-};
+e_vector vectors[256];
 
 /* nmi handler for the Amiga */
 asm(".text\n"
@@ -61,10 +58,11 @@ asm(".text\n"
 /*
  * this must be called very early as the kernel might
  * use some instruction that are emulated on the 060
+ * and so we're prepared for early probe attempts (e.g. nf_init).
  */
 void __init base_trap_init(void)
 {
-	if(MACH_IS_SUN3X) {
+	if (MACH_IS_SUN3X) {
 		extern e_vector *sun3x_prom_vbr;
 
 		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
@@ -79,6 +77,10 @@ void __init base_trap_init(void)
 
 		vectors[VEC_UNIMPII] = unimp_vec;
 	}
+
+	vectors[VEC_BUSERR] = buserr;
+	vectors[VEC_ILLEGAL] = trap;
+	vectors[VEC_SYS] = system_call;
 }
 
 void __init trap_init (void)
@@ -1055,9 +1057,11 @@ asmlinkage void trap_c(struct frame *fp)
 	siginfo_t info;
 
 	if (fp->ptregs.sr & PS_S) {
-		if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
-			/* traced a trapping instruction */
-		} else
+		if (fp->ptregs.vector == VEC_TRACE << 2) {
+			/* traced a trapping instruction on a 68020/30,
+			 * real exception will be executed afterwards.
+			 */
+		} else if (!handle_kernel_fault(&fp->ptregs))
 			bad_super_trap(fp);
 		return;
 	}
diff --git a/arch/m68k/math-emu/Makefile b/arch/m68k/math-emu/Makefile
index a0935bf..547c23c 100644
--- a/arch/m68k/math-emu/Makefile
+++ b/arch/m68k/math-emu/Makefile
@@ -2,8 +2,8 @@
 # Makefile for the linux kernel.
 #
 
-#EXTRA_AFLAGS += -DFPU_EMU_DEBUG
-#EXTRA_CFLAGS += -DFPU_EMU_DEBUG
+#asflags-y := -DFPU_EMU_DEBUG
+#ccflags-y := -DFPU_EMU_DEBUG
 
 obj-y		:= fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \
 			fp_cond.o fp_arith.o fp_log.o fp_trig.o
diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c
index a96394a..2db6099 100644
--- a/arch/m68k/mm/fault.c
+++ b/arch/m68k/mm/fault.c
@@ -18,7 +18,6 @@
 #include <asm/pgalloc.h>
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
-extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
 
 int send_fault_sig(struct pt_regs *regs)
 {
@@ -35,21 +34,8 @@ int send_fault_sig(struct pt_regs *regs)
 		force_sig_info(siginfo.si_signo,
 			       &siginfo, current);
 	} else {
-		const struct exception_table_entry *fixup;
-
-		/* Are we prepared to handle this kernel fault? */
-		if ((fixup = search_exception_tables(regs->pc))) {
-			struct pt_regs *tregs;
-			/* Create a new four word stack frame, discarding the old
-			   one.  */
-			regs->stkadj = frame_extra_sizes[regs->format];
-			tregs =	(struct pt_regs *)((ulong)regs + regs->stkadj);
-			tregs->vector = regs->vector;
-			tregs->format = 0;
-			tregs->pc = fixup->fixup;
-			tregs->sr = regs->sr;
+		if (handle_kernel_fault(regs))
 			return -1;
-		}
 
 		//if (siginfo.si_signo == SIGBUS)
 		//	force_sig_info(siginfo.si_signo,
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 100baaa..6cb9c3a 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -46,8 +46,8 @@ extern void mvme147_reset (void);
 
 static int bcd2int (unsigned char b);
 
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c, called via mvme147_process_int() */
+/* Save tick handler routine pointer, will point to xtime_update() in
+ * kernel/time/timekeeping.c, called via mvme147_process_int() */
 
 irq_handler_t tick_handler;
 
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 11edf61..0b28e26 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -51,8 +51,8 @@ extern void mvme16x_reset (void);
 
 int bcd2int (unsigned char b);
 
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c, called via mvme16x_process_int() */
+/* Save tick handler routine pointer, will point to xtime_update() in
+ * kernel/time/timekeeping.c, called via mvme16x_process_int() */
 
 static irq_handler_t tick_handler;
 
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index 2d9e21b..6464ad3 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -66,7 +66,7 @@ static irqreturn_t sun3_int5(int irq, void *dev_id)
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
-        do_timer(1);
+	xtime_update(1);
 	update_process_times(user_mode(get_irq_regs()));
         if (!(kstat_cpu(0).irqs[irq] % 20))
                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 8b9daca..b5424cf 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -3,6 +3,7 @@ config M68K
 	default y
 	select HAVE_IDE
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config MMU
 	bool
@@ -78,6 +79,12 @@ config HAVE_CACHE_SPLIT
 config HAVE_CACHE_CB
 	bool
 
+config HAVE_MBAR
+	bool
+
+config HAVE_IPSBAR
+	bool
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -111,12 +118,14 @@ config M68360
 config M5206
 	bool "MCF5206"
 	select COLDFIRE_SW_A7
+	select HAVE_MBAR
 	help
 	  Motorola ColdFire 5206 processor support.
 
 config M5206e
 	bool "MCF5206e"
 	select COLDFIRE_SW_A7
+	select HAVE_MBAR
 	help
 	  Motorola ColdFire 5206e processor support.
 
@@ -131,30 +140,35 @@ config M523x
 	bool "MCF523x"
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
 	help
 	  Freescale Coldfire 5230/1/2/4/5 processor support
 
 config M5249
 	bool "MCF5249"
 	select COLDFIRE_SW_A7
+	select HAVE_MBAR
 	help
 	  Motorola ColdFire 5249 processor support.
 
 config M5271
 	bool "MCF5271"
 	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
 	help
 	  Freescale (Motorola) ColdFire 5270/5271 processor support.
 
 config M5272
 	bool "MCF5272"
 	select COLDFIRE_SW_A7
+	select HAVE_MBAR
 	help
 	  Motorola ColdFire 5272 processor support.
 
 config M5275
 	bool "MCF5275"
 	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
 	help
 	  Freescale (Motorola) ColdFire 5274/5275 processor support.
 
@@ -162,6 +176,7 @@ config M528x
 	bool "MCF528x"
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
 	help
 	  Motorola ColdFire 5280/5282 processor support.
 
@@ -169,6 +184,7 @@ config M5307
 	bool "MCF5307"
 	select COLDFIRE_SW_A7
 	select HAVE_CACHE_CB
+	select HAVE_MBAR
 	help
 	  Motorola ColdFire 5307 processor support.
 
@@ -182,18 +198,21 @@ config M5407
 	bool "MCF5407"
 	select COLDFIRE_SW_A7
 	select HAVE_CACHE_CB
+	select HAVE_MBAR
 	help
 	  Motorola ColdFire 5407 processor support.
 
 config M547x
 	bool "MCF547x"
 	select HAVE_CACHE_CB
+	select HAVE_MBAR
 	help
 	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
 
 config M548x
 	bool "MCF548x"
 	select HAVE_CACHE_CB
+	select HAVE_MBAR
 	help
 	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
 
@@ -241,17 +260,6 @@ config CLOCK_FREQ
 	  if it is fitted (there are some exceptions). This value will be
 	  specific to the exact CPU that you are using.
 
-config CLOCK_DIV
-	int "Set the core/bus clock divide ratio"
-	default "1"
-	depends on CLOCK_SET
-	help
-	  On many SoC style CPUs the master CPU clock is also used to drive 
-	  on-chip peripherals. The clock that is distributed to these
-	  peripherals is sometimes a fixed ratio of the master clock
-	  frequency. If so then set this to the divider ratio of the
-	  master clock to the peripheral clock. If not sure then select 1.
-
 config OLDMASK
 	bool "Old mask 5307 (1H55J) silicon"
 	depends on M5307
@@ -500,6 +508,12 @@ config M5407C3
 	help
 	  Support for the Motorola M5407C3 board.
 
+config FIREBEE
+	bool "FireBee board support"
+	depends on M547x
+	help
+	  Support for the FireBee ColdFire 5475 based board.
+
 config CLEOPATRA
 	bool "Feith CLEOPATRA board support"
 	depends on (M5307 || M5407)
@@ -649,6 +663,28 @@ config VECTORBASE
 	  platforms this address is programmed into the VBR register, thus
 	  actually setting the address to use.
 
+config MBAR
+	hex "Address of the MBAR (internal peripherals)"
+	default "0x10000000"
+	depends on HAVE_MBAR
+	help
+	  Define the address of the internal system peripherals. This value
+	  is set in the processors MBAR register. This is generally setup by
+	  the boot loader, and will not be written by the kernel. By far most
+	  ColdFire boards use the default 0x10000000 value, so if unsure then
+	  use this.
+
+config IPSBAR
+	hex "Address of the IPSBAR (internal peripherals)"
+	default "0x40000000"
+	depends on HAVE_IPSBAR
+	help
+	  Define the address of the internal system peripherals. This value
+	  is set in the processors IPSBAR register. This is generally setup by
+	  the boot loader, and will not be written by the kernel. By far most
+	  ColdFire boards use the default 0x40000000 value, so if unsure then
+	  use this.
+
 config KERNELBASE
 	hex "Address of the base of kernel code"
 	default "0x400"
diff --git a/arch/m68knommu/kernel/irq.c b/arch/m68knommu/kernel/irq.c
index c9cac36..c7dd48f 100644
--- a/arch/m68knommu/kernel/irq.c
+++ b/arch/m68knommu/kernel/irq.c
@@ -38,11 +38,13 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_puts(p, "           CPU0\n");
 
 	if (irq < NR_IRQS) {
-		ap = irq_desc[irq].action;
+		struct irq_desc *desc = irq_to_desc(irq);
+
+		ap = desc->action;
 		if (ap) {
 			seq_printf(p, "%3d: ", irq);
 			seq_printf(p, "%10u ", kstat_irqs(irq));
-			seq_printf(p, "%14s  ", irq_desc[irq].chip->name);
+			seq_printf(p, "%14s  ", get_irq_desc_chip(desc)->name);
 
 			seq_printf(p, "%s", ap->name);
 			for (ap = ap->next; ap; ap = ap->next)
diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
index d6ac2a4..6623909 100644
--- a/arch/m68knommu/kernel/time.c
+++ b/arch/m68knommu/kernel/time.c
@@ -36,7 +36,7 @@ static inline int set_rtc_mmss(unsigned long nowtime)
 #ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 irqreturn_t arch_timer_interrupt(int irq, void *dummy)
 {
@@ -44,11 +44,7 @@ irqreturn_t arch_timer_interrupt(int irq, void *dummy)
 	if (current->pid)
 		profile_tick(CPU_PROFILING);
 
-	write_seqlock(&xtime_lock);
-
-	do_timer(1);
-
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 
 	update_process_times(user_mode(get_irq_regs()));
 
diff --git a/arch/m68knommu/platform/5206/gpio.c b/arch/m68knommu/platform/5206/gpio.c
index 60f779c..b9ab4a1 100644
--- a/arch/m68knommu/platform/5206/gpio.c
+++ b/arch/m68knommu/platform/5206/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
 	},
 };
 
diff --git a/arch/m68knommu/platform/5206e/gpio.c b/arch/m68knommu/platform/5206e/gpio.c
index 60f779c..b9ab4a1 100644
--- a/arch/m68knommu/platform/5206e/gpio.c
+++ b/arch/m68knommu/platform/5206e/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
 	},
 };
 
diff --git a/arch/m68knommu/platform/520x/config.c b/arch/m68knommu/platform/520x/config.c
index 71d2ba4..621238f 100644
--- a/arch/m68knommu/platform/520x/config.c
+++ b/arch/m68knommu/platform/520x/config.c
@@ -27,15 +27,15 @@
 
 static struct mcf_platform_uart m520x_uart_platform[] = {
 	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.mapbase	= MCFUART_BASE1,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.mapbase 	= MCFUART_BASE2,
 		.irq		= MCFINT_VECBASE + MCFINT_UART1,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
+		.mapbase 	= MCFUART_BASE3,
 		.irq		= MCFINT_VECBASE + MCFINT_UART2,
 	},
 	{ },
@@ -49,8 +49,8 @@ static struct platform_device m520x_uart = {
 
 static struct resource m520x_fec_resources[] = {
 	{
-		.start		= MCF_MBAR + 0x30000,
-		.end		= MCF_MBAR + 0x30000 + 0x7ff,
+		.start		= MCFFEC_BASE,
+		.end		= MCFFEC_BASE + MCFFEC_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
@@ -208,11 +208,11 @@ static void __init m520x_qspi_init(void)
 {
 	u16 par;
 	/* setup Port QS for QSPI with gpio CS control */
-	writeb(0x3f, MCF_IPSBAR + MCF_GPIO_PAR_QSPI);
+	writeb(0x3f, MCF_GPIO_PAR_QSPI);
 	/* make U1CTS and U2RTS gpio for cs_control */
-	par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+	par = readw(MCF_GPIO_PAR_UART);
 	par &= 0x00ff;
-	writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
+	writew(par, MCF_GPIO_PAR_UART);
 }
 #endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
 
@@ -234,23 +234,23 @@ static void __init m520x_uart_init_line(int line, int irq)
 
 	switch (line) {
 	case 0:
-		par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+		par = readw(MCF_GPIO_PAR_UART);
 		par |= MCF_GPIO_PAR_UART_PAR_UTXD0 |
 		       MCF_GPIO_PAR_UART_PAR_URXD0;
-		writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
+		writew(par, MCF_GPIO_PAR_UART);
 		break;
 	case 1:
-		par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+		par = readw(MCF_GPIO_PAR_UART);
 		par |= MCF_GPIO_PAR_UART_PAR_UTXD1 |
 		       MCF_GPIO_PAR_UART_PAR_URXD1;
-		writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
+		writew(par, MCF_GPIO_PAR_UART);
 		break;
 	case 2:
-		par2 = readb(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
+		par2 = readb(MCF_GPIO_PAR_FECI2C);
 		par2 &= ~0x0F;
 		par2 |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 |
 			MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
-		writeb(par2, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
+		writeb(par2, MCF_GPIO_PAR_FECI2C);
 		break;
 	}
 }
@@ -271,11 +271,11 @@ static void __init m520x_fec_init(void)
 	u8 v;
 
 	/* Set multi-function pins to ethernet mode */
-	v = readb(MCF_IPSBAR + MCF_GPIO_PAR_FEC);
-	writeb(v | 0xf0, MCF_IPSBAR + MCF_GPIO_PAR_FEC);
+	v = readb(MCF_GPIO_PAR_FEC);
+	writeb(v | 0xf0, MCF_GPIO_PAR_FEC);
 
-	v = readb(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
-	writeb(v | 0x0f, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
+	v = readb(MCF_GPIO_PAR_FECI2C);
+	writeb(v | 0x0f, MCF_GPIO_PAR_FECI2C);
 }
 
 /***************************************************************************/
diff --git a/arch/m68knommu/platform/520x/gpio.c b/arch/m68knommu/platform/520x/gpio.c
index 15b5bb6..d757328 100644
--- a/arch/m68knommu/platform/520x/gpio.c
+++ b/arch/m68knommu/platform/520x/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
 	},
 	{
 		.gpio_chip			= {
@@ -48,11 +48,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 8,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
 	},
 	{
 		.gpio_chip			= {
@@ -66,11 +66,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 16,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_BE,
-		.podr				= MCFGPIO_PODR_BE,
-		.ppdr				= MCFGPIO_PPDSDR_BE,
-		.setr				= MCFGPIO_PPDSDR_BE,
-		.clrr				= MCFGPIO_PCLRR_BE,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BE,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BE,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BE,
 	},
 	{
 		.gpio_chip			= {
@@ -84,11 +84,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 25,
 			.ngpio			= 3,
 		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
 	},
 	{
 		.gpio_chip			= {
@@ -102,11 +102,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
 	},
 	{
 		.gpio_chip			= {
@@ -120,11 +120,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 40,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
 	},
 	{
 		.gpio_chip			= {
@@ -138,11 +138,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 48,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
 	},
 	{
 		.gpio_chip			= {
@@ -156,11 +156,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 56,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_UART,
-		.podr				= MCFGPIO_PODR_UART,
-		.ppdr				= MCFGPIO_PPDSDR_UART,
-		.setr				= MCFGPIO_PPDSDR_UART,
-		.clrr				= MCFGPIO_PCLRR_UART,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UART,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UART,
 	},
 	{
 		.gpio_chip			= {
@@ -174,11 +174,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 64,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FECH,
-		.podr				= MCFGPIO_PODR_FECH,
-		.ppdr				= MCFGPIO_PPDSDR_FECH,
-		.setr				= MCFGPIO_PPDSDR_FECH,
-		.clrr				= MCFGPIO_PCLRR_FECH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECH,
 	},
 	{
 		.gpio_chip			= {
@@ -192,11 +192,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 72,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FECL,
-		.podr				= MCFGPIO_PODR_FECL,
-		.ppdr				= MCFGPIO_PPDSDR_FECL,
-		.setr				= MCFGPIO_PPDSDR_FECL,
-		.clrr				= MCFGPIO_PCLRR_FECL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECL,
 	},
 };
 
diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c
index 8980f6d..418a76f 100644
--- a/arch/m68knommu/platform/523x/config.c
+++ b/arch/m68knommu/platform/523x/config.c
@@ -28,15 +28,15 @@
 
 static struct mcf_platform_uart m523x_uart_platform[] = {
 	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.mapbase	= MCFUART_BASE1,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.mapbase 	= MCFUART_BASE2,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 1,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
+		.mapbase 	= MCFUART_BASE3,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 2,
 	},
 	{ },
@@ -50,8 +50,8 @@ static struct platform_device m523x_uart = {
 
 static struct resource m523x_fec_resources[] = {
 	{
-		.start		= MCF_MBAR + 0x1000,
-		.end		= MCF_MBAR + 0x1000 + 0x7ff,
+		.start		= MCFFEC_BASE,
+		.end		= MCFFEC_BASE + MCFFEC_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
diff --git a/arch/m68knommu/platform/523x/gpio.c b/arch/m68knommu/platform/523x/gpio.c
index a8842dc..327ebf1 100644
--- a/arch/m68knommu/platform/523x/gpio.c
+++ b/arch/m68knommu/platform/523x/gpio.c
@@ -33,9 +33,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 1,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
 	},
 	{
 		.gpio_chip			= {
@@ -49,11 +49,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 13,
 			.ngpio			= 3,
 		},
-		.pddr				= MCFGPIO_PDDR_ADDR,
-		.podr				= MCFGPIO_PODR_ADDR,
-		.ppdr				= MCFGPIO_PPDSDR_ADDR,
-		.setr				= MCFGPIO_PPDSDR_ADDR,
-		.clrr				= MCFGPIO_PCLRR_ADDR,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ADDR,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ADDR,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ADDR,
 	},
 	{
 		.gpio_chip			= {
@@ -67,11 +67,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 16,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_DATAH,
-		.podr				= MCFGPIO_PODR_DATAH,
-		.ppdr				= MCFGPIO_PPDSDR_DATAH,
-		.setr				= MCFGPIO_PPDSDR_DATAH,
-		.clrr				= MCFGPIO_PCLRR_DATAH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAH,
 	},
 	{
 		.gpio_chip			= {
@@ -85,11 +85,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 24,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_DATAL,
-		.podr				= MCFGPIO_PODR_DATAL,
-		.ppdr				= MCFGPIO_PPDSDR_DATAL,
-		.setr				= MCFGPIO_PPDSDR_DATAL,
-		.clrr				= MCFGPIO_PCLRR_DATAL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAL,
 	},
 	{
 		.gpio_chip			= {
@@ -103,11 +103,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
 	},
 	{
 		.gpio_chip			= {
@@ -121,11 +121,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 40,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_BS,
-		.podr				= MCFGPIO_PODR_BS,
-		.ppdr				= MCFGPIO_PPDSDR_BS,
-		.setr				= MCFGPIO_PPDSDR_BS,
-		.clrr				= MCFGPIO_PCLRR_BS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BS,
 	},
 	{
 		.gpio_chip			= {
@@ -139,11 +139,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 49,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
 	},
 	{
 		.gpio_chip			= {
@@ -157,11 +157,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 56,
 			.ngpio			= 6,
 		},
-		.pddr				= MCFGPIO_PDDR_SDRAM,
-		.podr				= MCFGPIO_PODR_SDRAM,
-		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
-		.setr				= MCFGPIO_PPDSDR_SDRAM,
-		.clrr				= MCFGPIO_PCLRR_SDRAM,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SDRAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SDRAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SDRAM,
 	},
 	{
 		.gpio_chip			= {
@@ -175,11 +175,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 64,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
 	},
 	{
 		.gpio_chip			= {
@@ -193,11 +193,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 72,
 			.ngpio			= 2,
 		},
-		.pddr				= MCFGPIO_PDDR_UARTH,
-		.podr				= MCFGPIO_PODR_UARTH,
-		.ppdr				= MCFGPIO_PPDSDR_UARTH,
-		.setr				= MCFGPIO_PPDSDR_UARTH,
-		.clrr				= MCFGPIO_PCLRR_UARTH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTH,
 	},
 	{
 		.gpio_chip			= {
@@ -211,11 +211,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 80,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_UARTL,
-		.podr				= MCFGPIO_PODR_UARTL,
-		.ppdr				= MCFGPIO_PPDSDR_UARTL,
-		.setr				= MCFGPIO_PPDSDR_UARTL,
-		.clrr				= MCFGPIO_PCLRR_UARTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTL,
 	},
 	{
 		.gpio_chip			= {
@@ -229,11 +229,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 88,
 			.ngpio			= 5,
 		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
 	},
 	{
 		.gpio_chip			= {
@@ -247,11 +247,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 96,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
 	},
 	{
 		.gpio_chip			= {
@@ -265,11 +265,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 104,
 			.ngpio			= 3,
 		},
-		.pddr				= MCFGPIO_PDDR_ETPU,
-		.podr				= MCFGPIO_PODR_ETPU,
-		.ppdr				= MCFGPIO_PPDSDR_ETPU,
-		.setr				= MCFGPIO_PPDSDR_ETPU,
-		.clrr				= MCFGPIO_PCLRR_ETPU,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ETPU,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ETPU,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ETPU,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ETPU,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ETPU,
 	},
 };
 
diff --git a/arch/m68knommu/platform/5249/gpio.c b/arch/m68knommu/platform/5249/gpio.c
index c611eab..2b56c6e 100644
--- a/arch/m68knommu/platform/5249/gpio.c
+++ b/arch/m68knommu/platform/5249/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 32,
 		},
-		.pddr				= MCFSIM2_GPIOENABLE,
-		.podr				= MCFSIM2_GPIOWRITE,
-		.ppdr				= MCFSIM2_GPIOREAD,
+		.pddr				= (void __iomem *) MCFSIM2_GPIOENABLE,
+		.podr				= (void __iomem *) MCFSIM2_GPIOWRITE,
+		.ppdr				= (void __iomem *) MCFSIM2_GPIOREAD,
 	},
 	{
 		.gpio_chip			= {
@@ -48,9 +48,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 32,
 		},
-		.pddr				= MCFSIM2_GPIO1ENABLE,
-		.podr				= MCFSIM2_GPIO1WRITE,
-		.ppdr				= MCFSIM2_GPIO1READ,
+		.pddr				= (void __iomem *) MCFSIM2_GPIO1ENABLE,
+		.podr				= (void __iomem *) MCFSIM2_GPIO1WRITE,
+		.ppdr				= (void __iomem *) MCFSIM2_GPIO1READ,
 	},
 };
 
diff --git a/arch/m68knommu/platform/5249/intc2.c b/arch/m68knommu/platform/5249/intc2.c
index c5151f8..8f4b63e 100644
--- a/arch/m68knommu/platform/5249/intc2.c
+++ b/arch/m68knommu/platform/5249/intc2.c
@@ -17,32 +17,32 @@
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 
-static void intc2_irq_gpio_mask(unsigned int irq)
+static void intc2_irq_gpio_mask(struct irq_data *d)
 {
 	u32 imr;
 	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-	imr &= ~(0x1 << (irq - MCFINTC2_GPIOIRQ0));
+	imr &= ~(0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
 	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
 }
 
-static void intc2_irq_gpio_unmask(unsigned int irq)
+static void intc2_irq_gpio_unmask(struct irq_data *d)
 {
 	u32 imr;
 	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-	imr |= (0x1 << (irq - MCFINTC2_GPIOIRQ0));
+	imr |= (0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
 	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
 }
 
-static void intc2_irq_gpio_ack(unsigned int irq)
+static void intc2_irq_gpio_ack(struct irq_data *d)
 {
-	writel(0x1 << (irq - MCFINTC2_GPIOIRQ0), MCF_MBAR2 + MCFSIM2_GPIOINTCLEAR);
+	writel(0x1 << (d->irq - MCFINTC2_GPIOIRQ0), MCF_MBAR2 + MCFSIM2_GPIOINTCLEAR);
 }
 
 static struct irq_chip intc2_irq_gpio_chip = {
 	.name		= "CF-INTC2",
-	.mask		= intc2_irq_gpio_mask,
-	.unmask		= intc2_irq_gpio_unmask,
-	.ack		= intc2_irq_gpio_ack,
+	.irq_mask	= intc2_irq_gpio_mask,
+	.irq_unmask	= intc2_irq_gpio_unmask,
+	.irq_ack	= intc2_irq_gpio_ack,
 };
 
 static int __init mcf_intc2_init(void)
@@ -51,7 +51,7 @@ static int __init mcf_intc2_init(void)
 
 	/* GPIO interrupt sources */
 	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) {
-		irq_desc[irq].chip = &intc2_irq_gpio_chip;
+		set_irq_chip(irq, &intc2_irq_gpio_chip);
 		set_irq_handler(irq, handle_edge_irq);
 	}
 
diff --git a/arch/m68knommu/platform/5272/gpio.c b/arch/m68knommu/platform/5272/gpio.c
index 459db89..57ac10a 100644
--- a/arch/m68knommu/platform/5272/gpio.c
+++ b/arch/m68knommu/platform/5272/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 16,
 		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
 	},
 	{
 		.gpio_chip			= {
@@ -48,9 +48,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 16,
 			.ngpio			= 16,
 		},
-		.pddr				= MCFSIM_PBDDR,
-		.podr				= MCFSIM_PBDAT,
-		.ppdr				= MCFSIM_PBDAT,
+		.pddr				= (void __iomem *) MCFSIM_PBDDR,
+		.podr				= (void __iomem *) MCFSIM_PBDAT,
+		.ppdr				= (void __iomem *) MCFSIM_PBDAT,
 	},
 	{
 		.gpio_chip			= {
@@ -64,9 +64,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 16,
 		},
-		.pddr				= MCFSIM_PCDDR,
-		.podr				= MCFSIM_PCDAT,
-		.ppdr				= MCFSIM_PCDAT,
+		.pddr				= (void __iomem *) MCFSIM_PCDDR,
+		.podr				= (void __iomem *) MCFSIM_PCDAT,
+		.ppdr				= (void __iomem *) MCFSIM_PCDAT,
 	},
 };
 
diff --git a/arch/m68knommu/platform/5272/intc.c b/arch/m68knommu/platform/5272/intc.c
index 3cf681c..969ff0a 100644
--- a/arch/m68knommu/platform/5272/intc.c
+++ b/arch/m68knommu/platform/5272/intc.c
@@ -78,8 +78,10 @@ static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
  * an interrupt on this irq (for the external irqs). So this mask function
  * is also an ack_mask function.
  */
-static void intc_irq_mask(unsigned int irq)
+static void intc_irq_mask(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
 		u32 v;
 		irq -= MCFINT_VECBASE;
@@ -88,8 +90,10 @@ static void intc_irq_mask(unsigned int irq)
 	}
 }
 
-static void intc_irq_unmask(unsigned int irq)
+static void intc_irq_unmask(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
 		u32 v;
 		irq -= MCFINT_VECBASE;
@@ -98,8 +102,10 @@ static void intc_irq_unmask(unsigned int irq)
 	}
 }
 
-static void intc_irq_ack(unsigned int irq)
+static void intc_irq_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	/* Only external interrupts are acked */
 	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
 		irq -= MCFINT_VECBASE;
@@ -113,8 +119,10 @@ static void intc_irq_ack(unsigned int irq)
 	}
 }
 
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
 {
+	unsigned int irq = d->irq;
+
 	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
 		irq -= MCFINT_VECBASE;
 		if (intc_irqmap[irq].ack) {
@@ -137,20 +145,17 @@ static int intc_irq_set_type(unsigned int irq, unsigned int type)
  */
 static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
 {
-	kstat_incr_irqs_this_cpu(irq, desc);
-	desc->status |= IRQ_INPROGRESS;
-	desc->chip->ack(irq);
-	handle_IRQ_event(irq, desc->action);
-	desc->status &= ~IRQ_INPROGRESS;
+	get_irq_desc_chip(desc)->irq_ack(&desc->irq_data);
+	handle_simple_irq(irq, desc);
 }
 
 static struct irq_chip intc_irq_chip = {
 	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.mask_ack	= intc_irq_mask,
-	.ack		= intc_irq_ack,
-	.set_type	= intc_irq_set_type,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_mask_ack	= intc_irq_mask,
+	.irq_ack	= intc_irq_ack,
+	.irq_set_type	= intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
diff --git a/arch/m68knommu/platform/527x/config.c b/arch/m68knommu/platform/527x/config.c
index 3d9c35c..fa35959 100644
--- a/arch/m68knommu/platform/527x/config.c
+++ b/arch/m68knommu/platform/527x/config.c
@@ -28,15 +28,15 @@
 
 static struct mcf_platform_uart m527x_uart_platform[] = {
 	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.mapbase	= MCFUART_BASE1,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.mapbase 	= MCFUART_BASE2,
 		.irq		= MCFINT_VECBASE + MCFINT_UART1,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
+		.mapbase 	= MCFUART_BASE3,
 		.irq		= MCFINT_VECBASE + MCFINT_UART2,
 	},
 	{ },
@@ -50,8 +50,8 @@ static struct platform_device m527x_uart = {
 
 static struct resource m527x_fec0_resources[] = {
 	{
-		.start		= MCF_MBAR + 0x1000,
-		.end		= MCF_MBAR + 0x1000 + 0x7ff,
+		.start		= MCFFEC_BASE0,
+		.end		= MCFFEC_BASE0 + MCFFEC_SIZE0 - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
@@ -73,8 +73,8 @@ static struct resource m527x_fec0_resources[] = {
 
 static struct resource m527x_fec1_resources[] = {
 	{
-		.start		= MCF_MBAR + 0x1800,
-		.end		= MCF_MBAR + 0x1800 + 0x7ff,
+		.start		= MCFFEC_BASE1,
+		.end		= MCFFEC_BASE1 + MCFFEC_SIZE1 - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
diff --git a/arch/m68knommu/platform/527x/gpio.c b/arch/m68knommu/platform/527x/gpio.c
index 0b56e19..205da0a 100644
--- a/arch/m68knommu/platform/527x/gpio.c
+++ b/arch/m68knommu/platform/527x/gpio.c
@@ -34,9 +34,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 1,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
 	},
 	{
 		.gpio_chip			= {
@@ -50,11 +50,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 13,
 			.ngpio			= 3,
 		},
-		.pddr				= MCFGPIO_PDDR_ADDR,
-		.podr				= MCFGPIO_PODR_ADDR,
-		.ppdr				= MCFGPIO_PPDSDR_ADDR,
-		.setr				= MCFGPIO_PPDSDR_ADDR,
-		.clrr				= MCFGPIO_PCLRR_ADDR,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ADDR,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ADDR,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ADDR,
 	},
 	{
 		.gpio_chip			= {
@@ -68,11 +68,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 16,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_DATAH,
-		.podr				= MCFGPIO_PODR_DATAH,
-		.ppdr				= MCFGPIO_PPDSDR_DATAH,
-		.setr				= MCFGPIO_PPDSDR_DATAH,
-		.clrr				= MCFGPIO_PCLRR_DATAH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAH,
 	},
 	{
 		.gpio_chip			= {
@@ -86,11 +86,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 24,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_DATAL,
-		.podr				= MCFGPIO_PODR_DATAL,
-		.ppdr				= MCFGPIO_PPDSDR_DATAL,
-		.setr				= MCFGPIO_PPDSDR_DATAL,
-		.clrr				= MCFGPIO_PCLRR_DATAL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAL,
 	},
 	{
 		.gpio_chip			= {
@@ -104,11 +104,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
 	},
 	{
 		.gpio_chip			= {
@@ -122,11 +122,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 40,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_BS,
-		.podr				= MCFGPIO_PODR_BS,
-		.ppdr				= MCFGPIO_PPDSDR_BS,
-		.setr				= MCFGPIO_PPDSDR_BS,
-		.clrr				= MCFGPIO_PCLRR_BS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BS,
 	},
 	{
 		.gpio_chip			= {
@@ -140,11 +140,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 49,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
 	},
 	{
 		.gpio_chip			= {
@@ -158,11 +158,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 56,
 			.ngpio			= 6,
 		},
-		.pddr				= MCFGPIO_PDDR_SDRAM,
-		.podr				= MCFGPIO_PODR_SDRAM,
-		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
-		.setr				= MCFGPIO_PPDSDR_SDRAM,
-		.clrr				= MCFGPIO_PCLRR_SDRAM,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SDRAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SDRAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SDRAM,
 	},
 	{
 		.gpio_chip			= {
@@ -176,11 +176,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 64,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
 	},
 	{
 		.gpio_chip			= {
@@ -194,11 +194,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 72,
 			.ngpio			= 2,
 		},
-		.pddr				= MCFGPIO_PDDR_UARTH,
-		.podr				= MCFGPIO_PODR_UARTH,
-		.ppdr				= MCFGPIO_PPDSDR_UARTH,
-		.setr				= MCFGPIO_PPDSDR_UARTH,
-		.clrr				= MCFGPIO_PCLRR_UARTH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTH,
 	},
 	{
 		.gpio_chip			= {
@@ -212,11 +212,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 80,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_UARTL,
-		.podr				= MCFGPIO_PODR_UARTL,
-		.ppdr				= MCFGPIO_PPDSDR_UARTL,
-		.setr				= MCFGPIO_PPDSDR_UARTL,
-		.clrr				= MCFGPIO_PCLRR_UARTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTL,
 	},
 	{
 		.gpio_chip			= {
@@ -230,11 +230,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 88,
 			.ngpio			= 5,
 		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
 	},
 	{
 		.gpio_chip			= {
@@ -248,11 +248,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 96,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
 	},
 #elif defined(CONFIG_M5275)
 	{
@@ -267,9 +267,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 1,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
 	},
 	{
 		.gpio_chip			= {
@@ -283,11 +283,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 8,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
 	},
 	{
 		.gpio_chip			= {
@@ -301,11 +301,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 21,
 			.ngpio			= 3,
 		},
-		.pddr				= MCFGPIO_PDDR_ADDR,
-		.podr				= MCFGPIO_PODR_ADDR,
-		.ppdr				= MCFGPIO_PPDSDR_ADDR,
-		.setr				= MCFGPIO_PPDSDR_ADDR,
-		.clrr				= MCFGPIO_PCLRR_ADDR,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ADDR,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ADDR,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ADDR,
 	},
 	{
 		.gpio_chip			= {
@@ -319,11 +319,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 25,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
 	},
 	{
 		.gpio_chip			= {
@@ -337,11 +337,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FEC0H,
-		.podr				= MCFGPIO_PODR_FEC0H,
-		.ppdr				= MCFGPIO_PPDSDR_FEC0H,
-		.setr				= MCFGPIO_PPDSDR_FEC0H,
-		.clrr				= MCFGPIO_PCLRR_FEC0H,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC0H,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC0H,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0H,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0H,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC0H,
 	},
 	{
 		.gpio_chip			= {
@@ -355,11 +355,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 40,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FEC0L,
-		.podr				= MCFGPIO_PODR_FEC0L,
-		.ppdr				= MCFGPIO_PPDSDR_FEC0L,
-		.setr				= MCFGPIO_PPDSDR_FEC0L,
-		.clrr				= MCFGPIO_PCLRR_FEC0L,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC0L,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC0L,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0L,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0L,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC0L,
 	},
 	{
 		.gpio_chip			= {
@@ -373,11 +373,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 48,
 			.ngpio			= 6,
 		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
 	},
 	{
 		.gpio_chip			= {
@@ -391,11 +391,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 56,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
 	},
 	{
 		.gpio_chip			= {
@@ -409,11 +409,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 64,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_SDRAM,
-		.podr				= MCFGPIO_PODR_SDRAM,
-		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
-		.setr				= MCFGPIO_PPDSDR_SDRAM,
-		.clrr				= MCFGPIO_PCLRR_SDRAM,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SDRAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SDRAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SDRAM,
 	},
 	{
 		.gpio_chip			= {
@@ -427,11 +427,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 72,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_TIMERH,
-		.podr				= MCFGPIO_PODR_TIMERH,
-		.ppdr				= MCFGPIO_PPDSDR_TIMERH,
-		.setr				= MCFGPIO_PPDSDR_TIMERH,
-		.clrr				= MCFGPIO_PCLRR_TIMERH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMERH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMERH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMERH,
 	},
 	{
 		.gpio_chip			= {
@@ -445,11 +445,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 80,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_TIMERL,
-		.podr				= MCFGPIO_PODR_TIMERL,
-		.ppdr				= MCFGPIO_PPDSDR_TIMERL,
-		.setr				= MCFGPIO_PPDSDR_TIMERL,
-		.clrr				= MCFGPIO_PCLRR_TIMERL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMERL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMERL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMERL,
 	},
 	{
 		.gpio_chip			= {
@@ -463,11 +463,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 88,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_UARTL,
-		.podr				= MCFGPIO_PODR_UARTL,
-		.ppdr				= MCFGPIO_PPDSDR_UARTL,
-		.setr				= MCFGPIO_PPDSDR_UARTL,
-		.clrr				= MCFGPIO_PCLRR_UARTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTL,
 	},
 	{
 		.gpio_chip			= {
@@ -481,11 +481,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 96,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FEC1H,
-		.podr				= MCFGPIO_PODR_FEC1H,
-		.ppdr				= MCFGPIO_PPDSDR_FEC1H,
-		.setr				= MCFGPIO_PPDSDR_FEC1H,
-		.clrr				= MCFGPIO_PCLRR_FEC1H,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC1H,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC1H,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1H,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1H,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC1H,
 	},
 	{
 		.gpio_chip			= {
@@ -499,11 +499,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 104,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FEC1L,
-		.podr				= MCFGPIO_PODR_FEC1L,
-		.ppdr				= MCFGPIO_PPDSDR_FEC1L,
-		.setr				= MCFGPIO_PPDSDR_FEC1L,
-		.clrr				= MCFGPIO_PCLRR_FEC1L,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC1L,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC1L,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1L,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1L,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC1L,
 	},
 	{
 		.gpio_chip			= {
@@ -517,11 +517,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 114,
 			.ngpio			= 2,
 		},
-		.pddr				= MCFGPIO_PDDR_BS,
-		.podr				= MCFGPIO_PODR_BS,
-		.ppdr				= MCFGPIO_PPDSDR_BS,
-		.setr				= MCFGPIO_PPDSDR_BS,
-		.clrr				= MCFGPIO_PCLRR_BS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BS,
 	},
 	{
 		.gpio_chip			= {
@@ -535,11 +535,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 121,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFGPIO_PDDR_IRQ,
-		.podr				= MCFGPIO_PODR_IRQ,
-		.ppdr				= MCFGPIO_PPDSDR_IRQ,
-		.setr				= MCFGPIO_PPDSDR_IRQ,
-		.clrr				= MCFGPIO_PCLRR_IRQ,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_IRQ,
+		.podr				= (void __iomem *) MCFGPIO_PODR_IRQ,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_IRQ,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_IRQ,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_IRQ,
 	},
 	{
 		.gpio_chip			= {
@@ -553,11 +553,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 128,
 			.ngpio			= 1,
 		},
-		.pddr				= MCFGPIO_PDDR_USBH,
-		.podr				= MCFGPIO_PODR_USBH,
-		.ppdr				= MCFGPIO_PPDSDR_USBH,
-		.setr				= MCFGPIO_PPDSDR_USBH,
-		.clrr				= MCFGPIO_PCLRR_USBH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_USBH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_USBH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_USBH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_USBH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_USBH,
 	},
 	{
 		.gpio_chip			= {
@@ -571,11 +571,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 136,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_USBL,
-		.podr				= MCFGPIO_PODR_USBL,
-		.ppdr				= MCFGPIO_PPDSDR_USBL,
-		.setr				= MCFGPIO_PPDSDR_USBL,
-		.clrr				= MCFGPIO_PCLRR_USBL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_USBL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_USBL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_USBL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_USBL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_USBL,
 	},
 	{
 		.gpio_chip			= {
@@ -589,11 +589,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 144,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_UARTH,
-		.podr				= MCFGPIO_PODR_UARTH,
-		.ppdr				= MCFGPIO_PPDSDR_UARTH,
-		.setr				= MCFGPIO_PPDSDR_UARTH,
-		.clrr				= MCFGPIO_PCLRR_UARTH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTH,
 	},
 #endif
 };
diff --git a/arch/m68knommu/platform/528x/config.c b/arch/m68knommu/platform/528x/config.c
index 76b7433..ac39fc6 100644
--- a/arch/m68knommu/platform/528x/config.c
+++ b/arch/m68knommu/platform/528x/config.c
@@ -29,15 +29,15 @@
 
 static struct mcf_platform_uart m528x_uart_platform[] = {
 	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.mapbase	= MCFUART_BASE1,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.mapbase 	= MCFUART_BASE2,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 1,
 	},
 	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
+		.mapbase 	= MCFUART_BASE3,
 		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 2,
 	},
 	{ },
@@ -51,8 +51,8 @@ static struct platform_device m528x_uart = {
 
 static struct resource m528x_fec_resources[] = {
 	{
-		.start		= MCF_MBAR + 0x1000,
-		.end		= MCF_MBAR + 0x1000 + 0x7ff,
+		.start		= MCFFEC_BASE,
+		.end		= MCFFEC_BASE + MCFFEC_SIZE - 1,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
@@ -227,9 +227,9 @@ static void __init m528x_uart_init_line(int line, int irq)
 
 	/* make sure PUAPAR is set for UART0 and UART1 */
 	if (line < 2) {
-		port = readb(MCF_MBAR + MCF5282_GPIO_PUAPAR);
+		port = readb(MCF5282_GPIO_PUAPAR);
 		port |= (0x03 << (line * 2));
-		writeb(port, MCF_MBAR + MCF5282_GPIO_PUAPAR);
+		writeb(port, MCF5282_GPIO_PUAPAR);
 	}
 }
 
diff --git a/arch/m68knommu/platform/528x/gpio.c b/arch/m68knommu/platform/528x/gpio.c
index eedaf0a..526db66 100644
--- a/arch/m68knommu/platform/528x/gpio.c
+++ b/arch/m68knommu/platform/528x/gpio.c
@@ -33,9 +33,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 1,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
+		.pddr				= (void __iomem *)MCFEPORT_EPDDR,
+		.podr				= (void __iomem *)MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *)MCFEPORT_EPPDR,
 	},
 	{
 		.gpio_chip			= {
@@ -49,9 +49,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 8,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPTA_GPTDDR,
-		.podr				= MCFGPTA_GPTPORT,
-		.ppdr				= MCFGPTB_GPTPORT,
+		.pddr				= (void __iomem *)MCFGPTA_GPTDDR,
+		.podr				= (void __iomem *)MCFGPTA_GPTPORT,
+		.ppdr				= (void __iomem *)MCFGPTB_GPTPORT,
 	},
 	{
 		.gpio_chip			= {
@@ -65,9 +65,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 16,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPTB_GPTDDR,
-		.podr				= MCFGPTB_GPTPORT,
-		.ppdr				= MCFGPTB_GPTPORT,
+		.pddr				= (void __iomem *)MCFGPTB_GPTDDR,
+		.podr				= (void __iomem *)MCFGPTB_GPTPORT,
+		.ppdr				= (void __iomem *)MCFGPTB_GPTPORT,
 	},
 	{
 		.gpio_chip			= {
@@ -81,9 +81,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 24,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFQADC_DDRQA,
-		.podr				= MCFQADC_PORTQA,
-		.ppdr				= MCFQADC_PORTQA,
+		.pddr				= (void __iomem *)MCFQADC_DDRQA,
+		.podr				= (void __iomem *)MCFQADC_PORTQA,
+		.ppdr				= (void __iomem *)MCFQADC_PORTQA,
 	},
 	{
 		.gpio_chip			= {
@@ -97,9 +97,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFQADC_DDRQB,
-		.podr				= MCFQADC_PORTQB,
-		.ppdr				= MCFQADC_PORTQB,
+		.pddr				= (void __iomem *)MCFQADC_DDRQB,
+		.podr				= (void __iomem *)MCFQADC_PORTQB,
+		.ppdr				= (void __iomem *)MCFQADC_PORTQB,
 	},
 	{
 		.gpio_chip			= {
@@ -113,11 +113,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 40,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRA,
-		.podr				= MCFGPIO_PORTA,
-		.ppdr				= MCFGPIO_PORTAP,
-		.setr				= MCFGPIO_SETA,
-		.clrr				= MCFGPIO_CLRA,
+		.pddr				= (void __iomem *)MCFGPIO_DDRA,
+		.podr				= (void __iomem *)MCFGPIO_PORTA,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTAP,
+		.setr				= (void __iomem *)MCFGPIO_SETA,
+		.clrr				= (void __iomem *)MCFGPIO_CLRA,
 	},
 	{
 		.gpio_chip			= {
@@ -131,11 +131,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 48,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRB,
-		.podr				= MCFGPIO_PORTB,
-		.ppdr				= MCFGPIO_PORTBP,
-		.setr				= MCFGPIO_SETB,
-		.clrr				= MCFGPIO_CLRB,
+		.pddr				= (void __iomem *)MCFGPIO_DDRB,
+		.podr				= (void __iomem *)MCFGPIO_PORTB,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTBP,
+		.setr				= (void __iomem *)MCFGPIO_SETB,
+		.clrr				= (void __iomem *)MCFGPIO_CLRB,
 	},
 	{
 		.gpio_chip			= {
@@ -149,11 +149,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 56,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRC,
-		.podr				= MCFGPIO_PORTC,
-		.ppdr				= MCFGPIO_PORTCP,
-		.setr				= MCFGPIO_SETC,
-		.clrr				= MCFGPIO_CLRC,
+		.pddr				= (void __iomem *)MCFGPIO_DDRC,
+		.podr				= (void __iomem *)MCFGPIO_PORTC,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTCP,
+		.setr				= (void __iomem *)MCFGPIO_SETC,
+		.clrr				= (void __iomem *)MCFGPIO_CLRC,
 	},
 	{
 		.gpio_chip			= {
@@ -167,11 +167,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 64,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRD,
-		.podr				= MCFGPIO_PORTD,
-		.ppdr				= MCFGPIO_PORTDP,
-		.setr				= MCFGPIO_SETD,
-		.clrr				= MCFGPIO_CLRD,
+		.pddr				= (void __iomem *)MCFGPIO_DDRD,
+		.podr				= (void __iomem *)MCFGPIO_PORTD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTDP,
+		.setr				= (void __iomem *)MCFGPIO_SETD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRD,
 	},
 	{
 		.gpio_chip			= {
@@ -185,11 +185,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 72,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRE,
-		.podr				= MCFGPIO_PORTE,
-		.ppdr				= MCFGPIO_PORTEP,
-		.setr				= MCFGPIO_SETE,
-		.clrr				= MCFGPIO_CLRE,
+		.pddr				= (void __iomem *)MCFGPIO_DDRE,
+		.podr				= (void __iomem *)MCFGPIO_PORTE,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTEP,
+		.setr				= (void __iomem *)MCFGPIO_SETE,
+		.clrr				= (void __iomem *)MCFGPIO_CLRE,
 	},
 	{
 		.gpio_chip			= {
@@ -203,11 +203,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 80,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRF,
-		.podr				= MCFGPIO_PORTF,
-		.ppdr				= MCFGPIO_PORTFP,
-		.setr				= MCFGPIO_SETF,
-		.clrr				= MCFGPIO_CLRF,
+		.pddr				= (void __iomem *)MCFGPIO_DDRF,
+		.podr				= (void __iomem *)MCFGPIO_PORTF,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTFP,
+		.setr				= (void __iomem *)MCFGPIO_SETF,
+		.clrr				= (void __iomem *)MCFGPIO_CLRF,
 	},
 	{
 		.gpio_chip			= {
@@ -221,11 +221,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 88,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRG,
-		.podr				= MCFGPIO_PORTG,
-		.ppdr				= MCFGPIO_PORTGP,
-		.setr				= MCFGPIO_SETG,
-		.clrr				= MCFGPIO_CLRG,
+		.pddr				= (void __iomem *)MCFGPIO_DDRG,
+		.podr				= (void __iomem *)MCFGPIO_PORTG,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTGP,
+		.setr				= (void __iomem *)MCFGPIO_SETG,
+		.clrr				= (void __iomem *)MCFGPIO_CLRG,
 	},
 	{
 		.gpio_chip			= {
@@ -239,11 +239,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 96,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRH,
-		.podr				= MCFGPIO_PORTH,
-		.ppdr				= MCFGPIO_PORTHP,
-		.setr				= MCFGPIO_SETH,
-		.clrr				= MCFGPIO_CLRH,
+		.pddr				= (void __iomem *)MCFGPIO_DDRH,
+		.podr				= (void __iomem *)MCFGPIO_PORTH,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTHP,
+		.setr				= (void __iomem *)MCFGPIO_SETH,
+		.clrr				= (void __iomem *)MCFGPIO_CLRH,
 	},
 	{
 		.gpio_chip			= {
@@ -257,11 +257,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 104,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRJ,
-		.podr				= MCFGPIO_PORTJ,
-		.ppdr				= MCFGPIO_PORTJP,
-		.setr				= MCFGPIO_SETJ,
-		.clrr				= MCFGPIO_CLRJ,
+		.pddr				= (void __iomem *)MCFGPIO_DDRJ,
+		.podr				= (void __iomem *)MCFGPIO_PORTJ,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTJP,
+		.setr				= (void __iomem *)MCFGPIO_SETJ,
+		.clrr				= (void __iomem *)MCFGPIO_CLRJ,
 	},
 	{
 		.gpio_chip			= {
@@ -275,11 +275,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 112,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDRDD,
-		.podr				= MCFGPIO_PORTDD,
-		.ppdr				= MCFGPIO_PORTDDP,
-		.setr				= MCFGPIO_SETDD,
-		.clrr				= MCFGPIO_CLRDD,
+		.pddr				= (void __iomem *)MCFGPIO_DDRDD,
+		.podr				= (void __iomem *)MCFGPIO_PORTDD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTDDP,
+		.setr				= (void __iomem *)MCFGPIO_SETDD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRDD,
 	},
 	{
 		.gpio_chip			= {
@@ -293,11 +293,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 120,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDREH,
-		.podr				= MCFGPIO_PORTEH,
-		.ppdr				= MCFGPIO_PORTEHP,
-		.setr				= MCFGPIO_SETEH,
-		.clrr				= MCFGPIO_CLREH,
+		.pddr				= (void __iomem *)MCFGPIO_DDREH,
+		.podr				= (void __iomem *)MCFGPIO_PORTEH,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTEHP,
+		.setr				= (void __iomem *)MCFGPIO_SETEH,
+		.clrr				= (void __iomem *)MCFGPIO_CLREH,
 	},
 	{
 		.gpio_chip			= {
@@ -311,11 +311,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 128,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_DDREL,
-		.podr				= MCFGPIO_PORTEL,
-		.ppdr				= MCFGPIO_PORTELP,
-		.setr				= MCFGPIO_SETEL,
-		.clrr				= MCFGPIO_CLREL,
+		.pddr				= (void __iomem *)MCFGPIO_DDREL,
+		.podr				= (void __iomem *)MCFGPIO_PORTEL,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTELP,
+		.setr				= (void __iomem *)MCFGPIO_SETEL,
+		.clrr				= (void __iomem *)MCFGPIO_CLREL,
 	},
 	{
 		.gpio_chip			= {
@@ -329,11 +329,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 136,
 			.ngpio			= 6,
 		},
-		.pddr				= MCFGPIO_DDRAS,
-		.podr				= MCFGPIO_PORTAS,
-		.ppdr				= MCFGPIO_PORTASP,
-		.setr				= MCFGPIO_SETAS,
-		.clrr				= MCFGPIO_CLRAS,
+		.pddr				= (void __iomem *)MCFGPIO_DDRAS,
+		.podr				= (void __iomem *)MCFGPIO_PORTAS,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTASP,
+		.setr				= (void __iomem *)MCFGPIO_SETAS,
+		.clrr				= (void __iomem *)MCFGPIO_CLRAS,
 	},
 	{
 		.gpio_chip			= {
@@ -347,11 +347,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 144,
 			.ngpio			= 7,
 		},
-		.pddr				= MCFGPIO_DDRQS,
-		.podr				= MCFGPIO_PORTQS,
-		.ppdr				= MCFGPIO_PORTQSP,
-		.setr				= MCFGPIO_SETQS,
-		.clrr				= MCFGPIO_CLRQS,
+		.pddr				= (void __iomem *)MCFGPIO_DDRQS,
+		.podr				= (void __iomem *)MCFGPIO_PORTQS,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTQSP,
+		.setr				= (void __iomem *)MCFGPIO_SETQS,
+		.clrr				= (void __iomem *)MCFGPIO_CLRQS,
 	},
 	{
 		.gpio_chip			= {
@@ -365,11 +365,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 152,
 			.ngpio			= 6,
 		},
-		.pddr				= MCFGPIO_DDRSD,
-		.podr				= MCFGPIO_PORTSD,
-		.ppdr				= MCFGPIO_PORTSDP,
-		.setr				= MCFGPIO_SETSD,
-		.clrr				= MCFGPIO_CLRSD,
+		.pddr				= (void __iomem *)MCFGPIO_DDRSD,
+		.podr				= (void __iomem *)MCFGPIO_PORTSD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTSDP,
+		.setr				= (void __iomem *)MCFGPIO_SETSD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRSD,
 	},
 	{
 		.gpio_chip			= {
@@ -383,11 +383,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 160,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_DDRTC,
-		.podr				= MCFGPIO_PORTTC,
-		.ppdr				= MCFGPIO_PORTTCP,
-		.setr				= MCFGPIO_SETTC,
-		.clrr				= MCFGPIO_CLRTC,
+		.pddr				= (void __iomem *)MCFGPIO_DDRTC,
+		.podr				= (void __iomem *)MCFGPIO_PORTTC,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTTCP,
+		.setr				= (void __iomem *)MCFGPIO_SETTC,
+		.clrr				= (void __iomem *)MCFGPIO_CLRTC,
 	},
 	{
 		.gpio_chip			= {
@@ -401,11 +401,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 168,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_DDRTD,
-		.podr				= MCFGPIO_PORTTD,
-		.ppdr				= MCFGPIO_PORTTDP,
-		.setr				= MCFGPIO_SETTD,
-		.clrr				= MCFGPIO_CLRTD,
+		.pddr				= (void __iomem *)MCFGPIO_DDRTD,
+		.podr				= (void __iomem *)MCFGPIO_PORTTD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTTDP,
+		.setr				= (void __iomem *)MCFGPIO_SETTD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRTD,
 	},
 	{
 		.gpio_chip			= {
@@ -419,11 +419,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 176,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_DDRUA,
-		.podr				= MCFGPIO_PORTUA,
-		.ppdr				= MCFGPIO_PORTUAP,
-		.setr				= MCFGPIO_SETUA,
-		.clrr				= MCFGPIO_CLRUA,
+		.pddr				= (void __iomem *)MCFGPIO_DDRUA,
+		.podr				= (void __iomem *)MCFGPIO_PORTUA,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTUAP,
+		.setr				= (void __iomem *)MCFGPIO_SETUA,
+		.clrr				= (void __iomem *)MCFGPIO_CLRUA,
 	},
 };
 
diff --git a/arch/m68knommu/platform/5307/gpio.c b/arch/m68knommu/platform/5307/gpio.c
index 8da5880..5850612 100644
--- a/arch/m68knommu/platform/5307/gpio.c
+++ b/arch/m68knommu/platform/5307/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 16,
 		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
 	},
 };
 
diff --git a/arch/m68knommu/platform/532x/gpio.c b/arch/m68knommu/platform/532x/gpio.c
index 184b773..212a85d 100644
--- a/arch/m68knommu/platform/532x/gpio.c
+++ b/arch/m68knommu/platform/532x/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
 	},
 	{
 		.gpio_chip			= {
@@ -48,11 +48,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 8,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FECH,
-		.podr				= MCFGPIO_PODR_FECH,
-		.ppdr				= MCFGPIO_PPDSDR_FECH,
-		.setr				= MCFGPIO_PPDSDR_FECH,
-		.clrr				= MCFGPIO_PCLRR_FECH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECH,
 	},
 	{
 		.gpio_chip			= {
@@ -66,11 +66,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 16,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_FECL,
-		.podr				= MCFGPIO_PODR_FECL,
-		.ppdr				= MCFGPIO_PPDSDR_FECL,
-		.setr				= MCFGPIO_PPDSDR_FECL,
-		.clrr				= MCFGPIO_PCLRR_FECL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECL,
 	},
 	{
 		.gpio_chip			= {
@@ -84,11 +84,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 24,
 			.ngpio			= 5,
 		},
-		.pddr				= MCFGPIO_PDDR_SSI,
-		.podr				= MCFGPIO_PODR_SSI,
-		.ppdr				= MCFGPIO_PPDSDR_SSI,
-		.setr				= MCFGPIO_PPDSDR_SSI,
-		.clrr				= MCFGPIO_PCLRR_SSI,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SSI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SSI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SSI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SSI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SSI,
 	},
 	{
 		.gpio_chip			= {
@@ -102,11 +102,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 32,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
 	},
 	{
 		.gpio_chip			= {
@@ -120,11 +120,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 40,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_BE,
-		.podr				= MCFGPIO_PODR_BE,
-		.ppdr				= MCFGPIO_PPDSDR_BE,
-		.setr				= MCFGPIO_PPDSDR_BE,
-		.clrr				= MCFGPIO_PCLRR_BE,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BE,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BE,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BE,
 	},
 	{
 		.gpio_chip			= {
@@ -138,11 +138,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 49,
 			.ngpio			= 5,
 		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
 	},
 	{
 		.gpio_chip			= {
@@ -156,11 +156,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 58,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_PWM,
-		.podr				= MCFGPIO_PODR_PWM,
-		.ppdr				= MCFGPIO_PPDSDR_PWM,
-		.setr				= MCFGPIO_PPDSDR_PWM,
-		.clrr				= MCFGPIO_PCLRR_PWM,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_PWM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_PWM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_PWM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_PWM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_PWM,
 	},
 	{
 		.gpio_chip			= {
@@ -174,11 +174,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 64,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
 	},
 	{
 		.gpio_chip			= {
@@ -192,11 +192,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 72,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_UART,
-		.podr				= MCFGPIO_PODR_UART,
-		.ppdr				= MCFGPIO_PPDSDR_UART,
-		.setr				= MCFGPIO_PPDSDR_UART,
-		.clrr				= MCFGPIO_PCLRR_UART,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UART,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UART,
 	},
 	{
 		.gpio_chip			= {
@@ -210,11 +210,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 80,
 			.ngpio			= 6,
 		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
 	},
 	{
 		.gpio_chip			= {
@@ -228,11 +228,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 88,
 			.ngpio			= 4,
 		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
 	},
 	{
 		.gpio_chip			= {
@@ -246,11 +246,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 96,
 			.ngpio			= 2,
 		},
-		.pddr				= MCFGPIO_PDDR_LCDDATAH,
-		.podr				= MCFGPIO_PODR_LCDDATAH,
-		.ppdr				= MCFGPIO_PPDSDR_LCDDATAH,
-		.setr				= MCFGPIO_PPDSDR_LCDDATAH,
-		.clrr				= MCFGPIO_PCLRR_LCDDATAH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAH,
 	},
 	{
 		.gpio_chip			= {
@@ -264,11 +264,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 104,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_LCDDATAM,
-		.podr				= MCFGPIO_PODR_LCDDATAM,
-		.ppdr				= MCFGPIO_PPDSDR_LCDDATAM,
-		.setr				= MCFGPIO_PPDSDR_LCDDATAM,
-		.clrr				= MCFGPIO_PCLRR_LCDDATAM,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAM,
 	},
 	{
 		.gpio_chip			= {
@@ -282,11 +282,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 112,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_LCDDATAL,
-		.podr				= MCFGPIO_PODR_LCDDATAL,
-		.ppdr				= MCFGPIO_PPDSDR_LCDDATAL,
-		.setr				= MCFGPIO_PPDSDR_LCDDATAL,
-		.clrr				= MCFGPIO_PCLRR_LCDDATAL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAL,
 	},
 	{
 		.gpio_chip			= {
@@ -300,11 +300,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 120,
 			.ngpio			= 1,
 		},
-		.pddr				= MCFGPIO_PDDR_LCDCTLH,
-		.podr				= MCFGPIO_PODR_LCDCTLH,
-		.ppdr				= MCFGPIO_PPDSDR_LCDCTLH,
-		.setr				= MCFGPIO_PPDSDR_LCDCTLH,
-		.clrr				= MCFGPIO_PCLRR_LCDCTLH,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDCTLH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDCTLH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDCTLH,
 	},
 	{
 		.gpio_chip			= {
@@ -318,11 +318,11 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.base			= 128,
 			.ngpio			= 8,
 		},
-		.pddr				= MCFGPIO_PDDR_LCDCTLL,
-		.podr				= MCFGPIO_PODR_LCDCTLL,
-		.ppdr				= MCFGPIO_PPDSDR_LCDCTLL,
-		.setr				= MCFGPIO_PPDSDR_LCDCTLL,
-		.clrr				= MCFGPIO_PCLRR_LCDCTLL,
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDCTLL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDCTLL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDCTLL,
 	},
 };
 
diff --git a/arch/m68knommu/platform/5407/gpio.c b/arch/m68knommu/platform/5407/gpio.c
index 8da5880..5850612 100644
--- a/arch/m68knommu/platform/5407/gpio.c
+++ b/arch/m68knommu/platform/5407/gpio.c
@@ -32,9 +32,9 @@ static struct mcf_gpio_chip mcf_gpio_chips[] = {
 			.set			= mcf_gpio_set_value,
 			.ngpio			= 16,
 		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
 	},
 };
 
diff --git a/arch/m68knommu/platform/54xx/Makefile b/arch/m68knommu/platform/54xx/Makefile
index e6035e7..6cfd090 100644
--- a/arch/m68knommu/platform/54xx/Makefile
+++ b/arch/m68knommu/platform/54xx/Makefile
@@ -15,4 +15,5 @@
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
 
 obj-y := config.o
+obj-$(CONFIG_FIREBEE) += firebee.o
 
diff --git a/arch/m68knommu/platform/54xx/firebee.c b/arch/m68knommu/platform/54xx/firebee.c
new file mode 100644
index 0000000..46d5053
--- /dev/null
+++ b/arch/m68knommu/platform/54xx/firebee.c
@@ -0,0 +1,86 @@
+/***************************************************************************/
+
+/*
+ *	firebee.c -- extra startup code support for the FireBee boards
+ *
+ *	Copyright (C) 2011, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+/*
+ *	8MB of NOR flash fitted to the FireBee board.
+ */
+#define	FLASH_PHYS_ADDR		0xe0000000	/* Physical address of flash */
+#define	FLASH_PHYS_SIZE		0x00800000	/* Size of flash */
+
+#define	PART_BOOT_START		0x00000000	/* Start at bottom of flash */
+#define	PART_BOOT_SIZE		0x00040000	/* 256k in size */
+#define	PART_IMAGE_START	0x00040000	/* Start after boot loader */
+#define	PART_IMAGE_SIZE		0x006c0000	/* Most of flash */
+#define	PART_FPGA_START		0x00700000	/* Start at offset 7MB */
+#define	PART_FPGA_SIZE		0x00100000	/* 1MB in size */
+
+static struct mtd_partition firebee_flash_parts[] = {
+	{
+		.name	= "dBUG",
+		.offset	= PART_BOOT_START,
+		.size	= PART_BOOT_SIZE,
+	},
+	{
+		.name	= "FPGA",
+		.offset	= PART_FPGA_START,
+		.size	= PART_FPGA_SIZE,
+	},
+	{
+		.name	= "image",
+		.offset	= PART_IMAGE_START,
+		.size	= PART_IMAGE_SIZE,
+	},
+};
+
+static struct physmap_flash_data firebee_flash_data = {
+	.width		= 2,
+	.nr_parts	= ARRAY_SIZE(firebee_flash_parts),
+	.parts		= firebee_flash_parts,
+};
+
+static struct resource firebee_flash_resource = {
+	.start		= FLASH_PHYS_ADDR,
+	.end		= FLASH_PHYS_ADDR + FLASH_PHYS_SIZE,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device firebee_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &firebee_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &firebee_flash_resource,
+};
+
+/***************************************************************************/
+
+static int __init init_firebee(void)
+{
+	platform_device_register(&firebee_flash);
+	return 0;
+}
+
+arch_initcall(init_firebee);
+
+/***************************************************************************/
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
index 2a3af19..e563183 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68knommu/platform/68328/ints.c
@@ -135,20 +135,20 @@ void process_int(int vec, struct pt_regs *fp)
 	}
 }
 
-static void intc_irq_unmask(unsigned int irq)
+static void intc_irq_unmask(struct irq_data *d)
 {
-	IMR &= ~(1<<irq);
+	IMR &= ~(1 << d->irq);
 }
 
-static void intc_irq_mask(unsigned int irq)
+static void intc_irq_mask(struct irq_data *d)
 {
-	IMR |= (1<<irq);
+	IMR |= (1 << d->irq);
 }
 
 static struct irq_chip intc_irq_chip = {
 	.name		= "M68K-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
 };
 
 /*
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c
index a29041c..8de3feb 100644
--- a/arch/m68knommu/platform/68360/ints.c
+++ b/arch/m68knommu/platform/68360/ints.c
@@ -37,26 +37,26 @@ extern void *_ramvec[];
 /* The number of spurious interrupts */
 volatile unsigned int num_spurious;
 
-static void intc_irq_unmask(unsigned int irq)
+static void intc_irq_unmask(struct irq_data *d)
 {
-	pquicc->intr_cimr |= (1 << irq);
+	pquicc->intr_cimr |= (1 << d->irq);
 }
 
-static void intc_irq_mask(unsigned int irq)
+static void intc_irq_mask(struct irq_data *d)
 {
-	pquicc->intr_cimr &= ~(1 << irq);
+	pquicc->intr_cimr &= ~(1 << d->irq);
 }
 
-static void intc_irq_ack(unsigned int irq)
+static void intc_irq_ack(struct irq_data *d)
 {
-	pquicc->intr_cisr = (1 << irq);
+	pquicc->intr_cisr = (1 << d->irq);
 }
 
 static struct irq_chip intc_irq_chip = {
 	.name		= "M68K-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.ack		= intc_irq_ack,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_ack	= intc_irq_ack,
 };
 
 /*
diff --git a/arch/m68knommu/platform/coldfire/dma.c b/arch/m68knommu/platform/coldfire/dma.c
index 2b30cf1..e88b95e 100644
--- a/arch/m68knommu/platform/coldfire/dma.c
+++ b/arch/m68knommu/platform/coldfire/dma.c
@@ -21,16 +21,16 @@
  */
 unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
 #ifdef MCFDMA_BASE0
-	MCF_MBAR + MCFDMA_BASE0,
+	MCFDMA_BASE0,
 #endif
 #ifdef MCFDMA_BASE1
-	MCF_MBAR + MCFDMA_BASE1,
+	MCFDMA_BASE1,
 #endif
 #ifdef MCFDMA_BASE2
-	MCF_MBAR + MCFDMA_BASE2,
+	MCFDMA_BASE2,
 #endif
 #ifdef MCFDMA_BASE3
-	MCF_MBAR + MCFDMA_BASE3,
+	MCFDMA_BASE3,
 #endif
 };
 
diff --git a/arch/m68knommu/platform/coldfire/head.S b/arch/m68knommu/platform/coldfire/head.S
index d597790..129bff49 100644
--- a/arch/m68knommu/platform/coldfire/head.S
+++ b/arch/m68knommu/platform/coldfire/head.S
@@ -41,17 +41,17 @@
  *	DRAM controller is quite different.
  */
 .macro GET_MEM_SIZE
-	movel	MCF_MBAR+MCFSIM_DMR0,%d0 /* get mask for 1st bank */
+	movel	MCFSIM_DMR0,%d0		/* get mask for 1st bank */
 	btst	#0,%d0			/* check if region enabled */
 	beq	1f
 	andl	#0xfffc0000,%d0
 	beq	1f
 	addl	#0x00040000,%d0		/* convert mask to size */
 1:
-	movel	MCF_MBAR+MCFSIM_DMR1,%d1 /* get mask for 2nd bank */
+	movel	MCFSIM_DMR1,%d1		/* get mask for 2nd bank */
 	btst	#0,%d1			/* check if region enabled */
 	beq	2f
-	andl	#0xfffc0000, %d1
+	andl	#0xfffc0000,%d1
 	beq	2f
 	addl	#0x00040000,%d1
 	addl	%d1,%d0			/* total mem size in d0 */
@@ -68,14 +68,14 @@
 #elif defined(CONFIG_M520x)
 .macro GET_MEM_SIZE
 	clrl	%d0
-	movel	MCF_MBAR+MCFSIM_SDCS0, %d2 /* Get SDRAM chip select 0 config */
+	movel	MCFSIM_SDCS0, %d2	/* Get SDRAM chip select 0 config */
 	andl	#0x1f, %d2		/* Get only the chip select size */
 	beq	3f			/* Check if it is enabled */
 	addql	#1, %d2			/* Form exponent */
 	moveql	#1, %d0
 	lsll	%d2, %d0		/* 2 ^ exponent */
 3:
-	movel	MCF_MBAR+MCFSIM_SDCS1, %d2 /* Get SDRAM chip select 1 config */
+	movel	MCFSIM_SDCS1, %d2	/* Get SDRAM chip select 1 config */
 	andl	#0x1f, %d2		/* Get only the chip select size */
 	beq	4f			/* Check if it is enabled */
 	addql	#1, %d2			/* Form exponent */
diff --git a/arch/m68knommu/platform/coldfire/intc-2.c b/arch/m68knommu/platform/coldfire/intc-2.c
index 85daa2b..2cbfbf0 100644
--- a/arch/m68knommu/platform/coldfire/intc-2.c
+++ b/arch/m68knommu/platform/coldfire/intc-2.c
@@ -7,7 +7,10 @@
  * family, the 5270, 5271, 5274, 5275, and the 528x family which have two such
  * controllers, and the 547x and 548x families which have only one of them.
  *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ * The external 7 fixed interrupts are part the the Edge Port unit of these
+ * ColdFire parts. They can be configured as level or edge triggered.
+ *
+ * (C) Copyright 2009-2011, Greg Ungerer <gerg@snapgear.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
@@ -31,11 +34,12 @@
 #define MCFSIM_ICR_PRI(p)	(p)		/* Priority p intr */
 
 /*
- *	Each vector needs a unique priority and level associated with it.
- *	We don't really care so much what they are, we don't rely on the
- *	traditional priority interrupt scheme of the m68k/ColdFire.
+ *	The EDGE Port interrupts are the fixed 7 external interrupts.
+ *	They need some special treatment, for example they need to be acked.
  */
-static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
+#define	EINT0	64	/* Is not actually used, but spot reserved for it */
+#define	EINT1	65	/* EDGE Port interrupt 1 */
+#define	EINT7	71	/* EDGE Port interrupt 7 */
 
 #ifdef MCFICM_INTC1
 #define NR_VECS	128
@@ -43,66 +47,147 @@ static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
 #define NR_VECS	64
 #endif
 
-static void intc_irq_mask(unsigned int irq)
+static void intc_irq_mask(struct irq_data *d)
 {
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
-		unsigned long imraddr;
-		u32 val, imrbit;
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long imraddr;
+	u32 val, imrbit;
 
-		irq -= MCFINT_VECBASE;
-		imraddr = MCF_IPSBAR;
 #ifdef MCFICM_INTC1
-		imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+	imraddr = (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
 #else
-		imraddr += MCFICM_INTC0;
+	imraddr = MCFICM_INTC0;
 #endif
-		imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
-		imrbit = 0x1 << (irq & 0x1f);
+	imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
+	imrbit = 0x1 << (irq & 0x1f);
 
-		val = __raw_readl(imraddr);
-		__raw_writel(val | imrbit, imraddr);
-	}
+	val = __raw_readl(imraddr);
+	__raw_writel(val | imrbit, imraddr);
+}
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long imraddr;
+	u32 val, imrbit;
+
+#ifdef MCFICM_INTC1
+	imraddr = (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+	imraddr = MCFICM_INTC0;
+#endif
+	imraddr += ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
+	imrbit = 0x1 << (irq & 0x1f);
+
+	/* Don't set the "maskall" bit! */
+	if ((irq & 0x20) == 0)
+		imrbit |= 0x1;
+
+	val = __raw_readl(imraddr);
+	__raw_writel(val & ~imrbit, imraddr);
+}
+
+/*
+ *	Only the external (or EDGE Port) interrupts need to be acknowledged
+ *	here, as part of the IRQ handler. They only really need to be ack'ed
+ *	if they are in edge triggered mode, but there is no harm in doing it
+ *	for all types.
+ */
+static void intc_irq_ack(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	__raw_writeb(0x1 << (irq - EINT0), MCFEPORT_EPFR);
 }
 
-static void intc_irq_unmask(unsigned int irq)
+/*
+ *	Each vector needs a unique priority and level associated with it.
+ *	We don't really care so much what they are, we don't rely on the
+ *	traditional priority interrupt scheme of the m68k/ColdFire. This
+ *	only needs to be set once for an interrupt, and we will never change
+ *	these values once we have set them.
+ */
+static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
+
+static unsigned int intc_irq_startup(struct irq_data *d)
 {
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
-		unsigned long intaddr, imraddr, icraddr;
-		u32 val, imrbit;
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long icraddr;
 
-		irq -= MCFINT_VECBASE;
-		intaddr = MCF_IPSBAR;
 #ifdef MCFICM_INTC1
-		intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+	icraddr = (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
 #else
-		intaddr += MCFICM_INTC0;
+	icraddr = MCFICM_INTC0;
 #endif
-		imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
-		icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
-		imrbit = 0x1 << (irq & 0x1f);
+	icraddr += MCFINTC_ICR0 + (irq & 0x3f);
+	if (__raw_readb(icraddr) == 0)
+		__raw_writeb(intc_intpri--, icraddr);
 
-		/* Don't set the "maskall" bit! */
-		if ((irq & 0x20) == 0)
-			imrbit |= 0x1;
+	irq = d->irq;
+	if ((irq >= EINT1) && (irq <= EINT7)) {
+		u8 v;
 
-		if (__raw_readb(icraddr) == 0)
-			__raw_writeb(intc_intpri--, icraddr);
+		irq -= EINT0;
 
-		val = __raw_readl(imraddr);
-		__raw_writel(val & ~imrbit, imraddr);
+		/* Set EPORT line as input */
+		v = __raw_readb(MCFEPORT_EPDDR);
+		__raw_writeb(v & ~(0x1 << irq), MCFEPORT_EPDDR);
+
+		/* Set EPORT line as interrupt source */
+		v = __raw_readb(MCFEPORT_EPIER);
+		__raw_writeb(v | (0x1 << irq), MCFEPORT_EPIER);
 	}
+
+	intc_irq_unmask(d);
+	return 0;
 }
 
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
 {
+	unsigned int irq = d->irq;
+	u16 pa, tb;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		tb = 0x1;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		tb = 0x2;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		tb = 0x3;
+		break;
+	default:
+		/* Level triggered */
+		tb = 0;
+		break;
+	}
+
+	if (tb)
+		set_irq_handler(irq, handle_edge_irq);
+
+	irq -= EINT0;
+	pa = __raw_readw(MCFEPORT_EPPAR);
+	pa = (pa & ~(0x3 << (irq * 2))) | (tb << (irq * 2));
+	__raw_writew(pa, MCFEPORT_EPPAR);
+	
 	return 0;
 }
 
 static struct irq_chip intc_irq_chip = {
 	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.set_type	= intc_irq_set_type,
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+};
+
+static struct irq_chip intc_irq_chip_edge_port = {
+	.name		= "CF-INTC-EP",
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_ack	= intc_irq_ack,
+	.irq_set_type	= intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
@@ -112,13 +197,16 @@ void __init init_IRQ(void)
 	init_vectors();
 
 	/* Mask all interrupt sources */
-	__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
+	__raw_writel(0x1, MCFICM_INTC0 + MCFINTC_IMRL);
 #ifdef MCFICM_INTC1
-	__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
+	__raw_writel(0x1, MCFICM_INTC1 + MCFINTC_IMRL);
 #endif
 
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		set_irq_chip(irq, &intc_irq_chip);
+	for (irq = MCFINT_VECBASE; (irq < MCFINT_VECBASE + NR_VECS); irq++) {
+		if ((irq >= EINT1) && (irq <=EINT7))
+			set_irq_chip(irq, &intc_irq_chip_edge_port);
+		else
+			set_irq_chip(irq, &intc_irq_chip);
 		set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
 		set_irq_handler(irq, handle_level_irq);
 	}
diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68knommu/platform/coldfire/intc-simr.c
index bb704863..e642b24 100644
--- a/arch/m68knommu/platform/coldfire/intc-simr.c
+++ b/arch/m68knommu/platform/coldfire/intc-simr.c
@@ -3,7 +3,7 @@
  *
  * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts.
  *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
+ * (C) Copyright 2009-2011, Greg Ungerer <gerg@snapgear.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
@@ -20,47 +20,156 @@
 #include <asm/mcfsim.h>
 #include <asm/traps.h>
 
-static void intc_irq_mask(unsigned int irq)
+/*
+ *	The EDGE Port interrupts are the fixed 7 external interrupts.
+ *	They need some special treatment, for example they need to be acked.
+ */
+#ifdef CONFIG_M520x
+/*
+ *	The 520x parts only support a limited range of these external
+ *	interrupts, only 1, 4 and 7 (as interrupts 65, 66 and 67).
+ */
+#define	EINT0	64	/* Is not actually used, but spot reserved for it */
+#define	EINT1	65	/* EDGE Port interrupt 1 */
+#define	EINT4	66	/* EDGE Port interrupt 4 */
+#define	EINT7	67	/* EDGE Port interrupt 7 */
+
+static unsigned int irqebitmap[] = { 0, 1, 4, 7 };
+static unsigned int inline irq2ebit(unsigned int irq)
 {
-	if (irq >= MCFINT_VECBASE) {
-		if (irq < MCFINT_VECBASE + 64)
-			__raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_SIMR);
-		else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_SIMR)
-			__raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_SIMR);
-	}
+	return irqebitmap[irq - EINT0];
+}
+
+#else
+
+/*
+ *	Most of the ColdFire parts with the EDGE Port module just have
+ *	a strait direct mapping of the 7 external interrupts. Although
+ *	there is a bit reserved for 0, it is not used.
+ */
+#define	EINT0	64	/* Is not actually used, but spot reserved for it */
+#define	EINT1	65	/* EDGE Port interrupt 1 */
+#define	EINT7	71	/* EDGE Port interrupt 7 */
+
+static unsigned int inline irq2ebit(unsigned int irq)
+{
+	return irq - EINT0;
+}
+
+#endif
+
+/*
+ *	There maybe one or two interrupt control units, each has 64
+ *	interrupts. If there is no second unit then MCFINTC1_* defines
+ *	will be 0 (and code for them optimized away).
+ */
+
+static void intc_irq_mask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+
+	if (MCFINTC1_SIMR && (irq > 64))
+		__raw_writeb(irq - 64, MCFINTC1_SIMR);
+	else
+		__raw_writeb(irq, MCFINTC0_SIMR);
 }
 
-static void intc_irq_unmask(unsigned int irq)
+static void intc_irq_unmask(struct irq_data *d)
 {
-	if (irq >= MCFINT_VECBASE) {
-		if (irq < MCFINT_VECBASE + 64)
-			__raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_CIMR);
-		else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_CIMR)
-			__raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_CIMR);
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+
+	if (MCFINTC1_CIMR && (irq > 64))
+		__raw_writeb(irq - 64, MCFINTC1_CIMR);
+	else
+		__raw_writeb(irq, MCFINTC0_CIMR);
+}
+
+static void intc_irq_ack(struct irq_data *d)
+{
+	unsigned int ebit = irq2ebit(d->irq);
+
+	__raw_writeb(0x1 << ebit, MCFEPORT_EPFR);
+}
+
+static unsigned int intc_irq_startup(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	if ((irq >= EINT1) && (irq <= EINT7)) {
+		unsigned int ebit = irq2ebit(irq);
+		u8 v;
+
+		/* Set EPORT line as input */
+		v = __raw_readb(MCFEPORT_EPDDR);
+		__raw_writeb(v & ~(0x1 << ebit), MCFEPORT_EPDDR);
+
+		/* Set EPORT line as interrupt source */
+		v = __raw_readb(MCFEPORT_EPIER);
+		__raw_writeb(v | (0x1 << ebit), MCFEPORT_EPIER);
 	}
+
+	irq -= MCFINT_VECBASE;
+	if (MCFINTC1_ICR0 && (irq > 64))
+		__raw_writeb(5, MCFINTC1_ICR0 + irq - 64);
+	else
+		__raw_writeb(5, MCFINTC0_ICR0 + irq);
+
+
+	intc_irq_unmask(d);
+	return 0;
 }
 
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	if (irq >= MCFINT_VECBASE) {
-		if (irq < MCFINT_VECBASE + 64)
-			__raw_writeb(5, MCFINTC0_ICR0 + irq - MCFINT_VECBASE);
-		else if ((irq < MCFINT_VECBASE) && MCFINTC1_ICR0)
-			__raw_writeb(5, MCFINTC1_ICR0 + irq - MCFINT_VECBASE - 64);
+	unsigned int ebit, irq = d->irq;
+	u16 pa, tb;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		tb = 0x1;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		tb = 0x2;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		tb = 0x3;
+		break;
+	default:
+		/* Level triggered */
+		tb = 0;
+		break;
 	}
+
+	if (tb)
+		set_irq_handler(irq, handle_edge_irq);
+
+	ebit = irq2ebit(irq) * 2;
+	pa = __raw_readw(MCFEPORT_EPPAR);
+	pa = (pa & ~(0x3 << ebit)) | (tb << ebit);
+	__raw_writew(pa, MCFEPORT_EPPAR);
+	
 	return 0;
 }
 
 static struct irq_chip intc_irq_chip = {
 	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.set_type	= intc_irq_set_type,
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+};
+
+static struct irq_chip intc_irq_chip_edge_port = {
+	.name		= "CF-INTC-EP",
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_ack	= intc_irq_ack,
+	.irq_set_type	= intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
 {
-	int irq;
+	int irq, eirq;
 
 	init_vectors();
 
@@ -69,8 +178,12 @@ void __init init_IRQ(void)
 	if (MCFINTC1_SIMR)
 		__raw_writeb(0xff, MCFINTC1_SIMR);
 
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		set_irq_chip(irq, &intc_irq_chip);
+	eirq = MCFINT_VECBASE + 64 + (MCFINTC1_ICR0 ? 64 : 0);
+	for (irq = MCFINT_VECBASE; (irq < eirq); irq++) {
+		if ((irq >= EINT1) && (irq <= EINT7))
+			set_irq_chip(irq, &intc_irq_chip_edge_port);
+		else
+			set_irq_chip(irq, &intc_irq_chip);
 		set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
 		set_irq_handler(irq, handle_level_irq);
 	}
diff --git a/arch/m68knommu/platform/coldfire/intc.c b/arch/m68knommu/platform/coldfire/intc.c
index 60d2fcb..d648081 100644
--- a/arch/m68knommu/platform/coldfire/intc.c
+++ b/arch/m68knommu/platform/coldfire/intc.c
@@ -111,28 +111,28 @@ void mcf_autovector(int irq)
 #endif
 }
 
-static void intc_irq_mask(unsigned int irq)
+static void intc_irq_mask(struct irq_data *d)
 {
-	if (mcf_irq2imr[irq])
-		mcf_setimr(mcf_irq2imr[irq]);
+	if (mcf_irq2imr[d->irq])
+		mcf_setimr(mcf_irq2imr[d->irq]);
 }
 
-static void intc_irq_unmask(unsigned int irq)
+static void intc_irq_unmask(struct irq_data *d)
 {
-	if (mcf_irq2imr[irq])
-		mcf_clrimr(mcf_irq2imr[irq]);
+	if (mcf_irq2imr[d->irq])
+		mcf_clrimr(mcf_irq2imr[d->irq]);
 }
 
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
 {
 	return 0;
 }
 
 static struct irq_chip intc_irq_chip = {
 	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.set_type	= intc_irq_set_type,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_set_type	= intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
diff --git a/arch/m68knommu/platform/coldfire/pit.c b/arch/m68knommu/platform/coldfire/pit.c
index aebea19..c2b9809 100644
--- a/arch/m68knommu/platform/coldfire/pit.c
+++ b/arch/m68knommu/platform/coldfire/pit.c
@@ -31,7 +31,7 @@
  *	By default use timer1 as the system clock timer.
  */
 #define	FREQ	((MCF_CLK / 2) / 64)
-#define	TA(a)	(MCF_IPSBAR + MCFPIT_BASE1 + (a))
+#define	TA(a)	(MCFPIT_BASE1 + (a))
 #define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
 
 static u32 pit_cnt;
diff --git a/arch/m68knommu/platform/coldfire/timers.c b/arch/m68knommu/platform/coldfire/timers.c
index 2304d73..60242f6 100644
--- a/arch/m68knommu/platform/coldfire/timers.c
+++ b/arch/m68knommu/platform/coldfire/timers.c
@@ -28,7 +28,7 @@
  *	By default use timer1 as the system clock timer.
  */
 #define	FREQ	(MCF_BUSCLK / 16)
-#define	TA(a)	(MCF_MBAR + MCFTIMER_BASE1 + (a))
+#define	TA(a)	(MCFTIMER_BASE1 + (a))
 
 /*
  *	These provide the underlying interrupt vector support.
@@ -126,7 +126,7 @@ void hw_timer_init(void)
 /*
  *	By default use timer2 as the profiler clock timer.
  */
-#define	PA(a)	(MCF_MBAR + MCFTIMER_BASE2 + (a))
+#define	PA(a)	(MCFTIMER_BASE2 + (a))
 
 /*
  *	Choose a reasonably fast profile timer. Make it an odd value to
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 3168003..922c419 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -17,6 +17,7 @@ config MICROBLAZE
 	select OF_EARLY_FLATTREE
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config SWAP
 	def_bool n
@@ -183,6 +184,17 @@ config LOWMEM_SIZE
 	hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
 	default "0x30000000"
 
+config MANUAL_RESET_VECTOR
+	hex "Microblaze reset vector address setup"
+	default "0x0"
+	help
+	  Set this option to have the kernel override the CPU Reset vector.
+	  If zero, no change will be made to the MicroBlaze reset vector at
+	  address 0x0.
+	  If non-zero, a jump instruction to this address, will be written
+	  to the reset vector at address 0x0.
+	  If you are unsure, set it to default value 0x0.
+
 config KERNEL_START_BOOL
 	bool "Set custom kernel base address"
 	depends on ADVANCED_OPTIONS
@@ -247,7 +259,7 @@ endmenu
 
 source "mm/Kconfig"
 
-menu "Exectuable file formats"
+menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
 
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h
index 7ebd955..0f553bc 100644
--- a/arch/microblaze/include/asm/cacheflush.h
+++ b/arch/microblaze/include/asm/cacheflush.h
@@ -84,12 +84,13 @@ do { \
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
 
-
 #define flush_cache_dup_mm(mm)				do { } while (0)
 #define flush_cache_vmap(start, end)			do { } while (0)
 #define flush_cache_vunmap(start, end)			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
+
+#define flush_cache_page(vma, vmaddr, pfn) \
+	flush_dcache_range(pfn << PAGE_SHIFT, (pfn << PAGE_SHIFT) + PAGE_SIZE);
 
 /* MS: kgdb code use this macro, wrong len with FLASH */
 #if 0
@@ -104,9 +105,13 @@ do { \
 #define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
 do {									\
 	u32 addr = virt_to_phys(dst);					\
-	invalidate_icache_range((unsigned) (addr), (unsigned) (addr) + (len));\
 	memcpy((dst), (src), (len));					\
-	flush_dcache_range((unsigned) (addr), (unsigned) (addr) + (len));\
+	if (vma->vm_flags & VM_EXEC) {					\
+		invalidate_icache_range((unsigned) (addr),		\
+					(unsigned) (addr) + PAGE_SIZE);	\
+		flush_dcache_range((unsigned) (addr),			\
+					(unsigned) (addr) + PAGE_SIZE);	\
+	}								\
 } while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len)		\
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h
index cd25753..d8f0133 100644
--- a/arch/microblaze/include/asm/cpuinfo.h
+++ b/arch/microblaze/include/asm/cpuinfo.h
@@ -96,8 +96,8 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
 
 static inline unsigned int fcpu(struct device_node *cpu, char *n)
 {
-	int *val;
-	return (val = (int *) of_get_property(cpu, n, NULL)) ?
+	const __be32 *val;
+	return (val = of_get_property(cpu, n, NULL)) ?
 							be32_to_cpup(val) : 0;
 }
 
diff --git a/arch/microblaze/include/asm/entry.h b/arch/microblaze/include/asm/entry.h
index ec89f2a..af0144b 100644
--- a/arch/microblaze/include/asm/entry.h
+++ b/arch/microblaze/include/asm/entry.h
@@ -31,40 +31,4 @@ DECLARE_PER_CPU(unsigned int, R11_SAVE); /* Temp variable for entry */
 DECLARE_PER_CPU(unsigned int, CURRENT_SAVE); /* Saved current pointer */
 # endif /* __ASSEMBLY__ */
 
-#ifndef CONFIG_MMU
-
-/* noMMU hasn't any space for args */
-# define STATE_SAVE_ARG_SPACE	(0)
-
-#else /* CONFIG_MMU */
-
-/* If true, system calls save and restore all registers (except result
- * registers, of course).  If false, then `call clobbered' registers
- * will not be preserved, on the theory that system calls are basically
- * function calls anyway, and the caller should be able to deal with it.
- * This is a security risk, of course, as `internal' values may leak out
- * after a system call, but that certainly doesn't matter very much for
- * a processor with no MMU protection!  For a protected-mode kernel, it
- * would be faster to just zero those registers before returning.
- *
- * I can not rely on the glibc implementation. If you turn it off make
- * sure that r11/r12 is saved in user-space. --KAA
- *
- * These are special variables using by the kernel trap/interrupt code
- * to save registers in, at a time when there are no spare registers we
- * can use to do so, and we can't depend on the value of the stack
- * pointer.  This means that they must be within a signed 16-bit
- * displacement of 0x00000000.
- */
-
-/* A `state save frame' is a struct pt_regs preceded by some extra space
- * suitable for a function call stack frame. */
-
-/* Amount of room on the stack reserved for arguments and to satisfy the
- * C calling conventions, in addition to the space used by the struct
- * pt_regs that actually holds saved values. */
-#define STATE_SAVE_ARG_SPACE	(6*4) /* Up to six arguments */
-
-#endif /* CONFIG_MMU */
-
 #endif /* _ASM_MICROBLAZE_ENTRY_H */
diff --git a/arch/microblaze/include/asm/exceptions.h b/arch/microblaze/include/asm/exceptions.h
index 6479097..e6a8dde 100644
--- a/arch/microblaze/include/asm/exceptions.h
+++ b/arch/microblaze/include/asm/exceptions.h
@@ -66,6 +66,9 @@
 asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
 							int fsr, int addr);
 
+asmlinkage void sw_exception(struct pt_regs *regs);
+void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig);
+
 void die(const char *str, struct pt_regs *fp, long err);
 void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
 
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index ad3fd61..b0526d2 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -29,7 +29,7 @@
 })
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -94,31 +94,34 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
-					cmp	%1, %0, %3;		\
-					beqi	%1, 3f;			\
-				2:	swx	%4, %2, r0;		\
-					addic	%1, r0, 0;		\
-					bnei	%1, 1b;			\
+	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
+					cmp	%2, %1, %4;		\
+					beqi	%2, 3f;			\
+				2:	swx	%5, %3, r0;		\
+					addic	%2, r0, 0;		\
+					bnei	%2, 1b;			\
 				3:					\
 				.section .fixup,\"ax\";			\
 				4:	brid	3b;			\
-					addik	%0, r0, %5;		\
+					addik	%0, r0, %6;		\
 				.previous;				\
 				.section __ex_table,\"a\";		\
 				.word	1b,4b,2b,4b;			\
 				.previous;"				\
-		: "=&r" (prev), "=&r"(cmp)				\
+		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
 		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
index ec5583d..cc54187 100644
--- a/arch/microblaze/include/asm/irq.h
+++ b/arch/microblaze/include/asm/irq.h
@@ -12,8 +12,6 @@
 #define NR_IRQS 32
 #include <asm-generic/irq.h>
 
-#include <linux/interrupt.h>
-
 /* This type is the placeholder for a hardware interrupt number. It has to
  * be big enough to enclose whatever representation is used by a given
  * platform.
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
index 0c68764..1071766 100644
--- a/arch/microblaze/include/asm/pci-bridge.h
+++ b/arch/microblaze/include/asm/pci-bridge.h
@@ -104,11 +104,22 @@ struct pci_controller {
 	int global_number;	/* PCI domain number */
 };
 
+#ifdef CONFIG_PCI
 static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 {
 	return bus->sysdata;
 }
 
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	struct pci_controller *host;
+
+	if (bus->self)
+		return pci_device_to_OF_node(bus->self);
+	host = pci_bus_to_host(bus);
+	return host ? host->dn : NULL;
+}
+
 static inline int isa_vaddr_is_ioport(void __iomem *address)
 {
 	/* No specific ISA handling on ppc32 at this stage, it
@@ -116,6 +127,7 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
 	 */
 	return 0;
 }
+#endif /* CONFIG_PCI */
 
 /* These are used for config access before all the PCI probing
    has been done. */
diff --git a/arch/microblaze/include/asm/pgtable.h b/arch/microblaze/include/asm/pgtable.h
index 885574a..b2af423 100644
--- a/arch/microblaze/include/asm/pgtable.h
+++ b/arch/microblaze/include/asm/pgtable.h
@@ -572,7 +572,7 @@ void __init *early_get_page(void);
 
 extern unsigned long ioremap_bot, ioremap_base;
 
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle);
 void consistent_free(size_t size, void *vaddr);
 void consistent_sync(void *vaddr, size_t size, int direction);
 void consistent_sync_page(struct page *page, unsigned long offset,
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index 8eeb092..aed2a6b 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -155,7 +155,7 @@ unsigned long get_wchan(struct task_struct *p);
 #  define task_regs(task) ((struct pt_regs *)task_tos(task) - 1)
 
 #  define task_pt_regs_plus_args(tsk) \
-	(((void *)task_pt_regs(tsk)) - STATE_SAVE_ARG_SPACE)
+	((void *)task_pt_regs(tsk))
 
 #  define task_sp(task)	(task_regs(task)->r1)
 #  define task_pc(task)	(task_regs(task)->pc)
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index 2e72af0..d0890d3 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -64,21 +64,6 @@ extern void kdump_move_device_tree(void);
 /* CPU OF node matching */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev:	the device whose interrupt is to be resolved
- * @out_irq:	structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-struct pci_dev;
-struct of_irq;
-extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
-
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
diff --git a/arch/microblaze/include/asm/ptrace.h b/arch/microblaze/include/asm/ptrace.h
index d74dbfb..d9b6630 100644
--- a/arch/microblaze/include/asm/ptrace.h
+++ b/arch/microblaze/include/asm/ptrace.h
@@ -66,13 +66,13 @@ void show_regs(struct pt_regs *);
 #else /* __KERNEL__ */
 
 /* pt_regs offsets used by gdbserver etc in ptrace syscalls */
-#define PT_GPR(n)       ((n) * sizeof(microblaze_reg_t))
-#define PT_PC           (32 * sizeof(microblaze_reg_t))
-#define PT_MSR          (33 * sizeof(microblaze_reg_t))
-#define PT_EAR          (34 * sizeof(microblaze_reg_t))
-#define PT_ESR          (35 * sizeof(microblaze_reg_t))
-#define PT_FSR          (36 * sizeof(microblaze_reg_t))
-#define PT_KERNEL_MODE  (37 * sizeof(microblaze_reg_t))
+#define PT_GPR(n)	((n) * sizeof(microblaze_reg_t))
+#define PT_PC		(32 * sizeof(microblaze_reg_t))
+#define PT_MSR		(33 * sizeof(microblaze_reg_t))
+#define PT_EAR		(34 * sizeof(microblaze_reg_t))
+#define PT_ESR		(35 * sizeof(microblaze_reg_t))
+#define PT_FSR		(36 * sizeof(microblaze_reg_t))
+#define PT_KERNEL_MODE	(37 * sizeof(microblaze_reg_t))
 
 #endif /* __KERNEL */
 
diff --git a/arch/microblaze/include/asm/syscall.h b/arch/microblaze/include/asm/syscall.h
index 048dfcd..9bc4317 100644
--- a/arch/microblaze/include/asm/syscall.h
+++ b/arch/microblaze/include/asm/syscall.h
@@ -96,4 +96,7 @@ static inline void syscall_set_arguments(struct task_struct *task,
 		microblaze_set_syscall_arg(regs, i++, *args++);
 }
 
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
+
 #endif /* __ASM_MICROBLAZE_SYSCALL_H */
diff --git a/arch/microblaze/include/asm/syscalls.h b/arch/microblaze/include/asm/syscalls.h
index 720761c..27f2f4c 100644
--- a/arch/microblaze/include/asm/syscalls.h
+++ b/arch/microblaze/include/asm/syscalls.h
@@ -1,5 +1,13 @@
 #ifndef __ASM_MICROBLAZE_SYSCALLS_H
 
+asmlinkage long microblaze_vfork(struct pt_regs *regs);
+asmlinkage long microblaze_clone(int flags, unsigned long stack,
+							struct pt_regs *regs);
+asmlinkage long microblaze_execve(const char __user *filenamei,
+				  const char __user *const __user *argv,
+				  const char __user *const __user *envp,
+				  struct pt_regs *regs);
+
 asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
 #define sys_clone sys_clone
 
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h
index d840f4a..5bb95a1 100644
--- a/arch/microblaze/include/asm/uaccess.h
+++ b/arch/microblaze/include/asm/uaccess.h
@@ -120,16 +120,16 @@ static inline unsigned long __must_check __clear_user(void __user *to,
 {
 	/* normal memset with two words to __ex_table */
 	__asm__ __volatile__ (				\
-			"1:	sb	r0, %2, r0;"	\
+			"1:	sb	r0, %1, r0;"	\
 			"	addik	%0, %0, -1;"	\
 			"	bneid	%0, 1b;"	\
-			"	addik	%2, %2, 1;"	\
+			"	addik	%1, %1, 1;"	\
 			"2:			"	\
 			__EX_TABLE_SECTION		\
 			".word	1b,2b;"			\
 			".previous;"			\
-		: "=r"(n)				\
-		: "0"(n), "r"(to)
+		: "=r"(n), "=r"(to)			\
+		: "0"(n), "1"(to)
 	);
 	return n;
 }
diff --git a/arch/microblaze/include/asm/unaligned.h b/arch/microblaze/include/asm/unaligned.h
index 2b97cbe..b162ed8 100644
--- a/arch/microblaze/include/asm/unaligned.h
+++ b/arch/microblaze/include/asm/unaligned.h
@@ -12,18 +12,19 @@
 
 # ifdef __KERNEL__
 
-# include <linux/unaligned/be_byteshift.h>
-# include <linux/unaligned/le_byteshift.h>
-# include <linux/unaligned/generic.h>
-
-
 #  ifdef __MICROBLAZEEL__
+#   include <linux/unaligned/le_struct.h>
+#   include <linux/unaligned/be_byteshift.h>
 #   define get_unaligned	__get_unaligned_le
 #   define put_unaligned	__put_unaligned_le
 #  else
+#   include <linux/unaligned/be_struct.h>
+#   include <linux/unaligned/le_byteshift.h>
 #   define get_unaligned	__get_unaligned_be
 #   define put_unaligned	__put_unaligned_be
 #  endif
 
+# include <linux/unaligned/generic.h>
+
 # endif	/* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNALIGNED_H */
diff --git a/arch/microblaze/kernel/cpu/Makefile b/arch/microblaze/kernel/cpu/Makefile
index 59cc7bc..fceed4e 100644
--- a/arch/microblaze/kernel/cpu/Makefile
+++ b/arch/microblaze/kernel/cpu/Makefile
@@ -6,7 +6,7 @@ ifdef CONFIG_FUNCTION_TRACER
 CFLAGS_REMOVE_cache.o = -pg
 endif
 
-EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
+ccflags-y := -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
 		-DCPU_REV=$(CPU_REV)
 
 obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o
diff --git a/arch/microblaze/kernel/cpu/cache.c b/arch/microblaze/kernel/cpu/cache.c
index 109876e..cf0afd9 100644
--- a/arch/microblaze/kernel/cpu/cache.c
+++ b/arch/microblaze/kernel/cpu/cache.c
@@ -519,7 +519,7 @@ static void __flush_dcache_range_wb(unsigned long start, unsigned long end)
 struct scache *mbc;
 
 /* new wb cache model */
-const struct scache wb_msr = {
+static const struct scache wb_msr = {
 	.ie = __enable_icache_msr,
 	.id = __disable_icache_msr,
 	.ifl = __flush_icache_all_noirq,
@@ -535,7 +535,7 @@ const struct scache wb_msr = {
 };
 
 /* There is only difference in ie, id, de, dd functions */
-const struct scache wb_nomsr = {
+static const struct scache wb_nomsr = {
 	.ie = __enable_icache_nomsr,
 	.id = __disable_icache_nomsr,
 	.ifl = __flush_icache_all_noirq,
@@ -551,7 +551,7 @@ const struct scache wb_nomsr = {
 };
 
 /* Old wt cache model with disabling irq and turn off cache */
-const struct scache wt_msr = {
+static const struct scache wt_msr = {
 	.ie = __enable_icache_msr,
 	.id = __disable_icache_msr,
 	.ifl = __flush_icache_all_msr_irq,
@@ -566,7 +566,7 @@ const struct scache wt_msr = {
 	.dinr = __invalidate_dcache_range_msr_irq_wt,
 };
 
-const struct scache wt_nomsr = {
+static const struct scache wt_nomsr = {
 	.ie = __enable_icache_nomsr,
 	.id = __disable_icache_nomsr,
 	.ifl = __flush_icache_all_nomsr_irq,
@@ -582,7 +582,7 @@ const struct scache wt_nomsr = {
 };
 
 /* New wt cache model for newer Microblaze versions */
-const struct scache wt_msr_noirq = {
+static const struct scache wt_msr_noirq = {
 	.ie = __enable_icache_msr,
 	.id = __disable_icache_msr,
 	.ifl = __flush_icache_all_noirq,
@@ -597,7 +597,7 @@ const struct scache wt_msr_noirq = {
 	.dinr = __invalidate_dcache_range_nomsr_wt,
 };
 
-const struct scache wt_nomsr_noirq = {
+static const struct scache wt_nomsr_noirq = {
 	.ie = __enable_icache_nomsr,
 	.id = __disable_icache_nomsr,
 	.ifl = __flush_icache_all_noirq,
@@ -624,7 +624,7 @@ void microblaze_cache_init(void)
 		if (cpuinfo.dcache_wb) {
 			INFO("wb_msr");
 			mbc = (struct scache *)&wb_msr;
-			if (cpuinfo.ver_code < CPUVER_7_20_D) {
+			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
 				/* MS: problem with signal handling - hw bug */
 				INFO("WB won't work properly");
 			}
@@ -641,7 +641,7 @@ void microblaze_cache_init(void)
 		if (cpuinfo.dcache_wb) {
 			INFO("wb_nomsr");
 			mbc = (struct scache *)&wb_nomsr;
-			if (cpuinfo.ver_code < CPUVER_7_20_D) {
+			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
 				/* MS: problem with signal handling - hw bug */
 				INFO("WB won't work properly");
 			}
diff --git a/arch/microblaze/kernel/cpu/cpuinfo.c b/arch/microblaze/kernel/cpu/cpuinfo.c
index 2c309fc..c1640c5 100644
--- a/arch/microblaze/kernel/cpu/cpuinfo.c
+++ b/arch/microblaze/kernel/cpu/cpuinfo.c
@@ -33,6 +33,7 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
 	{"7.30.b", 0x11},
 	{"8.00.a", 0x12},
 	{"8.00.b", 0x13},
+	{"8.10.a", 0x14},
 	{NULL, 0},
 };
 
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index 79c7465..393e6b2 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -26,6 +26,7 @@ static inline void __dma_sync_page(unsigned long paddr, unsigned long offset,
 {
 	switch (direction) {
 	case DMA_TO_DEVICE:
+	case DMA_BIDIRECTIONAL:
 		flush_dcache_range(paddr + offset, paddr + offset + size);
 		break;
 	case DMA_FROM_DEVICE:
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S
index ca84368..34b526f 100644
--- a/arch/microblaze/kernel/entry-nommu.S
+++ b/arch/microblaze/kernel/entry-nommu.S
@@ -115,7 +115,7 @@ ENTRY(_interrupt)
 	/* restore r31 */
 	lwi	r31, r0, PER_CPU(CURRENT_SAVE)
 	/* prepare the link register, the argument and jump */
-	la	r15, r0, ret_from_intr - 8
+	addik	r15, r0, ret_from_intr - 8
 	addk	r6, r0, r15
 	braid	do_IRQ
 	add	r5, r0, r1
@@ -283,7 +283,7 @@ ENTRY(_user_exception)
 	add	r12, r12, r12			/* convert num -> ptr */
 	add	r12, r12, r12
 	lwi	r12, r12, sys_call_table	/* Get function pointer */
-	la	r15, r0, ret_to_user-8		/* set return address */
+	addik	r15, r0, ret_to_user-8		/* set return address */
 	bra	r12				/* Make the system call. */
 	bri	0				/* won't reach here */
 1:
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S
index 41c30cd..ca15bc5 100644
--- a/arch/microblaze/kernel/entry.S
+++ b/arch/microblaze/kernel/entry.S
@@ -33,11 +33,14 @@
 
 #undef DEBUG
 
-/* The size of a state save frame. */
-#define STATE_SAVE_SIZE		(PT_SIZE + STATE_SAVE_ARG_SPACE)
-
-/* The offset of the struct pt_regs in a `state save frame' on the stack. */
-#define PTO	STATE_SAVE_ARG_SPACE /* 24 the space for args */
+#ifdef DEBUG
+/* Create space for syscalls counting. */
+.section .data
+.global syscall_debug_table
+.align 4
+syscall_debug_table:
+	.space	(__NR_syscalls * 4)
+#endif /* DEBUG */
 
 #define C_ENTRY(name)	.globl name; .align 4; name
 
@@ -172,72 +175,72 @@
 1:
 
 #define SAVE_REGS \
-	swi	r2, r1, PTO+PT_R2;	/* Save SDA */			\
-	swi	r3, r1, PTO+PT_R3;					\
-	swi	r4, r1, PTO+PT_R4;					\
-	swi	r5, r1, PTO+PT_R5;					\
-	swi	r6, r1, PTO+PT_R6;					\
-	swi	r7, r1, PTO+PT_R7;					\
-	swi	r8, r1, PTO+PT_R8;					\
-	swi	r9, r1, PTO+PT_R9;					\
-	swi	r10, r1, PTO+PT_R10;					\
-	swi	r11, r1, PTO+PT_R11;	/* save clobbered regs after rval */\
-	swi	r12, r1, PTO+PT_R12;					\
-	swi	r13, r1, PTO+PT_R13;	/* Save SDA2 */			\
-	swi	r14, r1, PTO+PT_PC;	/* PC, before IRQ/trap */	\
-	swi	r15, r1, PTO+PT_R15;	/* Save LP */			\
-	swi	r16, r1, PTO+PT_R16;					\
-	swi	r17, r1, PTO+PT_R17;					\
-	swi	r18, r1, PTO+PT_R18;	/* Save asm scratch reg */	\
-	swi	r19, r1, PTO+PT_R19;					\
-	swi	r20, r1, PTO+PT_R20;					\
-	swi	r21, r1, PTO+PT_R21;					\
-	swi	r22, r1, PTO+PT_R22;					\
-	swi	r23, r1, PTO+PT_R23;					\
-	swi	r24, r1, PTO+PT_R24;					\
-	swi	r25, r1, PTO+PT_R25;					\
-	swi	r26, r1, PTO+PT_R26;					\
-	swi	r27, r1, PTO+PT_R27;					\
-	swi	r28, r1, PTO+PT_R28;					\
-	swi	r29, r1, PTO+PT_R29;					\
-	swi	r30, r1, PTO+PT_R30;					\
-	swi	r31, r1, PTO+PT_R31;	/* Save current task reg */	\
+	swi	r2, r1, PT_R2;	/* Save SDA */			\
+	swi	r3, r1, PT_R3;					\
+	swi	r4, r1, PT_R4;					\
+	swi	r5, r1, PT_R5;					\
+	swi	r6, r1, PT_R6;					\
+	swi	r7, r1, PT_R7;					\
+	swi	r8, r1, PT_R8;					\
+	swi	r9, r1, PT_R9;					\
+	swi	r10, r1, PT_R10;					\
+	swi	r11, r1, PT_R11;	/* save clobbered regs after rval */\
+	swi	r12, r1, PT_R12;					\
+	swi	r13, r1, PT_R13;	/* Save SDA2 */			\
+	swi	r14, r1, PT_PC;	/* PC, before IRQ/trap */	\
+	swi	r15, r1, PT_R15;	/* Save LP */			\
+	swi	r16, r1, PT_R16;					\
+	swi	r17, r1, PT_R17;					\
+	swi	r18, r1, PT_R18;	/* Save asm scratch reg */	\
+	swi	r19, r1, PT_R19;					\
+	swi	r20, r1, PT_R20;					\
+	swi	r21, r1, PT_R21;					\
+	swi	r22, r1, PT_R22;					\
+	swi	r23, r1, PT_R23;					\
+	swi	r24, r1, PT_R24;					\
+	swi	r25, r1, PT_R25;					\
+	swi	r26, r1, PT_R26;					\
+	swi	r27, r1, PT_R27;					\
+	swi	r28, r1, PT_R28;					\
+	swi	r29, r1, PT_R29;					\
+	swi	r30, r1, PT_R30;					\
+	swi	r31, r1, PT_R31;	/* Save current task reg */	\
 	mfs	r11, rmsr;		/* save MSR */			\
-	swi	r11, r1, PTO+PT_MSR;
+	swi	r11, r1, PT_MSR;
 
 #define RESTORE_REGS \
-	lwi	r11, r1, PTO+PT_MSR;					\
+	lwi	r11, r1, PT_MSR;					\
 	mts	rmsr , r11;						\
-	lwi	r2, r1, PTO+PT_R2;	/* restore SDA */		\
-	lwi	r3, r1, PTO+PT_R3;					\
-	lwi	r4, r1, PTO+PT_R4;					\
-	lwi	r5, r1, PTO+PT_R5;					\
-	lwi	r6, r1, PTO+PT_R6;					\
-	lwi	r7, r1, PTO+PT_R7;					\
-	lwi	r8, r1, PTO+PT_R8;					\
-	lwi	r9, r1, PTO+PT_R9;					\
-	lwi	r10, r1, PTO+PT_R10;					\
-	lwi	r11, r1, PTO+PT_R11;	/* restore clobbered regs after rval */\
-	lwi	r12, r1, PTO+PT_R12;					\
-	lwi	r13, r1, PTO+PT_R13;	/* restore SDA2 */		\
-	lwi	r14, r1, PTO+PT_PC;	/* RESTORE_LINK PC, before IRQ/trap */\
-	lwi	r15, r1, PTO+PT_R15;	/* restore LP */		\
-	lwi	r16, r1, PTO+PT_R16;					\
-	lwi	r17, r1, PTO+PT_R17;					\
-	lwi	r18, r1, PTO+PT_R18;	/* restore asm scratch reg */	\
-	lwi	r19, r1, PTO+PT_R19;					\
-	lwi	r20, r1, PTO+PT_R20;					\
-	lwi	r21, r1, PTO+PT_R21;					\
-	lwi	r22, r1, PTO+PT_R22;					\
-	lwi	r23, r1, PTO+PT_R23;					\
-	lwi	r24, r1, PTO+PT_R24;					\
-	lwi	r25, r1, PTO+PT_R25;					\
-	lwi	r26, r1, PTO+PT_R26;					\
-	lwi	r27, r1, PTO+PT_R27;					\
-	lwi	r28, r1, PTO+PT_R28;					\
-	lwi	r29, r1, PTO+PT_R29;					\
-	lwi	r30, r1, PTO+PT_R30;					\
-	lwi	r31, r1, PTO+PT_R31;	/* Restore cur task reg */
+	lwi	r2, r1, PT_R2;	/* restore SDA */		\
+	lwi	r3, r1, PT_R3;					\
+	lwi	r4, r1, PT_R4;					\
+	lwi	r5, r1, PT_R5;					\
+	lwi	r6, r1, PT_R6;					\
+	lwi	r7, r1, PT_R7;					\
+	lwi	r8, r1, PT_R8;					\
+	lwi	r9, r1, PT_R9;					\
+	lwi	r10, r1, PT_R10;					\
+	lwi	r11, r1, PT_R11;	/* restore clobbered regs after rval */\
+	lwi	r12, r1, PT_R12;					\
+	lwi	r13, r1, PT_R13;	/* restore SDA2 */		\
+	lwi	r14, r1, PT_PC;	/* RESTORE_LINK PC, before IRQ/trap */\
+	lwi	r15, r1, PT_R15;	/* restore LP */		\
+	lwi	r16, r1, PT_R16;					\
+	lwi	r17, r1, PT_R17;					\
+	lwi	r18, r1, PT_R18;	/* restore asm scratch reg */	\
+	lwi	r19, r1, PT_R19;					\
+	lwi	r20, r1, PT_R20;					\
+	lwi	r21, r1, PT_R21;					\
+	lwi	r22, r1, PT_R22;					\
+	lwi	r23, r1, PT_R23;					\
+	lwi	r24, r1, PT_R24;					\
+	lwi	r25, r1, PT_R25;					\
+	lwi	r26, r1, PT_R26;					\
+	lwi	r27, r1, PT_R27;					\
+	lwi	r28, r1, PT_R28;					\
+	lwi	r29, r1, PT_R29;					\
+	lwi	r30, r1, PT_R30;					\
+	lwi	r31, r1, PT_R31;	/* Restore cur task reg */
 
 #define SAVE_STATE	\
 	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */	\
@@ -250,11 +253,11 @@
 	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
 	/* FIXME: I can add these two lines to one */			\
 	/* tophys(r1,r1); */						\
-	/* addik	r1, r1, -STATE_SAVE_SIZE; */			\
-	addik	r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
+	/* addik	r1, r1, -PT_SIZE; */				\
+	addik	r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
 	SAVE_REGS							\
 	brid	2f;							\
-	swi	r1, r1, PTO+PT_MODE; 	 				\
+	swi	r1, r1, PT_MODE; 	 				\
 1:	/* User-mode state save.  */					\
 	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
 	tophys(r1,r1);							\
@@ -262,12 +265,12 @@
 	/* MS these three instructions can be added to one */		\
 	/* addik	r1, r1, THREAD_SIZE; */				\
 	/* tophys(r1,r1); */						\
-	/* addik	r1, r1, -STATE_SAVE_SIZE; */			\
-	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
+	/* addik	r1, r1, -PT_SIZE; */			\
+	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
 	SAVE_REGS							\
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
-	swi	r11, r1, PTO+PT_R1; /* Store user SP.  */		\
-	swi	r0, r1, PTO + PT_MODE; /* Was in user-mode.  */		\
+	swi	r11, r1, PT_R1; /* Store user SP.  */		\
+	swi	r0, r1, PT_MODE; /* Was in user-mode.  */		\
 	/* MS: I am clearing UMS even in case when I come from kernel space */ \
 	clear_ums; 							\
 2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
@@ -299,10 +302,10 @@ C_ENTRY(_user_exception):
 	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
 	tophys(r1,r1);
 
-	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
+	addik	r1, r1, -PT_SIZE; /* Make room on the stack. */
 	SAVE_REGS
 
-	swi	r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */
+	swi	r1, r1, PT_MODE; /* pt_regs -> kernel mode */
 	brid	2f;
 	nop;				/* Fill delay slot */
 
@@ -315,18 +318,18 @@ C_ENTRY(_user_exception):
 	addik	r1, r1, THREAD_SIZE;
 	tophys(r1,r1);
 
-	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	addik	r1, r1, -PT_SIZE; /* Make room on the stack.  */
 	SAVE_REGS
-	swi	r0, r1, PTO + PT_R3
-	swi	r0, r1, PTO + PT_R4
+	swi	r0, r1, PT_R3
+	swi	r0, r1, PT_R4
 
-	swi	r0, r1, PTO + PT_MODE;			/* Was in user-mode. */
+	swi	r0, r1, PT_MODE;			/* Was in user-mode. */
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
-	swi	r11, r1, PTO+PT_R1;		/* Store user SP.  */
+	swi	r11, r1, PT_R1;		/* Store user SP.  */
 	clear_ums;
 2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	/* Save away the syscall number.  */
-	swi	r12, r1, PTO+PT_R0;
+	swi	r12, r1, PT_R0;
 	tovirt(r1,r1)
 
 /* where the trap should return need -8 to adjust for rtsd r15, 8*/
@@ -345,18 +348,18 @@ C_ENTRY(_user_exception):
 	beqi	r11, 4f
 
 	addik	r3, r0, -ENOSYS
-	swi	r3, r1, PTO + PT_R3
+	swi	r3, r1, PT_R3
 	brlid	r15, do_syscall_trace_enter
-	addik	r5, r1, PTO + PT_R0
+	addik	r5, r1, PT_R0
 
 	# do_syscall_trace_enter returns the new syscall nr.
 	addk	r12, r0, r3
-	lwi	r5, r1, PTO+PT_R5;
-	lwi	r6, r1, PTO+PT_R6;
-	lwi	r7, r1, PTO+PT_R7;
-	lwi	r8, r1, PTO+PT_R8;
-	lwi	r9, r1, PTO+PT_R9;
-	lwi	r10, r1, PTO+PT_R10;
+	lwi	r5, r1, PT_R5;
+	lwi	r6, r1, PT_R6;
+	lwi	r7, r1, PT_R7;
+	lwi	r8, r1, PT_R8;
+	lwi	r9, r1, PT_R9;
+	lwi	r10, r1, PT_R10;
 4:
 /* Jump to the appropriate function for the system call number in r12
  * (r12 is not preserved), or return an error if r12 is not valid.
@@ -371,10 +374,14 @@ C_ENTRY(_user_exception):
 	add	r12, r12, r12;
 
 #ifdef DEBUG
-	/* Trac syscalls and stored them to r0_ram */
-	lwi	r3, r12, 0x400 + r0_ram
+	/* Trac syscalls and stored them to syscall_debug_table */
+	/* The first syscall location stores total syscall number */
+	lwi	r3, r0, syscall_debug_table
+	addi	r3, r3, 1
+	swi	r3, r0, syscall_debug_table
+	lwi	r3, r12, syscall_debug_table
 	addi	r3, r3, 1
-	swi	r3, r12, 0x400 + r0_ram
+	swi	r3, r12, syscall_debug_table
 #endif
 
 	# Find and jump into the syscall handler.
@@ -391,10 +398,10 @@ C_ENTRY(_user_exception):
 /* Entry point used to return from a syscall/trap */
 /* We re-enable BIP bit before state restore */
 C_ENTRY(ret_from_trap):
-	swi	r3, r1, PTO + PT_R3
-	swi	r4, r1, PTO + PT_R4
+	swi	r3, r1, PT_R3
+	swi	r4, r1, PT_R4
 
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 /* See if returning to kernel mode, if so, skip resched &c.  */
 	bnei	r11, 2f;
 	/* We're returning to user mode, so check for various conditions that
@@ -406,7 +413,7 @@ C_ENTRY(ret_from_trap):
 	beqi	r11, 1f
 
 	brlid	r15, do_syscall_trace_leave
-	addik	r5, r1, PTO + PT_R0
+	addik	r5, r1, PT_R0
 1:
 	/* We're returning to user mode, so check for various conditions that
 	 * trigger rescheduling. */
@@ -426,7 +433,7 @@ C_ENTRY(ret_from_trap):
 	andi	r11, r11, _TIF_SIGPENDING;
 	beqi	r11, 1f;		/* Signals to handle, handle them */
 
-	addik	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	addi	r7, r0, 1;		/* Arg 3: int in_syscall */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
@@ -437,7 +444,7 @@ C_ENTRY(ret_from_trap):
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 	lwi	r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
 	bri	6f;
 
@@ -446,7 +453,7 @@ C_ENTRY(ret_from_trap):
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 	tovirt(r1,r1);
 6:
 TRAP_return:		/* Make global symbol for debugging */
@@ -459,8 +466,8 @@ TRAP_return:		/* Make global symbol for debugging */
 
 C_ENTRY(sys_fork_wrapper):
 	addi	r5, r0, SIGCHLD			/* Arg 0: flags */
-	lwi	r6, r1, PTO+PT_R1	/* Arg 1: child SP (use parent's) */
-	addik	r7, r1, PTO			/* Arg 2: parent context */
+	lwi	r6, r1, PT_R1	/* Arg 1: child SP (use parent's) */
+	addik	r7, r1, 0			/* Arg 2: parent context */
 	add	r8. r0, r0			/* Arg 3: (unused) */
 	add	r9, r0, r0;			/* Arg 4: (unused) */
 	brid	do_fork		/* Do real work (tail-call) */
@@ -480,12 +487,12 @@ C_ENTRY(ret_from_fork):
 
 C_ENTRY(sys_vfork):
 	brid	microblaze_vfork	/* Do real work (tail-call) */
-	addik	r5, r1, PTO
+	addik	r5, r1, 0
 
 C_ENTRY(sys_clone):
 	bnei	r6, 1f;			/* See if child SP arg (arg 1) is 0. */
-	lwi	r6, r1, PTO + PT_R1;	/* If so, use paret's stack ptr */
-1:	addik	r7, r1, PTO;			/* Arg 2: parent context */
+	lwi	r6, r1, PT_R1;	/* If so, use paret's stack ptr */
+1:	addik	r7, r1, 0;			/* Arg 2: parent context */
 	add	r8, r0, r0;			/* Arg 3: (unused) */
 	add	r9, r0, r0;			/* Arg 4: (unused) */
 	brid	do_fork		/* Do real work (tail-call) */
@@ -493,11 +500,11 @@ C_ENTRY(sys_clone):
 
 C_ENTRY(sys_execve):
 	brid	microblaze_execve;	/* Do real work (tail-call).*/
-	addik	r8, r1, PTO;		/* add user context as 4th arg */
+	addik	r8, r1, 0;		/* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
 	brid	sys_rt_sigreturn	/* Do real work */
-	addik	r5, r1, PTO;		/* add user context as 1st arg */
+	addik	r5, r1, 0;		/* add user context as 1st arg */
 
 /*
  * HW EXCEPTION rutine start
@@ -508,7 +515,7 @@ C_ENTRY(full_exception_trap):
 	addik	r17, r17, -4
 	SAVE_STATE /* Save registers */
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* FIXME this can be store directly in PT_ESR reg.
 	 * I tested it but there is a fault */
@@ -518,7 +525,7 @@ C_ENTRY(full_exception_trap):
 	mfs	r7, rfsr;		/* save FSR */
 	mts	rfsr, r0;	/* Clear sticky fsr */
 	rted	r0, full_exception
-	addik	r5, r1, PTO		 /* parameter struct pt_regs * regs */
+	addik	r5, r1, 0		 /* parameter struct pt_regs * regs */
 
 /*
  * Unaligned data trap.
@@ -544,14 +551,14 @@ C_ENTRY(unaligned_data_trap):
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
 	addik	r15, r0, ret_from_exc-8
 	mfs	r3, resr		/* ESR */
 	mfs	r4, rear		/* EAR */
 	rtbd	r0, _unaligned_data_exception
-	addik	r7, r1, PTO		/* parameter struct pt_regs * regs */
+	addik	r7, r1, 0		/* parameter struct pt_regs * regs */
 
 /*
  * Page fault traps.
@@ -574,30 +581,30 @@ C_ENTRY(unaligned_data_trap):
 C_ENTRY(page_fault_data_trap):
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
 	addik	r15, r0, ret_from_exc-8
 	mfs	r6, rear		/* parameter unsigned long address */
 	mfs	r7, resr		/* parameter unsigned long error_code */
 	rted	r0, do_page_fault
-	addik	r5, r1, PTO		/* parameter struct pt_regs * regs */
+	addik	r5, r1, 0		/* parameter struct pt_regs * regs */
 
 C_ENTRY(page_fault_instr_trap):
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
 	addik	r15, r0, ret_from_exc-8
 	mfs	r6, rear		/* parameter unsigned long address */
 	ori	r7, r0, 0		/* parameter unsigned long error_code */
 	rted	r0, do_page_fault
-	addik	r5, r1, PTO		/* parameter struct pt_regs * regs */
+	addik	r5, r1, 0		/* parameter struct pt_regs * regs */
 
 /* Entry point used to return from an exception.  */
 C_ENTRY(ret_from_exc):
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 	bnei	r11, 2f;		/* See if returning to kernel mode, */
 					/* ... if so, skip resched &c.  */
 
@@ -629,7 +636,7 @@ C_ENTRY(ret_from_exc):
 	 * complete register state.  Here we save anything not saved by
 	 * the normal entry sequence, so that it may be safely restored
 	 * (in a possibly modified form) after do_signal returns. */
-	addik	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	addi	r7, r0, 0;		/* Arg 3: int in_syscall */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
@@ -641,7 +648,7 @@ C_ENTRY(ret_from_exc):
 	tophys(r1,r1);
 
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 
 	lwi	r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
 	bri	6f;
@@ -650,7 +657,7 @@ C_ENTRY(ret_from_exc):
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 
 	tovirt(r1,r1);
 6:
@@ -683,10 +690,10 @@ C_ENTRY(_interrupt):
 	tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
 	/* save registers */
 /* MS: Make room on the stack -> activation record */
-	addik	r1, r1, -STATE_SAVE_SIZE;
+	addik	r1, r1, -PT_SIZE;
 	SAVE_REGS
 	brid	2f;
-	swi	r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
+	swi	r1, r1, PT_MODE; /* 0 - user mode, 1 - kernel mode */
 1:
 /* User-mode state save. */
  /* MS: get the saved current */
@@ -696,23 +703,23 @@ C_ENTRY(_interrupt):
 	addik	r1, r1, THREAD_SIZE;
 	tophys(r1,r1);
 	/* save registers */
-	addik	r1, r1, -STATE_SAVE_SIZE;
+	addik	r1, r1, -PT_SIZE;
 	SAVE_REGS
 	/* calculate mode */
-	swi	r0, r1, PTO + PT_MODE;
+	swi	r0, r1, PT_MODE;
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
-	swi	r11, r1, PTO+PT_R1;
+	swi	r11, r1, PT_R1;
 	clear_ums;
 2:
 	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	tovirt(r1,r1)
 	addik	r15, r0, irq_call;
 irq_call:rtbd	r0, do_IRQ;
-	addik	r5, r1, PTO;
+	addik	r5, r1, 0;
 
 /* MS: we are in virtual mode */
 ret_from_irq:
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 	bnei	r11, 2f;
 
 	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;
@@ -729,7 +736,7 @@ ret_from_irq:
 	beqid	r11, no_intr_resched
 /* Handle a signal return; Pending signals should be in r18. */
 	addi	r7, r0, 0; /* Arg 3: int in_syscall */
-	addik	r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0; /* Arg 1: struct pt_regs *regs */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0; /* Arg 2: sigset_t *oldset */
 
@@ -741,7 +748,7 @@ no_intr_resched:
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS
-	addik	r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
+	addik	r1, r1, PT_SIZE /* MS: Clean up stack space. */
 	lwi	r1, r1, PT_R1 - PT_SIZE;
 	bri	6f;
 /* MS: Return to kernel state. */
@@ -769,7 +776,7 @@ restore:
 	VM_OFF /* MS: turn off MMU */
 	tophys(r1,r1)
 	RESTORE_REGS
-	addik	r1, r1, STATE_SAVE_SIZE	/* MS: Clean up stack space. */
+	addik	r1, r1, PT_SIZE	/* MS: Clean up stack space. */
 	tovirt(r1,r1);
 6:
 IRQ_return: /* MS: Make global symbol for debugging */
@@ -792,29 +799,29 @@ C_ENTRY(_debug_exception):
 	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
 
 	/* BIP bit is set on entry, no interrupts can occur */
-	addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
+	addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE;
 	SAVE_REGS;
 	/* save all regs to pt_reg structure */
-	swi	r0, r1, PTO+PT_R0;	/* R0 must be saved too */
-	swi	r14, r1, PTO+PT_R14	/* rewrite saved R14 value */
-	swi	r16, r1, PTO+PT_PC; /* PC and r16 are the same */
+	swi	r0, r1, PT_R0;	/* R0 must be saved too */
+	swi	r14, r1, PT_R14	/* rewrite saved R14 value */
+	swi	r16, r1, PT_PC; /* PC and r16 are the same */
 	/* save special purpose registers to pt_regs */
 	mfs	r11, rear;
-	swi	r11, r1, PTO+PT_EAR;
+	swi	r11, r1, PT_EAR;
 	mfs	r11, resr;
-	swi	r11, r1, PTO+PT_ESR;
+	swi	r11, r1, PT_ESR;
 	mfs	r11, rfsr;
-	swi	r11, r1, PTO+PT_FSR;
+	swi	r11, r1, PT_FSR;
 
 	/* stack pointer is in physical address at it is decrease
-	 * by STATE_SAVE_SIZE but we need to get correct R1 value */
-	addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
-	swi	r11, r1, PTO+PT_R1
+	 * by PT_SIZE but we need to get correct R1 value */
+	addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + PT_SIZE;
+	swi	r11, r1, PT_R1
 	/* MS: r31 - current pointer isn't changed */
 	tovirt(r1,r1)
 #ifdef CONFIG_KGDB
-	addi	r5, r1, PTO /* pass pt_reg address as the first arg */
-	la	r15, r0, dbtrap_call; /* return address */
+	addi	r5, r1, 0 /* pass pt_reg address as the first arg */
+	addik	r15, r0, dbtrap_call; /* return address */
 	rtbd	r0, microblaze_kgdb_break
 	nop;
 #endif
@@ -829,16 +836,16 @@ C_ENTRY(_debug_exception):
 	addik	r1, r1, THREAD_SIZE;	/* calculate kernel stack pointer */
 	tophys(r1,r1);
 
-	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	addik	r1, r1, -PT_SIZE; /* Make room on the stack.  */
 	SAVE_REGS;
-	swi	r16, r1, PTO+PT_PC;	/* Save LP */
-	swi	r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
+	swi	r16, r1, PT_PC;	/* Save LP */
+	swi	r0, r1, PT_MODE; /* Was in user-mode.  */
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
-	swi	r11, r1, PTO+PT_R1; /* Store user SP.  */
+	swi	r11, r1, PT_R1; /* Store user SP.  */
 	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	tovirt(r1,r1)
 	set_vms;
-	addik	r5, r1, PTO;
+	addik	r5, r1, 0;
 	addik	r15, r0, dbtrap_call;
 dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
 	rtbd	r0, sw_exception
@@ -846,7 +853,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
 
 	/* MS: The first instruction for the second part of the gdb/kgdb */
 	set_bip; /* Ints masked for state restore */
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 	bnei	r11, 2f;
 /* MS: Return to user space - gdb */
 	/* Get current task ptr into r11 */
@@ -865,7 +872,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
 	andi	r11, r11, _TIF_SIGPENDING;
 	beqi	r11, 1f;		/* Signals to handle, handle them */
 
-	addik	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	addi  r7, r0, 0;	/* Arg 3: int in_syscall */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
@@ -876,7 +883,7 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
 	tophys(r1,r1);
 	/* MS: Restore all regs */
 	RESTORE_REGS
-	addik	r1, r1, STATE_SAVE_SIZE	 /* Clean up stack space */
+	addik	r1, r1, PT_SIZE	 /* Clean up stack space */
 	lwi	r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 DBTRAP_return_user: /* MS: Make global symbol for debugging */
 	rtbd	r16, 0; /* MS: Instructions to return from a debug trap */
@@ -887,9 +894,9 @@ DBTRAP_return_user: /* MS: Make global symbol for debugging */
 	tophys(r1,r1);
 	/* MS: Restore all regs */
 	RESTORE_REGS
-	lwi	r14, r1, PTO+PT_R14;
-	lwi	r16, r1, PTO+PT_PC;
-	addik	r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
+	lwi	r14, r1, PT_R14;
+	lwi	r16, r1, PT_PC;
+	addik	r1, r1, PT_SIZE; /* MS: Clean up stack space */
 	tovirt(r1,r1);
 DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
 	rtbd	r16, 0; /* MS: Instructions to return from a debug trap */
@@ -981,20 +988,22 @@ ENTRY(_switch_to)
 	nop
 
 ENTRY(_reset)
-	brai	0x70; /* Jump back to FS-boot */
+	brai	0; /* Jump to reset vector */
 
 	/* These are compiled and loaded into high memory, then
 	 * copied into place in mach_early_setup */
 	.section	.init.ivt, "ax"
+#if CONFIG_MANUAL_RESET_VECTOR
 	.org	0x0
-	/* this is very important - here is the reset vector */
-	/* in current MMU branch you don't care what is here - it is
-	 * used from bootloader site - but this is correct for FS-BOOT */
-	brai	0x70
-	nop
+	brai	CONFIG_MANUAL_RESET_VECTOR
+#endif
+	.org	0x8
 	brai	TOPHYS(_user_exception); /* syscall handler */
+	.org	0x10
 	brai	TOPHYS(_interrupt);	/* Interrupt handler */
+	.org	0x18
 	brai	TOPHYS(_debug_exception);	/* debug trap handler */
+	.org	0x20
 	brai	TOPHYS(_hw_exception_handler);	/* HW exception handler */
 
 .section .rodata,"a"
diff --git a/arch/microblaze/kernel/exceptions.c b/arch/microblaze/kernel/exceptions.c
index a7fa6ae..66fad23 100644
--- a/arch/microblaze/kernel/exceptions.c
+++ b/arch/microblaze/kernel/exceptions.c
@@ -50,7 +50,7 @@ void die(const char *str, struct pt_regs *fp, long err)
 }
 
 /* for user application debugging */
-void sw_exception(struct pt_regs *regs)
+asmlinkage void sw_exception(struct pt_regs *regs)
 {
 	_exception(SIGTRAP, regs, TRAP_BRKPT, regs->r16);
 	flush_dcache_range(regs->r16, regs->r16 + 0x4);
diff --git a/arch/microblaze/kernel/head.S b/arch/microblaze/kernel/head.S
index 778a5ce..77320b8 100644
--- a/arch/microblaze/kernel/head.S
+++ b/arch/microblaze/kernel/head.S
@@ -39,7 +39,7 @@
 #include <asm/mmu.h>
 #include <asm/processor.h>
 
-.data
+.section .data
 .global empty_zero_page
 .align 12
 empty_zero_page:
@@ -50,6 +50,11 @@ swapper_pg_dir:
 
 #endif /* CONFIG_MMU */
 
+.section .rodata
+.align 4
+endian_check:
+	.word	1
+
 	__HEAD
 ENTRY(_start)
 #if CONFIG_KERNEL_BASE_ADDR == 0
@@ -79,10 +84,7 @@ real_start:
 /* Does r7 point to a valid FDT? Load HEADER magic number */
 	/* Run time Big/Little endian platform */
 	/* Save 1 as word and load byte - 0 - BIG, 1 - LITTLE */
-	addik	r11, r0, 0x1 /* BIG/LITTLE checking value */
-	/* __bss_start will be zeroed later - it is just temp location */
-	swi	r11, r0, TOPHYS(__bss_start)
-	lbui	r11, r0, TOPHYS(__bss_start)
+	lbui	r11, r0, TOPHYS(endian_check)
 	beqid	r11, big_endian /* DO NOT break delay stop dependency */
 	lw	r11, r0, r7 /* Big endian load in delay slot */
 	lwr	r11, r0, r7 /* Little endian load */
@@ -222,26 +224,26 @@ start_here:
 #endif /* CONFIG_MMU */
 
 	/* Initialize small data anchors */
-	la	r13, r0, _KERNEL_SDA_BASE_
-	la	r2, r0, _KERNEL_SDA2_BASE_
+	addik	r13, r0, _KERNEL_SDA_BASE_
+	addik	r2, r0, _KERNEL_SDA2_BASE_
 
 	/* Initialize stack pointer */
-	la	r1, r0, init_thread_union + THREAD_SIZE - 4
+	addik	r1, r0, init_thread_union + THREAD_SIZE - 4
 
 	/* Initialize r31 with current task address */
-	la	r31, r0, init_task
+	addik	r31, r0, init_task
 
 	/*
 	 * Call platform dependent initialize function.
 	 * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for
 	 * the function.
 	 */
-	la	r9, r0, machine_early_init
+	addik	r9, r0, machine_early_init
 	brald	r15, r9
 	nop
 
 #ifndef CONFIG_MMU
-	la	r15, r0, machine_halt
+	addik	r15, r0, machine_halt
 	braid	start_kernel
 	nop
 #else
diff --git a/arch/microblaze/kernel/hw_exception_handler.S b/arch/microblaze/kernel/hw_exception_handler.S
index 782680d..56572e9 100644
--- a/arch/microblaze/kernel/hw_exception_handler.S
+++ b/arch/microblaze/kernel/hw_exception_handler.S
@@ -77,6 +77,8 @@
 #include <asm/signal.h>
 #include <asm/asm-offsets.h>
 
+#undef DEBUG
+
 /* Helpful Macros */
 #define NUM_TO_REG(num)		r ## num
 
@@ -91,7 +93,7 @@
 		lwi	r6, r1, PT_R6;		\
 		lwi	r11, r1, PT_R11;	\
 		lwi	r31, r1, PT_R31;	\
-		lwi	r1, r0, TOPHYS(r0_ram + 0);
+		lwi	r1, r1, PT_R1;
 #endif /* CONFIG_MMU */
 
 #define LWREG_NOP			\
@@ -206,8 +208,8 @@
  *      |      .      |
  *      |      .      |
  *
- * NO_MMU kernel use the same r0_ram pointed space - look to vmlinux.lds.S
- * which is used for storing register values - old style was, that value were
+ * MMU kernel uses the same 'pt_pool_space' pointed space
+ * which is used for storing register values - noMMu style was, that values were
  * stored in stack but in case of failure you lost information about register.
  * Currently you can see register value in memory in specific place.
  * In compare to with previous solution the speed should be the same.
@@ -226,8 +228,22 @@
  */
 
 /* wrappers to restore state before coming to entry.S */
-
 #ifdef CONFIG_MMU
+.section .data
+.align 4
+pt_pool_space:
+	.space	PT_SIZE
+
+#ifdef DEBUG
+/* Create space for exception counting. */
+.section .data
+.global exception_debug_table
+.align 4
+exception_debug_table:
+	/* Look at exception vector table. There is 32 exceptions * word size */
+	.space	(32 * 4)
+#endif /* DEBUG */
+
 .section .rodata
 .align 4
 _MB_HW_ExceptionVectorTable:
@@ -287,10 +303,10 @@ _hw_exception_handler:
 #ifndef CONFIG_MMU
 	addik	r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */
 #else
-	swi	r1, r0, TOPHYS(r0_ram + 0); /* GET_SP */
+	swi	r1, r0, TOPHYS(pt_pool_space + PT_R1); /* GET_SP */
 	/* Save date to kernel memory. Here is the problem
 	 * when you came from user space */
-	ori	r1, r0, TOPHYS(r0_ram + 28);
+	ori	r1, r0, TOPHYS(pt_pool_space);
 #endif
 	swi	r3, r1, PT_R3
 	swi	r4, r1, PT_R4
@@ -329,12 +345,12 @@ not_in_delay_slot:
 
 #ifdef DEBUG
 /* counting which exception happen */
-	lwi	r5, r0, 0x200 + TOPHYS(r0_ram)
+	lwi	r5, r0, TOPHYS(exception_debug_table)
 	addi	r5, r5, 1
-	swi	r5, r0, 0x200 + TOPHYS(r0_ram)
-	lwi	r5, r6, 0x200 + TOPHYS(r0_ram)
+	swi	r5, r0, TOPHYS(exception_debug_table)
+	lwi	r5, r6, TOPHYS(exception_debug_table)
 	addi	r5, r5, 1
-	swi	r5, r6, 0x200 + TOPHYS(r0_ram)
+	swi	r5, r6, TOPHYS(exception_debug_table)
 #endif
 /* end */
 	/* Load the HW Exception vector */
@@ -474,7 +490,7 @@ ex_lw_tail:
 	/* Get the destination register number into r5 */
 	lbui	r5, r0, TOPHYS(ex_reg_op);
 	/* Form load_word jump table offset (lw_table + (8 * regnum)) */
-	la	r6, r0, TOPHYS(lw_table);
+	addik	r6, r0, TOPHYS(lw_table);
 	addk	r5, r5, r5;
 	addk	r5, r5, r5;
 	addk	r5, r5, r5;
@@ -485,7 +501,7 @@ ex_sw:
 	/* Get the destination register number into r5 */
 	lbui	r5, r0, TOPHYS(ex_reg_op);
 	/* Form store_word jump table offset (sw_table + (8 * regnum)) */
-	la	r6, r0, TOPHYS(sw_table);
+	addik	r6, r0, TOPHYS(sw_table);
 	add	r5, r5, r5;
 	add	r5, r5, r5;
 	add	r5, r5, r5;
@@ -896,7 +912,7 @@ ex_lw_vm:
 	beqid	r6, ex_lhw_vm;
 load1:	lbui	r5, r4, 0;	/* Exception address in r4 - delay slot */
 /* Load a word, byte-by-byte from destination address and save it in tmp space*/
-	la	r6, r0, ex_tmp_data_loc_0;
+	addik	r6, r0, ex_tmp_data_loc_0;
 	sbi	r5, r6, 0;
 load2:	lbui	r5, r4, 1;
 	sbi	r5, r6, 1;
@@ -910,7 +926,7 @@ load4:	lbui	r5, r4, 3;
 ex_lhw_vm:
 	/* Load a half-word, byte-by-byte from destination address and
 	 * save it in tmp space */
-	la	r6, r0, ex_tmp_data_loc_0;
+	addik	r6, r0, ex_tmp_data_loc_0;
 	sbi	r5, r6, 0;
 load5:	lbui	r5, r4, 1;
 	sbi	r5, r6, 1;
@@ -926,7 +942,7 @@ ex_sw_vm:
 	addik	r5, r8, sw_table_vm;
 	bra	r5;
 ex_sw_tail_vm:
-	la	r5, r0, ex_tmp_data_loc_0;
+	addik	r5, r0, ex_tmp_data_loc_0;
 	beqid	r6, ex_shw_vm;
 	swi	r3, r5, 0;	/* Get the word - delay slot */
 	/* Store the word, byte-by-byte into destination address */
@@ -969,7 +985,7 @@ ex_unaligned_fixup:
 	addik	r7, r0, SIGSEGV
 	/* call bad_page_fault for finding aligned fixup, fixup address is saved
 	 * in PT_PC which is used as return address from exception */
-	la	r15, r0, ret_from_exc-8 /* setup return address */
+	addik	r15, r0, ret_from_exc-8 /* setup return address */
 	brid	bad_page_fault
 	nop
 
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index d61ea33..e466128 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -40,59 +40,46 @@ unsigned int nr_irq;
 #define MER_ME (1<<0)
 #define MER_HIE (1<<1)
 
-static void intc_enable_or_unmask(unsigned int irq)
+static void intc_enable_or_unmask(struct irq_data *d)
 {
-	unsigned long mask = 1 << irq;
-	pr_debug("enable_or_unmask: %d\n", irq);
+	unsigned long mask = 1 << d->irq;
+	pr_debug("enable_or_unmask: %d\n", d->irq);
 	out_be32(INTC_BASE + SIE, mask);
 
 	/* ack level irqs because they can't be acked during
 	 * ack function since the handle_level_irq function
 	 * acks the irq before calling the interrupt handler
 	 */
-	if (irq_desc[irq].status & IRQ_LEVEL)
+	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
 		out_be32(INTC_BASE + IAR, mask);
 }
 
-static void intc_disable_or_mask(unsigned int irq)
+static void intc_disable_or_mask(struct irq_data *d)
 {
-	pr_debug("disable: %d\n", irq);
-	out_be32(INTC_BASE + CIE, 1 << irq);
+	pr_debug("disable: %d\n", d->irq);
+	out_be32(INTC_BASE + CIE, 1 << d->irq);
 }
 
-static void intc_ack(unsigned int irq)
+static void intc_ack(struct irq_data *d)
 {
-	pr_debug("ack: %d\n", irq);
-	out_be32(INTC_BASE + IAR, 1 << irq);
+	pr_debug("ack: %d\n", d->irq);
+	out_be32(INTC_BASE + IAR, 1 << d->irq);
 }
 
-static void intc_mask_ack(unsigned int irq)
+static void intc_mask_ack(struct irq_data *d)
 {
-	unsigned long mask = 1 << irq;
-	pr_debug("disable_and_ack: %d\n", irq);
+	unsigned long mask = 1 << d->irq;
+	pr_debug("disable_and_ack: %d\n", d->irq);
 	out_be32(INTC_BASE + CIE, mask);
 	out_be32(INTC_BASE + IAR, mask);
 }
 
-static void intc_end(unsigned int irq)
-{
-	unsigned long mask = 1 << irq;
-	pr_debug("end: %d\n", irq);
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		out_be32(INTC_BASE + SIE, mask);
-		/* ack level sensitive intr */
-		if (irq_desc[irq].status & IRQ_LEVEL)
-			out_be32(INTC_BASE + IAR, mask);
-	}
-}
-
 static struct irq_chip intc_dev = {
 	.name = "Xilinx INTC",
-	.unmask = intc_enable_or_unmask,
-	.mask = intc_disable_or_mask,
-	.ack = intc_ack,
-	.mask_ack = intc_mask_ack,
-	.end = intc_end,
+	.irq_unmask = intc_enable_or_unmask,
+	.irq_mask = intc_disable_or_mask,
+	.irq_ack = intc_ack,
+	.irq_mask_ack = intc_mask_ack,
 };
 
 unsigned int get_irq(struct pt_regs *regs)
@@ -172,11 +159,11 @@ void __init init_IRQ(void)
 		if (intr_type & (0x00000001 << i)) {
 			set_irq_chip_and_handler_name(i, &intc_dev,
 				handle_edge_irq, intc_dev.name);
-			irq_desc[i].status &= ~IRQ_LEVEL;
+			irq_clear_status_flags(i, IRQ_LEVEL);
 		} else {
 			set_irq_chip_and_handler_name(i, &intc_dev,
 				handle_level_irq, intc_dev.name);
-			irq_desc[i].status |= IRQ_LEVEL;
+			irq_set_status_flags(i, IRQ_LEVEL);
 		}
 	}
 }
diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
index a9345fb..0988224 100644
--- a/arch/microblaze/kernel/irq.c
+++ b/arch/microblaze/kernel/irq.c
@@ -50,6 +50,7 @@ next_irq:
 int show_interrupts(struct seq_file *p, void *v)
 {
 	int i = *(loff_t *) v, j;
+	struct irq_desc *desc;
 	struct irqaction *action;
 	unsigned long flags;
 
@@ -61,8 +62,9 @@ int show_interrupts(struct seq_file *p, void *v)
 	}
 
 	if (i < nr_irq) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		desc = irq_to_desc(i);
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
@@ -72,9 +74,9 @@ int show_interrupts(struct seq_file *p, void *v)
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		seq_printf(p, " %8s", irq_desc[i].status &
+		seq_printf(p, " %8s", desc->status &
 					IRQ_LEVEL ? "level" : "edge");
-		seq_printf(p, " %8s", irq_desc[i].chip->name);
+		seq_printf(p, " %8s", desc->irq_data.chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action = action->next; action; action = action->next)
@@ -82,7 +84,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
 		seq_putc(p, '\n');
 skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
 	return 0;
 }
diff --git a/arch/microblaze/kernel/microblaze_ksyms.c b/arch/microblaze/kernel/microblaze_ksyms.c
index 5cb0341..49faeb4 100644
--- a/arch/microblaze/kernel/microblaze_ksyms.c
+++ b/arch/microblaze/kernel/microblaze_ksyms.c
@@ -24,6 +24,7 @@
 
 extern char *_ebss;
 EXPORT_SYMBOL_GPL(_ebss);
+
 #ifdef CONFIG_FUNCTION_TRACER
 extern void _mcount(void);
 EXPORT_SYMBOL(_mcount);
@@ -45,3 +46,14 @@ EXPORT_SYMBOL(empty_zero_page);
 #endif
 
 EXPORT_SYMBOL(mbc);
+
+extern void __divsi3(void);
+EXPORT_SYMBOL(__divsi3);
+extern void __modsi3(void);
+EXPORT_SYMBOL(__modsi3);
+extern void __mulsi3(void);
+EXPORT_SYMBOL(__mulsi3);
+extern void __udivsi3(void);
+EXPORT_SYMBOL(__udivsi3);
+extern void __umodsi3(void);
+EXPORT_SYMBOL(__umodsi3);
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index ba7c4b1..968648a 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -159,7 +159,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 	}
 
 	/* FIXME STATE_SAVE_PT_OFFSET; */
-	ti->cpu_context.r1  = (unsigned long)childregs - STATE_SAVE_ARG_SPACE;
+	ti->cpu_context.r1  = (unsigned long)childregs;
 	/* we should consider the fact that childregs is a copy of the parent
 	 * regs which were saved immediately after entering the kernel state
 	 * before enabling VM. This MSR will be restored in switch_to and
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index bceaa55..00ee90f 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -59,7 +59,7 @@ static int __init early_init_dt_scan_serial(unsigned long node,
 {
 	unsigned long l;
 	char *p;
-	int *addr;
+	const __be32 *addr;
 
 	pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
 
diff --git a/arch/microblaze/kernel/prom_parse.c b/arch/microblaze/kernel/prom_parse.c
index 9ae24f4..47187cc 100644
--- a/arch/microblaze/kernel/prom_parse.c
+++ b/arch/microblaze/kernel/prom_parse.c
@@ -2,88 +2,11 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/pci_regs.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	u32 lspec;
-	u32 laddr[3];
-	u8 pin;
-	int rc;
-
-	/* Check if we have a device node, if yes, fallback to standard OF
-	 * parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn)
-		return of_irq_map_one(dn, 0, out_irq);
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		return rc;
-	/* No pin, exit */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	lspec = pin;
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-			struct pci_controller *host;
-			host = pci_bus_to_host(pdev->bus);
-			ppnode = host ? host->dn : NULL;
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL)
-				return -EINVAL;
-		} else
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't
-		 * include the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
-
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
-		 */
-		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
-		pdev = ppdev;
-	}
-
-	laddr[0] = (pdev->bus->number << 16)
-		| (pdev->devfn << 8);
-	laddr[1]  = laddr[2] = 0;
-	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
 
 void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
 		unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/arch/microblaze/kernel/ptrace.c b/arch/microblaze/kernel/ptrace.c
index 05ac8cc..6a8e0cc 100644
--- a/arch/microblaze/kernel/ptrace.c
+++ b/arch/microblaze/kernel/ptrace.c
@@ -39,6 +39,7 @@
 #include <linux/uaccess.h>
 #include <asm/asm-offsets.h>
 #include <asm/cacheflush.h>
+#include <asm/syscall.h>
 #include <asm/io.h>
 
 /* Returns the address where the register at REG_OFFS in P is stashed away. */
@@ -123,7 +124,7 @@ long arch_ptrace(struct task_struct *child, long request,
 			rval = -EIO;
 
 		if (rval == 0 && request == PTRACE_PEEKUSR)
-			rval = put_user(val, (unsigned long *)data);
+			rval = put_user(val, (unsigned long __user *)data);
 		break;
 	default:
 		rval = ptrace_request(child, request, addr, data);
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 9312fbb..8e2c09b 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -95,7 +95,8 @@ inline unsigned get_romfs_len(unsigned *addr)
 void __init machine_early_init(const char *cmdline, unsigned int ram,
 		unsigned int fdt, unsigned int msr)
 {
-	unsigned long *src, *dst = (unsigned long *)0x0;
+	unsigned long *src, *dst;
+	unsigned int offset = 0;
 
 	/* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the
 	 * end of kernel. There are two position which we want to check.
@@ -168,7 +169,14 @@ void __init machine_early_init(const char *cmdline, unsigned int ram,
 				"CPU have it %x\n", msr);
 #endif
 
-	for (src = __ivt_start; src < __ivt_end; src++, dst++)
+	/* Do not copy reset vectors. offset = 0x2 means skip the first
+	 * two instructions. dst is pointer to MB vectors which are placed
+	 * in block ram. If you want to copy reset vector setup offset to 0x0 */
+#if !CONFIG_MANUAL_RESET_VECTOR
+	offset = 0x2;
+#endif
+	dst = (unsigned long *) (offset * sizeof(u32));
+	for (src = __ivt_start + offset; src < __ivt_end; src++, dst++)
 		*dst = *src;
 
 	/* Initialize global data */
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index d8d3bb3..5996711 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -93,7 +93,7 @@ static int restore_sigcontext(struct pt_regs *regs,
 asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
+		(struct rt_sigframe __user *)(regs->r1);
 
 	sigset_t set;
 	int rval;
@@ -197,8 +197,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	/* Create the ucontext. */
 	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user((void *)current->sas_ss_sp,
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void __user *)current->sas_ss_sp,
 			&frame->uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->r1),
 			&frame->uc.uc_stack.ss_flags);
@@ -247,7 +247,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 		goto give_sigsegv;
 
 	/* Set up registers for signal handler */
-	regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
+	regs->r1 = (unsigned long) frame;
 
 	/* Signal handler args: */
 	regs->r5 = signal; /* arg 0: signum */
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c
index 2250fe9..e5b154f 100644
--- a/arch/microblaze/kernel/sys_microblaze.c
+++ b/arch/microblaze/kernel/sys_microblaze.c
@@ -40,7 +40,8 @@ asmlinkage long microblaze_vfork(struct pt_regs *regs)
 						regs, 0, NULL, NULL);
 }
 
-asmlinkage long microblaze_clone(int flags, unsigned long stack, struct pt_regs *regs)
+asmlinkage long microblaze_clone(int flags, unsigned long stack,
+							struct pt_regs *regs)
 {
 	if (!stack)
 		stack = regs->r1;
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c
index a5aa33d..d8a214f 100644
--- a/arch/microblaze/kernel/timer.c
+++ b/arch/microblaze/kernel/timer.c
@@ -38,8 +38,8 @@ static unsigned int timer_baseaddr;
 #define TIMER_BASE	timer_baseaddr
 #endif
 
-unsigned int freq_div_hz;
-unsigned int timer_clock_freq;
+static unsigned int freq_div_hz;
+static unsigned int timer_clock_freq;
 
 #define TCSR0	(0x00)
 #define TLR0	(0x04)
@@ -202,7 +202,7 @@ static struct cyclecounter microblaze_cc = {
 	.shift = 8,
 };
 
-int __init init_microblaze_timecounter(void)
+static int __init init_microblaze_timecounter(void)
 {
 	microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
 				microblaze_cc.shift);
diff --git a/arch/microblaze/kernel/unwind.c b/arch/microblaze/kernel/unwind.c
index fefac5c..9781a52 100644
--- a/arch/microblaze/kernel/unwind.c
+++ b/arch/microblaze/kernel/unwind.c
@@ -183,7 +183,7 @@ static inline void unwind_trap(struct task_struct *task, unsigned long pc,
  * @trace : Where to store stack backtrace (PC values).
  *	    NULL == print backtrace to kernel log
  */
-void microblaze_unwind_inner(struct task_struct *task,
+static void microblaze_unwind_inner(struct task_struct *task,
 			     unsigned long pc, unsigned long fp,
 			     unsigned long leaf_return,
 			     struct stack_trace *trace)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 3451bde..ac0e1a5 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -70,11 +70,6 @@ SECTIONS {
 	RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
 	_edata = . ;
 
-	/* Reserve some low RAM for r0 based memory references */
-	. = ALIGN(0x4) ;
-	r0_ram = . ;
-	. = . +  PAGE_SIZE;	/* a page should be enough */
-
 	/* Under the microblaze ABI, .sdata and .sbss must be contiguous */
 	. = ALIGN(8);
 	.sdata : AT(ADDR(.sdata) - LOAD_OFFSET) {
diff --git a/arch/microblaze/lib/muldi3.c b/arch/microblaze/lib/muldi3.c
index d4860e1..0585bcc 100644
--- a/arch/microblaze/lib/muldi3.c
+++ b/arch/microblaze/lib/muldi3.c
@@ -58,3 +58,4 @@ DWtype __muldi3(DWtype u, DWtype v)
 
 	return w.ll;
 }
+EXPORT_SYMBOL(__muldi3);
diff --git a/arch/microblaze/mm/consistent.c b/arch/microblaze/mm/consistent.c
index 5a59dad..a1e2e18 100644
--- a/arch/microblaze/mm/consistent.c
+++ b/arch/microblaze/mm/consistent.c
@@ -59,7 +59,7 @@
  * uncached region.  This will no doubt cause big problems if memory allocated
  * here is not also freed properly. -- JW
  */
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
 {
 	unsigned long order, vaddr;
 	void *ret;
diff --git a/arch/microblaze/mm/fault.c b/arch/microblaze/mm/fault.c
index 57bd2a0..ae97d2c 100644
--- a/arch/microblaze/mm/fault.c
+++ b/arch/microblaze/mm/fault.c
@@ -48,7 +48,7 @@ static int store_updates_sp(struct pt_regs *regs)
 {
 	unsigned int inst;
 
-	if (get_user(inst, (unsigned int *)regs->pc))
+	if (get_user(inst, (unsigned int __user *)regs->pc))
 		return 0;
 	/* check for 1 in the rD field */
 	if (((inst >> 21) & 0x1f) != 1)
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index e363615..1e01a12 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_pci.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
diff --git a/arch/microblaze/pci/pci_32.c b/arch/microblaze/pci/pci_32.c
index 3c3d808..92728a6 100644
--- a/arch/microblaze/pci/pci_32.c
+++ b/arch/microblaze/pci/pci_32.c
@@ -332,6 +332,7 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
 		       hose->global_number);
 		return;
 	}
+	bus.dev->of_node = of_node_get(node);
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 7c1102e..ac1d5b6 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -286,11 +286,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64
 archprepare:
 ifdef CONFIG_MIPS32_N32
 	@echo '  Checking missing-syscalls for N32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
 	@echo '  Checking missing-syscalls for O32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
 endif
 
 install:
diff --git a/arch/mips/bcm63xx/boards/Makefile b/arch/mips/bcm63xx/boards/Makefile
index e5cc86d..9f64fb4 100644
--- a/arch/mips/bcm63xx/boards/Makefile
+++ b/arch/mips/bcm63xx/boards/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_BOARD_BCM963XX)		+= board_bcm963xx.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
diff --git a/arch/mips/fw/arc/Makefile b/arch/mips/fw/arc/Makefile
index e0aaad4..5314b37 100644
--- a/arch/mips/fw/arc/Makefile
+++ b/arch/mips/fw/arc/Makefile
@@ -9,4 +9,4 @@ lib-$(CONFIG_ARC_MEMORY)	+= memory.o
 lib-$(CONFIG_ARC_CONSOLE)	+= arc_con.o
 lib-$(CONFIG_ARC_PROMLIB)	+= promlib.o
 
-EXTRA_CFLAGS			+= -Werror
+ccflags-y			:= -Werror
diff --git a/arch/mips/include/asm/errno.h b/arch/mips/include/asm/errno.h
index a0efc73..6dcd358 100644
--- a/arch/mips/include/asm/errno.h
+++ b/arch/mips/include/asm/errno.h
@@ -121,6 +121,8 @@
 
 #define	ERFKILL		167	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	168	/* Memory page has hardware error */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 #ifdef __KERNEL__
diff --git a/arch/mips/include/asm/futex.h b/arch/mips/include/asm/futex.h
index b9cce90..6ebf173 100644
--- a/arch/mips/include/asm/futex.h
+++ b/arch/mips/include/asm/futex.h
@@ -75,7 +75,7 @@
 }
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -85,7 +85,7 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -132,11 +132,13 @@ futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int retval;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
@@ -145,25 +147,25 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -172,31 +174,32 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
 
-	return retval;
+	*uval = val;
+	return ret;
 }
 
 #endif
diff --git a/arch/mips/include/asm/ioctls.h b/arch/mips/include/asm/ioctls.h
index d967b89..92403c3 100644
--- a/arch/mips/include/asm/ioctls.h
+++ b/arch/mips/include/asm/ioctls.h
@@ -85,6 +85,7 @@
 #define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T', 0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 /* I hope the range from 0x5480 on is free ... */
 #define TIOCSCTTY	0x5480		/* become controlling tty */
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 8987a76..564ab81 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -30,6 +30,7 @@ extern struct platform_device jz4740_i2s_device;
 extern struct platform_device jz4740_pcm_device;
 extern struct platform_device jz4740_codec_device;
 extern struct platform_device jz4740_adc_device;
+extern struct platform_device jz4740_wdt_device;
 
 void jz4740_serial_device_register(void);
 
diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h
index d309556..d71160d 100644
--- a/arch/mips/include/asm/thread_info.h
+++ b/arch/mips/include/asm/thread_info.h
@@ -88,9 +88,11 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node) \
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node) \
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(info) kfree(info)
diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h
index 544a285..9520dc8 100644
--- a/arch/mips/include/asm/types.h
+++ b/arch/mips/include/asm/types.h
@@ -33,12 +33,6 @@ typedef unsigned short umode_t;
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \
-    || defined(CONFIG_64BIT)
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
 typedef u64 dma64_addr_t;
 
 /*
diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
index a604eae..a9dff33 100644
--- a/arch/mips/jz4740/Makefile
+++ b/arch/mips/jz4740/Makefile
@@ -17,4 +17,4 @@ obj-$(CONFIG_JZ4740_QI_LB60)	+= board-qi_lb60.o
 
 obj-$(CONFIG_PM) += pm.o
 
-EXTRA_CFLAGS += -Werror -Wall
+ccflags-y := -Werror -Wall
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 1cc9e54..10929e2 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -289,3 +289,19 @@ void jz4740_serial_device_register(void)
 
 	platform_device_register(&jz4740_uart_device);
 }
+
+/* Watchdog */
+static struct resource jz4740_wdt_resources[] = {
+	{
+		.start = JZ4740_WDT_BASE_ADDR,
+		.end   = JZ4740_WDT_BASE_ADDR + 0x10 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device jz4740_wdt_device = {
+	.name          = "jz4740-wdt",
+	.id            = -1,
+	.num_resources = ARRAY_SIZE(jz4740_wdt_resources),
+	.resource      = jz4740_wdt_resources,
+};
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 570607b..832afbb 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -115,7 +115,7 @@ SECTIONS
 		EXIT_DATA
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(1 << CONFIG_MIPS_L1_CACHE_SHIFT, PAGE_SIZE)
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
 	/* freed after init ends here */
diff --git a/arch/mips/oprofile/Makefile b/arch/mips/oprofile/Makefile
index 02cc65e..4b9d704 100644
--- a/arch/mips/oprofile/Makefile
+++ b/arch/mips/oprofile/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -Werror
+ccflags-y := -Werror
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
diff --git a/arch/mips/pmc-sierra/yosemite/Makefile b/arch/mips/pmc-sierra/yosemite/Makefile
index b16f95c..02f5fb9 100644
--- a/arch/mips/pmc-sierra/yosemite/Makefile
+++ b/arch/mips/pmc-sierra/yosemite/Makefile
@@ -6,4 +6,4 @@ obj-y    += irq.o prom.o py-console.o setup.o
 
 obj-$(CONFIG_SMP)		+= smp.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
diff --git a/arch/mips/powertv/Makefile b/arch/mips/powertv/Makefile
index baf6e90..348d2e8 100644
--- a/arch/mips/powertv/Makefile
+++ b/arch/mips/powertv/Makefile
@@ -28,4 +28,4 @@ obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \
 
 obj-$(CONFIG_USB) += powertv-usb.o
 
-EXTRA_CFLAGS += -Wall
+ccflags-y := -Wall
diff --git a/arch/mips/powertv/asic/Makefile b/arch/mips/powertv/asic/Makefile
index f0e95dc..d810a33 100644
--- a/arch/mips/powertv/asic/Makefile
+++ b/arch/mips/powertv/asic/Makefile
@@ -20,4 +20,4 @@ obj-y += asic-calliope.o asic-cronus.o asic-gaia.o asic-zeus.o \
 	asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
 	prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
 
-EXTRA_CFLAGS += -Wall -Werror
+ccflags-y := -Wall -Werror
diff --git a/arch/mips/powertv/pci/Makefile b/arch/mips/powertv/pci/Makefile
index f5c6246..5783201 100644
--- a/arch/mips/powertv/pci/Makefile
+++ b/arch/mips/powertv/pci/Makefile
@@ -18,4 +18,4 @@
 
 obj-$(CONFIG_PCI)	+= fixup-powertv.o
 
-EXTRA_CFLAGS += -Wall -Werror
+ccflags-y := -Wall -Werror
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 243bfa2..10971be 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -1,7 +1,8 @@
 config MN10300
 	def_bool y
 	select HAVE_OPROFILE
-	select GENERIC_HARDIRQS
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config AM33_2
 	def_bool n
@@ -53,21 +54,6 @@ config GENERIC_TIME
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-config GENERIC_CLOCKEVENTS_BUILD
-	def_bool y
-	depends on GENERIC_CLOCKEVENTS
-
-config GENERIC_CLOCKEVENTS_BROADCAST
-	bool
-
-config CEVT_MN10300
-       def_bool y
-       depends on GENERIC_CLOCKEVENTS
-
-config CSRC_MN10300
-       def_bool y
-       depends on GENERIC_TIME
-
 config GENERIC_BUG
 	def_bool y
 
diff --git a/arch/mn10300/include/asm/intctl-regs.h b/arch/mn10300/include/asm/intctl-regs.h
index 585b708..d65bbee 100644
--- a/arch/mn10300/include/asm/intctl-regs.h
+++ b/arch/mn10300/include/asm/intctl-regs.h
@@ -60,11 +60,6 @@
 
 #ifndef __ASSEMBLY__
 extern void set_intr_level(int irq, u16 level);
-extern void mn10300_intc_set_level(unsigned int irq, unsigned int level);
-extern void mn10300_intc_clear(unsigned int irq);
-extern void mn10300_intc_set(unsigned int irq);
-extern void mn10300_intc_enable(unsigned int irq);
-extern void mn10300_intc_disable(unsigned int irq);
 extern void mn10300_set_lateack_irq_type(int irq);
 #endif
 
diff --git a/arch/mn10300/include/asm/thread_info.h b/arch/mn10300/include/asm/thread_info.h
index aa07a4a..8d53f09 100644
--- a/arch/mn10300/include/asm/thread_info.h
+++ b/arch/mn10300/include/asm/thread_info.h
@@ -124,9 +124,11 @@ static inline unsigned long current_stack_pointer(void)
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(ti)	kfree((ti))
diff --git a/arch/mn10300/include/asm/types.h b/arch/mn10300/include/asm/types.h
index 7b9f010..c1833eb 100644
--- a/arch/mn10300/include/asm/types.h
+++ b/arch/mn10300/include/asm/types.h
@@ -26,13 +26,6 @@ typedef unsigned short umode_t;
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-typedef u32 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TYPES_H */
diff --git a/arch/mn10300/kernel/Makefile b/arch/mn10300/kernel/Makefile
index 8f5f1e8..a06a2e1 100644
--- a/arch/mn10300/kernel/Makefile
+++ b/arch/mn10300/kernel/Makefile
@@ -8,7 +8,8 @@ fpu-obj-$(CONFIG_FPU) := fpu.o fpu-low.o
 
 obj-y   := process.o signal.o entry.o traps.o irq.o \
 	   ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
-	   switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
+	   switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \
+	   csrc-mn10300.o cevt-mn10300.o
 
 obj-$(CONFIG_SMP) += smp.o smp-low.o
 
@@ -28,5 +29,3 @@ obj-$(CONFIG_MN10300_RTC) += rtc.o
 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o
-obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o
diff --git a/arch/mn10300/kernel/cevt-mn10300.c b/arch/mn10300/kernel/cevt-mn10300.c
index d4cb535..69cae02 100644
--- a/arch/mn10300/kernel/cevt-mn10300.c
+++ b/arch/mn10300/kernel/cevt-mn10300.c
@@ -89,9 +89,10 @@ int __init init_clockevents(void)
 	cd->name		= "Timestamp";
 	cd->features		= CLOCK_EVT_FEAT_ONESHOT;
 
-	/* Calculate the min / max delta */
-	clockevent_set_clock(cd, MN10300_JCCLK);
+	/* Calculate shift/mult. We want to spawn at least 1 second */
+	clockevents_calc_mult_shift(cd, MN10300_JCCLK, 1);
 
+	/* Calculate the min / max delta */
 	cd->max_delta_ns	= clockevent_delta2ns(TMJCBR_MAX, cd);
 	cd->min_delta_ns	= clockevent_delta2ns(100, cd);
 
@@ -110,9 +111,9 @@ int __init init_clockevents(void)
 #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
 	/* setup timer irq affinity so it only runs on this cpu */
 	{
-		struct irq_desc *desc;
-		desc = irq_to_desc(cd->irq);
-		cpumask_copy(desc->affinity, cpumask_of(cpu));
+		struct irq_data *data;
+		data = irq_get_irq_data(cd->irq);
+		cpumask_copy(data->affinity, cpumask_of(cpu));
 		iact->flags |= IRQF_NOBALANCING;
 	}
 #endif
diff --git a/arch/mn10300/kernel/csrc-mn10300.c b/arch/mn10300/kernel/csrc-mn10300.c
index ba2f0c4..45644cf 100644
--- a/arch/mn10300/kernel/csrc-mn10300.c
+++ b/arch/mn10300/kernel/csrc-mn10300.c
@@ -29,7 +29,6 @@ static struct clocksource clocksource_mn10300 = {
 int __init init_clocksource(void)
 {
 	startup_timestamp_counter();
-	clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK);
-	clocksource_register(&clocksource_mn10300);
+	clocksource_register_hz(&clocksource_mn10300, MN10300_TSCCLK);
 	return 0;
 }
diff --git a/arch/mn10300/kernel/internal.h b/arch/mn10300/kernel/internal.h
index 6a064ab..ea94661 100644
--- a/arch/mn10300/kernel/internal.h
+++ b/arch/mn10300/kernel/internal.h
@@ -33,13 +33,3 @@ extern void mn10300_low_ipi_handler(void);
  * time.c
  */
 extern irqreturn_t local_timer_interrupt(void);
-
-/*
- * time.c
- */
-#ifdef CONFIG_CEVT_MN10300
-extern void clockevent_set_clock(struct clock_event_device *, unsigned int);
-#endif
-#ifdef CONFIG_CSRC_MN10300
-extern void clocksource_set_clock(struct clocksource *, unsigned int);
-#endif
diff --git a/arch/mn10300/kernel/irq.c b/arch/mn10300/kernel/irq.c
index ac11754..f09fed5 100644
--- a/arch/mn10300/kernel/irq.c
+++ b/arch/mn10300/kernel/irq.c
@@ -37,8 +37,9 @@ atomic_t irq_err_count;
 /*
  * MN10300 interrupt controller operations
  */
-static void mn10300_cpupic_ack(unsigned int irq)
+static void mn10300_cpupic_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 	u16 tmp;
 
@@ -61,13 +62,14 @@ static void __mask_and_set_icr(unsigned int irq,
 	arch_local_irq_restore(flags);
 }
 
-static void mn10300_cpupic_mask(unsigned int irq)
+static void mn10300_cpupic_mask(struct irq_data *d)
 {
-	__mask_and_set_icr(irq, GxICR_LEVEL, 0);
+	__mask_and_set_icr(d->irq, GxICR_LEVEL, 0);
 }
 
-static void mn10300_cpupic_mask_ack(unsigned int irq)
+static void mn10300_cpupic_mask_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 #ifdef CONFIG_SMP
 	unsigned long flags;
 	u16 tmp;
@@ -85,7 +87,7 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
 		tmp2 = GxICR(irq);
 
 		irq_affinity_online[irq] =
-			any_online_cpu(*irq_desc[irq].affinity);
+			any_online_cpu(*d->affinity);
 		CROSS_GxICR(irq, irq_affinity_online[irq]) =
 			(tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
 		tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
@@ -97,13 +99,14 @@ static void mn10300_cpupic_mask_ack(unsigned int irq)
 #endif /* CONFIG_SMP */
 }
 
-static void mn10300_cpupic_unmask(unsigned int irq)
+static void mn10300_cpupic_unmask(struct irq_data *d)
 {
-	__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE);
+	__mask_and_set_icr(d->irq, GxICR_LEVEL, GxICR_ENABLE);
 }
 
-static void mn10300_cpupic_unmask_clear(unsigned int irq)
+static void mn10300_cpupic_unmask_clear(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	/* the MN10300 PIC latches its interrupt request bit, even after the
 	 * device has ceased to assert its interrupt line and the interrupt
 	 * channel has been disabled in the PIC, so for level-triggered
@@ -121,7 +124,7 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq)
 	} else {
 		tmp = GxICR(irq);
 
-		irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity);
+		irq_affinity_online[irq] = any_online_cpu(*d->affinity);
 		CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
 		tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
 	}
@@ -134,7 +137,8 @@ static void mn10300_cpupic_unmask_clear(unsigned int irq)
 
 #ifdef CONFIG_SMP
 static int
-mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
+mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
+			   bool force)
 {
 	unsigned long flags;
 	int err;
@@ -142,7 +146,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
 	flags = arch_local_cli_save();
 
 	/* check irq no */
-	switch (irq) {
+	switch (d->irq) {
 	case TMJCIRQ:
 	case RESCHEDULE_IPI:
 	case CALL_FUNC_SINGLE_IPI:
@@ -181,7 +185,7 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
 		break;
 
 	default:
-		set_bit(irq, irq_affinity_request);
+		set_bit(d->irq, irq_affinity_request);
 		err = 0;
 		break;
 	}
@@ -202,15 +206,15 @@ mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
  * mask_ack() is provided), and mask_ack() just masks.
  */
 static struct irq_chip mn10300_cpu_pic_level = {
-	.name		= "cpu_l",
-	.disable	= mn10300_cpupic_mask,
-	.enable		= mn10300_cpupic_unmask_clear,
-	.ack		= NULL,
-	.mask		= mn10300_cpupic_mask,
-	.mask_ack	= mn10300_cpupic_mask,
-	.unmask		= mn10300_cpupic_unmask_clear,
+	.name			= "cpu_l",
+	.irq_disable		= mn10300_cpupic_mask,
+	.irq_enable		= mn10300_cpupic_unmask_clear,
+	.irq_ack		= NULL,
+	.irq_mask		= mn10300_cpupic_mask,
+	.irq_mask_ack		= mn10300_cpupic_mask,
+	.irq_unmask		= mn10300_cpupic_unmask_clear,
 #ifdef CONFIG_SMP
-	.set_affinity	= mn10300_cpupic_setaffinity,
+	.irq_set_affinity	= mn10300_cpupic_setaffinity,
 #endif
 };
 
@@ -220,15 +224,15 @@ static struct irq_chip mn10300_cpu_pic_level = {
  * We use the latch clearing function of the PIC as the 'ACK' function.
  */
 static struct irq_chip mn10300_cpu_pic_edge = {
-	.name		= "cpu_e",
-	.disable	= mn10300_cpupic_mask,
-	.enable		= mn10300_cpupic_unmask,
-	.ack		= mn10300_cpupic_ack,
-	.mask		= mn10300_cpupic_mask,
-	.mask_ack	= mn10300_cpupic_mask_ack,
-	.unmask		= mn10300_cpupic_unmask,
+	.name			= "cpu_e",
+	.irq_disable		= mn10300_cpupic_mask,
+	.irq_enable		= mn10300_cpupic_unmask,
+	.irq_ack		= mn10300_cpupic_ack,
+	.irq_mask		= mn10300_cpupic_mask,
+	.irq_mask_ack		= mn10300_cpupic_mask_ack,
+	.irq_unmask		= mn10300_cpupic_unmask,
 #ifdef CONFIG_SMP
-	.set_affinity	= mn10300_cpupic_setaffinity,
+	.irq_set_affinity	= mn10300_cpupic_setaffinity,
 #endif
 };
 
@@ -252,31 +256,6 @@ void set_intr_level(int irq, u16 level)
 	__mask_and_set_icr(irq, GxICR_ENABLE, level);
 }
 
-void mn10300_intc_set_level(unsigned int irq, unsigned int level)
-{
-	set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL);
-}
-
-void mn10300_intc_clear(unsigned int irq)
-{
-	__mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT);
-}
-
-void mn10300_intc_set(unsigned int irq)
-{
-	__mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT);
-}
-
-void mn10300_intc_enable(unsigned int irq)
-{
-	mn10300_cpupic_unmask(irq);
-}
-
-void mn10300_intc_disable(unsigned int irq)
-{
-	mn10300_cpupic_mask(irq);
-}
-
 /*
  * mark an interrupt to be ACK'd after interrupt handlers have been run rather
  * than before
@@ -296,7 +275,7 @@ void __init init_IRQ(void)
 	int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++)
-		if (irq_desc[irq].chip == &no_irq_chip)
+		if (get_irq_chip(irq) == &no_irq_chip)
 			/* due to the PIC latching interrupt requests, even
 			 * when the IRQ is disabled, IRQ_PENDING is superfluous
 			 * and we can use handle_level_irq() for edge-triggered
@@ -384,12 +363,12 @@ int show_interrupts(struct seq_file *p, void *v)
 
 			if (i < NR_CPU_IRQS)
 				seq_printf(p, " %14s.%u",
-					   irq_desc[i].chip->name,
+					   irq_desc[i].irq_data.chip->name,
 					   (GxICR(i) & GxICR_LEVEL) >>
 					   GxICR_LEVEL_SHIFT);
 			else
 				seq_printf(p, " %14s",
-					   irq_desc[i].chip->name);
+					   irq_desc[i].irq_data.chip->name);
 
 			seq_printf(p, "  %s", action->name);
 
diff --git a/arch/mn10300/kernel/mn10300-serial.c b/arch/mn10300/kernel/mn10300-serial.c
index 996384d..93c5373 100644
--- a/arch/mn10300/kernel/mn10300-serial.c
+++ b/arch/mn10300/kernel/mn10300-serial.c
@@ -384,17 +384,21 @@ static void mn10300_serial_mask_ack(unsigned int irq)
 	arch_local_irq_restore(flags);
 }
 
-static void mn10300_serial_nop(unsigned int irq)
+static void mn10300_serial_chip_mask_ack(struct irq_data *d)
+{
+	mn10300_serial_mask_ack(d->irq);
+}
+
+static void mn10300_serial_nop(struct irq_data *d)
 {
 }
 
 static struct irq_chip mn10300_serial_pic = {
 	.name		= "mnserial",
-	.ack		= mn10300_serial_mask_ack,
-	.mask		= mn10300_serial_mask_ack,
-	.mask_ack	= mn10300_serial_mask_ack,
-	.unmask		= mn10300_serial_nop,
-	.end		= mn10300_serial_nop,
+	.irq_ack	= mn10300_serial_chip_mask_ack,
+	.irq_mask	= mn10300_serial_chip_mask_ack,
+	.irq_mask_ack	= mn10300_serial_chip_mask_ack,
+	.irq_unmask	= mn10300_serial_nop,
 };
 
 
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c
index 0dcd1c6..1ebb79f 100644
--- a/arch/mn10300/kernel/smp.c
+++ b/arch/mn10300/kernel/smp.c
@@ -113,15 +113,17 @@ static void init_ipi(void);
  */
 static void mn10300_ipi_disable(unsigned int irq);
 static void mn10300_ipi_enable(unsigned int irq);
-static void mn10300_ipi_ack(unsigned int irq);
-static void mn10300_ipi_nop(unsigned int irq);
+static void mn10300_ipi_chip_disable(struct irq_data *d);
+static void mn10300_ipi_chip_enable(struct irq_data *d);
+static void mn10300_ipi_ack(struct irq_data *d);
+static void mn10300_ipi_nop(struct irq_data *d);
 
 static struct irq_chip mn10300_ipi_type = {
 	.name		= "cpu_ipi",
-	.disable	= mn10300_ipi_disable,
-	.enable		= mn10300_ipi_enable,
-	.ack		= mn10300_ipi_ack,
-	.eoi		= mn10300_ipi_nop
+	.irq_disable	= mn10300_ipi_chip_disable,
+	.irq_enable	= mn10300_ipi_chip_enable,
+	.irq_ack	= mn10300_ipi_ack,
+	.irq_eoi	= mn10300_ipi_nop
 };
 
 static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id);
@@ -236,6 +238,11 @@ static void mn10300_ipi_enable(unsigned int irq)
 	arch_local_irq_restore(flags);
 }
 
+static void mn10300_ipi_chip_enable(struct irq_data *d)
+{
+	mn10300_ipi_enable(d->irq);
+}
+
 /**
  * mn10300_ipi_disable - Disable an IPI
  * @irq: The IPI to be disabled.
@@ -254,6 +261,12 @@ static void mn10300_ipi_disable(unsigned int irq)
 	arch_local_irq_restore(flags);
 }
 
+static void mn10300_ipi_chip_disable(struct irq_data *d)
+{
+	mn10300_ipi_disable(d->irq);
+}
+
+
 /**
  * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC
  * @irq: The IPI to be acknowledged.
@@ -261,8 +274,9 @@ static void mn10300_ipi_disable(unsigned int irq)
  * Clear the interrupt detection flag for the IPI on the appropriate interrupt
  * channel in the PIC.
  */
-static void mn10300_ipi_ack(unsigned int irq)
+static void mn10300_ipi_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 	u16 tmp;
 
@@ -276,7 +290,7 @@ static void mn10300_ipi_ack(unsigned int irq)
  * mn10300_ipi_nop - Dummy IPI action
  * @irq: The IPI to be acted upon.
  */
-static void mn10300_ipi_nop(unsigned int irq)
+static void mn10300_ipi_nop(struct irq_data *d)
 {
 }
 
diff --git a/arch/mn10300/kernel/time.c b/arch/mn10300/kernel/time.c
index 75da468..67c6416 100644
--- a/arch/mn10300/kernel/time.c
+++ b/arch/mn10300/kernel/time.c
@@ -93,83 +93,6 @@ irqreturn_t local_timer_interrupt(void)
 	return IRQ_HANDLED;
 }
 
-#ifndef CONFIG_GENERIC_TIME
-/*
- * advance the kernel's time keeping clocks (xtime and jiffies)
- * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
- *   there's a need to update
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	unsigned tsc, elapse;
-	irqreturn_t ret;
-
-	write_seqlock(&xtime_lock);
-
-	while (tsc = get_cycles(),
-	       elapse = tsc - mn10300_last_tsc, /* time elapsed since last
-						 * tick */
-	       elapse > MN10300_TSC_PER_HZ
-	       ) {
-		mn10300_last_tsc += MN10300_TSC_PER_HZ;
-
-		/* advance the kernel's time tracking system */
-		do_timer(1);
-	}
-
-	write_sequnlock(&xtime_lock);
-
-	ret = local_timer_interrupt();
-#ifdef CONFIG_SMP
-	send_IPI_allbutself(LOCAL_TIMER_IPI);
-#endif
-	return ret;
-}
-
-static struct irqaction timer_irq = {
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
-	.name		= "timer",
-};
-#endif /* CONFIG_GENERIC_TIME */
-
-#ifdef CONFIG_CSRC_MN10300
-void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
-{
-	u64 temp;
-	u32 shift;
-
-	/* Find a shift value */
-	for (shift = 32; shift > 0; shift--) {
-		temp = (u64) NSEC_PER_SEC << shift;
-		do_div(temp, clock);
-		if ((temp >> 32) == 0)
-			break;
-	}
-	cs->shift = shift;
-	cs->mult = (u32) temp;
-}
-#endif
-
-#if CONFIG_CEVT_MN10300
-void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
-				    unsigned int clock)
-{
-	u64 temp;
-	u32 shift;
-
-	/* Find a shift value */
-	for (shift = 32; shift > 0; shift--) {
-		temp = (u64) clock << shift;
-		do_div(temp, NSEC_PER_SEC);
-		if ((temp >> 32) == 0)
-			break;
-	}
-	cd->shift = shift;
-	cd->mult = (u32) temp;
-}
-#endif
-
 /*
  * initialise the various timers used by the main part of the kernel
  */
@@ -181,11 +104,7 @@ void __init time_init(void)
 	 */
 	TMPSCNT |= TMPSCNT_ENABLE;
 
-#ifdef CONFIG_GENERIC_TIME
 	init_clocksource();
-#else
-	startup_timestamp_counter();
-#endif
 
 	printk(KERN_INFO
 	       "timestamp counter I/O clock running at %lu.%02lu"
@@ -194,12 +113,7 @@ void __init time_init(void)
 
 	mn10300_last_tsc = read_timestamp_counter();
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 	init_clockevents();
-#else
-	reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
-	setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL);
-#endif
 
 #ifdef CONFIG_MN10300_WD_TIMER
 	/* start the watchdog timer */
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index febbeee..968bcd2 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -70,7 +70,7 @@ SECTIONS
 	.exit.text : { EXIT_TEXT; }
 	.exit.data : { EXIT_DATA; }
 
-  PERCPU(PAGE_SIZE)
+  PERCPU(32, PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
diff --git a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
index 7cf1205..33f100f 100644
--- a/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
+++ b/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
@@ -14,7 +14,7 @@
 #define ASB2364_FPGA_REG_RESET_USB	__SYSREG(0xa900130c, u16)
 #define ASB2364_FPGA_REG_RESET_AV	__SYSREG(0xa9001310, u16)
 
-#define ASB2364_FPGA_REG_IRQ(X)		__SYSREG(0xa9001590+((X)*4), u16)
+#define ASB2364_FPGA_REG_IRQ(X)		__SYSREG(0xa9001510+((X)*4), u16)
 #define ASB2364_FPGA_REG_IRQ_LAN	ASB2364_FPGA_REG_IRQ(0)
 #define ASB2364_FPGA_REG_IRQ_UART	ASB2364_FPGA_REG_IRQ(1)
 #define ASB2364_FPGA_REG_IRQ_I2C	ASB2364_FPGA_REG_IRQ(2)
diff --git a/arch/mn10300/unit-asb2364/include/unit/serial.h b/arch/mn10300/unit-asb2364/include/unit/serial.h
index 7f048bb..92f224a 100644
--- a/arch/mn10300/unit-asb2364/include/unit/serial.h
+++ b/arch/mn10300/unit-asb2364/include/unit/serial.h
@@ -59,18 +59,18 @@ static inline void __debug_to_serial(const char *p, int n)
 #define SERIAL_PORT_DFNS /* stolen by gdb-stub */
 
 #if defined(CONFIG_GDBSTUB_ON_TTYS0)
-#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 4, u8)
-#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 4, u8)
-#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
-#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
-#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
-#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
-#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
-#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
-#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
-#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
-#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
-#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
+#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 2, u8)
+#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 2, u8)
+#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 2, u8)
+#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 2, u8)
+#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 2, u8)
+#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 2, u8)
+#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 2, u8)
+#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 2, u8)
+#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 2, u8)
+#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 2, u8)
+#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 2, u8)
 #define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
 
 #elif defined(CONFIG_GDBSTUB_ON_TTYS1)
diff --git a/arch/mn10300/unit-asb2364/irq-fpga.c b/arch/mn10300/unit-asb2364/irq-fpga.c
index fcf2975..ee84e62 100644
--- a/arch/mn10300/unit-asb2364/irq-fpga.c
+++ b/arch/mn10300/unit-asb2364/irq-fpga.c
@@ -17,38 +17,38 @@
 /*
  * FPGA PIC operations
  */
-static void asb2364_fpga_mask(unsigned int irq)
+static void asb2364_fpga_mask(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
 }
 
-static void asb2364_fpga_ack(unsigned int irq)
+static void asb2364_fpga_ack(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
 }
 
-static void asb2364_fpga_mask_ack(unsigned int irq)
+static void asb2364_fpga_mask_ack(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
-	ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
 }
 
-static void asb2364_fpga_unmask(unsigned int irq)
+static void asb2364_fpga_unmask(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000;
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0000;
 	SyncExBus();
 }
 
 static struct irq_chip asb2364_fpga_pic = {
 	.name		= "fpga",
-	.ack		= asb2364_fpga_ack,
-	.mask		= asb2364_fpga_mask,
-	.mask_ack	= asb2364_fpga_mask_ack,
-	.unmask		= asb2364_fpga_unmask,
+	.irq_ack	= asb2364_fpga_ack,
+	.irq_mask	= asb2364_fpga_mask,
+	.irq_mask_ack	= asb2364_fpga_mask_ack,
+	.irq_unmask	= asb2364_fpga_unmask,
 };
 
 /*
@@ -88,6 +88,17 @@ void __init irq_fpga_init(void)
 {
 	int irq;
 
+	ASB2364_FPGA_REG_MASK_LAN  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_UART = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_I2C  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_USB  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_FPGA = 0x0001;
+	SyncExBus();
+
 	for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++)
 		set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq);
 
diff --git a/arch/mn10300/unit-asb2364/unit-init.c b/arch/mn10300/unit-asb2364/unit-init.c
index 1144080..6359b41 100644
--- a/arch/mn10300/unit-asb2364/unit-init.c
+++ b/arch/mn10300/unit-asb2364/unit-init.c
@@ -20,13 +20,41 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/intctl-regs.h>
+#include <asm/serial-regs.h>
 #include <unit/fpga-regs.h>
+#include <unit/serial.h>
+#include <unit/smsc911x.h>
+
+#define TTYS0_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define LAN_IRQ_CFG		__SYSREG(SMSC911X_BASE + 0x54, u32)
+#define LAN_INT_EN		__SYSREG(SMSC911X_BASE + 0x5c, u32)
 
 /*
  * initialise some of the unit hardware before gdbstub is set up
  */
 asmlinkage void __init unit_init(void)
 {
+	/* Make sure we aren't going to get unexpected interrupts */
+	TTYS0_SERIAL_IER = 0;
+	SC0RXICR = 0;
+	SC0TXICR = 0;
+	SC1RXICR = 0;
+	SC1TXICR = 0;
+	SC2RXICR = 0;
+	SC2TXICR = 0;
+
+	/* Attempt to reset the FPGA attached peripherals */
+	ASB2364_FPGA_REG_RESET_LAN = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_UART = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_I2C = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_USB = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_AV = 0x0000;
+	SyncExBus();
+
 	/* set up the external interrupts */
 
 	/* XIRQ[0]: NAND RXBY */
@@ -56,7 +84,23 @@ asmlinkage void __init unit_init(void)
  */
 asmlinkage void __init unit_setup(void)
 {
+	/* Release the reset on the SMSC911X so that it is ready by the time we
+	 * need it */
+	ASB2364_FPGA_REG_RESET_LAN = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_UART = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_I2C = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_USB = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_AV = 0x0001;
+	SyncExBus();
 
+	/* Make sure the ethernet chipset isn't going to give us an interrupt
+	 * storm from stuff it was doing pre-reset */
+	LAN_IRQ_CFG = 0;
+	LAN_INT_EN = 0;
 }
 
 /*
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index fed2946..fafdf30 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -15,6 +15,7 @@ config PARISC
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select IRQ_PER_CPU
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 3039408..6ab9580 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -185,26 +185,21 @@ struct hpux_statfs {
      int16_t f_pad;
 };
 
-static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf)
+static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p)
 {
-	struct kstatfs st;
-	int retval;
-	
-	retval = vfs_statfs(path, &st);
-	if (retval)
-		return retval;
-
-	memset(buf, 0, sizeof(*buf));
-	buf->f_type = st.f_type;
-	buf->f_bsize = st.f_bsize;
-	buf->f_blocks = st.f_blocks;
-	buf->f_bfree = st.f_bfree;
-	buf->f_bavail = st.f_bavail;
-	buf->f_files = st.f_files;
-	buf->f_ffree = st.f_ffree;
-	buf->f_fsid[0] = st.f_fsid.val[0];
-	buf->f_fsid[1] = st.f_fsid.val[1];
-
+	struct hpux_statfs buf;
+	memset(&buf, 0, sizeof(buf));
+	buf.f_type = st->f_type;
+	buf.f_bsize = st->f_bsize;
+	buf.f_blocks = st->f_blocks;
+	buf.f_bfree = st->f_bfree;
+	buf.f_bavail = st->f_bavail;
+	buf.f_files = st->f_files;
+	buf.f_ffree = st->f_ffree;
+	buf.f_fsid[0] = st->f_fsid.val[0];
+	buf.f_fsid[1] = st->f_fsid.val[1];
+	if (copy_to_user(p, &buf, sizeof(buf)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -212,35 +207,19 @@ static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf)
 asmlinkage long hpux_statfs(const char __user *pathname,
 						struct hpux_statfs __user *buf)
 {
-	struct path path;
-	int error;
-
-	error = user_path(pathname, &path);
-	if (!error) {
-		struct hpux_statfs tmp;
-		error = do_statfs_hpux(&path, &tmp);
-		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-			error = -EFAULT;
-		path_put(&path);
-	}
+	struct kstatfs st;
+	int error = user_statfs(pathname, &st);
+	if (!error)
+		error = do_statfs_hpux(&st, buf);
 	return error;
 }
 
 asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
 {
-	struct file *file;
-	struct hpux_statfs tmp;
-	int error;
-
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-	error = do_statfs_hpux(&file->f_path, &tmp);
-	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-		error = -EFAULT;
-	fput(file);
- out:
+	struct kstatfs st;
+	int error = fd_statfs(fd, &st);
+	if (!error)
+		error = do_statfs_hpux(&st, buf);
 	return error;
 }
 
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index f388a85..d18328b 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -26,8 +26,6 @@ void flush_user_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_page_asm(void *);
 void flush_kernel_icache_page(void *);
-void flush_user_dcache_page(unsigned long);
-void flush_user_icache_page(unsigned long);
 void flush_user_dcache_range(unsigned long, unsigned long);
 void flush_user_icache_range(unsigned long, unsigned long);
 
@@ -37,6 +35,13 @@ void flush_cache_all_local(void);
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+void flush_kernel_dcache_page_addr(void *addr);
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+	flush_kernel_dcache_page_addr(page_address(page));
+}
+
 #define flush_kernel_dcache_range(start,size) \
 	flush_kernel_dcache_range_asm((start), (start)+(size));
 /* vmap range flushes and invalidates.  Architecturally, we don't need
@@ -50,6 +55,16 @@ static inline void flush_kernel_vmap_range(void *vaddr, int size)
 }
 static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
 {
+	unsigned long start = (unsigned long)vaddr;
+	void *cursor = vaddr;
+
+	for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) {
+		struct page *page = vmalloc_to_page(cursor);
+
+		if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+			flush_kernel_dcache_page(page);
+	}
+	flush_kernel_dcache_range_asm(start, start + size);
 }
 
 #define flush_cache_vmap(start, end)		flush_cache_all()
@@ -90,19 +105,15 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned
 void flush_cache_range(struct vm_area_struct *vma,
 		unsigned long start, unsigned long end);
 
+/* defined in pacache.S exported in cache.c used by flush_anon_page */
+void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+
 #define ARCH_HAS_FLUSH_ANON_PAGE
 static inline void
 flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
 {
 	if (PageAnon(page))
-		flush_user_dcache_page(vmaddr);
-}
-
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-void flush_kernel_dcache_page_addr(void *addr);
-static inline void flush_kernel_dcache_page(struct page *page)
-{
-	flush_kernel_dcache_page_addr(page_address(page));
+		flush_dcache_page_asm(page_to_phys(page), vmaddr);
 }
 
 #ifdef CONFIG_DEBUG_RODATA
diff --git a/arch/parisc/include/asm/errno.h b/arch/parisc/include/asm/errno.h
index 9992abd..135ad60 100644
--- a/arch/parisc/include/asm/errno.h
+++ b/arch/parisc/include/asm/errno.h
@@ -122,4 +122,6 @@
 
 #define	ERFKILL		256	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	257	/* Memory page has hardware error */
+
 #endif
diff --git a/arch/parisc/include/asm/fcntl.h b/arch/parisc/include/asm/fcntl.h
index f357fc6..0304b92 100644
--- a/arch/parisc/include/asm/fcntl.h
+++ b/arch/parisc/include/asm/fcntl.h
@@ -19,6 +19,8 @@
 #define O_NOFOLLOW	000000200 /* don't follow links */
 #define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
 
+#define O_PATH		020000000
+
 #define F_GETLK64	8
 #define F_SETLK64	9
 #define F_SETLKW64	10
diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h
index 0c705c3..67a33cc 100644
--- a/arch/parisc/include/asm/futex.h
+++ b/arch/parisc/include/asm/futex.h
@@ -8,7 +8,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -51,10 +51,10 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int err = 0;
-	int uval;
+	u32 val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -62,15 +62,15 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
 	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
 		return -EFAULT;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	err = get_user(uval, uaddr);
-	if (err) return -EFAULT;
-	if (uval == oldval)
-		err = put_user(newval, uaddr);
-	if (err) return -EFAULT;
-	return uval;
+	if (get_user(val, uaddr))
+		return -EFAULT;
+	if (val == oldval && put_user(newval, uaddr))
+		return -EFAULT;
+	*uval = val;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff --git a/arch/parisc/include/asm/ioctls.h b/arch/parisc/include/asm/ioctls.h
index 6ba80d0..054ec06 100644
--- a/arch/parisc/include/asm/ioctls.h
+++ b/arch/parisc/include/asm/ioctls.h
@@ -54,6 +54,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, int)  /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 #define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX		0x5451
diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h
index c67dccf..1073599 100644
--- a/arch/parisc/include/asm/irq.h
+++ b/arch/parisc/include/asm/irq.h
@@ -32,15 +32,10 @@ static __inline__ int irq_canonicalize(int irq)
 }
 
 struct irq_chip;
+struct irq_data;
 
-/*
- * Some useful "we don't have to do anything here" handlers.  Should
- * probably be provided by the generic code.
- */
-void no_ack_irq(unsigned int irq);
-void no_end_irq(unsigned int irq);
-void cpu_ack_irq(unsigned int irq);
-void cpu_eoi_irq(unsigned int irq);
+void cpu_ack_irq(struct irq_data *d);
+void cpu_eoi_irq(struct irq_data *d);
 
 extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
@@ -49,7 +44,7 @@ extern unsigned long txn_alloc_addr(unsigned int);
 extern unsigned long txn_affinity_addr(unsigned int irq, int cpu);
 
 extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
-extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest);
+extern int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest);
 
 /* soft power switch support (power.c) */
 extern struct tasklet_struct power_tasklet;
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 6f1f65d..5d7b8ce 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -138,8 +138,7 @@ struct vm_area_struct;
 #define _PAGE_NO_CACHE_BIT 24   /* (0x080) Uncached Page (U bit) */
 #define _PAGE_ACCESSED_BIT 23   /* (0x100) Software: Page Accessed */
 #define _PAGE_PRESENT_BIT  22   /* (0x200) Software: translation valid */
-#define _PAGE_FLUSH_BIT    21   /* (0x400) Software: translation valid */
-				/*             for cache flushing only */
+/* bit 21 was formerly the FLUSH bit but is now unused */
 #define _PAGE_USER_BIT     20   /* (0x800) Software: User accessible page */
 
 /* N.B. The bits are defined in terms of a 32 bit word above, so the */
@@ -173,7 +172,6 @@ struct vm_area_struct;
 #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT))
 #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT))
 #define _PAGE_PRESENT  (1 << xlate_pabit(_PAGE_PRESENT_BIT))
-#define _PAGE_FLUSH    (1 << xlate_pabit(_PAGE_FLUSH_BIT))
 #define _PAGE_USER     (1 << xlate_pabit(_PAGE_USER_BIT))
 #define _PAGE_FILE     (1 << xlate_pabit(_PAGE_FILE_BIT))
 
@@ -213,7 +211,6 @@ struct vm_area_struct;
 #define PAGE_KERNEL_RO	__pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
 #define PAGE_KERNEL_UNC	__pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
 #define PAGE_GATEWAY    __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ)
-#define PAGE_FLUSH      __pgprot(_PAGE_FLUSH)
 
 
 /*
@@ -261,7 +258,7 @@ extern unsigned long *empty_zero_page;
 
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
-#define pte_none(x)     ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH))
+#define pte_none(x)     (pte_val(x) == 0)
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
 #define pte_clear(mm,addr,xp)	do { pte_val(*(xp)) = 0; } while (0)
 
@@ -444,13 +441,10 @@ struct mm_struct;
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t old_pte;
-	pte_t pte;
 
 	spin_lock(&pa_dbit_lock);
-	pte = old_pte = *ptep;
-	pte_val(pte) &= ~_PAGE_PRESENT;
-	pte_val(pte) |= _PAGE_FLUSH;
-	set_pte_at(mm,addr,ptep,pte);
+	old_pte = *ptep;
+	pte_clear(mm,addr,ptep);
 	spin_unlock(&pa_dbit_lock);
 
 	return old_pte;
diff --git a/arch/parisc/include/asm/types.h b/arch/parisc/include/asm/types.h
index 20135cc..bc164dd 100644
--- a/arch/parisc/include/asm/types.h
+++ b/arch/parisc/include/asm/types.h
@@ -16,9 +16,6 @@ typedef unsigned short umode_t;
 
 #ifndef __ASSEMBLY__
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
 typedef u64 dma64_addr_t;
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index d054f3d..3f11331 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -27,12 +27,17 @@
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
+#include <asm/shmparam.h>
 
 int split_tlb __read_mostly;
 int dcache_stride __read_mostly;
 int icache_stride __read_mostly;
 EXPORT_SYMBOL(dcache_stride);
 
+void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+EXPORT_SYMBOL(flush_dcache_page_asm);
+void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+
 
 /* On some machines (e.g. ones with the Merced bus), there can be
  * only a single PxTLB broadcast at a time; this must be guaranteed
@@ -259,81 +264,13 @@ void disable_sr_hashing(void)
 		panic("SpaceID hashing is still on!\n");
 }
 
-/* Simple function to work out if we have an existing address translation
- * for a user space vma. */
-static inline int translation_exists(struct vm_area_struct *vma,
-				unsigned long addr, unsigned long pfn)
-{
-	pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
-	pmd_t *pmd;
-	pte_t pte;
-
-	if(pgd_none(*pgd))
-		return 0;
-
-	pmd = pmd_offset(pgd, addr);
-	if(pmd_none(*pmd) || pmd_bad(*pmd))
-		return 0;
-
-	/* We cannot take the pte lock here: flush_cache_page is usually
-	 * called with pte lock already held.  Whereas flush_dcache_page
-	 * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
-	 * the vma itself is secure, but the pte might come or go racily.
-	 */
-	pte = *pte_offset_map(pmd, addr);
-	/* But pte_unmap() does nothing on this architecture */
-
-	/* Filter out coincidental file entries and swap entries */
-	if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
-		return 0;
-
-	return pte_pfn(pte) == pfn;
-}
-
-/* Private function to flush a page from the cache of a non-current
- * process.  cr25 contains the Page Directory of the current user
- * process; we're going to hijack both it and the user space %sr3 to
- * temporarily make the non-current process current.  We have to do
- * this because cache flushing may cause a non-access tlb miss which
- * the handlers have to fill in from the pgd of the non-current
- * process. */
 static inline void
-flush_user_cache_page_non_current(struct vm_area_struct *vma,
-				  unsigned long vmaddr)
+__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
+		   unsigned long physaddr)
 {
-	/* save the current process space and pgd */
-	unsigned long space = mfsp(3), pgd = mfctl(25);
-
-	/* we don't mind taking interrupts since they may not
-	 * do anything with user space, but we can't
-	 * be preempted here */
-	preempt_disable();
-
-	/* make us current */
-	mtctl(__pa(vma->vm_mm->pgd), 25);
-	mtsp(vma->vm_mm->context, 3);
-
-	flush_user_dcache_page(vmaddr);
-	if(vma->vm_flags & VM_EXEC)
-		flush_user_icache_page(vmaddr);
-
-	/* put the old current process back */
-	mtsp(space, 3);
-	mtctl(pgd, 25);
-	preempt_enable();
-}
-
-
-static inline void
-__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
-{
-	if (likely(vma->vm_mm->context == mfsp(3))) {
-		flush_user_dcache_page(vmaddr);
-		if (vma->vm_flags & VM_EXEC)
-			flush_user_icache_page(vmaddr);
-	} else {
-		flush_user_cache_page_non_current(vma, vmaddr);
-	}
+	flush_dcache_page_asm(physaddr, vmaddr);
+	if (vma->vm_flags & VM_EXEC)
+		flush_icache_page_asm(physaddr, vmaddr);
 }
 
 void flush_dcache_page(struct page *page)
@@ -342,10 +279,8 @@ void flush_dcache_page(struct page *page)
 	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
 	unsigned long offset;
-	unsigned long addr;
+	unsigned long addr, old_addr = 0;
 	pgoff_t pgoff;
-	unsigned long pfn = page_to_pfn(page);
-
 
 	if (mapping && !mapping_mapped(mapping)) {
 		set_bit(PG_dcache_dirty, &page->flags);
@@ -369,20 +304,11 @@ void flush_dcache_page(struct page *page)
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 		addr = mpnt->vm_start + offset;
 
-		/* Flush instructions produce non access tlb misses.
-		 * On PA, we nullify these instructions rather than
-		 * taking a page fault if the pte doesn't exist.
-		 * This is just for speed.  If the page translation
-		 * isn't there, there's no point exciting the
-		 * nadtlb handler into a nullification frenzy.
-		 *
-		 * Make sure we really have this page: the private
-		 * mappings may cover this area but have COW'd this
-		 * particular page.
-		 */
-  		if (translation_exists(mpnt, addr, pfn)) {
-			__flush_cache_page(mpnt, addr);
-			break;
+		if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
+			__flush_cache_page(mpnt, addr, page_to_phys(page));
+			if (old_addr)
+				printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
+			old_addr = addr;
 		}
 	}
 	flush_dcache_mmap_unlock(mapping);
@@ -573,7 +499,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
 {
 	BUG_ON(!vma->vm_mm->context);
 
-	if (likely(translation_exists(vma, vmaddr, pfn)))
-		__flush_cache_page(vma, vmaddr);
+	__flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
 
 }
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6337ade..e547709 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -225,22 +225,13 @@
 #ifndef CONFIG_64BIT
 	/*
 	 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
-	 *
-	 * Note: naitlb misses will be treated
-	 * as an ordinary itlb miss for now.
-	 * However, note that naitlb misses
-	 * have the faulting address in the
-	 * IOR/ISR.
 	 */
 
 	.macro	naitlb_11 code
 
 	mfctl	%isr,spc
-	b	itlb_miss_11
+	b	naitlb_miss_11
 	mfctl 	%ior,va
-	/* FIXME: If user causes a naitlb miss, the priv level may not be in
-	 * lower bits of va, where the itlb miss handler is expecting them
-	 */
 
 	.align		32
 	.endm
@@ -248,26 +239,17 @@
 	
 	/*
 	 * naitlb miss interruption handler (parisc 2.0)
-	 *
-	 * Note: naitlb misses will be treated
-	 * as an ordinary itlb miss for now.
-	 * However, note that naitlb misses
-	 * have the faulting address in the
-	 * IOR/ISR.
 	 */
 
 	.macro	naitlb_20 code
 
 	mfctl	%isr,spc
 #ifdef CONFIG_64BIT
-	b       itlb_miss_20w
+	b       naitlb_miss_20w
 #else
-	b	itlb_miss_20
+	b	naitlb_miss_20
 #endif
 	mfctl 	%ior,va
-	/* FIXME: If user causes a naitlb miss, the priv level may not be in
-	 * lower bits of va, where the itlb miss handler is expecting them
-	 */
 
 	.align		32
 	.endm
@@ -581,7 +563,24 @@
 	copy		\va,\tmp1
 	depi		0,31,23,\tmp1
 	cmpb,COND(<>),n	\tmp,\tmp1,\fault
-	ldi		(_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
+	mfctl		%cr19,\tmp	/* iir */
+	/* get the opcode (first six bits) into \tmp */
+	extrw,u		\tmp,5,6,\tmp
+	/*
+	 * Only setting the T bit prevents data cache movein
+	 * Setting access rights to zero prevents instruction cache movein
+	 *
+	 * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go
+	 * to type field and _PAGE_READ goes to top bit of PL1
+	 */
+	ldi		(_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot
+	/*
+	 * so if the opcode is one (i.e. this is a memory management
+	 * instruction) nullify the next load so \prot is only T.
+	 * Otherwise this is a normal data operation
+	 */
+	cmpiclr,=	0x01,\tmp,%r0
+	ldi		(_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
 	depd,z		\prot,8,7,\prot
 	/*
 	 * OK, it is in the temp alias region, check whether "from" or "to".
@@ -631,11 +630,7 @@ ENTRY(fault_vector_20)
 	def		13
 	def		14
 	dtlb_20		15
-#if 0
 	naitlb_20	16
-#else
-	def             16
-#endif
 	nadtlb_20	17
 	def		18
 	def		19
@@ -678,11 +673,7 @@ ENTRY(fault_vector_11)
 	def		13
 	def		14
 	dtlb_11		15
-#if 0
 	naitlb_11	16
-#else
-	def             16
-#endif
 	nadtlb_11	17
 	def		18
 	def		19
@@ -1203,7 +1194,7 @@ nadtlb_miss_20w:
 	get_pgd		spc,ptp
 	space_check	spc,t0,nadtlb_fault
 
-	L3_ptep		ptp,pte,t0,va,nadtlb_check_flush_20w
+	L3_ptep		ptp,pte,t0,va,nadtlb_check_alias_20w
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1214,16 +1205,8 @@ nadtlb_miss_20w:
 	rfir
 	nop
 
-nadtlb_check_flush_20w:
-	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-	/* Insert a "flush only" translation */
-
-	depdi,z         7,7,3,prot
-	depdi           1,10,1,prot
-
-	/* Drop prot bits from pte and convert to page addr for idtlbt */
-	convert_for_tlb_insert20 pte
+nadtlb_check_alias_20w:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_emulate
 
 	idtlbt          pte,prot
 
@@ -1255,25 +1238,7 @@ dtlb_miss_11:
 	nop
 
 dtlb_check_alias_11:
-
-	/* Check to see if fault is in the temporary alias region */
-
-	cmpib,<>,n      0,spc,dtlb_fault /* forward */
-	ldil            L%(TMPALIAS_MAP_START),t0
-	copy            va,t1
-	depwi           0,31,23,t1
-	cmpb,<>,n       t0,t1,dtlb_fault /* forward */
-	ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
-	depw,z          prot,8,7,prot
-
-	/*
-	 * OK, it is in the temp alias region, check whether "from" or "to".
-	 * Check "subtle" note in pacache.S re: r23/r26.
-	 */
-
-	extrw,u,=       va,9,1,r0
-	or,tr           %r23,%r0,pte    /* If "from" use "from" page */
-	or              %r26,%r0,pte    /* else "to", use "to" page  */
+	do_alias	spc,t0,t1,va,pte,prot,dtlb_fault
 
 	idtlba          pte,(va)
 	idtlbp          prot,(va)
@@ -1286,7 +1251,7 @@ nadtlb_miss_11:
 
 	space_check	spc,t0,nadtlb_fault
 
-	L2_ptep		ptp,pte,t0,va,nadtlb_check_flush_11
+	L2_ptep		ptp,pte,t0,va,nadtlb_check_alias_11
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1304,26 +1269,11 @@ nadtlb_miss_11:
 	rfir
 	nop
 
-nadtlb_check_flush_11:
-	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-	/* Insert a "flush only" translation */
-
-	zdepi           7,7,3,prot
-	depi            1,10,1,prot
+nadtlb_check_alias_11:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_emulate
 
-	/* Get rid of prot bits and convert to page addr for idtlba */
-
-	depi		0,31,ASM_PFN_PTE_SHIFT,pte
-	SHRREG		pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte
-
-	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
-	mtsp		spc,%sr1
-
-	idtlba		pte,(%sr1,va)
-	idtlbp		prot,(%sr1,va)
-
-	mtsp		t0, %sr1	/* Restore sr1 */
+	idtlba          pte,(va)
+	idtlbp          prot,(va)
 
 	rfir
 	nop
@@ -1359,7 +1309,7 @@ nadtlb_miss_20:
 
 	space_check	spc,t0,nadtlb_fault
 
-	L2_ptep		ptp,pte,t0,va,nadtlb_check_flush_20
+	L2_ptep		ptp,pte,t0,va,nadtlb_check_alias_20
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1372,21 +1322,14 @@ nadtlb_miss_20:
 	rfir
 	nop
 
-nadtlb_check_flush_20:
-	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-	/* Insert a "flush only" translation */
-
-	depdi,z         7,7,3,prot
-	depdi           1,10,1,prot
-
-	/* Drop prot bits from pte and convert to page addr for idtlbt */
-	convert_for_tlb_insert20 pte
+nadtlb_check_alias_20:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_emulate
 
 	idtlbt          pte,prot
 
 	rfir
 	nop
+
 #endif
 
 nadtlb_emulate:
@@ -1484,6 +1427,36 @@ itlb_miss_20w:
 	rfir
 	nop
 
+naitlb_miss_20w:
+
+	/*
+	 * I miss is a little different, since we allow users to fault
+	 * on the gateway page which is in the kernel address space.
+	 */
+
+	space_adjust	spc,va,t0
+	get_pgd		spc,ptp
+	space_check	spc,t0,naitlb_fault
+
+	L3_ptep		ptp,pte,t0,va,naitlb_check_alias_20w
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb	spc,pte,prot
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
+naitlb_check_alias_20w:
+	do_alias	spc,t0,t1,va,pte,prot,naitlb_fault
+
+	iitlbt		pte,prot
+
+	rfir
+	nop
+
 #else
 
 itlb_miss_11:
@@ -1508,6 +1481,38 @@ itlb_miss_11:
 	rfir
 	nop
 
+naitlb_miss_11:
+	get_pgd		spc,ptp
+
+	space_check	spc,t0,naitlb_fault
+
+	L2_ptep		ptp,pte,t0,va,naitlb_check_alias_11
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb_11	spc,pte,prot
+
+	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+	mtsp		spc,%sr1
+
+	iitlba		pte,(%sr1,va)
+	iitlbp		prot,(%sr1,va)
+
+	mtsp		t0, %sr1	/* Restore sr1 */
+
+	rfir
+	nop
+
+naitlb_check_alias_11:
+	do_alias	spc,t0,t1,va,pte,prot,itlb_fault
+
+	iitlba          pte,(%sr0, va)
+	iitlbp          prot,(%sr0, va)
+
+	rfir
+	nop
+
+
 itlb_miss_20:
 	get_pgd		spc,ptp
 
@@ -1526,6 +1531,32 @@ itlb_miss_20:
 	rfir
 	nop
 
+naitlb_miss_20:
+	get_pgd		spc,ptp
+
+	space_check	spc,t0,naitlb_fault
+
+	L2_ptep		ptp,pte,t0,va,naitlb_check_alias_20
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb	spc,pte,prot
+
+	f_extend	pte,t0
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
+naitlb_check_alias_20:
+	do_alias	spc,t0,t1,va,pte,prot,naitlb_fault
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
 #endif
 
 #ifdef CONFIG_64BIT
@@ -1662,6 +1693,10 @@ nadtlb_fault:
 	b               intr_save
 	ldi             17,%r8
 
+naitlb_fault:
+	b               intr_save
+	ldi             16,%r8
+
 dtlb_fault:
 	b               intr_save
 	ldi             15,%r8
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index d7d94b8..cb450e1 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -52,9 +52,9 @@ static volatile unsigned long cpu_eiem = 0;
 */
 static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
 
-static void cpu_mask_irq(unsigned int irq)
+static void cpu_mask_irq(struct irq_data *d)
 {
-	unsigned long eirr_bit = EIEM_MASK(irq);
+	unsigned long eirr_bit = EIEM_MASK(d->irq);
 
 	cpu_eiem &= ~eirr_bit;
 	/* Do nothing on the other CPUs.  If they get this interrupt,
@@ -63,7 +63,7 @@ static void cpu_mask_irq(unsigned int irq)
 	 * then gets disabled */
 }
 
-static void cpu_unmask_irq(unsigned int irq)
+static void __cpu_unmask_irq(unsigned int irq)
 {
 	unsigned long eirr_bit = EIEM_MASK(irq);
 
@@ -75,9 +75,14 @@ static void cpu_unmask_irq(unsigned int irq)
 	smp_send_all_nop();
 }
 
-void cpu_ack_irq(unsigned int irq)
+static void cpu_unmask_irq(struct irq_data *d)
+{
+	__cpu_unmask_irq(d->irq);
+}
+
+void cpu_ack_irq(struct irq_data *d)
 {
-	unsigned long mask = EIEM_MASK(irq);
+	unsigned long mask = EIEM_MASK(d->irq);
 	int cpu = smp_processor_id();
 
 	/* Clear in EIEM so we can no longer process */
@@ -90,9 +95,9 @@ void cpu_ack_irq(unsigned int irq)
 	mtctl(mask, 23);
 }
 
-void cpu_eoi_irq(unsigned int irq)
+void cpu_eoi_irq(struct irq_data *d)
 {
-	unsigned long mask = EIEM_MASK(irq);
+	unsigned long mask = EIEM_MASK(d->irq);
 	int cpu = smp_processor_id();
 
 	/* set it in the eiems---it's no longer in process */
@@ -103,15 +108,16 @@ void cpu_eoi_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_SMP
-int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
+int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest)
 {
 	int cpu_dest;
 
 	/* timer and ipi have to always be received on all CPUs */
-	if (CHECK_IRQ_PER_CPU(irq)) {
+	if (CHECK_IRQ_PER_CPU(irq_to_desc(d->irq)->status)) {
 		/* Bad linux design decision.  The mask has already
-		 * been set; we must reset it */
-		cpumask_setall(irq_desc[irq].affinity);
+		 * been set; we must reset it. Will fix - tglx
+		 */
+		cpumask_setall(d->affinity);
 		return -EINVAL;
 	}
 
@@ -121,33 +127,34 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
 	return cpu_dest;
 }
 
-static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int cpu_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
+				bool force)
 {
 	int cpu_dest;
 
-	cpu_dest = cpu_check_affinity(irq, dest);
+	cpu_dest = cpu_check_affinity(d, dest);
 	if (cpu_dest < 0)
 		return -1;
 
-	cpumask_copy(irq_desc[irq].affinity, dest);
+	cpumask_copy(d->affinity, dest);
 
 	return 0;
 }
 #endif
 
 static struct irq_chip cpu_interrupt_type = {
-	.name		= "CPU",
-	.mask		= cpu_mask_irq,
-	.unmask		= cpu_unmask_irq,
-	.ack		= cpu_ack_irq,
-	.eoi		= cpu_eoi_irq,
+	.name			= "CPU",
+	.irq_mask		= cpu_mask_irq,
+	.irq_unmask		= cpu_unmask_irq,
+	.irq_ack		= cpu_ack_irq,
+	.irq_eoi		= cpu_eoi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity	= cpu_set_affinity_irq,
+	.irq_set_affinity	= cpu_set_affinity_irq,
 #endif
 	/* XXX: Needs to be written.  We managed without it so far, but
 	 * we really ought to write it.
 	 */
-	.retrigger	= NULL,
+	.irq_retrigger	= NULL,
 };
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -181,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
 
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
 #ifndef PARISC_IRQ_CR16_COUNTS
 		seq_printf(p, "  %s", action->name);
 
@@ -233,14 +240,14 @@ int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
 	if (irq_desc[irq].action)
 		return -EBUSY;
-	if (irq_desc[irq].chip != &cpu_interrupt_type)
+	if (get_irq_chip(irq) != &cpu_interrupt_type)
 		return -EBUSY;
 
 	/* for iosapic interrupts */
 	if (type) {
 		set_irq_chip_and_handler(irq, type, handle_percpu_irq);
 		set_irq_chip_data(irq, data);
-		cpu_unmask_irq(irq);
+		__cpu_unmask_irq(irq);
 	}
 	return 0;
 }
@@ -289,7 +296,8 @@ int txn_alloc_irq(unsigned int bits_wide)
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+	struct irq_data *d = irq_get_irq_data(irq);
+	cpumask_copy(d->affinity, cpumask_of(cpu));
 #endif
 
 	return per_cpu(cpu_data, cpu).txn_addr;
@@ -333,6 +341,7 @@ void do_cpu_irq_mask(struct pt_regs *regs)
 	unsigned long eirr_val;
 	int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
+	struct irq_desc *desc;
 	cpumask_t dest;
 #endif
 
@@ -346,8 +355,9 @@ void do_cpu_irq_mask(struct pt_regs *regs)
 	irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-	cpumask_copy(&dest, irq_desc[irq].affinity);
-	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
+	desc = irq_to_desc(irq);
+	cpumask_copy(&dest, desc->irq_data.affinity);
+	if (CHECK_IRQ_PER_CPU(desc->status) &&
 	    !cpu_isset(smp_processor_id(), dest)) {
 		int cpu = first_cpu(dest);
 
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 09b77b2..a858236 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -608,93 +608,131 @@ ENTRY(__clear_user_page_asm)
 	.procend
 ENDPROC(__clear_user_page_asm)
 
-ENTRY(flush_kernel_dcache_page_asm)
+ENTRY(flush_dcache_page_asm)
 	.proc
 	.callinfo NO_CALLS
 	.entry
 
+	ldil		L%(TMPALIAS_MAP_START), %r28
+#ifdef CONFIG_64BIT
+#if (TMPALIAS_MAP_START >= 0x80000000)
+	depdi		0, 31,32, %r28		/* clear any sign extension */
+	/* FIXME: page size dependend */
+#endif
+	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
+	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
+#else
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
+#endif
+
+	/* Purge any old translation */
+
+	pdtlb		0(%r28)
+
 	ldil		L%dcache_stride, %r1
-	ldw		R%dcache_stride(%r1), %r23
+	ldw		R%dcache_stride(%r1), %r1
 
 #ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add		%r26, %r25, %r25
-	sub		%r25, %r23, %r25
-
-
-1:      fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	cmpb,COND(<<)		%r26, %r25,1b
-	fdc,m		%r23(%r26)
+	add		%r28, %r25, %r25
+	sub		%r25, %r1, %r25
+
+
+1:      fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	cmpb,COND(<<)		%r28, %r25,1b
+	fdc,m		%r1(%r28)
 
 	sync
 	bv		%r0(%r2)
-	nop
+	pdtlb		(%r25)
 	.exit
 
 	.procend
-ENDPROC(flush_kernel_dcache_page_asm)
-	
-ENTRY(flush_user_dcache_page)
+ENDPROC(flush_dcache_page_asm)
+
+ENTRY(flush_icache_page_asm)
 	.proc
 	.callinfo NO_CALLS
 	.entry
 
-	ldil		L%dcache_stride, %r1
-	ldw		R%dcache_stride(%r1), %r23
-
+	ldil		L%(TMPALIAS_MAP_START), %r28
 #ifdef CONFIG_64BIT
-	depdi,z		1,63-PAGE_SHIFT,1, %r25
+#if (TMPALIAS_MAP_START >= 0x80000000)
+	depdi		0, 31,32, %r28		/* clear any sign extension */
+	/* FIXME: page size dependend */
+#endif
+	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
+	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
 #else
-	depwi,z		1,31-PAGE_SHIFT,1, %r25
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
 #endif
-	add		%r26, %r25, %r25
-	sub		%r25, %r23, %r25
 
+	/* Purge any old translation */
 
-1:      fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	cmpb,COND(<<)		%r26, %r25,1b
-	fdc,m		%r23(%sr3, %r26)
+	pitlb		(%sr0,%r28)
+
+	ldil		L%icache_stride, %r1
+	ldw		R%icache_stride(%r1), %r1
+
+#ifdef CONFIG_64BIT
+	depdi,z		1, 63-PAGE_SHIFT,1, %r25
+#else
+	depwi,z		1, 31-PAGE_SHIFT,1, %r25
+#endif
+	add		%r28, %r25, %r25
+	sub		%r25, %r1, %r25
+
+
+1:      fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	cmpb,COND(<<)		%r28, %r25,1b
+	fic,m		%r1(%r28)
 
 	sync
 	bv		%r0(%r2)
-	nop
+	pitlb		(%sr0,%r25)
 	.exit
 
 	.procend
-ENDPROC(flush_user_dcache_page)
+ENDPROC(flush_icache_page_asm)
 
-ENTRY(flush_user_icache_page)
+ENTRY(flush_kernel_dcache_page_asm)
 	.proc
 	.callinfo NO_CALLS
 	.entry
@@ -711,23 +749,23 @@ ENTRY(flush_user_icache_page)
 	sub		%r25, %r23, %r25
 
 
-1:      fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
+1:      fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
 	cmpb,COND(<<)		%r26, %r25,1b
-	fic,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%r26)
 
 	sync
 	bv		%r0(%r2)
@@ -735,8 +773,7 @@ ENTRY(flush_user_icache_page)
 	.exit
 
 	.procend
-ENDPROC(flush_user_icache_page)
-
+ENDPROC(flush_kernel_dcache_page_asm)
 
 ENTRY(purge_kernel_dcache_page)
 	.proc
@@ -780,69 +817,6 @@ ENTRY(purge_kernel_dcache_page)
 	.procend
 ENDPROC(purge_kernel_dcache_page)
 
-#if 0
-	/* Currently not used, but it still is a possible alternate
-	 * solution.
-	 */
-
-ENTRY(flush_alias_page)
-	.proc
-	.callinfo NO_CALLS
-	.entry
-
-	tophys_r1		%r26
-
-	ldil		L%(TMPALIAS_MAP_START), %r28
-#ifdef CONFIG_64BIT
-	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
-	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
-	depdi		0, 63,12, %r28		/* Clear any offset bits */
-#else
-	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
-	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
-	depwi		0, 31,12, %r28		/* Clear any offset bits */
-#endif
-
-	/* Purge any old translation */
-
-	pdtlb		0(%r28)
-
-	ldil		L%dcache_stride, %r1
-	ldw		R%dcache_stride(%r1), %r23
-
-#ifdef CONFIG_64BIT
-	depdi,z		1, 63-PAGE_SHIFT,1, %r29
-#else
-	depwi,z		1, 31-PAGE_SHIFT,1, %r29
-#endif
-	add		%r28, %r29, %r29
-	sub		%r29, %r23, %r29
-
-1:      fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	cmpb,COND(<<)		%r28, %r29, 1b
-	fdc,m		%r23(%r28)
-
-	sync
-	bv		%r0(%r2)
-	nop
-	.exit
-
-	.procend
-#endif
 
 	.export flush_user_dcache_range_asm
 
@@ -865,7 +839,6 @@ flush_user_dcache_range_asm:
 	.exit
 
 	.procend
-ENDPROC(flush_alias_page)
 
 ENTRY(flush_kernel_dcache_range_asm)
 	.proc
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index 05511cc..45b7389 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -162,11 +162,8 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
 		update_process_times(user_mode(get_irq_regs()));
 	}
 
-	if (cpu == 0) {
-		write_seqlock(&xtime_lock);
-		do_timer(ticks_elapsed);
-		write_sequnlock(&xtime_lock);
-	}
+	if (cpu == 0)
+		xtime_update(ticks_elapsed);
 
 	return IRQ_HANDLED;
 }
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index d64a6bb..8f1e4ef 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -145,7 +145,7 @@ SECTIONS
 		EXIT_DATA
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
 	/* freed after init ends here */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 7d69e9b..71ba047 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -134,6 +134,7 @@ config PPC
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
 	select IRQ_PER_CPU
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config EARLY_PRINTK
 	bool
diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts
index 5b27a4b..2779f08 100644
--- a/arch/powerpc/boot/dts/canyonlands.dts
+++ b/arch/powerpc/boot/dts/canyonlands.dts
@@ -172,6 +172,19 @@
 			interrupts = <0x1e 4>;
 		};
 
+		USBOTG0: usbotg@bff80000 {
+			compatible = "amcc,dwc-otg";
+			reg = <0x4 0xbff80000 0x10000>;
+			interrupt-parent = <&USBOTG0>;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x1 0x2>;
+			interrupt-map = </* USB-OTG */ 0x0 &UIC2 0x1c 0x4
+					 /* HIGH-POWER */ 0x1 &UIC1 0x1a 0x8
+					 /* DMA */ 0x2 &UIC0 0xc 0x4>;
+		};
+
 		SATA0: sata@bffd1000 {
 			compatible = "amcc,sata-460ex";
 			reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
@@ -233,6 +246,11 @@
 					};
 				};
 
+				cpld@2,0 {
+					compatible = "amcc,ppc460ex-bcsr";
+					reg = <2 0x0 0x9>;
+				};
+
 				ndfc@3,0 {
 					compatible = "ibm,ndfc";
 					reg = <0x00000003 0x00000000 0x00002000>;
@@ -307,6 +325,12 @@
 				interrupts = <0x3 0x4>;
 			};
 
+			GPIO0: gpio@ef600b00 {
+				compatible = "ibm,ppc4xx-gpio";
+				reg = <0xef600b00 0x00000048>;
+				gpio-controller;
+			};
+
 			ZMII0: emac-zmii@ef600d00 {
 				compatible = "ibm,zmii-460ex", "ibm,zmii";
 				reg = <0xef600d00 0x0000000c>;
diff --git a/arch/powerpc/boot/dts/kmeter1.dts b/arch/powerpc/boot/dts/kmeter1.dts
index d8b5d12..d16bae1 100644
--- a/arch/powerpc/boot/dts/kmeter1.dts
+++ b/arch/powerpc/boot/dts/kmeter1.dts
@@ -1,7 +1,7 @@
 /*
  * Keymile KMETER1 Device Tree Source
  *
- * 2008 DENX Software Engineering GmbH
+ * 2008-2011 DENX Software Engineering GmbH
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -70,11 +70,11 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			cell-index = <0>;
-			compatible = "fsl-i2c";
+			compatible = "fsl,mpc8313-i2c","fsl-i2c";
 			reg = <0x3000 0x100>;
 			interrupts = <14 0x8>;
 			interrupt-parent = <&ipic>;
-			dfsrr;
+			clock-frequency = <400000>;
 		};
 
 		serial0: serial@4500 {
@@ -137,6 +137,13 @@
 			compatible = "fsl,mpc8360-par_io";
 			num-ports = <7>;
 
+			qe_pio_c: gpio-controller@30 {
+				#gpio-cells = <2>;
+				compatible = "fsl,mpc8360-qe-pario-bank",
+					     "fsl,mpc8323-qe-pario-bank";
+				reg = <0x1430 0x18>;
+				gpio-controller;
+			};
 			pio_ucc1: ucc_pin@0 {
 				reg = <0>;
 
@@ -472,7 +479,17 @@
 				#address-cells = <0>;
 				#interrupt-cells = <1>;
 				reg = <0x80 0x80>;
-				interrupts = <32 8 33 8>;
+				big-endian;
+				interrupts = <
+					32 0x8
+					33 0x8
+					34 0x8
+					35 0x8
+					40 0x8
+					41 0x8
+					42 0x8
+					43 0x8
+				>;
 				interrupt-parent = <&ipic>;
 			};
 		};
@@ -484,43 +501,31 @@
 		compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
 			     "simple-bus";
 		reg = <0xe0005000 0xd8>;
-		ranges = <0 0 0xf0000000 0x04000000>;	/* Filled in by U-Boot */
+		ranges = <0 0 0xf0000000 0x04000000	/* LB 0 */
+			  1 0 0xe8000000 0x01000000	/* LB 1 */
+			  3 0 0xa0000000 0x10000000>;	/* LB 3 */
 
-		flash@f0000000,0 {
+		flash@0,0 {
 			compatible = "cfi-flash";
-			/*
-			 * The Intel P30 chip has 2 non-identical chips on
-			 * one die, so we need to define 2 separate regions
-			 * that are scanned by physmap_of independantly.
-			 */
-			reg = <0 0x00000000 0x02000000
-			       0 0x02000000 0x02000000>;	/* Filled in by U-Boot */
-			bank-width = <2>;
+			reg = <0 0 0x04000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-			partition@0 {
+			bank-width = <2>;
+			partition@0 { /* 768KB */
 				label = "u-boot";
-				reg = <0 0x40000>;
+				reg = <0 0xC0000>;
 			};
-			partition@40000 {
+			partition@c0000 { /* 128KB */
 				label = "env";
-				reg = <0x40000 0x40000>;
-			};
-			partition@80000 {
-				label = "dtb";
-				reg = <0x80000 0x20000>;
-			};
-			partition@a0000 {
-				label = "kernel";
-				reg = <0xa0000 0x300000>;
+				reg = <0xC0000 0x20000>;
 			};
-			partition@3a0000 {
-				label = "ramdisk";
-				reg = <0x3a0000 0x800000>;
+			partition@e0000 { /* 128KB */
+				label = "envred";
+				reg = <0xE0000 0x20000>;
 			};
-			partition@ba0000 {
-				label = "user";
-				reg = <0xba0000 0x3460000>;
+			partition@100000 { /* 64512KB */
+				label = "ubi0";
+				reg = <0x100000 0x3F00000>;
 			};
 		};
 	};
diff --git a/arch/powerpc/boot/dts/mgcoge.dts b/arch/powerpc/boot/dts/mgcoge.dts
index 0ce9664..1360d2f 100644
--- a/arch/powerpc/boot/dts/mgcoge.dts
+++ b/arch/powerpc/boot/dts/mgcoge.dts
@@ -13,7 +13,7 @@
 /dts-v1/;
 / {
 	model = "MGCOGE";
-	compatible = "keymile,mgcoge";
+	compatible = "keymile,km82xx";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -48,8 +48,10 @@
 		reg = <0xf0010100 0x40>;
 
 		ranges = <0 0 0xfe000000 0x00400000
-			  5 0 0x50000000 0x20000000
-			>; /* Filled in by U-Boot */
+			  1 0 0x30000000 0x00010000
+			  2 0 0x40000000 0x00010000
+			  5 0 0x50000000 0x04000000
+			>;
 
 		flash@0,0 {
 			compatible = "cfi-flash";
@@ -60,36 +62,32 @@
 			device-width = <1>;
 			partition@0 {
 				label = "u-boot";
-				reg = <0 0x40000>;
+				reg = <0x00000 0xC0000>;
 			};
-			partition@40000 {
+			partition@1 {
 				label = "env";
-				reg = <0x40000 0x20000>;
+				reg = <0xC0000 0x20000>;
 			};
-			partition@60000 {
-				label = "kernel";
-				reg = <0x60000 0x220000>;
+			partition@2 {
+				label = "envred";
+				reg = <0xE0000 0x20000>;
 			};
-			partition@280000 {
-				label = "dtb";
-				reg = <0x280000 0x20000>;
+			partition@3 {
+				label = "free";
+				reg = <0x100000 0x300000>;
 			};
 		};
 
 		flash@5,0 {
 			compatible = "cfi-flash";
-			reg = <5 0x0 0x2000000>;
+			reg = <5 0x00000000 0x02000000
+			       5 0x02000000 0x02000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			bank-width = <2>;
-			device-width = <2>;
-			partition@0 {
-				label = "ramdisk";
-				reg = <0 0x7a0000>;
-			};
-			partition@7a0000 {
-				label = "user";
-				reg = <0x7a0000 0x1860000>;
+			partition@app { /* 64 MBytes */
+				label = "ubi0";
+				reg = <0x00000000 0x04000000>;
 			};
 		};
 	};
@@ -217,6 +215,13 @@
 			};
 		};
 
+		cpm2_pio_c: gpio-controller@10d40 {
+			#gpio-cells = <2>;
+			compatible = "fsl,cpm2-pario-bank";
+			reg = <0x10d40 0x14>;
+			gpio-controller;
+		};
+
 		PIC: interrupt-controller@10c00 {
 			#interrupt-cells = <2>;
 			interrupt-controller;
diff --git a/arch/powerpc/boot/dts/mgsuvd.dts b/arch/powerpc/boot/dts/mgsuvd.dts
deleted file mode 100644
index e4fc53a..0000000
--- a/arch/powerpc/boot/dts/mgsuvd.dts
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * MGSUVD Device Tree Source
- *
- * Copyright 2008 DENX Software Engineering GmbH
- * Heiko Schocher <hs@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.
- */
-
-/dts-v1/;
-/ {
-	model = "MGSUVD";
-	compatible = "keymile,mgsuvd";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		PowerPC,852@0 {
-			device_type = "cpu";
-			reg = <0>;
-			d-cache-line-size = <16>;
-			i-cache-line-size = <16>;
-			d-cache-size = <8192>;
-			i-cache-size = <8192>;
-			timebase-frequency = <0>;	/* Filled in by u-boot */
-			bus-frequency = <0>;		/* Filled in by u-boot */
-			clock-frequency = <0>;		/* Filled in by u-boot */
-			interrupts = <15 2>;		/* decrementer interrupt */
-			interrupt-parent = <&PIC>;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <00000000 0x4000000>;  /* Filled in by u-boot */
-	};
-
-	localbus@fff00100 {
-		compatible = "fsl,mpc852-localbus", "fsl,pq1-localbus", "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		reg = <0xfff00100 0x40>;
-
-		ranges = <0 0 0xf0000000 0x01000000>;  /* Filled in by u-boot */
-
-		flash@0,0 {
-			compatible = "cfi-flash";
-			reg = <0 0 0x1000000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			bank-width = <1>;
-			device-width = <1>;
-			partition@0 {
-				label = "u-boot";
-				reg = <0 0x80000>;
-			};
-			partition@80000 {
-				label = "env";
-				reg = <0x80000 0x20000>;
-			};
-			partition@a0000 {
-				label = "kernel";
-				reg = <0xa0000 0x1e0000>;
-			};
-			partition@280000 {
-				label = "dtb";
-				reg = <0x280000 0x20000>;
-			};
-			partition@2a0000 {
-			        label = "root";
-			        reg = <0x2a0000 0x500000>;
-			};
-			partition@7a0000 {
-			        label = "user";
-			        reg = <0x7a0000 0x860000>;
-			};
-		};
-	};
-
-	soc@fff00000 {
-		compatible = "fsl,mpc852", "fsl,pq1-soc", "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "soc";
-		ranges = <0 0xfff00000 0x00004000>;
-
-		PIC: interrupt-controller@0 {
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			reg = <0 24>;
-			compatible = "fsl,mpc852-pic", "fsl,pq1-pic";
-		};
-
-		cpm@9c0 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,mpc852-cpm", "fsl,cpm1", "simple-bus";
-			interrupts = <0>;	/* cpm error interrupt */
-			interrupt-parent = <&CPM_PIC>;
-			reg = <0x9c0 10>;
-			ranges;
-
-			muram@2000 {
-				compatible = "fsl,cpm-muram";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				ranges = <0 0x2000 0x2000>;
-
-				data@0 {
-					compatible = "fsl,cpm-muram-data";
-					reg = <0x800 0x1800>;
-				};
-			};
-
-			brg@9f0 {
-				compatible = "fsl,mpc852-brg",
-				             "fsl,cpm1-brg",
-				             "fsl,cpm-brg";
-				reg = <0x9f0 0x10>;
-				clock-frequency = <0>; /* Filled in by u-boot */
-			};
-
-			CPM_PIC: interrupt-controller@930 {
-				interrupt-controller;
-				#interrupt-cells = <1>;
-				interrupts = <5 2 0 2>;
-				interrupt-parent = <&PIC>;
-				reg = <0x930 0x20>;
-				compatible = "fsl,cpm1-pic";
-			};
-
-			/* MON-1 */
-			serial@a80 {
-				device_type = "serial";
-				compatible = "fsl,cpm1-smc-uart";
-				reg = <0xa80 0x10 0x3fc0 0x40>;
-				interrupts = <4>;
-				interrupt-parent = <&CPM_PIC>;
-				fsl,cpm-brg = <1>;
-				fsl,cpm-command = <0x0090>;
-				current-speed = <0>; /* Filled in by u-boot */
-			};
-
-			ethernet@a40 {
-				device_type = "network";
-				compatible  = "fsl,mpc866-scc-enet",
-				              "fsl,cpm1-scc-enet";
-				reg = <0xa40 0x18 0x3e00 0x100>;
-				local-mac-address = [ 00 00 00 00 00 00 ];  /* Filled in by u-boot */
-				interrupts = <28>;
-				interrupt-parent = <&CPM_PIC>;
-				fsl,cpm-command = <0x80>;
-				fixed-link = <0 0 10 0 0>;
-			};
-		};
-	};
-};
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts
index 69422eb..59ef405 100644
--- a/arch/powerpc/boot/dts/p1022ds.dts
+++ b/arch/powerpc/boot/dts/p1022ds.dts
@@ -475,14 +475,14 @@
 		};
 
 		sata@18000 {
-			compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
+			compatible = "fsl,p1022-sata", "fsl,pq-sata-v2";
 			reg = <0x18000 0x1000>;
 			cell-index = <1>;
 			interrupts = <74 0x2>;
 		};
 
 		sata@19000 {
-			compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
+			compatible = "fsl,p1022-sata", "fsl,pq-sata-v2";
 			reg = <0x19000 0x1000>;
 			cell-index = <2>;
 			interrupts = <41 0x2>;
diff --git a/arch/powerpc/configs/83xx/kmeter1_defconfig b/arch/powerpc/configs/83xx/kmeter1_defconfig
index 7a7b731..07e1bba 100644
--- a/arch/powerpc/configs/83xx/kmeter1_defconfig
+++ b/arch/powerpc/configs/83xx/kmeter1_defconfig
@@ -2,6 +2,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
@@ -18,7 +19,6 @@ CONFIG_KMETER1=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -37,7 +37,6 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -49,13 +48,12 @@ CONFIG_MTD_UBI=y
 CONFIG_MTD_UBI_GLUEBI=y
 CONFIG_MTD_UBI_DEBUG=y
 CONFIG_PROC_DEVICETREE=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+CONFIG_MII=y
 CONFIG_MARVELL_PHY=y
 CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
 CONFIG_UCC_GETH=y
 # CONFIG_NETDEV_10000 is not set
 CONFIG_WAN=y
@@ -77,7 +75,6 @@ CONFIG_I2C_MPC=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_UIO=y
 # CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
diff --git a/arch/powerpc/configs/mgcoge_defconfig b/arch/powerpc/configs/mgcoge_defconfig
index 39518e9..6cb588a 100644
--- a/arch/powerpc/configs/mgcoge_defconfig
+++ b/arch/powerpc/configs/mgcoge_defconfig
@@ -1,4 +1,5 @@
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -10,7 +11,6 @@ CONFIG_SLAB=y
 CONFIG_PPC_82xx=y
 CONFIG_MGCOGE=y
 CONFIG_BINFMT_MISC=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -30,7 +30,6 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_CFI=y
@@ -43,7 +42,6 @@ CONFIG_MTD_PHYSMAP_OF=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 CONFIG_FIXED_PHY=y
@@ -67,7 +65,6 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
@@ -88,13 +85,9 @@ CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BDI_SWITCH=y
-CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/configs/mgsuvd_defconfig b/arch/powerpc/configs/mgsuvd_defconfig
deleted file mode 100644
index 2a49062..0000000
--- a/arch/powerpc/configs/mgsuvd_defconfig
+++ /dev/null
@@ -1,81 +0,0 @@
-CONFIG_PPC_8xx=y
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_BUG is not set
-# CONFIG_BASE_FULL is not set
-# CONFIG_EPOLL is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PPC_MGSUVD=y
-CONFIG_8xx_COPYBACK=y
-CONFIG_8xx_CPU6=y
-CONFIG_I2C_SPI_SMC1_UCODE_PATCH=y
-CONFIG_HZ_1000=y
-CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
-# CONFIG_SECCOMP is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_SYN_COOKIES=y
-# 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_OF_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FS_ENET=y
-# CONFIG_FS_ENET_HAS_FEC is not set
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_GEN_RTC=y
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_CRC_CCITT=y
-CONFIG_DEBUG_FS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index f0a211d..be3cdf9 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -154,6 +154,7 @@ extern const char *powerpc_base_platform;
 #define CPU_FTR_NAP_DISABLE_L2_PR	ASM_CONST(0x0000000000002000)
 #define CPU_FTR_DUAL_PLL_750FX		ASM_CONST(0x0000000000004000)
 #define CPU_FTR_NO_DPM			ASM_CONST(0x0000000000008000)
+#define CPU_FTR_476_DD2			ASM_CONST(0x0000000000010000)
 #define CPU_FTR_NEED_COHERENT		ASM_CONST(0x0000000000020000)
 #define CPU_FTR_NO_BTIC			ASM_CONST(0x0000000000040000)
 #define CPU_FTR_NODSISRALIGN		ASM_CONST(0x0000000000100000)
@@ -465,7 +466,7 @@ enum {
 	    CPU_FTRS_44X | CPU_FTRS_440x6 |
 #endif
 #ifdef CONFIG_PPC_47x
-	    CPU_FTRS_47X |
+	    CPU_FTRS_47X | CPU_FTR_476_DD2 |
 #endif
 #ifdef CONFIG_E200
 	    CPU_FTRS_E200 |
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 7c589ef..c94e4a3 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -30,7 +30,7 @@
 	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 	: "cr0", "memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -40,7 +40,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -82,35 +82,38 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev;
+	int ret = 0;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
         PPC_RELEASE_BARRIER
-"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
-        cmpw    0,%0,%3\n\
+"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
+        cmpw    0,%1,%4\n\
         bne-    3f\n"
-        PPC405_ERR77(0,%2)
-"2:     stwcx.  %4,0,%2\n\
+        PPC405_ERR77(0,%3)
+"2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
         PPC_ACQUIRE_BARRIER
 "3:	.section .fixup,\"ax\"\n\
-4:	li	%0,%5\n\
+4:	li	%0,%6\n\
 	b	3b\n\
 	.previous\n\
 	.section __ex_table,\"a\"\n\
 	.align 3\n\
 	" PPC_LONG "1b,4b,2b,4b\n\
 	.previous" \
-        : "=&r" (prev), "+m" (*uaddr)
+        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
 
-        return prev;
+	*uval = prev;
+        return ret;
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index ff08b70..bb712c9 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -141,6 +141,8 @@ static inline bool arch_irqs_disabled(void)
 
 #endif /* CONFIG_PPC64 */
 
+#define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST
+
 /*
  * interrupt-retrigger: should we handle this via lost interrupts and IPIs
  * or should we not care like we do now ? --BenH.
diff --git a/arch/powerpc/include/asm/ioctls.h b/arch/powerpc/include/asm/ioctls.h
index c7dc17c..e9b7887 100644
--- a/arch/powerpc/include/asm/ioctls.h
+++ b/arch/powerpc/include/asm/ioctls.h
@@ -96,6 +96,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index e000cce..7005ee0 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -367,6 +367,10 @@ struct mpic
 #define MPIC_SINGLE_DEST_CPU		0x00001000
 /* Enable CoreInt delivery of interrupts */
 #define MPIC_ENABLE_COREINT		0x00002000
+/* Disable resetting of the MPIC.
+ * NOTE: This flag trumps MPIC_WANTS_RESET.
+ */
+#define MPIC_NO_RESET			0x00004000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK		0xf0000000
@@ -467,11 +471,11 @@ extern void mpic_request_ipis(void);
 void smp_mpic_message_pass(int target, int msg);
 
 /* Unmask a specific virq */
-extern void mpic_unmask_irq(unsigned int irq);
+extern void mpic_unmask_irq(struct irq_data *d);
 /* Mask a specific virq */
-extern void mpic_mask_irq(unsigned int irq);
+extern void mpic_mask_irq(struct irq_data *d);
 /* EOI a specific virq */
-extern void mpic_end_irq(unsigned int irq);
+extern void mpic_end_irq(struct irq_data *d);
 
 /* Fetch interrupt from a given mpic */
 extern unsigned int mpic_get_one_irq(struct mpic *mpic);
diff --git a/arch/powerpc/include/asm/nvram.h b/arch/powerpc/include/asm/nvram.h
index 92efe67..9d1aafe 100644
--- a/arch/powerpc/include/asm/nvram.h
+++ b/arch/powerpc/include/asm/nvram.h
@@ -51,7 +51,8 @@ static inline int mmio_nvram_init(void)
 extern int __init nvram_scan_partitions(void);
 extern loff_t nvram_create_partition(const char *name, int sig,
 				     int req_size, int min_size);
-extern int nvram_remove_partition(const char *name, int sig);
+extern int nvram_remove_partition(const char *name, int sig,
+					const char *exceptions[]);
 extern int nvram_get_partition_size(loff_t data_index);
 extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
 
diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index 51e9e6f..5e156e0 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -164,13 +164,23 @@ extern void setup_indirect_pci(struct pci_controller* hose,
 			       resource_size_t cfg_addr,
 			       resource_size_t cfg_data, u32 flags);
 
-#ifndef CONFIG_PPC64
-
 static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 {
 	return bus->sysdata;
 }
 
+#ifndef CONFIG_PPC64
+
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	struct pci_controller *host;
+
+	if (bus->self)
+		return pci_device_to_OF_node(bus->self);
+	host = pci_bus_to_host(bus);
+	return host ? host->dn : NULL;
+}
+
 static inline int isa_vaddr_is_ioport(void __iomem *address)
 {
 	/* No specific ISA handling on ppc32 at this stage, it
@@ -218,19 +228,10 @@ extern void * update_dn_pci_info(struct device_node *dn, void *data);
 
 /* Get a device_node from a pci_dev.  This code must be fast except
  * in the case where the sysdata is incorrect and needs to be fixed
- * up (this will only happen once).
- * In this case the sysdata will have been inherited from a PCI host
- * bridge or a PCI-PCI bridge further up the tree, so it will point
- * to a valid struct pci_dn, just not the one we want.
- */
+ * up (this will only happen once). */
 static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
 {
-	struct device_node *dn = dev->sysdata;
-	struct pci_dn *pdn = dn->data;
-
-	if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number)
-		return dn;	/* fast path.  sysdata is good */
-	return fetch_dev_dn(dev);
+	return dev->dev.of_node ? dev->dev.of_node : fetch_dev_dn(dev);
 }
 
 static inline int pci_device_from_OF_node(struct device_node *np,
@@ -248,7 +249,7 @@ static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
 	if (bus->self)
 		return pci_device_to_OF_node(bus->self);
 	else
-		return bus->sysdata; /* Must be root bus (PHB) */
+		return bus->dev.of_node; /* Must be root bus (PHB) */
 }
 
 /** Find the bus corresponding to the indicated device node */
@@ -260,14 +261,6 @@ extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 /** Discover new pci devices under this bus, and add them */
 extern void pcibios_add_pci_devices(struct pci_bus *bus);
 
-static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
-{
-	struct device_node *busdn = bus->sysdata;
-
-	BUG_ON(busdn == NULL);
-	return PCI_DN(busdn)->phb;
-}
-
 
 extern void isa_bridge_find_early(struct pci_controller *hose);
 
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index a20a9ad..7d77909 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -201,7 +201,7 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
 extern void pcibios_setup_bus_devices(struct pci_bus *bus);
 extern void pcibios_setup_bus_self(struct pci_bus *bus);
 extern void pcibios_setup_phb_io_space(struct pci_controller *hose);
-extern void pcibios_scan_phb(struct pci_controller *hose, void *sysdata);
+extern void pcibios_scan_phb(struct pci_controller *hose);
 
 #endif	/* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h
index 89f1587..88b0bd9 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -170,6 +170,7 @@ extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addre
 #define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
 				            _PAGE_COHERENT | _PAGE_WRITETHRU))
 
+#define pgprot_writecombine pgprot_noncached_wc
 
 struct file;
 extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index d727575..c189aa5 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -70,21 +70,6 @@ static inline int of_node_to_nid(struct device_node *device) { return 0; }
 #endif
 #define of_node_to_nid of_node_to_nid
 
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev:	the device whose interrupt is to be resolved
- * @out_irq:	structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-struct pci_dev;
-struct of_irq;
-extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
-
 extern void of_instantiate_rtc(void);
 
 /* These includes are put at the bottom because they may contain things
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 0175a67..48223f9 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -125,8 +125,10 @@ extern int ptrace_put_reg(struct task_struct *task, int regno,
 #endif /* ! __powerpc64__ */
 #define TRAP(regs)		((regs)->trap & ~0xF)
 #ifdef __powerpc64__
+#define NV_REG_POISON		0xdeadbeefdeadbeefUL
 #define CHECK_FULL_REGS(regs)	BUG_ON(regs->trap & 1)
 #else
+#define NV_REG_POISON		0xdeadbeef
 #define CHECK_FULL_REGS(regs)						      \
 do {									      \
 	if ((regs)->trap & 1)						      \
diff --git a/arch/powerpc/include/asm/qe_ic.h b/arch/powerpc/include/asm/qe_ic.h
index cf51966..9e2cb20 100644
--- a/arch/powerpc/include/asm/qe_ic.h
+++ b/arch/powerpc/include/asm/qe_ic.h
@@ -81,7 +81,7 @@ int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
 static inline void qe_ic_cascade_low_ipic(unsigned int irq,
 					  struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = get_irq_desc_data(desc);
 	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
 
 	if (cascade_irq != NO_IRQ)
@@ -91,7 +91,7 @@ static inline void qe_ic_cascade_low_ipic(unsigned int irq,
 static inline void qe_ic_cascade_high_ipic(unsigned int irq,
 					   struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = get_irq_desc_data(desc);
 	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
 
 	if (cascade_irq != NO_IRQ)
@@ -101,32 +101,35 @@ static inline void qe_ic_cascade_high_ipic(unsigned int irq,
 static inline void qe_ic_cascade_low_mpic(unsigned int irq,
 					  struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = get_irq_desc_data(desc);
 	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static inline void qe_ic_cascade_high_mpic(unsigned int irq,
 					   struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = get_irq_desc_data(desc);
 	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static inline void qe_ic_cascade_muxed_mpic(unsigned int irq,
 					    struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = get_irq_desc_data(desc);
 	unsigned int cascade_irq;
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 
 	cascade_irq = qe_ic_get_high_irq(qe_ic);
 	if (cascade_irq == NO_IRQ)
@@ -135,7 +138,7 @@ static inline void qe_ic_cascade_muxed_mpic(unsigned int irq,
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 #endif /* _ASM_POWERPC_QE_IC_H */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 125fc1a..7e4abeb 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -170,6 +170,16 @@
 #define SPEFSCR_FRMC 	0x00000003	/* Embedded FP rounding mode control */
 
 /* Special Purpose Registers (SPRNs)*/
+
+#ifdef CONFIG_40x
+#define SPRN_PID	0x3B1	/* Process ID */
+#else
+#define SPRN_PID	0x030	/* Process ID */
+#ifdef CONFIG_BOOKE
+#define SPRN_PID0	SPRN_PID/* Process ID Register 0 */
+#endif
+#endif
+
 #define SPRN_CTR	0x009	/* Count Register */
 #define SPRN_DSCR	0x11
 #define SPRN_CTRLF	0x088
@@ -852,6 +862,8 @@
 #define PVR_7450	0x80000000
 #define PVR_8540	0x80200000
 #define PVR_8560	0x80200000
+#define PVR_VER_E500V1	0x8020
+#define PVR_VER_E500V2	0x8021
 /*
  * For the 8xx processors, all of them report the same PVR family for
  * the PowerPC core. The various versions of these processors must be
@@ -880,6 +892,7 @@
 #define PV_970		0x0039
 #define PV_POWER5	0x003A
 #define PV_POWER5p	0x003B
+#define PV_POWER7	0x003F
 #define PV_970FX	0x003C
 #define PV_630		0x0040
 #define PV_630p	0x0041
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index e68c69b..86ad812 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -150,8 +150,6 @@
  * or IBM 40x.
  */
 #ifdef CONFIG_BOOKE
-#define SPRN_PID	0x030	/* Process ID */
-#define SPRN_PID0	SPRN_PID/* Process ID Register 0 */
 #define SPRN_CSRR0	0x03A	/* Critical Save and Restore Register 0 */
 #define SPRN_CSRR1	0x03B	/* Critical Save and Restore Register 1 */
 #define SPRN_DEAR	0x03D	/* Data Error Address Register */
@@ -168,7 +166,6 @@
 #define SPRN_TCR	0x154	/* Timer Control Register */
 #endif /* Book E */
 #ifdef CONFIG_40x
-#define SPRN_PID	0x3B1	/* Process ID */
 #define SPRN_DBCR1	0x3BD	/* Debug Control Register 1 */		
 #define SPRN_ESR	0x3D4	/* Exception Syndrome Register */
 #define SPRN_DEAR	0x3D5	/* Data Error Address Register */
diff --git a/arch/powerpc/include/asm/rwsem.h b/arch/powerpc/include/asm/rwsem.h
index 8447d89..bb1e2cd 100644
--- a/arch/powerpc/include/asm/rwsem.h
+++ b/arch/powerpc/include/asm/rwsem.h
@@ -13,11 +13,6 @@
  * by Paul Mackerras <paulus@samba.org>.
  */
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
 /*
  * the semaphore definition
  */
@@ -33,47 +28,6 @@
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
-struct rw_semaphore {
-	long			count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name)				\
-{								\
-	RWSEM_UNLOCKED_VALUE,					\
-	__SPIN_LOCK_UNLOCKED((name).wait_lock),			\
-	LIST_HEAD_INIT((name).wait_list)			\
-	__RWSEM_DEP_MAP_INIT(name)				\
-}
-
-#define DECLARE_RWSEM(name)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)					\
-	do {						\
-		static struct lock_class_key __key;	\
-							\
-		__init_rwsem((sem), #sem, &__key);	\
-	} while (0)
-
 /*
  * lock for reading
  */
@@ -174,10 +128,5 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 	return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return sem->count != 0;
-}
-
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_RWSEM_H */
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 65eb859..d8529ef 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -72,7 +72,7 @@ struct thread_info {
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
 extern void free_thread_info(struct thread_info *ti);
 
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
diff --git a/arch/powerpc/include/asm/types.h b/arch/powerpc/include/asm/types.h
index a5aea0c..e16a6b2 100644
--- a/arch/powerpc/include/asm/types.h
+++ b/arch/powerpc/include/asm/types.h
@@ -44,11 +44,6 @@ typedef struct {
 
 typedef __vector128 vector128;
 
-#if defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT)
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
 typedef u64 dma64_addr_t;
 
 typedef struct {
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index e8e915c..c9b68d0 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1811,11 +1811,11 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.machine_check		= machine_check_440A,
 		.platform		= "ppc440",
 	},
-	{ /* 476 core */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x11a50000,
+	{ /* 476 DD2 core */
+		.pvr_mask		= 0xffffffff,
+		.pvr_value		= 0x11a52080,
 		.cpu_name		= "476",
-		.cpu_features		= CPU_FTRS_47X,
+		.cpu_features		= CPU_FTRS_47X | CPU_FTR_476_DD2,
 		.cpu_user_features	= COMMON_USER_BOOKE |
 			PPC_FEATURE_HAS_FPU,
 		.mmu_features		= MMU_FTR_TYPE_47x |
@@ -1839,6 +1839,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
 		.machine_check		= machine_check_47x,
 		.platform		= "ppc470",
 	},
+	{ /* 476 others */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x11a50000,
+		.cpu_name		= "476",
+		.cpu_features		= CPU_FTRS_47X,
+		.cpu_user_features	= COMMON_USER_BOOKE |
+			PPC_FEATURE_HAS_FPU,
+		.mmu_features		= MMU_FTR_TYPE_47x |
+			MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 128,
+		.machine_check		= machine_check_47x,
+		.platform		= "ppc470",
+	},
 	{	/* default match */
 		.pvr_mask		= 0x00000000,
 		.pvr_value		= 0x00000000,
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index f62efdf..c00d4ca 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -201,13 +201,14 @@ int ibmebus_register_driver(struct of_platform_driver *drv)
 	/* If the driver uses devices that ibmebus doesn't know, add them */
 	ibmebus_create_devices(drv->driver.of_match_table);
 
-	return of_register_driver(drv, &ibmebus_bus_type);
+	drv->driver.bus = &ibmebus_bus_type;
+	return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
 void ibmebus_unregister_driver(struct of_platform_driver *drv)
 {
-	of_unregister_driver(drv);
+	driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
@@ -308,15 +309,410 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
 	}
 }
 
+
 static struct bus_attribute ibmebus_bus_attrs[] = {
 	__ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
 	__ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
 	__ATTR_NULL
 };
 
+static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
+{
+	const struct of_device_id *matches = drv->of_match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, dev) != NULL;
+}
+
+static int ibmebus_bus_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct platform_device *of_dev;
+	const struct of_device_id *match;
+
+	drv = to_of_platform_driver(dev->driver);
+	of_dev = to_platform_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	match = of_match_device(drv->driver.of_match_table, dev);
+	if (match)
+		error = drv->probe(of_dev, match);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int ibmebus_bus_device_remove(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static void ibmebus_bus_device_shutdown(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->shutdown)
+		drv->shutdown(of_dev);
+}
+
+/*
+ * ibmebus_bus_device_attrs
+ */
+static ssize_t devspec_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *ofdev;
+
+	ofdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
+}
+
+static ssize_t name_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *ofdev;
+
+	ofdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
+}
+
+static ssize_t modalias_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
+	buf[len] = '\n';
+	buf[len+1] = 0;
+	return len+1;
+}
+
+struct device_attribute ibmebus_bus_device_attrs[] = {
+	__ATTR_RO(devspec),
+	__ATTR_RO(name),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int ibmebus_bus_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+	int ret = 0;
+
+	if (dev->driver && drv->suspend)
+		ret = drv->suspend(of_dev, mesg);
+	return ret;
+}
+
+static int ibmebus_bus_legacy_resume(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+	int ret = 0;
+
+	if (dev->driver && drv->resume)
+		ret = drv->resume(of_dev);
+	return ret;
+}
+
+static int ibmebus_bus_pm_prepare(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (drv && drv->pm && drv->pm->prepare)
+		ret = drv->pm->prepare(dev);
+
+	return ret;
+}
+
+static void ibmebus_bus_pm_complete(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+
+	if (drv && drv->pm && drv->pm->complete)
+		drv->pm->complete(dev);
+}
+
+#ifdef CONFIG_SUSPEND
+
+static int ibmebus_bus_pm_suspend(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend)
+			ret = drv->pm->suspend(dev);
+	} else {
+		ret = ibmebus_bus_legacy_suspend(dev, PMSG_SUSPEND);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_suspend_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend_noirq)
+			ret = drv->pm->suspend_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_resume(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume)
+			ret = drv->pm->resume(dev);
+	} else {
+		ret = ibmebus_bus_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_resume_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume_noirq)
+			ret = drv->pm->resume_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_SUSPEND */
+
+#define ibmebus_bus_pm_suspend		NULL
+#define ibmebus_bus_pm_resume		NULL
+#define ibmebus_bus_pm_suspend_noirq	NULL
+#define ibmebus_bus_pm_resume_noirq	NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATION
+
+static int ibmebus_bus_pm_freeze(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze)
+			ret = drv->pm->freeze(dev);
+	} else {
+		ret = ibmebus_bus_legacy_suspend(dev, PMSG_FREEZE);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_freeze_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze_noirq)
+			ret = drv->pm->freeze_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_thaw(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw)
+			ret = drv->pm->thaw(dev);
+	} else {
+		ret = ibmebus_bus_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_thaw_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw_noirq)
+			ret = drv->pm->thaw_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_poweroff(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff)
+			ret = drv->pm->poweroff(dev);
+	} else {
+		ret = ibmebus_bus_legacy_suspend(dev, PMSG_HIBERNATE);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_poweroff_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff_noirq)
+			ret = drv->pm->poweroff_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_restore(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore)
+			ret = drv->pm->restore(dev);
+	} else {
+		ret = ibmebus_bus_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_restore_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore_noirq)
+			ret = drv->pm->restore_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_HIBERNATION */
+
+#define ibmebus_bus_pm_freeze		NULL
+#define ibmebus_bus_pm_thaw		NULL
+#define ibmebus_bus_pm_poweroff		NULL
+#define ibmebus_bus_pm_restore		NULL
+#define ibmebus_bus_pm_freeze_noirq	NULL
+#define ibmebus_bus_pm_thaw_noirq		NULL
+#define ibmebus_bus_pm_poweroff_noirq	NULL
+#define ibmebus_bus_pm_restore_noirq	NULL
+
+#endif /* !CONFIG_HIBERNATION */
+
+static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
+	.prepare = ibmebus_bus_pm_prepare,
+	.complete = ibmebus_bus_pm_complete,
+	.suspend = ibmebus_bus_pm_suspend,
+	.resume = ibmebus_bus_pm_resume,
+	.freeze = ibmebus_bus_pm_freeze,
+	.thaw = ibmebus_bus_pm_thaw,
+	.poweroff = ibmebus_bus_pm_poweroff,
+	.restore = ibmebus_bus_pm_restore,
+	.suspend_noirq = ibmebus_bus_pm_suspend_noirq,
+	.resume_noirq = ibmebus_bus_pm_resume_noirq,
+	.freeze_noirq = ibmebus_bus_pm_freeze_noirq,
+	.thaw_noirq = ibmebus_bus_pm_thaw_noirq,
+	.poweroff_noirq = ibmebus_bus_pm_poweroff_noirq,
+	.restore_noirq = ibmebus_bus_pm_restore_noirq,
+};
+
+#define IBMEBUS_BUS_PM_OPS_PTR	(&ibmebus_bus_dev_pm_ops)
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define IBMEBUS_BUS_PM_OPS_PTR	NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
 struct bus_type ibmebus_bus_type = {
+	.name      = "ibmebus",
 	.uevent    = of_device_uevent,
-	.bus_attrs = ibmebus_bus_attrs
+	.bus_attrs = ibmebus_bus_attrs,
+	.match     = ibmebus_bus_bus_match,
+	.probe     = ibmebus_bus_device_probe,
+	.remove    = ibmebus_bus_device_remove,
+	.shutdown  = ibmebus_bus_device_shutdown,
+	.dev_attrs = ibmebus_bus_device_attrs,
+	.pm        = IBMEBUS_BUS_PM_OPS_PTR,
 };
 EXPORT_SYMBOL(ibmebus_bus_type);
 
@@ -326,7 +722,7 @@ static int __init ibmebus_bus_init(void)
 
 	printk(KERN_INFO "IBM eBus Device Driver\n");
 
-	err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
+	err = bus_register(&ibmebus_bus_type);
 	if (err) {
 		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
 		       __func__);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index ce557f6..0a557033 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -237,6 +237,7 @@ int show_interrupts(struct seq_file *p, void *v)
 	int i = *(loff_t *) v, j, prec;
 	struct irqaction *action;
 	struct irq_desc *desc;
+	struct irq_chip *chip;
 
 	if (i > nr_irqs)
 		return 0;
@@ -270,8 +271,9 @@ int show_interrupts(struct seq_file *p, void *v)
 	for_each_online_cpu(j)
 		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 
-	if (desc->chip)
-		seq_printf(p, "  %-16s", desc->chip->name);
+	chip = get_irq_desc_chip(desc);
+	if (chip)
+		seq_printf(p, "  %-16s", chip->name);
 	else
 		seq_printf(p, "  %-16s", "None");
 	seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge");
@@ -313,6 +315,8 @@ void fixup_irqs(const struct cpumask *map)
 	alloc_cpumask_var(&mask, GFP_KERNEL);
 
 	for_each_irq(irq) {
+		struct irq_chip *chip;
+
 		desc = irq_to_desc(irq);
 		if (!desc)
 			continue;
@@ -320,13 +324,15 @@ void fixup_irqs(const struct cpumask *map)
 		if (desc->status & IRQ_PER_CPU)
 			continue;
 
-		cpumask_and(mask, desc->affinity, map);
+		chip = get_irq_desc_chip(desc);
+
+		cpumask_and(mask, desc->irq_data.affinity, map);
 		if (cpumask_any(mask) >= nr_cpu_ids) {
 			printk("Breaking affinity for irq %i\n", irq);
 			cpumask_copy(mask, map);
 		}
-		if (desc->chip->set_affinity)
-			desc->chip->set_affinity(irq, mask);
+		if (chip->irq_set_affinity)
+			chip->irq_set_affinity(&desc->irq_data, mask, true);
 		else if (desc->action && !(warned++))
 			printk("Cannot set affinity for irq %i\n", irq);
 	}
@@ -678,16 +684,15 @@ void irq_set_virq_count(unsigned int count)
 static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 			    irq_hw_number_t hwirq)
 {
-	struct irq_desc *desc;
+	int res;
 
-	desc = irq_to_desc_alloc_node(virq, 0);
-	if (!desc) {
+	res = irq_alloc_desc_at(virq, 0);
+	if (res != virq) {
 		pr_debug("irq: -> allocating desc failed\n");
 		goto error;
 	}
 
-	/* Clear IRQ_NOREQUEST flag */
-	desc->status &= ~IRQ_NOREQUEST;
+	irq_clear_status_flags(virq, IRQ_NOREQUEST);
 
 	/* map it */
 	smp_wmb();
@@ -696,11 +701,13 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 
 	if (host->ops->map(host, virq, hwirq)) {
 		pr_debug("irq: -> mapping failed, freeing\n");
-		goto error;
+		goto errdesc;
 	}
 
 	return 0;
 
+errdesc:
+	irq_free_descs(virq, 1);
 error:
 	irq_free_virt(virq, 1);
 	return -1;
@@ -879,9 +886,9 @@ void irq_dispose_mapping(unsigned int virq)
 	smp_mb();
 	irq_map[virq].hwirq = host->inval_irq;
 
-	/* Set some flags */
-	irq_to_desc(virq)->status |= IRQ_NOREQUEST;
+	irq_set_status_flags(virq, IRQ_NOREQUEST);
 
+	irq_free_descs(virq, 1);
 	/* Free it */
 	irq_free_virt(virq, 1);
 }
@@ -1074,21 +1081,6 @@ void irq_free_virt(unsigned int virq, unsigned int count)
 
 int arch_early_irq_init(void)
 {
-	struct irq_desc *desc;
-	int i;
-
-	for (i = 0; i < NR_IRQS; i++) {
-		desc = irq_to_desc(i);
-		if (desc)
-			desc->status |= IRQ_NOREQUEST;
-	}
-
-	return 0;
-}
-
-int arch_init_chip_data(struct irq_desc *desc, int node)
-{
-	desc->status |= IRQ_NOREQUEST;
 	return 0;
 }
 
@@ -1159,11 +1151,14 @@ static int virq_debug_show(struct seq_file *m, void *private)
 		raw_spin_lock_irqsave(&desc->lock, flags);
 
 		if (desc->action && desc->action->handler) {
+			struct irq_chip *chip;
+
 			seq_printf(m, "%5d  ", i);
 			seq_printf(m, "0x%05lx  ", virq_to_hw(i));
 
-			if (desc->chip && desc->chip->name)
-				p = desc->chip->name;
+			chip = get_irq_desc_chip(desc);
+			if (chip && chip->name)
+				p = chip->name;
 			else
 				p = none;
 			seq_printf(m, "%-15s  ", p);
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index a5f8672..bd1e1ff 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -26,20 +26,23 @@ void machine_kexec_mask_interrupts(void) {
 
 	for_each_irq(i) {
 		struct irq_desc *desc = irq_to_desc(i);
+		struct irq_chip *chip;
 
-		if (!desc || !desc->chip)
+		if (!desc)
 			continue;
 
-		if (desc->chip->eoi &&
-		    desc->status & IRQ_INPROGRESS)
-			desc->chip->eoi(i);
+		chip = get_irq_desc_chip(desc);
+		if (!chip)
+			continue;
+
+		if (chip->irq_eoi && desc->status & IRQ_INPROGRESS)
+			chip->irq_eoi(&desc->irq_data);
 
-		if (desc->chip->mask)
-			desc->chip->mask(i);
+		if (chip->irq_mask)
+			chip->irq_mask(&desc->irq_data);
 
-		if (desc->chip->disable &&
-		    !(desc->status & IRQ_DISABLED))
-			desc->chip->disable(i);
+		if (chip->irq_disable && !(desc->status & IRQ_DISABLED))
+			chip->irq_disable(&desc->irq_data);
 	}
 }
 
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index bb12b32..bec1e93 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -237,22 +237,45 @@ static unsigned char __init nvram_checksum(struct nvram_header *p)
 	return c_sum;
 }
 
+/*
+ * Per the criteria passed via nvram_remove_partition(), should this
+ * partition be removed?  1=remove, 0=keep
+ */
+static int nvram_can_remove_partition(struct nvram_partition *part,
+		const char *name, int sig, const char *exceptions[])
+{
+	if (part->header.signature != sig)
+		return 0;
+	if (name) {
+		if (strncmp(name, part->header.name, 12))
+			return 0;
+	} else if (exceptions) {
+		const char **except;
+		for (except = exceptions; *except; except++) {
+			if (!strncmp(*except, part->header.name, 12))
+				return 0;
+		}
+	}
+	return 1;
+}
+
 /**
  * nvram_remove_partition - Remove one or more partitions in nvram
  * @name: name of the partition to remove, or NULL for a
  *        signature only match
  * @sig: signature of the partition(s) to remove
+ * @exceptions: When removing all partitions with a matching signature,
+ *        leave these alone.
  */
 
-int __init nvram_remove_partition(const char *name, int sig)
+int __init nvram_remove_partition(const char *name, int sig,
+						const char *exceptions[])
 {
 	struct nvram_partition *part, *prev, *tmp;
 	int rc;
 
 	list_for_each_entry(part, &nvram_partitions, partition) {
-		if (part->header.signature != sig)
-			continue;
-		if (name && strncmp(name, part->header.name, 12))
+		if (!nvram_can_remove_partition(part, name, sig, exceptions))
 			continue;
 
 		/* Make partition a free partition */
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index b2c363e..2458218 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -36,8 +36,7 @@
  * lacking some bits needed here.
  */
 
-static int __devinit of_pci_phb_probe(struct platform_device *dev,
-				      const struct of_device_id *match)
+static int __devinit of_pci_phb_probe(struct platform_device *dev)
 {
 	struct pci_controller *phb;
 
@@ -74,7 +73,7 @@ static int __devinit of_pci_phb_probe(struct platform_device *dev,
 #endif /* CONFIG_EEH */
 
 	/* Scan the bus */
-	pcibios_scan_phb(phb, dev->dev.of_node);
+	pcibios_scan_phb(phb);
 	if (phb->bus == NULL)
 		return -ENXIO;
 
@@ -104,7 +103,7 @@ static struct of_device_id of_pci_phb_ids[] = {
 	{}
 };
 
-static struct of_platform_driver of_pci_phb_driver = {
+static struct platform_driver of_pci_phb_driver = {
 	.probe = of_pci_phb_probe,
 	.driver = {
 		.name = "of-pci",
@@ -115,7 +114,7 @@ static struct of_platform_driver of_pci_phb_driver = {
 
 static __init int of_pci_phb_init(void)
 {
-	return of_register_platform_driver(&of_pci_phb_driver);
+	return platform_driver_register(&of_pci_phb_driver);
 }
 
 device_initcall(of_pci_phb_init);
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 10a44e6..3cd85fa 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/of_address.h>
+#include <linux/of_pci.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/syscalls.h>
@@ -1687,13 +1688,8 @@ int early_find_capability(struct pci_controller *hose, int bus, int devfn,
 /**
  * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
  * @hose: Pointer to the PCI host controller instance structure
- * @sysdata: value to use for sysdata pointer.  ppc32 and ppc64 differ here
- *
- * Note: the 'data' pointer is a temporary measure.  As 32 and 64 bit
- * pci code gets merged, this parameter should become unnecessary because
- * both will use the same value.
  */
-void __devinit pcibios_scan_phb(struct pci_controller *hose, void *sysdata)
+void __devinit pcibios_scan_phb(struct pci_controller *hose)
 {
 	struct pci_bus *bus;
 	struct device_node *node = hose->dn;
@@ -1703,13 +1699,13 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose, void *sysdata)
 		 node ? node->full_name : "<NO NAME>");
 
 	/* Create an empty bus for the toplevel */
-	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops,
-			     sysdata);
+	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
 	if (bus == NULL) {
 		pr_err("Failed to create bus for PCI domain %04x\n",
 			hose->global_number);
 		return;
 	}
+	bus->dev.of_node = of_node_get(node);
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index e7db5b4..bedb370 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -381,7 +381,7 @@ static int __init pcibios_init(void)
 		if (pci_assign_all_buses)
 			hose->first_busno = next_busno;
 		hose->last_busno = 0xff;
-		pcibios_scan_phb(hose, hose);
+		pcibios_scan_phb(hose);
 		pci_bus_add_devices(hose->bus);
 		if (pci_assign_all_buses || next_busno <= hose->last_busno)
 			next_busno = hose->last_busno + pcibios_assign_bus_offset;
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 8515776..fc6452b 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -64,7 +64,7 @@ static int __init pcibios_init(void)
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		pcibios_scan_phb(hose, hose->dn);
+		pcibios_scan_phb(hose);
 		pci_bus_add_devices(hose->bus);
 	}
 
@@ -242,10 +242,10 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
 			break;
 		bus = NULL;
 	}
-	if (bus == NULL || bus->sysdata == NULL)
+	if (bus == NULL || bus->dev.of_node == NULL)
 		return -ENODEV;
 
-	hose_node = (struct device_node *)bus->sysdata;
+	hose_node = bus->dev.of_node;
 	hose = PCI_DN(hose_node)->phb;
 
 	switch (which) {
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index d56b35e..d225d99 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -161,7 +161,7 @@ static void *is_devfn_node(struct device_node *dn, void *data)
 /*
  * This is the "slow" path for looking up a device_node from a
  * pci_dev.  It will hunt for the device under its parent's
- * phb and then update sysdata for a future fastpath.
+ * phb and then update of_node pointer.
  *
  * It may also do fixups on the actual device since this happens
  * on the first read/write.
@@ -170,16 +170,22 @@ static void *is_devfn_node(struct device_node *dn, void *data)
  * In this case it may probe for real hardware ("just in case")
  * and add a device_node to the device tree if necessary.
  *
+ * Is this function necessary anymore now that dev->dev.of_node is
+ * used to store the node pointer?
+ *
  */
 struct device_node *fetch_dev_dn(struct pci_dev *dev)
 {
-	struct device_node *orig_dn = dev->sysdata;
+	struct pci_controller *phb = dev->sysdata;
 	struct device_node *dn;
 	unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
 
-	dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
+	if (WARN_ON(!phb))
+		return NULL;
+
+	dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval);
 	if (dn)
-		dev->sysdata = dn;
+		dev->dev.of_node = dn;
 	return dn;
 }
 EXPORT_SYMBOL(fetch_dev_dn);
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index e751506..1e89a72 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -135,7 +135,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
 	pr_debug("    create device, devfn: %x, type: %s\n", devfn, type);
 
 	dev->bus = bus;
-	dev->sysdata = node;
+	dev->dev.of_node = of_node_get(node);
 	dev->dev.parent = bus->bridge;
 	dev->dev.bus = &pci_bus_type;
 	dev->devfn = devfn;
@@ -238,7 +238,7 @@ void __devinit of_scan_pci_bridge(struct device_node *node,
 	bus->primary = dev->bus->number;
 	bus->subordinate = busrange[1];
 	bus->bridge_ctl = 0;
-	bus->sysdata = node;
+	bus->dev.of_node = of_node_get(node);
 
 	/* parse ranges property */
 	/* PCI #address-cells == 3 and #size-cells == 2 always */
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index ab6f6be..97e0ae4 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1269,6 +1269,28 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
 	return ip;
 }
 
+static bool pmc_overflow(unsigned long val)
+{
+	if ((int)val < 0)
+		return true;
+
+	/*
+	 * Events on POWER7 can roll back if a speculative event doesn't
+	 * eventually complete. Unfortunately in some rare cases they will
+	 * raise a performance monitor exception. We need to catch this to
+	 * ensure we reset the PMC. In all cases the PMC will be 256 or less
+	 * cycles from overflow.
+	 *
+	 * We only do this if the first pass fails to find any overflowing
+	 * PMCs because a user might set a period of less than 256 and we
+	 * don't want to mistakenly reset them.
+	 */
+	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+		return true;
+
+	return false;
+}
+
 /*
  * Performance monitor interrupt stuff
  */
@@ -1316,7 +1338,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
 			if (is_limited_pmc(i + 1))
 				continue;
 			val = read_pmc(i + 1);
-			if ((int)val < 0)
+			if (pmc_overflow(val))
 				write_pmc(i + 1, 0);
 		}
 	}
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 8303a6c..f74f355 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1218,11 +1218,11 @@ void __ppc64_runlatch_off(void)
 
 static struct kmem_cache *thread_info_cache;
 
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
 {
 	struct thread_info *ti;
 
-	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
+	ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
 	if (unlikely(ti == NULL))
 		return NULL;
 #ifdef CONFIG_DEBUG_STACK_USAGE
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 7185f0d..05b7139 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -97,7 +97,7 @@ static void __init move_device_tree(void)
 	start = __pa(initial_boot_params);
 	size = be32_to_cpu(initial_boot_params->totalsize);
 
-	if ((memory_limit && (start + size) > memory_limit) ||
+	if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
 			overlaps_crashkernel(start, size)) {
 		p = __va(memblock_alloc(size, PAGE_SIZE));
 		memcpy(p, initial_boot_params, size);
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index c2b7a07..47187cc 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -2,95 +2,11 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/pci_regs.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	u32 lspec;
-	u32 laddr[3];
-	u8 pin;
-	int rc;
-
-	/* Check if we have a device node, if yes, fallback to standard OF
-	 * parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn) {
-		rc = of_irq_map_one(dn, 0, out_irq);
-		if (!rc)
-			return rc;
-	}
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		return rc;
-	/* No pin, exit */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	lspec = pin;
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
-			ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
-			struct pci_controller *host;
-			host = pci_bus_to_host(pdev->bus);
-			ppnode = host ? host->dn : NULL;
-#endif
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL)
-				return -EINVAL;
-		} else
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't include
-		 * the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
-
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
-		 */
-		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
-		pdev = ppdev;
-	}
-
-	laddr[0] = (pdev->bus->number << 16)
-		| (pdev->devfn << 8);
-	laddr[1]  = laddr[2] = 0;
-	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
 
 void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
 		unsigned long *busno, unsigned long *phys, unsigned long *size)
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 9065369..895b082 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -229,12 +229,16 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset,
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
 {
-	int ret;
+	int i, ret;
 
 	if (target->thread.regs == NULL)
 		return -EIO;
 
-	CHECK_FULL_REGS(target->thread.regs);
+	if (!FULL_REGS(target->thread.regs)) {
+		/* We have a partial register set.  Fill 14-31 with bogus values */
+		for (i = 14; i < 32; i++)
+			target->thread.regs->gpr[i] = NV_REG_POISON;
+	}
 
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				  target->thread.regs,
@@ -641,11 +645,16 @@ static int gpr32_get(struct task_struct *target,
 	compat_ulong_t *k = kbuf;
 	compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
+	int i;
 
 	if (target->thread.regs == NULL)
 		return -EIO;
 
-	CHECK_FULL_REGS(target->thread.regs);
+	if (!FULL_REGS(target->thread.regs)) {
+		/* We have a partial register set.  Fill 14-31 with bogus values */
+		for (i = 14; i < 32; i++)
+			target->thread.regs->gpr[i] = NV_REG_POISON; 
+	}
 
 	pos /= sizeof(reg);
 	count /= sizeof(reg);
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 049dbec..7980ec0 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -412,7 +412,8 @@ static void rtas_event_scan(struct work_struct *w)
 
 	get_online_cpus();
 
-	cpu = cpumask_next(smp_processor_id(), cpu_online_mask);
+	/* raw_ OK because just using CPU as starting point. */
+	cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
         if (cpu >= nr_cpu_ids) {
 		cpu = cpumask_first(cpu_online_mask);
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8a0deef..b9150f0 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -160,7 +160,7 @@ SECTIONS
 		INIT_RAM_FS
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 
 	. = ALIGN(8);
 	.machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) {
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index badc983..c961de4 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -1141,9 +1141,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	regs->sprg1 = vcpu->arch.shared->sprg1;
 	regs->sprg2 = vcpu->arch.shared->sprg2;
 	regs->sprg3 = vcpu->arch.shared->sprg3;
-	regs->sprg5 = vcpu->arch.sprg4;
-	regs->sprg6 = vcpu->arch.sprg5;
-	regs->sprg7 = vcpu->arch.sprg6;
+	regs->sprg4 = vcpu->arch.sprg4;
+	regs->sprg5 = vcpu->arch.sprg5;
+	regs->sprg6 = vcpu->arch.sprg6;
+	regs->sprg7 = vcpu->arch.sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -1167,9 +1168,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	vcpu->arch.shared->sprg1 = regs->sprg1;
 	vcpu->arch.shared->sprg2 = regs->sprg2;
 	vcpu->arch.shared->sprg3 = regs->sprg3;
-	vcpu->arch.sprg5 = regs->sprg4;
-	vcpu->arch.sprg6 = regs->sprg5;
-	vcpu->arch.sprg7 = regs->sprg6;
+	vcpu->arch.sprg4 = regs->sprg4;
+	vcpu->arch.sprg5 = regs->sprg5;
+	vcpu->arch.sprg6 = regs->sprg6;
+	vcpu->arch.sprg7 = regs->sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 77575d0..ef76acb 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -546,9 +546,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	regs->sprg1 = vcpu->arch.shared->sprg1;
 	regs->sprg2 = vcpu->arch.shared->sprg2;
 	regs->sprg3 = vcpu->arch.shared->sprg3;
-	regs->sprg5 = vcpu->arch.sprg4;
-	regs->sprg6 = vcpu->arch.sprg5;
-	regs->sprg7 = vcpu->arch.sprg6;
+	regs->sprg4 = vcpu->arch.sprg4;
+	regs->sprg5 = vcpu->arch.sprg5;
+	regs->sprg6 = vcpu->arch.sprg6;
+	regs->sprg7 = vcpu->arch.sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -572,9 +573,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	vcpu->arch.shared->sprg1 = regs->sprg1;
 	vcpu->arch.shared->sprg2 = regs->sprg2;
 	vcpu->arch.shared->sprg3 = regs->sprg3;
-	vcpu->arch.sprg5 = regs->sprg4;
-	vcpu->arch.sprg6 = regs->sprg5;
-	vcpu->arch.sprg7 = regs->sprg6;
+	vcpu->arch.sprg4 = regs->sprg4;
+	vcpu->arch.sprg5 = regs->sprg5;
+	vcpu->arch.sprg6 = regs->sprg6;
+	vcpu->arch.sprg7 = regs->sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
diff --git a/arch/powerpc/math-emu/math_efp.c b/arch/powerpc/math-emu/math_efp.c
index 41f4ef3..6227920 100644
--- a/arch/powerpc/math-emu/math_efp.c
+++ b/arch/powerpc/math-emu/math_efp.c
@@ -1,7 +1,7 @@
 /*
  * arch/powerpc/math-emu/math_efp.c
  *
- * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
  *
  * Author: Ebony Zhu,	<ebony.zhu@freescale.com>
  *         Yu Liu,	<yu.liu@freescale.com>
@@ -104,6 +104,8 @@
 #define FP_EX_MASK	(FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
 			FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
 
+static int have_e500_cpu_a005_erratum;
+
 union dw_union {
 	u64 dp[1];
 	u32 wp[2];
@@ -320,7 +322,8 @@ int do_spe_mathemu(struct pt_regs *regs)
 			} else {
 				_FP_ROUND_ZERO(1, SB);
 			}
-			FP_TO_INT_S(vc.wp[1], SB, 32, ((func & 0x3) != 0));
+			FP_TO_INT_S(vc.wp[1], SB, 32,
+					(((func & 0x3) != 0) || SB_s));
 			goto update_regs;
 
 		default:
@@ -458,7 +461,8 @@ cmp_s:
 			} else {
 				_FP_ROUND_ZERO(2, DB);
 			}
-			FP_TO_INT_D(vc.wp[1], DB, 32, ((func & 0x3) != 0));
+			FP_TO_INT_D(vc.wp[1], DB, 32,
+					(((func & 0x3) != 0) || DB_s));
 			goto update_regs;
 
 		default:
@@ -589,8 +593,10 @@ cmp_d:
 				_FP_ROUND_ZERO(1, SB0);
 				_FP_ROUND_ZERO(1, SB1);
 			}
-			FP_TO_INT_S(vc.wp[0], SB0, 32, ((func & 0x3) != 0));
-			FP_TO_INT_S(vc.wp[1], SB1, 32, ((func & 0x3) != 0));
+			FP_TO_INT_S(vc.wp[0], SB0, 32,
+					(((func & 0x3) != 0) || SB0_s));
+			FP_TO_INT_S(vc.wp[1], SB1, 32,
+					(((func & 0x3) != 0) || SB1_s));
 			goto update_regs;
 
 		default:
@@ -652,6 +658,15 @@ update_regs:
 	return 0;
 
 illegal:
+	if (have_e500_cpu_a005_erratum) {
+		/* according to e500 cpu a005 erratum, reissue efp inst */
+		regs->nip -= 4;
+#ifdef DEBUG
+		printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
+#endif
+		return 0;
+	}
+
 	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
 	return -ENOSYS;
 }
@@ -718,3 +733,43 @@ int speround_handler(struct pt_regs *regs)
 
 	return 0;
 }
+
+int __init spe_mathemu_init(void)
+{
+	u32 pvr, maj, min;
+
+	pvr = mfspr(SPRN_PVR);
+
+	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
+	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
+		maj = PVR_MAJ(pvr);
+		min = PVR_MIN(pvr);
+
+		/*
+		 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
+		 * need cpu a005 errata workaround
+		 */
+		switch (maj) {
+		case 1:
+			if (min < 1)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		case 2:
+			if (min < 3)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		case 3:
+		case 4:
+		case 5:
+			if (min < 1)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+module_init(spe_mathemu_init);
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 742da43..d65b591 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -148,7 +148,7 @@ void __init MMU_init(void)
 		lowmem_end_addr = memstart_addr + total_lowmem;
 #ifndef CONFIG_HIGHMEM
 		total_memory = total_lowmem;
-		memblock_enforce_memory_limit(lowmem_end_addr);
+		memblock_enforce_memory_limit(total_lowmem);
 		memblock_analyze();
 #endif /* CONFIG_HIGHMEM */
 	}
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S
index af405ee..7c63c0e 100644
--- a/arch/powerpc/mm/tlb_nohash_low.S
+++ b/arch/powerpc/mm/tlb_nohash_low.S
@@ -189,6 +189,13 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
 	blr
 
 #ifdef CONFIG_PPC_47x
+
+/*
+ * 47x variant of icbt
+ */
+# define ICBT(CT,RA,RB)	\
+	.long	0x7c00002c | ((CT) << 21) | ((RA) << 16) | ((RB) << 11)
+
 /*
  * _tlbivax_bcast is only on 47x. We don't bother doing a runtime
  * check though, it will blow up soon enough if we mistakenly try
@@ -206,7 +213,35 @@ _GLOBAL(_tlbivax_bcast)
 	isync
 	eieio
 	tlbsync
+BEGIN_FTR_SECTION
+	b	1f
+END_FTR_SECTION_IFSET(CPU_FTR_476_DD2)
+	sync
+	wrtee	r10
+	blr
+/*
+ * DD2 HW could hang if in instruction fetch happens before msync completes.
+ * Touch enough instruction cache lines to ensure cache hits
+ */
+1:	mflr	r9
+	bl	2f
+2:	mflr	r6
+	li	r7,32
+	ICBT(0,r6,r7)		/* touch next cache line */
+	add	r6,r6,r7
+	ICBT(0,r6,r7)		/* touch next cache line */
+	add	r6,r6,r7
+	ICBT(0,r6,r7)		/* touch next cache line */
 	sync
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	mtlr	r9
 	wrtee	r10
 	blr
 #endif /* CONFIG_PPC_47x */
diff --git a/arch/powerpc/platforms/44x/44x.h b/arch/powerpc/platforms/44x/44x.h
index dbc4d2b..63f703e 100644
--- a/arch/powerpc/platforms/44x/44x.h
+++ b/arch/powerpc/platforms/44x/44x.h
@@ -4,4 +4,8 @@
 extern u8 as1_readb(volatile u8 __iomem  *addr);
 extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
 
+#define GPIO0_OSRH	0xC
+#define GPIO0_TSRH	0x14
+#define GPIO0_ISR1H	0x34
+
 #endif /* __POWERPC_PLATFORMS_44X_44X_H */
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 0f979c5..f485fc5f 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -115,7 +115,6 @@ config CANYONLANDS
 	bool "Canyonlands"
 	depends on 44x
 	default n
-	select PPC44x_SIMPLE
 	select 460EX
 	select PCI
 	select PPC4xx_PCI_EXPRESS
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index c04d16d..553db60 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_WARP)	+= warp.o
 obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
 obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
 obj-$(CONFIG_ISS4xx)	+= iss4xx.o
+obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
diff --git a/arch/powerpc/platforms/44x/canyonlands.c b/arch/powerpc/platforms/44x/canyonlands.c
new file mode 100644
index 0000000..afc5e8e
--- /dev/null
+++ b/arch/powerpc/platforms/44x/canyonlands.c
@@ -0,0 +1,134 @@
+/*
+ * This contain platform specific code for APM PPC460EX based Canyonlands
+ * board.
+ *
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Rupjyoti Sarmah <rsarmah@apm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc4xx.h>
+#include <asm/udbg.h>
+#include <asm/uic.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+#include "44x.h"
+
+#define BCSR_USB_EN	0x11
+
+static __initdata struct of_device_id ppc460ex_of_bus[] = {
+	{ .compatible = "ibm,plb4", },
+	{ .compatible = "ibm,opb", },
+	{ .compatible = "ibm,ebc", },
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+static int __init ppc460ex_device_probe(void)
+{
+	of_platform_bus_probe(NULL, ppc460ex_of_bus, NULL);
+
+	return 0;
+}
+machine_device_initcall(canyonlands, ppc460ex_device_probe);
+
+/* Using this code only for the Canyonlands board.  */
+
+static int __init ppc460ex_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+	if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
+		ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+		return 1;
+		}
+	return 0;
+}
+
+/* USB PHY fixup code on Canyonlands kit. */
+
+static int __init ppc460ex_canyonlands_fixup(void)
+{
+	u8 __iomem *bcsr ;
+	void __iomem *vaddr;
+	struct device_node *np;
+	int ret = 0;
+
+	np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-bcsr");
+	if (!np) {
+		printk(KERN_ERR "failed did not find amcc, ppc460ex bcsr node\n");
+		return -ENODEV;
+	}
+
+	bcsr = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!bcsr) {
+		printk(KERN_CRIT "Could not remap bcsr\n");
+		ret = -ENODEV;
+		goto err_bcsr;
+	}
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,ppc4xx-gpio");
+	if (!np) {
+		printk(KERN_ERR "failed did not find ibm,ppc4xx-gpio node\n");
+		return -ENODEV;
+	}
+
+	vaddr = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!vaddr) {
+		printk(KERN_CRIT "Could not get gpio node address\n");
+		ret = -ENODEV;
+		goto err_gpio;
+	}
+	/* Disable USB, through the BCSR7 bits */
+	setbits8(&bcsr[7], BCSR_USB_EN);
+
+	/* Wait for a while after reset */
+	msleep(100);
+
+	/* Enable USB here */
+	clrbits8(&bcsr[7], BCSR_USB_EN);
+
+	/*
+	 * Configure multiplexed gpio16 and gpio19 as alternate1 output
+	 * source after USB reset. In this configuration gpio16 will be
+	 * USB2HStop and gpio19 will be USB2DStop. For more details refer to
+	 * table 34-7 of PPC460EX user manual.
+	 */
+	setbits32((vaddr + GPIO0_OSRH), 0x42000000);
+	setbits32((vaddr + GPIO0_TSRH), 0x42000000);
+err_gpio:
+	iounmap(vaddr);
+err_bcsr:
+	iounmap(bcsr);
+	return ret;
+}
+machine_device_initcall(canyonlands, ppc460ex_canyonlands_fixup);
+define_machine(canyonlands) {
+	.name = "Canyonlands",
+	.probe = ppc460ex_probe,
+	.progress = udbg_progress,
+	.init_IRQ = uic_init_tree,
+	.get_irq = uic_get_irq,
+	.restart = ppc4xx_reset_system,
+	.calibrate_decr = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c
index 7ddcba3..c81c19c 100644
--- a/arch/powerpc/platforms/44x/ppc44x_simple.c
+++ b/arch/powerpc/platforms/44x/ppc44x_simple.c
@@ -53,7 +53,6 @@ static char *board[] __initdata = {
 	"amcc,arches",
 	"amcc,bamboo",
 	"amcc,bluestone",
-	"amcc,canyonlands",
 	"amcc,glacier",
 	"ibm,ebony",
 	"amcc,eiger",
diff --git a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
index 4ecf4cf..fde0ea5 100644
--- a/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
+++ b/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
@@ -59,9 +59,9 @@ irq_to_pic_bit(unsigned int irq)
 }
 
 static void
-cpld_mask_irq(unsigned int irq)
+cpld_mask_irq(struct irq_data *d)
 {
-	unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
 	void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
 
 	out_8(pic_mask,
@@ -69,9 +69,9 @@ cpld_mask_irq(unsigned int irq)
 }
 
 static void
-cpld_unmask_irq(unsigned int irq)
+cpld_unmask_irq(struct irq_data *d)
 {
-	unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
 	void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
 
 	out_8(pic_mask,
@@ -80,9 +80,9 @@ cpld_unmask_irq(unsigned int irq)
 
 static struct irq_chip cpld_pic = {
 	.name = "CPLD PIC",
-	.mask = cpld_mask_irq,
-	.ack = cpld_mask_irq,
-	.unmask = cpld_unmask_irq,
+	.irq_mask = cpld_mask_irq,
+	.irq_ack = cpld_mask_irq,
+	.irq_unmask = cpld_unmask_irq,
 };
 
 static int
diff --git a/arch/powerpc/platforms/52xx/media5200.c b/arch/powerpc/platforms/52xx/media5200.c
index 2c7780c..2bd1e6c 100644
--- a/arch/powerpc/platforms/52xx/media5200.c
+++ b/arch/powerpc/platforms/52xx/media5200.c
@@ -49,45 +49,46 @@ struct media5200_irq {
 };
 struct media5200_irq media5200_irq;
 
-static void media5200_irq_unmask(unsigned int virq)
+static void media5200_irq_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 val;
 
 	spin_lock_irqsave(&media5200_irq.lock, flags);
 	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
-	val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq);
+	val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq);
 	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
 	spin_unlock_irqrestore(&media5200_irq.lock, flags);
 }
 
-static void media5200_irq_mask(unsigned int virq)
+static void media5200_irq_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 val;
 
 	spin_lock_irqsave(&media5200_irq.lock, flags);
 	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
-	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq));
+	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq));
 	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
 	spin_unlock_irqrestore(&media5200_irq.lock, flags);
 }
 
 static struct irq_chip media5200_irq_chip = {
 	.name = "Media5200 FPGA",
-	.unmask = media5200_irq_unmask,
-	.mask = media5200_irq_mask,
-	.mask_ack = media5200_irq_mask,
+	.irq_unmask = media5200_irq_unmask,
+	.irq_mask = media5200_irq_mask,
+	.irq_mask_ack = media5200_irq_mask,
 };
 
 void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	int sub_virq, val;
 	u32 status, enable;
 
 	/* Mask off the cascaded IRQ */
 	raw_spin_lock(&desc->lock);
-	desc->chip->mask(virq);
+	chip->irq_mask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 
 	/* Ask the FPGA for IRQ status.  If 'val' is 0, then no irqs
@@ -105,9 +106,9 @@ void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
 
 	/* Processing done; can reenable the cascade now */
 	raw_spin_lock(&desc->lock);
-	desc->chip->ack(virq);
+	chip->irq_ack(&desc->irq_data);
 	if (!(desc->status & IRQ_DISABLED))
-		desc->chip->unmask(virq);
+		chip->irq_unmask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 }
 
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
index 0dad9a9..1757d1d 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
@@ -147,8 +147,7 @@ mpc52xx_wkup_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct mpc52xx_gpio_wkup __iomem *regs;
@@ -191,7 +190,7 @@ static const struct of_device_id mpc52xx_wkup_gpiochip_match[] = {
 	{}
 };
 
-static struct of_platform_driver mpc52xx_wkup_gpiochip_driver = {
+static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
 	.driver = {
 		.name = "gpio_wkup",
 		.owner = THIS_MODULE,
@@ -310,8 +309,7 @@ mpc52xx_simple_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 	return 0;
 }
 
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct gpio_chip *gc;
@@ -349,7 +347,7 @@ static const struct of_device_id mpc52xx_simple_gpiochip_match[] = {
 	{}
 };
 
-static struct of_platform_driver mpc52xx_simple_gpiochip_driver = {
+static struct platform_driver mpc52xx_simple_gpiochip_driver = {
 	.driver = {
 		.name = "gpio",
 		.owner = THIS_MODULE,
@@ -361,10 +359,10 @@ static struct of_platform_driver mpc52xx_simple_gpiochip_driver = {
 
 static int __init mpc52xx_gpio_init(void)
 {
-	if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver))
+	if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver))
 		printk(KERN_ERR "Unable to register wakeup GPIO driver\n");
 
-	if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver))
+	if (platform_driver_register(&mpc52xx_simple_gpiochip_driver))
 		printk(KERN_ERR "Unable to register simple GPIO driver\n");
 
 	return 0;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index e0d703c..6da44f0 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -135,9 +135,9 @@ DEFINE_MUTEX(mpc52xx_gpt_list_mutex);
  * Cascaded interrupt controller hooks
  */
 
-static void mpc52xx_gpt_irq_unmask(unsigned int virq)
+static void mpc52xx_gpt_irq_unmask(struct irq_data *d)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&gpt->lock, flags);
@@ -145,9 +145,9 @@ static void mpc52xx_gpt_irq_unmask(unsigned int virq)
 	spin_unlock_irqrestore(&gpt->lock, flags);
 }
 
-static void mpc52xx_gpt_irq_mask(unsigned int virq)
+static void mpc52xx_gpt_irq_mask(struct irq_data *d)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&gpt->lock, flags);
@@ -155,20 +155,20 @@ static void mpc52xx_gpt_irq_mask(unsigned int virq)
 	spin_unlock_irqrestore(&gpt->lock, flags);
 }
 
-static void mpc52xx_gpt_irq_ack(unsigned int virq)
+static void mpc52xx_gpt_irq_ack(struct irq_data *d)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 
 	out_be32(&gpt->regs->status, MPC52xx_GPT_STATUS_IRQMASK);
 }
 
-static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc52xx_gpt_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 	u32 reg;
 
-	dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, virq, flow_type);
+	dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, d->irq, flow_type);
 
 	spin_lock_irqsave(&gpt->lock, flags);
 	reg = in_be32(&gpt->regs->mode) & ~MPC52xx_GPT_MODE_ICT_MASK;
@@ -184,10 +184,10 @@ static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
 
 static struct irq_chip mpc52xx_gpt_irq_chip = {
 	.name = "MPC52xx GPT",
-	.unmask = mpc52xx_gpt_irq_unmask,
-	.mask = mpc52xx_gpt_irq_mask,
-	.ack = mpc52xx_gpt_irq_ack,
-	.set_type = mpc52xx_gpt_irq_set_type,
+	.irq_unmask = mpc52xx_gpt_irq_unmask,
+	.irq_mask = mpc52xx_gpt_irq_mask,
+	.irq_ack = mpc52xx_gpt_irq_ack,
+	.irq_set_type = mpc52xx_gpt_irq_set_type,
 };
 
 void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
@@ -721,8 +721,7 @@ static inline int mpc52xx_gpt_wdt_setup(struct mpc52xx_gpt_priv *gpt,
 /* ---------------------------------------------------------------------
  * of_platform bus binding code
  */
-static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev,
-				       const struct of_device_id *match)
+static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpt_priv *gpt;
 
@@ -781,7 +780,7 @@ static const struct of_device_id mpc52xx_gpt_match[] = {
 	{}
 };
 
-static struct of_platform_driver mpc52xx_gpt_driver = {
+static struct platform_driver mpc52xx_gpt_driver = {
 	.driver = {
 		.name = "mpc52xx-gpt",
 		.owner = THIS_MODULE,
@@ -793,10 +792,7 @@ static struct of_platform_driver mpc52xx_gpt_driver = {
 
 static int __init mpc52xx_gpt_init(void)
 {
-	if (of_register_platform_driver(&mpc52xx_gpt_driver))
-		pr_err("error registering MPC52xx GPT driver\n");
-
-	return 0;
+	return platform_driver_register(&mpc52xx_gpt_driver);
 }
 
 /* Make sure GPIOs and IRQs get set up before anyone tries to use them */
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
index f4ac213..6385d88 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
@@ -436,8 +436,7 @@ void mpc52xx_lpbfifo_abort(struct mpc52xx_lpbfifo_request *req)
 }
 EXPORT_SYMBOL(mpc52xx_lpbfifo_abort);
 
-static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op,
-					   const struct of_device_id *match)
+static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op)
 {
 	struct resource res;
 	int rc = -ENOMEM;
@@ -536,7 +535,7 @@ static struct of_device_id mpc52xx_lpbfifo_match[] __devinitconst = {
 	{},
 };
 
-static struct of_platform_driver mpc52xx_lpbfifo_driver = {
+static struct platform_driver mpc52xx_lpbfifo_driver = {
 	.driver = {
 		.name = "mpc52xx-lpbfifo",
 		.owner = THIS_MODULE,
@@ -551,14 +550,12 @@ static struct of_platform_driver mpc52xx_lpbfifo_driver = {
  */
 static int __init mpc52xx_lpbfifo_init(void)
 {
-	pr_debug("Registering LocalPlus bus FIFO driver\n");
-	return of_register_platform_driver(&mpc52xx_lpbfifo_driver);
+	return platform_driver_register(&mpc52xx_lpbfifo_driver);
 }
 module_init(mpc52xx_lpbfifo_init);
 
 static void __exit mpc52xx_lpbfifo_exit(void)
 {
-	pr_debug("Unregistering LocalPlus bus FIFO driver\n");
-	of_unregister_platform_driver(&mpc52xx_lpbfifo_driver);
+	platform_driver_unregister(&mpc52xx_lpbfifo_driver);
 }
 module_exit(mpc52xx_lpbfifo_exit);
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
index 4bf4bf7..9f3ed58 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
@@ -155,47 +155,47 @@ static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
 /*
  * IRQ[0-3] interrupt irq_chip
  */
-static void mpc52xx_extirq_mask(unsigned int virq)
+static void mpc52xx_extirq_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&intr->ctrl, 11 - l2irq);
 }
 
-static void mpc52xx_extirq_unmask(unsigned int virq)
+static void mpc52xx_extirq_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->ctrl, 11 - l2irq);
 }
 
-static void mpc52xx_extirq_ack(unsigned int virq)
+static void mpc52xx_extirq_ack(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->ctrl, 27-l2irq);
 }
 
-static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	u32 ctrl_reg, type;
 	int irq;
 	int l2irq;
 	void *handler = handle_level_irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
@@ -214,44 +214,44 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
 	ctrl_reg |= (type << (22 - (l2irq * 2)));
 	out_be32(&intr->ctrl, ctrl_reg);
 
-	__set_irq_handler_unlocked(virq, handler);
+	__set_irq_handler_unlocked(d->irq, handler);
 
 	return 0;
 }
 
 static struct irq_chip mpc52xx_extirq_irqchip = {
 	.name = "MPC52xx External",
-	.mask = mpc52xx_extirq_mask,
-	.unmask = mpc52xx_extirq_unmask,
-	.ack = mpc52xx_extirq_ack,
-	.set_type = mpc52xx_extirq_set_type,
+	.irq_mask = mpc52xx_extirq_mask,
+	.irq_unmask = mpc52xx_extirq_unmask,
+	.irq_ack = mpc52xx_extirq_ack,
+	.irq_set_type = mpc52xx_extirq_set_type,
 };
 
 /*
  * Main interrupt irq_chip
  */
-static int mpc52xx_null_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc52xx_null_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	return 0; /* Do nothing so that the sense mask will get updated */
 }
 
-static void mpc52xx_main_mask(unsigned int virq)
+static void mpc52xx_main_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->main_mask, 16 - l2irq);
 }
 
-static void mpc52xx_main_unmask(unsigned int virq)
+static void mpc52xx_main_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&intr->main_mask, 16 - l2irq);
@@ -259,32 +259,32 @@ static void mpc52xx_main_unmask(unsigned int virq)
 
 static struct irq_chip mpc52xx_main_irqchip = {
 	.name = "MPC52xx Main",
-	.mask = mpc52xx_main_mask,
-	.mask_ack = mpc52xx_main_mask,
-	.unmask = mpc52xx_main_unmask,
-	.set_type = mpc52xx_null_set_type,
+	.irq_mask = mpc52xx_main_mask,
+	.irq_mask_ack = mpc52xx_main_mask,
+	.irq_unmask = mpc52xx_main_unmask,
+	.irq_set_type = mpc52xx_null_set_type,
 };
 
 /*
  * Peripherals interrupt irq_chip
  */
-static void mpc52xx_periph_mask(unsigned int virq)
+static void mpc52xx_periph_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->per_mask, 31 - l2irq);
 }
 
-static void mpc52xx_periph_unmask(unsigned int virq)
+static void mpc52xx_periph_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&intr->per_mask, 31 - l2irq);
@@ -292,43 +292,43 @@ static void mpc52xx_periph_unmask(unsigned int virq)
 
 static struct irq_chip mpc52xx_periph_irqchip = {
 	.name = "MPC52xx Peripherals",
-	.mask = mpc52xx_periph_mask,
-	.mask_ack = mpc52xx_periph_mask,
-	.unmask = mpc52xx_periph_unmask,
-	.set_type = mpc52xx_null_set_type,
+	.irq_mask = mpc52xx_periph_mask,
+	.irq_mask_ack = mpc52xx_periph_mask,
+	.irq_unmask = mpc52xx_periph_unmask,
+	.irq_set_type = mpc52xx_null_set_type,
 };
 
 /*
  * SDMA interrupt irq_chip
  */
-static void mpc52xx_sdma_mask(unsigned int virq)
+static void mpc52xx_sdma_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&sdma->IntMask, l2irq);
 }
 
-static void mpc52xx_sdma_unmask(unsigned int virq)
+static void mpc52xx_sdma_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&sdma->IntMask, l2irq);
 }
 
-static void mpc52xx_sdma_ack(unsigned int virq)
+static void mpc52xx_sdma_ack(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	out_be32(&sdma->IntPend, 1 << l2irq);
@@ -336,10 +336,10 @@ static void mpc52xx_sdma_ack(unsigned int virq)
 
 static struct irq_chip mpc52xx_sdma_irqchip = {
 	.name = "MPC52xx SDMA",
-	.mask = mpc52xx_sdma_mask,
-	.unmask = mpc52xx_sdma_unmask,
-	.ack = mpc52xx_sdma_ack,
-	.set_type = mpc52xx_null_set_type,
+	.irq_mask = mpc52xx_sdma_mask,
+	.irq_unmask = mpc52xx_sdma_unmask,
+	.irq_ack = mpc52xx_sdma_ack,
+	.irq_set_type = mpc52xx_null_set_type,
 };
 
 /**
diff --git a/arch/powerpc/platforms/82xx/Makefile b/arch/powerpc/platforms/82xx/Makefile
index d982793..455fe21 100644
--- a/arch/powerpc/platforms/82xx/Makefile
+++ b/arch/powerpc/platforms/82xx/Makefile
@@ -6,4 +6,4 @@ obj-$(CONFIG_CPM2) += pq2.o
 obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o
 obj-$(CONFIG_PQ2FADS) += pq2fads.o
 obj-$(CONFIG_EP8248E) += ep8248e.o
-obj-$(CONFIG_MGCOGE) += mgcoge.o
+obj-$(CONFIG_MGCOGE) += km82xx.o
diff --git a/arch/powerpc/platforms/82xx/ep8248e.c b/arch/powerpc/platforms/82xx/ep8248e.c
index 1565e04..10ff526 100644
--- a/arch/powerpc/platforms/82xx/ep8248e.c
+++ b/arch/powerpc/platforms/82xx/ep8248e.c
@@ -111,8 +111,7 @@ static struct mdiobb_ctrl ep8248e_mdio_ctrl = {
 	.ops = &ep8248e_mdio_ops,
 };
 
-static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev)
 {
 	struct mii_bus *bus;
 	struct resource res;
@@ -167,7 +166,7 @@ static const struct of_device_id ep8248e_mdio_match[] = {
 	{},
 };
 
-static struct of_platform_driver ep8248e_mdio_driver = {
+static struct platform_driver ep8248e_mdio_driver = {
 	.driver = {
 		.name = "ep8248e-mdio-bitbang",
 		.owner = THIS_MODULE,
@@ -308,7 +307,7 @@ static  __initdata struct of_device_id of_bus_ids[] = {
 static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-	of_register_platform_driver(&ep8248e_mdio_driver);
+	platform_driver_register(&ep8248e_mdio_driver);
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/82xx/km82xx.c b/arch/powerpc/platforms/82xx/km82xx.c
new file mode 100644
index 0000000..428c5e0
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/km82xx.c
@@ -0,0 +1,206 @@
+/*
+ * Keymile km82xx support
+ * Copyright 2008-2011 DENX Software Engineering GmbH
+ * Author: Heiko Schocher <hs@denx.de>
+ *
+ * based on code from:
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/cpm2.h>
+#include <asm/udbg.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/mpc8260.h>
+#include <asm/prom.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/cpm2_pic.h>
+
+#include "pq2.h"
+
+static void __init km82xx_pic_init(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+							"fsl,pq2-pic");
+	if (!np) {
+		printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
+		return;
+	}
+
+	cpm2_pic_init(np);
+	of_node_put(np);
+}
+
+struct cpm_pin {
+	int port, pin, flags;
+};
+
+static __initdata struct cpm_pin km82xx_pins[] = {
+
+	/* SMC2 */
+	{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+	/* SCC1 */
+	{2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+
+	/* SCC4 */
+	{2, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2,  9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2,  8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+	/* FCC1 */
+	{0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+	{0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+	{0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+	{0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+	{0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+	{0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+
+	{2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 23, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+
+	/* FCC2 */
+	{1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+	{1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+	{2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+
+	/* MDC */
+	{0, 13, CPM_PIN_OUTPUT | CPM_PIN_GPIO},
+
+#if defined(CONFIG_I2C_CPM)
+	/* I2C */
+	{3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
+	{3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
+#endif
+
+	/* USB */
+	{0, 10, CPM_PIN_OUTPUT | CPM_PIN_GPIO},    /* FULL_SPEED */
+	{0, 11, CPM_PIN_OUTPUT | CPM_PIN_GPIO},    /*/SLAVE */
+	{2, 10, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXN */
+	{2, 11, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXP */
+	{2, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* /OE */
+	{2, 27, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXCLK */
+	{3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXP */
+	{3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXN */
+	{3, 25, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXD */
+};
+
+static void __init init_ioports(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(km82xx_pins); i++) {
+		const struct cpm_pin *pin = &km82xx_pins[i];
+		cpm2_set_pin(pin->port, pin->pin, pin->flags);
+	}
+
+	cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+	cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_TX);
+	cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RTX);
+	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX);
+	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9,  CPM_CLK_TX);
+	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
+
+	/* Force USB FULL SPEED bit to '1' */
+	setbits32(&cpm2_immr->im_ioport.iop_pdata, 1 << (31 - 10));
+	/* clear USB_SLAVE */
+	clrbits32(&cpm2_immr->im_ioport.iop_pdata, 1 << (31 - 11));
+}
+
+static void __init km82xx_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("km82xx_setup_arch()", 0);
+
+	cpm2_reset();
+
+	/* When this is set, snooping CPM DMA from RAM causes
+	 * machine checks.  See erratum SIU18.
+	 */
+	clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
+
+	init_ioports();
+
+	if (ppc_md.progress)
+		ppc_md.progress("km82xx_setup_arch(), finish", 0);
+}
+
+static  __initdata struct of_device_id of_bus_ids[] = {
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+	of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(km82xx, declare_of_platform_devices);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init km82xx_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+	return of_flat_dt_is_compatible(root, "keymile,km82xx");
+}
+
+define_machine(km82xx)
+{
+	.name = "Keymile km82xx",
+	.probe = km82xx_probe,
+	.setup_arch = km82xx_setup_arch,
+	.init_IRQ = km82xx_pic_init,
+	.get_irq = cpm2_get_irq,
+	.calibrate_decr = generic_calibrate_decr,
+	.restart = pq2_restart,
+	.progress = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/82xx/mgcoge.c b/arch/powerpc/platforms/82xx/mgcoge.c
deleted file mode 100644
index 7a5de9e..0000000
--- a/arch/powerpc/platforms/82xx/mgcoge.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Keymile mgcoge support
- * Copyright 2008 DENX Software Engineering GmbH
- * Author: Heiko Schocher <hs@denx.de>
- *
- * based on code from:
- * Copyright 2007 Freescale Semiconductor, Inc.
- * Author: Scott Wood <scottwood@freescale.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/of_platform.h>
-
-#include <asm/io.h>
-#include <asm/cpm2.h>
-#include <asm/udbg.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/mpc8260.h>
-#include <asm/prom.h>
-
-#include <sysdev/fsl_soc.h>
-#include <sysdev/cpm2_pic.h>
-
-#include "pq2.h"
-
-static void __init mgcoge_pic_init(void)
-{
-	struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
-	if (!np) {
-		printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
-		return;
-	}
-
-	cpm2_pic_init(np);
-	of_node_put(np);
-}
-
-struct cpm_pin {
-	int port, pin, flags;
-};
-
-static __initdata struct cpm_pin mgcoge_pins[] = {
-
-	/* SMC2 */
-	{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-
-	/* SCC4 */
-	{2, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2,  9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2,  8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{3, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{3, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-
-	/* FCC1 */
-	{0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-	{0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-	{0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-	{0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-	{0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-	{0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-
-	{2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2, 23, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-
-	/* FCC2 */
-	{1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-	{1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-
-	{2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-
-	/* MDC */
-	{0, 13, CPM_PIN_OUTPUT | CPM_PIN_GPIO},
-
-#if defined(CONFIG_I2C_CPM)
-	/* I2C */
-	{3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
-	{3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
-#endif
-};
-
-static void __init init_ioports(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mgcoge_pins); i++) {
-		const struct cpm_pin *pin = &mgcoge_pins[i];
-		cpm2_set_pin(pin->port, pin->pin, pin->flags);
-	}
-
-	cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
-	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX);
-	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX);
-	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_RX);
-	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9,  CPM_CLK_TX);
-	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
-	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
-}
-
-static void __init mgcoge_setup_arch(void)
-{
-	if (ppc_md.progress)
-		ppc_md.progress("mgcoge_setup_arch()", 0);
-
-	cpm2_reset();
-
-	/* When this is set, snooping CPM DMA from RAM causes
-	 * machine checks.  See erratum SIU18.
-	 */
-	clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
-
-	init_ioports();
-
-	if (ppc_md.progress)
-		ppc_md.progress("mgcoge_setup_arch(), finish", 0);
-}
-
-static  __initdata struct of_device_id of_bus_ids[] = {
-	{ .compatible = "simple-bus", },
-	{},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-
-	return 0;
-}
-machine_device_initcall(mgcoge, declare_of_platform_devices);
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init mgcoge_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-	return of_flat_dt_is_compatible(root, "keymile,mgcoge");
-}
-
-define_machine(mgcoge)
-{
-	.name = "Keymile MGCOGE",
-	.probe = mgcoge_probe,
-	.setup_arch = mgcoge_setup_arch,
-	.init_IRQ = mgcoge_pic_init,
-	.get_irq = cpm2_get_irq,
-	.calibrate_decr = generic_calibrate_decr,
-	.restart = pq2_restart,
-	.progress = udbg_progress,
-};
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
index 5a55d87..926dfda 100644
--- a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -39,10 +39,10 @@ struct pq2ads_pci_pic {
 
 #define NUM_IRQS 32
 
-static void pq2ads_pci_mask_irq(unsigned int virq)
+static void pq2ads_pci_mask_irq(struct irq_data *d)
 {
-	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
-	int irq = NUM_IRQS - virq_to_hw(virq) - 1;
+	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
+	int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
 
 	if (irq != -1) {
 		unsigned long flags;
@@ -55,10 +55,10 @@ static void pq2ads_pci_mask_irq(unsigned int virq)
 	}
 }
 
-static void pq2ads_pci_unmask_irq(unsigned int virq)
+static void pq2ads_pci_unmask_irq(struct irq_data *d)
 {
-	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
-	int irq = NUM_IRQS - virq_to_hw(virq) - 1;
+	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
+	int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
 
 	if (irq != -1) {
 		unsigned long flags;
@@ -71,18 +71,17 @@ static void pq2ads_pci_unmask_irq(unsigned int virq)
 
 static struct irq_chip pq2ads_pci_ic = {
 	.name = "PQ2 ADS PCI",
-	.end = pq2ads_pci_unmask_irq,
-	.mask = pq2ads_pci_mask_irq,
-	.mask_ack = pq2ads_pci_mask_irq,
-	.ack = pq2ads_pci_mask_irq,
-	.unmask = pq2ads_pci_unmask_irq,
-	.enable = pq2ads_pci_unmask_irq,
-	.disable = pq2ads_pci_mask_irq
+	.irq_mask = pq2ads_pci_mask_irq,
+	.irq_mask_ack = pq2ads_pci_mask_irq,
+	.irq_ack = pq2ads_pci_mask_irq,
+	.irq_unmask = pq2ads_pci_unmask_irq,
+	.irq_enable = pq2ads_pci_unmask_irq,
+	.irq_disable = pq2ads_pci_mask_irq
 };
 
 static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	struct pq2ads_pci_pic *priv = desc->handler_data;
+	struct pq2ads_pci_pic *priv = get_irq_desc_data(desc);
 	u32 stat, mask, pend;
 	int bit;
 
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 6e8bbbb..ed95bfc 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -16,4 +16,4 @@ obj-$(CONFIG_MPC837x_MDS)	+= mpc837x_mds.o
 obj-$(CONFIG_SBC834x)		+= sbc834x.o
 obj-$(CONFIG_MPC837x_RDB)	+= mpc837x_rdb.o
 obj-$(CONFIG_ASP834x)		+= asp834x.o
-obj-$(CONFIG_KMETER1)		+= kmeter1.o
+obj-$(CONFIG_KMETER1)		+= km83xx.o
diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c
new file mode 100644
index 0000000..a2b9b9e
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/km83xx.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2008-2011 DENX Software Engineering GmbH
+ * Author: Heiko Schocher <hs@denx.de>
+ *
+ * Description:
+ * Keymile KMETER1 board specific routines.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include <asm/qe.h>
+#include <asm/qe_ic.h>
+
+#include "mpc83xx.h"
+
+#define SVR_REV(svr)    (((svr) >>  0) & 0xFFFF) /* Revision field */
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init mpc83xx_km_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("kmpbec83xx_setup_arch()", 0);
+
+#ifdef CONFIG_PCI
+	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
+		mpc83xx_add_bridge(np);
+#endif
+
+#ifdef CONFIG_QUICC_ENGINE
+	qe_reset();
+
+	np = of_find_node_by_name(NULL, "par_io");
+	if (np != NULL) {
+		par_io_init(np);
+		of_node_put(np);
+
+		for_each_node_by_name(np, "spi")
+			par_io_of_config(np);
+
+		for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+			par_io_of_config(np);
+	}
+
+	np = of_find_compatible_node(NULL, "network", "ucc_geth");
+	if (np != NULL) {
+		uint svid;
+
+		/* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */
+		svid = mfspr(SPRN_SVR);
+		if (SVR_REV(svid) == 0x0021) {
+			struct	device_node *np_par;
+			struct	resource res;
+			void	__iomem *base;
+			int	ret;
+
+			np_par = of_find_node_by_name(NULL, "par_io");
+			if (np_par == NULL) {
+				printk(KERN_WARNING "%s couldn;t find par_io node\n",
+					__func__);
+				return;
+			}
+			/* Map Parallel I/O ports registers */
+			ret = of_address_to_resource(np_par, 0, &res);
+			if (ret) {
+				printk(KERN_WARNING "%s couldn;t map par_io registers\n",
+					__func__);
+				return;
+			}
+			base = ioremap(res.start, res.end - res.start + 1);
+
+			/*
+			 * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
+			 * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1)
+			 */
+			setbits32((base + 0xa8), 0x0c003000);
+
+			/*
+			 * IMMR + 0x14AC[20:27] = 10101010
+			 * (data delay for both UCC's)
+			 */
+			clrsetbits_be32((base + 0xac), 0xff0, 0xaa0);
+			iounmap(base);
+			of_node_put(np_par);
+		}
+		of_node_put(np);
+	}
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+static struct of_device_id kmpbec83xx_ids[] = {
+	{ .type = "soc", },
+	{ .compatible = "soc", },
+	{ .compatible = "simple-bus", },
+	{ .type = "qe", },
+	{ .compatible = "fsl,qe", },
+	{},
+};
+
+static int __init kmeter_declare_of_platform_devices(void)
+{
+	/* Publish the QE devices */
+	of_platform_bus_probe(NULL, kmpbec83xx_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(mpc83xx_km, kmeter_declare_of_platform_devices);
+
+static void __init mpc83xx_km_init_IRQ(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,pq2pro-pic");
+	if (!np) {
+		np = of_find_node_by_type(NULL, "ipic");
+		if (!np)
+			return;
+	}
+
+	ipic_init(np, 0);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+	of_node_put(np);
+
+#ifdef CONFIG_QUICC_ENGINE
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+	if (!np) {
+		np = of_find_node_by_type(NULL, "qeic");
+		if (!np)
+			return;
+	}
+	qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
+	of_node_put(np);
+#endif				/* CONFIG_QUICC_ENGINE */
+}
+
+/* list of the supported boards */
+static char *board[] __initdata = {
+	"Keymile,KMETER1",
+	"Keymile,kmpbec8321",
+	NULL
+};
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc83xx_km_probe(void)
+{
+	unsigned long node = of_get_flat_dt_root();
+	int i = 0;
+
+	while (board[i]) {
+		if (of_flat_dt_is_compatible(node, board[i]))
+			break;
+		i++;
+	}
+	return (board[i] != NULL);
+}
+
+define_machine(mpc83xx_km) {
+	.name		= "mpc83xx-km-platform",
+	.probe		= mpc83xx_km_probe,
+	.setup_arch	= mpc83xx_km_setup_arch,
+	.init_IRQ	= mpc83xx_km_init_IRQ,
+	.get_irq	= ipic_get_irq,
+	.restart	= mpc83xx_restart,
+	.time_init	= mpc83xx_time_init,
+	.calibrate_decr	= generic_calibrate_decr,
+	.progress	= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/83xx/kmeter1.c b/arch/powerpc/platforms/83xx/kmeter1.c
deleted file mode 100644
index 903acfd..0000000
--- a/arch/powerpc/platforms/83xx/kmeter1.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright 2008 DENX Software Engineering GmbH
- * Author: Heiko Schocher <hs@denx.de>
- *
- * Description:
- * Keymile KMETER1 board specific routines.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-#include <linux/initrd.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
-
-#include <asm/system.h>
-#include <asm/atomic.h>
-#include <asm/time.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/ipic.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/udbg.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/qe.h>
-#include <asm/qe_ic.h>
-
-#include "mpc83xx.h"
-
-#define SVR_REV(svr)    (((svr) >>  0) & 0xFFFF) /* Revision field */
-/* ************************************************************************
- *
- * Setup the architecture
- *
- */
-static void __init kmeter1_setup_arch(void)
-{
-	struct device_node *np;
-
-	if (ppc_md.progress)
-		ppc_md.progress("kmeter1_setup_arch()", 0);
-
-#ifdef CONFIG_PCI
-	for_each_compatible_node(np, "pci", "fsl,mpc8349-pci")
-		mpc83xx_add_bridge(np);
-#endif
-
-#ifdef CONFIG_QUICC_ENGINE
-	qe_reset();
-
-	np = of_find_node_by_name(NULL, "par_io");
-	if (np != NULL) {
-		par_io_init(np);
-		of_node_put(np);
-
-		for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
-			par_io_of_config(np);
-	}
-
-	np = of_find_compatible_node(NULL, "network", "ucc_geth");
-	if (np != NULL) {
-		uint svid;
-
-		/* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */
-		svid = mfspr(SPRN_SVR);
-		if (SVR_REV(svid) == 0x0021) {
-			struct	device_node *np_par;
-			struct	resource res;
-			void	__iomem *base;
-			int	ret;
-
-			np_par = of_find_node_by_name(NULL, "par_io");
-			if (np_par == NULL) {
-				printk(KERN_WARNING "%s couldn;t find par_io node\n",
-					__func__);
-				return;
-			}
-			/* Map Parallel I/O ports registers */
-			ret = of_address_to_resource(np_par, 0, &res);
-			if (ret) {
-				printk(KERN_WARNING "%s couldn;t map par_io registers\n",
-					__func__);
-				return;
-			}
-			base = ioremap(res.start, res.end - res.start + 1);
-
-			/*
-			 * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
-			 * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1)
-			 */
-			setbits32((base + 0xa8), 0x0c003000);
-
-			/*
-			 * IMMR + 0x14AC[20:27] = 10101010
-			 * (data delay for both UCC's)
-			 */
-			clrsetbits_be32((base + 0xac), 0xff0, 0xaa0);
-			iounmap(base);
-			of_node_put(np_par);
-		}
-		of_node_put(np);
-	}
-#endif				/* CONFIG_QUICC_ENGINE */
-}
-
-static struct of_device_id kmeter_ids[] = {
-	{ .type = "soc", },
-	{ .compatible = "soc", },
-	{ .compatible = "simple-bus", },
-	{ .type = "qe", },
-	{ .compatible = "fsl,qe", },
-	{},
-};
-
-static int __init kmeter_declare_of_platform_devices(void)
-{
-	/* Publish the QE devices */
-	of_platform_bus_probe(NULL, kmeter_ids, NULL);
-
-	return 0;
-}
-machine_device_initcall(kmeter1, kmeter_declare_of_platform_devices);
-
-static void __init kmeter1_init_IRQ(void)
-{
-	struct device_node *np;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,pq2pro-pic");
-	if (!np) {
-		np = of_find_node_by_type(NULL, "ipic");
-		if (!np)
-			return;
-	}
-
-	ipic_init(np, 0);
-
-	/* Initialize the default interrupt mapping priorities,
-	 * in case the boot rom changed something on us.
-	 */
-	ipic_set_default_priority();
-	of_node_put(np);
-
-#ifdef CONFIG_QUICC_ENGINE
-	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
-	if (!np) {
-		np = of_find_node_by_type(NULL, "qeic");
-		if (!np)
-			return;
-	}
-	qe_ic_init(np, 0, qe_ic_cascade_low_ipic, qe_ic_cascade_high_ipic);
-	of_node_put(np);
-#endif				/* CONFIG_QUICC_ENGINE */
-}
-
-/*
- * Called very early, MMU is off, device-tree isn't unflattened
- */
-static int __init kmeter1_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-
-	return of_flat_dt_is_compatible(root, "keymile,KMETER1");
-}
-
-define_machine(kmeter1) {
-	.name		= "KMETER1",
-	.probe		= kmeter1_probe,
-	.setup_arch	= kmeter1_setup_arch,
-	.init_IRQ	= kmeter1_init_IRQ,
-	.get_irq	= ipic_get_irq,
-	.restart	= mpc83xx_restart,
-	.time_init	= mpc83xx_time_init,
-	.calibrate_decr	= generic_calibrate_decr,
-	.progress	= udbg_progress,
-};
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
index fd4f2f2..1882729 100644
--- a/arch/powerpc/platforms/83xx/suspend.c
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -318,14 +318,18 @@ static const struct platform_suspend_ops mpc83xx_suspend_ops = {
 	.end = mpc83xx_suspend_end,
 };
 
-static int pmc_probe(struct platform_device *ofdev,
-                     const struct of_device_id *match)
+static int pmc_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct resource res;
-	struct pmc_type *type = match->data;
+	struct pmc_type *type;
 	int ret = 0;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+
+	type = ofdev->dev.of_match->data;
+
 	if (!of_device_is_available(np))
 		return -ENODEV;
 
@@ -422,7 +426,7 @@ static struct of_device_id pmc_match[] = {
 	{}
 };
 
-static struct of_platform_driver pmc_driver = {
+static struct platform_driver pmc_driver = {
 	.driver = {
 		.name = "mpc83xx-pmc",
 		.owner = THIS_MODULE,
@@ -434,7 +438,7 @@ static struct of_platform_driver pmc_driver = {
 
 static int pmc_init(void)
 {
-	return of_register_platform_driver(&pmc_driver);
+	return platform_driver_register(&pmc_driver);
 }
 
 module_init(pmc_init);
diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c
index f4d36b5..64447e4 100644
--- a/arch/powerpc/platforms/85xx/ksi8560.c
+++ b/arch/powerpc/platforms/85xx/ksi8560.c
@@ -56,12 +56,13 @@ static void machine_restart(char *cmd)
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init ksi8560_pic_init(void)
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
index 9438a89..1352d11 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c
@@ -50,12 +50,13 @@ static int mpc85xx_exclude_device(struct pci_controller *hose,
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 #endif /* CONFIG_CPM2 */
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 8190bc2..793ead7 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -47,12 +47,13 @@
 #ifdef CONFIG_PPC_I8259
 static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
 
 	if (cascade_irq != NO_IRQ) {
 		generic_handle_irq(cascade_irq);
 	}
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif	/* CONFIG_PPC_I8259 */
 
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
index a5ad1c7..d7e28ec 100644
--- a/arch/powerpc/platforms/85xx/sbc8560.c
+++ b/arch/powerpc/platforms/85xx/sbc8560.c
@@ -41,12 +41,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 #endif /* CONFIG_CPM2 */
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 5c91a99..0d00ff9 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -91,10 +91,14 @@ smp_85xx_kick_cpu(int nr)
 	while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
 		mdelay(1);
 #else
+	smp_generic_kick_cpu(nr);
+
 	out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
 		__pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
 
-	smp_generic_kick_cpu(nr);
+	if (!ioremappable)
+		flush_dcache_range((ulong)bptr_vaddr,
+				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
 #endif
 
 	local_irq_restore(flags);
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
index d48527f..79d85ac 100644
--- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
+++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
@@ -93,6 +93,7 @@ static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
 
 void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq;
 
 	/*
@@ -103,17 +104,16 @@ void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
 
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
-
+	chip->irq_eoi(&desc->irq_data);
 }
 
-static void socrates_fpga_pic_ack(unsigned int virq)
+static void socrates_fpga_pic_ack(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq, irq_line;
 	uint32_t mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -124,14 +124,14 @@ static void socrates_fpga_pic_ack(unsigned int virq)
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_mask(unsigned int virq)
+static void socrates_fpga_pic_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -142,14 +142,14 @@ static void socrates_fpga_pic_mask(unsigned int virq)
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_mask_ack(unsigned int virq)
+static void socrates_fpga_pic_mask_ack(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -161,14 +161,14 @@ static void socrates_fpga_pic_mask_ack(unsigned int virq)
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_unmask(unsigned int virq)
+static void socrates_fpga_pic_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -179,14 +179,14 @@ static void socrates_fpga_pic_unmask(unsigned int virq)
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_eoi(unsigned int virq)
+static void socrates_fpga_pic_eoi(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -197,7 +197,7 @@ static void socrates_fpga_pic_eoi(unsigned int virq)
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static int socrates_fpga_pic_set_type(unsigned int virq,
+static int socrates_fpga_pic_set_type(struct irq_data *d,
 		unsigned int flow_type)
 {
 	unsigned long flags;
@@ -205,7 +205,7 @@ static int socrates_fpga_pic_set_type(unsigned int virq,
 	int polarity;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
 		return -EINVAL;
@@ -233,12 +233,12 @@ static int socrates_fpga_pic_set_type(unsigned int virq,
 
 static struct irq_chip socrates_fpga_pic_chip = {
 	.name		= "FPGA-PIC",
-	.ack		= socrates_fpga_pic_ack,
-	.mask           = socrates_fpga_pic_mask,
-	.mask_ack       = socrates_fpga_pic_mask_ack,
-	.unmask         = socrates_fpga_pic_unmask,
-	.eoi		= socrates_fpga_pic_eoi,
-	.set_type	= socrates_fpga_pic_set_type,
+	.irq_ack	= socrates_fpga_pic_ack,
+	.irq_mask	= socrates_fpga_pic_mask,
+	.irq_mask_ack	= socrates_fpga_pic_mask_ack,
+	.irq_unmask	= socrates_fpga_pic_unmask,
+	.irq_eoi	= socrates_fpga_pic_eoi,
+	.irq_set_type	= socrates_fpga_pic_set_type,
 };
 
 static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
diff --git a/arch/powerpc/platforms/85xx/stx_gp3.c b/arch/powerpc/platforms/85xx/stx_gp3.c
index bc33d18..2b62b06 100644
--- a/arch/powerpc/platforms/85xx/stx_gp3.c
+++ b/arch/powerpc/platforms/85xx/stx_gp3.c
@@ -46,12 +46,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif /* CONFIG_CPM2 */
 
diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c
index 5e847d0..2265b68 100644
--- a/arch/powerpc/platforms/85xx/tqm85xx.c
+++ b/arch/powerpc/platforms/85xx/tqm85xx.c
@@ -44,12 +44,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif /* CONFIG_CPM2 */
 
diff --git a/arch/powerpc/platforms/86xx/gef_pic.c b/arch/powerpc/platforms/86xx/gef_pic.c
index 6df9e25..0adfe3b 100644
--- a/arch/powerpc/platforms/86xx/gef_pic.c
+++ b/arch/powerpc/platforms/86xx/gef_pic.c
@@ -95,6 +95,7 @@ static int gef_pic_cascade_irq;
 
 void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq;
 
 	/*
@@ -106,17 +107,16 @@ void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
-
+	chip->irq_eoi(&desc->irq_data);
 }
 
-static void gef_pic_mask(unsigned int virq)
+static void gef_pic_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	u32 mask;
 
-	hwirq = gef_irq_to_hw(virq);
+	hwirq = gef_irq_to_hw(d->irq);
 
 	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
@@ -125,21 +125,21 @@ static void gef_pic_mask(unsigned int virq)
 	raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
 }
 
-static void gef_pic_mask_ack(unsigned int virq)
+static void gef_pic_mask_ack(struct irq_data *d)
 {
 	/* Don't think we actually have to do anything to ack an interrupt,
 	 * we just need to clear down the devices interrupt and it will go away
 	 */
-	gef_pic_mask(virq);
+	gef_pic_mask(d);
 }
 
-static void gef_pic_unmask(unsigned int virq)
+static void gef_pic_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	u32 mask;
 
-	hwirq = gef_irq_to_hw(virq);
+	hwirq = gef_irq_to_hw(d->irq);
 
 	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
@@ -150,9 +150,9 @@ static void gef_pic_unmask(unsigned int virq)
 
 static struct irq_chip gef_pic_chip = {
 	.name		= "gefp",
-	.mask		= gef_pic_mask,
-	.mask_ack	= gef_pic_mask_ack,
-	.unmask		= gef_pic_unmask,
+	.irq_mask	= gef_pic_mask,
+	.irq_mask_ack	= gef_pic_mask_ack,
+	.irq_unmask	= gef_pic_unmask,
 };
 
 
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c
index 668275d..cbe3363 100644
--- a/arch/powerpc/platforms/86xx/pic.c
+++ b/arch/powerpc/platforms/86xx/pic.c
@@ -19,10 +19,13 @@
 #ifdef CONFIG_PPC_I8259
 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif	/* CONFIG_PPC_I8259 */
 
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig
index dd35ce0..ee56a9e 100644
--- a/arch/powerpc/platforms/8xx/Kconfig
+++ b/arch/powerpc/platforms/8xx/Kconfig
@@ -49,12 +49,6 @@ config PPC_ADDER875
 	  This enables support for the Analogue & Micro Adder 875
 	  board.
 
-config PPC_MGSUVD
-	bool "MGSUVD"
-	select CPM1
-	help
-	  This enables support for the Keymile MGSUVD board.
-
 config TQM8XX
 	bool "TQM8XX"
 	select CPM1
diff --git a/arch/powerpc/platforms/8xx/Makefile b/arch/powerpc/platforms/8xx/Makefile
index a491fe6..76a81c3 100644
--- a/arch/powerpc/platforms/8xx/Makefile
+++ b/arch/powerpc/platforms/8xx/Makefile
@@ -6,5 +6,4 @@ obj-$(CONFIG_MPC885ADS)   += mpc885ads_setup.o
 obj-$(CONFIG_MPC86XADS)   += mpc86xads_setup.o
 obj-$(CONFIG_PPC_EP88XC)  += ep88xc.o
 obj-$(CONFIG_PPC_ADDER875) += adder875.o
-obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o
 obj-$(CONFIG_TQM8XX)      += tqm8xx_setup.o
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index 60168c1..fabb108 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -218,15 +218,20 @@ void mpc8xx_restart(char *cmd)
 
 static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip;
 	int cascade_irq;
 
 	if ((cascade_irq = cpm_get_irq()) >= 0) {
 		struct irq_desc *cdesc = irq_to_desc(cascade_irq);
 
 		generic_handle_irq(cascade_irq);
-		cdesc->chip->eoi(cascade_irq);
+
+		chip = get_irq_desc_chip(cdesc);
+		chip->irq_eoi(&cdesc->irq_data);
 	}
-	desc->chip->eoi(irq);
+
+	chip = get_irq_desc_chip(desc);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 /* Initialize the internal interrupt controllers.  The number of
diff --git a/arch/powerpc/platforms/8xx/mgsuvd.c b/arch/powerpc/platforms/8xx/mgsuvd.c
deleted file mode 100644
index ca3cb07..0000000
--- a/arch/powerpc/platforms/8xx/mgsuvd.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *
- * Platform setup for the Keymile mgsuvd board
- *
- * Heiko Schocher <hs@denx.de>
- *
- * Copyright 2008 DENX Software Engineering GmbH
- *
- * 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/ioport.h>
-#include <linux/of_platform.h>
-
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/processor.h>
-#include <asm/cpm1.h>
-#include <asm/prom.h>
-#include <asm/fs_pd.h>
-
-#include "mpc8xx.h"
-
-struct cpm_pin {
-	int port, pin, flags;
-};
-
-static __initdata struct cpm_pin mgsuvd_pins[] = {
-	/* SMC1 */
-	{CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
-	{CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
-
-	/* SCC3 */
-	{CPM_PORTA, 10, CPM_PIN_INPUT},
-	{CPM_PORTA, 11, CPM_PIN_INPUT},
-	{CPM_PORTA, 3, CPM_PIN_INPUT},
-	{CPM_PORTA, 2, CPM_PIN_INPUT},
-	{CPM_PORTC, 13, CPM_PIN_INPUT},
-};
-
-static void __init init_ioports(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mgsuvd_pins); i++) {
-		struct cpm_pin *pin = &mgsuvd_pins[i];
-		cpm1_set_pin(pin->port, pin->pin, pin->flags);
-	}
-
-	setbits16(&mpc8xx_immr->im_ioport.iop_pcso, 0x300);
-	cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RX);
-	cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK6, CPM_CLK_TX);
-	cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
-}
-
-static void __init mgsuvd_setup_arch(void)
-{
-	cpm_reset();
-	init_ioports();
-}
-
-static __initdata struct of_device_id of_bus_ids[] = {
-	{ .compatible = "simple-bus" },
-	{},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-	return 0;
-}
-machine_device_initcall(mgsuvd, declare_of_platform_devices);
-
-static int __init mgsuvd_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-	return of_flat_dt_is_compatible(root, "keymile,mgsuvd");
-}
-
-define_machine(mgsuvd) {
-	.name           = "MGSUVD",
-	.probe          = mgsuvd_probe,
-	.setup_arch     = mgsuvd_setup_arch,
-	.init_IRQ       = mpc8xx_pics_init,
-	.get_irq        = mpc8xx_get_irq,
-	.restart        = mpc8xx_restart,
-	.calibrate_decr = mpc8xx_calibrate_decr,
-	.set_rtc_time   = mpc8xx_set_rtc_time,
-	.get_rtc_time   = mpc8xx_get_rtc_time,
-};
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index e3e379c..c48b66a 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -93,6 +93,7 @@ static void msic_dcr_write(struct axon_msic *msic, unsigned int dcr_n, u32 val)
 
 static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	struct axon_msic *msic = get_irq_data(irq);
 	u32 write_offset, msi;
 	int idx;
@@ -145,7 +146,7 @@ static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 		msic->read_offset &= MSIC_FIFO_SIZE_MASK;
 	}
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static struct axon_msic *find_msi_translator(struct pci_dev *dev)
@@ -328,7 +329,7 @@ static struct irq_host_ops msic_host_ops = {
 	.map	= msic_host_map,
 };
 
-static int axon_msi_shutdown(struct platform_device *device)
+static void axon_msi_shutdown(struct platform_device *device)
 {
 	struct axon_msic *msic = dev_get_drvdata(&device->dev);
 	u32 tmp;
@@ -338,12 +339,9 @@ static int axon_msi_shutdown(struct platform_device *device)
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
-
-	return 0;
 }
 
-static int axon_msi_probe(struct platform_device *device,
-			  const struct of_device_id *device_id)
+static int axon_msi_probe(struct platform_device *device)
 {
 	struct device_node *dn = device->dev.of_node;
 	struct axon_msic *msic;
@@ -446,7 +444,7 @@ static const struct of_device_id axon_msi_device_id[] = {
 	{}
 };
 
-static struct of_platform_driver axon_msi_driver = {
+static struct platform_driver axon_msi_driver = {
 	.probe		= axon_msi_probe,
 	.shutdown	= axon_msi_shutdown,
 	.driver = {
@@ -458,7 +456,7 @@ static struct of_platform_driver axon_msi_driver = {
 
 static int __init axon_msi_init(void)
 {
-	return of_register_platform_driver(&axon_msi_driver);
+	return platform_driver_register(&axon_msi_driver);
 }
 subsys_initcall(axon_msi_init);
 
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
index 682af97..0b8f7d7 100644
--- a/arch/powerpc/platforms/cell/beat_interrupt.c
+++ b/arch/powerpc/platforms/cell/beat_interrupt.c
@@ -61,59 +61,59 @@ static inline void beatic_update_irq_mask(unsigned int irq_plug)
 		panic("Failed to set mask IRQ!");
 }
 
-static void beatic_mask_irq(unsigned int irq_plug)
+static void beatic_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_enable[d->irq/64] &= ~(1UL << (63 - (d->irq%64)));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
-static void beatic_unmask_irq(unsigned int irq_plug)
+static void beatic_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_enable[d->irq/64] |= 1UL << (63 - (d->irq%64));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
-static void beatic_ack_irq(unsigned int irq_plug)
+static void beatic_ack_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_ack[d->irq/64] &= ~(1UL << (63 - (d->irq%64)));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
-static void beatic_end_irq(unsigned int irq_plug)
+static void beatic_end_irq(struct irq_data *d)
 {
 	s64 err;
 	unsigned long flags;
 
-	err = beat_downcount_of_interrupt(irq_plug);
+	err = beat_downcount_of_interrupt(d->irq);
 	if (err != 0) {
 		if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
 			panic("Failed to downcount IRQ! Error = %16llx", err);
 
-		printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
+		printk(KERN_ERR "IRQ over-downcounted, plug %d\n", d->irq);
 	}
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_ack[d->irq/64] |= 1UL << (63 - (d->irq%64));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
 static struct irq_chip beatic_pic = {
 	.name = "CELL-BEAT",
-	.unmask = beatic_unmask_irq,
-	.mask = beatic_mask_irq,
-	.eoi = beatic_end_irq,
+	.irq_unmask = beatic_unmask_irq,
+	.irq_mask = beatic_mask_irq,
+	.irq_eoi = beatic_end_irq,
 };
 
 /*
@@ -232,7 +232,7 @@ unsigned int beatic_get_irq(void)
 
 	ret = beatic_get_irq_plug();
 	if (ret != NO_IRQ)
-		beatic_ack_irq(ret);
+		beatic_ack_irq(irq_get_irq_data(ret));
 	return ret;
 }
 
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 10eb1a4..624d26e 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -72,15 +72,15 @@ static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
 		return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
 }
 
-static void iic_mask(unsigned int irq)
+static void iic_mask(struct irq_data *d)
 {
 }
 
-static void iic_unmask(unsigned int irq)
+static void iic_unmask(struct irq_data *d)
 {
 }
 
-static void iic_eoi(unsigned int irq)
+static void iic_eoi(struct irq_data *d)
 {
 	struct iic *iic = &__get_cpu_var(cpu_iic);
 	out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
@@ -89,19 +89,21 @@ static void iic_eoi(unsigned int irq)
 
 static struct irq_chip iic_chip = {
 	.name = "CELL-IIC",
-	.mask = iic_mask,
-	.unmask = iic_unmask,
-	.eoi = iic_eoi,
+	.irq_mask = iic_mask,
+	.irq_unmask = iic_unmask,
+	.irq_eoi = iic_eoi,
 };
 
 
-static void iic_ioexc_eoi(unsigned int irq)
+static void iic_ioexc_eoi(struct irq_data *d)
 {
 }
 
 static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct cbe_iic_regs __iomem *node_iic = (void __iomem *)desc->handler_data;
+	struct irq_chip *chip = get_irq_desc_chip(desc);
+	struct cbe_iic_regs __iomem *node_iic =
+		(void __iomem *)get_irq_desc_data(desc);
 	unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
 	unsigned long bits, ack;
 	int cascade;
@@ -128,15 +130,15 @@ static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
 		if (ack)
 			out_be64(&node_iic->iic_is, ack);
 	}
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 
 static struct irq_chip iic_ioexc_chip = {
 	.name = "CELL-IOEX",
-	.mask = iic_mask,
-	.unmask = iic_unmask,
-	.eoi = iic_ioexc_eoi,
+	.irq_mask = iic_mask,
+	.irq_unmask = iic_unmask,
+	.irq_eoi = iic_ioexc_eoi,
 };
 
 /* Get an IRQ number from the pending state register of the IIC */
@@ -237,6 +239,8 @@ extern int noirqdebug;
 
 static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
+
 	raw_spin_lock(&desc->lock);
 
 	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
@@ -275,7 +279,7 @@ static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
 
 	desc->status &= ~IRQ_INPROGRESS;
 out_eoi:
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 }
 
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index 6919957..6a28d02 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -187,13 +187,15 @@ machine_subsys_initcall(cell, cell_publish_devices);
 
 static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct mpic *mpic = desc->handler_data;
+	struct irq_chip *chip = get_irq_desc_chip(desc);
+	struct mpic *mpic = get_irq_desc_data(desc);
 	unsigned int virq;
 
 	virq = mpic_get_one_irq(mpic);
 	if (virq != NO_IRQ)
 		generic_handle_irq(virq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init mpic_init_IRQ(void)
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c
index 3f2e557..b38cdfc 100644
--- a/arch/powerpc/platforms/cell/spider-pic.c
+++ b/arch/powerpc/platforms/cell/spider-pic.c
@@ -79,30 +79,30 @@ static void __iomem *spider_get_irq_config(struct spider_pic *pic,
 	return pic->regs + TIR_CFGA + 8 * src;
 }
 
-static void spider_unmask_irq(unsigned int virq)
+static void spider_unmask_irq(struct irq_data *d)
 {
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
 
 	out_be32(cfg, in_be32(cfg) | 0x30000000u);
 }
 
-static void spider_mask_irq(unsigned int virq)
+static void spider_mask_irq(struct irq_data *d)
 {
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
 
 	out_be32(cfg, in_be32(cfg) & ~0x30000000u);
 }
 
-static void spider_ack_irq(unsigned int virq)
+static void spider_ack_irq(struct irq_data *d)
 {
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	unsigned int src = irq_map[virq].hwirq;
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	unsigned int src = irq_map[d->irq].hwirq;
 
 	/* Reset edge detection logic if necessary
 	 */
-	if (irq_to_desc(virq)->status & IRQ_LEVEL)
+	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
 		return;
 
 	/* Only interrupts 47 to 50 can be set to edge */
@@ -113,13 +113,13 @@ static void spider_ack_irq(unsigned int virq)
 	out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
 }
 
-static int spider_set_irq_type(unsigned int virq, unsigned int type)
+static int spider_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	unsigned int hw = irq_map[virq].hwirq;
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	unsigned int hw = irq_map[d->irq].hwirq;
 	void __iomem *cfg = spider_get_irq_config(pic, hw);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	u32 old_mask;
 	u32 ic;
 
@@ -169,10 +169,10 @@ static int spider_set_irq_type(unsigned int virq, unsigned int type)
 
 static struct irq_chip spider_pic = {
 	.name = "SPIDER",
-	.unmask = spider_unmask_irq,
-	.mask = spider_mask_irq,
-	.ack = spider_ack_irq,
-	.set_type = spider_set_irq_type,
+	.irq_unmask = spider_unmask_irq,
+	.irq_mask = spider_mask_irq,
+	.irq_ack = spider_ack_irq,
+	.irq_set_type = spider_set_irq_type,
 };
 
 static int spider_host_map(struct irq_host *h, unsigned int virq,
@@ -207,7 +207,8 @@ static struct irq_host_ops spider_host_ops = {
 
 static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct spider_pic *pic = desc->handler_data;
+	struct irq_chip *chip = get_irq_desc_chip(desc);
+	struct spider_pic *pic = get_irq_desc_data(desc);
 	unsigned int cs, virq;
 
 	cs = in_be32(pic->regs + TIR_CS) >> 24;
@@ -215,9 +216,11 @@ static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 		virq = NO_IRQ;
 	else
 		virq = irq_linear_revmap(pic->host, cs);
+
 	if (virq != NO_IRQ)
 		generic_handle_irq(virq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 /* For hooking up the cascace we have a problem. Our device-tree is
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 187a7d3..a3d2ce5 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -70,7 +70,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
 	if (!IS_ERR(tmp)) {
 		struct nameidata nd;
 
-		ret = path_lookup(tmp, LOOKUP_PARENT, &nd);
+		ret = kern_path_parent(tmp, &nd);
 		if (!ret) {
 			nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
 			ret = spufs_create(&nd, flags, mode, neighbor);
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 8553cc4..4c12884 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -365,10 +365,13 @@ void __init chrp_setup_arch(void)
 
 static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 /*
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
index c278bd3..0aca0e2 100644
--- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c
@@ -46,10 +46,10 @@
  *
  */
 
-static void flipper_pic_mask_and_ack(unsigned int virq)
+static void flipper_pic_mask_and_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 	u32 mask = 1 << irq;
 
 	clrbits32(io_base + FLIPPER_IMR, mask);
@@ -57,27 +57,27 @@ static void flipper_pic_mask_and_ack(unsigned int virq)
 	out_be32(io_base + FLIPPER_ICR, mask);
 }
 
-static void flipper_pic_ack(unsigned int virq)
+static void flipper_pic_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	/* this is at least needed for RSW */
 	out_be32(io_base + FLIPPER_ICR, 1 << irq);
 }
 
-static void flipper_pic_mask(unsigned int virq)
+static void flipper_pic_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	clrbits32(io_base + FLIPPER_IMR, 1 << irq);
 }
 
-static void flipper_pic_unmask(unsigned int virq)
+static void flipper_pic_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	setbits32(io_base + FLIPPER_IMR, 1 << irq);
 }
@@ -85,10 +85,10 @@ static void flipper_pic_unmask(unsigned int virq)
 
 static struct irq_chip flipper_pic = {
 	.name		= "flipper-pic",
-	.ack		= flipper_pic_ack,
-	.mask_ack	= flipper_pic_mask_and_ack,
-	.mask		= flipper_pic_mask,
-	.unmask		= flipper_pic_unmask,
+	.irq_ack	= flipper_pic_ack,
+	.irq_mask_ack	= flipper_pic_mask_and_ack,
+	.irq_mask	= flipper_pic_mask,
+	.irq_unmask	= flipper_pic_unmask,
 };
 
 /*
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
index a771f91..35e448b 100644
--- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
+++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
@@ -41,36 +41,36 @@
  *
  */
 
-static void hlwd_pic_mask_and_ack(unsigned int virq)
+static void hlwd_pic_mask_and_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 	u32 mask = 1 << irq;
 
 	clrbits32(io_base + HW_BROADWAY_IMR, mask);
 	out_be32(io_base + HW_BROADWAY_ICR, mask);
 }
 
-static void hlwd_pic_ack(unsigned int virq)
+static void hlwd_pic_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
 }
 
-static void hlwd_pic_mask(unsigned int virq)
+static void hlwd_pic_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
 }
 
-static void hlwd_pic_unmask(unsigned int virq)
+static void hlwd_pic_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
 }
@@ -78,10 +78,10 @@ static void hlwd_pic_unmask(unsigned int virq)
 
 static struct irq_chip hlwd_pic = {
 	.name		= "hlwd-pic",
-	.ack		= hlwd_pic_ack,
-	.mask_ack	= hlwd_pic_mask_and_ack,
-	.mask		= hlwd_pic_mask,
-	.unmask		= hlwd_pic_unmask,
+	.irq_ack	= hlwd_pic_ack,
+	.irq_mask_ack	= hlwd_pic_mask_and_ack,
+	.irq_mask	= hlwd_pic_mask,
+	.irq_unmask	= hlwd_pic_unmask,
 };
 
 /*
@@ -129,11 +129,12 @@ static unsigned int __hlwd_pic_get_irq(struct irq_host *h)
 static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
 				      struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	struct irq_host *irq_host = get_irq_data(cascade_virq);
 	unsigned int virq;
 
 	raw_spin_lock(&desc->lock);
-	desc->chip->mask(cascade_virq); /* IRQ_LEVEL */
+	chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */
 	raw_spin_unlock(&desc->lock);
 
 	virq = __hlwd_pic_get_irq(irq_host);
@@ -143,9 +144,9 @@ static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
 		pr_err("spurious interrupt!\n");
 
 	raw_spin_lock(&desc->lock);
-	desc->chip->ack(cascade_virq); /* IRQ_LEVEL */
-	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-		desc->chip->unmask(cascade_virq);
+	chip->irq_ack(&desc->irq_data); /* IRQ_LEVEL */
+	if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
+		chip->irq_unmask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 }
 
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index ba446bf..4fb96f0 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -167,11 +167,11 @@ static void pci_event_handler(struct HvLpEvent *event)
  * This will be called by device drivers (via enable_IRQ)
  * to enable INTA in the bridge interrupt status register.
  */
-static void iseries_enable_IRQ(unsigned int irq)
+static void iseries_enable_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	/* The IRQ has already been locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -184,23 +184,23 @@ static void iseries_enable_IRQ(unsigned int irq)
 }
 
 /* This is called by iseries_activate_IRQs */
-static unsigned int iseries_startup_IRQ(unsigned int irq)
+static unsigned int iseries_startup_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	bus = REAL_IRQ_TO_BUS(rirq);
 	function = REAL_IRQ_TO_FUNC(rirq);
 	dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
 
 	/* Link the IRQ number to the bridge */
-	HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq);
+	HvCallXm_connectBusUnit(bus, sub_bus, dev_id, d->irq);
 
 	/* Unmask bridge interrupts in the FISR */
 	mask = 0x01010000 << function;
 	HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
-	iseries_enable_IRQ(irq);
+	iseries_enable_IRQ(d);
 	return 0;
 }
 
@@ -215,21 +215,26 @@ void __init iSeries_activate_IRQs()
 
 	for_each_irq (irq) {
 		struct irq_desc *desc = irq_to_desc(irq);
+		struct irq_chip *chip;
 
-		if (desc && desc->chip && desc->chip->startup) {
+		if (!desc)
+			continue;
+
+		chip = get_irq_desc_chip(desc);
+		if (chip && chip->irq_startup) {
 			raw_spin_lock_irqsave(&desc->lock, flags);
-			desc->chip->startup(irq);
+			chip->irq_startup(&desc->irq_data);
 			raw_spin_unlock_irqrestore(&desc->lock, flags);
 		}
 	}
 }
 
 /*  this is not called anywhere currently */
-static void iseries_shutdown_IRQ(unsigned int irq)
+static void iseries_shutdown_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	/* irq should be locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -248,11 +253,11 @@ static void iseries_shutdown_IRQ(unsigned int irq)
  * This will be called by device drivers (via disable_IRQ)
  * to disable INTA in the bridge interrupt status register.
  */
-static void iseries_disable_IRQ(unsigned int irq)
+static void iseries_disable_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	/* The IRQ has already been locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -264,9 +269,9 @@ static void iseries_disable_IRQ(unsigned int irq)
 	HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
 }
 
-static void iseries_end_IRQ(unsigned int irq)
+static void iseries_end_IRQ(struct irq_data *d)
 {
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
 		(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
@@ -274,11 +279,11 @@ static void iseries_end_IRQ(unsigned int irq)
 
 static struct irq_chip iseries_pic = {
 	.name		= "iSeries",
-	.startup	= iseries_startup_IRQ,
-	.shutdown	= iseries_shutdown_IRQ,
-	.unmask		= iseries_enable_IRQ,
-	.mask		= iseries_disable_IRQ,
-	.eoi		= iseries_end_IRQ
+	.irq_startup	= iseries_startup_IRQ,
+	.irq_shutdown	= iseries_shutdown_IRQ,
+	.irq_unmask	= iseries_enable_IRQ,
+	.irq_mask	= iseries_disable_IRQ,
+	.irq_eoi	= iseries_end_IRQ
 };
 
 /*
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c
index a5d907b..9886296 100644
--- a/arch/powerpc/platforms/pasemi/gpio_mdio.c
+++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c
@@ -216,8 +216,7 @@ static int gpio_mdio_reset(struct mii_bus *bus)
 }
 
 
-static int __devinit gpio_mdio_probe(struct platform_device *ofdev,
-				     const struct of_device_id *match)
+static int __devinit gpio_mdio_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -299,7 +298,7 @@ static struct of_device_id gpio_mdio_match[] =
 };
 MODULE_DEVICE_TABLE(of, gpio_mdio_match);
 
-static struct of_platform_driver gpio_mdio_driver =
+static struct platform_driver gpio_mdio_driver =
 {
 	.probe		= gpio_mdio_probe,
 	.remove		= gpio_mdio_remove,
@@ -326,13 +325,13 @@ int gpio_mdio_init(void)
 	if (!gpio_regs)
 		return -ENODEV;
 
-	return of_register_platform_driver(&gpio_mdio_driver);
+	return platform_driver_register(&gpio_mdio_driver);
 }
 module_init(gpio_mdio_init);
 
 void gpio_mdio_exit(void)
 {
-	of_unregister_platform_driver(&gpio_mdio_driver);
+	platform_driver_unregister(&gpio_mdio_driver);
 	if (gpio_regs)
 		iounmap(gpio_regs);
 }
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index f372ec1..a6067b3 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -240,7 +240,7 @@ static __init void pas_init_IRQ(void)
 		nmi_virq = irq_create_mapping(NULL, *nmiprop);
 		mpic_irq_set_priority(nmi_virq, 15);
 		set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
-		mpic_unmask_irq(nmi_virq);
+		mpic_unmask_irq(irq_get_irq_data(nmi_virq));
 	}
 
 	of_node_put(mpic_node);
@@ -266,7 +266,7 @@ static int pas_machine_check_handler(struct pt_regs *regs)
 	if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
 		printk(KERN_ERR "NMI delivered\n");
 		debugger(regs);
-		mpic_end_irq(nmi_virq);
+		mpic_end_irq(irq_get_irq_data(nmi_virq));
 		goto out;
 	}
 
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 415ca6d..04af5f4 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -429,7 +429,7 @@ static u32 read_gpio(struct device_node *np)
 	return offset;
 }
 
-static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
+static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	/* Ok, this could be made a bit smarter, but let's be robust for now. We
 	 * always force a speed change to high speed before sleep, to make sure
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 890d5f7..c55812b 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -82,9 +82,9 @@ static void __pmac_retrigger(unsigned int irq_nr)
 	}
 }
 
-static void pmac_mask_and_ack_irq(unsigned int virq)
+static void pmac_mask_and_ack_irq(struct irq_data *d)
 {
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
         unsigned long flags;
@@ -104,9 +104,9 @@ static void pmac_mask_and_ack_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
-static void pmac_ack_irq(unsigned int virq)
+static void pmac_ack_irq(struct irq_data *d)
 {
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
         unsigned long flags;
@@ -149,15 +149,15 @@ static void __pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
 /* When an irq gets requested for the first client, if it's an
  * edge interrupt, we clear any previous one on the controller
  */
-static unsigned int pmac_startup_irq(unsigned int virq)
+static unsigned int pmac_startup_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
-	if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0)
+	if ((irq_to_desc(d->irq)->status & IRQ_LEVEL) == 0)
 		out_le32(&pmac_irq_hw[i]->ack, bit);
         __set_bit(src, ppc_cached_irq_mask);
         __pmac_set_irq_mask(src, 0);
@@ -166,10 +166,10 @@ static unsigned int pmac_startup_irq(unsigned int virq)
 	return 0;
 }
 
-static void pmac_mask_irq(unsigned int virq)
+static void pmac_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
         __clear_bit(src, ppc_cached_irq_mask);
@@ -177,10 +177,10 @@ static void pmac_mask_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
-static void pmac_unmask_irq(unsigned int virq)
+static void pmac_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
 	__set_bit(src, ppc_cached_irq_mask);
@@ -188,24 +188,24 @@ static void pmac_unmask_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
-static int pmac_retrigger(unsigned int virq)
+static int pmac_retrigger(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
-	__pmac_retrigger(irq_map[virq].hwirq);
+	__pmac_retrigger(irq_map[d->irq].hwirq);
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 	return 1;
 }
 
 static struct irq_chip pmac_pic = {
 	.name		= "PMAC-PIC",
-	.startup	= pmac_startup_irq,
-	.mask		= pmac_mask_irq,
-	.ack		= pmac_ack_irq,
-	.mask_ack	= pmac_mask_and_ack_irq,
-	.unmask		= pmac_unmask_irq,
-	.retrigger	= pmac_retrigger,
+	.irq_startup	= pmac_startup_irq,
+	.irq_mask	= pmac_mask_irq,
+	.irq_ack	= pmac_ack_irq,
+	.irq_mask_ack	= pmac_mask_and_ack_irq,
+	.irq_unmask	= pmac_unmask_irq,
+	.irq_retrigger	= pmac_retrigger,
 };
 
 static irqreturn_t gatwick_action(int cpl, void *dev_id)
@@ -472,12 +472,14 @@ int of_irq_map_oldworld(struct device_node *device, int index,
 
 static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct mpic *mpic = desc->handler_data;
-
+	struct irq_chip *chip = get_irq_desc_chip(desc);
+	struct mpic *mpic = get_irq_desc_data(desc);
 	unsigned int cascade_irq = mpic_get_one_irq(mpic);
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
@@ -707,7 +709,7 @@ static int pmacpic_resume(struct sys_device *sysdev)
 	mb();
 	for (i = 0; i < max_real_irqs; ++i)
 		if (test_bit(i, sleep_save_mask))
-			pmac_unmask_irq(i);
+			pmac_unmask_irq(irq_get_irq_data(i));
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 92290ff..3988c86 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -99,16 +99,16 @@ static DEFINE_PER_CPU(struct ps3_private, ps3_private);
  * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
  */
 
-static void ps3_chip_mask(unsigned int virq)
+static void ps3_chip_mask(struct irq_data *d)
 {
-	struct ps3_private *pd = get_irq_chip_data(virq);
+	struct ps3_private *pd = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
-		pd->thread_id, virq);
+		pd->thread_id, d->irq);
 
 	local_irq_save(flags);
-	clear_bit(63 - virq, &pd->bmp.mask);
+	clear_bit(63 - d->irq, &pd->bmp.mask);
 	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
 	local_irq_restore(flags);
 }
@@ -120,16 +120,16 @@ static void ps3_chip_mask(unsigned int virq)
  * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
  */
 
-static void ps3_chip_unmask(unsigned int virq)
+static void ps3_chip_unmask(struct irq_data *d)
 {
-	struct ps3_private *pd = get_irq_chip_data(virq);
+	struct ps3_private *pd = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
-		pd->thread_id, virq);
+		pd->thread_id, d->irq);
 
 	local_irq_save(flags);
-	set_bit(63 - virq, &pd->bmp.mask);
+	set_bit(63 - d->irq, &pd->bmp.mask);
 	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
 	local_irq_restore(flags);
 }
@@ -141,10 +141,10 @@ static void ps3_chip_unmask(unsigned int virq)
  * Calls lv1_end_of_interrupt_ext().
  */
 
-static void ps3_chip_eoi(unsigned int virq)
+static void ps3_chip_eoi(struct irq_data *d)
 {
-	const struct ps3_private *pd = get_irq_chip_data(virq);
-	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
+	const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
+	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
 }
 
 /**
@@ -153,9 +153,9 @@ static void ps3_chip_eoi(unsigned int virq)
 
 static struct irq_chip ps3_irq_chip = {
 	.name = "ps3",
-	.mask = ps3_chip_mask,
-	.unmask = ps3_chip_unmask,
-	.eoi = ps3_chip_eoi,
+	.irq_mask = ps3_chip_mask,
+	.irq_unmask = ps3_chip_unmask,
+	.irq_eoi = ps3_chip_eoi,
 };
 
 /**
@@ -202,7 +202,7 @@ static int ps3_virq_setup(enum ps3_cpu_binding cpu, unsigned long outlet,
 		goto fail_set;
 	}
 
-	ps3_chip_mask(*virq);
+	ps3_chip_mask(irq_get_irq_data(*virq));
 
 	return result;
 
@@ -296,7 +296,7 @@ int ps3_irq_plug_destroy(unsigned int virq)
 	pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
 		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
 
@@ -357,7 +357,7 @@ int ps3_event_receive_port_destroy(unsigned int virq)
 
 	pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -492,7 +492,7 @@ int ps3_io_irq_destroy(unsigned int virq)
 	int result;
 	unsigned long outlet = virq_to_hw(virq);
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	/*
 	 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
@@ -553,7 +553,7 @@ int ps3_vuart_irq_destroy(unsigned int virq)
 {
 	int result;
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 	result = lv1_deconfigure_virtual_uart_irq();
 
 	if (result) {
@@ -605,7 +605,7 @@ int ps3_spe_irq_destroy(unsigned int virq)
 {
 	int result;
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	result = ps3_irq_plug_destroy(virq);
 	BUG_ON(result);
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
index f480386..3cafc30 100644
--- a/arch/powerpc/platforms/pseries/cmm.c
+++ b/arch/powerpc/platforms/pseries/cmm.c
@@ -508,12 +508,7 @@ static int cmm_memory_isolate_cb(struct notifier_block *self,
 	if (action == MEM_ISOLATE_COUNT)
 		ret = cmm_count_pages(arg);
 
-	if (ret)
-		ret = notifier_from_errno(ret);
-	else
-		ret = NOTIFY_OK;
-
-	return ret;
+	return notifier_from_errno(ret);
 }
 
 static struct notifier_block cmm_mem_isolate_nb = {
@@ -635,12 +630,7 @@ static int cmm_memory_cb(struct notifier_block *self,
 		break;
 	}
 
-	if (ret)
-		ret = notifier_from_errno(ret);
-	else
-		ret = NOTIFY_OK;
-
-	return ret;
+	return notifier_from_errno(ret);
 }
 
 static struct notifier_block cmm_mem_nb = {
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 17a11c8..3cc4d10 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -876,7 +876,7 @@ void eeh_restore_bars(struct pci_dn *pdn)
  *
  * Save the values of the device bars. Unlike the restore
  * routine, this routine is *not* recursive. This is because
- * PCI devices are added individuallly; but, for the restore,
+ * PCI devices are added individually; but, for the restore,
  * an entire slot is reset at a time.
  */
 static void eeh_save_bars(struct pci_dn *pdn)
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index bc88036..33867ec 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -17,6 +17,54 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/sparsemem.h>
 
+static unsigned long get_memblock_size(void)
+{
+	struct device_node *np;
+	unsigned int memblock_size = 0;
+
+	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (np) {
+		const unsigned long *size;
+
+		size = of_get_property(np, "ibm,lmb-size", NULL);
+		memblock_size = size ? *size : 0;
+
+		of_node_put(np);
+	} else {
+		unsigned int memzero_size = 0;
+		const unsigned int *regs;
+
+		np = of_find_node_by_path("/memory@0");
+		if (np) {
+			regs = of_get_property(np, "reg", NULL);
+			memzero_size = regs ? regs[3] : 0;
+			of_node_put(np);
+		}
+
+		if (memzero_size) {
+			/* We now know the size of memory@0, use this to find
+			 * the first memoryblock and get its size.
+			 */
+			char buf[64];
+
+			sprintf(buf, "/memory@%x", memzero_size);
+			np = of_find_node_by_path(buf);
+			if (np) {
+				regs = of_get_property(np, "reg", NULL);
+				memblock_size = regs ? regs[3] : 0;
+				of_node_put(np);
+			}
+		}
+	}
+
+	return memblock_size;
+}
+
+unsigned long memory_block_size_bytes(void)
+{
+	return get_memblock_size();
+}
+
 static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
 {
 	unsigned long start, start_pfn;
@@ -127,30 +175,22 @@ static int pseries_add_memory(struct device_node *np)
 
 static int pseries_drconf_memory(unsigned long *base, unsigned int action)
 {
-	struct device_node *np;
-	const unsigned long *lmb_size;
+	unsigned long memblock_size;
 	int rc;
 
-	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
-	if (!np)
+	memblock_size = get_memblock_size();
+	if (!memblock_size)
 		return -EINVAL;
 
-	lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
-	if (!lmb_size) {
-		of_node_put(np);
-		return -EINVAL;
-	}
-
 	if (action == PSERIES_DRCONF_MEM_ADD) {
-		rc = memblock_add(*base, *lmb_size);
+		rc = memblock_add(*base, memblock_size);
 		rc = (rc < 0) ? -EINVAL : 0;
 	} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
-		rc = pseries_remove_memblock(*base, *lmb_size);
+		rc = pseries_remove_memblock(*base, memblock_size);
 	} else {
 		rc = -EINVAL;
 	}
 
-	of_node_put(np);
 	return rc;
 }
 
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index edea60b..154c464 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/crash_dump.h>
+#include <linux/memory.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -45,6 +46,7 @@
 #include <asm/tce.h>
 #include <asm/ppc-pci.h>
 #include <asm/udbg.h>
+#include <asm/mmzone.h>
 
 #include "plpar_wrappers.h"
 
@@ -270,6 +272,152 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
 	return tce_ret;
 }
 
+/* this is compatable with cells for the device tree property */
+struct dynamic_dma_window_prop {
+	__be32	liobn;		/* tce table number */
+	__be64	dma_base;	/* address hi,lo */
+	__be32	tce_shift;	/* ilog2(tce_page_size) */
+	__be32	window_shift;	/* ilog2(tce_window_size) */
+};
+
+struct direct_window {
+	struct device_node *device;
+	const struct dynamic_dma_window_prop *prop;
+	struct list_head list;
+};
+
+/* Dynamic DMA Window support */
+struct ddw_query_response {
+	u32 windows_available;
+	u32 largest_available_block;
+	u32 page_size;
+	u32 migration_capable;
+};
+
+struct ddw_create_response {
+	u32 liobn;
+	u32 addr_hi;
+	u32 addr_lo;
+};
+
+static LIST_HEAD(direct_window_list);
+/* prevents races between memory on/offline and window creation */
+static DEFINE_SPINLOCK(direct_window_list_lock);
+/* protects initializing window twice for same device */
+static DEFINE_MUTEX(direct_window_init_mutex);
+#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
+
+static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
+					unsigned long num_pfn, const void *arg)
+{
+	const struct dynamic_dma_window_prop *maprange = arg;
+	int rc;
+	u64 tce_size, num_tce, dma_offset, next;
+	u32 tce_shift;
+	long limit;
+
+	tce_shift = be32_to_cpu(maprange->tce_shift);
+	tce_size = 1ULL << tce_shift;
+	next = start_pfn << PAGE_SHIFT;
+	num_tce = num_pfn << PAGE_SHIFT;
+
+	/* round back to the beginning of the tce page size */
+	num_tce += next & (tce_size - 1);
+	next &= ~(tce_size - 1);
+
+	/* covert to number of tces */
+	num_tce |= tce_size - 1;
+	num_tce >>= tce_shift;
+
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, num_tce, 512);
+		dma_offset = next + be64_to_cpu(maprange->dma_base);
+
+		rc = plpar_tce_stuff((u64)be32_to_cpu(maprange->liobn),
+					     dma_offset,
+					     0, limit);
+		num_tce -= limit;
+	} while (num_tce > 0 && !rc);
+
+	return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
+					unsigned long num_pfn, const void *arg)
+{
+	const struct dynamic_dma_window_prop *maprange = arg;
+	u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn;
+	u32 tce_shift;
+	u64 rc = 0;
+	long l, limit;
+
+	local_irq_disable();	/* to protect tcep and the page behind it */
+	tcep = __get_cpu_var(tce_page);
+
+	if (!tcep) {
+		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
+		if (!tcep) {
+			local_irq_enable();
+			return -ENOMEM;
+		}
+		__get_cpu_var(tce_page) = tcep;
+	}
+
+	proto_tce = TCE_PCI_READ | TCE_PCI_WRITE;
+
+	liobn = (u64)be32_to_cpu(maprange->liobn);
+	tce_shift = be32_to_cpu(maprange->tce_shift);
+	tce_size = 1ULL << tce_shift;
+	next = start_pfn << PAGE_SHIFT;
+	num_tce = num_pfn << PAGE_SHIFT;
+
+	/* round back to the beginning of the tce page size */
+	num_tce += next & (tce_size - 1);
+	next &= ~(tce_size - 1);
+
+	/* covert to number of tces */
+	num_tce |= tce_size - 1;
+	num_tce >>= tce_shift;
+
+	/* We can map max one pageful of TCEs at a time */
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, num_tce, 4096/TCE_ENTRY_SIZE);
+		dma_offset = next + be64_to_cpu(maprange->dma_base);
+
+		for (l = 0; l < limit; l++) {
+			tcep[l] = proto_tce | next;
+			next += tce_size;
+		}
+
+		rc = plpar_tce_put_indirect(liobn,
+					    dma_offset,
+					    (u64)virt_to_abs(tcep),
+					    limit);
+
+		num_tce -= limit;
+	} while (num_tce > 0 && !rc);
+
+	/* error cleanup: caller will clear whole range */
+
+	local_irq_enable();
+	return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP_walk(unsigned long start_pfn,
+		unsigned long num_pfn, void *arg)
+{
+	return tce_setrange_multi_pSeriesLP(start_pfn, num_pfn, arg);
+}
+
+
 #ifdef CONFIG_PCI
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
@@ -495,6 +643,329 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
 		       pci_name(dev));
 }
 
+static int __read_mostly disable_ddw;
+
+static int __init disable_ddw_setup(char *str)
+{
+	disable_ddw = 1;
+	printk(KERN_INFO "ppc iommu: disabling ddw.\n");
+
+	return 0;
+}
+
+early_param("disable_ddw", disable_ddw_setup);
+
+static void remove_ddw(struct device_node *np)
+{
+	struct dynamic_dma_window_prop *dwp;
+	struct property *win64;
+	const u32 *ddr_avail;
+	u64 liobn;
+	int len, ret;
+
+	ddr_avail = of_get_property(np, "ibm,ddw-applicable", &len);
+	win64 = of_find_property(np, DIRECT64_PROPNAME, NULL);
+	if (!win64 || !ddr_avail || len < 3 * sizeof(u32))
+		return;
+
+	dwp = win64->value;
+	liobn = (u64)be32_to_cpu(dwp->liobn);
+
+	/* clear the whole window, note the arg is in kernel pages */
+	ret = tce_clearrange_multi_pSeriesLP(0,
+		1ULL << (be32_to_cpu(dwp->window_shift) - PAGE_SHIFT), dwp);
+	if (ret)
+		pr_warning("%s failed to clear tces in window.\n",
+			 np->full_name);
+	else
+		pr_debug("%s successfully cleared tces in window.\n",
+			 np->full_name);
+
+	ret = rtas_call(ddr_avail[2], 1, 1, NULL, liobn);
+	if (ret)
+		pr_warning("%s: failed to remove direct window: rtas returned "
+			"%d to ibm,remove-pe-dma-window(%x) %llx\n",
+			np->full_name, ret, ddr_avail[2], liobn);
+	else
+		pr_debug("%s: successfully removed direct window: rtas returned "
+			"%d to ibm,remove-pe-dma-window(%x) %llx\n",
+			np->full_name, ret, ddr_avail[2], liobn);
+}
+
+
+static int dupe_ddw_if_already_created(struct pci_dev *dev, struct device_node *pdn)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	struct direct_window *window;
+	const struct dynamic_dma_window_prop *direct64;
+	u64 dma_addr = 0;
+
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	spin_lock(&direct_window_list_lock);
+	/* check if we already created a window and dupe that config if so */
+	list_for_each_entry(window, &direct_window_list, list) {
+		if (window->device == pdn) {
+			direct64 = window->prop;
+			dma_addr = direct64->dma_base;
+			break;
+		}
+	}
+	spin_unlock(&direct_window_list_lock);
+
+	return dma_addr;
+}
+
+static u64 dupe_ddw_if_kexec(struct pci_dev *dev, struct device_node *pdn)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	int len;
+	struct direct_window *window;
+	const struct dynamic_dma_window_prop *direct64;
+	u64 dma_addr = 0;
+
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
+	if (direct64) {
+		window = kzalloc(sizeof(*window), GFP_KERNEL);
+		if (!window) {
+			remove_ddw(pdn);
+		} else {
+			window->device = pdn;
+			window->prop = direct64;
+			spin_lock(&direct_window_list_lock);
+			list_add(&window->list, &direct_window_list);
+			spin_unlock(&direct_window_list_lock);
+			dma_addr = direct64->dma_base;
+		}
+	}
+
+	return dma_addr;
+}
+
+static int query_ddw(struct pci_dev *dev, const u32 *ddr_avail,
+			struct ddw_query_response *query)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	u32 cfg_addr;
+	u64 buid;
+	int ret;
+
+	/*
+	 * Get the config address and phb buid of the PE window.
+	 * Rely on eeh to retrieve this for us.
+	 * Retrieve them from the pci device, not the node with the
+	 * dma-window property
+	 */
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	cfg_addr = pcidn->eeh_config_addr;
+	if (pcidn->eeh_pe_config_addr)
+		cfg_addr = pcidn->eeh_pe_config_addr;
+	buid = pcidn->phb->buid;
+	ret = rtas_call(ddr_avail[0], 3, 5, (u32 *)query,
+		  cfg_addr, BUID_HI(buid), BUID_LO(buid));
+	dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
+		" returned %d\n", ddr_avail[0], cfg_addr, BUID_HI(buid),
+		BUID_LO(buid), ret);
+	return ret;
+}
+
+static int create_ddw(struct pci_dev *dev, const u32 *ddr_avail,
+			struct ddw_create_response *create, int page_shift,
+			int window_shift)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	u32 cfg_addr;
+	u64 buid;
+	int ret;
+
+	/*
+	 * Get the config address and phb buid of the PE window.
+	 * Rely on eeh to retrieve this for us.
+	 * Retrieve them from the pci device, not the node with the
+	 * dma-window property
+	 */
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	cfg_addr = pcidn->eeh_config_addr;
+	if (pcidn->eeh_pe_config_addr)
+		cfg_addr = pcidn->eeh_pe_config_addr;
+	buid = pcidn->phb->buid;
+
+	do {
+		/* extra outputs are LIOBN and dma-addr (hi, lo) */
+		ret = rtas_call(ddr_avail[1], 5, 4, (u32 *)create, cfg_addr,
+				BUID_HI(buid), BUID_LO(buid), page_shift, window_shift);
+	} while (rtas_busy_delay(ret));
+	dev_info(&dev->dev,
+		"ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d "
+		"(liobn = 0x%x starting addr = %x %x)\n", ddr_avail[1],
+		 cfg_addr, BUID_HI(buid), BUID_LO(buid), page_shift,
+		 window_shift, ret, create->liobn, create->addr_hi, create->addr_lo);
+
+	return ret;
+}
+
+/*
+ * If the PE supports dynamic dma windows, and there is space for a table
+ * that can map all pages in a linear offset, then setup such a table,
+ * and record the dma-offset in the struct device.
+ *
+ * dev: the pci device we are checking
+ * pdn: the parent pe node with the ibm,dma_window property
+ * Future: also check if we can remap the base window for our base page size
+ *
+ * returns the dma offset for use by dma_set_mask
+ */
+static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+{
+	int len, ret;
+	struct ddw_query_response query;
+	struct ddw_create_response create;
+	int page_shift;
+	u64 dma_addr, max_addr;
+	struct device_node *dn;
+	const u32 *uninitialized_var(ddr_avail);
+	struct direct_window *window;
+	struct property *uninitialized_var(win64);
+	struct dynamic_dma_window_prop *ddwprop;
+
+	mutex_lock(&direct_window_init_mutex);
+
+	dma_addr = dupe_ddw_if_already_created(dev, pdn);
+	if (dma_addr != 0)
+		goto out_unlock;
+
+	dma_addr = dupe_ddw_if_kexec(dev, pdn);
+	if (dma_addr != 0)
+		goto out_unlock;
+
+	/*
+	 * the ibm,ddw-applicable property holds the tokens for:
+	 * ibm,query-pe-dma-window
+	 * ibm,create-pe-dma-window
+	 * ibm,remove-pe-dma-window
+	 * for the given node in that order.
+	 * the property is actually in the parent, not the PE
+	 */
+	ddr_avail = of_get_property(pdn, "ibm,ddw-applicable", &len);
+	if (!ddr_avail || len < 3 * sizeof(u32))
+		goto out_unlock;
+
+       /*
+	 * Query if there is a second window of size to map the
+	 * whole partition.  Query returns number of windows, largest
+	 * block assigned to PE (partition endpoint), and two bitmasks
+	 * of page sizes: supported and supported for migrate-dma.
+	 */
+	dn = pci_device_to_OF_node(dev);
+	ret = query_ddw(dev, ddr_avail, &query);
+	if (ret != 0)
+		goto out_unlock;
+
+	if (query.windows_available == 0) {
+		/*
+		 * no additional windows are available for this device.
+		 * We might be able to reallocate the existing window,
+		 * trading in for a larger page size.
+		 */
+		dev_dbg(&dev->dev, "no free dynamic windows");
+		goto out_unlock;
+	}
+	if (query.page_size & 4) {
+		page_shift = 24; /* 16MB */
+	} else if (query.page_size & 2) {
+		page_shift = 16; /* 64kB */
+	} else if (query.page_size & 1) {
+		page_shift = 12; /* 4kB */
+	} else {
+		dev_dbg(&dev->dev, "no supported direct page size in mask %x",
+			  query.page_size);
+		goto out_unlock;
+	}
+	/* verify the window * number of ptes will map the partition */
+	/* check largest block * page size > max memory hotplug addr */
+	max_addr = memory_hotplug_max();
+	if (query.largest_available_block < (max_addr >> page_shift)) {
+		dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
+			  "%llu-sized pages\n", max_addr,  query.largest_available_block,
+			  1ULL << page_shift);
+		goto out_unlock;
+	}
+	len = order_base_2(max_addr);
+	win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
+	if (!win64) {
+		dev_info(&dev->dev,
+			"couldn't allocate property for 64bit dma window\n");
+		goto out_unlock;
+	}
+	win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
+	win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
+	if (!win64->name || !win64->value) {
+		dev_info(&dev->dev,
+			"couldn't allocate property name and value\n");
+		goto out_free_prop;
+	}
+
+	ret = create_ddw(dev, ddr_avail, &create, page_shift, len);
+	if (ret != 0)
+		goto out_free_prop;
+
+	ddwprop->liobn = cpu_to_be32(create.liobn);
+	ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2));
+	ddwprop->tce_shift = cpu_to_be32(page_shift);
+	ddwprop->window_shift = cpu_to_be32(len);
+
+	dev_dbg(&dev->dev, "created tce table LIOBN 0x%x for %s\n",
+		  create.liobn, dn->full_name);
+
+	window = kzalloc(sizeof(*window), GFP_KERNEL);
+	if (!window)
+		goto out_clear_window;
+
+	ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
+			win64->value, tce_setrange_multi_pSeriesLP_walk);
+	if (ret) {
+		dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
+			 dn->full_name, ret);
+		goto out_clear_window;
+	}
+
+	ret = prom_add_property(pdn, win64);
+	if (ret) {
+		dev_err(&dev->dev, "unable to add dma window property for %s: %d",
+			 pdn->full_name, ret);
+		goto out_clear_window;
+	}
+
+	window->device = pdn;
+	window->prop = ddwprop;
+	spin_lock(&direct_window_list_lock);
+	list_add(&window->list, &direct_window_list);
+	spin_unlock(&direct_window_list_lock);
+
+	dma_addr = of_read_number(&create.addr_hi, 2);
+	goto out_unlock;
+
+out_clear_window:
+	remove_ddw(pdn);
+
+out_free_prop:
+	kfree(win64->name);
+	kfree(win64->value);
+	kfree(win64);
+
+out_unlock:
+	mutex_unlock(&direct_window_init_mutex);
+	return dma_addr;
+}
+
 static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 {
 	struct device_node *pdn, *dn;
@@ -541,23 +1012,137 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 
 	set_iommu_table_base(&dev->dev, pci->iommu_table);
 }
+
+static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
+{
+	bool ddw_enabled = false;
+	struct device_node *pdn, *dn;
+	struct pci_dev *pdev;
+	const void *dma_window = NULL;
+	u64 dma_offset;
+
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	/* only attempt to use a new window if 64-bit DMA is requested */
+	if (!disable_ddw && dma_mask == DMA_BIT_MASK(64)) {
+		pdev = to_pci_dev(dev);
+
+		dn = pci_device_to_OF_node(pdev);
+		dev_dbg(dev, "node is %s\n", dn->full_name);
+
+		/*
+		 * the device tree might contain the dma-window properties
+		 * per-device and not neccesarily for the bus. So we need to
+		 * search upwards in the tree until we either hit a dma-window
+		 * property, OR find a parent with a table already allocated.
+		 */
+		for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
+				pdn = pdn->parent) {
+			dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
+			if (dma_window)
+				break;
+		}
+		if (pdn && PCI_DN(pdn)) {
+			dma_offset = enable_ddw(pdev, pdn);
+			if (dma_offset != 0) {
+				dev_info(dev, "Using 64-bit direct DMA at offset %llx\n", dma_offset);
+				set_dma_offset(dev, dma_offset);
+				set_dma_ops(dev, &dma_direct_ops);
+				ddw_enabled = true;
+			}
+		}
+	}
+
+	/* fall-through to iommu ops */
+	if (!ddw_enabled) {
+		dev_info(dev, "Using 32-bit DMA via iommu\n");
+		set_dma_ops(dev, &dma_iommu_ops);
+	}
+
+	*dev->dma_mask = dma_mask;
+	return 0;
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries	NULL
 #define pci_dma_dev_setup_pSeries	NULL
 #define pci_dma_bus_setup_pSeriesLP	NULL
 #define pci_dma_dev_setup_pSeriesLP	NULL
+#define dma_set_mask_pSeriesLP		NULL
 #endif /* !CONFIG_PCI */
 
+static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
+		void *data)
+{
+	struct direct_window *window;
+	struct memory_notify *arg = data;
+	int ret = 0;
+
+	switch (action) {
+	case MEM_GOING_ONLINE:
+		spin_lock(&direct_window_list_lock);
+		list_for_each_entry(window, &direct_window_list, list) {
+			ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
+					arg->nr_pages, window->prop);
+			/* XXX log error */
+		}
+		spin_unlock(&direct_window_list_lock);
+		break;
+	case MEM_CANCEL_ONLINE:
+	case MEM_OFFLINE:
+		spin_lock(&direct_window_list_lock);
+		list_for_each_entry(window, &direct_window_list, list) {
+			ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
+					arg->nr_pages, window->prop);
+			/* XXX log error */
+		}
+		spin_unlock(&direct_window_list_lock);
+		break;
+	default:
+		break;
+	}
+	if (ret && action != MEM_CANCEL_ONLINE)
+		return NOTIFY_BAD;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block iommu_mem_nb = {
+	.notifier_call = iommu_mem_notifier,
+};
+
 static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
 {
 	int err = NOTIFY_OK;
 	struct device_node *np = node;
 	struct pci_dn *pci = PCI_DN(np);
+	struct direct_window *window;
 
 	switch (action) {
 	case PSERIES_RECONFIG_REMOVE:
 		if (pci && pci->iommu_table)
 			iommu_free_table(pci->iommu_table, np->full_name);
+
+		spin_lock(&direct_window_list_lock);
+		list_for_each_entry(window, &direct_window_list, list) {
+			if (window->device == np) {
+				list_del(&window->list);
+				kfree(window);
+				break;
+			}
+		}
+		spin_unlock(&direct_window_list_lock);
+
+		/*
+		 * Because the notifier runs after isolation of the
+		 * slot, we are guaranteed any DMA window has already
+		 * been revoked and the TCEs have been marked invalid,
+		 * so we don't need a call to remove_ddw(np). However,
+		 * if an additional notifier action is added before the
+		 * isolate call, we should update this code for
+		 * completeness with such a call.
+		 */
 		break;
 	default:
 		err = NOTIFY_DONE;
@@ -587,6 +1172,7 @@ void iommu_init_early_pSeries(void)
 		ppc_md.tce_get   = tce_get_pSeriesLP;
 		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
 		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
+		ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
@@ -597,6 +1183,7 @@ void iommu_init_early_pSeries(void)
 
 
 	pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
+	register_memory_notifier(&iommu_mem_nb);
 
 	set_pci_dma_ops(&dma_iommu_ops);
 }
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 1164c34..18ac801 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -93,8 +93,18 @@ static void rtas_disable_msi(struct pci_dev *pdev)
 	if (!pdn)
 		return;
 
-	if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
-		pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
+	/*
+	 * disabling MSI with the explicit interface also disables MSI-X
+	 */
+	if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, 0) != 0) {
+		/* 
+		 * may have failed because explicit interface is not
+		 * present
+		 */
+		if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0) {
+			pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
+		}
+	}
 }
 
 static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 7e828ba..419707b 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -16,6 +16,8 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/kmsg_dump.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -30,17 +32,54 @@ static int nvram_fetch, nvram_store;
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
-static long nvram_error_log_index = -1;
-static long nvram_error_log_size = 0;
-
 struct err_log_info {
 	int error_type;
 	unsigned int seq_num;
 };
-#define NVRAM_MAX_REQ		2079
-#define NVRAM_MIN_REQ		1055
 
-#define NVRAM_LOG_PART_NAME	"ibm,rtas-log"
+struct nvram_os_partition {
+	const char *name;
+	int req_size;	/* desired size, in bytes */
+	int min_size;	/* minimum acceptable size (0 means req_size) */
+	long size;	/* size of data portion (excluding err_log_info) */
+	long index;	/* offset of data portion of partition */
+};
+
+static struct nvram_os_partition rtas_log_partition = {
+	.name = "ibm,rtas-log",
+	.req_size = 2079,
+	.min_size = 1055,
+	.index = -1
+};
+
+static struct nvram_os_partition oops_log_partition = {
+	.name = "lnx,oops-log",
+	.req_size = 4000,
+	.min_size = 2000,
+	.index = -1
+};
+
+static const char *pseries_nvram_os_partitions[] = {
+	"ibm,rtas-log",
+	"lnx,oops-log",
+	NULL
+};
+
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason,
+		const char *old_msgs, unsigned long old_len,
+		const char *new_msgs, unsigned long new_len);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+	.dump = oops_to_nvram
+};
+
+/* See clobbering_unread_rtas_event() */
+#define NVRAM_RTAS_READ_TIMEOUT 5		/* seconds */
+static unsigned long last_unread_rtas_event;	/* timestamp */
+
+/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
+static char *oops_buf;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -134,7 +173,7 @@ static ssize_t pSeries_nvram_get_size(void)
 }
 
 
-/* nvram_write_error_log
+/* nvram_write_os_partition, nvram_write_error_log
  *
  * We need to buffer the error logs into nvram to ensure that we have
  * the failure information to decode.  If we have a severe error there
@@ -156,48 +195,58 @@ static ssize_t pSeries_nvram_get_size(void)
  * The 'data' section would look like (in bytes):
  * +--------------+------------+-----------------------------------+
  * | event_logged | sequence # | error log                         |
- * |0            3|4          7|8            nvram_error_log_size-1|
+ * |0            3|4          7|8                  error_log_size-1|
  * +--------------+------------+-----------------------------------+
  *
  * event_logged: 0 if event has not been logged to syslog, 1 if it has
  * sequence #: The unique sequence # for each event. (until it wraps)
  * error log: The error log from event_scan
  */
-int nvram_write_error_log(char * buff, int length,
-                          unsigned int err_type, unsigned int error_log_cnt)
+int nvram_write_os_partition(struct nvram_os_partition *part, char * buff,
+		int length, unsigned int err_type, unsigned int error_log_cnt)
 {
 	int rc;
 	loff_t tmp_index;
 	struct err_log_info info;
 	
-	if (nvram_error_log_index == -1) {
+	if (part->index == -1) {
 		return -ESPIPE;
 	}
 
-	if (length > nvram_error_log_size) {
-		length = nvram_error_log_size;
+	if (length > part->size) {
+		length = part->size;
 	}
 
 	info.error_type = err_type;
 	info.seq_num = error_log_cnt;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = part->index;
 
 	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		pr_err("%s: Failed nvram_write (%d)\n", __FUNCTION__, rc);
 		return rc;
 	}
 
 	rc = ppc_md.nvram_write(buff, length, &tmp_index);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		pr_err("%s: Failed nvram_write (%d)\n", __FUNCTION__, rc);
 		return rc;
 	}
 	
 	return 0;
 }
 
+int nvram_write_error_log(char * buff, int length,
+                          unsigned int err_type, unsigned int error_log_cnt)
+{
+	int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
+						err_type, error_log_cnt);
+	if (!rc)
+		last_unread_rtas_event = get_seconds();
+	return rc;
+}
+
 /* nvram_read_error_log
  *
  * Reads nvram for error log for at most 'length'
@@ -209,13 +258,13 @@ int nvram_read_error_log(char * buff, int length,
 	loff_t tmp_index;
 	struct err_log_info info;
 	
-	if (nvram_error_log_index == -1)
+	if (rtas_log_partition.index == -1)
 		return -1;
 
-	if (length > nvram_error_log_size)
-		length = nvram_error_log_size;
+	if (length > rtas_log_partition.size)
+		length = rtas_log_partition.size;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = rtas_log_partition.index;
 
 	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
 	if (rc <= 0) {
@@ -244,37 +293,40 @@ int nvram_clear_error_log(void)
 	int clear_word = ERR_FLAG_ALREADY_LOGGED;
 	int rc;
 
-	if (nvram_error_log_index == -1)
+	if (rtas_log_partition.index == -1)
 		return -1;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = rtas_log_partition.index;
 	
 	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
 	if (rc <= 0) {
 		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
 		return rc;
 	}
+	last_unread_rtas_event = 0;
 
 	return 0;
 }
 
-/* pseries_nvram_init_log_partition
+/* pseries_nvram_init_os_partition
  *
- * This will setup the partition we need for buffering the
- * error logs and cleanup partitions if needed.
+ * This sets up a partition with an "OS" signature.
  *
  * The general strategy is the following:
- * 1.) If there is log partition large enough then use it.
- * 2.) If there is none large enough, search
- * for a free partition that is large enough.
- * 3.) If there is not a free partition large enough remove 
- * _all_ OS partitions and consolidate the space.
- * 4.) Will first try getting a chunk that will satisfy the maximum
- * error log size (NVRAM_MAX_REQ).
- * 5.) If the max chunk cannot be allocated then try finding a chunk
- * that will satisfy the minum needed (NVRAM_MIN_REQ).
+ * 1.) If a partition with the indicated name already exists...
+ *	- If it's large enough, use it.
+ *	- Otherwise, recycle it and keep going.
+ * 2.) Search for a free partition that is large enough.
+ * 3.) If there's not a free partition large enough, recycle any obsolete
+ * OS partitions and try again.
+ * 4.) Will first try getting a chunk that will satisfy the requested size.
+ * 5.) If a chunk of the requested size cannot be allocated, then try finding
+ * a chunk that will satisfy the minum needed.
+ *
+ * Returns 0 on success, else -1.
  */
-static int __init pseries_nvram_init_log_partition(void)
+static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
+									*part)
 {
 	loff_t p;
 	int size;
@@ -282,47 +334,76 @@ static int __init pseries_nvram_init_log_partition(void)
 	/* Scan nvram for partitions */
 	nvram_scan_partitions();
 
-	/* Lookg for ours */
-	p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
+	/* Look for ours */
+	p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
 
 	/* Found one but too small, remove it */
-	if (p && size < NVRAM_MIN_REQ) {
-		pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition"
-			",removing it...");
-		nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
+	if (p && size < part->min_size) {
+		pr_info("nvram: Found too small %s partition,"
+					" removing it...\n", part->name);
+		nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
 		p = 0;
 	}
 
 	/* Create one if we didn't find */
 	if (!p) {
-		p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
-					   NVRAM_MAX_REQ, NVRAM_MIN_REQ);
-		/* No room for it, try to get rid of any OS partition
-		 * and try again
-		 */
+		p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+					part->req_size, part->min_size);
 		if (p == -ENOSPC) {
-			pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME
-				" partition, deleting all OS partitions...");
-			nvram_remove_partition(NULL, NVRAM_SIG_OS);
-			p = nvram_create_partition(NVRAM_LOG_PART_NAME,
-						   NVRAM_SIG_OS, NVRAM_MAX_REQ,
-						   NVRAM_MIN_REQ);
+			pr_info("nvram: No room to create %s partition, "
+				"deleting any obsolete OS partitions...\n",
+				part->name);
+			nvram_remove_partition(NULL, NVRAM_SIG_OS,
+						pseries_nvram_os_partitions);
+			p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+					part->req_size, part->min_size);
 		}
 	}
 
 	if (p <= 0) {
-		pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
-		       " partition, err %d\n", (int)p);
-		return 0;
+		pr_err("nvram: Failed to find or create %s"
+		       " partition, err %d\n", part->name, (int)p);
+		return -1;
 	}
 
-	nvram_error_log_index = p;
-	nvram_error_log_size = nvram_get_partition_size(p) -
-		sizeof(struct err_log_info);
+	part->index = p;
+	part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
 	
 	return 0;
 }
-machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
+
+static void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+	int rc;
+
+	rc = pseries_nvram_init_os_partition(&oops_log_partition);
+	if (rc != 0) {
+		if (!rtas_partition_exists)
+			return;
+		pr_notice("nvram: Using %s partition to log both"
+			" RTAS errors and oops/panic reports\n",
+			rtas_log_partition.name);
+		memcpy(&oops_log_partition, &rtas_log_partition,
+						sizeof(rtas_log_partition));
+	}
+	oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+	rc = kmsg_dump_register(&nvram_kmsg_dumper);
+	if (rc != 0) {
+		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
+		kfree(oops_buf);
+		return;
+	}
+}
+
+static int __init pseries_nvram_init_log_partitions(void)
+{
+	int rc;
+
+	rc = pseries_nvram_init_os_partition(&rtas_log_partition);
+	nvram_init_oops_partition(rc == 0);
+	return 0;
+}
+machine_arch_initcall(pseries, pseries_nvram_init_log_partitions);
 
 int __init pSeries_nvram_init(void)
 {
@@ -353,3 +434,59 @@ int __init pSeries_nvram_init(void)
 
 	return 0;
 }
+
+/*
+ * Try to capture the last capture_len bytes of the printk buffer.  Return
+ * the amount actually captured.
+ */
+static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
+				const char *new_msgs, size_t new_len,
+				char *captured, size_t capture_len)
+{
+	if (new_len >= capture_len) {
+		memcpy(captured, new_msgs + (new_len - capture_len),
+								capture_len);
+		return capture_len;
+	} else {
+		/* Grab the end of old_msgs. */
+		size_t old_tail_len = min(old_len, capture_len - new_len);
+		memcpy(captured, old_msgs + (old_len - old_tail_len),
+								old_tail_len);
+		memcpy(captured + old_tail_len, new_msgs, new_len);
+		return old_tail_len + new_len;
+	}
+}
+
+/*
+ * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
+ * would logging this oops/panic overwrite an RTAS event that rtas_errd
+ * hasn't had a chance to read and process?  Return 1 if so, else 0.
+ *
+ * We assume that if rtas_errd hasn't read the RTAS event in
+ * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
+ */
+static int clobbering_unread_rtas_event(void)
+{
+	return (oops_log_partition.index == rtas_log_partition.index
+		&& last_unread_rtas_event
+		&& get_seconds() - last_unread_rtas_event <=
+						NVRAM_RTAS_READ_TIMEOUT);
+}
+
+/* our kmsg_dump callback */
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason,
+		const char *old_msgs, unsigned long old_len,
+		const char *new_msgs, unsigned long new_len)
+{
+	static unsigned int oops_count = 0;
+	size_t text_len;
+
+	if (clobbering_unread_rtas_event())
+		return;
+
+	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
+					oops_buf, oops_log_partition.size);
+	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
+		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+}
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 5fcc92a..3bf4488 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -149,7 +149,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
 	if (dn->child)
 		eeh_add_device_tree_early(dn);
 
-	pcibios_scan_phb(phb, dn);
+	pcibios_scan_phb(phb);
 	pcibios_finish_adding_to_bus(phb->bus);
 
 	return phb;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index d345bfd..2a0089a 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -114,10 +114,13 @@ static void __init fwnmi_init(void)
 
 static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init pseries_setup_i8259_cascade(void)
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 7b96e5a..01fea46 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -202,20 +202,20 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask,
 #define get_irq_server(virq, cpumask, strict_check) (default_server)
 #endif
 
-static void xics_unmask_irq(unsigned int virq)
+static void xics_unmask_irq(struct irq_data *d)
 {
 	unsigned int irq;
 	int call_status;
 	int server;
 
-	pr_devel("xics: unmask virq %d\n", virq);
+	pr_devel("xics: unmask virq %d\n", d->irq);
 
-	irq = (unsigned int)irq_map[virq].hwirq;
+	irq = (unsigned int)irq_map[d->irq].hwirq;
 	pr_devel(" -> map to hwirq 0x%x\n", irq);
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
 
-	server = get_irq_server(virq, irq_to_desc(virq)->affinity, 0);
+	server = get_irq_server(d->irq, d->affinity, 0);
 
 	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
 				DEFAULT_PRIORITY);
@@ -235,61 +235,61 @@ static void xics_unmask_irq(unsigned int virq)
 	}
 }
 
-static unsigned int xics_startup(unsigned int virq)
+static unsigned int xics_startup(struct irq_data *d)
 {
 	/*
 	 * The generic MSI code returns with the interrupt disabled on the
 	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
 	 * at that level, so we do it here by hand.
 	 */
-	if (irq_to_desc(virq)->msi_desc)
-		unmask_msi_irq(irq_get_irq_data(virq));
+	if (d->msi_desc)
+		unmask_msi_irq(d);
 
 	/* unmask it */
-	xics_unmask_irq(virq);
+	xics_unmask_irq(d);
 	return 0;
 }
 
-static void xics_mask_real_irq(unsigned int irq)
+static void xics_mask_real_irq(struct irq_data *d)
 {
 	int call_status;
 
-	if (irq == XICS_IPI)
+	if (d->irq == XICS_IPI)
 		return;
 
-	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
+	call_status = rtas_call(ibm_int_off, 1, 1, NULL, d->irq);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
-			__func__, irq, call_status);
+			__func__, d->irq, call_status);
 		return;
 	}
 
 	/* Have to set XIVE to 0xff to be able to remove a slot */
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, d->irq,
 				default_server, 0xff);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
-			__func__, irq, call_status);
+			__func__, d->irq, call_status);
 		return;
 	}
 }
 
-static void xics_mask_irq(unsigned int virq)
+static void xics_mask_irq(struct irq_data *d)
 {
 	unsigned int irq;
 
-	pr_devel("xics: mask virq %d\n", virq);
+	pr_devel("xics: mask virq %d\n", d->irq);
 
-	irq = (unsigned int)irq_map[virq].hwirq;
+	irq = (unsigned int)irq_map[d->irq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
-	xics_mask_real_irq(irq);
+	xics_mask_real_irq(d);
 }
 
 static void xics_mask_unknown_vec(unsigned int vec)
 {
 	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
-	xics_mask_real_irq(vec);
+	xics_mask_real_irq(irq_get_irq_data(vec));
 }
 
 static inline unsigned int xics_xirr_vector(unsigned int xirr)
@@ -371,30 +371,31 @@ static unsigned char pop_cppr(void)
 	return os_cppr->stack[--os_cppr->index];
 }
 
-static void xics_eoi_direct(unsigned int virq)
+static void xics_eoi_direct(struct irq_data *d)
 {
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq = (unsigned int)irq_map[d->irq].hwirq;
 
 	iosync();
 	direct_xirr_info_set((pop_cppr() << 24) | irq);
 }
 
-static void xics_eoi_lpar(unsigned int virq)
+static void xics_eoi_lpar(struct irq_data *d)
 {
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq = (unsigned int)irq_map[d->irq].hwirq;
 
 	iosync();
 	lpar_xirr_info_set((pop_cppr() << 24) | irq);
 }
 
-static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
+static int
+xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
 {
 	unsigned int irq;
 	int status;
 	int xics_status[2];
 	int irq_server;
 
-	irq = (unsigned int)irq_map[virq].hwirq;
+	irq = (unsigned int)irq_map[d->irq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return -1;
 
@@ -406,13 +407,13 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 		return -1;
 	}
 
-	irq_server = get_irq_server(virq, cpumask, 1);
+	irq_server = get_irq_server(d->irq, cpumask, 1);
 	if (irq_server == -1) {
 		char cpulist[128];
 		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
 		printk(KERN_WARNING
 			"%s: No online cpus in the mask %s for irq %d\n",
-			__func__, cpulist, virq);
+			__func__, cpulist, d->irq);
 		return -1;
 	}
 
@@ -430,20 +431,20 @@ static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
 
 static struct irq_chip xics_pic_direct = {
 	.name = "XICS",
-	.startup = xics_startup,
-	.mask = xics_mask_irq,
-	.unmask = xics_unmask_irq,
-	.eoi = xics_eoi_direct,
-	.set_affinity = xics_set_affinity
+	.irq_startup = xics_startup,
+	.irq_mask = xics_mask_irq,
+	.irq_unmask = xics_unmask_irq,
+	.irq_eoi = xics_eoi_direct,
+	.irq_set_affinity = xics_set_affinity
 };
 
 static struct irq_chip xics_pic_lpar = {
 	.name = "XICS",
-	.startup = xics_startup,
-	.mask = xics_mask_irq,
-	.unmask = xics_unmask_irq,
-	.eoi = xics_eoi_lpar,
-	.set_affinity = xics_set_affinity
+	.irq_startup = xics_startup,
+	.irq_mask = xics_mask_irq,
+	.irq_unmask = xics_unmask_irq,
+	.irq_eoi = xics_eoi_lpar,
+	.irq_set_affinity = xics_set_affinity
 };
 
 
@@ -890,6 +891,7 @@ void xics_migrate_irqs_away(void)
 
 	for_each_irq(virq) {
 		struct irq_desc *desc;
+		struct irq_chip *chip;
 		int xics_status[2];
 		int status;
 		unsigned long flags;
@@ -903,12 +905,15 @@ void xics_migrate_irqs_away(void)
 		/* We need to get IPIs still. */
 		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 			continue;
+
 		desc = irq_to_desc(virq);
 
 		/* We only need to migrate enabled IRQS */
-		if (desc == NULL || desc->chip == NULL
-		    || desc->action == NULL
-		    || desc->chip->set_affinity == NULL)
+		if (desc == NULL || desc->action == NULL)
+			continue;
+
+		chip = get_irq_desc_chip(desc);
+		if (chip == NULL || chip->irq_set_affinity == NULL)
 			continue;
 
 		raw_spin_lock_irqsave(&desc->lock, flags);
@@ -934,8 +939,8 @@ void xics_migrate_irqs_away(void)
 			       virq, cpu);
 
 		/* Reset affinity to all cpus */
-		cpumask_setall(irq_to_desc(virq)->affinity);
-		desc->chip->set_affinity(virq, cpu_all_mask);
+		cpumask_setall(desc->irq_data.affinity);
+		chip->irq_set_affinity(&desc->irq_data, cpu_all_mask, true);
 unlock:
 		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 2659a60..27402c7d 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -172,10 +172,9 @@ static const struct block_device_operations axon_ram_devops = {
 
 /**
  * axon_ram_probe - probe() method for platform driver
- * @device, @device_id: see of_platform_driver method
+ * @device: see platform_driver method
  */
-static int axon_ram_probe(struct platform_device *device,
-			  const struct of_device_id *device_id)
+static int axon_ram_probe(struct platform_device *device)
 {
 	static int axon_ram_bank_id = -1;
 	struct axon_ram_bank *bank;
@@ -326,7 +325,7 @@ static struct of_device_id axon_ram_device_id[] = {
 	{}
 };
 
-static struct of_platform_driver axon_ram_driver = {
+static struct platform_driver axon_ram_driver = {
 	.probe		= axon_ram_probe,
 	.remove		= axon_ram_remove,
 	.driver = {
@@ -350,7 +349,7 @@ axon_ram_init(void)
 	}
 	azfs_minor = 0;
 
-	return of_register_platform_driver(&axon_ram_driver);
+	return platform_driver_register(&axon_ram_driver);
 }
 
 /**
@@ -359,7 +358,7 @@ axon_ram_init(void)
 static void __exit
 axon_ram_exit(void)
 {
-	of_unregister_platform_driver(&axon_ram_driver);
+	platform_driver_unregister(&axon_ram_driver);
 	unregister_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
 }
 
diff --git a/arch/powerpc/sysdev/bestcomm/bestcomm.c b/arch/powerpc/sysdev/bestcomm/bestcomm.c
index 6502561..b3fbb27 100644
--- a/arch/powerpc/sysdev/bestcomm/bestcomm.c
+++ b/arch/powerpc/sysdev/bestcomm/bestcomm.c
@@ -365,8 +365,7 @@ bcom_engine_cleanup(void)
 /* OF platform driver                                                       */
 /* ======================================================================== */
 
-static int __devinit mpc52xx_bcom_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc52xx_bcom_probe(struct platform_device *op)
 {
 	struct device_node *ofn_sram;
 	struct resource res_bcom;
@@ -492,7 +491,7 @@ static struct of_device_id mpc52xx_bcom_of_match[] = {
 MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
 
 
-static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
+static struct platform_driver mpc52xx_bcom_of_platform_driver = {
 	.probe		= mpc52xx_bcom_probe,
 	.remove		= mpc52xx_bcom_remove,
 	.driver = {
@@ -510,13 +509,13 @@ static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
 static int __init
 mpc52xx_bcom_init(void)
 {
-	return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver);
+	return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
 }
 
 static void __exit
 mpc52xx_bcom_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_bcom_of_platform_driver);
+	platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
 }
 
 /* If we're not a module, we must make sure everything is setup before  */
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c
index 0085212..0476bcc 100644
--- a/arch/powerpc/sysdev/cpm1.c
+++ b/arch/powerpc/sysdev/cpm1.c
@@ -56,32 +56,32 @@ static cpic8xx_t __iomem *cpic_reg;
 
 static struct irq_host *cpm_pic_host;
 
-static void cpm_mask_irq(unsigned int irq)
+static void cpm_mask_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
 
 	clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
 }
 
-static void cpm_unmask_irq(unsigned int irq)
+static void cpm_unmask_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
 
 	setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
 }
 
-static void cpm_end_irq(unsigned int irq)
+static void cpm_end_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
 
 	out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
 }
 
 static struct irq_chip cpm_pic = {
 	.name = "CPM PIC",
-	.mask = cpm_mask_irq,
-	.unmask = cpm_unmask_irq,
-	.eoi = cpm_end_irq,
+	.irq_mask = cpm_mask_irq,
+	.irq_unmask = cpm_unmask_irq,
+	.irq_eoi = cpm_end_irq,
 };
 
 int cpm_get_irq(void)
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index fcea4ff..4730325 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -78,10 +78,10 @@ static const u_char irq_to_siubit[] = {
 	24, 25, 26, 27, 28, 29, 30, 31,
 };
 
-static void cpm2_mask_irq(unsigned int virq)
+static void cpm2_mask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -90,10 +90,10 @@ static void cpm2_mask_irq(unsigned int virq)
 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
 }
 
-static void cpm2_unmask_irq(unsigned int virq)
+static void cpm2_unmask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -102,10 +102,10 @@ static void cpm2_unmask_irq(unsigned int virq)
 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
 }
 
-static void cpm2_ack(unsigned int virq)
+static void cpm2_ack(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -113,11 +113,11 @@ static void cpm2_ack(unsigned int virq)
 	out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit);
 }
 
-static void cpm2_end_irq(unsigned int virq)
+static void cpm2_end_irq(struct irq_data *d)
 {
 	struct irq_desc *desc;
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	desc = irq_to_desc(irq_nr);
 	if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
@@ -137,10 +137,10 @@ static void cpm2_end_irq(unsigned int virq)
 	}
 }
 
-static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	unsigned int src = virq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	unsigned int src = virq_to_hw(d->irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	unsigned int vold, vnew, edibit;
 
 	/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
@@ -199,11 +199,11 @@ err_sense:
 
 static struct irq_chip cpm2_pic = {
 	.name = "CPM2 SIU",
-	.mask = cpm2_mask_irq,
-	.unmask = cpm2_unmask_irq,
-	.ack = cpm2_ack,
-	.eoi = cpm2_end_irq,
-	.set_type = cpm2_set_irq_type,
+	.irq_mask = cpm2_mask_irq,
+	.irq_unmask = cpm2_unmask_irq,
+	.irq_ack = cpm2_ack,
+	.irq_eoi = cpm2_end_irq,
+	.irq_set_type = cpm2_set_irq_type,
 };
 
 unsigned int cpm2_get_irq(void)
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
index cc8d655..5f88797 100644
--- a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
+++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
@@ -71,8 +71,7 @@ static int __init get_offset_from_cmdline(char *str)
 __setup("cache-sram-size=", get_size_from_cmdline);
 __setup("cache-sram-offset=", get_offset_from_cmdline);
 
-static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev,
-					  const struct of_device_id *match)
+static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev)
 {
 	long rval;
 	unsigned int rem;
@@ -94,14 +93,14 @@ static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev,
 	l2cache_size = *prop;
 
 	sram_params.sram_size  = get_cache_sram_size();
-	if (sram_params.sram_size <= 0) {
+	if ((int)sram_params.sram_size <= 0) {
 		dev_err(&dev->dev,
 			"Entire L2 as cache, Aborting Cache-SRAM stuff\n");
 		return -EINVAL;
 	}
 
 	sram_params.sram_offset  = get_cache_sram_offset();
-	if (sram_params.sram_offset <= 0) {
+	if ((int64_t)sram_params.sram_offset <= 0) {
 		dev_err(&dev->dev,
 			"Entire L2 as cache, provide a valid sram offset\n");
 		return -EINVAL;
@@ -204,7 +203,7 @@ static struct of_device_id mpc85xx_l2ctlr_of_match[] = {
 	{},
 };
 
-static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
+static struct platform_driver mpc85xx_l2ctlr_of_platform_driver = {
 	.driver	= {
 		.name		= "fsl-l2ctlr",
 		.owner		= THIS_MODULE,
@@ -216,12 +215,12 @@ static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
 
 static __init int mpc85xx_l2ctlr_of_init(void)
 {
-	return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+	return platform_driver_register(&mpc85xx_l2ctlr_of_platform_driver);
 }
 
 static void __exit mpc85xx_l2ctlr_of_exit(void)
 {
-	of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+	platform_driver_unregister(&mpc85xx_l2ctlr_of_platform_driver);
 }
 
 subsys_initcall(mpc85xx_l2ctlr_of_init);
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
index 108d76f..58e09b2 100644
--- a/arch/powerpc/sysdev/fsl_msi.c
+++ b/arch/powerpc/sysdev/fsl_msi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc.
  *
  * Author: Tony Li <tony.li@freescale.com>
  *	   Jason Jin <Jason.jin@freescale.com>
@@ -47,14 +47,14 @@ static inline u32 fsl_msi_read(u32 __iomem *base, unsigned int reg)
  * We do not need this actually. The MSIR register has been read once
  * in the cascade interrupt. So, this MSI interrupt has been acked
 */
-static void fsl_msi_end_irq(unsigned int virq)
+static void fsl_msi_end_irq(struct irq_data *d)
 {
 }
 
 static struct irq_chip fsl_msi_chip = {
 	.irq_mask	= mask_msi_irq,
 	.irq_unmask	= unmask_msi_irq,
-	.ack		= fsl_msi_end_irq,
+	.irq_ack	= fsl_msi_end_irq,
 	.name		= "FSL-MSI",
 };
 
@@ -183,6 +183,7 @@ out_free:
 
 static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq;
 	struct fsl_msi *msi_data;
 	int msir_index = -1;
@@ -196,11 +197,11 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 
 	raw_spin_lock(&desc->lock);
 	if ((msi_data->feature &  FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
-		if (desc->chip->mask_ack)
-			desc->chip->mask_ack(irq);
+		if (chip->irq_mask_ack)
+			chip->irq_mask_ack(&desc->irq_data);
 		else {
-			desc->chip->mask(irq);
-			desc->chip->ack(irq);
+			chip->irq_mask(&desc->irq_data);
+			chip->irq_ack(&desc->irq_data);
 		}
 	}
 
@@ -238,11 +239,11 @@ static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 
 	switch (msi_data->feature & FSL_PIC_IP_MASK) {
 	case FSL_PIC_IP_MPIC:
-		desc->chip->eoi(irq);
+		chip->irq_eoi(&desc->irq_data);
 		break;
 	case FSL_PIC_IP_IPIC:
-		if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-			desc->chip->unmask(irq);
+		if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
+			chip->irq_unmask(&desc->irq_data);
 		break;
 	}
 unlock:
@@ -273,19 +274,50 @@ static int fsl_of_msi_remove(struct platform_device *ofdev)
 	return 0;
 }
 
-static int __devinit fsl_of_msi_probe(struct platform_device *dev,
-				const struct of_device_id *match)
+static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
+					 struct platform_device *dev,
+					 int offset, int irq_index)
+{
+	struct fsl_msi_cascade_data *cascade_data = NULL;
+	int virt_msir;
+
+	virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index);
+	if (virt_msir == NO_IRQ) {
+		dev_err(&dev->dev, "%s: Cannot translate IRQ index %d\n",
+			__func__, irq_index);
+		return 0;
+	}
+
+	cascade_data = kzalloc(sizeof(struct fsl_msi_cascade_data), GFP_KERNEL);
+	if (!cascade_data) {
+		dev_err(&dev->dev, "No memory for MSI cascade data\n");
+		return -ENOMEM;
+	}
+
+	msi->msi_virqs[irq_index] = virt_msir;
+	cascade_data->index = offset + irq_index;
+	cascade_data->msi_data = msi;
+	set_irq_data(virt_msir, cascade_data);
+	set_irq_chained_handler(virt_msir, fsl_msi_cascade);
+
+	return 0;
+}
+
+static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 {
 	struct fsl_msi *msi;
 	struct resource res;
-	int err, i, count;
+	int err, i, j, irq_index, count;
 	int rc;
-	int virt_msir;
 	const u32 *p;
-	struct fsl_msi_feature *features = match->data;
-	struct fsl_msi_cascade_data *cascade_data = NULL;
+	struct fsl_msi_feature *features;
 	int len;
 	u32 offset;
+	static const u32 all_avail[] = { 0, NR_MSI_IRQS };
+
+	if (!dev->dev.of_match)
+		return -EINVAL;
+	features = dev->dev.of_match->data;
 
 	printk(KERN_DEBUG "Setting up Freescale MSI support\n");
 
@@ -332,42 +364,34 @@ static int __devinit fsl_of_msi_probe(struct platform_device *dev,
 		goto error_out;
 	}
 
-	p = of_get_property(dev->dev.of_node, "interrupts", &count);
-	if (!p) {
-		dev_err(&dev->dev, "no interrupts property found on %s\n",
-				dev->dev.of_node->full_name);
-		err = -ENODEV;
-		goto error_out;
-	}
-	if (count % 8 != 0) {
-		dev_err(&dev->dev, "Malformed interrupts property on %s\n",
-				dev->dev.of_node->full_name);
+	p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
+	if (p && len % (2 * sizeof(u32)) != 0) {
+		dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
+			__func__);
 		err = -EINVAL;
 		goto error_out;
 	}
-	offset = 0;
-	p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
-	if (p)
-		offset = *p / IRQS_PER_MSI_REG;
-
-	count /= sizeof(u32);
-	for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
-		virt_msir = irq_of_parse_and_map(dev->dev.of_node, i);
-		if (virt_msir != NO_IRQ) {
-			cascade_data = kzalloc(
-					sizeof(struct fsl_msi_cascade_data),
-					GFP_KERNEL);
-			if (!cascade_data) {
-				dev_err(&dev->dev,
-					"No memory for MSI cascade data\n");
-				err = -ENOMEM;
+
+	if (!p)
+		p = all_avail;
+
+	for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
+		if (p[i * 2] % IRQS_PER_MSI_REG ||
+		    p[i * 2 + 1] % IRQS_PER_MSI_REG) {
+			printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
+			       __func__, dev->dev.of_node->full_name,
+			       p[i * 2 + 1], p[i * 2]);
+			err = -EINVAL;
+			goto error_out;
+		}
+
+		offset = p[i * 2] / IRQS_PER_MSI_REG;
+		count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
+
+		for (j = 0; j < count; j++, irq_index++) {
+			err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index);
+			if (err)
 				goto error_out;
-			}
-			msi->msi_virqs[i] = virt_msir;
-			cascade_data->index = i + offset;
-			cascade_data->msi_data = msi;
-			set_irq_data(virt_msir, (void *)cascade_data);
-			set_irq_chained_handler(virt_msir, fsl_msi_cascade);
 		}
 	}
 
@@ -411,7 +435,7 @@ static const struct of_device_id fsl_of_msi_ids[] = {
 	{}
 };
 
-static struct of_platform_driver fsl_of_msi_driver = {
+static struct platform_driver fsl_of_msi_driver = {
 	.driver = {
 		.name = "fsl-msi",
 		.owner = THIS_MODULE,
@@ -423,7 +447,7 @@ static struct of_platform_driver fsl_of_msi_driver = {
 
 static __init int fsl_of_msi_init(void)
 {
-	return of_register_platform_driver(&fsl_of_msi_driver);
+	return platform_driver_register(&fsl_of_msi_driver);
 }
 
 subsys_initcall(fsl_of_msi_init);
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 818f7c6..f8f7f28 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -1,7 +1,7 @@
 /*
  * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
  * Copyright 2008-2009 MontaVista Software, Inc.
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -99,7 +99,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 				  struct resource *rsrc)
 {
 	struct ccsr_pci __iomem *pci;
-	int i, j, n, mem_log, win_idx = 2;
+	int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
 	u64 mem, sz, paddr_hi = 0;
 	u64 paddr_lo = ULLONG_MAX;
 	u32 pcicsrbar = 0, pcicsrbar_sz;
@@ -109,6 +109,13 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 
 	pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
 		    (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
+
+	if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
+		win_idx = 2;
+		start_idx = 0;
+		end_idx = 3;
+	}
+
 	pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
 	if (!pci) {
 	    dev_err(hose->parent, "Unable to map ATMU registers\n");
@@ -118,7 +125,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 	/* Disable all windows (except powar0 since it's ignored) */
 	for(i = 1; i < 5; i++)
 		out_be32(&pci->pow[i].powar, 0);
-	for(i = 0; i < 3; i++)
+	for (i = start_idx; i < end_idx; i++)
 		out_be32(&pci->piw[i].piwar, 0);
 
 	/* Setup outbound MEM window */
@@ -204,7 +211,7 @@ static void __init setup_pci_atmu(struct pci_controller *hose,
 			mem_log++;
 		}
 
-		piwar |= (mem_log - 1);
+		piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
 
 		/* Setup inbound memory window */
 		out_be32(&pci->piw[win_idx].pitar,  0x00000000);
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 8ad72a1..a39ed5c 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -1,7 +1,7 @@
 /*
  * MPC85xx/86xx PCI Express structure define
  *
- * Copyright 2007 Freescale Semiconductor, Inc
+ * Copyright 2007,2011 Freescale Semiconductor, Inc
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -21,6 +21,7 @@
 #define PIWAR_TGI_LOCAL		0x00f00000	/* target - local memory */
 #define PIWAR_READ_SNOOP	0x00050000
 #define PIWAR_WRITE_SNOOP	0x00005000
+#define PIWAR_SZ_MASK          0x0000003f
 
 /* PCI/PCI Express outbound window reg */
 struct pci_outbound_window_regs {
@@ -49,7 +50,9 @@ struct ccsr_pci {
 	__be32	int_ack;		/* 0x.008 - PCI Interrupt Acknowledge Register */
 	__be32	pex_otb_cpl_tor;	/* 0x.00c - PCIE Outbound completion timeout register */
 	__be32	pex_conf_tor;		/* 0x.010 - PCIE configuration timeout register */
-	u8	res2[12];
+	__be32	pex_config;		/* 0x.014 - PCIE CONFIG Register */
+	__be32	pex_int_status;		/* 0x.018 - PCIE interrupt status */
+	u8	res2[4];
 	__be32	pex_pme_mes_dr;		/* 0x.020 - PCIE PME and message detect register */
 	__be32	pex_pme_mes_disr;	/* 0x.024 - PCIE PME and message disable register */
 	__be32	pex_pme_mes_ier;	/* 0x.028 - PCIE PME and message interrupt enable register */
@@ -62,14 +65,14 @@ struct ccsr_pci {
  * in all of the other outbound windows.
  */
 	struct pci_outbound_window_regs pow[5];
-
-	u8	res14[256];
-
-/* PCI/PCI Express inbound window 3-1
+	u8	res14[96];
+	struct pci_inbound_window_regs	pmit;	/* 0xd00 - 0xd9c Inbound MSI */
+	u8	res6[96];
+/* PCI/PCI Express inbound window 3-0
  * inbound window 1 supports only a 32-bit base address and does not
  * define an inbound window base extended address register.
  */
-	struct pci_inbound_window_regs piw[3];
+	struct pci_inbound_window_regs piw[4];
 
 	__be32	pex_err_dr;		/* 0x.e00 - PCI/PCIE error detect register */
 	u8	res21[4];
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index e9381bf..f122e89 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -58,8 +58,7 @@ static const struct platform_suspend_ops pmc_suspend_ops = {
 	.enter = pmc_suspend_enter,
 };
 
-static int pmc_probe(struct platform_device *ofdev,
-		     const struct of_device_id *id)
+static int pmc_probe(struct platform_device *ofdev)
 {
 	pmc_regs = of_iomap(ofdev->dev.of_node, 0);
 	if (!pmc_regs)
@@ -76,7 +75,7 @@ static const struct of_device_id pmc_ids[] = {
 	{ },
 };
 
-static struct of_platform_driver pmc_driver = {
+static struct platform_driver pmc_driver = {
 	.driver = {
 		.name = "fsl-pmc",
 		.owner = THIS_MODULE,
@@ -87,6 +86,6 @@ static struct of_platform_driver pmc_driver = {
 
 static int __init pmc_init(void)
 {
-	return of_register_platform_driver(&pmc_driver);
+	return platform_driver_register(&pmc_driver);
 }
 device_initcall(pmc_init);
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index 8c6cab0..3eff2c3 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -1570,8 +1570,7 @@ err_ops:
 
 /* The probe function for RapidIO peer-to-peer network.
  */
-static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev,
-				     const struct of_device_id *match)
+static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev)
 {
 	int rc;
 	printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
@@ -1594,7 +1593,7 @@ static const struct of_device_id fsl_of_rio_rpn_ids[] = {
 	{},
 };
 
-static struct of_platform_driver fsl_of_rio_rpn_driver = {
+static struct platform_driver fsl_of_rio_rpn_driver = {
 	.driver = {
 		.name = "fsl-of-rio",
 		.owner = THIS_MODULE,
@@ -1605,7 +1604,7 @@ static struct of_platform_driver fsl_of_rio_rpn_driver = {
 
 static __init int fsl_of_rio_rpn_init(void)
 {
-	return of_register_platform_driver(&fsl_of_rio_rpn_driver);
+	return platform_driver_register(&fsl_of_rio_rpn_driver);
 }
 
 subsys_initcall(fsl_of_rio_rpn_init);
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 6323e70..aeda4c8 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -78,19 +78,19 @@ unsigned int i8259_irq(void)
 	return irq;
 }
 
-static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+static void i8259_mask_and_ack_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&i8259_lock, flags);
-	if (irq_nr > 7) {
-		cached_A1 |= 1 << (irq_nr-8);
+	if (d->irq > 7) {
+		cached_A1 |= 1 << (d->irq-8);
 		inb(0xA1); 	/* DUMMY */
 		outb(cached_A1, 0xA1);
 		outb(0x20, 0xA0);	/* Non-specific EOI */
 		outb(0x20, 0x20);	/* Non-specific EOI to cascade */
 	} else {
-		cached_21 |= 1 << irq_nr;
+		cached_21 |= 1 << d->irq;
 		inb(0x21); 	/* DUMMY */
 		outb(cached_21, 0x21);
 		outb(0x20, 0x20);	/* Non-specific EOI */
@@ -104,42 +104,42 @@ static void i8259_set_irq_mask(int irq_nr)
 	outb(cached_21,0x21);
 }
 
-static void i8259_mask_irq(unsigned int irq_nr)
+static void i8259_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
-	pr_debug("i8259_mask_irq(%d)\n", irq_nr);
+	pr_debug("i8259_mask_irq(%d)\n", d->irq);
 
 	raw_spin_lock_irqsave(&i8259_lock, flags);
-	if (irq_nr < 8)
-		cached_21 |= 1 << irq_nr;
+	if (d->irq < 8)
+		cached_21 |= 1 << d->irq;
 	else
-		cached_A1 |= 1 << (irq_nr-8);
-	i8259_set_irq_mask(irq_nr);
+		cached_A1 |= 1 << (d->irq-8);
+	i8259_set_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
-static void i8259_unmask_irq(unsigned int irq_nr)
+static void i8259_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
-	pr_debug("i8259_unmask_irq(%d)\n", irq_nr);
+	pr_debug("i8259_unmask_irq(%d)\n", d->irq);
 
 	raw_spin_lock_irqsave(&i8259_lock, flags);
-	if (irq_nr < 8)
-		cached_21 &= ~(1 << irq_nr);
+	if (d->irq < 8)
+		cached_21 &= ~(1 << d->irq);
 	else
-		cached_A1 &= ~(1 << (irq_nr-8));
-	i8259_set_irq_mask(irq_nr);
+		cached_A1 &= ~(1 << (d->irq-8));
+	i8259_set_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
 static struct irq_chip i8259_pic = {
 	.name		= "i8259",
-	.mask		= i8259_mask_irq,
-	.disable	= i8259_mask_irq,
-	.unmask		= i8259_unmask_irq,
-	.mask_ack	= i8259_mask_and_ack_irq,
+	.irq_mask	= i8259_mask_irq,
+	.irq_disable	= i8259_mask_irq,
+	.irq_unmask	= i8259_unmask_irq,
+	.irq_mask_ack	= i8259_mask_and_ack_irq,
 };
 
 static struct resource pic1_iores = {
@@ -188,7 +188,7 @@ static int i8259_host_map(struct irq_host *h, unsigned int virq,
 static void i8259_host_unmap(struct irq_host *h, unsigned int virq)
 {
 	/* Make sure irq is masked in hardware */
-	i8259_mask_irq(virq);
+	i8259_mask_irq(irq_get_irq_data(virq));
 
 	/* remove chip and handler */
 	set_irq_chip_and_handler(virq, NULL, NULL);
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index d7b9b9c..497047d 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -523,10 +523,10 @@ static inline struct ipic * ipic_from_irq(unsigned int virq)
 
 #define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
 
-static void ipic_unmask_irq(unsigned int virq)
+static void ipic_unmask_irq(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -539,10 +539,10 @@ static void ipic_unmask_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_mask_irq(unsigned int virq)
+static void ipic_mask_irq(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -559,10 +559,10 @@ static void ipic_mask_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_ack_irq(unsigned int virq)
+static void ipic_ack_irq(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -578,10 +578,10 @@ static void ipic_ack_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_mask_irq_and_ack(unsigned int virq)
+static void ipic_mask_irq_and_ack(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -601,11 +601,11 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	unsigned int vold, vnew, edibit;
 
 	if (flow_type == IRQ_TYPE_NONE)
@@ -630,10 +630,10 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
 	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
 		desc->status |= IRQ_LEVEL;
 		desc->handle_irq = handle_level_irq;
-		desc->chip = &ipic_level_irq_chip;
+		desc->irq_data.chip = &ipic_level_irq_chip;
 	} else {
 		desc->handle_irq = handle_edge_irq;
-		desc->chip = &ipic_edge_irq_chip;
+		desc->irq_data.chip = &ipic_edge_irq_chip;
 	}
 
 	/* only EXT IRQ senses are programmable on ipic
@@ -661,19 +661,19 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
 /* level interrupts and edge interrupts have different ack operations */
 static struct irq_chip ipic_level_irq_chip = {
 	.name		= "IPIC",
-	.unmask		= ipic_unmask_irq,
-	.mask		= ipic_mask_irq,
-	.mask_ack	= ipic_mask_irq,
-	.set_type	= ipic_set_irq_type,
+	.irq_unmask	= ipic_unmask_irq,
+	.irq_mask	= ipic_mask_irq,
+	.irq_mask_ack	= ipic_mask_irq,
+	.irq_set_type	= ipic_set_irq_type,
 };
 
 static struct irq_chip ipic_edge_irq_chip = {
 	.name		= "IPIC",
-	.unmask		= ipic_unmask_irq,
-	.mask		= ipic_mask_irq,
-	.mask_ack	= ipic_mask_irq_and_ack,
-	.ack		= ipic_ack_irq,
-	.set_type	= ipic_set_irq_type,
+	.irq_unmask	= ipic_unmask_irq,
+	.irq_mask	= ipic_mask_irq,
+	.irq_mask_ack	= ipic_mask_irq_and_ack,
+	.irq_ack	= ipic_ack_irq,
+	.irq_set_type	= ipic_set_irq_type,
 };
 
 static int ipic_host_match(struct irq_host *h, struct device_node *node)
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index 8c27d26..1a75a7f 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -25,10 +25,10 @@ static sysconf8xx_t __iomem *siu_reg;
 
 int cpm_get_irq(struct pt_regs *regs);
 
-static void mpc8xx_unmask_irq(unsigned int virq)
+static void mpc8xx_unmask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -37,10 +37,10 @@ static void mpc8xx_unmask_irq(unsigned int virq)
 	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
 }
 
-static void mpc8xx_mask_irq(unsigned int virq)
+static void mpc8xx_mask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -49,19 +49,19 @@ static void mpc8xx_mask_irq(unsigned int virq)
 	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
 }
 
-static void mpc8xx_ack(unsigned int virq)
+static void mpc8xx_ack(struct irq_data *d)
 {
 	int	bit;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
 }
 
-static void mpc8xx_end_irq(unsigned int virq)
+static void mpc8xx_end_irq(struct irq_data *d)
 {
 	int bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -70,9 +70,9 @@ static void mpc8xx_end_irq(unsigned int virq)
 	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
 }
 
-static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 
 	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
 	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
@@ -80,7 +80,7 @@ static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
 		desc->status |= IRQ_LEVEL;
 
 	if (flow_type & IRQ_TYPE_EDGE_FALLING) {
-		irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
+		irq_hw_number_t hw = (unsigned int)irq_map[d->irq].hwirq;
 		unsigned int siel = in_be32(&siu_reg->sc_siel);
 
 		/* only external IRQ senses are programmable */
@@ -95,11 +95,11 @@ static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
 
 static struct irq_chip mpc8xx_pic = {
 	.name = "MPC8XX SIU",
-	.unmask = mpc8xx_unmask_irq,
-	.mask = mpc8xx_mask_irq,
-	.ack = mpc8xx_ack,
-	.eoi = mpc8xx_end_irq,
-	.set_type = mpc8xx_set_irq_type,
+	.irq_unmask = mpc8xx_unmask_irq,
+	.irq_mask = mpc8xx_mask_irq,
+	.irq_ack = mpc8xx_ack,
+	.irq_eoi = mpc8xx_end_irq,
+	.irq_set_type = mpc8xx_set_irq_type,
 };
 
 unsigned int mpc8xx_get_irq(void)
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
index c48cd81..232e701 100644
--- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
+++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
@@ -155,43 +155,43 @@ static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
 						     32 - ffs(mask)));
 }
 
-static void mpc8xxx_irq_unmask(unsigned int virq)
+static void mpc8xxx_irq_unmask(struct irq_data *d)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
+	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 
 	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
-static void mpc8xxx_irq_mask(unsigned int virq)
+static void mpc8xxx_irq_mask(struct irq_data *d)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
+	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 
 	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
-static void mpc8xxx_irq_ack(unsigned int virq)
+static void mpc8xxx_irq_ack(struct irq_data *d)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 
-	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(virq)));
+	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 }
 
-static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned long flags;
 
@@ -199,14 +199,14 @@ static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
 	case IRQ_TYPE_EDGE_FALLING:
 		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		setbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(virq_to_hw(virq)));
+			  mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 		break;
 
 	case IRQ_TYPE_EDGE_BOTH:
 		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		clrbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(virq_to_hw(virq)));
+			  mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 		break;
 
@@ -217,11 +217,11 @@ static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
 	return 0;
 }
 
-static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long gpio = virq_to_hw(virq);
+	unsigned long gpio = virq_to_hw(d->irq);
 	void __iomem *reg;
 	unsigned int shift;
 	unsigned long flags;
@@ -264,10 +264,10 @@ static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type)
 
 static struct irq_chip mpc8xxx_irq_chip = {
 	.name		= "mpc8xxx-gpio",
-	.unmask		= mpc8xxx_irq_unmask,
-	.mask		= mpc8xxx_irq_mask,
-	.ack		= mpc8xxx_irq_ack,
-	.set_type	= mpc8xxx_irq_set_type,
+	.irq_unmask	= mpc8xxx_irq_unmask,
+	.irq_mask	= mpc8xxx_irq_mask,
+	.irq_ack	= mpc8xxx_irq_ack,
+	.irq_set_type	= mpc8xxx_irq_set_type,
 };
 
 static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
@@ -276,7 +276,7 @@ static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
 	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
 
 	if (mpc8xxx_gc->of_dev_id_data)
-		mpc8xxx_irq_chip.set_type = mpc8xxx_gc->of_dev_id_data;
+		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
 
 	set_irq_chip_data(virq, h->host_data);
 	set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
@@ -310,6 +310,7 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {
 	{ .compatible = "fsl,mpc8572-gpio", },
 	{ .compatible = "fsl,mpc8610-gpio", },
 	{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+	{ .compatible = "fsl,qoriq-gpio",   },
 	{}
 };
 
@@ -389,9 +390,6 @@ static int __init mpc8xxx_add_gpiochips(void)
 	for_each_matching_node(np, mpc8xxx_gpio_ids)
 		mpc8xxx_add_controller(np);
 
-	for_each_compatible_node(np, NULL, "fsl,qoriq-gpio")
-		mpc8xxx_add_controller(np);
-
 	return 0;
 }
 arch_initcall(mpc8xxx_add_gpiochips);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index b0c8469..0f7c671 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -147,6 +147,16 @@ static u32 mpic_infos[][MPIC_IDX_END] = {
 
 #endif /* CONFIG_MPIC_WEIRD */
 
+static inline unsigned int mpic_processor_id(struct mpic *mpic)
+{
+	unsigned int cpu = 0;
+
+	if (mpic->flags & MPIC_PRIMARY)
+		cpu = hard_smp_processor_id();
+
+	return cpu;
+}
+
 /*
  * Register accessor functions
  */
@@ -210,19 +220,14 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu
 
 static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
 {
-	unsigned int cpu = 0;
+	unsigned int cpu = mpic_processor_id(mpic);
 
-	if (mpic->flags & MPIC_PRIMARY)
-		cpu = hard_smp_processor_id();
 	return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
 }
 
 static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
 {
-	unsigned int cpu = 0;
-
-	if (mpic->flags & MPIC_PRIMARY)
-		cpu = hard_smp_processor_id();
+	unsigned int cpu = mpic_processor_id(mpic);
 
 	_mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
 }
@@ -611,7 +616,7 @@ static struct mpic *mpic_find(unsigned int irq)
 	if (irq < NUM_ISA_INTERRUPTS)
 		return NULL;
 
-	return irq_to_desc(irq)->chip_data;
+	return get_irq_chip_data(irq);
 }
 
 /* Determine if the linux irq is an IPI */
@@ -636,16 +641,22 @@ static inline u32 mpic_physmask(u32 cpumask)
 
 #ifdef CONFIG_SMP
 /* Get the mpic structure from the IPI number */
-static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+static inline struct mpic * mpic_from_ipi(struct irq_data *d)
 {
-	return irq_to_desc(ipi)->chip_data;
+	return irq_data_get_irq_chip_data(d);
 }
 #endif
 
 /* Get the mpic structure from the irq number */
 static inline struct mpic * mpic_from_irq(unsigned int irq)
 {
-	return irq_to_desc(irq)->chip_data;
+	return get_irq_chip_data(irq);
+}
+
+/* Get the mpic structure from the irq data */
+static inline struct mpic * mpic_from_irq_data(struct irq_data *d)
+{
+	return irq_data_get_irq_chip_data(d);
 }
 
 /* Send an EOI */
@@ -660,13 +671,13 @@ static inline void mpic_eoi(struct mpic *mpic)
  */
 
 
-void mpic_unmask_irq(unsigned int irq)
+void mpic_unmask_irq(struct irq_data *d)
 {
 	unsigned int loops = 100000;
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
+	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
 
 	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
 		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
@@ -681,13 +692,13 @@ void mpic_unmask_irq(unsigned int irq)
 	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
 }
 
-void mpic_mask_irq(unsigned int irq)
+void mpic_mask_irq(struct irq_data *d)
 {
 	unsigned int loops = 100000;
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
 
 	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
 		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
@@ -703,12 +714,12 @@ void mpic_mask_irq(unsigned int irq)
 	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
 }
 
-void mpic_end_irq(unsigned int irq)
+void mpic_end_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
 
 #ifdef DEBUG_IRQ
-	DBG("%s: end_irq: %d\n", mpic->name, irq);
+	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
 #endif
 	/* We always EOI on end_irq() even for edge interrupts since that
 	 * should only lower the priority, the MPIC should have properly
@@ -720,51 +731,51 @@ void mpic_end_irq(unsigned int irq)
 
 #ifdef CONFIG_MPIC_U3_HT_IRQS
 
-static void mpic_unmask_ht_irq(unsigned int irq)
+static void mpic_unmask_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	mpic_unmask_irq(irq);
+	mpic_unmask_irq(d);
 
-	if (irq_to_desc(irq)->status & IRQ_LEVEL)
+	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
 		mpic_ht_end_irq(mpic, src);
 }
 
-static unsigned int mpic_startup_ht_irq(unsigned int irq)
+static unsigned int mpic_startup_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	mpic_unmask_irq(irq);
-	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
+	mpic_unmask_irq(d);
+	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
 
 	return 0;
 }
 
-static void mpic_shutdown_ht_irq(unsigned int irq)
+static void mpic_shutdown_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
-	mpic_mask_irq(irq);
+	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(d->irq)->status);
+	mpic_mask_irq(d);
 }
 
-static void mpic_end_ht_irq(unsigned int irq)
+static void mpic_end_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
 #ifdef DEBUG_IRQ
-	DBG("%s: end_irq: %d\n", mpic->name, irq);
+	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
 #endif
 	/* We always EOI on end_irq() even for edge interrupts since that
 	 * should only lower the priority, the MPIC should have properly
 	 * latched another edge interrupt coming in anyway
 	 */
 
-	if (irq_to_desc(irq)->status & IRQ_LEVEL)
+	if (irq_to_desc(d->irq)->status & IRQ_LEVEL)
 		mpic_ht_end_irq(mpic, src);
 	mpic_eoi(mpic);
 }
@@ -772,23 +783,23 @@ static void mpic_end_ht_irq(unsigned int irq)
 
 #ifdef CONFIG_SMP
 
-static void mpic_unmask_ipi(unsigned int irq)
+static void mpic_unmask_ipi(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_ipi(irq);
-	unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0];
+	struct mpic *mpic = mpic_from_ipi(d);
+	unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
 
-	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
 	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
 }
 
-static void mpic_mask_ipi(unsigned int irq)
+static void mpic_mask_ipi(struct irq_data *d)
 {
 	/* NEVER disable an IPI... that's just plain wrong! */
 }
 
-static void mpic_end_ipi(unsigned int irq)
+static void mpic_end_ipi(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_ipi(irq);
+	struct mpic *mpic = mpic_from_ipi(d);
 
 	/*
 	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
@@ -802,10 +813,11 @@ static void mpic_end_ipi(unsigned int irq)
 
 #endif /* CONFIG_SMP */
 
-int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
+		      bool force)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
 	if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
 		int cpuid = irq_choose_cpu(cpumask);
@@ -848,15 +860,15 @@ static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
 	}
 }
 
-int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
+int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpic *mpic = mpic_from_irq(virq);
-	unsigned int src = mpic_irq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	unsigned int vecpri, vold, vnew;
 
 	DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
-	    mpic, virq, src, flow_type);
+	    mpic, d->irq, src, flow_type);
 
 	if (src >= mpic->irq_count)
 		return -EINVAL;
@@ -906,29 +918,43 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
 	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
 }
 
+void mpic_set_destination(unsigned int virq, unsigned int cpuid)
+{
+	struct mpic *mpic = mpic_from_irq(virq);
+	unsigned int src = mpic_irq_to_hw(virq);
+
+	DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
+	    mpic, virq, src, cpuid);
+
+	if (src >= mpic->irq_count)
+		return;
+
+	mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
+}
+
 static struct irq_chip mpic_irq_chip = {
-	.mask		= mpic_mask_irq,
-	.unmask		= mpic_unmask_irq,
-	.eoi		= mpic_end_irq,
-	.set_type	= mpic_set_irq_type,
+	.irq_mask	= mpic_mask_irq,
+	.irq_unmask	= mpic_unmask_irq,
+	.irq_eoi	= mpic_end_irq,
+	.irq_set_type	= mpic_set_irq_type,
 };
 
 #ifdef CONFIG_SMP
 static struct irq_chip mpic_ipi_chip = {
-	.mask		= mpic_mask_ipi,
-	.unmask		= mpic_unmask_ipi,
-	.eoi		= mpic_end_ipi,
+	.irq_mask	= mpic_mask_ipi,
+	.irq_unmask	= mpic_unmask_ipi,
+	.irq_eoi	= mpic_end_ipi,
 };
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_MPIC_U3_HT_IRQS
 static struct irq_chip mpic_irq_ht_chip = {
-	.startup	= mpic_startup_ht_irq,
-	.shutdown	= mpic_shutdown_ht_irq,
-	.mask		= mpic_mask_irq,
-	.unmask		= mpic_unmask_ht_irq,
-	.eoi		= mpic_end_ht_irq,
-	.set_type	= mpic_set_irq_type,
+	.irq_startup	= mpic_startup_ht_irq,
+	.irq_shutdown	= mpic_shutdown_ht_irq,
+	.irq_mask	= mpic_mask_irq,
+	.irq_unmask	= mpic_unmask_ht_irq,
+	.irq_eoi	= mpic_end_ht_irq,
+	.irq_set_type	= mpic_set_irq_type,
 };
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
@@ -986,6 +1012,16 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
 	/* Set default irq type */
 	set_irq_type(virq, IRQ_TYPE_NONE);
 
+	/* If the MPIC was reset, then all vectors have already been
+	 * initialized.  Otherwise, a per source lazy initialization
+	 * is done here.
+	 */
+	if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+		mpic_set_vector(virq, hw);
+		mpic_set_destination(virq, mpic_processor_id(mpic));
+		mpic_irq_set_priority(virq, 8);
+	}
+
 	return 0;
 }
 
@@ -1033,6 +1069,11 @@ static struct irq_host_ops mpic_host_ops = {
 	.xlate = mpic_host_xlate,
 };
 
+static int mpic_reset_prohibited(struct device_node *node)
+{
+	return node && of_get_property(node, "pic-no-reset", NULL);
+}
+
 /*
  * Exported functions
  */
@@ -1060,12 +1101,12 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 	mpic->hc_irq = mpic_irq_chip;
 	mpic->hc_irq.name = name;
 	if (flags & MPIC_PRIMARY)
-		mpic->hc_irq.set_affinity = mpic_set_affinity;
+		mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
 #ifdef CONFIG_MPIC_U3_HT_IRQS
 	mpic->hc_ht_irq = mpic_irq_ht_chip;
 	mpic->hc_ht_irq.name = name;
 	if (flags & MPIC_PRIMARY)
-		mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
+		mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
 #ifdef CONFIG_SMP
@@ -1153,7 +1194,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
 	mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
 	/* Reset */
-	if (flags & MPIC_WANTS_RESET) {
+
+	/* When using a device-node, reset requests are only honored if the MPIC
+	 * is allowed to reset.
+	 */
+	if (mpic_reset_prohibited(node))
+		mpic->flags |= MPIC_NO_RESET;
+
+	if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
+		printk(KERN_DEBUG "mpic: Resetting\n");
 		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
 			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 			   | MPIC_GREG_GCONF_RESET);
@@ -1313,22 +1362,21 @@ void __init mpic_init(struct mpic *mpic)
 
 	mpic_pasemi_msi_init(mpic);
 
-	if (mpic->flags & MPIC_PRIMARY)
-		cpu = hard_smp_processor_id();
-	else
-		cpu = 0;
+	cpu = mpic_processor_id(mpic);
 
-	for (i = 0; i < mpic->num_sources; i++) {
-		/* start with vector = source number, and masked */
-		u32 vecpri = MPIC_VECPRI_MASK | i |
-			(8 << MPIC_VECPRI_PRIORITY_SHIFT);
+	if (!(mpic->flags & MPIC_NO_RESET)) {
+		for (i = 0; i < mpic->num_sources; i++) {
+			/* start with vector = source number, and masked */
+			u32 vecpri = MPIC_VECPRI_MASK | i |
+				(8 << MPIC_VECPRI_PRIORITY_SHIFT);
 		
-		/* check if protected */
-		if (mpic->protected && test_bit(i, mpic->protected))
-			continue;
-		/* init hw */
-		mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
-		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+			/* check if protected */
+			if (mpic->protected && test_bit(i, mpic->protected))
+				continue;
+			/* init hw */
+			mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+			mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+		}
 	}
 	
 	/* Init spurious vector */
diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h
index e4a6df7..13f3e89 100644
--- a/arch/powerpc/sysdev/mpic.h
+++ b/arch/powerpc/sysdev/mpic.h
@@ -34,9 +34,10 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
 }
 #endif
 
-extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type);
 extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
+extern int mpic_set_affinity(struct irq_data *d,
+			     const struct cpumask *cpumask, bool force);
 extern void mpic_reset_core(int cpu);
 
 #endif /* _POWERPC_SYSDEV_MPIC_H */
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c
index 320ad5a..0b7794a 100644
--- a/arch/powerpc/sysdev/mpic_pasemi_msi.c
+++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c
@@ -43,24 +43,24 @@ static void mpic_pasemi_msi_mask_irq(struct irq_data *data)
 {
 	pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
 	mask_msi_irq(data);
-	mpic_mask_irq(data->irq);
+	mpic_mask_irq(data);
 }
 
 static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
 {
 	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
-	mpic_unmask_irq(data->irq);
+	mpic_unmask_irq(data);
 	unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_pasemi_msi_chip = {
-	.irq_shutdown	= mpic_pasemi_msi_mask_irq,
-	.irq_mask	= mpic_pasemi_msi_mask_irq,
-	.irq_unmask	= mpic_pasemi_msi_unmask_irq,
-	.eoi		= mpic_end_irq,
-	.set_type	= mpic_set_irq_type,
-	.set_affinity	= mpic_set_affinity,
-	.name		= "PASEMI-MSI",
+	.irq_shutdown		= mpic_pasemi_msi_mask_irq,
+	.irq_mask		= mpic_pasemi_msi_mask_irq,
+	.irq_unmask		= mpic_pasemi_msi_unmask_irq,
+	.irq_eoi		= mpic_end_irq,
+	.irq_set_type		= mpic_set_irq_type,
+	.irq_set_affinity	= mpic_set_affinity,
+	.name			= "PASEMI-MSI",
 };
 
 static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
index a2b028b..71900ac 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -26,23 +26,23 @@ static struct mpic *msi_mpic;
 static void mpic_u3msi_mask_irq(struct irq_data *data)
 {
 	mask_msi_irq(data);
-	mpic_mask_irq(data->irq);
+	mpic_mask_irq(data);
 }
 
 static void mpic_u3msi_unmask_irq(struct irq_data *data)
 {
-	mpic_unmask_irq(data->irq);
+	mpic_unmask_irq(data);
 	unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_u3msi_chip = {
-	.irq_shutdown	= mpic_u3msi_mask_irq,
-	.irq_mask	= mpic_u3msi_mask_irq,
-	.irq_unmask	= mpic_u3msi_unmask_irq,
-	.eoi		= mpic_end_irq,
-	.set_type	= mpic_set_irq_type,
-	.set_affinity	= mpic_set_affinity,
-	.name		= "MPIC-U3MSI",
+	.irq_shutdown		= mpic_u3msi_mask_irq,
+	.irq_mask		= mpic_u3msi_mask_irq,
+	.irq_unmask		= mpic_u3msi_unmask_irq,
+	.irq_eoi		= mpic_end_irq,
+	.irq_set_type		= mpic_set_irq_type,
+	.irq_set_affinity	= mpic_set_affinity,
+	.name			= "MPIC-U3MSI",
 };
 
 static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index feaee40..0f6af41 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -346,7 +346,7 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
 	if (prop)
 		pdata.freq_m = *prop;
 
-	pdata.freq_m = 3;	/* default */
+	pdata.freq_n = 3;	/* default */
 	prop = of_get_property(np, "freq_n", NULL);
 	if (prop)
 		pdata.freq_n = *prop;
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c
index 485b924..bc61ebb 100644
--- a/arch/powerpc/sysdev/mv64x60_pic.c
+++ b/arch/powerpc/sysdev/mv64x60_pic.c
@@ -76,9 +76,9 @@ static struct irq_host *mv64x60_irq_host;
  * mv64x60_chip_low functions
  */
 
-static void mv64x60_mask_low(unsigned int virq)
+static void mv64x60_mask_low(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -89,9 +89,9 @@ static void mv64x60_mask_low(unsigned int virq)
 	(void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO);
 }
 
-static void mv64x60_unmask_low(unsigned int virq)
+static void mv64x60_unmask_low(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -104,18 +104,18 @@ static void mv64x60_unmask_low(unsigned int virq)
 
 static struct irq_chip mv64x60_chip_low = {
 	.name		= "mv64x60_low",
-	.mask		= mv64x60_mask_low,
-	.mask_ack	= mv64x60_mask_low,
-	.unmask		= mv64x60_unmask_low,
+	.irq_mask	= mv64x60_mask_low,
+	.irq_mask_ack	= mv64x60_mask_low,
+	.irq_unmask	= mv64x60_unmask_low,
 };
 
 /*
  * mv64x60_chip_high functions
  */
 
-static void mv64x60_mask_high(unsigned int virq)
+static void mv64x60_mask_high(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -126,9 +126,9 @@ static void mv64x60_mask_high(unsigned int virq)
 	(void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI);
 }
 
-static void mv64x60_unmask_high(unsigned int virq)
+static void mv64x60_unmask_high(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -141,18 +141,18 @@ static void mv64x60_unmask_high(unsigned int virq)
 
 static struct irq_chip mv64x60_chip_high = {
 	.name		= "mv64x60_high",
-	.mask		= mv64x60_mask_high,
-	.mask_ack	= mv64x60_mask_high,
-	.unmask		= mv64x60_unmask_high,
+	.irq_mask	= mv64x60_mask_high,
+	.irq_mask_ack	= mv64x60_mask_high,
+	.irq_unmask	= mv64x60_unmask_high,
 };
 
 /*
  * mv64x60_chip_gpp functions
  */
 
-static void mv64x60_mask_gpp(unsigned int virq)
+static void mv64x60_mask_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -163,9 +163,9 @@ static void mv64x60_mask_gpp(unsigned int virq)
 	(void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK);
 }
 
-static void mv64x60_mask_ack_gpp(unsigned int virq)
+static void mv64x60_mask_ack_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -178,9 +178,9 @@ static void mv64x60_mask_ack_gpp(unsigned int virq)
 	(void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE);
 }
 
-static void mv64x60_unmask_gpp(unsigned int virq)
+static void mv64x60_unmask_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -193,9 +193,9 @@ static void mv64x60_unmask_gpp(unsigned int virq)
 
 static struct irq_chip mv64x60_chip_gpp = {
 	.name		= "mv64x60_gpp",
-	.mask		= mv64x60_mask_gpp,
-	.mask_ack	= mv64x60_mask_ack_gpp,
-	.unmask		= mv64x60_unmask_gpp,
+	.irq_mask	= mv64x60_mask_gpp,
+	.irq_mask_ack	= mv64x60_mask_ack_gpp,
+	.irq_unmask	= mv64x60_unmask_gpp,
 };
 
 /*
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c
index 4260f36..8ce4fc3 100644
--- a/arch/powerpc/sysdev/pmi.c
+++ b/arch/powerpc/sysdev/pmi.c
@@ -121,8 +121,7 @@ static void pmi_notify_handlers(struct work_struct *work)
 	spin_unlock(&data->handler_spinlock);
 }
 
-static int pmi_of_probe(struct platform_device *dev,
-			const struct of_device_id *match)
+static int pmi_of_probe(struct platform_device *dev)
 {
 	struct device_node *np = dev->dev.of_node;
 	int rc;
@@ -205,7 +204,7 @@ static int pmi_of_remove(struct platform_device *dev)
 	return 0;
 }
 
-static struct of_platform_driver pmi_of_platform_driver = {
+static struct platform_driver pmi_of_platform_driver = {
 	.probe		= pmi_of_probe,
 	.remove		= pmi_of_remove,
 	.driver = {
@@ -217,13 +216,13 @@ static struct of_platform_driver pmi_of_platform_driver = {
 
 static int __init pmi_module_init(void)
 {
-	return of_register_platform_driver(&pmi_of_platform_driver);
+	return platform_driver_register(&pmi_of_platform_driver);
 }
 module_init(pmi_module_init);
 
 static void __exit pmi_module_exit(void)
 {
-	of_unregister_platform_driver(&pmi_of_platform_driver);
+	platform_driver_unregister(&pmi_of_platform_driver);
 }
 module_exit(pmi_module_exit);
 
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 90020de..904c6cb 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -659,8 +659,7 @@ static int qe_resume(struct platform_device *ofdev)
 	return 0;
 }
 
-static int qe_probe(struct platform_device *ofdev,
-		    const struct of_device_id *id)
+static int qe_probe(struct platform_device *ofdev)
 {
 	return 0;
 }
@@ -670,7 +669,7 @@ static const struct of_device_id qe_ids[] = {
 	{ },
 };
 
-static struct of_platform_driver qe_driver = {
+static struct platform_driver qe_driver = {
 	.driver = {
 		.name = "fsl-qe",
 		.owner = THIS_MODULE,
@@ -682,7 +681,7 @@ static struct of_platform_driver qe_driver = {
 
 static int __init qe_drv_init(void)
 {
-	return of_register_platform_driver(&qe_driver);
+	return platform_driver_register(&qe_driver);
 }
 device_initcall(qe_drv_init);
 #endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */
diff --git a/arch/powerpc/sysdev/qe_lib/qe_ic.c b/arch/powerpc/sysdev/qe_lib/qe_ic.c
index 541ba98..8c9ded8 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_ic.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_ic.c
@@ -189,15 +189,20 @@ static inline void qe_ic_write(volatile __be32  __iomem * base, unsigned int reg
 
 static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
 {
-	return irq_to_desc(virq)->chip_data;
+	return get_irq_chip_data(virq);
+}
+
+static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
+{
+	return irq_data_get_irq_chip_data(d);
 }
 
 #define virq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
 
-static void qe_ic_unmask_irq(unsigned int virq)
+static void qe_ic_unmask_irq(struct irq_data *d)
 {
-	struct qe_ic *qe_ic = qe_ic_from_irq(virq);
-	unsigned int src = virq_to_hw(virq);
+	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
+	unsigned int src = virq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -210,10 +215,10 @@ static void qe_ic_unmask_irq(unsigned int virq)
 	raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
 }
 
-static void qe_ic_mask_irq(unsigned int virq)
+static void qe_ic_mask_irq(struct irq_data *d)
 {
-	struct qe_ic *qe_ic = qe_ic_from_irq(virq);
-	unsigned int src = virq_to_hw(virq);
+	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
+	unsigned int src = virq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -238,9 +243,9 @@ static void qe_ic_mask_irq(unsigned int virq)
 
 static struct irq_chip qe_ic_irq_chip = {
 	.name = "QEIC",
-	.unmask = qe_ic_unmask_irq,
-	.mask = qe_ic_mask_irq,
-	.mask_ack = qe_ic_mask_irq,
+	.irq_unmask = qe_ic_unmask_irq,
+	.irq_mask = qe_ic_mask_irq,
+	.irq_mask_ack = qe_ic_mask_irq,
 };
 
 static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c
index 0ab9281..02c91db 100644
--- a/arch/powerpc/sysdev/tsi108_pci.c
+++ b/arch/powerpc/sysdev/tsi108_pci.c
@@ -343,24 +343,9 @@ static inline unsigned int get_pci_source(void)
  * Linux descriptor level callbacks
  */
 
-static void tsi108_pci_irq_enable(u_int irq)
+static void tsi108_pci_irq_unmask(struct irq_data *d)
 {
-	tsi108_pci_int_unmask(irq);
-}
-
-static void tsi108_pci_irq_disable(u_int irq)
-{
-	tsi108_pci_int_mask(irq);
-}
-
-static void tsi108_pci_irq_ack(u_int irq)
-{
-	tsi108_pci_int_mask(irq);
-}
-
-static void tsi108_pci_irq_end(u_int irq)
-{
-	tsi108_pci_int_unmask(irq);
+	tsi108_pci_int_unmask(d->irq);
 
 	/* Enable interrupts from PCI block */
 	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
@@ -370,16 +355,25 @@ static void tsi108_pci_irq_end(u_int irq)
 	mb();
 }
 
+static void tsi108_pci_irq_mask(struct irq_data *d)
+{
+	tsi108_pci_int_mask(d->irq);
+}
+
+static void tsi108_pci_irq_ack(struct irq_data *d)
+{
+	tsi108_pci_int_mask(d->irq);
+}
+
 /*
  * Interrupt controller descriptor for cascaded PCI interrupt controller.
  */
 
 static struct irq_chip tsi108_pci_irq = {
 	.name = "tsi108_PCI_int",
-	.mask = tsi108_pci_irq_disable,
-	.ack = tsi108_pci_irq_ack,
-	.end = tsi108_pci_irq_end,
-	.unmask = tsi108_pci_irq_enable,
+	.irq_mask = tsi108_pci_irq_mask,
+	.irq_ack = tsi108_pci_irq_ack,
+	.irq_unmask = tsi108_pci_irq_unmask,
 };
 
 static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,
@@ -437,8 +431,11 @@ void __init tsi108_pci_int_init(struct device_node *node)
 
 void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq = get_pci_source();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 0038fb7..835f795 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -55,11 +55,11 @@ struct uic {
 	struct irq_host	*irqhost;
 };
 
-static void uic_unmask_irq(unsigned int virq)
+static void uic_unmask_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 er, sr;
 
@@ -74,10 +74,10 @@ static void uic_unmask_irq(unsigned int virq)
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static void uic_mask_irq(unsigned int virq)
+static void uic_mask_irq(struct irq_data *d)
 {
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 er;
 
@@ -88,10 +88,10 @@ static void uic_mask_irq(unsigned int virq)
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static void uic_ack_irq(unsigned int virq)
+static void uic_ack_irq(struct irq_data *d)
 {
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&uic->lock, flags);
@@ -99,11 +99,11 @@ static void uic_ack_irq(unsigned int virq)
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static void uic_mask_ack_irq(unsigned int virq)
+static void uic_mask_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 er, sr;
 
@@ -125,18 +125,18 @@ static void uic_mask_ack_irq(unsigned int virq)
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 	unsigned long flags;
 	int trigger, polarity;
 	u32 tr, pr, mask;
 
 	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_NONE:
-		uic_mask_irq(virq);
+		uic_mask_irq(d);
 		return 0;
 
 	case IRQ_TYPE_EDGE_RISING:
@@ -178,11 +178,11 @@ static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
 
 static struct irq_chip uic_irq_chip = {
 	.name		= "UIC",
-	.unmask		= uic_unmask_irq,
-	.mask		= uic_mask_irq,
- 	.mask_ack	= uic_mask_ack_irq,
-	.ack		= uic_ack_irq,
-	.set_type	= uic_set_irq_type,
+	.irq_unmask	= uic_unmask_irq,
+	.irq_mask	= uic_mask_irq,
+	.irq_mask_ack	= uic_mask_ack_irq,
+	.irq_ack	= uic_ack_irq,
+	.irq_set_type	= uic_set_irq_type,
 };
 
 static int uic_host_map(struct irq_host *h, unsigned int virq,
@@ -220,6 +220,7 @@ static struct irq_host_ops uic_host_ops = {
 
 void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	struct uic *uic = get_irq_data(virq);
 	u32 msr;
 	int src;
@@ -227,9 +228,9 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 
 	raw_spin_lock(&desc->lock);
 	if (desc->status & IRQ_LEVEL)
-		desc->chip->mask(virq);
+		chip->irq_mask(&desc->irq_data);
 	else
-		desc->chip->mask_ack(virq);
+		chip->irq_mask_ack(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 
 	msr = mfdcr(uic->dcrbase + UIC_MSR);
@@ -244,9 +245,9 @@ void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 uic_irq_ret:
 	raw_spin_lock(&desc->lock);
 	if (desc->status & IRQ_LEVEL)
-		desc->chip->ack(virq);
-	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-		desc->chip->unmask(virq);
+		chip->irq_ack(&desc->irq_data);
+	if (!(desc->status & IRQ_DISABLED) && chip->irq_unmask)
+		chip->irq_unmask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 }
 
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 1e0ccfa..7436f3e 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -69,17 +69,17 @@ static unsigned char xilinx_intc_map_senses[] = {
  *
  * IRQ Chip common (across level and edge) operations
  */
-static void xilinx_intc_mask(unsigned int virq)
+static void xilinx_intc_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void * regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("mask: %d\n", irq);
 	out_be32(regs + XINTC_CIE, 1 << irq);
 }
 
-static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
+static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct irq_desc *desc = irq_to_desc(d->irq);
 
 	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
 	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
@@ -91,10 +91,10 @@ static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
 /*
  * IRQ Chip level operations
  */
-static void xilinx_intc_level_unmask(unsigned int virq)
+static void xilinx_intc_level_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void * regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("unmask: %d\n", irq);
 	out_be32(regs + XINTC_SIE, 1 << irq);
 
@@ -107,37 +107,37 @@ static void xilinx_intc_level_unmask(unsigned int virq)
 
 static struct irq_chip xilinx_intc_level_irqchip = {
 	.name = "Xilinx Level INTC",
-	.mask = xilinx_intc_mask,
-	.mask_ack = xilinx_intc_mask,
-	.unmask = xilinx_intc_level_unmask,
-	.set_type = xilinx_intc_set_type,
+	.irq_mask = xilinx_intc_mask,
+	.irq_mask_ack = xilinx_intc_mask,
+	.irq_unmask = xilinx_intc_level_unmask,
+	.irq_set_type = xilinx_intc_set_type,
 };
 
 /*
  * IRQ Chip edge operations
  */
-static void xilinx_intc_edge_unmask(unsigned int virq)
+static void xilinx_intc_edge_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void *regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void *regs = irq_data_get_irq_chip_data(d);
 	pr_debug("unmask: %d\n", irq);
 	out_be32(regs + XINTC_SIE, 1 << irq);
 }
 
-static void xilinx_intc_edge_ack(unsigned int virq)
+static void xilinx_intc_edge_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void * regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("ack: %d\n", irq);
 	out_be32(regs + XINTC_IAR, 1 << irq);
 }
 
 static struct irq_chip xilinx_intc_edge_irqchip = {
 	.name = "Xilinx Edge  INTC",
-	.mask = xilinx_intc_mask,
-	.unmask = xilinx_intc_edge_unmask,
-	.ack = xilinx_intc_edge_ack,
-	.set_type = xilinx_intc_set_type,
+	.irq_mask = xilinx_intc_mask,
+	.irq_unmask = xilinx_intc_edge_unmask,
+	.irq_ack = xilinx_intc_edge_ack,
+	.irq_set_type = xilinx_intc_set_type,
 };
 
 /*
@@ -229,12 +229,14 @@ int xilinx_intc_get_irq(void)
  */
 static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = get_irq_desc_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq)
 		generic_handle_irq(cascade_irq);
 
 	/* Let xilinx_intc end the interrupt */
-	desc->chip->unmask(irq);
+	chip->irq_unmask(&desc->irq_data);
 }
 
 static void __init xilinx_i8259_setup_cascade(void)
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 636bcb8..2508a6f 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -85,6 +85,7 @@ config S390
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_XZ
 	select HAVE_GET_USER_PAGES_FAST
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select ARCH_INLINE_SPIN_TRYLOCK
@@ -341,26 +342,16 @@ config STACK_GUARD
 	  The minimum size for the stack guard should be 256 for 31 bit and
 	  512 for 64 bit.
 
-config WARN_STACK
+config WARN_DYNAMIC_STACK
 	def_bool n
-	prompt "Emit compiler warnings for function with broken stack usage"
+	prompt "Emit compiler warnings for function with dynamic stack usage"
 	help
-	  This option enables the compiler options -mwarn-framesize and
-	  -mwarn-dynamicstack. If the compiler supports these options it
-	  will generate warnings for function which either use alloca or
-	  create a stack frame bigger than CONFIG_WARN_STACK_SIZE.
+	  This option enables the compiler option -mwarn-dynamicstack. If the
+	  compiler supports this options generates warnings for functions
+	  that dynamically allocate stack space using alloca.
 
 	  Say N if you are unsure.
 
-config WARN_STACK_SIZE
-	int "Maximum frame size considered safe (128-2048)"
-	range 128 2048
-	depends on WARN_STACK
-	default "2048"
-	help
-	  This allows you to specify the maximum frame size a function may
-	  have without the compiler complaining about it.
-
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
 
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
index 2b380df..d76cef3 100644
--- a/arch/s390/Kconfig.debug
+++ b/arch/s390/Kconfig.debug
@@ -31,4 +31,7 @@ config DEBUG_STRICT_USER_COPY_CHECKS
 
 	  If unsure, or if you run an older (pre 4.4) gcc, say N.
 
+config DEBUG_SET_MODULE_RONX
+	def_bool y
+	depends on MODULES
 endmenu
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index d5b8a6a..27a0b5d 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -80,8 +80,7 @@ endif
 endif
 
 ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
-cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
-cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
+cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
 endif
 
 KBUILD_CFLAGS	+= -mbackchain -msoft-float $(cflags-y)
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile
index 8800cf09..635d677 100644
--- a/arch/s390/boot/Makefile
+++ b/arch/s390/boot/Makefile
@@ -6,7 +6,7 @@ COMPILE_VERSION := __linux_compile_version_id__`hostname |  \
 			tr -c '[0-9A-Za-z]' '_'`__`date | \
 			tr -c '[0-9A-Za-z]' '_'`_t
 
-EXTRA_CFLAGS  := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
+ccflags-y  := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
 
 targets := image
 targets += bzImage
diff --git a/arch/s390/boot/compressed/Makefile b/arch/s390/boot/compressed/Makefile
index 1c999f7..10e22c4 100644
--- a/arch/s390/boot/compressed/Makefile
+++ b/arch/s390/boot/compressed/Makefile
@@ -7,7 +7,8 @@
 BITS := $(if $(CONFIG_64BIT),64,31)
 
 targets	:= vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \
-	   vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o sizes.h head$(BITS).o
+	   vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \
+	   sizes.h head$(BITS).o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += $(cflags-y)
@@ -48,6 +49,7 @@ suffix-$(CONFIG_KERNEL_GZIP)  := gz
 suffix-$(CONFIG_KERNEL_BZIP2) := bz2
 suffix-$(CONFIG_KERNEL_LZMA)  := lzma
 suffix-$(CONFIG_KERNEL_LZO)  := lzo
+suffix-$(CONFIG_KERNEL_XZ)  := xz
 
 $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y)
 	$(call if_changed,gzip)
@@ -57,6 +59,8 @@ $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y)
 	$(call if_changed,lzma)
 $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y)
 	$(call if_changed,lzo)
+$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y)
+	$(call if_changed,xzkern)
 
 LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T
 $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y)
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c
index 2751b3a..028f23e 100644
--- a/arch/s390/boot/compressed/misc.c
+++ b/arch/s390/boot/compressed/misc.c
@@ -19,6 +19,7 @@
 #undef memset
 #undef memcpy
 #undef memmove
+#define memmove memmove
 #define memzero(s, n) memset((s), 0, (n))
 
 /* Symbols defined by linker scripts */
@@ -54,6 +55,10 @@ static unsigned long free_mem_end_ptr;
 #include "../../../../lib/decompress_unlzo.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 extern _sclp_print_early(const char *);
 
 int puts(const char *s)
diff --git a/arch/s390/include/asm/cacheflush.h b/arch/s390/include/asm/cacheflush.h
index 7e1f776..43a5c78 100644
--- a/arch/s390/include/asm/cacheflush.h
+++ b/arch/s390/include/asm/cacheflush.h
@@ -8,4 +8,8 @@
 void kernel_map_pages(struct page *page, int numpages, int enable);
 #endif
 
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+
 #endif /* _S390_CACHEFLUSH_H */
diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h
index 5c5d02d..81cf36b 100644
--- a/arch/s390/include/asm/futex.h
+++ b/arch/s390/include/asm/futex.h
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -39,13 +39,13 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
+	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h
index 423fdda..d0eb465 100644
--- a/arch/s390/include/asm/rwsem.h
+++ b/arch/s390/include/asm/rwsem.h
@@ -43,29 +43,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-struct rwsem_waiter;
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_downgrade_write(struct rw_semaphore *);
-
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	signed long		count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
 #ifndef __s390x__
 #define RWSEM_UNLOCKED_VALUE	0x00000000
 #define RWSEM_ACTIVE_BIAS	0x00000001
@@ -81,41 +58,6 @@ struct rw_semaphore {
 #define RWSEM_ACTIVE_WRITE_BIAS	(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
 /*
- * initialisation
- */
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
- { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait.lock), \
-   LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)				\
-do {						\
-	static struct lock_class_key __key;	\
-						\
-	__init_rwsem((sem), #sem, &__key);	\
-} while (0)
-
-
-/*
  * lock for reading
  */
 static inline void __down_read(struct rw_semaphore *sem)
@@ -377,10 +319,5 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 	return new;
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _S390_RWSEM_H */
diff --git a/arch/s390/include/asm/types.h b/arch/s390/include/asm/types.h
index 04d6b95..f7f6ae6 100644
--- a/arch/s390/include/asm/types.h
+++ b/arch/s390/include/asm/types.h
@@ -31,12 +31,6 @@ typedef __signed__ long saddr_t;
 #ifndef __ASSEMBLY__
 
 typedef u64 dma64_addr_t;
-#ifdef __s390x__
-/* DMA addresses come in 32-bit and 64-bit flavours. */
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
 
 #ifndef __s390x__
 typedef union {
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index d6b1ed0..2d9ea11f 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -83,8 +83,8 @@ struct uaccess_ops {
 	size_t (*clear_user)(size_t, void __user *);
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
+	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
+	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
 };
 
 extern struct uaccess_ops uaccess;
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index a922d51..b09b9c6 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -12,6 +12,7 @@
 #include <linux/kexec.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
+#include <linux/ftrace.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
@@ -71,6 +72,7 @@ static void __machine_kexec(void *data)
 
 void machine_kexec(struct kimage *image)
 {
+	tracer_disable();
 	smp_send_stop();
 	smp_switch_to_ipl_cpu(__machine_kexec, image);
 }
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index a68ac10..1bc18cd 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -77,7 +77,7 @@ SECTIONS
 	. = ALIGN(PAGE_SIZE);
 	INIT_DATA_SECTION(0x100)
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(0x100, PAGE_SIZE)
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;		/* freed after init ends here */
 
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index e5221ec..860d265 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -8,7 +8,7 @@
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm
+ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
 kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
 obj-$(CONFIG_KVM) += kvm.o
diff --git a/arch/s390/lib/uaccess.h b/arch/s390/lib/uaccess.h
index 126011d..1d2536c 100644
--- a/arch/s390/lib/uaccess.h
+++ b/arch/s390/lib/uaccess.h
@@ -12,12 +12,12 @@ extern size_t copy_from_user_std(size_t, const void __user *, void *);
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int __user *, int, int);
-extern int futex_atomic_op_std(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
+extern int futex_atomic_op_std(int, u32 __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
-extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c
index 404f2de..7483383 100644
--- a/arch/s390/lib/uaccess_pt.c
+++ b/arch/s390/lib/uaccess_pt.c
@@ -302,7 +302,7 @@ fault:
 		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		       "m" (*uaddr) : "cc" );
 
-static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -335,7 +335,7 @@ static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int ret;
 
@@ -354,26 +354,29 @@ int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+				     u32 oldval, u32 newval)
 {
 	int ret;
 
 	asm volatile("0: cs   %1,%4,0(%5)\n"
-		     "1: lr   %0,%1\n"
+		     "1: la   %0,0\n"
 		     "2:\n"
 		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		     : "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+			    u32 oldval, u32 newval)
 {
 	int ret;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
 	if (!uaddr) {
@@ -382,7 +385,7 @@ int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
 	}
 	get_page(virt_to_page(uaddr));
 	spin_unlock(&current->mm->page_table_lock);
-	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
diff --git a/arch/s390/lib/uaccess_std.c b/arch/s390/lib/uaccess_std.c
index a6c4f7e..bb1a7ee 100644
--- a/arch/s390/lib/uaccess_std.c
+++ b/arch/s390/lib/uaccess_std.c
@@ -255,7 +255,7 @@ size_t strncpy_from_user_std(size_t size, const char __user *src, char *dst)
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		  "m" (*uaddr) : "cc");
 
-int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -287,19 +287,21 @@ int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
+			     u32 oldval, u32 newval)
 {
 	int ret;
 
 	asm volatile(
 		"   sacf 256\n"
 		"0: cs   %1,%4,0(%5)\n"
-		"1: lr   %0,%1\n"
+		"1: la   %0,0\n"
 		"2: sacf 0\n"
 		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		: "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
diff --git a/arch/s390/math-emu/Makefile b/arch/s390/math-emu/Makefile
index c848903..51d3995 100644
--- a/arch/s390/math-emu/Makefile
+++ b/arch/s390/math-emu/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_MATHEMU) := math.o
 
-EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
+ccflags-y := -I$(src) -Iinclude/math-emu -w
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index 6fbc6f3..d98fe90 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -6,3 +6,4 @@ obj-y	 := init.o fault.o extmem.o mmap.o vmem.o pgtable.o maccess.o \
 	    page-states.o gup.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
new file mode 100644
index 0000000..122ffbd
--- /dev/null
+++ b/arch/s390/mm/pageattr.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright IBM Corp. 2011
+ * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <asm/pgtable.h>
+
+static void change_page_attr(unsigned long addr, int numpages,
+			     pte_t (*set) (pte_t))
+{
+	pte_t *ptep, pte;
+	pmd_t *pmdp;
+	pud_t *pudp;
+	pgd_t *pgdp;
+	int i;
+
+	for (i = 0; i < numpages; i++) {
+		pgdp = pgd_offset(&init_mm, addr);
+		pudp = pud_offset(pgdp, addr);
+		pmdp = pmd_offset(pudp, addr);
+		if (pmd_huge(*pmdp)) {
+			WARN_ON_ONCE(1);
+			continue;
+		}
+		ptep = pte_offset_kernel(pmdp, addr + i * PAGE_SIZE);
+
+		pte = *ptep;
+		pte = set(pte);
+		ptep_invalidate(&init_mm, addr + i * PAGE_SIZE, ptep);
+		*ptep = pte;
+	}
+}
+
+int set_memory_ro(unsigned long addr, int numpages)
+{
+	change_page_attr(addr, numpages, pte_wrprotect);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_ro);
+
+int set_memory_rw(unsigned long addr, int numpages)
+{
+	change_page_attr(addr, numpages, pte_mkwrite);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_rw);
+
+/* not possible */
+int set_memory_nx(unsigned long addr, int numpages)
+{
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_nx);
diff --git a/arch/s390/oprofile/Makefile b/arch/s390/oprofile/Makefile
index 537b2d8..d698cdd 100644
--- a/arch/s390/oprofile/Makefile
+++ b/arch/s390/oprofile/Makefile
@@ -6,4 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
 		oprofilefs.o oprofile_stats.o  \
 		timer_int.o )
 
-oprofile-y				:= $(DRIVER_OBJS) init.o backtrace.o
+oprofile-y :=	$(DRIVER_OBJS) init.o backtrace.o hwsampler.o
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c
new file mode 100644
index 0000000..3d48f4d
--- /dev/null
+++ b/arch/s390/oprofile/hwsampler.c
@@ -0,0 +1,1256 @@
+/**
+ * arch/s390/oprofile/hwsampler.c
+ *
+ * Copyright IBM Corp. 2010
+ * Author: Heinz Graalfs <graalfs@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/semaphore.h>
+#include <linux/oom.h>
+#include <linux/oprofile.h>
+
+#include <asm/lowcore.h>
+#include <asm/s390_ext.h>
+
+#include "hwsampler.h"
+
+#define MAX_NUM_SDB 511
+#define MIN_NUM_SDB 1
+
+#define ALERT_REQ_MASK   0x4000000000000000ul
+#define BUFFER_FULL_MASK 0x8000000000000000ul
+
+#define EI_IEA      (1 << 31)	/* invalid entry address              */
+#define EI_ISE      (1 << 30)	/* incorrect SDBT entry               */
+#define EI_PRA      (1 << 29)	/* program request alert              */
+#define EI_SACA     (1 << 23)	/* sampler authorization change alert */
+#define EI_LSDA     (1 << 22)	/* loss of sample data alert          */
+
+DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
+
+struct hws_execute_parms {
+	void *buffer;
+	signed int rc;
+};
+
+DEFINE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
+EXPORT_PER_CPU_SYMBOL(sampler_cpu_buffer);
+
+static DEFINE_MUTEX(hws_sem);
+static DEFINE_MUTEX(hws_sem_oom);
+
+static unsigned char hws_flush_all;
+static unsigned int hws_oom;
+static struct workqueue_struct *hws_wq;
+
+static unsigned int hws_state;
+enum {
+	HWS_INIT = 1,
+	HWS_DEALLOCATED,
+	HWS_STOPPED,
+	HWS_STARTED,
+	HWS_STOPPING };
+
+/* set to 1 if called by kernel during memory allocation */
+static unsigned char oom_killer_was_active;
+/* size of SDBT and SDB as of allocate API */
+static unsigned long num_sdbt = 100;
+static unsigned long num_sdb = 511;
+/* sampling interval (machine cycles) */
+static unsigned long interval;
+
+static unsigned long min_sampler_rate;
+static unsigned long max_sampler_rate;
+
+static int ssctl(void *buffer)
+{
+	int cc;
+
+	/* set in order to detect a program check */
+	cc = 1;
+
+	asm volatile(
+		"0: .insn s,0xB2870000,0(%1)\n"
+		"1: ipm %0\n"
+		"   srl %0,28\n"
+		"2:\n"
+		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+		: "+d" (cc), "+a" (buffer)
+		: "m" (*((struct hws_ssctl_request_block *)buffer))
+		: "cc", "memory");
+
+	return cc ? -EINVAL : 0 ;
+}
+
+static int qsi(void *buffer)
+{
+	int cc;
+	cc = 1;
+
+	asm volatile(
+		"0: .insn s,0xB2860000,0(%1)\n"
+		"1: lhi %0,0\n"
+		"2:\n"
+		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+		: "=d" (cc), "+a" (buffer)
+		: "m" (*((struct hws_qsi_info_block *)buffer))
+		: "cc", "memory");
+
+	return cc ? -EINVAL : 0;
+}
+
+static void execute_qsi(void *parms)
+{
+	struct hws_execute_parms *ep = parms;
+
+	ep->rc = qsi(ep->buffer);
+}
+
+static void execute_ssctl(void *parms)
+{
+	struct hws_execute_parms *ep = parms;
+
+	ep->rc = ssctl(ep->buffer);
+}
+
+static int smp_ctl_ssctl_stop(int cpu)
+{
+	int rc;
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	cb->ssctl.es = 0;
+	cb->ssctl.cs = 0;
+
+	ep.buffer = &cb->ssctl;
+	smp_call_function_single(cpu, execute_ssctl, &ep, 1);
+	rc = ep.rc;
+	if (rc) {
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
+		dump_stack();
+	}
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+
+	if (cb->qsi.es || cb->qsi.cs) {
+		printk(KERN_EMERG "CPUMF sampling did not stop properly.\n");
+		dump_stack();
+	}
+
+	return rc;
+}
+
+static int smp_ctl_ssctl_deactivate(int cpu)
+{
+	int rc;
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	cb->ssctl.es = 1;
+	cb->ssctl.cs = 0;
+
+	ep.buffer = &cb->ssctl;
+	smp_call_function_single(cpu, execute_ssctl, &ep, 1);
+	rc = ep.rc;
+	if (rc)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+
+	if (cb->qsi.cs)
+		printk(KERN_EMERG "CPUMF sampling was not set inactive.\n");
+
+	return rc;
+}
+
+static int smp_ctl_ssctl_enable_activate(int cpu, unsigned long interval)
+{
+	int rc;
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	cb->ssctl.h = 1;
+	cb->ssctl.tear = cb->first_sdbt;
+	cb->ssctl.dear = *(unsigned long *) cb->first_sdbt;
+	cb->ssctl.interval = interval;
+	cb->ssctl.es = 1;
+	cb->ssctl.cs = 1;
+
+	ep.buffer = &cb->ssctl;
+	smp_call_function_single(cpu, execute_ssctl, &ep, 1);
+	rc = ep.rc;
+	if (rc)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+	if (ep.rc)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF QSI failed.\n", cpu);
+
+	return rc;
+}
+
+static int smp_ctl_qsi(int cpu)
+{
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+
+	return ep.rc;
+}
+
+static inline unsigned long *trailer_entry_ptr(unsigned long v)
+{
+	void *ret;
+
+	ret = (void *)v;
+	ret += PAGE_SIZE;
+	ret -= sizeof(struct hws_trailer_entry);
+
+	return (unsigned long *) ret;
+}
+
+/* prototypes for external interrupt handler and worker */
+static void hws_ext_handler(unsigned int ext_int_code,
+				unsigned int param32, unsigned long param64);
+
+static void worker(struct work_struct *work);
+
+static void add_samples_to_oprofile(unsigned cpu, unsigned long *,
+				unsigned long *dear);
+
+static void init_all_cpu_buffers(void)
+{
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		memset(cb, 0, sizeof(struct hws_cpu_buffer));
+	}
+}
+
+static int is_link_entry(unsigned long *s)
+{
+	return *s & 0x1ul ? 1 : 0;
+}
+
+static unsigned long *get_next_sdbt(unsigned long *s)
+{
+	return (unsigned long *) (*s & ~0x1ul);
+}
+
+static int prepare_cpu_buffers(void)
+{
+	int cpu;
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		atomic_set(&cb->ext_params, 0);
+		cb->worker_entry = 0;
+		cb->sample_overflow = 0;
+		cb->req_alert = 0;
+		cb->incorrect_sdbt_entry = 0;
+		cb->invalid_entry_address = 0;
+		cb->loss_of_sample_data = 0;
+		cb->sample_auth_change_alert = 0;
+		cb->finish = 0;
+		cb->oom = 0;
+		cb->stop_mode = 0;
+	}
+
+	return rc;
+}
+
+/*
+ * allocate_sdbt() - allocate sampler memory
+ * @cpu: the cpu for which sampler memory is allocated
+ *
+ * A 4K page is allocated for each requested SDBT.
+ * A maximum of 511 4K pages are allocated for the SDBs in each of the SDBTs.
+ * Set ALERT_REQ mask in each SDBs trailer.
+ * Returns zero if successful, <0 otherwise.
+ */
+static int allocate_sdbt(int cpu)
+{
+	int j, k, rc;
+	unsigned long *sdbt;
+	unsigned long  sdb;
+	unsigned long *tail;
+	unsigned long *trailer;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	if (cb->first_sdbt)
+		return -EINVAL;
+
+	sdbt = NULL;
+	tail = sdbt;
+
+	for (j = 0; j < num_sdbt; j++) {
+		sdbt = (unsigned long *)get_zeroed_page(GFP_KERNEL);
+
+		mutex_lock(&hws_sem_oom);
+		/* OOM killer might have been activated */
+		barrier();
+		if (oom_killer_was_active || !sdbt) {
+			if (sdbt)
+				free_page((unsigned long)sdbt);
+
+			goto allocate_sdbt_error;
+		}
+		if (cb->first_sdbt == 0)
+			cb->first_sdbt = (unsigned long)sdbt;
+
+		/* link current page to tail of chain */
+		if (tail)
+			*tail = (unsigned long)(void *)sdbt + 1;
+
+		mutex_unlock(&hws_sem_oom);
+
+		for (k = 0; k < num_sdb; k++) {
+			/* get and set SDB page */
+			sdb = get_zeroed_page(GFP_KERNEL);
+
+			mutex_lock(&hws_sem_oom);
+			/* OOM killer might have been activated */
+			barrier();
+			if (oom_killer_was_active || !sdb) {
+				if (sdb)
+					free_page(sdb);
+
+				goto allocate_sdbt_error;
+			}
+			*sdbt = sdb;
+			trailer = trailer_entry_ptr(*sdbt);
+			*trailer = ALERT_REQ_MASK;
+			sdbt++;
+			mutex_unlock(&hws_sem_oom);
+		}
+		tail = sdbt;
+	}
+	mutex_lock(&hws_sem_oom);
+	if (oom_killer_was_active)
+		goto allocate_sdbt_error;
+
+	rc = 0;
+	if (tail)
+		*tail = (unsigned long)
+			((void *)cb->first_sdbt) + 1;
+
+allocate_sdbt_exit:
+	mutex_unlock(&hws_sem_oom);
+	return rc;
+
+allocate_sdbt_error:
+	rc = -ENOMEM;
+	goto allocate_sdbt_exit;
+}
+
+/*
+ * deallocate_sdbt() - deallocate all sampler memory
+ *
+ * For each online CPU all SDBT trees are deallocated.
+ * Returns the number of freed pages.
+ */
+static int deallocate_sdbt(void)
+{
+	int cpu;
+	int counter;
+
+	counter = 0;
+
+	for_each_online_cpu(cpu) {
+		unsigned long start;
+		unsigned long sdbt;
+		unsigned long *curr;
+		struct hws_cpu_buffer *cb;
+
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+		if (!cb->first_sdbt)
+			continue;
+
+		sdbt = cb->first_sdbt;
+		curr = (unsigned long *) sdbt;
+		start = sdbt;
+
+		/* we'll free the SDBT after all SDBs are processed... */
+		while (1) {
+			if (!*curr || !sdbt)
+				break;
+
+			/* watch for link entry reset if found */
+			if (is_link_entry(curr)) {
+				curr = get_next_sdbt(curr);
+				if (sdbt)
+					free_page(sdbt);
+
+				/* we are done if we reach the start */
+				if ((unsigned long) curr == start)
+					break;
+				else
+					sdbt = (unsigned long) curr;
+			} else {
+				/* process SDB pointer */
+				if (*curr) {
+					free_page(*curr);
+					curr++;
+				}
+			}
+			counter++;
+		}
+		cb->first_sdbt = 0;
+	}
+	return counter;
+}
+
+static int start_sampling(int cpu)
+{
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	rc = smp_ctl_ssctl_enable_activate(cpu, interval);
+	if (rc) {
+		printk(KERN_INFO "hwsampler: CPU %d ssctl failed.\n", cpu);
+		goto start_exit;
+	}
+
+	rc = -EINVAL;
+	if (!cb->qsi.es) {
+		printk(KERN_INFO "hwsampler: CPU %d ssctl not enabled.\n", cpu);
+		goto start_exit;
+	}
+
+	if (!cb->qsi.cs) {
+		printk(KERN_INFO "hwsampler: CPU %d ssctl not active.\n", cpu);
+		goto start_exit;
+	}
+
+	printk(KERN_INFO
+		"hwsampler: CPU %d, CPUMF Sampling started, interval %lu.\n",
+		cpu, interval);
+
+	rc = 0;
+
+start_exit:
+	return rc;
+}
+
+static int stop_sampling(int cpu)
+{
+	unsigned long v;
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = smp_ctl_qsi(cpu);
+	WARN_ON(rc);
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	if (!rc && !cb->qsi.es)
+		printk(KERN_INFO "hwsampler: CPU %d, already stopped.\n", cpu);
+
+	rc = smp_ctl_ssctl_stop(cpu);
+	if (rc) {
+		printk(KERN_INFO "hwsampler: CPU %d, ssctl stop error %d.\n",
+				cpu, rc);
+		goto stop_exit;
+	}
+
+	printk(KERN_INFO "hwsampler: CPU %d, CPUMF Sampling stopped.\n", cpu);
+
+stop_exit:
+	v = cb->req_alert;
+	if (v)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF Request alert,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->loss_of_sample_data;
+	if (v)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF Loss of sample data,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->invalid_entry_address;
+	if (v)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF Invalid entry address,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->incorrect_sdbt_entry;
+	if (v)
+		printk(KERN_ERR
+				"hwsampler: CPU %d CPUMF Incorrect SDBT address,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->sample_auth_change_alert;
+	if (v)
+		printk(KERN_ERR
+				"hwsampler: CPU %d CPUMF Sample authorization change,"
+				" count=%lu.\n", cpu, v);
+
+	return rc;
+}
+
+static int check_hardware_prerequisites(void)
+{
+	unsigned long long facility_bits[2];
+
+	memcpy(facility_bits, S390_lowcore.stfle_fac_list, 32);
+	if (!(facility_bits[1] & (1ULL << 59)))
+		return -EOPNOTSUPP;
+
+	return 0;
+}
+/*
+ * hws_oom_callback() - the OOM callback function
+ *
+ * In case the callback is invoked during memory allocation for the
+ *  hw sampler, all obtained memory is deallocated and a flag is set
+ *  so main sampler memory allocation can exit with a failure code.
+ * In case the callback is invoked during sampling the hw sampler
+ *  is deactivated for all CPUs.
+ */
+static int hws_oom_callback(struct notifier_block *nfb,
+	unsigned long dummy, void *parm)
+{
+	unsigned long *freed;
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	freed = parm;
+
+	mutex_lock(&hws_sem_oom);
+
+	if (hws_state == HWS_DEALLOCATED) {
+		/* during memory allocation */
+		if (oom_killer_was_active == 0) {
+			oom_killer_was_active = 1;
+			*freed += deallocate_sdbt();
+		}
+	} else {
+		int i;
+		cpu = get_cpu();
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+		if (!cb->oom) {
+			for_each_online_cpu(i) {
+				smp_ctl_ssctl_deactivate(i);
+				cb->oom = 1;
+			}
+			cb->finish = 1;
+
+			printk(KERN_INFO
+				"hwsampler: CPU %d, OOM notify during CPUMF Sampling.\n",
+				cpu);
+		}
+	}
+
+	mutex_unlock(&hws_sem_oom);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block hws_oom_notifier = {
+	.notifier_call = hws_oom_callback
+};
+
+static int hws_cpu_callback(struct notifier_block *nfb,
+	unsigned long action, void *hcpu)
+{
+	/* We do not have sampler space available for all possible CPUs.
+	   All CPUs should be online when hw sampling is activated. */
+	return NOTIFY_BAD;
+}
+
+static struct notifier_block hws_cpu_notifier = {
+	.notifier_call = hws_cpu_callback
+};
+
+/**
+ * hwsampler_deactivate() - set hardware sampling temporarily inactive
+ * @cpu:  specifies the CPU to be set inactive.
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_deactivate(unsigned int cpu)
+{
+	/*
+	 * Deactivate hw sampling temporarily and flush the buffer
+	 * by pushing all the pending samples to oprofile buffer.
+	 *
+	 * This function can be called under one of the following conditions:
+	 *     Memory unmap, task is exiting.
+	 */
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	mutex_lock(&hws_sem);
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	if (hws_state == HWS_STARTED) {
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (cb->qsi.cs) {
+			rc = smp_ctl_ssctl_deactivate(cpu);
+			if (rc) {
+				printk(KERN_INFO
+				"hwsampler: CPU %d, CPUMF Deactivation failed.\n", cpu);
+				cb->finish = 1;
+				hws_state = HWS_STOPPING;
+			} else  {
+				hws_flush_all = 1;
+				/* Add work to queue to read pending samples.*/
+				queue_work_on(cpu, hws_wq, &cb->worker);
+			}
+		}
+	}
+	mutex_unlock(&hws_sem);
+
+	if (hws_wq)
+		flush_workqueue(hws_wq);
+
+	return rc;
+}
+
+/**
+ * hwsampler_activate() - activate/resume hardware sampling which was deactivated
+ * @cpu:  specifies the CPU to be set active.
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_activate(unsigned int cpu)
+{
+	/*
+	 * Re-activate hw sampling. This should be called in pair with
+	 * hwsampler_deactivate().
+	 */
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	mutex_lock(&hws_sem);
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	if (hws_state == HWS_STARTED) {
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (!cb->qsi.cs) {
+			hws_flush_all = 0;
+			rc = smp_ctl_ssctl_enable_activate(cpu, interval);
+			if (rc) {
+				printk(KERN_ERR
+				"CPU %d, CPUMF activate sampling failed.\n",
+					 cpu);
+			}
+		}
+	}
+
+	mutex_unlock(&hws_sem);
+
+	return rc;
+}
+
+static void hws_ext_handler(unsigned int ext_int_code,
+			    unsigned int param32, unsigned long param64)
+{
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	cpu = smp_processor_id();
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	atomic_xchg(
+			&cb->ext_params,
+			atomic_read(&cb->ext_params)
+				| S390_lowcore.ext_params);
+
+	if (hws_wq)
+		queue_work(hws_wq, &cb->worker);
+}
+
+static int check_qsi_on_setup(void)
+{
+	int rc;
+	unsigned int cpu;
+	struct hws_cpu_buffer *cb;
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (rc)
+			return -EOPNOTSUPP;
+
+		if (!cb->qsi.as) {
+			printk(KERN_INFO "hwsampler: CPUMF sampling is not authorized.\n");
+			return -EINVAL;
+		}
+
+		if (cb->qsi.es) {
+			printk(KERN_WARNING "hwsampler: CPUMF is still enabled.\n");
+			rc = smp_ctl_ssctl_stop(cpu);
+			if (rc)
+				return -EINVAL;
+
+			printk(KERN_INFO
+				"CPU %d, CPUMF Sampling stopped now.\n", cpu);
+		}
+	}
+	return 0;
+}
+
+static int check_qsi_on_start(void)
+{
+	unsigned int cpu;
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+
+		if (!cb->qsi.as)
+			return -EINVAL;
+
+		if (cb->qsi.es)
+			return -EINVAL;
+
+		if (cb->qsi.cs)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static void worker_on_start(unsigned int cpu)
+{
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	cb->worker_entry = cb->first_sdbt;
+}
+
+static int worker_check_error(unsigned int cpu, int ext_params)
+{
+	int rc;
+	unsigned long *sdbt;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	sdbt = (unsigned long *) cb->worker_entry;
+
+	if (!sdbt || !*sdbt)
+		return -EINVAL;
+
+	if (ext_params & EI_IEA)
+		cb->req_alert++;
+
+	if (ext_params & EI_LSDA)
+		cb->loss_of_sample_data++;
+
+	if (ext_params & EI_IEA) {
+		cb->invalid_entry_address++;
+		rc = -EINVAL;
+	}
+
+	if (ext_params & EI_ISE) {
+		cb->incorrect_sdbt_entry++;
+		rc = -EINVAL;
+	}
+
+	if (ext_params & EI_SACA) {
+		cb->sample_auth_change_alert++;
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static void worker_on_finish(unsigned int cpu)
+{
+	int rc, i;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	if (cb->finish) {
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (cb->qsi.es) {
+			printk(KERN_INFO
+				"hwsampler: CPU %d, CPUMF Stop/Deactivate sampling.\n",
+				cpu);
+			rc = smp_ctl_ssctl_stop(cpu);
+			if (rc)
+				printk(KERN_INFO
+					"hwsampler: CPU %d, CPUMF Deactivation failed.\n",
+					cpu);
+
+			for_each_online_cpu(i) {
+				if (i == cpu)
+					continue;
+				if (!cb->finish) {
+					cb->finish = 1;
+					queue_work_on(i, hws_wq,
+						&cb->worker);
+				}
+			}
+		}
+	}
+}
+
+static void worker_on_interrupt(unsigned int cpu)
+{
+	unsigned long *sdbt;
+	unsigned char done;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	sdbt = (unsigned long *) cb->worker_entry;
+
+	done = 0;
+	/* do not proceed if stop was entered,
+	 * forget the buffers not yet processed */
+	while (!done && !cb->stop_mode) {
+		unsigned long *trailer;
+		struct hws_trailer_entry *te;
+		unsigned long *dear = 0;
+
+		trailer = trailer_entry_ptr(*sdbt);
+		/* leave loop if no more work to do */
+		if (!(*trailer & BUFFER_FULL_MASK)) {
+			done = 1;
+			if (!hws_flush_all)
+				continue;
+		}
+
+		te = (struct hws_trailer_entry *)trailer;
+		cb->sample_overflow += te->overflow;
+
+		add_samples_to_oprofile(cpu, sdbt, dear);
+
+		/* reset trailer */
+		xchg((unsigned char *) te, 0x40);
+
+		/* advance to next sdb slot in current sdbt */
+		sdbt++;
+		/* in case link bit is set use address w/o link bit */
+		if (is_link_entry(sdbt))
+			sdbt = get_next_sdbt(sdbt);
+
+		cb->worker_entry = (unsigned long)sdbt;
+	}
+}
+
+static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt,
+		unsigned long *dear)
+{
+	struct hws_data_entry *sample_data_ptr;
+	unsigned long *trailer;
+
+	trailer = trailer_entry_ptr(*sdbt);
+	if (dear) {
+		if (dear > trailer)
+			return;
+		trailer = dear;
+	}
+
+	sample_data_ptr = (struct hws_data_entry *)(*sdbt);
+
+	while ((unsigned long *)sample_data_ptr < trailer) {
+		struct pt_regs *regs = NULL;
+		struct task_struct *tsk = NULL;
+
+		/*
+		 * Check sampling mode, 1 indicates basic (=customer) sampling
+		 * mode.
+		 */
+		if (sample_data_ptr->def != 1) {
+			/* sample slot is not yet written */
+			break;
+		} else {
+			/* make sure we don't use it twice,
+			 * the next time the sampler will set it again */
+			sample_data_ptr->def = 0;
+		}
+
+		/* Get pt_regs. */
+		if (sample_data_ptr->P == 1) {
+			/* userspace sample */
+			unsigned int pid = sample_data_ptr->prim_asn;
+			rcu_read_lock();
+			tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
+			if (tsk)
+				regs = task_pt_regs(tsk);
+			rcu_read_unlock();
+		} else {
+			/* kernelspace sample */
+			regs = task_pt_regs(current);
+		}
+
+		mutex_lock(&hws_sem);
+		oprofile_add_ext_hw_sample(sample_data_ptr->ia, regs, 0,
+				!sample_data_ptr->P, tsk);
+		mutex_unlock(&hws_sem);
+
+		sample_data_ptr++;
+	}
+}
+
+static void worker(struct work_struct *work)
+{
+	unsigned int cpu;
+	int ext_params;
+	struct hws_cpu_buffer *cb;
+
+	cb = container_of(work, struct hws_cpu_buffer, worker);
+	cpu = smp_processor_id();
+	ext_params = atomic_xchg(&cb->ext_params, 0);
+
+	if (!cb->worker_entry)
+		worker_on_start(cpu);
+
+	if (worker_check_error(cpu, ext_params))
+		return;
+
+	if (!cb->finish)
+		worker_on_interrupt(cpu);
+
+	if (cb->finish)
+		worker_on_finish(cpu);
+}
+
+/**
+ * hwsampler_allocate() - allocate memory for the hardware sampler
+ * @sdbt:  number of SDBTs per online CPU (must be > 0)
+ * @sdb:   number of SDBs per SDBT (minimum 1, maximum 511)
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_allocate(unsigned long sdbt, unsigned long sdb)
+{
+	int cpu, rc;
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state != HWS_DEALLOCATED)
+		goto allocate_exit;
+
+	if (sdbt < 1)
+		goto allocate_exit;
+
+	if (sdb > MAX_NUM_SDB || sdb < MIN_NUM_SDB)
+		goto allocate_exit;
+
+	num_sdbt = sdbt;
+	num_sdb = sdb;
+
+	oom_killer_was_active = 0;
+	register_oom_notifier(&hws_oom_notifier);
+
+	for_each_online_cpu(cpu) {
+		if (allocate_sdbt(cpu)) {
+			unregister_oom_notifier(&hws_oom_notifier);
+			goto allocate_error;
+		}
+	}
+	unregister_oom_notifier(&hws_oom_notifier);
+	if (oom_killer_was_active)
+		goto allocate_error;
+
+	hws_state = HWS_STOPPED;
+	rc = 0;
+
+allocate_exit:
+	mutex_unlock(&hws_sem);
+	return rc;
+
+allocate_error:
+	rc = -ENOMEM;
+	printk(KERN_ERR "hwsampler: CPUMF Memory allocation failed.\n");
+	goto allocate_exit;
+}
+
+/**
+ * hwsampler_deallocate() - deallocate hardware sampler memory
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_deallocate()
+{
+	int rc;
+
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state != HWS_STOPPED)
+		goto deallocate_exit;
+
+	smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */
+	deallocate_sdbt();
+
+	hws_state = HWS_DEALLOCATED;
+	rc = 0;
+
+deallocate_exit:
+	mutex_unlock(&hws_sem);
+
+	return rc;
+}
+
+long hwsampler_query_min_interval(void)
+{
+	if (min_sampler_rate)
+		return min_sampler_rate;
+	else
+		return -EINVAL;
+}
+
+long hwsampler_query_max_interval(void)
+{
+	if (max_sampler_rate)
+		return max_sampler_rate;
+	else
+		return -EINVAL;
+}
+
+unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu)
+{
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	return cb->sample_overflow;
+}
+
+int hwsampler_setup()
+{
+	int rc;
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state)
+		goto setup_exit;
+
+	hws_state = HWS_INIT;
+
+	init_all_cpu_buffers();
+
+	rc = check_hardware_prerequisites();
+	if (rc)
+		goto setup_exit;
+
+	rc = check_qsi_on_setup();
+	if (rc)
+		goto setup_exit;
+
+	rc = -EINVAL;
+	hws_wq = create_workqueue("hwsampler");
+	if (!hws_wq)
+		goto setup_exit;
+
+	register_cpu_notifier(&hws_cpu_notifier);
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		INIT_WORK(&cb->worker, worker);
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (min_sampler_rate != cb->qsi.min_sampl_rate) {
+			if (min_sampler_rate) {
+				printk(KERN_WARNING
+					"hwsampler: different min sampler rate values.\n");
+				if (min_sampler_rate < cb->qsi.min_sampl_rate)
+					min_sampler_rate =
+						cb->qsi.min_sampl_rate;
+			} else
+				min_sampler_rate = cb->qsi.min_sampl_rate;
+		}
+		if (max_sampler_rate != cb->qsi.max_sampl_rate) {
+			if (max_sampler_rate) {
+				printk(KERN_WARNING
+					"hwsampler: different max sampler rate values.\n");
+				if (max_sampler_rate > cb->qsi.max_sampl_rate)
+					max_sampler_rate =
+						cb->qsi.max_sampl_rate;
+			} else
+				max_sampler_rate = cb->qsi.max_sampl_rate;
+		}
+	}
+	register_external_interrupt(0x1407, hws_ext_handler);
+
+	hws_state = HWS_DEALLOCATED;
+	rc = 0;
+
+setup_exit:
+	mutex_unlock(&hws_sem);
+	return rc;
+}
+
+int hwsampler_shutdown()
+{
+	int rc;
+
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state == HWS_DEALLOCATED || hws_state == HWS_STOPPED) {
+		mutex_unlock(&hws_sem);
+
+		if (hws_wq)
+			flush_workqueue(hws_wq);
+
+		mutex_lock(&hws_sem);
+
+		if (hws_state == HWS_STOPPED) {
+			smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */
+			deallocate_sdbt();
+		}
+		if (hws_wq) {
+			destroy_workqueue(hws_wq);
+			hws_wq = NULL;
+		}
+
+		unregister_external_interrupt(0x1407, hws_ext_handler);
+		hws_state = HWS_INIT;
+		rc = 0;
+	}
+	mutex_unlock(&hws_sem);
+
+	unregister_cpu_notifier(&hws_cpu_notifier);
+
+	return rc;
+}
+
+/**
+ * hwsampler_start_all() - start hardware sampling on all online CPUs
+ * @rate:  specifies the used interval when samples are taken
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_start_all(unsigned long rate)
+{
+	int rc, cpu;
+
+	mutex_lock(&hws_sem);
+
+	hws_oom = 0;
+
+	rc = -EINVAL;
+	if (hws_state != HWS_STOPPED)
+		goto start_all_exit;
+
+	interval = rate;
+
+	/* fail if rate is not valid */
+	if (interval < min_sampler_rate || interval > max_sampler_rate)
+		goto start_all_exit;
+
+	rc = check_qsi_on_start();
+	if (rc)
+		goto start_all_exit;
+
+	rc = prepare_cpu_buffers();
+	if (rc)
+		goto start_all_exit;
+
+	for_each_online_cpu(cpu) {
+		rc = start_sampling(cpu);
+		if (rc)
+			break;
+	}
+	if (rc) {
+		for_each_online_cpu(cpu) {
+			stop_sampling(cpu);
+		}
+		goto start_all_exit;
+	}
+	hws_state = HWS_STARTED;
+	rc = 0;
+
+start_all_exit:
+	mutex_unlock(&hws_sem);
+
+	if (rc)
+		return rc;
+
+	register_oom_notifier(&hws_oom_notifier);
+	hws_oom = 1;
+	hws_flush_all = 0;
+	/* now let them in, 1407 CPUMF external interrupts */
+	smp_ctl_set_bit(0, 5); /* set CR0 bit 58 */
+
+	return 0;
+}
+
+/**
+ * hwsampler_stop_all() - stop hardware sampling on all online CPUs
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_stop_all()
+{
+	int tmp_rc, rc, cpu;
+	struct hws_cpu_buffer *cb;
+
+	mutex_lock(&hws_sem);
+
+	rc = 0;
+	if (hws_state == HWS_INIT) {
+		mutex_unlock(&hws_sem);
+		return rc;
+	}
+	hws_state = HWS_STOPPING;
+	mutex_unlock(&hws_sem);
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		cb->stop_mode = 1;
+		tmp_rc = stop_sampling(cpu);
+		if (tmp_rc)
+			rc = tmp_rc;
+	}
+
+	if (hws_wq)
+		flush_workqueue(hws_wq);
+
+	mutex_lock(&hws_sem);
+	if (hws_oom) {
+		unregister_oom_notifier(&hws_oom_notifier);
+		hws_oom = 0;
+	}
+	hws_state = HWS_STOPPED;
+	mutex_unlock(&hws_sem);
+
+	return rc;
+}
diff --git a/arch/s390/oprofile/hwsampler.h b/arch/s390/oprofile/hwsampler.h
new file mode 100644
index 0000000..8c72b59
--- /dev/null
+++ b/arch/s390/oprofile/hwsampler.h
@@ -0,0 +1,113 @@
+/*
+ * CPUMF HW sampler functions and internal structures
+ *
+ *    Copyright IBM Corp. 2010
+ *    Author(s): Heinz Graalfs <graalfs@de.ibm.com>
+ */
+
+#ifndef HWSAMPLER_H_
+#define HWSAMPLER_H_
+
+#include <linux/workqueue.h>
+
+struct hws_qsi_info_block          /* QUERY SAMPLING information block  */
+{ /* Bit(s) */
+	unsigned int b0_13:14;      /* 0-13: zeros                       */
+	unsigned int as:1;          /* 14: sampling authorisation control*/
+	unsigned int b15_21:7;      /* 15-21: zeros                      */
+	unsigned int es:1;          /* 22: sampling enable control       */
+	unsigned int b23_29:7;      /* 23-29: zeros                      */
+	unsigned int cs:1;          /* 30: sampling activation control   */
+	unsigned int:1;             /* 31: reserved                      */
+	unsigned int bsdes:16;      /* 4-5: size of sampling entry       */
+	unsigned int:16;            /* 6-7: reserved                     */
+	unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
+	unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
+	unsigned long tear;         /* 24-31: TEAR contents              */
+	unsigned long dear;         /* 32-39: DEAR contents              */
+	unsigned int rsvrd0;        /* 40-43: reserved                   */
+	unsigned int cpu_speed;     /* 44-47: CPU speed                  */
+	unsigned long long rsvrd1;  /* 48-55: reserved                   */
+	unsigned long long rsvrd2;  /* 56-63: reserved                   */
+};
+
+struct hws_ssctl_request_block     /* SET SAMPLING CONTROLS req block   */
+{ /* bytes 0 - 7  Bit(s) */
+	unsigned int s:1;           /* 0: maximum buffer indicator       */
+	unsigned int h:1;           /* 1: part. level reserved for VM use*/
+	unsigned long b2_53:52;     /* 2-53: zeros                       */
+	unsigned int es:1;          /* 54: sampling enable control       */
+	unsigned int b55_61:7;      /* 55-61: - zeros                    */
+	unsigned int cs:1;          /* 62: sampling activation control   */
+	unsigned int b63:1;         /* 63: zero                          */
+	unsigned long interval;     /* 8-15: sampling interval           */
+	unsigned long tear;         /* 16-23: TEAR contents              */
+	unsigned long dear;         /* 24-31: DEAR contents              */
+	/* 32-63:                                                        */
+	unsigned long rsvrd1;       /* reserved                          */
+	unsigned long rsvrd2;       /* reserved                          */
+	unsigned long rsvrd3;       /* reserved                          */
+	unsigned long rsvrd4;       /* reserved                          */
+};
+
+struct hws_cpu_buffer {
+	unsigned long first_sdbt;       /* @ of 1st SDB-Table for this CP*/
+	unsigned long worker_entry;
+	unsigned long sample_overflow;  /* taken from SDB ...            */
+	struct hws_qsi_info_block qsi;
+	struct hws_ssctl_request_block ssctl;
+	struct work_struct worker;
+	atomic_t ext_params;
+	unsigned long req_alert;
+	unsigned long loss_of_sample_data;
+	unsigned long invalid_entry_address;
+	unsigned long incorrect_sdbt_entry;
+	unsigned long sample_auth_change_alert;
+	unsigned int finish:1;
+	unsigned int oom:1;
+	unsigned int stop_mode:1;
+};
+
+struct hws_data_entry {
+	unsigned int def:16;        /* 0-15  Data Entry Format           */
+	unsigned int R:4;           /* 16-19 reserved                    */
+	unsigned int U:4;           /* 20-23 Number of unique instruct.  */
+	unsigned int z:2;           /* zeros                             */
+	unsigned int T:1;           /* 26 PSW DAT mode                   */
+	unsigned int W:1;           /* 27 PSW wait state                 */
+	unsigned int P:1;           /* 28 PSW Problem state              */
+	unsigned int AS:2;          /* 29-30 PSW address-space control   */
+	unsigned int I:1;           /* 31 entry valid or invalid         */
+	unsigned int:16;
+	unsigned int prim_asn:16;   /* primary ASN                       */
+	unsigned long long ia;      /* Instruction Address               */
+	unsigned long long lpp;     /* Logical-Partition Program Param.  */
+	unsigned long long vpp;     /* Virtual-Machine Program Param.    */
+};
+
+struct hws_trailer_entry {
+	unsigned int f:1;           /* 0 - Block Full Indicator          */
+	unsigned int a:1;           /* 1 - Alert request control         */
+	unsigned long:62;           /* 2 - 63: Reserved                  */
+	unsigned long overflow;     /* 64 - sample Overflow count        */
+	unsigned long timestamp;    /* 16 - time-stamp                   */
+	unsigned long timestamp1;   /*                                   */
+	unsigned long reserved1;    /* 32 -Reserved                      */
+	unsigned long reserved2;    /*                                   */
+	unsigned long progusage1;   /* 48 - reserved for programming use */
+	unsigned long progusage2;   /*                                   */
+};
+
+int hwsampler_setup(void);
+int hwsampler_shutdown(void);
+int hwsampler_allocate(unsigned long sdbt, unsigned long sdb);
+int hwsampler_deallocate(void);
+long hwsampler_query_min_interval(void);
+long hwsampler_query_max_interval(void);
+int hwsampler_start_all(unsigned long interval);
+int hwsampler_stop_all(void);
+int hwsampler_deactivate(unsigned int cpu);
+int hwsampler_activate(unsigned int cpu);
+unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu);
+
+#endif /*HWSAMPLER_H_*/
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index 7a99511..16c76de 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -4,23 +4,182 @@
  * S390 Version
  *   Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Author(s): Mahesh Salgaonkar (mahesh@linux.vnet.ibm.com)
+ *   Author(s): Heinz Graalfs (graalfs@linux.vnet.ibm.com)
  *
- * @remark Copyright 2002 OProfile authors
+ * @remark Copyright 2002-2011 OProfile authors
  */
 
 #include <linux/oprofile.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/oprofile.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+
+#include "../../../drivers/oprofile/oprof.h"
+#include "hwsampler.h"
+
+#define DEFAULT_INTERVAL	4096
+
+#define DEFAULT_SDBT_BLOCKS	1
+#define DEFAULT_SDB_BLOCKS	511
+
+static unsigned long oprofile_hw_interval = DEFAULT_INTERVAL;
+static unsigned long oprofile_min_interval;
+static unsigned long oprofile_max_interval;
+
+static unsigned long oprofile_sdbt_blocks = DEFAULT_SDBT_BLOCKS;
+static unsigned long oprofile_sdb_blocks = DEFAULT_SDB_BLOCKS;
 
+static int hwsampler_file;
+static int hwsampler_running;	/* start_mutex must be held to change */
+
+static struct oprofile_operations timer_ops;
 
 extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
 
-int __init oprofile_arch_init(struct oprofile_operations* ops)
+static int oprofile_hwsampler_start(void)
+{
+	int retval;
+
+	hwsampler_running = hwsampler_file;
+
+	if (!hwsampler_running)
+		return timer_ops.start();
+
+	retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks);
+	if (retval)
+		return retval;
+
+	retval = hwsampler_start_all(oprofile_hw_interval);
+	if (retval)
+		hwsampler_deallocate();
+
+	return retval;
+}
+
+static void oprofile_hwsampler_stop(void)
+{
+	if (!hwsampler_running) {
+		timer_ops.stop();
+		return;
+	}
+
+	hwsampler_stop_all();
+	hwsampler_deallocate();
+	return;
+}
+
+static ssize_t hwsampler_read(struct file *file, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return oprofilefs_ulong_to_user(hwsampler_file, buf, count, offset);
+}
+
+static ssize_t hwsampler_write(struct file *file, char const __user *buf,
+		size_t count, loff_t *offset)
+{
+	unsigned long val;
+	int retval;
+
+	if (*offset)
+		return -EINVAL;
+
+	retval = oprofilefs_ulong_from_user(&val, buf, count);
+	if (retval)
+		return retval;
+
+	if (oprofile_started)
+		/*
+		 * save to do without locking as we set
+		 * hwsampler_running in start() when start_mutex is
+		 * held
+		 */
+		return -EBUSY;
+
+	hwsampler_file = val;
+
+	return count;
+}
+
+static const struct file_operations hwsampler_fops = {
+	.read		= hwsampler_read,
+	.write		= hwsampler_write,
+};
+
+static int oprofile_create_hwsampling_files(struct super_block *sb,
+						struct dentry *root)
+{
+	struct dentry *hw_dir;
+
+	/* reinitialize default values */
+	hwsampler_file = 1;
+
+	hw_dir = oprofilefs_mkdir(sb, root, "hwsampling");
+	if (!hw_dir)
+		return -EINVAL;
+
+	oprofilefs_create_file(sb, hw_dir, "hwsampler", &hwsampler_fops);
+	oprofilefs_create_ulong(sb, hw_dir, "hw_interval",
+				&oprofile_hw_interval);
+	oprofilefs_create_ro_ulong(sb, hw_dir, "hw_min_interval",
+				&oprofile_min_interval);
+	oprofilefs_create_ro_ulong(sb, hw_dir, "hw_max_interval",
+				&oprofile_max_interval);
+	oprofilefs_create_ulong(sb, hw_dir, "hw_sdbt_blocks",
+				&oprofile_sdbt_blocks);
+
+	return 0;
+}
+
+static int oprofile_hwsampler_init(struct oprofile_operations *ops)
+{
+	if (hwsampler_setup())
+		return -ENODEV;
+
+	/*
+	 * create hwsampler files only if hwsampler_setup() succeeds.
+	 */
+	oprofile_min_interval = hwsampler_query_min_interval();
+	if (oprofile_min_interval < 0) {
+		oprofile_min_interval = 0;
+		return -ENODEV;
+	}
+	oprofile_max_interval = hwsampler_query_max_interval();
+	if (oprofile_max_interval < 0) {
+		oprofile_max_interval = 0;
+		return -ENODEV;
+	}
+
+	if (oprofile_timer_init(ops))
+		return -ENODEV;
+
+	printk(KERN_INFO "oprofile: using hardware sampling\n");
+
+	memcpy(&timer_ops, ops, sizeof(timer_ops));
+
+	ops->start = oprofile_hwsampler_start;
+	ops->stop = oprofile_hwsampler_stop;
+	ops->create_files = oprofile_create_hwsampling_files;
+
+	return 0;
+}
+
+static void oprofile_hwsampler_exit(void)
+{
+	oprofile_timer_exit();
+	hwsampler_shutdown();
+}
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
 	ops->backtrace = s390_backtrace;
-	return -ENODEV;
+
+	return oprofile_hwsampler_init(ops);
 }
 
 void oprofile_arch_exit(void)
 {
+	oprofile_hwsampler_exit();
 }
diff --git a/arch/score/include/asm/thread_info.h b/arch/score/include/asm/thread_info.h
index 8570d08..2205c62 100644
--- a/arch/score/include/asm/thread_info.h
+++ b/arch/score/include/asm/thread_info.h
@@ -71,7 +71,7 @@ struct thread_info {
 register struct thread_info *__current_thread_info __asm__("r28");
 #define current_thread_info()	__current_thread_info
 
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node) kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #define free_thread_info(info) kfree(info)
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 8a9011d..2d264fa 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -25,6 +25,7 @@ config SUPERH
 	select GENERIC_ATOMIC64
 	# Support the deprecated APIs until MFD and GPIOLIB catch up.
 	select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
+	select GENERIC_IRQ_SHOW
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
@@ -434,6 +435,8 @@ config CPU_SUBTYPE_SH7757
 	select CPU_SH4A
 	select CPU_SHX2
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select USB_ARCH_HAS_OHCI
+	select USB_ARCH_HAS_EHCI
 	help
 	  Select SH7757 if you have a SH4A SH7757 CPU.
 
diff --git a/arch/sh/boards/board-espt.c b/arch/sh/boards/board-espt.c
index d5ce5e1..9da92ac 100644
--- a/arch/sh/boards/board-espt.c
+++ b/arch/sh/boards/board-espt.c
@@ -66,6 +66,11 @@ static struct resource sh_eth_resources[] = {
 		.end    = 0xFEE00F7C - 1,
 		.flags  = IORESOURCE_MEM,
 	}, {
+		.start  = 0xFEE01800,   /* TSU */
+		.end    = 0xFEE01FFF,
+		.flags  = IORESOURCE_MEM,
+	}, {
+
 		.start  = 57,   /* irq number */
 		.flags  = IORESOURCE_IRQ,
 	},
@@ -74,6 +79,8 @@ static struct resource sh_eth_resources[] = {
 static struct sh_eth_plat_data sh7763_eth_pdata = {
 	.phy = 0,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
 };
 
 static struct platform_device espt_eth_device = {
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
index c475f10..a9e3356 100644
--- a/arch/sh/boards/board-sh7757lcr.c
+++ b/arch/sh/boards/board-sh7757lcr.c
@@ -15,6 +15,9 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mfd/sh_mobile_sdhi.h>
 #include <cpu/sh7757.h>
 #include <asm/sh_eth.h>
 #include <asm/heartbeat.h>
@@ -44,6 +47,17 @@ static struct platform_device heartbeat_device = {
 };
 
 /* Fast Ethernet */
+#define GBECONT		0xffc10100
+#define GBECONT_RMII1	BIT(17)
+#define GBECONT_RMII0	BIT(16)
+static void sh7757_eth_set_mdio_gate(unsigned long addr)
+{
+	if ((addr & 0x00000fff) < 0x0800)
+		writel(readl(GBECONT) | GBECONT_RMII0, GBECONT);
+	else
+		writel(readl(GBECONT) | GBECONT_RMII1, GBECONT);
+}
+
 static struct resource sh_eth0_resources[] = {
 	{
 		.start  = 0xfef00000,
@@ -59,6 +73,8 @@ static struct resource sh_eth0_resources[] = {
 static struct sh_eth_plat_data sh7757_eth0_pdata = {
 	.phy = 1,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_FAST_SH4,
+	.set_mdio_gate = sh7757_eth_set_mdio_gate,
 };
 
 static struct platform_device sh7757_eth0_device = {
@@ -86,6 +102,8 @@ static struct resource sh_eth1_resources[] = {
 static struct sh_eth_plat_data sh7757_eth1_pdata = {
 	.phy = 1,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_FAST_SH4,
+	.set_mdio_gate = sh7757_eth_set_mdio_gate,
 };
 
 static struct platform_device sh7757_eth1_device = {
@@ -98,10 +116,173 @@ static struct platform_device sh7757_eth1_device = {
 	},
 };
 
+static void sh7757_eth_giga_set_mdio_gate(unsigned long addr)
+{
+	if ((addr & 0x00000fff) < 0x0800) {
+		gpio_set_value(GPIO_PTT4, 1);
+		writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT);
+	} else {
+		gpio_set_value(GPIO_PTT4, 0);
+		writel(readl(GBECONT) & ~GBECONT_RMII1, GBECONT);
+	}
+}
+
+static struct resource sh_eth_giga0_resources[] = {
+	{
+		.start  = 0xfee00000,
+		.end    = 0xfee007ff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		/* TSU */
+		.start  = 0xfee01800,
+		.end    = 0xfee01fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = 315,
+		.end    = 315,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_eth_plat_data sh7757_eth_giga0_pdata = {
+	.phy = 18,
+	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
+	.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
+};
+
+static struct platform_device sh7757_eth_giga0_device = {
+	.name		= "sh-eth",
+	.resource	= sh_eth_giga0_resources,
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(sh_eth_giga0_resources),
+	.dev		= {
+		.platform_data = &sh7757_eth_giga0_pdata,
+	},
+};
+
+static struct resource sh_eth_giga1_resources[] = {
+	{
+		.start  = 0xfee00800,
+		.end    = 0xfee00fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = 316,
+		.end    = 316,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_eth_plat_data sh7757_eth_giga1_pdata = {
+	.phy = 19,
+	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
+	.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
+};
+
+static struct platform_device sh7757_eth_giga1_device = {
+	.name		= "sh-eth",
+	.resource	= sh_eth_giga1_resources,
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(sh_eth_giga1_resources),
+	.dev		= {
+		.platform_data = &sh7757_eth_giga1_pdata,
+	},
+};
+
+/* SH_MMCIF */
+static struct resource sh_mmcif_resources[] = {
+	[0] = {
+		.start	= 0xffcb0000,
+		.end	= 0xffcb00ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 211,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= 212,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mmcif_dma sh7757lcr_mmcif_dma = {
+	.chan_priv_tx	= SHDMA_SLAVE_MMCIF_TX,
+	.chan_priv_rx	= SHDMA_SLAVE_MMCIF_RX,
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+	.dma		= &sh7757lcr_mmcif_dma,
+	.sup_pclk	= 0x0f,
+	.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+	.ocr		= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static struct platform_device sh_mmcif_device = {
+	.name		= "sh_mmcif",
+	.id		= 0,
+	.dev		= {
+		.platform_data		= &sh_mmcif_plat,
+	},
+	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),
+	.resource	= sh_mmcif_resources,
+};
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI_RX,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
+};
+
+static struct resource sdhi_resources[] = {
+	[0] = {
+		.start  = 0xffe50000,
+		.end    = 0xffe501ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 20,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi_device = {
+	.name           = "sh_mobile_sdhi",
+	.num_resources  = ARRAY_SIZE(sdhi_resources),
+	.resource       = sdhi_resources,
+	.id             = 0,
+	.dev	= {
+		.platform_data	= &sdhi_info,
+	},
+};
+
 static struct platform_device *sh7757lcr_devices[] __initdata = {
 	&heartbeat_device,
 	&sh7757_eth0_device,
 	&sh7757_eth1_device,
+	&sh7757_eth_giga0_device,
+	&sh7757_eth_giga1_device,
+	&sh_mmcif_device,
+	&sdhi_device,
+};
+
+static struct flash_platform_data spi_flash_data = {
+	.name = "m25p80",
+	.type = "m25px64",
+};
+
+static struct spi_board_info spi_board_info[] = {
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &spi_flash_data,
+	},
 };
 
 static int __init sh7757lcr_devices_setup(void)
@@ -332,6 +513,10 @@ static int __init sh7757lcr_devices_setup(void)
 	gpio_request(GPIO_PTT5, NULL);		/* eMMC_PRST# */
 	gpio_direction_output(GPIO_PTT5, 1);
 
+	/* register SPI device information */
+	spi_register_board_info(spi_board_info,
+				ARRAY_SIZE(spi_board_info));
+
 	/* General platform */
 	return platform_add_devices(sh7757lcr_devices,
 				    ARRAY_SIZE(sh7757lcr_devices));
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 701667a..e44480c 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -142,6 +142,8 @@ static struct resource sh_eth_resources[] = {
 static struct sh_eth_plat_data sh_eth_plat = {
 	.phy = 0x1f, /* SMSC LAN8700 */
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_FAST_SH4,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
 	.ether_link_active_low = 1
 };
 
@@ -723,11 +725,7 @@ static struct platform_device camera_devices[] = {
 
 /* FSI */
 static struct sh_fsi_platform_info fsi_info = {
-	.portb_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OUT_SLAVE_MODE |
-		       SH_FSI_IN_SLAVE_MODE |
-		       SH_FSI_OFMT(I2S) |
-		       SH_FSI_IFMT(I2S),
+	.portb_flags = SH_FSI_BRS_INV,
 };
 
 static struct resource fsi_resources[] = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 5276793..c8bcf6a 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -286,11 +286,7 @@ static struct platform_device ceu1_device = {
 /* FSI */
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OUT_SLAVE_MODE |
-		       SH_FSI_IN_SLAVE_MODE |
-		       SH_FSI_OFMT(PCM) |
-		       SH_FSI_IFMT(PCM),
+	.porta_flags = SH_FSI_BRS_INV,
 };
 
 static struct resource fsi_resources[] = {
diff --git a/arch/sh/boards/mach-sh7763rdp/setup.c b/arch/sh/boards/mach-sh7763rdp/setup.c
index f64a691..f3d828f 100644
--- a/arch/sh/boards/mach-sh7763rdp/setup.c
+++ b/arch/sh/boards/mach-sh7763rdp/setup.c
@@ -75,6 +75,10 @@ static struct resource sh_eth_resources[] = {
 		.end    = 0xFEE00F7C - 1,
 		.flags  = IORESOURCE_MEM,
 	}, {
+		.start  = 0xFEE01800,   /* TSU */
+		.end    = 0xFEE01FFF,
+		.flags  = IORESOURCE_MEM,
+	}, {
 		.start  = 57,   /* irq number */
 		.flags  = IORESOURCE_IRQ,
 	},
@@ -83,6 +87,8 @@ static struct resource sh_eth_resources[] = {
 static struct sh_eth_plat_data sh7763_eth_pdata = {
 	.phy = 1,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
 };
 
 static struct platform_device sh7763rdp_eth_device = {
diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile
index e0b0293..780e083 100644
--- a/arch/sh/boot/compressed/Makefile
+++ b/arch/sh/boot/compressed/Makefile
@@ -11,6 +11,8 @@ targets		:= vmlinux vmlinux.bin vmlinux.bin.gz \
 
 OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
 
+GCOV_PROFILE := n
+
 #
 # IMAGE_OFFSET is the load offset of the compression loader
 #
diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig
index 5f7f667..fa0ecf8 100644
--- a/arch/sh/configs/sh7757lcr_defconfig
+++ b/arch/sh/configs/sh7757lcr_defconfig
@@ -38,7 +38,15 @@ CONFIG_IPV6=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_VITESSE_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -53,8 +61,17 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_SH=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_MFD_SH_MOBILE_SDHI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_TMIO=y
+CONFIG_MMC_SH_MMCIF=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_ISO9660_FS=y
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index 96e9b05..4418f90 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -1,16 +1,19 @@
 /*
  * Low-Level PCI Express Support for the SH7786
  *
- *  Copyright (C) 2009 - 2010  Paul Mundt
+ *  Copyright (C) 2009 - 2011  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.
  */
+#define pr_fmt(fmt) "PCI: " fmt
+
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/async.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
@@ -31,7 +34,7 @@ static unsigned int nr_ports;
 
 static struct sh7786_pcie_hwops {
 	int (*core_init)(void);
-	int (*port_init_hw)(struct sh7786_pcie_port *port);
+	async_func_ptr *port_init_hw;
 } *sh7786_pcie_hwops;
 
 static struct resource sh7786_pci0_resources[] = {
@@ -474,8 +477,9 @@ static int __init sh7786_pcie_core_init(void)
 	return test_mode_pin(MODE_PIN12) ? 3 : 2;
 }
 
-static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
+static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie)
 {
+	struct sh7786_pcie_port *port = data;
 	int ret;
 
 	/*
@@ -488,18 +492,30 @@ static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
 	 * Setup clocks, needed both for PHY and PCIe registers.
 	 */
 	ret = pcie_clk_init(port);
-	if (unlikely(ret < 0))
-		return ret;
+	if (unlikely(ret < 0)) {
+		pr_err("clock initialization failed for port#%d\n",
+		       port->index);
+		return;
+	}
 
 	ret = phy_init(port);
-	if (unlikely(ret < 0))
-		return ret;
+	if (unlikely(ret < 0)) {
+		pr_err("phy initialization failed for port#%d\n",
+		       port->index);
+		return;
+	}
 
 	ret = pcie_init(port);
-	if (unlikely(ret < 0))
-		return ret;
+	if (unlikely(ret < 0)) {
+		pr_err("core initialization failed for port#%d\n",
+			       port->index);
+		return;
+	}
 
-	return register_pci_controller(port->hose);
+	/* In the interest of preserving device ordering, synchronize */
+	async_synchronize_cookie(cookie);
+
+	register_pci_controller(port->hose);
 }
 
 static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
@@ -510,7 +526,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
 static int __init sh7786_pcie_init(void)
 {
 	struct clk *platclk;
-	int ret = 0, i;
+	int i;
 
 	printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
@@ -552,14 +568,10 @@ static int __init sh7786_pcie_init(void)
 		port->hose		= sh7786_pci_channels + i;
 		port->hose->io_map_base	= port->hose->resources[0].start;
 
-		ret |= sh7786_pcie_hwops->port_init_hw(port);
+		async_schedule(sh7786_pcie_hwops->port_init_hw, port);
 	}
 
-	if (unlikely(ret)) {
-		clk_disable(platclk);
-		clk_put(platclk);
-		return ret;
-	}
+	async_synchronize_full();
 
 	return 0;
 }
diff --git a/arch/sh/include/asm/futex-irq.h b/arch/sh/include/asm/futex-irq.h
index a9f16a7..6cb9f19 100644
--- a/arch/sh/include/asm/futex-irq.h
+++ b/arch/sh/include/asm/futex-irq.h
@@ -3,7 +3,7 @@
 
 #include <asm/system.h>
 
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -20,7 +20,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -37,7 +37,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
 					  int *oldval)
 {
 	unsigned long flags;
@@ -54,7 +54,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -71,7 +71,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -88,11 +88,13 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
-						   int oldval, int newval)
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+						   u32 __user *uaddr,
+						   u32 oldval, u32 newval)
 {
 	unsigned long flags;
-	int ret, prev = 0;
+	int ret;
+	u32 prev = 0;
 
 	local_irq_save(flags);
 
@@ -102,10 +104,8 @@ static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
 
 	local_irq_restore(flags);
 
-	if (ret)
-		return ret;
-
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __ASM_SH_FUTEX_IRQ_H */
diff --git a/arch/sh/include/asm/futex.h b/arch/sh/include/asm/futex.h
index 68256ec..7be39a6 100644
--- a/arch/sh/include/asm/futex.h
+++ b/arch/sh/include/asm/futex.h
@@ -10,7 +10,7 @@
 /* XXX: UP variants, fix for SH-4A and SMP.. */
 #include <asm/futex-irq.h>
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -21,7 +21,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -65,12 +65,13 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/ioctls.h b/arch/sh/include/asm/ioctls.h
index 84e85a7..a6769f3 100644
--- a/arch/sh/include/asm/ioctls.h
+++ b/arch/sh/include/asm/ioctls.h
@@ -87,6 +87,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	_IO('T', 0x37)
 
 #define TIOCSERCONFIG	_IO('T', 83) /* 0x5453 */
 #define TIOCSERGWILD	_IOR('T', 84,  int) /* 0x5454 */
diff --git a/arch/sh/include/asm/rwsem.h b/arch/sh/include/asm/rwsem.h
index 06e2251..edab572 100644
--- a/arch/sh/include/asm/rwsem.h
+++ b/arch/sh/include/asm/rwsem.h
@@ -11,64 +11,13 @@
 #endif
 
 #ifdef __KERNEL__
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
 
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	long		count;
 #define RWSEM_UNLOCKED_VALUE		0x00000000
 #define RWSEM_ACTIVE_BIAS		0x00000001
 #define RWSEM_ACTIVE_MASK		0x0000ffff
 #define RWSEM_WAITING_BIAS		(-0x00010000)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-	  LIST_HEAD_INIT((name).wait_list) \
-	  __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)				\
-do {						\
-	static struct lock_class_key __key;	\
-						\
-	__init_rwsem((sem), #sem, &__key);	\
-} while (0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
 
 /*
  * lock for reading
@@ -179,10 +128,5 @@ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_SH_RWSEM_H */
diff --git a/arch/sh/include/asm/sh_eth.h b/arch/sh/include/asm/sh_eth.h
index f739061..0f325da 100644
--- a/arch/sh/include/asm/sh_eth.h
+++ b/arch/sh/include/asm/sh_eth.h
@@ -1,11 +1,21 @@
 #ifndef __ASM_SH_ETH_H__
 #define __ASM_SH_ETH_H__
 
+#include <linux/phy.h>
+
 enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
+enum {
+	SH_ETH_REG_GIGABIT,
+	SH_ETH_REG_FAST_SH4,
+	SH_ETH_REG_FAST_SH3_SH2
+};
 
 struct sh_eth_plat_data {
 	int phy;
 	int edmac_endian;
+	int register_type;
+	phy_interface_t phy_interface;
+	void (*set_mdio_gate)(unsigned long addr);
 
 	unsigned char mac_addr[6];
 	unsigned no_ether_link:1;
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h
index c228946..ea2d508 100644
--- a/arch/sh/include/asm/thread_info.h
+++ b/arch/sh/include/asm/thread_info.h
@@ -95,7 +95,7 @@ static inline struct thread_info *current_thread_info(void)
 
 #endif
 
-extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
 extern void free_thread_info(struct thread_info *ti);
 extern void arch_task_cache_init(void);
 #define arch_task_cache_init arch_task_cache_init
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
index d6741fc..b5a74e8 100644
--- a/arch/sh/include/asm/unistd_32.h
+++ b/arch/sh/include/asm/unistd_32.h
@@ -369,8 +369,11 @@
 #define __NR_recvmsg		356
 #define __NR_recvmmsg		357
 #define __NR_accept4		358
+#define __NR_name_to_handle_at	359
+#define __NR_open_by_handle_at	360
+#define __NR_clock_adjtime	361
 
-#define NR_syscalls 359
+#define NR_syscalls 362
 
 #ifdef __KERNEL__
 
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h
index 09aa93f..953da4a 100644
--- a/arch/sh/include/asm/unistd_64.h
+++ b/arch/sh/include/asm/unistd_64.h
@@ -390,10 +390,13 @@
 #define __NR_fanotify_init	367
 #define __NR_fanotify_mark	368
 #define __NR_prlimit64		369
+#define __NR_name_to_handle_at	370
+#define __NR_open_by_handle_at	371
+#define __NR_clock_adjtime	372
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 370
+#define NR_syscalls 373
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h
index 9a6125e..18fa80a 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-register.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h
@@ -40,6 +40,11 @@
 #define CHCR_TS_LOW_SHIFT	3
 #define CHCR_TS_HIGH_MASK	0
 #define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0x00100000
+#define CHCR_TS_HIGH_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define CHCR_TS_LOW_MASK	0x00000018
 #define CHCR_TS_LOW_SHIFT	3
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7757.h b/arch/sh/include/cpu-sh4/cpu/sh7757.h
index 15f3de1..05b8196 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7757.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7757.h
@@ -251,4 +251,36 @@ enum {
 	GPIO_FN_ON_DQ3,	GPIO_FN_ON_DQ2,	GPIO_FN_ON_DQ1,	GPIO_FN_ON_DQ0,
 };
 
+enum {
+	SHDMA_SLAVE_SDHI_TX,
+	SHDMA_SLAVE_SDHI_RX,
+	SHDMA_SLAVE_MMCIF_TX,
+	SHDMA_SLAVE_MMCIF_RX,
+	SHDMA_SLAVE_SCIF2_TX,
+	SHDMA_SLAVE_SCIF2_RX,
+	SHDMA_SLAVE_SCIF3_TX,
+	SHDMA_SLAVE_SCIF3_RX,
+	SHDMA_SLAVE_SCIF4_TX,
+	SHDMA_SLAVE_SCIF4_RX,
+	SHDMA_SLAVE_RIIC0_TX,
+	SHDMA_SLAVE_RIIC0_RX,
+	SHDMA_SLAVE_RIIC1_TX,
+	SHDMA_SLAVE_RIIC1_RX,
+	SHDMA_SLAVE_RIIC2_TX,
+	SHDMA_SLAVE_RIIC2_RX,
+	SHDMA_SLAVE_RIIC3_TX,
+	SHDMA_SLAVE_RIIC3_RX,
+	SHDMA_SLAVE_RIIC4_TX,
+	SHDMA_SLAVE_RIIC4_RX,
+	SHDMA_SLAVE_RIIC5_TX,
+	SHDMA_SLAVE_RIIC5_RX,
+	SHDMA_SLAVE_RIIC6_TX,
+	SHDMA_SLAVE_RIIC6_RX,
+	SHDMA_SLAVE_RIIC7_TX,
+	SHDMA_SLAVE_RIIC7_RX,
+	SHDMA_SLAVE_RIIC8_TX,
+	SHDMA_SLAVE_RIIC8_RX,
+	SHDMA_SLAVE_RIIC9_TX,
+	SHDMA_SLAVE_RIIC9_RX,
+};
 #endif /* __ASM_SH7757_H__ */
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
index e073e3e..eedddad 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -77,9 +77,10 @@ struct clk div4_clks[DIV4_NR] = {
 
 #define MSTPCR0		0xffc80030
 #define MSTPCR1		0xffc80034
+#define MSTPCR2		0xffc10028
 
 enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
-       MSTP111, MSTP110, MSTP103, MSTP102,
+       MSTP111, MSTP110, MSTP103, MSTP102, MSTP220,
        MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
@@ -95,6 +96,9 @@ static struct clk mstp_clks[MSTP_NR] = {
 	[MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
 	[MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
 	[MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
+
+	/* MSTPCR2 */
+	[MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0),
 };
 
 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
@@ -140,6 +144,7 @@ static struct clk_lookup lookups[] = {
 		.clk		= &mstp_clks[MSTP110],
 	},
 	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
+	CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
 
 int __init arch_clk_init(void)
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
index 9c1de26..423dabf 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
@@ -1,7 +1,7 @@
 /*
  * SH7757 Setup
  *
- * Copyright (C) 2009  Renesas Solutions Corp.
+ * Copyright (C) 2009, 2011  Renesas Solutions Corp.
  *
  *  based on setup-sh7785.c : Copyright (C) 2007  Paul Mundt
  *
@@ -16,6 +16,10 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/sh_timer.h>
+#include <linux/sh_dma.h>
+
+#include <cpu/dma-register.h>
+#include <cpu/sh7757.h>
 
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xfe4b0000,		/* SCIF2 */
@@ -124,12 +128,548 @@ static struct platform_device tmu1_device = {
 	.num_resources	= ARRAY_SIZE(tmu1_resources),
 };
 
+static struct resource spi0_resources[] = {
+	[0] = {
+		.start	= 0xfe002000,
+		.end	= 0xfe0020ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 86,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* DMA */
+static const struct sh_dmae_slave_config sh7757_dmae0_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_SDHI_TX,
+		.addr		= 0x1fe50030,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.mid_rid	= 0xc5,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SDHI_RX,
+		.addr		= 0x1fe50030,
+		.chcr		= DM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.mid_rid	= 0xc6,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_MMCIF_TX,
+		.addr		= 0x1fcb0034,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd3,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_MMCIF_RX,
+		.addr		= 0x1fcb0034,
+		.chcr		= DM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd7,
+	},
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF2_TX,
+		.addr		= 0x1f4b000c,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF2_RX,
+		.addr		= 0x1f4b0014,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF3_TX,
+		.addr		= 0x1f4c000c,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF3_RX,
+		.addr		= 0x1f4c0014,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF4_TX,
+		.addr		= 0x1f4d000c,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x41,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF4_RX,
+		.addr		= 0x1f4d0014,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x42,
+	},
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC0_TX,
+		.addr		= 0x1e500012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC0_RX,
+		.addr		= 0x1e500013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC1_TX,
+		.addr		= 0x1e510012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC1_RX,
+		.addr		= 0x1e510013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC2_TX,
+		.addr		= 0x1e520012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xa1,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC2_RX,
+		.addr		= 0x1e520013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xa2,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC3_TX,
+		.addr		= 0x1e530012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xab,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC3_RX,
+		.addr		= 0x1e530013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xaf,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC4_TX,
+		.addr		= 0x1e540012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xc1,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC4_RX,
+		.addr		= 0x1e540013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xc2,
+	},
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC5_TX,
+		.addr		= 0x1e550012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC5_RX,
+		.addr		= 0x1e550013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC6_TX,
+		.addr		= 0x1e560012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC6_RX,
+		.addr		= 0x1e560013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC7_TX,
+		.addr		= 0x1e570012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x41,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC7_RX,
+		.addr		= 0x1e570013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x42,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC8_TX,
+		.addr		= 0x1e580012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x45,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC8_RX,
+		.addr		= 0x1e580013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x46,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC9_TX,
+		.addr		= 0x1e590012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x51,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC9_RX,
+		.addr		= 0x1e590013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x52,
+	},
+};
+
+static const struct sh_dmae_channel sh7757_dmae_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+	.slave		= sh7757_dmae0_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae0_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+	.slave		= sh7757_dmae1_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae1_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma2_platform_data = {
+	.slave		= sh7757_dmae2_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae2_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma3_platform_data = {
+	.slave		= sh7757_dmae3_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae3_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+/* channel 0 to 5 */
+static struct resource sh7757_dmae0_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff608020,
+		.end	= 0xff60808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff609000,
+		.end	= 0xff60900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= 34,
+		.end	= 34,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+/* channel 6 to 11 */
+static struct resource sh7757_dmae1_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff618020,
+		.end	= 0xff61808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff619000,
+		.end	= 0xff61900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error */
+		.start	= 34,
+		.end	= 34,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 4 */
+		.start	= 46,
+		.end	= 46,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 5 */
+		.start	= 46,
+		.end	= 46,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 6 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 7 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 8 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 9 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 10 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 11 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+/* channel 12 to 17 */
+static struct resource sh7757_dmae2_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff708020,
+		.end	= 0xff70808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff709000,
+		.end	= 0xff70900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error */
+		.start	= 323,
+		.end	= 323,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 12 to 16 */
+		.start	= 272,
+		.end	= 276,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channel 17 */
+		.start	= 279,
+		.end	= 279,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* channel 18 to 23 */
+static struct resource sh7757_dmae3_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff718020,
+		.end	= 0xff71808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff719000,
+		.end	= 0xff71900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error */
+		.start	= 324,
+		.end	= 324,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 18 to 22 */
+		.start	= 280,
+		.end	= 284,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channel 23 */
+		.start	= 288,
+		.end	= 288,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device dma0_device = {
+	.name           = "sh-dma-engine",
+	.id             = 0,
+	.resource	= sh7757_dmae0_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae0_resources),
+	.dev            = {
+		.platform_data	= &dma0_platform_data,
+	},
+};
+
+static struct platform_device dma1_device = {
+	.name		= "sh-dma-engine",
+	.id		= 1,
+	.resource	= sh7757_dmae1_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae1_resources),
+	.dev		= {
+		.platform_data	= &dma1_platform_data,
+	},
+};
+
+static struct platform_device dma2_device = {
+	.name		= "sh-dma-engine",
+	.id		= 2,
+	.resource	= sh7757_dmae2_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae2_resources),
+	.dev		= {
+		.platform_data	= &dma2_platform_data,
+	},
+};
+
+static struct platform_device dma3_device = {
+	.name		= "sh-dma-engine",
+	.id		= 3,
+	.resource	= sh7757_dmae3_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae3_resources),
+	.dev		= {
+		.platform_data	= &dma3_platform_data,
+	},
+};
+
+static struct platform_device spi0_device = {
+	.name	= "sh_spi",
+	.id	= 0,
+	.dev	= {
+		.dma_mask		= NULL,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.resource	= spi0_resources,
+};
+
 static struct platform_device *sh7757_devices[] __initdata = {
 	&scif2_device,
 	&scif3_device,
 	&scif4_device,
 	&tmu0_device,
 	&tmu1_device,
+	&dma0_device,
+	&dma1_device,
+	&dma2_device,
+	&dma3_device,
+	&spi0_device,
 };
 
 static int __init sh7757_devices_setup(void)
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c
index c19e2a9..e4469e72 100644
--- a/arch/sh/kernel/cpu/shmobile/cpuidle.c
+++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c
@@ -75,7 +75,7 @@ void sh_mobile_setup_cpuidle(void)
 	i = CPUIDLE_DRIVER_STATE_START;
 
 	state = &dev->states[i++];
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
+	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
 	strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
 	state->exit_latency = 1;
 	state->target_residency = 1 * 2;
@@ -88,7 +88,7 @@ void sh_mobile_setup_cpuidle(void)
 
 	if (sh_mobile_sleep_supported & SUSP_SH_SF) {
 		state = &dev->states[i++];
-		snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
+		snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
 		strncpy(state->desc, "SuperH Sleep Mode [SF]",
 			CPUIDLE_DESC_LEN);
 		state->exit_latency = 100;
@@ -101,7 +101,7 @@ void sh_mobile_setup_cpuidle(void)
 
 	if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
 		state = &dev->states[i++];
-		snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
+		snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
 		strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
 			CPUIDLE_DESC_LEN);
 		state->exit_latency = 2300;
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 68ecbe6..64ea0b1 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -34,9 +34,9 @@ void ack_bad_irq(unsigned int irq)
 
 #if defined(CONFIG_PROC_FS)
 /*
- * /proc/interrupts printing:
+ * /proc/interrupts printing for arch specific interrupts
  */
-static int show_other_interrupts(struct seq_file *p, int prec)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	int j;
 
@@ -49,63 +49,6 @@ static int show_other_interrupts(struct seq_file *p, int prec)
 
 	return 0;
 }
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	unsigned long flags, any_count = 0;
-	int i = *(loff_t *)v, j, prec;
-	struct irqaction *action;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	struct irq_chip *chip;
-
-	if (i > nr_irqs)
-		return 0;
-
-	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
-		j *= 10;
-
-	if (i == nr_irqs)
-		return show_other_interrupts(p, prec);
-
-	if (i == 0) {
-		seq_printf(p, "%*s", prec + 8, "");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	desc = irq_to_desc(i);
-	if (!desc)
-		return 0;
-
-	data = irq_get_irq_data(i);
-	chip = irq_data_get_irq_chip(data);
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	for_each_online_cpu(j)
-		any_count |= kstat_irqs_cpu(i, j);
-	action = desc->action;
-	if (!action && !any_count)
-		goto out;
-
-	seq_printf(p, "%*d: ", prec, i);
-	for_each_online_cpu(j)
-		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-	seq_printf(p, " %14s", chip->name);
-	seq_printf(p, "-%-8s", desc->name);
-
-	if (action) {
-		seq_printf(p, "  %s", action->name);
-		while ((action = action->next) != NULL)
-			seq_printf(p, ", %s", action->name);
-	}
-
-	seq_putc(p, '\n');
-out:
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	return 0;
-}
 #endif
 
 #ifdef CONFIG_IRQSTACKS
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index dcb126d..f39ad57 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -32,16 +32,16 @@ void free_thread_xstate(struct task_struct *tsk)
 #if THREAD_SHIFT < PAGE_SHIFT
 static struct kmem_cache *thread_info_cache;
 
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
+struct thread_info *alloc_thread_info(struct task_struct *tsk, int node)
 {
 	struct thread_info *ti;
-
-	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
-	if (unlikely(ti == NULL))
-		return NULL;
 #ifdef CONFIG_DEBUG_STACK_USAGE
-	memset(ti, 0, THREAD_SIZE);
+	gfp_t mask = GFP_KERNEL | __GFP_ZERO;
+#else
+	gfp_t mask = GFP_KERNEL;
 #endif
+
+	ti = kmem_cache_alloc_node(thread_info_cache, mask, node);
 	return ti;
 }
 
@@ -64,7 +64,9 @@ struct thread_info *alloc_thread_info(struct task_struct *tsk)
 #else
 	gfp_t mask = GFP_KERNEL;
 #endif
-	return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+	struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER);
+
+	return page ? page_address(page) : NULL;
 }
 
 void free_thread_info(struct thread_info *ti)
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index 6fc347e..768fb33 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -376,3 +376,6 @@ ENTRY(sys_call_table)
 	.long sys_recvmsg
 	.long sys_recvmmsg
 	.long sys_accept4
+	.long sys_name_to_handle_at
+	.long sys_open_by_handle_at	/* 360 */
+	.long sys_clock_adjtime
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 6658570..44e7b00 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -396,3 +396,6 @@ sys_call_table:
 	.long sys_fanotify_init
 	.long sys_fanotify_mark
 	.long sys_prlimit64
+	.long sys_name_to_handle_at	/* 370 */
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 7f8a709..af4d461 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -66,7 +66,7 @@ SECTIONS
 		__machvec_end = .;
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 
 	/*
 	 * .exit.text is discarded at runtime, not link time, to deal with
diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
index 150aa32..2228c8c 100644
--- a/arch/sh/mm/Makefile
+++ b/arch/sh/mm/Makefile
@@ -42,6 +42,8 @@ obj-$(CONFIG_IOREMAP_FIXED)	+= ioremap_fixed.o
 obj-$(CONFIG_UNCACHED_MAPPING)	+= uncached.o
 obj-$(CONFIG_HAVE_SRAM_POOL)	+= sram.o
 
+GCOV_PROFILE_pmb.o := n
+
 # Special flags for fault_64.o.  This puts restrictions on the number of
 # caller-save registers that the compiler can target when building this file.
 # This is required because the code is called from a context in entry.S where
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 95695e9..e48f471 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -51,6 +51,7 @@ config SPARC64
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config ARCH_DEFCONFIG
 	string
@@ -460,6 +461,39 @@ config SPARC_LEON
 	  from www.gaisler.com. You can download a sparc-linux cross-compilation
 	  toolchain at www.gaisler.com.
 
+if SPARC_LEON
+menu "U-Boot options"
+
+config UBOOT_LOAD_ADDR
+	hex "uImage Load Address"
+	default 0x40004000
+	---help---
+	 U-Boot kernel load address, the address in physical address space
+	 where u-boot will place the Linux kernel before booting it.
+	 This address is normally the base address of main memory + 0x4000.
+
+config UBOOT_FLASH_ADDR
+	hex "uImage.o Load Address"
+	default 0x00080000
+	---help---
+	 Optional setting only affecting the uImage.o ELF-image used to
+	 download the uImage file to the target using a ELF-loader other than
+	 U-Boot. It may for example be used to download an uImage to FLASH with
+	 the GRMON utility before even starting u-boot.
+
+config UBOOT_ENTRY_ADDR
+	hex "uImage Entry Address"
+	default 0xf0004000
+	---help---
+	 Do not change this unless you know what you're doing. This is
+	 hardcoded by the SPARC32 and LEON port.
+
+	 This is the virtual address u-boot jumps to when booting the Linux
+	 Kernel.
+
+endmenu
+endif
+
 endmenu
 
 menu "Bus options (PCI etc.)"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 113225b..ad1fb5d 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -88,7 +88,7 @@ boot := arch/sparc/boot
 # Default target
 all: zImage
 
-image zImage tftpboot.img vmlinux.aout: vmlinux
+image zImage uImage tftpboot.img vmlinux.aout: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 archclean:
@@ -102,6 +102,7 @@ ifeq ($(ARCH),sparc)
 define archhelp
   echo  '* image        - kernel image ($(boot)/image)'
   echo  '* zImage       - stripped kernel image ($(boot)/zImage)'
+  echo  '  uImage       - U-Boot SPARC32 Image (only for LEON)'
   echo  '  tftpboot.img - image prepared for tftp'
 endef
 else
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile
index a2c5898..9205416 100644
--- a/arch/sparc/boot/Makefile
+++ b/arch/sparc/boot/Makefile
@@ -5,6 +5,7 @@
 
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
+MKIMAGE 	:= $(srctree)/scripts/mkuboot.sh
 
 hostprogs-y	:= piggyback btfixupprep
 targets		:= tftpboot.img btfix.o btfix.S image zImage vmlinux.aout
@@ -77,6 +78,36 @@ $(obj)/zImage: $(obj)/image
 $(obj)/vmlinux.aout: vmlinux FORCE
 	$(call if_changed,elftoaout)
 	@echo '  kernel: $@ is ready'
+else
+
+# The following lines make a readable image for U-Boot.
+#  uImage   - Binary file read by U-boot
+#  uImage.o - object file of uImage for loading with a
+#             flash programmer understanding ELF.
+
+OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment
+$(obj)/image.bin: $(obj)/image FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/image.gz: $(obj)/image.bin
+	$(call if_changed,gzip)
+
+quiet_cmd_uimage = UIMAGE  $@
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sparc -O linux -T kernel \
+               -C gzip -a $(CONFIG_UBOOT_LOAD_ADDR) \
+	       -e $(CONFIG_UBOOT_ENTRY_ADDR) -n 'Linux-$(KERNELRELEASE)' \
+               -d $< $@
+
+quiet_cmd_uimage.o = UIMAGE.O $@
+      cmd_uimage.o = $(LD) -Tdata $(CONFIG_UBOOT_FLASH_ADDR) \
+                     -r -b binary $@ -o $@.o
+
+targets += uImage
+$(obj)/uImage: $(obj)/image.gz
+	$(call if_changed,uimage)
+	$(call if_changed,uimage.o)
+	@echo '  Image $@ is ready'
+
 endif
 
 $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
diff --git a/arch/sparc/include/asm/errno.h b/arch/sparc/include/asm/errno.h
index 4e2bc49..c351aba 100644
--- a/arch/sparc/include/asm/errno.h
+++ b/arch/sparc/include/asm/errno.h
@@ -112,4 +112,6 @@
 
 #define	ERFKILL		134	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	135	/* Memory page has hardware error */
+
 #endif
diff --git a/arch/sparc/include/asm/fcntl.h b/arch/sparc/include/asm/fcntl.h
index 38f37b33..d0b83f6 100644
--- a/arch/sparc/include/asm/fcntl.h
+++ b/arch/sparc/include/asm/fcntl.h
@@ -34,6 +34,8 @@
 #define __O_SYNC	0x800000
 #define O_SYNC		(__O_SYNC|O_DSYNC)
 
+#define O_PATH		0x1000000
+
 #define F_GETOWN	5	/*  for sockets. */
 #define F_SETOWN	6	/*  for sockets. */
 #define F_GETLK		7
diff --git a/arch/sparc/include/asm/futex_64.h b/arch/sparc/include/asm/futex_64.h
index 47f9583..444e7be 100644
--- a/arch/sparc/include/asm/futex_64.h
+++ b/arch/sparc/include/asm/futex_64.h
@@ -30,7 +30,7 @@
 	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
 	: "memory")
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -38,7 +38,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	int cmparg = (encoded_op << 20) >> 20;
 	int oldval = 0, ret, tem;
 
-	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
+	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
 		return -EFAULT;
 	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
 		return -EINVAL;
@@ -85,26 +85,30 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
+	int ret = 0;
+
 	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"\n1:	casa	[%4] %%asi, %3, %1\n"
 	"2:\n"
 	"	.section .fixup,#alloc,#execinstr\n"
 	"	.align	4\n"
 	"3:	sethi	%%hi(2b), %0\n"
 	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
+	"	mov	%5, %0\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
 	"	.align	4\n"
 	"	.word	1b, 3b\n"
 	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "+r" (ret), "=r" (newval)
+	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
 	: "memory");
 
-	return newval;
+	*uval = newval;
+	return ret;
 }
 
 #endif /* !(_SPARC64_FUTEX_H) */
diff --git a/arch/sparc/include/asm/ioctls.h b/arch/sparc/include/asm/ioctls.h
index ed3807b..28d0c8b 100644
--- a/arch/sparc/include/asm/ioctls.h
+++ b/arch/sparc/include/asm/ioctls.h
@@ -20,6 +20,7 @@
 #define TCSETSW2	_IOW('T', 14, struct termios2)
 #define TCSETSF2	_IOW('T', 15, struct termios2)
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCVHANGUP	_IO('T', 0x37)
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
diff --git a/arch/sparc/include/asm/irq_32.h b/arch/sparc/include/asm/irq_32.h
index cbf4801..eced3e3 100644
--- a/arch/sparc/include/asm/irq_32.h
+++ b/arch/sparc/include/asm/irq_32.h
@@ -13,4 +13,7 @@
 #define irq_canonicalize(irq)	(irq)
 
 extern void __init init_IRQ(void);
+
+#define NO_IRQ		0xffffffff
+
 #endif
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h
index a0b443c..16dcae6d 100644
--- a/arch/sparc/include/asm/irq_64.h
+++ b/arch/sparc/include/asm/irq_64.h
@@ -33,34 +33,34 @@
 
 /* The largest number of unique interrupt sources we support.
  * If this needs to ever be larger than 255, you need to change
- * the type of ino_bucket->virt_irq as appropriate.
+ * the type of ino_bucket->irq as appropriate.
  *
- * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq().
+ * ino_bucket->irq allocation is made during {sun4v_,}build_irq().
  */
 #define NR_IRQS    255
 
-extern void irq_install_pre_handler(int virt_irq,
+extern void irq_install_pre_handler(int irq,
 				    void (*func)(unsigned int, void *, void *),
 				    void *arg1, void *arg2);
 #define irq_canonicalize(irq)	(irq)
 extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
 extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
 extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
-extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
+extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *irq_p,
 				    unsigned int msi_devino_start,
 				    unsigned int msi_devino_end);
-extern void sun4v_destroy_msi(unsigned int virt_irq);
-extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p,
+extern void sun4v_destroy_msi(unsigned int irq);
+extern unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p,
 				    unsigned int msi_devino_start,
 				    unsigned int msi_devino_end,
 				    unsigned long imap_base,
 				    unsigned long iclr_base);
-extern void sun4u_destroy_msi(unsigned int virt_irq);
+extern void sun4u_destroy_msi(unsigned int irq);
 
-extern unsigned char virt_irq_alloc(unsigned int dev_handle,
+extern unsigned char irq_alloc(unsigned int dev_handle,
 				    unsigned int dev_ino);
 #ifdef CONFIG_PCI_MSI
-extern void virt_irq_free(unsigned int virt_irq);
+extern void irq_free(unsigned int irq);
 #endif
 
 extern void __init init_IRQ(void);
@@ -97,4 +97,6 @@ extern void *softirq_stack[NR_CPUS];
 #define __ARCH_HAS_DO_SOFTIRQ
 #define ARCH_HAS_NMI_WATCHDOG
 
+#define NO_IRQ		0xffffffff
+
 #endif
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index 8580d17..c04f96f 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -375,9 +375,6 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
 
 extern unsigned int real_irq_entry[], smpleon_ticker[];
 extern unsigned int patchme_maybe_smp_msg[];
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
 extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
 extern unsigned int linux_trap_ipi15_sun4m[];
 
diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h
index 263c719..e50f326 100644
--- a/arch/sparc/include/asm/leon_amba.h
+++ b/arch/sparc/include/asm/leon_amba.h
@@ -180,6 +180,7 @@ struct amba_ahb_device {
 struct device_node;
 void _amba_init(struct device_node *dp, struct device_node ***nextp);
 
+extern unsigned long amba_system_id;
 extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
 extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
 extern struct amba_apb_device leon_percpu_timer_dev[16];
@@ -254,6 +255,11 @@ extern unsigned int sparc_leon_eirq;
 #define GAISLER_L2C      0xffe	/* internal device: leon2compat */
 #define GAISLER_PLUGPLAY 0xfff	/* internal device: plug & play configarea */
 
+/* Chip IDs */
+#define AEROFLEX_UT699    0x0699
+#define LEON4_NEXTREME1   0x0102
+#define GAISLER_GR712RC   0x0712
+
 #define amba_vendor(x) (((x) >> 24) & 0xff)
 
 #define amba_device(x) (((x) >> 12) & 0xfff)
diff --git a/arch/sparc/include/asm/mmu_32.h b/arch/sparc/include/asm/mmu_32.h
index ccd36d2..6f056e5 100644
--- a/arch/sparc/include/asm/mmu_32.h
+++ b/arch/sparc/include/asm/mmu_32.h
@@ -4,4 +4,7 @@
 /* Default "unsigned long" context */
 typedef unsigned long mm_context_t;
 
+/* mm/srmmu.c */
+extern ctxd_t *srmmu_ctx_table_phys;
+
 #endif
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h
index aa4c826..cb33608 100644
--- a/arch/sparc/include/asm/parport.h
+++ b/arch/sparc/include/asm/parport.h
@@ -103,7 +103,7 @@ static inline unsigned int get_dma_residue(unsigned int dmanr)
 	return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
 }
 
-static int __devinit ecpp_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ecpp_probe(struct platform_device *op)
 {
 	unsigned long base = op->resource[0].start;
 	unsigned long config = op->resource[1].start;
@@ -235,7 +235,7 @@ static const struct of_device_id ecpp_match[] = {
 	{},
 };
 
-static struct of_platform_driver ecpp_driver = {
+static struct platform_driver ecpp_driver = {
 	.driver = {
 		.name = "ecpp",
 		.owner = THIS_MODULE,
@@ -247,7 +247,7 @@ static struct of_platform_driver ecpp_driver = {
 
 static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
 {
-	return of_register_platform_driver(&ecpp_driver);
+	return platform_driver_register(&ecpp_driver);
 }
 
 #endif /* !(_ASM_SPARC64_PARPORT_H */
diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h
index a2b4302..069bf4d 100644
--- a/arch/sparc/include/asm/rwsem.h
+++ b/arch/sparc/include/asm/rwsem.h
@@ -13,53 +13,12 @@
 
 #ifdef __KERNEL__
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-struct rwsem_waiter;
-
-struct rw_semaphore {
-	signed long			count;
 #define RWSEM_UNLOCKED_VALUE		0x00000000L
 #define RWSEM_ACTIVE_BIAS		0x00000001L
 #define RWSEM_ACTIVE_MASK		0xffffffffL
 #define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t			wait_lock;
-	struct list_head		wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map		dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-  LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)						\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__init_rwsem((sem), #sem, &__key);			\
-} while (0)
 
 /*
  * lock for reading
@@ -160,11 +119,6 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 	return atomic64_add_return(delta, (atomic64_t *)(&sem->count));
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* _SPARC64_RWSEM_H */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index 841905c..d82d7f4 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -29,10 +29,16 @@
  */
 
 extern unsigned char boot_cpu_id;
+extern volatile unsigned long cpu_callin_map[NR_CPUS];
+extern cpumask_t smp_commenced_mask;
+extern struct linux_prom_registers smp_penguin_ctable;
 
 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.
  */
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h
index 9dd0318..fa57532 100644
--- a/arch/sparc/include/asm/thread_info_32.h
+++ b/arch/sparc/include/asm/thread_info_32.h
@@ -82,8 +82,8 @@ register struct thread_info *current_thread_info_reg asm("g6");
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
-#define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
+BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info_node, int)
+#define alloc_thread_info_node(tsk, node) BTFIXUP_CALL(alloc_thread_info_node)(node)
 
 BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 #define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
@@ -92,7 +92,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 
 /*
  * Size of kernel stack for each process.
- * Observe the order of get_free_pages() in alloc_thread_info().
+ * Observe the order of get_free_pages() in alloc_thread_info_node().
  * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste.
  */
 #define THREAD_SIZE		8192
diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h
index fb2ea77..60d86be 100644
--- a/arch/sparc/include/asm/thread_info_64.h
+++ b/arch/sparc/include/asm/thread_info_64.h
@@ -146,21 +146,21 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-({								\
-	struct thread_info *ret;				\
-								\
-	ret = (struct thread_info *)				\
-	  __get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER);	\
-	if (ret)						\
-		memset(ret, 0, PAGE_SIZE<<__THREAD_INFO_ORDER);	\
-	ret;							\
-})
+#define THREAD_FLAGS (GFP_KERNEL | __GFP_ZERO)
 #else
-#define alloc_thread_info(tsk) \
-	((struct thread_info *)__get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER))
+#define THREAD_FLAGS (GFP_KERNEL)
 #endif
 
+#define alloc_thread_info_node(tsk, node)				\
+({									\
+	struct page *page = alloc_pages_node(node, THREAD_FLAGS,	\
+					     __THREAD_INFO_ORDER);	\
+	struct thread_info *ret;					\
+									\
+	ret = page ? page_address(page) : NULL;				\
+	ret;								\
+})
+
 #define free_thread_info(ti) \
 	free_pages((unsigned long)(ti),__THREAD_INFO_ORDER)
 
diff --git a/arch/sparc/include/asm/types.h b/arch/sparc/include/asm/types.h
index 09c79a9..f02d330 100644
--- a/arch/sparc/include/asm/types.h
+++ b/arch/sparc/include/asm/types.h
@@ -22,10 +22,6 @@ typedef unsigned short umode_t;
 
 #ifndef __ASSEMBLY__
 
-/* Dma addresses come in generic and 64-bit flavours.  */
-
-typedef u32 dma_addr_t;
-
 #if defined(__arch64__)
 
 /*** SPARC 64 bit ***/
diff --git a/arch/sparc/include/asm/unistd.h b/arch/sparc/include/asm/unistd.h
index 03eb5a8..2f475d7 100644
--- a/arch/sparc/include/asm/unistd.h
+++ b/arch/sparc/include/asm/unistd.h
@@ -400,8 +400,11 @@
 #define __NR_fanotify_init	329
 #define __NR_fanotify_mark	330
 #define __NR_prlimit64		331
+#define __NR_name_to_handle_at	332
+#define __NR_open_by_handle_at	333
+#define __NR_clock_adjtime	334
 
-#define NR_syscalls		332
+#define NR_syscalls		335
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 599398f..99aa4db 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -42,7 +42,6 @@ obj-$(CONFIG_SPARC32)   += windows.o
 obj-y                   += cpu.o
 obj-$(CONFIG_SPARC32)   += devices.o
 obj-$(CONFIG_SPARC32)   += tadpole.o
-obj-$(CONFIG_SPARC32)   += tick14.o
 obj-y                   += ptrace_$(BITS).o
 obj-y                   += unaligned_$(BITS).o
 obj-y                   += una_asm_$(BITS).o
@@ -54,6 +53,7 @@ obj-y                   += of_device_$(BITS).o
 obj-$(CONFIG_SPARC64)   += prom_irqtrans.o
 
 obj-$(CONFIG_SPARC_LEON)+= leon_kernel.o
+obj-$(CONFIG_SPARC_LEON)+= leon_pmc.o
 
 obj-$(CONFIG_SPARC64)   += reboot.o
 obj-$(CONFIG_SPARC64)   += sysfs.o
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c
index 52de4a9..f679c57 100644
--- a/arch/sparc/kernel/apc.c
+++ b/arch/sparc/kernel/apc.c
@@ -137,8 +137,7 @@ static const struct file_operations apc_fops = {
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
 
-static int __devinit apc_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit apc_probe(struct platform_device *op)
 {
 	int err;
 
@@ -174,7 +173,7 @@ static struct of_device_id __initdata apc_match[] = {
 };
 MODULE_DEVICE_TABLE(of, apc_match);
 
-static struct of_platform_driver apc_driver = {
+static struct platform_driver apc_driver = {
 	.driver = {
 		.name = "apc",
 		.owner = THIS_MODULE,
@@ -185,7 +184,7 @@ static struct of_platform_driver apc_driver = {
 
 static int __init apc_init(void)
 {
-	return of_register_platform_driver(&apc_driver);
+	return platform_driver_register(&apc_driver);
 }
 
 /* This driver is not critical to the boot process
diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c
index 3efd3c5..2abace0 100644
--- a/arch/sparc/kernel/auxio_64.c
+++ b/arch/sparc/kernel/auxio_64.c
@@ -102,8 +102,7 @@ static struct of_device_id __initdata auxio_match[] = {
 
 MODULE_DEVICE_TABLE(of, auxio_match);
 
-static int __devinit auxio_probe(struct platform_device *dev,
-				 const struct of_device_id *match)
+static int __devinit auxio_probe(struct platform_device *dev)
 {
 	struct device_node *dp = dev->dev.of_node;
 	unsigned long size;
@@ -132,7 +131,7 @@ static int __devinit auxio_probe(struct platform_device *dev,
 	return 0;
 }
 
-static struct of_platform_driver auxio_driver = {
+static struct platform_driver auxio_driver = {
 	.probe		= auxio_probe,
 	.driver = {
 		.name = "auxio",
@@ -143,7 +142,7 @@ static struct of_platform_driver auxio_driver = {
 
 static int __init auxio_init(void)
 {
-	return of_register_platform_driver(&auxio_driver);
+	return platform_driver_register(&auxio_driver);
 }
 
 /* Must be after subsys_initcall() so that busses are probed.  Must
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c
index cfa2624..136d371 100644
--- a/arch/sparc/kernel/central.c
+++ b/arch/sparc/kernel/central.c
@@ -59,8 +59,7 @@ static int __devinit clock_board_calc_nslots(struct clock_board *p)
 	}
 }
 
-static int __devinit clock_board_probe(struct platform_device *op,
-				       const struct of_device_id *match)
+static int __devinit clock_board_probe(struct platform_device *op)
 {
 	struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -148,7 +147,7 @@ static struct of_device_id __initdata clock_board_match[] = {
 	{},
 };
 
-static struct of_platform_driver clock_board_driver = {
+static struct platform_driver clock_board_driver = {
 	.probe		= clock_board_probe,
 	.driver = {
 		.name = "clock_board",
@@ -157,8 +156,7 @@ static struct of_platform_driver clock_board_driver = {
 	},
 };
 
-static int __devinit fhc_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit fhc_probe(struct platform_device *op)
 {
 	struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -254,7 +252,7 @@ static struct of_device_id __initdata fhc_match[] = {
 	{},
 };
 
-static struct of_platform_driver fhc_driver = {
+static struct platform_driver fhc_driver = {
 	.probe		= fhc_probe,
 	.driver = {
 		.name = "fhc",
@@ -265,8 +263,8 @@ static struct of_platform_driver fhc_driver = {
 
 static int __init sunfire_init(void)
 {
-	(void) of_register_platform_driver(&fhc_driver);
-	(void) of_register_platform_driver(&clock_board_driver);
+	(void) platform_driver_register(&fhc_driver);
+	(void) platform_driver_register(&clock_board_driver);
 	return 0;
 }
 
diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c
index 08c466e..668c7be 100644
--- a/arch/sparc/kernel/chmc.c
+++ b/arch/sparc/kernel/chmc.c
@@ -392,8 +392,7 @@ static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p,
 	}
 }
 
-static int __devinit jbusmc_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit jbusmc_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *mem_regs;
 	struct device_node *mem_node;
@@ -690,8 +689,7 @@ static void chmc_fetch_decode_regs(struct chmc *p)
 				      chmc_read_mcreg(p, CHMCTRL_DECODE4));
 }
 
-static int __devinit chmc_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit chmc_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	unsigned long ver;
@@ -765,13 +763,12 @@ out_free:
 	goto out;
 }
 
-static int __devinit us3mc_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit us3mc_probe(struct platform_device *op)
 {
 	if (mc_type == MC_TYPE_SAFARI)
-		return chmc_probe(op, match);
+		return chmc_probe(op);
 	else if (mc_type == MC_TYPE_JBUS)
-		return jbusmc_probe(op, match);
+		return jbusmc_probe(op);
 	return -ENODEV;
 }
 
@@ -810,7 +807,7 @@ static const struct of_device_id us3mc_match[] = {
 };
 MODULE_DEVICE_TABLE(of, us3mc_match);
 
-static struct of_platform_driver us3mc_driver = {
+static struct platform_driver us3mc_driver = {
 	.driver = {
 		.name = "us3mc",
 		.owner = THIS_MODULE,
@@ -848,7 +845,7 @@ static int __init us3mc_init(void)
 	ret = register_dimm_printer(us3mc_dimm_printer);
 
 	if (!ret) {
-		ret = of_register_platform_driver(&us3mc_driver);
+		ret = platform_driver_register(&us3mc_driver);
 		if (ret)
 			unregister_dimm_printer(us3mc_dimm_printer);
 	}
@@ -859,7 +856,7 @@ static void __exit us3mc_cleanup(void)
 {
 	if (us3mc_platform()) {
 		unregister_dimm_printer(us3mc_dimm_printer);
-		of_unregister_platform_driver(&us3mc_driver);
+		platform_driver_unregister(&us3mc_driver);
 	}
 }
 
diff --git a/arch/sparc/kernel/cpu.c b/arch/sparc/kernel/cpu.c
index 0dc714f..7925c54 100644
--- a/arch/sparc/kernel/cpu.c
+++ b/arch/sparc/kernel/cpu.c
@@ -324,7 +324,7 @@ void __cpuinit cpu_probe(void)
 	psr = get_psr();
 	put_psr(psr | PSR_EF);
 #ifdef CONFIG_SPARC_LEON
-	fpu_vers = 7;
+	fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7;
 #else
 	fpu_vers = ((get_fsr() >> 17) & 0x7);
 #endif
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index c011b93..d1f1361 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -213,8 +213,8 @@ extern struct cheetah_err_info *cheetah_error_log;
 struct ino_bucket {
 /*0x00*/unsigned long __irq_chain_pa;
 
-	/* Virtual interrupt number assigned to this INO.  */
-/*0x08*/unsigned int __virt_irq;
+	/* Interrupt number assigned to this INO.  */
+/*0x08*/unsigned int __irq;
 /*0x0c*/unsigned int __pad;
 };
 
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 72509d0..6f01e8c 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -333,13 +333,10 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
 				 void *cpu, dma_addr_t dvma)
 {
 	struct iommu *iommu;
-	iopte_t *iopte;
 	unsigned long flags, order, npages;
 
 	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
 	iommu = dev->archdata.iommu;
-	iopte = iommu->page_table +
-		((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 41f7e4e..c6ce9a6 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -50,10 +50,14 @@
 #include <asm/io-unit.h>
 #include <asm/leon.h>
 
-#ifdef CONFIG_SPARC_LEON
-#define mmu_inval_dma_area(p, l) leon_flush_dcache_all()
-#else
+#ifndef CONFIG_SPARC_LEON
 #define mmu_inval_dma_area(p, l)	/* Anton pulled it out for 2.4.0-xx */
+#else
+static inline void mmu_inval_dma_area(void *va, unsigned long len)
+{
+	if (!sparc_leon3_snooping_enabled())
+		leon_flush_dcache_all();
+}
 #endif
 
 static struct resource *_sparc_find_resource(struct resource *r,
@@ -254,7 +258,7 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 				 dma_addr_t *dma_addrp, gfp_t gfp)
 {
 	struct platform_device *op = to_platform_device(dev);
-	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
+	unsigned long len_total = PAGE_ALIGN(len);
 	unsigned long va;
 	struct resource *res;
 	int order;
@@ -280,7 +284,8 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
 		goto err_nova;
 	}
-	mmu_inval_dma_area(va, len_total);
+	mmu_inval_dma_area((void *)va, len_total);
+
 	// XXX The mmu_map_dma_area does this for us below, see comments.
 	// sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
@@ -297,9 +302,9 @@ static void *sbus_alloc_coherent(struct device *dev, size_t len,
 err_noiommu:
 	release_resource(res);
 err_nova:
-	free_pages(va, order);
-err_nomem:
 	kfree(res);
+err_nomem:
+	free_pages(va, order);
 err_nopages:
 	return NULL;
 }
@@ -321,7 +326,7 @@ static void sbus_free_coherent(struct device *dev, size_t n, void *p,
 		return;
 	}
 
-	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	n = PAGE_ALIGN(n);
 	if ((res->end-res->start)+1 != n) {
 		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
 		    (long)((res->end-res->start)+1), n);
@@ -408,9 +413,6 @@ struct dma_map_ops sbus_dma_ops = {
 	.sync_sg_for_device	= sbus_sync_sg_for_device,
 };
 
-struct dma_map_ops *dma_ops = &sbus_dma_ops;
-EXPORT_SYMBOL(dma_ops);
-
 static int __init sparc_register_ioport(void)
 {
 	register_proc_sparc_ioport();
@@ -422,7 +424,9 @@ arch_initcall(sparc_register_ioport);
 
 #endif /* CONFIG_SBUS */
 
-#ifdef CONFIG_PCI
+
+/* LEON reuses PCI DMA ops */
+#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON)
 
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
  * hwdev should be valid struct pci_dev pointer for PCI devices.
@@ -430,8 +434,8 @@ arch_initcall(sparc_register_ioport);
 static void *pci32_alloc_coherent(struct device *dev, size_t len,
 				  dma_addr_t *pba, gfp_t gfp)
 {
-	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
-	unsigned long va;
+	unsigned long len_total = PAGE_ALIGN(len);
+	void *va;
 	struct resource *res;
 	int order;
 
@@ -443,34 +447,34 @@ static void *pci32_alloc_coherent(struct device *dev, size_t len,
 	}
 
 	order = get_order(len_total);
-	va = __get_free_pages(GFP_KERNEL, order);
-	if (va == 0) {
+	va = (void *) __get_free_pages(GFP_KERNEL, order);
+	if (va == NULL) {
 		printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT);
-		return NULL;
+		goto err_nopages;
 	}
 
 	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		free_pages(va, order);
 		printk("pci_alloc_consistent: no core\n");
-		return NULL;
+		goto err_nomem;
 	}
 
 	if (allocate_resource(&_sparc_dvma, res, len_total,
 	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
 		printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
-		free_pages(va, order);
-		kfree(res);
-		return NULL;
+		goto err_nova;
 	}
 	mmu_inval_dma_area(va, len_total);
-#if 0
-/* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %lx\n",
-  (long)va, (long)res->start, (long)virt_to_phys(va), len_total);
-#endif
 	sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
 
 	*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
 	return (void *) res->start;
+
+err_nova:
+	kfree(res);
+err_nomem:
+	free_pages((unsigned long)va, order);
+err_nopages:
+	return NULL;
 }
 
 /* Free and unmap a consistent DMA buffer.
@@ -485,7 +489,7 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
 				dma_addr_t ba)
 {
 	struct resource *res;
-	unsigned long pgp;
+	void *pgp;
 
 	if ((res = _sparc_find_resource(&_sparc_dvma,
 	    (unsigned long)p)) == NULL) {
@@ -498,21 +502,21 @@ static void pci32_free_coherent(struct device *dev, size_t n, void *p,
 		return;
 	}
 
-	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	n = PAGE_ALIGN(n);
 	if ((res->end-res->start)+1 != n) {
 		printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
 		    (long)((res->end-res->start)+1), (long)n);
 		return;
 	}
 
-	pgp = (unsigned long) phys_to_virt(ba);	/* bus_to_virt actually */
+	pgp = phys_to_virt(ba);	/* bus_to_virt actually */
 	mmu_inval_dma_area(pgp, n);
 	sparc_unmapiorange((unsigned long)p, n);
 
 	release_resource(res);
 	kfree(res);
 
-	free_pages(pgp, get_order(n));
+	free_pages((unsigned long)pgp, get_order(n));
 }
 
 /*
@@ -527,6 +531,13 @@ static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
 	return page_to_phys(page) + offset;
 }
 
+static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
+			     enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	if (dir != PCI_DMA_TODEVICE)
+		mmu_inval_dma_area(phys_to_virt(ba), PAGE_ALIGN(size));
+}
+
 /* Map a set of buffers described by scatterlist in streaming
  * mode for DMA.  This is the scather-gather version of the
  * above pci_map_single interface.  Here the scatter gather list
@@ -572,9 +583,8 @@ static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl,
 	if (dir != PCI_DMA_TODEVICE) {
 		for_each_sg(sgl, sg, nents, n) {
 			BUG_ON(page_address(sg_page(sg)) == NULL);
-			mmu_inval_dma_area(
-			    (unsigned long) page_address(sg_page(sg)),
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+			mmu_inval_dma_area(page_address(sg_page(sg)),
+					   PAGE_ALIGN(sg->length));
 		}
 	}
 }
@@ -593,8 +603,8 @@ static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba,
 				      size_t size, enum dma_data_direction dir)
 {
 	if (dir != PCI_DMA_TODEVICE) {
-		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
-		    (size + PAGE_SIZE-1) & PAGE_MASK);
+		mmu_inval_dma_area(phys_to_virt(ba),
+				   PAGE_ALIGN(size));
 	}
 }
 
@@ -602,8 +612,8 @@ static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba,
 					 size_t size, enum dma_data_direction dir)
 {
 	if (dir != PCI_DMA_TODEVICE) {
-		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
-		    (size + PAGE_SIZE-1) & PAGE_MASK);
+		mmu_inval_dma_area(phys_to_virt(ba),
+				   PAGE_ALIGN(size));
 	}
 }
 
@@ -622,9 +632,8 @@ static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
 	if (dir != PCI_DMA_TODEVICE) {
 		for_each_sg(sgl, sg, nents, n) {
 			BUG_ON(page_address(sg_page(sg)) == NULL);
-			mmu_inval_dma_area(
-			    (unsigned long) page_address(sg_page(sg)),
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+			mmu_inval_dma_area(page_address(sg_page(sg)),
+					   PAGE_ALIGN(sg->length));
 		}
 	}
 }
@@ -638,9 +647,8 @@ static void pci32_sync_sg_for_device(struct device *device, struct scatterlist *
 	if (dir != PCI_DMA_TODEVICE) {
 		for_each_sg(sgl, sg, nents, n) {
 			BUG_ON(page_address(sg_page(sg)) == NULL);
-			mmu_inval_dma_area(
-			    (unsigned long) page_address(sg_page(sg)),
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+			mmu_inval_dma_area(page_address(sg_page(sg)),
+					   PAGE_ALIGN(sg->length));
 		}
 	}
 }
@@ -649,6 +657,7 @@ struct dma_map_ops pci32_dma_ops = {
 	.alloc_coherent		= pci32_alloc_coherent,
 	.free_coherent		= pci32_free_coherent,
 	.map_page		= pci32_map_page,
+	.unmap_page		= pci32_unmap_page,
 	.map_sg			= pci32_map_sg,
 	.unmap_sg		= pci32_unmap_sg,
 	.sync_single_for_cpu	= pci32_sync_single_for_cpu,
@@ -658,7 +667,16 @@ struct dma_map_ops pci32_dma_ops = {
 };
 EXPORT_SYMBOL(pci32_dma_ops);
 
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */
+
+#ifdef CONFIG_SPARC_LEON
+struct dma_map_ops *dma_ops = &pci32_dma_ops;
+#elif defined(CONFIG_SBUS)
+struct dma_map_ops *dma_ops = &sbus_dma_ops;
+#endif
+
+EXPORT_SYMBOL(dma_ops);
+
 
 /*
  * Return whether the given PCI device DMA address mask can be
@@ -717,7 +735,7 @@ static const struct file_operations sparc_io_proc_fops = {
 static struct resource *_sparc_find_resource(struct resource *root,
 					     unsigned long hit)
 {
-        struct resource *tmp;
+	struct resource *tmp;
 
 	for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
 		if (tmp->start <= hit && tmp->end >= hit)
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h
index db75138..008453b 100644
--- a/arch/sparc/kernel/irq.h
+++ b/arch/sparc/kernel/irq.h
@@ -1,5 +1,41 @@
+#include <linux/platform_device.h>
+
 #include <asm/btfixup.h>
 
+/* sun4m specific type definitions */
+
+/* This maps direct to CPU specific interrupt registers */
+struct sun4m_irq_percpu {
+	u32	pending;
+	u32	clear;
+	u32	set;
+};
+
+/* This maps direct to global interrupt registers */
+struct sun4m_irq_global {
+	u32	pending;
+	u32	mask;
+	u32	mask_clear;
+	u32	mask_set;
+	u32	interrupt_target;
+};
+
+extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
+extern struct sun4m_irq_global __iomem *sun4m_irq_global;
+
+/*
+ * Platform specific irq configuration
+ * The individual platforms assign their platform
+ * specifics in their init functions.
+ */
+struct sparc_irq_config {
+	void (*init_timers)(irq_handler_t);
+	unsigned int (*build_device_irq)(struct platform_device *op,
+	                                 unsigned int real_irq);
+};
+extern struct sparc_irq_config sparc_irq_config;
+
+
 /* Dave Redman (djhr@tadpole.co.uk)
  * changed these to function pointers.. it saves cycles and will allow
  * the irq dependencies to be split into different files at a later date
@@ -45,12 +81,6 @@ static inline void load_profile_irq(int cpu, int limit)
 	BTFIXUP_CALL(load_profile_irq)(cpu, limit);
 }
 
-extern void (*sparc_init_timers)(irq_handler_t lvl10_irq);
-
-extern void claim_ticker14(irq_handler_t irq_handler,
-			   int irq,
-			   unsigned int timeout);
-
 #ifdef CONFIG_SMP
 BTFIXUPDEF_CALL(void, set_cpu_int, int, int)
 BTFIXUPDEF_CALL(void, clear_cpu_int, int, int)
diff --git a/arch/sparc/kernel/irq_32.c b/arch/sparc/kernel/irq_32.c
index 5ad6e5c..7c93df4 100644
--- a/arch/sparc/kernel/irq_32.c
+++ b/arch/sparc/kernel/irq_32.c
@@ -1,8 +1,8 @@
 /*
- *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
- *                            Sparc the IRQs are basically 'cast in stone'
- *                            and you are supposed to probe the prom's device
- *                            node trees to find out who's got which IRQ.
+ * Interrupt request handling routines. On the
+ * Sparc the IRQs are basically 'cast in stone'
+ * and you are supposed to probe the prom's device
+ * node trees to find out who's got which IRQ.
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -11,40 +11,11 @@
  *  Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
  */
 
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/linkage.h>
 #include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/delay.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
 #include <linux/seq_file.h>
 
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/smp.h>
-#include <asm/vaddrs.h>
-#include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/pcic.h>
 #include <asm/cacheflush.h>
-#include <asm/irq_regs.h>
+#include <asm/pcic.h>
 #include <asm/leon.h>
 
 #include "kernel.h"
@@ -57,6 +28,10 @@
 #define SMP_NOP2
 #define SMP_NOP3
 #endif /* SMP */
+
+/* platform specific irq setup */
+struct sparc_irq_config sparc_irq_config;
+
 unsigned long arch_local_irq_save(void)
 {
 	unsigned long retval;
@@ -128,15 +103,7 @@ EXPORT_SYMBOL(arch_local_irq_restore);
  *
  */
 
-static void irq_panic(void)
-{
-    extern char *cputypval;
-    prom_printf("machine: %s doesn't have irq handlers defined!\n",cputypval);
-    prom_halt();
-}
 
-void (*sparc_init_timers)(irq_handler_t ) =
-    (void (*)(irq_handler_t )) irq_panic;
 
 /*
  * Dave Redman (djhr@tadpole.co.uk)
@@ -145,7 +112,7 @@ void (*sparc_init_timers)(irq_handler_t ) =
  * instead, because some of the devices attach very early, I do something
  * equally sucky but at least we'll never try to free statically allocated
  * space or call kmalloc before kmalloc_init :(.
- * 
+ *
  * In fact it's the timer10 that attaches first.. then timer14
  * then kmalloc_init is called.. then the tty interrupts attach.
  * hmmm....
@@ -166,22 +133,20 @@ DEFINE_SPINLOCK(irq_action_lock);
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i = *(loff_t *) v;
-	struct irqaction * action;
+	int i = *(loff_t *)v;
+	struct irqaction *action;
 	unsigned long flags;
 #ifdef CONFIG_SMP
 	int j;
 #endif
 
-	if (sparc_cpu_model == sun4d) {
-		extern int show_sun4d_interrupts(struct seq_file *, void *);
-		
+	if (sparc_cpu_model == sun4d)
 		return show_sun4d_interrupts(p, v);
-	}
+
 	spin_lock_irqsave(&irq_action_lock, flags);
 	if (i < NR_IRQS) {
 		action = sparc_irq[i].action;
-		if (!action) 
+		if (!action)
 			goto out_unlock;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
@@ -195,7 +160,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		seq_printf(p, " %c %s",
 			(action->flags & IRQF_DISABLED) ? '+' : ' ',
 			action->name);
-		for (action=action->next; action; action = action->next) {
+		for (action = action->next; action; action = action->next) {
 			seq_printf(p, ",%s %s",
 				(action->flags & IRQF_DISABLED) ? " +" : "",
 				action->name);
@@ -209,22 +174,20 @@ out_unlock:
 
 void free_irq(unsigned int irq, void *dev_id)
 {
-	struct irqaction * action;
+	struct irqaction *action;
 	struct irqaction **actionp;
-        unsigned long flags;
+	unsigned long flags;
 	unsigned int cpu_irq;
-	
+
 	if (sparc_cpu_model == sun4d) {
-		extern void sun4d_free_irq(unsigned int, void *);
-		
 		sun4d_free_irq(irq, dev_id);
 		return;
 	}
 	cpu_irq = irq & (NR_IRQS - 1);
-        if (cpu_irq > 14) {  /* 14 irq levels on the sparc */
-                printk("Trying to free bogus IRQ %d\n", irq);
-                return;
-        }
+	if (cpu_irq > 14) {  /* 14 irq levels on the sparc */
+		printk(KERN_ERR "Trying to free bogus IRQ %d\n", irq);
+		return;
+	}
 
 	spin_lock_irqsave(&irq_action_lock, flags);
 
@@ -232,7 +195,7 @@ void free_irq(unsigned int irq, void *dev_id)
 	action = *actionp;
 
 	if (!action->handler) {
-		printk("Trying to free free IRQ%d\n",irq);
+		printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
 		goto out_unlock;
 	}
 	if (dev_id) {
@@ -242,19 +205,21 @@ void free_irq(unsigned int irq, void *dev_id)
 			actionp = &action->next;
 		}
 		if (!action) {
-			printk("Trying to free free shared IRQ%d\n",irq);
+			printk(KERN_ERR "Trying to free free shared IRQ%d\n",
+			       irq);
 			goto out_unlock;
 		}
 	} else if (action->flags & IRQF_SHARED) {
-		printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+		printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
+		       irq);
 		goto out_unlock;
 	}
-	if (action->flags & SA_STATIC_ALLOC)
-	{
-		/* This interrupt is marked as specially allocated
+	if (action->flags & SA_STATIC_ALLOC) {
+		/*
+		 * This interrupt is marked as specially allocated
 		 * so it is a bad idea to free it.
 		 */
-		printk("Attempt to free statically allocated IRQ%d (%s)\n",
+		printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
 		       irq, action->name);
 		goto out_unlock;
 	}
@@ -275,7 +240,6 @@ void free_irq(unsigned int irq, void *dev_id)
 out_unlock:
 	spin_unlock_irqrestore(&irq_action_lock, flags);
 }
-
 EXPORT_SYMBOL(free_irq);
 
 /*
@@ -297,64 +261,62 @@ void synchronize_irq(unsigned int irq)
 EXPORT_SYMBOL(synchronize_irq);
 #endif /* SMP */
 
-void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
+void unexpected_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
-        int i;
-	struct irqaction * action;
+	int i;
+	struct irqaction *action;
 	unsigned int cpu_irq;
-	
+
 	cpu_irq = irq & (NR_IRQS - 1);
 	action = sparc_irq[cpu_irq].action;
 
-        printk("IO device interrupt, irq = %d\n", irq);
-        printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, 
+	printk(KERN_ERR "IO device interrupt, irq = %d\n", irq);
+	printk(KERN_ERR "PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
 		    regs->npc, regs->u_regs[14]);
 	if (action) {
-		printk("Expecting: ");
-        	for (i = 0; i < 16; i++)
-                	if (action->handler)
-                        	printk("[%s:%d:0x%x] ", action->name,
-				       (int) i, (unsigned int) action->handler);
+		printk(KERN_ERR "Expecting: ");
+		for (i = 0; i < 16; i++)
+			if (action->handler)
+				printk(KERN_CONT "[%s:%d:0x%x] ", action->name,
+				       i, (unsigned int)action->handler);
 	}
-        printk("AIEEE\n");
+	printk(KERN_ERR "AIEEE\n");
 	panic("bogus interrupt received");
 }
 
-void handler_irq(int irq, struct pt_regs * regs)
+void handler_irq(int pil, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
-	struct irqaction * action;
+	struct irqaction *action;
 	int cpu = smp_processor_id();
-#ifdef CONFIG_SMP
-	extern void smp4m_irq_rotate(int cpu);
-#endif
 
 	old_regs = set_irq_regs(regs);
 	irq_enter();
-	disable_pil_irq(irq);
+	disable_pil_irq(pil);
 #ifdef CONFIG_SMP
 	/* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */
-	if((sparc_cpu_model==sun4m) && (irq < 10))
+	if ((sparc_cpu_model==sun4m) && (pil < 10))
 		smp4m_irq_rotate(cpu);
 #endif
-	action = sparc_irq[irq].action;
-	sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
-	kstat_cpu(cpu).irqs[irq]++;
+	action = sparc_irq[pil].action;
+	sparc_irq[pil].flags |= SPARC_IRQ_INPROGRESS;
+	kstat_cpu(cpu).irqs[pil]++;
 	do {
 		if (!action || !action->handler)
-			unexpected_irq(irq, NULL, regs);
-		action->handler(irq, action->dev_id);
+			unexpected_irq(pil, NULL, regs);
+		action->handler(pil, action->dev_id);
 		action = action->next;
 	} while (action);
-	sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
-	enable_pil_irq(irq);
+	sparc_irq[pil].flags &= ~SPARC_IRQ_INPROGRESS;
+	enable_pil_irq(pil);
 	irq_exit();
 	set_irq_regs(old_regs);
 }
 
 #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
 
-/* Fast IRQs on the Sparc can only have one routine attached to them,
+/*
+ * Fast IRQs on the Sparc can only have one routine attached to them,
  * thus no sharing possible.
  */
 static int request_fast_irq(unsigned int irq,
@@ -367,15 +329,13 @@ static int request_fast_irq(unsigned int irq,
 	int ret;
 #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
 	struct tt_entry *trap_table;
-	extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;
 #endif
-	
 	cpu_irq = irq & (NR_IRQS - 1);
-	if(cpu_irq > 14) {
+	if (cpu_irq > 14) {
 		ret = -EINVAL;
 		goto out;
 	}
-	if(!handler) {
+	if (!handler) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -383,34 +343,33 @@ static int request_fast_irq(unsigned int irq,
 	spin_lock_irqsave(&irq_action_lock, flags);
 
 	action = sparc_irq[cpu_irq].action;
-	if(action) {
-		if(action->flags & IRQF_SHARED)
+	if (action) {
+		if (action->flags & IRQF_SHARED)
 			panic("Trying to register fast irq when already shared.\n");
-		if(irqflags & IRQF_SHARED)
+		if (irqflags & IRQF_SHARED)
 			panic("Trying to register fast irq as shared.\n");
 
 		/* Anyway, someone already owns it so cannot be made fast. */
-		printk("request_fast_irq: Trying to register yet already owned.\n");
+		printk(KERN_ERR "request_fast_irq: Trying to register yet already owned.\n");
 		ret = -EBUSY;
 		goto out_unlock;
 	}
 
-	/* If this is flagged as statically allocated then we use our
+	/*
+	 * If this is flagged as statically allocated then we use our
 	 * private struct which is never freed.
 	 */
 	if (irqflags & SA_STATIC_ALLOC) {
-	    if (static_irq_count < MAX_STATIC_ALLOC)
-		action = &static_irqaction[static_irq_count++];
-	    else
-		printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
-		       irq, devname);
+		if (static_irq_count < MAX_STATIC_ALLOC)
+			action = &static_irqaction[static_irq_count++];
+		else
+			printk(KERN_ERR "Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
+			       irq, devname);
 	}
-	
+
 	if (action == NULL)
-	    action = kmalloc(sizeof(struct irqaction),
-						 GFP_ATOMIC);
-	
-	if (!action) { 
+		action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+	if (!action) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
@@ -426,9 +385,12 @@ static int request_fast_irq(unsigned int irq,
 
 	INSTANTIATE(sparc_ttable)
 #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
-	trap_table = &trapbase_cpu1; INSTANTIATE(trap_table)
-	trap_table = &trapbase_cpu2; INSTANTIATE(trap_table)
-	trap_table = &trapbase_cpu3; INSTANTIATE(trap_table)
+	trap_table = &trapbase_cpu1;
+	INSTANTIATE(trap_table)
+	trap_table = &trapbase_cpu2;
+	INSTANTIATE(trap_table)
+	trap_table = &trapbase_cpu3;
+	INSTANTIATE(trap_table)
 #endif
 #undef INSTANTIATE
 	/*
@@ -454,7 +416,8 @@ out:
 	return ret;
 }
 
-/* These variables are used to access state from the assembler
+/*
+ * These variables are used to access state from the assembler
  * interrupt handler, floppy_hardint, so we cannot put these in
  * the floppy driver image because that would not work in the
  * modular case.
@@ -477,8 +440,6 @@ EXPORT_SYMBOL(pdma_base);
 unsigned long pdma_areasize;
 EXPORT_SYMBOL(pdma_areasize);
 
-extern void floppy_hardint(void);
-
 static irq_handler_t floppy_irq_handler;
 
 void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
@@ -494,9 +455,11 @@ void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
 	irq_exit();
 	enable_pil_irq(irq);
 	set_irq_regs(old_regs);
-	// XXX Eek, it's totally changed with preempt_count() and such
-	// if (softirq_pending(cpu))
-	//	do_softirq();
+	/*
+	 * XXX Eek, it's totally changed with preempt_count() and such
+	 * if (softirq_pending(cpu))
+	 *	do_softirq();
+	 */
 }
 
 int sparc_floppy_request_irq(int irq, unsigned long flags,
@@ -511,21 +474,18 @@ EXPORT_SYMBOL(sparc_floppy_request_irq);
 
 int request_irq(unsigned int irq,
 		irq_handler_t handler,
-		unsigned long irqflags, const char * devname, void *dev_id)
+		unsigned long irqflags, const char *devname, void *dev_id)
 {
-	struct irqaction * action, **actionp;
+	struct irqaction *action, **actionp;
 	unsigned long flags;
 	unsigned int cpu_irq;
 	int ret;
-	
-	if (sparc_cpu_model == sun4d) {
-		extern int sun4d_request_irq(unsigned int, 
-					     irq_handler_t ,
-					     unsigned long, const char *, void *);
+
+	if (sparc_cpu_model == sun4d)
 		return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
-	}
+
 	cpu_irq = irq & (NR_IRQS - 1);
-	if(cpu_irq > 14) {
+	if (cpu_irq > 14) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -533,7 +493,7 @@ int request_irq(unsigned int irq,
 		ret = -EINVAL;
 		goto out;
 	}
-	    
+
 	spin_lock_irqsave(&irq_action_lock, flags);
 
 	actionp = &sparc_irq[cpu_irq].action;
@@ -544,7 +504,8 @@ int request_irq(unsigned int irq,
 			goto out_unlock;
 		}
 		if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) {
-			printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+			printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
+			       irq);
 			ret = -EBUSY;
 			goto out_unlock;
 		}
@@ -559,14 +520,12 @@ int request_irq(unsigned int irq,
 		if (static_irq_count < MAX_STATIC_ALLOC)
 			action = &static_irqaction[static_irq_count++];
 		else
-			printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname);
+			printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
+			       irq, devname);
 	}
-	
 	if (action == NULL)
-		action = kmalloc(sizeof(struct irqaction),
-						     GFP_ATOMIC);
-	
-	if (!action) { 
+		action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+	if (!action) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
@@ -587,7 +546,6 @@ out_unlock:
 out:
 	return ret;
 }
-
 EXPORT_SYMBOL(request_irq);
 
 void disable_irq_nosync(unsigned int irq)
@@ -606,26 +564,30 @@ void enable_irq(unsigned int irq)
 {
 	__enable_irq(irq);
 }
-
 EXPORT_SYMBOL(enable_irq);
 
-/* We really don't need these at all on the Sparc.  We only have
+/*
+ * We really don't need these at all on the Sparc.  We only have
  * stubs here because they are exported to modules.
  */
 unsigned long probe_irq_on(void)
 {
 	return 0;
 }
-
 EXPORT_SYMBOL(probe_irq_on);
 
 int probe_irq_off(unsigned long mask)
 {
 	return 0;
 }
-
 EXPORT_SYMBOL(probe_irq_off);
 
+static unsigned int build_device_irq(struct platform_device *op,
+                                     unsigned int real_irq)
+{
+	return real_irq;
+}
+
 /* djhr
  * This could probably be made indirect too and assigned in the CPU
  * bits of the code. That would be much nicer I think and would also
@@ -636,11 +598,9 @@ EXPORT_SYMBOL(probe_irq_off);
 
 void __init init_IRQ(void)
 {
-	extern void sun4c_init_IRQ( void );
-	extern void sun4m_init_IRQ( void );
-	extern void sun4d_init_IRQ( void );
+	sparc_irq_config.build_device_irq = build_device_irq;
 
-	switch(sparc_cpu_model) {
+	switch (sparc_cpu_model) {
 	case sun4c:
 	case sun4:
 		sun4c_init_IRQ();
@@ -656,7 +616,7 @@ void __init init_IRQ(void)
 #endif
 		sun4m_init_IRQ();
 		break;
-		
+
 	case sun4d:
 		sun4d_init_IRQ();
 		break;
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 830d70a..eb16e3b 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -82,7 +82,7 @@ static void bucket_clear_chain_pa(unsigned long bucket_pa)
 			       "i" (ASI_PHYS_USE_EC));
 }
 
-static unsigned int bucket_get_virt_irq(unsigned long bucket_pa)
+static unsigned int bucket_get_irq(unsigned long bucket_pa)
 {
 	unsigned int ret;
 
@@ -90,21 +90,20 @@ static unsigned int bucket_get_virt_irq(unsigned long bucket_pa)
 			     : "=&r" (ret)
 			     : "r" (bucket_pa +
 				    offsetof(struct ino_bucket,
-					     __virt_irq)),
+					     __irq)),
 			       "i" (ASI_PHYS_USE_EC));
 
 	return ret;
 }
 
-static void bucket_set_virt_irq(unsigned long bucket_pa,
-				unsigned int virt_irq)
+static void bucket_set_irq(unsigned long bucket_pa, unsigned int irq)
 {
 	__asm__ __volatile__("stwa	%0, [%1] %2"
 			     : /* no outputs */
-			     : "r" (virt_irq),
+			     : "r" (irq),
 			       "r" (bucket_pa +
 				    offsetof(struct ino_bucket,
-					     __virt_irq)),
+					     __irq)),
 			       "i" (ASI_PHYS_USE_EC));
 }
 
@@ -114,50 +113,49 @@ static struct {
 	unsigned int dev_handle;
 	unsigned int dev_ino;
 	unsigned int in_use;
-} virt_irq_table[NR_IRQS];
-static DEFINE_SPINLOCK(virt_irq_alloc_lock);
+} irq_table[NR_IRQS];
+static DEFINE_SPINLOCK(irq_alloc_lock);
 
-unsigned char virt_irq_alloc(unsigned int dev_handle,
-			     unsigned int dev_ino)
+unsigned char irq_alloc(unsigned int dev_handle, unsigned int dev_ino)
 {
 	unsigned long flags;
 	unsigned char ent;
 
 	BUILD_BUG_ON(NR_IRQS >= 256);
 
-	spin_lock_irqsave(&virt_irq_alloc_lock, flags);
+	spin_lock_irqsave(&irq_alloc_lock, flags);
 
 	for (ent = 1; ent < NR_IRQS; ent++) {
-		if (!virt_irq_table[ent].in_use)
+		if (!irq_table[ent].in_use)
 			break;
 	}
 	if (ent >= NR_IRQS) {
 		printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
 		ent = 0;
 	} else {
-		virt_irq_table[ent].dev_handle = dev_handle;
-		virt_irq_table[ent].dev_ino = dev_ino;
-		virt_irq_table[ent].in_use = 1;
+		irq_table[ent].dev_handle = dev_handle;
+		irq_table[ent].dev_ino = dev_ino;
+		irq_table[ent].in_use = 1;
 	}
 
-	spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
+	spin_unlock_irqrestore(&irq_alloc_lock, flags);
 
 	return ent;
 }
 
 #ifdef CONFIG_PCI_MSI
-void virt_irq_free(unsigned int virt_irq)
+void irq_free(unsigned int irq)
 {
 	unsigned long flags;
 
-	if (virt_irq >= NR_IRQS)
+	if (irq >= NR_IRQS)
 		return;
 
-	spin_lock_irqsave(&virt_irq_alloc_lock, flags);
+	spin_lock_irqsave(&irq_alloc_lock, flags);
 
-	virt_irq_table[virt_irq].in_use = 0;
+	irq_table[irq].in_use = 0;
 
-	spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
+	spin_unlock_irqrestore(&irq_alloc_lock, flags);
 }
 #endif
 
@@ -190,7 +188,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %9s", irq_desc[i].chip->name);
+		seq_printf(p, " %9s", irq_desc[i].irq_data.chip->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -253,39 +251,38 @@ struct irq_handler_data {
 };
 
 #ifdef CONFIG_SMP
-static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity)
+static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity)
 {
 	cpumask_t mask;
 	int cpuid;
 
 	cpumask_copy(&mask, affinity);
 	if (cpus_equal(mask, cpu_online_map)) {
-		cpuid = map_to_cpu(virt_irq);
+		cpuid = map_to_cpu(irq);
 	} else {
 		cpumask_t tmp;
 
 		cpus_and(tmp, cpu_online_map, mask);
-		cpuid = cpus_empty(tmp) ? map_to_cpu(virt_irq) : first_cpu(tmp);
+		cpuid = cpus_empty(tmp) ? map_to_cpu(irq) : first_cpu(tmp);
 	}
 
 	return cpuid;
 }
 #else
-#define irq_choose_cpu(virt_irq, affinity)	\
+#define irq_choose_cpu(irq, affinity)	\
 	real_hard_smp_processor_id()
 #endif
 
-static void sun4u_irq_enable(unsigned int virt_irq)
+static void sun4u_irq_enable(struct irq_data *data)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_handler_data *handler_data = data->handler_data;
 
-	if (likely(data)) {
+	if (likely(handler_data)) {
 		unsigned long cpuid, imap, val;
 		unsigned int tid;
 
-		cpuid = irq_choose_cpu(virt_irq,
-				       irq_desc[virt_irq].affinity);
-		imap = data->imap;
+		cpuid = irq_choose_cpu(data->irq, data->affinity);
+		imap = handler_data->imap;
 
 		tid = sun4u_compute_tid(imap, cpuid);
 
@@ -294,21 +291,21 @@ static void sun4u_irq_enable(unsigned int virt_irq)
 			 IMAP_AID_SAFARI | IMAP_NID_SAFARI);
 		val |= tid | IMAP_VALID;
 		upa_writeq(val, imap);
-		upa_writeq(ICLR_IDLE, data->iclr);
+		upa_writeq(ICLR_IDLE, handler_data->iclr);
 	}
 }
 
-static int sun4u_set_affinity(unsigned int virt_irq,
-			       const struct cpumask *mask)
+static int sun4u_set_affinity(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_handler_data *handler_data = data->handler_data;
 
-	if (likely(data)) {
+	if (likely(handler_data)) {
 		unsigned long cpuid, imap, val;
 		unsigned int tid;
 
-		cpuid = irq_choose_cpu(virt_irq, mask);
-		imap = data->imap;
+		cpuid = irq_choose_cpu(data->irq, mask);
+		imap = handler_data->imap;
 
 		tid = sun4u_compute_tid(imap, cpuid);
 
@@ -317,7 +314,7 @@ static int sun4u_set_affinity(unsigned int virt_irq,
 			 IMAP_AID_SAFARI | IMAP_NID_SAFARI);
 		val |= tid | IMAP_VALID;
 		upa_writeq(val, imap);
-		upa_writeq(ICLR_IDLE, data->iclr);
+		upa_writeq(ICLR_IDLE, handler_data->iclr);
 	}
 
 	return 0;
@@ -340,27 +337,26 @@ static int sun4u_set_affinity(unsigned int virt_irq,
  * sees that, it also hooks up a default ->shutdown method which
  * invokes ->mask() which we do not want.  See irq_chip_set_defaults().
  */
-static void sun4u_irq_disable(unsigned int virt_irq)
+static void sun4u_irq_disable(struct irq_data *data)
 {
 }
 
-static void sun4u_irq_eoi(unsigned int virt_irq)
+static void sun4u_irq_eoi(struct irq_data *data)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	struct irq_desc *desc = irq_desc + virt_irq;
+	struct irq_handler_data *handler_data = data->handler_data;
+	struct irq_desc *desc = irq_desc + data->irq;
 
 	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		return;
 
-	if (likely(data))
-		upa_writeq(ICLR_IDLE, data->iclr);
+	if (likely(handler_data))
+		upa_writeq(ICLR_IDLE, handler_data->iclr);
 }
 
-static void sun4v_irq_enable(unsigned int virt_irq)
+static void sun4v_irq_enable(struct irq_data *data)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	unsigned long cpuid = irq_choose_cpu(virt_irq,
-					     irq_desc[virt_irq].affinity);
+	unsigned int ino = irq_table[data->irq].dev_ino;
+	unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity);
 	int err;
 
 	err = sun4v_intr_settarget(ino, cpuid);
@@ -377,11 +373,11 @@ static void sun4v_irq_enable(unsigned int virt_irq)
 		       ino, err);
 }
 
-static int sun4v_set_affinity(unsigned int virt_irq,
-			       const struct cpumask *mask)
+static int sun4v_set_affinity(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	unsigned long cpuid = irq_choose_cpu(virt_irq, mask);
+	unsigned int ino = irq_table[data->irq].dev_ino;
+	unsigned long cpuid = irq_choose_cpu(data->irq, mask);
 	int err;
 
 	err = sun4v_intr_settarget(ino, cpuid);
@@ -392,9 +388,9 @@ static int sun4v_set_affinity(unsigned int virt_irq,
 	return 0;
 }
 
-static void sun4v_irq_disable(unsigned int virt_irq)
+static void sun4v_irq_disable(struct irq_data *data)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+	unsigned int ino = irq_table[data->irq].dev_ino;
 	int err;
 
 	err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
@@ -403,10 +399,10 @@ static void sun4v_irq_disable(unsigned int virt_irq)
 		       "err(%d)\n", ino, err);
 }
 
-static void sun4v_irq_eoi(unsigned int virt_irq)
+static void sun4v_irq_eoi(struct irq_data *data)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	struct irq_desc *desc = irq_desc + virt_irq;
+	unsigned int ino = irq_table[data->irq].dev_ino;
+	struct irq_desc *desc = irq_desc + data->irq;
 	int err;
 
 	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
@@ -418,15 +414,15 @@ static void sun4v_irq_eoi(unsigned int virt_irq)
 		       "err(%d)\n", ino, err);
 }
 
-static void sun4v_virq_enable(unsigned int virt_irq)
+static void sun4v_virq_enable(struct irq_data *data)
 {
 	unsigned long cpuid, dev_handle, dev_ino;
 	int err;
 
-	cpuid = irq_choose_cpu(virt_irq, irq_desc[virt_irq].affinity);
+	cpuid = irq_choose_cpu(data->irq, data->affinity);
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
 	if (err != HV_EOK)
@@ -447,16 +443,16 @@ static void sun4v_virq_enable(unsigned int virt_irq)
 		       dev_handle, dev_ino, err);
 }
 
-static int sun4v_virt_set_affinity(unsigned int virt_irq,
-				    const struct cpumask *mask)
+static int sun4v_virt_set_affinity(struct irq_data *data,
+				    const struct cpumask *mask, bool force)
 {
 	unsigned long cpuid, dev_handle, dev_ino;
 	int err;
 
-	cpuid = irq_choose_cpu(virt_irq, mask);
+	cpuid = irq_choose_cpu(data->irq, mask);
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
 	if (err != HV_EOK)
@@ -467,13 +463,13 @@ static int sun4v_virt_set_affinity(unsigned int virt_irq,
 	return 0;
 }
 
-static void sun4v_virq_disable(unsigned int virt_irq)
+static void sun4v_virq_disable(struct irq_data *data)
 {
 	unsigned long dev_handle, dev_ino;
 	int err;
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_valid(dev_handle, dev_ino,
 				    HV_INTR_DISABLED);
@@ -483,17 +479,17 @@ static void sun4v_virq_disable(unsigned int virt_irq)
 		       dev_handle, dev_ino, err);
 }
 
-static void sun4v_virq_eoi(unsigned int virt_irq)
+static void sun4v_virq_eoi(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_desc + virt_irq;
+	struct irq_desc *desc = irq_desc + data->irq;
 	unsigned long dev_handle, dev_ino;
 	int err;
 
 	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
 		return;
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_state(dev_handle, dev_ino,
 				    HV_INTR_STATE_IDLE);
@@ -504,50 +500,49 @@ static void sun4v_virq_eoi(unsigned int virt_irq)
 }
 
 static struct irq_chip sun4u_irq = {
-	.name		= "sun4u",
-	.enable		= sun4u_irq_enable,
-	.disable	= sun4u_irq_disable,
-	.eoi		= sun4u_irq_eoi,
-	.set_affinity	= sun4u_set_affinity,
+	.name			= "sun4u",
+	.irq_enable		= sun4u_irq_enable,
+	.irq_disable		= sun4u_irq_disable,
+	.irq_eoi		= sun4u_irq_eoi,
+	.irq_set_affinity	= sun4u_set_affinity,
 };
 
 static struct irq_chip sun4v_irq = {
-	.name		= "sun4v",
-	.enable		= sun4v_irq_enable,
-	.disable	= sun4v_irq_disable,
-	.eoi		= sun4v_irq_eoi,
-	.set_affinity	= sun4v_set_affinity,
+	.name			= "sun4v",
+	.irq_enable		= sun4v_irq_enable,
+	.irq_disable		= sun4v_irq_disable,
+	.irq_eoi		= sun4v_irq_eoi,
+	.irq_set_affinity	= sun4v_set_affinity,
 };
 
 static struct irq_chip sun4v_virq = {
-	.name		= "vsun4v",
-	.enable		= sun4v_virq_enable,
-	.disable	= sun4v_virq_disable,
-	.eoi		= sun4v_virq_eoi,
-	.set_affinity	= sun4v_virt_set_affinity,
+	.name			= "vsun4v",
+	.irq_enable		= sun4v_virq_enable,
+	.irq_disable		= sun4v_virq_disable,
+	.irq_eoi		= sun4v_virq_eoi,
+	.irq_set_affinity	= sun4v_virt_set_affinity,
 };
 
-static void pre_flow_handler(unsigned int virt_irq,
-				      struct irq_desc *desc)
+static void pre_flow_handler(unsigned int irq, struct irq_desc *desc)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+	struct irq_handler_data *handler_data = get_irq_data(irq);
+	unsigned int ino = irq_table[irq].dev_ino;
 
-	data->pre_handler(ino, data->arg1, data->arg2);
+	handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2);
 
-	handle_fasteoi_irq(virt_irq, desc);
+	handle_fasteoi_irq(irq, desc);
 }
 
-void irq_install_pre_handler(int virt_irq,
+void irq_install_pre_handler(int irq,
 			     void (*func)(unsigned int, void *, void *),
 			     void *arg1, void *arg2)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	struct irq_desc *desc = irq_desc + virt_irq;
+	struct irq_handler_data *handler_data = get_irq_data(irq);
+	struct irq_desc *desc = irq_desc + irq;
 
-	data->pre_handler = func;
-	data->arg1 = arg1;
-	data->arg2 = arg2;
+	handler_data->pre_handler = func;
+	handler_data->arg1 = arg1;
+	handler_data->arg2 = arg2;
 
 	desc->handle_irq = pre_flow_handler;
 }
@@ -555,81 +550,81 @@ void irq_install_pre_handler(int virt_irq,
 unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
 {
 	struct ino_bucket *bucket;
-	struct irq_handler_data *data;
-	unsigned int virt_irq;
+	struct irq_handler_data *handler_data;
+	unsigned int irq;
 	int ino;
 
 	BUG_ON(tlb_type == hypervisor);
 
 	ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
 	bucket = &ivector_table[ino];
-	virt_irq = bucket_get_virt_irq(__pa(bucket));
-	if (!virt_irq) {
-		virt_irq = virt_irq_alloc(0, ino);
-		bucket_set_virt_irq(__pa(bucket), virt_irq);
-		set_irq_chip_and_handler_name(virt_irq,
+	irq = bucket_get_irq(__pa(bucket));
+	if (!irq) {
+		irq = irq_alloc(0, ino);
+		bucket_set_irq(__pa(bucket), irq);
+		set_irq_chip_and_handler_name(irq,
 					      &sun4u_irq,
 					      handle_fasteoi_irq,
 					      "IVEC");
 	}
 
-	data = get_irq_chip_data(virt_irq);
-	if (unlikely(data))
+	handler_data = get_irq_data(irq);
+	if (unlikely(handler_data))
 		goto out;
 
-	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
-	if (unlikely(!data)) {
+	handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!handler_data)) {
 		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
-	set_irq_chip_data(virt_irq, data);
+	set_irq_data(irq, handler_data);
 
-	data->imap  = imap;
-	data->iclr  = iclr;
+	handler_data->imap  = imap;
+	handler_data->iclr  = iclr;
 
 out:
-	return virt_irq;
+	return irq;
 }
 
 static unsigned int sun4v_build_common(unsigned long sysino,
 				       struct irq_chip *chip)
 {
 	struct ino_bucket *bucket;
-	struct irq_handler_data *data;
-	unsigned int virt_irq;
+	struct irq_handler_data *handler_data;
+	unsigned int irq;
 
 	BUG_ON(tlb_type != hypervisor);
 
 	bucket = &ivector_table[sysino];
-	virt_irq = bucket_get_virt_irq(__pa(bucket));
-	if (!virt_irq) {
-		virt_irq = virt_irq_alloc(0, sysino);
-		bucket_set_virt_irq(__pa(bucket), virt_irq);
-		set_irq_chip_and_handler_name(virt_irq, chip,
+	irq = bucket_get_irq(__pa(bucket));
+	if (!irq) {
+		irq = irq_alloc(0, sysino);
+		bucket_set_irq(__pa(bucket), irq);
+		set_irq_chip_and_handler_name(irq, chip,
 					      handle_fasteoi_irq,
 					      "IVEC");
 	}
 
-	data = get_irq_chip_data(virt_irq);
-	if (unlikely(data))
+	handler_data = get_irq_data(irq);
+	if (unlikely(handler_data))
 		goto out;
 
-	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
-	if (unlikely(!data)) {
+	handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!handler_data)) {
 		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
-	set_irq_chip_data(virt_irq, data);
+	set_irq_data(irq, handler_data);
 
 	/* Catch accidental accesses to these things.  IMAP/ICLR handling
 	 * is done by hypervisor calls on sun4v platforms, not by direct
 	 * register accesses.
 	 */
-	data->imap = ~0UL;
-	data->iclr = ~0UL;
+	handler_data->imap = ~0UL;
+	handler_data->iclr = ~0UL;
 
 out:
-	return virt_irq;
+	return irq;
 }
 
 unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
@@ -641,11 +636,11 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
 
 unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
-	struct irq_handler_data *data;
+	struct irq_handler_data *handler_data;
 	unsigned long hv_err, cookie;
 	struct ino_bucket *bucket;
 	struct irq_desc *desc;
-	unsigned int virt_irq;
+	unsigned int irq;
 
 	bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
 	if (unlikely(!bucket))
@@ -662,32 +657,32 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 			     ((unsigned long) bucket +
 			      sizeof(struct ino_bucket)));
 
-	virt_irq = virt_irq_alloc(devhandle, devino);
-	bucket_set_virt_irq(__pa(bucket), virt_irq);
+	irq = irq_alloc(devhandle, devino);
+	bucket_set_irq(__pa(bucket), irq);
 
-	set_irq_chip_and_handler_name(virt_irq, &sun4v_virq,
+	set_irq_chip_and_handler_name(irq, &sun4v_virq,
 				      handle_fasteoi_irq,
 				      "IVEC");
 
-	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
-	if (unlikely(!data))
+	handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!handler_data))
 		return 0;
 
 	/* In order to make the LDC channel startup sequence easier,
 	 * especially wrt. locking, we do not let request_irq() enable
 	 * the interrupt.
 	 */
-	desc = irq_desc + virt_irq;
+	desc = irq_desc + irq;
 	desc->status |= IRQ_NOAUTOEN;
 
-	set_irq_chip_data(virt_irq, data);
+	set_irq_data(irq, handler_data);
 
 	/* Catch accidental accesses to these things.  IMAP/ICLR handling
 	 * is done by hypervisor calls on sun4v platforms, not by direct
 	 * register accesses.
 	 */
-	data->imap = ~0UL;
-	data->iclr = ~0UL;
+	handler_data->imap = ~0UL;
+	handler_data->iclr = ~0UL;
 
 	cookie = ~__pa(bucket);
 	hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie);
@@ -697,30 +692,30 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 		prom_halt();
 	}
 
-	return virt_irq;
+	return irq;
 }
 
-void ack_bad_irq(unsigned int virt_irq)
+void ack_bad_irq(unsigned int irq)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+	unsigned int ino = irq_table[irq].dev_ino;
 
 	if (!ino)
 		ino = 0xdeadbeef;
 
-	printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n",
-	       ino, virt_irq);
+	printk(KERN_CRIT "Unexpected IRQ from ino[%x] irq[%u]\n",
+	       ino, irq);
 }
 
 void *hardirq_stack[NR_CPUS];
 void *softirq_stack[NR_CPUS];
 
-void __irq_entry handler_irq(int irq, struct pt_regs *regs)
+void __irq_entry handler_irq(int pil, struct pt_regs *regs)
 {
 	unsigned long pstate, bucket_pa;
 	struct pt_regs *old_regs;
 	void *orig_sp;
 
-	clear_softint(1 << irq);
+	clear_softint(1 << pil);
 
 	old_regs = set_irq_regs(regs);
 	irq_enter();
@@ -741,16 +736,16 @@ void __irq_entry handler_irq(int irq, struct pt_regs *regs)
 	while (bucket_pa) {
 		struct irq_desc *desc;
 		unsigned long next_pa;
-		unsigned int virt_irq;
+		unsigned int irq;
 
 		next_pa = bucket_get_chain_pa(bucket_pa);
-		virt_irq = bucket_get_virt_irq(bucket_pa);
+		irq = bucket_get_irq(bucket_pa);
 		bucket_clear_chain_pa(bucket_pa);
 
-		desc = irq_desc + virt_irq;
+		desc = irq_desc + irq;
 
 		if (!(desc->status & IRQ_DISABLED))
-			desc->handle_irq(virt_irq, desc);
+			desc->handle_irq(irq, desc);
 
 		bucket_pa = next_pa;
 	}
@@ -798,9 +793,12 @@ void fixup_irqs(void)
 		raw_spin_lock_irqsave(&irq_desc[irq].lock, flags);
 		if (irq_desc[irq].action &&
 		    !(irq_desc[irq].status & IRQ_PER_CPU)) {
-			if (irq_desc[irq].chip->set_affinity)
-				irq_desc[irq].chip->set_affinity(irq,
-					irq_desc[irq].affinity);
+			struct irq_data *data = irq_get_irq_data(irq);
+
+			if (data->chip->irq_set_affinity)
+				data->chip->irq_set_affinity(data,
+				                             data->affinity,
+				                             false);
 		}
 		raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
 	}
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h
index 15d8a3f..24ad449 100644
--- a/arch/sparc/kernel/kernel.h
+++ b/arch/sparc/kernel/kernel.h
@@ -3,6 +3,8 @@
 
 #include <linux/interrupt.h>
 
+#include <asm/traps.h>
+
 /* cpu.c */
 extern const char *sparc_cpu_type;
 extern const char *sparc_pmu_type;
@@ -26,6 +28,53 @@ extern int static_irq_count;
 extern spinlock_t irq_action_lock;
 
 extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs);
+extern void init_IRQ(void);
+
+/* sun4c_irq.c */
+extern void sun4c_init_IRQ(void);
+
+/* sun4m_irq.c */
+extern unsigned int lvl14_resolution;
+
+extern void sun4m_init_IRQ(void);
+extern void sun4m_clear_profile_irq(int cpu);
+
+/* sun4d_irq.c */
+extern spinlock_t sun4d_imsk_lock;
+
+extern void sun4d_init_IRQ(void);
+extern int sun4d_request_irq(unsigned int irq,
+                             irq_handler_t handler,
+                             unsigned long irqflags,
+                             const char *devname, void *dev_id);
+extern int show_sun4d_interrupts(struct seq_file *, void *);
+extern void sun4d_distribute_irqs(void);
+extern void sun4d_free_irq(unsigned int irq, void *dev_id);
+
+/* head_32.S */
+extern unsigned int t_nmi[];
+extern unsigned int linux_trap_ipi15_sun4d[];
+extern unsigned int linux_trap_ipi15_sun4m[];
+
+extern struct tt_entry trapbase_cpu1;
+extern struct tt_entry trapbase_cpu2;
+extern struct tt_entry trapbase_cpu3;
+
+extern char cputypval[];
+
+/* entry.S */
+extern unsigned long lvl14_save[4];
+extern unsigned int real_irq_entry[];
+extern unsigned int smp4d_ticker[];
+extern unsigned int patchme_maybe_smp_msg[];
+
+extern void floppy_hardint(void);
+
+/* trampoline_32.S */
+extern int __smp4m_processor_id(void);
+extern int __smp4d_processor_id(void);
+extern unsigned long sun4m_cpu_startup;
+extern unsigned long sun4d_cpu_startup;
 
 #else /* CONFIG_SPARC32 */
 #endif /* CONFIG_SPARC32 */
diff --git a/arch/sparc/kernel/ldc.c b/arch/sparc/kernel/ldc.c
index df39a0f..732b0bc 100644
--- a/arch/sparc/kernel/ldc.c
+++ b/arch/sparc/kernel/ldc.c
@@ -790,16 +790,20 @@ static void send_events(struct ldc_channel *lp, unsigned int event_mask)
 static irqreturn_t ldc_rx(int irq, void *dev_id)
 {
 	struct ldc_channel *lp = dev_id;
-	unsigned long orig_state, hv_err, flags;
+	unsigned long orig_state, flags;
 	unsigned int event_mask;
 
 	spin_lock_irqsave(&lp->lock, flags);
 
 	orig_state = lp->chan_state;
-	hv_err = sun4v_ldc_rx_get_state(lp->id,
-					&lp->rx_head,
-					&lp->rx_tail,
-					&lp->chan_state);
+
+	/* We should probably check for hypervisor errors here and
+	 * reset the LDC channel if we get one.
+	 */
+	sun4v_ldc_rx_get_state(lp->id,
+			       &lp->rx_head,
+			       &lp->rx_tail,
+			       &lp->chan_state);
 
 	ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
 	       orig_state, lp->chan_state, lp->rx_head, lp->rx_tail);
@@ -904,16 +908,20 @@ out:
 static irqreturn_t ldc_tx(int irq, void *dev_id)
 {
 	struct ldc_channel *lp = dev_id;
-	unsigned long flags, hv_err, orig_state;
+	unsigned long flags, orig_state;
 	unsigned int event_mask = 0;
 
 	spin_lock_irqsave(&lp->lock, flags);
 
 	orig_state = lp->chan_state;
-	hv_err = sun4v_ldc_tx_get_state(lp->id,
-					&lp->tx_head,
-					&lp->tx_tail,
-					&lp->chan_state);
+
+	/* We should probably check for hypervisor errors here and
+	 * reset the LDC channel if we get one.
+	 */
+	sun4v_ldc_tx_get_state(lp->id,
+			       &lp->tx_head,
+			       &lp->tx_tail,
+			       &lp->chan_state);
 
 	ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
 	       orig_state, lp->chan_state, lp->tx_head, lp->tx_tail);
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index fdab7f8..2969f77 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -30,6 +30,7 @@ struct amba_apb_device leon_percpu_timer_dev[16];
 int leondebug_irq_disable;
 int leon_debug_irqout;
 static int dummy_master_l10_counter;
+unsigned long amba_system_id;
 
 unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
 unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
@@ -117,10 +118,16 @@ void __init leon_init_timers(irq_handler_t counter_fn)
 	master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
 	dummy_master_l10_counter = 0;
 
-	/*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/
 	rootnp = of_find_node_by_path("/ambapp0");
 	if (!rootnp)
 		goto bad;
+
+	/* Find System ID: GRLIB build ID and optional CHIP ID */
+	pp = of_find_property(rootnp, "systemid", &len);
+	if (pp)
+		amba_system_id = *(unsigned long *)pp->value;
+
+	/* Find IRQMP IRQ Controller Registers base adr otherwise bail out */
 	np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
 	if (!np) {
 		np = of_find_node_by_name(rootnp, "01_00d");
@@ -340,7 +347,7 @@ void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
 
 void __init leon_init_IRQ(void)
 {
-	sparc_init_timers = leon_init_timers;
+	sparc_irq_config.init_timers = leon_init_timers;
 
 	BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/leon_pmc.c b/arch/sparc/kernel/leon_pmc.c
new file mode 100644
index 0000000..519ca92
--- /dev/null
+++ b/arch/sparc/kernel/leon_pmc.c
@@ -0,0 +1,82 @@
+/* leon_pmc.c: LEON Power-down cpu_idle() handler
+ *
+ * Copyright (C) 2011 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
+ */
+
+#include <linux/init.h>
+#include <linux/pm.h>
+
+#include <asm/leon_amba.h>
+#include <asm/leon.h>
+
+/* List of Systems that need fixup instructions around power-down instruction */
+unsigned int pmc_leon_fixup_ids[] = {
+	AEROFLEX_UT699,
+	GAISLER_GR712RC,
+	LEON4_NEXTREME1,
+	0
+};
+
+int pmc_leon_need_fixup(void)
+{
+	unsigned int systemid = amba_system_id >> 16;
+	unsigned int *id;
+
+	id = &pmc_leon_fixup_ids[0];
+	while (*id != 0) {
+		if (*id == systemid)
+			return 1;
+		id++;
+	}
+
+	return 0;
+}
+
+/*
+ * CPU idle callback function for systems that need some extra handling
+ * See .../arch/sparc/kernel/process.c
+ */
+void pmc_leon_idle_fixup(void)
+{
+	/* Prepare an address to a non-cachable region. APB is always
+	 * none-cachable. One instruction is executed after the Sleep
+	 * instruction, we make sure to read the bus and throw away the
+	 * value by accessing a non-cachable area, also we make sure the
+	 * MMU does not get a TLB miss here by using the MMU BYPASS ASI.
+	 */
+	register unsigned int address = (unsigned int)leon3_irqctrl_regs;
+	__asm__ __volatile__ (
+		"mov	%%g0, %%asr19\n"
+		"lda	[%0] %1, %%g0\n"
+		:
+		: "r"(address), "i"(ASI_LEON_BYPASS));
+}
+
+/*
+ * CPU idle callback function
+ * See .../arch/sparc/kernel/process.c
+ */
+void pmc_leon_idle(void)
+{
+	/* For systems without power-down, this will be no-op */
+	__asm__ __volatile__ ("mov	%g0, %asr19\n\t");
+}
+
+/* Install LEON Power Down function */
+static int __init leon_pmc_install(void)
+{
+	/* Assign power management IDLE handler */
+	if (pmc_leon_need_fixup())
+		pm_idle = pmc_leon_idle_fixup;
+	else
+		pm_idle = pmc_leon_idle;
+
+	printk(KERN_INFO "leon: power management initialized\n");
+
+	return 0;
+}
+
+/* This driver is not critical to the boot process, don't care
+ * if initialized late.
+ */
+late_initcall(leon_pmc_install);
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 16582d8..8f5de4a 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -41,6 +41,8 @@
 #include <asm/leon.h>
 #include <asm/leon_amba.h>
 
+#include "kernel.h"
+
 #ifdef CONFIG_SPARC_LEON
 
 #include "irq.h"
@@ -261,23 +263,23 @@ void __init leon_smp_done(void)
 
 	/* Free unneeded trap tables */
 	if (!cpu_isset(1, cpu_present_map)) {
-		ClearPageReserved(virt_to_page(trapbase_cpu1));
-		init_page_count(virt_to_page(trapbase_cpu1));
-		free_page((unsigned long)trapbase_cpu1);
+		ClearPageReserved(virt_to_page(&trapbase_cpu1));
+		init_page_count(virt_to_page(&trapbase_cpu1));
+		free_page((unsigned long)&trapbase_cpu1);
 		totalram_pages++;
 		num_physpages++;
 	}
 	if (!cpu_isset(2, cpu_present_map)) {
-		ClearPageReserved(virt_to_page(trapbase_cpu2));
-		init_page_count(virt_to_page(trapbase_cpu2));
-		free_page((unsigned long)trapbase_cpu2);
+		ClearPageReserved(virt_to_page(&trapbase_cpu2));
+		init_page_count(virt_to_page(&trapbase_cpu2));
+		free_page((unsigned long)&trapbase_cpu2);
 		totalram_pages++;
 		num_physpages++;
 	}
 	if (!cpu_isset(3, cpu_present_map)) {
-		ClearPageReserved(virt_to_page(trapbase_cpu3));
-		init_page_count(virt_to_page(trapbase_cpu3));
-		free_page((unsigned long)trapbase_cpu3);
+		ClearPageReserved(virt_to_page(&trapbase_cpu3));
+		init_page_count(virt_to_page(&trapbase_cpu3));
+		free_page((unsigned long)&trapbase_cpu3);
 		totalram_pages++;
 		num_physpages++;
 	}
@@ -437,15 +439,6 @@ void __init leon_blackbox_current(unsigned *addr)
 
 }
 
-/*
- * CPU idle callback function
- * See .../arch/sparc/kernel/process.c
- */
-void pmc_leon_idle(void)
-{
-	__asm__ volatile ("mov %g0, %asr19");
-}
-
 void __init leon_init_smp(void)
 {
 	/* Patch ipi15 trap table */
@@ -456,13 +449,6 @@ void __init leon_init_smp(void)
 	BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
 			BTFIXUPCALL_NORM);
-
-#ifndef PMC_NO_IDLE
-	/* Assign power management IDLE handler */
-	pm_idle = pmc_leon_idle;
-	printk(KERN_INFO "leon: power management initialized\n");
-#endif
-
 }
 
 #endif /* CONFIG_SPARC_LEON */
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 2d055a1..a312af4 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -13,6 +13,7 @@
 #include <asm/leon_amba.h>
 
 #include "of_device_common.h"
+#include "irq.h"
 
 /*
  * PCI bus specific translator
@@ -355,7 +356,8 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
 	if (intr) {
 		op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
 		for (i = 0; i < op->archdata.num_irqs; i++)
-			op->archdata.irqs[i] = intr[i].pri;
+			op->archdata.irqs[i] =
+			    sparc_irq_config.build_device_irq(op, intr[i].pri);
 	} else {
 		const unsigned int *irq =
 			of_get_property(dp, "interrupts", &len);
@@ -363,64 +365,13 @@ static struct platform_device * __init scan_one_device(struct device_node *dp,
 		if (irq) {
 			op->archdata.num_irqs = len / sizeof(unsigned int);
 			for (i = 0; i < op->archdata.num_irqs; i++)
-				op->archdata.irqs[i] = irq[i];
+				op->archdata.irqs[i] =
+				    sparc_irq_config.build_device_irq(op, irq[i]);
 		} else {
 			op->archdata.num_irqs = 0;
 		}
 	}
-	if (sparc_cpu_model == sun4d) {
-		static int pil_to_sbus[] = {
-			0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
-		};
-		struct device_node *io_unit, *sbi = dp->parent;
-		const struct linux_prom_registers *regs;
-		int board, slot;
-
-		while (sbi) {
-			if (!strcmp(sbi->name, "sbi"))
-				break;
-
-			sbi = sbi->parent;
-		}
-		if (!sbi)
-			goto build_resources;
-
-		regs = of_get_property(dp, "reg", NULL);
-		if (!regs)
-			goto build_resources;
-
-		slot = regs->which_io;
-
-		/* If SBI's parent is not io-unit or the io-unit lacks
-		 * a "board#" property, something is very wrong.
-		 */
-		if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
-			printk("%s: Error, parent is not io-unit.\n",
-			       sbi->full_name);
-			goto build_resources;
-		}
-		io_unit = sbi->parent;
-		board = of_getintprop_default(io_unit, "board#", -1);
-		if (board == -1) {
-			printk("%s: Error, lacks board# property.\n",
-			       io_unit->full_name);
-			goto build_resources;
-		}
-
-		for (i = 0; i < op->archdata.num_irqs; i++) {
-			int this_irq = op->archdata.irqs[i];
-			int sbusl = pil_to_sbus[this_irq];
-
-			if (sbusl)
-				this_irq = (((board + 1) << 5) +
-					    (sbusl << 2) +
-					    slot);
-
-			op->archdata.irqs[i] = this_irq;
-		}
-	}
 
-build_resources:
 	build_device_resources(op, parent);
 
 	op->dev.parent = parent;
diff --git a/arch/sparc/kernel/of_device_common.c b/arch/sparc/kernel/of_device_common.c
index 49ddff5..cb15bbf 100644
--- a/arch/sparc/kernel/of_device_common.c
+++ b/arch/sparc/kernel/of_device_common.c
@@ -22,6 +22,33 @@ unsigned int irq_of_parse_and_map(struct device_node *node, int index)
 }
 EXPORT_SYMBOL(irq_of_parse_and_map);
 
+int of_address_to_resource(struct device_node *node, int index,
+			   struct resource *r)
+{
+	struct platform_device *op = of_find_device_by_node(node);
+
+	if (!op || index >= op->num_resources)
+		return -EINVAL;
+
+	memcpy(r, &op->archdata.resource[index], sizeof(*r));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_address_to_resource);
+
+void __iomem *of_iomap(struct device_node *node, int index)
+{
+	struct platform_device *op = of_find_device_by_node(node);
+	struct resource *r;
+
+	if (!op || index >= op->num_resources)
+		return NULL;
+
+	r = &op->archdata.resource[index];
+
+	return of_ioremap(r, 0, resource_size(r), (char *) r->name);
+}
+EXPORT_SYMBOL(of_iomap);
+
 /* Take the archdata values for IOMMU, STC, and HOSTDATA found in
  * BUS and propagate to all child platform_device objects.
  */
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 4137579..44f41e3 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -675,6 +675,7 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
 		 * humanoid.
 		 */
 		err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr);
+		(void) err;
 	}
 	list_for_each_entry(child_bus, &bus->children, node)
 		pci_bus_register_of_sysfs(child_bus);
@@ -1001,22 +1002,22 @@ EXPORT_SYMBOL(pci_domain_nr);
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
-	unsigned int virt_irq;
+	unsigned int irq;
 
 	if (!pbm->setup_msi_irq)
 		return -EINVAL;
 
-	return pbm->setup_msi_irq(&virt_irq, pdev, desc);
+	return pbm->setup_msi_irq(&irq, pdev, desc);
 }
 
-void arch_teardown_msi_irq(unsigned int virt_irq)
+void arch_teardown_msi_irq(unsigned int irq)
 {
-	struct msi_desc *entry = get_irq_msi(virt_irq);
+	struct msi_desc *entry = get_irq_msi(irq);
 	struct pci_dev *pdev = entry->dev;
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
 
 	if (pbm->teardown_msi_irq)
-		pbm->teardown_msi_irq(virt_irq, pdev);
+		pbm->teardown_msi_irq(irq, pdev);
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c
index 6c7a33a..6e3874b 100644
--- a/arch/sparc/kernel/pci_common.c
+++ b/arch/sparc/kernel/pci_common.c
@@ -295,14 +295,17 @@ static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 	unsigned int bus = bus_dev->number;
 	unsigned int device = PCI_SLOT(devfn);
 	unsigned int func = PCI_FUNC(devfn);
-	unsigned long ret;
 
 	if (config_out_of_range(pbm, bus, devfn, where)) {
 		/* Do nothing. */
 	} else {
-		ret = pci_sun4v_config_put(devhandle,
-				HV_PCI_DEVICE_BUILD(bus, device, func),
-				where, size, value);
+		/* We don't check for hypervisor errors here, but perhaps
+		 * we should and influence our return value depending upon
+		 * what kind of error is thrown.
+		 */
+		pci_sun4v_config_put(devhandle,
+				     HV_PCI_DEVICE_BUILD(bus, device, func),
+				     where, size, value);
 	}
 	return PCIBIOS_SUCCESSFUL;
 }
diff --git a/arch/sparc/kernel/pci_fire.c b/arch/sparc/kernel/pci_fire.c
index efb896d..3d70f83 100644
--- a/arch/sparc/kernel/pci_fire.c
+++ b/arch/sparc/kernel/pci_fire.c
@@ -214,11 +214,9 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid,
 
 static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi)
 {
-	unsigned long msiqid;
 	u64 val;
 
 	val = upa_readq(pbm->pbm_regs + MSI_MAP(msi));
-	msiqid = (val & MSI_MAP_EQNUM);
 
 	val &= ~MSI_MAP_VALID;
 
@@ -277,7 +275,7 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm,
 {
 	unsigned long cregs = (unsigned long) pbm->pbm_regs;
 	unsigned long imap_reg, iclr_reg, int_ctrlr;
-	unsigned int virt_irq;
+	unsigned int irq;
 	int fixup;
 	u64 val;
 
@@ -293,14 +291,14 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm,
 
 	fixup = ((pbm->portid << 6) | devino) - int_ctrlr;
 
-	virt_irq = build_irq(fixup, iclr_reg, imap_reg);
-	if (!virt_irq)
+	irq = build_irq(fixup, iclr_reg, imap_reg);
+	if (!irq)
 		return -ENOMEM;
 
 	upa_writeq(EVENT_QUEUE_CONTROL_SET_EN,
 		   pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid));
 
-	return virt_irq;
+	return irq;
 }
 
 static const struct sparc64_msiq_ops pci_fire_msiq_ops = {
@@ -455,8 +453,7 @@ static int __devinit pci_fire_pbm_init(struct pci_pbm_info *pbm,
 	return 0;
 }
 
-static int __devinit fire_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit fire_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct pci_pbm_info *pbm;
@@ -507,7 +504,7 @@ static struct of_device_id __initdata fire_match[] = {
 	{},
 };
 
-static struct of_platform_driver fire_driver = {
+static struct platform_driver fire_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -518,7 +515,7 @@ static struct of_platform_driver fire_driver = {
 
 static int __init fire_init(void)
 {
-	return of_register_platform_driver(&fire_driver);
+	return platform_driver_register(&fire_driver);
 }
 
 subsys_initcall(fire_init);
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h
index e20ed5f..6beb60d 100644
--- a/arch/sparc/kernel/pci_impl.h
+++ b/arch/sparc/kernel/pci_impl.h
@@ -131,9 +131,9 @@ struct pci_pbm_info {
 	void				*msi_queues;
 	unsigned long			*msi_bitmap;
 	unsigned int			*msi_irq_table;
-	int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
+	int (*setup_msi_irq)(unsigned int *irq_p, struct pci_dev *pdev,
 			     struct msi_desc *entry);
-	void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
+	void (*teardown_msi_irq)(unsigned int irq, struct pci_dev *pdev);
 	const struct sparc64_msiq_ops	*msi_ops;
 #endif /* !(CONFIG_PCI_MSI) */
 
diff --git a/arch/sparc/kernel/pci_msi.c b/arch/sparc/kernel/pci_msi.c
index b210416..550e937 100644
--- a/arch/sparc/kernel/pci_msi.c
+++ b/arch/sparc/kernel/pci_msi.c
@@ -31,12 +31,12 @@ static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie)
 		err = ops->dequeue_msi(pbm, msiqid, &head, &msi);
 		if (likely(err > 0)) {
 			struct irq_desc *desc;
-			unsigned int virt_irq;
+			unsigned int irq;
 
-			virt_irq = pbm->msi_irq_table[msi - pbm->msi_first];
-			desc = irq_desc + virt_irq;
+			irq = pbm->msi_irq_table[msi - pbm->msi_first];
+			desc = irq_desc + irq;
 
-			desc->handle_irq(virt_irq, desc);
+			desc->handle_irq(irq, desc);
 		}
 
 		if (unlikely(err < 0))
@@ -121,7 +121,7 @@ static struct irq_chip msi_irq = {
 	/* XXX affinity XXX */
 };
 
-static int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
+static int sparc64_setup_msi_irq(unsigned int *irq_p,
 				 struct pci_dev *pdev,
 				 struct msi_desc *entry)
 {
@@ -131,17 +131,17 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
 	int msi, err;
 	u32 msiqid;
 
-	*virt_irq_p = virt_irq_alloc(0, 0);
+	*irq_p = irq_alloc(0, 0);
 	err = -ENOMEM;
-	if (!*virt_irq_p)
+	if (!*irq_p)
 		goto out_err;
 
-	set_irq_chip_and_handler_name(*virt_irq_p, &msi_irq,
+	set_irq_chip_and_handler_name(*irq_p, &msi_irq,
 				      handle_simple_irq, "MSI");
 
 	err = alloc_msi(pbm);
 	if (unlikely(err < 0))
-		goto out_virt_irq_free;
+		goto out_irq_free;
 
 	msi = err;
 
@@ -152,7 +152,7 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
 	if (err)
 		goto out_msi_free;
 
-	pbm->msi_irq_table[msi - pbm->msi_first] = *virt_irq_p;
+	pbm->msi_irq_table[msi - pbm->msi_first] = *irq_p;
 
 	if (entry->msi_attrib.is_64) {
 		msg.address_hi = pbm->msi64_start >> 32;
@@ -163,24 +163,24 @@ static int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
 	}
 	msg.data = msi;
 
-	set_irq_msi(*virt_irq_p, entry);
-	write_msi_msg(*virt_irq_p, &msg);
+	set_irq_msi(*irq_p, entry);
+	write_msi_msg(*irq_p, &msg);
 
 	return 0;
 
 out_msi_free:
 	free_msi(pbm, msi);
 
-out_virt_irq_free:
-	set_irq_chip(*virt_irq_p, NULL);
-	virt_irq_free(*virt_irq_p);
-	*virt_irq_p = 0;
+out_irq_free:
+	set_irq_chip(*irq_p, NULL);
+	irq_free(*irq_p);
+	*irq_p = 0;
 
 out_err:
 	return err;
 }
 
-static void sparc64_teardown_msi_irq(unsigned int virt_irq,
+static void sparc64_teardown_msi_irq(unsigned int irq,
 				     struct pci_dev *pdev)
 {
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
@@ -189,12 +189,12 @@ static void sparc64_teardown_msi_irq(unsigned int virt_irq,
 	int i, err;
 
 	for (i = 0; i < pbm->msi_num; i++) {
-		if (pbm->msi_irq_table[i] == virt_irq)
+		if (pbm->msi_irq_table[i] == irq)
 			break;
 	}
 	if (i >= pbm->msi_num) {
 		printk(KERN_ERR "%s: teardown: No MSI for irq %u\n",
-		       pbm->name, virt_irq);
+		       pbm->name, irq);
 		return;
 	}
 
@@ -205,14 +205,14 @@ static void sparc64_teardown_msi_irq(unsigned int virt_irq,
 	if (err) {
 		printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, "
 		       "irq %u, gives error %d\n",
-		       pbm->name, msi_num, virt_irq, err);
+		       pbm->name, msi_num, irq, err);
 		return;
 	}
 
 	free_msi(pbm, msi_num);
 
-	set_irq_chip(virt_irq, NULL);
-	virt_irq_free(virt_irq);
+	set_irq_chip(irq, NULL);
+	irq_free(irq);
 }
 
 static int msi_bitmap_alloc(struct pci_pbm_info *pbm)
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c
index 22eab7c..56ee745 100644
--- a/arch/sparc/kernel/pci_psycho.c
+++ b/arch/sparc/kernel/pci_psycho.c
@@ -503,8 +503,7 @@ static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid)
 
 #define PSYCHO_CONFIGSPACE	0x001000000UL
 
-static int __devinit psycho_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit psycho_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *pr_regs;
 	struct device_node *dp = op->dev.of_node;
@@ -601,7 +600,7 @@ static struct of_device_id __initdata psycho_match[] = {
 	{},
 };
 
-static struct of_platform_driver psycho_driver = {
+static struct platform_driver psycho_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -612,7 +611,7 @@ static struct of_platform_driver psycho_driver = {
 
 static int __init psycho_init(void)
 {
-	return of_register_platform_driver(&psycho_driver);
+	return platform_driver_register(&psycho_driver);
 }
 
 subsys_initcall(psycho_init);
diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c
index 5c3f5ec..2857073 100644
--- a/arch/sparc/kernel/pci_sabre.c
+++ b/arch/sparc/kernel/pci_sabre.c
@@ -452,8 +452,7 @@ static void __devinit sabre_pbm_init(struct pci_pbm_info *pbm,
 	sabre_scan_bus(pbm, &op->dev);
 }
 
-static int __devinit sabre_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit sabre_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *pr_regs;
 	struct device_node *dp = op->dev.of_node;
@@ -464,7 +463,7 @@ static int __devinit sabre_probe(struct platform_device *op,
 	const u32 *vdma;
 	u64 clear_irq;
 
-	hummingbird_p = (match->data != NULL);
+	hummingbird_p = op->dev.of_match && (op->dev.of_match->data != NULL);
 	if (!hummingbird_p) {
 		struct device_node *cpu_dp;
 
@@ -595,7 +594,7 @@ static struct of_device_id __initdata sabre_match[] = {
 	{},
 };
 
-static struct of_platform_driver sabre_driver = {
+static struct platform_driver sabre_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -606,7 +605,7 @@ static struct of_platform_driver sabre_driver = {
 
 static int __init sabre_init(void)
 {
-	return of_register_platform_driver(&sabre_driver);
+	return platform_driver_register(&sabre_driver);
 }
 
 subsys_initcall(sabre_init);
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c
index 445a47a..1d41af7 100644
--- a/arch/sparc/kernel/pci_schizo.c
+++ b/arch/sparc/kernel/pci_schizo.c
@@ -1313,7 +1313,7 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
 	const struct linux_prom64_registers *regs;
 	struct device_node *dp = op->dev.of_node;
 	const char *chipset_name;
-	int is_pbm_a, err;
+	int err;
 
 	switch (chip_type) {
 	case PBM_CHIP_TYPE_TOMATILLO:
@@ -1343,8 +1343,6 @@ static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm,
 	 */
 	regs = of_get_property(dp, "reg", NULL);
 
-	is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
-
 	pbm->next = pci_pbm_root;
 	pci_pbm_root = pbm;
 
@@ -1460,10 +1458,11 @@ out_err:
 	return err;
 }
 
-static int __devinit schizo_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit schizo_probe(struct platform_device *op)
 {
-	return __schizo_init(op, (unsigned long) match->data);
+	if (!op->dev.of_match)
+		return -EINVAL;
+	return __schizo_init(op, (unsigned long) op->dev.of_match->data);
 }
 
 /* The ordering of this table is very important.  Some Tomatillo
@@ -1490,7 +1489,7 @@ static struct of_device_id __initdata schizo_match[] = {
 	{},
 };
 
-static struct of_platform_driver schizo_driver = {
+static struct platform_driver schizo_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1501,7 +1500,7 @@ static struct of_platform_driver schizo_driver = {
 
 static int __init schizo_init(void)
 {
-	return of_register_platform_driver(&schizo_driver);
+	return platform_driver_register(&schizo_driver);
 }
 
 subsys_initcall(schizo_init);
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 743344a..6cf5346 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -580,7 +580,7 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 {
 	static const u32 vdma_default[] = { 0x80000000, 0x80000000 };
 	struct iommu *iommu = pbm->iommu;
-	unsigned long num_tsb_entries, sz, tsbsize;
+	unsigned long num_tsb_entries, sz;
 	u32 dma_mask, dma_offset;
 	const u32 *vdma;
 
@@ -596,7 +596,6 @@ static int __devinit pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 
 	dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
 	num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
-	tsbsize = num_tsb_entries * sizeof(iopte_t);
 
 	dma_offset = vdma[0];
 
@@ -844,9 +843,9 @@ static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm,
 				    unsigned long msiqid,
 				    unsigned long devino)
 {
-	unsigned int virt_irq = sun4v_build_irq(pbm->devhandle, devino);
+	unsigned int irq = sun4v_build_irq(pbm->devhandle, devino);
 
-	if (!virt_irq)
+	if (!irq)
 		return -ENOMEM;
 
 	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
@@ -854,7 +853,7 @@ static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm,
 	if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
 		return -EINVAL;
 
-	return virt_irq;
+	return irq;
 }
 
 static const struct sparc64_msiq_ops pci_sun4v_msiq_ops = {
@@ -918,8 +917,7 @@ static int __devinit pci_sun4v_pbm_init(struct pci_pbm_info *pbm,
 	return 0;
 }
 
-static int __devinit pci_sun4v_probe(struct platform_device *op,
-				     const struct of_device_id *match)
+static int __devinit pci_sun4v_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *regs;
 	static int hvapi_negotiated = 0;
@@ -1008,7 +1006,7 @@ static struct of_device_id __initdata pci_sun4v_match[] = {
 	{},
 };
 
-static struct of_platform_driver pci_sun4v_driver = {
+static struct platform_driver pci_sun4v_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1019,7 +1017,7 @@ static struct of_platform_driver pci_sun4v_driver = {
 
 static int __init pci_sun4v_init(void)
 {
-	return of_register_platform_driver(&pci_sun4v_driver);
+	return platform_driver_register(&pci_sun4v_driver);
 }
 
 subsys_initcall(pci_sun4v_init);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index aeaa09a..2cdc131 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -700,10 +700,8 @@ static void pcic_clear_clock_irq(void)
 
 static irqreturn_t pcic_timer_handler (int irq, void *h)
 {
-	write_seqlock(&xtime_lock);	/* Dummy, to show that we remember */
 	pcic_clear_clock_irq();
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
 #endif
diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c
index 7c2ced6..8ac23e6 100644
--- a/arch/sparc/kernel/pcr.c
+++ b/arch/sparc/kernel/pcr.c
@@ -81,7 +81,7 @@ static void n2_pcr_write(u64 val)
 	unsigned long ret;
 
 	ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-	if (val != HV_EOK)
+	if (ret != HV_EOK)
 		write_pcr(val);
 }
 
diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c
index 94536a8..93d7b44 100644
--- a/arch/sparc/kernel/pmc.c
+++ b/arch/sparc/kernel/pmc.c
@@ -51,8 +51,7 @@ static void pmc_swift_idle(void)
 #endif
 }
 
-static int __devinit pmc_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit pmc_probe(struct platform_device *op)
 {
 	regs = of_ioremap(&op->resource[0], 0,
 			  resource_size(&op->resource[0]), PMC_OBPNAME);
@@ -78,7 +77,7 @@ static struct of_device_id __initdata pmc_match[] = {
 };
 MODULE_DEVICE_TABLE(of, pmc_match);
 
-static struct of_platform_driver pmc_driver = {
+static struct platform_driver pmc_driver = {
 	.driver = {
 		.name = "pmc",
 		.owner = THIS_MODULE,
@@ -89,7 +88,7 @@ static struct of_platform_driver pmc_driver = {
 
 static int __init pmc_init(void)
 {
-	return of_register_platform_driver(&pmc_driver);
+	return platform_driver_register(&pmc_driver);
 }
 
 /* This driver is not critical to the boot process
diff --git a/arch/sparc/kernel/power.c b/arch/sparc/kernel/power.c
index 2c59f4d..cd725fe 100644
--- a/arch/sparc/kernel/power.c
+++ b/arch/sparc/kernel/power.c
@@ -33,7 +33,7 @@ static int __devinit has_button_interrupt(unsigned int irq, struct device_node *
 	return 1;
 }
 
-static int __devinit power_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit power_probe(struct platform_device *op)
 {
 	struct resource *res = &op->resource[0];
 	unsigned int irq = op->archdata.irqs[0];
@@ -59,7 +59,7 @@ static struct of_device_id __initdata power_match[] = {
 	{},
 };
 
-static struct of_platform_driver power_driver = {
+static struct platform_driver power_driver = {
 	.probe		= power_probe,
 	.driver = {
 		.name = "power",
@@ -70,7 +70,7 @@ static struct of_platform_driver power_driver = {
 
 static int __init power_init(void)
 {
-	return of_register_platform_driver(&power_driver);
+	return platform_driver_register(&power_driver);
 }
 
 device_initcall(power_init);
diff --git a/arch/sparc/kernel/prom_irqtrans.c b/arch/sparc/kernel/prom_irqtrans.c
index ce65114..570b98f 100644
--- a/arch/sparc/kernel/prom_irqtrans.c
+++ b/arch/sparc/kernel/prom_irqtrans.c
@@ -227,7 +227,7 @@ static unsigned int sabre_irq_build(struct device_node *dp,
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
 	int inofixup = 0;
-	int virt_irq;
+	int irq;
 
 	ino &= 0x3f;
 	if (ino < SABRE_ONBOARD_IRQ_BASE) {
@@ -247,7 +247,7 @@ static unsigned int sabre_irq_build(struct device_node *dp,
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
 
-	virt_irq = build_irq(inofixup, iclr, imap);
+	irq = build_irq(inofixup, iclr, imap);
 
 	/* If the parent device is a PCI<->PCI bridge other than
 	 * APB, we have to install a pre-handler to ensure that
@@ -256,13 +256,13 @@ static unsigned int sabre_irq_build(struct device_node *dp,
 	 */
 	regs = of_get_property(dp, "reg", NULL);
 	if (regs && sabre_device_needs_wsync(dp)) {
-		irq_install_pre_handler(virt_irq,
+		irq_install_pre_handler(irq,
 					sabre_wsync_handler,
 					(void *) (long) regs->phys_hi,
 					(void *) irq_data);
 	}
 
-	return virt_irq;
+	return irq;
 }
 
 static void __init sabre_irq_trans_init(struct device_node *dp)
@@ -382,7 +382,7 @@ static unsigned int schizo_irq_build(struct device_node *dp,
 	unsigned long pbm_regs = irq_data->pbm_regs;
 	unsigned long imap, iclr;
 	int ign_fixup;
-	int virt_irq;
+	int irq;
 	int is_tomatillo;
 
 	ino &= 0x3f;
@@ -409,17 +409,17 @@ static unsigned int schizo_irq_build(struct device_node *dp,
 			ign_fixup = (1 << 6);
 	}
 
-	virt_irq = build_irq(ign_fixup, iclr, imap);
+	irq = build_irq(ign_fixup, iclr, imap);
 
 	if (is_tomatillo) {
-		irq_install_pre_handler(virt_irq,
+		irq_install_pre_handler(irq,
 					tomatillo_wsync_handler,
 					((irq_data->chip_version <= 4) ?
 					 (void *) 1 : (void *) 0),
 					(void *) irq_data->sync_reg);
 	}
 
-	return virt_irq;
+	return irq;
 }
 
 static void __init __schizo_irq_trans_init(struct device_node *dp,
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 9ccc812..96ee50a 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -1086,6 +1086,7 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
+#ifdef CONFIG_AUDITSYSCALL
 	if (unlikely(current->audit_context)) {
 		unsigned long tstate = regs->tstate;
 		int result = AUDITSC_SUCCESS;
@@ -1095,7 +1096,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 
 		audit_syscall_exit(result, regs->u_regs[UREG_I0]);
 	}
-
+#endif
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_exit(regs, regs->u_regs[UREG_G1]);
 
diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c
index 648f216..7b8b76c 100644
--- a/arch/sparc/kernel/setup_32.c
+++ b/arch/sparc/kernel/setup_32.c
@@ -184,7 +184,6 @@ static void __init boot_flags_init(char *commands)
  */
 
 extern void sun4c_probe_vac(void);
-extern char cputypval;
 
 extern unsigned short root_flags;
 extern unsigned short root_dev;
@@ -218,21 +217,21 @@ void __init setup_arch(char **cmdline_p)
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
-	if (!strcmp(&cputypval,"sun4 "))
+	if (!strcmp(&cputypval[0], "sun4 "))
 		sparc_cpu_model = sun4;
-	if (!strcmp(&cputypval,"sun4c"))
+	if (!strcmp(&cputypval[0], "sun4c"))
 		sparc_cpu_model = sun4c;
-	if (!strcmp(&cputypval,"sun4m"))
+	if (!strcmp(&cputypval[0], "sun4m"))
 		sparc_cpu_model = sun4m;
-	if (!strcmp(&cputypval,"sun4s"))
+	if (!strcmp(&cputypval[0], "sun4s"))
 		sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
-	if (!strcmp(&cputypval,"sun4d"))
+	if (!strcmp(&cputypval[0], "sun4d"))
 		sparc_cpu_model = sun4d;
-	if (!strcmp(&cputypval,"sun4e"))
+	if (!strcmp(&cputypval[0], "sun4e"))
 		sparc_cpu_model = sun4e;
-	if (!strcmp(&cputypval,"sun4u"))
+	if (!strcmp(&cputypval[0], "sun4u"))
 		sparc_cpu_model = sun4u;
-	if (!strncmp(&cputypval, "leon" , 4))
+	if (!strncmp(&cputypval[0], "leon" , 4))
 		sparc_cpu_model = sparc_leon;
 
 	printk("ARCH: ");
@@ -335,7 +334,7 @@ static int show_cpuinfo(struct seq_file *m, void *__unused)
 		   prom_rev,
 		   romvec->pv_printrev >> 16,
 		   romvec->pv_printrev & 0xffff,
-		   &cputypval,
+		   &cputypval[0],
 		   ncpus_probed,
 		   num_online_cpus()
 #ifndef CONFIG_SMP
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 555a76d..3e94a8c 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -189,7 +189,7 @@ static inline long get_delta (long *rt, long *master)
 void smp_synchronize_tick_client(void)
 {
 	long i, delta, adj, adjust_latency = 0, done = 0;
-	unsigned long flags, rt, master_time_stamp, bound;
+	unsigned long flags, rt, master_time_stamp;
 #if DEBUG_TICK_SYNC
 	struct {
 		long rt;	/* roundtrip time */
@@ -208,10 +208,8 @@ void smp_synchronize_tick_client(void)
 	{
 		for (i = 0; i < NUM_ROUNDS; i++) {
 			delta = get_delta(&rt, &master_time_stamp);
-			if (delta == 0) {
+			if (delta == 0)
 				done = 1;	/* let's lock on to this... */
-				bound = rt;
-			}
 
 			if (!done) {
 				if (i > 0) {
@@ -933,13 +931,12 @@ void smp_flush_dcache_page_impl(struct page *page, int cpu)
 void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 {
 	void *pg_addr;
-	int this_cpu;
 	u64 data0;
 
 	if (tlb_type == hypervisor)
 		return;
 
-	this_cpu = get_cpu();
+	preempt_disable();
 
 #ifdef CONFIG_DEBUG_DCFLUSH
 	atomic_inc(&dcpage_flushes);
@@ -964,7 +961,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 	}
 	__local_flush_dcache_page(page);
 
-	put_cpu();
+	preempt_enable();
 }
 
 void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index 892fb88..90eea38 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -1,5 +1,5 @@
-/*  sun4c_irq.c
- *  arch/sparc/kernel/sun4c_irq.c:
+/*
+ * sun4c irq support
  *
  *  djhr: Hacked out of irq.c into a CPU dependent version.
  *
@@ -9,31 +9,41 @@
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
-#include <linux/errno.h>
-#include <linux/linkage.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include "irq.h"
 
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/vaddrs.h>
-#include <asm/timer.h>
-#include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/traps.h>
+#include <asm/timer.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
+
+#include "irq.h"
+
+/* Sun4c interrupts are typically laid out as follows:
+ *
+ *  1 - Software interrupt, SBUS level 1
+ *  2 - SBUS level 2
+ *  3 - ESP SCSI, SBUS level 3
+ *  4 - Software interrupt
+ *  5 - Lance ethernet, SBUS level 4
+ *  6 - Software interrupt
+ *  7 - Graphics card, SBUS level 5
+ *  8 - SBUS level 6
+ *  9 - SBUS level 7
+ * 10 - Counter timer
+ * 11 - Floppy
+ * 12 - Zilog uart
+ * 13 - CS4231 audio
+ * 14 - Profiling timer
+ * 15 - NMI
+ *
+ * The interrupt enable bits in the interrupt mask register are
+ * really only used to enable/disable the timer interrupts, and
+ * for signalling software interrupts.  There is also a master
+ * interrupt enable bit in this register.
+ *
+ * Interrupts are enabled by setting the SUN4C_INT_* bits, they
+ * are disabled by clearing those bits.
+ */
 
 /*
  * Bit field defines for the interrupt registers on various
@@ -49,26 +59,21 @@
 #define SUN4C_INT_E4      0x04     /* Enable level 4 IRQ. */
 #define SUN4C_INT_E1      0x02     /* Enable level 1 IRQ. */
 
-/* Pointer to the interrupt enable byte
- *
- * Dave Redman (djhr@tadpole.co.uk)
- * What you may not be aware of is that entry.S requires this variable.
- *
- *  --- linux_trap_nmi_sun4c --
- *
- * so don't go making it static, like I tried. sigh.
+/*
+ * Pointer to the interrupt enable byte
+ * Used by entry.S
  */
-unsigned char __iomem *interrupt_enable = NULL;
+unsigned char __iomem *interrupt_enable;
 
 static void sun4c_disable_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
 	unsigned char current_mask, new_mask;
-    
+
 	local_irq_save(flags);
 	irq_nr &= (NR_IRQS - 1);
 	current_mask = sbus_readb(interrupt_enable);
-	switch(irq_nr) {
+	switch (irq_nr) {
 	case 1:
 		new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
 		break;
@@ -93,11 +98,11 @@ static void sun4c_enable_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
 	unsigned char current_mask, new_mask;
-    
+
 	local_irq_save(flags);
 	irq_nr &= (NR_IRQS - 1);
 	current_mask = sbus_readb(interrupt_enable);
-	switch(irq_nr) {
+	switch (irq_nr) {
 	case 1:
 		new_mask = ((current_mask) | SUN4C_INT_E1);
 		break;
@@ -180,12 +185,14 @@ static void __init sun4c_init_timers(irq_handler_t counter_fn)
 		prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
 		prom_halt();
 	}
-    
+
 	sun4c_disable_irq(irq[1].pri);
 }
 
 #ifdef CONFIG_SMP
-static void sun4c_nop(void) {}
+static void sun4c_nop(void)
+{
+}
 #endif
 
 void __init sun4c_init_IRQ(void)
@@ -214,7 +221,9 @@ void __init sun4c_init_IRQ(void)
 	BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
-	sparc_init_timers = sun4c_init_timers;
+
+	sparc_irq_config.init_timers = sun4c_init_timers;
+
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index e11b461..77b4a89 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -1,50 +1,42 @@
 /*
- *  arch/sparc/kernel/sun4d_irq.c:
- *			SS1000/SC2000 interrupt handling.
+ * SS1000/SC2000 interrupt handling.
  *
  *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *  Heavily based on arch/sparc/kernel/irq.c.
  */
 
-#include <linux/errno.h>
-#include <linux/linkage.h>
 #include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
 #include <linux/seq_file.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/smp.h>
-#include <asm/vaddrs.h>
+
 #include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
 #include <asm/sbi.h>
 #include <asm/cacheflush.h>
-#include <asm/irq_regs.h>
 
 #include "kernel.h"
 #include "irq.h"
 
-/* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */
-/* #define DISTRIBUTE_IRQS */
+/* Sun4d interrupts fall roughly into two categories.  SBUS and
+ * cpu local.  CPU local interrupts cover the timer interrupts
+ * and whatnot, and we encode those as normal PILs between
+ * 0 and 15.
+ *
+ * SBUS interrupts are encoded integers including the board number
+ * (plus one), the SBUS level, and the SBUS slot number.  Sun4D
+ * IRQ dispatch is done by:
+ *
+ * 1) Reading the BW local interrupt table in order to get the bus
+ *    interrupt mask.
+ *
+ *    This table is indexed by SBUS interrupt level which can be
+ *    derived from the PIL we got interrupted on.
+ *
+ * 2) For each bus showing interrupt pending from #1, read the
+ *    SBI interrupt state register.  This will indicate which slots
+ *    have interrupts pending for that SBUS interrupt level.
+ */
 
 struct sun4d_timer_regs {
 	u32	l10_timer_limit;
@@ -59,11 +51,9 @@ static struct sun4d_timer_regs __iomem *sun4d_timers;
 #define TIMER_IRQ	10
 
 #define MAX_STATIC_ALLOC	4
-extern int static_irq_count;
 static unsigned char sbus_tid[32];
 
 static struct irqaction *irq_action[NR_IRQS];
-extern spinlock_t irq_action_lock;
 
 static struct sbus_action {
 	struct irqaction *action;
@@ -71,11 +61,33 @@ static struct sbus_action {
 } *sbus_actions;
 
 static int pil_to_sbus[] = {
-	0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
+	0,
+	0,
+	1,
+	2,
+	0,
+	3,
+	0,
+	4,
+	0,
+	5,
+	0,
+	6,
+	0,
+	7,
+	0,
+	0,
 };
 
 static int sbus_to_pil[] = {
-	0, 2, 3, 5, 7, 9, 11, 13,
+	0,
+	2,
+	3,
+	5,
+	7,
+	9,
+	11,
+	13,
 };
 
 static int nsbi;
@@ -86,7 +98,7 @@ DEFINE_SPINLOCK(sun4d_imsk_lock);
 int show_sun4d_interrupts(struct seq_file *p, void *v)
 {
 	int i = *(loff_t *) v, j = 0, k = 0, sbusl;
-	struct irqaction * action;
+	struct irqaction *action;
 	unsigned long flags;
 #ifdef CONFIG_SMP
 	int x;
@@ -96,13 +108,14 @@ int show_sun4d_interrupts(struct seq_file *p, void *v)
 	if (i < NR_IRQS) {
 		sbusl = pil_to_sbus[i];
 		if (!sbusl) {
-	 		action = *(i + irq_action);
-			if (!action) 
-		        	goto out_unlock;
+			action = *(i + irq_action);
+			if (!action)
+				goto out_unlock;
 		} else {
 			for (j = 0; j < nsbi; j++) {
 				for (k = 0; k < 4; k++)
-					if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action))
+					action = sbus_actions[(j << 5) + (sbusl << 2) + k].action;
+					if (action)
 						goto found_it;
 			}
 			goto out_unlock;
@@ -125,15 +138,17 @@ found_it:	seq_printf(p, "%3d: ", i);
 					(action->flags & IRQF_DISABLED) ? " +" : "",
 					action->name);
 			}
-			if (!sbusl) break;
+			if (!sbusl)
+				break;
 			k++;
-			if (k < 4)
-				action = sbus_actions [(j << 5) + (sbusl << 2) + k].action;
-			else {
+			if (k < 4) {
+				action = sbus_actions[(j << 5) + (sbusl << 2) + k].action;
+			} else {
 				j++;
-				if (j == nsbi) break;
+				if (j == nsbi)
+					break;
 				k = 0;
-				action = sbus_actions [(j << 5) + (sbusl << 2)].action;
+				action = sbus_actions[(j << 5) + (sbusl << 2)].action;
 			}
 		}
 		seq_putc(p, '\n');
@@ -147,7 +162,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id)
 {
 	struct irqaction *action, **actionp;
 	struct irqaction *tmp = NULL;
-        unsigned long flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&irq_action_lock, flags);
 	if (irq < 15)
@@ -156,7 +171,7 @@ void sun4d_free_irq(unsigned int irq, void *dev_id)
 		actionp = &(sbus_actions[irq - (1 << 5)].action);
 	action = *actionp;
 	if (!action) {
-		printk("Trying to free free IRQ%d\n",irq);
+		printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
 		goto out_unlock;
 	}
 	if (dev_id) {
@@ -166,23 +181,25 @@ void sun4d_free_irq(unsigned int irq, void *dev_id)
 			tmp = action;
 		}
 		if (!action) {
-			printk("Trying to free free shared IRQ%d\n",irq);
+			printk(KERN_ERR "Trying to free free shared IRQ%d\n",
+			       irq);
 			goto out_unlock;
 		}
 	} else if (action->flags & IRQF_SHARED) {
-		printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+		printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
+		       irq);
 		goto out_unlock;
 	}
-	if (action->flags & SA_STATIC_ALLOC)
-	{
-		/* This interrupt is marked as specially allocated
+	if (action->flags & SA_STATIC_ALLOC) {
+		/*
+		 * This interrupt is marked as specially allocated
 		 * so it is a bad idea to free it.
 		 */
-		printk("Attempt to free statically allocated IRQ%d (%s)\n",
+		printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
 		       irq, action->name);
 		goto out_unlock;
 	}
-	
+
 	if (tmp)
 		tmp->next = action->next;
 	else
@@ -203,30 +220,28 @@ out_unlock:
 	spin_unlock_irqrestore(&irq_action_lock, flags);
 }
 
-extern void unexpected_irq(int, void *, struct pt_regs *);
-
-void sun4d_handler_irq(int irq, struct pt_regs * regs)
+void sun4d_handler_irq(int pil, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
-	struct irqaction * action;
+	struct irqaction *action;
 	int cpu = smp_processor_id();
 	/* SBUS IRQ level (1 - 7) */
-	int sbusl = pil_to_sbus[irq];
-	
+	int sbusl = pil_to_sbus[pil];
+
 	/* FIXME: Is this necessary?? */
 	cc_get_ipen();
-	
-	cc_set_iclr(1 << irq);
-	
+
+	cc_set_iclr(1 << pil);
+
 	old_regs = set_irq_regs(regs);
 	irq_enter();
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_cpu(cpu).irqs[pil]++;
 	if (!sbusl) {
-		action = *(irq + irq_action);
+		action = *(pil + irq_action);
 		if (!action)
-			unexpected_irq(irq, NULL, regs);
+			unexpected_irq(pil, NULL, regs);
 		do {
-			action->handler(irq, action->dev_id);
+			action->handler(pil, action->dev_id);
 			action = action->next;
 		} while (action);
 	} else {
@@ -235,9 +250,9 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs)
 		struct sbus_action *actionp;
 		unsigned mask, slot;
 		int sbil = (sbusl << 2);
-		
+
 		bw_clear_intr_mask(sbusl, bus_mask);
-		
+
 		/* Loop for each pending SBI */
 		for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1)
 			if (bus_mask & 1) {
@@ -249,11 +264,11 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs)
 					if (mask & slot) {
 						mask &= ~slot;
 						action = actionp->action;
-						
+
 						if (!action)
-							unexpected_irq(irq, NULL, regs);
+							unexpected_irq(pil, NULL, regs);
 						do {
-							action->handler(irq, action->dev_id);
+							action->handler(pil, action->dev_id);
 							action = action->next;
 						} while (action);
 						release_sbi(SBI2DEVID(sbino), slot);
@@ -266,13 +281,13 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs)
 
 int sun4d_request_irq(unsigned int irq,
 		irq_handler_t handler,
-		unsigned long irqflags, const char * devname, void *dev_id)
+		unsigned long irqflags, const char *devname, void *dev_id)
 {
 	struct irqaction *action, *tmp = NULL, **actionp;
 	unsigned long flags;
 	int ret;
-	
-	if(irq > 14 && irq < (1 << 5)) {
+
+	if (irq > 14 && irq < (1 << 5)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -289,16 +304,18 @@ int sun4d_request_irq(unsigned int irq,
 	else
 		actionp = irq + irq_action;
 	action = *actionp;
-	
+
 	if (action) {
 		if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) {
-			for (tmp = action; tmp->next; tmp = tmp->next);
+			for (tmp = action; tmp->next; tmp = tmp->next)
+				/* find last entry - tmp used below */;
 		} else {
 			ret = -EBUSY;
 			goto out_unlock;
 		}
 		if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) {
-			printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+			printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
+			       irq);
 			ret = -EBUSY;
 			goto out_unlock;
 		}
@@ -312,14 +329,14 @@ int sun4d_request_irq(unsigned int irq,
 		if (static_irq_count < MAX_STATIC_ALLOC)
 			action = &static_irqaction[static_irq_count++];
 		else
-			printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname);
+			printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
+			       irq, devname);
 	}
-	
+
 	if (action == NULL)
-		action = kmalloc(sizeof(struct irqaction),
-						     GFP_ATOMIC);
-	
-	if (!action) { 
+		action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+
+	if (!action) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
@@ -334,7 +351,7 @@ int sun4d_request_irq(unsigned int irq,
 		tmp->next = action;
 	else
 		*actionp = action;
-		
+
 	__enable_irq(irq);
 
 	ret = 0;
@@ -348,7 +365,7 @@ static void sun4d_disable_irq(unsigned int irq)
 {
 	int tid = sbus_tid[(irq >> 5) - 1];
 	unsigned long flags;
-	
+
 	if (irq < NR_IRQS)
 		return;
 
@@ -361,7 +378,7 @@ static void sun4d_enable_irq(unsigned int irq)
 {
 	int tid = sbus_tid[(irq >> 5) - 1];
 	unsigned long flags;
-	
+
 	if (irq < NR_IRQS)
 		return;
 
@@ -389,44 +406,6 @@ void __init sun4d_distribute_irqs(void)
 {
 	struct device_node *dp;
 
-#ifdef DISTRIBUTE_IRQS
-	cpumask_t sbus_serving_map;
-
-	sbus_serving_map = cpu_present_map;
-	for_each_node_by_name(dp, "sbi") {
-		int board = of_getintprop_default(dp, "board#", 0);
-
-		if ((board * 2) == boot_cpu_id && cpu_isset(board * 2 + 1, cpu_present_map))
-			sbus_tid[board] = (board * 2 + 1);
-		else if (cpu_isset(board * 2, cpu_present_map))
-			sbus_tid[board] = (board * 2);
-		else if (cpu_isset(board * 2 + 1, cpu_present_map))
-			sbus_tid[board] = (board * 2 + 1);
-		else
-			sbus_tid[board] = 0xff;
-		if (sbus_tid[board] != 0xff)
-			cpu_clear(sbus_tid[board], sbus_serving_map);
-	}
-	for_each_node_by_name(dp, "sbi") {
-		int board = of_getintprop_default(dp, "board#", 0);
-		if (sbus_tid[board] == 0xff) {
-			int i = 31;
-				
-			if (cpus_empty(sbus_serving_map))
-				sbus_serving_map = cpu_present_map;
-			while (cpu_isset(i, sbus_serving_map))
-				i--;
-			sbus_tid[board] = i;
-			cpu_clear(i, sbus_serving_map);
-		}
-	}
-	for_each_node_by_name(dp, "sbi") {
-		int devid = of_getintprop_default(dp, "device-id", 0);
-		int board = of_getintprop_default(dp, "board#", 0);
-		printk("sbus%d IRQs directed to CPU%d\n", board, sbus_tid[board]);
-		set_sbi_tid(devid, sbus_tid[board] << 3);
-	}
-#else
 	int cpuid = cpu_logical_map(1);
 
 	if (cpuid == -1)
@@ -437,11 +416,10 @@ void __init sun4d_distribute_irqs(void)
 		sbus_tid[board] = cpuid;
 		set_sbi_tid(devid, cpuid << 3);
 	}
-	printk("All sbus IRQs directed to CPU%d\n", cpuid);
-#endif
+	printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
 }
 #endif
- 
+
 static void sun4d_clear_clock_irq(void)
 {
 	sbus_readl(&sun4d_timers->l10_timer_limit);
@@ -462,14 +440,61 @@ static void __init sun4d_load_profile_irqs(void)
 	}
 }
 
+unsigned int sun4d_build_device_irq(struct platform_device *op,
+                                    unsigned int real_irq)
+{
+	static int pil_to_sbus[] = {
+		0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
+	};
+	struct device_node *dp = op->dev.of_node;
+	struct device_node *io_unit, *sbi = dp->parent;
+	const struct linux_prom_registers *regs;
+	int board, slot;
+	int sbusl;
+
+	while (sbi) {
+		if (!strcmp(sbi->name, "sbi"))
+			break;
+
+		sbi = sbi->parent;
+	}
+	if (!sbi)
+		goto err_out;
+
+	regs = of_get_property(dp, "reg", NULL);
+	if (!regs)
+		goto err_out;
+
+	slot = regs->which_io;
+
+	/*
+	 *  If SBI's parent is not io-unit or the io-unit lacks
+	 * a "board#" property, something is very wrong.
+	 */
+	if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
+		printk("%s: Error, parent is not io-unit.\n", sbi->full_name);
+		goto err_out;
+	}
+	io_unit = sbi->parent;
+	board = of_getintprop_default(io_unit, "board#", -1);
+	if (board == -1) {
+		printk("%s: Error, lacks board# property.\n", io_unit->full_name);
+		goto err_out;
+	}
+
+	sbusl = pil_to_sbus[real_irq];
+	if (sbusl)
+		return (((board + 1) << 5) + (sbusl << 2) + slot);
+
+err_out:
+	return real_irq;
+}
+
 static void __init sun4d_fixup_trap_table(void)
 {
 #ifdef CONFIG_SMP
 	unsigned long flags;
-	extern unsigned long lvl14_save[4];
 	struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
-	extern unsigned int real_irq_entry[], smp4d_ticker[];
-	extern unsigned int patchme_maybe_smp_msg[];
 
 	/* Adjust so that we jump directly to smp4d_ticker */
 	lvl14_save[2] += smp4d_ticker - real_irq_entry;
@@ -531,7 +556,8 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
 			  (IRQF_DISABLED | SA_STATIC_ALLOC),
 			  "timer", NULL);
 	if (err) {
-		prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err);
+		prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
+		             err);
 		prom_halt();
 	}
 	sun4d_load_profile_irqs();
@@ -550,7 +576,7 @@ void __init sun4d_init_sbi_irq(void)
 	nsbi = 0;
 	for_each_node_by_name(dp, "sbi")
 		nsbi++;
-	sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
+	sbus_actions = kzalloc(nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
 	if (!sbus_actions) {
 		prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n");
 		prom_halt();
@@ -566,7 +592,8 @@ void __init sun4d_init_sbi_irq(void)
 		/* Get rid of pending irqs from PROM */
 		mask = acquire_sbi(devid, 0xffffffff);
 		if (mask) {
-			printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board);
+			printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
+			       mask, board);
 			release_sbi(devid, mask);
 		}
 	}
@@ -580,7 +607,10 @@ void __init sun4d_init_IRQ(void)
 	BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
-	sparc_init_timers = sun4d_init_timers;
+
+	sparc_irq_config.init_timers = sun4d_init_timers;
+	sparc_irq_config.build_device_irq = sun4d_build_device_irq;
+
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 482f2ab..475d50b 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -1,4 +1,4 @@
-/* sun4d_smp.c: Sparc SS1000/SC2000 SMP support.
+/* Sparc SS1000/SC2000 SMP support.
  *
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *
@@ -6,59 +6,23 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/head.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
 #include <linux/cpu.h>
 
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq_regs.h>
-
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/oplib.h>
 #include <asm/sbi.h>
+#include <asm/mmu.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
-#include <asm/cpudata.h>
 
+#include "kernel.h"
 #include "irq.h"
-#define IRQ_CROSS_CALL		15
 
-extern ctxd_t *srmmu_ctx_table_phys;
+#define IRQ_CROSS_CALL		15
 
-static volatile int smp_processors_ready = 0;
+static volatile int smp_processors_ready;
 static int smp_highest_cpu;
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
-extern cpuinfo_sparc cpu_data[NR_CPUS];
-extern unsigned char boot_cpu_id;
-extern volatile int smp_process_available;
-
-extern cpumask_t smp_commenced_mask;
-
-extern int __smp4d_processor_id(void);
-
-/* #define SMP_DEBUG */
-
-#ifdef SMP_DEBUG
-#define SMP_PRINTK(x)	printk x
-#else
-#define SMP_PRINTK(x)
-#endif
 
 static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned long val)
 {
@@ -69,8 +33,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
 }
 
 static void smp_setup_percpu_timer(void);
-extern void cpu_probe(void);
-extern void sun4d_distribute_irqs(void);
 
 static unsigned char cpu_leds[32];
 
@@ -86,9 +48,8 @@ static inline void show_leds(int cpuid)
 void __cpuinit smp4d_callin(void)
 {
 	int cpuid = hard_smp4d_processor_id();
-	extern spinlock_t sun4d_imsk_lock;
 	unsigned long flags;
-	
+
 	/* Show we are alive */
 	cpu_leds[cpuid] = 0x6;
 	show_leds(cpuid);
@@ -118,15 +79,15 @@ void __cpuinit smp4d_callin(void)
 	sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
 	local_flush_cache_all();
 	local_flush_tlb_all();
-	
+
 	cpu_probe();
 
-	while((unsigned long)current_set[cpuid] < PAGE_OFFSET)
+	while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
 		barrier();
-		
-	while(current_set[cpuid]->cpu != cpuid)
+
+	while (current_set[cpuid]->cpu != cpuid)
 		barrier();
-		
+
 	/* Fix idle thread fields. */
 	__asm__ __volatile__("ld [%0], %%g6\n\t"
 			     : : "r" (&current_set[cpuid])
@@ -134,16 +95,16 @@ void __cpuinit smp4d_callin(void)
 
 	cpu_leds[cpuid] = 0x9;
 	show_leds(cpuid);
-	
+
 	/* Attach to the address space of init_task. */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
 
 	local_flush_cache_all();
 	local_flush_tlb_all();
-	
+
 	local_irq_enable();	/* We don't allow PIL 14 yet */
-	
+
 	while (!cpu_isset(cpuid, smp_commenced_mask))
 		barrier();
 
@@ -154,15 +115,9 @@ void __cpuinit smp4d_callin(void)
 
 }
 
-extern void init_IRQ(void);
-extern void cpu_panic(void);
-
 /*
  *	Cycle through the processors asking the PROM to start each one.
  */
- 
-extern struct linux_prom_registers smp_penguin_ctable;
-
 void __init smp4d_boot_cpus(void)
 {
 	if (boot_cpu_id)
@@ -173,43 +128,42 @@ void __init smp4d_boot_cpus(void)
 
 int __cpuinit smp4d_boot_one_cpu(int i)
 {
-			extern unsigned long sun4d_cpu_startup;
-			unsigned long *entry = &sun4d_cpu_startup;
-			struct task_struct *p;
-			int timeout;
-			int cpu_node;
+	unsigned long *entry = &sun4d_cpu_startup;
+	struct task_struct *p;
+	int timeout;
+	int cpu_node;
 
-			cpu_find_by_instance(i, &cpu_node,NULL);
-			/* Cook up an idler for this guy. */
-			p = fork_idle(i);
-			current_set[i] = task_thread_info(p);
+	cpu_find_by_instance(i, &cpu_node, NULL);
+	/* Cook up an idler for this guy. */
+	p = fork_idle(i);
+	current_set[i] = task_thread_info(p);
+
+	/*
+	 * Initialize the contexts table
+	 * Since the call to prom_startcpu() trashes the structure,
+	 * we need to re-initialize it for each cpu
+	 */
+	smp_penguin_ctable.which_io = 0;
+	smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+	smp_penguin_ctable.reg_size = 0;
+
+	/* whirrr, whirrr, whirrrrrrrrr... */
+	printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
+	local_flush_cache_all();
+	prom_startcpu(cpu_node,
+		      &smp_penguin_ctable, 0, (char *)entry);
+
+	printk(KERN_INFO "prom_startcpu returned :)\n");
+
+	/* wheee... it's going... */
+	for (timeout = 0; timeout < 10000; timeout++) {
+		if (cpu_callin_map[i])
+			break;
+		udelay(200);
+	}
 
-			/*
-			 * Initialize the contexts table
-			 * Since the call to prom_startcpu() trashes the structure,
-			 * we need to re-initialize it for each cpu
-			 */
-			smp_penguin_ctable.which_io = 0;
-			smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
-			smp_penguin_ctable.reg_size = 0;
-
-			/* whirrr, whirrr, whirrrrrrrrr... */
-			SMP_PRINTK(("Starting CPU %d at %p\n", i, entry));
-			local_flush_cache_all();
-			prom_startcpu(cpu_node,
-				      &smp_penguin_ctable, 0, (char *)entry);
-				      
-			SMP_PRINTK(("prom_startcpu returned :)\n"));
-
-			/* wheee... it's going... */
-			for(timeout = 0; timeout < 10000; timeout++) {
-				if(cpu_callin_map[i])
-					break;
-				udelay(200);
-			}
-			
 	if (!(cpu_callin_map[i])) {
-		printk("Processor %d is stuck.\n", i);
+		printk(KERN_ERR "Processor %d is stuck.\n", i);
 		return -ENODEV;
 
 	}
@@ -255,14 +209,17 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
 			     unsigned long arg2, unsigned long arg3,
 			     unsigned long arg4)
 {
-	if(smp_processors_ready) {
+	if (smp_processors_ready) {
 		register int high = smp_highest_cpu;
 		unsigned long flags;
 
 		spin_lock_irqsave(&cross_call_lock, flags);
 
 		{
-			/* If you make changes here, make sure gcc generates proper code... */
+			/*
+			 * If you make changes here, make sure
+			 * gcc generates proper code...
+			 */
 			register smpfunc_t f asm("i0") = func;
 			register unsigned long a1 asm("i1") = arg1;
 			register unsigned long a2 asm("i2") = arg2;
@@ -284,7 +241,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
 
 			cpu_clear(smp_processor_id(), mask);
 			cpus_and(mask, cpu_online_map, mask);
-			for(i = 0; i <= high; i++) {
+			for (i = 0; i <= high; i++) {
 				if (cpu_isset(i, mask)) {
 					ccall_info.processors_in[i] = 0;
 					ccall_info.processors_out[i] = 0;
@@ -300,17 +257,17 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_in[i])
+				while (!ccall_info.processors_in[i])
 					barrier();
-			} while(++i <= high);
+			} while (++i <= high);
 
 			i = 0;
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_out[i])
+				while (!ccall_info.processors_out[i])
 					barrier();
-			} while(++i <= high);
+			} while (++i <= high);
 		}
 
 		spin_unlock_irqrestore(&cross_call_lock, flags);
@@ -336,7 +293,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 	static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
 
 	old_regs = set_irq_regs(regs);
-	bw_get_prof_limit(cpu);	
+	bw_get_prof_limit(cpu);
 	bw_clear_intr_mask(0, 1);	/* INTR_TABLE[0] & 1 is Profile IRQ */
 
 	cpu_tick[cpu]++;
@@ -349,7 +306,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 
 	profile_tick(CPU_PROFILING);
 
-	if(!--prof_counter(cpu)) {
+	if (!--prof_counter(cpu)) {
 		int user = user_mode(regs);
 
 		irq_enter();
@@ -361,8 +318,6 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
 	set_irq_regs(old_regs);
 }
 
-extern unsigned int lvl14_resolution;
-
 static void __cpuinit smp_setup_percpu_timer(void)
 {
 	int cpu = hard_smp4d_processor_id();
@@ -374,16 +329,16 @@ static void __cpuinit smp_setup_percpu_timer(void)
 void __init smp4d_blackbox_id(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
-	
+
 	addr[0] = 0xc0800800 | rd;		/* lda [%g0] ASI_M_VIKING_TMP1, reg */
-	addr[1] = 0x01000000;    		/* nop */
-	addr[2] = 0x01000000;    		/* nop */
+	addr[1] = 0x01000000;			/* nop */
+	addr[2] = 0x01000000;			/* nop */
 }
 
 void __init smp4d_blackbox_current(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
-	
+
 	addr[0] = 0xc0800800 | rd;		/* lda [%g0] ASI_M_VIKING_TMP1, reg */
 	addr[2] = 0x81282002 | rd | (rd >> 11);	/* sll reg, 2, reg */
 	addr[4] = 0x01000000;			/* nop */
@@ -392,17 +347,16 @@ void __init smp4d_blackbox_current(unsigned *addr)
 void __init sun4d_init_smp(void)
 {
 	int i;
-	extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[];
 
 	/* Patch ipi15 trap table */
 	t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
-	
+
 	/* And set btfixup... */
 	BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
 	BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
 	BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
-	
+
 	for (i = 0; i < NR_CPUS; i++) {
 		ccall_info.processors_in[i] = 1;
 		ccall_info.processors_out[i] = 1;
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 7f3b97f..69df625 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -1,5 +1,5 @@
-/*  sun4m_irq.c
- *  arch/sparc/kernel/sun4m_irq.c:
+/*
+ * sun4m irq support
  *
  *  djhr: Hacked out of irq.c into a CPU dependent version.
  *
@@ -9,101 +9,44 @@
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
-#include <linux/errno.h>
-#include <linux/linkage.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/vaddrs.h>
 #include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
 #include <asm/traps.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
-#include <asm/smp.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
 #include "irq.h"
+#include "kernel.h"
 
-struct sun4m_irq_percpu {
-	u32		pending;
-	u32		clear;
-	u32		set;
-};
-
-struct sun4m_irq_global {
-	u32		pending;
-	u32		mask;
-	u32		mask_clear;
-	u32		mask_set;
-	u32		interrupt_target;
-};
-
-/* Code in entry.S needs to get at these register mappings.  */
-struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
-struct sun4m_irq_global __iomem *sun4m_irq_global;
-
-/* Dave Redman (djhr@tadpole.co.uk)
- * The sun4m interrupt registers.
- */
-#define SUN4M_INT_ENABLE  	0x80000000
-#define SUN4M_INT_E14     	0x00000080
-#define SUN4M_INT_E10     	0x00080000
-
-#define SUN4M_HARD_INT(x)	(0x000000001 << (x))
-#define SUN4M_SOFT_INT(x)	(0x000010000 << (x))
-
-#define	SUN4M_INT_MASKALL	0x80000000	  /* mask all interrupts */
-#define	SUN4M_INT_MODULE_ERR	0x40000000	  /* module error */
-#define	SUN4M_INT_M2S_WRITE_ERR	0x20000000	  /* write buffer error */
-#define	SUN4M_INT_ECC_ERR	0x10000000	  /* ecc memory error */
-#define	SUN4M_INT_VME_ERR	0x08000000	  /* vme async error */
-#define	SUN4M_INT_FLOPPY	0x00400000	  /* floppy disk */
-#define	SUN4M_INT_MODULE	0x00200000	  /* module interrupt */
-#define	SUN4M_INT_VIDEO		0x00100000	  /* onboard video */
-#define	SUN4M_INT_REALTIME	0x00080000	  /* system timer */
-#define	SUN4M_INT_SCSI		0x00040000	  /* onboard scsi */
-#define	SUN4M_INT_AUDIO		0x00020000	  /* audio/isdn */
-#define	SUN4M_INT_ETHERNET	0x00010000	  /* onboard ethernet */
-#define	SUN4M_INT_SERIAL	0x00008000	  /* serial ports */
-#define	SUN4M_INT_KBDMS		0x00004000	  /* keyboard/mouse */
-#define	SUN4M_INT_SBUSBITS	0x00003F80	  /* sbus int bits */
-#define	SUN4M_INT_VMEBITS	0x0000007F	  /* vme int bits */
-
-#define	SUN4M_INT_ERROR		(SUN4M_INT_MODULE_ERR |    \
-				 SUN4M_INT_M2S_WRITE_ERR | \
-				 SUN4M_INT_ECC_ERR |       \
-				 SUN4M_INT_VME_ERR)
-
-#define SUN4M_INT_SBUS(x)	(1 << (x+7))
-#define SUN4M_INT_VME(x)	(1 << (x))
-
-/* Interrupt levels used by OBP */
-#define	OBP_INT_LEVEL_SOFT	0x10
-#define	OBP_INT_LEVEL_ONBOARD	0x20
-#define	OBP_INT_LEVEL_SBUS	0x30
-#define	OBP_INT_LEVEL_VME	0x40
-
-/* Interrupt level assignment on sun4m:
+/* Sample sun4m IRQ layout:
+ *
+ * 0x22 - Power
+ * 0x24 - ESP SCSI
+ * 0x26 - Lance ethernet
+ * 0x2b - Floppy
+ * 0x2c - Zilog uart
+ * 0x32 - SBUS level 0
+ * 0x33 - Parallel port, SBUS level 1
+ * 0x35 - SBUS level 2
+ * 0x37 - SBUS level 3
+ * 0x39 - Audio, Graphics card, SBUS level 4
+ * 0x3b - SBUS level 5
+ * 0x3d - SBUS level 6
+ *
+ * Each interrupt source has a mask bit in the interrupt registers.
+ * When the mask bit is set, this blocks interrupt deliver.  So you
+ * clear the bit to enable the interrupt.
+ *
+ * Interrupts numbered less than 0x10 are software triggered interrupts
+ * and unused by Linux.
+ *
+ * Interrupt level assignment on sun4m:
  *
  *	level		source
  * ------------------------------------------------------------
- *        1		softint-1
+ *	  1		softint-1
  *	  2		softint-2, VME/SBUS level 1
  *	  3		softint-3, VME/SBUS level 2
  *	  4		softint-4, onboard SCSI
@@ -138,10 +81,10 @@ struct sun4m_irq_global __iomem *sun4m_irq_global;
  * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and
  * Tadpole S3 GX systems.
  *
- * esp: 	0x24	onboard ESP SCSI
- * le:  	0x26	onboard Lance ETHERNET
+ * esp:		0x24	onboard ESP SCSI
+ * le:		0x26	onboard Lance ETHERNET
  * p9100:	0x32	SBUS level 1 P9100 video
- * bpp:  	0x33	SBUS level 2 BPP parallel port device
+ * bpp:		0x33	SBUS level 2 BPP parallel port device
  * DBRI:	0x39	SBUS level 5 DBRI ISDN audio
  * SUNW,leo:	0x39	SBUS level 5 LEO video
  * pcmcia:	0x3b	SBUS level 6 PCMCIA controller
@@ -152,8 +95,57 @@ struct sun4m_irq_global __iomem *sun4m_irq_global;
  * power:	0x22	onboard power device (XXX unknown mask bit XXX)
  */
 
+
+/* Code in entry.S needs to get at these register mappings.  */
+struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
+struct sun4m_irq_global __iomem *sun4m_irq_global;
+
+/* Dave Redman (djhr@tadpole.co.uk)
+ * The sun4m interrupt registers.
+ */
+#define SUN4M_INT_ENABLE	0x80000000
+#define SUN4M_INT_E14		0x00000080
+#define SUN4M_INT_E10		0x00080000
+
+#define SUN4M_HARD_INT(x)	(0x000000001 << (x))
+#define SUN4M_SOFT_INT(x)	(0x000010000 << (x))
+
+#define	SUN4M_INT_MASKALL	0x80000000	  /* mask all interrupts */
+#define	SUN4M_INT_MODULE_ERR	0x40000000	  /* module error */
+#define	SUN4M_INT_M2S_WRITE_ERR	0x20000000	  /* write buffer error */
+#define	SUN4M_INT_ECC_ERR	0x10000000	  /* ecc memory error */
+#define	SUN4M_INT_VME_ERR	0x08000000	  /* vme async error */
+#define	SUN4M_INT_FLOPPY	0x00400000	  /* floppy disk */
+#define	SUN4M_INT_MODULE	0x00200000	  /* module interrupt */
+#define	SUN4M_INT_VIDEO		0x00100000	  /* onboard video */
+#define	SUN4M_INT_REALTIME	0x00080000	  /* system timer */
+#define	SUN4M_INT_SCSI		0x00040000	  /* onboard scsi */
+#define	SUN4M_INT_AUDIO		0x00020000	  /* audio/isdn */
+#define	SUN4M_INT_ETHERNET	0x00010000	  /* onboard ethernet */
+#define	SUN4M_INT_SERIAL	0x00008000	  /* serial ports */
+#define	SUN4M_INT_KBDMS		0x00004000	  /* keyboard/mouse */
+#define	SUN4M_INT_SBUSBITS	0x00003F80	  /* sbus int bits */
+#define	SUN4M_INT_VMEBITS	0x0000007F	  /* vme int bits */
+
+#define	SUN4M_INT_ERROR		(SUN4M_INT_MODULE_ERR |    \
+				 SUN4M_INT_M2S_WRITE_ERR | \
+				 SUN4M_INT_ECC_ERR |       \
+				 SUN4M_INT_VME_ERR)
+
+#define SUN4M_INT_SBUS(x)	(1 << (x+7))
+#define SUN4M_INT_VME(x)	(1 << (x))
+
+/* Interrupt levels used by OBP */
+#define	OBP_INT_LEVEL_SOFT	0x10
+#define	OBP_INT_LEVEL_ONBOARD	0x20
+#define	OBP_INT_LEVEL_SBUS	0x30
+#define	OBP_INT_LEVEL_VME	0x40
+
+#define SUN4M_TIMER_IRQ         (OBP_INT_LEVEL_ONBOARD | 10)
+#define SUM4M_PROFILE_IRQ       (OBP_INT_LEVEL_ONBOARD | 14)
+
 static unsigned long irq_mask[0x50] = {
-	/* SMP */
+	/* 0x00 - SMP */
 	0,  SUN4M_SOFT_INT(1),
 	SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
 	SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
@@ -162,7 +154,7 @@ static unsigned long irq_mask[0x50] = {
 	SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
 	SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
 	SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
-	/* soft */
+	/* 0x10 - soft */
 	0,  SUN4M_SOFT_INT(1),
 	SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
 	SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
@@ -171,19 +163,19 @@ static unsigned long irq_mask[0x50] = {
 	SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
 	SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
 	SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
-	/* onboard */
+	/* 0x20 - onboard */
 	0, 0, 0, 0,
 	SUN4M_INT_SCSI,  0, SUN4M_INT_ETHERNET, 0,
 	SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
 	SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
 	(SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
 	SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR,
-	/* sbus */
+	/* 0x30 - sbus */
 	0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
 	0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
 	0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5),
 	0, SUN4M_INT_SBUS(6), 0, 0,
-	/* vme */
+	/* 0x40 - vme */
 	0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1),
 	0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3),
 	0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5),
@@ -193,7 +185,7 @@ static unsigned long irq_mask[0x50] = {
 static unsigned long sun4m_get_irqmask(unsigned int irq)
 {
 	unsigned long mask;
-    
+
 	if (irq < 0x50)
 		mask = irq_mask[irq];
 	else
@@ -217,7 +209,7 @@ static void sun4m_disable_irq(unsigned int irq_nr)
 		sbus_writel(mask, &sun4m_irq_global->mask_set);
 	else
 		sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
-	local_irq_restore(flags);    
+	local_irq_restore(flags);
 }
 
 static void sun4m_enable_irq(unsigned int irq_nr)
@@ -226,17 +218,17 @@ static void sun4m_enable_irq(unsigned int irq_nr)
 	int cpu = smp_processor_id();
 
 	/* Dreadful floppy hack. When we use 0x2b instead of
-         * 0x0b the system blows (it starts to whistle!).
-         * So we continue to use 0x0b. Fixme ASAP. --P3
-         */
-        if (irq_nr != 0x0b) {
+	 * 0x0b the system blows (it starts to whistle!).
+	 * So we continue to use 0x0b. Fixme ASAP. --P3
+	 */
+	if (irq_nr != 0x0b) {
 		mask = sun4m_get_irqmask(irq_nr);
 		local_irq_save(flags);
 		if (irq_nr > 15)
 			sbus_writel(mask, &sun4m_irq_global->mask_clear);
 		else
 			sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
-		local_irq_restore(flags);    
+		local_irq_restore(flags);
 	} else {
 		local_irq_save(flags);
 		sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear);
@@ -260,7 +252,7 @@ static unsigned long cpu_pil_to_imask[16] = {
 /*12*/	SUN4M_INT_SERIAL  | SUN4M_INT_KBDMS,
 /*13*/	SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO,
 /*14*/	SUN4M_INT_E14,
-/*15*/	SUN4M_INT_ERROR
+/*15*/	SUN4M_INT_ERROR,
 };
 
 /* We assume the caller has disabled local interrupts when these are called,
@@ -280,12 +272,14 @@ static void sun4m_enable_pil_irq(unsigned int pil)
 static void sun4m_send_ipi(int cpu, int level)
 {
 	unsigned long mask = sun4m_get_irqmask(level);
+
 	sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
 }
 
 static void sun4m_clear_ipi(int cpu, int level)
 {
 	unsigned long mask = sun4m_get_irqmask(level);
+
 	sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
 }
 
@@ -314,7 +308,6 @@ struct sun4m_timer_global {
 
 static struct sun4m_timer_global __iomem *timers_global;
 
-#define TIMER_IRQ  	(OBP_INT_LEVEL_ONBOARD | 10)
 
 unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
 
@@ -391,7 +384,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
 
 	master_l10_counter = &timers_global->l10_count;
 
-	err = request_irq(TIMER_IRQ, counter_fn,
+	err = request_irq(SUN4M_TIMER_IRQ, counter_fn,
 			  (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
 	if (err) {
 		printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
@@ -407,7 +400,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
 #ifdef CONFIG_SMP
 	{
 		unsigned long flags;
-		extern unsigned long lvl14_save[4];
 		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
 
 		/* For SMP we use the level 14 ticker, however the bootup code
@@ -466,7 +458,9 @@ void __init sun4m_init_IRQ(void)
 	BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
-	sparc_init_timers = sun4m_init_timers;
+
+	sparc_irq_config.init_timers = sun4m_init_timers;
+
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 762d6ee..5cc7dc5 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -1,59 +1,22 @@
-/* sun4m_smp.c: Sparc SUN4M SMP support.
+/*
+ *  sun4m SMP support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/head.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
 #include <linux/cpu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/irq_regs.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/oplib.h>
-#include <asm/cpudata.h>
 
 #include "irq.h"
+#include "kernel.h"
 
 #define IRQ_CROSS_CALL		15
 
-extern ctxd_t *srmmu_ctx_table_phys;
-
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
-extern unsigned char boot_cpu_id;
-
-extern cpumask_t smp_commenced_mask;
-
-extern int __smp4m_processor_id(void);
-
-/*#define SMP_DEBUG*/
-
-#ifdef SMP_DEBUG
-#define SMP_PRINTK(x)	printk x
-#else
-#define SMP_PRINTK(x)
-#endif
-
 static inline unsigned long
 swap_ulong(volatile unsigned long *ptr, unsigned long val)
 {
@@ -64,7 +27,6 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val)
 }
 
 static void smp_setup_percpu_timer(void);
-extern void cpu_probe(void);
 
 void __cpuinit smp4m_callin(void)
 {
@@ -96,7 +58,7 @@ void __cpuinit smp4m_callin(void)
 	/* XXX: What's up with all the flushes? */
 	local_flush_cache_all();
 	local_flush_tlb_all();
-	
+
 	cpu_probe();
 
 	/* Fix idle thread fields. */
@@ -119,9 +81,6 @@ void __cpuinit smp4m_callin(void)
 /*
  *	Cycle through the processors asking the PROM to start each one.
  */
- 
-extern struct linux_prom_registers smp_penguin_ctable;
-
 void __init smp4m_boot_cpus(void)
 {
 	smp_setup_percpu_timer();
@@ -130,7 +89,6 @@ void __init smp4m_boot_cpus(void)
 
 int __cpuinit smp4m_boot_one_cpu(int i)
 {
-	extern unsigned long sun4m_cpu_startup;
 	unsigned long *entry = &sun4m_cpu_startup;
 	struct task_struct *p;
 	int timeout;
@@ -142,7 +100,7 @@ int __cpuinit smp4m_boot_one_cpu(int i)
 	p = fork_idle(i);
 	current_set[i] = task_thread_info(p);
 	/* See trampoline.S for details... */
-	entry += ((i-1) * 3);
+	entry += ((i - 1) * 3);
 
 	/*
 	 * Initialize the contexts table
@@ -154,20 +112,19 @@ int __cpuinit smp4m_boot_one_cpu(int i)
 	smp_penguin_ctable.reg_size = 0;
 
 	/* whirrr, whirrr, whirrrrrrrrr... */
-	printk("Starting CPU %d at %p\n", i, entry);
+	printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
 	local_flush_cache_all();
-	prom_startcpu(cpu_node,
-		      &smp_penguin_ctable, 0, (char *)entry);
+	prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
 
 	/* wheee... it's going... */
-	for(timeout = 0; timeout < 10000; timeout++) {
-		if(cpu_callin_map[i])
+	for (timeout = 0; timeout < 10000; timeout++) {
+		if (cpu_callin_map[i])
 			break;
 		udelay(200);
 	}
 
 	if (!(cpu_callin_map[i])) {
-		printk("Processor %d is stuck.\n", i);
+		printk(KERN_ERR "Processor %d is stuck.\n", i);
 		return -ENODEV;
 	}
 
@@ -202,6 +159,7 @@ void __init smp4m_smp_done(void)
 void smp4m_irq_rotate(int cpu)
 {
 	int next = cpu_data(cpu).next;
+
 	if (next != cpu)
 		set_irq_udt(next);
 }
@@ -243,7 +201,7 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
 
 			cpu_clear(smp_processor_id(), mask);
 			cpus_and(mask, cpu_online_map, mask);
-			for(i = 0; i < ncpus; i++) {
+			for (i = 0; i < ncpus; i++) {
 				if (cpu_isset(i, mask)) {
 					ccall_info.processors_in[i] = 0;
 					ccall_info.processors_out[i] = 0;
@@ -262,19 +220,18 @@ static void smp4m_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_in[i])
+				while (!ccall_info.processors_in[i])
 					barrier();
-			} while(++i < ncpus);
+			} while (++i < ncpus);
 
 			i = 0;
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_out[i])
+				while (!ccall_info.processors_out[i])
 					barrier();
-			} while(++i < ncpus);
+			} while (++i < ncpus);
 		}
-
 		spin_unlock_irqrestore(&cross_call_lock, flags);
 }
 
@@ -289,8 +246,6 @@ void smp4m_cross_call_irq(void)
 	ccall_info.processors_out[i] = 1;
 }
 
-extern void sun4m_clear_profile_irq(int cpu);
-
 void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
@@ -302,7 +257,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 
 	profile_tick(CPU_PROFILING);
 
-	if(!--prof_counter(cpu)) {
+	if (!--prof_counter(cpu)) {
 		int user = user_mode(regs);
 
 		irq_enter();
@@ -314,8 +269,6 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 	set_irq_regs(old_regs);
 }
 
-extern unsigned int lvl14_resolution;
-
 static void __cpuinit smp_setup_percpu_timer(void)
 {
 	int cpu = smp_processor_id();
@@ -323,7 +276,7 @@ static void __cpuinit smp_setup_percpu_timer(void)
 	prof_counter(cpu) = prof_multiplier(cpu) = 1;
 	load_profile_irq(cpu, lvl14_resolution);
 
-	if(cpu == boot_cpu_id)
+	if (cpu == boot_cpu_id)
 		enable_pil_irq(14);
 }
 
@@ -331,9 +284,9 @@ static void __init smp4m_blackbox_id(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
-	
+
 	addr[0] = 0x81580000 | rd;		/* rd %tbr, reg */
-	addr[1] = 0x8130200c | rd | rs1;    	/* srl reg, 0xc, reg */
+	addr[1] = 0x8130200c | rd | rs1;	/* srl reg, 0xc, reg */
 	addr[2] = 0x80082003 | rd | rs1;	/* and reg, 3, reg */
 }
 
@@ -341,9 +294,9 @@ static void __init smp4m_blackbox_current(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
-	
+
 	addr[0] = 0x81580000 | rd;		/* rd %tbr, reg */
-	addr[2] = 0x8130200a | rd | rs1;    	/* srl reg, 0xa, reg */
+	addr[2] = 0x8130200a | rd | rs1;	/* srl reg, 0xa, reg */
 	addr[4] = 0x8008200c | rd | rs1;	/* and reg, 0xc, reg */
 }
 
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index f836f4e..96082d3 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -360,20 +360,25 @@ unsigned long get_fb_unmapped_area(struct file *filp, unsigned long orig_addr, u
 }
 EXPORT_SYMBOL(get_fb_unmapped_area);
 
-/* Essentially the same as PowerPC... */
-void arch_pick_mmap_layout(struct mm_struct *mm)
+/* Essentially the same as PowerPC.  */
+static unsigned long mmap_rnd(void)
 {
-	unsigned long random_factor = 0UL;
-	unsigned long gap;
+	unsigned long rnd = 0UL;
 
 	if (current->flags & PF_RANDOMIZE) {
-		random_factor = get_random_int();
+		unsigned long val = get_random_int();
 		if (test_thread_flag(TIF_32BIT))
-			random_factor &= ((1 * 1024 * 1024) - 1);
+			rnd = (val % (1UL << (22UL-PAGE_SHIFT)));
 		else
-			random_factor = ((random_factor << PAGE_SHIFT) &
-					 0xffffffffUL);
+			rnd = (val % (1UL << (29UL-PAGE_SHIFT)));
 	}
+	return (rnd << PAGE_SHIFT) * 2;
+}
+
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	unsigned long random_factor = mmap_rnd();
+	unsigned long gap;
 
 	/*
 	 * Fall back to the standard layout if the personality
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index ec396e1..4b86eaf 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -83,5 +83,5 @@ sys_call_table:
 /*315*/	.long sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/	.long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 /*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
-/*330*/	.long sys_fanotify_mark, sys_prlimit64
+/*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index 8cfcaa5..0331baf 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -84,7 +84,7 @@ sys_call_table32:
 	.word compat_sys_timerfd_settime, compat_sys_timerfd_gettime, compat_sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
 	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
-/*330*/	.word sys32_fanotify_mark, sys_prlimit64
+/*330*/	.word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
 
 #endif /* CONFIG_COMPAT */
 
@@ -160,4 +160,4 @@ sys_call_table:
 	.word sys_timerfd_settime, sys_timerfd_gettime, sys_signalfd4, sys_eventfd2, sys_epoll_create1
 /*320*/	.word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 	.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
-/*330*/	.word sys_fanotify_mark, sys_prlimit64
+/*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c
deleted file mode 100644
index 138bbf5..0000000
--- a/arch/sparc/kernel/tick14.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/* tick14.c
- *
- * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
- *
- * This file handles the Sparc specific level14 ticker
- * This is really useful for profiling OBP uses it for keyboard
- * aborts and other stuff.
- */
-#include <linux/kernel.h>
-
-extern unsigned long lvl14_save[5];
-static unsigned long *linux_lvl14 = NULL;
-static unsigned long obp_lvl14[4];
- 
-/*
- * Call with timer IRQ closed.
- * First time we do it with disable_irq, later prom code uses spin_lock_irq().
- */
-void install_linux_ticker(void)
-{
-
-	if (!linux_lvl14)
-		return;
-	linux_lvl14[0] =  lvl14_save[0];
-	linux_lvl14[1] =  lvl14_save[1];
-	linux_lvl14[2] =  lvl14_save[2];
-	linux_lvl14[3] =  lvl14_save[3];
-}
-
-void install_obp_ticker(void)
-{
-
-	if (!linux_lvl14)
-		return;
-	linux_lvl14[0] =  obp_lvl14[0];
-	linux_lvl14[1] =  obp_lvl14[1];
-	linux_lvl14[2] =  obp_lvl14[2];
-	linux_lvl14[3] =  obp_lvl14[3]; 
-}
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 9c743b1..8237dd4 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -85,7 +85,7 @@ int update_persistent_clock(struct timespec now)
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 
 #define TICK_SIZE (tick_nsec / 1000)
@@ -96,14 +96,9 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id)
 	profile_tick(CPU_PROFILING);
 #endif
 
-	/* Protect counter clear so that do_gettimeoffset works */
-	write_seqlock(&xtime_lock);
-
 	clear_clock_irq();
 
-	do_timer(1);
-
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
@@ -142,7 +137,7 @@ static struct platform_device m48t59_rtc = {
 	},
 };
 
-static int __devinit clock_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit clock_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	const char *model = of_get_property(dp, "model", NULL);
@@ -176,7 +171,7 @@ static struct of_device_id __initdata clock_match[] = {
 	{},
 };
 
-static struct of_platform_driver clock_driver = {
+static struct platform_driver clock_driver = {
 	.probe		= clock_probe,
 	.driver = {
 		.name = "rtc",
@@ -189,7 +184,7 @@ static struct of_platform_driver clock_driver = {
 /* Probe for the mostek real time clock chip. */
 static int __init clock_init(void)
 {
-	return of_register_platform_driver(&clock_driver);
+	return platform_driver_register(&clock_driver);
 }
 /* Must be after subsys_initcall() so that busses are probed.  Must
  * be before device_initcall() because things like the RTC driver
@@ -224,7 +219,7 @@ static void __init sbus_time_init(void)
 
 	btfixup();
 
-	sparc_init_timers(timer_interrupt);
+	sparc_irq_config.init_timers(timer_interrupt);
 }
 
 void __init time_init(void)
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index 3bc9c99..95ec25f 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -419,7 +419,7 @@ static struct platform_device rtc_cmos_device = {
 	.num_resources	= 1,
 };
 
-static int __devinit rtc_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit rtc_probe(struct platform_device *op)
 {
 	struct resource *r;
 
@@ -462,7 +462,7 @@ static struct of_device_id __initdata rtc_match[] = {
 	{},
 };
 
-static struct of_platform_driver rtc_driver = {
+static struct platform_driver rtc_driver = {
 	.probe		= rtc_probe,
 	.driver = {
 		.name = "rtc",
@@ -477,7 +477,7 @@ static struct platform_device rtc_bq4802_device = {
 	.num_resources	= 1,
 };
 
-static int __devinit bq4802_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bq4802_probe(struct platform_device *op)
 {
 
 	printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n",
@@ -495,7 +495,7 @@ static struct of_device_id __initdata bq4802_match[] = {
 	{},
 };
 
-static struct of_platform_driver bq4802_driver = {
+static struct platform_driver bq4802_driver = {
 	.probe		= bq4802_probe,
 	.driver = {
 		.name = "bq4802",
@@ -534,7 +534,7 @@ static struct platform_device m48t59_rtc = {
 	},
 };
 
-static int __devinit mostek_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit mostek_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -559,7 +559,7 @@ static struct of_device_id __initdata mostek_match[] = {
 	{},
 };
 
-static struct of_platform_driver mostek_driver = {
+static struct platform_driver mostek_driver = {
 	.probe		= mostek_probe,
 	.driver = {
 		.name = "mostek",
@@ -586,9 +586,9 @@ static int __init clock_init(void)
 	if (tlb_type == hypervisor)
 		return platform_device_register(&rtc_sun4v_device);
 
-	(void) of_register_platform_driver(&rtc_driver);
-	(void) of_register_platform_driver(&mostek_driver);
-	(void) of_register_platform_driver(&bq4802_driver);
+	(void) platform_driver_register(&rtc_driver);
+	(void) platform_driver_register(&mostek_driver);
+	(void) platform_driver_register(&bq4802_driver);
 
 	return 0;
 }
@@ -816,14 +816,12 @@ void __init time_init(void)
 		clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT);
 
 	clocksource_tick.name = tick_ops->name;
-	clocksource_calc_mult_shift(&clocksource_tick, freq, 4);
 	clocksource_tick.read = clocksource_tick_read;
 
+	clocksource_register_hz(&clocksource_tick, freq);
 	printk("clocksource: mult[%x] shift[%d]\n",
 	       clocksource_tick.mult, clocksource_tick.shift);
 
-	clocksource_register(&clocksource_tick);
-
 	sparc64_clockevent.name = tick_ops->name;
 	clockevents_calc_mult_shift(&sparc64_clockevent, freq, 4);
 
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 1e97709..1ed547b 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2152,7 +2152,7 @@ static void user_instruction_dump(unsigned int __user *pc)
 
 void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
-	unsigned long fp, thread_base, ksp;
+	unsigned long fp, ksp;
 	struct thread_info *tp;
 	int count = 0;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -2173,7 +2173,6 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 		flushw_all();
 
 	fp = ksp + STACK_BIAS;
-	thread_base = (unsigned long) tp;
 
 	printk("Call Trace:\n");
 	do {
diff --git a/arch/sparc/kernel/una_asm_64.S b/arch/sparc/kernel/una_asm_64.S
index be183fe..1c8d332 100644
--- a/arch/sparc/kernel/una_asm_64.S
+++ b/arch/sparc/kernel/una_asm_64.S
@@ -127,7 +127,7 @@ do_int_load:
 	wr	%o5, 0x0, %asi
 	retl
 	 mov	0, %o0
-	.size	__do_int_load, .-__do_int_load
+	.size	do_int_load, .-do_int_load
 
 	.section	__ex_table,"a"
 	.word		4b, __retl_efault
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 0c1e678..92b557a 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -108,7 +108,7 @@ SECTIONS
 		__sun4v_2insn_patch_end = .;
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(SMP_CACHE_BYTES, PAGE_SIZE)
 
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
diff --git a/arch/sparc/lib/atomic32.c b/arch/sparc/lib/atomic32.c
index cbddeb3..d3c7a12 100644
--- a/arch/sparc/lib/atomic32.c
+++ b/arch/sparc/lib/atomic32.c
@@ -16,7 +16,7 @@
 #define ATOMIC_HASH(a)	(&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)])
 
 spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
-	[0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+	[0 ... (ATOMIC_HASH_SIZE-1)] = __SPIN_LOCK_UNLOCKED(__atomic_hash)
 };
 
 #else /* SMP */
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 5b836f5..b10ac4d 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -240,11 +240,10 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
 	 * only copy the information from the master page table,
 	 * nothing more.
 	 */
+	code = SEGV_MAPERR;
 	if (!ARCH_SUN4C && address >= TASK_SIZE)
 		goto vmalloc_fault;
 
-	code = SEGV_MAPERR;
-
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 92319aa..fe09fd8 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -650,7 +650,7 @@ static void srmmu_unmapiorange(unsigned long virt_addr, unsigned int len)
  * mappings on the kernel stack without any special code as we did
  * need on the sun4c.
  */
-static struct thread_info *srmmu_alloc_thread_info(void)
+static struct thread_info *srmmu_alloc_thread_info_node(int node)
 {
 	struct thread_info *ret;
 
@@ -2271,7 +2271,7 @@ void __init ld_mmu_srmmu(void)
 
 	BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(alloc_thread_info, srmmu_alloc_thread_info, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(alloc_thread_info_node, srmmu_alloc_thread_info_node, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(free_thread_info, srmmu_free_thread_info, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pte_to_pgoff, srmmu_pte_to_pgoff, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index b5137cc..a2350b5 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -922,7 +922,7 @@ static inline void garbage_collect(int entry)
 	free_locked_segment(BUCKET_ADDR(entry));
 }
 
-static struct thread_info *sun4c_alloc_thread_info(void)
+static struct thread_info *sun4c_alloc_thread_info_node(int node)
 {
 	unsigned long addr, pages;
 	int entry;
@@ -2155,7 +2155,7 @@ void __init ld_mmu_sun4c(void)
 	BTFIXUPSET_CALL(__swp_offset, sun4c_swp_offset, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__swp_entry, sun4c_swp_entry, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(alloc_thread_info, sun4c_alloc_thread_info, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(alloc_thread_info_node, sun4c_alloc_thread_info_node, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(free_thread_info, sun4c_free_thread_info, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/prom/misc_32.c b/arch/sparc/prom/misc_32.c
index 8c278c3..677b6a1 100644
--- a/arch/sparc/prom/misc_32.c
+++ b/arch/sparc/prom/misc_32.c
@@ -54,15 +54,11 @@ EXPORT_SYMBOL(prom_feval);
 void
 prom_cmdline(void)
 {
-	extern void install_obp_ticker(void);
-	extern void install_linux_ticker(void);
 	unsigned long flags;
 
 	spin_lock_irqsave(&prom_lock, flags);
-	install_obp_ticker();
 	(*(romvec->pv_abort))();
 	restore_current();
-	install_linux_ticker();
 	spin_unlock_irqrestore(&prom_lock, flags);
 	set_auxio(AUXIO_LED, 0);
 }
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 08948e4..f3b7870 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -1,5 +1,5 @@
 # For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
 
 config TILE
 	def_bool y
@@ -11,17 +11,18 @@ config TILE
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 # FIXME: investigate whether we need/want these options.
 #	select HAVE_IOREMAP_PROT
-#       select HAVE_OPTPROBES
-#       select HAVE_REGS_AND_STACK_ACCESS_API
-#       select HAVE_HW_BREAKPOINT
-#       select PERF_EVENTS
-#       select HAVE_USER_RETURN_NOTIFIER
-#       config NO_BOOTMEM
-#       config ARCH_SUPPORTS_DEBUG_PAGEALLOC
-#       config HUGETLB_PAGE_SIZE_VARIABLE
+#	select HAVE_OPTPROBES
+#	select HAVE_REGS_AND_STACK_ACCESS_API
+#	select HAVE_HW_BREAKPOINT
+#	select PERF_EVENTS
+#	select HAVE_USER_RETURN_NOTIFIER
+#	config NO_BOOTMEM
+#	config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+#	config HUGETLB_PAGE_SIZE_VARIABLE
 
 config MMU
 	def_bool y
@@ -39,7 +40,7 @@ config HAVE_SETUP_PER_CPU_AREA
 	def_bool y
 
 config NEED_PER_CPU_PAGE_FIRST_CHUNK
-        def_bool y
+	def_bool y
 
 config SYS_SUPPORTS_HUGETLBFS
 	def_bool y
@@ -201,12 +202,6 @@ config NODES_SHIFT
 	  By default, 2, i.e. 2^2 == 4 DDR2 controllers.
 	  In a system with more controllers, this value should be raised.
 
-# Need 16MB areas to enable hugetlb
-# See build-time check in arch/tile/mm/init.c.
-config FORCE_MAX_ZONEORDER
-	int
-	default 9
-
 choice
 	depends on !TILEGX
 	prompt "Memory split" if EXPERT
@@ -233,8 +228,12 @@ choice
 		bool "3.5G/0.5G user/kernel split"
 	config VMSPLIT_3G
 		bool "3G/1G user/kernel split"
-	config VMSPLIT_3G_OPT
-		bool "3G/1G user/kernel split (for full 1G low memory)"
+	config VMSPLIT_2_75G
+		bool "2.75G/1.25G user/kernel split (for full 1G low memory)"
+	config VMSPLIT_2_5G
+		bool "2.5G/1.5G user/kernel split"
+	config VMSPLIT_2_25G
+		bool "2.25G/1.75G user/kernel split"
 	config VMSPLIT_2G
 		bool "2G/2G user/kernel split"
 	config VMSPLIT_1G
@@ -245,7 +244,9 @@ config PAGE_OFFSET
 	hex
 	default 0xF0000000 if VMSPLIT_3_75G
 	default 0xE0000000 if VMSPLIT_3_5G
-	default 0xB0000000 if VMSPLIT_3G_OPT
+	default 0xB0000000 if VMSPLIT_2_75G
+	default 0xA0000000 if VMSPLIT_2_5G
+	default 0x90000000 if VMSPLIT_2_25G
 	default 0x80000000 if VMSPLIT_2G
 	default 0x40000000 if VMSPLIT_1G
 	default 0xC0000000
diff --git a/arch/tile/include/arch/interrupts_32.h b/arch/tile/include/arch/interrupts_32.h
index 9d0bfa7..96b5710 100644
--- a/arch/tile/include/arch/interrupts_32.h
+++ b/arch/tile/include/arch/interrupts_32.h
@@ -16,10 +16,11 @@
 #define __ARCH_INTERRUPTS_H__
 
 /** Mask for an interrupt. */
-#ifdef __ASSEMBLER__
 /* Note: must handle breaking interrupts into high and low words manually. */
-#define INT_MASK(intno) (1 << (intno))
-#else
+#define INT_MASK_LO(intno) (1 << (intno))
+#define INT_MASK_HI(intno) (1 << ((intno) - 32))
+
+#ifndef __ASSEMBLER__
 #define INT_MASK(intno) (1ULL << (intno))
 #endif
 
@@ -89,6 +90,7 @@
 
 #define NUM_INTERRUPTS 49
 
+#ifndef __ASSEMBLER__
 #define QUEUED_INTERRUPTS ( \
     INT_MASK(INT_MEM_ERROR) | \
     INT_MASK(INT_DMATLB_MISS) | \
@@ -301,4 +303,5 @@
     INT_MASK(INT_DOUBLE_FAULT) | \
     INT_MASK(INT_AUX_PERF_COUNT) | \
     0)
+#endif /* !__ASSEMBLER__ */
 #endif /* !__ARCH_INTERRUPTS_H__ */
diff --git a/arch/tile/include/arch/sim.h b/arch/tile/include/arch/sim.h
index 74b7c16..e54b7b0 100644
--- a/arch/tile/include/arch/sim.h
+++ b/arch/tile/include/arch/sim.h
@@ -152,16 +152,33 @@ sim_dump(unsigned int mask)
 /**
  * Print a string to the simulator stdout.
  *
- * @param str The string to be written; a newline is automatically added.
+ * @param str The string to be written.
+ */
+static __inline void
+sim_print(const char* str)
+{
+  for ( ; *str != '\0'; str++)
+  {
+    __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+                 (*str << _SIM_CONTROL_OPERATOR_BITS));
+  }
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+               (SIM_PUTC_FLUSH_BINARY << _SIM_CONTROL_OPERATOR_BITS));
+}
+
+
+/**
+ * Print a string to the simulator stdout.
+ *
+ * @param str The string to be written (a newline is automatically added).
  */
 static __inline void
 sim_print_string(const char* str)
 {
-  int i;
-  for (i = 0; str[i] != 0; i++)
+  for ( ; *str != '\0'; str++)
   {
     __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
-                 (str[i] << _SIM_CONTROL_OPERATOR_BITS));
+                 (*str << _SIM_CONTROL_OPERATOR_BITS));
   }
   __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
                (SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS));
@@ -203,7 +220,7 @@ sim_command(const char* str)
  * we are passing to the simulator are actually valid in the registers
  * (i.e. returned from memory) prior to the SIM_CONTROL spr.
  */
-static __inline int _sim_syscall0(int val)
+static __inline long _sim_syscall0(int val)
 {
   long result;
   __asm__ __volatile__ ("mtspr SIM_CONTROL, r0"
@@ -211,7 +228,7 @@ static __inline int _sim_syscall0(int val)
   return result;
 }
 
-static __inline int _sim_syscall1(int val, long arg1)
+static __inline long _sim_syscall1(int val, long arg1)
 {
   long result;
   __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
@@ -219,7 +236,7 @@ static __inline int _sim_syscall1(int val, long arg1)
   return result;
 }
 
-static __inline int _sim_syscall2(int val, long arg1, long arg2)
+static __inline long _sim_syscall2(int val, long arg1, long arg2)
 {
   long result;
   __asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
@@ -233,7 +250,7 @@ static __inline int _sim_syscall2(int val, long arg1, long arg2)
    the register values for arguments 3 and up may still be in flight
    to the core from a stack frame reload. */
 
-static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3)
+static __inline long _sim_syscall3(int val, long arg1, long arg2, long arg3)
 {
   long result;
   __asm__ __volatile__ ("{ and zero, r3, r3 };"
@@ -244,7 +261,7 @@ static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3)
   return result;
 }
 
-static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3,
+static __inline long _sim_syscall4(int val, long arg1, long arg2, long arg3,
                                   long arg4)
 {
   long result;
@@ -256,7 +273,7 @@ static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3,
   return result;
 }
 
-static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
+static __inline long _sim_syscall5(int val, long arg1, long arg2, long arg3,
                                   long arg4, long arg5)
 {
   long result;
@@ -268,7 +285,6 @@ static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
   return result;
 }
 
-
 /**
  * Make a special syscall to the simulator itself, if running under
  * simulation. This is used as the implementation of other functions
@@ -281,7 +297,8 @@ static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
  */
 #define _sim_syscall(syscall_num, nr, args...) \
   _sim_syscall##nr( \
-    ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, args)
+    ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, \
+    ##args)
 
 
 /* Values for the "access_mask" parameters below. */
@@ -365,6 +382,13 @@ sim_validate_lines_evicted(unsigned long long pa, unsigned long length)
 }
 
 
+/* Return the current CPU speed in cycles per second. */
+static __inline long
+sim_query_cpu_speed(void)
+{
+  return _sim_syscall(SIM_SYSCALL_QUERY_CPU_SPEED, 0);
+}
+
 #endif /* !__DOXYGEN__ */
 
 
diff --git a/arch/tile/include/arch/sim_def.h b/arch/tile/include/arch/sim_def.h
index 7a17082..4b44a2b 100644
--- a/arch/tile/include/arch/sim_def.h
+++ b/arch/tile/include/arch/sim_def.h
@@ -243,6 +243,9 @@
  */
 #define SIM_SYSCALL_VALIDATE_LINES_EVICTED 5
 
+/** Syscall number for sim_query_cpu_speed(). */
+#define SIM_SYSCALL_QUERY_CPU_SPEED 6
+
 
 /*
  * Bit masks which can be shifted by 8, combined with
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 3b8f55b..849ab2f 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
 header-y += ucontext.h
+header-y += hardwall.h
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h
index b8c49f9..75a1602 100644
--- a/arch/tile/include/asm/atomic.h
+++ b/arch/tile/include/asm/atomic.h
@@ -32,7 +32,7 @@
  */
 static inline int atomic_read(const atomic_t *v)
 {
-       return v->counter;
+	return ACCESS_ONCE(v->counter);
 }
 
 /**
diff --git a/arch/tile/include/asm/bitops_32.h b/arch/tile/include/asm/bitops_32.h
index 7a93c00..2638be5 100644
--- a/arch/tile/include/asm/bitops_32.h
+++ b/arch/tile/include/asm/bitops_32.h
@@ -122,7 +122,7 @@ static inline int test_and_change_bit(unsigned nr,
 	return (_atomic_xor(addr, mask) & mask) != 0;
 }
 
-/* See discussion at smp_mb__before_atomic_dec() in <asm/atomic.h>. */
+/* See discussion at smp_mb__before_atomic_dec() in <asm/atomic_32.h>. */
 #define smp_mb__before_clear_bit()	smp_mb()
 #define smp_mb__after_clear_bit()	do {} while (0)
 
diff --git a/arch/tile/include/asm/cache.h b/arch/tile/include/asm/cache.h
index 08a2815..392e533 100644
--- a/arch/tile/include/asm/cache.h
+++ b/arch/tile/include/asm/cache.h
@@ -40,7 +40,7 @@
 #define INTERNODE_CACHE_BYTES   L2_CACHE_BYTES
 
 /* Group together read-mostly things to avoid cache false sharing */
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 /*
  * Attribute for data that is kept read/write coherent until the end of
diff --git a/arch/tile/include/asm/cacheflush.h b/arch/tile/include/asm/cacheflush.h
index 14a3f85..12fb0fb 100644
--- a/arch/tile/include/asm/cacheflush.h
+++ b/arch/tile/include/asm/cacheflush.h
@@ -138,55 +138,12 @@ static inline void finv_buffer(void *buffer, size_t size)
 }
 
 /*
- * Flush & invalidate a VA range that is homed remotely on a single core,
- * waiting until the memory controller holds the flushed values.
+ * Flush and invalidate a VA range that is homed remotely, waiting
+ * until the memory controller holds the flushed values.  If "hfh" is
+ * true, we will do a more expensive flush involving additional loads
+ * to make sure we have touched all the possible home cpus of a buffer
+ * that is homed with "hash for home".
  */
-static inline void finv_buffer_remote(void *buffer, size_t size)
-{
-	char *p;
-	int i;
-
-	/*
-	 * Flush and invalidate the buffer out of the local L1/L2
-	 * and request the home cache to flush and invalidate as well.
-	 */
-	__finv_buffer(buffer, size);
-
-	/*
-	 * Wait for the home cache to acknowledge that it has processed
-	 * all the flush-and-invalidate requests.  This does not mean
-	 * that the flushed data has reached the memory controller yet,
-	 * but it does mean the home cache is processing the flushes.
-	 */
-	__insn_mf();
-
-	/*
-	 * Issue a load to the last cache line, which can't complete
-	 * until all the previously-issued flushes to the same memory
-	 * controller have also completed.  If we weren't striping
-	 * memory, that one load would be sufficient, but since we may
-	 * be, we also need to back up to the last load issued to
-	 * another memory controller, which would be the point where
-	 * we crossed an 8KB boundary (the granularity of striping
-	 * across memory controllers).  Keep backing up and doing this
-	 * until we are before the beginning of the buffer, or have
-	 * hit all the controllers.
-	 */
-	for (i = 0, p = (char *)buffer + size - 1;
-	     i < (1 << CHIP_LOG_NUM_MSHIMS()) && p >= (char *)buffer;
-	     ++i) {
-		const unsigned long STRIPE_WIDTH = 8192;
-
-		/* Force a load instruction to issue. */
-		*(volatile char *)p;
-
-		/* Jump to end of previous stripe. */
-		p -= STRIPE_WIDTH;
-		p = (char *)((unsigned long)p | (STRIPE_WIDTH - 1));
-	}
-
-	/* Wait for the loads (and thus flushes) to have completed. */
-	__insn_mf();
-}
+void finv_buffer_remote(void *buffer, size_t size, int hfh);
 
 #endif /* _ASM_TILE_CACHEFLUSH_H */
diff --git a/arch/tile/include/asm/edac.h b/arch/tile/include/asm/edac.h
new file mode 100644
index 0000000..87fc83e
--- /dev/null
+++ b/arch/tile/include/asm/edac.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _ASM_TILE_EDAC_H
+#define _ASM_TILE_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static inline void atomic_scrub(void *va, u32 size)
+{
+	/*
+	 * These is nothing to be done here because CE is
+	 * corrected by the mshim.
+	 */
+	return;
+}
+
+#endif /* _ASM_TILE_EDAC_H */
diff --git a/arch/tile/include/asm/futex.h b/arch/tile/include/asm/futex.h
index fe0d10d..d03ec12 100644
--- a/arch/tile/include/asm/futex.h
+++ b/arch/tile/include/asm/futex.h
@@ -29,16 +29,16 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 
-extern struct __get_user futex_set(int __user *v, int i);
-extern struct __get_user futex_add(int __user *v, int n);
-extern struct __get_user futex_or(int __user *v, int n);
-extern struct __get_user futex_andn(int __user *v, int n);
-extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
+extern struct __get_user futex_set(u32 __user *v, int i);
+extern struct __get_user futex_add(u32 __user *v, int n);
+extern struct __get_user futex_or(u32 __user *v, int n);
+extern struct __get_user futex_andn(u32 __user *v, int n);
+extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
 
 #ifndef __tilegx__
-extern struct __get_user futex_xor(int __user *v, int n);
+extern struct __get_user futex_xor(u32 __user *v, int n);
 #else
-static inline struct __get_user futex_xor(int __user *uaddr, int n)
+static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
 {
 	struct __get_user asm_ret = __get_user_4(uaddr);
 	if (!asm_ret.err) {
@@ -53,7 +53,7 @@ static inline struct __get_user futex_xor(int __user *uaddr, int n)
 }
 #endif
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -65,7 +65,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -119,16 +119,17 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	struct __get_user asm_ret;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
-	return asm_ret.err ? asm_ret.err : asm_ret.val;
+	*uval = asm_ret.val;
+	return asm_ret.err;
 }
 
 #ifndef __tilegx__
diff --git a/arch/tile/include/asm/hugetlb.h b/arch/tile/include/asm/hugetlb.h
index 0521c27..d396d18 100644
--- a/arch/tile/include/asm/hugetlb.h
+++ b/arch/tile/include/asm/hugetlb.h
@@ -54,7 +54,7 @@ static inline void hugetlb_free_pgd_range(struct mmu_gather *tlb,
 static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 				   pte_t *ptep, pte_t pte)
 {
-	set_pte_order(ptep, pte, HUGETLB_PAGE_ORDER);
+	set_pte(ptep, pte);
 }
 
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index 641e4ff..5db0ce5 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -18,6 +18,8 @@
 #include <arch/interrupts.h>
 #include <arch/chip.h>
 
+#if !defined(__tilegx__) && defined(__ASSEMBLY__)
+
 /*
  * The set of interrupts we want to allow when interrupts are nominally
  * disabled.  The remainder are effectively "NMI" interrupts from
@@ -25,6 +27,16 @@
  * interrupts (aka "non-queued") are not blocked by the mask in any case.
  */
 #if CHIP_HAS_AUX_PERF_COUNTERS()
+#define LINUX_MASKABLE_INTERRUPTS_HI \
+       (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT)))
+#else
+#define LINUX_MASKABLE_INTERRUPTS_HI \
+       (~(INT_MASK_HI(INT_PERF_COUNT)))
+#endif
+
+#else
+
+#if CHIP_HAS_AUX_PERF_COUNTERS()
 #define LINUX_MASKABLE_INTERRUPTS \
 	(~(INT_MASK(INT_PERF_COUNT) | INT_MASK(INT_AUX_PERF_COUNT)))
 #else
@@ -32,6 +44,8 @@
 	(~(INT_MASK(INT_PERF_COUNT)))
 #endif
 
+#endif
+
 #ifndef __ASSEMBLY__
 
 /* NOTE: we can't include <linux/percpu.h> due to #include dependencies. */
@@ -224,11 +238,11 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 #define IRQ_DISABLE(tmp0, tmp1)					\
 	{							\
 	 movei  tmp0, -1;					\
-	 moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS)		\
+	 moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS_HI)	\
 	};							\
 	{							\
 	 mtspr  SPR_INTERRUPT_MASK_SET_K_0, tmp0;		\
-	 auli   tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS)	\
+	 auli   tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS_HI)	\
 	};							\
 	mtspr   SPR_INTERRUPT_MASK_SET_K_1, tmp1
 
diff --git a/arch/tile/include/asm/page.h b/arch/tile/include/asm/page.h
index 7979a45..3eb5352 100644
--- a/arch/tile/include/asm/page.h
+++ b/arch/tile/include/asm/page.h
@@ -16,10 +16,11 @@
 #define _ASM_TILE_PAGE_H
 
 #include <linux/const.h>
+#include <hv/pagesize.h>
 
 /* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */
-#define PAGE_SHIFT	16
-#define HPAGE_SHIFT	24
+#define PAGE_SHIFT	HV_LOG2_PAGE_SIZE_SMALL
+#define HPAGE_SHIFT	HV_LOG2_PAGE_SIZE_LARGE
 
 #define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
 #define HPAGE_SIZE	(_AC(1, UL) << HPAGE_SHIFT)
@@ -29,25 +30,18 @@
 
 #ifdef __KERNEL__
 
-#include <hv/hypervisor.h>
-#include <arch/chip.h>
-
 /*
- * The {,H}PAGE_SHIFT values must match the HV_LOG2_PAGE_SIZE_xxx
- * definitions in <hv/hypervisor.h>.  We validate this at build time
- * here, and again at runtime during early boot.  We provide a
- * separate definition since userspace doesn't have <hv/hypervisor.h>.
- *
- * Be careful to distinguish PAGE_SHIFT from HV_PTE_INDEX_PFN, since
- * they are the same on i386 but not TILE.
+ * If the Kconfig doesn't specify, set a maximum zone order that
+ * is enough so that we can create huge pages from small pages given
+ * the respective sizes of the two page types.  See <linux/mmzone.h>.
  */
-#if HV_LOG2_PAGE_SIZE_SMALL != PAGE_SHIFT
-# error Small page size mismatch in Linux
-#endif
-#if HV_LOG2_PAGE_SIZE_LARGE != HPAGE_SHIFT
-# error Huge page size mismatch in Linux
+#ifndef CONFIG_FORCE_MAX_ZONEORDER
+#define CONFIG_FORCE_MAX_ZONEORDER (HPAGE_SHIFT - PAGE_SHIFT + 1)
 #endif
 
+#include <hv/hypervisor.h>
+#include <arch/chip.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -81,12 +75,6 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
  * Hypervisor page tables are made of the same basic structure.
  */
 
-typedef __u64 pteval_t;
-typedef __u64 pmdval_t;
-typedef __u64 pudval_t;
-typedef __u64 pgdval_t;
-typedef __u64 pgprotval_t;
-
 typedef HV_PTE pte_t;
 typedef HV_PTE pgd_t;
 typedef HV_PTE pgprot_t;
diff --git a/arch/tile/include/asm/pgalloc.h b/arch/tile/include/asm/pgalloc.h
index cf52791..e919c0b 100644
--- a/arch/tile/include/asm/pgalloc.h
+++ b/arch/tile/include/asm/pgalloc.h
@@ -41,9 +41,9 @@
 static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
 {
 #ifdef CONFIG_64BIT
-	set_pte_order(pmdp, pmd, L2_USER_PGTABLE_ORDER);
+	set_pte(pmdp, pmd);
 #else
-	set_pte_order(&pmdp->pud.pgd, pmd.pud.pgd, L2_USER_PGTABLE_ORDER);
+	set_pte(&pmdp->pud.pgd, pmd.pud.pgd);
 #endif
 }
 
@@ -100,6 +100,9 @@ pte_t *get_prealloc_pte(unsigned long pfn);
 /* During init, we can shatter kernel huge pages if needed. */
 void shatter_pmd(pmd_t *pmd);
 
+/* After init, a more complex technique is required. */
+void shatter_huge_page(unsigned long addr);
+
 #ifdef __tilegx__
 /* We share a single page allocator for both L1 and L2 page tables. */
 #if HV_L1_SIZE != HV_L2_SIZE
diff --git a/arch/tile/include/asm/pgtable.h b/arch/tile/include/asm/pgtable.h
index a6604e9..1a20b7e 100644
--- a/arch/tile/include/asm/pgtable.h
+++ b/arch/tile/include/asm/pgtable.h
@@ -233,15 +233,23 @@ static inline void __pte_clear(pte_t *ptep)
 #define pgd_ERROR(e) \
 	pr_err("%s:%d: bad pgd 0x%016llx.\n", __FILE__, __LINE__, pgd_val(e))
 
+/* Return PA and protection info for a given kernel VA. */
+int va_to_cpa_and_pte(void *va, phys_addr_t *cpa, pte_t *pte);
+
+/*
+ * __set_pte() ensures we write the 64-bit PTE with 32-bit words in
+ * the right order on 32-bit platforms and also allows us to write
+ * hooks to check valid PTEs, etc., if we want.
+ */
+void __set_pte(pte_t *ptep, pte_t pte);
+
 /*
- * set_pte_order() sets the given PTE and also sanity-checks the
+ * set_pte() sets the given PTE and also sanity-checks the
  * requested PTE against the page homecaching.  Unspecified parts
  * of the PTE are filled in when it is written to memory, i.e. all
  * caching attributes if "!forcecache", or the home cpu if "anyhome".
  */
-extern void set_pte_order(pte_t *ptep, pte_t pte, int order);
-
-#define set_pte(ptep, pteval) set_pte_order(ptep, pteval, 0)
+extern void set_pte(pte_t *ptep, pte_t pte);
 #define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
 
@@ -293,21 +301,6 @@ extern void check_mm_caching(struct mm_struct *prev, struct mm_struct *next);
 #define __swp_entry_to_pte(swp)	((pte_t) { (((long long) ((swp).val)) << 32) })
 
 /*
- * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
- *
- *  dst - pointer to pgd range anwhere on a pgd page
- *  src - ""
- *  count - the number of pgds to copy.
- *
- * dst and src can be on the same page, but the range must not overlap,
- * and must not cross a page boundary.
- */
-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
-{
-       memcpy(dst, src, count * sizeof(pgd_t));
-}
-
-/*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
diff --git a/arch/tile/include/asm/pgtable_32.h b/arch/tile/include/asm/pgtable_32.h
index 53ec348..9f98529 100644
--- a/arch/tile/include/asm/pgtable_32.h
+++ b/arch/tile/include/asm/pgtable_32.h
@@ -24,6 +24,7 @@
 #define PGDIR_SIZE	HV_PAGE_SIZE_LARGE
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 #define PTRS_PER_PGD	(1 << (32 - PGDIR_SHIFT))
+#define SIZEOF_PGD	(PTRS_PER_PGD * sizeof(pgd_t))
 
 /*
  * The level-2 index is defined by the difference between the huge
@@ -33,6 +34,7 @@
  * this nomenclature is somewhat confusing.
  */
 #define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL))
+#define SIZEOF_PTE	(PTRS_PER_PTE * sizeof(pte_t))
 
 #ifndef __ASSEMBLY__
 
@@ -94,7 +96,6 @@ static inline int pgd_addr_invalid(unsigned long addr)
  */
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 
 extern int ptep_test_and_clear_young(struct vm_area_struct *,
 				     unsigned long addr, pte_t *);
@@ -110,6 +111,11 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
 	return pte;
 }
 
+static inline void __set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+	set_pte(&pmdp->pud.pgd, pmdval.pud.pgd);
+}
+
 /* Create a pmd from a PTFN. */
 static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot)
 {
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index a9e7c87..e688947 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -269,7 +269,6 @@ extern char chip_model[64];
 /* Data on which physical memory controller corresponds to which NUMA node. */
 extern int node_controller[];
 
-
 /* Do we dump information to the console when a user application crashes? */
 extern int show_crashinfo;
 
diff --git a/arch/tile/include/asm/ptrace.h b/arch/tile/include/asm/ptrace.h
index ac6d343..6be2246 100644
--- a/arch/tile/include/asm/ptrace.h
+++ b/arch/tile/include/asm/ptrace.h
@@ -141,6 +141,9 @@ struct single_step_state {
 /* Single-step the instruction at regs->pc */
 extern void single_step_once(struct pt_regs *regs);
 
+/* Clean up after execve(). */
+extern void single_step_execve(void);
+
 struct task_struct;
 
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
diff --git a/arch/tile/include/asm/spinlock_32.h b/arch/tile/include/asm/spinlock_32.h
index 88efdde..a8f2c6e 100644
--- a/arch/tile/include/asm/spinlock_32.h
+++ b/arch/tile/include/asm/spinlock_32.h
@@ -78,13 +78,6 @@ void arch_spin_unlock_wait(arch_spinlock_t *lock);
 #define _RD_COUNT_SHIFT 24
 #define _RD_COUNT_WIDTH 8
 
-/* Internal functions; do not use. */
-void arch_read_lock_slow(arch_rwlock_t *, u32);
-int arch_read_trylock_slow(arch_rwlock_t *);
-void arch_read_unlock_slow(arch_rwlock_t *);
-void arch_write_lock_slow(arch_rwlock_t *, u32);
-void arch_write_unlock_slow(arch_rwlock_t *, u32);
-
 /**
  * arch_read_can_lock() - would read_trylock() succeed?
  */
@@ -104,94 +97,32 @@ static inline int arch_write_can_lock(arch_rwlock_t *rwlock)
 /**
  * arch_read_lock() - acquire a read lock.
  */
-static inline void arch_read_lock(arch_rwlock_t *rwlock)
-{
-	u32 val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val << _RD_COUNT_WIDTH)) {
-		arch_read_lock_slow(rwlock, val);
-		return;
-	}
-	rwlock->lock = val + (1 << _RD_COUNT_SHIFT);
-}
+void arch_read_lock(arch_rwlock_t *rwlock);
 
 /**
- * arch_read_lock() - acquire a write lock.
+ * arch_write_lock() - acquire a write lock.
  */
-static inline void arch_write_lock(arch_rwlock_t *rwlock)
-{
-	u32 val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val != 0)) {
-		arch_write_lock_slow(rwlock, val);
-		return;
-	}
-	rwlock->lock = 1 << _WR_NEXT_SHIFT;
-}
+void arch_write_lock(arch_rwlock_t *rwlock);
 
 /**
  * arch_read_trylock() - try to acquire a read lock.
  */
-static inline int arch_read_trylock(arch_rwlock_t *rwlock)
-{
-	int locked;
-	u32 val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val & 1))
-		return arch_read_trylock_slow(rwlock);
-	locked = (val << _RD_COUNT_WIDTH) == 0;
-	rwlock->lock = val + (locked << _RD_COUNT_SHIFT);
-	return locked;
-}
+int arch_read_trylock(arch_rwlock_t *rwlock);
 
 /**
  * arch_write_trylock() - try to acquire a write lock.
  */
-static inline int arch_write_trylock(arch_rwlock_t *rwlock)
-{
-	u32 val = __insn_tns((int *)&rwlock->lock);
-
-	/*
-	 * If a tns is in progress, or there's a waiting or active locker,
-	 * or active readers, we can't take the lock, so give up.
-	 */
-	if (unlikely(val != 0)) {
-		if (!(val & 1))
-			rwlock->lock = val;
-		return 0;
-	}
-
-	/* Set the "next" field to mark it locked. */
-	rwlock->lock = 1 << _WR_NEXT_SHIFT;
-	return 1;
-}
+int arch_write_trylock(arch_rwlock_t *rwlock);
 
 /**
  * arch_read_unlock() - release a read lock.
  */
-static inline void arch_read_unlock(arch_rwlock_t *rwlock)
-{
-	u32 val;
-	mb();  /* guarantee anything modified under the lock is visible */
-	val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val & 1)) {
-		arch_read_unlock_slow(rwlock);
-		return;
-	}
-	rwlock->lock = val - (1 << _RD_COUNT_SHIFT);
-}
+void arch_read_unlock(arch_rwlock_t *rwlock);
 
 /**
  * arch_write_unlock() - release a write lock.
  */
-static inline void arch_write_unlock(arch_rwlock_t *rwlock)
-{
-	u32 val;
-	mb();  /* guarantee anything modified under the lock is visible */
-	val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val != (1 << _WR_NEXT_SHIFT))) {
-		arch_write_unlock_slow(rwlock, val);
-		return;
-	}
-	rwlock->lock = 0;
-}
+void arch_write_unlock(arch_rwlock_t *rwlock);
 
 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
diff --git a/arch/tile/include/asm/stack.h b/arch/tile/include/asm/stack.h
index f908473..4d97a2d 100644
--- a/arch/tile/include/asm/stack.h
+++ b/arch/tile/include/asm/stack.h
@@ -18,13 +18,14 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <asm/backtrace.h>
+#include <asm/page.h>
 #include <hv/hypervisor.h>
 
 /* Everything we need to keep track of a backtrace iteration */
 struct KBacktraceIterator {
 	BacktraceIterator it;
 	struct task_struct *task;     /* task we are backtracing */
-	HV_PTE *pgtable;	      /* page table for user space access */
+	pte_t *pgtable;		      /* page table for user space access */
 	int end;		      /* iteration complete. */
 	int new_context;              /* new context is starting */
 	int profile;                  /* profiling, so stop on async intrpt */
diff --git a/arch/tile/include/asm/system.h b/arch/tile/include/asm/system.h
index 5388850..23d1842 100644
--- a/arch/tile/include/asm/system.h
+++ b/arch/tile/include/asm/system.h
@@ -90,7 +90,24 @@
 #endif
 
 #if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-int __mb_incoherent(void);  /* Helper routine for mb_incoherent(). */
+#include <hv/syscall_public.h>
+/*
+ * Issue an uncacheable load to each memory controller, then
+ * wait until those loads have completed.
+ */
+static inline void __mb_incoherent(void)
+{
+	long clobber_r10;
+	asm volatile("swint2"
+		     : "=R10" (clobber_r10)
+		     : "R10" (HV_SYS_fence_incoherent)
+		     : "r0", "r1", "r2", "r3", "r4",
+		       "r5", "r6", "r7", "r8", "r9",
+		       "r11", "r12", "r13", "r14",
+		       "r15", "r16", "r17", "r18", "r19",
+		       "r20", "r21", "r22", "r23", "r24",
+		       "r25", "r26", "r27", "r28", "r29");
+}
 #endif
 
 /* Fence to guarantee visibility of stores to incoherent memory. */
diff --git a/arch/tile/include/asm/thread_info.h b/arch/tile/include/asm/thread_info.h
index 3872f2b..3405b52 100644
--- a/arch/tile/include/asm/thread_info.h
+++ b/arch/tile/include/asm/thread_info.h
@@ -68,6 +68,7 @@ struct thread_info {
 #else
 #define THREAD_SIZE_ORDER (0)
 #endif
+#define THREAD_SIZE_PAGES (1 << THREAD_SIZE_ORDER)
 
 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define LOG2_THREAD_SIZE (PAGE_SHIFT + THREAD_SIZE_ORDER)
@@ -83,7 +84,7 @@ register unsigned long stack_pointer __asm__("sp");
   ((struct thread_info *)(stack_pointer & -THREAD_SIZE))
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-extern struct thread_info *alloc_thread_info(struct task_struct *task);
+extern struct thread_info *alloc_thread_info_node(struct task_struct *task, int node);
 extern void free_thread_info(struct thread_info *info);
 
 /* Sit on a nap instruction until interrupted. */
diff --git a/arch/tile/include/asm/timex.h b/arch/tile/include/asm/timex.h
index 3baf5fc..29921f0 100644
--- a/arch/tile/include/asm/timex.h
+++ b/arch/tile/include/asm/timex.h
@@ -38,6 +38,9 @@ static inline cycles_t get_cycles(void)
 
 cycles_t get_clock_rate(void);
 
+/* Convert nanoseconds to core clock cycles. */
+cycles_t ns2cycles(unsigned long nsecs);
+
 /* Called at cpu initialization to set some low-level constants. */
 void setup_clock(void);
 
diff --git a/arch/tile/include/hv/drv_mshim_intf.h b/arch/tile/include/hv/drv_mshim_intf.h
new file mode 100644
index 0000000..c6ef3bd
--- /dev/null
+++ b/arch/tile/include/hv/drv_mshim_intf.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * @file drv_mshim_intf.h
+ * Interface definitions for the Linux EDAC memory controller driver.
+ */
+
+#ifndef _SYS_HV_INCLUDE_DRV_MSHIM_INTF_H
+#define _SYS_HV_INCLUDE_DRV_MSHIM_INTF_H
+
+/** Number of memory controllers in the public API. */
+#define TILE_MAX_MSHIMS 4
+
+/** Memory info under each memory controller. */
+struct mshim_mem_info
+{
+  uint64_t mem_size;     /**< Total memory size in bytes. */
+  uint8_t mem_type;      /**< Memory type, DDR2 or DDR3. */
+  uint8_t mem_ecc;       /**< Memory supports ECC. */
+};
+
+/**
+ * DIMM error structure.
+ * For now, only correctable errors are counted and the mshim doesn't record
+ * the error PA. HV takes panic upon uncorrectable errors.
+ */
+struct mshim_mem_error
+{
+  uint32_t sbe_count;     /**< Number of single-bit errors. */
+};
+
+/** Read this offset to get the memory info per mshim. */
+#define MSHIM_MEM_INFO_OFF 0x100
+
+/** Read this offset to check DIMM error. */
+#define MSHIM_MEM_ERROR_OFF 0x200
+
+#endif /* _SYS_HV_INCLUDE_DRV_MSHIM_INTF_H */
diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h
index f672544..1b8bf03 100644
--- a/arch/tile/include/hv/hypervisor.h
+++ b/arch/tile/include/hv/hypervisor.h
@@ -338,9 +338,10 @@ typedef int HV_Errno;
 #define HV_ENOTREADY   -812  /**< Device not ready */
 #define HV_EIO         -813  /**< I/O error */
 #define HV_ENOMEM      -814  /**< Out of memory */
+#define HV_EAGAIN      -815  /**< Try again */
 
 #define HV_ERR_MAX     -801  /**< Largest HV error code */
-#define HV_ERR_MIN     -814  /**< Smallest HV error code */
+#define HV_ERR_MIN     -815  /**< Smallest HV error code */
 
 #ifndef __ASSEMBLER__
 
@@ -867,6 +868,43 @@ typedef struct
  */
 HV_PhysAddrRange hv_inquire_physical(int idx);
 
+/** Possible DIMM types. */
+typedef enum
+{
+  NO_DIMM                    = 0,  /**< No DIMM */
+  DDR2                       = 1,  /**< DDR2 */
+  DDR3                       = 2   /**< DDR3 */
+} HV_DIMM_Type;
+
+#ifdef __tilegx__
+
+/** Log2 of minimum DIMM bytes supported by the memory controller. */
+#define HV_MSH_MIN_DIMM_SIZE_SHIFT 29
+
+/** Max number of DIMMs contained by one memory controller. */
+#define HV_MSH_MAX_DIMMS 8
+
+#else
+
+/** Log2 of minimum DIMM bytes supported by the memory controller. */
+#define HV_MSH_MIN_DIMM_SIZE_SHIFT 26
+
+/** Max number of DIMMs contained by one memory controller. */
+#define HV_MSH_MAX_DIMMS 2
+
+#endif
+
+/** Number of bits to right-shift to get the DIMM type. */
+#define HV_DIMM_TYPE_SHIFT 0
+
+/** Bits to mask to get the DIMM type. */
+#define HV_DIMM_TYPE_MASK 0xf
+
+/** Number of bits to right-shift to get the DIMM size. */
+#define HV_DIMM_SIZE_SHIFT 4
+
+/** Bits to mask to get the DIMM size. */
+#define HV_DIMM_SIZE_MASK 0xf
 
 /** Memory controller information. */
 typedef struct
@@ -964,6 +1002,11 @@ HV_ASIDRange hv_inquire_asid(int idx);
 
 /** Waits for at least the specified number of nanoseconds then returns.
  *
+ * NOTE: this deprecated function currently assumes a 750 MHz clock,
+ * and is thus not generally suitable for use.  New code should call
+ * hv_sysconf(HV_SYSCONF_CPU_SPEED), compute a cycle count to wait for,
+ * and delay by looping while checking the cycle counter SPR.
+ *
  * @param nanosecs The number of nanoseconds to sleep.
  */
 void hv_nanosleep(int nanosecs);
@@ -1038,6 +1081,7 @@ int hv_console_write(HV_VirtAddr bytes, int len);
  *  downcall:
  *
  *  INT_MESSAGE_RCV_DWNCL   (hypervisor message available)
+ *  INT_DEV_INTR_DWNCL      (device interrupt)
  *  INT_DMATLB_MISS_DWNCL   (DMA TLB miss)
  *  INT_SNITLB_MISS_DWNCL   (SNI TLB miss)
  *  INT_DMATLB_ACCESS_DWNCL (DMA TLB access violation)
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index fd8dc42..431e9ae 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -38,12 +38,6 @@ STD_ENTRY(kernel_execve)
 	jrp lr
 	STD_ENDPROC(kernel_execve)
 
-/* Delay a fixed number of cycles. */
-STD_ENTRY(__delay)
-	{ addi r0, r0, -1; bnzt r0, . }
-	jrp lr
-	STD_ENDPROC(__delay)
-
 /*
  * We don't run this function directly, but instead copy it to a page
  * we map into every user process.  See vdso_setup().
@@ -97,23 +91,17 @@ STD_ENTRY(smp_nap)
 
 /*
  * Enable interrupts racelessly and then nap until interrupted.
+ * Architecturally, we are guaranteed that enabling interrupts via
+ * mtspr to INTERRUPT_CRITICAL_SECTION only interrupts at the next PC.
  * This function's _cpu_idle_nap address is special; see intvec.S.
  * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and
  * as a result return to the function that called _cpu_idle().
  */
 STD_ENTRY(_cpu_idle)
-	{
-	 lnk r0
-	 movei r1, KERNEL_PL
-	}
-	{
-	 addli r0, r0, _cpu_idle_nap - .
-	 mtspr INTERRUPT_CRITICAL_SECTION, r1
-	}
+	movei r1, 1
+	mtspr INTERRUPT_CRITICAL_SECTION, r1
 	IRQ_ENABLE(r2, r3)             /* unmask, but still with ICS set */
-	mtspr SPR_EX_CONTEXT_K_1, r1   /* Kernel PL, ICS clear */
-	mtspr SPR_EX_CONTEXT_K_0, r0
-	iret
+	mtspr INTERRUPT_CRITICAL_SECTION, zero
 	.global _cpu_idle_nap
 _cpu_idle_nap:
 	nap
diff --git a/arch/tile/kernel/head_32.S b/arch/tile/kernel/head_32.S
index 90e7c44..1a39b7c 100644
--- a/arch/tile/kernel/head_32.S
+++ b/arch/tile/kernel/head_32.S
@@ -133,7 +133,7 @@ ENTRY(_start)
 	}
 	ENDPROC(_start)
 
-.section ".bss.page_aligned","w"
+__PAGE_ALIGNED_BSS
 	.align PAGE_SIZE
 ENTRY(empty_zero_page)
 	.fill PAGE_SIZE,1,0
@@ -145,10 +145,10 @@ ENTRY(empty_zero_page)
 	.endif
 	.word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \
 	      (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE)
-	.word (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN)
+	.word (\bits1) | (HV_CPA_TO_PFN(\cpa) << (HV_PTE_INDEX_PFN - 32))
 	.endm
 
-.section ".data.page_aligned","wa"
+__PAGE_ALIGNED_DATA
 	.align PAGE_SIZE
 ENTRY(swapper_pg_dir)
 	/*
@@ -158,12 +158,14 @@ ENTRY(swapper_pg_dir)
 	 */
 	.set addr, 0
 	.rept (MEM_USER_INTRPT - PAGE_OFFSET) >> PGDIR_SHIFT
-	PTE addr + PAGE_OFFSET, addr, HV_PTE_READABLE | HV_PTE_WRITABLE
+	PTE addr + PAGE_OFFSET, addr, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
+				      (1 << (HV_PTE_INDEX_WRITABLE - 32))
 	.set addr, addr + PGDIR_SIZE
 	.endr
 
 	/* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */
-	PTE MEM_SV_INTRPT, 0, HV_PTE_READABLE | HV_PTE_EXECUTABLE
+	PTE MEM_SV_INTRPT, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
+			      (1 << (HV_PTE_INDEX_EXECUTABLE - 32))
 	.org swapper_pg_dir + HV_L1_SIZE
 	END(swapper_pg_dir)
 
@@ -176,6 +178,7 @@ ENTRY(swapper_pg_dir)
 	__INITDATA
 	.align CHIP_L2_LINE_SIZE()
 ENTRY(swapper_pgprot)
-	PTE	0, 0, HV_PTE_READABLE | HV_PTE_WRITABLE, 1
+	PTE	0, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
+		      (1 << (HV_PTE_INDEX_WRITABLE - 32)), 1
 	.align CHIP_L2_LINE_SIZE()
 	END(swapper_pgprot)
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index 5eed4a0..fffcfa6 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -32,10 +32,6 @@
 # error "No support for kernel preemption currently"
 #endif
 
-#if INT_INTCTRL_K < 32 || INT_INTCTRL_K >= 48
-# error INT_INTCTRL_K coded to set high interrupt mask
-#endif
-
 #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
 
 #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR)
@@ -1199,46 +1195,6 @@ STD_ENTRY(interrupt_return)
 	STD_ENDPROC(interrupt_return)
 
 	/*
-	 * This interrupt variant clears the INT_INTCTRL_K interrupt mask bit
-	 * before returning, so we can properly get more downcalls.
-	 */
-	.pushsection .text.handle_interrupt_downcall,"ax"
-handle_interrupt_downcall:
-	finish_interrupt_save handle_interrupt_downcall
-	check_single_stepping normal, .Ldispatch_downcall
-.Ldispatch_downcall:
-
-	/* Clear INTCTRL_K from the set of interrupts we ever enable. */
-	GET_INTERRUPTS_ENABLED_MASK_PTR(r30)
-	{
-	 addi   r30, r30, 4
-	 movei  r31, INT_MASK(INT_INTCTRL_K)
-	}
-	{
-	 lw     r20, r30
-	 nor    r21, r31, zero
-	}
-	and     r20, r20, r21
-	sw      r30, r20
-
-	{
-	 jalr   r0
-	 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
-	}
-	FEEDBACK_REENTER(handle_interrupt_downcall)
-
-	/* Allow INTCTRL_K to be enabled next time we enable interrupts. */
-	lw      r20, r30
-	or      r20, r20, r31
-	sw      r30, r20
-
-	{
-	 movei  r30, 0   /* not an NMI */
-	 j      interrupt_return
-	}
-	STD_ENDPROC(handle_interrupt_downcall)
-
-	/*
 	 * Some interrupts don't check for single stepping
 	 */
 	.pushsection .text.handle_interrupt_no_single_step,"ax"
@@ -1600,7 +1556,10 @@ STD_ENTRY(_sys_clone)
 	.align 64
 	/* Align much later jump on the start of a cache line. */
 #if !ATOMIC_LOCKS_FOUND_VIA_TABLE()
-	nop; nop
+	nop
+#if PAGE_SIZE >= 0x10000
+	nop
+#endif
 #endif
 ENTRY(sys_cmpxchg)
 
@@ -1628,9 +1587,13 @@ ENTRY(sys_cmpxchg)
 	 * about aliasing among multiple mappings of the same physical page,
 	 * and we ignore the low 3 bits so we have one lock that covers
 	 * both a cmpxchg64() and a cmpxchg() on either its low or high word.
-	 * NOTE: this code must match __atomic_hashed_lock() in lib/atomic.c.
+	 * NOTE: this must match __atomic_hashed_lock() in lib/atomic_32.c.
 	 */
 
+#if (PAGE_OFFSET & 0xffff) != 0
+# error Code here assumes PAGE_OFFSET can be loaded with just hi16()
+#endif
+
 #if ATOMIC_LOCKS_FOUND_VIA_TABLE()
 	{
 	 /* Check for unaligned input. */
@@ -1723,11 +1686,14 @@ ENTRY(sys_cmpxchg)
 	 lw	r26, r0
 	}
 	{
-	 /* atomic_locks is page aligned so this suffices to get its addr. */
-	 auli	r21, zero, hi16(atomic_locks)
+	 auli	r21, zero, ha16(atomic_locks)
 
 	 bbns   r23, .Lcmpxchg_badaddr
 	}
+#if PAGE_SIZE < 0x10000
+	/* atomic_locks is page-aligned so for big pages we don't need this. */
+	addli   r21, r21, lo16(atomic_locks)
+#endif
 	{
 	 /*
 	  * Insert the hash bits into the page-aligned pointer.
@@ -1762,7 +1728,7 @@ ENTRY(sys_cmpxchg)
 
 	/*
 	 * Perform the actual cmpxchg or atomic_update.
-	 * Note that __futex_mark_unlocked() in uClibc relies on
+	 * Note that the system <arch/atomic.h> header relies on
 	 * atomic_update() to always perform an "mf", so don't make
 	 * it optional or conditional without modifying that code.
 	 */
@@ -2014,17 +1980,17 @@ int_unalign:
 #endif
 	int_hand     INT_INTCTRL_0, INTCTRL_0, bad_intr
 	int_hand     INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \
-		     hv_message_intr, handle_interrupt_downcall
+		     hv_message_intr
 	int_hand     INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, \
-		     tile_dev_intr, handle_interrupt_downcall
+		     tile_dev_intr
 	int_hand     INT_I_ASID, I_ASID, bad_intr
 	int_hand     INT_D_ASID, D_ASID, bad_intr
 	int_hand     INT_DMATLB_MISS_DWNCL, DMATLB_MISS_DWNCL, \
-		     do_page_fault, handle_interrupt_downcall
+		     do_page_fault
 	int_hand     INT_SNITLB_MISS_DWNCL, SNITLB_MISS_DWNCL, \
-		     do_page_fault, handle_interrupt_downcall
+		     do_page_fault
 	int_hand     INT_DMATLB_ACCESS_DWNCL, DMATLB_ACCESS_DWNCL, \
-		     do_page_fault, handle_interrupt_downcall
+		     do_page_fault
 	int_hand     INT_SN_CPL, SN_CPL, bad_intr
 	int_hand     INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap
 #if CHIP_HAS_AUX_PERF_COUNTERS()
diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c
index 128805e..0baa758 100644
--- a/arch/tile/kernel/irq.c
+++ b/arch/tile/kernel/irq.c
@@ -176,43 +176,43 @@ void disable_percpu_irq(unsigned int irq)
 EXPORT_SYMBOL(disable_percpu_irq);
 
 /* Mask an interrupt. */
-static void tile_irq_chip_mask(unsigned int irq)
+static void tile_irq_chip_mask(struct irq_data *d)
 {
-	mask_irqs(1UL << irq);
+	mask_irqs(1UL << d->irq);
 }
 
 /* Unmask an interrupt. */
-static void tile_irq_chip_unmask(unsigned int irq)
+static void tile_irq_chip_unmask(struct irq_data *d)
 {
-	unmask_irqs(1UL << irq);
+	unmask_irqs(1UL << d->irq);
 }
 
 /*
  * Clear an interrupt before processing it so that any new assertions
  * will trigger another irq.
  */
-static void tile_irq_chip_ack(unsigned int irq)
+static void tile_irq_chip_ack(struct irq_data *d)
 {
-	if ((unsigned long)get_irq_chip_data(irq) != IS_HW_CLEARED)
-		clear_irqs(1UL << irq);
+	if ((unsigned long)irq_data_get_irq_chip_data(d) != IS_HW_CLEARED)
+		clear_irqs(1UL << d->irq);
 }
 
 /*
  * For per-cpu interrupts, we need to avoid unmasking any interrupts
  * that we disabled via disable_percpu_irq().
  */
-static void tile_irq_chip_eoi(unsigned int irq)
+static void tile_irq_chip_eoi(struct irq_data *d)
 {
-	if (!(__get_cpu_var(irq_disable_mask) & (1UL << irq)))
-		unmask_irqs(1UL << irq);
+	if (!(__get_cpu_var(irq_disable_mask) & (1UL << d->irq)))
+		unmask_irqs(1UL << d->irq);
 }
 
 static struct irq_chip tile_irq_chip = {
 	.name = "tile_irq_chip",
-	.ack = tile_irq_chip_ack,
-	.eoi = tile_irq_chip_eoi,
-	.mask = tile_irq_chip_mask,
-	.unmask = tile_irq_chip_unmask,
+	.irq_ack = tile_irq_chip_ack,
+	.irq_eoi = tile_irq_chip_eoi,
+	.irq_mask = tile_irq_chip_mask,
+	.irq_unmask = tile_irq_chip_unmask,
 };
 
 void __init init_IRQ(void)
@@ -277,8 +277,10 @@ int show_interrupts(struct seq_file *p, void *v)
 	}
 
 	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_to_desc(i);
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
@@ -288,7 +290,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", get_irq_desc_chip(desc)->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action = action->next; action; action = action->next)
@@ -296,7 +298,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
 		seq_putc(p, '\n');
 skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
 	return 0;
 }
diff --git a/arch/tile/kernel/machine_kexec.c b/arch/tile/kernel/machine_kexec.c
index 0d8b9e9..e00d717 100644
--- a/arch/tile/kernel/machine_kexec.c
+++ b/arch/tile/kernel/machine_kexec.c
@@ -240,8 +240,11 @@ static void setup_quasi_va_is_pa(void)
 	pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE);
 	pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3);
 
-	for (i = 0; i < pgd_index(PAGE_OFFSET); i++)
-		pgtable[i] = pfn_pte(i << (HPAGE_SHIFT - PAGE_SHIFT), pte);
+	for (i = 0; i < pgd_index(PAGE_OFFSET); i++) {
+		unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT);
+		if (pfn_valid(pfn))
+			__set_pte(&pgtable[i], pfn_pte(pfn, pte));
+	}
 }
 
 
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c
index 5ad5e13..658752b2 100644
--- a/arch/tile/kernel/pci-dma.c
+++ b/arch/tile/kernel/pci-dma.c
@@ -86,6 +86,21 @@ EXPORT_SYMBOL(dma_free_coherent);
  * can count on nothing having been touched.
  */
 
+/* Flush a PA range from cache page by page. */
+static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size)
+{
+	struct page *page = pfn_to_page(PFN_DOWN(dma_addr));
+	size_t bytesleft = PAGE_SIZE - (dma_addr & (PAGE_SIZE - 1));
+
+	while ((ssize_t)size > 0) {
+		/* Flush the page. */
+		homecache_flush_cache(page++, 0);
+
+		/* Figure out if we need to continue on the next page. */
+		size -= bytesleft;
+		bytesleft = PAGE_SIZE;
+	}
+}
 
 /*
  * dma_map_single can be passed any memory address, and there appear
@@ -97,26 +112,12 @@ EXPORT_SYMBOL(dma_free_coherent);
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 	       enum dma_data_direction direction)
 {
-	struct page *page;
-	dma_addr_t dma_addr;
-	int thispage;
+	dma_addr_t dma_addr = __pa(ptr);
 
 	BUG_ON(!valid_dma_direction(direction));
 	WARN_ON(size == 0);
 
-	dma_addr = __pa(ptr);
-
-	/* We might have been handed a buffer that wraps a page boundary */
-	while ((int)size > 0) {
-		/* The amount to flush that's on this page */
-		thispage = PAGE_SIZE - ((unsigned long)ptr & (PAGE_SIZE - 1));
-		thispage = min((int)thispage, (int)size);
-		/* Is this valid for any page we could be handed? */
-		page = pfn_to_page(kaddr_to_pfn(ptr));
-		homecache_flush_cache(page, 0);
-		ptr += thispage;
-		size -= thispage;
-	}
+	__dma_map_pa_range(dma_addr, size);
 
 	return dma_addr;
 }
@@ -140,10 +141,8 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
 	WARN_ON(nents == 0 || sglist->length == 0);
 
 	for_each_sg(sglist, sg, nents, i) {
-		struct page *page;
 		sg->dma_address = sg_phys(sg);
-		page = pfn_to_page(sg->dma_address >> PAGE_SHIFT);
-		homecache_flush_cache(page, 0);
+		__dma_map_pa_range(sg->dma_address, sg->length);
 	}
 
 	return nents;
@@ -163,6 +162,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
 {
 	BUG_ON(!valid_dma_direction(direction));
 
+	BUG_ON(offset + size > PAGE_SIZE);
 	homecache_flush_cache(page, 0);
 
 	return page_to_pa(page) + offset;
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index e90eb53..d006510 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -109,7 +109,7 @@ void cpu_idle(void)
 	}
 }
 
-struct thread_info *alloc_thread_info(struct task_struct *task)
+struct thread_info *alloc_thread_info_node(struct task_struct *task, int node)
 {
 	struct page *page;
 	gfp_t flags = GFP_KERNEL;
@@ -118,7 +118,7 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
 	flags |= __GFP_ZERO;
 #endif
 
-	page = alloc_pages(flags, THREAD_SIZE_ORDER);
+	page = alloc_pages_node(node, flags, THREAD_SIZE_ORDER);
 	if (!page)
 		return NULL;
 
@@ -165,7 +165,7 @@ void free_thread_info(struct thread_info *info)
 		kfree(step_state);
 	}
 
-	free_page((unsigned long)info);
+	free_pages((unsigned long)info, THREAD_SIZE_ORDER);
 }
 
 static void save_arch_state(struct thread_struct *t);
@@ -574,6 +574,8 @@ SYSCALL_DEFINE4(execve, const char __user *, path,
 		goto out;
 	error = do_execve(filename, argv, envp, regs);
 	putname(filename);
+	if (error == 0)
+		single_step_execve();
 out:
 	return error;
 }
@@ -593,6 +595,8 @@ long compat_sys_execve(const char __user *path,
 		goto out;
 	error = compat_do_execve(filename, argv, envp, regs);
 	putname(filename);
+	if (error == 0)
+		single_step_execve();
 out:
 	return error;
 }
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index f185736..3696b18 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -59,6 +59,8 @@ unsigned long __initdata node_memmap_pfn[MAX_NUMNODES];
 unsigned long __initdata node_percpu_pfn[MAX_NUMNODES];
 unsigned long __initdata node_free_pfn[MAX_NUMNODES];
 
+static unsigned long __initdata node_percpu[MAX_NUMNODES];
+
 #ifdef CONFIG_HIGHMEM
 /* Page frame index of end of lowmem on each controller. */
 unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES];
@@ -554,7 +556,6 @@ static void __init setup_bootmem_allocator(void)
 		reserve_bootmem(crashk_res.start,
 			crashk_res.end - crashk_res.start + 1, 0);
 #endif
-
 }
 
 void *__init alloc_remap(int nid, unsigned long size)
@@ -568,11 +569,13 @@ void *__init alloc_remap(int nid, unsigned long size)
 
 static int __init percpu_size(void)
 {
-	int size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE);
-#ifdef CONFIG_MODULES
-	if (size < PERCPU_ENOUGH_ROOM)
-		size = PERCPU_ENOUGH_ROOM;
-#endif
+	int size = __per_cpu_end - __per_cpu_start;
+	size += PERCPU_MODULE_RESERVE;
+	size += PERCPU_DYNAMIC_EARLY_SIZE;
+	if (size < PCPU_MIN_UNIT_SIZE)
+		size = PCPU_MIN_UNIT_SIZE;
+	size = roundup(size, PAGE_SIZE);
+
 	/* In several places we assume the per-cpu data fits on a huge page. */
 	BUG_ON(kdata_huge && size > HPAGE_SIZE);
 	return size;
@@ -589,7 +592,6 @@ static inline unsigned long alloc_bootmem_pfn(int size, unsigned long goal)
 static void __init zone_sizes_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES] = { 0 };
-	unsigned long node_percpu[MAX_NUMNODES] = { 0 };
 	int size = percpu_size();
 	int num_cpus = smp_height * smp_width;
 	int i;
@@ -674,7 +676,7 @@ static void __init zone_sizes_init(void)
 		NODE_DATA(i)->bdata = NODE_DATA(0)->bdata;
 
 		free_area_init_node(i, zones_size, start, NULL);
-		printk(KERN_DEBUG "  DMA zone: %ld per-cpu pages\n",
+		printk(KERN_DEBUG "  Normal zone: %ld per-cpu pages\n",
 		       PFN_UP(node_percpu[i]));
 
 		/* Track the type of memory on each node */
@@ -1312,6 +1314,8 @@ static void *__init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
 
 	BUG_ON(size % PAGE_SIZE != 0);
 	pfn_offset[nid] += size / PAGE_SIZE;
+	BUG_ON(node_percpu[nid] < size);
+	node_percpu[nid] -= size;
 	if (percpu_pfn[cpu] == 0)
 		percpu_pfn[cpu] = pfn;
 	return pfn_to_kaddr(pfn);
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 1eb3b39..84a729e 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -56,7 +56,7 @@ enum mem_op {
 	MEMOP_STORE_POSTINCR
 };
 
-static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, int32_t offset)
+static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset)
 {
 	tile_bundle_bits result;
 
@@ -254,6 +254,18 @@ P("\n");
 	return bundle;
 }
 
+/*
+ * Called after execve() has started the new image.  This allows us
+ * to reset the info state.  Note that the the mmap'ed memory, if there
+ * was any, has already been unmapped by the exec.
+ */
+void single_step_execve(void)
+{
+	struct thread_info *ti = current_thread_info();
+	kfree(ti->step_state);
+	ti->step_state = NULL;
+}
+
 /**
  * single_step_once() - entry point when single stepping has been triggered.
  * @regs: The machine register state
@@ -373,7 +385,7 @@ void single_step_once(struct pt_regs *regs)
 		/* branches */
 		case BRANCH_OPCODE_X1:
 		{
-			int32_t offset = signExtend17(get_BrOff_X1(bundle));
+			s32 offset = signExtend17(get_BrOff_X1(bundle));
 
 			/*
 			 * For branches, we use a rewriting trick to let the
@@ -731,4 +743,9 @@ void single_step_once(struct pt_regs *regs)
 	__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
 }
 
+void single_step_execve(void)
+{
+	/* Nothing */
+}
+
 #endif /* !__tilegx__ */
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c
index 9575b37..a429310 100644
--- a/arch/tile/kernel/smp.c
+++ b/arch/tile/kernel/smp.c
@@ -36,6 +36,22 @@ static unsigned long __iomem *ipi_mappings[NR_CPUS];
 /* Set by smp_send_stop() to avoid recursive panics. */
 static int stopping_cpus;
 
+static void __send_IPI_many(HV_Recipient *recip, int nrecip, int tag)
+{
+	int sent = 0;
+	while (sent < nrecip) {
+		int rc = hv_send_message(recip, nrecip,
+					 (HV_VirtAddr)&tag, sizeof(tag));
+		if (rc < 0) {
+			if (!stopping_cpus)  /* avoid recursive panic */
+				panic("hv_send_message returned %d", rc);
+			break;
+		}
+		WARN_ONCE(rc == 0, "hv_send_message() returned zero\n");
+		sent += rc;
+	}
+}
+
 void send_IPI_single(int cpu, int tag)
 {
 	HV_Recipient recip = {
@@ -43,14 +59,13 @@ void send_IPI_single(int cpu, int tag)
 		.x = cpu % smp_width,
 		.state = HV_TO_BE_SENT
 	};
-	int rc = hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag));
-	BUG_ON(rc <= 0);
+	__send_IPI_many(&recip, 1, tag);
 }
 
 void send_IPI_many(const struct cpumask *mask, int tag)
 {
 	HV_Recipient recip[NR_CPUS];
-	int cpu, sent;
+	int cpu;
 	int nrecip = 0;
 	int my_cpu = smp_processor_id();
 	for_each_cpu(cpu, mask) {
@@ -61,17 +76,7 @@ void send_IPI_many(const struct cpumask *mask, int tag)
 		r->x = cpu % smp_width;
 		r->state = HV_TO_BE_SENT;
 	}
-	sent = 0;
-	while (sent < nrecip) {
-		int rc = hv_send_message(recip, nrecip,
-					 (HV_VirtAddr)&tag, sizeof(tag));
-		if (rc <= 0) {
-			if (!stopping_cpus)  /* avoid recursive panic */
-				panic("hv_send_message returned %d", rc);
-			break;
-		}
-		sent += rc;
-	}
+	__send_IPI_many(recip, nrecip, tag);
 }
 
 void send_IPI_allbutself(int tag)
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index 0d54106b..dd81713 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -44,13 +44,6 @@ static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp)
 	return sp >= kstack_base && sp < kstack_base + THREAD_SIZE;
 }
 
-/* Is address in the specified kernel code? */
-static int in_kernel_text(VirtualAddress address)
-{
-	return (address >= MEM_SV_INTRPT &&
-		address < MEM_SV_INTRPT + HPAGE_SIZE);
-}
-
 /* Is address valid for reading? */
 static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address)
 {
@@ -63,6 +56,23 @@ static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address)
 	if (l1_pgtable == NULL)
 		return 0;	/* can't read user space in other tasks */
 
+#ifdef CONFIG_64BIT
+	/* Find the real l1_pgtable by looking in the l0_pgtable. */
+	pte = l1_pgtable[HV_L0_INDEX(address)];
+	if (!hv_pte_get_present(pte))
+		return 0;
+	pfn = hv_pte_get_pfn(pte);
+	if (pte_huge(pte)) {
+		if (!pfn_valid(pfn)) {
+			pr_err("L0 huge page has bad pfn %#lx\n", pfn);
+			return 0;
+		}
+		return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
+	}
+	page = pfn_to_page(pfn);
+	BUG_ON(PageHighMem(page));  /* No HIGHMEM on 64-bit. */
+	l1_pgtable = (HV_PTE *)pfn_to_kaddr(pfn);
+#endif
 	pte = l1_pgtable[HV_L1_INDEX(address)];
 	if (!hv_pte_get_present(pte))
 		return 0;
@@ -92,7 +102,7 @@ static bool read_memory_func(void *result, VirtualAddress address,
 {
 	int retval;
 	struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt;
-	if (in_kernel_text(address)) {
+	if (__kernel_text_address(address)) {
 		/* OK to read kernel code. */
 	} else if (address >= PAGE_OFFSET) {
 		/* We only tolerate kernel-space reads of this task's stack */
@@ -132,7 +142,7 @@ static struct pt_regs *valid_fault_handler(struct KBacktraceIterator* kbt)
 		}
 	}
 	if (EX1_PL(p->ex1) == KERNEL_PL &&
-	    in_kernel_text(p->pc) &&
+	    __kernel_text_address(p->pc) &&
 	    in_kernel_stack(kbt, p->sp) &&
 	    p->sp >= sp) {
 		if (kbt->verbose)
diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c
index f2e156e..49a605b 100644
--- a/arch/tile/kernel/time.c
+++ b/arch/tile/kernel/time.c
@@ -224,3 +224,13 @@ int setup_profiling_timer(unsigned int multiplier)
 {
 	return -EINVAL;
 }
+
+/*
+ * Use the tile timer to convert nsecs to core clock cycles, relying
+ * on it having the same frequency as SPR_CYCLE.
+ */
+cycles_t ns2cycles(unsigned long nsecs)
+{
+	struct clock_event_device *dev = &__get_cpu_var(tile_timer);
+	return ((u64)nsecs * dev->mult) >> dev->shift;
+}
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 25fdc0c..38f64fa 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -59,11 +59,8 @@ SECTIONS
 
   . = ALIGN(PAGE_SIZE);
   VMLINUX_SYMBOL(_sinitdata) = .;
-  .init.page : AT (ADDR(.init.page) - LOAD_OFFSET) {
-    *(.init.page)
-  } :data =0
-  INIT_DATA_SECTION(16)
-  PERCPU(PAGE_SIZE)
+  INIT_DATA_SECTION(16) :data =0
+  PERCPU(L2_CACHE_BYTES, PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   VMLINUX_SYMBOL(_einitdata) = .;
 
diff --git a/arch/tile/lib/Makefile b/arch/tile/lib/Makefile
index 93122d5..0c26086 100644
--- a/arch/tile/lib/Makefile
+++ b/arch/tile/lib/Makefile
@@ -2,9 +2,8 @@
 # Makefile for TILE-specific library files..
 #
 
-lib-y = cacheflush.o checksum.o cpumask.o delay.o \
-	mb_incoherent.o uaccess.o memmove.o \
-	memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
+lib-y = cacheflush.o checksum.o cpumask.o delay.o uaccess.o \
+	memmove.o memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
 	strchr_$(BITS).o strlen_$(BITS).o
 
 ifeq ($(CONFIG_TILEGX),y)
diff --git a/arch/tile/lib/atomic_32.c b/arch/tile/lib/atomic_32.c
index 7a5cc70..4657021 100644
--- a/arch/tile/lib/atomic_32.c
+++ b/arch/tile/lib/atomic_32.c
@@ -46,14 +46,13 @@ struct atomic_locks_on_cpu *atomic_lock_ptr[ATOMIC_HASH_L1_SIZE]
 #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
 /* This page is remapped on startup to be hash-for-home. */
-int atomic_locks[PAGE_SIZE / sizeof(int) /* Only ATOMIC_HASH_SIZE is used */]
-  __attribute__((aligned(PAGE_SIZE), section(".bss.page_aligned")));
+int atomic_locks[PAGE_SIZE / sizeof(int)] __page_aligned_bss;
 
 #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
 static inline int *__atomic_hashed_lock(volatile void *v)
 {
-	/* NOTE: this code must match "sys_cmpxchg" in kernel/intvec.S */
+	/* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */
 #if ATOMIC_LOCKS_FOUND_VIA_TABLE()
 	unsigned long i =
 		(unsigned long) v & ((PAGE_SIZE-1) & -sizeof(long long));
@@ -203,32 +202,32 @@ static inline int *__futex_setup(int __user *v)
 	return __atomic_hashed_lock((int __force *)v);
 }
 
-struct __get_user futex_set(int __user *v, int i)
+struct __get_user futex_set(u32 __user *v, int i)
 {
 	return __atomic_xchg((int __force *)v, __futex_setup(v), i);
 }
 
-struct __get_user futex_add(int __user *v, int n)
+struct __get_user futex_add(u32 __user *v, int n)
 {
 	return __atomic_xchg_add((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_or(int __user *v, int n)
+struct __get_user futex_or(u32 __user *v, int n)
 {
 	return __atomic_or((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_andn(int __user *v, int n)
+struct __get_user futex_andn(u32 __user *v, int n)
 {
 	return __atomic_andn((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_xor(int __user *v, int n)
+struct __get_user futex_xor(u32 __user *v, int n)
 {
 	return __atomic_xor((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_cmpxchg(int __user *v, int o, int n)
+struct __get_user futex_cmpxchg(u32 __user *v, int o, int n)
 {
 	return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n);
 }
diff --git a/arch/tile/lib/atomic_asm_32.S b/arch/tile/lib/atomic_asm_32.S
index 5a5514b..82f64cc 100644
--- a/arch/tile/lib/atomic_asm_32.S
+++ b/arch/tile/lib/atomic_asm_32.S
@@ -14,7 +14,7 @@
  * Support routines for atomic operations.  Each function takes:
  *
  * r0: address to manipulate
- * r1: pointer to atomic lock guarding this operation (for FUTEX_LOCK_REG)
+ * r1: pointer to atomic lock guarding this operation (for ATOMIC_LOCK_REG)
  * r2: new value to write, or for cmpxchg/add_unless, value to compare against
  * r3: (cmpxchg/xchg_add_unless) new value to write or add;
  *     (atomic64 ops) high word of value to write
diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c
index 11b6164..35c1d8c 100644
--- a/arch/tile/lib/cacheflush.c
+++ b/arch/tile/lib/cacheflush.c
@@ -21,3 +21,105 @@ void __flush_icache_range(unsigned long start, unsigned long end)
 {
 	invalidate_icache((const void *)start, end - start, PAGE_SIZE);
 }
+
+
+/* Force a load instruction to issue. */
+static inline void force_load(char *p)
+{
+	*(volatile char *)p;
+}
+
+/*
+ * Flush and invalidate a VA range that is homed remotely on a single
+ * core (if "!hfh") or homed via hash-for-home (if "hfh"), waiting
+ * until the memory controller holds the flushed values.
+ */
+void finv_buffer_remote(void *buffer, size_t size, int hfh)
+{
+	char *p, *base;
+	size_t step_size, load_count;
+	const unsigned long STRIPE_WIDTH = 8192;
+
+	/*
+	 * Flush and invalidate the buffer out of the local L1/L2
+	 * and request the home cache to flush and invalidate as well.
+	 */
+	__finv_buffer(buffer, size);
+
+	/*
+	 * Wait for the home cache to acknowledge that it has processed
+	 * all the flush-and-invalidate requests.  This does not mean
+	 * that the flushed data has reached the memory controller yet,
+	 * but it does mean the home cache is processing the flushes.
+	 */
+	__insn_mf();
+
+	/*
+	 * Issue a load to the last cache line, which can't complete
+	 * until all the previously-issued flushes to the same memory
+	 * controller have also completed.  If we weren't striping
+	 * memory, that one load would be sufficient, but since we may
+	 * be, we also need to back up to the last load issued to
+	 * another memory controller, which would be the point where
+	 * we crossed an 8KB boundary (the granularity of striping
+	 * across memory controllers).  Keep backing up and doing this
+	 * until we are before the beginning of the buffer, or have
+	 * hit all the controllers.
+	 *
+	 * If we are flushing a hash-for-home buffer, it's even worse.
+	 * Each line may be homed on a different tile, and each tile
+	 * may have up to four lines that are on different
+	 * controllers.  So as we walk backwards, we have to touch
+	 * enough cache lines to satisfy these constraints.  In
+	 * practice this ends up being close enough to "load from
+	 * every cache line on a full memory stripe on each
+	 * controller" that we simply do that, to simplify the logic.
+	 *
+	 * FIXME: See bug 9535 for some issues with this code.
+	 */
+	if (hfh) {
+		step_size = L2_CACHE_BYTES;
+		load_count = (STRIPE_WIDTH / L2_CACHE_BYTES) *
+			      (1 << CHIP_LOG_NUM_MSHIMS());
+	} else {
+		step_size = STRIPE_WIDTH;
+		load_count = (1 << CHIP_LOG_NUM_MSHIMS());
+	}
+
+	/* Load the last byte of the buffer. */
+	p = (char *)buffer + size - 1;
+	force_load(p);
+
+	/* Bump down to the end of the previous stripe or cache line. */
+	p -= step_size;
+	p = (char *)((unsigned long)p | (step_size - 1));
+
+	/* Figure out how far back we need to go. */
+	base = p - (step_size * (load_count - 2));
+	if ((long)base < (long)buffer)
+		base = buffer;
+
+	/*
+	 * Fire all the loads we need.  The MAF only has eight entries
+	 * so we can have at most eight outstanding loads, so we
+	 * unroll by that amount.
+	 */
+#pragma unroll 8
+	for (; p >= base; p -= step_size)
+		force_load(p);
+
+	/*
+	 * Repeat, but with inv's instead of loads, to get rid of the
+	 * data we just loaded into our own cache and the old home L3.
+	 * No need to unroll since inv's don't target a register.
+	 */
+	p = (char *)buffer + size - 1;
+	__insn_inv(p);
+	p -= step_size;
+	p = (char *)((unsigned long)p | (step_size - 1));
+	for (; p >= base; p -= step_size)
+		__insn_inv(p);
+
+	/* Wait for the load+inv's (and thus finvs) to have completed. */
+	__insn_mf();
+}
diff --git a/arch/tile/lib/delay.c b/arch/tile/lib/delay.c
index 5801b03..cdacdd1 100644
--- a/arch/tile/lib/delay.c
+++ b/arch/tile/lib/delay.c
@@ -15,20 +15,31 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/thread_info.h>
-#include <asm/fixmap.h>
-#include <hv/hypervisor.h>
+#include <asm/timex.h>
 
 void __udelay(unsigned long usecs)
 {
-	hv_nanosleep(usecs * 1000);
+	if (usecs > ULONG_MAX / 1000) {
+		WARN_ON_ONCE(usecs > ULONG_MAX / 1000);
+		usecs = ULONG_MAX / 1000;
+	}
+	__ndelay(usecs * 1000);
 }
 EXPORT_SYMBOL(__udelay);
 
 void __ndelay(unsigned long nsecs)
 {
-	hv_nanosleep(nsecs);
+	cycles_t target = get_cycles();
+	target += ns2cycles(nsecs);
+	while (get_cycles() < target)
+		cpu_relax();
 }
 EXPORT_SYMBOL(__ndelay);
 
-/* FIXME: should be declared in a header somewhere. */
+void __delay(unsigned long cycles)
+{
+	cycles_t target = get_cycles() + cycles;
+	while (get_cycles() < target)
+		cpu_relax();
+}
 EXPORT_SYMBOL(__delay);
diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c
index 1509c55..49284fa 100644
--- a/arch/tile/lib/exports.c
+++ b/arch/tile/lib/exports.c
@@ -29,6 +29,9 @@ EXPORT_SYMBOL(__put_user_8);
 EXPORT_SYMBOL(strnlen_user_asm);
 EXPORT_SYMBOL(strncpy_from_user_asm);
 EXPORT_SYMBOL(clear_user_asm);
+EXPORT_SYMBOL(flush_user_asm);
+EXPORT_SYMBOL(inv_user_asm);
+EXPORT_SYMBOL(finv_user_asm);
 
 /* arch/tile/kernel/entry.S */
 #include <linux/kernel.h>
@@ -45,9 +48,6 @@ EXPORT_SYMBOL(__copy_from_user_zeroing);
 EXPORT_SYMBOL(__copy_in_user_inatomic);
 #endif
 
-/* arch/tile/lib/mb_incoherent.S */
-EXPORT_SYMBOL(__mb_incoherent);
-
 /* hypervisor glue */
 #include <hv/hypervisor.h>
 EXPORT_SYMBOL(hv_dev_open);
@@ -85,4 +85,8 @@ int64_t __muldi3(int64_t, int64_t);
 EXPORT_SYMBOL(__muldi3);
 uint64_t __lshrdi3(uint64_t, unsigned int);
 EXPORT_SYMBOL(__lshrdi3);
+uint64_t __ashrdi3(uint64_t, unsigned int);
+EXPORT_SYMBOL(__ashrdi3);
+uint64_t __ashldi3(uint64_t, unsigned int);
+EXPORT_SYMBOL(__ashldi3);
 #endif
diff --git a/arch/tile/lib/mb_incoherent.S b/arch/tile/lib/mb_incoherent.S
deleted file mode 100644
index 989ad7b..0000000
--- a/arch/tile/lib/mb_incoherent.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
- *
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation, 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, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- *
- * Assembly code for invoking the HV's fence_incoherent syscall.
- */
-
-#include <linux/linkage.h>
-#include <hv/syscall_public.h>
-#include <arch/abi.h>
-#include <arch/chip.h>
-
-#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-
-/*
- * Invoke the hypervisor's fence_incoherent syscall, which guarantees
- * that all victims for cachelines homed on this tile have reached memory.
- */
-STD_ENTRY(__mb_incoherent)
-	moveli TREG_SYSCALL_NR_NAME, HV_SYS_fence_incoherent
-	swint2
-	jrp lr
-	STD_ENDPROC(__mb_incoherent)
-
-#endif
diff --git a/arch/tile/lib/memcpy_tile64.c b/arch/tile/lib/memcpy_tile64.c
index f7d4a6a..b2fe15e 100644
--- a/arch/tile/lib/memcpy_tile64.c
+++ b/arch/tile/lib/memcpy_tile64.c
@@ -96,7 +96,7 @@ static void memcpy_multicache(void *dest, const void *source,
 	newsrc = __fix_to_virt(idx) + ((unsigned long)source & (PAGE_SIZE-1));
 	pmdp = pmd_offset(pud_offset(pgd_offset_k(newsrc), newsrc), newsrc);
 	ptep = pte_offset_kernel(pmdp, newsrc);
-	*ptep = src_pte;   /* set_pte() would be confused by this */
+	__set_pte(ptep, src_pte);   /* set_pte() would be confused by this */
 	local_flush_tlb_page(NULL, newsrc, PAGE_SIZE);
 
 	/* Actually move the data. */
@@ -109,7 +109,7 @@ static void memcpy_multicache(void *dest, const void *source,
 	 */
 	src_pte = hv_pte_set_mode(src_pte, HV_PTE_MODE_CACHE_NO_L3);
 	src_pte = hv_pte_set_writable(src_pte); /* need write access for inv */
-	*ptep = src_pte;   /* set_pte() would be confused by this */
+	__set_pte(ptep, src_pte);   /* set_pte() would be confused by this */
 	local_flush_tlb_page(NULL, newsrc, PAGE_SIZE);
 
 	/*
diff --git a/arch/tile/lib/spinlock_32.c b/arch/tile/lib/spinlock_32.c
index 5cd1c40..cb0999f 100644
--- a/arch/tile/lib/spinlock_32.c
+++ b/arch/tile/lib/spinlock_32.c
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <asm/processor.h>
+#include <arch/spr_def.h>
 
 #include "spinlock_common.h"
 
@@ -91,75 +92,75 @@ EXPORT_SYMBOL(arch_spin_unlock_wait);
 #define RD_COUNT_MASK   ((1 << RD_COUNT_WIDTH) - 1)
 
 
-/* Lock the word, spinning until there are no tns-ers. */
-static inline u32 get_rwlock(arch_rwlock_t *rwlock)
-{
-	u32 iterations = 0;
-	for (;;) {
-		u32 val = __insn_tns((int *)&rwlock->lock);
-		if (unlikely(val & 1)) {
-			delay_backoff(iterations++);
-			continue;
-		}
-		return val;
-	}
-}
-
-int arch_read_trylock_slow(arch_rwlock_t *rwlock)
-{
-	u32 val = get_rwlock(rwlock);
-	int locked = (val << RD_COUNT_WIDTH) == 0;
-	rwlock->lock = val + (locked << RD_COUNT_SHIFT);
-	return locked;
-}
-EXPORT_SYMBOL(arch_read_trylock_slow);
-
-void arch_read_unlock_slow(arch_rwlock_t *rwlock)
-{
-	u32 val = get_rwlock(rwlock);
-	rwlock->lock = val - (1 << RD_COUNT_SHIFT);
-}
-EXPORT_SYMBOL(arch_read_unlock_slow);
-
-void arch_write_unlock_slow(arch_rwlock_t *rwlock, u32 val)
+/*
+ * We can get the read lock if everything but the reader bits (which
+ * are in the high part of the word) is zero, i.e. no active or
+ * waiting writers, no tns.
+ *
+ * We guard the tns/store-back with an interrupt critical section to
+ * preserve the semantic that the same read lock can be acquired in an
+ * interrupt context.
+ */
+inline int arch_read_trylock(arch_rwlock_t *rwlock)
 {
-	u32 eq, mask = 1 << WR_CURR_SHIFT;
-	while (unlikely(val & 1)) {
-		/* Limited backoff since we are the highest-priority task. */
-		relax(4);
-		val = __insn_tns((int *)&rwlock->lock);
+	u32 val;
+	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1);
+	val = __insn_tns((int *)&rwlock->lock);
+	if (likely((val << _RD_COUNT_WIDTH) == 0)) {
+		val += 1 << RD_COUNT_SHIFT;
+		rwlock->lock = val;
+		__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+		BUG_ON(val == 0);  /* we don't expect wraparound */
+		return 1;
 	}
-	val = __insn_addb(val, mask);
-	eq = __insn_seqb(val, val << (WR_CURR_SHIFT - WR_NEXT_SHIFT));
-	val = __insn_mz(eq & mask, val);
-	rwlock->lock = val;
+	if ((val & 1) == 0)
+		rwlock->lock = val;
+	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+	return 0;
 }
-EXPORT_SYMBOL(arch_write_unlock_slow);
+EXPORT_SYMBOL(arch_read_trylock);
 
 /*
- * We spin until everything but the reader bits (which are in the high
- * part of the word) are zero, i.e. no active or waiting writers, no tns.
- *
+ * Spin doing arch_read_trylock() until we acquire the lock.
  * ISSUE: This approach can permanently starve readers.  A reader who sees
  * a writer could instead take a ticket lock (just like a writer would),
  * and atomically enter read mode (with 1 reader) when it gets the ticket.
- * This way both readers and writers will always make forward progress
+ * This way both readers and writers would always make forward progress
  * in a finite time.
  */
-void arch_read_lock_slow(arch_rwlock_t *rwlock, u32 val)
+void arch_read_lock(arch_rwlock_t *rwlock)
 {
 	u32 iterations = 0;
-	do {
-		if (!(val & 1))
-			rwlock->lock = val;
+	while (unlikely(!arch_read_trylock(rwlock)))
 		delay_backoff(iterations++);
+}
+EXPORT_SYMBOL(arch_read_lock);
+
+void arch_read_unlock(arch_rwlock_t *rwlock)
+{
+	u32 val, iterations = 0;
+
+	mb();  /* guarantee anything modified under the lock is visible */
+	for (;;) {
+		__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1);
 		val = __insn_tns((int *)&rwlock->lock);
-	} while ((val << RD_COUNT_WIDTH) != 0);
-	rwlock->lock = val + (1 << RD_COUNT_SHIFT);
+		if (likely(val & 1) == 0) {
+			rwlock->lock = val - (1 << _RD_COUNT_SHIFT);
+			__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+			break;
+		}
+		__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+		delay_backoff(iterations++);
+	}
 }
-EXPORT_SYMBOL(arch_read_lock_slow);
+EXPORT_SYMBOL(arch_read_unlock);
 
-void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
+/*
+ * We don't need an interrupt critical section here (unlike for
+ * arch_read_lock) since we should never use a bare write lock where
+ * it could be interrupted by code that could try to re-acquire it.
+ */
+void arch_write_lock(arch_rwlock_t *rwlock)
 {
 	/*
 	 * The trailing underscore on this variable (and curr_ below)
@@ -168,6 +169,12 @@ void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
 	 */
 	u32 my_ticket_;
 	u32 iterations = 0;
+	u32 val = __insn_tns((int *)&rwlock->lock);
+
+	if (likely(val == 0)) {
+		rwlock->lock = 1 << _WR_NEXT_SHIFT;
+		return;
+	}
 
 	/*
 	 * Wait until there are no readers, then bump up the next
@@ -206,23 +213,47 @@ void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
 			relax(4);
 	}
 }
-EXPORT_SYMBOL(arch_write_lock_slow);
+EXPORT_SYMBOL(arch_write_lock);
 
-int __tns_atomic_acquire(atomic_t *lock)
+int arch_write_trylock(arch_rwlock_t *rwlock)
 {
-	int ret;
-	u32 iterations = 0;
+	u32 val = __insn_tns((int *)&rwlock->lock);
 
-	BUG_ON(__insn_mfspr(SPR_INTERRUPT_CRITICAL_SECTION));
-	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1);
+	/*
+	 * If a tns is in progress, or there's a waiting or active locker,
+	 * or active readers, we can't take the lock, so give up.
+	 */
+	if (unlikely(val != 0)) {
+		if (!(val & 1))
+			rwlock->lock = val;
+		return 0;
+	}
 
-	while ((ret = __insn_tns((void *)&lock->counter)) == 1)
-		delay_backoff(iterations++);
-	return ret;
+	/* Set the "next" field to mark it locked. */
+	rwlock->lock = 1 << _WR_NEXT_SHIFT;
+	return 1;
 }
+EXPORT_SYMBOL(arch_write_trylock);
 
-void __tns_atomic_release(atomic_t *p, int v)
+void arch_write_unlock(arch_rwlock_t *rwlock)
 {
-	p->counter = v;
-	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+	u32 val, eq, mask;
+
+	mb();  /* guarantee anything modified under the lock is visible */
+	val = __insn_tns((int *)&rwlock->lock);
+	if (likely(val == (1 << _WR_NEXT_SHIFT))) {
+		rwlock->lock = 0;
+		return;
+	}
+	while (unlikely(val & 1)) {
+		/* Limited backoff since we are the highest-priority task. */
+		relax(4);
+		val = __insn_tns((int *)&rwlock->lock);
+	}
+	mask = 1 << WR_CURR_SHIFT;
+	val = __insn_addb(val, mask);
+	eq = __insn_seqb(val, val << (WR_CURR_SHIFT - WR_NEXT_SHIFT));
+	val = __insn_mz(eq & mask, val);
+	rwlock->lock = val;
 }
+EXPORT_SYMBOL(arch_write_unlock);
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index dcebfc8..758f597 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -655,14 +655,6 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,
 	}
 
 	/*
-	 * NOTE: the one other type of access that might bring us here
-	 * are the memory ops in __tns_atomic_acquire/__tns_atomic_release,
-	 * but we don't have to check specially for them since we can
-	 * always safely return to the address of the fault and retry,
-	 * since no separate atomic locks are involved.
-	 */
-
-	/*
 	 * Now that we have released the atomic lock (if necessary),
 	 * it's safe to spin if the PTE that caused the fault was migrating.
 	 */
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index d78df3a..cbe6f4f 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -179,23 +179,46 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
 	panic("Unsafe to continue.");
 }
 
+void flush_remote_page(struct page *page, int order)
+{
+	int i, pages = (1 << order);
+	for (i = 0; i < pages; ++i, ++page) {
+		void *p = kmap_atomic(page);
+		int hfh = 0;
+		int home = page_home(page);
+#if CHIP_HAS_CBOX_HOME_MAP()
+		if (home == PAGE_HOME_HASH)
+			hfh = 1;
+		else
+#endif
+			BUG_ON(home < 0 || home >= NR_CPUS);
+		finv_buffer_remote(p, PAGE_SIZE, hfh);
+		kunmap_atomic(p);
+	}
+}
+
 void homecache_evict(const struct cpumask *mask)
 {
 	flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0);
 }
 
-/* Return a mask of the cpus whose caches currently own these pages. */
-static void homecache_mask(struct page *page, int pages,
-			   struct cpumask *home_mask)
+/*
+ * Return a mask of the cpus whose caches currently own these pages.
+ * The return value is whether the pages are all coherently cached
+ * (i.e. none are immutable, incoherent, or uncached).
+ */
+static int homecache_mask(struct page *page, int pages,
+			  struct cpumask *home_mask)
 {
 	int i;
+	int cached_coherently = 1;
 	cpumask_clear(home_mask);
 	for (i = 0; i < pages; ++i) {
 		int home = page_home(&page[i]);
 		if (home == PAGE_HOME_IMMUTABLE ||
 		    home == PAGE_HOME_INCOHERENT) {
 			cpumask_copy(home_mask, cpu_possible_mask);
-			return;
+			return 0;
 		}
 #if CHIP_HAS_CBOX_HOME_MAP()
 		if (home == PAGE_HOME_HASH) {
@@ -203,11 +226,14 @@ static void homecache_mask(struct page *page, int pages,
 			continue;
 		}
 #endif
-		if (home == PAGE_HOME_UNCACHED)
+		if (home == PAGE_HOME_UNCACHED) {
+			cached_coherently = 0;
 			continue;
+		}
 		BUG_ON(home < 0 || home >= NR_CPUS);
 		cpumask_set_cpu(home, home_mask);
 	}
+	return cached_coherently;
 }
 
 /*
@@ -386,7 +412,7 @@ void homecache_change_page_home(struct page *page, int order, int home)
 		pte_t *ptep = virt_to_pte(NULL, kva);
 		pte_t pteval = *ptep;
 		BUG_ON(!pte_present(pteval) || pte_huge(pteval));
-		*ptep = pte_set_home(pteval, home);
+		__set_pte(ptep, pte_set_home(pteval, home));
 	}
 }
 
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index 0b9ce69..d6e87fd 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -53,22 +53,11 @@
 
 #include "migrate.h"
 
-/*
- * We could set FORCE_MAX_ZONEORDER to "(HPAGE_SHIFT - PAGE_SHIFT + 1)"
- * in the Tile Kconfig, but this generates configure warnings.
- * Do it here and force people to get it right to compile this file.
- * The problem is that with 4KB small pages and 16MB huge pages,
- * the default value doesn't allow us to group enough small pages
- * together to make up a huge page.
- */
-#if CONFIG_FORCE_MAX_ZONEORDER < HPAGE_SHIFT - PAGE_SHIFT + 1
-# error "Change FORCE_MAX_ZONEORDER in arch/tile/Kconfig to match page size"
-#endif
-
 #define clear_pgd(pmdptr) (*(pmdptr) = hv_pte(0))
 
 #ifndef __tilegx__
 unsigned long VMALLOC_RESERVE = CONFIG_VMALLOC_RESERVE;
+EXPORT_SYMBOL(VMALLOC_RESERVE);
 #endif
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -445,7 +434,7 @@ static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
 
 /* Temporary page table we use for staging. */
 static pgd_t pgtables[PTRS_PER_PGD]
- __attribute__((section(".init.page")));
+ __attribute__((aligned(HV_PAGE_TABLE_ALIGN)));
 
 /*
  * This maps the physical memory to kernel virtual address space, a total
@@ -653,6 +642,17 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
 	memcpy(pgd_base, pgtables, sizeof(pgtables));
 	__install_page_table(pgd_base, __get_cpu_var(current_asid),
 			     swapper_pgprot);
+
+	/*
+	 * We just read swapper_pgprot and thus brought it into the cache,
+	 * with its new home & caching mode.  When we start the other CPUs,
+	 * they're going to reference swapper_pgprot via their initial fake
+	 * VA-is-PA mappings, which cache everything locally.  At that
+	 * time, if it's in our cache with a conflicting home, the
+	 * simulator's coherence checker will complain.  So, flush it out
+	 * of our cache; we're not going to ever use it again anyway.
+	 */
+	__insn_finv(&swapper_pgprot);
 }
 
 /*
@@ -950,11 +950,7 @@ struct kmem_cache *pgd_cache;
 
 void __init pgtable_cache_init(void)
 {
-	pgd_cache = kmem_cache_create("pgd",
-				PTRS_PER_PGD*sizeof(pgd_t),
-				PTRS_PER_PGD*sizeof(pgd_t),
-				0,
-				NULL);
+	pgd_cache = kmem_cache_create("pgd", SIZEOF_PGD, SIZEOF_PGD, 0, NULL);
 	if (!pgd_cache)
 		panic("pgtable_cache_init(): Cannot create pgd cache");
 }
@@ -989,7 +985,7 @@ static long __write_once initfree = 1;
 static int __init set_initfree(char *str)
 {
 	long val;
-	if (strict_strtol(str, 0, &val)) {
+	if (strict_strtol(str, 0, &val) == 0) {
 		initfree = val;
 		pr_info("initfree: %s free init pages\n",
 			initfree ? "will" : "won't");
diff --git a/arch/tile/mm/migrate_32.S b/arch/tile/mm/migrate_32.S
index f738765..ac01a7c 100644
--- a/arch/tile/mm/migrate_32.S
+++ b/arch/tile/mm/migrate_32.S
@@ -18,6 +18,7 @@
 #include <linux/linkage.h>
 #include <linux/threads.h>
 #include <asm/page.h>
+#include <asm/thread_info.h>
 #include <asm/types.h>
 #include <asm/asm-offsets.h>
 #include <hv/hypervisor.h>
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index 1f5430c..1a2b36f 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -142,6 +142,76 @@ pte_t *_pte_offset_map(pmd_t *dir, unsigned long address)
 }
 #endif
 
+/**
+ * shatter_huge_page() - ensure a given address is mapped by a small page.
+ *
+ * This function converts a huge PTE mapping kernel LOWMEM into a bunch
+ * of small PTEs with the same caching.  No cache flush required, but we
+ * must do a global TLB flush.
+ *
+ * Any caller that wishes to modify a kernel mapping that might
+ * have been made with a huge page should call this function,
+ * since doing so properly avoids race conditions with installing the
+ * newly-shattered page and then flushing all the TLB entries.
+ *
+ * @addr: Address at which to shatter any existing huge page.
+ */
+void shatter_huge_page(unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	unsigned long flags = 0;  /* happy compiler */
+#ifdef __PAGETABLE_PMD_FOLDED
+	struct list_head *pos;
+#endif
+
+	/* Get a pointer to the pmd entry that we need to change. */
+	addr &= HPAGE_MASK;
+	BUG_ON(pgd_addr_invalid(addr));
+	BUG_ON(addr < PAGE_OFFSET);  /* only for kernel LOWMEM */
+	pgd = swapper_pg_dir + pgd_index(addr);
+	pud = pud_offset(pgd, addr);
+	BUG_ON(!pud_present(*pud));
+	pmd = pmd_offset(pud, addr);
+	BUG_ON(!pmd_present(*pmd));
+	if (!pmd_huge_page(*pmd))
+		return;
+
+	/*
+	 * Grab the pgd_lock, since we may need it to walk the pgd_list,
+	 * and since we need some kind of lock here to avoid races.
+	 */
+	spin_lock_irqsave(&pgd_lock, flags);
+	if (!pmd_huge_page(*pmd)) {
+		/* Lost the race to convert the huge page. */
+		spin_unlock_irqrestore(&pgd_lock, flags);
+		return;
+	}
+
+	/* Shatter the huge page into the preallocated L2 page table. */
+	pmd_populate_kernel(&init_mm, pmd,
+			    get_prealloc_pte(pte_pfn(*(pte_t *)pmd)));
+
+#ifdef __PAGETABLE_PMD_FOLDED
+	/* Walk every pgd on the system and update the pmd there. */
+	list_for_each(pos, &pgd_list) {
+		pmd_t *copy_pmd;
+		pgd = list_to_pgd(pos) + pgd_index(addr);
+		pud = pud_offset(pgd, addr);
+		copy_pmd = pmd_offset(pud, addr);
+		__set_pmd(copy_pmd, *pmd);
+	}
+#endif
+
+	/* Tell every cpu to notice the change. */
+	flush_remote(0, 0, NULL, addr, HPAGE_SIZE, HPAGE_SIZE,
+		     cpu_possible_mask, NULL, 0);
+
+	/* Hold the lock until the TLB flush is finished to avoid races. */
+	spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
 /*
  * List of all pgd's needed so it can invalidate entries in both cached
  * and uncached pgd's. This is essentially codepath-based locking
@@ -184,9 +254,9 @@ static void pgd_ctor(pgd_t *pgd)
 	BUG_ON(((u64 *)swapper_pg_dir)[pgd_index(MEM_USER_INTRPT)] != 0);
 #endif
 
-	clone_pgd_range(pgd + KERNEL_PGD_INDEX_START,
-			swapper_pg_dir + KERNEL_PGD_INDEX_START,
-			KERNEL_PGD_PTRS);
+	memcpy(pgd + KERNEL_PGD_INDEX_START,
+	       swapper_pg_dir + KERNEL_PGD_INDEX_START,
+	       KERNEL_PGD_PTRS * sizeof(pgd_t));
 
 	pgd_list_add(pgd);
 	spin_unlock_irqrestore(&pgd_lock, flags);
@@ -220,8 +290,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd)
 
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO|__GFP_COMP;
+	gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO;
 	struct page *p;
+#if L2_USER_PGTABLE_ORDER > 0
+	int i;
+#endif
 
 #ifdef CONFIG_HIGHPTE
 	flags |= __GFP_HIGHMEM;
@@ -231,6 +304,18 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 	if (p == NULL)
 		return NULL;
 
+#if L2_USER_PGTABLE_ORDER > 0
+	/*
+	 * Make every page have a page_count() of one, not just the first.
+	 * We don't use __GFP_COMP since it doesn't look like it works
+	 * correctly with tlb_remove_page().
+	 */
+	for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) {
+		init_page_count(p+i);
+		inc_zone_page_state(p+i, NR_PAGETABLE);
+	}
+#endif
+
 	pgtable_page_ctor(p);
 	return p;
 }
@@ -242,8 +327,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
  */
 void pte_free(struct mm_struct *mm, struct page *p)
 {
+	int i;
+
 	pgtable_page_dtor(p);
-	__free_pages(p, L2_USER_PGTABLE_ORDER);
+	__free_page(p);
+
+	for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) {
+		__free_page(p+i);
+		dec_zone_page_state(p+i, NR_PAGETABLE);
+	}
 }
 
 void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
@@ -252,18 +344,11 @@ void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
 	int i;
 
 	pgtable_page_dtor(pte);
-	tlb->need_flush = 1;
-	if (tlb_fast_mode(tlb)) {
-		struct page *pte_pages[L2_USER_PGTABLE_PAGES];
-		for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i)
-			pte_pages[i] = pte + i;
-		free_pages_and_swap_cache(pte_pages, L2_USER_PGTABLE_PAGES);
-		return;
-	}
-	for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i) {
-		tlb->pages[tlb->nr++] = pte + i;
-		if (tlb->nr >= FREE_PTE_NR)
-			tlb_flush_mmu(tlb, 0, 0);
+	tlb_remove_page(tlb, pte);
+
+	for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) {
+		tlb_remove_page(tlb, pte + i);
+		dec_zone_page_state(pte + i, NR_PAGETABLE);
 	}
 }
 
@@ -346,35 +431,51 @@ int get_remote_cache_cpu(pgprot_t prot)
 	return x + y * smp_width;
 }
 
-void set_pte_order(pte_t *ptep, pte_t pte, int order)
+/*
+ * Convert a kernel VA to a PA and homing information.
+ */
+int va_to_cpa_and_pte(void *va, unsigned long long *cpa, pte_t *pte)
 {
-	unsigned long pfn = pte_pfn(pte);
-	struct page *page = pfn_to_page(pfn);
+	struct page *page = virt_to_page(va);
+	pte_t null_pte = { 0 };
 
-	/* Update the home of a PTE if necessary */
-	pte = pte_set_home(pte, page_home(page));
+	*cpa = __pa(va);
 
+	/* Note that this is not writing a page table, just returning a pte. */
+	*pte = pte_set_home(null_pte, page_home(page));
+
+	return 0; /* return non-zero if not hfh? */
+}
+EXPORT_SYMBOL(va_to_cpa_and_pte);
+
+void __set_pte(pte_t *ptep, pte_t pte)
+{
 #ifdef __tilegx__
 	*ptep = pte;
 #else
-	/*
-	 * When setting a PTE, write the high bits first, then write
-	 * the low bits.  This sets the "present" bit only after the
-	 * other bits are in place.  If a particular PTE update
-	 * involves transitioning from one valid PTE to another, it
-	 * may be necessary to call set_pte_order() more than once,
-	 * transitioning via a suitable intermediate state.
-	 * Note that this sequence also means that if we are transitioning
-	 * from any migrating PTE to a non-migrating one, we will not
-	 * see a half-updated PTE with the migrating bit off.
-	 */
-#if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32
-# error Must write the present and migrating bits last
-#endif
-	((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32);
-	barrier();
-	((u32 *)ptep)[0] = (u32)(pte_val(pte));
-#endif
+# if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32
+#  error Must write the present and migrating bits last
+# endif
+	if (pte_present(pte)) {
+		((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32);
+		barrier();
+		((u32 *)ptep)[0] = (u32)(pte_val(pte));
+	} else {
+		((u32 *)ptep)[0] = (u32)(pte_val(pte));
+		barrier();
+		((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32);
+	}
+#endif /* __tilegx__ */
+}
+
+void set_pte(pte_t *ptep, pte_t pte)
+{
+	struct page *page = pfn_to_page(pte_pfn(pte));
+
+	/* Update the home of a PTE if necessary */
+	pte = pte_set_home(pte, page_home(page));
+
+	__set_pte(ptep, pte);
 }
 
 /* Can this mm load a PTE with cached_priority set? */
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index e351e14..1e78940 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -7,6 +7,7 @@ config UML
 	bool
 	default y
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_HARDIRQS_NO_DEPRECATED
 
 config MMU
 	bool
diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
index 5ee3280..02fb017 100644
--- a/arch/um/Kconfig.x86
+++ b/arch/um/Kconfig.x86
@@ -10,6 +10,8 @@ endmenu
 
 config UML_X86
 	def_bool y
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_FIND_NEXT_BIT
 
 config 64BIT
 	bool
@@ -19,6 +21,9 @@ config X86_32
 	def_bool !64BIT
 	select HAVE_AOUT
 
+config X86_64
+	def_bool 64BIT
+
 config RWSEM_XCHGADD_ALGORITHM
 	def_bool X86_XADD
 
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 050e4dd..35dd0b8 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -255,8 +255,8 @@ static const struct {
 	{ KDSIGACCEPT, KERN_INFO,  "KDSIGACCEPT" },
 };
 
-int line_ioctl(struct tty_struct *tty, struct file * file,
-	       unsigned int cmd, unsigned long arg)
+int line_ioctl(struct tty_struct *tty, unsigned int cmd,
+				unsigned long arg)
 {
 	int ret;
 	int i;
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 975613b..c70e047 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req)
 #if 0
 void mconsole_proc(struct mc_request *req)
 {
-	struct nameidata nd;
 	struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
 	struct file *file;
-	int n, err;
+	int n;
 	char *ptr = req->request.data, *buf;
 	mm_segment_t old_fs = get_fs();
 
 	ptr += strlen("proc");
 	ptr = skip_spaces(ptr);
 
-	err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd);
-	if (err) {
-		mconsole_reply(req, "Failed to look up file", 1, 0);
-		goto out;
-	}
-
-	err = may_open(&nd.path, MAY_READ, O_RDONLY);
-	if (result) {
-		mconsole_reply(req, "Failed to open file", 1, 0);
-		path_put(&nd.path);
-		goto out;
-	}
-
-	file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
-			   current_cred());
-	err = PTR_ERR(file);
+	file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
 	if (IS_ERR(file)) {
 		mconsole_reply(req, "Failed to open file", 1, 0);
-		path_put(&nd.path);
 		goto out;
 	}
 
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index ba4a98b..620f5b7 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -185,7 +185,7 @@ struct ubd {
 	.no_cow =               0, \
 	.shared =		0, \
 	.cow =			DEFAULT_COW, \
-	.lock =			SPIN_LOCK_UNLOCKED,	\
+	.lock =			__SPIN_LOCK_UNLOCKED(ubd_devs.lock), \
 	.request =		NULL, \
 	.start_sg =		0, \
 	.end_sg =		0, \
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index ac55b9e..34bede8 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -42,7 +42,7 @@
 	INIT_SETUP(0)
   }
 
-  PERCPU(32)
+  PERCPU(32, 32)
 	
   .initcall.init : {
 	INIT_CALLS
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index bed6688..d1d1b0d 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -66,7 +66,7 @@ struct thread_struct {
 	.request		= { 0 } \
 }
 
-extern struct task_struct *alloc_task_struct(void);
+extern struct task_struct *alloc_task_struct_node(int node);
 
 static inline void release_thread(struct task_struct *task)
 {
diff --git a/arch/um/include/shared/line.h b/arch/um/include/shared/line.h
index 311a0d3..72f4f25 100644
--- a/arch/um/include/shared/line.h
+++ b/arch/um/include/shared/line.h
@@ -77,8 +77,8 @@ extern int line_chars_in_buffer(struct tty_struct *tty);
 extern void line_flush_buffer(struct tty_struct *tty);
 extern void line_flush_chars(struct tty_struct *tty);
 extern int line_write_room(struct tty_struct *tty);
-extern int line_ioctl(struct tty_struct *tty, struct file * file,
-		      unsigned int cmd, unsigned long arg);
+extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
+				unsigned long arg);
 extern void line_throttle(struct tty_struct *tty);
 extern void line_unthrottle(struct tty_struct *tty);
 
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 3f0ac9e..64cfea8 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -35,8 +35,10 @@ int show_interrupts(struct seq_file *p, void *v)
 	}
 
 	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_to_desc(i);
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
@@ -46,7 +48,7 @@ int show_interrupts(struct seq_file *p, void *v)
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
 #endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", get_irq_desc_chip(desc)->name);
 		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
@@ -54,7 +56,7 @@ int show_interrupts(struct seq_file *p, void *v)
 
 		seq_putc(p, '\n');
 skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	} else if (i == NR_IRQS)
 		seq_putc(p, '\n');
 
@@ -360,10 +362,10 @@ EXPORT_SYMBOL(um_request_irq);
 EXPORT_SYMBOL(reactivate_fd);
 
 /*
- * irq_chip must define (startup || enable) &&
- * (shutdown || disable) && end
+ * irq_chip must define at least enable/disable and ack when
+ * the edge handler is used.
  */
-static void dummy(unsigned int irq)
+static void dummy(struct irq_data *d)
 {
 }
 
@@ -371,20 +373,17 @@ static void dummy(unsigned int irq)
 static struct irq_chip normal_irq_type = {
 	.name = "SIGIO",
 	.release = free_irq_by_irq_and_dev,
-	.disable = dummy,
-	.enable = dummy,
-	.ack = dummy,
-	.end = dummy
+	.irq_disable = dummy,
+	.irq_enable = dummy,
+	.irq_ack = dummy,
 };
 
 static struct irq_chip SIGVTALRM_irq_type = {
 	.name = "SIGVTALRM",
 	.release = free_irq_by_irq_and_dev,
-	.shutdown = dummy, /* never called */
-	.disable = dummy,
-	.enable = dummy,
-	.ack = dummy,
-	.end = dummy
+	.irq_disable = dummy,
+	.irq_enable = dummy,
+	.irq_ack = dummy,
 };
 
 void __init init_IRQ(void)
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index a979a22..d964a41 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -75,6 +75,8 @@ typedef struct user_i387_struct elf_fpregset_t;
 	pr_reg[16] = PT_REGS_SS(regs);		\
 } while (0);
 
+#define task_pt_regs(t) (&(t)->thread.regs)
+
 struct task_struct;
 
 extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
index b8bc844..20d363b 100644
--- a/arch/um/sys-ppc/Makefile
+++ b/arch/um/sys-ppc/Makefile
@@ -6,7 +6,7 @@ OBJ = built-in.o
 OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \
 	ptrace_user.o sysrq.o
 
-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
+asflags-y := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
 
 all: $(OBJ)
 
@@ -15,10 +15,10 @@ $(OBJ): $(OBJS)
 	$(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
 
 ptrace_user.o: ptrace_user.c
-	$(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+	$(CC) -D__KERNEL__ $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
 
 sigcontext.o: sigcontext.c
-	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+	$(CC) $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
 
 checksum.S:
 	rm -f $@
@@ -53,13 +53,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
 checksum.o: checksum.S
 	rm -f asm
 	ln -s $(srctree)/include/asm-ppc asm
-	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+	$(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
 misc.o: misc.S ppc_defs.h
 	rm -f asm
 	ln -s $(srctree)/include/asm-ppc asm
-	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+	$(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
 clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c
diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h
index d760967f..d6d5af3 100644
--- a/arch/um/sys-x86_64/asm/elf.h
+++ b/arch/um/sys-x86_64/asm/elf.h
@@ -95,6 +95,8 @@ typedef struct user_i387_struct elf_fpregset_t;
 	(pr_reg)[25] = 0;					\
 	(pr_reg)[26] = 0;
 
+#define task_pt_regs(t) (&(t)->thread.regs)
+
 struct task_struct;
 
 extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
diff --git a/arch/unicore32/.gitignore b/arch/unicore32/.gitignore
new file mode 100644
index 0000000..947e99c
--- /dev/null
+++ b/arch/unicore32/.gitignore
@@ -0,0 +1,21 @@
+#
+# Generated include files
+#
+include/generated
+#
+# Generated ld script file
+#
+kernel/vmlinux.lds
+#
+# Generated images in boot
+#
+boot/Image
+boot/zImage
+boot/uImage
+#
+# Generated files in boot/compressed
+#
+boot/compressed/piggy.S
+boot/compressed/piggy.gzip
+boot/compressed/vmlinux
+boot/compressed/vmlinux.lds
diff --git a/arch/unicore32/Kconfig b/arch/unicore32/Kconfig
new file mode 100644
index 0000000..4a36db4
--- /dev/null
+++ b/arch/unicore32/Kconfig
@@ -0,0 +1,275 @@
+config UNICORE32
+	def_bool y
+	select HAVE_MEMBLOCK
+	select HAVE_GENERIC_DMA_COHERENT
+	select HAVE_GENERIC_HARDIRQS
+	select HAVE_DMA_ATTRS
+	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_BZIP2
+	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_LZMA
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_IRQ_PROBE
+	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select ARCH_WANT_FRAME_POINTERS
+	help
+	  UniCore-32 is 32-bit Instruction Set Architecture,
+	  including a series of low-power-consumption RISC chip
+	  designs licensed by PKUnity Ltd.
+	  Please see web page at <http://www.pkunity.com/>.
+
+config HAVE_PWM
+	bool
+
+config GENERIC_GPIO
+	def_bool y
+
+config GENERIC_CLOCKEVENTS
+	bool
+
+config GENERIC_CSUM
+	def_bool y
+
+config GENERIC_IOMAP
+	def_bool y
+
+config NO_IOPORT
+	bool
+
+config STACKTRACE_SUPPORT
+	def_bool y
+
+config HAVE_LATENCYTOP_SUPPORT
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+
+config ARCH_HAS_ILOG2_U32
+	bool
+
+config ARCH_HAS_ILOG2_U64
+	bool
+
+config ARCH_HAS_CPUFREQ
+	bool
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+	def_bool y
+
+config ARCH_MAY_HAVE_PC_FDC
+	bool
+
+config NEED_DMA_MAP_STATE
+       def_bool y
+
+source "init/Kconfig"
+
+source "kernel/Kconfig.freezer"
+
+menu "System Type"
+
+config MMU
+	def_bool y
+
+config ARCH_FPGA
+	bool
+
+config ARCH_PUV3
+	def_bool y
+	select CPU_UCV2
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_CPUFREQ
+
+# CONFIGs for ARCH_PUV3
+
+if ARCH_PUV3
+
+choice
+	prompt "Board Selection"
+	default PUV3_DB0913
+
+config PUV3_FPGA_DLX200
+	select ARCH_FPGA
+	bool "FPGA board"
+
+config PUV3_DB0913
+	bool "DEBUG board (0913)"
+
+config PUV3_NB0916
+	bool "NetBook board (0916)"
+	select HAVE_PWM
+
+config PUV3_SMW0919
+	bool "Security Mini-Workstation board (0919)"
+
+endchoice
+
+config PUV3_PM
+	def_bool y if !ARCH_FPGA
+
+endif
+
+source "arch/unicore32/mm/Kconfig"
+
+comment "Floating poing support"
+
+config UNICORE_FPU_F64
+	def_bool y if !ARCH_FPGA
+
+endmenu
+
+menu "Bus support"
+
+config PCI
+	bool "PCI Support"
+	help
+	  Find out whether you have a PCI motherboard. PCI is the name of a
+	  bus system, i.e. the way the CPU talks to the other stuff inside
+	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+	  VESA. If you have PCI, say Y, otherwise N.
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+endmenu
+
+menu "Kernel Features"
+
+source "kernel/time/Kconfig"
+
+source "kernel/Kconfig.preempt"
+
+source "kernel/Kconfig.hz"
+
+source "mm/Kconfig"
+
+config LEDS
+	def_bool y
+	depends on GENERIC_GPIO
+
+config ALIGNMENT_TRAP
+	def_bool y
+	help
+	  Unicore processors can not fetch/store information which is not
+	  naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+	  address divisible by 4. On 32-bit Unicore processors, these non-aligned
+	  fetch/store instructions will be emulated in software if you say
+	  here, which has a severe performance impact. This is necessary for
+	  correct operation of some network protocols. With an IP-only
+	  configuration it is safe to say N, otherwise say Y.
+
+endmenu
+
+menu "Boot options"
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+
+config CMDLINE_FORCE
+	bool "Always use the default kernel command string"
+	depends on CMDLINE != ""
+	help
+	  Always use the default kernel command string, even if the boot
+	  loader passes other arguments to the kernel.
+	  This is useful if you cannot or don't want to change the
+	  command-line options your boot loader passes to the kernel.
+
+	  If unsure, say N.
+
+endmenu
+
+menu "Userspace binary formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+menu "Power management options"
+
+source "kernel/power/Kconfig"
+
+if ARCH_HAS_CPUFREQ
+source "drivers/cpufreq/Kconfig"
+endif
+
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y if !ARCH_FPGA
+
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y if !ARCH_FPGA
+
+endmenu
+
+source "net/Kconfig"
+
+if ARCH_PUV3
+
+config PUV3_GPIO
+	bool
+	depends on !ARCH_FPGA
+	select GENERIC_GPIO
+	select GPIO_SYSFS if EXPERIMENTAL
+	default y
+
+config PUV3_PWM
+	tristate
+	default BACKLIGHT_PWM
+	help
+	  Enable support for NB0916 PWM controllers
+
+config PUV3_RTC
+	tristate "PKUnity v3 RTC Support"
+	depends on !ARCH_FPGA
+
+if PUV3_NB0916
+
+menu "PKUnity NetBook-0916 Features"
+
+config I2C_BATTERY_BQ27200
+	tristate "I2C Battery BQ27200 Support"
+	select PUV3_I2C
+	select POWER_SUPPLY
+	select BATTERY_BQ27x00
+
+config I2C_EEPROM_AT24
+	tristate "I2C EEPROMs AT24 support"
+	select PUV3_I2C
+	select MISC_DEVICES
+	select EEPROM_AT24
+
+config LCD_BACKLIGHT
+	tristate "LCD Backlight support"
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_PWM
+
+endmenu
+
+endif
+
+endif
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/unicore32/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff --git a/arch/unicore32/Kconfig.debug b/arch/unicore32/Kconfig.debug
new file mode 100644
index 0000000..3140151
--- /dev/null
+++ b/arch/unicore32/Kconfig.debug
@@ -0,0 +1,68 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config STRICT_DEVMEM
+	bool "Filter access to /dev/mem"
+	depends on MMU
+	---help---
+	  If this option is disabled, you allow userspace (root) access to all
+	  of memory, including kernel and userspace memory. Accidental
+	  access to this is obviously disastrous, but specific access can
+	  be used by people debugging the kernel.
+
+	  If this option is switched on, the /dev/mem file only allows
+	  userspace access to memory mapped peripherals.
+
+          If in doubt, say Y.
+
+config EARLY_PRINTK
+	def_bool DEBUG_OCD
+	help
+	  Write kernel log output directly into the ocd or to a serial port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
+
+config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T output.
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+	bool "Kernel low-level debugging functions"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to include definitions of printascii, printch, printhex
+	  in the kernel.  This is helpful if you are debugging code that
+	  executes before the console is initialized.
+
+config DEBUG_OCD
+	bool "Kernel low-level debugging via On-Chip-Debugger"
+	depends on DEBUG_LL
+	default y
+	help
+	  Say Y here if you want the debug print routines to direct their
+	  output to the UniCore On-Chip-Debugger channel using CP #1.
+
+config DEBUG_OCD_BREAKPOINT
+	bool "Breakpoint support via On-Chip-Debugger"
+	depends on DEBUG_OCD
+
+config DEBUG_UART
+	int "Kernel low-level debugging messages via serial port"
+	depends on DEBUG_LL
+	range 0 1
+	default "0"
+	help
+	  Choice for UART for kernel low-level using PKUnity UARTS,
+	  should be between zero and one. The port must have been
+	  initialised by the boot-loader before use.
+
+endmenu
diff --git a/arch/unicore32/Makefile b/arch/unicore32/Makefile
new file mode 100644
index 0000000..e08d6d3
--- /dev/null
+++ b/arch/unicore32/Makefile
@@ -0,0 +1,95 @@
+#
+# arch/unicore32/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# 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) 2002~2010 by Guan Xue-tao
+#
+ifneq ($(SUBARCH),$(ARCH))
+	ifeq ($(CROSS_COMPILE),)
+		CROSS_COMPILE := $(call cc-cross-prefix, unicore32-linux-)
+	endif
+endif
+
+LDFLAGS_vmlinux		:= -p --no-undefined -X
+
+OBJCOPYFLAGS		:= -O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+# Never generate .eh_frame
+KBUILD_CFLAGS		+= $(call cc-option,-fno-dwarf2-cfi-asm)
+
+# Never use hard float in kernel
+KBUILD_CFLAGS		+= -msoft-float
+
+ifeq ($(CONFIG_FRAME_POINTER),y)
+KBUILD_CFLAGS		+= -mno-sched-prolog
+endif
+
+CHECKFLAGS		+= -D__unicore32__
+
+head-y			:= arch/unicore32/kernel/head.o
+head-y			+= arch/unicore32/kernel/init_task.o
+
+core-y			+= arch/unicore32/kernel/
+core-y			+= arch/unicore32/mm/
+
+libs-y			+= arch/unicore32/lib/
+
+ASM_GENERATED_DIR	:= $(srctree)/arch/unicore32/include/generated
+LINUXINCLUDE		+= -I$(ASM_GENERATED_DIR)
+
+ASM_GENERIC_HEADERS	:= atomic.h auxvec.h
+ASM_GENERIC_HEADERS	+= bitsperlong.h bug.h bugs.h
+ASM_GENERIC_HEADERS	+= cputime.h current.h
+ASM_GENERIC_HEADERS	+= device.h div64.h
+ASM_GENERIC_HEADERS	+= emergency-restart.h errno.h
+ASM_GENERIC_HEADERS	+= fb.h fcntl.h ftrace.h
+ASM_GENERIC_HEADERS	+= hardirq.h hw_irq.h
+ASM_GENERIC_HEADERS	+= ioctl.h ioctls.h ipcbuf.h irq_regs.h
+ASM_GENERIC_HEADERS	+= kdebug.h kmap_types.h
+ASM_GENERIC_HEADERS	+= local.h
+ASM_GENERIC_HEADERS	+= mman.h module.h msgbuf.h
+ASM_GENERIC_HEADERS	+= param.h parport.h percpu.h poll.h posix_types.h
+ASM_GENERIC_HEADERS	+= resource.h
+ASM_GENERIC_HEADERS	+= scatterlist.h sections.h segment.h sembuf.h serial.h
+ASM_GENERIC_HEADERS	+= setup.h shmbuf.h shmparam.h
+ASM_GENERIC_HEADERS	+= siginfo.h signal.h sizes.h
+ASM_GENERIC_HEADERS	+= socket.h sockios.h stat.h statfs.h swab.h syscalls.h
+ASM_GENERIC_HEADERS	+= termbits.h termios.h topology.h types.h
+ASM_GENERIC_HEADERS	+= ucontext.h unaligned.h user.h
+ASM_GENERIC_HEADERS	+= vga.h
+ASM_GENERIC_HEADERS	+= xor.h
+
+archprepare:
+ifneq ($(ASM_GENERATED_DIR), $(wildcard $(ASM_GENERATED_DIR)))
+	$(Q)mkdir -p $(ASM_GENERATED_DIR)/asm
+	$(Q)$(foreach a, $(ASM_GENERIC_HEADERS),	\
+		echo '#include <asm-generic/$a>'	\
+			> $(ASM_GENERATED_DIR)/asm/$a; )
+endif
+
+boot			:= arch/unicore32/boot
+
+# Default target when executing plain make
+KBUILD_IMAGE		:= zImage
+
+all:	$(KBUILD_IMAGE)
+
+zImage Image uImage: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+MRPROPER_DIRS		+= $(ASM_GENERATED_DIR)
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+  echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+  echo  '  uImage        - U-Boot wrapped zImage'
+endef
diff --git a/arch/unicore32/boot/Makefile b/arch/unicore32/boot/Makefile
new file mode 100644
index 0000000..79e5f88
--- /dev/null
+++ b/arch/unicore32/boot/Makefile
@@ -0,0 +1,47 @@
+#
+# arch/unicore32/boot/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2001~2010 GUAN Xue-tao
+#
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+targets := Image zImage uImage
+
+$(obj)/Image: vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: $(obj)/Image FORCE
+	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
+
+quiet_cmd_uimage = UIMAGE  $@
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A unicore -O linux -T kernel \
+		   -C none -a $(LOADADDR) -e $(STARTADDR) \
+		   -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
+$(obj)/uImage: LOADADDR=0x0
+
+$(obj)/uImage: STARTADDR=$(LOADADDR)
+
+$(obj)/uImage: $(obj)/zImage FORCE
+	$(call if_changed,uimage)
+	@echo '  Image $@ is ready'
+
+PHONY += initrd FORCE
+initrd:
+	@test "$(INITRD)" != "" || \
+	(echo You must specify INITRD; exit -1)
+
+subdir- := compressed
diff --git a/arch/unicore32/boot/compressed/Makefile b/arch/unicore32/boot/compressed/Makefile
new file mode 100644
index 0000000..9537342
--- /dev/null
+++ b/arch/unicore32/boot/compressed/Makefile
@@ -0,0 +1,68 @@
+#
+# linux/arch/unicore32/boot/compressed/Makefile
+#
+# create a compressed vmlinuz image from the original vmlinux
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2001~2010 GUAN Xue-tao
+#
+
+EXTRA_CFLAGS	:= -fpic -fno-builtin
+EXTRA_AFLAGS	:= -Wa,-march=all
+
+OBJS		:= misc.o
+
+# font.c and font.o
+CFLAGS_font.o	:= -Dstatic=
+$(obj)/font.c: $(srctree)/drivers/video/console/font_8x8.c
+	$(call cmd,shipped)
+
+# piggy.S and piggy.o
+suffix_$(CONFIG_KERNEL_GZIP)	:= gzip
+suffix_$(CONFIG_KERNEL_BZIP2)	:= bz2
+suffix_$(CONFIG_KERNEL_LZO)	:= lzo
+suffix_$(CONFIG_KERNEL_LZMA)	:= lzma
+
+$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
+	$(call if_changed,$(suffix_y))
+
+SEDFLAGS_piggy	= s/DECOMP_SUFFIX/$(suffix_y)/
+$(obj)/piggy.S: $(obj)/piggy.S.in
+	@sed "$(SEDFLAGS_piggy)" < $< > $@
+
+$(obj)/piggy.o:  $(obj)/piggy.$(suffix_y) $(obj)/piggy.S FORCE
+
+targets		:= vmlinux vmlinux.lds font.o font.c head.o misc.o \
+			piggy.$(suffix_y) piggy.o piggy.S \
+
+# Make sure files are removed during clean
+extra-y		+= piggy.gzip piggy.bz2 piggy.lzo piggy.lzma
+
+# ?
+LDFLAGS_vmlinux += -p
+# Report unresolved symbol references
+LDFLAGS_vmlinux += --no-undefined
+# Delete all temporary local symbols
+LDFLAGS_vmlinux += -X
+# Next argument is a linker script
+LDFLAGS_vmlinux += -T
+
+# For uidivmod
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \
+		$(obj)/misc.o FORCE
+	$(call if_changed,ld)
+	@:
+
+# We now have a PIC decompressor implementation.  Decompressors running
+# from RAM should not define ZTEXTADDR.  Decompressors running directly
+# from ROM or Flash must define ZTEXTADDR (preferably via the config)
+ZTEXTADDR	:= 0
+ZBSSADDR	:= ALIGN(4)
+
+SEDFLAGS_lds	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/unicore32/boot/Makefile $(KCONFIG_CONFIG)
+	@sed "$(SEDFLAGS_lds)" < $< > $@
+
diff --git a/arch/unicore32/boot/compressed/head.S b/arch/unicore32/boot/compressed/head.S
new file mode 100644
index 0000000..fbd1e37
--- /dev/null
+++ b/arch/unicore32/boot/compressed/head.S
@@ -0,0 +1,204 @@
+/*
+ * linux/arch/unicore32/boot/compressed/head.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 <mach/memory.h>
+
+#define csub	cmpsub
+#define cand	cmpand
+#define nop8	nop; nop; nop; nop; nop; nop; nop; nop
+
+		.section ".start", #alloc, #execinstr
+		.text
+start:
+		.type	start,#function
+
+		/* Initialize ASR, PRIV mode and INTR off */
+		mov	r0, #0xD3
+		mov.a	asr, r0
+
+		adr	r0, LC0
+		ldm	(r1, r2, r3, r5, r6, r7, r8), [r0]+
+		ldw	sp, [r0+], #28
+		sub.a	r0, r0, r1		@ calculate the delta offset
+
+		/*
+		 * if delta is zero, we are running at the address
+		 * we were linked at.
+		 */
+		beq	not_relocated
+
+		/*
+		 * We're running at a different address.  We need to fix
+		 * up various pointers:
+		 *   r5 - zImage base address (_start)
+		 *   r7 - GOT start
+		 *   r8 - GOT end
+		 */
+		add	r5, r5, r0
+		add	r7, r7, r0
+		add	r8, r8, r0
+
+		/*
+		 * we need to fix up pointers into the BSS region.
+		 *   r2 - BSS start
+		 *   r3 - BSS end
+		 *   sp - stack pointer
+		 */
+		add	r2, r2, r0
+		add	r3, r3, r0
+		add	sp, sp, r0
+
+		/*
+		 * Relocate all entries in the GOT table.
+		 * This fixes up the C references.
+		 *   r7 - GOT start
+		 *   r8 - GOT end
+		 */
+1001:		ldw	r1, [r7+], #0
+		add	r1, r1, r0
+		stw.w	r1, [r7]+, #4
+		csub.a	r7, r8
+		bub	1001b
+
+not_relocated:
+		/*
+		 * Clear BSS region.
+		 *   r2 - BSS start
+		 *   r3 - BSS end
+		 */
+		mov	r0, #0
+1002:		stw.w	r0, [r2]+, #4
+		csub.a	r2, r3
+		bub	1002b
+
+		/*
+		 * Turn on the cache.
+		 */
+                mov     r0, #0
+                movc    p0.c5, r0, #28		@ cache invalidate all
+                nop8
+                movc    p0.c6, r0, #6		@ tlb invalidate all
+                nop8
+
+                mov     r0, #0x1c		@ en icache and wb dcache
+                movc    p0.c1, r0, #0
+                nop8
+
+		/*
+		 * Set up some pointers, for starting decompressing.
+		 */
+
+		mov	r1, sp			@ malloc space above stack
+		add	r2, sp, #0x10000	@ 64k max
+
+		/*
+		 * Check to see if we will overwrite ourselves.
+		 *   r4 = final kernel address
+		 *   r5 = start of this image
+		 *   r6 = size of decompressed image
+		 *   r2 = end of malloc space (and therefore this image)
+		 * We basically want:
+		 *   r4 >= r2 -> OK
+		 *   r4 + image length <= r5 -> OK
+		 */
+		ldw	r4, =KERNEL_IMAGE_START
+		csub.a	r4, r2
+		bea	wont_overwrite
+		add	r0, r4, r6
+		csub.a	r0, r5
+		beb	wont_overwrite
+
+		/*
+		 * If overwrite, just print error message
+		 */
+		b	__error_overwrite
+
+		/*
+		 * We're not in danger of overwriting ourselves.
+		 * Do this the simple way.
+		 */
+wont_overwrite:
+		/*
+		 * decompress_kernel:
+		 *   r0: output_start
+		 *   r1: free_mem_ptr_p
+		 *   r2: free_mem_ptr_end_p
+		 */
+		mov	r0, r4
+		b.l	decompress_kernel	@ C functions
+
+		/*
+		 * Clean and flush the cache to maintain consistency.
+		 */
+		mov	r0, #0
+                movc    p0.c5, r0, #14		@ flush dcache
+		nop8
+                movc    p0.c5, r0, #20		@ icache invalidate all
+                nop8
+
+		/*
+		 * Turn off the Cache and MMU.
+		 */
+		mov	r0, #0			@ disable i/d cache and MMU
+		movc	p0.c1, r0, #0
+                nop8
+
+		mov	r0, #0			@ must be zero
+		ldw	r4, =KERNEL_IMAGE_START
+		mov	pc, r4			@ call kernel
+
+
+		.align	2
+		.type	LC0, #object
+LC0:		.word	LC0			@ r1
+		.word	__bss_start		@ r2
+		.word	_end			@ r3
+		.word	_start			@ r5
+		.word	_image_size		@ r6
+		.word	_got_start		@ r7
+		.word	_got_end		@ r8
+		.word	decompress_stack_end	@ sp
+		.size	LC0, . - LC0
+
+print_string:
+#ifdef CONFIG_DEBUG_OCD
+2001:		ldb.w	r1, [r0]+, #1
+		csub.a	r1, #0
+		bne	2002f
+		mov	pc, lr
+2002:
+		movc	r2, p1.c0, #0
+		cand.a	r2, #2
+		bne	2002b
+		movc	p1.c1, r1, #1
+		csub.a	r1, #'\n'
+		cmoveq	r1, #'\r'
+		beq	2002b
+		b	2001b
+#else
+		mov	pc, lr
+#endif
+
+__error_overwrite:
+		adr	r0, str_error
+		b.l	print_string
+2001:		nop8
+		b	2001b
+str_error:	.asciz	"\nError: Kernel address OVERWRITE\n"
+		.align
+
+		.ltorg
+
+		.align	4
+		.section ".stack", "aw", %nobits
+decompress_stack:	.space	4096
+decompress_stack_end:
diff --git a/arch/unicore32/boot/compressed/misc.c b/arch/unicore32/boot/compressed/misc.c
new file mode 100644
index 0000000..176d5bd
--- /dev/null
+++ b/arch/unicore32/boot/compressed/misc.c
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/unicore32/boot/compressed/misc.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/unaligned.h>
+#include <mach/uncompress.h>
+
+/*
+ * gzip delarations
+ */
+unsigned char *output_data;
+unsigned long output_ptr;
+
+unsigned int free_mem_ptr;
+unsigned int free_mem_end_ptr;
+
+#define STATIC static
+#define STATIC_RW_DATA	/* non-static please */
+
+/*
+ * arch-dependent implementations
+ */
+#ifndef ARCH_HAVE_DECOMP_ERROR
+#define arch_decomp_error(x)
+#endif
+
+#ifndef ARCH_HAVE_DECOMP_SETUP
+#define arch_decomp_setup()
+#endif
+
+#ifndef ARCH_HAVE_DECOMP_PUTS
+#define arch_decomp_puts(p)
+#endif
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	int i = 0;
+	unsigned char *d = (unsigned char *)dest, *s = (unsigned char *)src;
+
+	for (i = n >> 3; i > 0; i--) {
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (n & 1 << 2) {
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (n & 1 << 1) {
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (n & 1)
+		*d++ = *s++;
+
+	return dest;
+}
+
+void error(char *x)
+{
+	arch_decomp_puts("\n\n");
+	arch_decomp_puts(x);
+	arch_decomp_puts("\n\n -- System halted");
+
+	arch_decomp_error(x);
+
+	for (;;)
+		; /* Halt */
+}
+
+/* Heap size should be adjusted for different decompress method */
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZO
+#include "../../../../lib/decompress_unlzo.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+unsigned long decompress_kernel(unsigned long output_start,
+		unsigned long free_mem_ptr_p,
+		unsigned long free_mem_ptr_end_p)
+{
+	unsigned char *tmp;
+
+	output_data		= (unsigned char *)output_start;
+	free_mem_ptr		= free_mem_ptr_p;
+	free_mem_end_ptr	= free_mem_ptr_end_p;
+
+	arch_decomp_setup();
+
+	tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
+	output_ptr = get_unaligned_le32(tmp);
+
+	arch_decomp_puts("Uncompressing Linux...");
+	decompress(input_data, input_data_end - input_data, NULL, NULL,
+			output_data, NULL, error);
+	arch_decomp_puts(" done, booting the kernel.\n");
+	return output_ptr;
+}
diff --git a/arch/unicore32/boot/compressed/piggy.S.in b/arch/unicore32/boot/compressed/piggy.S.in
new file mode 100644
index 0000000..b79704d
--- /dev/null
+++ b/arch/unicore32/boot/compressed/piggy.S.in
@@ -0,0 +1,6 @@
+	.section .piggydata,#alloc
+	.globl	input_data
+input_data:
+	.incbin	"arch/unicore32/boot/compressed/piggy.DECOMP_SUFFIX"
+	.globl	input_data_end
+input_data_end:
diff --git a/arch/unicore32/boot/compressed/vmlinux.lds.in b/arch/unicore32/boot/compressed/vmlinux.lds.in
new file mode 100644
index 0000000..d5a3ce2
--- /dev/null
+++ b/arch/unicore32/boot/compressed/vmlinux.lds.in
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/unicore/boot/compressed/vmlinux.lds.in
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+OUTPUT_ARCH(unicore32)
+ENTRY(_start)
+SECTIONS
+{
+  /DISCARD/ : {
+    /*
+     * Discard any r/w data - this produces a link error if we have any,
+     * which is required for PIC decompression.  Local data generates
+     * GOTOFF relocations, which prevents it being relocated independently
+     * of the text/got segments.
+     */
+    *(.data)
+  }
+
+  . = TEXT_START;
+  _text = .;
+
+  .text : {
+    _start = .;
+    *(.start)
+    *(.text)
+    *(.text.*)
+    *(.fixup)
+    *(.gnu.warning)
+    *(.rodata)
+    *(.rodata.*)
+    *(.piggydata)
+    . = ALIGN(4);
+  }
+
+  _etext = .;
+
+  /* Assume size of decompressed image is 4x the compressed image */
+  _image_size = (_etext - _text) * 4;
+
+  _got_start = .;
+  .got			: { *(.got) }
+  _got_end = .;
+  .got.plt		: { *(.got.plt) }
+  _edata = .;
+
+  . = BSS_START;
+  __bss_start = .;
+  .bss			: { *(.bss) }
+  _end = .;
+
+  .stack		: { *(.stack) }
+  .comment 0		: { *(.comment) }
+}
+
diff --git a/arch/unicore32/configs/debug_defconfig b/arch/unicore32/configs/debug_defconfig
new file mode 100644
index 0000000..b5fbde9
--- /dev/null
+++ b/arch/unicore32/configs/debug_defconfig
@@ -0,0 +1,215 @@
+### General setup
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-debug"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_HOTPLUG=y
+#	Initial RAM filesystem and RAM disk (initramfs/initrd) support
+#CONFIG_BLK_DEV_INITRD=y
+#CONFIG_INITRAMFS_SOURCE="arch/unicore/ramfs/ramfs_config"
+
+### Enable loadable module support
+CONFIG_MODULES=n
+CONFIG_MODULE_UNLOAD=y
+
+### System Type
+CONFIG_ARCH_PUV3=y
+#	Board Selection
+CONFIG_PUV3_NB0916=y
+#	Processor Features
+CONFIG_CPU_DCACHE_LINE_DISABLE=y
+CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE=n
+
+### Bus support
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY=n
+
+### Boot options
+#	for debug, adding: earlyprintk=ocd,keep initcall_debug
+#	others support: test_suspend=mem root=/dev/sda
+#	hibernate support: resume=/dev/sda3
+CONFIG_CMDLINE="earlyprintk=ocd,keep ignore_loglevel"
+# TODO: mem=512M video=unifb:1024x600-16@75
+# for nfs: root=/dev/nfs rw nfsroot=192.168.10.88:/home/udb/nfs/,rsize=1024,wsize=1024
+#	ip=192.168.10.83:192.168.10.88:192.168.10.1:255.255.255.0::eth0:off
+CONFIG_CMDLINE_FORCE=y
+
+### Power management options
+CONFIG_PM=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/sda3"
+CONFIG_CPU_FREQ=n
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+
+### Networking support
+CONFIG_NET=y
+#	Networking options
+CONFIG_PACKET=m
+CONFIG_UNIX=m
+#	TCP/IP networking
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=n
+#	Wireless
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+
+### PKUnity SoC Features
+CONFIG_USB_WLAN_HED_AQ3=n
+CONFIG_USB_CMMB_INNOFIDEI=n
+CONFIG_I2C_BATTERY_BQ27200=n
+CONFIG_I2C_EEPROM_AT24=n
+CONFIG_LCD_BACKLIGHT=n
+
+CONFIG_PUV3_RTC=y
+CONFIG_PUV3_UMAL=y
+CONFIG_PUV3_MUSB=n
+CONFIG_PUV3_AC97=n
+CONFIG_PUV3_NAND=n
+CONFIG_PUV3_MMC=n
+CONFIG_PUV3_UART=n
+
+### Device Drivers
+#	Memory Technology Device (MTD) support
+CONFIG_MTD=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+#	RAM/ROM/Flash chip drivers
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_CFI_AMDSTD=m
+#	Mapping drivers for chip access
+CONFIG_MTD_PHYSMAP=m
+
+#	Block devices
+CONFIG_BLK_DEV_LOOP=m
+
+#	SCSI device support
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+
+#	Serial ATA (prod) and Parallel ATA (experimental) drivers
+CONFIG_ATA=y
+CONFIG_SATA_VIA=y
+
+#	Network device support
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_NETDEV_1000=y
+#	Wireless LAN
+CONFIG_WLAN_80211=n
+CONFIG_RT2X00=n
+CONFIG_RT73USB=n
+
+#	Input device support
+CONFIG_INPUT_EVDEV=m
+#	Keyboards
+CONFIG_KEYBOARD_GPIO=m
+
+#	I2C support
+CONFIG_I2C=y
+CONFIG_I2C_PUV3=y
+
+#	Hardware Monitoring support
+#CONFIG_SENSORS_LM75=m
+#	Generic Thermal sysfs driver
+#CONFIG_THERMAL=m
+#CONFIG_THERMAL_HWMON=y
+
+#	Multimedia support
+CONFIG_MEDIA_SUPPORT=n
+CONFIG_VIDEO_DEV=n
+CONFIG_USB_VIDEO_CLASS=n
+
+#	Graphics support
+CONFIG_FB=y
+CONFIG_FB_PUV3_UNIGFX=y
+#	Console display driver support
+CONFIG_VGA_CONSOLE=n
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+#	Bootup logo
+CONFIG_LOGO=n
+
+#	Sound card support
+CONFIG_SOUND=m
+#	Advanced Linux Sound Architecture
+CONFIG_SND=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+
+#	USB support
+CONFIG_USB_ARCH_HAS_HCD=n
+CONFIG_USB=n
+CONFIG_USB_DEVICEFS=n
+CONFIG_USB_PRINTER=n
+CONFIG_USB_STORAGE=n
+#	Inventra Highspeed Dual Role Controller
+CONFIG_USB_MUSB_HDRC=n
+
+#	LED Support
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+#	LED Triggers
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+
+#	Real Time Clock
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+### File systems
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=m
+#	CD-ROM/DVD Filesystems
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+#	DOS/FAT/NT Filesystems
+CONFIG_VFAT_FS=m
+#	Pseudo filesystems
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+#	Miscellaneous filesystems
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_JFFS2_FS=m
+CONFIG_UBIFS_FS=m
+#	Network File Systems
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+#	Partition Types
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MSDOS_PARTITION=y
+#	Native language support
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
+
+### Kernel hacking
+CONFIG_FRAME_WARN=8096
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_LOCKING=n
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_LL=y
+
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
new file mode 100644
index 0000000..b200fda
--- /dev/null
+++ b/arch/unicore32/include/asm/Kbuild
@@ -0,0 +1,2 @@
+include include/asm-generic/Kbuild.asm
+
diff --git a/arch/unicore32/include/asm/assembler.h b/arch/unicore32/include/asm/assembler.h
new file mode 100644
index 0000000..8e87ed7
--- /dev/null
+++ b/arch/unicore32/include/asm/assembler.h
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/unicore32/include/asm/assembler.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 include any C declarations in this file - it is included by
+ *  assembler source.
+ */
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
+#endif
+
+#include <asm/ptrace.h>
+
+/*
+ * Little Endian independent macros for shifting bytes within registers.
+ */
+#define pull            >>
+#define push            <<
+#define get_byte_0      << #0
+#define get_byte_1	>> #8
+#define get_byte_2	>> #16
+#define get_byte_3	>> #24
+#define put_byte_0      << #0
+#define put_byte_1	<< #8
+#define put_byte_2	<< #16
+#define put_byte_3	<< #24
+
+#define cadd		cmpadd
+#define cand		cmpand
+#define csub		cmpsub
+#define cxor		cmpxor
+
+/*
+ * Enable and disable interrupts
+ */
+	.macro disable_irq, temp
+	mov	\temp, asr
+	andn     \temp, \temp, #0xFF
+	or	\temp, \temp, #PSR_I_BIT | PRIV_MODE
+	mov.a	asr, \temp
+	.endm
+
+	.macro enable_irq, temp
+	mov	\temp, asr
+	andn     \temp, \temp, #0xFF
+	or	\temp, \temp, #PRIV_MODE
+	mov.a	asr, \temp
+	.endm
+
+#define USER(x...)				\
+9999:	x;					\
+	.pushsection __ex_table, "a";		\
+	.align	3;				\
+	.long	9999b, 9001f;			\
+	.popsection
+
+	.macro	notcond, cond, nexti = .+8
+	.ifc	\cond, eq
+		bne	\nexti
+	.else;	.ifc	\cond, ne
+		beq	\nexti
+	.else;	.ifc	\cond, ea
+		bub	\nexti
+	.else;	.ifc	\cond, ub
+		bea	\nexti
+	.else;	.ifc	\cond, fs
+		bns	\nexti
+	.else;	.ifc	\cond, ns
+		bfs	\nexti
+	.else;	.ifc	\cond, fv
+		bnv	\nexti
+	.else;	.ifc	\cond, nv
+		bfv	\nexti
+	.else;	.ifc	\cond, ua
+		beb	\nexti
+	.else;	.ifc	\cond, eb
+		bua	\nexti
+	.else;	.ifc	\cond, eg
+		bsl	\nexti
+	.else;	.ifc	\cond, sl
+		beg	\nexti
+	.else;	.ifc	\cond, sg
+		bel	\nexti
+	.else;	.ifc	\cond, el
+		bsg	\nexti
+	.else;	.ifnc	\cond, al
+		.error  "Unknown cond in notcond macro argument"
+	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
+	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
+	.endif
+	.endm
+
+	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
+	.rept	\rept
+	notcond	\cond, .+8
+9999 :
+	.if	\inc == 1
+	\instr\()b.u \reg, [\ptr], #\inc
+	.elseif	\inc == 4
+	\instr\()w.u \reg, [\ptr], #\inc
+	.else
+	.error	"Unsupported inc macro argument"
+	.endif
+
+	.pushsection __ex_table, "a"
+	.align	3
+	.long	9999b, \abort
+	.popsection
+	.endr
+	.endm
+
+	.macro	strusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
+	usracc	st, \reg, \ptr, \inc, \cond, \rept, \abort
+	.endm
+
+	.macro	ldrusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
+	usracc	ld, \reg, \ptr, \inc, \cond, \rept, \abort
+	.endm
+
+	.macro	nop8
+	.rept	8
+		nop
+	.endr
+	.endm
diff --git a/arch/unicore32/include/asm/bitops.h b/arch/unicore32/include/asm/bitops.h
new file mode 100644
index 0000000..1628a63
--- /dev/null
+++ b/arch/unicore32/include/asm/bitops.h
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/unicore32/include/asm/bitops.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_BITOPS_H__
+#define __UNICORE_BITOPS_H__
+
+#define find_next_bit		__uc32_find_next_bit
+#define find_next_zero_bit	__uc32_find_next_zero_bit
+
+#define find_first_bit		__uc32_find_first_bit
+#define find_first_zero_bit	__uc32_find_first_zero_bit
+
+#define _ASM_GENERIC_BITOPS_FLS_H_
+#define _ASM_GENERIC_BITOPS___FLS_H_
+#define _ASM_GENERIC_BITOPS_FFS_H_
+#define _ASM_GENERIC_BITOPS___FFS_H_
+/*
+ * On UNICORE, those functions can be implemented around
+ * the cntlz instruction for much better code efficiency.
+ */
+
+static inline int fls(int x)
+{
+	int ret;
+
+	asm("cntlz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
+	ret = 32 - ret;
+
+	return ret;
+}
+
+#define __fls(x) (fls(x) - 1)
+#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
+#define __ffs(x) (ffs(x) - 1)
+
+#include <asm-generic/bitops.h>
+
+#endif /* __UNICORE_BITOPS_H__ */
diff --git a/arch/unicore32/include/asm/byteorder.h b/arch/unicore32/include/asm/byteorder.h
new file mode 100644
index 0000000..ebe1b3f
--- /dev/null
+++ b/arch/unicore32/include/asm/byteorder.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/asm/byteorder.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UniCore ONLY support Little Endian mode, the data bus is connected such
+ * that byte accesses appear as:
+ *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
+ * and word accesses (data or instruction) appear as:
+ *  d0...d31
+ */
+#ifndef __UNICORE_BYTEORDER_H__
+#define __UNICORE_BYTEORDER_H__
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
+
diff --git a/arch/unicore32/include/asm/cache.h b/arch/unicore32/include/asm/cache.h
new file mode 100644
index 0000000..ad8f795
--- /dev/null
+++ b/arch/unicore32/include/asm/cache.h
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/unicore32/include/asm/cache.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_CACHE_H__
+#define __UNICORE_CACHE_H__
+
+#define L1_CACHE_SHIFT		(5)
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+/*
+ * Memory returned by kmalloc() may be used for DMA, so we must make
+ * sure that all such allocations are cache aligned. Otherwise,
+ * unrelated code may cause parts of the buffer to be read into the
+ * cache before the transfer is done, causing old data to be seen by
+ * the CPU.
+ */
+#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
+
+#endif
diff --git a/arch/unicore32/include/asm/cacheflush.h b/arch/unicore32/include/asm/cacheflush.h
new file mode 100644
index 0000000..c0301e6
--- /dev/null
+++ b/arch/unicore32/include/asm/cacheflush.h
@@ -0,0 +1,211 @@
+/*
+ * linux/arch/unicore32/include/asm/cacheflush.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_CACHEFLUSH_H__
+#define __UNICORE_CACHEFLUSH_H__
+
+#include <linux/mm.h>
+
+#include <asm/shmparam.h>
+
+#define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
+
+/*
+ * This flag is used to indicate that the page pointed to by a pte is clean
+ * and does not require cleaning before returning it to the user.
+ */
+#define PG_dcache_clean PG_arch_1
+
+/*
+ *	MM Cache Management
+ *	===================
+ *
+ *	The arch/unicore32/mm/cache.S files implement these methods.
+ *
+ *	Start addresses are inclusive and end addresses are exclusive;
+ *	start addresses should be rounded down, end addresses up.
+ *
+ *	See Documentation/cachetlb.txt for more information.
+ *	Please note that the implementation of these, and the required
+ *	effects are cache-type (VIVT/VIPT/PIPT) specific.
+ *
+ *	flush_icache_all()
+ *
+ *		Unconditionally clean and invalidate the entire icache.
+ *		Currently only needed for cache-v6.S and cache-v7.S, see
+ *		__flush_icache_all for the generic implementation.
+ *
+ *	flush_kern_all()
+ *
+ *		Unconditionally clean and invalidate the entire cache.
+ *
+ *	flush_user_all()
+ *
+ *		Clean and invalidate all user space cache entries
+ *		before a change of page tables.
+ *
+ *	flush_user_range(start, end, flags)
+ *
+ *		Clean and invalidate a range of cache entries in the
+ *		specified address space before a change of page tables.
+ *		- start - user start address (inclusive, page aligned)
+ *		- end   - user end address   (exclusive, page aligned)
+ *		- flags - vma->vm_flags field
+ *
+ *	coherent_kern_range(start, end)
+ *
+ *		Ensure coherency between the Icache and the Dcache in the
+ *		region described by start, end.  If you have non-snooping
+ *		Harvard caches, you need to implement this function.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	coherent_user_range(start, end)
+ *
+ *		Ensure coherency between the Icache and the Dcache in the
+ *		region described by start, end.  If you have non-snooping
+ *		Harvard caches, you need to implement this function.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	flush_kern_dcache_area(kaddr, size)
+ *
+ *		Ensure that the data held in page is written back.
+ *		- kaddr  - page address
+ *		- size   - region size
+ *
+ *	DMA Cache Coherency
+ *	===================
+ *
+ *	dma_flush_range(start, end)
+ *
+ *		Clean and invalidate the specified virtual address range.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ */
+
+extern void __cpuc_flush_icache_all(void);
+extern void __cpuc_flush_kern_all(void);
+extern void __cpuc_flush_user_all(void);
+extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
+extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
+extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
+extern void __cpuc_flush_dcache_area(void *, size_t);
+extern void __cpuc_flush_kern_dcache_area(void *addr, size_t size);
+
+/*
+ * These are private to the dma-mapping API.  Do not use directly.
+ * Their sole purpose is to ensure that data held in the cache
+ * is visible to DMA, or data written by DMA to system memory is
+ * visible to the CPU.
+ */
+extern void __cpuc_dma_clean_range(unsigned long, unsigned long);
+extern void __cpuc_dma_flush_range(unsigned long, unsigned long);
+
+/*
+ * Copy user data from/to a page which is mapped into a different
+ * processes address space.  Really, we want to allow our "user
+ * space" model to handle this.
+ */
+extern void copy_to_user_page(struct vm_area_struct *, struct page *,
+	unsigned long, void *, const void *, unsigned long);
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)	\
+	do {							\
+		memcpy(dst, src, len);				\
+	} while (0)
+
+/*
+ * Convert calls to our calling convention.
+ */
+/* Invalidate I-cache */
+static inline void __flush_icache_all(void)
+{
+	asm("movc	p0.c5, %0, #20;\n"
+	    "nop; nop; nop; nop; nop; nop; nop; nop\n"
+	    :
+	    : "r" (0));
+}
+
+#define flush_cache_all()		__cpuc_flush_kern_all()
+
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma,
+		unsigned long start, unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma,
+		unsigned long user_addr, unsigned long pfn);
+
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
+/*
+ * flush_cache_user_range is used when we want to ensure that the
+ * Harvard caches are synchronised for the user space address range.
+ * This is used for the UniCore private sys_cacheflush system call.
+ */
+#define flush_cache_user_range(vma, start, end) \
+	__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
+
+/*
+ * Perform necessary cache operations to ensure that data previously
+ * stored within this range of addresses can be executed by the CPU.
+ */
+#define flush_icache_range(s, e)	__cpuc_coherent_kern_range(s, e)
+
+/*
+ * Perform necessary cache operations to ensure that the TLB will
+ * see data written in the specified area.
+ */
+#define clean_dcache_area(start, size)	cpu_dcache_clean_area(start, size)
+
+/*
+ * flush_dcache_page is used when the kernel has written to the page
+ * cache page at virtual address page->virtual.
+ *
+ * If this page isn't mapped (ie, page_mapping == NULL), or it might
+ * have userspace mappings, then we _must_ always clean + invalidate
+ * the dcache entries associated with the kernel mapping.
+ *
+ * Otherwise we can defer the operation, and clean the cache when we are
+ * about to change to user space.  This is the same method as used on SPARC64.
+ * See update_mmu_cache for the user space part.
+ */
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+extern void flush_dcache_page(struct page *);
+
+#define flush_dcache_mmap_lock(mapping)			\
+	spin_lock_irq(&(mapping)->tree_lock)
+#define flush_dcache_mmap_unlock(mapping)		\
+	spin_unlock_irq(&(mapping)->tree_lock)
+
+#define flush_icache_user_range(vma, page, addr, len)	\
+	flush_dcache_page(page)
+
+/*
+ * We don't appear to need to do anything here.  In fact, if we did, we'd
+ * duplicate cache flushing elsewhere performed by flush_dcache_page().
+ */
+#define flush_icache_page(vma, page)	do { } while (0)
+
+/*
+ * flush_cache_vmap() is used when creating mappings (eg, via vmap,
+ * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
+ * caches, since the direct-mappings of these pages may contain cached
+ * data, we need to do a full cache flush to ensure that writebacks
+ * don't corrupt data placed into these pages via the new mappings.
+ */
+static inline void flush_cache_vmap(unsigned long start, unsigned long end)
+{
+}
+
+static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
+{
+}
+
+#endif
diff --git a/arch/unicore32/include/asm/checksum.h b/arch/unicore32/include/asm/checksum.h
new file mode 100644
index 0000000..f55c3f9
--- /dev/null
+++ b/arch/unicore32/include/asm/checksum.h
@@ -0,0 +1,41 @@
+/*
+ * linux/arch/unicore32/include/asm/checksum.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * IP checksum routines
+ */
+#ifndef __UNICORE_CHECKSUM_H__
+#define __UNICORE_CHECKSUM_H__
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+		   unsigned short proto, __wsum sum)
+{
+	__asm__(
+	"add.a	%0, %1, %2\n"
+	"addc.a	%0, %0, %3\n"
+	"addc.a	%0, %0, %4 << #8\n"
+	"addc.a	%0, %0, %5\n"
+	"addc	%0, %0, #0\n"
+	: "=&r"(sum)
+	: "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
+	: "cc");
+	return sum;
+}
+#define csum_tcpudp_nofold	csum_tcpudp_nofold
+
+#include <asm-generic/checksum.h>
+
+#endif
diff --git a/arch/unicore32/include/asm/cpu-single.h b/arch/unicore32/include/asm/cpu-single.h
new file mode 100644
index 0000000..0f55d18
--- /dev/null
+++ b/arch/unicore32/include/asm/cpu-single.h
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/unicore32/include/asm/cpu-single.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_CPU_SINGLE_H__
+#define __UNICORE_CPU_SINGLE_H__
+
+#include <asm/page.h>
+#include <asm/memory.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#define cpu_switch_mm(pgd, mm) cpu_do_switch_mm(virt_to_phys(pgd), mm)
+
+#define cpu_get_pgd()					\
+	({						\
+		unsigned long pg;			\
+		__asm__("movc	%0, p0.c2, #0"		\
+			 : "=r" (pg) : : "cc");		\
+		pg &= ~0x0fff;				\
+		(pgd_t *)phys_to_virt(pg);		\
+	})
+
+struct mm_struct;
+
+/* declare all the functions as extern */
+extern void cpu_proc_fin(void);
+extern int cpu_do_idle(void);
+extern void cpu_dcache_clean_area(void *, int);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_set_pte(pte_t *ptep, pte_t pte);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* __UNICORE_CPU_SINGLE_H__ */
diff --git a/arch/unicore32/include/asm/cputype.h b/arch/unicore32/include/asm/cputype.h
new file mode 100644
index 0000000..ec1a30f
--- /dev/null
+++ b/arch/unicore32/include/asm/cputype.h
@@ -0,0 +1,33 @@
+/*
+ * linux/arch/unicore32/include/asm/cputype.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_CPUTYPE_H__
+#define __UNICORE_CPUTYPE_H__
+
+#include <linux/stringify.h>
+
+#define CPUID_CPUID	0
+#define CPUID_CACHETYPE	1
+
+#define read_cpuid(reg)							\
+	({								\
+		unsigned int __val;					\
+		asm("movc	%0, p0.c0, #" __stringify(reg)		\
+		    : "=r" (__val)					\
+		    :							\
+		    : "cc");						\
+		__val;							\
+	})
+
+#define uc32_cpuid		read_cpuid(CPUID_CPUID)
+#define uc32_cachetype		read_cpuid(CPUID_CACHETYPE)
+
+#endif
diff --git a/arch/unicore32/include/asm/delay.h b/arch/unicore32/include/asm/delay.h
new file mode 100644
index 0000000..164ae61
--- /dev/null
+++ b/arch/unicore32/include/asm/delay.h
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/unicore32/include/asm/delay.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Delay routines, using a pre-computed "loops_per_second" value.
+ */
+#ifndef __UNICORE_DELAY_H__
+#define __UNICORE_DELAY_H__
+
+#include <asm/param.h>	/* HZ */
+
+extern void __delay(int loops);
+
+/*
+ * This function intentionally does not exist; if you see references to
+ * it, it means that you're calling udelay() with an out of range value.
+ *
+ * With currently imposed limits, this means that we support a max delay
+ * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
+ */
+extern void __bad_udelay(void);
+
+/*
+ * division by multiplication: you don't have to worry about
+ * loss of precision.
+ *
+ * Use only for very small delays ( < 1 msec).  Should probably use a
+ * lookup table, really, as the multiplications take much too long with
+ * short delays.  This is a "reasonable" implementation, though (and the
+ * first constant multiplications gets optimized away if the delay is
+ * a constant)
+ */
+extern void __udelay(unsigned long usecs);
+extern void __const_udelay(unsigned long);
+
+#define MAX_UDELAY_MS 2
+
+#define udelay(n)							\
+	(__builtin_constant_p(n) ?					\
+	  ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :		\
+			__const_udelay((n) * ((2199023U*HZ)>>11))) :	\
+	  __udelay(n))
+
+#endif /* __UNICORE_DELAY_H__ */
+
diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
new file mode 100644
index 0000000..9258e59
--- /dev/null
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/unicore32/include/asm/dma-mapping.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_DMA_MAPPING_H__
+#define __UNICORE_DMA_MAPPING_H__
+
+#ifdef __KERNEL__
+
+#include <linux/mm_types.h>
+#include <linux/scatterlist.h>
+#include <linux/swiotlb.h>
+
+#include <asm-generic/dma-coherent.h>
+
+#include <asm/memory.h>
+#include <asm/cacheflush.h>
+
+extern struct dma_map_ops swiotlb_dma_map_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	return &swiotlb_dma_map_ops;
+}
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (unlikely(dma_ops == NULL))
+		return 0;
+
+	return dma_ops->dma_supported(dev, mask);
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops->mapping_error)
+		return dma_ops->mapping_error(dev, dma_addr);
+
+	return 0;
+}
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (dev && dev->dma_mask)
+		return addr + size - 1 <= *dev->dma_mask;
+
+	return 1;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return paddr;
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return daddr;
+}
+
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	*dev->dma_mask = dma_mask;
+
+	return 0;
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+				     void *cpu_addr, dma_addr_t dma_handle)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+static inline void dma_cache_sync(struct device *dev, void *vaddr,
+		size_t size, enum dma_data_direction direction)
+{
+	unsigned long start = (unsigned long)vaddr;
+	unsigned long end   = start + size;
+
+	switch (direction) {
+	case DMA_NONE:
+		BUG();
+	case DMA_FROM_DEVICE:
+	case DMA_BIDIRECTIONAL:	/* writeback and invalidate */
+		__cpuc_dma_flush_range(start, end);
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		__cpuc_dma_clean_range(start, end);
+		break;
+	}
+}
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/unicore32/include/asm/dma.h b/arch/unicore32/include/asm/dma.h
new file mode 100644
index 0000000..38dfff9
--- /dev/null
+++ b/arch/unicore32/include/asm/dma.h
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/unicore32/include/asm/dma.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_DMA_H__
+#define __UNICORE_DMA_H__
+
+#include <asm/memory.h>
+#include <asm-generic/dma.h>
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#endif
+
+#endif /* __UNICORE_DMA_H__ */
diff --git a/arch/unicore32/include/asm/elf.h b/arch/unicore32/include/asm/elf.h
new file mode 100644
index 0000000..829042d
--- /dev/null
+++ b/arch/unicore32/include/asm/elf.h
@@ -0,0 +1,94 @@
+/*
+ * linux/arch/unicore32/include/asm/elf.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_ELF_H__
+#define __UNICORE_ELF_H__
+
+#include <asm/hwcap.h>
+
+/*
+ * ELF register definitions..
+ */
+#include <asm/ptrace.h>
+
+typedef unsigned long elf_greg_t;
+typedef unsigned long elf_freg_t[3];
+
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct fp_state elf_fpregset_t;
+
+#define EM_UNICORE		110
+
+#define R_UNICORE_NONE		0
+#define R_UNICORE_PC24		1
+#define R_UNICORE_ABS32		2
+#define R_UNICORE_CALL		28
+#define R_UNICORE_JUMP24	29
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_UNICORE
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ *
+ */
+#define ELF_PLATFORM_SIZE 8
+#define ELF_PLATFORM	(elf_platform)
+
+extern char elf_platform[];
+
+struct elf32_hdr;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+extern int elf_check_arch(const struct elf32_hdr *);
+#define elf_check_arch elf_check_arch
+
+struct task_struct;
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
+#define ELF_CORE_COPY_TASK_REGS dump_task_regs
+
+#define ELF_EXEC_PAGESIZE	4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE	(2 * TASK_SIZE / 3)
+
+/* When the program starts, a1 contains a pointer to a function to be
+   registered with atexit, as per the SVR4 ABI.  A value of 0 means we
+   have no such handler.  */
+#define ELF_PLAT_INIT(_r, load_addr)	{(_r)->UCreg_00 = 0; }
+
+extern void elf_set_personality(const struct elf32_hdr *);
+#define SET_PERSONALITY(ex)	elf_set_personality(&(ex))
+
+struct mm_struct;
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
+extern int vectors_user_mapping(void);
+#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+
+#endif
diff --git a/arch/unicore32/include/asm/fpstate.h b/arch/unicore32/include/asm/fpstate.h
new file mode 100644
index 0000000..ba97fac
--- /dev/null
+++ b/arch/unicore32/include/asm/fpstate.h
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/unicore32/include/asm/fpstate.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_FPSTATE_H__
+#define __UNICORE_FPSTATE_H__
+
+#ifndef __ASSEMBLY__
+
+#define FP_REGS_NUMBER		33
+
+struct fp_state {
+	unsigned int regs[FP_REGS_NUMBER];
+} __attribute__((aligned(8)));
+
+#endif
+
+#endif
diff --git a/arch/unicore32/include/asm/fpu-ucf64.h b/arch/unicore32/include/asm/fpu-ucf64.h
new file mode 100644
index 0000000..16c1457
--- /dev/null
+++ b/arch/unicore32/include/asm/fpu-ucf64.h
@@ -0,0 +1,53 @@
+/*
+ * linux/arch/unicore32/include/asm/fpu-ucf64.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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 FPSCR			s31
+
+/* FPSCR bits */
+#define FPSCR_DEFAULT_NAN	(1<<25)
+
+#define FPSCR_CMPINSTR_BIT	(1<<31)
+
+#define FPSCR_CON		(1<<29)
+#define FPSCR_TRAP		(1<<27)
+
+/* RND mode */
+#define FPSCR_ROUND_NEAREST	(0<<0)
+#define FPSCR_ROUND_PLUSINF	(2<<0)
+#define FPSCR_ROUND_MINUSINF	(3<<0)
+#define FPSCR_ROUND_TOZERO	(1<<0)
+#define FPSCR_RMODE_BIT		(0)
+#define FPSCR_RMODE_MASK	(7 << FPSCR_RMODE_BIT)
+
+/* trap enable */
+#define FPSCR_IOE		(1<<16)
+#define FPSCR_OFE		(1<<14)
+#define FPSCR_UFE		(1<<13)
+#define FPSCR_IXE		(1<<12)
+#define FPSCR_HIE		(1<<11)
+#define FPSCR_NDE		(1<<10)	/* non denomal */
+
+/* flags */
+#define FPSCR_IDC		(1<<24)
+#define FPSCR_HIC		(1<<23)
+#define FPSCR_IXC		(1<<22)
+#define FPSCR_OFC		(1<<21)
+#define FPSCR_UFC		(1<<20)
+#define FPSCR_IOC		(1<<19)
+
+/* stick bits */
+#define FPSCR_IOS		(1<<9)
+#define FPSCR_OFS		(1<<7)
+#define FPSCR_UFS		(1<<6)
+#define FPSCR_IXS		(1<<5)
+#define FPSCR_HIS		(1<<4)
+#define FPSCR_NDS		(1<<3)	/*non denomal */
diff --git a/arch/unicore32/include/asm/futex.h b/arch/unicore32/include/asm/futex.h
new file mode 100644
index 0000000..07dea61
--- /dev/null
+++ b/arch/unicore32/include/asm/futex.h
@@ -0,0 +1,143 @@
+/*
+ * linux/arch/unicore32/include/asm/futex.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_FUTEX_H__
+#define __UNICORE_FUTEX_H__
+
+#ifdef __KERNEL__
+
+#include <linux/futex.h>
+#include <linux/preempt.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)	\
+	__asm__ __volatile__(					\
+	"1:	ldw.u	%1, [%2]\n"				\
+	"	" insn "\n"					\
+	"2:	stw.u	%0, [%2]\n"				\
+	"	mov	%0, #0\n"				\
+	"3:\n"							\
+	"	.pushsection __ex_table,\"a\"\n"		\
+	"	.align	3\n"					\
+	"	.long	1b, 4f, 2b, 4f\n"			\
+	"	.popsection\n"					\
+	"	.pushsection .fixup,\"ax\"\n"			\
+	"4:	mov	%0, %4\n"				\
+	"	b	3b\n"					\
+	"	.popsection"					\
+	: "=&r" (ret), "=&r" (oldval)				\
+	: "r" (uaddr), "r" (oparg), "Ir" (-EFAULT)		\
+	: "cc", "memory")
+
+static inline int
+futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+{
+	int op = (encoded_op >> 28) & 7;
+	int cmp = (encoded_op >> 24) & 15;
+	int oparg = (encoded_op << 8) >> 20;
+	int cmparg = (encoded_op << 20) >> 20;
+	int oldval = 0, ret;
+
+	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+		oparg = 1 << oparg;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();	/* implies preempt_disable() */
+
+	switch (op) {
+	case FUTEX_OP_SET:
+		__futex_atomic_op("mov	%0, %3", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ADD:
+		__futex_atomic_op("add	%0, %1, %3", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_OR:
+		__futex_atomic_op("or	%0, %1, %3", ret, oldval, uaddr, oparg);
+		break;
+	case FUTEX_OP_ANDN:
+		__futex_atomic_op("and	%0, %1, %3",
+				ret, oldval, uaddr, ~oparg);
+		break;
+	case FUTEX_OP_XOR:
+		__futex_atomic_op("xor	%0, %1, %3", ret, oldval, uaddr, oparg);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	pagefault_enable();	/* subsumes preempt_enable() */
+
+	if (!ret) {
+		switch (cmp) {
+		case FUTEX_OP_CMP_EQ:
+			ret = (oldval == cmparg);
+			break;
+		case FUTEX_OP_CMP_NE:
+			ret = (oldval != cmparg);
+			break;
+		case FUTEX_OP_CMP_LT:
+			ret = (oldval <  cmparg);
+			break;
+		case FUTEX_OP_CMP_GE:
+			ret = (oldval >= cmparg);
+			break;
+		case FUTEX_OP_CMP_LE:
+			ret = (oldval <= cmparg);
+			break;
+		case FUTEX_OP_CMP_GT:
+			ret = (oldval >  cmparg);
+			break;
+		default:
+			ret = -ENOSYS;
+		}
+	}
+	return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+	int val;
+
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+		return -EFAULT;
+
+	pagefault_disable();	/* implies preempt_disable() */
+
+	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
+	"1:	ldw.u	%0, [%3]\n"
+	"	cmpxor.a	%0, %1\n"
+	"	bne	3f\n"
+	"2:	stw.u	%2, [%3]\n"
+	"3:\n"
+	"	.pushsection __ex_table,\"a\"\n"
+	"	.align	3\n"
+	"	.long	1b, 4f, 2b, 4f\n"
+	"	.popsection\n"
+	"	.pushsection .fixup,\"ax\"\n"
+	"4:	mov	%0, %4\n"
+	"	b	3b\n"
+	"	.popsection"
+	: "=&r" (val)
+	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
+	: "cc", "memory");
+
+	pagefault_enable();	/* subsumes preempt_enable() */
+
+	return val;
+}
+
+#endif /* __KERNEL__ */
+#endif /* __UNICORE_FUTEX_H__ */
diff --git a/arch/unicore32/include/asm/gpio.h b/arch/unicore32/include/asm/gpio.h
new file mode 100644
index 0000000..2716f14
--- /dev/null
+++ b/arch/unicore32/include/asm/gpio.h
@@ -0,0 +1,104 @@
+/*
+ * linux/arch/unicore32/include/asm/gpio.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_GPIO_H__
+#define __UNICORE_GPIO_H__
+
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm-generic/gpio.h>
+
+#define GPI_OTP_INT             0
+#define GPI_PCI_INTA            1
+#define GPI_PCI_INTB            2
+#define GPI_PCI_INTC            3
+#define GPI_PCI_INTD            4
+#define GPI_BAT_DET             5
+#define GPI_SD_CD               6
+#define GPI_SOFF_REQ            7
+#define GPI_SD_WP               8
+#define GPI_LCD_CASE_OFF        9
+#define GPO_WIFI_EN             10
+#define GPO_HDD_LED             11
+#define GPO_VGA_EN              12
+#define GPO_LCD_EN              13
+#define GPO_LED_DATA            14
+#define GPO_LED_CLK             15
+#define GPO_CAM_PWR_EN          16
+#define GPO_LCD_VCC_EN          17
+#define GPO_SOFT_OFF            18
+#define GPO_BT_EN               19
+#define GPO_FAN_ON              20
+#define GPO_SPKR                21
+#define GPO_SET_V1              23
+#define GPO_SET_V2              24
+#define GPO_CPU_HEALTH          25
+#define GPO_LAN_SEL             26
+
+#ifdef CONFIG_PUV3_NB0916
+#define GPI_BTN_TOUCH		14
+#define GPIO_IN			0x000043ff /* 1 for input */
+#define GPIO_OUT		0x0fffbc00 /* 1 for output */
+#endif	/* CONFIG_PUV3_NB0916 */
+
+#ifdef CONFIG_PUV3_SMW0919
+#define GPIO_IN			0x000003ff /* 1 for input */
+#define GPIO_OUT		0x0ffffc00 /* 1 for output */
+#endif  /* CONFIG_PUV3_SMW0919 */
+
+#ifdef CONFIG_PUV3_DB0913
+#define GPIO_IN			0x000001df /* 1 for input */
+#define GPIO_OUT		0x03fee800 /* 1 for output */
+#endif  /* CONFIG_PUV3_DB0913 */
+
+#define GPIO_DIR                (~((GPIO_IN) | 0xf0000000))
+				/* 0 input, 1 output */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
+		return readl(GPIO_GPLR) & GPIO_GPIO(gpio);
+	else
+		return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
+		if (value)
+			writel(GPIO_GPIO(gpio), GPIO_GPSR);
+		else
+			writel(GPIO_GPIO(gpio), GPIO_GPCR);
+	else
+		__gpio_set_value(gpio, value);
+}
+
+#define gpio_cansleep	__gpio_cansleep
+
+static inline unsigned gpio_to_irq(unsigned gpio)
+{
+	if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & readl(GPIO_GPIR)))
+		return IRQ_GPIOLOW0 + gpio;
+	else
+		return IRQ_GPIO0 + gpio;
+}
+
+static inline unsigned irq_to_gpio(unsigned irq)
+{
+	if (irq < IRQ_GPIOHIGH)
+		return irq - IRQ_GPIOLOW0;
+	else
+		return irq - IRQ_GPIO0;
+}
+
+#endif /* __UNICORE_GPIO_H__ */
diff --git a/arch/unicore32/include/asm/hwcap.h b/arch/unicore32/include/asm/hwcap.h
new file mode 100644
index 0000000..97bd40f
--- /dev/null
+++ b/arch/unicore32/include/asm/hwcap.h
@@ -0,0 +1,32 @@
+/*
+ * linux/arch/unicore32/include/asm/hwcap.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_HWCAP_H__
+#define __UNICORE_HWCAP_H__
+
+/*
+ * HWCAP flags
+ */
+#define HWCAP_MSP		1
+#define HWCAP_UNICORE16		2
+#define HWCAP_CMOV		4
+#define HWCAP_UNICORE_F64       8
+#define HWCAP_TLS		0x80
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP		(HWCAP_CMOV | HWCAP_UNICORE_F64)
+#endif
+
+#endif
diff --git a/arch/unicore32/include/asm/io.h b/arch/unicore32/include/asm/io.h
new file mode 100644
index 0000000..4bd87f3
--- /dev/null
+++ b/arch/unicore32/include/asm/io.h
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/unicore32/include/asm/io.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_IO_H__
+#define __UNICORE_IO_H__
+
+#ifdef __KERNEL__
+
+#include <asm/byteorder.h>
+#include <asm/memory.h>
+#include <asm/system.h>
+
+#define PCI_IOBASE	PKUNITY_PCILIO_BASE
+#include <asm-generic/io.h>
+
+/*
+ * __uc32_ioremap and __uc32_ioremap_cached takes CPU physical address.
+ */
+extern void __iomem *__uc32_ioremap(unsigned long, size_t);
+extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t);
+extern void __uc32_iounmap(volatile void __iomem *addr);
+
+/*
+ * ioremap and friends.
+ *
+ * ioremap takes a PCI memory address, as specified in
+ * Documentation/IO-mapping.txt.
+ *
+ */
+#define ioremap(cookie, size)		__uc32_ioremap(cookie, size)
+#define ioremap_cached(cookie, size)	__uc32_ioremap_cached(cookie, size)
+#define iounmap(cookie)			__uc32_iounmap(cookie)
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#undef xlate_dev_mem_ptr
+#define xlate_dev_mem_ptr(p)	__va(p)
+
+#define HAVE_ARCH_PIO_SIZE
+#define PIO_OFFSET		(unsigned int)(PCI_IOBASE)
+#define PIO_MASK		(unsigned int)(IO_SPACE_LIMIT)
+#define PIO_RESERVED		(PIO_OFFSET + PIO_MASK + 1)
+
+#endif	/* __KERNEL__ */
+#endif	/* __UNICORE_IO_H__ */
diff --git a/arch/unicore32/include/asm/irq.h b/arch/unicore32/include/asm/irq.h
new file mode 100644
index 0000000..baea93e
--- /dev/null
+++ b/arch/unicore32/include/asm/irq.h
@@ -0,0 +1,105 @@
+/*
+ * linux/arch/unicore32/include/asm/irq.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_IRQ_H__
+#define __UNICORE_IRQ_H__
+
+#include <asm-generic/irq.h>
+
+#define	IRQ_GPIOLOW0		0x00
+#define	IRQ_GPIOLOW1		0x01
+#define	IRQ_GPIOLOW2		0x02
+#define	IRQ_GPIOLOW3		0x03
+#define	IRQ_GPIOLOW4		0x04
+#define	IRQ_GPIOLOW5		0x05
+#define	IRQ_GPIOLOW6		0x06
+#define	IRQ_GPIOLOW7		0x07
+#define IRQ_GPIOHIGH		0x08
+#define IRQ_USB			0x09
+#define IRQ_SDC			0x0a
+#define IRQ_AC97		0x0b
+#define IRQ_SATA		0x0c
+#define IRQ_MME			0x0d
+#define IRQ_PCI_BRIDGE		0x0e
+#define	IRQ_DDR			0x0f
+#define	IRQ_SPI			0x10
+#define	IRQ_UNIGFX		0x11
+#define	IRQ_I2C			0x11
+#define	IRQ_UART1		0x12
+#define	IRQ_UART0		0x13
+#define IRQ_UMAL		0x14
+#define IRQ_NAND		0x15
+#define IRQ_PS2_KBD		0x16
+#define IRQ_PS2_AUX		0x17
+#define IRQ_DMA			0x18
+#define IRQ_DMAERR		0x19
+#define	IRQ_TIMER0		0x1a
+#define	IRQ_TIMER1		0x1b
+#define	IRQ_TIMER2		0x1c
+#define	IRQ_TIMER3		0x1d
+#define	IRQ_RTC			0x1e
+#define	IRQ_RTCAlarm		0x1f
+
+#define	IRQ_GPIO0		0x20
+#define	IRQ_GPIO1		0x21
+#define	IRQ_GPIO2		0x22
+#define	IRQ_GPIO3		0x23
+#define	IRQ_GPIO4		0x24
+#define	IRQ_GPIO5		0x25
+#define	IRQ_GPIO6		0x26
+#define	IRQ_GPIO7		0x27
+#define IRQ_GPIO8		0x28
+#define IRQ_GPIO9		0x29
+#define IRQ_GPIO10		0x2a
+#define IRQ_GPIO11		0x2b
+#define IRQ_GPIO12		0x2c
+#define IRQ_GPIO13		0x2d
+#define IRQ_GPIO14		0x2e
+#define IRQ_GPIO15		0x2f
+#define IRQ_GPIO16		0x30
+#define IRQ_GPIO17		0x31
+#define IRQ_GPIO18		0x32
+#define IRQ_GPIO19		0x33
+#define IRQ_GPIO20		0x34
+#define IRQ_GPIO21		0x35
+#define IRQ_GPIO22		0x36
+#define IRQ_GPIO23		0x37
+#define IRQ_GPIO24		0x38
+#define IRQ_GPIO25		0x39
+#define IRQ_GPIO26		0x3a
+#define IRQ_GPIO27		0x3b
+
+#ifdef CONFIG_ARCH_FPGA
+#define IRQ_PCIINTA             IRQ_GPIOLOW2
+#define IRQ_PCIINTB             IRQ_GPIOLOW1
+#define IRQ_PCIINTC             IRQ_GPIOLOW0
+#define IRQ_PCIINTD             IRQ_GPIOLOW6
+#endif
+
+#if defined(CONFIG_PUV3_DB0913) || defined(CONFIG_PUV3_NB0916)	\
+	|| defined(CONFIG_PUV3_SMW0919)
+#define IRQ_PCIINTA             IRQ_GPIOLOW1
+#define IRQ_PCIINTB             IRQ_GPIOLOW2
+#define IRQ_PCIINTC             IRQ_GPIOLOW3
+#define IRQ_PCIINTD             IRQ_GPIOLOW4
+#endif
+
+#define IRQ_SD_CD               IRQ_GPIO6 /* falling or rising trigger */
+
+#ifndef __ASSEMBLY__
+struct pt_regs;
+
+extern void asm_do_IRQ(unsigned int, struct pt_regs *);
+
+#endif
+
+#endif
+
diff --git a/arch/unicore32/include/asm/irqflags.h b/arch/unicore32/include/asm/irqflags.h
new file mode 100644
index 0000000..6d8a28d
--- /dev/null
+++ b/arch/unicore32/include/asm/irqflags.h
@@ -0,0 +1,53 @@
+/*
+ * linux/arch/unicore32/include/asm/irqflags.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_IRQFLAGS_H__
+#define __UNICORE_IRQFLAGS_H__
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+
+#define ARCH_IRQ_DISABLED	(PRIV_MODE | PSR_I_BIT)
+#define ARCH_IRQ_ENABLED	(PRIV_MODE)
+
+/*
+ * Save the current interrupt enable state.
+ */
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long temp;
+
+	asm volatile("mov %0, asr" : "=r" (temp) : : "memory", "cc");
+
+	return temp & PSR_c;
+}
+
+/*
+ * restore saved IRQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	unsigned long temp;
+
+	asm volatile(
+		"mov	%0, asr\n"
+		"mov.a	asr, %1\n"
+		"mov.f	asr, %0"
+		: "=&r" (temp)
+		: "r" (flags)
+		: "memory", "cc");
+}
+
+#include <asm-generic/irqflags.h>
+
+#endif
+#endif
diff --git a/arch/unicore32/include/asm/linkage.h b/arch/unicore32/include/asm/linkage.h
new file mode 100644
index 0000000..d1618bd
--- /dev/null
+++ b/arch/unicore32/include/asm/linkage.h
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/unicore32/include/asm/linkage.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_LINKAGE_H__
+#define __UNICORE_LINKAGE_H__
+
+#define __ALIGN .align 0
+#define __ALIGN_STR ".align 0"
+
+#define ENDPROC(name) \
+	.type name, %function; \
+	END(name)
+
+#endif
diff --git a/arch/unicore32/include/asm/memblock.h b/arch/unicore32/include/asm/memblock.h
new file mode 100644
index 0000000..a8a5d8d
--- /dev/null
+++ b/arch/unicore32/include/asm/memblock.h
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/unicore32/include/asm/memblock.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_MEMBLOCK_H__
+#define __UNICORE_MEMBLOCK_H__
+
+/*
+ * Memory map description
+ */
+# define NR_BANKS 8
+
+struct membank {
+	unsigned long start;
+	unsigned long size;
+	unsigned int highmem;
+};
+
+struct meminfo {
+	int nr_banks;
+	struct membank bank[NR_BANKS];
+};
+
+extern struct meminfo meminfo;
+
+#define for_each_bank(iter, mi)				\
+	for (iter = 0; iter < (mi)->nr_banks; iter++)
+
+#define bank_pfn_start(bank)	__phys_to_pfn((bank)->start)
+#define bank_pfn_end(bank)	__phys_to_pfn((bank)->start + (bank)->size)
+#define bank_pfn_size(bank)	((bank)->size >> PAGE_SHIFT)
+#define bank_phys_start(bank)	((bank)->start)
+#define bank_phys_end(bank)	((bank)->start + (bank)->size)
+#define bank_phys_size(bank)	((bank)->size)
+
+extern void uc32_memblock_init(struct meminfo *);
+
+#endif
diff --git a/arch/unicore32/include/asm/memory.h b/arch/unicore32/include/asm/memory.h
new file mode 100644
index 0000000..5eddb99
--- /dev/null
+++ b/arch/unicore32/include/asm/memory.h
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/unicore32/include/asm/memory.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Note: this file should not be included by non-asm/.h files
+ */
+#ifndef __UNICORE_MEMORY_H__
+#define __UNICORE_MEMORY_H__
+
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <asm/sizes.h>
+#include <mach/memory.h>
+
+/*
+ * Allow for constants defined here to be used from assembly code
+ * by prepending the UL suffix only with actual C code compilation.
+ */
+#define UL(x) _AC(x, UL)
+
+/*
+ * PAGE_OFFSET - the virtual address of the start of the kernel image
+ * TASK_SIZE - the maximum size of a user space task.
+ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
+ */
+#define PAGE_OFFSET		UL(0xC0000000)
+#define TASK_SIZE		(PAGE_OFFSET - UL(0x41000000))
+#define TASK_UNMAPPED_BASE	(PAGE_OFFSET / 3)
+
+/*
+ * The module space lives between the addresses given by TASK_SIZE
+ * and PAGE_OFFSET - it must be within 32MB of the kernel text.
+ */
+#define MODULES_VADDR		(PAGE_OFFSET - 16*1024*1024)
+#if TASK_SIZE > MODULES_VADDR
+#error Top of user space clashes with start of module space
+#endif
+
+#define MODULES_END		(PAGE_OFFSET)
+
+/*
+ * Allow 16MB-aligned ioremap pages
+ */
+#define IOREMAP_MAX_ORDER	24
+
+/*
+ * Physical vs virtual RAM address space conversion.  These are
+ * private definitions which should NOT be used outside memory.h
+ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#ifndef __virt_to_phys
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+#endif
+
+/*
+ * Convert a physical address to a Page Frame Number and back
+ */
+#define	__phys_to_pfn(paddr)	((paddr) >> PAGE_SHIFT)
+#define	__pfn_to_phys(pfn)	((pfn) << PAGE_SHIFT)
+
+/*
+ * Convert a page to/from a physical address
+ */
+#define page_to_phys(page)	(__pfn_to_phys(page_to_pfn(page)))
+#define phys_to_page(phys)	(pfn_to_page(__phys_to_pfn(phys)))
+
+#ifndef __ASSEMBLY__
+
+#ifndef arch_adjust_zones
+#define arch_adjust_zones(size, holes) do { } while (0)
+#endif
+
+/*
+ * PFNs are used to describe any physical page; this means
+ * PFN 0 == physical address 0.
+ *
+ * This is the PFN of the first RAM page in the kernel
+ * direct-mapped view.  We assume this is the first page
+ * of RAM in the mem_map as well.
+ */
+#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
+
+/*
+ * Drivers should NOT use these either.
+ */
+#define __pa(x)			__virt_to_phys((unsigned long)(x))
+#define __va(x)			((void *)__phys_to_virt((unsigned long)(x)))
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
+/*
+ * Conversion between a struct page and a physical address.
+ *
+ * Note: when converting an unknown physical address to a
+ * struct page, the resulting pointer must be validated
+ * using VALID_PAGE().  It must return an invalid struct page
+ * for any physical address not corresponding to a system
+ * RAM address.
+ *
+ *  page_to_pfn(page)	convert a struct page * to a PFN number
+ *  pfn_to_page(pfn)	convert a _valid_ PFN number to struct page *
+ *
+ *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
+ *  virt_addr_valid(k)	indicates whether a virtual address is valid
+ */
+#define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && \
+		(unsigned long)(kaddr) < (unsigned long)high_memory)
+
+#endif
+
+#include <asm-generic/memory_model.h>
+
+#endif
diff --git a/arch/unicore32/include/asm/mmu.h b/arch/unicore32/include/asm/mmu.h
new file mode 100644
index 0000000..66fa341
--- /dev/null
+++ b/arch/unicore32/include/asm/mmu.h
@@ -0,0 +1,17 @@
+/*
+ * linux/arch/unicore32/include/asm/mmu.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_MMU_H__
+#define __UNICORE_MMU_H__
+
+typedef	unsigned long mm_context_t;
+
+#endif
diff --git a/arch/unicore32/include/asm/mmu_context.h b/arch/unicore32/include/asm/mmu_context.h
new file mode 100644
index 0000000..fb5e4c6
--- /dev/null
+++ b/arch/unicore32/include/asm/mmu_context.h
@@ -0,0 +1,87 @@
+/*
+ * linux/arch/unicore32/include/asm/mmu_context.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_MMU_CONTEXT_H__
+#define __UNICORE_MMU_CONTEXT_H__
+
+#include <linux/compiler.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cpu-single.h>
+
+#define init_new_context(tsk, mm)	0
+
+#define destroy_context(mm)		do { } while (0)
+
+/*
+ * This is called when "tsk" is about to enter lazy TLB mode.
+ *
+ * mm:  describes the currently active mm context
+ * tsk: task which is entering lazy tlb
+ * cpu: cpu number which is entering lazy tlb
+ *
+ * tsk->mm will be NULL
+ */
+static inline void
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/*
+ * This is the actual mm switch as far as the scheduler
+ * is concerned.  No registers are touched.  We avoid
+ * calling the CPU specific function when the mm hasn't
+ * actually changed.
+ */
+static inline void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next)
+		cpu_switch_mm(next->pgd, next);
+}
+
+#define deactivate_mm(tsk, mm)	do { } while (0)
+#define activate_mm(prev, next)	switch_mm(prev, next, NULL)
+
+/*
+ * We are inserting a "fake" vma for the user-accessible vector page so
+ * gdb and friends can get to it through ptrace and /proc/<pid>/mem.
+ * But we also want to remove it before the generic code gets to see it
+ * during process exit or the unmapping of it would  cause total havoc.
+ * (the macro is used as remove_vma() is static to mm/mmap.c)
+ */
+#define arch_exit_mmap(mm) \
+do { \
+	struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
+	if (high_vma) { \
+		BUG_ON(high_vma->vm_next);  /* it should be last */ \
+		if (high_vma->vm_prev) \
+			high_vma->vm_prev->vm_next = NULL; \
+		else \
+			mm->mmap = NULL; \
+		rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
+		mm->mmap_cache = NULL; \
+		mm->map_count--; \
+		remove_vma(high_vma); \
+	} \
+} while (0)
+
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+				 struct mm_struct *mm)
+{
+}
+
+#endif
diff --git a/arch/unicore32/include/asm/mutex.h b/arch/unicore32/include/asm/mutex.h
new file mode 100644
index 0000000..fab7d0e
--- /dev/null
+++ b/arch/unicore32/include/asm/mutex.h
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/unicore32/include/asm/mutex.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * UniCore optimized mutex locking primitives
+ *
+ * Please look into asm-generic/mutex-xchg.h for a formal definition.
+ */
+#ifndef __UNICORE_MUTEX_H__
+#define __UNICORE_MUTEX_H__
+
+# include <asm-generic/mutex-xchg.h>
+#endif
diff --git a/arch/unicore32/include/asm/page.h b/arch/unicore32/include/asm/page.h
new file mode 100644
index 0000000..594b322
--- /dev/null
+++ b/arch/unicore32/include/asm/page.h
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/unicore32/include/asm/page.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PAGE_H__
+#define __UNICORE_PAGE_H__
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT		12
+#define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+struct page;
+struct vm_area_struct;
+
+#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
+extern void copy_page(void *to, const void *from);
+
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) })
+#define __pgd(x)	((pgd_t) { (x) })
+#define __pgprot(x)     ((pgprot_t) { (x) })
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pgd_val(x)      (x)
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pgd(x)	(x)
+#define __pgprot(x)     (x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+typedef struct page *pgtable_t;
+
+extern int pfn_valid(unsigned long);
+
+#include <asm/memory.h>
+
+#endif /* !__ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/getorder.h>
+
+#endif
diff --git a/arch/unicore32/include/asm/pci.h b/arch/unicore32/include/asm/pci.h
new file mode 100644
index 0000000..c5b28b4
--- /dev/null
+++ b/arch/unicore32/include/asm/pci.h
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/unicore32/include/asm/pci.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PCI_H__
+#define __UNICORE_PCI_H__
+
+#ifdef __KERNEL__
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci.h>
+#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
+
+static inline void pcibios_set_master(struct pci_dev *dev)
+{
+	/* No special bus mastering setup handling */
+}
+
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+	/* We don't do dynamic PCI IRQ allocation */
+}
+
+#ifdef CONFIG_PCI
+static inline void pci_dma_burst_advice(struct pci_dev *pdev,
+					enum pci_dma_burst_strategy *strat,
+					unsigned long *strategy_parameter)
+{
+	*strat = PCI_DMA_BURST_INFINITY;
+	*strategy_parameter = ~0UL;
+}
+#endif
+
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+	enum pci_mmap_state mmap_state, int write_combine);
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/unicore32/include/asm/pgalloc.h b/arch/unicore32/include/asm/pgalloc.h
new file mode 100644
index 0000000..0213e37
--- /dev/null
+++ b/arch/unicore32/include/asm/pgalloc.h
@@ -0,0 +1,110 @@
+/*
+ * linux/arch/unicore32/include/asm/pgalloc.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PGALLOC_H__
+#define __UNICORE_PGALLOC_H__
+
+#include <asm/pgtable-hwdef.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+#define check_pgt_cache()		do { } while (0)
+
+#define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_PRESENT)
+#define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_PRESENT)
+
+extern pgd_t *get_pgd_slow(struct mm_struct *mm);
+extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
+
+#define pgd_alloc(mm)			get_pgd_slow(mm)
+#define pgd_free(mm, pgd)		free_pgd_slow(mm, pgd)
+
+#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+
+/*
+ * Allocate one PTE table.
+ */
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
+{
+	pte_t *pte;
+
+	pte = (pte_t *)__get_free_page(PGALLOC_GFP);
+	if (pte)
+		clean_dcache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
+
+	return pte;
+}
+
+static inline pgtable_t
+pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	struct page *pte;
+
+	pte = alloc_pages(PGALLOC_GFP, 0);
+	if (pte) {
+		if (!PageHighMem(pte)) {
+			void *page = page_address(pte);
+			clean_dcache_area(page, PTRS_PER_PTE * sizeof(pte_t));
+		}
+		pgtable_page_ctor(pte);
+	}
+
+	return pte;
+}
+
+/*
+ * Free one PTE table.
+ */
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	if (pte)
+		free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
+{
+	set_pmd(pmdp, __pmd(pmdval));
+	flush_pmd_entry(pmdp);
+}
+
+/*
+ * Populate the pmdp entry with a pointer to the pte.  This pmd is part
+ * of the mm address space.
+ */
+static inline void
+pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
+{
+	unsigned long pte_ptr = (unsigned long)ptep;
+
+	/*
+	 * The pmd must be loaded with the physical
+	 * address of the PTE table
+	 */
+	__pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
+}
+
+static inline void
+pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
+{
+	__pmd_populate(pmdp,
+			page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
+}
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#endif
diff --git a/arch/unicore32/include/asm/pgtable-hwdef.h b/arch/unicore32/include/asm/pgtable-hwdef.h
new file mode 100644
index 0000000..7314e85
--- /dev/null
+++ b/arch/unicore32/include/asm/pgtable-hwdef.h
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/unicore32/include/asm/pgtable-hwdef.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PGTABLE_HWDEF_H__
+#define __UNICORE_PGTABLE_HWDEF_H__
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ *   - common
+ */
+#define PMD_TYPE_MASK		(3 << 0)
+#define PMD_TYPE_TABLE		(0 << 0)
+/*#define PMD_TYPE_LARGE	(1 << 0) */
+#define PMD_TYPE_INVALID	(2 << 0)
+#define PMD_TYPE_SECT		(3 << 0)
+
+#define PMD_PRESENT		(1 << 2)
+#define PMD_YOUNG		(1 << 3)
+
+/*#define PMD_SECT_DIRTY	(1 << 4) */
+#define PMD_SECT_CACHEABLE	(1 << 5)
+#define PMD_SECT_EXEC		(1 << 6)
+#define PMD_SECT_WRITE		(1 << 7)
+#define PMD_SECT_READ		(1 << 8)
+
+/*
+ * + Level 2 descriptor (PTE)
+ *   - common
+ */
+#define PTE_TYPE_MASK		(3 << 0)
+#define PTE_TYPE_SMALL		(0 << 0)
+#define PTE_TYPE_MIDDLE		(1 << 0)
+#define PTE_TYPE_LARGE		(2 << 0)
+#define PTE_TYPE_INVALID	(3 << 0)
+
+#define PTE_PRESENT		(1 << 2)
+#define PTE_FILE		(1 << 3)	/* only when !PRESENT */
+#define PTE_YOUNG		(1 << 3)
+#define PTE_DIRTY		(1 << 4)
+#define PTE_CACHEABLE		(1 << 5)
+#define PTE_EXEC		(1 << 6)
+#define PTE_WRITE		(1 << 7)
+#define PTE_READ		(1 << 8)
+
+#endif
diff --git a/arch/unicore32/include/asm/pgtable.h b/arch/unicore32/include/asm/pgtable.h
new file mode 100644
index 0000000..68b2f29
--- /dev/null
+++ b/arch/unicore32/include/asm/pgtable.h
@@ -0,0 +1,317 @@
+/*
+ * linux/arch/unicore32/include/asm/pgtable.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PGTABLE_H__
+#define __UNICORE_PGTABLE_H__
+
+#include <asm-generic/pgtable-nopmd.h>
+#include <asm/cpu-single.h>
+
+#include <asm/memory.h>
+#include <asm/pgtable-hwdef.h>
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ *
+ * Note that platforms may override VMALLOC_START, but they must provide
+ * VMALLOC_END.  VMALLOC_END defines the (exclusive) limit of this space,
+ * which may not overlap IO space.
+ */
+#ifndef VMALLOC_START
+#define VMALLOC_OFFSET		SZ_8M
+#define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) \
+					& ~(VMALLOC_OFFSET-1))
+#define VMALLOC_END		(0xff000000UL)
+#endif
+
+#define PTRS_PER_PTE		1024
+#define PTRS_PER_PGD		1024
+
+/*
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PGDIR_SHIFT		22
+
+#ifndef __ASSEMBLY__
+extern void __pte_error(const char *file, int line, unsigned long val);
+extern void __pgd_error(const char *file, int line, unsigned long val);
+
+#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
+#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#endif /* !__ASSEMBLY__ */
+
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * This is the lowest virtual address we can permit any user space
+ * mapping to be mapped at.  This is particularly important for
+ * non-high vector CPUs.
+ */
+#define FIRST_USER_ADDRESS	PAGE_SIZE
+
+#define FIRST_USER_PGD_NR	1
+#define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		22
+#define SECTION_SIZE		(1UL << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The pgprot_* and protection_map entries will be fixed up in runtime
+ * to include the cachable bits based on memory policy, as well as any
+ * architecture dependent bits.
+ */
+#define _PTE_DEFAULT		(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE)
+
+extern pgprot_t pgprot_user;
+extern pgprot_t pgprot_kernel;
+
+#define PAGE_NONE		pgprot_user
+#define PAGE_SHARED		__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_WRITE)
+#define PAGE_SHARED_EXEC	__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_WRITE \
+								| PTE_EXEC)
+#define PAGE_COPY		__pgprot(pgprot_val(pgprot_user | PTE_READ)
+#define PAGE_COPY_EXEC		__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_EXEC)
+#define PAGE_READONLY		__pgprot(pgprot_val(pgprot_user | PTE_READ)
+#define PAGE_READONLY_EXEC	__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_EXEC)
+#define PAGE_KERNEL		pgprot_kernel
+#define PAGE_KERNEL_EXEC	__pgprot(pgprot_val(pgprot_kernel | PTE_EXEC))
+
+#define __PAGE_NONE		__pgprot(_PTE_DEFAULT)
+#define __PAGE_SHARED		__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_WRITE)
+#define __PAGE_SHARED_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_WRITE \
+							| PTE_EXEC)
+#define __PAGE_COPY		__pgprot(_PTE_DEFAULT | PTE_READ)
+#define __PAGE_COPY_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_EXEC)
+#define __PAGE_READONLY		__pgprot(_PTE_DEFAULT | PTE_READ)
+#define __PAGE_READONLY_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_EXEC)
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The table below defines the page protection levels that we insert into our
+ * Linux page table version.  These get translated into the best that the
+ * architecture can perform.  Note that on UniCore hardware:
+ *  1) We cannot do execute protection
+ *  2) If we could do execute protection, then read is implied
+ *  3) write implies read permissions
+ */
+#define __P000  __PAGE_NONE
+#define __P001  __PAGE_READONLY
+#define __P010  __PAGE_COPY
+#define __P011  __PAGE_COPY
+#define __P100  __PAGE_READONLY_EXEC
+#define __P101  __PAGE_READONLY_EXEC
+#define __P110  __PAGE_COPY_EXEC
+#define __P111  __PAGE_COPY_EXEC
+
+#define __S000  __PAGE_NONE
+#define __S001  __PAGE_READONLY
+#define __S010  __PAGE_SHARED
+#define __S011  __PAGE_SHARED
+#define __S100  __PAGE_READONLY_EXEC
+#define __S101  __PAGE_READONLY_EXEC
+#define __S110  __PAGE_SHARED_EXEC
+#define __S111  __PAGE_SHARED_EXEC
+
+#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern struct page *empty_zero_page;
+#define ZERO_PAGE(vaddr)		(empty_zero_page)
+
+#define pte_pfn(pte)			(pte_val(pte) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot)		(__pte(((pfn) << PAGE_SHIFT) \
+						| pgprot_val(prot)))
+
+#define pte_none(pte)			(!pte_val(pte))
+#define pte_clear(mm, addr, ptep)	set_pte(ptep, __pte(0))
+#define pte_page(pte)			(pfn_to_page(pte_pfn(pte)))
+#define pte_offset_kernel(dir, addr)	(pmd_page_vaddr(*(dir)) \
+						+ __pte_index(addr))
+
+#define pte_offset_map(dir, addr)	(pmd_page_vaddr(*(dir)) \
+						+ __pte_index(addr))
+#define pte_unmap(pte)			do { } while (0)
+
+#define set_pte(ptep, pte)	cpu_set_pte(ptep, pte)
+
+#define set_pte_at(mm, addr, ptep, pteval)	\
+	do {					\
+		set_pte(ptep, pteval);          \
+	} while (0)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+#define pte_present(pte)	(pte_val(pte) & PTE_PRESENT)
+#define pte_write(pte)		(pte_val(pte) & PTE_WRITE)
+#define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
+#define pte_young(pte)		(pte_val(pte) & PTE_YOUNG)
+#define pte_exec(pte)		(pte_val(pte) & PTE_EXEC)
+#define pte_special(pte)	(0)
+
+#define PTE_BIT_FUNC(fn, op) \
+static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+
+PTE_BIT_FUNC(wrprotect, &= ~PTE_WRITE);
+PTE_BIT_FUNC(mkwrite,   |= PTE_WRITE);
+PTE_BIT_FUNC(mkclean,   &= ~PTE_DIRTY);
+PTE_BIT_FUNC(mkdirty,   |= PTE_DIRTY);
+PTE_BIT_FUNC(mkold,     &= ~PTE_YOUNG);
+PTE_BIT_FUNC(mkyoung,   |= PTE_YOUNG);
+
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+/*
+ * Mark the prot value as uncacheable.
+ */
+#define pgprot_noncached(prot)		\
+	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
+#define pgprot_writecombine(prot)	\
+	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
+#define pgprot_dmacoherent(prot)	\
+	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
+
+#define pmd_none(pmd)		(!pmd_val(pmd))
+#define pmd_present(pmd)	(pmd_val(pmd) & PMD_PRESENT)
+#define pmd_bad(pmd)		(((pmd_val(pmd) &		\
+				(PMD_PRESENT | PMD_TYPE_MASK))	\
+				!= (PMD_PRESENT | PMD_TYPE_TABLE)))
+
+#define set_pmd(pmdpd, pmdval)		\
+	do {				\
+		*(pmdpd) = pmdval;	\
+	} while (0)
+
+#define pmd_clear(pmdp)			\
+	do {				\
+		set_pmd(pmdp, __pmd(0));\
+		clean_pmd_entry(pmdp);	\
+	} while (0)
+
+#define pmd_page_vaddr(pmd) ((pte_t *)__va(pmd_val(pmd) & PAGE_MASK))
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
+
+#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
+
+/* Find an entry in the third-level page table.. */
+#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	const unsigned long mask = PTE_EXEC | PTE_WRITE | PTE_READ;
+	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+	return pte;
+}
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/*
+ * Encode and decode a swap entry.  Swap entries are stored in the Linux
+ * page tables as follows:
+ *
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *   <--------------- offset --------------> <--- type --> 0 0 0 0 0
+ *
+ * This gives us up to 127 swap files and 32GB per swap file.  Note that
+ * the offset field is always non-zero.
+ */
+#define __SWP_TYPE_SHIFT	5
+#define __SWP_TYPE_BITS		7
+#define __SWP_TYPE_MASK		((1 << __SWP_TYPE_BITS) - 1)
+#define __SWP_OFFSET_SHIFT	(__SWP_TYPE_BITS + __SWP_TYPE_SHIFT)
+
+#define __swp_type(x)		(((x).val >> __SWP_TYPE_SHIFT)		\
+				& __SWP_TYPE_MASK)
+#define __swp_offset(x)		((x).val >> __SWP_OFFSET_SHIFT)
+#define __swp_entry(type, offset) ((swp_entry_t) {			\
+				((type) << __SWP_TYPE_SHIFT) |		\
+				((offset) << __SWP_OFFSET_SHIFT) })
+
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(swp)	((pte_t) { (swp).val })
+
+/*
+ * It is an error for the kernel to have more swap files than we can
+ * encode in the PTEs.  This ensures that we know when MAX_SWAPFILES
+ * is increased beyond what we presently support.
+ */
+#define MAX_SWAPFILES_CHECK()	\
+	BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
+
+/*
+ * Encode and decode a file entry.  File entries are stored in the Linux
+ * page tables as follows:
+ *
+ *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+ *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *   <----------------------- offset ----------------------> 1 0 0 0
+ */
+#define pte_file(pte)		(pte_val(pte) & PTE_FILE)
+#define pte_to_pgoff(x)		(pte_val(x) >> 4)
+#define pgoff_to_pte(x)		__pte(((x) << 4) | PTE_FILE)
+
+#define PTE_FILE_MAX_BITS	28
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+/* FIXME: this is not correct */
+#define kern_addr_valid(addr)	(1)
+
+#include <asm-generic/pgtable.h>
+
+/*
+ * remap a physical page `pfn' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_pfn_range(vma, from, pfn, size, prot)	\
+		remap_pfn_range(vma, from, pfn, size, prot)
+
+#define pgtable_cache_init() do { } while (0)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __UNICORE_PGTABLE_H__ */
diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h
new file mode 100644
index 0000000..e11cb07
--- /dev/null
+++ b/arch/unicore32/include/asm/processor.h
@@ -0,0 +1,92 @@
+/*
+ * linux/arch/unicore32/include/asm/processor.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PROCESSOR_H__
+#define __UNICORE_PROCESSOR_H__
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#ifdef __KERNEL__
+#define STACK_TOP	TASK_SIZE
+#define STACK_TOP_MAX	TASK_SIZE
+#endif
+
+struct debug_entry {
+	u32			address;
+	u32			insn;
+};
+
+struct debug_info {
+	int			nsaved;
+	struct debug_entry	bp[2];
+};
+
+struct thread_struct {
+							/* fault info	  */
+	unsigned long		address;
+	unsigned long		trap_no;
+	unsigned long		error_code;
+							/* debugging	  */
+	struct debug_info	debug;
+};
+
+#define INIT_THREAD  {	}
+
+#define start_thread(regs, pc, sp)					\
+({									\
+	unsigned long *stack = (unsigned long *)sp;			\
+	set_fs(USER_DS);						\
+	memset(regs->uregs, 0, sizeof(regs->uregs));			\
+	regs->UCreg_asr = USER_MODE;					\
+	regs->UCreg_pc = pc & ~1;	/* pc */                        \
+	regs->UCreg_sp = sp;		/* sp */                        \
+	regs->UCreg_02 = stack[2];	/* r2 (envp) */                 \
+	regs->UCreg_01 = stack[1];	/* r1 (argv) */                 \
+	regs->UCreg_00 = stack[0];	/* r0 (argc) */                 \
+})
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define cpu_relax()			barrier()
+
+/*
+ * Create a new kernel thread
+ */
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+#define task_pt_regs(p) \
+	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
+
+#define KSTK_EIP(tsk)	(task_pt_regs(tsk)->UCreg_pc)
+#define KSTK_ESP(tsk)	(task_pt_regs(tsk)->UCreg_sp)
+
+#endif
+
+#endif /* __UNICORE_PROCESSOR_H__ */
diff --git a/arch/unicore32/include/asm/ptrace.h b/arch/unicore32/include/asm/ptrace.h
new file mode 100644
index 0000000..b9caf9b
--- /dev/null
+++ b/arch/unicore32/include/asm/ptrace.h
@@ -0,0 +1,133 @@
+/*
+ * linux/arch/unicore32/include/asm/ptrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_PTRACE_H__
+#define __UNICORE_PTRACE_H__
+
+#define PTRACE_GET_THREAD_AREA	22
+
+/*
+ * PSR bits
+ */
+#define USER_MODE	0x00000010
+#define REAL_MODE	0x00000011
+#define INTR_MODE	0x00000012
+#define PRIV_MODE	0x00000013
+#define ABRT_MODE	0x00000017
+#define EXTN_MODE	0x0000001b
+#define SUSR_MODE	0x0000001f
+#define MODE_MASK	0x0000001f
+#define PSR_R_BIT	0x00000040
+#define PSR_I_BIT	0x00000080
+#define PSR_V_BIT	0x10000000
+#define PSR_C_BIT	0x20000000
+#define PSR_Z_BIT	0x40000000
+#define PSR_S_BIT	0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f		0xff000000	/* Flags		*/
+#define PSR_c		0x000000ff	/* Control		*/
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+	unsigned long uregs[34];
+};
+
+#define UCreg_asr		uregs[32]
+#define UCreg_pc		uregs[31]
+#define UCreg_lr		uregs[30]
+#define UCreg_sp		uregs[29]
+#define UCreg_ip		uregs[28]
+#define UCreg_fp		uregs[27]
+#define UCreg_26		uregs[26]
+#define UCreg_25		uregs[25]
+#define UCreg_24		uregs[24]
+#define UCreg_23		uregs[23]
+#define UCreg_22		uregs[22]
+#define UCreg_21		uregs[21]
+#define UCreg_20		uregs[20]
+#define UCreg_19		uregs[19]
+#define UCreg_18		uregs[18]
+#define UCreg_17		uregs[17]
+#define UCreg_16		uregs[16]
+#define UCreg_15		uregs[15]
+#define UCreg_14		uregs[14]
+#define UCreg_13		uregs[13]
+#define UCreg_12		uregs[12]
+#define UCreg_11		uregs[11]
+#define UCreg_10		uregs[10]
+#define UCreg_09		uregs[9]
+#define UCreg_08		uregs[8]
+#define UCreg_07		uregs[7]
+#define UCreg_06		uregs[6]
+#define UCreg_05		uregs[5]
+#define UCreg_04		uregs[4]
+#define UCreg_03		uregs[3]
+#define UCreg_02		uregs[2]
+#define UCreg_01		uregs[1]
+#define UCreg_00		uregs[0]
+#define UCreg_ORIG_00		uregs[33]
+
+#ifdef __KERNEL__
+
+#define user_mode(regs)	\
+	(processor_mode(regs) == USER_MODE)
+
+#define processor_mode(regs) \
+	((regs)->UCreg_asr & MODE_MASK)
+
+#define interrupts_enabled(regs) \
+	(!((regs)->UCreg_asr & PSR_I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+	(!((regs)->UCreg_asr & PSR_R_BIT))
+
+/* Are the current registers suitable for user mode?
+ * (used to maintain security in signal handlers)
+ */
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+	unsigned long mode = regs->UCreg_asr & MODE_MASK;
+
+	/*
+	 * Always clear the R (REAL) bits
+	 */
+	regs->UCreg_asr &= ~(PSR_R_BIT);
+
+	if ((regs->UCreg_asr & PSR_I_BIT) == 0) {
+		if (mode == USER_MODE)
+			return 1;
+	}
+
+	/*
+	 * Force ASR to something logical...
+	 */
+	regs->UCreg_asr &= PSR_f | USER_MODE;
+
+	return 0;
+}
+
+#define instruction_pointer(regs)	((regs)->UCreg_pc)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif
+
diff --git a/arch/unicore32/include/asm/sigcontext.h b/arch/unicore32/include/asm/sigcontext.h
new file mode 100644
index 0000000..6a2d767
--- /dev/null
+++ b/arch/unicore32/include/asm/sigcontext.h
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/unicore32/include/asm/sigcontext.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_SIGCONTEXT_H__
+#define __UNICORE_SIGCONTEXT_H__
+
+#include <asm/ptrace.h>
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	unsigned long trap_no;
+	unsigned long error_code;
+	unsigned long oldmask;
+	unsigned long fault_address;
+	struct pt_regs regs;
+};
+
+#endif
diff --git a/arch/unicore32/include/asm/stacktrace.h b/arch/unicore32/include/asm/stacktrace.h
new file mode 100644
index 0000000..76edc65
--- /dev/null
+++ b/arch/unicore32/include/asm/stacktrace.h
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/unicore32/include/asm/stacktrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_STACKTRACE_H__
+#define __UNICORE_STACKTRACE_H__
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long sp;
+	unsigned long lr;
+	unsigned long pc;
+};
+
+#ifdef CONFIG_FRAME_POINTER
+extern int unwind_frame(struct stackframe *frame);
+#else
+#define unwind_frame(f) (-EINVAL)
+#endif
+extern void walk_stackframe(struct stackframe *frame,
+			    int (*fn)(struct stackframe *, void *), void *data);
+
+#endif	/* __UNICORE_STACKTRACE_H__ */
diff --git a/arch/unicore32/include/asm/string.h b/arch/unicore32/include/asm/string.h
new file mode 100644
index 0000000..55264c8
--- /dev/null
+++ b/arch/unicore32/include/asm/string.h
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/unicore32/include/asm/string.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_STRING_H__
+#define __UNICORE_STRING_H__
+
+/*
+ * We don't do inline string functions, since the
+ * optimised inline asm versions are not small.
+ */
+
+#define __HAVE_ARCH_STRRCHR
+extern char *strrchr(const char *s, int c);
+
+#define __HAVE_ARCH_STRCHR
+extern char *strchr(const char *s, 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/unicore32/include/asm/suspend.h b/arch/unicore32/include/asm/suspend.h
new file mode 100644
index 0000000..88a9c0f
--- /dev/null
+++ b/arch/unicore32/include/asm/suspend.h
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/unicore32/include/asm/suspend.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_SUSPEND_H__
+#define __UNICORE_SUSPEND_H__
+
+#ifndef __ASSEMBLY__
+static inline int arch_prepare_suspend(void) { return 0; }
+
+#include <asm/ptrace.h>
+
+struct swsusp_arch_regs {
+	struct cpu_context_save	cpu_context;	/* cpu context */
+#ifdef CONFIG_UNICORE_FPU_F64
+	struct fp_state		fpstate __attribute__((aligned(8)));
+#endif
+};
+#endif
+
+#endif /* __UNICORE_SUSPEND_H__ */
+
diff --git a/arch/unicore32/include/asm/system.h b/arch/unicore32/include/asm/system.h
new file mode 100644
index 0000000..246b71c
--- /dev/null
+++ b/arch/unicore32/include/asm/system.h
@@ -0,0 +1,161 @@
+/*
+ * linux/arch/unicore32/include/asm/system.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_SYSTEM_H__
+#define __UNICORE_SYSTEM_H__
+
+#ifdef __KERNEL__
+
+/*
+ * CR1 bits (CP#0 CR1)
+ */
+#define CR_M	(1 << 0)	/* MMU enable				*/
+#define CR_A	(1 << 1)	/* Alignment abort enable		*/
+#define CR_D	(1 << 2)	/* Dcache enable			*/
+#define CR_I	(1 << 3)	/* Icache enable			*/
+#define CR_B	(1 << 4)	/* Dcache write mechanism: write back	*/
+#define CR_T	(1 << 5)	/* Burst enable				*/
+#define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+
+struct thread_info;
+struct task_struct;
+
+struct pt_regs;
+
+void die(const char *msg, struct pt_regs *regs, int err);
+
+struct siginfo;
+void uc32_notify_die(const char *str, struct pt_regs *regs,
+		struct siginfo *info, unsigned long err, unsigned long trap);
+
+void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
+				       struct pt_regs *),
+		     int sig, int code, const char *name);
+
+#define xchg(ptr, x) \
+	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+struct mm_struct;
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+extern void __show_regs(struct pt_regs *);
+
+extern int cpu_architecture(void);
+extern void cpu_init(void);
+
+#define vectors_high()	(cr_alignment & CR_V)
+
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("" : : : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+
+#define mb()		barrier()
+#define rmb()		barrier()
+#define wmb()		barrier()
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define read_barrier_depends()		do { } while (0)
+#define smp_read_barrier_depends()	do { } while (0)
+
+#define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
+extern unsigned long cr_no_alignment;	/* defined in entry-unicore.S */
+extern unsigned long cr_alignment;	/* defined in entry-unicore.S */
+
+static inline unsigned int get_cr(void)
+{
+	unsigned int val;
+	asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
+	return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+	asm volatile("movc p0.c1, %0, #0	@set CR"
+	  : : "r" (val) : "cc");
+	isb();
+}
+
+extern void adjust_cr(unsigned long mask, unsigned long set);
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.  schedule() itself
+ * contains the memory barrier to tell GCC not to cache `current'.
+ */
+extern struct task_struct *__switch_to(struct task_struct *,
+		struct thread_info *, struct thread_info *);
+extern void panic(const char *fmt, ...);
+
+#define switch_to(prev, next, last)					\
+do {									\
+	last = __switch_to(prev,					\
+		task_thread_info(prev), task_thread_info(next));	\
+} while (0)
+
+static inline unsigned long
+__xchg(unsigned long x, volatile void *ptr, int size)
+{
+	unsigned long ret;
+
+	switch (size) {
+	case 1:
+		asm volatile("@	__xchg1\n"
+		"	swapb	%0, %1, [%2]"
+			: "=&r" (ret)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	case 4:
+		asm volatile("@	__xchg4\n"
+		"	swapw	%0, %1, [%2]"
+			: "=&r" (ret)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	default:
+		panic("xchg: bad data size: ptr 0x%p, size %d\n",
+			ptr, size);
+	}
+
+	return ret;
+}
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)					\
+		((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),	\
+		(unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)					\
+		__cmpxchg64_local_generic((ptr), (o), (n))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif /* __ASSEMBLY__ */
+
+#define arch_align_stack(x) (x)
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/unicore32/include/asm/thread_info.h b/arch/unicore32/include/asm/thread_info.h
new file mode 100644
index 0000000..c270e9e
--- /dev/null
+++ b/arch/unicore32/include/asm/thread_info.h
@@ -0,0 +1,154 @@
+/*
+ * linux/arch/unicore32/include/asm/thread_info.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_THREAD_INFO_H__
+#define __UNICORE_THREAD_INFO_H__
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <asm/fpstate.h>
+
+#define THREAD_SIZE_ORDER	1
+#define THREAD_SIZE		8192
+#define THREAD_START_SP		(THREAD_SIZE - 8)
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+struct exec_domain;
+
+#include <asm/types.h>
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+struct cpu_context_save {
+	__u32	r4;
+	__u32	r5;
+	__u32	r6;
+	__u32	r7;
+	__u32	r8;
+	__u32	r9;
+	__u32	r10;
+	__u32	r11;
+	__u32	r12;
+	__u32	r13;
+	__u32	r14;
+	__u32	r15;
+	__u32	r16;
+	__u32	r17;
+	__u32	r18;
+	__u32	r19;
+	__u32	r20;
+	__u32	r21;
+	__u32	r22;
+	__u32	r23;
+	__u32	r24;
+	__u32	r25;
+	__u32	r26;
+	__u32	fp;
+	__u32	sp;
+	__u32	pc;
+};
+
+/*
+ * low level task data that entry.S needs immediate access to.
+ * __switch_to() assumes cpu_context follows immediately after cpu_domain.
+ */
+struct thread_info {
+	unsigned long		flags;		/* low level flags */
+	int			preempt_count;	/* 0 => preemptable */
+						/* <0 => bug */
+	mm_segment_t		addr_limit;	/* address limit */
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	__u32			cpu;		/* cpu */
+	struct cpu_context_save	cpu_context;	/* cpu context */
+	__u32			syscall;	/* syscall number */
+	__u8			used_cp[16];	/* thread used copro */
+#ifdef CONFIG_UNICORE_FPU_F64
+	struct fp_state		fpstate __attribute__((aligned(8)));
+#endif
+	struct restart_block	restart_block;
+};
+
+#define INIT_THREAD_INFO(tsk)						\
+{									\
+	.task		= &tsk,						\
+	.exec_domain	= &default_exec_domain,				\
+	.flags		= 0,						\
+	.preempt_count	= INIT_PREEMPT_COUNT,				\
+	.addr_limit	= KERNEL_DS,					\
+	.restart_block	= {						\
+		.fn	= do_no_restart_syscall,			\
+	},								\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/*
+ * how to get the thread information struct from C
+ */
+static inline struct thread_info *current_thread_info(void) __attribute_const__;
+
+static inline struct thread_info *current_thread_info(void)
+{
+	register unsigned long sp asm ("sp");
+	return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
+}
+
+#define thread_saved_pc(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
+#define thread_saved_sp(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.sp))
+#define thread_saved_fp(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
+
+#endif
+
+/*
+ * We use bit 30 of the preempt_count to indicate that kernel
+ * preemption is occurring.  See <asm/hardirq.h>.
+ */
+#define PREEMPT_ACTIVE	0x40000000
+
+/*
+ * thread information flags:
+ *  TIF_SYSCALL_TRACE	- syscall trace active
+ *  TIF_SIGPENDING	- signal pending
+ *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NOTIFY_RESUME	- callback before returning to user
+ */
+#define TIF_SIGPENDING		0
+#define TIF_NEED_RESCHED	1
+#define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
+#define TIF_SYSCALL_TRACE	8
+#define TIF_MEMDIE		18
+#define TIF_FREEZE		19
+#define TIF_RESTORE_SIGMASK	20
+
+#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
+#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+
+/*
+ * Change these and you break ASM code in entry-common.S
+ */
+#define _TIF_WORK_MASK		0x000000ff
+
+#endif /* __KERNEL__ */
+#endif /* __UNICORE_THREAD_INFO_H__ */
diff --git a/arch/unicore32/include/asm/timex.h b/arch/unicore32/include/asm/timex.h
new file mode 100644
index 0000000..faf16ba
--- /dev/null
+++ b/arch/unicore32/include/asm/timex.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/unicore32/include/asm/timex.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_TIMEX_H__
+#define __UNICORE_TIMEX_H__
+
+#ifdef	CONFIG_ARCH_FPGA
+
+/* in FPGA, APB clock is 33M, and OST clock is 32K, */
+/* so, 1M is selected for timer interrupt correctly */
+#define	CLOCK_TICK_RATE		(32*1024)
+
+#endif
+
+#if defined(CONFIG_PUV3_DB0913)		\
+	|| defined(CONFIG_PUV3_NB0916)	\
+	|| defined(CONFIG_PUV3_SMW0919)
+
+#define  CLOCK_TICK_RATE         (14318000)
+
+#endif
+
+#include <asm-generic/timex.h>
+
+#endif
diff --git a/arch/unicore32/include/asm/tlb.h b/arch/unicore32/include/asm/tlb.h
new file mode 100644
index 0000000..9cca15c
--- /dev/null
+++ b/arch/unicore32/include/asm/tlb.h
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/unicore32/include/asm/tlb.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_TLB_H__
+#define __UNICORE_TLB_H__
+
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#define __pte_free_tlb(tlb, pte, addr)				\
+	do {							\
+		pgtable_page_dtor(pte);				\
+		tlb_remove_page((tlb), (pte));			\
+	} while (0)
+
+#include <asm-generic/tlb.h>
+
+#endif
diff --git a/arch/unicore32/include/asm/tlbflush.h b/arch/unicore32/include/asm/tlbflush.h
new file mode 100644
index 0000000..e446ac8
--- /dev/null
+++ b/arch/unicore32/include/asm/tlbflush.h
@@ -0,0 +1,195 @@
+/*
+ * linux/arch/unicore32/include/asm/tlbflush.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_TLBFLUSH_H__
+#define __UNICORE_TLBFLUSH_H__
+
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+
+extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long,
+					struct vm_area_struct *);
+extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
+
+/*
+ *	TLB Management
+ *	==============
+ *
+ *	The arch/unicore/mm/tlb-*.S files implement these methods.
+ *
+ *	The TLB specific code is expected to perform whatever tests it
+ *	needs to determine if it should invalidate the TLB for each
+ *	call.  Start addresses are inclusive and end addresses are
+ *	exclusive; it is safe to round these addresses down.
+ *
+ *	flush_tlb_all()
+ *
+ *		Invalidate the entire TLB.
+ *
+ *	flush_tlb_mm(mm)
+ *
+ *		Invalidate all TLB entries in a particular address
+ *		space.
+ *		- mm	- mm_struct describing address space
+ *
+ *	flush_tlb_range(mm,start,end)
+ *
+ *		Invalidate a range of TLB entries in the specified
+ *		address space.
+ *		- mm	- mm_struct describing address space
+ *		- start - start address (may not be aligned)
+ *		- end	- end address (exclusive, may not be aligned)
+ *
+ *	flush_tlb_page(vaddr,vma)
+ *
+ *		Invalidate the specified page in the specified address range.
+ *		- vaddr - virtual address (may not be aligned)
+ *		- vma	- vma_struct describing address range
+ *
+ *	flush_kern_tlb_page(kaddr)
+ *
+ *		Invalidate the TLB entry for the specified page.  The address
+ *		will be in the kernels virtual memory space.  Current uses
+ *		only require the D-TLB to be invalidated.
+ *		- kaddr - Kernel virtual memory address
+ */
+
+static inline void local_flush_tlb_all(void)
+{
+	const int zero = 0;
+
+	/* TLB invalidate all */
+	asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (zero) : "cc");
+}
+
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+{
+	const int zero = 0;
+
+	if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
+		/* TLB invalidate all */
+		asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (zero) : "cc");
+	}
+	put_cpu();
+}
+
+static inline void
+local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+	if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
+#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+		/* iTLB invalidate page */
+		asm("movc p0.c6, %0, #5; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (uaddr & PAGE_MASK) : "cc");
+		/* dTLB invalidate page */
+		asm("movc p0.c6, %0, #3; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (uaddr & PAGE_MASK) : "cc");
+#else
+		/* TLB invalidate all */
+		asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (uaddr & PAGE_MASK) : "cc");
+#endif
+	}
+}
+
+static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
+{
+#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+	/* iTLB invalidate page */
+	asm("movc p0.c6, %0, #5; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (kaddr & PAGE_MASK) : "cc");
+	/* dTLB invalidate page */
+	asm("movc p0.c6, %0, #3; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (kaddr & PAGE_MASK) : "cc");
+#else
+	/* TLB invalidate all */
+	asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (kaddr & PAGE_MASK) : "cc");
+#endif
+}
+
+/*
+ *	flush_pmd_entry
+ *
+ *	Flush a PMD entry (word aligned, or double-word aligned) to
+ *	RAM if the TLB for the CPU we are running on requires this.
+ *	This is typically used when we are creating PMD entries.
+ *
+ *	clean_pmd_entry
+ *
+ *	Clean (but don't drain the write buffer) if the CPU requires
+ *	these operations.  This is typically used when we are removing
+ *	PMD entries.
+ */
+static inline void flush_pmd_entry(pmd_t *pmd)
+{
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	/* flush dcache line, see dcacheline_flush in proc-macros.S */
+	asm("mov	r1, %0 << #20\n"
+		"ldw	r2, =_stext\n"
+		"add	r2, r2, r1 >> #20\n"
+		"ldw	r1, [r2+], #0x0000\n"
+		"ldw	r1, [r2+], #0x1000\n"
+		"ldw	r1, [r2+], #0x2000\n"
+		"ldw	r1, [r2+], #0x3000\n"
+		: : "r" (pmd) : "r1", "r2");
+#else
+	/* flush dcache all */
+	asm("movc p0.c5, %0, #14; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (pmd) : "cc");
+#endif
+}
+
+static inline void clean_pmd_entry(pmd_t *pmd)
+{
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	/* clean dcache line */
+	asm("movc p0.c5, %0, #11; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (__pa(pmd) & ~(L1_CACHE_BYTES - 1)) : "cc");
+#else
+	/* clean dcache all */
+	asm("movc p0.c5, %0, #10; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (pmd) : "cc");
+#endif
+}
+
+/*
+ * Convert calls to our calling convention.
+ */
+#define local_flush_tlb_range(vma, start, end)	\
+	__cpu_flush_user_tlb_range(start, end, vma)
+#define local_flush_tlb_kernel_range(s, e)	\
+	__cpu_flush_kern_tlb_range(s, e)
+
+#define flush_tlb_all		local_flush_tlb_all
+#define flush_tlb_mm		local_flush_tlb_mm
+#define flush_tlb_page		local_flush_tlb_page
+#define flush_tlb_kernel_page	local_flush_tlb_kernel_page
+#define flush_tlb_range		local_flush_tlb_range
+#define flush_tlb_kernel_range	local_flush_tlb_kernel_range
+
+/*
+ * if PG_dcache_clean is not set for the page, we need to ensure that any
+ * cache entries for the kernels virtual memory range are written
+ * back to the page.
+ */
+extern void update_mmu_cache(struct vm_area_struct *vma,
+		unsigned long addr, pte_t *ptep);
+
+extern void do_bad_area(unsigned long addr, unsigned int fsr,
+		struct pt_regs *regs);
+
+#endif
+
+#endif
diff --git a/arch/unicore32/include/asm/traps.h b/arch/unicore32/include/asm/traps.h
new file mode 100644
index 0000000..66e17a7
--- /dev/null
+++ b/arch/unicore32/include/asm/traps.h
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/unicore32/include/asm/traps.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_TRAP_H__
+#define __UNICORE_TRAP_H__
+
+extern void __init early_trap_init(void);
+extern void dump_backtrace_entry(unsigned long where,
+		unsigned long from, unsigned long frame);
+
+extern void do_DataAbort(unsigned long addr, unsigned int fsr,
+		 struct pt_regs *regs);
+#endif
diff --git a/arch/unicore32/include/asm/uaccess.h b/arch/unicore32/include/asm/uaccess.h
new file mode 100644
index 0000000..2acda50
--- /dev/null
+++ b/arch/unicore32/include/asm/uaccess.h
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/unicore32/include/asm/uaccess.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_UACCESS_H__
+#define __UNICORE_UACCESS_H__
+
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+
+#include <asm/memory.h>
+#include <asm/system.h>
+
+#define __copy_from_user	__copy_from_user
+#define __copy_to_user		__copy_to_user
+#define __strncpy_from_user	__strncpy_from_user
+#define __strnlen_user		__strnlen_user
+#define __clear_user		__clear_user
+
+#define __kernel_ok		(segment_eq(get_fs(), KERNEL_DS))
+#define __user_ok(addr, size)	(((size) <= TASK_SIZE)			\
+				&& ((addr) <= TASK_SIZE - (size)))
+#define __access_ok(addr, size)	(__kernel_ok || __user_ok((addr), (size)))
+
+extern unsigned long __must_check
+__copy_from_user(void *to, const void __user *from, unsigned long n);
+extern unsigned long __must_check
+__copy_to_user(void __user *to, const void *from, unsigned long n);
+extern unsigned long __must_check
+__clear_user(void __user *addr, unsigned long n);
+extern unsigned long __must_check
+__strncpy_from_user(char *to, const char __user *from, unsigned long count);
+extern unsigned long
+__strnlen_user(const char __user *s, long n);
+
+#include <asm-generic/uaccess.h>
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#endif /* __UNICORE_UACCESS_H__ */
diff --git a/arch/unicore32/include/asm/unistd.h b/arch/unicore32/include/asm/unistd.h
new file mode 100644
index 0000000..9b24280
--- /dev/null
+++ b/arch/unicore32/include/asm/unistd.h
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/unicore32/include/asm/unistd.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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(__UNICORE_UNISTD_H__) || defined(__SYSCALL)
+#define __UNICORE_UNISTD_H__
+
+/* Use the standard ABI for syscalls. */
+#include <asm-generic/unistd.h>
+
+#endif /* __UNICORE_UNISTD_H__ */
diff --git a/arch/unicore32/include/mach/PKUnity.h b/arch/unicore32/include/mach/PKUnity.h
new file mode 100644
index 0000000..a18bdc3
--- /dev/null
+++ b/arch/unicore32/include/mach/PKUnity.h
@@ -0,0 +1,108 @@
+/*
+ * linux/arch/unicore32/include/mach/PKUnity.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Be sure that virtual mapping is defined right */
+#ifndef __MACH_PUV3_HARDWARE_H__
+#error You must include hardware.h not PKUnity.h
+#endif
+
+#include "bitfield.h"
+
+/*
+ * Memory Definitions
+ */
+#define PKUNITY_SDRAM_BASE		0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
+#define PKUNITY_MMIO_BASE		0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
+
+/*
+ * PKUNITY Memory Map Addresses: 0x0D000000 - 0x0EFFFFFF (32MB)
+ *	0x0D000000 - 0x0DFFFFFF 16MB: for UVC
+ *	0x0E000000 - 0x0EFFFFFF 16MB: for UNIGFX
+ */
+#define PKUNITY_UVC_MMAP_BASE		0x0D000000
+#define PKUNITY_UVC_MMAP_SIZE		0x01000000 /* 16MB */
+#define PKUNITY_UNIGFX_MMAP_BASE        0x0E000000
+#define PKUNITY_UNIGFX_MMAP_SIZE        0x01000000 /* 16MB */
+
+/*
+ * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
+ * 0x80000000 - 0x8000000B 12B    PCI Configuration regs
+ * 0x80010000 - 0x80010250 592B   PCI Bridge Base
+ * 0x80030000 - 0x8003FFFF 64KB   PCI Legacy IO
+ * 0x90000000 - 0x97FFFFFF 128MB  PCI AHB-PCI MEM-mapping
+ * 0x98000000 - 0x9FFFFFFF 128MB  PCI PCI-AHB MEM-mapping
+ */
+#define PKUNITY_PCI_BASE		io_p2v(0x80000000) /* 0x80000000 - 0xBFFFFFFF 1GB */
+#include "regs-pci.h"
+
+#define PKUNITY_PCICFG_BASE		(PKUNITY_PCI_BASE + 0x0)
+#define PKUNITY_PCIBRI_BASE		(PKUNITY_PCI_BASE + 0x00010000)
+#define PKUNITY_PCILIO_BASE		(PKUNITY_PCI_BASE + 0x00030000)
+#define PKUNITY_PCIMEM_BASE		(PKUNITY_PCI_BASE + 0x10000000)
+#define PKUNITY_PCIAHB_BASE		(PKUNITY_PCI_BASE + 0x18000000)
+
+/*
+ * PKUNITY System Bus Addresses (AHB): 0xC0000000 - 0xEDFFFFFF (640MB)
+ */
+#define PKUNITY_AHB_BASE		io_p2v(0xC0000000)
+
+/* AHB-0 is DDR2 SDRAM */
+/* AHB-1 is PCI Space */
+#define PKUNITY_ARBITER_BASE		(PKUNITY_AHB_BASE + 0x000000) /* AHB-2 */
+#define PKUNITY_DDR2CTRL_BASE		(PKUNITY_AHB_BASE + 0x100000) /* AHB-3 */
+#define PKUNITY_DMAC_BASE		(PKUNITY_AHB_BASE + 0x200000) /* AHB-4 */
+#include "regs-dmac.h"
+#define PKUNITY_UMAL_BASE		(PKUNITY_AHB_BASE + 0x300000) /* AHB-5 */
+#include "regs-umal.h"
+#define PKUNITY_USB_BASE		(PKUNITY_AHB_BASE + 0x400000) /* AHB-6 */
+#define PKUNITY_SATA_BASE		(PKUNITY_AHB_BASE + 0x500000) /* AHB-7 */
+#define PKUNITY_SMC_BASE		(PKUNITY_AHB_BASE + 0x600000) /* AHB-8 */
+/* AHB-9 is for APB bridge */
+#define PKUNITY_MME_BASE		(PKUNITY_AHB_BASE + 0x700000) /* AHB-10 */
+#define PKUNITY_UNIGFX_BASE		(PKUNITY_AHB_BASE + 0x800000) /* AHB-11 */
+#include "regs-unigfx.h"
+#define PKUNITY_NAND_BASE		(PKUNITY_AHB_BASE + 0x900000) /* AHB-12 */
+#include "regs-nand.h"
+#define PKUNITY_H264D_BASE		(PKUNITY_AHB_BASE + 0xA00000) /* AHB-13 */
+#define PKUNITY_H264E_BASE		(PKUNITY_AHB_BASE + 0xB00000) /* AHB-14 */
+
+/*
+ * PKUNITY Peripheral Bus Addresses (APB): 0xEE000000 - 0xEFFFFFFF (128MB)
+ */
+#define PKUNITY_APB_BASE		io_p2v(0xEE000000)
+
+#define PKUNITY_UART0_BASE		(PKUNITY_APB_BASE + 0x000000) /* APB-0 */
+#define PKUNITY_UART1_BASE		(PKUNITY_APB_BASE + 0x100000) /* APB-1 */
+#include "regs-uart.h"
+#define PKUNITY_I2C_BASE		(PKUNITY_APB_BASE + 0x200000) /* APB-2 */
+#include "regs-i2c.h"
+#define PKUNITY_SPI_BASE		(PKUNITY_APB_BASE + 0x300000) /* APB-3 */
+#include "regs-spi.h"
+#define PKUNITY_AC97_BASE		(PKUNITY_APB_BASE + 0x400000) /* APB-4 */
+#include "regs-ac97.h"
+#define PKUNITY_GPIO_BASE		(PKUNITY_APB_BASE + 0x500000) /* APB-5 */
+#include "regs-gpio.h"
+#define PKUNITY_INTC_BASE		(PKUNITY_APB_BASE + 0x600000) /* APB-6 */
+#include "regs-intc.h"
+#define PKUNITY_RTC_BASE		(PKUNITY_APB_BASE + 0x700000) /* APB-7 */
+#include "regs-rtc.h"
+#define PKUNITY_OST_BASE		(PKUNITY_APB_BASE + 0x800000) /* APB-8 */
+#include "regs-ost.h"
+#define PKUNITY_RESETC_BASE		(PKUNITY_APB_BASE + 0x900000) /* APB-9 */
+#include "regs-resetc.h"
+#define PKUNITY_PM_BASE			(PKUNITY_APB_BASE + 0xA00000) /* APB-10 */
+#include "regs-pm.h"
+#define PKUNITY_PS2_BASE		(PKUNITY_APB_BASE + 0xB00000) /* APB-11 */
+#include "regs-ps2.h"
+#define PKUNITY_SDC_BASE		(PKUNITY_APB_BASE + 0xC00000) /* APB-12 */
+#include "regs-sdc.h"
+
diff --git a/arch/unicore32/include/mach/bitfield.h b/arch/unicore32/include/mach/bitfield.h
new file mode 100644
index 0000000..128a702
--- /dev/null
+++ b/arch/unicore32/include/mach/bitfield.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/mach/bitfield.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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_PUV3_BITFIELD_H__
+#define __MACH_PUV3_BITFIELD_H__
+
+#ifndef __ASSEMBLY__
+#define UData(Data)	((unsigned long) (Data))
+#else
+#define UData(Data)	(Data)
+#endif
+
+#define FIELD(val, vmask, vshift)	(((val) & ((UData(1) << (vmask)) - 1)) << (vshift))
+#define FMASK(vmask, vshift)		(((UData(1) << (vmask)) - 1) << (vshift))
+
+#endif /* __MACH_PUV3_BITFIELD_H__ */
diff --git a/arch/unicore32/include/mach/dma.h b/arch/unicore32/include/mach/dma.h
new file mode 100644
index 0000000..d655c1b
--- /dev/null
+++ b/arch/unicore32/include/mach/dma.h
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/unicore32/include/mach/dma.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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_PUV3_DMA_H__
+#define __MACH_PUV3_DMA_H__
+
+/*
+ * The PKUnity has six internal DMA channels.
+ */
+#define MAX_DMA_CHANNELS	6
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+} puv3_dma_prio;
+
+/*
+ * DMA registration
+ */
+
+extern int puv3_request_dma(char *name,
+			 puv3_dma_prio prio,
+			 void (*irq_handler)(int, void *),
+			 void (*err_handler)(int, void *),
+			 void *data);
+
+extern void puv3_free_dma(int dma_ch);
+
+static inline void puv3_stop_dma(int ch)
+{
+	writel(readl(DMAC_CONFIG(ch)) & ~DMAC_CONFIG_EN, DMAC_CONFIG(ch));
+}
+
+static inline void puv3_resume_dma(int ch)
+{
+	writel(readl(DMAC_CONFIG(ch)) | DMAC_CONFIG_EN, DMAC_CONFIG(ch));
+}
+
+#endif /* __MACH_PUV3_DMA_H__ */
diff --git a/arch/unicore32/include/mach/hardware.h b/arch/unicore32/include/mach/hardware.h
new file mode 100644
index 0000000..930bea6
--- /dev/null
+++ b/arch/unicore32/include/mach/hardware.h
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/unicore32/include/mach/hardware.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 hardware definitions for PKUnity architecture
+ */
+
+#ifndef __MACH_PUV3_HARDWARE_H__
+#define __MACH_PUV3_HARDWARE_H__
+
+#include "PKUnity.h"
+
+#ifndef __ASSEMBLY__
+#define io_p2v(x)	(void __iomem *)((x) - PKUNITY_MMIO_BASE)
+#define io_v2p(x)	(phys_addr_t)((x) + PKUNITY_MMIO_BASE)
+#else
+#define io_p2v(x)	((x) - PKUNITY_MMIO_BASE)
+#define io_v2p(x)	((x) + PKUNITY_MMIO_BASE)
+#endif
+
+#define PCIBIOS_MIN_IO			0x4000 /* should lower than 64KB */
+#define PCIBIOS_MIN_MEM			io_v2p(PKUNITY_PCIMEM_BASE)
+
+/*
+ * We override the standard dma-mask routines for bouncing.
+ */
+#define	HAVE_ARCH_PCI_SET_DMA_MASK
+
+#define pcibios_assign_all_busses()	1
+
+#endif  /* __MACH_PUV3_HARDWARE_H__ */
diff --git a/arch/unicore32/include/mach/map.h b/arch/unicore32/include/mach/map.h
new file mode 100644
index 0000000..55c9365
--- /dev/null
+++ b/arch/unicore32/include/mach/map.h
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/unicore32/include/mach/map.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Page table mapping constructs and function prototypes
+ */
+#define MT_DEVICE		0
+#define MT_DEVICE_CACHED	2
+#define MT_KUSER		7
+#define MT_HIGH_VECTORS		8
+#define MT_MEMORY		9
+#define MT_ROM			10
+
diff --git a/arch/unicore32/include/mach/memory.h b/arch/unicore32/include/mach/memory.h
new file mode 100644
index 0000000..0bf21c9
--- /dev/null
+++ b/arch/unicore32/include/mach/memory.h
@@ -0,0 +1,58 @@
+/*
+ * linux/arch/unicore32/include/mach/memory.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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_PUV3_MEMORY_H__
+#define __MACH_PUV3_MEMORY_H__
+
+#include <mach/hardware.h>
+
+/* Physical DRAM offset. */
+#define PHYS_OFFSET	UL(0x00000000)
+/* The base address of exception vectors. */
+#define VECTORS_BASE	UL(0xffff0000)
+/* The base address of kuser area. */
+#define KUSER_BASE	UL(0x80000000)
+
+#ifdef __ASSEMBLY__
+/* The byte offset of the kernel image in RAM from the start of RAM. */
+#define KERNEL_IMAGE_START	0x00408000
+#endif
+
+#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
+
+void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
+
+#define arch_adjust_zones(size, holes) \
+	puv3_pci_adjust_zones(size, holes)
+
+#endif
+
+/*
+ * PCI controller in PKUnity-3 masks highest 5-bit for upstream channel,
+ * so we must limit the DMA allocation within 128M physical memory for
+ * supporting PCI devices.
+ */
+#define PCI_DMA_THRESHOLD	(PHYS_OFFSET + SZ_128M - 1)
+
+#define is_pcibus_device(dev)	(dev &&			\
+				(strncmp(dev->bus->name, "pci", 3) == 0))
+
+#define __virt_to_pcibus(x)     (__virt_to_phys((x) + PKUNITY_PCIAHB_BASE))
+#define __pcibus_to_virt(x)     (__phys_to_virt(x) - PKUNITY_PCIAHB_BASE)
+
+/* kuser area */
+#define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
+#define KUSER_UNIGFX_BASE	(PAGE_OFFSET + PKUNITY_UNIGFX_MMAP_BASE)
+/* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
+#define kuser_vecpage_to_vectors(x)	((x) - (KUSER_VECPAGE_BASE)	\
+					+ (VECTORS_BASE))
+
+#endif
diff --git a/arch/unicore32/include/mach/ocd.h b/arch/unicore32/include/mach/ocd.h
new file mode 100644
index 0000000..189fd71
--- /dev/null
+++ b/arch/unicore32/include/mach/ocd.h
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/unicore32/include/mach/ocd.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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_PUV3_OCD_H__
+#define __MACH_PUV3_OCD_H__
+
+#if defined(CONFIG_DEBUG_OCD)
+static inline void ocd_putc(unsigned int c)
+{
+	int status, i = 0x2000000;
+
+	do {
+		if (--i < 0)
+			return;
+
+		asm volatile ("movc %0, p1.c0, #0" : "=r" (status));
+	} while (status & 2);
+
+	asm("movc p1.c1, %0, #1" : : "r" (c));
+}
+
+#define putc(ch)	ocd_putc(ch)
+#else
+#define putc(ch)
+#endif
+
+#endif
diff --git a/arch/unicore32/include/mach/pm.h b/arch/unicore32/include/mach/pm.h
new file mode 100644
index 0000000..4dcd34a
--- /dev/null
+++ b/arch/unicore32/include/mach/pm.h
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/unicore/include/mach/pm.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __PUV3_PM_H__
+#define __PUV3_PM_H__
+
+#include <linux/suspend.h>
+
+struct puv3_cpu_pm_fns {
+	int	save_count;
+	void	(*save)(unsigned long *);
+	void	(*restore)(unsigned long *);
+	int	(*valid)(suspend_state_t state);
+	void	(*enter)(suspend_state_t state);
+	int	(*prepare)(void);
+	void	(*finish)(void);
+};
+
+extern struct puv3_cpu_pm_fns *puv3_cpu_pm_fns;
+
+/* sleep.S */
+extern void puv3_cpu_suspend(unsigned int);
+
+extern void puv3_cpu_resume(void);
+
+extern int puv3_pm_enter(suspend_state_t state);
+
+/* Defined in hibernate_asm.S */
+extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+extern struct pbe *restore_pblist;
+#endif
diff --git a/arch/unicore32/include/mach/regs-ac97.h b/arch/unicore32/include/mach/regs-ac97.h
new file mode 100644
index 0000000..b7563e9
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-ac97.h
@@ -0,0 +1,32 @@
+/*
+ * PKUnity AC97 Registers
+ */
+
+#define PKUNITY_AC97_CONR		(PKUNITY_AC97_BASE + 0x0000)
+#define PKUNITY_AC97_OCR		(PKUNITY_AC97_BASE + 0x0004)
+#define PKUNITY_AC97_ICR		(PKUNITY_AC97_BASE + 0x0008)
+#define PKUNITY_AC97_CRAC		(PKUNITY_AC97_BASE + 0x000C)
+#define PKUNITY_AC97_INTR		(PKUNITY_AC97_BASE + 0x0010)
+#define PKUNITY_AC97_INTRSTAT		(PKUNITY_AC97_BASE + 0x0014)
+#define PKUNITY_AC97_INTRCLEAR		(PKUNITY_AC97_BASE + 0x0018)
+#define PKUNITY_AC97_ENABLE		(PKUNITY_AC97_BASE + 0x001C)
+#define PKUNITY_AC97_OUT_FIFO		(PKUNITY_AC97_BASE + 0x0020)
+#define PKUNITY_AC97_IN_FIFO		(PKUNITY_AC97_BASE + 0x0030)
+
+#define AC97_CODEC_REG(v)               FIELD((v), 7, 16)
+#define AC97_CODEC_VAL(v)               FIELD((v), 16, 0)
+#define AC97_CODEC_WRITECOMPLETE        FIELD(1, 1, 2)
+
+/*
+ * VAR PLAY SAMPLE RATE
+ */
+#define AC97_CMD_VPSAMPLE		(FIELD(3, 2, 16) | FIELD(3, 2, 0))
+
+/*
+ * FIX CAPTURE SAMPLE RATE
+ */
+#define AC97_CMD_FCSAMPLE		FIELD(7, 3, 0)
+
+#define AC97_CMD_RESET			FIELD(1, 1, 0)
+#define AC97_CMD_ENABLE			FIELD(1, 1, 0)
+#define AC97_CMD_DISABLE		FIELD(0, 1, 0)
diff --git a/arch/unicore32/include/mach/regs-dmac.h b/arch/unicore32/include/mach/regs-dmac.h
new file mode 100644
index 0000000..66de9e7
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-dmac.h
@@ -0,0 +1,81 @@
+/*
+ * PKUnity Direct Memory Access Controller (DMAC)
+ */
+
+/*
+ * Interrupt Status Reg DMAC_ISR.
+ */
+#define DMAC_ISR		(PKUNITY_DMAC_BASE + 0x0020)
+/*
+ * Interrupt Transfer Complete Status Reg DMAC_ITCSR.
+ */
+#define DMAC_ITCSR		(PKUNITY_DMAC_BASE + 0x0050)
+/*
+ * Interrupt Transfer Complete Clear Reg DMAC_ITCCR.
+ */
+#define DMAC_ITCCR		(PKUNITY_DMAC_BASE + 0x0060)
+/*
+ * Interrupt Error Status Reg DMAC_IESR.
+ */
+#define DMAC_IESR		(PKUNITY_DMAC_BASE + 0x0080)
+/*
+ * Interrupt Error Clear Reg DMAC_IECR.
+ */
+#define DMAC_IECR		(PKUNITY_DMAC_BASE + 0x0090)
+/*
+ * Enable Channels Reg DMAC_ENCH.
+ */
+#define DMAC_ENCH		(PKUNITY_DMAC_BASE + 0x00B0)
+
+/*
+ * DMA control reg. Space [byte]
+ */
+#define DMASp                   0x00000100
+
+/*
+ * Source Addr DMAC_SRCADDR(ch).
+ */
+#define DMAC_SRCADDR(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x00)
+/*
+ * Destination Addr DMAC_DESTADDR(ch).
+ */
+#define DMAC_DESTADDR(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x04)
+/*
+ * Control Reg DMAC_CONTROL(ch).
+ */
+#define DMAC_CONTROL(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x0C)
+/*
+ * Configuration Reg DMAC_CONFIG(ch).
+ */
+#define DMAC_CONFIG(ch)		(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x10)
+
+#define DMAC_IR_MASK            FMASK(6, 0)
+/*
+ * select channel (ch)
+ */
+#define DMAC_CHANNEL(ch)	FIELD(1, 1, (ch))
+
+#define DMAC_CONTROL_SIZE_BYTE(v)       (FIELD((v), 12, 14) | \
+					FIELD(0, 3, 9) | FIELD(0, 3, 6))
+#define DMAC_CONTROL_SIZE_HWORD(v)      (FIELD((v) >> 1, 12, 14) | \
+					FIELD(1, 3, 9) | FIELD(1, 3, 6))
+#define DMAC_CONTROL_SIZE_WORD(v)       (FIELD((v) >> 2, 12, 14) | \
+					FIELD(2, 3, 9) | FIELD(2, 3, 6))
+#define DMAC_CONTROL_DI                 FIELD(1, 1, 13)
+#define DMAC_CONTROL_SI                 FIELD(1, 1, 12)
+#define DMAC_CONTROL_BURST_1BYTE        (FIELD(0, 3, 3) | FIELD(0, 3, 0))
+#define DMAC_CONTROL_BURST_4BYTE        (FIELD(3, 3, 3) | FIELD(3, 3, 0))
+#define DMAC_CONTROL_BURST_8BYTE        (FIELD(5, 3, 3) | FIELD(5, 3, 0))
+#define DMAC_CONTROL_BURST_16BYTE       (FIELD(7, 3, 3) | FIELD(7, 3, 0))
+
+#define	DMAC_CONFIG_UART0_WR    (FIELD(2, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_UART0_RD    (FIELD(2, 4, 7)  | FIELD(2, 2, 1))
+#define	DMAC_CONFIG_UART1_WR    (FIELD(3, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_UART1RD     (FIELD(3, 4, 7)  | FIELD(2, 2, 1))
+#define	DMAC_CONFIG_AC97WR      (FIELD(4, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_AC97RD      (FIELD(4, 4, 7)  | FIELD(2, 2, 1))
+#define	DMAC_CONFIG_MMCWR       (FIELD(7, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_MMCRD       (FIELD(7, 4, 7)  | FIELD(2, 2, 1))
+#define DMAC_CONFIG_MASKITC     FIELD(1, 1, 4)
+#define DMAC_CONFIG_MASKIE      FIELD(1, 1, 3)
+#define DMAC_CONFIG_EN          FIELD(1, 1, 0)
diff --git a/arch/unicore32/include/mach/regs-gpio.h b/arch/unicore32/include/mach/regs-gpio.h
new file mode 100644
index 0000000..0273b86
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-gpio.h
@@ -0,0 +1,70 @@
+/*
+ * PKUnity General-Purpose Input/Output (GPIO) Registers
+ */
+
+/*
+ * Voltage Status Reg GPIO_GPLR.
+ */
+#define GPIO_GPLR	(PKUNITY_GPIO_BASE + 0x0000)
+/*
+ * Pin Direction Reg GPIO_GPDR.
+ */
+#define GPIO_GPDR	(PKUNITY_GPIO_BASE + 0x0004)
+/*
+ * Output Pin Set Reg GPIO_GPSR.
+ */
+#define GPIO_GPSR	(PKUNITY_GPIO_BASE + 0x0008)
+/*
+ * Output Pin Clear Reg GPIO_GPCR.
+ */
+#define GPIO_GPCR	(PKUNITY_GPIO_BASE + 0x000C)
+/*
+ * Raise Edge Detect Reg GPIO_GRER.
+ */
+#define GPIO_GRER	(PKUNITY_GPIO_BASE + 0x0010)
+/*
+ * Fall Edge Detect Reg GPIO_GFER.
+ */
+#define GPIO_GFER	(PKUNITY_GPIO_BASE + 0x0014)
+/*
+ * Edge Status Reg GPIO_GEDR.
+ */
+#define GPIO_GEDR	(PKUNITY_GPIO_BASE + 0x0018)
+/*
+ * Sepcial Voltage Detect Reg GPIO_GPIR.
+ */
+#define GPIO_GPIR	(PKUNITY_GPIO_BASE + 0x0020)
+
+#define GPIO_MIN	(0)
+#define GPIO_MAX	(27)
+
+#define GPIO_GPIO(Nb)	(0x00000001 << (Nb))	/* GPIO [0..27] */
+#define GPIO_GPIO0	GPIO_GPIO(0)	/* GPIO  [0] */
+#define GPIO_GPIO1	GPIO_GPIO(1)	/* GPIO  [1] */
+#define GPIO_GPIO2	GPIO_GPIO(2)	/* GPIO  [2] */
+#define GPIO_GPIO3	GPIO_GPIO(3)	/* GPIO  [3] */
+#define GPIO_GPIO4	GPIO_GPIO(4)	/* GPIO  [4] */
+#define GPIO_GPIO5	GPIO_GPIO(5)	/* GPIO  [5] */
+#define GPIO_GPIO6	GPIO_GPIO(6)	/* GPIO  [6] */
+#define GPIO_GPIO7	GPIO_GPIO(7)	/* GPIO  [7] */
+#define GPIO_GPIO8	GPIO_GPIO(8)	/* GPIO  [8] */
+#define GPIO_GPIO9	GPIO_GPIO(9)	/* GPIO  [9] */
+#define GPIO_GPIO10	GPIO_GPIO(10)	/* GPIO [10] */
+#define GPIO_GPIO11	GPIO_GPIO(11)	/* GPIO [11] */
+#define GPIO_GPIO12	GPIO_GPIO(12)	/* GPIO [12] */
+#define GPIO_GPIO13	GPIO_GPIO(13)	/* GPIO [13] */
+#define GPIO_GPIO14	GPIO_GPIO(14)	/* GPIO [14] */
+#define GPIO_GPIO15	GPIO_GPIO(15)	/* GPIO [15] */
+#define GPIO_GPIO16	GPIO_GPIO(16)	/* GPIO [16] */
+#define GPIO_GPIO17	GPIO_GPIO(17)	/* GPIO [17] */
+#define GPIO_GPIO18	GPIO_GPIO(18)	/* GPIO [18] */
+#define GPIO_GPIO19	GPIO_GPIO(19)	/* GPIO [19] */
+#define GPIO_GPIO20	GPIO_GPIO(20)	/* GPIO [20] */
+#define GPIO_GPIO21	GPIO_GPIO(21)	/* GPIO [21] */
+#define GPIO_GPIO22	GPIO_GPIO(22)	/* GPIO [22] */
+#define GPIO_GPIO23	GPIO_GPIO(23)	/* GPIO [23] */
+#define GPIO_GPIO24	GPIO_GPIO(24)	/* GPIO [24] */
+#define GPIO_GPIO25	GPIO_GPIO(25)	/* GPIO [25] */
+#define GPIO_GPIO26	GPIO_GPIO(26)	/* GPIO [26] */
+#define GPIO_GPIO27	GPIO_GPIO(27)	/* GPIO [27] */
+
diff --git a/arch/unicore32/include/mach/regs-i2c.h b/arch/unicore32/include/mach/regs-i2c.h
new file mode 100644
index 0000000..463d108
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-i2c.h
@@ -0,0 +1,63 @@
+/*
+ * PKUnity Inter-integrated Circuit (I2C) Registers
+ */
+
+/*
+ * Control Reg I2C_CON.
+ */
+#define I2C_CON		(PKUNITY_I2C_BASE + 0x0000)
+/*
+ * Target Address Reg I2C_TAR.
+ */
+#define I2C_TAR		(PKUNITY_I2C_BASE + 0x0004)
+/*
+ * Data buffer and command Reg I2C_DATACMD.
+ */
+#define I2C_DATACMD	(PKUNITY_I2C_BASE + 0x0010)
+/*
+ * Enable Reg I2C_ENABLE.
+ */
+#define I2C_ENABLE	(PKUNITY_I2C_BASE + 0x006C)
+/*
+ * Status Reg I2C_STATUS.
+ */
+#define I2C_STATUS	(PKUNITY_I2C_BASE + 0x0070)
+/*
+ * Tx FIFO Length Reg I2C_TXFLR.
+ */
+#define I2C_TXFLR	(PKUNITY_I2C_BASE + 0x0074)
+/*
+ * Rx FIFO Length Reg I2C_RXFLR.
+ */
+#define I2C_RXFLR	(PKUNITY_I2C_BASE + 0x0078)
+/*
+ * Enable Status Reg I2C_ENSTATUS.
+ */
+#define I2C_ENSTATUS	(PKUNITY_I2C_BASE + 0x009C)
+
+#define I2C_CON_MASTER          FIELD(1, 1, 0)
+#define I2C_CON_SPEED_STD       FIELD(1, 2, 1)
+#define I2C_CON_SPEED_FAST      FIELD(2, 2, 1)
+#define I2C_CON_RESTART         FIELD(1, 1, 5)
+#define I2C_CON_SLAVEDISABLE    FIELD(1, 1, 6)
+
+#define I2C_DATACMD_READ        FIELD(1, 1, 8)
+#define I2C_DATACMD_WRITE       FIELD(0, 1, 8)
+#define I2C_DATACMD_DAT_MASK    FMASK(8, 0)
+#define I2C_DATACMD_DAT(v)      FIELD((v), 8, 0)
+
+#define I2C_ENABLE_ENABLE       FIELD(1, 1, 0)
+#define I2C_ENABLE_DISABLE      FIELD(0, 1, 0)
+
+#define I2C_STATUS_RFF          FIELD(1, 1, 4)
+#define I2C_STATUS_RFNE         FIELD(1, 1, 3)
+#define I2C_STATUS_TFE          FIELD(1, 1, 2)
+#define I2C_STATUS_TFNF         FIELD(1, 1, 1)
+#define I2C_STATUS_ACTIVITY     FIELD(1, 1, 0)
+
+#define I2C_ENSTATUS_ENABLE	FIELD(1, 1, 0)
+
+#define I2C_TAR_THERMAL	0x4f
+#define I2C_TAR_SPD	0x50
+#define I2C_TAR_PWIC    0x55
+#define I2C_TAR_EEPROM	0x57
diff --git a/arch/unicore32/include/mach/regs-intc.h b/arch/unicore32/include/mach/regs-intc.h
new file mode 100644
index 0000000..25648f8
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-intc.h
@@ -0,0 +1,28 @@
+/*
+ * PKUNITY Interrupt Controller (INTC) Registers
+ */
+/*
+ * INTC Level Reg INTC_ICLR.
+ */
+#define INTC_ICLR	(PKUNITY_INTC_BASE + 0x0000)
+/*
+ * INTC Mask Reg INTC_ICMR.
+ */
+#define INTC_ICMR	(PKUNITY_INTC_BASE + 0x0004)
+/*
+ * INTC Pending Reg INTC_ICPR.
+ */
+#define INTC_ICPR	(PKUNITY_INTC_BASE + 0x0008)
+/*
+ * INTC IRQ Pending Reg INTC_ICIP.
+ */
+#define INTC_ICIP	(PKUNITY_INTC_BASE + 0x000C)
+/*
+ * INTC REAL Pending Reg INTC_ICFP.
+ */
+#define INTC_ICFP	(PKUNITY_INTC_BASE + 0x0010)
+/*
+ * INTC Control Reg INTC_ICCR.
+ */
+#define INTC_ICCR	(PKUNITY_INTC_BASE + 0x0014)
+
diff --git a/arch/unicore32/include/mach/regs-nand.h b/arch/unicore32/include/mach/regs-nand.h
new file mode 100644
index 0000000..a7c5563
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-nand.h
@@ -0,0 +1,79 @@
+/*
+ * PKUnity NAND Controller Registers
+ */
+/*
+ * ID Reg. 0 NAND_IDR0
+ */
+#define NAND_IDR0	(PKUNITY_NAND_BASE + 0x0000)
+/*
+ * ID Reg. 1 NAND_IDR1
+ */
+#define NAND_IDR1	(PKUNITY_NAND_BASE + 0x0004)
+/*
+ * ID Reg. 2 NAND_IDR2
+ */
+#define NAND_IDR2	(PKUNITY_NAND_BASE + 0x0008)
+/*
+ * ID Reg. 3 NAND_IDR3
+ */
+#define NAND_IDR3	(PKUNITY_NAND_BASE + 0x000C)
+/*
+ * Page Address Reg 0 NAND_PAR0
+ */
+#define NAND_PAR0	(PKUNITY_NAND_BASE + 0x0010)
+/*
+ * Page Address Reg 1 NAND_PAR1
+ */
+#define NAND_PAR1	(PKUNITY_NAND_BASE + 0x0014)
+/*
+ * Page Address Reg 2 NAND_PAR2
+ */
+#define NAND_PAR2	(PKUNITY_NAND_BASE + 0x0018)
+/*
+ * ECC Enable Reg NAND_ECCEN
+ */
+#define NAND_ECCEN	(PKUNITY_NAND_BASE + 0x001C)
+/*
+ * Buffer Reg NAND_BUF
+ */
+#define NAND_BUF	(PKUNITY_NAND_BASE + 0x0020)
+/*
+ * ECC Status Reg NAND_ECCSR
+ */
+#define NAND_ECCSR	(PKUNITY_NAND_BASE + 0x0024)
+/*
+ * Command Reg NAND_CMD
+ */
+#define NAND_CMD	(PKUNITY_NAND_BASE + 0x0028)
+/*
+ * DMA Configure Reg NAND_DMACR
+ */
+#define NAND_DMACR	(PKUNITY_NAND_BASE + 0x002C)
+/*
+ * Interrupt Reg NAND_IR
+ */
+#define NAND_IR		(PKUNITY_NAND_BASE + 0x0030)
+/*
+ * Interrupt Mask Reg NAND_IMR
+ */
+#define NAND_IMR	(PKUNITY_NAND_BASE + 0x0034)
+/*
+ * Chip Enable Reg NAND_CHIPEN
+ */
+#define NAND_CHIPEN	(PKUNITY_NAND_BASE + 0x0038)
+/*
+ * Address Reg NAND_ADDR
+ */
+#define NAND_ADDR	(PKUNITY_NAND_BASE + 0x003C)
+
+/*
+ * Command bits NAND_CMD_CMD_MASK
+ */
+#define NAND_CMD_CMD_MASK		FMASK(4, 4)
+#define NAND_CMD_CMD_READPAGE		FIELD(0x0, 4, 4)
+#define NAND_CMD_CMD_ERASEBLOCK		FIELD(0x6, 4, 4)
+#define NAND_CMD_CMD_READSTATUS		FIELD(0x7, 4, 4)
+#define NAND_CMD_CMD_WRITEPAGE		FIELD(0x8, 4, 4)
+#define NAND_CMD_CMD_READID		FIELD(0x9, 4, 4)
+#define NAND_CMD_CMD_RESET		FIELD(0xf, 4, 4)
+
diff --git a/arch/unicore32/include/mach/regs-ost.h b/arch/unicore32/include/mach/regs-ost.h
new file mode 100644
index 0000000..7b91fe6
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-ost.h
@@ -0,0 +1,92 @@
+/*
+ * PKUnity Operating System Timer (OST) Registers
+ */
+/*
+ * Match Reg 0 OST_OSMR0
+ */
+#define OST_OSMR0	(PKUNITY_OST_BASE + 0x0000)
+/*
+ * Match Reg 1 OST_OSMR1
+ */
+#define OST_OSMR1	(PKUNITY_OST_BASE + 0x0004)
+/*
+ * Match Reg 2 OST_OSMR2
+ */
+#define OST_OSMR2	(PKUNITY_OST_BASE + 0x0008)
+/*
+ * Match Reg 3 OST_OSMR3
+ */
+#define OST_OSMR3	(PKUNITY_OST_BASE + 0x000C)
+/*
+ * Counter Reg OST_OSCR
+ */
+#define OST_OSCR	(PKUNITY_OST_BASE + 0x0010)
+/*
+ * Status Reg OST_OSSR
+ */
+#define OST_OSSR	(PKUNITY_OST_BASE + 0x0014)
+/*
+ * Watchdog Enable Reg OST_OWER
+ */
+#define OST_OWER	(PKUNITY_OST_BASE + 0x0018)
+/*
+ * Interrupt Enable Reg OST_OIER
+ */
+#define OST_OIER	(PKUNITY_OST_BASE + 0x001C)
+/*
+ * PWM Pulse Width Control Reg OST_PWMPWCR
+ */
+#define OST_PWMPWCR	(PKUNITY_OST_BASE + 0x0080)
+/*
+ * PWM Duty Cycle Control Reg OST_PWMDCCR
+ */
+#define OST_PWMDCCR	(PKUNITY_OST_BASE + 0x0084)
+/*
+ * PWM Period Control Reg OST_PWMPCR
+ */
+#define OST_PWMPCR	(PKUNITY_OST_BASE + 0x0088)
+
+/*
+ * Match detected 0 OST_OSSR_M0
+ */
+#define OST_OSSR_M0		FIELD(1, 1, 0)
+/*
+ * Match detected 1 OST_OSSR_M1
+ */
+#define OST_OSSR_M1		FIELD(1, 1, 1)
+/*
+ * Match detected 2 OST_OSSR_M2
+ */
+#define OST_OSSR_M2		FIELD(1, 1, 2)
+/*
+ * Match detected 3 OST_OSSR_M3
+ */
+#define OST_OSSR_M3		FIELD(1, 1, 3)
+
+/*
+ * Interrupt enable 0 OST_OIER_E0
+ */
+#define OST_OIER_E0		FIELD(1, 1, 0)
+/*
+ * Interrupt enable 1 OST_OIER_E1
+ */
+#define OST_OIER_E1		FIELD(1, 1, 1)
+/*
+ * Interrupt enable 2 OST_OIER_E2
+ */
+#define OST_OIER_E2		FIELD(1, 1, 2)
+/*
+ * Interrupt enable 3 OST_OIER_E3
+ */
+#define OST_OIER_E3		FIELD(1, 1, 3)
+
+/*
+ * Watchdog Match Enable OST_OWER_WME
+ */
+#define OST_OWER_WME		FIELD(1, 1, 0)
+
+/*
+ * PWM Full Duty Cycle OST_PWMDCCR_FDCYCLE
+ */
+#define OST_PWMDCCR_FDCYCLE	FIELD(1, 1, 10)
+
diff --git a/arch/unicore32/include/mach/regs-pci.h b/arch/unicore32/include/mach/regs-pci.h
new file mode 100644
index 0000000..6a93416
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-pci.h
@@ -0,0 +1,94 @@
+/*
+ * PKUnity AHB-PCI Bridge Registers
+ */
+
+/*
+ * AHB/PCI fixed physical address for pci addess configuration
+ */
+/*
+ * PCICFG Bridge Base Reg.
+ */
+#define PCICFG_BRIBASE          (PKUNITY_PCICFG_BASE + 0x0000)
+/*
+ * PCICFG Address Reg.
+ */
+#define PCICFG_ADDR             (PKUNITY_PCICFG_BASE + 0x0004)
+/*
+ * PCICFG Address Reg.
+ */
+#define PCICFG_DATA             (PKUNITY_PCICFG_BASE + 0x0008)
+
+/*
+ * PCI Bridge configuration space
+ */
+#define PCIBRI_ID		(PKUNITY_PCIBRI_BASE + 0x0000)
+#define PCIBRI_CMD		(PKUNITY_PCIBRI_BASE + 0x0004)
+#define PCIBRI_CLASS		(PKUNITY_PCIBRI_BASE + 0x0008)
+#define PCIBRI_LTR		(PKUNITY_PCIBRI_BASE + 0x000C)
+#define PCIBRI_BAR0		(PKUNITY_PCIBRI_BASE + 0x0010)
+#define PCIBRI_BAR1		(PKUNITY_PCIBRI_BASE + 0x0014)
+#define PCIBRI_BAR2		(PKUNITY_PCIBRI_BASE + 0x0018)
+#define PCIBRI_BAR3		(PKUNITY_PCIBRI_BASE + 0x001C)
+#define PCIBRI_BAR4		(PKUNITY_PCIBRI_BASE + 0x0020)
+#define PCIBRI_BAR5		(PKUNITY_PCIBRI_BASE + 0x0024)
+
+#define PCIBRI_PCICTL0		(PKUNITY_PCIBRI_BASE + 0x0100)
+#define PCIBRI_PCIBAR0		(PKUNITY_PCIBRI_BASE + 0x0104)
+#define PCIBRI_PCIAMR0		(PKUNITY_PCIBRI_BASE + 0x0108)
+#define PCIBRI_PCITAR0		(PKUNITY_PCIBRI_BASE + 0x010C)
+#define PCIBRI_PCICTL1		(PKUNITY_PCIBRI_BASE + 0x0110)
+#define PCIBRI_PCIBAR1		(PKUNITY_PCIBRI_BASE + 0x0114)
+#define PCIBRI_PCIAMR1		(PKUNITY_PCIBRI_BASE + 0x0118)
+#define PCIBRI_PCITAR1		(PKUNITY_PCIBRI_BASE + 0x011C)
+#define PCIBRI_PCICTL2		(PKUNITY_PCIBRI_BASE + 0x0120)
+#define PCIBRI_PCIBAR2		(PKUNITY_PCIBRI_BASE + 0x0124)
+#define PCIBRI_PCIAMR2		(PKUNITY_PCIBRI_BASE + 0x0128)
+#define PCIBRI_PCITAR2		(PKUNITY_PCIBRI_BASE + 0x012C)
+#define PCIBRI_PCICTL3		(PKUNITY_PCIBRI_BASE + 0x0130)
+#define PCIBRI_PCIBAR3		(PKUNITY_PCIBRI_BASE + 0x0134)
+#define PCIBRI_PCIAMR3		(PKUNITY_PCIBRI_BASE + 0x0138)
+#define PCIBRI_PCITAR3		(PKUNITY_PCIBRI_BASE + 0x013C)
+#define PCIBRI_PCICTL4		(PKUNITY_PCIBRI_BASE + 0x0140)
+#define PCIBRI_PCIBAR4		(PKUNITY_PCIBRI_BASE + 0x0144)
+#define PCIBRI_PCIAMR4		(PKUNITY_PCIBRI_BASE + 0x0148)
+#define PCIBRI_PCITAR4		(PKUNITY_PCIBRI_BASE + 0x014C)
+#define PCIBRI_PCICTL5		(PKUNITY_PCIBRI_BASE + 0x0150)
+#define PCIBRI_PCIBAR5		(PKUNITY_PCIBRI_BASE + 0x0154)
+#define PCIBRI_PCIAMR5		(PKUNITY_PCIBRI_BASE + 0x0158)
+#define PCIBRI_PCITAR5		(PKUNITY_PCIBRI_BASE + 0x015C)
+
+#define PCIBRI_AHBCTL0		(PKUNITY_PCIBRI_BASE + 0x0180)
+#define PCIBRI_AHBBAR0		(PKUNITY_PCIBRI_BASE + 0x0184)
+#define PCIBRI_AHBAMR0		(PKUNITY_PCIBRI_BASE + 0x0188)
+#define PCIBRI_AHBTAR0		(PKUNITY_PCIBRI_BASE + 0x018C)
+#define PCIBRI_AHBCTL1		(PKUNITY_PCIBRI_BASE + 0x0190)
+#define PCIBRI_AHBBAR1		(PKUNITY_PCIBRI_BASE + 0x0194)
+#define PCIBRI_AHBAMR1		(PKUNITY_PCIBRI_BASE + 0x0198)
+#define PCIBRI_AHBTAR1		(PKUNITY_PCIBRI_BASE + 0x019C)
+#define PCIBRI_AHBCTL2		(PKUNITY_PCIBRI_BASE + 0x01A0)
+#define PCIBRI_AHBBAR2		(PKUNITY_PCIBRI_BASE + 0x01A4)
+#define PCIBRI_AHBAMR2		(PKUNITY_PCIBRI_BASE + 0x01A8)
+#define PCIBRI_AHBTAR2		(PKUNITY_PCIBRI_BASE + 0x01AC)
+#define PCIBRI_AHBCTL3		(PKUNITY_PCIBRI_BASE + 0x01B0)
+#define PCIBRI_AHBBAR3		(PKUNITY_PCIBRI_BASE + 0x01B4)
+#define PCIBRI_AHBAMR3		(PKUNITY_PCIBRI_BASE + 0x01B8)
+#define PCIBRI_AHBTAR3		(PKUNITY_PCIBRI_BASE + 0x01BC)
+#define PCIBRI_AHBCTL4		(PKUNITY_PCIBRI_BASE + 0x01C0)
+#define PCIBRI_AHBBAR4		(PKUNITY_PCIBRI_BASE + 0x01C4)
+#define PCIBRI_AHBAMR4		(PKUNITY_PCIBRI_BASE + 0x01C8)
+#define PCIBRI_AHBTAR4		(PKUNITY_PCIBRI_BASE + 0x01CC)
+#define PCIBRI_AHBCTL5		(PKUNITY_PCIBRI_BASE + 0x01D0)
+#define PCIBRI_AHBBAR5		(PKUNITY_PCIBRI_BASE + 0x01D4)
+#define PCIBRI_AHBAMR5		(PKUNITY_PCIBRI_BASE + 0x01D8)
+#define PCIBRI_AHBTAR5		(PKUNITY_PCIBRI_BASE + 0x01DC)
+
+#define PCIBRI_CTLx_AT          FIELD(1, 1, 2)
+#define PCIBRI_CTLx_PREF        FIELD(1, 1, 1)
+#define PCIBRI_CTLx_MRL         FIELD(1, 1, 0)
+
+#define PCIBRI_BARx_ADDR        FIELD(0xFFFFFFFC, 30, 2)
+#define PCIBRI_BARx_IO          FIELD(1, 1, 0)
+#define PCIBRI_BARx_MEM         FIELD(0, 1, 0)
+
+#define PCIBRI_CMD_IO           FIELD(1, 1, 0)
+#define PCIBRI_CMD_MEM          FIELD(1, 1, 1)
diff --git a/arch/unicore32/include/mach/regs-pm.h b/arch/unicore32/include/mach/regs-pm.h
new file mode 100644
index 0000000..854844a
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-pm.h
@@ -0,0 +1,126 @@
+/*
+ * PKUNITY Power Manager (PM) Registers
+ */
+/*
+ * PM Control Reg PM_PMCR
+ */
+#define PM_PMCR                 (PKUNITY_PM_BASE + 0x0000)
+/*
+ * PM General Conf. Reg PM_PGCR
+ */
+#define PM_PGCR                 (PKUNITY_PM_BASE + 0x0004)
+/*
+ * PM PLL Conf. Reg PM_PPCR
+ */
+#define PM_PPCR                 (PKUNITY_PM_BASE + 0x0008)
+/*
+ * PM Wakeup Enable Reg PM_PWER
+ */
+#define PM_PWER                 (PKUNITY_PM_BASE + 0x000C)
+/*
+ * PM GPIO Sleep Status Reg PM_PGSR
+ */
+#define PM_PGSR                 (PKUNITY_PM_BASE + 0x0010)
+/*
+ * PM Clock Gate Reg PM_PCGR
+ */
+#define PM_PCGR                 (PKUNITY_PM_BASE + 0x0014)
+/*
+ * PM SYS PLL Conf. Reg PM_PLLSYSCFG
+ */
+#define PM_PLLSYSCFG            (PKUNITY_PM_BASE + 0x0018)
+/*
+ * PM DDR PLL Conf. Reg PM_PLLDDRCFG
+ */
+#define PM_PLLDDRCFG            (PKUNITY_PM_BASE + 0x001C)
+/*
+ * PM VGA PLL Conf. Reg PM_PLLVGACFG
+ */
+#define PM_PLLVGACFG            (PKUNITY_PM_BASE + 0x0020)
+/*
+ * PM Div Conf. Reg PM_DIVCFG
+ */
+#define PM_DIVCFG               (PKUNITY_PM_BASE + 0x0024)
+/*
+ * PM SYS PLL Status Reg PM_PLLSYSSTATUS
+ */
+#define PM_PLLSYSSTATUS         (PKUNITY_PM_BASE + 0x0028)
+/*
+ * PM DDR PLL Status Reg PM_PLLDDRSTATUS
+ */
+#define PM_PLLDDRSTATUS         (PKUNITY_PM_BASE + 0x002C)
+/*
+ * PM VGA PLL Status Reg PM_PLLVGASTATUS
+ */
+#define PM_PLLVGASTATUS         (PKUNITY_PM_BASE + 0x0030)
+/*
+ * PM Div Status Reg PM_DIVSTATUS
+ */
+#define PM_DIVSTATUS            (PKUNITY_PM_BASE + 0x0034)
+/*
+ * PM Software Reset Reg PM_SWRESET
+ */
+#define PM_SWRESET              (PKUNITY_PM_BASE + 0x0038)
+/*
+ * PM DDR2 PAD Start Reg PM_DDR2START
+ */
+#define PM_DDR2START            (PKUNITY_PM_BASE + 0x003C)
+/*
+ * PM DDR2 PAD Status Reg PM_DDR2CAL0
+ */
+#define PM_DDR2CAL0             (PKUNITY_PM_BASE + 0x0040)
+/*
+ * PM PLL DFC Done Reg PM_PLLDFCDONE
+ */
+#define PM_PLLDFCDONE           (PKUNITY_PM_BASE + 0x0044)
+
+#define PM_PMCR_SFB             FIELD(1, 1, 0)
+#define PM_PMCR_IFB             FIELD(1, 1, 1)
+#define PM_PMCR_CFBSYS          FIELD(1, 1, 2)
+#define PM_PMCR_CFBDDR          FIELD(1, 1, 3)
+#define PM_PMCR_CFBVGA          FIELD(1, 1, 4)
+#define PM_PMCR_CFBDIVBCLK      FIELD(1, 1, 5)
+
+/*
+ * GPIO 8~27 wake-up enable PM_PWER_GPIOHIGH
+ */
+#define PM_PWER_GPIOHIGH        FIELD(1, 1, 8)
+/*
+ * RTC alarm wake-up enable PM_PWER_RTC
+ */
+#define PM_PWER_RTC             FIELD(1, 1, 31)
+
+#define PM_PCGR_BCLK64DDR	FIELD(1, 1, 0)
+#define PM_PCGR_BCLK64VGA	FIELD(1, 1, 1)
+#define PM_PCGR_BCLKDDR		FIELD(1, 1, 2)
+#define PM_PCGR_BCLKPCI		FIELD(1, 1, 4)
+#define PM_PCGR_BCLKDMAC	FIELD(1, 1, 5)
+#define PM_PCGR_BCLKUMAL	FIELD(1, 1, 6)
+#define PM_PCGR_BCLKUSB		FIELD(1, 1, 7)
+#define PM_PCGR_BCLKMME		FIELD(1, 1, 10)
+#define PM_PCGR_BCLKNAND	FIELD(1, 1, 11)
+#define PM_PCGR_BCLKH264E	FIELD(1, 1, 12)
+#define PM_PCGR_BCLKVGA		FIELD(1, 1, 13)
+#define PM_PCGR_BCLKH264D	FIELD(1, 1, 14)
+#define PM_PCGR_VECLK		FIELD(1, 1, 15)
+#define PM_PCGR_HECLK		FIELD(1, 1, 16)
+#define PM_PCGR_HDCLK		FIELD(1, 1, 17)
+#define PM_PCGR_NANDCLK		FIELD(1, 1, 18)
+#define PM_PCGR_GECLK		FIELD(1, 1, 19)
+#define PM_PCGR_VGACLK          FIELD(1, 1, 20)
+#define PM_PCGR_PCICLK		FIELD(1, 1, 21)
+#define PM_PCGR_SATACLK		FIELD(1, 1, 25)
+
+/*
+ * [23:20]PM_DIVCFG_VGACLK(v)
+ */
+#define PM_DIVCFG_VGACLK_MASK   FMASK(4, 20)
+#define PM_DIVCFG_VGACLK(v)	FIELD((v), 4, 20)
+
+#define PM_SWRESET_USB          FIELD(1, 1, 6)
+#define PM_SWRESET_VGADIV       FIELD(1, 1, 26)
+#define PM_SWRESET_GEDIV        FIELD(1, 1, 27)
+
+#define PM_PLLDFCDONE_SYSDFC    FIELD(1, 1, 0)
+#define PM_PLLDFCDONE_DDRDFC    FIELD(1, 1, 1)
+#define PM_PLLDFCDONE_VGADFC    FIELD(1, 1, 2)
diff --git a/arch/unicore32/include/mach/regs-ps2.h b/arch/unicore32/include/mach/regs-ps2.h
new file mode 100644
index 0000000..17d4e6d
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-ps2.h
@@ -0,0 +1,20 @@
+/*
+ * PKUnity PS2 Controller Registers
+ */
+/*
+ * the same as I8042_DATA_REG PS2_DATA
+ */
+#define PS2_DATA	(PKUNITY_PS2_BASE + 0x0060)
+/*
+ * the same as I8042_COMMAND_REG PS2_COMMAND
+ */
+#define PS2_COMMAND	(PKUNITY_PS2_BASE + 0x0064)
+/*
+ * the same as I8042_STATUS_REG PS2_STATUS
+ */
+#define PS2_STATUS	(PKUNITY_PS2_BASE + 0x0064)
+/*
+ * counter reg PS2_CNT
+ */
+#define PS2_CNT		(PKUNITY_PS2_BASE + 0x0068)
+
diff --git a/arch/unicore32/include/mach/regs-resetc.h b/arch/unicore32/include/mach/regs-resetc.h
new file mode 100644
index 0000000..39900cf
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-resetc.h
@@ -0,0 +1,34 @@
+/*
+ * PKUnity Reset Controller (RC) Registers
+ */
+/*
+ * Software Reset Register
+ */
+#define RESETC_SWRR	(PKUNITY_RESETC_BASE + 0x0000)
+/*
+ * Reset Status Register
+ */
+#define RESETC_RSSR	(PKUNITY_RESETC_BASE + 0x0004)
+
+/*
+ * Software Reset Bit
+ */
+#define RESETC_SWRR_SRB		FIELD(1, 1, 0)
+
+/*
+ * Hardware Reset
+ */
+#define RESETC_RSSR_HWR		FIELD(1, 1, 0)
+/*
+ * Software Reset
+ */
+#define RESETC_RSSR_SWR		FIELD(1, 1, 1)
+/*
+ * Watchdog Reset
+ */
+#define RESETC_RSSR_WDR		FIELD(1, 1, 2)
+/*
+ * Sleep Mode Reset
+ */
+#define RESETC_RSSR_SMR		FIELD(1, 1, 3)
+
diff --git a/arch/unicore32/include/mach/regs-rtc.h b/arch/unicore32/include/mach/regs-rtc.h
new file mode 100644
index 0000000..e94ca19
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-rtc.h
@@ -0,0 +1,37 @@
+/*
+ * PKUnity Real-Time Clock (RTC) control registers
+ */
+/*
+ * RTC Alarm Reg RTC_RTAR
+ */
+#define RTC_RTAR	(PKUNITY_RTC_BASE + 0x0000)
+/*
+ * RTC Count Reg RTC_RCNR
+ */
+#define RTC_RCNR	(PKUNITY_RTC_BASE + 0x0004)
+/*
+ * RTC Trim Reg RTC_RTTR
+ */
+#define RTC_RTTR	(PKUNITY_RTC_BASE + 0x0008)
+/*
+ * RTC Status Reg RTC_RTSR
+ */
+#define RTC_RTSR	(PKUNITY_RTC_BASE + 0x0010)
+
+/*
+ * ALarm detected RTC_RTSR_AL
+ */
+#define RTC_RTSR_AL		FIELD(1, 1, 0)
+/*
+ * 1 Hz clock detected RTC_RTSR_HZ
+ */
+#define RTC_RTSR_HZ		FIELD(1, 1, 1)
+/*
+ * ALarm interrupt Enable RTC_RTSR_ALE
+ */
+#define RTC_RTSR_ALE		FIELD(1, 1, 2)
+/*
+ * 1 Hz clock interrupt Enable RTC_RTSR_HZE
+ */
+#define RTC_RTSR_HZE		FIELD(1, 1, 3)
+
diff --git a/arch/unicore32/include/mach/regs-sdc.h b/arch/unicore32/include/mach/regs-sdc.h
new file mode 100644
index 0000000..1303ecf
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-sdc.h
@@ -0,0 +1,156 @@
+/*
+ * PKUnity Multi-Media Card and Security Digital Card (MMC/SD) Registers
+ */
+/*
+ * Clock Control Reg SDC_CCR
+ */
+#define SDC_CCR		(PKUNITY_SDC_BASE + 0x0000)
+/*
+ * Software Reset Reg SDC_SRR
+ */
+#define SDC_SRR		(PKUNITY_SDC_BASE + 0x0004)
+/*
+ * Argument Reg SDC_ARGUMENT
+ */
+#define SDC_ARGUMENT	(PKUNITY_SDC_BASE + 0x0008)
+/*
+ * Command Reg SDC_COMMAND
+ */
+#define SDC_COMMAND	(PKUNITY_SDC_BASE + 0x000C)
+/*
+ * Block Size Reg SDC_BLOCKSIZE
+ */
+#define SDC_BLOCKSIZE	(PKUNITY_SDC_BASE + 0x0010)
+/*
+ * Block Cound Reg SDC_BLOCKCOUNT
+ */
+#define SDC_BLOCKCOUNT	(PKUNITY_SDC_BASE + 0x0014)
+/*
+ * Transfer Mode Reg SDC_TMR
+ */
+#define SDC_TMR		(PKUNITY_SDC_BASE + 0x0018)
+/*
+ * Response Reg. 0 SDC_RES0
+ */
+#define SDC_RES0	(PKUNITY_SDC_BASE + 0x001C)
+/*
+ * Response Reg. 1 SDC_RES1
+ */
+#define SDC_RES1	(PKUNITY_SDC_BASE + 0x0020)
+/*
+ * Response Reg. 2 SDC_RES2
+ */
+#define SDC_RES2	(PKUNITY_SDC_BASE + 0x0024)
+/*
+ * Response Reg. 3 SDC_RES3
+ */
+#define SDC_RES3	(PKUNITY_SDC_BASE + 0x0028)
+/*
+ * Read Timeout Control Reg SDC_RTCR
+ */
+#define SDC_RTCR	(PKUNITY_SDC_BASE + 0x002C)
+/*
+ * Interrupt Status Reg SDC_ISR
+ */
+#define SDC_ISR		(PKUNITY_SDC_BASE + 0x0030)
+/*
+ * Interrupt Status Mask Reg SDC_ISMR
+ */
+#define SDC_ISMR	(PKUNITY_SDC_BASE + 0x0034)
+/*
+ * RX FIFO SDC_RXFIFO
+ */
+#define SDC_RXFIFO	(PKUNITY_SDC_BASE + 0x0038)
+/*
+ * TX FIFO SDC_TXFIFO
+ */
+#define SDC_TXFIFO	(PKUNITY_SDC_BASE + 0x003C)
+
+/*
+ * SD Clock Enable SDC_CCR_CLKEN
+ */
+#define SDC_CCR_CLKEN			FIELD(1, 1, 2)
+/*
+ * [15:8] SDC_CCR_PDIV(v)
+ */
+#define SDC_CCR_PDIV(v)			FIELD((v), 8, 8)
+
+/*
+ * Software reset enable SDC_SRR_ENABLE
+ */
+#define SDC_SRR_ENABLE			FIELD(0, 1, 0)
+/*
+ * Software reset disable SDC_SRR_DISABLE
+ */
+#define SDC_SRR_DISABLE			FIELD(1, 1, 0)
+
+/*
+ * Response type SDC_COMMAND_RESTYPE_MASK
+ */
+#define SDC_COMMAND_RESTYPE_MASK	FMASK(2, 0)
+/*
+ * No response SDC_COMMAND_RESTYPE_NONE
+ */
+#define SDC_COMMAND_RESTYPE_NONE	FIELD(0, 2, 0)
+/*
+ * 136-bit long response SDC_COMMAND_RESTYPE_LONG
+ */
+#define SDC_COMMAND_RESTYPE_LONG	FIELD(1, 2, 0)
+/*
+ * 48-bit short response SDC_COMMAND_RESTYPE_SHORT
+ */
+#define SDC_COMMAND_RESTYPE_SHORT	FIELD(2, 2, 0)
+/*
+ * 48-bit short and test if busy response SDC_COMMAND_RESTYPE_SHORTBUSY
+ */
+#define SDC_COMMAND_RESTYPE_SHORTBUSY	FIELD(3, 2, 0)
+/*
+ * data ready SDC_COMMAND_DATAREADY
+ */
+#define SDC_COMMAND_DATAREADY		FIELD(1, 1, 2)
+#define SDC_COMMAND_CMDEN		FIELD(1, 1, 3)
+/*
+ * [10:5] SDC_COMMAND_CMDINDEX(v)
+ */
+#define SDC_COMMAND_CMDINDEX(v)		FIELD((v), 6, 5)
+
+/*
+ * [10:0] SDC_BLOCKSIZE_BSMASK(v)
+ */
+#define SDC_BLOCKSIZE_BSMASK(v)		FIELD((v), 11, 0)
+/*
+ * [11:0] SDC_BLOCKCOUNT_BCMASK(v)
+ */
+#define SDC_BLOCKCOUNT_BCMASK(v)	FIELD((v), 12, 0)
+
+/*
+ * Data Width 1bit SDC_TMR_WTH_1BIT
+ */
+#define SDC_TMR_WTH_1BIT		FIELD(0, 1, 0)
+/*
+ * Data Width 4bit SDC_TMR_WTH_4BIT
+ */
+#define SDC_TMR_WTH_4BIT		FIELD(1, 1, 0)
+/*
+ * Read SDC_TMR_DIR_READ
+ */
+#define SDC_TMR_DIR_READ		FIELD(0, 1, 1)
+/*
+ * Write SDC_TMR_DIR_WRITE
+ */
+#define SDC_TMR_DIR_WRITE		FIELD(1, 1, 1)
+
+#define SDC_IR_MASK			FMASK(13, 0)
+#define SDC_IR_RESTIMEOUT		FIELD(1, 1, 0)
+#define SDC_IR_WRITECRC			FIELD(1, 1, 1)
+#define SDC_IR_READCRC			FIELD(1, 1, 2)
+#define SDC_IR_TXFIFOREAD		FIELD(1, 1, 3)
+#define SDC_IR_RXFIFOWRITE		FIELD(1, 1, 4)
+#define SDC_IR_READTIMEOUT		FIELD(1, 1, 5)
+#define SDC_IR_DATACOMPLETE		FIELD(1, 1, 6)
+#define SDC_IR_CMDCOMPLETE		FIELD(1, 1, 7)
+#define SDC_IR_RXFIFOFULL		FIELD(1, 1, 8)
+#define SDC_IR_RXFIFOEMPTY		FIELD(1, 1, 9)
+#define SDC_IR_TXFIFOFULL		FIELD(1, 1, 10)
+#define SDC_IR_TXFIFOEMPTY		FIELD(1, 1, 11)
+#define SDC_IR_ENDCMDWITHRES		FIELD(1, 1, 12)
diff --git a/arch/unicore32/include/mach/regs-spi.h b/arch/unicore32/include/mach/regs-spi.h
new file mode 100644
index 0000000..de16895
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-spi.h
@@ -0,0 +1,98 @@
+/*
+ * PKUnity Serial Peripheral Interface (SPI) Registers
+ */
+/*
+ * Control reg. 0 SPI_CR0
+ */
+#define SPI_CR0		(PKUNITY_SPI_BASE + 0x0000)
+/*
+ * Control reg. 1 SPI_CR1
+ */
+#define SPI_CR1		(PKUNITY_SPI_BASE + 0x0004)
+/*
+ * Enable reg SPI_SSIENR
+ */
+#define SPI_SSIENR	(PKUNITY_SPI_BASE + 0x0008)
+/*
+ * Status reg SPI_SR
+ */
+#define SPI_SR		(PKUNITY_SPI_BASE + 0x0028)
+/*
+ * Interrupt Mask reg SPI_IMR
+ */
+#define SPI_IMR		(PKUNITY_SPI_BASE + 0x002C)
+/*
+ * Interrupt Status reg SPI_ISR
+ */
+#define SPI_ISR		(PKUNITY_SPI_BASE + 0x0030)
+
+/*
+ * Enable SPI Controller SPI_SSIENR_EN
+ */
+#define SPI_SSIENR_EN		FIELD(1, 1, 0)
+
+/*
+ * SPI Busy SPI_SR_BUSY
+ */
+#define SPI_SR_BUSY		FIELD(1, 1, 0)
+/*
+ * Transmit FIFO Not Full SPI_SR_TFNF
+ */
+#define SPI_SR_TFNF		FIELD(1, 1, 1)
+/*
+ * Transmit FIFO Empty SPI_SR_TFE
+ */
+#define SPI_SR_TFE		FIELD(1, 1, 2)
+/*
+ * Receive FIFO Not Empty SPI_SR_RFNE
+ */
+#define SPI_SR_RFNE		FIELD(1, 1, 3)
+/*
+ * Receive FIFO Full SPI_SR_RFF
+ */
+#define SPI_SR_RFF		FIELD(1, 1, 4)
+
+/*
+ * Trans. FIFO Empty Interrupt Status SPI_ISR_TXEIS
+ */
+#define SPI_ISR_TXEIS		FIELD(1, 1, 0)
+/*
+ * Trans. FIFO Overflow Interrupt Status SPI_ISR_TXOIS
+ */
+#define SPI_ISR_TXOIS		FIELD(1, 1, 1)
+/*
+ * Receiv. FIFO Underflow Interrupt Status SPI_ISR_RXUIS
+ */
+#define SPI_ISR_RXUIS		FIELD(1, 1, 2)
+/*
+ * Receiv. FIFO Overflow Interrupt Status SPI_ISR_RXOIS
+ */
+#define SPI_ISR_RXOIS		FIELD(1, 1, 3)
+/*
+ * Receiv. FIFO Full Interrupt Status SPI_ISR_RXFIS
+ */
+#define SPI_ISR_RXFIS		FIELD(1, 1, 4)
+#define SPI_ISR_MSTIS		FIELD(1, 1, 5)
+
+/*
+ * Trans. FIFO Empty Interrupt Mask SPI_IMR_TXEIM
+ */
+#define SPI_IMR_TXEIM		FIELD(1, 1, 0)
+/*
+ * Trans. FIFO Overflow Interrupt Mask SPI_IMR_TXOIM
+ */
+#define SPI_IMR_TXOIM		FIELD(1, 1, 1)
+/*
+ * Receiv. FIFO Underflow Interrupt Mask SPI_IMR_RXUIM
+ */
+#define SPI_IMR_RXUIM		FIELD(1, 1, 2)
+/*
+ * Receiv. FIFO Overflow Interrupt Mask SPI_IMR_RXOIM
+ */
+#define SPI_IMR_RXOIM		FIELD(1, 1, 3)
+/*
+ * Receiv. FIFO Full Interrupt Mask SPI_IMR_RXFIM
+ */
+#define SPI_IMR_RXFIM		FIELD(1, 1, 4)
+#define SPI_IMR_MSTIM		FIELD(1, 1, 5)
+
diff --git a/arch/unicore32/include/mach/regs-uart.h b/arch/unicore32/include/mach/regs-uart.h
new file mode 100644
index 0000000..9fa6b19
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-uart.h
@@ -0,0 +1,3 @@
+/*
+ * PKUnity Universal Asynchronous Receiver/Transmitter (UART) Registers
+ */
diff --git a/arch/unicore32/include/mach/regs-umal.h b/arch/unicore32/include/mach/regs-umal.h
new file mode 100644
index 0000000..885bb62
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-umal.h
@@ -0,0 +1,229 @@
+/*
+ * PKUnity Ultra Media Access Layer (UMAL) Ethernet MAC Registers
+ */
+
+/* MAC module of UMAL */
+/* UMAL's MAC module includes G/MII interface, several additional PHY
+ * interfaces, and MAC control sub-layer, which provides support for control
+ * frames (e.g. PAUSE frames).
+ */
+/*
+ * TX/RX reset and control UMAL_CFG1
+ */
+#define UMAL_CFG1		(PKUNITY_UMAL_BASE + 0x0000)
+/*
+ * MAC interface mode control UMAL_CFG2
+ */
+#define UMAL_CFG2		(PKUNITY_UMAL_BASE + 0x0004)
+/*
+ * Inter Packet/Frame Gap UMAL_IPGIFG
+ */
+#define UMAL_IPGIFG		(PKUNITY_UMAL_BASE + 0x0008)
+/*
+ * Collision retry or backoff UMAL_HALFDUPLEX
+ */
+#define UMAL_HALFDUPLEX		(PKUNITY_UMAL_BASE + 0x000c)
+/*
+ * Maximum Frame Length UMAL_MAXFRAME
+ */
+#define UMAL_MAXFRAME		(PKUNITY_UMAL_BASE + 0x0010)
+/*
+ * Test Regsiter UMAL_TESTREG
+ */
+#define UMAL_TESTREG		(PKUNITY_UMAL_BASE + 0x001c)
+/*
+ * MII Management Configure UMAL_MIICFG
+ */
+#define UMAL_MIICFG		(PKUNITY_UMAL_BASE + 0x0020)
+/*
+ * MII Management Command UMAL_MIICMD
+ */
+#define UMAL_MIICMD		(PKUNITY_UMAL_BASE + 0x0024)
+/*
+ * MII Management Address UMAL_MIIADDR
+ */
+#define UMAL_MIIADDR		(PKUNITY_UMAL_BASE + 0x0028)
+/*
+ * MII Management Control UMAL_MIICTRL
+ */
+#define UMAL_MIICTRL		(PKUNITY_UMAL_BASE + 0x002c)
+/*
+ * MII Management Status UMAL_MIISTATUS
+ */
+#define UMAL_MIISTATUS		(PKUNITY_UMAL_BASE + 0x0030)
+/*
+ * MII Managment Indicator UMAL_MIIIDCT
+ */
+#define UMAL_MIIIDCT		(PKUNITY_UMAL_BASE + 0x0034)
+/*
+ * Interface Control UMAL_IFCTRL
+ */
+#define UMAL_IFCTRL		(PKUNITY_UMAL_BASE + 0x0038)
+/*
+ * Interface Status UMAL_IFSTATUS
+ */
+#define UMAL_IFSTATUS		(PKUNITY_UMAL_BASE + 0x003c)
+/*
+ * MAC address (high 4 bytes) UMAL_STADDR1
+ */
+#define UMAL_STADDR1		(PKUNITY_UMAL_BASE + 0x0040)
+/*
+ * MAC address (low 2 bytes) UMAL_STADDR2
+ */
+#define UMAL_STADDR2		(PKUNITY_UMAL_BASE + 0x0044)
+
+/* FIFO MODULE OF UMAL */
+/* UMAL's FIFO module provides data queuing for increased system level
+ * throughput
+ */
+#define UMAL_FIFOCFG0		(PKUNITY_UMAL_BASE + 0x0048)
+#define UMAL_FIFOCFG1		(PKUNITY_UMAL_BASE + 0x004c)
+#define UMAL_FIFOCFG2		(PKUNITY_UMAL_BASE + 0x0050)
+#define UMAL_FIFOCFG3		(PKUNITY_UMAL_BASE + 0x0054)
+#define UMAL_FIFOCFG4		(PKUNITY_UMAL_BASE + 0x0058)
+#define UMAL_FIFOCFG5		(PKUNITY_UMAL_BASE + 0x005c)
+#define UMAL_FIFORAM0		(PKUNITY_UMAL_BASE + 0x0060)
+#define UMAL_FIFORAM1		(PKUNITY_UMAL_BASE + 0x0064)
+#define UMAL_FIFORAM2		(PKUNITY_UMAL_BASE + 0x0068)
+#define UMAL_FIFORAM3		(PKUNITY_UMAL_BASE + 0x006c)
+#define UMAL_FIFORAM4		(PKUNITY_UMAL_BASE + 0x0070)
+#define UMAL_FIFORAM5		(PKUNITY_UMAL_BASE + 0x0074)
+#define UMAL_FIFORAM6		(PKUNITY_UMAL_BASE + 0x0078)
+#define UMAL_FIFORAM7		(PKUNITY_UMAL_BASE + 0x007c)
+
+/* MAHBE MODUEL OF UMAL */
+/* UMAL's MAHBE module interfaces to the host system through 32-bit AHB Master
+ * and Slave ports.Registers within the M-AHBE provide Control and Status
+ * information concerning these transfers.
+ */
+/*
+ * Transmit Control UMAL_DMATxCtrl
+ */
+#define UMAL_DMATxCtrl		(PKUNITY_UMAL_BASE + 0x0180)
+/*
+ * Pointer to TX Descripter UMAL_DMATxDescriptor
+ */
+#define UMAL_DMATxDescriptor	(PKUNITY_UMAL_BASE + 0x0184)
+/*
+ * Status of Tx Packet Transfers UMAL_DMATxStatus
+ */
+#define UMAL_DMATxStatus	(PKUNITY_UMAL_BASE + 0x0188)
+/*
+ * Receive Control UMAL_DMARxCtrl
+ */
+#define UMAL_DMARxCtrl		(PKUNITY_UMAL_BASE + 0x018c)
+/*
+ * Pointer to Rx Descriptor UMAL_DMARxDescriptor
+ */
+#define UMAL_DMARxDescriptor	(PKUNITY_UMAL_BASE + 0x0190)
+/*
+ * Status of Rx Packet Transfers UMAL_DMARxStatus
+ */
+#define UMAL_DMARxStatus	(PKUNITY_UMAL_BASE + 0x0194)
+/*
+ * Interrupt Mask UMAL_DMAIntrMask
+ */
+#define UMAL_DMAIntrMask	(PKUNITY_UMAL_BASE + 0x0198)
+/*
+ * Interrupts, read only UMAL_DMAInterrupt
+ */
+#define UMAL_DMAInterrupt	(PKUNITY_UMAL_BASE + 0x019c)
+
+/*
+ * Commands for UMAL_CFG1 register
+ */
+#define UMAL_CFG1_TXENABLE	FIELD(1, 1, 0)
+#define UMAL_CFG1_RXENABLE	FIELD(1, 1, 2)
+#define UMAL_CFG1_TXFLOWCTL	FIELD(1, 1, 4)
+#define UMAL_CFG1_RXFLOWCTL	FIELD(1, 1, 5)
+#define UMAL_CFG1_CONFLPBK	FIELD(1, 1, 8)
+#define UMAL_CFG1_RESET		FIELD(1, 1, 31)
+#define UMAL_CFG1_CONFFLCTL	(MAC_TX_FLOW_CTL | MAC_RX_FLOW_CTL)
+
+/*
+ * Commands for UMAL_CFG2 register
+ */
+#define UMAL_CFG2_FULLDUPLEX	FIELD(1, 1, 0)
+#define UMAL_CFG2_CRCENABLE	FIELD(1, 1, 1)
+#define UMAL_CFG2_PADCRC	FIELD(1, 1, 2)
+#define UMAL_CFG2_LENGTHCHECK	FIELD(1, 1, 4)
+#define UMAL_CFG2_MODEMASK	FMASK(2, 8)
+#define UMAL_CFG2_NIBBLEMODE	FIELD(1, 2, 8)
+#define UMAL_CFG2_BYTEMODE	FIELD(2, 2, 8)
+#define UMAL_CFG2_PREAMBLENMASK	FMASK(4, 12)
+#define UMAL_CFG2_DEFPREAMBLEN	FIELD(7, 4, 12)
+#define UMAL_CFG2_FD100		(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
+				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+				| UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
+#define UMAL_CFG2_FD1000	(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_BYTEMODE \
+				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+				| UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
+#define UMAL_CFG2_HD100		(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
+				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+				| UMAL_CFG2_CRCENABLE)
+
+/*
+ * Command for UMAL_IFCTRL register
+ */
+#define UMAL_IFCTRL_RESET	FIELD(1, 1, 31)
+
+/*
+ * Command for UMAL_MIICFG register
+ */
+#define UMAL_MIICFG_RESET	FIELD(1, 1, 31)
+
+/*
+ * Command for UMAL_MIICMD register
+ */
+#define UMAL_MIICMD_READ	FIELD(1, 1, 0)
+
+/*
+ * Command for UMAL_MIIIDCT register
+ */
+#define UMAL_MIIIDCT_BUSY	FIELD(1, 1, 0)
+#define UMAL_MIIIDCT_NOTVALID	FIELD(1, 1, 2)
+
+/*
+ * Commands for DMATxCtrl regesters
+ */
+#define UMAL_DMA_Enable		FIELD(1, 1, 0)
+
+/*
+ * Commands for DMARxCtrl regesters
+ */
+#define UMAL_DMAIntrMask_ENABLEHALFWORD	FIELD(1, 1, 16)
+
+/*
+ * Command for DMARxStatus
+ */
+#define CLR_RX_BUS_ERR		FIELD(1, 1, 3)
+#define CLR_RX_OVERFLOW		FIELD(1, 1, 2)
+#define CLR_RX_PKT		FIELD(1, 1, 0)
+
+/*
+ * Command for DMATxStatus
+ */
+#define CLR_TX_BUS_ERR		FIELD(1, 1, 3)
+#define CLR_TX_UNDERRUN		FIELD(1, 1, 1)
+#define CLR_TX_PKT		FIELD(1, 1, 0)
+
+/*
+ * Commands for DMAIntrMask and DMAInterrupt register
+ */
+#define INT_RX_MASK		FIELD(0xd, 4, 4)
+#define INT_TX_MASK		FIELD(0xb, 4, 0)
+
+#define INT_RX_BUS_ERR		FIELD(1, 1, 7)
+#define INT_RX_OVERFLOW		FIELD(1, 1, 6)
+#define INT_RX_PKT		FIELD(1, 1, 4)
+#define INT_TX_BUS_ERR		FIELD(1, 1, 3)
+#define INT_TX_UNDERRUN		FIELD(1, 1, 1)
+#define INT_TX_PKT		FIELD(1, 1, 0)
+
+/*
+ * MARCOS of UMAL's descriptors
+ */
+#define UMAL_DESC_PACKETSIZE_EMPTY	FIELD(1, 1, 31)
+#define UMAL_DESC_PACKETSIZE_NONEMPTY	FIELD(0, 1, 31)
+#define UMAL_DESC_PACKETSIZE_SIZEMASK	FMASK(12, 0)
+
diff --git a/arch/unicore32/include/mach/regs-unigfx.h b/arch/unicore32/include/mach/regs-unigfx.h
new file mode 100644
index 0000000..faf8b28
--- /dev/null
+++ b/arch/unicore32/include/mach/regs-unigfx.h
@@ -0,0 +1,200 @@
+/*
+ * PKUnity UNIGFX Registers
+ */
+
+#define UDE_BASE      (PKUNITY_UNIGFX_BASE + 0x1400)
+#define UGE_BASE      (PKUNITY_UNIGFX_BASE + 0x0000)
+
+/*
+ * command reg for UNIGFX DE
+ */
+/*
+ * control reg UDE_CFG
+ */
+#define UDE_CFG       (UDE_BASE + 0x0000)
+/*
+ * framebuffer start address reg UDE_FSA
+ */
+#define UDE_FSA       (UDE_BASE + 0x0004)
+/*
+ * line size reg UDE_LS
+ */
+#define UDE_LS        (UDE_BASE + 0x0008)
+/*
+ * pitch size reg UDE_PS
+ */
+#define UDE_PS        (UDE_BASE + 0x000C)
+/*
+ * horizontal active time reg UDE_HAT
+ */
+#define UDE_HAT       (UDE_BASE + 0x0010)
+/*
+ * horizontal blank time reg UDE_HBT
+ */
+#define UDE_HBT       (UDE_BASE + 0x0014)
+/*
+ * horizontal sync time reg UDE_HST
+ */
+#define UDE_HST       (UDE_BASE + 0x0018)
+/*
+ * vertival active time reg UDE_VAT
+ */
+#define UDE_VAT       (UDE_BASE + 0x001C)
+/*
+ * vertival blank time reg UDE_VBT
+ */
+#define UDE_VBT       (UDE_BASE + 0x0020)
+/*
+ * vertival sync time reg UDE_VST
+ */
+#define UDE_VST       (UDE_BASE + 0x0024)
+/*
+ * cursor position UDE_CXY
+ */
+#define UDE_CXY       (UDE_BASE + 0x0028)
+/*
+ * cursor front color UDE_CC0
+ */
+#define UDE_CC0       (UDE_BASE + 0x002C)
+/*
+ * cursor background color UDE_CC1
+ */
+#define UDE_CC1       (UDE_BASE + 0x0030)
+/*
+ * video position UDE_VXY
+ */
+#define UDE_VXY       (UDE_BASE + 0x0034)
+/*
+ * video start address reg UDE_VSA
+ */
+#define UDE_VSA       (UDE_BASE + 0x0040)
+/*
+ * video size reg UDE_VS
+ */
+#define UDE_VS        (UDE_BASE + 0x004C)
+
+/*
+ * command reg for UNIGFX GE
+ */
+/*
+ * src xy reg UGE_SRCXY
+ */
+#define UGE_SRCXY     (UGE_BASE + 0x0000)
+/*
+ * dst xy reg UGE_DSTXY
+ */
+#define UGE_DSTXY     (UGE_BASE + 0x0004)
+/*
+ * pitch reg UGE_PITCH
+ */
+#define UGE_PITCH     (UGE_BASE + 0x0008)
+/*
+ * src start reg UGE_SRCSTART
+ */
+#define UGE_SRCSTART  (UGE_BASE + 0x000C)
+/*
+ * dst start reg UGE_DSTSTART
+ */
+#define UGE_DSTSTART  (UGE_BASE + 0x0010)
+/*
+ * width height reg UGE_WIDHEIGHT
+ */
+#define UGE_WIDHEIGHT (UGE_BASE + 0x0014)
+/*
+ * rop alpah reg UGE_ROPALPHA
+ */
+#define UGE_ROPALPHA  (UGE_BASE + 0x0018)
+/*
+ * front color UGE_FCOLOR
+ */
+#define UGE_FCOLOR    (UGE_BASE + 0x001C)
+/*
+ * background color UGE_BCOLOR
+ */
+#define UGE_BCOLOR    (UGE_BASE + 0x0020)
+/*
+ * src color key for high value UGE_SCH
+ */
+#define UGE_SCH       (UGE_BASE + 0x0024)
+/*
+ * dst color key for high value UGE_DCH
+ */
+#define UGE_DCH       (UGE_BASE + 0x0028)
+/*
+ * src color key for low value UGE_SCL
+ */
+#define UGE_SCL       (UGE_BASE + 0x002C)
+/*
+ * dst color key for low value UGE_DCL
+ */
+#define UGE_DCL       (UGE_BASE + 0x0030)
+/*
+ * clip 0 reg UGE_CLIP0
+ */
+#define UGE_CLIP0     (UGE_BASE + 0x0034)
+/*
+ * clip 1 reg UGE_CLIP1
+ */
+#define UGE_CLIP1     (UGE_BASE + 0x0038)
+/*
+ * command reg UGE_COMMAND
+ */
+#define UGE_COMMAND   (UGE_BASE + 0x003C)
+/*
+ * pattern 0 UGE_P0
+ */
+#define UGE_P0        (UGE_BASE + 0x0040)
+#define UGE_P1        (UGE_BASE + 0x0044)
+#define UGE_P2        (UGE_BASE + 0x0048)
+#define UGE_P3        (UGE_BASE + 0x004C)
+#define UGE_P4        (UGE_BASE + 0x0050)
+#define UGE_P5        (UGE_BASE + 0x0054)
+#define UGE_P6        (UGE_BASE + 0x0058)
+#define UGE_P7        (UGE_BASE + 0x005C)
+#define UGE_P8        (UGE_BASE + 0x0060)
+#define UGE_P9        (UGE_BASE + 0x0064)
+#define UGE_P10       (UGE_BASE + 0x0068)
+#define UGE_P11       (UGE_BASE + 0x006C)
+#define UGE_P12       (UGE_BASE + 0x0070)
+#define UGE_P13       (UGE_BASE + 0x0074)
+#define UGE_P14       (UGE_BASE + 0x0078)
+#define UGE_P15       (UGE_BASE + 0x007C)
+#define UGE_P16       (UGE_BASE + 0x0080)
+#define UGE_P17       (UGE_BASE + 0x0084)
+#define UGE_P18       (UGE_BASE + 0x0088)
+#define UGE_P19       (UGE_BASE + 0x008C)
+#define UGE_P20       (UGE_BASE + 0x0090)
+#define UGE_P21       (UGE_BASE + 0x0094)
+#define UGE_P22       (UGE_BASE + 0x0098)
+#define UGE_P23       (UGE_BASE + 0x009C)
+#define UGE_P24       (UGE_BASE + 0x00A0)
+#define UGE_P25       (UGE_BASE + 0x00A4)
+#define UGE_P26       (UGE_BASE + 0x00A8)
+#define UGE_P27       (UGE_BASE + 0x00AC)
+#define UGE_P28       (UGE_BASE + 0x00B0)
+#define UGE_P29       (UGE_BASE + 0x00B4)
+#define UGE_P30       (UGE_BASE + 0x00B8)
+#define UGE_P31       (UGE_BASE + 0x00BC)
+
+#define UDE_CFG_DST_MASK	FMASK(2, 8)
+#define UDE_CFG_DST8            FIELD(0x0, 2, 8)
+#define UDE_CFG_DST16           FIELD(0x1, 2, 8)
+#define UDE_CFG_DST24           FIELD(0x2, 2, 8)
+#define UDE_CFG_DST32           FIELD(0x3, 2, 8)
+
+/*
+ * GDEN enable UDE_CFG_GDEN_ENABLE
+ */
+#define UDE_CFG_GDEN_ENABLE     FIELD(1, 1, 3)
+/*
+ * VDEN enable UDE_CFG_VDEN_ENABLE
+ */
+#define UDE_CFG_VDEN_ENABLE     FIELD(1, 1, 4)
+/*
+ * CDEN enable UDE_CFG_CDEN_ENABLE
+ */
+#define UDE_CFG_CDEN_ENABLE     FIELD(1, 1, 5)
+/*
+ * TIMEUP enable UDE_CFG_TIMEUP_ENABLE
+ */
+#define UDE_CFG_TIMEUP_ENABLE   FIELD(1, 1, 6)
diff --git a/arch/unicore32/include/mach/uncompress.h b/arch/unicore32/include/mach/uncompress.h
new file mode 100644
index 0000000..142d3e7
--- /dev/null
+++ b/arch/unicore32/include/mach/uncompress.h
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/unicore32/include/mach/uncompress.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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_PUV3_UNCOMPRESS_H__
+#define __MACH_PUV3_UNCOMPRESS_H__
+
+#include "hardware.h"
+#include "ocd.h"
+
+extern char input_data[];
+extern char input_data_end[];
+
+static void arch_decomp_puts(const char *ptr)
+{
+	char c;
+
+	while ((c = *ptr++) != '\0') {
+		if (c == '\n')
+			putc('\r');
+		putc(c);
+	}
+}
+#define ARCH_HAVE_DECOMP_PUTS
+
+#endif /* __MACH_PUV3_UNCOMPRESS_H__ */
diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile
new file mode 100644
index 0000000..ec23a2f
--- /dev/null
+++ b/arch/unicore32/kernel/Makefile
@@ -0,0 +1,33 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+obj-y				:= dma.o elf.o entry.o process.o ptrace.o
+obj-y				+= setup.o signal.o sys.o stacktrace.o traps.o
+
+obj-$(CONFIG_MODULES)		+= ksyms.o module.o
+obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+
+obj-$(CONFIG_CPU_FREQ)		+= cpu-ucv2.o
+obj-$(CONFIG_UNICORE_FPU_F64)	+= fpu-ucf64.o
+
+# obj-y for architecture PKUnity v3
+obj-$(CONFIG_ARCH_PUV3)		+= clock.o irq.o time.o
+
+obj-$(CONFIG_PUV3_GPIO)		+= gpio.o
+obj-$(CONFIG_PUV3_RTC)		+= rtc.o
+obj-$(CONFIG_PUV3_PWM)		+= pwm.o
+obj-$(CONFIG_PUV3_PM)		+= pm.o sleep.o
+obj-$(CONFIG_HIBERNATION)	+= hibernate.o hibernate_asm.o
+
+obj-$(CONFIG_PCI)		+= pci.o
+
+# obj-y for specific machines
+obj-$(CONFIG_ARCH_PUV3)		+= puv3-core.o
+obj-$(CONFIG_PUV3_NB0916)	+= puv3-nb0916.o
+
+head-y				:= head.o
+obj-$(CONFIG_DEBUG_LL)		+= debug.o
+
+extra-y				:= $(head-y) init_task.o vmlinux.lds
diff --git a/arch/unicore32/kernel/asm-offsets.c b/arch/unicore32/kernel/asm-offsets.c
new file mode 100644
index 0000000..ffcbe75
--- /dev/null
+++ b/arch/unicore32/kernel/asm-offsets.c
@@ -0,0 +1,112 @@
+/*
+ * linux/arch/unicore32/kernel/asm-offsets.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ *
+ * This program is free software; you can 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/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/kbuild.h>
+#include <linux/suspend.h>
+#include <linux/thread_info.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+
+/*
+ * GCC 3.0, 3.1: general bad code generation.
+ * GCC 3.2.0: incorrect function argument offset calculation.
+ * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
+ *	(http://gcc.gnu.org/PR8896) and incorrect structure
+ *		initialisation in fs/jffs2/erase.c
+ */
+#if (__GNUC__ < 4)
+#error Your compiler should upgrade to uc4
+#error	Known good compilers: 4.2.2
+#endif
+
+int main(void)
+{
+	DEFINE(TSK_ACTIVE_MM,	offsetof(struct task_struct, active_mm));
+	BLANK();
+	DEFINE(TI_FLAGS,	offsetof(struct thread_info, flags));
+	DEFINE(TI_PREEMPT,	offsetof(struct thread_info, preempt_count));
+	DEFINE(TI_ADDR_LIMIT,	offsetof(struct thread_info, addr_limit));
+	DEFINE(TI_TASK,		offsetof(struct thread_info, task));
+	DEFINE(TI_EXEC_DOMAIN,	offsetof(struct thread_info, exec_domain));
+	DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+	DEFINE(TI_CPU_SAVE,	offsetof(struct thread_info, cpu_context));
+	DEFINE(TI_USED_CP,	offsetof(struct thread_info, used_cp));
+#ifdef CONFIG_UNICORE_FPU_F64
+	DEFINE(TI_FPSTATE,	offsetof(struct thread_info, fpstate));
+#endif
+	BLANK();
+	DEFINE(S_R0,		offsetof(struct pt_regs, UCreg_00));
+	DEFINE(S_R1,		offsetof(struct pt_regs, UCreg_01));
+	DEFINE(S_R2,		offsetof(struct pt_regs, UCreg_02));
+	DEFINE(S_R3,		offsetof(struct pt_regs, UCreg_03));
+	DEFINE(S_R4,		offsetof(struct pt_regs, UCreg_04));
+	DEFINE(S_R5,		offsetof(struct pt_regs, UCreg_05));
+	DEFINE(S_R6,		offsetof(struct pt_regs, UCreg_06));
+	DEFINE(S_R7,		offsetof(struct pt_regs, UCreg_07));
+	DEFINE(S_R8,		offsetof(struct pt_regs, UCreg_08));
+	DEFINE(S_R9,		offsetof(struct pt_regs, UCreg_09));
+	DEFINE(S_R10,		offsetof(struct pt_regs, UCreg_10));
+	DEFINE(S_R11,		offsetof(struct pt_regs, UCreg_11));
+	DEFINE(S_R12,		offsetof(struct pt_regs, UCreg_12));
+	DEFINE(S_R13,		offsetof(struct pt_regs, UCreg_13));
+	DEFINE(S_R14,		offsetof(struct pt_regs, UCreg_14));
+	DEFINE(S_R15,		offsetof(struct pt_regs, UCreg_15));
+	DEFINE(S_R16,		offsetof(struct pt_regs, UCreg_16));
+	DEFINE(S_R17,		offsetof(struct pt_regs, UCreg_17));
+	DEFINE(S_R18,		offsetof(struct pt_regs, UCreg_18));
+	DEFINE(S_R19,		offsetof(struct pt_regs, UCreg_19));
+	DEFINE(S_R20,		offsetof(struct pt_regs, UCreg_20));
+	DEFINE(S_R21,		offsetof(struct pt_regs, UCreg_21));
+	DEFINE(S_R22,		offsetof(struct pt_regs, UCreg_22));
+	DEFINE(S_R23,		offsetof(struct pt_regs, UCreg_23));
+	DEFINE(S_R24,		offsetof(struct pt_regs, UCreg_24));
+	DEFINE(S_R25,		offsetof(struct pt_regs, UCreg_25));
+	DEFINE(S_R26,		offsetof(struct pt_regs, UCreg_26));
+	DEFINE(S_FP,		offsetof(struct pt_regs, UCreg_fp));
+	DEFINE(S_IP,		offsetof(struct pt_regs, UCreg_ip));
+	DEFINE(S_SP,		offsetof(struct pt_regs, UCreg_sp));
+	DEFINE(S_LR,		offsetof(struct pt_regs, UCreg_lr));
+	DEFINE(S_PC,		offsetof(struct pt_regs, UCreg_pc));
+	DEFINE(S_PSR,		offsetof(struct pt_regs, UCreg_asr));
+	DEFINE(S_OLD_R0,	offsetof(struct pt_regs, UCreg_ORIG_00));
+	DEFINE(S_FRAME_SIZE,	sizeof(struct pt_regs));
+	BLANK();
+	DEFINE(VMA_VM_MM,	offsetof(struct vm_area_struct, vm_mm));
+	DEFINE(VMA_VM_FLAGS,	offsetof(struct vm_area_struct, vm_flags));
+	BLANK();
+	DEFINE(VM_EXEC,		VM_EXEC);
+	BLANK();
+	DEFINE(PAGE_SZ,		PAGE_SIZE);
+	BLANK();
+	DEFINE(SYS_ERROR0,	0x9f0000);
+	BLANK();
+	DEFINE(PBE_ADDRESS,		offsetof(struct pbe, address));
+	DEFINE(PBE_ORIN_ADDRESS,	offsetof(struct pbe, orig_address));
+	DEFINE(PBE_NEXT,		offsetof(struct pbe, next));
+	DEFINE(SWSUSP_CPU,		offsetof(struct swsusp_arch_regs, \
+							cpu_context));
+#ifdef	CONFIG_UNICORE_FPU_F64
+	DEFINE(SWSUSP_FPSTATE,		offsetof(struct swsusp_arch_regs, \
+							fpstate));
+#endif
+	BLANK();
+	DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
+	DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
+	DEFINE(DMA_FROM_DEVICE,		DMA_FROM_DEVICE);
+	return 0;
+}
diff --git a/arch/unicore32/kernel/clock.c b/arch/unicore32/kernel/clock.c
new file mode 100644
index 0000000..18d4563
--- /dev/null
+++ b/arch/unicore32/kernel/clock.c
@@ -0,0 +1,390 @@
+/*
+ * linux/arch/unicore32/kernel/clock.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/device.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+/*
+ * Very simple clock implementation
+ */
+struct clk {
+	struct list_head	node;
+	unsigned long		rate;
+	const char		*name;
+};
+
+static struct clk clk_ost_clk = {
+	.name		= "OST_CLK",
+	.rate		= CLOCK_TICK_RATE,
+};
+
+static struct clk clk_mclk_clk = {
+	.name		= "MAIN_CLK",
+};
+
+static struct clk clk_bclk32_clk = {
+	.name		= "BUS32_CLK",
+};
+
+static struct clk clk_ddr_clk = {
+	.name		= "DDR_CLK",
+};
+
+static struct clk clk_vga_clk = {
+	.name		= "VGA_CLK",
+};
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+	mutex_lock(&clocks_mutex);
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0) {
+			clk = p;
+			break;
+		}
+	}
+	mutex_unlock(&clocks_mutex);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+struct {
+	unsigned long rate;
+	unsigned long cfg;
+	unsigned long div;
+} vga_clk_table[] = {
+	{.rate =  25175000, .cfg = 0x00002001, .div = 0x9},
+	{.rate =  31500000, .cfg = 0x00002001, .div = 0x7},
+	{.rate =  40000000, .cfg = 0x00003801, .div = 0x9},
+	{.rate =  49500000, .cfg = 0x00003801, .div = 0x7},
+	{.rate =  65000000, .cfg = 0x00002c01, .div = 0x4},
+	{.rate =  78750000, .cfg = 0x00002400, .div = 0x7},
+	{.rate = 108000000, .cfg = 0x00002c01, .div = 0x2},
+	{.rate = 106500000, .cfg = 0x00003c01, .div = 0x3},
+	{.rate =  50650000, .cfg = 0x00106400, .div = 0x9},
+	{.rate =  61500000, .cfg = 0x00106400, .div = 0xa},
+	{.rate =  85500000, .cfg = 0x00002800, .div = 0x6},
+};
+
+struct {
+	unsigned long mrate;
+	unsigned long prate;
+} mclk_clk_table[] = {
+	{.mrate = 500000000, .prate = 0x00109801},
+	{.mrate = 525000000, .prate = 0x00104C00},
+	{.mrate = 550000000, .prate = 0x00105000},
+	{.mrate = 575000000, .prate = 0x00105400},
+	{.mrate = 600000000, .prate = 0x00105800},
+	{.mrate = 625000000, .prate = 0x00105C00},
+	{.mrate = 650000000, .prate = 0x00106000},
+	{.mrate = 675000000, .prate = 0x00106400},
+	{.mrate = 700000000, .prate = 0x00106800},
+	{.mrate = 725000000, .prate = 0x00106C00},
+	{.mrate = 750000000, .prate = 0x00107000},
+	{.mrate = 775000000, .prate = 0x00107400},
+	{.mrate = 800000000, .prate = 0x00107800},
+};
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == &clk_vga_clk) {
+		unsigned long pll_vgacfg, pll_vgadiv;
+		int ret, i;
+
+		/* lookup vga_clk_table */
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(vga_clk_table); i++) {
+			if (rate == vga_clk_table[i].rate) {
+				pll_vgacfg = vga_clk_table[i].cfg;
+				pll_vgadiv = vga_clk_table[i].div;
+				ret = 0;
+				break;
+			}
+		}
+
+		if (ret)
+			return ret;
+
+		if (readl(PM_PLLVGACFG) == pll_vgacfg)
+			return 0;
+
+		/* set pll vga cfg reg. */
+		writel(pll_vgacfg, PM_PLLVGACFG);
+
+		writel(PM_PMCR_CFBVGA, PM_PMCR);
+		while ((readl(PM_PLLDFCDONE) & PM_PLLDFCDONE_VGADFC)
+				!= PM_PLLDFCDONE_VGADFC)
+			udelay(100); /* about 1ms */
+
+		/* set div cfg reg. */
+		writel(readl(PM_PCGR) | PM_PCGR_VGACLK, PM_PCGR);
+
+		writel((readl(PM_DIVCFG) & ~PM_DIVCFG_VGACLK_MASK)
+				| PM_DIVCFG_VGACLK(pll_vgadiv), PM_DIVCFG);
+
+		writel(readl(PM_SWRESET) | PM_SWRESET_VGADIV, PM_SWRESET);
+		while ((readl(PM_SWRESET) & PM_SWRESET_VGADIV)
+				== PM_SWRESET_VGADIV)
+			udelay(100); /* 65536 bclk32, about 320us */
+
+		writel(readl(PM_PCGR) & ~PM_PCGR_VGACLK, PM_PCGR);
+	}
+#ifdef CONFIG_CPU_FREQ
+	if (clk == &clk_mclk_clk) {
+		u32 pll_rate, divstatus = PM_DIVSTATUS;
+		int ret, i;
+
+		/* lookup mclk_clk_table */
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(mclk_clk_table); i++) {
+			if (rate == mclk_clk_table[i].mrate) {
+				pll_rate = mclk_clk_table[i].prate;
+				clk_mclk_clk.rate = mclk_clk_table[i].mrate;
+				ret = 0;
+				break;
+			}
+		}
+
+		if (ret)
+			return ret;
+
+		if (clk_mclk_clk.rate)
+			clk_bclk32_clk.rate = clk_mclk_clk.rate
+				/ (((divstatus & 0x0000f000) >> 12) + 1);
+
+		/* set pll sys cfg reg. */
+		PM_PLLSYSCFG = pll_rate;
+
+		PM_PMCR = PM_PMCR_CFBSYS;
+		while ((PM_PLLDFCDONE & PM_PLLDFCDONE_SYSDFC)
+				!= PM_PLLDFCDONE_SYSDFC)
+			udelay(100);
+			/* about 1ms */
+	}
+#endif
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+	mutex_lock(&clocks_mutex);
+	list_add(&clk->node, &clocks);
+	mutex_unlock(&clocks_mutex);
+	printk(KERN_DEFAULT "PKUnity PM: %s %lu.%02luM\n", clk->name,
+		(clk->rate)/1000000, (clk->rate)/10000 % 100);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	mutex_lock(&clocks_mutex);
+	list_del(&clk->node);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+struct {
+	unsigned long prate;
+	unsigned long rate;
+} pllrate_table[] = {
+	{.prate = 0x00002001, .rate = 250000000},
+	{.prate = 0x00104801, .rate = 250000000},
+	{.prate = 0x00104C01, .rate = 262500000},
+	{.prate = 0x00002401, .rate = 275000000},
+	{.prate = 0x00105001, .rate = 275000000},
+	{.prate = 0x00105401, .rate = 287500000},
+	{.prate = 0x00002801, .rate = 300000000},
+	{.prate = 0x00105801, .rate = 300000000},
+	{.prate = 0x00105C01, .rate = 312500000},
+	{.prate = 0x00002C01, .rate = 325000000},
+	{.prate = 0x00106001, .rate = 325000000},
+	{.prate = 0x00106401, .rate = 337500000},
+	{.prate = 0x00003001, .rate = 350000000},
+	{.prate = 0x00106801, .rate = 350000000},
+	{.prate = 0x00106C01, .rate = 362500000},
+	{.prate = 0x00003401, .rate = 375000000},
+	{.prate = 0x00107001, .rate = 375000000},
+	{.prate = 0x00107401, .rate = 387500000},
+	{.prate = 0x00003801, .rate = 400000000},
+	{.prate = 0x00107801, .rate = 400000000},
+	{.prate = 0x00107C01, .rate = 412500000},
+	{.prate = 0x00003C01, .rate = 425000000},
+	{.prate = 0x00108001, .rate = 425000000},
+	{.prate = 0x00108401, .rate = 437500000},
+	{.prate = 0x00004001, .rate = 450000000},
+	{.prate = 0x00108801, .rate = 450000000},
+	{.prate = 0x00108C01, .rate = 462500000},
+	{.prate = 0x00004401, .rate = 475000000},
+	{.prate = 0x00109001, .rate = 475000000},
+	{.prate = 0x00109401, .rate = 487500000},
+	{.prate = 0x00004801, .rate = 500000000},
+	{.prate = 0x00109801, .rate = 500000000},
+	{.prate = 0x00104C00, .rate = 525000000},
+	{.prate = 0x00002400, .rate = 550000000},
+	{.prate = 0x00105000, .rate = 550000000},
+	{.prate = 0x00105400, .rate = 575000000},
+	{.prate = 0x00002800, .rate = 600000000},
+	{.prate = 0x00105800, .rate = 600000000},
+	{.prate = 0x00105C00, .rate = 625000000},
+	{.prate = 0x00002C00, .rate = 650000000},
+	{.prate = 0x00106000, .rate = 650000000},
+	{.prate = 0x00106400, .rate = 675000000},
+	{.prate = 0x00003000, .rate = 700000000},
+	{.prate = 0x00106800, .rate = 700000000},
+	{.prate = 0x00106C00, .rate = 725000000},
+	{.prate = 0x00003400, .rate = 750000000},
+	{.prate = 0x00107000, .rate = 750000000},
+	{.prate = 0x00107400, .rate = 775000000},
+	{.prate = 0x00003800, .rate = 800000000},
+	{.prate = 0x00107800, .rate = 800000000},
+	{.prate = 0x00107C00, .rate = 825000000},
+	{.prate = 0x00003C00, .rate = 850000000},
+	{.prate = 0x00108000, .rate = 850000000},
+	{.prate = 0x00108400, .rate = 875000000},
+	{.prate = 0x00004000, .rate = 900000000},
+	{.prate = 0x00108800, .rate = 900000000},
+	{.prate = 0x00108C00, .rate = 925000000},
+	{.prate = 0x00004400, .rate = 950000000},
+	{.prate = 0x00109000, .rate = 950000000},
+	{.prate = 0x00109400, .rate = 975000000},
+	{.prate = 0x00004800, .rate = 1000000000},
+	{.prate = 0x00109800, .rate = 1000000000},
+};
+
+struct {
+	unsigned long prate;
+	unsigned long drate;
+} pddr_table[] = {
+	{.prate = 0x00100800, .drate = 44236800},
+	{.prate = 0x00100C00, .drate = 66355200},
+	{.prate = 0x00101000, .drate = 88473600},
+	{.prate = 0x00101400, .drate = 110592000},
+	{.prate = 0x00101800, .drate = 132710400},
+	{.prate = 0x00101C01, .drate = 154828800},
+	{.prate = 0x00102001, .drate = 176947200},
+	{.prate = 0x00102401, .drate = 199065600},
+	{.prate = 0x00102801, .drate = 221184000},
+	{.prate = 0x00102C01, .drate = 243302400},
+	{.prate = 0x00103001, .drate = 265420800},
+	{.prate = 0x00103401, .drate = 287539200},
+	{.prate = 0x00103801, .drate = 309657600},
+	{.prate = 0x00103C01, .drate = 331776000},
+	{.prate = 0x00104001, .drate = 353894400},
+};
+
+static int __init clk_init(void)
+{
+#ifdef CONFIG_PUV3_PM
+	u32 pllrate, divstatus = readl(PM_DIVSTATUS);
+	u32 pcgr_val = readl(PM_PCGR);
+	int i;
+
+	pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
+			| PM_PCGR_HECLK | PM_PCGR_HDCLK;
+	writel(pcgr_val, PM_PCGR);
+
+	pllrate = readl(PM_PLLSYSSTATUS);
+
+	/* lookup pmclk_table */
+	clk_mclk_clk.rate = 0;
+	for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
+		if (pllrate == pllrate_table[i].prate) {
+			clk_mclk_clk.rate = pllrate_table[i].rate;
+			break;
+		}
+	}
+
+	if (clk_mclk_clk.rate)
+		clk_bclk32_clk.rate = clk_mclk_clk.rate /
+			(((divstatus & 0x0000f000) >> 12) + 1);
+
+	pllrate = readl(PM_PLLDDRSTATUS);
+
+	/* lookup pddr_table */
+	clk_ddr_clk.rate = 0;
+	for (i = 0; i < ARRAY_SIZE(pddr_table); i++) {
+		if (pllrate == pddr_table[i].prate) {
+			clk_ddr_clk.rate = pddr_table[i].drate;
+			break;
+		}
+	}
+
+	pllrate = readl(PM_PLLVGASTATUS);
+
+	/* lookup pvga_table */
+	clk_vga_clk.rate = 0;
+	for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
+		if (pllrate == pllrate_table[i].prate) {
+			clk_vga_clk.rate = pllrate_table[i].rate;
+			break;
+		}
+	}
+
+	if (clk_vga_clk.rate)
+		clk_vga_clk.rate = clk_vga_clk.rate /
+			(((divstatus & 0x00f00000) >> 20) + 1);
+
+	clk_register(&clk_vga_clk);
+#endif
+#ifdef CONFIG_ARCH_FPGA
+	clk_ddr_clk.rate = 33000000;
+	clk_mclk_clk.rate = 33000000;
+	clk_bclk32_clk.rate = 33000000;
+#endif
+	clk_register(&clk_ddr_clk);
+	clk_register(&clk_mclk_clk);
+	clk_register(&clk_bclk32_clk);
+	clk_register(&clk_ost_clk);
+	return 0;
+}
+core_initcall(clk_init);
diff --git a/arch/unicore32/kernel/cpu-ucv2.c b/arch/unicore32/kernel/cpu-ucv2.c
new file mode 100644
index 0000000..4a99f62
--- /dev/null
+++ b/arch/unicore32/kernel/cpu-ucv2.c
@@ -0,0 +1,93 @@
+/*
+ * linux/arch/unicore32/kernel/cpu-ucv2.c: clock scaling for the UniCore-II
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/cpufreq.h>
+
+#include <mach/hardware.h>
+
+static struct cpufreq_driver ucv2_driver;
+
+/* make sure that only the "userspace" governor is run
+ * -- anything else wouldn't make sense on this platform, anyway.
+ */
+int ucv2_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu)
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy,
+			policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+	return 0;
+}
+
+static unsigned int ucv2_getspeed(unsigned int cpu)
+{
+	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
+
+	if (cpu)
+		return 0;
+	return clk_get_rate(mclk)/1000;
+}
+
+static int ucv2_target(struct cpufreq_policy *policy,
+			 unsigned int target_freq,
+			 unsigned int relation)
+{
+	unsigned int cur = ucv2_getspeed(0);
+	struct cpufreq_freqs freqs;
+	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
+
+	cpufreq_notify_transition(&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);
+
+	return 0;
+}
+
+static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+	policy->cur = ucv2_getspeed(0);
+	policy->min = policy->cpuinfo.min_freq = 250000;
+	policy->max = policy->cpuinfo.max_freq = 1000000;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	return 0;
+}
+
+static struct cpufreq_driver ucv2_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= ucv2_verify_speed,
+	.target		= ucv2_target,
+	.get		= ucv2_getspeed,
+	.init		= ucv2_cpu_init,
+	.name		= "UniCore-II",
+};
+
+static int __init ucv2_cpufreq_init(void)
+{
+	return cpufreq_register_driver(&ucv2_driver);
+}
+
+arch_initcall(ucv2_cpufreq_init);
diff --git a/arch/unicore32/kernel/debug-macro.S b/arch/unicore32/kernel/debug-macro.S
new file mode 100644
index 0000000..2711d6d
--- /dev/null
+++ b/arch/unicore32/kernel/debug-macro.S
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/unicore32/kernel/debug-macro.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Debugging macro include header
+ */
+#include <generated/asm-offsets.h>
+#include <mach/hardware.h>
+
+		.macro	put_word_ocd, rd, rx=r16
+1001:		movc		\rx, p1.c0, #0
+		cand.a	\rx, #2
+		bne	1001b
+		movc		p1.c1, \rd, #1
+		.endm
+
+#ifdef CONFIG_DEBUG_OCD
+		/* debug using UniCore On-Chip-Debugger */
+		.macro	addruart, rx
+		.endm
+
+		.macro	senduart, rd, rx
+		put_word_ocd	\rd, \rx
+		.endm
+
+		.macro	busyuart, rd, rx
+		.endm
+
+		.macro	waituart, rd, rx
+		.endm
+#else
+#define UART_CLK_DEFAULT        3686400 * 20
+	/* Uartclk = MCLK/ 2, The MCLK on my board is 3686400 * 40  */
+#define BAUD_RATE_DEFAULT	115200
+	/* The baud rate of the serial port */
+
+#define UART_DIVISOR_DEFAULT	(UART_CLK_DEFAULT \
+				/ (16 * BAUD_RATE_DEFAULT) - 1)
+
+		.macro	addruart,rx
+		mrc	p0, #0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0xee000000	@ physical base address
+		movne	\rx, #0x6e000000	@ virtual address
+
+		@ We probe for the active serial port here
+		@ However, now we assume UART0 is active:	epip4d
+		@ We assume r1 and r2 can be clobbered.
+
+		movl 	r2, #UART_DIVISOR_DEFAULT
+		mov 	r1, #0x80
+		str	r1, [\rx, #UART_LCR_OFFSET]
+		and	r1, r2, #0xff00
+		mov	r1, r1, lsr #8
+		str	r1, [\rx, #UART_DLH_OFFSET]
+		and	r1, r2, #0xff
+		str	r1, [\rx, #UART_DLL_OFFSET]
+		mov 	r1, #0x7
+		str	r1, [\rx, #UART_FCR_OFFSET]
+		mov 	r1, #0x3
+		str	r1, [\rx, #UART_LCR_OFFSET]
+		mov 	r1, #0x0
+		str	r1, [\rx, #UART_IER_OFFSET]
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_THR_OFFSET]
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #UART_LSR_OFFSET]
+		tst	\rd, #UART_LSR_THRE
+		beq	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #UART_LSR_OFFSET]
+		tst	\rd, #UART_LSR_TEMT
+		bne	1001b
+		.endm
+#endif
+
diff --git a/arch/unicore32/kernel/debug.S b/arch/unicore32/kernel/debug.S
new file mode 100644
index 0000000..029fd12
--- /dev/null
+++ b/arch/unicore32/kernel/debug.S
@@ -0,0 +1,85 @@
+/*
+ * linux/arch/unicore32/kernel/debug.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  32-bit debugging code
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+/*
+ * Some debugging routines (useful if you've got MM problems and
+ * printk isn't working).  For DEBUGGING ONLY!!!  Do not leave
+ * references to these in a production kernel!
+ */
+#include "debug-macro.S"
+
+/*
+ * Useful debugging routines
+ */
+ENTRY(printhex8)
+		mov	r1, #8
+		b	printhex
+ENDPROC(printhex8)
+
+ENTRY(printhex4)
+		mov	r1, #4
+		b	printhex
+ENDPROC(printhex4)
+
+ENTRY(printhex2)
+		mov	r1, #2
+printhex:	adr	r2, hexbuf
+		add	r3, r2, r1
+		mov	r1, #0
+		stb	r1, [r3]
+1:		and	r1, r0, #15
+		mov	r0, r0 >> #4
+		csub.a	r1, #10
+		beg	2f
+		add	r1, r1, #'0' - 'a' + 10
+2:		add	r1, r1, #'a' - 10
+		stb.w	r1, [r3+], #-1
+		cxor.a	r3, r2
+		bne	1b
+		mov	r0, r2
+		b	printascii
+ENDPROC(printhex2)
+
+		.ltorg
+
+ENTRY(printascii)
+		addruart r3
+		b	2f
+1:		waituart r2, r3
+		senduart r1, r3
+		busyuart r2, r3
+		cxor.a	r1, #'\n'
+		cmoveq	r1, #'\r'
+		beq	1b
+2:		cxor.a	r0, #0
+		beq	3f
+		ldb.w	r1, [r0]+, #1
+		cxor.a	r1, #0
+		bne	1b
+3:		mov	pc, lr
+ENDPROC(printascii)
+
+ENTRY(printch)
+		addruart r3
+		mov	r1, r0
+		mov	r0, #0
+		b	1b
+ENDPROC(printch)
+
+hexbuf:		.space 16
+
diff --git a/arch/unicore32/kernel/dma.c b/arch/unicore32/kernel/dma.c
new file mode 100644
index 0000000..ae441bc
--- /dev/null
+++ b/arch/unicore32/kernel/dma.c
@@ -0,0 +1,183 @@
+/*
+ * linux/arch/unicore32/kernel/dma.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <mach/dma.h>
+
+struct dma_channel {
+	char *name;
+	puv3_dma_prio prio;
+	void (*irq_handler)(int, void *);
+	void (*err_handler)(int, void *);
+	void *data;
+};
+
+static struct dma_channel dma_channels[MAX_DMA_CHANNELS];
+
+int puv3_request_dma(char *name, puv3_dma_prio prio,
+			 void (*irq_handler)(int, void *),
+			 void (*err_handler)(int, void *),
+			 void *data)
+{
+	unsigned long flags;
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	do {
+		/* try grabbing a DMA channel with the requested priority */
+		for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+			if ((dma_channels[i].prio == prio) &&
+			    !dma_channels[i].name) {
+				found = 1;
+				break;
+			}
+		}
+		/* if requested prio group is full, try a hier priority */
+	} while (!found && prio--);
+
+	if (found) {
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].err_handler = err_handler;
+		dma_channels[i].data = data;
+	} else {
+		printk(KERN_WARNING "No more available DMA channels for %s\n",
+				name);
+		i = -ENODEV;
+	}
+
+	local_irq_restore(flags);
+	return i;
+}
+EXPORT_SYMBOL(puv3_request_dma);
+
+void puv3_free_dma(int dma_ch)
+{
+	unsigned long flags;
+
+	if (!dma_channels[dma_ch].name) {
+		printk(KERN_CRIT
+			"%s: trying to free channel %d which is already freed\n",
+			__func__, dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	dma_channels[dma_ch].name = NULL;
+	dma_channels[dma_ch].err_handler = NULL;
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(puv3_free_dma);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+{
+	int i, dint;
+
+	dint = readl(DMAC_ITCSR);
+	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+		if (dint & DMAC_CHANNEL(i)) {
+			struct dma_channel *channel = &dma_channels[i];
+
+			/* Clear TC interrupt of channel i */
+			writel(DMAC_CHANNEL(i), DMAC_ITCCR);
+			writel(0, DMAC_ITCCR);
+
+			if (channel->name && channel->irq_handler) {
+				channel->irq_handler(i, channel->data);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel:
+				 * let's clear the interrupts and disable it.
+				 */
+				printk(KERN_WARNING "spurious IRQ for"
+						" DMA channel %d\n", i);
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dma_err_handler(int irq, void *dev_id)
+{
+	int i, dint;
+
+	dint = readl(DMAC_IESR);
+	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+		if (dint & DMAC_CHANNEL(i)) {
+			struct dma_channel *channel = &dma_channels[i];
+
+			/* Clear Err interrupt of channel i */
+			writel(DMAC_CHANNEL(i), DMAC_IECR);
+			writel(0, DMAC_IECR);
+
+			if (channel->name && channel->err_handler) {
+				channel->err_handler(i, channel->data);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel:
+				 * let's clear the interrupts and disable it.
+				 */
+				printk(KERN_WARNING "spurious IRQ for"
+						" DMA channel %d\n", i);
+			}
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+int __init puv3_init_dma(void)
+{
+	int i, ret;
+
+	/* dma channel priorities on v8 processors:
+	 * ch 0 - 1  <--> (0) DMA_PRIO_HIGH
+	 * ch 2 - 3  <--> (1) DMA_PRIO_MEDIUM
+	 * ch 4 - 5  <--> (2) DMA_PRIO_LOW
+	 */
+	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+		puv3_stop_dma(i);
+		dma_channels[i].name = NULL;
+		dma_channels[i].prio = min((i & 0x7) >> 1, DMA_PRIO_LOW);
+	}
+
+	ret = request_irq(IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Can't register IRQ for DMA\n");
+		return ret;
+	}
+
+	ret = request_irq(IRQ_DMAERR, dma_err_handler, 0, "DMAERR", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Can't register IRQ for DMAERR\n");
+		free_irq(IRQ_DMA, "DMA");
+		return ret;
+	}
+
+	return 0;
+}
+
+postcore_initcall(puv3_init_dma);
diff --git a/arch/unicore32/kernel/early_printk.c b/arch/unicore32/kernel/early_printk.c
new file mode 100644
index 0000000..3922255
--- /dev/null
+++ b/arch/unicore32/kernel/early_printk.c
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/unicore32/kernel/early_printk.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/console.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <mach/ocd.h>
+
+/* On-Chip-Debugger functions */
+
+static void early_ocd_write(struct console *con, const char *s, unsigned n)
+{
+	while (*s && n-- > 0) {
+		if (*s == '\n')
+			ocd_putc((int)'\r');
+		ocd_putc((int)*s);
+		s++;
+	}
+}
+
+static struct console early_ocd_console = {
+	.name =		"earlyocd",
+	.write =	early_ocd_write,
+	.flags =	CON_PRINTBUFFER,
+	.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)
+		return 0;
+
+	if (strstr(buf, "keep"))
+		keep_early = 1;
+
+	if (!strncmp(buf, "ocd", 3))
+		early_console = &early_ocd_console;
+
+	if (keep_early)
+		early_console->flags &= ~CON_BOOT;
+	else
+		early_console->flags |= CON_BOOT;
+	register_console(early_console);
+	return 0;
+}
+early_param("earlyprintk", setup_early_printk);
diff --git a/arch/unicore32/kernel/elf.c b/arch/unicore32/kernel/elf.c
new file mode 100644
index 0000000..0a17673
--- /dev/null
+++ b/arch/unicore32/kernel/elf.c
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/unicore32/kernel/elf.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/sched.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+#include <linux/elf.h>
+
+int elf_check_arch(const struct elf32_hdr *x)
+{
+	/* Make sure it's an UniCore executable */
+	if (x->e_machine != EM_UNICORE)
+		return 0;
+
+	/* Make sure the entry address is reasonable */
+	if (x->e_entry & 3)
+		return 0;
+
+	return 1;
+}
+EXPORT_SYMBOL(elf_check_arch);
+
+void elf_set_personality(const struct elf32_hdr *x)
+{
+	unsigned int personality = PER_LINUX;
+
+	set_personality(personality);
+}
+EXPORT_SYMBOL(elf_set_personality);
diff --git a/arch/unicore32/kernel/entry.S b/arch/unicore32/kernel/entry.S
new file mode 100644
index 0000000..00a259f
--- /dev/null
+++ b/arch/unicore32/kernel/entry.S
@@ -0,0 +1,824 @@
+/*
+ * linux/arch/unicore32/kernel/entry.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Low-level vector interface routines
+ */
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/unistd.h>
+#include <generated/asm-offsets.h>
+#include "debug-macro.S"
+
+@
+@ Most of the stack format comes from struct pt_regs, but with
+@ the addition of 8 bytes for storing syscall args 5 and 6.
+@
+#define S_OFF		8
+
+/*
+ * The SWI code relies on the fact that R0 is at the bottom of the stack
+ * (due to slow/fast restore user regs).
+ */
+#if S_R0 != 0
+#error "Please fix"
+#endif
+
+	.macro	zero_fp
+#ifdef CONFIG_FRAME_POINTER
+	mov	fp, #0
+#endif
+	.endm
+
+	.macro	alignment_trap, rtemp
+#ifdef CONFIG_ALIGNMENT_TRAP
+	ldw	\rtemp, .LCcralign
+	ldw	\rtemp, [\rtemp]
+	movc	p0.c1, \rtemp, #0
+#endif
+	.endm
+
+	.macro	load_user_sp_lr, rd, rtemp, offset = 0
+	mov	\rtemp, asr
+	xor	\rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
+	mov.a	asr, \rtemp			@ switch to the SUSR mode
+
+	ldw	sp, [\rd+], #\offset		@ load sp_user
+	ldw	lr, [\rd+], #\offset + 4	@ load lr_user
+
+	xor	\rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
+	mov.a	asr, \rtemp			@ switch back to the PRIV mode
+	.endm
+
+	.macro	priv_exit, rpsr
+	mov.a	bsr, \rpsr
+	ldm.w	(r0 - r15), [sp]+
+	ldm.b	(r16 - pc), [sp]+		@ load r0 - pc, asr
+	.endm
+
+	.macro	restore_user_regs, fast = 0, offset = 0
+	ldw	r1, [sp+], #\offset + S_PSR	@ get calling asr
+	ldw	lr, [sp+], #\offset + S_PC	@ get pc
+	mov.a	bsr, r1				@ save in bsr_priv
+	.if	\fast
+	add	sp, sp, #\offset + S_R1		@ r0 is syscall return value
+	ldm.w	(r1 - r15), [sp]+		@ get calling r1 - r15
+	ldur	(r16 - lr), [sp]+		@ get calling r16 - lr
+	.else
+	ldm.w	(r0 - r15), [sp]+		@ get calling r0 - r15
+	ldur	(r16 - lr), [sp]+		@ get calling r16 - lr
+	.endif
+	nop
+	add	sp, sp, #S_FRAME_SIZE - S_R16
+	mov.a	pc, lr				@ return
+						@ and move bsr_priv into asr
+	.endm
+
+	.macro	get_thread_info, rd
+	mov	\rd, sp >> #13
+	mov	\rd, \rd << #13
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldw	\base, =(PKUNITY_INTC_BASE)
+	ldw	\irqstat, [\base+], #0xC	@ INTC_ICIP
+	ldw	\tmp,	  [\base+], #0x4	@ INTC_ICMR
+	and.a	\irqstat, \irqstat, \tmp
+	beq	1001f
+	cntlz	\irqnr, \irqstat
+	rsub	\irqnr, \irqnr, #31
+1001:	/* EQ will be set if no irqs pending */
+	.endm
+
+#ifdef CONFIG_DEBUG_LL
+	.macro	printreg, reg, temp
+		adr	\temp, 901f
+		stm	(r0-r3), [\temp]+
+		stw	lr, [\temp+], #0x10
+		mov	r0, \reg
+		b.l	printhex8
+		mov	r0, #':'
+		b.l	printch
+		mov	r0, pc
+		b.l	printhex8
+		adr	r0, 902f
+		b.l	printascii
+		adr	\temp, 901f
+		ldm	(r0-r3), [\temp]+
+		ldw	lr, [\temp+], #0x10
+		b	903f
+901:	.word	0, 0, 0, 0, 0	@ r0-r3, lr
+902:	.asciz	": epip4d\n"
+	.align
+903:
+	.endm
+#endif
+
+/*
+ * 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.
+ *
+ * Note that tbl == why is intentional.
+ *
+ * We must set at least "tsk" and "why" when calling ret_with_reschedule.
+ */
+scno	.req	r21		@ syscall number
+tbl	.req	r22		@ syscall table pointer
+why	.req	r22		@ Linux syscall (!= 0)
+tsk	.req	r23		@ current thread_info
+
+/*
+ * Interrupt handling.  Preserves r17, r18, r19
+ */
+	.macro	intr_handler
+1:	get_irqnr_and_base r0, r6, r5, lr
+	beq	2f
+	mov	r1, sp
+	@
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	@
+	adr	lr, 1b
+	b	asm_do_IRQ
+2:
+	.endm
+
+/*
+ * PRIV mode handlers
+ */
+	.macro	priv_entry
+	sub	sp, sp, #(S_FRAME_SIZE - 4)
+	stm	(r1 - r15), [sp]+
+	add	r5, sp, #S_R15
+	stm	(r16 - r28), [r5]+
+
+	ldm	(r1 - r3), [r0]+
+	add	r5, sp, #S_SP - 4	@ here for interlock avoidance
+	mov	r4, #-1			@  ""  ""      ""       ""
+	add	r0, sp, #(S_FRAME_SIZE - 4)
+	stw.w	r1, [sp+], #-4		@ save the "real" r0 copied
+					@ from the exception stack
+
+	mov	r1, lr
+
+	@
+	@ We are now ready to fill in the remaining blanks on the stack:
+	@
+	@  r0 - sp_priv
+	@  r1 - lr_priv
+	@  r2 - lr_<exception>, already fixed up for correct return/restart
+	@  r3 - bsr_<exception>
+	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
+	@
+	stm	(r0 - r4), [r5]+
+	.endm
+
+/*
+ * User mode handlers
+ *
+ */
+	.macro	user_entry
+	sub	sp, sp, #S_FRAME_SIZE
+	stm	(r1 - r15), [sp+]
+	add	r4, sp, #S_R16
+	stm	(r16 - r28), [r4]+
+
+	ldm	(r1 - r3), [r0]+
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r4, #-1			@  ""  ""     ""        ""
+
+	stw	r1, [sp]		@ save the "real" r0 copied
+					@ from the exception stack
+
+	@
+	@ We are now ready to fill in the remaining blanks on the stack:
+	@
+	@  r2 - lr_<exception>, already fixed up for correct return/restart
+	@  r3 - bsr_<exception>
+	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
+	@
+	@ Also, separately save sp_user and lr_user
+	@
+	stm	(r2 - r4), [r0]+
+	stur	(sp, lr), [r0-]
+
+	@
+	@ Enable the alignment trap while in kernel mode
+	@
+	alignment_trap r0
+
+	@
+	@ Clear FP to mark the first stack frame
+	@
+	zero_fp
+	.endm
+
+	.text
+
+@
+@ __invalid - generic code for failed exception
+@			(re-entrant version of handlers)
+@
+__invalid:
+	sub	sp, sp, #S_FRAME_SIZE
+	stm	(r1 - r15), [sp+]
+	add	r1, sp, #S_R16
+	stm	(r16 - r28, sp, lr), [r1]+
+
+	zero_fp
+
+	ldm	(r4 - r6), [r0]+
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r7, #-1			@  ""   ""    ""        ""
+	stw	r4, [sp]		@ save preserved r0
+	stm	(r5 - r7), [r0]+	@ lr_<exception>,
+					@ asr_<exception>, "old_r0"
+
+	mov	r0, sp
+	mov	r1, asr
+	b	bad_mode
+ENDPROC(__invalid)
+
+	.align	5
+__dabt_priv:
+	priv_entry
+
+	@
+	@ get ready to re-enable interrupts if appropriate
+	@
+	mov	r17, asr
+	cand.a	r3, #PSR_I_BIT
+	bne	1f
+	andn	r17, r17, #PSR_I_BIT
+1:
+
+	@
+	@ Call the processor-specific abort handler:
+	@
+	@  r2 - aborted context pc
+	@  r3 - aborted context asr
+	@
+	@ The abort handler must return the aborted address in r0, and
+	@ the fault status register in r1.
+	@
+	movc	r1, p0.c3, #0		@ get FSR
+	movc	r0, p0.c4, #0		@ get FAR
+
+	@
+	@ set desired INTR state, then call main handler
+	@
+	mov.a	asr, r17
+	mov	r2, sp
+	b.l	do_DataAbort
+
+	@
+	@ INTRs off again before pulling preserved data off the stack
+	@
+	disable_irq r0
+
+	@
+	@ restore BSR and restart the instruction
+	@
+	ldw	r2, [sp+], #S_PSR
+	priv_exit r2				@ return from exception
+ENDPROC(__dabt_priv)
+
+	.align	5
+__intr_priv:
+	priv_entry
+
+	intr_handler
+
+	mov	r0, #0				@ epip4d
+	movc	p0.c5, r0, #14
+	nop; nop; nop; nop; nop; nop; nop; nop
+
+	ldw	r4, [sp+], #S_PSR		@ irqs are already disabled
+
+	priv_exit r4				@ return from exception
+ENDPROC(__intr_priv)
+
+	.ltorg
+
+	.align	5
+__extn_priv:
+	priv_entry
+
+	mov	r0, sp				@ struct pt_regs *regs
+	mov	r1, asr
+	b	bad_mode			@ not supported
+ENDPROC(__extn_priv)
+
+	.align	5
+__pabt_priv:
+	priv_entry
+
+	@
+	@ re-enable interrupts if appropriate
+	@
+	mov	r17, asr
+	cand.a	r3, #PSR_I_BIT
+	bne	1f
+	andn	r17, r17, #PSR_I_BIT
+1:
+
+	@
+	@ set args, then call main handler
+	@
+	@  r0 - address of faulting instruction
+	@  r1 - pointer to registers on stack
+	@
+	mov	r0, r2			@ pass address of aborted instruction
+	mov	r1, #5
+	mov.a	asr, r17
+	mov	r2, sp			@ regs
+	b.l	do_PrefetchAbort	@ call abort handler
+
+	@
+	@ INTRs off again before pulling preserved data off the stack
+	@
+	disable_irq r0
+
+	@
+	@ restore BSR and restart the instruction
+	@
+	ldw	r2, [sp+], #S_PSR
+	priv_exit r2			@ return from exception
+ENDPROC(__pabt_priv)
+
+	.align	5
+.LCcralign:
+	.word	cr_alignment
+
+	.align	5
+__dabt_user:
+	user_entry
+
+#ifdef CONFIG_UNICORE_FPU_F64
+	cff	ip, s31
+	cand.a	ip, #0x08000000		@ FPU execption traps?
+	beq	209f
+
+	ldw	ip, [sp+], #S_PC
+	add	ip, ip, #4
+	stw	ip, [sp+], #S_PC
+	@
+	@ fall through to the emulation code, which returns using r19 if
+	@ it has emulated the instruction, or the more conventional lr
+	@ if we are to treat this as a real extended instruction
+	@
+	@  r0 - instruction
+	@
+1:	ldw.u	r0, [r2]
+	adr	r19, ret_from_exception
+	adr	lr, 209f
+	@
+	@ fallthrough to call do_uc_f64
+	@
+/*
+ * Check whether the instruction is a co-processor instruction.
+ * If yes, we need to call the relevant co-processor handler.
+ *
+ * Note that we don't do a full check here for the co-processor
+ * instructions; all instructions with bit 27 set are well
+ * defined.  The only instructions that should fault are the
+ * co-processor instructions.
+ *
+ * Emulators may wish to make use of the following registers:
+ *  r0  = instruction opcode.
+ *  r2  = PC
+ *  r19 = normal "successful" return address
+ *  r20 = this threads thread_info structure.
+ *  lr  = unrecognised instruction return address
+ */
+	get_thread_info r20			@ get current thread
+	and	r8, r0, #0x00003c00		@ mask out CP number
+	mov	r7, #1
+	stb	r7, [r20+], #TI_USED_CP + 2	@ set appropriate used_cp[]
+
+	@ F64 hardware support entry point.
+	@  r0  = faulted instruction
+	@  r19 = return address
+	@  r20 = fp_state
+	enable_irq r4
+	add	r20, r20, #TI_FPSTATE	@ r20 = workspace
+	cff	r1, s31			@ get fpu FPSCR
+	andn    r2, r1, #0x08000000
+	ctf     r2, s31			@ clear 27 bit
+	mov	r2, sp			@ nothing stacked - regdump is at TOS
+	mov	lr, r19			@ setup for a return to the user code
+
+	@ Now call the C code to package up the bounce to the support code
+	@   r0 holds the trigger instruction
+	@   r1 holds the FPSCR value
+	@   r2 pointer to register dump
+	b	ucf64_exchandler
+209:
+#endif
+	@
+	@ Call the processor-specific abort handler:
+	@
+	@  r2 - aborted context pc
+	@  r3 - aborted context asr
+	@
+	@ The abort handler must return the aborted address in r0, and
+	@ the fault status register in r1.
+	@
+	movc	r1, p0.c3, #0		@ get FSR
+	movc	r0, p0.c4, #0		@ get FAR
+
+	@
+	@ INTRs on, then call the main handler
+	@
+	enable_irq r2
+	mov	r2, sp
+	adr	lr, ret_from_exception
+	b	do_DataAbort
+ENDPROC(__dabt_user)
+
+	.align	5
+__intr_user:
+	user_entry
+
+	get_thread_info tsk
+
+	intr_handler
+
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__intr_user)
+
+	.ltorg
+
+	.align	5
+__extn_user:
+	user_entry
+
+	mov	r0, sp
+	mov	r1, asr
+	b	bad_mode
+ENDPROC(__extn_user)
+
+	.align	5
+__pabt_user:
+	user_entry
+
+	mov	r0, r2			@ pass address of aborted instruction.
+	mov	r1, #5
+	enable_irq r1			@ Enable interrupts
+	mov	r2, sp			@ regs
+	b.l	do_PrefetchAbort	@ call abort handler
+	/* fall through */
+/*
+ * This is the return code to user mode for abort handlers
+ */
+ENTRY(ret_from_exception)
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pabt_user)
+ENDPROC(ret_from_exception)
+
+/*
+ * Register switch for UniCore V2 processors
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	add	ip, r1, #TI_CPU_SAVE
+	stm.w	(r4 - r15), [ip]+
+	stm.w	(r16 - r27, sp, lr), [ip]+
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	add	ip, r1, #TI_FPSTATE
+	sfm.w	(f0  - f7 ), [ip]+
+	sfm.w	(f8  - f15), [ip]+
+	sfm.w	(f16 - f23), [ip]+
+	sfm.w	(f24 - f31), [ip]+
+	cff	r4, s31
+	stw	r4, [ip]
+
+	add	ip, r2, #TI_FPSTATE
+	lfm.w	(f0  - f7 ), [ip]+
+	lfm.w	(f8  - f15), [ip]+
+	lfm.w	(f16 - f23), [ip]+
+	lfm.w	(f24 - f31), [ip]+
+	ldw	r4, [ip]
+	ctf	r4, s31
+#endif
+	add	ip, r2, #TI_CPU_SAVE
+	ldm.w	(r4 - r15), [ip]+
+	ldm	(r16 - r27, sp, pc), [ip]+	@ Load all regs saved previously
+ENDPROC(__switch_to)
+
+	.align	5
+/*
+ * This is the fast syscall return path.  We do as little as
+ * possible here, and this includes saving r0 back into the PRIV
+ * stack.
+ */
+ret_fast_syscall:
+	disable_irq r1				@ disable interrupts
+	ldw	r1, [tsk+], #TI_FLAGS
+	cand.a	r1, #_TIF_WORK_MASK
+	bne	fast_work_pending
+
+	@ fast_restore_user_regs
+	restore_user_regs fast = 1, offset = S_OFF
+
+/*
+ * Ok, we need to do extra processing, enter the slow path.
+ */
+fast_work_pending:
+	stw.w	r0, [sp+], #S_R0+S_OFF		@ returned r0
+work_pending:
+	cand.a	r1, #_TIF_NEED_RESCHED
+	bne	work_resched
+	cand.a	r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
+	beq	no_work_pending
+	mov	r0, sp				@ 'regs'
+	mov	r2, why				@ 'syscall'
+	cand.a	r1, #_TIF_SIGPENDING		@ delivering a signal?
+	cmovne	why, #0				@ prevent further restarts
+	b.l	do_notify_resume
+	b	ret_slow_syscall		@ Check work again
+
+work_resched:
+	b.l	schedule
+/*
+ * "slow" syscall return path.  "why" tells us if this was a real syscall.
+ */
+ENTRY(ret_to_user)
+ret_slow_syscall:
+	disable_irq r1				@ disable interrupts
+	get_thread_info tsk			@ epip4d, one path error?!
+	ldw	r1, [tsk+], #TI_FLAGS
+	cand.a	r1, #_TIF_WORK_MASK
+	bne	work_pending
+no_work_pending:
+	@ slow_restore_user_regs
+	restore_user_regs fast = 0, offset = 0
+ENDPROC(ret_to_user)
+
+/*
+ * This is how we return from a fork.
+ */
+ENTRY(ret_from_fork)
+	b.l	schedule_tail
+	get_thread_info tsk
+	ldw	r1, [tsk+], #TI_FLAGS		@ check for syscall tracing
+	mov	why, #1
+	cand.a	r1, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+	beq	ret_slow_syscall
+	mov	r1, sp
+	mov	r0, #1				@ trace exit [IP = 1]
+	b.l	syscall_trace
+	b	ret_slow_syscall
+ENDPROC(ret_from_fork)
+
+/*=============================================================================
+ * SWI handler
+ *-----------------------------------------------------------------------------
+ */
+	.align	5
+ENTRY(vector_swi)
+	sub	sp, sp, #S_FRAME_SIZE
+	stm	(r0 - r15), [sp]+		@ Calling r0 - r15
+	add	r8, sp, #S_R16
+	stm	(r16 - r28), [r8]+		@ Calling r16 - r28
+	add	r8, sp, #S_PC
+	stur	(sp, lr), [r8-]			@ Calling sp, lr
+	mov	r8, bsr				@ called from non-REAL mode
+	stw	lr, [sp+], #S_PC		@ Save calling PC
+	stw	r8, [sp+], #S_PSR		@ Save ASR
+	stw	r0, [sp+], #S_OLD_R0		@ Save OLD_R0
+	zero_fp
+
+	/*
+	 * Get the system call number.
+	 */
+	sub	ip, lr, #4
+	ldw.u	scno, [ip]			@ get SWI instruction
+
+#ifdef CONFIG_ALIGNMENT_TRAP
+	ldw	ip, __cr_alignment
+	ldw	ip, [ip]
+	movc	p0.c1, ip, #0                   @ update control register
+#endif
+	enable_irq ip
+
+	get_thread_info tsk
+	ldw	tbl, =sys_call_table		@ load syscall table pointer
+
+	andn	scno, scno, #0xff000000		@ mask off SWI op-code
+	andn	scno, scno, #0x00ff0000		@ mask off SWI op-code
+
+	stm.w	(r4, r5), [sp-]			@ push fifth and sixth args
+	ldw	ip, [tsk+], #TI_FLAGS		@ check for syscall tracing
+	cand.a	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+	bne	__sys_trace
+
+	csub.a	scno, #__NR_syscalls		@ check upper syscall limit
+	adr	lr, ret_fast_syscall		@ return address
+	bea	1f
+	ldw	pc, [tbl+], scno << #2		@ call sys_* routine
+1:
+	add	r1, sp, #S_OFF
+2:	mov	why, #0				@ no longer a real syscall
+	b	sys_ni_syscall			@ not private func
+
+	/*
+	 * This is the really slow path.  We're going to be doing
+	 * context switches, and waiting for our parent to respond.
+	 */
+__sys_trace:
+	mov	r2, scno
+	add	r1, sp, #S_OFF
+	mov	r0, #0				@ trace entry [IP = 0]
+	b.l	syscall_trace
+
+	adr	lr, __sys_trace_return		@ return address
+	mov	scno, r0			@ syscall number (possibly new)
+	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	csub.a	scno, #__NR_syscalls		@ check upper syscall limit
+	bea	2b
+	ldm	(r0 - r3), [r1]+		@ have to reload r0 - r3
+	ldw	pc, [tbl+], scno << #2		@ call sys_* routine
+
+__sys_trace_return:
+	stw.w	r0, [sp+], #S_R0 + S_OFF	@ save returned r0
+	mov	r2, scno
+	mov	r1, sp
+	mov	r0, #1				@ trace exit [IP = 1]
+	b.l	syscall_trace
+	b	ret_slow_syscall
+
+	.align	5
+#ifdef CONFIG_ALIGNMENT_TRAP
+	.type	__cr_alignment, #object
+__cr_alignment:
+	.word	cr_alignment
+#endif
+	.ltorg
+
+ENTRY(sys_execve)
+		add	r3, sp, #S_OFF
+		b	__sys_execve
+ENDPROC(sys_execve)
+
+ENTRY(sys_clone)
+		add	ip, sp, #S_OFF
+		stw	ip, [sp+], #4
+		b	__sys_clone
+ENDPROC(sys_clone)
+
+ENTRY(sys_rt_sigreturn)
+		add	r0, sp, #S_OFF
+		mov	why, #0		@ prevent syscall restart handling
+		b	__sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn)
+
+ENTRY(sys_sigaltstack)
+		ldw	r2, [sp+], #S_OFF + S_SP
+		b	do_sigaltstack
+ENDPROC(sys_sigaltstack)
+
+	__INIT
+
+/*
+ * Vector stubs.
+ *
+ * This code is copied to 0xffff0200 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not
+ * exceed 0x300 bytes.
+ *
+ * Common stub entry macro:
+ *   Enter in INTR mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
+ *
+ * SP points to a minimal amount of processor-private memory, the address
+ * of which is copied into r0 for the mode specific abort handler.
+ */
+	.macro	vector_stub, name, mode
+	.align	5
+
+vector_\name:
+	@
+	@ Save r0, lr_<exception> (parent PC) and bsr_<exception>
+	@ (parent ASR)
+	@
+	stw	r0, [sp]
+	stw	lr, [sp+], #4		@ save r0, lr
+	mov	lr, bsr
+	stw	lr, [sp+], #8		@ save bsr
+
+	@
+	@ Prepare for PRIV mode.  INTRs remain disabled.
+	@
+	mov	r0, asr
+	xor	r0, r0, #(\mode ^ PRIV_MODE)
+	mov.a	bsr, r0
+
+	@
+	@ the branch table must immediately follow this code
+	@
+	and	lr, lr, #0x03
+	add	lr, lr, #1
+	mov	r0, sp
+	ldw	lr, [pc+], lr << #2
+	mov.a	pc, lr			@ branch to handler in PRIV mode
+ENDPROC(vector_\name)
+	.align	2
+	@ handler addresses follow this label
+	.endm
+
+	.globl	__stubs_start
+__stubs_start:
+/*
+ * Interrupt dispatcher
+ */
+	vector_stub	intr, INTR_MODE
+
+	.long	__intr_user			@  0  (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2
+	.long	__intr_priv			@  3  (PRIV)
+
+/*
+ * Data abort dispatcher
+ * Enter in ABT mode, bsr = USER ASR, lr = USER PC
+ */
+	vector_stub	dabt, ABRT_MODE
+
+	.long	__dabt_user			@  0  (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2  (INTR)
+	.long	__dabt_priv			@  3  (PRIV)
+
+/*
+ * Prefetch abort dispatcher
+ * Enter in ABT mode, bsr = USER ASR, lr = USER PC
+ */
+	vector_stub	pabt, ABRT_MODE
+
+	.long	__pabt_user			@  0 (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2 (INTR)
+	.long	__pabt_priv			@  3 (PRIV)
+
+/*
+ * Undef instr entry dispatcher
+ * Enter in EXTN mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
+ */
+	vector_stub	extn, EXTN_MODE
+
+	.long	__extn_user			@  0 (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2 (INTR)
+	.long	__extn_priv			@  3 (PRIV)
+
+/*
+ * We group all the following data together to optimise
+ * for CPUs with separate I & D caches.
+ */
+	.align	5
+
+.LCvswi:
+	.word	vector_swi
+
+	.globl	__stubs_end
+__stubs_end:
+
+	.equ	stubs_offset, __vectors_start + 0x200 - __stubs_start
+
+	.globl	__vectors_start
+__vectors_start:
+	jepriv	SYS_ERROR0
+	b	vector_extn + stubs_offset
+	ldw	pc, .LCvswi + stubs_offset
+	b	vector_pabt + stubs_offset
+	b	vector_dabt + stubs_offset
+	jepriv	SYS_ERROR0
+	b	vector_intr + stubs_offset
+	jepriv	SYS_ERROR0
+
+	.globl	__vectors_end
+__vectors_end:
+
+	.data
+
+	.globl	cr_alignment
+	.globl	cr_no_alignment
+cr_alignment:
+	.space	4
+cr_no_alignment:
+	.space	4
diff --git a/arch/unicore32/kernel/fpu-ucf64.c b/arch/unicore32/kernel/fpu-ucf64.c
new file mode 100644
index 0000000..282a60a
--- /dev/null
+++ b/arch/unicore32/kernel/fpu-ucf64.c
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/unicore32/kernel/fpu-ucf64.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/fpu-ucf64.h>
+
+/*
+ * A special flag to tell the normalisation code not to normalise.
+ */
+#define F64_NAN_FLAG	0x100
+
+/*
+ * A bit pattern used to indicate the initial (unset) value of the
+ * exception mask, in case nothing handles an instruction.  This
+ * doesn't include the NAN flag, which get masked out before
+ * we check for an error.
+ */
+#define F64_EXCEPTION_ERROR	((u32)-1 & ~F64_NAN_FLAG)
+
+/*
+ * Since we aren't building with -mfpu=f64, we need to code
+ * these instructions using their MRC/MCR equivalents.
+ */
+#define f64reg(_f64_) #_f64_
+
+#define cff(_f64_) ({			\
+	u32 __v;			\
+	asm("cff %0, " f64reg(_f64_) "@ fmrx	%0, " #_f64_	\
+	    : "=r" (__v) : : "cc");	\
+	__v;				\
+	})
+
+#define ctf(_f64_, _var_)		\
+	asm("ctf %0, " f64reg(_f64_) "@ fmxr	" #_f64_ ", %0"	\
+	   : : "r" (_var_) : "cc")
+
+/*
+ * Raise a SIGFPE for the current process.
+ * sicode describes the signal being raised.
+ */
+void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	memset(&info, 0, sizeof(info));
+
+	info.si_signo = SIGFPE;
+	info.si_code = sicode;
+	info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
+
+	/*
+	 * This is the same as NWFPE, because it's not clear what
+	 * this is used for
+	 */
+	current->thread.error_code = 0;
+	current->thread.trap_no = 6;
+
+	send_sig_info(SIGFPE, &info, current);
+}
+
+/*
+ * Handle exceptions of UniCore-F64.
+ */
+void ucf64_exchandler(u32 inst, u32 fpexc, struct pt_regs *regs)
+{
+	u32 tmp = fpexc;
+	u32 exc = F64_EXCEPTION_ERROR & fpexc;
+
+	pr_debug("UniCore-F64: instruction %08x fpscr %08x\n",
+			inst, fpexc);
+
+	if (exc & FPSCR_CMPINSTR_BIT) {
+		if (exc & FPSCR_CON)
+			tmp |= FPSCR_CON;
+		else
+			tmp &= ~(FPSCR_CON);
+		exc &= ~(FPSCR_CMPINSTR_BIT | FPSCR_CON);
+	} else {
+		pr_debug(KERN_ERR "UniCore-F64 Error: unhandled exceptions\n");
+		pr_debug(KERN_ERR "UniCore-F64 FPSCR 0x%08x INST 0x%08x\n",
+				cff(FPSCR), inst);
+
+		ucf64_raise_sigfpe(0, regs);
+		return;
+	}
+
+	/*
+	 * Update the FPSCR with the additional exception flags.
+	 * Comparison instructions always return at least one of
+	 * these flags set.
+	 */
+	tmp &= ~(FPSCR_TRAP | FPSCR_IOS | FPSCR_OFS | FPSCR_UFS |
+			FPSCR_IXS | FPSCR_HIS | FPSCR_IOC | FPSCR_OFC |
+			FPSCR_UFC | FPSCR_IXC | FPSCR_HIC);
+
+	tmp |= exc;
+	ctf(FPSCR, tmp);
+}
+
+/*
+ * F64 support code initialisation.
+ */
+static int __init ucf64_init(void)
+{
+	ctf(FPSCR, 0x0);     /* FPSCR_UFE | FPSCR_NDE perhaps better */
+
+	printk(KERN_INFO "Enable UniCore-F64 support.\n");
+
+	return 0;
+}
+
+late_initcall(ucf64_init);
diff --git a/arch/unicore32/kernel/gpio.c b/arch/unicore32/kernel/gpio.c
new file mode 100644
index 0000000..cb12ec3
--- /dev/null
+++ b/arch/unicore32/kernel/gpio.c
@@ -0,0 +1,122 @@
+/*
+ * linux/arch/unicore32/kernel/gpio.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/* in FPGA, no GPIO support */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <mach/hardware.h>
+
+#ifdef CONFIG_LEDS
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+
+static const struct gpio_led puv3_gpio_leds[] = {
+	{ .name = "cpuhealth", .gpio = GPO_CPU_HEALTH, .active_low = 0,
+		.default_trigger = "heartbeat",	},
+	{ .name = "hdd_led", .gpio = GPO_HDD_LED, .active_low = 1,
+		.default_trigger = "ide-disk", },
+};
+
+static const struct gpio_led_platform_data puv3_gpio_led_data = {
+	.num_leds =	ARRAY_SIZE(puv3_gpio_leds),
+	.leds =		(void *) puv3_gpio_leds,
+};
+
+static struct platform_device puv3_gpio_gpio_leds = {
+	.name =		"leds-gpio",
+	.id =		-1,
+	.dev = {
+		.platform_data = (void *) &puv3_gpio_led_data,
+	}
+};
+
+static int __init puv3_gpio_leds_init(void)
+{
+	platform_device_register(&puv3_gpio_gpio_leds);
+	return 0;
+}
+
+device_initcall(puv3_gpio_leds_init);
+#endif
+
+static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return readl(GPIO_GPLR) & GPIO_GPIO(offset);
+}
+
+static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (value)
+		writel(GPIO_GPIO(offset), GPIO_GPSR);
+	else
+		writel(GPIO_GPIO(offset), GPIO_GPCR);
+}
+
+static int puv3_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	writel(readl(GPIO_GPDR) & ~GPIO_GPIO(offset), GPIO_GPDR);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int puv3_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	puv3_gpio_set(chip, offset, value);
+	writel(readl(GPIO_GPDR) | GPIO_GPIO(offset), GPIO_GPDR);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static struct gpio_chip puv3_gpio_chip = {
+	.label			= "gpio",
+	.direction_input	= puv3_direction_input,
+	.direction_output	= puv3_direction_output,
+	.set			= puv3_gpio_set,
+	.get			= puv3_gpio_get,
+	.base			= 0,
+	.ngpio			= GPIO_MAX + 1,
+};
+
+void __init puv3_init_gpio(void)
+{
+	writel(GPIO_DIR, GPIO_GPDR);
+#if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)	\
+	|| defined(CONFIG_PUV3_DB0913)
+	gpio_set_value(GPO_WIFI_EN, 1);
+	gpio_set_value(GPO_HDD_LED, 1);
+	gpio_set_value(GPO_VGA_EN, 1);
+	gpio_set_value(GPO_LCD_EN, 1);
+	gpio_set_value(GPO_CAM_PWR_EN, 0);
+	gpio_set_value(GPO_LCD_VCC_EN, 1);
+	gpio_set_value(GPO_SOFT_OFF, 1);
+	gpio_set_value(GPO_BT_EN, 1);
+	gpio_set_value(GPO_FAN_ON, 0);
+	gpio_set_value(GPO_SPKR, 0);
+	gpio_set_value(GPO_CPU_HEALTH, 1);
+	gpio_set_value(GPO_LAN_SEL, 1);
+/*
+ * DO NOT modify the GPO_SET_V1 and GPO_SET_V2 in kernel
+ *	gpio_set_value(GPO_SET_V1, 1);
+ *	gpio_set_value(GPO_SET_V2, 1);
+ */
+#endif
+	gpiochip_add(&puv3_gpio_chip);
+}
diff --git a/arch/unicore32/kernel/head.S b/arch/unicore32/kernel/head.S
new file mode 100644
index 0000000..92255f3
--- /dev/null
+++ b/arch/unicore32/kernel/head.S
@@ -0,0 +1,252 @@
+/*
+ * linux/arch/unicore32/kernel/head.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/assembler.h>
+#include <asm/ptrace.h>
+#include <generated/asm-offsets.h>
+#include <asm/memory.h>
+#include <asm/thread_info.h>
+#include <asm/system.h>
+#include <asm/pgtable-hwdef.h>
+
+#if (PHYS_OFFSET & 0x003fffff)
+#error "PHYS_OFFSET must be at an even 4MiB boundary!"
+#endif
+
+#define KERNEL_RAM_VADDR	(PAGE_OFFSET + KERNEL_IMAGE_START)
+#define KERNEL_RAM_PADDR	(PHYS_OFFSET + KERNEL_IMAGE_START)
+
+#define KERNEL_PGD_PADDR	(KERNEL_RAM_PADDR - 0x1000)
+#define KERNEL_PGD_VADDR	(KERNEL_RAM_VADDR - 0x1000)
+
+#define KERNEL_START		KERNEL_RAM_VADDR
+#define KERNEL_END		_end
+
+/*
+ * swapper_pg_dir is the virtual address of the initial page table.
+ * We place the page tables 4K below KERNEL_RAM_VADDR.  Therefore, we must
+ * make sure that KERNEL_RAM_VADDR is correctly set.  Currently, we expect
+ * the least significant 16 bits to be 0x8000, but we could probably
+ * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x1000.
+ */
+#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
+#error KERNEL_RAM_VADDR must start at 0xXXXX8000
+#endif
+
+	.globl	swapper_pg_dir
+	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x1000
+
+/*
+ * Kernel startup entry point.
+ * ---------------------------
+ *
+ * This is normally called from the decompressor code.  The requirements
+ * are: MMU = off, D-cache = off, I-cache = dont care
+ *
+ * This code is mostly position independent, so if you link the kernel at
+ * 0xc0008000, you call this at __pa(0xc0008000).
+ */
+	__HEAD
+ENTRY(stext)
+	@ set asr
+	mov	r0, #PRIV_MODE			@ ensure priv mode
+	or	r0, #PSR_R_BIT | PSR_I_BIT	@ disable irqs
+	mov.a	asr, r0
+
+	@ process identify
+	movc	r0, p0.c0, #0			@ cpuid
+	movl	r1, 0xff00ffff			@ mask
+	movl	r2, 0x4d000863			@ value
+	and	r0, r1, r0
+	cxor.a	r0, r2
+	bne	__error_p			@ invalid processor id
+
+	/*
+	 * Clear the 4K level 1 swapper page table
+	 */
+	movl	r0, #KERNEL_PGD_PADDR		@ page table address
+	mov	r1, #0
+	add	r2, r0, #0x1000
+101:	stw.w	r1, [r0]+, #4
+	stw.w	r1, [r0]+, #4
+	stw.w	r1, [r0]+, #4
+	stw.w	r1, [r0]+, #4
+	cxor.a	r0, r2
+	bne	101b
+
+	movl	r4, #KERNEL_PGD_PADDR		@ page table address
+	mov	r7, #PMD_TYPE_SECT | PMD_PRESENT	@ page size: section
+	or	r7, r7, #PMD_SECT_CACHEABLE		@ cacheable
+	or	r7, r7, #PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC
+
+	/*
+	 * Create identity mapping for first 4MB of kernel to
+	 * cater for the MMU enable.  This identity mapping
+	 * will be removed by paging_init().  We use our current program
+	 * counter to determine corresponding section base address.
+	 */
+	mov	r6, pc
+	mov	r6, r6 >> #22			@ start of kernel section
+	or	r1, r7, r6 << #22		@ flags + kernel base
+	stw	r1, [r4+], r6 << #2		@ identity mapping
+
+	/*
+	 * Now setup the pagetables for our kernel direct
+	 * mapped region.
+	 */
+	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 20
+	stw.w	r1, [r0+], #(KERNEL_START & 0x00c00000) >> 20
+	movl	r6, #(KERNEL_END - 1)
+	add	r0, r0, #4
+	add	r6, r4, r6 >> #20
+102:	csub.a	r0, r6
+	add	r1, r1, #1 << 22
+	bua	103f
+	stw.w	r1, [r0]+, #4
+	b	102b
+103:
+	/*
+	 * Then map first 4MB of ram in case it contains our boot params.
+	 */
+	add	r0, r4, #PAGE_OFFSET >> 20
+	or	r6, r7, #(PHYS_OFFSET & 0xffc00000)
+	stw	r6, [r0]
+
+	ldw	r15, __switch_data		@ address to jump to after
+
+	/*
+	 * Initialise TLB, Caches, and MMU state ready to switch the MMU
+	 * on.
+	 */
+	mov	r0, #0
+	movc	p0.c5, r0, #28			@ cache invalidate all
+	nop8
+	movc	p0.c6, r0, #6			@ TLB invalidate all
+	nop8
+
+	/*
+	 * ..V. .... ..TB IDAM
+	 * ..1. .... ..01 1111
+	 */
+	movl	r0, #0x201f			@ control register setting
+
+	/*
+	 * Setup common bits before finally enabling the MMU.  Essentially
+	 * this is just loading the page table pointer and domain access
+	 * registers.
+	 */
+	#ifndef CONFIG_ALIGNMENT_TRAP
+		andn	r0, r0, #CR_A
+	#endif
+	#ifdef CONFIG_CPU_DCACHE_DISABLE
+		andn	r0, r0, #CR_D
+	#endif
+	#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+		andn	r0, r0, #CR_B
+	#endif
+	#ifdef CONFIG_CPU_ICACHE_DISABLE
+		andn	r0, r0, #CR_I
+	#endif
+
+	movc	p0.c2, r4, #0			@ set pgd
+	b	__turn_mmu_on
+ENDPROC(stext)
+
+/*
+ * Enable the MMU.  This completely changes the stucture of the visible
+ * memory space.  You will not be able to trace execution through this.
+ *
+ *  r0  = cp#0 control register
+ *  r15 = *virtual* address to jump to upon completion
+ */
+	.align	5
+__turn_mmu_on:
+	mov	r0, r0
+	movc	p0.c1, r0, #0			@ write control reg
+	nop					@ fetch inst by phys addr
+	mov	pc, r15
+	nop8					@ fetch inst by phys addr
+ENDPROC(__turn_mmu_on)
+
+/*
+ * Setup the initial page tables.  We only setup the barest
+ * amount which are required to get the kernel running, which
+ * generally means mapping in the kernel code.
+ *
+ * r9  = cpuid
+ * r10 = procinfo
+ *
+ * Returns:
+ *  r0, r3, r6, r7 corrupted
+ *  r4 = physical page table address
+ */
+	.ltorg
+
+	.align	2
+	.type	__switch_data, %object
+__switch_data:
+	.long	__mmap_switched
+	.long	__bss_start			@ r6
+	.long	_end				@ r7
+	.long	cr_alignment			@ r8
+	.long	init_thread_union + THREAD_START_SP @ sp
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ *
+ *  r0  = cp#0 control register
+ */
+__mmap_switched:
+	adr	r3, __switch_data + 4
+
+	ldm.w	(r6, r7, r8), [r3]+
+	ldw	sp, [r3]
+
+	mov	fp, #0				@ Clear BSS (and zero fp)
+203:	csub.a	r6, r7
+	bea	204f
+	stw.w	fp, [r6]+,#4
+	b	203b
+204:
+	andn	r1, r0, #CR_A			@ Clear 'A' bit
+	stm	(r0, r1), [r8]+			@ Save control register values
+	b	start_kernel
+ENDPROC(__mmap_switched)
+
+/*
+ * Exception handling.  Something went wrong and we can't proceed.  We
+ * ought to tell the user, but since we don't have any guarantee that
+ * we're even running on the right architecture, we do virtually nothing.
+ *
+ * If CONFIG_DEBUG_LL is set we try to print out something about the error
+ * and hope for the best (useful if bootloader fails to pass a proper
+ * machine ID for example).
+ */
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+	adr	r0, str_p1
+	b.l	printascii
+	mov	r0, r9
+	b.l	printhex8
+	adr	r0, str_p2
+	b.l	printascii
+901:	nop8
+	b	901b
+str_p1:	.asciz	"\nError: unrecognized processor variant (0x"
+str_p2:	.asciz	").\n"
+	.align
+#endif
+ENDPROC(__error_p)
+
diff --git a/arch/unicore32/kernel/hibernate.c b/arch/unicore32/kernel/hibernate.c
new file mode 100644
index 0000000..7d0f0b7
--- /dev/null
+++ b/arch/unicore32/kernel/hibernate.c
@@ -0,0 +1,160 @@
+/*
+ *  linux/arch/unicore32/kernel/hibernate.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/gfp.h>
+#include <linux/suspend.h>
+#include <linux/bootmem.h>
+
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/suspend.h>
+
+#include "mach/pm.h"
+
+/* Pointer to the temporary resume page tables */
+pgd_t *resume_pg_dir;
+
+struct swsusp_arch_regs swsusp_arch_regs_cpu0;
+
+/*
+ * Create a middle page table on a resume-safe page and put a pointer to it in
+ * the given global directory entry.  This only returns the gd entry
+ * in non-PAE compilation mode, since the middle layer is folded.
+ */
+static pmd_t *resume_one_md_table_init(pgd_t *pgd)
+{
+	pud_t *pud;
+	pmd_t *pmd_table;
+
+	pud = pud_offset(pgd, 0);
+	pmd_table = pmd_offset(pud, 0);
+
+	return pmd_table;
+}
+
+/*
+ * Create a page table on a resume-safe page and place a pointer to it in
+ * a middle page directory entry.
+ */
+static pte_t *resume_one_page_table_init(pmd_t *pmd)
+{
+	if (pmd_none(*pmd)) {
+		pte_t *page_table = (pte_t *)get_safe_page(GFP_ATOMIC);
+		if (!page_table)
+			return NULL;
+
+		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_KERNEL_TABLE));
+
+		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+
+		return page_table;
+	}
+
+	return pte_offset_kernel(pmd, 0);
+}
+
+/*
+ * This maps the physical memory to kernel virtual address space, a total
+ * of max_low_pfn pages, by creating page tables starting from address
+ * PAGE_OFFSET.  The page tables are allocated out of resume-safe pages.
+ */
+static int resume_physical_mapping_init(pgd_t *pgd_base)
+{
+	unsigned long pfn;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int pgd_idx, pmd_idx;
+
+	pgd_idx = pgd_index(PAGE_OFFSET);
+	pgd = pgd_base + pgd_idx;
+	pfn = 0;
+
+	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+		pmd = resume_one_md_table_init(pgd);
+		if (!pmd)
+			return -ENOMEM;
+
+		if (pfn >= max_low_pfn)
+			continue;
+
+		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) {
+			pte_t *max_pte;
+
+			if (pfn >= max_low_pfn)
+				break;
+
+			/* Map with normal page tables.
+			 * NOTE: We can mark everything as executable here
+			 */
+			pte = resume_one_page_table_init(pmd);
+			if (!pte)
+				return -ENOMEM;
+
+			max_pte = pte + PTRS_PER_PTE;
+			for (; pte < max_pte; pte++, pfn++) {
+				if (pfn >= max_low_pfn)
+					break;
+
+				set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+			}
+		}
+	}
+
+	return 0;
+}
+
+static inline void resume_init_first_level_page_table(pgd_t *pg_dir)
+{
+}
+
+int swsusp_arch_resume(void)
+{
+	int error;
+
+	resume_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
+	if (!resume_pg_dir)
+		return -ENOMEM;
+
+	resume_init_first_level_page_table(resume_pg_dir);
+	error = resume_physical_mapping_init(resume_pg_dir);
+	if (error)
+		return error;
+
+	/* We have got enough memory and from now on we cannot recover */
+	restore_image(resume_pg_dir, restore_pblist);
+	return 0;
+}
+
+/*
+ *	pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+	unsigned long end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
+
+	return (pfn >= begin_pfn) && (pfn < end_pfn);
+}
+
+void save_processor_state(void)
+{
+}
+
+void restore_processor_state(void)
+{
+	local_flush_tlb_all();
+}
diff --git a/arch/unicore32/kernel/hibernate_asm.S b/arch/unicore32/kernel/hibernate_asm.S
new file mode 100644
index 0000000..cc3c652
--- /dev/null
+++ b/arch/unicore32/kernel/hibernate_asm.S
@@ -0,0 +1,117 @@
+/*
+ * linux/arch/unicore32/kernel/hibernate_asm.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/sys.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <generated/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/assembler.h>
+
+@ restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist)
+@ r0: resume_pg_dir
+@ r1: restore_pblist
+@ copy restore_pblist pages
+@ restore registers from swsusp_arch_regs_cpu0
+@
+ENTRY(restore_image)
+	sub	r0, r0, #PAGE_OFFSET
+	mov	r5, #0
+	movc	p0.c6, r5, #6	@invalidate ITLB & DTLB
+	movc	p0.c2, r0, #0
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	.p2align 4,,7
+101:
+	csub.a	r1, #0
+	beq	109f
+
+	ldw	r6, [r1+], #PBE_ADDRESS
+	ldw	r7, [r1+], #PBE_ORIN_ADDRESS
+
+	movl	ip, #128
+102:	ldm.w	(r8 - r15), [r6]+
+	stm.w	(r8 - r15), [r7]+
+	sub.a	ip, ip, #1
+	bne	102b
+
+	ldw	r1, [r1+], #PBE_NEXT
+	b	101b
+
+	.p2align 4,,7
+109:
+	/* go back to the original page tables */
+	ldw	r0, =swapper_pg_dir
+	sub	r0, r0, #PAGE_OFFSET
+	mov	r5, #0
+	movc	p0.c6, r5, #6
+	movc	p0.c2, r0, #0
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_FPSTATE
+	lfm.w	(f0  - f7 ), [ip]+
+	lfm.w	(f8  - f15), [ip]+
+	lfm.w	(f16 - f23), [ip]+
+	lfm.w	(f24 - f31), [ip]+
+	ldw	r4, [ip]
+	ctf	r4, s31
+#endif
+	mov	r0, #0x0
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_CPU
+	ldm.w	(r4 - r15), [ip]+
+	ldm	(r16 - r27, sp, pc), [ip]+	@ Load all regs saved previously
+
+	.align	2
+1:	.long	swsusp_arch_regs_cpu0
+
+
+@ swsusp_arch_suspend()
+@ - prepare pc for resume, return from function without swsusp_save on resume
+@ - save registers in swsusp_arch_regs_cpu0
+@ - call swsusp_save write suspend image
+
+ENTRY(swsusp_arch_suspend)
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_CPU
+	stm.w	(r4 - r15), [ip]+
+	stm.w	(r16 - r27, sp, lr), [ip]+
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_FPSTATE
+	sfm.w	(f0  - f7 ), [ip]+
+	sfm.w	(f8  - f15), [ip]+
+	sfm.w	(f16 - f23), [ip]+
+	sfm.w	(f24 - f31), [ip]+
+	cff	r4, s31
+	stw	r4, [ip]
+#endif
+	b	swsusp_save			@ no return
+
+1:	.long	swsusp_arch_regs_cpu0
diff --git a/arch/unicore32/kernel/init_task.c b/arch/unicore32/kernel/init_task.c
new file mode 100644
index 0000000..a35a1e5
--- /dev/null
+++ b/arch/unicore32/kernel/init_task.c
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/unicore32/kernel/init_task.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+#include <linux/uaccess.h>
+
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ *
+ * The things we do for performance..
+ */
+union thread_union init_thread_union __init_task_data = {
+	INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff --git a/arch/unicore32/kernel/irq.c b/arch/unicore32/kernel/irq.c
new file mode 100644
index 0000000..b23624c
--- /dev/null
+++ b/arch/unicore32/kernel/irq.c
@@ -0,0 +1,426 @@
+/*
+ * linux/arch/unicore32/kernel/irq.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/kallsyms.h>
+#include <linux/proc_fs.h>
+#include <linux/sysdev.h>
+#include <linux/gpio.h>
+
+#include <asm/system.h>
+#include <mach/hardware.h>
+
+#include "setup.h"
+
+/*
+ * PKUnity GPIO edge detection for IRQs:
+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+ * Use this instead of directly setting GRER/GFER.
+ */
+static int GPIO_IRQ_rising_edge;
+static int GPIO_IRQ_falling_edge;
+static int GPIO_IRQ_mask = 0;
+
+#define GPIO_MASK(irq)		(1 << (irq - IRQ_GPIO0))
+
+static int puv3_gpio_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int mask;
+
+	if (d->irq < IRQ_GPIOHIGH)
+		mask = 1 << d->irq;
+	else
+		mask = GPIO_MASK(d->irq);
+
+	if (type == IRQ_TYPE_PROBE) {
+		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
+			return 0;
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		GPIO_IRQ_rising_edge |= mask;
+	else
+		GPIO_IRQ_rising_edge &= ~mask;
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		GPIO_IRQ_falling_edge |= mask;
+	else
+		GPIO_IRQ_falling_edge &= ~mask;
+
+	writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
+	writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+
+	return 0;
+}
+
+/*
+ * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 7.
+ */
+static void puv3_low_gpio_ack(struct irq_data *d)
+{
+	writel((1 << d->irq), GPIO_GEDR);
+}
+
+static void puv3_low_gpio_mask(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
+}
+
+static void puv3_low_gpio_unmask(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
+}
+
+static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
+{
+	if (on)
+		writel(readl(PM_PWER) | (1 << d->irq), PM_PWER);
+	else
+		writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER);
+	return 0;
+}
+
+static struct irq_chip puv3_low_gpio_chip = {
+	.name		= "GPIO-low",
+	.irq_ack	= puv3_low_gpio_ack,
+	.irq_mask	= puv3_low_gpio_mask,
+	.irq_unmask	= puv3_low_gpio_unmask,
+	.irq_set_type	= puv3_gpio_type,
+	.irq_set_wake	= puv3_low_gpio_wake,
+};
+
+/*
+ * IRQ8 (GPIO0 through 27) handler.  We enter here with the
+ * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
+ * and call the handler.
+ */
+static void
+puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int mask;
+
+	mask = readl(GPIO_GEDR);
+	do {
+		/*
+		 * clear down all currently active IRQ sources.
+		 * We will be processing them all.
+		 */
+		writel(mask, GPIO_GEDR);
+
+		irq = IRQ_GPIO0;
+		do {
+			if (mask & 1)
+				generic_handle_irq(irq);
+			mask >>= 1;
+			irq++;
+		} while (mask);
+		mask = readl(GPIO_GEDR);
+	} while (mask);
+}
+
+/*
+ * GPIO0-27 edge IRQs need to be handled specially.
+ * In addition, the IRQs are all collected up into one bit in the
+ * interrupt controller registers.
+ */
+static void puv3_high_gpio_ack(struct irq_data *d)
+{
+	unsigned int mask = GPIO_MASK(d->irq);
+
+	writel(mask, GPIO_GEDR);
+}
+
+static void puv3_high_gpio_mask(struct irq_data *d)
+{
+	unsigned int mask = GPIO_MASK(d->irq);
+
+	GPIO_IRQ_mask &= ~mask;
+
+	writel(readl(GPIO_GRER) & ~mask, GPIO_GRER);
+	writel(readl(GPIO_GFER) & ~mask, GPIO_GFER);
+}
+
+static void puv3_high_gpio_unmask(struct irq_data *d)
+{
+	unsigned int mask = GPIO_MASK(d->irq);
+
+	GPIO_IRQ_mask |= mask;
+
+	writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
+	writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+}
+
+static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
+{
+	if (on)
+		writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER);
+	else
+		writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER);
+	return 0;
+}
+
+static struct irq_chip puv3_high_gpio_chip = {
+	.name		= "GPIO-high",
+	.irq_ack	= puv3_high_gpio_ack,
+	.irq_mask	= puv3_high_gpio_mask,
+	.irq_unmask	= puv3_high_gpio_unmask,
+	.irq_set_type	= puv3_gpio_type,
+	.irq_set_wake	= puv3_high_gpio_wake,
+};
+
+/*
+ * We don't need to ACK IRQs on the PKUnity unless they're GPIOs
+ * this is for internal IRQs i.e. from 8 to 31.
+ */
+static void puv3_mask_irq(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
+}
+
+static void puv3_unmask_irq(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
+}
+
+/*
+ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+ */
+static int puv3_set_wake(struct irq_data *d, unsigned int on)
+{
+	if (d->irq == IRQ_RTCAlarm) {
+		if (on)
+			writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER);
+		else
+			writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static struct irq_chip puv3_normal_chip = {
+	.name		= "PKUnity-v3",
+	.irq_ack	= puv3_mask_irq,
+	.irq_mask	= puv3_mask_irq,
+	.irq_unmask	= puv3_unmask_irq,
+	.irq_set_wake	= puv3_set_wake,
+};
+
+static struct resource irq_resource = {
+	.name	= "irqs",
+	.start	= io_v2p(PKUNITY_INTC_BASE),
+	.end	= io_v2p(PKUNITY_INTC_BASE) + 0xFFFFF,
+};
+
+static struct puv3_irq_state {
+	unsigned int	saved;
+	unsigned int	icmr;
+	unsigned int	iclr;
+	unsigned int	iccr;
+} puv3_irq_state;
+
+static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct puv3_irq_state *st = &puv3_irq_state;
+
+	st->saved = 1;
+	st->icmr = readl(INTC_ICMR);
+	st->iclr = readl(INTC_ICLR);
+	st->iccr = readl(INTC_ICCR);
+
+	/*
+	 * Disable all GPIO-based interrupts.
+	 */
+	writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR);
+
+	/*
+	 * Set the appropriate edges for wakeup.
+	 */
+	writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER);
+	writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER);
+
+	/*
+	 * Clear any pending GPIO interrupts.
+	 */
+	writel(readl(GPIO_GEDR), GPIO_GEDR);
+
+	return 0;
+}
+
+static int puv3_irq_resume(struct sys_device *dev)
+{
+	struct puv3_irq_state *st = &puv3_irq_state;
+
+	if (st->saved) {
+		writel(st->iccr, INTC_ICCR);
+		writel(st->iclr, INTC_ICLR);
+
+		writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
+		writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+
+		writel(st->icmr, INTC_ICMR);
+	}
+	return 0;
+}
+
+static struct sysdev_class puv3_irq_sysclass = {
+	.name		= "pkunity-irq",
+	.suspend	= puv3_irq_suspend,
+	.resume		= puv3_irq_resume,
+};
+
+static struct sys_device puv3_irq_device = {
+	.id		= 0,
+	.cls		= &puv3_irq_sysclass,
+};
+
+static int __init puv3_irq_init_devicefs(void)
+{
+	sysdev_class_register(&puv3_irq_sysclass);
+	return sysdev_register(&puv3_irq_device);
+}
+
+device_initcall(puv3_irq_init_devicefs);
+
+void __init init_IRQ(void)
+{
+	unsigned int irq;
+
+	request_resource(&iomem_resource, &irq_resource);
+
+	/* disable all IRQs */
+	writel(0, INTC_ICMR);
+
+	/* all IRQs are IRQ, not REAL */
+	writel(0, INTC_ICLR);
+
+	/* clear all GPIO edge detects */
+	writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR);
+	writel(0, GPIO_GFER);
+	writel(0, GPIO_GRER);
+	writel(0x0FFFFFFF, GPIO_GEDR);
+
+	writel(1, INTC_ICCR);
+
+	for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
+		set_irq_chip(irq, &puv3_low_gpio_chip);
+		set_irq_handler(irq, handle_edge_irq);
+		irq_modify_status(irq,
+			IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
+			0);
+	}
+
+	for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
+		set_irq_chip(irq, &puv3_normal_chip);
+		set_irq_handler(irq, handle_level_irq);
+		irq_modify_status(irq,
+			IRQ_NOREQUEST | IRQ_NOAUTOEN,
+			IRQ_NOPROBE);
+	}
+
+	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
+		set_irq_chip(irq, &puv3_high_gpio_chip);
+		set_irq_handler(irq, handle_edge_irq);
+		irq_modify_status(irq,
+			IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
+			0);
+	}
+
+	/*
+	 * Install handler for GPIO 0-27 edge detect interrupts
+	 */
+	set_irq_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
+	set_irq_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
+
+#ifdef CONFIG_PUV3_GPIO
+	puv3_init_gpio();
+#endif
+}
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	int i = *(loff_t *) v, cpu;
+	struct irq_desc *desc;
+	struct irqaction *action;
+	unsigned long flags;
+
+	if (i == 0) {
+		char cpuname[12];
+
+		seq_printf(p, "    ");
+		for_each_present_cpu(cpu) {
+			sprintf(cpuname, "CPU%d", cpu);
+			seq_printf(p, " %10s", cpuname);
+		}
+		seq_putc(p, '\n');
+	}
+
+	if (i < nr_irqs) {
+		desc = irq_to_desc(i);
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
+		if (!action)
+			goto unlock;
+
+		seq_printf(p, "%3d: ", i);
+		for_each_present_cpu(cpu)
+			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
+		seq_printf(p, " %10s", desc->irq_data.chip->name ? : "-");
+		seq_printf(p, "  %s", action->name);
+		for (action = action->next; action; action = action->next)
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+unlock:
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
+	} else if (i == nr_irqs) {
+		seq_printf(p, "Error in interrupt!\n");
+	}
+	return 0;
+}
+
+/*
+ * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
+ * come via this function.  Instead, they should provide their
+ * own 'handler'
+ */
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+
+	/*
+	 * Some hardware gives randomly wrong interrupts.  Rather
+	 * than crashing, do something sensible.
+	 */
+	if (unlikely(irq >= nr_irqs)) {
+		if (printk_ratelimit())
+			printk(KERN_WARNING "Bad IRQ%u\n", irq);
+		ack_bad_irq(irq);
+	} else {
+		generic_handle_irq(irq);
+	}
+
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
diff --git a/arch/unicore32/kernel/ksyms.c b/arch/unicore32/kernel/ksyms.c
new file mode 100644
index 0000000..a897080
--- /dev/null
+++ b/arch/unicore32/kernel/ksyms.c
@@ -0,0 +1,99 @@
+/*
+ * linux/arch/unicore32/kernel/ksyms.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/sched.h>
+#include <linux/string.h>
+#include <linux/cryptohash.h>
+#include <linux/delay.h>
+#include <linux/in6.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/checksum.h>
+#include <asm/system.h>
+
+#include "ksyms.h"
+
+EXPORT_SYMBOL(__uc32_find_next_zero_bit);
+EXPORT_SYMBOL(__uc32_find_next_bit);
+
+EXPORT_SYMBOL(__backtrace);
+
+	/* platform dependent support */
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__const_udelay);
+
+	/* networking */
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+EXPORT_SYMBOL(__csum_ipv6_magic);
+
+	/* io */
+#ifndef __raw_readsb
+EXPORT_SYMBOL(__raw_readsb);
+#endif
+#ifndef __raw_readsw
+EXPORT_SYMBOL(__raw_readsw);
+#endif
+#ifndef __raw_readsl
+EXPORT_SYMBOL(__raw_readsl);
+#endif
+#ifndef __raw_writesb
+EXPORT_SYMBOL(__raw_writesb);
+#endif
+#ifndef __raw_writesw
+EXPORT_SYMBOL(__raw_writesw);
+#endif
+#ifndef __raw_writesl
+EXPORT_SYMBOL(__raw_writesl);
+#endif
+
+	/* string / mem functions */
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+
+	/* user mem (segment) */
+EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+
+EXPORT_SYMBOL(copy_page);
+
+EXPORT_SYMBOL(__copy_from_user);
+EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__clear_user);
+
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
+
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__bswapsi2);
+
diff --git a/arch/unicore32/kernel/ksyms.h b/arch/unicore32/kernel/ksyms.h
new file mode 100644
index 0000000..185cdc7
--- /dev/null
+++ b/arch/unicore32/kernel/ksyms.h
@@ -0,0 +1,15 @@
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler...  (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __ucmpdi2(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+extern void __bswapsi2(void);
diff --git a/arch/unicore32/kernel/module.c b/arch/unicore32/kernel/module.c
new file mode 100644
index 0000000..3e5a38d
--- /dev/null
+++ b/arch/unicore32/kernel/module.c
@@ -0,0 +1,152 @@
+/*
+ * linux/arch/unicore32/kernel/module.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/moduleloader.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/gfp.h>
+
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+
+void *module_alloc(unsigned long size)
+{
+	struct vm_struct *area;
+
+	size = PAGE_ALIGN(size);
+	if (!size)
+		return NULL;
+
+	area = __get_vm_area(size, VM_ALLOC, MODULES_VADDR, MODULES_END);
+	if (!area)
+		return NULL;
+
+	return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC);
+}
+
+void module_free(struct module *module, void *region)
+{
+	vfree(region);
+}
+
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
+{
+	return 0;
+}
+
+int
+apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
+	       unsigned int relindex, struct module *module)
+{
+	Elf32_Shdr *symsec = sechdrs + symindex;
+	Elf32_Shdr *relsec = sechdrs + relindex;
+	Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
+	Elf32_Rel *rel = (void *)relsec->sh_addr;
+	unsigned int i;
+
+	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
+		unsigned long loc;
+		Elf32_Sym *sym;
+		s32 offset;
+
+		offset = ELF32_R_SYM(rel->r_info);
+		if (offset < 0 || offset >
+				(symsec->sh_size / sizeof(Elf32_Sym))) {
+			printk(KERN_ERR "%s: bad relocation, "
+					"section %d reloc %d\n",
+					module->name, relindex, i);
+			return -ENOEXEC;
+		}
+
+		sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
+
+		if (rel->r_offset < 0 || rel->r_offset >
+				dstsec->sh_size - sizeof(u32)) {
+			printk(KERN_ERR "%s: out of bounds relocation, "
+				"section %d reloc %d offset %d size %d\n",
+				module->name, relindex, i, rel->r_offset,
+				dstsec->sh_size);
+			return -ENOEXEC;
+		}
+
+		loc = dstsec->sh_addr + rel->r_offset;
+
+		switch (ELF32_R_TYPE(rel->r_info)) {
+		case R_UNICORE_NONE:
+			/* ignore */
+			break;
+
+		case R_UNICORE_ABS32:
+			*(u32 *)loc += sym->st_value;
+			break;
+
+		case R_UNICORE_PC24:
+		case R_UNICORE_CALL:
+		case R_UNICORE_JUMP24:
+			offset = (*(u32 *)loc & 0x00ffffff) << 2;
+			if (offset & 0x02000000)
+				offset -= 0x04000000;
+
+			offset += sym->st_value - loc;
+			if (offset & 3 ||
+			    offset <= (s32)0xfe000000 ||
+			    offset >= (s32)0x02000000) {
+				printk(KERN_ERR
+				       "%s: relocation out of range, section "
+				       "%d reloc %d sym '%s'\n", module->name,
+				       relindex, i, strtab + sym->st_name);
+				return -ENOEXEC;
+			}
+
+			offset >>= 2;
+
+			*(u32 *)loc &= 0xff000000;
+			*(u32 *)loc |= offset & 0x00ffffff;
+			break;
+
+		default:
+			printk(KERN_ERR "%s: unknown relocation: %u\n",
+			       module->name, ELF32_R_TYPE(rel->r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int
+apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+		   unsigned int symindex, unsigned int relsec,
+		   struct module *module)
+{
+	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+	       module->name);
+	return -ENOEXEC;
+}
+
+int
+module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		struct module *module)
+{
+	return 0;
+}
+
+void
+module_arch_cleanup(struct module *mod)
+{
+}
diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
new file mode 100644
index 0000000..100eab8
--- /dev/null
+++ b/arch/unicore32/kernel/pci.c
@@ -0,0 +1,404 @@
+/*
+ * linux/arch/unicore32/kernel/pci.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  PCI bios-type initialisation for PCI machines
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+static int debug_pci;
+static int use_firmware;
+
+#define CONFIG_CMD(bus, devfn, where)	\
+	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static int
+puv3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+			int size, u32 *value)
+{
+	writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR);
+	switch (size) {
+	case 1:
+		*value = (readl(PCICFG_DATA) >> ((where & 3) * 8)) & 0xFF;
+		break;
+	case 2:
+		*value = (readl(PCICFG_DATA) >> ((where & 2) * 8)) & 0xFFFF;
+		break;
+	case 4:
+		*value = readl(PCICFG_DATA);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+puv3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+			int size, u32 value)
+{
+	writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR);
+	switch (size) {
+	case 1:
+		writel((readl(PCICFG_DATA) & ~FMASK(8, (where&3)*8))
+			| FIELD(value, 8, (where&3)*8), PCICFG_DATA);
+		break;
+	case 2:
+		writel((readl(PCICFG_DATA) & ~FMASK(16, (where&2)*8))
+			| FIELD(value, 16, (where&2)*8), PCICFG_DATA);
+		break;
+	case 4:
+		writel(value, PCICFG_DATA);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pci_puv3_ops = {
+	.read  = puv3_read_config,
+	.write = puv3_write_config,
+};
+
+void pci_puv3_preinit(void)
+{
+	printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n");
+	/* config PCI bridge base */
+	writel(io_v2p(PKUNITY_PCIBRI_BASE), PCICFG_BRIBASE);
+
+	writel(0, PCIBRI_AHBCTL0);
+	writel(io_v2p(PKUNITY_PCIBRI_BASE) | PCIBRI_BARx_MEM, PCIBRI_AHBBAR0);
+	writel(0xFFFF0000, PCIBRI_AHBAMR0);
+	writel(0, PCIBRI_AHBTAR0);
+
+	writel(PCIBRI_CTLx_AT, PCIBRI_AHBCTL1);
+	writel(io_v2p(PKUNITY_PCILIO_BASE) | PCIBRI_BARx_IO, PCIBRI_AHBBAR1);
+	writel(0xFFFF0000, PCIBRI_AHBAMR1);
+	writel(0x00000000, PCIBRI_AHBTAR1);
+
+	writel(PCIBRI_CTLx_PREF, PCIBRI_AHBCTL2);
+	writel(io_v2p(PKUNITY_PCIMEM_BASE) | PCIBRI_BARx_MEM, PCIBRI_AHBBAR2);
+	writel(0xF8000000, PCIBRI_AHBAMR2);
+	writel(0, PCIBRI_AHBTAR2);
+
+	writel(io_v2p(PKUNITY_PCIAHB_BASE) | PCIBRI_BARx_MEM, PCIBRI_BAR1);
+
+	writel(PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF, PCIBRI_PCICTL0);
+	writel(io_v2p(PKUNITY_PCIAHB_BASE) | PCIBRI_BARx_MEM, PCIBRI_PCIBAR0);
+	writel(0xF8000000, PCIBRI_PCIAMR0);
+	writel(PKUNITY_SDRAM_BASE, PCIBRI_PCITAR0);
+
+	writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD);
+}
+
+static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (dev->bus->number == 0) {
+#ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
+		if      (dev->devfn == 0x00)
+			return IRQ_PCIINTA;
+		else if (dev->devfn == 0x08)
+			return IRQ_PCIINTB;
+		else if (dev->devfn == 0x10)
+			return IRQ_PCIINTC;
+		else if (dev->devfn == 0x18)
+			return IRQ_PCIINTD;
+#endif
+#ifdef CONFIG_PUV3_DB0913 /* 3 pci slots */
+		if      (dev->devfn == 0x30)
+			return IRQ_PCIINTB;
+		else if (dev->devfn == 0x60)
+			return IRQ_PCIINTC;
+		else if (dev->devfn == 0x58)
+			return IRQ_PCIINTD;
+#endif
+#if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)
+		/* only support 2 pci devices */
+		if      (dev->devfn == 0x00)
+			return IRQ_PCIINTC; /* sata */
+#endif
+	}
+	return -1;
+}
+
+/*
+ * Only first 128MB of memory can be accessed via PCI.
+ * We use GFP_DMA to allocate safe buffers to do map/unmap.
+ * This is really ugly and we need a better way of specifying
+ * DMA-capable regions of memory.
+ */
+void __init puv3_pci_adjust_zones(unsigned long *zone_size,
+	unsigned long *zhole_size)
+{
+	unsigned int sz = SZ_128M >> PAGE_SHIFT;
+
+	/*
+	 * Only adjust if > 128M on current system
+	 */
+	if (zone_size[0] <= sz)
+		return;
+
+	zone_size[1] = zone_size[0] - sz;
+	zone_size[0] = sz;
+	zhole_size[1] = zhole_size[0];
+	zhole_size[0] = 0;
+}
+
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	if (debug_pci)
+		printk(KERN_DEBUG "PCI: Assigning IRQ %02d to %s\n",
+				irq, pci_name(dev));
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * If the bus contains any of these devices, then we must not turn on
+ * parity checking of any kind.
+ */
+static inline int pdev_bad_for_parity(struct pci_dev *dev)
+{
+	return 0;
+}
+
+/*
+ * pcibios_fixup_bus - Called after each bus is probed,
+ * but before its children are examined.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	u16 features = PCI_COMMAND_SERR
+		| PCI_COMMAND_PARITY
+		| PCI_COMMAND_FAST_BACK;
+
+	bus->resource[0] = &ioport_resource;
+	bus->resource[1] = &iomem_resource;
+
+	/*
+	 * Walk the devices on this bus, working out what we can
+	 * and can't support.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 status;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+
+		/*
+		 * If any device on this bus does not support fast back
+		 * to back transfers, then the bus as a whole is not able
+		 * to support them.  Having fast back to back transfers
+		 * on saves us one PCI cycle per transaction.
+		 */
+		if (!(status & PCI_STATUS_FAST_BACK))
+			features &= ~PCI_COMMAND_FAST_BACK;
+
+		if (pdev_bad_for_parity(dev))
+			features &= ~(PCI_COMMAND_SERR
+					| PCI_COMMAND_PARITY);
+
+		switch (dev->class >> 8) {
+		case PCI_CLASS_BRIDGE_PCI:
+			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
+			status |= PCI_BRIDGE_CTL_PARITY
+				| PCI_BRIDGE_CTL_MASTER_ABORT;
+			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
+				| PCI_BRIDGE_CTL_FAST_BACK);
+			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
+			break;
+
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+					&status);
+			status |= PCI_CB_BRIDGE_CTL_PARITY
+				| PCI_CB_BRIDGE_CTL_MASTER_ABORT;
+			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+					status);
+			break;
+		}
+	}
+
+	/*
+	 * Now walk the devices again, this time setting them up.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 cmd;
+
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd |= features;
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+				      L1_CACHE_BYTES >> 2);
+	}
+
+	/*
+	 * Propagate the flags to the PCI bridge.
+	 */
+	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		if (features & PCI_COMMAND_FAST_BACK)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+		if (features & PCI_COMMAND_PARITY)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
+	}
+
+	/*
+	 * Report what we did for this bus
+	 */
+	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
+		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
+}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+#endif
+
+static int __init pci_common_init(void)
+{
+	struct pci_bus *puv3_bus;
+
+	pci_puv3_preinit();
+
+	puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
+
+	if (!puv3_bus)
+		panic("PCI: unable to scan bus!");
+
+	pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
+
+	if (!use_firmware) {
+		/*
+		 * Size the bridge windows.
+		 */
+		pci_bus_size_bridges(puv3_bus);
+
+		/*
+		 * Assign resources.
+		 */
+		pci_bus_assign_resources(puv3_bus);
+	}
+
+	/*
+	 * Tell drivers about devices found.
+	 */
+	pci_bus_add_devices(puv3_bus);
+
+	return 0;
+}
+subsys_initcall(pci_common_init);
+
+char * __devinit pcibios_setup(char *str)
+{
+	if (!strcmp(str, "debug")) {
+		debug_pci = 1;
+		return NULL;
+	} else if (!strcmp(str, "firmware")) {
+		use_firmware = 1;
+		return NULL;
+	}
+	return str;
+}
+
+/*
+ * From arch/i386/kernel/pci-i386.c:
+ *
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might be mirrored at 0x0100-0x03ff..
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	resource_size_t start = res->start;
+
+	if (res->flags & IORESOURCE_IO && start & 0x300)
+		start = (start + 0x3ff) & ~0x3ff;
+
+	start = (start + align - 1) & ~(align - 1);
+
+	return start;
+}
+
+/**
+ * pcibios_enable_device - Enable I/O and memory.
+ * @dev: PCI device to be enabled
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
+
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because"
+			       " of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+
+	/*
+	 * Bridges (eg, cardbus bridges) need to be fully enabled
+	 */
+	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+	if (cmd != old_cmd) {
+		printk("PCI: enabling device %s (%04x -> %04x)\n",
+		       pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	unsigned long phys;
+
+	if (mmap_state == pci_mmap_io)
+		return -EINVAL;
+
+	phys = vma->vm_pgoff;
+
+	/*
+	 * Mark this as IO
+	 */
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (remap_pfn_range(vma, vma->vm_start, phys,
+			     vma->vm_end - vma->vm_start,
+			     vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
diff --git a/arch/unicore32/kernel/pm.c b/arch/unicore32/kernel/pm.c
new file mode 100644
index 0000000..784bc2d
--- /dev/null
+++ b/arch/unicore32/kernel/pm.c
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/unicore32/kernel/pm.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/module.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/pm.h>
+
+#include "setup.h"
+
+struct puv3_cpu_pm_fns *puv3_cpu_pm_fns;
+static unsigned long *sleep_save;
+
+int puv3_pm_enter(suspend_state_t state)
+{
+	unsigned long sleep_save_checksum = 0, checksum = 0;
+	int i;
+
+	/* skip registers saving for standby */
+	if (state != PM_SUSPEND_STANDBY) {
+		puv3_cpu_pm_fns->save(sleep_save);
+		/* before sleeping, calculate and save a checksum */
+		for (i = 0; i < puv3_cpu_pm_fns->save_count - 1; i++)
+			sleep_save_checksum += sleep_save[i];
+	}
+
+	/* *** go zzz *** */
+	puv3_cpu_pm_fns->enter(state);
+	cpu_init();
+#ifdef CONFIG_INPUT_KEYBOARD
+	puv3_ps2_init();
+#endif
+#ifdef CONFIG_PCI
+	pci_puv3_preinit();
+#endif
+	if (state != PM_SUSPEND_STANDBY) {
+		/* after sleeping, validate the checksum */
+		for (i = 0; i < puv3_cpu_pm_fns->save_count - 1; i++)
+			checksum += sleep_save[i];
+
+		/* if invalid, display message and wait for a hardware reset */
+		if (checksum != sleep_save_checksum) {
+			while (1)
+				puv3_cpu_pm_fns->enter(state);
+		}
+		puv3_cpu_pm_fns->restore(sleep_save);
+	}
+
+	pr_debug("*** made it back from resume\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(puv3_pm_enter);
+
+unsigned long sleep_phys_sp(void *sp)
+{
+	return virt_to_phys(sp);
+}
+
+static int puv3_pm_valid(suspend_state_t state)
+{
+	if (puv3_cpu_pm_fns)
+		return puv3_cpu_pm_fns->valid(state);
+
+	return -EINVAL;
+}
+
+static int puv3_pm_prepare(void)
+{
+	int ret = 0;
+
+	if (puv3_cpu_pm_fns && puv3_cpu_pm_fns->prepare)
+		ret = puv3_cpu_pm_fns->prepare();
+
+	return ret;
+}
+
+static void puv3_pm_finish(void)
+{
+	if (puv3_cpu_pm_fns && puv3_cpu_pm_fns->finish)
+		puv3_cpu_pm_fns->finish();
+}
+
+static struct platform_suspend_ops puv3_pm_ops = {
+	.valid		= puv3_pm_valid,
+	.enter		= puv3_pm_enter,
+	.prepare	= puv3_pm_prepare,
+	.finish		= puv3_pm_finish,
+};
+
+static int __init puv3_pm_init(void)
+{
+	if (!puv3_cpu_pm_fns) {
+		printk(KERN_ERR "no valid puv3_cpu_pm_fns defined\n");
+		return -EINVAL;
+	}
+
+	sleep_save = kmalloc(puv3_cpu_pm_fns->save_count
+				* sizeof(unsigned long), GFP_KERNEL);
+	if (!sleep_save) {
+		printk(KERN_ERR "failed to alloc memory for pm save\n");
+		return -ENOMEM;
+	}
+
+	suspend_set_ops(&puv3_pm_ops);
+	return 0;
+}
+
+device_initcall(puv3_pm_init);
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
new file mode 100644
index 0000000..ba401df
--- /dev/null
+++ b/arch/unicore32/kernel/process.c
@@ -0,0 +1,389 @@
+/*
+ * linux/arch/unicore32/kernel/process.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 <stdarg.h>
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/elfcore.h>
+#include <linux/pm.h>
+#include <linux/tick.h>
+#include <linux/utsname.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include <linux/gpio.h>
+#include <linux/stacktrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/stacktrace.h>
+
+#include "setup.h"
+
+static const char * const processor_modes[] = {
+	"UK00", "UK01", "UK02", "UK03", "UK04", "UK05", "UK06", "UK07",
+	"UK08", "UK09", "UK0A", "UK0B", "UK0C", "UK0D", "UK0E", "UK0F",
+	"USER", "REAL", "INTR", "PRIV", "UK14", "UK15", "UK16", "ABRT",
+	"UK18", "UK19", "UK1A", "EXTN", "UK1C", "UK1D", "UK1E", "SUSR"
+};
+
+/*
+ * The idle thread, has rather strange semantics for calling pm_idle,
+ * but this is what x86 does and we need to do the same, so that
+ * things like cpuidle get called in the same way.
+ */
+void cpu_idle(void)
+{
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		while (!need_resched()) {
+			local_irq_disable();
+			stop_critical_timings();
+			cpu_do_idle();
+			local_irq_enable();
+			start_critical_timings();
+		}
+		tick_nohz_restart_sched_tick();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+static char reboot_mode = 'h';
+
+int __init reboot_setup(char *str)
+{
+	reboot_mode = str[0];
+	return 1;
+}
+
+__setup("reboot=", reboot_setup);
+
+void machine_halt(void)
+{
+	gpio_set_value(GPO_SOFT_OFF, 0);
+}
+
+/*
+ * Function pointers to optional machine specific functions
+ */
+void (*pm_power_off)(void) = NULL;
+
+void machine_power_off(void)
+{
+	if (pm_power_off)
+		pm_power_off();
+	machine_halt();
+}
+
+void machine_restart(char *cmd)
+{
+	/* Disable interrupts first */
+	local_irq_disable();
+
+	/*
+	 * Tell the mm system that we are going to reboot -
+	 * we may need it to insert some 1:1 mappings so that
+	 * soft boot works.
+	 */
+	setup_mm_for_reboot(reboot_mode);
+
+	/* Clean and invalidate caches */
+	flush_cache_all();
+
+	/* Turn off caching */
+	cpu_proc_fin();
+
+	/* Push out any further dirty data, and ensure cache is empty */
+	flush_cache_all();
+
+	/*
+	 * Now handle reboot code.
+	 */
+	if (reboot_mode == 's') {
+		/* Jump into ROM at address 0xffff0000 */
+		cpu_reset(VECTORS_BASE);
+	} else {
+		writel(0x00002001, PM_PLLSYSCFG); /* cpu clk = 250M */
+		writel(0x00100800, PM_PLLDDRCFG); /* ddr clk =  44M */
+		writel(0x00002001, PM_PLLVGACFG); /* vga clk = 250M */
+
+		/* Use on-chip reset capability */
+		/* following instructions must be in one icache line */
+		__asm__ __volatile__(
+			"	.align 5\n\t"
+			"	stw	%1, [%0]\n\t"
+			"201:	ldw	r0, [%0]\n\t"
+			"	cmpsub.a	r0, #0\n\t"
+			"	bne	201b\n\t"
+			"	stw	%3, [%2]\n\t"
+			"	nop; nop; nop\n\t"
+			/* prefetch 3 instructions at most */
+			:
+			: "r" (PM_PMCR),
+			  "r" (PM_PMCR_CFBSYS | PM_PMCR_CFBDDR
+				| PM_PMCR_CFBVGA),
+			  "r" (RESETC_SWRR),
+			  "r" (RESETC_SWRR_SRB)
+			: "r0", "memory");
+	}
+
+	/*
+	 * Whoops - the architecture was unable to reboot.
+	 * Tell the user!
+	 */
+	mdelay(1000);
+	printk(KERN_EMERG "Reboot failed -- System halted\n");
+	do { } while (1);
+}
+
+void __show_regs(struct pt_regs *regs)
+{
+	unsigned long flags;
+	char buf[64];
+
+	printk(KERN_DEFAULT "CPU: %d    %s  (%s %.*s)\n",
+		raw_smp_processor_id(), print_tainted(),
+		init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
+	print_symbol("PC is at %s\n", instruction_pointer(regs));
+	print_symbol("LR is at %s\n", regs->UCreg_lr);
+	printk(KERN_DEFAULT "pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
+	       "sp : %08lx  ip : %08lx  fp : %08lx\n",
+		regs->UCreg_pc, regs->UCreg_lr, regs->UCreg_asr,
+		regs->UCreg_sp, regs->UCreg_ip, regs->UCreg_fp);
+	printk(KERN_DEFAULT "r26: %08lx  r25: %08lx  r24: %08lx\n",
+		regs->UCreg_26, regs->UCreg_25,
+		regs->UCreg_24);
+	printk(KERN_DEFAULT "r23: %08lx  r22: %08lx  r21: %08lx  r20: %08lx\n",
+		regs->UCreg_23, regs->UCreg_22,
+		regs->UCreg_21, regs->UCreg_20);
+	printk(KERN_DEFAULT "r19: %08lx  r18: %08lx  r17: %08lx  r16: %08lx\n",
+		regs->UCreg_19, regs->UCreg_18,
+		regs->UCreg_17, regs->UCreg_16);
+	printk(KERN_DEFAULT "r15: %08lx  r14: %08lx  r13: %08lx  r12: %08lx\n",
+		regs->UCreg_15, regs->UCreg_14,
+		regs->UCreg_13, regs->UCreg_12);
+	printk(KERN_DEFAULT "r11: %08lx  r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+		regs->UCreg_11, regs->UCreg_10,
+		regs->UCreg_09, regs->UCreg_08);
+	printk(KERN_DEFAULT "r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+		regs->UCreg_07, regs->UCreg_06,
+		regs->UCreg_05, regs->UCreg_04);
+	printk(KERN_DEFAULT "r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+		regs->UCreg_03, regs->UCreg_02,
+		regs->UCreg_01, regs->UCreg_00);
+
+	flags = regs->UCreg_asr;
+	buf[0] = flags & PSR_S_BIT ? 'S' : 's';
+	buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
+	buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
+	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
+	buf[4] = '\0';
+
+	printk(KERN_DEFAULT "Flags: %s  INTR o%s  REAL o%s  Mode %s  Segment %s\n",
+		buf, interrupts_enabled(regs) ? "n" : "ff",
+		fast_interrupts_enabled(regs) ? "n" : "ff",
+		processor_modes[processor_mode(regs)],
+		segment_eq(get_fs(), get_ds()) ? "kernel" : "user");
+	{
+		unsigned int ctrl;
+
+		buf[0] = '\0';
+		{
+			unsigned int transbase;
+			asm("movc %0, p0.c2, #0\n"
+			    : "=r" (transbase));
+			snprintf(buf, sizeof(buf), "  Table: %08x", transbase);
+		}
+		asm("movc %0, p0.c1, #0\n" : "=r" (ctrl));
+
+		printk(KERN_DEFAULT "Control: %08x%s\n", ctrl, buf);
+	}
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_DEFAULT "\n");
+	printk(KERN_DEFAULT "Pid: %d, comm: %20s\n",
+			task_pid_nr(current), current->comm);
+	__show_regs(regs);
+	__backtrace();
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
+
+	memset(thread->used_cp, 0, sizeof(thread->used_cp));
+	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+#ifdef CONFIG_UNICORE_FPU_F64
+	memset(&thread->fpstate, 0, sizeof(struct fp_state));
+#endif
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+
+int
+copy_thread(unsigned long clone_flags, unsigned long stack_start,
+	    unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
+{
+	struct thread_info *thread = task_thread_info(p);
+	struct pt_regs *childregs = task_pt_regs(p);
+
+	*childregs = *regs;
+	childregs->UCreg_00 = 0;
+	childregs->UCreg_sp = stack_start;
+
+	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
+	thread->cpu_context.sp = (unsigned long)childregs;
+	thread->cpu_context.pc = (unsigned long)ret_from_fork;
+
+	if (clone_flags & CLONE_SETTLS)
+		childregs->UCreg_16 = regs->UCreg_03;
+
+	return 0;
+}
+
+/*
+ * Fill in the task's elfregs structure for a core dump.
+ */
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
+{
+	elf_core_copy_regs(elfregs, task_pt_regs(t));
+	return 1;
+}
+
+/*
+ * fill in the fpe structure for a core dump...
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
+{
+	struct thread_info *thread = current_thread_info();
+	int used_math = thread->used_cp[1] | thread->used_cp[2];
+
+#ifdef CONFIG_UNICORE_FPU_F64
+	if (used_math)
+		memcpy(fp, &thread->fpstate, sizeof(*fp));
+#endif
+	return used_math != 0;
+}
+EXPORT_SYMBOL(dump_fpu);
+
+/*
+ * Shuffle the argument into the correct register before calling the
+ * thread function.  r1 is the thread argument, r2 is the pointer to
+ * the thread function, and r3 points to the exit function.
+ */
+asm(".pushsection .text\n"
+"	.align\n"
+"	.type	kernel_thread_helper, #function\n"
+"kernel_thread_helper:\n"
+"	mov.a	asr, r7\n"
+"	mov	r0, r4\n"
+"	mov	lr, r6\n"
+"	mov	pc, r5\n"
+"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
+"	.popsection");
+
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+
+	regs.UCreg_04 = (unsigned long)arg;
+	regs.UCreg_05 = (unsigned long)fn;
+	regs.UCreg_06 = (unsigned long)do_exit;
+	regs.UCreg_07 = PRIV_MODE;
+	regs.UCreg_pc = (unsigned long)kernel_thread_helper;
+	regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
+
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	struct stackframe frame;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	frame.fp = thread_saved_fp(p);
+	frame.sp = thread_saved_sp(p);
+	frame.lr = 0;			/* recovered from the stack */
+	frame.pc = thread_saved_pc(p);
+	do {
+		int ret = unwind_frame(&frame);
+		if (ret < 0)
+			return 0;
+		if (!in_sched_functions(frame.pc))
+			return frame.pc;
+	} while ((count++) < 16);
+	return 0;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+	unsigned long range_end = mm->brk + 0x02000000;
+	return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
+}
+
+/*
+ * The vectors page is always readable from user space for the
+ * atomic helpers and the signal restart code.  Let's declare a mapping
+ * for it so it is visible through ptrace and /proc/<pid>/mem.
+ */
+
+int vectors_user_mapping(void)
+{
+	struct mm_struct *mm = current->mm;
+	return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
+				       VM_READ | VM_EXEC |
+				       VM_MAYREAD | VM_MAYEXEC |
+				       VM_ALWAYSDUMP | VM_RESERVED,
+				       NULL);
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
+}
diff --git a/arch/unicore32/kernel/ptrace.c b/arch/unicore32/kernel/ptrace.c
new file mode 100644
index 0000000..9f07c08
--- /dev/null
+++ b/arch/unicore32/kernel/ptrace.c
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/unicore32/kernel/ptrace.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * By Ross Biro 1/23/92
+ *
+ * This program is free software; you can 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/ptrace.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+
+/*
+ * this routine will get a word off of the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline long get_user_reg(struct task_struct *task, int offset)
+{
+	return task_pt_regs(task)->uregs[offset];
+}
+
+/*
+ * this routine will put a word on the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline int
+put_user_reg(struct task_struct *task, int offset, long data)
+{
+	struct pt_regs newregs, *regs = task_pt_regs(task);
+	int ret = -EINVAL;
+
+	newregs = *regs;
+	newregs.uregs[offset] = data;
+
+	if (valid_user_regs(&newregs)) {
+		regs->uregs[offset] = data;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ */
+void ptrace_disable(struct task_struct *child)
+{
+}
+
+/*
+ * We actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
+			    unsigned long __user *ret)
+{
+	unsigned long tmp;
+
+	tmp = 0;
+	if (off < sizeof(struct pt_regs))
+		tmp = get_user_reg(tsk, off >> 2);
+
+	return put_user(tmp, ret);
+}
+
+/*
+ * We actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
+			     unsigned long val)
+{
+	if (off >= sizeof(struct pt_regs))
+		return 0;
+
+	return put_user_reg(tsk, off >> 2, val);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	int ret;
+	unsigned long __user *datap = (unsigned long __user *) data;
+
+	switch (request) {
+	case PTRACE_PEEKUSR:
+		ret = ptrace_read_user(child, addr, datap);
+		break;
+
+	case PTRACE_POKEUSR:
+		ret = ptrace_write_user(child, addr, data);
+		break;
+
+	case PTRACE_GET_THREAD_AREA:
+		ret = put_user(task_pt_regs(child)->UCreg_16,
+			       datap);
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
+{
+	unsigned long ip;
+
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return scno;
+	if (!(current->ptrace & PT_PTRACED))
+		return scno;
+
+	/*
+	 * Save IP.  IP is used to denote syscall entry/exit:
+	 *  IP = 0 -> entry, = 1 -> exit
+	 */
+	ip = regs->UCreg_ip;
+	regs->UCreg_ip = why;
+
+	current_thread_info()->syscall = scno;
+
+	/* 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));
+	/*
+	 * 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;
+	}
+	regs->UCreg_ip = ip;
+
+	return current_thread_info()->syscall;
+}
diff --git a/arch/unicore32/kernel/puv3-core.c b/arch/unicore32/kernel/puv3-core.c
new file mode 100644
index 0000000..8b1b6be
--- /dev/null
+++ b/arch/unicore32/kernel/puv3-core.c
@@ -0,0 +1,285 @@
+/*
+ *  linux/arch/unicore32/kernel/puv3-core.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/device.h>
+#include <linux/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/usb/musb.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <mach/pm.h>
+
+/*
+ * This is the PKUnity sched_clock implementation.  This has
+ * a resolution of 271ns, and a maximum value of 32025597s (370 days).
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to this function.
+ *
+ *  ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
+ */
+unsigned long long sched_clock(void)
+{
+	unsigned long long v = cnt32_to_63(readl(OST_OSCR));
+
+	/* original conservative method, but overflow frequently
+	 * v *= NSEC_PER_SEC >> 12;
+	 * do_div(v, CLOCK_TICK_RATE >> 12);
+	 */
+	v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
+
+	return v;
+}
+
+static struct resource puv3_usb_resources[] = {
+	/* order is significant! */
+	{
+		.start		= io_v2p(PKUNITY_USB_BASE),
+		.end		= io_v2p(PKUNITY_USB_BASE) + 0x3ff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IRQ_USB,
+		.flags		= IORESOURCE_IRQ,
+	}, {
+		.start		= IRQ_USB,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct musb_hdrc_config	puv3_usb_config[] = {
+	{
+		.num_eps = 16,
+		.multipoint = 1,
+#ifdef CONFIG_USB_INVENTRA_DMA
+		.dma = 1,
+		.dma_channels = 8,
+#endif
+	},
+};
+
+static struct musb_hdrc_platform_data puv3_usb_plat = {
+	.mode		= MUSB_HOST,
+	.min_power	= 100,
+	.clock		= 0,
+	.config		= puv3_usb_config,
+};
+
+static struct resource puv3_mmc_resources[] = {
+	[0] = {
+		.start	= io_v2p(PKUNITY_SDC_BASE),
+		.end	= io_v2p(PKUNITY_SDC_BASE) + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SDC,
+		.end	= IRQ_SDC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource puv3_unigfx_resources[] = {
+	[0] = {
+		.start	= io_v2p(PKUNITY_UNIGFX_BASE),
+		.end	= io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= PKUNITY_UNIGFX_MMAP_BASE,
+		.end	= PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource puv3_rtc_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_RTC_BASE),
+		.end   = io_v2p(PKUNITY_RTC_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_RTCAlarm,
+		.end   = IRQ_RTCAlarm,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_RTC,
+		.end   = IRQ_RTC,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource puv3_pwm_resources[] = {
+	[0] = {
+		.start	= io_v2p(PKUNITY_OST_BASE) + 0x80,
+		.end	= io_v2p(PKUNITY_OST_BASE) + 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource puv3_uart0_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_UART0_BASE),
+		.end   = io_v2p(PKUNITY_UART0_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_UART0,
+		.end   = IRQ_UART0,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource puv3_uart1_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_UART1_BASE),
+		.end   = io_v2p(PKUNITY_UART1_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_UART1,
+		.end   = IRQ_UART1,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource puv3_umal_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_UMAL_BASE),
+		.end   = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_UMAL,
+		.end   = IRQ_UMAL,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+#ifdef CONFIG_PUV3_PM
+
+#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
+#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
+
+/*
+ * List of global PXA peripheral registers to preserve.
+ * More ones like CP and general purpose register values are preserved
+ * with the stack pointer in sleep.S.
+ */
+enum {
+	SLEEP_SAVE_PM_PLLDDRCFG,
+	SLEEP_SAVE_COUNT
+};
+
+
+static void puv3_cpu_pm_save(unsigned long *sleep_save)
+{
+/*	SAVE(PM_PLLDDRCFG); */
+}
+
+static void puv3_cpu_pm_restore(unsigned long *sleep_save)
+{
+/*	RESTORE(PM_PLLDDRCFG); */
+}
+
+static int puv3_cpu_pm_prepare(void)
+{
+	/* set resume return address */
+	writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
+	return 0;
+}
+
+static void puv3_cpu_pm_enter(suspend_state_t state)
+{
+	/* Clear reset status */
+	writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
+			| RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
+
+	switch (state) {
+/*	case PM_SUSPEND_ON:
+		puv3_cpu_idle();
+		break; */
+	case PM_SUSPEND_MEM:
+		puv3_cpu_pm_prepare();
+		puv3_cpu_suspend(PM_PMCR_SFB);
+		break;
+	}
+}
+
+static int puv3_cpu_pm_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM;
+}
+
+static void puv3_cpu_pm_finish(void)
+{
+	/* ensure not to come back here if it wasn't intended */
+	/* PSPR = 0; */
+}
+
+static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
+	.save_count	= SLEEP_SAVE_COUNT,
+	.valid		= puv3_cpu_pm_valid,
+	.save		= puv3_cpu_pm_save,
+	.restore	= puv3_cpu_pm_restore,
+	.enter		= puv3_cpu_pm_enter,
+	.prepare	= puv3_cpu_pm_prepare,
+	.finish		= puv3_cpu_pm_finish,
+};
+
+static void __init puv3_init_pm(void)
+{
+	puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
+}
+#else
+static inline void puv3_init_pm(void) {}
+#endif
+
+void puv3_ps2_init(void)
+{
+	struct clk *bclk32;
+
+	bclk32 = clk_get(NULL, "BUS32_CLK");
+	writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
+}
+
+void __init puv3_core_init(void)
+{
+	puv3_init_pm();
+	puv3_ps2_init();
+
+	platform_device_register_simple("PKUnity-v3-RTC", -1,
+			puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
+	platform_device_register_simple("PKUnity-v3-UMAL", -1,
+			puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
+	platform_device_register_simple("PKUnity-v3-MMC", -1,
+			puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
+	platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
+			puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
+	platform_device_register_simple("PKUnity-v3-PWM", -1,
+			puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
+	platform_device_register_simple("PKUnity-v3-UART", 0,
+			puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
+	platform_device_register_simple("PKUnity-v3-UART", 1,
+			puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
+	platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
+	platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+			puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
+			&puv3_usb_plat, sizeof(puv3_usb_plat));
+}
+
diff --git a/arch/unicore32/kernel/puv3-nb0916.c b/arch/unicore32/kernel/puv3-nb0916.c
new file mode 100644
index 0000000..e731c56
--- /dev/null
+++ b/arch/unicore32/kernel/puv3-nb0916.c
@@ -0,0 +1,145 @@
+/*
+ * linux/arch/unicore32/kernel/puv3-nb0916.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/device.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <mach/hardware.h>
+
+static struct physmap_flash_data physmap_flash_data = {
+	.width		= 1,
+};
+
+static struct resource physmap_flash_resource = {
+	.start		= 0xFFF80000,
+	.end		= 0xFFFFFFFF,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct resource puv3_i2c_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_I2C_BASE),
+		.end   = io_v2p(PKUNITY_I2C_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_I2C,
+		.end   = IRQ_I2C,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_pwm_backlight_data nb0916_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 100,
+	.dft_brightness	= 100,
+	.pwm_period_ns	= 70 * 1024,
+};
+
+static struct gpio_keys_button nb0916_gpio_keys[] = {
+	{
+		.type	= EV_KEY,
+		.code	= KEY_POWER,
+		.gpio	= GPI_SOFF_REQ,
+		.desc	= "Power Button",
+		.wakeup = 1,
+		.active_low = 1,
+	},
+	{
+		.type	= EV_KEY,
+		.code	= BTN_TOUCH,
+		.gpio	= GPI_BTN_TOUCH,
+		.desc	= "Touchpad Button",
+		.wakeup = 1,
+		.active_low = 1,
+	},
+};
+
+static struct gpio_keys_platform_data nb0916_gpio_button_data = {
+	.buttons	= nb0916_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(nb0916_gpio_keys),
+};
+
+static irqreturn_t nb0916_lcdcaseoff_handler(int irq, void *dev_id)
+{
+	if (gpio_get_value(GPI_LCD_CASE_OFF))
+		gpio_set_value(GPO_LCD_EN, 1);
+	else
+		gpio_set_value(GPO_LCD_EN, 0);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t nb0916_overheat_handler(int irq, void *dev_id)
+{
+	machine_halt();
+	/* SYSTEM HALT, NO RETURN */
+	return IRQ_HANDLED;
+}
+
+static struct i2c_board_info __initdata puv3_i2c_devices[] = {
+	{	I2C_BOARD_INFO("lm75",		I2C_TAR_THERMAL),	},
+	{	I2C_BOARD_INFO("bq27200",	I2C_TAR_PWIC),		},
+	{	I2C_BOARD_INFO("24c02",		I2C_TAR_EEPROM),	},
+};
+
+int __init mach_nb0916_init(void)
+{
+	i2c_register_board_info(0, puv3_i2c_devices,
+			ARRAY_SIZE(puv3_i2c_devices));
+
+	platform_device_register_simple("PKUnity-v3-I2C", -1,
+			puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
+
+	platform_device_register_data(&platform_bus, "pwm-backlight", -1,
+			&nb0916_backlight_data, sizeof(nb0916_backlight_data));
+
+	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+			&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
+
+	platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
+			&physmap_flash_resource, 1,
+			&physmap_flash_data, sizeof(physmap_flash_data));
+
+	if (request_irq(gpio_to_irq(GPI_LCD_CASE_OFF),
+		&nb0916_lcdcaseoff_handler,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"NB0916 lcd case off", NULL) < 0) {
+
+		printk(KERN_DEBUG "LCD-Case-OFF IRQ %d not available\n",
+			gpio_to_irq(GPI_LCD_CASE_OFF));
+	}
+
+	if (request_irq(gpio_to_irq(GPI_OTP_INT), &nb0916_overheat_handler,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"NB0916 overheating protection", NULL) < 0) {
+
+		printk(KERN_DEBUG "Overheating Protection IRQ %d not available\n",
+			gpio_to_irq(GPI_OTP_INT));
+	}
+
+	return 0;
+}
+
+subsys_initcall_sync(mach_nb0916_init);
diff --git a/arch/unicore32/kernel/pwm.c b/arch/unicore32/kernel/pwm.c
new file mode 100644
index 0000000..4615d51
--- /dev/null
+++ b/arch/unicore32/kernel/pwm.c
@@ -0,0 +1,263 @@
+/*
+ * linux/arch/unicore32/kernel/pwm.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#include <asm/div64.h>
+#include <mach/hardware.h>
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device *pdev;
+
+	const char	*label;
+	struct clk	*clk;
+	int		clk_enabled;
+
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+/*
+ * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
+ * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ */
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+
+	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	c = clk_get_rate(pwm->clk);
+	c = c * period_ns;
+	do_div(c, 1000000000);
+	period_cycles = c;
+
+	if (period_cycles < 1)
+		period_cycles = 1;
+	prescale = (period_cycles - 1) / 1024;
+	pv = period_cycles / (prescale + 1) - 1;
+
+	if (prescale > 63)
+		return -EINVAL;
+
+	if (duty_ns == period_ns)
+		dc = OST_PWMDCCR_FDCYCLE;
+	else
+		dc = (pv + 1) * duty_ns / period_ns;
+
+	/* NOTE: the clock to PWM has to be enabled first
+	 * before writing to the registers
+	 */
+	clk_enable(pwm->clk);
+	OST_PWMPWCR = prescale;
+	OST_PWMDCCR = pv - dc;
+	OST_PWMPCR  = pv;
+	clk_disable(pwm->clk);
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	int rc = 0;
+
+	if (!pwm->clk_enabled) {
+		rc = clk_enable(pwm->clk);
+		if (!rc)
+			pwm->clk_enabled = 1;
+	}
+	return rc;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	if (pwm->clk_enabled) {
+		clk_disable(pwm->clk);
+		pwm->clk_enabled = 0;
+	}
+}
+EXPORT_SYMBOL(pwm_disable);
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm;
+	int found = 0;
+
+	mutex_lock(&pwm_lock);
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->pwm_id == pwm_id) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		if (pwm->use_count == 0) {
+			pwm->use_count++;
+			pwm->label = label;
+		} else
+			pwm = ERR_PTR(-EBUSY);
+	} else
+		pwm = ERR_PTR(-ENOENT);
+
+	mutex_unlock(&pwm_lock);
+	return pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+
+	if (pwm->use_count) {
+		pwm->use_count--;
+		pwm->label = NULL;
+	} else
+		pr_warning("PWM device already freed\n");
+
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+static inline void __add_pwm(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+	list_add_tail(&pwm->node, &pwm_list);
+	mutex_unlock(&pwm_lock);
+}
+
+static struct pwm_device *pwm_probe(struct platform_device *pdev,
+		unsigned int pwm_id, struct pwm_device *parent_pwm)
+{
+	struct pwm_device *pwm;
+	struct resource *r;
+	int ret = 0;
+
+	pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
+	if (pwm == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pwm->clk = clk_get(NULL, "OST_CLK");
+	if (IS_ERR(pwm->clk)) {
+		ret = PTR_ERR(pwm->clk);
+		goto err_free;
+	}
+	pwm->clk_enabled = 0;
+
+	pwm->use_count = 0;
+	pwm->pwm_id = pwm_id;
+	pwm->pdev = pdev;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto err_free_clk;
+	}
+
+	r = request_mem_region(r->start, resource_size(r), pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free_clk;
+	}
+
+	__add_pwm(pwm);
+	platform_set_drvdata(pdev, pwm);
+	return pwm;
+
+err_free_clk:
+	clk_put(pwm->clk);
+err_free:
+	kfree(pwm);
+	return ERR_PTR(ret);
+}
+
+static int __devinit puv3_pwm_probe(struct platform_device *pdev)
+{
+	struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
+
+	if (IS_ERR(pwm))
+		return PTR_ERR(pwm);
+
+	return 0;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+	struct pwm_device *pwm;
+	struct resource *r;
+
+	pwm = platform_get_drvdata(pdev);
+	if (pwm == NULL)
+		return -ENODEV;
+
+	mutex_lock(&pwm_lock);
+	list_del(&pwm->node);
+	mutex_unlock(&pwm_lock);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	clk_put(pwm->clk);
+	kfree(pwm);
+	return 0;
+}
+
+static struct platform_driver puv3_pwm_driver = {
+	.driver		= {
+		.name	= "PKUnity-v3-PWM",
+	},
+	.probe		= puv3_pwm_probe,
+	.remove		= __devexit_p(pwm_remove),
+};
+
+static int __init pwm_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&puv3_pwm_driver);
+	if (ret) {
+		printk(KERN_ERR "failed to register puv3_pwm_driver\n");
+		return ret;
+	}
+
+	return ret;
+}
+arch_initcall(pwm_init);
+
+static void __exit pwm_exit(void)
+{
+	platform_driver_unregister(&puv3_pwm_driver);
+}
+module_exit(pwm_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/unicore32/kernel/rtc.c b/arch/unicore32/kernel/rtc.c
new file mode 100644
index 0000000..c5f0682
--- /dev/null
+++ b/arch/unicore32/kernel/rtc.c
@@ -0,0 +1,380 @@
+/*
+ * linux/arch/unicore32/kernel/rtc.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+
+static struct resource *puv3_rtc_mem;
+
+static int puv3_rtc_alarmno = IRQ_RTCAlarm;
+static int puv3_rtc_tickno  = IRQ_RTC;
+
+static DEFINE_SPINLOCK(puv3_rtc_pie_lock);
+
+/* IRQ Handlers */
+
+static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
+{
+	struct rtc_device *rdev = id;
+
+	writel(readl(RTC_RTSR) | RTC_RTSR_AL, RTC_RTSR);
+	rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
+{
+	struct rtc_device *rdev = id;
+
+	writel(readl(RTC_RTSR) | RTC_RTSR_HZ, RTC_RTSR);
+	rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
+	return IRQ_HANDLED;
+}
+
+/* Update control registers */
+static void puv3_rtc_setaie(int to)
+{
+	unsigned int tmp;
+
+	pr_debug("%s: aie=%d\n", __func__, to);
+
+	tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE;
+
+	if (to)
+		tmp |= RTC_RTSR_ALE;
+
+	writel(tmp, RTC_RTSR);
+}
+
+static int puv3_rtc_setpie(struct device *dev, int enabled)
+{
+	unsigned int tmp;
+
+	pr_debug("%s: pie=%d\n", __func__, enabled);
+
+	spin_lock_irq(&puv3_rtc_pie_lock);
+	tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE;
+
+	if (enabled)
+		tmp |= RTC_RTSR_HZE;
+
+	writel(tmp, RTC_RTSR);
+	spin_unlock_irq(&puv3_rtc_pie_lock);
+
+	return 0;
+}
+
+static int puv3_rtc_setfreq(struct device *dev, int freq)
+{
+	return 0;
+}
+
+/* Time read/write */
+
+static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+{
+	rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
+
+	pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
+		 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+		 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
+	return 0;
+}
+
+static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	unsigned long rtc_count = 0;
+
+	pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+		 tm->tm_year, tm->tm_mon, tm->tm_mday,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	rtc_tm_to_time(tm, &rtc_count);
+	writel(rtc_count, RTC_RCNR);
+
+	return 0;
+}
+
+static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_time *alm_tm = &alrm->time;
+
+	rtc_time_to_tm(readl(RTC_RTAR), alm_tm);
+
+	alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
+
+	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
+		 alrm->enabled,
+		 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
+		 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
+
+	return 0;
+}
+
+static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_time *tm = &alrm->time;
+	unsigned long rtcalarm_count = 0;
+
+	pr_debug("puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
+		 alrm->enabled,
+		 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
+		 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
+
+	rtc_tm_to_time(tm, &rtcalarm_count);
+	writel(rtcalarm_count, RTC_RTAR);
+
+	puv3_rtc_setaie(alrm->enabled);
+
+	if (alrm->enabled)
+		enable_irq_wake(puv3_rtc_alarmno);
+	else
+		disable_irq_wake(puv3_rtc_alarmno);
+
+	return 0;
+}
+
+static int puv3_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	seq_printf(seq, "periodic_IRQ\t: %s\n",
+		     (readl(RTC_RTSR) & RTC_RTSR_HZE) ? "yes" : "no");
+	return 0;
+}
+
+static int puv3_rtc_open(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
+			  IRQF_DISABLED,  "pkunity-rtc alarm", rtc_dev);
+
+	if (ret) {
+		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
+		return ret;
+	}
+
+	ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
+			  IRQF_DISABLED,  "pkunity-rtc tick", rtc_dev);
+
+	if (ret) {
+		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);
+		goto tick_err;
+	}
+
+	return ret;
+
+ tick_err:
+	free_irq(puv3_rtc_alarmno, rtc_dev);
+	return ret;
+}
+
+static void puv3_rtc_release(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+
+	/* do not clear AIE here, it may be needed for wake */
+
+	puv3_rtc_setpie(dev, 0);
+	free_irq(puv3_rtc_alarmno, rtc_dev);
+	free_irq(puv3_rtc_tickno, rtc_dev);
+}
+
+static const struct rtc_class_ops puv3_rtcops = {
+	.open		= puv3_rtc_open,
+	.release	= puv3_rtc_release,
+	.read_time	= puv3_rtc_gettime,
+	.set_time	= puv3_rtc_settime,
+	.read_alarm	= puv3_rtc_getalarm,
+	.set_alarm	= puv3_rtc_setalarm,
+	.irq_set_freq	= puv3_rtc_setfreq,
+	.irq_set_state	= puv3_rtc_setpie,
+	.proc	        = puv3_rtc_proc,
+};
+
+static void puv3_rtc_enable(struct platform_device *pdev, int en)
+{
+	if (!en) {
+		writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR);
+	} else {
+		/* re-enable the device, and check it is ok */
+
+		if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) {
+			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+			writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR);
+		}
+	}
+}
+
+static int puv3_rtc_remove(struct platform_device *dev)
+{
+	struct rtc_device *rtc = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+	rtc_device_unregister(rtc);
+
+	puv3_rtc_setpie(&dev->dev, 0);
+	puv3_rtc_setaie(0);
+
+	release_resource(puv3_rtc_mem);
+	kfree(puv3_rtc_mem);
+
+	return 0;
+}
+
+static int puv3_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	int ret;
+
+	pr_debug("%s: probe=%p\n", __func__, pdev);
+
+	/* find the IRQs */
+
+	puv3_rtc_tickno = platform_get_irq(pdev, 1);
+	if (puv3_rtc_tickno < 0) {
+		dev_err(&pdev->dev, "no irq for rtc tick\n");
+		return -ENOENT;
+	}
+
+	puv3_rtc_alarmno = platform_get_irq(pdev, 0);
+	if (puv3_rtc_alarmno < 0) {
+		dev_err(&pdev->dev, "no irq for alarm\n");
+		return -ENOENT;
+	}
+
+	pr_debug("PKUnity_rtc: tick irq %d, alarm irq %d\n",
+		 puv3_rtc_tickno, puv3_rtc_alarmno);
+
+	/* get the memory region */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get memory region resource\n");
+		return -ENOENT;
+	}
+
+	puv3_rtc_mem = request_mem_region(res->start,
+					 res->end-res->start+1,
+					 pdev->name);
+
+	if (puv3_rtc_mem == NULL) {
+		dev_err(&pdev->dev, "failed to reserve memory region\n");
+		ret = -ENOENT;
+		goto err_nores;
+	}
+
+	puv3_rtc_enable(pdev, 1);
+
+	puv3_rtc_setfreq(&pdev->dev, 1);
+
+	/* register RTC and exit */
+
+	rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,
+				  THIS_MODULE);
+
+	if (IS_ERR(rtc)) {
+		dev_err(&pdev->dev, "cannot attach rtc\n");
+		ret = PTR_ERR(rtc);
+		goto err_nortc;
+	}
+
+	/* platform setup code should have handled this; sigh */
+	if (!device_can_wakeup(&pdev->dev))
+		device_init_wakeup(&pdev->dev, 1);
+
+	platform_set_drvdata(pdev, rtc);
+	return 0;
+
+ err_nortc:
+	puv3_rtc_enable(pdev, 0);
+	release_resource(puv3_rtc_mem);
+
+ err_nores:
+	return ret;
+}
+
+#ifdef CONFIG_PM
+
+/* RTC Power management control */
+
+static int ticnt_save;
+
+static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	/* save RTAR for anyone using periodic interrupts */
+	ticnt_save = readl(RTC_RTAR);
+	puv3_rtc_enable(pdev, 0);
+	return 0;
+}
+
+static int puv3_rtc_resume(struct platform_device *pdev)
+{
+	puv3_rtc_enable(pdev, 1);
+	writel(ticnt_save, RTC_RTAR);
+	return 0;
+}
+#else
+#define puv3_rtc_suspend NULL
+#define puv3_rtc_resume  NULL
+#endif
+
+static struct platform_driver puv3_rtcdrv = {
+	.probe		= puv3_rtc_probe,
+	.remove		= __devexit_p(puv3_rtc_remove),
+	.suspend	= puv3_rtc_suspend,
+	.resume		= puv3_rtc_resume,
+	.driver		= {
+		.name	= "PKUnity-v3-RTC",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
+
+static int __init puv3_rtc_init(void)
+{
+	printk(banner);
+	return platform_driver_register(&puv3_rtcdrv);
+}
+
+static void __exit puv3_rtc_exit(void)
+{
+	platform_driver_unregister(&puv3_rtcdrv);
+}
+
+module_init(puv3_rtc_init);
+module_exit(puv3_rtc_exit);
+
+MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
+MODULE_AUTHOR("Hu Dongliang");
+MODULE_LICENSE("GPL v2");
+
diff --git a/arch/unicore32/kernel/setup.c b/arch/unicore32/kernel/setup.c
new file mode 100644
index 0000000..1e175a8
--- /dev/null
+++ b/arch/unicore32/kernel/setup.c
@@ -0,0 +1,360 @@
+/*
+ * linux/arch/unicore32/kernel/setup.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/stddef.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/utsname.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/screen_info.h>
+#include <linux/init.h>
+#include <linux/root_dev.h>
+#include <linux/cpu.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/memblock.h>
+#include <linux/elf.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/traps.h>
+
+#include "setup.h"
+
+#ifndef MEM_SIZE
+#define MEM_SIZE	(16*1024*1024)
+#endif
+
+struct stack {
+	u32 irq[3];
+	u32 abt[3];
+	u32 und[3];
+} ____cacheline_aligned;
+
+static struct stack stacks[NR_CPUS];
+
+char elf_platform[ELF_PLATFORM_SIZE];
+EXPORT_SYMBOL(elf_platform);
+
+static char __initdata cmd_line[COMMAND_LINE_SIZE];
+
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+/*
+ * Standard memory resources
+ */
+static struct resource mem_res[] = {
+	{
+		.name = "Video RAM",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.name = "Kernel text",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.name = "Kernel data",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	}
+};
+
+#define video_ram   mem_res[0]
+#define kernel_code mem_res[1]
+#define kernel_data mem_res[2]
+
+/*
+ * These functions re-use the assembly code in head.S, which
+ * already provide the required functionality.
+ */
+static void __init setup_processor(void)
+{
+	printk(KERN_DEFAULT "CPU: UniCore-II [%08x] revision %d, cr=%08lx\n",
+	       uc32_cpuid, (int)(uc32_cpuid >> 16) & 15, cr_alignment);
+
+	sprintf(init_utsname()->machine, "puv3");
+	sprintf(elf_platform, "ucv2");
+}
+
+/*
+ * cpu_init - initialise one CPU.
+ *
+ * cpu_init sets up the per-CPU stacks.
+ */
+void cpu_init(void)
+{
+	unsigned int cpu = smp_processor_id();
+	struct stack *stk = &stacks[cpu];
+
+	/*
+	 * setup stacks for re-entrant exception handlers
+	 */
+	__asm__ (
+	"mov.a	asr, %1\n\t"
+	"add	sp, %0, %2\n\t"
+	"mov.a	asr, %3\n\t"
+	"add	sp, %0, %4\n\t"
+	"mov.a	asr, %5\n\t"
+	"add	sp, %0, %6\n\t"
+	"mov.a	asr, %7"
+	    :
+	    : "r" (stk),
+	      "r" (PSR_R_BIT | PSR_I_BIT | INTR_MODE),
+	      "I" (offsetof(struct stack, irq[0])),
+	      "r" (PSR_R_BIT | PSR_I_BIT | ABRT_MODE),
+	      "I" (offsetof(struct stack, abt[0])),
+	      "r" (PSR_R_BIT | PSR_I_BIT | EXTN_MODE),
+	      "I" (offsetof(struct stack, und[0])),
+	      "r" (PSR_R_BIT | PSR_I_BIT | PRIV_MODE)
+	: "r30", "cc");
+}
+
+static int __init uc32_add_memory(unsigned long start, unsigned long size)
+{
+	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
+
+	if (meminfo.nr_banks >= NR_BANKS) {
+		printk(KERN_CRIT "NR_BANKS too low, "
+			"ignoring memory at %#lx\n", start);
+		return -EINVAL;
+	}
+
+	/*
+	 * Ensure that start/size are aligned to a page boundary.
+	 * Size is appropriately rounded down, start is rounded up.
+	 */
+	size -= start & ~PAGE_MASK;
+
+	bank->start = PAGE_ALIGN(start);
+	bank->size  = size & PAGE_MASK;
+
+	/*
+	 * Check whether this memory region has non-zero size or
+	 * invalid node number.
+	 */
+	if (bank->size == 0)
+		return -EINVAL;
+
+	meminfo.nr_banks++;
+	return 0;
+}
+
+/*
+ * Pick out the memory size.  We look for mem=size@start,
+ * where start and size are "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+	static int usermem __initdata = 1;
+	unsigned long size, start;
+	char *endp;
+
+	/*
+	 * If the user specifies memory size, we
+	 * blow away any automatically generated
+	 * size.
+	 */
+	if (usermem) {
+		usermem = 0;
+		meminfo.nr_banks = 0;
+	}
+
+	start = PHYS_OFFSET;
+	size  = memparse(p, &endp);
+	if (*endp == '@')
+		start = memparse(endp + 1, NULL);
+
+	uc32_add_memory(start, size);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+static void __init
+request_standard_resources(struct meminfo *mi)
+{
+	struct resource *res;
+	int i;
+
+	kernel_code.start   = virt_to_phys(_stext);
+	kernel_code.end     = virt_to_phys(_etext - 1);
+	kernel_data.start   = virt_to_phys(_sdata);
+	kernel_data.end     = virt_to_phys(_end - 1);
+
+	for (i = 0; i < mi->nr_banks; i++) {
+		if (mi->bank[i].size == 0)
+			continue;
+
+		res = alloc_bootmem_low(sizeof(*res));
+		res->name  = "System RAM";
+		res->start = mi->bank[i].start;
+		res->end   = mi->bank[i].start + mi->bank[i].size - 1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+		request_resource(&iomem_resource, res);
+
+		if (kernel_code.start >= res->start &&
+		    kernel_code.end <= res->end)
+			request_resource(res, &kernel_code);
+		if (kernel_data.start >= res->start &&
+		    kernel_data.end <= res->end)
+			request_resource(res, &kernel_data);
+	}
+
+	video_ram.start = PKUNITY_UNIGFX_MMAP_BASE;
+	video_ram.end   = PKUNITY_UNIGFX_MMAP_BASE + PKUNITY_UNIGFX_MMAP_SIZE;
+	request_resource(&iomem_resource, &video_ram);
+}
+
+static void (*init_machine)(void) __initdata;
+
+static int __init customize_machine(void)
+{
+	/* customizes platform devices, or adds new ones */
+	if (init_machine)
+		init_machine();
+	return 0;
+}
+arch_initcall(customize_machine);
+
+void __init setup_arch(char **cmdline_p)
+{
+	char *from = default_command_line;
+
+	setup_processor();
+
+	init_mm.start_code = (unsigned long) _stext;
+	init_mm.end_code   = (unsigned long) _etext;
+	init_mm.end_data   = (unsigned long) _edata;
+	init_mm.brk	   = (unsigned long) _end;
+
+	/* parse_early_param needs a boot_command_line */
+	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+
+	/* populate cmd_line too for later use, preserving boot_command_line */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = cmd_line;
+
+	parse_early_param();
+
+	uc32_memblock_init(&meminfo);
+
+	paging_init();
+	request_standard_resources(&meminfo);
+
+	cpu_init();
+
+	/*
+	 * Set up various architecture-specific pointers
+	 */
+	init_machine = puv3_core_init;
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+	early_trap_init();
+}
+
+static struct cpu cpuinfo_unicore;
+
+static int __init topology_init(void)
+{
+	int i;
+
+	for_each_possible_cpu(i)
+		register_cpu(&cpuinfo_unicore, i);
+
+	return 0;
+}
+subsys_initcall(topology_init);
+
+#ifdef CONFIG_HAVE_PROC_CPU
+static int __init proc_cpu_init(void)
+{
+	struct proc_dir_entry *res;
+
+	res = proc_mkdir("cpu", NULL);
+	if (!res)
+		return -ENOMEM;
+	return 0;
+}
+fs_initcall(proc_cpu_init);
+#endif
+
+static int c_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "Processor\t: UniCore-II rev %d (%s)\n",
+		   (int)(uc32_cpuid >> 16) & 15, elf_platform);
+
+	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+		   loops_per_jiffy / (500000/HZ),
+		   (loops_per_jiffy / (5000/HZ)) % 100);
+
+	/* dump out the processor features */
+	seq_puts(m, "Features\t: CMOV UC-F64");
+
+	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", uc32_cpuid >> 24);
+	seq_printf(m, "CPU architecture: 2\n");
+	seq_printf(m, "CPU revision\t: %d\n", (uc32_cpuid >> 16) & 15);
+
+	seq_printf(m, "Cache type\t: write-back\n"
+			"Cache clean\t: cp0 c5 ops\n"
+			"Cache lockdown\t: not support\n"
+			"Cache format\t: Harvard\n");
+
+	seq_puts(m, "\n");
+
+	seq_printf(m, "Hardware\t: PKUnity v3\n");
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= c_show
+};
diff --git a/arch/unicore32/kernel/setup.h b/arch/unicore32/kernel/setup.h
new file mode 100644
index 0000000..dcd1306
--- /dev/null
+++ b/arch/unicore32/kernel/setup.h
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/unicore32/kernel/setup.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 __UNICORE_KERNEL_SETUP_H__
+#define __UNICORE_KERNEL_SETUP_H__
+
+extern void paging_init(void);
+extern void puv3_core_init(void);
+
+extern void puv3_ps2_init(void);
+extern void pci_puv3_preinit(void);
+extern void __init puv3_init_gpio(void);
+
+extern void setup_mm_for_reboot(char mode);
+
+extern char __stubs_start[], __stubs_end[];
+extern char __vectors_start[], __vectors_end[];
+
+extern void kernel_thread_helper(void);
+
+extern void __init early_signal_init(void);
+#endif
diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c
new file mode 100644
index 0000000..b163fca
--- /dev/null
+++ b/arch/unicore32/kernel/signal.c
@@ -0,0 +1,494 @@
+/*
+ * linux/arch/unicore32/kernel/signal.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+#include <linux/unistd.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * For UniCore syscalls, we encode the syscall number into the instruction.
+ */
+#define SWI_SYS_SIGRETURN	(0xff000000) /* error number for new abi */
+#define SWI_SYS_RT_SIGRETURN	(0xff000000 | (__NR_rt_sigreturn))
+#define SWI_SYS_RESTART		(0xff000000 | (__NR_restart_syscall))
+
+#define KERN_SIGRETURN_CODE	(KUSER_VECPAGE_BASE + 0x00000500)
+#define KERN_RESTART_CODE	(KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
+
+const unsigned long sigreturn_codes[3] = {
+	SWI_SYS_SIGRETURN, SWI_SYS_RT_SIGRETURN,
+};
+
+const unsigned long syscall_restart_code[2] = {
+	SWI_SYS_RESTART,	/* swi	__NR_restart_syscall */
+	0x69efc004,		/* ldr	pc, [sp], #4 */
+};
+
+/*
+ * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
+ */
+struct sigframe {
+	struct ucontext uc;
+	unsigned long retcode[2];
+};
+
+struct rt_sigframe {
+	struct siginfo info;
+	struct sigframe sig;
+};
+
+static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
+{
+	sigset_t set;
+	int err;
+
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		spin_lock_irq(&current->sighand->siglock);
+		current->blocked = set;
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
+	err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
+	err |= __get_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02);
+	err |= __get_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03);
+	err |= __get_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04);
+	err |= __get_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05);
+	err |= __get_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06);
+	err |= __get_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07);
+	err |= __get_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08);
+	err |= __get_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09);
+	err |= __get_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10);
+	err |= __get_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11);
+	err |= __get_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12);
+	err |= __get_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13);
+	err |= __get_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14);
+	err |= __get_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15);
+	err |= __get_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16);
+	err |= __get_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17);
+	err |= __get_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18);
+	err |= __get_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19);
+	err |= __get_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20);
+	err |= __get_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21);
+	err |= __get_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22);
+	err |= __get_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23);
+	err |= __get_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24);
+	err |= __get_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25);
+	err |= __get_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26);
+	err |= __get_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp);
+	err |= __get_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip);
+	err |= __get_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp);
+	err |= __get_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr);
+	err |= __get_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc);
+	err |= __get_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr);
+
+	err |= !valid_user_regs(regs);
+
+	return err;
+}
+
+asmlinkage int __sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 64-bit boundary,
+	 * then 'sp' should be word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->UCreg_sp & 7)
+		goto badframe;
+
+	frame = (struct rt_sigframe __user *)regs->UCreg_sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+
+	if (restore_sigframe(regs, &frame->sig))
+		goto badframe;
+
+	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->UCreg_sp)
+			== -EFAULT)
+		goto badframe;
+
+	return regs->UCreg_00;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static int setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs,
+		sigset_t *set)
+{
+	int err = 0;
+
+	err |= __put_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
+	err |= __put_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
+	err |= __put_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02);
+	err |= __put_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03);
+	err |= __put_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04);
+	err |= __put_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05);
+	err |= __put_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06);
+	err |= __put_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07);
+	err |= __put_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08);
+	err |= __put_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09);
+	err |= __put_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10);
+	err |= __put_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11);
+	err |= __put_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12);
+	err |= __put_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13);
+	err |= __put_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14);
+	err |= __put_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15);
+	err |= __put_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16);
+	err |= __put_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17);
+	err |= __put_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18);
+	err |= __put_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19);
+	err |= __put_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20);
+	err |= __put_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21);
+	err |= __put_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22);
+	err |= __put_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23);
+	err |= __put_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24);
+	err |= __put_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25);
+	err |= __put_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26);
+	err |= __put_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp);
+	err |= __put_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip);
+	err |= __put_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp);
+	err |= __put_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr);
+	err |= __put_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc);
+	err |= __put_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr);
+
+	err |= __put_user(current->thread.trap_no,
+			&sf->uc.uc_mcontext.trap_no);
+	err |= __put_user(current->thread.error_code,
+			&sf->uc.uc_mcontext.error_code);
+	err |= __put_user(current->thread.address,
+			&sf->uc.uc_mcontext.fault_address);
+	err |= __put_user(set->sig[0], &sf->uc.uc_mcontext.oldmask);
+
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	return err;
+}
+
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+		struct pt_regs *regs, int framesize)
+{
+	unsigned long sp = regs->UCreg_sp;
+	void __user *frame;
+
+	/*
+	 * This is the X/Open sanctioned signal stack switching.
+	 */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	/*
+	 * ATPCS B01 mandates 8-byte alignment
+	 */
+	frame = (void __user *)((sp - framesize) & ~7);
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
+}
+
+static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+	     unsigned long __user *rc, void __user *frame, int usig)
+{
+	unsigned long handler = (unsigned long)ka->sa.sa_handler;
+	unsigned long retcode;
+	unsigned long asr = regs->UCreg_asr & ~PSR_f;
+
+	unsigned int idx = 0;
+
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		idx += 1;
+
+	if (__put_user(sigreturn_codes[idx],   rc) ||
+	    __put_user(sigreturn_codes[idx+1], rc+1))
+		return 1;
+
+	retcode = KERN_SIGRETURN_CODE + (idx << 2);
+
+	regs->UCreg_00 = usig;
+	regs->UCreg_sp = (unsigned long)frame;
+	regs->UCreg_lr = retcode;
+	regs->UCreg_pc = handler;
+	regs->UCreg_asr = asr;
+
+	return 0;
+}
+
+static int setup_frame(int usig, struct k_sigaction *ka,
+		sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
+	int err = 0;
+
+	if (!frame)
+		return 1;
+
+	/*
+	 * Set uc.uc_flags to a value which sc.trap_no would never have.
+	 */
+	err |= __put_user(0x5ac3c35a, &frame->uc.uc_flags);
+
+	err |= setup_sigframe(frame, regs, set);
+	if (err == 0)
+		err |= setup_return(regs, ka, frame->retcode, frame, usig);
+
+	return err;
+}
+
+static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+	       sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame =
+			get_sigframe(ka, regs, sizeof(*frame));
+	stack_t stack;
+	int err = 0;
+
+	if (!frame)
+		return 1;
+
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	err |= __put_user(0, &frame->sig.uc.uc_flags);
+	err |= __put_user(NULL, &frame->sig.uc.uc_link);
+
+	memset(&stack, 0, sizeof(stack));
+	stack.ss_sp = (void __user *)current->sas_ss_sp;
+	stack.ss_flags = sas_ss_flags(regs->UCreg_sp);
+	stack.ss_size = current->sas_ss_size;
+	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
+
+	err |= setup_sigframe(&frame->sig, regs, set);
+	if (err == 0)
+		err |= setup_return(regs, ka, frame->sig.retcode, frame, usig);
+
+	if (err == 0) {
+		/*
+		 * For realtime signals we must also set the second and third
+		 * arguments for the signal handler.
+		 */
+		regs->UCreg_01 = (unsigned long)&frame->info;
+		regs->UCreg_02 = (unsigned long)&frame->sig.uc;
+	}
+
+	return err;
+}
+
+static inline void setup_syscall_restart(struct pt_regs *regs)
+{
+	regs->UCreg_00 = regs->UCreg_ORIG_00;
+	regs->UCreg_pc -= 4;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static int handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset,
+	      struct pt_regs *regs, int syscall)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
+	int usig = sig;
+	int ret;
+
+	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall) {
+		switch (regs->UCreg_00) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->UCreg_00 = -EINTR;
+			break;
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->UCreg_00 = -EINTR;
+				break;
+			}
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			setup_syscall_restart(regs);
+		}
+	}
+
+	/*
+	 * translate the signal
+	 */
+	if (usig < 32 && thread->exec_domain
+			&& thread->exec_domain->signal_invmap)
+		usig = thread->exec_domain->signal_invmap[usig];
+
+	/*
+	 * Set up the stack frame
+	 */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(usig, ka, info, oldset, regs);
+	else
+		ret = setup_frame(usig, ka, oldset, regs);
+
+	/*
+	 * Check that the resulting registers are actually sane.
+	 */
+	ret |= !valid_user_regs(regs);
+
+	if (ret != 0) {
+		force_sigsegv(sig, tsk);
+		return ret;
+	}
+
+	/*
+	 * Block the signal if we were successful.
+	 */
+	spin_lock_irq(&tsk->sighand->siglock);
+	sigorsets(&tsk->blocked, &tsk->blocked,
+		  &ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&tsk->blocked, sig);
+	recalc_sigpending();
+	spin_unlock_irq(&tsk->sighand->siglock);
+
+	return 0;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+static void do_signal(struct pt_regs *regs, int syscall)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	int signr;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return;
+
+	if (try_to_freeze())
+		goto no_signal;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		sigset_t *oldset;
+
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+		if (handle_signal(signr, &ka, &info, oldset, regs, syscall)
+				== 0) {
+			/*
+			 * A signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag.
+			 */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		return;
+	}
+
+ no_signal:
+	/*
+	 * No signal to deliver to the process - restart the syscall.
+	 */
+	if (syscall) {
+		if (regs->UCreg_00 == -ERESTART_RESTARTBLOCK) {
+				u32 __user *usp;
+
+				regs->UCreg_sp -= 4;
+				usp = (u32 __user *)regs->UCreg_sp;
+
+				if (put_user(regs->UCreg_pc, usp) == 0) {
+					regs->UCreg_pc = KERN_RESTART_CODE;
+				} else {
+					regs->UCreg_sp += 4;
+					force_sigsegv(0, current);
+				}
+		}
+		if (regs->UCreg_00 == -ERESTARTNOHAND ||
+		    regs->UCreg_00 == -ERESTARTSYS ||
+		    regs->UCreg_00 == -ERESTARTNOINTR) {
+			setup_syscall_restart(regs);
+		}
+
+		/* If there's no signal to deliver, we just put the saved
+		 * sigmask back.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
+	}
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs,
+		unsigned int thread_flags, int syscall)
+{
+	if (thread_flags & _TIF_SIGPENDING)
+		do_signal(regs, syscall);
+
+	if (thread_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
+
+/*
+ * Copy signal return handlers into the vector page, and
+ * set sigreturn to be a pointer to these.
+ */
+void __init early_signal_init(void)
+{
+	memcpy((void *)kuser_vecpage_to_vectors(KERN_SIGRETURN_CODE),
+			sigreturn_codes, sizeof(sigreturn_codes));
+	memcpy((void *)kuser_vecpage_to_vectors(KERN_RESTART_CODE),
+			syscall_restart_code, sizeof(syscall_restart_code));
+	/* Need not to flush icache, since early_trap_init will do it last. */
+}
diff --git a/arch/unicore32/kernel/sleep.S b/arch/unicore32/kernel/sleep.S
new file mode 100644
index 0000000..607a104
--- /dev/null
+++ b/arch/unicore32/kernel/sleep.S
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/unicore32/kernel/sleep.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/hardware.h>
+
+		.text
+
+pkunity_cpu_save_cp:
+
+	@ get coprocessor registers
+
+	movc	r3, p0.c7, #0			@ PID
+	movc	r4, p0.c2, #0			@ translation table base addr
+	movc	r5, p0.c1, #0			@ control reg
+
+
+	@ store them plus current virtual stack ptr on stack
+	mov	r6, sp
+	stm.w	(r3 - r6), [sp-]
+
+	mov	pc, lr
+
+pkunity_cpu_save_sp:
+	@ preserve phys address of stack
+	mov	r0, sp
+	stw.w	lr, [sp+], #-4
+	b.l	sleep_phys_sp
+	ldw	r1, =sleep_save_sp
+	stw	r0, [r1]
+	ldw.w	pc, [sp]+, #4
+
+/*
+ * puv3_cpu_suspend()
+ *
+ * Forces CPU into sleep state.
+ *
+ * r0 = value for PWRMODE M field for desired sleep state
+ */
+
+ENTRY(puv3_cpu_suspend)
+	stm.w	(r16 - r27, lr), [sp-]		@ save registers on stack
+	stm.w	(r4 - r15), [sp-]		@ save registers on stack
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	sfm.w	(f0  - f7 ), [sp-]
+	sfm.w	(f8  - f15), [sp-]
+	sfm.w	(f16 - f23), [sp-]
+	sfm.w	(f24 - f31), [sp-]
+	cff	r4, s31
+	stm.w	(r4), [sp-]
+#endif
+	b.l	pkunity_cpu_save_cp
+
+	b.l	pkunity_cpu_save_sp
+
+	@ clean data cache
+	mov	r1, #0
+	movc	p0.c5, r1, #14
+	nop
+	nop
+	nop
+	nop
+
+
+
+	@ DDR2 BaseAddr
+	ldw	r0, =(PKUNITY_DDR2CTRL_BASE)
+
+	@ PM BaseAddr
+	ldw	r1, =(PKUNITY_PM_BASE)
+
+	@ set PLL_SYS_CFG reg, 275
+	movl	r6, #0x00002401
+	stw	r6, [r1+], #0x18
+	@ set PLL_DDR_CFG reg, 66MHz
+	movl	r6, #0x00100c00
+	stw	r6, [r1+], #0x1c
+
+	@ set wake up source
+	movl	r8, #0x800001ff		@ epip4d
+	stw	r8, [r1+], #0xc
+
+	@ set PGSR
+	movl	r5, #0x40000
+	stw	r5, [r1+], #0x10
+
+	@ prepare DDR2 refresh settings
+	ldw	r5, [r0+], #0x24
+	or	r5, r5, #0x00000001
+
+	@ prepare PMCR for PLL changing
+	movl	r6, #0xc
+
+	@ prepare for closing PLL
+	movl	r7, #0x1
+
+	@ prepare sleep mode
+	mov	r8, #0x1
+
+@	movl	r0, 0x11111111
+@	put_word_ocd r0
+	b	pkunity_cpu_do_suspend
+
+	.ltorg
+	.align	5
+pkunity_cpu_do_suspend:
+	b	101f
+	@ put DDR2 into self-refresh
+100:	stw	r5, [r0+], #0x24
+	@ change PLL
+	stw	r6, [r1]
+	b	1f
+
+	.ltorg
+	.align	5
+101:	b	102f
+	@ wait for PLL changing complete
+1:	ldw	r6, [r1+], #0x44
+	csub.a	r6, #0x1
+	bne	1b
+	b	2f
+
+	.ltorg
+	.align	5
+102:	b	100b
+	@ close PLL
+2:	stw	r7, [r1+], #0x4
+	@ enter sleep mode
+	stw	r8, [r1]
+3:	b	3b
+
+
+
+
+/*
+ * puv3_cpu_resume()
+ *
+ * entry point from bootloader into kernel during resume
+ *
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+
+	.data
+	.align 5
+ENTRY(puv3_cpu_resume)
+@	movl	r0, 0x20202020
+@	put_word_ocd r0
+
+	ldw	r0, sleep_save_sp		@ stack phys addr
+	ldw	r2, =resume_after_mmu		@ its absolute virtual address
+	ldm	(r3 - r6), [r0]+		@ CP regs + virt stack ptr
+	mov	sp, r6				@ CP regs + virt stack ptr
+
+	mov	r1, #0
+	movc	p0.c6, r1, #6			@ invalidate I & D TLBs
+	movc	p0.c5, r1, #28			@ invalidate I & D caches, BTB
+
+	movc	p0.c7, r3, #0			@ PID
+	movc	p0.c2, r4, #0			@ translation table base addr
+	movc	p0.c1, r5, #0			@ control reg, turn on mmu
+	nop
+	jump	r2
+	nop
+	nop
+	nop
+	nop
+	nop
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
+
+	.text
+resume_after_mmu:
+@	movl	r0, 0x30303030
+@	put_word_ocd r0
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	lfm.w	(f0  - f7 ), [sp]+
+	lfm.w	(f8  - f15), [sp]+
+	lfm.w	(f16 - f23), [sp]+
+	lfm.w	(f24 - f31), [sp]+
+	ldm.w	(r4), [sp]+
+	ctf	r4, s31
+#endif
+	ldm.w	(r4 - r15), [sp]+		@ restore registers from stack
+	ldm.w	(r16 - r27, pc), [sp]+		@ return to caller
diff --git a/arch/unicore32/kernel/stacktrace.c b/arch/unicore32/kernel/stacktrace.c
new file mode 100644
index 0000000..b34030b
--- /dev/null
+++ b/arch/unicore32/kernel/stacktrace.c
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/unicore32/kernel/stacktrace.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/sched.h>
+#include <linux/stacktrace.h>
+
+#include <asm/stacktrace.h>
+
+#if defined(CONFIG_FRAME_POINTER)
+/*
+ * Unwind the current stack frame and store the new register values in the
+ * structure passed as argument. Unwinding is equivalent to a function return,
+ * hence the new PC value rather than LR should be used for backtrace.
+ *
+ * With framepointer enabled, a simple function prologue looks like this:
+ *	mov	ip, sp
+ *	stmdb	sp!, {fp, ip, lr, pc}
+ *	sub	fp, ip, #4
+ *
+ * A simple function epilogue looks like this:
+ *	ldm	sp, {fp, sp, pc}
+ *
+ * Note that with framepointer enabled, even the leaf functions have the same
+ * prologue and epilogue, therefore we can ignore the LR value in this case.
+ */
+int notrace unwind_frame(struct stackframe *frame)
+{
+	unsigned long high, low;
+	unsigned long fp = frame->fp;
+
+	/* only go to a higher address on the stack */
+	low = frame->sp;
+	high = ALIGN(low, THREAD_SIZE);
+
+	/* check current frame pointer is within bounds */
+	if (fp < (low + 12) || fp + 4 >= high)
+		return -EINVAL;
+
+	/* restore the registers from the stack frame */
+	frame->fp = *(unsigned long *)(fp - 12);
+	frame->sp = *(unsigned long *)(fp - 8);
+	frame->pc = *(unsigned long *)(fp - 4);
+
+	return 0;
+}
+#endif
+
+void notrace walk_stackframe(struct stackframe *frame,
+		     int (*fn)(struct stackframe *, void *), void *data)
+{
+	while (1) {
+		int ret;
+
+		if (fn(frame, data))
+			break;
+		ret = unwind_frame(frame);
+		if (ret < 0)
+			break;
+	}
+}
+EXPORT_SYMBOL(walk_stackframe);
+
+#ifdef CONFIG_STACKTRACE
+struct stack_trace_data {
+	struct stack_trace *trace;
+	unsigned int no_sched_functions;
+	unsigned int skip;
+};
+
+static int save_trace(struct stackframe *frame, void *d)
+{
+	struct stack_trace_data *data = d;
+	struct stack_trace *trace = data->trace;
+	unsigned long addr = frame->pc;
+
+	if (data->no_sched_functions && in_sched_functions(addr))
+		return 0;
+	if (data->skip) {
+		data->skip--;
+		return 0;
+	}
+
+	trace->entries[trace->nr_entries++] = addr;
+
+	return trace->nr_entries >= trace->max_entries;
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+	struct stack_trace_data data;
+	struct stackframe frame;
+
+	data.trace = trace;
+	data.skip = trace->skip;
+
+	if (tsk != current) {
+		data.no_sched_functions = 1;
+		frame.fp = thread_saved_fp(tsk);
+		frame.sp = thread_saved_sp(tsk);
+		frame.lr = 0;		/* recovered from the stack */
+		frame.pc = thread_saved_pc(tsk);
+	} else {
+		register unsigned long current_sp asm("sp");
+
+		data.no_sched_functions = 0;
+		frame.fp = (unsigned long)__builtin_frame_address(0);
+		frame.sp = current_sp;
+		frame.lr = (unsigned long)__builtin_return_address(0);
+		frame.pc = (unsigned long)save_stack_trace_tsk;
+	}
+
+	walk_stackframe(&frame, save_trace, &data);
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
+void save_stack_trace(struct stack_trace *trace)
+{
+	save_stack_trace_tsk(current, trace);
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+#endif
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c
new file mode 100644
index 0000000..3afe60a
--- /dev/null
+++ b/arch/unicore32/kernel/sys.c
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/unicore32/kernel/sys.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/errno.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/ipc.h>
+#include <linux/uaccess.h>
+
+#include <asm/syscalls.h>
+#include <asm/cacheflush.h>
+
+/* Clone a task - this clones the calling program thread.
+ * This is called indirectly via a small wrapper
+ */
+asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 void __user *parent_tid, void __user *child_tid,
+			 struct pt_regs *regs)
+{
+	if (!newsp)
+		newsp = regs->UCreg_sp;
+
+	return do_fork(clone_flags, newsp, regs, 0,
+			parent_tid, child_tid);
+}
+
+/* sys_execve() executes a new program.
+ * This is called indirectly via a small wrapper
+ */
+asmlinkage long __sys_execve(const char __user *filename,
+			  const char __user *const __user *argv,
+			  const char __user *const __user *envp,
+			  struct pt_regs *regs)
+{
+	int error;
+	char *fn;
+
+	fn = getname(filename);
+	error = PTR_ERR(fn);
+	if (IS_ERR(fn))
+		goto out;
+	error = do_execve(fn, argv, envp, regs);
+	putname(fn);
+out:
+	return error;
+}
+
+int kernel_execve(const char *filename,
+		  const char *const argv[],
+		  const char *const envp[])
+{
+	struct pt_regs regs;
+	int ret;
+
+	memset(&regs, 0, sizeof(struct pt_regs));
+	ret = do_execve(filename,
+			(const char __user *const __user *)argv,
+			(const char __user *const __user *)envp, &regs);
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * Save argc to the register structure for userspace.
+	 */
+	regs.UCreg_00 = ret;
+
+	/*
+	 * We were successful.  We won't be returning to our caller, but
+	 * instead to user space by manipulating the kernel stack.
+	 */
+	asm("add	r0, %0, %1\n\t"
+		"mov	r1, %2\n\t"
+		"mov	r2, %3\n\t"
+		"mov	r22, #0\n\t"	/* not a syscall */
+		"mov	r23, %0\n\t"	/* thread structure */
+		"b.l	memmove\n\t"	/* copy regs to top of stack */
+		"mov	sp, r0\n\t"	/* reposition stack pointer */
+		"b	ret_to_user"
+		:
+		: "r" (current_thread_info()),
+		  "Ir" (THREAD_START_SP - sizeof(regs)),
+		  "r" (&regs),
+		  "Ir" (sizeof(regs))
+		: "r0", "r1", "r2", "r3", "ip", "lr", "memory");
+
+ out:
+	return ret;
+}
+EXPORT_SYMBOL(kernel_execve);
+
+/* Note: used by the compat code even in 64-bit Linux. */
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+		unsigned long, prot, unsigned long, flags,
+		unsigned long, fd, unsigned long, off_4k)
+{
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      off_4k);
+}
+
+/* Provide the actual syscall number to call mapping. */
+#undef __SYSCALL
+#define __SYSCALL(nr, call)	[nr] = (call),
+
+/* Note that we don't include <linux/unistd.h> but <asm/unistd.h> */
+void *sys_call_table[__NR_syscalls] = {
+	[0 ... __NR_syscalls-1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
diff --git a/arch/unicore32/kernel/time.c b/arch/unicore32/kernel/time.c
new file mode 100644
index 0000000..080710c
--- /dev/null
+++ b/arch/unicore32/kernel/time.c
@@ -0,0 +1,143 @@
+/*
+ * linux/arch/unicore32/kernel/time.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/clockchips.h>
+
+#include <mach/hardware.h>
+
+#define MIN_OSCR_DELTA 2
+
+static irqreturn_t puv3_ost0_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *c = dev_id;
+
+	/* Disarm the compare/match, signal the event. */
+	writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
+	writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
+	c->event_handler(c);
+
+	return IRQ_HANDLED;
+}
+
+static int
+puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
+{
+	unsigned long next, oscr;
+
+	writel(readl(OST_OIER) | OST_OIER_E0, OST_OIER);
+	next = readl(OST_OSCR) + delta;
+	writel(next, OST_OSMR0);
+	oscr = readl(OST_OSCR);
+
+	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
+}
+
+static void
+puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
+		writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	}
+}
+
+static struct clock_event_device ckevt_puv3_osmr0 = {
+	.name		= "osmr0",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= puv3_osmr0_set_next_event,
+	.set_mode	= puv3_osmr0_set_mode,
+};
+
+static cycle_t puv3_read_oscr(struct clocksource *cs)
+{
+	return readl(OST_OSCR);
+}
+
+static struct clocksource cksrc_puv3_oscr = {
+	.name		= "oscr",
+	.rating		= 200,
+	.read		= puv3_read_oscr,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct irqaction puv3_timer_irq = {
+	.name		= "ost0",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= puv3_ost0_interrupt,
+	.dev_id		= &ckevt_puv3_osmr0,
+};
+
+void __init time_init(void)
+{
+	writel(0, OST_OIER);		/* disable any timer interrupts */
+	writel(0, OST_OSSR);		/* clear status on all timers */
+
+	clockevents_calc_mult_shift(&ckevt_puv3_osmr0, CLOCK_TICK_RATE, 5);
+
+	ckevt_puv3_osmr0.max_delta_ns =
+		clockevent_delta2ns(0x7fffffff, &ckevt_puv3_osmr0);
+	ckevt_puv3_osmr0.min_delta_ns =
+		clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_puv3_osmr0) + 1;
+	ckevt_puv3_osmr0.cpumask = cpumask_of(0);
+
+	setup_irq(IRQ_TIMER0, &puv3_timer_irq);
+
+	clocksource_register_hz(&cksrc_puv3_oscr, CLOCK_TICK_RATE);
+	clockevents_register_device(&ckevt_puv3_osmr0);
+}
+
+#ifdef CONFIG_PM
+unsigned long osmr[4], oier;
+
+void puv3_timer_suspend(void)
+{
+	osmr[0] = readl(OST_OSMR0);
+	osmr[1] = readl(OST_OSMR1);
+	osmr[2] = readl(OST_OSMR2);
+	osmr[3] = readl(OST_OSMR3);
+	oier = readl(OST_OIER);
+}
+
+void puv3_timer_resume(void)
+{
+	writel(0, OST_OSSR);
+	writel(osmr[0], OST_OSMR0);
+	writel(osmr[1], OST_OSMR1);
+	writel(osmr[2], OST_OSMR2);
+	writel(osmr[3], OST_OSMR3);
+	writel(oier, OST_OIER);
+
+	/*
+	 * OSMR0 is the system timer: make sure OSCR is sufficiently behind
+	 */
+	writel(readl(OST_OSMR0) - LATCH, OST_OSCR);
+}
+#else
+void puv3_timer_suspend(void) { };
+void puv3_timer_resume(void) { };
+#endif
+
diff --git a/arch/unicore32/kernel/traps.c b/arch/unicore32/kernel/traps.c
new file mode 100644
index 0000000..25abbb1
--- /dev/null
+++ b/arch/unicore32/kernel/traps.c
@@ -0,0 +1,333 @@
+/*
+ * linux/arch/unicore32/kernel/traps.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  'traps.c' handles hardware exceptions after we have saved some state.
+ *  Mostly a debugging aid, but will probably kill the offending process.
+ */
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/spinlock.h>
+#include <linux/personality.h>
+#include <linux/kallsyms.h>
+#include <linux/kdebug.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
+#include <linux/unistd.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+#include "setup.h"
+
+static void dump_mem(const char *, const char *, unsigned long, unsigned long);
+
+void dump_backtrace_entry(unsigned long where,
+		unsigned long from, unsigned long frame)
+{
+#ifdef CONFIG_KALLSYMS
+	printk(KERN_DEFAULT "[<%08lx>] (%pS) from [<%08lx>] (%pS)\n",
+			where, (void *)where, from, (void *)from);
+#else
+	printk(KERN_DEFAULT "Function entered at [<%08lx>] from [<%08lx>]\n",
+			where, from);
+#endif
+}
+
+/*
+ * Stack pointers should always be within the kernels view of
+ * physical memory.  If it is not there, then we can't dump
+ * out any information relating to the stack.
+ */
+static int verify_stack(unsigned long sp)
+{
+	if (sp < PAGE_OFFSET ||
+	    (sp > (unsigned long)high_memory && high_memory != NULL))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Dump out the contents of some memory nicely...
+ */
+static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+		     unsigned long top)
+{
+	unsigned long first;
+	mm_segment_t fs;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	printk(KERN_DEFAULT "%s%s(0x%08lx to 0x%08lx)\n",
+			lvl, str, bottom, top);
+
+	for (first = bottom & ~31; first < top; first += 32) {
+		unsigned long p;
+		char str[sizeof(" 12345678") * 8 + 1];
+
+		memset(str, ' ', sizeof(str));
+		str[sizeof(str) - 1] = '\0';
+
+		for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
+			if (p >= bottom && p < top) {
+				unsigned long val;
+				if (__get_user(val, (unsigned long *)p) == 0)
+					sprintf(str + i * 9, " %08lx", val);
+				else
+					sprintf(str + i * 9, " ????????");
+			}
+		}
+		printk(KERN_DEFAULT "%s%04lx:%s\n", lvl, first & 0xffff, str);
+	}
+
+	set_fs(fs);
+}
+
+static void dump_instr(const char *lvl, struct pt_regs *regs)
+{
+	unsigned long addr = instruction_pointer(regs);
+	const int width = 8;
+	mm_segment_t fs;
+	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	for (i = -4; i < 1; i++) {
+		unsigned int val, bad;
+
+		bad = __get_user(val, &((u32 *)addr)[i]);
+
+		if (!bad)
+			p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
+					width, val);
+		else {
+			p += sprintf(p, "bad PC value");
+			break;
+		}
+	}
+	printk(KERN_DEFAULT "%sCode: %s\n", lvl, str);
+
+	set_fs(fs);
+}
+
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+	unsigned int fp, mode;
+	int ok = 1;
+
+	printk(KERN_DEFAULT "Backtrace: ");
+
+	if (!tsk)
+		tsk = current;
+
+	if (regs) {
+		fp = regs->UCreg_fp;
+		mode = processor_mode(regs);
+	} else if (tsk != current) {
+		fp = thread_saved_fp(tsk);
+		mode = 0x10;
+	} else {
+		asm("mov %0, fp" : "=r" (fp) : : "cc");
+		mode = 0x10;
+	}
+
+	if (!fp) {
+		printk("no frame pointer");
+		ok = 0;
+	} else if (verify_stack(fp)) {
+		printk("invalid frame pointer 0x%08x", fp);
+		ok = 0;
+	} else if (fp < (unsigned long)end_of_stack(tsk))
+		printk("frame pointer underflow");
+	printk("\n");
+
+	if (ok)
+		c_backtrace(fp, mode);
+}
+
+void dump_stack(void)
+{
+	dump_backtrace(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+	dump_backtrace(NULL, tsk);
+	barrier();
+}
+
+static int __die(const char *str, int err, struct thread_info *thread,
+		struct pt_regs *regs)
+{
+	struct task_struct *tsk = thread->task;
+	static int die_counter;
+	int ret;
+
+	printk(KERN_EMERG "Internal error: %s: %x [#%d]\n",
+	       str, err, ++die_counter);
+	sysfs_printk_last_file();
+
+	/* trap and error numbers are mostly meaningless on UniCore */
+	ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, \
+			SIGSEGV);
+	if (ret == NOTIFY_STOP)
+		return ret;
+
+	print_modules();
+	__show_regs(regs);
+	printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
+		TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+
+	if (!user_mode(regs) || in_interrupt()) {
+		dump_mem(KERN_EMERG, "Stack: ", regs->UCreg_sp,
+			 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
+		dump_backtrace(regs, tsk);
+		dump_instr(KERN_EMERG, regs);
+	}
+
+	return ret;
+}
+
+DEFINE_SPINLOCK(die_lock);
+
+/*
+ * This function is protected against re-entrancy.
+ */
+void die(const char *str, struct pt_regs *regs, int err)
+{
+	struct thread_info *thread = current_thread_info();
+	int ret;
+
+	oops_enter();
+
+	spin_lock_irq(&die_lock);
+	console_verbose();
+	bust_spinlocks(1);
+	ret = __die(str, err, thread, regs);
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+	spin_unlock_irq(&die_lock);
+	oops_exit();
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+	if (panic_on_oops)
+		panic("Fatal exception");
+	if (ret != NOTIFY_STOP)
+		do_exit(SIGSEGV);
+}
+
+void uc32_notify_die(const char *str, struct pt_regs *regs,
+		struct siginfo *info, unsigned long err, unsigned long trap)
+{
+	if (user_mode(regs)) {
+		current->thread.error_code = err;
+		current->thread.trap_no = trap;
+
+		force_sig_info(info->si_signo, info, current);
+	} else
+		die(str, regs, err);
+}
+
+/*
+ * bad_mode handles the impossible case in the vectors.  If you see one of
+ * these, then it's extremely serious, and could mean you have buggy hardware.
+ * It never returns, and never tries to sync.  We hope that we can at least
+ * dump out some state information...
+ */
+asmlinkage void bad_mode(struct pt_regs *regs, unsigned int reason)
+{
+	console_verbose();
+
+	printk(KERN_CRIT "Bad mode detected with reason 0x%x\n", reason);
+
+	die("Oops - bad mode", regs, 0);
+	local_irq_disable();
+	panic("bad mode");
+}
+
+void __pte_error(const char *file, int line, unsigned long val)
+{
+	printk(KERN_DEFAULT "%s:%d: bad pte %08lx.\n", file, line, val);
+}
+
+void __pmd_error(const char *file, int line, unsigned long val)
+{
+	printk(KERN_DEFAULT "%s:%d: bad pmd %08lx.\n", file, line, val);
+}
+
+void __pgd_error(const char *file, int line, unsigned long val)
+{
+	printk(KERN_DEFAULT "%s:%d: bad pgd %08lx.\n", file, line, val);
+}
+
+asmlinkage void __div0(void)
+{
+	printk(KERN_DEFAULT "Division by zero in kernel.\n");
+	dump_stack();
+}
+EXPORT_SYMBOL(__div0);
+
+void abort(void)
+{
+	BUG();
+
+	/* if that doesn't kill us, halt */
+	panic("Oops failed to kill thread");
+}
+EXPORT_SYMBOL(abort);
+
+void __init trap_init(void)
+{
+	return;
+}
+
+void __init early_trap_init(void)
+{
+	unsigned long vectors = VECTORS_BASE;
+
+	/*
+	 * Copy the vectors, stubs (in entry-unicore.S)
+	 * into the vector page, mapped at 0xffff0000, and ensure these
+	 * are visible to the instruction stream.
+	 */
+	memcpy((void *)vectors,
+			__vectors_start,
+			__vectors_end - __vectors_start);
+	memcpy((void *)vectors + 0x200,
+			__stubs_start,
+			__stubs_end - __stubs_start);
+
+	early_signal_init();
+
+	flush_icache_range(vectors, vectors + PAGE_SIZE);
+}
diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..0b4eb89
--- /dev/null
+++ b/arch/unicore32/kernel/vmlinux.lds.S
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/unicore32/kernel/vmlinux.lds.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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-generic/vmlinux.lds.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+
+OUTPUT_ARCH(unicore32)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+SECTIONS
+{
+	. = PAGE_OFFSET + KERNEL_IMAGE_START;
+
+	_text = .;
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	INIT_DATA_SECTION(16)
+	PERCPU(PAGE_SIZE)
+	__init_end = .;
+
+	_stext = .;
+	.text : {		/* Real text segment */
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+
+		*(.fixup)
+		*(.gnu.warning)
+	}
+	_etext = .;
+
+	_sdata = .;
+	RO_DATA_SECTION(PAGE_SIZE)
+	RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
+	_edata = .;
+
+	EXCEPTION_TABLE(32)
+	NOTES
+
+	BSS_SECTION(0, 0, 0)
+	_end = .;
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+	DISCARDS		/* Exit code and data */
+}
diff --git a/arch/unicore32/lib/Makefile b/arch/unicore32/lib/Makefile
new file mode 100644
index 0000000..87229a5
--- /dev/null
+++ b/arch/unicore32/lib/Makefile
@@ -0,0 +1,27 @@
+#
+# linux/arch/unicore32/lib/Makefile
+#
+# Copyright (C) 2001-2010 GUAN Xue-tao
+#
+
+lib-y	:= backtrace.o delay.o findbit.o
+lib-y	+= strncpy_from_user.o strnlen_user.o
+lib-y	+= clear_user.o copy_page.o
+lib-y	+= copy_from_user.o copy_to_user.o
+
+GNU_LIBC_A		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libc.a)
+GNU_LIBC_A_OBJS		:= memchr.o memcpy.o memmove.o memset.o
+GNU_LIBC_A_OBJS		+= strchr.o strrchr.o
+GNU_LIBC_A_OBJS		+= rawmemchr.o			# needed by strrchr.o
+
+GNU_LIBGCC_A		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a)
+GNU_LIBGCC_A_OBJS	:= _ashldi3.o _ashrdi3.o _lshrdi3.o
+GNU_LIBGCC_A_OBJS	+= _divsi3.o _modsi3.o _ucmpdi2.o _umodsi3.o _udivsi3.o
+
+lib-y	+= $(GNU_LIBC_A_OBJS) $(GNU_LIBGCC_A_OBJS)
+
+$(addprefix $(obj)/, $(GNU_LIBC_A_OBJS)):
+	$(Q)$(AR) p $(GNU_LIBC_A) $(notdir $@) > $@
+
+$(addprefix $(obj)/, $(GNU_LIBGCC_A_OBJS)):
+	$(Q)$(AR) p $(GNU_LIBGCC_A) $(notdir $@) > $@
diff --git a/arch/unicore32/lib/backtrace.S b/arch/unicore32/lib/backtrace.S
new file mode 100644
index 0000000..ef01d77
--- /dev/null
+++ b/arch/unicore32/lib/backtrace.S
@@ -0,0 +1,163 @@
+/*
+ * linux/arch/unicore32/lib/backtrace.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+		.text
+
+@ fp is 0 or stack frame
+
+#define frame	v4
+#define sv_fp	v5
+#define sv_pc	v6
+#define offset	v8
+
+ENTRY(__backtrace)
+		mov	r0, fp
+
+ENTRY(c_backtrace)
+
+#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
+		mov	pc, lr
+ENDPROC(__backtrace)
+ENDPROC(c_backtrace)
+#else
+		stm.w	(v4 - v8, lr), [sp-]	@ Save an extra register
+						@ so we have a location...
+		mov.a	frame, r0		@ if frame pointer is zero
+		beq	no_frame		@ we have no stack frames
+
+1:		stm.w	(pc), [sp-]		@ calculate offset of PC stored
+		ldw.w	r0, [sp]+, #4		@ by stmfd for this CPU
+		adr	r1, 1b
+		sub	offset, r0, r1
+
+/*
+ * Stack frame layout:
+ *             optionally saved caller registers (r4 - r10)
+ *             saved fp
+ *             saved sp
+ *             saved lr
+ *    frame => saved pc
+ *             optionally saved arguments (r0 - r3)
+ * saved sp => <next word>
+ *
+ * Functions start with the following code sequence:
+ *                  mov   ip, sp
+ *                  stm.w (r0 - r3), [sp-] (optional)
+ * corrected pc =>  stm.w sp, (..., fp, ip, lr, pc)
+ */
+for_each_frame:
+
+1001:		ldw	sv_pc, [frame+], #0	@ get saved pc
+1002:		ldw	sv_fp, [frame+], #-12	@ get saved fp
+
+		sub	sv_pc, sv_pc, offset	@ Correct PC for prefetching
+
+1003:		ldw	r2, [sv_pc+], #-4	@ if stmfd sp, {args} exists,
+		ldw	r3, .Ldsi+4		@ adjust saved 'pc' back one
+		cxor.a	r3, r2 >> #14		@ instruction
+		beq	201f
+		sub	r0, sv_pc, #4		@ allow for mov
+		b	202f
+201:
+		sub	r0, sv_pc, #8		@ allow for mov + stmia
+202:
+		ldw	r1, [frame+], #-4	@ get saved lr
+		mov	r2, frame
+		b.l	dump_backtrace_entry
+
+		ldw	r1, [sv_pc+], #-4	@ if stmfd sp, {args} exists,
+		ldw	r3, .Ldsi+4
+		cxor.a	r3, r1 >> #14
+		bne	1004f
+		ldw	r0, [frame+], #-8	@ get sp
+		sub	r0, r0, #4		@ point at the last arg
+		b.l	.Ldumpstm		@ dump saved registers
+
+1004:		ldw	r1, [sv_pc+], #0	@ if stmfd {, fp, ip, lr, pc}
+		ldw	r3, .Ldsi		@ instruction exists,
+		cxor.a	r3, r1 >> #14
+		bne	201f
+		sub	r0, frame, #16
+		b.l	.Ldumpstm		@ dump saved registers
+201:
+		cxor.a	sv_fp, #0		@ zero saved fp means
+		beq	no_frame		@ no further frames
+
+		csub.a	sv_fp, frame		@ next frame must be
+		mov	frame, sv_fp		@ above the current frame
+		bua	for_each_frame
+
+1006:		adr	r0, .Lbad
+		mov	r1, frame
+		b.l	printk
+no_frame:	ldm.w	(v4 - v8, pc), [sp]+
+ENDPROC(__backtrace)
+ENDPROC(c_backtrace)
+
+		.pushsection __ex_table,"a"
+		.align	3
+		.long	1001b, 1006b
+		.long	1002b, 1006b
+		.long	1003b, 1006b
+		.long	1004b, 1006b
+		.popsection
+
+#define instr v4
+#define reg   v5
+#define stack v6
+
+.Ldumpstm:	stm.w	(instr, reg, stack, v7, lr), [sp-]
+		mov	stack, r0
+		mov	instr, r1
+		mov	reg, #14
+		mov	v7, #0
+1:		mov	r3, #1
+		csub.a	reg, #8
+		bne	201f
+		sub	reg, reg, #3
+201:
+		cand.a	instr, r3 << reg
+		beq	2f
+		add	v7, v7, #1
+		cxor.a	v7, #6
+		cmoveq	v7, #1
+		cmoveq	r1, #'\n'
+		cmovne	r1, #' '
+		ldw.w	r3, [stack]+, #-4
+		mov	r2, reg
+		csub.a	r2, #8
+		bsl	201f
+		sub	r2, r2, #3
+201:
+		cand.a	instr, #0x40		@ if H is 1, high 16 regs
+		beq	201f
+		add	r2, r2, #0x10		@ so r2 need add 16
+201:
+		adr	r0, .Lfp
+		b.l	printk
+2:		sub.a	reg, reg, #1
+		bns	1b
+		cxor.a	v7, #0
+		beq	201f
+		adr	r0, .Lcr
+		b.l	printk
+201:		ldm.w	(instr, reg, stack, v7, pc), [sp]+
+
+.Lfp:		.asciz	"%cr%d:%08x"
+.Lcr:		.asciz	"\n"
+.Lbad:		.asciz	"Backtrace aborted due to bad frame pointer <%p>\n"
+		.align
+.Ldsi:		.word	0x92eec000 >> 14	@ stm.w sp, (... fp, ip, lr, pc)
+		.word	0x92e10000 >> 14	@ stm.w sp, ()
+
+#endif
diff --git a/arch/unicore32/lib/clear_user.S b/arch/unicore32/lib/clear_user.S
new file mode 100644
index 0000000..20047f7
--- /dev/null
+++ b/arch/unicore32/lib/clear_user.S
@@ -0,0 +1,57 @@
+/*
+ * linux/arch/unicore32/lib/clear_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+/* Prototype: int __clear_user(void *addr, size_t sz)
+ * Purpose  : clear some user memory
+ * Params   : addr - user memory address to clear
+ *          : sz   - number of bytes to clear
+ * Returns  : number of bytes NOT cleared
+ */
+WEAK(__clear_user)
+		stm.w	(lr), [sp-]
+		stm.w	(r1), [sp-]
+		mov	r2, #0
+		csub.a	r1, #4
+		bsl	2f
+		and.a	ip, r0, #3
+		beq	1f
+		csub.a	ip, #2
+		strusr	r2, r0, 1
+		strusr	r2, r0, 1, el
+		strusr	r2, r0, 1, sl
+		rsub	ip, ip, #4
+		sub	r1, r1, ip		@  7  6  5  4  3  2  1
+1:		sub.a	r1, r1, #8		@ -1 -2 -3 -4 -5 -6 -7
+		strusr	r2, r0, 4, ns, rept=2
+		bns	1b
+		add.a	r1, r1, #4		@  3  2  1  0 -1 -2 -3
+		strusr	r2, r0, 4, ns
+2:		cand.a	r1, #2			@ 1x 1x 0x 0x 1x 1x 0x
+		strusr	r2, r0, 1, ne, rept=2
+		cand.a	r1, #1			@ x1 x0 x1 x0 x1 x0 x1
+		beq	3f
+USER(		stb.u	r2, [r0])
+3:		mov	r0, #0
+		ldm.w	(r1), [sp]+
+		ldm.w	(pc), [sp]+
+ENDPROC(__clear_user)
+
+		.pushsection .fixup,"ax"
+		.align	0
+9001:		ldm.w	(r0), [sp]+
+		ldm.w	(pc), [sp]+
+		.popsection
+
diff --git a/arch/unicore32/lib/copy_from_user.S b/arch/unicore32/lib/copy_from_user.S
new file mode 100644
index 0000000..ab0767e
--- /dev/null
+++ b/arch/unicore32/lib/copy_from_user.S
@@ -0,0 +1,108 @@
+/*
+ * linux/arch/unicore32/lib/copy_from_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Prototype:
+ *
+ *	size_t __copy_from_user(void *to, const void *from, size_t n)
+ *
+ * Purpose:
+ *
+ *	copy a block to kernel memory from user memory
+ *
+ * Params:
+ *
+ *	to = kernel memory
+ *	from = user memory
+ *	n = number of bytes to copy
+ *
+ * Return value:
+ *
+ *	Number of bytes NOT copied.
+ */
+
+	.macro ldr1w ptr reg abort
+	ldrusr	\reg, \ptr, 4, abort=\abort
+	.endm
+
+	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
+100:	ldm.w	(\reg1, \reg2, \reg3, \reg4), [\ptr]+
+	.pushsection __ex_table, "a"
+	.align	3
+	.long 100b, \abort
+	.popsection
+	.endm
+
+	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+100:	ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+	.pushsection __ex_table, "a"
+	.align	3
+	.long 100b, \abort
+	.popsection
+	.endm
+
+	.macro ldr1b ptr reg cond=al abort
+	ldrusr	\reg, \ptr, 1, \cond, abort=\abort
+	.endm
+
+	.macro str1w ptr reg abort
+	stw.w \reg, [\ptr]+, #4
+	.endm
+
+	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+	stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+	.endm
+
+	.macro str1b ptr reg cond=al abort
+	.ifnc	\cond, al
+	b\cond	201f
+	b	202f
+	.endif
+201:	stb.w \reg, [\ptr]+, #1
+202:
+	.endm
+
+	.macro enter
+	mov	r3, #0
+	stm.w	(r0, r2, r3), [sp-]
+	.endm
+
+	.macro exit
+	add	sp, sp, #8
+	ldm.w	(r0), [sp]+
+	mov	pc, lr
+	.endm
+
+	.text
+
+ENTRY(__copy_from_user)
+
+#include "copy_template.S"
+
+ENDPROC(__copy_from_user)
+
+	.pushsection .fixup,"ax"
+	.align 0
+	copy_abort_preamble
+	ldm.w	(r1, r2), [sp]+
+	sub	r3, r0, r1
+	rsub	r2, r3, r2
+	stw	r2, [sp]
+	mov	r1, #0
+	b.l	memset
+	ldw.w	r0, [sp]+, #4
+	copy_abort_end
+	.popsection
+
diff --git a/arch/unicore32/lib/copy_page.S b/arch/unicore32/lib/copy_page.S
new file mode 100644
index 0000000..3a448d7
--- /dev/null
+++ b/arch/unicore32/lib/copy_page.S
@@ -0,0 +1,39 @@
+/*
+ * linux/arch/unicore32/lib/copy_page.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ASM optimised string functions
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <generated/asm-offsets.h>
+#include <asm/cache.h>
+
+#define COPY_COUNT (PAGE_SZ/256)
+
+		.text
+		.align	5
+/*
+ * UniCore optimised copy_page routine
+ */
+ENTRY(copy_page)
+		stm.w	(r17 - r19, lr), [sp-]
+		mov	r17, r0
+		mov	r18, r1
+		mov	r19, #COPY_COUNT
+1:
+	.rept	4
+		ldm.w	(r0 - r15), [r18]+
+		stm.w	(r0 - r15), [r17]+
+	.endr
+		sub.a	r19, r19, #1
+		bne	1b
+		ldm.w	(r17 - r19, pc), [sp]+
+ENDPROC(copy_page)
diff --git a/arch/unicore32/lib/copy_template.S b/arch/unicore32/lib/copy_template.S
new file mode 100644
index 0000000..524287f
--- /dev/null
+++ b/arch/unicore32/lib/copy_template.S
@@ -0,0 +1,214 @@
+/*
+ * linux/arch/unicore32/lib/copy_template.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * Theory of operation
+ * -------------------
+ *
+ * This file provides the core code for a forward memory copy used in
+ * the implementation of memcopy(), copy_to_user() and copy_from_user().
+ *
+ * The including file must define the following accessor macros
+ * according to the need of the given function:
+ *
+ * ldr1w ptr reg abort
+ *
+ *	This loads one word from 'ptr', stores it in 'reg' and increments
+ *	'ptr' to the next word. The 'abort' argument is used for fixup tables.
+ *
+ * ldr4w ptr reg1 reg2 reg3 reg4 abort
+ * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ *
+ *	This loads four or eight words starting from 'ptr', stores them
+ *	in provided registers and increments 'ptr' past those words.
+ *	The'abort' argument is used for fixup tables.
+ *
+ * ldr1b ptr reg cond abort
+ *
+ *	Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
+ *	It also must apply the condition code if provided, otherwise the
+ *	"al" condition is assumed by default.
+ *
+ * str1w ptr reg abort
+ * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ * str1b ptr reg cond abort
+ *
+ *	Same as their ldr* counterparts, but data is stored to 'ptr' location
+ *	rather than being loaded.
+ *
+ * enter
+ *
+ *	Preserve the provided registers on the stack plus any additional
+ *	data as needed by the implementation including this code. Called
+ *	upon code entry.
+ *
+ * exit
+ *
+ *	Restore registers with the values previously saved with the
+ *	'preserv' macro. Called upon code termination.
+ */
+
+
+		enter
+
+		sub.a	r2, r2, #4
+		bsl	8f
+		and.a	ip, r0, #3
+		bne	9f
+		and.a	ip, r1, #3
+		bne	10f
+
+1:		sub.a	r2, r2, #(28)
+		stm.w	(r5 - r8), [sp-]
+		bsl	5f
+
+3:
+4:		ldr8w	r1, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
+		sub.a	r2, r2, #32
+		str8w	r0, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
+		beg	3b
+
+5:		and.a	ip, r2, #28
+		rsub	ip, ip, #32
+		beq	7f
+		add	pc, pc, ip		@ C is always clear here
+		nop
+
+		ldr1w	r1, r3, abort=20f
+		ldr1w	r1, r4, abort=20f
+		ldr1w	r1, r5, abort=20f
+		ldr1w	r1, r6, abort=20f
+		ldr1w	r1, r7, abort=20f
+		ldr1w	r1, r8, abort=20f
+		ldr1w	r1, r11, abort=20f
+
+		add	pc, pc, ip
+		nop
+
+		str1w	r0, r3, abort=20f
+		str1w	r0, r4, abort=20f
+		str1w	r0, r5, abort=20f
+		str1w	r0, r6, abort=20f
+		str1w	r0, r7, abort=20f
+		str1w	r0, r8, abort=20f
+		str1w	r0, r11, abort=20f
+
+7:		ldm.w	(r5 - r8), [sp]+
+
+8:		mov.a	r2, r2 << #31
+		ldr1b	r1, r3, ne, abort=21f
+		ldr1b	r1, r4, ea, abort=21f
+		ldr1b	r1, r10, ea, abort=21f
+		str1b	r0, r3, ne, abort=21f
+		str1b	r0, r4, ea, abort=21f
+		str1b	r0, r10, ea, abort=21f
+
+		exit
+
+9:		rsub	ip, ip, #4
+		csub.a	ip, #2
+		ldr1b	r1, r3, sg, abort=21f
+		ldr1b	r1, r4, eg, abort=21f
+		ldr1b	r1, r11, abort=21f
+		str1b	r0, r3, sg, abort=21f
+		str1b	r0, r4, eg, abort=21f
+		sub.a	r2, r2, ip
+		str1b	r0, r11, abort=21f
+		bsl	8b
+		and.a	ip, r1, #3
+		beq	1b
+
+10:		andn	r1, r1, #3
+		csub.a	ip, #2
+		ldr1w	r1, r11, abort=21f
+		beq	17f
+		bsg	18f
+
+
+		.macro	forward_copy_shift a b
+
+		sub.a	r2, r2, #28
+		bsl	14f
+
+11:		stm.w	(r5 - r9), [sp-]
+
+12:
+		ldr4w	r1, r4, r5, r6, r7, abort=19f
+		mov	r3, r11 pull #\a
+		sub.a	r2, r2, #32
+		ldr4w	r1, r8, r9, r10, r11, abort=19f
+		or	r3, r3, r4 push #\b
+		mov	r4, r4 pull #\a
+		or	r4, r4, r5 push #\b
+		mov	r5, r5 pull #\a
+		or	r5, r5, r6 push #\b
+		mov	r6, r6 pull #\a
+		or	r6, r6, r7 push #\b
+		mov	r7, r7 pull #\a
+		or	r7, r7, r8 push #\b
+		mov	r8, r8 pull #\a
+		or	r8, r8, r9 push #\b
+		mov	r9, r9 pull #\a
+		or	r9, r9, r10 push #\b
+		mov	r10, r10 pull #\a
+		or	r10, r10, r11 push #\b
+		str8w	r0, r3, r4, r5, r6, r7, r8, r9, r10, , abort=19f
+		beg	12b
+
+		ldm.w	(r5 - r9), [sp]+
+
+14:		and.a	ip, r2, #28
+		beq	16f
+
+15:		mov	r3, r11 pull #\a
+		ldr1w	r1, r11, abort=21f
+		sub.a	ip, ip, #4
+		or	r3, r3, r11 push #\b
+		str1w	r0, r3, abort=21f
+		bsg	15b
+
+16:		sub	r1, r1, #(\b / 8)
+		b	8b
+
+		.endm
+
+
+		forward_copy_shift	a=8	b=24
+
+17:		forward_copy_shift	a=16	b=16
+
+18:		forward_copy_shift	a=24	b=8
+
+
+/*
+ * Abort preamble and completion macros.
+ * If a fixup handler is required then those macros must surround it.
+ * It is assumed that the fixup code will handle the private part of
+ * the exit macro.
+ */
+
+	.macro	copy_abort_preamble
+19:	ldm.w	(r5 - r9), [sp]+
+	b	21f
+299:	.word	0			@ store lr
+					@ to avoid function call in fixup
+20:	ldm.w	(r5 - r8), [sp]+
+21:
+	adr	r1, 299b
+	stw	lr, [r1]
+	.endm
+
+	.macro	copy_abort_end
+	adr	lr, 299b
+	ldw	pc, [lr]
+	.endm
+
diff --git a/arch/unicore32/lib/copy_to_user.S b/arch/unicore32/lib/copy_to_user.S
new file mode 100644
index 0000000..6e22151
--- /dev/null
+++ b/arch/unicore32/lib/copy_to_user.S
@@ -0,0 +1,96 @@
+/*
+ * linux/arch/unicore32/lib/copy_to_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+/*
+ * Prototype:
+ *
+ *	size_t __copy_to_user(void *to, const void *from, size_t n)
+ *
+ * Purpose:
+ *
+ *	copy a block to user memory from kernel memory
+ *
+ * Params:
+ *
+ *	to = user memory
+ *	from = kernel memory
+ *	n = number of bytes to copy
+ *
+ * Return value:
+ *
+ *	Number of bytes NOT copied.
+ */
+
+	.macro ldr1w ptr reg abort
+	ldw.w \reg, [\ptr]+, #4
+	.endm
+
+	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
+	ldm.w	(\reg1, \reg2, \reg3, \reg4), [\ptr]+
+	.endm
+
+	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+	ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+	.endm
+
+	.macro ldr1b ptr reg cond=al abort
+	notcond	\cond, .+8
+	ldb.w \reg, [\ptr]+, #1
+	.endm
+
+	.macro str1w ptr reg abort
+	strusr	\reg, \ptr, 4, abort=\abort
+	.endm
+
+	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+100:	stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+
+	.pushsection __ex_table, "a"
+	.long 100b, \abort
+	.popsection
+	.endm
+
+	.macro str1b ptr reg cond=al abort
+	strusr	\reg, \ptr, 1, \cond, abort=\abort
+	.endm
+
+	.macro enter
+	mov	r3, #0
+	stm.w	(r0, r2, r3), [sp-]
+	.endm
+
+	.macro exit
+	add	sp, sp, #8
+	ldm.w	(r0), [sp]+
+	mov	pc, lr
+	.endm
+
+	.text
+
+WEAK(__copy_to_user)
+
+#include "copy_template.S"
+
+ENDPROC(__copy_to_user)
+
+	.pushsection .fixup,"ax"
+	.align 0
+	copy_abort_preamble
+	ldm.w	(r1, r2, r3), [sp]+
+	sub	r0, r0, r1
+	rsub	r0, r0, r2
+	copy_abort_end
+	.popsection
+
diff --git a/arch/unicore32/lib/delay.S b/arch/unicore32/lib/delay.S
new file mode 100644
index 0000000..24664c0
--- /dev/null
+++ b/arch/unicore32/lib/delay.S
@@ -0,0 +1,51 @@
+/*
+ * linux/arch/unicore32/lib/delay.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/param.h>
+		.text
+
+.LC0:		.word	loops_per_jiffy
+.LC1:		.word	(2199023*HZ)>>11
+
+/*
+ * r0  <= 2000
+ * lpj <= 0x01ffffff (max. 3355 bogomips)
+ * HZ  <= 1000
+ */
+
+ENTRY(__udelay)
+		ldw	r2, .LC1
+		mul	r0, r2, r0
+ENTRY(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
+		ldw	r2, .LC0
+		ldw	r2, [r2]		@ max = 0x01ffffff
+		mov	r0, r0 >> #14		@ max = 0x0001ffff
+		mov	r2, r2 >> #10		@ max = 0x00007fff
+		mul	r0, r2, r0		@ max = 2^32-1
+		mov.a	r0, r0 >> #6
+		cmoveq	pc, lr
+
+/*
+ * loops = r0 * HZ * loops_per_jiffy / 1000000
+ *
+ * Oh, if only we had a cycle counter...
+ */
+
+@ Delay routine
+ENTRY(__delay)
+		sub.a	r0, r0, #2
+		bua	__delay
+		mov	pc, lr
+ENDPROC(__udelay)
+ENDPROC(__const_udelay)
+ENDPROC(__delay)
diff --git a/arch/unicore32/lib/findbit.S b/arch/unicore32/lib/findbit.S
new file mode 100644
index 0000000..c360ce9
--- /dev/null
+++ b/arch/unicore32/lib/findbit.S
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/unicore32/lib/findbit.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+/*
+ * Purpose  : Find a 'zero' bit
+ * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
+ */
+__uc32_find_first_zero_bit:
+		cxor.a	r1, #0
+		beq	3f
+		mov	r2, #0
+1:		ldb	r3, [r0+], r2 >> #3
+		xor.a	r3, r3, #0xff		@ invert bits
+		bne	.L_found		@ any now set - found zero bit
+		add	r2, r2, #8		@ next bit pointer
+2:		csub.a	r2, r1			@ any more?
+		bub	1b
+3:		mov	r0, r1			@ no free bits
+		mov	pc, lr
+
+/*
+ * Purpose  : Find next 'zero' bit
+ * Prototype: int find_next_zero_bit
+ *		(void *addr, unsigned int maxbit, int offset)
+ */
+ENTRY(__uc32_find_next_zero_bit)
+		cxor.a	r1, #0
+		beq	3b
+		and.a	ip, r2, #7
+		beq	1b			@ If new byte, goto old routine
+		ldb	r3, [r0+], r2 >> #3
+		xor	r3, r3, #0xff		@ now looking for a 1 bit
+		mov.a	r3, r3 >> ip		@ shift off unused bits
+		bne	.L_found
+		or	r2, r2, #7		@ if zero, then no bits here
+		add	r2, r2, #1		@ align bit pointer
+		b	2b			@ loop for next bit
+ENDPROC(__uc32_find_next_zero_bit)
+
+/*
+ * Purpose  : Find a 'one' bit
+ * Prototype: int find_first_bit
+ *		(const unsigned long *addr, unsigned int maxbit);
+ */
+__uc32_find_first_bit:
+		cxor.a	r1, #0
+		beq	3f
+		mov	r2, #0
+1:		ldb	r3, [r0+], r2 >> #3
+		mov.a	r3, r3
+		bne	.L_found		@ any now set - found zero bit
+		add	r2, r2, #8		@ next bit pointer
+2:		csub.a	r2, r1			@ any more?
+		bub	1b
+3:		mov	r0, r1			@ no free bits
+		mov	pc, lr
+
+/*
+ * Purpose  : Find next 'one' bit
+ * Prototype: int find_next_zero_bit
+ *		(void *addr, unsigned int maxbit, int offset)
+ */
+ENTRY(__uc32_find_next_bit)
+		cxor.a	r1, #0
+		beq	3b
+		and.a	ip, r2, #7
+		beq	1b			@ If new byte, goto old routine
+		ldb	r3, [r0+], r2 >> #3
+		mov.a	r3, r3 >> ip		@ shift off unused bits
+		bne	.L_found
+		or	r2, r2, #7		@ if zero, then no bits here
+		add	r2, r2, #1		@ align bit pointer
+		b	2b			@ loop for next bit
+ENDPROC(__uc32_find_next_bit)
+
+/*
+ * One or more bits in the LSB of r3 are assumed to be set.
+ */
+.L_found:
+		rsub	r1, r3, #0
+		and	r3, r3, r1
+		cntlz	r3, r3
+		rsub	r3, r3, #31
+		add	r0, r2, r3
+		mov	pc, lr
+
diff --git a/arch/unicore32/lib/strncpy_from_user.S b/arch/unicore32/lib/strncpy_from_user.S
new file mode 100644
index 0000000..ff6c304
--- /dev/null
+++ b/arch/unicore32/lib/strncpy_from_user.S
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/unicore32/lib/strncpy_from_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+	.text
+	.align	5
+
+/*
+ * Copy a string from user space to kernel space.
+ *  r0 = dst, r1 = src, r2 = byte length
+ * returns the number of characters copied (strlen of copied string),
+ *  -EFAULT on exception, or "len" if we fill the whole buffer
+ */
+ENTRY(__strncpy_from_user)
+	mov	ip, r1
+1:	sub.a	r2, r2, #1
+	ldrusr	r3, r1, 1, ns
+	bfs	2f
+	stb.w	r3, [r0]+, #1
+	cxor.a	r3, #0
+	bne	1b
+	sub	r1, r1, #1	@ take NUL character out of count
+2:	sub	r0, r1, ip
+	mov	pc, lr
+ENDPROC(__strncpy_from_user)
+
+	.pushsection .fixup,"ax"
+	.align	0
+9001:	mov	r3, #0
+	stb	r3, [r0+], #0	@ null terminate
+	mov	r0, #-EFAULT
+	mov	pc, lr
+	.popsection
+
diff --git a/arch/unicore32/lib/strnlen_user.S b/arch/unicore32/lib/strnlen_user.S
new file mode 100644
index 0000000..7586303
--- /dev/null
+++ b/arch/unicore32/lib/strnlen_user.S
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/unicore32/lib/strnlen_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+
+	.text
+	.align	5
+
+/* Prototype: unsigned long __strnlen_user(const char *str, long n)
+ * Purpose  : get length of a string in user memory
+ * Params   : str - address of string in user memory
+ * Returns  : length of string *including terminator*
+ *	      or zero on exception, or n + 1 if too long
+ */
+ENTRY(__strnlen_user)
+	mov	r2, r0
+1:
+	ldrusr	r3, r0, 1
+	cxor.a	r3, #0
+	beq	2f
+	sub.a	r1, r1, #1
+	bne	1b
+	add	r0, r0, #1
+2:	sub	r0, r0, r2
+	mov	pc, lr
+ENDPROC(__strnlen_user)
+
+	.pushsection .fixup,"ax"
+	.align	0
+9001:	mov	r0, #0
+	mov	pc, lr
+	.popsection
diff --git a/arch/unicore32/mm/Kconfig b/arch/unicore32/mm/Kconfig
new file mode 100644
index 0000000..5f77fb3
--- /dev/null
+++ b/arch/unicore32/mm/Kconfig
@@ -0,0 +1,50 @@
+comment "Processor Type"
+
+# Select CPU types depending on the architecture selected.  This selects
+# which CPUs we support in the kernel image, and the compiler instruction
+# optimiser behaviour.
+
+config CPU_UCV2
+	def_bool y
+
+comment "Processor Features"
+
+config CPU_ICACHE_DISABLE
+	bool "Disable I-Cache (I-bit)"
+	help
+	  Say Y here to disable the processor instruction cache. Unless
+	  you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_DISABLE
+	bool "Disable D-Cache (D-bit)"
+	help
+	  Say Y here to disable the processor data cache. Unless
+	  you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_WRITETHROUGH
+	bool "Force write through D-cache"
+	help
+	  Say Y here to use the data cache in writethrough mode. Unless you
+	  specifically require this or are unsure, say N.
+
+config CPU_DCACHE_LINE_DISABLE
+	bool "Disable D-cache line ops"
+	default y
+	help
+	  Say Y here to disable the data cache line operations.
+
+config CPU_TLB_SINGLE_ENTRY_DISABLE
+	bool "Disable TLB single entry ops"
+	default y
+	help
+	  Say Y here to disable the TLB single entry operations.
+
+config SWIOTLB
+	def_bool y
+
+config IOMMU_HELPER
+	def_bool SWIOTLB
+
+config NEED_SG_DMA_LENGTH
+	def_bool SWIOTLB
+
diff --git a/arch/unicore32/mm/Makefile b/arch/unicore32/mm/Makefile
new file mode 100644
index 0000000..46c1666
--- /dev/null
+++ b/arch/unicore32/mm/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the linux unicore-specific parts of the memory manager.
+#
+
+obj-y				:= extable.o fault.o init.o pgd.o mmu.o
+obj-y				+= flush.o ioremap.o
+
+obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
+
+obj-$(CONFIG_MODULES)		+= proc-syms.o
+
+obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
+
+obj-$(CONFIG_CPU_UCV2)		+= cache-ucv2.o tlb-ucv2.o proc-ucv2.o
+
diff --git a/arch/unicore32/mm/alignment.c b/arch/unicore32/mm/alignment.c
new file mode 100644
index 0000000..28f576d
--- /dev/null
+++ b/arch/unicore32/mm/alignment.c
@@ -0,0 +1,523 @@
+/*
+ * linux/arch/unicore32/mm/alignment.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/*
+ * TODO:
+ *  FPU ldm/stm not handling
+ */
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+
+#include <asm/tlbflush.h>
+#include <asm/unaligned.h>
+
+#define CODING_BITS(i)	(i & 0xe0000120)
+
+#define LDST_P_BIT(i)	(i & (1 << 28))	/* Preindex             */
+#define LDST_U_BIT(i)	(i & (1 << 27))	/* Add offset           */
+#define LDST_W_BIT(i)	(i & (1 << 25))	/* Writeback            */
+#define LDST_L_BIT(i)	(i & (1 << 24))	/* Load                 */
+
+#define LDST_P_EQ_U(i)	((((i) ^ ((i) >> 1)) & (1 << 27)) == 0)
+
+#define LDSTH_I_BIT(i)	(i & (1 << 26))	/* half-word immed      */
+#define LDM_S_BIT(i)	(i & (1 << 26))	/* write ASR from BSR */
+#define LDM_H_BIT(i)	(i & (1 << 6))	/* select r0-r15 or r16-r31 */
+
+#define RN_BITS(i)	((i >> 19) & 31)	/* Rn                   */
+#define RD_BITS(i)	((i >> 14) & 31)	/* Rd                   */
+#define RM_BITS(i)	(i & 31)	/* Rm                   */
+
+#define REGMASK_BITS(i)	(((i & 0x7fe00) >> 3) | (i & 0x3f))
+#define OFFSET_BITS(i)	(i & 0x03fff)
+
+#define SHIFT_BITS(i)	((i >> 9) & 0x1f)
+#define SHIFT_TYPE(i)	(i & 0xc0)
+#define SHIFT_LSL	0x00
+#define SHIFT_LSR	0x40
+#define SHIFT_ASR	0x80
+#define SHIFT_RORRRX	0xc0
+
+union offset_union {
+	unsigned long un;
+	signed long sn;
+};
+
+#define TYPE_ERROR	0
+#define TYPE_FAULT	1
+#define TYPE_LDST	2
+#define TYPE_DONE	3
+#define TYPE_SWAP  4
+#define TYPE_COLS  5		/* Coprocessor load/store */
+
+#define get8_unaligned_check(val, addr, err)		\
+	__asm__(					\
+	"1:	ldb.u	%1, [%2], #1\n"			\
+	"2:\n"						\
+	"	.pushsection .fixup,\"ax\"\n"		\
+	"	.align	2\n"				\
+	"3:	mov	%0, #1\n"			\
+	"	b	2b\n"				\
+	"	.popsection\n"				\
+	"	.pushsection __ex_table,\"a\"\n"		\
+	"	.align	3\n"				\
+	"	.long	1b, 3b\n"			\
+	"	.popsection\n"				\
+	: "=r" (err), "=&r" (val), "=r" (addr)		\
+	: "0" (err), "2" (addr))
+
+#define get8t_unaligned_check(val, addr, err)		\
+	__asm__(					\
+	"1:	ldb.u	%1, [%2], #1\n"			\
+	"2:\n"						\
+	"	.pushsection .fixup,\"ax\"\n"		\
+	"	.align	2\n"				\
+	"3:	mov	%0, #1\n"			\
+	"	b	2b\n"				\
+	"	.popsection\n"				\
+	"	.pushsection __ex_table,\"a\"\n"		\
+	"	.align	3\n"				\
+	"	.long	1b, 3b\n"			\
+	"	.popsection\n"				\
+	: "=r" (err), "=&r" (val), "=r" (addr)		\
+	: "0" (err), "2" (addr))
+
+#define get16_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8_unaligned_check(val, a, err);		\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 8;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put16_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v = val, a = addr;	\
+		__asm__(					\
+		"1:	stb.u	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"2:	stb.u	%1, [%2]\n"			\
+		"3:\n"						\
+		"	.pushsection .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"4:	mov	%0, #1\n"			\
+		"	b	3b\n"				\
+		"	.popsection\n"				\
+		"	.pushsection __ex_table,\"a\"\n"		\
+		"	.align	3\n"				\
+		"	.long	1b, 4b\n"			\
+		"	.long	2b, 4b\n"			\
+		"	.popsection\n"				\
+		: "=r" (err), "=&r" (v), "=&r" (a)		\
+		: "0" (err), "1" (v), "2" (a));			\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define __put32_unaligned_check(ins, val, addr)			\
+	do {							\
+		unsigned int err = 0, v = val, a = addr;	\
+		__asm__(					\
+		"1:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"2:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"3:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"4:	"ins"	%1, [%2]\n"			\
+		"5:\n"						\
+		"	.pushsection .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"6:	mov	%0, #1\n"			\
+		"	b	5b\n"				\
+		"	.popsection\n"				\
+		"	.pushsection __ex_table,\"a\"\n"		\
+		"	.align	3\n"				\
+		"	.long	1b, 6b\n"			\
+		"	.long	2b, 6b\n"			\
+		"	.long	3b, 6b\n"			\
+		"	.long	4b, 6b\n"			\
+		"	.popsection\n"				\
+		: "=r" (err), "=&r" (v), "=&r" (a)		\
+		: "0" (err), "1" (v), "2" (a));			\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define get32_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8_unaligned_check(val, a, err);		\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 8;					\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 16;					\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 24;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put32_unaligned_check(val, addr)			\
+	__put32_unaligned_check("stb.u", val, addr)
+
+#define get32t_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8t_unaligned_check(val, a, err);		\
+		get8t_unaligned_check(v, a, err);		\
+		val |= v << 8;					\
+		get8t_unaligned_check(v, a, err);		\
+		val |= v << 16;					\
+		get8t_unaligned_check(v, a, err);		\
+		val |= v << 24;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put32t_unaligned_check(val, addr)			\
+	__put32_unaligned_check("stb.u", val, addr)
+
+static void
+do_alignment_finish_ldst(unsigned long addr, unsigned long instr,
+			 struct pt_regs *regs, union offset_union offset)
+{
+	if (!LDST_U_BIT(instr))
+		offset.un = -offset.un;
+
+	if (!LDST_P_BIT(instr))
+		addr += offset.un;
+
+	if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
+		regs->uregs[RN_BITS(instr)] = addr;
+}
+
+static int
+do_alignment_ldrhstrh(unsigned long addr, unsigned long instr,
+		      struct pt_regs *regs)
+{
+	unsigned int rd = RD_BITS(instr);
+
+	/* old value 0x40002120, can't judge swap instr correctly */
+	if ((instr & 0x4b003fe0) == 0x40000120)
+		goto swp;
+
+	if (LDST_L_BIT(instr)) {
+		unsigned long val;
+		get16_unaligned_check(val, addr);
+
+		/* signed half-word? */
+		if (instr & 0x80)
+			val = (signed long)((signed short)val);
+
+		regs->uregs[rd] = val;
+	} else
+		put16_unaligned_check(regs->uregs[rd], addr);
+
+	return TYPE_LDST;
+
+swp:
+	/* only handle swap word
+	 * for swap byte should not active this alignment exception */
+	get32_unaligned_check(regs->uregs[RD_BITS(instr)], addr);
+	put32_unaligned_check(regs->uregs[RM_BITS(instr)], addr);
+	return TYPE_SWAP;
+
+fault:
+	return TYPE_FAULT;
+}
+
+static int
+do_alignment_ldrstr(unsigned long addr, unsigned long instr,
+		    struct pt_regs *regs)
+{
+	unsigned int rd = RD_BITS(instr);
+
+	if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
+		goto trans;
+
+	if (LDST_L_BIT(instr))
+		get32_unaligned_check(regs->uregs[rd], addr);
+	else
+		put32_unaligned_check(regs->uregs[rd], addr);
+	return TYPE_LDST;
+
+trans:
+	if (LDST_L_BIT(instr))
+		get32t_unaligned_check(regs->uregs[rd], addr);
+	else
+		put32t_unaligned_check(regs->uregs[rd], addr);
+	return TYPE_LDST;
+
+fault:
+	return TYPE_FAULT;
+}
+
+/*
+ * LDM/STM alignment handler.
+ *
+ * There are 4 variants of this instruction:
+ *
+ * B = rn pointer before instruction, A = rn pointer after instruction
+ *              ------ increasing address ----->
+ *	        |    | r0 | r1 | ... | rx |    |
+ * PU = 01             B                    A
+ * PU = 11        B                    A
+ * PU = 00        A                    B
+ * PU = 10             A                    B
+ */
+static int
+do_alignment_ldmstm(unsigned long addr, unsigned long instr,
+		    struct pt_regs *regs)
+{
+	unsigned int rd, rn, pc_correction, reg_correction, nr_regs, regbits;
+	unsigned long eaddr, newaddr;
+
+	if (LDM_S_BIT(instr))
+		goto bad;
+
+	pc_correction = 4;	/* processor implementation defined */
+
+	/* count the number of registers in the mask to be transferred */
+	nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
+
+	rn = RN_BITS(instr);
+	newaddr = eaddr = regs->uregs[rn];
+
+	if (!LDST_U_BIT(instr))
+		nr_regs = -nr_regs;
+	newaddr += nr_regs;
+	if (!LDST_U_BIT(instr))
+		eaddr = newaddr;
+
+	if (LDST_P_EQ_U(instr))	/* U = P */
+		eaddr += 4;
+
+	/*
+	 * This is a "hint" - we already have eaddr worked out by the
+	 * processor for us.
+	 */
+	if (addr != eaddr) {
+		printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
+		       "addr = %08lx, eaddr = %08lx\n",
+		       instruction_pointer(regs), instr, addr, eaddr);
+		show_regs(regs);
+	}
+
+	if (LDM_H_BIT(instr))
+		reg_correction = 0x10;
+	else
+		reg_correction = 0x00;
+
+	for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
+	     regbits >>= 1, rd += 1)
+		if (regbits & 1) {
+			if (LDST_L_BIT(instr))
+				get32_unaligned_check(regs->
+					uregs[rd + reg_correction], eaddr);
+			else
+				put32_unaligned_check(regs->
+					uregs[rd + reg_correction], eaddr);
+			eaddr += 4;
+		}
+
+	if (LDST_W_BIT(instr))
+		regs->uregs[rn] = newaddr;
+	return TYPE_DONE;
+
+fault:
+	regs->UCreg_pc -= pc_correction;
+	return TYPE_FAULT;
+
+bad:
+	printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
+	return TYPE_ERROR;
+}
+
+static int
+do_alignment(unsigned long addr, unsigned int error_code, struct pt_regs *regs)
+{
+	union offset_union offset;
+	unsigned long instr, instrptr;
+	int (*handler) (unsigned long addr, unsigned long instr,
+			struct pt_regs *regs);
+	unsigned int type;
+
+	instrptr = instruction_pointer(regs);
+	if (instrptr >= PAGE_OFFSET)
+		instr = *(unsigned long *)instrptr;
+	else {
+		__asm__ __volatile__(
+				"ldw.u	%0, [%1]\n"
+				: "=&r"(instr)
+				: "r"(instrptr));
+	}
+
+	regs->UCreg_pc += 4;
+
+	switch (CODING_BITS(instr)) {
+	case 0x40000120:	/* ldrh or strh */
+		if (LDSTH_I_BIT(instr))
+			offset.un = (instr & 0x3e00) >> 4 | (instr & 31);
+		else
+			offset.un = regs->uregs[RM_BITS(instr)];
+		handler = do_alignment_ldrhstrh;
+		break;
+
+	case 0x60000000:	/* ldr or str immediate */
+	case 0x60000100:	/* ldr or str immediate */
+	case 0x60000020:	/* ldr or str immediate */
+	case 0x60000120:	/* ldr or str immediate */
+		offset.un = OFFSET_BITS(instr);
+		handler = do_alignment_ldrstr;
+		break;
+
+	case 0x40000000:	/* ldr or str register */
+		offset.un = regs->uregs[RM_BITS(instr)];
+		{
+			unsigned int shiftval = SHIFT_BITS(instr);
+
+			switch (SHIFT_TYPE(instr)) {
+			case SHIFT_LSL:
+				offset.un <<= shiftval;
+				break;
+
+			case SHIFT_LSR:
+				offset.un >>= shiftval;
+				break;
+
+			case SHIFT_ASR:
+				offset.sn >>= shiftval;
+				break;
+
+			case SHIFT_RORRRX:
+				if (shiftval == 0) {
+					offset.un >>= 1;
+					if (regs->UCreg_asr & PSR_C_BIT)
+						offset.un |= 1 << 31;
+				} else
+					offset.un = offset.un >> shiftval |
+					    offset.un << (32 - shiftval);
+				break;
+			}
+		}
+		handler = do_alignment_ldrstr;
+		break;
+
+	case 0x80000000:	/* ldm or stm */
+	case 0x80000020:	/* ldm or stm */
+		handler = do_alignment_ldmstm;
+		break;
+
+	default:
+		goto bad;
+	}
+
+	type = handler(addr, instr, regs);
+
+	if (type == TYPE_ERROR || type == TYPE_FAULT)
+		goto bad_or_fault;
+
+	if (type == TYPE_LDST)
+		do_alignment_finish_ldst(addr, instr, regs, offset);
+
+	return 0;
+
+bad_or_fault:
+	if (type == TYPE_ERROR)
+		goto bad;
+	regs->UCreg_pc -= 4;
+	/*
+	 * We got a fault - fix it up, or die.
+	 */
+	do_bad_area(addr, error_code, regs);
+	return 0;
+
+bad:
+	/*
+	 * Oops, we didn't handle the instruction.
+	 * However, we must handle fpu instr firstly.
+	 */
+#ifdef CONFIG_UNICORE_FPU_F64
+	/* handle co.load/store */
+#define CODING_COLS                0xc0000000
+#define COLS_OFFSET_BITS(i)	(i & 0x1FF)
+#define COLS_L_BITS(i)		(i & (1<<24))
+#define COLS_FN_BITS(i)		((i>>14) & 31)
+	if ((instr & 0xe0000000) == CODING_COLS) {
+		unsigned int fn = COLS_FN_BITS(instr);
+		unsigned long val = 0;
+		if (COLS_L_BITS(instr)) {
+			get32t_unaligned_check(val, addr);
+			switch (fn) {
+#define ASM_MTF(n)	case n:						\
+			__asm__ __volatile__("MTF %0, F" __stringify(n)	\
+				: : "r"(val));				\
+			break;
+			ASM_MTF(0); ASM_MTF(1); ASM_MTF(2); ASM_MTF(3);
+			ASM_MTF(4); ASM_MTF(5); ASM_MTF(6); ASM_MTF(7);
+			ASM_MTF(8); ASM_MTF(9); ASM_MTF(10); ASM_MTF(11);
+			ASM_MTF(12); ASM_MTF(13); ASM_MTF(14); ASM_MTF(15);
+			ASM_MTF(16); ASM_MTF(17); ASM_MTF(18); ASM_MTF(19);
+			ASM_MTF(20); ASM_MTF(21); ASM_MTF(22); ASM_MTF(23);
+			ASM_MTF(24); ASM_MTF(25); ASM_MTF(26); ASM_MTF(27);
+			ASM_MTF(28); ASM_MTF(29); ASM_MTF(30); ASM_MTF(31);
+#undef ASM_MTF
+			}
+		} else {
+			switch (fn) {
+#define ASM_MFF(n)	case n:						\
+			__asm__ __volatile__("MFF %0, F" __stringify(n)	\
+				: : "r"(val));				\
+			break;
+			ASM_MFF(0); ASM_MFF(1); ASM_MFF(2); ASM_MFF(3);
+			ASM_MFF(4); ASM_MFF(5); ASM_MFF(6); ASM_MFF(7);
+			ASM_MFF(8); ASM_MFF(9); ASM_MFF(10); ASM_MFF(11);
+			ASM_MFF(12); ASM_MFF(13); ASM_MFF(14); ASM_MFF(15);
+			ASM_MFF(16); ASM_MFF(17); ASM_MFF(18); ASM_MFF(19);
+			ASM_MFF(20); ASM_MFF(21); ASM_MFF(22); ASM_MFF(23);
+			ASM_MFF(24); ASM_MFF(25); ASM_MFF(26); ASM_MFF(27);
+			ASM_MFF(28); ASM_MFF(29); ASM_MFF(30); ASM_MFF(31);
+#undef ASM_MFF
+			}
+			put32t_unaligned_check(val, addr);
+		}
+		return TYPE_COLS;
+	}
+fault:
+	return TYPE_FAULT;
+#endif
+	printk(KERN_ERR "Alignment trap: not handling instruction "
+	       "%08lx at [<%08lx>]\n", instr, instrptr);
+	return 1;
+}
+
+/*
+ * This needs to be done after sysctl_init, otherwise sys/ will be
+ * overwritten.  Actually, this shouldn't be in sys/ at all since
+ * it isn't a sysctl, and it doesn't contain sysctl information.
+ */
+static int __init alignment_init(void)
+{
+	hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
+			"alignment exception");
+
+	return 0;
+}
+
+fs_initcall(alignment_init);
diff --git a/arch/unicore32/mm/cache-ucv2.S b/arch/unicore32/mm/cache-ucv2.S
new file mode 100644
index 0000000..ecaa172
--- /dev/null
+++ b/arch/unicore32/mm/cache-ucv2.S
@@ -0,0 +1,212 @@
+/*
+ * linux/arch/unicore32/mm/cache-ucv2.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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 is the "shell" of the UniCore-v2 processor support.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/page.h>
+
+#include "proc-macros.S"
+
+/*
+ *	__cpuc_flush_icache_all()
+ *	__cpuc_flush_kern_all()
+ *	__cpuc_flush_user_all()
+ *
+ *	Flush the entire cache.
+ */
+ENTRY(__cpuc_flush_icache_all)
+	/*FALLTHROUGH*/
+ENTRY(__cpuc_flush_kern_all)
+	/*FALLTHROUGH*/
+ENTRY(__cpuc_flush_user_all)
+	mov	r0, #0
+	movc	p0.c5, r0, #14			@ Dcache flush all
+	nop8
+
+	mov	r0, #0
+	movc	p0.c5, r0, #20			@ Icache invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_flush_user_range(start, end, flags)
+ *
+ *	Flush a range of TLB entries in the specified address space.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ *	- flags	- vm_area_struct flags describing address space
+ */
+ENTRY(__cpuc_flush_user_range)
+	cxor.a	r2, #0
+	beq	__cpuc_dma_flush_range
+
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
+	sub	r1, r1, r0
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+101:	dcacheline_flush	r0, r11, r12
+
+	add	r0, r0, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	101b
+	b	3f
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #14			@ Dcache flush all
+	nop8
+
+3:	mov	ip, #0
+	movc	p0.c5, ip, #20			@ Icache invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_coherent_kern_range(start,end)
+ *	__cpuc_coherent_user_range(start,end)
+ *
+ *	Ensure that the I and D caches are coherent within specified
+ *	region.  This is typically used when code has been written to
+ *	a memory region, and will be executed.
+ *
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(__cpuc_coherent_kern_range)
+	/* FALLTHROUGH */
+ENTRY(__cpuc_coherent_user_range)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
+	sub	r1, r1, r0
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+	@ r0 va2pa r10
+	mov	r9, #PAGE_SZ
+	sub	r9, r9, #1			@ PAGE_MASK
+101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
+	b	103f
+102:	cand.a	r0, r9
+	beq	101b
+
+103:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
+	nop8
+
+	add	r0, r0, #CACHE_LINESIZE
+	add	r10, r10, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	102b
+	b	3f
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #10			@ Dcache clean all
+	nop8
+
+3:	mov	ip, #0
+	movc	p0.c5, ip, #20			@ Icache invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_flush_kern_dcache_area(void *addr, size_t size)
+ *
+ *	- addr	- kernel address
+ *	- size	- region size
+ */
+ENTRY(__cpuc_flush_kern_dcache_area)
+	mov	ip, #0
+	movc	p0.c5, ip, #14			@ Dcache flush all
+	nop8
+	mov	pc, lr
+
+/*
+ *	__cpuc_dma_clean_range(start,end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(__cpuc_dma_clean_range)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1
+	sub	r1, r1, r0
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	@ r0 va2pa r10
+	mov	r9, #PAGE_SZ
+	sub	r9, r9, #1			@ PAGE_MASK
+101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
+	b	1f
+102:	cand.a	r0, r9
+	beq	101b
+
+1:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
+	nop8
+	add	r0, r0, #CACHE_LINESIZE
+	add	r10, r10, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	102b
+	mov	pc, lr
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #10			@ Dcache clean all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_dma_inv_range(start,end)
+ *	__cpuc_dma_flush_range(start,end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+__cpuc_dma_inv_range:
+	/* FALLTHROUGH */
+ENTRY(__cpuc_dma_flush_range)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1
+	sub	r1, r1, r0
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	@ r0 va2pa r10
+101:	dcacheline_flush	r0, r11, r12
+
+	add	r0, r0, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	101b
+	mov	pc, lr
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #14			@ Dcache flush all
+	nop8
+
+	mov	pc, lr
+
diff --git a/arch/unicore32/mm/dma-swiotlb.c b/arch/unicore32/mm/dma-swiotlb.c
new file mode 100644
index 0000000..bfa9fbb
--- /dev/null
+++ b/arch/unicore32/mm/dma-swiotlb.c
@@ -0,0 +1,34 @@
+/*
+ * Contains routines needed to support swiotlb for UniCore32.
+ *
+ * Copyright (C) 2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/pci.h>
+#include <linux/cache.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
+#include <linux/bootmem.h>
+
+#include <asm/dma.h>
+
+struct dma_map_ops swiotlb_dma_map_ops = {
+	.alloc_coherent = swiotlb_alloc_coherent,
+	.free_coherent = swiotlb_free_coherent,
+	.map_sg = swiotlb_map_sg_attrs,
+	.unmap_sg = swiotlb_unmap_sg_attrs,
+	.dma_supported = swiotlb_dma_supported,
+	.map_page = swiotlb_map_page,
+	.unmap_page = swiotlb_unmap_page,
+	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+	.sync_single_for_device = swiotlb_sync_single_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_device,
+	.mapping_error = swiotlb_dma_mapping_error,
+};
+EXPORT_SYMBOL(swiotlb_dma_map_ops);
diff --git a/arch/unicore32/mm/extable.c b/arch/unicore32/mm/extable.c
new file mode 100644
index 0000000..6564180
--- /dev/null
+++ b/arch/unicore32/mm/extable.c
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/mm/extable.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(instruction_pointer(regs));
+	if (fixup)
+		regs->UCreg_pc = fixup->fixup;
+
+	return fixup != NULL;
+}
diff --git a/arch/unicore32/mm/fault.c b/arch/unicore32/mm/fault.c
new file mode 100644
index 0000000..283aa4b
--- /dev/null
+++ b/arch/unicore32/mm/fault.c
@@ -0,0 +1,479 @@
+/*
+ * linux/arch/unicore32/mm/fault.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/signal.h>
+#include <linux/mm.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/page-flags.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Fault status register encodings.  We steal bit 31 for our own purposes.
+ */
+#define FSR_LNX_PF		(1 << 31)
+
+static inline int fsr_fs(unsigned int fsr)
+{
+	/* xyabcde will be abcde+xy */
+	return (fsr & 31) + ((fsr & (3 << 5)) >> 5);
+}
+
+/*
+ * This is useful to dump out the page tables associated with
+ * 'addr' in mm 'mm'.
+ */
+void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+
+	if (!mm)
+		mm = &init_mm;
+
+	printk(KERN_ALERT "pgd = %p\n", mm->pgd);
+	pgd = pgd_offset(mm, addr);
+	printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
+
+	do {
+		pmd_t *pmd;
+		pte_t *pte;
+
+		if (pgd_none(*pgd))
+			break;
+
+		if (pgd_bad(*pgd)) {
+			printk("(bad)");
+			break;
+		}
+
+		pmd = pmd_offset((pud_t *) pgd, addr);
+		if (PTRS_PER_PMD != 1)
+			printk(", *pmd=%08lx", pmd_val(*pmd));
+
+		if (pmd_none(*pmd))
+			break;
+
+		if (pmd_bad(*pmd)) {
+			printk("(bad)");
+			break;
+		}
+
+		/* We must not map this if we have highmem enabled */
+		if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
+			break;
+
+		pte = pte_offset_map(pmd, addr);
+		printk(", *pte=%08lx", pte_val(*pte));
+		pte_unmap(pte);
+	} while (0);
+
+	printk("\n");
+}
+
+/*
+ * Oops.  The kernel tried to access some page that wasn't present.
+ */
+static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
+		unsigned int fsr, struct pt_regs *regs)
+{
+	/*
+	 * Are we prepared to handle this kernel fault?
+	 */
+	if (fixup_exception(regs))
+		return;
+
+	/*
+	 * No handler, we'll have to terminate things with extreme prejudice.
+	 */
+	bust_spinlocks(1);
+	printk(KERN_ALERT
+	       "Unable to handle kernel %s at virtual address %08lx\n",
+	       (addr < PAGE_SIZE) ? "NULL pointer dereference" :
+	       "paging request", addr);
+
+	show_pte(mm, addr);
+	die("Oops", regs, fsr);
+	bust_spinlocks(0);
+	do_exit(SIGKILL);
+}
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * User mode accesses just cause a SIGSEGV
+ */
+static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
+		unsigned int fsr, unsigned int sig, int code,
+		struct pt_regs *regs)
+{
+	struct siginfo si;
+
+	tsk->thread.address = addr;
+	tsk->thread.error_code = fsr;
+	tsk->thread.trap_no = 14;
+	si.si_signo = sig;
+	si.si_errno = 0;
+	si.si_code = code;
+	si.si_addr = (void __user *)addr;
+	force_sig_info(sig, &si, tsk);
+}
+
+void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->active_mm;
+
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (user_mode(regs))
+		__do_user_fault(tsk, addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
+	else
+		__do_kernel_fault(mm, addr, fsr, regs);
+}
+
+#define VM_FAULT_BADMAP		0x010000
+#define VM_FAULT_BADACCESS	0x020000
+
+/*
+ * Check that the permissions on the VMA allow for the fault which occurred.
+ * If we encountered a write fault, we must have write permission, otherwise
+ * we allow any permission.
+ */
+static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
+{
+	unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
+
+	if (!(fsr ^ 0x12))	/* write? */
+		mask = VM_WRITE;
+	if (fsr & FSR_LNX_PF)
+		mask = VM_EXEC;
+
+	return vma->vm_flags & mask ? false : true;
+}
+
+static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
+		struct task_struct *tsk)
+{
+	struct vm_area_struct *vma;
+	int fault;
+
+	vma = find_vma(mm, addr);
+	fault = VM_FAULT_BADMAP;
+	if (unlikely(!vma))
+		goto out;
+	if (unlikely(vma->vm_start > addr))
+		goto check_stack;
+
+	/*
+	 * Ok, we have a good vm_area for this
+	 * memory access, so we can handle it.
+	 */
+good_area:
+	if (access_error(fsr, vma)) {
+		fault = VM_FAULT_BADACCESS;
+		goto out;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault, make
+	 * sure we exit gracefully rather than endlessly redo the fault.
+	 */
+	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
+			    (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
+	if (unlikely(fault & VM_FAULT_ERROR))
+		return fault;
+	if (fault & VM_FAULT_MAJOR)
+		tsk->maj_flt++;
+	else
+		tsk->min_flt++;
+	return fault;
+
+check_stack:
+	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+		goto good_area;
+out:
+	return fault;
+}
+
+static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	int fault, sig, code;
+
+	tsk = current;
+	mm = tsk->mm;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_atomic() || !mm)
+		goto no_context;
+
+	/*
+	 * As per x86, we may deadlock here.  However, since the kernel only
+	 * validly references user space from well defined areas of the code,
+	 * we can bug out early if this is from code which shouldn't.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if (!user_mode(regs)
+		    && !search_exception_tables(regs->UCreg_pc))
+			goto no_context;
+		down_read(&mm->mmap_sem);
+	} else {
+		/*
+		 * The above down_read_trylock() might have succeeded in
+		 * which case, we'll have missed the might_sleep() from
+		 * down_read()
+		 */
+		might_sleep();
+#ifdef CONFIG_DEBUG_VM
+		if (!user_mode(regs) &&
+		    !search_exception_tables(regs->UCreg_pc))
+			goto no_context;
+#endif
+	}
+
+	fault = __do_pf(mm, addr, fsr, tsk);
+	up_read(&mm->mmap_sem);
+
+	/*
+	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
+	 */
+	if (likely(!(fault &
+	       (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
+		return 0;
+
+	if (fault & VM_FAULT_OOM) {
+		/*
+		 * We ran out of memory, call the OOM killer, and return to
+		 * userspace (which will retry the fault, or kill us if we
+		 * got oom-killed)
+		 */
+		pagefault_out_of_memory();
+		return 0;
+	}
+
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (!user_mode(regs))
+		goto no_context;
+
+	if (fault & VM_FAULT_SIGBUS) {
+		/*
+		 * We had some memory, but were unable to
+		 * successfully fix up this page fault.
+		 */
+		sig = SIGBUS;
+		code = BUS_ADRERR;
+	} else {
+		/*
+		 * Something tried to access memory that
+		 * isn't in our memory map..
+		 */
+		sig = SIGSEGV;
+		code = fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR;
+	}
+
+	__do_user_fault(tsk, addr, fsr, sig, code, regs);
+	return 0;
+
+no_context:
+	__do_kernel_fault(mm, addr, fsr, regs);
+	return 0;
+}
+
+/*
+ * First Level Translation Fault Handler
+ *
+ * We enter here because the first level page table doesn't contain
+ * a valid entry for the address.
+ *
+ * If the address is in kernel space (>= TASK_SIZE), then we are
+ * probably faulting in the vmalloc() area.
+ *
+ * If the init_task's first level page tables contains the relevant
+ * entry, we copy the it to this task.  If not, we send the process
+ * a signal, fixup the exception, or oops the kernel.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may be in an
+ * interrupt or a critical region, and should only copy the information
+ * from the master page table, nothing more.
+ */
+static int do_ifault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	unsigned int index;
+	pgd_t *pgd, *pgd_k;
+	pmd_t *pmd, *pmd_k;
+
+	if (addr < TASK_SIZE)
+		return do_pf(addr, fsr, regs);
+
+	if (user_mode(regs))
+		goto bad_area;
+
+	index = pgd_index(addr);
+
+	pgd = cpu_get_pgd() + index;
+	pgd_k = init_mm.pgd + index;
+
+	if (pgd_none(*pgd_k))
+		goto bad_area;
+
+	pmd_k = pmd_offset((pud_t *) pgd_k, addr);
+	pmd = pmd_offset((pud_t *) pgd, addr);
+
+	if (pmd_none(*pmd_k))
+		goto bad_area;
+
+	set_pmd(pmd, *pmd_k);
+	flush_pmd_entry(pmd);
+	return 0;
+
+bad_area:
+	do_bad_area(addr, fsr, regs);
+	return 0;
+}
+
+/*
+ * This abort handler always returns "fault".
+ */
+static int do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	return 1;
+}
+
+static int do_good(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	unsigned int res1, res2;
+
+	printk("dabt exception but no error!\n");
+
+	__asm__ __volatile__(
+			"mff %0,f0\n"
+			"mff %1,f1\n"
+			: "=r"(res1), "=r"(res2)
+			:
+			: "memory");
+
+	printk(KERN_EMERG "r0 :%08x  r1 :%08x\n", res1, res2);
+	panic("shut up\n");
+	return 0;
+}
+
+static struct fsr_info {
+	int (*fn) (unsigned long addr, unsigned int fsr, struct pt_regs *regs);
+	int sig;
+	int code;
+	const char *name;
+} fsr_info[] = {
+	/*
+	 * The following are the standard Unicore-I and UniCore-II aborts.
+	 */
+	{ do_good,	SIGBUS,  0,		"no error"		},
+	{ do_bad,	SIGBUS,  BUS_ADRALN,	"alignment exception"	},
+	{ do_bad,	SIGBUS,  BUS_OBJERR,	"external exception"	},
+	{ do_bad,	SIGBUS,  0,		"burst operation"	},
+	{ do_bad,	SIGBUS,  0,		"unknown 00100"		},
+	{ do_ifault,	SIGSEGV, SEGV_MAPERR,	"2nd level pt non-exist"},
+	{ do_bad,	SIGBUS,  0,		"2nd lvl large pt non-exist" },
+	{ do_bad,	SIGBUS,  0,		"invalid pte"		},
+	{ do_pf,	SIGSEGV, SEGV_MAPERR,	"page miss"		},
+	{ do_bad,	SIGBUS,  0,		"middle page miss"	},
+	{ do_bad,	SIGBUS,	 0,		"large page miss"	},
+	{ do_pf,	SIGSEGV, SEGV_MAPERR,	"super page (section) miss" },
+	{ do_bad,	SIGBUS,  0,		"unknown 01100"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 01101"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 01110"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 01111"		},
+	{ do_bad,	SIGBUS,  0,		"addr: up 3G or IO"	},
+	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"read unreadable addr"	},
+	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"write unwriteable addr"},
+	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"exec unexecutable addr"},
+	{ do_bad,	SIGBUS,  0,		"unknown 10100"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 10101"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 10110"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 10111"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11000"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11001"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11010"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11011"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11100"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11101"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11110"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11111"		}
+};
+
+void __init hook_fault_code(int nr,
+		int (*fn) (unsigned long, unsigned int, struct pt_regs *),
+		int sig, int code, const char *name)
+{
+	if (nr < 0 || nr >= ARRAY_SIZE(fsr_info))
+		BUG();
+
+	fsr_info[nr].fn   = fn;
+	fsr_info[nr].sig  = sig;
+	fsr_info[nr].code = code;
+	fsr_info[nr].name = name;
+}
+
+/*
+ * Dispatch a data abort to the relevant handler.
+ */
+asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr,
+			struct pt_regs *regs)
+{
+	const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
+	struct siginfo info;
+
+	if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
+		return;
+
+	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
+	       inf->name, fsr, addr);
+
+	info.si_signo = inf->sig;
+	info.si_errno = 0;
+	info.si_code = inf->code;
+	info.si_addr = (void __user *)addr;
+	uc32_notify_die("", regs, &info, fsr, 0);
+}
+
+asmlinkage void do_PrefetchAbort(unsigned long addr,
+			unsigned int ifsr, struct pt_regs *regs)
+{
+	const struct fsr_info *inf = fsr_info + fsr_fs(ifsr);
+	struct siginfo info;
+
+	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
+		return;
+
+	printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
+	       inf->name, ifsr, addr);
+
+	info.si_signo = inf->sig;
+	info.si_errno = 0;
+	info.si_code = inf->code;
+	info.si_addr = (void __user *)addr;
+	uc32_notify_die("", regs, &info, ifsr, 0);
+}
diff --git a/arch/unicore32/mm/flush.c b/arch/unicore32/mm/flush.c
new file mode 100644
index 0000000..93478cc
--- /dev/null
+++ b/arch/unicore32/mm/flush.c
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/unicore32/mm/flush.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+		unsigned long end)
+{
+	if (vma->vm_flags & VM_EXEC)
+		__flush_icache_all();
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr,
+		unsigned long pfn)
+{
+}
+
+static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+			 unsigned long uaddr, void *kaddr, unsigned long len)
+{
+	/* VIPT non-aliasing D-cache */
+	if (vma->vm_flags & VM_EXEC) {
+		unsigned long addr = (unsigned long)kaddr;
+
+		__cpuc_coherent_kern_range(addr, addr + len);
+	}
+}
+
+/*
+ * Copy user data from/to a page which is mapped into a different
+ * processes address space.  Really, we want to allow our "user
+ * space" model to handle this.
+ *
+ * Note that this code needs to run on the current CPU.
+ */
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+		       unsigned long uaddr, void *dst, const void *src,
+		       unsigned long len)
+{
+	memcpy(dst, src, len);
+	flush_ptrace_access(vma, page, uaddr, dst, len);
+}
+
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
+{
+	/*
+	 * Writeback any data associated with the kernel mapping of this
+	 * page.  This ensures that data in the physical page is mutually
+	 * coherent with the kernels mapping.
+	 */
+	__cpuc_flush_kern_dcache_area(page_address(page), PAGE_SIZE);
+}
+
+/*
+ * Ensure cache coherency between kernel mapping and userspace mapping
+ * of this page.
+ */
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping;
+
+	/*
+	 * The zero page is never written to, so never has any dirty
+	 * cache lines, and therefore never needs to be flushed.
+	 */
+	if (page == ZERO_PAGE(0))
+		return;
+
+	mapping = page_mapping(page);
+
+	if (mapping && !mapping_mapped(mapping))
+		clear_bit(PG_dcache_clean, &page->flags);
+	else {
+		__flush_dcache_page(mapping, page);
+		if (mapping)
+			__flush_icache_all();
+		set_bit(PG_dcache_clean, &page->flags);
+	}
+}
+EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c
new file mode 100644
index 0000000..3dbe370
--- /dev/null
+++ b/arch/unicore32/mm/init.c
@@ -0,0 +1,517 @@
+/*
+ *  linux/arch/unicore32/mm/init.c
+ *
+ *  Copyright (C) 2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/swap.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/initrd.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
+#include <linux/memblock.h>
+#include <linux/sort.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
+#include <mach/map.h>
+
+#include "mm.h"
+
+static unsigned long phys_initrd_start __initdata = 0x01000000;
+static unsigned long phys_initrd_size __initdata = SZ_8M;
+
+static int __init early_initrd(char *p)
+{
+	unsigned long start, size;
+	char *endp;
+
+	start = memparse(p, &endp);
+	if (*endp == ',') {
+		size = memparse(endp + 1, NULL);
+
+		phys_initrd_start = start;
+		phys_initrd_size = size;
+	}
+	return 0;
+}
+early_param("initrd", early_initrd);
+
+/*
+ * This keeps memory configuration data used by a couple memory
+ * initialization functions, as well as show_mem() for the skipping
+ * of holes in the memory map.  It is populated by uc32_add_memory().
+ */
+struct meminfo meminfo;
+
+void show_mem(void)
+{
+	int free = 0, total = 0, reserved = 0;
+	int shared = 0, cached = 0, slab = 0, i;
+	struct meminfo *mi = &meminfo;
+
+	printk(KERN_DEFAULT "Mem-info:\n");
+	show_free_areas();
+
+	for_each_bank(i, mi) {
+		struct membank *bank = &mi->bank[i];
+		unsigned int pfn1, pfn2;
+		struct page *page, *end;
+
+		pfn1 = bank_pfn_start(bank);
+		pfn2 = bank_pfn_end(bank);
+
+		page = pfn_to_page(pfn1);
+		end  = pfn_to_page(pfn2 - 1) + 1;
+
+		do {
+			total++;
+			if (PageReserved(page))
+				reserved++;
+			else if (PageSwapCache(page))
+				cached++;
+			else if (PageSlab(page))
+				slab++;
+			else if (!page_count(page))
+				free++;
+			else
+				shared += page_count(page) - 1;
+			page++;
+		} while (page < end);
+	}
+
+	printk(KERN_DEFAULT "%d pages of RAM\n", total);
+	printk(KERN_DEFAULT "%d free pages\n", free);
+	printk(KERN_DEFAULT "%d reserved pages\n", reserved);
+	printk(KERN_DEFAULT "%d slab pages\n", slab);
+	printk(KERN_DEFAULT "%d pages shared\n", shared);
+	printk(KERN_DEFAULT "%d pages swap cached\n", cached);
+}
+
+static void __init find_limits(unsigned long *min, unsigned long *max_low,
+	unsigned long *max_high)
+{
+	struct meminfo *mi = &meminfo;
+	int i;
+
+	*min = -1UL;
+	*max_low = *max_high = 0;
+
+	for_each_bank(i, mi) {
+		struct membank *bank = &mi->bank[i];
+		unsigned long start, end;
+
+		start = bank_pfn_start(bank);
+		end = bank_pfn_end(bank);
+
+		if (*min > start)
+			*min = start;
+		if (*max_high < end)
+			*max_high = end;
+		if (bank->highmem)
+			continue;
+		if (*max_low < end)
+			*max_low = end;
+	}
+}
+
+static void __init uc32_bootmem_init(unsigned long start_pfn,
+	unsigned long end_pfn)
+{
+	struct memblock_region *reg;
+	unsigned int boot_pages;
+	phys_addr_t bitmap;
+	pg_data_t *pgdat;
+
+	/*
+	 * Allocate the bootmem bitmap page.  This must be in a region
+	 * of memory which has already been mapped.
+	 */
+	boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+	bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
+				__pfn_to_phys(end_pfn));
+
+	/*
+	 * Initialise the bootmem allocator, handing the
+	 * memory banks over to bootmem.
+	 */
+	node_set_online(0);
+	pgdat = NODE_DATA(0);
+	init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
+
+	/* Free the lowmem regions from memblock into bootmem. */
+	for_each_memblock(memory, reg) {
+		unsigned long start = memblock_region_memory_base_pfn(reg);
+		unsigned long end = memblock_region_memory_end_pfn(reg);
+
+		if (end >= end_pfn)
+			end = end_pfn;
+		if (start >= end)
+			break;
+
+		free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
+	}
+
+	/* Reserve the lowmem memblock reserved regions in bootmem. */
+	for_each_memblock(reserved, reg) {
+		unsigned long start = memblock_region_reserved_base_pfn(reg);
+		unsigned long end = memblock_region_reserved_end_pfn(reg);
+
+		if (end >= end_pfn)
+			end = end_pfn;
+		if (start >= end)
+			break;
+
+		reserve_bootmem(__pfn_to_phys(start),
+			(end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
+	}
+}
+
+static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low,
+	unsigned long max_high)
+{
+	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
+	struct memblock_region *reg;
+
+	/*
+	 * initialise the zones.
+	 */
+	memset(zone_size, 0, sizeof(zone_size));
+
+	/*
+	 * The memory size has already been determined.  If we need
+	 * to do anything fancy with the allocation of this memory
+	 * to the zones, now is the time to do it.
+	 */
+	zone_size[0] = max_low - min;
+
+	/*
+	 * Calculate the size of the holes.
+	 *  holes = node_size - sum(bank_sizes)
+	 */
+	memcpy(zhole_size, zone_size, sizeof(zhole_size));
+	for_each_memblock(memory, reg) {
+		unsigned long start = memblock_region_memory_base_pfn(reg);
+		unsigned long end = memblock_region_memory_end_pfn(reg);
+
+		if (start < max_low) {
+			unsigned long low_end = min(end, max_low);
+			zhole_size[0] -= low_end - start;
+		}
+	}
+
+	/*
+	 * Adjust the sizes according to any special requirements for
+	 * this machine type.
+	 */
+	arch_adjust_zones(zone_size, zhole_size);
+
+	free_area_init_node(0, zone_size, min, zhole_size);
+}
+
+int pfn_valid(unsigned long pfn)
+{
+	return memblock_is_memory(pfn << PAGE_SHIFT);
+}
+EXPORT_SYMBOL(pfn_valid);
+
+static void uc32_memory_present(void)
+{
+}
+
+static int __init meminfo_cmp(const void *_a, const void *_b)
+{
+	const struct membank *a = _a, *b = _b;
+	long cmp = bank_pfn_start(a) - bank_pfn_start(b);
+	return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+}
+
+void __init uc32_memblock_init(struct meminfo *mi)
+{
+	int i;
+
+	sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]),
+		meminfo_cmp, NULL);
+
+	memblock_init();
+	for (i = 0; i < mi->nr_banks; i++)
+		memblock_add(mi->bank[i].start, mi->bank[i].size);
+
+	/* Register the kernel text, kernel data and initrd with memblock. */
+	memblock_reserve(__pa(_text), _end - _text);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (phys_initrd_size) {
+		memblock_reserve(phys_initrd_start, phys_initrd_size);
+
+		/* Now convert initrd to virtual addresses */
+		initrd_start = __phys_to_virt(phys_initrd_start);
+		initrd_end = initrd_start + phys_initrd_size;
+	}
+#endif
+
+	uc32_mm_memblock_reserve();
+
+	memblock_analyze();
+	memblock_dump_all();
+}
+
+void __init bootmem_init(void)
+{
+	unsigned long min, max_low, max_high;
+
+	max_low = max_high = 0;
+
+	find_limits(&min, &max_low, &max_high);
+
+	uc32_bootmem_init(min, max_low);
+
+#ifdef CONFIG_SWIOTLB
+	swiotlb_init(1);
+#endif
+	/*
+	 * Sparsemem tries to allocate bootmem in memory_present(),
+	 * so must be done after the fixed reservations
+	 */
+	uc32_memory_present();
+
+	/*
+	 * sparse_init() needs the bootmem allocator up and running.
+	 */
+	sparse_init();
+
+	/*
+	 * Now free the memory - free_area_init_node needs
+	 * the sparse mem_map arrays initialized by sparse_init()
+	 * for memmap_init_zone(), otherwise all PFNs are invalid.
+	 */
+	uc32_bootmem_free(min, max_low, max_high);
+
+	high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
+
+	/*
+	 * This doesn't seem to be used by the Linux memory manager any
+	 * more, but is used by ll_rw_block.  If we can get rid of it, we
+	 * also get rid of some of the stuff above as well.
+	 *
+	 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
+	 * the system, not the maximum PFN.
+	 */
+	max_low_pfn = max_low - PHYS_PFN_OFFSET;
+	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)
+{
+	struct page *start_pg, *end_pg;
+	unsigned long pg, pgend;
+
+	/*
+	 * Convert start_pfn/end_pfn to a struct page pointer.
+	 */
+	start_pg = pfn_to_page(start_pfn - 1) + 1;
+	end_pg = pfn_to_page(end_pfn);
+
+	/*
+	 * Convert to physical addresses, and
+	 * round start upwards and end downwards.
+	 */
+	pg = PAGE_ALIGN(__pa(start_pg));
+	pgend = __pa(end_pg) & PAGE_MASK;
+
+	/*
+	 * If there are free pages between these,
+	 * free the section of the memmap array.
+	 */
+	if (pg < pgend)
+		free_bootmem(pg, pgend - pg);
+}
+
+/*
+ * The mem_map array can get very big.  Free the unused area of the memory map.
+ */
+static void __init free_unused_memmap(struct meminfo *mi)
+{
+	unsigned long bank_start, prev_bank_end = 0;
+	unsigned int i;
+
+	/*
+	 * This relies on each bank being in address order.
+	 * The banks are sorted previously in bootmem_init().
+	 */
+	for_each_bank(i, mi) {
+		struct membank *bank = &mi->bank[i];
+
+		bank_start = bank_pfn_start(bank);
+
+		/*
+		 * If we had a previous bank, and there is a space
+		 * between the current bank and the previous, free it.
+		 */
+		if (prev_bank_end && prev_bank_end < bank_start)
+			free_memmap(prev_bank_end, bank_start);
+
+		/*
+		 * Align up here since the VM subsystem insists that the
+		 * memmap entries are valid from the bank end aligned to
+		 * MAX_ORDER_NR_PAGES.
+		 */
+		prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
+	}
+}
+
+/*
+ * mem_init() marks the free areas in the mem_map and tells us how much
+ * memory is free.  This is done after various parts of the system have
+ * claimed their memory after the kernel image.
+ */
+void __init mem_init(void)
+{
+	unsigned long reserved_pages, free_pages;
+	struct memblock_region *reg;
+	int i;
+
+	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);
+
+	totalram_pages += free_all_bootmem();
+
+	reserved_pages = free_pages = 0;
+
+	for_each_bank(i, &meminfo) {
+		struct membank *bank = &meminfo.bank[i];
+		unsigned int pfn1, pfn2;
+		struct page *page, *end;
+
+		pfn1 = bank_pfn_start(bank);
+		pfn2 = bank_pfn_end(bank);
+
+		page = pfn_to_page(pfn1);
+		end  = pfn_to_page(pfn2 - 1) + 1;
+
+		do {
+			if (PageReserved(page))
+				reserved_pages++;
+			else if (!page_count(page))
+				free_pages++;
+			page++;
+		} while (page < end);
+	}
+
+	/*
+	 * Since our memory may not be contiguous, calculate the
+	 * real number of pages we have in this system
+	 */
+	printk(KERN_INFO "Memory:");
+	num_physpages = 0;
+	for_each_memblock(memory, reg) {
+		unsigned long pages = memblock_region_memory_end_pfn(reg) -
+			memblock_region_memory_base_pfn(reg);
+		num_physpages += pages;
+		printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
+	}
+	printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
+
+	printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
+		nr_free_pages() << (PAGE_SHIFT-10),
+		free_pages << (PAGE_SHIFT-10),
+		reserved_pages << (PAGE_SHIFT-10),
+		totalhigh_pages << (PAGE_SHIFT-10));
+
+	printk(KERN_NOTICE "Virtual kernel memory layout:\n"
+		"    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n",
+
+		VECTORS_BASE, VECTORS_BASE + PAGE_SIZE,
+		DIV_ROUND_UP(PAGE_SIZE, SZ_1K),
+		VMALLOC_START, VMALLOC_END,
+		DIV_ROUND_UP((VMALLOC_END - VMALLOC_START), SZ_1M),
+		PAGE_OFFSET, (unsigned long)high_memory,
+		DIV_ROUND_UP(((unsigned long)high_memory - PAGE_OFFSET), SZ_1M),
+		MODULES_VADDR, MODULES_END,
+		DIV_ROUND_UP((MODULES_END - MODULES_VADDR), SZ_1M),
+
+		__init_begin, __init_end,
+		DIV_ROUND_UP((__init_end - __init_begin), SZ_1K),
+		_stext, _etext,
+		DIV_ROUND_UP((_etext - _stext), SZ_1K),
+		_sdata, _edata,
+		DIV_ROUND_UP((_edata - _sdata), SZ_1K));
+
+	BUILD_BUG_ON(TASK_SIZE				> MODULES_VADDR);
+	BUG_ON(TASK_SIZE				> MODULES_VADDR);
+
+	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
+		/*
+		 * On a machine this small we won't get
+		 * anywhere without overcommit, so turn
+		 * it on by default.
+		 */
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
+	}
+}
+
+void free_initmem(void)
+{
+	totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
+				    __phys_to_pfn(__pa(__init_end)),
+				    "init");
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+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");
+}
+
+static int __init keepinitrd_setup(char *__unused)
+{
+	keep_initrd = 1;
+	return 1;
+}
+
+__setup("keepinitrd", keepinitrd_setup);
+#endif
diff --git a/arch/unicore32/mm/ioremap.c b/arch/unicore32/mm/ioremap.c
new file mode 100644
index 0000000..b7a6055
--- /dev/null
+++ b/arch/unicore32/mm/ioremap.c
@@ -0,0 +1,261 @@
+/*
+ * linux/arch/unicore32/mm/ioremap.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * This allows a driver to remap an arbitrary region of bus memory into
+ * virtual space.  One should *only* use readl, writel, memcpy_toio and
+ * so on with such remapped areas.
+ *
+ * Because UniCore only has a 32-bit address space we can't address the
+ * whole of the (physical) PCI space at once.  PCI huge-mode addressing
+ * allows us to circumvent this restriction by splitting PCI space into
+ * two 2GB chunks and mapping only one at a time into processor memory.
+ * We use MMU protection domains to trap any attempt to access the bank
+ * that is not currently mapped.  (This isn't fully implemented yet.)
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/sizes.h>
+
+#include <mach/map.h>
+#include "mm.h"
+
+/*
+ * Used by ioremap() and iounmap() code to mark (super)section-mapped
+ * I/O regions in vm_struct->flags field.
+ */
+#define VM_UNICORE_SECTION_MAPPING	0x80000000
+
+int ioremap_page(unsigned long virt, unsigned long phys,
+		 const struct mem_type *mtype)
+{
+	return ioremap_page_range(virt, virt + PAGE_SIZE, phys,
+				  __pgprot(mtype->prot_pte));
+}
+EXPORT_SYMBOL(ioremap_page);
+
+/*
+ * Section support is unsafe on SMP - If you iounmap and ioremap a region,
+ * the other CPUs will not see this change until their next context switch.
+ * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs
+ * which requires the new ioremap'd region to be referenced, the CPU will
+ * reference the _old_ region.
+ *
+ * Note that get_vm_area_caller() allocates a guard 4K page, so we need to
+ * mask the size back to 4MB aligned or we will overflow in the loop below.
+ */
+static void unmap_area_sections(unsigned long virt, unsigned long size)
+{
+	unsigned long addr = virt, end = virt + (size & ~(SZ_4M - 1));
+	pgd_t *pgd;
+
+	flush_cache_vunmap(addr, end);
+	pgd = pgd_offset_k(addr);
+	do {
+		pmd_t pmd, *pmdp = pmd_offset((pud_t *)pgd, addr);
+
+		pmd = *pmdp;
+		if (!pmd_none(pmd)) {
+			/*
+			 * Clear the PMD from the page table, and
+			 * increment the kvm sequence so others
+			 * notice this change.
+			 *
+			 * Note: this is still racy on SMP machines.
+			 */
+			pmd_clear(pmdp);
+
+			/*
+			 * Free the page table, if there was one.
+			 */
+			if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
+				pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
+		}
+
+		addr += PGDIR_SIZE;
+		pgd++;
+	} while (addr < end);
+
+	flush_tlb_kernel_range(virt, end);
+}
+
+static int
+remap_area_sections(unsigned long virt, unsigned long pfn,
+		    size_t size, const struct mem_type *type)
+{
+	unsigned long addr = virt, end = virt + size;
+	pgd_t *pgd;
+
+	/*
+	 * Remove and free any PTE-based mapping, and
+	 * sync the current kernel mapping.
+	 */
+	unmap_area_sections(virt, size);
+
+	pgd = pgd_offset_k(addr);
+	do {
+		pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
+
+		set_pmd(pmd, __pmd(__pfn_to_phys(pfn) | type->prot_sect));
+		pfn += SZ_4M >> PAGE_SHIFT;
+		flush_pmd_entry(pmd);
+
+		addr += PGDIR_SIZE;
+		pgd++;
+	} while (addr < end);
+
+	return 0;
+}
+
+void __iomem *__uc32_ioremap_pfn_caller(unsigned long pfn,
+	unsigned long offset, size_t size, unsigned int mtype, void *caller)
+{
+	const struct mem_type *type;
+	int err;
+	unsigned long addr;
+	struct vm_struct *area;
+
+	/*
+	 * High mappings must be section aligned
+	 */
+	if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SECTION_MASK))
+		return NULL;
+
+	/*
+	 * Don't allow RAM to be mapped
+	 */
+	if (pfn_valid(pfn)) {
+		printk(KERN_WARNING "BUG: Your driver calls ioremap() on\n"
+			"system memory.  This leads to architecturally\n"
+			"unpredictable behaviour, and ioremap() will fail in\n"
+			"the next kernel release. Please fix your driver.\n");
+		WARN_ON(1);
+	}
+
+	type = get_mem_type(mtype);
+	if (!type)
+		return NULL;
+
+	/*
+	 * Page align the mapping size, taking account of any offset.
+	 */
+	size = PAGE_ALIGN(offset + size);
+
+	area = get_vm_area_caller(size, VM_IOREMAP, caller);
+	if (!area)
+		return NULL;
+	addr = (unsigned long)area->addr;
+
+	if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
+		area->flags |= VM_UNICORE_SECTION_MAPPING;
+		err = remap_area_sections(addr, pfn, size, type);
+	} else
+		err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn),
+					 __pgprot(type->prot_pte));
+
+	if (err) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+
+	flush_cache_vmap(addr, addr + size);
+	return (void __iomem *) (offset + addr);
+}
+
+void __iomem *__uc32_ioremap_caller(unsigned long phys_addr, size_t size,
+	unsigned int mtype, void *caller)
+{
+	unsigned long last_addr;
+	unsigned long offset = phys_addr & ~PAGE_MASK;
+	unsigned long pfn = __phys_to_pfn(phys_addr);
+
+	/*
+	 * Don't allow wraparound or zero size
+	 */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, caller);
+}
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void __iomem *
+__uc32_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
+		  unsigned int mtype)
+{
+	return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype,
+			__builtin_return_address(0));
+}
+EXPORT_SYMBOL(__uc32_ioremap_pfn);
+
+void __iomem *
+__uc32_ioremap(unsigned long phys_addr, size_t size)
+{
+	return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE,
+			__builtin_return_address(0));
+}
+EXPORT_SYMBOL(__uc32_ioremap);
+
+void __iomem *
+__uc32_ioremap_cached(unsigned long phys_addr, size_t size)
+{
+	return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE_CACHED,
+			__builtin_return_address(0));
+}
+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;
+
+	/*
+	 * If this is a section based mapping we need to handle it
+	 * specially as the VM subsystem does not know how to handle
+	 * such a beast. We need the lock here b/c we need to clear
+	 * 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);
+
+	vunmap(addr);
+}
+EXPORT_SYMBOL(__uc32_iounmap);
diff --git a/arch/unicore32/mm/mm.h b/arch/unicore32/mm/mm.h
new file mode 100644
index 0000000..3296bca
--- /dev/null
+++ b/arch/unicore32/mm/mm.h
@@ -0,0 +1,39 @@
+/*
+ * linux/arch/unicore32/mm/mm.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/* the upper-most page table pointer */
+extern pmd_t *top_pmd;
+extern int sysctl_overcommit_memory;
+
+#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
+
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+	return pmd_offset((pud_t *)pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+	return pmd_off(pgd_offset_k(virt), virt);
+}
+
+struct mem_type {
+	unsigned int prot_pte;
+	unsigned int prot_l1;
+	unsigned int prot_sect;
+};
+
+const struct mem_type *get_mem_type(unsigned int type);
+
+extern void __flush_dcache_page(struct address_space *, struct page *);
+
+void __init bootmem_init(void);
+void uc32_mm_memblock_reserve(void);
diff --git a/arch/unicore32/mm/mmu.c b/arch/unicore32/mm/mmu.c
new file mode 100644
index 0000000..7bf3d58
--- /dev/null
+++ b/arch/unicore32/mm/mmu.c
@@ -0,0 +1,533 @@
+/*
+ * linux/arch/unicore32/mm/mmu.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/memblock.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
+
+#include <mach/map.h>
+
+#include "mm.h"
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/*
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
+ */
+struct page *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
+/*
+ * The pmd table for the upper-most set of pages.
+ */
+pmd_t *top_pmd;
+
+pgprot_t pgprot_user;
+EXPORT_SYMBOL(pgprot_user);
+
+pgprot_t pgprot_kernel;
+EXPORT_SYMBOL(pgprot_kernel);
+
+static int __init noalign_setup(char *__unused)
+{
+	cr_alignment &= ~CR_A;
+	cr_no_alignment &= ~CR_A;
+	set_cr(cr_alignment);
+	return 1;
+}
+__setup("noalign", noalign_setup);
+
+void adjust_cr(unsigned long mask, unsigned long set)
+{
+	unsigned long flags;
+
+	mask &= ~CR_A;
+
+	set &= mask;
+
+	local_irq_save(flags);
+
+	cr_no_alignment = (cr_no_alignment & ~mask) | set;
+	cr_alignment = (cr_alignment & ~mask) | set;
+
+	set_cr((get_cr() & ~mask) | set);
+
+	local_irq_restore(flags);
+}
+
+struct map_desc {
+	unsigned long virtual;
+	unsigned long pfn;
+	unsigned long length;
+	unsigned int type;
+};
+
+#define PROT_PTE_DEVICE		(PTE_PRESENT | PTE_YOUNG |	\
+				PTE_DIRTY | PTE_READ | PTE_WRITE)
+#define PROT_SECT_DEVICE	(PMD_TYPE_SECT | PMD_PRESENT |	\
+				PMD_SECT_READ | PMD_SECT_WRITE)
+
+static struct mem_type mem_types[] = {
+	[MT_DEVICE] = {		  /* Strongly ordered */
+		.prot_pte	= PROT_PTE_DEVICE,
+		.prot_l1	= PMD_TYPE_TABLE | PMD_PRESENT,
+		.prot_sect	= PROT_SECT_DEVICE,
+	},
+	/*
+	 * MT_KUSER: pte for vecpage -- cacheable,
+	 *       and sect for unigfx mmap -- noncacheable
+	 */
+	[MT_KUSER] = {
+		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
+				PTE_CACHEABLE | PTE_READ | PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
+		.prot_sect = PROT_SECT_DEVICE,
+	},
+	[MT_HIGH_VECTORS] = {
+		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
+				PTE_CACHEABLE | PTE_READ | PTE_WRITE |
+				PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
+	},
+	[MT_MEMORY] = {
+		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
+				PTE_WRITE | PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
+		.prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
+				PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC,
+	},
+	[MT_ROM] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
+				PMD_SECT_READ,
+	},
+};
+
+const struct mem_type *get_mem_type(unsigned int type)
+{
+	return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL;
+}
+EXPORT_SYMBOL(get_mem_type);
+
+/*
+ * Adjust the PMD section entries according to the CPU in use.
+ */
+static void __init build_mem_type_table(void)
+{
+	pgprot_user   = __pgprot(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE);
+	pgprot_kernel = __pgprot(PTE_PRESENT | PTE_YOUNG |
+				 PTE_DIRTY | PTE_READ | PTE_WRITE |
+				 PTE_EXEC | PTE_CACHEABLE);
+}
+
+#define vectors_base()	(vectors_high() ? 0xffff0000 : 0)
+
+static void __init *early_alloc(unsigned long sz)
+{
+	void *ptr = __va(memblock_alloc(sz, sz));
+	memset(ptr, 0, sz);
+	return ptr;
+}
+
+static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
+		unsigned long prot)
+{
+	if (pmd_none(*pmd)) {
+		pte_t *pte = early_alloc(PTRS_PER_PTE * sizeof(pte_t));
+		__pmd_populate(pmd, __pa(pte) | prot);
+	}
+	BUG_ON(pmd_bad(*pmd));
+	return pte_offset_kernel(pmd, addr);
+}
+
+static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
+				  unsigned long end, unsigned long pfn,
+				  const struct mem_type *type)
+{
+	pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
+	do {
+		set_pte(pte, pfn_pte(pfn, __pgprot(type->prot_pte)));
+		pfn++;
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
+				      unsigned long end, unsigned long phys,
+				      const struct mem_type *type)
+{
+	pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
+
+	/*
+	 * Try a section mapping - end, addr and phys must all be aligned
+	 * to a section boundary.
+	 */
+	if (((addr | end | phys) & ~SECTION_MASK) == 0) {
+		pmd_t *p = pmd;
+
+		do {
+			set_pmd(pmd, __pmd(phys | type->prot_sect));
+			phys += SECTION_SIZE;
+		} while (pmd++, addr += SECTION_SIZE, addr != end);
+
+		flush_pmd_entry(p);
+	} else {
+		/*
+		 * No need to loop; pte's aren't interested in the
+		 * individual L1 entries.
+		 */
+		alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
+	}
+}
+
+/*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections.
+ */
+static void __init create_mapping(struct map_desc *md)
+{
+	unsigned long phys, addr, length, end;
+	const struct mem_type *type;
+	pgd_t *pgd;
+
+	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+		printk(KERN_WARNING "BUG: not creating mapping for "
+		       "0x%08llx at 0x%08lx in user region\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
+		return;
+	}
+
+	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
+		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
+		       "overlaps vmalloc space\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
+	}
+
+	type = &mem_types[md->type];
+
+	addr = md->virtual & PAGE_MASK;
+	phys = (unsigned long)__pfn_to_phys(md->pfn);
+	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
+
+	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
+		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
+		       "be mapped using pages, ignoring.\n",
+		       __pfn_to_phys(md->pfn), addr);
+		return;
+	}
+
+	pgd = pgd_offset_k(addr);
+	end = addr + length;
+	do {
+		unsigned long next = pgd_addr_end(addr, end);
+
+		alloc_init_section(pgd, addr, next, phys, type);
+
+		phys += next - addr;
+		addr = next;
+	} while (pgd++, addr != end);
+}
+
+static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
+
+/*
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the vmalloc
+ * area - the default is 128m.
+ */
+static int __init early_vmalloc(char *arg)
+{
+	unsigned long vmalloc_reserve = memparse(arg, NULL);
+
+	if (vmalloc_reserve < SZ_16M) {
+		vmalloc_reserve = SZ_16M;
+		printk(KERN_WARNING
+			"vmalloc area too small, limiting to %luMB\n",
+			vmalloc_reserve >> 20);
+	}
+
+	if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) {
+		vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M);
+		printk(KERN_WARNING
+			"vmalloc area is too big, limiting to %luMB\n",
+			vmalloc_reserve >> 20);
+	}
+
+	vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve);
+	return 0;
+}
+early_param("vmalloc", early_vmalloc);
+
+static phys_addr_t lowmem_limit __initdata = SZ_1G;
+
+static void __init sanity_check_meminfo(void)
+{
+	int i, j;
+
+	lowmem_limit = __pa(vmalloc_min - 1) + 1;
+	memblock_set_current_limit(lowmem_limit);
+
+	for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
+		struct membank *bank = &meminfo.bank[j];
+		*bank = meminfo.bank[i];
+		j++;
+	}
+	meminfo.nr_banks = j;
+}
+
+static inline void prepare_page_table(void)
+{
+	unsigned long addr;
+	phys_addr_t end;
+
+	/*
+	 * Clear out all the mappings below the kernel image.
+	 */
+	for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Find the end of the first block of lowmem.
+	 */
+	end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
+	if (end >= lowmem_limit)
+		end = lowmem_limit;
+
+	/*
+	 * Clear out all the kernel space mappings, except for the first
+	 * memory bank, up to the end of the vmalloc region.
+	 */
+	for (addr = __phys_to_virt(end);
+	     addr < VMALLOC_END; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+}
+
+/*
+ * Reserve the special regions of memory
+ */
+void __init uc32_mm_memblock_reserve(void)
+{
+	/*
+	 * Reserve the page tables.  These are already in use,
+	 * and can only be in node 0.
+	 */
+	memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
+
+#ifdef CONFIG_PUV3_UNIGFX
+	/*
+	 * These should likewise go elsewhere.  They pre-reserve the
+	 * screen/video memory region at the 48M~64M of main system memory.
+	 */
+	memblock_reserve(PKUNITY_UNIGFX_MMAP_BASE, PKUNITY_UNIGFX_MMAP_SIZE);
+	memblock_reserve(PKUNITY_UVC_MMAP_BASE, PKUNITY_UVC_MMAP_SIZE);
+#endif
+}
+
+/*
+ * Set up device the mappings.  Since we clear out the page tables for all
+ * mappings above VMALLOC_END, we will remove any debug device mappings.
+ * This means you have to be careful how you debug this function, or any
+ * called function.  This means you can't use any function or debugging
+ * method which may touch any device, otherwise the kernel _will_ crash.
+ */
+static void __init devicemaps_init(void)
+{
+	struct map_desc map;
+	unsigned long addr;
+	void *vectors;
+
+	/*
+	 * Allocate the vector page early.
+	 */
+	vectors = early_alloc(PAGE_SIZE);
+
+	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Create a mapping for UniGFX VRAM
+	 */
+#ifdef CONFIG_PUV3_UNIGFX
+	map.pfn = __phys_to_pfn(PKUNITY_UNIGFX_MMAP_BASE);
+	map.virtual = KUSER_UNIGFX_BASE;
+	map.length = PKUNITY_UNIGFX_MMAP_SIZE;
+	map.type = MT_KUSER;
+	create_mapping(&map);
+#endif
+
+	/*
+	 * Create a mapping for the machine vectors at the high-vectors
+	 * location (0xffff0000).  If we aren't using high-vectors, also
+	 * create a mapping at the low-vectors virtual address.
+	 */
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.virtual = VECTORS_BASE;
+	map.length = PAGE_SIZE;
+	map.type = MT_HIGH_VECTORS;
+	create_mapping(&map);
+
+	/*
+	 * Create a mapping for the kuser page at the special
+	 * location (0xbfff0000) to the same vectors location.
+	 */
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.virtual = KUSER_VECPAGE_BASE;
+	map.length = PAGE_SIZE;
+	map.type = MT_KUSER;
+	create_mapping(&map);
+
+	/*
+	 * Finally flush the caches and tlb to ensure that we're in a
+	 * consistent state wrt the writebuffer.  This also ensures that
+	 * any write-allocated cache lines in the vector page are written
+	 * back.  After this point, we can start to touch devices again.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+}
+
+static void __init map_lowmem(void)
+{
+	struct memblock_region *reg;
+
+	/* Map all the lowmem memory banks. */
+	for_each_memblock(memory, reg) {
+		phys_addr_t start = reg->base;
+		phys_addr_t end = start + reg->size;
+		struct map_desc map;
+
+		if (end > lowmem_limit)
+			end = lowmem_limit;
+		if (start >= end)
+			break;
+
+		map.pfn = __phys_to_pfn(start);
+		map.virtual = __phys_to_virt(start);
+		map.length = end - start;
+		map.type = MT_MEMORY;
+
+		create_mapping(&map);
+	}
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(void)
+{
+	void *zero_page;
+
+	build_mem_type_table();
+	sanity_check_meminfo();
+	prepare_page_table();
+	map_lowmem();
+	devicemaps_init();
+
+	top_pmd = pmd_off_k(0xffff0000);
+
+	/* allocate the zero page. */
+	zero_page = early_alloc(PAGE_SIZE);
+
+	bootmem_init();
+
+	empty_zero_page = virt_to_page(zero_page);
+	__flush_dcache_page(NULL, empty_zero_page);
+}
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+	unsigned long base_pmdval;
+	pgd_t *pgd;
+	int i;
+
+	/*
+	 * We need to access to user-mode page tables here. For kernel threads
+	 * we don't have any user-mode mappings so we use the context that we
+	 * "borrowed".
+	 */
+	pgd = current->active_mm->pgd;
+
+	base_pmdval = PMD_SECT_WRITE | PMD_SECT_READ | PMD_TYPE_SECT;
+
+	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
+		unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
+		pmd_t *pmd;
+
+		pmd = pmd_off(pgd, i << PGDIR_SHIFT);
+		set_pmd(pmd, __pmd(pmdval));
+		flush_pmd_entry(pmd);
+	}
+
+	local_flush_tlb_all();
+}
+
+/*
+ * Take care of architecture specific things when placing a new PTE into
+ * a page table, or changing an existing PTE.  Basically, there are two
+ * things that we need to take care of:
+ *
+ *  1. If PG_dcache_clean is not set for the page, we need to ensure
+ *     that any cache entries for the kernels virtual memory
+ *     range are written back to the page.
+ *  2. If we have multiple shared mappings of the same space in
+ *     an object, we need to deal with the cache aliasing issues.
+ *
+ * Note that the pte lock will be held.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+	pte_t *ptep)
+{
+	unsigned long pfn = pte_pfn(*ptep);
+	struct address_space *mapping;
+	struct page *page;
+
+	if (!pfn_valid(pfn))
+		return;
+
+	/*
+	 * The zero page is never written to, so never has any dirty
+	 * cache lines, and therefore never needs to be flushed.
+	 */
+	page = pfn_to_page(pfn);
+	if (page == ZERO_PAGE(0))
+		return;
+
+	mapping = page_mapping(page);
+	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+		__flush_dcache_page(mapping, page);
+	if (mapping)
+		if (vma->vm_flags & VM_EXEC)
+			__flush_icache_all();
+}
diff --git a/arch/unicore32/mm/pgd.c b/arch/unicore32/mm/pgd.c
new file mode 100644
index 0000000..08b8d42
--- /dev/null
+++ b/arch/unicore32/mm/pgd.c
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/unicore32/mm/pgd.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/mm.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+
+#include "mm.h"
+
+#define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
+
+/*
+ * need to get a 4k page for level 1
+ */
+pgd_t *get_pgd_slow(struct mm_struct *mm)
+{
+	pgd_t *new_pgd, *init_pgd;
+	pmd_t *new_pmd, *init_pmd;
+	pte_t *new_pte, *init_pte;
+
+	new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 0);
+	if (!new_pgd)
+		goto no_pgd;
+
+	memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+
+	/*
+	 * Copy over the kernel and IO PGD entries
+	 */
+	init_pgd = pgd_offset_k(0);
+	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+
+	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+
+	if (!vectors_high()) {
+		/*
+		 * On UniCore, first page must always be allocated since it
+		 * contains the machine vectors.
+		 */
+		new_pmd = pmd_alloc(mm, (pud_t *)new_pgd, 0);
+		if (!new_pmd)
+			goto no_pmd;
+
+		new_pte = pte_alloc_map(mm, NULL, new_pmd, 0);
+		if (!new_pte)
+			goto no_pte;
+
+		init_pmd = pmd_offset((pud_t *)init_pgd, 0);
+		init_pte = pte_offset_map(init_pmd, 0);
+		set_pte(new_pte, *init_pte);
+		pte_unmap(init_pte);
+		pte_unmap(new_pte);
+	}
+
+	return new_pgd;
+
+no_pte:
+	pmd_free(mm, new_pmd);
+no_pmd:
+	free_pages((unsigned long)new_pgd, 0);
+no_pgd:
+	return NULL;
+}
+
+void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
+{
+	pmd_t *pmd;
+	pgtable_t pte;
+
+	if (!pgd)
+		return;
+
+	/* pgd is always present and good */
+	pmd = pmd_off(pgd, 0);
+	if (pmd_none(*pmd))
+		goto free;
+	if (pmd_bad(*pmd)) {
+		pmd_ERROR(*pmd);
+		pmd_clear(pmd);
+		goto free;
+	}
+
+	pte = pmd_pgtable(*pmd);
+	pmd_clear(pmd);
+	pte_free(mm, pte);
+	pmd_free(mm, pmd);
+free:
+	free_pages((unsigned long) pgd, 0);
+}
diff --git a/arch/unicore32/mm/proc-macros.S b/arch/unicore32/mm/proc-macros.S
new file mode 100644
index 0000000..51560d6
--- /dev/null
+++ b/arch/unicore32/mm/proc-macros.S
@@ -0,0 +1,145 @@
+/*
+ * linux/arch/unicore32/mm/proc-macros.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * We need constants.h for:
+ *  VMA_VM_MM
+ *  VMA_VM_FLAGS
+ *  VM_EXEC
+ */
+#include <generated/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+
+/*
+ * the cache line sizes of the I and D cache are the same
+ */
+#define CACHE_LINESIZE	32
+
+/*
+ * This is the maximum size of an area which will be invalidated
+ * using the single invalidate entry instructions.  Anything larger
+ * than this, and we go for the whole cache.
+ *
+ * This value should be chosen such that we choose the cheapest
+ * alternative.
+ */
+#ifdef CONFIG_CPU_UCV2
+#define MAX_AREA_SIZE	0x800		/* 64 cache line */
+#endif
+
+/*
+ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
+ */
+	.macro	vma_vm_mm, rd, rn
+	ldw	\rd, [\rn+], #VMA_VM_MM
+	.endm
+
+/*
+ * vma_vm_flags - get vma->vm_flags
+ */
+	.macro	vma_vm_flags, rd, rn
+	ldw	\rd, [\rn+], #VMA_VM_FLAGS
+	.endm
+
+	.macro	tsk_mm, rd, rn
+	ldw	\rd, [\rn+], #TI_TASK
+	ldw	\rd, [\rd+], #TSK_ACTIVE_MM
+	.endm
+
+/*
+ * act_mm - get current->active_mm
+ */
+	.macro	act_mm, rd
+	andn	\rd, sp, #8128
+	andn	\rd, \rd, #63
+	ldw	\rd, [\rd+], #TI_TASK
+	ldw	\rd, [\rd+], #TSK_ACTIVE_MM
+	.endm
+
+/*
+ * mmid - get context id from mm pointer (mm->context.id)
+ */
+	.macro	mmid, rd, rn
+	ldw	\rd, [\rn+], #MM_CONTEXT_ID
+	.endm
+
+/*
+ * mask_asid - mask the ASID from the context ID
+ */
+	.macro	asid, rd, rn
+	and	\rd, \rn, #255
+	.endm
+
+	.macro	crval, clear, mmuset, ucset
+	.word	\clear
+	.word	\mmuset
+	.endm
+
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+/*
+ * va2pa va, pa, tbl, msk, off, err
+ *	This macro is used to translate virtual address to its physical address.
+ *
+ *	va: virtual address
+ *	pa: physical address, result is stored in this register
+ *	tbl, msk, off:	temp registers, will be destroyed
+ *	err: jump to error label if the physical address not exist
+ * NOTE: all regs must be different
+ */
+	.macro	va2pa, va, pa, tbl, msk, off, err=990f
+	movc	\pa, p0.c2, #0
+	mov	\off, \va >> #22		@ off <- index of 1st page table
+	adr	\tbl, 910f			@ tbl <- table of 1st page table
+900:						@ ---- handle 1, 2 page table
+	add	\pa, \pa, #PAGE_OFFSET		@ pa <- virt addr of page table
+	ldw	\pa, [\pa+], \off << #2		@ pa <- the content of pt
+	cand.a	\pa, #4				@ test exist bit
+	beq	\err				@ if not exist
+	and	\off, \pa, #3			@ off <- the last 2 bits
+	add	\tbl, \tbl, \off << #3		@ cmove table pointer
+	ldw	\msk, [\tbl+], #0		@ get the mask
+	ldw	pc, [\tbl+], #4
+930:						@ ---- handle 2nd page table
+	and	\pa, \pa, \msk			@ pa <- phys addr of 2nd pt
+	mov	\off, \va << #10
+	cntlo	\tbl, \msk			@ use tbl as temp reg
+	mov	\off, \off >> \tbl
+	mov	\off, \off >> #2		@ off <- index of 2nd pt
+	adr	\tbl, 920f			@ tbl <- table of 2nd pt
+	b	900b
+910:						@ 1st level page table
+	.word	0xfffff000, 930b		@ second level page table
+	.word	0xfffffc00, 930b		@ second level large page table
+	.word	0x00000000, \err		@ invalid
+	.word	0xffc00000, 980f		@ super page
+
+920:						@ 2nd level page table
+	.word	0xfffff000, 980f		@ page
+	.word	0xffffc000, 980f		@ middle page
+	.word	0xffff0000, 980f		@ large page
+	.word	0x00000000, \err		@ invalid
+980:
+	andn	\tbl, \va, \msk
+	and	\pa, \pa, \msk
+	or	\pa, \pa, \tbl
+990:
+	.endm
+#endif
+
+	.macro dcacheline_flush, addr, t1, t2
+	mov	\t1, \addr << #20
+	ldw	\t2, =_stext			@ _stext must ALIGN(4096)
+	add	\t2, \t2, \t1 >> #20
+	ldw	\t1, [\t2+], #0x0000
+	ldw	\t1, [\t2+], #0x1000
+	ldw	\t1, [\t2+], #0x2000
+	ldw	\t1, [\t2+], #0x3000
+	.endm
diff --git a/arch/unicore32/mm/proc-syms.c b/arch/unicore32/mm/proc-syms.c
new file mode 100644
index 0000000..f30071e
--- /dev/null
+++ b/arch/unicore32/mm/proc-syms.c
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/unicore32/mm/proc-syms.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/mm.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+
+EXPORT_SYMBOL(cpu_dcache_clean_area);
+EXPORT_SYMBOL(cpu_set_pte);
+
+EXPORT_SYMBOL(__cpuc_dma_flush_range);
+EXPORT_SYMBOL(__cpuc_dma_clean_range);
diff --git a/arch/unicore32/mm/proc-ucv2.S b/arch/unicore32/mm/proc-ucv2.S
new file mode 100644
index 0000000..9d29609
--- /dev/null
+++ b/arch/unicore32/mm/proc-ucv2.S
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/unicore32/mm/proc-ucv2.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hwcap.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+
+#include "proc-macros.S"
+
+ENTRY(cpu_proc_fin)
+	stm.w	(lr), [sp-]
+	mov	ip, #PSR_R_BIT | PSR_I_BIT | PRIV_MODE
+	mov.a	asr, ip
+	b.l	__cpuc_flush_kern_all
+	ldm.w	(pc), [sp]+
+
+/*
+ *	cpu_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_reset)
+	mov	ip, #0
+	movc	p0.c5, ip, #28			@ Cache invalidate all
+	nop8
+
+	movc	p0.c6, ip, #6			@ TLB invalidate all
+	nop8
+
+	movc	ip, p0.c1, #0			@ ctrl register
+	or	ip, ip, #0x2000			@ vector base address
+	andn	ip, ip, #0x000f			@ ............idam
+	movc	p0.c1, ip, #0			@ disable caches and mmu
+	nop
+	mov	pc, r0				@ jump to loc
+	nop8
+
+/*
+ *	cpu_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_do_idle)
+	mov	r0, #0				@ PCI address
+	.rept	8
+	ldw	r1, [r0]
+	.endr
+	mov	pc, lr
+
+ENTRY(cpu_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	101f
+	mov	r9, #PAGE_SZ
+	sub	r9, r9, #1			@ PAGE_MASK
+1:	va2pa	r0, r10, r11, r12, r13		@ r10 is PA
+	b	3f
+2:	cand.a	r0, r9
+	beq	1b
+3:	movc	p0.c5, r10, #11			@ clean D entry
+	nop8
+	add	r0, r0, #CACHE_LINESIZE
+	add	r10, r10, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bua	2b
+	mov	pc, lr
+#endif
+101:	mov	ip, #0
+	movc	p0.c5, ip, #10			@ Dcache clean all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	cpu_do_switch_mm(pgd_phys)
+ *
+ *	Set the translation table base pointer to be pgd_phys
+ *
+ *	- pgd_phys - physical address of new pgd
+ *
+ *	It is assumed that:
+ *	- we are not using split page tables
+ */
+	.align	5
+ENTRY(cpu_do_switch_mm)
+	movc	p0.c2, r0, #0			@ update page table ptr
+	nop8
+
+	movc	p0.c6, ip, #6			@ TLB invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	cpu_set_pte(ptep, pte)
+ *
+ *	Set a level 2 translation table entry.
+ *
+ *	- ptep  - pointer to level 2 translation table entry
+ *	- pte   - PTE value to store
+ */
+	.align	5
+ENTRY(cpu_set_pte)
+	stw	r1, [r0]
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	sub	r2, r0, #PAGE_OFFSET
+	movc	p0.c5, r2, #11				@ Dcache clean line
+	nop8
+#else
+	mov	ip, #0
+	movc	p0.c5, ip, #10				@ Dcache clean all
+	nop8
+	@dcacheline_flush	r0, r2, ip
+#endif
+	mov	pc, lr
+
diff --git a/arch/unicore32/mm/tlb-ucv2.S b/arch/unicore32/mm/tlb-ucv2.S
new file mode 100644
index 0000000..061d455
--- /dev/null
+++ b/arch/unicore32/mm/tlb-ucv2.S
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/unicore32/mm/tlb-ucv2.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * This program is free software; you can 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+/*
+ *	__cpu_flush_user_tlb_range(start, end, vma)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ *	- vma   - vma_struct describing address range
+ */
+ENTRY(__cpu_flush_user_tlb_range)
+#ifndef	CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+	mov	r0, r0 >> #PAGE_SHIFT		@ align address
+	mov	r0, r0 << #PAGE_SHIFT
+	vma_vm_flags r2, r2			@ get vma->vm_flags
+1:
+	movc	p0.c6, r0, #3
+	nop8
+
+	cand.a	r2, #VM_EXEC			@ Executable area ?
+	beq	2f
+
+	movc	p0.c6, r0, #5
+	nop8
+2:
+	add	r0, r0, #PAGE_SZ
+	csub.a	r0, r1
+	beb	1b
+#else
+	movc	p0.c6, r0, #2
+	nop8
+
+	cand.a	r2, #VM_EXEC			@ Executable area ?
+	beq	2f
+
+	movc	p0.c6, r0, #4
+	nop8
+2:
+#endif
+	mov	pc, lr
+
+/*
+ *	__cpu_flush_kern_tlb_range(start,end)
+ *
+ *	Invalidate a range of kernel TLB entries
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ */
+ENTRY(__cpu_flush_kern_tlb_range)
+#ifndef	CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+	mov	r0, r0 >> #PAGE_SHIFT		@ align address
+	mov	r0, r0 << #PAGE_SHIFT
+1:
+	movc	p0.c6, r0, #3
+	nop8
+
+	movc	p0.c6, r0, #5
+	nop8
+
+	add	r0, r0, #PAGE_SZ
+	csub.a	r0, r1
+	beb	1b
+#else
+	movc	p0.c6, r0, #2
+	nop8
+
+	movc	p0.c6, r0, #4
+	nop8
+#endif
+	mov	pc, lr
+
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index d5ed94d..d57ddd7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -64,8 +64,12 @@ config X86
 	select HAVE_TEXT_POKE_SMP
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_FIND_NEXT_BIT
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_IRQ_SHOW
+	select IRQ_FORCED_THREADING
 	select USE_GENERIC_SMP_HELPERS if SMP
 
 config INSTRUCTION_DECODER
@@ -119,7 +123,7 @@ config NEED_SG_DMA_LENGTH
 	def_bool y
 
 config GENERIC_ISA_DMA
-	def_bool y
+	def_bool ISA_DMA_API
 
 config GENERIC_IOMAP
 	def_bool y
@@ -139,7 +143,7 @@ config GENERIC_GPIO
 	bool
 
 config ARCH_MAY_HAVE_PC_FDC
-	def_bool y
+	def_bool ISA_DMA_API
 
 config RWSEM_GENERIC_SPINLOCK
 	def_bool !X86_XADD
@@ -217,10 +221,6 @@ config X86_HT
 	def_bool y
 	depends on SMP
 
-config X86_TRAMPOLINE
-	def_bool y
-	depends on SMP || (64BIT && ACPI_SLEEP)
-
 config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
@@ -382,6 +382,8 @@ config X86_INTEL_CE
 	depends on X86_32
 	depends on X86_EXTENDED_PLATFORM
 	select X86_REBOOTFIXUPS
+	select OF
+	select OF_EARLY_FLATTREE
 	---help---
 	  Select for the Intel CE media processor (CE4100) SOC.
 	  This option compiles in support for the CE4100 SOC for settop
@@ -811,7 +813,7 @@ config X86_LOCAL_APIC
 
 config X86_IO_APIC
 	def_bool y
-	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
+	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
 
 config X86_VISWS_APIC
 	def_bool y
@@ -1705,7 +1707,7 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
 	depends on NUMA
 
 config USE_PERCPU_NUMA_NODE_ID
-	def_bool X86_64
+	def_bool y
 	depends on NUMA
 
 menu "Power management and ACPI options"
@@ -2000,9 +2002,13 @@ source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
 
-# x86_64 have no ISA slots, but do have ISA-style DMA.
+# x86_64 have no ISA slots, but can have ISA-style DMA.
 config ISA_DMA_API
-	def_bool y
+	bool "ISA-style DMA support" if (X86_64 && EXPERT)
+	default y
+	help
+	  Enables ISA-style DMA support for devices requiring such controllers.
+	  If unsure, say Y.
 
 if X86_32
 
@@ -2066,9 +2072,10 @@ config SCx200HR_TIMER
 
 config OLPC
 	bool "One Laptop Per Child support"
+	depends on !X86_PAE
 	select GPIOLIB
-	select OLPC_OPENFIRMWARE
-	depends on !X86_64 && !X86_PAE
+	select OF
+	select OF_PROMTREE if PROC_DEVICETREE
 	---help---
 	  Add support for detecting the unique features of the OLPC
 	  XO hardware.
@@ -2079,21 +2086,6 @@ config OLPC_XO1
 	---help---
 	  Add support for non-essential features of the OLPC XO-1 laptop.
 
-config OLPC_OPENFIRMWARE
-	bool "Support for OLPC's Open Firmware"
-	depends on !X86_64 && !X86_PAE
-	default n
-	select OF
-	help
-	  This option adds support for the implementation of Open Firmware
-	  that is used on the OLPC XO-1 Children's Machine.
-	  If unsure, say N here.
-
-config OLPC_OPENFIRMWARE_DT
-	bool
-	default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
-	select OF_PROMTREE
-
 endif # X86_32
 
 config AMD_NB
@@ -2138,6 +2130,11 @@ config SYSVIPC_COMPAT
 	def_bool y
 	depends on COMPAT && SYSVIPC
 
+config KEYS_COMPAT
+	bool
+	depends on COMPAT && KEYS
+	default y
+
 endmenu
 
 
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
index 283c5a6..d161e93 100644
--- a/arch/x86/Kconfig.cpu
+++ b/arch/x86/Kconfig.cpu
@@ -294,11 +294,6 @@ config X86_GENERIC
 
 endif
 
-config X86_CPU
-	def_bool y
-	select GENERIC_FIND_FIRST_BIT
-	select GENERIC_FIND_NEXT_BIT
-
 #
 # Define implied options from the CPU selection here
 config X86_INTERNODE_CACHE_SHIFT
@@ -331,7 +326,7 @@ config X86_PPRO_FENCE
 	  Old PentiumPro multiprocessor systems had errata that could cause
 	  memory operations to violate the x86 ordering standard in rare cases.
 	  Enabling this option will attempt to work around some (but not all)
-	  occurances of this problem, at the cost of much heavier spinlock and
+	  occurrences of this problem, at the cost of much heavier spinlock and
 	  memory barrier operations.
 
 	  If unsure, say n here. Even distro kernels should think twice before
@@ -371,7 +366,7 @@ config X86_INTEL_USERCOPY
 
 config X86_USE_PPRO_CHECKSUM
 	def_bool y
-	depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM
+	depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM
 
 config X86_USE_3DNOW
 	def_bool y
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
index 8fe2a49..adcf794 100644
--- a/arch/x86/crypto/aesni-intel_asm.S
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -1346,7 +1346,7 @@ _zero_cipher_left_decrypt:
 	and	$15, %r13				# %r13 = arg4 (mod 16)
 	je	_multiple_of_16_bytes_decrypt
 
-        # Handle the last <16 byte block seperately
+        # Handle the last <16 byte block separately
 
 	paddd ONE(%rip), %xmm0         # increment CNT to get Yn
         movdqa SHUF_MASK(%rip), %xmm10
@@ -1355,7 +1355,7 @@ _zero_cipher_left_decrypt:
 	ENCRYPT_SINGLE_BLOCK  %xmm0, %xmm1    # E(K, Yn)
 	sub $16, %r11
 	add %r13, %r11
-	movdqu (%arg3,%r11,1), %xmm1   # recieve the last <16 byte block
+	movdqu (%arg3,%r11,1), %xmm1   # receive the last <16 byte block
 	lea SHIFT_MASK+16(%rip), %r12
 	sub %r13, %r12
 # adjust the shuffle mask pointer to be able to shift 16-%r13 bytes
@@ -1607,7 +1607,7 @@ _zero_cipher_left_encrypt:
 	and	$15, %r13			# %r13 = arg4 (mod 16)
 	je	_multiple_of_16_bytes_encrypt
 
-         # Handle the last <16 Byte block seperately
+         # Handle the last <16 Byte block separately
 	paddd ONE(%rip), %xmm0                # INCR CNT to get Yn
         movdqa SHUF_MASK(%rip), %xmm10
 	PSHUFB_XMM %xmm10, %xmm0
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
index e1e60c7..e0e6340 100644
--- a/arch/x86/crypto/aesni-intel_glue.c
+++ b/arch/x86/crypto/aesni-intel_glue.c
@@ -873,22 +873,18 @@ rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len)
 	crypto_ablkcipher_clear_flags(ctr_tfm, ~0);
 
 	ret = crypto_ablkcipher_setkey(ctr_tfm, key, key_len);
-	if (ret) {
-		crypto_free_ablkcipher(ctr_tfm);
-		return ret;
-	}
+	if (ret)
+		goto out_free_ablkcipher;
 
+	ret = -ENOMEM;
 	req = ablkcipher_request_alloc(ctr_tfm, GFP_KERNEL);
-	if (!req) {
-		crypto_free_ablkcipher(ctr_tfm);
-		return -EINVAL;
-	}
+	if (!req)
+		goto out_free_ablkcipher;
 
 	req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
-	if (!req_data) {
-		crypto_free_ablkcipher(ctr_tfm);
-		return -ENOMEM;
-	}
+	if (!req_data)
+		goto out_free_request;
+
 	memset(req_data->iv, 0, sizeof(req_data->iv));
 
 	/* Clear the data in the hash sub key container to zero.*/
@@ -913,8 +909,10 @@ rfc4106_set_hash_subkey(u8 *hash_subkey, const u8 *key, unsigned int key_len)
 		if (!ret)
 			ret = req_data->result.err;
 	}
-	ablkcipher_request_free(req);
 	kfree(req_data);
+out_free_request:
+	ablkcipher_request_free(req);
+out_free_ablkcipher:
 	crypto_free_ablkcipher(ctr_tfm);
 	return ret;
 }
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 518bb99..849a9d2 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -25,6 +25,8 @@
 #define sysretl_audit ia32_ret_from_sys_call
 #endif
 
+	.section .entry.text, "ax"
+
 #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
 
 	.macro IA32_ARG_FIXUP noebp=0
@@ -126,26 +128,20 @@ ENTRY(ia32_sysenter_target)
 	 */
 	ENABLE_INTERRUPTS(CLBR_NONE)
  	movl	%ebp,%ebp		/* zero extension */
-	pushq	$__USER32_DS
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi $__USER32_DS
 	/*CFI_REL_OFFSET ss,0*/
-	pushq	%rbp
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rbp
 	CFI_REL_OFFSET rsp,0
-	pushfq
-	CFI_ADJUST_CFA_OFFSET 8
+	pushfq_cfi
 	/*CFI_REL_OFFSET rflags,0*/
 	movl	8*3-THREAD_SIZE+TI_sysenter_return(%rsp), %r10d
 	CFI_REGISTER rip,r10
-	pushq	$__USER32_CS
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi $__USER32_CS
 	/*CFI_REL_OFFSET cs,0*/
 	movl	%eax, %eax
-	pushq	%r10
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %r10
 	CFI_REL_OFFSET rip,0
-	pushq	%rax
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rax
 	cld
 	SAVE_ARGS 0,0,1
  	/* no need to do an access_ok check here because rbp has been
@@ -182,11 +178,9 @@ sysexit_from_sys_call:
 	xorq	%r9,%r9
 	xorq	%r10,%r10
 	xorq	%r11,%r11
-	popfq
-	CFI_ADJUST_CFA_OFFSET -8
+	popfq_cfi
 	/*CFI_RESTORE rflags*/
-	popq	%rcx				/* User %esp */
-	CFI_ADJUST_CFA_OFFSET -8
+	popq_cfi %rcx				/* User %esp */
 	CFI_REGISTER rsp,rcx
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS_SYSEXIT32
@@ -421,8 +415,7 @@ ENTRY(ia32_syscall)
 	 */
 	ENABLE_INTERRUPTS(CLBR_NONE)
 	movl %eax,%eax
-	pushq %rax
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rax
 	cld
 	/* note the registers are not zero extended to the sf.
 	   this could be a problem. */
@@ -851,4 +844,8 @@ ia32_sys_call_table:
 	.quad sys_fanotify_init
 	.quad sys32_fanotify_mark
 	.quad sys_prlimit64		/* 340 */
+	.quad sys_name_to_handle_at
+	.quad compat_sys_open_by_handle_at
+	.quad compat_sys_clock_adjtime
+	.quad sys_syncfs
 ia32_syscall_end:
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 4ea15ca..448d73a 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -29,6 +29,7 @@
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mpspec.h>
+#include <asm/trampoline.h>
 
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
@@ -117,7 +118,8 @@ static inline void acpi_disable_pci(void)
 extern int acpi_save_state_mem(void);
 extern void acpi_restore_state_mem(void);
 
-extern unsigned long acpi_wakeup_address;
+extern const unsigned char acpi_wakeup_code[];
+#define acpi_wakeup_address (__pa(TRAMPOLINE_SYM(acpi_wakeup_code)))
 
 /* early initialization routine */
 extern void acpi_reserve_wakeup_memory(void);
@@ -186,15 +188,7 @@ struct bootnode;
 
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
-extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
-				unsigned long end);
-extern int acpi_scan_nodes(unsigned long start, unsigned long end);
-#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
-
-#ifdef CONFIG_NUMA_EMU
-extern void acpi_fake_nodes(const struct bootnode *fake_nodes,
-				   int num_nodes);
-#endif
+extern int x86_acpi_numa_init(void);
 #endif /* CONFIG_ACPI_NUMA */
 
 #define acpi_unlazy_tlb(x)	leave_mm(x)
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 64dc82e..3316822 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -9,23 +9,20 @@ struct amd_nb_bus_dev_range {
 	u8 dev_limit;
 };
 
-extern struct pci_device_id amd_nb_misc_ids[];
+extern const struct pci_device_id amd_nb_misc_ids[];
 extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[];
 struct bootnode;
 
-extern int early_is_amd_nb(u32 value);
+extern bool early_is_amd_nb(u32 value);
 extern int amd_cache_northbridges(void);
 extern void amd_flush_garts(void);
-extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
-extern int amd_scan_nodes(void);
-
-#ifdef CONFIG_NUMA_EMU
-extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes);
-extern void amd_get_nodes(struct bootnode *nodes);
-#endif
+extern int amd_numa_init(void);
+extern int amd_get_subcaches(int);
+extern int amd_set_subcaches(int, int);
 
 struct amd_northbridge {
 	struct pci_dev *misc;
+	struct pci_dev *link;
 };
 
 struct amd_northbridge_info {
@@ -35,17 +32,18 @@ struct amd_northbridge_info {
 };
 extern struct amd_northbridge_info amd_northbridges;
 
-#define AMD_NB_GART			0x1
-#define AMD_NB_L3_INDEX_DISABLE		0x2
+#define AMD_NB_GART			BIT(0)
+#define AMD_NB_L3_INDEX_DISABLE		BIT(1)
+#define AMD_NB_L3_PARTITIONING		BIT(2)
 
 #ifdef CONFIG_AMD_NB
 
-static inline int amd_nb_num(void)
+static inline u16 amd_nb_num(void)
 {
 	return amd_northbridges.num;
 }
 
-static inline int amd_nb_has_feature(int feature)
+static inline bool amd_nb_has_feature(unsigned feature)
 {
 	return ((amd_northbridges.flags & feature) == feature);
 }
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 3c89694..a279d98 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -220,7 +220,6 @@ extern void enable_IR_x2apic(void);
 
 extern int get_physical_broadcast(void);
 
-extern void apic_disable(void);
 extern int lapic_get_maxlvt(void);
 extern void clear_local_APIC(void);
 extern void connect_bsp_APIC(void);
@@ -228,7 +227,6 @@ extern void disconnect_bsp_APIC(int virt_wire_setup);
 extern void disable_local_APIC(void);
 extern void lapic_shutdown(void);
 extern int verify_local_APIC(void);
-extern void cache_APIC_registers(void);
 extern void sync_Arb_IDs(void);
 extern void init_bsp_APIC(void);
 extern void setup_local_APIC(void);
@@ -239,8 +237,7 @@ void register_lapic_address(unsigned long address);
 extern void setup_boot_APIC_clock(void);
 extern void setup_secondary_APIC_clock(void);
 extern int APIC_init_uniprocessor(void);
-extern void enable_NMI_through_LVT0(void);
-extern int apic_force_enable(void);
+extern int apic_force_enable(unsigned long addr);
 
 /*
  * On 32bit this is mach-xxx local
@@ -261,7 +258,6 @@ static inline void lapic_shutdown(void) { }
 #define local_apic_timer_c2_ok		1
 static inline void init_apic_mappings(void) { }
 static inline void disable_local_APIC(void) { }
-static inline void apic_disable(void) { }
 # define setup_boot_APIC_clock x86_init_noop
 # define setup_secondary_APIC_clock x86_init_noop
 #endif /* !CONFIG_X86_LOCAL_APIC */
@@ -307,8 +303,6 @@ struct apic {
 
 	void (*setup_apic_routing)(void);
 	int (*multi_timer_check)(int apic, int irq);
-	int (*apicid_to_node)(int logical_apicid);
-	int (*cpu_to_logical_apicid)(int cpu);
 	int (*cpu_present_to_apicid)(int mps_cpu);
 	void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
 	void (*setup_portio_remap)(void);
@@ -356,6 +350,23 @@ struct apic {
 	void (*icr_write)(u32 low, u32 high);
 	void (*wait_icr_idle)(void);
 	u32 (*safe_wait_icr_idle)(void);
+
+#ifdef CONFIG_X86_32
+	/*
+	 * Called very early during boot from get_smp_config().  It should
+	 * return the logical apicid.  x86_[bios]_cpu_to_apicid is
+	 * initialized before this function is called.
+	 *
+	 * If logical apicid can't be determined that early, the function
+	 * may return BAD_APICID.  Logical apicid will be configured after
+	 * init_apic_ldr() while bringing up CPUs.  Note that NUMA affinity
+	 * won't be applied properly during early boot in this case.
+	 */
+	int (*x86_32_early_logical_apicid)(int cpu);
+
+	/* determine CPU -> NUMA node mapping */
+	int (*x86_32_numa_cpu_node)(int cpu);
+#endif
 };
 
 /*
@@ -503,6 +514,11 @@ extern struct apic apic_noop;
 
 extern struct apic apic_default;
 
+static inline int noop_x86_32_early_logical_apicid(int cpu)
+{
+	return BAD_APICID;
+}
+
 /*
  * Set up the logical destination ID.
  *
@@ -522,7 +538,7 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
 	return cpuid_apic >> index_msb;
 }
 
-extern int default_apicid_to_node(int logical_apicid);
+extern int default_x86_32_numa_cpu_node(int cpu);
 
 #endif
 
@@ -558,12 +574,6 @@ static inline void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_ma
 	*retmap = *phys_map;
 }
 
-/* Mapping from cpu number to logical apicid */
-static inline int default_cpu_to_logical_apicid(int cpu)
-{
-	return 1 << cpu;
-}
-
 static inline int __default_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
@@ -596,8 +606,4 @@ extern int default_check_phys_apicid_present(int phys_apicid);
 
 #endif /* CONFIG_X86_LOCAL_APIC */
 
-#ifdef CONFIG_X86_32
-extern u8 cpu_2_logical_apicid[NR_CPUS];
-#endif
-
 #endif /* _ASM_X86_APIC_H */
diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h
index 47a30ff..d87988b 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -426,4 +426,16 @@ struct local_apic {
 #else
  #define BAD_APICID 0xFFFFu
 #endif
+
+enum ioapic_irq_destination_types {
+	dest_Fixed		= 0,
+	dest_LowestPrio		= 1,
+	dest_SMI		= 2,
+	dest__reserved_1	= 3,
+	dest_NMI		= 4,
+	dest_INIT		= 5,
+	dest__reserved_2	= 6,
+	dest_ExtINT		= 7
+};
+
 #endif /* _ASM_X86_APICDEF_H */
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
index c8bfe63..e020d88 100644
--- a/arch/x86/include/asm/bootparam.h
+++ b/arch/x86/include/asm/bootparam.h
@@ -12,6 +12,7 @@
 /* setup data types */
 #define SETUP_NONE			0
 #define SETUP_E820_EXT			1
+#define SETUP_DTB			2
 
 /* extensible setup data list node */
 struct setup_data {
diff --git a/arch/x86/include/asm/cacheflush.h b/arch/x86/include/asm/cacheflush.h
index 62f0844..4e12668 100644
--- a/arch/x86/include/asm/cacheflush.h
+++ b/arch/x86/include/asm/cacheflush.h
@@ -71,7 +71,7 @@ static inline void set_page_memtype(struct page *pg, unsigned long memtype) { }
  * Read/Write    : ReadOnly, ReadWrite
  * Presence      : NotPresent
  *
- * Within a catagory, the attributes are mutually exclusive.
+ * Within a category, the attributes are mutually exclusive.
  *
  * The implementation of this API will take care of various aspects that
  * are associated with changing such attributes, such as:
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 220e2ea..91f3e087 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -160,6 +160,7 @@
 #define X86_FEATURE_NODEID_MSR	(6*32+19) /* NodeId MSR */
 #define X86_FEATURE_TBM		(6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT	(6*32+22) /* topology extensions CPUID leafs */
+#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
@@ -279,6 +280,7 @@ extern const char * const x86_power_flags[32];
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
+#define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg		1
diff --git a/arch/x86/include/asm/dma.h b/arch/x86/include/asm/dma.h
index ca1098a..97b6d81 100644
--- a/arch/x86/include/asm/dma.h
+++ b/arch/x86/include/asm/dma.h
@@ -151,6 +151,7 @@
 #define DMA_AUTOINIT		0x10
 
 
+#ifdef CONFIG_ISA_DMA_API
 extern spinlock_t  dma_spin_lock;
 
 static inline unsigned long claim_dma_lock(void)
@@ -164,6 +165,7 @@ static inline void release_dma_lock(unsigned long flags)
 {
 	spin_unlock_irqrestore(&dma_spin_lock, flags);
 }
+#endif /* CONFIG_ISA_DMA_API */
 
 /* enable/disable a specific DMA channel */
 static inline void enable_dma(unsigned int dmanr)
@@ -303,9 +305,11 @@ static inline int get_dma_residue(unsigned int dmanr)
 }
 
 
-/* These are in kernel/dma.c: */
+/* These are in kernel/dma.c because x86 uses CONFIG_GENERIC_ISA_DMA */
+#ifdef CONFIG_ISA_DMA_API
 extern int request_dma(unsigned int dmanr, const char *device_id);
 extern void free_dma(unsigned int dmanr);
+#endif
 
 /* From PCI */
 
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index e99d55d..908b969 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -96,7 +96,7 @@ extern void e820_setup_gap(void);
 extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
 			unsigned long start_addr, unsigned long long end_addr);
 struct setup_data;
-extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data);
+extern void parse_e820_ext(struct setup_data *data);
 
 #if defined(CONFIG_X86_64) || \
 	(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h
index 57650ab..1cd6d26 100644
--- a/arch/x86/include/asm/entry_arch.h
+++ b/arch/x86/include/asm/entry_arch.h
@@ -16,10 +16,13 @@ BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
 BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
 BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
 
-.irpc idx, "01234567"
+.irp idx,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
+.if NUM_INVALIDATE_TLB_VECTORS > \idx
 BUILD_INTERRUPT3(invalidate_interrupt\idx,
 		 (INVALIDATE_TLB_VECTOR_START)+\idx,
 		 smp_invalidate_interrupt)
+.endif
 .endr
 #endif
 
diff --git a/arch/x86/include/asm/frame.h b/arch/x86/include/asm/frame.h
index 06850a7..2c6fc9e 100644
--- a/arch/x86/include/asm/frame.h
+++ b/arch/x86/include/asm/frame.h
@@ -7,14 +7,12 @@
    frame pointer later */
 #ifdef CONFIG_FRAME_POINTER
 	.macro FRAME
-	pushl %ebp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebp
 	CFI_REL_OFFSET ebp,0
 	movl %esp,%ebp
 	.endm
 	.macro ENDFRAME
-	popl %ebp
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebp
 	CFI_RESTORE ebp
 	.endm
 #else
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index 1f11ce4..d09bb03 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -37,7 +37,7 @@
 		       "+m" (*uaddr), "=&r" (tem)		\
 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -48,7 +48,7 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
@@ -109,9 +109,10 @@ static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
+	int ret = 0;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
 	/* Real i386 machines have no cmpxchg instruction */
@@ -119,21 +120,22 @@ static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
 		return -ENOSYS;
 #endif
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
+	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
 		     "2:\t.section .fixup, \"ax\"\n"
-		     "3:\tmov     %2, %0\n"
+		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
 		     _ASM_EXTABLE(1b, 3b)
-		     : "=a" (oldval), "+m" (*uaddr)
-		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
+		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
 	);
 
-	return oldval;
+	*uval = oldval;
+	return ret;
 }
 
 #endif
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index 0274ec5..bb9efe8 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -45,6 +45,30 @@ extern void invalidate_interrupt4(void);
 extern void invalidate_interrupt5(void);
 extern void invalidate_interrupt6(void);
 extern void invalidate_interrupt7(void);
+extern void invalidate_interrupt8(void);
+extern void invalidate_interrupt9(void);
+extern void invalidate_interrupt10(void);
+extern void invalidate_interrupt11(void);
+extern void invalidate_interrupt12(void);
+extern void invalidate_interrupt13(void);
+extern void invalidate_interrupt14(void);
+extern void invalidate_interrupt15(void);
+extern void invalidate_interrupt16(void);
+extern void invalidate_interrupt17(void);
+extern void invalidate_interrupt18(void);
+extern void invalidate_interrupt19(void);
+extern void invalidate_interrupt20(void);
+extern void invalidate_interrupt21(void);
+extern void invalidate_interrupt22(void);
+extern void invalidate_interrupt23(void);
+extern void invalidate_interrupt24(void);
+extern void invalidate_interrupt25(void);
+extern void invalidate_interrupt26(void);
+extern void invalidate_interrupt27(void);
+extern void invalidate_interrupt28(void);
+extern void invalidate_interrupt29(void);
+extern void invalidate_interrupt30(void);
+extern void invalidate_interrupt31(void);
 
 extern void irq_move_cleanup_interrupt(void);
 extern void reboot_interrupt(void);
diff --git a/arch/x86/include/asm/init.h b/arch/x86/include/asm/init.h
index 36fb1a6..8dbe353 100644
--- a/arch/x86/include/asm/init.h
+++ b/arch/x86/include/asm/init.h
@@ -11,8 +11,8 @@ kernel_physical_mapping_init(unsigned long start,
 			     unsigned long page_size_mask);
 
 
-extern unsigned long __initdata e820_table_start;
-extern unsigned long __meminitdata e820_table_end;
-extern unsigned long __meminitdata e820_table_top;
+extern unsigned long __initdata pgt_buf_start;
+extern unsigned long __meminitdata pgt_buf_end;
+extern unsigned long __meminitdata pgt_buf_top;
 
 #endif /* _ASM_X86_INIT_32_H */
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index f327d38..c4bd267 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -63,17 +63,6 @@ union IO_APIC_reg_03 {
 	} __attribute__ ((packed)) bits;
 };
 
-enum ioapic_irq_destination_types {
-	dest_Fixed = 0,
-	dest_LowestPrio = 1,
-	dest_SMI = 2,
-	dest__reserved_1 = 3,
-	dest_NMI = 4,
-	dest_INIT = 5,
-	dest__reserved_2 = 6,
-	dest_ExtINT = 7
-};
-
 struct IO_APIC_route_entry {
 	__u32	vector		:  8,
 		delivery_mode	:  3,	/* 000: FIXED
@@ -106,6 +95,10 @@ struct IR_IO_APIC_route_entry {
 		index		: 15;
 } __attribute__ ((packed));
 
+#define IOAPIC_AUTO     -1
+#define IOAPIC_EDGE     0
+#define IOAPIC_LEVEL    1
+
 #ifdef CONFIG_X86_IO_APIC
 
 /*
@@ -150,11 +143,6 @@ extern int timer_through_8259;
 #define io_apic_assign_pci_irqs \
 	(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
 
-extern u8 io_apic_unique_id(u8 id);
-extern int io_apic_get_unique_id(int ioapic, int apic_id);
-extern int io_apic_get_version(int ioapic);
-extern int io_apic_get_redir_entries(int ioapic);
-
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
@@ -162,6 +150,8 @@ void setup_IO_APIC_irq_extra(u32 gsi);
 extern void ioapic_and_gsi_init(void);
 extern void ioapic_insert_resources(void);
 
+int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
 extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
@@ -186,6 +176,8 @@ extern void __init pre_init_apic_IRQ0(void);
 
 extern void mp_save_irq(struct mpc_intsrc *m);
 
+extern void disable_ioapic_support(void);
+
 #else  /* !CONFIG_X86_IO_APIC */
 
 #define io_apic_assign_pci_irqs 0
@@ -199,6 +191,26 @@ static inline int mp_find_ioapic(u32 gsi) { return 0; }
 struct io_apic_irq_attr;
 static inline int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr) { return 0; }
+
+static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+{
+	return NULL;
+}
+
+static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { }
+static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent)
+{
+	return -ENOMEM;
+}
+
+static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { }
+static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent)
+{
+	return -ENOMEM;
+}
+
+static inline void mp_save_irq(struct mpc_intsrc *m) { };
+static inline void disable_ioapic_support(void) { }
 #endif
 
 #endif /* _ASM_X86_IO_APIC_H */
diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h
index 0b72282..615fa90 100644
--- a/arch/x86/include/asm/ipi.h
+++ b/arch/x86/include/asm/ipi.h
@@ -123,10 +123,6 @@ extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask,
 						 int vector);
 extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
 							 int vector);
-extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
-							 int vector);
-extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
-							 int vector);
 
 /* Avoid include hell */
 #define NMI_VECTOR 0x02
@@ -150,6 +146,10 @@ static inline void __default_local_send_IPI_all(int vector)
 }
 
 #ifdef CONFIG_X86_32
+extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
+							 int vector);
+extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
+							 int vector);
 extern void default_send_IPI_mask_logical(const struct cpumask *mask,
 						 int vector);
 extern void default_send_IPI_allbutself(int vector);
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index c704b38..ba870bb 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -10,9 +10,6 @@
 #include <asm/apicdef.h>
 #include <asm/irq_vectors.h>
 
-/* Even though we don't support this, supply it to appease OF */
-static inline void irq_dispose_mapping(unsigned int virq) { }
-
 static inline int irq_canonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
diff --git a/arch/x86/include/asm/irq_controller.h b/arch/x86/include/asm/irq_controller.h
new file mode 100644
index 0000000..423bbbd
--- /dev/null
+++ b/arch/x86/include/asm/irq_controller.h
@@ -0,0 +1,12 @@
+#ifndef __IRQ_CONTROLLER__
+#define __IRQ_CONTROLLER__
+
+struct irq_domain {
+	int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize,
+			u32 *out_hwirq, u32 *out_type);
+	void *priv;
+	struct device_node *controller;
+	struct list_head l;
+};
+
+#endif
diff --git a/arch/x86/include/asm/irq_vectors.h b/arch/x86/include/asm/irq_vectors.h
index 6af0894..6e976ee 100644
--- a/arch/x86/include/asm/irq_vectors.h
+++ b/arch/x86/include/asm/irq_vectors.h
@@ -1,6 +1,7 @@
 #ifndef _ASM_X86_IRQ_VECTORS_H
 #define _ASM_X86_IRQ_VECTORS_H
 
+#include <linux/threads.h>
 /*
  * Linux IRQ vector layout.
  *
@@ -16,8 +17,8 @@
  *  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
  *  Vectors  32 ... 127 : device interrupts
  *  Vector  128         : legacy int80 syscall interface
- *  Vectors 129 ... 237 : device interrupts
- *  Vectors 238 ... 255 : special interrupts
+ *  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 : device interrupts
+ *  Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
  *
  * 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
  *
@@ -96,37 +97,43 @@
 #define THRESHOLD_APIC_VECTOR		0xf9
 #define REBOOT_VECTOR			0xf8
 
-/* f0-f7 used for spreading out TLB flushes: */
-#define INVALIDATE_TLB_VECTOR_END	0xf7
-#define INVALIDATE_TLB_VECTOR_START	0xf0
-#define NUM_INVALIDATE_TLB_VECTORS	   8
-
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR		0xef
-
 /*
  * Generic system vector for platform specific use
  */
-#define X86_PLATFORM_IPI_VECTOR		0xed
+#define X86_PLATFORM_IPI_VECTOR		0xf7
 
 /*
  * IRQ work vector:
  */
-#define IRQ_WORK_VECTOR			0xec
+#define IRQ_WORK_VECTOR			0xf6
 
-#define UV_BAU_MESSAGE			0xea
+#define UV_BAU_MESSAGE			0xf5
 
 /*
  * Self IPI vector for machine checks
  */
-#define MCE_SELF_VECTOR			0xeb
+#define MCE_SELF_VECTOR			0xf4
 
 /* Xen vector callback to receive events in a HVM domain */
-#define XEN_HVM_EVTCHN_CALLBACK		0xe9
+#define XEN_HVM_EVTCHN_CALLBACK		0xf3
+
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR		0xef
+
+/* up to 32 vectors used for spreading out TLB flushes: */
+#if NR_CPUS <= 32
+# define NUM_INVALIDATE_TLB_VECTORS	(NR_CPUS)
+#else
+# define NUM_INVALIDATE_TLB_VECTORS	(32)
+#endif
+
+#define INVALIDATE_TLB_VECTOR_END	(0xee)
+#define INVALIDATE_TLB_VECTOR_START	\
+	(INVALIDATE_TLB_VECTOR_END-NUM_INVALIDATE_TLB_VECTORS+1)
 
 #define NR_VECTORS			 256
 
diff --git a/arch/x86/include/asm/kdebug.h b/arch/x86/include/asm/kdebug.h
index ca242d3..fe2cc6e 100644
--- a/arch/x86/include/asm/kdebug.h
+++ b/arch/x86/include/asm/kdebug.h
@@ -13,7 +13,6 @@ enum die_val {
 	DIE_PANIC,
 	DIE_NMI,
 	DIE_DIE,
-	DIE_NMIWATCHDOG,
 	DIE_KERNELDEBUG,
 	DIE_TRAP,
 	DIE_GPF,
@@ -27,7 +26,7 @@ extern void die(const char *, struct pt_regs *,long);
 extern int __must_check __die(const char *, struct pt_regs *, long);
 extern void show_registers(struct pt_regs *regs);
 extern void show_trace(struct task_struct *t, struct pt_regs *regs,
-		       unsigned long *sp);
+		       unsigned long *sp, unsigned long bp);
 extern void __show_regs(struct pt_regs *regs, int all);
 extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 8e37deb..0f52135 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -142,9 +142,9 @@ struct x86_emulate_ops {
 	int (*pio_out_emulated)(int size, unsigned short port, const void *val,
 				unsigned int count, struct kvm_vcpu *vcpu);
 
-	bool (*get_cached_descriptor)(struct desc_struct *desc,
+	bool (*get_cached_descriptor)(struct desc_struct *desc, u32 *base3,
 				      int seg, struct kvm_vcpu *vcpu);
-	void (*set_cached_descriptor)(struct desc_struct *desc,
+	void (*set_cached_descriptor)(struct desc_struct *desc, u32 base3,
 				      int seg, struct kvm_vcpu *vcpu);
 	u16 (*get_segment_selector)(int seg, struct kvm_vcpu *vcpu);
 	void (*set_segment_selector)(u16 sel, int seg, struct kvm_vcpu *vcpu);
@@ -239,6 +239,7 @@ struct x86_emulate_ctxt {
 	int interruptibility;
 
 	bool perm_ok; /* do not check permissions if true */
+	bool only_vendor_specific_insn;
 
 	bool have_exception;
 	struct x86_exception exception;
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index ffd7f8d..c8af099 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -85,7 +85,7 @@
 
 #define ASYNC_PF_PER_VCPU 64
 
-extern spinlock_t kvm_lock;
+extern raw_spinlock_t kvm_lock;
 extern struct list_head vm_list;
 
 struct kvm_vcpu;
@@ -255,6 +255,8 @@ struct kvm_mmu {
 	int (*sync_page)(struct kvm_vcpu *vcpu,
 			 struct kvm_mmu_page *sp);
 	void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
+	void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+			u64 *spte, const void *pte, unsigned long mmu_seq);
 	hpa_t root_hpa;
 	int root_level;
 	int shadow_root_level;
@@ -335,12 +337,6 @@ struct kvm_vcpu_arch {
 	u64  *last_pte_updated;
 	gfn_t last_pte_gfn;
 
-	struct {
-		gfn_t gfn;	/* presumed gfn during guest pte update */
-		pfn_t pfn;	/* pfn corresponding to that gfn */
-		unsigned long mmu_seq;
-	} update_pte;
-
 	struct fpu guest_fpu;
 	u64 xcr0;
 
@@ -448,7 +444,7 @@ struct kvm_arch {
 
 	unsigned long irq_sources_bitmap;
 	s64 kvmclock_offset;
-	spinlock_t tsc_write_lock;
+	raw_spinlock_t tsc_write_lock;
 	u64 last_tsc_nsec;
 	u64 last_tsc_offset;
 	u64 last_tsc_write;
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 0c90dd9..9c7d95f 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -25,7 +25,6 @@ extern int pic_mode;
 #define MAX_IRQ_SOURCES		256
 
 extern unsigned int def_to_bigsmp;
-extern u8 apicid_2_node[];
 
 #ifdef CONFIG_X86_NUMAQ
 extern int mp_bus_id_to_node[MAX_MP_BUSSES];
@@ -33,8 +32,6 @@ extern int mp_bus_id_to_local[MAX_MP_BUSSES];
 extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
 #endif
 
-#define MAX_APICID		256
-
 #else /* CONFIG_X86_64: */
 
 #define MAX_MP_BUSSES		256
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 43a18c7..fd5a1f3 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -43,6 +43,7 @@
 
 #define MSR_MTRRcap			0x000000fe
 #define MSR_IA32_BBL_CR_CTL		0x00000119
+#define MSR_IA32_BBL_CR_CTL3		0x0000011e
 
 #define MSR_IA32_SYSENTER_CS		0x00000174
 #define MSR_IA32_SYSENTER_ESP		0x00000175
@@ -52,6 +53,9 @@
 #define MSR_IA32_MCG_STATUS		0x0000017a
 #define MSR_IA32_MCG_CTL		0x0000017b
 
+#define MSR_OFFCORE_RSP_0		0x000001a6
+#define MSR_OFFCORE_RSP_1		0x000001a7
+
 #define MSR_IA32_PEBS_ENABLE		0x000003f1
 #define MSR_IA32_DS_AREA		0x00000600
 #define MSR_IA32_PERF_CAPABILITIES	0x00000345
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index c76f5b9..4886a68 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -7,7 +7,6 @@
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
-extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
 extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
 extern int reserve_perfctr_nmi(unsigned int);
 extern void release_perfctr_nmi(unsigned int);
@@ -30,8 +29,8 @@ void arch_trigger_all_cpu_backtrace(void);
  * external nmis, because the local ones are more frequent.
  *
  * Also setup some default high/normal/low settings for
- * subsystems to registers with.  Using 4 bits to seperate
- * the priorities.  This can go alot higher if needed be.
+ * subsystems to registers with.  Using 4 bits to separate
+ * the priorities.  This can go a lot higher if needed be.
  */
 
 #define NMI_LOCAL_SHIFT		16	/* randomly picked */
diff --git a/arch/x86/include/asm/nops.h b/arch/x86/include/asm/nops.h
index 6d8723a..af78849 100644
--- a/arch/x86/include/asm/nops.h
+++ b/arch/x86/include/asm/nops.h
@@ -38,7 +38,7 @@
 #define K8_NOP8	K8_NOP4 K8_NOP4
 
 /* K7 nops
-   uses eax dependencies (arbitary choice)
+   uses eax dependencies (arbitrary choice)
    1: nop
    2: movl %eax,%eax
    3: leal (,%eax,1),%eax
diff --git a/arch/x86/include/asm/numa.h b/arch/x86/include/asm/numa.h
index 27da400..3d4dab4 100644
--- a/arch/x86/include/asm/numa.h
+++ b/arch/x86/include/asm/numa.h
@@ -1,5 +1,57 @@
+#ifndef _ASM_X86_NUMA_H
+#define _ASM_X86_NUMA_H
+
+#include <asm/topology.h>
+#include <asm/apicdef.h>
+
+#ifdef CONFIG_NUMA
+
+#define NR_NODE_MEMBLKS		(MAX_NUMNODES*2)
+
+/*
+ * __apicid_to_node[] stores the raw mapping between physical apicid and
+ * node and is used to initialize cpu_to_node mapping.
+ *
+ * The mapping may be overridden by apic->numa_cpu_node() on 32bit and thus
+ * should be accessed by the accessors - set_apicid_to_node() and
+ * numa_cpu_node().
+ */
+extern s16 __apicid_to_node[MAX_LOCAL_APIC];
+
+static inline void set_apicid_to_node(int apicid, s16 node)
+{
+	__apicid_to_node[apicid] = node;
+}
+#else	/* CONFIG_NUMA */
+static inline void set_apicid_to_node(int apicid, s16 node)
+{
+}
+#endif	/* CONFIG_NUMA */
+
 #ifdef CONFIG_X86_32
 # include "numa_32.h"
 #else
 # include "numa_64.h"
 #endif
+
+#ifdef CONFIG_NUMA
+extern void __cpuinit numa_set_node(int cpu, int node);
+extern void __cpuinit numa_clear_node(int cpu);
+extern void __init numa_init_array(void);
+extern void __init init_cpu_to_node(void);
+extern void __cpuinit numa_add_cpu(int cpu);
+extern void __cpuinit numa_remove_cpu(int cpu);
+#else	/* CONFIG_NUMA */
+static inline void numa_set_node(int cpu, int node)	{ }
+static inline void numa_clear_node(int cpu)		{ }
+static inline void numa_init_array(void)		{ }
+static inline void init_cpu_to_node(void)		{ }
+static inline void numa_add_cpu(int cpu)		{ }
+static inline void numa_remove_cpu(int cpu)		{ }
+#endif	/* CONFIG_NUMA */
+
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable);
+#endif
+
+#endif	/* _ASM_X86_NUMA_H */
diff --git a/arch/x86/include/asm/numa_32.h b/arch/x86/include/asm/numa_32.h
index b0ef2b4..c6beed1 100644
--- a/arch/x86/include/asm/numa_32.h
+++ b/arch/x86/include/asm/numa_32.h
@@ -4,7 +4,12 @@
 extern int numa_off;
 
 extern int pxm_to_nid(int pxm);
-extern void numa_remove_cpu(int cpu);
+
+#ifdef CONFIG_NUMA
+extern int __cpuinit numa_cpu_node(int cpu);
+#else	/* CONFIG_NUMA */
+static inline int numa_cpu_node(int cpu)		{ return NUMA_NO_NODE; }
+#endif	/* CONFIG_NUMA */
 
 #ifdef CONFIG_HIGHMEM
 extern void set_highmem_pages_init(void);
diff --git a/arch/x86/include/asm/numa_64.h b/arch/x86/include/asm/numa_64.h
index 0493be3..344eb17 100644
--- a/arch/x86/include/asm/numa_64.h
+++ b/arch/x86/include/asm/numa_64.h
@@ -2,23 +2,16 @@
 #define _ASM_X86_NUMA_64_H
 
 #include <linux/nodemask.h>
-#include <asm/apicdef.h>
 
 struct bootnode {
 	u64 start;
 	u64 end;
 };
 
-extern int compute_hash_shift(struct bootnode *nodes, int numblks,
-			      int *nodeids);
-
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
-extern void numa_init_array(void);
 extern int numa_off;
 
-extern s16 apicid_to_node[MAX_LOCAL_APIC];
-
 extern unsigned long numa_free_all_bootmem(void);
 extern void setup_node_bootmem(int nodeid, unsigned long start,
 			       unsigned long end);
@@ -31,11 +24,11 @@ extern void setup_node_bootmem(int nodeid, unsigned long start,
  */
 #define NODE_MIN_SIZE (4*1024*1024)
 
-extern void __init init_cpu_to_node(void);
-extern void __cpuinit numa_set_node(int cpu, int node);
-extern void __cpuinit numa_clear_node(int cpu);
-extern void __cpuinit numa_add_cpu(int cpu);
-extern void __cpuinit numa_remove_cpu(int cpu);
+extern nodemask_t numa_nodes_parsed __initdata;
+
+extern int __cpuinit numa_cpu_node(int cpu);
+extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
+extern void __init numa_set_distance(int from, int to, int distance);
 
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
@@ -43,11 +36,7 @@ extern void __cpuinit numa_remove_cpu(int cpu);
 void numa_emu_cmdline(char *);
 #endif /* CONFIG_NUMA_EMU */
 #else
-static inline void init_cpu_to_node(void)		{ }
-static inline void numa_set_node(int cpu, int node)	{ }
-static inline void numa_clear_node(int cpu)		{ }
-static inline void numa_add_cpu(int cpu, int node)	{ }
-static inline void numa_remove_cpu(int cpu)		{ }
+static inline int numa_cpu_node(int cpu)		{ return NUMA_NO_NODE; }
 #endif
 
 #endif /* _ASM_X86_NUMA_64_H */
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index f482010..5ca6801 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -20,7 +20,7 @@ extern struct olpc_platform_t olpc_platform_info;
 
 /*
  * OLPC board IDs contain the major build number within the mask 0x0ff0,
- * and the minor build number withing 0x000f.  Pre-builds have a minor
+ * and the minor build number within 0x000f.  Pre-builds have a minor
  * number less than 8, and normal builds start at 8.  For example, 0x0B10
  * is a PreB1, and 0x0C18 is a C1.
  */
diff --git a/arch/x86/include/asm/olpc_ofw.h b/arch/x86/include/asm/olpc_ofw.h
index 641988e..c5d3a5a 100644
--- a/arch/x86/include/asm/olpc_ofw.h
+++ b/arch/x86/include/asm/olpc_ofw.h
@@ -6,7 +6,7 @@
 
 #define OLPC_OFW_SIG 0x2057464F	/* aka "OFW " */
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE
+#ifdef CONFIG_OLPC
 
 extern bool olpc_ofw_is_installed(void);
 
@@ -26,19 +26,15 @@ extern void setup_olpc_ofw_pgd(void);
 /* check if OFW was detected during boot */
 extern bool olpc_ofw_present(void);
 
-#else /* !CONFIG_OLPC_OPENFIRMWARE */
-
-static inline bool olpc_ofw_is_installed(void) { return false; }
+#else /* !CONFIG_OLPC */
 static inline void olpc_ofw_detect(void) { }
 static inline void setup_olpc_ofw_pgd(void) { }
-static inline bool olpc_ofw_present(void) { return false; }
-
-#endif /* !CONFIG_OLPC_OPENFIRMWARE */
+#endif /* !CONFIG_OLPC */
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE_DT
+#ifdef CONFIG_OF_PROMTREE
 extern void olpc_dt_build_devicetree(void);
 #else
 static inline void olpc_dt_build_devicetree(void) { }
-#endif /* CONFIG_OLPC_OPENFIRMWARE_DT */
+#endif
 
 #endif /* _ASM_X86_OLPC_OFW_H */
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index 1df6621..bce688d 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -2,6 +2,7 @@
 #define _ASM_X86_PAGE_DEFS_H
 
 #include <linux/const.h>
+#include <linux/types.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
@@ -45,11 +46,15 @@ extern int devmem_is_allowed(unsigned long pagenr);
 extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
 
+static inline phys_addr_t get_max_mapped(void)
+{
+	return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
+}
+
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
-extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8);
+extern void initmem_init(void);
 extern void free_initmem(void);
 
 #endif	/* !__ASSEMBLY__ */
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h
index 7e17295..a09e1f0 100644
--- a/arch/x86/include/asm/percpu.h
+++ b/arch/x86/include/asm/percpu.h
@@ -451,6 +451,26 @@ do {									\
 #define irqsafe_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
 #endif /* !CONFIG_M386 */
 
+#ifdef CONFIG_X86_CMPXCHG64
+#define percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)			\
+({									\
+	char __ret;							\
+	typeof(o1) __o1 = o1;						\
+	typeof(o1) __n1 = n1;						\
+	typeof(o2) __o2 = o2;						\
+	typeof(o2) __n2 = n2;						\
+	typeof(o2) __dummy = n2;					\
+	asm volatile("cmpxchg8b "__percpu_arg(1)"\n\tsetz %0\n\t"	\
+		    : "=a"(__ret), "=m" (pcp1), "=d"(__dummy)		\
+		    :  "b"(__n1), "c"(__n2), "a"(__o1), "d"(__o2));	\
+	__ret;								\
+})
+
+#define __this_cpu_cmpxchg_double_4(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)
+#define this_cpu_cmpxchg_double_4(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)
+#define irqsafe_cpu_cmpxchg_double_4(pcp1, pcp2, o1, o2, n1, n2)	percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)
+#endif /* CONFIG_X86_CMPXCHG64 */
+
 /*
  * Per cpu atomic 64 bit operations are only available under 64 bit.
  * 32 bit must fall back to generic operations.
@@ -480,6 +500,34 @@ do {									\
 #define irqsafe_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define irqsafe_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
 #define irqsafe_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+
+/*
+ * Pretty complex macro to generate cmpxchg16 instruction.  The instruction
+ * is not supported on early AMD64 processors so we must be able to emulate
+ * it in software.  The address used in the cmpxchg16 instruction must be
+ * aligned to a 16 byte boundary.
+ */
+#define percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)			\
+({									\
+	char __ret;							\
+	typeof(o1) __o1 = o1;						\
+	typeof(o1) __n1 = n1;						\
+	typeof(o2) __o2 = o2;						\
+	typeof(o2) __n2 = n2;						\
+	typeof(o2) __dummy;						\
+	alternative_io("call this_cpu_cmpxchg16b_emu\n\t" P6_NOP4,	\
+		       "cmpxchg16b %%gs:(%%rsi)\n\tsetz %0\n\t",	\
+		       X86_FEATURE_CX16,				\
+		       ASM_OUTPUT2("=a"(__ret), "=d"(__dummy)),		\
+		       "S" (&pcp1), "b"(__n1), "c"(__n2),		\
+		       "a"(__o1), "d"(__o2));				\
+	__ret;								\
+})
+
+#define __this_cpu_cmpxchg_double_8(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)
+#define this_cpu_cmpxchg_double_8(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)
+#define irqsafe_cpu_cmpxchg_double_8(pcp1, pcp2, o1, o2, n1, n2)	percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)
+
 #endif
 
 /* This is not atomic against other CPUs -- CPU preemption needs to be off */
diff --git a/arch/x86/include/asm/perf_event_p4.h b/arch/x86/include/asm/perf_event_p4.h
index cc29086..56fd9e3 100644
--- a/arch/x86/include/asm/perf_event_p4.h
+++ b/arch/x86/include/asm/perf_event_p4.h
@@ -1,5 +1,5 @@
 /*
- * Netburst Perfomance Events (P4, old Xeon)
+ * Netburst Performance Events (P4, old Xeon)
  */
 
 #ifndef PERF_EVENT_P4_H
@@ -9,7 +9,7 @@
 #include <linux/bitops.h>
 
 /*
- * NetBurst has perfomance MSRs shared between
+ * NetBurst has performance MSRs shared between
  * threads if HT is turned on, ie for both logical
  * processors (mem: in turn in Atom with HT support
  * perf-MSRs are not shared and every thread has its
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
index 94b979d..effff47 100644
--- a/arch/x86/include/asm/pgtable-3level.h
+++ b/arch/x86/include/asm/pgtable-3level.h
@@ -69,8 +69,6 @@ static inline void native_pmd_clear(pmd_t *pmd)
 
 static inline void pud_clear(pud_t *pudp)
 {
-	unsigned long pgd;
-
 	set_pud(pudp, __pud(0));
 
 	/*
@@ -79,13 +77,10 @@ static inline void pud_clear(pud_t *pudp)
 	 * section 8.1: in PAE mode we explicitly have to flush the
 	 * TLB via cr3 if the top-level pgd is changed...
 	 *
-	 * Make sure the pud entry we're updating is within the
-	 * current pgd to avoid unnecessary TLB flushes.
+	 * Currently all places where pud_clear() is called either have
+	 * flush_tlb_mm() followed or don't need TLB flush (x86_64 code or
+	 * pud_clear_bad()), so we don't need TLB flush here.
 	 */
-	pgd = read_cr3();
-	if (__pa(pudp) >= pgd && __pa(pudp) <
-	    (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
-		write_cr3(pgd);
 }
 
 #ifdef CONFIG_SMP
diff --git a/arch/x86/include/asm/processor-flags.h b/arch/x86/include/asm/processor-flags.h
index 7a3e836..a898a2b 100644
--- a/arch/x86/include/asm/processor-flags.h
+++ b/arch/x86/include/asm/processor-flags.h
@@ -7,7 +7,7 @@
  */
 #define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
 #define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
-#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
+#define X86_EFLAGS_AF	0x00000010 /* Auxiliary carry Flag */
 #define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
 #define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
 #define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 45636ce..4c25ab4 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -94,10 +94,6 @@ struct cpuinfo_x86 {
 	int			x86_cache_alignment;	/* In bytes */
 	int			x86_power;
 	unsigned long		loops_per_jiffy;
-#ifdef CONFIG_SMP
-	/* cpus sharing the last level cache: */
-	cpumask_var_t		llc_shared_map;
-#endif
 	/* cpuid returned max cores value: */
 	u16			 x86_max_cores;
 	u16			apicid;
diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index b4ec95f..971e0b4 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -1 +1,69 @@
-/* dummy prom.h; here to make linux/of.h's #includes happy */
+/*
+ * Definitions for Device tree / OpenFirmware handling on X86
+ *
+ * based on arch/powerpc/include/asm/prom.h which is
+ *         Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _ASM_X86_PROM_H
+#define _ASM_X86_PROM_H
+#ifndef __ASSEMBLY__
+
+#include <linux/of.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/setup.h>
+#include <asm/irq_controller.h>
+
+#ifdef CONFIG_OF
+extern int of_ioapic;
+extern u64 initial_dtb;
+extern void add_dtb(u64 data);
+extern void x86_add_irq_domains(void);
+void __cpuinit x86_of_pci_init(void);
+void x86_dtb_init(void);
+
+static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+	return pdev ? pdev->dev.of_node : NULL;
+}
+
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	return pci_device_to_OF_node(bus->self);
+}
+
+#else
+static inline void add_dtb(u64 data) { }
+static inline void x86_add_irq_domains(void) { }
+static inline void x86_of_pci_init(void) { }
+static inline void x86_dtb_init(void) { }
+#define of_ioapic 0
+#endif
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+
+#define pci_address_to_pio pci_address_to_pio
+unsigned long pci_address_to_pio(phys_addr_t addr);
+
+/**
+ * irq_dispose_mapping - Unmap an interrupt
+ * @virq: linux virq number of the interrupt to unmap
+ *
+ * FIXME: We really should implement proper virq handling like power,
+ * but that's going to be major surgery.
+ */
+static inline void irq_dispose_mapping(unsigned int virq) { }
+
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/arch/x86/include/asm/ptrace-abi.h b/arch/x86/include/asm/ptrace-abi.h
index 52b098a..7b0a55a 100644
--- a/arch/x86/include/asm/ptrace-abi.h
+++ b/arch/x86/include/asm/ptrace-abi.h
@@ -31,7 +31,7 @@
 #define R12 24
 #define RBP 32
 #define RBX 40
-/* arguments: interrupts/non tracing syscalls only save upto here*/
+/* arguments: interrupts/non tracing syscalls only save up to here*/
 #define R11 48
 #define R10 56
 #define R9 64
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 78cd1ea..1babf8a 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -73,7 +73,7 @@ struct pt_regs {
 	unsigned long r12;
 	unsigned long rbp;
 	unsigned long rbx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
+/* arguments: non interrupts/non tracing syscalls only save up to here*/
 	unsigned long r11;
 	unsigned long r10;
 	unsigned long r9;
@@ -103,7 +103,7 @@ struct pt_regs {
 	unsigned long r12;
 	unsigned long bp;
 	unsigned long bx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
+/* arguments: non interrupts/non tracing syscalls only save up to here*/
 	unsigned long r11;
 	unsigned long r10;
 	unsigned long r9;
diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h
index 562d4fd..3250e3d 100644
--- a/arch/x86/include/asm/reboot.h
+++ b/arch/x86/include/asm/reboot.h
@@ -18,7 +18,10 @@ extern struct machine_ops machine_ops;
 
 void native_machine_crash_shutdown(struct pt_regs *regs);
 void native_machine_shutdown(void);
-void machine_real_restart(const unsigned char *code, int length);
+void machine_real_restart(unsigned int type);
+/* These must match dispatch_table in reboot_32.S */
+#define MRR_BIOS	0
+#define MRR_APM		1
 
 typedef void (*nmi_shootdown_cb)(int, struct die_args*);
 void nmi_shootdown_cpus(nmi_shootdown_cb callback);
diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h
index d1e41b0..df4cd32 100644
--- a/arch/x86/include/asm/rwsem.h
+++ b/arch/x86/include/asm/rwsem.h
@@ -37,26 +37,9 @@
 #endif
 
 #ifdef __KERNEL__
-
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/lockdep.h>
 #include <asm/asm.h>
 
-struct rwsem_waiter;
-
-extern asmregparm struct rw_semaphore *
- rwsem_down_read_failed(struct rw_semaphore *sem);
-extern asmregparm struct rw_semaphore *
- rwsem_down_write_failed(struct rw_semaphore *sem);
-extern asmregparm struct rw_semaphore *
- rwsem_wake(struct rw_semaphore *);
-extern asmregparm struct rw_semaphore *
- rwsem_downgrade_wake(struct rw_semaphore *sem);
-
 /*
- * the semaphore definition
- *
  * The bias values and the counter type limits the number of
  * potential readers/writers to 32767 for 32 bits and 2147483647
  * for 64 bits.
@@ -74,43 +57,6 @@ extern asmregparm struct rw_semaphore *
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
-typedef signed long rwsem_count_t;
-
-struct rw_semaphore {
-	rwsem_count_t		count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-
-#define __RWSEM_INITIALIZER(name)				\
-{								\
-	RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-	LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) \
-}
-
-#define DECLARE_RWSEM(name)					\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)						\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__init_rwsem((sem), #sem, &__key);			\
-} while (0)
-
 /*
  * lock for reading
  */
@@ -133,7 +79,7 @@ static inline void __down_read(struct rw_semaphore *sem)
  */
 static inline int __down_read_trylock(struct rw_semaphore *sem)
 {
-	rwsem_count_t result, tmp;
+	long result, tmp;
 	asm volatile("# beginning __down_read_trylock\n\t"
 		     "  mov          %0,%1\n\t"
 		     "1:\n\t"
@@ -155,7 +101,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
  */
 static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
-	rwsem_count_t tmp;
+	long tmp;
 	asm volatile("# beginning down_write\n\t"
 		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* adds 0xffff0001, returns the old value */
@@ -180,9 +126,8 @@ static inline void __down_write(struct rw_semaphore *sem)
  */
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
-	rwsem_count_t ret = cmpxchg(&sem->count,
-				    RWSEM_UNLOCKED_VALUE,
-				    RWSEM_ACTIVE_WRITE_BIAS);
+	long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+			   RWSEM_ACTIVE_WRITE_BIAS);
 	if (ret == RWSEM_UNLOCKED_VALUE)
 		return 1;
 	return 0;
@@ -193,7 +138,7 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
  */
 static inline void __up_read(struct rw_semaphore *sem)
 {
-	rwsem_count_t tmp;
+	long tmp;
 	asm volatile("# beginning __up_read\n\t"
 		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* subtracts 1, returns the old value */
@@ -211,7 +156,7 @@ static inline void __up_read(struct rw_semaphore *sem)
  */
 static inline void __up_write(struct rw_semaphore *sem)
 {
-	rwsem_count_t tmp;
+	long tmp;
 	asm volatile("# beginning __up_write\n\t"
 		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* subtracts 0xffff0001, returns the old value */
@@ -247,8 +192,7 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
 /*
  * implement atomic add functionality
  */
-static inline void rwsem_atomic_add(rwsem_count_t delta,
-				    struct rw_semaphore *sem)
+static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
 {
 	asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0"
 		     : "+m" (sem->count)
@@ -258,10 +202,9 @@ static inline void rwsem_atomic_add(rwsem_count_t delta,
 /*
  * implement exchange and add functionality
  */
-static inline rwsem_count_t rwsem_atomic_update(rwsem_count_t delta,
-						struct rw_semaphore *sem)
+static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
-	rwsem_count_t tmp = delta;
+	long tmp = delta;
 
 	asm volatile(LOCK_PREFIX "xadd %0,%1"
 		     : "+r" (tmp), "+m" (sem->count)
@@ -270,10 +213,5 @@ static inline rwsem_count_t rwsem_atomic_update(rwsem_count_t delta,
 	return tmp + delta;
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_RWSEM_H */
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 231f1c1..cd84f72 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -1,14 +1,16 @@
 #ifndef _ASM_X86_SEGMENT_H
 #define _ASM_X86_SEGMENT_H
 
+#include <linux/const.h>
+
 /* Constructor for a conventional segment GDT (or LDT) entry */
 /* This is a macro so it can be used in initializers */
 #define GDT_ENTRY(flags, base, limit)			\
-	((((base)  & 0xff000000ULL) << (56-24)) |	\
-	 (((flags) & 0x0000f0ffULL) << 40) |		\
-	 (((limit) & 0x000f0000ULL) << (48-16)) |	\
-	 (((base)  & 0x00ffffffULL) << 16) |		\
-	 (((limit) & 0x0000ffffULL)))
+	((((base)  & _AC(0xff000000,ULL)) << (56-24)) |	\
+	 (((flags) & _AC(0x0000f0ff,ULL)) << 40) |	\
+	 (((limit) & _AC(0x000f0000,ULL)) << (48-16)) |	\
+	 (((base)  & _AC(0x00ffffff,ULL)) << 16) |	\
+	 (((limit) & _AC(0x0000ffff,ULL))))
 
 /* Simple and small GDT entries for booting only */
 
diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 1f46951..73b11bc 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -17,12 +17,24 @@
 #endif
 #include <asm/thread_info.h>
 #include <asm/cpumask.h>
+#include <asm/cpufeature.h>
 
 extern int smp_num_siblings;
 extern unsigned int num_processors;
 
+static inline bool cpu_has_ht_siblings(void)
+{
+	bool has_siblings = false;
+#ifdef CONFIG_SMP
+	has_siblings = cpu_has_ht && smp_num_siblings > 1;
+#endif
+	return has_siblings;
+}
+
 DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
 DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
+/* cpus sharing the last level cache: */
+DECLARE_PER_CPU(cpumask_var_t, cpu_llc_shared_map);
 DECLARE_PER_CPU(u16, cpu_llc_id);
 DECLARE_PER_CPU(int, cpu_number);
 
@@ -36,8 +48,16 @@ static inline struct cpumask *cpu_core_mask(int cpu)
 	return per_cpu(cpu_core_map, cpu);
 }
 
+static inline struct cpumask *cpu_llc_shared_mask(int cpu)
+{
+	return per_cpu(cpu_llc_shared_map, cpu);
+}
+
 DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid);
 DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
+DECLARE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid);
+#endif
 
 /* Static state in head.S used to set up a CPU */
 extern unsigned long stack_start; /* Initial stack pointer address */
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 52b5c7e..d7e89c8 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -47,7 +47,7 @@ struct stacktrace_ops {
 };
 
 void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
-		unsigned long *stack,
+		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data);
 
 #ifdef CONFIG_X86_32
@@ -86,11 +86,11 @@ stack_frame(struct task_struct *task, struct pt_regs *regs)
 
 extern void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *stack, char *log_lvl);
+		   unsigned long *stack, unsigned long bp, char *log_lvl);
 
 extern void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, char *log_lvl);
+		   unsigned long *sp, unsigned long bp, char *log_lvl);
 
 extern unsigned int code_bytes;
 
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index 33ecc3e..12569e6 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -98,8 +98,6 @@ do {									\
  */
 #define HAVE_DISABLE_HLT
 #else
-#define __SAVE(reg, offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
-#define __RESTORE(reg, offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
 
 /* frame pointer must be last for get_wchan */
 #define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index f0b6e5d..1f2e61e 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -161,8 +161,14 @@ struct thread_info {
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-#define alloc_thread_info(tsk)						\
-	((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+#define alloc_thread_info_node(tsk, node)				\
+({									\
+	struct page *page = alloc_pages_node(node, THREAD_FLAGS,	\
+					     THREAD_ORDER);		\
+	struct thread_info *ret = page ? page_address(page) : NULL;	\
+									\
+	ret;								\
+})
 
 #ifdef CONFIG_X86_32
 
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 21899cc3..910a708 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -47,21 +47,6 @@
 
 #include <asm/mpspec.h>
 
-#ifdef CONFIG_X86_32
-
-/* Mappings between logical cpu number and node number */
-extern int cpu_to_node_map[];
-
-/* Returns the number of the node containing CPU 'cpu' */
-static inline int __cpu_to_node(int cpu)
-{
-	return cpu_to_node_map[cpu];
-}
-#define early_cpu_to_node __cpu_to_node
-#define cpu_to_node __cpu_to_node
-
-#else /* CONFIG_X86_64 */
-
 /* Mappings between logical cpu number and node number */
 DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map);
 
@@ -84,8 +69,6 @@ static inline int early_cpu_to_node(int cpu)
 
 #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */
 
-#endif /* CONFIG_X86_64 */
-
 /* Mappings between node number and cpus on that node. */
 extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 
@@ -155,7 +138,7 @@ extern unsigned long node_remap_size[];
 	.balance_interval	= 1,					\
 }
 
-#ifdef CONFIG_X86_64_ACPI_NUMA
+#ifdef CONFIG_X86_64
 extern int __node_distance(int, int);
 #define node_distance(a, b) __node_distance(a, b)
 #endif
diff --git a/arch/x86/include/asm/trampoline.h b/arch/x86/include/asm/trampoline.h
index f4500fb..feca311 100644
--- a/arch/x86/include/asm/trampoline.h
+++ b/arch/x86/include/asm/trampoline.h
@@ -3,25 +3,36 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_X86_TRAMPOLINE
+#include <linux/types.h>
+#include <asm/io.h>
+
 /*
- * Trampoline 80x86 program as an array.
+ * Trampoline 80x86 program as an array.  These are in the init rodata
+ * segment, but that's okay, because we only care about the relative
+ * addresses of the symbols.
  */
-extern const unsigned char trampoline_data [];
-extern const unsigned char trampoline_end  [];
-extern unsigned char *trampoline_base;
+extern const unsigned char x86_trampoline_start [];
+extern const unsigned char x86_trampoline_end   [];
+extern unsigned char *x86_trampoline_base;
 
 extern unsigned long init_rsp;
 extern unsigned long initial_code;
 extern unsigned long initial_gs;
 
-#define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
+extern void __init setup_trampolines(void);
+
+extern const unsigned char trampoline_data[];
+extern const unsigned char trampoline_status[];
+
+#define TRAMPOLINE_SYM(x)						\
+	((void *)(x86_trampoline_base +					\
+		  ((const unsigned char *)(x) - x86_trampoline_start)))
 
-extern unsigned long setup_trampoline(void);
-extern void __init reserve_trampoline_memory(void);
-#else
-static inline void reserve_trampoline_memory(void) {}
-#endif /* CONFIG_X86_TRAMPOLINE */
+/* Address of the SMP trampoline */
+static inline unsigned long trampoline_address(void)
+{
+	return virt_to_phys(TRAMPOLINE_SYM(trampoline_data));
+}
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/x86/include/asm/tsc.h b/arch/x86/include/asm/tsc.h
index 1ca132f..83e2efd 100644
--- a/arch/x86/include/asm/tsc.h
+++ b/arch/x86/include/asm/tsc.h
@@ -35,7 +35,7 @@ static inline cycles_t get_cycles(void)
 static __always_inline cycles_t vget_cycles(void)
 {
 	/*
-	 * We only do VDSOs on TSC capable CPUs, so this shouldnt
+	 * We only do VDSOs on TSC capable CPUs, so this shouldn't
 	 * access boot_cpu_data (which is not VDSO-safe):
 	 */
 #ifndef CONFIG_X86_TSC
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index df1da20..8810205 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -1,20 +1,12 @@
 #ifndef _ASM_X86_TYPES_H
 #define _ASM_X86_TYPES_H
 
-#define dma_addr_t	dma_addr_t
-
 #include <asm-generic/types.h>
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 typedef u64 dma64_addr_t;
-#if defined(CONFIG_X86_64) || defined(CONFIG_HIGHMEM64G)
-/* DMA addresses come in 32-bit and 64-bit flavours. */
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
 
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/unistd_32.h b/arch/x86/include/asm/unistd_32.h
index b766a5e..a755ef5 100644
--- a/arch/x86/include/asm/unistd_32.h
+++ b/arch/x86/include/asm/unistd_32.h
@@ -346,10 +346,14 @@
 #define __NR_fanotify_init	338
 #define __NR_fanotify_mark	339
 #define __NR_prlimit64		340
+#define __NR_name_to_handle_at	341
+#define __NR_open_by_handle_at  342
+#define __NR_clock_adjtime	343
+#define __NR_syncfs             344
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 341
+#define NR_syscalls 345
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/include/asm/unistd_64.h b/arch/x86/include/asm/unistd_64.h
index 363e9b8..160fa76 100644
--- a/arch/x86/include/asm/unistd_64.h
+++ b/arch/x86/include/asm/unistd_64.h
@@ -669,6 +669,14 @@ __SYSCALL(__NR_fanotify_init, sys_fanotify_init)
 __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
 #define __NR_prlimit64				302
 __SYSCALL(__NR_prlimit64, sys_prlimit64)
+#define __NR_name_to_handle_at			303
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at			304
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
+#define __NR_clock_adjtime			305
+__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
+#define __NR_syncfs                             306
+__SYSCALL(__NR_syncfs, sys_syncfs)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 64642ad..643ebf2 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -83,11 +83,13 @@ struct x86_init_paging {
  *				boot cpu
  * @tsc_pre_init:		platform function called before TSC init
  * @timer_init:			initialize the platform timer (default PIT/HPET)
+ * @wallclock_init:		init the wallclock device
  */
 struct x86_init_timers {
 	void (*setup_percpu_clockev)(void);
 	void (*tsc_pre_init)(void);
 	void (*timer_init)(void);
+	void (*wallclock_init)(void);
 };
 
 /**
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index a3c28ae..8508bfe 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -287,7 +287,7 @@ HYPERVISOR_fpu_taskswitch(int set)
 static inline int
 HYPERVISOR_sched_op(int cmd, void *arg)
 {
-	return _hypercall2(int, sched_op_new, cmd, arg);
+	return _hypercall2(int, sched_op, cmd, arg);
 }
 
 static inline long
@@ -422,10 +422,17 @@ HYPERVISOR_set_segment_base(int reg, unsigned long value)
 #endif
 
 static inline int
-HYPERVISOR_suspend(unsigned long srec)
+HYPERVISOR_suspend(unsigned long start_info_mfn)
 {
-	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
-			   SHUTDOWN_suspend, srec);
+	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
+
+	/*
+	 * For a PV guest the tools require that the start_info mfn be
+	 * present in rdx/edx when the hypercall is made. Per the
+	 * hypercall calling convention this is the third hypercall
+	 * argument, which is start_info_mfn here.
+	 */
+	return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
 }
 
 static inline int
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
index 1c10c88..5d4922a 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -86,7 +86,7 @@ DEFINE_GUEST_HANDLE(void);
  * The privilege level specifies which modes may enter a trap via a software
  * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
  * privilege levels as follows:
- *  Level == 0: Noone may enter
+ *  Level == 0: No one may enter
  *  Level == 1: Kernel may enter
  *  Level == 2: Kernel may enter
  *  Level == 3: Everyone may enter
diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
index f25bdf2..c61934f 100644
--- a/arch/x86/include/asm/xen/page.h
+++ b/arch/x86/include/asm/xen/page.h
@@ -29,8 +29,10 @@ typedef struct xpaddr {
 
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
 #define INVALID_P2M_ENTRY	(~0UL)
-#define FOREIGN_FRAME_BIT	(1UL<<31)
+#define FOREIGN_FRAME_BIT	(1UL<<(BITS_PER_LONG-1))
+#define IDENTITY_FRAME_BIT	(1UL<<(BITS_PER_LONG-2))
 #define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
+#define IDENTITY_FRAME(m)	((m) | IDENTITY_FRAME_BIT)
 
 /* Maximum amount of memory we can handle in a domain in pages */
 #define MAX_DOMAIN_PAGES						\
@@ -41,12 +43,18 @@ extern unsigned int   machine_to_phys_order;
 
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
+extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
+extern unsigned long set_phys_range_identity(unsigned long pfn_s,
+					     unsigned long pfn_e);
 
 extern int m2p_add_override(unsigned long mfn, struct page *page);
 extern int m2p_remove_override(struct page *page);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
+#ifdef CONFIG_XEN_DEBUG_FS
+extern int p2m_dump_show(struct seq_file *m, void *v);
+#endif
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
 {
 	unsigned long mfn;
@@ -57,7 +65,7 @@ static inline unsigned long pfn_to_mfn(unsigned long pfn)
 	mfn = get_phys_to_machine(pfn);
 
 	if (mfn != INVALID_P2M_ENTRY)
-		mfn &= ~FOREIGN_FRAME_BIT;
+		mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT);
 
 	return mfn;
 }
@@ -73,25 +81,44 @@ static inline int phys_to_machine_mapping_valid(unsigned long pfn)
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
 	unsigned long pfn;
+	int ret = 0;
 
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return mfn;
 
+	if (unlikely((mfn >> machine_to_phys_order) != 0)) {
+		pfn = ~0;
+		goto try_override;
+	}
 	pfn = 0;
 	/*
 	 * The array access can fail (e.g., device space beyond end of RAM).
 	 * In such cases it doesn't matter what we return (we return garbage),
 	 * but we must handle the fault without crashing!
 	 */
-	__get_user(pfn, &machine_to_phys_mapping[mfn]);
-
-	/*
-	 * If this appears to be a foreign mfn (because the pfn
-	 * doesn't map back to the mfn), then check the local override
-	 * table to see if there's a better pfn to use.
+	ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
+try_override:
+	/* ret might be < 0 if there are no entries in the m2p for mfn */
+	if (ret < 0)
+		pfn = ~0;
+	else if (get_phys_to_machine(pfn) != mfn)
+		/*
+		 * If this appears to be a foreign mfn (because the pfn
+		 * doesn't map back to the mfn), then check the local override
+		 * table to see if there's a better pfn to use.
+		 *
+		 * m2p_find_override_pfn returns ~0 if it doesn't find anything.
+		 */
+		pfn = m2p_find_override_pfn(mfn, ~0);
+
+	/* 
+	 * pfn is ~0 if there are no entries in the m2p for mfn or if the
+	 * entry doesn't map back to the mfn and m2p_override doesn't have a
+	 * valid entry for it.
 	 */
-	if (get_phys_to_machine(pfn) != mfn)
-		pfn = m2p_find_override_pfn(mfn, pfn);
+	if (pfn == ~0 &&
+			get_phys_to_machine(mfn) == IDENTITY_FRAME(mfn))
+		pfn = mfn;
 
 	return pfn;
 }
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h
index 2329b3e..aa86209 100644
--- a/arch/x86/include/asm/xen/pci.h
+++ b/arch/x86/include/asm/xen/pci.h
@@ -27,16 +27,16 @@ static inline void __init xen_setup_pirqs(void)
  * its own functions.
  */
 struct xen_pci_frontend_ops {
-	int (*enable_msi)(struct pci_dev *dev, int **vectors);
+	int (*enable_msi)(struct pci_dev *dev, int vectors[]);
 	void (*disable_msi)(struct pci_dev *dev);
-	int (*enable_msix)(struct pci_dev *dev, int **vectors, int nvec);
+	int (*enable_msix)(struct pci_dev *dev, int vectors[], int nvec);
 	void (*disable_msix)(struct pci_dev *dev);
 };
 
 extern struct xen_pci_frontend_ops *xen_pci_frontend;
 
 static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev,
-					      int **vectors)
+					      int vectors[])
 {
 	if (xen_pci_frontend && xen_pci_frontend->enable_msi)
 		return xen_pci_frontend->enable_msi(dev, vectors);
@@ -48,7 +48,7 @@ static inline void xen_pci_frontend_disable_msi(struct pci_dev *dev)
 			xen_pci_frontend->disable_msi(dev);
 }
 static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev,
-					       int **vectors, int nvec)
+					       int vectors[], int nvec)
 {
 	if (xen_pci_frontend && xen_pci_frontend->enable_msix)
 		return xen_pci_frontend->enable_msix(dev, vectors, nvec);
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 34244b2..7338ef2 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -41,13 +41,13 @@ obj-$(CONFIG_X86_32)	+= sys_i386_32.o i386_ksyms_32.o
 obj-$(CONFIG_X86_64)	+= sys_x86_64.o x8664_ksyms_64.o
 obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o
 obj-y			+= bootflag.o e820.o
-obj-y			+= pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
+obj-y			+= pci-dma.o quirks.o topology.o kdebugfs.o
 obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y			+= tsc.o io_delay.o rtc.o
 obj-y			+= pci-iommu_table.o
 obj-y			+= resource.o
 
-obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
+obj-y				+= trampoline.o trampoline_$(BITS).o
 obj-y				+= process.o
 obj-y				+= i387.o xsave.o
 obj-y				+= ptrace.o
@@ -55,10 +55,12 @@ obj-$(CONFIG_X86_32)		+= tls.o
 obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
+obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-y				+= cpu/
 obj-y				+= acpi/
 obj-y				+= reboot.o
+obj-$(CONFIG_X86_32)		+= reboot_32.o
 obj-$(CONFIG_MCA)		+= mca_32.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
@@ -66,10 +68,9 @@ obj-$(CONFIG_PCI)		+= early-quirks.o
 apm-y				:= apm_32.o
 obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_SMP)		+= smpboot.o tsc_sync.o
+obj-$(CONFIG_SMP)		+= smpboot.o
+obj-$(CONFIG_SMP)		+= tsc_sync.o
 obj-$(CONFIG_SMP)		+= setup_percpu.o
-obj-$(CONFIG_X86_64_SMP)	+= tsc_sync.o
-obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline_$(BITS).o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-y				+= apic/
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
@@ -109,6 +110,7 @@ obj-$(CONFIG_MICROCODE)			+= microcode.o
 obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 
 obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
+obj-$(CONFIG_OF)			+= devicetree.o
 
 ###
 # 64 bit specific files
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 3e6e2d6..9a966c5 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -595,14 +595,8 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 	nid = acpi_get_node(handle);
 	if (nid == -1 || !node_online(nid))
 		return;
-#ifdef CONFIG_X86_64
-	apicid_to_node[physid] = nid;
+	set_apicid_to_node(physid, nid);
 	numa_set_node(cpu, nid);
-#else /* CONFIG_X86_32 */
-	apicid_2_node[physid] = nid;
-	cpu_to_node_map[cpu] = nid;
-#endif
-
 #endif
 }
 
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
index 28595d6..ead21b6 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.S
+++ b/arch/x86/kernel/acpi/realmode/wakeup.S
@@ -6,11 +6,17 @@
 #include <asm/page_types.h>
 #include <asm/pgtable_types.h>
 #include <asm/processor-flags.h>
+#include "wakeup.h"
 
 	.code16
-	.section ".header", "a"
+	.section ".jump", "ax"
+	.globl	_start
+_start:
+	cli
+	jmp	wakeup_code
 
 /* This should match the structure in wakeup.h */
+		.section ".header", "a"
 		.globl	wakeup_header
 wakeup_header:
 video_mode:	.short	0	/* Video mode number */
@@ -30,14 +36,11 @@ wakeup_jmp:	.byte	0xea	/* ljmpw */
 wakeup_jmp_off:	.word	3f
 wakeup_jmp_seg:	.word	0
 wakeup_gdt:	.quad	0, 0, 0
-signature:	.long	0x51ee1111
+signature:	.long	WAKEUP_HEADER_SIGNATURE
 
 	.text
-	.globl	_start
 	.code16
 wakeup_code:
-_start:
-	cli
 	cld
 
 	/* Apparently some dimwit BIOS programmers don't know how to
@@ -77,12 +80,12 @@ _start:
 
 	/* Check header signature... */
 	movl	signature, %eax
-	cmpl	$0x51ee1111, %eax
+	cmpl	$WAKEUP_HEADER_SIGNATURE, %eax
 	jne	bogus_real_magic
 
 	/* Check we really have everything... */
 	movl	end_signature, %eax
-	cmpl	$0x65a22c82, %eax
+	cmpl	$WAKEUP_END_SIGNATURE, %eax
 	jne	bogus_real_magic
 
 	/* Call the C code */
@@ -147,3 +150,7 @@ wakeup_heap:
 wakeup_stack:
 	.space	2048
 wakeup_stack_end:
+
+	.section ".signature","a"
+end_signature:
+	.long	WAKEUP_END_SIGNATURE
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h
index 69d38d0..e1828c0 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.h
+++ b/arch/x86/kernel/acpi/realmode/wakeup.h
@@ -35,7 +35,8 @@ struct wakeup_header {
 extern struct wakeup_header wakeup_header;
 #endif
 
-#define HEADER_OFFSET 0x3f00
-#define WAKEUP_SIZE   0x4000
+#define WAKEUP_HEADER_OFFSET	8
+#define WAKEUP_HEADER_SIGNATURE 0x51ee1111
+#define WAKEUP_END_SIGNATURE	0x65a22c82
 
 #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
index 060fff8..d4f8010 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.lds.S
+++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S
@@ -13,9 +13,19 @@ ENTRY(_start)
 SECTIONS
 {
 	. = 0;
+	.jump	: {
+		*(.jump)
+	} = 0x90909090
+
+	. = WAKEUP_HEADER_OFFSET;
+	.header : {
+		*(.header)
+	}
+
+	. = ALIGN(16);
 	.text : {
 		 *(.text*)
-	}
+	} = 0x90909090
 
 	. = ALIGN(16);
 	.rodata : {
@@ -33,11 +43,6 @@ SECTIONS
 		 *(.data*)
 	}
 
-	.signature : {
-		end_signature = .;
-		LONG(0x65a22c82)
-	}
-
 	. = ALIGN(16);
 	.bss :	{
 		__bss_start = .;
@@ -45,20 +50,13 @@ SECTIONS
 		__bss_end = .;
 	}
 
-	. = HEADER_OFFSET;
-	.header : {
-		*(.header)
+	.signature : {
+		*(.signature)
 	}
 
-	. = ALIGN(16);
 	_end = .;
 
 	/DISCARD/ : {
 		*(.note*)
 	}
-
-	/*
-	 * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
-	 */
-	. = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
 }
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 68d1537..4572c58 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -18,12 +18,8 @@
 #include "realmode/wakeup.h"
 #include "sleep.h"
 
-unsigned long acpi_wakeup_address;
 unsigned long acpi_realmode_flags;
 
-/* address in low memory of the wakeup routine. */
-static unsigned long acpi_realmode;
-
 #if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
 static char temp_stack[4096];
 #endif
@@ -33,22 +29,17 @@ static char temp_stack[4096];
  *
  * Create an identity mapped page table and copy the wakeup routine to
  * low memory.
- *
- * Note that this is too late to change acpi_wakeup_address.
  */
 int acpi_save_state_mem(void)
 {
 	struct wakeup_header *header;
+	/* address in low memory of the wakeup routine. */
+	char *acpi_realmode;
 
-	if (!acpi_realmode) {
-		printk(KERN_ERR "Could not allocate memory during boot, "
-		       "S3 disabled\n");
-		return -ENOMEM;
-	}
-	memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
+	acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code);
 
-	header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
-	if (header->signature != 0x51ee1111) {
+	header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET);
+	if (header->signature != WAKEUP_HEADER_SIGNATURE) {
 		printk(KERN_ERR "wakeup header does not match\n");
 		return -EINVAL;
 	}
@@ -68,9 +59,7 @@ int acpi_save_state_mem(void)
 	/* GDT[0]: GDT self-pointer */
 	header->wakeup_gdt[0] =
 		(u64)(sizeof(header->wakeup_gdt) - 1) +
-		((u64)(acpi_wakeup_address +
-			((char *)&header->wakeup_gdt - (char *)acpi_realmode))
-				<< 16);
+		((u64)__pa(&header->wakeup_gdt) << 16);
 	/* GDT[1]: big real mode-like code segment */
 	header->wakeup_gdt[1] =
 		GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
@@ -96,7 +85,7 @@ int acpi_save_state_mem(void)
 	header->pmode_cr3 = (u32)__pa(&initial_page_table);
 	saved_magic = 0x12345678;
 #else /* CONFIG_64BIT */
-	header->trampoline_segment = setup_trampoline() >> 4;
+	header->trampoline_segment = trampoline_address() >> 4;
 #ifdef CONFIG_SMP
 	stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
 	early_gdt_descr.address =
@@ -117,46 +106,6 @@ void acpi_restore_state_mem(void)
 {
 }
 
-
-/**
- * acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation
- *
- * We allocate a page from the first 1MB of memory for the wakeup
- * routine for when we come back from a sleep state. The
- * runtime allocator allows specification of <16MB pages, but not
- * <1MB pages.
- */
-void __init acpi_reserve_wakeup_memory(void)
-{
-	phys_addr_t mem;
-
-	if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
-		printk(KERN_ERR
-		       "ACPI: Wakeup code way too big, S3 disabled.\n");
-		return;
-	}
-
-	mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
-
-	if (mem == MEMBLOCK_ERROR) {
-		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
-		return;
-	}
-	acpi_realmode = (unsigned long) phys_to_virt(mem);
-	acpi_wakeup_address = mem;
-	memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
-}
-
-int __init acpi_configure_wakeup_memory(void)
-{
-	if (acpi_realmode)
-		set_memory_x(acpi_realmode, WAKEUP_SIZE >> PAGE_SHIFT);
-
-	return 0;
-}
-arch_initcall(acpi_configure_wakeup_memory);
-
-
 static int __init acpi_sleep_setup(char *str)
 {
 	while ((str != NULL) && (*str != '\0')) {
diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h
index adbcbaa..86ba1c8 100644
--- a/arch/x86/kernel/acpi/sleep.h
+++ b/arch/x86/kernel/acpi/sleep.h
@@ -4,13 +4,10 @@
 
 #include <asm/trampoline.h>
 
-extern char wakeup_code_start, wakeup_code_end;
-
 extern unsigned long saved_video_mode;
 extern long saved_magic;
 
 extern int wakeup_pmode_return;
-extern char swsusp_pg_dir[PAGE_SIZE];
 
 extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 extern void wakeup_long64(void);
diff --git a/arch/x86/kernel/acpi/wakeup_rm.S b/arch/x86/kernel/acpi/wakeup_rm.S
index 6ff3b57..63b8ab5 100644
--- a/arch/x86/kernel/acpi/wakeup_rm.S
+++ b/arch/x86/kernel/acpi/wakeup_rm.S
@@ -2,9 +2,11 @@
  * Wrapper script for the realmode binary as a transport object
  * before copying to low memory.
  */
-	.section ".rodata","a"
-	.globl	wakeup_code_start, wakeup_code_end
-wakeup_code_start:
+#include <asm/page_types.h>
+
+	.section ".x86_trampoline","a"
+	.balign PAGE_SIZE
+	.globl	acpi_wakeup_code
+acpi_wakeup_code:
 	.incbin	"arch/x86/kernel/acpi/realmode/wakeup.bin"
-wakeup_code_end:
-	.size	wakeup_code_start, .-wakeup_code_start
+	.size	acpi_wakeup_code, .-acpi_wakeup_code
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 7038b95..4a23467 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -199,7 +199,7 @@ void *text_poke_early(void *addr, const void *opcode, size_t len);
 
 /* Replace instructions with better alternatives for this CPU type.
    This runs before SMP is initialized to avoid SMP problems with
-   self modifying code. This implies that assymetric systems where
+   self modifying code. This implies that asymmetric systems where
    APs have less capabilities than the boot processor are not handled.
    Tough. Make sure you disable such features by hand. */
 
@@ -620,7 +620,12 @@ static int __kprobes stop_machine_text_poke(void *data)
 		flush_icache_range((unsigned long)p->addr,
 				   (unsigned long)p->addr + p->len);
 	}
-
+	/*
+	 * Intel Archiecture Software Developer's Manual section 7.1.3 specifies
+	 * that a core serializing instruction such as "cpuid" should be
+	 * executed on _each_ core before the new instruction is made visible.
+	 */
+	sync_core();
 	return 0;
 }
 
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 0a99f71..6801959 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -12,14 +12,19 @@
 
 static u32 *flush_words;
 
-struct pci_device_id amd_nb_misc_ids[] = {
+const struct pci_device_id amd_nb_misc_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
 	{}
 };
 EXPORT_SYMBOL(amd_nb_misc_ids);
 
+static struct pci_device_id amd_nb_link_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_LINK) },
+	{}
+};
+
 const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = {
 	{ 0x00, 0x18, 0x20 },
 	{ 0xff, 0x00, 0x20 },
@@ -31,7 +36,7 @@ struct amd_northbridge_info amd_northbridges;
 EXPORT_SYMBOL(amd_northbridges);
 
 static struct pci_dev *next_northbridge(struct pci_dev *dev,
-					struct pci_device_id *ids)
+					const struct pci_device_id *ids)
 {
 	do {
 		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
@@ -43,9 +48,9 @@ static struct pci_dev *next_northbridge(struct pci_dev *dev,
 
 int amd_cache_northbridges(void)
 {
-	int i = 0;
+	u16 i = 0;
 	struct amd_northbridge *nb;
-	struct pci_dev *misc;
+	struct pci_dev *misc, *link;
 
 	if (amd_nb_num())
 		return 0;
@@ -64,10 +69,12 @@ int amd_cache_northbridges(void)
 	amd_northbridges.nb = nb;
 	amd_northbridges.num = i;
 
-	misc = NULL;
+	link = misc = NULL;
 	for (i = 0; i != amd_nb_num(); i++) {
 		node_to_amd_nb(i)->misc = misc =
 			next_northbridge(misc, amd_nb_misc_ids);
+		node_to_amd_nb(i)->link = link =
+			next_northbridge(link, amd_nb_link_ids);
         }
 
 	/* some CPU families (e.g. family 0x11) do not support GART */
@@ -85,26 +92,95 @@ int amd_cache_northbridges(void)
 	     boot_cpu_data.x86_mask >= 0x1))
 		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
 
+	if (boot_cpu_data.x86 == 0x15)
+		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
+
+	/* L3 cache partitioning is supported on family 0x15 */
+	if (boot_cpu_data.x86 == 0x15)
+		amd_northbridges.flags |= AMD_NB_L3_PARTITIONING;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(amd_cache_northbridges);
 
-/* Ignores subdevice/subvendor but as far as I can figure out
-   they're useless anyways */
-int __init early_is_amd_nb(u32 device)
+/*
+ * Ignores subdevice/subvendor but as far as I can figure out
+ * they're useless anyways
+ */
+bool __init early_is_amd_nb(u32 device)
 {
-	struct pci_device_id *id;
+	const struct pci_device_id *id;
 	u32 vendor = device & 0xffff;
+
 	device >>= 16;
 	for (id = amd_nb_misc_ids; id->vendor; id++)
 		if (vendor == id->vendor && device == id->device)
-			return 1;
+			return true;
+	return false;
+}
+
+int amd_get_subcaches(int cpu)
+{
+	struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;
+	unsigned int mask;
+	int cuid = 0;
+
+	if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		return 0;
+
+	pci_read_config_dword(link, 0x1d4, &mask);
+
+#ifdef CONFIG_SMP
+	cuid = cpu_data(cpu).compute_unit_id;
+#endif
+	return (mask >> (4 * cuid)) & 0xf;
+}
+
+int amd_set_subcaches(int cpu, int mask)
+{
+	static unsigned int reset, ban;
+	struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu));
+	unsigned int reg;
+	int cuid = 0;
+
+	if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING) || mask > 0xf)
+		return -EINVAL;
+
+	/* if necessary, collect reset state of L3 partitioning and BAN mode */
+	if (reset == 0) {
+		pci_read_config_dword(nb->link, 0x1d4, &reset);
+		pci_read_config_dword(nb->misc, 0x1b8, &ban);
+		ban &= 0x180000;
+	}
+
+	/* deactivate BAN mode if any subcaches are to be disabled */
+	if (mask != 0xf) {
+		pci_read_config_dword(nb->misc, 0x1b8, &reg);
+		pci_write_config_dword(nb->misc, 0x1b8, reg & ~0x180000);
+	}
+
+#ifdef CONFIG_SMP
+	cuid = cpu_data(cpu).compute_unit_id;
+#endif
+	mask <<= 4 * cuid;
+	mask |= (0xf ^ (1 << cuid)) << 26;
+
+	pci_write_config_dword(nb->link, 0x1d4, mask);
+
+	/* reset BAN mode if L3 partitioning returned to reset state */
+	pci_read_config_dword(nb->link, 0x1d4, &reg);
+	if (reg == reset) {
+		pci_read_config_dword(nb->misc, 0x1b8, &reg);
+		reg &= ~0x180000;
+		pci_write_config_dword(nb->misc, 0x1b8, reg | ban);
+	}
+
 	return 0;
 }
 
-int amd_cache_gart(void)
+static int amd_cache_gart(void)
 {
-       int i;
+	u16 i;
 
        if (!amd_nb_has_feature(AMD_NB_GART))
                return 0;
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index 51d4e16..1293c70 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -508,64 +508,12 @@ static int apbt_next_event(unsigned long delta,
 	return 0;
 }
 
-/*
- * APB timer clock is not in sync with pclk on Langwell, which translates to
- * unreliable read value caused by sampling error. the error does not add up
- * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
- * would go backwards. the following code is trying to prevent time traveling
- * backwards. little bit paranoid.
- */
 static cycle_t apbt_read_clocksource(struct clocksource *cs)
 {
-	unsigned long t0, t1, t2;
-	static unsigned long last_read;
-
-bad_count:
-	t1 = apbt_readl(phy_cs_timer_id,
-			APBTMR_N_CURRENT_VALUE);
-	t2 = apbt_readl(phy_cs_timer_id,
-			APBTMR_N_CURRENT_VALUE);
-	if (unlikely(t1 < t2)) {
-		pr_debug("APBT: read current count error %lx:%lx:%lx\n",
-			 t1, t2, t2 - t1);
-		goto bad_count;
-	}
-	/*
-	 * check against cached last read, makes sure time does not go back.
-	 * it could be a normal rollover but we will do tripple check anyway
-	 */
-	if (unlikely(t2 > last_read)) {
-		/* check if we have a normal rollover */
-		unsigned long raw_intr_status =
-			apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
-		/*
-		 * cs timer interrupt is masked but raw intr bit is set if
-		 * rollover occurs. then we read EOI reg to clear it.
-		 */
-		if (raw_intr_status & (1 << phy_cs_timer_id)) {
-			apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
-			goto out;
-		}
-		pr_debug("APB CS going back %lx:%lx:%lx ",
-			 t2, last_read, t2 - last_read);
-bad_count_x3:
-		pr_debug("triple check enforced\n");
-		t0 = apbt_readl(phy_cs_timer_id,
-				APBTMR_N_CURRENT_VALUE);
-		udelay(1);
-		t1 = apbt_readl(phy_cs_timer_id,
-				APBTMR_N_CURRENT_VALUE);
-		udelay(1);
-		t2 = apbt_readl(phy_cs_timer_id,
-				APBTMR_N_CURRENT_VALUE);
-		if ((t2 > t1) || (t1 > t0)) {
-			printk(KERN_ERR "Error: APB CS tripple check failed\n");
-			goto bad_count_x3;
-		}
-	}
-out:
-	last_read = t2;
-	return (cycle_t)~t2;
+	unsigned long current_count;
+
+	current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
+	return (cycle_t)~current_count;
 }
 
 static int apbt_clocksource_register(void)
diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c
index 5955a78..86d1ad4 100644
--- a/arch/x86/kernel/aperture_64.c
+++ b/arch/x86/kernel/aperture_64.c
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
@@ -57,7 +57,7 @@ static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
 static u32 __init allocate_aperture(void)
 {
 	u32 aper_size;
-	void *p;
+	unsigned long addr;
 
 	/* aper_size should <= 1G */
 	if (fallback_aper_order > 5)
@@ -73,7 +73,7 @@ static u32 __init allocate_aperture(void)
 	/*
 	 * using 512M as goal, in case kexec will load kernel_big
 	 * that will do the on position decompress, and  could overlap with
-	 * that positon with gart that is used.
+	 * that position with gart that is used.
 	 * sequende:
 	 * kernel_small
 	 * ==> kexec (with kdump trigger path or previous doesn't shutdown gart)
@@ -83,27 +83,26 @@ static u32 __init allocate_aperture(void)
 	 * so don't use 512M below as gart iommu, leave the space for kernel
 	 * code for safe
 	 */
-	p = __alloc_bootmem_nopanic(aper_size, aper_size, 512ULL<<20);
+	addr = memblock_find_in_range(0, 1ULL<<32, aper_size, 512ULL<<20);
+	if (addr == MEMBLOCK_ERROR || addr + aper_size > 0xffffffff) {
+		printk(KERN_ERR
+			"Cannot allocate aperture memory hole (%lx,%uK)\n",
+				addr, aper_size>>10);
+		return 0;
+	}
+	memblock_x86_reserve_range(addr, addr + aper_size, "aperture64");
 	/*
 	 * Kmemleak should not scan this block as it may not be mapped via the
 	 * kernel direct mapping.
 	 */
-	kmemleak_ignore(p);
-	if (!p || __pa(p)+aper_size > 0xffffffff) {
-		printk(KERN_ERR
-			"Cannot allocate aperture memory hole (%p,%uK)\n",
-				p, aper_size>>10);
-		if (p)
-			free_bootmem(__pa(p), aper_size);
-		return 0;
-	}
+	kmemleak_ignore(phys_to_virt(addr));
 	printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n",
-			aper_size >> 10, __pa(p));
-	insert_aperture_resource((u32)__pa(p), aper_size);
-	register_nosave_region((u32)__pa(p) >> PAGE_SHIFT,
-				(u32)__pa(p+aper_size) >> PAGE_SHIFT);
+			aper_size >> 10, addr);
+	insert_aperture_resource((u32)addr, aper_size);
+	register_nosave_region(addr >> PAGE_SHIFT,
+			       (addr+aper_size) >> PAGE_SHIFT);
 
-	return (u32)__pa(p);
+	return (u32)addr;
 }
 
 
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 76b96d7..966673f 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -43,6 +43,7 @@
 #include <asm/i8259.h>
 #include <asm/proto.h>
 #include <asm/apic.h>
+#include <asm/io_apic.h>
 #include <asm/desc.h>
 #include <asm/hpet.h>
 #include <asm/idle.h>
@@ -78,12 +79,21 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_apicid);
 EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
 
 #ifdef CONFIG_X86_32
+
+/*
+ * On x86_32, the mapping between cpu and logical apicid may vary
+ * depending on apic in use.  The following early percpu variable is
+ * used for the mapping.  This is where the behaviors of x86_64 and 32
+ * actually diverge.  Let's keep it ugly for now.
+ */
+DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID);
+
 /*
  * Knob to control our willingness to enable the local APIC.
  *
  * +1=force-enable
  */
-static int force_enable_local_apic;
+static int force_enable_local_apic __initdata;
 /*
  * APIC command line parameters
  */
@@ -153,7 +163,7 @@ early_param("nox2apic", setup_nox2apic);
 unsigned long mp_lapic_addr;
 int disable_apic;
 /* Disable local APIC timer from the kernel commandline or via dmi quirk */
-static int disable_apic_timer __cpuinitdata;
+static int disable_apic_timer __initdata;
 /* Local APIC timer works in C2 */
 int local_apic_timer_c2_ok;
 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
@@ -177,29 +187,8 @@ static struct resource lapic_resource = {
 
 static unsigned int calibration_result;
 
-static int lapic_next_event(unsigned long delta,
-			    struct clock_event_device *evt);
-static void lapic_timer_setup(enum clock_event_mode mode,
-			      struct clock_event_device *evt);
-static void lapic_timer_broadcast(const struct cpumask *mask);
 static void apic_pm_activate(void);
 
-/*
- * The local apic timer can be used for any function which is CPU local.
- */
-static struct clock_event_device lapic_clockevent = {
-	.name		= "lapic",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
-			| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
-	.shift		= 32,
-	.set_mode	= lapic_timer_setup,
-	.set_next_event	= lapic_next_event,
-	.broadcast	= lapic_timer_broadcast,
-	.rating		= 100,
-	.irq		= -1,
-};
-static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
-
 static unsigned long apic_phys;
 
 /*
@@ -238,7 +227,7 @@ static int modern_apic(void)
  * right after this call apic become NOOP driven
  * so apic->write/read doesn't do anything
  */
-void apic_disable(void)
+static void __init apic_disable(void)
 {
 	pr_info("APIC: switched to apic NOOP\n");
 	apic = &apic_noop;
@@ -282,23 +271,6 @@ u64 native_apic_icr_read(void)
 	return icr1 | ((u64)icr2 << 32);
 }
 
-/**
- * enable_NMI_through_LVT0 - enable NMI through local vector table 0
- */
-void __cpuinit enable_NMI_through_LVT0(void)
-{
-	unsigned int v;
-
-	/* unmask and set to NMI */
-	v = APIC_DM_NMI;
-
-	/* Level triggered for 82489DX (32bit mode) */
-	if (!lapic_is_integrated())
-		v |= APIC_LVT_LEVEL_TRIGGER;
-
-	apic_write(APIC_LVT0, v);
-}
-
 #ifdef CONFIG_X86_32
 /**
  * get_physical_broadcast - Get number of physical broadcast IDs
@@ -508,6 +480,23 @@ static void lapic_timer_broadcast(const struct cpumask *mask)
 #endif
 }
 
+
+/*
+ * The local apic timer can be used for any function which is CPU local.
+ */
+static struct clock_event_device lapic_clockevent = {
+	.name		= "lapic",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
+			| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
+	.shift		= 32,
+	.set_mode	= lapic_timer_setup,
+	.set_next_event	= lapic_next_event,
+	.broadcast	= lapic_timer_broadcast,
+	.rating		= 100,
+	.irq		= -1,
+};
+static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+
 /*
  * Setup the local APIC timer for this CPU. Copy the initialized values
  * of the boot CPU and register the clock event in the framework.
@@ -1209,7 +1198,7 @@ void __cpuinit setup_local_APIC(void)
 		rdtscll(tsc);
 
 	if (disable_apic) {
-		arch_disable_smp_support();
+		disable_ioapic_support();
 		return;
 	}
 
@@ -1237,6 +1226,19 @@ void __cpuinit setup_local_APIC(void)
 	 */
 	apic->init_apic_ldr();
 
+#ifdef CONFIG_X86_32
+	/*
+	 * APIC LDR is initialized.  If logical_apicid mapping was
+	 * initialized during get_smp_config(), make sure it matches the
+	 * actual value.
+	 */
+	i = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+	WARN_ON(i != BAD_APICID && i != logical_smp_processor_id());
+	/* always use the value from LDR */
+	early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+		logical_smp_processor_id();
+#endif
+
 	/*
 	 * Set Task Priority to 'accept all'. We never change this
 	 * later on.
@@ -1448,7 +1450,7 @@ int __init enable_IR(void)
 void __init enable_IR_x2apic(void)
 {
 	unsigned long flags;
-	struct IO_APIC_route_entry **ioapic_entries = NULL;
+	struct IO_APIC_route_entry **ioapic_entries;
 	int ret, x2apic_enabled = 0;
 	int dmar_table_init_ret;
 
@@ -1537,7 +1539,7 @@ static int __init detect_init_APIC(void)
 }
 #else
 
-static int apic_verify(void)
+static int __init apic_verify(void)
 {
 	u32 features, h, l;
 
@@ -1562,7 +1564,7 @@ static int apic_verify(void)
 	return 0;
 }
 
-int apic_force_enable(void)
+int __init apic_force_enable(unsigned long addr)
 {
 	u32 h, l;
 
@@ -1578,7 +1580,7 @@ int apic_force_enable(void)
 	if (!(l & MSR_IA32_APICBASE_ENABLE)) {
 		pr_info("Local APIC disabled by BIOS -- reenabling.\n");
 		l &= ~MSR_IA32_APICBASE_BASE;
-		l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+		l |= MSR_IA32_APICBASE_ENABLE | addr;
 		wrmsr(MSR_IA32_APICBASE, l, h);
 		enabled_via_apicbase = 1;
 	}
@@ -1619,7 +1621,7 @@ static int __init detect_init_APIC(void)
 				"you can enable it with \"lapic\"\n");
 			return -1;
 		}
-		if (apic_force_enable())
+		if (apic_force_enable(APIC_DEFAULT_PHYS_BASE))
 			return -1;
 	} else {
 		if (apic_verify())
@@ -1930,17 +1932,6 @@ void __cpuinit generic_processor_info(int apicid, int version)
 {
 	int cpu;
 
-	/*
-	 * Validate version
-	 */
-	if (version == 0x0) {
-		pr_warning("BIOS bug, APIC version is 0 for CPU#%d! "
-			   "fixing up to 0x10. (tell your hw vendor)\n",
-				version);
-		version = 0x10;
-	}
-	apic_version[apicid] = version;
-
 	if (num_processors >= nr_cpu_ids) {
 		int max = nr_cpu_ids;
 		int thiscpu = max + disabled_cpus;
@@ -1954,22 +1945,34 @@ void __cpuinit generic_processor_info(int apicid, int version)
 	}
 
 	num_processors++;
-	cpu = cpumask_next_zero(-1, cpu_present_mask);
-
-	if (version != apic_version[boot_cpu_physical_apicid])
-		WARN_ONCE(1,
-			"ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n",
-			apic_version[boot_cpu_physical_apicid], cpu, version);
-
-	physid_set(apicid, phys_cpu_present_map);
 	if (apicid == boot_cpu_physical_apicid) {
 		/*
 		 * x86_bios_cpu_apicid is required to have processors listed
 		 * in same order as logical cpu numbers. Hence the first
 		 * entry is BSP, and so on.
+		 * boot_cpu_init() already hold bit 0 in cpu_present_mask
+		 * for BSP.
 		 */
 		cpu = 0;
+	} else
+		cpu = cpumask_next_zero(-1, cpu_present_mask);
+
+	/*
+	 * Validate version
+	 */
+	if (version == 0x0) {
+		pr_warning("BIOS bug: APIC version is 0 for CPU %d/0x%x, fixing up to 0x10\n",
+			   cpu, apicid);
+		version = 0x10;
 	}
+	apic_version[apicid] = version;
+
+	if (version != apic_version[boot_cpu_physical_apicid]) {
+		pr_warning("BIOS bug: APIC version mismatch, boot CPU: %x, CPU %d: version %x\n",
+			apic_version[boot_cpu_physical_apicid], cpu, version);
+	}
+
+	physid_set(apicid, phys_cpu_present_map);
 	if (apicid > max_physical_apicid)
 		max_physical_apicid = apicid;
 
@@ -1977,7 +1980,10 @@ void __cpuinit generic_processor_info(int apicid, int version)
 	early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
 	early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
 #endif
-
+#ifdef CONFIG_X86_32
+	early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+		apic->x86_32_early_logical_apicid(cpu);
+#endif
 	set_cpu_possible(cpu, true);
 	set_cpu_present(cpu, true);
 }
@@ -1998,10 +2004,14 @@ void default_init_apic_ldr(void)
 }
 
 #ifdef CONFIG_X86_32
-int default_apicid_to_node(int logical_apicid)
+int default_x86_32_numa_cpu_node(int cpu)
 {
-#ifdef CONFIG_SMP
-	return apicid_2_node[hard_smp_processor_id()];
+#ifdef CONFIG_NUMA
+	int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
+
+	if (apicid != BAD_APICID)
+		return __apicid_to_node[apicid];
+	return NUMA_NO_NODE;
 #else
 	return 0;
 #endif
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 09d3b17..5652d31 100644
--- a/arch/x86/kernel/apic/apic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -185,8 +185,6 @@ struct apic apic_flat =  {
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
@@ -337,8 +335,6 @@ struct apic apic_physflat =  {
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
index e31b9ff..f1baa2d 100644
--- a/arch/x86/kernel/apic/apic_noop.c
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -54,11 +54,6 @@ static u64 noop_apic_icr_read(void)
 	return 0;
 }
 
-static int noop_cpu_to_logical_apicid(int cpu)
-{
-	return 0;
-}
-
 static int noop_phys_pkg_id(int cpuid_apic, int index_msb)
 {
 	return 0;
@@ -113,12 +108,6 @@ static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask)
 	cpumask_set_cpu(cpu, retmask);
 }
 
-int noop_apicid_to_node(int logical_apicid)
-{
-	/* we're always on node 0 */
-	return 0;
-}
-
 static u32 noop_apic_read(u32 reg)
 {
 	WARN_ON_ONCE((cpu_has_apic && !disable_apic));
@@ -130,6 +119,14 @@ static void noop_apic_write(u32 reg, u32 v)
 	WARN_ON_ONCE(cpu_has_apic && !disable_apic);
 }
 
+#ifdef CONFIG_X86_32
+static int noop_x86_32_numa_cpu_node(int cpu)
+{
+	/* we're always on node 0 */
+	return 0;
+}
+#endif
+
 struct apic apic_noop = {
 	.name				= "noop",
 	.probe				= noop_probe,
@@ -153,9 +150,7 @@ struct apic apic_noop = {
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= noop_apicid_to_node,
 
-	.cpu_to_logical_apicid		= noop_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 
@@ -197,4 +192,9 @@ struct apic apic_noop = {
 	.icr_write			= noop_apic_icr_write,
 	.wait_icr_idle			= noop_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= noop_safe_apic_wait_icr_idle,
+
+#ifdef CONFIG_X86_32
+	.x86_32_early_logical_apicid	= noop_x86_32_early_logical_apicid,
+	.x86_32_numa_cpu_node		= noop_x86_32_numa_cpu_node,
+#endif
 };
diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index cb804c5..541a2e4 100644
--- a/arch/x86/kernel/apic/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -45,6 +45,12 @@ static unsigned long bigsmp_check_apicid_present(int bit)
 	return 1;
 }
 
+static int bigsmp_early_logical_apicid(int cpu)
+{
+	/* on bigsmp, logical apicid is the same as physical */
+	return early_per_cpu(x86_cpu_to_apicid, cpu);
+}
+
 static inline unsigned long calculate_ldr(int cpu)
 {
 	unsigned long val, id;
@@ -80,11 +86,6 @@ static void bigsmp_setup_apic_routing(void)
 		nr_ioapics);
 }
 
-static int bigsmp_apicid_to_node(int logical_apicid)
-{
-	return apicid_2_node[hard_smp_processor_id()];
-}
-
 static int bigsmp_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids)
@@ -93,14 +94,6 @@ static int bigsmp_cpu_present_to_apicid(int mps_cpu)
 	return BAD_APICID;
 }
 
-/* Mapping from cpu number to logical apicid */
-static inline int bigsmp_cpu_to_logical_apicid(int cpu)
-{
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_physical_id(cpu);
-}
-
 static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
 {
 	/* For clustered we don't have a good way to do this yet - hack */
@@ -115,7 +108,11 @@ static int bigsmp_check_phys_apicid_present(int phys_apicid)
 /* As we are using single CPU as destination, pick only one CPU here */
 static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask)
 {
-	return bigsmp_cpu_to_logical_apicid(cpumask_first(cpumask));
+	int cpu = cpumask_first(cpumask);
+
+	if (cpu < nr_cpu_ids)
+		return cpu_physical_id(cpu);
+	return BAD_APICID;
 }
 
 static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
@@ -129,9 +126,9 @@ static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
 	 */
 	for_each_cpu_and(cpu, cpumask, andmask) {
 		if (cpumask_test_cpu(cpu, cpu_online_mask))
-			break;
+			return cpu_physical_id(cpu);
 	}
-	return bigsmp_cpu_to_logical_apicid(cpu);
+	return BAD_APICID;
 }
 
 static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
@@ -219,8 +216,6 @@ struct apic apic_bigsmp = {
 	.ioapic_phys_id_map		= bigsmp_ioapic_phys_id_map,
 	.setup_apic_routing		= bigsmp_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= bigsmp_apicid_to_node,
-	.cpu_to_logical_apicid		= bigsmp_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= bigsmp_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 	.setup_portio_remap		= NULL,
@@ -256,4 +251,7 @@ struct apic apic_bigsmp = {
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= bigsmp_early_logical_apicid,
+	.x86_32_numa_cpu_node		= default_x86_32_numa_cpu_node,
 };
diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 8593582..3e9de48 100644
--- a/arch/x86/kernel/apic/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -460,6 +460,12 @@ static unsigned long es7000_check_apicid_present(int bit)
 	return physid_isset(bit, phys_cpu_present_map);
 }
 
+static int es7000_early_logical_apicid(int cpu)
+{
+	/* on es7000, logical apicid is the same as physical */
+	return early_per_cpu(x86_bios_cpu_apicid, cpu);
+}
+
 static unsigned long calculate_ldr(int cpu)
 {
 	unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu);
@@ -504,12 +510,11 @@ static void es7000_setup_apic_routing(void)
 		nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
 }
 
-static int es7000_apicid_to_node(int logical_apicid)
+static int es7000_numa_cpu_node(int cpu)
 {
 	return 0;
 }
 
-
 static int es7000_cpu_present_to_apicid(int mps_cpu)
 {
 	if (!mps_cpu)
@@ -528,18 +533,6 @@ static void es7000_apicid_to_cpu_present(int phys_apicid, physid_mask_t *retmap)
 	++cpu_id;
 }
 
-/* Mapping from cpu number to logical apicid */
-static int es7000_cpu_to_logical_apicid(int cpu)
-{
-#ifdef CONFIG_SMP
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_2_logical_apicid[cpu];
-#else
-	return logical_smp_processor_id();
-#endif
-}
-
 static void es7000_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
 {
 	/* For clustered we don't have a good way to do this yet - hack */
@@ -561,7 +554,7 @@ static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask)
 	 * The cpus in the mask must all be on the apic cluster.
 	 */
 	for_each_cpu(cpu, cpumask) {
-		int new_apicid = es7000_cpu_to_logical_apicid(cpu);
+		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
 		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
 			WARN(1, "Not a valid mask!");
@@ -578,7 +571,7 @@ static unsigned int
 es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
 			      const struct cpumask *andmask)
 {
-	int apicid = es7000_cpu_to_logical_apicid(0);
+	int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 	cpumask_var_t cpumask;
 
 	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
@@ -655,8 +648,6 @@ struct apic __refdata apic_es7000_cluster = {
 	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
 	.setup_apic_routing		= es7000_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= es7000_apicid_to_node,
-	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
 	.setup_portio_remap		= NULL,
@@ -695,6 +686,9 @@ struct apic __refdata apic_es7000_cluster = {
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= es7000_early_logical_apicid,
+	.x86_32_numa_cpu_node		= es7000_numa_cpu_node,
 };
 
 struct apic __refdata apic_es7000 = {
@@ -720,8 +714,6 @@ struct apic __refdata apic_es7000 = {
 	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
 	.setup_apic_routing		= es7000_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= es7000_apicid_to_node,
-	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
 	.setup_portio_remap		= NULL,
@@ -758,4 +750,7 @@ struct apic __refdata apic_es7000 = {
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= es7000_early_logical_apicid,
+	.x86_32_numa_cpu_node		= es7000_numa_cpu_node,
 };
diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c
index 79fd43c..c4e557a 100644
--- a/arch/x86/kernel/apic/hw_nmi.c
+++ b/arch/x86/kernel/apic/hw_nmi.c
@@ -83,7 +83,6 @@ arch_trigger_all_cpu_backtrace_handler(struct notifier_block *self,
 		arch_spin_lock(&lock);
 		printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
 		show_regs(regs);
-		dump_stack();
 		arch_spin_unlock(&lock);
 		cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
 		return NOTIFY_STOP;
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index ca9e2a3..180ca24 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -108,7 +108,10 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 
 int skip_ioapic_setup;
 
-void arch_disable_smp_support(void)
+/**
+ * disable_ioapic_support() - disables ioapic support at runtime
+ */
+void disable_ioapic_support(void)
 {
 #ifdef CONFIG_PCI
 	noioapicquirk = 1;
@@ -120,11 +123,14 @@ void arch_disable_smp_support(void)
 static int __init parse_noapic(char *str)
 {
 	/* disable IO-APIC */
-	arch_disable_smp_support();
+	disable_ioapic_support();
 	return 0;
 }
 early_param("noapic", parse_noapic);
 
+static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+				      struct io_apic_irq_attr *attr);
+
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
 {
@@ -181,7 +187,7 @@ int __init arch_early_irq_init(void)
 	irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
 
 	for (i = 0; i < count; i++) {
-		set_irq_chip_data(i, &cfg[i]);
+		irq_set_chip_data(i, &cfg[i]);
 		zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
 		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
 		/*
@@ -200,7 +206,7 @@ int __init arch_early_irq_init(void)
 #ifdef CONFIG_SPARSE_IRQ
 static struct irq_cfg *irq_cfg(unsigned int irq)
 {
-	return get_irq_chip_data(irq);
+	return irq_get_chip_data(irq);
 }
 
 static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
@@ -226,7 +232,7 @@ static void free_irq_cfg(unsigned int at, struct irq_cfg *cfg)
 {
 	if (!cfg)
 		return;
-	set_irq_chip_data(at, NULL);
+	irq_set_chip_data(at, NULL);
 	free_cpumask_var(cfg->domain);
 	free_cpumask_var(cfg->old_domain);
 	kfree(cfg);
@@ -256,14 +262,14 @@ static struct irq_cfg *alloc_irq_and_cfg_at(unsigned int at, int node)
 	if (res < 0) {
 		if (res != -EEXIST)
 			return NULL;
-		cfg = get_irq_chip_data(at);
+		cfg = irq_get_chip_data(at);
 		if (cfg)
 			return cfg;
 	}
 
 	cfg = alloc_irq_cfg(at, node);
 	if (cfg)
-		set_irq_chip_data(at, cfg);
+		irq_set_chip_data(at, cfg);
 	else
 		irq_free_desc(at);
 	return cfg;
@@ -818,7 +824,7 @@ static int EISA_ELCR(unsigned int irq)
 #define default_MCA_trigger(idx)	(1)
 #define default_MCA_polarity(idx)	default_ISA_polarity(idx)
 
-static int MPBIOS_polarity(int idx)
+static int irq_polarity(int idx)
 {
 	int bus = mp_irqs[idx].srcbus;
 	int polarity;
@@ -860,7 +866,7 @@ static int MPBIOS_polarity(int idx)
 	return polarity;
 }
 
-static int MPBIOS_trigger(int idx)
+static int irq_trigger(int idx)
 {
 	int bus = mp_irqs[idx].srcbus;
 	int trigger;
@@ -932,16 +938,6 @@ static int MPBIOS_trigger(int idx)
 	return trigger;
 }
 
-static inline int irq_polarity(int idx)
-{
-	return MPBIOS_polarity(idx);
-}
-
-static inline int irq_trigger(int idx)
-{
-	return MPBIOS_trigger(idx);
-}
-
 static int pin_2_irq(int idx, int apic, int pin)
 {
 	int irq;
@@ -1189,7 +1185,7 @@ void __setup_vector_irq(int cpu)
 	raw_spin_lock(&vector_lock);
 	/* Mark the inuse vectors */
 	for_each_active_irq(irq) {
-		cfg = get_irq_chip_data(irq);
+		cfg = irq_get_chip_data(irq);
 		if (!cfg)
 			continue;
 		/*
@@ -1220,10 +1216,6 @@ void __setup_vector_irq(int cpu)
 static struct irq_chip ioapic_chip;
 static struct irq_chip ir_ioapic_chip;
 
-#define IOAPIC_AUTO     -1
-#define IOAPIC_EDGE     0
-#define IOAPIC_LEVEL    1
-
 #ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
 {
@@ -1248,35 +1240,31 @@ static inline int IO_APIC_irq_trigger(int irq)
 }
 #endif
 
-static void ioapic_register_intr(unsigned int irq, unsigned long trigger)
+static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
+				 unsigned long trigger)
 {
+	struct irq_chip *chip = &ioapic_chip;
+	irq_flow_handler_t hdl;
+	bool fasteoi;
 
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
+	    trigger == IOAPIC_LEVEL) {
 		irq_set_status_flags(irq, IRQ_LEVEL);
-	else
+		fasteoi = true;
+	} else {
 		irq_clear_status_flags(irq, IRQ_LEVEL);
+		fasteoi = false;
+	}
 
-	if (irq_remapped(get_irq_chip_data(irq))) {
+	if (irq_remapped(cfg)) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		if (trigger)
-			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
-						      handle_fasteoi_irq,
-						     "fasteoi");
-		else
-			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
-						      handle_edge_irq, "edge");
-		return;
+		chip = &ir_ioapic_chip;
+		fasteoi = trigger != 0;
 	}
 
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					      handle_fasteoi_irq,
-					      "fasteoi");
-	else
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					      handle_edge_irq, "edge");
+	hdl = fasteoi ? handle_fasteoi_irq : handle_edge_irq;
+	irq_set_chip_and_handler_name(irq, chip, hdl,
+				      fasteoi ? "fasteoi" : "edge");
 }
 
 static int setup_ioapic_entry(int apic_id, int irq,
@@ -1374,7 +1362,7 @@ static void setup_ioapic_irq(int apic_id, int pin, unsigned int irq,
 		return;
 	}
 
-	ioapic_register_intr(irq, trigger);
+	ioapic_register_intr(irq, cfg, trigger);
 	if (irq < legacy_pic->nr_legacy_irqs)
 		legacy_pic->mask(irq);
 
@@ -1385,33 +1373,26 @@ static struct {
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
-static void __init setup_IO_APIC_irqs(void)
+static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
 {
-	int apic_id, pin, idx, irq, notcon = 0;
-	int node = cpu_to_node(0);
-	struct irq_cfg *cfg;
+	if (idx != -1)
+		return false;
 
-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
+		    mp_ioapics[apic_id].apicid, pin);
+	return true;
+}
+
+static void __init __io_apic_setup_irqs(unsigned int apic_id)
+{
+	int idx, node = cpu_to_node(0);
+	struct io_apic_irq_attr attr;
+	unsigned int pin, irq;
 
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
 		idx = find_irq_entry(apic_id, pin, mp_INT);
-		if (idx == -1) {
-			if (!notcon) {
-				notcon = 1;
-				apic_printk(APIC_VERBOSE,
-					KERN_DEBUG " %d-%d",
-					mp_ioapics[apic_id].apicid, pin);
-			} else
-				apic_printk(APIC_VERBOSE, " %d-%d",
-					mp_ioapics[apic_id].apicid, pin);
+		if (io_apic_pin_not_connected(idx, apic_id, pin))
 			continue;
-		}
-		if (notcon) {
-			apic_printk(APIC_VERBOSE,
-				" (apicid-pin) not connected\n");
-			notcon = 0;
-		}
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
@@ -1423,25 +1404,24 @@ static void __init setup_IO_APIC_irqs(void)
 		 * installed and if it returns 1:
 		 */
 		if (apic->multi_timer_check &&
-				apic->multi_timer_check(apic_id, irq))
+		    apic->multi_timer_check(apic_id, irq))
 			continue;
 
-		cfg = alloc_irq_and_cfg_at(irq, node);
-		if (!cfg)
-			continue;
+		set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+				     irq_polarity(idx));
 
-		add_pin_to_irq_node(cfg, node, apic_id, pin);
-		/*
-		 * don't mark it in pin_programmed, so later acpi could
-		 * set it correctly when irq < 16
-		 */
-		setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
-				  irq_polarity(idx));
+		io_apic_setup_irq_pin(irq, node, &attr);
 	}
+}
 
-	if (notcon)
-		apic_printk(APIC_VERBOSE,
-			" (apicid-pin) not connected\n");
+static void __init setup_IO_APIC_irqs(void)
+{
+	unsigned int apic_id;
+
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
+		__io_apic_setup_irqs(apic_id);
 }
 
 /*
@@ -1452,7 +1432,7 @@ static void __init setup_IO_APIC_irqs(void)
 void setup_IO_APIC_irq_extra(u32 gsi)
 {
 	int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
-	struct irq_cfg *cfg;
+	struct io_apic_irq_attr attr;
 
 	/*
 	 * Convert 'gsi' to 'ioapic.pin'.
@@ -1472,21 +1452,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
 	if (apic_id == 0 || irq < NR_IRQS_LEGACY)
 		return;
 
-	cfg = alloc_irq_and_cfg_at(irq, node);
-	if (!cfg)
-		return;
-
-	add_pin_to_irq_node(cfg, node, apic_id, pin);
-
-	if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
-		pr_debug("Pin %d-%d already programmed\n",
-			 mp_ioapics[apic_id].apicid, pin);
-		return;
-	}
-	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+	set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+			     irq_polarity(idx));
 
-	setup_ioapic_irq(apic_id, pin, irq, cfg,
-			irq_trigger(idx), irq_polarity(idx));
+	io_apic_setup_irq_pin_once(irq, node, &attr);
 }
 
 /*
@@ -1518,7 +1487,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
 	 * The timer IRQ doesn't have to know that behind the
 	 * scene we may have a 8259A-master in AEOI mode ...
 	 */
-	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+	irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq,
+				      "edge");
 
 	/*
 	 * Add it to the IO-APIC irq-routing table:
@@ -1625,7 +1595,7 @@ __apicdebuginit(void) print_IO_APIC(void)
 	for_each_active_irq(irq) {
 		struct irq_pin_list *entry;
 
-		cfg = get_irq_chip_data(irq);
+		cfg = irq_get_chip_data(irq);
 		if (!cfg)
 			continue;
 		entry = cfg->irq_2_pin;
@@ -1916,7 +1886,7 @@ void disable_IO_APIC(void)
 	 *
 	 * With interrupt-remapping, for now we will use virtual wire A mode,
 	 * as virtual wire B is little complex (need to configure both
-	 * IOAPIC RTE aswell as interrupt-remapping table entry).
+	 * IOAPIC RTE as well as interrupt-remapping table entry).
 	 * As this gets called during crash dump, keep this simple for now.
 	 */
 	if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
@@ -2391,7 +2361,7 @@ static void irq_complete_move(struct irq_cfg *cfg)
 
 void irq_force_complete_move(int irq)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 
 	if (!cfg)
 		return;
@@ -2405,7 +2375,7 @@ static inline void irq_complete_move(struct irq_cfg *cfg) { }
 static void ack_apic_edge(struct irq_data *data)
 {
 	irq_complete_move(data->chip_data);
-	move_native_irq(data->irq);
+	irq_move_irq(data);
 	ack_APIC_irq();
 }
 
@@ -2462,7 +2432,7 @@ static void ack_apic_level(struct irq_data *data)
 	irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	/* If we are moving the irq we need to mask it */
-	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
+	if (unlikely(irqd_is_setaffinity_pending(data))) {
 		do_unmask_irq = 1;
 		mask_ioapic(cfg);
 	}
@@ -2551,7 +2521,7 @@ static void ack_apic_level(struct irq_data *data)
 		 * and you can go talk to the chipset vendor about it.
 		 */
 		if (!io_apic_level_ack_pending(cfg))
-			move_masked_irq(irq);
+			irq_move_masked_irq(data);
 		unmask_ioapic(cfg);
 	}
 }
@@ -2614,7 +2584,7 @@ static inline void init_IO_APIC_traps(void)
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
 	for_each_active_irq(irq) {
-		cfg = get_irq_chip_data(irq);
+		cfg = irq_get_chip_data(irq);
 		if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2625,7 +2595,7 @@ static inline void init_IO_APIC_traps(void)
 				legacy_pic->make_irq(irq);
 			else
 				/* Strange. Oh, well.. */
-				set_irq_chip(irq, &no_irq_chip);
+				irq_set_chip(irq, &no_irq_chip);
 		}
 	}
 }
@@ -2665,7 +2635,7 @@ static struct irq_chip lapic_chip __read_mostly = {
 static void lapic_register_intr(int irq)
 {
 	irq_clear_status_flags(irq, IRQ_LEVEL);
-	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+	irq_set_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
 				      "edge");
 }
 
@@ -2749,7 +2719,7 @@ int timer_through_8259 __initdata;
  */
 static inline void __init check_timer(void)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(0);
+	struct irq_cfg *cfg = irq_get_chip_data(0);
 	int node = cpu_to_node(0);
 	int apic1, pin1, apic2, pin2;
 	unsigned long flags;
@@ -2935,7 +2905,7 @@ void __init setup_IO_APIC(void)
 }
 
 /*
- *      Called after all the initialization is done. If we didnt find any
+ *      Called after all the initialization is done. If we didn't find any
  *      APIC bugs then we can allow the modify fast path
  */
 
@@ -3060,7 +3030,7 @@ unsigned int create_irq_nr(unsigned int from, int node)
 	raw_spin_unlock_irqrestore(&vector_lock, flags);
 
 	if (ret) {
-		set_irq_chip_data(irq, cfg);
+		irq_set_chip_data(irq, cfg);
 		irq_clear_status_flags(irq, IRQ_NOREQUEST);
 	} else {
 		free_irq_at(irq, cfg);
@@ -3085,7 +3055,7 @@ int create_irq(void)
 
 void destroy_irq(unsigned int irq)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 	unsigned long flags;
 
 	irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
@@ -3119,7 +3089,7 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
 
-	if (irq_remapped(get_irq_chip_data(irq))) {
+	if (irq_remapped(cfg)) {
 		struct irte irte;
 		int ir_index;
 		u16 sub_handle;
@@ -3291,6 +3261,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
 
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 {
+	struct irq_chip *chip = &msi_chip;
 	struct msi_msg msg;
 	int ret;
 
@@ -3298,14 +3269,15 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 	if (ret < 0)
 		return ret;
 
-	set_irq_msi(irq, msidesc);
+	irq_set_msi_desc(irq, msidesc);
 	write_msi_msg(irq, &msg);
 
-	if (irq_remapped(get_irq_chip_data(irq))) {
+	if (irq_remapped(irq_get_chip_data(irq))) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
-	} else
-		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+		chip = &msi_ir_chip;
+	}
+
+	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 
 	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
 
@@ -3423,8 +3395,8 @@ int arch_setup_dmar_msi(unsigned int irq)
 	if (ret < 0)
 		return ret;
 	dmar_msi_write(irq, &msg);
-	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-		"edge");
+	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+				      "edge");
 	return 0;
 }
 #endif
@@ -3482,6 +3454,7 @@ static struct irq_chip hpet_msi_type = {
 
 int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
 {
+	struct irq_chip *chip = &hpet_msi_type;
 	struct msi_msg msg;
 	int ret;
 
@@ -3501,15 +3474,12 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
 	if (ret < 0)
 		return ret;
 
-	hpet_msi_write(get_irq_data(irq), &msg);
+	hpet_msi_write(irq_get_handler_data(irq), &msg);
 	irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-	if (irq_remapped(get_irq_chip_data(irq)))
-		set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type,
-					      handle_edge_irq, "edge");
-	else
-		set_irq_chip_and_handler_name(irq, &hpet_msi_type,
-					      handle_edge_irq, "edge");
+	if (irq_remapped(irq_get_chip_data(irq)))
+		chip = &ir_hpet_msi_type;
 
+	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 	return 0;
 }
 #endif
@@ -3596,7 +3566,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 
 		write_ht_irq_msg(irq, &msg);
 
-		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+		irq_set_chip_and_handler_name(irq, &ht_irq_chip,
 					      handle_edge_irq, "edge");
 
 		dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
@@ -3605,7 +3575,40 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 }
 #endif /* CONFIG_HT_IRQ */
 
-int __init io_apic_get_redir_entries (int ioapic)
+int
+io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
+{
+	struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
+	int ret;
+
+	if (!cfg)
+		return -EINVAL;
+	ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
+	if (!ret)
+		setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
+				 attr->trigger, attr->polarity);
+	return ret;
+}
+
+static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+				      struct io_apic_irq_attr *attr)
+{
+	unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
+	int ret;
+
+	/* Avoid redundant programming */
+	if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[id].apicid, pin);
+		return 0;
+	}
+	ret = io_apic_setup_irq_pin(irq, node, attr);
+	if (!ret)
+		set_bit(pin, mp_ioapic_routing[id].pin_programmed);
+	return ret;
+}
+
+static int __init io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3659,96 +3662,24 @@ int __init arch_probe_nr_irqs(void)
 }
 #endif
 
-static int __io_apic_set_pci_routing(struct device *dev, int irq,
-				struct io_apic_irq_attr *irq_attr)
+int io_apic_set_pci_routing(struct device *dev, int irq,
+			    struct io_apic_irq_attr *irq_attr)
 {
-	struct irq_cfg *cfg;
 	int node;
-	int ioapic, pin;
-	int trigger, polarity;
 
-	ioapic = irq_attr->ioapic;
 	if (!IO_APIC_IRQ(irq)) {
 		apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
-			ioapic);
+			    irq_attr->ioapic);
 		return -EINVAL;
 	}
 
-	if (dev)
-		node = dev_to_node(dev);
-	else
-		node = cpu_to_node(0);
-
-	cfg = alloc_irq_and_cfg_at(irq, node);
-	if (!cfg)
-		return 0;
-
-	pin = irq_attr->ioapic_pin;
-	trigger = irq_attr->trigger;
-	polarity = irq_attr->polarity;
+	node = dev ? dev_to_node(dev) : cpu_to_node(0);
 
-	/*
-	 * IRQs < 16 are already in the irq_2_pin[] map
-	 */
-	if (irq >= legacy_pic->nr_legacy_irqs) {
-		if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
-			printk(KERN_INFO "can not add pin %d for irq %d\n",
-				pin, irq);
-			return 0;
-		}
-	}
-
-	setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
-
-	return 0;
+	return io_apic_setup_irq_pin_once(irq, node, irq_attr);
 }
 
-int io_apic_set_pci_routing(struct device *dev, int irq,
-				struct io_apic_irq_attr *irq_attr)
-{
-	int ioapic, pin;
-	/*
-	 * Avoid pin reprogramming.  PRTs typically include entries
-	 * with redundant pin->gsi mappings (but unique PCI devices);
-	 * we only program the IOAPIC on the first.
-	 */
-	ioapic = irq_attr->ioapic;
-	pin = irq_attr->ioapic_pin;
-	if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
-		pr_debug("Pin %d-%d already programmed\n",
-			 mp_ioapics[ioapic].apicid, pin);
-		return 0;
-	}
-	set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
-
-	return __io_apic_set_pci_routing(dev, irq, irq_attr);
-}
-
-u8 __init io_apic_unique_id(u8 id)
-{
 #ifdef CONFIG_X86_32
-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
-	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return io_apic_get_unique_id(nr_ioapics, id);
-	else
-		return id;
-#else
-	int i;
-	DECLARE_BITMAP(used, 256);
-
-	bitmap_zero(used, 256);
-	for (i = 0; i < nr_ioapics; i++) {
-		struct mpc_ioapic *ia = &mp_ioapics[i];
-		__set_bit(ia->apicid, used);
-	}
-	if (!test_bit(id, used))
-		return id;
-	return find_first_zero_bit(used, 256);
-#endif
-}
-
-#ifdef CONFIG_X86_32
-int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
 	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3821,9 +3752,33 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
 
 	return apic_id;
 }
+
+static u8 __init io_apic_unique_id(u8 id)
+{
+	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return io_apic_get_unique_id(nr_ioapics, id);
+	else
+		return id;
+}
+#else
+static u8 __init io_apic_unique_id(u8 id)
+{
+	int i;
+	DECLARE_BITMAP(used, 256);
+
+	bitmap_zero(used, 256);
+	for (i = 0; i < nr_ioapics; i++) {
+		struct mpc_ioapic *ia = &mp_ioapics[i];
+		__set_bit(ia->apicid, used);
+	}
+	if (!test_bit(id, used))
+		return id;
+	return find_first_zero_bit(used, 256);
+}
 #endif
 
-int __init io_apic_get_version(int ioapic)
+static int __init io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3868,8 +3823,8 @@ int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity)
 void __init setup_ioapic_dest(void)
 {
 	int pin, ioapic, irq, irq_entry;
-	struct irq_desc *desc;
 	const struct cpumask *mask;
+	struct irq_data *idata;
 
 	if (skip_ioapic_setup == 1)
 		return;
@@ -3884,21 +3839,20 @@ void __init setup_ioapic_dest(void)
 		if ((ioapic > 0) && (irq > 16))
 			continue;
 
-		desc = irq_to_desc(irq);
+		idata = irq_get_irq_data(irq);
 
 		/*
 		 * Honour affinities which have been set in early boot
 		 */
-		if (desc->status &
-		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
-			mask = desc->irq_data.affinity;
+		if (!irqd_can_balance(idata) || irqd_affinity_was_set(idata))
+			mask = idata->affinity;
 		else
 			mask = apic->target_cpus();
 
 		if (intr_remapping_enabled)
-			ir_ioapic_set_affinity(&desc->irq_data, mask, false);
+			ir_ioapic_set_affinity(idata, mask, false);
 		else
-			ioapic_set_affinity(&desc->irq_data, mask, false);
+			ioapic_set_affinity(idata, mask, false);
 	}
 
 }
@@ -4026,10 +3980,10 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
 	return gsi - mp_gsi_routing[ioapic].gsi_base;
 }
 
-static int bad_ioapic(unsigned long address)
+static __init int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
-		printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
+		printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded "
 		       "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
 		return 1;
 	}
@@ -4086,20 +4040,16 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
 /* Enable IOAPIC early just for system timer */
 void __init pre_init_apic_IRQ0(void)
 {
-	struct irq_cfg *cfg;
+	struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
 
 	printk(KERN_INFO "Early APIC setup for system timer0\n");
 #ifndef CONFIG_SMP
 	physid_set_mask_of_physid(boot_cpu_physical_apicid,
 					 &phys_cpu_present_map);
 #endif
-	/* Make sure the irq descriptor is set up */
-	cfg = alloc_irq_and_cfg_at(0, 0);
-
 	setup_local_APIC();
 
-	add_pin_to_irq_node(cfg, 0, 0, 0);
-	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
-
-	setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
+	io_apic_setup_irq_pin(0, 0, &attr);
+	irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq,
+				      "edge");
 }
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c
index 08385e0..cce91bf 100644
--- a/arch/x86/kernel/apic/ipi.c
+++ b/arch/x86/kernel/apic/ipi.c
@@ -56,6 +56,8 @@ void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
 	local_irq_restore(flags);
 }
 
+#ifdef CONFIG_X86_32
+
 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
 						 int vector)
 {
@@ -71,8 +73,8 @@ void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
 	local_irq_save(flags);
 	for_each_cpu(query_cpu, mask)
 		__default_send_IPI_dest_field(
-			apic->cpu_to_logical_apicid(query_cpu), vector,
-			apic->dest_logical);
+			early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+			vector, apic->dest_logical);
 	local_irq_restore(flags);
 }
 
@@ -90,14 +92,12 @@ void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
 		if (query_cpu == this_cpu)
 			continue;
 		__default_send_IPI_dest_field(
-			apic->cpu_to_logical_apicid(query_cpu), vector,
-			apic->dest_logical);
+			early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+			vector, apic->dest_logical);
 		}
 	local_irq_restore(flags);
 }
 
-#ifdef CONFIG_X86_32
-
 /*
  * This is only used on smaller machines.
  */
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 960f26a..6273eee 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -373,13 +373,6 @@ static inline void numaq_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask
 	return physids_promote(0xFUL, retmap);
 }
 
-static inline int numaq_cpu_to_logical_apicid(int cpu)
-{
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_2_logical_apicid[cpu];
-}
-
 /*
  * Supporting over 60 cpus on NUMA-Q requires a locality-dependent
  * cpu to APIC ID relation to properly interact with the intelligent
@@ -398,6 +391,15 @@ static inline int numaq_apicid_to_node(int logical_apicid)
 	return logical_apicid >> 4;
 }
 
+static int numaq_numa_cpu_node(int cpu)
+{
+	int logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+
+	if (logical_apicid != BAD_APICID)
+		return numaq_apicid_to_node(logical_apicid);
+	return NUMA_NO_NODE;
+}
+
 static void numaq_apicid_to_cpu_present(int logical_apicid, physid_mask_t *retmap)
 {
 	int node = numaq_apicid_to_node(logical_apicid);
@@ -508,8 +510,6 @@ struct apic __refdata apic_numaq = {
 	.ioapic_phys_id_map		= numaq_ioapic_phys_id_map,
 	.setup_apic_routing		= numaq_setup_apic_routing,
 	.multi_timer_check		= numaq_multi_timer_check,
-	.apicid_to_node			= numaq_apicid_to_node,
-	.cpu_to_logical_apicid		= numaq_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= numaq_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= numaq_apicid_to_cpu_present,
 	.setup_portio_remap		= numaq_setup_portio_remap,
@@ -547,4 +547,7 @@ struct apic __refdata apic_numaq = {
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= noop_x86_32_early_logical_apicid,
+	.x86_32_numa_cpu_node		= numaq_numa_cpu_node,
 };
diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 99d2fe0..fc84c7b 100644
--- a/arch/x86/kernel/apic/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -77,6 +77,11 @@ void __init default_setup_apic_routing(void)
 		apic->setup_apic_routing();
 }
 
+static int default_x86_32_early_logical_apicid(int cpu)
+{
+	return 1 << cpu;
+}
+
 static void setup_apic_flat_routing(void)
 {
 #ifdef CONFIG_X86_IO_APIC
@@ -130,8 +135,6 @@ struct apic apic_default = {
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
 	.setup_apic_routing		= setup_apic_flat_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= default_apicid_to_node,
-	.cpu_to_logical_apicid		= default_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 	.setup_portio_remap		= NULL,
@@ -167,6 +170,9 @@ struct apic apic_default = {
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= default_x86_32_early_logical_apicid,
+	.x86_32_numa_cpu_node		= default_x86_32_numa_cpu_node,
 };
 
 extern struct apic apic_numaq;
diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index 9b41926..e4b8059 100644
--- a/arch/x86/kernel/apic/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -194,11 +194,10 @@ static unsigned long summit_check_apicid_present(int bit)
 	return 1;
 }
 
-static void summit_init_apic_ldr(void)
+static int summit_early_logical_apicid(int cpu)
 {
-	unsigned long val, id;
 	int count = 0;
-	u8 my_id = (u8)hard_smp_processor_id();
+	u8 my_id = early_per_cpu(x86_cpu_to_apicid, cpu);
 	u8 my_cluster = APIC_CLUSTER(my_id);
 #ifdef CONFIG_SMP
 	u8 lid;
@@ -206,7 +205,7 @@ static void summit_init_apic_ldr(void)
 
 	/* Create logical APIC IDs by counting CPUs already in cluster. */
 	for (count = 0, i = nr_cpu_ids; --i >= 0; ) {
-		lid = cpu_2_logical_apicid[i];
+		lid = early_per_cpu(x86_cpu_to_logical_apicid, i);
 		if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
 			++count;
 	}
@@ -214,7 +213,15 @@ static void summit_init_apic_ldr(void)
 	/* We only have a 4 wide bitmap in cluster mode.  If a deranged
 	 * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
 	BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
-	id = my_cluster | (1UL << count);
+	return my_cluster | (1UL << count);
+}
+
+static void summit_init_apic_ldr(void)
+{
+	int cpu = smp_processor_id();
+	unsigned long id = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+	unsigned long val;
+
 	apic_write(APIC_DFR, SUMMIT_APIC_DFR_VALUE);
 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
 	val |= SET_APIC_LOGICAL_ID(id);
@@ -232,27 +239,6 @@ static void summit_setup_apic_routing(void)
 						nr_ioapics);
 }
 
-static int summit_apicid_to_node(int logical_apicid)
-{
-#ifdef CONFIG_SMP
-	return apicid_2_node[hard_smp_processor_id()];
-#else
-	return 0;
-#endif
-}
-
-/* Mapping from cpu number to logical apicid */
-static inline int summit_cpu_to_logical_apicid(int cpu)
-{
-#ifdef CONFIG_SMP
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_2_logical_apicid[cpu];
-#else
-	return logical_smp_processor_id();
-#endif
-}
-
 static int summit_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids)
@@ -286,7 +272,7 @@ static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask)
 	 * The cpus in the mask must all be on the apic cluster.
 	 */
 	for_each_cpu(cpu, cpumask) {
-		int new_apicid = summit_cpu_to_logical_apicid(cpu);
+		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
 		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
 			printk("%s: Not a valid mask!\n", __func__);
@@ -301,7 +287,7 @@ static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask)
 static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
 			      const struct cpumask *andmask)
 {
-	int apicid = summit_cpu_to_logical_apicid(0);
+	int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 	cpumask_var_t cpumask;
 
 	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
@@ -528,8 +514,6 @@ struct apic apic_summit = {
 	.ioapic_phys_id_map		= summit_ioapic_phys_id_map,
 	.setup_apic_routing		= summit_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= summit_apicid_to_node,
-	.cpu_to_logical_apicid		= summit_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= summit_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= summit_apicid_to_cpu_present,
 	.setup_portio_remap		= NULL,
@@ -565,4 +549,7 @@ struct apic apic_summit = {
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= summit_early_logical_apicid,
+	.x86_32_numa_cpu_node		= default_x86_32_numa_cpu_node,
 };
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index cf69c59..90949bb 100644
--- a/arch/x86/kernel/apic/x2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -206,8 +206,6 @@ struct apic apic_x2apic_cluster = {
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 8972f38..c7e6d66 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -195,8 +195,6 @@ struct apic apic_x2apic_phys = {
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index bd16b58..3c28928 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -338,8 +338,6 @@ struct apic __refdata apic_x2apic_uv_x = {
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 0e4f24c..0b4be43 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -66,7 +66,7 @@
  *    1.5: Fix segment register reloading (in case of bad segments saved
  *         across BIOS call).
  *         Stephen Rothwell
- *    1.6: Cope with complier/assembler differences.
+ *    1.6: Cope with compiler/assembler differences.
  *         Only try to turn off the first display device.
  *         Fix OOPS at power off with no APM BIOS by Jan Echternach
  *                   <echter@informatik.uni-rostock.de>
@@ -227,6 +227,7 @@
 #include <linux/suspend.h>
 #include <linux/kthread.h>
 #include <linux/jiffies.h>
+#include <linux/acpi.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -975,20 +976,10 @@ recalc:
 
 static void apm_power_off(void)
 {
-	unsigned char po_bios_call[] = {
-		0xb8, 0x00, 0x10,	/* movw  $0x1000,ax  */
-		0x8e, 0xd0,		/* movw  ax,ss       */
-		0xbc, 0x00, 0xf0,	/* movw  $0xf000,sp  */
-		0xb8, 0x07, 0x53,	/* movw  $0x5307,ax  */
-		0xbb, 0x01, 0x00,	/* movw  $0x0001,bx  */
-		0xb9, 0x03, 0x00,	/* movw  $0x0003,cx  */
-		0xcd, 0x15		/* int   $0x15       */
-	};
-
 	/* Some bioses don't like being called from CPU != 0 */
 	if (apm_info.realmode_power_off) {
 		set_cpus_allowed_ptr(current, cpumask_of(0));
-		machine_real_restart(po_bios_call, sizeof(po_bios_call));
+		machine_real_restart(MRR_APM);
 	} else {
 		(void)set_system_power_state(APM_STATE_OFF);
 	}
@@ -2331,12 +2322,11 @@ static int __init apm_init(void)
 		apm_info.disabled = 1;
 		return -ENODEV;
 	}
-	if (pm_flags & PM_ACPI) {
+	if (!acpi_disabled) {
 		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
 		apm_info.disabled = 1;
 		return -ENODEV;
 	}
-	pm_flags |= PM_APM;
 
 	/*
 	 * Set up the long jump entry point to the APM BIOS, which is called
@@ -2428,7 +2418,6 @@ static void __exit apm_exit(void)
 		kthread_stop(kapmd_task);
 		kapmd_task = NULL;
 	}
-	pm_flags &= ~PM_APM;
 }
 
 module_init(apm_init);
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index cfa82c8..4f13faf 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -1,5 +1,70 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ */
+#define COMPILE_OFFSETS
+
+#include <linux/crypto.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/hardirq.h>
+#include <linux/suspend.h>
+#include <linux/kbuild.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/sigframe.h>
+#include <asm/bootparam.h>
+#include <asm/suspend.h>
+
+#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+#endif
+
 #ifdef CONFIG_X86_32
 # include "asm-offsets_32.c"
 #else
 # include "asm-offsets_64.c"
 #endif
+
+void common(void) {
+	BLANK();
+	OFFSET(TI_flags, thread_info, flags);
+	OFFSET(TI_status, thread_info, status);
+	OFFSET(TI_addr_limit, thread_info, addr_limit);
+	OFFSET(TI_preempt_count, thread_info, preempt_count);
+
+	BLANK();
+	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+
+	BLANK();
+	OFFSET(pbe_address, pbe, address);
+	OFFSET(pbe_orig_address, pbe, orig_address);
+	OFFSET(pbe_next, pbe, next);
+
+#ifdef CONFIG_PARAVIRT
+	BLANK();
+	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
+	OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
+	OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
+	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
+	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
+	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
+	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
+	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
+	OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
+#endif
+
+#ifdef CONFIG_XEN
+	BLANK();
+	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
+#endif
+
+	BLANK();
+	OFFSET(BP_scratch, boot_params, scratch);
+	OFFSET(BP_loadflags, boot_params, hdr.loadflags);
+	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
+	OFFSET(BP_version, boot_params, hdr.version);
+	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
+}
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index 1a4088d..c29d631 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -1,26 +1,4 @@
-/*
- * Generate definitions needed by assembly language modules.
- * This code generates raw asm output which is post-processed
- * to extract and format the required data.
- */
-
-#include <linux/crypto.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/personality.h>
-#include <linux/suspend.h>
-#include <linux/kbuild.h>
 #include <asm/ucontext.h>
-#include <asm/sigframe.h>
-#include <asm/pgtable.h>
-#include <asm/fixmap.h>
-#include <asm/processor.h>
-#include <asm/thread_info.h>
-#include <asm/bootparam.h>
-#include <asm/elf.h>
-#include <asm/suspend.h>
-
-#include <xen/interface/xen.h>
 
 #include <linux/lguest.h>
 #include "../../../drivers/lguest/lg.h"
@@ -51,21 +29,10 @@ void foo(void)
 	OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
 	BLANK();
 
-	OFFSET(TI_task, thread_info, task);
-	OFFSET(TI_exec_domain, thread_info, exec_domain);
-	OFFSET(TI_flags, thread_info, flags);
-	OFFSET(TI_status, thread_info, status);
-	OFFSET(TI_preempt_count, thread_info, preempt_count);
-	OFFSET(TI_addr_limit, thread_info, addr_limit);
-	OFFSET(TI_restart_block, thread_info, restart_block);
 	OFFSET(TI_sysenter_return, thread_info, sysenter_return);
 	OFFSET(TI_cpu, thread_info, cpu);
 	BLANK();
 
-	OFFSET(GDS_size, desc_ptr, size);
-	OFFSET(GDS_address, desc_ptr, address);
-	BLANK();
-
 	OFFSET(PT_EBX, pt_regs, bx);
 	OFFSET(PT_ECX, pt_regs, cx);
 	OFFSET(PT_EDX, pt_regs, dx);
@@ -85,42 +52,13 @@ void foo(void)
 	OFFSET(PT_OLDSS,  pt_regs, ss);
 	BLANK();
 
-	OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
 	OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
 	BLANK();
 
-	OFFSET(pbe_address, pbe, address);
-	OFFSET(pbe_orig_address, pbe, orig_address);
-	OFFSET(pbe_next, pbe, next);
-
 	/* Offset from the sysenter stack to tss.sp0 */
 	DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
 		 sizeof(struct tss_struct));
 
-	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
-	DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
-	DEFINE(THREAD_SIZE_asm, THREAD_SIZE);
-
-	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
-
-#ifdef CONFIG_PARAVIRT
-	BLANK();
-	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
-	OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
-	OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
-	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
-	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
-	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
-	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
-	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
-#endif
-
-#ifdef CONFIG_XEN
-	BLANK();
-	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
-	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
-#endif
-
 #if defined(CONFIG_LGUEST) || defined(CONFIG_LGUEST_GUEST) || defined(CONFIG_LGUEST_MODULE)
 	BLANK();
 	OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
@@ -139,11 +77,4 @@ void foo(void)
 	OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode);
 	OFFSET(LGUEST_PAGES_regs, lguest_pages, regs);
 #endif
-
-	BLANK();
-	OFFSET(BP_scratch, boot_params, scratch);
-	OFFSET(BP_loadflags, boot_params, hdr.loadflags);
-	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
-	OFFSET(BP_version, boot_params, hdr.version);
-	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
 }
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index 4a6aeed..e72a119 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -1,27 +1,4 @@
-/*
- * Generate definitions needed by assembly language modules.
- * This code generates raw asm output which is post-processed to extract
- * and format the required data.
- */
-#define COMPILE_OFFSETS
-
-#include <linux/crypto.h>
-#include <linux/sched.h> 
-#include <linux/stddef.h>
-#include <linux/errno.h> 
-#include <linux/hardirq.h>
-#include <linux/suspend.h>
-#include <linux/kbuild.h>
-#include <asm/processor.h>
-#include <asm/segment.h>
-#include <asm/thread_info.h>
 #include <asm/ia32.h>
-#include <asm/bootparam.h>
-#include <asm/suspend.h>
-
-#include <xen/interface/xen.h>
-
-#include <asm/sigframe.h>
 
 #define __NO_STUBS 1
 #undef __SYSCALL
@@ -33,41 +10,19 @@ static char syscalls[] = {
 
 int main(void)
 {
-#define ENTRY(entry) DEFINE(tsk_ ## entry, offsetof(struct task_struct, entry))
-	ENTRY(state);
-	ENTRY(flags); 
-	ENTRY(pid);
-	BLANK();
-#undef ENTRY
-#define ENTRY(entry) DEFINE(TI_ ## entry, offsetof(struct thread_info, entry))
-	ENTRY(flags);
-	ENTRY(addr_limit);
-	ENTRY(preempt_count);
-	ENTRY(status);
-#ifdef CONFIG_IA32_EMULATION
-	ENTRY(sysenter_return);
-#endif
-	BLANK();
-#undef ENTRY
 #ifdef CONFIG_PARAVIRT
-	BLANK();
-	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
-	OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
-	OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
-	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
-	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
 	OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame);
-	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
 	OFFSET(PV_CPU_usergs_sysret32, pv_cpu_ops, usergs_sysret32);
 	OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64);
-	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
 	OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
-	OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
+	BLANK();
 #endif
 
-
 #ifdef CONFIG_IA32_EMULATION
-#define ENTRY(entry) DEFINE(IA32_SIGCONTEXT_ ## entry, offsetof(struct sigcontext_ia32, entry))
+	OFFSET(TI_sysenter_return, thread_info, sysenter_return);
+	BLANK();
+
+#define ENTRY(entry) OFFSET(IA32_SIGCONTEXT_ ## entry, sigcontext_ia32, entry)
 	ENTRY(ax);
 	ENTRY(bx);
 	ENTRY(cx);
@@ -79,15 +34,12 @@ int main(void)
 	ENTRY(ip);
 	BLANK();
 #undef ENTRY
-	DEFINE(IA32_RT_SIGFRAME_sigcontext,
-	       offsetof (struct rt_sigframe_ia32, uc.uc_mcontext));
+
+	OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext);
 	BLANK();
 #endif
-	DEFINE(pbe_address, offsetof(struct pbe, address));
-	DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
-	DEFINE(pbe_next, offsetof(struct pbe, next));
-	BLANK();
-#define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry))
+
+#define ENTRY(entry) OFFSET(pt_regs_ ## entry, pt_regs, entry)
 	ENTRY(bx);
 	ENTRY(bx);
 	ENTRY(cx);
@@ -107,7 +59,8 @@ int main(void)
 	ENTRY(flags);
 	BLANK();
 #undef ENTRY
-#define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry))
+
+#define ENTRY(entry) OFFSET(saved_context_ ## entry, saved_context, entry)
 	ENTRY(cr0);
 	ENTRY(cr2);
 	ENTRY(cr3);
@@ -115,26 +68,11 @@ int main(void)
 	ENTRY(cr8);
 	BLANK();
 #undef ENTRY
-	DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist));
-	BLANK();
-	DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
-	BLANK();
-	DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
 
+	OFFSET(TSS_ist, tss_struct, x86_tss.ist);
 	BLANK();
-	OFFSET(BP_scratch, boot_params, scratch);
-	OFFSET(BP_loadflags, boot_params, hdr.loadflags);
-	OFFSET(BP_hardware_subarch, boot_params, hdr.hardware_subarch);
-	OFFSET(BP_version, boot_params, hdr.version);
-	OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
 
-	BLANK();
-	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
-#ifdef CONFIG_XEN
-	BLANK();
-	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
-	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
-#undef ENTRY
-#endif
+	DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+
 	return 0;
 }
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 7c7bedb..3ecece0 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -233,18 +233,22 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c)
 }
 #endif
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
+/*
+ * To workaround broken NUMA config.  Read the comment in
+ * srat_detect_node().
+ */
 static int __cpuinit nearby_node(int apicid)
 {
 	int i, node;
 
 	for (i = apicid - 1; i >= 0; i--) {
-		node = apicid_to_node[i];
+		node = __apicid_to_node[i];
 		if (node != NUMA_NO_NODE && node_online(node))
 			return node;
 	}
 	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
-		node = apicid_to_node[i];
+		node = __apicid_to_node[i];
 		if (node != NUMA_NO_NODE && node_online(node))
 			return node;
 	}
@@ -261,7 +265,7 @@ static int __cpuinit nearby_node(int apicid)
 #ifdef CONFIG_X86_HT
 static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 {
-	u32 nodes;
+	u32 nodes, cores_per_cu = 1;
 	u8 node_id;
 	int cpu = smp_processor_id();
 
@@ -276,6 +280,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 		/* get compute unit information */
 		smp_num_siblings = ((ebx >> 8) & 3) + 1;
 		c->compute_unit_id = ebx & 0xff;
+		cores_per_cu += ((ebx >> 8) & 3);
 	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
 		u64 value;
 
@@ -288,15 +293,18 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 	/* fixup multi-node processor information */
 	if (nodes > 1) {
 		u32 cores_per_node;
+		u32 cus_per_node;
 
 		set_cpu_cap(c, X86_FEATURE_AMD_DCM);
 		cores_per_node = c->x86_max_cores / nodes;
+		cus_per_node = cores_per_node / cores_per_cu;
 
 		/* store NodeID, use llc_shared_map to store sibling info */
 		per_cpu(cpu_llc_id, cpu) = node_id;
 
-		/* core id to be in range from 0 to (cores_per_node - 1) */
-		c->cpu_core_id = c->cpu_core_id % cores_per_node;
+		/* core id has to be in the [0 .. cores_per_node - 1] range */
+		c->cpu_core_id %= cores_per_node;
+		c->compute_unit_id %= cus_per_node;
 	}
 }
 #endif
@@ -334,31 +342,40 @@ EXPORT_SYMBOL_GPL(amd_get_nb_id);
 
 static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 {
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
 	int cpu = smp_processor_id();
 	int node;
 	unsigned apicid = c->apicid;
 
-	node = per_cpu(cpu_llc_id, cpu);
+	node = numa_cpu_node(cpu);
+	if (node == NUMA_NO_NODE)
+		node = per_cpu(cpu_llc_id, cpu);
 
-	if (apicid_to_node[apicid] != NUMA_NO_NODE)
-		node = apicid_to_node[apicid];
 	if (!node_online(node)) {
-		/* Two possibilities here:
-		   - The CPU is missing memory and no node was created.
-		   In that case try picking one from a nearby CPU
-		   - The APIC IDs differ from the HyperTransport node IDs
-		   which the K8 northbridge parsing fills in.
-		   Assume they are all increased by a constant offset,
-		   but in the same order as the HT nodeids.
-		   If that doesn't result in a usable node fall back to the
-		   path for the previous case.  */
-
+		/*
+		 * Two possibilities here:
+		 *
+		 * - The CPU is missing memory and no node was created.  In
+		 *   that case try picking one from a nearby CPU.
+		 *
+		 * - The APIC IDs differ from the HyperTransport node IDs
+		 *   which the K8 northbridge parsing fills in.  Assume
+		 *   they are all increased by a constant offset, but in
+		 *   the same order as the HT nodeids.  If that doesn't
+		 *   result in a usable node fall back to the path for the
+		 *   previous case.
+		 *
+		 * This workaround operates directly on the mapping between
+		 * APIC ID and NUMA node, assuming certain relationship
+		 * between APIC ID, HT node ID and NUMA topology.  As going
+		 * through CPU mapping may alter the outcome, directly
+		 * access __apicid_to_node[].
+		 */
 		int ht_nodeid = c->initial_apicid;
 
 		if (ht_nodeid >= 0 &&
-		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
-			node = apicid_to_node[ht_nodeid];
+		    __apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+			node = __apicid_to_node[ht_nodeid];
 		/* Pick a nearby node */
 		if (!node_online(node))
 			node = nearby_node(apicid);
@@ -594,6 +611,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 		}
 	}
 #endif
+
+	/* As a rule processors have APIC timer running in deep C states */
+	if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400))
+		set_cpu_cap(c, X86_FEATURE_ARAT);
 }
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1d59834..e2ced00 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -675,7 +675,7 @@ void __init early_cpu_init(void)
 	const struct cpu_dev *const *cdev;
 	int count = 0;
 
-#ifdef PROCESSOR_SELECT
+#ifdef CONFIG_PROCESSOR_SELECT
 	printk(KERN_INFO "KERNEL supported cpus:\n");
 #endif
 
@@ -687,7 +687,7 @@ void __init early_cpu_init(void)
 		cpu_devs[count] = cpudev;
 		count++;
 
-#ifdef PROCESSOR_SELECT
+#ifdef CONFIG_PROCESSOR_SELECT
 		{
 			unsigned int j;
 
@@ -869,7 +869,7 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 
 	select_idle_routine(c);
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
 	numa_add_cpu(smp_processor_id());
 #endif
 }
diff --git a/arch/x86/kernel/cpu/cpufreq/longhaul.c b/arch/x86/kernel/cpu/cpufreq/longhaul.c
index 03162da..cf48cdd 100644
--- a/arch/x86/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/x86/kernel/cpu/cpufreq/longhaul.c
@@ -444,7 +444,7 @@ static int __cpuinit longhaul_get_ranges(void)
 		return -EINVAL;
 	}
 	/* Get max multiplier - as we always did.
-	 * Longhaul MSR is usefull only when voltage scaling is enabled.
+	 * Longhaul MSR is useful only when voltage scaling is enabled.
 	 * C3 is booting at max anyway. */
 	maxmult = mult;
 	/* Get min multiplier */
@@ -1011,7 +1011,7 @@ static void __exit longhaul_exit(void)
  * trigger frequency transition in some cases. */
 module_param(disable_acpi_c3, int, 0644);
 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
-/* Change CPU voltage with frequency. Very usefull to save
+/* Change CPU voltage with frequency. Very useful to save
  * power, but most VIA C3 processors aren't supporting it. */
 module_param(scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
index 4a5a42b..755a31e 100644
--- a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
+++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
@@ -315,8 +315,6 @@ static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
 
 	input.count = 4;
 	input.pointer = in_params;
-	input.count = 4;
-	input.pointer = in_params;
 	in_params[0].type               = ACPI_TYPE_BUFFER;
 	in_params[0].buffer.length      = 16;
 	in_params[0].buffer.pointer     = OSC_UUID;
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index c567dec..2368e38 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -630,8 +630,7 @@ static void print_basics(struct powernow_k8_data *data)
 					data->powernow_table[j].frequency/1000);
 			} else {
 				printk(KERN_INFO PFX
-					"   %d : fid 0x%x (%d MHz), vid 0x%x\n",
-					j,
+					"fid 0x%x (%d MHz), vid 0x%x\n",
 					data->powernow_table[j].index & 0xff,
 					data->powernow_table[j].frequency/1000,
 					data->powernow_table[j].index >> 8);
@@ -1276,7 +1275,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
 
 	if (powernow_k8_cpu_init_acpi(data)) {
 		/*
-		 * Use the PSB BIOS structure. This is only availabe on
+		 * Use the PSB BIOS structure. This is only available on
 		 * an UP version, and is deprecated by AMD.
 		 */
 		if (num_online_cpus() != 1) {
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
index 8abd869..91bc25b 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
@@ -292,7 +292,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
 
 	result = speedstep_smi_ownership();
 	if (result) {
-		dprintk("fails in aquiring ownership of a SMI interface.\n");
+		dprintk("fails in acquiring ownership of a SMI interface.\n");
 		return -EINVAL;
 	}
 
@@ -360,7 +360,7 @@ static int speedstep_resume(struct cpufreq_policy *policy)
 	int result = speedstep_smi_ownership();
 
 	if (result)
-		dprintk("fails in re-aquiring ownership of a SMI interface.\n");
+		dprintk("fails in re-acquiring ownership of a SMI interface.\n");
 
 	return result;
 }
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index d16c2c5..df86bc8 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -276,14 +276,13 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
 
 static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 {
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
 	unsigned node;
 	int cpu = smp_processor_id();
-	int apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
 
 	/* Don't do the funky fallback heuristics the AMD version employs
 	   for now. */
-	node = apicid_to_node[apicid];
+	node = numa_cpu_node(cpu);
 	if (node == NUMA_NO_NODE || !node_online(node)) {
 		/* reuse the value from init_cpu_to_node() */
 		node = cpu_to_node(cpu);
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index ec2c19a..1ce1af2 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -304,8 +304,9 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
 
 struct _cache_attr {
 	struct attribute attr;
-	ssize_t (*show)(struct _cpuid4_info *, char *);
-	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+	ssize_t (*show)(struct _cpuid4_info *, char *, unsigned int);
+	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count,
+			 unsigned int);
 };
 
 #ifdef CONFIG_AMD_NB
@@ -400,7 +401,8 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,
 
 #define SHOW_CACHE_DISABLE(slot)					\
 static ssize_t								\
-show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf)	\
+show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf,	\
+			  unsigned int cpu)				\
 {									\
 	return show_cache_disable(this_leaf, buf, slot);		\
 }
@@ -512,7 +514,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
 #define STORE_CACHE_DISABLE(slot)					\
 static ssize_t								\
 store_cache_disable_##slot(struct _cpuid4_info *this_leaf,		\
-			   const char *buf, size_t count)		\
+			   const char *buf, size_t count,		\
+			   unsigned int cpu)				\
 {									\
 	return store_cache_disable(this_leaf, buf, count, slot);	\
 }
@@ -524,6 +527,39 @@ static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
 static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
 		show_cache_disable_1, store_cache_disable_1);
 
+static ssize_t
+show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
+{
+	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		return -EINVAL;
+
+	return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
+}
+
+static ssize_t
+store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
+		unsigned int cpu)
+{
+	unsigned long val;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		return -EINVAL;
+
+	if (strict_strtoul(buf, 16, &val) < 0)
+		return -EINVAL;
+
+	if (amd_set_subcaches(cpu, val))
+		return -EINVAL;
+
+	return count;
+}
+
+static struct _cache_attr subcaches =
+	__ATTR(subcaches, 0644, show_subcaches, store_subcaches);
+
 #else	/* CONFIG_AMD_NB */
 #define amd_init_l3_cache(x, y)
 #endif /* CONFIG_AMD_NB */
@@ -532,9 +568,9 @@ static int
 __cpuinit cpuid4_cache_lookup_regs(int index,
 				   struct _cpuid4_info_regs *this_leaf)
 {
-	union _cpuid4_leaf_eax 	eax;
-	union _cpuid4_leaf_ebx 	ebx;
-	union _cpuid4_leaf_ecx 	ecx;
+	union _cpuid4_leaf_eax	eax;
+	union _cpuid4_leaf_ebx	ebx;
+	union _cpuid4_leaf_ecx	ecx;
 	unsigned		edx;
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
@@ -732,11 +768,11 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) {
-		for_each_cpu(i, c->llc_shared_map) {
+		for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
 			if (!per_cpu(ici_cpuid4_info, i))
 				continue;
 			this_leaf = CPUID4_INFO_IDX(i, index);
-			for_each_cpu(sibling, c->llc_shared_map) {
+			for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
 				if (!cpu_online(sibling))
 					continue;
 				set_bit(sibling, this_leaf->shared_cpu_map);
@@ -870,8 +906,8 @@ static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject);
 #define INDEX_KOBJECT_PTR(x, y)		(&((per_cpu(ici_index_kobject, x))[y]))
 
 #define show_one_plus(file_name, object, val)				\
-static ssize_t show_##file_name						\
-			(struct _cpuid4_info *this_leaf, char *buf)	\
+static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \
+				unsigned int cpu)			\
 {									\
 	return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
 }
@@ -882,7 +918,8 @@ show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
 show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
 show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
 
-static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
+			 unsigned int cpu)
 {
 	return sprintf(buf, "%luK\n", this_leaf->size / 1024);
 }
@@ -906,17 +943,20 @@ static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
 	return n;
 }
 
-static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
+static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf,
+					  unsigned int cpu)
 {
 	return show_shared_cpu_map_func(leaf, 0, buf);
 }
 
-static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
+static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf,
+					   unsigned int cpu)
 {
 	return show_shared_cpu_map_func(leaf, 1, buf);
 }
 
-static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf)
+static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
+			 unsigned int cpu)
 {
 	switch (this_leaf->eax.split.type) {
 	case CACHE_TYPE_DATA:
@@ -974,6 +1014,9 @@ static struct attribute ** __cpuinit amd_l3_attrs(void)
 	if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		n += 2;
 
+	if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		n += 1;
+
 	attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL);
 	if (attrs == NULL)
 		return attrs = default_attrs;
@@ -986,6 +1029,9 @@ static struct attribute ** __cpuinit amd_l3_attrs(void)
 		attrs[n++] = &cache_disable_1.attr;
 	}
 
+	if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		attrs[n++] = &subcaches.attr;
+
 	return attrs;
 }
 #endif
@@ -998,7 +1044,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 
 	ret = fattr->show ?
 		fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
-			buf) :
+			buf, this_leaf->cpu) :
 		0;
 	return ret;
 }
@@ -1012,7 +1058,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 
 	ret = fattr->store ?
 		fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
-			buf, count) :
+			buf, count, this_leaf->cpu) :
 		0;
 	return ret;
 }
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index a779719..0ed633c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -32,7 +32,7 @@ static void inject_mce(struct mce *m)
 {
 	struct mce *i = &per_cpu(injectm, m->extcpu);
 
-	/* Make sure noone reads partially written injectm */
+	/* Make sure no one reads partially written injectm */
 	i->finished = 0;
 	mb();
 	m->finished = 0;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index d916183..ab11229 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -881,7 +881,7 @@ reset:
  * Check if the address reported by the CPU is in a format we can parse.
  * It would be possible to add code for most other cases, but all would
  * be somewhat complicated (e.g. segment offset would require an instruction
- * parser). So only support physical addresses upto page granuality for now.
+ * parser). So only support physical addresses up to page granuality for now.
  */
 static int mce_usable_address(struct mce *m)
 {
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 5bf2fac..167f97b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -527,15 +527,12 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 	int i, err = 0;
 	struct threshold_bank *b = NULL;
 	char name[32];
-#ifdef CONFIG_SMP
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
-#endif
 
 	sprintf(name, "threshold_bank%i", bank);
 
 #ifdef CONFIG_SMP
 	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
-		i = cpumask_first(c->llc_shared_map);
+		i = cpumask_first(cpu_llc_shared_mask(cpu));
 
 		/* first core not up yet */
 		if (cpu_data(i).cpu_core_id)
@@ -555,7 +552,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 		if (err)
 			goto out;
 
-		cpumask_copy(b->cpus, c->llc_shared_map);
+		cpumask_copy(b->cpus, cpu_llc_shared_mask(cpu));
 		per_cpu(threshold_banks, cpu)[bank] = b;
 
 		goto out;
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 9f27228..a71efcdb 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -1,6 +1,6 @@
 /*
  * This only handles 32bit MTRR on 32bit hosts. This is strictly wrong
- * because MTRRs can span upto 40 bits (36bits on most modern x86)
+ * because MTRRs can span up to 40 bits (36bits on most modern x86)
  */
 #define DEBUG
 
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 9d977a2..87eab4a 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -30,6 +30,7 @@
 #include <asm/stacktrace.h>
 #include <asm/nmi.h>
 #include <asm/compat.h>
+#include <asm/smp.h>
 
 #if 0
 #undef wrmsrl
@@ -93,6 +94,8 @@ struct amd_nb {
 	struct event_constraint event_constraints[X86_PMC_IDX_MAX];
 };
 
+struct intel_percore;
+
 #define MAX_LBR_ENTRIES		16
 
 struct cpu_hw_events {
@@ -128,6 +131,13 @@ struct cpu_hw_events {
 	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
 
 	/*
+	 * Intel percore register state.
+	 * Coordinate shared resources between HT threads.
+	 */
+	int				percore_used; /* Used by this CPU? */
+	struct intel_percore		*per_core;
+
+	/*
 	 * AMD specific bits
 	 */
 	struct amd_nb		*amd_nb;
@@ -166,7 +176,7 @@ struct cpu_hw_events {
 /*
  * Constraint on the Event code + UMask
  */
-#define PEBS_EVENT_CONSTRAINT(c, n)	\
+#define INTEL_UEVENT_CONSTRAINT(c, n)	\
 	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
 
 #define EVENT_CONSTRAINT_END		\
@@ -175,6 +185,28 @@ struct cpu_hw_events {
 #define for_each_event_constraint(e, c)	\
 	for ((e) = (c); (e)->weight; (e)++)
 
+/*
+ * Extra registers for specific events.
+ * Some events need large masks and require external MSRs.
+ * Define a mapping to these extra registers.
+ */
+struct extra_reg {
+	unsigned int		event;
+	unsigned int		msr;
+	u64			config_mask;
+	u64			valid_mask;
+};
+
+#define EVENT_EXTRA_REG(e, ms, m, vm) {	\
+	.event = (e),		\
+	.msr = (ms),		\
+	.config_mask = (m),	\
+	.valid_mask = (vm),	\
+	}
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm)	\
+	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm)
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0)
+
 union perf_capabilities {
 	struct {
 		u64	lbr_format    : 6;
@@ -219,6 +251,7 @@ struct x86_pmu {
 	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
 						 struct perf_event *event);
 	struct event_constraint *event_constraints;
+	struct event_constraint *percore_constraints;
 	void		(*quirks)(void);
 	int		perfctr_second_write;
 
@@ -247,6 +280,11 @@ struct x86_pmu {
 	 */
 	unsigned long	lbr_tos, lbr_from, lbr_to; /* MSR base regs       */
 	int		lbr_nr;			   /* hardware stack size */
+
+	/*
+	 * Extra registers for events
+	 */
+	struct extra_reg *extra_regs;
 };
 
 static struct x86_pmu x86_pmu __read_mostly;
@@ -271,6 +309,10 @@ static u64 __read_mostly hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+static u64 __read_mostly hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
 /*
  * Propagate event elapsed time into the generic event.
@@ -298,7 +340,7 @@ x86_perf_event_update(struct perf_event *event)
 	 */
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
-	rdmsrl(hwc->event_base + idx, new_raw_count);
+	rdmsrl(hwc->event_base, new_raw_count);
 
 	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
 					new_raw_count) != prev_raw_count)
@@ -321,6 +363,49 @@ again:
 	return new_raw_count;
 }
 
+/* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */
+static inline int x86_pmu_addr_offset(int index)
+{
+	if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
+		return index << 1;
+	return index;
+}
+
+static inline unsigned int x86_pmu_config_addr(int index)
+{
+	return x86_pmu.eventsel + x86_pmu_addr_offset(index);
+}
+
+static inline unsigned int x86_pmu_event_addr(int index)
+{
+	return x86_pmu.perfctr + x86_pmu_addr_offset(index);
+}
+
+/*
+ * Find and validate any extra registers to set up.
+ */
+static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
+{
+	struct extra_reg *er;
+
+	event->hw.extra_reg = 0;
+	event->hw.extra_config = 0;
+
+	if (!x86_pmu.extra_regs)
+		return 0;
+
+	for (er = x86_pmu.extra_regs; er->msr; er++) {
+		if (er->event != (config & er->config_mask))
+			continue;
+		if (event->attr.config1 & ~er->valid_mask)
+			return -EINVAL;
+		event->hw.extra_reg = er->msr;
+		event->hw.extra_config = event->attr.config1;
+		break;
+	}
+	return 0;
+}
+
 static atomic_t active_events;
 static DEFINE_MUTEX(pmc_reserve_mutex);
 
@@ -331,12 +416,12 @@ static bool reserve_pmc_hardware(void)
 	int i;
 
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
+		if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
 			goto perfctr_fail;
 	}
 
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
+		if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
 			goto eventsel_fail;
 	}
 
@@ -344,13 +429,13 @@ static bool reserve_pmc_hardware(void)
 
 eventsel_fail:
 	for (i--; i >= 0; i--)
-		release_evntsel_nmi(x86_pmu.eventsel + i);
+		release_evntsel_nmi(x86_pmu_config_addr(i));
 
 	i = x86_pmu.num_counters;
 
 perfctr_fail:
 	for (i--; i >= 0; i--)
-		release_perfctr_nmi(x86_pmu.perfctr + i);
+		release_perfctr_nmi(x86_pmu_event_addr(i));
 
 	return false;
 }
@@ -360,8 +445,8 @@ static void release_pmc_hardware(void)
 	int i;
 
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		release_perfctr_nmi(x86_pmu.perfctr + i);
-		release_evntsel_nmi(x86_pmu.eventsel + i);
+		release_perfctr_nmi(x86_pmu_event_addr(i));
+		release_evntsel_nmi(x86_pmu_config_addr(i));
 	}
 }
 
@@ -382,7 +467,7 @@ static bool check_hw_exists(void)
 	 * complain and bail.
 	 */
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		reg = x86_pmu.eventsel + i;
+		reg = x86_pmu_config_addr(i);
 		ret = rdmsrl_safe(reg, &val);
 		if (ret)
 			goto msr_fail;
@@ -407,8 +492,8 @@ static bool check_hw_exists(void)
 	 * that don't trap on the MSR access and always return 0s.
 	 */
 	val = 0xabcdUL;
-	ret = checking_wrmsrl(x86_pmu.perfctr, val);
-	ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new);
+	ret = checking_wrmsrl(x86_pmu_event_addr(0), val);
+	ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new);
 	if (ret || val != val_new)
 		goto msr_fail;
 
@@ -442,8 +527,9 @@ static inline int x86_pmu_initialized(void)
 }
 
 static inline int
-set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr)
+set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
 {
+	struct perf_event_attr *attr = &event->attr;
 	unsigned int cache_type, cache_op, cache_result;
 	u64 config, val;
 
@@ -470,8 +556,8 @@ set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr)
 		return -EINVAL;
 
 	hwc->config |= val;
-
-	return 0;
+	attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
+	return x86_pmu_extra_regs(val, event);
 }
 
 static int x86_setup_perfctr(struct perf_event *event)
@@ -496,10 +582,10 @@ static int x86_setup_perfctr(struct perf_event *event)
 	}
 
 	if (attr->type == PERF_TYPE_RAW)
-		return 0;
+		return x86_pmu_extra_regs(event->attr.config, event);
 
 	if (attr->type == PERF_TYPE_HW_CACHE)
-		return set_ext_hw_attr(hwc, attr);
+		return set_ext_hw_attr(hwc, event);
 
 	if (attr->config >= x86_pmu.max_events)
 		return -EINVAL;
@@ -617,11 +703,11 @@ static void x86_pmu_disable_all(void)
 
 		if (!test_bit(idx, cpuc->active_mask))
 			continue;
-		rdmsrl(x86_pmu.eventsel + idx, val);
+		rdmsrl(x86_pmu_config_addr(idx), val);
 		if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
 			continue;
 		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-		wrmsrl(x86_pmu.eventsel + idx, val);
+		wrmsrl(x86_pmu_config_addr(idx), val);
 	}
 }
 
@@ -642,21 +728,26 @@ static void x86_pmu_disable(struct pmu *pmu)
 	x86_pmu.disable_all();
 }
 
+static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
+					  u64 enable_mask)
+{
+	if (hwc->extra_reg)
+		wrmsrl(hwc->extra_reg, hwc->extra_config);
+	wrmsrl(hwc->config_base, hwc->config | enable_mask);
+}
+
 static void x86_pmu_enable_all(int added)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx;
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-		struct perf_event *event = cpuc->events[idx];
-		u64 val;
+		struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
 
 		if (!test_bit(idx, cpuc->active_mask))
 			continue;
 
-		val = event->hw.config;
-		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-		wrmsrl(x86_pmu.eventsel + idx, val);
+		__x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
 	}
 }
 
@@ -821,15 +912,10 @@ static inline void x86_assign_hw_event(struct perf_event *event,
 		hwc->event_base	= 0;
 	} else if (hwc->idx >= X86_PMC_IDX_FIXED) {
 		hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
-		/*
-		 * We set it so that event_base + idx in wrmsr/rdmsr maps to
-		 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
-		 */
-		hwc->event_base =
-			MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
+		hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0;
 	} else {
-		hwc->config_base = x86_pmu.eventsel;
-		hwc->event_base  = x86_pmu.perfctr;
+		hwc->config_base = x86_pmu_config_addr(hwc->idx);
+		hwc->event_base  = x86_pmu_event_addr(hwc->idx);
 	}
 }
 
@@ -915,17 +1001,11 @@ static void x86_pmu_enable(struct pmu *pmu)
 	x86_pmu.enable_all(added);
 }
 
-static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
-					  u64 enable_mask)
-{
-	wrmsrl(hwc->config_base + hwc->idx, hwc->config | enable_mask);
-}
-
 static inline void x86_pmu_disable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 
-	wrmsrl(hwc->config_base + hwc->idx, hwc->config);
+	wrmsrl(hwc->config_base, hwc->config);
 }
 
 static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
@@ -978,7 +1058,7 @@ x86_perf_event_set_period(struct perf_event *event)
 	 */
 	local64_set(&hwc->prev_count, (u64)-left);
 
-	wrmsrl(hwc->event_base + idx, (u64)(-left) & x86_pmu.cntval_mask);
+	wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
 
 	/*
 	 * Due to erratum on certan cpu we need
@@ -986,7 +1066,7 @@ x86_perf_event_set_period(struct perf_event *event)
 	 * is updated properly
 	 */
 	if (x86_pmu.perfctr_second_write) {
-		wrmsrl(hwc->event_base + idx,
+		wrmsrl(hwc->event_base,
 			(u64)(-left) & x86_pmu.cntval_mask);
 	}
 
@@ -1029,7 +1109,7 @@ static int x86_pmu_add(struct perf_event *event, int flags)
 
 	/*
 	 * If group events scheduling transaction was started,
-	 * skip the schedulability test here, it will be peformed
+	 * skip the schedulability test here, it will be performed
 	 * at commit time (->commit_txn) as a whole
 	 */
 	if (cpuc->group_flag & PERF_EVENT_TXN)
@@ -1113,8 +1193,8 @@ void perf_event_print_debug(void)
 	pr_info("CPU#%d: active:     %016llx\n", cpu, *(u64 *)cpuc->active_mask);
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-		rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl);
-		rdmsrl(x86_pmu.perfctr  + idx, pmc_count);
+		rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
+		rdmsrl(x86_pmu_event_addr(idx), pmc_count);
 
 		prev_left = per_cpu(pmc_prev_left[idx], cpu);
 
@@ -1389,7 +1469,7 @@ static void __init pmu_check_apic(void)
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-int __init init_hw_perf_events(void)
+static int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1608,7 +1688,7 @@ out:
 	return ret;
 }
 
-int x86_pmu_event_init(struct perf_event *event)
+static int x86_pmu_event_init(struct perf_event *event)
 {
 	struct pmu *tmp;
 	int err;
@@ -1710,7 +1790,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 
 	perf_callchain_store(entry, regs->ip);
 
-	dump_trace(NULL, regs, NULL, &backtrace_ops, entry);
+	dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry);
 }
 
 #ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index 67e2202..461f62b 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -127,6 +127,11 @@ static int amd_pmu_hw_config(struct perf_event *event)
 /*
  * AMD64 events are detected based on their event codes.
  */
+static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
+{
+	return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
+}
+
 static inline int amd_is_nb_event(struct hw_perf_event *hwc)
 {
 	return (hwc->config & 0xe0) == 0xe0;
@@ -385,13 +390,181 @@ static __initconst const struct x86_pmu amd_pmu = {
 	.cpu_dead		= amd_pmu_cpu_dead,
 };
 
+/* AMD Family 15h */
+
+#define AMD_EVENT_TYPE_MASK	0x000000F0ULL
+
+#define AMD_EVENT_FP		0x00000000ULL ... 0x00000010ULL
+#define AMD_EVENT_LS		0x00000020ULL ... 0x00000030ULL
+#define AMD_EVENT_DC		0x00000040ULL ... 0x00000050ULL
+#define AMD_EVENT_CU		0x00000060ULL ... 0x00000070ULL
+#define AMD_EVENT_IC_DE		0x00000080ULL ... 0x00000090ULL
+#define AMD_EVENT_EX_LS		0x000000C0ULL
+#define AMD_EVENT_DE		0x000000D0ULL
+#define AMD_EVENT_NB		0x000000E0ULL ... 0x000000F0ULL
+
+/*
+ * AMD family 15h event code/PMC mappings:
+ *
+ * type = event_code & 0x0F0:
+ *
+ * 0x000	FP	PERF_CTL[5:3]
+ * 0x010	FP	PERF_CTL[5:3]
+ * 0x020	LS	PERF_CTL[5:0]
+ * 0x030	LS	PERF_CTL[5:0]
+ * 0x040	DC	PERF_CTL[5:0]
+ * 0x050	DC	PERF_CTL[5:0]
+ * 0x060	CU	PERF_CTL[2:0]
+ * 0x070	CU	PERF_CTL[2:0]
+ * 0x080	IC/DE	PERF_CTL[2:0]
+ * 0x090	IC/DE	PERF_CTL[2:0]
+ * 0x0A0	---
+ * 0x0B0	---
+ * 0x0C0	EX/LS	PERF_CTL[5:0]
+ * 0x0D0	DE	PERF_CTL[2:0]
+ * 0x0E0	NB	NB_PERF_CTL[3:0]
+ * 0x0F0	NB	NB_PERF_CTL[3:0]
+ *
+ * Exceptions:
+ *
+ * 0x003	FP	PERF_CTL[3]
+ * 0x00B	FP	PERF_CTL[3]
+ * 0x00D	FP	PERF_CTL[3]
+ * 0x023	DE	PERF_CTL[2:0]
+ * 0x02D	LS	PERF_CTL[3]
+ * 0x02E	LS	PERF_CTL[3,0]
+ * 0x043	CU	PERF_CTL[2:0]
+ * 0x045	CU	PERF_CTL[2:0]
+ * 0x046	CU	PERF_CTL[2:0]
+ * 0x054	CU	PERF_CTL[2:0]
+ * 0x055	CU	PERF_CTL[2:0]
+ * 0x08F	IC	PERF_CTL[0]
+ * 0x187	DE	PERF_CTL[0]
+ * 0x188	DE	PERF_CTL[0]
+ * 0x0DB	EX	PERF_CTL[5:0]
+ * 0x0DC	LS	PERF_CTL[5:0]
+ * 0x0DD	LS	PERF_CTL[5:0]
+ * 0x0DE	LS	PERF_CTL[5:0]
+ * 0x0DF	LS	PERF_CTL[5:0]
+ * 0x1D6	EX	PERF_CTL[5:0]
+ * 0x1D8	EX	PERF_CTL[5:0]
+ */
+
+static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
+static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
+static struct event_constraint amd_f15_PMC3  = EVENT_CONSTRAINT(0, 0x08, 0);
+static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT(0, 0x09, 0);
+static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
+static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
+
+static struct event_constraint *
+amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+	unsigned int event_code = amd_get_event_code(&event->hw);
+
+	switch (event_code & AMD_EVENT_TYPE_MASK) {
+	case AMD_EVENT_FP:
+		switch (event_code) {
+		case 0x003:
+		case 0x00B:
+		case 0x00D:
+			return &amd_f15_PMC3;
+		default:
+			return &amd_f15_PMC53;
+		}
+	case AMD_EVENT_LS:
+	case AMD_EVENT_DC:
+	case AMD_EVENT_EX_LS:
+		switch (event_code) {
+		case 0x023:
+		case 0x043:
+		case 0x045:
+		case 0x046:
+		case 0x054:
+		case 0x055:
+			return &amd_f15_PMC20;
+		case 0x02D:
+			return &amd_f15_PMC3;
+		case 0x02E:
+			return &amd_f15_PMC30;
+		default:
+			return &amd_f15_PMC50;
+		}
+	case AMD_EVENT_CU:
+	case AMD_EVENT_IC_DE:
+	case AMD_EVENT_DE:
+		switch (event_code) {
+		case 0x08F:
+		case 0x187:
+		case 0x188:
+			return &amd_f15_PMC0;
+		case 0x0DB ... 0x0DF:
+		case 0x1D6:
+		case 0x1D8:
+			return &amd_f15_PMC50;
+		default:
+			return &amd_f15_PMC20;
+		}
+	case AMD_EVENT_NB:
+		/* not yet implemented */
+		return &emptyconstraint;
+	default:
+		return &emptyconstraint;
+	}
+}
+
+static __initconst const struct x86_pmu amd_pmu_f15h = {
+	.name			= "AMD Family 15h",
+	.handle_irq		= x86_pmu_handle_irq,
+	.disable_all		= x86_pmu_disable_all,
+	.enable_all		= x86_pmu_enable_all,
+	.enable			= x86_pmu_enable_event,
+	.disable		= x86_pmu_disable_event,
+	.hw_config		= amd_pmu_hw_config,
+	.schedule_events	= x86_schedule_events,
+	.eventsel		= MSR_F15H_PERF_CTL,
+	.perfctr		= MSR_F15H_PERF_CTR,
+	.event_map		= amd_pmu_event_map,
+	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
+	.num_counters		= 6,
+	.cntval_bits		= 48,
+	.cntval_mask		= (1ULL << 48) - 1,
+	.apic			= 1,
+	/* use highest bit to detect overflow */
+	.max_period		= (1ULL << 47) - 1,
+	.get_event_constraints	= amd_get_event_constraints_f15h,
+	/* nortbridge counters not yet implemented: */
+#if 0
+	.put_event_constraints	= amd_put_event_constraints,
+
+	.cpu_prepare		= amd_pmu_cpu_prepare,
+	.cpu_starting		= amd_pmu_cpu_starting,
+	.cpu_dead		= amd_pmu_cpu_dead,
+#endif
+};
+
 static __init int amd_pmu_init(void)
 {
 	/* Performance-monitoring supported from K7 and later: */
 	if (boot_cpu_data.x86 < 6)
 		return -ENODEV;
 
-	x86_pmu = amd_pmu;
+	/*
+	 * If core performance counter extensions exists, it must be
+	 * family 15h, otherwise fail. See x86_pmu_addr_offset().
+	 */
+	switch (boot_cpu_data.x86) {
+	case 0x15:
+		if (!cpu_has_perfctr_core)
+			return -ENODEV;
+		x86_pmu = amd_pmu_f15h;
+		break;
+	default:
+		if (cpu_has_perfctr_core)
+			return -ENODEV;
+		x86_pmu = amd_pmu;
+		break;
+	}
 
 	/* Events are common for all AMDs */
 	memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 008835c..8fc2b2c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -1,5 +1,27 @@
 #ifdef CONFIG_CPU_SUP_INTEL
 
+#define MAX_EXTRA_REGS 2
+
+/*
+ * Per register state.
+ */
+struct er_account {
+	int			ref;		/* reference count */
+	unsigned int		extra_reg;	/* extra MSR number */
+	u64			extra_config;	/* extra MSR config */
+};
+
+/*
+ * Per core state
+ * This used to coordinate shared registers for HT threads.
+ */
+struct intel_percore {
+	raw_spinlock_t		lock;		/* protect structure */
+	struct er_account	regs[MAX_EXTRA_REGS];
+	int			refcnt;		/* number of threads */
+	unsigned		core_id;
+};
+
 /*
  * Intel PerfMon, used on Core and later.
  */
@@ -64,6 +86,18 @@ static struct event_constraint intel_nehalem_event_constraints[] =
 	EVENT_CONSTRAINT_END
 };
 
+static struct extra_reg intel_nehalem_extra_regs[] =
+{
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
+	EVENT_EXTRA_END
+};
+
+static struct event_constraint intel_nehalem_percore_constraints[] =
+{
+	INTEL_EVENT_CONSTRAINT(0xb7, 0),
+	EVENT_CONSTRAINT_END
+};
+
 static struct event_constraint intel_westmere_event_constraints[] =
 {
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -76,6 +110,33 @@ static struct event_constraint intel_westmere_event_constraints[] =
 	EVENT_CONSTRAINT_END
 };
 
+static struct event_constraint intel_snb_event_constraints[] =
+{
+	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+	/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
+	INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
+	INTEL_EVENT_CONSTRAINT(0xb7, 0x1), /* OFF_CORE_RESPONSE_0 */
+	INTEL_EVENT_CONSTRAINT(0xbb, 0x8), /* OFF_CORE_RESPONSE_1 */
+	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
+	INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
+	EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg intel_westmere_extra_regs[] =
+{
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
+	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff),
+	EVENT_EXTRA_END
+};
+
+static struct event_constraint intel_westmere_percore_constraints[] =
+{
+	INTEL_EVENT_CONSTRAINT(0xb7, 0),
+	INTEL_EVENT_CONSTRAINT(0xbb, 0),
+	EVENT_CONSTRAINT_END
+};
+
 static struct event_constraint intel_gen_event_constraints[] =
 {
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -89,6 +150,106 @@ static u64 intel_pmu_event_map(int hw_event)
 	return intel_perfmon_event_map[hw_event];
 }
 
+static __initconst const u64 snb_hw_cache_event_ids
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0xf1d0, /* MEM_UOP_RETIRED.LOADS        */
+		[ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPLACEMENT              */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0xf2d0, /* MEM_UOP_RETIRED.STORES       */
+		[ C(RESULT_MISS)   ] = 0x0851, /* L1D.ALL_M_REPLACEMENT        */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x024e, /* HW_PRE_REQ.DL1_MISS          */
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0280, /* ICACHE.MISSES */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(LL  ) ] = {
+	/*
+	 * TBD: Need Off-core Response Performance Monitoring support
+	 */
+	[ C(OP_READ) ] = {
+		/* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01bb,
+	},
+	[ C(OP_WRITE) ] = {
+		/* OFFCORE_RESPONSE_0.ANY_RFO.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE_1.ANY_RFO.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01bb,
+	},
+	[ C(OP_PREFETCH) ] = {
+		/* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01bb,
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOP_RETIRED.ALL_LOADS */
+		[ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.CAUSES_A_WALK */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOP_RETIRED.ALL_STORES */
+		[ C(RESULT_MISS)   ] = 0x0149, /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x1085, /* ITLB_MISSES.STLB_HIT         */
+		[ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.CAUSES_A_WALK    */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+ [ C(BPU ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
+		[ C(RESULT_MISS)   ] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
 static __initconst const u64 westmere_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -124,16 +285,26 @@ static __initconst const u64 westmere_hw_cache_event_ids
  },
  [ C(LL  ) ] = {
 	[ C(OP_READ) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS               */
-		[ C(RESULT_MISS)   ] = 0x0224, /* L2_RQSTS.LD_MISS             */
+		/* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01bb,
 	},
+	/*
+	 * Use RFO, not WRITEBACK, because a write miss would typically occur
+	 * on RFO.
+	 */
 	[ C(OP_WRITE) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS                */
-		[ C(RESULT_MISS)   ] = 0x0824, /* L2_RQSTS.RFO_MISS            */
+		/* OFFCORE_RESPONSE_1.ANY_RFO.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01bb,
+		/* OFFCORE_RESPONSE_0.ANY_RFO.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
 	[ C(OP_PREFETCH) ] = {
-		[ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference                */
-		[ C(RESULT_MISS)   ] = 0x412e, /* LLC Misses                   */
+		/* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01bb,
 	},
  },
  [ C(DTLB) ] = {
@@ -180,6 +351,39 @@ static __initconst const u64 westmere_hw_cache_event_ids
  },
 };
 
+/*
+ * OFFCORE_RESPONSE MSR bits (subset), See IA32 SDM Vol 3 30.6.1.3
+ */
+
+#define DMND_DATA_RD     (1 << 0)
+#define DMND_RFO         (1 << 1)
+#define DMND_WB          (1 << 3)
+#define PF_DATA_RD       (1 << 4)
+#define PF_DATA_RFO      (1 << 5)
+#define RESP_UNCORE_HIT  (1 << 8)
+#define RESP_MISS        (0xf600) /* non uncore hit */
+
+static __initconst const u64 nehalem_hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = DMND_DATA_RD|RESP_UNCORE_HIT,
+		[ C(RESULT_MISS)   ] = DMND_DATA_RD|RESP_MISS,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = DMND_RFO|DMND_WB|RESP_UNCORE_HIT,
+		[ C(RESULT_MISS)   ] = DMND_RFO|DMND_WB|RESP_MISS,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_UNCORE_HIT,
+		[ C(RESULT_MISS)   ] = PF_DATA_RD|PF_DATA_RFO|RESP_MISS,
+	},
+ }
+};
+
 static __initconst const u64 nehalem_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -215,16 +419,26 @@ static __initconst const u64 nehalem_hw_cache_event_ids
  },
  [ C(LL  ) ] = {
 	[ C(OP_READ) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS               */
-		[ C(RESULT_MISS)   ] = 0x0224, /* L2_RQSTS.LD_MISS             */
+		/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
+	/*
+	 * Use RFO, not WRITEBACK, because a write miss would typically occur
+	 * on RFO.
+	 */
 	[ C(OP_WRITE) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS                */
-		[ C(RESULT_MISS)   ] = 0x0824, /* L2_RQSTS.RFO_MISS            */
+		/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
 	[ C(OP_PREFETCH) ] = {
-		[ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference                */
-		[ C(RESULT_MISS)   ] = 0x412e, /* LLC Misses                   */
+		/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
  },
  [ C(DTLB) ] = {
@@ -691,8 +905,8 @@ static void intel_pmu_reset(void)
 	printk("clearing PMU state on CPU#%d\n", smp_processor_id());
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-		checking_wrmsrl(x86_pmu.eventsel + idx, 0ull);
-		checking_wrmsrl(x86_pmu.perfctr  + idx, 0ull);
+		checking_wrmsrl(x86_pmu_config_addr(idx), 0ull);
+		checking_wrmsrl(x86_pmu_event_addr(idx),  0ull);
 	}
 	for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
 		checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
@@ -794,6 +1008,67 @@ intel_bts_constraints(struct perf_event *event)
 }
 
 static struct event_constraint *
+intel_percore_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned int e = hwc->config & ARCH_PERFMON_EVENTSEL_EVENT;
+	struct event_constraint *c;
+	struct intel_percore *pc;
+	struct er_account *era;
+	int i;
+	int free_slot;
+	int found;
+
+	if (!x86_pmu.percore_constraints || hwc->extra_alloc)
+		return NULL;
+
+	for (c = x86_pmu.percore_constraints; c->cmask; c++) {
+		if (e != c->code)
+			continue;
+
+		/*
+		 * Allocate resource per core.
+		 */
+		pc = cpuc->per_core;
+		if (!pc)
+			break;
+		c = &emptyconstraint;
+		raw_spin_lock(&pc->lock);
+		free_slot = -1;
+		found = 0;
+		for (i = 0; i < MAX_EXTRA_REGS; i++) {
+			era = &pc->regs[i];
+			if (era->ref > 0 && hwc->extra_reg == era->extra_reg) {
+				/* Allow sharing same config */
+				if (hwc->extra_config == era->extra_config) {
+					era->ref++;
+					cpuc->percore_used = 1;
+					hwc->extra_alloc = 1;
+					c = NULL;
+				}
+				/* else conflict */
+				found = 1;
+				break;
+			} else if (era->ref == 0 && free_slot == -1)
+				free_slot = i;
+		}
+		if (!found && free_slot != -1) {
+			era = &pc->regs[free_slot];
+			era->ref = 1;
+			era->extra_reg = hwc->extra_reg;
+			era->extra_config = hwc->extra_config;
+			cpuc->percore_used = 1;
+			hwc->extra_alloc = 1;
+			c = NULL;
+		}
+		raw_spin_unlock(&pc->lock);
+		return c;
+	}
+
+	return NULL;
+}
+
+static struct event_constraint *
 intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
 	struct event_constraint *c;
@@ -806,9 +1081,51 @@ intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event
 	if (c)
 		return c;
 
+	c = intel_percore_constraints(cpuc, event);
+	if (c)
+		return c;
+
 	return x86_get_event_constraints(cpuc, event);
 }
 
+static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+					struct perf_event *event)
+{
+	struct extra_reg *er;
+	struct intel_percore *pc;
+	struct er_account *era;
+	struct hw_perf_event *hwc = &event->hw;
+	int i, allref;
+
+	if (!cpuc->percore_used)
+		return;
+
+	for (er = x86_pmu.extra_regs; er->msr; er++) {
+		if (er->event != (hwc->config & er->config_mask))
+			continue;
+
+		pc = cpuc->per_core;
+		raw_spin_lock(&pc->lock);
+		for (i = 0; i < MAX_EXTRA_REGS; i++) {
+			era = &pc->regs[i];
+			if (era->ref > 0 &&
+			    era->extra_config == hwc->extra_config &&
+			    era->extra_reg == er->msr) {
+				era->ref--;
+				hwc->extra_alloc = 0;
+				break;
+			}
+		}
+		allref = 0;
+		for (i = 0; i < MAX_EXTRA_REGS; i++)
+			allref += pc->regs[i].ref;
+		if (allref == 0)
+			cpuc->percore_used = 0;
+		raw_spin_unlock(&pc->lock);
+		break;
+	}
+}
+
 static int intel_pmu_hw_config(struct perf_event *event)
 {
 	int ret = x86_pmu_hw_config(event);
@@ -880,20 +1197,67 @@ static __initconst const struct x86_pmu core_pmu = {
 	 */
 	.max_period		= (1ULL << 31) - 1,
 	.get_event_constraints	= intel_get_event_constraints,
+	.put_event_constraints	= intel_put_event_constraints,
 	.event_constraints	= intel_core_event_constraints,
 };
 
+static int intel_pmu_cpu_prepare(int cpu)
+{
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+
+	if (!cpu_has_ht_siblings())
+		return NOTIFY_OK;
+
+	cpuc->per_core = kzalloc_node(sizeof(struct intel_percore),
+				      GFP_KERNEL, cpu_to_node(cpu));
+	if (!cpuc->per_core)
+		return NOTIFY_BAD;
+
+	raw_spin_lock_init(&cpuc->per_core->lock);
+	cpuc->per_core->core_id = -1;
+	return NOTIFY_OK;
+}
+
 static void intel_pmu_cpu_starting(int cpu)
 {
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+	int core_id = topology_core_id(cpu);
+	int i;
+
 	init_debug_store_on_cpu(cpu);
 	/*
 	 * Deal with CPUs that don't clear their LBRs on power-up.
 	 */
 	intel_pmu_lbr_reset();
+
+	if (!cpu_has_ht_siblings())
+		return;
+
+	for_each_cpu(i, topology_thread_cpumask(cpu)) {
+		struct intel_percore *pc = per_cpu(cpu_hw_events, i).per_core;
+
+		if (pc && pc->core_id == core_id) {
+			kfree(cpuc->per_core);
+			cpuc->per_core = pc;
+			break;
+		}
+	}
+
+	cpuc->per_core->core_id = core_id;
+	cpuc->per_core->refcnt++;
 }
 
 static void intel_pmu_cpu_dying(int cpu)
 {
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+	struct intel_percore *pc = cpuc->per_core;
+
+	if (pc) {
+		if (pc->core_id == -1 || --pc->refcnt == 0)
+			kfree(pc);
+		cpuc->per_core = NULL;
+	}
+
 	fini_debug_store_on_cpu(cpu);
 }
 
@@ -918,7 +1282,9 @@ static __initconst const struct x86_pmu intel_pmu = {
 	 */
 	.max_period		= (1ULL << 31) - 1,
 	.get_event_constraints	= intel_get_event_constraints,
+	.put_event_constraints	= intel_put_event_constraints,
 
+	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
 	.cpu_dying		= intel_pmu_cpu_dying,
 };
@@ -1024,6 +1390,7 @@ static __init int intel_pmu_init(void)
 		intel_pmu_lbr_init_core();
 
 		x86_pmu.event_constraints = intel_core2_event_constraints;
+		x86_pmu.pebs_constraints = intel_core2_pebs_event_constraints;
 		pr_cont("Core2 events, ");
 		break;
 
@@ -1032,11 +1399,16 @@ static __init int intel_pmu_init(void)
 	case 46: /* 45 nm nehalem-ex, "Beckton" */
 		memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
+		memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
+		       sizeof(hw_cache_extra_regs));
 
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_nehalem_event_constraints;
+		x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
+		x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
+		x86_pmu.extra_regs = intel_nehalem_extra_regs;
 		pr_cont("Nehalem events, ");
 		break;
 
@@ -1047,6 +1419,7 @@ static __init int intel_pmu_init(void)
 		intel_pmu_lbr_init_atom();
 
 		x86_pmu.event_constraints = intel_gen_event_constraints;
+		x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
 		pr_cont("Atom events, ");
 		break;
 
@@ -1054,14 +1427,30 @@ static __init int intel_pmu_init(void)
 	case 44: /* 32 nm nehalem, "Gulftown" */
 		memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
+		memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
+		       sizeof(hw_cache_extra_regs));
 
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_westmere_event_constraints;
+		x86_pmu.percore_constraints = intel_westmere_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
+		x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
+		x86_pmu.extra_regs = intel_westmere_extra_regs;
 		pr_cont("Westmere events, ");
 		break;
 
+	case 42: /* SandyBridge */
+		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+
+		intel_pmu_lbr_init_nhm();
+
+		x86_pmu.event_constraints = intel_snb_event_constraints;
+		x86_pmu.pebs_constraints = intel_snb_pebs_events;
+		pr_cont("SandyBridge events, ");
+		break;
+
 	default:
 		/*
 		 * default constraints for v2 and up
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index b7dcd9f..bab491b 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -361,30 +361,70 @@ static int intel_pmu_drain_bts_buffer(void)
 /*
  * PEBS
  */
+static struct event_constraint intel_core2_pebs_event_constraints[] = {
+	INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+	INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
+	INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
+	INTEL_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+	EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_atom_pebs_event_constraints[] = {
+	INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+	INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+	EVENT_CONSTRAINT_END
+};
 
-static struct event_constraint intel_core_pebs_events[] = {
-	PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INSTR_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
-	PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x01cb, 0x1), /* MEM_LOAD_RETIRED.L1D_MISS */
-	PEBS_EVENT_CONSTRAINT(0x02cb, 0x1), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x04cb, 0x1), /* MEM_LOAD_RETIRED.L2_MISS */
-	PEBS_EVENT_CONSTRAINT(0x08cb, 0x1), /* MEM_LOAD_RETIRED.L2_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x10cb, 0x1), /* MEM_LOAD_RETIRED.DTLB_MISS */
+static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
+	INTEL_EVENT_CONSTRAINT(0x0b, 0xf),    /* MEM_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+	INTEL_EVENT_CONSTRAINT(0xc0, 0xf),    /* INST_RETIRED.ANY */
+	INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
+	INTEL_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_nehalem_pebs_events[] = {
-	PEBS_EVENT_CONSTRAINT(0x00c0, 0xf), /* INSTR_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0xfec1, 0xf), /* X87_OPS_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x00c5, 0xf), /* BR_INST_RETIRED.MISPRED */
-	PEBS_EVENT_CONSTRAINT(0x1fc7, 0xf), /* SIMD_INST_RETURED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x01cb, 0xf), /* MEM_LOAD_RETIRED.L1D_MISS */
-	PEBS_EVENT_CONSTRAINT(0x02cb, 0xf), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x04cb, 0xf), /* MEM_LOAD_RETIRED.L2_MISS */
-	PEBS_EVENT_CONSTRAINT(0x08cb, 0xf), /* MEM_LOAD_RETIRED.L2_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x10cb, 0xf), /* MEM_LOAD_RETIRED.DTLB_MISS */
+static struct event_constraint intel_westmere_pebs_event_constraints[] = {
+	INTEL_EVENT_CONSTRAINT(0x0b, 0xf),    /* MEM_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+	INTEL_EVENT_CONSTRAINT(0xc0, 0xf),    /* INSTR_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+	EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_snb_pebs_events[] = {
+	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+	INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
+	INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
+	INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xcd, 0x8),    /* MEM_TRANS_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */
+	INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */
+	INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */
+	INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */
+	INTEL_EVENT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
 	EVENT_CONSTRAINT_END
 };
 
@@ -695,20 +735,17 @@ static void intel_ds_init(void)
 			printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
 			x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
 			x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
-			x86_pmu.pebs_constraints = intel_core_pebs_events;
 			break;
 
 		case 1:
 			printk(KERN_CONT "PEBS fmt1%c, ", pebs_type);
 			x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm);
 			x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
-			x86_pmu.pebs_constraints = intel_nehalem_pebs_events;
 			break;
 
 		default:
 			printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type);
 			x86_pmu.pebs = 0;
-			break;
 		}
 	}
 }
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index ff751a9..0811f5e 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -1,5 +1,5 @@
 /*
- * Netburst Perfomance Events (P4, old Xeon)
+ * Netburst Performance Events (P4, old Xeon)
  *
  *  Copyright (C) 2010 Parallels, Inc., Cyrill Gorcunov <gorcunov@openvz.org>
  *  Copyright (C) 2010 Intel Corporation, Lin Ming <ming.m.lin@intel.com>
@@ -679,7 +679,7 @@ static int p4_validate_raw_event(struct perf_event *event)
 	 */
 
 	/*
-	 * if an event is shared accross the logical threads
+	 * if an event is shared across the logical threads
 	 * the user needs special permissions to be able to use it
 	 */
 	if (p4_ht_active() && p4_event_bind_map[v].shared) {
@@ -764,9 +764,9 @@ static inline int p4_pmu_clear_cccr_ovf(struct hw_perf_event *hwc)
 	u64 v;
 
 	/* an official way for overflow indication */
-	rdmsrl(hwc->config_base + hwc->idx, v);
+	rdmsrl(hwc->config_base, v);
 	if (v & P4_CCCR_OVF) {
-		wrmsrl(hwc->config_base + hwc->idx, v & ~P4_CCCR_OVF);
+		wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
 		return 1;
 	}
 
@@ -790,13 +790,13 @@ static void p4_pmu_disable_pebs(void)
 	 *
 	 * It's still allowed that two threads setup same cache
 	 * events so we can't simply clear metrics until we knew
-	 * noone is depending on us, so we need kind of counter
+	 * no one is depending on us, so we need kind of counter
 	 * for "ReplayEvent" users.
 	 *
 	 * What is more complex -- RAW events, if user (for some
 	 * reason) will pass some cache event metric with improper
 	 * event opcode -- it's fine from hardware point of view
-	 * but completely nonsence from "meaning" of such action.
+	 * but completely nonsense from "meaning" of such action.
 	 *
 	 * So at moment let leave metrics turned on forever -- it's
 	 * ok for now but need to be revisited!
@@ -815,7 +815,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event)
 	 * state we need to clear P4_CCCR_OVF, otherwise interrupt get
 	 * asserted again and again
 	 */
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx,
+	(void)checking_wrmsrl(hwc->config_base,
 		(u64)(p4_config_unpack_cccr(hwc->config)) &
 			~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
 }
@@ -885,7 +885,7 @@ static void p4_pmu_enable_event(struct perf_event *event)
 	p4_pmu_enable_pebs(hwc->config);
 
 	(void)checking_wrmsrl(escr_addr, escr_conf);
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx,
+	(void)checking_wrmsrl(hwc->config_base,
 				(cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
 }
 
diff --git a/arch/x86/kernel/cpu/perf_event_p6.c b/arch/x86/kernel/cpu/perf_event_p6.c
index 34ba07b..20c097e 100644
--- a/arch/x86/kernel/cpu/perf_event_p6.c
+++ b/arch/x86/kernel/cpu/perf_event_p6.c
@@ -68,7 +68,7 @@ p6_pmu_disable_event(struct perf_event *event)
 	if (cpuc->enabled)
 		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx, val);
+	(void)checking_wrmsrl(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
@@ -81,7 +81,7 @@ static void p6_pmu_enable_event(struct perf_event *event)
 	if (cpuc->enabled)
 		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx, val);
+	(void)checking_wrmsrl(hwc->config_base, val);
 }
 
 static __initconst const struct x86_pmu p6_pmu = {
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index d5a2366..966512b 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -46,6 +46,8 @@ static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
 	/* returns the bit offset of the performance counter register */
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
+		if (msr >= MSR_F15H_PERF_CTR)
+			return (msr - MSR_F15H_PERF_CTR) >> 1;
 		return msr - MSR_K7_PERFCTR0;
 	case X86_VENDOR_INTEL:
 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
@@ -70,6 +72,8 @@ static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
 	/* returns the bit offset of the event selection register */
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
+		if (msr >= MSR_F15H_PERF_CTL)
+			return (msr - MSR_F15H_PERF_CTL) >> 1;
 		return msr - MSR_K7_EVNTSEL0;
 	case X86_VENDOR_INTEL:
 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 227b044..d22d0c4 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -86,7 +86,7 @@ static void __init vmware_platform_setup(void)
 }
 
 /*
- * While checking the dmi string infomation, just checking the product
+ * While checking the dmi string information, just checking the product
  * serial key should be enough, as this will always have a VMware
  * specific string when running under VMware hypervisor.
  */
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
new file mode 100644
index 0000000..7a8cebc
--- /dev/null
+++ b/arch/x86/kernel/devicetree.c
@@ -0,0 +1,441 @@
+/*
+ * Architecture specific OF callbacks.
+ */
+#include <linux/bootmem.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/of_pci.h>
+
+#include <asm/hpet.h>
+#include <asm/irq_controller.h>
+#include <asm/apic.h>
+#include <asm/pci_x86.h>
+
+__initdata u64 initial_dtb;
+char __initdata cmd_line[COMMAND_LINE_SIZE];
+static LIST_HEAD(irq_domains);
+static DEFINE_RAW_SPINLOCK(big_irq_lock);
+
+int __initdata of_ioapic;
+
+#ifdef CONFIG_X86_IO_APIC
+static void add_interrupt_host(struct irq_domain *ih)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&big_irq_lock, flags);
+	list_add(&ih->l, &irq_domains);
+	raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+}
+#endif
+
+static struct irq_domain *get_ih_from_node(struct device_node *controller)
+{
+	struct irq_domain *ih, *found = NULL;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&big_irq_lock, flags);
+	list_for_each_entry(ih, &irq_domains, l) {
+		if (ih->controller ==  controller) {
+			found = ih;
+			break;
+		}
+	}
+	raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+	return found;
+}
+
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	struct irq_domain *ih;
+	u32 virq, type;
+	int ret;
+
+	ih = get_ih_from_node(controller);
+	if (!ih)
+		return 0;
+	ret = ih->xlate(ih, intspec, intsize, &virq, &type);
+	if (ret)
+		return ret;
+	if (type == IRQ_TYPE_NONE)
+		return virq;
+	/* set the mask if it is different from current */
+	if (type == (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
+		set_irq_type(virq, type);
+	return virq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+	/*
+	 * The ioport address can be directly used by inX / outX
+	 */
+	BUG_ON(address >= (1 << 16));
+	return (unsigned long)address;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
+void __init early_init_dt_scan_chosen_arch(unsigned long node)
+{
+	BUG();
+}
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	BUG();
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
+}
+
+void __init add_dtb(u64 data)
+{
+	initial_dtb = data + offsetof(struct setup_data, data);
+}
+
+/*
+ * CE4100 ids. Will be moved to machine_device_initcall() once we have it.
+ */
+static struct of_device_id __initdata ce4100_ids[] = {
+	{ .compatible = "intel,ce4100-cp", },
+	{ .compatible = "isa", },
+	{ .compatible = "pci", },
+	{},
+};
+
+static int __init add_bus_probe(void)
+{
+	if (!of_have_populated_dt())
+		return 0;
+
+	return of_platform_bus_probe(NULL, ce4100_ids, NULL);
+}
+module_init(add_bus_probe);
+
+#ifdef CONFIG_PCI
+static int x86_of_pci_irq_enable(struct pci_dev *dev)
+{
+	struct of_irq oirq;
+	u32 virq;
+	int ret;
+	u8 pin;
+
+	ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (ret)
+		return ret;
+	if (!pin)
+		return 0;
+
+	ret = of_irq_map_pci(dev, &oirq);
+	if (ret)
+		return ret;
+
+	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+			oirq.size);
+	if (virq == 0)
+		return -EINVAL;
+	dev->irq = virq;
+	return 0;
+}
+
+static void x86_of_pci_irq_disable(struct pci_dev *dev)
+{
+}
+
+void __cpuinit x86_of_pci_init(void)
+{
+	struct device_node *np;
+
+	pcibios_enable_irq = x86_of_pci_irq_enable;
+	pcibios_disable_irq = x86_of_pci_irq_disable;
+
+	for_each_node_by_type(np, "pci") {
+		const void *prop;
+		struct pci_bus *bus;
+		unsigned int bus_min;
+		struct device_node *child;
+
+		prop = of_get_property(np, "bus-range", NULL);
+		if (!prop)
+			continue;
+		bus_min = be32_to_cpup(prop);
+
+		bus = pci_find_bus(0, bus_min);
+		if (!bus) {
+			printk(KERN_ERR "Can't find a node for bus %s.\n",
+					np->full_name);
+			continue;
+		}
+
+		if (bus->self)
+			bus->self->dev.of_node = np;
+		else
+			bus->dev.of_node = np;
+
+		for_each_child_of_node(np, child) {
+			struct pci_dev *dev;
+			u32 devfn;
+
+			prop = of_get_property(child, "reg", NULL);
+			if (!prop)
+				continue;
+
+			devfn = (be32_to_cpup(prop) >> 8) & 0xff;
+			dev = pci_get_slot(bus, devfn);
+			if (!dev)
+				continue;
+			dev->dev.of_node = child;
+			pci_dev_put(dev);
+		}
+	}
+}
+#endif
+
+static void __init dtb_setup_hpet(void)
+{
+#ifdef CONFIG_HPET_TIMER
+	struct device_node *dn;
+	struct resource r;
+	int ret;
+
+	dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
+	if (!dn)
+		return;
+	ret = of_address_to_resource(dn, 0, &r);
+	if (ret) {
+		WARN_ON(1);
+		return;
+	}
+	hpet_address = r.start;
+#endif
+}
+
+static void __init dtb_lapic_setup(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	struct device_node *dn;
+	struct resource r;
+	int ret;
+
+	dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
+	if (!dn)
+		return;
+
+	ret = of_address_to_resource(dn, 0, &r);
+	if (WARN_ON(ret))
+		return;
+
+	/* Did the boot loader setup the local APIC ? */
+	if (!cpu_has_apic) {
+		if (apic_force_enable(r.start))
+			return;
+	}
+	smp_found_config = 1;
+	pic_mode = 1;
+	register_lapic_address(r.start);
+	generic_processor_info(boot_cpu_physical_apicid,
+			       GET_APIC_VERSION(apic_read(APIC_LVR)));
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+static unsigned int ioapic_id;
+
+static void __init dtb_add_ioapic(struct device_node *dn)
+{
+	struct resource r;
+	int ret;
+
+	ret = of_address_to_resource(dn, 0, &r);
+	if (ret) {
+		printk(KERN_ERR "Can't obtain address from node %s.\n",
+				dn->full_name);
+		return;
+	}
+	mp_register_ioapic(++ioapic_id, r.start, gsi_top);
+}
+
+static void __init dtb_ioapic_setup(void)
+{
+	struct device_node *dn;
+
+	for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+		dtb_add_ioapic(dn);
+
+	if (nr_ioapics) {
+		of_ioapic = 1;
+		return;
+	}
+	printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
+
+static void __init dtb_apic_setup(void)
+{
+	dtb_lapic_setup();
+	dtb_ioapic_setup();
+}
+
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
+{
+	u32 size, map_len;
+	void *new_dtb;
+
+	if (!initial_dtb)
+		return;
+
+	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
+			(u64)sizeof(struct boot_param_header));
+
+	initial_boot_params = early_memremap(initial_dtb, map_len);
+	size = be32_to_cpu(initial_boot_params->totalsize);
+	if (map_len < size) {
+		early_iounmap(initial_boot_params, map_len);
+		initial_boot_params = early_memremap(initial_dtb, size);
+		map_len = size;
+	}
+
+	new_dtb = alloc_bootmem(size);
+	memcpy(new_dtb, initial_boot_params, size);
+	early_iounmap(initial_boot_params, map_len);
+
+	initial_boot_params = new_dtb;
+
+	/* root level address cells */
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+	unflatten_device_tree();
+}
+#else
+static inline void x86_flattree_get_config(void) { }
+#endif
+
+void __init x86_dtb_init(void)
+{
+	x86_flattree_get_config();
+
+	if (!of_have_populated_dt())
+		return;
+
+	dtb_setup_hpet();
+	dtb_apic_setup();
+}
+
+#ifdef CONFIG_X86_IO_APIC
+
+struct of_ioapic_type {
+	u32 out_type;
+	u32 trigger;
+	u32 polarity;
+};
+
+static struct of_ioapic_type of_ioapic_type[] =
+{
+	{
+		.out_type	= IRQ_TYPE_EDGE_RISING,
+		.trigger	= IOAPIC_EDGE,
+		.polarity	= 1,
+	},
+	{
+		.out_type	= IRQ_TYPE_LEVEL_LOW,
+		.trigger	= IOAPIC_LEVEL,
+		.polarity	= 0,
+	},
+	{
+		.out_type	= IRQ_TYPE_LEVEL_HIGH,
+		.trigger	= IOAPIC_LEVEL,
+		.polarity	= 1,
+	},
+	{
+		.out_type	= IRQ_TYPE_EDGE_FALLING,
+		.trigger	= IOAPIC_EDGE,
+		.polarity	= 0,
+	},
+};
+
+static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
+			u32 *out_hwirq, u32 *out_type)
+{
+	struct io_apic_irq_attr attr;
+	struct of_ioapic_type *it;
+	u32 line, idx, type;
+
+	if (intsize < 2)
+		return -EINVAL;
+
+	line = *intspec;
+	idx = (u32) id->priv;
+	*out_hwirq = line + mp_gsi_routing[idx].gsi_base;
+
+	intspec++;
+	type = *intspec;
+
+	if (type >= ARRAY_SIZE(of_ioapic_type))
+		return -EINVAL;
+
+	it = of_ioapic_type + type;
+	*out_type = it->out_type;
+
+	set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
+
+	return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
+}
+
+static void __init ioapic_add_ofnode(struct device_node *np)
+{
+	struct resource r;
+	int i, ret;
+
+	ret = of_address_to_resource(np, 0, &r);
+	if (ret) {
+		printk(KERN_ERR "Failed to obtain address for %s\n",
+				np->full_name);
+		return;
+	}
+
+	for (i = 0; i < nr_ioapics; i++) {
+		if (r.start == mp_ioapics[i].apicaddr) {
+			struct irq_domain *id;
+
+			id = kzalloc(sizeof(*id), GFP_KERNEL);
+			BUG_ON(!id);
+			id->controller = np;
+			id->xlate = ioapic_xlate;
+			id->priv = (void *)i;
+			add_interrupt_host(id);
+			return;
+		}
+	}
+	printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+}
+
+void __init x86_add_irq_domains(void)
+{
+	struct device_node *dp;
+
+	if (!of_have_populated_dt())
+		return;
+
+	for_each_node_with_property(dp, "interrupt-controller") {
+		if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
+			ioapic_add_ofnode(dp);
+	}
+}
+#else
+void __init x86_add_irq_domains(void) { }
+#endif
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index df20723..81ac6c7 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -175,21 +175,21 @@ static const struct stacktrace_ops print_trace_ops = {
 
 void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, char *log_lvl)
+		unsigned long *stack, unsigned long bp, char *log_lvl)
 {
 	printk("%sCall Trace:\n", log_lvl);
-	dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
+	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
 }
 
 void show_trace(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack)
+		unsigned long *stack, unsigned long bp)
 {
-	show_trace_log_lvl(task, regs, stack, "");
+	show_trace_log_lvl(task, regs, stack, bp, "");
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
-	show_stack_log_lvl(task, NULL, sp, "");
+	show_stack_log_lvl(task, NULL, sp, 0, "");
 }
 
 /*
@@ -197,14 +197,16 @@ void show_stack(struct task_struct *task, unsigned long *sp)
  */
 void dump_stack(void)
 {
+	unsigned long bp;
 	unsigned long stack;
 
+	bp = stack_frame(current, NULL);
 	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
 		current->pid, current->comm, print_tainted(),
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
-	show_trace(NULL, NULL, &stack);
+	show_trace(NULL, NULL, &stack, bp);
 }
 EXPORT_SYMBOL(dump_stack);
 
@@ -320,41 +322,6 @@ void die(const char *str, struct pt_regs *regs, long err)
 	oops_end(flags, regs, sig);
 }
 
-void notrace __kprobes
-die_nmi(char *str, struct pt_regs *regs, int do_panic)
-{
-	unsigned long flags;
-
-	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
-		return;
-
-	/*
-	 * We are in trouble anyway, lets at least try
-	 * to get a message out.
-	 */
-	flags = oops_begin();
-	printk(KERN_EMERG "%s", str);
-	printk(" on CPU%d, ip %08lx, registers:\n",
-		smp_processor_id(), regs->ip);
-	show_registers(regs);
-	oops_end(flags, regs, 0);
-	if (do_panic || panic_on_oops)
-		panic("Non maskable interrupt");
-	nmi_exit();
-	local_irq_enable();
-	do_exit(SIGBUS);
-}
-
-static int __init oops_setup(char *s)
-{
-	if (!s)
-		return -EINVAL;
-	if (!strcmp(s, "panic"))
-		panic_on_oops = 1;
-	return 0;
-}
-early_param("oops", oops_setup);
-
 static int __init kstack_setup(char *s)
 {
 	if (!s)
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c
index 74cc1ed..3b97a80 100644
--- a/arch/x86/kernel/dumpstack_32.c
+++ b/arch/x86/kernel/dumpstack_32.c
@@ -17,12 +17,11 @@
 #include <asm/stacktrace.h>
 
 
-void dump_trace(struct task_struct *task,
-		struct pt_regs *regs, unsigned long *stack,
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data)
 {
 	int graph = 0;
-	unsigned long bp;
 
 	if (!task)
 		task = current;
@@ -35,7 +34,9 @@ void dump_trace(struct task_struct *task,
 			stack = (unsigned long *)task->thread.sp;
 	}
 
-	bp = stack_frame(task, regs);
+	if (!bp)
+		bp = stack_frame(task, regs);
+
 	for (;;) {
 		struct thread_info *context;
 
@@ -55,7 +56,7 @@ EXPORT_SYMBOL(dump_trace);
 
 void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, char *log_lvl)
+		   unsigned long *sp, unsigned long bp, char *log_lvl)
 {
 	unsigned long *stack;
 	int i;
@@ -77,7 +78,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
 		touch_nmi_watchdog();
 	}
 	printk(KERN_CONT "\n");
-	show_trace_log_lvl(task, regs, sp, log_lvl);
+	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
 
@@ -102,7 +103,7 @@ void show_registers(struct pt_regs *regs)
 		u8 *ip;
 
 		printk(KERN_EMERG "Stack:\n");
-		show_stack_log_lvl(NULL, regs, &regs->sp, KERN_EMERG);
+		show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index a6b6fcf..e71c98d 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -139,8 +139,8 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-void dump_trace(struct task_struct *task,
-		struct pt_regs *regs, unsigned long *stack,
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data)
 {
 	const unsigned cpu = get_cpu();
@@ -150,7 +150,6 @@ void dump_trace(struct task_struct *task,
 	struct thread_info *tinfo;
 	int graph = 0;
 	unsigned long dummy;
-	unsigned long bp;
 
 	if (!task)
 		task = current;
@@ -161,7 +160,8 @@ void dump_trace(struct task_struct *task,
 			stack = (unsigned long *)task->thread.sp;
 	}
 
-	bp = stack_frame(task, regs);
+	if (!bp)
+		bp = stack_frame(task, regs);
 	/*
 	 * Print function call entries in all stacks, starting at the
 	 * current stack address. If the stacks consist of nested
@@ -225,7 +225,7 @@ EXPORT_SYMBOL(dump_trace);
 
 void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, char *log_lvl)
+		   unsigned long *sp, unsigned long bp, char *log_lvl)
 {
 	unsigned long *irq_stack_end;
 	unsigned long *irq_stack;
@@ -269,7 +269,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
 	preempt_enable();
 
 	printk(KERN_CONT "\n");
-	show_trace_log_lvl(task, regs, sp, log_lvl);
+	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
 void show_registers(struct pt_regs *regs)
@@ -298,7 +298,7 @@ void show_registers(struct pt_regs *regs)
 
 		printk(KERN_EMERG "Stack:\n");
 		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
-				   KERN_EMERG);
+				   0, KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 294f26d..cdf5bfd 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -667,21 +667,15 @@ __init void e820_setup_gap(void)
  * boot_params.e820_map, others are passed via SETUP_E820_EXT node of
  * linked list of struct setup_data, which is parsed here.
  */
-void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
+void __init parse_e820_ext(struct setup_data *sdata)
 {
-	u32 map_len;
 	int entries;
 	struct e820entry *extmap;
 
 	entries = sdata->len / sizeof(struct e820entry);
-	map_len = sdata->len + sizeof(struct setup_data);
-	if (map_len > PAGE_SIZE)
-		sdata = early_ioremap(pa_data, map_len);
 	extmap = (struct e820entry *)(sdata->data);
 	__append_e820_map(extmap, entries);
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-	if (map_len > PAGE_SIZE)
-		early_iounmap(sdata, map_len);
 	printk(KERN_INFO "extended physical RAM map:\n");
 	e820_print_map("extended");
 }
@@ -847,15 +841,21 @@ static int __init parse_memopt(char *p)
 	if (!p)
 		return -EINVAL;
 
-#ifdef CONFIG_X86_32
 	if (!strcmp(p, "nopentium")) {
+#ifdef CONFIG_X86_32
 		setup_clear_cpu_cap(X86_FEATURE_PSE);
 		return 0;
-	}
+#else
+		printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
+		return -EINVAL;
 #endif
+	}
 
 	userdef = 1;
 	mem_size = memparse(p, &p);
+	/* don't remove all of memory when handling "mem={invalid}" param */
+	if (mem_size == 0)
+		return -EINVAL;
 	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c
index 9efbdcc..3755ef4 100644
--- a/arch/x86/kernel/early-quirks.c
+++ b/arch/x86/kernel/early-quirks.c
@@ -159,7 +159,12 @@ static void __init ati_bugs_contd(int num, int slot, int func)
 	if (rev >= 0x40)
 		acpi_fix_pin2_polarity = 1;
 
-	if (rev > 0x13)
+	/*
+	 * SB600: revisions 0x11, 0x12, 0x13, 0x14, ...
+	 * SB700: revisions 0x39, 0x3a, ...
+	 * SB800: revisions 0x40, 0x41, ...
+	 */
+	if (rev >= 0x39)
 		return;
 
 	if (acpi_use_timer_override)
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index c8b4efa..5c1a9197 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -65,6 +65,8 @@
 #define sysexit_audit	syscall_exit_work
 #endif
 
+	.section .entry.text, "ax"
+
 /*
  * We use macros for low-level operations which need to be overridden
  * for paravirtualization.  The following will never clobber any registers:
@@ -395,7 +397,7 @@ sysenter_past_esp:
 	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
 	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
 	 */
-	pushl_cfi ((TI_sysenter_return)-THREAD_SIZE_asm+8+4*4)(%esp)
+	pushl_cfi ((TI_sysenter_return)-THREAD_SIZE+8+4*4)(%esp)
 	CFI_REL_OFFSET eip, 0
 
 	pushl_cfi %eax
@@ -788,7 +790,7 @@ ENDPROC(ptregs_clone)
  */
 .section .init.rodata,"a"
 ENTRY(interrupt)
-.text
+.section .entry.text, "ax"
 	.p2align 5
 	.p2align CONFIG_X86_L1_CACHE_SHIFT
 ENTRY(irq_entries_start)
@@ -807,7 +809,7 @@ vector=FIRST_EXTERNAL_VECTOR
       .endif
       .previous
 	.long 1b
-      .text
+      .section .entry.text, "ax"
 vector=vector+1
     .endif
   .endr
@@ -1409,11 +1411,10 @@ END(general_protection)
 #ifdef CONFIG_KVM_GUEST
 ENTRY(async_page_fault)
 	RING0_EC_FRAME
-	pushl $do_async_page_fault
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_async_page_fault
 	jmp error_code
 	CFI_ENDPROC
-END(apf_page_fault)
+END(async_page_fault)
 #endif
 
 /*
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index aed1ffb..8a445a0 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -18,7 +18,7 @@
  * A note on terminology:
  * - top of stack: Architecture defined interrupt frame from SS to RIP
  * at the top of the kernel process stack.
- * - partial stack frame: partially saved registers upto R11.
+ * - partial stack frame: partially saved registers up to R11.
  * - full stack frame: Like partial stack frame, but all register saved.
  *
  * Some macro usage:
@@ -61,6 +61,8 @@
 #define __AUDIT_ARCH_LE	   0x40000000
 
 	.code64
+	.section .entry.text, "ax"
+
 #ifdef CONFIG_FUNCTION_TRACER
 #ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(mcount)
@@ -420,7 +422,7 @@ ENTRY(ret_from_fork)
 END(ret_from_fork)
 
 /*
- * System call entry. Upto 6 arguments in registers are supported.
+ * System call entry. Up to 6 arguments in registers are supported.
  *
  * SYSCALL does not save anything on the stack and does not change the
  * stack pointer.
@@ -744,7 +746,7 @@ END(stub_rt_sigreturn)
  */
 	.section .init.rodata,"a"
 ENTRY(interrupt)
-	.text
+	.section .entry.text
 	.p2align 5
 	.p2align CONFIG_X86_L1_CACHE_SHIFT
 ENTRY(irq_entries_start)
@@ -763,7 +765,7 @@ vector=FIRST_EXTERNAL_VECTOR
       .endif
       .previous
 	.quad 1b
-      .text
+      .section .entry.text
 vector=vector+1
     .endif
   .endr
@@ -975,9 +977,12 @@ apicinterrupt X86_PLATFORM_IPI_VECTOR \
 	x86_platform_ipi smp_x86_platform_ipi
 
 #ifdef CONFIG_SMP
-.irpc idx, "01234567"
+.irp idx,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
+.if NUM_INVALIDATE_TLB_VECTORS > \idx
 apicinterrupt (INVALIDATE_TLB_VECTOR_START)+\idx \
 	invalidate_interrupt\idx smp_invalidate_interrupt
+.endif
 .endr
 #endif
 
@@ -1248,7 +1253,7 @@ ENTRY(xen_do_hypervisor_callback)   # do_hypervisor_callback(struct *pt_regs)
 	decl PER_CPU_VAR(irq_count)
 	jmp  error_exit
 	CFI_ENDPROC
-END(do_hypervisor_callback)
+END(xen_do_hypervisor_callback)
 
 /*
  * Hypervisor uses this for application faults while it executes.
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 382eb29..a93742a 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -437,18 +437,19 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		return;
 	}
 
-	if (ftrace_push_return_trace(old, self_addr, &trace.depth,
-		    frame_pointer) == -EBUSY) {
-		*parent = old;
-		return;
-	}
-
 	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
 
 	/* Only trace if the calling function expects to */
 	if (!ftrace_graph_entry(&trace)) {
-		current->curr_ret_stack--;
 		*parent = old;
+		return;
+	}
+
+	if (ftrace_push_return_trace(old, self_addr, &trace.depth,
+		    frame_pointer) == -EBUSY) {
+		*parent = old;
+		return;
 	}
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 7f138b3..d6d6bb3 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -34,15 +34,6 @@ void __init i386_start_kernel(void)
 {
 	memblock_init();
 
-#ifdef CONFIG_X86_TRAMPOLINE
-	/*
-	 * But first pinch a few for the stack/trampoline stuff
-	 * FIXME: Don't need the extra page at 4K, but need to fix
-	 * trampoline before removing it. (see the GDT stuff)
-	 */
-	memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
-#endif
-
 	memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 2d2673c..5655c22 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -77,9 +77,6 @@ void __init x86_64_start_kernel(char * real_mode_data)
 	/* Make NULL pointers segfault */
 	zap_identity_mappings();
 
-	/* Cleanup the over mapped high alias */
-	cleanup_highmap();
-
 	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
 
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 767d6c4..ce0be7c 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -73,7 +73,7 @@ MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
  */
 KERNEL_PAGES = LOWMEM_PAGES
 
-INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
+INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
 
 /*
@@ -137,7 +137,7 @@ ENTRY(startup_32)
 	movsl
 1:
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE
+#ifdef CONFIG_OLPC
 	/* save OFW's pgdir table for later use when calling into OFW */
 	movl %cr3, %eax
 	movl %eax, pa(olpc_ofw_pgd)
@@ -623,7 +623,7 @@ ENTRY(initial_code)
  * BSS section
  */
 __PAGE_ALIGNED_BSS
-	.align PAGE_SIZE_asm
+	.align PAGE_SIZE
 #ifdef CONFIG_X86_PAE
 initial_pg_pmd:
 	.fill 1024*KPMDS,4,0
@@ -644,7 +644,7 @@ ENTRY(swapper_pg_dir)
 #ifdef CONFIG_X86_PAE
 __PAGE_ALIGNED_DATA
 	/* Page-aligned for the benefit of paravirt? */
-	.align PAGE_SIZE_asm
+	.align PAGE_SIZE
 ENTRY(initial_page_table)
 	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
 # if KPMDS == 3
@@ -662,7 +662,7 @@ ENTRY(initial_page_table)
 # else
 #  error "Kernel PMDs should be 1, 2 or 3"
 # endif
-	.align PAGE_SIZE_asm		/* needs to be page-sized too */
+	.align PAGE_SIZE		/* needs to be page-sized too */
 #endif
 
 .data
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 239046b..e11e394 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -136,10 +136,9 @@ ident_complete:
 	/* Fixup phys_base */
 	addq	%rbp, phys_base(%rip)
 
-#ifdef CONFIG_X86_TRAMPOLINE
+	/* Fixup trampoline */
 	addq	%rbp, trampoline_level4_pgt + 0(%rip)
 	addq	%rbp, trampoline_level4_pgt + (511*8)(%rip)
-#endif
 
 	/* Due to ENTRY(), sometimes the empty space gets filled with
 	 * zeros. Better take a jmp than relying on empty space being
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 4ff5968..bfe8f72 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -503,7 +503,7 @@ static int hpet_assign_irq(struct hpet_dev *dev)
 	if (!irq)
 		return -EINVAL;
 
-	set_irq_data(irq, dev);
+	irq_set_handler_data(irq, dev);
 
 	if (hpet_setup_msi_irq(irq))
 		return -EINVAL;
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index e60c38c..12aff25 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -145,7 +145,7 @@ EXPORT_SYMBOL_GPL(fpu_finit);
  * The _current_ task is using the FPU for the first time
  * so initialize it and set the mxcsr to its default
  * value at reset if we support XMM instructions and then
- * remeber the current task has used the FPU.
+ * remember the current task has used the FPU.
  */
 int init_fpu(struct task_struct *tsk)
 {
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 20757cb..d9ca749 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -112,7 +112,7 @@ static void make_8259A_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
-	set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
+	irq_set_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
 				      i8259A_chip.name);
 	enable_irq(irq);
 }
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c
index 8eec0ec..8c96897 100644
--- a/arch/x86/kernel/ioport.c
+++ b/arch/x86/kernel/ioport.c
@@ -14,22 +14,9 @@
 #include <linux/slab.h>
 #include <linux/thread_info.h>
 #include <linux/syscalls.h>
+#include <linux/bitmap.h>
 #include <asm/syscalls.h>
 
-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
-static void set_bitmap(unsigned long *bitmap, unsigned int base,
-		       unsigned int extent, int new_value)
-{
-	unsigned int i;
-
-	for (i = base; i < base + extent; i++) {
-		if (new_value)
-			__set_bit(i, bitmap);
-		else
-			__clear_bit(i, bitmap);
-	}
-}
-
 /*
  * this changes the io permissions bitmap in the current task.
  */
@@ -69,7 +56,10 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 	 */
 	tss = &per_cpu(init_tss, get_cpu());
 
-	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
+	if (turn_on)
+		bitmap_clear(t->io_bitmap_ptr, from, num);
+	else
+		bitmap_set(t->io_bitmap_ptr, from, num);
 
 	/*
 	 * Search for a (possibly new) maximum. This is simple and stupid,
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 387b6a0..948a31e 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -44,9 +44,9 @@ void ack_bad_irq(unsigned int irq)
 
 #define irq_stats(x)		(&per_cpu(irq_stat, x))
 /*
- * /proc/interrupts printing:
+ * /proc/interrupts printing for arch specific interrupts
  */
-static int show_other_interrupts(struct seq_file *p, int prec)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	int j;
 
@@ -122,59 +122,6 @@ static int show_other_interrupts(struct seq_file *p, int prec)
 	return 0;
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	unsigned long flags, any_count = 0;
-	int i = *(loff_t *) v, j, prec;
-	struct irqaction *action;
-	struct irq_desc *desc;
-
-	if (i > nr_irqs)
-		return 0;
-
-	for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
-		j *= 10;
-
-	if (i == nr_irqs)
-		return show_other_interrupts(p, prec);
-
-	/* print header */
-	if (i == 0) {
-		seq_printf(p, "%*s", prec + 8, "");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	desc = irq_to_desc(i);
-	if (!desc)
-		return 0;
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	for_each_online_cpu(j)
-		any_count |= kstat_irqs_cpu(i, j);
-	action = desc->action;
-	if (!action && !any_count)
-		goto out;
-
-	seq_printf(p, "%*d: ", prec, i);
-	for_each_online_cpu(j)
-		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-	seq_printf(p, " %8s", desc->irq_data.chip->name);
-	seq_printf(p, "-%-8s", desc->name);
-
-	if (action) {
-		seq_printf(p, "  %s", action->name);
-		while ((action = action->next) != NULL)
-			seq_printf(p, ", %s", action->name);
-	}
-
-	seq_putc(p, '\n');
-out:
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	return 0;
-}
-
 /*
  * /proc/stat helpers
  */
@@ -276,15 +223,6 @@ void smp_x86_platform_ipi(struct pt_regs *regs)
 
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
 
-#ifdef CONFIG_OF
-unsigned int irq_create_of_mapping(struct device_node *controller,
-		const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 /* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
 void fixup_irqs(void)
@@ -293,6 +231,7 @@ void fixup_irqs(void)
 	static int warned;
 	struct irq_desc *desc;
 	struct irq_data *data;
+	struct irq_chip *chip;
 
 	for_each_irq_desc(irq, desc) {
 		int break_affinity = 0;
@@ -307,10 +246,10 @@ void fixup_irqs(void)
 		/* interrupt's are disabled at this point */
 		raw_spin_lock(&desc->lock);
 
-		data = &desc->irq_data;
+		data = irq_desc_get_irq_data(desc);
 		affinity = data->affinity;
 		if (!irq_has_action(irq) ||
-		    cpumask_equal(affinity, cpu_online_mask)) {
+		    cpumask_subset(affinity, cpu_online_mask)) {
 			raw_spin_unlock(&desc->lock);
 			continue;
 		}
@@ -327,16 +266,17 @@ void fixup_irqs(void)
 			affinity = cpu_all_mask;
 		}
 
-		if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_mask)
-			data->chip->irq_mask(data);
+		chip = irq_data_get_irq_chip(data);
+		if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
+			chip->irq_mask(data);
 
-		if (data->chip->irq_set_affinity)
-			data->chip->irq_set_affinity(data, affinity, true);
+		if (chip->irq_set_affinity)
+			chip->irq_set_affinity(data, affinity, true);
 		else if (!(warned++))
 			set_affinity = 0;
 
-		if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_unmask)
-			data->chip->irq_unmask(data);
+		if (!irqd_can_move_in_process_context(data) && chip->irq_unmask)
+			chip->irq_unmask(data);
 
 		raw_spin_unlock(&desc->lock);
 
@@ -368,10 +308,11 @@ void fixup_irqs(void)
 			irq = __this_cpu_read(vector_irq[vector]);
 
 			desc = irq_to_desc(irq);
-			data = &desc->irq_data;
+			data = irq_desc_get_irq_data(desc);
+			chip = irq_data_get_irq_chip(data);
 			raw_spin_lock(&desc->lock);
-			if (data->chip->irq_retrigger)
-				data->chip->irq_retrigger(data);
+			if (chip->irq_retrigger)
+				chip->irq_retrigger(data);
 			raw_spin_unlock(&desc->lock);
 		}
 	}
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 9974d21..7209070 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -172,7 +172,7 @@ asmlinkage void do_softirq(void)
 
 		call_on_stack(__do_softirq, isp);
 		/*
-		 * Shouldnt happen, we returned above if in_interrupt():
+		 * Shouldn't happen, we returned above if in_interrupt():
 		 */
 		WARN_ON_ONCE(softirq_count());
 	}
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index c752e97..f470e4e 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -25,6 +25,7 @@
 #include <asm/setup.h>
 #include <asm/i8259.h>
 #include <asm/traps.h>
+#include <asm/prom.h>
 
 /*
  * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
@@ -71,6 +72,7 @@ static irqreturn_t math_error_irq(int cpl, void *dev_id)
 static struct irqaction fpu_irq = {
 	.handler = math_error_irq,
 	.name = "fpu",
+	.flags = IRQF_NO_THREAD,
 };
 #endif
 
@@ -80,6 +82,7 @@ static struct irqaction fpu_irq = {
 static struct irqaction irq2 = {
 	.handler = no_action,
 	.name = "cascade",
+	.flags = IRQF_NO_THREAD,
 };
 
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
@@ -110,7 +113,7 @@ void __init init_ISA_irqs(void)
 	legacy_pic->init(0);
 
 	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
-		set_irq_chip_and_handler_name(i, chip, handle_level_irq, name);
+		irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
 }
 
 void __init init_IRQ(void)
@@ -118,6 +121,12 @@ void __init init_IRQ(void)
 	int i;
 
 	/*
+	 * We probably need a better place for this, but it works for
+	 * now ...
+	 */
+	x86_add_irq_domains();
+
+	/*
 	 * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
 	 * If these IRQ's are handled by legacy interrupt-controllers like PIC,
 	 * then this configuration will likely be static after the boot. If
@@ -164,14 +173,77 @@ static void __init smp_intr_init(void)
 	alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
 
 	/* IPIs for invalidation */
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
-	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
+#define ALLOC_INVTLB_VEC(NR) \
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+NR, \
+		invalidate_interrupt##NR)
+
+	switch (NUM_INVALIDATE_TLB_VECTORS) {
+	default:
+		ALLOC_INVTLB_VEC(31);
+	case 31:
+		ALLOC_INVTLB_VEC(30);
+	case 30:
+		ALLOC_INVTLB_VEC(29);
+	case 29:
+		ALLOC_INVTLB_VEC(28);
+	case 28:
+		ALLOC_INVTLB_VEC(27);
+	case 27:
+		ALLOC_INVTLB_VEC(26);
+	case 26:
+		ALLOC_INVTLB_VEC(25);
+	case 25:
+		ALLOC_INVTLB_VEC(24);
+	case 24:
+		ALLOC_INVTLB_VEC(23);
+	case 23:
+		ALLOC_INVTLB_VEC(22);
+	case 22:
+		ALLOC_INVTLB_VEC(21);
+	case 21:
+		ALLOC_INVTLB_VEC(20);
+	case 20:
+		ALLOC_INVTLB_VEC(19);
+	case 19:
+		ALLOC_INVTLB_VEC(18);
+	case 18:
+		ALLOC_INVTLB_VEC(17);
+	case 17:
+		ALLOC_INVTLB_VEC(16);
+	case 16:
+		ALLOC_INVTLB_VEC(15);
+	case 15:
+		ALLOC_INVTLB_VEC(14);
+	case 14:
+		ALLOC_INVTLB_VEC(13);
+	case 13:
+		ALLOC_INVTLB_VEC(12);
+	case 12:
+		ALLOC_INVTLB_VEC(11);
+	case 11:
+		ALLOC_INVTLB_VEC(10);
+	case 10:
+		ALLOC_INVTLB_VEC(9);
+	case 9:
+		ALLOC_INVTLB_VEC(8);
+	case 8:
+		ALLOC_INVTLB_VEC(7);
+	case 7:
+		ALLOC_INVTLB_VEC(6);
+	case 6:
+		ALLOC_INVTLB_VEC(5);
+	case 5:
+		ALLOC_INVTLB_VEC(4);
+	case 4:
+		ALLOC_INVTLB_VEC(3);
+	case 3:
+		ALLOC_INVTLB_VEC(2);
+	case 2:
+		ALLOC_INVTLB_VEC(1);
+	case 1:
+		ALLOC_INVTLB_VEC(0);
+		break;
+	}
 
 	/* IPI for generic function call */
 	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
@@ -243,7 +315,7 @@ void __init native_init_IRQ(void)
 			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
 	}
 
-	if (!acpi_ioapic)
+	if (!acpi_ioapic && !of_ioapic)
 		setup_irq(2, &irq2);
 
 #ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index a413000..dba0b36 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -278,7 +278,7 @@ static int hw_break_release_slot(int breakno)
 		pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
 		if (dbg_release_bp_slot(*pevent))
 			/*
-			 * The debugger is responisble for handing the retry on
+			 * The debugger is responsible for handing the retry on
 			 * remove failure.
 			 */
 			return -1;
@@ -533,15 +533,6 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd)
 		}
 		return NOTIFY_DONE;
 
-	case DIE_NMIWATCHDOG:
-		if (atomic_read(&kgdb_active) != -1) {
-			/* KGDB CPU roundup: */
-			kgdb_nmicallback(raw_smp_processor_id(), regs);
-			return NOTIFY_STOP;
-		}
-		/* Enter debugger: */
-		break;
-
 	case DIE_DEBUG:
 		if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
 			if (user_mode(regs))
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index d91c477..c969fd9 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -1276,6 +1276,14 @@ static int __kprobes can_optimize(unsigned long paddr)
 	if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
 		return 0;
 
+	/*
+	 * Do not optimize in the entry code due to the unstable
+	 * stack handling.
+	 */
+	if ((paddr >= (unsigned long )__entry_text_start) &&
+	    (paddr <  (unsigned long )__entry_text_end))
+		return 0;
+
 	/* Check there is enough space for a relative jump. */
 	if (size - offset < RELATIVEJUMP_SIZE)
 		return 0;
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 8dc4466..33c07b0 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -493,7 +493,7 @@ static void __init kvm_smp_prepare_boot_cpu(void)
 	native_smp_prepare_boot_cpu();
 }
 
-static void kvm_guest_cpu_online(void *dummy)
+static void __cpuinit kvm_guest_cpu_online(void *dummy)
 {
 	kvm_guest_cpu_init();
 }
diff --git a/arch/x86/kernel/mca_32.c b/arch/x86/kernel/mca_32.c
index 63eaf65..177183c 100644
--- a/arch/x86/kernel/mca_32.c
+++ b/arch/x86/kernel/mca_32.c
@@ -259,7 +259,7 @@ static int __init mca_init(void)
 	/*
 	 * WARNING: Be careful when making changes here. Putting an adapter
 	 * and the motherboard simultaneously into setup mode may result in
-	 * damage to chips (according to The Indispensible PC Hardware Book
+	 * damage to chips (according to The Indispensable PC Hardware Book
 	 * by Hans-Peter Messmer). Also, we disable system interrupts (so
 	 * that we are not disturbed in the middle of this).
 	 */
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 0fe6d1a..c561038 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -66,7 +66,6 @@ struct microcode_amd {
 	unsigned int			mpb[0];
 };
 
-#define UCODE_MAX_SIZE			2048
 #define UCODE_CONTAINER_SECTION_HDR	8
 #define UCODE_CONTAINER_HEADER_SIZE	12
 
@@ -77,20 +76,20 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig)
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	u32 dummy;
 
-	memset(csig, 0, sizeof(*csig));
 	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
-		pr_warning("microcode: CPU%d: AMD CPU family 0x%x not "
-			   "supported\n", cpu, c->x86);
+		pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
 		return -1;
 	}
+
 	rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy);
-	pr_info("CPU%d: patch_level=0x%x\n", cpu, csig->rev);
+	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
+
 	return 0;
 }
 
-static int get_matching_microcode(int cpu, void *mc, int rev)
+static int get_matching_microcode(int cpu, struct microcode_header_amd *mc_hdr,
+				  int rev)
 {
-	struct microcode_header_amd *mc_header = mc;
 	unsigned int current_cpu_id;
 	u16 equiv_cpu_id = 0;
 	unsigned int i = 0;
@@ -109,17 +108,17 @@ static int get_matching_microcode(int cpu, void *mc, int rev)
 	if (!equiv_cpu_id)
 		return 0;
 
-	if (mc_header->processor_rev_id != equiv_cpu_id)
+	if (mc_hdr->processor_rev_id != equiv_cpu_id)
 		return 0;
 
 	/* ucode might be chipset specific -- currently we don't support this */
-	if (mc_header->nb_dev_id || mc_header->sb_dev_id) {
-		pr_err("CPU%d: loading of chipset specific code not yet supported\n",
+	if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
+		pr_err("CPU%d: chipset specific code not yet supported\n",
 		       cpu);
 		return 0;
 	}
 
-	if (mc_header->patch_id <= rev)
+	if (mc_hdr->patch_id <= rev)
 		return 0;
 
 	return 1;
@@ -144,71 +143,93 @@ static int apply_microcode_amd(int cpu)
 
 	/* check current patch id and patch's id for match */
 	if (rev != mc_amd->hdr.patch_id) {
-		pr_err("CPU%d: update failed (for patch_level=0x%x)\n",
+		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 		       cpu, mc_amd->hdr.patch_id);
 		return -1;
 	}
 
-	pr_info("CPU%d: updated (new patch_level=0x%x)\n", cpu, rev);
+	pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
 	uci->cpu_sig.rev = rev;
 
 	return 0;
 }
 
-static void *
-get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
+static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
 {
-	unsigned int total_size;
-	u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
-	void *mc;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	unsigned int max_size, actual_size;
+
+#define F1XH_MPB_MAX_SIZE 2048
+#define F14H_MPB_MAX_SIZE 1824
+#define F15H_MPB_MAX_SIZE 4096
+
+	switch (c->x86) {
+	case 0x14:
+		max_size = F14H_MPB_MAX_SIZE;
+		break;
+	case 0x15:
+		max_size = F15H_MPB_MAX_SIZE;
+		break;
+	default:
+		max_size = F1XH_MPB_MAX_SIZE;
+		break;
+	}
 
-	get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR);
+	actual_size = buf[4] + (buf[5] << 8);
 
-	if (section_hdr[0] != UCODE_UCODE_TYPE) {
-		pr_err("error: invalid type field in container file section header\n");
-		return NULL;
+	if (actual_size > size || actual_size > max_size) {
+		pr_err("section size mismatch\n");
+		return 0;
 	}
 
-	total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8));
+	return actual_size;
+}
 
-	if (total_size > size || total_size > UCODE_MAX_SIZE) {
-		pr_err("error: size mismatch\n");
-		return NULL;
+static struct microcode_header_amd *
+get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
+{
+	struct microcode_header_amd *mc = NULL;
+	unsigned int actual_size = 0;
+
+	if (buf[0] != UCODE_UCODE_TYPE) {
+		pr_err("invalid type field in container file section header\n");
+		goto out;
 	}
 
-	mc = vzalloc(UCODE_MAX_SIZE);
+	actual_size = verify_ucode_size(cpu, buf, size);
+	if (!actual_size)
+		goto out;
+
+	mc = vzalloc(actual_size);
 	if (!mc)
-		return NULL;
+		goto out;
 
-	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size);
-	*mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
+	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
+	*mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
 
+out:
 	return mc;
 }
 
 static int install_equiv_cpu_table(const u8 *buf)
 {
-	u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE];
-	unsigned int *buf_pos = (unsigned int *)container_hdr;
-	unsigned long size;
-
-	get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE);
-
-	size = buf_pos[2];
-
-	if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
-		pr_err("error: invalid type field in container file section header\n");
-		return 0;
+	unsigned int *ibuf = (unsigned int *)buf;
+	unsigned int type = ibuf[1];
+	unsigned int size = ibuf[2];
+
+	if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
+		pr_err("empty section/"
+		       "invalid type field in container file section header\n");
+		return -EINVAL;
 	}
 
 	equiv_cpu_table = vmalloc(size);
 	if (!equiv_cpu_table) {
 		pr_err("failed to allocate equivalent CPU table\n");
-		return 0;
+		return -ENOMEM;
 	}
 
-	buf += UCODE_CONTAINER_HEADER_SIZE;
-	get_ucode_data(equiv_cpu_table, buf, size);
+	get_ucode_data(equiv_cpu_table, buf + UCODE_CONTAINER_HEADER_SIZE, size);
 
 	return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */
 }
@@ -223,16 +244,16 @@ static enum ucode_state
 generic_load_microcode(int cpu, const u8 *data, size_t size)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	struct microcode_header_amd *mc_hdr = NULL;
+	unsigned int mc_size, leftover;
+	int offset;
 	const u8 *ucode_ptr = data;
 	void *new_mc = NULL;
-	void *mc;
-	int new_rev = uci->cpu_sig.rev;
-	unsigned int leftover;
-	unsigned long offset;
+	unsigned int new_rev = uci->cpu_sig.rev;
 	enum ucode_state state = UCODE_OK;
 
 	offset = install_equiv_cpu_table(ucode_ptr);
-	if (!offset) {
+	if (offset < 0) {
 		pr_err("failed to create equivalent cpu table\n");
 		return UCODE_ERROR;
 	}
@@ -241,64 +262,65 @@ generic_load_microcode(int cpu, const u8 *data, size_t size)
 	leftover = size - offset;
 
 	while (leftover) {
-		unsigned int uninitialized_var(mc_size);
-		struct microcode_header_amd *mc_header;
-
-		mc = get_next_ucode(ucode_ptr, leftover, &mc_size);
-		if (!mc)
+		mc_hdr = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
+		if (!mc_hdr)
 			break;
 
-		mc_header = (struct microcode_header_amd *)mc;
-		if (get_matching_microcode(cpu, mc, new_rev)) {
+		if (get_matching_microcode(cpu, mc_hdr, new_rev)) {
 			vfree(new_mc);
-			new_rev = mc_header->patch_id;
-			new_mc  = mc;
+			new_rev = mc_hdr->patch_id;
+			new_mc  = mc_hdr;
 		} else
-			vfree(mc);
+			vfree(mc_hdr);
 
 		ucode_ptr += mc_size;
 		leftover  -= mc_size;
 	}
 
-	if (new_mc) {
-		if (!leftover) {
-			vfree(uci->mc);
-			uci->mc = new_mc;
-			pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
-				 cpu, new_rev, uci->cpu_sig.rev);
-		} else {
-			vfree(new_mc);
-			state = UCODE_ERROR;
-		}
-	} else
+	if (!new_mc) {
 		state = UCODE_NFOUND;
+		goto free_table;
+	}
 
+	if (!leftover) {
+		vfree(uci->mc);
+		uci->mc = new_mc;
+		pr_debug("CPU%d update ucode (0x%08x -> 0x%08x)\n",
+			 cpu, uci->cpu_sig.rev, new_rev);
+	} else {
+		vfree(new_mc);
+		state = UCODE_ERROR;
+	}
+
+free_table:
 	free_equiv_cpu_table();
 
 	return state;
 }
 
-static enum ucode_state request_microcode_fw(int cpu, struct device *device)
+static enum ucode_state request_microcode_amd(int cpu, struct device *device)
 {
 	const char *fw_name = "amd-ucode/microcode_amd.bin";
-	const struct firmware *firmware;
-	enum ucode_state ret;
+	const struct firmware *fw;
+	enum ucode_state ret = UCODE_NFOUND;
 
-	if (request_firmware(&firmware, fw_name, device)) {
-		printk(KERN_ERR "microcode: failed to load file %s\n", fw_name);
-		return UCODE_NFOUND;
+	if (request_firmware(&fw, fw_name, device)) {
+		pr_err("failed to load file %s\n", fw_name);
+		goto out;
 	}
 
-	if (*(u32 *)firmware->data != UCODE_MAGIC) {
-		pr_err("invalid UCODE_MAGIC (0x%08x)\n",
-		       *(u32 *)firmware->data);
-		return UCODE_ERROR;
+	ret = UCODE_ERROR;
+	if (*(u32 *)fw->data != UCODE_MAGIC) {
+		pr_err("invalid magic value (0x%08x)\n", *(u32 *)fw->data);
+		goto fw_release;
 	}
 
-	ret = generic_load_microcode(cpu, firmware->data, firmware->size);
+	ret = generic_load_microcode(cpu, fw->data, fw->size);
 
-	release_firmware(firmware);
+fw_release:
+	release_firmware(fw);
 
+out:
 	return ret;
 }
 
@@ -319,7 +341,7 @@ static void microcode_fini_cpu_amd(int cpu)
 
 static struct microcode_ops microcode_amd_ops = {
 	.request_microcode_user           = request_microcode_user,
-	.request_microcode_fw             = request_microcode_fw,
+	.request_microcode_fw             = request_microcode_amd,
 	.collect_cpu_info                 = collect_cpu_info_amd,
 	.apply_microcode                  = apply_microcode_amd,
 	.microcode_fini_cpu               = microcode_fini_cpu_amd,
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index 1cca374..87af68e 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -417,8 +417,10 @@ static int mc_sysdev_add(struct sys_device *sys_dev)
 	if (err)
 		return err;
 
-	if (microcode_init_cpu(cpu) == UCODE_ERROR)
-		err = -EINVAL;
+	if (microcode_init_cpu(cpu) == UCODE_ERROR) {
+		sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+		return -EINVAL;
+	}
 
 	return err;
 }
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 01b0f6d..6f789a8 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -883,7 +883,7 @@ static int __init update_mp_table(void)
 
 	if (!mpc_new_phys) {
 		unsigned char old, new;
-		/* check if we can change the postion */
+		/* check if we can change the position */
 		mpc->checksum = 0;
 		old = mpf_checksum((unsigned char *)mpc, mpc->length);
 		mpc->checksum = 0xff;
@@ -892,7 +892,7 @@ static int __init update_mp_table(void)
 			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
 			return 0;
 		}
-		printk(KERN_INFO "use in-positon replacing\n");
+		printk(KERN_INFO "use in-position replacing\n");
 	} else {
 		mpf->physptr = mpc_new_phys;
 		mpc_new = phys_to_virt(mpc_new_phys);
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index f56a117..e8c33a3 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -1279,7 +1279,7 @@ static int __init calgary_bus_has_devices(int bus, unsigned short pci_dev)
 
 	if (pci_dev == PCI_DEVICE_ID_IBM_CALIOC2) {
 		/*
-		 * FIXME: properly scan for devices accross the
+		 * FIXME: properly scan for devices across the
 		 * PCI-to-PCI bridge on every CalIOC2 port.
 		 */
 		return 1;
@@ -1295,7 +1295,7 @@ static int __init calgary_bus_has_devices(int bus, unsigned short pci_dev)
 
 /*
  * calgary_init_bitmap_from_tce_table():
- * Funtion for kdump case. In the second/kdump kernel initialize
+ * Function for kdump case. In the second/kdump kernel initialize
  * the bitmap based on the tce table entries obtained from first kernel
  */
 static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index ff45541..d46cbe4 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -87,7 +87,7 @@ void exit_thread(void)
 void show_regs(struct pt_regs *regs)
 {
 	show_registers(regs);
-	show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs));
+	show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs), 0);
 }
 
 void show_regs_common(void)
@@ -110,12 +110,9 @@ void show_regs_common(void)
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
-	printk(KERN_CONT " ");
-	printk(KERN_CONT "%s %s", vendor, product);
-	if (board) {
-		printk(KERN_CONT "/");
-		printk(KERN_CONT "%s", board);
-	}
+	printk(KERN_CONT " %s %s", vendor, product);
+	if (board)
+		printk(KERN_CONT "/%s", board);
 	printk(KERN_CONT "\n");
 }
 
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 715037c..d3ce37e 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -303,68 +303,16 @@ static int __init reboot_init(void)
 }
 core_initcall(reboot_init);
 
-/* The following code and data reboots the machine by switching to real
-   mode and jumping to the BIOS reset entry point, as if the CPU has
-   really been reset.  The previous version asked the keyboard
-   controller to pulse the CPU reset line, which is more thorough, but
-   doesn't work with at least one type of 486 motherboard.  It is easy
-   to stop this code working; hence the copious comments. */
-static const unsigned long long
-real_mode_gdt_entries [3] =
-{
-	0x0000000000000000ULL,	/* Null descriptor */
-	0x00009b000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
-	0x000093000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
-};
+extern const unsigned char machine_real_restart_asm[];
+extern const u64 machine_real_restart_gdt[3];
 
-static const struct desc_ptr
-real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
-real_mode_idt = { 0x3ff, 0 };
-
-/* This is 16-bit protected mode code to disable paging and the cache,
-   switch to real mode and jump to the BIOS reset code.
-
-   The instruction that switches to real mode by writing to CR0 must be
-   followed immediately by a far jump instruction, which set CS to a
-   valid value for real mode, and flushes the prefetch queue to avoid
-   running instructions that have already been decoded in protected
-   mode.
-
-   Clears all the flags except ET, especially PG (paging), PE
-   (protected-mode enable) and TS (task switch for coprocessor state
-   save).  Flushes the TLB after paging has been disabled.  Sets CD and
-   NW, to disable the cache on a 486, and invalidates the cache.  This
-   is more like the state of a 486 after reset.  I don't know if
-   something else should be done for other chips.
-
-   More could be done here to set up the registers as if a CPU reset had
-   occurred; hopefully real BIOSs don't assume much. */
-static const unsigned char real_mode_switch [] =
-{
-	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
-	0x66, 0x83, 0xe0, 0x11,			/*    andl  $0x00000011,%eax */
-	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
-	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
-	0x66, 0x0f, 0x22, 0xd8,			/*    movl  %eax,%cr3        */
-	0x66, 0x0f, 0x20, 0xc3,			/*    movl  %cr0,%ebx        */
-	0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,	/*    andl  $0x60000000,%ebx */
-	0x74, 0x02,				/*    jz    f                */
-	0x0f, 0x09,				/*    wbinvd                 */
-	0x24, 0x10,				/* f: andb  $0x10,al         */
-	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
-};
-static const unsigned char jump_to_bios [] =
+void machine_real_restart(unsigned int type)
 {
-	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
-};
+	void *restart_va;
+	unsigned long restart_pa;
+	void (*restart_lowmem)(unsigned int);
+	u64 *lowmem_gdt;
 
-/*
- * Switch to real mode and then execute the code
- * specified by the code and length parameters.
- * We assume that length will aways be less that 100!
- */
-void machine_real_restart(const unsigned char *code, int length)
-{
 	local_irq_disable();
 
 	/* Write zero to CMOS register number 0x0f, which the BIOS POST
@@ -392,41 +340,23 @@ void machine_real_restart(const unsigned char *code, int length)
 	   too. */
 	*((unsigned short *)0x472) = reboot_mode;
 
-	/* For the switch to real mode, copy some code to low memory.  It has
-	   to be in the first 64k because it is running in 16-bit mode, and it
-	   has to have the same physical and virtual address, because it turns
-	   off paging.  Copy it near the end of the first page, out of the way
-	   of BIOS variables. */
-	memcpy((void *)(0x1000 - sizeof(real_mode_switch) - 100),
-		real_mode_switch, sizeof (real_mode_switch));
-	memcpy((void *)(0x1000 - 100), code, length);
-
-	/* Set up the IDT for real mode. */
-	load_idt(&real_mode_idt);
-
-	/* Set up a GDT from which we can load segment descriptors for real
-	   mode.  The GDT is not used in real mode; it is just needed here to
-	   prepare the descriptors. */
-	load_gdt(&real_mode_gdt);
-
-	/* Load the data segment registers, and thus the descriptors ready for
-	   real mode.  The base address of each segment is 0x100, 16 times the
-	   selector value being loaded here.  This is so that the segment
-	   registers don't have to be reloaded after switching to real mode:
-	   the values are consistent for real mode operation already. */
-	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
-				"\tmovl %%eax,%%ds\n"
-				"\tmovl %%eax,%%es\n"
-				"\tmovl %%eax,%%fs\n"
-				"\tmovl %%eax,%%gs\n"
-				"\tmovl %%eax,%%ss" : : : "eax");
-
-	/* Jump to the 16-bit code that we copied earlier.  It disables paging
-	   and the cache, switches to real mode, and jumps to the BIOS reset
-	   entry point. */
-	__asm__ __volatile__ ("ljmp $0x0008,%0"
-				:
-				: "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
+	/* Patch the GDT in the low memory trampoline */
+	lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
+
+	restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
+	restart_pa = virt_to_phys(restart_va);
+	restart_lowmem = (void (*)(unsigned int))restart_pa;
+
+	/* GDT[0]: GDT self-pointer */
+	lowmem_gdt[0] =
+		(u64)(sizeof(machine_real_restart_gdt) - 1) +
+		((u64)virt_to_phys(lowmem_gdt) << 16);
+	/* GDT[1]: 64K real mode code segment */
+	lowmem_gdt[1] =
+		GDT_ENTRY(0x009b, restart_pa, 0xffff);
+
+	/* Jump to the identity-mapped low memory code */
+	restart_lowmem(type);
 }
 #ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(machine_real_restart);
@@ -581,7 +511,7 @@ static void native_machine_emergency_restart(void)
 
 #ifdef CONFIG_X86_32
 		case BOOT_BIOS:
-			machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+			machine_real_restart(MRR_BIOS);
 
 			reboot_type = BOOT_KBD;
 			break;
diff --git a/arch/x86/kernel/reboot_32.S b/arch/x86/kernel/reboot_32.S
new file mode 100644
index 0000000..29092b3
--- /dev/null
+++ b/arch/x86/kernel/reboot_32.S
@@ -0,0 +1,135 @@
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/segment.h>
+#include <asm/page_types.h>
+
+/*
+ * The following code and data reboots the machine by switching to real
+ * mode and jumping to the BIOS reset entry point, as if the CPU has
+ * really been reset.  The previous version asked the keyboard
+ * controller to pulse the CPU reset line, which is more thorough, but
+ * doesn't work with at least one type of 486 motherboard.  It is easy
+ * to stop this code working; hence the copious comments.
+ *
+ * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
+ */
+	.section ".x86_trampoline","a"
+	.balign 16
+	.code32
+ENTRY(machine_real_restart_asm)
+r_base = .
+	/* Get our own relocated address */
+	call	1f
+1:	popl	%ebx
+	subl	$1b, %ebx
+
+	/* Compute the equivalent real-mode segment */
+	movl	%ebx, %ecx
+	shrl	$4, %ecx
+	
+	/* Patch post-real-mode segment jump */
+	movw	dispatch_table(%ebx,%eax,2),%ax
+	movw	%ax, 101f(%ebx)
+	movw	%cx, 102f(%ebx)
+
+	/* Set up the IDT for real mode. */
+	lidtl	machine_real_restart_idt(%ebx)
+
+	/*
+	 * Set up a GDT from which we can load segment descriptors for real
+	 * mode.  The GDT is not used in real mode; it is just needed here to
+	 * prepare the descriptors.
+	 */
+	lgdtl	machine_real_restart_gdt(%ebx)
+
+	/*
+	 * Load the data segment registers with 16-bit compatible values
+	 */
+	movl	$16, %ecx
+	movl	%ecx, %ds
+	movl	%ecx, %es
+	movl	%ecx, %fs
+	movl	%ecx, %gs
+	movl	%ecx, %ss
+	ljmpl	$8, $1f - r_base
+
+/*
+ * This is 16-bit protected mode code to disable paging and the cache,
+ * switch to real mode and jump to the BIOS reset code.
+ *
+ * The instruction that switches to real mode by writing to CR0 must be
+ * followed immediately by a far jump instruction, which set CS to a
+ * valid value for real mode, and flushes the prefetch queue to avoid
+ * running instructions that have already been decoded in protected
+ * mode.
+ *
+ * Clears all the flags except ET, especially PG (paging), PE
+ * (protected-mode enable) and TS (task switch for coprocessor state
+ * save).  Flushes the TLB after paging has been disabled.  Sets CD and
+ * NW, to disable the cache on a 486, and invalidates the cache.  This
+ * is more like the state of a 486 after reset.  I don't know if
+ * something else should be done for other chips.
+ *
+ * More could be done here to set up the registers as if a CPU reset had
+ * occurred; hopefully real BIOSs don't assume much.  This is not the
+ * actual BIOS entry point, anyway (that is at 0xfffffff0).
+ *
+ * Most of this work is probably excessive, but it is what is tested.
+ */
+	.code16
+1:
+	xorl	%ecx, %ecx
+	movl	%cr0, %eax
+	andl	$0x00000011, %eax
+	orl	$0x60000000, %eax
+	movl	%eax, %cr0
+	movl	%ecx, %cr3
+	movl	%cr0, %edx
+	andl	$0x60000000, %edx	/* If no cache bits -> no wbinvd */
+	jz	2f
+	wbinvd
+2:
+	andb	$0x10, %al
+	movl	%eax, %cr0
+	.byte	0xea			/* ljmpw */
+101:	.word	0			/* Offset */
+102:	.word	0			/* Segment */
+
+bios:
+	ljmpw	$0xf000, $0xfff0
+
+apm:
+	movw	$0x1000, %ax
+	movw	%ax, %ss
+	movw	$0xf000, %sp
+	movw	$0x5307, %ax
+	movw	$0x0001, %bx
+	movw	$0x0003, %cx
+	int	$0x15
+
+END(machine_real_restart_asm)
+
+	.balign 16
+	/* These must match <asm/reboot.h */
+dispatch_table:
+	.word	bios - r_base
+	.word	apm - r_base
+END(dispatch_table)
+
+	.balign 16
+machine_real_restart_idt:
+	.word	0xffff		/* Length - real mode default value */
+	.long	0		/* Base - real mode default value */
+END(machine_real_restart_idt)
+
+	.balign 16
+ENTRY(machine_real_restart_gdt)
+	.quad	0		/* Self-pointer, filled in by PM code */
+	.quad	0		/* 16-bit code segment, filled in by PM code */
+	/*
+	 * 16-bit data segment with the selector value 16 = 0x10 and
+	 * base value 0x100; since this is consistent with real mode
+	 * semantics we don't have to reload the segments once CR0.PE = 0.
+	 */
+	.quad	GDT_ENTRY(0x0093, 0x100, 0xffff)
+END(machine_real_restart_gdt)
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 6f39cab..3f2ad26 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -6,6 +6,7 @@
 #include <linux/acpi.h>
 #include <linux/bcd.h>
 #include <linux/pnp.h>
+#include <linux/of.h>
 
 #include <asm/vsyscall.h>
 #include <asm/x86_init.h>
@@ -236,6 +237,8 @@ static __init int add_rtc_cmos(void)
 		}
 	}
 #endif
+	if (of_have_populated_dt())
+		return 0;
 
 	platform_device_register(&rtc_device);
 	dev_info(&rtc_device.dev,
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index d3cfe26..32bd87c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -113,6 +113,7 @@
 #endif
 #include <asm/mce.h>
 #include <asm/alternative.h>
+#include <asm/prom.h>
 
 /*
  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -297,6 +298,9 @@ static void __init init_gbpages(void)
 static inline void init_gbpages(void)
 {
 }
+static void __init cleanup_highmap(void)
+{
+}
 #endif
 
 static void __init reserve_brk(void)
@@ -429,16 +433,30 @@ static void __init parse_setup_data(void)
 		return;
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
-		data = early_memremap(pa_data, PAGE_SIZE);
+		u32 data_len, map_len;
+
+		map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK),
+			      (u64)sizeof(struct setup_data));
+		data = early_memremap(pa_data, map_len);
+		data_len = data->len + sizeof(struct setup_data);
+		if (data_len > map_len) {
+			early_iounmap(data, map_len);
+			data = early_memremap(pa_data, data_len);
+			map_len = data_len;
+		}
+
 		switch (data->type) {
 		case SETUP_E820_EXT:
-			parse_e820_ext(data, pa_data);
+			parse_e820_ext(data);
+			break;
+		case SETUP_DTB:
+			add_dtb(pa_data);
 			break;
 		default:
 			break;
 		}
 		pa_data = data->next;
-		early_iounmap(data, PAGE_SIZE);
+		early_iounmap(data, map_len);
 	}
 }
 
@@ -680,15 +698,6 @@ static int __init parse_reservelow(char *p)
 
 early_param("reservelow", parse_reservelow);
 
-static u64 __init get_max_mapped(void)
-{
-	u64 end = max_pfn_mapped;
-
-	end <<= PAGE_SHIFT;
-
-	return end;
-}
-
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -704,8 +713,6 @@ static u64 __init get_max_mapped(void)
 
 void __init setup_arch(char **cmdline_p)
 {
-	int acpi = 0;
-	int amd = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_X86_32
@@ -922,6 +929,8 @@ void __init setup_arch(char **cmdline_p)
 	 */
 	reserve_brk();
 
+	cleanup_highmap();
+
 	memblock.current_limit = get_max_mapped();
 	memblock_x86_fill();
 
@@ -935,15 +944,8 @@ void __init setup_arch(char **cmdline_p)
 	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
 			max_pfn_mapped<<PAGE_SHIFT);
 
-	reserve_trampoline_memory();
+	setup_trampolines();
 
-#ifdef CONFIG_ACPI_SLEEP
-	/*
-	 * Reserve low memory region for sleep support.
-	 * even before init_memory_mapping
-	 */
-	acpi_reserve_wakeup_memory();
-#endif
 	init_gbpages();
 
 	/* max_pfn_mapped is updated here */
@@ -984,19 +986,7 @@ void __init setup_arch(char **cmdline_p)
 
 	early_acpi_boot_init();
 
-#ifdef CONFIG_ACPI_NUMA
-	/*
-	 * Parse SRAT to discover nodes.
-	 */
-	acpi = acpi_numa_init();
-#endif
-
-#ifdef CONFIG_AMD_NUMA
-	if (!acpi)
-		amd = !amd_numa_init(0, max_pfn);
-#endif
-
-	initmem_init(0, max_pfn, acpi, amd);
+	initmem_init();
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
@@ -1029,8 +1019,8 @@ void __init setup_arch(char **cmdline_p)
 	 * Read APIC and some other early information from ACPI tables.
 	 */
 	acpi_boot_init();
-
 	sfi_init();
+	x86_dtb_init();
 
 	/*
 	 * get boot-time SMP configuration:
@@ -1040,9 +1030,7 @@ void __init setup_arch(char **cmdline_p)
 
 	prefill_possible_map();
 
-#ifdef CONFIG_X86_64
 	init_cpu_to_node();
-#endif
 
 	init_apic_mappings();
 	ioapic_and_gsi_init();
@@ -1066,6 +1054,8 @@ void __init setup_arch(char **cmdline_p)
 #endif
 	x86_init.oem.banner();
 
+	x86_init.timers.wallclock_init();
+
 	mcheck_init();
 
 	local_irq_save(flags);
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 002b796..71f4727 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -225,10 +225,15 @@ void __init setup_per_cpu_areas(void)
 		per_cpu(x86_bios_cpu_apicid, cpu) =
 			early_per_cpu_map(x86_bios_cpu_apicid, cpu);
 #endif
+#ifdef CONFIG_X86_32
+		per_cpu(x86_cpu_to_logical_apicid, cpu) =
+			early_per_cpu_map(x86_cpu_to_logical_apicid, cpu);
+#endif
 #ifdef CONFIG_X86_64
 		per_cpu(irq_stack_ptr, cpu) =
 			per_cpu(irq_stack_union.irq_stack, cpu) +
 			IRQ_STACK_SIZE - 64;
+#endif
 #ifdef CONFIG_NUMA
 		per_cpu(x86_cpu_to_node_map, cpu) =
 			early_per_cpu_map(x86_cpu_to_node_map, cpu);
@@ -242,7 +247,6 @@ void __init setup_per_cpu_areas(void)
 		 */
 		set_cpu_numa_node(cpu, early_cpu_to_node(cpu));
 #endif
-#endif
 		/*
 		 * Up to this point, the boot CPU has been using .init.data
 		 * area.  Reload any changed state for the boot CPU.
@@ -256,7 +260,10 @@ void __init setup_per_cpu_areas(void)
 	early_per_cpu_ptr(x86_cpu_to_apicid) = NULL;
 	early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL;
 #endif
-#if defined(CONFIG_X86_64) && defined(CONFIG_NUMA)
+#ifdef CONFIG_X86_32
+	early_per_cpu_ptr(x86_cpu_to_logical_apicid) = NULL;
+#endif
+#ifdef CONFIG_NUMA
 	early_per_cpu_ptr(x86_cpu_to_node_map) = NULL;
 #endif
 
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 08776a9..c2871d3 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -64,6 +64,7 @@
 #include <asm/mtrr.h>
 #include <asm/mwait.h>
 #include <asm/apic.h>
+#include <asm/io_apic.h>
 #include <asm/setup.h>
 #include <asm/uv/uv.h>
 #include <linux/mc146818rtc.h>
@@ -71,10 +72,6 @@
 #include <asm/smpboot_hooks.h>
 #include <asm/i8259.h>
 
-#ifdef CONFIG_X86_32
-u8 apicid_2_node[MAX_APICID];
-#endif
-
 /* State of each CPU */
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
@@ -130,68 +127,14 @@ EXPORT_PER_CPU_SYMBOL(cpu_sibling_map);
 DEFINE_PER_CPU(cpumask_var_t, cpu_core_map);
 EXPORT_PER_CPU_SYMBOL(cpu_core_map);
 
+DEFINE_PER_CPU(cpumask_var_t, cpu_llc_shared_map);
+
 /* Per CPU bogomips and other parameters */
 DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 atomic_t init_deasserted;
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_32)
-/* which node each logical CPU is on */
-int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
-EXPORT_SYMBOL(cpu_to_node_map);
-
-/* set up a mapping between cpu and node. */
-static void map_cpu_to_node(int cpu, int node)
-{
-	printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node);
-	cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
-	cpu_to_node_map[cpu] = node;
-}
-
-/* undo a mapping between cpu and node. */
-static void unmap_cpu_to_node(int cpu)
-{
-	int node;
-
-	printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu);
-	for (node = 0; node < MAX_NUMNODES; node++)
-		cpumask_clear_cpu(cpu, node_to_cpumask_map[node]);
-	cpu_to_node_map[cpu] = 0;
-}
-#else /* !(CONFIG_NUMA && CONFIG_X86_32) */
-#define map_cpu_to_node(cpu, node)	({})
-#define unmap_cpu_to_node(cpu)	({})
-#endif
-
-#ifdef CONFIG_X86_32
-static int boot_cpu_logical_apicid;
-
-u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
-					{ [0 ... NR_CPUS-1] = BAD_APICID };
-
-static void map_cpu_to_logical_apicid(void)
-{
-	int cpu = smp_processor_id();
-	int apicid = logical_smp_processor_id();
-	int node = apic->apicid_to_node(apicid);
-
-	if (!node_online(node))
-		node = first_online_node;
-
-	cpu_2_logical_apicid[cpu] = apicid;
-	map_cpu_to_node(cpu, node);
-}
-
-void numa_remove_cpu(int cpu)
-{
-	cpu_2_logical_apicid[cpu] = BAD_APICID;
-	unmap_cpu_to_node(cpu);
-}
-#else
-#define map_cpu_to_logical_apicid()  do {} while (0)
-#endif
-
 /*
  * Report back to the Boot Processor.
  * Running on AP.
@@ -259,7 +202,6 @@ static void __cpuinit smp_callin(void)
 		apic->smp_callin_clear_local_apic();
 	setup_local_APIC();
 	end_local_APIC_setup();
-	map_cpu_to_logical_apicid();
 
 	/*
 	 * Need to setup vector mappings before we enable interrupts.
@@ -355,23 +297,6 @@ notrace static void __cpuinit start_secondary(void *unused)
 	cpu_idle();
 }
 
-#ifdef CONFIG_CPUMASK_OFFSTACK
-/* In this case, llc_shared_map is a pointer to a cpumask. */
-static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst,
-				    const struct cpuinfo_x86 *src)
-{
-	struct cpumask *llc = dst->llc_shared_map;
-	*dst = *src;
-	dst->llc_shared_map = llc;
-}
-#else
-static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst,
-				    const struct cpuinfo_x86 *src)
-{
-	*dst = *src;
-}
-#endif /* CONFIG_CPUMASK_OFFSTACK */
-
 /*
  * The bootstrap kernel entry code has set these up. Save them for
  * a given CPU
@@ -381,7 +306,7 @@ void __cpuinit smp_store_cpu_info(int id)
 {
 	struct cpuinfo_x86 *c = &cpu_data(id);
 
-	copy_cpuinfo_x86(c, &boot_cpu_data);
+	*c = boot_cpu_data;
 	c->cpu_index = id;
 	if (id != 0)
 		identify_secondary_cpu(c);
@@ -389,15 +314,12 @@ void __cpuinit smp_store_cpu_info(int id)
 
 static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
 {
-	struct cpuinfo_x86 *c1 = &cpu_data(cpu1);
-	struct cpuinfo_x86 *c2 = &cpu_data(cpu2);
-
 	cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
 	cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1));
 	cpumask_set_cpu(cpu1, cpu_core_mask(cpu2));
 	cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
-	cpumask_set_cpu(cpu1, c2->llc_shared_map);
-	cpumask_set_cpu(cpu2, c1->llc_shared_map);
+	cpumask_set_cpu(cpu1, cpu_llc_shared_mask(cpu2));
+	cpumask_set_cpu(cpu2, cpu_llc_shared_mask(cpu1));
 }
 
 
@@ -414,6 +336,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
 
 			if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
 				if (c->phys_proc_id == o->phys_proc_id &&
+				    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i) &&
 				    c->compute_unit_id == o->compute_unit_id)
 					link_thread_siblings(cpu, i);
 			} else if (c->phys_proc_id == o->phys_proc_id &&
@@ -425,7 +348,7 @@ void __cpuinit set_cpu_sibling_map(int cpu)
 		cpumask_set_cpu(cpu, cpu_sibling_mask(cpu));
 	}
 
-	cpumask_set_cpu(cpu, c->llc_shared_map);
+	cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
 
 	if (__this_cpu_read(cpu_info.x86_max_cores) == 1) {
 		cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu));
@@ -436,8 +359,8 @@ void __cpuinit set_cpu_sibling_map(int cpu)
 	for_each_cpu(i, cpu_sibling_setup_mask) {
 		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
 		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
-			cpumask_set_cpu(i, c->llc_shared_map);
-			cpumask_set_cpu(cpu, cpu_data(i).llc_shared_map);
+			cpumask_set_cpu(i, cpu_llc_shared_mask(cpu));
+			cpumask_set_cpu(cpu, cpu_llc_shared_mask(i));
 		}
 		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
 			cpumask_set_cpu(i, cpu_core_mask(cpu));
@@ -476,7 +399,7 @@ const struct cpumask *cpu_coregroup_mask(int cpu)
 	    !(cpu_has(c, X86_FEATURE_AMD_DCM)))
 		return cpu_core_mask(cpu);
 	else
-		return c->llc_shared_map;
+		return cpu_llc_shared_mask(cpu);
 }
 
 static void impress_friends(void)
@@ -788,7 +711,7 @@ do_rest:
 	stack_start  = c_idle.idle->thread.sp;
 
 	/* start_ip had better be page-aligned! */
-	start_ip = setup_trampoline();
+	start_ip = trampoline_address();
 
 	/* So we see what's up */
 	announce_cpu(cpu, apicid);
@@ -798,6 +721,8 @@ do_rest:
 	 * the targeted processor.
 	 */
 
+	printk(KERN_DEBUG "smpboot cpu %d: start_ip = %lx\n", cpu, start_ip);
+
 	atomic_set(&init_deasserted, 0);
 
 	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
@@ -851,8 +776,8 @@ do_rest:
 			pr_debug("CPU%d: has booted.\n", cpu);
 		else {
 			boot_error = 1;
-			if (*((volatile unsigned char *)trampoline_base)
-					== 0xA5)
+			if (*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status)
+			    == 0xA5A5A5A5)
 				/* trampoline started but...? */
 				pr_err("CPU%d: Stuck ??\n", cpu);
 			else
@@ -878,7 +803,7 @@ do_rest:
 	}
 
 	/* mark "stuck" area as not stuck */
-	*((volatile unsigned long *)trampoline_base) = 0;
+	*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) = 0;
 
 	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
 		/*
@@ -945,6 +870,14 @@ int __cpuinit native_cpu_up(unsigned int cpu)
 	return 0;
 }
 
+/**
+ * arch_disable_smp_support() - disables SMP support for x86 at runtime
+ */
+void arch_disable_smp_support(void)
+{
+	disable_ioapic_support();
+}
+
 /*
  * Fall back to non SMP mode after errors.
  *
@@ -960,7 +893,6 @@ static __init void disable_smp(void)
 		physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
 	else
 		physid_set_mask_of_physid(0, &phys_cpu_present_map);
-	map_cpu_to_logical_apicid();
 	cpumask_set_cpu(0, cpu_sibling_mask(0));
 	cpumask_set_cpu(0, cpu_core_mask(0));
 }
@@ -1045,7 +977,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
 				"(tell your hw vendor)\n");
 		}
 		smpboot_clear_io_apic();
-		arch_disable_smp_support();
+		disable_ioapic_support();
 		return -1;
 	}
 
@@ -1089,21 +1021,19 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 	preempt_disable();
 	smp_cpu_index_default();
-	memcpy(__this_cpu_ptr(&cpu_info), &boot_cpu_data, sizeof(cpu_info));
-	cpumask_copy(cpu_callin_mask, cpumask_of(0));
-	mb();
+
 	/*
 	 * Setup boot CPU information
 	 */
 	smp_store_cpu_info(0); /* Final full version of the data */
-#ifdef CONFIG_X86_32
-	boot_cpu_logical_apicid = logical_smp_processor_id();
-#endif
+	cpumask_copy(cpu_callin_mask, cpumask_of(0));
+	mb();
+
 	current_thread_info()->cpu = 0;  /* needed? */
 	for_each_possible_cpu(i) {
 		zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
 		zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
-		zalloc_cpumask_var(&cpu_data(i).llc_shared_map, GFP_KERNEL);
+		zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
 	}
 	set_cpu_sibling_map(0);
 
@@ -1139,8 +1069,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 	bsp_end_local_APIC_setup();
 
-	map_cpu_to_logical_apicid();
-
 	if (apic->setup_portio_remap)
 		apic->setup_portio_remap();
 
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 938c8e1..6515733 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -73,7 +73,7 @@ static const struct stacktrace_ops save_stack_ops_nosched = {
  */
 void save_stack_trace(struct stack_trace *trace)
 {
-	dump_trace(current, NULL, NULL, &save_stack_ops, trace);
+	dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
@@ -81,14 +81,14 @@ EXPORT_SYMBOL_GPL(save_stack_trace);
 
 void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs)
 {
-	dump_trace(current, regs, NULL, &save_stack_ops, trace);
+	dump_trace(current, regs, NULL, 0, &save_stack_ops, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
 
 void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 {
-	dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace);
+	dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index 58de45e..7977f0c 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -166,7 +166,7 @@ static void enable_step(struct task_struct *child, bool block)
 	 * Make sure block stepping (BTF) is not enabled unless it should be.
 	 * Note that we don't try to worry about any is_setting_trap_flag()
 	 * instructions after the first when using block stepping.
-	 * So noone should try to use debugger block stepping in a program
+	 * So no one should try to use debugger block stepping in a program
 	 * that uses user-mode single stepping itself.
 	 */
 	if (enable_single_step(child) && block) {
diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
index b35786d..abce34d 100644
--- a/arch/x86/kernel/syscall_table_32.S
+++ b/arch/x86/kernel/syscall_table_32.S
@@ -340,3 +340,7 @@ ENTRY(sys_call_table)
 	.long sys_fanotify_init
 	.long sys_fanotify_mark
 	.long sys_prlimit64		/* 340 */
+	.long sys_name_to_handle_at
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
+	.long sys_syncfs
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index 7e45159..8927486 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -39,7 +39,7 @@ int __ref arch_register_cpu(int num)
 	/*
 	 * CPU0 cannot be offlined due to several
 	 * restrictions and assumptions in kernel. This basically
-	 * doesnt add a control file, one cannot attempt to offline
+	 * doesn't add a control file, one cannot attempt to offline
 	 * BSP.
 	 *
 	 * Also certain PCI quirks require not to enable hotplug control
diff --git a/arch/x86/kernel/trampoline.c b/arch/x86/kernel/trampoline.c
index a375616..a91ae77 100644
--- a/arch/x86/kernel/trampoline.c
+++ b/arch/x86/kernel/trampoline.c
@@ -2,39 +2,41 @@
 #include <linux/memblock.h>
 
 #include <asm/trampoline.h>
+#include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
-#define __trampinit
-#define __trampinitdata
-#else
-#define __trampinit __cpuinit
-#define __trampinitdata __cpuinitdata
-#endif
+unsigned char *x86_trampoline_base;
 
-/* ready for x86_64 and x86 */
-unsigned char *__trampinitdata trampoline_base;
-
-void __init reserve_trampoline_memory(void)
+void __init setup_trampolines(void)
 {
 	phys_addr_t mem;
+	size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
 
 	/* Has to be in very low memory so we can execute real-mode AP code. */
-	mem = memblock_find_in_range(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
+	mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
 	if (mem == MEMBLOCK_ERROR)
 		panic("Cannot allocate trampoline\n");
 
-	trampoline_base = __va(mem);
-	memblock_x86_reserve_range(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
+	x86_trampoline_base = __va(mem);
+	memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE");
+
+	printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
+	       x86_trampoline_base, (unsigned long long)mem, size);
+
+	memcpy(x86_trampoline_base, x86_trampoline_start, size);
 }
 
 /*
- * Currently trivial. Write the real->protected mode
- * bootstrap into the page concerned. The caller
- * has made sure it's suitably aligned.
+ * setup_trampolines() gets called very early, to guarantee the
+ * availability of low memory.  This is before the proper kernel page
+ * tables are set up, so we cannot set page permissions in that
+ * function.  Thus, we use an arch_initcall instead.
  */
-unsigned long __trampinit setup_trampoline(void)
+static int __init configure_trampolines(void)
 {
-	memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
-	return virt_to_phys(trampoline_base);
+	size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
+
+	set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT);
+	return 0;
 }
+arch_initcall(configure_trampolines);
diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
index 8508237..451c0a7 100644
--- a/arch/x86/kernel/trampoline_32.S
+++ b/arch/x86/kernel/trampoline_32.S
@@ -32,9 +32,11 @@
 #include <asm/segment.h>
 #include <asm/page_types.h>
 
-/* We can free up trampoline after bootup if cpu hotplug is not supported. */
-__CPUINITRODATA
-.code16
+#ifdef CONFIG_SMP
+
+	.section ".x86_trampoline","a"
+	.balign PAGE_SIZE
+	.code16
 
 ENTRY(trampoline_data)
 r_base = .
@@ -44,7 +46,7 @@ r_base = .
 
 	cli			# We should be safe anyway
 
-	movl	$0xA5A5A5A5, trampoline_data - r_base
+	movl	$0xA5A5A5A5, trampoline_status - r_base
 				# write marker for master knows we're running
 
 	/* GDT tables in non default location kernel can be beyond 16MB and
@@ -72,5 +74,10 @@ boot_idt_descr:
 	.word	0				# idt limit = 0
 	.long	0				# idt base = 0L
 
+ENTRY(trampoline_status)
+	.long	0
+
 .globl trampoline_end
 trampoline_end:
+
+#endif /* CONFIG_SMP */
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
index 075d130..09ff517 100644
--- a/arch/x86/kernel/trampoline_64.S
+++ b/arch/x86/kernel/trampoline_64.S
@@ -32,13 +32,9 @@
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
 
-#ifdef CONFIG_ACPI_SLEEP
-.section .rodata, "a", @progbits
-#else
-/* We can free up the trampoline after bootup if cpu hotplug is not supported. */
-__CPUINITRODATA
-#endif
-.code16
+	.section ".x86_trampoline","a"
+	.balign PAGE_SIZE
+	.code16
 
 ENTRY(trampoline_data)
 r_base = .
@@ -50,7 +46,7 @@ r_base = .
 	mov	%ax, %ss
 
 
-	movl	$0xA5A5A5A5, trampoline_data - r_base
+	movl	$0xA5A5A5A5, trampoline_status - r_base
 				# write marker for master knows we're running
 
 					# Setup stack
@@ -64,10 +60,13 @@ r_base = .
 	movzx	%ax, %esi		# Find the 32bit trampoline location
 	shll	$4, %esi
 
-					# Fixup the vectors
-	addl	%esi, startup_32_vector - r_base
-	addl	%esi, startup_64_vector - r_base
-	addl	%esi, tgdt + 2 - r_base	# Fixup the gdt pointer
+					# Fixup the absolute vectors
+	leal	(startup_32 - r_base)(%esi), %eax
+	movl	%eax, startup_32_vector - r_base
+	leal	(startup_64 - r_base)(%esi), %eax
+	movl	%eax, startup_64_vector - r_base
+	leal	(tgdt - r_base)(%esi), %eax
+	movl	%eax, (tgdt + 2 - r_base)
 
 	/*
 	 * GDT tables in non default location kernel can be beyond 16MB and
@@ -129,6 +128,7 @@ no_longmode:
 	jmp no_longmode
 #include "verify_cpu.S"
 
+	.balign 4
 	# Careful these need to be in the same 64K segment as the above;
 tidt:
 	.word	0			# idt limit = 0
@@ -156,6 +156,10 @@ startup_64_vector:
 	.long	startup_64 - r_base
 	.word	__KERNEL_CS, 0
 
+	.balign 4
+ENTRY(trampoline_status)
+	.long	0
+
 trampoline_stack:
 	.org 0x1000
 trampoline_stack_end:
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index ffe5755..9335bf7 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -427,7 +427,7 @@ unsigned long native_calibrate_tsc(void)
 	 * the delta to the previous read. We keep track of the min
 	 * and max values of that delta. The delta is mostly defined
 	 * by the IO time of the PIT access, so we can detect when a
-	 * SMI/SMM disturbance happend between the two reads. If the
+	 * SMI/SMM disturbance happened between the two reads. If the
 	 * maximum time is significantly larger than the minimum time,
 	 * then we discard the result and have another try.
 	 *
@@ -900,7 +900,7 @@ static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
  * timer based, instead of loop based, we don't block the boot
  * process while this longer calibration is done.
  *
- * If there are any calibration anomolies (too many SMIs, etc),
+ * If there are any calibration anomalies (too many SMIs, etc),
  * or the refined calibration is off by 1% of the fast early
  * calibration, we throw out the new calibration and use the
  * early calibration.
diff --git a/arch/x86/kernel/verify_cpu.S b/arch/x86/kernel/verify_cpu.S
index 0edefc1..b9242ba 100644
--- a/arch/x86/kernel/verify_cpu.S
+++ b/arch/x86/kernel/verify_cpu.S
@@ -18,7 +18,7 @@
  *	This file is expected to run in 32bit code.  Currently:
  *
  *	arch/x86/boot/compressed/head_64.S: Boot cpu verification
- *	arch/x86/kernel/trampoline_64.S: secondary processor verfication
+ *	arch/x86/kernel/trampoline_64.S: secondary processor verification
  *	arch/x86/kernel/head_32.S: processor startup
  *
  *	verify_cpu, returns the status of longmode and SSE in register %eax.
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index bf47007..624a201 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -105,6 +105,7 @@ SECTIONS
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		ENTRY_TEXT
 		IRQENTRY_TEXT
 		*(.fixup)
 		*(.gnu.warning)
@@ -230,7 +231,7 @@ SECTIONS
 	 * output PHDR, so the next output section - .init.text - should
 	 * start another segment - init.
 	 */
-	PERCPU_VADDR(0, :percpu)
+	PERCPU_VADDR(INTERNODE_CACHE_BYTES, 0, :percpu)
 #endif
 
 	INIT_TEXT_SECTION(PAGE_SIZE)
@@ -240,6 +241,18 @@ SECTIONS
 
 	INIT_DATA_SECTION(16)
 
+	/*
+	 * Code and data for a variety of lowlevel trampolines, to be
+	 * copied into base memory (< 1 MiB) during initialization.
+	 * Since it is copied early, the main copy can be discarded
+	 * afterwards.
+	 */
+	 .x86_trampoline : AT(ADDR(.x86_trampoline) - LOAD_OFFSET) {
+		x86_trampoline_start = .;
+		*(.x86_trampoline)
+		x86_trampoline_end = .;
+	}
+
 	.x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
 		__x86_cpu_dev_start = .;
 		*(.x86_cpu_dev.init)
@@ -291,6 +304,7 @@ SECTIONS
 		*(.iommu_table)
 		__iommu_table_end = .;
 	}
+
 	. = ALIGN(8);
 	/*
 	 * .exit.text is discard at runtime, not link time, to deal with
@@ -305,7 +319,7 @@ SECTIONS
 	}
 
 #if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
-	PERCPU(THREAD_SIZE)
+	PERCPU(INTERNODE_CACHE_BYTES, PAGE_SIZE)
 #endif
 
 	. = ALIGN(PAGE_SIZE);
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 1b950d1..9796c2f 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -52,6 +52,7 @@ extern void *__memcpy(void *, const void *, __kernel_size_t);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(empty_zero_page);
 #ifndef CONFIG_PARAVIRT
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index ceb2911..c11514e 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -70,6 +70,7 @@ struct x86_init_ops x86_init __initdata = {
 		.setup_percpu_clockev	= setup_boot_APIC_clock,
 		.tsc_pre_init		= x86_init_noop,
 		.timer_init		= hpet_time_init,
+		.wallclock_init		= x86_init_noop,
 	},
 
 	.iommu = {
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index 5471285..a391134 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -53,7 +53,7 @@ void __sanitize_i387_state(struct task_struct *tsk)
 
 	/*
 	 * None of the feature bits are in init state. So nothing else
-	 * to do for us, as the memory layout is upto date.
+	 * to do for us, as the memory layout is up to date.
 	 */
 	if ((xstate_bv & pcntxt_mask) == pcntxt_mask)
 		return;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index caf9667..0ad47b8 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -76,6 +76,7 @@
 #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
 #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
 /* Misc flags */
+#define VendorSpecific (1<<22) /* Vendor specific instruction */
 #define NoAccess    (1<<23) /* Don't access memory (lea/invlpg/verr etc) */
 #define Op3264      (1<<24) /* Operand is 64b in long mode, 32b otherwise */
 #define Undefined   (1<<25) /* No Such Instruction */
@@ -877,7 +878,8 @@ static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
 	if (selector & 1 << 2) {
 		struct desc_struct desc;
 		memset (dt, 0, sizeof *dt);
-		if (!ops->get_cached_descriptor(&desc, VCPU_SREG_LDTR, ctxt->vcpu))
+		if (!ops->get_cached_descriptor(&desc, NULL, VCPU_SREG_LDTR,
+						ctxt->vcpu))
 			return;
 
 		dt->size = desc_limit_scaled(&desc); /* what if limit > 65535? */
@@ -929,6 +931,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	return ret;
 }
 
+/* Does not support long mode */
 static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 				   struct x86_emulate_ops *ops,
 				   u16 selector, int seg)
@@ -1040,7 +1043,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 	}
 load:
 	ops->set_segment_selector(selector, seg, ctxt->vcpu);
-	ops->set_cached_descriptor(&seg_desc, seg, ctxt->vcpu);
+	ops->set_cached_descriptor(&seg_desc, 0, seg, ctxt->vcpu);
 	return X86EMUL_CONTINUE;
 exception:
 	emulate_exception(ctxt, err_vec, err_code, true);
@@ -1560,7 +1563,7 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
 			struct desc_struct *ss)
 {
 	memset(cs, 0, sizeof(struct desc_struct));
-	ops->get_cached_descriptor(cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->get_cached_descriptor(cs, NULL, VCPU_SREG_CS, ctxt->vcpu);
 	memset(ss, 0, sizeof(struct desc_struct));
 
 	cs->l = 0;		/* will be adjusted later */
@@ -1607,9 +1610,9 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 		cs.d = 0;
 		cs.l = 1;
 	}
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	c->regs[VCPU_REGS_RCX] = c->eip;
@@ -1679,9 +1682,9 @@ emulate_sysenter(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 		cs.l = 1;
 	}
 
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
@@ -1736,9 +1739,9 @@ emulate_sysexit(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
 	cs_sel |= SELECTOR_RPL_MASK;
 	ss_sel |= SELECTOR_RPL_MASK;
 
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	c->eip = c->regs[VCPU_REGS_RDX];
@@ -1764,24 +1767,28 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
 					    u16 port, u16 len)
 {
 	struct desc_struct tr_seg;
+	u32 base3;
 	int r;
-	u16 io_bitmap_ptr;
-	u8 perm, bit_idx = port & 0x7;
+	u16 io_bitmap_ptr, perm, bit_idx = port & 0x7;
 	unsigned mask = (1 << len) - 1;
+	unsigned long base;
 
-	ops->get_cached_descriptor(&tr_seg, VCPU_SREG_TR, ctxt->vcpu);
+	ops->get_cached_descriptor(&tr_seg, &base3, VCPU_SREG_TR, ctxt->vcpu);
 	if (!tr_seg.p)
 		return false;
 	if (desc_limit_scaled(&tr_seg) < 103)
 		return false;
-	r = ops->read_std(get_desc_base(&tr_seg) + 102, &io_bitmap_ptr, 2,
-			  ctxt->vcpu, NULL);
+	base = get_desc_base(&tr_seg);
+#ifdef CONFIG_X86_64
+	base |= ((u64)base3) << 32;
+#endif
+	r = ops->read_std(base + 102, &io_bitmap_ptr, 2, ctxt->vcpu, NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
 	if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
 		return false;
-	r = ops->read_std(get_desc_base(&tr_seg) + io_bitmap_ptr + port/8,
-			  &perm, 1, ctxt->vcpu, NULL);
+	r = ops->read_std(base + io_bitmap_ptr + port/8, &perm, 2, ctxt->vcpu,
+			  NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
 	if ((perm >> bit_idx) & mask)
@@ -2126,7 +2133,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt,
 	}
 
 	ops->set_cr(0,  ops->get_cr(0, ctxt->vcpu) | X86_CR0_TS, ctxt->vcpu);
-	ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu);
+	ops->set_cached_descriptor(&next_tss_desc, 0, VCPU_SREG_TR, ctxt->vcpu);
 	ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu);
 
 	if (has_error_code) {
@@ -2365,7 +2372,8 @@ static struct group_dual group7 = { {
 	D(SrcMem16 | ModRM | Mov | Priv),
 	D(SrcMem | ModRM | ByteOp | Priv | NoAccess),
 }, {
-	D(SrcNone | ModRM | Priv), N, N, D(SrcNone | ModRM | Priv),
+	D(SrcNone | ModRM | Priv | VendorSpecific), N,
+	N, D(SrcNone | ModRM | Priv | VendorSpecific),
 	D(SrcNone | ModRM | DstMem | Mov), N,
 	D(SrcMem16 | ModRM | Mov | Priv), N,
 } };
@@ -2489,7 +2497,7 @@ static struct opcode opcode_table[256] = {
 static struct opcode twobyte_table[256] = {
 	/* 0x00 - 0x0F */
 	N, GD(0, &group7), N, N,
-	N, D(ImplicitOps), D(ImplicitOps | Priv), N,
+	N, D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv), N,
 	D(ImplicitOps | Priv), D(ImplicitOps | Priv), N, N,
 	N, D(ImplicitOps | ModRM), N, N,
 	/* 0x10 - 0x1F */
@@ -2502,7 +2510,8 @@ static struct opcode twobyte_table[256] = {
 	/* 0x30 - 0x3F */
 	D(ImplicitOps | Priv), I(ImplicitOps, em_rdtsc),
 	D(ImplicitOps | Priv), N,
-	D(ImplicitOps), D(ImplicitOps | Priv), N, N,
+	D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv | VendorSpecific),
+	N, N,
 	N, N, N, N, N, N, N, N,
 	/* 0x40 - 0x4F */
 	X16(D(DstReg | SrcMem | ModRM | Mov)),
@@ -2741,6 +2750,9 @@ done_prefixes:
 	if (c->d == 0 || (c->d & Undefined))
 		return -1;
 
+	if (!(c->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
+		return -1;
+
 	if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
 		c->op_bytes = 8;
 
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index 3cece05..19fe855 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -62,9 +62,6 @@ static void pic_unlock(struct kvm_pic *s)
 		}
 
 		if (!found)
-			found = s->kvm->bsp_vcpu;
-
-		if (!found)
 			return;
 
 		kvm_make_request(KVM_REQ_EVENT, found);
@@ -75,7 +72,6 @@ static void pic_unlock(struct kvm_pic *s)
 static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
 {
 	s->isr &= ~(1 << irq);
-	s->isr_ack |= (1 << irq);
 	if (s != &s->pics_state->pics[0])
 		irq += 8;
 	/*
@@ -89,16 +85,6 @@ static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
 	pic_lock(s->pics_state);
 }
 
-void kvm_pic_clear_isr_ack(struct kvm *kvm)
-{
-	struct kvm_pic *s = pic_irqchip(kvm);
-
-	pic_lock(s);
-	s->pics[0].isr_ack = 0xff;
-	s->pics[1].isr_ack = 0xff;
-	pic_unlock(s);
-}
-
 /*
  * set irq level. If an edge is detected, then the IRR is set to 1
  */
@@ -281,7 +267,6 @@ void kvm_pic_reset(struct kvm_kpic_state *s)
 	s->irr = 0;
 	s->imr = 0;
 	s->isr = 0;
-	s->isr_ack = 0xff;
 	s->priority_add = 0;
 	s->irq_base = 0;
 	s->read_reg_select = 0;
@@ -545,15 +530,11 @@ static int picdev_read(struct kvm_io_device *this,
  */
 static void pic_irq_request(struct kvm *kvm, int level)
 {
-	struct kvm_vcpu *vcpu = kvm->bsp_vcpu;
 	struct kvm_pic *s = pic_irqchip(kvm);
-	int irq = pic_get_irq(&s->pics[0]);
 
-	s->output = level;
-	if (vcpu && level && (s->pics[0].isr_ack & (1 << irq))) {
-		s->pics[0].isr_ack &= ~(1 << irq);
+	if (!s->output)
 		s->wakeup_needed = true;
-	}
+	s->output = level;
 }
 
 static const struct kvm_io_device_ops picdev_ops = {
@@ -575,8 +556,6 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
 	s->pics[1].elcr_mask = 0xde;
 	s->pics[0].pics_state = s;
 	s->pics[1].pics_state = s;
-	s->pics[0].isr_ack = 0xff;
-	s->pics[1].isr_ack = 0xff;
 
 	/*
 	 * Initialize PIO device
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 93cf9d0..2b2255b 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -417,10 +417,6 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
 	case APIC_DM_INIT:
 		if (level) {
 			result = 1;
-			if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE)
-				printk(KERN_DEBUG
-				       "INIT on a runnable vcpu %d\n",
-				       vcpu->vcpu_id);
 			vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
 			kvm_make_request(KVM_REQ_EVENT, vcpu);
 			kvm_vcpu_kick(vcpu);
@@ -875,8 +871,8 @@ void kvm_free_lapic(struct kvm_vcpu *vcpu)
 
 	hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
 
-	if (vcpu->arch.apic->regs_page)
-		__free_page(vcpu->arch.apic->regs_page);
+	if (vcpu->arch.apic->regs)
+		free_page((unsigned long)vcpu->arch.apic->regs);
 
 	kfree(vcpu->arch.apic);
 }
@@ -1065,13 +1061,12 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu)
 
 	vcpu->arch.apic = apic;
 
-	apic->regs_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
-	if (apic->regs_page == NULL) {
+	apic->regs = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!apic->regs) {
 		printk(KERN_ERR "malloc apic regs error for vcpu %x\n",
 		       vcpu->vcpu_id);
 		goto nomem_free_apic;
 	}
-	apic->regs = page_address(apic->regs_page);
 	apic->vcpu = vcpu;
 
 	hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index f5fe32c..52c9e6b 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -13,7 +13,6 @@ struct kvm_lapic {
 	u32 divide_count;
 	struct kvm_vcpu *vcpu;
 	bool irr_pending;
-	struct page *regs_page;
 	void *regs;
 	gpa_t vapic_addr;
 	struct page *vapic_page;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index f02b8ed..22fae75 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -111,9 +111,6 @@ module_param(oos_shadow, bool, 0644);
 #define PT64_LEVEL_SHIFT(level) \
 		(PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS)
 
-#define PT64_LEVEL_MASK(level) \
-		(((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level))
-
 #define PT64_INDEX(address, level)\
 	(((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
 
@@ -123,8 +120,6 @@ module_param(oos_shadow, bool, 0644);
 #define PT32_LEVEL_SHIFT(level) \
 		(PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS)
 
-#define PT32_LEVEL_MASK(level) \
-		(((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level))
 #define PT32_LVL_OFFSET_MASK(level) \
 	(PT32_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \
 						* PT32_LEVEL_BITS))) - 1))
@@ -379,15 +374,15 @@ static void mmu_free_memory_cache(struct kvm_mmu_memory_cache *mc,
 static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache,
 				       int min)
 {
-	struct page *page;
+	void *page;
 
 	if (cache->nobjs >= min)
 		return 0;
 	while (cache->nobjs < ARRAY_SIZE(cache->objects)) {
-		page = alloc_page(GFP_KERNEL);
+		page = (void *)__get_free_page(GFP_KERNEL);
 		if (!page)
 			return -ENOMEM;
-		cache->objects[cache->nobjs++] = page_address(page);
+		cache->objects[cache->nobjs++] = page;
 	}
 	return 0;
 }
@@ -554,13 +549,23 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn)
 	return ret;
 }
 
-static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+static struct kvm_memory_slot *
+gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn,
+			    bool no_dirty_log)
 {
 	struct kvm_memory_slot *slot;
-	slot = gfn_to_memslot(vcpu->kvm, large_gfn);
-	if (slot && slot->dirty_bitmap)
-		return true;
-	return false;
+
+	slot = gfn_to_memslot(vcpu->kvm, gfn);
+	if (!slot || slot->flags & KVM_MEMSLOT_INVALID ||
+	      (no_dirty_log && slot->dirty_bitmap))
+		slot = NULL;
+
+	return slot;
+}
+
+static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+{
+	return gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true);
 }
 
 static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
@@ -1032,9 +1037,9 @@ static void kvm_mmu_free_page(struct kvm *kvm, struct kvm_mmu_page *sp)
 	ASSERT(is_empty_shadow_page(sp->spt));
 	hlist_del(&sp->hash_link);
 	list_del(&sp->link);
-	__free_page(virt_to_page(sp->spt));
+	free_page((unsigned long)sp->spt);
 	if (!sp->role.direct)
-		__free_page(virt_to_page(sp->gfns));
+		free_page((unsigned long)sp->gfns);
 	kmem_cache_free(mmu_page_header_cache, sp);
 	kvm_mod_used_mmu_pages(kvm, -1);
 }
@@ -1199,6 +1204,13 @@ static void nonpaging_invlpg(struct kvm_vcpu *vcpu, gva_t gva)
 {
 }
 
+static void nonpaging_update_pte(struct kvm_vcpu *vcpu,
+				 struct kvm_mmu_page *sp, u64 *spte,
+				 const void *pte, unsigned long mmu_seq)
+{
+	WARN_ON(1);
+}
+
 #define KVM_PAGE_ARRAY_NR 16
 
 struct kvm_mmu_pages {
@@ -2150,26 +2162,13 @@ static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
 {
 }
 
-static struct kvm_memory_slot *
-pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log)
-{
-	struct kvm_memory_slot *slot;
-
-	slot = gfn_to_memslot(vcpu->kvm, gfn);
-	if (!slot || slot->flags & KVM_MEMSLOT_INVALID ||
-	      (no_dirty_log && slot->dirty_bitmap))
-		slot = NULL;
-
-	return slot;
-}
-
 static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
 				     bool no_dirty_log)
 {
 	struct kvm_memory_slot *slot;
 	unsigned long hva;
 
-	slot = pte_prefetch_gfn_to_memslot(vcpu, gfn, no_dirty_log);
+	slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, no_dirty_log);
 	if (!slot) {
 		get_page(bad_page);
 		return page_to_pfn(bad_page);
@@ -2190,7 +2189,7 @@ static int direct_pte_prefetch_many(struct kvm_vcpu *vcpu,
 	gfn_t gfn;
 
 	gfn = kvm_mmu_page_get_gfn(sp, start - sp->spt);
-	if (!pte_prefetch_gfn_to_memslot(vcpu, gfn, access & ACC_WRITE_MASK))
+	if (!gfn_to_memslot_dirty_bitmap(vcpu, gfn, access & ACC_WRITE_MASK))
 		return -1;
 
 	ret = gfn_to_page_many_atomic(vcpu->kvm, gfn, pages, end - start);
@@ -2804,6 +2803,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu,
 	context->prefetch_page = nonpaging_prefetch_page;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
+	context->update_pte = nonpaging_update_pte;
 	context->root_level = 0;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
 	context->root_hpa = INVALID_PAGE;
@@ -2933,6 +2933,7 @@ static int paging64_init_context_common(struct kvm_vcpu *vcpu,
 	context->prefetch_page = paging64_prefetch_page;
 	context->sync_page = paging64_sync_page;
 	context->invlpg = paging64_invlpg;
+	context->update_pte = paging64_update_pte;
 	context->free = paging_free;
 	context->root_level = level;
 	context->shadow_root_level = level;
@@ -2961,6 +2962,7 @@ static int paging32_init_context(struct kvm_vcpu *vcpu,
 	context->prefetch_page = paging32_prefetch_page;
 	context->sync_page = paging32_sync_page;
 	context->invlpg = paging32_invlpg;
+	context->update_pte = paging32_update_pte;
 	context->root_level = PT32_ROOT_LEVEL;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
 	context->root_hpa = INVALID_PAGE;
@@ -2985,6 +2987,7 @@ static int init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
 	context->prefetch_page = nonpaging_prefetch_page;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
+	context->update_pte = nonpaging_update_pte;
 	context->shadow_root_level = kvm_x86_ops->get_tdp_level();
 	context->root_hpa = INVALID_PAGE;
 	context->direct_map = true;
@@ -3089,8 +3092,6 @@ static int init_kvm_nested_mmu(struct kvm_vcpu *vcpu)
 
 static int init_kvm_mmu(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.update_pte.pfn = bad_pfn;
-
 	if (mmu_is_nested(vcpu))
 		return init_kvm_nested_mmu(vcpu);
 	else if (tdp_enabled)
@@ -3164,7 +3165,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu *vcpu,
 static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
 				  struct kvm_mmu_page *sp,
 				  u64 *spte,
-				  const void *new)
+				  const void *new, unsigned long mmu_seq)
 {
 	if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
 		++vcpu->kvm->stat.mmu_pde_zapped;
@@ -3172,10 +3173,7 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
         }
 
 	++vcpu->kvm->stat.mmu_pte_updated;
-	if (!sp->role.cr4_pae)
-		paging32_update_pte(vcpu, sp, spte, new);
-	else
-		paging64_update_pte(vcpu, sp, spte, new);
+	vcpu->arch.mmu.update_pte(vcpu, sp, spte, new, mmu_seq);
 }
 
 static bool need_remote_flush(u64 old, u64 new)
@@ -3210,28 +3208,6 @@ static bool last_updated_pte_accessed(struct kvm_vcpu *vcpu)
 	return !!(spte && (*spte & shadow_accessed_mask));
 }
 
-static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-					  u64 gpte)
-{
-	gfn_t gfn;
-	pfn_t pfn;
-
-	if (!is_present_gpte(gpte))
-		return;
-	gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
-
-	vcpu->arch.update_pte.mmu_seq = vcpu->kvm->mmu_notifier_seq;
-	smp_rmb();
-	pfn = gfn_to_pfn(vcpu->kvm, gfn);
-
-	if (is_error_pfn(pfn)) {
-		kvm_release_pfn_clean(pfn);
-		return;
-	}
-	vcpu->arch.update_pte.gfn = gfn;
-	vcpu->arch.update_pte.pfn = pfn;
-}
-
 static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn)
 {
 	u64 *spte = vcpu->arch.last_pte_updated;
@@ -3253,21 +3229,14 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 	struct kvm_mmu_page *sp;
 	struct hlist_node *node;
 	LIST_HEAD(invalid_list);
-	u64 entry, gentry;
-	u64 *spte;
-	unsigned offset = offset_in_page(gpa);
-	unsigned pte_size;
-	unsigned page_offset;
-	unsigned misaligned;
-	unsigned quadrant;
-	int level;
-	int flooded = 0;
-	int npte;
-	int r;
-	int invlpg_counter;
+	unsigned long mmu_seq;
+	u64 entry, gentry, *spte;
+	unsigned pte_size, page_offset, misaligned, quadrant, offset;
+	int level, npte, invlpg_counter, r, flooded = 0;
 	bool remote_flush, local_flush, zap_page;
 
 	zap_page = remote_flush = local_flush = false;
+	offset = offset_in_page(gpa);
 
 	pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
 
@@ -3275,9 +3244,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 
 	/*
 	 * Assume that the pte write on a page table of the same type
-	 * as the current vcpu paging mode.  This is nearly always true
-	 * (might be false while changing modes).  Note it is verified later
-	 * by update_pte().
+	 * as the current vcpu paging mode since we update the sptes only
+	 * when they have the same mode.
 	 */
 	if ((is_pae(vcpu) && bytes == 4) || !new) {
 		/* Handle a 32-bit guest writing two halves of a 64-bit gpte */
@@ -3303,15 +3271,17 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 		break;
 	}
 
-	mmu_guess_page_from_pte_write(vcpu, gpa, gentry);
+	mmu_seq = vcpu->kvm->mmu_notifier_seq;
+	smp_rmb();
+
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter)
 		gentry = 0;
-	kvm_mmu_access_page(vcpu, gfn);
 	kvm_mmu_free_some_pages(vcpu);
 	++vcpu->kvm->stat.mmu_pte_write;
 	trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE);
 	if (guest_initiated) {
+		kvm_mmu_access_page(vcpu, gfn);
 		if (gfn == vcpu->arch.last_pt_write_gfn
 		    && !last_updated_pte_accessed(vcpu)) {
 			++vcpu->arch.last_pt_write_count;
@@ -3375,7 +3345,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 			if (gentry &&
 			      !((sp->role.word ^ vcpu->arch.mmu.base_role.word)
 			      & mask.word))
-				mmu_pte_write_new_pte(vcpu, sp, spte, &gentry);
+				mmu_pte_write_new_pte(vcpu, sp, spte, &gentry,
+						      mmu_seq);
 			if (!remote_flush && need_remote_flush(entry, *spte))
 				remote_flush = true;
 			++spte;
@@ -3385,10 +3356,6 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 	kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
 	trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE);
 	spin_unlock(&vcpu->kvm->mmu_lock);
-	if (!is_error_pfn(vcpu->arch.update_pte.pfn)) {
-		kvm_release_pfn_clean(vcpu->arch.update_pte.pfn);
-		vcpu->arch.update_pte.pfn = bad_pfn;
-	}
 }
 
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
@@ -3538,14 +3505,23 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot)
 		if (!test_bit(slot, sp->slot_bitmap))
 			continue;
 
-		if (sp->role.level != PT_PAGE_TABLE_LEVEL)
-			continue;
-
 		pt = sp->spt;
-		for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+		for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+			if (!is_shadow_present_pte(pt[i]) ||
+			      !is_last_spte(pt[i], sp->role.level))
+				continue;
+
+			if (is_large_pte(pt[i])) {
+				drop_spte(kvm, &pt[i],
+					  shadow_trap_nonpresent_pte);
+				--kvm->stat.lpages;
+				continue;
+			}
+
 			/* avoid RMW */
 			if (is_writable_pte(pt[i]))
 				update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK);
+		}
 	}
 	kvm_flush_remote_tlbs(kvm);
 }
@@ -3583,7 +3559,7 @@ static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
 	if (nr_to_scan == 0)
 		goto out;
 
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 
 	list_for_each_entry(kvm, &vm_list, vm_list) {
 		int idx, freed_pages;
@@ -3606,7 +3582,7 @@ static int mmu_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
 	if (kvm_freed)
 		list_move_tail(&kvm_freed->vm_list, &vm_list);
 
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 
 out:
 	return percpu_counter_read_positive(&kvm_total_used_mmu_pages);
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 6bccc24..c639779 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -31,7 +31,6 @@
 	#define PT_LVL_ADDR_MASK(lvl) PT64_LVL_ADDR_MASK(lvl)
 	#define PT_LVL_OFFSET_MASK(lvl) PT64_LVL_OFFSET_MASK(lvl)
 	#define PT_INDEX(addr, level) PT64_INDEX(addr, level)
-	#define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
 	#define PT_LEVEL_BITS PT64_LEVEL_BITS
 	#ifdef CONFIG_X86_64
 	#define PT_MAX_FULL_LEVELS 4
@@ -48,7 +47,6 @@
 	#define PT_LVL_ADDR_MASK(lvl) PT32_LVL_ADDR_MASK(lvl)
 	#define PT_LVL_OFFSET_MASK(lvl) PT32_LVL_OFFSET_MASK(lvl)
 	#define PT_INDEX(addr, level) PT32_INDEX(addr, level)
-	#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
 	#define PT_LEVEL_BITS PT32_LEVEL_BITS
 	#define PT_MAX_FULL_LEVELS 2
 	#define CMPXCHG cmpxchg
@@ -327,7 +325,7 @@ no_present:
 }
 
 static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-			      u64 *spte, const void *pte)
+			      u64 *spte, const void *pte, unsigned long mmu_seq)
 {
 	pt_element_t gpte;
 	unsigned pte_access;
@@ -339,16 +337,16 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
 
 	pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
 	pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
-	if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)
+	pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
+	if (is_error_pfn(pfn)) {
+		kvm_release_pfn_clean(pfn);
 		return;
-	pfn = vcpu->arch.update_pte.pfn;
-	if (is_error_pfn(pfn))
-		return;
-	if (mmu_notifier_retry(vcpu, vcpu->arch.update_pte.mmu_seq))
+	}
+	if (mmu_notifier_retry(vcpu, mmu_seq))
 		return;
-	kvm_get_pfn(pfn);
+
 	/*
-	 * we call mmu_set_spte() with host_writable = true beacuse that
+	 * we call mmu_set_spte() with host_writable = true because that
 	 * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
 	 */
 	mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
@@ -829,7 +827,6 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 #undef FNAME
 #undef PT_BASE_ADDR_MASK
 #undef PT_INDEX
-#undef PT_LEVEL_MASK
 #undef PT_LVL_ADDR_MASK
 #undef PT_LVL_OFFSET_MASK
 #undef PT_LEVEL_BITS
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 63fec15..6bb15d5 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -135,6 +135,8 @@ struct vcpu_svm {
 
 	u32 *msrpm;
 
+	ulong nmi_iret_rip;
+
 	struct nested_state nested;
 
 	bool nmi_singlestep;
@@ -1153,8 +1155,10 @@ static void svm_vcpu_put(struct kvm_vcpu *vcpu)
 	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
 	load_gs_index(svm->host.gs);
 #else
+#ifdef CONFIG_X86_32_LAZY_GS
 	loadsegment(gs, svm->host.gs);
 #endif
+#endif
 	for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
 		wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
@@ -2653,6 +2657,7 @@ static int iret_interception(struct vcpu_svm *svm)
 	++svm->vcpu.stat.nmi_window_exits;
 	clr_intercept(svm, INTERCEPT_IRET);
 	svm->vcpu.arch.hflags |= HF_IRET_MASK;
+	svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
 	return 1;
 }
 
@@ -3474,7 +3479,12 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
 
 	svm->int3_injected = 0;
 
-	if (svm->vcpu.arch.hflags & HF_IRET_MASK) {
+	/*
+	 * If we've made progress since setting HF_IRET_MASK, we've
+	 * executed an IRET and can allow NMI injection.
+	 */
+	if ((svm->vcpu.arch.hflags & HF_IRET_MASK)
+	    && kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip) {
 		svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
 		kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 	}
@@ -3641,19 +3651,30 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 	wrmsrl(MSR_GS_BASE, svm->host.gs_base);
 #else
 	loadsegment(fs, svm->host.fs);
+#ifndef CONFIG_X86_32_LAZY_GS
+	loadsegment(gs, svm->host.gs);
+#endif
 #endif
 
 	reload_tss(vcpu);
 
 	local_irq_disable();
 
-	stgi();
-
 	vcpu->arch.cr2 = svm->vmcb->save.cr2;
 	vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
+	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
+		kvm_before_handle_nmi(&svm->vcpu);
+
+	stgi();
+
+	/* Any pending NMI will happen here */
+
+	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
+		kvm_after_handle_nmi(&svm->vcpu);
+
 	sync_cr8_to_lapic(vcpu);
 
 	svm->next_rip = 0;
diff --git a/arch/x86/kvm/timer.c b/arch/x86/kvm/timer.c
index fc7a101..abd86e86 100644
--- a/arch/x86/kvm/timer.c
+++ b/arch/x86/kvm/timer.c
@@ -25,7 +25,7 @@ static int __kvm_timer_fn(struct kvm_vcpu *vcpu, struct kvm_timer *ktimer)
 
 	/*
 	 * There is a race window between reading and incrementing, but we do
-	 * not care about potentially loosing timer events in the !reinject
+	 * not care about potentially losing timer events in the !reinject
 	 * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
 	 * in vcpu_enter_guest.
 	 */
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 1357d7c..db93276 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -62,21 +62,21 @@ TRACE_EVENT(kvm_hv_hypercall,
 	TP_ARGS(code, fast, rep_cnt, rep_idx, ingpa, outgpa),
 
 	TP_STRUCT__entry(
-		__field(	__u16, 		code		)
-		__field(	bool,		fast		)
 		__field(	__u16,		rep_cnt		)
 		__field(	__u16,		rep_idx		)
 		__field(	__u64,		ingpa		)
 		__field(	__u64,		outgpa		)
+		__field(	__u16, 		code		)
+		__field(	bool,		fast		)
 	),
 
 	TP_fast_assign(
-		__entry->code		= code;
-		__entry->fast		= fast;
 		__entry->rep_cnt	= rep_cnt;
 		__entry->rep_idx	= rep_idx;
 		__entry->ingpa		= ingpa;
 		__entry->outgpa		= outgpa;
+		__entry->code		= code;
+		__entry->fast		= fast;
 	),
 
 	TP_printk("code 0x%x %s cnt 0x%x idx 0x%x in 0x%llx out 0x%llx",
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index bf89ec2..5b4cdcb 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -93,14 +93,14 @@ module_param(yield_on_hlt, bool, S_IRUGO);
  * These 2 parameters are used to config the controls for Pause-Loop Exiting:
  * ple_gap:    upper bound on the amount of time between two successive
  *             executions of PAUSE in a loop. Also indicate if ple enabled.
- *             According to test, this time is usually small than 41 cycles.
+ *             According to test, this time is usually smaller than 128 cycles.
  * ple_window: upper bound on the amount of time a guest is allowed to execute
  *             in a PAUSE loop. Tests indicate that most spinlocks are held for
  *             less than 2^12 cycles
  * Time is measured based on a counter that runs at the same rate as the TSC,
  * refer SDM volume 3b section 21.6.13 & 22.1.3.
  */
-#define KVM_VMX_DEFAULT_PLE_GAP    41
+#define KVM_VMX_DEFAULT_PLE_GAP    128
 #define KVM_VMX_DEFAULT_PLE_WINDOW 4096
 static int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
 module_param(ple_gap, int, S_IRUGO);
@@ -176,11 +176,11 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
 	return container_of(vcpu, struct vcpu_vmx, vcpu);
 }
 
-static int init_rmode(struct kvm *kvm);
 static u64 construct_eptp(unsigned long root_hpa);
 static void kvm_cpu_vmxon(u64 addr);
 static void kvm_cpu_vmxoff(void);
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
+static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
@@ -1333,19 +1333,25 @@ static __init int vmx_disabled_by_bios(void)
 
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
 	if (msr & FEATURE_CONTROL_LOCKED) {
+		/* launched w/ TXT and VMX disabled */
 		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
 			&& tboot_enabled())
 			return 1;
+		/* launched w/o TXT and VMX only enabled w/ TXT */
 		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+			&& (msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
 			&& !tboot_enabled()) {
 			printk(KERN_WARNING "kvm: disable TXT in the BIOS or "
-				" activate TXT before enabling KVM\n");
+				"activate TXT before enabling KVM\n");
 			return 1;
 		}
+		/* launched w/o TXT and VMX disabled */
+		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+			&& !tboot_enabled())
+			return 1;
 	}
 
 	return 0;
-	/* locked but not enabled */
 }
 
 static void kvm_cpu_vmxon(u64 addr)
@@ -1683,6 +1689,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 	vmx->emulation_required = 1;
 	vmx->rmode.vm86_active = 0;
 
+	vmcs_write16(GUEST_TR_SELECTOR, vmx->rmode.tr.selector);
 	vmcs_writel(GUEST_TR_BASE, vmx->rmode.tr.base);
 	vmcs_write32(GUEST_TR_LIMIT, vmx->rmode.tr.limit);
 	vmcs_write32(GUEST_TR_AR_BYTES, vmx->rmode.tr.ar);
@@ -1756,6 +1763,19 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 	vmx->emulation_required = 1;
 	vmx->rmode.vm86_active = 1;
 
+	/*
+	 * Very old userspace does not call KVM_SET_TSS_ADDR before entering
+	 * vcpu. Call it here with phys address pointing 16M below 4G.
+	 */
+	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->rmode.tr.selector = vmcs_read16(GUEST_TR_SELECTOR);
 	vmx->rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
 	vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
 
@@ -1794,7 +1814,6 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 
 continue_rmode:
 	kvm_mmu_reset_context(vcpu);
-	init_rmode(vcpu->kvm);
 }
 
 static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
@@ -2030,23 +2049,40 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 	vmcs_writel(GUEST_CR4, hw_cr4);
 }
 
-static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
-{
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
-
-	return vmcs_readl(sf->base);
-}
-
 static void vmx_get_segment(struct kvm_vcpu *vcpu,
 			    struct kvm_segment *var, int seg)
 {
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	struct kvm_save_segment *save;
 	u32 ar;
 
+	if (vmx->rmode.vm86_active
+	    && (seg == VCPU_SREG_TR || seg == VCPU_SREG_ES
+		|| seg == VCPU_SREG_DS || seg == VCPU_SREG_FS
+		|| seg == VCPU_SREG_GS)
+	    && !emulate_invalid_guest_state) {
+		switch (seg) {
+		case VCPU_SREG_TR: save = &vmx->rmode.tr; break;
+		case VCPU_SREG_ES: save = &vmx->rmode.es; break;
+		case VCPU_SREG_DS: save = &vmx->rmode.ds; break;
+		case VCPU_SREG_FS: save = &vmx->rmode.fs; break;
+		case VCPU_SREG_GS: save = &vmx->rmode.gs; break;
+		default: BUG();
+		}
+		var->selector = save->selector;
+		var->base = save->base;
+		var->limit = save->limit;
+		ar = save->ar;
+		if (seg == VCPU_SREG_TR
+		    || var->selector == vmcs_read16(sf->selector))
+			goto use_saved_rmode_seg;
+	}
 	var->base = vmcs_readl(sf->base);
 	var->limit = vmcs_read32(sf->limit);
 	var->selector = vmcs_read16(sf->selector);
 	ar = vmcs_read32(sf->ar_bytes);
+use_saved_rmode_seg:
 	if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state)
 		ar = 0;
 	var->type = ar & 15;
@@ -2060,6 +2096,18 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
 	var->unusable = (ar >> 16) & 1;
 }
 
+static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	struct kvm_segment s;
+
+	if (to_vmx(vcpu)->rmode.vm86_active) {
+		vmx_get_segment(vcpu, &s, seg);
+		return s.base;
+	}
+	return vmcs_readl(sf->base);
+}
+
 static int vmx_get_cpl(struct kvm_vcpu *vcpu)
 {
 	if (!is_protmode(vcpu))
@@ -2101,6 +2149,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
 	u32 ar;
 
 	if (vmx->rmode.vm86_active && seg == VCPU_SREG_TR) {
+		vmcs_write16(sf->selector, var->selector);
 		vmx->rmode.tr.selector = var->selector;
 		vmx->rmode.tr.base = var->base;
 		vmx->rmode.tr.limit = var->limit;
@@ -2361,11 +2410,12 @@ static bool guest_state_valid(struct kvm_vcpu *vcpu)
 
 static int init_rmode_tss(struct kvm *kvm)
 {
-	gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
+	gfn_t fn;
 	u16 data = 0;
-	int ret = 0;
-	int r;
+	int r, idx, ret = 0;
 
+	idx = srcu_read_lock(&kvm->srcu);
+	fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
 	r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
 	if (r < 0)
 		goto out;
@@ -2389,12 +2439,13 @@ static int init_rmode_tss(struct kvm *kvm)
 
 	ret = 1;
 out:
+	srcu_read_unlock(&kvm->srcu, idx);
 	return ret;
 }
 
 static int init_rmode_identity_map(struct kvm *kvm)
 {
-	int i, r, ret;
+	int i, idx, r, ret;
 	pfn_t identity_map_pfn;
 	u32 tmp;
 
@@ -2409,6 +2460,7 @@ static int init_rmode_identity_map(struct kvm *kvm)
 		return 1;
 	ret = 0;
 	identity_map_pfn = kvm->arch.ept_identity_map_addr >> PAGE_SHIFT;
+	idx = srcu_read_lock(&kvm->srcu);
 	r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE);
 	if (r < 0)
 		goto out;
@@ -2424,6 +2476,7 @@ static int init_rmode_identity_map(struct kvm *kvm)
 	kvm->arch.ept_identity_pagetable_done = true;
 	ret = 1;
 out:
+	srcu_read_unlock(&kvm->srcu, idx);
 	return ret;
 }
 
@@ -2699,22 +2752,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
 	return 0;
 }
 
-static int init_rmode(struct kvm *kvm)
-{
-	int idx, ret = 0;
-
-	idx = srcu_read_lock(&kvm->srcu);
-	if (!init_rmode_tss(kvm))
-		goto exit;
-	if (!init_rmode_identity_map(kvm))
-		goto exit;
-
-	ret = 1;
-exit:
-	srcu_read_unlock(&kvm->srcu, idx);
-	return ret;
-}
-
 static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2722,10 +2759,6 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 	int ret;
 
 	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
-	if (!init_rmode(vmx->vcpu.kvm)) {
-		ret = -ENOMEM;
-		goto out;
-	}
 
 	vmx->rmode.vm86_active = 0;
 
@@ -2805,7 +2838,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 		vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
 		if (vm_need_tpr_shadow(vmx->vcpu.kvm))
 			vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
-				page_to_phys(vmx->vcpu.arch.apic->regs_page));
+				     __pa(vmx->vcpu.arch.apic->regs));
 		vmcs_write32(TPR_THRESHOLD, 0);
 	}
 
@@ -2971,6 +3004,9 @@ static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr)
 	if (ret)
 		return ret;
 	kvm->arch.tss_addr = addr;
+	if (!init_rmode_tss(kvm))
+		return  -ENOMEM;
+
 	return 0;
 }
 
@@ -3962,7 +3998,7 @@ static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
 #define Q "l"
 #endif
 
-static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
@@ -3991,6 +4027,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
 	asm(
 		/* Store host registers */
 		"push %%"R"dx; push %%"R"bp;"
+		"push %%"R"cx \n\t" /* placeholder for guest rcx */
 		"push %%"R"cx \n\t"
 		"cmp %%"R"sp, %c[host_rsp](%0) \n\t"
 		"je 1f \n\t"
@@ -4032,10 +4069,11 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
 		".Lkvm_vmx_return: "
 		/* Save guest registers, load host registers, keep flags */
-		"xchg %0,     (%%"R"sp) \n\t"
+		"mov %0, %c[wordsize](%%"R"sp) \n\t"
+		"pop %0 \n\t"
 		"mov %%"R"ax, %c[rax](%0) \n\t"
 		"mov %%"R"bx, %c[rbx](%0) \n\t"
-		"push"Q" (%%"R"sp); pop"Q" %c[rcx](%0) \n\t"
+		"pop"Q" %c[rcx](%0) \n\t"
 		"mov %%"R"dx, %c[rdx](%0) \n\t"
 		"mov %%"R"si, %c[rsi](%0) \n\t"
 		"mov %%"R"di, %c[rdi](%0) \n\t"
@@ -4053,7 +4091,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		"mov %%cr2, %%"R"ax   \n\t"
 		"mov %%"R"ax, %c[cr2](%0) \n\t"
 
-		"pop  %%"R"bp; pop  %%"R"bp; pop  %%"R"dx \n\t"
+		"pop  %%"R"bp; pop  %%"R"dx \n\t"
 		"setbe %c[fail](%0) \n\t"
 	      : : "c"(vmx), "d"((unsigned long)HOST_RSP),
 		[launched]"i"(offsetof(struct vcpu_vmx, launched)),
@@ -4076,7 +4114,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
 		[r14]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R14])),
 		[r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
 #endif
-		[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))
+		[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)),
+		[wordsize]"i"(sizeof(ulong))
 	      : "cc", "memory"
 		, R"ax", R"bx", R"di", R"si"
 #ifdef CONFIG_X86_64
@@ -4183,8 +4222,11 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
 		if (!kvm->arch.ept_identity_map_addr)
 			kvm->arch.ept_identity_map_addr =
 				VMX_EPT_IDENTITY_PAGETABLE_ADDR;
+		err = -ENOMEM;
 		if (alloc_identity_pagetable(kvm) != 0)
 			goto free_vmcs;
+		if (!init_rmode_identity_map(kvm))
+			goto free_vmcs;
 	}
 
 	return &vmx->vcpu;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bcc0efc..58f517b 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -81,9 +81,10 @@
  * - enable LME and LMA per default on 64 bit KVM
  */
 #ifdef CONFIG_X86_64
-static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffafeULL;
+static
+u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA));
 #else
-static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffffeULL;
+static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
 #endif
 
 #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
@@ -360,8 +361,8 @@ void kvm_propagate_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault)
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
 {
+	kvm_make_request(KVM_REQ_NMI, vcpu);
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
-	vcpu->arch.nmi_pending = 1;
 }
 EXPORT_SYMBOL_GPL(kvm_inject_nmi);
 
@@ -525,8 +526,10 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 
 	kvm_x86_ops->set_cr0(vcpu, cr0);
 
-	if ((cr0 ^ old_cr0) & X86_CR0_PG)
+	if ((cr0 ^ old_cr0) & X86_CR0_PG) {
 		kvm_clear_async_pf_completion_queue(vcpu);
+		kvm_async_pf_hash_reset(vcpu);
+	}
 
 	if ((cr0 ^ old_cr0) & update_bits)
 		kvm_mmu_reset_context(vcpu);
@@ -1017,7 +1020,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
 	unsigned long flags;
 	s64 sdiff;
 
-	spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
+	raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
 	offset = data - native_read_tsc();
 	ns = get_kernel_ns();
 	elapsed = ns - kvm->arch.last_tsc_nsec;
@@ -1028,7 +1031,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
 	/*
 	 * Special case: close write to TSC within 5 seconds of
 	 * another CPU is interpreted as an attempt to synchronize
-	 * The 5 seconds is to accomodate host load / swapping as
+	 * The 5 seconds is to accommodate host load / swapping as
 	 * well as any reset of TSC during the boot process.
 	 *
 	 * In that case, for a reliable TSC, we can match TSC offsets,
@@ -1050,7 +1053,7 @@ void kvm_write_tsc(struct kvm_vcpu *vcpu, u64 data)
 	kvm->arch.last_tsc_write = data;
 	kvm->arch.last_tsc_offset = offset;
 	kvm_x86_ops->write_tsc_offset(vcpu, offset);
-	spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
+	raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 
 	/* Reset of TSC must disable overshoot protection below */
 	vcpu->arch.hv_clock.tsc_timestamp = 0;
@@ -1453,6 +1456,14 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
 	return 0;
 }
 
+static void kvmclock_reset(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->arch.time_page) {
+		kvm_release_page_dirty(vcpu->arch.time_page);
+		vcpu->arch.time_page = NULL;
+	}
+}
+
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
 	switch (msr) {
@@ -1510,10 +1521,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		break;
 	case MSR_KVM_SYSTEM_TIME_NEW:
 	case MSR_KVM_SYSTEM_TIME: {
-		if (vcpu->arch.time_page) {
-			kvm_release_page_dirty(vcpu->arch.time_page);
-			vcpu->arch.time_page = NULL;
-		}
+		kvmclock_reset(vcpu);
 
 		vcpu->arch.time = data;
 		kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -1592,6 +1600,12 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 		} else
 			return set_msr_hyperv(vcpu, msr, data);
 		break;
+	case MSR_IA32_BBL_CR_CTL3:
+		/* Drop writes to this legacy MSR -- see rdmsr
+		 * counterpart for further detail.
+		 */
+		pr_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data);
+		break;
 	default:
 		if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr))
 			return xen_hvm_config(vcpu, data);
@@ -1846,6 +1860,19 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
 		} else
 			return get_msr_hyperv(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_BBL_CR_CTL3:
+		/* This legacy MSR exists but isn't fully documented in current
+		 * silicon.  It is however accessed by winxp in very narrow
+		 * scenarios where it sets bit #19, itself documented as
+		 * a "reserved" bit.  Best effort attempt to source coherent
+		 * read data here should the balance of the register be
+		 * interpreted by the guest:
+		 *
+		 * L2 cache control register 3: 64GB range, 256KB size,
+		 * enabled, latency 0x1, configured
+		 */
+		data = 0xbe702111;
+		break;
 	default:
 		if (!ignore_msrs) {
 			pr_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr);
@@ -2100,8 +2127,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 		if (check_tsc_unstable()) {
 			kvm_x86_ops->adjust_tsc_offset(vcpu, -tsc_delta);
 			vcpu->arch.tsc_catchup = 1;
-			kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 		}
+		kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 		if (vcpu->cpu != cpu)
 			kvm_migrate_timers(vcpu);
 		vcpu->cpu = cpu;
@@ -2575,9 +2602,6 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu,
 	if (mce->status & MCI_STATUS_UC) {
 		if ((vcpu->arch.mcg_status & MCG_STATUS_MCIP) ||
 		    !kvm_read_cr4_bits(vcpu, X86_CR4_MCE)) {
-			printk(KERN_DEBUG "kvm: set_mce: "
-			       "injects mce exception while "
-			       "previous one is in progress!\n");
 			kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
 			return 0;
 		}
@@ -2648,8 +2672,6 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
 	vcpu->arch.interrupt.pending = events->interrupt.injected;
 	vcpu->arch.interrupt.nr = events->interrupt.nr;
 	vcpu->arch.interrupt.soft = events->interrupt.soft;
-	if (vcpu->arch.interrupt.pending && irqchip_in_kernel(vcpu->kvm))
-		kvm_pic_clear_isr_ack(vcpu->kvm);
 	if (events->flags & KVM_VCPUEVENT_VALID_SHADOW)
 		kvm_x86_ops->set_interrupt_shadow(vcpu,
 						  events->interrupt.shadow);
@@ -4140,8 +4162,8 @@ static unsigned long emulator_get_cached_segment_base(int seg,
 	return get_segment_base(vcpu, seg);
 }
 
-static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
-					   struct kvm_vcpu *vcpu)
+static bool emulator_get_cached_descriptor(struct desc_struct *desc, u32 *base3,
+					   int seg, struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment var;
 
@@ -4154,6 +4176,10 @@ static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
 		var.limit >>= 12;
 	set_desc_limit(desc, var.limit);
 	set_desc_base(desc, (unsigned long)var.base);
+#ifdef CONFIG_X86_64
+	if (base3)
+		*base3 = var.base >> 32;
+#endif
 	desc->type = var.type;
 	desc->s = var.s;
 	desc->dpl = var.dpl;
@@ -4166,8 +4192,8 @@ static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
 	return true;
 }
 
-static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg,
-					   struct kvm_vcpu *vcpu)
+static void emulator_set_cached_descriptor(struct desc_struct *desc, u32 base3,
+					   int seg, struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment var;
 
@@ -4175,6 +4201,9 @@ static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg,
 	kvm_get_segment(vcpu, &var, seg);
 
 	var.base = get_desc_base(desc);
+#ifdef CONFIG_X86_64
+	var.base |= ((u64)base3) << 32;
+#endif
 	var.limit = get_desc_limit(desc);
 	if (desc->g)
 		var.limit = (var.limit << 12) | 0xfff;
@@ -4390,41 +4419,16 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu,
 		vcpu->arch.emulate_ctxt.have_exception = false;
 		vcpu->arch.emulate_ctxt.perm_ok = false;
 
+		vcpu->arch.emulate_ctxt.only_vendor_specific_insn
+			= emulation_type & EMULTYPE_TRAP_UD;
+
 		r = x86_decode_insn(&vcpu->arch.emulate_ctxt, insn, insn_len);
-		if (r == X86EMUL_PROPAGATE_FAULT)
-			goto done;
 
 		trace_kvm_emulate_insn_start(vcpu);
-
-		/* Only allow emulation of specific instructions on #UD
-		 * (namely VMMCALL, sysenter, sysexit, syscall)*/
-		if (emulation_type & EMULTYPE_TRAP_UD) {
-			if (!c->twobyte)
-				return EMULATE_FAIL;
-			switch (c->b) {
-			case 0x01: /* VMMCALL */
-				if (c->modrm_mod != 3 || c->modrm_rm != 1)
-					return EMULATE_FAIL;
-				break;
-			case 0x34: /* sysenter */
-			case 0x35: /* sysexit */
-				if (c->modrm_mod != 0 || c->modrm_rm != 0)
-					return EMULATE_FAIL;
-				break;
-			case 0x05: /* syscall */
-				if (c->modrm_mod != 0 || c->modrm_rm != 0)
-					return EMULATE_FAIL;
-				break;
-			default:
-				return EMULATE_FAIL;
-			}
-
-			if (!(c->modrm_reg == 0 || c->modrm_reg == 3))
-				return EMULATE_FAIL;
-		}
-
 		++vcpu->stat.insn_emulation;
 		if (r)  {
+			if (emulation_type & EMULTYPE_TRAP_UD)
+				return EMULATE_FAIL;
 			if (reexecute_instruction(vcpu, cr2))
 				return EMULATE_DONE;
 			if (emulation_type & EMULTYPE_SKIP)
@@ -4452,7 +4456,6 @@ restart:
 		return handle_emulation_failure(vcpu);
 	}
 
-done:
 	if (vcpu->arch.emulate_ctxt.have_exception) {
 		inject_emulated_exception(vcpu);
 		r = EMULATE_DONE;
@@ -4562,7 +4565,7 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
 
 	smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
 
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	list_for_each_entry(kvm, &vm_list, vm_list) {
 		kvm_for_each_vcpu(i, vcpu, kvm) {
 			if (vcpu->cpu != freq->cpu)
@@ -4572,7 +4575,7 @@ static int kvmclock_cpufreq_notifier(struct notifier_block *nb, unsigned long va
 				send_ipi = 1;
 		}
 	}
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 
 	if (freq->old < freq->new && send_ipi) {
 		/*
@@ -5185,6 +5188,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 			r = 1;
 			goto out;
 		}
+		if (kvm_check_request(KVM_REQ_NMI, vcpu))
+			vcpu->arch.nmi_pending = true;
 	}
 
 	r = kvm_mmu_reload(vcpu);
@@ -5213,14 +5218,18 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 		kvm_load_guest_fpu(vcpu);
 	kvm_load_guest_xcr0(vcpu);
 
-	atomic_set(&vcpu->guest_mode, 1);
-	smp_wmb();
+	vcpu->mode = IN_GUEST_MODE;
+
+	/* We should set ->mode before check ->requests,
+	 * see the comment in make_all_cpus_request.
+	 */
+	smp_mb();
 
 	local_irq_disable();
 
-	if (!atomic_read(&vcpu->guest_mode) || vcpu->requests
+	if (vcpu->mode == EXITING_GUEST_MODE || vcpu->requests
 	    || need_resched() || signal_pending(current)) {
-		atomic_set(&vcpu->guest_mode, 0);
+		vcpu->mode = OUTSIDE_GUEST_MODE;
 		smp_wmb();
 		local_irq_enable();
 		preempt_enable();
@@ -5256,7 +5265,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 
 	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
 
-	atomic_set(&vcpu->guest_mode, 0);
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
 	local_irq_enable();
 
@@ -5574,7 +5583,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 				  struct kvm_sregs *sregs)
 {
 	int mmu_reset_needed = 0;
-	int pending_vec, max_bits;
+	int pending_vec, max_bits, idx;
 	struct desc_ptr dt;
 
 	dt.size = sregs->idt.limit;
@@ -5603,10 +5612,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
 	if (sregs->cr4 & X86_CR4_OSXSAVE)
 		update_cpuid(vcpu);
+
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	if (!is_long_mode(vcpu) && is_pae(vcpu)) {
 		load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
 		mmu_reset_needed = 1;
 	}
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
 	if (mmu_reset_needed)
 		kvm_mmu_reset_context(vcpu);
@@ -5617,8 +5629,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 	if (pending_vec < max_bits) {
 		kvm_queue_interrupt(vcpu, pending_vec, false);
 		pr_debug("Set back pending irq %d\n", pending_vec);
-		if (irqchip_in_kernel(vcpu->kvm))
-			kvm_pic_clear_isr_ack(vcpu->kvm);
 	}
 
 	kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS);
@@ -5814,10 +5824,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
 
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
-	if (vcpu->arch.time_page) {
-		kvm_release_page_dirty(vcpu->arch.time_page);
-		vcpu->arch.time_page = NULL;
-	}
+	kvmclock_reset(vcpu);
 
 	free_cpumask_var(vcpu->arch.wbinvd_dirty_mask);
 	fx_free(vcpu);
@@ -5878,6 +5885,8 @@ int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu)
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 	vcpu->arch.apf.msr_val = 0;
 
+	kvmclock_reset(vcpu);
+
 	kvm_clear_async_pf_completion_queue(vcpu);
 	kvm_async_pf_hash_reset(vcpu);
 	vcpu->arch.apf.halted = false;
@@ -6005,7 +6014,7 @@ int kvm_arch_init_vm(struct kvm *kvm)
 	/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
 	set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
 
-	spin_lock_init(&kvm->arch.tsc_write_lock);
+	raw_spin_lock_init(&kvm->arch.tsc_write_lock);
 
 	return 0;
 }
@@ -6103,7 +6112,7 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 				int user_alloc)
 {
 
-	int npages = mem->memory_size >> PAGE_SHIFT;
+	int nr_mmu_pages = 0, npages = mem->memory_size >> PAGE_SHIFT;
 
 	if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
 		int ret;
@@ -6118,12 +6127,12 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
 			       "failed to munmap memory\n");
 	}
 
+	if (!kvm->arch.n_requested_mmu_pages)
+		nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
+
 	spin_lock(&kvm->mmu_lock);
-	if (!kvm->arch.n_requested_mmu_pages) {
-		unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
+	if (nr_mmu_pages)
 		kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
-	}
-
 	kvm_mmu_slot_remove_write_access(kvm, mem->slot);
 	spin_unlock(&kvm->mmu_lock);
 }
@@ -6157,7 +6166,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 
 	me = get_cpu();
 	if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu))
-		if (atomic_xchg(&vcpu->guest_mode, 0))
+		if (kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE)
 			smp_send_reschedule(cpu);
 	put_cpu();
 }
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index eba687f0..1cd6089 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -397,7 +397,7 @@ static void lguest_load_tr_desc(void)
  * instead we just use the real "cpuid" instruction.  Then I pretty much turned
  * off feature bits until the Guest booted.  (Don't say that: you'll damage
  * lguest sales!)  Shut up, inner voice!  (Hey, just pointing out that this is
- * hardly future proof.)  Noone's listening!  They don't like you anyway,
+ * hardly future proof.)  No one's listening!  They don't like you anyway,
  * parenthetic weirdo!
  *
  * Replacing the cpuid so we can turn features off is great for the kernel, but
@@ -847,7 +847,7 @@ static void __init lguest_init_IRQ(void)
 void lguest_setup_irq(unsigned int irq)
 {
 	irq_alloc_desc_at(irq, 0);
-	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
+	irq_set_chip_and_handler_name(irq, &lguest_irq_controller,
 				      handle_level_irq, "level");
 }
 
@@ -995,7 +995,7 @@ static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
 static void lguest_time_init(void)
 {
 	/* Set up the timer interrupt (0) to go to our simple timer routine */
-	set_irq_handler(0, lguest_time_irq);
+	irq_set_handler(0, lguest_time_irq);
 
 	clocksource_register(&lguest_clock);
 
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index e10cf07..f2479f1 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -42,4 +42,5 @@ else
         lib-y += memmove_64.o memset_64.o
         lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
 	lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o
+	lib-y += cmpxchg16b_emu.o
 endif
diff --git a/arch/x86/lib/atomic64_386_32.S b/arch/x86/lib/atomic64_386_32.S
index 2cda60a..e8e7e0d 100644
--- a/arch/x86/lib/atomic64_386_32.S
+++ b/arch/x86/lib/atomic64_386_32.S
@@ -15,14 +15,12 @@
 
 /* if you want SMP support, implement these with real spinlocks */
 .macro LOCK reg
-	pushfl
-	CFI_ADJUST_CFA_OFFSET 4
+	pushfl_cfi
 	cli
 .endm
 
 .macro UNLOCK reg
-	popfl
-	CFI_ADJUST_CFA_OFFSET -4
+	popfl_cfi
 .endm
 
 #define BEGIN(op) \
diff --git a/arch/x86/lib/atomic64_cx8_32.S b/arch/x86/lib/atomic64_cx8_32.S
index 71e080d..391a083 100644
--- a/arch/x86/lib/atomic64_cx8_32.S
+++ b/arch/x86/lib/atomic64_cx8_32.S
@@ -14,14 +14,12 @@
 #include <asm/dwarf2.h>
 
 .macro SAVE reg
-	pushl %\reg
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %\reg
 	CFI_REL_OFFSET \reg, 0
 .endm
 
 .macro RESTORE reg
-	popl %\reg
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %\reg
 	CFI_RESTORE \reg
 .endm
 
diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S
index adbccd0..78d16a5 100644
--- a/arch/x86/lib/checksum_32.S
+++ b/arch/x86/lib/checksum_32.S
@@ -50,11 +50,9 @@ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
 	   */		
 ENTRY(csum_partial)
 	CFI_STARTPROC
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl 20(%esp),%eax	# Function arg: unsigned int sum
 	movl 16(%esp),%ecx	# Function arg: int len
@@ -132,11 +130,9 @@ ENTRY(csum_partial)
 	jz 8f
 	roll $8, %eax
 8:
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
 	ret
 	CFI_ENDPROC
@@ -148,11 +144,9 @@ ENDPROC(csum_partial)
 
 ENTRY(csum_partial)
 	CFI_STARTPROC
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl 20(%esp),%eax	# Function arg: unsigned int sum
 	movl 16(%esp),%ecx	# Function arg: int len
@@ -260,11 +254,9 @@ ENTRY(csum_partial)
 	jz 90f
 	roll $8, %eax
 90: 
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
 	ret
 	CFI_ENDPROC
@@ -309,14 +301,11 @@ ENTRY(csum_partial_copy_generic)
 	CFI_STARTPROC
 	subl  $4,%esp	
 	CFI_ADJUST_CFA_OFFSET 4
-	pushl %edi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edi
 	CFI_REL_OFFSET edi, 0
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl ARGBASE+16(%esp),%eax	# sum
 	movl ARGBASE+12(%esp),%ecx	# len
@@ -426,17 +415,13 @@ DST(	movb %cl, (%edi)	)
 
 .previous
 
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
-	popl %edi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edi
 	CFI_RESTORE edi
-	popl %ecx			# equivalent to addl $4,%esp
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx			# equivalent to addl $4,%esp
 	ret	
 	CFI_ENDPROC
 ENDPROC(csum_partial_copy_generic)
@@ -459,14 +444,11 @@ ENDPROC(csum_partial_copy_generic)
 		
 ENTRY(csum_partial_copy_generic)
 	CFI_STARTPROC
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
-	pushl %edi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edi
 	CFI_REL_OFFSET edi, 0
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
 	movl ARGBASE+4(%esp),%esi	#src
 	movl ARGBASE+8(%esp),%edi	#dst	
@@ -527,14 +509,11 @@ DST(	movb %dl, (%edi)         )
 	jmp  7b			
 .previous				
 
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
-	popl %edi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edi
 	CFI_RESTORE edi
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
 	ret
 	CFI_ENDPROC
diff --git a/arch/x86/lib/cmpxchg16b_emu.S b/arch/x86/lib/cmpxchg16b_emu.S
new file mode 100644
index 0000000..3e8b08a
--- /dev/null
+++ b/arch/x86/lib/cmpxchg16b_emu.S
@@ -0,0 +1,59 @@
+/*
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; version 2
+ *	of the License.
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+.text
+
+/*
+ * Inputs:
+ * %rsi : memory location to compare
+ * %rax : low 64 bits of old value
+ * %rdx : high 64 bits of old value
+ * %rbx : low 64 bits of new value
+ * %rcx : high 64 bits of new value
+ * %al  : Operation successful
+ */
+ENTRY(this_cpu_cmpxchg16b_emu)
+CFI_STARTPROC
+
+#
+# Emulate 'cmpxchg16b %gs:(%rsi)' except we return the result in %al not
+# via the ZF.  Caller will access %al to get result.
+#
+# Note that this is only useful for a cpuops operation.  Meaning that we
+# do *not* have a fully atomic operation but just an operation that is
+# *atomic* on a single cpu (as provided by the this_cpu_xx class of
+# macros).
+#
+this_cpu_cmpxchg16b_emu:
+	pushf
+	cli
+
+	cmpq %gs:(%rsi), %rax
+	jne not_same
+	cmpq %gs:8(%rsi), %rdx
+	jne not_same
+
+	movq %rbx, %gs:(%rsi)
+	movq %rcx, %gs:8(%rsi)
+
+	popf
+	mov $1, %al
+	ret
+
+ not_same:
+	popf
+	xor %al,%al
+	ret
+
+CFI_ENDPROC
+
+ENDPROC(this_cpu_cmpxchg16b_emu)
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index a460158..99e4826 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -117,7 +117,7 @@ ENDPROC(bad_from_user)
  * rdx count
  *
  * Output:
- * eax uncopied bytes or 0 if successfull.
+ * eax uncopied bytes or 0 if successful.
  */
 ENTRY(copy_user_generic_unrolled)
 	CFI_STARTPROC
diff --git a/arch/x86/lib/csum-copy_64.S b/arch/x86/lib/csum-copy_64.S
index f0dba36..fb903b7 100644
--- a/arch/x86/lib/csum-copy_64.S
+++ b/arch/x86/lib/csum-copy_64.S
@@ -1,6 +1,6 @@
 /*
- * Copyright 2002,2003 Andi Kleen, SuSE Labs.
- *	
+ * Copyright 2002, 2003 Andi Kleen, SuSE Labs.
+ *
  * 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. No warranty for anything given at all.
@@ -11,82 +11,82 @@
 
 /*
  * Checksum copy with exception handling.
- * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the 
+ * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the
  * destination is zeroed.
- * 
+ *
  * Input
  * rdi  source
  * rsi  destination
  * edx  len (32bit)
- * ecx  sum (32bit) 
+ * ecx  sum (32bit)
  * r8   src_err_ptr (int)
  * r9   dst_err_ptr (int)
  *
  * Output
  * eax  64bit sum. undefined in case of exception.
- * 
- * Wrappers need to take care of valid exception sum and zeroing.		 
+ *
+ * Wrappers need to take care of valid exception sum and zeroing.
  * They also should align source or destination to 8 bytes.
  */
 
 	.macro source
 10:
-	.section __ex_table,"a"
+	.section __ex_table, "a"
 	.align 8
-	.quad 10b,.Lbad_source
+	.quad 10b, .Lbad_source
 	.previous
 	.endm
-		
+
 	.macro dest
 20:
-	.section __ex_table,"a"
+	.section __ex_table, "a"
 	.align 8
-	.quad 20b,.Lbad_dest
+	.quad 20b, .Lbad_dest
 	.previous
 	.endm
-			
+
 	.macro ignore L=.Lignore
 30:
-	.section __ex_table,"a"
+	.section __ex_table, "a"
 	.align 8
-	.quad 30b,\L
+	.quad 30b, \L
 	.previous
 	.endm
-	
-				
+
+
 ENTRY(csum_partial_copy_generic)
 	CFI_STARTPROC
-	cmpl	 $3*64,%edx
-	jle	 .Lignore
+	cmpl	$3*64, %edx
+	jle	.Lignore
 
-.Lignore:		
-	subq  $7*8,%rsp
+.Lignore:
+	subq  $7*8, %rsp
 	CFI_ADJUST_CFA_OFFSET 7*8
-	movq  %rbx,2*8(%rsp)
+	movq  %rbx, 2*8(%rsp)
 	CFI_REL_OFFSET rbx, 2*8
-	movq  %r12,3*8(%rsp)
+	movq  %r12, 3*8(%rsp)
 	CFI_REL_OFFSET r12, 3*8
-	movq  %r14,4*8(%rsp)
+	movq  %r14, 4*8(%rsp)
 	CFI_REL_OFFSET r14, 4*8
-	movq  %r13,5*8(%rsp)
+	movq  %r13, 5*8(%rsp)
 	CFI_REL_OFFSET r13, 5*8
-	movq  %rbp,6*8(%rsp)
+	movq  %rbp, 6*8(%rsp)
 	CFI_REL_OFFSET rbp, 6*8
 
-	movq  %r8,(%rsp)
-	movq  %r9,1*8(%rsp)
-	
-	movl  %ecx,%eax
-	movl  %edx,%ecx
+	movq  %r8, (%rsp)
+	movq  %r9, 1*8(%rsp)
 
-	xorl  %r9d,%r9d
-	movq  %rcx,%r12
+	movl  %ecx, %eax
+	movl  %edx, %ecx
 
-	shrq  $6,%r12
-	jz    .Lhandle_tail       /* < 64 */
+	xorl  %r9d, %r9d
+	movq  %rcx, %r12
+
+	shrq  $6, %r12
+	jz	.Lhandle_tail       /* < 64 */
 
 	clc
-	
+
 	/* main loop. clear in 64 byte blocks */
 	/* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
 	/* r11:	temp3, rdx: temp4, r12 loopcnt */
@@ -94,156 +94,156 @@ ENTRY(csum_partial_copy_generic)
 	.p2align 4
 .Lloop:
 	source
-	movq  (%rdi),%rbx
+	movq  (%rdi), %rbx
 	source
-	movq  8(%rdi),%r8
+	movq  8(%rdi), %r8
 	source
-	movq  16(%rdi),%r11
+	movq  16(%rdi), %r11
 	source
-	movq  24(%rdi),%rdx
+	movq  24(%rdi), %rdx
 
 	source
-	movq  32(%rdi),%r10
+	movq  32(%rdi), %r10
 	source
-	movq  40(%rdi),%rbp
+	movq  40(%rdi), %rbp
 	source
-	movq  48(%rdi),%r14
+	movq  48(%rdi), %r14
 	source
-	movq  56(%rdi),%r13
-		
+	movq  56(%rdi), %r13
+
 	ignore 2f
 	prefetcht0 5*64(%rdi)
-2:							
-	adcq  %rbx,%rax
-	adcq  %r8,%rax
-	adcq  %r11,%rax
-	adcq  %rdx,%rax
-	adcq  %r10,%rax
-	adcq  %rbp,%rax
-	adcq  %r14,%rax
-	adcq  %r13,%rax
+2:
+	adcq  %rbx, %rax
+	adcq  %r8, %rax
+	adcq  %r11, %rax
+	adcq  %rdx, %rax
+	adcq  %r10, %rax
+	adcq  %rbp, %rax
+	adcq  %r14, %rax
+	adcq  %r13, %rax
 
 	decl %r12d
-	
+
 	dest
-	movq %rbx,(%rsi)
+	movq %rbx, (%rsi)
 	dest
-	movq %r8,8(%rsi)
+	movq %r8, 8(%rsi)
 	dest
-	movq %r11,16(%rsi)
+	movq %r11, 16(%rsi)
 	dest
-	movq %rdx,24(%rsi)
+	movq %rdx, 24(%rsi)
 
 	dest
-	movq %r10,32(%rsi)
+	movq %r10, 32(%rsi)
 	dest
-	movq %rbp,40(%rsi)
+	movq %rbp, 40(%rsi)
 	dest
-	movq %r14,48(%rsi)
+	movq %r14, 48(%rsi)
 	dest
-	movq %r13,56(%rsi)
-	
+	movq %r13, 56(%rsi)
+
 3:
-	
-	leaq 64(%rdi),%rdi
-	leaq 64(%rsi),%rsi
 
-	jnz   .Lloop
+	leaq 64(%rdi), %rdi
+	leaq 64(%rsi), %rsi
 
-	adcq  %r9,%rax
+	jnz	.Lloop
 
-	/* do last upto 56 bytes */
+	adcq  %r9, %rax
+
+	/* do last up to 56 bytes */
 .Lhandle_tail:
 	/* ecx:	count */
-	movl %ecx,%r10d
-	andl $63,%ecx
-	shrl $3,%ecx
-	jz 	 .Lfold
+	movl %ecx, %r10d
+	andl $63, %ecx
+	shrl $3, %ecx
+	jz	.Lfold
 	clc
 	.p2align 4
-.Lloop_8:	
+.Lloop_8:
 	source
-	movq (%rdi),%rbx
-	adcq %rbx,%rax
+	movq (%rdi), %rbx
+	adcq %rbx, %rax
 	decl %ecx
 	dest
-	movq %rbx,(%rsi)
-	leaq 8(%rsi),%rsi /* preserve carry */
-	leaq 8(%rdi),%rdi
+	movq %rbx, (%rsi)
+	leaq 8(%rsi), %rsi /* preserve carry */
+	leaq 8(%rdi), %rdi
 	jnz	.Lloop_8
-	adcq %r9,%rax	/* add in carry */
+	adcq %r9, %rax	/* add in carry */
 
 .Lfold:
 	/* reduce checksum to 32bits */
-	movl %eax,%ebx
-	shrq $32,%rax
-	addl %ebx,%eax
-	adcl %r9d,%eax
+	movl %eax, %ebx
+	shrq $32, %rax
+	addl %ebx, %eax
+	adcl %r9d, %eax
 
-	/* do last upto 6 bytes */	
+	/* do last up to 6 bytes */
 .Lhandle_7:
-	movl %r10d,%ecx
-	andl $7,%ecx
-	shrl $1,%ecx
+	movl %r10d, %ecx
+	andl $7, %ecx
+	shrl $1, %ecx
 	jz   .Lhandle_1
-	movl $2,%edx
-	xorl %ebx,%ebx
-	clc  
+	movl $2, %edx
+	xorl %ebx, %ebx
+	clc
 	.p2align 4
-.Lloop_1:	
+.Lloop_1:
 	source
-	movw (%rdi),%bx
-	adcl %ebx,%eax
+	movw (%rdi), %bx
+	adcl %ebx, %eax
 	decl %ecx
 	dest
-	movw %bx,(%rsi)
-	leaq 2(%rdi),%rdi
-	leaq 2(%rsi),%rsi
+	movw %bx, (%rsi)
+	leaq 2(%rdi), %rdi
+	leaq 2(%rsi), %rsi
 	jnz .Lloop_1
-	adcl %r9d,%eax	/* add in carry */
-	
+	adcl %r9d, %eax	/* add in carry */
+
 	/* handle last odd byte */
 .Lhandle_1:
-	testl $1,%r10d
+	testl $1, %r10d
 	jz    .Lende
-	xorl  %ebx,%ebx
+	xorl  %ebx, %ebx
 	source
-	movb (%rdi),%bl
+	movb (%rdi), %bl
 	dest
-	movb %bl,(%rsi)
-	addl %ebx,%eax
-	adcl %r9d,%eax		/* carry */
-			
+	movb %bl, (%rsi)
+	addl %ebx, %eax
+	adcl %r9d, %eax		/* carry */
+
 	CFI_REMEMBER_STATE
 .Lende:
-	movq 2*8(%rsp),%rbx
+	movq 2*8(%rsp), %rbx
 	CFI_RESTORE rbx
-	movq 3*8(%rsp),%r12
+	movq 3*8(%rsp), %r12
 	CFI_RESTORE r12
-	movq 4*8(%rsp),%r14
+	movq 4*8(%rsp), %r14
 	CFI_RESTORE r14
-	movq 5*8(%rsp),%r13
+	movq 5*8(%rsp), %r13
 	CFI_RESTORE r13
-	movq 6*8(%rsp),%rbp
+	movq 6*8(%rsp), %rbp
 	CFI_RESTORE rbp
-	addq $7*8,%rsp
+	addq $7*8, %rsp
 	CFI_ADJUST_CFA_OFFSET -7*8
 	ret
 	CFI_RESTORE_STATE
 
 	/* Exception handlers. Very simple, zeroing is done in the wrappers */
 .Lbad_source:
-	movq (%rsp),%rax
-	testq %rax,%rax
+	movq (%rsp), %rax
+	testq %rax, %rax
 	jz   .Lende
-	movl $-EFAULT,(%rax)
+	movl $-EFAULT, (%rax)
 	jmp  .Lende
-	
+
 .Lbad_dest:
-	movq 8(%rsp),%rax
-	testq %rax,%rax
-	jz   .Lende	
-	movl $-EFAULT,(%rax)
+	movq 8(%rsp), %rax
+	testq %rax, %rax
+	jz   .Lende
+	movl $-EFAULT, (%rax)
 	jmp .Lende
 	CFI_ENDPROC
 ENDPROC(csum_partial_copy_generic)
diff --git a/arch/x86/lib/csum-partial_64.c b/arch/x86/lib/csum-partial_64.c
index bf51144..9845371 100644
--- a/arch/x86/lib/csum-partial_64.c
+++ b/arch/x86/lib/csum-partial_64.c
@@ -84,7 +84,7 @@ static unsigned do_csum(const unsigned char *buff, unsigned len)
 				count64--;
 			}
 
-			/* last upto 7 8byte blocks */
+			/* last up to 7 8byte blocks */
 			count %= 8; 
 			while (count) { 
 				asm("addq %1,%0\n\t"
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
new file mode 100644
index 0000000..0ecb843
--- /dev/null
+++ b/arch/x86/lib/memmove_64.S
@@ -0,0 +1,197 @@
+/*
+ * Normally compiler builtins are used, but sometimes the compiler calls out
+ * of line code. Based on asm-i386/string.h.
+ *
+ * This assembly file is re-written from memmove_64.c file.
+ *	- Copyright 2011 Fenghua Yu <fenghua.yu@intel.com>
+ */
+#define _STRING_C
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
+#undef memmove
+
+/*
+ * Implement memmove(). This can handle overlap between src and dst.
+ *
+ * Input:
+ * rdi: dest
+ * rsi: src
+ * rdx: count
+ *
+ * Output:
+ * rax: dest
+ */
+ENTRY(memmove)
+	CFI_STARTPROC
+	/* Handle more 32bytes in loop */
+	mov %rdi, %rax
+	cmp $0x20, %rdx
+	jb	1f
+
+	/* Decide forward/backward copy mode */
+	cmp %rdi, %rsi
+	jb	2f
+
+	/*
+	 * movsq instruction have many startup latency
+	 * so we handle small size by general register.
+	 */
+	cmp  $680, %rdx
+	jb	3f
+	/*
+	 * movsq instruction is only good for aligned case.
+	 */
+
+	cmpb %dil, %sil
+	je 4f
+3:
+	sub $0x20, %rdx
+	/*
+	 * We gobble 32byts forward in each loop.
+	 */
+5:
+	sub $0x20, %rdx
+	movq 0*8(%rsi), %r11
+	movq 1*8(%rsi), %r10
+	movq 2*8(%rsi), %r9
+	movq 3*8(%rsi), %r8
+	leaq 4*8(%rsi), %rsi
+
+	movq %r11, 0*8(%rdi)
+	movq %r10, 1*8(%rdi)
+	movq %r9, 2*8(%rdi)
+	movq %r8, 3*8(%rdi)
+	leaq 4*8(%rdi), %rdi
+	jae 5b
+	addq $0x20, %rdx
+	jmp 1f
+	/*
+	 * Handle data forward by movsq.
+	 */
+	.p2align 4
+4:
+	movq %rdx, %rcx
+	movq -8(%rsi, %rdx), %r11
+	lea -8(%rdi, %rdx), %r10
+	shrq $3, %rcx
+	rep movsq
+	movq %r11, (%r10)
+	jmp 13f
+	/*
+	 * Handle data backward by movsq.
+	 */
+	.p2align 4
+7:
+	movq %rdx, %rcx
+	movq (%rsi), %r11
+	movq %rdi, %r10
+	leaq -8(%rsi, %rdx), %rsi
+	leaq -8(%rdi, %rdx), %rdi
+	shrq $3, %rcx
+	std
+	rep movsq
+	cld
+	movq %r11, (%r10)
+	jmp 13f
+
+	/*
+	 * Start to prepare for backward copy.
+	 */
+	.p2align 4
+2:
+	cmp $680, %rdx
+	jb 6f
+	cmp %dil, %sil
+	je 7b
+6:
+	/*
+	 * Calculate copy position to tail.
+	 */
+	addq %rdx, %rsi
+	addq %rdx, %rdi
+	subq $0x20, %rdx
+	/*
+	 * We gobble 32byts backward in each loop.
+	 */
+8:
+	subq $0x20, %rdx
+	movq -1*8(%rsi), %r11
+	movq -2*8(%rsi), %r10
+	movq -3*8(%rsi), %r9
+	movq -4*8(%rsi), %r8
+	leaq -4*8(%rsi), %rsi
+
+	movq %r11, -1*8(%rdi)
+	movq %r10, -2*8(%rdi)
+	movq %r9, -3*8(%rdi)
+	movq %r8, -4*8(%rdi)
+	leaq -4*8(%rdi), %rdi
+	jae 8b
+	/*
+	 * Calculate copy position to head.
+	 */
+	addq $0x20, %rdx
+	subq %rdx, %rsi
+	subq %rdx, %rdi
+1:
+	cmpq $16, %rdx
+	jb 9f
+	/*
+	 * Move data from 16 bytes to 31 bytes.
+	 */
+	movq 0*8(%rsi), %r11
+	movq 1*8(%rsi), %r10
+	movq -2*8(%rsi, %rdx), %r9
+	movq -1*8(%rsi, %rdx), %r8
+	movq %r11, 0*8(%rdi)
+	movq %r10, 1*8(%rdi)
+	movq %r9, -2*8(%rdi, %rdx)
+	movq %r8, -1*8(%rdi, %rdx)
+	jmp 13f
+	.p2align 4
+9:
+	cmpq $8, %rdx
+	jb 10f
+	/*
+	 * Move data from 8 bytes to 15 bytes.
+	 */
+	movq 0*8(%rsi), %r11
+	movq -1*8(%rsi, %rdx), %r10
+	movq %r11, 0*8(%rdi)
+	movq %r10, -1*8(%rdi, %rdx)
+	jmp 13f
+10:
+	cmpq $4, %rdx
+	jb 11f
+	/*
+	 * Move data from 4 bytes to 7 bytes.
+	 */
+	movl (%rsi), %r11d
+	movl -4(%rsi, %rdx), %r10d
+	movl %r11d, (%rdi)
+	movl %r10d, -4(%rdi, %rdx)
+	jmp 13f
+11:
+	cmp $2, %rdx
+	jb 12f
+	/*
+	 * Move data from 2 bytes to 3 bytes.
+	 */
+	movw (%rsi), %r11w
+	movw -2(%rsi, %rdx), %r10w
+	movw %r11w, (%rdi)
+	movw %r10w, -2(%rdi, %rdx)
+	jmp 13f
+12:
+	cmp $1, %rdx
+	jb 13f
+	/*
+	 * Move data for 1 byte.
+	 */
+	movb (%rsi), %r11b
+	movb %r11b, (%rdi)
+13:
+	retq
+	CFI_ENDPROC
+ENDPROC(memmove)
diff --git a/arch/x86/lib/memmove_64.c b/arch/x86/lib/memmove_64.c
deleted file mode 100644
index 6d0f0ec..0000000
--- a/arch/x86/lib/memmove_64.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Normally compiler builtins are used, but sometimes the compiler calls out
-   of line code. Based on asm-i386/string.h.
- */
-#define _STRING_C
-#include <linux/string.h>
-#include <linux/module.h>
-
-#undef memmove
-void *memmove(void *dest, const void *src, size_t count)
-{
-	unsigned long d0,d1,d2,d3,d4,d5,d6,d7;
-	char *ret;
-
-	__asm__ __volatile__(
-		/* Handle more 32bytes in loop */
-		"mov %2, %3\n\t"
-		"cmp $0x20, %0\n\t"
-		"jb	1f\n\t"
-
-		/* Decide forward/backward copy mode */
-		"cmp %2, %1\n\t"
-		"jb	2f\n\t"
-
-		/*
-		 * movsq instruction have many startup latency
-		 * so we handle small size by general register.
-		 */
-		"cmp  $680, %0\n\t"
-		"jb 3f\n\t"
-		/*
-		 * movsq instruction is only good for aligned case.
-		 */
-		"cmpb %%dil, %%sil\n\t"
-		"je 4f\n\t"
-		"3:\n\t"
-		"sub $0x20, %0\n\t"
-		/*
-		 * We gobble 32byts forward in each loop.
-		 */
-		"5:\n\t"
-		"sub $0x20, %0\n\t"
-		"movq 0*8(%1), %4\n\t"
-		"movq 1*8(%1), %5\n\t"
-		"movq 2*8(%1), %6\n\t"
-		"movq 3*8(%1), %7\n\t"
-		"leaq 4*8(%1), %1\n\t"
-
-		"movq %4, 0*8(%2)\n\t"
-		"movq %5, 1*8(%2)\n\t"
-		"movq %6, 2*8(%2)\n\t"
-		"movq %7, 3*8(%2)\n\t"
-		"leaq 4*8(%2), %2\n\t"
-		"jae 5b\n\t"
-		"addq $0x20, %0\n\t"
-		"jmp 1f\n\t"
-		/*
-		 * Handle data forward by movsq.
-		 */
-		".p2align 4\n\t"
-		"4:\n\t"
-		"movq %0, %8\n\t"
-		"movq -8(%1, %0), %4\n\t"
-		"lea -8(%2, %0), %5\n\t"
-		"shrq $3, %8\n\t"
-		"rep movsq\n\t"
-		"movq %4, (%5)\n\t"
-		"jmp 13f\n\t"
-		/*
-		 * Handle data backward by movsq.
-		 */
-		".p2align 4\n\t"
-		"7:\n\t"
-		"movq %0, %8\n\t"
-		"movq (%1), %4\n\t"
-		"movq %2, %5\n\t"
-		"leaq -8(%1, %0), %1\n\t"
-		"leaq -8(%2, %0), %2\n\t"
-		"shrq $3, %8\n\t"
-		"std\n\t"
-		"rep movsq\n\t"
-		"cld\n\t"
-		"movq %4, (%5)\n\t"
-		"jmp 13f\n\t"
-
-		/*
-		 * Start to prepare for backward copy.
-		 */
-		".p2align 4\n\t"
-		"2:\n\t"
-		"cmp $680, %0\n\t"
-		"jb 6f \n\t"
-		"cmp %%dil, %%sil\n\t"
-		"je 7b \n\t"
-		"6:\n\t"
-		/*
-		 * Calculate copy position to tail.
-		 */
-		"addq %0, %1\n\t"
-		"addq %0, %2\n\t"
-		"subq $0x20, %0\n\t"
-		/*
-		 * We gobble 32byts backward in each loop.
-		 */
-		"8:\n\t"
-		"subq $0x20, %0\n\t"
-		"movq -1*8(%1), %4\n\t"
-		"movq -2*8(%1), %5\n\t"
-		"movq -3*8(%1), %6\n\t"
-		"movq -4*8(%1), %7\n\t"
-		"leaq -4*8(%1), %1\n\t"
-
-		"movq %4, -1*8(%2)\n\t"
-		"movq %5, -2*8(%2)\n\t"
-		"movq %6, -3*8(%2)\n\t"
-		"movq %7, -4*8(%2)\n\t"
-		"leaq -4*8(%2), %2\n\t"
-		"jae 8b\n\t"
-		/*
-		 * Calculate copy position to head.
-		 */
-		"addq $0x20, %0\n\t"
-		"subq %0, %1\n\t"
-		"subq %0, %2\n\t"
-		"1:\n\t"
-		"cmpq $16, %0\n\t"
-		"jb 9f\n\t"
-		/*
-		 * Move data from 16 bytes to 31 bytes.
-		 */
-		"movq 0*8(%1), %4\n\t"
-		"movq 1*8(%1), %5\n\t"
-		"movq -2*8(%1, %0), %6\n\t"
-		"movq -1*8(%1, %0), %7\n\t"
-		"movq %4, 0*8(%2)\n\t"
-		"movq %5, 1*8(%2)\n\t"
-		"movq %6, -2*8(%2, %0)\n\t"
-		"movq %7, -1*8(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		".p2align 4\n\t"
-		"9:\n\t"
-		"cmpq $8, %0\n\t"
-		"jb 10f\n\t"
-		/*
-		 * Move data from 8 bytes to 15 bytes.
-		 */
-		"movq 0*8(%1), %4\n\t"
-		"movq -1*8(%1, %0), %5\n\t"
-		"movq %4, 0*8(%2)\n\t"
-		"movq %5, -1*8(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		"10:\n\t"
-		"cmpq $4, %0\n\t"
-		"jb 11f\n\t"
-		/*
-		 * Move data from 4 bytes to 7 bytes.
-		 */
-		"movl (%1), %4d\n\t"
-		"movl -4(%1, %0), %5d\n\t"
-		"movl %4d, (%2)\n\t"
-		"movl %5d, -4(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		"11:\n\t"
-		"cmp $2, %0\n\t"
-		"jb 12f\n\t"
-		/*
-		 * Move data from 2 bytes to 3 bytes.
-		 */
-		"movw (%1), %4w\n\t"
-		"movw -2(%1, %0), %5w\n\t"
-		"movw %4w, (%2)\n\t"
-		"movw %5w, -2(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		"12:\n\t"
-		"cmp $1, %0\n\t"
-		"jb 13f\n\t"
-		/*
-		 * Move data for 1 byte.
-		 */
-		"movb (%1), %4b\n\t"
-		"movb %4b, (%2)\n\t"
-		"13:\n\t"
-		: "=&d" (d0), "=&S" (d1), "=&D" (d2), "=&a" (ret) ,
-		  "=r"(d3), "=r"(d4), "=r"(d5), "=r"(d6), "=&c" (d7)
-		:"0" (count),
-		 "1" (src),
-		 "2" (dest)
-		:"memory");
-
-		return ret;
-
-}
-EXPORT_SYMBOL(memmove);
diff --git a/arch/x86/lib/rwsem_64.S b/arch/x86/lib/rwsem_64.S
index 41fcf00..6774397 100644
--- a/arch/x86/lib/rwsem_64.S
+++ b/arch/x86/lib/rwsem_64.S
@@ -23,43 +23,50 @@
 #include <asm/dwarf2.h>
 
 #define save_common_regs \
-	pushq %rdi; \
-	pushq %rsi; \
-	pushq %rcx; \
-	pushq %r8; \
-	pushq %r9; \
-	pushq %r10; \
-	pushq %r11
+	pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
+	pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
+	pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
+	pushq_cfi %r8;  CFI_REL_OFFSET r8,  0; \
+	pushq_cfi %r9;  CFI_REL_OFFSET r9,  0; \
+	pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
+	pushq_cfi %r11; CFI_REL_OFFSET r11, 0
 
 #define restore_common_regs \
-	popq %r11; \
-	popq %r10; \
-	popq %r9; \
-	popq %r8; \
-	popq %rcx; \
-	popq %rsi; \
-	popq %rdi
+	popq_cfi %r11; CFI_RESTORE r11; \
+	popq_cfi %r10; CFI_RESTORE r10; \
+	popq_cfi %r9;  CFI_RESTORE r9; \
+	popq_cfi %r8;  CFI_RESTORE r8; \
+	popq_cfi %rcx; CFI_RESTORE rcx; \
+	popq_cfi %rsi; CFI_RESTORE rsi; \
+	popq_cfi %rdi; CFI_RESTORE rdi
 
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
+	CFI_STARTPROC
 	save_common_regs
-	pushq %rdx
+	pushq_cfi %rdx
+	CFI_REL_OFFSET rdx, 0
 	movq %rax,%rdi
 	call rwsem_down_read_failed
-	popq %rdx
+	popq_cfi %rdx
+	CFI_RESTORE rdx
 	restore_common_regs
 	ret
-	ENDPROC(call_rwsem_down_read_failed)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_down_read_failed)
 
 ENTRY(call_rwsem_down_write_failed)
+	CFI_STARTPROC
 	save_common_regs
 	movq %rax,%rdi
 	call rwsem_down_write_failed
 	restore_common_regs
 	ret
-	ENDPROC(call_rwsem_down_write_failed)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_down_write_failed)
 
 ENTRY(call_rwsem_wake)
+	CFI_STARTPROC
 	decl %edx	/* do nothing if still outstanding active readers */
 	jnz 1f
 	save_common_regs
@@ -67,15 +74,20 @@ ENTRY(call_rwsem_wake)
 	call rwsem_wake
 	restore_common_regs
 1:	ret
-	ENDPROC(call_rwsem_wake)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_wake)
 
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_downgrade_wake)
+	CFI_STARTPROC
 	save_common_regs
-	pushq %rdx
+	pushq_cfi %rdx
+	CFI_REL_OFFSET rdx, 0
 	movq %rax,%rdi
 	call rwsem_downgrade_wake
-	popq %rdx
+	popq_cfi %rdx
+	CFI_RESTORE rdx
 	restore_common_regs
 	ret
-	ENDPROC(call_rwsem_downgrade_wake)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_downgrade_wake)
diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
index 648fe47..06691da 100644
--- a/arch/x86/lib/semaphore_32.S
+++ b/arch/x86/lib/semaphore_32.S
@@ -36,7 +36,7 @@
  */
 #ifdef CONFIG_SMP
 ENTRY(__write_lock_failed)
-	CFI_STARTPROC simple
+	CFI_STARTPROC
 	FRAME
 2: 	LOCK_PREFIX
 	addl	$ RW_LOCK_BIAS,(%eax)
@@ -74,29 +74,23 @@ ENTRY(__read_lock_failed)
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
 	CFI_STARTPROC
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edx
 	CFI_REL_OFFSET edx,0
 	call rwsem_down_read_failed
-	pop %edx
-	CFI_ADJUST_CFA_OFFSET -4
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edx
+	popl_cfi %ecx
 	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_down_read_failed)
 
 ENTRY(call_rwsem_down_write_failed)
 	CFI_STARTPROC
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
 	calll rwsem_down_write_failed
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx
 	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_down_write_failed)
@@ -105,12 +99,10 @@ ENTRY(call_rwsem_wake)
 	CFI_STARTPROC
 	decw %dx    /* do nothing if still outstanding active readers */
 	jnz 1f
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
 	call rwsem_wake
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx
 1:	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_wake)
@@ -118,17 +110,13 @@ ENTRY(call_rwsem_wake)
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_downgrade_wake)
 	CFI_STARTPROC
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edx
 	CFI_REL_OFFSET edx,0
 	call rwsem_downgrade_wake
-	pop %edx
-	CFI_ADJUST_CFA_OFFSET -4
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edx
+	popl_cfi %ecx
 	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_downgrade_wake)
diff --git a/arch/x86/lib/thunk_32.S b/arch/x86/lib/thunk_32.S
index 650b11e..2930ae0 100644
--- a/arch/x86/lib/thunk_32.S
+++ b/arch/x86/lib/thunk_32.S
@@ -7,24 +7,6 @@
 
 	#include <linux/linkage.h>
 
-#define ARCH_TRACE_IRQS_ON			\
-	pushl %eax;				\
-	pushl %ecx;				\
-	pushl %edx;				\
-	call trace_hardirqs_on;			\
-	popl %edx;				\
-	popl %ecx;				\
-	popl %eax;
-
-#define ARCH_TRACE_IRQS_OFF			\
-	pushl %eax;				\
-	pushl %ecx;				\
-	pushl %edx;				\
-	call trace_hardirqs_off;		\
-	popl %edx;				\
-	popl %ecx;				\
-	popl %eax;
-
 #ifdef CONFIG_TRACE_IRQFLAGS
 	/* put return address in eax (arg1) */
 	.macro thunk_ra name,func
diff --git a/arch/x86/lib/thunk_64.S b/arch/x86/lib/thunk_64.S
index bf9a7d5..782b082 100644
--- a/arch/x86/lib/thunk_64.S
+++ b/arch/x86/lib/thunk_64.S
@@ -22,26 +22,6 @@
 	CFI_ENDPROC
 	.endm
 
-	/* rdi:	arg1 ... normal C conventions. rax is passed from C. */ 	
-	.macro thunk_retrax name,func
-	.globl \name
-\name:	
-	CFI_STARTPROC
-	SAVE_ARGS
-	call \func
-	jmp  restore_norax
-	CFI_ENDPROC
-	.endm
-	
-
-	.section .sched.text, "ax"
-#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
-	thunk rwsem_down_read_failed_thunk,rwsem_down_read_failed
-	thunk rwsem_down_write_failed_thunk,rwsem_down_write_failed
-	thunk rwsem_wake_thunk,rwsem_wake
-	thunk rwsem_downgrade_thunk,rwsem_downgrade_wake
-#endif	
-	
 #ifdef CONFIG_TRACE_IRQFLAGS
 	/* put return address in rdi (arg1) */
 	.macro thunk_ra name,func
@@ -72,10 +52,3 @@ restore:
 	RESTORE_ARGS
 	ret	
 	CFI_ENDPROC
-	
-	CFI_STARTPROC
-	SAVE_ARGS
-restore_norax:	
-	RESTORE_ARGS 1
-	ret
-	CFI_ENDPROC
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index 09df2f9..3e608ed 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_MMIOTRACE_TEST)	+= testmmiotrace.o
 obj-$(CONFIG_NUMA)		+= numa.o numa_$(BITS).o
 obj-$(CONFIG_AMD_NUMA)		+= amdtopology_64.o
 obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
+obj-$(CONFIG_NUMA_EMU)		+= numa_emulation.o
 
 obj-$(CONFIG_HAVE_MEMBLOCK)		+= memblock.o
 
diff --git a/arch/x86/mm/amdtopology_64.c b/arch/x86/mm/amdtopology_64.c
index f21962c..0919c26 100644
--- a/arch/x86/mm/amdtopology_64.c
+++ b/arch/x86/mm/amdtopology_64.c
@@ -26,9 +26,7 @@
 #include <asm/apic.h>
 #include <asm/amd_nb.h>
 
-static struct bootnode __initdata nodes[8];
 static unsigned char __initdata nodeids[8];
-static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
 
 static __init int find_northbridge(void)
 {
@@ -51,7 +49,7 @@ static __init int find_northbridge(void)
 		return num;
 	}
 
-	return -1;
+	return -ENOENT;
 }
 
 static __init void early_get_boot_cpu_id(void)
@@ -69,17 +67,18 @@ static __init void early_get_boot_cpu_id(void)
 #endif
 }
 
-int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
+int __init amd_numa_init(void)
 {
-	unsigned long start = PFN_PHYS(start_pfn);
-	unsigned long end = PFN_PHYS(end_pfn);
+	unsigned long start = PFN_PHYS(0);
+	unsigned long end = PFN_PHYS(max_pfn);
 	unsigned numnodes;
 	unsigned long prevbase;
-	int i, nb, found = 0;
+	int i, j, nb;
 	u32 nodeid, reg;
+	unsigned int bits, cores, apicid_base;
 
 	if (!early_pci_allowed())
-		return -1;
+		return -EINVAL;
 
 	nb = find_northbridge();
 	if (nb < 0)
@@ -90,7 +89,7 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 	reg = read_pci_config(0, nb, 0, 0x60);
 	numnodes = ((reg >> 4) & 0xF) + 1;
 	if (numnodes <= 1)
-		return -1;
+		return -ENOENT;
 
 	pr_info("Number of physical nodes %d\n", numnodes);
 
@@ -121,9 +120,9 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 		if ((base >> 8) & 3 || (limit >> 8) & 3) {
 			pr_err("Node %d using interleaving mode %lx/%lx\n",
 			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
-			return -1;
+			return -EINVAL;
 		}
-		if (node_isset(nodeid, nodes_parsed)) {
+		if (node_isset(nodeid, numa_nodes_parsed)) {
 			pr_info("Node %d already present, skipping\n",
 				nodeid);
 			continue;
@@ -160,117 +159,28 @@ int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
 		if (prevbase > base) {
 			pr_err("Node map not sorted %lx,%lx\n",
 			       prevbase, base);
-			return -1;
+			return -EINVAL;
 		}
 
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
 			nodeid, base, limit);
 
-		found++;
-
-		nodes[nodeid].start = base;
-		nodes[nodeid].end = limit;
-
 		prevbase = base;
-
-		node_set(nodeid, nodes_parsed);
-	}
-
-	if (!found)
-		return -1;
-	return 0;
-}
-
-#ifdef CONFIG_NUMA_EMU
-static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
-	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
-};
-
-void __init amd_get_nodes(struct bootnode *physnodes)
-{
-	int i;
-
-	for_each_node_mask(i, nodes_parsed) {
-		physnodes[i].start = nodes[i].start;
-		physnodes[i].end = nodes[i].end;
+		numa_add_memblk(nodeid, base, limit);
+		node_set(nodeid, numa_nodes_parsed);
 	}
-}
-
-static int __init find_node_by_addr(unsigned long addr)
-{
-	int ret = NUMA_NO_NODE;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		if (addr >= nodes[i].start && addr < nodes[i].end) {
-			ret = i;
-			break;
-		}
-	return ret;
-}
 
-/*
- * For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be
- * setup to represent the physical topology but reflect the emulated
- * environment.  For each emulated node, the real node which it appears on is
- * found and a fake pxm to nid mapping is created which mirrors the actual
- * locality.  node_distance() then represents the correct distances between
- * emulated nodes by using the fake acpi mappings to pxms.
- */
-void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
-{
-	unsigned int bits;
-	unsigned int cores;
-	unsigned int apicid_base = 0;
-	int i;
+	if (!nodes_weight(numa_nodes_parsed))
+		return -ENOENT;
 
+	/*
+	 * We seem to have valid NUMA configuration.  Map apicids to nodes
+	 * using the coreid bits from early_identify_cpu.
+	 */
 	bits = boot_cpu_data.x86_coreid_bits;
 	cores = 1 << bits;
-	early_get_boot_cpu_id();
-	if (boot_cpu_physical_apicid > 0)
-		apicid_base = boot_cpu_physical_apicid;
-
-	for (i = 0; i < nr_nodes; i++) {
-		int index;
-		int nid;
-		int j;
-
-		nid = find_node_by_addr(nodes[i].start);
-		if (nid == NUMA_NO_NODE)
-			continue;
-
-		index = nodeids[nid] << bits;
-		if (fake_apicid_to_node[index + apicid_base] == NUMA_NO_NODE)
-			for (j = apicid_base; j < cores + apicid_base; j++)
-				fake_apicid_to_node[index + j] = i;
-#ifdef CONFIG_ACPI_NUMA
-		__acpi_map_pxm_to_node(nid, i);
-#endif
-	}
-	memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
-}
-#endif /* CONFIG_NUMA_EMU */
-
-int __init amd_scan_nodes(void)
-{
-	unsigned int bits;
-	unsigned int cores;
-	unsigned int apicid_base;
-	int i;
-
-	BUG_ON(nodes_empty(nodes_parsed));
-	node_possible_map = nodes_parsed;
-	memnode_shift = compute_hash_shift(nodes, 8, NULL);
-	if (memnode_shift < 0) {
-		pr_err("No NUMA node hash function found. Contact maintainer\n");
-		return -1;
-	}
-	pr_info("Using node hash shift of %d\n", memnode_shift);
-
-	/* use the coreid bits from early_identify_cpu */
-	bits = boot_cpu_data.x86_coreid_bits;
-	cores = (1<<bits);
 	apicid_base = 0;
+
 	/* get the APIC ID of the BSP early for systems with apicid lifting */
 	early_get_boot_cpu_id();
 	if (boot_cpu_physical_apicid > 0) {
@@ -278,17 +188,9 @@ int __init amd_scan_nodes(void)
 		apicid_base = boot_cpu_physical_apicid;
 	}
 
-	for_each_node_mask(i, node_possible_map) {
-		int j;
-
-		memblock_x86_register_active_regions(i,
-				nodes[i].start >> PAGE_SHIFT,
-				nodes[i].end >> PAGE_SHIFT);
+	for_each_node_mask(i, numa_nodes_parsed)
 		for (j = apicid_base; j < cores + apicid_base; j++)
-			apicid_to_node[(i << bits) + j] = i;
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	}
+			set_apicid_to_node((i << bits) + j, i);
 
-	numa_init_array();
 	return 0;
 }
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 069ce7c..d420398 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -326,7 +326,7 @@ try_again:
 	if (mm->free_area_cache < len)
 		goto fail;
 
-	/* either no address requested or cant fit in requested address hole */
+	/* either no address requested or can't fit in requested address hole */
 	addr = (mm->free_area_cache - len) & huge_page_mask(h);
 	do {
 		/*
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 947f42a..286d289 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -18,9 +18,9 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-unsigned long __initdata e820_table_start;
-unsigned long __meminitdata e820_table_end;
-unsigned long __meminitdata e820_table_top;
+unsigned long __initdata pgt_buf_start;
+unsigned long __meminitdata pgt_buf_end;
+unsigned long __meminitdata pgt_buf_top;
 
 int after_bootmem;
 
@@ -33,7 +33,7 @@ int direct_gbpages
 static void __init find_early_table_space(unsigned long end, int use_pse,
 					  int use_gbpages)
 {
-	unsigned long puds, pmds, ptes, tables, start;
+	unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
 	phys_addr_t base;
 
 	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
@@ -65,29 +65,20 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
 #ifdef CONFIG_X86_32
 	/* for fixmap */
 	tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
-#endif
 
-	/*
-	 * RED-PEN putting page tables only on node 0 could
-	 * cause a hotspot and fill up ZONE_DMA. The page tables
-	 * need roughly 0.5KB per GB.
-	 */
-#ifdef CONFIG_X86_32
-	start = 0x7000;
-#else
-	start = 0x8000;
+	good_end = max_pfn_mapped << PAGE_SHIFT;
 #endif
-	base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT,
-					tables, PAGE_SIZE);
+
+	base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE);
 	if (base == MEMBLOCK_ERROR)
 		panic("Cannot find space for the kernel page tables");
 
-	e820_table_start = base >> PAGE_SHIFT;
-	e820_table_end = e820_table_start;
-	e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
+	pgt_buf_start = base >> PAGE_SHIFT;
+	pgt_buf_end = pgt_buf_start;
+	pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
 	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
-		end, e820_table_start << PAGE_SHIFT, e820_table_top << PAGE_SHIFT);
+		end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
 }
 
 struct map_range {
@@ -279,30 +270,11 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
 	load_cr3(swapper_pg_dir);
 #endif
 
-#ifdef CONFIG_X86_64
-	if (!after_bootmem && !start) {
-		pud_t *pud;
-		pmd_t *pmd;
-
-		mmu_cr4_features = read_cr4();
-
-		/*
-		 * _brk_end cannot change anymore, but it and _end may be
-		 * located on different 2M pages. cleanup_highmap(), however,
-		 * can only consider _end when it runs, so destroy any
-		 * mappings beyond _brk_end here.
-		 */
-		pud = pud_offset(pgd_offset_k(_brk_end), _brk_end);
-		pmd = pmd_offset(pud, _brk_end - 1);
-		while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1))
-			pmd_clear(pmd);
-	}
-#endif
 	__flush_tlb_all();
 
-	if (!after_bootmem && e820_table_end > e820_table_start)
-		memblock_x86_reserve_range(e820_table_start << PAGE_SHIFT,
-				 e820_table_end << PAGE_SHIFT, "PGTABLE");
+	if (!after_bootmem && pgt_buf_end > pgt_buf_start)
+		memblock_x86_reserve_range(pgt_buf_start << PAGE_SHIFT,
+				 pgt_buf_end << PAGE_SHIFT, "PGTABLE");
 
 	if (!after_bootmem)
 		early_memtest(start, end);
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index c821074..80088f9 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -62,10 +62,10 @@ bool __read_mostly __vmalloc_start_set = false;
 
 static __init void *alloc_low_page(void)
 {
-	unsigned long pfn = e820_table_end++;
+	unsigned long pfn = pgt_buf_end++;
 	void *adr;
 
-	if (pfn >= e820_table_top)
+	if (pfn >= pgt_buf_top)
 		panic("alloc_low_page: ran out of memory");
 
 	adr = __va(pfn * PAGE_SIZE);
@@ -163,8 +163,8 @@ static pte_t *__init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
 	if (pmd_idx_kmap_begin != pmd_idx_kmap_end
 	    && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
 	    && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
-	    && ((__pa(pte) >> PAGE_SHIFT) < e820_table_start
-		|| (__pa(pte) >> PAGE_SHIFT) >= e820_table_end)) {
+	    && ((__pa(pte) >> PAGE_SHIFT) < pgt_buf_start
+		|| (__pa(pte) >> PAGE_SHIFT) >= pgt_buf_end)) {
 		pte_t *newpte;
 		int i;
 
@@ -644,8 +644,7 @@ void __init find_low_pfn_range(void)
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
 	highstart_pfn = highend_pfn = max_pfn;
@@ -918,7 +917,7 @@ static void mark_nxdata_nx(void)
 {
 	/*
 	 * When this called, init has already been executed and released,
-	 * so everything past _etext sould be NX.
+	 * so everything past _etext should be NX.
 	 */
 	unsigned long start = PFN_ALIGN(_etext);
 	/*
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index c14a542..2362b64 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -51,6 +51,8 @@
 #include <asm/numa.h>
 #include <asm/cacheflush.h>
 #include <asm/init.h>
+#include <asm/uv/uv.h>
+#include <asm/setup.h>
 
 static int __init parse_direct_gbpages_off(char *arg)
 {
@@ -293,18 +295,18 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size)
  * to the compile time generated pmds. This results in invalid pmds up
  * to the point where we hit the physaddr 0 mapping.
  *
- * We limit the mappings to the region from _text to _end.  _end is
- * rounded up to the 2MB boundary. This catches the invalid pmds as
+ * We limit the mappings to the region from _text to _brk_end.  _brk_end
+ * is rounded up to the 2MB boundary. This catches the invalid pmds as
  * well, as they are located before _text:
  */
 void __init cleanup_highmap(void)
 {
 	unsigned long vaddr = __START_KERNEL_map;
-	unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1;
+	unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT);
+	unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1;
 	pmd_t *pmd = level2_kernel_pgt;
-	pmd_t *last_pmd = pmd + PTRS_PER_PMD;
 
-	for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
+	for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) {
 		if (pmd_none(*pmd))
 			continue;
 		if (vaddr < (unsigned long) _text || vaddr > end)
@@ -314,7 +316,7 @@ void __init cleanup_highmap(void)
 
 static __ref void *alloc_low_page(unsigned long *phys)
 {
-	unsigned long pfn = e820_table_end++;
+	unsigned long pfn = pgt_buf_end++;
 	void *adr;
 
 	if (after_bootmem) {
@@ -324,7 +326,7 @@ static __ref void *alloc_low_page(unsigned long *phys)
 		return adr;
 	}
 
-	if (pfn >= e820_table_top)
+	if (pfn >= pgt_buf_top)
 		panic("alloc_low_page: ran out of memory");
 
 	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
@@ -333,12 +335,28 @@ static __ref void *alloc_low_page(unsigned long *phys)
 	return adr;
 }
 
+static __ref void *map_low_page(void *virt)
+{
+	void *adr;
+	unsigned long phys, left;
+
+	if (after_bootmem)
+		return virt;
+
+	phys = __pa(virt);
+	left = phys & (PAGE_SIZE - 1);
+	adr = early_memremap(phys & PAGE_MASK, PAGE_SIZE);
+	adr = (void *)(((unsigned long)adr) | left);
+
+	return adr;
+}
+
 static __ref void unmap_low_page(void *adr)
 {
 	if (after_bootmem)
 		return;
 
-	early_iounmap(adr, PAGE_SIZE);
+	early_iounmap((void *)((unsigned long)adr & PAGE_MASK), PAGE_SIZE);
 }
 
 static unsigned long __meminit
@@ -386,15 +404,6 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
 }
 
 static unsigned long __meminit
-phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end,
-		pgprot_t prot)
-{
-	pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd);
-
-	return phys_pte_init(pte, address, end, prot);
-}
-
-static unsigned long __meminit
 phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
 	      unsigned long page_size_mask, pgprot_t prot)
 {
@@ -420,8 +429,10 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
 		if (pmd_val(*pmd)) {
 			if (!pmd_large(*pmd)) {
 				spin_lock(&init_mm.page_table_lock);
-				last_map_addr = phys_pte_update(pmd, address,
+				pte = map_low_page((pte_t *)pmd_page_vaddr(*pmd));
+				last_map_addr = phys_pte_init(pte, address,
 								end, prot);
+				unmap_low_page(pte);
 				spin_unlock(&init_mm.page_table_lock);
 				continue;
 			}
@@ -468,18 +479,6 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
 }
 
 static unsigned long __meminit
-phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end,
-		unsigned long page_size_mask, pgprot_t prot)
-{
-	pmd_t *pmd = pmd_offset(pud, 0);
-	unsigned long last_map_addr;
-
-	last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot);
-	__flush_tlb_all();
-	return last_map_addr;
-}
-
-static unsigned long __meminit
 phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
 			 unsigned long page_size_mask)
 {
@@ -504,8 +503,11 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
 
 		if (pud_val(*pud)) {
 			if (!pud_large(*pud)) {
-				last_map_addr = phys_pmd_update(pud, addr, end,
+				pmd = map_low_page(pmd_offset(pud, 0));
+				last_map_addr = phys_pmd_init(pmd, addr, end,
 							 page_size_mask, prot);
+				unmap_low_page(pmd);
+				__flush_tlb_all();
 				continue;
 			}
 			/*
@@ -553,17 +555,6 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
 	return last_map_addr;
 }
 
-static unsigned long __meminit
-phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end,
-		 unsigned long page_size_mask)
-{
-	pud_t *pud;
-
-	pud = (pud_t *)pgd_page_vaddr(*pgd);
-
-	return phys_pud_init(pud, addr, end, page_size_mask);
-}
-
 unsigned long __meminit
 kernel_physical_mapping_init(unsigned long start,
 			     unsigned long end,
@@ -587,8 +578,10 @@ kernel_physical_mapping_init(unsigned long start,
 			next = end;
 
 		if (pgd_val(*pgd)) {
-			last_map_addr = phys_pud_update(pgd, __pa(start),
+			pud = map_low_page((pud_t *)pgd_page_vaddr(*pgd));
+			last_map_addr = phys_pud_init(pud, __pa(start),
 						 __pa(end), page_size_mask);
+			unmap_low_page(pud);
 			continue;
 		}
 
@@ -612,10 +605,9 @@ kernel_physical_mapping_init(unsigned long start,
 }
 
 #ifndef CONFIG_NUMA
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(void)
 {
-	memblock_x86_register_active_regions(0, start_pfn, end_pfn);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
 }
 #endif
 
@@ -908,6 +900,19 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 	return NULL;
 }
 
+#ifdef CONFIG_X86_UV
+#define MIN_MEMORY_BLOCK_SIZE   (1 << SECTION_SIZE_BITS)
+
+unsigned long memory_block_size_bytes(void)
+{
+	if (is_uv_system()) {
+		printk(KERN_INFO "UV: memory block size 2GB\n");
+		return 2UL * 1024 * 1024 * 1024;
+	}
+	return MIN_MEMORY_BLOCK_SIZE;
+}
+#endif
+
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 /*
  * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index ebf6d78..9559d36 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -26,12 +26,50 @@ static __init int numa_setup(char *opt)
 early_param("numa", numa_setup);
 
 /*
- * Which logical CPUs are on which nodes
+ * apicid, cpu, node mappings
  */
+s16 __apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+
 cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 EXPORT_SYMBOL(node_to_cpumask_map);
 
 /*
+ * Map cpu index to node index
+ */
+DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE);
+EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map);
+
+void __cpuinit numa_set_node(int cpu, int node)
+{
+	int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map);
+
+	/* early setting, no percpu area yet */
+	if (cpu_to_node_map) {
+		cpu_to_node_map[cpu] = node;
+		return;
+	}
+
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+	if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
+		printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu);
+		dump_stack();
+		return;
+	}
+#endif
+	per_cpu(x86_cpu_to_node_map, cpu) = node;
+
+	if (node != NUMA_NO_NODE)
+		set_cpu_numa_node(cpu, node);
+}
+
+void __cpuinit numa_clear_node(int cpu)
+{
+	numa_set_node(cpu, NUMA_NO_NODE);
+}
+
+/*
  * Allocate node_to_cpumask_map based on number of available nodes
  * Requires node_possible_map to be valid.
  *
@@ -57,7 +95,174 @@ void __init setup_node_to_cpumask_map(void)
 	pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids);
 }
 
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+/*
+ * There are unfortunately some poorly designed mainboards around that
+ * only connect memory to a single CPU. This breaks the 1:1 cpu->node
+ * mapping. To avoid this fill in the mapping for all possible CPUs,
+ * as the number of CPUs is not known yet. We round robin the existing
+ * nodes.
+ */
+void __init numa_init_array(void)
+{
+	int rr, i;
+
+	rr = first_node(node_online_map);
+	for (i = 0; i < nr_cpu_ids; i++) {
+		if (early_cpu_to_node(i) != NUMA_NO_NODE)
+			continue;
+		numa_set_node(i, rr);
+		rr = next_node(rr, node_online_map);
+		if (rr == MAX_NUMNODES)
+			rr = first_node(node_online_map);
+	}
+}
+
+static __init int find_near_online_node(int node)
+{
+	int n, val;
+	int min_val = INT_MAX;
+	int best_node = -1;
+
+	for_each_online_node(n) {
+		val = node_distance(node, n);
+
+		if (val < min_val) {
+			min_val = val;
+			best_node = n;
+		}
+	}
+
+	return best_node;
+}
+
+/*
+ * Setup early cpu_to_node.
+ *
+ * Populate cpu_to_node[] only if x86_cpu_to_apicid[],
+ * and apicid_to_node[] tables have valid entries for a CPU.
+ * This means we skip cpu_to_node[] initialisation for NUMA
+ * emulation and faking node case (when running a kernel compiled
+ * for NUMA on a non NUMA box), which is OK as cpu_to_node[]
+ * is already initialized in a round robin manner at numa_init_array,
+ * prior to this call, and this initialization is good enough
+ * for the fake NUMA cases.
+ *
+ * Called before the per_cpu areas are setup.
+ */
+void __init init_cpu_to_node(void)
+{
+	int cpu;
+	u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
+
+	BUG_ON(cpu_to_apicid == NULL);
+
+	for_each_possible_cpu(cpu) {
+		int node = numa_cpu_node(cpu);
+
+		if (node == NUMA_NO_NODE)
+			continue;
+		if (!node_online(node))
+			node = find_near_online_node(node);
+		numa_set_node(cpu, node);
+	}
+}
+
+#ifndef CONFIG_DEBUG_PER_CPU_MAPS
+
+# ifndef CONFIG_NUMA_EMU
+void __cpuinit numa_add_cpu(int cpu)
+{
+	cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
+}
+# endif	/* !CONFIG_NUMA_EMU */
+
+#else	/* !CONFIG_DEBUG_PER_CPU_MAPS */
+
+int __cpu_to_node(int cpu)
+{
+	if (early_per_cpu_ptr(x86_cpu_to_node_map)) {
+		printk(KERN_WARNING
+			"cpu_to_node(%d): usage too early!\n", cpu);
+		dump_stack();
+		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
+	}
+	return per_cpu(x86_cpu_to_node_map, cpu);
+}
+EXPORT_SYMBOL(__cpu_to_node);
+
+/*
+ * Same function as cpu_to_node() but used if called before the
+ * per_cpu areas are setup.
+ */
+int early_cpu_to_node(int cpu)
+{
+	if (early_per_cpu_ptr(x86_cpu_to_node_map))
+		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
+
+	if (!cpu_possible(cpu)) {
+		printk(KERN_WARNING
+			"early_cpu_to_node(%d): no per_cpu area!\n", cpu);
+		dump_stack();
+		return NUMA_NO_NODE;
+	}
+	return per_cpu(x86_cpu_to_node_map, cpu);
+}
+
+struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable)
+{
+	int node = early_cpu_to_node(cpu);
+	struct cpumask *mask;
+	char buf[64];
+
+	if (node == NUMA_NO_NODE) {
+		/* early_cpu_to_node() already emits a warning and trace */
+		return NULL;
+	}
+	mask = node_to_cpumask_map[node];
+	if (!mask) {
+		pr_err("node_to_cpumask_map[%i] NULL\n", node);
+		dump_stack();
+		return NULL;
+	}
+
+	cpulist_scnprintf(buf, sizeof(buf), mask);
+	printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
+		enable ? "numa_add_cpu" : "numa_remove_cpu",
+		cpu, node, buf);
+	return mask;
+}
+
+# ifndef CONFIG_NUMA_EMU
+static void __cpuinit numa_set_cpumask(int cpu, int enable)
+{
+	struct cpumask *mask;
+
+	mask = debug_cpumask_set_cpu(cpu, enable);
+	if (!mask)
+		return;
+
+	if (enable)
+		cpumask_set_cpu(cpu, mask);
+	else
+		cpumask_clear_cpu(cpu, mask);
+}
+
+void __cpuinit numa_add_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, 1);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, 0);
+}
+# endif	/* !CONFIG_NUMA_EMU */
+
 /*
  * Returns a pointer to the bitmask of CPUs on Node 'node'.
  */
@@ -80,4 +285,5 @@ const struct cpumask *cpumask_of_node(int node)
 	return node_to_cpumask_map[node];
 }
 EXPORT_SYMBOL(cpumask_of_node);
-#endif
+
+#endif	/* !CONFIG_DEBUG_PER_CPU_MAPS */
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index 84a3e4c..bde3906 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -110,6 +110,12 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
 
 static unsigned long kva_start_pfn;
 static unsigned long kva_pages;
+
+int __cpuinit numa_cpu_node(int cpu)
+{
+	return apic->x86_32_numa_cpu_node(cpu);
+}
+
 /*
  * FLAT - support for basic PC memory model with discontig enabled, essentially
  *        a single node with all available processors in it with a flat
@@ -346,8 +352,7 @@ static void init_remap_allocator(int nid)
 		(ulong) node_remap_end_vaddr[nid]);
 }
 
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(void)
 {
 	int nid;
 	long kva_target_pfn;
@@ -361,6 +366,7 @@ void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
 	 */
 
 	get_memcfg_numa();
+	numa_init_array();
 
 	kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
 
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index 1337c51..e8c00cc 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -13,31 +13,30 @@
 #include <linux/module.h>
 #include <linux/nodemask.h>
 #include <linux/sched.h>
+#include <linux/acpi.h>
 
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/dma.h>
-#include <asm/numa.h>
 #include <asm/acpi.h>
 #include <asm/amd_nb.h>
 
+#include "numa_internal.h"
+
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
-struct memnode memnode;
+nodemask_t numa_nodes_parsed __initdata;
 
-s16 apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
-	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
-};
+struct memnode memnode;
 
 static unsigned long __initdata nodemap_addr;
 static unsigned long __initdata nodemap_size;
 
-/*
- * Map cpu index to node index
- */
-DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE);
-EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map);
+static struct numa_meminfo numa_meminfo __initdata;
+
+static int numa_distance_cnt;
+static u8 *numa_distance;
 
 /*
  * Given a shift value, try to populate memnodemap[]
@@ -46,16 +45,15 @@ EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map);
  * 0 if memnodmap[] too small (of shift too small)
  * -1 if node overlap or lost ram (shift too big)
  */
-static int __init populate_memnodemap(const struct bootnode *nodes,
-				      int numnodes, int shift, int *nodeids)
+static int __init populate_memnodemap(const struct numa_meminfo *mi, int shift)
 {
 	unsigned long addr, end;
 	int i, res = -1;
 
 	memset(memnodemap, 0xff, sizeof(s16)*memnodemapsize);
-	for (i = 0; i < numnodes; i++) {
-		addr = nodes[i].start;
-		end = nodes[i].end;
+	for (i = 0; i < mi->nr_blks; i++) {
+		addr = mi->blk[i].start;
+		end = mi->blk[i].end;
 		if (addr >= end)
 			continue;
 		if ((end >> shift) >= memnodemapsize)
@@ -63,12 +61,7 @@ static int __init populate_memnodemap(const struct bootnode *nodes,
 		do {
 			if (memnodemap[addr >> shift] != NUMA_NO_NODE)
 				return -1;
-
-			if (!nodeids)
-				memnodemap[addr >> shift] = i;
-			else
-				memnodemap[addr >> shift] = nodeids[i];
-
+			memnodemap[addr >> shift] = mi->blk[i].nid;
 			addr += (1UL << shift);
 		} while (addr < end);
 		res = 1;
@@ -86,7 +79,7 @@ static int __init allocate_cachealigned_memnodemap(void)
 
 	addr = 0x8000;
 	nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
-	nodemap_addr = memblock_find_in_range(addr, max_pfn<<PAGE_SHIFT,
+	nodemap_addr = memblock_find_in_range(addr, get_max_mapped(),
 				      nodemap_size, L1_CACHE_BYTES);
 	if (nodemap_addr == MEMBLOCK_ERROR) {
 		printk(KERN_ERR
@@ -106,16 +99,15 @@ static int __init allocate_cachealigned_memnodemap(void)
  * The LSB of all start and end addresses in the node map is the value of the
  * maximum possible shift.
  */
-static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
-					 int numnodes)
+static int __init extract_lsb_from_nodes(const struct numa_meminfo *mi)
 {
 	int i, nodes_used = 0;
 	unsigned long start, end;
 	unsigned long bitfield = 0, memtop = 0;
 
-	for (i = 0; i < numnodes; i++) {
-		start = nodes[i].start;
-		end = nodes[i].end;
+	for (i = 0; i < mi->nr_blks; i++) {
+		start = mi->blk[i].start;
+		end = mi->blk[i].end;
 		if (start >= end)
 			continue;
 		bitfield |= start;
@@ -131,18 +123,17 @@ static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
 	return i;
 }
 
-int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
-			      int *nodeids)
+static int __init compute_hash_shift(const struct numa_meminfo *mi)
 {
 	int shift;
 
-	shift = extract_lsb_from_nodes(nodes, numnodes);
+	shift = extract_lsb_from_nodes(mi);
 	if (allocate_cachealigned_memnodemap())
 		return -1;
 	printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
 		shift);
 
-	if (populate_memnodemap(nodes, numnodes, shift, nodeids) != 1) {
+	if (populate_memnodemap(mi, shift) != 1) {
 		printk(KERN_INFO "Your memory is not aligned you need to "
 		       "rebuild your kernel with a bigger NODEMAPSIZE "
 		       "shift=%d\n", shift);
@@ -188,6 +179,63 @@ static void * __init early_node_mem(int nodeid, unsigned long start,
 	return NULL;
 }
 
+static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
+				     struct numa_meminfo *mi)
+{
+	/* ignore zero length blks */
+	if (start == end)
+		return 0;
+
+	/* whine about and ignore invalid blks */
+	if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
+		pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
+			   nid, start, end);
+		return 0;
+	}
+
+	if (mi->nr_blks >= NR_NODE_MEMBLKS) {
+		pr_err("NUMA: too many memblk ranges\n");
+		return -EINVAL;
+	}
+
+	mi->blk[mi->nr_blks].start = start;
+	mi->blk[mi->nr_blks].end = end;
+	mi->blk[mi->nr_blks].nid = nid;
+	mi->nr_blks++;
+	return 0;
+}
+
+/**
+ * numa_remove_memblk_from - Remove one numa_memblk from a numa_meminfo
+ * @idx: Index of memblk to remove
+ * @mi: numa_meminfo to remove memblk from
+ *
+ * Remove @idx'th numa_memblk from @mi by shifting @mi->blk[] and
+ * decrementing @mi->nr_blks.
+ */
+void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
+{
+	mi->nr_blks--;
+	memmove(&mi->blk[idx], &mi->blk[idx + 1],
+		(mi->nr_blks - idx) * sizeof(mi->blk[0]));
+}
+
+/**
+ * numa_add_memblk - Add one numa_memblk to numa_meminfo
+ * @nid: NUMA node ID of the new memblk
+ * @start: Start address of the new memblk
+ * @end: End address of the new memblk
+ *
+ * Add a new memblk to the default numa_meminfo.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init numa_add_memblk(int nid, u64 start, u64 end)
+{
+	return numa_add_memblk_to(nid, start, end, &numa_meminfo);
+}
+
 /* Initialize bootmem allocator for a node */
 void __init
 setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
@@ -234,692 +282,386 @@ setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 	node_set_online(nodeid);
 }
 
-/*
- * There are unfortunately some poorly designed mainboards around that
- * only connect memory to a single CPU. This breaks the 1:1 cpu->node
- * mapping. To avoid this fill in the mapping for all possible CPUs,
- * as the number of CPUs is not known yet. We round robin the existing
- * nodes.
+/**
+ * numa_cleanup_meminfo - Cleanup a numa_meminfo
+ * @mi: numa_meminfo to clean up
+ *
+ * Sanitize @mi by merging and removing unncessary memblks.  Also check for
+ * conflicts and clear unused memblks.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
-void __init numa_init_array(void)
+int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 {
-	int rr, i;
+	const u64 low = 0;
+	const u64 high = (u64)max_pfn << PAGE_SHIFT;
+	int i, j, k;
 
-	rr = first_node(node_online_map);
-	for (i = 0; i < nr_cpu_ids; i++) {
-		if (early_cpu_to_node(i) != NUMA_NO_NODE)
-			continue;
-		numa_set_node(i, rr);
-		rr = next_node(rr, node_online_map);
-		if (rr == MAX_NUMNODES)
-			rr = first_node(node_online_map);
-	}
-}
-
-#ifdef CONFIG_NUMA_EMU
-/* Numa emulation */
-static struct bootnode nodes[MAX_NUMNODES] __initdata;
-static struct bootnode physnodes[MAX_NUMNODES] __cpuinitdata;
-static char *cmdline __initdata;
+	for (i = 0; i < mi->nr_blks; i++) {
+		struct numa_memblk *bi = &mi->blk[i];
 
-void __init numa_emu_cmdline(char *str)
-{
-	cmdline = str;
-}
+		/* make sure all blocks are inside the limits */
+		bi->start = max(bi->start, low);
+		bi->end = min(bi->end, high);
 
-static int __init setup_physnodes(unsigned long start, unsigned long end,
-					int acpi, int amd)
-{
-	int ret = 0;
-	int i;
-
-	memset(physnodes, 0, sizeof(physnodes));
-#ifdef CONFIG_ACPI_NUMA
-	if (acpi)
-		acpi_get_nodes(physnodes, start, end);
-#endif
-#ifdef CONFIG_AMD_NUMA
-	if (amd)
-		amd_get_nodes(physnodes);
-#endif
-	/*
-	 * Basic sanity checking on the physical node map: there may be errors
-	 * if the SRAT or AMD code incorrectly reported the topology or the mem=
-	 * kernel parameter is used.
-	 */
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (physnodes[i].start == physnodes[i].end)
-			continue;
-		if (physnodes[i].start > end) {
-			physnodes[i].end = physnodes[i].start;
-			continue;
-		}
-		if (physnodes[i].end < start) {
-			physnodes[i].start = physnodes[i].end;
+		/* and there's no empty block */
+		if (bi->start == bi->end) {
+			numa_remove_memblk_from(i--, mi);
 			continue;
 		}
-		if (physnodes[i].start < start)
-			physnodes[i].start = start;
-		if (physnodes[i].end > end)
-			physnodes[i].end = end;
-		ret++;
-	}
 
-	/*
-	 * If no physical topology was detected, a single node is faked to cover
-	 * the entire address space.
-	 */
-	if (!ret) {
-		physnodes[ret].start = start;
-		physnodes[ret].end = end;
-		ret = 1;
-	}
-	return ret;
-}
-
-static void __init fake_physnodes(int acpi, int amd, int nr_nodes)
-{
-	int i;
-
-	BUG_ON(acpi && amd);
-#ifdef CONFIG_ACPI_NUMA
-	if (acpi)
-		acpi_fake_nodes(nodes, nr_nodes);
-#endif
-#ifdef CONFIG_AMD_NUMA
-	if (amd)
-		amd_fake_nodes(nodes, nr_nodes);
-#endif
-	if (!acpi && !amd)
-		for (i = 0; i < nr_cpu_ids; i++)
-			numa_set_node(i, 0);
-}
-
-/*
- * Setups up nid to range from addr to addr + size.  If the end
- * boundary is greater than max_addr, then max_addr is used instead.
- * The return value is 0 if there is additional memory left for
- * allocation past addr and -1 otherwise.  addr is adjusted to be at
- * the end of the node.
- */
-static int __init setup_node_range(int nid, u64 *addr, u64 size, u64 max_addr)
-{
-	int ret = 0;
-	nodes[nid].start = *addr;
-	*addr += size;
-	if (*addr >= max_addr) {
-		*addr = max_addr;
-		ret = -1;
-	}
-	nodes[nid].end = *addr;
-	node_set(nid, node_possible_map);
-	printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
-	       nodes[nid].start, nodes[nid].end,
-	       (nodes[nid].end - nodes[nid].start) >> 20);
-	return ret;
-}
-
-/*
- * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr
- * to max_addr.  The return value is the number of nodes allocated.
- */
-static int __init split_nodes_interleave(u64 addr, u64 max_addr, int nr_nodes)
-{
-	nodemask_t physnode_mask = NODE_MASK_NONE;
-	u64 size;
-	int big;
-	int ret = 0;
-	int i;
-
-	if (nr_nodes <= 0)
-		return -1;
-	if (nr_nodes > MAX_NUMNODES) {
-		pr_info("numa=fake=%d too large, reducing to %d\n",
-			nr_nodes, MAX_NUMNODES);
-		nr_nodes = MAX_NUMNODES;
-	}
-
-	size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
-	/*
-	 * Calculate the number of big nodes that can be allocated as a result
-	 * of consolidating the remainder.
-	 */
-	big = ((size & ~FAKE_NODE_MIN_HASH_MASK) * nr_nodes) /
-		FAKE_NODE_MIN_SIZE;
-
-	size &= FAKE_NODE_MIN_HASH_MASK;
-	if (!size) {
-		pr_err("Not enough memory for each node.  "
-			"NUMA emulation disabled.\n");
-		return -1;
-	}
-
-	for (i = 0; i < MAX_NUMNODES; i++)
-		if (physnodes[i].start != physnodes[i].end)
-			node_set(i, physnode_mask);
-
-	/*
-	 * Continue to fill physical nodes with fake nodes until there is no
-	 * memory left on any of them.
-	 */
-	while (nodes_weight(physnode_mask)) {
-		for_each_node_mask(i, physnode_mask) {
-			u64 end = physnodes[i].start + size;
-			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
-
-			if (ret < big)
-				end += FAKE_NODE_MIN_SIZE;
+		for (j = i + 1; j < mi->nr_blks; j++) {
+			struct numa_memblk *bj = &mi->blk[j];
+			unsigned long start, end;
 
 			/*
-			 * Continue to add memory to this fake node if its
-			 * non-reserved memory is less than the per-node size.
+			 * See whether there are overlapping blocks.  Whine
+			 * about but allow overlaps of the same nid.  They
+			 * will be merged below.
 			 */
-			while (end - physnodes[i].start -
-				memblock_x86_hole_size(physnodes[i].start, end) < size) {
-				end += FAKE_NODE_MIN_SIZE;
-				if (end > physnodes[i].end) {
-					end = physnodes[i].end;
-					break;
+			if (bi->end > bj->start && bi->start < bj->end) {
+				if (bi->nid != bj->nid) {
+					pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
+					       bi->nid, bi->start, bi->end,
+					       bj->nid, bj->start, bj->end);
+					return -EINVAL;
 				}
+				pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
+					   bi->nid, bi->start, bi->end,
+					   bj->start, bj->end);
 			}
 
 			/*
-			 * If there won't be at least FAKE_NODE_MIN_SIZE of
-			 * non-reserved memory in ZONE_DMA32 for the next node,
-			 * this one must extend to the boundary.
-			 */
-			if (end < dma32_end && dma32_end - end -
-			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
-				end = dma32_end;
-
-			/*
-			 * If there won't be enough non-reserved memory for the
-			 * next node, this one must extend to the end of the
-			 * physical node.
+			 * Join together blocks on the same node, holes
+			 * between which don't overlap with memory on other
+			 * nodes.
 			 */
-			if (physnodes[i].end - end -
-			    memblock_x86_hole_size(end, physnodes[i].end) < size)
-				end = physnodes[i].end;
-
-			/*
-			 * Avoid allocating more nodes than requested, which can
-			 * happen as a result of rounding down each node's size
-			 * to FAKE_NODE_MIN_SIZE.
-			 */
-			if (nodes_weight(physnode_mask) + ret >= nr_nodes)
-				end = physnodes[i].end;
-
-			if (setup_node_range(ret++, &physnodes[i].start,
-						end - physnodes[i].start,
-						physnodes[i].end) < 0)
-				node_clear(i, physnode_mask);
+			if (bi->nid != bj->nid)
+				continue;
+			start = max(min(bi->start, bj->start), low);
+			end = min(max(bi->end, bj->end), high);
+			for (k = 0; k < mi->nr_blks; k++) {
+				struct numa_memblk *bk = &mi->blk[k];
+
+				if (bi->nid == bk->nid)
+					continue;
+				if (start < bk->end && end > bk->start)
+					break;
+			}
+			if (k < mi->nr_blks)
+				continue;
+			printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
+			       bi->nid, bi->start, bi->end, bj->start, bj->end,
+			       start, end);
+			bi->start = start;
+			bi->end = end;
+			numa_remove_memblk_from(j--, mi);
 		}
 	}
-	return ret;
-}
-
-/*
- * Returns the end address of a node so that there is at least `size' amount of
- * non-reserved memory or `max_addr' is reached.
- */
-static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
-{
-	u64 end = start + size;
 
-	while (end - start - memblock_x86_hole_size(start, end) < size) {
-		end += FAKE_NODE_MIN_SIZE;
-		if (end > max_addr) {
-			end = max_addr;
-			break;
-		}
+	for (i = mi->nr_blks; i < ARRAY_SIZE(mi->blk); i++) {
+		mi->blk[i].start = mi->blk[i].end = 0;
+		mi->blk[i].nid = NUMA_NO_NODE;
 	}
-	return end;
+
+	return 0;
 }
 
 /*
- * Sets up fake nodes of `size' interleaved over physical nodes ranging from
- * `addr' to `max_addr'.  The return value is the number of nodes allocated.
+ * Set nodes, which have memory in @mi, in *@nodemask.
  */
-static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
+static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask,
+					      const struct numa_meminfo *mi)
 {
-	nodemask_t physnode_mask = NODE_MASK_NONE;
-	u64 min_size;
-	int ret = 0;
 	int i;
 
-	if (!size)
-		return -1;
-	/*
-	 * The limit on emulated nodes is MAX_NUMNODES, so the size per node is
-	 * increased accordingly if the requested size is too small.  This
-	 * creates a uniform distribution of node sizes across the entire
-	 * machine (but not necessarily over physical nodes).
-	 */
-	min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
-						MAX_NUMNODES;
-	min_size = max(min_size, FAKE_NODE_MIN_SIZE);
-	if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
-		min_size = (min_size + FAKE_NODE_MIN_SIZE) &
-						FAKE_NODE_MIN_HASH_MASK;
-	if (size < min_size) {
-		pr_err("Fake node size %LuMB too small, increasing to %LuMB\n",
-			size >> 20, min_size >> 20);
-		size = min_size;
-	}
-	size &= FAKE_NODE_MIN_HASH_MASK;
-
-	for (i = 0; i < MAX_NUMNODES; i++)
-		if (physnodes[i].start != physnodes[i].end)
-			node_set(i, physnode_mask);
-	/*
-	 * Fill physical nodes with fake nodes of size until there is no memory
-	 * left on any of them.
-	 */
-	while (nodes_weight(physnode_mask)) {
-		for_each_node_mask(i, physnode_mask) {
-			u64 dma32_end = MAX_DMA32_PFN << PAGE_SHIFT;
-			u64 end;
-
-			end = find_end_of_node(physnodes[i].start,
-						physnodes[i].end, size);
-			/*
-			 * If there won't be at least FAKE_NODE_MIN_SIZE of
-			 * non-reserved memory in ZONE_DMA32 for the next node,
-			 * this one must extend to the boundary.
-			 */
-			if (end < dma32_end && dma32_end - end -
-			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
-				end = dma32_end;
+	for (i = 0; i < ARRAY_SIZE(mi->blk); i++)
+		if (mi->blk[i].start != mi->blk[i].end &&
+		    mi->blk[i].nid != NUMA_NO_NODE)
+			node_set(mi->blk[i].nid, *nodemask);
+}
 
-			/*
-			 * If there won't be enough non-reserved memory for the
-			 * next node, this one must extend to the end of the
-			 * physical node.
-			 */
-			if (physnodes[i].end - end -
-			    memblock_x86_hole_size(end, physnodes[i].end) < size)
-				end = physnodes[i].end;
+/**
+ * numa_reset_distance - Reset NUMA distance table
+ *
+ * The current table is freed.  The next numa_set_distance() call will
+ * create a new one.
+ */
+void __init numa_reset_distance(void)
+{
+	size_t size = numa_distance_cnt * numa_distance_cnt * sizeof(numa_distance[0]);
 
-			/*
-			 * Setup the fake node that will be allocated as bootmem
-			 * later.  If setup_node_range() returns non-zero, there
-			 * is no more memory available on this physical node.
-			 */
-			if (setup_node_range(ret++, &physnodes[i].start,
-						end - physnodes[i].start,
-						physnodes[i].end) < 0)
-				node_clear(i, physnode_mask);
-		}
-	}
-	return ret;
+	/* numa_distance could be 1LU marking allocation failure, test cnt */
+	if (numa_distance_cnt)
+		memblock_x86_free_range(__pa(numa_distance),
+					__pa(numa_distance) + size);
+	numa_distance_cnt = 0;
+	numa_distance = NULL;	/* enable table creation */
 }
 
-/*
- * Sets up the system RAM area from start_pfn to last_pfn according to the
- * numa=fake command-line option.
- */
-static int __init numa_emulation(unsigned long start_pfn,
-			unsigned long last_pfn, int acpi, int amd)
+static int __init numa_alloc_distance(void)
 {
-	u64 addr = start_pfn << PAGE_SHIFT;
-	u64 max_addr = last_pfn << PAGE_SHIFT;
-	int num_nodes;
-	int i;
+	nodemask_t nodes_parsed;
+	size_t size;
+	int i, j, cnt = 0;
+	u64 phys;
 
-	/*
-	 * If the numa=fake command-line contains a 'M' or 'G', it represents
-	 * the fixed node size.  Otherwise, if it is just a single number N,
-	 * split the system RAM into N fake nodes.
-	 */
-	if (strchr(cmdline, 'M') || strchr(cmdline, 'G')) {
-		u64 size;
+	/* size the new table and allocate it */
+	nodes_parsed = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&nodes_parsed, &numa_meminfo);
 
-		size = memparse(cmdline, &cmdline);
-		num_nodes = split_nodes_size_interleave(addr, max_addr, size);
-	} else {
-		unsigned long n;
+	for_each_node_mask(i, nodes_parsed)
+		cnt = i;
+	cnt++;
+	size = cnt * cnt * sizeof(numa_distance[0]);
 
-		n = simple_strtoul(cmdline, NULL, 0);
-		num_nodes = split_nodes_interleave(addr, max_addr, n);
+	phys = memblock_find_in_range(0, (u64)max_pfn_mapped << PAGE_SHIFT,
+				      size, PAGE_SIZE);
+	if (phys == MEMBLOCK_ERROR) {
+		pr_warning("NUMA: Warning: can't allocate distance table!\n");
+		/* don't retry until explicitly reset */
+		numa_distance = (void *)1LU;
+		return -ENOMEM;
 	}
+	memblock_x86_reserve_range(phys, phys + size, "NUMA DIST");
 
-	if (num_nodes < 0)
-		return num_nodes;
-	memnode_shift = compute_hash_shift(nodes, num_nodes, NULL);
-	if (memnode_shift < 0) {
-		memnode_shift = 0;
-		printk(KERN_ERR "No NUMA hash function found.  NUMA emulation "
-		       "disabled.\n");
-		return -1;
-	}
+	numa_distance = __va(phys);
+	numa_distance_cnt = cnt;
+
+	/* fill with the default distances */
+	for (i = 0; i < cnt; i++)
+		for (j = 0; j < cnt; j++)
+			numa_distance[i * cnt + j] = i == j ?
+				LOCAL_DISTANCE : REMOTE_DISTANCE;
+	printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt);
 
-	/*
-	 * We need to vacate all active ranges that may have been registered for
-	 * the e820 memory map.
-	 */
-	remove_all_active_ranges();
-	for_each_node_mask(i, node_possible_map) {
-		memblock_x86_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
-						nodes[i].end >> PAGE_SHIFT);
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	}
-	setup_physnodes(addr, max_addr, acpi, amd);
-	fake_physnodes(acpi, amd, num_nodes);
-	numa_init_array();
 	return 0;
 }
-#endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
-				int acpi, int amd)
+/**
+ * numa_set_distance - Set NUMA distance from one NUMA to another
+ * @from: the 'from' node to set distance
+ * @to: the 'to'  node to set distance
+ * @distance: NUMA distance
+ *
+ * Set the distance from node @from to @to to @distance.  If distance table
+ * doesn't exist, one which is large enough to accommodate all the currently
+ * known nodes will be created.
+ *
+ * If such table cannot be allocated, a warning is printed and further
+ * calls are ignored until the distance table is reset with
+ * numa_reset_distance().
+ *
+ * If @from or @to is higher than the highest known node at the time of
+ * table creation or @distance doesn't make sense, the call is ignored.
+ * This is to allow simplification of specific NUMA config implementations.
+ */
+void __init numa_set_distance(int from, int to, int distance)
 {
-	int i;
-
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-
-#ifdef CONFIG_NUMA_EMU
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
-	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd))
+	if (!numa_distance && numa_alloc_distance() < 0)
 		return;
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
 
-#ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes(start_pfn << PAGE_SHIFT,
-						  last_pfn << PAGE_SHIFT))
+	if (from >= numa_distance_cnt || to >= numa_distance_cnt) {
+		printk_once(KERN_DEBUG "NUMA: Debug: distance out of bound, from=%d to=%d distance=%d\n",
+			    from, to, distance);
 		return;
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
+	}
 
-#ifdef CONFIG_AMD_NUMA
-	if (!numa_off && amd && !amd_scan_nodes())
+	if ((u8)distance != distance ||
+	    (from == to && distance != LOCAL_DISTANCE)) {
+		pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
+			     from, to, distance);
 		return;
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
-	printk(KERN_INFO "%s\n",
-	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
+	}
 
-	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
-	       start_pfn << PAGE_SHIFT,
-	       last_pfn << PAGE_SHIFT);
-	/* setup dummy node covering all memory */
-	memnode_shift = 63;
-	memnodemap = memnode.embedded_map;
-	memnodemap[0] = 0;
-	node_set_online(0);
-	node_set(0, node_possible_map);
-	for (i = 0; i < nr_cpu_ids; i++)
-		numa_set_node(i, 0);
-	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
-	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
+	numa_distance[from * numa_distance_cnt + to] = distance;
 }
 
-unsigned long __init numa_free_all_bootmem(void)
+int __node_distance(int from, int to)
 {
-	unsigned long pages = 0;
-	int i;
+	if (from >= numa_distance_cnt || to >= numa_distance_cnt)
+		return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
+	return numa_distance[from * numa_distance_cnt + to];
+}
+EXPORT_SYMBOL(__node_distance);
 
-	for_each_online_node(i)
-		pages += free_all_bootmem_node(NODE_DATA(i));
+/*
+ * Sanity check to catch more bad NUMA configurations (they are amazingly
+ * common).  Make sure the nodes cover all memory.
+ */
+static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
+{
+	unsigned long numaram, e820ram;
+	int i;
 
-	pages += free_all_memory_core_early(MAX_NUMNODES);
+	numaram = 0;
+	for (i = 0; i < mi->nr_blks; i++) {
+		unsigned long s = mi->blk[i].start >> PAGE_SHIFT;
+		unsigned long e = mi->blk[i].end >> PAGE_SHIFT;
+		numaram += e - s;
+		numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
+		if ((long)numaram < 0)
+			numaram = 0;
+	}
 
-	return pages;
+	e820ram = max_pfn - (memblock_x86_hole_size(0,
+					max_pfn << PAGE_SHIFT) >> PAGE_SHIFT);
+	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
+	if ((long)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
+		printk(KERN_ERR "NUMA: nodes only cover %luMB of your %luMB e820 RAM. Not used.\n",
+		       (numaram << PAGE_SHIFT) >> 20,
+		       (e820ram << PAGE_SHIFT) >> 20);
+		return false;
+	}
+	return true;
 }
 
-#ifdef CONFIG_NUMA
-
-static __init int find_near_online_node(int node)
+static int __init numa_register_memblks(struct numa_meminfo *mi)
 {
-	int n, val;
-	int min_val = INT_MAX;
-	int best_node = -1;
+	int i, nid;
 
-	for_each_online_node(n) {
-		val = node_distance(node, n);
+	/* Account for nodes with cpus and no memory */
+	node_possible_map = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&node_possible_map, mi);
+	if (WARN_ON(nodes_empty(node_possible_map)))
+		return -EINVAL;
 
-		if (val < min_val) {
-			min_val = val;
-			best_node = n;
+	memnode_shift = compute_hash_shift(mi);
+	if (memnode_shift < 0) {
+		printk(KERN_ERR "NUMA: No NUMA node hash function found. Contact maintainer\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < mi->nr_blks; i++)
+		memblock_x86_register_active_regions(mi->blk[i].nid,
+					mi->blk[i].start >> PAGE_SHIFT,
+					mi->blk[i].end >> PAGE_SHIFT);
+
+	/* for out of order entries */
+	sort_node_map();
+	if (!numa_meminfo_cover_memory(mi))
+		return -EINVAL;
+
+	/* Finally register nodes. */
+	for_each_node_mask(nid, node_possible_map) {
+		u64 start = (u64)max_pfn << PAGE_SHIFT;
+		u64 end = 0;
+
+		for (i = 0; i < mi->nr_blks; i++) {
+			if (nid != mi->blk[i].nid)
+				continue;
+			start = min(mi->blk[i].start, start);
+			end = max(mi->blk[i].end, end);
 		}
+
+		if (start < end)
+			setup_node_bootmem(nid, start, end);
 	}
 
-	return best_node;
+	return 0;
 }
 
-/*
- * Setup early cpu_to_node.
+/**
+ * dummy_numma_init - Fallback dummy NUMA init
  *
- * Populate cpu_to_node[] only if x86_cpu_to_apicid[],
- * and apicid_to_node[] tables have valid entries for a CPU.
- * This means we skip cpu_to_node[] initialisation for NUMA
- * emulation and faking node case (when running a kernel compiled
- * for NUMA on a non NUMA box), which is OK as cpu_to_node[]
- * is already initialized in a round robin manner at numa_init_array,
- * prior to this call, and this initialization is good enough
- * for the fake NUMA cases.
+ * Used if there's no underlying NUMA architecture, NUMA initialization
+ * fails, or NUMA is disabled on the command line.
  *
- * Called before the per_cpu areas are setup.
+ * Must online at least one node and add memory blocks that cover all
+ * allowed memory.  This function must not fail.
  */
-void __init init_cpu_to_node(void)
+static int __init dummy_numa_init(void)
 {
-	int cpu;
-	u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
-
-	BUG_ON(cpu_to_apicid == NULL);
+	printk(KERN_INFO "%s\n",
+	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
+	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
+	       0LU, max_pfn << PAGE_SHIFT);
 
-	for_each_possible_cpu(cpu) {
-		int node;
-		u16 apicid = cpu_to_apicid[cpu];
+	node_set(0, numa_nodes_parsed);
+	numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
 
-		if (apicid == BAD_APICID)
-			continue;
-		node = apicid_to_node[apicid];
-		if (node == NUMA_NO_NODE)
-			continue;
-		if (!node_online(node))
-			node = find_near_online_node(node);
-		numa_set_node(cpu, node);
-	}
+	return 0;
 }
-#endif
 
-
-void __cpuinit numa_set_node(int cpu, int node)
+static int __init numa_init(int (*init_func)(void))
 {
-	int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map);
-
-	/* early setting, no percpu area yet */
-	if (cpu_to_node_map) {
-		cpu_to_node_map[cpu] = node;
-		return;
-	}
-
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
-	if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
-		printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu);
-		dump_stack();
-		return;
-	}
-#endif
-	per_cpu(x86_cpu_to_node_map, cpu) = node;
+	int i;
+	int ret;
 
-	if (node != NUMA_NO_NODE)
-		set_cpu_numa_node(cpu, node);
-}
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		set_apicid_to_node(i, NUMA_NO_NODE);
 
-void __cpuinit numa_clear_node(int cpu)
-{
-	numa_set_node(cpu, NUMA_NO_NODE);
-}
-
-#ifndef CONFIG_DEBUG_PER_CPU_MAPS
+	nodes_clear(numa_nodes_parsed);
+	nodes_clear(node_possible_map);
+	nodes_clear(node_online_map);
+	memset(&numa_meminfo, 0, sizeof(numa_meminfo));
+	remove_all_active_ranges();
+	numa_reset_distance();
 
-#ifndef CONFIG_NUMA_EMU
-void __cpuinit numa_add_cpu(int cpu)
-{
-	cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
-}
+	ret = init_func();
+	if (ret < 0)
+		return ret;
+	ret = numa_cleanup_meminfo(&numa_meminfo);
+	if (ret < 0)
+		return ret;
 
-void __cpuinit numa_remove_cpu(int cpu)
-{
-	cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
-}
-#else
-void __cpuinit numa_add_cpu(int cpu)
-{
-	unsigned long addr;
-	u16 apicid;
-	int physnid;
-	int nid = NUMA_NO_NODE;
+	numa_emulation(&numa_meminfo, numa_distance_cnt);
 
-	nid = early_cpu_to_node(cpu);
-	BUG_ON(nid == NUMA_NO_NODE || !node_online(nid));
+	ret = numa_register_memblks(&numa_meminfo);
+	if (ret < 0)
+		return ret;
 
-	/*
-	 * Use the starting address of the emulated node to find which physical
-	 * node it is allocated on.
-	 */
-	addr = node_start_pfn(nid) << PAGE_SHIFT;
-	for (physnid = 0; physnid < MAX_NUMNODES; physnid++)
-		if (addr >= physnodes[physnid].start &&
-		    addr < physnodes[physnid].end)
-			break;
+	for (i = 0; i < nr_cpu_ids; i++) {
+		int nid = early_cpu_to_node(i);
 
-	/*
-	 * Map the cpu to each emulated node that is allocated on the physical
-	 * node of the cpu's apic id.
-	 */
-	for_each_online_node(nid) {
-		addr = node_start_pfn(nid) << PAGE_SHIFT;
-		if (addr >= physnodes[physnid].start &&
-		    addr < physnodes[physnid].end)
-			cpumask_set_cpu(cpu, node_to_cpumask_map[nid]);
+		if (nid == NUMA_NO_NODE)
+			continue;
+		if (!node_online(nid))
+			numa_clear_node(i);
 	}
+	numa_init_array();
+	return 0;
 }
 
-void __cpuinit numa_remove_cpu(int cpu)
+void __init initmem_init(void)
 {
-	int i;
+	int ret;
 
-	for_each_online_node(i)
-		cpumask_clear_cpu(cpu, node_to_cpumask_map[i]);
-}
-#endif /* !CONFIG_NUMA_EMU */
-
-#else /* CONFIG_DEBUG_PER_CPU_MAPS */
-static struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable)
-{
-	int node = early_cpu_to_node(cpu);
-	struct cpumask *mask;
-	char buf[64];
-
-	mask = node_to_cpumask_map[node];
-	if (!mask) {
-		pr_err("node_to_cpumask_map[%i] NULL\n", node);
-		dump_stack();
-		return NULL;
+	if (!numa_off) {
+#ifdef CONFIG_ACPI_NUMA
+		ret = numa_init(x86_acpi_numa_init);
+		if (!ret)
+			return;
+#endif
+#ifdef CONFIG_AMD_NUMA
+		ret = numa_init(amd_numa_init);
+		if (!ret)
+			return;
+#endif
 	}
 
-	cpulist_scnprintf(buf, sizeof(buf), mask);
-	printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
-		enable ? "numa_add_cpu" : "numa_remove_cpu",
-		cpu, node, buf);
-	return mask;
+	numa_init(dummy_numa_init);
 }
 
-/*
- * --------- debug versions of the numa functions ---------
- */
-#ifndef CONFIG_NUMA_EMU
-static void __cpuinit numa_set_cpumask(int cpu, int enable)
-{
-	struct cpumask *mask;
-
-	mask = debug_cpumask_set_cpu(cpu, enable);
-	if (!mask)
-		return;
-
-	if (enable)
-		cpumask_set_cpu(cpu, mask);
-	else
-		cpumask_clear_cpu(cpu, mask);
-}
-#else
-static void __cpuinit numa_set_cpumask(int cpu, int enable)
+unsigned long __init numa_free_all_bootmem(void)
 {
-	int node = early_cpu_to_node(cpu);
-	struct cpumask *mask;
+	unsigned long pages = 0;
 	int i;
 
-	for_each_online_node(i) {
-		unsigned long addr;
-
-		addr = node_start_pfn(i) << PAGE_SHIFT;
-		if (addr < physnodes[node].start ||
-					addr >= physnodes[node].end)
-			continue;
-		mask = debug_cpumask_set_cpu(cpu, enable);
-		if (!mask)
-			return;
-
-		if (enable)
-			cpumask_set_cpu(cpu, mask);
-		else
-			cpumask_clear_cpu(cpu, mask);
-	}
-}
-#endif /* CONFIG_NUMA_EMU */
+	for_each_online_node(i)
+		pages += free_all_bootmem_node(NODE_DATA(i));
 
-void __cpuinit numa_add_cpu(int cpu)
-{
-	numa_set_cpumask(cpu, 1);
-}
+	pages += free_all_memory_core_early(MAX_NUMNODES);
 
-void __cpuinit numa_remove_cpu(int cpu)
-{
-	numa_set_cpumask(cpu, 0);
+	return pages;
 }
 
-int __cpu_to_node(int cpu)
+int __cpuinit numa_cpu_node(int cpu)
 {
-	if (early_per_cpu_ptr(x86_cpu_to_node_map)) {
-		printk(KERN_WARNING
-			"cpu_to_node(%d): usage too early!\n", cpu);
-		dump_stack();
-		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
-	}
-	return per_cpu(x86_cpu_to_node_map, cpu);
-}
-EXPORT_SYMBOL(__cpu_to_node);
+	int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
 
-/*
- * Same function as cpu_to_node() but used if called before the
- * per_cpu areas are setup.
- */
-int early_cpu_to_node(int cpu)
-{
-	if (early_per_cpu_ptr(x86_cpu_to_node_map))
-		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
-
-	if (!cpu_possible(cpu)) {
-		printk(KERN_WARNING
-			"early_cpu_to_node(%d): no per_cpu area!\n", cpu);
-		dump_stack();
-		return NUMA_NO_NODE;
-	}
-	return per_cpu(x86_cpu_to_node_map, cpu);
+	if (apicid != BAD_APICID)
+		return __apicid_to_node[apicid];
+	return NUMA_NO_NODE;
 }
-
-/*
- * --------- end of debug versions of the numa functions ---------
- */
-
-#endif /* CONFIG_DEBUG_PER_CPU_MAPS */
diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c
new file mode 100644
index 0000000..ad091e4
--- /dev/null
+++ b/arch/x86/mm/numa_emulation.c
@@ -0,0 +1,494 @@
+/*
+ * NUMA emulation
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/topology.h>
+#include <linux/memblock.h>
+#include <asm/dma.h>
+
+#include "numa_internal.h"
+
+static int emu_nid_to_phys[MAX_NUMNODES] __cpuinitdata;
+static char *emu_cmdline __initdata;
+
+void __init numa_emu_cmdline(char *str)
+{
+	emu_cmdline = str;
+}
+
+static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi)
+{
+	int i;
+
+	for (i = 0; i < mi->nr_blks; i++)
+		if (mi->blk[i].nid == nid)
+			return i;
+	return -ENOENT;
+}
+
+/*
+ * Sets up nid to range from @start to @end.  The return value is -errno if
+ * something went wrong, 0 otherwise.
+ */
+static int __init emu_setup_memblk(struct numa_meminfo *ei,
+				   struct numa_meminfo *pi,
+				   int nid, int phys_blk, u64 size)
+{
+	struct numa_memblk *eb = &ei->blk[ei->nr_blks];
+	struct numa_memblk *pb = &pi->blk[phys_blk];
+
+	if (ei->nr_blks >= NR_NODE_MEMBLKS) {
+		pr_err("NUMA: Too many emulated memblks, failing emulation\n");
+		return -EINVAL;
+	}
+
+	ei->nr_blks++;
+	eb->start = pb->start;
+	eb->end = pb->start + size;
+	eb->nid = nid;
+
+	if (emu_nid_to_phys[nid] == NUMA_NO_NODE)
+		emu_nid_to_phys[nid] = pb->nid;
+
+	pb->start += size;
+	if (pb->start >= pb->end) {
+		WARN_ON_ONCE(pb->start > pb->end);
+		numa_remove_memblk_from(phys_blk, pi);
+	}
+
+	printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
+	       eb->start, eb->end, (eb->end - eb->start) >> 20);
+	return 0;
+}
+
+/*
+ * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr
+ * to max_addr.  The return value is the number of nodes allocated.
+ */
+static int __init split_nodes_interleave(struct numa_meminfo *ei,
+					 struct numa_meminfo *pi,
+					 u64 addr, u64 max_addr, int nr_nodes)
+{
+	nodemask_t physnode_mask = NODE_MASK_NONE;
+	u64 size;
+	int big;
+	int nid = 0;
+	int i, ret;
+
+	if (nr_nodes <= 0)
+		return -1;
+	if (nr_nodes > MAX_NUMNODES) {
+		pr_info("numa=fake=%d too large, reducing to %d\n",
+			nr_nodes, MAX_NUMNODES);
+		nr_nodes = MAX_NUMNODES;
+	}
+
+	size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
+	/*
+	 * Calculate the number of big nodes that can be allocated as a result
+	 * of consolidating the remainder.
+	 */
+	big = ((size & ~FAKE_NODE_MIN_HASH_MASK) * nr_nodes) /
+		FAKE_NODE_MIN_SIZE;
+
+	size &= FAKE_NODE_MIN_HASH_MASK;
+	if (!size) {
+		pr_err("Not enough memory for each node.  "
+			"NUMA emulation disabled.\n");
+		return -1;
+	}
+
+	for (i = 0; i < pi->nr_blks; i++)
+		node_set(pi->blk[i].nid, physnode_mask);
+
+	/*
+	 * Continue to fill physical nodes with fake nodes until there is no
+	 * memory left on any of them.
+	 */
+	while (nodes_weight(physnode_mask)) {
+		for_each_node_mask(i, physnode_mask) {
+			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
+			u64 start, limit, end;
+			int phys_blk;
+
+			phys_blk = emu_find_memblk_by_nid(i, pi);
+			if (phys_blk < 0) {
+				node_clear(i, physnode_mask);
+				continue;
+			}
+			start = pi->blk[phys_blk].start;
+			limit = pi->blk[phys_blk].end;
+			end = start + size;
+
+			if (nid < big)
+				end += FAKE_NODE_MIN_SIZE;
+
+			/*
+			 * Continue to add memory to this fake node if its
+			 * non-reserved memory is less than the per-node size.
+			 */
+			while (end - start -
+			       memblock_x86_hole_size(start, end) < size) {
+				end += FAKE_NODE_MIN_SIZE;
+				if (end > limit) {
+					end = limit;
+					break;
+				}
+			}
+
+			/*
+			 * If there won't be at least FAKE_NODE_MIN_SIZE of
+			 * non-reserved memory in ZONE_DMA32 for the next node,
+			 * this one must extend to the boundary.
+			 */
+			if (end < dma32_end && dma32_end - end -
+			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+				end = dma32_end;
+
+			/*
+			 * If there won't be enough non-reserved memory for the
+			 * next node, this one must extend to the end of the
+			 * physical node.
+			 */
+			if (limit - end -
+			    memblock_x86_hole_size(end, limit) < size)
+				end = limit;
+
+			ret = emu_setup_memblk(ei, pi, nid++ % nr_nodes,
+					       phys_blk,
+					       min(end, limit) - start);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Returns the end address of a node so that there is at least `size' amount of
+ * non-reserved memory or `max_addr' is reached.
+ */
+static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
+{
+	u64 end = start + size;
+
+	while (end - start - memblock_x86_hole_size(start, end) < size) {
+		end += FAKE_NODE_MIN_SIZE;
+		if (end > max_addr) {
+			end = max_addr;
+			break;
+		}
+	}
+	return end;
+}
+
+/*
+ * Sets up fake nodes of `size' interleaved over physical nodes ranging from
+ * `addr' to `max_addr'.  The return value is the number of nodes allocated.
+ */
+static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
+					      struct numa_meminfo *pi,
+					      u64 addr, u64 max_addr, u64 size)
+{
+	nodemask_t physnode_mask = NODE_MASK_NONE;
+	u64 min_size;
+	int nid = 0;
+	int i, ret;
+
+	if (!size)
+		return -1;
+	/*
+	 * The limit on emulated nodes is MAX_NUMNODES, so the size per node is
+	 * increased accordingly if the requested size is too small.  This
+	 * creates a uniform distribution of node sizes across the entire
+	 * machine (but not necessarily over physical nodes).
+	 */
+	min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
+						MAX_NUMNODES;
+	min_size = max(min_size, FAKE_NODE_MIN_SIZE);
+	if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
+		min_size = (min_size + FAKE_NODE_MIN_SIZE) &
+						FAKE_NODE_MIN_HASH_MASK;
+	if (size < min_size) {
+		pr_err("Fake node size %LuMB too small, increasing to %LuMB\n",
+			size >> 20, min_size >> 20);
+		size = min_size;
+	}
+	size &= FAKE_NODE_MIN_HASH_MASK;
+
+	for (i = 0; i < pi->nr_blks; i++)
+		node_set(pi->blk[i].nid, physnode_mask);
+
+	/*
+	 * Fill physical nodes with fake nodes of size until there is no memory
+	 * left on any of them.
+	 */
+	while (nodes_weight(physnode_mask)) {
+		for_each_node_mask(i, physnode_mask) {
+			u64 dma32_end = MAX_DMA32_PFN << PAGE_SHIFT;
+			u64 start, limit, end;
+			int phys_blk;
+
+			phys_blk = emu_find_memblk_by_nid(i, pi);
+			if (phys_blk < 0) {
+				node_clear(i, physnode_mask);
+				continue;
+			}
+			start = pi->blk[phys_blk].start;
+			limit = pi->blk[phys_blk].end;
+
+			end = find_end_of_node(start, limit, size);
+			/*
+			 * If there won't be at least FAKE_NODE_MIN_SIZE of
+			 * non-reserved memory in ZONE_DMA32 for the next node,
+			 * this one must extend to the boundary.
+			 */
+			if (end < dma32_end && dma32_end - end -
+			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+				end = dma32_end;
+
+			/*
+			 * If there won't be enough non-reserved memory for the
+			 * next node, this one must extend to the end of the
+			 * physical node.
+			 */
+			if (limit - end -
+			    memblock_x86_hole_size(end, limit) < size)
+				end = limit;
+
+			ret = emu_setup_memblk(ei, pi, nid++ % MAX_NUMNODES,
+					       phys_blk,
+					       min(end, limit) - start);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+/**
+ * numa_emulation - Emulate NUMA nodes
+ * @numa_meminfo: NUMA configuration to massage
+ * @numa_dist_cnt: The size of the physical NUMA distance table
+ *
+ * Emulate NUMA nodes according to the numa=fake kernel parameter.
+ * @numa_meminfo contains the physical memory configuration and is modified
+ * to reflect the emulated configuration on success.  @numa_dist_cnt is
+ * used to determine the size of the physical distance table.
+ *
+ * On success, the following modifications are made.
+ *
+ * - @numa_meminfo is updated to reflect the emulated nodes.
+ *
+ * - __apicid_to_node[] is updated such that APIC IDs are mapped to the
+ *   emulated nodes.
+ *
+ * - NUMA distance table is rebuilt to represent distances between emulated
+ *   nodes.  The distances are determined considering how emulated nodes
+ *   are mapped to physical nodes and match the actual distances.
+ *
+ * - emu_nid_to_phys[] reflects how emulated nodes are mapped to physical
+ *   nodes.  This is used by numa_add_cpu() and numa_remove_cpu().
+ *
+ * If emulation is not enabled or fails, emu_nid_to_phys[] is filled with
+ * identity mapping and no other modification is made.
+ */
+void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
+{
+	static struct numa_meminfo ei __initdata;
+	static struct numa_meminfo pi __initdata;
+	const u64 max_addr = max_pfn << PAGE_SHIFT;
+	u8 *phys_dist = NULL;
+	size_t phys_size = numa_dist_cnt * numa_dist_cnt * sizeof(phys_dist[0]);
+	int max_emu_nid, dfl_phys_nid;
+	int i, j, ret;
+
+	if (!emu_cmdline)
+		goto no_emu;
+
+	memset(&ei, 0, sizeof(ei));
+	pi = *numa_meminfo;
+
+	for (i = 0; i < MAX_NUMNODES; i++)
+		emu_nid_to_phys[i] = NUMA_NO_NODE;
+
+	/*
+	 * If the numa=fake command-line contains a 'M' or 'G', it represents
+	 * the fixed node size.  Otherwise, if it is just a single number N,
+	 * split the system RAM into N fake nodes.
+	 */
+	if (strchr(emu_cmdline, 'M') || strchr(emu_cmdline, 'G')) {
+		u64 size;
+
+		size = memparse(emu_cmdline, &emu_cmdline);
+		ret = split_nodes_size_interleave(&ei, &pi, 0, max_addr, size);
+	} else {
+		unsigned long n;
+
+		n = simple_strtoul(emu_cmdline, NULL, 0);
+		ret = split_nodes_interleave(&ei, &pi, 0, max_addr, n);
+	}
+
+	if (ret < 0)
+		goto no_emu;
+
+	if (numa_cleanup_meminfo(&ei) < 0) {
+		pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
+		goto no_emu;
+	}
+
+	/* copy the physical distance table */
+	if (numa_dist_cnt) {
+		u64 phys;
+
+		phys = memblock_find_in_range(0,
+					      (u64)max_pfn_mapped << PAGE_SHIFT,
+					      phys_size, PAGE_SIZE);
+		if (phys == MEMBLOCK_ERROR) {
+			pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
+			goto no_emu;
+		}
+		memblock_x86_reserve_range(phys, phys + phys_size, "TMP NUMA DIST");
+		phys_dist = __va(phys);
+
+		for (i = 0; i < numa_dist_cnt; i++)
+			for (j = 0; j < numa_dist_cnt; j++)
+				phys_dist[i * numa_dist_cnt + j] =
+					node_distance(i, j);
+	}
+
+	/*
+	 * Determine the max emulated nid and the default phys nid to use
+	 * for unmapped nodes.
+	 */
+	max_emu_nid = 0;
+	dfl_phys_nid = NUMA_NO_NODE;
+	for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++) {
+		if (emu_nid_to_phys[i] != NUMA_NO_NODE) {
+			max_emu_nid = i;
+			if (dfl_phys_nid == NUMA_NO_NODE)
+				dfl_phys_nid = emu_nid_to_phys[i];
+		}
+	}
+	if (dfl_phys_nid == NUMA_NO_NODE) {
+		pr_warning("NUMA: Warning: can't determine default physical node, disabling emulation\n");
+		goto no_emu;
+	}
+
+	/* commit */
+	*numa_meminfo = ei;
+
+	/*
+	 * Transform __apicid_to_node table to use emulated nids by
+	 * reverse-mapping phys_nid.  The maps should always exist but fall
+	 * back to zero just in case.
+	 */
+	for (i = 0; i < ARRAY_SIZE(__apicid_to_node); i++) {
+		if (__apicid_to_node[i] == NUMA_NO_NODE)
+			continue;
+		for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
+			if (__apicid_to_node[i] == emu_nid_to_phys[j])
+				break;
+		__apicid_to_node[i] = j < ARRAY_SIZE(emu_nid_to_phys) ? j : 0;
+	}
+
+	/* make sure all emulated nodes are mapped to a physical node */
+	for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
+		if (emu_nid_to_phys[i] == NUMA_NO_NODE)
+			emu_nid_to_phys[i] = dfl_phys_nid;
+
+	/* transform distance table */
+	numa_reset_distance();
+	for (i = 0; i < max_emu_nid + 1; i++) {
+		for (j = 0; j < max_emu_nid + 1; j++) {
+			int physi = emu_nid_to_phys[i];
+			int physj = emu_nid_to_phys[j];
+			int dist;
+
+			if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
+				dist = physi == physj ?
+					LOCAL_DISTANCE : REMOTE_DISTANCE;
+			else
+				dist = phys_dist[physi * numa_dist_cnt + physj];
+
+			numa_set_distance(i, j, dist);
+		}
+	}
+
+	/* free the copied physical distance table */
+	if (phys_dist)
+		memblock_x86_free_range(__pa(phys_dist), __pa(phys_dist) + phys_size);
+	return;
+
+no_emu:
+	/* No emulation.  Build identity emu_nid_to_phys[] for numa_add_cpu() */
+	for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
+		emu_nid_to_phys[i] = i;
+}
+
+#ifndef CONFIG_DEBUG_PER_CPU_MAPS
+void __cpuinit numa_add_cpu(int cpu)
+{
+	int physnid, nid;
+
+	nid = early_cpu_to_node(cpu);
+	BUG_ON(nid == NUMA_NO_NODE || !node_online(nid));
+
+	physnid = emu_nid_to_phys[nid];
+
+	/*
+	 * Map the cpu to each emulated node that is allocated on the physical
+	 * node of the cpu's apic id.
+	 */
+	for_each_online_node(nid)
+		if (emu_nid_to_phys[nid] == physnid)
+			cpumask_set_cpu(cpu, node_to_cpumask_map[nid]);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	int i;
+
+	for_each_online_node(i)
+		cpumask_clear_cpu(cpu, node_to_cpumask_map[i]);
+}
+#else	/* !CONFIG_DEBUG_PER_CPU_MAPS */
+static void __cpuinit numa_set_cpumask(int cpu, int enable)
+{
+	struct cpumask *mask;
+	int nid, physnid, i;
+
+	nid = early_cpu_to_node(cpu);
+	if (nid == NUMA_NO_NODE) {
+		/* early_cpu_to_node() already emits a warning and trace */
+		return;
+	}
+
+	physnid = emu_nid_to_phys[nid];
+
+	for_each_online_node(i) {
+		if (emu_nid_to_phys[nid] != physnid)
+			continue;
+
+		mask = debug_cpumask_set_cpu(cpu, enable);
+		if (!mask)
+			return;
+
+		if (enable)
+			cpumask_set_cpu(cpu, mask);
+		else
+			cpumask_clear_cpu(cpu, mask);
+	}
+}
+
+void __cpuinit numa_add_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, 1);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, 0);
+}
+#endif	/* !CONFIG_DEBUG_PER_CPU_MAPS */
diff --git a/arch/x86/mm/numa_internal.h b/arch/x86/mm/numa_internal.h
new file mode 100644
index 0000000..ef2d973
--- /dev/null
+++ b/arch/x86/mm/numa_internal.h
@@ -0,0 +1,31 @@
+#ifndef __X86_MM_NUMA_INTERNAL_H
+#define __X86_MM_NUMA_INTERNAL_H
+
+#include <linux/types.h>
+#include <asm/numa.h>
+
+struct numa_memblk {
+	u64			start;
+	u64			end;
+	int			nid;
+};
+
+struct numa_meminfo {
+	int			nr_blks;
+	struct numa_memblk	blk[NR_NODE_MEMBLKS];
+};
+
+void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi);
+int __init numa_cleanup_meminfo(struct numa_meminfo *mi);
+void __init numa_reset_distance(void);
+
+#ifdef CONFIG_NUMA_EMU
+void __init numa_emulation(struct numa_meminfo *numa_meminfo,
+			   int numa_dist_cnt);
+#else
+static inline void numa_emulation(struct numa_meminfo *numa_meminfo,
+				  int numa_dist_cnt)
+{ }
+#endif
+
+#endif	/* __X86_MM_NUMA_INTERNAL_H */
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 90825f2..f9e5267 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -310,7 +310,7 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
 		 * these shared mappings are made of small page mappings.
 		 * Thus this don't enforce !RW mapping for small page kernel
 		 * text mapping logic will help Linux Xen parvirt guest boot
-		 * aswell.
+		 * as well.
 		 */
 		if (lookup_address(address, &level) && (level != PG_LEVEL_4K))
 			pgprot_val(forbidden) |= _PAGE_RW;
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 0113d19..8573b83 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -168,8 +168,7 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
 	 * section 8.1: in PAE mode we explicitly have to flush the
 	 * TLB via cr3 if the top-level pgd is changed...
 	 */
-	if (mm == current->active_mm)
-		write_cr3(read_cr3());
+	flush_tlb_mm(mm);
 }
 #else  /* !CONFIG_X86_PAE */
 
diff --git a/arch/x86/mm/srat_32.c b/arch/x86/mm/srat_32.c
index ae96e7b..48651c6 100644
--- a/arch/x86/mm/srat_32.c
+++ b/arch/x86/mm/srat_32.c
@@ -57,7 +57,7 @@ struct node_memory_chunk_s {
 static struct node_memory_chunk_s __initdata node_memory_chunk[MAXCHUNKS];
 
 static int __initdata num_memory_chunks; /* total number of memory chunks */
-static u8 __initdata apicid_to_pxm[MAX_APICID];
+static u8 __initdata apicid_to_pxm[MAX_LOCAL_APIC];
 
 int acpi_numa __initdata;
 
@@ -254,8 +254,8 @@ int __init get_memcfg_from_srat(void)
 	printk(KERN_DEBUG "Number of memory chunks in system = %d\n",
 			 num_memory_chunks);
 
-	for (i = 0; i < MAX_APICID; i++)
-		apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]);
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		set_apicid_to_node(i, pxm_to_node(apicid_to_pxm[i]));
 
 	for (j = 0; j < num_memory_chunks; j++){
 		struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index 603d285..8e9d339 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -26,88 +26,34 @@
 
 int acpi_numa __initdata;
 
-static struct acpi_table_slit *acpi_slit;
-
-static nodemask_t nodes_parsed __initdata;
-static nodemask_t cpu_nodes_parsed __initdata;
-static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES];
 
-static int num_node_memblks __initdata;
-static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
-static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
-
 static __init int setup_node(int pxm)
 {
 	return acpi_map_pxm_to_node(pxm);
 }
 
-static __init int conflicting_memblks(unsigned long start, unsigned long end)
-{
-	int i;
-	for (i = 0; i < num_node_memblks; i++) {
-		struct bootnode *nd = &node_memblk_range[i];
-		if (nd->start == nd->end)
-			continue;
-		if (nd->end > start && nd->start < end)
-			return memblk_nodeid[i];
-		if (nd->end == end && nd->start == start)
-			return memblk_nodeid[i];
-	}
-	return -1;
-}
-
-static __init void cutoff_node(int i, unsigned long start, unsigned long end)
-{
-	struct bootnode *nd = &nodes[i];
-
-	if (nd->start < start) {
-		nd->start = start;
-		if (nd->end < nd->start)
-			nd->start = nd->end;
-	}
-	if (nd->end > end) {
-		nd->end = end;
-		if (nd->start > nd->end)
-			nd->start = nd->end;
-	}
-}
-
 static __init void bad_srat(void)
 {
-	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
-	for (i = 0; i < MAX_LOCAL_APIC; i++)
-		apicid_to_node[i] = NUMA_NO_NODE;
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		nodes[i].start = nodes[i].end = 0;
-		nodes_add[i].start = nodes_add[i].end = 0;
-	}
-	remove_all_active_ranges();
+	memset(nodes_add, 0, sizeof(nodes_add));
 }
 
 static __init inline int srat_disabled(void)
 {
-	return numa_off || acpi_numa < 0;
+	return acpi_numa < 0;
 }
 
 /* Callback for SLIT parsing */
 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 {
-	unsigned length;
-	unsigned long phys;
-
-	length = slit->header.length;
-	phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length,
-		 PAGE_SIZE);
-
-	if (phys == MEMBLOCK_ERROR)
-		panic(" Can not save slit!\n");
+	int i, j;
 
-	acpi_slit = __va(phys);
-	memcpy(acpi_slit, slit, length);
-	memblock_x86_reserve_range(phys, phys + length, "ACPI SLIT");
+	for (i = 0; i < slit->locality_count; i++)
+		for (j = 0; j < slit->locality_count; j++)
+			numa_set_distance(pxm_to_node(i), pxm_to_node(j),
+				slit->entry[slit->locality_count * i + j]);
 }
 
 /* Callback for Proximity Domain -> x2APIC mapping */
@@ -138,8 +84,8 @@ acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa)
 		printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node);
 		return;
 	}
-	apicid_to_node[apic_id] = node;
-	node_set(node, cpu_nodes_parsed);
+	set_apicid_to_node(apic_id, node);
+	node_set(node, numa_nodes_parsed);
 	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
 	       pxm, apic_id, node);
@@ -178,8 +124,8 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
 		return;
 	}
 
-	apicid_to_node[apic_id] = node;
-	node_set(node, cpu_nodes_parsed);
+	set_apicid_to_node(apic_id, node);
+	node_set(node, numa_nodes_parsed);
 	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
 	       pxm, apic_id, node);
@@ -241,7 +187,7 @@ update_nodes_add(int node, unsigned long start, unsigned long end)
 	}
 
 	if (changed) {
-		node_set(node, cpu_nodes_parsed);
+		node_set(node, numa_nodes_parsed);
 		printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
 				 nd->start, nd->end);
 	}
@@ -251,10 +197,8 @@ update_nodes_add(int node, unsigned long start, unsigned long end)
 void __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
-	struct bootnode *nd, oldnode;
 	unsigned long start, end;
 	int node, pxm;
-	int i;
 
 	if (srat_disabled())
 		return;
@@ -276,300 +220,31 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 		bad_srat();
 		return;
 	}
-	i = conflicting_memblks(start, end);
-	if (i == node) {
-		printk(KERN_WARNING
-		"SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
-			pxm, start, end, nodes[i].start, nodes[i].end);
-	} else if (i >= 0) {
-		printk(KERN_ERR
-		       "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
-		       pxm, start, end, node_to_pxm(i),
-			nodes[i].start, nodes[i].end);
+
+	if (numa_add_memblk(node, start, end) < 0) {
 		bad_srat();
 		return;
 	}
-	nd = &nodes[node];
-	oldnode = *nd;
-	if (!node_test_and_set(node, nodes_parsed)) {
-		nd->start = start;
-		nd->end = end;
-	} else {
-		if (start < nd->start)
-			nd->start = start;
-		if (nd->end < end)
-			nd->end = end;
-	}
 
 	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
 	       start, end);
 
-	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
+	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)
 		update_nodes_add(node, start, end);
-		/* restore nodes[node] */
-		*nd = oldnode;
-		if ((nd->start | nd->end) == 0)
-			node_clear(node, nodes_parsed);
-	}
-
-	node_memblk_range[num_node_memblks].start = start;
-	node_memblk_range[num_node_memblks].end = end;
-	memblk_nodeid[num_node_memblks] = node;
-	num_node_memblks++;
-}
-
-/* Sanity check to catch more bad SRATs (they are amazingly common).
-   Make sure the PXMs cover all memory. */
-static int __init nodes_cover_memory(const struct bootnode *nodes)
-{
-	int i;
-	unsigned long pxmram, e820ram;
-
-	pxmram = 0;
-	for_each_node_mask(i, nodes_parsed) {
-		unsigned long s = nodes[i].start >> PAGE_SHIFT;
-		unsigned long e = nodes[i].end >> PAGE_SHIFT;
-		pxmram += e - s;
-		pxmram -= __absent_pages_in_range(i, s, e);
-		if ((long)pxmram < 0)
-			pxmram = 0;
-	}
-
-	e820ram = max_pfn - (memblock_x86_hole_size(0, max_pfn<<PAGE_SHIFT)>>PAGE_SHIFT);
-	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
-	if ((long)(e820ram - pxmram) >= (1<<(20 - PAGE_SHIFT))) {
-		printk(KERN_ERR
-	"SRAT: PXMs only cover %luMB of your %luMB e820 RAM. Not used.\n",
-			(pxmram << PAGE_SHIFT) >> 20,
-			(e820ram << PAGE_SHIFT) >> 20);
-		return 0;
-	}
-	return 1;
 }
 
 void __init acpi_numa_arch_fixup(void) {}
 
-#ifdef CONFIG_NUMA_EMU
-void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
-				unsigned long end)
-{
-	int i;
-
-	for_each_node_mask(i, nodes_parsed) {
-		cutoff_node(i, start, end);
-		physnodes[i].start = nodes[i].start;
-		physnodes[i].end = nodes[i].end;
-	}
-}
-#endif /* CONFIG_NUMA_EMU */
-
-/* Use the information discovered above to actually set up the nodes. */
-int __init acpi_scan_nodes(unsigned long start, unsigned long end)
+int __init x86_acpi_numa_init(void)
 {
-	int i;
-
-	if (acpi_numa <= 0)
-		return -1;
-
-	/* First clean up the node list */
-	for (i = 0; i < MAX_NUMNODES; i++)
-		cutoff_node(i, start, end);
-
-	/*
-	 * Join together blocks on the same node, holes between
-	 * which don't overlap with memory on other nodes.
-	 */
-	for (i = 0; i < num_node_memblks; ++i) {
-		int j, k;
-
-		for (j = i + 1; j < num_node_memblks; ++j) {
-			unsigned long start, end;
-
-			if (memblk_nodeid[i] != memblk_nodeid[j])
-				continue;
-			start = min(node_memblk_range[i].end,
-			            node_memblk_range[j].end);
-			end = max(node_memblk_range[i].start,
-			          node_memblk_range[j].start);
-			for (k = 0; k < num_node_memblks; ++k) {
-				if (memblk_nodeid[i] == memblk_nodeid[k])
-					continue;
-				if (start < node_memblk_range[k].end &&
-				    end > node_memblk_range[k].start)
-					break;
-			}
-			if (k < num_node_memblks)
-				continue;
-			start = min(node_memblk_range[i].start,
-			            node_memblk_range[j].start);
-			end = max(node_memblk_range[i].end,
-			          node_memblk_range[j].end);
-			printk(KERN_INFO "SRAT: Node %d "
-			       "[%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
-			       memblk_nodeid[i],
-			       node_memblk_range[i].start,
-			       node_memblk_range[i].end,
-			       node_memblk_range[j].start,
-			       node_memblk_range[j].end,
-			       start, end);
-			node_memblk_range[i].start = start;
-			node_memblk_range[i].end = end;
-			k = --num_node_memblks - j;
-			memmove(memblk_nodeid + j, memblk_nodeid + j+1,
-				k * sizeof(*memblk_nodeid));
-			memmove(node_memblk_range + j, node_memblk_range + j+1,
-				k * sizeof(*node_memblk_range));
-			--j;
-		}
-	}
-
-	memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
-					   memblk_nodeid);
-	if (memnode_shift < 0) {
-		printk(KERN_ERR
-		     "SRAT: No NUMA node hash function found. Contact maintainer\n");
-		bad_srat();
-		return -1;
-	}
-
-	for (i = 0; i < num_node_memblks; i++)
-		memblock_x86_register_active_regions(memblk_nodeid[i],
-				node_memblk_range[i].start >> PAGE_SHIFT,
-				node_memblk_range[i].end >> PAGE_SHIFT);
-
-	/* for out of order entries in SRAT */
-	sort_node_map();
-	if (!nodes_cover_memory(nodes)) {
-		bad_srat();
-		return -1;
-	}
+	int ret;
 
-	/* Account for nodes with cpus and no memory */
-	nodes_or(node_possible_map, nodes_parsed, cpu_nodes_parsed);
-
-	/* Finally register nodes */
-	for_each_node_mask(i, node_possible_map)
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	/* Try again in case setup_node_bootmem missed one due
-	   to missing bootmem */
-	for_each_node_mask(i, node_possible_map)
-		if (!node_online(i))
-			setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		int node = early_cpu_to_node(i);
-
-		if (node == NUMA_NO_NODE)
-			continue;
-		if (!node_online(node))
-			numa_clear_node(i);
-	}
-	numa_init_array();
-	return 0;
-}
-
-#ifdef CONFIG_NUMA_EMU
-static int fake_node_to_pxm_map[MAX_NUMNODES] __initdata = {
-	[0 ... MAX_NUMNODES-1] = PXM_INVAL
-};
-static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
-	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
-};
-static int __init find_node_by_addr(unsigned long addr)
-{
-	int ret = NUMA_NO_NODE;
-	int i;
-
-	for_each_node_mask(i, nodes_parsed) {
-		/*
-		 * Find the real node that this emulated node appears on.  For
-		 * the sake of simplicity, we only use a real node's starting
-		 * address to determine which emulated node it appears on.
-		 */
-		if (addr >= nodes[i].start && addr < nodes[i].end) {
-			ret = i;
-			break;
-		}
-	}
-	return ret;
+	ret = acpi_numa_init();
+	if (ret < 0)
+		return ret;
+	return srat_disabled() ? -EINVAL : 0;
 }
 
-/*
- * In NUMA emulation, we need to setup proximity domain (_PXM) to node ID
- * mappings that respect the real ACPI topology but reflect our emulated
- * environment.  For each emulated node, we find which real node it appears on
- * and create PXM to NID mappings for those fake nodes which mirror that
- * locality.  SLIT will now represent the correct distances between emulated
- * nodes as a result of the real topology.
- */
-void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes)
-{
-	int i, j;
-
-	for (i = 0; i < num_nodes; i++) {
-		int nid, pxm;
-
-		nid = find_node_by_addr(fake_nodes[i].start);
-		if (nid == NUMA_NO_NODE)
-			continue;
-		pxm = node_to_pxm(nid);
-		if (pxm == PXM_INVAL)
-			continue;
-		fake_node_to_pxm_map[i] = pxm;
-		/*
-		 * For each apicid_to_node mapping that exists for this real
-		 * node, it must now point to the fake node ID.
-		 */
-		for (j = 0; j < MAX_LOCAL_APIC; j++)
-			if (apicid_to_node[j] == nid &&
-			    fake_apicid_to_node[j] == NUMA_NO_NODE)
-				fake_apicid_to_node[j] = i;
-	}
-
-	/*
-	 * If there are apicid-to-node mappings for physical nodes that do not
-	 * have a corresponding emulated node, it should default to a guaranteed
-	 * value.
-	 */
-	for (i = 0; i < MAX_LOCAL_APIC; i++)
-		if (apicid_to_node[i] != NUMA_NO_NODE &&
-		    fake_apicid_to_node[i] == NUMA_NO_NODE)
-			fake_apicid_to_node[i] = 0;
-
-	for (i = 0; i < num_nodes; i++)
-		__acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i);
-	memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
-
-	nodes_clear(nodes_parsed);
-	for (i = 0; i < num_nodes; i++)
-		if (fake_nodes[i].start != fake_nodes[i].end)
-			node_set(i, nodes_parsed);
-}
-
-static int null_slit_node_compare(int a, int b)
-{
-	return node_to_pxm(a) == node_to_pxm(b);
-}
-#else
-static int null_slit_node_compare(int a, int b)
-{
-	return a == b;
-}
-#endif /* CONFIG_NUMA_EMU */
-
-int __node_distance(int a, int b)
-{
-	int index;
-
-	if (!acpi_slit)
-		return null_slit_node_compare(a, b) ? LOCAL_DISTANCE :
-						      REMOTE_DISTANCE;
-	index = acpi_slit->locality_count * node_to_pxm(a);
-	return acpi_slit->entry[index + node_to_pxm(b)];
-}
-
-EXPORT_SYMBOL(__node_distance);
-
 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY)
 int memory_add_physaddr_to_nid(u64 start)
 {
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 6acc724..d6c0418 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -179,12 +179,8 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask,
 	sender = this_cpu_read(tlb_vector_offset);
 	f = &flush_state[sender];
 
-	/*
-	 * Could avoid this lock when
-	 * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
-	 * probably not worth checking this for a cache-hot lock.
-	 */
-	raw_spin_lock(&f->tlbstate_lock);
+	if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS)
+		raw_spin_lock(&f->tlbstate_lock);
 
 	f->flush_mm = mm;
 	f->flush_va = va;
@@ -202,7 +198,8 @@ static void flush_tlb_others_ipi(const struct cpumask *cpumask,
 
 	f->flush_mm = NULL;
 	f->flush_va = 0;
-	raw_spin_unlock(&f->tlbstate_lock);
+	if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS)
+		raw_spin_unlock(&f->tlbstate_lock);
 }
 
 void native_flush_tlb_others(const struct cpumask *cpumask,
@@ -211,11 +208,10 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
 	if (is_uv_system()) {
 		unsigned int cpu;
 
-		cpu = get_cpu();
+		cpu = smp_processor_id();
 		cpumask = uv_flush_tlb_others(cpumask, mm, va, cpu);
 		if (cpumask)
 			flush_tlb_others_ipi(cpumask, mm, va);
-		put_cpu();
 		return;
 	}
 	flush_tlb_others_ipi(cpumask, mm, va);
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c
index 72cbec1..2d49d4e 100644
--- a/arch/x86/oprofile/backtrace.c
+++ b/arch/x86/oprofile/backtrace.c
@@ -126,7 +126,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
 	if (!user_mode_vm(regs)) {
 		unsigned long stack = kernel_stack_pointer(regs);
 		if (depth)
-			dump_trace(NULL, regs, (unsigned long *)stack,
+			dump_trace(NULL, regs, (unsigned long *)stack, 0,
 				   &backtrace_ops, &depth);
 		return;
 	}
diff --git a/arch/x86/oprofile/op_model_p4.c b/arch/x86/oprofile/op_model_p4.c
index 9fadec0..98ab130 100644
--- a/arch/x86/oprofile/op_model_p4.c
+++ b/arch/x86/oprofile/op_model_p4.c
@@ -50,7 +50,7 @@ static inline void setup_num_counters(void)
 #endif
 }
 
-static int inline addr_increment(void)
+static inline int addr_increment(void)
 {
 #ifdef CONFIG_SMP
 	return smp_num_siblings == 2 ? 2 : 1;
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index e27dffb..026e493 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -350,7 +350,7 @@ static int __init early_fill_mp_bus_info(void)
 
 #define ENABLE_CF8_EXT_CFG      (1ULL << 46)
 
-static void enable_pci_io_ecs(void *unused)
+static void __cpuinit enable_pci_io_ecs(void *unused)
 {
 	u64 reg;
 	rdmsrl(MSR_AMD64_NB_CFG, reg);
diff --git a/arch/x86/pci/ce4100.c b/arch/x86/pci/ce4100.c
index 9260b3e..67858be 100644
--- a/arch/x86/pci/ce4100.c
+++ b/arch/x86/pci/ce4100.c
@@ -255,7 +255,7 @@ int bridge_read(unsigned int devfn, int reg, int len, u32 *value)
 static int ce4100_conf_read(unsigned int seg, unsigned int bus,
 			    unsigned int devfn, int reg, int len, u32 *value)
 {
-	int i, retval = 1;
+	int i;
 
 	if (bus == 1) {
 		for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index b1805b7..494f2e7 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -241,7 +241,7 @@ void __init pcibios_resource_survey(void)
 	e820_reserve_resources_late();
 	/*
 	 * Insert the IO APIC resources after PCI initialization has
-	 * occured to handle IO APICS that are mapped in on a BAR in
+	 * occurred to handle IO APICS that are mapped in on a BAR in
 	 * PCI space, but before trying to assign unassigned pci res.
 	 */
 	ioapic_insert_resources();
@@ -304,7 +304,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
 		/*
 		 * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
 		 * To avoid attribute conflicts, request UC MINUS here
-		 * aswell.
+		 * as well.
 		 */
 		prot |= _PAGE_CACHE_UC_MINUS;
 
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index 87e6c83..8201165 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -597,21 +597,18 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
 		return 1;
 	}
 
-	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN) && 
-		(device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)) {
+	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN && 
+	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX) 
+	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && 
+	     device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)
+	||  (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN &&
+	     device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)) {
 		r->name = "PIIX/ICH";
 		r->get = pirq_piix_get;
 		r->set = pirq_piix_set;
 		return 1;
 	}
 
-	if ((device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN) && 
-		(device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)) {
-		r->name = "PIIX/ICH";
-		r->get = pirq_piix_get;
-		r->set = pirq_piix_set;
-		return 1;
-	}
 	return 0;
 }
 
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 25cd4a0..e37b407 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -20,7 +20,8 @@
 #include <asm/xen/pci.h>
 
 #ifdef CONFIG_ACPI
-static int xen_hvm_register_pirq(u32 gsi, int triggering)
+static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
+				 int trigger, int polarity)
 {
 	int rc, irq;
 	struct physdev_map_pirq map_irq;
@@ -41,7 +42,7 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering)
 		return -1;
 	}
 
-	if (triggering == ACPI_EDGE_SENSITIVE) {
+	if (trigger == ACPI_EDGE_SENSITIVE) {
 		shareable = 0;
 		name = "ioapic-edge";
 	} else {
@@ -49,18 +50,12 @@ static int xen_hvm_register_pirq(u32 gsi, int triggering)
 		name = "ioapic-level";
 	}
 
-	irq = xen_map_pirq_gsi(map_irq.pirq, gsi, shareable, name);
+	irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name);
 
 	printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
 
 	return irq;
 }
-
-static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
-				 int trigger, int polarity)
-{
-	return xen_hvm_register_pirq(gsi, trigger);
-}
 #endif
 
 #if defined(CONFIG_PCI_MSI)
@@ -91,7 +86,7 @@ static void xen_msi_compose_msg(struct pci_dev *pdev, unsigned int pirq,
 
 static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-	int irq, pirq, ret = 0;
+	int irq, pirq;
 	struct msi_desc *msidesc;
 	struct msi_msg msg;
 
@@ -99,39 +94,32 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		__read_msi_msg(msidesc, &msg);
 		pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
 			((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
-		if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) {
-			xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
-					"msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ);
-			if (irq < 0)
+		if (msg.data != XEN_PIRQ_MSI_DATA ||
+		    xen_irq_from_pirq(pirq) < 0) {
+			pirq = xen_allocate_pirq_msi(dev, msidesc);
+			if (pirq < 0)
 				goto error;
-			ret = set_irq_msi(irq, msidesc);
-			if (ret < 0)
-				goto error_while;
-			printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d"
-					" pirq=%d\n", irq, pirq);
-			return 0;
+			xen_msi_compose_msg(dev, pirq, &msg);
+			__write_msi_msg(msidesc, &msg);
+			dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
+		} else {
+			dev_dbg(&dev->dev,
+				"xen: msi already bound to pirq=%d\n", pirq);
 		}
-		xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
-				"msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ));
-		if (irq < 0 || pirq < 0)
+		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "msi-x" : "msi");
+		if (irq < 0)
 			goto error;
-		printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq);
-		xen_msi_compose_msg(dev, pirq, &msg);
-		ret = set_irq_msi(irq, msidesc);
-		if (ret < 0)
-			goto error_while;
-		write_msi_msg(irq, &msg);
+		dev_dbg(&dev->dev,
+			"xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
 	}
 	return 0;
 
-error_while:
-	unbind_from_irqhandler(irq, NULL);
 error:
-	if (ret == -ENODEV)
-		dev_err(&dev->dev, "Xen PCI frontend has not registered" \
-				" MSI/MSI-X support!\n");
-
-	return ret;
+	dev_err(&dev->dev,
+		"Xen PCI frontend has not registered MSI/MSI-X support!\n");
+	return -ENODEV;
 }
 
 /*
@@ -150,35 +138,26 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		return -ENOMEM;
 
 	if (type == PCI_CAP_ID_MSIX)
-		ret = xen_pci_frontend_enable_msix(dev, &v, nvec);
+		ret = xen_pci_frontend_enable_msix(dev, v, nvec);
 	else
-		ret = xen_pci_frontend_enable_msi(dev, &v);
+		ret = xen_pci_frontend_enable_msi(dev, v);
 	if (ret)
 		goto error;
 	i = 0;
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = xen_allocate_pirq(v[i], 0, /* not sharable */
-			(type == PCI_CAP_ID_MSIX) ?
-			"pcifront-msi-x" : "pcifront-msi");
-		if (irq < 0) {
-			ret = -1;
+		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "pcifront-msi-x" :
+					       "pcifront-msi");
+		if (irq < 0)
 			goto free;
-		}
-
-		ret = set_irq_msi(irq, msidesc);
-		if (ret)
-			goto error_while;
 		i++;
 	}
 	kfree(v);
 	return 0;
 
-error_while:
-	unbind_from_irqhandler(irq, NULL);
 error:
-	if (ret == -ENODEV)
-		dev_err(&dev->dev, "Xen PCI frontend has not registered" \
-			" MSI/MSI-X support!\n");
+	dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
 free:
 	kfree(v);
 	return ret;
@@ -193,6 +172,9 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev)
 		xen_pci_frontend_disable_msix(dev);
 	else
 		xen_pci_frontend_disable_msi(dev);
+
+	/* Free the IRQ's and the msidesc using the generic code. */
+	default_teardown_msi_irqs(dev);
 }
 
 static void xen_teardown_msi_irq(unsigned int irq)
@@ -200,47 +182,91 @@ static void xen_teardown_msi_irq(unsigned int irq)
 	xen_destroy_irq(irq);
 }
 
+#ifdef CONFIG_XEN_DOM0
 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-	int irq, ret;
+	int ret = 0;
 	struct msi_desc *msidesc;
 
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = xen_create_msi_irq(dev, msidesc, type);
-		if (irq < 0)
-			return -1;
+		struct physdev_map_pirq map_irq;
 
-		ret = set_irq_msi(irq, msidesc);
-		if (ret)
-			goto error;
-	}
-	return 0;
+		memset(&map_irq, 0, sizeof(map_irq));
+		map_irq.domid = DOMID_SELF;
+		map_irq.type = MAP_PIRQ_TYPE_MSI;
+		map_irq.index = -1;
+		map_irq.pirq = -1;
+		map_irq.bus = dev->bus->number;
+		map_irq.devfn = dev->devfn;
 
-error:
-	xen_destroy_irq(irq);
+		if (type == PCI_CAP_ID_MSIX) {
+			int pos;
+			u32 table_offset, bir;
+
+			pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+
+			pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
+					      &table_offset);
+			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+
+			map_irq.table_base = pci_resource_start(dev, bir);
+			map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
+		}
+
+		ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+		if (ret) {
+			dev_warn(&dev->dev, "xen map irq failed %d\n", ret);
+			goto out;
+		}
+
+		ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
+					       map_irq.pirq, map_irq.index,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "msi-x" : "msi");
+		if (ret < 0)
+			goto out;
+	}
+	ret = 0;
+out:
 	return ret;
 }
 #endif
+#endif
 
 static int xen_pcifront_enable_irq(struct pci_dev *dev)
 {
 	int rc;
 	int share = 1;
+	int pirq;
+	u8 gsi;
 
-	dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq);
+	rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
+			 rc);
+		return rc;
+	}
 
-	if (dev->irq < 0)
-		return -EINVAL;
+	rc = xen_allocate_pirq_gsi(gsi);
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n",
+			 gsi, rc);
+		return rc;
+	}
+	pirq = rc;
 
-	if (dev->irq < NR_IRQS_LEGACY)
+	if (gsi < NR_IRQS_LEGACY)
 		share = 0;
 
-	rc = xen_allocate_pirq(dev->irq, share, "pcifront");
+	rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
 	if (rc < 0) {
-		dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n",
-			 dev->irq, rc);
+		dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
+			 gsi, pirq, rc);
 		return rc;
 	}
+
+	dev->irq = rc;
+	dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
 	return 0;
 }
 
@@ -292,7 +318,7 @@ int __init pci_xen_hvm_init(void)
 #ifdef CONFIG_XEN_DOM0
 static int xen_register_pirq(u32 gsi, int triggering)
 {
-	int rc, irq;
+	int rc, pirq, irq = -1;
 	struct physdev_map_pirq map_irq;
 	int shareable = 0;
 	char *name;
@@ -308,17 +334,20 @@ static int xen_register_pirq(u32 gsi, int triggering)
 		name = "ioapic-level";
 	}
 
-	irq = xen_allocate_pirq(gsi, shareable, name);
-
-	printk(KERN_DEBUG "xen: --> irq=%d\n", irq);
+	pirq = xen_allocate_pirq_gsi(gsi);
+	if (pirq < 0)
+		goto out;
 
+	irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
 	if (irq < 0)
 		goto out;
 
+	printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq);
+
 	map_irq.domid = DOMID_SELF;
 	map_irq.type = MAP_PIRQ_TYPE_GSI;
 	map_irq.index = gsi;
-	map_irq.pirq = irq;
+	map_irq.pirq = pirq;
 
 	rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
 	if (rc) {
@@ -405,13 +434,18 @@ static int __init pci_xen_initial_domain(void)
 
 void __init xen_setup_pirqs(void)
 {
-	int irq;
+	int pirq, irq;
 
 	pci_xen_initial_domain();
 
 	if (0 == nr_ioapics) {
-		for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
-			xen_allocate_pirq(irq, 0, "xt-pic");
+		for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
+			pirq = xen_allocate_pirq_gsi(irq);
+			if (WARN(pirq < 0,
+				 "Could not allocate PIRQ for legacy interrupt\n"))
+				break;
+			irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic");
+		}
 		return;
 	}
 
diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c
index cd6f184..28071bb 100644
--- a/arch/x86/platform/ce4100/ce4100.c
+++ b/arch/x86/platform/ce4100/ce4100.c
@@ -16,21 +16,19 @@
 #include <linux/serial_8250.h>
 
 #include <asm/ce4100.h>
+#include <asm/prom.h>
 #include <asm/setup.h>
+#include <asm/i8259.h>
 #include <asm/io.h>
+#include <asm/io_apic.h>
 
 static int ce4100_i8042_detect(void)
 {
 	return 0;
 }
 
-static void __init sdv_find_smp_config(void)
-{
-}
-
 #ifdef CONFIG_SERIAL_8250
 
-
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
 {
 	offset = offset << p->regshift;
@@ -119,6 +117,15 @@ static void __init sdv_arch_setup(void)
 	sdv_serial_fixup();
 }
 
+#ifdef CONFIG_X86_IO_APIC
+static void __cpuinit sdv_pci_init(void)
+{
+	x86_of_pci_init();
+	/* We can't set this earlier, because we need to calibrate the timer */
+	legacy_pic = &null_legacy_pic;
+}
+#endif
+
 /*
  * CE4100 specific x86_init function overrides and early setup
  * calls.
@@ -129,6 +136,11 @@ void __init x86_ce4100_early_setup(void)
 	x86_platform.i8042_detect = ce4100_i8042_detect;
 	x86_init.resources.probe_roms = x86_init_noop;
 	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
-	x86_init.mpparse.find_smp_config = sdv_find_smp_config;
+	x86_init.mpparse.find_smp_config = x86_init_noop;
 	x86_init.pci.init = ce4100_pci_init;
+
+#ifdef CONFIG_X86_IO_APIC
+	x86_init.pci.init_irq = sdv_pci_init;
+	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
+#endif
 }
diff --git a/arch/x86/platform/ce4100/falconfalls.dts b/arch/x86/platform/ce4100/falconfalls.dts
new file mode 100644
index 0000000..dc701ea
--- /dev/null
+++ b/arch/x86/platform/ce4100/falconfalls.dts
@@ -0,0 +1,428 @@
+/*
+ * CE4100 on Falcon Falls
+ *
+ * (c) Copyright 2010 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+/dts-v1/;
+/ {
+	model = "intel,falconfalls";
+	compatible = "intel,falconfalls";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "intel,ce4100";
+			reg = <0>;
+			lapic = <&lapic0>;
+		};
+	};
+
+	soc@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "intel,ce4100-cp";
+		ranges;
+
+		ioapic1: interrupt-controller@fec00000 {
+			#interrupt-cells = <2>;
+			compatible = "intel,ce4100-ioapic";
+			interrupt-controller;
+			reg = <0xfec00000 0x1000>;
+		};
+
+		timer@fed00000 {
+			compatible = "intel,ce4100-hpet";
+			reg = <0xfed00000 0x200>;
+		};
+
+		lapic0: interrupt-controller@fee00000 {
+			compatible = "intel,ce4100-lapic";
+			reg = <0xfee00000 0x1000>;
+		};
+
+		pci@3fc {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			compatible = "intel,ce4100-pci", "pci";
+			device_type = "pci";
+			bus-range = <0 0>;
+			ranges = <0x2000000 0 0xbffff000 0xbffff000 0 0x1000
+				  0x2000000 0 0xdffe0000 0xdffe0000 0 0x1000
+				  0x0000000 0 0x0	 0x0	    0 0x100>;
+
+			/* Secondary IO-APIC */
+			ioapic2: interrupt-controller@0,1 {
+				#interrupt-cells = <2>;
+				compatible = "intel,ce4100-ioapic";
+				interrupt-controller;
+				reg = <0x100 0x0 0x0 0x0 0x0>;
+				assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+			};
+
+			pci@1,0 {
+				#address-cells = <3>;
+				#size-cells = <2>;
+				compatible = "intel,ce4100-pci", "pci";
+				device_type = "pci";
+				bus-range = <1 1>;
+				ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
+
+				interrupt-parent = <&ioapic2>;
+
+				display@2,0 {
+					compatible = "pci8086,2e5b.2",
+						   "pci8086,2e5b",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x11000 0x0 0x0 0x0 0x0>;
+					interrupts = <0 1>;
+				};
+
+				multimedia@3,0 {
+					compatible = "pci8086,2e5c.2",
+						   "pci8086,2e5c",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x11800 0x0 0x0 0x0 0x0>;
+					interrupts = <2 1>;
+				};
+
+				multimedia@4,0 {
+					compatible = "pci8086,2e5d.2",
+						   "pci8086,2e5d",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12000 0x0 0x0 0x0 0x0>;
+					interrupts = <4 1>;
+				};
+
+				multimedia@4,1 {
+					compatible = "pci8086,2e5e.2",
+						   "pci8086,2e5e",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12100 0x0 0x0 0x0 0x0>;
+					interrupts = <5 1>;
+				};
+
+				sound@6,0 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13000 0x0 0x0 0x0 0x0>;
+					interrupts = <6 1>;
+				};
+
+				sound@6,1 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13100 0x0 0x0 0x0 0x0>;
+					interrupts = <7 1>;
+				};
+
+				sound@6,2 {
+					compatible = "pci8086,2e60.2",
+						   "pci8086,2e60",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13200 0x0 0x0 0x0 0x0>;
+					interrupts = <8 1>;
+				};
+
+				display@8,0 {
+					compatible = "pci8086,2e61.2",
+						   "pci8086,2e61",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14000 0x0 0x0 0x0 0x0>;
+					interrupts = <9 1>;
+				};
+
+				display@8,1 {
+					compatible = "pci8086,2e62.2",
+						   "pci8086,2e62",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14100 0x0 0x0 0x0 0x0>;
+					interrupts = <10 1>;
+				};
+
+				multimedia@8,2 {
+					compatible = "pci8086,2e63.2",
+						   "pci8086,2e63",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x14200 0x0 0x0 0x0 0x0>;
+					interrupts = <11 1>;
+				};
+
+				entertainment-encryption@9,0 {
+					compatible = "pci8086,2e64.2",
+						   "pci8086,2e64",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x14800 0x0 0x0 0x0 0x0>;
+					interrupts = <12 1>;
+				};
+
+				localbus@a,0 {
+					compatible = "pci8086,2e65.2",
+						   "pci8086,2e65",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15000 0x0 0x0 0x0 0x0>;
+				};
+
+				serial@b,0 {
+					compatible = "pci8086,2e66.2",
+						   "pci8086,2e66",
+						   "pciclass070003",
+						   "pciclass0700";
+
+					reg = <0x15800 0x0 0x0 0x0 0x0>;
+					interrupts = <14 1>;
+				};
+
+				gpio@b,1 {
+					compatible = "pci8086,2e67.2",
+						   "pci8086,2e67",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					#gpio-cells = <2>;
+					reg = <0x15900 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+					gpio-controller;
+				};
+
+				i2c-controller@b,2 {
+					#address-cells = <2>;
+					#size-cells = <1>;
+					compatible = "pci8086,2e68.2",
+						   "pci8086,2e68",
+						   "pciclass,ff0000",
+						   "pciclass,ff00";
+
+					reg = <0x15a00 0x0 0x0 0x0 0x0>;
+					interrupts = <16 1>;
+					ranges = <0 0	0x02000000 0 0xdffe0500	0x100
+						  1 0	0x02000000 0 0xdffe0600	0x100
+						  2 0	0x02000000 0 0xdffe0700	0x100>;
+
+					i2c@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <0 0 0x100>;
+					};
+
+					i2c@1 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <1 0 0x100>;
+
+						gpio@26 {
+							#gpio-cells = <2>;
+							compatible = "ti,pcf8575";
+							reg = <0x26>;
+							gpio-controller;
+						};
+					};
+
+					i2c@2 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <2 0 0x100>;
+
+						gpio@26 {
+							#gpio-cells = <2>;
+							compatible = "ti,pcf8575";
+							reg = <0x26>;
+							gpio-controller;
+						};
+					};
+				};
+
+				smard-card@b,3 {
+					compatible = "pci8086,2e69.2",
+						   "pci8086,2e69",
+						   "pciclass070500",
+						   "pciclass0705";
+
+					reg = <0x15b00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+				};
+
+				spi-controller@b,4 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible =
+						"pci8086,2e6a.2",
+						"pci8086,2e6a",
+						"pciclass,ff0000",
+						"pciclass,ff00";
+
+					reg = <0x15c00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+
+					dac@0 {
+						compatible = "ti,pcm1755";
+						reg = <0>;
+						spi-max-frequency = <115200>;
+					};
+
+					dac@1 {
+						compatible = "ti,pcm1609a";
+						reg = <1>;
+						spi-max-frequency = <115200>;
+					};
+
+					eeprom@2 {
+						compatible = "atmel,at93c46";
+						reg = <2>;
+						spi-max-frequency = <115200>;
+					};
+				};
+
+				multimedia@b,7 {
+					compatible = "pci8086,2e6d.2",
+						   "pci8086,2e6d",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15f00 0x0 0x0 0x0 0x0>;
+				};
+
+				ethernet@c,0 {
+					compatible = "pci8086,2e6e.2",
+						   "pci8086,2e6e",
+						   "pciclass020000",
+						   "pciclass0200";
+
+					reg = <0x16000 0x0 0x0 0x0 0x0>;
+					interrupts = <21 1>;
+				};
+
+				clock@c,1 {
+					compatible = "pci8086,2e6f.2",
+						   "pci8086,2e6f",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x16100 0x0 0x0 0x0 0x0>;
+					interrupts = <3 1>;
+				};
+
+				usb@d,0 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16800 0x0 0x0 0x0 0x0>;
+					interrupts = <22 3>;
+				};
+
+				usb@d,1 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16900 0x0 0x0 0x0 0x0>;
+					interrupts = <22 3>;
+				};
+
+				sata@e,0 {
+					compatible = "pci8086,2e71.0",
+						   "pci8086,2e71",
+						   "pciclass010601",
+						   "pciclass0106";
+
+					reg = <0x17000 0x0 0x0 0x0 0x0>;
+					interrupts = <23 3>;
+				};
+
+				flash@f,0 {
+					compatible = "pci8086,701.1",
+						   "pci8086,701",
+						   "pciclass050100",
+						   "pciclass0501";
+
+					reg = <0x17800 0x0 0x0 0x0 0x0>;
+					interrupts = <13 1>;
+				};
+
+				entertainment-encryption@10,0 {
+					compatible = "pci8086,702.1",
+						   "pci8086,702",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x18000 0x0 0x0 0x0 0x0>;
+				};
+
+				co-processor@11,0 {
+					compatible = "pci8086,703.1",
+						   "pci8086,703",
+						   "pciclass0b4000",
+						   "pciclass0b40";
+
+					reg = <0x18800 0x0 0x0 0x0 0x0>;
+					interrupts = <1 1>;
+				};
+
+				multimedia@12,0 {
+					compatible = "pci8086,704.0",
+						   "pci8086,704",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x19000 0x0 0x0 0x0 0x0>;
+				};
+			};
+
+			isa@1f,0 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				compatible = "isa";
+				ranges = <1 0 0 0 0 0x100>;
+
+				rtc@70 {
+					compatible = "intel,ce4100-rtc", "motorola,mc146818";
+					interrupts = <8 3>;
+					interrupt-parent = <&ioapic1>;
+					ctrl-reg = <2>;
+					freq-reg = <0x26>;
+					reg = <1 0x70 2>;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index ea6529e..5c0207b 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -31,6 +31,7 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
 #include <asm/io.h>
 #include <asm/i8259.h>
 #include <asm/intel_scu_ipc.h>
@@ -268,6 +269,7 @@ void __init x86_mrst_early_setup(void)
 
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
 	x86_platform.i8042_detect = mrst_i8042_detect;
+	x86_init.timers.wallclock_init = mrst_rtc_init;
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/mrst/vrtc.c
index 32cd7ed..04cf645 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/mrst/vrtc.c
@@ -100,22 +100,14 @@ int vrtc_set_mmss(unsigned long nowtime)
 
 void __init mrst_rtc_init(void)
 {
-	unsigned long rtc_paddr;
-	void __iomem *virt_base;
+	unsigned long vrtc_paddr = sfi_mrtc_array[0].phys_addr;
 
 	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
-	if (!sfi_mrtc_num)
+	if (!sfi_mrtc_num || !vrtc_paddr)
 		return;
 
-	rtc_paddr = sfi_mrtc_array[0].phys_addr;
-
-	/* vRTC's register address may not be page aligned */
-	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
-
-	virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
-	virt_base += rtc_paddr & ~PAGE_MASK;
-	vrtc_virt_base = virt_base;
-
+	vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
+								vrtc_paddr);
 	x86_platform.get_wallclock = vrtc_get_time;
 	x86_platform.set_wallclock = vrtc_set_mmss;
 }
diff --git a/arch/x86/platform/olpc/Makefile b/arch/x86/platform/olpc/Makefile
index e797428..c2a8cab 100644
--- a/arch/x86/platform/olpc/Makefile
+++ b/arch/x86/platform/olpc/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_OLPC)		+= olpc.o
 obj-$(CONFIG_OLPC_XO1)		+= olpc-xo1.o
-obj-$(CONFIG_OLPC_OPENFIRMWARE)	+= olpc_ofw.o
-obj-$(CONFIG_OLPC_OPENFIRMWARE_DT)	+= olpc_dt.o
+obj-$(CONFIG_OLPC)		+= olpc_ofw.o
+obj-$(CONFIG_OF_PROMTREE)	+= olpc_dt.o
diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c
index 7b24460..374a05d 100644
--- a/arch/x86/platform/uv/uv_irq.c
+++ b/arch/x86/platform/uv/uv_irq.c
@@ -131,7 +131,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
 		       unsigned long mmr_offset, int limit)
 {
 	const struct cpumask *eligible_cpu = cpumask_of(cpu);
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 	unsigned long mmr_value;
 	struct uv_IO_APIC_route_entry *entry;
 	int mmr_pnode, err;
@@ -148,7 +148,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
 	else
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 
-	set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
+	irq_set_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
 				      irq_name);
 
 	mmr_value = 0;
diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c
index 6320376..fe4cf82 100644
--- a/arch/x86/platform/visws/visws_quirks.c
+++ b/arch/x86/platform/visws/visws_quirks.c
@@ -569,11 +569,13 @@ out_unlock:
 static struct irqaction master_action = {
 	.handler =	piix4_master_intr,
 	.name =		"PIIX4-8259",
+	.flags =	IRQF_NO_THREAD,
 };
 
 static struct irqaction cascade_action = {
 	.handler = 	no_action,
 	.name =		"cascade",
+	.flags =	IRQF_NO_THREAD,
 };
 
 static inline void set_piix4_virtual_irq_type(void)
@@ -606,7 +608,7 @@ static void __init visws_pre_intr_init(void)
 			chip = &cobalt_irq_type;
 
 		if (chip)
-			set_irq_chip(i, chip);
+			irq_set_chip(i, chip);
 	}
 
 	setup_irq(CO_IRQ_8259, &master_action);
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 5b54892..1c7121b 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -38,7 +38,7 @@ config XEN_MAX_DOMAIN_MEMORY
 
 config XEN_SAVE_RESTORE
        bool
-       depends on XEN && PM
+       depends on XEN
        default y
 
 config XEN_DEBUG_FS
@@ -48,3 +48,11 @@ config XEN_DEBUG_FS
 	help
 	  Enable statistics output and various tuning options in debugfs.
 	  Enabling this option may incur a significant performance overhead.
+
+config XEN_DEBUG
+	bool "Enable Xen debug checks"
+	depends on XEN
+	default n
+	help
+	  Enable various WARN_ON checks in the Xen MMU code.
+	  Enabling this option WILL incur a significant performance overhead.
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 50542ef..49dbd78 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1284,15 +1284,14 @@ static int init_hvm_pv_info(int *major, int *minor)
 
 	xen_setup_features();
 
-	pv_info = xen_info;
-	pv_info.kernel_rpl = 0;
+	pv_info.name = "Xen HVM";
 
 	xen_domain_type = XEN_HVM_DOMAIN;
 
 	return 0;
 }
 
-void xen_hvm_init_shared_info(void)
+void __ref xen_hvm_init_shared_info(void)
 {
 	int cpu;
 	struct xen_add_to_physmap xatp;
@@ -1331,6 +1330,8 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
 	switch (action) {
 	case CPU_UP_PREPARE:
 		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+		if (xen_have_vector_callback)
+			xen_init_lock_cpu(cpu);
 		break;
 	default:
 		break;
@@ -1355,6 +1356,7 @@ static void __init xen_hvm_guest_init(void)
 
 	if (xen_feature(XENFEAT_hvm_callback_vector))
 		xen_have_vector_callback = 1;
+	xen_hvm_smp_init();
 	register_cpu_notifier(&xen_hvm_cpu_notifier);
 	xen_unplug_emulated_devices();
 	have_vcpu_info_placement = 0;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index f608942..c82df6c 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -46,6 +46,7 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/seq_file.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -78,8 +79,7 @@
 
 /*
  * Protects atomic reservation decrease/increase against concurrent increases.
- * Also protects non-atomic updates of current_pages and driver_pages, and
- * balloon lists.
+ * Also protects non-atomic updates of current_pages and balloon lists.
  */
 DEFINE_SPINLOCK(xen_reservation_lock);
 
@@ -416,8 +416,12 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
 	if (val & _PAGE_PRESENT) {
 		unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
 		pteval_t flags = val & PTE_FLAGS_MASK;
-		unsigned long mfn = pfn_to_mfn(pfn);
+		unsigned long mfn;
 
+		if (!xen_feature(XENFEAT_auto_translated_physmap))
+			mfn = get_phys_to_machine(pfn);
+		else
+			mfn = pfn;
 		/*
 		 * If there's no mfn for the pfn, then just create an
 		 * empty non-present pte.  Unfortunately this loses
@@ -427,8 +431,18 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
 		if (unlikely(mfn == INVALID_P2M_ENTRY)) {
 			mfn = 0;
 			flags = 0;
+		} else {
+			/*
+			 * Paramount to do this test _after_ the
+			 * INVALID_P2M_ENTRY as INVALID_P2M_ENTRY &
+			 * IDENTITY_FRAME_BIT resolves to true.
+			 */
+			mfn &= ~FOREIGN_FRAME_BIT;
+			if (mfn & IDENTITY_FRAME_BIT) {
+				mfn &= ~IDENTITY_FRAME_BIT;
+				flags |= _PAGE_IOMAP;
+			}
 		}
-
 		val = ((pteval_t)mfn << PAGE_SHIFT) | flags;
 	}
 
@@ -532,6 +546,41 @@ pte_t xen_make_pte(pteval_t pte)
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte);
 
+#ifdef CONFIG_XEN_DEBUG
+pte_t xen_make_pte_debug(pteval_t pte)
+{
+	phys_addr_t addr = (pte & PTE_PFN_MASK);
+	phys_addr_t other_addr;
+	bool io_page = false;
+	pte_t _pte;
+
+	if (pte & _PAGE_IOMAP)
+		io_page = true;
+
+	_pte = xen_make_pte(pte);
+
+	if (!addr)
+		return _pte;
+
+	if (io_page &&
+	    (xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
+		other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT;
+		WARN(addr != other_addr,
+			"0x%lx is using VM_IO, but it is 0x%lx!\n",
+			(unsigned long)addr, (unsigned long)other_addr);
+	} else {
+		pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP;
+		other_addr = (_pte.pte & PTE_PFN_MASK);
+		WARN((addr == other_addr) && (!io_page) && (!iomap_set),
+			"0x%lx is missing VM_IO (and wasn't fixed)!\n",
+			(unsigned long)addr);
+	}
+
+	return _pte;
+}
+PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug);
+#endif
+
 pgd_t xen_make_pgd(pgdval_t pgd)
 {
 	pgd = pte_pfn_to_mfn(pgd);
@@ -1438,10 +1487,12 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 	/*
 	 * If the new pfn is within the range of the newly allocated
 	 * kernel pagetable, and it isn't being mapped into an
-	 * early_ioremap fixmap slot, make sure it is RO.
+	 * early_ioremap fixmap slot as a freshly allocated page, make sure
+	 * it is RO.
 	 */
-	if (!is_early_ioremap_ptep(ptep) &&
-	    pfn >= e820_table_start && pfn < e820_table_end)
+	if (((!is_early_ioremap_ptep(ptep) &&
+			pfn >= pgt_buf_start && pfn < pgt_buf_end)) ||
+			(is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1)))
 		pte = pte_wrprotect(pte);
 
 	return pte;
@@ -1651,9 +1702,6 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
 		for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
 			pte_t pte;
 
-			if (pfn > max_pfn_mapped)
-				max_pfn_mapped = pfn;
-
 			if (!pte_none(pte_page[pteidx]))
 				continue;
 
@@ -1695,7 +1743,7 @@ static void convert_pfn_mfn(void *v)
 }
 
 /*
- * Set up the inital kernel pagetable.
+ * Set up the initial kernel pagetable.
  *
  * We can construct this by grafting the Xen provided pagetable into
  * head_64.S's preconstructed pagetables.  We copy the Xen L2's into
@@ -1711,6 +1759,12 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
 	pud_t *l3;
 	pmd_t *l2;
 
+	/* max_pfn_mapped is the last pfn mapped in the initial memory
+	 * mappings. Considering that on Xen after the kernel mappings we
+	 * have the mappings of some pages that don't exist in pfn space, we
+	 * set max_pfn_mapped to the last real pfn mapped. */
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
+
 	/* Zap identity mapping */
 	init_level4_pgt[0] = __pgd(0);
 
@@ -1815,9 +1869,7 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
 	initial_kernel_pmd =
 		extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
 
-	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
-				  xen_start_info->nr_pt_frames * PAGE_SIZE +
-				  512*1024);
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
 
 	kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
 	memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
@@ -1940,6 +1992,9 @@ __init void xen_ident_map_ISA(void)
 
 static __init void xen_post_allocator_init(void)
 {
+#ifdef CONFIG_XEN_DEBUG
+	pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
+#endif
 	pv_mmu_ops.set_pte = xen_set_pte;
 	pv_mmu_ops.set_pmd = xen_set_pmd;
 	pv_mmu_ops.set_pud = xen_set_pud;
@@ -2072,7 +2127,7 @@ static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order,
 			in_frames[i] = virt_to_mfn(vaddr);
 
 		MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0);
-		set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);
+		__set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);
 
 		if (out_frames)
 			out_frames[i] = virt_to_pfn(vaddr);
@@ -2351,6 +2406,18 @@ EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
 
 #ifdef CONFIG_XEN_DEBUG_FS
 
+static int p2m_dump_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, p2m_dump_show, NULL);
+}
+
+static const struct file_operations p2m_dump_fops = {
+	.open		= p2m_dump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static struct dentry *d_mmu_debug;
 
 static int __init xen_mmu_debugfs(void)
@@ -2406,6 +2473,7 @@ static int __init xen_mmu_debugfs(void)
 	debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug,
 			   &mmu_stats.prot_commit_batched);
 
+	debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
 	return 0;
 }
 fs_initcall(xen_mmu_debugfs);
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index fd12d7c..215a3ce 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -23,6 +23,129 @@
  * P2M_PER_PAGE depends on the architecture, as a mfn is always
  * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
  * 512 and 1024 entries respectively. 
+ *
+ * In short, these structures contain the Machine Frame Number (MFN) of the PFN.
+ *
+ * However not all entries are filled with MFNs. Specifically for all other
+ * leaf entries, or for the top  root, or middle one, for which there is a void
+ * entry, we assume it is  "missing". So (for example)
+ *  pfn_to_mfn(0x90909090)=INVALID_P2M_ENTRY.
+ *
+ * We also have the possibility of setting 1-1 mappings on certain regions, so
+ * that:
+ *  pfn_to_mfn(0xc0000)=0xc0000
+ *
+ * The benefit of this is, that we can assume for non-RAM regions (think
+ * PCI BARs, or ACPI spaces), we can create mappings easily b/c we
+ * get the PFN value to match the MFN.
+ *
+ * For this to work efficiently we have one new page p2m_identity and
+ * allocate (via reserved_brk) any other pages we need to cover the sides
+ * (1GB or 4MB boundary violations). All entries in p2m_identity are set to
+ * INVALID_P2M_ENTRY type (Xen toolstack only recognizes that and MFNs,
+ * no other fancy value).
+ *
+ * On lookup we spot that the entry points to p2m_identity and return the
+ * identity value instead of dereferencing and returning INVALID_P2M_ENTRY.
+ * If the entry points to an allocated page, we just proceed as before and
+ * return the PFN.  If the PFN has IDENTITY_FRAME_BIT set we unmask that in
+ * appropriate functions (pfn_to_mfn).
+ *
+ * The reason for having the IDENTITY_FRAME_BIT instead of just returning the
+ * PFN is that we could find ourselves where pfn_to_mfn(pfn)==pfn for a
+ * non-identity pfn. To protect ourselves against we elect to set (and get) the
+ * IDENTITY_FRAME_BIT on all identity mapped PFNs.
+ *
+ * This simplistic diagram is used to explain the more subtle piece of code.
+ * There is also a digram of the P2M at the end that can help.
+ * Imagine your E820 looking as so:
+ *
+ *                    1GB                                           2GB
+ * /-------------------+---------\/----\         /----------\    /---+-----\
+ * | System RAM        | Sys RAM ||ACPI|         | reserved |    | Sys RAM |
+ * \-------------------+---------/\----/         \----------/    \---+-----/
+ *                               ^- 1029MB                       ^- 2001MB
+ *
+ * [1029MB = 263424 (0x40500), 2001MB = 512256 (0x7D100),
+ *  2048MB = 524288 (0x80000)]
+ *
+ * And dom0_mem=max:3GB,1GB is passed in to the guest, meaning memory past 1GB
+ * is actually not present (would have to kick the balloon driver to put it in).
+ *
+ * When we are told to set the PFNs for identity mapping (see patch: "xen/setup:
+ * Set identity mapping for non-RAM E820 and E820 gaps.") we pass in the start
+ * of the PFN and the end PFN (263424 and 512256 respectively). The first step
+ * is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page
+ * covers 512^2 of page estate (1GB) and in case the start or end PFN is not
+ * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn
+ * to end pfn.  We reserve_brk top leaf pages if they are missing (means they
+ * point to p2m_mid_missing).
+ *
+ * With the E820 example above, 263424 is not 1GB aligned so we allocate a
+ * reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000.
+ * Each entry in the allocate page is "missing" (points to p2m_missing).
+ *
+ * Next stage is to determine if we need to do a more granular boundary check
+ * on the 4MB (or 2MB depending on architecture) off the start and end pfn's.
+ * We check if the start pfn and end pfn violate that boundary check, and if
+ * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer
+ * granularity of setting which PFNs are missing and which ones are identity.
+ * In our example 263424 and 512256 both fail the check so we reserve_brk two
+ * pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing"
+ * values) and assign them to p2m[1][2] and p2m[1][488] respectively.
+ *
+ * At this point we would at minimum reserve_brk one page, but could be up to
+ * three. Each call to set_phys_range_identity has at maximum a three page
+ * cost. If we were to query the P2M at this stage, all those entries from
+ * start PFN through end PFN (so 1029MB -> 2001MB) would return
+ * INVALID_P2M_ENTRY ("missing").
+ *
+ * The next step is to walk from the start pfn to the end pfn setting
+ * the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity.
+ * If we find that the middle leaf is pointing to p2m_missing we can swap it
+ * over to p2m_identity - this way covering 4MB (or 2MB) PFN space.  At this
+ * point we do not need to worry about boundary aligment (so no need to
+ * reserve_brk a middle page, figure out which PFNs are "missing" and which
+ * ones are identity), as that has been done earlier.  If we find that the
+ * middle leaf is not occupied by p2m_identity or p2m_missing, we dereference
+ * that page (which covers 512 PFNs) and set the appropriate PFN with
+ * IDENTITY_FRAME_BIT. In our example 263424 and 512256 end up there, and we
+ * set from p2m[1][2][256->511] and p2m[1][488][0->256] with
+ * IDENTITY_FRAME_BIT set.
+ *
+ * All other regions that are void (or not filled) either point to p2m_missing
+ * (considered missing) or have the default value of INVALID_P2M_ENTRY (also
+ * considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511]
+ * contain the INVALID_P2M_ENTRY value and are considered "missing."
+ *
+ * This is what the p2m ends up looking (for the E820 above) with this
+ * fabulous drawing:
+ *
+ *    p2m         /--------------\
+ *  /-----\       | &mfn_list[0],|                           /-----------------\
+ *  |  0  |------>| &mfn_list[1],|    /---------------\      | ~0, ~0, ..      |
+ *  |-----|       |  ..., ~0, ~0 |    | ~0, ~0, [x]---+----->| IDENTITY [@256] |
+ *  |  1  |---\   \--------------/    | [p2m_identity]+\     | IDENTITY [@257] |
+ *  |-----|    \                      | [p2m_identity]+\\    | ....            |
+ *  |  2  |--\  \-------------------->|  ...          | \\   \----------------/
+ *  |-----|   \                       \---------------/  \\
+ *  |  3  |\   \                                          \\  p2m_identity
+ *  |-----| \   \-------------------->/---------------\   /-----------------\
+ *  | ..  +->+                        | [p2m_identity]+-->| ~0, ~0, ~0, ... |
+ *  \-----/ /                         | [p2m_identity]+-->| ..., ~0         |
+ *         / /---------------\        | ....          |   \-----------------/
+ *        /  | IDENTITY[@0]  |      /-+-[x], ~0, ~0.. |
+ *       /   | IDENTITY[@256]|<----/  \---------------/
+ *      /    | ~0, ~0, ....  |
+ *     |     \---------------/
+ *     |
+ *     p2m_missing             p2m_missing
+ * /------------------\     /------------\
+ * | [p2m_mid_missing]+---->| ~0, ~0, ~0 |
+ * | [p2m_mid_missing]+---->| ..., ~0    |
+ * \------------------/     \------------/
+ *
+ * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT)
  */
 
 #include <linux/init.h>
@@ -30,6 +153,7 @@
 #include <linux/list.h>
 #include <linux/hash.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 
 #include <asm/cache.h>
 #include <asm/setup.h>
@@ -59,9 +183,15 @@ static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
 
+static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
+
 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 
+/* We might hit two boundary violations at the start and end, at max each
+ * boundary violation will require three middle nodes. */
+RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
+
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
 	BUG_ON(pfn >= MAX_P2M_PFN);
@@ -136,7 +266,7 @@ static void p2m_init(unsigned long *p2m)
  * - After resume we're called from within stop_machine, but the mfn
  *   tree should alreay be completely allocated.
  */
-void xen_build_mfn_list_list(void)
+void __ref xen_build_mfn_list_list(void)
 {
 	unsigned long pfn;
 
@@ -221,6 +351,9 @@ void __init xen_build_dynamic_phys_to_machine(void)
 	p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
 	p2m_top_init(p2m_top);
 
+	p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_init(p2m_identity);
+
 	/*
 	 * The domain builder gives us a pre-constructed p2m array in
 	 * mfn_list for all the pages initially given to us, so we just
@@ -266,6 +399,14 @@ unsigned long get_phys_to_machine(unsigned long pfn)
 	mididx = p2m_mid_index(pfn);
 	idx = p2m_index(pfn);
 
+	/*
+	 * The INVALID_P2M_ENTRY is filled in both p2m_*identity
+	 * and in p2m_*missing, so returning the INVALID_P2M_ENTRY
+	 * would be wrong.
+	 */
+	if (p2m_top[topidx][mididx] == p2m_identity)
+		return IDENTITY_FRAME(pfn);
+
 	return p2m_top[topidx][mididx][idx];
 }
 EXPORT_SYMBOL_GPL(get_phys_to_machine);
@@ -335,9 +476,11 @@ static bool alloc_p2m(unsigned long pfn)
 			p2m_top_mfn_p[topidx] = mid_mfn;
 	}
 
-	if (p2m_top[topidx][mididx] == p2m_missing) {
+	if (p2m_top[topidx][mididx] == p2m_identity ||
+	    p2m_top[topidx][mididx] == p2m_missing) {
 		/* p2m leaf page is missing */
 		unsigned long *p2m;
+		unsigned long *p2m_orig = p2m_top[topidx][mididx];
 
 		p2m = alloc_p2m_page();
 		if (!p2m)
@@ -345,7 +488,7 @@ static bool alloc_p2m(unsigned long pfn)
 
 		p2m_init(p2m);
 
-		if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
+		if (cmpxchg(&mid[mididx], p2m_orig, p2m) != p2m_orig)
 			free_p2m_page(p2m);
 		else
 			mid_mfn[mididx] = virt_to_mfn(p2m);
@@ -354,11 +497,91 @@ static bool alloc_p2m(unsigned long pfn)
 	return true;
 }
 
+bool __early_alloc_p2m(unsigned long pfn)
+{
+	unsigned topidx, mididx, idx;
+
+	topidx = p2m_top_index(pfn);
+	mididx = p2m_mid_index(pfn);
+	idx = p2m_index(pfn);
+
+	/* Pfff.. No boundary cross-over, lets get out. */
+	if (!idx)
+		return false;
+
+	WARN(p2m_top[topidx][mididx] == p2m_identity,
+		"P2M[%d][%d] == IDENTITY, should be MISSING (or alloced)!\n",
+		topidx, mididx);
+
+	/*
+	 * Could be done by xen_build_dynamic_phys_to_machine..
+	 */
+	if (p2m_top[topidx][mididx] != p2m_missing)
+		return false;
+
+	/* Boundary cross-over for the edges: */
+	if (idx) {
+		unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE);
+
+		p2m_init(p2m);
+
+		p2m_top[topidx][mididx] = p2m;
+
+	}
+	return idx != 0;
+}
+unsigned long set_phys_range_identity(unsigned long pfn_s,
+				      unsigned long pfn_e)
+{
+	unsigned long pfn;
+
+	if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN))
+		return 0;
+
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return pfn_e - pfn_s;
+
+	if (pfn_s > pfn_e)
+		return 0;
+
+	for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1));
+		pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE));
+		pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
+	{
+		unsigned topidx = p2m_top_index(pfn);
+		if (p2m_top[topidx] == p2m_mid_missing) {
+			unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
+
+			p2m_mid_init(mid);
+
+			p2m_top[topidx] = mid;
+		}
+	}
+
+	__early_alloc_p2m(pfn_s);
+	__early_alloc_p2m(pfn_e);
+
+	for (pfn = pfn_s; pfn < pfn_e; pfn++)
+		if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)))
+			break;
+
+	if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
+		"Identity mapping failed. We are %ld short of 1-1 mappings!\n",
+		(pfn_e - pfn_s) - (pfn - pfn_s)))
+		printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn);
+
+	return pfn - pfn_s;
+}
+
 /* Try to install p2m mapping; fail if intermediate bits missing */
 bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
 	unsigned topidx, mididx, idx;
 
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+		return true;
+	}
 	if (unlikely(pfn >= MAX_P2M_PFN)) {
 		BUG_ON(mfn != INVALID_P2M_ENTRY);
 		return true;
@@ -368,6 +591,21 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 	mididx = p2m_mid_index(pfn);
 	idx = p2m_index(pfn);
 
+	/* For sparse holes were the p2m leaf has real PFN along with
+	 * PCI holes, stick in the PFN as the MFN value.
+	 */
+	if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) {
+		if (p2m_top[topidx][mididx] == p2m_identity)
+			return true;
+
+		/* Swap over from MISSING to IDENTITY if needed. */
+		if (p2m_top[topidx][mididx] == p2m_missing) {
+			WARN_ON(cmpxchg(&p2m_top[topidx][mididx], p2m_missing,
+				p2m_identity) != p2m_missing);
+			return true;
+		}
+	}
+
 	if (p2m_top[topidx][mididx] == p2m_missing)
 		return mfn == INVALID_P2M_ENTRY;
 
@@ -378,11 +616,6 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 
 bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
-	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
-		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
-		return true;
-	}
-
 	if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
 		if (!alloc_p2m(pfn))
 			return false;
@@ -421,7 +654,7 @@ int m2p_add_override(unsigned long mfn, struct page *page)
 {
 	unsigned long flags;
 	unsigned long pfn;
-	unsigned long address;
+	unsigned long uninitialized_var(address);
 	unsigned level;
 	pte_t *ptep = NULL;
 
@@ -455,7 +688,7 @@ int m2p_remove_override(struct page *page)
 	unsigned long flags;
 	unsigned long mfn;
 	unsigned long pfn;
-	unsigned long address;
+	unsigned long uninitialized_var(address);
 	unsigned level;
 	pte_t *ptep = NULL;
 
@@ -520,3 +753,80 @@ unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn)
 	return ret;
 }
 EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
+
+#ifdef CONFIG_XEN_DEBUG_FS
+
+int p2m_dump_show(struct seq_file *m, void *v)
+{
+	static const char * const level_name[] = { "top", "middle",
+						"entry", "abnormal" };
+	static const char * const type_name[] = { "identity", "missing",
+						"pfn", "abnormal"};
+#define TYPE_IDENTITY 0
+#define TYPE_MISSING 1
+#define TYPE_PFN 2
+#define TYPE_UNKNOWN 3
+	unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
+	unsigned int uninitialized_var(prev_level);
+	unsigned int uninitialized_var(prev_type);
+
+	if (!p2m_top)
+		return 0;
+
+	for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn++) {
+		unsigned topidx = p2m_top_index(pfn);
+		unsigned mididx = p2m_mid_index(pfn);
+		unsigned idx = p2m_index(pfn);
+		unsigned lvl, type;
+
+		lvl = 4;
+		type = TYPE_UNKNOWN;
+		if (p2m_top[topidx] == p2m_mid_missing) {
+			lvl = 0; type = TYPE_MISSING;
+		} else if (p2m_top[topidx] == NULL) {
+			lvl = 0; type = TYPE_UNKNOWN;
+		} else if (p2m_top[topidx][mididx] == NULL) {
+			lvl = 1; type = TYPE_UNKNOWN;
+		} else if (p2m_top[topidx][mididx] == p2m_identity) {
+			lvl = 1; type = TYPE_IDENTITY;
+		} else if (p2m_top[topidx][mididx] == p2m_missing) {
+			lvl = 1; type = TYPE_MISSING;
+		} else if (p2m_top[topidx][mididx][idx] == 0) {
+			lvl = 2; type = TYPE_UNKNOWN;
+		} else if (p2m_top[topidx][mididx][idx] == IDENTITY_FRAME(pfn)) {
+			lvl = 2; type = TYPE_IDENTITY;
+		} else if (p2m_top[topidx][mididx][idx] == INVALID_P2M_ENTRY) {
+			lvl = 2; type = TYPE_MISSING;
+		} else if (p2m_top[topidx][mididx][idx] == pfn) {
+			lvl = 2; type = TYPE_PFN;
+		} else if (p2m_top[topidx][mididx][idx] != pfn) {
+			lvl = 2; type = TYPE_PFN;
+		}
+		if (pfn == 0) {
+			prev_level = lvl;
+			prev_type = type;
+		}
+		if (pfn == MAX_DOMAIN_PAGES-1) {
+			lvl = 3;
+			type = TYPE_UNKNOWN;
+		}
+		if (prev_type != type) {
+			seq_printf(m, " [0x%lx->0x%lx] %s\n",
+				prev_pfn_type, pfn, type_name[prev_type]);
+			prev_pfn_type = pfn;
+			prev_type = type;
+		}
+		if (prev_level != lvl) {
+			seq_printf(m, " [0x%lx->0x%lx] level %s\n",
+				prev_pfn_level, pfn, level_name[prev_level]);
+			prev_pfn_level = pfn;
+			prev_level = lvl;
+		}
+	}
+	return 0;
+#undef TYPE_IDENTITY
+#undef TYPE_MISSING
+#undef TYPE_PFN
+#undef TYPE_UNKNOWN
+}
+#endif
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index a8a66a5..fa0269a 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -52,6 +52,8 @@ phys_addr_t xen_extra_mem_start, xen_extra_mem_size;
 
 static __init void xen_add_extra_mem(unsigned long pages)
 {
+	unsigned long pfn;
+
 	u64 size = (u64)pages * PAGE_SIZE;
 	u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
 
@@ -66,6 +68,9 @@ static __init void xen_add_extra_mem(unsigned long pages)
 	xen_extra_mem_size += size;
 
 	xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
+
+	for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++)
+		__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 }
 
 static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
@@ -104,7 +109,7 @@ static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
 		WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n",
 		     start, end, ret);
 		if (ret == 1) {
-			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+			__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 			len++;
 		}
 	}
@@ -138,12 +143,55 @@ static unsigned long __init xen_return_unused_memory(unsigned long max_pfn,
 	return released;
 }
 
+static unsigned long __init xen_set_identity(const struct e820entry *list,
+					     ssize_t map_size)
+{
+	phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS;
+	phys_addr_t start_pci = last;
+	const struct e820entry *entry;
+	unsigned long identity = 0;
+	int i;
+
+	for (i = 0, entry = list; i < map_size; i++, entry++) {
+		phys_addr_t start = entry->addr;
+		phys_addr_t end = start + entry->size;
+
+		if (start < last)
+			start = last;
+
+		if (end <= start)
+			continue;
+
+		/* Skip over the 1MB region. */
+		if (last > end)
+			continue;
+
+		if (entry->type == E820_RAM) {
+			if (start > start_pci)
+				identity += set_phys_range_identity(
+						PFN_UP(start_pci), PFN_DOWN(start));
+
+			/* Without saving 'last' we would gooble RAM too
+			 * at the end of the loop. */
+			last = end;
+			start_pci = end;
+			continue;
+		}
+		start_pci = min(start, start_pci);
+		last = end;
+	}
+	if (last > start_pci)
+		identity += set_phys_range_identity(
+					PFN_UP(start_pci), PFN_DOWN(last));
+	return identity;
+}
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
 char * __init xen_memory_setup(void)
 {
 	static struct e820entry map[E820MAX] __initdata;
+	static struct e820entry map_raw[E820MAX] __initdata;
 
 	unsigned long max_pfn = xen_start_info->nr_pages;
 	unsigned long long mem_end;
@@ -151,6 +199,7 @@ char * __init xen_memory_setup(void)
 	struct xen_memory_map memmap;
 	unsigned long extra_pages = 0;
 	unsigned long extra_limit;
+	unsigned long identity_pages = 0;
 	int i;
 	int op;
 
@@ -176,6 +225,7 @@ char * __init xen_memory_setup(void)
 	}
 	BUG_ON(rc);
 
+	memcpy(map_raw, map, sizeof(map));
 	e820.nr_map = 0;
 	xen_extra_mem_start = mem_end;
 	for (i = 0; i < memmap.nr_entries; i++) {
@@ -194,6 +244,15 @@ char * __init xen_memory_setup(void)
 			end -= delta;
 
 			extra_pages += PFN_DOWN(delta);
+			/*
+			 * Set RAM below 4GB that is not for us to be unusable.
+			 * This prevents "System RAM" address space from being
+			 * used as potential resource for I/O address (happens
+			 * when 'allocate_resource' is called).
+			 */
+			if (delta &&
+				(xen_initial_domain() && end < 0x100000000ULL))
+				e820_add_region(end, delta, E820_UNUSABLE);
 		}
 
 		if (map[i].size > 0 && end > xen_extra_mem_start)
@@ -251,6 +310,13 @@ char * __init xen_memory_setup(void)
 
 	xen_add_extra_mem(extra_pages);
 
+	/*
+	 * Set P2M for all non-RAM pages and E820 gaps to be identity
+	 * type PFNs. We supply it with the non-sanitized version
+	 * of the E820.
+	 */
+	identity_pages = xen_set_identity(map_raw, memmap.nr_entries);
+	printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages);
 	return "Xen";
 }
 
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 72a4c79..3061244 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -509,3 +509,41 @@ void __init xen_smp_init(void)
 	xen_fill_possible_map();
 	xen_init_spinlocks();
 }
+
+static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
+{
+	native_smp_prepare_cpus(max_cpus);
+	WARN_ON(xen_smp_intr_init(0));
+
+	if (!xen_have_vector_callback)
+		return;
+	xen_init_lock_cpu(0);
+	xen_init_spinlocks();
+}
+
+static int __cpuinit xen_hvm_cpu_up(unsigned int cpu)
+{
+	int rc;
+	rc = native_cpu_up(cpu);
+	WARN_ON (xen_smp_intr_init(cpu));
+	return rc;
+}
+
+static void xen_hvm_cpu_die(unsigned int cpu)
+{
+	unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
+	unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
+	unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
+	unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
+	native_cpu_die(cpu);
+}
+
+void __init xen_hvm_smp_init(void)
+{
+	smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
+	smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
+	smp_ops.cpu_up = xen_hvm_cpu_up;
+	smp_ops.cpu_die = xen_hvm_cpu_die;
+	smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
+	smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
+}
diff --git a/arch/x86/xen/suspend.c b/arch/x86/xen/suspend.c
index 9bbd63a..45329c8 100644
--- a/arch/x86/xen/suspend.c
+++ b/arch/x86/xen/suspend.c
@@ -12,7 +12,7 @@
 #include "xen-ops.h"
 #include "mmu.h"
 
-void xen_pre_suspend(void)
+void xen_arch_pre_suspend(void)
 {
 	xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
 	xen_start_info->console.domU.mfn =
@@ -26,8 +26,9 @@ void xen_pre_suspend(void)
 		BUG();
 }
 
-void xen_hvm_post_suspend(int suspend_cancelled)
+void xen_arch_hvm_post_suspend(int suspend_cancelled)
 {
+#ifdef CONFIG_XEN_PVHVM
 	int cpu;
 	xen_hvm_init_shared_info();
 	xen_callback_vector();
@@ -37,9 +38,10 @@ void xen_hvm_post_suspend(int suspend_cancelled)
 			xen_setup_runstate_info(cpu);
 		}
 	}
+#endif
 }
 
-void xen_post_suspend(int suspend_cancelled)
+void xen_arch_post_suspend(int suspend_cancelled)
 {
 	xen_build_mfn_list_list();
 
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 067759e..2e2d370 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -397,7 +397,9 @@ void xen_setup_timer(int cpu)
 		name = "<timer kasprintf failed>";
 
 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
-				      IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER,
+				      IRQF_DISABLED|IRQF_PERCPU|
+				      IRQF_NOBALANCING|IRQF_TIMER|
+				      IRQF_FORCE_RESUME,
 				      name, NULL);
 
 	evt = &per_cpu(xen_clock_events, cpu);
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 1a5ff24..aaa7291 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -28,9 +28,9 @@ ENTRY(startup_xen)
 	__FINIT
 
 .pushsection .text
-	.align PAGE_SIZE_asm
+	.align PAGE_SIZE
 ENTRY(hypercall_page)
-	.skip PAGE_SIZE_asm
+	.skip PAGE_SIZE
 .popsection
 
 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 9d41bf9..3112f55 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -64,10 +64,12 @@ void xen_setup_vcpu_info_placement(void);
 
 #ifdef CONFIG_SMP
 void xen_smp_init(void);
+void __init xen_hvm_smp_init(void);
 
 extern cpumask_var_t xen_cpu_initialized_map;
 #else
 static inline void xen_smp_init(void) {}
+static inline void xen_hvm_smp_init(void) {}
 #endif
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
index 40aa55b..70fd145 100644
--- a/arch/xtensa/boot/Makefile
+++ b/arch/xtensa/boot/Makefile
@@ -14,7 +14,7 @@ HOSTFLAGS	+= -Iarch/$(ARCH)/boot/include
 
 BIG_ENDIAN	:= $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
 
-export EXTRA_CFLAGS
+export ccflags-y
 export BIG_ENDIAN
 
 subdir-y	:= lib
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
index d3d2aa2..ad8952e 100644
--- a/arch/xtensa/boot/lib/Makefile
+++ b/arch/xtensa/boot/lib/Makefile
@@ -6,7 +6,7 @@ zlib	:= inffast.c inflate.c inftrees.c
 
 lib-y	+= $(zlib:.c=.o) zmem.o
 
-EXTRA_CFLAGS	+= -Ilib/zlib_inflate
+ccflags-y	:= -Ilib/zlib_inflate
 
 quiet_cmd_copy_zlib = COPY    $@
       cmd_copy_zlib = cat $< > $@
diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig
index 095cd80..42b7feb 100644
--- a/arch/xtensa/configs/s6105_defconfig
+++ b/arch/xtensa/configs/s6105_defconfig
@@ -598,7 +598,7 @@ CONFIG_DEBUG_NOMMU_REGIONS=y
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 
 #
diff --git a/arch/xtensa/include/asm/ioctls.h b/arch/xtensa/include/asm/ioctls.h
index ccf1800..fd1d136 100644
--- a/arch/xtensa/include/asm/ioctls.h
+++ b/arch/xtensa/include/asm/ioctls.h
@@ -100,6 +100,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	_IO('T', 0x37)
 
 #define TIOCSERCONFIG	_IO('T', 83)
 #define TIOCSERGWILD	_IOR('T', 84,  int)
diff --git a/arch/xtensa/include/asm/rwsem.h b/arch/xtensa/include/asm/rwsem.h
index e39edf5..249619e 100644
--- a/arch/xtensa/include/asm/rwsem.h
+++ b/arch/xtensa/include/asm/rwsem.h
@@ -17,44 +17,12 @@
 #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
 #endif
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	signed long		count;
 #define RWSEM_UNLOCKED_VALUE		0x00000000
 #define RWSEM_ACTIVE_BIAS		0x00000001
 #define RWSEM_ACTIVE_MASK		0x0000ffff
 #define RWSEM_WAITING_BIAS		(-0x00010000)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-};
-
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	  LIST_HEAD_INIT((name).wait_list) }
-
-#define DECLARE_RWSEM(name)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
 
 /*
  * lock for reading
@@ -160,9 +128,4 @@ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif	/* _XTENSA_RWSEM_H */
diff --git a/arch/xtensa/include/asm/types.h b/arch/xtensa/include/asm/types.h
index c89569a..b1c981e 100644
--- a/arch/xtensa/include/asm/types.h
+++ b/arch/xtensa/include/asm/types.h
@@ -32,10 +32,6 @@ typedef unsigned short umode_t;
 
 #define BITS_PER_LONG 32
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
 #endif	/* __KERNEL__ */
 #endif
 
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 19df764..f3e5eb4 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -96,16 +96,12 @@ again:
 		update_process_times(user_mode(get_irq_regs()));
 #endif
 
-		write_seqlock(&xtime_lock);
-
-		do_timer(1); /* Linux handler in kernel/timer.c */
+		xtime_update(1); /* Linux handler in kernel/time/timekeeping */
 
 		/* Note that writing CCOMPARE clears the interrupt. */
 
 		next += CCOUNT_PER_JIFFY;
 		set_linux_timer(next);
-
-		write_sequnlock(&xtime_lock);
 	}
 
 	/* Allow platform to do something useful (Wdog). */
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index 9b52615..a282006 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -155,7 +155,7 @@ SECTIONS
     INIT_RAM_FS
   }
 
-  PERCPU(PAGE_SIZE)
+  PERCPU(XCHAL_ICACHE_LINESIZE, PAGE_SIZE)
 
   /* We need this dummy segment here */
 
diff --git a/block/blk-core.c b/block/blk-core.c
index 518dd42..a63336d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2045,9 +2045,26 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
 
 	if (error && req->cmd_type == REQ_TYPE_FS &&
 	    !(req->cmd_flags & REQ_QUIET)) {
-		printk(KERN_ERR "end_request: I/O error, dev %s, sector %llu\n",
-				req->rq_disk ? req->rq_disk->disk_name : "?",
-				(unsigned long long)blk_rq_pos(req));
+		char *error_type;
+
+		switch (error) {
+		case -ENOLINK:
+			error_type = "recoverable transport";
+			break;
+		case -EREMOTEIO:
+			error_type = "critical target";
+			break;
+		case -EBADE:
+			error_type = "critical nexus";
+			break;
+		case -EIO:
+		default:
+			error_type = "I/O";
+			break;
+		}
+		printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
+		       error_type, req->rq_disk ? req->rq_disk->disk_name : "?",
+		       (unsigned long long)blk_rq_pos(req));
 	}
 
 	blk_account_io_completion(req, nr_bytes);
diff --git a/crypto/Makefile b/crypto/Makefile
index e9a399c..ce5a813 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -78,7 +78,7 @@ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
 obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
-obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
+obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index a854df2..fdc67d3 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -141,8 +141,7 @@ err:
 
 	if (walk->iv != req->info)
 		memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize);
-	if (walk->iv_buffer)
-		kfree(walk->iv_buffer);
+	kfree(walk->iv_buffer);
 
 	return err;
 }
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
new file mode 100644
index 0000000..136b68b
--- /dev/null
+++ b/crypto/authencesn.c
@@ -0,0 +1,835 @@
+/*
+ * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
+ *                 derived from authenc.c
+ *
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.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 <crypto/aead.h>
+#include <crypto/internal/hash.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/authenc.h>
+#include <crypto/scatterwalk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtnetlink.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct authenc_esn_instance_ctx {
+	struct crypto_ahash_spawn auth;
+	struct crypto_skcipher_spawn enc;
+};
+
+struct crypto_authenc_esn_ctx {
+	unsigned int reqoff;
+	struct crypto_ahash *auth;
+	struct crypto_ablkcipher *enc;
+};
+
+struct authenc_esn_request_ctx {
+	unsigned int cryptlen;
+	unsigned int headlen;
+	unsigned int trailen;
+	struct scatterlist *sg;
+	struct scatterlist hsg[2];
+	struct scatterlist tsg[1];
+	struct scatterlist cipher[2];
+	crypto_completion_t complete;
+	crypto_completion_t update_complete;
+	crypto_completion_t update_complete2;
+	char tail[];
+};
+
+static void authenc_esn_request_complete(struct aead_request *req, int err)
+{
+	if (err != -EINPROGRESS)
+		aead_request_complete(req, err);
+}
+
+static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
+				     unsigned int keylen)
+{
+	unsigned int authkeylen;
+	unsigned int enckeylen;
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct crypto_ahash *auth = ctx->auth;
+	struct crypto_ablkcipher *enc = ctx->enc;
+	struct rtattr *rta = (void *)key;
+	struct crypto_authenc_key_param *param;
+	int err = -EINVAL;
+
+	if (!RTA_OK(rta, keylen))
+		goto badkey;
+	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+		goto badkey;
+	if (RTA_PAYLOAD(rta) < sizeof(*param))
+		goto badkey;
+
+	param = RTA_DATA(rta);
+	enckeylen = be32_to_cpu(param->enckeylen);
+
+	key += RTA_ALIGN(rta->rta_len);
+	keylen -= RTA_ALIGN(rta->rta_len);
+
+	if (keylen < enckeylen)
+		goto badkey;
+
+	authkeylen = keylen - enckeylen;
+
+	crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
+	crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
+				     CRYPTO_TFM_REQ_MASK);
+	err = crypto_ahash_setkey(auth, key, authkeylen);
+	crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
+					   CRYPTO_TFM_RES_MASK);
+
+	if (err)
+		goto out;
+
+	crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
+	crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
+	crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
+					   CRYPTO_TFM_RES_MASK);
+
+out:
+	return err;
+
+badkey:
+	crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	goto out;
+}
+
+static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
+						int err)
+{
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
+				areq_ctx->cryptlen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->update_complete2, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
+				 areq_ctx->cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
+						 int err)
+{
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
+				 areq_ctx->cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+
+static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
+					 int err)
+{
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+
+	if (err)
+		goto out;
+
+	scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
+				 areq_ctx->cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+
+out:
+	aead_request_complete(req, err);
+}
+
+
+static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
+						 int err)
+{
+	u8 *ihash;
+	unsigned int authsize;
+	struct ablkcipher_request *abreq;
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	unsigned int cryptlen = req->cryptlen;
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
+				areq_ctx->cryptlen);
+
+	ahash_request_set_callback(ahreq,
+				   aead_request_flags(req) &
+				   CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->update_complete2, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	cryptlen -= authsize;
+	ihash = ahreq->result + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+
+	err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+	if (err)
+		goto out;
+
+	abreq = aead_request_ctx(req);
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst,
+				     cryptlen, req->iv);
+
+	err = crypto_ablkcipher_decrypt(abreq);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
+						  int err)
+{
+	u8 *ihash;
+	unsigned int authsize;
+	struct ablkcipher_request *abreq;
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	unsigned int cryptlen = req->cryptlen;
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	cryptlen -= authsize;
+	ihash = ahreq->result + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+
+	err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+	if (err)
+		goto out;
+
+	abreq = aead_request_ctx(req);
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst,
+				     cryptlen, req->iv);
+
+	err = crypto_ablkcipher_decrypt(abreq);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+
+static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
+					  int err)
+{
+	u8 *ihash;
+	unsigned int authsize;
+	struct ablkcipher_request *abreq;
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	unsigned int cryptlen = req->cryptlen;
+
+	if (err)
+		goto out;
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	cryptlen -= authsize;
+	ihash = ahreq->result + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+
+	err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+	if (err)
+		goto out;
+
+	abreq = aead_request_ctx(req);
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst,
+				     cryptlen, req->iv);
+
+	err = crypto_ablkcipher_decrypt(abreq);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
+				    unsigned int flags)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct crypto_ahash *auth = ctx->auth;
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	u8 *hash = areq_ctx->tail;
+	int err;
+
+	hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
+			    crypto_ahash_alignmask(auth) + 1);
+
+	ahash_request_set_tfm(ahreq, auth);
+
+	err = crypto_ahash_init(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
+				   areq_ctx->update_complete, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
+				   areq_ctx->update_complete2, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	return hash;
+}
+
+static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
+				     unsigned int flags)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct scatterlist *dst = req->dst;
+	struct scatterlist *assoc = req->assoc;
+	struct scatterlist *cipher = areq_ctx->cipher;
+	struct scatterlist *hsg = areq_ctx->hsg;
+	struct scatterlist *tsg = areq_ctx->tsg;
+	struct scatterlist *assoc1;
+	struct scatterlist *assoc2;
+	unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
+	unsigned int cryptlen = req->cryptlen;
+	struct page *dstp;
+	u8 *vdst;
+	u8 *hash;
+
+	dstp = sg_page(dst);
+	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
+
+	if (ivsize) {
+		sg_init_table(cipher, 2);
+		sg_set_buf(cipher, iv, ivsize);
+		scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
+		dst = cipher;
+		cryptlen += ivsize;
+	}
+
+	if (sg_is_last(assoc))
+		return -EINVAL;
+
+	assoc1 = assoc + 1;
+	if (sg_is_last(assoc1))
+		return -EINVAL;
+
+	assoc2 = assoc + 2;
+	if (!sg_is_last(assoc2))
+		return -EINVAL;
+
+	sg_init_table(hsg, 2);
+	sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
+	sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+
+	sg_init_table(tsg, 1);
+	sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+
+	areq_ctx->cryptlen = cryptlen;
+	areq_ctx->headlen = assoc->length + assoc2->length;
+	areq_ctx->trailen = assoc1->length;
+	areq_ctx->sg = dst;
+
+	areq_ctx->complete = authenc_esn_geniv_ahash_done;
+	areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done;
+	areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2;
+
+	hash = crypto_authenc_esn_ahash(req, flags);
+	if (IS_ERR(hash))
+		return PTR_ERR(hash);
+
+	scatterwalk_map_and_copy(hash, dst, cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+	return 0;
+}
+
+
+static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
+					    int err)
+{
+	struct aead_request *areq = req->data;
+
+	if (!err) {
+		struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq);
+		struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+		struct ablkcipher_request *abreq = aead_request_ctx(areq);
+		u8 *iv = (u8 *)(abreq + 1) +
+			 crypto_ablkcipher_reqsize(ctx->enc);
+
+		err = crypto_authenc_esn_genicv(areq, iv, 0);
+	}
+
+	authenc_esn_request_complete(areq, err);
+}
+
+static int crypto_authenc_esn_encrypt(struct aead_request *req)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct crypto_ablkcipher *enc = ctx->enc;
+	struct scatterlist *dst = req->dst;
+	unsigned int cryptlen = req->cryptlen;
+	struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+						    + ctx->reqoff);
+	u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
+	int err;
+
+	ablkcipher_request_set_tfm(abreq, enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					crypto_authenc_esn_encrypt_done, req);
+	ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
+
+	memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
+
+	err = crypto_ablkcipher_encrypt(abreq);
+	if (err)
+		return err;
+
+	return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+}
+
+static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
+					       int err)
+{
+	struct aead_request *areq = req->data;
+
+	if (!err) {
+		struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
+
+		err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
+	}
+
+	authenc_esn_request_complete(areq, err);
+}
+
+static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
+{
+	struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct aead_request *areq = &req->areq;
+	struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
+	u8 *iv = req->giv;
+	int err;
+
+	skcipher_givcrypt_set_tfm(greq, ctx->enc);
+	skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
+				       crypto_authenc_esn_givencrypt_done, areq);
+	skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
+				    areq->iv);
+	skcipher_givcrypt_set_giv(greq, iv, req->seq);
+
+	err = crypto_skcipher_givencrypt(greq);
+	if (err)
+		return err;
+
+	return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+}
+
+static int crypto_authenc_esn_verify(struct aead_request *req)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	u8 *ohash;
+	u8 *ihash;
+	unsigned int authsize;
+
+	areq_ctx->complete = authenc_esn_verify_ahash_done;
+	areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
+
+	ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
+	if (IS_ERR(ohash))
+		return PTR_ERR(ohash);
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	ihash = ohash + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+	return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
+}
+
+static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
+				      unsigned int cryptlen)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct scatterlist *src = req->src;
+	struct scatterlist *assoc = req->assoc;
+	struct scatterlist *cipher = areq_ctx->cipher;
+	struct scatterlist *hsg = areq_ctx->hsg;
+	struct scatterlist *tsg = areq_ctx->tsg;
+	struct scatterlist *assoc1;
+	struct scatterlist *assoc2;
+	unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
+	struct page *srcp;
+	u8 *vsrc;
+
+	srcp = sg_page(src);
+	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
+
+	if (ivsize) {
+		sg_init_table(cipher, 2);
+		sg_set_buf(cipher, iv, ivsize);
+		scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
+		src = cipher;
+		cryptlen += ivsize;
+	}
+
+	if (sg_is_last(assoc))
+		return -EINVAL;
+
+	assoc1 = assoc + 1;
+	if (sg_is_last(assoc1))
+		return -EINVAL;
+
+	assoc2 = assoc + 2;
+	if (!sg_is_last(assoc2))
+		return -EINVAL;
+
+	sg_init_table(hsg, 2);
+	sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
+	sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+
+	sg_init_table(tsg, 1);
+	sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+
+	areq_ctx->cryptlen = cryptlen;
+	areq_ctx->headlen = assoc->length + assoc2->length;
+	areq_ctx->trailen = assoc1->length;
+	areq_ctx->sg = src;
+
+	areq_ctx->complete = authenc_esn_verify_ahash_done;
+	areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
+	areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2;
+
+	return crypto_authenc_esn_verify(req);
+}
+
+static int crypto_authenc_esn_decrypt(struct aead_request *req)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct ablkcipher_request *abreq = aead_request_ctx(req);
+	unsigned int cryptlen = req->cryptlen;
+	unsigned int authsize = crypto_aead_authsize(authenc_esn);
+	u8 *iv = req->iv;
+	int err;
+
+	if (cryptlen < authsize)
+		return -EINVAL;
+	cryptlen -= authsize;
+
+	err = crypto_authenc_esn_iverify(req, iv, cryptlen);
+	if (err)
+		return err;
+
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
+
+	return crypto_ablkcipher_decrypt(abreq);
+}
+
+static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst);
+	struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_ahash *auth;
+	struct crypto_ablkcipher *enc;
+	int err;
+
+	auth = crypto_spawn_ahash(&ictx->auth);
+	if (IS_ERR(auth))
+		return PTR_ERR(auth);
+
+	enc = crypto_spawn_skcipher(&ictx->enc);
+	err = PTR_ERR(enc);
+	if (IS_ERR(enc))
+		goto err_free_ahash;
+
+	ctx->auth = auth;
+	ctx->enc = enc;
+
+	ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
+			    crypto_ahash_alignmask(auth),
+			    crypto_ahash_alignmask(auth) + 1) +
+		      crypto_ablkcipher_ivsize(enc);
+
+	tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) +
+				ctx->reqoff +
+				max_t(unsigned int,
+				crypto_ahash_reqsize(auth) +
+				sizeof(struct ahash_request),
+				sizeof(struct skcipher_givcrypt_request) +
+				crypto_ablkcipher_reqsize(enc));
+
+	return 0;
+
+err_free_ahash:
+	crypto_free_ahash(auth);
+	return err;
+}
+
+static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_ahash(ctx->auth);
+	crypto_free_ablkcipher(ctx->enc);
+}
+
+static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
+{
+	struct crypto_attr_type *algt;
+	struct crypto_instance *inst;
+	struct hash_alg_common *auth;
+	struct crypto_alg *auth_base;
+	struct crypto_alg *enc;
+	struct authenc_esn_instance_ctx *ctx;
+	const char *enc_name;
+	int err;
+
+	algt = crypto_get_attr_type(tb);
+	err = PTR_ERR(algt);
+	if (IS_ERR(algt))
+		return ERR_PTR(err);
+
+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+		return ERR_PTR(-EINVAL);
+
+	auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
+			       CRYPTO_ALG_TYPE_AHASH_MASK);
+	if (IS_ERR(auth))
+		return ERR_CAST(auth);
+
+	auth_base = &auth->base;
+
+	enc_name = crypto_attr_alg_name(tb[2]);
+	err = PTR_ERR(enc_name);
+	if (IS_ERR(enc_name))
+		goto out_put_auth;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!inst)
+		goto out_put_auth;
+
+	ctx = crypto_instance_ctx(inst);
+
+	err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
+	if (err)
+		goto err_free_inst;
+
+	crypto_set_skcipher_spawn(&ctx->enc, inst);
+	err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
+	if (err)
+		goto err_drop_auth;
+
+	enc = crypto_skcipher_spawn_alg(&ctx->enc);
+
+	err = -ENAMETOOLONG;
+	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+		     "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
+	    CRYPTO_MAX_ALG_NAME)
+		goto err_drop_enc;
+
+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+		     "authencesn(%s,%s)", auth_base->cra_driver_name,
+		     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_drop_enc;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+	inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
+	inst->alg.cra_priority = enc->cra_priority *
+				 10 + auth_base->cra_priority;
+	inst->alg.cra_blocksize = enc->cra_blocksize;
+	inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
+	inst->alg.cra_type = &crypto_aead_type;
+
+	inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
+	inst->alg.cra_aead.maxauthsize = auth->digestsize;
+
+	inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
+
+	inst->alg.cra_init = crypto_authenc_esn_init_tfm;
+	inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
+
+	inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey;
+	inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt;
+	inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt;
+	inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt;
+
+out:
+	crypto_mod_put(auth_base);
+	return inst;
+
+err_drop_enc:
+	crypto_drop_skcipher(&ctx->enc);
+err_drop_auth:
+	crypto_drop_ahash(&ctx->auth);
+err_free_inst:
+	kfree(inst);
+out_put_auth:
+	inst = ERR_PTR(err);
+	goto out;
+}
+
+static void crypto_authenc_esn_free(struct crypto_instance *inst)
+{
+	struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+	crypto_drop_skcipher(&ctx->enc);
+	crypto_drop_ahash(&ctx->auth);
+	kfree(inst);
+}
+
+static struct crypto_template crypto_authenc_esn_tmpl = {
+	.name = "authencesn",
+	.alloc = crypto_authenc_esn_alloc,
+	.free = crypto_authenc_esn_free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_authenc_esn_module_init(void)
+{
+	return crypto_register_template(&crypto_authenc_esn_tmpl);
+}
+
+static void __exit crypto_authenc_esn_module_exit(void)
+{
+	crypto_unregister_template(&crypto_authenc_esn_tmpl);
+}
+
+module_init(crypto_authenc_esn_module_init);
+module_exit(crypto_authenc_esn_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
+MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
diff --git a/crypto/deflate.c b/crypto/deflate.c
index cbc7a33..b5ccae2 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -48,7 +48,8 @@ static int deflate_comp_init(struct deflate_ctx *ctx)
 	int ret = 0;
 	struct z_stream_s *stream = &ctx->comp_stream;
 
-	stream->workspace = vzalloc(zlib_deflate_workspacesize());
+	stream->workspace = vzalloc(zlib_deflate_workspacesize(
+				-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
 	if (!stream->workspace) {
 		ret = -ENOMEM;
 		goto out;
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 9aac5e5..e912ea5 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -146,7 +146,8 @@ static void test_cipher_speed(const char *algo, int enc, unsigned int sec,
 			      unsigned int tcount, u8 *keysize)
 {
 	unsigned int ret, i, j, iv_len;
-	const char *key, iv[128];
+	const char *key;
+	char iv[128];
 	struct crypto_blkcipher *tfm;
 	struct blkcipher_desc desc;
 	const char *e;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 27ea9fe..2854865 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2077,6 +2077,7 @@ static const struct alg_test_desc alg_test_descs[] = {
 	}, {
 		.alg = "ghash",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = ghash_tv_template,
@@ -2453,6 +2454,7 @@ static const struct alg_test_desc alg_test_descs[] = {
 	}, {
 		.alg = "xts(aes)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 834af7f..aa6dac0 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -451,8 +451,9 @@ static struct hash_testvec rmd320_tv_template[] = {
 
 /*
  * SHA1 test vectors  from from FIPS PUB 180-1
+ * Long vector from CAVS 5.0
  */
-#define SHA1_TEST_VECTORS	2
+#define SHA1_TEST_VECTORS	3
 
 static struct hash_testvec sha1_tv_template[] = {
 	{
@@ -467,6 +468,33 @@ static struct hash_testvec sha1_tv_template[] = {
 			  "\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1",
 		.np	= 2,
 		.tap	= { 28, 28 }
+	}, {
+		.plaintext = "\xec\x29\x56\x12\x44\xed\xe7\x06"
+			     "\xb6\xeb\x30\xa1\xc3\x71\xd7\x44"
+			     "\x50\xa1\x05\xc3\xf9\x73\x5f\x7f"
+			     "\xa9\xfe\x38\xcf\x67\xf3\x04\xa5"
+			     "\x73\x6a\x10\x6e\x92\xe1\x71\x39"
+			     "\xa6\x81\x3b\x1c\x81\xa4\xf3\xd3"
+			     "\xfb\x95\x46\xab\x42\x96\xfa\x9f"
+			     "\x72\x28\x26\xc0\x66\x86\x9e\xda"
+			     "\xcd\x73\xb2\x54\x80\x35\x18\x58"
+			     "\x13\xe2\x26\x34\xa9\xda\x44\x00"
+			     "\x0d\x95\xa2\x81\xff\x9f\x26\x4e"
+			     "\xcc\xe0\xa9\x31\x22\x21\x62\xd0"
+			     "\x21\xcc\xa2\x8d\xb5\xf3\xc2\xaa"
+			     "\x24\x94\x5a\xb1\xe3\x1c\xb4\x13"
+			     "\xae\x29\x81\x0f\xd7\x94\xca\xd5"
+			     "\xdf\xaf\x29\xec\x43\xcb\x38\xd1"
+			     "\x98\xfe\x4a\xe1\xda\x23\x59\x78"
+			     "\x02\x21\x40\x5b\xd6\x71\x2a\x53"
+			     "\x05\xda\x4b\x1b\x73\x7f\xce\x7c"
+			     "\xd2\x1c\x0e\xb7\x72\x8d\x08\x23"
+			     "\x5a\x90\x11",
+		.psize	= 163,
+		.digest	= "\x97\x01\x11\xc4\xe7\x7b\xcc\x88\xcc\x20"
+			  "\x45\x9c\x02\xb6\x9b\x4a\xa8\xf5\x82\x17",
+		.np	= 4,
+		.tap	= { 63, 64, 31, 5 }
 	}
 };
 
diff --git a/crypto/zlib.c b/crypto/zlib.c
index 739b8fc..d11d761 100644
--- a/crypto/zlib.c
+++ b/crypto/zlib.c
@@ -85,6 +85,7 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
 	struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
 	struct z_stream_s *stream = &ctx->comp_stream;
 	struct nlattr *tb[ZLIB_COMP_MAX + 1];
+	int window_bits, mem_level;
 	size_t workspacesize;
 	int ret;
 
@@ -94,7 +95,14 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
 
 	zlib_comp_exit(ctx);
 
-	workspacesize = zlib_deflate_workspacesize();
+	window_bits = tb[ZLIB_COMP_WINDOWBITS]
+					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
+					: MAX_WBITS;
+	mem_level = tb[ZLIB_COMP_MEMLEVEL]
+					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
+					: DEF_MEM_LEVEL;
+
+	workspacesize = zlib_deflate_workspacesize(window_bits, mem_level);
 	stream->workspace = vzalloc(workspacesize);
 	if (!stream->workspace)
 		return -ENOMEM;
@@ -106,12 +114,8 @@ static int zlib_compress_setup(struct crypto_pcomp *tfm, void *params,
 				tb[ZLIB_COMP_METHOD]
 					? nla_get_u32(tb[ZLIB_COMP_METHOD])
 					: Z_DEFLATED,
-				tb[ZLIB_COMP_WINDOWBITS]
-					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
-					: MAX_WBITS,
-				tb[ZLIB_COMP_MEMLEVEL]
-					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
-					: DEF_MEM_LEVEL,
+				window_bits,
+				mem_level,
 				tb[ZLIB_COMP_STRATEGY]
 					? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
 					: Z_DEFAULT_STRATEGY);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 9bfb71f..177c7d1 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -117,4 +117,6 @@ source "drivers/staging/Kconfig"
 source "drivers/platform/Kconfig"
 
 source "drivers/clk/Kconfig"
+
+source "drivers/hwspinlock/Kconfig"
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index b423bb1..3f135b6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -117,3 +117,5 @@ obj-y				+= platform/
 obj-y				+= ieee802154/
 #common clk code
 obj-y				+= clk/
+
+obj-$(CONFIG_HWSPINLOCK)	+= hwspinlock/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 2aa042a..3a17ca5 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -7,7 +7,6 @@ menuconfig ACPI
 	depends on !IA64_HP_SIM
 	depends on IA64 || X86
 	depends on PCI
-	depends on PM
 	select PNP
 	default y
 	help
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig
index fca34cc..e91680c 100644
--- a/drivers/acpi/apei/Kconfig
+++ b/drivers/acpi/apei/Kconfig
@@ -1,5 +1,6 @@
 config ACPI_APEI
 	bool "ACPI Platform Error Interface (APEI)"
+	select PSTORE
 	depends on X86
 	help
 	  APEI allows to report errors (for example from the chipset)
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index cf6db6b..c02005a 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -34,6 +34,7 @@
 #include <linux/cper.h>
 #include <linux/nmi.h>
 #include <linux/hardirq.h>
+#include <linux/pstore.h>
 #include <acpi/apei.h>
 
 #include "apei-internal.h"
@@ -781,6 +782,128 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
 	return 0;
 }
 
+static size_t erst_reader(u64 *id, enum pstore_type_id *type,
+		       struct timespec *time);
+static u64 erst_writer(enum pstore_type_id type, size_t size);
+
+static struct pstore_info erst_info = {
+	.owner		= THIS_MODULE,
+	.name		= "erst",
+	.read		= erst_reader,
+	.write		= erst_writer,
+	.erase		= erst_clear
+};
+
+#define CPER_CREATOR_PSTORE						\
+	UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c,	\
+		0x64, 0x90, 0xb8, 0x9d)
+#define CPER_SECTION_TYPE_DMESG						\
+	UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54,	\
+		0x94, 0x19, 0xeb, 0x12)
+#define CPER_SECTION_TYPE_MCE						\
+	UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96,	\
+		0x04, 0x4a, 0x38, 0xfc)
+
+struct cper_pstore_record {
+	struct cper_record_header hdr;
+	struct cper_section_descriptor sec_hdr;
+	char data[];
+} __packed;
+
+static size_t erst_reader(u64 *id, enum pstore_type_id *type,
+		       struct timespec *time)
+{
+	int rc;
+	ssize_t len;
+	unsigned long flags;
+	u64 record_id;
+	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
+					(erst_info.buf - sizeof(*rcd));
+
+	if (erst_disable)
+		return -ENODEV;
+
+	raw_spin_lock_irqsave(&erst_lock, flags);
+skip:
+	rc = __erst_get_next_record_id(&record_id);
+	if (rc) {
+		raw_spin_unlock_irqrestore(&erst_lock, flags);
+		return rc;
+	}
+	/* no more record */
+	if (record_id == APEI_ERST_INVALID_RECORD_ID) {
+		raw_spin_unlock_irqrestore(&erst_lock, flags);
+		return 0;
+	}
+
+	len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
+			  erst_erange.size);
+	if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
+		goto skip;
+	raw_spin_unlock_irqrestore(&erst_lock, flags);
+
+	*id = record_id;
+	if (uuid_le_cmp(rcd->sec_hdr.section_type,
+			CPER_SECTION_TYPE_DMESG) == 0)
+		*type = PSTORE_TYPE_DMESG;
+	else if (uuid_le_cmp(rcd->sec_hdr.section_type,
+			     CPER_SECTION_TYPE_MCE) == 0)
+		*type = PSTORE_TYPE_MCE;
+	else
+		*type = PSTORE_TYPE_UNKNOWN;
+
+	if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
+		time->tv_sec = rcd->hdr.timestamp;
+	else
+		time->tv_sec = 0;
+	time->tv_nsec = 0;
+
+	return len - sizeof(*rcd);
+}
+
+static u64 erst_writer(enum pstore_type_id type, size_t size)
+{
+	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
+					(erst_info.buf - sizeof(*rcd));
+
+	memset(rcd, 0, sizeof(*rcd));
+	memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
+	rcd->hdr.revision = CPER_RECORD_REV;
+	rcd->hdr.signature_end = CPER_SIG_END;
+	rcd->hdr.section_count = 1;
+	rcd->hdr.error_severity = CPER_SEV_FATAL;
+	/* timestamp valid. platform_id, partition_id are invalid */
+	rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
+	rcd->hdr.timestamp = get_seconds();
+	rcd->hdr.record_length = sizeof(*rcd) + size;
+	rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
+	rcd->hdr.notification_type = CPER_NOTIFY_MCE;
+	rcd->hdr.record_id = cper_next_record_id();
+	rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;
+
+	rcd->sec_hdr.section_offset = sizeof(*rcd);
+	rcd->sec_hdr.section_length = size;
+	rcd->sec_hdr.revision = CPER_SEC_REV;
+	/* fru_id and fru_text is invalid */
+	rcd->sec_hdr.validation_bits = 0;
+	rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
+	switch (type) {
+	case PSTORE_TYPE_DMESG:
+		rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
+		break;
+	case PSTORE_TYPE_MCE:
+		rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE;
+		break;
+	default:
+		return -EINVAL;
+	}
+	rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
+
+	erst_write(&rcd->hdr);
+
+	return rcd->hdr.record_id;
+}
+
 static int __init erst_init(void)
 {
 	int rc = 0;
@@ -788,6 +911,7 @@ static int __init erst_init(void)
 	struct apei_exec_context ctx;
 	struct apei_resources erst_resources;
 	struct resource *r;
+	char *buf;
 
 	if (acpi_disabled)
 		goto err;
@@ -854,6 +978,18 @@ static int __init erst_init(void)
 	if (!erst_erange.vaddr)
 		goto err_release_erange;
 
+	buf = kmalloc(erst_erange.size, GFP_KERNEL);
+	mutex_init(&erst_info.buf_mutex);
+	if (buf) {
+		erst_info.buf = buf + sizeof(struct cper_pstore_record);
+		erst_info.bufsize = erst_erange.size -
+				    sizeof(struct cper_pstore_record);
+		if (pstore_register(&erst_info)) {
+			pr_info(ERST_PFX "Could not register with persistent store\n");
+			kfree(buf);
+		}
+	}
+
 	pr_info(ERST_PFX
 	"Error Record Serialization Table (ERST) support is initialized.\n");
 
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 7ced61f..9749980 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -40,6 +40,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/dmi.h>
+#include <linux/suspend.h>
 
 #include "internal.h"
 
@@ -1006,8 +1007,7 @@ struct kobject *acpi_kobj;
 
 static int __init acpi_init(void)
 {
-	int result = 0;
-
+	int result;
 
 	if (acpi_disabled) {
 		printk(KERN_INFO PREFIX "Interpreter disabled.\n");
@@ -1022,29 +1022,18 @@ static int __init acpi_init(void)
 
 	init_acpi_device_notify();
 	result = acpi_bus_init();
-
-	if (!result) {
-		pci_mmcfg_late_init();
-		if (!(pm_flags & PM_APM))
-			pm_flags |= PM_ACPI;
-		else {
-			printk(KERN_INFO PREFIX
-			       "APM is already active, exiting\n");
-			disable_acpi();
-			result = -ENODEV;
-		}
-	} else
+	if (result) {
 		disable_acpi();
-
-	if (acpi_disabled)
 		return result;
+	}
 
+	pci_mmcfg_late_init();
 	acpi_scan_init();
 	acpi_ec_init();
 	acpi_debugfs_init();
 	acpi_sleep_proc_init();
 	acpi_wakeup_device_init();
-	return result;
+	return 0;
 }
 
 subsys_initcall(acpi_init);
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 5eb25eb..3b5c318 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -274,7 +274,7 @@ acpi_table_parse_srat(enum acpi_srat_type id,
 
 int __init acpi_numa_init(void)
 {
-	int ret = 0;
+	int cnt = 0;
 
 	/*
 	 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
@@ -288,7 +288,7 @@ int __init acpi_numa_init(void)
 				     acpi_parse_x2apic_affinity, 0);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
 				     acpi_parse_processor_affinity, 0);
-		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
+		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
 	}
@@ -297,7 +297,10 @@ int __init acpi_numa_init(void)
 	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
 	acpi_numa_arch_fixup();
-	return ret;
+
+	if (cnt <= 0)
+		return cnt ?: -ENOENT;
+	return 0;
 }
 
 int acpi_get_pxm(acpi_handle h)
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c90c76a..4a67530 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1589,9 +1589,9 @@ acpi_status __init acpi_os_initialize(void)
 
 acpi_status __init acpi_os_initialize1(void)
 {
-	kacpid_wq = create_workqueue("kacpid");
-	kacpi_notify_wq = create_workqueue("kacpi_notify");
-	kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
+	kacpid_wq = alloc_workqueue("kacpid", 0, 1);
+	kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
+	kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1);
 	BUG_ON(!kacpid_wq);
 	BUG_ON(!kacpi_notify_wq);
 	BUG_ON(!kacpi_hotplug_wq);
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index d6a8cd1..1850dac 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/suspend.h>
 #include <linux/reboot.h>
+#include <linux/acpi.h>
 
 #include <asm/io.h>
 
@@ -585,7 +586,7 @@ int acpi_suspend(u32 acpi_state)
 	return -EINVAL;
 }
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 /**
  *	acpi_pm_device_sleep_state - return preferred power state of ACPI device
  *		in the system sleep state given by %acpi_target_sleep_state
@@ -671,7 +672,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
 		*d_min_p = d_min;
 	return d_max;
 }
-#endif /* CONFIG_PM_OPS */
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_SLEEP
 /**
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index 90f8f76..a18e497 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -782,6 +782,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
 	if (acpi_video_backlight_support()) {
 		struct backlight_properties props;
+		struct pci_dev *pdev;
+		acpi_handle acpi_parent;
+		struct device *parent = NULL;
 		int result;
 		static int count = 0;
 		char *name;
@@ -794,9 +797,20 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 			return;
 		count++;
 
+		acpi_get_parent(device->dev->handle, &acpi_parent);
+
+		pdev = acpi_get_pci_dev(acpi_parent);
+		if (pdev) {
+			parent = &pdev->dev;
+			pci_dev_put(pdev);
+		}
+
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_FIRMWARE;
 		props.max_brightness = device->brightness->count - 3;
-		device->backlight = backlight_device_register(name, NULL, device,
+		device->backlight = backlight_device_register(name,
+							      parent,
+							      device,
 							      &acpi_backlight_ops,
 							      &props);
 		kfree(name);
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index e7df019..6d2bb25 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -13,16 +13,17 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/amba/bus.h>
 
 #include <asm/irq.h>
 #include <asm/sizes.h>
 
-#define to_amba_device(d)	container_of(d, struct amba_device, dev)
 #define to_amba_driver(d)	container_of(d, struct amba_driver, drv)
 
-static struct amba_id *
-amba_lookup(struct amba_id *table, struct amba_device *dev)
+static const struct amba_id *
+amba_lookup(const struct amba_id *table, struct amba_device *dev)
 {
 	int ret = 0;
 
@@ -57,26 +58,6 @@ static int amba_uevent(struct device *dev, struct kobj_uevent_env *env)
 #define amba_uevent NULL
 #endif
 
-static int amba_suspend(struct device *dev, pm_message_t state)
-{
-	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(to_amba_device(dev), state);
-	return ret;
-}
-
-static int amba_resume(struct device *dev)
-{
-	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(to_amba_device(dev));
-	return ret;
-}
-
 #define amba_attr_func(name,fmt,arg...)					\
 static ssize_t name##_show(struct device *_dev,				\
 			   struct device_attribute *attr, char *buf)	\
@@ -102,17 +83,330 @@ static struct device_attribute amba_dev_attrs[] = {
 	__ATTR_NULL,
 };
 
+#ifdef CONFIG_PM_SLEEP
+
+static int amba_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct amba_driver *adrv = to_amba_driver(dev->driver);
+	struct amba_device *adev = to_amba_device(dev);
+	int ret = 0;
+
+	if (dev->driver && adrv->suspend)
+		ret = adrv->suspend(adev, mesg);
+
+	return ret;
+}
+
+static int amba_legacy_resume(struct device *dev)
+{
+	struct amba_driver *adrv = to_amba_driver(dev->driver);
+	struct amba_device *adev = to_amba_device(dev);
+	int ret = 0;
+
+	if (dev->driver && adrv->resume)
+		ret = adrv->resume(adev);
+
+	return ret;
+}
+
+static int amba_pm_prepare(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (drv && drv->pm && drv->pm->prepare)
+		ret = drv->pm->prepare(dev);
+
+	return ret;
+}
+
+static void amba_pm_complete(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+
+	if (drv && drv->pm && drv->pm->complete)
+		drv->pm->complete(dev);
+}
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define amba_pm_prepare		NULL
+#define amba_pm_complete		NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_SUSPEND
+
+static int amba_pm_suspend(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend)
+			ret = drv->pm->suspend(dev);
+	} else {
+		ret = amba_legacy_suspend(dev, PMSG_SUSPEND);
+	}
+
+	return ret;
+}
+
+static int amba_pm_suspend_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend_noirq)
+			ret = drv->pm->suspend_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_resume(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume)
+			ret = drv->pm->resume(dev);
+	} else {
+		ret = amba_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_resume_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume_noirq)
+			ret = drv->pm->resume_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_SUSPEND */
+
+#define amba_pm_suspend		NULL
+#define amba_pm_resume		NULL
+#define amba_pm_suspend_noirq	NULL
+#define amba_pm_resume_noirq	NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATION
+
+static int amba_pm_freeze(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze)
+			ret = drv->pm->freeze(dev);
+	} else {
+		ret = amba_legacy_suspend(dev, PMSG_FREEZE);
+	}
+
+	return ret;
+}
+
+static int amba_pm_freeze_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze_noirq)
+			ret = drv->pm->freeze_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_thaw(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw)
+			ret = drv->pm->thaw(dev);
+	} else {
+		ret = amba_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_thaw_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw_noirq)
+			ret = drv->pm->thaw_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_poweroff(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff)
+			ret = drv->pm->poweroff(dev);
+	} else {
+		ret = amba_legacy_suspend(dev, PMSG_HIBERNATE);
+	}
+
+	return ret;
+}
+
+static int amba_pm_poweroff_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff_noirq)
+			ret = drv->pm->poweroff_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_restore(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore)
+			ret = drv->pm->restore(dev);
+	} else {
+		ret = amba_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_restore_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore_noirq)
+			ret = drv->pm->restore_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_HIBERNATION */
+
+#define amba_pm_freeze		NULL
+#define amba_pm_thaw		NULL
+#define amba_pm_poweroff		NULL
+#define amba_pm_restore		NULL
+#define amba_pm_freeze_noirq	NULL
+#define amba_pm_thaw_noirq		NULL
+#define amba_pm_poweroff_noirq	NULL
+#define amba_pm_restore_noirq	NULL
+
+#endif /* !CONFIG_HIBERNATION */
+
+#ifdef CONFIG_PM
+
+static const struct dev_pm_ops amba_pm = {
+	.prepare	= amba_pm_prepare,
+	.complete	= amba_pm_complete,
+	.suspend	= amba_pm_suspend,
+	.resume		= amba_pm_resume,
+	.freeze		= amba_pm_freeze,
+	.thaw		= amba_pm_thaw,
+	.poweroff	= amba_pm_poweroff,
+	.restore	= amba_pm_restore,
+	.suspend_noirq	= amba_pm_suspend_noirq,
+	.resume_noirq	= amba_pm_resume_noirq,
+	.freeze_noirq	= amba_pm_freeze_noirq,
+	.thaw_noirq	= amba_pm_thaw_noirq,
+	.poweroff_noirq	= amba_pm_poweroff_noirq,
+	.restore_noirq	= amba_pm_restore_noirq,
+	SET_RUNTIME_PM_OPS(
+		pm_generic_runtime_suspend,
+		pm_generic_runtime_resume,
+		pm_generic_runtime_idle
+	)
+};
+
+#define AMBA_PM (&amba_pm)
+
+#else /* !CONFIG_PM */
+
+#define AMBA_PM	NULL
+
+#endif /* !CONFIG_PM */
+
 /*
  * Primecells are part of the Advanced Microcontroller Bus Architecture,
  * so we call the bus "amba".
  */
-static struct bus_type amba_bustype = {
+struct bus_type amba_bustype = {
 	.name		= "amba",
 	.dev_attrs	= amba_dev_attrs,
 	.match		= amba_match,
 	.uevent		= amba_uevent,
-	.suspend	= amba_suspend,
-	.resume		= amba_resume,
+	.pm		= AMBA_PM,
 };
 
 static int __init amba_init(void)
@@ -188,7 +482,7 @@ static int amba_probe(struct device *dev)
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 	struct amba_driver *pcdrv = to_amba_driver(dev->driver);
-	struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
+	const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
 	int ret;
 
 	do {
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index c2328ae..75afa75 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -202,6 +202,18 @@ config SATA_DWC
 
 	  If unsure, say N.
 
+config SATA_DWC_DEBUG
+	bool "Debugging driver version"
+	depends on SATA_DWC
+	help
+	  This option enables debugging output in the driver.
+
+config SATA_DWC_VDEBUG
+	bool "Verbose debug output"
+	depends on SATA_DWC_DEBUG
+	help
+	  This option enables the taskfile dumping and NCQ debugging.
+
 config SATA_MV
 	tristate "Marvell SATA support"
 	help
@@ -299,6 +311,12 @@ config PATA_AMD
 
 	  If unsure, say N.
 
+config PATA_ARASAN_CF
+	tristate "ARASAN CompactFlash PATA Controller Support"
+	select DMA_ENGINE
+	help
+	  Say Y here to support the ARASAN CompactFlash PATA controller
+
 config PATA_ARTOP
 	tristate "ARTOP 6210/6260 PATA support"
 	depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 27291aa..8ac64e1 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_SATA_DWC)		+= sata_dwc_460ex.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
+obj-$(CONFIG_PATA_ARASAN_CF)	+= pata_arasan_cf.o
 obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o
 obj-$(CONFIG_SATA_QSTOR)	+= sata_qstor.o
 obj-$(CONFIG_SATA_SX4)		+= sata_sx4.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index b8d96ce..e62f693 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -175,8 +175,7 @@ static const struct ata_port_info ahci_port_info[] = {
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -260,6 +259,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
@@ -383,6 +383,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
 	  .class_mask = 0xffffff,
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
+	{ PCI_DEVICE(0x1b4b, 0x9125),
+	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
+	{ PCI_DEVICE(0x1b4b, 0x91a3),
+	  .driver_data = board_ahci_yes_fbs },
 
 	/* Promise */
 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 3e606c3..ccaf081 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -213,10 +213,8 @@ enum {
 
 	/* ap->flags bits */
 
-	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
-					  ATA_FLAG_LPM,
+	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
+					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
 
 	ICH_MAP				= 0x90, /* ICH MAP register */
 
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 6981f76..721d38b 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -237,7 +237,7 @@ static struct pci_device_id ata_generic[] = {
 #endif
 	/* Intel, IDE class device */
 	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 
+	  PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL,
 	  .driver_data = ATA_GEN_INTEL_IDER },
 	/* Must come last. If you add entries adjust this table appropriately */
 	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 6cb14ca..cdec4ab 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -230,7 +230,7 @@ static const struct pci_device_id piix_pci_tbl[] = {
 	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 
 	/* SATA ports */
-	
+
 	/* 82801EB (ICH5) */
 	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	/* 82801EB (ICH5) */
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 8b5ea39..a791b8ce 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -660,8 +660,7 @@ static int ata_acpi_filter_tf(struct ata_device *dev,
  * @dev: target ATA device
  * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
  *
- * Outputs ATA taskfile to standard ATA host controller using MMIO
- * or PIO as indicated by the ATA_FLAG_MMIO flag.
+ * Outputs ATA taskfile to standard ATA host controller.
  * Writes the control, feature, nsect, lbal, lbam, and lbah registers.
  * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
  * hob_lbal, hob_lbam, and hob_lbah.
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index d4e52e2..b91e19c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4210,7 +4210,7 @@ static int glob_match (const char *text, const char *pattern)
 		return 0;  /* End of both strings: match */
 	return 1;  /* No match */
 }
- 
+
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
 {
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -5479,7 +5479,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
 	ap = kzalloc(sizeof(*ap), GFP_KERNEL);
 	if (!ap)
 		return NULL;
-	
+
 	ap->pflags |= ATA_PFLAG_INITIALIZING;
 	ap->lock = &host->lock;
 	ap->print_id = -1;
@@ -5887,21 +5887,9 @@ void ata_host_init(struct ata_host *host, struct device *dev,
 	host->ops = ops;
 }
 
-
-static void async_port_probe(void *data, async_cookie_t cookie)
+int ata_port_probe(struct ata_port *ap)
 {
-	int rc;
-	struct ata_port *ap = data;
-
-	/*
-	 * If we're not allowed to scan this host in parallel,
-	 * we need to wait until all previous scans have completed
-	 * before going further.
-	 * Jeff Garzik says this is only within a controller, so we
-	 * don't need to wait for port 0, only for later ports.
-	 */
-	if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
-		async_synchronize_cookie(cookie);
+	int rc = 0;
 
 	/* probe */
 	if (ap->ops->error_handler) {
@@ -5927,23 +5915,33 @@ static void async_port_probe(void *data, async_cookie_t cookie)
 		DPRINTK("ata%u: bus probe begin\n", ap->print_id);
 		rc = ata_bus_probe(ap);
 		DPRINTK("ata%u: bus probe end\n", ap->print_id);
-
-		if (rc) {
-			/* FIXME: do something useful here?
-			 * Current libata behavior will
-			 * tear down everything when
-			 * the module is removed
-			 * or the h/w is unplugged.
-			 */
-		}
 	}
+	return rc;
+}
+
+
+static void async_port_probe(void *data, async_cookie_t cookie)
+{
+	struct ata_port *ap = data;
+
+	/*
+	 * If we're not allowed to scan this host in parallel,
+	 * we need to wait until all previous scans have completed
+	 * before going further.
+	 * Jeff Garzik says this is only within a controller, so we
+	 * don't need to wait for port 0, only for later ports.
+	 */
+	if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
+		async_synchronize_cookie(cookie);
+
+	(void)ata_port_probe(ap);
 
 	/* in order to keep device order, we need to synchronize at this point */
 	async_synchronize_cookie(cookie);
 
 	ata_scsi_scan_host(ap, 1);
-
 }
+
 /**
  *	ata_host_register - register initialized ATA host
  *	@host: ATA host to register
@@ -5983,7 +5981,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 	for (i = 0; i < host->n_ports; i++)
 		host->ports[i]->print_id = ata_print_id++;
 
-	
+
 	/* Create associated sysfs transport objects  */
 	for (i = 0; i < host->n_ports; i++) {
 		rc = ata_tport_add(host->dev,host->ports[i]);
@@ -6471,7 +6469,7 @@ static int __init ata_init(void)
 		ata_sff_exit();
 		rc = -ENOMEM;
 		goto err_out;
-	}		
+	}
 
 	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
 	return 0;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 17a6378..df3f314 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -587,11 +587,43 @@ static void ata_eh_unload(struct ata_port *ap)
 void ata_scsi_error(struct Scsi_Host *host)
 {
 	struct ata_port *ap = ata_shost_to_port(host);
-	int i;
 	unsigned long flags;
+	LIST_HEAD(eh_work_q);
 
 	DPRINTK("ENTER\n");
 
+	spin_lock_irqsave(host->host_lock, flags);
+	list_splice_init(&host->eh_cmd_q, &eh_work_q);
+	spin_unlock_irqrestore(host->host_lock, flags);
+
+	ata_scsi_cmd_error_handler(host, ap, &eh_work_q);
+
+	/* If we timed raced normal completion and there is nothing to
+	   recover nr_timedout == 0 why exactly are we doing error recovery ? */
+	ata_scsi_port_error_handler(host, ap);
+
+	/* finish or retry handled scmd's and clean up */
+	WARN_ON(host->host_failed || !list_empty(&eh_work_q));
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ * ata_scsi_cmd_error_handler - error callback for a list of commands
+ * @host:	scsi host containing the port
+ * @ap:		ATA port within the host
+ * @eh_work_q:	list of commands to process
+ *
+ * process the given list of commands and return those finished to the
+ * ap->eh_done_q.  This function is the first part of the libata error
+ * handler which processes a given list of failed commands.
+ */
+void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
+				struct list_head *eh_work_q)
+{
+	int i;
+	unsigned long flags;
+
 	/* make sure sff pio task is not running */
 	ata_sff_flush_pio_task(ap);
 
@@ -627,7 +659,7 @@ void ata_scsi_error(struct Scsi_Host *host)
 		if (ap->ops->lost_interrupt)
 			ap->ops->lost_interrupt(ap);
 
-		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
+		list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {
 			struct ata_queued_cmd *qc;
 
 			for (i = 0; i < ATA_MAX_QUEUE; i++) {
@@ -671,8 +703,20 @@ void ata_scsi_error(struct Scsi_Host *host)
 	} else
 		spin_unlock_wait(ap->lock);
 
-	/* If we timed raced normal completion and there is nothing to
-	   recover nr_timedout == 0 why exactly are we doing error recovery ? */
+}
+EXPORT_SYMBOL(ata_scsi_cmd_error_handler);
+
+/**
+ * ata_scsi_port_error_handler - recover the port after the commands
+ * @host:	SCSI host containing the port
+ * @ap:		the ATA port
+ *
+ * Handle the recovery of the port @ap after all the commands
+ * have been recovered.
+ */
+void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
+{
+	unsigned long flags;
 
 	/* invoke error handler */
 	if (ap->ops->error_handler) {
@@ -761,9 +805,6 @@ void ata_scsi_error(struct Scsi_Host *host)
 		ap->ops->eng_timeout(ap);
 	}
 
-	/* finish or retry handled scmd's and clean up */
-	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
-
 	scsi_eh_flush_done_q(&ap->eh_done_q);
 
 	/* clean up */
@@ -784,9 +825,8 @@ void ata_scsi_error(struct Scsi_Host *host)
 	wake_up_all(&ap->eh_wait_q);
 
 	spin_unlock_irqrestore(ap->lock, flags);
-
-	DPRINTK("EXIT\n");
 }
+EXPORT_SYMBOL_GPL(ata_scsi_port_error_handler);
 
 /**
  *	ata_port_wait_eh - Wait for the currently pending EH to complete
@@ -1618,7 +1658,7 @@ static void ata_eh_analyze_serror(struct ata_link *link)
 	 * host links.  For disabled PMP links, only N bit is
 	 * considered as X bit is left at 1 for link plugging.
 	 */
-	if (link->lpm_policy != ATA_LPM_MAX_POWER)
+	if (link->lpm_policy > ATA_LPM_MAX_POWER)
 		hotplug_mask = 0;	/* hotplug doesn't work w/ LPM */
 	else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
 		hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 600f635..a834199 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2056,6 +2056,17 @@ static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
 		      ATA_ID_SERNO_LEN);
 	num += ATA_ID_SERNO_LEN;
 
+	if (ata_id_has_wwn(args->id)) {
+		/* SAT defined lu world wide name */
+		/* piv=0, assoc=lu, code_set=binary, designator=NAA */
+		rbuf[num + 0] = 1;
+		rbuf[num + 1] = 3;
+		rbuf[num + 3] = ATA_ID_WWN_LEN;
+		num += 4;
+		ata_id_string(args->id, (unsigned char *) rbuf + num,
+			      ATA_ID_WWN, ATA_ID_WWN_LEN);
+		num += ATA_ID_WWN_LEN;
+	}
 	rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
 	return 0;
 }
@@ -3759,7 +3770,7 @@ struct ata_port *ata_sas_port_alloc(struct ata_host *host,
 		return NULL;
 
 	ap->port_no = 0;
-	ap->lock = shost->host_lock;
+	ap->lock = &host->lock;
 	ap->pio_mask = port_info->pio_mask;
 	ap->mwdma_mask = port_info->mwdma_mask;
 	ap->udma_mask = port_info->udma_mask;
@@ -3821,7 +3832,7 @@ int ata_sas_port_init(struct ata_port *ap)
 
 	if (!rc) {
 		ap->print_id = ata_print_id++;
-		rc = ata_bus_probe(ap);
+		rc = ata_port_probe(ap);
 	}
 
 	return rc;
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index af6141b..cf7acbc 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1302,6 +1302,18 @@ fsm_start:
 }
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 
+void ata_sff_queue_work(struct work_struct *work)
+{
+	queue_work(ata_sff_wq, work);
+}
+EXPORT_SYMBOL_GPL(ata_sff_queue_work);
+
+void ata_sff_queue_delayed_work(struct delayed_work *dwork, unsigned long delay)
+{
+	queue_delayed_work(ata_sff_wq, dwork, delay);
+}
+EXPORT_SYMBOL_GPL(ata_sff_queue_delayed_work);
+
 void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)
 {
 	struct ata_port *ap = link->ap;
@@ -1311,8 +1323,7 @@ void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)
 	ap->sff_pio_task_link = link;
 
 	/* may fail if ata_sff_flush_pio_task() in progress */
-	queue_delayed_work(ata_sff_wq, &ap->sff_pio_task,
-			   msecs_to_jiffies(delay));
+	ata_sff_queue_delayed_work(&ap->sff_pio_task, msecs_to_jiffies(delay));
 }
 EXPORT_SYMBOL_GPL(ata_sff_queue_pio_task);
 
@@ -1336,7 +1347,7 @@ static void ata_sff_pio_task(struct work_struct *work)
 	u8 status;
 	int poll_next;
 
-	BUG_ON(ap->sff_pio_task_link == NULL); 
+	BUG_ON(ap->sff_pio_task_link == NULL);
 	/* qc can be NULL if timeout occurred */
 	qc = ata_qc_from_tag(ap, link->active_tag);
 	if (!qc) {
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index a9be110..773de97 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -103,6 +103,7 @@ extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern struct ata_port *ata_port_alloc(struct ata_host *host);
 extern const char *sata_spd_string(unsigned int spd);
+extern int ata_port_probe(struct ata_port *ap);
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index c8d4703..91949d9 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -245,7 +245,7 @@ static struct ata_port_operations pacpi_ops = {
 static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	static const struct ata_port_info info = {
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
new file mode 100644
index 0000000..65cee74
--- /dev/null
+++ b/drivers/ata/pata_arasan_cf.c
@@ -0,0 +1,983 @@
+/*
+ * drivers/ata/pata_arasan_cf.c
+ *
+ * Arasan Compact Flash host controller source file
+ *
+ * Copyright (C) 2011 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/*
+ * The Arasan CompactFlash Device Controller IP core has three basic modes of
+ * operation: PC card ATA using I/O mode, PC card ATA using memory mode, PC card
+ * ATA using true IDE modes. This driver supports only True IDE mode currently.
+ *
+ * Arasan CF Controller shares global irq register with Arasan XD Controller.
+ *
+ * Tested on arch/arm/mach-spear13xx
+ */
+
+#include <linux/ata.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/module.h>
+#include <linux/pata_arasan_cf_data.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#define DRIVER_NAME	"arasan_cf"
+#define TIMEOUT		msecs_to_jiffies(3000)
+
+/* Registers */
+/* CompactFlash Interface Status */
+#define CFI_STS			0x000
+	#define STS_CHG				(1)
+	#define BIN_AUDIO_OUT			(1 << 1)
+	#define CARD_DETECT1			(1 << 2)
+	#define CARD_DETECT2			(1 << 3)
+	#define INP_ACK				(1 << 4)
+	#define CARD_READY			(1 << 5)
+	#define IO_READY			(1 << 6)
+	#define B16_IO_PORT_SEL			(1 << 7)
+/* IRQ */
+#define IRQ_STS			0x004
+/* Interrupt Enable */
+#define IRQ_EN			0x008
+	#define CARD_DETECT_IRQ			(1)
+	#define STATUS_CHNG_IRQ			(1 << 1)
+	#define MEM_MODE_IRQ			(1 << 2)
+	#define IO_MODE_IRQ			(1 << 3)
+	#define TRUE_IDE_MODE_IRQ		(1 << 8)
+	#define PIO_XFER_ERR_IRQ		(1 << 9)
+	#define BUF_AVAIL_IRQ			(1 << 10)
+	#define XFER_DONE_IRQ			(1 << 11)
+	#define IGNORED_IRQS	(STATUS_CHNG_IRQ | MEM_MODE_IRQ | IO_MODE_IRQ |\
+					TRUE_IDE_MODE_IRQ)
+	#define TRUE_IDE_IRQS	(CARD_DETECT_IRQ | PIO_XFER_ERR_IRQ |\
+					BUF_AVAIL_IRQ | XFER_DONE_IRQ)
+/* Operation Mode */
+#define OP_MODE			0x00C
+	#define CARD_MODE_MASK			(0x3)
+	#define MEM_MODE			(0x0)
+	#define IO_MODE				(0x1)
+	#define TRUE_IDE_MODE			(0x2)
+
+	#define CARD_TYPE_MASK			(1 << 2)
+	#define CF_CARD				(0)
+	#define CF_PLUS_CARD			(1 << 2)
+
+	#define CARD_RESET			(1 << 3)
+	#define CFHOST_ENB			(1 << 4)
+	#define OUTPUTS_TRISTATE		(1 << 5)
+	#define ULTRA_DMA_ENB			(1 << 8)
+	#define MULTI_WORD_DMA_ENB		(1 << 9)
+	#define DRQ_BLOCK_SIZE_MASK		(0x3 << 11)
+	#define DRQ_BLOCK_SIZE_512		(0)
+	#define DRQ_BLOCK_SIZE_1024		(1 << 11)
+	#define DRQ_BLOCK_SIZE_2048		(2 << 11)
+	#define DRQ_BLOCK_SIZE_4096		(3 << 11)
+/* CF Interface Clock Configuration */
+#define CLK_CFG			0x010
+	#define CF_IF_CLK_MASK			(0XF)
+/* CF Timing Mode Configuration */
+#define TM_CFG			0x014
+	#define MEM_MODE_TIMING_MASK		(0x3)
+	#define MEM_MODE_TIMING_250NS		(0x0)
+	#define MEM_MODE_TIMING_120NS		(0x1)
+	#define MEM_MODE_TIMING_100NS		(0x2)
+	#define MEM_MODE_TIMING_80NS		(0x3)
+
+	#define IO_MODE_TIMING_MASK		(0x3 << 2)
+	#define IO_MODE_TIMING_250NS		(0x0 << 2)
+	#define IO_MODE_TIMING_120NS		(0x1 << 2)
+	#define IO_MODE_TIMING_100NS		(0x2 << 2)
+	#define IO_MODE_TIMING_80NS		(0x3 << 2)
+
+	#define TRUEIDE_PIO_TIMING_MASK		(0x7 << 4)
+	#define TRUEIDE_PIO_TIMING_SHIFT	4
+
+	#define TRUEIDE_MWORD_DMA_TIMING_MASK	(0x7 << 7)
+	#define TRUEIDE_MWORD_DMA_TIMING_SHIFT	7
+
+	#define ULTRA_DMA_TIMING_MASK		(0x7 << 10)
+	#define ULTRA_DMA_TIMING_SHIFT		10
+/* CF Transfer Address */
+#define XFER_ADDR		0x014
+	#define XFER_ADDR_MASK			(0x7FF)
+	#define MAX_XFER_COUNT			0x20000u
+/* Transfer Control */
+#define XFER_CTR		0x01C
+	#define XFER_COUNT_MASK			(0x3FFFF)
+	#define ADDR_INC_DISABLE		(1 << 24)
+	#define XFER_WIDTH_MASK			(1 << 25)
+	#define XFER_WIDTH_8B			(0)
+	#define XFER_WIDTH_16B			(1 << 25)
+
+	#define MEM_TYPE_MASK			(1 << 26)
+	#define MEM_TYPE_COMMON			(0)
+	#define MEM_TYPE_ATTRIBUTE		(1 << 26)
+
+	#define MEM_IO_XFER_MASK		(1 << 27)
+	#define MEM_XFER			(0)
+	#define IO_XFER				(1 << 27)
+
+	#define DMA_XFER_MODE			(1 << 28)
+
+	#define AHB_BUS_NORMAL_PIO_OPRTN	(~(1 << 29))
+	#define XFER_DIR_MASK			(1 << 30)
+	#define XFER_READ			(0)
+	#define XFER_WRITE			(1 << 30)
+
+	#define XFER_START			(1 << 31)
+/* Write Data Port */
+#define WRITE_PORT		0x024
+/* Read Data Port */
+#define READ_PORT		0x028
+/* ATA Data Port */
+#define ATA_DATA_PORT		0x030
+	#define ATA_DATA_PORT_MASK		(0xFFFF)
+/* ATA Error/Features */
+#define ATA_ERR_FTR		0x034
+/* ATA Sector Count */
+#define ATA_SC			0x038
+/* ATA Sector Number */
+#define ATA_SN			0x03C
+/* ATA Cylinder Low */
+#define ATA_CL			0x040
+/* ATA Cylinder High */
+#define ATA_CH			0x044
+/* ATA Select Card/Head */
+#define ATA_SH			0x048
+/* ATA Status-Command */
+#define ATA_STS_CMD		0x04C
+/* ATA Alternate Status/Device Control */
+#define ATA_ASTS_DCTR		0x050
+/* Extended Write Data Port 0x200-0x3FC */
+#define EXT_WRITE_PORT		0x200
+/* Extended Read Data Port 0x400-0x5FC */
+#define EXT_READ_PORT		0x400
+	#define FIFO_SIZE	0x200u
+/* Global Interrupt Status */
+#define GIRQ_STS		0x800
+/* Global Interrupt Status enable */
+#define GIRQ_STS_EN		0x804
+/* Global Interrupt Signal enable */
+#define GIRQ_SGN_EN		0x808
+	#define GIRQ_CF		(1)
+	#define GIRQ_XD		(1 << 1)
+
+/* Compact Flash Controller Dev Structure */
+struct arasan_cf_dev {
+	/* pointer to ata_host structure */
+	struct ata_host *host;
+	/* clk structure, only if HAVE_CLK is defined */
+#ifdef CONFIG_HAVE_CLK
+	struct clk *clk;
+#endif
+
+	/* physical base address of controller */
+	dma_addr_t pbase;
+	/* virtual base address of controller */
+	void __iomem *vbase;
+	/* irq number*/
+	int irq;
+
+	/* status to be updated to framework regarding DMA transfer */
+	u8 dma_status;
+	/* Card is present or Not */
+	u8 card_present;
+
+	/* dma specific */
+	/* Completion for transfer complete interrupt from controller */
+	struct completion cf_completion;
+	/* Completion for DMA transfer complete. */
+	struct completion dma_completion;
+	/* Dma channel allocated */
+	struct dma_chan *dma_chan;
+	/* Mask for DMA transfers */
+	dma_cap_mask_t mask;
+	/* dma channel private data */
+	void *dma_priv;
+	/* DMA transfer work */
+	struct work_struct work;
+	/* DMA delayed finish work */
+	struct delayed_work dwork;
+	/* qc to be transferred using DMA */
+	struct ata_queued_cmd *qc;
+};
+
+static struct scsi_host_template arasan_cf_sht = {
+	ATA_BASE_SHT(DRIVER_NAME),
+	.sg_tablesize = SG_NONE,
+	.dma_boundary = 0xFFFFFFFFUL,
+};
+
+static void cf_dumpregs(struct arasan_cf_dev *acdev)
+{
+	struct device *dev = acdev->host->dev;
+
+	dev_dbg(dev, ": =========== REGISTER DUMP ===========");
+	dev_dbg(dev, ": CFI_STS: %x", readl(acdev->vbase + CFI_STS));
+	dev_dbg(dev, ": IRQ_STS: %x", readl(acdev->vbase + IRQ_STS));
+	dev_dbg(dev, ": IRQ_EN: %x", readl(acdev->vbase + IRQ_EN));
+	dev_dbg(dev, ": OP_MODE: %x", readl(acdev->vbase + OP_MODE));
+	dev_dbg(dev, ": CLK_CFG: %x", readl(acdev->vbase + CLK_CFG));
+	dev_dbg(dev, ": TM_CFG: %x", readl(acdev->vbase + TM_CFG));
+	dev_dbg(dev, ": XFER_CTR: %x", readl(acdev->vbase + XFER_CTR));
+	dev_dbg(dev, ": GIRQ_STS: %x", readl(acdev->vbase + GIRQ_STS));
+	dev_dbg(dev, ": GIRQ_STS_EN: %x", readl(acdev->vbase + GIRQ_STS_EN));
+	dev_dbg(dev, ": GIRQ_SGN_EN: %x", readl(acdev->vbase + GIRQ_SGN_EN));
+	dev_dbg(dev, ": =====================================");
+}
+
+/* Enable/Disable global interrupts shared between CF and XD ctrlr. */
+static void cf_ginterrupt_enable(struct arasan_cf_dev *acdev, bool enable)
+{
+	/* enable should be 0 or 1 */
+	writel(enable, acdev->vbase + GIRQ_STS_EN);
+	writel(enable, acdev->vbase + GIRQ_SGN_EN);
+}
+
+/* Enable/Disable CF interrupts */
+static inline void
+cf_interrupt_enable(struct arasan_cf_dev *acdev, u32 mask, bool enable)
+{
+	u32 val = readl(acdev->vbase + IRQ_EN);
+	/* clear & enable/disable irqs */
+	if (enable) {
+		writel(mask, acdev->vbase + IRQ_STS);
+		writel(val | mask, acdev->vbase + IRQ_EN);
+	} else
+		writel(val & ~mask, acdev->vbase + IRQ_EN);
+}
+
+static inline void cf_card_reset(struct arasan_cf_dev *acdev)
+{
+	u32 val = readl(acdev->vbase + OP_MODE);
+
+	writel(val | CARD_RESET, acdev->vbase + OP_MODE);
+	udelay(200);
+	writel(val & ~CARD_RESET, acdev->vbase + OP_MODE);
+}
+
+static inline void cf_ctrl_reset(struct arasan_cf_dev *acdev)
+{
+	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB,
+			acdev->vbase + OP_MODE);
+	writel(readl(acdev->vbase + OP_MODE) | CFHOST_ENB,
+			acdev->vbase + OP_MODE);
+}
+
+static void cf_card_detect(struct arasan_cf_dev *acdev, bool hotplugged)
+{
+	struct ata_port *ap = acdev->host->ports[0];
+	struct ata_eh_info *ehi = &ap->link.eh_info;
+	u32 val = readl(acdev->vbase + CFI_STS);
+
+	/* Both CD1 & CD2 should be low if card inserted completely */
+	if (!(val & (CARD_DETECT1 | CARD_DETECT2))) {
+		if (acdev->card_present)
+			return;
+		acdev->card_present = 1;
+		cf_card_reset(acdev);
+	} else {
+		if (!acdev->card_present)
+			return;
+		acdev->card_present = 0;
+	}
+
+	if (hotplugged) {
+		ata_ehi_hotplugged(ehi);
+		ata_port_freeze(ap);
+	}
+}
+
+static int cf_init(struct arasan_cf_dev *acdev)
+{
+	struct arasan_cf_pdata *pdata = dev_get_platdata(acdev->host->dev);
+	unsigned long flags;
+	int ret = 0;
+
+#ifdef CONFIG_HAVE_CLK
+	ret = clk_enable(acdev->clk);
+	if (ret) {
+		dev_dbg(acdev->host->dev, "clock enable failed");
+		return ret;
+	}
+#endif
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	/* configure CF interface clock */
+	writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
+			CF_IF_CLK_166M, acdev->vbase + CLK_CFG);
+
+	writel(TRUE_IDE_MODE | CFHOST_ENB, acdev->vbase + OP_MODE);
+	cf_interrupt_enable(acdev, CARD_DETECT_IRQ, 1);
+	cf_ginterrupt_enable(acdev, 1);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	return ret;
+}
+
+static void cf_exit(struct arasan_cf_dev *acdev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	cf_ginterrupt_enable(acdev, 0);
+	cf_interrupt_enable(acdev, TRUE_IDE_IRQS, 0);
+	cf_card_reset(acdev);
+	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB,
+			acdev->vbase + OP_MODE);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+#ifdef CONFIG_HAVE_CLK
+	clk_disable(acdev->clk);
+#endif
+}
+
+static void dma_callback(void *dev)
+{
+	struct arasan_cf_dev *acdev = (struct arasan_cf_dev *) dev;
+
+	complete(&acdev->dma_completion);
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	chan->private = slave;
+	return true;
+}
+
+static inline void dma_complete(struct arasan_cf_dev *acdev)
+{
+	struct ata_queued_cmd *qc = acdev->qc;
+	unsigned long flags;
+
+	acdev->qc = NULL;
+	ata_sff_interrupt(acdev->irq, acdev->host);
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+		ata_ehi_push_desc(&qc->ap->link.eh_info, "DMA Failed: Timeout");
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+}
+
+static inline int wait4buf(struct arasan_cf_dev *acdev)
+{
+	if (!wait_for_completion_timeout(&acdev->cf_completion, TIMEOUT)) {
+		u32 rw = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+
+		dev_err(acdev->host->dev, "%s TimeOut", rw ? "write" : "read");
+		return -ETIMEDOUT;
+	}
+
+	/* Check if PIO Error interrupt has occured */
+	if (acdev->dma_status & ATA_DMA_ERR)
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int
+dma_xfer(struct arasan_cf_dev *acdev, dma_addr_t src, dma_addr_t dest, u32 len)
+{
+	struct dma_async_tx_descriptor *tx;
+	struct dma_chan *chan = acdev->dma_chan;
+	dma_cookie_t cookie;
+	unsigned long flags = DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP |
+		DMA_COMPL_SKIP_DEST_UNMAP;
+	int ret = 0;
+
+	tx = chan->device->device_prep_dma_memcpy(chan, dest, src, len, flags);
+	if (!tx) {
+		dev_err(acdev->host->dev, "device_prep_dma_memcpy failed\n");
+		return -EAGAIN;
+	}
+
+	tx->callback = dma_callback;
+	tx->callback_param = acdev;
+	cookie = tx->tx_submit(tx);
+
+	ret = dma_submit_error(cookie);
+	if (ret) {
+		dev_err(acdev->host->dev, "dma_submit_error\n");
+		return ret;
+	}
+
+	chan->device->device_issue_pending(chan);
+
+	/* Wait for DMA to complete */
+	if (!wait_for_completion_timeout(&acdev->dma_completion, TIMEOUT)) {
+		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		dev_err(acdev->host->dev, "wait_for_completion_timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int sg_xfer(struct arasan_cf_dev *acdev, struct scatterlist *sg)
+{
+	dma_addr_t dest = 0, src = 0;
+	u32 xfer_cnt, sglen, dma_len, xfer_ctr;
+	u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+	unsigned long flags;
+	int ret = 0;
+
+	sglen = sg_dma_len(sg);
+	if (write) {
+		src = sg_dma_address(sg);
+		dest = acdev->pbase + EXT_WRITE_PORT;
+	} else {
+		dest = sg_dma_address(sg);
+		src = acdev->pbase + EXT_READ_PORT;
+	}
+
+	/*
+	 * For each sg:
+	 * MAX_XFER_COUNT data will be transferred before we get transfer
+	 * complete interrupt. Inbetween after FIFO_SIZE data
+	 * buffer available interrupt will be generated. At this time we will
+	 * fill FIFO again: max FIFO_SIZE data.
+	 */
+	while (sglen) {
+		xfer_cnt = min(sglen, MAX_XFER_COUNT);
+		spin_lock_irqsave(&acdev->host->lock, flags);
+		xfer_ctr = readl(acdev->vbase + XFER_CTR) &
+			~XFER_COUNT_MASK;
+		writel(xfer_ctr | xfer_cnt | XFER_START,
+				acdev->vbase + XFER_CTR);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+		/* continue dma xfers untill current sg is completed */
+		while (xfer_cnt) {
+			/* wait for read to complete */
+			if (!write) {
+				ret = wait4buf(acdev);
+				if (ret)
+					goto fail;
+			}
+
+			/* read/write FIFO in chunk of FIFO_SIZE */
+			dma_len = min(xfer_cnt, FIFO_SIZE);
+			ret = dma_xfer(acdev, src, dest, dma_len);
+			if (ret) {
+				dev_err(acdev->host->dev, "dma failed");
+				goto fail;
+			}
+
+			if (write)
+				src += dma_len;
+			else
+				dest += dma_len;
+
+			sglen -= dma_len;
+			xfer_cnt -= dma_len;
+
+			/* wait for write to complete */
+			if (write) {
+				ret = wait4buf(acdev);
+				if (ret)
+					goto fail;
+			}
+		}
+	}
+
+fail:
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START,
+			acdev->vbase + XFER_CTR);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	return ret;
+}
+
+/*
+ * This routine uses External DMA controller to read/write data to FIFO of CF
+ * controller. There are two xfer related interrupt supported by CF controller:
+ * - buf_avail: This interrupt is generated as soon as we have buffer of 512
+ *	bytes available for reading or empty buffer available for writing.
+ * - xfer_done: This interrupt is generated on transfer of "xfer_size" amount of
+ *	data to/from FIFO. xfer_size is programmed in XFER_CTR register.
+ *
+ * Max buffer size = FIFO_SIZE = 512 Bytes.
+ * Max xfer_size = MAX_XFER_COUNT = 256 KB.
+ */
+static void data_xfer(struct work_struct *work)
+{
+	struct arasan_cf_dev *acdev = container_of(work, struct arasan_cf_dev,
+			work);
+	struct ata_queued_cmd *qc = acdev->qc;
+	struct scatterlist *sg;
+	unsigned long flags;
+	u32 temp;
+	int ret = 0;
+
+	/* request dma channels */
+	/* dma_request_channel may sleep, so calling from process context */
+	acdev->dma_chan = dma_request_channel(acdev->mask, filter,
+			acdev->dma_priv);
+	if (!acdev->dma_chan) {
+		dev_err(acdev->host->dev, "Unable to get dma_chan\n");
+		goto chan_request_fail;
+	}
+
+	for_each_sg(qc->sg, sg, qc->n_elem, temp) {
+		ret = sg_xfer(acdev, sg);
+		if (ret)
+			break;
+	}
+
+	dma_release_channel(acdev->dma_chan);
+
+	/* data xferred successfully */
+	if (!ret) {
+		u32 status;
+
+		spin_lock_irqsave(&acdev->host->lock, flags);
+		status = ioread8(qc->ap->ioaddr.altstatus_addr);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		if (status & (ATA_BUSY | ATA_DRQ)) {
+			ata_sff_queue_delayed_work(&acdev->dwork, 1);
+			return;
+		}
+
+		goto sff_intr;
+	}
+
+	cf_dumpregs(acdev);
+
+chan_request_fail:
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	/* error when transfering data to/from memory */
+	qc->err_mask |= AC_ERR_HOST_BUS;
+	qc->ap->hsm_task_state = HSM_ST_ERR;
+
+	cf_ctrl_reset(acdev);
+	spin_unlock_irqrestore(qc->ap->lock, flags);
+sff_intr:
+	dma_complete(acdev);
+}
+
+static void delayed_finish(struct work_struct *work)
+{
+	struct arasan_cf_dev *acdev = container_of(work, struct arasan_cf_dev,
+			dwork.work);
+	struct ata_queued_cmd *qc = acdev->qc;
+	unsigned long flags;
+	u8 status;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	status = ioread8(qc->ap->ioaddr.altstatus_addr);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	if (status & (ATA_BUSY | ATA_DRQ))
+		ata_sff_queue_delayed_work(&acdev->dwork, 1);
+	else
+		dma_complete(acdev);
+}
+
+static irqreturn_t arasan_cf_interrupt(int irq, void *dev)
+{
+	struct arasan_cf_dev *acdev = ((struct ata_host *)dev)->private_data;
+	unsigned long flags;
+	u32 irqsts;
+
+	irqsts = readl(acdev->vbase + GIRQ_STS);
+	if (!(irqsts & GIRQ_CF))
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	irqsts = readl(acdev->vbase + IRQ_STS);
+	writel(irqsts, acdev->vbase + IRQ_STS);		/* clear irqs */
+	writel(GIRQ_CF, acdev->vbase + GIRQ_STS);	/* clear girqs */
+
+	/* handle only relevant interrupts */
+	irqsts &= ~IGNORED_IRQS;
+
+	if (irqsts & CARD_DETECT_IRQ) {
+		cf_card_detect(acdev, 1);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+	if (irqsts & PIO_XFER_ERR_IRQ) {
+		acdev->dma_status = ATA_DMA_ERR;
+		writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START,
+				acdev->vbase + XFER_CTR);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		complete(&acdev->cf_completion);
+		dev_err(acdev->host->dev, "pio xfer err irq\n");
+		return IRQ_HANDLED;
+	}
+
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	if (irqsts & BUF_AVAIL_IRQ) {
+		complete(&acdev->cf_completion);
+		return IRQ_HANDLED;
+	}
+
+	if (irqsts & XFER_DONE_IRQ) {
+		struct ata_queued_cmd *qc = acdev->qc;
+
+		/* Send Complete only for write */
+		if (qc->tf.flags & ATA_TFLAG_WRITE)
+			complete(&acdev->cf_completion);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void arasan_cf_freeze(struct ata_port *ap)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+
+	/* stop transfer and reset controller */
+	writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START,
+			acdev->vbase + XFER_CTR);
+	cf_ctrl_reset(acdev);
+	acdev->dma_status = ATA_DMA_ERR;
+
+	ata_sff_dma_pause(ap);
+	ata_sff_freeze(ap);
+}
+
+void arasan_cf_error_handler(struct ata_port *ap)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+
+	/*
+	 * DMA transfers using an external DMA controller may be scheduled.
+	 * Abort them before handling error. Refer data_xfer() for further
+	 * details.
+	 */
+	cancel_work_sync(&acdev->work);
+	cancel_delayed_work_sync(&acdev->dwork);
+	return ata_sff_error_handler(ap);
+}
+
+static void arasan_cf_dma_start(struct arasan_cf_dev *acdev)
+{
+	u32 xfer_ctr = readl(acdev->vbase + XFER_CTR) & ~XFER_DIR_MASK;
+	u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+
+	xfer_ctr |= write ? XFER_WRITE : XFER_READ;
+	writel(xfer_ctr, acdev->vbase + XFER_CTR);
+
+	acdev->qc->ap->ops->sff_exec_command(acdev->qc->ap, &acdev->qc->tf);
+	ata_sff_queue_work(&acdev->work);
+}
+
+unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+
+	/* defer PIO handling to sff_qc_issue */
+	if (!ata_is_dma(qc->tf.protocol))
+		return ata_sff_qc_issue(qc);
+
+	/* select the device */
+	ata_wait_idle(ap);
+	ata_sff_dev_select(ap, qc->dev->devno);
+	ata_wait_idle(ap);
+
+	/* start the command */
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
+
+		ap->ops->sff_tf_load(ap, &qc->tf);
+		acdev->dma_status = 0;
+		acdev->qc = qc;
+		arasan_cf_dma_start(acdev);
+		ap->hsm_task_state = HSM_ST_LAST;
+		break;
+
+	default:
+		WARN_ON(1);
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+static void arasan_cf_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+	u8 pio = adev->pio_mode - XFER_PIO_0;
+	unsigned long flags;
+	u32 val;
+
+	/* Arasan ctrl supports Mode0 -> Mode6 */
+	if (pio > 6) {
+		dev_err(ap->dev, "Unknown PIO mode\n");
+		return;
+	}
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	val = readl(acdev->vbase + OP_MODE) &
+		~(ULTRA_DMA_ENB | MULTI_WORD_DMA_ENB | DRQ_BLOCK_SIZE_MASK);
+	writel(val, acdev->vbase + OP_MODE);
+	val = readl(acdev->vbase + TM_CFG) & ~TRUEIDE_PIO_TIMING_MASK;
+	val |= pio << TRUEIDE_PIO_TIMING_SHIFT;
+	writel(val, acdev->vbase + TM_CFG);
+
+	cf_interrupt_enable(acdev, BUF_AVAIL_IRQ | XFER_DONE_IRQ, 0);
+	cf_interrupt_enable(acdev, PIO_XFER_ERR_IRQ, 1);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+}
+
+static void arasan_cf_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+	u32 opmode, tmcfg, dma_mode = adev->dma_mode;
+	unsigned long flags;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	opmode = readl(acdev->vbase + OP_MODE) &
+		~(MULTI_WORD_DMA_ENB | ULTRA_DMA_ENB);
+	tmcfg = readl(acdev->vbase + TM_CFG);
+
+	if ((dma_mode >= XFER_UDMA_0) && (dma_mode <= XFER_UDMA_6)) {
+		opmode |= ULTRA_DMA_ENB;
+		tmcfg &= ~ULTRA_DMA_TIMING_MASK;
+		tmcfg |= (dma_mode - XFER_UDMA_0) << ULTRA_DMA_TIMING_SHIFT;
+	} else if ((dma_mode >= XFER_MW_DMA_0) && (dma_mode <= XFER_MW_DMA_4)) {
+		opmode |= MULTI_WORD_DMA_ENB;
+		tmcfg &= ~TRUEIDE_MWORD_DMA_TIMING_MASK;
+		tmcfg |= (dma_mode - XFER_MW_DMA_0) <<
+			TRUEIDE_MWORD_DMA_TIMING_SHIFT;
+	} else {
+		dev_err(ap->dev, "Unknown DMA mode\n");
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		return;
+	}
+
+	writel(opmode, acdev->vbase + OP_MODE);
+	writel(tmcfg, acdev->vbase + TM_CFG);
+	writel(DMA_XFER_MODE, acdev->vbase + XFER_CTR);
+
+	cf_interrupt_enable(acdev, PIO_XFER_ERR_IRQ, 0);
+	cf_interrupt_enable(acdev, BUF_AVAIL_IRQ | XFER_DONE_IRQ, 1);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+}
+
+static struct ata_port_operations arasan_cf_ops = {
+	.inherits = &ata_sff_port_ops,
+	.freeze = arasan_cf_freeze,
+	.error_handler = arasan_cf_error_handler,
+	.qc_issue = arasan_cf_qc_issue,
+	.set_piomode = arasan_cf_set_piomode,
+	.set_dmamode = arasan_cf_set_dmamode,
+};
+
+static int __devinit arasan_cf_probe(struct platform_device *pdev)
+{
+	struct arasan_cf_dev *acdev;
+	struct arasan_cf_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct ata_host *host;
+	struct ata_port *ap;
+	struct resource *res;
+	irq_handler_t irq_handler = NULL;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				DRIVER_NAME)) {
+		dev_warn(&pdev->dev, "Failed to get memory region resource\n");
+		return -ENOENT;
+	}
+
+	acdev = devm_kzalloc(&pdev->dev, sizeof(*acdev), GFP_KERNEL);
+	if (!acdev) {
+		dev_warn(&pdev->dev, "kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	/* if irq is 0, support only PIO */
+	acdev->irq = platform_get_irq(pdev, 0);
+	if (acdev->irq)
+		irq_handler = arasan_cf_interrupt;
+	else
+		pdata->quirk |= CF_BROKEN_MWDMA | CF_BROKEN_UDMA;
+
+	acdev->pbase = res->start;
+	acdev->vbase = devm_ioremap_nocache(&pdev->dev, res->start,
+			resource_size(res));
+	if (!acdev->vbase) {
+		dev_warn(&pdev->dev, "ioremap fail\n");
+		return -ENOMEM;
+	}
+
+#ifdef CONFIG_HAVE_CLK
+	acdev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(acdev->clk)) {
+		dev_warn(&pdev->dev, "Clock not found\n");
+		return PTR_ERR(acdev->clk);
+	}
+#endif
+
+	/* allocate host */
+	host = ata_host_alloc(&pdev->dev, 1);
+	if (!host) {
+		ret = -ENOMEM;
+		dev_warn(&pdev->dev, "alloc host fail\n");
+		goto free_clk;
+	}
+
+	ap = host->ports[0];
+	host->private_data = acdev;
+	acdev->host = host;
+	ap->ops = &arasan_cf_ops;
+	ap->pio_mask = ATA_PIO6;
+	ap->mwdma_mask = ATA_MWDMA4;
+	ap->udma_mask = ATA_UDMA6;
+
+	init_completion(&acdev->cf_completion);
+	init_completion(&acdev->dma_completion);
+	INIT_WORK(&acdev->work, data_xfer);
+	INIT_DELAYED_WORK(&acdev->dwork, delayed_finish);
+	dma_cap_set(DMA_MEMCPY, acdev->mask);
+	acdev->dma_priv = pdata->dma_priv;
+
+	/* Handle platform specific quirks */
+	if (pdata->quirk) {
+		if (pdata->quirk & CF_BROKEN_PIO) {
+			ap->ops->set_piomode = NULL;
+			ap->pio_mask = 0;
+		}
+		if (pdata->quirk & CF_BROKEN_MWDMA)
+			ap->mwdma_mask = 0;
+		if (pdata->quirk & CF_BROKEN_UDMA)
+			ap->udma_mask = 0;
+	}
+	ap->flags |= ATA_FLAG_PIO_POLLING | ATA_FLAG_NO_ATAPI;
+
+	ap->ioaddr.cmd_addr = acdev->vbase + ATA_DATA_PORT;
+	ap->ioaddr.data_addr = acdev->vbase + ATA_DATA_PORT;
+	ap->ioaddr.error_addr = acdev->vbase + ATA_ERR_FTR;
+	ap->ioaddr.feature_addr = acdev->vbase + ATA_ERR_FTR;
+	ap->ioaddr.nsect_addr = acdev->vbase + ATA_SC;
+	ap->ioaddr.lbal_addr = acdev->vbase + ATA_SN;
+	ap->ioaddr.lbam_addr = acdev->vbase + ATA_CL;
+	ap->ioaddr.lbah_addr = acdev->vbase + ATA_CH;
+	ap->ioaddr.device_addr = acdev->vbase + ATA_SH;
+	ap->ioaddr.status_addr = acdev->vbase + ATA_STS_CMD;
+	ap->ioaddr.command_addr = acdev->vbase + ATA_STS_CMD;
+	ap->ioaddr.altstatus_addr = acdev->vbase + ATA_ASTS_DCTR;
+	ap->ioaddr.ctl_addr = acdev->vbase + ATA_ASTS_DCTR;
+
+	ata_port_desc(ap, "phy_addr %llx virt_addr %p",
+		      (unsigned long long) res->start, acdev->vbase);
+
+	ret = cf_init(acdev);
+	if (ret)
+		goto free_clk;
+
+	cf_card_detect(acdev, 0);
+
+	return ata_host_activate(host, acdev->irq, irq_handler, 0,
+			&arasan_cf_sht);
+
+free_clk:
+#ifdef CONFIG_HAVE_CLK
+	clk_put(acdev->clk);
+#endif
+	return ret;
+}
+
+static int __devexit arasan_cf_remove(struct platform_device *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
+
+	ata_host_detach(host);
+	cf_exit(acdev);
+#ifdef CONFIG_HAVE_CLK
+	clk_put(acdev->clk);
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int arasan_cf_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
+
+	if (acdev->dma_chan) {
+		acdev->dma_chan->device->device_control(acdev->dma_chan,
+				DMA_TERMINATE_ALL, 0);
+		dma_release_channel(acdev->dma_chan);
+	}
+	cf_exit(acdev);
+	return ata_host_suspend(host, PMSG_SUSPEND);
+}
+
+static int arasan_cf_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
+
+	cf_init(acdev);
+	ata_host_resume(host);
+
+	return 0;
+}
+
+static const struct dev_pm_ops arasan_cf_pm_ops = {
+	.suspend	= arasan_cf_suspend,
+	.resume		= arasan_cf_resume,
+};
+#endif
+
+static struct platform_driver arasan_cf_driver = {
+	.probe		= arasan_cf_probe,
+	.remove		= __devexit_p(arasan_cf_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm		= &arasan_cf_pm_ops,
+#endif
+	},
+};
+
+static int __init arasan_cf_init(void)
+{
+	return platform_driver_register(&arasan_cf_driver);
+}
+module_init(arasan_cf_init);
+
+static void __exit arasan_cf_exit(void)
+{
+	platform_driver_unregister(&arasan_cf_driver);
+}
+module_exit(arasan_cf_exit);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
+MODULE_DESCRIPTION("Arasan ATA Compact Flash driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
index 66ce6a5..36f189c 100644
--- a/drivers/ata/pata_at32.c
+++ b/drivers/ata/pata_at32.c
@@ -194,7 +194,7 @@ static int __init pata_at32_init_one(struct device *dev,
 	/* Setup ATA bindings */
 	ap->ops	     = &at32_port_ops;
 	ap->pio_mask = PIO_MASK;
-	ap->flags   |= ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS;
+	ap->flags   |= ATA_FLAG_SLAVE_POSS;
 
 	/*
 	 * Since all 8-bit taskfile transfers has to go on the lower
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
index 7aed5c7..e0b58b8 100644
--- a/drivers/ata/pata_bf54x.c
+++ b/drivers/ata/pata_bf54x.c
@@ -1454,9 +1454,7 @@ static struct ata_port_operations bfin_pata_ops = {
 
 static struct ata_port_info bfin_port_info[] = {
 	{
-		.flags		= ATA_FLAG_SLAVE_POSS
-				| ATA_FLAG_MMIO
-				| ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= 0,
 		.udma_mask	= 0,
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c
index 538ec38..6c77d68 100644
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -14,6 +14,7 @@
  *	Look into engine reset on timeout errors. Should not be required.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -25,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt366"
-#define DRV_VERSION	"0.6.10"
+#define DRV_VERSION	"0.6.11"
 
 struct hpt_clock {
 	u8	xfer_mode;
@@ -160,8 +161,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
 
 	while (list[i] != NULL) {
 		if (!strcmp(list[i], model_num)) {
-			pr_warning(DRV_NAME ": %s is not supported for %s.\n",
-				   modestr, list[i]);
+			pr_warn("%s is not supported for %s\n",
+				modestr, list[i]);
 			return 1;
 		}
 		i++;
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
index 4c5b518..9620636 100644
--- a/drivers/ata/pata_hpt37x.c
+++ b/drivers/ata/pata_hpt37x.c
@@ -14,6 +14,8 @@
  *	Look into engine reset on timeout errors. Should not be	required.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -24,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt37x"
-#define DRV_VERSION	"0.6.22"
+#define DRV_VERSION	"0.6.23"
 
 struct hpt_clock {
 	u8	xfer_speed;
@@ -229,8 +231,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr,
 
 	while (list[i] != NULL) {
 		if (!strcmp(list[i], model_num)) {
-			pr_warning(DRV_NAME ": %s is not supported for %s.\n",
-				   modestr, list[i]);
+			pr_warn("%s is not supported for %s\n",
+				modestr, list[i]);
 			return 1;
 		}
 		i++;
@@ -863,8 +865,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 			chip_table = &hpt372;
 			break;
 		default:
-			pr_err(DRV_NAME ": Unknown HPT366 subtype, "
-			       "please report (%d).\n", rev);
+			pr_err("Unknown HPT366 subtype, please report (%d)\n",
+			       rev);
 			return -ENODEV;
 		}
 		break;
@@ -904,8 +906,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 			*ppi = &info_hpt374_fn1;
 		break;
 	default:
-		pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
-		       dev->device);
+		pr_err("PCI table is bogus, please report (%d)\n", dev->device);
 		return -ENODEV;
 	}
 	/* Ok so this is a chip we support */
@@ -953,7 +954,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		u8 sr;
 		u32 total = 0;
 
-		pr_warning(DRV_NAME ": BIOS has not set timing clocks.\n");
+		pr_warn("BIOS has not set timing clocks\n");
 
 		/* This is the process the HPT371 BIOS is reported to use */
 		for (i = 0; i < 128; i++) {
@@ -1009,7 +1010,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 					       (f_high << 16) | f_low | 0x100);
 		}
 		if (adjust == 8) {
-			pr_err(DRV_NAME ": DPLL did not stabilize!\n");
+			pr_err("DPLL did not stabilize!\n");
 			return -ENODEV;
 		}
 		if (dpll == 3)
@@ -1017,7 +1018,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		else
 			private_data = (void *)hpt37x_timings_50;
 
-		pr_info(DRV_NAME ": bus clock %dMHz, using %dMHz DPLL.\n",
+		pr_info("bus clock %dMHz, using %dMHz DPLL\n",
 			MHz[clock_slot], MHz[dpll]);
 	} else {
 		private_data = (void *)chip_table->clocks[clock_slot];
@@ -1032,7 +1033,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 		if (clock_slot < 2 && ppi[0] == &info_hpt370a)
 			ppi[0] = &info_hpt370a_33;
 
-		pr_info(DRV_NAME ": %s using %dMHz bus clock.\n",
+		pr_info("%s using %dMHz bus clock\n",
 			chip_table->name, MHz[clock_slot]);
 	}
 
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c
index eca68ca..765f136 100644
--- a/drivers/ata/pata_hpt3x2n.c
+++ b/drivers/ata/pata_hpt3x2n.c
@@ -15,6 +15,8 @@
  *	Work out best PLL policy
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -25,7 +27,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt3x2n"
-#define DRV_VERSION	"0.3.14"
+#define DRV_VERSION	"0.3.15"
 
 enum {
 	HPT_PCI_FAST	=	(1 << 31),
@@ -418,7 +420,7 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev)
 		u16 sr;
 		u32 total = 0;
 
-		pr_warning(DRV_NAME ": BIOS clock data not set.\n");
+		pr_warn("BIOS clock data not set\n");
 
 		/* This is the process the HPT371 BIOS is reported to use */
 		for (i = 0; i < 128; i++) {
@@ -528,8 +530,7 @@ hpt372n:
 		ppi[0] = &info_hpt372n;
 		break;
 	default:
-		pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
-		       dev->device);
+		pr_err("PCI table is bogus, please report (%d)\n", dev->device);
 		return -ENODEV;
 	}
 
@@ -578,11 +579,11 @@ hpt372n:
 		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
 	}
 	if (adjust == 8) {
-		pr_err(DRV_NAME ": DPLL did not stabilize!\n");
+		pr_err("DPLL did not stabilize!\n");
 		return -ENODEV;
 	}
 
-	pr_info(DRV_NAME ": bus clock %dMHz, using 66MHz DPLL.\n", pci_mhz);
+	pr_info("bus clock %dMHz, using 66MHz DPLL\n", pci_mhz);
 
 	/*
 	 * Set our private data up. We only need a few flags
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c
index b63d5e2..24d7df8 100644
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -151,7 +151,7 @@ static struct ata_port_operations hpt3x3_port_ops = {
 	.check_atapi_dma= hpt3x3_atapi_dma,
 	.freeze		= hpt3x3_freeze,
 #endif
-	
+
 };
 
 /**
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
index aa0e0c5..2d15f25 100644
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -616,7 +616,7 @@ static void it821x_display_disk(int n, u8 *buf)
 	if (buf[52] > 4)	/* No Disk */
 		return;
 
-	ata_id_c_string((u16 *)buf, id, 0, 41); 
+	ata_id_c_string((u16 *)buf, id, 0, 41);
 
 	if (buf[51]) {
 		mode = ffs(buf[51]);
@@ -910,7 +910,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
-		
+
 	if (pdev->vendor == PCI_VENDOR_ID_RDC) {
 		/* Deal with Vortex86SX */
 		if (pdev->revision == 0x11)
diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
index ba54b08..5253b27 100644
--- a/drivers/ata/pata_ixp4xx_cf.c
+++ b/drivers/ata/pata_ixp4xx_cf.c
@@ -177,7 +177,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev)
 
 	ap->ops	= &ixp4xx_port_ops;
 	ap->pio_mask = ATA_PIO4;
-	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
+	ap->flags |= ATA_FLAG_NO_ATAPI;
 
 	ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
 
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c
index 75b49d0..46f589e 100644
--- a/drivers/ata/pata_macio.c
+++ b/drivers/ata/pata_macio.c
@@ -1053,8 +1053,7 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv	*priv,
 	/* Allocate libata host for 1 port */
 	memset(&pinfo, 0, sizeof(struct ata_port_info));
 	pmac_macio_calc_timing_masks(priv, &pinfo);
-	pinfo.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO |
-				  ATA_FLAG_NO_LEGACY;
+	pinfo.flags		= ATA_FLAG_SLAVE_POSS;
 	pinfo.port_ops		= &pata_macio_ops;
 	pinfo.private_data	= priv;
 
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c
index dd38083..75a6a0c 100644
--- a/drivers/ata/pata_marvell.c
+++ b/drivers/ata/pata_marvell.c
@@ -38,7 +38,7 @@ static int marvell_pata_active(struct pci_dev *pdev)
 
 	/* We don't yet know how to do this for other devices */
 	if (pdev->device != 0x6145)
-		return 1;	
+		return 1;
 
 	barp = pci_iomap(pdev, 5, 0x10);
 	if (barp == NULL)
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index d7d8026..2fcac51 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -680,7 +680,7 @@ mpc52xx_ata_remove_one(struct device *dev)
 /* ======================================================================== */
 
 static int __devinit
-mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)
+mpc52xx_ata_probe(struct platform_device *op)
 {
 	unsigned int ipb_freq;
 	struct resource res_mem;
@@ -883,7 +883,7 @@ static struct of_device_id mpc52xx_ata_of_match[] = {
 };
 
 
-static struct of_platform_driver mpc52xx_ata_of_platform_driver = {
+static struct platform_driver mpc52xx_ata_of_platform_driver = {
 	.probe		= mpc52xx_ata_probe,
 	.remove		= mpc52xx_ata_remove,
 #ifdef CONFIG_PM
@@ -906,13 +906,13 @@ static int __init
 mpc52xx_ata_init(void)
 {
 	printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
-	return of_register_platform_driver(&mpc52xx_ata_of_platform_driver);
+	return platform_driver_register(&mpc52xx_ata_of_platform_driver);
 }
 
 static void __exit
 mpc52xx_ata_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver);
+	platform_driver_unregister(&mpc52xx_ata_of_platform_driver);
 }
 
 module_init(mpc52xx_ata_init);
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
index cc50bd0..e277a14 100644
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -165,7 +165,7 @@ static int ninja32_reinit_one(struct pci_dev *pdev)
 		return rc;
 	ninja32_program(host->iomap[0]);
 	ata_host_resume(host);
-	return 0;			
+	return 0;
 }
 #endif
 
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c
index fa1b95a..220ddc9 100644
--- a/drivers/ata/pata_octeon_cf.c
+++ b/drivers/ata/pata_octeon_cf.c
@@ -848,8 +848,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev)
 	cf_port->ap = ap;
 	ap->ops = &octeon_cf_ops;
 	ap->pio_mask = ATA_PIO6;
-	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
-		  | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
+	ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
 
 	base = cs0 + ocd->base_region_bias;
 	if (!ocd->is16bit) {
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 480e043..f305400 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -14,8 +14,7 @@
 #include <linux/of_platform.h>
 #include <linux/ata_platform.h>
 
-static int __devinit pata_of_platform_probe(struct platform_device *ofdev,
-					    const struct of_device_id *match)
+static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
 {
 	int ret;
 	struct device_node *dn = ofdev->dev.of_node;
@@ -90,7 +89,7 @@ static struct of_device_id pata_of_platform_match[] = {
 };
 MODULE_DEVICE_TABLE(of, pata_of_platform_match);
 
-static struct of_platform_driver pata_of_platform_driver = {
+static struct platform_driver pata_of_platform_driver = {
 	.driver = {
 		.name = "pata_of_platform",
 		.owner = THIS_MODULE,
@@ -102,13 +101,13 @@ static struct of_platform_driver pata_of_platform_driver = {
 
 static int __init pata_of_platform_init(void)
 {
-	return of_register_platform_driver(&pata_of_platform_driver);
+	return platform_driver_register(&pata_of_platform_driver);
 }
 module_init(pata_of_platform_init);
 
 static void __exit pata_of_platform_exit(void)
 {
-	of_unregister_platform_driver(&pata_of_platform_driver);
+	platform_driver_unregister(&pata_of_platform_driver);
 }
 module_exit(pata_of_platform_exit);
 
diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c
index 11fb4cc..a2a73d9 100644
--- a/drivers/ata/pata_palmld.c
+++ b/drivers/ata/pata_palmld.c
@@ -85,7 +85,7 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev)
 	ap = host->ports[0];
 	ap->ops	= &palmld_port_ops;
 	ap->pio_mask = ATA_PIO4;
-	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_PIO_POLLING;
+	ap->flags |= ATA_FLAG_PIO_POLLING;
 
 	/* memory mapping voodoo */
 	ap->ioaddr.cmd_addr = mem + 0x10;
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
index 8062921..29af660 100644
--- a/drivers/ata/pata_pcmcia.c
+++ b/drivers/ata/pata_pcmcia.c
@@ -124,7 +124,7 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
  *	reset will recover the device.
  *
  */
- 
+
 static void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
 {
 	int count;
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
index b183511..9765ace 100644
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -150,8 +150,7 @@ static struct ata_port_operations pdc2027x_pata133_ops = {
 static struct ata_port_info pdc2027x_port_info[] = {
 	/* PDC_UDMA_100 */
 	{
-		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
-		                  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
@@ -159,8 +158,7 @@ static struct ata_port_info pdc2027x_port_info[] = {
 	},
 	/* PDC_UDMA_133 */
 	{
-		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
-                        	  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/pata_pxa.c b/drivers/ata/pata_pxa.c
index 1898c6e..b4ede40 100644
--- a/drivers/ata/pata_pxa.c
+++ b/drivers/ata/pata_pxa.c
@@ -292,7 +292,6 @@ static int __devinit pxa_ata_probe(struct platform_device *pdev)
 	ap->ops		= &pxa_ata_port_ops;
 	ap->pio_mask	= ATA_PIO4;
 	ap->mwdma_mask	= ATA_MWDMA2;
-	ap->flags	= ATA_FLAG_MMIO;
 
 	ap->ioaddr.cmd_addr	= devm_ioremap(&pdev->dev, cmd_res->start,
 						resource_size(cmd_res));
diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c
index 0ffd631..baeaf938 100644
--- a/drivers/ata/pata_rb532_cf.c
+++ b/drivers/ata/pata_rb532_cf.c
@@ -91,7 +91,6 @@ static void rb532_pata_setup_ports(struct ata_host *ah)
 
 	ap->ops		= &rb532_pata_port_ops;
 	ap->pio_mask	= ATA_PIO4;
-	ap->flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
 
 	ap->ioaddr.cmd_addr	= info->iobase + RB500_CF_REG_BASE;
 	ap->ioaddr.ctl_addr	= info->iobase + RB500_CF_REG_CTRL;
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c
index 8a51d67..c446ae6 100644
--- a/drivers/ata/pata_samsung_cf.c
+++ b/drivers/ata/pata_samsung_cf.c
@@ -531,7 +531,6 @@ static int __init pata_s3c_probe(struct platform_device *pdev)
 	}
 
 	ap = host->ports[0];
-	ap->flags |= ATA_FLAG_MMIO;
 	ap->pio_mask = ATA_PIO4;
 
 	if (cpu_type == TYPE_S3C64XX) {
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
index 093715c..88ea9b6 100644
--- a/drivers/ata/pata_scc.c
+++ b/drivers/ata/pata_scc.c
@@ -959,7 +959,7 @@ static struct ata_port_operations scc_pata_ops = {
 
 static struct ata_port_info scc_port_info[] = {
 	{
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		/* No MWDMA */
 		.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 60cea13..c04abc3 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -593,7 +593,7 @@ static const struct ata_port_info sis_info133 = {
 	.port_ops	= &sis_133_ops,
 };
 const struct ata_port_info sis_info133_for_sata = {
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
 	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
index adbe042..1111712 100644
--- a/drivers/ata/pdc_adma.c
+++ b/drivers/ata/pdc_adma.c
@@ -166,9 +166,7 @@ static struct ata_port_operations adma_ata_ops = {
 static struct ata_port_info adma_port_info[] = {
 	/* board_1841_idx */
 	{
-		.flags		= ATA_FLAG_SLAVE_POSS |
-				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
-				  ATA_FLAG_PIO_POLLING,
+		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= ATA_PIO4_ONLY,
 		.udma_mask	= ATA_UDMA4,
 		.port_ops	= &adma_ata_ops,
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 6cf57c5..1c4b3aa 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -40,8 +40,11 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 
+/* These two are defined in "libata.h" */
+#undef	DRV_NAME
+#undef	DRV_VERSION
 #define DRV_NAME        "sata-dwc"
-#define DRV_VERSION     "1.0"
+#define DRV_VERSION     "1.3"
 
 /* SATA DMA driver Globals */
 #define DMA_NUM_CHANS		1
@@ -333,11 +336,47 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
 			      void __iomem *addr, int dir);
 static void dma_dwc_xfer_start(int dma_ch);
 
+static const char *get_prot_descript(u8 protocol)
+{
+	switch ((enum ata_tf_protocols)protocol) {
+	case ATA_PROT_NODATA:
+		return "ATA no data";
+	case ATA_PROT_PIO:
+		return "ATA PIO";
+	case ATA_PROT_DMA:
+		return "ATA DMA";
+	case ATA_PROT_NCQ:
+		return "ATA NCQ";
+	case ATAPI_PROT_NODATA:
+		return "ATAPI no data";
+	case ATAPI_PROT_PIO:
+		return "ATAPI PIO";
+	case ATAPI_PROT_DMA:
+		return "ATAPI DMA";
+	default:
+		return "unknown";
+	}
+}
+
+static const char *get_dma_dir_descript(int dma_dir)
+{
+	switch ((enum dma_data_direction)dma_dir) {
+	case DMA_BIDIRECTIONAL:
+		return "bidirectional";
+	case DMA_TO_DEVICE:
+		return "to device";
+	case DMA_FROM_DEVICE:
+		return "from device";
+	default:
+		return "none";
+	}
+}
+
 static void sata_dwc_tf_dump(struct ata_taskfile *tf)
 {
 	dev_vdbg(host_pvt.dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags:"
-		"0x%lx device: %x\n", tf->command, ata_get_cmd_descript\
-		(tf->protocol), tf->flags, tf->device);
+		"0x%lx device: %x\n", tf->command,
+		get_prot_descript(tf->protocol), tf->flags, tf->device);
 	dev_vdbg(host_pvt.dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x "
 		"lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal,
 		 tf->lbam, tf->lbah);
@@ -715,7 +754,7 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
 	/* Program the CTL register with src enable / dst enable */
 	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].ctl.low),
 		 DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN);
-	return 0;
+	return dma_ch;
 }
 
 /*
@@ -967,7 +1006,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
 		}
 
 		dev_dbg(ap->dev, "%s non-NCQ cmd interrupt, protocol: %s\n",
-			__func__, ata_get_cmd_descript(qc->tf.protocol));
+			__func__, get_prot_descript(qc->tf.protocol));
 DRVSTILLBUSY:
 		if (ata_is_dma(qc->tf.protocol)) {
 			/*
@@ -1057,7 +1096,7 @@ DRVSTILLBUSY:
 
 		/* Process completed command */
 		dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__,
-			ata_get_cmd_descript(qc->tf.protocol));
+			get_prot_descript(qc->tf.protocol));
 		if (ata_is_dma(qc->tf.protocol)) {
 			host_pvt.dma_interrupt_count++;
 			if (hsdevp->dma_pending[tag] == \
@@ -1142,8 +1181,8 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
 	if (tag > 0) {
 		dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s "
 			 "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command,
-			 ata_get_cmd_descript(qc->dma_dir),
-			 ata_get_cmd_descript(qc->tf.protocol),
+			 get_dma_dir_descript(qc->dma_dir),
+			 get_prot_descript(qc->tf.protocol),
 			 in_le32(&(hsdev->sata_dwc_regs->dmacr)));
 	}
 #endif
@@ -1354,7 +1393,7 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap,
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
 	dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command,
-		ata_get_cmd_descript(tf), tag);
+		ata_get_cmd_descript(tf->command), tag);
 
 	spin_lock_irqsave(&ap->host->lock, flags);
 	hsdevp->cmd_issued[tag] = cmd_issued;
@@ -1413,7 +1452,7 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag)
 
 	dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s "
 		"start_dma? %x\n", __func__, qc, tag, qc->tf.command,
-		ata_get_cmd_descript(qc->dma_dir), start_dma);
+		get_dma_dir_descript(qc->dma_dir), start_dma);
 	sata_dwc_tf_dump(&(qc->tf));
 
 	if (start_dma) {
@@ -1462,10 +1501,9 @@ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
 	int dma_chan;
 	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-	int err;
 
 	dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n",
-		__func__, ap->port_no, ata_get_cmd_descript(qc->dma_dir),
+		__func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),
 		 qc->n_elem);
 
 	dma_chan = dma_dwc_xfer_setup(sg, qc->n_elem, hsdevp->llit[tag],
@@ -1474,7 +1512,7 @@ static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag)
 				      dmadr), qc->dma_dir);
 	if (dma_chan < 0) {
 		dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n",
-			__func__, err);
+			__func__, dma_chan);
 		return;
 	}
 	hsdevp->dma_chan[tag] = dma_chan;
@@ -1491,8 +1529,8 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc)
 		dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d "
 			 "prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n",
 			 __func__, ap->print_id, qc->tf.command,
-			 ata_get_cmd_descript(&qc->tf),
-			 qc->tag, ata_get_cmd_descript(qc->tf.protocol),
+			 ata_get_cmd_descript(qc->tf.command),
+			 qc->tag, get_prot_descript(qc->tf.protocol),
 			 ap->link.active_tag, ap->link.sactive);
 #endif
 
@@ -1533,7 +1571,7 @@ static void sata_dwc_qc_prep(struct ata_queued_cmd *qc)
 #ifdef DEBUG_NCQ
 	if (qc->tag > 0)
 		dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n",
-			 __func__, tag, qc->ap->link.active_tag);
+			 __func__, qc->tag, qc->ap->link.active_tag);
 
 	return ;
 #endif
@@ -1580,16 +1618,14 @@ static struct ata_port_operations sata_dwc_ops = {
 
 static const struct ata_port_info sata_dwc_port_info[] = {
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
-		.pio_mask	= 0x1f,	/* pio 0-4 */
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NCQ,
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &sata_dwc_ops,
 	},
 };
 
-static int sata_dwc_probe(struct platform_device *ofdev,
-			const struct of_device_id *match)
+static int sata_dwc_probe(struct platform_device *ofdev)
 {
 	struct sata_dwc_device *hsdev;
 	u32 idr, versionr;
@@ -1727,7 +1763,7 @@ static const struct of_device_id sata_dwc_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sata_dwc_match);
 
-static struct of_platform_driver sata_dwc_driver = {
+static struct platform_driver sata_dwc_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -1739,12 +1775,12 @@ static struct of_platform_driver sata_dwc_driver = {
 
 static int __init sata_dwc_init(void)
 {
-	return	of_register_platform_driver(&sata_dwc_driver);
+	return platform_driver_register(&sata_dwc_driver);
 }
 
 static void __exit sata_dwc_exit(void)
 {
-	of_unregister_platform_driver(&sata_dwc_driver);
+	platform_driver_unregister(&sata_dwc_driver);
 }
 
 module_init(sata_dwc_init);
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index b0214d0..0f91e58 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -6,7 +6,7 @@
  * Author: Ashish Kalra <ashish.kalra@freescale.com>
  * Li Yang <leoli@freescale.com>
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006-2007, 2011 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -33,8 +33,7 @@ enum {
 	SATA_FSL_MAX_PRD_USABLE	= SATA_FSL_MAX_PRD - 1,
 	SATA_FSL_MAX_PRD_DIRECT	= 16,	/* Direct PRDT entries */
 
-	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
 				ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN),
 
 	SATA_FSL_MAX_CMDS	= SATA_FSL_QUEUE_DEPTH,
@@ -158,7 +157,8 @@ enum {
 	    IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE,
 
 	EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31),
-	DATA_SNOOP_ENABLE = (1 << 22),
+	DATA_SNOOP_ENABLE_V1 = (1 << 22),
+	DATA_SNOOP_ENABLE_V2 = (1 << 28),
 };
 
 /*
@@ -186,6 +186,11 @@ enum {
 	COMMANDSTAT = 0x20,
 };
 
+/* TRANSCFG (transport-layer) configuration control */
+enum {
+	TRANSCFG_RX_WATER_MARK = (1 << 4),
+};
+
 /* PHY (link-layer) configuration control */
 enum {
 	PHY_BIST_ENABLE = 0x01,
@@ -256,6 +261,7 @@ struct sata_fsl_host_priv {
 	void __iomem *ssr_base;
 	void __iomem *csr_base;
 	int irq;
+	int data_snoop;
 };
 
 static inline unsigned int sata_fsl_tag(unsigned int tag,
@@ -308,7 +314,8 @@ static void sata_fsl_setup_cmd_hdr_entry(struct sata_fsl_port_priv *pp,
 }
 
 static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
-				     u32 *ttl, dma_addr_t cmd_desc_paddr)
+				     u32 *ttl, dma_addr_t cmd_desc_paddr,
+				     int data_snoop)
 {
 	struct scatterlist *sg;
 	unsigned int num_prde = 0;
@@ -358,8 +365,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
 
 		ttl_dwords += sg_len;
 		prd->dba = cpu_to_le32(sg_addr);
-		prd->ddc_and_ext =
-		    cpu_to_le32(DATA_SNOOP_ENABLE | (sg_len & ~0x03));
+		prd->ddc_and_ext = cpu_to_le32(data_snoop | (sg_len & ~0x03));
 
 		VPRINTK("sg_fill, ttl=%d, dba=0x%x, ddc=0x%x\n",
 			ttl_dwords, prd->dba, prd->ddc_and_ext);
@@ -374,7 +380,7 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
 		/* set indirect extension flag along with indirect ext. size */
 		prd_ptr_to_indirect_ext->ddc_and_ext =
 		    cpu_to_le32((EXT_INDIRECT_SEG_PRD_FLAG |
-				 DATA_SNOOP_ENABLE |
+				 data_snoop |
 				 (indirect_ext_segment_sz & ~0x03)));
 	}
 
@@ -417,7 +423,8 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
 
 	if (qc->flags & ATA_QCFLAG_DMAMAP)
 		num_prde = sata_fsl_fill_sg(qc, (void *)cd,
-					    &ttl_dwords, cd_paddr);
+					    &ttl_dwords, cd_paddr,
+					    host_priv->data_snoop);
 
 	if (qc->tf.protocol == ATA_PROT_NCQ)
 		desc_info |= FPDMA_QUEUED_CMD;
@@ -1040,12 +1047,15 @@ static void sata_fsl_error_intr(struct ata_port *ap)
 
 		/* find out the offending link and qc */
 		if (ap->nr_pmp_links) {
+			unsigned int dev_num;
+
 			dereg = ioread32(hcr_base + DE);
 			iowrite32(dereg, hcr_base + DE);
 			iowrite32(cereg, hcr_base + CE);
 
-			if (dereg < ap->nr_pmp_links) {
-				link = &ap->pmp_link[dereg];
+			dev_num = ffs(dereg) - 1;
+			if (dev_num < ap->nr_pmp_links && dereg != 0) {
+				link = &ap->pmp_link[dev_num];
 				ehi = &link->eh_info;
 				qc = ata_qc_from_tag(ap, link->active_tag);
 				/*
@@ -1293,8 +1303,7 @@ static const struct ata_port_info sata_fsl_port_info[] = {
 	 },
 };
 
-static int sata_fsl_probe(struct platform_device *ofdev,
-			const struct of_device_id *match)
+static int sata_fsl_probe(struct platform_device *ofdev)
 {
 	int retval = -ENXIO;
 	void __iomem *hcr_base = NULL;
@@ -1303,6 +1312,7 @@ static int sata_fsl_probe(struct platform_device *ofdev,
 	struct sata_fsl_host_priv *host_priv = NULL;
 	int irq;
 	struct ata_host *host;
+	u32 temp;
 
 	struct ata_port_info pi = sata_fsl_port_info[0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -1317,6 +1327,12 @@ static int sata_fsl_probe(struct platform_device *ofdev,
 	ssr_base = hcr_base + 0x100;
 	csr_base = hcr_base + 0x140;
 
+	if (!of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc8315-sata")) {
+		temp = ioread32(csr_base + TRANSCFG);
+		temp = temp & 0xffffffe0;
+		iowrite32(temp | TRANSCFG_RX_WATER_MARK, csr_base + TRANSCFG);
+	}
+
 	DPRINTK("@reset i/o = 0x%x\n", ioread32(csr_base + TRANSCFG));
 	DPRINTK("sizeof(cmd_desc) = %d\n", sizeof(struct command_desc));
 	DPRINTK("sizeof(#define cmd_desc) = %d\n", SATA_FSL_CMD_DESC_SIZE);
@@ -1336,6 +1352,11 @@ static int sata_fsl_probe(struct platform_device *ofdev,
 	}
 	host_priv->irq = irq;
 
+	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,pq-sata-v2"))
+		host_priv->data_snoop = DATA_SNOOP_ENABLE_V2;
+	else
+		host_priv->data_snoop = DATA_SNOOP_ENABLE_V1;
+
 	/* allocate host structure */
 	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
 
@@ -1418,12 +1439,15 @@ static struct of_device_id fsl_sata_match[] = {
 	{
 		.compatible = "fsl,pq-sata",
 	},
+	{
+		.compatible = "fsl,pq-sata-v2",
+	},
 	{},
 };
 
 MODULE_DEVICE_TABLE(of, fsl_sata_match);
 
-static struct of_platform_driver fsl_sata_driver = {
+static struct platform_driver fsl_sata_driver = {
 	.driver = {
 		.name = "fsl-sata",
 		.owner = THIS_MODULE,
@@ -1439,13 +1463,13 @@ static struct of_platform_driver fsl_sata_driver = {
 
 static int __init sata_fsl_init(void)
 {
-	of_register_platform_driver(&fsl_sata_driver);
+	platform_driver_register(&fsl_sata_driver);
 	return 0;
 }
 
 static void __exit sata_fsl_exit(void)
 {
-	of_unregister_platform_driver(&fsl_sata_driver);
+	platform_driver_unregister(&fsl_sata_driver);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index bf74a36..cd40651 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -160,8 +160,7 @@ enum {
 	/* Host Flags */
 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
 
-	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
+	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_PIO_POLLING,
 
 	MV_GEN_I_FLAGS		= MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI,
 
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 7254e25..42344e3 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -539,7 +539,7 @@ struct nv_pi_priv {
 static const struct ata_port_info nv_port_info[] = {
 	/* generic */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -548,7 +548,7 @@ static const struct ata_port_info nv_port_info[] = {
 	},
 	/* nforce2/3 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -557,7 +557,7 @@ static const struct ata_port_info nv_port_info[] = {
 	},
 	/* ck804 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -566,8 +566,7 @@ static const struct ata_port_info nv_port_info[] = {
 	},
 	/* ADMA */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NCQ,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -576,7 +575,7 @@ static const struct ata_port_info nv_port_info[] = {
 	},
 	/* MCP5x */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -585,8 +584,7 @@ static const struct ata_port_info nv_port_info[] = {
 	},
 	/* SWNCQ */
 	{
-		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_NCQ,
+		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NCQ,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index f03ad48..a004b1e 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -134,9 +134,7 @@ enum {
 	PDC_IRQ_DISABLE		= (1 << 10),
 	PDC_RESET		= (1 << 11), /* HDMA reset */
 
-	PDC_COMMON_FLAGS	= ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO |
-				  ATA_FLAG_PIO_POLLING,
+	PDC_COMMON_FLAGS	= ATA_FLAG_PIO_POLLING,
 
 	/* ap->flags bits */
 	PDC_FLAG_GEN_II		= (1 << 24),
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
index daeebf1..c560326 100644
--- a/drivers/ata/sata_qstor.c
+++ b/drivers/ata/sata_qstor.c
@@ -155,8 +155,7 @@ static struct ata_port_operations qs_ata_ops = {
 static const struct ata_port_info qs_port_info[] = {
 	/* board_2068_idx */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= ATA_PIO4_ONLY,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &qs_ata_ops,
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 3a4f842..b42edaa 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -61,8 +61,7 @@ enum {
 	SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
 	SIL_FLAG_MOD15WRITE	= (1 << 30),
 
-	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA,
 
 	/*
 	 * Controller IDs
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index af41c6f..06c564e 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -244,8 +244,7 @@ enum {
 	BID_SIL3131		= 2,
 
 	/* host flags */
-	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
 				  ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
 				  ATA_FLAG_AN | ATA_FLAG_PMP,
 	SIL24_FLAG_PCIX_IRQ_WOC	= (1 << 24), /* IRQ loss errata on PCI-X */
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c
index 2bfe3ae..cdcc13e 100644
--- a/drivers/ata/sata_sis.c
+++ b/drivers/ata/sata_sis.c
@@ -96,7 +96,7 @@ static struct ata_port_operations sis_ops = {
 };
 
 static const struct ata_port_info sis_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 7d9db4a..35eabcf 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -359,8 +359,7 @@ static struct ata_port_operations k2_sata_ops = {
 static const struct ata_port_info k2_port_info[] = {
 	/* chip_svw4 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
+		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
@@ -368,8 +367,7 @@ static const struct ata_port_info k2_port_info[] = {
 	},
 	/* chip_svw8 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
+		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA |
 				  K2_FLAG_SATA_8_PORTS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -378,8 +376,7 @@ static const struct ata_port_info k2_port_info[] = {
 	},
 	/* chip_svw42 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3,
+		.flags		= ATA_FLAG_SATA | K2_FLAG_BAR_POS_3,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
@@ -387,8 +384,7 @@ static const struct ata_port_info k2_port_info[] = {
 	},
 	/* chip_svw43 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index bedd518..8fd3b72 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -273,9 +273,8 @@ static struct ata_port_operations pdc_20621_ops = {
 static const struct ata_port_info pdc_port_info[] = {
 	/* board_20621 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_SRST | ATA_FLAG_MMIO |
-				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_ATAPI |
+				  ATA_FLAG_PIO_POLLING,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c
index b8578c3..235be71 100644
--- a/drivers/ata/sata_uli.c
+++ b/drivers/ata/sata_uli.c
@@ -88,8 +88,7 @@ static struct ata_port_operations uli_ops = {
 };
 
 static const struct ata_port_info uli_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-			  ATA_FLAG_IGN_SIMPLEX,
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_IGN_SIMPLEX,
 	.pio_mask       = ATA_PIO4,
 	.udma_mask      = ATA_UDMA6,
 	.port_ops       = &uli_ops,
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c
index 8b677bb..21242c5 100644
--- a/drivers/ata/sata_via.c
+++ b/drivers/ata/sata_via.c
@@ -148,7 +148,7 @@ static struct ata_port_operations vt8251_ops = {
 };
 
 static const struct ata_port_info vt6420_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
@@ -156,7 +156,7 @@ static const struct ata_port_info vt6420_port_info = {
 };
 
 static struct ata_port_info vt6421_sport_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
@@ -164,7 +164,7 @@ static struct ata_port_info vt6421_sport_info = {
 };
 
 static struct ata_port_info vt6421_pport_info = {
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
 	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
@@ -172,8 +172,7 @@ static struct ata_port_info vt6421_pport_info = {
 };
 
 static struct ata_port_info vt8251_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
-			  ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c
index e079cf2..7c98737 100644
--- a/drivers/ata/sata_vsc.c
+++ b/drivers/ata/sata_vsc.c
@@ -340,8 +340,7 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev,
 				       const struct pci_device_id *ent)
 {
 	static const struct ata_port_info pi = {
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 7d912ba..049650d 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -1031,7 +1031,7 @@ static int fs_open(struct atm_vcc *atm_vcc)
 		/* We now use the "submit_command" function to submit commands to
 		   the firestream. There is a define up near the definition of
 		   that routine that switches this routine between immediate write
-		   to the immediate comamnd registers and queuing the commands in
+		   to the immediate command registers and queuing the commands in
 		   the HPTXQ for execution. This last technique might be more
 		   efficient if we know we're going to submit a whole lot of
 		   commands in one go, but this driver is not setup to be able to
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 44f7785..bdd2719 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2643,14 +2643,17 @@ fore200e_init(struct fore200e* fore200e, struct device *parent)
 }
 
 #ifdef CONFIG_SBUS
-static int __devinit fore200e_sba_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit fore200e_sba_probe(struct platform_device *op)
 {
-	const struct fore200e_bus *bus = match->data;
+	const struct fore200e_bus *bus;
 	struct fore200e *fore200e;
 	static int index = 0;
 	int err;
 
+	if (!op->dev.of_match)
+		return -EINVAL;
+	bus = op->dev.of_match->data;
+
 	fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
 	if (!fore200e)
 		return -ENOMEM;
@@ -2694,7 +2697,7 @@ static const struct of_device_id fore200e_sba_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fore200e_sba_match);
 
-static struct of_platform_driver fore200e_sba_driver = {
+static struct platform_driver fore200e_sba_driver = {
 	.driver = {
 		.name = "fore_200e",
 		.owner = THIS_MODULE,
@@ -2795,7 +2798,7 @@ static int __init fore200e_module_init(void)
 	printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
 
 #ifdef CONFIG_SBUS
-	err = of_register_platform_driver(&fore200e_sba_driver);
+	err = platform_driver_register(&fore200e_sba_driver);
 	if (err)
 		return err;
 #endif
@@ -2806,7 +2809,7 @@ static int __init fore200e_module_init(void)
 
 #ifdef CONFIG_SBUS
 	if (err)
-		of_unregister_platform_driver(&fore200e_sba_driver);
+		platform_driver_unregister(&fore200e_sba_driver);
 #endif
 
 	return err;
@@ -2818,7 +2821,7 @@ static void __exit fore200e_module_cleanup(void)
 	pci_unregister_driver(&fore200e_pca_driver);
 #endif
 #ifdef CONFIG_SBUS
-	of_unregister_platform_driver(&fore200e_sba_driver);
+	platform_driver_unregister(&fore200e_sba_driver);
 #endif
 }
 
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 5f51c3b..4c5701c 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -1,6 +1,6 @@
 # Makefile for the Linux device tree
 
-obj-y			:= core.o sys.o bus.o dd.o \
+obj-y			:= core.o sys.o bus.o dd.o syscore.o \
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 080e9ca..81b78ed 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1320,7 +1320,10 @@ struct root_device
 	struct module *owner;
 };
 
-#define to_root_device(dev) container_of(dev, struct root_device, dev)
+inline struct root_device *to_root_device(struct device *d)
+{
+	return container_of(d, struct root_device, dev);
+}
 
 static void root_device_release(struct device *dev)
 {
@@ -1551,7 +1554,34 @@ EXPORT_SYMBOL_GPL(device_destroy);
  * on the same device to ensure that new_name is valid and
  * won't conflict with other devices.
  *
- * "Never use this function, bad things will happen" - gregkh
+ * Note: Don't call this function.  Currently, the networking layer calls this
+ * function, but that will change.  The following text from Kay Sievers offers
+ * some insight:
+ *
+ * Renaming devices is racy at many levels, symlinks and other stuff are not
+ * replaced atomically, and you get a "move" uevent, but it's not easy to
+ * connect the event to the old and new device. Device nodes are not renamed at
+ * all, there isn't even support for that in the kernel now.
+ *
+ * In the meantime, during renaming, your target name might be taken by another
+ * driver, creating conflicts. Or the old name is taken directly after you
+ * renamed it -- then you get events for the same DEVPATH, before you even see
+ * the "move" event. It's just a mess, and nothing new should ever rely on
+ * kernel device renaming. Besides that, it's not even implemented now for
+ * other things than (driver-core wise very simple) network devices.
+ *
+ * We are currently about to change network renaming in udev to completely
+ * disallow renaming of devices in the same namespace as the kernel uses,
+ * because we can't solve the problems properly, that arise with swapping names
+ * of multiple interfaces without races. Means, renaming of eth[0-9]* will only
+ * be allowed to some other name than eth[0-9]*, for the aforementioned
+ * reasons.
+ *
+ * Make up a "real" name in the driver before you register anything, or add
+ * some other attributes for userspace to find the device, or use udev to add
+ * symlinks -- but never rename kernel devices later, it's a complete mess. We
+ * don't even want to get into that and try to implement the missing pieces in
+ * the core. We really have other pieces to fix in the driver core mess. :)
  */
 int device_rename(struct device *dev, const char *new_name)
 {
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 40af43e..8c798ef 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -593,8 +593,7 @@ int
 request_firmware(const struct firmware **firmware_p, const char *name,
                  struct device *device)
 {
-        int uevent = 1;
-        return _request_firmware(firmware_p, name, device, uevent, false);
+        return _request_firmware(firmware_p, name, device, true, false);
 }
 
 /**
@@ -618,7 +617,7 @@ struct firmware_work {
 	struct device *device;
 	void *context;
 	void (*cont)(const struct firmware *fw, void *context);
-	int uevent;
+	bool uevent;
 };
 
 static int request_firmware_work_func(void *arg)
@@ -661,7 +660,7 @@ static int request_firmware_work_func(void *arg)
  **/
 int
 request_firmware_nowait(
-	struct module *module, int uevent,
+	struct module *module, bool uevent,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index cafeaaf..3da6a43 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -30,6 +30,14 @@
 static DEFINE_MUTEX(mem_sysfs_mutex);
 
 #define MEMORY_CLASS_NAME	"memory"
+#define MIN_MEMORY_BLOCK_SIZE	(1 << SECTION_SIZE_BITS)
+
+static int sections_per_block;
+
+static inline int base_memory_block_id(int section_nr)
+{
+	return section_nr / sections_per_block;
+}
 
 static struct sysdev_class memory_sysdev_class = {
 	.name = MEMORY_CLASS_NAME,
@@ -84,39 +92,72 @@ EXPORT_SYMBOL(unregister_memory_isolate_notifier);
  * register_memory - Setup a sysfs device for a memory block
  */
 static
-int register_memory(struct memory_block *memory, struct mem_section *section)
+int register_memory(struct memory_block *memory)
 {
 	int error;
 
 	memory->sysdev.cls = &memory_sysdev_class;
-	memory->sysdev.id = __section_nr(section);
+	memory->sysdev.id = memory->start_section_nr / sections_per_block;
 
 	error = sysdev_register(&memory->sysdev);
 	return error;
 }
 
 static void
-unregister_memory(struct memory_block *memory, struct mem_section *section)
+unregister_memory(struct memory_block *memory)
 {
 	BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
-	BUG_ON(memory->sysdev.id != __section_nr(section));
 
 	/* drop the ref. we got in remove_memory_block() */
 	kobject_put(&memory->sysdev.kobj);
 	sysdev_unregister(&memory->sysdev);
 }
 
+unsigned long __weak memory_block_size_bytes(void)
+{
+	return MIN_MEMORY_BLOCK_SIZE;
+}
+
+static unsigned long get_memory_block_size(void)
+{
+	unsigned long block_sz;
+
+	block_sz = memory_block_size_bytes();
+
+	/* Validate blk_sz is a power of 2 and not less than section size */
+	if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) {
+		WARN_ON(1);
+		block_sz = MIN_MEMORY_BLOCK_SIZE;
+	}
+
+	return block_sz;
+}
+
 /*
  * use this as the physical section index that this memsection
  * uses.
  */
 
-static ssize_t show_mem_phys_index(struct sys_device *dev,
+static ssize_t show_mem_start_phys_index(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
-	return sprintf(buf, "%08lx\n", mem->phys_index);
+	unsigned long phys_index;
+
+	phys_index = mem->start_section_nr / sections_per_block;
+	return sprintf(buf, "%08lx\n", phys_index);
+}
+
+static ssize_t show_mem_end_phys_index(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	unsigned long phys_index;
+
+	phys_index = mem->end_section_nr / sections_per_block;
+	return sprintf(buf, "%08lx\n", phys_index);
 }
 
 /*
@@ -125,13 +166,16 @@ static ssize_t show_mem_phys_index(struct sys_device *dev,
 static ssize_t show_mem_removable(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
-	unsigned long start_pfn;
-	int ret;
+	unsigned long i, pfn;
+	int ret = 1;
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
 
-	start_pfn = section_nr_to_pfn(mem->phys_index);
-	ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+	for (i = 0; i < sections_per_block; i++) {
+		pfn = section_nr_to_pfn(mem->start_section_nr + i);
+		ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
+	}
+
 	return sprintf(buf, "%d\n", ret);
 }
 
@@ -184,17 +228,14 @@ int memory_isolate_notify(unsigned long val, void *v)
  * OK to have direct references to sparsemem variables in here.
  */
 static int
-memory_block_action(struct memory_block *mem, unsigned long action)
+memory_section_action(unsigned long phys_index, unsigned long action)
 {
 	int i;
-	unsigned long psection;
 	unsigned long start_pfn, start_paddr;
 	struct page *first_page;
 	int ret;
-	int old_state = mem->state;
 
-	psection = mem->phys_index;
-	first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
+	first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
 
 	/*
 	 * The probe routines leave the pages reserved, just
@@ -207,8 +248,8 @@ memory_block_action(struct memory_block *mem, unsigned long action)
 				continue;
 
 			printk(KERN_WARNING "section number %ld page number %d "
-				"not reserved, was it already online? \n",
-				psection, i);
+				"not reserved, was it already online?\n",
+				phys_index, i);
 			return -EBUSY;
 		}
 	}
@@ -219,18 +260,13 @@ memory_block_action(struct memory_block *mem, unsigned long action)
 			ret = online_pages(start_pfn, PAGES_PER_SECTION);
 			break;
 		case MEM_OFFLINE:
-			mem->state = MEM_GOING_OFFLINE;
 			start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
 			ret = remove_memory(start_paddr,
 					    PAGES_PER_SECTION << PAGE_SHIFT);
-			if (ret) {
-				mem->state = old_state;
-				break;
-			}
 			break;
 		default:
-			WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
-					__func__, mem, action, action);
+			WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
+			     "%ld\n", __func__, phys_index, action, action);
 			ret = -EINVAL;
 	}
 
@@ -240,7 +276,8 @@ memory_block_action(struct memory_block *mem, unsigned long action)
 static int memory_block_change_state(struct memory_block *mem,
 		unsigned long to_state, unsigned long from_state_req)
 {
-	int ret = 0;
+	int i, ret = 0;
+
 	mutex_lock(&mem->state_mutex);
 
 	if (mem->state != from_state_req) {
@@ -248,8 +285,23 @@ static int memory_block_change_state(struct memory_block *mem,
 		goto out;
 	}
 
-	ret = memory_block_action(mem, to_state);
-	if (!ret)
+	if (to_state == MEM_OFFLINE)
+		mem->state = MEM_GOING_OFFLINE;
+
+	for (i = 0; i < sections_per_block; i++) {
+		ret = memory_section_action(mem->start_section_nr + i,
+					    to_state);
+		if (ret)
+			break;
+	}
+
+	if (ret) {
+		for (i = 0; i < sections_per_block; i++)
+			memory_section_action(mem->start_section_nr + i,
+					      from_state_req);
+
+		mem->state = from_state_req;
+	} else
 		mem->state = to_state;
 
 out:
@@ -262,20 +314,15 @@ store_mem_state(struct sys_device *dev,
 		struct sysdev_attribute *attr, const char *buf, size_t count)
 {
 	struct memory_block *mem;
-	unsigned int phys_section_nr;
 	int ret = -EINVAL;
 
 	mem = container_of(dev, struct memory_block, sysdev);
-	phys_section_nr = mem->phys_index;
-
-	if (!present_section_nr(phys_section_nr))
-		goto out;
 
 	if (!strncmp(buf, "online", min((int)count, 6)))
 		ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
 	else if(!strncmp(buf, "offline", min((int)count, 7)))
 		ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
-out:
+
 	if (ret)
 		return ret;
 	return count;
@@ -298,7 +345,8 @@ static ssize_t show_phys_device(struct sys_device *dev,
 	return sprintf(buf, "%d\n", mem->phys_device);
 }
 
-static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
+static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
+static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
 static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
 static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
 static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
@@ -315,7 +363,7 @@ static ssize_t
 print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
 		 char *buf)
 {
-	return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
+	return sprintf(buf, "%lx\n", get_memory_block_size());
 }
 
 static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
@@ -339,12 +387,19 @@ memory_probe_store(struct class *class, struct class_attribute *attr,
 {
 	u64 phys_addr;
 	int nid;
-	int ret;
+	int i, ret;
 
 	phys_addr = simple_strtoull(buf, NULL, 0);
 
-	nid = memory_add_physaddr_to_nid(phys_addr);
-	ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
+	for (i = 0; i < sections_per_block; i++) {
+		nid = memory_add_physaddr_to_nid(phys_addr);
+		ret = add_memory(nid, phys_addr,
+				 PAGES_PER_SECTION << PAGE_SHIFT);
+		if (ret)
+			break;
+
+		phys_addr += MIN_MEMORY_BLOCK_SIZE;
+	}
 
 	if (ret)
 		count = ret;
@@ -444,6 +499,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section,
 	struct sys_device *sysdev;
 	struct memory_block *mem;
 	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+	int block_id = base_memory_block_id(__section_nr(section));
 
 	kobj = hint ? &hint->sysdev.kobj : NULL;
 
@@ -451,7 +507,7 @@ struct memory_block *find_memory_block_hinted(struct mem_section *section,
 	 * This only works because we know that section == sysdev->id
 	 * slightly redundant with sysdev_register()
 	 */
-	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
 
 	kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
 	if (!kobj)
@@ -476,36 +532,62 @@ struct memory_block *find_memory_block(struct mem_section *section)
 	return find_memory_block_hinted(section, NULL);
 }
 
-static int add_memory_block(int nid, struct mem_section *section,
-			unsigned long state, enum mem_add_context context)
+static int init_memory_block(struct memory_block **memory,
+			     struct mem_section *section, unsigned long state)
 {
-	struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	struct memory_block *mem;
 	unsigned long start_pfn;
+	int scn_nr;
 	int ret = 0;
 
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem)
 		return -ENOMEM;
 
-	mutex_lock(&mem_sysfs_mutex);
-
-	mem->phys_index = __section_nr(section);
+	scn_nr = __section_nr(section);
+	mem->start_section_nr =
+			base_memory_block_id(scn_nr) * sections_per_block;
+	mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
 	mem->state = state;
 	mem->section_count++;
 	mutex_init(&mem->state_mutex);
-	start_pfn = section_nr_to_pfn(mem->phys_index);
+	start_pfn = section_nr_to_pfn(mem->start_section_nr);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
-	ret = register_memory(mem, section);
+	ret = register_memory(mem);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_index);
 	if (!ret)
+		ret = mem_create_simple_file(mem, end_phys_index);
+	if (!ret)
 		ret = mem_create_simple_file(mem, state);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_device);
 	if (!ret)
 		ret = mem_create_simple_file(mem, removable);
+
+	*memory = mem;
+	return ret;
+}
+
+static int add_memory_section(int nid, struct mem_section *section,
+			unsigned long state, enum mem_add_context context)
+{
+	struct memory_block *mem;
+	int ret = 0;
+
+	mutex_lock(&mem_sysfs_mutex);
+
+	mem = find_memory_block(section);
+	if (mem) {
+		mem->section_count++;
+		kobject_put(&mem->sysdev.kobj);
+	} else
+		ret = init_memory_block(&mem, section, state);
+
 	if (!ret) {
-		if (context == HOTPLUG)
+		if (context == HOTPLUG &&
+		    mem->section_count == sections_per_block)
 			ret = register_mem_sect_under_node(mem, nid);
 	}
 
@@ -520,16 +602,19 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
 
 	mutex_lock(&mem_sysfs_mutex);
 	mem = find_memory_block(section);
+	unregister_mem_sect_under_nodes(mem, __section_nr(section));
 
 	mem->section_count--;
 	if (mem->section_count == 0) {
-		unregister_mem_sect_under_nodes(mem);
 		mem_remove_simple_file(mem, phys_index);
+		mem_remove_simple_file(mem, end_phys_index);
 		mem_remove_simple_file(mem, state);
 		mem_remove_simple_file(mem, phys_device);
 		mem_remove_simple_file(mem, removable);
-		unregister_memory(mem, section);
-	}
+		unregister_memory(mem);
+		kfree(mem);
+	} else
+		kobject_put(&mem->sysdev.kobj);
 
 	mutex_unlock(&mem_sysfs_mutex);
 	return 0;
@@ -541,7 +626,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
  */
 int register_new_memory(int nid, struct mem_section *section)
 {
-	return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG);
+	return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -560,12 +645,16 @@ int __init memory_dev_init(void)
 	unsigned int i;
 	int ret;
 	int err;
+	unsigned long block_sz;
 
 	memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
 	ret = sysdev_class_register(&memory_sysdev_class);
 	if (ret)
 		goto out;
 
+	block_sz = get_memory_block_size();
+	sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
+
 	/*
 	 * Create entries for memory sections that were found
 	 * during boot and have been initialized
@@ -573,8 +662,8 @@ int __init memory_dev_init(void)
 	for (i = 0; i < NR_MEM_SECTIONS; i++) {
 		if (!present_section_nr(i))
 			continue;
-		err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
-				       BOOT);
+		err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
+					 BOOT);
 		if (!ret)
 			ret = err;
 	}
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 36b4305..b3b72d6 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -375,8 +375,10 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
 		return -EFAULT;
 	if (!node_online(nid))
 		return 0;
-	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
-	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+
+	sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
+	sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr);
+	sect_end_pfn += PAGES_PER_SECTION - 1;
 	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
 		int page_nid;
 
@@ -400,7 +402,8 @@ int register_mem_sect_under_node(struct memory_block *mem_blk, int nid)
 }
 
 /* unregister memory section under all nodes that it spans */
-int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+				    unsigned long phys_index)
 {
 	NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL);
 	unsigned long pfn, sect_start_pfn, sect_end_pfn;
@@ -412,7 +415,8 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
 	if (!unlinked_nodes)
 		return -ENOMEM;
 	nodes_clear(*unlinked_nodes);
-	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+
+	sect_start_pfn = section_nr_to_pfn(phys_index);
 	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
 	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
 		int nid;
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index abe46ed..118c1b9 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,7 +1,6 @@
-obj-$(CONFIG_PM)	+= sysfs.o
+obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
-obj-$(CONFIG_PM_OPS)	+= generic_ops.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
 obj-$(CONFIG_PM_OPP)	+= opp.o
 
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 8340497..052dc53 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -423,26 +423,22 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
-	if (dev->bus && dev->bus->pm) {
-		pm_dev_dbg(dev, state, "EARLY ");
-		error = pm_noirq_op(dev, dev->bus->pm, state);
-		if (error)
-			goto End;
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "EARLY power domain ");
+		pm_noirq_op(dev, &dev->pwr_domain->ops, state);
 	}
 
 	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "EARLY type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
-		if (error)
-			goto End;
-	}
-
-	if (dev->class && dev->class->pm) {
+	} else if (dev->class && dev->class->pm) {
 		pm_dev_dbg(dev, state, "EARLY class ");
 		error = pm_noirq_op(dev, dev->class->pm, state);
+	} else if (dev->bus && dev->bus->pm) {
+		pm_dev_dbg(dev, state, "EARLY ");
+		error = pm_noirq_op(dev, dev->bus->pm, state);
 	}
 
-End:
 	TRACE_RESUME(error);
 	return error;
 }
@@ -518,36 +514,39 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 
 	dev->power.in_suspend = false;
 
-	if (dev->bus) {
-		if (dev->bus->pm) {
-			pm_dev_dbg(dev, state, "");
-			error = pm_op(dev, dev->bus->pm, state);
-		} else if (dev->bus->resume) {
-			pm_dev_dbg(dev, state, "legacy ");
-			error = legacy_resume(dev, dev->bus->resume);
-		}
-		if (error)
-			goto End;
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "power domain ");
+		pm_op(dev, &dev->pwr_domain->ops, state);
 	}
 
-	if (dev->type) {
-		if (dev->type->pm) {
-			pm_dev_dbg(dev, state, "type ");
-			error = pm_op(dev, dev->type->pm, state);
-		}
-		if (error)
-			goto End;
+	if (dev->type && dev->type->pm) {
+		pm_dev_dbg(dev, state, "type ");
+		error = pm_op(dev, dev->type->pm, state);
+		goto End;
 	}
 
 	if (dev->class) {
 		if (dev->class->pm) {
 			pm_dev_dbg(dev, state, "class ");
 			error = pm_op(dev, dev->class->pm, state);
+			goto End;
 		} else if (dev->class->resume) {
 			pm_dev_dbg(dev, state, "legacy class ");
 			error = legacy_resume(dev, dev->class->resume);
+			goto End;
 		}
 	}
+
+	if (dev->bus) {
+		if (dev->bus->pm) {
+			pm_dev_dbg(dev, state, "");
+			error = pm_op(dev, dev->bus->pm, state);
+		} else if (dev->bus->resume) {
+			pm_dev_dbg(dev, state, "legacy ");
+			error = legacy_resume(dev, dev->bus->resume);
+		}
+	}
+
  End:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -629,19 +628,23 @@ static void device_complete(struct device *dev, pm_message_t state)
 {
 	device_lock(dev);
 
-	if (dev->class && dev->class->pm && dev->class->pm->complete) {
-		pm_dev_dbg(dev, state, "completing class ");
-		dev->class->pm->complete(dev);
+	if (dev->pwr_domain && dev->pwr_domain->ops.complete) {
+		pm_dev_dbg(dev, state, "completing power domain ");
+		dev->pwr_domain->ops.complete(dev);
 	}
 
-	if (dev->type && dev->type->pm && dev->type->pm->complete) {
+	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "completing type ");
-		dev->type->pm->complete(dev);
-	}
-
-	if (dev->bus && dev->bus->pm && dev->bus->pm->complete) {
+		if (dev->type->pm->complete)
+			dev->type->pm->complete(dev);
+	} else if (dev->class && dev->class->pm) {
+		pm_dev_dbg(dev, state, "completing class ");
+		if (dev->class->pm->complete)
+			dev->class->pm->complete(dev);
+	} else if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "completing ");
-		dev->bus->pm->complete(dev);
+		if (dev->bus->pm->complete)
+			dev->bus->pm->complete(dev);
 	}
 
 	device_unlock(dev);
@@ -669,7 +672,6 @@ static void dpm_complete(pm_message_t state)
 		mutex_unlock(&dpm_list_mtx);
 
 		device_complete(dev, state);
-		pm_runtime_put_sync(dev);
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
@@ -727,29 +729,31 @@ static pm_message_t resume_event(pm_message_t sleep_state)
  */
 static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
-	int error = 0;
-
-	if (dev->class && dev->class->pm) {
-		pm_dev_dbg(dev, state, "LATE class ");
-		error = pm_noirq_op(dev, dev->class->pm, state);
-		if (error)
-			goto End;
-	}
+	int error;
 
 	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "LATE type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
 		if (error)
-			goto End;
-	}
-
-	if (dev->bus && dev->bus->pm) {
+			return error;
+	} else if (dev->class && dev->class->pm) {
+		pm_dev_dbg(dev, state, "LATE class ");
+		error = pm_noirq_op(dev, dev->class->pm, state);
+		if (error)
+			return error;
+	} else if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "LATE ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
+		if (error)
+			return error;
 	}
 
-End:
-	return error;
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "LATE power domain ");
+		pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+	}
+
+	return 0;
 }
 
 /**
@@ -836,25 +840,22 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 		goto End;
 	}
 
+	if (dev->type && dev->type->pm) {
+		pm_dev_dbg(dev, state, "type ");
+		error = pm_op(dev, dev->type->pm, state);
+		goto Domain;
+	}
+
 	if (dev->class) {
 		if (dev->class->pm) {
 			pm_dev_dbg(dev, state, "class ");
 			error = pm_op(dev, dev->class->pm, state);
+			goto Domain;
 		} else if (dev->class->suspend) {
 			pm_dev_dbg(dev, state, "legacy class ");
 			error = legacy_suspend(dev, state, dev->class->suspend);
+			goto Domain;
 		}
-		if (error)
-			goto End;
-	}
-
-	if (dev->type) {
-		if (dev->type->pm) {
-			pm_dev_dbg(dev, state, "type ");
-			error = pm_op(dev, dev->type->pm, state);
-		}
-		if (error)
-			goto End;
 	}
 
 	if (dev->bus) {
@@ -867,6 +868,12 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
 		}
 	}
 
+ Domain:
+	if (!error && dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "power domain ");
+		pm_op(dev, &dev->pwr_domain->ops, state);
+	}
+
  End:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -957,27 +964,34 @@ static int device_prepare(struct device *dev, pm_message_t state)
 
 	device_lock(dev);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
+	if (dev->type && dev->type->pm) {
+		pm_dev_dbg(dev, state, "preparing type ");
+		if (dev->type->pm->prepare)
+			error = dev->type->pm->prepare(dev);
+		suspend_report_result(dev->type->pm->prepare, error);
+		if (error)
+			goto End;
+	} else if (dev->class && dev->class->pm) {
+		pm_dev_dbg(dev, state, "preparing class ");
+		if (dev->class->pm->prepare)
+			error = dev->class->pm->prepare(dev);
+		suspend_report_result(dev->class->pm->prepare, error);
+		if (error)
+			goto End;
+	} else if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "preparing ");
-		error = dev->bus->pm->prepare(dev);
+		if (dev->bus->pm->prepare)
+			error = dev->bus->pm->prepare(dev);
 		suspend_report_result(dev->bus->pm->prepare, error);
 		if (error)
 			goto End;
 	}
 
-	if (dev->type && dev->type->pm && dev->type->pm->prepare) {
-		pm_dev_dbg(dev, state, "preparing type ");
-		error = dev->type->pm->prepare(dev);
-		suspend_report_result(dev->type->pm->prepare, error);
-		if (error)
-			goto End;
+	if (dev->pwr_domain && dev->pwr_domain->ops.prepare) {
+		pm_dev_dbg(dev, state, "preparing power domain ");
+		dev->pwr_domain->ops.prepare(dev);
 	}
 
-	if (dev->class && dev->class->pm && dev->class->pm->prepare) {
-		pm_dev_dbg(dev, state, "preparing class ");
-		error = dev->class->pm->prepare(dev);
-		suspend_report_result(dev->class->pm->prepare, error);
-	}
  End:
 	device_unlock(dev);
 
@@ -1005,12 +1019,9 @@ static int dpm_prepare(pm_message_t state)
 		if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
 			pm_wakeup_event(dev, 0);
 
-		if (pm_wakeup_pending()) {
-			pm_runtime_put_sync(dev);
-			error = -EBUSY;
-		} else {
-			error = device_prepare(dev, state);
-		}
+		pm_runtime_put_sync(dev);
+		error = pm_wakeup_pending() ?
+				-EBUSY : device_prepare(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
diff --git a/drivers/base/power/opp.c b/drivers/base/power/opp.c
index 2bb9b4c..56a6899 100644
--- a/drivers/base/power/opp.c
+++ b/drivers/base/power/opp.c
@@ -222,7 +222,7 @@ int opp_get_opp_count(struct device *dev)
  * opp_find_freq_exact() - search for an exact frequency
  * @dev:		device for which we do this operation
  * @freq:		frequency to search for
- * @is_available:	true/false - match for available opp
+ * @available:		true/false - match for available opp
  *
  * Searches for exact match in the opp list and returns pointer to the matching
  * opp if found, else returns ERR_PTR in case of error and should be handled
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 698dde7..f2a25f1 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -58,19 +58,18 @@ static inline void device_pm_move_last(struct device *dev) {}
  * sysfs.c
  */
 
-extern int dpm_sysfs_add(struct device *);
-extern void dpm_sysfs_remove(struct device *);
-extern void rpm_sysfs_remove(struct device *);
+extern int dpm_sysfs_add(struct device *dev);
+extern void dpm_sysfs_remove(struct device *dev);
+extern void rpm_sysfs_remove(struct device *dev);
+extern int wakeup_sysfs_add(struct device *dev);
+extern void wakeup_sysfs_remove(struct device *dev);
 
 #else /* CONFIG_PM */
 
-static inline int dpm_sysfs_add(struct device *dev)
-{
-	return 0;
-}
-
-static inline void dpm_sysfs_remove(struct device *dev)
-{
-}
+static inline int dpm_sysfs_add(struct device *dev) { return 0; }
+static inline void dpm_sysfs_remove(struct device *dev) {}
+static inline void rpm_sysfs_remove(struct device *dev) {}
+static inline int wakeup_sysfs_add(struct device *dev) { return 0; }
+static inline void wakeup_sysfs_remove(struct device *dev) {}
 
 #endif
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 42615b4..54597c8 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -168,6 +168,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
 static int rpm_idle(struct device *dev, int rpmflags)
 {
 	int (*callback)(struct device *);
+	int (*domain_callback)(struct device *);
 	int retval;
 
 	retval = rpm_check_suspend_allowed(dev);
@@ -213,19 +214,28 @@ static int rpm_idle(struct device *dev, int rpmflags)
 
 	dev->power.idle_notification = true;
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle)
-		callback = dev->bus->pm->runtime_idle;
-	else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle)
+	if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_idle;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_idle;
+	else if (dev->bus && dev->bus->pm)
+		callback = dev->bus->pm->runtime_idle;
 	else
 		callback = NULL;
 
-	if (callback) {
+	if (dev->pwr_domain)
+		domain_callback = dev->pwr_domain->ops.runtime_idle;
+	else
+		domain_callback = NULL;
+
+	if (callback || domain_callback) {
 		spin_unlock_irq(&dev->power.lock);
 
-		callback(dev);
+		if (domain_callback)
+			retval = domain_callback(dev);
+
+		if (!retval && callback)
+			callback(dev);
 
 		spin_lock_irq(&dev->power.lock);
 	}
@@ -372,12 +382,12 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 
 	__update_runtime_status(dev, RPM_SUSPENDING);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend)
-		callback = dev->bus->pm->runtime_suspend;
-	else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend)
+	if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_suspend;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_suspend;
+	else if (dev->bus && dev->bus->pm)
+		callback = dev->bus->pm->runtime_suspend;
 	else
 		callback = NULL;
 
@@ -390,6 +400,8 @@ static int rpm_suspend(struct device *dev, int rpmflags)
 		else
 			pm_runtime_cancel_pending(dev);
 	} else {
+		if (dev->pwr_domain)
+			rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev);
  no_callback:
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_deactivate_timer(dev);
@@ -569,12 +581,15 @@ static int rpm_resume(struct device *dev, int rpmflags)
 
 	__update_runtime_status(dev, RPM_RESUMING);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume)
-		callback = dev->bus->pm->runtime_resume;
-	else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume)
+	if (dev->pwr_domain)
+		rpm_callback(dev->pwr_domain->ops.runtime_resume, dev);
+
+	if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_resume;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_resume;
+	else if (dev->bus && dev->bus->pm)
+		callback = dev->bus->pm->runtime_resume;
 	else
 		callback = NULL;
 
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 0b1e46b..fff49be 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -431,26 +431,18 @@ static ssize_t async_store(struct device *dev, struct device_attribute *attr,
 static DEVICE_ATTR(async, 0644, async_show, async_store);
 #endif /* CONFIG_PM_ADVANCED_DEBUG */
 
-static struct attribute * power_attrs[] = {
-	&dev_attr_wakeup.attr,
-#ifdef CONFIG_PM_SLEEP
-	&dev_attr_wakeup_count.attr,
-	&dev_attr_wakeup_active_count.attr,
-	&dev_attr_wakeup_hit_count.attr,
-	&dev_attr_wakeup_active.attr,
-	&dev_attr_wakeup_total_time_ms.attr,
-	&dev_attr_wakeup_max_time_ms.attr,
-	&dev_attr_wakeup_last_time_ms.attr,
-#endif
+static struct attribute *power_attrs[] = {
 #ifdef CONFIG_PM_ADVANCED_DEBUG
+#ifdef CONFIG_PM_SLEEP
 	&dev_attr_async.attr,
+#endif
 #ifdef CONFIG_PM_RUNTIME
 	&dev_attr_runtime_status.attr,
 	&dev_attr_runtime_usage.attr,
 	&dev_attr_runtime_active_kids.attr,
 	&dev_attr_runtime_enabled.attr,
 #endif
-#endif
+#endif /* CONFIG_PM_ADVANCED_DEBUG */
 	NULL,
 };
 static struct attribute_group pm_attr_group = {
@@ -458,9 +450,26 @@ static struct attribute_group pm_attr_group = {
 	.attrs	= power_attrs,
 };
 
-#ifdef CONFIG_PM_RUNTIME
+static struct attribute *wakeup_attrs[] = {
+#ifdef CONFIG_PM_SLEEP
+	&dev_attr_wakeup.attr,
+	&dev_attr_wakeup_count.attr,
+	&dev_attr_wakeup_active_count.attr,
+	&dev_attr_wakeup_hit_count.attr,
+	&dev_attr_wakeup_active.attr,
+	&dev_attr_wakeup_total_time_ms.attr,
+	&dev_attr_wakeup_max_time_ms.attr,
+	&dev_attr_wakeup_last_time_ms.attr,
+#endif
+	NULL,
+};
+static struct attribute_group pm_wakeup_attr_group = {
+	.name	= power_group_name,
+	.attrs	= wakeup_attrs,
+};
 
 static struct attribute *runtime_attrs[] = {
+#ifdef CONFIG_PM_RUNTIME
 #ifndef CONFIG_PM_ADVANCED_DEBUG
 	&dev_attr_runtime_status.attr,
 #endif
@@ -468,6 +477,7 @@ static struct attribute *runtime_attrs[] = {
 	&dev_attr_runtime_suspended_time.attr,
 	&dev_attr_runtime_active_time.attr,
 	&dev_attr_autosuspend_delay_ms.attr,
+#endif /* CONFIG_PM_RUNTIME */
 	NULL,
 };
 static struct attribute_group pm_runtime_attr_group = {
@@ -480,35 +490,49 @@ int dpm_sysfs_add(struct device *dev)
 	int rc;
 
 	rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
-	if (rc == 0 && !dev->power.no_callbacks) {
+	if (rc)
+		return rc;
+
+	if (pm_runtime_callbacks_present(dev)) {
 		rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
 		if (rc)
-			sysfs_remove_group(&dev->kobj, &pm_attr_group);
+			goto err_out;
+	}
+
+	if (device_can_wakeup(dev)) {
+		rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
+		if (rc) {
+			if (pm_runtime_callbacks_present(dev))
+				sysfs_unmerge_group(&dev->kobj,
+						    &pm_runtime_attr_group);
+			goto err_out;
+		}
 	}
+	return 0;
+
+ err_out:
+	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 	return rc;
 }
 
-void rpm_sysfs_remove(struct device *dev)
+int wakeup_sysfs_add(struct device *dev)
 {
-	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
+	return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-void dpm_sysfs_remove(struct device *dev)
+void wakeup_sysfs_remove(struct device *dev)
 {
-	rpm_sysfs_remove(dev);
-	sysfs_remove_group(&dev->kobj, &pm_attr_group);
+	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-#else /* CONFIG_PM_RUNTIME */
-
-int dpm_sysfs_add(struct device * dev)
+void rpm_sysfs_remove(struct device *dev)
 {
-	return sysfs_create_group(&dev->kobj, &pm_attr_group);
+	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
 }
 
-void dpm_sysfs_remove(struct device * dev)
+void dpm_sysfs_remove(struct device *dev)
 {
+	rpm_sysfs_remove(dev);
+	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 }
-
-#endif
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 9f4258d..c80e138 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -112,7 +112,7 @@ static unsigned int read_magic_time(void)
 	unsigned int val;
 
 	get_rtc_time(&time);
-	printk("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
+	pr_info("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
 		time.tm_hour, time.tm_min, time.tm_sec,
 		time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
 	val = time.tm_year;				/* 100 years */
@@ -179,7 +179,7 @@ static int show_file_hash(unsigned int value)
 		unsigned int hash = hash_string(lineno, file, FILEHASH);
 		if (hash != value)
 			continue;
-		printk("  hash matches %s:%u\n", file, lineno);
+		pr_info("  hash matches %s:%u\n", file, lineno);
 		match++;
 	}
 	return match;
@@ -255,7 +255,7 @@ static int late_resume_init(void)
 	val = val / FILEHASH;
 	dev = val /* % DEVHASH */;
 
-	printk("  Magic number: %d:%d:%d\n", user, file, dev);
+	pr_info("  Magic number: %d:%d:%d\n", user, file, dev);
 	show_file_hash(file);
 	show_dev_hash(dev);
 	return 0;
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 8ec406d..4573c83 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -24,12 +24,26 @@
  */
 bool events_check_enabled;
 
-/* The counter of registered wakeup events. */
-static atomic_t event_count = ATOMIC_INIT(0);
-/* A preserved old value of event_count. */
+/*
+ * Combined counters of registered wakeup events and wakeup events in progress.
+ * They need to be modified together atomically, so it's better to use one
+ * atomic variable to hold them both.
+ */
+static atomic_t combined_event_count = ATOMIC_INIT(0);
+
+#define IN_PROGRESS_BITS	(sizeof(int) * 4)
+#define MAX_IN_PROGRESS		((1 << IN_PROGRESS_BITS) - 1)
+
+static void split_counters(unsigned int *cnt, unsigned int *inpr)
+{
+	unsigned int comb = atomic_read(&combined_event_count);
+
+	*cnt = (comb >> IN_PROGRESS_BITS);
+	*inpr = comb & MAX_IN_PROGRESS;
+}
+
+/* A preserved old value of the events counter. */
 static unsigned int saved_count;
-/* The counter of wakeup events being processed. */
-static atomic_t events_in_progress = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(events_lock);
 
@@ -228,6 +242,35 @@ int device_wakeup_disable(struct device *dev)
 EXPORT_SYMBOL_GPL(device_wakeup_disable);
 
 /**
+ * device_set_wakeup_capable - Set/reset device wakeup capability flag.
+ * @dev: Device to handle.
+ * @capable: Whether or not @dev is capable of waking up the system from sleep.
+ *
+ * If @capable is set, set the @dev's power.can_wakeup flag and add its
+ * wakeup-related attributes to sysfs.  Otherwise, unset the @dev's
+ * power.can_wakeup flag and remove its wakeup-related attributes from sysfs.
+ *
+ * This function may sleep and it can't be called from any context where
+ * sleeping is not allowed.
+ */
+void device_set_wakeup_capable(struct device *dev, bool capable)
+{
+	if (!!dev->power.can_wakeup == !!capable)
+		return;
+
+	if (device_is_registered(dev)) {
+		if (capable) {
+			if (wakeup_sysfs_add(dev))
+				return;
+		} else {
+			wakeup_sysfs_remove(dev);
+		}
+	}
+	dev->power.can_wakeup = capable;
+}
+EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
+
+/**
  * device_init_wakeup - Device wakeup initialization.
  * @dev: Device to handle.
  * @enable: Whether or not to enable @dev as a wakeup device.
@@ -307,7 +350,8 @@ static void wakeup_source_activate(struct wakeup_source *ws)
 	ws->timer_expires = jiffies;
 	ws->last_time = ktime_get();
 
-	atomic_inc(&events_in_progress);
+	/* Increment the counter of events in progress. */
+	atomic_inc(&combined_event_count);
 }
 
 /**
@@ -394,14 +438,10 @@ static void wakeup_source_deactivate(struct wakeup_source *ws)
 	del_timer(&ws->timer);
 
 	/*
-	 * event_count has to be incremented before events_in_progress is
-	 * modified, so that the callers of pm_check_wakeup_events() and
-	 * pm_save_wakeup_count() don't see the old value of event_count and
-	 * events_in_progress equal to zero at the same time.
+	 * Increment the counter of registered wakeup events and decrement the
+	 * couter of wakeup events in progress simultaneously.
 	 */
-	atomic_inc(&event_count);
-	smp_mb__before_atomic_dec();
-	atomic_dec(&events_in_progress);
+	atomic_add(MAX_IN_PROGRESS, &combined_event_count);
 }
 
 /**
@@ -556,8 +596,10 @@ bool pm_wakeup_pending(void)
 
 	spin_lock_irqsave(&events_lock, flags);
 	if (events_check_enabled) {
-		ret = ((unsigned int)atomic_read(&event_count) != saved_count)
-			|| atomic_read(&events_in_progress);
+		unsigned int cnt, inpr;
+
+		split_counters(&cnt, &inpr);
+		ret = (cnt != saved_count || inpr > 0);
 		events_check_enabled = !ret;
 	}
 	spin_unlock_irqrestore(&events_lock, flags);
@@ -573,25 +615,25 @@ bool pm_wakeup_pending(void)
  * Store the number of registered wakeup events at the address in @count.  Block
  * if the current number of wakeup events being processed is nonzero.
  *
- * Return false if the wait for the number of wakeup events being processed to
+ * Return 'false' if the wait for the number of wakeup events being processed to
  * drop down to zero has been interrupted by a signal (and the current number
- * of wakeup events being processed is still nonzero).  Otherwise return true.
+ * of wakeup events being processed is still nonzero).  Otherwise return 'true'.
  */
 bool pm_get_wakeup_count(unsigned int *count)
 {
-	bool ret;
-
-	if (capable(CAP_SYS_ADMIN))
-		events_check_enabled = false;
+	unsigned int cnt, inpr;
 
-	while (atomic_read(&events_in_progress) && !signal_pending(current)) {
+	for (;;) {
+		split_counters(&cnt, &inpr);
+		if (inpr == 0 || signal_pending(current))
+			break;
 		pm_wakeup_update_hit_counts();
 		schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
 	}
 
-	ret = !atomic_read(&events_in_progress);
-	*count = atomic_read(&event_count);
-	return ret;
+	split_counters(&cnt, &inpr);
+	*count = cnt;
+	return !inpr;
 }
 
 /**
@@ -600,24 +642,25 @@ bool pm_get_wakeup_count(unsigned int *count)
  *
  * If @count is equal to the current number of registered wakeup events and the
  * current number of wakeup events being processed is zero, store @count as the
- * old number of registered wakeup events to be used by pm_check_wakeup_events()
- * and return true.  Otherwise return false.
+ * old number of registered wakeup events for pm_check_wakeup_events(), enable
+ * wakeup events detection and return 'true'.  Otherwise disable wakeup events
+ * detection and return 'false'.
  */
 bool pm_save_wakeup_count(unsigned int count)
 {
-	bool ret = false;
+	unsigned int cnt, inpr;
 
+	events_check_enabled = false;
 	spin_lock_irq(&events_lock);
-	if (count == (unsigned int)atomic_read(&event_count)
-	    && !atomic_read(&events_in_progress)) {
+	split_counters(&cnt, &inpr);
+	if (cnt == count && inpr == 0) {
 		saved_count = count;
 		events_check_enabled = true;
-		ret = true;
 	}
 	spin_unlock_irq(&events_lock);
-	if (!ret)
+	if (!events_check_enabled)
 		pm_wakeup_update_hit_counts();
-	return ret;
+	return events_check_enabled;
 }
 
 static struct dentry *wakeup_sources_stats_dentry;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 1667aaf..f6fb547 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -166,6 +166,36 @@ EXPORT_SYMBOL_GPL(sysdev_class_unregister);
 
 static DEFINE_MUTEX(sysdev_drivers_lock);
 
+/*
+ * @dev != NULL means that we're unwinding because some drv->add()
+ * failed for some reason. You need to grab sysdev_drivers_lock before
+ * calling this.
+ */
+static void __sysdev_driver_remove(struct sysdev_class *cls,
+				   struct sysdev_driver *drv,
+				   struct sys_device *from_dev)
+{
+	struct sys_device *dev = from_dev;
+
+	list_del_init(&drv->entry);
+	if (!cls)
+		return;
+
+	if (!drv->remove)
+		goto kset_put;
+
+	if (dev)
+		list_for_each_entry_continue_reverse(dev, &cls->kset.list,
+						     kobj.entry)
+			drv->remove(dev);
+	else
+		list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+			drv->remove(dev);
+
+kset_put:
+	kset_put(&cls->kset);
+}
+
 /**
  *	sysdev_driver_register - Register auxillary driver
  *	@cls:	Device class driver belongs to.
@@ -175,14 +205,14 @@ static DEFINE_MUTEX(sysdev_drivers_lock);
  *	called on each operation on devices of that class. The refcount
  *	of @cls is incremented.
  */
-
 int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
 {
+	struct sys_device *dev = NULL;
 	int err = 0;
 
 	if (!cls) {
-		WARN(1, KERN_WARNING "sysdev: invalid class passed to "
-			"sysdev_driver_register!\n");
+		WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -198,19 +228,27 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
 
 		/* If devices of this class already exist, tell the driver */
 		if (drv->add) {
-			struct sys_device *dev;
-			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
-				drv->add(dev);
+			list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
+				err = drv->add(dev);
+				if (err)
+					goto unwind;
+			}
 		}
 	} else {
 		err = -EINVAL;
 		WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
 	}
+
+	goto unlock;
+
+unwind:
+	__sysdev_driver_remove(cls, drv, dev);
+
+unlock:
 	mutex_unlock(&sysdev_drivers_lock);
 	return err;
 }
 
-
 /**
  *	sysdev_driver_unregister - Remove an auxillary driver.
  *	@cls:	Class driver belongs to.
@@ -220,23 +258,12 @@ void sysdev_driver_unregister(struct sysdev_class *cls,
 			      struct sysdev_driver *drv)
 {
 	mutex_lock(&sysdev_drivers_lock);
-	list_del_init(&drv->entry);
-	if (cls) {
-		if (drv->remove) {
-			struct sys_device *dev;
-			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
-				drv->remove(dev);
-		}
-		kset_put(&cls->kset);
-	}
+	__sysdev_driver_remove(cls, drv, NULL);
 	mutex_unlock(&sysdev_drivers_lock);
 }
-
 EXPORT_SYMBOL_GPL(sysdev_driver_register);
 EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
 
-
-
 /**
  *	sysdev_register - add a system device to the tree
  *	@sysdev:	device in question
diff --git a/drivers/base/syscore.c b/drivers/base/syscore.c
new file mode 100644
index 0000000..90af294
--- /dev/null
+++ b/drivers/base/syscore.c
@@ -0,0 +1,117 @@
+/*
+ *  syscore.c - Execution of system core operations.
+ *
+ *  Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ *  This file is released under the GPLv2.
+ */
+
+#include <linux/syscore_ops.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+
+static LIST_HEAD(syscore_ops_list);
+static DEFINE_MUTEX(syscore_ops_lock);
+
+/**
+ * register_syscore_ops - Register a set of system core operations.
+ * @ops: System core operations to register.
+ */
+void register_syscore_ops(struct syscore_ops *ops)
+{
+	mutex_lock(&syscore_ops_lock);
+	list_add_tail(&ops->node, &syscore_ops_list);
+	mutex_unlock(&syscore_ops_lock);
+}
+EXPORT_SYMBOL_GPL(register_syscore_ops);
+
+/**
+ * unregister_syscore_ops - Unregister a set of system core operations.
+ * @ops: System core operations to unregister.
+ */
+void unregister_syscore_ops(struct syscore_ops *ops)
+{
+	mutex_lock(&syscore_ops_lock);
+	list_del(&ops->node);
+	mutex_unlock(&syscore_ops_lock);
+}
+EXPORT_SYMBOL_GPL(unregister_syscore_ops);
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * syscore_suspend - Execute all the registered system core suspend callbacks.
+ *
+ * This function is executed with one CPU on-line and disabled interrupts.
+ */
+int syscore_suspend(void)
+{
+	struct syscore_ops *ops;
+	int ret = 0;
+
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled before system core suspend.\n");
+
+	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
+		if (ops->suspend) {
+			if (initcall_debug)
+				pr_info("PM: Calling %pF\n", ops->suspend);
+			ret = ops->suspend();
+			if (ret)
+				goto err_out;
+			WARN_ONCE(!irqs_disabled(),
+				"Interrupts enabled after %pF\n", ops->suspend);
+		}
+
+	return 0;
+
+ err_out:
+	pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend);
+
+	list_for_each_entry_continue(ops, &syscore_ops_list, node)
+		if (ops->resume)
+			ops->resume();
+
+	return ret;
+}
+
+/**
+ * syscore_resume - Execute all the registered system core resume callbacks.
+ *
+ * This function is executed with one CPU on-line and disabled interrupts.
+ */
+void syscore_resume(void)
+{
+	struct syscore_ops *ops;
+
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled before system core resume.\n");
+
+	list_for_each_entry(ops, &syscore_ops_list, node)
+		if (ops->resume) {
+			if (initcall_debug)
+				pr_info("PM: Calling %pF\n", ops->resume);
+			ops->resume();
+			WARN_ONCE(!irqs_disabled(),
+				"Interrupts enabled after %pF\n", ops->resume);
+		}
+}
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * syscore_shutdown - Execute all the registered system core shutdown callbacks.
+ */
+void syscore_shutdown(void)
+{
+	struct syscore_ops *ops;
+
+	mutex_lock(&syscore_ops_lock);
+
+	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
+		if (ops->shutdown) {
+			if (initcall_debug)
+				pr_info("PM: Calling %pF\n", ops->shutdown);
+			ops->shutdown();
+		}
+
+	mutex_unlock(&syscore_ops_lock);
+}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 7888501..363855c 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -1768,8 +1768,8 @@ static int __init amiga_floppy_probe(struct platform_device *pdev)
 		return -EBUSY;
 
 	ret = -ENOMEM;
-	if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) ==
-	    NULL) {
+	raw_buf = amiga_chip_alloc(RAW_BUF_SIZE, "Floppy");
+	if (!raw_buf) {
 		printk("fd: cannot get chip mem buffer\n");
 		goto out_blkdev;
 	}
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 8cbfaa6..fe81c85 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -2177,7 +2177,7 @@ static void drbd_connector_callback(struct cn_msg *req, struct netlink_skb_parms
 		return;
 	}
 
-	if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
+	if (!cap_raised(current_cap(), CAP_SYS_ADMIN)) {
 		retcode = ERR_PERM;
 		goto fail;
 	}
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index e1e38b1..16dc364 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -31,6 +31,7 @@
 #include <linux/ceph/osd_client.h>
 #include <linux/ceph/mon_client.h>
 #include <linux/ceph/decode.h>
+#include <linux/parser.h>
 
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -54,6 +55,8 @@
 
 #define DEV_NAME_LEN		32
 
+#define RBD_NOTIFY_TIMEOUT_DEFAULT 10
+
 /*
  * block device image metadata (in-memory version)
  */
@@ -71,6 +74,12 @@ struct rbd_image_header {
 
 	char *snap_names;
 	u64 *snap_sizes;
+
+	u64 obj_version;
+};
+
+struct rbd_options {
+	int	notify_timeout;
 };
 
 /*
@@ -78,6 +87,7 @@ struct rbd_image_header {
  */
 struct rbd_client {
 	struct ceph_client	*client;
+	struct rbd_options	*rbd_opts;
 	struct kref		kref;
 	struct list_head	node;
 };
@@ -124,6 +134,9 @@ struct rbd_device {
 	char			pool_name[RBD_MAX_POOL_NAME_LEN];
 	int			poolid;
 
+	struct ceph_osd_event   *watch_event;
+	struct ceph_osd_request *watch_request;
+
 	char                    snap_name[RBD_MAX_SNAP_NAME_LEN];
 	u32 cur_snap;	/* index+1 of current snapshot within snap context
 			   0 - for the head */
@@ -177,6 +190,8 @@ static void rbd_put_dev(struct rbd_device *rbd_dev)
 	put_device(&rbd_dev->dev);
 }
 
+static int __rbd_update_snaps(struct rbd_device *rbd_dev);
+
 static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
 	struct gendisk *disk = bdev->bd_disk;
@@ -211,7 +226,8 @@ static const struct block_device_operations rbd_bd_ops = {
  * Initialize an rbd client instance.
  * We own *opt.
  */
-static struct rbd_client *rbd_client_create(struct ceph_options *opt)
+static struct rbd_client *rbd_client_create(struct ceph_options *opt,
+					    struct rbd_options *rbd_opts)
 {
 	struct rbd_client *rbdc;
 	int ret = -ENOMEM;
@@ -233,6 +249,8 @@ static struct rbd_client *rbd_client_create(struct ceph_options *opt)
 	if (ret < 0)
 		goto out_err;
 
+	rbdc->rbd_opts = rbd_opts;
+
 	spin_lock(&node_lock);
 	list_add_tail(&rbdc->node, &rbd_client_list);
 	spin_unlock(&node_lock);
@@ -267,6 +285,59 @@ static struct rbd_client *__rbd_client_find(struct ceph_options *opt)
 }
 
 /*
+ * mount options
+ */
+enum {
+	Opt_notify_timeout,
+	Opt_last_int,
+	/* int args above */
+	Opt_last_string,
+	/* string args above */
+};
+
+static match_table_t rbdopt_tokens = {
+	{Opt_notify_timeout, "notify_timeout=%d"},
+	/* int args above */
+	/* string args above */
+	{-1, NULL}
+};
+
+static int parse_rbd_opts_token(char *c, void *private)
+{
+	struct rbd_options *rbdopt = private;
+	substring_t argstr[MAX_OPT_ARGS];
+	int token, intval, ret;
+
+	token = match_token((char *)c, rbdopt_tokens, argstr);
+	if (token < 0)
+		return -EINVAL;
+
+	if (token < Opt_last_int) {
+		ret = match_int(&argstr[0], &intval);
+		if (ret < 0) {
+			pr_err("bad mount option arg (not int) "
+			       "at '%s'\n", c);
+			return ret;
+		}
+		dout("got int token %d val %d\n", token, intval);
+	} else if (token > Opt_last_int && token < Opt_last_string) {
+		dout("got string token %d val %s\n", token,
+		     argstr[0].from);
+	} else {
+		dout("got token %d\n", token);
+	}
+
+	switch (token) {
+	case Opt_notify_timeout:
+		rbdopt->notify_timeout = intval;
+		break;
+	default:
+		BUG_ON(token);
+	}
+	return 0;
+}
+
+/*
  * Get a ceph client with specific addr and configuration, if one does
  * not exist create it.
  */
@@ -276,11 +347,18 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
 	struct rbd_client *rbdc;
 	struct ceph_options *opt;
 	int ret;
+	struct rbd_options *rbd_opts;
+
+	rbd_opts = kzalloc(sizeof(*rbd_opts), GFP_KERNEL);
+	if (!rbd_opts)
+		return -ENOMEM;
+
+	rbd_opts->notify_timeout = RBD_NOTIFY_TIMEOUT_DEFAULT;
 
 	ret = ceph_parse_options(&opt, options, mon_addr,
-				 mon_addr + strlen(mon_addr), NULL, NULL);
+				 mon_addr + strlen(mon_addr), parse_rbd_opts_token, rbd_opts);
 	if (ret < 0)
-		return ret;
+		goto done_err;
 
 	spin_lock(&node_lock);
 	rbdc = __rbd_client_find(opt);
@@ -296,13 +374,18 @@ static int rbd_get_client(struct rbd_device *rbd_dev, const char *mon_addr,
 	}
 	spin_unlock(&node_lock);
 
-	rbdc = rbd_client_create(opt);
-	if (IS_ERR(rbdc))
-		return PTR_ERR(rbdc);
+	rbdc = rbd_client_create(opt, rbd_opts);
+	if (IS_ERR(rbdc)) {
+		ret = PTR_ERR(rbdc);
+		goto done_err;
+	}
 
 	rbd_dev->rbd_client = rbdc;
 	rbd_dev->client = rbdc->client;
 	return 0;
+done_err:
+	kfree(rbd_opts);
+	return ret;
 }
 
 /*
@@ -318,6 +401,7 @@ static void rbd_client_release(struct kref *kref)
 	spin_unlock(&node_lock);
 
 	ceph_destroy_client(rbdc->client);
+	kfree(rbdc->rbd_opts);
 	kfree(rbdc);
 }
 
@@ -666,7 +750,9 @@ static int rbd_do_request(struct request *rq,
 			  struct ceph_osd_req_op *ops,
 			  int num_reply,
 			  void (*rbd_cb)(struct ceph_osd_request *req,
-					 struct ceph_msg *msg))
+					 struct ceph_msg *msg),
+			  struct ceph_osd_request **linger_req,
+			  u64 *ver)
 {
 	struct ceph_osd_request *req;
 	struct ceph_file_layout *layout;
@@ -729,12 +815,20 @@ static int rbd_do_request(struct request *rq,
 				req->r_oid, req->r_oid_len);
 	up_read(&header->snap_rwsem);
 
+	if (linger_req) {
+		ceph_osdc_set_request_linger(&dev->client->osdc, req);
+		*linger_req = req;
+	}
+
 	ret = ceph_osdc_start_request(&dev->client->osdc, req, false);
 	if (ret < 0)
 		goto done_err;
 
 	if (!rbd_cb) {
 		ret = ceph_osdc_wait_request(&dev->client->osdc, req);
+		if (ver)
+			*ver = le64_to_cpu(req->r_reassert_version.version);
+		dout("reassert_ver=%lld\n", le64_to_cpu(req->r_reassert_version.version));
 		ceph_osdc_put_request(req);
 	}
 	return ret;
@@ -789,6 +883,11 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
 	kfree(req_data);
 }
 
+static void rbd_simple_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
+{
+	ceph_osdc_put_request(req);
+}
+
 /*
  * Do a synchronous ceph osd operation
  */
@@ -801,7 +900,9 @@ static int rbd_req_sync_op(struct rbd_device *dev,
 			   int num_reply,
 			   const char *obj,
 			   u64 ofs, u64 len,
-			   char *buf)
+			   char *buf,
+			   struct ceph_osd_request **linger_req,
+			   u64 *ver)
 {
 	int ret;
 	struct page **pages;
@@ -833,7 +934,8 @@ static int rbd_req_sync_op(struct rbd_device *dev,
 			  flags,
 			  ops,
 			  2,
-			  NULL);
+			  NULL,
+			  linger_req, ver);
 	if (ret < 0)
 		goto done_ops;
 
@@ -893,7 +995,7 @@ static int rbd_do_op(struct request *rq,
 			     flags,
 			     ops,
 			     num_reply,
-			     rbd_req_cb);
+			     rbd_req_cb, 0, NULL);
 done:
 	kfree(seg_name);
 	return ret;
@@ -940,18 +1042,174 @@ static int rbd_req_sync_read(struct rbd_device *dev,
 			  u64 snapid,
 			  const char *obj,
 			  u64 ofs, u64 len,
-			  char *buf)
+			  char *buf,
+			  u64 *ver)
 {
 	return rbd_req_sync_op(dev, NULL,
 			       (snapid ? snapid : CEPH_NOSNAP),
 			       CEPH_OSD_OP_READ,
 			       CEPH_OSD_FLAG_READ,
 			       NULL,
-			       1, obj, ofs, len, buf);
+			       1, obj, ofs, len, buf, NULL, ver);
 }
 
 /*
- * Request sync osd read
+ * Request sync osd watch
+ */
+static int rbd_req_sync_notify_ack(struct rbd_device *dev,
+				   u64 ver,
+				   u64 notify_id,
+				   const char *obj)
+{
+	struct ceph_osd_req_op *ops;
+	struct page **pages = NULL;
+	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0);
+	if (ret < 0)
+		return ret;
+
+	ops[0].watch.ver = cpu_to_le64(dev->header.obj_version);
+	ops[0].watch.cookie = notify_id;
+	ops[0].watch.flag = 0;
+
+	ret = rbd_do_request(NULL, dev, NULL, CEPH_NOSNAP,
+			  obj, 0, 0, NULL,
+			  pages, 0,
+			  CEPH_OSD_FLAG_READ,
+			  ops,
+			  1,
+			  rbd_simple_req_cb, 0, NULL);
+
+	rbd_destroy_ops(ops);
+	return ret;
+}
+
+static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
+{
+	struct rbd_device *dev = (struct rbd_device *)data;
+	if (!dev)
+		return;
+
+	dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name,
+		notify_id, (int)opcode);
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+	__rbd_update_snaps(dev);
+	mutex_unlock(&ctl_mutex);
+
+	rbd_req_sync_notify_ack(dev, ver, notify_id, dev->obj_md_name);
+}
+
+/*
+ * Request sync osd watch
+ */
+static int rbd_req_sync_watch(struct rbd_device *dev,
+			      const char *obj,
+			      u64 ver)
+{
+	struct ceph_osd_req_op *ops;
+	struct ceph_osd_client *osdc = &dev->client->osdc;
+
+	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = ceph_osdc_create_event(osdc, rbd_watch_cb, 0,
+				     (void *)dev, &dev->watch_event);
+	if (ret < 0)
+		goto fail;
+
+	ops[0].watch.ver = cpu_to_le64(ver);
+	ops[0].watch.cookie = cpu_to_le64(dev->watch_event->cookie);
+	ops[0].watch.flag = 1;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			      CEPH_NOSNAP,
+			      0,
+			      CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			      ops,
+			      1, obj, 0, 0, NULL,
+			      &dev->watch_request, NULL);
+
+	if (ret < 0)
+		goto fail_event;
+
+	rbd_destroy_ops(ops);
+	return 0;
+
+fail_event:
+	ceph_osdc_cancel_event(dev->watch_event);
+	dev->watch_event = NULL;
+fail:
+	rbd_destroy_ops(ops);
+	return ret;
+}
+
+struct rbd_notify_info {
+	struct rbd_device *dev;
+};
+
+static void rbd_notify_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
+{
+	struct rbd_device *dev = (struct rbd_device *)data;
+	if (!dev)
+		return;
+
+	dout("rbd_notify_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name,
+		notify_id, (int)opcode);
+}
+
+/*
+ * Request sync osd notify
+ */
+static int rbd_req_sync_notify(struct rbd_device *dev,
+		          const char *obj)
+{
+	struct ceph_osd_req_op *ops;
+	struct ceph_osd_client *osdc = &dev->client->osdc;
+	struct ceph_osd_event *event;
+	struct rbd_notify_info info;
+	int payload_len = sizeof(u32) + sizeof(u32);
+	int ret;
+
+	ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY, payload_len);
+	if (ret < 0)
+		return ret;
+
+	info.dev = dev;
+
+	ret = ceph_osdc_create_event(osdc, rbd_notify_cb, 1,
+				     (void *)&info, &event);
+	if (ret < 0)
+		goto fail;
+
+	ops[0].watch.ver = 1;
+	ops[0].watch.flag = 1;
+	ops[0].watch.cookie = event->cookie;
+	ops[0].watch.prot_ver = RADOS_NOTIFY_VER;
+	ops[0].watch.timeout = 12;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			       CEPH_NOSNAP,
+			       0,
+			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			       ops,
+			       1, obj, 0, 0, NULL, NULL, NULL);
+	if (ret < 0)
+		goto fail_event;
+
+	ret = ceph_osdc_wait_event(event, CEPH_OSD_TIMEOUT_DEFAULT);
+	dout("ceph_osdc_wait_event returned %d\n", ret);
+	rbd_destroy_ops(ops);
+	return 0;
+
+fail_event:
+	ceph_osdc_cancel_event(event);
+fail:
+	rbd_destroy_ops(ops);
+	return ret;
+}
+
+/*
+ * Request sync osd rollback
  */
 static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
 				     u64 snapid,
@@ -969,13 +1227,10 @@ static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
 			       0,
 			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
 			       ops,
-			       1, obj, 0, 0, NULL);
+			       1, obj, 0, 0, NULL, NULL, NULL);
 
 	rbd_destroy_ops(ops);
 
-	if (ret < 0)
-		return ret;
-
 	return ret;
 }
 
@@ -987,7 +1242,8 @@ static int rbd_req_sync_exec(struct rbd_device *dev,
 			     const char *cls,
 			     const char *method,
 			     const char *data,
-			     int len)
+			     int len,
+			     u64 *ver)
 {
 	struct ceph_osd_req_op *ops;
 	int cls_len = strlen(cls);
@@ -1010,7 +1266,7 @@ static int rbd_req_sync_exec(struct rbd_device *dev,
 			       0,
 			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
 			       ops,
-			       1, obj, 0, 0, NULL);
+			       1, obj, 0, 0, NULL, NULL, ver);
 
 	rbd_destroy_ops(ops);
 
@@ -1156,6 +1412,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev,
 	struct rbd_image_header_ondisk *dh;
 	int snap_count = 0;
 	u64 snap_names_len = 0;
+	u64 ver;
 
 	while (1) {
 		int len = sizeof(*dh) +
@@ -1171,7 +1428,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev,
 				       NULL, CEPH_NOSNAP,
 				       rbd_dev->obj_md_name,
 				       0, len,
-				       (char *)dh);
+				       (char *)dh, &ver);
 		if (rc < 0)
 			goto out_dh;
 
@@ -1188,6 +1445,7 @@ static int rbd_read_header(struct rbd_device *rbd_dev,
 		}
 		break;
 	}
+	header->obj_version = ver;
 
 out_dh:
 	kfree(dh);
@@ -1205,6 +1463,7 @@ static int rbd_header_add_snap(struct rbd_device *dev,
 	u64 new_snapid;
 	int ret;
 	void *data, *data_start, *data_end;
+	u64 ver;
 
 	/* we should create a snapshot only if we're pointing at the head */
 	if (dev->cur_snap)
@@ -1227,7 +1486,7 @@ static int rbd_header_add_snap(struct rbd_device *dev,
 	ceph_encode_64_safe(&data, data_end, new_snapid, bad);
 
 	ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add",
-				data_start, data - data_start);
+				data_start, data - data_start, &ver);
 
 	kfree(data_start);
 
@@ -1259,6 +1518,7 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev)
 	int ret;
 	struct rbd_image_header h;
 	u64 snap_seq;
+	int follow_seq = 0;
 
 	ret = rbd_read_header(rbd_dev, &h);
 	if (ret < 0)
@@ -1267,6 +1527,11 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev)
 	down_write(&rbd_dev->header.snap_rwsem);
 
 	snap_seq = rbd_dev->header.snapc->seq;
+	if (rbd_dev->header.total_snaps &&
+	    rbd_dev->header.snapc->snaps[0] == snap_seq)
+		/* pointing at the head, will need to follow that
+		   if head moves */
+		follow_seq = 1;
 
 	kfree(rbd_dev->header.snapc);
 	kfree(rbd_dev->header.snap_names);
@@ -1277,7 +1542,10 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev)
 	rbd_dev->header.snap_names = h.snap_names;
 	rbd_dev->header.snap_names_len = h.snap_names_len;
 	rbd_dev->header.snap_sizes = h.snap_sizes;
-	rbd_dev->header.snapc->seq = snap_seq;
+	if (follow_seq)
+		rbd_dev->header.snapc->seq = rbd_dev->header.snapc->snaps[0];
+	else
+		rbd_dev->header.snapc->seq = snap_seq;
 
 	ret = __rbd_init_snaps_header(rbd_dev);
 
@@ -1699,7 +1967,28 @@ static void rbd_bus_del_dev(struct rbd_device *rbd_dev)
 	device_unregister(&rbd_dev->dev);
 }
 
-static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count)
+static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
+{
+	int ret, rc;
+
+	do {
+		ret = rbd_req_sync_watch(rbd_dev, rbd_dev->obj_md_name,
+					 rbd_dev->header.obj_version);
+		if (ret == -ERANGE) {
+			mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+			rc = __rbd_update_snaps(rbd_dev);
+			mutex_unlock(&ctl_mutex);
+			if (rc < 0)
+				return rc;
+		}
+	} while (ret == -ERANGE);
+
+	return ret;
+}
+
+static ssize_t rbd_add(struct bus_type *bus,
+		       const char *buf,
+		       size_t count)
 {
 	struct ceph_osd_client *osdc;
 	struct rbd_device *rbd_dev;
@@ -1797,6 +2086,10 @@ static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count)
 	if (rc)
 		goto err_out_bus;
 
+	rc = rbd_init_watch_dev(rbd_dev);
+	if (rc)
+		goto err_out_bus;
+
 	return count;
 
 err_out_bus:
@@ -1849,6 +2142,12 @@ static void rbd_dev_release(struct device *dev)
 	struct rbd_device *rbd_dev =
 			container_of(dev, struct rbd_device, dev);
 
+	if (rbd_dev->watch_request)
+		ceph_osdc_unregister_linger_request(&rbd_dev->client->osdc,
+						    rbd_dev->watch_request);
+	if (rbd_dev->watch_event)
+		ceph_osdc_cancel_event(rbd_dev->watch_event);
+
 	rbd_put_client(rbd_dev);
 
 	/* clean up and free blkdev */
@@ -1914,14 +2213,24 @@ static ssize_t rbd_snap_add(struct device *dev,
 	ret = rbd_header_add_snap(rbd_dev,
 				  name, GFP_KERNEL);
 	if (ret < 0)
-		goto done_unlock;
+		goto err_unlock;
 
 	ret = __rbd_update_snaps(rbd_dev);
 	if (ret < 0)
-		goto done_unlock;
+		goto err_unlock;
+
+	/* shouldn't hold ctl_mutex when notifying.. notify might
+	   trigger a watch callback that would need to get that mutex */
+	mutex_unlock(&ctl_mutex);
+
+	/* make a best effort, don't error if failed */
+	rbd_req_sync_notify(rbd_dev, rbd_dev->obj_md_name);
 
 	ret = count;
-done_unlock:
+	kfree(name);
+	return ret;
+
+err_unlock:
 	mutex_unlock(&ctl_mutex);
 	kfree(name);
 	return ret;
diff --git a/drivers/block/smart1,2.h b/drivers/block/smart1,2.h
index a0b403a..e5565fb 100644
--- a/drivers/block/smart1,2.h
+++ b/drivers/block/smart1,2.h
@@ -95,7 +95,7 @@ static unsigned long smart4_completed(ctlr_info_t *h)
  /*
  *  This hardware returns interrupt pending at a different place and 
  *  it does not tell us if the fifo is empty, we will have check  
- *  that by getting a 0 back from the comamnd_completed call. 
+ *  that by getting a 0 back from the command_completed call. 
  */
 static unsigned long smart4_intr_pending(ctlr_info_t *h)
 {
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index d7aa39e..9cb8668 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -120,6 +120,10 @@ static DEFINE_SPINLOCK(minor_lock);
 #define EXTENDED (1<<EXT_SHIFT)
 #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
 #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
+#define EMULATED_HD_DISK_MINOR_OFFSET (0)
+#define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256)
+#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16))
+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4)
 
 #define DEV_NAME	"xvd"	/* name in /dev */
 
@@ -281,7 +285,7 @@ static int blkif_queue_request(struct request *req)
 	info->shadow[id].request = req;
 
 	ring_req->id = id;
-	ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
+	ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
 	ring_req->handle = info->handle;
 
 	ring_req->operation = rq_data_dir(req) ?
@@ -317,7 +321,7 @@ static int blkif_queue_request(struct request *req)
 				rq_data_dir(req) );
 
 		info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
-		ring_req->seg[i] =
+		ring_req->u.rw.seg[i] =
 				(struct blkif_request_segment) {
 					.gref       = ref,
 					.first_sect = fsect,
@@ -434,6 +438,65 @@ static void xlvbd_flush(struct blkfront_info *info)
 	       info->feature_flush ? "enabled" : "disabled");
 }
 
+static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
+{
+	int major;
+	major = BLKIF_MAJOR(vdevice);
+	*minor = BLKIF_MINOR(vdevice);
+	switch (major) {
+		case XEN_IDE0_MAJOR:
+			*offset = (*minor / 64) + EMULATED_HD_DISK_NAME_OFFSET;
+			*minor = ((*minor / 64) * PARTS_PER_DISK) +
+				EMULATED_HD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_IDE1_MAJOR:
+			*offset = (*minor / 64) + 2 + EMULATED_HD_DISK_NAME_OFFSET;
+			*minor = (((*minor / 64) + 2) * PARTS_PER_DISK) +
+				EMULATED_HD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_SCSI_DISK0_MAJOR:
+			*offset = (*minor / PARTS_PER_DISK) + EMULATED_SD_DISK_NAME_OFFSET;
+			*minor = *minor + EMULATED_SD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_SCSI_DISK1_MAJOR:
+		case XEN_SCSI_DISK2_MAJOR:
+		case XEN_SCSI_DISK3_MAJOR:
+		case XEN_SCSI_DISK4_MAJOR:
+		case XEN_SCSI_DISK5_MAJOR:
+		case XEN_SCSI_DISK6_MAJOR:
+		case XEN_SCSI_DISK7_MAJOR:
+			*offset = (*minor / PARTS_PER_DISK) + 
+				((major - XEN_SCSI_DISK1_MAJOR + 1) * 16) +
+				EMULATED_SD_DISK_NAME_OFFSET;
+			*minor = *minor +
+				((major - XEN_SCSI_DISK1_MAJOR + 1) * 16 * PARTS_PER_DISK) +
+				EMULATED_SD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_SCSI_DISK8_MAJOR:
+		case XEN_SCSI_DISK9_MAJOR:
+		case XEN_SCSI_DISK10_MAJOR:
+		case XEN_SCSI_DISK11_MAJOR:
+		case XEN_SCSI_DISK12_MAJOR:
+		case XEN_SCSI_DISK13_MAJOR:
+		case XEN_SCSI_DISK14_MAJOR:
+		case XEN_SCSI_DISK15_MAJOR:
+			*offset = (*minor / PARTS_PER_DISK) + 
+				((major - XEN_SCSI_DISK8_MAJOR + 8) * 16) +
+				EMULATED_SD_DISK_NAME_OFFSET;
+			*minor = *minor +
+				((major - XEN_SCSI_DISK8_MAJOR + 8) * 16 * PARTS_PER_DISK) +
+				EMULATED_SD_DISK_MINOR_OFFSET;
+			break;
+		case XENVBD_MAJOR:
+			*offset = *minor / PARTS_PER_DISK;
+			break;
+		default:
+			printk(KERN_WARNING "blkfront: your disk configuration is "
+					"incorrect, please use an xvd device instead\n");
+			return -ENODEV;
+	}
+	return 0;
+}
 
 static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
 			       struct blkfront_info *info,
@@ -441,7 +504,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
 {
 	struct gendisk *gd;
 	int nr_minors = 1;
-	int err = -ENODEV;
+	int err;
 	unsigned int offset;
 	int minor;
 	int nr_parts;
@@ -456,12 +519,20 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
 	}
 
 	if (!VDEV_IS_EXTENDED(info->vdevice)) {
-		minor = BLKIF_MINOR(info->vdevice);
-		nr_parts = PARTS_PER_DISK;
+		err = xen_translate_vdev(info->vdevice, &minor, &offset);
+		if (err)
+			return err;		
+ 		nr_parts = PARTS_PER_DISK;
 	} else {
 		minor = BLKIF_MINOR_EXT(info->vdevice);
 		nr_parts = PARTS_PER_EXT_DISK;
+		offset = minor / nr_parts;
+		if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4)
+			printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with "
+					"emulated IDE disks,\n\t choose an xvd device name"
+					"from xvde on\n", info->vdevice);
 	}
+	err = -ENODEV;
 
 	if ((minor % nr_parts) == 0)
 		nr_minors = nr_parts;
@@ -475,8 +546,6 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
 	if (gd == NULL)
 		goto release;
 
-	offset = minor / nr_parts;
-
 	if (nr_minors > 1) {
 		if (offset < 26)
 			sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset);
@@ -615,7 +684,7 @@ static void blkif_completion(struct blk_shadow *s)
 {
 	int i;
 	for (i = 0; i < s->req.nr_segments; i++)
-		gnttab_end_foreign_access(s->req.seg[i].gref, 0, 0UL);
+		gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL);
 }
 
 static irqreturn_t blkif_interrupt(int irq, void *dev_id)
@@ -932,7 +1001,7 @@ static int blkif_recover(struct blkfront_info *info)
 		/* Rewrite any grant references invalidated by susp/resume. */
 		for (j = 0; j < req->nr_segments; j++)
 			gnttab_grant_foreign_access_ref(
-				req->seg[j].gref,
+				req->u.rw.seg[j].gref,
 				info->xbdev->otherend_id,
 				pfn_to_mfn(info->shadow[req->id].frame[j]),
 				rq_data_dir(info->shadow[req->id].request));
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
index 829161e..2c590a7 100644
--- a/drivers/block/xsysace.c
+++ b/drivers/block/xsysace.c
@@ -1195,16 +1195,13 @@ static struct platform_driver ace_platform_driver = {
  */
 
 #if defined(CONFIG_OF)
-static int __devinit
-ace_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ace_of_probe(struct platform_device *op)
 {
 	struct resource res;
 	resource_size_t physaddr;
 	const u32 *id;
 	int irq, bus_width, rc;
 
-	dev_dbg(&op->dev, "ace_of_probe(%p, %p)\n", op, match);
-
 	/* device id */
 	id = of_get_property(op->dev.of_node, "port-number", NULL);
 
@@ -1245,7 +1242,7 @@ static const struct of_device_id ace_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, ace_of_match);
 
-static struct of_platform_driver ace_of_driver = {
+static struct platform_driver ace_of_driver = {
 	.probe = ace_of_probe,
 	.remove = __devexit_p(ace_of_remove),
 	.driver = {
@@ -1259,12 +1256,12 @@ static struct of_platform_driver ace_of_driver = {
 static inline int __init ace_of_register(void)
 {
 	pr_debug("xsysace: registering OF binding\n");
-	return of_register_platform_driver(&ace_of_driver);
+	return platform_driver_register(&ace_of_driver);
 }
 
 static inline void __exit ace_of_unregister(void)
 {
-	of_unregister_platform_driver(&ace_of_driver);
+	platform_driver_unregister(&ace_of_driver);
 }
 #else /* CONFIG_OF */
 /* CONFIG_OF not enabled; do nothing helpers */
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 02deef4..8e0de9a 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -219,4 +219,14 @@ config BT_ATH3K
 	  Say Y here to compile support for "Atheros firmware download driver"
 	  into the kernel or say M to compile it as module (ath3k).
 
+config BT_WILINK
+	tristate "Texas Instruments WiLink7 driver"
+	depends on TI_ST
+	help
+	  This enables the Bluetooth driver for Texas Instrument's BT/FM/GPS
+	  combo devices. This makes use of shared transport line discipline
+	  core driver to communicate with the BT core of the combo chip.
+
+	  Say Y here to compile support for Texas Instrument's WiLink7 driver
+	  into the kernel or say M to compile it as module.
 endmenu
diff --git a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
index 71bdf13..f4460f4 100644
--- a/drivers/bluetooth/Makefile
+++ b/drivers/bluetooth/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_BT_HCIBTSDIO)	+= btsdio.o
 obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
 obj-$(CONFIG_BT_MRVL)		+= btmrvl.o
 obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o
+obj-$(CONFIG_BT_WILINK)		+= btwilink.o
 
 btmrvl-y			:= btmrvl_main.o
 btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 6dcd55a..5577ed6 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -31,6 +31,30 @@
 
 #define VERSION "1.0"
 
+#define ATH3K_DNLOAD				0x01
+#define ATH3K_GETSTATE				0x05
+#define ATH3K_SET_NORMAL_MODE			0x07
+#define ATH3K_GETVERSION			0x09
+#define USB_REG_SWITCH_VID_PID			0x0a
+
+#define ATH3K_MODE_MASK				0x3F
+#define ATH3K_NORMAL_MODE			0x0E
+
+#define ATH3K_PATCH_UPDATE			0x80
+#define ATH3K_SYSCFG_UPDATE			0x40
+
+#define ATH3K_XTAL_FREQ_26M			0x00
+#define ATH3K_XTAL_FREQ_40M			0x01
+#define ATH3K_XTAL_FREQ_19P2			0x02
+#define ATH3K_NAME_LEN				0xFF
+
+struct ath3k_version {
+	unsigned int	rom_version;
+	unsigned int	build_version;
+	unsigned int	ram_version;
+	unsigned char	ref_clock;
+	unsigned char	reserved[0x07];
+};
 
 static struct usb_device_id ath3k_table[] = {
 	/* Atheros AR3011 */
@@ -42,15 +66,31 @@ static struct usb_device_id ath3k_table[] = {
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03F0, 0x311D) },
 
+	/* Atheros AR3012 with sflash firmware*/
+	{ USB_DEVICE(0x0CF3, 0x3004) },
+
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
+
 	{ }	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(usb, ath3k_table);
 
+#define BTUSB_ATH3012		0x80
+/* This table is to load patch and sysconfig files
+ * for AR3012 */
+static struct usb_device_id ath3k_blist_tbl[] = {
+
+	/* Atheros AR3012 with sflash firmware*/
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+
+	{ }	/* Terminating entry */
+};
+
 #define USB_REQ_DFU_DNLOAD	1
 #define BULK_SIZE		4096
+#define FW_HDR_SIZE		20
 
 static int ath3k_load_firmware(struct usb_device *udev,
 				const struct firmware *firmware)
@@ -106,28 +146,265 @@ error:
 	return err;
 }
 
+static int ath3k_get_state(struct usb_device *udev, unsigned char *state)
+{
+	int pipe = 0;
+
+	pipe = usb_rcvctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, ATH3K_GETSTATE,
+			USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+			state, 0x01, USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_get_version(struct usb_device *udev,
+			struct ath3k_version *version)
+{
+	int pipe = 0;
+
+	pipe = usb_rcvctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, ATH3K_GETVERSION,
+			USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version,
+			sizeof(struct ath3k_version),
+			USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_load_fwfile(struct usb_device *udev,
+		const struct firmware *firmware)
+{
+	u8 *send_buf;
+	int err, pipe, len, size, count, sent = 0;
+	int ret;
+
+	count = firmware->size;
+
+	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	if (!send_buf) {
+		BT_ERR("Can't allocate memory chunk for firmware");
+		return -ENOMEM;
+	}
+
+	size = min_t(uint, count, FW_HDR_SIZE);
+	memcpy(send_buf, firmware->data, size);
+
+	pipe = usb_sndctrlpipe(udev, 0);
+	ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD,
+			USB_TYPE_VENDOR, 0, 0, send_buf,
+			size, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0) {
+		BT_ERR("Can't change to loading configuration err");
+		kfree(send_buf);
+		return ret;
+	}
+
+	sent += size;
+	count -= size;
+
+	while (count) {
+		size = min_t(uint, count, BULK_SIZE);
+		pipe = usb_sndbulkpipe(udev, 0x02);
+
+		memcpy(send_buf, firmware->data + sent, size);
+
+		err = usb_bulk_msg(udev, pipe, send_buf, size,
+					&len, 3000);
+		if (err || (len != size)) {
+			BT_ERR("Error in firmware loading err = %d,"
+				"len = %d, size = %d", err, len, size);
+			kfree(send_buf);
+			return err;
+		}
+		sent  += size;
+		count -= size;
+	}
+
+	kfree(send_buf);
+	return 0;
+}
+
+static int ath3k_switch_pid(struct usb_device *udev)
+{
+	int pipe = 0;
+
+	pipe = usb_sndctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID,
+			USB_TYPE_VENDOR, 0, 0,
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_set_normal_mode(struct usb_device *udev)
+{
+	unsigned char fw_state;
+	int pipe = 0, ret;
+
+	ret = ath3k_get_state(udev, &fw_state);
+	if (ret < 0) {
+		BT_ERR("Can't get state to change to normal mode err");
+		return ret;
+	}
+
+	if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
+		BT_DBG("firmware was already in normal mode");
+		return 0;
+	}
+
+	pipe = usb_sndctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE,
+			USB_TYPE_VENDOR, 0, 0,
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_load_patch(struct usb_device *udev)
+{
+	unsigned char fw_state;
+	char filename[ATH3K_NAME_LEN] = {0};
+	const struct firmware *firmware;
+	struct ath3k_version fw_version, pt_version;
+	int ret;
+
+	ret = ath3k_get_state(udev, &fw_state);
+	if (ret < 0) {
+		BT_ERR("Can't get state to change to load ram patch err");
+		return ret;
+	}
+
+	if (fw_state & ATH3K_PATCH_UPDATE) {
+		BT_DBG("Patch was already downloaded");
+		return 0;
+	}
+
+	ret = ath3k_get_version(udev, &fw_version);
+	if (ret < 0) {
+		BT_ERR("Can't get version to change to load ram patch err");
+		return ret;
+	}
+
+	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
+		fw_version.rom_version);
+
+	ret = request_firmware(&firmware, filename, &udev->dev);
+	if (ret < 0) {
+		BT_ERR("Patch file not found %s", filename);
+		return ret;
+	}
+
+	pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
+	pt_version.build_version = *(int *)
+		(firmware->data + firmware->size - 4);
+
+	if ((pt_version.rom_version != fw_version.rom_version) ||
+		(pt_version.build_version <= fw_version.build_version)) {
+		BT_ERR("Patch file version did not match with firmware");
+		release_firmware(firmware);
+		return -EINVAL;
+	}
+
+	ret = ath3k_load_fwfile(udev, firmware);
+	release_firmware(firmware);
+
+	return ret;
+}
+
+static int ath3k_load_syscfg(struct usb_device *udev)
+{
+	unsigned char fw_state;
+	char filename[ATH3K_NAME_LEN] = {0};
+	const struct firmware *firmware;
+	struct ath3k_version fw_version;
+	int clk_value, ret;
+
+	ret = ath3k_get_state(udev, &fw_state);
+	if (ret < 0) {
+		BT_ERR("Can't get state to change to load configration err");
+		return -EBUSY;
+	}
+
+	ret = ath3k_get_version(udev, &fw_version);
+	if (ret < 0) {
+		BT_ERR("Can't get version to change to load ram patch err");
+		return ret;
+	}
+
+	switch (fw_version.ref_clock) {
+
+	case ATH3K_XTAL_FREQ_26M:
+		clk_value = 26;
+		break;
+	case ATH3K_XTAL_FREQ_40M:
+		clk_value = 40;
+		break;
+	case ATH3K_XTAL_FREQ_19P2:
+		clk_value = 19;
+		break;
+	default:
+		clk_value = 0;
+		break;
+	}
+
+	snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
+		fw_version.rom_version, clk_value, ".dfu");
+
+	ret = request_firmware(&firmware, filename, &udev->dev);
+	if (ret < 0) {
+		BT_ERR("Configuration file not found %s", filename);
+		return ret;
+	}
+
+	ret = ath3k_load_fwfile(udev, firmware);
+	release_firmware(firmware);
+
+	return ret;
+}
+
 static int ath3k_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	const struct firmware *firmware;
 	struct usb_device *udev = interface_to_usbdev(intf);
+	int ret;
 
 	BT_DBG("intf %p id %p", intf, id);
 
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
 		return -ENODEV;
 
-	if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
-		return -EIO;
+	/* match device ID in ath3k blacklist table */
+	if (!id->driver_info) {
+		const struct usb_device_id *match;
+		match = usb_match_id(intf, ath3k_blist_tbl);
+		if (match)
+			id = match;
 	}
 
-	if (ath3k_load_firmware(udev, firmware)) {
-		release_firmware(firmware);
+	/* load patch and sysconfig files for AR3012 */
+	if (id->driver_info & BTUSB_ATH3012) {
+		ret = ath3k_load_patch(udev);
+		if (ret < 0) {
+			BT_ERR("Loading patch file failed");
+			return ret;
+		}
+		ret = ath3k_load_syscfg(udev);
+		if (ret < 0) {
+			BT_ERR("Loading sysconfig file failed");
+			return ret;
+		}
+		ret = ath3k_set_normal_mode(udev);
+		if (ret < 0) {
+			BT_ERR("Set normal mode failed");
+			return ret;
+		}
+		ath3k_switch_pid(udev);
+		return 0;
+	}
+
+	if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) {
+		BT_ERR("Error loading firmware");
 		return -EIO;
 	}
+
+	ret = ath3k_load_firmware(udev, firmware);
 	release_firmware(firmware);
 
-	return 0;
+	return ret;
 }
 
 static void ath3k_disconnect(struct usb_interface *intf)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 700a384..8668114 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -105,6 +105,9 @@ static struct usb_device_id blacklist_table[] = {
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
+	/* Atheros 3012 with sflash firmware */
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE },
+
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
 
@@ -430,7 +433,7 @@ static void btusb_isoc_complete(struct urb *urb)
 	}
 }
 
-static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
+static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
 {
 	int i, offset = 0;
 
@@ -714,15 +717,11 @@ static int btusb_send_frame(struct sk_buff *skb)
 		pipe = usb_sndisocpipe(data->udev,
 					data->isoc_tx_ep->bEndpointAddress);
 
-		urb->dev      = data->udev;
-		urb->pipe     = pipe;
-		urb->context  = skb;
-		urb->complete = btusb_isoc_tx_complete;
-		urb->interval = data->isoc_tx_ep->bInterval;
+		usb_fill_int_urb(urb, data->udev, pipe,
+				skb->data, skb->len, btusb_isoc_tx_complete,
+				skb, data->isoc_tx_ep->bInterval);
 
 		urb->transfer_flags  = URB_ISO_ASAP;
-		urb->transfer_buffer = skb->data;
-		urb->transfer_buffer_length = skb->len;
 
 		__fill_isoc_descriptor(urb, skb->len,
 				le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
@@ -781,7 +780,7 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt)
 	}
 }
 
-static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
+static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 {
 	struct btusb_data *data = hdev->driver_data;
 	struct usb_interface *intf = data->isoc;
diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c
new file mode 100644
index 0000000..65d27af
--- /dev/null
+++ b/drivers/bluetooth/btwilink.c
@@ -0,0 +1,395 @@
+/*
+ *  Texas Instrument's Bluetooth Driver For Shared Transport.
+ *
+ *  Bluetooth Driver acts as interface between HCI core and
+ *  TI Shared Transport Layer.
+ *
+ *  Copyright (C) 2009-2010 Texas Instruments
+ *  Author: Raja Mani <raja_mani@ti.com>
+ *	Pavan Savoy <pavan_savoy@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#define DEBUG
+#include <linux/platform_device.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/hci.h>
+
+#include <linux/ti_wilink_st.h>
+
+/* Bluetooth Driver Version */
+#define VERSION               "1.0"
+#define MAX_BT_CHNL_IDS		3
+
+/* Number of seconds to wait for registration completion
+ * when ST returns PENDING status.
+ */
+#define BT_REGISTER_TIMEOUT   6000	/* 6 sec */
+
+/**
+ * struct ti_st - driver operation structure
+ * @hdev: hci device pointer which binds to bt driver
+ * @reg_status: ST registration callback status
+ * @st_write: write function provided by the ST driver
+ *	to be used by the driver during send_frame.
+ * @wait_reg_completion - completion sync between ti_st_open
+ *	and st_reg_completion_cb.
+ */
+struct ti_st {
+	struct hci_dev *hdev;
+	char reg_status;
+	long (*st_write) (struct sk_buff *);
+	struct completion wait_reg_completion;
+};
+
+/* Increments HCI counters based on pocket ID (cmd,acl,sco) */
+static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type)
+{
+	struct hci_dev *hdev = hst->hdev;
+
+	/* Update HCI stat counters */
+	switch (pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+	}
+}
+
+/* ------- Interfaces to Shared Transport ------ */
+
+/* Called by ST layer to indicate protocol registration completion
+ * status.ti_st_open() function will wait for signal from this
+ * API when st_register() function returns ST_PENDING.
+ */
+static void st_reg_completion_cb(void *priv_data, char data)
+{
+	struct ti_st *lhst = priv_data;
+
+	/* Save registration status for use in ti_st_open() */
+	lhst->reg_status = data;
+	/* complete the wait in ti_st_open() */
+	complete(&lhst->wait_reg_completion);
+}
+
+/* Called by Shared Transport layer when receive data is
+ * available */
+static long st_receive(void *priv_data, struct sk_buff *skb)
+{
+	struct ti_st *lhst = priv_data;
+	int err;
+
+	if (!skb)
+		return -EFAULT;
+
+	if (!lhst) {
+		kfree_skb(skb);
+		return -EFAULT;
+	}
+
+	skb->dev = (void *) lhst->hdev;
+
+	/* Forward skb to HCI core layer */
+	err = hci_recv_frame(skb);
+	if (err < 0) {
+		BT_ERR("Unable to push skb to HCI core(%d)", err);
+		return err;
+	}
+
+	lhst->hdev->stat.byte_rx += skb->len;
+
+	return 0;
+}
+
+/* ------- Interfaces to HCI layer ------ */
+/* protocol structure registered with shared transport */
+static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
+	{
+		.chnl_id = HCI_ACLDATA_PKT, /* ACL */
+		.hdr_len = sizeof(struct hci_acl_hdr),
+		.offset_len_in_hdr = offsetof(struct hci_acl_hdr, dlen),
+		.len_size = 2,	/* sizeof(dlen) in struct hci_acl_hdr */
+		.reserve = 8,
+	},
+	{
+		.chnl_id = HCI_SCODATA_PKT, /* SCO */
+		.hdr_len = sizeof(struct hci_sco_hdr),
+		.offset_len_in_hdr = offsetof(struct hci_sco_hdr, dlen),
+		.len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */
+		.reserve = 8,
+	},
+	{
+		.chnl_id = HCI_EVENT_PKT, /* HCI Events */
+		.hdr_len = sizeof(struct hci_event_hdr),
+		.offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),
+		.len_size = 1, /* sizeof(plen) in struct hci_event_hdr */
+		.reserve = 8,
+	},
+};
+
+/* Called from HCI core to initialize the device */
+static int ti_st_open(struct hci_dev *hdev)
+{
+	unsigned long timeleft;
+	struct ti_st *hst;
+	int err, i;
+
+	BT_DBG("%s %p", hdev->name, hdev);
+
+	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+		return -EBUSY;
+
+	/* provide contexts for callbacks from ST */
+	hst = hdev->driver_data;
+
+	for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+		ti_st_proto[i].priv_data = hst;
+		ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE;
+		ti_st_proto[i].recv = st_receive;
+		ti_st_proto[i].reg_complete_cb = st_reg_completion_cb;
+
+		/* Prepare wait-for-completion handler */
+		init_completion(&hst->wait_reg_completion);
+		/* Reset ST registration callback status flag,
+		 * this value will be updated in
+		 * st_reg_completion_cb()
+		 * function whenever it called from ST driver.
+		 */
+		hst->reg_status = -EINPROGRESS;
+
+		err = st_register(&ti_st_proto[i]);
+		if (!err)
+			goto done;
+
+		if (err != -EINPROGRESS) {
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			BT_ERR("st_register failed %d", err);
+			return err;
+		}
+
+		/* ST is busy with either protocol
+		 * registration or firmware download.
+		 */
+		BT_DBG("waiting for registration "
+				"completion signal from ST");
+		timeleft = wait_for_completion_timeout
+			(&hst->wait_reg_completion,
+			 msecs_to_jiffies(BT_REGISTER_TIMEOUT));
+		if (!timeleft) {
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			BT_ERR("Timeout(%d sec),didn't get reg "
+					"completion signal from ST",
+					BT_REGISTER_TIMEOUT / 1000);
+			return -ETIMEDOUT;
+		}
+
+		/* Is ST registration callback
+		 * called with ERROR status? */
+		if (hst->reg_status != 0) {
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			BT_ERR("ST registration completed with invalid "
+					"status %d", hst->reg_status);
+			return -EAGAIN;
+		}
+
+done:
+		hst->st_write = ti_st_proto[i].write;
+		if (!hst->st_write) {
+			BT_ERR("undefined ST write function");
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+				/* Undo registration with ST */
+				err = st_unregister(&ti_st_proto[i]);
+				if (err)
+					BT_ERR("st_unregister() failed with "
+							"error %d", err);
+				hst->st_write = NULL;
+			}
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* Close device */
+static int ti_st_close(struct hci_dev *hdev)
+{
+	int err, i;
+	struct ti_st *hst = hdev->driver_data;
+
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+		return 0;
+
+	for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+		err = st_unregister(&ti_st_proto[i]);
+		if (err)
+			BT_ERR("st_unregister(%d) failed with error %d",
+					ti_st_proto[i].chnl_id, err);
+	}
+
+	hst->st_write = NULL;
+
+	return err;
+}
+
+static int ti_st_send_frame(struct sk_buff *skb)
+{
+	struct hci_dev *hdev;
+	struct ti_st *hst;
+	long len;
+
+	hdev = (struct hci_dev *)skb->dev;
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return -EBUSY;
+
+	hst = hdev->driver_data;
+
+	/* Prepend skb with frame type */
+	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
+			skb->len);
+
+	/* Insert skb to shared transport layer's transmit queue.
+	 * Freeing skb memory is taken care in shared transport layer,
+	 * so don't free skb memory here.
+	 */
+	len = hst->st_write(skb);
+	if (len < 0) {
+		kfree_skb(skb);
+		BT_ERR("ST write failed (%ld)", len);
+		/* Try Again, would only fail if UART has gone bad */
+		return -EAGAIN;
+	}
+
+	/* ST accepted our skb. So, Go ahead and do rest */
+	hdev->stat.byte_tx += len;
+	ti_st_tx_complete(hst, bt_cb(skb)->pkt_type);
+
+	return 0;
+}
+
+static void ti_st_destruct(struct hci_dev *hdev)
+{
+	BT_DBG("%s", hdev->name);
+	/* do nothing here, since platform remove
+	 * would free the hdev->driver_data
+	 */
+}
+
+static int bt_ti_probe(struct platform_device *pdev)
+{
+	static struct ti_st *hst;
+	struct hci_dev *hdev;
+	int err;
+
+	hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
+	if (!hst)
+		return -ENOMEM;
+
+	/* Expose "hciX" device to user space */
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		kfree(hst);
+		return -ENOMEM;
+	}
+
+	BT_DBG("hdev %p", hdev);
+
+	hst->hdev = hdev;
+	hdev->bus = HCI_UART;
+	hdev->driver_data = hst;
+	hdev->open = ti_st_open;
+	hdev->close = ti_st_close;
+	hdev->flush = NULL;
+	hdev->send = ti_st_send_frame;
+	hdev->destruct = ti_st_destruct;
+	hdev->owner = THIS_MODULE;
+
+	err = hci_register_dev(hdev);
+	if (err < 0) {
+		BT_ERR("Can't register HCI device error %d", err);
+		kfree(hst);
+		hci_free_dev(hdev);
+		return err;
+	}
+
+	BT_DBG("HCI device registered (hdev %p)", hdev);
+
+	dev_set_drvdata(&pdev->dev, hst);
+	return err;
+}
+
+static int bt_ti_remove(struct platform_device *pdev)
+{
+	struct hci_dev *hdev;
+	struct ti_st *hst = dev_get_drvdata(&pdev->dev);
+
+	if (!hst)
+		return -EFAULT;
+
+	BT_DBG("%s", hst->hdev->name);
+
+	hdev = hst->hdev;
+	ti_st_close(hdev);
+	hci_unregister_dev(hdev);
+
+	hci_free_dev(hdev);
+	kfree(hst);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+	return 0;
+}
+
+static struct platform_driver btwilink_driver = {
+	.probe = bt_ti_probe,
+	.remove = bt_ti_remove,
+	.driver = {
+		.name = "btwilink",
+		.owner = THIS_MODULE,
+	},
+};
+
+/* ------- Module Init/Exit interfaces ------ */
+static int __init btwilink_init(void)
+{
+	BT_INFO("Bluetooth Driver for TI WiLink - Version %s", VERSION);
+
+	return platform_driver_register(&btwilink_driver);
+}
+
+static void __exit btwilink_exit(void)
+{
+	platform_driver_unregister(&btwilink_driver);
+}
+
+module_init(btwilink_init);
+module_exit(btwilink_exit);
+
+/* ------ Module Info ------ */
+
+MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");
+MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 6a160c1..bd34406 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -51,32 +51,32 @@ struct ath_struct {
 
 static int ath_wakeup_ar3k(struct tty_struct *tty)
 {
-	struct termios settings;
-	int status = tty->driver->ops->tiocmget(tty, NULL);
+	struct ktermios ktermios;
+	int status = tty->driver->ops->tiocmget(tty);
 
 	if (status & TIOCM_CTS)
 		return status;
 
 	/* Disable Automatic RTSCTS */
-	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
-	settings.c_cflag &= ~CRTSCTS;
-	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
+	memcpy(&ktermios, tty->termios, sizeof(ktermios));
+	ktermios.c_cflag &= ~CRTSCTS;
+	tty_set_termios(tty, &ktermios);
 
 	/* Clear RTS first */
-	status = tty->driver->ops->tiocmget(tty, NULL);
-	tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS);
+	status = tty->driver->ops->tiocmget(tty);
+	tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS);
 	mdelay(20);
 
 	/* Set RTS, wake up board */
-	status = tty->driver->ops->tiocmget(tty, NULL);
-	tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00);
+	status = tty->driver->ops->tiocmget(tty);
+	tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00);
 	mdelay(20);
 
-	status = tty->driver->ops->tiocmget(tty, NULL);
+	status = tty->driver->ops->tiocmget(tty);
 
-	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
-	settings.c_cflag |= CRTSCTS;
-	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
+	/* Disable Automatic RTSCTS */
+	ktermios.c_cflag |= CRTSCTS;
+	status = tty_set_termios(tty, &ktermios);
 
 	return status;
 }
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 3c6cabc..48ad2a7 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -398,6 +398,7 @@ static int hci_uart_register_dev(struct hci_uart *hu)
 	hdev->flush = hci_uart_flush;
 	hdev->send  = hci_uart_send_frame;
 	hdev->destruct = hci_uart_destruct;
+	hdev->parent = hu->tty->dev;
 
 	hdev->owner = THIS_MODULE;
 
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index b7980a83..04f8b2d 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,89 +4,7 @@
 
 menu "Character devices"
 
-config VT
-	bool "Virtual terminal" if EXPERT
-	depends on !S390
-	select INPUT
-	default y
-	---help---
-	  If you say Y here, you will get support for terminal devices with
-	  display and keyboard devices. These are called "virtual" because you
-	  can run several virtual terminals (also called virtual consoles) on
-	  one physical terminal. This is rather useful, for example one
-	  virtual terminal can collect system messages and warnings, another
-	  one can be used for a text-mode user session, and a third could run
-	  an X session, all in parallel. Switching between virtual terminals
-	  is done with certain key combinations, usually Alt-<function key>.
-
-	  The setterm command ("man setterm") can be used to change the
-	  properties (such as colors or beeping) of a virtual terminal. The
-	  man page console_codes(4) ("man console_codes") contains the special
-	  character sequences that can be used to change those properties
-	  directly. The fonts used on virtual terminals can be changed with
-	  the setfont ("man setfont") command and the key bindings are defined
-	  with the loadkeys ("man loadkeys") command.
-
-	  You need at least one virtual terminal device in order to make use
-	  of your keyboard and monitor. Therefore, only people configuring an
-	  embedded system would want to say N here in order to save some
-	  memory; the only way to log into such a system is then via a serial
-	  or network connection.
-
-	  If unsure, say Y, or else you won't be able to do much with your new
-	  shiny Linux system :-)
-
-config CONSOLE_TRANSLATIONS
-	depends on VT
-	default y
-	bool "Enable character translations in console" if EXPERT
-	---help---
-	  This enables support for font mapping and Unicode translation
-	  on virtual consoles.
-
-config VT_CONSOLE
-	bool "Support for console on virtual terminal" if EXPERT
-	depends on VT
-	default y
-	---help---
-	  The system console is the device which receives all kernel messages
-	  and warnings and which allows logins in single user mode. If you
-	  answer Y here, a virtual terminal (the device used to interact with
-	  a physical terminal) can be used as system console. This is the most
-	  common mode of operations, so you should say Y here unless you want
-	  the kernel messages be output only to a serial port (in which case
-	  you should say Y to "Console on serial port", below).
-
-	  If you do say Y here, by default the currently visible virtual
-	  terminal (/dev/tty0) will be used as system console. You can change
-	  that with a kernel command line option such as "console=tty3" which
-	  would use the third virtual terminal as system console. (Try "man
-	  bootparam" or see the documentation of your boot loader (lilo or
-	  loadlin) about how to pass options to the kernel at boot time.)
-
-	  If unsure, say Y.
-
-config HW_CONSOLE
-	bool
-	depends on VT && !S390 && !UML
-	default y
-
-config VT_HW_CONSOLE_BINDING
-       bool "Support for binding and unbinding console drivers"
-       depends on HW_CONSOLE
-       default n
-       ---help---
-         The virtual terminal is the device that interacts with the physical
-         terminal through console drivers. On these systems, at least one
-         console driver is loaded. In other configurations, additional console
-         drivers may be enabled, such as the framebuffer console. If more than
-         1 console driver is enabled, setting this to 'y' will allow you to
-         select the console driver that will serve as the backend for the
-         virtual terminals.
-
-	 See <file:Documentation/console/console.txt> for more
-	 information. For framebuffer console users, please refer to
-	 <file:Documentation/fb/fbcon.txt>.
+source "drivers/tty/Kconfig"
 
 config DEVKMEM
 	bool "/dev/kmem virtual device support"
@@ -97,253 +15,6 @@ config DEVKMEM
 	  kind of kernel debugging operations.
 	  When in doubt, say "N".
 
-config BFIN_JTAG_COMM
-	tristate "Blackfin JTAG Communication"
-	depends on BLACKFIN
-	help
-	  Add support for emulating a TTY device over the Blackfin JTAG.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called bfin_jtag_comm.
-
-config BFIN_JTAG_COMM_CONSOLE
-	bool "Console on Blackfin JTAG"
-	depends on BFIN_JTAG_COMM=y
-
-config SERIAL_NONSTANDARD
-	bool "Non-standard serial port support"
-	depends on HAS_IOMEM
-	---help---
-	  Say Y here if you have any non-standard serial boards -- boards
-	  which aren't supported using the standard "dumb" serial driver.
-	  This includes intelligent serial boards such as Cyclades,
-	  Digiboards, etc. These are usually used for systems that need many
-	  serial ports because they serve many terminals or dial-in
-	  connections.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about non-standard serial boards.
-
-	  Most people can say N here.
-
-config COMPUTONE
-	tristate "Computone IntelliPort Plus serial support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	---help---
-	  This driver supports the entire family of Intelliport II/Plus
-	  controllers with the exception of the MicroChannel controllers and
-	  products previous to the Intelliport II. These are multiport cards,
-	  which give you many serial ports. You would need something like this
-	  to connect more than two modems to your Linux box, for instance in
-	  order to become a dial-in server. If you have a card like that, say
-	  Y here and read <file:Documentation/serial/computone.txt>.
-
-	  To compile this driver as module, choose M here: the
-	  module will be called ip2.
-
-config ROCKETPORT
-	tristate "Comtrol RocketPort support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	help
-	  This driver supports Comtrol RocketPort and RocketModem PCI boards.   
-          These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
-          modems.  For information about the RocketPort/RocketModem  boards
-          and this driver read <file:Documentation/serial/rocket.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called rocket.
-
-	  If you want to compile this driver into the kernel, say Y here.  If
-          you don't have a Comtrol RocketPort/RocketModem card installed, say N.
-
-config CYCLADES
-	tristate "Cyclades async mux support"
-	depends on SERIAL_NONSTANDARD && (PCI || ISA)
-	select FW_LOADER
-	---help---
-	  This driver supports Cyclades Z and Y multiserial boards.
-	  You would need something like this to connect more than two modems to
-	  your Linux box, for instance in order to become a dial-in server.
-
-	  For information about the Cyclades-Z card, read
-	  <file:Documentation/serial/README.cycladesZ>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cyclades.
-
-	  If you haven't heard about it, it's safe to say N.
-
-config CYZ_INTR
-	bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && CYCLADES
-	help
-	  The Cyclades-Z family of multiport cards allows 2 (two) driver op
-	  modes: polling and interrupt. In polling mode, the driver will check
-	  the status of the Cyclades-Z ports every certain amount of time
-	  (which is called polling cycle and is configurable). In interrupt
-	  mode, it will use an interrupt line (IRQ) in order to check the
-	  status of the Cyclades-Z ports. The default op mode is polling. If
-	  unsure, say N.
-
-config DIGIEPCA
-	tristate "Digiboard Intelligent Async Support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	---help---
-	  This is a driver for Digi International's Xx, Xeve, and Xem series
-	  of cards which provide multiple serial ports. You would need
-	  something like this to connect more than two modems to your Linux
-	  box, for instance in order to become a dial-in server. This driver
-	  supports the original PC (ISA) boards as well as PCI, and EISA. If
-	  you have a card like this, say Y here and read the file
-	  <file:Documentation/serial/digiepca.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called epca.
-
-config MOXA_INTELLIO
-	tristate "Moxa Intellio support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	select FW_LOADER
-	help
-	  Say Y here if you have a Moxa Intellio multiport serial card.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called moxa.
-
-config MOXA_SMARTIO
-	tristate "Moxa SmartIO support v. 2.0"
-	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
-	help
-	  Say Y here if you have a Moxa SmartIO multiport serial card and/or
-	  want to help develop a new version of this driver.
-
-	  This is upgraded (1.9.1) driver from original Moxa drivers with
-	  changes finally resulting in PCI probing.
-
-	  This driver can also be built as a module. The module will be called
-	  mxser. If you want to do that, say M here.
-
-config ISI
-	tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
-	depends on SERIAL_NONSTANDARD && PCI
-	select FW_LOADER
-	help
-	  This is a driver for the Multi-Tech cards which provide several
-	  serial ports.  The driver is experimental and can currently only be
-	  built as a module. The module will be called isicom.
-	  If you want to do that, choose M here.
-
-config SYNCLINK
-	tristate "Microgate SyncLink card support"
-	depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API
-	help
-	  Provides support for the SyncLink ISA and PCI multiprotocol serial
-	  adapters. These adapters support asynchronous and HDLC bit
-	  synchronous communication up to 10Mbps (PCI adapter).
-
-	  This driver can only be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called synclink.  If you want to do that, say M
-	  here.
-
-config SYNCLINKMP
-	tristate "SyncLink Multiport support"
-	depends on SERIAL_NONSTANDARD && PCI
-	help
-	  Enable support for the SyncLink Multiport (2 or 4 ports)
-	  serial adapter, running asynchronous and HDLC communications up
-	  to 2.048Mbps. Each ports is independently selectable for
-	  RS-232, V.35, RS-449, RS-530, and X.21
-
-	  This driver may be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called synclinkmp.  If you want to do that, say M
-	  here.
-
-config SYNCLINK_GT
-	tristate "SyncLink GT/AC support"
-	depends on SERIAL_NONSTANDARD && PCI
-	help
-	  Support for SyncLink GT and SyncLink AC families of
-	  synchronous and asynchronous serial adapters
-	  manufactured by Microgate Systems, Ltd. (www.microgate.com)
-
-config N_HDLC
-	tristate "HDLC line discipline support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  Allows synchronous HDLC communications with tty device drivers that
-	  support synchronous HDLC such as the Microgate SyncLink adapter.
-
-	  This driver can be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called n_hdlc. If you want to do that, say M
-	  here.
-
-config N_GSM
-	tristate "GSM MUX line discipline support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	depends on NET
-	help
-	  This line discipline provides support for the GSM MUX protocol and
-	  presents the mux as a set of 61 individual tty devices.
-
-config RISCOM8
-	tristate "SDL RISCom/8 card support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  This is a driver for the SDL Communications RISCom/8 multiport card,
-	  which gives you many serial ports. You would need something like
-	  this to connect more than two modems to your Linux box, for instance
-	  in order to become a dial-in server. If you have a card like that,
-	  say Y here and read the file <file:Documentation/serial/riscom8.txt>.
-
-	  Also it's possible to say M here and compile this driver as kernel
-	  loadable module; the module will be called riscom8.
-
-config SPECIALIX
-	tristate "Specialix IO8+ card support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  This is a driver for the Specialix IO8+ multiport card (both the
-	  ISA and the PCI version) which gives you many serial ports. You
-	  would need something like this to connect more than two modems to
-	  your Linux box, for instance in order to become a dial-in server.
-
-	  If you have a card like that, say Y here and read the file
-	  <file:Documentation/serial/specialix.txt>. Also it's possible to say
-	  M here and compile this driver as kernel loadable module which will be
-	  called specialix.
-
-config SX
-	tristate "Specialix SX (and SI) card support"
-	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
-	help
-	  This is a driver for the SX and SI multiport serial cards.
-	  Please read the file <file:Documentation/serial/sx.txt> for details.
-
-	  This driver can only be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called sx. If you want to do that, say M here.
-
-config RIO
-	tristate "Specialix RIO system support"
-	depends on SERIAL_NONSTANDARD && BROKEN
-	help
-	  This is a driver for the Specialix RIO, a smart serial card which
-	  drives an outboard box that can support up to 128 ports.  Product
-	  information is at <http://www.perle.com/support/documentation.html#multiport>.
-	  There are both ISA and PCI versions.
-
-config RIO_OLDPCI
-	bool "Support really old RIO/PCI cards"
-	depends on RIO
-	help
-	  Older RIO PCI cards need some initialization-time configuration to
-	  determine the IRQ and some control addresses.  If you have a RIO and
-	  this doesn't seem to work, try setting this to Y.
-
 config STALDRV
 	bool "Stallion multiport serial support"
 	depends on SERIAL_NONSTANDARD
@@ -356,54 +27,6 @@ config STALDRV
 	  in this case.  If you have never heard about all this, it's safe to
 	  say N.
 
-config STALLION
-	tristate "Stallion EasyIO or EC8/32 support"
-	depends on STALDRV && (ISA || EISA || PCI)
-	help
-	  If you have an EasyIO or EasyConnection 8/32 multiport Stallion
-	  card, then this is for you; say Y.  Make sure to read
-	  <file:Documentation/serial/stallion.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called stallion.
-
-config ISTALLION
-	tristate "Stallion EC8/64, ONboard, Brumby support"
-	depends on STALDRV && (ISA || EISA || PCI)
-	help
-	  If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
-	  serial multiport card, say Y here. Make sure to read
-	  <file:Documentation/serial/stallion.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called istallion.
-
-config NOZOMI
-	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter"
-	depends on PCI && EXPERIMENTAL
-	help
-	  If you have a HSDPA driver Broadband Wireless Data Card -
-	  Globe Trotter PCMCIA card, say Y here.
-
-	  To compile this driver as a module, choose M here, the module
-	  will be called nozomi.
-
-config A2232
-	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ZORRO && BROKEN
-	---help---
-	  This option supports the 2232 7-port serial card shipped with the
-	  Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
-	  a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
-	  each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
-	  ports were connected with 8 pin DIN connectors on the card bracket,
-	  for which 8 pin to DB25 adapters were supplied. The card also had
-	  jumpers internally to toggle various pinning configurations.
-
-	  This driver can be built as a module; but then "generic_serial"
-	  will also be built as a module. This has to be loaded before
-	  "ser_a2232". If you want to do this, answer M here.
-
 config SGI_SNSC
 	bool "SGI Altix system controller communication support"
 	depends on (IA64_SGI_SN2 || IA64_GENERIC)
@@ -428,71 +51,6 @@ config SGI_MBCS
 
 source "drivers/tty/serial/Kconfig"
 
-config UNIX98_PTYS
-	bool "Unix98 PTY support" if EXPERT
-	default y
-	---help---
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  All modern Linux systems use the Unix98 ptys.  Say Y unless
-	  you're on an embedded system and want to conserve memory.
-
-config DEVPTS_MULTIPLE_INSTANCES
-	bool "Support multiple instances of devpts"
-	depends on UNIX98_PTYS
-	default n
-	---help---
-	  Enable support for multiple instances of devpts filesystem.
-	  If you want to have isolated PTY namespaces (eg: in containers),
-	  say Y here.  Otherwise, say N. If enabled, each mount of devpts
-	  filesystem with the '-o newinstance' option will create an
-	  independent PTY namespace.
-
-config LEGACY_PTYS
-	bool "Legacy (BSD) PTY support"
-	default y
-	---help---
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx
-	  for masters and /dev/ttyxx for slaves of pseudo
-	  terminals. This scheme has a number of problems, including
-	  security.  This option enables these legacy devices; on most
-	  systems, it is safe to say N.
-
-
-config LEGACY_PTY_COUNT
-	int "Maximum number of legacy PTY in use"
-	depends on LEGACY_PTYS
-	range 0 256
-	default "256"
-	---help---
-	  The maximum number of legacy PTYs that can be used at any one time.
-	  The default is 256, and should be more than enough.  Embedded
-	  systems may want to reduce this to save memory.
-
-	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
-	  architectures and 24 bytes on 64-bit architectures.
-
 config TTY_PRINTK
 	bool "TTY driver to output user messages via printk"
 	depends on EXPERT
@@ -612,84 +170,7 @@ config PPDEV
 
 	  If unsure, say N.
 
-config HVC_DRIVER
-	bool
-	help
-	  Generic "hypervisor virtual console" infrastructure for various
-	  hypervisors (pSeries, iSeries, Xen, lguest).
-	  It will automatically be selected if one of the back-end console drivers
-	  is selected.
-
-config HVC_IRQ
-	bool
-
-config HVC_CONSOLE
-	bool "pSeries Hypervisor Virtual Console support"
-	depends on PPC_PSERIES
-	select HVC_DRIVER
-	select HVC_IRQ
-	help
-	  pSeries machines when partitioned support a hypervisor virtual
-	  console. This driver allows each pSeries partition to have a console
-	  which is accessed via the HMC.
-
-config HVC_ISERIES
-	bool "iSeries Hypervisor Virtual Console support"
-	depends on PPC_ISERIES
-	default y
-	select HVC_DRIVER
-	select HVC_IRQ
-	select VIOPATH
-	help
-	  iSeries machines support a hypervisor virtual console.
-
-config HVC_RTAS
-	bool "IBM RTAS Console support"
-	depends on PPC_RTAS
-	select HVC_DRIVER
-	help
-	  IBM Console device driver which makes use of RTAS
-
-config HVC_BEAT
-	bool "Toshiba's Beat Hypervisor Console support"
-	depends on PPC_CELLEB
-	select HVC_DRIVER
-	help
-	  Toshiba's Cell Reference Set Beat Console device driver
-
-config HVC_IUCV
-	bool "z/VM IUCV Hypervisor console support (VM only)"
-	depends on S390
-	select HVC_DRIVER
-	select IUCV
-	default y
-	help
-	  This driver provides a Hypervisor console (HVC) back-end to access
-	  a Linux (console) terminal via a z/VM IUCV communication path.
-
-config HVC_XEN
-	bool "Xen Hypervisor Console support"
-	depends on XEN
-	select HVC_DRIVER
-	select HVC_IRQ
-	default y
-	help
-	  Xen virtual console device driver
-
-config HVC_UDBG
-       bool "udbg based fake hypervisor console"
-       depends on PPC && EXPERIMENTAL
-       select HVC_DRIVER
-       default n
-
-config HVC_DCC
-       bool "ARM JTAG DCC console"
-       depends on ARM
-       select HVC_DRIVER
-       help
-         This console uses the JTAG DCC on ARM to create a console under the HVC
-	 driver. This console is used through a JTAG only on ARM. If you don't have
-	 a JTAG then you probably don't want this option.
+source "drivers/tty/hvc/Kconfig"
 
 config VIRTIO_CONSOLE
 	tristate "Virtio console"
@@ -707,23 +188,6 @@ config VIRTIO_CONSOLE
 	  the port which can be used by udev scripts to create a
 	  symlink to the device.
 
-config HVCS
-	tristate "IBM Hypervisor Virtual Console Server support"
-	depends on PPC_PSERIES && HVC_CONSOLE
-	help
-	  Partitionable IBM Power5 ppc64 machines allow hosting of
-	  firmware virtual consoles from one Linux partition by
-	  another Linux partition.  This driver allows console data
-	  from Linux partitions to be accessed through TTY device
-	  interfaces in the device tree of a Linux partition running
-	  this driver.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called hvcs.  Additionally, this module
-	  will depend on arch specific APIs exported from hvcserver.ko
-	  which will also be compiled when this driver is built as a
-	  module.
-
 config IBM_BSR
 	tristate "IBM POWER Barrier Synchronization Register support"
 	depends on PPC_PSERIES
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 8238f89..057f654 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -5,31 +5,7 @@
 obj-y				+= mem.o random.o
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
-obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
-obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_MVME162_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_BVME6000_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_ROCKETPORT)	+= rocket.o
-obj-$(CONFIG_SERIAL167)		+= serial167.o
-obj-$(CONFIG_CYCLADES)		+= cyclades.o
-obj-$(CONFIG_STALLION)		+= stallion.o
-obj-$(CONFIG_ISTALLION)		+= istallion.o
-obj-$(CONFIG_NOZOMI)		+= nozomi.o
-obj-$(CONFIG_DIGIEPCA)		+= epca.o
-obj-$(CONFIG_SPECIALIX)		+= specialix.o
-obj-$(CONFIG_MOXA_INTELLIO)	+= moxa.o
-obj-$(CONFIG_A2232)		+= ser_a2232.o generic_serial.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
-obj-$(CONFIG_MOXA_SMARTIO)	+= mxser.o
-obj-$(CONFIG_COMPUTONE)		+= ip2/
-obj-$(CONFIG_RISCOM8)		+= riscom8.o
-obj-$(CONFIG_ISI)		+= isicom.o
-obj-$(CONFIG_SYNCLINK)		+= synclink.o
-obj-$(CONFIG_SYNCLINKMP)	+= synclinkmp.o
-obj-$(CONFIG_SYNCLINK_GT)	+= synclink_gt.o
-obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
-obj-$(CONFIG_SX)		+= sx.o generic_serial.o
-obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
 obj-$(CONFIG_VIRTIO_CONSOLE)	+= virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
 obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
deleted file mode 100644
index 6ee3348..0000000
--- a/drivers/char/amiserial.c
+++ /dev/null
@@ -1,2178 +0,0 @@
-/*
- *  linux/drivers/char/amiserial.c
- *
- * Serial driver for the amiga builtin port.
- *
- * This code was created by taking serial.c version 4.30 from kernel
- * release 2.3.22, replacing all hardware related stuff with the
- * corresponding amiga hardware actions, and removing all irrelevant
- * code. As a consequence, it uses many of the constants and names
- * associated with the registers and bits of 16550 compatible UARTS -
- * but only to keep track of status, etc in the state variables. It
- * was done this was to make it easier to keep the code in line with
- * (non hardware specific) changes to serial.c.
- *
- * The port is registered with the tty driver as minor device 64, and
- * therefore other ports should should only use 65 upwards.
- *
- * Richard Lucock 28/12/99
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
- * 		1998, 1999  Theodore Ts'o
- *
- */
-
-/*
- * Serial driver configuration section.  Here are the various options:
- *
- * SERIAL_PARANOIA_CHECK
- * 		Check the magic number for the async_structure where
- * 		ever possible.
- */
-
-#include <linux/delay.h>
-
-#undef SERIAL_PARANOIA_CHECK
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
-/* Sanity checks */
-
-#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s)
-#else
-#define DBG_CNT(s)
-#endif
-
-/*
- * End of serial driver configuration section.
- */
-
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-static char *serial_version = "4.30";
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/console.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-
-#include <asm/system.h>
-
-#include <asm/irq.h>
-
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-
-#define custom amiga_custom
-static char *serial_name = "Amiga-builtin serial driver";
-
-static struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-static struct async_struct *IRQ_ports;
-
-static unsigned char current_ctl_bits;
-
-static void change_speed(struct async_struct *info, struct ktermios *old);
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-
-
-static struct serial_state rs_table[1];
-
-#define NR_PORTS ARRAY_SIZE(rs_table)
-
-#include <asm/uaccess.h>
-
-#define serial_isroot()	(capable(CAP_SYS_ADMIN))
-
-
-static inline int serial_paranoia_check(struct async_struct *info,
-					char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for serial struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null async_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != SERIAL_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/* some serial hardware definitions */
-#define SDR_OVRUN   (1<<15)
-#define SDR_RBF     (1<<14)
-#define SDR_TBE     (1<<13)
-#define SDR_TSRE    (1<<12)
-
-#define SERPER_PARENB    (1<<15)
-
-#define AC_SETCLR   (1<<15)
-#define AC_UARTBRK  (1<<11)
-
-#define SER_DTR     (1<<7)
-#define SER_RTS     (1<<6)
-#define SER_DCD     (1<<5)
-#define SER_CTS     (1<<4)
-#define SER_DSR     (1<<3)
-
-static __inline__ void rtsdtr_ctrl(int bits)
-{
-    ciab.pra = ((bits & (SER_RTS | SER_DTR)) ^ (SER_RTS | SER_DTR)) | (ciab.pra & ~(SER_RTS | SER_DTR));
-}
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_stop(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_stop"))
-		return;
-
-	local_irq_save(flags);
-	if (info->IER & UART_IER_THRI) {
-		info->IER &= ~UART_IER_THRI;
-		/* disable Tx interrupt and remove any pending interrupts */
-		custom.intena = IF_TBE;
-		mb();
-		custom.intreq = IF_TBE;
-		mb();
-	}
-	local_irq_restore(flags);
-}
-
-static void rs_start(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_start"))
-		return;
-
-	local_irq_save(flags);
-	if (info->xmit.head != info->xmit.tail
-	    && info->xmit.buf
-	    && !(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		custom.intena = IF_SETCLR | IF_TBE;
-		mb();
-		/* set a pending Tx Interrupt, transmitter should restart now */
-		custom.intreq = IF_SETCLR | IF_TBE;
-		mb();
-	}
-	local_irq_restore(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt().  They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off.  People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible.  After you are done making modifications, it is not a bad
- * idea to do:
- * 
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static void rs_sched_event(struct async_struct *info,
-			   int event)
-{
-	info->event |= 1 << event;
-	tasklet_schedule(&info->tlet);
-}
-
-static void receive_chars(struct async_struct *info)
-{
-        int status;
-	int serdatr;
-	struct tty_struct *tty = info->tty;
-	unsigned char ch, flag;
-	struct	async_icount *icount;
-	int oe = 0;
-
-	icount = &info->state->icount;
-
-	status = UART_LSR_DR; /* We obviously have a character! */
-	serdatr = custom.serdatr;
-	mb();
-	custom.intreq = IF_RBF;
-	mb();
-
-	if((serdatr & 0x1ff) == 0)
-	    status |= UART_LSR_BI;
-	if(serdatr & SDR_OVRUN)
-	    status |= UART_LSR_OE;
-
-	ch = serdatr & 0xff;
-	icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("DR%02x:%02x...", ch, status);
-#endif
-	flag = TTY_NORMAL;
-
-	/*
-	 * We don't handle parity or frame errors - but I have left
-	 * the code in, since I'm not sure that the errors can't be
-	 * detected.
-	 */
-
-	if (status & (UART_LSR_BI | UART_LSR_PE |
-		      UART_LSR_FE | UART_LSR_OE)) {
-	  /*
-	   * For statistics only
-	   */
-	  if (status & UART_LSR_BI) {
-	    status &= ~(UART_LSR_FE | UART_LSR_PE);
-	    icount->brk++;
-	  } else if (status & UART_LSR_PE)
-	    icount->parity++;
-	  else if (status & UART_LSR_FE)
-	    icount->frame++;
-	  if (status & UART_LSR_OE)
-	    icount->overrun++;
-
-	  /*
-	   * Now check to see if character should be
-	   * ignored, and mask off conditions which
-	   * should be ignored.
-	   */
-	  if (status & info->ignore_status_mask)
-	    goto out;
-
-	  status &= info->read_status_mask;
-
-	  if (status & (UART_LSR_BI)) {
-#ifdef SERIAL_DEBUG_INTR
-	    printk("handling break....");
-#endif
-	    flag = TTY_BREAK;
-	    if (info->flags & ASYNC_SAK)
-	      do_SAK(tty);
-	  } else if (status & UART_LSR_PE)
-	    flag = TTY_PARITY;
-	  else if (status & UART_LSR_FE)
-	    flag = TTY_FRAME;
-	  if (status & UART_LSR_OE) {
-	    /*
-	     * Overrun is special, since it's
-	     * reported immediately, and doesn't
-	     * affect the current character
-	     */
-	     oe = 1;
-	  }
-	}
-	tty_insert_flip_char(tty, ch, flag);
-	if (oe == 1)
-		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-	tty_flip_buffer_push(tty);
-out:
-	return;
-}
-
-static void transmit_chars(struct async_struct *info)
-{
-	custom.intreq = IF_TBE;
-	mb();
-	if (info->x_char) {
-	        custom.serdat = info->x_char | 0x100;
-		mb();
-		info->state->icount.tx++;
-		info->x_char = 0;
-		return;
-	}
-	if (info->xmit.head == info->xmit.tail
-	    || info->tty->stopped
-	    || info->tty->hw_stopped) {
-		info->IER &= ~UART_IER_THRI;
-	        custom.intena = IF_TBE;
-		mb();
-		return;
-	}
-
-	custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
-	mb();
-	info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
-	info->state->icount.tx++;
-
-	if (CIRC_CNT(info->xmit.head,
-		     info->xmit.tail,
-		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
-		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("THRE...");
-#endif
-	if (info->xmit.head == info->xmit.tail) {
-	        custom.intena = IF_TBE;
-		mb();
-		info->IER &= ~UART_IER_THRI;
-	}
-}
-
-static void check_modem_status(struct async_struct *info)
-{
-	unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
-	unsigned char dstatus;
-	struct	async_icount *icount;
-
-	/* Determine bits that have changed */
-	dstatus = status ^ current_ctl_bits;
-	current_ctl_bits = status;
-
-	if (dstatus) {
-		icount = &info->state->icount;
-		/* update input line counters */
-		if (dstatus & SER_DSR)
-			icount->dsr++;
-		if (dstatus & SER_DCD) {
-			icount->dcd++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    !(status & SER_DCD))
-				hardpps();
-#endif
-		}
-		if (dstatus & SER_CTS)
-			icount->cts++;
-		wake_up_interruptible(&info->delta_msr_wait);
-	}
-
-	if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttyS%d CD now %s...", info->line,
-		       (!(status & SER_DCD)) ? "on" : "off");
-#endif
-		if (!(status & SER_DCD))
-			wake_up_interruptible(&info->open_wait);
-		else {
-#ifdef SERIAL_DEBUG_OPEN
-			printk("doing serial hangup...");
-#endif
-			if (info->tty)
-				tty_hangup(info->tty);
-		}
-	}
-	if (info->flags & ASYNC_CTS_FLOW) {
-		if (info->tty->hw_stopped) {
-			if (!(status & SER_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx start...");
-#endif
-				info->tty->hw_stopped = 0;
-				info->IER |= UART_IER_THRI;
-				custom.intena = IF_SETCLR | IF_TBE;
-				mb();
-				/* set a pending Tx Interrupt, transmitter should restart now */
-				custom.intreq = IF_SETCLR | IF_TBE;
-				mb();
-				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-				return;
-			}
-		} else {
-			if ((status & SER_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx stop...");
-#endif
-				info->tty->hw_stopped = 1;
-				info->IER &= ~UART_IER_THRI;
-				/* disable Tx interrupt and remove any pending interrupts */
-				custom.intena = IF_TBE;
-				mb();
-				custom.intreq = IF_TBE;
-				mb();
-			}
-		}
-	}
-}
-
-static irqreturn_t ser_vbl_int( int irq, void *data)
-{
-        /* vbl is just a periodic interrupt we tie into to update modem status */
-	struct async_struct * info = IRQ_ports;
-	/*
-	 * TBD - is it better to unregister from this interrupt or to
-	 * ignore it if MSI is clear ?
-	 */
-	if(info->IER & UART_IER_MSI)
-	  check_modem_status(info);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ser_rx_int(int irq, void *dev_id)
-{
-	struct async_struct * info;
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("ser_rx_int...");
-#endif
-
-	info = IRQ_ports;
-	if (!info || !info->tty)
-		return IRQ_NONE;
-
-	receive_chars(info);
-	info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
-	printk("end.\n");
-#endif
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ser_tx_int(int irq, void *dev_id)
-{
-	struct async_struct * info;
-
-	if (custom.serdatr & SDR_TBE) {
-#ifdef SERIAL_DEBUG_INTR
-	  printk("ser_tx_int...");
-#endif
-
-	  info = IRQ_ports;
-	  if (!info || !info->tty)
-		return IRQ_NONE;
-
-	  transmit_chars(info);
-	  info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
-	  printk("end.\n");
-#endif
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-
-static void do_softint(unsigned long private_)
-{
-	struct async_struct	*info = (struct async_struct *) private_;
-	struct tty_struct	*tty;
-
-	tty = info->tty;
-	if (!tty)
-		return;
-
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
-		tty_wakeup(tty);
-}
-
-/*
- * ---------------------------------------------------------------
- * Low level utility subroutines for the serial driver:  routines to
- * figure out the appropriate timeout for an interrupt chain, routines
- * to initialize and startup a serial port, and routines to shutdown a
- * serial port.  Useful stuff like that.
- * ---------------------------------------------------------------
- */
-
-static int startup(struct async_struct * info)
-{
-	unsigned long flags;
-	int	retval=0;
-	unsigned long page;
-
-	page = get_zeroed_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	local_irq_save(flags);
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		free_page(page);
-		goto errout;
-	}
-
-	if (info->xmit.buf)
-		free_page(page);
-	else
-		info->xmit.buf = (unsigned char *) page;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttys%d ...", info->line);
-#endif
-
-	/* Clear anything in the input buffer */
-
-	custom.intreq = IF_RBF;
-	mb();
-
-	retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
-	if (retval) {
-	  if (serial_isroot()) {
-	    if (info->tty)
-	      set_bit(TTY_IO_ERROR,
-		      &info->tty->flags);
-	    retval = 0;
-	  }
-	  goto errout;
-	}
-
-	/* enable both Rx and Tx interrupts */
-	custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
-	mb();
-	info->IER = UART_IER_MSI;
-
-	/* remember current state of the DCD and CTS bits */
-	current_ctl_bits = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
-
-	IRQ_ports = info;
-
-	info->MCR = 0;
-	if (info->tty->termios->c_cflag & CBAUD)
-	  info->MCR = SER_DTR | SER_RTS;
-	rtsdtr_ctrl(info->MCR);
-
-	if (info->tty)
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	info->xmit.head = info->xmit.tail = 0;
-
-	/*
-	 * Set up the tty->alt_speed kludge
-	 */
-	if (info->tty) {
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			info->tty->alt_speed = 57600;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			info->tty->alt_speed = 115200;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			info->tty->alt_speed = 230400;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			info->tty->alt_speed = 460800;
-	}
-
-	/*
-	 * and set the speed of the serial port
-	 */
-	change_speed(info, NULL);
-
-	info->flags |= ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-	return 0;
-
-errout:
-	local_irq_restore(flags);
-	return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct async_struct * info)
-{
-	unsigned long	flags;
-	struct serial_state *state;
-
-	if (!(info->flags & ASYNC_INITIALIZED))
-		return;
-
-	state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d ....\n", info->line);
-#endif
-
-	local_irq_save(flags); /* Disable interrupts */
-
-	/*
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
-	wake_up_interruptible(&info->delta_msr_wait);
-
-	IRQ_ports = NULL;
-
-	/*
-	 * Free the IRQ, if necessary
-	 */
-	free_irq(IRQ_AMIGA_VERTB, info);
-
-	if (info->xmit.buf) {
-		free_page((unsigned long) info->xmit.buf);
-		info->xmit.buf = NULL;
-	}
-
-	info->IER = 0;
-	custom.intena = IF_RBF | IF_TBE;
-	mb();
-
-	/* disable break condition */
-	custom.adkcon = AC_UARTBRK;
-	mb();
-
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-		info->MCR &= ~(SER_DTR|SER_RTS);
-	rtsdtr_ctrl(info->MCR);
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	info->flags &= ~ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-}
-
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(struct async_struct *info,
-			 struct ktermios *old_termios)
-{
-	int	quot = 0, baud_base, baud;
-	unsigned cflag, cval = 0;
-	int	bits;
-	unsigned long	flags;
-
-	if (!info->tty || !info->tty->termios)
-		return;
-	cflag = info->tty->termios->c_cflag;
-
-	/* Byte size is always 8 bits plus parity bit if requested */
-
-	cval = 3; bits = 10;
-	if (cflag & CSTOPB) {
-		cval |= 0x04;
-		bits++;
-	}
-	if (cflag & PARENB) {
-		cval |= UART_LCR_PARITY;
-		bits++;
-	}
-	if (!(cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
-	if (cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-#endif
-
-	/* Determine divisor based on baud rate */
-	baud = tty_get_baud_rate(info->tty);
-	if (!baud)
-		baud = 9600;	/* B0 transition handled in rs_set_termios */
-	baud_base = info->state->baud_base;
-	if (baud == 38400 &&
-	    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-		quot = info->state->custom_divisor;
-	else {
-		if (baud == 134)
-			/* Special case since 134 is really 134.5 */
-			quot = (2*baud_base / 269);
-		else if (baud)
-			quot = baud_base / baud;
-	}
-	/* If the quotient is zero refuse the change */
-	if (!quot && old_termios) {
-		/* FIXME: Will need updating for new tty in the end */
-		info->tty->termios->c_cflag &= ~CBAUD;
-		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
-		baud = tty_get_baud_rate(info->tty);
-		if (!baud)
-			baud = 9600;
-		if (baud == 38400 &&
-		    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-			quot = info->state->custom_divisor;
-		else {
-			if (baud == 134)
-				/* Special case since 134 is really 134.5 */
-				quot = (2*baud_base / 269);
-			else if (baud)
-				quot = baud_base / baud;
-		}
-	}
-	/* As a last resort, if the quotient is zero, default to 9600 bps */
-	if (!quot)
-		quot = baud_base / 9600;
-	info->quot = quot;
-	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	/* CTS flow control flag and modem status interrupts */
-	info->IER &= ~UART_IER_MSI;
-	if (info->flags & ASYNC_HARDPPS_CD)
-		info->IER |= UART_IER_MSI;
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->IER |= UART_IER_MSI;
-	} else
-		info->flags &= ~ASYNC_CTS_FLOW;
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else {
-		info->flags |= ASYNC_CHECK_CD;
-		info->IER |= UART_IER_MSI;
-	}
-	/* TBD:
-	 * Does clearing IER_MSI imply that we should disable the VBL interrupt ?
-	 */
-
-	/*
-	 * Set up parity check flag
-	 */
-
-	info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
-	if (I_INPCK(info->tty))
-		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
-		info->read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	info->ignore_status_mask = 0;
-	if (I_IGNPAR(info->tty))
-		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (I_IGNBRK(info->tty)) {
-		info->ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore 
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->tty))
-			info->ignore_status_mask |= UART_LSR_OE;
-	}
-	/*
-	 * !!! ignore all characters if CREAD is not set
-	 */
-	if ((cflag & CREAD) == 0)
-		info->ignore_status_mask |= UART_LSR_DR;
-	local_irq_save(flags);
-
-	{
-	  short serper;
-
-	/* Set up the baud rate */
-	  serper = quot - 1;
-
-	/* Enable or disable parity bit */
-
-	if(cval & UART_LCR_PARITY)
-	  serper |= (SERPER_PARENB);
-
-	custom.serper = serper;
-	mb();
-	}
-
-	info->LCR = cval;				/* Save LCR */
-	local_irq_restore(flags);
-}
-
-static int rs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct async_struct *info;
-	unsigned long flags;
-
-	info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_put_char"))
-		return 0;
-
-	if (!info->xmit.buf)
-		return 0;
-
-	local_irq_save(flags);
-	if (CIRC_SPACE(info->xmit.head,
-		       info->xmit.tail,
-		       SERIAL_XMIT_SIZE) == 0) {
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	info->xmit.buf[info->xmit.head++] = ch;
-	info->xmit.head &= SERIAL_XMIT_SIZE-1;
-	local_irq_restore(flags);
-	return 1;
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
-		return;
-
-	if (info->xmit.head == info->xmit.tail
-	    || tty->stopped
-	    || tty->hw_stopped
-	    || !info->xmit.buf)
-		return;
-
-	local_irq_save(flags);
-	info->IER |= UART_IER_THRI;
-	custom.intena = IF_SETCLR | IF_TBE;
-	mb();
-	/* set a pending Tx Interrupt, transmitter should restart now */
-	custom.intreq = IF_SETCLR | IF_TBE;
-	mb();
-	local_irq_restore(flags);
-}
-
-static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	struct async_struct *info;
-	unsigned long flags;
-
-	info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_write"))
-		return 0;
-
-	if (!info->xmit.buf)
-		return 0;
-
-	local_irq_save(flags);
-	while (1) {
-		c = CIRC_SPACE_TO_END(info->xmit.head,
-				      info->xmit.tail,
-				      SERIAL_XMIT_SIZE);
-		if (count < c)
-			c = count;
-		if (c <= 0) {
-			break;
-		}
-		memcpy(info->xmit.buf + info->xmit.head, buf, c);
-		info->xmit.head = ((info->xmit.head + c) &
-				   (SERIAL_XMIT_SIZE-1));
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	local_irq_restore(flags);
-
-	if (info->xmit.head != info->xmit.tail
-	    && !tty->stopped
-	    && !tty->hw_stopped
-	    && !(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		local_irq_disable();
-		custom.intena = IF_SETCLR | IF_TBE;
-		mb();
-		/* set a pending Tx Interrupt, transmitter should restart now */
-		custom.intreq = IF_SETCLR | IF_TBE;
-		mb();
-		local_irq_restore(flags);
-	}
-	return ret;
-}
-
-static int rs_write_room(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_write_room"))
-		return 0;
-	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static int rs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
-		return 0;
-	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static void rs_flush_buffer(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
-		return;
-	local_irq_save(flags);
-	info->xmit.head = info->xmit.tail = 0;
-	local_irq_restore(flags);
-	tty_wakeup(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct async_struct *info = tty->driver_data;
-        unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_send_char"))
-		return;
-
-	info->x_char = ch;
-	if (ch) {
-		/* Make sure transmit interrupts are on */
-
-	        /* Check this ! */
-	        local_irq_save(flags);
-		if(!(custom.intenar & IF_TBE)) {
-		    custom.intena = IF_SETCLR | IF_TBE;
-		    mb();
-		    /* set a pending Tx Interrupt, transmitter should restart now */
-		    custom.intreq = IF_SETCLR | IF_TBE;
-		    mb();
-		}
-		local_irq_restore(flags);
-
-		info->IER |= UART_IER_THRI;
-	}
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- * 
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct * tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
-		return;
-
-	if (I_IXOFF(tty))
-		rs_send_xchar(tty, STOP_CHAR(tty));
-
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR &= ~SER_RTS;
-
-	local_irq_save(flags);
-	rtsdtr_ctrl(info->MCR);
-	local_irq_restore(flags);
-}
-
-static void rs_unthrottle(struct tty_struct * tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			rs_send_xchar(tty, START_CHAR(tty));
-	}
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR |= SER_RTS;
-	local_irq_save(flags);
-	rtsdtr_ctrl(info->MCR);
-	local_irq_restore(flags);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_serial_info(struct async_struct * info,
-			   struct serial_struct __user * retinfo)
-{
-	struct serial_struct tmp;
-	struct serial_state *state = info->state;
-   
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tty_lock();
-	tmp.type = state->type;
-	tmp.line = state->line;
-	tmp.port = state->port;
-	tmp.irq = state->irq;
-	tmp.flags = state->flags;
-	tmp.xmit_fifo_size = state->xmit_fifo_size;
-	tmp.baud_base = state->baud_base;
-	tmp.close_delay = state->close_delay;
-	tmp.closing_wait = state->closing_wait;
-	tmp.custom_divisor = state->custom_divisor;
-	tty_unlock();
-	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_serial_info(struct async_struct * info,
-			   struct serial_struct __user * new_info)
-{
-	struct serial_struct new_serial;
- 	struct serial_state old_state, *state;
-	unsigned int		change_irq,change_port;
-	int 			retval = 0;
-
-	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-		return -EFAULT;
-
-	tty_lock();
-	state = info->state;
-	old_state = *state;
-  
-	change_irq = new_serial.irq != state->irq;
-	change_port = (new_serial.port != state->port);
-	if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
-	  tty_unlock();
-	  return -EINVAL;
-	}
-  
-	if (!serial_isroot()) {
-		if ((new_serial.baud_base != state->baud_base) ||
-		    (new_serial.close_delay != state->close_delay) ||
-		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
-		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (state->flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		state->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	if (new_serial.baud_base < 9600) {
-		tty_unlock();
-		return -EINVAL;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	state->baud_base = new_serial.baud_base;
-	state->flags = ((state->flags & ~ASYNC_FLAGS) |
-			(new_serial.flags & ASYNC_FLAGS));
-	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
-		       (info->flags & ASYNC_INTERNAL_FLAGS));
-	state->custom_divisor = new_serial.custom_divisor;
-	state->close_delay = new_serial.close_delay * HZ/100;
-	state->closing_wait = new_serial.closing_wait * HZ/100;
-	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-check_and_exit:
-	if (info->flags & ASYNC_INITIALIZED) {
-		if (((old_state.flags & ASYNC_SPD_MASK) !=
-		     (state->flags & ASYNC_SPD_MASK)) ||
-		    (old_state.custom_divisor != state->custom_divisor)) {
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-				info->tty->alt_speed = 57600;
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-				info->tty->alt_speed = 115200;
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-				info->tty->alt_speed = 230400;
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-				info->tty->alt_speed = 460800;
-			change_speed(info, NULL);
-		}
-	} else
-		retval = startup(info);
-	tty_unlock();
-	return retval;
-}
-
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * 	    is emptied.  On bus types like RS485, the transmitter must
- * 	    release the bus after transmitting. This must be done when
- * 	    the transmit shift register is empty, not be done when the
- * 	    transmit holding register is empty.  This functionality
- * 	    allows an RS485 driver to be written in user space. 
- */
-static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
-{
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	status = custom.serdatr;
-	mb();
-	local_irq_restore(flags);
-	result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
-	if (copy_to_user(value, &result, sizeof(int)))
-		return -EFAULT;
-	return 0;
-}
-
-
-static int rs_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned char control, status;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	control = info->MCR;
-	local_irq_save(flags);
-	status = ciab.pra;
-	local_irq_restore(flags);
-	return    ((control & SER_RTS) ? TIOCM_RTS : 0)
-		| ((control & SER_DTR) ? TIOCM_DTR : 0)
-		| (!(status  & SER_DCD) ? TIOCM_CAR : 0)
-		| (!(status  & SER_DSR) ? TIOCM_DSR : 0)
-		| (!(status  & SER_CTS) ? TIOCM_CTS : 0);
-}
-
-static int rs_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	local_irq_save(flags);
-	if (set & TIOCM_RTS)
-		info->MCR |= SER_RTS;
-	if (set & TIOCM_DTR)
-		info->MCR |= SER_DTR;
-	if (clear & TIOCM_RTS)
-		info->MCR &= ~SER_RTS;
-	if (clear & TIOCM_DTR)
-		info->MCR &= ~SER_DTR;
-	rtsdtr_ctrl(info->MCR);
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*
- * rs_break() --- routine which turns the break handling on or off
- */
-static int rs_break(struct tty_struct *tty, int break_state)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_break"))
-		return -EINVAL;
-
-	local_irq_save(flags);
-	if (break_state == -1)
-	  custom.adkcon = AC_SETCLR | AC_UARTBRK;
-	else
-	  custom.adkcon = AC_UARTBRK;
-	mb();
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- *     RI where only 0->1 is counted.
- */
-static int rs_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct async_struct *info = tty->driver_data;
-	struct async_icount cnow;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	cnow = info->state->icount;
-	local_irq_restore(flags);
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct async_struct * info = tty->driver_data;
-	struct async_icount cprev, cnow;	/* kernel counter temps */
-	void __user *argp = (void __user *)arg;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-		case TIOCGSERIAL:
-			return get_serial_info(info, argp);
-		case TIOCSSERIAL:
-			return set_serial_info(info, argp);
-		case TIOCSERCONFIG:
-			return 0;
-
-		case TIOCSERGETLSR: /* Get line status register */
-			return get_lsr_info(info, argp);
-
-		case TIOCSERGSTRUCT:
-			if (copy_to_user(argp,
-					 info, sizeof(struct async_struct)))
-				return -EFAULT;
-			return 0;
-
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
- 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-		case TIOCMIWAIT:
-			local_irq_save(flags);
-			/* note the counters on entry */
-			cprev = info->state->icount;
-			local_irq_restore(flags);
-			while (1) {
-				interruptible_sleep_on(&info->delta_msr_wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				local_irq_save(flags);
-				cnow = info->state->icount; /* atomic copy */
-				local_irq_restore(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;
-			}
-			/* NOTREACHED */
-
-		case TIOCSERGWILD:
-		case TIOCSERSWILD:
-			/* "setserial -W" is called in Debian boot */
-			printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
-			return 0;
-
-		default:
-			return -ENOIOCTLCMD;
-		}
-	return 0;
-}
-
-static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-	unsigned int cflag = tty->termios->c_cflag;
-
-	change_speed(info, old_termios);
-
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) &&
-	    !(cflag & CBAUD)) {
-		info->MCR &= ~(SER_DTR|SER_RTS);
-		local_irq_save(flags);
-		rtsdtr_ctrl(info->MCR);
-		local_irq_restore(flags);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    (cflag & CBAUD)) {
-		info->MCR |= SER_DTR;
-		if (!(tty->termios->c_cflag & CRTSCTS) || 
-		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->MCR |= SER_RTS;
-		}
-		local_irq_save(flags);
-		rtsdtr_ctrl(info->MCR);
-		local_irq_restore(flags);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rs_start(tty);
-	}
-
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- * 
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_close(struct tty_struct *tty, struct file * filp)
-{
-	struct async_struct * info = tty->driver_data;
-	struct serial_state *state;
-	unsigned long flags;
-
-	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
-		return;
-
-	state = info->state;
-
-	local_irq_save(flags);
-
-	if (tty_hung_up_p(filp)) {
-		DBG_CNT("before DEC-hung");
-		local_irq_restore(flags);
-		return;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
-	if ((tty->count == 1) && (state->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  state->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("rs_close: bad serial port count; tty->count is 1, "
-		       "state->count is %d\n", state->count);
-		state->count = 1;
-	}
-	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for ttys%d: %d\n",
-		       info->line, state->count);
-		state->count = 0;
-	}
-	if (state->count) {
-		DBG_CNT("before DEC-2");
-		local_irq_restore(flags);
-		return;
-	}
-	info->flags |= ASYNC_CLOSING;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	info->read_status_mask &= ~UART_LSR_DR;
-	if (info->flags & ASYNC_INITIALIZED) {
-	        /* disable receive interrupts */
-	        custom.intena = IF_RBF;
-		mb();
-		/* clear any pending receive interrupt */
-		custom.intreq = IF_RBF;
-		mb();
-
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		rs_wait_until_sent(tty, info->timeout);
-	}
-	shutdown(info);
-	rs_flush_buffer(tty);
-		
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-	info->event = 0;
-	info->tty = NULL;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			msleep_interruptible(jiffies_to_msecs(info->close_delay));
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-	local_irq_restore(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	int tty_was_locked = tty_locked();
-	int lsr;
-
-	if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
-		return;
-
-	if (info->xmit_fifo_size == 0)
-		return; /* Just in case.... */
-
-	orig_jiffies = jiffies;
-
-	/*
-	 * tty_wait_until_sent is called from lots of places,
-	 * with or without the BTM.
-	 */
-	if (!tty_was_locked)
-		tty_lock();
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 * 
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
-	char_time = char_time / 5;
-	if (char_time == 0)
-		char_time = 1;
-	if (timeout)
-	  char_time = min_t(unsigned long, char_time, timeout);
-	/*
-	 * If the transmitter hasn't cleared in twice the approximate
-	 * amount of time to send the entire FIFO, it probably won't
-	 * ever clear.  This assumes the UART isn't doing flow
-	 * control, which is currently the case.  Hence, if it ever
-	 * takes longer than info->timeout, this is probably due to a
-	 * UART bug of some kind.  So, we clamp the timeout parameter at
-	 * 2*info->timeout.
-	 */
-	if (!timeout || timeout > 2*info->timeout)
-		timeout = 2*info->timeout;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
-	printk("jiff=%lu...", jiffies);
-#endif
-	while(!((lsr = custom.serdatr) & SDR_TSRE)) {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-		printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-		msleep_interruptible(jiffies_to_msecs(char_time));
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-	__set_current_state(TASK_RUNNING);
-	if (!tty_was_locked)
-		tty_unlock();
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_hangup(struct tty_struct *tty)
-{
-	struct async_struct * info = tty->driver_data;
-	struct serial_state *state = info->state;
-
-	if (serial_paranoia_check(info, tty->name, "rs_hangup"))
-		return;
-
-	state = info->state;
-
-	rs_flush_buffer(tty);
-	shutdown(info);
-	info->event = 0;
-	state->count = 0;
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->tty = NULL;
-	wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-			   struct async_struct *info)
-{
-#ifdef DECLARE_WAITQUEUE
-	DECLARE_WAITQUEUE(wait, current);
-#else
-	struct wait_queue wait = { current, NULL };
-#endif
-	struct serial_state *state = info->state;
-	int		retval;
-	int		do_clocal = 0, extra_count = 0;
-	unsigned long	flags;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		if (info->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		return ((info->flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, state->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);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttys%d, count = %d\n",
-	       state->line, state->count);
-#endif
-	local_irq_save(flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = 1;
-		state->count--;
-	}
-	local_irq_restore(flags);
-	info->blocked_open++;
-	while (1) {
-		local_irq_save(flags);
-		if (tty->termios->c_cflag & CBAUD)
-		        rtsdtr_ctrl(SER_DTR|SER_RTS);
-		local_irq_restore(flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-			if (info->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-		if (!(info->flags & ASYNC_CLOSING) &&
-		    (do_clocal || (!(ciab.pra & SER_DCD)) ))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttys%d, count = %d\n",
-		       info->line, state->count);
-#endif
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-	if (extra_count)
-		state->count++;
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttys%d, count = %d\n",
-	       info->line, state->count);
-#endif
-	if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}
-
-static int get_async_struct(int line, struct async_struct **ret_info)
-{
-	struct async_struct *info;
-	struct serial_state *sstate;
-
-	sstate = rs_table + line;
-	sstate->count++;
-	if (sstate->info) {
-		*ret_info = sstate->info;
-		return 0;
-	}
-	info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
-	if (!info) {
-		sstate->count--;
-		return -ENOMEM;
-	}
-#ifdef DECLARE_WAITQUEUE
-	init_waitqueue_head(&info->open_wait);
-	init_waitqueue_head(&info->close_wait);
-	init_waitqueue_head(&info->delta_msr_wait);
-#endif
-	info->magic = SERIAL_MAGIC;
-	info->port = sstate->port;
-	info->flags = sstate->flags;
-	info->xmit_fifo_size = sstate->xmit_fifo_size;
-	info->line = line;
-	tasklet_init(&info->tlet, do_softint, (unsigned long)info);
-	info->state = sstate;
-	if (sstate->info) {
-		kfree(info);
-		*ret_info = sstate->info;
-		return 0;
-	}
-	*ret_info = sstate->info = info;
-	return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_open(struct tty_struct *tty, struct file * filp)
-{
-	struct async_struct	*info;
-	int 			retval, line;
-
-	line = tty->index;
-	if ((line < 0) || (line >= NR_PORTS)) {
-		return -ENODEV;
-	}
-	retval = get_async_struct(line, &info);
-	if (retval) {
-		return retval;
-	}
-	tty->driver_data = info;
-	info->tty = tty;
-	if (serial_paranoia_check(info, tty->name, "rs_open"))
-		return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s, count = %d\n", tty->name, info->state->count);
-#endif
-	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	/*
-	 * If the port is the middle of closing, bail out now
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		if (info->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		return ((info->flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval) {
-		return retval;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("rs_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s successful...", tty->name);
-#endif
-	return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline void line_info(struct seq_file *m, struct serial_state *state)
-{
-	struct async_struct *info = state->info, scr_info;
-	char	stat_buf[30], control, status;
-	unsigned long flags;
-
-	seq_printf(m, "%d: uart:amiga_builtin",state->line);
-
-	/*
-	 * Figure out the current RS-232 lines
-	 */
-	if (!info) {
-		info = &scr_info;	/* This is just for serial_{in,out} */
-
-		info->magic = SERIAL_MAGIC;
-		info->flags = state->flags;
-		info->quot = 0;
-		info->tty = NULL;
-	}
-	local_irq_save(flags);
-	status = ciab.pra;
-	control = info ? info->MCR : status;
-	local_irq_restore(flags);
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if(!(control & SER_RTS))
-		strcat(stat_buf, "|RTS");
-	if(!(status & SER_CTS))
-		strcat(stat_buf, "|CTS");
-	if(!(control & SER_DTR))
-		strcat(stat_buf, "|DTR");
-	if(!(status & SER_DSR))
-		strcat(stat_buf, "|DSR");
-	if(!(status & SER_DCD))
-		strcat(stat_buf, "|CD");
-
-	if (info->quot) {
-		seq_printf(m, " baud:%d", state->baud_base / info->quot);
-	}
-
-	seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx);
-
-	if (state->icount.frame)
-		seq_printf(m, " fe:%d", state->icount.frame);
-
-	if (state->icount.parity)
-		seq_printf(m, " pe:%d", state->icount.parity);
-
-	if (state->icount.brk)
-		seq_printf(m, " brk:%d", state->icount.brk);
-
-	if (state->icount.overrun)
-		seq_printf(m, " oe:%d", state->icount.overrun);
-
-	/*
-	 * Last thing is the RS-232 status lines
-	 */
-	seq_printf(m, " %s\n", stat_buf+1);
-}
-
-static int rs_proc_show(struct seq_file *m, void *v)
-{
-	seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
-	line_info(m, &rs_table[0]);
-	return 0;
-}
-
-static int rs_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, rs_proc_show, NULL);
-}
-
-static const struct file_operations rs_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= rs_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static void show_serial_version(void)
-{
- 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
-static const struct tty_operations serial_ops = {
-	.open = rs_open,
-	.close = rs_close,
-	.write = rs_write,
-	.put_char = rs_put_char,
-	.flush_chars = rs_flush_chars,
-	.write_room = rs_write_room,
-	.chars_in_buffer = rs_chars_in_buffer,
-	.flush_buffer = rs_flush_buffer,
-	.ioctl = rs_ioctl,
-	.throttle = rs_throttle,
-	.unthrottle = rs_unthrottle,
-	.set_termios = rs_set_termios,
-	.stop = rs_stop,
-	.start = rs_start,
-	.hangup = rs_hangup,
-	.break_ctl = rs_break,
-	.send_xchar = rs_send_xchar,
-	.wait_until_sent = rs_wait_until_sent,
-	.tiocmget = rs_tiocmget,
-	.tiocmset = rs_tiocmset,
-	.get_icount = rs_get_icount,
-	.proc_fops = &rs_proc_fops,
-};
-
-/*
- * The serial driver boot-time initialization code!
- */
-static int __init amiga_serial_probe(struct platform_device *pdev)
-{
-	unsigned long flags;
-	struct serial_state * state;
-	int error;
-
-	serial_driver = alloc_tty_driver(1);
-	if (!serial_driver)
-		return -ENOMEM;
-
-	IRQ_ports = NULL;
-
-	show_serial_version();
-
-	/* Initialize the tty_driver structure */
-
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = "amiserial";
-	serial_driver->name = "ttyS";
-	serial_driver->major = TTY_MAJOR;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(serial_driver, &serial_ops);
-
-	error = tty_register_driver(serial_driver);
-	if (error)
-		goto fail_put_tty_driver;
-
-	state = rs_table;
-	state->magic = SSTATE_MAGIC;
-	state->port = (int)&custom.serdatr; /* Just to give it a value */
-	state->line = 0;
-	state->custom_divisor = 0;
-	state->close_delay = 5*HZ/10;
-	state->closing_wait = 30*HZ;
-	state->icount.cts = state->icount.dsr = 
-	  state->icount.rng = state->icount.dcd = 0;
-	state->icount.rx = state->icount.tx = 0;
-	state->icount.frame = state->icount.parity = 0;
-	state->icount.overrun = state->icount.brk = 0;
-
-	printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
-		       state->line);
-
-	/* Hardware set up */
-
-	state->baud_base = amiga_colorclock;
-	state->xmit_fifo_size = 1;
-
-	/* set ISRs, and then disable the rx interrupts */
-	error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
-	if (error)
-		goto fail_unregister;
-
-	error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED,
-			    "serial RX", state);
-	if (error)
-		goto fail_free_irq;
-
-	local_irq_save(flags);
-
-	/* turn off Rx and Tx interrupts */
-	custom.intena = IF_RBF | IF_TBE;
-	mb();
-
-	/* clear any pending interrupt */
-	custom.intreq = IF_RBF | IF_TBE;
-	mb();
-
-	local_irq_restore(flags);
-
-	/*
-	 * set the appropriate directions for the modem control flags,
-	 * and clear RTS and DTR
-	 */
-	ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
-	ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
-
-	platform_set_drvdata(pdev, state);
-
-	return 0;
-
-fail_free_irq:
-	free_irq(IRQ_AMIGA_TBE, state);
-fail_unregister:
-	tty_unregister_driver(serial_driver);
-fail_put_tty_driver:
-	put_tty_driver(serial_driver);
-	return error;
-}
-
-static int __exit amiga_serial_remove(struct platform_device *pdev)
-{
-	int error;
-	struct serial_state *state = platform_get_drvdata(pdev);
-	struct async_struct *info = state->info;
-
-	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
-	tasklet_kill(&info->tlet);
-	if ((error = tty_unregister_driver(serial_driver)))
-		printk("SERIAL: failed to unregister serial driver (%d)\n",
-		       error);
-	put_tty_driver(serial_driver);
-
-	rs_table[0].info = NULL;
-	kfree(info);
-
-	free_irq(IRQ_AMIGA_TBE, rs_table);
-	free_irq(IRQ_AMIGA_RBF, rs_table);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return error;
-}
-
-static struct platform_driver amiga_serial_driver = {
-	.remove = __exit_p(amiga_serial_remove),
-	.driver   = {
-		.name	= "amiga-serial",
-		.owner	= THIS_MODULE,
-	},
-};
-
-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);
-
-
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
-
-/*
- * ------------------------------------------------------------
- * Serial console driver
- * ------------------------------------------------------------
- */
-
-static void amiga_serial_putc(char c)
-{
-	custom.serdat = (unsigned char)c | 0x100;
-	while (!(custom.serdatr & 0x2000))
-		barrier();
-}
-
-/*
- *	Print a string to the serial port trying not to disturb
- *	any possible real use of the port...
- *
- *	The console must be locked when we get here.
- */
-static void serial_console_write(struct console *co, const char *s,
-				unsigned count)
-{
-	unsigned short intena = custom.intenar;
-
-	custom.intena = IF_TBE;
-
-	while (count--) {
-		if (*s == '\n')
-			amiga_serial_putc('\r');
-		amiga_serial_putc(*s++);
-	}
-
-	custom.intena = IF_SETCLR | (intena & IF_TBE);
-}
-
-static struct tty_driver *serial_console_device(struct console *c, int *index)
-{
-	*index = 0;
-	return serial_driver;
-}
-
-static struct console sercons = {
-	.name =		"ttyS",
-	.write =	serial_console_write,
-	.device =	serial_console_device,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
-/*
- *	Register console.
- */
-static int __init amiserial_console_init(void)
-{
-	register_console(&sercons);
-	return 0;
-}
-console_initcall(amiserial_console_init);
-
-#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:amiga-serial");
diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c
deleted file mode 100644
index 1640244..0000000
--- a/drivers/char/bfin_jtag_comm.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- * TTY over Blackfin JTAG Communication
- *
- * Copyright 2008-2009 Analog Devices Inc.
- *
- * Enter bugs at http://blackfin.uclinux.org/
- *
- * Licensed under the GPL-2 or later.
- */
-
-#define DRV_NAME "bfin-jtag-comm"
-#define DEV_NAME "ttyBFJC"
-#define pr_fmt(fmt) DRV_NAME ": " fmt
-
-#include <linux/circ_buf.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <asm/atomic.h>
-
-#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
-
-/* See the Debug/Emulation chapter in the HRM */
-#define EMUDOF   0x00000001	/* EMUDAT_OUT full & valid */
-#define EMUDIF   0x00000002	/* EMUDAT_IN full & valid */
-#define EMUDOOVF 0x00000004	/* EMUDAT_OUT overflow */
-#define EMUDIOVF 0x00000008	/* EMUDAT_IN overflow */
-
-static inline uint32_t bfin_write_emudat(uint32_t emudat)
-{
-	__asm__ __volatile__("emudat = %0;" : : "d"(emudat));
-	return emudat;
-}
-
-static inline uint32_t bfin_read_emudat(void)
-{
-	uint32_t emudat;
-	__asm__ __volatile__("%0 = emudat;" : "=d"(emudat));
-	return emudat;
-}
-
-static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d)
-{
-	return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24));
-}
-
-#define CIRC_SIZE 2048	/* see comment in tty_io.c:do_tty_write() */
-#define CIRC_MASK (CIRC_SIZE - 1)
-#define circ_empty(circ)     ((circ)->head == (circ)->tail)
-#define circ_free(circ)      CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE)
-#define circ_cnt(circ)       CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE)
-#define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK])
-
-static struct tty_driver *bfin_jc_driver;
-static struct task_struct *bfin_jc_kthread;
-static struct tty_struct * volatile bfin_jc_tty;
-static unsigned long bfin_jc_count;
-static DEFINE_MUTEX(bfin_jc_tty_mutex);
-static volatile struct circ_buf bfin_jc_write_buf;
-
-static int
-bfin_jc_emudat_manager(void *arg)
-{
-	uint32_t inbound_len = 0, outbound_len = 0;
-
-	while (!kthread_should_stop()) {
-		/* no one left to give data to, so sleep */
-		if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) {
-			pr_debug("waiting for readers\n");
-			__set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule();
-			__set_current_state(TASK_RUNNING);
-		}
-
-		/* no data available, so just chill */
-		if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) {
-			pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n",
-				inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head);
-			if (inbound_len)
-				schedule();
-			else
-				schedule_timeout_interruptible(HZ);
-			continue;
-		}
-
-		/* if incoming data is ready, eat it */
-		if (bfin_read_DBGSTAT() & EMUDIF) {
-			struct tty_struct *tty;
-			mutex_lock(&bfin_jc_tty_mutex);
-			tty = (struct tty_struct *)bfin_jc_tty;
-			if (tty != NULL) {
-				uint32_t emudat = bfin_read_emudat();
-				if (inbound_len == 0) {
-					pr_debug("incoming length: 0x%08x\n", emudat);
-					inbound_len = emudat;
-				} else {
-					size_t num_chars = (4 <= inbound_len ? 4 : inbound_len);
-					pr_debug("  incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars);
-					inbound_len -= num_chars;
-					tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars);
-					tty_flip_buffer_push(tty);
-				}
-			}
-			mutex_unlock(&bfin_jc_tty_mutex);
-		}
-
-		/* if outgoing data is ready, post it */
-		if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) {
-			if (outbound_len == 0) {
-				outbound_len = circ_cnt(&bfin_jc_write_buf);
-				bfin_write_emudat(outbound_len);
-				pr_debug("outgoing length: 0x%08x\n", outbound_len);
-			} else {
-				struct tty_struct *tty;
-				int tail = bfin_jc_write_buf.tail;
-				size_t ate = (4 <= outbound_len ? 4 : outbound_len);
-				uint32_t emudat =
-				bfin_write_emudat_chars(
-					circ_byte(&bfin_jc_write_buf, tail + 0),
-					circ_byte(&bfin_jc_write_buf, tail + 1),
-					circ_byte(&bfin_jc_write_buf, tail + 2),
-					circ_byte(&bfin_jc_write_buf, tail + 3)
-				);
-				bfin_jc_write_buf.tail += ate;
-				outbound_len -= ate;
-				mutex_lock(&bfin_jc_tty_mutex);
-				tty = (struct tty_struct *)bfin_jc_tty;
-				if (tty)
-					tty_wakeup(tty);
-				mutex_unlock(&bfin_jc_tty_mutex);
-				pr_debug("  outgoing data: 0x%08x (pushing %zu)\n", emudat, ate);
-			}
-		}
-	}
-
-	__set_current_state(TASK_RUNNING);
-	return 0;
-}
-
-static int
-bfin_jc_open(struct tty_struct *tty, struct file *filp)
-{
-	mutex_lock(&bfin_jc_tty_mutex);
-	pr_debug("open %lu\n", bfin_jc_count);
-	++bfin_jc_count;
-	bfin_jc_tty = tty;
-	wake_up_process(bfin_jc_kthread);
-	mutex_unlock(&bfin_jc_tty_mutex);
-	return 0;
-}
-
-static void
-bfin_jc_close(struct tty_struct *tty, struct file *filp)
-{
-	mutex_lock(&bfin_jc_tty_mutex);
-	pr_debug("close %lu\n", bfin_jc_count);
-	if (--bfin_jc_count == 0)
-		bfin_jc_tty = NULL;
-	wake_up_process(bfin_jc_kthread);
-	mutex_unlock(&bfin_jc_tty_mutex);
-}
-
-/* XXX: we dont handle the put_char() case where we must handle count = 1 */
-static int
-bfin_jc_circ_write(const unsigned char *buf, int count)
-{
-	int i;
-	count = min(count, circ_free(&bfin_jc_write_buf));
-	pr_debug("going to write chunk of %i bytes\n", count);
-	for (i = 0; i < count; ++i)
-		circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i];
-	bfin_jc_write_buf.head += i;
-	return i;
-}
-
-#ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE
-# define console_lock()
-# define console_unlock()
-#endif
-static int
-bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	int i;
-	console_lock();
-	i = bfin_jc_circ_write(buf, count);
-	console_unlock();
-	wake_up_process(bfin_jc_kthread);
-	return i;
-}
-
-static void
-bfin_jc_flush_chars(struct tty_struct *tty)
-{
-	wake_up_process(bfin_jc_kthread);
-}
-
-static int
-bfin_jc_write_room(struct tty_struct *tty)
-{
-	return circ_free(&bfin_jc_write_buf);
-}
-
-static int
-bfin_jc_chars_in_buffer(struct tty_struct *tty)
-{
-	return circ_cnt(&bfin_jc_write_buf);
-}
-
-static void
-bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	unsigned long expire = jiffies + timeout;
-	while (!circ_empty(&bfin_jc_write_buf)) {
-		if (signal_pending(current))
-			break;
-		if (time_after(jiffies, expire))
-			break;
-	}
-}
-
-static const struct tty_operations bfin_jc_ops = {
-	.open            = bfin_jc_open,
-	.close           = bfin_jc_close,
-	.write           = bfin_jc_write,
-	/*.put_char        = bfin_jc_put_char,*/
-	.flush_chars     = bfin_jc_flush_chars,
-	.write_room      = bfin_jc_write_room,
-	.chars_in_buffer = bfin_jc_chars_in_buffer,
-	.wait_until_sent = bfin_jc_wait_until_sent,
-};
-
-static int __init bfin_jc_init(void)
-{
-	int ret;
-
-	bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
-	if (IS_ERR(bfin_jc_kthread))
-		return PTR_ERR(bfin_jc_kthread);
-
-	ret = -ENOMEM;
-
-	bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0;
-	bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL);
-	if (!bfin_jc_write_buf.buf)
-		goto err;
-
-	bfin_jc_driver = alloc_tty_driver(1);
-	if (!bfin_jc_driver)
-		goto err;
-
-	bfin_jc_driver->owner        = THIS_MODULE;
-	bfin_jc_driver->driver_name  = DRV_NAME;
-	bfin_jc_driver->name         = DEV_NAME;
-	bfin_jc_driver->type         = TTY_DRIVER_TYPE_SERIAL;
-	bfin_jc_driver->subtype      = SERIAL_TYPE_NORMAL;
-	bfin_jc_driver->init_termios = tty_std_termios;
-	tty_set_operations(bfin_jc_driver, &bfin_jc_ops);
-
-	ret = tty_register_driver(bfin_jc_driver);
-	if (ret)
-		goto err;
-
-	pr_init(KERN_INFO DRV_NAME ": initialized\n");
-
-	return 0;
-
- err:
-	put_tty_driver(bfin_jc_driver);
-	kfree(bfin_jc_write_buf.buf);
-	kthread_stop(bfin_jc_kthread);
-	return ret;
-}
-module_init(bfin_jc_init);
-
-static void __exit bfin_jc_exit(void)
-{
-	kthread_stop(bfin_jc_kthread);
-	kfree(bfin_jc_write_buf.buf);
-	tty_unregister_driver(bfin_jc_driver);
-	put_tty_driver(bfin_jc_driver);
-}
-module_exit(bfin_jc_exit);
-
-#if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
-static void
-bfin_jc_straight_buffer_write(const char *buf, unsigned count)
-{
-	unsigned ate = 0;
-	while (bfin_read_DBGSTAT() & EMUDOF)
-		continue;
-	bfin_write_emudat(count);
-	while (ate < count) {
-		while (bfin_read_DBGSTAT() & EMUDOF)
-			continue;
-		bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]);
-		ate += 4;
-	}
-}
-#endif
-
-#ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE
-static void
-bfin_jc_console_write(struct console *co, const char *buf, unsigned count)
-{
-	if (bfin_jc_kthread == NULL)
-		bfin_jc_straight_buffer_write(buf, count);
-	else
-		bfin_jc_circ_write(buf, count);
-}
-
-static struct tty_driver *
-bfin_jc_console_device(struct console *co, int *index)
-{
-	*index = co->index;
-	return bfin_jc_driver;
-}
-
-static struct console bfin_jc_console = {
-	.name    = DEV_NAME,
-	.write   = bfin_jc_console_write,
-	.device  = bfin_jc_console_device,
-	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
-	.index   = -1,
-};
-
-static int __init bfin_jc_console_init(void)
-{
-	register_console(&bfin_jc_console);
-	return 0;
-}
-console_initcall(bfin_jc_console_init);
-#endif
-
-#ifdef CONFIG_EARLY_PRINTK
-static void __init
-bfin_jc_early_write(struct console *co, const char *buf, unsigned int count)
-{
-	bfin_jc_straight_buffer_write(buf, count);
-}
-
-static struct __initdata console bfin_jc_early_console = {
-	.name   = "early_BFJC",
-	.write   = bfin_jc_early_write,
-	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
-	.index   = -1,
-};
-
-struct console * __init
-bfin_jc_early_init(unsigned int port, unsigned int cflag)
-{
-	return &bfin_jc_early_console;
-}
-#endif
-
-MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
-MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/cd1865.h b/drivers/char/cd1865.h
deleted file mode 100644
index 9940966..0000000
--- a/drivers/char/cd1865.h
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- *      linux/drivers/char/cd1865.h -- Definitions relating to the CD1865
- *                          for the Specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support.
- *
- *      This driver was developped in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- */
-
-/*
- * Definitions for Driving CD180/CD1864/CD1865 based eightport serial cards.
- */
-
-
-/* Values of choice for Interrupt ACKs */
-/* These values are "obligatory" if you use the register based
- * interrupt acknowledgements. See page 99-101 of V2.0 of the CD1865
- * databook */
-#define SX_ACK_MINT     0x75    /* goes to PILR1                           */
-#define SX_ACK_TINT     0x76    /* goes to PILR2                           */
-#define SX_ACK_RINT     0x77    /* goes to PILR3                           */
-
-/* Chip ID (is used when chips ar daisy chained.) */
-#define SX_ID           0x10
-
-/* Definitions for Cirrus Logic CL-CD186x 8-port async mux chip */
- 
-#define CD186x_NCH       8       /* Total number of channels                */
-#define CD186x_TPC       16      /* Ticks per character                     */
-#define CD186x_NFIFO	 8	 /* TX FIFO size                            */
-
-
-/* Global registers */
-
-#define CD186x_GIVR      0x40    /* Global Interrupt Vector Register        */
-#define CD186x_GICR      0x41    /* Global Interrupting Channel Register    */
-#define CD186x_PILR1     0x61    /* Priority Interrupt Level Register 1     */
-#define CD186x_PILR2     0x62    /* Priority Interrupt Level Register 2     */
-#define CD186x_PILR3     0x63    /* Priority Interrupt Level Register 3     */
-#define CD186x_CAR       0x64    /* Channel Access Register                 */
-#define CD186x_SRSR      0x65    /* Channel Access Register                 */
-#define CD186x_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
-#define CD186x_PPRH      0x70    /* Prescaler Period Register High          */
-#define CD186x_PPRL      0x71    /* Prescaler Period Register Low           */
-#define CD186x_RDR       0x78    /* Receiver Data Register                  */
-#define CD186x_RCSR      0x7a    /* Receiver Character Status Register      */
-#define CD186x_TDR       0x7b    /* Transmit Data Register                  */
-#define CD186x_EOIR      0x7f    /* End of Interrupt Register               */
-#define CD186x_MRAR      0x75    /* Modem Request Acknowledge register       */
-#define CD186x_TRAR      0x76    /* Transmit Request Acknowledge register    */
-#define CD186x_RRAR      0x77    /* Receive Request Acknowledge register     */
-#define CD186x_SRCR      0x66    /* Service Request Configuration register  */
-
-/* Channel Registers */
-
-#define CD186x_CCR       0x01    /* Channel Command Register                */
-#define CD186x_IER       0x02    /* Interrupt Enable Register               */
-#define CD186x_COR1      0x03    /* Channel Option Register 1               */
-#define CD186x_COR2      0x04    /* Channel Option Register 2               */
-#define CD186x_COR3      0x05    /* Channel Option Register 3               */
-#define CD186x_CCSR      0x06    /* Channel Control Status Register         */
-#define CD186x_RDCR      0x07    /* Receive Data Count Register             */
-#define CD186x_SCHR1     0x09    /* Special Character Register 1            */
-#define CD186x_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD186x_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD186x_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD186x_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD186x_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD186x_MCR       0x12    /* Modem Change Register                   */
-#define CD186x_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD186x_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD186x_MSVRTS    0x29    /* Modem Signal Value Register             */
-#define CD186x_MSVDTR    0x2a    /* Modem Signal Value Register             */
-#define CD186x_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
-#define CD186x_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
-#define CD186x_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
-#define CD186x_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
-
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
-#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
-#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
- 
-#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GICR_CHAN_OFF   2       /* Channel Number shift                    */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Interrupt Enable Register (R/W) */
-
-#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define IER_CD          0x40    /* Enable interrupt on CD change           */
-#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Escape characters */
-
-#define CD186x_C_ESC     0x00    /* Escape character                        */
-#define CD186x_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD186x_C_DELAY   0x82    /* Delay output                            */
-#define CD186x_C_EBRK    0x83    /* Stop sending BREAK                      */
-
-#define SRSR_RREQint     0x10    /* This chip wants "rec" serviced          */
-#define SRSR_TREQint     0x04    /* This chip wants "transmit" serviced     */
-#define SRSR_MREQint     0x01    /* This chip wants "mdm change" serviced   */
-
-
-
-#define SRCR_PKGTYPE    0x80
-#define SRCR_REGACKEN   0x40
-#define SRCR_DAISYEN    0x20
-#define SRCR_GLOBPRI    0x10
-#define SRCR_UNFAIR     0x08
-#define SRCR_AUTOPRI    0x02
-#define SRCR_PRISEL     0x01
-
-
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
deleted file mode 100644
index 4f152c2..0000000
--- a/drivers/char/cyclades.c
+++ /dev/null
@@ -1,4200 +0,0 @@
-#undef	BLOCKMOVE
-#define	Z_WAKE
-#undef	Z_EXT_CHARS_IN_BUFFER
-
-/*
- *  linux/drivers/char/cyclades.c
- *
- * This file contains the driver for the Cyclades async multiport
- * serial boards.
- *
- * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
- * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
- *
- * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com>
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- * Converted to pci probing and cleaned up by Jiri Slaby.
- *
- */
-
-#define CY_VERSION	"2.6"
-
-/* If you need to install more boards than NR_CARDS, change the constant
-   in the definition below. No other change is necessary to support up to
-   eight boards. Beyond that you'll have to extend cy_isa_addresses. */
-
-#define NR_CARDS	4
-
-/*
-   If the total number of ports is larger than NR_PORTS, change this
-   constant in the definition below. No other change is necessary to
-   support more boards/ports. */
-
-#define NR_PORTS	256
-
-#define ZO_V1	0
-#define ZO_V2	1
-#define ZE_V1	2
-
-#define	SERIAL_PARANOIA_CHECK
-#undef	CY_DEBUG_OPEN
-#undef	CY_DEBUG_THROTTLE
-#undef	CY_DEBUG_OTHER
-#undef	CY_DEBUG_IO
-#undef	CY_DEBUG_COUNT
-#undef	CY_DEBUG_DTR
-#undef	CY_DEBUG_WAIT_UNTIL_SENT
-#undef	CY_DEBUG_INTERRUPTS
-#undef	CY_16Y_HACK
-#undef	CY_ENABLE_MONITORING
-#undef	CY_PCI_DEBUG
-
-/*
- * Include section
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/cyclades.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/bitops.h>
-#include <linux/firmware.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static void cy_send_xchar(struct tty_struct *tty, char ch);
-
-#ifndef SERIAL_XMIT_SIZE
-#define	SERIAL_XMIT_SIZE	(min(PAGE_SIZE, 4096))
-#endif
-
-#define STD_COM_FLAGS (0)
-
-/* firmware stuff */
-#define ZL_MAX_BLOCKS	16
-#define DRIVER_VERSION	0x02010203
-#define RAM_SIZE 0x80000
-
-enum zblock_type {
-	ZBLOCK_PRG = 0,
-	ZBLOCK_FPGA = 1
-};
-
-struct zfile_header {
-	char name[64];
-	char date[32];
-	char aux[32];
-	u32 n_config;
-	u32 config_offset;
-	u32 n_blocks;
-	u32 block_offset;
-	u32 reserved[9];
-} __attribute__ ((packed));
-
-struct zfile_config {
-	char name[64];
-	u32 mailbox;
-	u32 function;
-	u32 n_blocks;
-	u32 block_list[ZL_MAX_BLOCKS];
-} __attribute__ ((packed));
-
-struct zfile_block {
-	u32 type;
-	u32 file_offset;
-	u32 ram_offset;
-	u32 size;
-} __attribute__ ((packed));
-
-static struct tty_driver *cy_serial_driver;
-
-#ifdef CONFIG_ISA
-/* This is the address lookup table. The driver will probe for
-   Cyclom-Y/ISA boards at all addresses in here. If you want the
-   driver to probe addresses at a different address, add it to
-   this table.  If the driver is probing some other board and
-   causing problems, remove the offending address from this table.
-*/
-
-static unsigned int cy_isa_addresses[] = {
-	0xD0000,
-	0xD2000,
-	0xD4000,
-	0xD6000,
-	0xD8000,
-	0xDA000,
-	0xDC000,
-	0xDE000,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
-
-static long maddr[NR_CARDS];
-static int irq[NR_CARDS];
-
-module_param_array(maddr, long, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-
-#endif				/* CONFIG_ISA */
-
-/* This is the per-card data structure containing address, irq, number of
-   channels, etc. This driver supports a maximum of NR_CARDS cards.
-*/
-static struct cyclades_card cy_card[NR_CARDS];
-
-static int cy_next_channel;	/* next minor available */
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates.  The extra
- * are accessed via settings in info->port.flags.
- *      0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
- *     10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
- *                                               HI            VHI
- *     20
- */
-static const int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
-	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
-	230400, 0
-};
-
-static const char baud_co_25[] = {	/* 25 MHz clock option table */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
-	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const char baud_bpr_25[] = {	/* 25 MHz baud rate period table */
-	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
-	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-
-static const char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
-	0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00
-};
-
-static const char baud_bpr_60[] = {	/* 60 MHz baud rate period table (CD1400 J) */
-	0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
-	0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
-	0x21
-};
-
-static const char baud_cor3[] = {	/* receive threshold */
-	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
-	0x07
-};
-
-/*
- * The Cyclades driver implements HW flow control as any serial driver.
- * The cyclades_port structure member rflow and the vector rflow_thr
- * allows us to take advantage of a special feature in the CD1400 to avoid
- * data loss even when the system interrupt latency is too high. These flags
- * are to be used only with very special applications. Setting these flags
- * requires the use of a special cable (DTR and RTS reversed). In the new
- * CD1400-based boards (rev. 6.00 or later), there is no need for special
- * cables.
- */
-
-static const char rflow_thr[] = {	/* rflow threshold */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a
-};
-
-/*  The Cyclom-Ye has placed the sequential chips in non-sequential
- *  address order.  This look-up table overcomes that problem.
- */
-static const unsigned int cy_chip_offset[] = { 0x0000,
-	0x0400,
-	0x0800,
-	0x0C00,
-	0x0200,
-	0x0600,
-	0x0A00,
-	0x0E00
-};
-
-/* PCI related definitions */
-
-#ifdef CONFIG_PCI
-static const struct pci_device_id cy_pci_dev_id[] = {
-	/* PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
-	/* PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
-	/* 4Y PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
-	/* 4Y PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
-	/* 8Y PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
-	/* 8Y PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
-	/* Z PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
-	/* Z PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
-	{ }			/* end of table */
-};
-MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
-#endif
-
-static void cy_start(struct tty_struct *);
-static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
-static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
-#ifdef CONFIG_ISA
-static unsigned detect_isa_irq(void __iomem *);
-#endif				/* CONFIG_ISA */
-
-#ifndef CONFIG_CYZ_INTR
-static void cyz_poll(unsigned long);
-
-/* The Cyclades-Z polling cycle is defined by this variable */
-static long cyz_polling_cycle = CZ_DEF_POLL;
-
-static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
-
-#else				/* CONFIG_CYZ_INTR */
-static void cyz_rx_restart(unsigned long);
-static struct timer_list cyz_rx_full_timer[NR_PORTS];
-#endif				/* CONFIG_CYZ_INTR */
-
-static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
-{
-	struct cyclades_card *card = port->card;
-
-	cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
-}
-
-static inline u8 cyy_readb(struct cyclades_port *port, u32 reg)
-{
-	struct cyclades_card *card = port->card;
-
-	return readb(port->u.cyy.base_addr + (reg << card->bus_index));
-}
-
-static inline bool cy_is_Z(struct cyclades_card *card)
-{
-	return card->num_chips == (unsigned int)-1;
-}
-
-static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
-{
-	return readl(&ctl_addr->init_ctrl) & (1 << 17);
-}
-
-static inline bool cyz_fpga_loaded(struct cyclades_card *card)
-{
-	return __cyz_fpga_loaded(card->ctl_addr.p9060);
-}
-
-static inline bool cyz_is_loaded(struct cyclades_card *card)
-{
-	struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
-
-	return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
-			readl(&fw_id->signature) == ZFIRM_ID;
-}
-
-static inline int serial_paranoia_check(struct cyclades_port *info,
-		const char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	if (!info) {
-		printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
-				"in %s\n", name, routine);
-		return 1;
-	}
-
-	if (info->magic != CYCLADES_MAGIC) {
-		printk(KERN_WARNING "cyc Warning: bad magic number for serial "
-				"struct (%s) in %s\n", name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/***********************************************************/
-/********* Start of block of Cyclom-Y specific code ********/
-
-/* This routine waits up to 1000 micro-seconds for the previous
-   command to the Cirrus chip to complete and then issues the
-   new command.  An error is returned if the previous command
-   didn't finish within the time limit.
-
-   This function is only called from inside spinlock-protected code.
- */
-static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index)
-{
-	void __iomem *ccr = base_addr + (CyCCR << index);
-	unsigned int i;
-
-	/* Check to see that the previous command has completed */
-	for (i = 0; i < 100; i++) {
-		if (readb(ccr) == 0)
-			break;
-		udelay(10L);
-	}
-	/* if the CCR never cleared, the previous command
-	   didn't finish within the "reasonable time" */
-	if (i == 100)
-		return -1;
-
-	/* Issue the new command */
-	cy_writeb(ccr, cmd);
-
-	return 0;
-}
-
-static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd)
-{
-	return __cyy_issue_cmd(port->u.cyy.base_addr, cmd,
-			port->card->bus_index);
-}
-
-#ifdef CONFIG_ISA
-/* ISA interrupt detection code */
-static unsigned detect_isa_irq(void __iomem *address)
-{
-	int irq;
-	unsigned long irqs, flags;
-	int save_xir, save_car;
-	int index = 0;		/* IRQ probing is only for ISA */
-
-	/* forget possible initially masked and pending IRQ */
-	irq = probe_irq_off(probe_irq_on());
-
-	/* Clear interrupts on the board first */
-	cy_writeb(address + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-
-	irqs = probe_irq_on();
-	/* Wait ... */
-	msleep(5);
-
-	/* Enable the Tx interrupts on the CD1400 */
-	local_irq_save(flags);
-	cy_writeb(address + (CyCAR << index), 0);
-	__cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
-
-	cy_writeb(address + (CyCAR << index), 0);
-	cy_writeb(address + (CySRER << index),
-		  readb(address + (CySRER << index)) | CyTxRdy);
-	local_irq_restore(flags);
-
-	/* Wait ... */
-	msleep(5);
-
-	/* Check which interrupt is in use */
-	irq = probe_irq_off(irqs);
-
-	/* Clean up */
-	save_xir = (u_char) readb(address + (CyTIR << index));
-	save_car = readb(address + (CyCAR << index));
-	cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
-	cy_writeb(address + (CySRER << index),
-		  readb(address + (CySRER << index)) & ~CyTxRdy);
-	cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
-	cy_writeb(address + (CyCAR << index), (save_car));
-	cy_writeb(address + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-
-	return (irq > 0) ? irq : 0;
-}
-#endif				/* CONFIG_ISA */
-
-static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
-		void __iomem *base_addr)
-{
-	struct cyclades_port *info;
-	struct tty_struct *tty;
-	int len, index = cinfo->bus_index;
-	u8 ivr, save_xir, channel, save_car, data, char_count;
-
-#ifdef CY_DEBUG_INTERRUPTS
-	printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
-#endif
-	/* determine the channel & change to that context */
-	save_xir = readb(base_addr + (CyRIR << index));
-	channel = save_xir & CyIRChannel;
-	info = &cinfo->ports[channel + chip * 4];
-	save_car = cyy_readb(info, CyCAR);
-	cyy_writeb(info, CyCAR, save_xir);
-	ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
-
-	tty = tty_port_tty_get(&info->port);
-	/* if there is nowhere to put the data, discard it */
-	if (tty == NULL) {
-		if (ivr == CyIVRRxEx) {	/* exception */
-			data = cyy_readb(info, CyRDSR);
-		} else {	/* normal character reception */
-			char_count = cyy_readb(info, CyRDCR);
-			while (char_count--)
-				data = cyy_readb(info, CyRDSR);
-		}
-		goto end;
-	}
-	/* there is an open port for this data */
-	if (ivr == CyIVRRxEx) {	/* exception */
-		data = cyy_readb(info, CyRDSR);
-
-		/* For statistics only */
-		if (data & CyBREAK)
-			info->icount.brk++;
-		else if (data & CyFRAME)
-			info->icount.frame++;
-		else if (data & CyPARITY)
-			info->icount.parity++;
-		else if (data & CyOVERRUN)
-			info->icount.overrun++;
-
-		if (data & info->ignore_status_mask) {
-			info->icount.rx++;
-			tty_kref_put(tty);
-			return;
-		}
-		if (tty_buffer_request_room(tty, 1)) {
-			if (data & info->read_status_mask) {
-				if (data & CyBREAK) {
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_BREAK);
-					info->icount.rx++;
-					if (info->port.flags & ASYNC_SAK)
-						do_SAK(tty);
-				} else if (data & CyFRAME) {
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_FRAME);
-					info->icount.rx++;
-					info->idle_stats.frame_errs++;
-				} else if (data & CyPARITY) {
-					/* Pieces of seven... */
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_PARITY);
-					info->icount.rx++;
-					info->idle_stats.parity_errs++;
-				} else if (data & CyOVERRUN) {
-					tty_insert_flip_char(tty, 0,
-							TTY_OVERRUN);
-					info->icount.rx++;
-					/* If the flip buffer itself is
-					   overflowing, we still lose
-					   the next incoming character.
-					 */
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_FRAME);
-					info->icount.rx++;
-					info->idle_stats.overruns++;
-				/* These two conditions may imply */
-				/* a normal read should be done. */
-				/* } else if(data & CyTIMEOUT) { */
-				/* } else if(data & CySPECHAR) { */
-				} else {
-					tty_insert_flip_char(tty, 0,
-							TTY_NORMAL);
-					info->icount.rx++;
-				}
-			} else {
-				tty_insert_flip_char(tty, 0, TTY_NORMAL);
-				info->icount.rx++;
-			}
-		} else {
-			/* there was a software buffer overrun and nothing
-			 * could be done about it!!! */
-			info->icount.buf_overrun++;
-			info->idle_stats.overruns++;
-		}
-	} else {	/* normal character reception */
-		/* load # chars available from the chip */
-		char_count = cyy_readb(info, CyRDCR);
-
-#ifdef CY_ENABLE_MONITORING
-		++info->mon.int_count;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		len = tty_buffer_request_room(tty, char_count);
-		while (len--) {
-			data = cyy_readb(info, CyRDSR);
-			tty_insert_flip_char(tty, data, TTY_NORMAL);
-			info->idle_stats.recv_bytes++;
-			info->icount.rx++;
-#ifdef CY_16Y_HACK
-			udelay(10L);
-#endif
-		}
-		info->idle_stats.recv_idle = jiffies;
-	}
-	tty_schedule_flip(tty);
-	tty_kref_put(tty);
-end:
-	/* end of service */
-	cyy_writeb(info, CyRIR, save_xir & 0x3f);
-	cyy_writeb(info, CyCAR, save_car);
-}
-
-static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
-		void __iomem *base_addr)
-{
-	struct cyclades_port *info;
-	struct tty_struct *tty;
-	int char_count, index = cinfo->bus_index;
-	u8 save_xir, channel, save_car, outch;
-
-	/* Since we only get here when the transmit buffer
-	   is empty, we know we can always stuff a dozen
-	   characters. */
-#ifdef CY_DEBUG_INTERRUPTS
-	printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
-#endif
-
-	/* determine the channel & change to that context */
-	save_xir = readb(base_addr + (CyTIR << index));
-	channel = save_xir & CyIRChannel;
-	save_car = readb(base_addr + (CyCAR << index));
-	cy_writeb(base_addr + (CyCAR << index), save_xir);
-
-	info = &cinfo->ports[channel + chip * 4];
-	tty = tty_port_tty_get(&info->port);
-	if (tty == NULL) {
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
-		goto end;
-	}
-
-	/* load the on-chip space for outbound data */
-	char_count = info->xmit_fifo_size;
-
-	if (info->x_char) {	/* send special char */
-		outch = info->x_char;
-		cyy_writeb(info, CyTDR, outch);
-		char_count--;
-		info->icount.tx++;
-		info->x_char = 0;
-	}
-
-	if (info->breakon || info->breakoff) {
-		if (info->breakon) {
-			cyy_writeb(info, CyTDR, 0);
-			cyy_writeb(info, CyTDR, 0x81);
-			info->breakon = 0;
-			char_count -= 2;
-		}
-		if (info->breakoff) {
-			cyy_writeb(info, CyTDR, 0);
-			cyy_writeb(info, CyTDR, 0x83);
-			info->breakoff = 0;
-			char_count -= 2;
-		}
-	}
-
-	while (char_count-- > 0) {
-		if (!info->xmit_cnt) {
-			if (cyy_readb(info, CySRER) & CyTxMpty) {
-				cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) & ~CyTxMpty);
-			} else {
-				cyy_writeb(info, CySRER, CyTxMpty |
-					(cyy_readb(info, CySRER) & ~CyTxRdy));
-			}
-			goto done;
-		}
-		if (info->port.xmit_buf == NULL) {
-			cyy_writeb(info, CySRER,
-				cyy_readb(info, CySRER) & ~CyTxRdy);
-			goto done;
-		}
-		if (tty->stopped || tty->hw_stopped) {
-			cyy_writeb(info, CySRER,
-				cyy_readb(info, CySRER) & ~CyTxRdy);
-			goto done;
-		}
-		/* Because the Embedded Transmit Commands have been enabled,
-		 * we must check to see if the escape character, NULL, is being
-		 * sent. If it is, we must ensure that there is room for it to
-		 * be doubled in the output stream.  Therefore we no longer
-		 * advance the pointer when the character is fetched, but
-		 * rather wait until after the check for a NULL output
-		 * character. This is necessary because there may not be room
-		 * for the two chars needed to send a NULL.)
-		 */
-		outch = info->port.xmit_buf[info->xmit_tail];
-		if (outch) {
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1) &
-					(SERIAL_XMIT_SIZE - 1);
-			cyy_writeb(info, CyTDR, outch);
-			info->icount.tx++;
-		} else {
-			if (char_count > 1) {
-				info->xmit_cnt--;
-				info->xmit_tail = (info->xmit_tail + 1) &
-					(SERIAL_XMIT_SIZE - 1);
-				cyy_writeb(info, CyTDR, outch);
-				cyy_writeb(info, CyTDR, 0);
-				info->icount.tx++;
-				char_count--;
-			}
-		}
-	}
-
-done:
-	tty_wakeup(tty);
-	tty_kref_put(tty);
-end:
-	/* end of service */
-	cyy_writeb(info, CyTIR, save_xir & 0x3f);
-	cyy_writeb(info, CyCAR, save_car);
-}
-
-static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
-		void __iomem *base_addr)
-{
-	struct cyclades_port *info;
-	struct tty_struct *tty;
-	int index = cinfo->bus_index;
-	u8 save_xir, channel, save_car, mdm_change, mdm_status;
-
-	/* determine the channel & change to that context */
-	save_xir = readb(base_addr + (CyMIR << index));
-	channel = save_xir & CyIRChannel;
-	info = &cinfo->ports[channel + chip * 4];
-	save_car = cyy_readb(info, CyCAR);
-	cyy_writeb(info, CyCAR, save_xir);
-
-	mdm_change = cyy_readb(info, CyMISR);
-	mdm_status = cyy_readb(info, CyMSVR1);
-
-	tty = tty_port_tty_get(&info->port);
-	if (!tty)
-		goto end;
-
-	if (mdm_change & CyANY_DELTA) {
-		/* For statistics only */
-		if (mdm_change & CyDCD)
-			info->icount.dcd++;
-		if (mdm_change & CyCTS)
-			info->icount.cts++;
-		if (mdm_change & CyDSR)
-			info->icount.dsr++;
-		if (mdm_change & CyRI)
-			info->icount.rng++;
-
-		wake_up_interruptible(&info->port.delta_msr_wait);
-	}
-
-	if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
-		if (mdm_status & CyDCD)
-			wake_up_interruptible(&info->port.open_wait);
-		else
-			tty_hangup(tty);
-	}
-	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
-		if (tty->hw_stopped) {
-			if (mdm_status & CyCTS) {
-				/* cy_start isn't used
-				   because... !!! */
-				tty->hw_stopped = 0;
-				cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) | CyTxRdy);
-				tty_wakeup(tty);
-			}
-		} else {
-			if (!(mdm_status & CyCTS)) {
-				/* cy_stop isn't used
-				   because ... !!! */
-				tty->hw_stopped = 1;
-				cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) & ~CyTxRdy);
-			}
-		}
-	}
-/*	if (mdm_change & CyDSR) {
-	}
-	if (mdm_change & CyRI) {
-	}*/
-	tty_kref_put(tty);
-end:
-	/* end of service */
-	cyy_writeb(info, CyMIR, save_xir & 0x3f);
-	cyy_writeb(info, CyCAR, save_car);
-}
-
-/* The real interrupt service routine is called
-   whenever the card wants its hand held--chars
-   received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cyy_interrupt(int irq, void *dev_id)
-{
-	int status;
-	struct cyclades_card *cinfo = dev_id;
-	void __iomem *base_addr, *card_base_addr;
-	unsigned int chip, too_many, had_work;
-	int index;
-
-	if (unlikely(cinfo == NULL)) {
-#ifdef CY_DEBUG_INTERRUPTS
-		printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
-				irq);
-#endif
-		return IRQ_NONE;	/* spurious interrupt */
-	}
-
-	card_base_addr = cinfo->base_addr;
-	index = cinfo->bus_index;
-
-	/* card was not initialized yet (e.g. DEBUG_SHIRQ) */
-	if (unlikely(card_base_addr == NULL))
-		return IRQ_HANDLED;
-
-	/* This loop checks all chips in the card.  Make a note whenever
-	   _any_ chip had some work to do, as this is considered an
-	   indication that there will be more to do.  Only when no chip
-	   has any work does this outermost loop exit.
-	 */
-	do {
-		had_work = 0;
-		for (chip = 0; chip < cinfo->num_chips; chip++) {
-			base_addr = cinfo->base_addr +
-					(cy_chip_offset[chip] << index);
-			too_many = 0;
-			while ((status = readb(base_addr +
-						(CySVRR << index))) != 0x00) {
-				had_work++;
-			/* The purpose of the following test is to ensure that
-			   no chip can monopolize the driver.  This forces the
-			   chips to be checked in a round-robin fashion (after
-			   draining each of a bunch (1000) of characters).
-			 */
-				if (1000 < too_many++)
-					break;
-				spin_lock(&cinfo->card_lock);
-				if (status & CySRReceive) /* rx intr */
-					cyy_chip_rx(cinfo, chip, base_addr);
-				if (status & CySRTransmit) /* tx intr */
-					cyy_chip_tx(cinfo, chip, base_addr);
-				if (status & CySRModem) /* modem intr */
-					cyy_chip_modem(cinfo, chip, base_addr);
-				spin_unlock(&cinfo->card_lock);
-			}
-		}
-	} while (had_work);
-
-	/* clear interrupts */
-	spin_lock(&cinfo->card_lock);
-	cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-	spin_unlock(&cinfo->card_lock);
-	return IRQ_HANDLED;
-}				/* cyy_interrupt */
-
-static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
-		unsigned int clear)
-{
-	struct cyclades_card *card = info->card;
-	int channel = info->line - card->first_line;
-	u32 rts, dtr, msvrr, msvrd;
-
-	channel &= 0x03;
-
-	if (info->rtsdtr_inv) {
-		msvrr = CyMSVR2;
-		msvrd = CyMSVR1;
-		rts = CyDTR;
-		dtr = CyRTS;
-	} else {
-		msvrr = CyMSVR1;
-		msvrd = CyMSVR2;
-		rts = CyRTS;
-		dtr = CyDTR;
-	}
-	if (set & TIOCM_RTS) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrr, rts);
-	}
-	if (clear & TIOCM_RTS) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrr, ~rts);
-	}
-	if (set & TIOCM_DTR) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrd, dtr);
-#ifdef CY_DEBUG_DTR
-		printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
-		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			cyy_readb(info, CyMSVR1),
-			cyy_readb(info, CyMSVR2));
-#endif
-	}
-	if (clear & TIOCM_DTR) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrd, ~dtr);
-#ifdef CY_DEBUG_DTR
-		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
-		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			cyy_readb(info, CyMSVR1),
-			cyy_readb(info, CyMSVR2));
-#endif
-	}
-}
-
-/***********************************************************/
-/********* End of block of Cyclom-Y specific code **********/
-/******** Start of block of Cyclades-Z specific code *******/
-/***********************************************************/
-
-static int
-cyz_fetch_msg(struct cyclades_card *cinfo,
-		__u32 *channel, __u8 *cmd, __u32 *param)
-{
-	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
-	unsigned long loc_doorbell;
-
-	loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
-	if (loc_doorbell) {
-		*cmd = (char)(0xff & loc_doorbell);
-		*channel = readl(&board_ctrl->fwcmd_channel);
-		*param = (__u32) readl(&board_ctrl->fwcmd_param);
-		cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
-		return 1;
-	}
-	return 0;
-}				/* cyz_fetch_msg */
-
-static int
-cyz_issue_cmd(struct cyclades_card *cinfo,
-		__u32 channel, __u8 cmd, __u32 param)
-{
-	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
-	__u32 __iomem *pci_doorbell;
-	unsigned int index;
-
-	if (!cyz_is_loaded(cinfo))
-		return -1;
-
-	index = 0;
-	pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
-	while ((readl(pci_doorbell) & 0xff) != 0) {
-		if (index++ == 1000)
-			return (int)(readl(pci_doorbell) & 0xff);
-		udelay(50L);
-	}
-	cy_writel(&board_ctrl->hcmd_channel, channel);
-	cy_writel(&board_ctrl->hcmd_param, param);
-	cy_writel(pci_doorbell, (long)cmd);
-
-	return 0;
-}				/* cyz_issue_cmd */
-
-static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
-	struct cyclades_card *cinfo = info->card;
-	unsigned int char_count;
-	int len;
-#ifdef BLOCKMOVE
-	unsigned char *buf;
-#else
-	char data;
-#endif
-	__u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
-
-	rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
-	rx_put = readl(&buf_ctrl->rx_put);
-	rx_bufsize = readl(&buf_ctrl->rx_bufsize);
-	rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
-	if (rx_put >= rx_get)
-		char_count = rx_put - rx_get;
-	else
-		char_count = rx_put - rx_get + rx_bufsize;
-
-	if (char_count) {
-#ifdef CY_ENABLE_MONITORING
-		info->mon.int_count++;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		if (tty == NULL) {
-			/* flush received characters */
-			new_rx_get = (new_rx_get + char_count) &
-					(rx_bufsize - 1);
-			info->rflush_count++;
-		} else {
-#ifdef BLOCKMOVE
-		/* we'd like to use memcpy(t, f, n) and memset(s, c, count)
-		   for performance, but because of buffer boundaries, there
-		   may be several steps to the operation */
-			while (1) {
-				len = tty_prepare_flip_string(tty, &buf,
-						char_count);
-				if (!len)
-					break;
-
-				len = min_t(unsigned int, min(len, char_count),
-						rx_bufsize - new_rx_get);
-
-				memcpy_fromio(buf, cinfo->base_addr +
-						rx_bufaddr + new_rx_get, len);
-
-				new_rx_get = (new_rx_get + len) &
-						(rx_bufsize - 1);
-				char_count -= len;
-				info->icount.rx += len;
-				info->idle_stats.recv_bytes += len;
-			}
-#else
-			len = tty_buffer_request_room(tty, char_count);
-			while (len--) {
-				data = readb(cinfo->base_addr + rx_bufaddr +
-						new_rx_get);
-				new_rx_get = (new_rx_get + 1) &
-							(rx_bufsize - 1);
-				tty_insert_flip_char(tty, data, TTY_NORMAL);
-				info->idle_stats.recv_bytes++;
-				info->icount.rx++;
-			}
-#endif
-#ifdef CONFIG_CYZ_INTR
-		/* Recalculate the number of chars in the RX buffer and issue
-		   a cmd in case it's higher than the RX high water mark */
-			rx_put = readl(&buf_ctrl->rx_put);
-			if (rx_put >= rx_get)
-				char_count = rx_put - rx_get;
-			else
-				char_count = rx_put - rx_get + rx_bufsize;
-			if (char_count >= readl(&buf_ctrl->rx_threshold) &&
-					!timer_pending(&cyz_rx_full_timer[
-							info->line]))
-				mod_timer(&cyz_rx_full_timer[info->line],
-						jiffies + 1);
-#endif
-			info->idle_stats.recv_idle = jiffies;
-			tty_schedule_flip(tty);
-		}
-		/* Update rx_get */
-		cy_writel(&buf_ctrl->rx_get, new_rx_get);
-	}
-}
-
-static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
-	struct cyclades_card *cinfo = info->card;
-	u8 data;
-	unsigned int char_count;
-#ifdef BLOCKMOVE
-	int small_count;
-#endif
-	__u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
-
-	if (info->xmit_cnt <= 0)	/* Nothing to transmit */
-		return;
-
-	tx_get = readl(&buf_ctrl->tx_get);
-	tx_put = readl(&buf_ctrl->tx_put);
-	tx_bufsize = readl(&buf_ctrl->tx_bufsize);
-	tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
-	if (tx_put >= tx_get)
-		char_count = tx_get - tx_put - 1 + tx_bufsize;
-	else
-		char_count = tx_get - tx_put - 1;
-
-	if (char_count) {
-
-		if (tty == NULL)
-			goto ztxdone;
-
-		if (info->x_char) {	/* send special char */
-			data = info->x_char;
-
-			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
-			tx_put = (tx_put + 1) & (tx_bufsize - 1);
-			info->x_char = 0;
-			char_count--;
-			info->icount.tx++;
-		}
-#ifdef BLOCKMOVE
-		while (0 < (small_count = min_t(unsigned int,
-				tx_bufsize - tx_put, min_t(unsigned int,
-					(SERIAL_XMIT_SIZE - info->xmit_tail),
-					min_t(unsigned int, info->xmit_cnt,
-						char_count))))) {
-
-			memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
-					tx_put),
-					&info->port.xmit_buf[info->xmit_tail],
-					small_count);
-
-			tx_put = (tx_put + small_count) & (tx_bufsize - 1);
-			char_count -= small_count;
-			info->icount.tx += small_count;
-			info->xmit_cnt -= small_count;
-			info->xmit_tail = (info->xmit_tail + small_count) &
-					(SERIAL_XMIT_SIZE - 1);
-		}
-#else
-		while (info->xmit_cnt && char_count) {
-			data = info->port.xmit_buf[info->xmit_tail];
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1) &
-					(SERIAL_XMIT_SIZE - 1);
-
-			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
-			tx_put = (tx_put + 1) & (tx_bufsize - 1);
-			char_count--;
-			info->icount.tx++;
-		}
-#endif
-		tty_wakeup(tty);
-ztxdone:
-		/* Update tx_put */
-		cy_writel(&buf_ctrl->tx_put, tx_put);
-	}
-}
-
-static void cyz_handle_cmd(struct cyclades_card *cinfo)
-{
-	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	__u32 channel, param, fw_ver;
-	__u8 cmd;
-	int special_count;
-	int delta_count;
-
-	fw_ver = readl(&board_ctrl->fw_version);
-
-	while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
-		special_count = 0;
-		delta_count = 0;
-		info = &cinfo->ports[channel];
-		tty = tty_port_tty_get(&info->port);
-		if (tty == NULL)
-			continue;
-
-		switch (cmd) {
-		case C_CM_PR_ERROR:
-			tty_insert_flip_char(tty, 0, TTY_PARITY);
-			info->icount.rx++;
-			special_count++;
-			break;
-		case C_CM_FR_ERROR:
-			tty_insert_flip_char(tty, 0, TTY_FRAME);
-			info->icount.rx++;
-			special_count++;
-			break;
-		case C_CM_RXBRK:
-			tty_insert_flip_char(tty, 0, TTY_BREAK);
-			info->icount.rx++;
-			special_count++;
-			break;
-		case C_CM_MDCD:
-			info->icount.dcd++;
-			delta_count++;
-			if (info->port.flags & ASYNC_CHECK_CD) {
-				u32 dcd = fw_ver > 241 ? param :
-					readl(&info->u.cyz.ch_ctrl->rs_status);
-				if (dcd & C_RS_DCD)
-					wake_up_interruptible(&info->port.open_wait);
-				else
-					tty_hangup(tty);
-			}
-			break;
-		case C_CM_MCTS:
-			info->icount.cts++;
-			delta_count++;
-			break;
-		case C_CM_MRI:
-			info->icount.rng++;
-			delta_count++;
-			break;
-		case C_CM_MDSR:
-			info->icount.dsr++;
-			delta_count++;
-			break;
-#ifdef Z_WAKE
-		case C_CM_IOCTLW:
-			complete(&info->shutdown_wait);
-			break;
-#endif
-#ifdef CONFIG_CYZ_INTR
-		case C_CM_RXHIWM:
-		case C_CM_RXNNDT:
-		case C_CM_INTBACK2:
-			/* Reception Interrupt */
-#ifdef CY_DEBUG_INTERRUPTS
-			printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
-					"port %ld\n", info->card, channel);
-#endif
-			cyz_handle_rx(info, tty);
-			break;
-		case C_CM_TXBEMPTY:
-		case C_CM_TXLOWWM:
-		case C_CM_INTBACK:
-			/* Transmission Interrupt */
-#ifdef CY_DEBUG_INTERRUPTS
-			printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
-					"port %ld\n", info->card, channel);
-#endif
-			cyz_handle_tx(info, tty);
-			break;
-#endif				/* CONFIG_CYZ_INTR */
-		case C_CM_FATAL:
-			/* should do something with this !!! */
-			break;
-		default:
-			break;
-		}
-		if (delta_count)
-			wake_up_interruptible(&info->port.delta_msr_wait);
-		if (special_count)
-			tty_schedule_flip(tty);
-		tty_kref_put(tty);
-	}
-}
-
-#ifdef CONFIG_CYZ_INTR
-static irqreturn_t cyz_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_card *cinfo = dev_id;
-
-	if (unlikely(!cyz_is_loaded(cinfo))) {
-#ifdef CY_DEBUG_INTERRUPTS
-		printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
-				"(IRQ%d).\n", irq);
-#endif
-		return IRQ_NONE;
-	}
-
-	/* Handle the interrupts */
-	cyz_handle_cmd(cinfo);
-
-	return IRQ_HANDLED;
-}				/* cyz_interrupt */
-
-static void cyz_rx_restart(unsigned long arg)
-{
-	struct cyclades_port *info = (struct cyclades_port *)arg;
-	struct cyclades_card *card = info->card;
-	int retval;
-	__u32 channel = info->line - card->first_line;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
-	if (retval != 0) {
-		printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
-			info->line, retval);
-	}
-	spin_unlock_irqrestore(&card->card_lock, flags);
-}
-
-#else				/* CONFIG_CYZ_INTR */
-
-static void cyz_poll(unsigned long arg)
-{
-	struct cyclades_card *cinfo;
-	struct cyclades_port *info;
-	unsigned long expires = jiffies + HZ;
-	unsigned int port, card;
-
-	for (card = 0; card < NR_CARDS; card++) {
-		cinfo = &cy_card[card];
-
-		if (!cy_is_Z(cinfo))
-			continue;
-		if (!cyz_is_loaded(cinfo))
-			continue;
-
-	/* Skip first polling cycle to avoid racing conditions with the FW */
-		if (!cinfo->intr_enabled) {
-			cinfo->intr_enabled = 1;
-			continue;
-		}
-
-		cyz_handle_cmd(cinfo);
-
-		for (port = 0; port < cinfo->nports; port++) {
-			struct tty_struct *tty;
-
-			info = &cinfo->ports[port];
-			tty = tty_port_tty_get(&info->port);
-			/* OK to pass NULL to the handle functions below.
-			   They need to drop the data in that case. */
-
-			if (!info->throttle)
-				cyz_handle_rx(info, tty);
-			cyz_handle_tx(info, tty);
-			tty_kref_put(tty);
-		}
-		/* poll every 'cyz_polling_cycle' period */
-		expires = jiffies + cyz_polling_cycle;
-	}
-	mod_timer(&cyz_timerlist, expires);
-}				/* cyz_poll */
-
-#endif				/* CONFIG_CYZ_INTR */
-
-/********** End of block of Cyclades-Z specific code *********/
-/***********************************************************/
-
-/* This is called whenever a port becomes active;
-   interrupts are enabled and DTR & RTS are turned on.
- */
-static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct cyclades_card *card;
-	unsigned long flags;
-	int retval = 0;
-	int channel;
-	unsigned long page;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	page = get_zeroed_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		goto errout;
-
-	if (!info->type) {
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		goto errout;
-	}
-
-	if (info->port.xmit_buf)
-		free_page(page);
-	else
-		info->port.xmit_buf = (unsigned char *)page;
-
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	cy_set_line_char(info, tty);
-
-	if (!cy_is_Z(card)) {
-		channel &= 0x03;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		cyy_writeb(info, CyCAR, channel);
-
-		cyy_writeb(info, CyRTPR,
-			(info->default_timeout ? info->default_timeout : 0x02));
-		/* 10ms rx timeout */
-
-		cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR);
-
-		cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
-
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData);
-	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-
-		if (!cyz_is_loaded(card))
-			return -ENODEV;
-
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
-			"base_addr %p\n", card, channel, card->base_addr);
-#endif
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE);
-#ifdef Z_WAKE
-#ifdef CONFIG_CYZ_INTR
-		cy_writel(&ch_ctrl->intr_enable,
-			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
-			  C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
-#else
-		cy_writel(&ch_ctrl->intr_enable,
-			  C_IN_IOCTLW | C_IN_MDCD);
-#endif				/* CONFIG_CYZ_INTR */
-#else
-#ifdef CONFIG_CYZ_INTR
-		cy_writel(&ch_ctrl->intr_enable,
-			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
-			  C_IN_RXNNDT | C_IN_MDCD);
-#else
-		cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD);
-#endif				/* CONFIG_CYZ_INTR */
-#endif				/* Z_WAKE */
-
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-
-		/* Flush RX buffers before raising DTR and RTS */
-		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-
-		/* set timeout !!! */
-		/* set RTS and DTR !!! */
-		tty_port_raise_dtr_rts(&info->port);
-
-		/* enable send, recv, modem !!! */
-	}
-
-	info->port.flags |= ASYNC_INITIALIZED;
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	info->breakon = info->breakoff = 0;
-	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-	info->idle_stats.in_use =
-	info->idle_stats.recv_idle =
-	info->idle_stats.xmit_idle = jiffies;
-
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc startup done\n");
-#endif
-	return 0;
-
-errout:
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	free_page(page);
-	return retval;
-}				/* startup */
-
-static void start_xmit(struct cyclades_port *info)
-{
-	struct cyclades_card *card = info->card;
-	unsigned long flags;
-	int channel = info->line - card->first_line;
-
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	} else {
-#ifdef CONFIG_CYZ_INTR
-		int retval;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-		spin_unlock_irqrestore(&card->card_lock, flags);
-#else				/* CONFIG_CYZ_INTR */
-		/* Don't have to do anything at this time */
-#endif				/* CONFIG_CYZ_INTR */
-	}
-}				/* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct cyclades_card *card;
-	unsigned long flags;
-	int channel;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		/* Clear delta_msr_wait queue to avoid mem leaks. */
-		wake_up_interruptible(&info->port.delta_msr_wait);
-
-		if (info->port.xmit_buf) {
-			unsigned char *temp;
-			temp = info->port.xmit_buf;
-			info->port.xmit_buf = NULL;
-			free_page((unsigned long)temp);
-		}
-		if (tty->termios->c_cflag & HUPCL)
-			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
-
-		cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
-		/* it may be appropriate to clear _XMIT at
-		   some later date (after testing)!!! */
-
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		info->port.flags &= ~ASYNC_INITIALIZED;
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	} else {
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
-			"base_addr %p\n", card, channel, card->base_addr);
-#endif
-
-		if (!cyz_is_loaded(card))
-			return;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		if (info->port.xmit_buf) {
-			unsigned char *temp;
-			temp = info->port.xmit_buf;
-			info->port.xmit_buf = NULL;
-			free_page((unsigned long)temp);
-		}
-
-		if (tty->termios->c_cflag & HUPCL)
-			tty_port_lower_dtr_rts(&info->port);
-
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		info->port.flags &= ~ASYNC_INITIALIZED;
-
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc shutdown done\n");
-#endif
-}				/* shutdown */
-
-/*
- * ------------------------------------------------------------
- * cy_open() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * performs the serial-specific initialization for the tty structure.
- */
-static int cy_open(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info;
-	unsigned int i, line;
-	int retval;
-
-	line = tty->index;
-	if (tty->index < 0 || NR_PORTS <= line)
-		return -ENODEV;
-
-	for (i = 0; i < NR_CARDS; i++)
-		if (line < cy_card[i].first_line + cy_card[i].nports &&
-				line >= cy_card[i].first_line)
-			break;
-	if (i >= NR_CARDS)
-		return -ENODEV;
-	info = &cy_card[i].ports[line - cy_card[i].first_line];
-	if (info->line < 0)
-		return -ENODEV;
-
-	/* If the card's firmware hasn't been loaded,
-	   treat it as absent from the system.  This
-	   will make the user pay attention.
-	 */
-	if (cy_is_Z(info->card)) {
-		struct cyclades_card *cinfo = info->card;
-		struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
-
-		if (!cyz_is_loaded(cinfo)) {
-			if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
-					readl(&firm_id->signature) ==
-					ZFIRM_HLT) {
-				printk(KERN_ERR "cyc:Cyclades-Z Error: you "
-					"need an external power supply for "
-					"this number of ports.\nFirmware "
-					"halted.\n");
-			} else {
-				printk(KERN_ERR "cyc:Cyclades-Z firmware not "
-					"yet loaded\n");
-			}
-			return -ENODEV;
-		}
-#ifdef CONFIG_CYZ_INTR
-		else {
-		/* In case this Z board is operating in interrupt mode, its
-		   interrupts should be enabled as soon as the first open
-		   happens to one of its ports. */
-			if (!cinfo->intr_enabled) {
-				u16 intr;
-
-				/* Enable interrupts on the PLX chip */
-				intr = readw(&cinfo->ctl_addr.p9060->
-						intr_ctrl_stat) | 0x0900;
-				cy_writew(&cinfo->ctl_addr.p9060->
-						intr_ctrl_stat, intr);
-				/* Enable interrupts on the FW */
-				retval = cyz_issue_cmd(cinfo, 0,
-						C_CM_IRQ_ENBL, 0L);
-				if (retval != 0) {
-					printk(KERN_ERR "cyc:IRQ enable retval "
-						"was %x\n", retval);
-				}
-				cinfo->intr_enabled = 1;
-			}
-		}
-#endif				/* CONFIG_CYZ_INTR */
-		/* Make sure this Z port really exists in hardware */
-		if (info->line > (cinfo->first_line + cinfo->nports - 1))
-			return -ENODEV;
-	}
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
-#endif
-	tty->driver_data = info;
-	if (serial_paranoia_check(info, tty->name, "cy_open"))
-		return -ENODEV;
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
-			info->port.count);
-#endif
-	info->port.count++;
-#ifdef CY_DEBUG_COUNT
-	printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
-		current->pid, info->port.count);
-#endif
-
-	/*
-	 * If the port is the middle of closing, bail out now
-	 */
-	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(info->port.close_wait,
-				!(info->port.flags & ASYNC_CLOSING));
-		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
-	}
-
-	/*
-	 * Start up serial port
-	 */
-	retval = cy_startup(info, tty);
-	if (retval)
-		return retval;
-
-	retval = tty_port_block_til_ready(&info->port, tty, filp);
-	if (retval) {
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
-			"with %d\n", retval);
-#endif
-		return retval;
-	}
-
-	info->throttle = 0;
-	tty_port_tty_set(&info->port, tty);
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc:cy_open done\n");
-#endif
-	return 0;
-}				/* cy_open */
-
-/*
- * cy_wait_until_sent() --- wait until the transmitter is empty
- */
-static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct cyclades_card *card;
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long orig_jiffies;
-	int char_time;
-
-	if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
-		return;
-
-	if (info->xmit_fifo_size == 0)
-		return;		/* Just in case.... */
-
-	orig_jiffies = jiffies;
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 *
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
-	char_time = char_time / 5;
-	if (char_time <= 0)
-		char_time = 1;
-	if (timeout < 0)
-		timeout = 0;
-	if (timeout)
-		char_time = min(char_time, timeout);
-	/*
-	 * If the transmitter hasn't cleared in twice the approximate
-	 * amount of time to send the entire FIFO, it probably won't
-	 * ever clear.  This assumes the UART isn't doing flow
-	 * control, which is currently the case.  Hence, if it ever
-	 * takes longer than info->timeout, this is probably due to a
-	 * UART bug of some kind.  So, we clamp the timeout parameter at
-	 * 2*info->timeout.
-	 */
-	if (!timeout || timeout > 2 * info->timeout)
-		timeout = 2 * info->timeout;
-#ifdef CY_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...",
-		timeout, char_time, jiffies);
-#endif
-	card = info->card;
-	if (!cy_is_Z(card)) {
-		while (cyy_readb(info, CySRER) & CyTxRdy) {
-#ifdef CY_DEBUG_WAIT_UNTIL_SENT
-			printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies);
-#endif
-			if (msleep_interruptible(jiffies_to_msecs(char_time)))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies +
-					timeout))
-				break;
-		}
-	}
-	/* Run one more char cycle */
-	msleep_interruptible(jiffies_to_msecs(char_time * 5));
-#ifdef CY_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
-#endif
-}
-
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	int channel, retval;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-		return;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	if (cy_is_Z(card)) {	/* If it is a Z card, flush the on-board
-					   buffers as well */
-		spin_lock_irqsave(&card->card_lock, flags);
-		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-	tty_wakeup(tty);
-}				/* cy_flush_buffer */
-
-
-static void cy_do_close(struct tty_port *port)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-								port);
-	struct cyclades_card *card;
-	unsigned long flags;
-	int channel;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-	spin_lock_irqsave(&card->card_lock, flags);
-
-	if (!cy_is_Z(card)) {
-		/* Stop accepting input */
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData);
-		if (info->port.flags & ASYNC_INITIALIZED) {
-			/* Waiting for on-board buffers to be empty before
-			   closing the port */
-			spin_unlock_irqrestore(&card->card_lock, flags);
-			cy_wait_until_sent(port->tty, info->timeout);
-			spin_lock_irqsave(&card->card_lock, flags);
-		}
-	} else {
-#ifdef Z_WAKE
-		/* Waiting for on-board buffers to be empty before closing
-		   the port */
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		int retval;
-
-		if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
-			retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
-			if (retval != 0) {
-				printk(KERN_DEBUG "cyc:cy_close retval on "
-					"ttyC%d was %x\n", info->line, retval);
-			}
-			spin_unlock_irqrestore(&card->card_lock, flags);
-			wait_for_completion_interruptible(&info->shutdown_wait);
-			spin_lock_irqsave(&card->card_lock, flags);
-		}
-#endif
-	}
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	cy_shutdown(info, port->tty);
-}
-
-/*
- * This routine is called when a particular tty device is closed.
- */
-static void cy_close(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info = tty->driver_data;
-	if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
-		return;
-	tty_port_close(&info->port, tty, filp);
-}				/* cy_close */
-
-/* This routine gets called when tty_write has put something into
- * the write_queue.  The characters may come from user space or
- * kernel space.
- *
- * This routine will return the number of characters actually
- * accepted for writing.
- *
- * If the port is not already transmitting stuff, start it off by
- * enabling interrupts.  The interrupt service routine will then
- * ensure that the characters are sent.
- * If the port is already active, there is no need to kick it.
- *
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	int c, ret = 0;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write"))
-		return 0;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	while (1) {
-		c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
-		c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
-
-		if (c <= 0)
-			break;
-
-		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) &
-			(SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-	info->idle_stats.xmit_bytes += ret;
-	info->idle_stats.xmit_idle = jiffies;
-
-	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
-		start_xmit(info);
-
-	return ret;
-}				/* cy_write */
-
-/*
- * This routine is called by the kernel to write a single
- * character to the tty device.  If the kernel uses this routine,
- * it must call the flush_chars() routine (if defined) when it is
- * done stuffing characters into the driver.  If there is no room
- * in the queue, the character is ignored.
- */
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-		return 0;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
-		spin_unlock_irqrestore(&info->card->card_lock, flags);
-		return 0;
-	}
-
-	info->port.xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	info->xmit_cnt++;
-	info->idle_stats.xmit_bytes++;
-	info->idle_stats.xmit_idle = jiffies;
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-	return 1;
-}				/* cy_put_char */
-
-/*
- * This routine is called by the kernel after it has written a
- * series of characters to the tty device using put_char().
- */
-static void cy_flush_chars(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-			!info->port.xmit_buf)
-		return;
-
-	start_xmit(info);
-}				/* cy_flush_chars */
-
-/*
- * This routine returns the numbers of characters the tty driver
- * will accept for queuing to be written.  This number is subject
- * to change as output buffers get emptied, or if the output flow
- * control is activated.
- */
-static int cy_write_room(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-		return 0;
-	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}				/* cy_write_room */
-
-static int cy_chars_in_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-		return 0;
-
-#ifdef Z_EXT_CHARS_IN_BUFFER
-	if (!cy_is_Z(info->card)) {
-#endif				/* Z_EXT_CHARS_IN_BUFFER */
-#ifdef CY_DEBUG_IO
-		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
-			info->line, info->xmit_cnt);
-#endif
-		return info->xmit_cnt;
-#ifdef Z_EXT_CHARS_IN_BUFFER
-	} else {
-		struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
-		int char_count;
-		__u32 tx_put, tx_get, tx_bufsize;
-
-		tx_get = readl(&buf_ctrl->tx_get);
-		tx_put = readl(&buf_ctrl->tx_put);
-		tx_bufsize = readl(&buf_ctrl->tx_bufsize);
-		if (tx_put >= tx_get)
-			char_count = tx_put - tx_get;
-		else
-			char_count = tx_put - tx_get + tx_bufsize;
-#ifdef CY_DEBUG_IO
-		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
-			info->line, info->xmit_cnt + char_count);
-#endif
-		return info->xmit_cnt + char_count;
-	}
-#endif				/* Z_EXT_CHARS_IN_BUFFER */
-}				/* cy_chars_in_buffer */
-
-/*
- * ------------------------------------------------------------
- * cy_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
-{
-	int co, co_val, bpr;
-	__u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
-			25000000);
-
-	if (baud == 0) {
-		info->tbpr = info->tco = info->rbpr = info->rco = 0;
-		return;
-	}
-
-	/* determine which prescaler to use */
-	for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
-		if (cy_clock / co_val / baud > 63)
-			break;
-	}
-
-	bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
-	if (bpr > 255)
-		bpr = 255;
-
-	info->tbpr = info->rbpr = bpr;
-	info->tco = info->rco = co;
-}
-
-/*
- * This routine finds or computes the various line characteristics.
- * It used to be called config_setup
- */
-static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct cyclades_card *card;
-	unsigned long flags;
-	int channel;
-	unsigned cflag, iflag;
-	int baud, baud_rate = 0;
-	int i;
-
-	if (!tty->termios) /* XXX can this happen at all? */
-		return;
-
-	if (info->line == -1)
-		return;
-
-	cflag = tty->termios->c_cflag;
-	iflag = tty->termios->c_iflag;
-
-	/*
-	 * Set up the tty->alt_speed kludge
-	 */
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-		tty->alt_speed = 57600;
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-		tty->alt_speed = 115200;
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-		tty->alt_speed = 230400;
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-		tty->alt_speed = 460800;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	if (!cy_is_Z(card)) {
-		u32 cflags;
-
-		/* baud rate */
-		baud = tty_get_baud_rate(tty);
-		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			if (info->custom_divisor)
-				baud_rate = info->baud / info->custom_divisor;
-			else
-				baud_rate = info->baud;
-		} else if (baud > CD1400_MAX_SPEED) {
-			baud = CD1400_MAX_SPEED;
-		}
-		/* find the baud index */
-		for (i = 0; i < 20; i++) {
-			if (baud == baud_table[i])
-				break;
-		}
-		if (i == 20)
-			i = 19;	/* CD1400_MAX_SPEED */
-
-		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			cyy_baud_calc(info, baud_rate);
-		} else {
-			if (info->chip_rev >= CD1400_REV_J) {
-				/* It is a CD1400 rev. J or later */
-				info->tbpr = baud_bpr_60[i];	/* Tx BPR */
-				info->tco = baud_co_60[i];	/* Tx CO */
-				info->rbpr = baud_bpr_60[i];	/* Rx BPR */
-				info->rco = baud_co_60[i];	/* Rx CO */
-			} else {
-				info->tbpr = baud_bpr_25[i];	/* Tx BPR */
-				info->tco = baud_co_25[i];	/* Tx CO */
-				info->rbpr = baud_bpr_25[i];	/* Rx BPR */
-				info->rco = baud_co_25[i];	/* Rx CO */
-			}
-		}
-		if (baud_table[i] == 134) {
-			/* get it right for 134.5 baud */
-			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
-					2;
-		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud_rate) + 2;
-		} else if (baud_table[i]) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud_table[i]) + 2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-		/* By tradition (is it a standard?) a baud rate of zero
-		   implies the line should be/has been closed.  A bit
-		   later in this routine such a test is performed. */
-
-		/* byte size and parity */
-		info->cor5 = 0;
-		info->cor4 = 0;
-		/* receive threshold */
-		info->cor3 = (info->default_threshold ?
-				info->default_threshold : baud_cor3[i]);
-		info->cor2 = CyETC;
-		switch (cflag & CSIZE) {
-		case CS5:
-			info->cor1 = Cy_5_BITS;
-			break;
-		case CS6:
-			info->cor1 = Cy_6_BITS;
-			break;
-		case CS7:
-			info->cor1 = Cy_7_BITS;
-			break;
-		case CS8:
-			info->cor1 = Cy_8_BITS;
-			break;
-		}
-		if (cflag & CSTOPB)
-			info->cor1 |= Cy_2_STOP;
-
-		if (cflag & PARENB) {
-			if (cflag & PARODD)
-				info->cor1 |= CyPARITY_O;
-			else
-				info->cor1 |= CyPARITY_E;
-		} else
-			info->cor1 |= CyPARITY_NONE;
-
-		/* CTS flow control flag */
-		if (cflag & CRTSCTS) {
-			info->port.flags |= ASYNC_CTS_FLOW;
-			info->cor2 |= CyCtsAE;
-		} else {
-			info->port.flags &= ~ASYNC_CTS_FLOW;
-			info->cor2 &= ~CyCtsAE;
-		}
-		if (cflag & CLOCAL)
-			info->port.flags &= ~ASYNC_CHECK_CD;
-		else
-			info->port.flags |= ASYNC_CHECK_CD;
-
-	 /***********************************************
-	    The hardware option, CyRtsAO, presents RTS when
-	    the chip has characters to send.  Since most modems
-	    use RTS as reverse (inbound) flow control, this
-	    option is not used.  If inbound flow control is
-	    necessary, DTR can be programmed to provide the
-	    appropriate signals for use with a non-standard
-	    cable.  Contact Marcio Saito for details.
-	 ***********************************************/
-
-		channel &= 0x03;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel);
-
-		/* tx and rx baud rate */
-
-		cyy_writeb(info, CyTCOR, info->tco);
-		cyy_writeb(info, CyTBPR, info->tbpr);
-		cyy_writeb(info, CyRCOR, info->rco);
-		cyy_writeb(info, CyRBPR, info->rbpr);
-
-		/* set line characteristics  according configuration */
-
-		cyy_writeb(info, CySCHR1, START_CHAR(tty));
-		cyy_writeb(info, CySCHR2, STOP_CHAR(tty));
-		cyy_writeb(info, CyCOR1, info->cor1);
-		cyy_writeb(info, CyCOR2, info->cor2);
-		cyy_writeb(info, CyCOR3, info->cor3);
-		cyy_writeb(info, CyCOR4, info->cor4);
-		cyy_writeb(info, CyCOR5, info->cor5);
-
-		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
-				CyCOR3ch);
-
-		/* !!! Is this needed? */
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, CyRTPR,
-			(info->default_timeout ? info->default_timeout : 0x02));
-		/* 10ms rx timeout */
-
-		cflags = CyCTS;
-		if (!C_CLOCAL(tty))
-			cflags |= CyDSR | CyRI | CyDCD;
-		/* without modem intr */
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
-		/* act on 1->0 modem transitions */
-		if ((cflag & CRTSCTS) && info->rflow)
-			cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
-		else
-			cyy_writeb(info, CyMCOR1, cflags);
-		/* act on 0->1 modem transitions */
-		cyy_writeb(info, CyMCOR2, cflags);
-
-		if (i == 0)	/* baud rate is zero, turn off line */
-			cyy_change_rts_dtr(info, 0, TIOCM_DTR);
-		else
-			cyy_change_rts_dtr(info, TIOCM_DTR, 0);
-
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-
-	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		__u32 sw_flow;
-		int retval;
-
-		if (!cyz_is_loaded(card))
-			return;
-
-		/* baud rate */
-		baud = tty_get_baud_rate(tty);
-		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			if (info->custom_divisor)
-				baud_rate = info->baud / info->custom_divisor;
-			else
-				baud_rate = info->baud;
-		} else if (baud > CYZ_MAX_SPEED) {
-			baud = CYZ_MAX_SPEED;
-		}
-		cy_writel(&ch_ctrl->comm_baud, baud);
-
-		if (baud == 134) {
-			/* get it right for 134.5 baud */
-			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
-					2;
-		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud_rate) + 2;
-		} else if (baud) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud) + 2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-
-		/* byte size and parity */
-		switch (cflag & CSIZE) {
-		case CS5:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
-			break;
-		case CS6:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
-			break;
-		case CS7:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
-			break;
-		case CS8:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
-			break;
-		}
-		if (cflag & CSTOPB) {
-			cy_writel(&ch_ctrl->comm_data_l,
-				  readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
-		} else {
-			cy_writel(&ch_ctrl->comm_data_l,
-				  readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
-		}
-		if (cflag & PARENB) {
-			if (cflag & PARODD)
-				cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
-			else
-				cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
-		} else
-			cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
-
-		/* CTS flow control flag */
-		if (cflag & CRTSCTS) {
-			cy_writel(&ch_ctrl->hw_flow,
-				readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
-		} else {
-			cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
-					~(C_RS_CTS | C_RS_RTS));
-		}
-		/* As the HW flow control is done in firmware, the driver
-		   doesn't need to care about it */
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-		/* XON/XOFF/XANY flow control flags */
-		sw_flow = 0;
-		if (iflag & IXON) {
-			sw_flow |= C_FL_OXX;
-			if (iflag & IXANY)
-				sw_flow |= C_FL_OIXANY;
-		}
-		cy_writel(&ch_ctrl->sw_flow, sw_flow);
-
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-
-		/* CD sensitivity */
-		if (cflag & CLOCAL)
-			info->port.flags &= ~ASYNC_CHECK_CD;
-		else
-			info->port.flags |= ASYNC_CHECK_CD;
-
-		if (baud == 0) {	/* baud rate is zero, turn off line */
-			cy_writel(&ch_ctrl->rs_control,
-				  readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n");
-#endif
-		} else {
-			cy_writel(&ch_ctrl->rs_control,
-				  readl(&ch_ctrl->rs_control) | C_RS_DTR);
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n");
-#endif
-		}
-
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-	}
-}				/* set_line_char */
-
-static int cy_get_serial_info(struct cyclades_port *info,
-		struct serial_struct __user *retinfo)
-{
-	struct cyclades_card *cinfo = info->card;
-	struct serial_struct tmp = {
-		.type = info->type,
-		.line = info->line,
-		.port = (info->card - cy_card) * 0x100 + info->line -
-			cinfo->first_line,
-		.irq = cinfo->irq,
-		.flags = info->port.flags,
-		.close_delay = info->port.close_delay,
-		.closing_wait = info->port.closing_wait,
-		.baud_base = info->baud,
-		.custom_divisor = info->custom_divisor,
-		.hub6 = 0,		/*!!! */
-	};
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-static int
-cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
-		struct serial_struct __user *new_info)
-{
-	struct serial_struct new_serial;
-	int ret;
-
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-
-	mutex_lock(&info->port.mutex);
-	if (!capable(CAP_SYS_ADMIN)) {
-		if (new_serial.close_delay != info->port.close_delay ||
-				new_serial.baud_base != info->baud ||
-				(new_serial.flags & ASYNC_FLAGS &
-					~ASYNC_USR_MASK) !=
-				(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
-		{
-			mutex_unlock(&info->port.mutex);
-			return -EPERM;
-		}
-		info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
-				(new_serial.flags & ASYNC_USR_MASK);
-		info->baud = new_serial.baud_base;
-		info->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	info->baud = new_serial.baud_base;
-	info->custom_divisor = new_serial.custom_divisor;
-	info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
-			(new_serial.flags & ASYNC_FLAGS);
-	info->port.close_delay = new_serial.close_delay * HZ / 100;
-	info->port.closing_wait = new_serial.closing_wait * HZ / 100;
-
-check_and_exit:
-	if (info->port.flags & ASYNC_INITIALIZED) {
-		cy_set_line_char(info, tty);
-		ret = 0;
-	} else {
-		ret = cy_startup(info, tty);
-	}
-	mutex_unlock(&info->port.mutex);
-	return ret;
-}				/* set_serial_info */
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *	    is emptied.  On bus types like RS485, the transmitter must
- *	    release the bus after transmitting. This must be done when
- *	    the transmit shift register is empty, not be done when the
- *	    transmit holding register is empty.  This functionality
- *	    allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
-{
-	struct cyclades_card *card = info->card;
-	unsigned int result;
-	unsigned long flags;
-	u8 status;
-
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		result = (status ? 0 : TIOCSER_TEMT);
-	} else {
-		/* Not supported yet */
-		return -EINVAL;
-	}
-	return put_user(result, (unsigned long __user *)value);
-}
-
-static int cy_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	int result;
-
-	if (serial_paranoia_check(info, tty->name, __func__))
-		return -ENODEV;
-
-	card = info->card;
-
-	if (!cy_is_Z(card)) {
-		unsigned long flags;
-		int channel = info->line - card->first_line;
-		u8 status;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		status = cyy_readb(info, CyMSVR1);
-		status |= cyy_readb(info, CyMSVR2);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-
-		if (info->rtsdtr_inv) {
-			result = ((status & CyRTS) ? TIOCM_DTR : 0) |
-				((status & CyDTR) ? TIOCM_RTS : 0);
-		} else {
-			result = ((status & CyRTS) ? TIOCM_RTS : 0) |
-				((status & CyDTR) ? TIOCM_DTR : 0);
-		}
-		result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
-			((status & CyRI) ? TIOCM_RNG : 0) |
-			((status & CyDSR) ? TIOCM_DSR : 0) |
-			((status & CyCTS) ? TIOCM_CTS : 0);
-	} else {
-		u32 lstatus;
-
-		if (!cyz_is_loaded(card)) {
-			result = -ENODEV;
-			goto end;
-		}
-
-		lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
-		result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
-			((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
-			((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
-			((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
-			((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
-			((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
-	}
-end:
-	return result;
-}				/* cy_tiomget */
-
-static int
-cy_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, __func__))
-		return -ENODEV;
-
-	card = info->card;
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_change_rts_dtr(info, set, clear);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		int retval, channel = info->line - card->first_line;
-		u32 rs;
-
-		if (!cyz_is_loaded(card))
-			return -ENODEV;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		rs = readl(&ch_ctrl->rs_control);
-		if (set & TIOCM_RTS)
-			rs |= C_RS_RTS;
-		if (clear & TIOCM_RTS)
-			rs &= ~C_RS_RTS;
-		if (set & TIOCM_DTR) {
-			rs |= C_RS_DTR;
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n");
-#endif
-		}
-		if (clear & TIOCM_DTR) {
-			rs &= ~C_RS_DTR;
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_modem_info clearing "
-				"Z DTR\n");
-#endif
-		}
-		cy_writel(&ch_ctrl->rs_control, rs);
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-	}
-	return 0;
-}
-
-/*
- * cy_break() --- routine which turns the break handling on or off
- */
-static int cy_break(struct tty_struct *tty, int break_state)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-	int retval = 0;
-
-	if (serial_paranoia_check(info, tty->name, "cy_break"))
-		return -EINVAL;
-
-	card = info->card;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	if (!cy_is_Z(card)) {
-		/* Let the transmit ISR take care of this (since it
-		   requires stuffing characters into the output stream).
-		 */
-		if (break_state == -1) {
-			if (!info->breakon) {
-				info->breakon = 1;
-				if (!info->xmit_cnt) {
-					spin_unlock_irqrestore(&card->card_lock, flags);
-					start_xmit(info);
-					spin_lock_irqsave(&card->card_lock, flags);
-				}
-			}
-		} else {
-			if (!info->breakoff) {
-				info->breakoff = 1;
-				if (!info->xmit_cnt) {
-					spin_unlock_irqrestore(&card->card_lock, flags);
-					start_xmit(info);
-					spin_lock_irqsave(&card->card_lock, flags);
-				}
-			}
-		}
-	} else {
-		if (break_state == -1) {
-			retval = cyz_issue_cmd(card,
-				info->line - card->first_line,
-				C_CM_SET_BREAK, 0L);
-			if (retval != 0) {
-				printk(KERN_ERR "cyc:cy_break (set) retval on "
-					"ttyC%d was %x\n", info->line, retval);
-			}
-		} else {
-			retval = cyz_issue_cmd(card,
-				info->line - card->first_line,
-				C_CM_CLR_BREAK, 0L);
-			if (retval != 0) {
-				printk(KERN_DEBUG "cyc:cy_break (clr) retval "
-					"on ttyC%d was %x\n", info->line,
-					retval);
-			}
-		}
-	}
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	return retval;
-}				/* cy_break */
-
-static int set_threshold(struct cyclades_port *info, unsigned long value)
-{
-	struct cyclades_card *card = info->card;
-	unsigned long flags;
-
-	if (!cy_is_Z(card)) {
-		info->cor3 &= ~CyREC_FIFO;
-		info->cor3 |= value & CyREC_FIFO;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCOR3, info->cor3);
-		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-	return 0;
-}				/* set_threshold */
-
-static int get_threshold(struct cyclades_port *info,
-						unsigned long __user *value)
-{
-	struct cyclades_card *card = info->card;
-
-	if (!cy_is_Z(card)) {
-		u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO;
-		return put_user(tmp, value);
-	}
-	return 0;
-}				/* get_threshold */
-
-static int set_timeout(struct cyclades_port *info, unsigned long value)
-{
-	struct cyclades_card *card = info->card;
-	unsigned long flags;
-
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyRTPR, value & 0xff);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-	return 0;
-}				/* set_timeout */
-
-static int get_timeout(struct cyclades_port *info,
-						unsigned long __user *value)
-{
-	struct cyclades_card *card = info->card;
-
-	if (!cy_is_Z(card)) {
-		u8 tmp = cyy_readb(info, CyRTPR);
-		return put_user(tmp, value);
-	}
-	return 0;
-}				/* get_timeout */
-
-static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg,
-		struct cyclades_icount *cprev)
-{
-	struct cyclades_icount cnow;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	cnow = info->icount;	/* atomic copy */
-	spin_unlock_irqrestore(&info->card->card_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;
-}
-
-/*
- * This routine allows the tty driver to implement device-
- * specific ioctl's.  If the ioctl number passed in cmd is
- * not recognized by the driver, it should return ENOIOCTLCMD.
- */
-static int
-cy_ioctl(struct tty_struct *tty, struct file *file,
-	 unsigned int cmd, unsigned long arg)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_icount cnow;	/* kernel counter temps */
-	int ret_val = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
-		return -ENODEV;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
-		info->line, cmd, arg);
-#endif
-
-	switch (cmd) {
-	case CYGETMON:
-		if (copy_to_user(argp, &info->mon, sizeof(info->mon))) {
-			ret_val = -EFAULT;
-			break;
-		}
-		memset(&info->mon, 0, sizeof(info->mon));
-		break;
-	case CYGETTHRESH:
-		ret_val = get_threshold(info, argp);
-		break;
-	case CYSETTHRESH:
-		ret_val = set_threshold(info, arg);
-		break;
-	case CYGETDEFTHRESH:
-		ret_val = put_user(info->default_threshold,
-				(unsigned long __user *)argp);
-		break;
-	case CYSETDEFTHRESH:
-		info->default_threshold = arg & 0x0f;
-		break;
-	case CYGETTIMEOUT:
-		ret_val = get_timeout(info, argp);
-		break;
-	case CYSETTIMEOUT:
-		ret_val = set_timeout(info, arg);
-		break;
-	case CYGETDEFTIMEOUT:
-		ret_val = put_user(info->default_timeout,
-				(unsigned long __user *)argp);
-		break;
-	case CYSETDEFTIMEOUT:
-		info->default_timeout = arg & 0xff;
-		break;
-	case CYSETRFLOW:
-		info->rflow = (int)arg;
-		break;
-	case CYGETRFLOW:
-		ret_val = info->rflow;
-		break;
-	case CYSETRTSDTR_INV:
-		info->rtsdtr_inv = (int)arg;
-		break;
-	case CYGETRTSDTR_INV:
-		ret_val = info->rtsdtr_inv;
-		break;
-	case CYGETCD1400VER:
-		ret_val = info->chip_rev;
-		break;
-#ifndef CONFIG_CYZ_INTR
-	case CYZSETPOLLCYCLE:
-		cyz_polling_cycle = (arg * HZ) / 1000;
-		break;
-	case CYZGETPOLLCYCLE:
-		ret_val = (cyz_polling_cycle * 1000) / HZ;
-		break;
-#endif				/* CONFIG_CYZ_INTR */
-	case CYSETWAIT:
-		info->port.closing_wait = (unsigned short)arg * HZ / 100;
-		break;
-	case CYGETWAIT:
-		ret_val = info->port.closing_wait / (HZ / 100);
-		break;
-	case TIOCGSERIAL:
-		ret_val = cy_get_serial_info(info, argp);
-		break;
-	case TIOCSSERIAL:
-		ret_val = cy_set_serial_info(info, tty, argp);
-		break;
-	case TIOCSERGETLSR:	/* Get line status register */
-		ret_val = get_lsr_info(info, argp);
-		break;
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
-		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-	case TIOCMIWAIT:
-		spin_lock_irqsave(&info->card->card_lock, flags);
-		/* note the counters on entry */
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->card->card_lock, flags);
-		ret_val = wait_event_interruptible(info->port.delta_msr_wait,
-				cy_cflags_changed(info, arg, &cnow));
-		break;
-
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-	default:
-		ret_val = -ENOIOCTLCMD;
-	}
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_ioctl done\n");
-#endif
-	return ret_val;
-}				/* cy_ioctl */
-
-static int cy_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *sic)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_icount cnow;	/* Used to snapshot */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-	sic->cts = cnow.cts;
-	sic->dsr = cnow.dsr;
-	sic->rng = cnow.rng;
-	sic->dcd = cnow.dcd;
-	sic->rx = cnow.rx;
-	sic->tx = cnow.tx;
-	sic->frame = cnow.frame;
-	sic->overrun = cnow.overrun;
-	sic->parity = cnow.parity;
-	sic->brk = cnow.brk;
-	sic->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-/*
- * This routine allows the tty driver to be notified when
- * device's termios settings have changed.  Note that a
- * well-designed tty driver should be prepared to accept the case
- * where old == NULL, and try to do something rational.
- */
-static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
-#endif
-
-	cy_set_line_char(info, tty);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		cy_start(tty);
-	}
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->port.open_wait);
-#endif
-}				/* cy_set_termios */
-
-/* This function is used to send a high-priority XON/XOFF character to
-   the device.
-*/
-static void cy_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	int channel;
-
-	if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
-		return;
-
-	info->x_char = ch;
-
-	if (ch)
-		cy_start(tty);
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	if (cy_is_Z(card)) {
-		if (ch == STOP_CHAR(tty))
-			cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
-		else if (ch == START_CHAR(tty))
-			cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
-	}
-}
-
-/* This routine is called by the upper-layer tty layer to signal
-   that incoming characters should be throttled because the input
-   buffers are close to full.
- */
-static void cy_throttle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_THROTTLE
-	char buf[64];
-
-	printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf),
-			tty->ldisc.chars_in_buffer(tty), info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_throttle"))
-		return;
-
-	card = info->card;
-
-	if (I_IXOFF(tty)) {
-		if (!cy_is_Z(card))
-			cy_send_xchar(tty, STOP_CHAR(tty));
-		else
-			info->throttle = 1;
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		if (!cy_is_Z(card)) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cyy_change_rts_dtr(info, 0, TIOCM_RTS);
-			spin_unlock_irqrestore(&card->card_lock, flags);
-		} else {
-			info->throttle = 1;
-		}
-	}
-}				/* cy_throttle */
-
-/*
- * This routine notifies the tty driver that it should signal
- * that characters can now be sent to the tty without fear of
- * overrunning the input buffers of the line disciplines.
- */
-static void cy_unthrottle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_THROTTLE
-	char buf[64];
-
-	printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
-		tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			cy_send_xchar(tty, START_CHAR(tty));
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		card = info->card;
-		if (!cy_is_Z(card)) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cyy_change_rts_dtr(info, TIOCM_RTS, 0);
-			spin_unlock_irqrestore(&card->card_lock, flags);
-		} else {
-			info->throttle = 0;
-		}
-	}
-}				/* cy_unthrottle */
-
-/* cy_start and cy_stop provide software output flow control as a
-   function of XON/XOFF, software CTS, and other such stuff.
-*/
-static void cy_stop(struct tty_struct *tty)
-{
-	struct cyclades_card *cinfo;
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_stop"))
-		return;
-
-	cinfo = info->card;
-	channel = info->line - cinfo->first_line;
-	if (!cy_is_Z(cinfo)) {
-		spin_lock_irqsave(&cinfo->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
-		spin_unlock_irqrestore(&cinfo->card_lock, flags);
-	}
-}				/* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
-	struct cyclades_card *cinfo;
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_start"))
-		return;
-
-	cinfo = info->card;
-	channel = info->line - cinfo->first_line;
-	if (!cy_is_Z(cinfo)) {
-		spin_lock_irqsave(&cinfo->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
-		spin_unlock_irqrestore(&cinfo->card_lock, flags);
-	}
-}				/* cy_start */
-
-/*
- * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void cy_hangup(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-		return;
-
-	cy_flush_buffer(tty);
-	cy_shutdown(info, tty);
-	tty_port_hangup(&info->port);
-}				/* cy_hangup */
-
-static int cyy_carrier_raised(struct tty_port *port)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-	struct cyclades_card *cinfo = info->card;
-	unsigned long flags;
-	int channel = info->line - cinfo->first_line;
-	u32 cd;
-
-	spin_lock_irqsave(&cinfo->card_lock, flags);
-	cyy_writeb(info, CyCAR, channel & 0x03);
-	cd = cyy_readb(info, CyMSVR1) & CyDCD;
-	spin_unlock_irqrestore(&cinfo->card_lock, flags);
-
-	return cd;
-}
-
-static void cyy_dtr_rts(struct tty_port *port, int raise)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-	struct cyclades_card *cinfo = info->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cinfo->card_lock, flags);
-	cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
-			raise ? 0 : TIOCM_RTS | TIOCM_DTR);
-	spin_unlock_irqrestore(&cinfo->card_lock, flags);
-}
-
-static int cyz_carrier_raised(struct tty_port *port)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-
-	return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD;
-}
-
-static void cyz_dtr_rts(struct tty_port *port, int raise)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-	struct cyclades_card *cinfo = info->card;
-	struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-	int ret, channel = info->line - cinfo->first_line;
-	u32 rs;
-
-	rs = readl(&ch_ctrl->rs_control);
-	if (raise)
-		rs |= C_RS_RTS | C_RS_DTR;
-	else
-		rs &= ~(C_RS_RTS | C_RS_DTR);
-	cy_writel(&ch_ctrl->rs_control, rs);
-	ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L);
-	if (ret != 0)
-		printk(KERN_ERR "%s: retval on ttyC%d was %x\n",
-				__func__, info->line, ret);
-#ifdef CY_DEBUG_DTR
-	printk(KERN_DEBUG "%s: raising Z DTR\n", __func__);
-#endif
-}
-
-static const struct tty_port_operations cyy_port_ops = {
-	.carrier_raised = cyy_carrier_raised,
-	.dtr_rts = cyy_dtr_rts,
-	.shutdown = cy_do_close,
-};
-
-static const struct tty_port_operations cyz_port_ops = {
-	.carrier_raised = cyz_carrier_raised,
-	.dtr_rts = cyz_dtr_rts,
-	.shutdown = cy_do_close,
-};
-
-/*
- * ---------------------------------------------------------------------
- * cy_init() and friends
- *
- * cy_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-static int __devinit cy_init_card(struct cyclades_card *cinfo)
-{
-	struct cyclades_port *info;
-	unsigned int channel, port;
-
-	spin_lock_init(&cinfo->card_lock);
-	cinfo->intr_enabled = 0;
-
-	cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
-			GFP_KERNEL);
-	if (cinfo->ports == NULL) {
-		printk(KERN_ERR "Cyclades: cannot allocate ports\n");
-		return -ENOMEM;
-	}
-
-	for (channel = 0, port = cinfo->first_line; channel < cinfo->nports;
-			channel++, port++) {
-		info = &cinfo->ports[channel];
-		tty_port_init(&info->port);
-		info->magic = CYCLADES_MAGIC;
-		info->card = cinfo;
-		info->line = port;
-
-		info->port.closing_wait = CLOSING_WAIT_DELAY;
-		info->port.close_delay = 5 * HZ / 10;
-		info->port.flags = STD_COM_FLAGS;
-		init_completion(&info->shutdown_wait);
-
-		if (cy_is_Z(cinfo)) {
-			struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
-			struct ZFW_CTRL *zfw_ctrl;
-
-			info->port.ops = &cyz_port_ops;
-			info->type = PORT_STARTECH;
-
-			zfw_ctrl = cinfo->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-			info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel];
-			info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
-
-			if (cinfo->hw_ver == ZO_V1)
-				info->xmit_fifo_size = CYZ_FIFO_SIZE;
-			else
-				info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
-#ifdef CONFIG_CYZ_INTR
-			setup_timer(&cyz_rx_full_timer[port],
-				cyz_rx_restart, (unsigned long)info);
-#endif
-		} else {
-			unsigned short chip_number;
-			int index = cinfo->bus_index;
-
-			info->port.ops = &cyy_port_ops;
-			info->type = PORT_CIRRUS;
-			info->xmit_fifo_size = CyMAX_CHAR_FIFO;
-			info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
-			info->cor2 = CyETC;
-			info->cor3 = 0x08;	/* _very_ small rcv threshold */
-
-			chip_number = channel / CyPORTS_PER_CHIP;
-			info->u.cyy.base_addr = cinfo->base_addr +
-				(cy_chip_offset[chip_number] << index);
-			info->chip_rev = cyy_readb(info, CyGFRCR);
-
-			if (info->chip_rev >= CD1400_REV_J) {
-				/* It is a CD1400 rev. J or later */
-				info->tbpr = baud_bpr_60[13];	/* Tx BPR */
-				info->tco = baud_co_60[13];	/* Tx CO */
-				info->rbpr = baud_bpr_60[13];	/* Rx BPR */
-				info->rco = baud_co_60[13];	/* Rx CO */
-				info->rtsdtr_inv = 1;
-			} else {
-				info->tbpr = baud_bpr_25[13];	/* Tx BPR */
-				info->tco = baud_co_25[13];	/* Tx CO */
-				info->rbpr = baud_bpr_25[13];	/* Rx BPR */
-				info->rco = baud_co_25[13];	/* Rx CO */
-				info->rtsdtr_inv = 0;
-			}
-			info->read_status_mask = CyTIMEOUT | CySPECHAR |
-				CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
-		}
-
-	}
-
-#ifndef CONFIG_CYZ_INTR
-	if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
-		mod_timer(&cyz_timerlist, jiffies + 1);
-#ifdef CY_PCI_DEBUG
-		printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
-#endif
-	}
-#endif
-	return 0;
-}
-
-/* initialize chips on Cyclom-Y card -- return number of valid
-   chips (which is number of ports/4) */
-static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
-		int index)
-{
-	unsigned int chip_number;
-	void __iomem *base_addr;
-
-	cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
-	/* Cy_HwReset is 0x1400 */
-	cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-	udelay(500L);
-
-	for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
-							chip_number++) {
-		base_addr =
-		    true_base_addr + (cy_chip_offset[chip_number] << index);
-		mdelay(1);
-		if (readb(base_addr + (CyCCR << index)) != 0x00) {
-			/*************
-			printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
-			chip_number, (unsigned long)base_addr);
-			*************/
-			return chip_number;
-		}
-
-		cy_writeb(base_addr + (CyGFRCR << index), 0);
-		udelay(10L);
-
-		/* The Cyclom-16Y does not decode address bit 9 and therefore
-		   cannot distinguish between references to chip 0 and a non-
-		   existent chip 4.  If the preceding clearing of the supposed
-		   chip 4 GFRCR register appears at chip 0, there is no chip 4
-		   and this must be a Cyclom-16Y, not a Cyclom-32Ye.
-		 */
-		if (chip_number == 4 && readb(true_base_addr +
-				(cy_chip_offset[0] << index) +
-				(CyGFRCR << index)) == 0) {
-			return chip_number;
-		}
-
-		cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
-		mdelay(1);
-
-		if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
-			/*
-			   printk(" chip #%d at %#6lx is not responding ",
-			   chip_number, (unsigned long)base_addr);
-			   printk("(GFRCR stayed 0)\n",
-			 */
-			return chip_number;
-		}
-		if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
-				0x40) {
-			/*
-			printk(" chip #%d at %#6lx is not valid (GFRCR == "
-					"%#2x)\n",
-					chip_number, (unsigned long)base_addr,
-					base_addr[CyGFRCR<<index]);
-			 */
-			return chip_number;
-		}
-		cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
-		if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
-			/* It is a CD1400 rev. J or later */
-			/* Impossible to reach 5ms with this chip.
-			   Changed to 2ms instead (f = 500 Hz). */
-			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
-		} else {
-			/* f = 200 Hz */
-			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
-		}
-
-		/*
-		   printk(" chip #%d at %#6lx is rev 0x%2x\n",
-		   chip_number, (unsigned long)base_addr,
-		   readb(base_addr+(CyGFRCR<<index)));
-		 */
-	}
-	return chip_number;
-}				/* cyy_init_card */
-
-/*
- * ---------------------------------------------------------------------
- * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
- * sets global variables and return the number of ISA boards found.
- * ---------------------------------------------------------------------
- */
-static int __init cy_detect_isa(void)
-{
-#ifdef CONFIG_ISA
-	unsigned short cy_isa_irq, nboard;
-	void __iomem *cy_isa_address;
-	unsigned short i, j, cy_isa_nchan;
-	int isparam = 0;
-
-	nboard = 0;
-
-	/* Check for module parameters */
-	for (i = 0; i < NR_CARDS; i++) {
-		if (maddr[i] || i) {
-			isparam = 1;
-			cy_isa_addresses[i] = maddr[i];
-		}
-		if (!maddr[i])
-			break;
-	}
-
-	/* scan the address table probing for Cyclom-Y/ISA boards */
-	for (i = 0; i < NR_ISA_ADDRS; i++) {
-		unsigned int isa_address = cy_isa_addresses[i];
-		if (isa_address == 0x0000)
-			return nboard;
-
-		/* probe for CD1400... */
-		cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
-		if (cy_isa_address == NULL) {
-			printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
-					"address\n");
-			continue;
-		}
-		cy_isa_nchan = CyPORTS_PER_CHIP *
-			cyy_init_card(cy_isa_address, 0);
-		if (cy_isa_nchan == 0) {
-			iounmap(cy_isa_address);
-			continue;
-		}
-
-		if (isparam && i < NR_CARDS && irq[i])
-			cy_isa_irq = irq[i];
-		else
-			/* find out the board's irq by probing */
-			cy_isa_irq = detect_isa_irq(cy_isa_address);
-		if (cy_isa_irq == 0) {
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
-				"IRQ could not be detected.\n",
-				(unsigned long)cy_isa_address);
-			iounmap(cy_isa_address);
-			continue;
-		}
-
-		if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
-				"more channels are available. Change NR_PORTS "
-				"in cyclades.c and recompile kernel.\n",
-				(unsigned long)cy_isa_address);
-			iounmap(cy_isa_address);
-			return nboard;
-		}
-		/* fill the next cy_card structure available */
-		for (j = 0; j < NR_CARDS; j++) {
-			if (cy_card[j].base_addr == NULL)
-				break;
-		}
-		if (j == NR_CARDS) {	/* no more cy_cards available */
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
-				"more cards can be used. Change NR_CARDS in "
-				"cyclades.c and recompile kernel.\n",
-				(unsigned long)cy_isa_address);
-			iounmap(cy_isa_address);
-			return nboard;
-		}
-
-		/* allocate IRQ */
-		if (request_irq(cy_isa_irq, cyy_interrupt,
-				IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
-				"could not allocate IRQ#%d.\n",
-				(unsigned long)cy_isa_address, cy_isa_irq);
-			iounmap(cy_isa_address);
-			return nboard;
-		}
-
-		/* set cy_card */
-		cy_card[j].base_addr = cy_isa_address;
-		cy_card[j].ctl_addr.p9050 = NULL;
-		cy_card[j].irq = (int)cy_isa_irq;
-		cy_card[j].bus_index = 0;
-		cy_card[j].first_line = cy_next_channel;
-		cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
-		cy_card[j].nports = cy_isa_nchan;
-		if (cy_init_card(&cy_card[j])) {
-			cy_card[j].base_addr = NULL;
-			free_irq(cy_isa_irq, &cy_card[j]);
-			iounmap(cy_isa_address);
-			continue;
-		}
-		nboard++;
-
-		printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
-			"%d channels starting from port %d\n",
-			j + 1, (unsigned long)cy_isa_address,
-			(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
-			cy_isa_irq, cy_isa_nchan, cy_next_channel);
-
-		for (j = cy_next_channel;
-				j < cy_next_channel + cy_isa_nchan; j++)
-			tty_register_device(cy_serial_driver, j, NULL);
-		cy_next_channel += cy_isa_nchan;
-	}
-	return nboard;
-#else
-	return 0;
-#endif				/* CONFIG_ISA */
-}				/* cy_detect_isa */
-
-#ifdef CONFIG_PCI
-static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
-{
-	unsigned int a;
-
-	for (a = 0; a < size && *str; a++, str++)
-		if (*str & 0x80)
-			return -EINVAL;
-
-	for (; a < size; a++, str++)
-		if (*str)
-			return -EINVAL;
-
-	return 0;
-}
-
-static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
-		unsigned int size)
-{
-	for (; size > 0; size--) {
-		cy_writel(fpga, *data++);
-		udelay(10);
-	}
-}
-
-static void __devinit plx_init(struct pci_dev *pdev, int irq,
-		struct RUNTIME_9060 __iomem *addr)
-{
-	/* Reset PLX */
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
-	udelay(100L);
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
-
-	/* Reload Config. Registers from EEPROM */
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
-	udelay(100L);
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
-
-	/* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
-	 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
-	 * registers. This will remain here until we find a permanent fix.
-	 */
-	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
-}
-
-static int __devinit __cyz_load_fw(const struct firmware *fw,
-		const char *name, const u32 mailbox, void __iomem *base,
-		void __iomem *fpga)
-{
-	const void *ptr = fw->data;
-	const struct zfile_header *h = ptr;
-	const struct zfile_config *c, *cs;
-	const struct zfile_block *b, *bs;
-	unsigned int a, tmp, len = fw->size;
-#define BAD_FW KERN_ERR "Bad firmware: "
-	if (len < sizeof(*h)) {
-		printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
-		return -EINVAL;
-	}
-
-	cs = ptr + h->config_offset;
-	bs = ptr + h->block_offset;
-
-	if ((void *)(cs + h->n_config) > ptr + len ||
-			(void *)(bs + h->n_blocks) > ptr + len) {
-		printk(BAD_FW "too short");
-		return  -EINVAL;
-	}
-
-	if (cyc_isfwstr(h->name, sizeof(h->name)) ||
-			cyc_isfwstr(h->date, sizeof(h->date))) {
-		printk(BAD_FW "bad formatted header string\n");
-		return -EINVAL;
-	}
-
-	if (strncmp(name, h->name, sizeof(h->name))) {
-		printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
-		return -EINVAL;
-	}
-
-	tmp = 0;
-	for (c = cs; c < cs + h->n_config; c++) {
-		for (a = 0; a < c->n_blocks; a++)
-			if (c->block_list[a] > h->n_blocks) {
-				printk(BAD_FW "bad block ref number in cfgs\n");
-				return -EINVAL;
-			}
-		if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
-			tmp++;
-	}
-	if (!tmp) {
-		printk(BAD_FW "nothing appropriate\n");
-		return -EINVAL;
-	}
-
-	for (b = bs; b < bs + h->n_blocks; b++)
-		if (b->file_offset + b->size > len) {
-			printk(BAD_FW "bad block data offset\n");
-			return -EINVAL;
-		}
-
-	/* everything is OK, let's seek'n'load it */
-	for (c = cs; c < cs + h->n_config; c++)
-		if (c->mailbox == mailbox && c->function == 0)
-			break;
-
-	for (a = 0; a < c->n_blocks; a++) {
-		b = &bs[c->block_list[a]];
-		if (b->type == ZBLOCK_FPGA) {
-			if (fpga != NULL)
-				cyz_fpga_copy(fpga, ptr + b->file_offset,
-						b->size);
-		} else {
-			if (base != NULL)
-				memcpy_toio(base + b->ram_offset,
-					       ptr + b->file_offset, b->size);
-		}
-	}
-#undef BAD_FW
-	return 0;
-}
-
-static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
-		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
-{
-	const struct firmware *fw;
-	struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
-	struct CUSTOM_REG __iomem *cust = base_addr;
-	struct ZFW_CTRL __iomem *pt_zfwctrl;
-	void __iomem *tmp;
-	u32 mailbox, status, nchan;
-	unsigned int i;
-	int retval;
-
-	retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
-	if (retval) {
-		dev_err(&pdev->dev, "can't get firmware\n");
-		goto err;
-	}
-
-	/* Check whether the firmware is already loaded and running. If
-	   positive, skip this board */
-	if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
-		u32 cntval = readl(base_addr + 0x190);
-
-		udelay(100);
-		if (cntval != readl(base_addr + 0x190)) {
-			/* FW counter is working, FW is running */
-			dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
-					"Skipping board.\n");
-			retval = 0;
-			goto err_rel;
-		}
-	}
-
-	/* start boot */
-	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
-			~0x00030800UL);
-
-	mailbox = readl(&ctl_addr->mail_box_0);
-
-	if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
-		/* stops CPU and set window to beginning of RAM */
-		cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-		cy_writel(&cust->cpu_stop, 0);
-		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-		udelay(100);
-	}
-
-	plx_init(pdev, irq, ctl_addr);
-
-	if (mailbox != 0) {
-		/* load FPGA */
-		retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
-				base_addr);
-		if (retval)
-			goto err_rel;
-		if (!__cyz_fpga_loaded(ctl_addr)) {
-			dev_err(&pdev->dev, "fw upload successful, but fw is "
-					"not loaded\n");
-			goto err_rel;
-		}
-	}
-
-	/* stops CPU and set window to beginning of RAM */
-	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-	cy_writel(&cust->cpu_stop, 0);
-	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-	udelay(100);
-
-	/* clear memory */
-	for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
-		cy_writeb(tmp, 255);
-	if (mailbox != 0) {
-		/* set window to last 512K of RAM */
-		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
-		for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
-			cy_writeb(tmp, 255);
-		/* set window to beginning of RAM */
-		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-	}
-
-	retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
-	release_firmware(fw);
-	if (retval)
-		goto err;
-
-	/* finish boot and start boards */
-	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-	cy_writel(&cust->cpu_start, 0);
-	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-	i = 0;
-	while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
-		msleep(100);
-	if (status != ZFIRM_ID) {
-		if (status == ZFIRM_HLT) {
-			dev_err(&pdev->dev, "you need an external power supply "
-				"for this number of ports. Firmware halted and "
-				"board reset.\n");
-			retval = -EIO;
-			goto err;
-		}
-		dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
-				"some more time\n", status);
-		while ((status = readl(&fid->signature)) != ZFIRM_ID &&
-				i++ < 200)
-			msleep(100);
-		if (status != ZFIRM_ID) {
-			dev_err(&pdev->dev, "Board not started in 20 seconds! "
-					"Giving up. (fid->signature = 0x%x)\n",
-					status);
-			dev_info(&pdev->dev, "*** Warning ***: if you are "
-				"upgrading the FW, please power cycle the "
-				"system before loading the new FW to the "
-				"Cyclades-Z.\n");
-
-			if (__cyz_fpga_loaded(ctl_addr))
-				plx_init(pdev, irq, ctl_addr);
-
-			retval = -EIO;
-			goto err;
-		}
-		dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
-				i / 10);
-	}
-	pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
-
-	dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
-			base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
-			base_addr + readl(&fid->zfwctrl_addr));
-
-	nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
-	dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
-		readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
-
-	if (nchan == 0) {
-		dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
-			"check the connection between the Z host card and the "
-			"serial expanders.\n");
-
-		if (__cyz_fpga_loaded(ctl_addr))
-			plx_init(pdev, irq, ctl_addr);
-
-		dev_info(&pdev->dev, "Null number of ports detected. Board "
-				"reset.\n");
-		retval = 0;
-		goto err;
-	}
-
-	cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
-	cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
-
-	/*
-	   Early firmware failed to start looking for commands.
-	   This enables firmware interrupts for those commands.
-	 */
-	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
-			(1 << 17));
-	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
-			0x00030800UL);
-
-	return nchan;
-err_rel:
-	release_firmware(fw);
-err:
-	return retval;
-}
-
-static int __devinit cy_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	void __iomem *addr0 = NULL, *addr2 = NULL;
-	char *card_name = NULL;
-	u32 uninitialized_var(mailbox);
-	unsigned int device_id, nchan = 0, card_no, i;
-	unsigned char plx_ver;
-	int retval, irq;
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "cannot enable device\n");
-		goto err;
-	}
-
-	/* read PCI configuration area */
-	irq = pdev->irq;
-	device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
-
-#if defined(__alpha__)
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {	/* below 1M? */
-		dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
-			"addresses on Alpha systems.\n");
-		retval = -EIO;
-		goto err_dis;
-	}
-#endif
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
-		dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
-			"addresses\n");
-		retval = -EIO;
-		goto err_dis;
-	}
-
-	if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
-		dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
-				"it...\n");
-		pdev->resource[2].flags &= ~IORESOURCE_IO;
-	}
-
-	retval = pci_request_regions(pdev, "cyclades");
-	if (retval) {
-		dev_err(&pdev->dev, "failed to reserve resources\n");
-		goto err_dis;
-	}
-
-	retval = -EIO;
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-		card_name = "Cyclom-Y";
-
-		addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
-				CyPCI_Yctl);
-		if (addr0 == NULL) {
-			dev_err(&pdev->dev, "can't remap ctl region\n");
-			goto err_reg;
-		}
-		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
-				CyPCI_Ywin);
-		if (addr2 == NULL) {
-			dev_err(&pdev->dev, "can't remap base region\n");
-			goto err_unmap;
-		}
-
-		nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
-		if (nchan == 0) {
-			dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
-					"Serial-Modules\n");
-			goto err_unmap;
-		}
-	} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
-		struct RUNTIME_9060 __iomem *ctl_addr;
-
-		ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
-				CyPCI_Zctl);
-		if (addr0 == NULL) {
-			dev_err(&pdev->dev, "can't remap ctl region\n");
-			goto err_reg;
-		}
-
-		/* Disable interrupts on the PLX before resetting it */
-		cy_writew(&ctl_addr->intr_ctrl_stat,
-				readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
-
-		plx_init(pdev, irq, addr0);
-
-		mailbox = readl(&ctl_addr->mail_box_0);
-
-		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
-				mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
-		if (addr2 == NULL) {
-			dev_err(&pdev->dev, "can't remap base region\n");
-			goto err_unmap;
-		}
-
-		if (mailbox == ZE_V1) {
-			card_name = "Cyclades-Ze";
-		} else {
-			card_name = "Cyclades-8Zo";
-#ifdef CY_PCI_DEBUG
-			if (mailbox == ZO_V1) {
-				cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-				dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
-					"id %lx, ver %lx\n", (ulong)(0xff &
-					readl(&((struct CUSTOM_REG *)addr2)->
-						fpga_id)), (ulong)(0xff &
-					readl(&((struct CUSTOM_REG *)addr2)->
-						fpga_version)));
-				cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-			} else {
-				dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
-					"Cyclades-Z board.  FPGA not loaded\n");
-			}
-#endif
-			/* The following clears the firmware id word.  This
-			   ensures that the driver will not attempt to talk to
-			   the board until it has been properly initialized.
-			 */
-			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
-				cy_writel(addr2 + ID_ADDRESS, 0L);
-		}
-
-		retval = cyz_load_fw(pdev, addr2, addr0, irq);
-		if (retval <= 0)
-			goto err_unmap;
-		nchan = retval;
-	}
-
-	if ((cy_next_channel + nchan) > NR_PORTS) {
-		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
-			"channels are available. Change NR_PORTS in "
-			"cyclades.c and recompile kernel.\n");
-		goto err_unmap;
-	}
-	/* fill the next cy_card structure available */
-	for (card_no = 0; card_no < NR_CARDS; card_no++) {
-		if (cy_card[card_no].base_addr == NULL)
-			break;
-	}
-	if (card_no == NR_CARDS) {	/* no more cy_cards available */
-		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
-			"more cards can be used. Change NR_CARDS in "
-			"cyclades.c and recompile kernel.\n");
-		goto err_unmap;
-	}
-
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-		/* allocate IRQ */
-		retval = request_irq(irq, cyy_interrupt,
-				IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
-		if (retval) {
-			dev_err(&pdev->dev, "could not allocate IRQ\n");
-			goto err_unmap;
-		}
-		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
-	} else {
-		struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
-		struct ZFW_CTRL __iomem *zfw_ctrl;
-
-		zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-
-		cy_card[card_no].hw_ver = mailbox;
-		cy_card[card_no].num_chips = (unsigned int)-1;
-		cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
-#ifdef CONFIG_CYZ_INTR
-		/* allocate IRQ only if board has an IRQ */
-		if (irq != 0 && irq != 255) {
-			retval = request_irq(irq, cyz_interrupt,
-					IRQF_SHARED, "Cyclades-Z",
-					&cy_card[card_no]);
-			if (retval) {
-				dev_err(&pdev->dev, "could not allocate IRQ\n");
-				goto err_unmap;
-			}
-		}
-#endif				/* CONFIG_CYZ_INTR */
-	}
-
-	/* set cy_card */
-	cy_card[card_no].base_addr = addr2;
-	cy_card[card_no].ctl_addr.p9050 = addr0;
-	cy_card[card_no].irq = irq;
-	cy_card[card_no].bus_index = 1;
-	cy_card[card_no].first_line = cy_next_channel;
-	cy_card[card_no].nports = nchan;
-	retval = cy_init_card(&cy_card[card_no]);
-	if (retval)
-		goto err_null;
-
-	pci_set_drvdata(pdev, &cy_card[card_no]);
-
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-		/* enable interrupts in the PCI interface */
-		plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
-		switch (plx_ver) {
-		case PLX_9050:
-			cy_writeb(addr0 + 0x4c, 0x43);
-			break;
-
-		case PLX_9060:
-		case PLX_9080:
-		default:	/* Old boards, use PLX_9060 */
-		{
-			struct RUNTIME_9060 __iomem *ctl_addr = addr0;
-			plx_init(pdev, irq, ctl_addr);
-			cy_writew(&ctl_addr->intr_ctrl_stat,
-				readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
-			break;
-		}
-		}
-	}
-
-	dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
-		"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
-	for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
-		tty_register_device(cy_serial_driver, i, &pdev->dev);
-	cy_next_channel += nchan;
-
-	return 0;
-err_null:
-	cy_card[card_no].base_addr = NULL;
-	free_irq(irq, &cy_card[card_no]);
-err_unmap:
-	iounmap(addr0);
-	if (addr2)
-		iounmap(addr2);
-err_reg:
-	pci_release_regions(pdev);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return retval;
-}
-
-static void __devexit cy_pci_remove(struct pci_dev *pdev)
-{
-	struct cyclades_card *cinfo = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	/* non-Z with old PLX */
-	if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
-			PLX_9050)
-		cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
-	else
-#ifndef CONFIG_CYZ_INTR
-		if (!cy_is_Z(cinfo))
-#endif
-		cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
-			readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
-			~0x0900);
-
-	iounmap(cinfo->base_addr);
-	if (cinfo->ctl_addr.p9050)
-		iounmap(cinfo->ctl_addr.p9050);
-	if (cinfo->irq
-#ifndef CONFIG_CYZ_INTR
-		&& !cy_is_Z(cinfo)
-#endif /* CONFIG_CYZ_INTR */
-		)
-		free_irq(cinfo->irq, cinfo);
-	pci_release_regions(pdev);
-
-	cinfo->base_addr = NULL;
-	for (i = cinfo->first_line; i < cinfo->first_line +
-			cinfo->nports; i++)
-		tty_unregister_device(cy_serial_driver, i);
-	cinfo->nports = 0;
-	kfree(cinfo->ports);
-}
-
-static struct pci_driver cy_pci_driver = {
-	.name = "cyclades",
-	.id_table = cy_pci_dev_id,
-	.probe = cy_pci_probe,
-	.remove = __devexit_p(cy_pci_remove)
-};
-#endif
-
-static int cyclades_proc_show(struct seq_file *m, void *v)
-{
-	struct cyclades_port *info;
-	unsigned int i, j;
-	__u32 cur_jifs = jiffies;
-
-	seq_puts(m, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
-			"IdleIn  Overruns  Ldisc\n");
-
-	/* Output one line for each known port */
-	for (i = 0; i < NR_CARDS; i++)
-		for (j = 0; j < cy_card[i].nports; j++) {
-			info = &cy_card[i].ports[j];
-
-			if (info->port.count) {
-				/* XXX is the ldisc num worth this? */
-				struct tty_struct *tty;
-				struct tty_ldisc *ld;
-				int num = 0;
-				tty = tty_port_tty_get(&info->port);
-				if (tty) {
-					ld = tty_ldisc_ref(tty);
-					if (ld) {
-						num = ld->ops->num;
-						tty_ldisc_deref(ld);
-					}
-					tty_kref_put(tty);
-				}
-				seq_printf(m, "%3d %8lu %10lu %8lu "
-					"%10lu %8lu %9lu %6d\n", info->line,
-					(cur_jifs - info->idle_stats.in_use) /
-					HZ, info->idle_stats.xmit_bytes,
-					(cur_jifs - info->idle_stats.xmit_idle)/
-					HZ, info->idle_stats.recv_bytes,
-					(cur_jifs - info->idle_stats.recv_idle)/
-					HZ, info->idle_stats.overruns,
-					num);
-			} else
-				seq_printf(m, "%3d %8lu %10lu %8lu "
-					"%10lu %8lu %9lu %6ld\n",
-					info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
-		}
-	return 0;
-}
-
-static int cyclades_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, cyclades_proc_show, NULL);
-}
-
-static const struct file_operations cyclades_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= cyclades_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/* The serial driver boot-time initialization code!
-    Hardware I/O ports are mapped to character special devices on a
-    first found, first allocated manner.  That is, this code searches
-    for Cyclom cards in the system.  As each is found, it is probed
-    to discover how many chips (and thus how many ports) are present.
-    These ports are mapped to the tty ports 32 and upward in monotonic
-    fashion.  If an 8-port card is replaced with a 16-port card, the
-    port mapping on a following card will shift.
-
-    This approach is different from what is used in the other serial
-    device driver because the Cyclom is more properly a multiplexer,
-    not just an aggregation of serial ports on one card.
-
-    If there are more cards with more ports than have been
-    statically allocated above, a warning is printed and the
-    extra ports are ignored.
- */
-
-static const struct tty_operations cy_ops = {
-	.open = cy_open,
-	.close = cy_close,
-	.write = cy_write,
-	.put_char = cy_put_char,
-	.flush_chars = cy_flush_chars,
-	.write_room = cy_write_room,
-	.chars_in_buffer = cy_chars_in_buffer,
-	.flush_buffer = cy_flush_buffer,
-	.ioctl = cy_ioctl,
-	.throttle = cy_throttle,
-	.unthrottle = cy_unthrottle,
-	.set_termios = cy_set_termios,
-	.stop = cy_stop,
-	.start = cy_start,
-	.hangup = cy_hangup,
-	.break_ctl = cy_break,
-	.wait_until_sent = cy_wait_until_sent,
-	.tiocmget = cy_tiocmget,
-	.tiocmset = cy_tiocmset,
-	.get_icount = cy_get_icount,
-	.proc_fops = &cyclades_proc_fops,
-};
-
-static int __init cy_init(void)
-{
-	unsigned int nboards;
-	int retval = -ENOMEM;
-
-	cy_serial_driver = alloc_tty_driver(NR_PORTS);
-	if (!cy_serial_driver)
-		goto err;
-
-	printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n",
-			__DATE__, __TIME__);
-
-	/* Initialize the tty_driver structure */
-
-	cy_serial_driver->owner = THIS_MODULE;
-	cy_serial_driver->driver_name = "cyclades";
-	cy_serial_driver->name = "ttyC";
-	cy_serial_driver->major = CYCLADES_MAJOR;
-	cy_serial_driver->minor_start = 0;
-	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	cy_serial_driver->init_termios = tty_std_termios;
-	cy_serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(cy_serial_driver, &cy_ops);
-
-	retval = tty_register_driver(cy_serial_driver);
-	if (retval) {
-		printk(KERN_ERR "Couldn't register Cyclades serial driver\n");
-		goto err_frtty;
-	}
-
-	/* the code below is responsible to find the boards. Each different
-	   type of board has its own detection routine. If a board is found,
-	   the next cy_card structure available is set by the detection
-	   routine. These functions are responsible for checking the
-	   availability of cy_card and cy_port data structures and updating
-	   the cy_next_channel. */
-
-	/* look for isa boards */
-	nboards = cy_detect_isa();
-
-#ifdef CONFIG_PCI
-	/* look for pci boards */
-	retval = pci_register_driver(&cy_pci_driver);
-	if (retval && !nboards) {
-		tty_unregister_driver(cy_serial_driver);
-		goto err_frtty;
-	}
-#endif
-
-	return 0;
-err_frtty:
-	put_tty_driver(cy_serial_driver);
-err:
-	return retval;
-}				/* cy_init */
-
-static void __exit cy_cleanup_module(void)
-{
-	struct cyclades_card *card;
-	unsigned int i, e1;
-
-#ifndef CONFIG_CYZ_INTR
-	del_timer_sync(&cyz_timerlist);
-#endif /* CONFIG_CYZ_INTR */
-
-	e1 = tty_unregister_driver(cy_serial_driver);
-	if (e1)
-		printk(KERN_ERR "failed to unregister Cyclades serial "
-				"driver(%d)\n", e1);
-
-#ifdef CONFIG_PCI
-	pci_unregister_driver(&cy_pci_driver);
-#endif
-
-	for (i = 0; i < NR_CARDS; i++) {
-		card = &cy_card[i];
-		if (card->base_addr) {
-			/* clear interrupt */
-			cy_writeb(card->base_addr + Cy_ClrIntr, 0);
-			iounmap(card->base_addr);
-			if (card->ctl_addr.p9050)
-				iounmap(card->ctl_addr.p9050);
-			if (card->irq
-#ifndef CONFIG_CYZ_INTR
-				&& !cy_is_Z(card)
-#endif /* CONFIG_CYZ_INTR */
-				)
-				free_irq(card->irq, card);
-			for (e1 = card->first_line; e1 < card->first_line +
-					card->nports; e1++)
-				tty_unregister_device(cy_serial_driver, e1);
-			kfree(card->ports);
-		}
-	}
-
-	put_tty_driver(cy_serial_driver);
-} /* cy_cleanup_module */
-
-module_init(cy_init);
-module_exit(cy_cleanup_module);
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CY_VERSION);
-MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
-MODULE_FIRMWARE("cyzfirm.bin");
diff --git a/drivers/char/digi1.h b/drivers/char/digi1.h
deleted file mode 100644
index 94d4eab..0000000
--- a/drivers/char/digi1.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*          Definitions for DigiBoard ditty(1) command.                 */
-
-#if !defined(TIOCMODG)
-#define	TIOCMODG	(('d'<<8) | 250)	/* get modem ctrl state	*/
-#define	TIOCMODS	(('d'<<8) | 251)	/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMSET)
-#define	TIOCMSET	(('d'<<8) | 252)	/* set modem ctrl state	*/
-#define	TIOCMGET	(('d'<<8) | 253)	/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMBIC)
-#define	TIOCMBIC	(('d'<<8) | 254)	/* set modem ctrl state */
-#define	TIOCMBIS	(('d'<<8) | 255)	/* set modem ctrl state */
-#endif
-
-#if !defined(TIOCSDTR)
-#define	TIOCSDTR	(('e'<<8) | 0)		/* set DTR		*/
-#define	TIOCCDTR	(('e'<<8) | 1)		/* clear DTR		*/
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA	(('e'<<8) | 94)		/* Read params		*/
-
-#define DIGI_SETA	(('e'<<8) | 95)		/* Set params		*/
-#define DIGI_SETAW	(('e'<<8) | 96)		/* Drain & set params	*/
-#define DIGI_SETAF	(('e'<<8) | 97)		/* Drain, flush & set params */
-
-#define	DIGI_GETFLOW	(('e'<<8) | 99)		/* Get startc/stopc flow */
-						/* control characters 	 */
-#define	DIGI_SETFLOW	(('e'<<8) | 100)	/* Set startc/stopc flow */
-						/* control characters	 */
-#define	DIGI_GETAFLOW	(('e'<<8) | 101)	/* Get Aux. startc/stopc */
-						/* flow control chars 	 */
-#define	DIGI_SETAFLOW	(('e'<<8) | 102)	/* Set Aux. startc/stopc */
-						/* flow control chars	 */
-
-#define	DIGI_GETINFO	(('e'<<8) | 103)	/* Fill in digi_info */
-#define	DIGI_POLLER	(('e'<<8) | 104)	/* Turn on/off poller */
-#define	DIGI_INIT	(('e'<<8) | 105)	/* Allow things to run. */
-
-struct	digiflow_struct 
-{
-	unsigned char	startc;				/* flow cntl start char	*/
-	unsigned char	stopc;				/* flow cntl stop char	*/
-};
-
-typedef struct digiflow_struct digiflow_t;
-
-
-/************************************************************************
- * Values for digi_flags 
- ************************************************************************/
-#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
-#define DIGI_FAST	0x0002		/* Fast baud rates		*/
-#define RTSPACE		0x0004		/* RTS input flow control	*/
-#define CTSPACE		0x0008		/* CTS output flow control	*/
-#define DSRPACE		0x0010		/* DSR output flow control	*/
-#define DCDPACE		0x0020		/* DCD output flow control	*/
-#define DTRPACE		0x0040		/* DTR input flow control	*/
-#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
-#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
-#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
-
-
-/************************************************************************
- * Values for digiDload
- ************************************************************************/
-#define NORMAL  0
-#define PCI_CTL 1
-
-#define SIZE8  0
-#define SIZE16 1
-#define SIZE32 2
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_struct 
-{
-	unsigned short	digi_flags;		/* Flags (see above)	*/
-};
-
-typedef struct digi_struct digi_t;
-
-struct digi_info 
-{
-	unsigned long board;        /* Which board is this ? */
-	unsigned char status;       /* Alive or dead */
-	unsigned char type;         /* see epca.h */
-	unsigned char subtype;      /* For future XEM, XR, etc ... */
-	unsigned short numports;    /* Number of ports configured */
-	unsigned char *port;        /* I/O Address */
-	unsigned char *membase;     /* DPR Address */
-	unsigned char *version;     /* For future ... */
-	unsigned short windowData;  /* For future ... */
-} ;
diff --git a/drivers/char/digiFep1.h b/drivers/char/digiFep1.h
deleted file mode 100644
index 3c1f192..0000000
--- a/drivers/char/digiFep1.h
+++ /dev/null
@@ -1,136 +0,0 @@
-
-#define CSTART       0x400L
-#define CMAX         0x800L
-#define ISTART       0x800L
-#define IMAX         0xC00L
-#define CIN          0xD10L
-#define GLOBAL       0xD10L
-#define EIN          0xD18L
-#define FEPSTAT      0xD20L
-#define CHANSTRUCT   0x1000L
-#define RXTXBUF      0x4000L
-
-
-struct global_data 
-{
-	u16 cin;
-	u16 cout;
-	u16 cstart;
-	u16 cmax;
-	u16 ein;
-	u16 eout;
-	u16 istart;
-	u16 imax;
-};
-
-
-struct board_chan 
-{
-	u32 filler1;
-	u32 filler2;
-	u16 tseg;
-	u16 tin;
-	u16 tout;
-	u16 tmax;
-
-	u16 rseg;
-	u16 rin;
-	u16 rout;
-	u16 rmax;
-
-	u16 tlow;
-	u16 rlow;
-	u16 rhigh;
-	u16 incr;
-
-	u16 etime;
-	u16 edelay;
-	unchar *dev;
-
-	u16 iflag;
-	u16 oflag;
-	u16 cflag;
-	u16 gmask;
-
-	u16 col;
-	u16 delay;
-	u16 imask;
-	u16 tflush;
-
-	u32 filler3;
-	u32 filler4;
-	u32 filler5;
-	u32 filler6;
-
-	u8 num;
-	u8 ract;
-	u8 bstat;
-	u8 tbusy;
-	u8 iempty;
-	u8 ilow;
-	u8 idata;
-	u8 eflag;
-
-	u8 tflag;
-	u8 rflag;
-	u8 xmask;
-	u8 xval;
-	u8 mstat;
-	u8 mchange;
-	u8 mint;
-	u8 lstat;
-
-	u8 mtran;
-	u8 orun;
-	u8 startca;
-	u8 stopca;
-	u8 startc;
-	u8 stopc;
-	u8 vnext;
-	u8 hflow;
-
-	u8 fillc;
-	u8 ochar;
-	u8 omask;
-
-	u8 filler7;
-	u8 filler8[28];
-}; 
-
-
-#define SRXLWATER      0xE0
-#define SRXHWATER      0xE1
-#define STOUT          0xE2
-#define PAUSETX        0xE3
-#define RESUMETX       0xE4
-#define SAUXONOFFC     0xE6
-#define SENDBREAK      0xE8
-#define SETMODEM       0xE9
-#define SETIFLAGS      0xEA
-#define SONOFFC        0xEB
-#define STXLWATER      0xEC
-#define PAUSERX        0xEE
-#define RESUMERX       0xEF
-#define SETBUFFER      0xF2
-#define SETCOOKED      0xF3
-#define SETHFLOW       0xF4
-#define SETCTRLFLAGS   0xF5
-#define SETVNEXT       0xF6
-
-
-
-#define BREAK_IND        0x01
-#define LOWTX_IND        0x02
-#define EMPTYTX_IND      0x04
-#define DATA_IND         0x08
-#define MODEMCHG_IND     0x20
-
-#define FEP_HUPCL  0002000
-#if 0
-#define RTS   0x02
-#define CD    0x08
-#define DSR   0x10
-#define CTS   0x20
-#define RI    0x40
-#define DTR   0x80
-#endif
diff --git a/drivers/char/digiPCI.h b/drivers/char/digiPCI.h
deleted file mode 100644
index 6ca7819..0000000
--- a/drivers/char/digiPCI.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*************************************************************************
- * Defines and structure definitions for PCI BIOS Interface 
- *************************************************************************/
-#define	PCIMAX  32		/* maximum number of PCI boards */
-
-
-#define	PCI_VENDOR_DIGI		0x114F
-#define	PCI_DEVICE_EPC		0x0002
-#define	PCI_DEVICE_RIGHTSWITCH 0x0003  /* For testing */
-#define	PCI_DEVICE_XEM		0x0004
-#define	PCI_DEVICE_XR		0x0005
-#define	PCI_DEVICE_CX		0x0006
-#define	PCI_DEVICE_XRJ		0x0009   /* Jupiter boards with */
-#define	PCI_DEVICE_EPCJ		0x000a   /* PLX 9060 chip for PCI  */
-
-
-/*
- * On the PCI boards, there is no IO space allocated 
- * The I/O registers will be in the first 3 bytes of the   
- * upper 2MB of the 4MB memory space.  The board memory 
- * will be mapped into the low 2MB of the 4MB memory space 
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE		0x00020000	
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE		0x00400000	
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE		0x00200000	
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET 		0x00200000	
-
-#define MEMOUTB(basemem, pnum, setmemval)  *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval)
-#define MEMINB(basemem, pnum)  *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum ))   /* for PCI I/O */
-
-
-
-
-
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
deleted file mode 100644
index d9df46a..0000000
--- a/drivers/char/epca.c
+++ /dev/null
@@ -1,2784 +0,0 @@
-/*
-	Copyright (C) 1996  Digi International.
-
-	For technical support please email digiLinux@dgii.com or
-	call Digi tech support at (612) 912-3456
-
-	** This driver is no longer supported by Digi **
-
-	Much of this design and code came from epca.c which was
-	copyright (C) 1994, 1995 Troy De Jongh, and subsquently
-	modified by David Nugent, Christoph Lameter, Mike McLagan.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the GNU General Public License as published by
-	the Free Software Foundation; either version 2 of the License, or
-	(at your option) any later version.
-
-	This program is distributed in the hope that it will be useful,
-	but WITHOUT ANY WARRANTY; without even the implied warranty of
-	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-	GNU General Public License for more details.
-
-	You should have received a copy of the GNU General Public License
-	along with this program; if not, write to the Free Software
-	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-/* See README.epca for change history --DAT*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-#include "digiPCI.h"
-
-
-#include "digi1.h"
-#include "digiFep1.h"
-#include "epca.h"
-#include "epcaconfig.h"
-
-#define VERSION            "1.3.0.1-LK2.6"
-
-/* This major needs to be submitted to Linux to join the majors list */
-#define DIGIINFOMAJOR       35  /* For Digi specific ioctl */
-
-
-#define MAXCARDS 7
-#define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
-
-#define PFX "epca: "
-
-static int nbdevs, num_cards, liloconfig;
-static int digi_poller_inhibited = 1 ;
-
-static int setup_error_code;
-static int invalid_lilo_config;
-
-/*
- * The ISA boards do window flipping into the same spaces so its only sane with
- * a single lock. It's still pretty efficient. This lock guards the hardware
- * and the tty_port lock guards the kernel side stuff like use counts. Take
- * this lock inside the port lock if you must take both.
- */
-static DEFINE_SPINLOCK(epca_lock);
-
-/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
-   to 7 below. */
-static struct board_info boards[MAXBOARDS];
-
-static struct tty_driver *pc_driver;
-static struct tty_driver *pc_info;
-
-/* ------------------ Begin Digi specific structures -------------------- */
-
-/*
- * digi_channels represents an array of structures that keep track of each
- * channel of the Digi product. Information such as transmit and receive
- * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored
- * here. This structure is NOT used to overlay the cards physical channel
- * structure.
- */
-static struct channel digi_channels[MAX_ALLOC];
-
-/*
- * card_ptr is an array used to hold the address of the first channel structure
- * of each card. This array will hold the addresses of various channels located
- * in digi_channels.
- */
-static struct channel *card_ptr[MAXCARDS];
-
-static struct timer_list epca_timer;
-
-/*
- * Begin generic memory functions. These functions will be alias (point at)
- * more specific functions dependent on the board being configured.
- */
-static void memwinon(struct board_info *b, unsigned int win);
-static void memwinoff(struct board_info *b, unsigned int win);
-static void globalwinon(struct channel *ch);
-static void rxwinon(struct channel *ch);
-static void txwinon(struct channel *ch);
-static void memoff(struct channel *ch);
-static void assertgwinon(struct channel *ch);
-static void assertmemoff(struct channel *ch);
-
-/* ---- Begin more 'specific' memory functions for cx_like products --- */
-
-static void pcxem_memwinon(struct board_info *b, unsigned int win);
-static void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static void pcxem_globalwinon(struct channel *ch);
-static void pcxem_rxwinon(struct channel *ch);
-static void pcxem_txwinon(struct channel *ch);
-static void pcxem_memoff(struct channel *ch);
-
-/* ------ Begin more 'specific' memory functions for the pcxe ------- */
-
-static void pcxe_memwinon(struct board_info *b, unsigned int win);
-static void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static void pcxe_globalwinon(struct channel *ch);
-static void pcxe_rxwinon(struct channel *ch);
-static void pcxe_txwinon(struct channel *ch);
-static void pcxe_memoff(struct channel *ch);
-
-/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
-/* Note : pc64xe and pcxi share the same windowing routines */
-
-static void pcxi_memwinon(struct board_info *b, unsigned int win);
-static void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static void pcxi_globalwinon(struct channel *ch);
-static void pcxi_rxwinon(struct channel *ch);
-static void pcxi_txwinon(struct channel *ch);
-static void pcxi_memoff(struct channel *ch);
-
-/* - Begin 'specific' do nothing memory functions needed for some cards - */
-
-static void dummy_memwinon(struct board_info *b, unsigned int win);
-static void dummy_memwinoff(struct board_info *b, unsigned int win);
-static void dummy_globalwinon(struct channel *ch);
-static void dummy_rxwinon(struct channel *ch);
-static void dummy_txwinon(struct channel *ch);
-static void dummy_memoff(struct channel *ch);
-static void dummy_assertgwinon(struct channel *ch);
-static void dummy_assertmemoff(struct channel *ch);
-
-static struct channel *verifyChannel(struct tty_struct *);
-static void pc_sched_event(struct channel *, int);
-static void epca_error(int, char *);
-static void pc_close(struct tty_struct *, struct file *);
-static void shutdown(struct channel *, struct tty_struct *tty);
-static void pc_hangup(struct tty_struct *);
-static int pc_write_room(struct tty_struct *);
-static int pc_chars_in_buffer(struct tty_struct *);
-static void pc_flush_buffer(struct tty_struct *);
-static void pc_flush_chars(struct tty_struct *);
-static int pc_open(struct tty_struct *, struct file *);
-static void post_fep_init(unsigned int crd);
-static void epcapoll(unsigned long);
-static void doevent(int);
-static void fepcmd(struct channel *, int, int, int, int, int);
-static unsigned termios2digi_h(struct channel *ch, unsigned);
-static unsigned termios2digi_i(struct channel *ch, unsigned);
-static unsigned termios2digi_c(struct channel *ch, unsigned);
-static void epcaparam(struct tty_struct *, struct channel *);
-static void receive_data(struct channel *, struct tty_struct *tty);
-static int pc_ioctl(struct tty_struct *, struct file *,
-			unsigned int, unsigned long);
-static int info_ioctl(struct tty_struct *, struct file *,
-			unsigned int, unsigned long);
-static void pc_set_termios(struct tty_struct *, struct ktermios *);
-static void do_softint(struct work_struct *work);
-static void pc_stop(struct tty_struct *);
-static void pc_start(struct tty_struct *);
-static void pc_throttle(struct tty_struct *tty);
-static void pc_unthrottle(struct tty_struct *tty);
-static int pc_send_break(struct tty_struct *tty, int msec);
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-
-static int pc_write(struct tty_struct *, const unsigned char *, int);
-static int pc_init(void);
-static int init_PCI(void);
-
-/*
- * Table of functions for each board to handle memory. Mantaining parallelism
- * is a *very* good idea here. The idea is for the runtime code to blindly call
- * these functions, not knowing/caring about the underlying hardware. This
- * stuff should contain no conditionals; if more functionality is needed a
- * different entry should be established. These calls are the interface calls
- * and are the only functions that should be accessed. Anyone caught making
- * direct calls deserves what they get.
- */
-static void memwinon(struct board_info *b, unsigned int win)
-{
-	b->memwinon(b, win);
-}
-
-static void memwinoff(struct board_info *b, unsigned int win)
-{
-	b->memwinoff(b, win);
-}
-
-static void globalwinon(struct channel *ch)
-{
-	ch->board->globalwinon(ch);
-}
-
-static void rxwinon(struct channel *ch)
-{
-	ch->board->rxwinon(ch);
-}
-
-static void txwinon(struct channel *ch)
-{
-	ch->board->txwinon(ch);
-}
-
-static void memoff(struct channel *ch)
-{
-	ch->board->memoff(ch);
-}
-static void assertgwinon(struct channel *ch)
-{
-	ch->board->assertgwinon(ch);
-}
-
-static void assertmemoff(struct channel *ch)
-{
-	ch->board->assertmemoff(ch);
-}
-
-/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
-static void pcxem_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(FEPWIN | win, b->port + 1);
-}
-
-static void pcxem_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(0, b->port + 1);
-}
-
-static void pcxem_globalwinon(struct channel *ch)
-{
-	outb_p(FEPWIN, (int)ch->board->port + 1);
-}
-
-static void pcxem_rxwinon(struct channel *ch)
-{
-	outb_p(ch->rxwin, (int)ch->board->port + 1);
-}
-
-static void pcxem_txwinon(struct channel *ch)
-{
-	outb_p(ch->txwin, (int)ch->board->port + 1);
-}
-
-static void pcxem_memoff(struct channel *ch)
-{
-	outb_p(0, (int)ch->board->port + 1);
-}
-
-/* ----------------- Begin pcxe memory window stuff ------------------ */
-static void pcxe_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(FEPWIN | win, b->port + 1);
-}
-
-static void pcxe_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) & ~FEPMEM, b->port + 1);
-	outb_p(0, b->port + 1);
-}
-
-static void pcxe_globalwinon(struct channel *ch)
-{
-	outb_p(FEPWIN, (int)ch->board->port + 1);
-}
-
-static void pcxe_rxwinon(struct channel *ch)
-{
-	outb_p(ch->rxwin, (int)ch->board->port + 1);
-}
-
-static void pcxe_txwinon(struct channel *ch)
-{
-	outb_p(ch->txwin, (int)ch->board->port + 1);
-}
-
-static void pcxe_memoff(struct channel *ch)
-{
-	outb_p(0, (int)ch->board->port);
-	outb_p(0, (int)ch->board->port + 1);
-}
-
-/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-static void pcxi_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) | FEPMEM, b->port);
-}
-
-static void pcxi_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) & ~FEPMEM, b->port);
-}
-
-static void pcxi_globalwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_rxwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_txwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_memoff(struct channel *ch)
-{
-	outb_p(0, ch->board->port);
-}
-
-static void pcxi_assertgwinon(struct channel *ch)
-{
-	epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
-}
-
-static void pcxi_assertmemoff(struct channel *ch)
-{
-	epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
-}
-
-/*
- * Not all of the cards need specific memory windowing routines. Some cards
- * (Such as PCI) needs no windowing routines at all. We provide these do
- * nothing routines so that the same code base can be used. The driver will
- * ALWAYS call a windowing routine if it thinks it needs to; regardless of the
- * card. However, dependent on the card the routine may or may not do anything.
- */
-static void dummy_memwinon(struct board_info *b, unsigned int win)
-{
-}
-
-static void dummy_memwinoff(struct board_info *b, unsigned int win)
-{
-}
-
-static void dummy_globalwinon(struct channel *ch)
-{
-}
-
-static void dummy_rxwinon(struct channel *ch)
-{
-}
-
-static void dummy_txwinon(struct channel *ch)
-{
-}
-
-static void dummy_memoff(struct channel *ch)
-{
-}
-
-static void dummy_assertgwinon(struct channel *ch)
-{
-}
-
-static void dummy_assertmemoff(struct channel *ch)
-{
-}
-
-static struct channel *verifyChannel(struct tty_struct *tty)
-{
-	/*
-	 * This routine basically provides a sanity check. It insures that the
-	 * channel returned is within the proper range of addresses as well as
-	 * properly initialized. If some bogus info gets passed in
-	 * through tty->driver_data this should catch it.
-	 */
-	if (tty) {
-		struct channel *ch = tty->driver_data;
-		if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
-			if (ch->magic == EPCA_MAGIC)
-				return ch;
-		}
-	}
-	return NULL;
-}
-
-static void pc_sched_event(struct channel *ch, int event)
-{
-	/*
-	 * We call this to schedule interrupt processing on some event. The
-	 * kernel sees our request and calls the related routine in OUR driver.
-	 */
-	ch->event |= 1 << event;
-	schedule_work(&ch->tqueue);
-}
-
-static void epca_error(int line, char *msg)
-{
-	printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
-}
-
-static void pc_close(struct tty_struct *tty, struct file *filp)
-{
-	struct channel *ch;
-	struct tty_port *port;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return;
-	port = &ch->port;
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-
-	pc_flush_buffer(tty);
-	shutdown(ch, tty);
-
-	tty_port_close_end(port, tty);
-	ch->event = 0;	/* FIXME: review ch->event locking */
-	tty_port_tty_set(port, NULL);
-}
-
-static void shutdown(struct channel *ch, struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct board_chan __iomem *bc;
-	struct tty_port *port = &ch->port;
-
-	if (!(port->flags & ASYNC_INITIALIZED))
-		return;
-
-	spin_lock_irqsave(&epca_lock, flags);
-
-	globalwinon(ch);
-	bc = ch->brdchan;
-
-	/*
-	 * In order for an event to be generated on the receipt of data the
-	 * idata flag must be set. Since we are shutting down, this is not
-	 * necessary clear this flag.
-	 */
-	if (bc)
-		writeb(0, &bc->idata);
-
-	/* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
-	if (tty->termios->c_cflag & HUPCL)  {
-		ch->omodem &= ~(ch->m_rts | ch->m_dtr);
-		fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
-	}
-	memoff(ch);
-
-	/*
-	 * The channel has officialy been closed. The next time it is opened it
-	 * will have to reinitialized. Set a flag to indicate this.
-	 */
-	/* Prevent future Digi programmed interrupts from coming active */
-	port->flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&epca_lock, flags);
-}
-
-static void pc_hangup(struct tty_struct *tty)
-{
-	struct channel *ch;
-
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		pc_flush_buffer(tty);
-		tty_ldisc_flush(tty);
-		shutdown(ch, tty);
-
-		ch->event = 0;	/* FIXME: review locking of ch->event */
-		tty_port_hangup(&ch->port);
-	}
-}
-
-static int pc_write(struct tty_struct *tty,
-			const unsigned char *buf, int bytesAvailable)
-{
-	unsigned int head, tail;
-	int dataLen;
-	int size;
-	int amountCopied;
-	struct channel *ch;
-	unsigned long flags;
-	int remain;
-	struct board_chan __iomem *bc;
-
-	/*
-	 * pc_write is primarily called directly by the kernel routine
-	 * tty_write (Though it can also be called by put_char) found in
-	 * tty_io.c. pc_write is passed a line discipline buffer where the data
-	 * to be written out is stored. The line discipline implementation
-	 * itself is done at the kernel level and is not brought into the
-	 * driver.
-	 */
-
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return 0;
-
-	/* Make a pointer to the channel data structure found on the board. */
-	bc   = ch->brdchan;
-	size = ch->txbufsize;
-	amountCopied = 0;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-
-	head = readw(&bc->tin) & (size - 1);
-	tail = readw(&bc->tout);
-
-	if (tail != readw(&bc->tout))
-		tail = readw(&bc->tout);
-	tail &= (size - 1);
-
-	if (head >= tail) {
-		/* head has not wrapped */
-		/*
-		 * remain (much like dataLen above) represents the total amount
-		 * of space available on the card for data. Here dataLen
-		 * represents the space existing between the head pointer and
-		 * the end of buffer. This is important because a memcpy cannot
-		 * be told to automatically wrap around when it hits the buffer
-		 * end.
-		 */
-		dataLen = size - head;
-		remain = size - (head - tail) - 1;
-	} else {
-		/* head has wrapped around */
-		remain = tail - head - 1;
-		dataLen = remain;
-	}
-	/*
-	 * Check the space on the card. If we have more data than space; reduce
-	 * the amount of data to fit the space.
-	 */
-	bytesAvailable = min(remain, bytesAvailable);
-	txwinon(ch);
-	while (bytesAvailable > 0) {
-		/* there is data to copy onto card */
-
-		/*
-		 * If head is not wrapped, the below will make sure the first
-		 * data copy fills to the end of card buffer.
-		 */
-		dataLen = min(bytesAvailable, dataLen);
-		memcpy_toio(ch->txptr + head, buf, dataLen);
-		buf += dataLen;
-		head += dataLen;
-		amountCopied += dataLen;
-		bytesAvailable -= dataLen;
-
-		if (head >= size) {
-			head = 0;
-			dataLen = tail;
-		}
-	}
-	ch->statusflags |= TXBUSY;
-	globalwinon(ch);
-	writew(head, &bc->tin);
-
-	if ((ch->statusflags & LOWWAIT) == 0)  {
-		ch->statusflags |= LOWWAIT;
-		writeb(1, &bc->ilow);
-	}
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return amountCopied;
-}
-
-static int pc_write_room(struct tty_struct *tty)
-{
-	int remain = 0;
-	struct channel *ch;
-	unsigned long flags;
-	unsigned int head, tail;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-
-		bc   = ch->brdchan;
-		head = readw(&bc->tin) & (ch->txbufsize - 1);
-		tail = readw(&bc->tout);
-
-		if (tail != readw(&bc->tout))
-			tail = readw(&bc->tout);
-		/* Wrap tail if necessary */
-		tail &= (ch->txbufsize - 1);
-		remain = tail - head - 1;
-		if (remain < 0)
-			remain += ch->txbufsize;
-
-		if (remain && (ch->statusflags & LOWWAIT) == 0) {
-			ch->statusflags |= LOWWAIT;
-			writeb(1, &bc->ilow);
-		}
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-	/* Return how much room is left on card */
-	return remain;
-}
-
-static int pc_chars_in_buffer(struct tty_struct *tty)
-{
-	int chars;
-	unsigned int ctail, head, tail;
-	int remain;
-	unsigned long flags;
-	struct channel *ch;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return 0;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-
-	bc = ch->brdchan;
-	tail = readw(&bc->tout);
-	head = readw(&bc->tin);
-	ctail = readw(&ch->mailbox->cout);
-
-	if (tail == head && readw(&ch->mailbox->cin) == ctail &&
-						readb(&bc->tbusy) == 0)
-		chars = 0;
-	else  { /* Begin if some space on the card has been used */
-		head = readw(&bc->tin) & (ch->txbufsize - 1);
-		tail &= (ch->txbufsize - 1);
-		/*
-		 * The logic here is basically opposite of the above
-		 * pc_write_room here we are finding the amount of bytes in the
-		 * buffer filled. Not the amount of bytes empty.
-		 */
-		remain = tail - head - 1;
-		if (remain < 0)
-			remain += ch->txbufsize;
-		chars = (int)(ch->txbufsize - remain);
-		/*
-		 * Make it possible to wakeup anything waiting for output in
-		 * tty_ioctl.c, etc.
-		 *
-		 * If not already set. Setup an event to indicate when the
-		 * transmit buffer empties.
-		 */
-		if (!(ch->statusflags & EMPTYWAIT))
-			setup_empty_event(tty, ch);
-	} /* End if some space on the card has been used */
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	/* Return number of characters residing on card. */
-	return chars;
-}
-
-static void pc_flush_buffer(struct tty_struct *tty)
-{
-	unsigned int tail;
-	unsigned long flags;
-	struct channel *ch;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	bc   = ch->brdchan;
-	tail = readw(&bc->tout);
-	/* Have FEP move tout pointer; effectively flushing transmit buffer */
-	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	tty_wakeup(tty);
-}
-
-static void pc_flush_chars(struct tty_struct *tty)
-{
-	struct channel *ch;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&epca_lock, flags);
-		/*
-		 * If not already set and the transmitter is busy setup an
-		 * event to indicate when the transmit empties.
-		 */
-		if ((ch->statusflags & TXBUSY) &&
-				!(ch->statusflags & EMPTYWAIT))
-			setup_empty_event(tty, ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static int epca_carrier_raised(struct tty_port *port)
-{
-	struct channel *ch = container_of(port, struct channel, port);
-	if (ch->imodem & ch->dcd)
-		return 1;
-	return 0;
-}
-
-static void epca_dtr_rts(struct tty_port *port, int onoff)
-{
-}
-
-static int pc_open(struct tty_struct *tty, struct file *filp)
-{
-	struct channel *ch;
-	struct tty_port *port;
-	unsigned long flags;
-	int line, retval, boardnum;
-	struct board_chan __iomem *bc;
-	unsigned int head;
-
-	line = tty->index;
-	if (line < 0 || line >= nbdevs)
-		return -ENODEV;
-
-	ch = &digi_channels[line];
-	port = &ch->port;
-	boardnum = ch->boardnum;
-
-	/* Check status of board configured in system.  */
-
-	/*
-	 * I check to see if the epca_setup routine detected a user error. It
-	 * might be better to put this in pc_init, but for the moment it goes
-	 * here.
-	 */
-	if (invalid_lilo_config) {
-		if (setup_error_code & INVALID_BOARD_TYPE)
-			printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
-		if (setup_error_code & INVALID_NUM_PORTS)
-			printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
-		if (setup_error_code & INVALID_MEM_BASE)
-			printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
-		if (setup_error_code & INVALID_PORT_BASE)
-			printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
-		if (setup_error_code & INVALID_BOARD_STATUS)
-			printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
-		if (setup_error_code & INVALID_ALTPIN)
-			printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
-		tty->driver_data = NULL;   /* Mark this device as 'down' */
-		return -ENODEV;
-	}
-	if (boardnum >= num_cards || boards[boardnum].status == DISABLED)  {
-		tty->driver_data = NULL;   /* Mark this device as 'down' */
-		return(-ENODEV);
-	}
-
-	bc = ch->brdchan;
-	if (bc == NULL) {
-		tty->driver_data = NULL;
-		return -ENODEV;
-	}
-
-	spin_lock_irqsave(&port->lock, flags);
-	/*
-	 * Every time a channel is opened, increment a counter. This is
-	 * necessary because we do not wish to flush and shutdown the channel
-	 * until the last app holding the channel open, closes it.
-	 */
-	port->count++;
-	/*
-	 * Set a kernel structures pointer to our local channel structure. This
-	 * way we can get to it when passed only a tty struct.
-	 */
-	tty->driver_data = ch;
-	port->tty = tty;
-	/*
-	 * If this is the first time the channel has been opened, initialize
-	 * the tty->termios struct otherwise let pc_close handle it.
-	 */
-	spin_lock(&epca_lock);
-	globalwinon(ch);
-	ch->statusflags = 0;
-
-	/* Save boards current modem status */
-	ch->imodem = readb(&bc->mstat);
-
-	/*
-	 * Set receive head and tail ptrs to each other. This indicates no data
-	 * available to read.
-	 */
-	head = readw(&bc->rin);
-	writew(head, &bc->rout);
-
-	/* Set the channels associated tty structure */
-
-	/*
-	 * The below routine generally sets up parity, baud, flow control
-	 * issues, etc.... It effect both control flags and input flags.
-	 */
-	epcaparam(tty, ch);
-	memoff(ch);
-	spin_unlock(&epca_lock);
-	port->flags |= ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	retval = tty_port_block_til_ready(port, tty, filp);
-	if (retval)
-		return retval;
-	/*
-	 * Set this again in case a hangup set it to zero while this open() was
-	 * waiting for the line...
-	 */
-	spin_lock_irqsave(&port->lock, flags);
-	port->tty = tty;
-	spin_lock(&epca_lock);
-	globalwinon(ch);
-	/* Enable Digi Data events */
-	writeb(1, &bc->idata);
-	memoff(ch);
-	spin_unlock(&epca_lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	return 0;
-}
-
-static int __init epca_module_init(void)
-{
-	return pc_init();
-}
-module_init(epca_module_init);
-
-static struct pci_driver epca_driver;
-
-static void __exit epca_module_exit(void)
-{
-	int               count, crd;
-	struct board_info *bd;
-	struct channel    *ch;
-
-	del_timer_sync(&epca_timer);
-
-	if (tty_unregister_driver(pc_driver) ||
-				tty_unregister_driver(pc_info)) {
-		printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
-		return;
-	}
-	put_tty_driver(pc_driver);
-	put_tty_driver(pc_info);
-
-	for (crd = 0; crd < num_cards; crd++) {
-		bd = &boards[crd];
-		if (!bd) { /* sanity check */
-			printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
-			return;
-		}
-		ch = card_ptr[crd];
-		for (count = 0; count < bd->numports; count++, ch++) {
-			struct tty_struct *tty = tty_port_tty_get(&ch->port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-		}
-	}
-	pci_unregister_driver(&epca_driver);
-}
-module_exit(epca_module_exit);
-
-static const struct tty_operations pc_ops = {
-	.open = pc_open,
-	.close = pc_close,
-	.write = pc_write,
-	.write_room = pc_write_room,
-	.flush_buffer = pc_flush_buffer,
-	.chars_in_buffer = pc_chars_in_buffer,
-	.flush_chars = pc_flush_chars,
-	.ioctl = pc_ioctl,
-	.set_termios = pc_set_termios,
-	.stop = pc_stop,
-	.start = pc_start,
-	.throttle = pc_throttle,
-	.unthrottle = pc_unthrottle,
-	.hangup = pc_hangup,
-	.break_ctl = pc_send_break
-};
-
-static const struct tty_port_operations epca_port_ops = {
-	.carrier_raised = epca_carrier_raised,
-	.dtr_rts = epca_dtr_rts,
-};
-
-static int info_open(struct tty_struct *tty, struct file *filp)
-{
-	return 0;
-}
-
-static const struct tty_operations info_ops = {
-	.open = info_open,
-	.ioctl = info_ioctl,
-};
-
-static int __init pc_init(void)
-{
-	int crd;
-	struct board_info *bd;
-	unsigned char board_id = 0;
-	int err = -ENOMEM;
-
-	int pci_boards_found, pci_count;
-
-	pci_count = 0;
-
-	pc_driver = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_driver)
-		goto out1;
-
-	pc_info = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_info)
-		goto out2;
-
-	/*
-	 * If epca_setup has not been ran by LILO set num_cards to defaults;
-	 * copy board structure defined by digiConfig into drivers board
-	 * structure. Note : If LILO has ran epca_setup then epca_setup will
-	 * handle defining num_cards as well as copying the data into the board
-	 * structure.
-	 */
-	if (!liloconfig) {
-		/* driver has been configured via. epcaconfig */
-		nbdevs = NBDEVS;
-		num_cards = NUMCARDS;
-		memcpy(&boards, &static_boards,
-		       sizeof(struct board_info) * NUMCARDS);
-	}
-
-	/*
-	 * Note : If lilo was used to configure the driver and the ignore
-	 * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards
-	 * will equal 0 at this point. This is okay; PCI cards will still be
-	 * picked up if detected.
-	 */
-
-	/*
-	 * Set up interrupt, we will worry about memory allocation in
-	 * post_fep_init.
-	 */
-	printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
-
-	/*
-	 * NOTE : This code assumes that the number of ports found in the
-	 * boards array is correct. This could be wrong if the card in question
-	 * is PCI (And therefore has no ports entry in the boards structure.)
-	 * The rest of the information will be valid for PCI because the
-	 * beginning of pc_init scans for PCI and determines i/o and base
-	 * memory addresses. I am not sure if it is possible to read the number
-	 * of ports supported by the card prior to it being booted (Since that
-	 * is the state it is in when pc_init is run). Because it is not
-	 * possible to query the number of supported ports until after the card
-	 * has booted; we are required to calculate the card_ptrs as the card
-	 * is initialized (Inside post_fep_init). The negative thing about this
-	 * approach is that digiDload's call to GET_INFO will have a bad port
-	 * value. (Since this is called prior to post_fep_init.)
-	 */
-	pci_boards_found = 0;
-	if (num_cards < MAXBOARDS)
-		pci_boards_found += init_PCI();
-	num_cards += pci_boards_found;
-
-	pc_driver->owner = THIS_MODULE;
-	pc_driver->name = "ttyD";
-	pc_driver->major = DIGI_MAJOR;
-	pc_driver->minor_start = 0;
-	pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	pc_driver->subtype = SERIAL_TYPE_NORMAL;
-	pc_driver->init_termios = tty_std_termios;
-	pc_driver->init_termios.c_iflag = 0;
-	pc_driver->init_termios.c_oflag = 0;
-	pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	pc_driver->init_termios.c_lflag = 0;
-	pc_driver->init_termios.c_ispeed = 9600;
-	pc_driver->init_termios.c_ospeed = 9600;
-	pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(pc_driver, &pc_ops);
-
-	pc_info->owner = THIS_MODULE;
-	pc_info->name = "digi_ctl";
-	pc_info->major = DIGIINFOMAJOR;
-	pc_info->minor_start = 0;
-	pc_info->type = TTY_DRIVER_TYPE_SERIAL;
-	pc_info->subtype = SERIAL_TYPE_INFO;
-	pc_info->init_termios = tty_std_termios;
-	pc_info->init_termios.c_iflag = 0;
-	pc_info->init_termios.c_oflag = 0;
-	pc_info->init_termios.c_lflag = 0;
-	pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-	pc_info->init_termios.c_ispeed = 9600;
-	pc_info->init_termios.c_ospeed = 9600;
-	pc_info->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(pc_info, &info_ops);
-
-
-	for (crd = 0; crd < num_cards; crd++) {
-		/*
-		 * This is where the appropriate memory handlers for the
-		 * hardware is set. Everything at runtime blindly jumps through
-		 * these vectors.
-		 */
-
-		/* defined in epcaconfig.h */
-		bd = &boards[crd];
-
-		switch (bd->type) {
-		case PCXEM:
-		case EISAXEM:
-			bd->memwinon     = pcxem_memwinon;
-			bd->memwinoff    = pcxem_memwinoff;
-			bd->globalwinon  = pcxem_globalwinon;
-			bd->txwinon      = pcxem_txwinon;
-			bd->rxwinon      = pcxem_rxwinon;
-			bd->memoff       = pcxem_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			bd->memwinon     = dummy_memwinon;
-			bd->memwinoff    = dummy_memwinoff;
-			bd->globalwinon  = dummy_globalwinon;
-			bd->txwinon      = dummy_txwinon;
-			bd->rxwinon      = dummy_rxwinon;
-			bd->memoff       = dummy_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCXE:
-		case PCXEVE:
-			bd->memwinon     = pcxe_memwinon;
-			bd->memwinoff    = pcxe_memwinoff;
-			bd->globalwinon  = pcxe_globalwinon;
-			bd->txwinon      = pcxe_txwinon;
-			bd->rxwinon      = pcxe_rxwinon;
-			bd->memoff       = pcxe_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCXI:
-		case PC64XE:
-			bd->memwinon     = pcxi_memwinon;
-			bd->memwinoff    = pcxi_memwinoff;
-			bd->globalwinon  = pcxi_globalwinon;
-			bd->txwinon      = pcxi_txwinon;
-			bd->rxwinon      = pcxi_rxwinon;
-			bd->memoff       = pcxi_memoff;
-			bd->assertgwinon = pcxi_assertgwinon;
-			bd->assertmemoff = pcxi_assertmemoff;
-			break;
-
-		default:
-			break;
-		}
-
-		/*
-		 * Some cards need a memory segment to be defined for use in
-		 * transmit and receive windowing operations. These boards are
-		 * listed in the below switch. In the case of the XI the amount
-		 * of memory on the board is variable so the memory_seg is also
-		 * variable. This code determines what they segment should be.
-		 */
-		switch (bd->type) {
-		case PCXE:
-		case PCXEVE:
-		case PC64XE:
-			bd->memory_seg = 0xf000;
-			break;
-
-		case PCXI:
-			board_id = inb((int)bd->port);
-			if ((board_id & 0x1) == 0x1) {
-				/* it's an XI card */
-				/* Is it a 64K board */
-				if ((board_id & 0x30) == 0)
-					bd->memory_seg = 0xf000;
-
-				/* Is it a 128K board */
-				if ((board_id & 0x30) == 0x10)
-					bd->memory_seg = 0xe000;
-
-				/* Is is a 256K board */
-				if ((board_id & 0x30) == 0x20)
-					bd->memory_seg = 0xc000;
-
-				/* Is it a 512K board */
-				if ((board_id & 0x30) == 0x30)
-					bd->memory_seg = 0x8000;
-			} else
-				printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
-			break;
-		}
-	}
-
-	err = tty_register_driver(pc_driver);
-	if (err) {
-		printk(KERN_ERR "Couldn't register Digi PC/ driver");
-		goto out3;
-	}
-
-	err = tty_register_driver(pc_info);
-	if (err) {
-		printk(KERN_ERR "Couldn't register Digi PC/ info ");
-		goto out4;
-	}
-
-	/* Start up the poller to check for events on all enabled boards */
-	init_timer(&epca_timer);
-	epca_timer.function = epcapoll;
-	mod_timer(&epca_timer, jiffies + HZ/25);
-	return 0;
-
-out4:
-	tty_unregister_driver(pc_driver);
-out3:
-	put_tty_driver(pc_info);
-out2:
-	put_tty_driver(pc_driver);
-out1:
-	return err;
-}
-
-static void post_fep_init(unsigned int crd)
-{
-	int i;
-	void __iomem *memaddr;
-	struct global_data __iomem *gd;
-	struct board_info *bd;
-	struct board_chan __iomem *bc;
-	struct channel *ch;
-	int shrinkmem = 0, lowwater;
-
-	/*
-	 * This call is made by the user via. the ioctl call DIGI_INIT. It is
-	 * responsible for setting up all the card specific stuff.
-	 */
-	bd = &boards[crd];
-
-	/*
-	 * If this is a PCI board, get the port info. Remember PCI cards do not
-	 * have entries into the epcaconfig.h file, so we can't get the number
-	 * of ports from it. Unfortunetly, this means that anyone doing a
-	 * DIGI_GETINFO before the board has booted will get an invalid number
-	 * of ports returned (It should return 0). Calls to DIGI_GETINFO after
-	 * DIGI_INIT has been called will return the proper values.
-	 */
-	if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
-		/*
-		 * Below we use XEMPORTS as a memory offset regardless of which
-		 * PCI card it is. This is because all of the supported PCI
-		 * cards have the same memory offset for the channel data. This
-		 * will have to be changed if we ever develop a PCI/XE card.
-		 * NOTE : The FEP manual states that the port offset is 0xC22
-		 * as opposed to 0xC02. This is only true for PC/XE, and PC/XI
-		 * cards; not for the XEM, or CX series. On the PCI cards the
-		 * number of ports is determined by reading a ID PROM located
-		 * in the box attached to the card. The card can then determine
-		 * the index the id to determine the number of ports available.
-		 * (FYI - The id should be located at 0x1ac (And may use up to
-		 * 4 bytes if the box in question is a XEM or CX)).
-		 */
-		/* PCI cards are already remapped at this point ISA are not */
-		bd->numports = readw(bd->re_map_membase + XEMPORTS);
-		epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
-		nbdevs += (bd->numports);
-	} else {
-		/* Fix up the mappings for ISA/EISA etc */
-		/* FIXME: 64K - can we be smarter ? */
-		bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
-	}
-
-	if (crd != 0)
-		card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
-	else
-		card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
-
-	ch = card_ptr[crd];
-	epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
-
-	memaddr = bd->re_map_membase;
-
-	/*
-	 * The below assignment will set bc to point at the BEGINING of the
-	 * cards channel structures. For 1 card there will be between 8 and 64
-	 * of these structures.
-	 */
-	bc = memaddr + CHANSTRUCT;
-
-	/*
-	 * The below assignment will set gd to point at the BEGINING of global
-	 * memory address 0xc00. The first data in that global memory actually
-	 * starts at address 0xc1a. The command in pointer begins at 0xd10.
-	 */
-	gd = memaddr + GLOBAL;
-
-	/*
-	 * XEPORTS (address 0xc22) points at the number of channels the card
-	 * supports. (For 64XE, XI, XEM, and XR use 0xc02)
-	 */
-	if ((bd->type == PCXEVE || bd->type == PCXE) &&
-					(readw(memaddr + XEPORTS) < 3))
-		shrinkmem = 1;
-	if (bd->type < PCIXEM)
-		if (!request_region((int)bd->port, 4, board_desc[bd->type]))
-			return;
-	memwinon(bd, 0);
-
-	/*
-	 * Remember ch is the main drivers channels structure, while bc is the
-	 * cards channel structure.
-	 */
-	for (i = 0; i < bd->numports; i++, ch++, bc++) {
-		unsigned long flags;
-		u16 tseg, rseg;
-
-		tty_port_init(&ch->port);
-		ch->port.ops = &epca_port_ops;
-		ch->brdchan = bc;
-		ch->mailbox = gd;
-		INIT_WORK(&ch->tqueue, do_softint);
-		ch->board = &boards[crd];
-
-		spin_lock_irqsave(&epca_lock, flags);
-		switch (bd->type) {
-		/*
-		 * Since some of the boards use different bitmaps for
-		 * their control signals we cannot hard code these
-		 * values and retain portability. We virtualize this
-		 * data here.
-		 */
-		case EISAXEM:
-		case PCXEM:
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			ch->m_rts = 0x02;
-			ch->m_dcd = 0x80;
-			ch->m_dsr = 0x20;
-			ch->m_cts = 0x10;
-			ch->m_ri  = 0x40;
-			ch->m_dtr = 0x01;
-			break;
-
-		case PCXE:
-		case PCXEVE:
-		case PCXI:
-		case PC64XE:
-			ch->m_rts = 0x02;
-			ch->m_dcd = 0x08;
-			ch->m_dsr = 0x10;
-			ch->m_cts = 0x20;
-			ch->m_ri  = 0x40;
-			ch->m_dtr = 0x80;
-			break;
-		}
-
-		if (boards[crd].altpin) {
-			ch->dsr = ch->m_dcd;
-			ch->dcd = ch->m_dsr;
-			ch->digiext.digi_flags |= DIGI_ALTPIN;
-		} else {
-			ch->dcd = ch->m_dcd;
-			ch->dsr = ch->m_dsr;
-		}
-
-		ch->boardnum   = crd;
-		ch->channelnum = i;
-		ch->magic      = EPCA_MAGIC;
-		tty_port_tty_set(&ch->port, NULL);
-
-		if (shrinkmem) {
-			fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
-			shrinkmem = 0;
-		}
-
-		tseg = readw(&bc->tseg);
-		rseg = readw(&bc->rseg);
-
-		switch (bd->type) {
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			/* Cover all the 2MEG cards */
-			ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
-			ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
-			ch->txwin = FEPWIN | (tseg >> 11);
-			ch->rxwin = FEPWIN | (rseg >> 11);
-			break;
-
-		case PCXEM:
-		case EISAXEM:
-			/* Cover all the 32K windowed cards */
-			/* Mask equal to window size - 1 */
-			ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
-			ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
-			ch->txwin = FEPWIN | (tseg >> 11);
-			ch->rxwin = FEPWIN | (rseg >> 11);
-			break;
-
-		case PCXEVE:
-		case PCXE:
-			ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
-								& 0x1fff);
-			ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
-			ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
-								& 0x1fff);
-			ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
-			break;
-
-		case PCXI:
-		case PC64XE:
-			ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
-			ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
-			ch->txwin = ch->rxwin = 0;
-			break;
-		}
-
-		ch->txbufhead = 0;
-		ch->txbufsize = readw(&bc->tmax) + 1;
-
-		ch->rxbufhead = 0;
-		ch->rxbufsize = readw(&bc->rmax) + 1;
-
-		lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
-
-		/* Set transmitter low water mark */
-		fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
-
-		/* Set receiver low water mark */
-		fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0);
-
-		/* Set receiver high water mark */
-		fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
-
-		writew(100, &bc->edelay);
-		writeb(1, &bc->idata);
-
-		ch->startc  = readb(&bc->startc);
-		ch->stopc   = readb(&bc->stopc);
-		ch->startca = readb(&bc->startca);
-		ch->stopca  = readb(&bc->stopca);
-
-		ch->fepcflag = 0;
-		ch->fepiflag = 0;
-		ch->fepoflag = 0;
-		ch->fepstartc = 0;
-		ch->fepstopc = 0;
-		ch->fepstartca = 0;
-		ch->fepstopca = 0;
-
-		ch->port.close_delay = 50;
-
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-
-	printk(KERN_INFO
-	"Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
-				VERSION, board_desc[bd->type], (long)bd->port,
-					(long)bd->membase, bd->numports);
-	memwinoff(bd, 0);
-}
-
-static void epcapoll(unsigned long ignored)
-{
-	unsigned long flags;
-	int crd;
-	unsigned int head, tail;
-	struct channel *ch;
-	struct board_info *bd;
-
-	/*
-	 * This routine is called upon every timer interrupt. Even though the
-	 * Digi series cards are capable of generating interrupts this method
-	 * of non-looping polling is more efficient. This routine checks for
-	 * card generated events (Such as receive data, are transmit buffer
-	 * empty) and acts on those events.
-	 */
-	for (crd = 0; crd < num_cards; crd++) {
-		bd = &boards[crd];
-		ch = card_ptr[crd];
-
-		if ((bd->status == DISABLED) || digi_poller_inhibited)
-			continue;
-
-		/*
-		 * assertmemoff is not needed here; indeed it is an empty
-		 * subroutine. It is being kept because future boards may need
-		 * this as well as some legacy boards.
-		 */
-		spin_lock_irqsave(&epca_lock, flags);
-
-		assertmemoff(ch);
-
-		globalwinon(ch);
-
-		/*
-		 * In this case head and tail actually refer to the event queue
-		 * not the transmit or receive queue.
-		 */
-		head = readw(&ch->mailbox->ein);
-		tail = readw(&ch->mailbox->eout);
-
-		/* If head isn't equal to tail we have an event */
-		if (head != tail)
-			doevent(crd);
-		memoff(ch);
-
-		spin_unlock_irqrestore(&epca_lock, flags);
-	} /* End for each card */
-	mod_timer(&epca_timer, jiffies + (HZ / 25));
-}
-
-static void doevent(int crd)
-{
-	void __iomem *eventbuf;
-	struct channel *ch, *chan0;
-	static struct tty_struct *tty;
-	struct board_info *bd;
-	struct board_chan __iomem *bc;
-	unsigned int tail, head;
-	int event, channel;
-	int mstat, lstat;
-
-	/*
-	 * This subroutine is called by epcapoll when an event is detected
-	 * in the event queue. This routine responds to those events.
-	 */
-	bd = &boards[crd];
-
-	chan0 = card_ptr[crd];
-	epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
-	assertgwinon(chan0);
-	while ((tail = readw(&chan0->mailbox->eout)) !=
-			(head = readw(&chan0->mailbox->ein))) {
-		/* Begin while something in event queue */
-		assertgwinon(chan0);
-		eventbuf = bd->re_map_membase + tail + ISTART;
-		/* Get the channel the event occurred on */
-		channel = readb(eventbuf);
-		/* Get the actual event code that occurred */
-		event = readb(eventbuf + 1);
-		/*
-		 * The two assignments below get the current modem status
-		 * (mstat) and the previous modem status (lstat). These are
-		 * useful becuase an event could signal a change in modem
-		 * signals itself.
-		 */
-		mstat = readb(eventbuf + 2);
-		lstat = readb(eventbuf + 3);
-
-		ch = chan0 + channel;
-		if ((unsigned)channel >= bd->numports || !ch)  {
-			if (channel >= bd->numports)
-				ch = chan0;
-			bc = ch->brdchan;
-			goto next;
-		}
-
-		bc = ch->brdchan;
-		if (bc == NULL)
-			goto next;
-
-		tty = tty_port_tty_get(&ch->port);
-		if (event & DATA_IND)  { /* Begin DATA_IND */
-			receive_data(ch, tty);
-			assertgwinon(ch);
-		} /* End DATA_IND */
-		/* else *//* Fix for DCD transition missed bug */
-		if (event & MODEMCHG_IND) {
-			/* A modem signal change has been indicated */
-			ch->imodem = mstat;
-			if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) {
-				/* We are now receiving dcd */
-				if (mstat & ch->dcd)
-					wake_up_interruptible(&ch->port.open_wait);
-				else	/* No dcd; hangup */
-					pc_sched_event(ch, EPCA_EVENT_HANGUP);
-			}
-		}
-		if (tty) {
-			if (event & BREAK_IND) {
-				/* A break has been indicated */
-				tty_insert_flip_char(tty, 0, TTY_BREAK);
-				tty_schedule_flip(tty);
-			} else if (event & LOWTX_IND)  {
-				if (ch->statusflags & LOWWAIT) {
-					ch->statusflags &= ~LOWWAIT;
-					tty_wakeup(tty);
-				}
-			} else if (event & EMPTYTX_IND) {
-				/* This event is generated by
-				   setup_empty_event */
-				ch->statusflags &= ~TXBUSY;
-				if (ch->statusflags & EMPTYWAIT) {
-					ch->statusflags &= ~EMPTYWAIT;
-					tty_wakeup(tty);
-				}
-			}
-			tty_kref_put(tty);
-		}
-next:
-		globalwinon(ch);
-		BUG_ON(!bc);
-		writew(1, &bc->idata);
-		writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
-		globalwinon(chan0);
-	} /* End while something in event queue */
-}
-
-static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
-					int byte2, int ncmds, int bytecmd)
-{
-	unchar __iomem *memaddr;
-	unsigned int head, cmdTail, cmdStart, cmdMax;
-	long count;
-	int n;
-
-	/* This is the routine in which commands may be passed to the card. */
-
-	if (ch->board->status == DISABLED)
-		return;
-	assertgwinon(ch);
-	/* Remember head (As well as max) is just an offset not a base addr */
-	head = readw(&ch->mailbox->cin);
-	/* cmdStart is a base address */
-	cmdStart = readw(&ch->mailbox->cstart);
-	/*
-	 * We do the addition below because we do not want a max pointer
-	 * relative to cmdStart. We want a max pointer that points at the
-	 * physical end of the command queue.
-	 */
-	cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
-	memaddr = ch->board->re_map_membase;
-
-	if (head >= (cmdMax - cmdStart) || (head & 03))  {
-		printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
-						__LINE__,  cmd, head);
-		printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
-						__LINE__,  cmdMax, cmdStart);
-		return;
-	}
-	if (bytecmd)  {
-		writeb(cmd, memaddr + head + cmdStart + 0);
-		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
-		/* Below word_or_byte is bits to set */
-		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
-		/* Below byte2 is bits to reset */
-		writeb(byte2, memaddr + head + cmdStart + 3);
-	}  else {
-		writeb(cmd, memaddr + head + cmdStart + 0);
-		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
-		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
-	}
-	head = (head + 4) & (cmdMax - cmdStart - 4);
-	writew(head, &ch->mailbox->cin);
-	count = FEPTIMEOUT;
-
-	for (;;) {
-		count--;
-		if (count == 0)  {
-			printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
-			return;
-		}
-		head = readw(&ch->mailbox->cin);
-		cmdTail = readw(&ch->mailbox->cout);
-		n = (head - cmdTail) & (cmdMax - cmdStart - 4);
-		/*
-		 * Basically this will break when the FEP acknowledges the
-		 * command by incrementing cmdTail (Making it equal to head).
-		 */
-		if (n <= ncmds * (sizeof(short) * 4))
-			break;
-	}
-}
-
-/*
- * Digi products use fields in their channels structures that are very similar
- * to the c_cflag and c_iflag fields typically found in UNIX termios
- * structures. The below three routines allow mappings between these hardware
- * "flags" and their respective Linux flags.
- */
-static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
-{
-	unsigned res = 0;
-
-	if (cflag & CRTSCTS) {
-		ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
-		res |= ((ch->m_cts) | (ch->m_rts));
-	}
-
-	if (ch->digiext.digi_flags & RTSPACE)
-		res |= ch->m_rts;
-
-	if (ch->digiext.digi_flags & DTRPACE)
-		res |= ch->m_dtr;
-
-	if (ch->digiext.digi_flags & CTSPACE)
-		res |= ch->m_cts;
-
-	if (ch->digiext.digi_flags & DSRPACE)
-		res |= ch->dsr;
-
-	if (ch->digiext.digi_flags & DCDPACE)
-		res |= ch->dcd;
-
-	if (res & (ch->m_rts))
-		ch->digiext.digi_flags |= RTSPACE;
-
-	if (res & (ch->m_cts))
-		ch->digiext.digi_flags |= CTSPACE;
-
-	return res;
-}
-
-static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
-{
-	unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
-					INPCK | ISTRIP | IXON | IXANY | IXOFF);
-	if (ch->digiext.digi_flags & DIGI_AIXON)
-		res |= IAIXON;
-	return res;
-}
-
-static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
-{
-	unsigned res = 0;
-	if (cflag & CBAUDEX) {
-		ch->digiext.digi_flags |= DIGI_FAST;
-		/*
-		 * HUPCL bit is used by FEP to indicate fast baud table is to
-		 * be used.
-		 */
-		res |= FEP_HUPCL;
-	} else
-		ch->digiext.digi_flags &= ~DIGI_FAST;
-	/*
-	 * CBAUD has bit position 0x1000 set these days to indicate Linux
-	 * baud rate remap. Digi hardware can't handle the bit assignment.
-	 * (We use a different bit assignment for high speed.). Clear this
-	 * bit out.
-	 */
-	res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-	/*
-	 * This gets a little confusing. The Digi cards have their own
-	 * representation of c_cflags controlling baud rate. For the most part
-	 * this is identical to the Linux implementation. However; Digi
-	 * supports one rate (76800) that Linux doesn't. This means that the
-	 * c_cflag entry that would normally mean 76800 for Digi actually means
-	 * 115200 under Linux. Without the below mapping, a stty 115200 would
-	 * only drive the board at 76800. Since the rate 230400 is also found
-	 * after 76800, the same problem afflicts us when we choose a rate of
-	 * 230400. Without the below modificiation stty 230400 would actually
-	 * give us 115200.
-	 *
-	 * There are two additional differences. The Linux value for CLOCAL
-	 * (0x800; 0004000) has no meaning to the Digi hardware. Also in later
-	 * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000)
-	 * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be
-	 * checked for a screened out prior to termios2digi_c returning. Since
-	 * CLOCAL isn't used by the board this can be ignored as long as the
-	 * returned value is used only by Digi hardware.
-	 */
-	if (cflag & CBAUDEX) {
-		/*
-		 * The below code is trying to guarantee that only baud rates
-		 * 115200 and 230400 are remapped. We use exclusive or because
-		 * the various baud rates share common bit positions and
-		 * therefore can't be tested for easily.
-		 */
-		if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
-		    (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
-			res += 1;
-	}
-	return res;
-}
-
-/* Caller must hold the locks */
-static void epcaparam(struct tty_struct *tty, struct channel *ch)
-{
-	unsigned int cmdHead;
-	struct ktermios *ts;
-	struct board_chan __iomem *bc;
-	unsigned mval, hflow, cflag, iflag;
-
-	bc = ch->brdchan;
-	epcaassert(bc != NULL, "bc out of range");
-
-	assertgwinon(ch);
-	ts = tty->termios;
-	if ((ts->c_cflag & CBAUD) == 0)  { /* Begin CBAUD detected */
-		cmdHead = readw(&bc->rin);
-		writew(cmdHead, &bc->rout);
-		cmdHead = readw(&bc->tin);
-		/* Changing baud in mid-stream transmission can be wonderful */
-		/*
-		 * Flush current transmit buffer by setting cmdTail pointer
-		 * (tout) to cmdHead pointer (tin). Hopefully the transmit
-		 * buffer is empty.
-		 */
-		fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
-		mval = 0;
-	} else { /* Begin CBAUD not detected */
-		/*
-		 * c_cflags have changed but that change had nothing to do with
-		 * BAUD. Propagate the change to the card.
-		 */
-		cflag = termios2digi_c(ch, ts->c_cflag);
-		if (cflag != ch->fepcflag)  {
-			ch->fepcflag = cflag;
-			/* Set baud rate, char size, stop bits, parity */
-			fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
-		}
-		/*
-		 * If the user has not forced CLOCAL and if the device is not a
-		 * CALLOUT device (Which is always CLOCAL) we set flags such
-		 * that the driver will wait on carrier detect.
-		 */
-		if (ts->c_cflag & CLOCAL)
-			clear_bit(ASYNCB_CHECK_CD, &ch->port.flags);
-		else
-			set_bit(ASYNCB_CHECK_CD, &ch->port.flags);
-		mval = ch->m_dtr | ch->m_rts;
-	} /* End CBAUD not detected */
-	iflag = termios2digi_i(ch, ts->c_iflag);
-	/* Check input mode flags */
-	if (iflag != ch->fepiflag)  {
-		ch->fepiflag = iflag;
-		/*
-		 * Command sets channels iflag structure on the board. Such
-		 * things as input soft flow control, handling of parity
-		 * errors, and break handling are all set here.
-		 *
-		 * break handling, parity handling, input stripping,
-		 * flow control chars
-		 */
-		fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
-	}
-	/*
-	 * Set the board mint value for this channel. This will cause hardware
-	 * events to be generated each time the DCD signal (Described in mint)
-	 * changes.
-	 */
-	writeb(ch->dcd, &bc->mint);
-	if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
-		if (ch->digiext.digi_flags & DIGI_FORCEDCD)
-			writeb(0, &bc->mint);
-	ch->imodem = readb(&bc->mstat);
-	hflow = termios2digi_h(ch, ts->c_cflag);
-	if (hflow != ch->hflow)  {
-		ch->hflow = hflow;
-		/*
-		 * Hard flow control has been selected but the board is not
-		 * using it. Activate hard flow control now.
-		 */
-		fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
-	}
-	mval ^= ch->modemfake & (mval ^ ch->modem);
-
-	if (ch->omodem ^ mval)  {
-		ch->omodem = mval;
-		/*
-		 * The below command sets the DTR and RTS mstat structure. If
-		 * hard flow control is NOT active these changes will drive the
-		 * output of the actual DTR and RTS lines. If hard flow control
-		 * is active, the changes will be saved in the mstat structure
-		 * and only asserted when hard flow control is turned off.
-		 */
-
-		/* First reset DTR & RTS; then set them */
-		fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
-		fepcmd(ch, SETMODEM, mval, 0, 0, 1);
-	}
-	if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)  {
-		ch->fepstartc = ch->startc;
-		ch->fepstopc = ch->stopc;
-		/*
-		 * The XON / XOFF characters have changed; propagate these
-		 * changes to the card.
-		 */
-		fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
-	}
-	if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)  {
-		ch->fepstartca = ch->startca;
-		ch->fepstopca = ch->stopca;
-		/*
-		 * Similar to the above, this time the auxilarly XON / XOFF
-		 * characters have changed; propagate these changes to the card.
-		 */
-		fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
-	}
-}
-
-/* Caller holds lock */
-static void receive_data(struct channel *ch, struct tty_struct *tty)
-{
-	unchar *rptr;
-	struct ktermios *ts = NULL;
-	struct board_chan __iomem *bc;
-	int dataToRead, wrapgap, bytesAvailable;
-	unsigned int tail, head;
-	unsigned int wrapmask;
-
-	/*
-	 * This routine is called by doint when a receive data event has taken
-	 * place.
-	 */
-	globalwinon(ch);
-	if (ch->statusflags & RXSTOPPED)
-		return;
-	if (tty)
-		ts = tty->termios;
-	bc = ch->brdchan;
-	BUG_ON(!bc);
-	wrapmask = ch->rxbufsize - 1;
-
-	/*
-	 * Get the head and tail pointers to the receiver queue. Wrap the head
-	 * pointer if it has reached the end of the buffer.
-	 */
-	head = readw(&bc->rin);
-	head &= wrapmask;
-	tail = readw(&bc->rout) & wrapmask;
-
-	bytesAvailable = (head - tail) & wrapmask;
-	if (bytesAvailable == 0)
-		return;
-
-	/* If CREAD bit is off or device not open, set TX tail to head */
-	if (!tty || !ts || !(ts->c_cflag & CREAD)) {
-		writew(head, &bc->rout);
-		return;
-	}
-
-	if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
-		return;
-
-	if (readb(&bc->orun)) {
-		writeb(0, &bc->orun);
-		printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
-								tty->name);
-		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-	}
-	rxwinon(ch);
-	while (bytesAvailable > 0) {
-		/* Begin while there is data on the card */
-		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
-		/*
-		 * Even if head has wrapped around only report the amount of
-		 * data to be equal to the size - tail. Remember memcpy can't
-		 * automaticly wrap around the receive buffer.
-		 */
-		dataToRead = (wrapgap < bytesAvailable) ? wrapgap
-							: bytesAvailable;
-		/* Make sure we don't overflow the buffer */
-		dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
-		if (dataToRead == 0)
-			break;
-		/*
-		 * Move data read from our card into the line disciplines
-		 * buffer for translation if necessary.
-		 */
-		memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
-		tail = (tail + dataToRead) & wrapmask;
-		bytesAvailable -= dataToRead;
-	} /* End while there is data on the card */
-	globalwinon(ch);
-	writew(tail, &bc->rout);
-	/* Must be called with global data */
-	tty_schedule_flip(tty);
-}
-
-static int info_ioctl(struct tty_struct *tty, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case DIGI_GETINFO:
-		{
-			struct digi_info di;
-			int brd;
-
-			if (get_user(brd, (unsigned int __user *)arg))
-				return -EFAULT;
-			if (brd < 0 || brd >= num_cards || num_cards == 0)
-				return -ENODEV;
-
-			memset(&di, 0, sizeof(di));
-
-			di.board = brd;
-			di.status = boards[brd].status;
-			di.type = boards[brd].type ;
-			di.numports = boards[brd].numports ;
-			/* Legacy fixups - just move along nothing to see */
-			di.port = (unsigned char *)boards[brd].port ;
-			di.membase = (unsigned char *)boards[brd].membase ;
-
-			if (copy_to_user((void __user *)arg, &di, sizeof(di)))
-				return -EFAULT;
-			break;
-
-		}
-
-	case DIGI_POLLER:
-		{
-			int brd = arg & 0xff000000 >> 16;
-			unsigned char state = arg & 0xff;
-
-			if (brd < 0 || brd >= num_cards) {
-				printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
-				return -ENODEV;
-			}
-			digi_poller_inhibited = state;
-			break;
-		}
-
-	case DIGI_INIT:
-		{
-			/*
-			 * This call is made by the apps to complete the
-			 * initialization of the board(s). This routine is
-			 * responsible for setting the card to its initial
-			 * state and setting the drivers control fields to the
-			 * sutianle settings for the card in question.
-			 */
-			int crd;
-			for (crd = 0; crd < num_cards; crd++)
-				post_fep_init(crd);
-			break;
-		}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static int pc_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct channel *ch = tty->driver_data;
-	struct board_chan __iomem *bc;
-	unsigned int mstat, mflag = 0;
-	unsigned long flags;
-
-	if (ch)
-		bc = ch->brdchan;
-	else
-		return -EINVAL;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	mstat = readb(&bc->mstat);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-
-	if (mstat & ch->m_dtr)
-		mflag |= TIOCM_DTR;
-	if (mstat & ch->m_rts)
-		mflag |= TIOCM_RTS;
-	if (mstat & ch->m_cts)
-		mflag |= TIOCM_CTS;
-	if (mstat & ch->dsr)
-		mflag |= TIOCM_DSR;
-	if (mstat & ch->m_ri)
-		mflag |= TIOCM_RI;
-	if (mstat & ch->dcd)
-		mflag |= TIOCM_CD;
-	return mflag;
-}
-
-static int pc_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct channel *ch = tty->driver_data;
-	unsigned long flags;
-
-	if (!ch)
-		return -EINVAL;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	/*
-	 * I think this modemfake stuff is broken. It doesn't correctly reflect
-	 * the behaviour desired by the TIOCM* ioctls. Therefore this is
-	 * probably broken.
-	 */
-	if (set & TIOCM_RTS) {
-		ch->modemfake |= ch->m_rts;
-		ch->modem |= ch->m_rts;
-	}
-	if (set & TIOCM_DTR) {
-		ch->modemfake |= ch->m_dtr;
-		ch->modem |= ch->m_dtr;
-	}
-	if (clear & TIOCM_RTS) {
-		ch->modemfake |= ch->m_rts;
-		ch->modem &= ~ch->m_rts;
-	}
-	if (clear & TIOCM_DTR) {
-		ch->modemfake |= ch->m_dtr;
-		ch->modem &= ~ch->m_dtr;
-	}
-	globalwinon(ch);
-	/*
-	 * The below routine generally sets up parity, baud, flow control
-	 * issues, etc.... It effect both control flags and input flags.
-	 */
-	epcaparam(tty, ch);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return 0;
-}
-
-static int pc_ioctl(struct tty_struct *tty, struct file *file,
-					unsigned int cmd, unsigned long arg)
-{
-	digiflow_t dflow;
-	unsigned long flags;
-	unsigned int mflag, mstat;
-	unsigned char startc, stopc;
-	struct board_chan __iomem *bc;
-	struct channel *ch = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (ch)
-		bc = ch->brdchan;
-	else
-		return -EINVAL;
-	switch (cmd) {
-	case TIOCMODG:
-		mflag = pc_tiocmget(tty, file);
-		if (put_user(mflag, (unsigned long __user *)argp))
-			return -EFAULT;
-		break;
-	case TIOCMODS:
-		if (get_user(mstat, (unsigned __user *)argp))
-			return -EFAULT;
-		return pc_tiocmset(tty, file, mstat, ~mstat);
-	case TIOCSDTR:
-		spin_lock_irqsave(&epca_lock, flags);
-		ch->omodem |= ch->m_dtr;
-		globalwinon(ch);
-		fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-
-	case TIOCCDTR:
-		spin_lock_irqsave(&epca_lock, flags);
-		ch->omodem &= ~ch->m_dtr;
-		globalwinon(ch);
-		fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-	case DIGI_GETA:
-		if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
-			return -EFAULT;
-		break;
-	case DIGI_SETAW:
-	case DIGI_SETAF:
-		if (cmd == DIGI_SETAW) {
-			/* Setup an event to indicate when the transmit
-			   buffer empties */
-			spin_lock_irqsave(&epca_lock, flags);
-			setup_empty_event(tty, ch);
-			spin_unlock_irqrestore(&epca_lock, flags);
-			tty_wait_until_sent(tty, 0);
-		} else {
-			/* ldisc lock already held in ioctl */
-			if (tty->ldisc->ops->flush_buffer)
-				tty->ldisc->ops->flush_buffer(tty);
-		}
-		/* Fall Thru */
-	case DIGI_SETA:
-		if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
-			return -EFAULT;
-
-		if (ch->digiext.digi_flags & DIGI_ALTPIN)  {
-			ch->dcd = ch->m_dsr;
-			ch->dsr = ch->m_dcd;
-		} else {
-			ch->dcd = ch->m_dcd;
-			ch->dsr = ch->m_dsr;
-			}
-
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-
-		/*
-		 * The below routine generally sets up parity, baud, flow
-		 * control issues, etc.... It effect both control flags and
-		 * input flags.
-		 */
-		epcaparam(tty, ch);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-
-	case DIGI_GETFLOW:
-	case DIGI_GETAFLOW:
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-		if (cmd == DIGI_GETFLOW) {
-			dflow.startc = readb(&bc->startc);
-			dflow.stopc = readb(&bc->stopc);
-		} else {
-			dflow.startc = readb(&bc->startca);
-			dflow.stopc = readb(&bc->stopca);
-		}
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-
-		if (copy_to_user(argp, &dflow, sizeof(dflow)))
-			return -EFAULT;
-		break;
-
-	case DIGI_SETAFLOW:
-	case DIGI_SETFLOW:
-		if (cmd == DIGI_SETFLOW) {
-			startc = ch->startc;
-			stopc = ch->stopc;
-		} else {
-			startc = ch->startca;
-			stopc = ch->stopca;
-		}
-
-		if (copy_from_user(&dflow, argp, sizeof(dflow)))
-			return -EFAULT;
-
-		if (dflow.startc != startc || dflow.stopc != stopc) {
-			/* Begin  if setflow toggled */
-			spin_lock_irqsave(&epca_lock, flags);
-			globalwinon(ch);
-
-			if (cmd == DIGI_SETFLOW) {
-				ch->fepstartc = ch->startc = dflow.startc;
-				ch->fepstopc = ch->stopc = dflow.stopc;
-				fepcmd(ch, SONOFFC, ch->fepstartc,
-						ch->fepstopc, 0, 1);
-			} else {
-				ch->fepstartca = ch->startca = dflow.startc;
-				ch->fepstopca  = ch->stopca = dflow.stopc;
-				fepcmd(ch, SAUXONOFFC, ch->fepstartca,
-						ch->fepstopca, 0, 1);
-			}
-
-			if (ch->statusflags & TXSTOPPED)
-				pc_start(tty);
-
-			memoff(ch);
-			spin_unlock_irqrestore(&epca_lock, flags);
-		} /* End if setflow toggled */
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-
-	if (ch != NULL)  { /* Begin if channel valid */
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-		epcaparam(tty, ch);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-			 ((tty->termios->c_cflag & CRTSCTS) == 0))
-			tty->hw_stopped = 0;
-
-		if (!(old_termios->c_cflag & CLOCAL) &&
-			 (tty->termios->c_cflag & CLOCAL))
-			wake_up_interruptible(&ch->port.open_wait);
-
-	} /* End if channel valid */
-}
-
-static void do_softint(struct work_struct *work)
-{
-	struct channel *ch = container_of(work, struct channel, tqueue);
-	/* Called in response to a modem change event */
-	if (ch && ch->magic == EPCA_MAGIC) {
-		struct tty_struct *tty = tty_port_tty_get(&ch->port);
-
-		if (tty && tty->driver_data) {
-			if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
-				tty_hangup(tty);
-				wake_up_interruptible(&ch->port.open_wait);
-				clear_bit(ASYNCB_NORMAL_ACTIVE,
-						&ch->port.flags);
-			}
-		}
-		tty_kref_put(tty);
-	}
-}
-
-/*
- * pc_stop and pc_start provide software flow control to the routine and the
- * pc_ioctl routine.
- */
-static void pc_stop(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		if ((ch->statusflags & TXSTOPPED) == 0) {
-			/* Begin if transmit stop requested */
-			globalwinon(ch);
-			/* STOP transmitting now !! */
-			fepcmd(ch, PAUSETX, 0, 0, 0, 0);
-			ch->statusflags |= TXSTOPPED;
-			memoff(ch);
-		} /* End if transmit stop requested */
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static void pc_start(struct tty_struct *tty)
-{
-	struct channel *ch;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&epca_lock, flags);
-		/* Just in case output was resumed because of a change
-		   in Digi-flow */
-		if (ch->statusflags & TXSTOPPED)  {
-			/* Begin transmit resume requested */
-			struct board_chan __iomem *bc;
-			globalwinon(ch);
-			bc = ch->brdchan;
-			if (ch->statusflags & LOWWAIT)
-				writeb(1, &bc->ilow);
-			/* Okay, you can start transmitting again... */
-			fepcmd(ch, RESUMETX, 0, 0, 0, 0);
-			ch->statusflags &= ~TXSTOPPED;
-			memoff(ch);
-		} /* End transmit resume requested */
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-/*
- * The below routines pc_throttle and pc_unthrottle are used to slow (And
- * resume) the receipt of data into the kernels receive buffers. The exact
- * occurrence of this depends on the size of the kernels receive buffer and
- * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for
- * more details.
- */
-static void pc_throttle(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		if ((ch->statusflags & RXSTOPPED) == 0) {
-			globalwinon(ch);
-			fepcmd(ch, PAUSERX, 0, 0, 0, 0);
-			ch->statusflags |= RXSTOPPED;
-			memoff(ch);
-		}
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static void pc_unthrottle(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		/* Just in case output was resumed because of a change
-		   in Digi-flow */
-		spin_lock_irqsave(&epca_lock, flags);
-		if (ch->statusflags & RXSTOPPED) {
-			globalwinon(ch);
-			fepcmd(ch, RESUMERX, 0, 0, 0, 0);
-			ch->statusflags &= ~RXSTOPPED;
-			memoff(ch);
-		}
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static int pc_send_break(struct tty_struct *tty, int msec)
-{
-	struct channel *ch = tty->driver_data;
-	unsigned long flags;
-
-	if (msec == -1)
-		msec = 0xFFFF;
-	else if (msec > 0xFFFE)
-		msec = 0xFFFE;
-	else if (msec < 1)
-		msec = 1;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	/*
-	 * Maybe I should send an infinite break here, schedule() for msec
-	 * amount of time, and then stop the break. This way, the user can't
-	 * screw up the FEP by causing digi_send_break() to be called (i.e. via
-	 * an ioctl()) more than once in msec amount of time.
-	 * Try this for now...
-	 */
-	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return 0;
-}
-
-/* Caller MUST hold the lock */
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
-{
-	struct board_chan __iomem *bc = ch->brdchan;
-
-	globalwinon(ch);
-	ch->statusflags |= EMPTYWAIT;
-	/*
-	 * When set the iempty flag request a event to be generated when the
-	 * transmit buffer is empty (If there is no BREAK in progress).
-	 */
-	writeb(1, &bc->iempty);
-	memoff(ch);
-}
-
-#ifndef MODULE
-static void __init epca_setup(char *str, int *ints)
-{
-	struct board_info board;
-	int               index, loop, last;
-	char              *temp, *t2;
-	unsigned          len;
-
-	/*
-	 * If this routine looks a little strange it is because it is only
-	 * called if a LILO append command is given to boot the kernel with
-	 * parameters. In this way, we can provide the user a method of
-	 * changing his board configuration without rebuilding the kernel.
-	 */
-	if (!liloconfig)
-		liloconfig = 1;
-
-	memset(&board, 0, sizeof(board));
-
-	/* Assume the data is int first, later we can change it */
-	/* I think that array position 0 of ints holds the number of args */
-	for (last = 0, index = 1; index <= ints[0]; index++)
-		switch (index) { /* Begin parse switch */
-		case 1:
-			board.status = ints[index];
-			/*
-			 * We check for 2 (As opposed to 1; because 2 is a flag
-			 * instructing the driver to ignore epcaconfig.) For
-			 * this reason we check for 2.
-			 */
-			if (board.status == 2) {
-			/* Begin ignore epcaconfig as well as lilo cmd line */
-				nbdevs = 0;
-				num_cards = 0;
-				return;
-			} /* End ignore epcaconfig as well as lilo cmd line */
-
-			if (board.status > 2) {
-				printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
-						board.status);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_STATUS;
-				return;
-			}
-			last = index;
-			break;
-		case 2:
-			board.type = ints[index];
-			if (board.type >= PCIXEM)  {
-				printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_TYPE;
-				return;
-			}
-			last = index;
-			break;
-		case 3:
-			board.altpin = ints[index];
-			if (board.altpin > 1) {
-				printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_ALTPIN;
-				return;
-			}
-			last = index;
-			break;
-
-		case 4:
-			board.numports = ints[index];
-			if (board.numports < 2 || board.numports > 256) {
-				printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_NUM_PORTS;
-				return;
-			}
-			nbdevs += board.numports;
-			last = index;
-			break;
-
-		case 5:
-			board.port = ints[index];
-			if (ints[index] <= 0) {
-				printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_PORT_BASE;
-				return;
-			}
-			last = index;
-			break;
-
-		case 6:
-			board.membase = ints[index];
-			if (ints[index] <= 0) {
-				printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
-					(unsigned int)board.membase);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_MEM_BASE;
-				return;
-			}
-			last = index;
-			break;
-
-		default:
-			printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n");
-			return;
-
-		} /* End parse switch */
-
-	while (str && *str)  { /* Begin while there is a string arg */
-		/* find the next comma or terminator */
-		temp = str;
-		/* While string is not null, and a comma hasn't been found */
-		while (*temp && (*temp != ','))
-			temp++;
-		if (!*temp)
-			temp = NULL;
-		else
-			*temp++ = 0;
-		/* Set index to the number of args + 1 */
-		index = last + 1;
-
-		switch (index) {
-		case 1:
-			len = strlen(str);
-			if (strncmp("Disable", str, len) == 0)
-				board.status = 0;
-			else if (strncmp("Enable", str, len) == 0)
-				board.status = 1;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_STATUS;
-				return;
-			}
-			last = index;
-			break;
-
-		case 2:
-			for (loop = 0; loop < EPCA_NUM_TYPES; loop++)
-				if (strcmp(board_desc[loop], str) == 0)
-					break;
-			/*
-			 * If the index incremented above refers to a
-			 * legitamate board type set it here.
-			 */
-			if (index < EPCA_NUM_TYPES)
-				board.type = loop;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_TYPE;
-				return;
-			}
-			last = index;
-			break;
-
-		case 3:
-			len = strlen(str);
-			if (strncmp("Disable", str, len) == 0)
-				board.altpin = 0;
-			else if (strncmp("Enable", str, len) == 0)
-				board.altpin = 1;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_ALTPIN;
-				return;
-			}
-			last = index;
-			break;
-
-		case 4:
-			t2 = str;
-			while (isdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_NUM_PORTS;
-				return;
-			}
-
-			/*
-			 * There is not a man page for simple_strtoul but the
-			 * code can be found in vsprintf.c. The first argument
-			 * is the string to translate (To an unsigned long
-			 * obviously), the second argument can be the address
-			 * of any character variable or a NULL. If a variable
-			 * is given, the end pointer of the string will be
-			 * stored in that variable; if a NULL is given the end
-			 * pointer will not be returned. The last argument is
-			 * the base to use. If a 0 is indicated, the routine
-			 * will attempt to determine the proper base by looking
-			 * at the values prefix (A '0' for octal, a 'x' for
-			 * hex, etc ... If a value is given it will use that
-			 * value as the base.
-			 */
-			board.numports = simple_strtoul(str, NULL, 0);
-			nbdevs += board.numports;
-			last = index;
-			break;
-
-		case 5:
-			t2 = str;
-			while (isxdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_PORT_BASE;
-				return;
-			}
-
-			board.port = simple_strtoul(str, NULL, 16);
-			last = index;
-			break;
-
-		case 6:
-			t2 = str;
-			while (isxdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_MEM_BASE;
-				return;
-			}
-			board.membase = simple_strtoul(str, NULL, 16);
-			last = index;
-			break;
-		default:
-			printk(KERN_ERR "epca: Too many string parms\n");
-			return;
-		}
-		str = temp;
-	} /* End while there is a string arg */
-
-	if (last < 6) {
-		printk(KERN_ERR "epca: Insufficient parms specified\n");
-		return;
-	}
-
-	/* I should REALLY validate the stuff here */
-	/* Copies our local copy of board into boards */
-	memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
-	/* Does this get called once per lilo arg are what ? */
-	printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
-		num_cards, board_desc[board.type],
-		board.numports, (int)board.port, (unsigned int) board.membase);
-	num_cards++;
-}
-
-static int __init epca_real_setup(char *str)
-{
-	int ints[11];
-
-	epca_setup(get_options(str, 11, ints), ints);
-	return 1;
-}
-
-__setup("digiepca", epca_real_setup);
-#endif
-
-enum epic_board_types {
-	brd_xr = 0,
-	brd_xem,
-	brd_cx,
-	brd_xrj,
-};
-
-/* indexed directly by epic_board_types enum */
-static struct {
-	unsigned char board_type;
-	unsigned bar_idx;		/* PCI base address region */
-} epca_info_tbl[] = {
-	{ PCIXR, 0, },
-	{ PCIXEM, 0, },
-	{ PCICX, 0, },
-	{ PCIXRJ, 2, },
-};
-
-static int __devinit epca_init_one(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	static int board_num = -1;
-	int board_idx, info_idx = ent->driver_data;
-	unsigned long addr;
-
-	if (pci_enable_device(pdev))
-		return -EIO;
-
-	board_num++;
-	board_idx = board_num + num_cards;
-	if (board_idx >= MAXBOARDS)
-		goto err_out;
-
-	addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
-	if (!addr) {
-		printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
-			epca_info_tbl[info_idx].bar_idx);
-		goto err_out;
-	}
-
-	boards[board_idx].status = ENABLED;
-	boards[board_idx].type = epca_info_tbl[info_idx].board_type;
-	boards[board_idx].numports = 0x0;
-	boards[board_idx].port = addr + PCI_IO_OFFSET;
-	boards[board_idx].membase = addr;
-
-	if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
-		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out;
-	}
-
-	boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
-								0x200000);
-	if (!boards[board_idx].re_map_port) {
-		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out_free_pciio;
-	}
-
-	if (!request_mem_region(addr, 0x200000, "epca")) {
-		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
-			0x200000, addr);
-		goto err_out_free_iounmap;
-	}
-
-	boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
-	if (!boards[board_idx].re_map_membase) {
-		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out_free_memregion;
-	}
-
-	/*
-	 * I don't know what the below does, but the hardware guys say its
-	 * required on everything except PLX (In this case XRJ).
-	 */
-	if (info_idx != brd_xrj) {
-		pci_write_config_byte(pdev, 0x40, 0);
-		pci_write_config_byte(pdev, 0x46, 0);
-	}
-
-	return 0;
-
-err_out_free_memregion:
-	release_mem_region(addr, 0x200000);
-err_out_free_iounmap:
-	iounmap(boards[board_idx].re_map_port);
-err_out_free_pciio:
-	release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
-err_out:
-	return -ENODEV;
-}
-
-
-static struct pci_device_id epca_pci_tbl[] = {
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
-
-static int __init init_PCI(void)
-{
-	memset(&epca_driver, 0, sizeof(epca_driver));
-	epca_driver.name = "epca";
-	epca_driver.id_table = epca_pci_tbl;
-	epca_driver.probe = epca_init_one;
-
-	return pci_register_driver(&epca_driver);
-}
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/epca.h b/drivers/char/epca.h
deleted file mode 100644
index d414bf2..0000000
--- a/drivers/char/epca.h
+++ /dev/null
@@ -1,158 +0,0 @@
-#define XEMPORTS    0xC02
-#define XEPORTS     0xC22
-
-#define MAX_ALLOC   0x100
-
-#define MAXBOARDS   12
-#define FEPCODESEG  0x0200L
-#define FEPCODE     0x2000L
-#define BIOSCODE    0xf800L
-
-#define MISCGLOBAL  0x0C00L
-#define NPORT       0x0C22L
-#define MBOX        0x0C40L
-#define PORTBASE    0x0C90L
-
-/* Begin code defines used for epca_setup */
-
-#define INVALID_BOARD_TYPE   0x1
-#define INVALID_NUM_PORTS    0x2
-#define INVALID_MEM_BASE     0x4
-#define INVALID_PORT_BASE    0x8
-#define INVALID_BOARD_STATUS 0x10
-#define INVALID_ALTPIN       0x20
-
-/* End code defines used for epca_setup */
-
-
-#define FEPCLR      0x00
-#define FEPMEM      0x02
-#define FEPRST      0x04
-#define FEPINT      0x08
-#define	FEPMASK     0x0e
-#define	FEPWIN      0x80
-
-#define PCXE    0
-#define PCXEVE  1
-#define PCXEM   2   
-#define EISAXEM 3
-#define PC64XE  4
-#define PCXI    5
-#define PCIXEM  7
-#define PCICX   8
-#define PCIXR   9
-#define PCIXRJ  10
-#define EPCA_NUM_TYPES 6
-
-
-static char *board_desc[] = 
-{
-	"PC/Xe",
-	"PC/Xeve",
-	"PC/Xem",
-	"EISA/Xem",
-	"PC/64Xe",
-	"PC/Xi",
-	"unknown",
-	"PCI/Xem",
-	"PCI/CX",
-	"PCI/Xr",
-	"PCI/Xrj",
-};
-
-#define STARTC      021
-#define STOPC       023
-#define IAIXON      0x2000
-
-
-#define TXSTOPPED  0x1
-#define LOWWAIT    0x2
-#define EMPTYWAIT  0x4
-#define RXSTOPPED  0x8
-#define TXBUSY     0x10
-
-#define DISABLED   0
-#define ENABLED    1
-#define OFF        0
-#define ON         1
-
-#define FEPTIMEOUT 200000  
-#define SERIAL_TYPE_INFO    3
-#define EPCA_EVENT_HANGUP   1
-#define EPCA_MAGIC          0x5c6df104L
-
-struct channel 
-{
-	long   magic;
-	struct tty_port port;
-	unsigned char boardnum;
-	unsigned char channelnum;
-	unsigned char omodem;         /* FEP output modem status     */
-	unsigned char imodem;         /* FEP input modem status      */
-	unsigned char modemfake;      /* Modem values to be forced   */
-	unsigned char modem;          /* Force values                */
-	unsigned char hflow;
-	unsigned char dsr;
-	unsigned char dcd;
-	unsigned char m_rts ; 		/* The bits used in whatever FEP */
-	unsigned char m_dcd ;		/* is indiginous to this board to */
-	unsigned char m_dsr ;		/* represent each of the physical */
-	unsigned char m_cts ;		/* handshake lines */
-	unsigned char m_ri ;
-	unsigned char m_dtr ;
-	unsigned char stopc;
-	unsigned char startc;
-	unsigned char stopca;
-	unsigned char startca;
-	unsigned char fepstopc;
-	unsigned char fepstartc;
-	unsigned char fepstopca;
-	unsigned char fepstartca;
-	unsigned char txwin;
-	unsigned char rxwin;
-	unsigned short fepiflag;
-	unsigned short fepcflag;
-	unsigned short fepoflag;
-	unsigned short txbufhead;
-	unsigned short txbufsize;
-	unsigned short rxbufhead;
-	unsigned short rxbufsize;
-	int    close_delay;
-	unsigned long  event;
-	uint   dev;
-	unsigned long  statusflags;
-	unsigned long  c_iflag;
-	unsigned long  c_cflag;
-	unsigned long  c_lflag;
-	unsigned long  c_oflag;
-	unsigned char __iomem *txptr;
-	unsigned char __iomem *rxptr;
-	struct board_info           *board;
-	struct board_chan	    __iomem *brdchan;
-	struct digi_struct          digiext;
-	struct work_struct          tqueue;
-	struct global_data 	    __iomem *mailbox;
-};
-
-struct board_info	
-{
-	unsigned char status;
-	unsigned char type;
-	unsigned char altpin;
-	unsigned short numports;
-	unsigned long port;
-	unsigned long membase;
-	void __iomem *re_map_port;
-	void __iomem *re_map_membase;
-	unsigned long  memory_seg;
-	void ( * memwinon )	(struct board_info *, unsigned int) ;
-	void ( * memwinoff ) 	(struct board_info *, unsigned int) ;
-	void ( * globalwinon )	(struct channel *) ;
-	void ( * txwinon ) 	(struct channel *) ;
-	void ( * rxwinon )	(struct channel *) ;
-	void ( * memoff )	(struct channel *) ;
-	void ( * assertgwinon )	(struct channel *) ;
-	void ( * assertmemoff )	(struct channel *) ;
-	unsigned char poller_inhibited ;
-};
-
diff --git a/drivers/char/epcaconfig.h b/drivers/char/epcaconfig.h
deleted file mode 100644
index 55dec06..0000000
--- a/drivers/char/epcaconfig.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#define NUMCARDS 0
-#define NBDEVS 0
-
-struct board_info static_boards[NUMCARDS]={
-};
-
-/* DO NOT HAND EDIT THIS FILE! */
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
deleted file mode 100644
index 5954ee1..0000000
--- a/drivers/char/generic_serial.c
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- *  generic_serial.c
- *
- *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
- *
- *  written for the SX serial driver.
- *     Contains the code that should be shared over all the serial drivers.
- *
- *  Credit for the idea to do it this way might go to Alan Cox. 
- *
- *
- *  Version 0.1 -- December, 1998. Initial version.
- *  Version 0.2 -- March, 1999.    Some more routines. Bugfixes. Etc.
- *  Version 0.5 -- August, 1999.   Some more fixes. Reformat for Linus.
- *
- *  BitWizard is actively maintaining this file. We sometimes find
- *  that someone submitted changes to this file. We really appreciate
- *  your help, but please submit changes through us. We're doing our
- *  best to be responsive.  -- REW
- * */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/mm.h>
-#include <linux/generic_serial.h>
-#include <linux/interrupt.h>
-#include <linux/tty_flip.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <asm/uaccess.h>
-
-#define DEBUG 
-
-static int gs_debug;
-
-#ifdef DEBUG
-#define gs_dprintk(f, str...) if (gs_debug & f) printk (str)
-#else
-#define gs_dprintk(f, str...) /* nothing */
-#endif
-
-#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__)
-#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __func__)
-
-#define RS_EVENT_WRITE_WAKEUP	1
-
-module_param(gs_debug, int, 0644);
-
-
-int gs_put_char(struct tty_struct * tty, unsigned char ch)
-{
-	struct gs_port *port;
-
-	func_enter (); 
-
-	port = tty->driver_data;
-
-	if (!port) return 0;
-
-	if (! (port->port.flags & ASYNC_INITIALIZED)) return 0;
-
-	/* Take a lock on the serial tranmit buffer! */
-	mutex_lock(& port->port_write_mutex);
-
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
-		mutex_unlock(&port->port_write_mutex);
-		return 0;
-	}
-
-	port->xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;  /* Characters in buffer */
-
-	mutex_unlock(&port->port_write_mutex);
-	func_exit ();
-	return 1;
-}
-
-
-/*
-> Problems to take into account are:
->       -1- Interrupts that empty part of the buffer.
->       -2- page faults on the access to userspace. 
->       -3- Other processes that are also trying to do a "write". 
-*/
-
-int gs_write(struct tty_struct * tty, 
-                    const unsigned char *buf, int count)
-{
-	struct gs_port *port;
-	int c, total = 0;
-	int t;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return 0;
-
-	if (! (port->port.flags & ASYNC_INITIALIZED))
-		return 0;
-
-	/* get exclusive "write" access to this port (problem 3) */
-	/* This is not a spinlock because we can have a disk access (page 
-		 fault) in copy_from_user */
-	mutex_lock(& port->port_write_mutex);
-
-	while (1) {
-
-		c = count;
- 
-		/* This is safe because we "OWN" the "head". Noone else can 
-		   change the "head": we own the port_write_mutex. */
-		/* Don't overrun the end of the buffer */
-		t = SERIAL_XMIT_SIZE - port->xmit_head;
-		if (t < c) c = t;
- 
-		/* This is safe because the xmit_cnt can only decrease. This 
-		   would increase "t", so we might copy too little chars. */
-		/* Don't copy past the "head" of the buffer */
-		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
-		if (t < c) c = t;
- 
-		/* Can't copy more? break out! */
-		if (c <= 0) break;
-
-		memcpy (port->xmit_buf + port->xmit_head, buf, c);
-
-		port -> xmit_cnt += c;
-		port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1);
-		buf += c;
-		count -= c;
-		total += c;
-	}
-	mutex_unlock(& port->port_write_mutex);
-
-	gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", 
-	            (port->port.flags & GS_TX_INTEN)?"enabled": "disabled");
-
-	if (port->xmit_cnt && 
-	    !tty->stopped && 
-	    !tty->hw_stopped &&
-	    !(port->port.flags & GS_TX_INTEN)) {
-		port->port.flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-	return total;
-}
-
-
-
-int gs_write_room(struct tty_struct * tty)
-{
-	struct gs_port *port = tty->driver_data;
-	int ret;
-
-	func_enter ();
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	func_exit ();
-	return ret;
-}
-
-
-int gs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port = tty->driver_data;
-	func_enter ();
-
-	func_exit ();
-	return port->xmit_cnt;
-}
-
-
-static int gs_real_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port->rd) return 0;
-	if (!port->rd->chars_in_buffer) return 0;
-
-	func_exit ();
-	return port->xmit_cnt + port->rd->chars_in_buffer (port);
-}
-
-
-static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) 
-{
-	struct gs_port *port = ptr;
-	unsigned long end_jiffies;
-	int jiffies_to_transmit, charsleft = 0, rv = 0;
-	int rcib;
-
-	func_enter();
-
-	gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port);
-	if (port) {
-		gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", 
-		port->xmit_cnt, port->xmit_buf, port->port.tty);
-	}
-
-	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
-		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
-		func_exit();
-		return -EINVAL;  /* This is an error which we don't know how to handle. */
-	}
-
-	rcib = gs_real_chars_in_buffer(port->port.tty);
-
-	if(rcib <= 0) {
-		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
-		func_exit();
-		return rv;
-	}
-	/* stop trying: now + twice the time it would normally take +  seconds */
-	if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT;
-	end_jiffies  = jiffies; 
-	if (timeout !=  MAX_SCHEDULE_TIMEOUT)
-		end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0;
-	end_jiffies += timeout;
-
-	gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", 
-		    jiffies, end_jiffies, end_jiffies-jiffies); 
-
-	/* the expression is actually jiffies < end_jiffies, but that won't
-	   work around the wraparound. Tricky eh? */
-	while ((charsleft = gs_real_chars_in_buffer (port->port.tty)) &&
-	        time_after (end_jiffies, jiffies)) {
-		/* Units check: 
-		   chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies!
-		   check! */
-
-		charsleft += 16; /* Allow 16 chars more to be transmitted ... */
-		jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0;
-		/*                                ^^^ Round up.... */
-		if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1;
-
-		gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies "
-			    "(%d chars).\n", jiffies_to_transmit, charsleft); 
-
-		msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit));
-		if (signal_pending (current)) {
-			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
-			rv = -EINTR;
-			break;
-		}
-	}
-
-	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
-	set_current_state (TASK_RUNNING);
-
-	func_exit();
-	return rv;
-}
-
-
-
-void gs_flush_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	unsigned long flags;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	/* XXX Would the write semaphore do? */
-	spin_lock_irqsave (&port->driver_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore (&port->driver_lock, flags);
-
-	tty_wakeup(tty);
-	func_exit ();
-}
-
-
-void gs_flush_chars(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !port->xmit_buf) {
-		func_exit ();
-		return;
-	}
-
-	/* Beats me -- REW */
-	port->port.flags |= GS_TX_INTEN;
-	port->rd->enable_tx_interrupts (port);
-	func_exit ();
-}
-
-
-void gs_stop(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt && 
-	    port->xmit_buf && 
-	    (port->port.flags & GS_TX_INTEN) ) {
-		port->port.flags &= ~GS_TX_INTEN;
-		port->rd->disable_tx_interrupts (port);
-	}
-	func_exit ();
-}
-
-
-void gs_start(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt && 
-	    port->xmit_buf && 
-	    !(port->port.flags & GS_TX_INTEN) ) {
-		port->port.flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-}
-
-
-static void gs_shutdown_port (struct gs_port *port)
-{
-	unsigned long flags;
-
-	func_enter();
-	
-	if (!port) return;
-	
-	if (!(port->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}
-
-	if (port->port.tty)
-		set_bit(TTY_IO_ERROR, &port->port.tty->flags);
-
-	port->rd->shutdown_port (port);
-
-	port->port.flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-
-	func_exit();
-}
-
-
-void gs_hangup(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	unsigned long flags;
-
-	func_enter ();
-
-	port = tty->driver_data;
-	tty = port->port.tty;
-	if (!tty) 
-		return;
-
-	gs_shutdown_port (port);
-	spin_lock_irqsave(&port->port.lock, flags);
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
-	port->port.tty = NULL;
-	port->port.count = 0;
-	spin_unlock_irqrestore(&port->port.lock, flags);
-
-	wake_up_interruptible(&port->port.open_wait);
-	func_exit ();
-}
-
-
-int gs_block_til_ready(void *port_, struct file * filp)
-{
-	struct gs_port *gp = port_;
-	struct tty_port *port = &gp->port;
-	DECLARE_WAITQUEUE(wait, current);
-	int    retval;
-	int    do_clocal = 0;
-	int    CD;
-	struct tty_struct *tty;
-	unsigned long flags;
-
-	func_enter ();
-
-	if (!port) return 0;
-
-	tty = port->tty;
-
-	gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->close_wait);
-		if (port->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-	}
-
-	gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); 
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); 
- 
-	if (C_CLOCAL(tty))
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-
-	add_wait_queue(&port->open_wait, &wait);
-
-	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		port->count--;
-	}
-	port->blocked_open++;
-	spin_unlock_irqrestore(&port->lock, flags);
-	while (1) {
-		CD = tty_port_carrier_raised(port);
-		gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
-		set_current_state (TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->flags & ASYNC_INITIALIZED)) {
-			if (port->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-			break;
-		}
-		if (!(port->flags & ASYNC_CLOSING) &&
-		    (do_clocal || CD))
-			break;
-		gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", 
-		(int)signal_pending (current), *(long*)(&current->blocked)); 
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		schedule();
-	}
-	gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
-		    port->blocked_open);
-	set_current_state (TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-	
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		port->count++;
-	}
-	port->blocked_open--;
-	if (retval == 0)
-        	port->flags |= ASYNC_NORMAL_ACTIVE;
-	spin_unlock_irqrestore(&port->lock, flags);
-	func_exit ();
-	return retval;
-}			 
-
-
-void gs_close(struct tty_struct * tty, struct file * filp)
-{
-	unsigned long flags;
-	struct gs_port *port;
-	
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (!port->port.tty) {
-		/* This seems to happen when this is called from vhangup. */
-		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->port.tty is NULL\n");
-		port->port.tty = tty;
-	}
-
-	spin_lock_irqsave(&port->port.lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&port->port.lock, flags);
-		if (port->rd->hungup)
-			port->rd->hungup (port);
-		func_exit ();
-		return;
-	}
-
-	if ((tty->count == 1) && (port->port.count != 1)) {
-		printk(KERN_ERR "gs: gs_close port %p: bad port count;"
-		       " tty->count is 1, port count is %d\n", port, port->port.count);
-		port->port.count = 1;
-	}
-	if (--port->port.count < 0) {
-		printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->port.count);
-		port->port.count = 0;
-	}
-
-	if (port->port.count) {
-		gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
-		spin_unlock_irqrestore(&port->port.lock, flags);
-		func_exit ();
-		return;
-	}
-	port->port.flags |= ASYNC_CLOSING;
-
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	/* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-	   tty_wait_until_sent(tty, port->closing_wait); */
-
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-	port->rd->disable_rx_interrupts (port);
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	spin_unlock_irqrestore(&port->port.lock, flags);
-
-	/* close has no way of returning "EINTR", so discard return value */
-	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		gs_wait_tx_flushed (port, port->closing_wait);
-
-	port->port.flags &= ~GS_ACTIVE;
-
-	gs_flush_buffer(tty);
-
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-	port->event = 0;
-	port->rd->close (port);
-	port->rd->shutdown_port (port);
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-
-	spin_lock_irqsave(&port->port.lock, flags);
-	port->port.tty = NULL;
-
-	if (port->port.blocked_open) {
-		if (port->close_delay) {
-			spin_unlock_irqrestore(&port->port.lock, flags);
-			msleep_interruptible(jiffies_to_msecs(port->close_delay));
-			spin_lock_irqsave(&port->port.lock, flags);
-		}
-		wake_up_interruptible(&port->port.open_wait);
-	}
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
-	spin_unlock_irqrestore(&port->port.lock, flags);
-	wake_up_interruptible(&port->port.close_wait);
-
-	func_exit ();
-}
-
-
-void gs_set_termios (struct tty_struct * tty, 
-                     struct ktermios * old_termios)
-{
-	struct gs_port *port;
-	int baudrate, tmp, rv;
-	struct ktermios *tiosp;
-
-	func_enter();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-	if (!port->port.tty) {
-		/* This seems to happen when this is called after gs_close. */
-		gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->port.tty is NULL\n");
-		port->port.tty = tty;
-	}
-
-
-	tiosp = tty->termios;
-
-	if (gs_debug & GS_DEBUG_TERMIOS) {
-		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
-	}
-
-	if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
-		if(tiosp->c_iflag != old_termios->c_iflag)  printk("c_iflag changed\n");
-		if(tiosp->c_oflag != old_termios->c_oflag)  printk("c_oflag changed\n");
-		if(tiosp->c_cflag != old_termios->c_cflag)  printk("c_cflag changed\n");
-		if(tiosp->c_lflag != old_termios->c_lflag)  printk("c_lflag changed\n");
-		if(tiosp->c_line  != old_termios->c_line)   printk("c_line changed\n");
-		if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
-	}
-
-	baudrate = tty_get_baud_rate(tty);
-
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if (     (port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (port->baud_base / port->custom_divisor);
-	}
-
-	/* I recommend using THIS instead of the mess in termios (and
-	   duplicating the above code). Next we should create a clean
-	   interface towards this variable. If your card supports arbitrary
-	   baud rates, (e.g. CD1400 or 16550 based cards) then everything
-	   will be very easy..... */
-	port->baud = baudrate;
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	/* Baudrate/10 is cps. Divide by HZ to get chars per tick. */
-	tmp = (baudrate / 10 / HZ) * 2;			 
-
-	if (tmp <                 0) tmp = 0;
-	if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1;
-
-	port->wakeup_chars = tmp;
-
-	/* We should really wait for the characters to be all sent before
-	   changing the settings. -- CAL */
-	rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
-	if (rv < 0) return /* rv */;
-
-	rv = port->rd->set_real_termios(port);
-	if (rv < 0) return /* rv */;
-
-	if ((!old_termios || 
-	     (old_termios->c_cflag & CRTSCTS)) &&
-	    !(      tiosp->c_cflag & CRTSCTS)) {
-		tty->stopped = 0;
-		gs_start(tty);
-	}
-
-#ifdef tytso_patch_94Nov25_1726
-	/* This "makes sense", Why is it commented out? */
-
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&port->gs.open_wait);
-#endif
-
-	func_exit();
-	return /* 0 */;
-}
-
-
-
-/* Must be called with interrupts enabled */
-int gs_init_port(struct gs_port *port)
-{
-	unsigned long flags;
-
-	func_enter ();
-
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		func_exit ();
-		return 0;
-	}
-	if (!port->xmit_buf) {
-		/* We may sleep in get_zeroed_page() */
-		unsigned long tmp;
-
-		tmp = get_zeroed_page(GFP_KERNEL);
-		spin_lock_irqsave (&port->driver_lock, flags);
-		if (port->xmit_buf) 
-			free_page (tmp);
-		else
-			port->xmit_buf = (unsigned char *) tmp;
-		spin_unlock_irqrestore(&port->driver_lock, flags);
-		if (!port->xmit_buf) {
-			func_exit ();
-			return -ENOMEM;
-		}
-	}
-
-	spin_lock_irqsave (&port->driver_lock, flags);
-	if (port->port.tty)
-		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
-	mutex_init(&port->port_write_mutex);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	gs_set_termios(port->port.tty, NULL);
-	spin_lock_irqsave (&port->driver_lock, flags);
-	port->port.flags |= ASYNC_INITIALIZED;
-	port->port.flags &= ~GS_TX_INTEN;
-
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	func_exit ();
-	return 0;
-}
-
-
-int gs_setserial(struct gs_port *port, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return(-EFAULT);
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != port->baud_base) ||
-		    (sio.close_delay != port->close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK)))
-			return(-EPERM);
-	} 
-
-	port->port.flags = (port->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-  
-	port->baud_base = sio.baud_base;
-	port->close_delay = sio.close_delay;
-	port->closing_wait = sio.closing_wait;
-	port->custom_divisor = sio.custom_divisor;
-
-	gs_set_termios (port->port.tty, NULL);
-
-	return 0;
-}
-
-
-/*****************************************************************************/
-
-/*
- *      Generate the serial struct info.
- */
-
-int gs_getserial(struct gs_port *port, struct serial_struct __user *sp)
-{
-	struct serial_struct    sio;
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-	sio.flags = port->port.flags;
-	sio.baud_base = port->baud_base;
-	sio.close_delay = port->close_delay;
-	sio.closing_wait = port->closing_wait;
-	sio.custom_divisor = port->custom_divisor;
-	sio.hub6 = 0;
-
-	/* If you want you can override these. */
-	sio.type = PORT_UNKNOWN;
-	sio.xmit_fifo_size = -1;
-	sio.line = -1;
-	sio.port = -1;
-	sio.irq = -1;
-
-	if (port->rd->getserial)
-		port->rd->getserial (port, &sio);
-
-	if (copy_to_user(sp, &sio, sizeof(struct serial_struct)))
-		return -EFAULT;
-	return 0;
-
-}
-
-
-void gs_got_break(struct gs_port *port)
-{
-	func_enter ();
-
-	tty_insert_flip_char(port->port.tty, 0, TTY_BREAK);
-	tty_schedule_flip(port->port.tty);
-	if (port->port.flags & ASYNC_SAK) {
-		do_SAK (port->port.tty);
-	}
-
-	func_exit ();
-}
-
-
-EXPORT_SYMBOL(gs_put_char);
-EXPORT_SYMBOL(gs_write);
-EXPORT_SYMBOL(gs_write_room);
-EXPORT_SYMBOL(gs_chars_in_buffer);
-EXPORT_SYMBOL(gs_flush_buffer);
-EXPORT_SYMBOL(gs_flush_chars);
-EXPORT_SYMBOL(gs_stop);
-EXPORT_SYMBOL(gs_start);
-EXPORT_SYMBOL(gs_hangup);
-EXPORT_SYMBOL(gs_block_til_ready);
-EXPORT_SYMBOL(gs_close);
-EXPORT_SYMBOL(gs_set_termios);
-EXPORT_SYMBOL(gs_init_port);
-EXPORT_SYMBOL(gs_setserial);
-EXPORT_SYMBOL(gs_getserial);
-EXPORT_SYMBOL(gs_got_break);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index d31483c..beecd1c 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -198,3 +198,15 @@ config HW_RANDOM_NOMADIK
 	  module will be called nomadik-rng.
 
 	  If unsure, say Y.
+
+config HW_RANDOM_PICOXCELL
+	tristate "Picochip picoXcell true random number generator support"
+	depends on HW_RANDOM && ARCH_PICOXCELL && PICOXCELL_PC3X3
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Picochip PC3x3 and later devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called picoxcell-rng.
+
+	  If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 4273308..3db4eb8 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
 obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
 obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
 obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
+obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index a3f5e38..43ac619 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -619,15 +619,17 @@ static void __devinit n2rng_driver_version(void)
 		pr_info("%s", version);
 }
 
-static int __devinit n2rng_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit n2rng_probe(struct platform_device *op)
 {
-	int victoria_falls = (match->data != NULL);
+	int victoria_falls;
 	int err = -ENOMEM;
 	struct n2rng *np;
 
-	n2rng_driver_version();
+	if (!op->dev.of_match)
+		return -EINVAL;
+	victoria_falls = (op->dev.of_match->data != NULL);
 
+	n2rng_driver_version();
 	np = kzalloc(sizeof(*np), GFP_KERNEL);
 	if (!np)
 		goto out;
@@ -750,7 +752,7 @@ static const struct of_device_id n2rng_match[] = {
 };
 MODULE_DEVICE_TABLE(of, n2rng_match);
 
-static struct of_platform_driver n2rng_driver = {
+static struct platform_driver n2rng_driver = {
 	.driver = {
 		.name = "n2rng",
 		.owner = THIS_MODULE,
@@ -762,12 +764,12 @@ static struct of_platform_driver n2rng_driver = {
 
 static int __init n2rng_init(void)
 {
-	return of_register_platform_driver(&n2rng_driver);
+	return platform_driver_register(&n2rng_driver);
 }
 
 static void __exit n2rng_exit(void)
 {
-	of_unregister_platform_driver(&n2rng_driver);
+	platform_driver_unregister(&n2rng_driver);
 }
 
 module_init(n2rng_init);
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
index a348c7e..dd1d143 100644
--- a/drivers/char/hw_random/nomadik-rng.c
+++ b/drivers/char/hw_random/nomadik-rng.c
@@ -39,7 +39,7 @@ static struct hwrng nmk_rng = {
 	.read		= nmk_rng_read,
 };
 
-static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id)
+static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	void __iomem *base;
 	int ret;
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 06aad08..2cc755a 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -91,7 +91,7 @@ static struct hwrng omap_rng_ops = {
 
 static int __devinit omap_rng_probe(struct platform_device *pdev)
 {
-	struct resource *res, *mem;
+	struct resource *res;
 	int ret;
 
 	/*
@@ -116,14 +116,12 @@ static int __devinit omap_rng_probe(struct platform_device *pdev)
 	if (!res)
 		return -ENOENT;
 
-	mem = request_mem_region(res->start, resource_size(res),
-				 pdev->name);
-	if (mem == NULL) {
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
 		ret = -EBUSY;
 		goto err_region;
 	}
 
-	dev_set_drvdata(&pdev->dev, mem);
+	dev_set_drvdata(&pdev->dev, res);
 	rng_base = ioremap(res->start, resource_size(res));
 	if (!rng_base) {
 		ret = -ENOMEM;
@@ -146,7 +144,7 @@ err_register:
 	iounmap(rng_base);
 	rng_base = NULL;
 err_ioremap:
-	release_resource(mem);
+	release_mem_region(res->start, resource_size(res));
 err_region:
 	if (cpu_is_omap24xx()) {
 		clk_disable(rng_ick);
@@ -157,7 +155,7 @@ err_region:
 
 static int __exit omap_rng_remove(struct platform_device *pdev)
 {
-	struct resource *mem = dev_get_drvdata(&pdev->dev);
+	struct resource *res = dev_get_drvdata(&pdev->dev);
 
 	hwrng_unregister(&omap_rng_ops);
 
@@ -170,7 +168,7 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
 		clk_put(rng_ick);
 	}
 
-	release_resource(mem);
+	release_mem_region(res->start, resource_size(res));
 	rng_base = NULL;
 
 	return 0;
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index a31c830..1d50481 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -94,8 +94,7 @@ static struct hwrng pasemi_rng = {
 	.data_read	= pasemi_rng_data_read,
 };
 
-static int __devinit rng_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit rng_probe(struct platform_device *ofdev)
 {
 	void __iomem *rng_regs;
 	struct device_node *rng_np = ofdev->dev.of_node;
@@ -139,7 +138,7 @@ static struct of_device_id rng_match[] = {
 	{ },
 };
 
-static struct of_platform_driver rng_driver = {
+static struct platform_driver rng_driver = {
 	.driver = {
 		.name = "pasemi-rng",
 		.owner = THIS_MODULE,
@@ -151,13 +150,13 @@ static struct of_platform_driver rng_driver = {
 
 static int __init rng_init(void)
 {
-	return of_register_platform_driver(&rng_driver);
+	return platform_driver_register(&rng_driver);
 }
 module_init(rng_init);
 
 static void __exit rng_exit(void)
 {
-	of_unregister_platform_driver(&rng_driver);
+	platform_driver_unregister(&rng_driver);
 }
 module_exit(rng_exit);
 
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
new file mode 100644
index 0000000..990d55a
--- /dev/null
+++ b/drivers/char/hw_random/picoxcell-rng.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define DATA_REG_OFFSET		0x0200
+#define CSR_REG_OFFSET		0x0278
+#define CSR_OUT_EMPTY_MASK	(1 << 24)
+#define CSR_FAULT_MASK		(1 << 1)
+#define TRNG_BLOCK_RESET_MASK	(1 << 0)
+#define TAI_REG_OFFSET		0x0380
+
+/*
+ * The maximum amount of time in microseconds to spend waiting for data if the
+ * core wants us to wait.  The TRNG should generate 32 bits every 320ns so a
+ * timeout of 20us seems reasonable.  The TRNG does builtin tests of the data
+ * for randomness so we can't always assume there is data present.
+ */
+#define PICO_TRNG_TIMEOUT		20
+
+static void __iomem *rng_base;
+static struct clk *rng_clk;
+struct device *rng_dev;
+
+static inline u32 picoxcell_trng_read_csr(void)
+{
+	return __raw_readl(rng_base + CSR_REG_OFFSET);
+}
+
+static inline bool picoxcell_trng_is_empty(void)
+{
+	return picoxcell_trng_read_csr() & CSR_OUT_EMPTY_MASK;
+}
+
+/*
+ * Take the random number generator out of reset and make sure the interrupts
+ * are masked. We shouldn't need to get large amounts of random bytes so just
+ * poll the status register. The hardware generates 32 bits every 320ns so we
+ * shouldn't have to wait long enough to warrant waiting for an IRQ.
+ */
+static void picoxcell_trng_start(void)
+{
+	__raw_writel(0, rng_base + TAI_REG_OFFSET);
+	__raw_writel(0, rng_base + CSR_REG_OFFSET);
+}
+
+static void picoxcell_trng_reset(void)
+{
+	__raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + CSR_REG_OFFSET);
+	__raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + TAI_REG_OFFSET);
+	picoxcell_trng_start();
+}
+
+/*
+ * Get some random data from the random number generator. The hw_random core
+ * layer provides us with locking.
+ */
+static int picoxcell_trng_read(struct hwrng *rng, void *buf, size_t max,
+			       bool wait)
+{
+	int i;
+
+	/* Wait for some data to become available. */
+	for (i = 0; i < PICO_TRNG_TIMEOUT && picoxcell_trng_is_empty(); ++i) {
+		if (!wait)
+			return 0;
+
+		udelay(1);
+	}
+
+	if (picoxcell_trng_read_csr() & CSR_FAULT_MASK) {
+		dev_err(rng_dev, "fault detected, resetting TRNG\n");
+		picoxcell_trng_reset();
+		return -EIO;
+	}
+
+	if (i == PICO_TRNG_TIMEOUT)
+		return 0;
+
+	*(u32 *)buf = __raw_readl(rng_base + DATA_REG_OFFSET);
+	return sizeof(u32);
+}
+
+static struct hwrng picoxcell_trng = {
+	.name		= "picoxcell",
+	.read		= picoxcell_trng_read,
+};
+
+static int picoxcell_trng_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!mem) {
+		dev_warn(&pdev->dev, "no memory resource\n");
+		return -ENOMEM;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+				     "picoxcell_trng")) {
+		dev_warn(&pdev->dev, "unable to request io mem\n");
+		return -EBUSY;
+	}
+
+	rng_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!rng_base) {
+		dev_warn(&pdev->dev, "unable to remap io mem\n");
+		return -ENOMEM;
+	}
+
+	rng_clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(rng_clk)) {
+		dev_warn(&pdev->dev, "no clk\n");
+		return PTR_ERR(rng_clk);
+	}
+
+	ret = clk_enable(rng_clk);
+	if (ret) {
+		dev_warn(&pdev->dev, "unable to enable clk\n");
+		goto err_enable;
+	}
+
+	picoxcell_trng_start();
+	ret = hwrng_register(&picoxcell_trng);
+	if (ret)
+		goto err_register;
+
+	rng_dev = &pdev->dev;
+	dev_info(&pdev->dev, "pixoxcell random number generator active\n");
+
+	return 0;
+
+err_register:
+	clk_disable(rng_clk);
+err_enable:
+	clk_put(rng_clk);
+
+	return ret;
+}
+
+static int __devexit picoxcell_trng_remove(struct platform_device *pdev)
+{
+	hwrng_unregister(&picoxcell_trng);
+	clk_disable(rng_clk);
+	clk_put(rng_clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int picoxcell_trng_suspend(struct device *dev)
+{
+	clk_disable(rng_clk);
+
+	return 0;
+}
+
+static int picoxcell_trng_resume(struct device *dev)
+{
+	return clk_enable(rng_clk);
+}
+
+static const struct dev_pm_ops picoxcell_trng_pm_ops = {
+	.suspend	= picoxcell_trng_suspend,
+	.resume		= picoxcell_trng_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver picoxcell_trng_driver = {
+	.probe		= picoxcell_trng_probe,
+	.remove		= __devexit_p(picoxcell_trng_remove),
+	.driver		= {
+		.name	= "picoxcell-trng",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &picoxcell_trng_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init picoxcell_trng_init(void)
+{
+	return platform_driver_register(&picoxcell_trng_driver);
+}
+module_init(picoxcell_trng_init);
+
+static void __exit picoxcell_trng_exit(void)
+{
+	platform_driver_unregister(&picoxcell_trng_driver);
+}
+module_exit(picoxcell_trng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("Picochip picoXcell TRNG driver");
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile
deleted file mode 100644
index 7b78e0d..0000000
--- a/drivers/char/ip2/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the Computone IntelliPort Plus Driver
-#
-
-obj-$(CONFIG_COMPUTONE)         += ip2.o
-
-ip2-y			:= ip2main.o
-
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
deleted file mode 100644
index e7af647..0000000
--- a/drivers/char/ip2/i2cmd.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definition table for In-line and Bypass commands. Applicable
-*                only when the standard loadware is active. (This is included
-*                source code, not a separate compilation module.)
-*
-*******************************************************************************/
-
-//------------------------------------------------------------------------------
-//
-// Revision History:
-//
-// 10 October 1991   MAG First Draft
-//  7 November 1991  MAG Reflects additional commands.
-// 24 February 1992  MAG Additional commands for 1.4.x loadware
-// 11 March 1992     MAG Additional commands
-// 30 March 1992     MAG Additional command: CMD_DSS_NOW
-// 18 May 1992       MAG Discovered commands 39 & 40 must be at the end of a
-//                       packet: affects implementation.
-//------------------------------------------------------------------------------
-
-//************
-//* Includes *
-//************
-
-#include "i2cmd.h"   /* To get some bit-defines */
-
-//------------------------------------------------------------------------------
-// Here is the table of global arrays which represent each type of command
-// supported in the IntelliPort standard loadware. See also i2cmd.h
-// for a more complete explanation of what is going on.
-//------------------------------------------------------------------------------
-
-// Here are the various globals: note that the names are not used except through
-// the macros defined in i2cmd.h. Also note that although they are character
-// arrays here (for extendability) they are cast to structure pointers in the
-// i2cmd.h macros. See i2cmd.h for flags definitions.
-
-//                     Length Flags Command
-static UCHAR ct02[] = { 1, BTH,     0x02                     }; // DTR UP
-static UCHAR ct03[] = { 1, BTH,     0x03                     }; // DTR DN
-static UCHAR ct04[] = { 1, BTH,     0x04                     }; // RTS UP
-static UCHAR ct05[] = { 1, BTH,     0x05                     }; // RTS DN
-static UCHAR ct06[] = { 1, BYP,     0x06                     }; // START FL
-static UCHAR ct07[] = { 2, BTH,     0x07,0                   }; // BAUD
-static UCHAR ct08[] = { 2, BTH,     0x08,0                   }; // BITS
-static UCHAR ct09[] = { 2, BTH,     0x09,0                   }; // STOP
-static UCHAR ct10[] = { 2, BTH,     0x0A,0                   }; // PARITY
-static UCHAR ct11[] = { 2, BTH,     0x0B,0                   }; // XON
-static UCHAR ct12[] = { 2, BTH,     0x0C,0                   }; // XOFF
-static UCHAR ct13[] = { 1, BTH,     0x0D                     }; // STOP FL
-static UCHAR ct14[] = { 1, BYP|VIP, 0x0E                     }; // ACK HOTK
-//static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0                   }; // IRQ SET
-static UCHAR ct16[] = { 2, INL,     0x10,0                   }; // IXONOPTS
-static UCHAR ct17[] = { 2, INL,     0x11,0                   }; // OXONOPTS
-static UCHAR ct18[] = { 1, INL,     0x12                     }; // CTSENAB
-static UCHAR ct19[] = { 1, BTH,     0x13                     }; // CTSDSAB
-static UCHAR ct20[] = { 1, INL,     0x14                     }; // DCDENAB
-static UCHAR ct21[] = { 1, BTH,     0x15                     }; // DCDDSAB
-static UCHAR ct22[] = { 1, BTH,     0x16                     }; // DSRENAB
-static UCHAR ct23[] = { 1, BTH,     0x17                     }; // DSRDSAB
-static UCHAR ct24[] = { 1, BTH,     0x18                     }; // RIENAB
-static UCHAR ct25[] = { 1, BTH,     0x19                     }; // RIDSAB
-static UCHAR ct26[] = { 2, BTH,     0x1A,0                   }; // BRKENAB
-static UCHAR ct27[] = { 1, BTH,     0x1B                     }; // BRKDSAB
-//static UCHAR ct28[]={ 2, BTH,     0x1C,0                   }; // MAXBLOKSIZE
-//static UCHAR ct29[]={ 2, 0,       0x1D,0                   }; // reserved
-static UCHAR ct30[] = { 1, INL,     0x1E                     }; // CTSFLOWENAB
-static UCHAR ct31[] = { 1, INL,     0x1F                     }; // CTSFLOWDSAB
-static UCHAR ct32[] = { 1, INL,     0x20                     }; // RTSFLOWENAB
-static UCHAR ct33[] = { 1, INL,     0x21                     }; // RTSFLOWDSAB
-static UCHAR ct34[] = { 2, BTH,     0x22,0                   }; // ISTRIPMODE
-static UCHAR ct35[] = { 2, BTH|END, 0x23,0                   }; // SENDBREAK
-static UCHAR ct36[] = { 2, BTH,     0x24,0                   }; // SETERRMODE
-//static UCHAR ct36a[]={ 3, INL,    0x24,0,0                 }; // SET_REPLACE
-
-// The following is listed for completeness, but should never be sent directly
-// by user-level code. It is sent only by library routines in response to data
-// movement.
-//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0             }; // FLOW PACKET
-
-// Back to normal
-//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ
-//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0                 }; // OPOSTON
-//static UCHAR ct40[]={ 1, BTH|END, 0x28                     }; // OPOSTOFF
-static UCHAR ct41[] = { 1, BYP,     0x29                     }; // RESUME
-//static UCHAR ct42[]={ 2, BTH,     0x2A,0                   }; // TXBAUD
-//static UCHAR ct43[]={ 2, BTH,     0x2B,0                   }; // RXBAUD
-//static UCHAR ct44[]={ 2, BTH,     0x2C,0                   }; // MS PING
-//static UCHAR ct45[]={ 1, BTH,     0x2D                     }; // HOTENAB
-//static UCHAR ct46[]={ 1, BTH,     0x2E                     }; // HOTDSAB
-//static UCHAR ct47[]={ 7, BTH,     0x2F,0,0,0,0,0,0         }; // UNIX FLAGS
-//static UCHAR ct48[]={ 1, BTH,     0x30                     }; // DSRFLOWENAB
-//static UCHAR ct49[]={ 1, BTH,     0x31                     }; // DSRFLOWDSAB
-//static UCHAR ct50[]={ 1, BTH,     0x32                     }; // DTRFLOWENAB
-//static UCHAR ct51[]={ 1, BTH,     0x33                     }; // DTRFLOWDSAB
-//static UCHAR ct52[]={ 1, BTH,     0x34                     }; // BAUDTABRESET
-//static UCHAR ct53[] = { 3, BTH,     0x35,0,0                 }; // BAUDREMAP
-static UCHAR ct54[] = { 3, BTH,     0x36,0,0                 }; // CUSTOMBAUD1
-static UCHAR ct55[] = { 3, BTH,     0x37,0,0                 }; // CUSTOMBAUD2
-static UCHAR ct56[] = { 2, BTH|END, 0x38,0                   }; // PAUSE
-static UCHAR ct57[] = { 1, BYP,     0x39                     }; // SUSPEND
-static UCHAR ct58[] = { 1, BYP,     0x3A                     }; // UNSUSPEND
-static UCHAR ct59[] = { 2, BTH,     0x3B,0                   }; // PARITYCHK
-static UCHAR ct60[] = { 1, INL|VIP, 0x3C                     }; // BOOKMARKREQ
-//static UCHAR ct61[]={ 2, BTH,     0x3D,0                   }; // INTERNALLOOP
-//static UCHAR ct62[]={ 2, BTH,     0x3E,0                   }; // HOTKTIMEOUT
-static UCHAR ct63[] = { 2, INL,     0x3F,0                   }; // SETTXON
-static UCHAR ct64[] = { 2, INL,     0x40,0                   }; // SETTXOFF
-//static UCHAR ct65[]={ 2, BTH,     0x41,0                   }; // SETAUTORTS
-//static UCHAR ct66[]={ 2, BTH,     0x42,0                   }; // SETHIGHWAT
-//static UCHAR ct67[]={ 2, BYP,     0x43,0                   }; // STARTSELFL
-//static UCHAR ct68[]={ 2, INL,     0x44,0                   }; // ENDSELFL
-//static UCHAR ct69[]={ 1, BYP,     0x45                     }; // HWFLOW_OFF
-//static UCHAR ct70[]={ 1, BTH,     0x46                     }; // ODSRFL_ENAB
-//static UCHAR ct71[]={ 1, BTH,     0x47                     }; // ODSRFL_DSAB
-//static UCHAR ct72[]={ 1, BTH,     0x48                     }; // ODCDFL_ENAB
-//static UCHAR ct73[]={ 1, BTH,     0x49                     }; // ODCDFL_DSAB
-//static UCHAR ct74[]={ 2, BTH,     0x4A,0                   }; // LOADLEVEL
-//static UCHAR ct75[]={ 2, BTH,     0x4B,0                   }; // STATDATA
-//static UCHAR ct76[]={ 1, BYP,     0x4C                     }; // BREAK_ON
-//static UCHAR ct77[]={ 1, BYP,     0x4D                     }; // BREAK_OFF
-//static UCHAR ct78[]={ 1, BYP,     0x4E                     }; // GETFC
-static UCHAR ct79[] = { 2, BYP,     0x4F,0                   }; // XMIT_NOW
-//static UCHAR ct80[]={ 4, BTH,     0x50,0,0,0               }; // DIVISOR_LATCH
-//static UCHAR ct81[]={ 1, BYP,     0x51                     }; // GET_STATUS
-//static UCHAR ct82[]={ 1, BYP,     0x52                     }; // GET_TXCNT
-//static UCHAR ct83[]={ 1, BYP,     0x53                     }; // GET_RXCNT
-//static UCHAR ct84[]={ 1, BYP,     0x54                     }; // GET_BOXIDS
-//static UCHAR ct85[]={10, BYP,     0x55,0,0,0,0,0,0,0,0,0   }; // ENAB_MULT
-//static UCHAR ct86[]={ 2, BTH,     0x56,0                   }; // RCV_ENABLE
-static UCHAR ct87[] = { 1, BYP,     0x57                     }; // HW_TEST
-//static UCHAR ct88[]={ 3, BTH,     0x58,0,0                 }; // RCV_THRESHOLD
-//static UCHAR ct90[]={ 3, BYP,     0x5A,0,0                 }; // Set SILO
-//static UCHAR ct91[]={ 2, BYP,     0x5B,0                   }; // timed break
-
-// Some composite commands as well
-//static UCHAR cc01[]={ 2, BTH,     0x02,0x04                }; // DTR & RTS UP
-//static UCHAR cc02[]={ 2, BTH,     0x03,0x05                }; // DTR & RTS DN
-
-//********
-//* Code *
-//********
-
-//******************************************************************************
-// Function:   i2cmdUnixFlags(iflag, cflag, lflag)
-// Parameters: Unix tty flags
-//
-// Returns:    Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of command 47 and returns a pointer to the
-// appropriate structure.
-//******************************************************************************
-#if 0
-cmdSyntaxPtr
-i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
-{
-	cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47;
-
-	pCM->cmd[1] = (unsigned char)  iflag;
-	pCM->cmd[2] = (unsigned char) (iflag >> 8);
-	pCM->cmd[3] = (unsigned char)  cflag;
-	pCM->cmd[4] = (unsigned char) (cflag >> 8);
-	pCM->cmd[5] = (unsigned char)  lflag;
-	pCM->cmd[6] = (unsigned char) (lflag >> 8);
-	return pCM;
-}
-#endif  /*  0  */
-
-//******************************************************************************
-// Function:   i2cmdBaudDef(which, rate)
-// Parameters: ?
-//
-// Returns:    Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of commands 54 or 55 (according to the
-// argument which), and returns a pointer to the appropriate structure.
-//******************************************************************************
-static cmdSyntaxPtr
-i2cmdBaudDef(int which, unsigned short rate)
-{
-	cmdSyntaxPtr pCM;
-
-	switch(which)
-	{
-	case 1:
-		pCM = (cmdSyntaxPtr) ct54;
-		break;
-	default:
-	case 2:
-		pCM = (cmdSyntaxPtr) ct55;
-		break;
-	}
-	pCM->cmd[1] = (unsigned char) rate;
-	pCM->cmd[2] = (unsigned char) (rate >> 8);
-	return pCM;
-}
-
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h
deleted file mode 100644
index 29277ec..0000000
--- a/drivers/char/ip2/i2cmd.h
+++ /dev/null
@@ -1,630 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions and support for In-line and Bypass commands.
-*                Applicable only when the standard loadware is active.
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 10 October 1991   MAG First Draft
-//  7 November 1991  MAG Reflects some new commands
-// 20 February 1992  MAG CMD_HOTACK corrected: no argument.
-// 24 February 1992  MAG Support added for new commands for 1.4.x loadware.
-// 11 March 1992     MAG Additional commands.
-// 16 March 1992     MAG Additional commands.
-// 30 March 1992     MAG Additional command: CMD_DSS_NOW
-// 18 May   1992     MAG Changed CMD_OPOST
-//
-//------------------------------------------------------------------------------
-#ifndef I2CMD_H      // To prevent multiple includes
-#define I2CMD_H   1
-
-#include "ip2types.h"
-
-// This module is designed to provide a uniform method of sending commands to
-// the board through command packets. The difficulty is, some commands take
-// parameters, others do not. Furthermore, it is often useful to send several
-// commands to the same channel as part of the same packet. (See also i2pack.h.)
-//
-// This module is designed so that the caller should not be responsible for
-// remembering the exact syntax of each command, or at least so that the
-// compiler could check things somewhat. I'll explain as we go...
-//
-// First, a structure which can embody the syntax of each type of command.
-//
-typedef struct _cmdSyntax
-{
-	UCHAR length;   // Number of bytes in the command
-	UCHAR flags;    // Information about the command (see below)
-
-	// The command and its parameters, which may be of arbitrary length. Don't
-	// worry yet how the parameters will be initialized; macros later take care
-	// of it. Also, don't worry about the arbitrary length issue; this structure
-	// is never used to allocate space (see i2cmd.c).
-	UCHAR cmd[2];
-} cmdSyntax, *cmdSyntaxPtr;
-
-// Bit assignments for flags
-
-#define INL 1           // Set if suitable for inline commands
-#define BYP 2           // Set if suitable for bypass commands
-#define BTH (INL|BYP)   // suitable for either!
-#define END 4           // Set if this must be the last command in a block
-#define VIP 8           // Set if this command is special in some way and really
-						// should only be sent from the library-level and not
-						// directly from user-level
-#define VAR 0x10        // This command is of variable length!
-
-// Declarations for the global arrays used to bear the commands and their
-// arguments.
-//
-// Note: Since these are globals and the arguments might change, it is important
-// that the library routine COPY these into buffers from whence they would be
-// sent, rather than merely storing the pointers. In multi-threaded
-// environments, important that the copy should obtain before any context switch
-// is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND
-// MORE THAN ONCE WITH THE SAME PARAMETERS in the same call.
-//
-static UCHAR ct02[];
-static UCHAR ct03[];
-static UCHAR ct04[];
-static UCHAR ct05[];
-static UCHAR ct06[];
-static UCHAR ct07[];
-static UCHAR ct08[];
-static UCHAR ct09[];
-static UCHAR ct10[];
-static UCHAR ct11[];
-static UCHAR ct12[];
-static UCHAR ct13[];
-static UCHAR ct14[];
-static UCHAR ct15[];
-static UCHAR ct16[];
-static UCHAR ct17[];
-static UCHAR ct18[];
-static UCHAR ct19[];
-static UCHAR ct20[];
-static UCHAR ct21[];
-static UCHAR ct22[];
-static UCHAR ct23[];
-static UCHAR ct24[];
-static UCHAR ct25[];
-static UCHAR ct26[];
-static UCHAR ct27[];
-static UCHAR ct28[];
-static UCHAR ct29[];
-static UCHAR ct30[];
-static UCHAR ct31[];
-static UCHAR ct32[];
-static UCHAR ct33[];
-static UCHAR ct34[];
-static UCHAR ct35[];
-static UCHAR ct36[];
-static UCHAR ct36a[];
-static UCHAR ct41[];
-static UCHAR ct42[];
-static UCHAR ct43[];
-static UCHAR ct44[];
-static UCHAR ct45[];
-static UCHAR ct46[];
-static UCHAR ct48[];
-static UCHAR ct49[];
-static UCHAR ct50[];
-static UCHAR ct51[];
-static UCHAR ct52[];
-static UCHAR ct56[];
-static UCHAR ct57[];
-static UCHAR ct58[];
-static UCHAR ct59[];
-static UCHAR ct60[];
-static UCHAR ct61[];
-static UCHAR ct62[];
-static UCHAR ct63[];
-static UCHAR ct64[];
-static UCHAR ct65[];
-static UCHAR ct66[];
-static UCHAR ct67[];
-static UCHAR ct68[];
-static UCHAR ct69[];
-static UCHAR ct70[];
-static UCHAR ct71[];
-static UCHAR ct72[];
-static UCHAR ct73[];
-static UCHAR ct74[];
-static UCHAR ct75[];
-static UCHAR ct76[];
-static UCHAR ct77[];
-static UCHAR ct78[];
-static UCHAR ct79[];
-static UCHAR ct80[];
-static UCHAR ct81[];
-static UCHAR ct82[];
-static UCHAR ct83[];
-static UCHAR ct84[];
-static UCHAR ct85[];
-static UCHAR ct86[];
-static UCHAR ct87[];
-static UCHAR ct88[];
-static UCHAR ct89[];
-static UCHAR ct90[];
-static UCHAR ct91[];
-static UCHAR cc01[];
-static UCHAR cc02[];
-
-// Now, refer to i2cmd.c, and see the character arrays defined there. They are
-// cast here to cmdSyntaxPtr.
-//
-// There are library functions for issuing bypass or inline commands. These
-// functions take one or more arguments of the type cmdSyntaxPtr. The routine
-// then can figure out how long each command is supposed to be and easily add it
-// to the list.
-//
-// For ease of use, we define manifests which return pointers to appropriate
-// cmdSyntaxPtr things. But some commands also take arguments. If a single
-// argument is used, we define a macro which performs the single assignment and
-// (through the expedient of a comma expression) references the appropriate
-// pointer. For commands requiring several arguments, we actually define a
-// function to perform the assignments.
-
-#define CMD_DTRUP	(cmdSyntaxPtr)(ct02)	// Raise DTR
-#define CMD_DTRDN	(cmdSyntaxPtr)(ct03)	// Lower DTR
-#define CMD_RTSUP	(cmdSyntaxPtr)(ct04)	// Raise RTS
-#define CMD_RTSDN	(cmdSyntaxPtr)(ct05)	// Lower RTS
-#define CMD_STARTFL	(cmdSyntaxPtr)(ct06)	// Start Flushing Data
-
-#define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01)	// Raise DTR and RTS
-#define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02)	// Lower DTR and RTS
-
-// Set Baud Rate for transmit and receive
-#define CMD_SETBAUD(arg) \
-	(((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07))
-
-#define CBR_50       1
-#define CBR_75       2
-#define CBR_110      3
-#define CBR_134      4
-#define CBR_150      5
-#define CBR_200      6
-#define CBR_300      7
-#define CBR_600      8
-#define CBR_1200     9
-#define CBR_1800     10
-#define CBR_2400     11
-#define CBR_4800     12
-#define CBR_9600     13
-#define CBR_19200    14
-#define CBR_38400    15
-#define CBR_2000     16
-#define CBR_3600     17
-#define CBR_7200     18
-#define CBR_56000    19
-#define CBR_57600    20
-#define CBR_64000    21
-#define CBR_76800    22
-#define CBR_115200   23
-#define CBR_C1       24    // Custom baud rate 1
-#define CBR_C2       25    // Custom baud rate 2
-#define CBR_153600   26
-#define CBR_230400   27
-#define CBR_307200   28
-#define CBR_460800   29
-#define CBR_921600   30
-
-// Set Character size
-//
-#define CMD_SETBITS(arg) \
-	(((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08))
-
-#define CSZ_5  0
-#define CSZ_6  1
-#define CSZ_7  2
-#define CSZ_8  3
-
-// Set number of stop bits
-//
-#define CMD_SETSTOP(arg) \
-	(((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09))
-
-#define CST_1  0
-#define CST_15 1  // 1.5 stop bits
-#define CST_2  2
-
-// Set parity option
-//
-#define CMD_SETPAR(arg) \
-	(((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10))
-
-#define CSP_NP 0  // no parity
-#define CSP_OD 1  // odd parity
-#define CSP_EV 2  // Even parity
-#define CSP_SP 3  // Space parity
-#define CSP_MK 4  // Mark parity
-
-// Define xon char for transmitter flow control
-//
-#define CMD_DEF_IXON(arg) \
-	(((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11))
-
-// Define xoff char for transmitter flow control
-//
-#define CMD_DEF_IXOFF(arg) \
-	(((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12))
-
-#define CMD_STOPFL   (cmdSyntaxPtr)(ct13) // Stop Flushing data
-
-// Acknowledge receipt of hotkey signal
-//
-#define CMD_HOTACK   (cmdSyntaxPtr)(ct14)
-
-// Define irq level to use. Should actually be sent by library-level code, not
-// directly from user...
-//
-#define CMDVALUE_IRQ 15 // For library use at initialization. Until this command
-						// is sent, board processing doesn't really start.
-#define CMD_SET_IRQ(arg) \
-	(((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15))
-
-#define CIR_POLL  0  // No IRQ - Poll
-#define CIR_3     3  // IRQ 3
-#define CIR_4     4  // IRQ 4
-#define CIR_5     5  // IRQ 5
-#define CIR_7     7  // IRQ 7
-#define CIR_10    10 // IRQ 10
-#define CIR_11    11 // IRQ 11
-#define CIR_12    12 // IRQ 12
-#define CIR_15    15 // IRQ 15
-
-// Select transmit flow xon/xoff options
-//
-#define CMD_IXON_OPT(arg) \
-	(((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16))
-
-#define CIX_NONE  0  // Incoming Xon/Xoff characters not special
-#define CIX_XON   1  // Xoff disable, Xon enable
-#define CIX_XANY  2  // Xoff disable, any key enable
-
-// Select receive flow xon/xoff options
-//
-#define CMD_OXON_OPT(arg) \
-	(((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17))
-
-#define COX_NONE  0  // Don't send Xon/Xoff
-#define COX_XON   1  // Send xon/xoff to start/stop incoming data
-
-
-#define CMD_CTS_REP  (cmdSyntaxPtr)(ct18) // Enable  CTS reporting
-#define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting
-
-#define CMD_DCD_REP  (cmdSyntaxPtr)(ct20) // Enable  DCD reporting
-#define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting
-
-#define CMD_DSR_REP  (cmdSyntaxPtr)(ct22) // Enable  DSR reporting
-#define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting
-
-#define CMD_RI_REP   (cmdSyntaxPtr)(ct24) // Enable  RI  reporting
-#define CMD_RI_NREP  (cmdSyntaxPtr)(ct25) // Disable RI  reporting
-
-// Enable break reporting and select style
-//
-#define CMD_BRK_REP(arg) \
-	(((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26))
-
-#define CBK_STAT     0x00  // Report breaks as a status (exception,irq)
-#define CBK_NULL     0x01  // Report breaks as a good null
-#define CBK_STAT_SEQ 0x02  // Report breaks as a status AND as in-band character
-                           //  sequence FFh, 01h, 10h
-#define CBK_SEQ      0x03  // Report breaks as the in-band 
-						   //sequence FFh, 01h, 10h ONLY.
-#define CBK_FLSH     0x04  // if this bit set also flush input data
-#define CBK_POSIX    0x08  // if this bit set report as FF,0,0 sequence
-#define CBK_SINGLE   0x10  // if this bit set with CBK_SEQ or CBK_STAT_SEQ
-						   //then reports single null instead of triple
-
-#define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting
-
-// Specify maximum block size for received data
-//
-#define CMD_MAX_BLOCK(arg) \
-	(((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28))
-
-// -- COMMAND 29 is reserved --
-
-#define CMD_CTSFL_ENAB  (cmdSyntaxPtr)(ct30) // Enable  CTS flow control
-#define CMD_CTSFL_DSAB  (cmdSyntaxPtr)(ct31) // Disable CTS flow control
-#define CMD_RTSFL_ENAB  (cmdSyntaxPtr)(ct32) // Enable  RTS flow control
-#define CMD_RTSFL_DSAB  (cmdSyntaxPtr)(ct33) // Disable RTS flow control
-
-// Specify istrip option
-//
-#define CMD_ISTRIP_OPT(arg) \
-	(((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34))
-
-#define CIS_NOSTRIP  0  // Strip characters to character size
-#define CIS_STRIP    1  // Strip any 8-bit characters to 7 bits
-
-// Send a break of arg milliseconds
-//
-#define CMD_SEND_BRK(arg) \
-	(((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35))
-
-// Set error reporting mode
-//
-#define CMD_SET_ERROR(arg) \
-	(((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36))
-
-#define CSE_ESTAT 0  // Report error in a status packet
-#define CSE_NOREP 1  // Treat character as though it were good
-#define CSE_DROP  2  // Discard the character
-#define CSE_NULL  3  // Replace with a null
-#define CSE_MARK  4  // Replace with a 3-character sequence (as Unix)
-
-#define CSE_REPLACE  0x8	// Replace the errored character with the
-							// replacement character defined here
-
-#define CSE_STAT_REPLACE   0x18	// Replace the errored character with the
-								// replacement character defined here AND
-								// report the error as a status packet (as in
-								// CSE_ESTAT).
-
-
-// COMMAND 37, to send flow control packets, is handled only by low-level
-// library code in response to data movement and shouldn't ever be sent by the
-// user code. See i2pack.h and the body of i2lib.c for details.
-
-// Enable on-board post-processing, using options given in oflag argument.
-// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command
-// because the loadware does not permit sending back-to-back CMD_OPOST_ON
-// commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that
-// CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a
-// solo packet). This means the caller must specify separately CMD_OPOST_OFF,
-// CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure
-// each gets a separate packet. Extra CMD_OPOST_OFF's are always ok.
-//
-#define CMD_OPOST_ON(oflag)   \
-	(*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \
-		(cmdSyntaxPtr)(ct39))
-
-#define CMD_OPOST_OFF   (cmdSyntaxPtr)(ct40) // Disable on-board post-proc
-
-#define CMD_RESUME   (cmdSyntaxPtr)(ct41)	// Resume: behave as though an XON
-											// were received;
-
-// Set Transmit baud rate (see command 7 for arguments)
-//
-#define CMD_SETBAUD_TX(arg) \
-	(((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42))
-
-// Set Receive baud rate (see command 7 for arguments)
-//
-#define CMD_SETBAUD_RX(arg) \
-	(((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43))
-
-// Request interrupt from board each arg milliseconds. Interrupt will specify
-// "received data", even though there may be no data present. If arg == 0,
-// disables any such interrupts.
-//
-#define CMD_PING_REQ(arg) \
-	(((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44))
-
-#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
-#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
-
-#if 0
-// COMMAND 47: Send Protocol info via Unix flags:
-// iflag = Unix tty t_iflag
-// cflag = Unix tty t_cflag
-// lflag = Unix tty t_lflag
-// See System V Unix/Xenix documentation for the meanings of the bit fields
-// within these flags
-//
-#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
-#endif  /*  0  */
-
-#define CMD_DSRFL_ENAB  (cmdSyntaxPtr)(ct48) // Enable  DSR receiver ctrl
-#define CMD_DSRFL_DSAB  (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
-#define CMD_DTRFL_ENAB  (cmdSyntaxPtr)(ct50) // Enable  DTR flow control
-#define CMD_DTRFL_DSAB  (cmdSyntaxPtr)(ct51) // Disable DTR flow control
-#define CMD_BAUD_RESET  (cmdSyntaxPtr)(ct52) // Reset baudrate table
-
-// COMMAND 54: Define custom rate #1
-// rate = (short) 1/10 of the desired baud rate
-//
-#define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate)
-
-// COMMAND 55: Define custom rate #2
-// rate = (short) 1/10 of the desired baud rate
-//
-#define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate)
-
-// Pause arg hundredths of seconds. (Note, this is NOT milliseconds.)
-//
-#define CMD_PAUSE(arg) \
-	(((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56))
-
-#define CMD_SUSPEND     (cmdSyntaxPtr)(ct57) // Suspend output
-#define CMD_UNSUSPEND   (cmdSyntaxPtr)(ct58) // Un-Suspend output
-
-// Set parity-checking options
-//
-#define CMD_PARCHK(arg) \
-	(((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59))
-
-#define CPK_ENAB  0     // Enable parity checking on input
-#define CPK_DSAB  1     // Disable parity checking on input
-
-#define CMD_BMARK_REQ   (cmdSyntaxPtr)(ct60) // Bookmark request
-
-
-// Enable/Disable internal loopback mode
-//
-#define CMD_INLOOP(arg) \
-	(((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61))
-
-#define CIN_DISABLE  0  // Normal operation (default)
-#define CIN_ENABLE   1  // Internal (local) loopback
-#define CIN_REMOTE   2  // Remote loopback
-
-// Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0
-// --> no timeout: wait forever.
-//
-#define CMD_HOT_TIME(arg) \
-	(((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62))
-
-
-// Define (outgoing) xon for receive flow control
-//
-#define CMD_DEF_OXON(arg) \
-	(((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63))
-
-// Define (outgoing) xoff for receiver flow control
-//
-#define CMD_DEF_OXOFF(arg) \
-	(((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64))
-
-// Enable/Disable RTS on transmit (1/2 duplex-style)
-//
-#define CMD_RTS_XMIT(arg) \
-	(((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65))
-
-#define CHD_DISABLE  0
-#define CHD_ENABLE   1
-
-// Set high-water-mark level (debugging use only)
-//
-#define CMD_SETHIGHWAT(arg) \
-	(((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66))
-
-// Start flushing tagged data (tag = 0-14)
-//
-#define CMD_START_SELFL(tag) \
-	(((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67))
-
-// End flushing tagged data (tag = 0-14)
-//
-#define CMD_END_SELFL(tag) \
-	(((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68))
-
-#define CMD_HWFLOW_OFF  (cmdSyntaxPtr)(ct69) // Disable HW TX flow control
-#define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c
-#define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c
-#define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c
-#define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c
-
-// Set transmit interrupt load level. Count should be an even value 2-12
-//
-#define CMD_LOADLEVEL(count) \
-	(((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74))
-
-// If reporting DSS changes, map to character sequence FFh, 2, MSR
-//
-#define CMD_STATDATA(arg) \
-	(((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75))
-
-#define CSTD_DISABLE// Report DSS changes as status packets only (default)
-#define CSTD_ENABLE	// Report DSS changes as in-band data sequence as well as
-					// by status packet.
-
-#define CMD_BREAK_ON    (cmdSyntaxPtr)(ct76)// Set break and stop xmit
-#define CMD_BREAK_OFF   (cmdSyntaxPtr)(ct77)// End break and restart xmit
-#define CMD_GETFC       (cmdSyntaxPtr)(ct78)// Request for flow control packet
-											// from board.
-
-// Transmit this character immediately
-//
-#define CMD_XMIT_NOW(ch) \
-	(((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79))
-
-// Set baud rate via "divisor latch"
-//
-#define CMD_DIVISOR_LATCH(which,value) \
-			(((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \
-			(cmdSyntaxPtr)(ct80))
-
-#define CDL_RX 1	// Set receiver rate
-#define CDL_TX 2	// Set transmit rate
-					// (CDL_TX | CDL_RX) Set both rates
-
-// Request for special diagnostic status pkt from the board.
-//
-#define CMD_GET_STATUS (cmdSyntaxPtr)(ct81)
-
-// Request time-stamped transmit character count packet.
-//
-#define CMD_GET_TXCNT  (cmdSyntaxPtr)(ct82)
-
-// Request time-stamped receive character count packet.
-//
-#define CMD_GET_RXCNT  (cmdSyntaxPtr)(ct83)
-
-// Request for box/board I.D. packet.
-#define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84)
-
-// Enable or disable multiple channels according to bit-mapped ushorts box 1-4
-//
-#define CMD_ENAB_MULT(enable, box1, box2, box3, box4)    \
-			(((cmdSytaxPtr)(ct85))->cmd[1] = (enable),            \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \
-			(cmdSyntaxPtr)(ct85))
-
-#define CEM_DISABLE  0
-#define CEM_ENABLE   1
-
-// Enable or disable receiver or receiver interrupts (default both enabled)
-//
-#define CMD_RCV_ENABLE(ch) \
-	(((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86))
-
-#define CRE_OFF      0  // Disable the receiver
-#define CRE_ON       1  // Enable the receiver
-#define CRE_INTOFF   2  // Disable receiver interrupts (to loadware)
-#define CRE_INTON    3  // Enable receiver interrupts (to loadware)
-
-// Starts up a hardware test process, which runs transparently, and sends a
-// STAT_HWFAIL packet in case a hardware failure is detected.
-//
-#define CMD_HW_TEST  (cmdSyntaxPtr)(ct87)
-
-// Change receiver threshold and timeout value:
-// Defaults: timeout = 20mS
-// threshold count = 8 when DTRflow not in use,
-// threshold count = 5 when DTRflow in use.
-//
-#define CMD_RCV_THRESHOLD(count,ms) \
-			(((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \
-			((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \
-			(cmdSyntaxPtr)(ct88))
-
-// Makes the loadware report DSS signals for this channel immediately.
-//
-#define CMD_DSS_NOW (cmdSyntaxPtr)(ct89)
-	
-// Set the receive silo parameters 
-// 	timeout is ms idle wait until delivery       (~VTIME)
-// 	threshold is max characters cause interrupt  (~VMIN)
-//
-#define CMD_SET_SILO(timeout,threshold) \
-			(((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \
-			((cmdSyntaxPtr)(ct90))->cmd[2]  = (threshold), \
-			(cmdSyntaxPtr)(ct90))
-
-// Set timed break in decisecond (1/10s)
-//
-#define CMD_LBREAK(ds) \
-	(((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66))
-
-
-
-#endif // I2CMD_H
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
deleted file mode 100644
index 29db44d..0000000
--- a/drivers/char/ip2/i2ellis.c
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Low-level interface code for the device driver
-*                (This is included source code, not a separate compilation
-*                module.)
-*
-*******************************************************************************/
-//---------------------------------------------
-// Function declarations private to this module
-//---------------------------------------------
-// Functions called only indirectly through i2eBordStr entries.
-
-static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int);
-static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int);
-static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int);
-static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int);
-
-static unsigned short iiReadWord16(i2eBordStrPtr);
-static unsigned short iiReadWord8(i2eBordStrPtr);
-static void iiWriteWord16(i2eBordStrPtr, unsigned short);
-static void iiWriteWord8(i2eBordStrPtr, unsigned short);
-
-static int iiWaitForTxEmptyII(i2eBordStrPtr, int);
-static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int);
-static int iiTxMailEmptyII(i2eBordStrPtr);
-static int iiTxMailEmptyIIEX(i2eBordStrPtr);
-static int iiTrySendMailII(i2eBordStrPtr, unsigned char);
-static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char);
-
-static unsigned short iiGetMailII(i2eBordStrPtr);
-static unsigned short iiGetMailIIEX(i2eBordStrPtr);
-
-static void iiEnableMailIrqII(i2eBordStrPtr);
-static void iiEnableMailIrqIIEX(i2eBordStrPtr);
-static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
-static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
-
-static void ii2Nop(void);
-
-//***************
-//* Static Data *
-//***************
-
-static int ii2Safe;         // Safe I/O address for delay routine
-
-static int iiDelayed;	// Set when the iiResetDelay function is
-							// called. Cleared when ANY board is reset.
-static DEFINE_RWLOCK(Dl_spinlock);
-
-//********
-//* Code *
-//********
-
-//=======================================================
-// Initialization Routines
-//
-// iiSetAddress
-// iiReset
-// iiResetDelay
-// iiInitialize
-//=======================================================
-
-//******************************************************************************
-// Function:   iiSetAddress(pB, address, delay)
-// Parameters: pB      - pointer to the board structure
-//             address - the purported I/O address of the board
-//             delay   - pointer to the 1-ms delay function to use
-//                       in this and any future operations to this board
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// This routine (roughly) checks for address validity, sets the i2eValid OK and
-// sets the state to II_STATE_COLD which means that we haven't even sent a reset
-// yet.
-//
-//******************************************************************************
-static int
-iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay )
-{
-	// Should any failure occur before init is finished...
-	pB->i2eValid = I2E_INCOMPLETE;
-
-	// Cannot check upper limit except extremely: Might be microchannel
-	// Address must be on an 8-byte boundary
-
-	if ((unsigned int)address <= 0x100
-		|| (unsigned int)address >= 0xfff8
-		|| (address & 0x7)
-		)
-	{
-		I2_COMPLETE(pB, I2EE_BADADDR);
-	}
-
-	// Initialize accelerators
-	pB->i2eBase    = address;
-	pB->i2eData    = address + FIFO_DATA;
-	pB->i2eStatus  = address + FIFO_STATUS;
-	pB->i2ePointer = address + FIFO_PTR;
-	pB->i2eXMail   = address + FIFO_MAIL;
-	pB->i2eXMask   = address + FIFO_MASK;
-
-	// Initialize i/o address for ii2DelayIO
-	ii2Safe = address + FIFO_NOP;
-
-	// Initialize the delay routine
-	pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop);
-
-	pB->i2eValid = I2E_MAGIC;
-	pB->i2eState = II_STATE_COLD;
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReset(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Attempts to reset the board (see also i2hw.h). Normally, we would use this to
-// reset a board immediately after iiSetAddress(), but it is valid to reset a
-// board from any state, say, in order to change or re-load loadware. (Under
-// such circumstances, no reason to re-run iiSetAddress(), which is why it is a
-// separate routine and not included in this routine.
-//
-//******************************************************************************
-static int
-iiReset(i2eBordStrPtr pB)
-{
-	// Magic number should be set, else even the address is suspect
-	if (pB->i2eValid != I2E_MAGIC)
-	{
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-
-	outb(0, pB->i2eBase + FIFO_RESET);  /* Any data will do */
-	iiDelay(pB, 50);                    // Pause between resets
-	outb(0, pB->i2eBase + FIFO_RESET);  /* Second reset */
-
-	// We must wait before even attempting to read anything from the FIFO: the
-	// board's P.O.S.T may actually attempt to read and write its end of the
-	// FIFO in order to check flags, loop back (where supported), etc. On
-	// completion of this testing it would reset the FIFO, and on completion
-	// of all // P.O.S.T., write the message. We must not mistake data which
-	// might have been sent for testing as part of the reset message. To
-	// better utilize time, say, when resetting several boards, we allow the
-	// delay to be performed externally; in this way the caller can reset 
-	// several boards, delay a single time, then call the initialization
-	// routine for all.
-
-	pB->i2eState = II_STATE_RESET;
-
-	iiDelayed = 0;	// i.e., the delay routine hasn't been called since the most
-					// recent reset.
-
-	// Ensure anything which would have been of use to standard loadware is
-	// blanked out, since board has now forgotten everything!.
-
-	pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */
-	pB->i2eWaitingForEmptyFifo = 0;
-	pB->i2eOutMailWaiting = 0;
-	pB->i2eChannelPtr = NULL;
-	pB->i2eChannelCnt = 0;
-
-	pB->i2eLeadoffWord[0] = 0;
-	pB->i2eFifoInInts = 0;
-	pB->i2eFifoOutInts = 0;
-	pB->i2eFatalTrap = NULL;
-	pB->i2eFatal = 0;
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiResetDelay(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Using the delay defined in board structure, waits two seconds (for board to
-// reset).
-//
-//******************************************************************************
-static int
-iiResetDelay(i2eBordStrPtr pB)
-{
-	if (pB->i2eValid != I2E_MAGIC) {
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-	if (pB->i2eState != II_STATE_RESET) {
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-	iiDelay(pB,2000);       /* Now we wait for two seconds. */
-	iiDelayed = 1;          /* Delay has been called: ok to initialize */
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiInitialize(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Attempts to read the Power-on reset message. Initializes any remaining fields
-// in the pB structure.
-//
-// This should be called as the third step of a process beginning with
-// iiReset(), then iiResetDelay(). This routine checks to see that the structure
-// is "valid" and in the reset state, also confirms that the delay routine has
-// been called since the latest reset (to any board! overly strong!).
-//
-//******************************************************************************
-static int
-iiInitialize(i2eBordStrPtr pB)
-{
-	int itemp;
-	unsigned char c;
-	unsigned short utemp;
-	unsigned int ilimit;
-
-	if (pB->i2eValid != I2E_MAGIC)
-	{
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-
-	if (pB->i2eState != II_STATE_RESET || !iiDelayed)
-	{
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-
-	// In case there is a failure short of our completely reading the power-up
-	// message.
-	pB->i2eValid = I2E_INCOMPLETE;
-
-
-	// Now attempt to read the message.
-
-	for (itemp = 0; itemp < sizeof(porStr); itemp++)
-	{
-		// We expect the entire message is ready.
-		if (!I2_HAS_INPUT(pB)) {
-			pB->i2ePomSize = itemp;
-			I2_COMPLETE(pB, I2EE_PORM_SHORT);
-		}
-
-		pB->i2ePom.c[itemp] = c = inb(pB->i2eData);
-
-		// We check the magic numbers as soon as they are supposed to be read
-		// (rather than after) to minimize effect of reading something we
-		// already suspect can't be "us".
-		if (  (itemp == POR_1_INDEX && c != POR_MAGIC_1) ||
-				(itemp == POR_2_INDEX && c != POR_MAGIC_2))
-		{
-			pB->i2ePomSize = itemp+1;
-			I2_COMPLETE(pB, I2EE_BADMAGIC);
-		}
-	}
-
-	pB->i2ePomSize = itemp;
-
-	// Ensure that this was all the data...
-	if (I2_HAS_INPUT(pB))
-		I2_COMPLETE(pB, I2EE_PORM_LONG);
-
-	// For now, we'll fail to initialize if P.O.S.T reports bad chip mapper:
-	// Implying we will not be able to download any code either:  That's ok: the
-	// condition is pretty explicit.
-	if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER)
-	{
-		I2_COMPLETE(pB, I2EE_POSTERR);
-	}
-
-	// Determine anything which must be done differently depending on the family
-	// of boards!
-	switch (pB->i2ePom.e.porID & POR_ID_FAMILY)
-	{
-	case POR_ID_FII:  // IntelliPort-II
-
-		pB->i2eFifoStyle   = FIFO_II;
-		pB->i2eFifoSize    = 512;     // 512 bytes, always
-		pB->i2eDataWidth16 = false;
-
-		pB->i2eMaxIrq = 15;	// Because board cannot tell us it is in an 8-bit
-							// slot, we do allow it to be done (documentation!)
-
-		pB->i2eGoodMap[1] =
-		pB->i2eGoodMap[2] =
-		pB->i2eGoodMap[3] =
-		pB->i2eChannelMap[1] =
-		pB->i2eChannelMap[2] =
-		pB->i2eChannelMap[3] = 0;
-
-		switch (pB->i2ePom.e.porID & POR_ID_SIZE)
-		{
-		case POR_ID_II_4:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0x0f;  // four-port
-
-			// Since porPorts1 is based on the Hardware ID register, the numbers
-			// should always be consistent for IntelliPort-II.  Ditto below...
-			if (pB->i2ePom.e.porPorts1 != 4)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-
-		case POR_ID_II_8:
-		case POR_ID_II_8R:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0xff;  // Eight port
-			if (pB->i2ePom.e.porPorts1 != 8)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-
-		case POR_ID_II_6:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0x3f;  // Six Port
-			if (pB->i2ePom.e.porPorts1 != 6)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-		}
-
-		// Fix up the "good channel list based on any errors reported.
-		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1)
-		{
-			pB->i2eGoodMap[0] &= ~0x0f;
-		}
-
-		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2)
-		{
-			pB->i2eGoodMap[0] &= ~0xf0;
-		}
-
-		break;   // POR_ID_FII case
-
-	case POR_ID_FIIEX:   // IntelliPort-IIEX
-
-		pB->i2eFifoStyle = FIFO_IIEX;
-
-		itemp = pB->i2ePom.e.porFifoSize;
-
-		// Implicit assumption that fifo would not grow beyond 32k, 
-		// nor would ever be less than 256.
-
-		if (itemp < 8 || itemp > 15)
-		{
-			I2_COMPLETE(pB, I2EE_INCONSIST);
-		}
-		pB->i2eFifoSize = (1 << itemp);
-
-		// These are based on what P.O.S.T thinks should be there, based on
-		// box ID registers
-		ilimit = pB->i2ePom.e.porNumBoxes;
-		if (ilimit > ABS_MAX_BOXES)
-		{
-			ilimit = ABS_MAX_BOXES;
-		}
-
-		// For as many boxes as EXIST, gives the type of box.
-		// Added 8/6/93: check for the ISA-4 (asic) which looks like an
-		// expandable but for whom "8 or 16?" is not the right question.
-
-		utemp = pB->i2ePom.e.porFlags;
-		if (utemp & POR_CEX4)
-		{
-			pB->i2eChannelMap[0] = 0x000f;
-		} else {
-			utemp &= POR_BOXES;
-			for (itemp = 0; itemp < ilimit; itemp++)
-			{
-				pB->i2eChannelMap[itemp] = 
-					((utemp & POR_BOX_16) ? 0xffff : 0x00ff);
-				utemp >>= 1;
-			}
-		}
-
-		// These are based on what P.O.S.T actually found.
-
-		utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1;
-
-		for (itemp = 0; itemp < ilimit; itemp++)
-		{
-			pB->i2eGoodMap[itemp] = 0;
-			if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f;
-			if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0;
-			if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00;
-			if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000;
-			utemp >>= 4;
-		}
-
-		// Now determine whether we should transfer in 8 or 16-bit mode.
-		switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) )
-		{
-		case POR_BUS_SLOT16 | POR_BUS_DIP16:
-			pB->i2eDataWidth16 = true;
-			pB->i2eMaxIrq = 15;
-			break;
-
-		case POR_BUS_SLOT16:
-			pB->i2eDataWidth16 = false;
-			pB->i2eMaxIrq = 15;
-			break;
-
-		case 0:
-		case POR_BUS_DIP16:     // In an 8-bit slot, DIP switch don't care.
-		default:
-			pB->i2eDataWidth16 = false;
-			pB->i2eMaxIrq = 7;
-			break;
-		}
-		break;   // POR_ID_FIIEX case
-
-	default:    // Unknown type of board
-		I2_COMPLETE(pB, I2EE_BAD_FAMILY);
-		break;
-	}  // End the switch based on family
-
-	// Temporarily, claim there is no room in the outbound fifo. 
-	// We will maintain this whenever we check for an empty outbound FIFO.
-	pB->i2eFifoRemains = 0;
-
-	// Now, based on the bus type, should we expect to be able to re-configure
-	// interrupts (say, for testing purposes).
-	switch (pB->i2ePom.e.porBus & POR_BUS_TYPE)
-	{
-	case POR_BUS_T_ISA:
-	case POR_BUS_T_UNK:  // If the type of bus is undeclared, assume ok.
-	case POR_BUS_T_MCA:
-	case POR_BUS_T_EISA:
-		break;
-	default:
-		I2_COMPLETE(pB, I2EE_BADBUS);
-	}
-
-	if (pB->i2eDataWidth16)
-	{
-		pB->i2eWriteBuf  = iiWriteBuf16;
-		pB->i2eReadBuf   = iiReadBuf16;
-		pB->i2eWriteWord = iiWriteWord16;
-		pB->i2eReadWord  = iiReadWord16;
-	} else {
-		pB->i2eWriteBuf  = iiWriteBuf8;
-		pB->i2eReadBuf   = iiReadBuf8;
-		pB->i2eWriteWord = iiWriteWord8;
-		pB->i2eReadWord  = iiReadWord8;
-	}
-
-	switch(pB->i2eFifoStyle)
-	{
-	case FIFO_II:
-		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII;
-		pB->i2eTxMailEmpty    = iiTxMailEmptyII;
-		pB->i2eTrySendMail    = iiTrySendMailII;
-		pB->i2eGetMail        = iiGetMailII;
-		pB->i2eEnableMailIrq  = iiEnableMailIrqII;
-		pB->i2eWriteMask      = iiWriteMaskII;
-
-		break;
-
-	case FIFO_IIEX:
-		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX;
-		pB->i2eTxMailEmpty    = iiTxMailEmptyIIEX;
-		pB->i2eTrySendMail    = iiTrySendMailIIEX;
-		pB->i2eGetMail        = iiGetMailIIEX;
-		pB->i2eEnableMailIrq  = iiEnableMailIrqIIEX;
-		pB->i2eWriteMask      = iiWriteMaskIIEX;
-
-		break;
-
-	default:
-		I2_COMPLETE(pB, I2EE_INCONSIST);
-	}
-
-	// Initialize state information.
-	pB->i2eState = II_STATE_READY;   // Ready to load loadware.
-
-	// Some Final cleanup:
-	// For some boards, the bootstrap firmware may perform some sort of test
-	// resulting in a stray character pending in the incoming mailbox. If one is
-	// there, it should be read and discarded, especially since for the standard
-	// firmware, it's the mailbox that interrupts the host.
-
-	pB->i2eStartMail = iiGetMail(pB);
-
-	// Throw it away and clear the mailbox structure element
-	pB->i2eStartMail = NO_MAIL_HERE;
-
-	// Everything is ok now, return with good status/
-
-	pB->i2eValid = I2E_MAGIC;
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   ii2DelayTimer(mseconds)
-// Parameters: mseconds - number of milliseconds to delay
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine delays for approximately mseconds milliseconds and is intended
-// to be called indirectly through i2Delay field in i2eBordStr. It uses the
-// Linux timer_list mechanism.
-//
-// The Linux timers use a unit called "jiffies" which are 10mS in the Intel
-// architecture. This function rounds the delay period up to the next "jiffy".
-// In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended
-// for Alpha platforms at this time.
-//
-//******************************************************************************
-static void
-ii2DelayTimer(unsigned int mseconds)
-{
-	msleep_interruptible(mseconds);
-}
-
-#if 0
-//static void ii2DelayIO(unsigned int);
-//******************************************************************************
-// !!! Not Used, this is DOS crap, some of you young folks may be interested in
-//     in how things were done in the stone age of caculating machines       !!!
-// Function:   ii2DelayIO(mseconds)
-// Parameters: mseconds - number of milliseconds to delay
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine delays for approximately mseconds milliseconds and is intended
-// to be called indirectly through i2Delay field in i2eBordStr. It is intended
-// for use where a clock-based function is impossible: for example, DOS drivers.
-//
-// This function uses the IN instruction to place bounds on the timing and
-// assumes that ii2Safe has been set. This is because I/O instructions are not
-// subject to caching and will therefore take a certain minimum time. To ensure
-// the delay is at least long enough on fast machines, it is based on some
-// fastest-case calculations.  On slower machines this may cause VERY long
-// delays. (3 x fastest case). In the fastest case, everything is cached except
-// the I/O instruction itself.
-//
-// Timing calculations:
-// The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O
-// operation in question is a byte operation to an odd address. For 8-bit
-// operations, the architecture generally enforces two wait states. At 10 MHz, a
-// single cycle time is 100nS. A read operation at two wait states takes 6
-// cycles for a total time of 600nS. Therefore approximately 1666 iterations
-// would be required to generate a single millisecond delay. The worst
-// (reasonable) case would be an 8MHz system with no cacheing. In this case, the
-// I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code
-// fetch of other instructions in the loop would take time (zero wait states,
-// however) and would be hard to estimate. This is minimized by using in-line
-// assembler for the in inner loop of IN instructions. This consists of just a
-// few bytes. So we'll guess about four code fetches per loop. Each code fetch
-// should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is
-// that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS.
-//
-// So much for theoretical timings: results using 1666 value on some actual
-// machines:
-// IBM      286      6MHz     3.15 mS
-// Zenith   386      33MHz    2.45 mS
-// (brandX) 386      33MHz    1.90 mS  (has cache)
-// (brandY) 486      33MHz    2.35 mS
-// NCR      486      ??       1.65 mS (microchannel)
-//
-// For most machines, it is probably safe to scale this number back (remember,
-// for robust operation use an actual timed delay if possible), so we are using
-// a value of 1190. This yields 1.17 mS for the fastest machine in our sample,
-// 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine.
-//
-// 1/29/93:
-// The above timings are too slow. Actual cycle times might be faster. ISA cycle
-// times could approach 500 nS, and ...
-// The IBM model 77 being microchannel has no wait states for 8-bit reads and
-// seems to be accessing the I/O at 440 nS per access (from start of one to
-// start of next). This would imply we need 1000/.440 = 2272 iterations to
-// guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in
-// fact enough. For diagnostics, we keep the level at 1190, but developers note
-// this needs tuning.
-//
-// Safe assumption:  2270 i/o reads = 1 millisecond
-//
-//******************************************************************************
-
-
-static int ii2DelValue = 1190;  // See timing calculations below
-						// 1666 for fastest theoretical machine
-						// 1190 safe for most fast 386 machines
-						// 1000 for fastest machine tested here
-						//  540 (sic) for AT286/6Mhz
-static void
-ii2DelayIO(unsigned int mseconds)
-{
-	if (!ii2Safe) 
-		return;   /* Do nothing if this variable uninitialized */
-
-	while(mseconds--) {
-		int i = ii2DelValue;
-		while ( i-- ) {
-			inb(ii2Safe);
-		}
-	}
-}
-#endif 
-
-//******************************************************************************
-// Function:   ii2Nop()
-// Parameters: None
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// iiInitialize will set i2eDelay to this if the delay parameter is NULL. This
-// saves checking for a NULL pointer at every call.
-//******************************************************************************
-static void
-ii2Nop(void)
-{
-	return;	// no mystery here
-}
-
-//=======================================================
-// Routines which are available in 8/16-bit versions, or
-// in different fifo styles. These are ALL called
-// indirectly through the board structure.
-//=======================================================
-
-//******************************************************************************
-// Function:   iiWriteBuf16(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address of data to write
-//             count   - number of data bytes to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes 'count' bytes from 'address' to the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// sent (identity unknown...). Uses 16-bit (word) operations. Is called
-// indirectly through pB->i2eWriteBuf.
-//
-//******************************************************************************
-static int
-iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_OUTSW(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiWriteBuf8(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address of data to write
-//             count   - number of data bytes to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes 'count' bytes from 'address' to the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// sent (identity unknown...). This is to be consistent with the 16-bit version.
-// Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf.
-//
-//******************************************************************************
-static int
-iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	/* Rudimentary sanity checking here */
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_OUTSB(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadBuf16(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address to put data read
-//             count   - number of data bytes to read
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Reads 'count' bytes into 'address' from the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// received (identity unknown...). Uses 16-bit (word) operations. Is called
-// indirectly through pB->i2eReadBuf.
-//
-//******************************************************************************
-static int
-iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_INSW(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadBuf8(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address to put data read
-//             count   - number of data bytes to read
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Reads 'count' bytes into 'address' from the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// received (identity unknown...). This to match the 16-bit behaviour. Uses
-// 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf.
-//
-//******************************************************************************
-static int
-iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_INSB(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadWord16(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Returns the word read from the data fifo specified by the board-structure
-// pointer pB. Uses a 16-bit operation. Is called indirectly through
-// pB->i2eReadWord.
-//
-//******************************************************************************
-static unsigned short
-iiReadWord16(i2eBordStrPtr pB)
-{
-	return inw(pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiReadWord8(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Returns the word read from the data fifo specified by the board-structure
-// pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is
-// called indirectly through pB->i2eReadWord.
-//
-//******************************************************************************
-static unsigned short
-iiReadWord8(i2eBordStrPtr pB)
-{
-	unsigned short urs;
-
-	urs = inb(pB->i2eData);
-
-	return (inb(pB->i2eData) << 8) | urs;
-}
-
-//******************************************************************************
-// Function:   iiWriteWord16(pB, value)
-// Parameters: pB    - pointer to board structure
-//             value - data to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes the word 'value' to the data fifo specified by the board-structure
-// pointer pB. Uses 16-bit operation. Is called indirectly through
-// pB->i2eWriteWord.
-//
-//******************************************************************************
-static void
-iiWriteWord16(i2eBordStrPtr pB, unsigned short value)
-{
-	outw((int)value, pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiWriteWord8(pB, value)
-// Parameters: pB    - pointer to board structure
-//             value - data to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes the word 'value' to the data fifo specified by the board-structure
-// pointer pB. Uses two 8-bit operations (writes LSB first). Is called
-// indirectly through pB->i2eWriteWord.
-//
-//******************************************************************************
-static void
-iiWriteWord8(i2eBordStrPtr pB, unsigned short value)
-{
-	outb((char)value, pB->i2eData);
-	outb((char)(value >> 8), pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiWaitForTxEmptyII(pB, mSdelay)
-// Parameters: pB      - pointer to board structure
-//             mSdelay - period to wait before returning
-//
-// Returns:    True if the FIFO is empty.
-//             False if it not empty in the required time: the pB->i2eError
-//             field has the error.
-//
-// Description:
-//
-// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
-// not empty by the required time, returns false and error in pB->i2eError,
-// otherwise returns true.
-//
-// mSdelay == 0 is taken to mean must be empty on the first test.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-// Note this routine is organized so that if status is ok there is no delay at
-// all called either before or after the test.  Is called indirectly through
-// pB->i2eWaitForTxEmpty.
-//
-//******************************************************************************
-static int
-iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay)
-{
-	unsigned long	flags;
-	int itemp;
-
-	for (;;)
-	{
-		// This routine hinges on being able to see the "other" status register
-		// (as seen by the local processor).  His incoming fifo is our outgoing
-		// FIFO.
-		//
-		// By the nature of this routine, you would be using this as part of a
-		// larger atomic context: i.e., you would use this routine to ensure the
-		// fifo empty, then act on this information. Between these two halves, 
-		// you will generally not want to service interrupts or in any way 
-		// disrupt the assumptions implicit in the larger context.
-		//
-		// Even worse, however, this routine "shifts" the status register to 
-		// point to the local status register which is not the usual situation.
-		// Therefore for extra safety, we force the critical section to be
-		// completely atomic, and pick up after ourselves before allowing any
-		// interrupts of any kind.
-
-
-		write_lock_irqsave(&Dl_spinlock, flags);
-		outb(SEL_COMMAND, pB->i2ePointer);
-		outb(SEL_CMD_SH, pB->i2ePointer);
-
-		itemp = inb(pB->i2eStatus);
-
-		outb(SEL_COMMAND, pB->i2ePointer);
-		outb(SEL_CMD_UNSH, pB->i2ePointer);
-
-		if (itemp & ST_IN_EMPTY)
-		{
-			I2_UPDATE_FIFO_ROOM(pB);
-			write_unlock_irqrestore(&Dl_spinlock, flags);
-			I2_COMPLETE(pB, I2EE_GOOD);
-		}
-
-		write_unlock_irqrestore(&Dl_spinlock, flags);
-
-		if (mSdelay-- == 0)
-			break;
-
-		iiDelay(pB, 1);      /* 1 mS granularity on checking condition */
-	}
-	I2_COMPLETE(pB, I2EE_TXE_TIME);
-}
-
-//******************************************************************************
-// Function:   iiWaitForTxEmptyIIEX(pB, mSdelay)
-// Parameters: pB      - pointer to board structure
-//             mSdelay - period to wait before returning
-//
-// Returns:    True if the FIFO is empty.
-//             False if it not empty in the required time: the pB->i2eError
-//             field has the error.
-//
-// Description:
-//
-// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
-// not empty by the required time, returns false and error in pB->i2eError,
-// otherwise returns true.
-//
-// mSdelay == 0 is taken to mean must be empty on the first test.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-// Note this routine is organized so that if status is ok there is no delay at
-// all called either before or after the test.  Is called indirectly through
-// pB->i2eWaitForTxEmpty.
-//
-//******************************************************************************
-static int
-iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay)
-{
-	unsigned long	flags;
-
-	for (;;)
-	{
-		// By the nature of this routine, you would be using this as part of a
-		// larger atomic context: i.e., you would use this routine to ensure the
-		// fifo empty, then act on this information. Between these two halves,
-		// you will generally not want to service interrupts or in any way
-		// disrupt the assumptions implicit in the larger context.
-
-		write_lock_irqsave(&Dl_spinlock, flags);
-
-		if (inb(pB->i2eStatus) & STE_OUT_MT) {
-			I2_UPDATE_FIFO_ROOM(pB);
-			write_unlock_irqrestore(&Dl_spinlock, flags);
-			I2_COMPLETE(pB, I2EE_GOOD);
-		}
-		write_unlock_irqrestore(&Dl_spinlock, flags);
-
-		if (mSdelay-- == 0)
-			break;
-
-		iiDelay(pB, 1);      // 1 mS granularity on checking condition
-	}
-	I2_COMPLETE(pB, I2EE_TXE_TIME);
-}
-
-//******************************************************************************
-// Function:   iiTxMailEmptyII(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if the transmit mailbox is empty.
-//             False if it not empty.
-//
-// Description:
-//
-// Returns true or false according to whether the transmit mailbox is empty (and
-// therefore able to accept more mail)
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static int
-iiTxMailEmptyII(i2eBordStrPtr pB)
-{
-	int port = pB->i2ePointer;
-	outb(SEL_OUTMAIL, port);
-	return inb(port) == 0;
-}
-
-//******************************************************************************
-// Function:   iiTxMailEmptyIIEX(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if the transmit mailbox is empty.
-//             False if it not empty.
-//
-// Description:
-//
-// Returns true or false according to whether the transmit mailbox is empty (and
-// therefore able to accept more mail)
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static int
-iiTxMailEmptyIIEX(i2eBordStrPtr pB)
-{
-	return !(inb(pB->i2eStatus) & STE_OUT_MAIL);
-}
-
-//******************************************************************************
-// Function:   iiTrySendMailII(pB,mail)
-// Parameters: pB   - pointer to board structure
-//             mail - value to write to mailbox
-//
-// Returns:    True if the transmit mailbox is empty, and mail is sent.
-//             False if it not empty.
-//
-// Description:
-//
-// If outgoing mailbox is empty, sends mail and returns true. If outgoing
-// mailbox is not empty, returns false.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static int
-iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail)
-{
-	int port = pB->i2ePointer;
-
-	outb(SEL_OUTMAIL, port);
-	if (inb(port) == 0) {
-		outb(SEL_OUTMAIL, port);
-		outb(mail, port);
-		return 1;
-	}
-	return 0;
-}
-
-//******************************************************************************
-// Function:   iiTrySendMailIIEX(pB,mail)
-// Parameters: pB   - pointer to board structure
-//             mail - value to write to mailbox
-//
-// Returns:    True if the transmit mailbox is empty, and mail is sent.
-//             False if it not empty.
-//
-// Description:
-//
-// If outgoing mailbox is empty, sends mail and returns true. If outgoing
-// mailbox is not empty, returns false.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static int
-iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail)
-{
-	if (inb(pB->i2eStatus) & STE_OUT_MAIL)
-		return 0;
-	outb(mail, pB->i2eXMail);
-	return 1;
-}
-
-//******************************************************************************
-// Function:   iiGetMailII(pB,mail)
-// Parameters: pB   - pointer to board structure
-//
-// Returns:    Mailbox data or NO_MAIL_HERE.
-//
-// Description:
-//
-// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
-// the mailbox, which is guaranteed != NO_MAIL_HERE.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static unsigned short
-iiGetMailII(i2eBordStrPtr pB)
-{
-	if (I2_HAS_MAIL(pB)) {
-		outb(SEL_INMAIL, pB->i2ePointer);
-		return inb(pB->i2ePointer);
-	} else {
-		return NO_MAIL_HERE;
-	}
-}
-
-//******************************************************************************
-// Function:   iiGetMailIIEX(pB,mail)
-// Parameters: pB   - pointer to board structure
-//
-// Returns:    Mailbox data or NO_MAIL_HERE.
-//
-// Description:
-//
-// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
-// the mailbox, which is guaranteed != NO_MAIL_HERE.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static unsigned short
-iiGetMailIIEX(i2eBordStrPtr pB)
-{
-	if (I2_HAS_MAIL(pB))
-		return inb(pB->i2eXMail);
-	else
-		return NO_MAIL_HERE;
-}
-
-//******************************************************************************
-// Function:   iiEnableMailIrqII(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static void
-iiEnableMailIrqII(i2eBordStrPtr pB)
-{
-	outb(SEL_MASK, pB->i2ePointer);
-	outb(ST_IN_MAIL, pB->i2ePointer);
-}
-
-//******************************************************************************
-// Function:   iiEnableMailIrqIIEX(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static void
-iiEnableMailIrqIIEX(i2eBordStrPtr pB)
-{
-	outb(MX_IN_MAIL, pB->i2eXMask);
-}
-
-//******************************************************************************
-// Function:   iiWriteMaskII(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Writes arbitrary value to the mask register.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static void
-iiWriteMaskII(i2eBordStrPtr pB, unsigned char value)
-{
-	outb(SEL_MASK, pB->i2ePointer);
-	outb(value, pB->i2ePointer);
-}
-
-//******************************************************************************
-// Function:   iiWriteMaskIIEX(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Writes arbitrary value to the mask register.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static void
-iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value)
-{
-	outb(value, pB->i2eXMask);
-}
-
-//******************************************************************************
-// Function:   iiDownloadBlock(pB, pSource, isStandard)
-// Parameters: pB         - pointer to board structure
-//             pSource    - loadware block to download
-//             isStandard - True if "standard" loadware, else false.
-//
-// Returns:    Success or Failure
-//
-// Description:
-//
-// Downloads a single block (at pSource)to the board referenced by pB. Caller
-// sets isStandard to true/false according to whether the "standard" loadware is
-// what's being loaded. The normal process, then, is to perform an iiInitialize
-// to the board, then perform some number of iiDownloadBlocks using the returned
-// state to determine when download is complete.
-//
-// Possible return values: (see I2ELLIS.H)
-// II_DOWN_BADVALID
-// II_DOWN_BADFILE
-// II_DOWN_CONTINUING
-// II_DOWN_GOOD
-// II_DOWN_BAD
-// II_DOWN_BADSTATE
-// II_DOWN_TIMEOUT
-//
-// Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to
-// determine whether this is the first block, whether to check for magic
-// numbers, how many blocks there are to go...
-//
-//******************************************************************************
-static int
-iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard)
-{
-	int itemp;
-	int loadedFirst;
-
-	if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID;
-
-	switch(pB->i2eState)
-	{
-	case II_STATE_READY:
-
-		// Loading the first block after reset. Must check the magic number of the
-		// loadfile, store the number of blocks we expect to load.
-		if (pSource->e.loadMagic != MAGIC_LOADFILE)
-		{
-			return II_DOWN_BADFILE;
-		}
-
-		// Next we store the total number of blocks to load, including this one.
-		pB->i2eToLoad = 1 + pSource->e.loadBlocksMore;
-
-		// Set the state, store the version numbers. ('Cause this may have come
-		// from a file - we might want to report these versions and revisions in
-		// case of an error!
-		pB->i2eState = II_STATE_LOADING;
-		pB->i2eLVersion = pSource->e.loadVersion;
-		pB->i2eLRevision = pSource->e.loadRevision;
-		pB->i2eLSub = pSource->e.loadSubRevision;
-
-		// The time and date of compilation is also available but don't bother
-		// storing it for normal purposes.
-		loadedFirst = 1;
-		break;
-
-	case II_STATE_LOADING:
-		loadedFirst = 0;
-		break;
-
-	default:
-		return II_DOWN_BADSTATE;
-	}
-
-	// Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad
-	// must be positive still, because otherwise we would have cleaned up last
-	// time and set the state to II_STATE_LOADED.
-	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
-		return II_DOWN_TIMEOUT;
-	}
-
-	if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) {
-		return II_DOWN_BADVALID;
-	}
-
-	// If we just loaded the first block, wait for the fifo to empty an extra
-	// long time to allow for any special startup code in the firmware, like
-	// sending status messages to the LCD's.
-
-	if (loadedFirst) {
-		if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) {
-			return II_DOWN_TIMEOUT;
-		}
-	}
-
-	// Determine whether this was our last block!
-	if (--(pB->i2eToLoad)) {
-		return II_DOWN_CONTINUING;    // more to come...
-	}
-
-	// It WAS our last block: Clean up operations...
-	// ...Wait for last buffer to drain from the board...
-	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
-		return II_DOWN_TIMEOUT;
-	}
-	// If there were only a single block written, this would come back
-	// immediately and be harmless, though not strictly necessary.
-	itemp = MAX_DLOAD_ACK_TIME/10;
-	while (--itemp) {
-		if (I2_HAS_INPUT(pB)) {
-			switch (inb(pB->i2eData)) {
-			case LOADWARE_OK:
-				pB->i2eState =
-					isStandard ? II_STATE_STDLOADED :II_STATE_LOADED;
-
-				// Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2)
-				// will, // if there is a debug port attached, require some
-				// time to send information to the debug port now. It will do
-				// this before // executing any of the code we just downloaded.
-				// It may take up to 700 milliseconds.
-				if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) {
-					iiDelay(pB, 700);
-				}
-
-				return II_DOWN_GOOD;
-
-			case LOADWARE_BAD:
-			default:
-				return II_DOWN_BAD;
-			}
-		}
-
-		iiDelay(pB, 10);      // 10 mS granularity on checking condition
-	}
-
-	// Drop-through --> timed out waiting for firmware confirmation
-
-	pB->i2eState = II_STATE_BADLOAD;
-	return II_DOWN_TIMEOUT;
-}
-
-//******************************************************************************
-// Function:   iiDownloadAll(pB, pSource, isStandard, size)
-// Parameters: pB         - pointer to board structure
-//             pSource    - loadware block to download
-//             isStandard - True if "standard" loadware, else false.
-//             size       - size of data to download (in bytes)
-//
-// Returns:    Success or Failure
-//
-// Description:
-//
-// Given a pointer to a board structure, a pointer to the beginning of some
-// loadware, whether it is considered the "standard loadware", and the size of
-// the array in bytes loads the entire array to the board as loadware.
-//
-// Assumes the board has been freshly reset and the power-up reset message read.
-// (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be
-// too much or too little data to load, or if iiDownloadBlock complains.
-//******************************************************************************
-static int
-iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size)
-{
-	int status;
-
-	// We know (from context) board should be ready for the first block of
-	// download.  Complain if not.
-	if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE;
-
-	while (size > 0) {
-		size -= LOADWARE_BLOCK_SIZE;	// How much data should there be left to
-										// load after the following operation ?
-
-		// Note we just bump pSource by "one", because its size is actually that
-		// of an entire block, same as LOADWARE_BLOCK_SIZE.
-		status = iiDownloadBlock(pB, pSource++, isStandard);
-
-		switch(status)
-		{
-		case II_DOWN_GOOD:
-			return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD);
-
-		case II_DOWN_CONTINUING:
-			break;
-
-		default:
-			return status;
-		}
-	}
-
-	// We shouldn't drop out: it means "while" caught us with nothing left to
-	// download, yet the previous DownloadBlock did not return complete. Ergo,
-	// not enough data to match the size byte in the header.
-	return II_DOWN_UNDER;
-}
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h
deleted file mode 100644
index fb6df24..0000000
--- a/drivers/char/ip2/i2ellis.h
+++ /dev/null
@@ -1,566 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Mainline code for the device driver
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// i2ellis.h
-//
-// IntelliPort-II and IntelliPort-IIEX
-//
-// Extremely
-// Low
-// Level
-// Interface
-// Services
-//
-// Structure Definitions and declarations for "ELLIS" service routines found in
-// i2ellis.c
-//
-// These routines are based on properties of the IntelliPort-II and -IIEX
-// hardware and bootstrap firmware, and are not sensitive to particular
-// conventions of any particular loadware.
-//
-// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material
-// here and in i2ellis.c is intended to provice a useful, but not required,
-// layer of insulation from the hardware specifics.
-//------------------------------------------------------------------------------
-#ifndef  I2ELLIS_H   /* To prevent multiple includes */
-#define  I2ELLIS_H   1
-//------------------------------------------------
-// Revision History:
-//
-// 30 September 1991 MAG First Draft Started
-// 12 October   1991 ...continued...
-//
-// 20 December  1996 AKM Linux version
-//-------------------------------------------------
-
-//----------------------
-// Mandatory Includes:
-//----------------------
-#include "ip2types.h"
-#include "i2hw.h"       // The hardware definitions
-
-//------------------------------------------
-// STAT_BOXIDS packets
-//------------------------------------------
-#define MAX_BOX		4
-
-typedef struct _bidStat
-{
-	unsigned char bid_value[MAX_BOX];
-} bidStat, *bidStatPtr;
-
-// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX
-// boards, reports the hardware-specific "asynchronous resource register" on
-// each expansion box. Boxes not present report 0xff. For -II boards, the first
-// element contains 0x80 for 8-port, 0x40 for 4-port boards.
-
-// Box IDs aka ARR or Async Resource Register (more than you want to know)
-//   7   6   5   4   3   2   1   0
-//   F   F   N   N   L   S   S   S
-//   =============================
-//   F   F   -  Product Family Designator
-//   =====+++++++++++++++++++++++++++++++
-//   0   0   -  Intelliport II EX / ISA-8
-//   1   0   -  IntelliServer
-//   0   1   -  SAC - Port Device (Intelliport III ??? )
-//           =====+++++++++++++++++++++++++++++++++++++++
-//           N   N   -  Number of Ports
-//           0   0   -  8  (eight)
-//           0   1   -  4  (four)
-//           1   0   -  12 (twelve)
-//           1   1   -  16 (sixteen)
-//                   =++++++++++++++++++++++++++++++++++
-//                   L  -   LCD Display Module Present
-//                   0  -   No
-//                   1  -   LCD module present
-//                   =========+++++++++++++++++++++++++++++++++++++
-//                      S   S   S - Async Signals Supported Designator
-//                      0   0   0 - 8dss, Mod DCE DB25 Female
-//                      0   0   1 - 6dss, RJ-45
-//                      0   1   0 - RS-232/422 dss, DB25 Female
-//                      0   1   1 - RS-232/422 dss, separate 232/422 DB25 Female
-//                      1   0   0 - 6dss, 921.6 I/F with ST654's
-//                      1   0   1 - RS-423/232 8dss, RJ-45 10Pin
-//                      1   1   0 - 6dss, Mod DCE DB25 Female
-//                      1   1   1 - NO BOX PRESENT
-
-#define FF(c)	((c & 0xC0) >> 6)
-#define NN(c)	((c & 0x30) >> 4)
-#define L(c)	((c & 0x08) >> 3)
-#define SSS(c)	 (c & 0x07)
-
-#define BID_HAS_654(x)	(SSS(x) == 0x04)
-#define BID_NO_BOX	0xff /* no box */
-#define BID_8PORT  	0x80 /* IP2-8 port */
-#define BID_4PORT   	0x81 /* IP2-4 port */
-#define BID_EXP_MASK   	0x30 /* IP2-EX  */
-#define BID_EXP_8PORT	0x00 /*     8, */
-#define BID_EXP_4PORT	0x10 /*     4, */
-#define BID_EXP_UNDEF	0x20 /*     UNDEF, */
-#define BID_EXP_16PORT	0x30 /*    16, */
-#define BID_LCD_CTRL   	0x08 /* LCD Controller */
-#define BID_LCD_NONE	0x00 /* - no controller present */
-#define BID_LCD_PRES   	0x08 /* - controller present */
-#define BID_CON_MASK	0x07 /* - connector pinouts */
-#define BID_CON_DB25	0x00 /* - DB-25 F */
-#define BID_CON_RJ45	0x01 /* - rj45 */
-
-//------------------------------------------------------------------------------
-// i2eBordStr
-//
-// This structure contains all the information the ELLIS routines require in
-// dealing with a particular board.
-//------------------------------------------------------------------------------
-// There are some queues here which are guaranteed to never contain the entry
-// for a single channel twice. So they must be slightly larger to allow
-// unambiguous full/empty management
-//
-#define CH_QUEUE_SIZE ABS_MOST_PORTS+2
-
-typedef struct _i2eBordStr
-{
-	porStr         i2ePom;	// Structure containing the power-on message.
-
-	unsigned short i2ePomSize;
-						// The number of bytes actually read if
-						// different from sizeof i2ePom, indicates
-						// there is an error!
-
-	unsigned short i2eStartMail;
-						// Contains whatever inbound mailbox data
-						// present at startup. NO_MAIL_HERE indicates
-						// nothing was present. No special
-						// significance as of this writing, but may be
-						// useful for diagnostic reasons.
-
-	unsigned short i2eValid;
-						// Indicates validity of the structure; if
-						// i2eValid == I2E_MAGIC, then we can trust
-						// the other fields. Some (especially
-						// initialization) functions are good about
-						// checking for validity.  Many functions do
-						// not, it being assumed that the larger
-						// context assures we are using a valid
-						// i2eBordStrPtr.
-
-	unsigned short i2eError;
-						// Used for returning an error condition from
-						// several functions which use i2eBordStrPtr
-						// as an argument.
-
-	// Accelerators to characterize separate features of a board, derived from a
-	// number of sources.
-
-	unsigned short i2eFifoSize;
-						// Always, the size of the FIFO. For
-						// IntelliPort-II, always the same, for -IIEX
-						// taken from the Power-On reset message.
-
-	volatile 
-	unsigned short i2eFifoRemains;
-						// Used during normal operation to indicate a
-						// lower bound on the amount of data which
-						// might be in the outbound fifo.
-
-	unsigned char  i2eFifoStyle;
-						// Accelerator which tells which style (-II or
-						// -IIEX) FIFO we are using.
-
-	unsigned char  i2eDataWidth16;
-						// Accelerator which tells whether we should
-						// do 8 or 16-bit data transfers.
-
-	unsigned char  i2eMaxIrq;
-						// The highest allowable IRQ, based on the
-						// slot size.
-
-	// Accelerators for various addresses on the board
-	int            i2eBase;        // I/O Address of the Board
-	int            i2eData;        // From here data transfers happen
-	int            i2eStatus;      // From here status reads happen
-	int            i2ePointer;     // (IntelliPort-II: pointer/commands)
-	int            i2eXMail;       // (IntelliPOrt-IIEX: mailboxes
-	int            i2eXMask;       // (IntelliPort-IIEX: mask write
-
-	//-------------------------------------------------------
-	// Information presented in a common format across boards
-	// For each box, bit map of the channels present.  Box closest to 
-	// the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable)
-	// is taken to be box 0. These are derived from product i.d. registers.
-
-	unsigned short i2eChannelMap[ABS_MAX_BOXES];
-
-	// Same as above, except each is derived from firmware attempting to detect
-	// the uart presence (by reading a valid GFRCR register). If bits are set in
-	// i2eChannelMap and not in i2eGoodMap, there is a potential problem.
-
-	unsigned short i2eGoodMap[ABS_MAX_BOXES];
-
-	// ---------------------------
-	// For indirect function calls
-
-	// Routine to cause an N-millisecond delay: Patched by the ii2Initialize
-	// function.
-
-	void  (*i2eDelay)(unsigned int);
-
-	// Routine to write N bytes to the board through the FIFO. Returns true if
-	// all copacetic, otherwise returns false and error is in i2eError field.
-	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
-
-	int   (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int);
-
-	// Routine to read N bytes from the board through the FIFO. Returns true if
-	// copacetic, otherwise returns false and error in i2eError.
-	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
-
-	int   (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int);
-
-	// Returns a word from FIFO. Will use 2 byte operations if needed.
-
-	unsigned short (*i2eReadWord)(struct _i2eBordStr *);
-
-	// Writes a word to FIFO. Will use 2 byte operations if needed.
-
-	void  (*i2eWriteWord)(struct _i2eBordStr *, unsigned short);
-
-	// Waits specified time for the Transmit FIFO to go empty. Returns true if
-	//  ok, otherwise returns false and error in i2eError.
-
-	int   (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int);
-
-	// Returns true or false according to whether the outgoing mailbox is empty.
-
-	int   (*i2eTxMailEmpty)(struct _i2eBordStr *);
-
-	// Checks whether outgoing mailbox is empty.  If so, sends mail and returns
-	// true.  Otherwise returns false.
-
-	int   (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char);
-
-	// If no mail available, returns NO_MAIL_HERE, else returns the value in the
-	// mailbox (guaranteed can't be NO_MAIL_HERE).
-
-	unsigned short (*i2eGetMail)(struct _i2eBordStr *);
-
-	// Enables the board to interrupt the host when it writes to the mailbox.
-	// Irqs will not occur, however, until the loadware separately enables
-	// interrupt generation to the host.  The standard loadware does this in
-	// response to a command packet sent by the host. (Also, disables
-	// any other potential interrupt sources from the board -- other than the
-	// inbound mailbox).
-
-	void  (*i2eEnableMailIrq)(struct _i2eBordStr *);
-
-	// Writes an arbitrary value to the mask register.
-
-	void  (*i2eWriteMask)(struct _i2eBordStr *, unsigned char);
-
-
-	// State information
-
-	// During downloading, indicates the number of blocks remaining to download
-	// to the board.
-
-	short i2eToLoad;
-
-	// State of board (see manifests below) (e.g., whether in reset condition,
-	// whether standard loadware is installed, etc.
-
-	unsigned char  i2eState;
-
-	// These three fields are only valid when there is loadware running on the
-	// board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED )
-
-	unsigned char  i2eLVersion;  // Loadware version
-	unsigned char  i2eLRevision; // Loadware revision
-	unsigned char  i2eLSub;      // Loadware subrevision
-
-	// Flags which only have meaning in the context of the standard loadware.
-	// Somewhat violates the layering concept, but there is so little additional
-	// needed at the board level (while much additional at the channel level),
-	// that this beats maintaining two different per-board structures.
-
-	// Indicates which IRQ the board has been initialized (from software) to use
-	// For MicroChannel boards, any value different from IRQ_UNDEFINED means
-	// that the software command has been sent to enable interrupts (or specify
-	// they are disabled). Special value: IRQ_UNDEFINED indicates that the
-	// software command to select the interrupt has not yet been sent, therefore
-	// (since the standard loadware insists that it be sent before any other
-	// packets are sent) no other packets should be sent yet.
-
-	unsigned short i2eUsingIrq;
-
-	// This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us
-	// putting more in the mailbox until an appropriate mailbox message is
-	// received.
-
-	unsigned char  i2eWaitingForEmptyFifo;
-
-	// Any mailbox bits waiting to be sent to the board are OR'ed in here.
-
-	unsigned char  i2eOutMailWaiting;
-
-	// The head of any incoming packet is read into here, is then examined and 
-	// we dispatch accordingly.
-
-	unsigned short i2eLeadoffWord[1];
-
-	// Running counter of interrupts where the mailbox indicated incoming data.
-
-	unsigned short i2eFifoInInts;
-
-	// Running counter of interrupts where the mailbox indicated outgoing data
-	// had been stripped.
-
-	unsigned short i2eFifoOutInts;
-
-	// If not void, gives the address of a routine to call if fatal board error
-	// is found (only applies to standard l/w).
-
-	void  (*i2eFatalTrap)(struct _i2eBordStr *);
-
-	// Will point to an array of some sort of channel structures (whose format
-	// is unknown at this level, being a function of what loadware is
-	// installed and the code configuration (max sizes of buffers, etc.)).
-
-	void  *i2eChannelPtr;
-
-	// Set indicates that the board has gone fatal.
-
-	unsigned short i2eFatal;
-
-	// The number of elements pointed to by i2eChannelPtr.
-
-	unsigned short i2eChannelCnt;
-
-	// Ring-buffers of channel structures whose channels have particular needs.
-
-	rwlock_t	Fbuf_spinlock;
-	volatile
-	unsigned short i2Fbuf_strip;	// Strip index
-	volatile 
-	unsigned short i2Fbuf_stuff;	// Stuff index
-	void  *i2Fbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// flow control packets.
-	rwlock_t	Dbuf_spinlock;
-	volatile
-	unsigned short i2Dbuf_strip;	// Strip index
-	volatile
-	unsigned short i2Dbuf_stuff;	// Stuff index
-	void  *i2Dbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// data or in-line command packets.
-	rwlock_t	Bbuf_spinlock;
-	volatile
-	unsigned short i2Bbuf_strip;	// Strip index
-	volatile
-	unsigned short i2Bbuf_stuff;	// Stuff index
-	void  *i2Bbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// bypass command packets.
-
-	/*
-	 * A set of flags to indicate that certain events have occurred on at least
-	 * one of the ports on this board. We use this to decide whether to spin
-	 * through the channels looking for breaks, etc.
-	 */
-	int		got_input;
-	int		status_change;
-	bidStat	channelBtypes;
-
-	/*
-	 * Debugging counters, etc.
-	 */
-	unsigned long debugFlowQueued;
-	unsigned long debugInlineQueued;
-	unsigned long debugDataQueued;
-	unsigned long debugBypassQueued;
-	unsigned long debugFlowCount;
-	unsigned long debugInlineCount;
-	unsigned long debugBypassCount;
-	
-	rwlock_t	read_fifo_spinlock;
-	rwlock_t	write_fifo_spinlock;
-
-//	For queuing interrupt bottom half handlers.	/\/\|=mhw=|\/\/
-	struct work_struct	tqueue_interrupt;
-
-	struct timer_list  SendPendingTimer;   // Used by iiSendPending
-	unsigned int	SendPendingRetry;
-} i2eBordStr, *i2eBordStrPtr;
-
-//-------------------------------------------------------------------
-// Macro Definitions for the indirect calls defined in the i2eBordStr
-//-------------------------------------------------------------------
-//
-#define iiDelay(a,b)          (*(a)->i2eDelay)(b)
-#define iiWriteBuf(a,b,c)     (*(a)->i2eWriteBuf)(a,b,c)
-#define iiReadBuf(a,b,c)      (*(a)->i2eReadBuf)(a,b,c)
-
-#define iiWriteWord(a,b)      (*(a)->i2eWriteWord)(a,b)
-#define iiReadWord(a)         (*(a)->i2eReadWord)(a)
-
-#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b)
-
-#define iiTxMailEmpty(a)      (*(a)->i2eTxMailEmpty)(a)
-#define iiTrySendMail(a,b)    (*(a)->i2eTrySendMail)(a,b)
-
-#define iiGetMail(a)          (*(a)->i2eGetMail)(a)
-#define iiEnableMailIrq(a)    (*(a)->i2eEnableMailIrq)(a)
-#define iiDisableMailIrq(a)   (*(a)->i2eWriteMask)(a,0)
-#define iiWriteMask(a,b)      (*(a)->i2eWriteMask)(a,b)
-
-//-------------------------------------------
-// Manifests for i2eBordStr:
-//-------------------------------------------
-
-typedef void (*delayFunc_t)(unsigned int);
-
-// i2eValid
-//
-#define I2E_MAGIC       0x4251   // Structure is valid.
-#define I2E_INCOMPLETE  0x1122   // Structure failed during init.
-
-
-// i2eError
-//
-#define I2EE_GOOD       0	// Operation successful
-#define I2EE_BADADDR    1	// Address out of range
-#define I2EE_BADSTATE   2	// Attempt to perform a function when the board
-							// structure was in the incorrect state
-#define I2EE_BADMAGIC   3	// Bad magic number from Power On test (i2ePomSize
-							// reflects what was read
-#define I2EE_PORM_SHORT 4	// Power On message too short
-#define I2EE_PORM_LONG  5	// Power On message too long
-#define I2EE_BAD_FAMILY 6	// Un-supported board family type
-#define I2EE_INCONSIST  7	// Firmware reports something impossible,
-							// e.g. unexpected number of ports... Almost no
-							// excuse other than bad FIFO...
-#define I2EE_POSTERR    8	// Power-On self test reported a bad error
-#define I2EE_BADBUS     9	// Unknown Bus type declared in message
-#define I2EE_TXE_TIME   10	// Timed out waiting for TX Fifo to empty
-#define I2EE_INVALID    11	// i2eValid field does not indicate a valid and
-							// complete board structure (for functions which
-							// require this be so.)
-#define I2EE_BAD_PORT   12	// Discrepancy between channels actually found and
-							// what the product is supposed to have. Check
-							// i2eGoodMap vs i2eChannelMap for details.
-#define I2EE_BAD_IRQ    13	// Someone specified an unsupported IRQ
-#define I2EE_NOCHANNELS 14	// No channel structures have been defined (for
-							// functions requiring this).
-
-// i2eFifoStyle
-//
-#define FIFO_II   0  /* IntelliPort-II style: see also i2hw.h */
-#define FIFO_IIEX 1  /* IntelliPort-IIEX style */
-
-// i2eGetMail
-//
-#define NO_MAIL_HERE    0x1111	// Since mail is unsigned char, cannot possibly
-								// promote to 0x1111.
-// i2eState
-//
-#define II_STATE_COLD      0  // Addresses have been defined, but board not even
-							  // reset yet.
-#define II_STATE_RESET     1  // Board,if it exists, has just been reset
-#define II_STATE_READY     2  // Board ready for its first block
-#define II_STATE_LOADING   3  // Board continuing load
-#define II_STATE_LOADED    4  // Board has finished load: status ok
-#define II_STATE_BADLOAD   5  // Board has finished load: failed!
-#define II_STATE_STDLOADED 6  // Board has finished load: standard firmware
-
-// i2eUsingIrq
-//
-#define I2_IRQ_UNDEFINED	0x1352  /* No valid irq (or polling = 0) can
-					 * ever promote to this! */
-//------------------------------------------
-// Handy Macros for i2ellis.c and others
-// Note these are common to -II and -IIEX
-//------------------------------------------
-
-// Given a pointer to the board structure, does the input FIFO have any data or
-// not?
-//
-#define I2_HAS_INPUT(pB)	!(inb(pB->i2eStatus) & ST_IN_EMPTY)
-
-// Given a pointer to the board structure, is there anything in the incoming
-// mailbox?
-//
-#define I2_HAS_MAIL(pB)		(inb(pB->i2eStatus) & ST_IN_MAIL)
-
-#define I2_UPDATE_FIFO_ROOM(pB)	((pB)->i2eFifoRemains = (pB)->i2eFifoSize)
-
-//------------------------------------------
-// Function Declarations for i2ellis.c
-//------------------------------------------
-//
-// Functions called directly
-//
-// Initialization of a board & structure is in four (five!) parts:
-//
-// 1) iiSetAddress() - Define the board address & delay function for a board.
-// 2) iiReset()      - Reset the board   (provided it exists)
-//       -- Note you may do this to several boards --
-// 3) iiResetDelay() - Delay for 2 seconds (once for all boards)
-// 4) iiInitialize() - Attempt to read Power-up message; further initialize
-//                     accelerators
-//
-// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write
-// loadware.  To change loadware, you must begin again with step 2, resetting
-// the board again (step 1 not needed).
-
-static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
-static int iiReset(i2eBordStrPtr);
-static int iiResetDelay(i2eBordStrPtr);
-static int iiInitialize(i2eBordStrPtr);
-
-// Routine to validate that all channels expected are there.
-//
-extern int iiValidateChannels(i2eBordStrPtr);
-
-// Routine used to download a block of loadware.
-//
-static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int);
-
-// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile:
-//
-#define II_DOWN_BADVALID   0	// board structure is invalid
-#define II_DOWN_CONTINUING 1	// So far, so good, firmware expects more
-#define II_DOWN_GOOD       2	// Download complete, CRC good
-#define II_DOWN_BAD        3	// Download complete, but CRC bad
-#define II_DOWN_BADFILE    4	// Bad magic number in loadware file
-#define II_DOWN_BADSTATE   5	// Board is in an inappropriate state for
-								// downloading loadware. (see i2eState)
-#define II_DOWN_TIMEOUT    6	// Timeout waiting for firmware
-#define II_DOWN_OVER       7	// Too much data
-#define II_DOWN_UNDER      8	// Not enough data
-#define II_DOWN_NOFILE     9	// Loadware file not found
-
-// Routine to download an entire loadware module: Return values are a subset of
-// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING
-//
-static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);
-
-// Many functions defined here return True if good, False otherwise, with an
-// error code in i2eError field. Here is a handy macro for setting the error
-// code and returning.
-//
-#define I2_COMPLETE(pB,code) do { \
-		 pB->i2eError = code; \
-		 return (code == I2EE_GOOD);\
-	} while (0)
-
-#endif   // I2ELLIS_H
diff --git a/drivers/char/ip2/i2hw.h b/drivers/char/ip2/i2hw.h
deleted file mode 100644
index c0ba6c0..0000000
--- a/drivers/char/ip2/i2hw.h
+++ /dev/null
@@ -1,652 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions limited to properties of the hardware or the
-*                bootstrap firmware. As such, they are applicable regardless of
-*                operating system or loadware (standard or diagnostic).
-*
-*******************************************************************************/
-#ifndef I2HW_H
-#define I2HW_H 1
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 23 September 1991 MAG   First Draft Started...through...
-// 11 October 1991   ...   Continuing development...
-//  6 August 1993          Added support for ISA-4 (asic) which is architected
-//                         as an ISA-CEX with a single 4-port box.
-//
-// 20 December 1996  AKM   Version for Linux
-//
-//------------------------------------------------------------------------------
-/*------------------------------------------------------------------------------
-
-HARDWARE DESCRIPTION:
-
-Introduction:
-
-The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8)
-addresses in the host's I/O space.
-
-Some addresses are used to transfer data to/from the board, some to transfer
-so-called "mailbox" messages, and some to read bit-mapped status information.
-While all the products in the line are functionally similar, some use a 16-bit
-data path to transfer data while others use an 8-bit path. Also, the use of
-command /status/mailbox registers differs slightly between the II and IIEX
-branches of the family.
-
-The host determines what type of board it is dealing with by reading a string of
-sixteen characters from the board. These characters are always placed in the
-fifo by the board's local processor whenever the board is reset (either from
-power-on or under software control) and are known as the "Power-on Reset
-Message." In order that this message can be read from either type of board, the
-hardware registers used in reading this message are the same. Once this message
-has been read by the host, then it has the information required to operate.
-
-General Differences between boards:
-
-The greatest structural difference is between the -II and -IIEX families of
-product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support
-the data path, mailbox registers, and status registers. This chip contains some
-features which are not used in the IntelliPort-II products; a description of
-these is omitted here. Because of these many features, it contains many
-registers, too many to access directly within a small address space. They are
-accessed by first writing a value to a "pointer" register. This value selects
-the register to be accessed.  The next read or write to that address accesses
-the selected register rather than the pointer register.
-
-The -IIEX boards use a proprietary design similar to the Am4701 in function. But
-because of a simpler, more streamlined design it doesn't require so many
-registers. This means they can be accessed directly in single operations rather
-than through a pointer register.
-
-Besides these differences, there are differences in whether 8-bit or 16-bit
-transfers are used to move data to the board.
-
-The -II boards are capable only of 8-bit data transfers, while the -IIEX boards
-may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP
-switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit
-transfers are supported (and will be expected by the standard loadware). The
-on-board firmware can determine the position of the switch, and whether the
-board is installed in a 16-bit slot; it supplies this information to the host as
-part of the power-up reset message.
-
-The configuration switch (#8) and slot selection do not directly configure the
-hardware. It is up to the on-board loadware and host-based drivers to act
-according to the selected options. That is, loadware and drivers could be
-written to perform 8-bit transfers regardless of the state of the DIP switch or
-slot (and in a diagnostic environment might well do so). Likewise, 16-bit
-transfers could be performed as long as the card is in a 16-bit slot.
-
-Note the slot selection and DIP switch selection are provided separately: a
-board running in 8-bit mode in a 16-bit slot has a greater range of possible
-interrupts to choose from; information of potential use to the host.
-
-All 8-bit data transfers are done in the same way, regardless of whether on a
--II board or a -IIEX board.
-
-The host must consider two things then: 1) whether a -II or -IIEX product is
-being used, and 2) whether an 8-bit or 16-bit data path is used.
-
-A further difference is that -II boards always have a 512-byte fifo operating in
-each direction. -IIEX boards may use fifos of varying size; this size is
-reported as part of the power-up message.
-
-I/O Map Of IntelliPort-II and IntelliPort-IIEX boards:
-(Relative to the chosen base address)
-
-Addr  R/W      IntelliPort-II    IntelliPort-IIEX
-----  ---      --------------    ----------------
-0     R/W      Data Port (byte)  Data Port (byte or word)
-1     R/W      (Not used)        (MSB of word-wide data written to Data Port)
-2     R        Status Register   Status Register
-2     W        Pointer Register  Interrupt Mask Register
-3     R/W      (Not used)        Mailbox Registers (6 bits: 11111100)
-4,5   --       Reserved for future products
-6     --       Reserved for future products
-7     R        Guaranteed to have no effect
-7     W        Hardware reset of board.
-
-
-Rules:
-All data transfers are performed using the even i/o address. If byte-wide data
-transfers are being used, do INB/OUTB operations on the data port. If word-wide
-transfers are used, do INW/OUTW operations. In some circumstances (such as
-reading the power-up message) you will do INB from the data port, but in this
-case the MSB of each word read is lost. When accessing all other unreserved
-registers, use byte operations only.
-------------------------------------------------------------------------------*/
-
-//------------------------------------------------
-// Mandatory Includes:
-//------------------------------------------------
-//
-#include "ip2types.h"
-
-//-------------------------------------------------------------------------
-// Manifests for the I/O map:
-//-------------------------------------------------------------------------
-// R/W: Data port (byte) for IntelliPort-II,
-// R/W: Data port (byte or word) for IntelliPort-IIEX
-// Incoming or outgoing data passes through a FIFO, the status of which is
-// available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is
-// the primary means of transferring data, commands, flow-control, and status
-// information between the host and board.
-//
-#define FIFO_DATA 0
-
-// Another way of passing information between the board and the host is
-// through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of
-// data.  Writing data to the mailbox causes a status bit to be set, and
-// potentially interrupting the intended receiver. The sender has some way to
-// determine whether the data has been read yet; as soon as it has, it may send
-// more. The mailboxes are handled differently on -II and -IIEX products, as
-// suggested below.
-//------------------------------------------------------------------------------
-// Read: Status Register for IntelliPort-II or -IIEX
-// The presence of any bit set here will cause an interrupt to the host,
-// provided the corresponding bit has been unmasked in the interrupt mask
-// register. Furthermore, interrupts to the host are disabled globally until the
-// loadware selects the irq line to use. With the exception of STN_MR, the bits
-// remain set so long as the associated condition is true.
-//
-#define FIFO_STATUS 2
-
-// Bit map of status bits which are identical for -II and -IIEX
-//
-#define ST_OUT_FULL  0x40  // Outbound FIFO full
-#define ST_IN_EMPTY  0x20  // Inbound FIFO empty
-#define ST_IN_MAIL   0x04  // Inbound Mailbox full
-
-// The following exists only on the Intelliport-IIEX, and indicates that the
-// board has not read the last outgoing mailbox data yet. In the IntelliPort-II,
-// the outgoing mailbox may be read back: a zero indicates the board has read
-// the data.
-//
-#define STE_OUT_MAIL 0x80  // Outbound mailbox full (!)
-
-// The following bits are defined differently for -II and -IIEX boards. Code
-// which relies on these bits will need to be functionally different for the two
-// types of boards and should be generally avoided because of the additional
-// complexity this creates:
-
-// Bit map of status bits only on -II
-
-// Fifo has been RESET (cleared when the status register is read). Note that
-// this condition cannot be masked and would always interrupt the host, except
-// that the hardware reset also disables interrupts globally from the board
-// until re-enabled by loadware. This could also arise from the
-// Am4701-supported command to reset the chip, but this command is generally not
-// used here.
-//
-#define STN_MR       0x80
-
-// See the AMD Am4701 data sheet for details on the following four bits. They
-// are not presently used by Computone drivers.
-//
-#define STN_OUT_AF  0x10  // Outbound FIFO almost full (programmable)
-#define STN_IN_AE   0x08  // Inbound FIFO almost empty (programmable)
-#define STN_BD      0x02  // Inbound byte detected
-#define STN_PE      0x01  // Parity/Framing condition detected
-
-// Bit-map of status bits only on -IIEX
-//
-#define STE_OUT_HF  0x10  // Outbound FIFO half full
-#define STE_IN_HF   0x08  // Inbound FIFO half full
-#define STE_IN_FULL 0x02  // Inbound FIFO full
-#define STE_OUT_MT  0x01  // Outbound FIFO empty
-
-//------------------------------------------------------------------------------
-
-// Intelliport-II -- Write Only: the pointer register.
-// Values are written to this register to select the Am4701 internal register to
-// be accessed on the next operation.
-//
-#define FIFO_PTR    0x02
-
-// Values for the pointer register
-//
-#define SEL_COMMAND 0x1    // Selects the Am4701 command register
-
-// Some possible commands:
-//
-#define SEL_CMD_MR  0x80	// Am4701 command to reset the chip
-#define SEL_CMD_SH  0x40	// Am4701 command to map the "other" port into the
-							// status register.
-#define SEL_CMD_UNSH   0	// Am4701 command to "unshift": port maps into its
-							// own status register.
-#define SEL_MASK     0x2	// Selects the Am4701 interrupt mask register. The
-							// interrupt mask register is bit-mapped to match 
-							// the status register (FIFO_STATUS) except for
-							// STN_MR. (See above.)
-#define SEL_BYTE_DET 0x3	// Selects the Am4701 byte-detect register. (Not
-							// normally used except in diagnostics.)
-#define SEL_OUTMAIL  0x4	// Selects the outbound mailbox (R/W). Reading back
-							// a value of zero indicates that the mailbox has
-							// been read by the board and is available for more
-							// data./ Writing to the mailbox optionally
-							// interrupts the board, depending on the loadware's
-							// setting of its interrupt mask register.
-#define SEL_AEAF     0x5	// Selects AE/AF threshold register.
-#define SEL_INMAIL   0x6	// Selects the inbound mailbox (Read)
-
-//------------------------------------------------------------------------------
-// IntelliPort-IIEX --  Write Only: interrupt mask (and misc flags) register:
-// Unlike IntelliPort-II, bit assignments do NOT match those of the status
-// register.
-//
-#define FIFO_MASK    0x2
-
-// Mailbox readback select:
-// If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If
-// clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox.
-// This is the normal situation. The clearing of a mailbox is determined on
-// -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback
-// capability is provided for diagnostic purposes only.
-//
-#define  MX_OUTMAIL_RSEL   0x80
-
-#define  MX_IN_MAIL  0x40	// Enables interrupts when incoming mailbox goes
-							// full (ST_IN_MAIL set).
-#define  MX_IN_FULL  0x20	// Enables interrupts when incoming FIFO goes full
-							// (STE_IN_FULL).
-#define  MX_IN_MT    0x08	// Enables interrupts when incoming FIFO goes empty
-							// (ST_IN_MT).
-#define  MX_OUT_FULL 0x04	// Enables interrupts when outgoing FIFO goes full
-							// (ST_OUT_FULL).
-#define  MX_OUT_MT   0x01	// Enables interrupts when outgoing FIFO goes empty
-							// (STE_OUT_MT).
-
-// Any remaining bits are reserved, and should be written to ZERO for
-// compatibility with future Computone products.
-
-//------------------------------------------------------------------------------
-// IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two
-// bits always read back 0).
-// Read:  One of the mailboxes, usually Inbound.
-//        Inbound Mailbox (MX_OUTMAIL_RSEL = 0)
-//        Outbound Mailbox (MX_OUTMAIL_RSEL = 1)
-// Write: Outbound Mailbox
-// For the IntelliPort-II boards, the outbound mailbox is read back to determine
-// whether the board has read the data (0 --> data has been read). For the
-// IntelliPort-IIEX, this is done by reading a status register. To determine
-// whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit
-// in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by
-// setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the
-// case with the -II boards. For this reason, FIFO_MAIL is normally used to read
-// the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for
-// MX_OUTMAIL_RSEL description.)
-//
-#define  FIFO_MAIL   0x3
-
-//------------------------------------------------------------------------------
-// WRITE ONLY:  Resets the board. (Data doesn't matter).
-//
-#define  FIFO_RESET  0x7
-
-//------------------------------------------------------------------------------
-// READ ONLY:  Will have no effect. (Data is undefined.)
-// Actually, there will be an effect, in that the operation is sure to generate
-// a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short
-// delays when no comparable time constant is available.
-//
-#define  FIFO_NOP    0x7
-
-//------------------------------------------------------------------------------
-// RESET & POWER-ON RESET MESSAGE
-/*------------------------------------------------------------------------------
-RESET:
-
-The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel
-reset, and via a write to the reset register described above. For products using
-the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses,
-the Power-up and channel reset sources cause additional hardware initialization
-which should only occur at system startup time.
-
-The third type of reset, called a "command reset", is done by writing any data
-to the FIFO_RESET address described above. This resets the on-board processor,
-FIFO, UARTS, and associated hardware.
-
-This passes control of the board to the bootstrap firmware, which performs a
-Power-On Self Test and which detects its current configuration. For example,
--IIEX products determine the size of FIFO which has been installed, and the
-number and type of expansion boxes attached.
-
-This and other information is then written to the FIFO in a 16-byte data block
-to be read by the host. This block is guaranteed to be present within two (2)
-seconds of having received the command reset. The firmware is now ready to
-receive loadware from the host.
-
-It is good practice to perform a command reset to the board explicitly as part
-of your software initialization.  This allows your code to properly restart from
-a soft boot. (Many systems do not issue channel reset on soft boot).
-
-Because of a hardware reset problem on some of the Cirrus Logic 1400's which are
-used on the product, it is recommended that you reset the board twice, separated
-by an approximately 50 milliseconds delay. (VERY approximately: probably ok to
-be off by a factor of five. The important point is that the first command reset
-in fact generates a reset pulse on the board. This pulse is guaranteed to last
-less than 10 milliseconds. The additional delay ensures the 1400 has had the
-chance to respond sufficiently to the first reset. Why not a longer delay? Much
-more than 50 milliseconds gets to be noticable, but the board would still work.
-
-Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap
-firmware is ready to receive loadware.
-
-Note on Power-on Reset Message format:
-The various fields have been designed with future expansion in view.
-Combinations of bitfields and values have been defined which define products
-which may not currently exist. This has been done to allow drivers to anticipate
-the possible introduction of products in a systematic fashion. This is not
-intended to suggest that each potential product is actually under consideration.
-------------------------------------------------------------------------------*/
-
-//----------------------------------------
-// Format of Power-on Reset Message
-//----------------------------------------
-
-typedef union _porStr		// "por" stands for Power On Reset
-{
-	unsigned char  c[16];	// array used when considering the message as a
-							// string of undifferentiated characters
-
-	struct					// Elements used when considering values
-	{
-		// The first two bytes out of the FIFO are two magic numbers. These are
-		// intended to establish that there is indeed a member of the
-		// IntelliPort-II(EX) family present. The remaining bytes may be 
-		// expected // to be valid. When reading the Power-on Reset message, 
-		// if the magic numbers do not match it is probably best to stop
-		// reading immediately. You are certainly not reading our board (unless
-		// hardware is faulty), and may in fact be reading some other piece of
-		// hardware.
-
-		unsigned char porMagic1;   // magic number: first byte == POR_MAGIC_1 
-		unsigned char porMagic2;   // magic number: second byte == POR_MAGIC_2 
-
-		// The Version, Revision, and Subrevision are stored as absolute numbers
-		// and would normally be displayed in the format V.R.S (e.g. 1.0.2)
-
-		unsigned char porVersion;  // Bootstrap firmware version number
-		unsigned char porRevision; // Bootstrap firmware revision number
-		unsigned char porSubRev;   // Bootstrap firmware sub-revision number
-
-		unsigned char porID;	// Product ID:  Bit-mapped according to
-								// conventions described below. Among other
-								// things, this allows us to distinguish
-								// IntelliPort-II boards from IntelliPort-IIEX
-								// boards.
-
-		unsigned char porBus;	// IntelliPort-II: Unused
-								// IntelliPort-IIEX: Bus Information:
-								// Bit-mapped below
-
-		unsigned char porMemory;	// On-board DRAM size: in 32k blocks
-
-		// porPorts1 (and porPorts2) are used to determine the ports which are
-		// available to the board. For non-expandable product, a single number 
-		// is sufficient. For expandable product, the board may be connected
-		// to as many as four boxes. Each box may be (so far) either a 16-port
-		// or an 8-port size. Whenever an 8-port box is used, the remaining 8
-		// ports leave gaps between existing channels. For that reason,
-		// expandable products must report a MAP of available channels. Since 
-		// each UART supports four ports, we represent each UART found by a
-		// single bit. Using two bytes to supply the mapping information we
-		// report the presense or absense of up to 16 UARTS, or 64 ports in
-		// steps of 4 ports. For -IIEX products, the ports are numbered
-		// starting at the box closest to the controller in the "chain".
-
-		// Interpreted Differently for IntelliPort-II and -IIEX.
-		// -II:   Number of ports (Derived actually from product ID). See
-		// Diag1&2 to indicate if uart was actually detected.
-		// -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This
-		//        bitmap is based on detecting the uarts themselves; 
-		//        see porFlags for information from the box i.d's.
-		unsigned char  porPorts1;
-
-		unsigned char  porDiag1;	// Results of on-board P.O.S.T, 1st byte
-		unsigned char  porDiag2;	// Results of on-board P.O.S.T, 2nd byte
-		unsigned char  porSpeed;	// Speed of local CPU: given as MHz x10
-									// e.g., 16.0 MHz CPU is reported as 160
-		unsigned char  porFlags;	// Misc information (see manifests below)
-									// Bit-mapped: CPU type, UART's present
-
-		unsigned char  porPorts2;	// -II:  Undefined
-									// -IIEX: Bit-map of UARTS found, MSB (see
-									//        above for LSB)
-
-		// IntelliPort-II: undefined
-		// IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the
-		// host interface FIFO, in each direction. When running the -IIEX in
-		// 8-bit mode, fifo capacity is halved. The bootstrap firmware will
-		// have already accounted for this fact in generating this number.
-		unsigned char  porFifoSize;
-
-		// IntelliPort-II: undefined
-		// IntelliPort-IIEX: The number of boxes connected. (Presently 1-4)
-		unsigned char  porNumBoxes;
-	} e;
-} porStr, *porStrPtr;
-
-//--------------------------
-// Values for porStr fields
-//--------------------------
-
-//---------------------
-// porMagic1, porMagic2
-//----------------------
-//
-#define  POR_MAGIC_1    0x96  // The only valid value for porMagic1
-#define  POR_MAGIC_2    0x35  // The only valid value for porMagic2
-#define  POR_1_INDEX    0     // Byte position of POR_MAGIC_1
-#define  POR_2_INDEX    1     // Ditto for POR_MAGIC_2
-
-//----------------------
-// porID
-//----------------------
-//
-#define  POR_ID_FAMILY  0xc0	// These bits indicate the general family of
-								// product.
-#define  POR_ID_FII     0x00	// Family is "IntelliPort-II"
-#define  POR_ID_FIIEX   0x40	// Family is "IntelliPort-IIEX"
-
-// These bits are reserved, presently zero. May be used at a later date to
-// convey other product information.
-//
-#define POR_ID_RESERVED 0x3c
-
-#define POR_ID_SIZE     0x03	// Remaining bits indicate number of ports &
-								// Connector information.
-#define POR_ID_II_8     0x00	// For IntelliPort-II, indicates 8-port using
-								// standard brick.
-#define POR_ID_II_8R    0x01	// For IntelliPort-II, indicates 8-port using
-								// RJ11's (no CTS)
-#define POR_ID_II_6     0x02	// For IntelliPort-II, indicates 6-port using
-								// RJ45's
-#define POR_ID_II_4     0x03	// For IntelliPort-II, indicates 4-port using
-								// 4xRJ45 connectors
-#define POR_ID_EX       0x00	// For IntelliPort-IIEX, indicates standard
-								// expandable controller (other values reserved)
-
-//----------------------
-// porBus
-//----------------------
-
-// IntelliPort-IIEX only: Board is installed in a 16-bit slot
-//
-#define POR_BUS_SLOT16  0x20
-
-// IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface
-// operation.
-// 
-#define POR_BUS_DIP16   0x10
-
-// Bits 0-2 indicate type of bus: This information is stored in the bootstrap
-// loadware, different loadware being used on different products for different
-// buses. For most situations, the drivers do not need this information; but it
-// is handy in a diagnostic environment. For example, on microchannel boards,
-// you would not want to try to test several interrupts, only the one for which
-// you were configured.
-//
-#define  POR_BUS_TYPE   0x07
-
-// Unknown:  this product doesn't know what bus it is running in. (e.g. if same
-// bootstrap firmware were wanted for two different buses.)
-//
-#define  POR_BUS_T_UNK  0
-
-// Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK
-// state, since the same bootstrap firmware is used for each.
-
-#define  POR_BUS_T_MCA  1  // MCA BUS */
-#define  POR_BUS_T_EISA 2  // EISA BUS */
-#define  POR_BUS_T_ISA  3  // ISA BUS */
-
-// Values 4-7 Reserved
-
-// Remaining bits are reserved
-
-//----------------------
-// porDiag1
-//----------------------
-
-#define  POR_BAD_MAPPER 0x80	// HW failure on P.O.S.T: Chip mapper failed
-
-// These two bits valid only for the IntelliPort-II
-//
-#define  POR_BAD_UART1  0x01	// First  1400 bad
-#define  POR_BAD_UART2  0x02	// Second 1400 bad
-
-//----------------------
-// porDiag2
-//----------------------
-
-#define  POR_DEBUG_PORT 0x80	// debug port was detected by the P.O.S.T
-#define  POR_DIAG_OK    0x00	// Indicates passage: Failure codes not yet
-								// available.
-								// Other bits undefined.
-//----------------------
-// porFlags
-//----------------------
-
-#define  POR_CPU     0x03	// These bits indicate supposed CPU type
-#define  POR_CPU_8   0x01	// Board uses an 80188 (no such thing yet)
-#define  POR_CPU_6   0x02	// Board uses an 80186 (all existing products)
-#define  POR_CEX4    0x04	// If set, this is an ISA-CEX/4: An ISA-4 (asic)
-							// which is architected like an ISA-CEX connected
-							// to a (hitherto impossible) 4-port box.
-#define POR_BOXES    0xf0	// Valid for IntelliPort-IIEX only: Map of Box
-							// sizes based on box I.D.
-#define POR_BOX_16   0x10	// Set indicates 16-port, clear 8-port
-
-//-------------------------------------
-// LOADWARE and DOWNLOADING CODE
-//-------------------------------------
-
-/*
-Loadware may be sent to the board in two ways:
-1) It may be read from a (binary image) data file block by block as each block
-	is sent to the board. This is only possible when the initialization is
-	performed by code which can access your file system. This is most suitable
-	for diagnostics and appications which use the interface library directly.
-
-2) It may be hard-coded into your source by including a .h file (typically
-	supplied by Computone), which declares a data array and initializes every
-	element. This achieves the same result as if an entire loadware file had 
-	been read into the array.
-
-	This requires more data space in your program, but access to the file system
-	is not required. This method is more suited to driver code, which typically
-	is running at a level too low to access the file system directly.
-
-At present, loadware can only be generated at Computone.
-
-All Loadware begins with a header area which has a particular format. This
-includes a magic number which identifies the file as being (purportedly)
-loadware, CRC (for the loader), and version information.
-*/
-
-
-//-----------------------------------------------------------------------------
-// Format of loadware block
-//
-// This is defined as a union so we can pass a pointer to one of these items
-// and (if it is the first block) pick out the version information, etc.
-//
-// Otherwise, to deal with this as a simple character array
-//------------------------------------------------------------------------------
-
-#define LOADWARE_BLOCK_SIZE   512   // Number of bytes in each block of loadware
-
-typedef union _loadHdrStr
-{
-	unsigned char c[LOADWARE_BLOCK_SIZE];  // Valid for every block
-
-	struct	// These fields are valid for only the first block of loadware.
-	{
-		unsigned char loadMagic;		// Magic number: see below
-		unsigned char loadBlocksMore;	// How many more blocks?
-		unsigned char loadCRC[2];		// Two CRC bytes: used by loader
-		unsigned char loadVersion;		// Version number
-		unsigned char loadRevision;		// Revision number
-		unsigned char loadSubRevision;	// Sub-revision number
-		unsigned char loadSpares[9];	// Presently unused
-		unsigned char loadDates[32];	// Null-terminated string which can give
-										// date and time of compilation
-	} e;
-} loadHdrStr, *loadHdrStrPtr;
-
-//------------------------------------
-// Defines for downloading code:
-//------------------------------------
-
-// The loadMagic field in the first block of the loadfile must be this, else the
-// file is not valid.
-//
-#define  MAGIC_LOADFILE 0x3c
-
-// How do we know the load was successful? On completion of the load, the
-// bootstrap firmware returns a code to indicate whether it thought the download
-// was valid and intends to execute it. These are the only possible valid codes:
-//
-#define  LOADWARE_OK    0xc3        // Download was ok
-#define  LOADWARE_BAD   0x5a        // Download was bad (CRC error)
-
-// Constants applicable to writing blocks of loadware:
-// The first block of loadware might take 600 mS to load, in extreme cases.
-// (Expandable board: worst case for sending startup messages to the LCD's).
-// The 600mS figure is not really a calculation, but a conservative
-// guess/guarantee. Usually this will be within 100 mS, like subsequent blocks.
-//
-#define  MAX_DLOAD_START_TIME 1000  // 1000 mS
-#define  MAX_DLOAD_READ_TIME  100   // 100 mS
-
-// Firmware should respond with status (see above) within this long of host
-// having sent the final block.
-//
-#define  MAX_DLOAD_ACK_TIME   100   // 100 mS, again!
-
-//------------------------------------------------------
-// MAXIMUM NUMBER OF PORTS PER BOARD:
-// This is fixed for now (with the expandable), but may
-// be expanding according to even newer products.
-//------------------------------------------------------
-//
-#define ABS_MAX_BOXES   4     // Absolute most boxes per board
-#define ABS_BIGGEST_BOX 16    // Absolute the most ports per box
-#define ABS_MOST_PORTS  (ABS_MAX_BOXES * ABS_BIGGEST_BOX)
-
-#define I2_OUTSW(port, addr, count)	outsw((port), (addr), (((count)+1)/2))
-#define I2_OUTSB(port, addr, count)	outsb((port), (addr), (((count)+1))&-2)
-#define I2_INSW(port, addr, count)	insw((port), (addr), (((count)+1)/2))
-#define I2_INSB(port, addr, count)	insb((port), (addr), (((count)+1))&-2)
-
-#endif   // I2HW_H
-
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c
deleted file mode 100644
index 0d10b89..0000000
--- a/drivers/char/ip2/i2lib.c
+++ /dev/null
@@ -1,2214 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: High-level interface code for the device driver. Uses the
-*                Extremely Low Level Interface Support (i2ellis.c). Provides an
-*                interface to the standard loadware, to support drivers or
-*                application code. (This is included source code, not a separate
-*                compilation module.)
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// Note on Strategy:
-// Once the board has been initialized, it will interrupt us when:
-// 1) It has something in the fifo for us to read (incoming data, flow control
-// packets, or whatever).
-// 2) It has stripped whatever we have sent last time in the FIFO (and
-// consequently is ready for more).
-//
-// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This
-// worsens performance considerably, but is done so that a great many channels
-// might use only a little memory.
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 0.00 -  4/16/91 --- First Draft
-// 0.01 -  4/29/91 --- 1st beta release
-// 0.02 -  6/14/91 --- Changes to allow small model compilation
-// 0.03 -  6/17/91 MAG Break reporting protected from interrupts routines with
-//                     in-line asm added for moving data to/from ring buffers,
-//                     replacing a variety of methods used previously.
-// 0.04 -  6/21/91 MAG Initial flow-control packets not queued until
-//                     i2_enable_interrupts time. Former versions would enqueue
-//                     them at i2_init_channel time, before we knew how many
-//                     channels were supposed to exist!
-// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now;
-//                     supports new 16-bit protocol and expandable boards.
-//      - 10/24/91 MAG Most changes in place and stable.
-// 0.06 -  2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no
-//                     argument.
-// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt
-//                     level (mostly responses to specific commands.)
-// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet
-// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE
-//                     turning on the interrupt.
-// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check
-//                     some incoming.
-//
-// 1.1  - 12/25/96 AKM Linux version.
-//      - 10/09/98 DMC Revised Linux version.
-//------------------------------------------------------------------------------
-
-//************
-//* Includes *
-//************
-
-#include <linux/sched.h>
-#include "i2lib.h"
-
-
-//***********************
-//* Function Prototypes *
-//***********************
-static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int);
-static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int );
-static void i2StripFifo(i2eBordStrPtr);
-static void i2StuffFifoBypass(i2eBordStrPtr);
-static void i2StuffFifoFlow(i2eBordStrPtr);
-static void i2StuffFifoInline(i2eBordStrPtr);
-static int i2RetryFlushOutput(i2ChanStrPtr);
-
-// Not a documented part of the library routines (careful...) but the Diagnostic
-// i2diag.c finds them useful to help the throughput in certain limited
-// single-threaded operations.
-static void iiSendPendingMail(i2eBordStrPtr);
-static void serviceOutgoingFifo(i2eBordStrPtr);
-
-// Functions defined in ip2.c as part of interrupt handling
-static void do_input(struct work_struct *);
-static void do_status(struct work_struct *);
-
-//***************
-//* Debug  Data *
-//***************
-#ifdef DEBUG_FIFO
-
-unsigned char DBGBuf[0x4000];
-unsigned short I = 0;
-
-static void
-WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) 
-{
-	char *p = src;
-
-	// XXX: We need a spin lock here if we ever use this again
-
-	while (*s) {	// copy label
-		DBGBuf[I] = *s++;
-		I = I++ & 0x3fff;
-	}
-	while (n--) {	// copy data
-		DBGBuf[I] = *p++;
-		I = I++ & 0x3fff;
-	}
-}
-
-static void
-fatality(i2eBordStrPtr pB )
-{
-	int i;
-
-	for (i=0;i<sizeof(DBGBuf);i++) {
-		if ((i%16) == 0)
-			printk("\n%4x:",i);
-		printk("%02x ",DBGBuf[i]);
-	}
-	printk("\n");
-	for (i=0;i<sizeof(DBGBuf);i++) {
-		if ((i%16) == 0)
-			printk("\n%4x:",i);
-		if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') {
-			printk(" %c ",DBGBuf[i]);
-		} else {
-			printk(" . ");
-		}
-	}
-	printk("\n");
-	printk("Last index %x\n",I);
-}
-#endif /* DEBUG_FIFO */
-
-//********
-//* Code *
-//********
-
-static inline int
-i2Validate ( i2ChanStrPtr pCh )
-{
-	//ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity,
-	//	(CHANNEL_MAGIC | CHANNEL_SUPPORT));
-	return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) 
-			  == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
-}
-
-static void iiSendPendingMail_t(unsigned long data)
-{
-	i2eBordStrPtr pB = (i2eBordStrPtr)data;
-
-	iiSendPendingMail(pB);
-}
-
-//******************************************************************************
-// Function:   iiSendPendingMail(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// If any outgoing mail bits are set and there is outgoing mailbox is empty,
-// send the mail and clear the bits.
-//******************************************************************************
-static void
-iiSendPendingMail(i2eBordStrPtr pB)
-{
-	if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
-	{
-		if (iiTrySendMail(pB, pB->i2eOutMailWaiting))
-		{
-			/* If we were already waiting for fifo to empty,
-			 * or just sent MB_OUT_STUFFED, then we are
-			 * still waiting for it to empty, until we should
-			 * receive an MB_IN_STRIPPED from the board.
-			 */
-			pB->i2eWaitingForEmptyFifo |=
-				(pB->i2eOutMailWaiting & MB_OUT_STUFFED);
-			pB->i2eOutMailWaiting = 0;
-			pB->SendPendingRetry = 0;
-		} else {
-/*		The only time we hit this area is when "iiTrySendMail" has
-		failed.  That only occurs when the outbound mailbox is
-		still busy with the last message.  We take a short breather
-		to let the board catch up with itself and then try again.
-		16 Retries is the limit - then we got a borked board.
-			/\/\|=mhw=|\/\/				*/
-
-			if( ++pB->SendPendingRetry < 16 ) {
-				setup_timer(&pB->SendPendingTimer,
-					iiSendPendingMail_t, (unsigned long)pB);
-				mod_timer(&pB->SendPendingTimer, jiffies + 1);
-			} else {
-				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
-			}
-		}
-	}
-}
-
-//******************************************************************************
-// Function:   i2InitChannels(pB, nChannels, pCh)
-// Parameters: Pointer to Ellis Board structure
-//             Number of channels to initialize
-//             Pointer to first element in an array of channel structures
-// Returns:    Success or failure
-//
-// Description:
-//
-// This function patches pointers, back-pointers, and initializes all the
-// elements in the channel structure array.
-//
-// This should be run after the board structure is initialized, through having
-// loaded the standard loadware (otherwise it complains).
-//
-// In any case, it must be done before any serious work begins initializing the
-// irq's or sending commands...
-//
-//******************************************************************************
-static int
-i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
-{
-	int index, stuffIndex;
-	i2ChanStrPtr *ppCh;
-	
-	if (pB->i2eValid != I2E_MAGIC) {
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-	if (pB->i2eState != II_STATE_STDLOADED) {
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-
-	rwlock_init(&pB->read_fifo_spinlock);
-	rwlock_init(&pB->write_fifo_spinlock);
-	rwlock_init(&pB->Dbuf_spinlock);
-	rwlock_init(&pB->Bbuf_spinlock);
-	rwlock_init(&pB->Fbuf_spinlock);
-	
-	// NO LOCK needed yet - this is init
-
-	pB->i2eChannelPtr = pCh;
-	pB->i2eChannelCnt = nChannels;
-
-	pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0;
-	pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0;
-	pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0;
-
-	pB->SendPendingRetry = 0;
-
-	memset ( pCh, 0, sizeof (i2ChanStr) * nChannels );
-
-	for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf);
-		  nChannels && index < ABS_MOST_PORTS;
-		  index++)
-	{
-		if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
-			continue;
-		}
-		rwlock_init(&pCh->Ibuf_spinlock);
-		rwlock_init(&pCh->Obuf_spinlock);
-		rwlock_init(&pCh->Cbuf_spinlock);
-		rwlock_init(&pCh->Pbuf_spinlock);
-		// NO LOCK needed yet - this is init
-		// Set up validity flag according to support level
-		if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
-			pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT;
-		} else {
-			pCh->validity = CHANNEL_MAGIC;
-		}
-		pCh->pMyBord = pB;      /* Back-pointer */
-
-		// Prepare an outgoing flow-control packet to send as soon as the chance
-		// occurs.
-		if ( pCh->validity & CHANNEL_SUPPORT ) {
-			pCh->infl.hd.i2sChannel = index;
-			pCh->infl.hd.i2sCount = 5;
-			pCh->infl.hd.i2sType = PTYPE_BYPASS;
-			pCh->infl.fcmd = 37;
-			pCh->infl.asof = 0;
-			pCh->infl.room = IBUF_SIZE - 1;
-
-			pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full
-
-		// The following is similar to calling i2QueueNeeds, except that this
-		// is done in longhand, since we are setting up initial conditions on
-		// many channels at once.
-			pCh->channelNeeds = NEED_FLOW;  // Since starting from scratch
-			pCh->sinceLastFlow = 0;         // No bytes received since last flow
-											// control packet was queued
-			stuffIndex++;
-			*ppCh++ = pCh;      // List this channel as needing
-								// initial flow control packet sent
-		}
-
-		// Don't allow anything to be sent until the status packets come in from
-		// the board.
-
-		pCh->outfl.asof = 0;
-		pCh->outfl.room = 0;
-
-		// Initialize all the ring buffers
-
-		pCh->Ibuf_stuff = pCh->Ibuf_strip = 0;
-		pCh->Obuf_stuff = pCh->Obuf_strip = 0;
-		pCh->Cbuf_stuff = pCh->Cbuf_strip = 0;
-
-		memset( &pCh->icount, 0, sizeof (struct async_icount) );
-		pCh->hotKeyIn       = HOT_CLEAR;
-		pCh->channelOptions = 0;
-		pCh->bookMarks      = 0;
-		init_waitqueue_head(&pCh->pBookmarkWait);
-
-		init_waitqueue_head(&pCh->open_wait);
-		init_waitqueue_head(&pCh->close_wait);
-		init_waitqueue_head(&pCh->delta_msr_wait);
-
-		// Set base and divisor so default custom rate is 9600
-		pCh->BaudBase    = 921600;	// MAX for ST654, changed after we get
-		pCh->BaudDivisor = 96;		// the boxids (UART types) later
-
-		pCh->dataSetIn   = 0;
-		pCh->dataSetOut  = 0;
-
-		pCh->wopen       = 0;
-		pCh->throttled   = 0;
-
-		pCh->speed       = CBR_9600;
-
-		pCh->flags    = 0;
-
-		pCh->ClosingDelay     = 5*HZ/10;
-		pCh->ClosingWaitTime  = 30*HZ;
-
-		// Initialize task queue objects
-		INIT_WORK(&pCh->tqueue_input, do_input);
-		INIT_WORK(&pCh->tqueue_status, do_status);
-
-#ifdef IP2DEBUG_TRACE
-		pCh->trace = ip2trace;
-#endif
-
-		++pCh;
-     	--nChannels;
-	}
-	// No need to check for wrap here; this is initialization.
-	pB->i2Fbuf_stuff = stuffIndex;
-	I2_COMPLETE(pB, I2EE_GOOD);
-
-}
-
-//******************************************************************************
-// Function:   i2DeQueueNeeds(pB, type)
-// Parameters: Pointer to a board structure
-//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
-// Returns:   
-//             Pointer to a channel structure
-//
-// Description: Returns pointer struct of next channel that needs service of
-//  the type specified. Otherwise returns a NULL reference.
-//
-//******************************************************************************
-static i2ChanStrPtr 
-i2DeQueueNeeds(i2eBordStrPtr pB, int type)
-{
-	unsigned short queueIndex;
-	unsigned long flags;
-
-	i2ChanStrPtr pCh = NULL;
-
-	switch(type) {
-
-	case  NEED_INLINE:
-
-		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
-		if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
-		{
-			queueIndex = pB->i2Dbuf_strip;
-			pCh = pB->i2Dbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Dbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_INLINE;
-		}
-		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
-		break;
-
-	case NEED_BYPASS:
-
-		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
-		if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
-		{
-			queueIndex = pB->i2Bbuf_strip;
-			pCh = pB->i2Bbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Bbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_BYPASS;
-		}
-		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
-		break;
-	
-	case NEED_FLOW:
-
-		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
-		if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
-		{
-			queueIndex = pB->i2Fbuf_strip;
-			pCh = pB->i2Fbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Fbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_FLOW;
-		}
-		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
-		break;
-	default:
-		printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type);
-		break;
-	}
-	return pCh;
-}
-
-//******************************************************************************
-// Function:   i2QueueNeeds(pB, pCh, type)
-// Parameters: Pointer to a board structure
-//             Pointer to a channel structure
-//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
-// Returns:    Nothing
-//
-// Description:
-// For each type of need selected, if the given channel is not already in the
-// queue, adds it, and sets the flag indicating it is in the queue.
-//******************************************************************************
-static void
-i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
-{
-	unsigned short queueIndex;
-	unsigned long flags;
-
-	// We turn off all the interrupts during this brief process, since the
-	// interrupt-level code might want to put things on the queue as well.
-
-	switch (type) {
-
-	case NEED_INLINE:
-
-		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
-		if ( !(pCh->channelNeeds & NEED_INLINE) )
-		{
-			pCh->channelNeeds |= NEED_INLINE;
-			queueIndex = pB->i2Dbuf_stuff;
-			pB->i2Dbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Dbuf_stuff = queueIndex;
-		}
-		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
-		break;
-
-	case NEED_BYPASS:
-
-		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
-		if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
-		{
-			pCh->channelNeeds |= NEED_BYPASS;
-			queueIndex = pB->i2Bbuf_stuff;
-			pB->i2Bbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Bbuf_stuff = queueIndex;
-		} 
-		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
-		break;
-
-	case NEED_FLOW:
-
-		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
-		if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
-		{
-			pCh->channelNeeds |= NEED_FLOW;
-			queueIndex = pB->i2Fbuf_stuff;
-			pB->i2Fbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Fbuf_stuff = queueIndex;
-		}
-		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
-		break;
-
-	case NEED_CREDIT:
-		pCh->channelNeeds |= NEED_CREDIT;
-		break;
-	default:
-		printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type);
-		break;
-	}
-	return;
-}
-
-//******************************************************************************
-// Function:   i2QueueCommands(type, pCh, timeout, nCommands, pCs,...)
-// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE
-//             pointer to the channel structure
-//             maximum period to wait
-//             number of commands (n)
-//             n commands
-// Returns:    Number of commands sent, or -1 for error
-//
-// get board lock before calling
-//
-// Description:
-// Queues up some commands to be sent to a channel. To send possibly several
-// bypass or inline commands to the given channel. The timeout parameter
-// indicates how many HUNDREDTHS OF SECONDS to wait until there is room:
-// 0 = return immediately if no room, -ive  = wait forever, +ive = number of
-// 1/100 seconds to wait. Return values:
-// -1 Some kind of nasty error: bad channel structure or invalid arguments.
-//  0 No room to send all the commands
-// (+)   Number of commands sent
-//******************************************************************************
-static int
-i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
-					 cmdSyntaxPtr pCs0,...)
-{
-	int totalsize = 0;
-	int blocksize;
-	int lastended;
-	cmdSyntaxPtr *ppCs;
-	cmdSyntaxPtr pCs;
-	int count;
-	int flag;
-	i2eBordStrPtr pB;
-
-	unsigned short maxBlock;
-	unsigned short maxBuff;
-	short bufroom;
-	unsigned short stuffIndex;
-	unsigned char *pBuf;
-	unsigned char *pInsert;
-	unsigned char *pDest, *pSource;
-	unsigned short channel;
-	int cnt;
-	unsigned long flags = 0;
-	rwlock_t *lock_var_p = NULL;
-
-	// Make sure the channel exists, otherwise do nothing
-	if ( !i2Validate ( pCh ) ) {
-		return -1;
-	}
-
-	ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );
-
-	pB = pCh->pMyBord;
-
-	// Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT
-	if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED)
-		return -2;
-	// If the board has gone fatal, return bad, and also hit the trap routine if
-	// it exists.
-	if (pB->i2eFatal) {
-		if ( pB->i2eFatalTrap ) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return -3;
-	}
-	// Set up some variables, Which buffers are we using?  How big are they?
-	switch(type)
-	{
-	case PTYPE_INLINE:
-		flag = INL;
-		maxBlock = MAX_OBUF_BLOCK;
-		maxBuff = OBUF_SIZE;
-		pBuf = pCh->Obuf;
-		break;
-	case PTYPE_BYPASS:
-		flag = BYP;
-		maxBlock = MAX_CBUF_BLOCK;
-		maxBuff = CBUF_SIZE;
-		pBuf = pCh->Cbuf;
-		break;
-	default:
-		return -4;
-	}
-	// Determine the total size required for all the commands
-	totalsize = blocksize = sizeof(i2CmdHeader);
-	lastended = 0;
-	ppCs = &pCs0;
-	for ( count = nCommands; count; count--, ppCs++)
-	{
-		pCs = *ppCs;
-		cnt = pCs->length;
-		// Will a new block be needed for this one? 
-		// Two possible reasons: too
-		// big or previous command has to be at the end of a packet.
-		if ((blocksize + cnt > maxBlock) || lastended) {
-			blocksize = sizeof(i2CmdHeader);
-			totalsize += sizeof(i2CmdHeader);
-		}
-		totalsize += cnt;
-		blocksize += cnt;
-
-		// If this command had to end a block, then we will make sure to
-		// account for it should there be any more blocks.
-		lastended = pCs->flags & END;
-	}
-	for (;;) {
-		// Make sure any pending flush commands go out before we add more data.
-		if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {
-			// How much room (this time through) ?
-			switch(type) {
-			case PTYPE_INLINE:
-				lock_var_p = &pCh->Obuf_spinlock;
-				write_lock_irqsave(lock_var_p, flags);
-				stuffIndex = pCh->Obuf_stuff;
-				bufroom = pCh->Obuf_strip - stuffIndex;
-				break;
-			case PTYPE_BYPASS:
-				lock_var_p = &pCh->Cbuf_spinlock;
-				write_lock_irqsave(lock_var_p, flags);
-				stuffIndex = pCh->Cbuf_stuff;
-				bufroom = pCh->Cbuf_strip - stuffIndex;
-				break;
-			default:
-				return -5;
-			}
-			if (--bufroom < 0) {
-				bufroom += maxBuff;
-			}
-
-			ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );
-
-			// Check for overflow
-			if (totalsize <= bufroom) {
-				// Normal Expected path - We still hold LOCK
-				break; /* from for()- Enough room: goto proceed */
-			}
-			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-			write_unlock_irqrestore(lock_var_p, flags);
-		} else
-			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-
-		/* Prepare to wait for buffers to empty */
-		serviceOutgoingFifo(pB);	// Dump what we got
-
-		if (timeout == 0) {
-			return 0;   // Tired of waiting
-		}
-		if (timeout > 0)
-			timeout--;   // So negative values == forever
-		
-		if (!in_interrupt()) {
-			schedule_timeout_interruptible(1);	// short nap
-		} else {
-			// we cannot sched/sleep in interrupt silly
-			return 0;   
-		}
-		if (signal_pending(current)) {
-			return 0;   // Wake up! Time to die!!!
-		}
-
-		ip2trace (CHANN, ITRC_QUEUE, 4, 0 );
-
-	}	// end of for(;;)
-
-	// At this point we have room and the lock - stick them in.
-	channel = pCh->infl.hd.i2sChannel;
-	pInsert = &pBuf[stuffIndex];     // Pointer to start of packet
-	pDest = CMD_OF(pInsert);         // Pointer to start of command
-
-	// When we start counting, the block is the size of the header
-	for (blocksize = sizeof(i2CmdHeader), count = nCommands,
-			lastended = 0, ppCs = &pCs0;
-		count;
-		count--, ppCs++)
-	{
-		pCs = *ppCs;         // Points to command protocol structure
-
-		// If this is a bookmark request command, post the fact that a bookmark
-		// request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ
-		// has no parameters!  The more general solution would be to reference
-		// pCs->cmd[0].
-		if (pCs == CMD_BMARK_REQ) {
-			pCh->bookMarks++;
-
-			ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );
-
-		}
-		cnt = pCs->length;
-
-		// If this command would put us over the maximum block size or 
-		// if the last command had to be at the end of a block, we end
-		// the existing block here and start a new one.
-		if ((blocksize + cnt > maxBlock) || lastended) {
-
-			ip2trace (CHANN, ITRC_QUEUE, 5, 0 );
-
-			PTYPE_OF(pInsert) = type;
-			CHANNEL_OF(pInsert) = channel;
-			// count here does not include the header
-			CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
-			stuffIndex += blocksize;
-			if(stuffIndex >= maxBuff) {
-				stuffIndex = 0;
-				pInsert = pBuf;
-			}
-			pInsert = &pBuf[stuffIndex];  // Pointer to start of next pkt
-			pDest = CMD_OF(pInsert);
-			blocksize = sizeof(i2CmdHeader);
-		}
-		// Now we know there is room for this one in the current block
-
-		blocksize += cnt;       // Total bytes in this command
-		pSource = pCs->cmd;     // Copy the command into the buffer
-		while (cnt--) {
-			*pDest++ = *pSource++;
-		}
-		// If this command had to end a block, then we will make sure to account
-		// for it should there be any more blocks.
-		lastended = pCs->flags & END;
-	}	// end for
-	// Clean up the final block by writing header, etc
-
-	PTYPE_OF(pInsert) = type;
-	CHANNEL_OF(pInsert) = channel;
-	// count here does not include the header
-	CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
-	stuffIndex += blocksize;
-	if(stuffIndex >= maxBuff) {
-		stuffIndex = 0;
-		pInsert = pBuf;
-	}
-	// Updates the index, and post the need for service. When adding these to
-	// the queue of channels, we turn off the interrupt while doing so,
-	// because at interrupt level we might want to push a channel back to the
-	// end of the queue.
-	switch(type)
-	{
-	case PTYPE_INLINE:
-		pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer
-		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-		pB->debugInlineQueued++;
-		// Add the channel pointer to list of channels needing service (first
-		// come...), if it's not already there.
-		i2QueueNeeds(pB, pCh, NEED_INLINE);
-		break;
-
-	case PTYPE_BYPASS:
-		pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer
-		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
-
-		pB->debugBypassQueued++;
-		// Add the channel pointer to list of channels needing service (first
-		// come...), if it's not already there.
-		i2QueueNeeds(pB, pCh, NEED_BYPASS);
-		break;
-	}
-
-	ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );
-
-	return nCommands; // Good status: number of commands sent
-}
-
-//******************************************************************************
-// Function:   i2GetStatus(pCh,resetBits)
-// Parameters: Pointer to a channel structure
-//             Bit map of status bits to clear
-// Returns:    Bit map of current status bits
-//
-// Description:
-// Returns the state of data set signals, and whether a break has been received,
-// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status
-// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared
-// AFTER the condition is passed. If pCh does not point to a valid channel,
-// returns -1 (which would be impossible otherwise.
-//******************************************************************************
-static int
-i2GetStatus(i2ChanStrPtr pCh, int resetBits)
-{
-	unsigned short status;
-	i2eBordStrPtr pB;
-
-	ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );
-
-	// Make sure the channel exists, otherwise do nothing */
-	if ( !i2Validate ( pCh ) )
-		return -1;
-
-	pB = pCh->pMyBord;
-
-	status = pCh->dataSetIn;
-
-	// Clear any specified error bits: but note that only actual error bits can
-	// be cleared, regardless of the value passed.
-	if (resetBits)
-	{
-		pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));
-		pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);
-	}
-
-	ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );
-
-	return status;
-}
-
-//******************************************************************************
-// Function:   i2Input(pChpDest,count)
-// Parameters: Pointer to a channel structure
-//             Pointer to data buffer
-//             Number of bytes to read
-// Returns:    Number of bytes read, or -1 for error
-//
-// Description:
-// Strips data from the input buffer and writes it to pDest. If there is a
-// collosal blunder, (invalid structure pointers or the like), returns -1.
-// Otherwise, returns the number of bytes read.
-//******************************************************************************
-static int
-i2Input(i2ChanStrPtr pCh)
-{
-	int amountToMove;
-	unsigned short stripIndex;
-	int count;
-	unsigned long flags = 0;
-
-	ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);
-
-	// Ensure channel structure seems real
-	if ( !i2Validate( pCh ) ) {
-		count = -1;
-		goto i2Input_exit;
-	}
-	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-
-	// initialize some accelerators and private copies
-	stripIndex = pCh->Ibuf_strip;
-
-	count = pCh->Ibuf_stuff - stripIndex;
-
-	// If buffer is empty or requested data count was 0, (trivial case) return
-	// without any further thought.
-	if ( count == 0 ) {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		goto i2Input_exit;
-	}
-	// Adjust for buffer wrap
-	if ( count < 0 ) {
-		count += IBUF_SIZE;
-	}
-	// Don't give more than can be taken by the line discipline
-	amountToMove = pCh->pTTY->receive_room;
-	if (count > amountToMove) {
-		count = amountToMove;
-	}
-	// How much could we copy without a wrap?
-	amountToMove = IBUF_SIZE - stripIndex;
-
-	if (amountToMove > count) {
-		amountToMove = count;
-	}
-	// Move the first block
-	pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
-		 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
-	// If we needed to wrap, do the second data move
-	if (count > amountToMove) {
-		pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
-		 pCh->Ibuf, NULL, count - amountToMove );
-	}
-	// Bump and wrap the stripIndex all at once by the amount of data read. This
-	// method is good regardless of whether the data was in one or two pieces.
-	stripIndex += count;
-	if (stripIndex >= IBUF_SIZE) {
-		stripIndex -= IBUF_SIZE;
-	}
-	pCh->Ibuf_strip = stripIndex;
-
-	// Update our flow control information and possibly queue ourselves to send
-	// it, depending on how much data has been stripped since the last time a
-	// packet was sent.
-	pCh->infl.asof += count;
-
-	if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
-		pCh->sinceLastFlow -= pCh->whenSendFlow;
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
-	} else {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	}
-
-i2Input_exit:
-
-	ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);
-
-	return count;
-}
-
-//******************************************************************************
-// Function:   i2InputFlush(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Number of bytes stripped, or -1 for error
-//
-// Description:
-// Strips any data from the input buffer. If there is a collosal blunder,
-// (invalid structure pointers or the like), returns -1. Otherwise, returns the
-// number of bytes stripped.
-//******************************************************************************
-static int
-i2InputFlush(i2ChanStrPtr pCh)
-{
-	int count;
-	unsigned long flags;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) )
-		return -1;
-
-	ip2trace (CHANN, ITRC_INPUT, 10, 0);
-
-	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-
-	// Adjust for buffer wrap
-	if (count < 0) {
-		count += IBUF_SIZE;
-	}
-
-	// Expedient way to zero out the buffer
-	pCh->Ibuf_strip = pCh->Ibuf_stuff;
-
-
-	// Update our flow control information and possibly queue ourselves to send
-	// it, depending on how much data has been stripped since the last time a
-	// packet was sent.
-
-	pCh->infl.asof += count;
-
-	if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
-	{
-		pCh->sinceLastFlow -= pCh->whenSendFlow;
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
-	} else {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	}
-
-	ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
-
-	return count;
-}
-
-//******************************************************************************
-// Function:   i2InputAvailable(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Number of bytes available, or -1 for error
-//
-// Description:
-// If there is a collosal blunder, (invalid structure pointers or the like),
-// returns -1. Otherwise, returns the number of bytes stripped. Otherwise,
-// returns the number of bytes available in the buffer.
-//******************************************************************************
-#if 0
-static int
-i2InputAvailable(i2ChanStrPtr pCh)
-{
-	int count;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) return -1;
-
-
-	// initialize some accelerators and private copies
-	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-	read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-
-	// Adjust for buffer wrap
-	if (count < 0)
-	{
-		count += IBUF_SIZE;
-	}
-
-	return count;
-}
-#endif 
-
-//******************************************************************************
-// Function:   i2Output(pCh, pSource, count)
-// Parameters: Pointer to channel structure
-//             Pointer to source data
-//             Number of bytes to send
-// Returns:    Number of bytes sent, or -1 for error
-//
-// Description:
-// Queues the data at pSource to be sent as data packets to the board. If there
-// is a collosal blunder, (invalid structure pointers or the like), returns -1.
-// Otherwise, returns the number of bytes written. What if there is not enough
-// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then
-// we transfer as many characters as we can now, then return. If this bit is
-// clear (default), routine will spin along until all the data is buffered.
-// Should this occur, the 1-ms delay routine is called while waiting to avoid
-// applications that one cannot break out of.
-//******************************************************************************
-static int
-i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
-{
-	i2eBordStrPtr pB;
-	unsigned char *pInsert;
-	int amountToMove;
-	int countOriginal = count;
-	unsigned short channel;
-	unsigned short stuffIndex;
-	unsigned long flags;
-
-	int bailout = 10;
-
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 );
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) 
-		return -1;
-
-	// initialize some accelerators and private copies
-	pB = pCh->pMyBord;
-	channel = pCh->infl.hd.i2sChannel;
-
-	// If the board has gone fatal, return bad, and also hit the trap routine if
-	// it exists.
-	if (pB->i2eFatal) {
-		if (pB->i2eFatalTrap) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return -1;
-	}
-	// Proceed as though we would do everything
-	while ( count > 0 ) {
-
-		// How much room in output buffer is there?
-		read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-		amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-		read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-		if (amountToMove < 0) {
-			amountToMove += OBUF_SIZE;
-		}
-		// Subtract off the headers size and see how much room there is for real
-		// data. If this is negative, we will discover later.
-		amountToMove -= sizeof (i2DataHeader);
-
-		// Don't move more (now) than can go in a single packet
-		if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {
-			amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);
-		}
-		// Don't move more than the count we were given
-		if (amountToMove > count) {
-			amountToMove = count;
-		}
-		// Now we know how much we must move: NB because the ring buffers have
-		// an overflow area at the end, we needn't worry about wrapping in the
-		// middle of a packet.
-
-// Small WINDOW here with no LOCK but I can't call Flush with LOCK
-// We would be flushing (or ending flush) anyway
-
-		ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );
-
-		if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 
-				&& amountToMove > 0 )
-		{
-			write_lock_irqsave(&pCh->Obuf_spinlock, flags);
-			stuffIndex = pCh->Obuf_stuff;
-      
-			// Had room to move some data: don't know whether the block size,
-			// buffer space, or what was the limiting factor...
-			pInsert = &(pCh->Obuf[stuffIndex]);
-
-			// Set up the header
-			CHANNEL_OF(pInsert)     = channel;
-			PTYPE_OF(pInsert)       = PTYPE_DATA;
-			TAG_OF(pInsert)         = 0;
-			ID_OF(pInsert)          = ID_ORDINARY_DATA;
-			DATA_COUNT_OF(pInsert)  = amountToMove;
-
-			// Move the data
-			memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
-			// Adjust pointers and indices
-			pSource					+= amountToMove;
-			pCh->Obuf_char_count	+= amountToMove;
-			stuffIndex 				+= amountToMove + sizeof(i2DataHeader);
-			count 					-= amountToMove;
-
-			if (stuffIndex >= OBUF_SIZE) {
-				stuffIndex = 0;
-			}
-			pCh->Obuf_stuff = stuffIndex;
-
-			write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-			ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
-
-		} else {
-
-			// Cannot move data
-			// becuz we need to stuff a flush 
-			// or amount to move is <= 0
-
-			ip2trace(CHANN, ITRC_OUTPUT, 14, 3,
-				amountToMove,  pB->i2eFifoRemains,
-				pB->i2eWaitingForEmptyFifo );
-
-			// Put this channel back on queue
-			// this ultimatly gets more data or wakes write output
-			i2QueueNeeds(pB, pCh, NEED_INLINE);
-
-			if ( pB->i2eWaitingForEmptyFifo ) {
-
-				ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );
-
-				// or schedule
-				if (!in_interrupt()) {
-
-					ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
-
-					schedule_timeout_interruptible(2);
-					if (signal_pending(current)) {
-						break;
-					}
-					continue;
-				} else {
-
-					ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );
-
-					// let interrupt in = WAS restore_flags()
-					// We hold no lock nor is irq off anymore???
-					
-					break;
-				}
-				break;   // from while(count)
-			}
-			else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )
-			{
-				ip2trace (CHANN, ITRC_OUTPUT, 19, 2,
-					pB->i2eFifoRemains,
-					pB->i2eTxMailEmpty );
-
-				break;   // from while(count)
-			} else if ( pCh->channelNeeds & NEED_CREDIT ) {
-
-				ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );
-
-				break;   // from while(count)
-			} else if ( --bailout) {
-
-				// Try to throw more things (maybe not us) in the fifo if we're
-				// not already waiting for it.
-	
-				ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );
-
-				serviceOutgoingFifo(pB);
-				//break;  CONTINUE;
-			} else {
-				ip2trace (CHANN, ITRC_OUTPUT, 21, 3,
-					pB->i2eFifoRemains,
-					pB->i2eOutMailWaiting,
-					pB->i2eWaitingForEmptyFifo );
-
-				break;   // from while(count)
-			}
-		}
-	} // End of while(count)
-
-	i2QueueNeeds(pB, pCh, NEED_INLINE);
-
-	// We drop through either when the count expires, or when there is some
-	// count left, but there was a non-blocking write.
-	if (countOriginal > count) {
-
-		ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );
-
-		serviceOutgoingFifo( pB );
-	}
-
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );
-
-	return countOriginal - count;
-}
-
-//******************************************************************************
-// Function:   i2FlushOutput(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Nothing
-//
-// Description:
-// Sends bypass command to start flushing (waiting possibly forever until there
-// is room), then sends inline command to stop flushing output, (again waiting
-// possibly forever).
-//******************************************************************************
-static inline void
-i2FlushOutput(i2ChanStrPtr pCh)
-{
-
-	ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );
-
-	if (pCh->flush_flags)
-		return;
-
-	if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
-		pCh->flush_flags = STARTFL_FLAG;		// Failed - flag for later
-
-		ip2trace (CHANN, ITRC_FLUSH, 2, 0 );
-
-	} else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {
-		pCh->flush_flags = STOPFL_FLAG;		// Failed - flag for later
-
-		ip2trace (CHANN, ITRC_FLUSH, 3, 0 );
-	}
-}
-
-static int 
-i2RetryFlushOutput(i2ChanStrPtr pCh)
-{
-	int old_flags = pCh->flush_flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );
-
-	pCh->flush_flags = 0;	// Clear flag so we can avoid recursion
-									// and queue the commands
-
-	if ( old_flags & STARTFL_FLAG ) {
-		if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
-			old_flags = STOPFL_FLAG;	//Success - send stop flush
-		} else {
-			old_flags = STARTFL_FLAG;	//Failure - Flag for retry later
-		}
-
-		ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );
-
-	}
-	if ( old_flags & STOPFL_FLAG ) {
-		if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {
-			old_flags = 0;	// Success - clear flags
-		}
-
-		ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );
-	}
-	pCh->flush_flags = old_flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );
-
-	return old_flags;
-}
-
-//******************************************************************************
-// Function:   i2DrainOutput(pCh,timeout)
-// Parameters: Pointer to a channel structure
-//             Maximum period to wait
-// Returns:    ?
-//
-// Description:
-// Uses the bookmark request command to ask the board to send a bookmark back as
-// soon as all the data is completely sent.
-//******************************************************************************
-static void
-i2DrainWakeup(unsigned long d)
-{
-	i2ChanStrPtr pCh = (i2ChanStrPtr)d;
-
-	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
-
-	pCh->BookmarkTimer.expires = 0;
-	wake_up_interruptible( &pCh->pBookmarkWait );
-}
-
-static void
-i2DrainOutput(i2ChanStrPtr pCh, int timeout)
-{
-	wait_queue_t wait;
-	i2eBordStrPtr pB;
-
-	ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);
-
-	pB = pCh->pMyBord;
-	// If the board has gone fatal, return bad, 
-	// and also hit the trap routine if it exists.
-	if (pB->i2eFatal) {
-		if (pB->i2eFatalTrap) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return;
-	}
-	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
-		// One per customer (channel)
-		setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
-				(unsigned long)pCh);
-
-		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
-
-		mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
-	}
-	
-	i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&(pCh->pBookmarkWait), &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	serviceOutgoingFifo( pB );
-	
-	schedule();	// Now we take our interruptible sleep on
-
-	// Clean up the queue
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&(pCh->pBookmarkWait), &wait);
-
-	// if expires == 0 then timer poped, then do not need to del_timer
-	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
-	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
-		del_timer( &(pCh->BookmarkTimer) );
-		pCh->BookmarkTimer.expires = 0;
-
-		ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires );
-
-	}
-	ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires );
-	return;
-}
-
-//******************************************************************************
-// Function:   i2OutputFree(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Space in output buffer
-//
-// Description:
-// Returns -1 if very gross error. Otherwise returns the amount of bytes still
-// free in the output buffer.
-//******************************************************************************
-static int
-i2OutputFree(i2ChanStrPtr pCh)
-{
-	int amountToMove;
-	unsigned long flags;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) {
-		return -1;
-	}
-	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-	amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-	if (amountToMove < 0) {
-		amountToMove += OBUF_SIZE;
-	}
-	// If this is negative, we will discover later
-	amountToMove -= sizeof(i2DataHeader);
-
-	return (amountToMove < 0) ? 0 : amountToMove;
-}
-static void
-
-ip2_owake( PTTY tp)
-{
-	i2ChanStrPtr  pCh;
-
-	if (tp == NULL) return;
-
-	pCh = tp->driver_data;
-
-	ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
-			(1 << TTY_DO_WRITE_WAKEUP) );
-
-	tty_wakeup(tp);
-}
-
-static inline void
-set_baud_params(i2eBordStrPtr pB) 
-{
-	int i,j;
-	i2ChanStrPtr  *pCh;
-
-	pCh = (i2ChanStrPtr *) pB->i2eChannelPtr;
-
-	for (i = 0; i < ABS_MAX_BOXES; i++) {
-		if (pB->channelBtypes.bid_value[i]) {
-			if (BID_HAS_654(pB->channelBtypes.bid_value[i])) {
-				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
-					if (pCh[i*16+j] == NULL)
-						break;
-					(pCh[i*16+j])->BaudBase    = 921600;	// MAX for ST654
-					(pCh[i*16+j])->BaudDivisor = 96;
-				}
-			} else {	// has cirrus cd1400
-				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
-					if (pCh[i*16+j] == NULL)
-						break;
-					(pCh[i*16+j])->BaudBase    = 115200;	// MAX for CD1400
-					(pCh[i*16+j])->BaudDivisor = 12;
-				}
-			}
-		}
-	}
-}
-
-//******************************************************************************
-// Function:   i2StripFifo(pB)
-// Parameters: Pointer to a board structure
-// Returns:    ?
-//
-// Description:
-// Strips all the available data from the incoming FIFO, identifies the type of
-// packet, and either buffers the data or does what needs to be done.
-//
-// Note there is no overflow checking here: if the board sends more data than it
-// ought to, we will not detect it here, but blindly overflow...
-//******************************************************************************
-
-// A buffer for reading in blocks for unknown channels
-static unsigned char junkBuffer[IBUF_SIZE];
-
-// A buffer to read in a status packet. Because of the size of the count field
-// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE
-static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4];
-
-// This table changes the bit order from MSR order given by STAT_MODEM packet to
-// status bits used in our library.
-static char xlatDss[16] = {
-0      | 0     | 0      | 0      ,
-0      | 0     | 0      | I2_CTS ,
-0      | 0     | I2_DSR | 0      ,
-0      | 0     | I2_DSR | I2_CTS ,
-0      | I2_RI | 0      | 0      ,
-0      | I2_RI | 0      | I2_CTS ,
-0      | I2_RI | I2_DSR | 0      ,
-0      | I2_RI | I2_DSR | I2_CTS ,
-I2_DCD | 0     | 0      | 0      ,
-I2_DCD | 0     | 0      | I2_CTS ,
-I2_DCD | 0     | I2_DSR | 0      ,
-I2_DCD | 0     | I2_DSR | I2_CTS ,
-I2_DCD | I2_RI | 0      | 0      ,
-I2_DCD | I2_RI | 0      | I2_CTS ,
-I2_DCD | I2_RI | I2_DSR | 0      ,
-I2_DCD | I2_RI | I2_DSR | I2_CTS };
-
-static inline void
-i2StripFifo(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	int channel;
-	int count;
-	unsigned short stuffIndex;
-	int amountToRead;
-	unsigned char *pc, *pcLimit;
-	unsigned char uc;
-	unsigned char dss_change;
-	unsigned long bflags,cflags;
-
-//	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 );
-
-	while (I2_HAS_INPUT(pB)) {
-//		ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 );
-
-		// Process packet from fifo a one atomic unit
-		write_lock_irqsave(&pB->read_fifo_spinlock, bflags);
-   
-		// The first word (or two bytes) will have channel number and type of
-		// packet, possibly other information
-		pB->i2eLeadoffWord[0] = iiReadWord(pB);
-
-		switch(PTYPE_OF(pB->i2eLeadoffWord))
-		{
-		case PTYPE_DATA:
-			pB->got_input = 1;
-
-//			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 );
-
-			channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */
-			count = iiReadWord(pB);          /* Count is in the next word */
-
-// NEW: Check the count for sanity! Should the hardware fail, our death
-// is more pleasant. While an oversize channel is acceptable (just more
-// than the driver supports), an over-length count clearly means we are
-// sick!
-			if ( ((unsigned int)count) > IBUF_SIZE ) {
-				pB->i2eFatal = 2;
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				return;     /* Bail out ASAP */
-			}
-			// Channel is illegally big ?
-			if ((channel >= pB->i2eChannelCnt) ||
-				(NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
-			{
-				iiReadBuf(pB, junkBuffer, count);
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				break;         /* From switch: ready for next packet */
-			}
-
-			// Channel should be valid, then
-
-			// If this is a hot-key, merely post its receipt for now. These are
-			// always supposed to be 1-byte packets, so we won't even check the
-			// count. Also we will post an acknowledgement to the board so that
-			// more data can be forthcoming. Note that we are not trying to use
-			// these sequences in this driver, merely to robustly ignore them.
-			if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
-			{
-				pCh->hotKeyIn = iiReadWord(pB) & 0xff;
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
-				break;   /* From the switch: ready for next packet */
-			}
-
-			// Normal data! We crudely assume there is room for the data in our
-			// buffer because the board wouldn't have exceeded his credit limit.
-			write_lock_irqsave(&pCh->Ibuf_spinlock, cflags);
-													// We have 2 locks now
-			stuffIndex = pCh->Ibuf_stuff;
-			amountToRead = IBUF_SIZE - stuffIndex;
-			if (amountToRead > count)
-				amountToRead = count;
-
-			// stuffIndex would have been already adjusted so there would 
-			// always be room for at least one, and count is always at least
-			// one.
-
-			iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
-			pCh->icount.rx += amountToRead;
-
-			// Update the stuffIndex by the amount of data moved. Note we could
-			// never ask for more data than would just fit. However, we might
-			// have read in one more byte than we wanted because the read
-			// rounds up to even bytes. If this byte is on the end of the
-			// packet, and is padding, we ignore it. If the byte is part of
-			// the actual data, we need to move it.
-
-			stuffIndex += amountToRead;
-
-			if (stuffIndex >= IBUF_SIZE) {
-				if ((amountToRead & 1) && (count > amountToRead)) {
-					pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE];
-					amountToRead++;
-					stuffIndex = 1;
-				} else {
-					stuffIndex = 0;
-				}
-			}
-
-			// If there is anything left over, read it as well
-			if (count > amountToRead) {
-				amountToRead = count - amountToRead;
-				iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
-				pCh->icount.rx += amountToRead;
-				stuffIndex += amountToRead;
-			}
-
-			// Update stuff index
-			pCh->Ibuf_stuff = stuffIndex;
-			write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags);
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-#ifdef USE_IQ
-			schedule_work(&pCh->tqueue_input);
-#else
-			do_input(&pCh->tqueue_input);
-#endif
-
-			// Note we do not need to maintain any flow-control credits at this
-			// time:  if we were to increment .asof and decrement .room, there
-			// would be no net effect. Instead, when we strip data, we will
-			// increment .asof and leave .room unchanged.
-
-			break;   // From switch: ready for next packet
-
-		case PTYPE_STATUS:
-			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 );
-      
-			count = CMD_COUNT_OF(pB->i2eLeadoffWord);
-
-			iiReadBuf(pB, cmdBuffer, count);
-			// We can release early with buffer grab
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-			pc = cmdBuffer;
-			pcLimit = &(cmdBuffer[count]);
-
-			while (pc < pcLimit) {
-				channel = *pc++;
-
-				ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc );
-
-				/* check for valid channel */
-				if (channel < pB->i2eChannelCnt
-					 && 
-					 (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL
-					)
-				{
-					dss_change = 0;
-
-					switch (uc = *pc++)
-					{
-					/* Breaks and modem signals are easy: just update status */
-					case STAT_CTS_UP:
-						if ( !(pCh->dataSetIn & I2_CTS) )
-						{
-							pCh->dataSetIn |= I2_DCTS;
-							pCh->icount.cts++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_CTS;
-						break;
-
-					case STAT_CTS_DN:
-						if ( pCh->dataSetIn & I2_CTS )
-						{
-							pCh->dataSetIn |= I2_DCTS;
-							pCh->icount.cts++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_CTS;
-						break;
-
-					case STAT_DCD_UP:
-						ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn );
-
-						if ( !(pCh->dataSetIn & I2_DCD) )
-						{
-							ip2trace (CHANN, ITRC_MODEM, 2, 0 );
-							pCh->dataSetIn |= I2_DDCD;
-							pCh->icount.dcd++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_DCD;
-
-						ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn );
-						break;
-
-					case STAT_DCD_DN:
-						ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn );
-						if ( pCh->dataSetIn & I2_DCD )
-						{
-							ip2trace (channel, ITRC_MODEM, 5, 0 );
-							pCh->dataSetIn |= I2_DDCD;
-							pCh->icount.dcd++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_DCD;
-
-						ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn );
-						break;
-
-					case STAT_DSR_UP:
-						if ( !(pCh->dataSetIn & I2_DSR) )
-						{
-							pCh->dataSetIn |= I2_DDSR;
-							pCh->icount.dsr++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_DSR;
-						break;
-
-					case STAT_DSR_DN:
-						if ( pCh->dataSetIn & I2_DSR )
-						{
-							pCh->dataSetIn |= I2_DDSR;
-							pCh->icount.dsr++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_DSR;
-						break;
-
-					case STAT_RI_UP:
-						if ( !(pCh->dataSetIn & I2_RI) )
-						{
-							pCh->dataSetIn |= I2_DRI;
-							pCh->icount.rng++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_RI ;
-						break;
-
-					case STAT_RI_DN:
-						// to be compat with serial.c
-						//if ( pCh->dataSetIn & I2_RI )
-						//{
-						//	pCh->dataSetIn |= I2_DRI;
-						//	pCh->icount.rng++; 
-						//	dss_change = 1;
-						//}
-						pCh->dataSetIn &= ~I2_RI ;
-						break;
-
-					case STAT_BRK_DET:
-						pCh->dataSetIn |= I2_BRK;
-						pCh->icount.brk++;
-						dss_change = 1;
-						break;
-
-					// Bookmarks? one less request we're waiting for
-					case STAT_BMARK:
-						pCh->bookMarks--;
-						if (pCh->bookMarks <= 0 ) {
-							pCh->bookMarks = 0;
-							wake_up_interruptible( &pCh->pBookmarkWait );
-
-						ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires );
-						}
-						break;
-
-					// Flow control packets? Update the new credits, and if
-					// someone was waiting for output, queue him up again.
-					case STAT_FLOW:
-						pCh->outfl.room =
-							((flowStatPtr)pc)->room -
-							(pCh->outfl.asof - ((flowStatPtr)pc)->asof);
-
-						ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room );
-
-						if (pCh->channelNeeds & NEED_CREDIT)
-						{
-							ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds);
-
-							pCh->channelNeeds &= ~NEED_CREDIT;
-							i2QueueNeeds(pB, pCh, NEED_INLINE);
-							if ( pCh->pTTY )
-								ip2_owake(pCh->pTTY);
-						}
-
-						ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds);
-
-						pc += sizeof(flowStat);
-						break;
-
-					/* Special packets: */
-					/* Just copy the information into the channel structure */
-
-					case STAT_STATUS:
-
-						pCh->channelStatus = *((debugStatPtr)pc);
-						pc += sizeof(debugStat);
-						break;
-
-					case STAT_TXCNT:
-
-						pCh->channelTcount = *((cntStatPtr)pc);
-						pc += sizeof(cntStat);
-						break;
-
-					case STAT_RXCNT:
-
-						pCh->channelRcount = *((cntStatPtr)pc);
-						pc += sizeof(cntStat);
-						break;
-
-					case STAT_BOXIDS:
-						pB->channelBtypes = *((bidStatPtr)pc);
-						pc += sizeof(bidStat);
-						set_baud_params(pB);
-						break;
-
-					case STAT_HWFAIL:
-						i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);
-						pCh->channelFail = *((failStatPtr)pc);
-						pc += sizeof(failStat);
-						break;
-
-					/* No explicit match? then
-					 * Might be an error packet...
-					 */
-					default:
-						switch (uc & STAT_MOD_ERROR)
-						{
-						case STAT_ERROR:
-							if (uc & STAT_E_PARITY) {
-								pCh->dataSetIn |= I2_PAR;
-								pCh->icount.parity++;
-							}
-							if (uc & STAT_E_FRAMING){
-								pCh->dataSetIn |= I2_FRA;
-								pCh->icount.frame++;
-							}
-							if (uc & STAT_E_OVERRUN){
-								pCh->dataSetIn |= I2_OVR;
-								pCh->icount.overrun++;
-							}
-							break;
-
-						case STAT_MODEM:
-							// the answer to DSS_NOW request (not change)
-							pCh->dataSetIn = (pCh->dataSetIn
-								& ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )
-								| xlatDss[uc & 0xf];
-							wake_up_interruptible ( &pCh->dss_now_wait );
-						default:
-							break;
-						}
-					}  /* End of switch on status type */
-					if (dss_change) {
-#ifdef USE_IQ
-						schedule_work(&pCh->tqueue_status);
-#else
-						do_status(&pCh->tqueue_status);
-#endif
-					}
-				}
-				else  /* Or else, channel is invalid */
-				{
-					// Even though the channel is invalid, we must test the
-					// status to see how much additional data it has (to be
-					// skipped)
-					switch (*pc++)
-					{
-					case STAT_FLOW:
-						pc += 4;    /* Skip the data */
-						break;
-
-					default:
-						break;
-					}
-				}
-			}  // End of while (there is still some status packet left)
-			break;
-
-		default: // Neither packet? should be impossible
-			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
-				PTYPE_OF(pB->i2eLeadoffWord) );
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-			break;
-		}  // End of switch on type of packets
-	}	/*while(board I2_HAS_INPUT)*/
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
-
-	// Send acknowledgement to the board even if there was no data!
-	pB->i2eOutMailWaiting |= MB_IN_STRIPPED;
-	return;
-}
-
-//******************************************************************************
-// Function:   i2Write2Fifo(pB,address,count)
-// Parameters: Pointer to a board structure, source address, byte count
-// Returns:    bytes written
-//
-// Description:
-//  Writes count bytes to board io address(implied) from source
-//  Adjusts count, leaves reserve for next time around bypass cmds
-//******************************************************************************
-static int
-i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
-{
-	int rc = 0;
-	unsigned long flags;
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	if (!pB->i2eWaitingForEmptyFifo) {
-		if (pB->i2eFifoRemains > (count+reserve)) {
-			pB->i2eFifoRemains -= count;
-			iiWriteBuf(pB, source, count);
-			pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
-			rc =  count;
-		}
-	}
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-	return rc;
-}
-//******************************************************************************
-// Function:   i2StuffFifoBypass(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as many bypass commands into the fifo as possible. This is simpler
-// than stuffing data or inline commands to fifo, since we do not have
-// flow-control to deal with.
-//******************************************************************************
-static inline void
-i2StuffFifoBypass(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned char *pRemove;
-	unsigned short stripIndex;
-	unsigned short packetSize;
-	unsigned short paddedSize;
-	unsigned short notClogged = 1;
-	unsigned long flags;
-
-	int bailout = 1000;
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( --bailout && notClogged && 
-			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
-	{
-		write_lock_irqsave(&pCh->Cbuf_spinlock, flags);
-		stripIndex = pCh->Cbuf_strip;
-
-		// as long as there are packets for this channel...
-
-		while (stripIndex != pCh->Cbuf_stuff) {
-			pRemove = &(pCh->Cbuf[stripIndex]);
-			packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
-			paddedSize = roundup(packetSize, 2);
-
-			if (paddedSize > 0) {
-				if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
-					notClogged = 0;	/* fifo full */
-					i2QueueNeeds(pB, pCh, NEED_BYPASS);	// Put back on queue
-					break;   // Break from the channel
-				} 
-			}
-#ifdef DEBUG_FIFO
-WriteDBGBuf("BYPS", pRemove, paddedSize);
-#endif	/* DEBUG_FIFO */
-			pB->debugBypassCount++;
-
-			pRemove += packetSize;
-			stripIndex += packetSize;
-			if (stripIndex >= CBUF_SIZE) {
-				stripIndex = 0;
-				pRemove = pCh->Cbuf;
-			}
-		}
-		// Done with this channel. Move to next, removing this one from 
-		// the queue of channels if we cleaned it out (i.e., didn't get clogged.
-		pCh->Cbuf_strip = stripIndex;
-		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
-	}  // Either clogged or finished all the work
-
-#ifdef IP2DEBUG_TRACE
-	if ( !bailout ) {
-		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );
-	}
-#endif
-}
-
-//******************************************************************************
-// Function:   i2StuffFifoFlow(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as many flow control packets into the fifo as possible. This is easier
-// even than doing normal bypass commands, because there is always at most one
-// packet, already assembled, for each channel.
-//******************************************************************************
-static inline void
-i2StuffFifoFlow(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned short paddedSize = roundup(sizeof(flowIn), 2);
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
-		pB->i2eFifoRemains, paddedSize );
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {
-		pB->debugFlowCount++;
-
-		// NO Chan LOCK needed ???
-		if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {
-			break;
-		}
-#ifdef DEBUG_FIFO
-		WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);
-#endif /* DEBUG_FIFO */
-
-	}  // Either clogged or finished all the work
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );
-}
-
-//******************************************************************************
-// Function:   i2StuffFifoInline(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as much data and inline commands into the fifo as possible. This is
-// the most complex fifo-stuffing operation, since there if now the channel
-// flow-control issue to deal with.
-//******************************************************************************
-static inline void
-i2StuffFifoInline(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned char *pRemove;
-	unsigned short stripIndex;
-	unsigned short packetSize;
-	unsigned short paddedSize;
-	unsigned short notClogged = 1;
-	unsigned short flowsize;
-	unsigned long flags;
-
-	int bailout  = 1000;
-	int bailout2;
-
-	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 
-			pB->i2Dbuf_strip, pB->i2Dbuf_stuff );
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( --bailout && notClogged && 
-			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
-	{
-		write_lock_irqsave(&pCh->Obuf_spinlock, flags);
-		stripIndex = pCh->Obuf_strip;
-
-		ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
-
-		// as long as there are packets for this channel...
-		bailout2 = 1000;
-		while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {
-			pRemove = &(pCh->Obuf[stripIndex]);
-
-			// Must determine whether this be a data or command packet to
-			// calculate correctly the header size and the amount of
-			// flow-control credit this type of packet will use.
-			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
-				flowsize = DATA_COUNT_OF(pRemove);
-				packetSize = flowsize + sizeof(i2DataHeader);
-			} else {
-				flowsize = CMD_COUNT_OF(pRemove);
-				packetSize = flowsize + sizeof(i2CmdHeader);
-			}
-			flowsize = CREDIT_USAGE(flowsize);
-			paddedSize = roundup(packetSize, 2);
-
-			ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
-
-			// If we don't have enough credits from the board to send the data,
-			// flag the channel that we are waiting for flow control credit, and
-			// break out. This will clean up this channel and remove us from the
-			// queue of hot things to do.
-
-				ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );
-
-			if (pCh->outfl.room <= flowsize)	{
-				// Do Not have the credits to send this packet.
-				i2QueueNeeds(pB, pCh, NEED_CREDIT);
-				notClogged = 0;
-				break;   // So to do next channel
-			}
-			if ( (paddedSize > 0) 
-				&& ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {
-				// Do Not have room in fifo to send this packet.
-				notClogged = 0;
-				i2QueueNeeds(pB, pCh, NEED_INLINE);	
-				break;   // Break from the channel
-			}
-#ifdef DEBUG_FIFO
-WriteDBGBuf("DATA", pRemove, paddedSize);
-#endif /* DEBUG_FIFO */
-			pB->debugInlineCount++;
-
-			pCh->icount.tx += flowsize;
-			// Update current credits
-			pCh->outfl.room -= flowsize;
-			pCh->outfl.asof += flowsize;
-			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
-				pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);
-			}
-			pRemove += packetSize;
-			stripIndex += packetSize;
-
-			ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);
-
-			if (stripIndex >= OBUF_SIZE) {
-				stripIndex = 0;
-				pRemove = pCh->Obuf;
-
-				ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );
-
-			}
-		}	/* while */
-		if ( !bailout2 ) {
-			ip2trace (CHANN, ITRC_ERROR, 3, 0 );
-		}
-		// Done with this channel. Move to next, removing this one from the
-		// queue of channels if we cleaned it out (i.e., didn't get clogged.
-		pCh->Obuf_strip = stripIndex;
-		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-		if ( notClogged )
-		{
-
-			ip2trace (CHANN, ITRC_SICMD, 8, 0 );
-
-			if ( pCh->pTTY ) {
-				ip2_owake(pCh->pTTY);
-			}
-		}
-	}  // Either clogged or finished all the work
-
-	if ( !bailout ) {
-		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );
-	}
-
-	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);
-}
-
-//******************************************************************************
-// Function:   serviceOutgoingFifo(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Helper routine to put data in the outgoing fifo, if we aren't already waiting
-// for something to be there. If the fifo has only room for a very little data,
-// go head and hit the board with a mailbox hit immediately. Otherwise, it will
-// have to happen later in the interrupt processing. Since this routine may be
-// called both at interrupt and foreground time, we must turn off interrupts
-// during the entire process.
-//******************************************************************************
-static void
-serviceOutgoingFifo(i2eBordStrPtr pB)
-{
-	// If we aren't currently waiting for the board to empty our fifo, service
-	// everything that is pending, in priority order (especially, Bypass before
-	// Inline).
-	if ( ! pB->i2eWaitingForEmptyFifo )
-	{
-		i2StuffFifoFlow(pB);
-		i2StuffFifoBypass(pB);
-		i2StuffFifoInline(pB);
-
-		iiSendPendingMail(pB);
-	} 
-}
-
-//******************************************************************************
-// Function:   i2ServiceBoard(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Normally this is called from interrupt level, but there is deliberately
-// nothing in here specific to being called from interrupt level. All the
-// hardware-specific, interrupt-specific things happen at the outer levels.
-//
-// For example, a timer interrupt could drive this routine for some sort of
-// polled operation. The only requirement is that the programmer deal with any
-// atomiticity/concurrency issues that result.
-//
-// This routine responds to the board's having sent mailbox information to the
-// host (which would normally cause an interrupt). This routine reads the
-// incoming mailbox. If there is no data in it, this board did not create the
-// interrupt and/or has nothing to be done to it. (Except, if we have been
-// waiting to write mailbox data to it, we may do so.
-//
-// Based on the value in the mailbox, we may take various actions.
-//
-// No checking here of pB validity: after all, it shouldn't have been called by
-// the handler unless pB were on the list.
-//******************************************************************************
-static inline int
-i2ServiceBoard ( i2eBordStrPtr pB )
-{
-	unsigned inmail;
-	unsigned long flags;
-
-
-	/* This should be atomic because of the way we are called... */
-	if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {
-		inmail = iiGetMail(pB);
-	}
-	pB->i2eStartMail = NO_MAIL_HERE;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );
-
-	if (inmail != NO_MAIL_HERE) {
-		// If the board has gone fatal, nothing to do but hit a bit that will
-		// alert foreground tasks to protest!
-		if ( inmail & MB_FATAL_ERROR ) {
-			pB->i2eFatal = 1;
-			goto exit_i2ServiceBoard;
-		}
-
-		/* Assuming no fatal condition, we proceed to do work */
-		if ( inmail & MB_IN_STUFFED ) {
-			pB->i2eFifoInInts++;
-			i2StripFifo(pB);     /* There might be incoming packets */
-		}
-
-		if (inmail & MB_OUT_STRIPPED) {
-			pB->i2eFifoOutInts++;
-			write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-			pB->i2eFifoRemains = pB->i2eFifoSize;
-			pB->i2eWaitingForEmptyFifo = 0;
-			write_unlock_irqrestore(&pB->write_fifo_spinlock,
-					flags);
-
-			ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
-
-		}
-		serviceOutgoingFifo(pB);
-	}
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 );
-
-exit_i2ServiceBoard:
-
-	return 0;
-}
diff --git a/drivers/char/ip2/i2lib.h b/drivers/char/ip2/i2lib.h
deleted file mode 100644
index e559e9b..0000000
--- a/drivers/char/ip2/i2lib.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Header file for high level library functions
-*
-*******************************************************************************/
-#ifndef I2LIB_H
-#define I2LIB_H   1
-//------------------------------------------------------------------------------
-// I2LIB.H
-//
-// IntelliPort-II and IntelliPort-IIEX
-//
-// Defines, structure definitions, and external declarations for i2lib.c
-//------------------------------------------------------------------------------
-//--------------------------------------
-// Mandatory Includes:
-//--------------------------------------
-#include "ip2types.h"
-#include "i2ellis.h"
-#include "i2pack.h"
-#include "i2cmd.h"
-#include <linux/workqueue.h>
-
-//------------------------------------------------------------------------------
-// i2ChanStr -- Channel Structure:
-// Used to track per-channel information for the library routines using standard
-// loadware. Note also, a pointer to an array of these structures is patched
-// into the i2eBordStr (see i2ellis.h)
-//------------------------------------------------------------------------------
-//
-// If we make some limits on the maximum block sizes, we can avoid dealing with
-// buffer wrap. The wrapping of the buffer is based on where the start of the
-// packet is. Then there is always room for the packet contiguously.
-//
-// Maximum total length of an outgoing data or in-line command block. The limit
-// of 36 on data is quite arbitrary and based more on DOS memory limitations
-// than the board interface. However, for commands, the maximum packet length is
-// MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits
-// (see I2PACK.H) in such packets. For data packets, the count field size is not
-// the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE,
-// but be careful if wanting to modify either.
-//
-#define MAX_OBUF_BLOCK  36
-
-// Another note on maximum block sizes: we are buffering packets here. Data is
-// put into the buffer (if there is room) regardless of the credits from the
-// board. The board sends new credits whenever it has removed from his buffers a
-// number of characters equal to 80% of total buffer size. (Of course, the total
-// buffer size is what is reported when the very first set of flow control
-// status packets are received from the board. Therefore, to be robust, you must
-// always fill the board to at least 80% of the current credit limit, else you
-// might not give it enough to trigger a new report. These conditions are
-// obtained here so long as the maximum output block size is less than 20% the
-// size of the board's output buffers. This is true at present by "coincidence"
-// or "infernal knowledge": the board's output buffers are at least 700 bytes
-// long (20% = 140 bytes, at least). The 80% figure is "official", so the safest
-// strategy might be to trap the first flow control report and guarantee that
-// the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first
-// reported buffer credit.
-//
-#define MAX_CBUF_BLOCK  6	// Maximum total length of a bypass command block
-
-#define IBUF_SIZE       512	// character capacity of input buffer per channel
-#define OBUF_SIZE       1024// character capacity of output buffer per channel
-#define CBUF_SIZE       10	// character capacity of output bypass buffer
-
-typedef struct _i2ChanStr
-{
-	// First, back-pointers so that given a pointer to this structure, you can
-	// determine the correct board and channel number to reference, (say, when
-	// issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.)
-
-	int      port_index;    // Index of port in channel structure array attached
-							// to board structure.
-	PTTY     pTTY;          // Pointer to tty structure for port (OS specific)
-	USHORT   validity;      // Indicates whether the given channel has been
-							// initialized, really exists (or is a missing
-							// channel, e.g. channel 9 on an 8-port box.)
-
-	i2eBordStrPtr  pMyBord; // Back-pointer to this channel's board structure 
-
-	int      wopen;			// waiting fer carrier
-
-	int      throttled;		// Set if upper layer can take no data
-
-	int      flags;         // Defined in tty.h
-
-	PWAITQ   open_wait;     // Pointer for OS sleep function.
-	PWAITQ   close_wait;    // Pointer for OS sleep function.
-	PWAITQ   delta_msr_wait;// Pointer for OS sleep function.
-	PWAITQ   dss_now_wait;	// Pointer for OS sleep function.
-
-	struct timer_list  BookmarkTimer;   // Used by i2DrainOutput
-	wait_queue_head_t pBookmarkWait;   // Used by i2DrainOutput
-
-	int      BaudBase;
-	int      BaudDivisor;
-
-	USHORT   ClosingDelay;
-	USHORT   ClosingWaitTime;
-
-	volatile
-	flowIn   infl;	// This structure is initialized as a completely
-					// formed flow-control command packet, and as such
-					// has the channel number, also the capacity and
-					// "as-of" data needed continuously.
-
-	USHORT   sinceLastFlow; // Counts the number of characters read from input
-							// buffers, since the last time flow control info
-							// was sent.
-
-	USHORT   whenSendFlow;  // Determines when new flow control is to be sent to
-							// the board. Note unlike earlier manifestations of
-							// the driver, these packets can be sent from
-							// in-place.
-
-	USHORT   channelNeeds;  // Bit map of important things which must be done
-							// for this channel. (See bits below )
-
-	volatile
-	flowStat outfl;         // Same type of structure is used to hold current
-							// flow control information used to control our
-							// output. "asof" is kept updated as data is sent,
-							// and "room" never goes to zero.
-
-	// The incoming ring buffer
-	// Unlike the outgoing buffers, this holds raw data, not packets. The two
-	// extra bytes are used to hold the byte-padding when there is room for an
-	// odd number of bytes before we must wrap.
-	//
-	UCHAR    Ibuf[IBUF_SIZE + 2];
-	volatile
-	USHORT   Ibuf_stuff;     // Stuffing index
-	volatile
-	USHORT   Ibuf_strip;     // Stripping index
-
-	// The outgoing ring-buffer: Holds Data and command packets. N.B., even
-	// though these are in the channel structure, the channel is also written
-	// here, the easier to send it to the fifo when ready. HOWEVER, individual
-	// packets here are NOT padded to even length: the routines for writing
-	// blocks to the fifo will pad to even byte counts.
-	//
-	UCHAR	Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4];
-	volatile
-	USHORT	Obuf_stuff;     // Stuffing index
-	volatile
-	USHORT	Obuf_strip;     // Stripping index
-	int	Obuf_char_count;
-
-	// The outgoing bypass-command buffer. Unlike earlier manifestations, the
-	// flow control packets are sent directly from the structures. As above, the
-	// channel number is included in the packet, but they are NOT padded to even
-	// size.
-	//
-	UCHAR    Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2];
-	volatile
-	USHORT   Cbuf_stuff;     // Stuffing index
-	volatile
-	USHORT   Cbuf_strip;     // Stripping index
-
-	// The temporary buffer for the Linux tty driver PutChar entry.
-	//
-	UCHAR    Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)];
-	volatile
-	USHORT   Pbuf_stuff;     // Stuffing index
-
-	// The state of incoming data-set signals
-	//
-	USHORT   dataSetIn;     // Bit-mapped according to below. Also indicates
-							// whether a break has been detected since last
-							// inquiry.
-
-	// The state of outcoming data-set signals (as far as we can tell!)
-	//
-	USHORT   dataSetOut;     // Bit-mapped according to below. 
-
-	// Most recent hot-key identifier detected
-	//
-	USHORT   hotKeyIn;      // Hot key as sent by the board, HOT_CLEAR indicates
-				// no hot key detected since last examined.
-
-	// Counter of outstanding requests for bookmarks
-	//
-	short   bookMarks;	// Number of outstanding bookmark requests, (+ive
-						// whenever a bookmark request if queued up, -ive
-						// whenever a bookmark is received).
-
-	// Misc options
-	//
-	USHORT   channelOptions;   // See below
-
-	// To store various incoming special packets
-	//
-	debugStat   channelStatus;
-	cntStat     channelRcount;
-	cntStat     channelTcount;
-	failStat    channelFail;
-
-	// To store the last values for line characteristics we sent to the board.
-	//
-	int	speed;
-
-	int flush_flags;
-
-	void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...);
-
-	/*
-	 * Kernel counters for the 4 input interrupts 
-	 */
-	struct async_icount icount;
-
-	/*
-	 *	Task queues for processing input packets from the board.
-	 */
-	struct work_struct	tqueue_input;
-	struct work_struct	tqueue_status;
-	struct work_struct	tqueue_hangup;
-
-	rwlock_t Ibuf_spinlock;
-	rwlock_t Obuf_spinlock;
-	rwlock_t Cbuf_spinlock;
-	rwlock_t Pbuf_spinlock;
-
-} i2ChanStr, *i2ChanStrPtr;
-
-//---------------------------------------------------
-// Manifests and bit-maps for elements in i2ChanStr
-//---------------------------------------------------
-//
-// flush flags
-//
-#define STARTFL_FLAG 1
-#define STOPFL_FLAG  2
-
-// validity
-//
-#define CHANNEL_MAGIC_BITS 0xff00
-#define CHANNEL_MAGIC      0x5300   // (validity & CHANNEL_MAGIC_BITS) ==
-									// CHANNEL_MAGIC --> structure good
-
-#define CHANNEL_SUPPORT    0x0001   // Indicates channel is supported, exists,
-									// and passed P.O.S.T.
-
-// channelNeeds
-//
-#define NEED_FLOW    1  // Indicates flow control has been queued
-#define NEED_INLINE  2  // Indicates inline commands or data queued
-#define NEED_BYPASS  4  // Indicates bypass commands queued
-#define NEED_CREDIT  8  // Indicates would be sending except has not sufficient
-						// credit. The data is still in the channel structure,
-						// but the channel is not enqueued in the board
-						// structure again until there is a credit received from
-						// the board.
-
-// dataSetIn (Also the bits for i2GetStatus return value)
-//
-#define I2_DCD 1
-#define I2_CTS 2
-#define I2_DSR 4
-#define I2_RI  8
-
-// dataSetOut (Also the bits for i2GetStatus return value)
-//
-#define I2_DTR 1
-#define I2_RTS 2
-
-// i2GetStatus() can optionally clear these bits
-//
-#define I2_BRK    0x10  // A break was detected
-#define I2_PAR    0x20  // A parity error was received 
-#define I2_FRA    0x40  // A framing error was received
-#define I2_OVR    0x80  // An overrun error was received 
-
-// i2GetStatus() automatically clears these bits */
-//
-#define I2_DDCD   0x100 // DCD changed from its  former value
-#define I2_DCTS   0x200 // CTS changed from its former value 
-#define I2_DDSR   0x400 // DSR changed from its former value 
-#define I2_DRI    0x800 // RI changed from its former value 
-
-// hotKeyIn
-//
-#define HOT_CLEAR 0x1322   // Indicates that no hot-key has been detected
-
-// channelOptions
-//
-#define CO_NBLOCK_WRITE 1  	// Writes don't block waiting for buffer. (Default
-							// is, they do wait.)
-
-// fcmodes
-//
-#define I2_OUTFLOW_CTS  0x0001
-#define I2_INFLOW_RTS   0x0002
-#define I2_INFLOW_DSR   0x0004
-#define I2_INFLOW_DTR   0x0008
-#define I2_OUTFLOW_DSR  0x0010
-#define I2_OUTFLOW_DTR  0x0020
-#define I2_OUTFLOW_XON  0x0040
-#define I2_OUTFLOW_XANY 0x0080
-#define I2_INFLOW_XON   0x0100
-
-#define I2_CRTSCTS      (I2_OUTFLOW_CTS|I2_INFLOW_RTS)
-#define I2_IXANY_MODE   (I2_OUTFLOW_XON|I2_OUTFLOW_XANY)
-
-//-------------------------------------------
-// Macros used from user level like functions
-//-------------------------------------------
-
-// Macros to set and clear channel options
-//
-#define i2SetOption(pCh, option) pCh->channelOptions |= option
-#define i2ClrOption(pCh, option) pCh->channelOptions &= ~option
-
-// Macro to set fatal-error trap
-//
-#define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine
-
-//--------------------------------------------
-// Declarations and prototypes for i2lib.c
-//--------------------------------------------
-//
-static int  i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr);
-static int  i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...);
-static int  i2GetStatus(i2ChanStrPtr, int);
-static int  i2Input(i2ChanStrPtr);
-static int  i2InputFlush(i2ChanStrPtr);
-static int  i2Output(i2ChanStrPtr, const char *, int);
-static int  i2OutputFree(i2ChanStrPtr);
-static int  i2ServiceBoard(i2eBordStrPtr);
-static void i2DrainOutput(i2ChanStrPtr, int);
-
-#ifdef IP2DEBUG_TRACE
-void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);
-#else
-#define ip2trace(a,b,c,d...) do {} while (0)
-#endif
-
-// Argument to i2QueueCommands
-//
-#define C_IN_LINE 1
-#define C_BYPASS  0
-
-#endif   // I2LIB_H
diff --git a/drivers/char/ip2/i2pack.h b/drivers/char/ip2/i2pack.h
deleted file mode 100644
index 00342a6..0000000
--- a/drivers/char/ip2/i2pack.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions of the packets used to transfer data and commands
-*                Host <--> Board. Information provided here is only applicable
-*                when the standard loadware is active.
-*
-*******************************************************************************/
-#ifndef I2PACK_H
-#define I2PACK_H  1
-
-//-----------------------------------------------
-// Revision History:
-//
-// 10 October 1991   MAG First draft
-// 24 February 1992  MAG Additions for 1.4.x loadware
-// 11 March 1992     MAG New status packets
-//
-//-----------------------------------------------
-
-//------------------------------------------------------------------------------
-// Packet Formats:
-//
-// Information passes between the host and board through the FIFO in packets.
-// These have headers which indicate the type of packet. Because the fifo data
-// path may be 16-bits wide, the protocol is constrained such that each packet
-// is always padded to an even byte count. (The lower-level interface routines
-// -- i2ellis.c -- are designed to do this).
-//
-// The sender (be it host or board) must place some number of complete packets
-// in the fifo, then place a message in the mailbox that packets are available.
-// Placing such a message interrupts the "receiver" (be it board or host), who
-// reads the mailbox message and determines that there are incoming packets
-// ready. Since there are no partial packets, and the length of a packet is
-// given in the header, the remainder of the packet can be read without checking
-// for FIFO empty condition. The process is repeated, packet by packet, until
-// the incoming FIFO is empty. Then the receiver uses the outbound mailbox to
-// signal the board that it has read the data. Only then can the sender place
-// additional data in the fifo.
-//------------------------------------------------------------------------------
-//
-//------------------------------------------------
-// Definition of Packet Header Area
-//------------------------------------------------
-//
-// Caution: these only define header areas. In actual use the data runs off
-// beyond the end of these structures.
-//
-// Since these structures are based on sequences of bytes which go to the board,
-// there cannot be ANY padding between the elements.
-#pragma pack(1)
-
-//----------------------------
-// DATA PACKETS
-//----------------------------
-
-typedef struct _i2DataHeader
-{
-	unsigned char i2sChannel;  /* The channel number: 0-255 */
-
-	// -- Bitfields are allocated LSB first --
-
-	// For incoming data, indicates whether this is an ordinary packet or a
-	// special one (e.g., hot key hit).
-	unsigned i2sId : 2 __attribute__ ((__packed__));
-
-	// For tagging data packets. There are flush commands which flush only data
-	// packets bearing a particular tag. (used in implementing IntelliView and
-	// IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has
-	// meaning internally to the loadware).
-	unsigned i2sTag : 4;
-
-	// These two bits determine the type of packet sent/received.
-	unsigned i2sType : 2;
-
-	// The count of data to follow: does not include the possible additional
-	// padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0.
-	unsigned short i2sCount;
-
-} i2DataHeader, *i2DataHeaderPtr;
-
-// Structure is immediately followed by the data, proper.
-
-//----------------------------
-// NON-DATA PACKETS
-//----------------------------
-
-typedef struct _i2CmdHeader
-{
-	unsigned char i2sChannel;	// The channel number: 0-255 (Except where noted
-								// - see below
-
-	// Number of bytes of commands, status or whatever to follow
-	unsigned i2sCount : 6;
-
-	// These two bits determine the type of packet sent/received.
-	unsigned i2sType : 2;
-
-} i2CmdHeader, *i2CmdHeaderPtr;
-
-// Structure is immediately followed by the applicable data.
-
-//---------------------------------------
-// Flow Control Packets (Outbound)
-//---------------------------------------
-
-// One type of outbound command packet is so important that the entire structure
-// is explicitly defined here. That is the flow-control packet. This is never
-// sent by user-level code (as would be the commands to raise/lower DTR, for
-// example). These are only sent by the library routines in response to reading
-// incoming data into the buffers.
-//
-// The parameters inside the command block are maintained in place, then the
-// block is sent at the appropriate time.
-
-typedef struct _flowIn
-{
-	i2CmdHeader    hd;      // Channel #, count, type (see above)
-	unsigned char  fcmd;    // The flow control command (37)
-	unsigned short asof;    // As of byte number "asof" (LSB first!) I have room
-							// for "room" bytes
-	unsigned short room;
-} flowIn, *flowInPtr;
-
-//----------------------------------------
-// (Incoming) Status Packets
-//----------------------------------------
-
-// Incoming packets which are non-data packets are status packets. In this case,
-// the channel number in the header is unimportant. What follows are one or more
-// sub-packets, the first word of which consists of the channel (first or low
-// byte) and the status indicator (second or high byte), followed by possibly
-// more data.
-
-#define STAT_CTS_UP     0  /* CTS raised  (no other bytes) */
-#define STAT_CTS_DN     1  /* CTS dropped (no other bytes) */
-#define STAT_DCD_UP     2  /* DCD raised  (no other bytes) */
-#define STAT_DCD_DN     3  /* DCD dropped (no other bytes) */
-#define STAT_DSR_UP     4  /* DSR raised  (no other bytes) */
-#define STAT_DSR_DN     5  /* DSR dropped (no other bytes) */
-#define STAT_RI_UP      6  /* RI  raised  (no other bytes) */
-#define STAT_RI_DN      7  /* RI  dropped (no other bytes) */
-#define STAT_BRK_DET    8  /* BRK detect  (no other bytes) */
-#define STAT_FLOW       9  /* Flow control(-- more: see below */
-#define STAT_BMARK      10 /* Bookmark    (no other bytes)
-							* Bookmark is sent as a response to
-							* a command 60: request for bookmark
-							*/
-#define STAT_STATUS     11 /* Special packet: see below */
-#define STAT_TXCNT      12 /* Special packet: see below */
-#define STAT_RXCNT      13 /* Special packet: see below */
-#define STAT_BOXIDS     14 /* Special packet: see below */
-#define STAT_HWFAIL     15 /* Special packet: see below */
-
-#define STAT_MOD_ERROR  0xc0
-#define STAT_MODEM      0xc0/* If status & STAT_MOD_ERROR:
-							 * == STAT_MODEM, then this is a modem
-							 * status packet, given in response to a
-							 * CMD_DSS_NOW command.
-							 * The low nibble has each data signal:
-							 */
-#define STAT_MOD_DCD    0x8
-#define STAT_MOD_RI     0x4
-#define STAT_MOD_DSR    0x2
-#define STAT_MOD_CTS    0x1
-
-#define STAT_ERROR      0x80/* If status & STAT_MOD_ERROR
-							 * == STAT_ERROR, then
-							 * sort of error on the channel.
-							 * The remaining seven bits indicate
-							 * what sort of error it is.
-							 */
-/* The low three bits indicate parity, framing, or overrun errors */
-
-#define STAT_E_PARITY   4     /* Parity error */
-#define STAT_E_FRAMING  2     /* Framing error */
-#define STAT_E_OVERRUN  1     /* (uxart) overrun error */
-
-//---------------------------------------
-// STAT_FLOW packets
-//---------------------------------------
-
-typedef struct _flowStat
-{
-	unsigned short asof;
-	unsigned short room;
-}flowStat, *flowStatPtr;
-
-// flowStat packets are received from the board to regulate the flow of outgoing
-// data. A local copy of this structure is also kept to track the amount of
-// credits used and credits remaining. "room" is the amount of space in the
-// board's buffers, "as of" having received a certain byte number. When sending
-// data to the fifo, you must calculate how much buffer space your packet will
-// use.  Add this to the current "asof" and subtract it from the current "room".
-//
-// The calculation for the board's buffer is given by CREDIT_USAGE, where size
-// is the un-rounded count of either data characters or command characters.
-// (Which is to say, the count rounded up, plus two).
-
-#define CREDIT_USAGE(size) (((size) + 3) & ~1)
-
-//---------------------------------------
-// STAT_STATUS packets
-//---------------------------------------
-
-typedef  struct   _debugStat
-{
-	unsigned char d_ccsr;
-	unsigned char d_txinh;
-	unsigned char d_stat1;
-	unsigned char d_stat2;
-} debugStat, *debugStatPtr;
-
-// debugStat packets are sent to the host in response to a CMD_GET_STATUS
-// command.  Each byte is bit-mapped as described below:
-
-#define D_CCSR_XON      2     /* Has received XON, ready to transmit */
-#define D_CCSR_XOFF     4     /* Has received XOFF, not transmitting */
-#define D_CCSR_TXENAB   8     /* Transmitter is enabled */
-#define D_CCSR_RXENAB   0x80  /* Receiver is enabled */
-
-#define D_TXINH_BREAK   1     /* We are sending a break */
-#define D_TXINH_EMPTY   2     /* No data to send */
-#define D_TXINH_SUSP    4     /* Output suspended via command 57 */
-#define D_TXINH_CMD     8     /* We are processing an in-line command */
-#define D_TXINH_LCD     0x10  /* LCD diagnostics are running */
-#define D_TXINH_PAUSE   0x20  /* We are processing a PAUSE command */
-#define D_TXINH_DCD     0x40  /* DCD is low, preventing transmission */
-#define D_TXINH_DSR     0x80  /* DSR is low, preventing transmission */
-
-#define D_STAT1_TXEN    1     /* Transmit INTERRUPTS enabled */
-#define D_STAT1_RXEN    2     /* Receiver INTERRUPTS enabled */
-#define D_STAT1_MDEN    4     /* Modem (data set sigs) interrupts enabled */
-#define D_STAT1_RLM     8     /* Remote loopback mode selected */
-#define D_STAT1_LLM     0x10  /* Local internal loopback mode selected */
-#define D_STAT1_CTS     0x20  /* CTS is low, preventing transmission */
-#define D_STAT1_DTR     0x40  /* DTR is low, to stop remote transmission */
-#define D_STAT1_RTS     0x80  /* RTS is low, to stop remote transmission */
-
-#define D_STAT2_TXMT    1     /* Transmit buffers are all empty */
-#define D_STAT2_RXMT    2     /* Receive buffers are all empty */
-#define D_STAT2_RXINH   4     /* Loadware has tried to inhibit remote
-							   * transmission:  dropped DTR, sent XOFF,
-							   * whatever...
-							   */
-#define D_STAT2_RXFLO   8     /* Loadware can send no more data to host
-							   * until it receives a flow-control packet
-							   */
-//-----------------------------------------
-// STAT_TXCNT and STAT_RXCNT packets
-//----------------------------------------
-
-typedef  struct   _cntStat
-{
-	unsigned short cs_time;    // (Assumes host is little-endian!)
-	unsigned short cs_count;
-} cntStat, *cntStatPtr;
-
-// These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT
-// bypass command. cs_time is a running 1 Millisecond counter which acts as a
-// time stamp. cs_count is a running counter of data sent or received from the
-// uxarts. (Not including data added by the chip itself, as with CRLF
-// processing).
-//------------------------------------------
-// STAT_HWFAIL packets
-//------------------------------------------
-
-typedef struct _failStat
-{
-	unsigned char fs_written;
-	unsigned char fs_read;
-	unsigned short fs_address;
-} failStat, *failStatPtr;
-
-// This packet is sent whenever the on-board diagnostic process detects an
-// error. At startup, this process is dormant. The host can wake it up by
-// issuing the bypass command CMD_HW_TEST. The process runs at low priority and
-// performs continuous hardware verification; writing data to certain on-board
-// registers, reading it back, and comparing. If it detects an error, this
-// packet is sent to the host, and the process goes dormant again until the host
-// sends another CMD_HW_TEST. It then continues with the next register to be
-// tested.
-
-//------------------------------------------------------------------------------
-// Macros to deal with the headers more easily! Note that these are defined so
-// they may be used as "left" as well as "right" expressions.
-//------------------------------------------------------------------------------
-
-// Given a pointer to the packet, reference the channel number
-//
-#define CHANNEL_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sChannel
-
-// Given a pointer to the packet, reference the Packet type
-//
-#define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType
-
-// The possible types of packets
-//
-#define PTYPE_DATA   0  /* Host <--> Board */
-#define PTYPE_BYPASS 1  /* Host ---> Board */
-#define PTYPE_INLINE 2  /* Host ---> Board */
-#define PTYPE_STATUS 2  /* Host <--- Board */
-
-// Given a pointer to a Data packet, reference the Tag
-//
-#define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag
-
-// Given a pointer to a Data packet, reference the data i.d.
-//
-#define ID_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sId
-
-// The possible types of ID's
-//
-#define ID_ORDINARY_DATA   0
-#define ID_HOT_KEY         1
-
-// Given a pointer to a Data packet, reference the count
-//
-#define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount
-
-// Given a pointer to a Data packet, reference the beginning of data
-//
-#define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header
-
-// Given a pointer to a Non-Data packet, reference the count
-//
-#define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount
-
-#define MAX_CMD_PACK_SIZE  62 // Maximum size of such a count
-
-// Given a pointer to a Non-Data packet, reference the beginning of data
-//
-#define CMD_OF(pP) &((unsigned char *)(pP))[2]  // 2 = size of header
-
-//--------------------------------
-// MailBox Bits:
-//--------------------------------
-
-//--------------------------
-// Outgoing (host to board)
-//--------------------------
-//
-#define MB_OUT_STUFFED     0x80  // Host has placed output in fifo 
-#define MB_IN_STRIPPED     0x40  // Host has read in all input from fifo 
-
-//--------------------------
-// Incoming (board to host)
-//--------------------------
-//
-#define MB_IN_STUFFED      0x80  // Board has placed input in fifo 
-#define MB_OUT_STRIPPED    0x40  // Board has read all output from fifo 
-#define MB_FATAL_ERROR     0x20  // Board has encountered a fatal error
-
-#pragma pack()                  // Reset padding to command-line default
-
-#endif      // I2PACK_H
-
diff --git a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h
deleted file mode 100644
index 936ccc5..0000000
--- a/drivers/char/ip2/ip2.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants for configuration and tuning
-*
-*   NOTES:
-*
-*******************************************************************************/
-#ifndef IP2_H
-#define IP2_H
-
-#include "ip2types.h"
-#include "i2cmd.h"
-
-/*************/
-/* Constants */
-/*************/
-
-/* Device major numbers - since version 2.0.26. */
-#define IP2_TTY_MAJOR      71
-#define IP2_CALLOUT_MAJOR  72
-#define IP2_IPL_MAJOR      73
-
-/* Board configuration array.
- * This array defines the hardware irq and address for up to IP2_MAX_BOARDS
- * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified,
- * PCI and EISA boards are probed for and automagicly configed
- * iff the addresses are set to 1 and 2 respectivily.
- *    0x0100 - 0x03f0 == ISA
- *	         1        == PCI
- *	         2        == EISA
- *	         0        == (skip this board)
- * This array defines the hardware addresses for them. Special 
- * addresses are EISA and PCI which go sniffing for boards. 
-
- * In a multiboard system the position in the array determines which port
- * devices are assigned to each board: 
- *		board 0 is assigned ttyF0.. to ttyF63, 
- *		board 1 is assigned ttyF64  to ttyF127,
- *		board 2 is assigned ttyF128 to ttyF191,
- *		board 3 is assigned ttyF192 to ttyF255. 
- *
- * In PCI and EISA bus systems each range is mapped to card in 
- * monotonically increasing slot number order, ISA position is as specified
- * here.
-
- * If the irqs are ALL set to 0,0,0,0 all boards operate in 
- * polled mode. For interrupt operation ISA boards require that the IRQ be 
- * specified, while PCI and EISA boards any nonzero entry 
- * will enable interrupts using the BIOS configured irq for the board. 
- * An invalid irq entry will default to polled mode for that card and print
- * console warning.
- 
- * When the driver is loaded as a module these setting can be overridden on the 
- * modprobe command line or on an option line in /etc/modprobe.conf.
- * If the driver is built-in the configuration must be 
- * set here for ISA cards and address set to 1 and 2 for PCI and EISA.
- *
- * Here is an example that shows most if not all possibe combinations:
-
- *static ip2config_t ip2config =
- *{
- *	{11,1,0,0},		// irqs
- *	{				// Addresses
- *		0x0308,		// Board 0, ttyF0   - ttyF63// ISA card at io=0x308, irq=11
- *		0x0001,		// Board 1, ttyF64  - ttyF127//PCI card configured by BIOS
- *		0x0000,		// Board 2, ttyF128 - ttyF191// Slot skipped
- *		0x0002		// Board 3, ttyF192 - ttyF255//EISA card configured by BIOS
- *												 // but polled not irq driven
- *	}
- *};
- */
-
- /* this structure is zeroed out because the suggested method is to configure
-  * the driver as a module, set up the parameters with an options line in
-  * /etc/modprobe.conf and load with modprobe or kmod, the kernel
-  * module loader
-  */
-
- /* This structure is NOW always initialized when the driver is initialized.
-  * Compiled in defaults MUST be added to the io and irq arrays in
-  * ip2.c.  Those values are configurable from insmod parameters in the
-  * case of modules or from command line parameters (ip2=io,irq) when
-  * compiled in.
-  */
-
-static ip2config_t ip2config =
-{
-	{0,0,0,0},		// irqs
-	{				// Addresses
-	/* Do NOT set compile time defaults HERE!  Use the arrays in
-		ip2.c!  These WILL be overwritten!  =mhw= */
-		0x0000,		// Board 0, ttyF0   - ttyF63
-		0x0000,		// Board 1, ttyF64  - ttyF127
-		0x0000,		// Board 2, ttyF128 - ttyF191
-		0x0000		// Board 3, ttyF192 - ttyF255
-	}
-};
-
-#endif
diff --git a/drivers/char/ip2/ip2ioctl.h b/drivers/char/ip2/ip2ioctl.h
deleted file mode 100644
index aa0a9da..0000000
--- a/drivers/char/ip2/ip2ioctl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants for configuration and tuning
-*
-*   NOTES:
-*
-*******************************************************************************/
-
-#ifndef IP2IOCTL_H
-#define IP2IOCTL_H
-
-//*************
-//* Constants *
-//*************
-
-// High baud rates (if not defined elsewhere.
-#ifndef B153600   
-#	define B153600   0010005
-#endif
-#ifndef B307200   
-#	define B307200   0010006
-#endif
-#ifndef B921600   
-#	define B921600   0010007
-#endif
-
-#endif
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
deleted file mode 100644
index c3a0253..0000000
--- a/drivers/char/ip2/ip2main.c
+++ /dev/null
@@ -1,3234 +0,0 @@
-/*
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Mainline code for the device driver
-*
-*******************************************************************************/
-// ToDo:
-//
-// Fix the immediate DSS_NOW problem.
-// Work over the channel stats return logic in ip2_ipl_ioctl so they
-//	make sense for all 256 possible channels and so the user space
-//	utilities will compile and work properly.
-//
-// Done:
-//
-// 1.2.14	/\/\|=mhw=|\/\/
-// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
-// Changed the definition of ip2trace to be more consistent with kernel style
-//	Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates
-//
-// 1.2.13	/\/\|=mhw=|\/\/
-// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform
-//	to agreed devfs serial device naming convention.
-//
-// 1.2.12	/\/\|=mhw=|\/\/
-// Cleaned up some remove queue cut and paste errors
-//
-// 1.2.11	/\/\|=mhw=|\/\/
-// Clean up potential NULL pointer dereferences
-// Clean up devfs registration
-// Add kernel command line parsing for io and irq
-//	Compile defaults for io and irq are now set in ip2.c not ip2.h!
-// Reworked poll_only hack for explicit parameter setting
-//	You must now EXPLICITLY set poll_only = 1 or set all irqs to 0
-// Merged ip2_loadmain and old_ip2_init
-// Converted all instances of interruptible_sleep_on into queue calls
-//	Most of these had no race conditions but better to clean up now
-//
-// 1.2.10	/\/\|=mhw=|\/\/
-// Fixed the bottom half interrupt handler and enabled USE_IQI
-//	to split the interrupt handler into a formal top-half / bottom-half
-// Fixed timing window on high speed processors that queued messages to
-// 	the outbound mail fifo faster than the board could handle.
-//
-// 1.2.9
-// Four box EX was barfing on >128k kmalloc, made structure smaller by
-// reducing output buffer size
-//
-// 1.2.8
-// Device file system support (MHW)
-//
-// 1.2.7 
-// Fixed
-// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
-//
-// 1.2.6
-//Fixes DCD problems
-//	DCD was not reported when CLOCAL was set on call to TIOCMGET
-//
-//Enhancements:
-//	TIOCMGET requests and waits for status return
-//	No DSS interrupts enabled except for DCD when needed
-//
-// For internal use only
-//
-//#define IP2DEBUG_INIT
-//#define IP2DEBUG_OPEN
-//#define IP2DEBUG_WRITE
-//#define IP2DEBUG_READ
-//#define IP2DEBUG_IOCTL
-//#define IP2DEBUG_IPL
-
-//#define IP2DEBUG_TRACE
-//#define DEBUG_FIFO
-
-/************/
-/* Includes */
-/************/
-
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/major.h>
-#include <linux/wait.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/platform_device.h>
-
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/termios.h>
-#include <linux/tty_driver.h>
-#include <linux/serial.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-
-#include <linux/cdk.h>
-#include <linux/comstats.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-
-#include "ip2types.h"
-#include "ip2trace.h"
-#include "ip2ioctl.h"
-#include "ip2.h"
-#include "i2ellis.h"
-#include "i2lib.h"
-
-/*****************
- * /proc/ip2mem  *
- *****************/
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static DEFINE_MUTEX(ip2_mutex);
-static const struct file_operations ip2mem_proc_fops;
-static const struct file_operations ip2_proc_fops;
-
-/********************/
-/* Type Definitions */
-/********************/
-
-/*************/
-/* Constants */
-/*************/
-
-/* String constants to identify ourselves */
-static const char pcName[] = "Computone IntelliPort Plus multiport driver";
-static const char pcVersion[] = "1.2.14";
-
-/* String constants for port names */
-static const char pcDriver_name[] = "ip2";
-static const char pcIpl[] = "ip2ipl";
-
-/***********************/
-/* Function Prototypes */
-/***********************/
-
-/* Global module entry functions */
-
-/* Private (static) functions */
-static int  ip2_open(PTTY, struct file *);
-static void ip2_close(PTTY, struct file *);
-static int  ip2_write(PTTY, const unsigned char *, int);
-static int  ip2_putchar(PTTY, unsigned char);
-static void ip2_flush_chars(PTTY);
-static int  ip2_write_room(PTTY);
-static int  ip2_chars_in_buf(PTTY);
-static void ip2_flush_buffer(PTTY);
-static int  ip2_ioctl(PTTY, struct file *, UINT, ULONG);
-static void ip2_set_termios(PTTY, struct ktermios *);
-static void ip2_set_line_discipline(PTTY);
-static void ip2_throttle(PTTY);
-static void ip2_unthrottle(PTTY);
-static void ip2_stop(PTTY);
-static void ip2_start(PTTY);
-static void ip2_hangup(PTTY);
-static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
-static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear);
-static int ip2_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount);
-
-static void set_irq(int, int);
-static void ip2_interrupt_bh(struct work_struct *work);
-static irqreturn_t ip2_interrupt(int irq, void *dev_id);
-static void ip2_poll(unsigned long arg);
-static inline void service_all_boards(void);
-static void do_input(struct work_struct *);
-static void do_status(struct work_struct *);
-
-static void ip2_wait_until_sent(PTTY,int);
-
-static void set_params (i2ChanStrPtr, struct ktermios *);
-static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
-static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
-
-static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
-static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
-static int ip2_ipl_open(struct inode *, struct file *);
-
-static int DumpTraceBuffer(char __user *, int);
-static int DumpFifoBuffer( char __user *, int);
-
-static void ip2_init_board(int, const struct firmware *);
-static unsigned short find_eisa_board(int);
-static int ip2_setup(char *str);
-
-/***************/
-/* Static Data */
-/***************/
-
-static struct tty_driver *ip2_tty_driver;
-
-/* Here, then is a table of board pointers which the interrupt routine should
- * scan through to determine who it must service.
- */
-static unsigned short i2nBoards; // Number of boards here
-
-static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
-
-static i2ChanStrPtr  DevTable[IP2_MAX_PORTS];
-//DevTableMem just used to save addresses for kfree
-static void  *DevTableMem[IP2_MAX_BOARDS];
-
-/* This is the driver descriptor for the ip2ipl device, which is used to
- * download the loadware to the boards.
- */
-static const struct file_operations ip2_ipl = {
-	.owner		= THIS_MODULE,
-	.read		= ip2_ipl_read,
-	.write		= ip2_ipl_write,
-	.unlocked_ioctl	= ip2_ipl_ioctl,
-	.open		= ip2_ipl_open,
-	.llseek		= noop_llseek,
-}; 
-
-static unsigned long irq_counter;
-static unsigned long bh_counter;
-
-// Use immediate queue to service interrupts
-#define USE_IQI
-//#define USE_IQ	// PCI&2.2 needs work
-
-/* The timer_list entry for our poll routine. If interrupt operation is not
- * selected, the board is serviced periodically to see if anything needs doing.
- */
-#define  POLL_TIMEOUT   (jiffies + 1)
-static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
-
-#ifdef IP2DEBUG_TRACE
-/* Trace (debug) buffer data */
-#define TRACEMAX  1000
-static unsigned long tracebuf[TRACEMAX];
-static int tracestuff;
-static int tracestrip;
-static int tracewrap;
-#endif
-
-/**********/
-/* Macros */
-/**********/
-
-#ifdef IP2DEBUG_OPEN
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
-		    tty->name,(pCh->flags), \
-		    tty->count,/*GET_USE_COUNT(module)*/0,s)
-#else
-#define DBG_CNT(s)
-#endif
-
-/********/
-/* Code */
-/********/
-
-#include "i2ellis.c"    /* Extremely low-level interface services */
-#include "i2cmd.c"      /* Standard loadware command definitions */
-#include "i2lib.c"      /* High level interface services */
-
-/* Configuration area for modprobe */
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-MODULE_LICENSE("GPL");
-
-#define	MAX_CMD_STR	50
-
-static int poll_only;
-static char cmd[MAX_CMD_STR];
-
-static int Eisa_irq;
-static int Eisa_slot;
-
-static int iindx;
-static char rirqs[IP2_MAX_BOARDS];
-static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
-
-/* Note: Add compiled in defaults to these arrays, not to the structure
-	in ip2.h any longer.  That structure WILL get overridden
-	by these values, or command line values, or insmod values!!!  =mhw=
-*/
-static int io[IP2_MAX_BOARDS];
-static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
-module_param(poll_only, bool, 0);
-MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
-module_param_string(ip2, cmd, MAX_CMD_STR, 0);
-MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
-
-/* for sysfs class support */
-static struct class *ip2_class;
-
-/* Some functions to keep track of what irqs we have */
-
-static int __init is_valid_irq(int irq)
-{
-	int *i = Valid_Irqs;
-	
-	while (*i != 0 && *i != irq)
-		i++;
-
-	return *i;
-}
-
-static void __init mark_requested_irq(char irq)
-{
-	rirqs[iindx++] = irq;
-}
-
-static int __exit clear_requested_irq(char irq)
-{
-	int i;
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (rirqs[i] == irq) {
-			rirqs[i] = 0;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int have_requested_irq(char irq)
-{
-	/* array init to zeros so 0 irq will not be requested as a side
-	 * effect */
-	int i;
-	for (i = 0; i < IP2_MAX_BOARDS; ++i)
-		if (rirqs[i] == irq)
-			return 1;
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   cleanup_module()                                               */
-/* Parameters: None                                                           */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This is a required entry point for an installable module. It has to return */
-/* the device and the driver to a passive state. It should not be necessary   */
-/* to reset the board fully, especially as the loadware is downloaded         */
-/* externally rather than in the driver. We just want to disable the board    */
-/* and clear the loadware to a reset state. To allow this there has to be a   */
-/* way to detect whether the board has the loadware running at init time to   */
-/* handle subsequent installations of the driver. All memory allocated by the */
-/* driver should be returned since it may be unloaded from memory.            */
-/******************************************************************************/
-static void __exit ip2_cleanup_module(void)
-{
-	int err;
-	int i;
-
-	del_timer_sync(&PollTimer);
-
-	/* Reset the boards we have. */
-	for (i = 0; i < IP2_MAX_BOARDS; i++)
-		if (i2BoardPtrTable[i])
-			iiReset(i2BoardPtrTable[i]);
-
-	/* The following is done at most once, if any boards were installed. */
-	for (i = 0; i < IP2_MAX_BOARDS; i++) {
-		if (i2BoardPtrTable[i]) {
-			iiResetDelay(i2BoardPtrTable[i]);
-			/* free io addresses and Tibet */
-			release_region(ip2config.addr[i], 8);
-			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
-			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i + 1));
-		}
-		/* Disable and remove interrupt handler. */
-		if (ip2config.irq[i] > 0 &&
-				have_requested_irq(ip2config.irq[i])) {
-			free_irq(ip2config.irq[i], (void *)&pcName);
-			clear_requested_irq(ip2config.irq[i]);
-		}
-	}
-	class_destroy(ip2_class);
-	err = tty_unregister_driver(ip2_tty_driver);
-	if (err)
-		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
-				err);
-	put_tty_driver(ip2_tty_driver);
-	unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
-	remove_proc_entry("ip2mem", NULL);
-
-	/* free memory */
-	for (i = 0; i < IP2_MAX_BOARDS; i++) {
-		void *pB;
-#ifdef CONFIG_PCI
-		if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
-			pci_disable_device(ip2config.pci_dev[i]);
-			pci_dev_put(ip2config.pci_dev[i]);
-			ip2config.pci_dev[i] = NULL;
-		}
-#endif
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			kfree(pB);
-			i2BoardPtrTable[i] = NULL;
-		}
-		if (DevTableMem[i] != NULL) {
-			kfree(DevTableMem[i]);
-			DevTableMem[i] = NULL;
-		}
-	}
-}
-module_exit(ip2_cleanup_module);
-
-static const struct tty_operations ip2_ops = {
-	.open            = ip2_open,
-	.close           = ip2_close,
-	.write           = ip2_write,
-	.put_char        = ip2_putchar,
-	.flush_chars     = ip2_flush_chars,
-	.write_room      = ip2_write_room,
-	.chars_in_buffer = ip2_chars_in_buf,
-	.flush_buffer    = ip2_flush_buffer,
-	.ioctl           = ip2_ioctl,
-	.throttle        = ip2_throttle,
-	.unthrottle      = ip2_unthrottle,
-	.set_termios     = ip2_set_termios,
-	.set_ldisc       = ip2_set_line_discipline,
-	.stop            = ip2_stop,
-	.start           = ip2_start,
-	.hangup          = ip2_hangup,
-	.tiocmget	 = ip2_tiocmget,
-	.tiocmset	 = ip2_tiocmset,
-	.get_icount	 = ip2_get_icount,
-	.proc_fops	 = &ip2_proc_fops,
-};
-
-/******************************************************************************/
-/* Function:   ip2_loadmain()                                                 */
-/* Parameters: irq, io from command line of insmod et. al.                    */
-/*		pointer to fip firmware and firmware size for boards	      */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/* This was the required entry point for all drivers (now in ip2.c)           */
-/* It performs all                                                            */
-/* initialisation of the devices and driver structures, and registers itself  */
-/* with the relevant kernel modules.                                          */
-/******************************************************************************/
-/* IRQF_DISABLED - if set blocks all interrupts else only this line */
-/* IRQF_SHARED    - for shared irq PCI or maybe EISA only */
-/* SA_RANDOM   - can be source for cert. random number generators */
-#define IP2_SA_FLAGS	0
-
-
-static const struct firmware *ip2_request_firmware(void)
-{
-	struct platform_device *pdev;
-	const struct firmware *fw;
-
-	pdev = platform_device_register_simple("ip2", 0, NULL, 0);
-	if (IS_ERR(pdev)) {
-		printk(KERN_ERR "Failed to register platform device for ip2\n");
-		return NULL;
-	}
-	if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) {
-		printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n");
-		fw = NULL;
-	}
-	platform_device_unregister(pdev);
-	return fw;
-}
-
-/******************************************************************************
- *	ip2_setup:
- *		str: kernel command line string
- *
- *	Can't autoprobe the boards so user must specify configuration on
- *	kernel command line.  Sane people build it modular but the others
- *	come here.
- *
- *	Alternating pairs of io,irq for up to 4 boards.
- *		ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
- *
- *		io=0 => No board
- *		io=1 => PCI
- *		io=2 => EISA
- *		else => ISA I/O address
- *
- *		irq=0 or invalid for ISA will revert to polling mode
- *
- *		Any value = -1, do not overwrite compiled in value.
- *
- ******************************************************************************/
-static int __init ip2_setup(char *str)
-{
-	int j, ints[10];	/* 4 boards, 2 parameters + 2 */
-	unsigned int i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0, j = 1; i < 4; i++) {
-		if (j > ints[0])
-			break;
-		if (ints[j] >= 0)
-			io[i] = ints[j];
-		j++;
-		if (j > ints[0])
-			break;
-		if (ints[j] >= 0)
-			irq[i] = ints[j];
-		j++;
-	}
-	return 1;
-}
-__setup("ip2=", ip2_setup);
-
-static int __init ip2_loadmain(void)
-{
-	int i, j, box;
-	int err = 0;
-	i2eBordStrPtr pB = NULL;
-	int rc = -1;
-	const struct firmware *fw = NULL;
-	char *str;
-
-	str = cmd;
-
-	if (poll_only) {
-		/* Hard lock the interrupts to zero */
-		irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
-	}
-
-	/* Check module parameter with 'ip2=' has been passed or not */
-	if (!poll_only && (!strncmp(str, "ip2=", 4)))
-		ip2_setup(str);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
-
-	/* process command line arguments to modprobe or
-		insmod i.e. iop & irqp */
-	/* irqp and iop should ALWAYS be specified now...  But we check
-		them individually just to be sure, anyways... */
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		ip2config.addr[i] = io[i];
-		if (irq[i] >= 0)
-			ip2config.irq[i] = irq[i];
-		else
-			ip2config.irq[i] = 0;
-	/* This is a little bit of a hack.  If poll_only=1 on command
-	   line back in ip2.c OR all IRQs on all specified boards are
-	   explicitly set to 0, then drop to poll only mode and override
-	   PCI or EISA interrupts.  This superceeds the old hack of
-	   triggering if all interrupts were zero (like da default).
-	   Still a hack but less prone to random acts of terrorism.
-
-	   What we really should do, now that the IRQ default is set
-	   to -1, is to use 0 as a hard coded, do not probe.
-
-		/\/\|=mhw=|\/\/
-	*/
-		poll_only |= irq[i];
-	}
-	poll_only = !poll_only;
-
-	/* Announce our presence */
-	printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
-
-	ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
-	if (!ip2_tty_driver)
-		return -ENOMEM;
-
-	/* Initialise all the boards we can find (up to the maximum). */
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		switch (ip2config.addr[i]) {
-		case 0:	/* skip this slot even if card is present */
-			break;
-		default: /* ISA */
-		   /* ISA address must be specified */
-			if (ip2config.addr[i] < 0x100 ||
-					ip2config.addr[i] > 0x3f8) {
-				printk(KERN_ERR "IP2: Bad ISA board %d "
-						"address %x\n", i,
-						ip2config.addr[i]);
-				ip2config.addr[i] = 0;
-				break;
-			}
-			ip2config.type[i] = ISA;
-
-			/* Check for valid irq argument, set for polling if
-			 * invalid */
-			if (ip2config.irq[i] &&
-					!is_valid_irq(ip2config.irq[i])) {
-				printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
-						ip2config.irq[i]);
-				/* 0 is polling and is valid in that sense */
-				ip2config.irq[i] = 0;
-			}
-			break;
-		case PCI:
-#ifdef CONFIG_PCI
-		{
-			struct pci_dev *pdev = NULL;
-			u32 addr;
-			int status;
-
-			pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
-					PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
-			if (pdev == NULL) {
-				ip2config.addr[i] = 0;
-				printk(KERN_ERR "IP2: PCI board %d not "
-						"found\n", i);
-				break;
-			}
-
-			if (pci_enable_device(pdev)) {
-				dev_err(&pdev->dev, "can't enable device\n");
-				goto out;
-			}
-			ip2config.type[i] = PCI;
-			ip2config.pci_dev[i] = pci_dev_get(pdev);
-			status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
-					&addr);
-			if (addr & 1)
-				ip2config.addr[i] = (USHORT)(addr & 0xfffe);
-			else
-				dev_err(&pdev->dev, "I/O address error\n");
-
-			ip2config.irq[i] = pdev->irq;
-out:
-			pci_dev_put(pdev);
-		}
-#else
-			printk(KERN_ERR "IP2: PCI card specified but PCI "
-					"support not enabled.\n");
-			printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
-					"defined!\n");
-#endif /* CONFIG_PCI */
-			break;
-		case EISA:
-			ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
-			if (ip2config.addr[i] != 0) {
-				/* Eisa_irq set as side effect, boo */
-				ip2config.type[i] = EISA;
-			} 
-			ip2config.irq[i] = Eisa_irq;
-			break;
-		}	/* switch */
-	}	/* for */
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (ip2config.addr[i]) {
-			pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
-			if (pB) {
-				i2BoardPtrTable[i] = pB;
-				iiSetAddress(pB, ip2config.addr[i],
-						ii2DelayTimer);
-				iiReset(pB);
-			} else
-				printk(KERN_ERR "IP2: board memory allocation "
-						"error\n");
-		}
-	}
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			iiResetDelay(pB);
-			break;
-		}
-	}
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		/* We don't want to request the firmware unless we have at
-		   least one board */
-		if (i2BoardPtrTable[i] != NULL) {
-			if (!fw)
-				fw = ip2_request_firmware();
-			if (!fw)
-				break;
-			ip2_init_board(i, fw);
-		}
-	}
-	if (fw)
-		release_firmware(fw);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
-
-	ip2_tty_driver->owner		    = THIS_MODULE;
-	ip2_tty_driver->name                 = "ttyF";
-	ip2_tty_driver->driver_name          = pcDriver_name;
-	ip2_tty_driver->major                = IP2_TTY_MAJOR;
-	ip2_tty_driver->minor_start          = 0;
-	ip2_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
-	ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
-	ip2_tty_driver->init_termios         = tty_std_termios;
-	ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-	ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(ip2_tty_driver, &ip2_ops);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
-
-	err = tty_register_driver(ip2_tty_driver);
-	if (err) {
-		printk(KERN_ERR "IP2: failed to register tty driver\n");
-		put_tty_driver(ip2_tty_driver);
-		return err; /* leaking resources */
-	}
-
-	err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
-	if (err) {
-		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
-				err);
-	} else {
-		/* create the sysfs class */
-		ip2_class = class_create(THIS_MODULE, "ip2");
-		if (IS_ERR(ip2_class)) {
-			err = PTR_ERR(ip2_class);
-			goto out_chrdev;	
-		}
-	}
-	/* Register the read_procmem thing */
-	if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
-		printk(KERN_ERR "IP2: failed to register read_procmem\n");
-		return -EIO; /* leaking resources */
-	}
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
-	/* Register the interrupt handler or poll handler, depending upon the
-	 * specified interrupt.
-	 */
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (ip2config.addr[i] == 0)
-			continue;
-
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			device_create(ip2_class, NULL,
-				      MKDEV(IP2_IPL_MAJOR, 4 * i),
-				      NULL, "ipl%d", i);
-			device_create(ip2_class, NULL,
-				      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-				      NULL, "stat%d", i);
-
-			for (box = 0; box < ABS_MAX_BOXES; box++)
-				for (j = 0; j < ABS_BIGGEST_BOX; j++)
-					if (pB->i2eChannelMap[box] & (1 << j))
-						tty_register_device(
-							ip2_tty_driver,
-							j + ABS_BIGGEST_BOX *
-							(box+i*ABS_MAX_BOXES),
-							NULL);
-		}
-
-		if (poll_only) {
-			/* Poll only forces driver to only use polling and
-			   to ignore the probed PCI or EISA interrupts. */
-			ip2config.irq[i] = CIR_POLL;
-		}
-		if (ip2config.irq[i] == CIR_POLL) {
-retry:
-			if (!timer_pending(&PollTimer)) {
-				mod_timer(&PollTimer, POLL_TIMEOUT);
-				printk(KERN_INFO "IP2: polling\n");
-			}
-		} else {
-			if (have_requested_irq(ip2config.irq[i]))
-				continue;
-			rc = request_irq(ip2config.irq[i], ip2_interrupt,
-				IP2_SA_FLAGS |
-				(ip2config.type[i] == PCI ? IRQF_SHARED : 0),
-				pcName, i2BoardPtrTable[i]);
-			if (rc) {
-				printk(KERN_ERR "IP2: request_irq failed: "
-						"error %d\n", rc);
-				ip2config.irq[i] = CIR_POLL;
-				printk(KERN_INFO "IP2: Polling %ld/sec.\n",
-						(POLL_TIMEOUT - jiffies));
-				goto retry;
-			}
-			mark_requested_irq(ip2config.irq[i]);
-			/* Initialise the interrupt handler bottom half
-			 * (aka slih). */
-		}
-	}
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (i2BoardPtrTable[i]) {
-			/* set and enable board interrupt */
-			set_irq(i, ip2config.irq[i]);
-		}
-	}
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
-
-	return 0;
-
-out_chrdev:
-	unregister_chrdev(IP2_IPL_MAJOR, "ip2");
-	/* unregister and put tty here */
-	return err;
-}
-module_init(ip2_loadmain);
-
-/******************************************************************************/
-/* Function:   ip2_init_board()                                               */
-/* Parameters: Index of board in configuration structure                      */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/* This function initializes the specified board. The loadware is copied to   */
-/* the board, the channel structures are initialized, and the board details   */
-/* are reported on the console.                                               */
-/******************************************************************************/
-static void
-ip2_init_board(int boardnum, const struct firmware *fw)
-{
-	int i;
-	int nports = 0, nboxes = 0;
-	i2ChanStrPtr pCh;
-	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
-
-	if ( !iiInitialize ( pB ) ) {
-		printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
-			 pB->i2eBase, pB->i2eError );
-		goto err_initialize;
-	}
-	printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1,
-	       ip2config.addr[boardnum], ip2config.irq[boardnum] );
-
-	if (!request_region( ip2config.addr[boardnum], 8, pcName )) {
-		printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]);
-		goto err_initialize;
-	}
-
-	if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size )
-	    != II_DOWN_GOOD ) {
-		printk ( KERN_ERR "IP2: failed to download loadware\n" );
-		goto err_release_region;
-	} else {
-		printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n",
-			 pB->i2ePom.e.porVersion,
-			 pB->i2ePom.e.porRevision,
-			 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
-			 pB->i2eLRevision, pB->i2eLSub );
-	}
-
-	switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
-
-	default:
-		printk( KERN_ERR "IP2: Unknown board type, ID = %x\n",
-				pB->i2ePom.e.porID );
-		nports = 0;
-		goto err_release_region;
-		break;
-
-	case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
-		printk ( KERN_INFO "IP2: ISA-4\n" );
-		nports = 4;
-		break;
-
-	case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
-		printk ( KERN_INFO "IP2: ISA-8 std\n" );
-		nports = 8;
-		break;
-
-	case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
-		printk ( KERN_INFO "IP2: ISA-8 RJ11\n" );
-		nports = 8;
-		break;
-
-	case POR_ID_FIIEX: /* IntelliPort IIEX */
-	{
-		int portnum = IP2_PORTS_PER_BOARD * boardnum;
-		int            box;
-
-		for( box = 0; box < ABS_MAX_BOXES; ++box ) {
-			if ( pB->i2eChannelMap[box] != 0 ) {
-				++nboxes;
-			}
-			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
-				if ( pB->i2eChannelMap[box] & 1<< i ) {
-					++nports;
-				}
-			}
-		}
-		DevTableMem[boardnum] = pCh =
-			kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
-		if ( !pCh ) {
-			printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
-			goto err_release_region;
-		}
-		if ( !i2InitChannels( pB, nports, pCh ) ) {
-			printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
-			kfree ( pCh );
-			goto err_release_region;
-		}
-		pB->i2eChannelPtr = &DevTable[portnum];
-		pB->i2eChannelCnt = ABS_MOST_PORTS;
-
-		for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
-			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
-				if ( pB->i2eChannelMap[box] & (1 << i) ) {
-					DevTable[portnum + i] = pCh;
-					pCh->port_index = portnum + i;
-					pCh++;
-				}
-			}
-		}
-		printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n",
-			nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
-		}
-		goto ex_exit;
-	}
-	DevTableMem[boardnum] = pCh =
-		kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
-	if ( !pCh ) {
-		printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
-		goto err_release_region;
-	}
-	pB->i2eChannelPtr = pCh;
-	pB->i2eChannelCnt = nports;
-	if ( !i2InitChannels( pB, nports, pCh ) ) {
-		printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
-		kfree ( pCh );
-		goto err_release_region;
-	}
-	pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
-
-	for( i = 0; i < pB->i2eChannelCnt; ++i ) {
-		DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
-		pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
-		pCh++;
-	}
-ex_exit:
-	INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
-	return;
-
-err_release_region:
-	release_region(ip2config.addr[boardnum], 8);
-err_initialize:
-	kfree ( pB );
-	i2BoardPtrTable[boardnum] = NULL;
-	return;
-}
-
-/******************************************************************************/
-/* Function:   find_eisa_board ( int start_slot )                             */
-/* Parameters: First slot to check                                            */
-/* Returns:    Address of EISA IntelliPort II controller                      */
-/*                                                                            */
-/* Description:                                                               */
-/* This function searches for an EISA IntelliPort controller, starting        */
-/* from the specified slot number. If the motherboard is not identified as an */
-/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
-/* it returns the base address of the controller.                             */
-/******************************************************************************/
-static unsigned short
-find_eisa_board( int start_slot )
-{
-	int i, j;
-	unsigned int idm = 0;
-	unsigned int idp = 0;
-	unsigned int base = 0;
-	unsigned int value;
-	int setup_address;
-	int setup_irq;
-	int ismine = 0;
-
-	/*
-	 * First a check for an EISA motherboard, which we do by comparing the
-	 * EISA ID registers for the system board and the first couple of slots.
-	 * No slot ID should match the system board ID, but on an ISA or PCI
-	 * machine the odds are that an empty bus will return similar values for
-	 * each slot.
-	 */
-	i = 0x0c80;
-	value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
-	for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
-		j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
-		if ( value == j )
-			return 0;
-	}
-
-	/*
-	 * OK, so we are inclined to believe that this is an EISA machine. Find
-	 * an IntelliPort controller.
-	 */
-	for( i = start_slot; i < 16; i++ ) {
-		base = i << 12;
-		idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
-		idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
-		ismine = 0;
-		if ( idm == 0x0e8e ) {
-			if ( idp == 0x0281 || idp == 0x0218 ) {
-				ismine = 1;
-			} else if ( idp == 0x0282 || idp == 0x0283 ) {
-				ismine = 3;	/* Can do edge-trigger */
-			}
-			if ( ismine ) {
-				Eisa_slot = i;
-				break;
-			}
-		}
-	}
-	if ( !ismine )
-		return 0;
-
-	/* It's some sort of EISA card, but at what address is it configured? */
-
-	setup_address = base + 0xc88;
-	value = inb(base + 0xc86);
-	setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
-
-	if ( (ismine & 2) && !(value & 0x10) ) {
-		ismine = 1;	/* Could be edging, but not */
-	}
-
-	if ( Eisa_irq == 0 ) {
-		Eisa_irq = setup_irq;
-	} else if ( Eisa_irq != setup_irq ) {
-		printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
-	}
-
-#ifdef IP2DEBUG_INIT
-printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
-	       base >> 12, idm, idp, setup_address);
-	if ( Eisa_irq ) {
-		printk(KERN_DEBUG ", Interrupt %d %s\n",
-		       setup_irq, (ismine & 2) ? "(edge)" : "(level)");
-	} else {
-		printk(KERN_DEBUG ", (polled)\n");
-	}
-#endif
-	return setup_address;
-}
-
-/******************************************************************************/
-/* Function:   set_irq()                                                      */
-/* Parameters: index to board in board table                                  */
-/*             IRQ to use                                                     */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/******************************************************************************/
-static void
-set_irq( int boardnum, int boardIrq )
-{
-	unsigned char tempCommand[16];
-	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
-	unsigned long flags;
-
-	/*
-	 * Notify the boards they may generate interrupts. This is done by
-	 * sending an in-line command to channel 0 on each board. This is why
-	 * the channels have to be defined already. For each board, if the
-	 * interrupt has never been defined, we must do so NOW, directly, since
-	 * board will not send flow control or even give an interrupt until this
-	 * is done.  If polling we must send 0 as the interrupt parameter.
-	 */
-
-	// We will get an interrupt here at the end of this function
-
-	iiDisableMailIrq(pB);
-
-	/* We build up the entire packet header. */
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_INLINE;
-	CMD_COUNT_OF(tempCommand) = 2;
-	(CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
-	(CMD_OF(tempCommand))[1] = boardIrq;
-	/*
-	 * Write to FIFO; don't bother to adjust fifo capacity for this, since
-	 * board will respond almost immediately after SendMail hit.
-	 */
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 4);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-	pB->i2eUsingIrq = boardIrq;
-	pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
-
-	/* Need to update number of boards before you enable mailbox int */
-	++i2nBoards;
-
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 6;
-	(CMD_OF(tempCommand))[0] = 88;	// SILO
-	(CMD_OF(tempCommand))[1] = 64;	// chars
-	(CMD_OF(tempCommand))[2] = 32;	// ms
-
-	(CMD_OF(tempCommand))[3] = 28;	// MAX_BLOCK
-	(CMD_OF(tempCommand))[4] = 64;	// chars
-
-	(CMD_OF(tempCommand))[5] = 87;	// HW_TEST
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 8);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 1;
-	(CMD_OF(tempCommand))[0] = 84;	/* get BOX_IDS */
-	iiWriteBuf(pB, tempCommand, 3);
-
-#ifdef XXX
-	// enable heartbeat for test porpoises
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 2;
-	(CMD_OF(tempCommand))[0] = 44;	/* get ping */
-	(CMD_OF(tempCommand))[1] = 200;	/* 200 ms */
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 4);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-#endif
-
-	iiEnableMailIrq(pB);
-	iiSendPendingMail(pB);
-}
-
-/******************************************************************************/
-/* Interrupt Handler Section                                                  */
-/******************************************************************************/
-
-static inline void
-service_all_boards(void)
-{
-	int i;
-	i2eBordStrPtr  pB;
-
-	/* Service every board on the list */
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		pB = i2BoardPtrTable[i];
-		if ( pB ) {
-			i2ServiceBoard( pB );
-		}
-	}
-}
-
-
-/******************************************************************************/
-/* Function:   ip2_interrupt_bh(work)                                         */
-/* Parameters: work - pointer to the board structure                          */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*	Service the board in a bottom half interrupt handler and then         */
-/*	reenable the board's interrupts if it has an IRQ number               */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_interrupt_bh(struct work_struct *work)
-{
-	i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
-//	pB better well be set or we have a problem!  We can only get
-//	here from the IMMEDIATE queue.  Here, we process the boards.
-//	Checking pB doesn't cost much and it saves us from the sanity checkers.
-
-	bh_counter++; 
-
-	if ( pB ) {
-		i2ServiceBoard( pB );
-		if( pB->i2eUsingIrq ) {
-//			Re-enable his interrupts
-			iiEnableMailIrq(pB);
-		}
-	}
-}
-
-
-/******************************************************************************/
-/* Function:   ip2_interrupt(int irq, void *dev_id)    */
-/* Parameters: irq - interrupt number                                         */
-/*             pointer to optional device ID structure                        */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*	Our task here is simply to identify each board which needs servicing. */
-/*	If we are queuing then, queue it to be serviced, and disable its irq  */
-/*	mask otherwise process the board directly.                            */
-/*                                                                            */
-/*	We could queue by IRQ but that just complicates things on both ends   */
-/*	with very little gain in performance (how many instructions does      */
-/*	it take to iterate on the immediate queue).                           */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_irq_work(i2eBordStrPtr pB)
-{
-#ifdef USE_IQI
-	if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
-//		Disable his interrupt (will be enabled when serviced)
-//		This is mostly to protect from reentrancy.
-		iiDisableMailIrq(pB);
-
-//		Park the board on the immediate queue for processing.
-		schedule_work(&pB->tqueue_interrupt);
-
-//		Make sure the immediate queue is flagged to fire.
-	}
-#else
-
-//	We are using immediate servicing here.  This sucks and can
-//	cause all sorts of havoc with ppp and others.  The failsafe
-//	check on iiSendPendingMail could also throw a hairball.
-
-	i2ServiceBoard( pB );
-
-#endif /* USE_IQI */
-}
-
-static void
-ip2_polled_interrupt(void)
-{
-	int i;
-	i2eBordStrPtr  pB;
-
-	ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
-
-	/* Service just the boards on the list using this irq */
-	for( i = 0; i < i2nBoards; ++i ) {
-		pB = i2BoardPtrTable[i];
-
-//		Only process those boards which match our IRQ.
-//			IRQ = 0 for polled boards, we won't poll "IRQ" boards
-
-		if (pB && pB->i2eUsingIrq == 0)
-			ip2_irq_work(pB);
-	}
-
-	++irq_counter;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-}
-
-static irqreturn_t
-ip2_interrupt(int irq, void *dev_id)
-{
-	i2eBordStrPtr pB = dev_id;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
-
-	ip2_irq_work(pB);
-
-	++irq_counter;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************/
-/* Function:   ip2_poll(unsigned long arg)                                    */
-/* Parameters: ?                                                              */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function calls the library routine i2ServiceBoard for each board in   */
-/* the board table. This is used instead of the interrupt routine when polled */
-/* mode is specified.                                                         */
-/******************************************************************************/
-static void
-ip2_poll(unsigned long arg)
-{
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
-
-	// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
-	// It will NOT poll boards handled by hard interrupts.
-	// The issue of queued BH interrupts is handled in ip2_interrupt().
-	ip2_polled_interrupt();
-
-	mod_timer(&PollTimer, POLL_TIMEOUT);
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-}
-
-static void do_input(struct work_struct *work)
-{
-	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
-	unsigned long flags;
-
-	ip2trace(CHANN, ITRC_INPUT, 21, 0 );
-
-	// Data input
-	if ( pCh->pTTY != NULL ) {
-		read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-		if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
-			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-			i2Input( pCh );
-		} else
-			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	} else {
-		ip2trace(CHANN, ITRC_INPUT, 22, 0 );
-
-		i2InputFlush( pCh );
-	}
-}
-
-// code duplicated from n_tty (ldisc)
-static inline void  isig(int sig, struct tty_struct *tty, int flush)
-{
-	/* FIXME: This is completely bogus */
-	if (tty->pgrp)
-		kill_pgrp(tty->pgrp, sig, 1);
-	if (flush || !L_NOFLSH(tty)) {
-		if ( tty->ldisc->ops->flush_buffer )  
-			tty->ldisc->ops->flush_buffer(tty);
-		i2InputFlush( tty->driver_data );
-	}
-}
-
-static void do_status(struct work_struct *work)
-{
-	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
-	int status;
-
-	status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
-
-	ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
-
-	if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
-		if ( (status & I2_BRK) ) {
-			// code duplicated from n_tty (ldisc)
-			if (I_IGNBRK(pCh->pTTY))
-				goto skip_this;
-			if (I_BRKINT(pCh->pTTY)) {
-				isig(SIGINT, pCh->pTTY, 1);
-				goto skip_this;
-			}
-			wake_up_interruptible(&pCh->pTTY->read_wait);
-		}
-#ifdef NEVER_HAPPENS_AS_SETUP_XXX
-	// and can't work because we don't know the_char
-	// as the_char is reported on a separate path
-	// The intelligent board does this stuff as setup
-	{
-	char brkf = TTY_NORMAL;
-	unsigned char brkc = '\0';
-	unsigned char tmp;
-		if ( (status & I2_BRK) ) {
-			brkf = TTY_BREAK;
-			brkc = '\0';
-		} 
-		else if (status & I2_PAR) {
-			brkf = TTY_PARITY;
-			brkc = the_char;
-		} else if (status & I2_FRA) {
-			brkf = TTY_FRAME;
-			brkc = the_char;
-		} else if (status & I2_OVR) {
-			brkf = TTY_OVERRUN;
-			brkc = the_char;
-		}
-		tmp = pCh->pTTY->real_raw;
-		pCh->pTTY->real_raw = 0;
-		pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
-		pCh->pTTY->real_raw = tmp;
-	}
-#endif /* NEVER_HAPPENS_AS_SETUP_XXX */
-	}
-skip_this:
-
-	if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
-		wake_up_interruptible(&pCh->delta_msr_wait);
-
-		if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
-			if ( status & I2_DCD ) {
-				if ( pCh->wopen ) {
-					wake_up_interruptible ( &pCh->open_wait );
-				}
-			} else {
-				if (pCh->pTTY &&  (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
-					tty_hangup( pCh->pTTY );
-				}
-			}
-		}
-	}
-
-	ip2trace (CHANN, ITRC_STATUS, 26, 0 );
-}
-
-/******************************************************************************/
-/* Device Open/Close/Ioctl Entry Point Section                                */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   open_sanity_check()                                            */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/* Verifies the structure magic numbers and cross links.                      */
-/******************************************************************************/
-#ifdef IP2DEBUG_OPEN
-static void 
-open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
-{
-	if ( pBrd->i2eValid != I2E_MAGIC ) {
-		printk(KERN_ERR "IP2: invalid board structure\n" );
-	} else if ( pBrd != pCh->pMyBord ) {
-		printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
-			 pCh->pMyBord );
-	} else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
-		printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
-	} else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
-	} else {
-		printk(KERN_INFO "IP2: all pointers check out!\n" );
-	}
-}
-#endif
-
-
-/******************************************************************************/
-/* Function:   ip2_open()                                                     */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description: (MANDATORY)                                                   */
-/* A successful device open has to run a gauntlet of checks before it         */
-/* completes. After some sanity checking and pointer setup, the function      */
-/* blocks until all conditions are satisfied. It then initialises the port to */
-/* the default characteristics and returns.                                   */
-/******************************************************************************/
-static int
-ip2_open( PTTY tty, struct file *pFile )
-{
-	wait_queue_t wait;
-	int rc = 0;
-	int do_clocal = 0;
-	i2ChanStrPtr  pCh = DevTable[tty->index];
-
-	ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 );
-
-	if ( pCh == NULL ) {
-		return -ENODEV;
-	}
-	/* Setup pointer links in device and tty structures */
-	pCh->pTTY = tty;
-	tty->driver_data = pCh;
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG \
-			"IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n",
-	       tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index);
-	open_sanity_check ( pCh, pCh->pMyBord );
-#endif
-
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
-	pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	/* Block here until the port is ready (per serial and istallion) */
-	/*
-	 * 1. If the port is in the middle of closing wait for the completion
-	 *    and then return the appropriate error.
-	 */
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->close_wait, &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
-		if ( pCh->flags & ASYNC_CLOSING ) {
-			tty_unlock();
-			schedule();
-			tty_lock();
-		}
-		if ( tty_hung_up_p(pFile) ) {
-			set_current_state( TASK_RUNNING );
-			remove_wait_queue(&pCh->close_wait, &wait);
-			return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
-		}
-	}
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->close_wait, &wait);
-
-	/*
-	 * 3. Handle a non-blocking open of a normal port.
-	 */
-	if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
-		pCh->flags |= ASYNC_NORMAL_ACTIVE;
-		goto noblock;
-	}
-	/*
-	 * 4. Now loop waiting for the port to be free and carrier present
-	 *    (if required).
-	 */
-	if ( tty->termios->c_cflag & CLOCAL )
-		do_clocal = 1;
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
-#endif
-
-	++pCh->wopen;
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->open_wait, &wait);
-
-	for(;;) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
-		pCh->dataSetOut |= (I2_DTR | I2_RTS);
-		set_current_state( TASK_INTERRUPTIBLE );
-		serviceOutgoingFifo( pCh->pMyBord );
-		if ( tty_hung_up_p(pFile) ) {
-			set_current_state( TASK_RUNNING );
-			remove_wait_queue(&pCh->open_wait, &wait);
-			return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
-		}
-		if (!(pCh->flags & ASYNC_CLOSING) && 
-				(do_clocal || (pCh->dataSetIn & I2_DCD) )) {
-			rc = 0;
-			break;
-		}
-
-#ifdef IP2DEBUG_OPEN
-		printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
-			(pCh->flags & ASYNC_CLOSING)?"True":"False");
-		printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
-#endif
-		ip2trace (CHANN, ITRC_OPEN, 3, 2, 0,
-				(pCh->flags & ASYNC_CLOSING) );
-		/* check for signal */
-		if (signal_pending(current)) {
-			rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
-			break;
-		}
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->open_wait, &wait);
-
-	--pCh->wopen; //why count?
-
-	ip2trace (CHANN, ITRC_OPEN, 4, 0 );
-
-	if (rc != 0 ) {
-		return rc;
-	}
-	pCh->flags |= ASYNC_NORMAL_ACTIVE;
-
-noblock:
-
-	/* first open - Assign termios structure to port */
-	if ( tty->count == 1 ) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-		/* Now we must send the termios settings to the loadware */
-		set_params( pCh, NULL );
-	}
-
-	/*
-	 * Now set any i2lib options. These may go away if the i2lib code ends
-	 * up rolled into the mainline.
-	 */
-	pCh->channelOptions |= CO_NBLOCK_WRITE;
-
-#ifdef IP2DEBUG_OPEN
-	printk (KERN_DEBUG "IP2: open completed\n" );
-#endif
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
-
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_close()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_close( PTTY tty, struct file *pFile )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	if ( !pCh ) {
-		return;
-	}
-
-	ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG "IP2:close %s:\n",tty->name);
-#endif
-
-	if ( tty_hung_up_p ( pFile ) ) {
-
-		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
-
-		return;
-	}
-	if ( tty->count > 1 ) { /* not the last close */
-
-		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
-
-		return;
-	}
-	pCh->flags |= ASYNC_CLOSING;	// last close actually
-
-	tty->closing = 1;
-
-	if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
-		/*
-		 * Before we drop DTR, make sure the transmitter has completely drained.
-		 * This uses an timeout, after which the close
-		 * completes.
-		 */
-		ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
-	}
-	/*
-	 * At this point we stop accepting input. Here we flush the channel
-	 * input buffer which will allow the board to send up more data. Any
-	 * additional input is tossed at interrupt/poll time.
-	 */
-	i2InputFlush( pCh );
-
-	/* disable DSS reporting */
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
-				CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-	if (tty->termios->c_cflag & HUPCL) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
-		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-	}
-
-	serviceOutgoingFifo ( pCh->pMyBord );
-
-	tty_ldisc_flush(tty);
-	tty_driver_flush_buffer(tty);
-	tty->closing = 0;
-	
-	pCh->pTTY = NULL;
-
-	if (pCh->wopen) {
-		if (pCh->ClosingDelay) {
-			msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay));
-		}
-		wake_up_interruptible(&pCh->open_wait);
-	}
-
-	pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&pCh->close_wait);
-
-#ifdef IP2DEBUG_OPEN
-	DBG_CNT("ip2_close: after wakeups--");
-#endif
-
-
-	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
-
-	return;
-}
-
-/******************************************************************************/
-/* Function:   ip2_hangup()                                                   */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_hangup ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	if( !pCh ) {
-		return;
-	}
-
-	ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
-
-	ip2_flush_buffer(tty);
-
-	/* disable DSS reporting */
-
-	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
-	i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-	if ( (tty->termios->c_cflag & HUPCL) ) {
-		i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
-		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-	}
-	i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, 
-				CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-	serviceOutgoingFifo ( pCh->pMyBord );
-
-	wake_up_interruptible ( &pCh->delta_msr_wait );
-
-	pCh->flags &= ~ASYNC_NORMAL_ACTIVE;
-	pCh->pTTY = NULL;
-	wake_up_interruptible ( &pCh->open_wait );
-
-	ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/* Device Output Section                                                      */
-/******************************************************************************/
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_write()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Flag denoting data is in user (1) or kernel (0) space          */
-/*             Pointer to data                                                */
-/*             Number of bytes to write                                       */
-/* Returns:    Number of bytes actually written                               */
-/*                                                                            */
-/* Description: (MANDATORY)                                                   */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_write( PTTY tty, const unsigned char *pData, int count)
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	int bytesSent = 0;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
-
-	/* Flush out any buffered data left over from ip2_putchar() calls. */
-	ip2_flush_chars( tty );
-
-	/* This is the actual move bit. Make sure it does what we need!!!!! */
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	bytesSent = i2Output( pCh, pData, count);
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-
-	ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
-
-	return bytesSent > 0 ? bytesSent : 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_putchar()                                                  */
-/* Parameters: Pointer to tty structure                                       */
-/*             Character to write                                             */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_putchar( PTTY tty, unsigned char ch )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-//	ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
-
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
-	if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
-		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-		ip2_flush_chars( tty );
-	} else
-		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	return 1;
-
-//	ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
-}
-
-/******************************************************************************/
-/* Function:   ip2_flush_chars()                                              */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_flush_chars( PTTY tty )
-{
-	int   strip;
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	if ( pCh->Pbuf_stuff ) {
-
-//		ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
-
-		//
-		// We may need to restart i2Output if it does not fullfill this request
-		//
-		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
-		if ( strip != pCh->Pbuf_stuff ) {
-			memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
-		}
-		pCh->Pbuf_stuff -= strip;
-	}
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-}
-
-/******************************************************************************/
-/* Function:   ip2_write_room()                                               */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Number of bytes that the driver can accept                     */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_write_room ( PTTY tty )
-{
-	int bytesFree;
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
-	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-
-	ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
-
-	return ((bytesFree > 0) ? bytesFree : 0);
-}
-
-/******************************************************************************/
-/* Function:   ip2_chars_in_buf()                                             */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Number of bytes queued for transmission                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_chars_in_buf ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	int rc;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
-
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
-				 pCh->Obuf_char_count + pCh->Pbuf_stuff,
-				 pCh->Obuf_char_count, pCh->Pbuf_stuff );
-#endif
-	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-	rc =  pCh->Obuf_char_count;
-	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	rc +=  pCh->Pbuf_stuff;
-	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	return rc;
-}
-
-/******************************************************************************/
-/* Function:   ip2_flush_buffer()                                             */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_flush_buffer( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
-
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: flush buffer\n" );
-#endif
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	pCh->Pbuf_stuff = 0;
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	i2FlushOutput( pCh );
-	ip2_owake(tty);
-
-	ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
-
-}
-
-/******************************************************************************/
-/* Function:   ip2_wait_until_sent()                                          */
-/* Parameters: Pointer to tty structure                                       */
-/*             Timeout for wait.                                              */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function is used in place of the normal tty_wait_until_sent, which    */
-/* only waits for the driver buffers to be empty (or rather, those buffers    */
-/* reported by chars_in_buffer) which doesn't work for IP2 due to the         */
-/* indeterminate number of bytes buffered on the board.                       */
-/******************************************************************************/
-static void
-ip2_wait_until_sent ( PTTY tty, int timeout )
-{
-	int i = jiffies;
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	tty_wait_until_sent(tty, timeout );
-	if ( (i = timeout - (jiffies -i)) > 0)
-		i2DrainOutput( pCh, i );
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/* Device Input Section                                                       */
-/******************************************************************************/
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_throttle()                                                 */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_throttle ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-#ifdef IP2DEBUG_READ
-	printk (KERN_DEBUG "IP2: throttle\n" );
-#endif
-	/*
-	 * Signal the poll/interrupt handlers not to forward incoming data to
-	 * the line discipline. This will cause the buffers to fill up in the
-	 * library and thus cause the library routines to send the flow control
-	 * stuff.
-	 */
-	pCh->throttled = 1;
-}
-
-/******************************************************************************/
-/* Function:   ip2_unthrottle()                                               */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_unthrottle ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-#ifdef IP2DEBUG_READ
-	printk (KERN_DEBUG "IP2: unthrottle\n" );
-#endif
-
-	/* Pass incoming data up to the line discipline again. */
-	pCh->throttled = 0;
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
-	serviceOutgoingFifo( pCh->pMyBord );
-	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
-		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-#ifdef IP2DEBUG_READ
-		printk (KERN_DEBUG "i2Input called from unthrottle\n" );
-#endif
-		i2Input( pCh );
-	} else
-		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-}
-
-static void
-ip2_start ( PTTY tty )
-{
- 	i2ChanStrPtr  pCh = DevTable[tty->index];
-
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: start tx\n" );
-#endif
-}
-
-static void
-ip2_stop ( PTTY tty )
-{
- 	i2ChanStrPtr  pCh = DevTable[tty->index];
-
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: stop tx\n" );
-#endif
-}
-
-/******************************************************************************/
-/* Device Ioctl Section                                                       */
-/******************************************************************************/
-
-static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-#ifdef	ENABLE_DSSNOW
-	wait_queue_t wait;
-#endif
-
-	if (pCh == NULL)
-		return -ENODEV;
-
-/*
-	FIXME - the following code is causing a NULL pointer dereference in
-	2.3.51 in an interrupt handler.  It's suppose to prompt the board
-	to return the DSS signal status immediately.  Why doesn't it do
-	the same thing in 2.2.14?
-*/
-
-/*	This thing is still busted in the 1.2.12 driver on 2.4.x
-	and even hoses the serial console so the oops can be trapped.
-		/\/\|=mhw=|\/\/			*/
-
-#ifdef	ENABLE_DSSNOW
-	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->dss_now_wait, &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	schedule();
-
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->dss_now_wait, &wait);
-
-	if (signal_pending(current)) {
-		return -EINTR;
-	}
-#endif
-	return  ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
-	      | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
-	      | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
-	      | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
-	      | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
-	      | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0);
-}
-
-static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
-			unsigned int set, unsigned int clear)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-
-	if (pCh == NULL)
-		return -ENODEV;
-
-	if (set & TIOCM_RTS) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
-		pCh->dataSetOut |= I2_RTS;
-	}
-	if (set & TIOCM_DTR) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
-		pCh->dataSetOut |= I2_DTR;
-	}
-
-	if (clear & TIOCM_RTS) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
-		pCh->dataSetOut &= ~I2_RTS;
-	}
-	if (clear & TIOCM_DTR) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
-		pCh->dataSetOut &= ~I2_DTR;
-	}
-	serviceOutgoingFifo( pCh->pMyBord );
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ioctl()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/*             Command                                                        */
-/*             Argument                                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
-{
-	wait_queue_t wait;
-	i2ChanStrPtr pCh = DevTable[tty->index];
-	i2eBordStrPtr pB;
-	struct async_icount cprev, cnow;	/* kernel counter temps */
-	int rc = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	if ( pCh == NULL )
-		return -ENODEV;
-
-	pB = pCh->pMyBord;
-
-	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
-
-#ifdef IP2DEBUG_IOCTL
-	printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
-#endif
-
-	switch(cmd) {
-	case TIOCGSERIAL:
-
-		ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
-
-		rc = get_serial_info(pCh, argp);
-		if (rc)
-			return rc;
-		break;
-
-	case TIOCSSERIAL:
-
-		ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
-
-		rc = set_serial_info(pCh, argp);
-		if (rc)
-			return rc;
-		break;
-
-	case TCXONC:
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-		switch (arg) {
-		case TCOOFF:
-			//return  -ENOIOCTLCMD;
-			break;
-		case TCOON:
-			//return  -ENOIOCTLCMD;
-			break;
-		case TCIOFF:
-			if (STOP_CHAR(tty) != __DISABLED_CHAR) {
-				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
-						CMD_XMIT_NOW(STOP_CHAR(tty)));
-			}
-			break;
-		case TCION:
-			if (START_CHAR(tty) != __DISABLED_CHAR) {
-				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
-						CMD_XMIT_NOW(START_CHAR(tty)));
-			}
-			break;
-		default:
-			return -EINVAL;
-		}
-		return 0;
-
-	case TCSBRK:   /* SVID version: non-zero arg --> no break */
-		rc = tty_check_change(tty);
-
-		ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
-
-		if (!rc) {
-			ip2_wait_until_sent(tty,0);
-			if (!arg) {
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
-				serviceOutgoingFifo( pCh->pMyBord );
-			}
-		}
-		break;
-
-	case TCSBRKP:  /* support for POSIX tcsendbreak() */
-		rc = tty_check_change(tty);
-
-		ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
-
-		if (!rc) {
-			ip2_wait_until_sent(tty,0);
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
-				CMD_SEND_BRK(arg ? arg*100 : 250));
-			serviceOutgoingFifo ( pCh->pMyBord );	
-		}
-		break;
-
-	case TIOCGSOFTCAR:
-
-		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
-
-			rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
-		if (rc)	
-			return rc;
-	break;
-
-	case TIOCSSOFTCAR:
-
-		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
-
-		rc = get_user(arg,(unsigned long __user *) argp);
-		if (rc) 
-			return rc;
-		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
-					 | (arg ? CLOCAL : 0));
-		
-		break;
-
-	/*
-	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
-	 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
-	 * for masking). Caller should use TIOCGICOUNT to see which one it was
-	 */
-	case TIOCMIWAIT:
-		write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-		cprev = pCh->icount;	 /* note the counters on entry */
-		write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
-						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
-		init_waitqueue_entry(&wait, current);
-		add_wait_queue(&pCh->delta_msr_wait, &wait);
-		set_current_state( TASK_INTERRUPTIBLE );
-
-		serviceOutgoingFifo( pCh->pMyBord );
-		for(;;) {
-			ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
-
-			schedule();
-
-			ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
-
-			/* see if a signal did it */
-			if (signal_pending(current)) {
-				rc = -ERESTARTSYS;
-				break;
-			}
-			write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-			cnow = pCh->icount; /* atomic copy */
-			write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-				rc =  -EIO; /* no change => rc */
-				break;
-			}
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-				rc =  0;
-				break;
-			}
-			cprev = cnow;
-		}
-		set_current_state( TASK_RUNNING );
-		remove_wait_queue(&pCh->delta_msr_wait, &wait);
-
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
-						 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-		if ( ! (pCh->flags	& ASYNC_CHECK_CD)) {
-			i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
-		}
-		serviceOutgoingFifo( pCh->pMyBord );
-		return rc;
-		break;
-
-	/*
-	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
-	 * will be passed to the line discipline for it to handle.
-	 */
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERSWILD:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-
-	default:
-		ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
-
-		rc =  -ENOIOCTLCMD;
-		break;
-	}
-
-	ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
-
-	return rc;
-}
-
-static int ip2_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-	i2eBordStrPtr pB;
-	struct async_icount cnow;	/* kernel counter temp */
-	unsigned long flags;
-
-	if ( pCh == NULL )
-		return -ENODEV;
-
-	pB = pCh->pMyBord;
-
-	/*
-	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-	 * Return: write counters to the user passed counter struct
-	 * NB: both 1->0 and 0->1 transitions are counted except for RI where
-	 * only 0->1 is counted. The controller is quite capable of counting
-	 * both, but this done to preserve compatibility with the standard
-	 * serial driver.
-	 */
-
-	write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-	cnow = pCh->icount;
-	write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   GetSerialInfo()                                                */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This is to support the setserial command, and requires processing of the   */
-/* standard Linux serial structure.                                           */
-/******************************************************************************/
-static int
-get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo )
-{
-	struct serial_struct tmp;
-
-	memset ( &tmp, 0, sizeof(tmp) );
-	tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
-	if (BID_HAS_654(tmp.type)) {
-		tmp.type = PORT_16650;
-	} else {
-		tmp.type = PORT_CIRRUS;
-	}
-	tmp.line = pCh->port_index;
-	tmp.port = pCh->pMyBord->i2eBase;
-	tmp.irq  = ip2config.irq[pCh->port_index/64];
-	tmp.flags = pCh->flags;
-	tmp.baud_base = pCh->BaudBase;
-	tmp.close_delay = pCh->ClosingDelay;
-	tmp.closing_wait = pCh->ClosingWaitTime;
-	tmp.custom_divisor = pCh->BaudDivisor;
-   	return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
-}
-
-/******************************************************************************/
-/* Function:   SetSerialInfo()                                                */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function provides support for setserial, which uses the TIOCSSERIAL   */
-/* ioctl. Not all setserial parameters are relevant. If the user attempts to  */
-/* change the IRQ, address or type of the port the ioctl fails.               */
-/******************************************************************************/
-static int
-set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
-{
-	struct serial_struct ns;
-	int   old_flags, old_baud_divisor;
-
-	if (copy_from_user(&ns, new_info, sizeof (ns)))
-		return -EFAULT;
-
-	/*
-	 * We don't allow setserial to change IRQ, board address, type or baud
-	 * base. Also line nunber as such is meaningless but we use it for our
-	 * array index so it is fixed also.
-	 */
-	if ( (ns.irq  	    != ip2config.irq[pCh->port_index])
-	    || ((int) ns.port      != ((int) (pCh->pMyBord->i2eBase)))
-	    || (ns.baud_base != pCh->BaudBase)
-	    || (ns.line      != pCh->port_index) ) {
-		return -EINVAL;
-	}
-
-	old_flags = pCh->flags;
-	old_baud_divisor = pCh->BaudDivisor;
-
-	if ( !capable(CAP_SYS_ADMIN) ) {
-		if ( ( ns.close_delay != pCh->ClosingDelay ) ||
-		    ( (ns.flags & ~ASYNC_USR_MASK) !=
-		      (pCh->flags & ~ASYNC_USR_MASK) ) ) {
-			return -EPERM;
-		}
-
-		pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
-			       (ns.flags & ASYNC_USR_MASK);
-		pCh->BaudDivisor = ns.custom_divisor;
-	} else {
-		pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
-			       (ns.flags & ASYNC_FLAGS);
-		pCh->BaudDivisor = ns.custom_divisor;
-		pCh->ClosingDelay = ns.close_delay * HZ/100;
-		pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
-	}
-
-	if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
-	    || (old_baud_divisor != pCh->BaudDivisor) ) {
-		// Invalidate speed and reset parameters
-		set_params( pCh, NULL );
-	}
-
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_set_termios()                                              */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_set_termios( PTTY tty, struct ktermios *old_termios )
-{
-	i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
-
-#ifdef IP2DEBUG_IOCTL
-	printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
-#endif
-
-	set_params( pCh, old_termios );
-}
-
-/******************************************************************************/
-/* Function:   ip2_set_line_discipline()                                      */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:  Does nothing                                                 */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_set_line_discipline ( PTTY tty )
-{
-#ifdef IP2DEBUG_IOCTL
-	printk (KERN_DEBUG "IP2: set line discipline\n" );
-#endif
-
-	ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
-
-}
-
-/******************************************************************************/
-/* Function:   SetLine Characteristics()                                      */
-/* Parameters: Pointer to channel structure                                   */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This routine is called to update the channel structure with the new line   */
-/* characteristics, and send the appropriate commands to the board when they  */
-/* change.                                                                    */
-/******************************************************************************/
-static void
-set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
-{
-	tcflag_t cflag, iflag, lflag;
-	char stop_char, start_char;
-	struct ktermios dummy;
-
-	lflag = pCh->pTTY->termios->c_lflag;
-	cflag = pCh->pTTY->termios->c_cflag;
-	iflag = pCh->pTTY->termios->c_iflag;
-
-	if (o_tios == NULL) {
-		dummy.c_lflag = ~lflag;
-		dummy.c_cflag = ~cflag;
-		dummy.c_iflag = ~iflag;
-		o_tios = &dummy;
-	}
-
-	{
-		switch ( cflag & CBAUD ) {
-		case B0:
-			i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
-			pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-			i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-			pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
-			goto service_it;
-			break;
-		case B38400:
-			/*
-			 * This is the speed that is overloaded with all the other high
-			 * speeds, depending upon the flag settings.
-			 */
-			if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
-				pCh->speed = CBR_57600;
-			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
-				pCh->speed = CBR_115200;
-			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
-				pCh->speed = CBR_C1;
-			} else {
-				pCh->speed = CBR_38400;
-			}
-			break;
-		case B50:      pCh->speed = CBR_50;      break;
-		case B75:      pCh->speed = CBR_75;      break;
-		case B110:     pCh->speed = CBR_110;     break;
-		case B134:     pCh->speed = CBR_134;     break;
-		case B150:     pCh->speed = CBR_150;     break;
-		case B200:     pCh->speed = CBR_200;     break;
-		case B300:     pCh->speed = CBR_300;     break;
-		case B600:     pCh->speed = CBR_600;     break;
-		case B1200:    pCh->speed = CBR_1200;    break;
-		case B1800:    pCh->speed = CBR_1800;    break;
-		case B2400:    pCh->speed = CBR_2400;    break;
-		case B4800:    pCh->speed = CBR_4800;    break;
-		case B9600:    pCh->speed = CBR_9600;    break;
-		case B19200:   pCh->speed = CBR_19200;   break;
-		case B57600:   pCh->speed = CBR_57600;   break;
-		case B115200:  pCh->speed = CBR_115200;  break;
-		case B153600:  pCh->speed = CBR_153600;  break;
-		case B230400:  pCh->speed = CBR_230400;  break;
-		case B307200:  pCh->speed = CBR_307200;  break;
-		case B460800:  pCh->speed = CBR_460800;  break;
-		case B921600:  pCh->speed = CBR_921600;  break;
-		default:       pCh->speed = CBR_9600;    break;
-		}
-		if ( pCh->speed == CBR_C1 ) {
-			// Process the custom speed parameters.
-			int bps = pCh->BaudBase / pCh->BaudDivisor;
-			if ( bps == 921600 ) {
-				pCh->speed = CBR_921600;
-			} else {
-				bps = bps/10;
-				i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
-			}
-		}
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
-		
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
-		pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	}
-	if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) 
-	{
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, 
-			CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
-	}
-	if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) 
-	{
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
-			CMD_SETPAR( 
-				(cflag & PARENB ?  (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
-			)
-		);
-	}
-	/* byte size and parity */
-	if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) 
-	{
-		int datasize;
-		switch ( cflag & CSIZE ) {
-		case CS5: datasize = CSZ_5; break;
-		case CS6: datasize = CSZ_6; break;
-		case CS7: datasize = CSZ_7; break;
-		case CS8: datasize = CSZ_8; break;
-		default:  datasize = CSZ_5; break;	/* as per serial.c */
-		}
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
-	}
-	/* Process CTS flow control flag setting */
-	if ( (cflag & CRTSCTS) ) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100,
-						2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
-	} else {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100,
-						2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-	}
-	//
-	// Process XON/XOFF flow control flags settings
-	//
-	stop_char = STOP_CHAR(pCh->pTTY);
-	start_char = START_CHAR(pCh->pTTY);
-
-	//////////// can't be \000
-	if (stop_char == __DISABLED_CHAR ) 
-	{
-		stop_char = ~__DISABLED_CHAR; 
-	}
-	if (start_char == __DISABLED_CHAR ) 
-	{
-		start_char = ~__DISABLED_CHAR;
-	}
-	/////////////////////////////////
-
-	if ( o_tios->c_cc[VSTART] != start_char ) 
-	{
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
-	}
-	if ( o_tios->c_cc[VSTOP] != stop_char ) 
-	{
-		 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
-		 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
-	}
-	if (stop_char == __DISABLED_CHAR ) 
-	{
-		stop_char = ~__DISABLED_CHAR;  //TEST123
-		goto no_xoff;
-	}
-	if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) 
-	{
-		if ( iflag & IXOFF ) {	// Enable XOFF output flow control
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
-		} else {	// Disable XOFF output flow control
-no_xoff:
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
-		}
-	}
-	if (start_char == __DISABLED_CHAR ) 
-	{
-		goto no_xon;
-	}
-	if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) 
-	{
-		if ( iflag & IXON ) {
-			if ( iflag & IXANY ) { // Enable XON/XANY output flow control
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
-			} else { // Enable XON output flow control
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
-			}
-		} else { // Disable XON output flow control
-no_xon:
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
-		}
-	}
-	if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) 
-	{
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
-				CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
-	}
-	if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) 
-	{
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
-				CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
-	}
-
-	if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) 
-			^	( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) 
-	{
-		char brkrpt = 0;
-		char parrpt = 0;
-
-		if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
-			/* Ignore breaks altogether */
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
-		} else {
-			if ( iflag & BRKINT ) {
-				if ( iflag & PARMRK ) {
-					brkrpt = 0x0a;	// exception an inline triple
-				} else {
-					brkrpt = 0x1a;	// exception and NULL
-				}
-				brkrpt |= 0x04;	// flush input
-			} else {
-				if ( iflag & PARMRK ) {
-					brkrpt = 0x0b;	//POSIX triple \0377 \0 \0
-				} else {
-					brkrpt = 0x01;	// Null only
-				}
-			}
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
-		} 
-
-		if (iflag & IGNPAR) {
-			parrpt = 0x20;
-													/* would be 2 for not cirrus bug */
-													/* would be 0x20 cept for cirrus bug */
-		} else {
-			if ( iflag & PARMRK ) {
-				/*
-				 * Replace error characters with 3-byte sequence (\0377,\0,char)
-				 */
-				parrpt = 0x04 ;
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
-			} else {
-				parrpt = 0x03;
-			} 
-		}
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
-	}
-	if (cflag & CLOCAL) {
-		// Status reporting fails for DCD if this is off
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
-		pCh->flags &= ~ASYNC_CHECK_CD;
-	} else {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
-		pCh->flags	|= ASYNC_CHECK_CD;
-	}
-
-service_it:
-	i2DrainOutput( pCh, 100 );		
-}
-
-/******************************************************************************/
-/* IPL Device Section                                                         */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_ipl_read()                                                  */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/*             Pointer to data                                                */
-/*             Number of bytes to read                                        */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:   Ugly                                                        */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-
-static 
-ssize_t
-ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
-{
-	unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
-	int rc = 0;
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
-#endif
-
-	switch( minor ) {
-	case 0:	    // IPL device
-		rc = -EINVAL;
-		break;
-	case 1:	    // Status dump
-		rc = -EINVAL;
-		break;
-	case 2:	    // Ping device
-		rc = -EINVAL;
-		break;
-	case 3:	    // Trace device
-		rc = DumpTraceBuffer ( pData, count );
-		break;
-	case 4:	    // Trace device
-		rc = DumpFifoBuffer ( pData, count );
-		break;
-	default:
-		rc = -ENODEV;
-		break;
-	}
-	return rc;
-}
-
-static int
-DumpFifoBuffer ( char __user *pData, int count )
-{
-#ifdef DEBUG_FIFO
-	int rc;
-	rc = copy_to_user(pData, DBGBuf, count);
-
-	printk(KERN_DEBUG "Last index %d\n", I );
-
-	return count;
-#endif	/* DEBUG_FIFO */
-	return 0;
-}
-
-static int
-DumpTraceBuffer ( char __user *pData, int count )
-{
-#ifdef IP2DEBUG_TRACE
-	int rc;
-	int dumpcount;
-	int chunk;
-	int *pIndex = (int __user *)pData;
-
-	if ( count < (sizeof(int) * 6) ) {
-		return -EIO;
-	}
-	rc = put_user(tracewrap, pIndex );
-	rc = put_user(TRACEMAX, ++pIndex );
-	rc = put_user(tracestrip, ++pIndex );
-	rc = put_user(tracestuff, ++pIndex );
-	pData += sizeof(int) * 6;
-	count -= sizeof(int) * 6;
-
-	dumpcount = tracestuff - tracestrip;
-	if ( dumpcount < 0 ) {
-		dumpcount += TRACEMAX;
-	}
-	if ( dumpcount > count ) {
-		dumpcount = count;
-	}
-	chunk = TRACEMAX - tracestrip;
-	if ( dumpcount > chunk ) {
-		rc = copy_to_user(pData, &tracebuf[tracestrip],
-			      chunk * sizeof(tracebuf[0]) );
-		pData += chunk * sizeof(tracebuf[0]);
-		tracestrip = 0;
-		chunk = dumpcount - chunk;
-	} else {
-		chunk = dumpcount;
-	}
-	rc = copy_to_user(pData, &tracebuf[tracestrip],
-		      chunk * sizeof(tracebuf[0]) );
-	tracestrip += chunk;
-	tracewrap = 0;
-
-	rc = put_user(tracestrip, ++pIndex );
-	rc = put_user(tracestuff, ++pIndex );
-
-	return dumpcount;
-#else
-	return 0;
-#endif
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_write()                                                 */
-/* Parameters:                                                                */
-/*             Pointer to file structure                                      */
-/*             Pointer to data                                                */
-/*             Number of bytes to write                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static ssize_t
-ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off)
-{
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
-#endif
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_ioctl()                                                */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/*             Command                                                        */
-/*             Argument                                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static long
-ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
-{
-	unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
-	int rc = 0;
-	void __user *argp = (void __user *)arg;
-	ULONG __user *pIndex = argp;
-	i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
-	i2ChanStrPtr pCh;
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
-#endif
-
-	mutex_lock(&ip2_mutex);
-
-	switch ( iplminor ) {
-	case 0:	    // IPL device
-		rc = -EINVAL;
-		break;
-	case 1:	    // Status dump
-	case 5:
-	case 9:
-	case 13:
-		switch ( cmd ) {
-		case 64:	/* Driver - ip2stat */
-			rc = put_user(-1, pIndex++ );
-			rc = put_user(irq_counter, pIndex++  );
-			rc = put_user(bh_counter, pIndex++  );
-			break;
-
-		case 65:	/* Board  - ip2stat */
-			if ( pB ) {
-				rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
-				rc = put_user(inb(pB->i2eStatus),
-					(ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
-			} else {
-				rc = -ENODEV;
-			}
-			break;
-
-		default:
-			if (cmd < IP2_MAX_PORTS) {
-				pCh = DevTable[cmd];
-				if ( pCh )
-				{
-					rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
-					if (rc)
-						rc = -EFAULT;
-				} else {
-					rc = -ENODEV;
-				}
-			} else {
-				rc = -EINVAL;
-			}
-		}
-		break;
-
-	case 2:	    // Ping device
-		rc = -EINVAL;
-		break;
-	case 3:	    // Trace device
-		/*
-		 * akpm: This used to write a whole bunch of function addresses
-		 * to userspace, which generated lots of put_user() warnings.
-		 * I killed it all.  Just return "success" and don't do
-		 * anything.
-		 */
-		if (cmd == 1)
-			rc = 0;
-		else
-			rc = -EINVAL;
-		break;
-
-	default:
-		rc = -ENODEV;
-		break;
-	}
-	mutex_unlock(&ip2_mutex);
-	return rc;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_open()                                                 */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_ipl_open( struct inode *pInode, struct file *pFile )
-{
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: open\n" );
-#endif
-	return 0;
-}
-
-static int
-proc_ip2mem_show(struct seq_file *m, void *v)
-{
-	i2eBordStrPtr  pB;
-	i2ChanStrPtr  pCh;
-	PTTY tty;
-	int i;
-
-#define FMTLINE	"%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
-#define FMTLIN2	"     0x%04x 0x%04x tx flow 0x%x\n"
-#define FMTLIN3	"     0x%04x 0x%04x rc flow\n"
-
-	seq_printf(m,"\n");
-
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		pB = i2BoardPtrTable[i];
-		if ( pB ) {
-			seq_printf(m,"board %d:\n",i);
-			seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
-				pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
-		}
-	}
-
-	seq_printf(m,"#: tty flags, port flags,     cflags,     iflags\n");
-	for (i=0; i < IP2_MAX_PORTS; i++) {
-		pCh = DevTable[i];
-		if (pCh) {
-			tty = pCh->pTTY;
-			if (tty && tty->count) {
-				seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
-									tty->termios->c_cflag,tty->termios->c_iflag);
-
-				seq_printf(m,FMTLIN2,
-						pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
-				seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
-			}
-		}
-	}
-	return 0;
-}
-
-static int proc_ip2mem_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_ip2mem_show, NULL);
-}
-
-static const struct file_operations ip2mem_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_ip2mem_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * This is the handler for /proc/tty/driver/ip2
- *
- * This stretch of code has been largely plagerized from at least three
- * different sources including ip2mkdev.c and a couple of other drivers.
- * The bugs are all mine.  :-)	=mhw=
- */
-static int ip2_proc_show(struct seq_file *m, void *v)
-{
-	int	i, j, box;
-	int	boxes = 0;
-	int	ports = 0;
-	int	tports = 0;
-	i2eBordStrPtr  pB;
-	char *sep;
-
-	seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion);
-	seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
-			IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
-			IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
-
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		/* This need to be reset for a board by board count... */
-		boxes = 0;
-		pB = i2BoardPtrTable[i];
-		if( pB ) {
-			switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) 
-			{
-			case POR_ID_FIIEX:
-				seq_printf(m, "Board %d: EX ports=", i);
-				sep = "";
-				for( box = 0; box < ABS_MAX_BOXES; ++box )
-				{
-					ports = 0;
-
-					if( pB->i2eChannelMap[box] != 0 ) ++boxes;
-					for( j = 0; j < ABS_BIGGEST_BOX; ++j ) 
-					{
-						if( pB->i2eChannelMap[box] & 1<< j ) {
-							++ports;
-						}
-					}
-					seq_printf(m, "%s%d", sep, ports);
-					sep = ",";
-					tports += ports;
-				}
-				seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8);
-				break;
-
-			case POR_ID_II_4:
-				seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i);
-				tports = ports = 4;
-				break;
-
-			case POR_ID_II_8:
-				seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i);
-				tports = ports = 8;
-				break;
-
-			case POR_ID_II_8R:
-				seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i);
-				tports = ports = 8;
-				break;
-
-			default:
-				seq_printf(m, "Board %d: unknown", i);
-				/* Don't try and probe for minor numbers */
-				tports = ports = 0;
-			}
-
-		} else {
-			/* Don't try and probe for minor numbers */
-			seq_printf(m, "Board %d: vacant", i);
-			tports = ports = 0;
-		}
-
-		if( tports ) {
-			seq_puts(m, " minors=");
-			sep = "";
-			for ( box = 0; box < ABS_MAX_BOXES; ++box )
-			{
-				for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
-				{
-					if ( pB->i2eChannelMap[box] & (1 << j) )
-					{
-						seq_printf(m, "%s%d", sep,
-							j + ABS_BIGGEST_BOX *
-							(box+i*ABS_MAX_BOXES));
-						sep = ",";
-					}
-				}
-			}
-		}
-		seq_putc(m, '\n');
-	}
-	return 0;
- }
-
-static int ip2_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ip2_proc_show, NULL);
-}
-
-static const struct file_operations ip2_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= ip2_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
- 
-/******************************************************************************/
-/* Function:   ip2trace()                                                     */
-/* Parameters: Value to add to trace buffer                                   */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-#ifdef IP2DEBUG_TRACE
-void
-ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
-{
-	long flags;
-	unsigned long *pCode = &codes;
-	union ip2breadcrumb bc;
-	i2ChanStrPtr  pCh;
-
-
-	tracebuf[tracestuff++] = jiffies;
-	if ( tracestuff == TRACEMAX ) {
-		tracestuff = 0;
-	}
-	if ( tracestuff == tracestrip ) {
-		if ( ++tracestrip == TRACEMAX ) {
-			tracestrip = 0;
-		}
-		++tracewrap;
-	}
-
-	bc.hdr.port  = 0xff & pn;
-	bc.hdr.cat   = cat;
-	bc.hdr.codes = (unsigned char)( codes & 0xff );
-	bc.hdr.label = label;
-	tracebuf[tracestuff++] = bc.value;
-
-	for (;;) {
-		if ( tracestuff == TRACEMAX ) {
-			tracestuff = 0;
-		}
-		if ( tracestuff == tracestrip ) {
-			if ( ++tracestrip == TRACEMAX ) {
-				tracestrip = 0;
-			}
-			++tracewrap;
-		}
-
-		if ( !codes-- )
-			break;
-
-		tracebuf[tracestuff++] = *++pCode;
-	}
-}
-#endif
-
-
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
-
-MODULE_FIRMWARE("intelliport2.bin");
diff --git a/drivers/char/ip2/ip2trace.h b/drivers/char/ip2/ip2trace.h
deleted file mode 100644
index da20435..0000000
--- a/drivers/char/ip2/ip2trace.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-//
-union ip2breadcrumb 
-{
-	struct { 
-		unsigned char port, cat, codes, label;
-	} __attribute__ ((packed)) hdr;
-	unsigned long value;
-};
-
-#define ITRC_NO_PORT 	0xFF
-#define CHANN	(pCh->port_index)
-
-#define	ITRC_ERROR	'!'
-#define	ITRC_INIT 	'A'
-#define	ITRC_OPEN	'B'
-#define	ITRC_CLOSE	'C'
-#define	ITRC_DRAIN	'D'
-#define	ITRC_IOCTL	'E'
-#define	ITRC_FLUSH	'F'
-#define	ITRC_STATUS	'G'
-#define	ITRC_HANGUP	'H'
-#define	ITRC_INTR 	'I'
-#define	ITRC_SFLOW	'J'
-#define	ITRC_SBCMD	'K'
-#define	ITRC_SICMD	'L'
-#define	ITRC_MODEM	'M'
-#define	ITRC_INPUT	'N'
-#define	ITRC_OUTPUT	'O'
-#define	ITRC_PUTC	'P'
-#define	ITRC_QUEUE	'Q'
-#define	ITRC_STFLW	'R'
-#define	ITRC_SFIFO	'S'
-#define	ITRC_VERIFY	'V'
-#define	ITRC_WRITE	'W'
-
-#define	ITRC_ENTER	0x00
-#define	ITRC_RETURN	0xFF
-
-#define	ITRC_QUEUE_ROOM	2
-#define	ITRC_QUEUE_CMD	6
-
diff --git a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h
deleted file mode 100644
index 9d67b26..0000000
--- a/drivers/char/ip2/ip2types.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants and type definitions.
-*
-*   NOTES:
-*
-*******************************************************************************/
-#ifndef IP2TYPES_H
-#define IP2TYPES_H
-
-//*************
-//* Constants *
-//*************
-
-// Define some limits for this driver. Ports per board is a hardware limitation
-// that will not change. Current hardware limits this to 64 ports per board.
-// Boards per driver is a self-imposed limit.
-//
-#define IP2_MAX_BOARDS        4
-#define IP2_PORTS_PER_BOARD   ABS_MOST_PORTS
-#define IP2_MAX_PORTS         (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD)
-
-#define ISA    0
-#define PCI    1
-#define EISA   2
-
-//********************
-//* Type Definitions *
-//********************
-
-typedef struct tty_struct *   PTTY;
-typedef wait_queue_head_t   PWAITQ;
-
-typedef unsigned char         UCHAR;
-typedef unsigned int          UINT;
-typedef unsigned short        USHORT;
-typedef unsigned long         ULONG;
-
-typedef struct 
-{
-	short irq[IP2_MAX_BOARDS]; 
-	unsigned short addr[IP2_MAX_BOARDS];
-	int type[IP2_MAX_BOARDS];
-#ifdef CONFIG_PCI
-	struct pci_dev *pci_dev[IP2_MAX_BOARDS];
-#endif
-} ip2config_t;
-
-#endif
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 62787e3..c86d43b 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -66,13 +66,10 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/pnp.h>
-
-#ifdef CONFIG_PPC_OF
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#endif
 
 #define PFX "ipmi_si: "
 
@@ -116,13 +113,7 @@ static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI",
 
 #define DEVICE_NAME "ipmi_si"
 
-static struct platform_driver ipmi_driver = {
-	.driver = {
-		.name = DEVICE_NAME,
-		.bus = &platform_bus_type
-	}
-};
-
+static struct platform_driver ipmi_driver;
 
 /*
  * Indexes into stats[] in smi_info below.
@@ -308,9 +299,6 @@ static int pci_registered;
 #ifdef CONFIG_ACPI
 static int pnp_registered;
 #endif
-#ifdef CONFIG_PPC_OF
-static int of_registered;
-#endif
 
 static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
 static int num_max_busy_us;
@@ -1868,8 +1856,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
 	return rv;
 }
 
-static void __devinit hardcode_find_bmc(void)
+static int __devinit hardcode_find_bmc(void)
 {
+	int ret = -ENODEV;
 	int             i;
 	struct smi_info *info;
 
@@ -1879,7 +1868,7 @@ static void __devinit hardcode_find_bmc(void)
 
 		info = smi_info_alloc();
 		if (!info)
-			return;
+			return -ENOMEM;
 
 		info->addr_source = SI_HARDCODED;
 		printk(KERN_INFO PFX "probing via hardcoded address\n");
@@ -1932,10 +1921,12 @@ static void __devinit hardcode_find_bmc(void)
 		if (!add_smi(info)) {
 			if (try_smi_init(info))
 				cleanup_one_si(info);
+			ret = 0;
 		} else {
 			kfree(info);
 		}
 	}
+	return ret;
 }
 
 #ifdef CONFIG_ACPI
@@ -2563,11 +2554,9 @@ static struct pci_driver ipmi_pci_driver = {
 };
 #endif /* CONFIG_PCI */
 
-
-#ifdef CONFIG_PPC_OF
-static int __devinit ipmi_of_probe(struct platform_device *dev,
-			 const struct of_device_id *match)
+static int __devinit ipmi_probe(struct platform_device *dev)
 {
+#ifdef CONFIG_OF
 	struct smi_info *info;
 	struct resource resource;
 	const __be32 *regsize, *regspacing, *regshift;
@@ -2577,6 +2566,9 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 
 	dev_info(&dev->dev, "probing via device tree\n");
 
+	if (!dev->dev.of_match)
+		return -EINVAL;
+
 	ret = of_address_to_resource(np, 0, &resource);
 	if (ret) {
 		dev_warn(&dev->dev, PFX "invalid address from OF\n");
@@ -2609,7 +2601,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 		return -ENOMEM;
 	}
 
-	info->si_type		= (enum si_type) match->data;
+	info->si_type		= (enum si_type) dev->dev.of_match->data;
 	info->addr_source	= SI_DEVICETREE;
 	info->irq_setup		= std_irq_setup;
 
@@ -2640,13 +2632,15 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
 		kfree(info);
 		return -EBUSY;
 	}
-
+#endif
 	return 0;
 }
 
-static int __devexit ipmi_of_remove(struct platform_device *dev)
+static int __devexit ipmi_remove(struct platform_device *dev)
 {
+#ifdef CONFIG_OF
 	cleanup_one_si(dev_get_drvdata(&dev->dev));
+#endif
 	return 0;
 }
 
@@ -2661,16 +2655,15 @@ static struct of_device_id ipmi_match[] =
 	{},
 };
 
-static struct of_platform_driver ipmi_of_platform_driver = {
+static struct platform_driver ipmi_driver = {
 	.driver = {
-		.name = "ipmi",
+		.name = DEVICE_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = ipmi_match,
 	},
-	.probe		= ipmi_of_probe,
-	.remove		= __devexit_p(ipmi_of_remove),
+	.probe		= ipmi_probe,
+	.remove		= __devexit_p(ipmi_remove),
 };
-#endif /* CONFIG_PPC_OF */
 
 static int wait_for_msg_done(struct smi_info *smi_info)
 {
@@ -3348,8 +3341,7 @@ static int __devinit init_ipmi_si(void)
 		return 0;
 	initialized = 1;
 
-	/* Register the device drivers. */
-	rv = driver_register(&ipmi_driver.driver);
+	rv = platform_driver_register(&ipmi_driver);
 	if (rv) {
 		printk(KERN_ERR PFX "Unable to register driver: %d\n", rv);
 		return rv;
@@ -3373,15 +3365,9 @@ static int __devinit init_ipmi_si(void)
 
 	printk(KERN_INFO "IPMI System Interface driver.\n");
 
-	hardcode_find_bmc();
-
 	/* If the user gave us a device, they presumably want us to use it */
-	mutex_lock(&smi_infos_lock);
-	if (!list_empty(&smi_infos)) {
-		mutex_unlock(&smi_infos_lock);
+	if (!hardcode_find_bmc())
 		return 0;
-	}
-	mutex_unlock(&smi_infos_lock);
 
 #ifdef CONFIG_PCI
 	rv = pci_register_driver(&ipmi_pci_driver);
@@ -3404,11 +3390,6 @@ static int __devinit init_ipmi_si(void)
 	spmi_find_bmc();
 #endif
 
-#ifdef CONFIG_PPC_OF
-	of_register_platform_driver(&ipmi_of_platform_driver);
-	of_registered = 1;
-#endif
-
 	/* We prefer devices with interrupts, but in the case of a machine
 	   with multiple BMCs we assume that there will be several instances
 	   of a given type so if we succeed in registering a type then also
@@ -3556,17 +3537,12 @@ static void __exit cleanup_ipmi_si(void)
 		pnp_unregister_driver(&ipmi_pnp_driver);
 #endif
 
-#ifdef CONFIG_PPC_OF
-	if (of_registered)
-		of_unregister_platform_driver(&ipmi_of_platform_driver);
-#endif
+	platform_driver_unregister(&ipmi_driver);
 
 	mutex_lock(&smi_infos_lock);
 	list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
 		cleanup_one_si(e);
 	mutex_unlock(&smi_infos_lock);
-
-	driver_unregister(&ipmi_driver.driver);
 }
 module_exit(cleanup_ipmi_si);
 
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
deleted file mode 100644
index c27e9d2..0000000
--- a/drivers/char/isicom.c
+++ /dev/null
@@ -1,1736 +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.
- *
- *	Original driver code supplied by Multi-Tech
- *
- *	Changes
- *	1/9/98	alan@lxorguk.ukuu.org.uk
- *					Merge to 2.0.x kernel tree
- *					Obtain and use official major/minors
- *					Loader switched to a misc device
- *					(fixed range check bug as a side effect)
- *					Printk clean up
- *	9/12/98	alan@lxorguk.ukuu.org.uk
- *					Rough port to 2.1.x
- *
- *	10/6/99 sameer			Merged the ISA and PCI drivers to
- *					a new unified driver.
- *
- *	3/9/99	sameer			Added support for ISI4616 cards.
- *
- *	16/9/99	sameer			We do not force RTS low anymore.
- *					This is to prevent the firmware
- *					from getting confused.
- *
- *	26/10/99 sameer			Cosmetic changes:The driver now
- *					dumps the Port Count information
- *					along with I/O address and IRQ.
- *
- *	13/12/99 sameer			Fixed the problem with IRQ sharing.
- *
- *	10/5/00  sameer			Fixed isicom_shutdown_board()
- *					to not lower DTR on all the ports
- *					when the last port on the card is
- *					closed.
- *
- *	10/5/00  sameer			Signal mask setup command added
- *					to  isicom_setup_port and
- *					isicom_shutdown_port.
- *
- *	24/5/00  sameer			The driver is now SMP aware.
- *
- *
- *	27/11/00 Vinayak P Risbud	Fixed the Driver Crash Problem
- *
- *
- *	03/01/01  anil .s		Added support for resetting the
- *					internal modems on ISI cards.
- *
- *	08/02/01  anil .s		Upgraded the driver for kernel
- *					2.4.x
- *
- *	11/04/01  Kevin			Fixed firmware load problem with
- *					ISIHP-4X card
- *
- *	30/04/01  anil .s		Fixed the remote login through
- *					ISI port problem. Now the link
- *					does not go down before password
- *					prompt.
- *
- *	03/05/01  anil .s		Fixed the problem with IRQ sharing
- *					among ISI-PCI cards.
- *
- *	03/05/01  anil .s		Added support to display the version
- *					info during insmod as well as module
- *					listing by lsmod.
- *
- *	10/05/01  anil .s		Done the modifications to the source
- *					file and Install script so that the
- *					same installation can be used for
- *					2.2.x and 2.4.x kernel.
- *
- *	06/06/01  anil .s		Now we drop both dtr and rts during
- *					shutdown_port as well as raise them
- *					during isicom_config_port.
- *
- *	09/06/01 acme@conectiva.com.br	use capable, not suser, do
- *					restore_flags on failure in
- *					isicom_send_break, verify put_user
- *					result
- *
- *	11/02/03  ranjeeth		Added support for 230 Kbps and 460 Kbps
- *					Baud index extended to 21
- *
- *	20/03/03  ranjeeth		Made to work for Linux Advanced server.
- *					Taken care of license warning.
- *
- *	10/12/03  Ravindra		Made to work for Fedora Core 1 of
- *					Red Hat Distribution
- *
- *	06/01/05  Alan Cox 		Merged the ISI and base kernel strands
- *					into a single 2.6 driver
- *
- *	***********************************************************
- *
- *	To use this driver you also need the support package. You
- *	can find this in RPM format on
- *		ftp://ftp.linux.org.uk/pub/linux/alan
- *
- *	You can find the original tools for this direct from Multitech
- *		ftp://ftp.multitech.com/ISI-Cards/
- *
- *	Having installed the cards the module options (/etc/modprobe.conf)
- *
- *	options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
- *
- *	Omit those entries for boards you don't have installed.
- *
- *	TODO
- *		Merge testing
- *		64-bit verification
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/termios.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <asm/system.h>
-
-#include <linux/pci.h>
-
-#include <linux/isicom.h>
-
-#define InterruptTheCard(base) outw(0, (base) + 0xc)
-#define ClearInterrupt(base) inw((base) + 0x0a)
-
-#ifdef DEBUG
-#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
-#else
-#define isicom_paranoia_check(a, b, c) 0
-#endif
-
-static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit isicom_remove(struct pci_dev *);
-
-static struct pci_device_id isicom_pci_tbl[] = {
-	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2051) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2052) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2053) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2054) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2055) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2056) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2057) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2058) },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
-
-static struct pci_driver isicom_driver = {
-	.name		= "isicom",
-	.id_table	= isicom_pci_tbl,
-	.probe		= isicom_probe,
-	.remove		= __devexit_p(isicom_remove)
-};
-
-static int prev_card = 3;	/*	start servicing isi_card[0]	*/
-static struct tty_driver *isicom_normal;
-
-static void isicom_tx(unsigned long _data);
-static void isicom_start(struct tty_struct *tty);
-
-static DEFINE_TIMER(tx, isicom_tx, 0, 0);
-
-/*   baud index mappings from linux defns to isi */
-
-static signed char linuxb_to_isib[] = {
-	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
-};
-
-struct	isi_board {
-	unsigned long		base;
-	int			irq;
-	unsigned char		port_count;
-	unsigned short		status;
-	unsigned short		port_status; /* each bit for each port */
-	unsigned short		shift_count;
-	struct isi_port		*ports;
-	signed char		count;
-	spinlock_t		card_lock; /* Card wide lock 11/5/00 -sameer */
-	unsigned long		flags;
-	unsigned int		index;
-};
-
-struct	isi_port {
-	unsigned short		magic;
-	struct tty_port		port;
-	u16			channel;
-	u16			status;
-	struct isi_board	*card;
-	unsigned char		*xmit_buf;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-};
-
-static struct isi_board isi_card[BOARD_COUNT];
-static struct isi_port  isi_ports[PORT_COUNT];
-
-/*
- *	Locking functions for card level locking. We need to own both
- *	the kernel lock for the card and have the card in a position that
- *	it wants to talk.
- */
-
-static inline int WaitTillCardIsFree(unsigned long base)
-{
-	unsigned int count = 0;
-	unsigned int a = in_atomic(); /* do we run under spinlock? */
-
-	while (!(inw(base + 0xe) & 0x1) && count++ < 100)
-		if (a)
-			mdelay(1);
-		else
-			msleep(1);
-
-	return !(inw(base + 0xe) & 0x1);
-}
-
-static int lock_card(struct isi_board *card)
-{
-	unsigned long base = card->base;
-	unsigned int retries, a;
-
-	for (retries = 0; retries < 10; retries++) {
-		spin_lock_irqsave(&card->card_lock, card->flags);
-		for (a = 0; a < 10; a++) {
-			if (inw(base + 0xe) & 0x1)
-				return 1;
-			udelay(10);
-		}
-		spin_unlock_irqrestore(&card->card_lock, card->flags);
-		msleep(10);
-	}
-	pr_warning("Failed to lock Card (0x%lx)\n", card->base);
-
-	return 0;	/* Failed to acquire the card! */
-}
-
-static void unlock_card(struct isi_board *card)
-{
-	spin_unlock_irqrestore(&card->card_lock, card->flags);
-}
-
-/*
- *  ISI Card specific ops ...
- */
-
-/* card->lock HAS to be held */
-static void raise_dtr(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0504, base);
-	InterruptTheCard(base);
-	port->status |= ISI_DTR;
-}
-
-/* card->lock HAS to be held */
-static inline void drop_dtr(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0404, base);
-	InterruptTheCard(base);
-	port->status &= ~ISI_DTR;
-}
-
-/* card->lock HAS to be held */
-static inline void raise_rts(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0a04, base);
-	InterruptTheCard(base);
-	port->status |= ISI_RTS;
-}
-
-/* card->lock HAS to be held */
-static inline void drop_rts(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0804, base);
-	InterruptTheCard(base);
-	port->status &= ~ISI_RTS;
-}
-
-/* card->lock MUST NOT be held */
-
-static void isicom_dtr_rts(struct tty_port *port, int on)
-{
-	struct isi_port *ip = container_of(port, struct isi_port, port);
-	struct isi_board *card = ip->card;
-	unsigned long base = card->base;
-	u16 channel = ip->channel;
-
-	if (!lock_card(card))
-		return;
-
-	if (on) {
-		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-		outw(0x0f04, base);
-		InterruptTheCard(base);
-		ip->status |= (ISI_DTR | ISI_RTS);
-	} else {
-		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-		outw(0x0C04, base);
-		InterruptTheCard(base);
-		ip->status &= ~(ISI_DTR | ISI_RTS);
-	}
-	unlock_card(card);
-}
-
-/* card->lock HAS to be held */
-static void drop_dtr_rts(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0c04, base);
-	InterruptTheCard(base);
-	port->status &= ~(ISI_RTS | ISI_DTR);
-}
-
-/*
- *	ISICOM Driver specific routines ...
- *
- */
-
-static inline int __isicom_paranoia_check(struct isi_port const *port,
-	char *name, const char *routine)
-{
-	if (!port) {
-		pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
-			   name, routine);
-		return 1;
-	}
-	if (port->magic != ISICOM_MAGIC) {
-		pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
-			   name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-
-/*
- *	Transmitter.
- *
- *	We shovel data into the card buffers on a regular basis. The card
- *	will do the rest of the work for us.
- */
-
-static void isicom_tx(unsigned long _data)
-{
-	unsigned long flags, base;
-	unsigned int retries;
-	short count = (BOARD_COUNT-1), card;
-	short txcount, wrd, residue, word_count, cnt;
-	struct isi_port *port;
-	struct tty_struct *tty;
-
-	/*	find next active board	*/
-	card = (prev_card + 1) & 0x0003;
-	while (count-- > 0) {
-		if (isi_card[card].status & BOARD_ACTIVE)
-			break;
-		card = (card + 1) & 0x0003;
-	}
-	if (!(isi_card[card].status & BOARD_ACTIVE))
-		goto sched_again;
-
-	prev_card = card;
-
-	count = isi_card[card].port_count;
-	port = isi_card[card].ports;
-	base = isi_card[card].base;
-
-	spin_lock_irqsave(&isi_card[card].card_lock, flags);
-	for (retries = 0; retries < 100; retries++) {
-		if (inw(base + 0xe) & 0x1)
-			break;
-		udelay(2);
-	}
-	if (retries >= 100)
-		goto unlock;
-
-	tty = tty_port_tty_get(&port->port);
-	if (tty == NULL)
-		goto put_unlock;
-
-	for (; count > 0; count--, port++) {
-		/* port not active or tx disabled to force flow control */
-		if (!(port->port.flags & ASYNC_INITIALIZED) ||
-				!(port->status & ISI_TXOK))
-			continue;
-
-		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
-		if (txcount <= 0 || tty->stopped || tty->hw_stopped)
-			continue;
-
-		if (!(inw(base + 0x02) & (1 << port->channel)))
-			continue;
-
-		pr_debug("txing %d bytes, port%d.\n",
-			 txcount, port->channel + 1);
-		outw((port->channel << isi_card[card].shift_count) | txcount,
-			base);
-		residue = NO;
-		wrd = 0;
-		while (1) {
-			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
-					- port->xmit_tail));
-			if (residue == YES) {
-				residue = NO;
-				if (cnt > 0) {
-					wrd |= (port->port.xmit_buf[port->xmit_tail]
-									<< 8);
-					port->xmit_tail = (port->xmit_tail + 1)
-						& (SERIAL_XMIT_SIZE - 1);
-					port->xmit_cnt--;
-					txcount--;
-					cnt--;
-					outw(wrd, base);
-				} else {
-					outw(wrd, base);
-					break;
-				}
-			}
-			if (cnt <= 0)
-				break;
-			word_count = cnt >> 1;
-			outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
-			port->xmit_tail = (port->xmit_tail
-				+ (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
-			txcount -= (word_count << 1);
-			port->xmit_cnt -= (word_count << 1);
-			if (cnt & 0x0001) {
-				residue = YES;
-				wrd = port->port.xmit_buf[port->xmit_tail];
-				port->xmit_tail = (port->xmit_tail + 1)
-					& (SERIAL_XMIT_SIZE - 1);
-				port->xmit_cnt--;
-				txcount--;
-			}
-		}
-
-		InterruptTheCard(base);
-		if (port->xmit_cnt <= 0)
-			port->status &= ~ISI_TXOK;
-		if (port->xmit_cnt <= WAKEUP_CHARS)
-			tty_wakeup(tty);
-	}
-
-put_unlock:
-	tty_kref_put(tty);
-unlock:
-	spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
-	/*	schedule another tx for hopefully in about 10ms	*/
-sched_again:
-	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
-}
-
-/*
- *	Main interrupt handler routine
- */
-
-static irqreturn_t isicom_interrupt(int irq, void *dev_id)
-{
-	struct isi_board *card = dev_id;
-	struct isi_port *port;
-	struct tty_struct *tty;
-	unsigned long base;
-	u16 header, word_count, count, channel;
-	short byte_count;
-	unsigned char *rp;
-
-	if (!card || !(card->status & FIRMWARE_LOADED))
-		return IRQ_NONE;
-
-	base = card->base;
-
-	/* did the card interrupt us? */
-	if (!(inw(base + 0x0e) & 0x02))
-		return IRQ_NONE;
-
-	spin_lock(&card->card_lock);
-
-	/*
-	 * disable any interrupts from the PCI card and lower the
-	 * interrupt line
-	 */
-	outw(0x8000, base+0x04);
-	ClearInterrupt(base);
-
-	inw(base);		/* get the dummy word out */
-	header = inw(base);
-	channel = (header & 0x7800) >> card->shift_count;
-	byte_count = header & 0xff;
-
-	if (channel + 1 > card->port_count) {
-		pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
-			   __func__, base, channel+1);
-		outw(0x0000, base+0x04); /* enable interrupts */
-		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;
-	}
-	port = card->ports + channel;
-	if (!(port->port.flags & ASYNC_INITIALIZED)) {
-		outw(0x0000, base+0x04); /* enable interrupts */
-		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;
-	}
-
-	tty = tty_port_tty_get(&port->port);
-	if (tty == NULL) {
-		word_count = byte_count >> 1;
-		while (byte_count > 1) {
-			inw(base);
-			byte_count -= 2;
-		}
-		if (byte_count & 0x01)
-			inw(base);
-		outw(0x0000, base+0x04); /* enable interrupts */
-		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;
-	}
-
-	if (header & 0x8000) {		/* Status Packet */
-		header = inw(base);
-		switch (header & 0xff) {
-		case 0:	/* Change in EIA signals */
-			if (port->port.flags & ASYNC_CHECK_CD) {
-				if (port->status & ISI_DCD) {
-					if (!(header & ISI_DCD)) {
-					/* Carrier has been lost  */
-						pr_debug("%s: DCD->low.\n",
-							 __func__);
-						port->status &= ~ISI_DCD;
-						tty_hangup(tty);
-					}
-				} else if (header & ISI_DCD) {
-				/* Carrier has been detected */
-					pr_debug("%s: DCD->high.\n",
-						__func__);
-					port->status |= ISI_DCD;
-					wake_up_interruptible(&port->port.open_wait);
-				}
-			} else {
-				if (header & ISI_DCD)
-					port->status |= ISI_DCD;
-				else
-					port->status &= ~ISI_DCD;
-			}
-
-			if (port->port.flags & ASYNC_CTS_FLOW) {
-				if (tty->hw_stopped) {
-					if (header & ISI_CTS) {
-						port->port.tty->hw_stopped = 0;
-						/* start tx ing */
-						port->status |= (ISI_TXOK
-							| ISI_CTS);
-						tty_wakeup(tty);
-					}
-				} else if (!(header & ISI_CTS)) {
-					tty->hw_stopped = 1;
-					/* stop tx ing */
-					port->status &= ~(ISI_TXOK | ISI_CTS);
-				}
-			} else {
-				if (header & ISI_CTS)
-					port->status |= ISI_CTS;
-				else
-					port->status &= ~ISI_CTS;
-			}
-
-			if (header & ISI_DSR)
-				port->status |= ISI_DSR;
-			else
-				port->status &= ~ISI_DSR;
-
-			if (header & ISI_RI)
-				port->status |= ISI_RI;
-			else
-				port->status &= ~ISI_RI;
-
-			break;
-
-		case 1:	/* Received Break !!! */
-			tty_insert_flip_char(tty, 0, TTY_BREAK);
-			if (port->port.flags & ASYNC_SAK)
-				do_SAK(tty);
-			tty_flip_buffer_push(tty);
-			break;
-
-		case 2:	/* Statistics		 */
-			pr_debug("%s: stats!!!\n", __func__);
-			break;
-
-		default:
-			pr_debug("%s: Unknown code in status packet.\n",
-				 __func__);
-			break;
-		}
-	} else {				/* Data   Packet */
-
-		count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
-		pr_debug("%s: Can rx %d of %d bytes.\n",
-			 __func__, count, byte_count);
-		word_count = count >> 1;
-		insw(base, rp, word_count);
-		byte_count -= (word_count << 1);
-		if (count & 0x0001) {
-			tty_insert_flip_char(tty,  inw(base) & 0xff,
-				TTY_NORMAL);
-			byte_count -= 2;
-		}
-		if (byte_count > 0) {
-			pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
-				 __func__, base, channel + 1);
-		/* drain out unread xtra data */
-		while (byte_count > 0) {
-				inw(base);
-				byte_count -= 2;
-			}
-		}
-		tty_flip_buffer_push(tty);
-	}
-	outw(0x0000, base+0x04); /* enable interrupts */
-	spin_unlock(&card->card_lock);
-	tty_kref_put(tty);
-
-	return IRQ_HANDLED;
-}
-
-static void isicom_config_port(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long baud;
-	unsigned long base = card->base;
-	u16 channel_setup, channel = port->channel,
-		shift_count = card->shift_count;
-	unsigned char flow_ctrl;
-
-	/* FIXME: Switch to new tty baud API */
-	baud = C_BAUD(tty);
-	if (baud & CBAUDEX) {
-		baud &= ~CBAUDEX;
-
-		/*  if CBAUDEX bit is on and the baud is set to either 50 or 75
-		 *  then the card is programmed for 57.6Kbps or 115Kbps
-		 *  respectively.
-		 */
-
-		/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
-		if (baud < 1 || baud > 4)
-			tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			baud += 15;
-	}
-	if (baud == 15) {
-
-		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
-		 *  by the set_serial_info ioctl ... this is done by
-		 *  the 'setserial' utility.
-		 */
-
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud++; /*  57.6 Kbps */
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud += 2; /*  115  Kbps */
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baud += 3; /* 230 kbps*/
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baud += 4; /* 460 kbps*/
-	}
-	if (linuxb_to_isib[baud] == -1) {
-		/* hang up */
-		drop_dtr(port);
-		return;
-	} else
-		raise_dtr(port);
-
-	if (WaitTillCardIsFree(base) == 0) {
-		outw(0x8000 | (channel << shift_count) | 0x03, base);
-		outw(linuxb_to_isib[baud] << 8 | 0x03, base);
-		channel_setup = 0;
-		switch (C_CSIZE(tty)) {
-		case CS5:
-			channel_setup |= ISICOM_CS5;
-			break;
-		case CS6:
-			channel_setup |= ISICOM_CS6;
-			break;
-		case CS7:
-			channel_setup |= ISICOM_CS7;
-			break;
-		case CS8:
-			channel_setup |= ISICOM_CS8;
-			break;
-		}
-
-		if (C_CSTOPB(tty))
-			channel_setup |= ISICOM_2SB;
-		if (C_PARENB(tty)) {
-			channel_setup |= ISICOM_EVPAR;
-			if (C_PARODD(tty))
-				channel_setup |= ISICOM_ODPAR;
-		}
-		outw(channel_setup, base);
-		InterruptTheCard(base);
-	}
-	if (C_CLOCAL(tty))
-		port->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->port.flags |= ASYNC_CHECK_CD;
-
-	/* flow control settings ...*/
-	flow_ctrl = 0;
-	port->port.flags &= ~ASYNC_CTS_FLOW;
-	if (C_CRTSCTS(tty)) {
-		port->port.flags |= ASYNC_CTS_FLOW;
-		flow_ctrl |= ISICOM_CTSRTS;
-	}
-	if (I_IXON(tty))
-		flow_ctrl |= ISICOM_RESPOND_XONXOFF;
-	if (I_IXOFF(tty))
-		flow_ctrl |= ISICOM_INITIATE_XONXOFF;
-
-	if (WaitTillCardIsFree(base) == 0) {
-		outw(0x8000 | (channel << shift_count) | 0x04, base);
-		outw(flow_ctrl << 8 | 0x05, base);
-		outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
-		InterruptTheCard(base);
-	}
-
-	/*	rx enabled -> enable port for rx on the card	*/
-	if (C_CREAD(tty)) {
-		card->port_status |= (1 << channel);
-		outw(card->port_status, base + 0x02);
-	}
-}
-
-/* open et all */
-
-static inline void isicom_setup_board(struct isi_board *bp)
-{
-	int channel;
-	struct isi_port *port;
-
-	bp->count++;
-	if (!(bp->status & BOARD_INIT)) {
-		port = bp->ports;
-		for (channel = 0; channel < bp->port_count; channel++, port++)
-			drop_dtr_rts(port);
-	}
-	bp->status |= BOARD_ACTIVE | BOARD_INIT;
-}
-
-/* Activate and thus setup board are protected from races against shutdown
-   by the tty_port mutex */
-
-static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
-{
-	struct isi_port *port = container_of(tport, struct isi_port, port);
-	struct isi_board *card = port->card;
-	unsigned long flags;
-
-	if (tty_port_alloc_xmit_buf(tport) < 0)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	isicom_setup_board(card);
-
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
-	/*	discard any residual data	*/
-	if (WaitTillCardIsFree(card->base) == 0) {
-		outw(0x8000 | (port->channel << card->shift_count) | 0x02,
-				card->base);
-		outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
-		InterruptTheCard(card->base);
-	}
-	isicom_config_port(tty);
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	return 0;
-}
-
-static int isicom_carrier_raised(struct tty_port *port)
-{
-	struct isi_port *ip = container_of(port, struct isi_port, port);
-	return (ip->status & ISI_DCD)?1 : 0;
-}
-
-static struct tty_port *isicom_find_port(struct tty_struct *tty)
-{
-	struct isi_port *port;
-	struct isi_board *card;
-	unsigned int board;
-	int line = tty->index;
-
-	if (line < 0 || line > PORT_COUNT-1)
-		return NULL;
-	board = BOARD(line);
-	card = &isi_card[board];
-
-	if (!(card->status & FIRMWARE_LOADED))
-		return NULL;
-
-	/*  open on a port greater than the port count for the card !!! */
-	if (line > ((board * 16) + card->port_count - 1))
-		return NULL;
-
-	port = &isi_ports[line];
-	if (isicom_paranoia_check(port, tty->name, "isicom_open"))
-		return NULL;
-
-	return &port->port;
-}
-
-static int isicom_open(struct tty_struct *tty, struct file *filp)
-{
-	struct isi_port *port;
-	struct tty_port *tport;
-
-	tport = isicom_find_port(tty);
-	if (tport == NULL)
-		return -ENODEV;
-	port = container_of(tport, struct isi_port, port);
-
-	tty->driver_data = port;
-	return tty_port_open(tport, tty, filp);
-}
-
-/* close et all */
-
-/* card->lock HAS to be held */
-static void isicom_shutdown_port(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-
-	if (--card->count < 0) {
-		pr_debug("%s: bad board(0x%lx) count %d.\n",
-			 __func__, card->base, card->count);
-		card->count = 0;
-	}
-	/* last port was closed, shutdown that board too */
-	if (!card->count)
-		card->status &= BOARD_ACTIVE;
-}
-
-static void isicom_flush_buffer(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	tty_wakeup(tty);
-}
-
-static void isicom_shutdown(struct tty_port *port)
-{
-	struct isi_port *ip = container_of(port, struct isi_port, port);
-	struct isi_board *card = ip->card;
-	unsigned long flags;
-
-	/* indicate to the card that no more data can be received
-	   on this port */
-	spin_lock_irqsave(&card->card_lock, flags);
-	card->port_status &= ~(1 << ip->channel);
-	outw(card->port_status, card->base + 0x02);
-	isicom_shutdown_port(ip);
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	tty_port_free_xmit_buf(port);
-}
-
-static void isicom_close(struct tty_struct *tty, struct file *filp)
-{
-	struct isi_port *ip = tty->driver_data;
-	struct tty_port *port;
-
-	if (ip == NULL)
-		return;
-
-	port = &ip->port;
-	if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
-		return;
-	tty_port_close(port, tty, filp);
-}
-
-/* write et all */
-static int isicom_write(struct tty_struct *tty,	const unsigned char *buf,
-	int count)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long flags;
-	int cnt, total = 0;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_write"))
-		return 0;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-
-	while (1) {
-		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
-				- 1, SERIAL_XMIT_SIZE - port->xmit_head));
-		if (cnt <= 0)
-			break;
-
-		memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
-		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
-			- 1);
-		port->xmit_cnt += cnt;
-		buf += cnt;
-		count -= cnt;
-		total += cnt;
-	}
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
-		port->status |= ISI_TXOK;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	return total;
-}
-
-/* put_char et all */
-static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
-		return 0;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		return 0;
-	}
-
-	port->port.xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
-	port->xmit_cnt++;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	return 1;
-}
-
-/* flush_chars et all */
-static void isicom_flush_chars(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-			!port->port.xmit_buf)
-		return;
-
-	/* this tells the transmitter to consider this port for
-	   data output to the card ... that's the best we can do. */
-	port->status |= ISI_TXOK;
-}
-
-/* write_room et all */
-static int isicom_write_room(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	int free;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
-		return 0;
-
-	free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (free < 0)
-		free = 0;
-	return free;
-}
-
-/* chars_in_buffer et all */
-static int isicom_chars_in_buffer(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
-		return 0;
-	return port->xmit_cnt;
-}
-
-/* ioctl et all */
-static int isicom_send_break(struct tty_struct *tty, int length)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-
-	if (length == -1)
-		return -EOPNOTSUPP;
-
-	if (!lock_card(card))
-		return -EINVAL;
-
-	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
-	outw((length & 0xff) << 8 | 0x00, base);
-	outw((length & 0xff00), base);
-	InterruptTheCard(base);
-
-	unlock_card(card);
-	return 0;
-}
-
-static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct isi_port *port = tty->driver_data;
-	/* just send the port status */
-	u16 status = port->status;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
-		return -ENODEV;
-
-	return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
-		((status & ISI_DTR) ? TIOCM_DTR : 0) |
-		((status & ISI_DCD) ? TIOCM_CAR : 0) |
-		((status & ISI_DSR) ? TIOCM_DSR : 0) |
-		((status & ISI_CTS) ? TIOCM_CTS : 0) |
-		((status & ISI_RI ) ? TIOCM_RI  : 0);
-}
-
-static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear)
-{
-	struct isi_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
-		return -ENODEV;
-
-	spin_lock_irqsave(&port->card->card_lock, flags);
-	if (set & TIOCM_RTS)
-		raise_rts(port);
-	if (set & TIOCM_DTR)
-		raise_dtr(port);
-
-	if (clear & TIOCM_RTS)
-		drop_rts(port);
-	if (clear & TIOCM_DTR)
-		drop_dtr(port);
-	spin_unlock_irqrestore(&port->card->card_lock, flags);
-
-	return 0;
-}
-
-static int isicom_set_serial_info(struct tty_struct *tty,
-					struct serial_struct __user *info)
-{
-	struct isi_port *port = tty->driver_data;
-	struct serial_struct newinfo;
-	int reconfig_port;
-
-	if (copy_from_user(&newinfo, info, sizeof(newinfo)))
-		return -EFAULT;
-
-	mutex_lock(&port->port.mutex);
-	reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
-		(newinfo.flags & ASYNC_SPD_MASK));
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((newinfo.close_delay != port->port.close_delay) ||
-				(newinfo.closing_wait != port->port.closing_wait) ||
-				((newinfo.flags & ~ASYNC_USR_MASK) !=
-				(port->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-				(newinfo.flags & ASYNC_USR_MASK));
-	} else {
-		port->port.close_delay = newinfo.close_delay;
-		port->port.closing_wait = newinfo.closing_wait;
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-				(newinfo.flags & ASYNC_FLAGS));
-	}
-	if (reconfig_port) {
-		unsigned long flags;
-		spin_lock_irqsave(&port->card->card_lock, flags);
-		isicom_config_port(tty);
-		spin_unlock_irqrestore(&port->card->card_lock, flags);
-	}
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-static int isicom_get_serial_info(struct isi_port *port,
-	struct serial_struct __user *info)
-{
-	struct serial_struct out_info;
-
-	mutex_lock(&port->port.mutex);
-	memset(&out_info, 0, sizeof(out_info));
-/*	out_info.type = ? */
-	out_info.line = port - isi_ports;
-	out_info.port = port->card->base;
-	out_info.irq = port->card->irq;
-	out_info.flags = port->port.flags;
-/*	out_info.baud_base = ? */
-	out_info.close_delay = port->port.close_delay;
-	out_info.closing_wait = port->port.closing_wait;
-	mutex_unlock(&port->port.mutex);
-	if (copy_to_user(info, &out_info, sizeof(out_info)))
-		return -EFAULT;
-	return 0;
-}
-
-static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
-	unsigned int cmd, unsigned long arg)
-{
-	struct isi_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
-		return -ENODEV;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		return isicom_get_serial_info(port, argp);
-
-	case TIOCSSERIAL:
-		return isicom_set_serial_info(tty, argp);
-
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-/* set_termios et all */
-static void isicom_set_termios(struct tty_struct *tty,
-	struct ktermios *old_termios)
-{
-	struct isi_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
-		return;
-
-	if (tty->termios->c_cflag == old_termios->c_cflag &&
-			tty->termios->c_iflag == old_termios->c_iflag)
-		return;
-
-	spin_lock_irqsave(&port->card->card_lock, flags);
-	isicom_config_port(tty);
-	spin_unlock_irqrestore(&port->card->card_lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		isicom_start(tty);
-	}
-}
-
-/* throttle et all */
-static void isicom_throttle(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
-		return;
-
-	/* tell the card that this port cannot handle any more data for now */
-	card->port_status &= ~(1 << port->channel);
-	outw(card->port_status, card->base + 0x02);
-}
-
-/* unthrottle et all */
-static void isicom_unthrottle(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
-		return;
-
-	/* tell the card that this port is ready to accept more data */
-	card->port_status |= (1 << port->channel);
-	outw(card->port_status, card->base + 0x02);
-}
-
-/* stop et all */
-static void isicom_stop(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
-		return;
-
-	/* this tells the transmitter not to consider this port for
-	   data output to the card. */
-	port->status &= ~ISI_TXOK;
-}
-
-/* start et all */
-static void isicom_start(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_start"))
-		return;
-
-	/* this tells the transmitter to consider this port for
-	   data output to the card. */
-	port->status |= ISI_TXOK;
-}
-
-static void isicom_hangup(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
-		return;
-	tty_port_hangup(&port->port);
-}
-
-
-/*
- * Driver init and deinit functions
- */
-
-static const struct tty_operations isicom_ops = {
-	.open			= isicom_open,
-	.close			= isicom_close,
-	.write			= isicom_write,
-	.put_char		= isicom_put_char,
-	.flush_chars		= isicom_flush_chars,
-	.write_room		= isicom_write_room,
-	.chars_in_buffer	= isicom_chars_in_buffer,
-	.ioctl			= isicom_ioctl,
-	.set_termios		= isicom_set_termios,
-	.throttle		= isicom_throttle,
-	.unthrottle		= isicom_unthrottle,
-	.stop			= isicom_stop,
-	.start			= isicom_start,
-	.hangup			= isicom_hangup,
-	.flush_buffer		= isicom_flush_buffer,
-	.tiocmget		= isicom_tiocmget,
-	.tiocmset		= isicom_tiocmset,
-	.break_ctl		= isicom_send_break,
-};
-
-static const struct tty_port_operations isicom_port_ops = {
-	.carrier_raised		= isicom_carrier_raised,
-	.dtr_rts		= isicom_dtr_rts,
-	.activate		= isicom_activate,
-	.shutdown		= isicom_shutdown,
-};
-
-static int __devinit reset_card(struct pci_dev *pdev,
-	const unsigned int card, unsigned int *signature)
-{
-	struct isi_board *board = pci_get_drvdata(pdev);
-	unsigned long base = board->base;
-	unsigned int sig, portcount = 0;
-	int retval = 0;
-
-	dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
-		base);
-
-	inw(base + 0x8);
-
-	msleep(10);
-
-	outw(0, base + 0x8); /* Reset */
-
-	msleep(1000);
-
-	sig = inw(base + 0x4) & 0xff;
-
-	if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
-			sig != 0xee) {
-		dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
-			"bad I/O Port Address 0x%lx).\n", card + 1, base);
-		dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
-		retval = -EIO;
-		goto end;
-	}
-
-	msleep(10);
-
-	portcount = inw(base + 0x2);
-	if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
-				portcount != 8 && portcount != 16)) {
-		dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
-			card + 1);
-		retval = -EIO;
-		goto end;
-	}
-
-	switch (sig) {
-	case 0xa5:
-	case 0xbb:
-	case 0xdd:
-		board->port_count = (portcount == 4) ? 4 : 8;
-		board->shift_count = 12;
-		break;
-	case 0xcc:
-	case 0xee:
-		board->port_count = 16;
-		board->shift_count = 11;
-		break;
-	}
-	dev_info(&pdev->dev, "-Done\n");
-	*signature = sig;
-
-end:
-	return retval;
-}
-
-static int __devinit load_firmware(struct pci_dev *pdev,
-	const unsigned int index, const unsigned int signature)
-{
-	struct isi_board *board = pci_get_drvdata(pdev);
-	const struct firmware *fw;
-	unsigned long base = board->base;
-	unsigned int a;
-	u16 word_count, status;
-	int retval = -EIO;
-	char *name;
-	u8 *data;
-
-	struct stframe {
-		u16	addr;
-		u16	count;
-		u8	data[0];
-	} *frame;
-
-	switch (signature) {
-	case 0xa5:
-		name = "isi608.bin";
-		break;
-	case 0xbb:
-		name = "isi608em.bin";
-		break;
-	case 0xcc:
-		name = "isi616em.bin";
-		break;
-	case 0xdd:
-		name = "isi4608.bin";
-		break;
-	case 0xee:
-		name = "isi4616.bin";
-		break;
-	default:
-		dev_err(&pdev->dev, "Unknown signature.\n");
-		goto end;
-	}
-
-	retval = request_firmware(&fw, name, &pdev->dev);
-	if (retval)
-		goto end;
-
-	retval = -EIO;
-
-	for (frame = (struct stframe *)fw->data;
-			frame < (struct stframe *)(fw->data + fw->size);
-			frame = (struct stframe *)((u8 *)(frame + 1) +
-				frame->count)) {
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		outw(0xf0, base);	/* start upload sequence */
-		outw(0x00, base);
-		outw(frame->addr, base); /* lsb of address */
-
-		word_count = frame->count / 2 + frame->count % 2;
-		outw(word_count, base);
-		InterruptTheCard(base);
-
-		udelay(100); /* 0x2f */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_warn(&pdev->dev, "Card%d rejected load header:\n"
-				 "Address:0x%x\n"
-				 "Count:0x%x\n"
-				 "Status:0x%x\n",
-				 index + 1, frame->addr, frame->count, status);
-			goto errrelfw;
-		}
-		outsw(base, frame->data, word_count);
-
-		InterruptTheCard(base);
-
-		udelay(50); /* 0x0f */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_err(&pdev->dev, "Card%d got out of sync.Card "
-				"Status:0x%x\n", index + 1, status);
-			goto errrelfw;
-		}
-	}
-
-/* XXX: should we test it by reading it back and comparing with original like
- * in load firmware package? */
-	for (frame = (struct stframe *)fw->data;
-			frame < (struct stframe *)(fw->data + fw->size);
-			frame = (struct stframe *)((u8 *)(frame + 1) +
-				frame->count)) {
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		outw(0xf1, base); /* start download sequence */
-		outw(0x00, base);
-		outw(frame->addr, base); /* lsb of address */
-
-		word_count = (frame->count >> 1) + frame->count % 2;
-		outw(word_count + 1, base);
-		InterruptTheCard(base);
-
-		udelay(50); /* 0xf */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
-				 "Address:0x%x\n"
-				 "Count:0x%x\n"
-				 "Status: 0x%x\n",
-				 index + 1, frame->addr, frame->count, status);
-			goto errrelfw;
-		}
-
-		data = kmalloc(word_count * 2, GFP_KERNEL);
-		if (data == NULL) {
-			dev_err(&pdev->dev, "Card%d, firmware upload "
-				"failed, not enough memory\n", index + 1);
-			goto errrelfw;
-		}
-		inw(base);
-		insw(base, data, word_count);
-		InterruptTheCard(base);
-
-		for (a = 0; a < frame->count; a++)
-			if (data[a] != frame->data[a]) {
-				kfree(data);
-				dev_err(&pdev->dev, "Card%d, firmware upload "
-					"failed\n", index + 1);
-				goto errrelfw;
-			}
-		kfree(data);
-
-		udelay(50); /* 0xf */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_err(&pdev->dev, "Card%d verify got out of sync. "
-				"Card Status:0x%x\n", index + 1, status);
-			goto errrelfw;
-		}
-	}
-
-	/* xfer ctrl */
-	if (WaitTillCardIsFree(base))
-		goto errrelfw;
-
-	outw(0xf2, base);
-	outw(0x800, base);
-	outw(0x0, base);
-	outw(0x0, base);
-	InterruptTheCard(base);
-	outw(0x0, base + 0x4); /* for ISI4608 cards */
-
-	board->status |= FIRMWARE_LOADED;
-	retval = 0;
-
-errrelfw:
-	release_firmware(fw);
-end:
-	return retval;
-}
-
-/*
- *	Insmod can set static symbols so keep these static
- */
-static unsigned int card_count;
-
-static int __devinit isicom_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	unsigned int uninitialized_var(signature), index;
-	int retval = -EPERM;
-	struct isi_board *board = NULL;
-
-	if (card_count >= BOARD_COUNT)
-		goto err;
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "failed to enable\n");
-		goto err;
-	}
-
-	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
-
-	/* allot the first empty slot in the array */
-	for (index = 0; index < BOARD_COUNT; index++) {
-		if (isi_card[index].base == 0) {
-			board = &isi_card[index];
-			break;
-		}
-	}
-	if (index == BOARD_COUNT) {
-		retval = -ENODEV;
-		goto err_disable;
-	}
-
-	board->index = index;
-	board->base = pci_resource_start(pdev, 3);
-	board->irq = pdev->irq;
-	card_count++;
-
-	pci_set_drvdata(pdev, board);
-
-	retval = pci_request_region(pdev, 3, ISICOM_NAME);
-	if (retval) {
-		dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
-			"will be disabled.\n", board->base, board->base + 15,
-			index + 1);
-		retval = -EBUSY;
-		goto errdec;
-	}
-
-	retval = request_irq(board->irq, isicom_interrupt,
-			IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
-	if (retval < 0) {
-		dev_err(&pdev->dev, "Could not install handler at Irq %d. "
-			"Card%d will be disabled.\n", board->irq, index + 1);
-		goto errunrr;
-	}
-
-	retval = reset_card(pdev, index, &signature);
-	if (retval < 0)
-		goto errunri;
-
-	retval = load_firmware(pdev, index, signature);
-	if (retval < 0)
-		goto errunri;
-
-	for (index = 0; index < board->port_count; index++)
-		tty_register_device(isicom_normal, board->index * 16 + index,
-				&pdev->dev);
-
-	return 0;
-
-errunri:
-	free_irq(board->irq, board);
-errunrr:
-	pci_release_region(pdev, 3);
-errdec:
-	board->base = 0;
-	card_count--;
-err_disable:
-	pci_disable_device(pdev);
-err:
-	return retval;
-}
-
-static void __devexit isicom_remove(struct pci_dev *pdev)
-{
-	struct isi_board *board = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	for (i = 0; i < board->port_count; i++)
-		tty_unregister_device(isicom_normal, board->index * 16 + i);
-
-	free_irq(board->irq, board);
-	pci_release_region(pdev, 3);
-	board->base = 0;
-	card_count--;
-	pci_disable_device(pdev);
-}
-
-static int __init isicom_init(void)
-{
-	int retval, idx, channel;
-	struct isi_port *port;
-
-	for (idx = 0; idx < BOARD_COUNT; idx++) {
-		port = &isi_ports[idx * 16];
-		isi_card[idx].ports = port;
-		spin_lock_init(&isi_card[idx].card_lock);
-		for (channel = 0; channel < 16; channel++, port++) {
-			tty_port_init(&port->port);
-			port->port.ops = &isicom_port_ops;
-			port->magic = ISICOM_MAGIC;
-			port->card = &isi_card[idx];
-			port->channel = channel;
-			port->port.close_delay = 50 * HZ/100;
-			port->port.closing_wait = 3000 * HZ/100;
-			port->status = 0;
-			/*  . . .  */
-		}
-		isi_card[idx].base = 0;
-		isi_card[idx].irq = 0;
-	}
-
-	/* tty driver structure initialization */
-	isicom_normal = alloc_tty_driver(PORT_COUNT);
-	if (!isicom_normal) {
-		retval = -ENOMEM;
-		goto error;
-	}
-
-	isicom_normal->owner			= THIS_MODULE;
-	isicom_normal->name 			= "ttyM";
-	isicom_normal->major			= ISICOM_NMAJOR;
-	isicom_normal->minor_start		= 0;
-	isicom_normal->type			= TTY_DRIVER_TYPE_SERIAL;
-	isicom_normal->subtype			= SERIAL_TYPE_NORMAL;
-	isicom_normal->init_termios		= tty_std_termios;
-	isicom_normal->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL |
-		CLOCAL;
-	isicom_normal->flags			= TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(isicom_normal, &isicom_ops);
-
-	retval = tty_register_driver(isicom_normal);
-	if (retval) {
-		pr_debug("Couldn't register the dialin driver\n");
-		goto err_puttty;
-	}
-
-	retval = pci_register_driver(&isicom_driver);
-	if (retval < 0) {
-		pr_err("Unable to register pci driver.\n");
-		goto err_unrtty;
-	}
-
-	mod_timer(&tx, jiffies + 1);
-
-	return 0;
-err_unrtty:
-	tty_unregister_driver(isicom_normal);
-err_puttty:
-	put_tty_driver(isicom_normal);
-error:
-	return retval;
-}
-
-static void __exit isicom_exit(void)
-{
-	del_timer_sync(&tx);
-
-	pci_unregister_driver(&isicom_driver);
-	tty_unregister_driver(isicom_normal);
-	put_tty_driver(isicom_normal);
-}
-
-module_init(isicom_init);
-module_exit(isicom_exit);
-
-MODULE_AUTHOR("MultiTech");
-MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("isi608.bin");
-MODULE_FIRMWARE("isi608em.bin");
-MODULE_FIRMWARE("isi616em.bin");
-MODULE_FIRMWARE("isi4608.bin");
-MODULE_FIRMWARE("isi4616.bin");
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
deleted file mode 100644
index 7c6de4c..0000000
--- a/drivers/char/istallion.c
+++ /dev/null
@@ -1,4507 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	istallion.c  -- stallion intelligent multiport serial driver.
- *
- *	Copyright (C) 1996-1999  Stallion Technologies
- *	Copyright (C) 1994-1996  Greg Ungerer.
- *
- *	This code is loosely based on the Linux serial driver, written by
- *	Linus Torvalds, Theodore T'so and others.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/seq_file.h>
-#include <linux/cdk.h>
-#include <linux/comstats.h>
-#include <linux/istallion.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/eisa.h>
-#include <linux/ctype.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/pci.h>
-
-/*****************************************************************************/
-
-/*
- *	Define different board types. Not all of the following board types
- *	are supported by this driver. But I will use the standard "assigned"
- *	board numbers. Currently supported boards are abbreviated as:
- *	ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
- *	STAL = Stallion.
- */
-#define	BRD_UNKNOWN	0
-#define	BRD_STALLION	1
-#define	BRD_BRUMBY4	2
-#define	BRD_ONBOARD2	3
-#define	BRD_ONBOARD	4
-#define	BRD_ONBOARDE	7
-#define	BRD_ECP		23
-#define BRD_ECPE	24
-#define	BRD_ECPMC	25
-#define	BRD_ECPPCI	29
-
-#define	BRD_BRUMBY	BRD_BRUMBY4
-
-/*
- *	Define a configuration structure to hold the board configuration.
- *	Need to set this up in the code (for now) with the boards that are
- *	to be configured into the system. This is what needs to be modified
- *	when adding/removing/modifying boards. Each line entry in the
- *	stli_brdconf[] array is a board. Each line contains io/irq/memory
- *	ranges for that board (as well as what type of board it is).
- *	Some examples:
- *		{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
- *	This line will configure an EasyConnection 8/64 at io address 2a0,
- *	and shared memory address of cc000. Multiple EasyConnection 8/64
- *	boards can share the same shared memory address space. No interrupt
- *	is required for this board type.
- *	Another example:
- *		{ BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 },
- *	This line will configure an EasyConnection 8/64 EISA in slot 5 and
- *	shared memory address of 0x80000000 (2 GByte). Multiple
- *	EasyConnection 8/64 EISA boards can share the same shared memory
- *	address space. No interrupt is required for this board type.
- *	Another example:
- *		{ BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 },
- *	This line will configure an ONboard (ISA type) at io address 240,
- *	and shared memory address of d0000. Multiple ONboards can share
- *	the same shared memory address space. No interrupt required.
- *	Another example:
- *		{ BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 },
- *	This line will configure a Brumby board (any number of ports!) at
- *	io address 360 and shared memory address of c8000. All Brumby boards
- *	configured into a system must have their own separate io and memory
- *	addresses. No interrupt is required.
- *	Another example:
- *		{ BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 },
- *	This line will configure an original Stallion board at io address 330
- *	and shared memory address d0000 (this would only be valid for a "V4.0"
- *	or Rev.O Stallion board). All Stallion boards configured into the
- *	system must have their own separate io and memory addresses. No
- *	interrupt is required.
- */
-
-struct stlconf {
-	int		brdtype;
-	int		ioaddr1;
-	int		ioaddr2;
-	unsigned long	memaddr;
-	int		irq;
-	int		irqtype;
-};
-
-static unsigned int stli_nrbrds;
-
-/* stli_lock must NOT be taken holding brd_lock */
-static spinlock_t stli_lock;	/* TTY logic lock */
-static spinlock_t brd_lock;	/* Board logic lock */
-
-/*
- *	There is some experimental EISA board detection code in this driver.
- *	By default it is disabled, but for those that want to try it out,
- *	then set the define below to be 1.
- */
-#define	STLI_EISAPROBE	0
-
-/*****************************************************************************/
-
-/*
- *	Define some important driver characteristics. Device major numbers
- *	allocated as per Linux Device Registry.
- */
-#ifndef	STL_SIOMEMMAJOR
-#define	STL_SIOMEMMAJOR		28
-#endif
-#ifndef	STL_SERIALMAJOR
-#define	STL_SERIALMAJOR		24
-#endif
-#ifndef	STL_CALLOUTMAJOR
-#define	STL_CALLOUTMAJOR	25
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Define our local driver identity first. Set up stuff to deal with
- *	all the local structures required by a serial tty driver.
- */
-static char	*stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
-static char	*stli_drvname = "istallion";
-static char	*stli_drvversion = "5.6.0";
-static char	*stli_serialname = "ttyE";
-
-static struct tty_driver	*stli_serial;
-static const struct tty_port_operations stli_port_ops;
-
-#define	STLI_TXBUFSIZE		4096
-
-/*
- *	Use a fast local buffer for cooked characters. Typically a whole
- *	bunch of cooked characters come in for a port, 1 at a time. So we
- *	save those up into a local buffer, then write out the whole lot
- *	with a large memcpy. Just use 1 buffer for all ports, since its
- *	use it is only need for short periods of time by each port.
- */
-static char			*stli_txcookbuf;
-static int			stli_txcooksize;
-static int			stli_txcookrealsize;
-static struct tty_struct	*stli_txcooktty;
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially. Basically all it defines is a raw port
- *	at 9600 baud, 8 data bits, no parity, 1 stop bit.
- */
-static struct ktermios		stli_deftermios = {
-	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_cc		= INIT_C_CC,
-	.c_ispeed	= 9600,
-	.c_ospeed	= 9600,
-};
-
-/*
- *	Define global stats structures. Not used often, and can be
- *	re-used for each stats call.
- */
-static comstats_t	stli_comstats;
-static combrd_t		stli_brdstats;
-static struct asystats	stli_cdkstats;
-
-/*****************************************************************************/
-
-static DEFINE_MUTEX(stli_brdslock);
-static struct stlibrd	*stli_brds[STL_MAXBRDS];
-
-static int		stli_shared;
-
-/*
- *	Per board state flags. Used with the state field of the board struct.
- *	Not really much here... All we need to do is keep track of whether
- *	the board has been detected, and whether it is actually running a slave
- *	or not.
- */
-#define	BST_FOUND	0
-#define	BST_STARTED	1
-#define	BST_PROBED	2
-
-/*
- *	Define the set of port state flags. These are marked for internal
- *	state purposes only, usually to do with the state of communications
- *	with the slave. Most of them need to be updated atomically, so always
- *	use the bit setting operations (unless protected by cli/sti).
- */
-#define	ST_OPENING	2
-#define	ST_CLOSING	3
-#define	ST_CMDING	4
-#define	ST_TXBUSY	5
-#define	ST_RXING	6
-#define	ST_DOFLUSHRX	7
-#define	ST_DOFLUSHTX	8
-#define	ST_DOSIGS	9
-#define	ST_RXSTOP	10
-#define	ST_GETSIGS	11
-
-/*
- *	Define an array of board names as printable strings. Handy for
- *	referencing boards when printing trace and stuff.
- */
-static char	*stli_brdnames[] = {
-	"Unknown",
-	"Stallion",
-	"Brumby",
-	"ONboard-MC",
-	"ONboard",
-	"Brumby",
-	"Brumby",
-	"ONboard-EI",
-	NULL,
-	"ONboard",
-	"ONboard-MC",
-	"ONboard-MC",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"EasyIO",
-	"EC8/32-AT",
-	"EC8/32-MC",
-	"EC8/64-AT",
-	"EC8/64-EI",
-	"EC8/64-MC",
-	"EC8/32-PCI",
-	"EC8/64-PCI",
-	"EasyIO-PCI",
-	"EC/RA-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *	Define some string labels for arguments passed from the module
- *	load line. These allow for easy board definitions, and easy
- *	modification of the io, memory and irq resoucres.
- */
-
-static char	*board0[8];
-static char	*board1[8];
-static char	*board2[8];
-static char	*board3[8];
-
-static char	**stli_brdsp[] = {
-	(char **) &board0,
-	(char **) &board1,
-	(char **) &board2,
-	(char **) &board3
-};
-
-/*
- *	Define a set of common board names, and types. This is used to
- *	parse any module arguments.
- */
-
-static struct stlibrdtype {
-	char	*name;
-	int	type;
-} stli_brdstr[] = {
-	{ "stallion", BRD_STALLION },
-	{ "1", BRD_STALLION },
-	{ "brumby", BRD_BRUMBY },
-	{ "brumby4", BRD_BRUMBY },
-	{ "brumby/4", BRD_BRUMBY },
-	{ "brumby-4", BRD_BRUMBY },
-	{ "brumby8", BRD_BRUMBY },
-	{ "brumby/8", BRD_BRUMBY },
-	{ "brumby-8", BRD_BRUMBY },
-	{ "brumby16", BRD_BRUMBY },
-	{ "brumby/16", BRD_BRUMBY },
-	{ "brumby-16", BRD_BRUMBY },
-	{ "2", BRD_BRUMBY },
-	{ "onboard2", BRD_ONBOARD2 },
-	{ "onboard-2", BRD_ONBOARD2 },
-	{ "onboard/2", BRD_ONBOARD2 },
-	{ "onboard-mc", BRD_ONBOARD2 },
-	{ "onboard/mc", BRD_ONBOARD2 },
-	{ "onboard-mca", BRD_ONBOARD2 },
-	{ "onboard/mca", BRD_ONBOARD2 },
-	{ "3", BRD_ONBOARD2 },
-	{ "onboard", BRD_ONBOARD },
-	{ "onboardat", BRD_ONBOARD },
-	{ "4", BRD_ONBOARD },
-	{ "onboarde", BRD_ONBOARDE },
-	{ "onboard-e", BRD_ONBOARDE },
-	{ "onboard/e", BRD_ONBOARDE },
-	{ "onboard-ei", BRD_ONBOARDE },
-	{ "onboard/ei", BRD_ONBOARDE },
-	{ "7", BRD_ONBOARDE },
-	{ "ecp", BRD_ECP },
-	{ "ecpat", BRD_ECP },
-	{ "ec8/64", BRD_ECP },
-	{ "ec8/64-at", BRD_ECP },
-	{ "ec8/64-isa", BRD_ECP },
-	{ "23", BRD_ECP },
-	{ "ecpe", BRD_ECPE },
-	{ "ecpei", BRD_ECPE },
-	{ "ec8/64-e", BRD_ECPE },
-	{ "ec8/64-ei", BRD_ECPE },
-	{ "24", BRD_ECPE },
-	{ "ecpmc", BRD_ECPMC },
-	{ "ec8/64-mc", BRD_ECPMC },
-	{ "ec8/64-mca", BRD_ECPMC },
-	{ "25", BRD_ECPMC },
-	{ "ecppci", BRD_ECPPCI },
-	{ "ec/ra", BRD_ECPPCI },
-	{ "ec/ra-pc", BRD_ECPPCI },
-	{ "ec/ra-pci", BRD_ECPPCI },
-	{ "29", BRD_ECPPCI },
-};
-
-/*
- *	Define the module agruments.
- */
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
-MODULE_LICENSE("GPL");
-
-
-module_param_array(board0, charp, NULL, 0);
-MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
-module_param_array(board1, charp, NULL, 0);
-MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
-module_param_array(board2, charp, NULL, 0);
-MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
-module_param_array(board3, charp, NULL, 0);
-MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
-
-#if STLI_EISAPROBE != 0
-/*
- *	Set up a default memory address table for EISA board probing.
- *	The default addresses are all bellow 1Mbyte, which has to be the
- *	case anyway. They should be safe, since we only read values from
- *	them, and interrupts are disabled while we do it. If the higher
- *	memory support is compiled in then we also try probing around
- *	the 1Gb, 2Gb and 3Gb areas as well...
- */
-static unsigned long	stli_eisamemprobeaddrs[] = {
-	0xc0000,    0xd0000,    0xe0000,    0xf0000,
-	0x80000000, 0x80010000, 0x80020000, 0x80030000,
-	0x40000000, 0x40010000, 0x40020000, 0x40030000,
-	0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000,
-	0xff000000, 0xff010000, 0xff020000, 0xff030000,
-};
-
-static int	stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
-#endif
-
-/*
- *	Define the Stallion PCI vendor and device IDs.
- */
-#ifndef PCI_DEVICE_ID_ECRA
-#define	PCI_DEVICE_ID_ECRA		0x0004
-#endif
-
-static struct pci_device_id istallion_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
-
-static struct pci_driver stli_pcidriver;
-
-/*****************************************************************************/
-
-/*
- *	Hardware configuration info for ECP boards. These defines apply
- *	to the directly accessible io ports of the ECP. There is a set of
- *	defines for each ECP board type, ISA, EISA, MCA and PCI.
- */
-#define	ECP_IOSIZE	4
-
-#define	ECP_MEMSIZE	(128 * 1024)
-#define	ECP_PCIMEMSIZE	(256 * 1024)
-
-#define	ECP_ATPAGESIZE	(4 * 1024)
-#define	ECP_MCPAGESIZE	(4 * 1024)
-#define	ECP_EIPAGESIZE	(64 * 1024)
-#define	ECP_PCIPAGESIZE	(64 * 1024)
-
-#define	STL_EISAID	0x8c4e
-
-/*
- *	Important defines for the ISA class of ECP board.
- */
-#define	ECP_ATIREG	0
-#define	ECP_ATCONFR	1
-#define	ECP_ATMEMAR	2
-#define	ECP_ATMEMPR	3
-#define	ECP_ATSTOP	0x1
-#define	ECP_ATINTENAB	0x10
-#define	ECP_ATENABLE	0x20
-#define	ECP_ATDISABLE	0x00
-#define	ECP_ATADDRMASK	0x3f000
-#define	ECP_ATADDRSHFT	12
-
-/*
- *	Important defines for the EISA class of ECP board.
- */
-#define	ECP_EIIREG	0
-#define	ECP_EIMEMARL	1
-#define	ECP_EICONFR	2
-#define	ECP_EIMEMARH	3
-#define	ECP_EIENABLE	0x1
-#define	ECP_EIDISABLE	0x0
-#define	ECP_EISTOP	0x4
-#define	ECP_EIEDGE	0x00
-#define	ECP_EILEVEL	0x80
-#define	ECP_EIADDRMASKL	0x00ff0000
-#define	ECP_EIADDRSHFTL	16
-#define	ECP_EIADDRMASKH	0xff000000
-#define	ECP_EIADDRSHFTH	24
-#define	ECP_EIBRDENAB	0xc84
-
-#define	ECP_EISAID	0x4
-
-/*
- *	Important defines for the Micro-channel class of ECP board.
- *	(It has a lot in common with the ISA boards.)
- */
-#define	ECP_MCIREG	0
-#define	ECP_MCCONFR	1
-#define	ECP_MCSTOP	0x20
-#define	ECP_MCENABLE	0x80
-#define	ECP_MCDISABLE	0x00
-
-/*
- *	Important defines for the PCI class of ECP board.
- *	(It has a lot in common with the other ECP boards.)
- */
-#define	ECP_PCIIREG	0
-#define	ECP_PCICONFR	1
-#define	ECP_PCISTOP	0x01
-
-/*
- *	Hardware configuration info for ONboard and Brumby boards. These
- *	defines apply to the directly accessible io ports of these boards.
- */
-#define	ONB_IOSIZE	16
-#define	ONB_MEMSIZE	(64 * 1024)
-#define	ONB_ATPAGESIZE	(64 * 1024)
-#define	ONB_MCPAGESIZE	(64 * 1024)
-#define	ONB_EIMEMSIZE	(128 * 1024)
-#define	ONB_EIPAGESIZE	(64 * 1024)
-
-/*
- *	Important defines for the ISA class of ONboard board.
- */
-#define	ONB_ATIREG	0
-#define	ONB_ATMEMAR	1
-#define	ONB_ATCONFR	2
-#define	ONB_ATSTOP	0x4
-#define	ONB_ATENABLE	0x01
-#define	ONB_ATDISABLE	0x00
-#define	ONB_ATADDRMASK	0xff0000
-#define	ONB_ATADDRSHFT	16
-
-#define	ONB_MEMENABLO	0
-#define	ONB_MEMENABHI	0x02
-
-/*
- *	Important defines for the EISA class of ONboard board.
- */
-#define	ONB_EIIREG	0
-#define	ONB_EIMEMARL	1
-#define	ONB_EICONFR	2
-#define	ONB_EIMEMARH	3
-#define	ONB_EIENABLE	0x1
-#define	ONB_EIDISABLE	0x0
-#define	ONB_EISTOP	0x4
-#define	ONB_EIEDGE	0x00
-#define	ONB_EILEVEL	0x80
-#define	ONB_EIADDRMASKL	0x00ff0000
-#define	ONB_EIADDRSHFTL	16
-#define	ONB_EIADDRMASKH	0xff000000
-#define	ONB_EIADDRSHFTH	24
-#define	ONB_EIBRDENAB	0xc84
-
-#define	ONB_EISAID	0x1
-
-/*
- *	Important defines for the Brumby boards. They are pretty simple,
- *	there is not much that is programmably configurable.
- */
-#define	BBY_IOSIZE	16
-#define	BBY_MEMSIZE	(64 * 1024)
-#define	BBY_PAGESIZE	(16 * 1024)
-
-#define	BBY_ATIREG	0
-#define	BBY_ATCONFR	1
-#define	BBY_ATSTOP	0x4
-
-/*
- *	Important defines for the Stallion boards. They are pretty simple,
- *	there is not much that is programmably configurable.
- */
-#define	STAL_IOSIZE	16
-#define	STAL_MEMSIZE	(64 * 1024)
-#define	STAL_PAGESIZE	(64 * 1024)
-
-/*
- *	Define the set of status register values for EasyConnection panels.
- *	The signature will return with the status value for each panel. From
- *	this we can determine what is attached to the board - before we have
- *	actually down loaded any code to it.
- */
-#define	ECH_PNLSTATUS	2
-#define	ECH_PNL16PORT	0x20
-#define	ECH_PNLIDMASK	0x07
-#define	ECH_PNLXPID	0x40
-#define	ECH_PNLINTRPEND	0x80
-
-/*
- *	Define some macros to do things to the board. Even those these boards
- *	are somewhat related there is often significantly different ways of
- *	doing some operation on it (like enable, paging, reset, etc). So each
- *	board class has a set of functions which do the commonly required
- *	operations. The macros below basically just call these functions,
- *	generally checking for a NULL function - which means that the board
- *	needs nothing done to it to achieve this operation!
- */
-#define	EBRDINIT(brdp)						\
-	if (brdp->init != NULL)					\
-		(* brdp->init)(brdp)
-
-#define	EBRDENABLE(brdp)					\
-	if (brdp->enable != NULL)				\
-		(* brdp->enable)(brdp);
-
-#define	EBRDDISABLE(brdp)					\
-	if (brdp->disable != NULL)				\
-		(* brdp->disable)(brdp);
-
-#define	EBRDINTR(brdp)						\
-	if (brdp->intr != NULL)					\
-		(* brdp->intr)(brdp);
-
-#define	EBRDRESET(brdp)						\
-	if (brdp->reset != NULL)				\
-		(* brdp->reset)(brdp);
-
-#define	EBRDGETMEMPTR(brdp,offset)				\
-	(* brdp->getmemptr)(brdp, offset, __LINE__)
-
-/*
- *	Define the maximal baud rate, and the default baud base for ports.
- */
-#define	STL_MAXBAUD	460800
-#define	STL_BAUDBASE	115200
-#define	STL_CLOSEDELAY	(5 * HZ / 10)
-
-/*****************************************************************************/
-
-/*
- *	Define macros to extract a brd or port number from a minor number.
- */
-#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
-#define	MINOR2PORT(min)		((min) & 0x3f)
-
-/*****************************************************************************/
-
-/*
- *	Prototype all functions in this driver!
- */
-
-static int	stli_parsebrd(struct stlconf *confp, char **argp);
-static int	stli_open(struct tty_struct *tty, struct file *filp);
-static void	stli_close(struct tty_struct *tty, struct file *filp);
-static int	stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int	stli_putchar(struct tty_struct *tty, unsigned char ch);
-static void	stli_flushchars(struct tty_struct *tty);
-static int	stli_writeroom(struct tty_struct *tty);
-static int	stli_charsinbuffer(struct tty_struct *tty);
-static int	stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void	stli_settermios(struct tty_struct *tty, struct ktermios *old);
-static void	stli_throttle(struct tty_struct *tty);
-static void	stli_unthrottle(struct tty_struct *tty);
-static void	stli_stop(struct tty_struct *tty);
-static void	stli_start(struct tty_struct *tty);
-static void	stli_flushbuffer(struct tty_struct *tty);
-static int	stli_breakctl(struct tty_struct *tty, int state);
-static void	stli_waituntilsent(struct tty_struct *tty, int timeout);
-static void	stli_sendxchar(struct tty_struct *tty, char ch);
-static void	stli_hangup(struct tty_struct *tty);
-
-static int	stli_brdinit(struct stlibrd *brdp);
-static int	stli_startbrd(struct stlibrd *brdp);
-static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
-static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
-static long	stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-static void	stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
-static void	stli_poll(unsigned long arg);
-static int	stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
-static int	stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
-static int	stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int	stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int	stli_setport(struct tty_struct *tty);
-static int	stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	__stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
-static void	stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
-static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
-static long	stli_mktiocm(unsigned long sigvalue);
-static void	stli_read(struct stlibrd *brdp, struct stliport *portp);
-static int	stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
-static int	stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
-static int	stli_getbrdstats(combrd_t __user *bp);
-static int	stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
-static int	stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
-static int	stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
-static int	stli_getportstruct(struct stliport __user *arg);
-static int	stli_getbrdstruct(struct stlibrd __user *arg);
-static struct stlibrd *stli_allocbrd(void);
-
-static void	stli_ecpinit(struct stlibrd *brdp);
-static void	stli_ecpenable(struct stlibrd *brdp);
-static void	stli_ecpdisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpreset(struct stlibrd *brdp);
-static void	stli_ecpintr(struct stlibrd *brdp);
-static void	stli_ecpeiinit(struct stlibrd *brdp);
-static void	stli_ecpeienable(struct stlibrd *brdp);
-static void	stli_ecpeidisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpeireset(struct stlibrd *brdp);
-static void	stli_ecpmcenable(struct stlibrd *brdp);
-static void	stli_ecpmcdisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpmcreset(struct stlibrd *brdp);
-static void	stli_ecppciinit(struct stlibrd *brdp);
-static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecppcireset(struct stlibrd *brdp);
-
-static void	stli_onbinit(struct stlibrd *brdp);
-static void	stli_onbenable(struct stlibrd *brdp);
-static void	stli_onbdisable(struct stlibrd *brdp);
-static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_onbreset(struct stlibrd *brdp);
-static void	stli_onbeinit(struct stlibrd *brdp);
-static void	stli_onbeenable(struct stlibrd *brdp);
-static void	stli_onbedisable(struct stlibrd *brdp);
-static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_onbereset(struct stlibrd *brdp);
-static void	stli_bbyinit(struct stlibrd *brdp);
-static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_bbyreset(struct stlibrd *brdp);
-static void	stli_stalinit(struct stlibrd *brdp);
-static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_stalreset(struct stlibrd *brdp);
-
-static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
-
-static int	stli_initecp(struct stlibrd *brdp);
-static int	stli_initonb(struct stlibrd *brdp);
-#if STLI_EISAPROBE != 0
-static int	stli_eisamemprobe(struct stlibrd *brdp);
-#endif
-static int	stli_initports(struct stlibrd *brdp);
-
-/*****************************************************************************/
-
-/*
- *	Define the driver info for a user level shared memory device. This
- *	device will work sort of like the /dev/kmem device - except that it
- *	will give access to the shared memory on the Stallion intelligent
- *	board. This is also a very useful debugging tool.
- */
-static const struct file_operations	stli_fsiomem = {
-	.owner		= THIS_MODULE,
-	.read		= stli_memread,
-	.write		= stli_memwrite,
-	.unlocked_ioctl	= stli_memioctl,
-	.llseek		= default_llseek,
-};
-
-/*****************************************************************************/
-
-/*
- *	Define a timer_list entry for our poll routine. The slave board
- *	is polled every so often to see if anything needs doing. This is
- *	much cheaper on host cpu than using interrupts. It turns out to
- *	not increase character latency by much either...
- */
-static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
-
-static int	stli_timeron;
-
-/*
- *	Define the calculation for the timeout routine.
- */
-#define	STLI_TIMEOUT	(jiffies + 1)
-
-/*****************************************************************************/
-
-static struct class *istallion_class;
-
-static void stli_cleanup_ports(struct stlibrd *brdp)
-{
-	struct stliport *portp;
-	unsigned int j;
-	struct tty_struct *tty;
-
-	for (j = 0; j < STL_MAXPORTS; j++) {
-		portp = brdp->ports[j];
-		if (portp != NULL) {
-			tty = tty_port_tty_get(&portp->port);
-			if (tty != NULL) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-			kfree(portp);
-		}
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Parse the supplied argument string, into the board conf struct.
- */
-
-static int stli_parsebrd(struct stlconf *confp, char **argp)
-{
-	unsigned int i;
-	char *sp;
-
-	if (argp[0] == NULL || *argp[0] == 0)
-		return 0;
-
-	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
-		*sp = tolower(*sp);
-
-	for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
-		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
-			break;
-	}
-	if (i == ARRAY_SIZE(stli_brdstr)) {
-		printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]);
-		return 0;
-	}
-
-	confp->brdtype = stli_brdstr[i].type;
-	if (argp[1] != NULL && *argp[1] != 0)
-		confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
-	if (argp[2] !=  NULL && *argp[2] != 0)
-		confp->memaddr = simple_strtoul(argp[2], NULL, 0);
-	return(1);
-}
-
-/*****************************************************************************/
-
-/*
- *	On the first open of the device setup the port hardware, and
- *	initialize the per port data structure. Since initializing the port
- *	requires several commands to the board we will need to wait for any
- *	other open that is already initializing the port.
- *
- *	Locking: protected by the port mutex.
- */
-
-static int stli_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	struct stlibrd *brdp = stli_brds[portp->brdnr];
-	int rc;
-
-	if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-	wake_up_interruptible(&portp->raw_wait);
-	return rc;
-}
-
-static int stli_open(struct tty_struct *tty, struct file *filp)
-{
-	struct stlibrd *brdp;
-	struct stliport *portp;
-	unsigned int minordev, brdnr, portnr;
-
-	minordev = tty->index;
-	brdnr = MINOR2BRD(minordev);
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (!test_bit(BST_STARTED, &brdp->state))
-		return -ENODEV;
-	portnr = MINOR2PORT(minordev);
-	if (portnr > brdp->nrports)
-		return -ENODEV;
-
-	portp = brdp->ports[portnr];
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->devnr < 1)
-		return -ENODEV;
-
-	tty->driver_data = portp;
-	return tty_port_open(&portp->port, tty, filp);
-}
-
-
-/*****************************************************************************/
-
-static void stli_shutdown(struct tty_port *port)
-{
-	struct stlibrd *brdp;
-	unsigned long ftype;
-	unsigned long flags;
-	struct stliport *portp = container_of(port, struct stliport, port);
-
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	/*
-	 *	May want to wait for data to drain before closing. The BUSY
-	 *	flag keeps track of whether we are still transmitting or not.
-	 *	It is updated by messages from the slave - indicating when all
-	 *	chars really have drained.
-	 */
-
-	if (!test_bit(ST_CLOSING, &portp->state))
-		stli_rawclose(brdp, portp, 0, 0);
-
- 	spin_lock_irqsave(&stli_lock, flags);
-	clear_bit(ST_TXBUSY, &portp->state);
-	clear_bit(ST_RXSTOP, &portp->state);
-	spin_unlock_irqrestore(&stli_lock, flags);
-
-	ftype = FLUSHTX | FLUSHRX;
-	stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
-}
-
-static void stli_close(struct tty_struct *tty, struct file *filp)
-{
-	struct stliport *portp = tty->driver_data;
-	unsigned long flags;
-	if (portp == NULL)
-		return;
- 	spin_lock_irqsave(&stli_lock, flags);
-	/*	Flush any internal buffering out first */
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	spin_unlock_irqrestore(&stli_lock, flags);
-	tty_port_close(&portp->port, tty, filp);
-}
-
-/*****************************************************************************/
-
-/*
- *	Carry out first open operations on a port. This involves a number of
- *	commands to be sent to the slave. We need to open the port, set the
- *	notification events, set the initial port settings, get and set the
- *	initial signal values. We sleep and wait in between each one. But
- *	this still all happens pretty quickly.
- */
-
-static int stli_initopen(struct tty_struct *tty,
-				struct stlibrd *brdp, struct stliport *portp)
-{
-	asynotify_t nt;
-	asyport_t aport;
-	int rc;
-
-	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
-		return rc;
-
-	memset(&nt, 0, sizeof(asynotify_t));
-	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
-	nt.signal = SG_DCD;
-	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
-	    sizeof(asynotify_t), 0)) < 0)
-		return rc;
-
-	stli_mkasyport(tty, portp, &aport, tty->termios);
-	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
-	    sizeof(asyport_t), 0)) < 0)
-		return rc;
-
-	set_bit(ST_GETSIGS, &portp->state);
-	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
-	    sizeof(asysigs_t), 1)) < 0)
-		return rc;
-	if (test_and_clear_bit(ST_GETSIGS, &portp->state))
-		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
-	stli_mkasysigs(&portp->asig, 1, 1);
-	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-	    sizeof(asysigs_t), 0)) < 0)
-		return rc;
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send an open message to the slave. This will sleep waiting for the
- *	acknowledgement, so must have user context. We need to co-ordinate
- *	with close events here, since we don't want open and close events
- *	to overlap.
- */
-
-static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-	unsigned long flags;
-	int rc;
-
-/*
- *	Send a message to the slave to open this port.
- */
-
-/*
- *	Slave is already closing this port. This can happen if a hangup
- *	occurs on this port. So we must wait until it is complete. The
- *	order of opens and closes may not be preserved across shared
- *	memory, so we must wait until it is complete.
- */
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_CLOSING, &portp->state));
-	if (signal_pending(current)) {
-		return -ERESTARTSYS;
-	}
-
-/*
- *	Everything is ready now, so write the open message into shared
- *	memory. Once the message is in set the service bits to say that
- *	this port wants service.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	writel(arg, &cp->openarg);
-	writeb(1, &cp->open);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	EBRDDISABLE(brdp);
-
-	if (wait == 0) {
-		spin_unlock_irqrestore(&brd_lock, flags);
-		return 0;
-	}
-
-/*
- *	Slave is in action, so now we must wait for the open acknowledgment
- *	to come back.
- */
-	rc = 0;
-	set_bit(ST_OPENING, &portp->state);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_OPENING, &portp->state));
-	if (signal_pending(current))
-		rc = -ERESTARTSYS;
-
-	if ((rc == 0) && (portp->rc != 0))
-		rc = -EIO;
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a close message to the slave. Normally this will sleep waiting
- *	for the acknowledgement, but if wait parameter is 0 it will not. If
- *	wait is true then must have user context (to sleep).
- */
-
-static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-	unsigned long flags;
-	int rc;
-
-/*
- *	Slave is already closing this port. This can happen if a hangup
- *	occurs on this port.
- */
-	if (wait) {
-		wait_event_interruptible_tty(portp->raw_wait,
-				!test_bit(ST_CLOSING, &portp->state));
-		if (signal_pending(current)) {
-			return -ERESTARTSYS;
-		}
-	}
-
-/*
- *	Write the close command into shared memory.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	writel(arg, &cp->closearg);
-	writeb(1, &cp->close);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) |portp->portbit, bits);
-	EBRDDISABLE(brdp);
-
-	set_bit(ST_CLOSING, &portp->state);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (wait == 0)
-		return 0;
-
-/*
- *	Slave is in action, so now we must wait for the open acknowledgment
- *	to come back.
- */
-	rc = 0;
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_CLOSING, &portp->state));
-	if (signal_pending(current))
-		rc = -ERESTARTSYS;
-
-	if ((rc == 0) && (portp->rc != 0))
-		rc = -EIO;
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a command to the slave and wait for the response. This must
- *	have user context (it sleeps). This routine is generic in that it
- *	can send any type of command. Its purpose is to wait for that command
- *	to complete (as opposed to initiating the command then returning).
- */
-
-static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	/*
-	 * no need for wait_event_tty because clearing ST_CMDING cannot block
-	 * on BTM
-	 */
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	if (portp->rc != 0)
-		return -EIO;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send the termios settings for this port to the slave. This sleeps
- *	waiting for the command to complete - so must have user context.
- */
-
-static int stli_setport(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	asyport_t aport;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	stli_mkasyport(tty, portp, &aport, tty->termios);
-	return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
-}
-
-/*****************************************************************************/
-
-static int stli_carrier_raised(struct tty_port *port)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	return (portp->sigs & TIOCM_CD) ? 1 : 0;
-}
-
-static void stli_dtr_rts(struct tty_port *port, int on)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	struct stlibrd *brdp = stli_brds[portp->brdnr];
-	stli_mkasysigs(&portp->asig, on, on);
-	if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-		sizeof(asysigs_t), 0) < 0)
-			printk(KERN_WARNING "istallion: dtr set failed.\n");
-}
-
-
-/*****************************************************************************/
-
-/*
- *	Write routine. Take the data and put it in the shared memory ring
- *	queue. If port is not already sending chars then need to mark the
- *	service bits for this port.
- */
-
-static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	cdkasy_t __iomem *ap;
-	cdkhdr_t __iomem *hdrp;
-	unsigned char __iomem *bits;
-	unsigned char __iomem *shbuf;
-	unsigned char *chbuf;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int len, stlen, head, tail, size;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	chbuf = (unsigned char *) buf;
-
-/*
- *	All data is now local, shove as much as possible into shared memory.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) readw(&ap->txq.head);
-	tail = (unsigned int) readw(&ap->txq.tail);
-	if (tail != ((unsigned int) readw(&ap->txq.tail)))
-		tail = (unsigned int) readw(&ap->txq.tail);
-	size = portp->txsize;
-	if (head >= tail) {
-		len = size - (head - tail) - 1;
-		stlen = size - head;
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, (unsigned int)count);
-	count = 0;
-	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
-
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy_toio(shbuf + head, chbuf, stlen);
-		chbuf += stlen;
-		len -= stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= size) {
-			head = 0;
-			stlen = tail;
-		}
-	}
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	writew(head, &ap->txq.head);
-	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (readl(&ap->changed.data) & DT_TXEMPTY)
-			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
-	}
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_TXBUSY, &portp->state);
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return(count);
-}
-
-/*****************************************************************************/
-
-/*
- *	Output a single character. We put it into a temporary local buffer
- *	(for speed) then write out that buffer when the flushchars routine
- *	is called. There is a safety catch here so that if some other port
- *	writes chars before the current buffer has been, then we write them
- *	first them do the new ports.
- */
-
-static int stli_putchar(struct tty_struct *tty, unsigned char ch)
-{
-	if (tty != stli_txcooktty) {
-		if (stli_txcooktty != NULL)
-			stli_flushchars(stli_txcooktty);
-		stli_txcooktty = tty;
-	}
-
-	stli_txcookbuf[stli_txcooksize++] = ch;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Transfer characters from the local TX cooking buffer to the board.
- *	We sort of ignore the tty that gets passed in here. We rely on the
- *	info stored with the TX cook buffer to tell us which port to flush
- *	the data on. In any case we clean out the TX cook buffer, for re-use
- *	by someone else.
- */
-
-static void stli_flushchars(struct tty_struct *tty)
-{
-	cdkhdr_t __iomem *hdrp;
-	unsigned char __iomem *bits;
-	cdkasy_t __iomem *ap;
-	struct tty_struct *cooktty;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int len, stlen, head, tail, size, count, cooksize;
-	unsigned char *buf;
-	unsigned char __iomem *shbuf;
-	unsigned long flags;
-
-	cooksize = stli_txcooksize;
-	cooktty = stli_txcooktty;
-	stli_txcooksize = 0;
-	stli_txcookrealsize = 0;
-	stli_txcooktty = NULL;
-
-	if (cooktty == NULL)
-		return;
-	if (tty != cooktty)
-		tty = cooktty;
-	if (cooksize == 0)
-		return;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) readw(&ap->txq.head);
-	tail = (unsigned int) readw(&ap->txq.tail);
-	if (tail != ((unsigned int) readw(&ap->txq.tail)))
-		tail = (unsigned int) readw(&ap->txq.tail);
-	size = portp->txsize;
-	if (head >= tail) {
-		len = size - (head - tail) - 1;
-		stlen = size - head;
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, cooksize);
-	count = 0;
-	shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
-	buf = stli_txcookbuf;
-
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy_toio(shbuf + head, buf, stlen);
-		buf += stlen;
-		len -= stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= size) {
-			head = 0;
-			stlen = tail;
-		}
-	}
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	writew(head, &ap->txq.head);
-
-	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (readl(&ap->changed.data) & DT_TXEMPTY)
-			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
-	}
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_TXBUSY, &portp->state);
-
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static int stli_writeroom(struct tty_struct *tty)
-{
-	cdkasyrq_t __iomem *rp;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int head, tail, len;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty) {
-		if (stli_txcookrealsize != 0) {
-			len = stli_txcookrealsize - stli_txcooksize;
-			return len;
-		}
-	}
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	if (tail != ((unsigned int) readw(&rp->tail)))
-		tail = (unsigned int) readw(&rp->tail);
-	len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head);
-	len--;
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (tty == stli_txcooktty) {
-		stli_txcookrealsize = len;
-		len -= stli_txcooksize;
-	}
-	return len;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the number of characters in the transmit buffer. Normally we
- *	will return the number of chars in the shared memory ring queue.
- *	We need to kludge around the case where the shared memory buffer is
- *	empty but not all characters have drained yet, for this case just
- *	return that there is 1 character in the buffer!
- */
-
-static int stli_charsinbuffer(struct tty_struct *tty)
-{
-	cdkasyrq_t __iomem *rp;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int head, tail, len;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	if (tail != ((unsigned int) readw(&rp->tail)))
-		tail = (unsigned int) readw(&rp->tail);
-	len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head));
-	if ((len == 0) && test_bit(ST_TXBUSY, &portp->state))
-		len = 1;
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return len;
-}
-
-/*****************************************************************************/
-
-/*
- *	Generate the serial struct info.
- */
-
-static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-	struct stlibrd *brdp;
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-	sio.type = PORT_UNKNOWN;
-	sio.line = portp->portnr;
-	sio.irq = 0;
-	sio.flags = portp->port.flags;
-	sio.baud_base = portp->baud_base;
-	sio.close_delay = portp->port.close_delay;
-	sio.closing_wait = portp->closing_wait;
-	sio.custom_divisor = portp->custom_divisor;
-	sio.xmit_fifo_size = 0;
-	sio.hub6 = 0;
-
-	brdp = stli_brds[portp->brdnr];
-	if (brdp != NULL)
-		sio.port = brdp->iobase;
-		
-	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ?
-			-EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Set port according to the serial struct info.
- *	At this point we do not do any auto-configure stuff, so we will
- *	just quietly ignore any requests to change irq, etc.
- */
-
-static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-	int rc;
-	struct stliport *portp = tty->driver_data;
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return -EFAULT;
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != portp->baud_base) ||
-		    (sio.close_delay != portp->port.close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		    (portp->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-	} 
-
-	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-	portp->baud_base = sio.baud_base;
-	portp->port.close_delay = sio.close_delay;
-	portp->closing_wait = sio.closing_wait;
-	portp->custom_divisor = sio.custom_divisor;
-
-	if ((rc = stli_setport(tty)) < 0)
-		return rc;
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int stli_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	int rc;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
-			       &portp->asig, sizeof(asysigs_t), 1)) < 0)
-		return rc;
-
-	return stli_mktiocm(portp->asig.sigvalue);
-}
-
-static int stli_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	int rts = -1, dtr = -1;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	stli_mkasysigs(&portp->asig, dtr, rts);
-
-	return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-			    sizeof(asysigs_t), 0);
-}
-
-static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	int rc;
-	void __user *argp = (void __user *)arg;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
-	}
-
-	rc = 0;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = stli_getserial(portp, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = stli_setserial(tty, argp);
-		break;
-	case STL_GETPFLAG:
-		rc = put_user(portp->pflag, (unsigned __user *)argp);
-		break;
-	case STL_SETPFLAG:
-		if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
-			stli_setport(tty);
-		break;
-	case COM_GETPORTSTATS:
-		rc = stli_getportstats(tty, portp, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stli_clrportstats(portp, argp);
-		break;
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERSWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	This routine assumes that we have user context and can sleep.
- *	Looks like it is true for the current ttys implementation..!!
- */
-
-static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	struct ktermios *tiosp;
-	asyport_t aport;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	tiosp = tty->termios;
-
-	stli_mkasyport(tty, portp, &aport, tiosp);
-	stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
-	stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
-	stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-		sizeof(asysigs_t), 0);
-	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0))
-		tty->hw_stopped = 0;
-	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
-		wake_up_interruptible(&portp->port.open_wait);
-}
-
-/*****************************************************************************/
-
-/*
- *	Attempt to flow control who ever is sending us data. We won't really
- *	do any flow control action here. We can't directly, and even if we
- *	wanted to we would have to send a command to the slave. The slave
- *	knows how to flow control, and will do so when its buffers reach its
- *	internal high water marks. So what we will do is set a local state
- *	bit that will stop us sending any RX data up from the poll routine
- *	(which is the place where RX data from the slave is handled).
- */
-
-static void stli_throttle(struct tty_struct *tty)
-{
-	struct stliport	*portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	set_bit(ST_RXSTOP, &portp->state);
-}
-
-/*****************************************************************************/
-
-/*
- *	Unflow control the device sending us data... That means that all
- *	we have to do is clear the RXSTOP state bit. The next poll call
- *	will then be able to pass the RX data back up.
- */
-
-static void stli_unthrottle(struct tty_struct *tty)
-{
-	struct stliport	*portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	clear_bit(ST_RXSTOP, &portp->state);
-}
-
-/*****************************************************************************/
-
-/*
- *	Stop the transmitter.
- */
-
-static void stli_stop(struct tty_struct *tty)
-{
-}
-
-/*****************************************************************************/
-
-/*
- *	Start the transmitter again.
- */
-
-static void stli_start(struct tty_struct *tty)
-{
-}
-
-/*****************************************************************************/
-
-
-/*
- *	Hangup this port. This is pretty much like closing the port, only
- *	a little more brutal. No waiting for data to drain. Shutdown the
- *	port and maybe drop signals. This is rather tricky really. We want
- *	to close the port as well.
- */
-
-static void stli_hangup(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	tty_port_hangup(&portp->port);
-}
-
-/*****************************************************************************/
-
-/*
- *	Flush characters from the lower buffer. We may not have user context
- *	so we cannot sleep waiting for it to complete. Also we need to check
- *	if there is chars for this port in the TX cook buffer, and flush them
- *	as well.
- */
-
-static void stli_flushbuffer(struct tty_struct *tty)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned long ftype, flags;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	if (tty == stli_txcooktty) {
-		stli_txcooktty = NULL;
-		stli_txcooksize = 0;
-		stli_txcookrealsize = 0;
-	}
-	if (test_bit(ST_CMDING, &portp->state)) {
-		set_bit(ST_DOFLUSHTX, &portp->state);
-	} else {
-		ftype = FLUSHTX;
-		if (test_bit(ST_DOFLUSHRX, &portp->state)) {
-			ftype |= FLUSHRX;
-			clear_bit(ST_DOFLUSHRX, &portp->state);
-		}
-		__stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
-	}
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
-static int stli_breakctl(struct tty_struct *tty, int state)
-{
-	struct stlibrd	*brdp;
-	struct stliport	*portp;
-	long		arg;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-	if (portp->brdnr >= stli_nrbrds)
-		return -EINVAL;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -EINVAL;
-
-	arg = (state == -1) ? BREAKON : BREAKOFF;
-	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void stli_waituntilsent(struct tty_struct *tty, int timeout)
-{
-	struct stliport *portp;
-	unsigned long tend;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (timeout == 0)
-		timeout = HZ;
-	tend = jiffies + timeout;
-
-	while (test_bit(ST_TXBUSY, &portp->state)) {
-		if (signal_pending(current))
-			break;
-		msleep_interruptible(20);
-		if (time_after_eq(jiffies, tend))
-			break;
-	}
-}
-
-/*****************************************************************************/
-
-static void stli_sendxchar(struct tty_struct *tty, char ch)
-{
-	struct stlibrd	*brdp;
-	struct stliport	*portp;
-	asyctrl_t	actrl;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	memset(&actrl, 0, sizeof(asyctrl_t));
-	if (ch == STOP_CHAR(tty)) {
-		actrl.rxctrl = CT_STOPFLOW;
-	} else if (ch == START_CHAR(tty)) {
-		actrl.rxctrl = CT_STARTFLOW;
-	} else {
-		actrl.txctrl = CT_SENDCHR;
-		actrl.tximdch = ch;
-	}
-	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
-}
-
-static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr)
-{
-	char *uart;
-	int rc;
-
-	rc = stli_portcmdstats(NULL, portp);
-
-	uart = "UNKNOWN";
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		switch (stli_comstats.hwid) {
-		case 0:	uart = "2681"; break;
-		case 1:	uart = "SC26198"; break;
-		default:uart = "CD1400"; break;
-		}
-	}
-	seq_printf(m, "%d: uart:%s ", portnr, uart);
-
-	if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) {
-		char sep;
-
-		seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
-			(int) stli_comstats.rxtotal);
-
-		if (stli_comstats.rxframing)
-			seq_printf(m, " fe:%d",
-				(int) stli_comstats.rxframing);
-		if (stli_comstats.rxparity)
-			seq_printf(m, " pe:%d",
-				(int) stli_comstats.rxparity);
-		if (stli_comstats.rxbreaks)
-			seq_printf(m, " brk:%d",
-				(int) stli_comstats.rxbreaks);
-		if (stli_comstats.rxoverrun)
-			seq_printf(m, " oe:%d",
-				(int) stli_comstats.rxoverrun);
-
-		sep = ' ';
-		if (stli_comstats.signals & TIOCM_RTS) {
-			seq_printf(m, "%c%s", sep, "RTS");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_CTS) {
-			seq_printf(m, "%c%s", sep, "CTS");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_DTR) {
-			seq_printf(m, "%c%s", sep, "DTR");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_CD) {
-			seq_printf(m, "%c%s", sep, "DCD");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_DSR) {
-			seq_printf(m, "%c%s", sep, "DSR");
-			sep = '|';
-		}
-	}
-	seq_putc(m, '\n');
-}
-
-/*****************************************************************************/
-
-/*
- *	Port info, read from the /proc file system.
- */
-
-static int stli_proc_show(struct seq_file *m, void *v)
-{
-	struct stlibrd *brdp;
-	struct stliport *portp;
-	unsigned int brdnr, portnr, totalport;
-
-	totalport = 0;
-
-	seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion);
-
-/*
- *	We scan through for each board, panel and port. The offset is
- *	calculated on the fly, and irrelevant ports are skipped.
- */
-	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
-		brdp = stli_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-
-		totalport = brdnr * STL_MAXPORTS;
-		for (portnr = 0; (portnr < brdp->nrports); portnr++,
-		    totalport++) {
-			portp = brdp->ports[portnr];
-			if (portp == NULL)
-				continue;
-			stli_portinfo(m, brdp, portp, totalport);
-		}
-	}
-	return 0;
-}
-
-static int stli_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, stli_proc_show, NULL);
-}
-
-static const struct file_operations stli_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= stli_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*****************************************************************************/
-
-/*
- *	Generic send command routine. This will send a message to the slave,
- *	of the specified type with the specified argument. Must be very
- *	careful of data that will be copied out from shared memory -
- *	containing command results. The command completion is all done from
- *	a poll routine that does not have user context. Therefore you cannot
- *	copy back directly into user space, or to the kernel stack of a
- *	process. This routine does not sleep, so can be called from anywhere.
- *
- *	The caller must hold the brd_lock (see also stli_sendcmd the usual
- *	entry point)
- */
-
-static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-
-	if (test_bit(ST_CMDING, &portp->state)) {
-		printk(KERN_ERR "istallion: command already busy, cmd=%x!\n",
-				(int) cmd);
-		return;
-	}
-
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	if (size > 0) {
-		memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);
-		if (copyback) {
-			portp->argp = arg;
-			portp->argsize = size;
-		}
-	}
-	writel(0, &cp->status);
-	writel(cmd, &cp->cmd);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_CMDING, &portp->state);
-	EBRDDISABLE(brdp);
-}
-
-static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	unsigned long		flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	__stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Read data from shared memory. This assumes that the shared memory
- *	is enabled and that interrupts are off. Basically we just empty out
- *	the shared memory buffer into the tty buffer. Must be careful to
- *	handle the case where we fill up the tty buffer, but still have
- *	more chars to unload.
- */
-
-static void stli_read(struct stlibrd *brdp, struct stliport *portp)
-{
-	cdkasyrq_t __iomem *rp;
-	char __iomem *shbuf;
-	struct tty_struct	*tty;
-	unsigned int head, tail, size;
-	unsigned int len, stlen;
-
-	if (test_bit(ST_RXSTOP, &portp->state))
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	head = (unsigned int) readw(&rp->head);
-	if (head != ((unsigned int) readw(&rp->head)))
-		head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	size = portp->rxsize;
-	if (head >= tail) {
-		len = head - tail;
-		stlen = len;
-	} else {
-		len = size - (tail - head);
-		stlen = size - tail;
-	}
-
-	len = tty_buffer_request_room(tty, len);
-
-	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);
-
-	while (len > 0) {
-		unsigned char *cptr;
-
-		stlen = min(len, stlen);
-		tty_prepare_flip_string(tty, &cptr, stlen);
-		memcpy_fromio(cptr, shbuf + tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= size) {
-			tail = 0;
-			stlen = head;
-		}
-	}
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	writew(tail, &rp->tail);
-
-	if (head != tail)
-		set_bit(ST_RXING, &portp->state);
-
-	tty_schedule_flip(tty);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up and carry out any delayed commands. There is only a small set
- *	of slave commands that can be done "off-level". So it is not too
- *	difficult to deal with them here.
- */
-
-static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
-{
-	int cmd;
-
-	if (test_bit(ST_DOSIGS, &portp->state)) {
-		if (test_bit(ST_DOFLUSHTX, &portp->state) &&
-		    test_bit(ST_DOFLUSHRX, &portp->state))
-			cmd = A_SETSIGNALSF;
-		else if (test_bit(ST_DOFLUSHTX, &portp->state))
-			cmd = A_SETSIGNALSFTX;
-		else if (test_bit(ST_DOFLUSHRX, &portp->state))
-			cmd = A_SETSIGNALSFRX;
-		else
-			cmd = A_SETSIGNALS;
-		clear_bit(ST_DOFLUSHTX, &portp->state);
-		clear_bit(ST_DOFLUSHRX, &portp->state);
-		clear_bit(ST_DOSIGS, &portp->state);
-		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,
-			sizeof(asysigs_t));
-		writel(0, &cp->status);
-		writel(cmd, &cp->cmd);
-		set_bit(ST_CMDING, &portp->state);
-	} else if (test_bit(ST_DOFLUSHTX, &portp->state) ||
-	    test_bit(ST_DOFLUSHRX, &portp->state)) {
-		cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0);
-		cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);
-		clear_bit(ST_DOFLUSHTX, &portp->state);
-		clear_bit(ST_DOFLUSHRX, &portp->state);
-		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int));
-		writel(0, &cp->status);
-		writel(A_FLUSH, &cp->cmd);
-		set_bit(ST_CMDING, &portp->state);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Host command service checking. This handles commands or messages
- *	coming from the slave to the host. Must have board shared memory
- *	enabled and interrupts off when called. Notice that by servicing the
- *	read data last we don't need to change the shared memory pointer
- *	during processing (which is a slow IO operation).
- *	Return value indicates if this port is still awaiting actions from
- *	the slave (like open, command, or even TX data being sent). If 0
- *	then port is still busy, otherwise no longer busy.
- */
-
-static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
-{
-	cdkasy_t __iomem *ap;
-	cdkctrl_t __iomem *cp;
-	struct tty_struct *tty;
-	asynotify_t nt;
-	unsigned long oldsigs;
-	int rc, donerx;
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	cp = &ap->ctrl;
-
-/*
- *	Check if we are waiting for an open completion message.
- */
-	if (test_bit(ST_OPENING, &portp->state)) {
-		rc = readl(&cp->openarg);
-		if (readb(&cp->open) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			writel(0, &cp->openarg);
-			portp->rc = rc;
-			clear_bit(ST_OPENING, &portp->state);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check if we are waiting for a close completion message.
- */
-	if (test_bit(ST_CLOSING, &portp->state)) {
-		rc = (int) readl(&cp->closearg);
-		if (readb(&cp->close) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			writel(0, &cp->closearg);
-			portp->rc = rc;
-			clear_bit(ST_CLOSING, &portp->state);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check if we are waiting for a command completion message. We may
- *	need to copy out the command results associated with this command.
- */
-	if (test_bit(ST_CMDING, &portp->state)) {
-		rc = readl(&cp->status);
-		if (readl(&cp->cmd) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			if (portp->argp != NULL) {
-				memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]),
-					portp->argsize);
-				portp->argp = NULL;
-			}
-			writel(0, &cp->status);
-			portp->rc = rc;
-			clear_bit(ST_CMDING, &portp->state);
-			stli_dodelaycmd(portp, cp);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check for any notification messages ready. This includes lots of
- *	different types of events - RX chars ready, RX break received,
- *	TX data low or empty in the slave, modem signals changed state.
- */
-	donerx = 0;
-
-	if (ap->notify) {
-		nt = ap->changed;
-		ap->notify = 0;
-		tty = tty_port_tty_get(&portp->port);
-
-		if (nt.signal & SG_DCD) {
-			oldsigs = portp->sigs;
-			portp->sigs = stli_mktiocm(nt.sigvalue);
-			clear_bit(ST_GETSIGS, &portp->state);
-			if ((portp->sigs & TIOCM_CD) &&
-			    ((oldsigs & TIOCM_CD) == 0))
-				wake_up_interruptible(&portp->port.open_wait);
-			if ((oldsigs & TIOCM_CD) &&
-			    ((portp->sigs & TIOCM_CD) == 0)) {
-				if (portp->port.flags & ASYNC_CHECK_CD) {
-					if (tty)
-						tty_hangup(tty);
-				}
-			}
-		}
-
-		if (nt.data & DT_TXEMPTY)
-			clear_bit(ST_TXBUSY, &portp->state);
-		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
-			if (tty != NULL) {
-				tty_wakeup(tty);
-				EBRDENABLE(brdp);
-			}
-		}
-
-		if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
-			if (tty != NULL) {
-				tty_insert_flip_char(tty, 0, TTY_BREAK);
-				if (portp->port.flags & ASYNC_SAK) {
-					do_SAK(tty);
-					EBRDENABLE(brdp);
-				}
-				tty_schedule_flip(tty);
-			}
-		}
-		tty_kref_put(tty);
-
-		if (nt.data & DT_RXBUSY) {
-			donerx++;
-			stli_read(brdp, portp);
-		}
-	}
-
-/*
- *	It might seem odd that we are checking for more RX chars here.
- *	But, we need to handle the case where the tty buffer was previously
- *	filled, but we had more characters to pass up. The slave will not
- *	send any more RX notify messages until the RX buffer has been emptied.
- *	But it will leave the service bits on (since the buffer is not empty).
- *	So from here we can try to process more RX chars.
- */
-	if ((!donerx) && test_bit(ST_RXING, &portp->state)) {
-		clear_bit(ST_RXING, &portp->state);
-		stli_read(brdp, portp);
-	}
-
-	return((test_bit(ST_OPENING, &portp->state) ||
-		test_bit(ST_CLOSING, &portp->state) ||
-		test_bit(ST_CMDING, &portp->state) ||
-		test_bit(ST_TXBUSY, &portp->state) ||
-		test_bit(ST_RXING, &portp->state)) ? 0 : 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Service all ports on a particular board. Assumes that the boards
- *	shared memory is enabled, and that the page pointer is pointed
- *	at the cdk header structure.
- */
-
-static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
-{
-	struct stliport *portp;
-	unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
-	unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
-	unsigned char __iomem *slavep;
-	int bitpos, bitat, bitsize;
-	int channr, nrdevs, slavebitchange;
-
-	bitsize = brdp->bitsize;
-	nrdevs = brdp->nrdevs;
-
-/*
- *	Check if slave wants any service. Basically we try to do as
- *	little work as possible here. There are 2 levels of service
- *	bits. So if there is nothing to do we bail early. We check
- *	8 service bits at a time in the inner loop, so we can bypass
- *	the lot if none of them want service.
- */
-	memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset),
-		bitsize);
-
-	memset(&slavebits[0], 0, bitsize);
-	slavebitchange = 0;
-
-	for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-		if (hostbits[bitpos] == 0)
-			continue;
-		channr = bitpos * 8;
-		for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) {
-			if (hostbits[bitpos] & bitat) {
-				portp = brdp->ports[(channr - 1)];
-				if (stli_hostcmd(brdp, portp)) {
-					slavebitchange++;
-					slavebits[bitpos] |= bitat;
-				}
-			}
-		}
-	}
-
-/*
- *	If any of the ports are no longer busy then update them in the
- *	slave request bits. We need to do this after, since a host port
- *	service may initiate more slave requests.
- */
-	if (slavebitchange) {
-		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset;
-		for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-			if (readb(slavebits + bitpos))
-				writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos);
-		}
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Driver poll routine. This routine polls the boards in use and passes
- *	messages back up to host when necessary. This is actually very
- *	CPU efficient, since we will always have the kernel poll clock, it
- *	adds only a few cycles when idle (since board service can be
- *	determined very easily), but when loaded generates no interrupts
- *	(with their expensive associated context change).
- */
-
-static void stli_poll(unsigned long arg)
-{
-	cdkhdr_t __iomem *hdrp;
-	struct stlibrd *brdp;
-	unsigned int brdnr;
-
-	mod_timer(&stli_timerlist, STLI_TIMEOUT);
-
-/*
- *	Check each board and do any servicing required.
- */
-	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
-		brdp = stli_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (!test_bit(BST_STARTED, &brdp->state))
-			continue;
-
-		spin_lock(&brd_lock);
-		EBRDENABLE(brdp);
-		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		if (readb(&hdrp->hostreq))
-			stli_brdpoll(brdp, hdrp);
-		EBRDDISABLE(brdp);
-		spin_unlock(&brd_lock);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Translate the termios settings into the port setting structure of
- *	the slave.
- */
-
-static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
-				asyport_t *pp, struct ktermios *tiosp)
-{
-	memset(pp, 0, sizeof(asyport_t));
-
-/*
- *	Start of by setting the baud, char size, parity and stop bit info.
- */
-	pp->baudout = tty_get_baud_rate(tty);
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			pp->baudout = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			pp->baudout = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			pp->baudout = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			pp->baudout = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			pp->baudout = (portp->baud_base / portp->custom_divisor);
-	}
-	if (pp->baudout > STL_MAXBAUD)
-		pp->baudout = STL_MAXBAUD;
-	pp->baudin = pp->baudout;
-
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		pp->csize = 5;
-		break;
-	case CS6:
-		pp->csize = 6;
-		break;
-	case CS7:
-		pp->csize = 7;
-		break;
-	default:
-		pp->csize = 8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		pp->stopbs = PT_STOP2;
-	else
-		pp->stopbs = PT_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			pp->parity = PT_ODDPARITY;
-		else
-			pp->parity = PT_EVENPARITY;
-	} else {
-		pp->parity = PT_NOPARITY;
-	}
-
-/*
- *	Set up any flow control options enabled.
- */
-	if (tiosp->c_iflag & IXON) {
-		pp->flow |= F_IXON;
-		if (tiosp->c_iflag & IXANY)
-			pp->flow |= F_IXANY;
-	}
-	if (tiosp->c_cflag & CRTSCTS)
-		pp->flow |= (F_RTSFLOW | F_CTSFLOW);
-
-	pp->startin = tiosp->c_cc[VSTART];
-	pp->stopin = tiosp->c_cc[VSTOP];
-	pp->startout = tiosp->c_cc[VSTART];
-	pp->stopout = tiosp->c_cc[VSTOP];
-
-/*
- *	Set up the RX char marking mask with those RX error types we must
- *	catch. We can get the slave to help us out a little here, it will
- *	ignore parity errors and breaks for us, and mark parity errors in
- *	the data stream.
- */
-	if (tiosp->c_iflag & IGNPAR)
-		pp->iflag |= FI_IGNRXERRS;
-	if (tiosp->c_iflag & IGNBRK)
-		pp->iflag |= FI_IGNBREAK;
-
-	portp->rxmarkmsk = 0;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		pp->iflag |= FI_1MARKRXERRS;
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= BRKINT;
-
-/*
- *	Set up clocal processing as required.
- */
-	if (tiosp->c_cflag & CLOCAL)
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		portp->port.flags |= ASYNC_CHECK_CD;
-
-/*
- *	Transfer any persistent flags into the asyport structure.
- */
-	pp->pflag = (portp->pflag & 0xffff);
-	pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0;
-	pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0;
-	pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Construct a slave signals structure for setting the DTR and RTS
- *	signals as specified.
- */
-
-static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
-{
-	memset(sp, 0, sizeof(asysigs_t));
-	if (dtr >= 0) {
-		sp->signal |= SG_DTR;
-		sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
-	}
-	if (rts >= 0) {
-		sp->signal |= SG_RTS;
-		sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Convert the signals returned from the slave into a local TIOCM type
- *	signals value. We keep them locally in TIOCM format.
- */
-
-static long stli_mktiocm(unsigned long sigvalue)
-{
-	long	tiocm = 0;
-	tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
-	tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
-	tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
-	tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
-	tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
-	tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
-	return(tiocm);
-}
-
-/*****************************************************************************/
-
-/*
- *	All panels and ports actually attached have been worked out. All
- *	we need to do here is set up the appropriate per port data structures.
- */
-
-static int stli_initports(struct stlibrd *brdp)
-{
-	struct stliport	*portp;
-	unsigned int i, panelnr, panelport;
-
-	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
-		portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
-		if (!portp) {
-			printk(KERN_WARNING "istallion: failed to allocate port structure\n");
-			continue;
-		}
-		tty_port_init(&portp->port);
-		portp->port.ops = &stli_port_ops;
-		portp->magic = STLI_PORTMAGIC;
-		portp->portnr = i;
-		portp->brdnr = brdp->brdnr;
-		portp->panelnr = panelnr;
-		portp->baud_base = STL_BAUDBASE;
-		portp->port.close_delay = STL_CLOSEDELAY;
-		portp->closing_wait = 30 * HZ;
-		init_waitqueue_head(&portp->port.open_wait);
-		init_waitqueue_head(&portp->port.close_wait);
-		init_waitqueue_head(&portp->raw_wait);
-		panelport++;
-		if (panelport >= brdp->panels[panelnr]) {
-			panelport = 0;
-			panelnr++;
-		}
-		brdp->ports[i] = portp;
-	}
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	All the following routines are board specific hardware operations.
- */
-
-static void stli_ecpinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
-	udelay(10);
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-	udelay(100);
-
-	memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
-	outb(memconf, (brdp->iobase + ECP_ATMEMAR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpenable(struct stlibrd *brdp)
-{	
-	outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpdisable(struct stlibrd *brdp)
-{	
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_ATPAGESIZE);
-		val = (unsigned char) (offset / ECP_ATPAGESIZE);
-	}
-	outb(val, (brdp->iobase + ECP_ATMEMPR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpreset(struct stlibrd *brdp)
-{	
-	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
-	udelay(10);
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpintr(struct stlibrd *brdp)
-{	
-	outb(0x1, brdp->iobase);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP EISA boards.
- */
-
-static void stli_ecpeiinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
-	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-	udelay(10);
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-	udelay(500);
-
-	memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
-	outb(memconf, (brdp->iobase + ECP_EIMEMARL));
-	memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
-	outb(memconf, (brdp->iobase + ECP_EIMEMARH));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeienable(struct stlibrd *brdp)
-{	
-	outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeidisable(struct stlibrd *brdp)
-{	
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char	val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_EIPAGESIZE);
-		if (offset < ECP_EIPAGESIZE)
-			val = ECP_EIENABLE;
-		else
-			val = ECP_EIENABLE | 0x40;
-	}
-	outb(val, (brdp->iobase + ECP_EICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeireset(struct stlibrd *brdp)
-{	
-	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-	udelay(10);
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP MCA boards.
- */
-
-static void stli_ecpmcenable(struct stlibrd *brdp)
-{	
-	outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcdisable(struct stlibrd *brdp)
-{	
-	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_MCPAGESIZE);
-		val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
-	}
-	outb(val, (brdp->iobase + ECP_MCCONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcreset(struct stlibrd *brdp)
-{	
-	outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
-	udelay(10);
-	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP PCI boards.
- */
-
-static void stli_ecppciinit(struct stlibrd *brdp)
-{
-	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + ECP_PCICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char	val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), board=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
-		val = (offset / ECP_PCIPAGESIZE) << 1;
-	}
-	outb(val, (brdp->iobase + ECP_PCICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecppcireset(struct stlibrd *brdp)
-{	
-	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + ECP_PCICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on ONboards.
- */
-
-static void stli_onbinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
-	udelay(10);
-	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
-	mdelay(1000);
-
-	memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
-	outb(memconf, (brdp->iobase + ONB_ATMEMAR));
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void stli_onbenable(struct stlibrd *brdp)
-{	
-	outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_onbdisable(struct stlibrd *brdp)
-{	
-	outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-	} else {
-		ptr = brdp->membase + (offset % ONB_ATPAGESIZE);
-	}
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbreset(struct stlibrd *brdp)
-{	
-	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
-	udelay(10);
-	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on ONboard EISA.
- */
-
-static void stli_onbeinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
-	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-	udelay(10);
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-	mdelay(1000);
-
-	memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
-	outb(memconf, (brdp->iobase + ONB_EIMEMARL));
-	memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
-	outb(memconf, (brdp->iobase + ONB_EIMEMARH));
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void stli_onbeenable(struct stlibrd *brdp)
-{	
-	outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_onbedisable(struct stlibrd *brdp)
-{	
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ONB_EIPAGESIZE);
-		if (offset < ONB_EIPAGESIZE)
-			val = ONB_EIENABLE;
-		else
-			val = ONB_EIENABLE | 0x40;
-	}
-	outb(val, (brdp->iobase + ONB_EICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbereset(struct stlibrd *brdp)
-{	
-	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-	udelay(10);
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on Brumby boards.
- */
-
-static void stli_bbyinit(struct stlibrd *brdp)
-{
-	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + BBY_ATCONFR));
-	mdelay(1000);
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	BUG_ON(offset > brdp->memsize);
-
-	ptr = brdp->membase + (offset % BBY_PAGESIZE);
-	val = (unsigned char) (offset / BBY_PAGESIZE);
-	outb(val, (brdp->iobase + BBY_ATCONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_bbyreset(struct stlibrd *brdp)
-{	
-	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + BBY_ATCONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on original old Stallion boards.
- */
-
-static void stli_stalinit(struct stlibrd *brdp)
-{
-	outb(0x1, brdp->iobase);
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	BUG_ON(offset > brdp->memsize);
-	return brdp->membase + (offset % STAL_PAGESIZE);
-}
-
-/*****************************************************************************/
-
-static void stli_stalreset(struct stlibrd *brdp)
-{	
-	u32 __iomem *vecp;
-
-	vecp = (u32 __iomem *) (brdp->membase + 0x30);
-	writel(0xffff0000, vecp);
-	outb(0, brdp->iobase);
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ECP board and initialize it. This handles only ECP
- *	board types.
- */
-
-static int stli_initecp(struct stlibrd *brdp)
-{
-	cdkecpsig_t sig;
-	cdkecpsig_t __iomem *sigsp;
-	unsigned int status, nxtid;
-	char *name;
-	int retval, panelnr, nrports;
-
-	if ((brdp->iobase == 0) || (brdp->memaddr == 0)) {
-		retval = -ENODEV;
-		goto err;
-	}
-
-	brdp->iosize = ECP_IOSIZE;
-
-	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
-		retval = -EIO;
-		goto err;
-	}
-
-/*
- *	Based on the specific board type setup the common vars to access
- *	and enable shared memory. Set all board specific information now
- *	as well.
- */
-	switch (brdp->brdtype) {
-	case BRD_ECP:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_ATPAGESIZE;
-		brdp->init = stli_ecpinit;
-		brdp->enable = stli_ecpenable;
-		brdp->reenable = stli_ecpenable;
-		brdp->disable = stli_ecpdisable;
-		brdp->getmemptr = stli_ecpgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpreset;
-		name = "serial(EC8/64)";
-		break;
-
-	case BRD_ECPE:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_EIPAGESIZE;
-		brdp->init = stli_ecpeiinit;
-		brdp->enable = stli_ecpeienable;
-		brdp->reenable = stli_ecpeienable;
-		brdp->disable = stli_ecpeidisable;
-		brdp->getmemptr = stli_ecpeigetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpeireset;
-		name = "serial(EC8/64-EI)";
-		break;
-
-	case BRD_ECPMC:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_MCPAGESIZE;
-		brdp->init = NULL;
-		brdp->enable = stli_ecpmcenable;
-		brdp->reenable = stli_ecpmcenable;
-		brdp->disable = stli_ecpmcdisable;
-		brdp->getmemptr = stli_ecpmcgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpmcreset;
-		name = "serial(EC8/64-MCA)";
-		break;
-
-	case BRD_ECPPCI:
-		brdp->memsize = ECP_PCIMEMSIZE;
-		brdp->pagesize = ECP_PCIPAGESIZE;
-		brdp->init = stli_ecppciinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_ecppcigetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecppcireset;
-		name = "serial(EC/RA-PCI)";
-		break;
-
-	default:
-		retval = -EINVAL;
-		goto err_reg;
-	}
-
-/*
- *	The per-board operations structure is all set up, so now let's go
- *	and get the board operational. Firstly initialize board configuration
- *	registers. Set the memory mapping info so we can get at the boards
- *	shared memory.
- */
-	EBRDINIT(brdp);
-
-	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == NULL) {
-		retval = -ENOMEM;
-		goto err_reg;
-	}
-
-/*
- *	Now that all specific code is set up, enable the shared memory and
- *	look for the a signature area that will tell us exactly what board
- *	this is, and what it is connected to it.
- */
-	EBRDENABLE(brdp);
-	sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
-	EBRDDISABLE(brdp);
-
-	if (sig.magic != cpu_to_le32(ECP_MAGIC)) {
-		retval = -ENODEV;
-		goto err_unmap;
-	}
-
-/*
- *	Scan through the signature looking at the panels connected to the
- *	board. Calculate the total number of ports as we go.
- */
-	for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
-		status = sig.panelid[nxtid];
-		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
-
-		brdp->panelids[panelnr] = status;
-		nrports = (status & ECH_PNL16PORT) ? 16 : 8;
-		if ((nrports == 16) && ((status & ECH_PNLXPID) == 0))
-			nxtid++;
-		brdp->panels[panelnr] = nrports;
-		brdp->nrports += nrports;
-		nxtid++;
-		brdp->nrpanels++;
-	}
-
-
-	set_bit(BST_FOUND, &brdp->state);
-	return 0;
-err_unmap:
-	iounmap(brdp->membase);
-	brdp->membase = NULL;
-err_reg:
-	release_region(brdp->iobase, brdp->iosize);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ONboard, Brumby or Stallion board and initialize it.
- *	This handles only these board types.
- */
-
-static int stli_initonb(struct stlibrd *brdp)
-{
-	cdkonbsig_t sig;
-	cdkonbsig_t __iomem *sigsp;
-	char *name;
-	int i, retval;
-
-/*
- *	Do a basic sanity check on the IO and memory addresses.
- */
-	if (brdp->iobase == 0 || brdp->memaddr == 0) {
-		retval = -ENODEV;
-		goto err;
-	}
-
-	brdp->iosize = ONB_IOSIZE;
-	
-	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
-		retval = -EIO;
-		goto err;
-	}
-
-/*
- *	Based on the specific board type setup the common vars to access
- *	and enable shared memory. Set all board specific information now
- *	as well.
- */
-	switch (brdp->brdtype) {
-	case BRD_ONBOARD:
-	case BRD_ONBOARD2:
-		brdp->memsize = ONB_MEMSIZE;
-		brdp->pagesize = ONB_ATPAGESIZE;
-		brdp->init = stli_onbinit;
-		brdp->enable = stli_onbenable;
-		brdp->reenable = stli_onbenable;
-		brdp->disable = stli_onbdisable;
-		brdp->getmemptr = stli_onbgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_onbreset;
-		if (brdp->memaddr > 0x100000)
-			brdp->enabval = ONB_MEMENABHI;
-		else
-			brdp->enabval = ONB_MEMENABLO;
-		name = "serial(ONBoard)";
-		break;
-
-	case BRD_ONBOARDE:
-		brdp->memsize = ONB_EIMEMSIZE;
-		brdp->pagesize = ONB_EIPAGESIZE;
-		brdp->init = stli_onbeinit;
-		brdp->enable = stli_onbeenable;
-		brdp->reenable = stli_onbeenable;
-		brdp->disable = stli_onbedisable;
-		brdp->getmemptr = stli_onbegetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_onbereset;
-		name = "serial(ONBoard/E)";
-		break;
-
-	case BRD_BRUMBY4:
-		brdp->memsize = BBY_MEMSIZE;
-		brdp->pagesize = BBY_PAGESIZE;
-		brdp->init = stli_bbyinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_bbygetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_bbyreset;
-		name = "serial(Brumby)";
-		break;
-
-	case BRD_STALLION:
-		brdp->memsize = STAL_MEMSIZE;
-		brdp->pagesize = STAL_PAGESIZE;
-		brdp->init = stli_stalinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_stalgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_stalreset;
-		name = "serial(Stallion)";
-		break;
-
-	default:
-		retval = -EINVAL;
-		goto err_reg;
-	}
-
-/*
- *	The per-board operations structure is all set up, so now let's go
- *	and get the board operational. Firstly initialize board configuration
- *	registers. Set the memory mapping info so we can get at the boards
- *	shared memory.
- */
-	EBRDINIT(brdp);
-
-	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == NULL) {
-		retval = -ENOMEM;
-		goto err_reg;
-	}
-
-/*
- *	Now that all specific code is set up, enable the shared memory and
- *	look for the a signature area that will tell us exactly what board
- *	this is, and how many ports.
- */
-	EBRDENABLE(brdp);
-	sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t));
-	EBRDDISABLE(brdp);
-
-	if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
-	    sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
-	    sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
-	    sig.magic3 != cpu_to_le16(ONB_MAGIC3)) {
-		retval = -ENODEV;
-		goto err_unmap;
-	}
-
-/*
- *	Scan through the signature alive mask and calculate how many ports
- *	there are on this board.
- */
-	brdp->nrpanels = 1;
-	if (sig.amask1) {
-		brdp->nrports = 32;
-	} else {
-		for (i = 0; (i < 16); i++) {
-			if (((sig.amask0 << i) & 0x8000) == 0)
-				break;
-		}
-		brdp->nrports = i;
-	}
-	brdp->panels[0] = brdp->nrports;
-
-
-	set_bit(BST_FOUND, &brdp->state);
-	return 0;
-err_unmap:
-	iounmap(brdp->membase);
-	brdp->membase = NULL;
-err_reg:
-	release_region(brdp->iobase, brdp->iosize);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Start up a running board. This routine is only called after the
- *	code has been down loaded to the board and is operational. It will
- *	read in the memory map, and get the show on the road...
- */
-
-static int stli_startbrd(struct stlibrd *brdp)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkmem_t __iomem *memp;
-	cdkasy_t __iomem *ap;
-	unsigned long flags;
-	unsigned int portnr, nrdevs, i;
-	struct stliport *portp;
-	int rc = 0;
-	u32 memoff;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	nrdevs = hdrp->nrdevs;
-
-#if 0
-	printk("%s(%d): CDK version %d.%d.%d --> "
-		"nrdevs=%d memp=%x hostp=%x slavep=%x\n",
-		 __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification),
-		 readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp),
-		 readl(&hdrp->slavep));
-#endif
-
-	if (nrdevs < (brdp->nrports + 1)) {
-		printk(KERN_ERR "istallion: slave failed to allocate memory for "
-				"all devices, devices=%d\n", nrdevs);
-		brdp->nrports = nrdevs - 1;
-	}
-	brdp->nrdevs = nrdevs;
-	brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
-	brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
-	brdp->bitsize = (nrdevs + 7) / 8;
-	memoff = readl(&hdrp->memp);
-	if (memoff > brdp->memsize) {
-		printk(KERN_ERR "istallion: corrupted shared memory region?\n");
-		rc = -EIO;
-		goto stli_donestartup;
-	}
-	memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
-	if (readw(&memp->dtype) != TYP_ASYNCTRL) {
-		printk(KERN_ERR "istallion: no slave control device found\n");
-		goto stli_donestartup;
-	}
-	memp++;
-
-/*
- *	Cycle through memory allocation of each port. We are guaranteed to
- *	have all ports inside the first page of slave window, so no need to
- *	change pages while reading memory map.
- */
-	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
-		if (readw(&memp->dtype) != TYP_ASYNC)
-			break;
-		portp = brdp->ports[portnr];
-		if (portp == NULL)
-			break;
-		portp->devnr = i;
-		portp->addr = readl(&memp->offset);
-		portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs));
-		portp->portidx = (unsigned char) (i / 8);
-		portp->portbit = (unsigned char) (0x1 << (i % 8));
-	}
-
-	writeb(0xff, &hdrp->slavereq);
-
-/*
- *	For each port setup a local copy of the RX and TX buffer offsets
- *	and sizes. We do this separate from the above, because we need to
- *	move the shared memory page...
- */
-	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
-		portp = brdp->ports[portnr];
-		if (portp == NULL)
-			break;
-		if (portp->addr == 0)
-			break;
-		ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-		if (ap != NULL) {
-			portp->rxsize = readw(&ap->rxq.size);
-			portp->txsize = readw(&ap->txq.size);
-			portp->rxoffset = readl(&ap->rxq.offset);
-			portp->txoffset = readl(&ap->txq.offset);
-		}
-	}
-
-stli_donestartup:
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (rc == 0)
-		set_bit(BST_STARTED, &brdp->state);
-
-	if (! stli_timeron) {
-		stli_timeron++;
-		mod_timer(&stli_timerlist, STLI_TIMEOUT);
-	}
-
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Probe and initialize the specified board.
- */
-
-static int __devinit stli_brdinit(struct stlibrd *brdp)
-{
-	int retval;
-
-	switch (brdp->brdtype) {
-	case BRD_ECP:
-	case BRD_ECPE:
-	case BRD_ECPMC:
-	case BRD_ECPPCI:
-		retval = stli_initecp(brdp);
-		break;
-	case BRD_ONBOARD:
-	case BRD_ONBOARDE:
-	case BRD_ONBOARD2:
-	case BRD_BRUMBY4:
-	case BRD_STALLION:
-		retval = stli_initonb(brdp);
-		break;
-	default:
-		printk(KERN_ERR "istallion: board=%d is unknown board "
-				"type=%d\n", brdp->brdnr, brdp->brdtype);
-		retval = -ENODEV;
-	}
-
-	if (retval)
-		return retval;
-
-	stli_initports(brdp);
-	printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x "
-		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
-		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
-		brdp->nrpanels, brdp->nrports);
-	return 0;
-}
-
-#if STLI_EISAPROBE != 0
-/*****************************************************************************/
-
-/*
- *	Probe around trying to find where the EISA boards shared memory
- *	might be. This is a bit if hack, but it is the best we can do.
- */
-
-static int stli_eisamemprobe(struct stlibrd *brdp)
-{
-	cdkecpsig_t	ecpsig, __iomem *ecpsigp;
-	cdkonbsig_t	onbsig, __iomem *onbsigp;
-	int		i, foundit;
-
-/*
- *	First up we reset the board, to get it into a known state. There
- *	is only 2 board types here we need to worry about. Don;t use the
- *	standard board init routine here, it programs up the shared
- *	memory address, and we don't know it yet...
- */
-	if (brdp->brdtype == BRD_ECPE) {
-		outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
-		outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-		udelay(10);
-		outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-		udelay(500);
-		stli_ecpeienable(brdp);
-	} else if (brdp->brdtype == BRD_ONBOARDE) {
-		outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
-		outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-		udelay(10);
-		outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-		mdelay(100);
-		outb(0x1, brdp->iobase);
-		mdelay(1);
-		stli_onbeenable(brdp);
-	} else {
-		return -ENODEV;
-	}
-
-	foundit = 0;
-	brdp->memsize = ECP_MEMSIZE;
-
-/*
- *	Board shared memory is enabled, so now we have a poke around and
- *	see if we can find it.
- */
-	for (i = 0; (i < stli_eisamempsize); i++) {
-		brdp->memaddr = stli_eisamemprobeaddrs[i];
-		brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-		if (brdp->membase == NULL)
-			continue;
-
-		if (brdp->brdtype == BRD_ECPE) {
-			ecpsigp = stli_ecpeigetmemptr(brdp,
-				CDK_SIGADDR, __LINE__);
-			memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
-			if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
-				foundit = 1;
-		} else {
-			onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp,
-				CDK_SIGADDR, __LINE__);
-			memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t));
-			if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) &&
-			    (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) &&
-			    (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) &&
-			    (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3)))
-				foundit = 1;
-		}
-
-		iounmap(brdp->membase);
-		if (foundit)
-			break;
-	}
-
-/*
- *	Regardless of whether we found the shared memory or not we must
- *	disable the region. After that return success or failure.
- */
-	if (brdp->brdtype == BRD_ECPE)
-		stli_ecpeidisable(brdp);
-	else
-		stli_onbedisable(brdp);
-
-	if (! foundit) {
-		brdp->memaddr = 0;
-		brdp->membase = NULL;
-		printk(KERN_ERR "istallion: failed to probe shared memory "
-				"region for %s in EISA slot=%d\n",
-			stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
-		return -ENODEV;
-	}
-	return 0;
-}
-#endif
-
-static int stli_getbrdnr(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < STL_MAXBRDS; i++) {
-		if (!stli_brds[i]) {
-			if (i >= stli_nrbrds)
-				stli_nrbrds = i + 1;
-			return i;
-		}
-	}
-	return -1;
-}
-
-#if STLI_EISAPROBE != 0
-/*****************************************************************************/
-
-/*
- *	Probe around and try to find any EISA boards in system. The biggest
- *	problem here is finding out what memory address is associated with
- *	an EISA board after it is found. The registers of the ECPE and
- *	ONboardE are not readable - so we can't read them from there. We
- *	don't have access to the EISA CMOS (or EISA BIOS) so we don't
- *	actually have any way to find out the real value. The best we can
- *	do is go probing around in the usual places hoping we can find it.
- */
-
-static int __init stli_findeisabrds(void)
-{
-	struct stlibrd *brdp;
-	unsigned int iobase, eid, i;
-	int brdnr, found = 0;
-
-/*
- *	Firstly check if this is an EISA system.  If this is not an EISA system then
- *	don't bother going any further!
- */
-	if (EISA_bus)
-		return 0;
-
-/*
- *	Looks like an EISA system, so go searching for EISA boards.
- */
-	for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) {
-		outb(0xff, (iobase + 0xc80));
-		eid = inb(iobase + 0xc80);
-		eid |= inb(iobase + 0xc81) << 8;
-		if (eid != STL_EISAID)
-			continue;
-
-/*
- *		We have found a board. Need to check if this board was
- *		statically configured already (just in case!).
- */
-		for (i = 0; (i < STL_MAXBRDS); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			if (brdp->iobase == iobase)
-				break;
-		}
-		if (i < STL_MAXBRDS)
-			continue;
-
-/*
- *		We have found a Stallion board and it is not configured already.
- *		Allocate a board structure and initialize it.
- */
-		if ((brdp = stli_allocbrd()) == NULL)
-			return found ? : -ENOMEM;
-		brdnr = stli_getbrdnr();
-		if (brdnr < 0)
-			return found ? : -ENOMEM;
-		brdp->brdnr = (unsigned int)brdnr;
-		eid = inb(iobase + 0xc82);
-		if (eid == ECP_EISAID)
-			brdp->brdtype = BRD_ECPE;
-		else if (eid == ONB_EISAID)
-			brdp->brdtype = BRD_ONBOARDE;
-		else
-			brdp->brdtype = BRD_UNKNOWN;
-		brdp->iobase = iobase;
-		outb(0x1, (iobase + 0xc84));
-		if (stli_eisamemprobe(brdp))
-			outb(0, (iobase + 0xc84));
-		if (stli_brdinit(brdp) < 0) {
-			kfree(brdp);
-			continue;
-		}
-
-		stli_brds[brdp->brdnr] = brdp;
-		found++;
-
-		for (i = 0; i < brdp->nrports; i++)
-			tty_register_device(stli_serial,
-					brdp->brdnr * STL_MAXPORTS + i, NULL);
-	}
-
-	return found;
-}
-#else
-static inline int stli_findeisabrds(void) { return 0; }
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Find the next available board number that is free.
- */
-
-/*****************************************************************************/
-
-/*
- *	We have a Stallion board. Allocate a board structure and
- *	initialize it. Read its IO and MEMORY resources from PCI
- *	configuration space.
- */
-
-static int __devinit stli_pciprobe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-	int brdnr, retval = -EIO;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err;
-	brdp = stli_allocbrd();
-	if (brdp == NULL) {
-		retval = -ENOMEM;
-		goto err;
-	}
-	mutex_lock(&stli_brdslock);
-	brdnr = stli_getbrdnr();
-	if (brdnr < 0) {
-		printk(KERN_INFO "istallion: too many boards found, "
-			"maximum supported %d\n", STL_MAXBRDS);
-		mutex_unlock(&stli_brdslock);
-		retval = -EIO;
-		goto err_fr;
-	}
-	brdp->brdnr = (unsigned int)brdnr;
-	stli_brds[brdp->brdnr] = brdp;
-	mutex_unlock(&stli_brdslock);
-	brdp->brdtype = BRD_ECPPCI;
-/*
- *	We have all resources from the board, so lets setup the actual
- *	board structure now.
- */
-	brdp->iobase = pci_resource_start(pdev, 3);
-	brdp->memaddr = pci_resource_start(pdev, 2);
-	retval = stli_brdinit(brdp);
-	if (retval)
-		goto err_null;
-
-	set_bit(BST_PROBED, &brdp->state);
-	pci_set_drvdata(pdev, brdp);
-
-	EBRDENABLE(brdp);
-	brdp->enable = NULL;
-	brdp->disable = NULL;
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i,
-				&pdev->dev);
-
-	return 0;
-err_null:
-	stli_brds[brdp->brdnr] = NULL;
-err_fr:
-	kfree(brdp);
-err:
-	return retval;
-}
-
-static void __devexit stli_pciremove(struct pci_dev *pdev)
-{
-	struct stlibrd *brdp = pci_get_drvdata(pdev);
-
-	stli_cleanup_ports(brdp);
-
-	iounmap(brdp->membase);
-	if (brdp->iosize > 0)
-		release_region(brdp->iobase, brdp->iosize);
-
-	stli_brds[brdp->brdnr] = NULL;
-	kfree(brdp);
-}
-
-static struct pci_driver stli_pcidriver = {
-	.name = "istallion",
-	.id_table = istallion_pci_tbl,
-	.probe = stli_pciprobe,
-	.remove = __devexit_p(stli_pciremove)
-};
-/*****************************************************************************/
-
-/*
- *	Allocate a new board structure. Fill out the basic info in it.
- */
-
-static struct stlibrd *stli_allocbrd(void)
-{
-	struct stlibrd *brdp;
-
-	brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
-	if (!brdp) {
-		printk(KERN_ERR "istallion: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlibrd));
-		return NULL;
-	}
-	brdp->magic = STLI_BOARDMAGIC;
-	return brdp;
-}
-
-/*****************************************************************************/
-
-/*
- *	Scan through all the boards in the configuration and see what we
- *	can find.
- */
-
-static int __init stli_initbrds(void)
-{
-	struct stlibrd *brdp, *nxtbrdp;
-	struct stlconf conf;
-	unsigned int i, j, found = 0;
-	int retval;
-
-	for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
-			stli_nrbrds++) {
-		memset(&conf, 0, sizeof(conf));
-		if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
-			continue;
-		if ((brdp = stli_allocbrd()) == NULL)
-			continue;
-		brdp->brdnr = stli_nrbrds;
-		brdp->brdtype = conf.brdtype;
-		brdp->iobase = conf.ioaddr1;
-		brdp->memaddr = conf.memaddr;
-		if (stli_brdinit(brdp) < 0) {
-			kfree(brdp);
-			continue;
-		}
-		stli_brds[brdp->brdnr] = brdp;
-		found++;
-
-		for (i = 0; i < brdp->nrports; i++)
-			tty_register_device(stli_serial,
-					brdp->brdnr * STL_MAXPORTS + i, NULL);
-	}
-
-	retval = stli_findeisabrds();
-	if (retval > 0)
-		found += retval;
-
-/*
- *	All found boards are initialized. Now for a little optimization, if
- *	no boards are sharing the "shared memory" regions then we can just
- *	leave them all enabled. This is in fact the usual case.
- */
-	stli_shared = 0;
-	if (stli_nrbrds > 1) {
-		for (i = 0; (i < stli_nrbrds); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			for (j = i + 1; (j < stli_nrbrds); j++) {
-				nxtbrdp = stli_brds[j];
-				if (nxtbrdp == NULL)
-					continue;
-				if ((brdp->membase >= nxtbrdp->membase) &&
-				    (brdp->membase <= (nxtbrdp->membase +
-				    nxtbrdp->memsize - 1))) {
-					stli_shared++;
-					break;
-				}
-			}
-		}
-	}
-
-	if (stli_shared == 0) {
-		for (i = 0; (i < stli_nrbrds); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			if (test_bit(BST_FOUND, &brdp->state)) {
-				EBRDENABLE(brdp);
-				brdp->enable = NULL;
-				brdp->disable = NULL;
-			}
-		}
-	}
-
-	retval = pci_register_driver(&stli_pcidriver);
-	if (retval && found == 0) {
-		printk(KERN_ERR "Neither isa nor eisa cards found nor pci "
-				"driver can be registered!\n");
-		goto err;
-	}
-
-	return 0;
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Code to handle an "staliomem" read operation. This device is the 
- *	contents of the board shared memory. It is used for down loading
- *	the slave image (and debugging :-)
- */
-
-static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
-{
-	unsigned long flags;
-	void __iomem *memptr;
-	struct stlibrd *brdp;
-	unsigned int brdnr;
-	int size, n;
-	void *p;
-	loff_t off = *offp;
-
-	brdnr = iminor(fp->f_path.dentry->d_inode);
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-	if (off >= brdp->memsize || off + count < off)
-		return 0;
-
-	size = min(count, (size_t)(brdp->memsize - off));
-
-	/*
-	 *	Copy the data a page at a time
-	 */
-
-	p = (void *)__get_free_page(GFP_KERNEL);
-	if(p == NULL)
-		return -ENOMEM;
-
-	while (size > 0) {
-		spin_lock_irqsave(&brd_lock, flags);
-		EBRDENABLE(brdp);
-		memptr = EBRDGETMEMPTR(brdp, off);
-		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-		n = min(n, (int)PAGE_SIZE);
-		memcpy_fromio(p, memptr, n);
-		EBRDDISABLE(brdp);
-		spin_unlock_irqrestore(&brd_lock, flags);
-		if (copy_to_user(buf, p, n)) {
-			count = -EFAULT;
-			goto out;
-		}
-		off += n;
-		buf += n;
-		size -= n;
-	}
-out:
-	*offp = off;
-	free_page((unsigned long)p);
-	return count;
-}
-
-/*****************************************************************************/
-
-/*
- *	Code to handle an "staliomem" write operation. This device is the 
- *	contents of the board shared memory. It is used for down loading
- *	the slave image (and debugging :-)
- *
- *	FIXME: copy under lock
- */
-
-static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
-{
-	unsigned long flags;
-	void __iomem *memptr;
-	struct stlibrd *brdp;
-	char __user *chbuf;
-	unsigned int brdnr;
-	int size, n;
-	void *p;
-	loff_t off = *offp;
-
-	brdnr = iminor(fp->f_path.dentry->d_inode);
-
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-	if (off >= brdp->memsize || off + count < off)
-		return 0;
-
-	chbuf = (char __user *) buf;
-	size = min(count, (size_t)(brdp->memsize - off));
-
-	/*
-	 *	Copy the data a page at a time
-	 */
-
-	p = (void *)__get_free_page(GFP_KERNEL);
-	if(p == NULL)
-		return -ENOMEM;
-
-	while (size > 0) {
-		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-		n = min(n, (int)PAGE_SIZE);
-		if (copy_from_user(p, chbuf, n)) {
-			if (count == 0)
-				count = -EFAULT;
-			goto out;
-		}
-		spin_lock_irqsave(&brd_lock, flags);
-		EBRDENABLE(brdp);
-		memptr = EBRDGETMEMPTR(brdp, off);
-		memcpy_toio(memptr, p, n);
-		EBRDDISABLE(brdp);
-		spin_unlock_irqrestore(&brd_lock, flags);
-		off += n;
-		chbuf += n;
-		size -= n;
-	}
-out:
-	free_page((unsigned long) p);
-	*offp = off;
-	return count;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the board stats structure to user app.
- */
-
-static int stli_getbrdstats(combrd_t __user *bp)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-
-	if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
-		return -EFAULT;
-	if (stli_brdstats.brd >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[stli_brdstats.brd];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	memset(&stli_brdstats, 0, sizeof(combrd_t));
-
-	stli_brdstats.brd = brdp->brdnr;
-	stli_brdstats.type = brdp->brdtype;
-	stli_brdstats.hwid = 0;
-	stli_brdstats.state = brdp->state;
-	stli_brdstats.ioaddr = brdp->iobase;
-	stli_brdstats.memaddr = brdp->memaddr;
-	stli_brdstats.nrpanels = brdp->nrpanels;
-	stli_brdstats.nrports = brdp->nrports;
-	for (i = 0; (i < brdp->nrpanels); i++) {
-		stli_brdstats.panels[i].panel = i;
-		stli_brdstats.panels[i].hwid = brdp->panelids[i];
-		stli_brdstats.panels[i].nrports = brdp->panels[i];
-	}
-
-	if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Resolve the referenced port number into a port struct pointer.
- */
-
-static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
-		unsigned int portnr)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-
-	if (brdnr >= STL_MAXBRDS)
-		return NULL;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return NULL;
-	for (i = 0; (i < panelnr); i++)
-		portnr += brdp->panels[i];
-	if (portnr >= brdp->nrports)
-		return NULL;
-	return brdp->ports[portnr];
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
-{
-	unsigned long	flags;
-	struct stlibrd	*brdp;
-	int		rc;
-
-	memset(&stli_comstats, 0, sizeof(comstats_t));
-
-	if (portp == NULL)
-		return -ENODEV;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	mutex_lock(&portp->port.mutex);
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
-		    &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
-			mutex_unlock(&portp->port.mutex);
-			return rc;
-		}
-	} else {
-		memset(&stli_cdkstats, 0, sizeof(asystats_t));
-	}
-
-	stli_comstats.brd = portp->brdnr;
-	stli_comstats.panel = portp->panelnr;
-	stli_comstats.port = portp->portnr;
-	stli_comstats.state = portp->state;
-	stli_comstats.flags = portp->port.flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	if (tty != NULL) {
-		if (portp->port.tty == tty) {
-			stli_comstats.ttystate = tty->flags;
-			stli_comstats.rxbuffered = -1;
-			if (tty->termios != NULL) {
-				stli_comstats.cflags = tty->termios->c_cflag;
-				stli_comstats.iflags = tty->termios->c_iflag;
-				stli_comstats.oflags = tty->termios->c_oflag;
-				stli_comstats.lflags = tty->termios->c_lflag;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	stli_comstats.txtotal = stli_cdkstats.txchars;
-	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
-	stli_comstats.txbuffered = stli_cdkstats.txringq;
-	stli_comstats.rxbuffered += stli_cdkstats.rxringq;
-	stli_comstats.rxoverrun = stli_cdkstats.overruns;
-	stli_comstats.rxparity = stli_cdkstats.parity;
-	stli_comstats.rxframing = stli_cdkstats.framing;
-	stli_comstats.rxlost = stli_cdkstats.ringover;
-	stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
-	stli_comstats.txbreaks = stli_cdkstats.txbreaks;
-	stli_comstats.txxon = stli_cdkstats.txstart;
-	stli_comstats.txxoff = stli_cdkstats.txstop;
-	stli_comstats.rxxon = stli_cdkstats.rxstart;
-	stli_comstats.rxxoff = stli_cdkstats.rxstop;
-	stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
-	stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
-	stli_comstats.modem = stli_cdkstats.dcdcnt;
-	stli_comstats.hwid = stli_cdkstats.hwid;
-	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
-	mutex_unlock(&portp->port.mutex);
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
-							comstats_t __user *cp)
-{
-	struct stlibrd *brdp;
-	int rc;
-
-	if (!portp) {
-		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
-			stli_comstats.port);
-		if (!portp)
-			return -ENODEV;
-	}
-
-	brdp = stli_brds[portp->brdnr];
-	if (!brdp)
-		return -ENODEV;
-
-	if ((rc = stli_portcmdstats(tty, portp)) < 0)
-		return rc;
-
-	return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
-			-EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
-{
-	struct stlibrd *brdp;
-	int rc;
-
-	if (!portp) {
-		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
-			stli_comstats.port);
-		if (!portp)
-			return -ENODEV;
-	}
-
-	brdp = stli_brds[portp->brdnr];
-	if (!brdp)
-		return -ENODEV;
-
-	mutex_lock(&portp->port.mutex);
-
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
-			mutex_unlock(&portp->port.mutex);
-			return rc;
-		}
-	}
-
-	memset(&stli_comstats, 0, sizeof(comstats_t));
-	stli_comstats.brd = portp->brdnr;
-	stli_comstats.panel = portp->panelnr;
-	stli_comstats.port = portp->portnr;
-	mutex_unlock(&portp->port.mutex);
-
-	if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver ports structure to a user app.
- */
-
-static int stli_getportstruct(struct stliport __user *arg)
-{
-	struct stliport stli_dummyport;
-	struct stliport *portp;
-
-	if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
-		return -EFAULT;
-	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
-		 stli_dummyport.portnr);
-	if (!portp)
-		return -ENODEV;
-	if (copy_to_user(arg, portp, sizeof(struct stliport)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver board structure to a user app.
- */
-
-static int stli_getbrdstruct(struct stlibrd __user *arg)
-{
-	struct stlibrd stli_dummybrd;
-	struct stlibrd *brdp;
-
-	if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
-		return -EFAULT;
-	if (stli_dummybrd.brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[stli_dummybrd.brdnr];
-	if (!brdp)
-		return -ENODEV;
-	if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	The "staliomem" device is also required to do some special operations on
- *	the board. We need to be able to send an interrupt to the board,
- *	reset it, and start/stop it.
- */
-
-static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
-	struct stlibrd *brdp;
-	int brdnr, rc, done;
-	void __user *argp = (void __user *)arg;
-
-/*
- *	First up handle the board independent ioctls.
- */
-	done = 0;
-	rc = 0;
-
-	switch (cmd) {
-	case COM_GETPORTSTATS:
-		rc = stli_getportstats(NULL, NULL, argp);
-		done++;
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stli_clrportstats(NULL, argp);
-		done++;
-		break;
-	case COM_GETBRDSTATS:
-		rc = stli_getbrdstats(argp);
-		done++;
-		break;
-	case COM_READPORT:
-		rc = stli_getportstruct(argp);
-		done++;
-		break;
-	case COM_READBOARD:
-		rc = stli_getbrdstruct(argp);
-		done++;
-		break;
-	}
-	if (done)
-		return rc;
-
-/*
- *	Now handle the board specific ioctls. These all depend on the
- *	minor number of the device they were called from.
- */
-	brdnr = iminor(fp->f_dentry->d_inode);
-	if (brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (!brdp)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-
-	switch (cmd) {
-	case STL_BINTR:
-		EBRDINTR(brdp);
-		break;
-	case STL_BSTART:
-		rc = stli_startbrd(brdp);
-		break;
-	case STL_BSTOP:
-		clear_bit(BST_STARTED, &brdp->state);
-		break;
-	case STL_BRESET:
-		clear_bit(BST_STARTED, &brdp->state);
-		EBRDRESET(brdp);
-		if (stli_shared == 0) {
-			if (brdp->reenable != NULL)
-				(* brdp->reenable)(brdp);
-		}
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-static const struct tty_operations stli_ops = {
-	.open = stli_open,
-	.close = stli_close,
-	.write = stli_write,
-	.put_char = stli_putchar,
-	.flush_chars = stli_flushchars,
-	.write_room = stli_writeroom,
-	.chars_in_buffer = stli_charsinbuffer,
-	.ioctl = stli_ioctl,
-	.set_termios = stli_settermios,
-	.throttle = stli_throttle,
-	.unthrottle = stli_unthrottle,
-	.stop = stli_stop,
-	.start = stli_start,
-	.hangup = stli_hangup,
-	.flush_buffer = stli_flushbuffer,
-	.break_ctl = stli_breakctl,
-	.wait_until_sent = stli_waituntilsent,
-	.send_xchar = stli_sendxchar,
-	.tiocmget = stli_tiocmget,
-	.tiocmset = stli_tiocmset,
-	.proc_fops = &stli_proc_fops,
-};
-
-static const struct tty_port_operations stli_port_ops = {
-	.carrier_raised = stli_carrier_raised,
-	.dtr_rts = stli_dtr_rts,
-	.activate = stli_activate,
-	.shutdown = stli_shutdown,
-};
-
-/*****************************************************************************/
-/*
- *	Loadable module initialization stuff.
- */
-
-static void istallion_cleanup_isa(void)
-{
-	struct stlibrd	*brdp;
-	unsigned int j;
-
-	for (j = 0; (j < stli_nrbrds); j++) {
-		if ((brdp = stli_brds[j]) == NULL ||
-				test_bit(BST_PROBED, &brdp->state))
-			continue;
-
-		stli_cleanup_ports(brdp);
-
-		iounmap(brdp->membase);
-		if (brdp->iosize > 0)
-			release_region(brdp->iobase, brdp->iosize);
-		kfree(brdp);
-		stli_brds[j] = NULL;
-	}
-}
-
-static int __init istallion_module_init(void)
-{
-	unsigned int i;
-	int retval;
-
-	printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
-
-	spin_lock_init(&stli_lock);
-	spin_lock_init(&brd_lock);
-
-	stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
-	if (!stli_txcookbuf) {
-		printk(KERN_ERR "istallion: failed to allocate memory "
-				"(size=%d)\n", STLI_TXBUFSIZE);
-		retval = -ENOMEM;
-		goto err;
-	}
-
-	stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stli_serial) {
-		retval = -ENOMEM;
-		goto err_free;
-	}
-
-	stli_serial->owner = THIS_MODULE;
-	stli_serial->driver_name = stli_drvname;
-	stli_serial->name = stli_serialname;
-	stli_serial->major = STL_SERIALMAJOR;
-	stli_serial->minor_start = 0;
-	stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stli_serial->subtype = SERIAL_TYPE_NORMAL;
-	stli_serial->init_termios = stli_deftermios;
-	stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stli_serial, &stli_ops);
-
-	retval = tty_register_driver(stli_serial);
-	if (retval) {
-		printk(KERN_ERR "istallion: failed to register serial driver\n");
-		goto err_ttyput;
-	}
-
-	retval = stli_initbrds();
-	if (retval)
-		goto err_ttyunr;
-
-/*
- *	Set up a character driver for the shared memory region. We need this
- *	to down load the slave code image. Also it is a useful debugging tool.
- */
-	retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
-	if (retval) {
-		printk(KERN_ERR "istallion: failed to register serial memory "
-				"device\n");
-		goto err_deinit;
-	}
-
-	istallion_class = class_create(THIS_MODULE, "staliomem");
-	for (i = 0; i < 4; i++)
-		device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      NULL, "staliomem%d", i);
-
-	return 0;
-err_deinit:
-	pci_unregister_driver(&stli_pcidriver);
-	istallion_cleanup_isa();
-err_ttyunr:
-	tty_unregister_driver(stli_serial);
-err_ttyput:
-	put_tty_driver(stli_serial);
-err_free:
-	kfree(stli_txcookbuf);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-static void __exit istallion_module_exit(void)
-{
-	unsigned int j;
-
-	printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
-		stli_drvversion);
-
-	if (stli_timeron) {
-		stli_timeron = 0;
-		del_timer_sync(&stli_timerlist);
-	}
-
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
-
-	for (j = 0; j < 4; j++)
-		device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
-	class_destroy(istallion_class);
-
-	pci_unregister_driver(&stli_pcidriver);
-	istallion_cleanup_isa();
-
-	tty_unregister_driver(stli_serial);
-	put_tty_driver(stli_serial);
-
-	kfree(stli_txcookbuf);
-}
-
-module_init(istallion_module_init);
-module_exit(istallion_module_exit);
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index e6d7562..33dc229 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -53,6 +53,8 @@ MODULE_LICENSE("GPL");
 
 #define RTC_BITS 55 /* 55 bits for this implementation */
 
+static struct k_clock sgi_clock;
+
 extern unsigned long sn_rtc_cycles_per_second;
 
 #define RTC_COUNTER_ADDR        ((long *)LOCAL_MMR_ADDR(SH_RTC))
@@ -487,7 +489,7 @@ static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
 	return 0;
 };
 
-static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
+static int sgi_clock_set(const clockid_t clockid, const struct timespec *tp)
 {
 
 	u64 nsec;
@@ -763,15 +765,21 @@ static int sgi_timer_set(struct k_itimer *timr, int flags,
 	return err;
 }
 
+static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp)
+{
+	tp->tv_sec = 0;
+	tp->tv_nsec = sgi_clock_period;
+	return 0;
+}
+
 static struct k_clock sgi_clock = {
-	.res = 0,
-	.clock_set = sgi_clock_set,
-	.clock_get = sgi_clock_get,
-	.timer_create = sgi_timer_create,
-	.nsleep = do_posix_clock_nonanosleep,
-	.timer_set = sgi_timer_set,
-	.timer_del = sgi_timer_del,
-	.timer_get = sgi_timer_get
+	.clock_set	= sgi_clock_set,
+	.clock_get	= sgi_clock_get,
+	.clock_getres	= sgi_clock_getres,
+	.timer_create	= sgi_timer_create,
+	.timer_set	= sgi_timer_set,
+	.timer_del	= sgi_timer_del,
+	.timer_get	= sgi_timer_get
 };
 
 /**
@@ -831,8 +839,8 @@ static int __init mmtimer_init(void)
 			(unsigned long) node);
 	}
 
-	sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
-	register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
+	sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second;
+	posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock);
 
 	printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
 	       sn_rtc_cycles_per_second/(unsigned long)1E6);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
deleted file mode 100644
index 107b0bd..0000000
--- a/drivers/char/moxa.c
+++ /dev/null
@@ -1,2092 +0,0 @@
-/*****************************************************************************/
-/*
- *           moxa.c  -- MOXA Intellio family multiport serial driver.
- *
- *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com).
- *      Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- */
-
-/*
- *    MOXA Intellio Series Driver
- *      for             : LINUX
- *      date            : 1999/1/7
- *      version         : 5.1
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/firmware.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/serial.h>
-#include <linux/tty_driver.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "moxa.h"
-
-#define MOXA_VERSION		"6.0k"
-
-#define MOXA_FW_HDRLEN		32
-
-#define MOXAMAJOR		172
-
-#define MAX_BOARDS		4	/* Don't change this value */
-#define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
-#define MAX_PORTS		(MAX_BOARDS * MAX_PORTS_PER_BOARD)
-
-#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
-		(brd)->boardType == MOXA_BOARD_C320_PCI)
-
-/*
- *    Define the Moxa PCI vendor and device IDs.
- */
-#define MOXA_BUS_TYPE_ISA	0
-#define MOXA_BUS_TYPE_PCI	1
-
-enum {
-	MOXA_BOARD_C218_PCI = 1,
-	MOXA_BOARD_C218_ISA,
-	MOXA_BOARD_C320_PCI,
-	MOXA_BOARD_C320_ISA,
-	MOXA_BOARD_CP204J,
-};
-
-static char *moxa_brdname[] =
-{
-	"C218 Turbo PCI series",
-	"C218 Turbo ISA series",
-	"C320 Turbo PCI series",
-	"C320 Turbo ISA series",
-	"CP-204J series",
-};
-
-#ifdef CONFIG_PCI
-static struct pci_device_id moxa_pcibrds[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218),
-		.driver_data = MOXA_BOARD_C218_PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320),
-		.driver_data = MOXA_BOARD_C320_PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J),
-		.driver_data = MOXA_BOARD_CP204J },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
-#endif /* CONFIG_PCI */
-
-struct moxa_port;
-
-static struct moxa_board_conf {
-	int boardType;
-	int numPorts;
-	int busType;
-
-	unsigned int ready;
-
-	struct moxa_port *ports;
-
-	void __iomem *basemem;
-	void __iomem *intNdx;
-	void __iomem *intPend;
-	void __iomem *intTable;
-} moxa_boards[MAX_BOARDS];
-
-struct mxser_mstatus {
-	tcflag_t cflag;
-	int cts;
-	int dsr;
-	int ri;
-	int dcd;
-};
-
-struct moxaq_str {
-	int inq;
-	int outq;
-};
-
-struct moxa_port {
-	struct tty_port port;
-	struct moxa_board_conf *board;
-	void __iomem *tableAddr;
-
-	int type;
-	int cflag;
-	unsigned long statusflags;
-
-	u8 DCDState;		/* Protected by the port lock */
-	u8 lineCtrl;
-	u8 lowChkFlag;
-};
-
-struct mon_str {
-	int tick;
-	int rxcnt[MAX_PORTS];
-	int txcnt[MAX_PORTS];
-};
-
-/* statusflags */
-#define TXSTOPPED	1
-#define LOWWAIT 	2
-#define EMPTYWAIT	3
-
-#define SERIAL_DO_RESTART
-
-#define WAKEUP_CHARS		256
-
-static int ttymajor = MOXAMAJOR;
-static struct mon_str moxaLog;
-static unsigned int moxaFuncTout = HZ / 2;
-static unsigned int moxaLowWaterChk;
-static DEFINE_MUTEX(moxa_openlock);
-static DEFINE_SPINLOCK(moxa_lock);
-
-static unsigned long baseaddr[MAX_BOARDS];
-static unsigned int type[MAX_BOARDS];
-static unsigned int numports[MAX_BOARDS];
-
-MODULE_AUTHOR("William Chen");
-MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_FIRMWARE("c218tunx.cod");
-MODULE_FIRMWARE("cp204unx.cod");
-MODULE_FIRMWARE("c320tunx.cod");
-
-module_param_array(type, uint, NULL, 0);
-MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
-module_param_array(baseaddr, ulong, NULL, 0);
-MODULE_PARM_DESC(baseaddr, "base address");
-module_param_array(numports, uint, NULL, 0);
-MODULE_PARM_DESC(numports, "numports (ignored for C218)");
-
-module_param(ttymajor, int, 0);
-
-/*
- * static functions:
- */
-static int moxa_open(struct tty_struct *, struct file *);
-static void moxa_close(struct tty_struct *, struct file *);
-static int moxa_write(struct tty_struct *, const unsigned char *, int);
-static int moxa_write_room(struct tty_struct *);
-static void moxa_flush_buffer(struct tty_struct *);
-static int moxa_chars_in_buffer(struct tty_struct *);
-static void moxa_set_termios(struct tty_struct *, struct ktermios *);
-static void moxa_stop(struct tty_struct *);
-static void moxa_start(struct tty_struct *);
-static void moxa_hangup(struct tty_struct *);
-static int moxa_tiocmget(struct tty_struct *tty, struct file *file);
-static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear);
-static void moxa_poll(unsigned long);
-static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
-static void moxa_shutdown(struct tty_port *);
-static int moxa_carrier_raised(struct tty_port *);
-static void moxa_dtr_rts(struct tty_port *, int);
-/*
- * moxa board interface functions:
- */
-static void MoxaPortEnable(struct moxa_port *);
-static void MoxaPortDisable(struct moxa_port *);
-static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
-static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
-static void MoxaPortLineCtrl(struct moxa_port *, int, int);
-static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
-static int MoxaPortLineStatus(struct moxa_port *);
-static void MoxaPortFlushData(struct moxa_port *, int);
-static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
-static int MoxaPortReadData(struct moxa_port *);
-static int MoxaPortTxQueue(struct moxa_port *);
-static int MoxaPortRxQueue(struct moxa_port *);
-static int MoxaPortTxFree(struct moxa_port *);
-static void MoxaPortTxDisable(struct moxa_port *);
-static void MoxaPortTxEnable(struct moxa_port *);
-static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
-static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
-static void MoxaSetFifo(struct moxa_port *port, int enable);
-
-/*
- * I/O functions
- */
-
-static DEFINE_SPINLOCK(moxafunc_lock);
-
-static void moxa_wait_finish(void __iomem *ofsAddr)
-{
-	unsigned long end = jiffies + moxaFuncTout;
-
-	while (readw(ofsAddr + FuncCode) != 0)
-		if (time_after(jiffies, end))
-			return;
-	if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
-		printk(KERN_WARNING "moxa function expired\n");
-}
-
-static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
-{
-        unsigned long flags;
-        spin_lock_irqsave(&moxafunc_lock, flags);
-	writew(arg, ofsAddr + FuncArg);
-	writew(cmd, ofsAddr + FuncCode);
-	moxa_wait_finish(ofsAddr);
-	spin_unlock_irqrestore(&moxafunc_lock, flags);
-}
-
-static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg)
-{
-        unsigned long flags;
-        u16 ret;
-        spin_lock_irqsave(&moxafunc_lock, flags);
-	writew(arg, ofsAddr + FuncArg);
-	writew(cmd, ofsAddr + FuncCode);
-	moxa_wait_finish(ofsAddr);
-	ret = readw(ofsAddr + FuncArg);
-	spin_unlock_irqrestore(&moxafunc_lock, flags);
-	return ret;
-}
-
-static void moxa_low_water_check(void __iomem *ofsAddr)
-{
-	u16 rptr, wptr, mask, len;
-
-	if (readb(ofsAddr + FlagStat) & Xoff_state) {
-		rptr = readw(ofsAddr + RXrptr);
-		wptr = readw(ofsAddr + RXwptr);
-		mask = readw(ofsAddr + RX_mask);
-		len = (wptr - rptr) & mask;
-		if (len <= Low_water)
-			moxafunc(ofsAddr, FC_SendXon, 0);
-	}
-}
-
-/*
- * TTY operations
- */
-
-static int moxa_ioctl(struct tty_struct *tty, struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	struct moxa_port *ch = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int status, ret = 0;
-
-	if (tty->index == MAX_PORTS) {
-		if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
-				cmd != MOXA_GETMSTATUS)
-			return -EINVAL;
-	} else if (!ch)
-		return -ENODEV;
-
-	switch (cmd) {
-	case MOXA_GETDATACOUNT:
-		moxaLog.tick = jiffies;
-		if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
-			ret = -EFAULT;
-		break;
-	case MOXA_FLUSH_QUEUE:
-		MoxaPortFlushData(ch, arg);
-		break;
-	case MOXA_GET_IOQUEUE: {
-		struct moxaq_str __user *argm = argp;
-		struct moxaq_str tmp;
-		struct moxa_port *p;
-		unsigned int i, j;
-
-		for (i = 0; i < MAX_BOARDS; i++) {
-			p = moxa_boards[i].ports;
-			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
-				memset(&tmp, 0, sizeof(tmp));
-				spin_lock_bh(&moxa_lock);
-				if (moxa_boards[i].ready) {
-					tmp.inq = MoxaPortRxQueue(p);
-					tmp.outq = MoxaPortTxQueue(p);
-				}
-				spin_unlock_bh(&moxa_lock);
-				if (copy_to_user(argm, &tmp, sizeof(tmp)))
-					return -EFAULT;
-			}
-		}
-		break;
-	} case MOXA_GET_OQUEUE:
-		status = MoxaPortTxQueue(ch);
-		ret = put_user(status, (unsigned long __user *)argp);
-		break;
-	case MOXA_GET_IQUEUE:
-		status = MoxaPortRxQueue(ch);
-		ret = put_user(status, (unsigned long __user *)argp);
-		break;
-	case MOXA_GETMSTATUS: {
-		struct mxser_mstatus __user *argm = argp;
-		struct mxser_mstatus tmp;
-		struct moxa_port *p;
-		unsigned int i, j;
-
-		for (i = 0; i < MAX_BOARDS; i++) {
-			p = moxa_boards[i].ports;
-			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
-				struct tty_struct *ttyp;
-				memset(&tmp, 0, sizeof(tmp));
-				spin_lock_bh(&moxa_lock);
-				if (!moxa_boards[i].ready) {
-				        spin_unlock_bh(&moxa_lock);
-					goto copy;
-                                }
-
-				status = MoxaPortLineStatus(p);
-				spin_unlock_bh(&moxa_lock);
-
-				if (status & 1)
-					tmp.cts = 1;
-				if (status & 2)
-					tmp.dsr = 1;
-				if (status & 4)
-					tmp.dcd = 1;
-
-				ttyp = tty_port_tty_get(&p->port);
-				if (!ttyp || !ttyp->termios)
-					tmp.cflag = p->cflag;
-				else
-					tmp.cflag = ttyp->termios->c_cflag;
-				tty_kref_put(tty);
-copy:
-				if (copy_to_user(argm, &tmp, sizeof(tmp)))
-					return -EFAULT;
-			}
-		}
-		break;
-	}
-	case TIOCGSERIAL:
-	        mutex_lock(&ch->port.mutex);
-		ret = moxa_get_serial_info(ch, argp);
-		mutex_unlock(&ch->port.mutex);
-		break;
-	case TIOCSSERIAL:
-	        mutex_lock(&ch->port.mutex);
-		ret = moxa_set_serial_info(ch, argp);
-		mutex_unlock(&ch->port.mutex);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-	return ret;
-}
-
-static int moxa_break_ctl(struct tty_struct *tty, int state)
-{
-	struct moxa_port *port = tty->driver_data;
-
-	moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
-			Magic_code);
-	return 0;
-}
-
-static const struct tty_operations moxa_ops = {
-	.open = moxa_open,
-	.close = moxa_close,
-	.write = moxa_write,
-	.write_room = moxa_write_room,
-	.flush_buffer = moxa_flush_buffer,
-	.chars_in_buffer = moxa_chars_in_buffer,
-	.ioctl = moxa_ioctl,
-	.set_termios = moxa_set_termios,
-	.stop = moxa_stop,
-	.start = moxa_start,
-	.hangup = moxa_hangup,
-	.break_ctl = moxa_break_ctl,
-	.tiocmget = moxa_tiocmget,
-	.tiocmset = moxa_tiocmset,
-};
-
-static const struct tty_port_operations moxa_port_ops = {
-	.carrier_raised = moxa_carrier_raised,
-	.dtr_rts = moxa_dtr_rts,
-	.shutdown = moxa_shutdown,
-};
-
-static struct tty_driver *moxaDriver;
-static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
-
-/*
- * HW init
- */
-
-static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
-{
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		if (model != 1)
-			goto err;
-		break;
-	case MOXA_BOARD_CP204J:
-		if (model != 3)
-			goto err;
-		break;
-	default:
-		if (model != 2)
-			goto err;
-		break;
-	}
-	return 0;
-err:
-	return -EINVAL;
-}
-
-static int moxa_check_fw(const void *ptr)
-{
-	const __le16 *lptr = ptr;
-
-	if (*lptr != cpu_to_le16(0x7980))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
-		size_t len)
-{
-	void __iomem *baseAddr = brd->basemem;
-	u16 tmp;
-
-	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
-	msleep(10);
-	memset_io(baseAddr, 0, 4096);
-	memcpy_toio(baseAddr, buf, len);	/* download BIOS */
-	writeb(0, baseAddr + Control_reg);	/* restart */
-
-	msleep(2000);
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		tmp = readw(baseAddr + C218_key);
-		if (tmp != C218_KeyCode)
-			goto err;
-		break;
-	case MOXA_BOARD_CP204J:
-		tmp = readw(baseAddr + C218_key);
-		if (tmp != CP204J_KeyCode)
-			goto err;
-		break;
-	default:
-		tmp = readw(baseAddr + C320_key);
-		if (tmp != C320_KeyCode)
-			goto err;
-		tmp = readw(baseAddr + C320_status);
-		if (tmp != STS_init) {
-			printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
-					"module not found\n");
-			return -EIO;
-		}
-		break;
-	}
-
-	return 0;
-err:
-	printk(KERN_ERR "MOXA: bios upload failed -- board not found\n");
-	return -EIO;
-}
-
-static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
-		size_t len)
-{
-	void __iomem *baseAddr = brd->basemem;
-
-	if (len < 7168) {
-		printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n");
-		return -EINVAL;
-	}
-
-	writew(len - 7168 - 2, baseAddr + C320bapi_len);
-	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
-	memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
-	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
-	memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
-
-	return 0;
-}
-
-static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
-		size_t len)
-{
-	void __iomem *baseAddr = brd->basemem;
-	const __le16 *uptr = ptr;
-	size_t wlen, len2, j;
-	unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
-	unsigned int i, retry;
-	u16 usum, keycode;
-
-	keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
-				C218_KeyCode;
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_CP204J:
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		key = C218_key;
-		loadbuf = C218_LoadBuf;
-		loadlen = C218DLoad_len;
-		checksum = C218check_sum;
-		checksum_ok = C218chksum_ok;
-		break;
-	default:
-		key = C320_key;
-		keycode = C320_KeyCode;
-		loadbuf = C320_LoadBuf;
-		loadlen = C320DLoad_len;
-		checksum = C320check_sum;
-		checksum_ok = C320chksum_ok;
-		break;
-	}
-
-	usum = 0;
-	wlen = len >> 1;
-	for (i = 0; i < wlen; i++)
-		usum += le16_to_cpu(uptr[i]);
-	retry = 0;
-	do {
-		wlen = len >> 1;
-		j = 0;
-		while (wlen) {
-			len2 = (wlen > 2048) ? 2048 : wlen;
-			wlen -= len2;
-			memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
-			j += len2 << 1;
-
-			writew(len2, baseAddr + loadlen);
-			writew(0, baseAddr + key);
-			for (i = 0; i < 100; i++) {
-				if (readw(baseAddr + key) == keycode)
-					break;
-				msleep(10);
-			}
-			if (readw(baseAddr + key) != keycode)
-				return -EIO;
-		}
-		writew(0, baseAddr + loadlen);
-		writew(usum, baseAddr + checksum);
-		writew(0, baseAddr + key);
-		for (i = 0; i < 100; i++) {
-			if (readw(baseAddr + key) == keycode)
-				break;
-			msleep(10);
-		}
-		retry++;
-	} while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
-	if (readb(baseAddr + checksum_ok) != 1)
-		return -EIO;
-
-	writew(0, baseAddr + key);
-	for (i = 0; i < 600; i++) {
-		if (readw(baseAddr + Magic_no) == Magic_code)
-			break;
-		msleep(10);
-	}
-	if (readw(baseAddr + Magic_no) != Magic_code)
-		return -EIO;
-
-	if (MOXA_IS_320(brd)) {
-		if (brd->busType == MOXA_BUS_TYPE_PCI) {	/* ASIC board */
-			writew(0x3800, baseAddr + TMS320_PORT1);
-			writew(0x3900, baseAddr + TMS320_PORT2);
-			writew(28499, baseAddr + TMS320_CLOCK);
-		} else {
-			writew(0x3200, baseAddr + TMS320_PORT1);
-			writew(0x3400, baseAddr + TMS320_PORT2);
-			writew(19999, baseAddr + TMS320_CLOCK);
-		}
-	}
-	writew(1, baseAddr + Disable_IRQ);
-	writew(0, baseAddr + Magic_no);
-	for (i = 0; i < 500; i++) {
-		if (readw(baseAddr + Magic_no) == Magic_code)
-			break;
-		msleep(10);
-	}
-	if (readw(baseAddr + Magic_no) != Magic_code)
-		return -EIO;
-
-	if (MOXA_IS_320(brd)) {
-		j = readw(baseAddr + Module_cnt);
-		if (j <= 0)
-			return -EIO;
-		brd->numPorts = j * 8;
-		writew(j, baseAddr + Module_no);
-		writew(0, baseAddr + Magic_no);
-		for (i = 0; i < 600; i++) {
-			if (readw(baseAddr + Magic_no) == Magic_code)
-				break;
-			msleep(10);
-		}
-		if (readw(baseAddr + Magic_no) != Magic_code)
-			return -EIO;
-	}
-	brd->intNdx = baseAddr + IRQindex;
-	brd->intPend = baseAddr + IRQpending;
-	brd->intTable = baseAddr + IRQtable;
-
-	return 0;
-}
-
-static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
-		size_t len)
-{
-	void __iomem *ofsAddr, *baseAddr = brd->basemem;
-	struct moxa_port *port;
-	int retval, i;
-
-	if (len % 2) {
-		printk(KERN_ERR "MOXA: bios length is not even\n");
-		return -EINVAL;
-	}
-
-	retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
-	if (retval)
-		return retval;
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-	case MOXA_BOARD_CP204J:
-		port = brd->ports;
-		for (i = 0; i < brd->numPorts; i++, port++) {
-			port->board = brd;
-			port->DCDState = 0;
-			port->tableAddr = baseAddr + Extern_table +
-					Extern_size * i;
-			ofsAddr = port->tableAddr;
-			writew(C218rx_mask, ofsAddr + RX_mask);
-			writew(C218tx_mask, ofsAddr + TX_mask);
-			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
-			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
-
-			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
-			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
-
-		}
-		break;
-	default:
-		port = brd->ports;
-		for (i = 0; i < brd->numPorts; i++, port++) {
-			port->board = brd;
-			port->DCDState = 0;
-			port->tableAddr = baseAddr + Extern_table +
-					Extern_size * i;
-			ofsAddr = port->tableAddr;
-			switch (brd->numPorts) {
-			case 8:
-				writew(C320p8rx_mask, ofsAddr + RX_mask);
-				writew(C320p8tx_mask, ofsAddr + TX_mask);
-				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
-				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
-				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
-
-				break;
-			case 16:
-				writew(C320p16rx_mask, ofsAddr + RX_mask);
-				writew(C320p16tx_mask, ofsAddr + TX_mask);
-				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
-				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
-				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
-				break;
-
-			case 24:
-				writew(C320p24rx_mask, ofsAddr + RX_mask);
-				writew(C320p24tx_mask, ofsAddr + TX_mask);
-				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
-				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
-				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
-				break;
-			case 32:
-				writew(C320p32rx_mask, ofsAddr + RX_mask);
-				writew(C320p32tx_mask, ofsAddr + TX_mask);
-				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
-				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
-				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
-				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
-				break;
-			}
-		}
-		break;
-	}
-	return 0;
-}
-
-static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
-{
-	const void *ptr = fw->data;
-	char rsn[64];
-	u16 lens[5];
-	size_t len;
-	unsigned int a, lenp, lencnt;
-	int ret = -EINVAL;
-	struct {
-		__le32 magic;	/* 0x34303430 */
-		u8 reserved1[2];
-		u8 type;	/* UNIX = 3 */
-		u8 model;	/* C218T=1, C320T=2, CP204=3 */
-		u8 reserved2[8];
-		__le16 len[5];
-	} const *hdr = ptr;
-
-	BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
-
-	if (fw->size < MOXA_FW_HDRLEN) {
-		strcpy(rsn, "too short (even header won't fit)");
-		goto err;
-	}
-	if (hdr->magic != cpu_to_le32(0x30343034)) {
-		sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
-		goto err;
-	}
-	if (hdr->type != 3) {
-		sprintf(rsn, "not for linux, type is %u", hdr->type);
-		goto err;
-	}
-	if (moxa_check_fw_model(brd, hdr->model)) {
-		sprintf(rsn, "not for this card, model is %u", hdr->model);
-		goto err;
-	}
-
-	len = MOXA_FW_HDRLEN;
-	lencnt = hdr->model == 2 ? 5 : 3;
-	for (a = 0; a < ARRAY_SIZE(lens); a++) {
-		lens[a] = le16_to_cpu(hdr->len[a]);
-		if (lens[a] && len + lens[a] <= fw->size &&
-				moxa_check_fw(&fw->data[len]))
-			printk(KERN_WARNING "MOXA firmware: unexpected input "
-				"at offset %u, but going on\n", (u32)len);
-		if (!lens[a] && a < lencnt) {
-			sprintf(rsn, "too few entries in fw file");
-			goto err;
-		}
-		len += lens[a];
-	}
-
-	if (len != fw->size) {
-		sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
-				(u32)len);
-		goto err;
-	}
-
-	ptr += MOXA_FW_HDRLEN;
-	lenp = 0; /* bios */
-
-	strcpy(rsn, "read above");
-
-	ret = moxa_load_bios(brd, ptr, lens[lenp]);
-	if (ret)
-		goto err;
-
-	/* we skip the tty section (lens[1]), since we don't need it */
-	ptr += lens[lenp] + lens[lenp + 1];
-	lenp += 2; /* comm */
-
-	if (hdr->model == 2) {
-		ret = moxa_load_320b(brd, ptr, lens[lenp]);
-		if (ret)
-			goto err;
-		/* skip another tty */
-		ptr += lens[lenp] + lens[lenp + 1];
-		lenp += 2;
-	}
-
-	ret = moxa_load_code(brd, ptr, lens[lenp]);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
-	return ret;
-}
-
-static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
-{
-	const struct firmware *fw;
-	const char *file;
-	struct moxa_port *p;
-	unsigned int i;
-	int ret;
-
-	brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
-			GFP_KERNEL);
-	if (brd->ports == NULL) {
-		printk(KERN_ERR "cannot allocate memory for ports\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
-		tty_port_init(&p->port);
-		p->port.ops = &moxa_port_ops;
-		p->type = PORT_16550A;
-		p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	}
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		file = "c218tunx.cod";
-		break;
-	case MOXA_BOARD_CP204J:
-		file = "cp204unx.cod";
-		break;
-	default:
-		file = "c320tunx.cod";
-		break;
-	}
-
-	ret = request_firmware(&fw, file, dev);
-	if (ret) {
-		printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
-				"you've placed '%s' file into your firmware "
-				"loader directory (e.g. /lib/firmware)\n",
-				file);
-		goto err_free;
-	}
-
-	ret = moxa_load_fw(brd, fw);
-
-	release_firmware(fw);
-
-	if (ret)
-		goto err_free;
-
-	spin_lock_bh(&moxa_lock);
-	brd->ready = 1;
-	if (!timer_pending(&moxaTimer))
-		mod_timer(&moxaTimer, jiffies + HZ / 50);
-	spin_unlock_bh(&moxa_lock);
-
-	return 0;
-err_free:
-	kfree(brd->ports);
-err:
-	return ret;
-}
-
-static void moxa_board_deinit(struct moxa_board_conf *brd)
-{
-	unsigned int a, opened;
-
-	mutex_lock(&moxa_openlock);
-	spin_lock_bh(&moxa_lock);
-	brd->ready = 0;
-	spin_unlock_bh(&moxa_lock);
-
-	/* 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);
-			}
-		}
-	while (1) {
-		opened = 0;
-		for (a = 0; a < brd->numPorts; a++)
-			if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
-				opened++;
-		mutex_unlock(&moxa_openlock);
-		if (!opened)
-			break;
-		msleep(50);
-		mutex_lock(&moxa_openlock);
-	}
-
-	iounmap(brd->basemem);
-	brd->basemem = NULL;
-	kfree(brd->ports);
-}
-
-#ifdef CONFIG_PCI
-static int __devinit moxa_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct moxa_board_conf *board;
-	unsigned int i;
-	int board_type = ent->driver_data;
-	int retval;
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "can't enable pci device\n");
-		goto err;
-	}
-
-	for (i = 0; i < MAX_BOARDS; i++)
-		if (moxa_boards[i].basemem == NULL)
-			break;
-
-	retval = -ENODEV;
-	if (i >= MAX_BOARDS) {
-		dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
-				"found. Board is ignored.\n", MAX_BOARDS);
-		goto err;
-	}
-
-	board = &moxa_boards[i];
-
-	retval = pci_request_region(pdev, 2, "moxa-base");
-	if (retval) {
-		dev_err(&pdev->dev, "can't request pci region 2\n");
-		goto err;
-	}
-
-	board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
-	if (board->basemem == NULL) {
-		dev_err(&pdev->dev, "can't remap io space 2\n");
-		goto err_reg;
-	}
-
-	board->boardType = board_type;
-	switch (board_type) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		board->numPorts = 8;
-		break;
-
-	case MOXA_BOARD_CP204J:
-		board->numPorts = 4;
-		break;
-	default:
-		board->numPorts = 0;
-		break;
-	}
-	board->busType = MOXA_BUS_TYPE_PCI;
-
-	retval = moxa_init_board(board, &pdev->dev);
-	if (retval)
-		goto err_base;
-
-	pci_set_drvdata(pdev, board);
-
-	dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n",
-			moxa_brdname[board_type - 1], board->numPorts);
-
-	return 0;
-err_base:
-	iounmap(board->basemem);
-	board->basemem = NULL;
-err_reg:
-	pci_release_region(pdev, 2);
-err:
-	return retval;
-}
-
-static void __devexit moxa_pci_remove(struct pci_dev *pdev)
-{
-	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
-
-	moxa_board_deinit(brd);
-
-	pci_release_region(pdev, 2);
-}
-
-static struct pci_driver moxa_pci_driver = {
-	.name = "moxa",
-	.id_table = moxa_pcibrds,
-	.probe = moxa_pci_probe,
-	.remove = __devexit_p(moxa_pci_remove)
-};
-#endif /* CONFIG_PCI */
-
-static int __init moxa_init(void)
-{
-	unsigned int isabrds = 0;
-	int retval = 0;
-	struct moxa_board_conf *brd = moxa_boards;
-	unsigned int i;
-
-	printk(KERN_INFO "MOXA Intellio family driver version %s\n",
-			MOXA_VERSION);
-	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
-	if (!moxaDriver)
-		return -ENOMEM;
-
-	moxaDriver->owner = THIS_MODULE;
-	moxaDriver->name = "ttyMX";
-	moxaDriver->major = ttymajor;
-	moxaDriver->minor_start = 0;
-	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
-	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
-	moxaDriver->init_termios = tty_std_termios;
-	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	moxaDriver->init_termios.c_ispeed = 9600;
-	moxaDriver->init_termios.c_ospeed = 9600;
-	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(moxaDriver, &moxa_ops);
-
-	if (tty_register_driver(moxaDriver)) {
-		printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
-		put_tty_driver(moxaDriver);
-		return -1;
-	}
-
-	/* Find the boards defined from module args. */
-
-	for (i = 0; i < MAX_BOARDS; i++) {
-		if (!baseaddr[i])
-			break;
-		if (type[i] == MOXA_BOARD_C218_ISA ||
-				type[i] == MOXA_BOARD_C320_ISA) {
-			pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
-					isabrds + 1, moxa_brdname[type[i] - 1],
-					baseaddr[i]);
-			brd->boardType = type[i];
-			brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
-					numports[i];
-			brd->busType = MOXA_BUS_TYPE_ISA;
-			brd->basemem = ioremap_nocache(baseaddr[i], 0x4000);
-			if (!brd->basemem) {
-				printk(KERN_ERR "MOXA: can't remap %lx\n",
-						baseaddr[i]);
-				continue;
-			}
-			if (moxa_init_board(brd, NULL)) {
-				iounmap(brd->basemem);
-				brd->basemem = NULL;
-				continue;
-			}
-
-			printk(KERN_INFO "MOXA isa board found at 0x%.8lu and "
-					"ready (%u ports, firmware loaded)\n",
-					baseaddr[i], brd->numPorts);
-
-			brd++;
-			isabrds++;
-		}
-	}
-
-#ifdef CONFIG_PCI
-	retval = pci_register_driver(&moxa_pci_driver);
-	if (retval) {
-		printk(KERN_ERR "Can't register MOXA pci driver!\n");
-		if (isabrds)
-			retval = 0;
-	}
-#endif
-
-	return retval;
-}
-
-static void __exit moxa_exit(void)
-{
-	unsigned int i;
-
-#ifdef CONFIG_PCI
-	pci_unregister_driver(&moxa_pci_driver);
-#endif
-
-	for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
-		if (moxa_boards[i].ready)
-			moxa_board_deinit(&moxa_boards[i]);
-
-	del_timer_sync(&moxaTimer);
-
-	if (tty_unregister_driver(moxaDriver))
-		printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
-				"serial driver\n");
-	put_tty_driver(moxaDriver);
-}
-
-module_init(moxa_init);
-module_exit(moxa_exit);
-
-static void moxa_shutdown(struct tty_port *port)
-{
-	struct moxa_port *ch = container_of(port, struct moxa_port, port);
-        MoxaPortDisable(ch);
-	MoxaPortFlushData(ch, 2);
-	clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
-}
-
-static int moxa_carrier_raised(struct tty_port *port)
-{
-	struct moxa_port *ch = container_of(port, struct moxa_port, port);
-	int dcd;
-
-	spin_lock_irq(&port->lock);
-	dcd = ch->DCDState;
-	spin_unlock_irq(&port->lock);
-	return dcd;
-}
-
-static void moxa_dtr_rts(struct tty_port *port, int onoff)
-{
-	struct moxa_port *ch = container_of(port, struct moxa_port, port);
-	MoxaPortLineCtrl(ch, onoff, onoff);
-}
-
-
-static int moxa_open(struct tty_struct *tty, struct file *filp)
-{
-	struct moxa_board_conf *brd;
-	struct moxa_port *ch;
-	int port;
-	int retval;
-
-	port = tty->index;
-	if (port == MAX_PORTS) {
-		return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
-	}
-	if (mutex_lock_interruptible(&moxa_openlock))
-		return -ERESTARTSYS;
-	brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
-	if (!brd->ready) {
-		mutex_unlock(&moxa_openlock);
-		return -ENODEV;
-	}
-
-	if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) {
-		mutex_unlock(&moxa_openlock);
-		return -ENODEV;
-	}
-
-	ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
-	ch->port.count++;
-	tty->driver_data = ch;
-	tty_port_tty_set(&ch->port, tty);
-	mutex_lock(&ch->port.mutex);
-	if (!(ch->port.flags & ASYNC_INITIALIZED)) {
-		ch->statusflags = 0;
-		moxa_set_tty_param(tty, tty->termios);
-		MoxaPortLineCtrl(ch, 1, 1);
-		MoxaPortEnable(ch);
-		MoxaSetFifo(ch, ch->type == PORT_16550A);
-		ch->port.flags |= ASYNC_INITIALIZED;
-	}
-	mutex_unlock(&ch->port.mutex);
-	mutex_unlock(&moxa_openlock);
-
-	retval = tty_port_block_til_ready(&ch->port, tty, filp);
-	if (retval == 0)
-	        set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags);
-	return retval;
-}
-
-static void moxa_close(struct tty_struct *tty, struct file *filp)
-{
-	struct moxa_port *ch = tty->driver_data;
-	ch->cflag = tty->termios->c_cflag;
-	tty_port_close(&ch->port, tty, filp);
-}
-
-static int moxa_write(struct tty_struct *tty,
-		      const unsigned char *buf, int count)
-{
-	struct moxa_port *ch = tty->driver_data;
-	int len;
-
-	if (ch == NULL)
-		return 0;
-
-	spin_lock_bh(&moxa_lock);
-	len = MoxaPortWriteData(tty, buf, count);
-	spin_unlock_bh(&moxa_lock);
-
-	set_bit(LOWWAIT, &ch->statusflags);
-	return len;
-}
-
-static int moxa_write_room(struct tty_struct *tty)
-{
-	struct moxa_port *ch;
-
-	if (tty->stopped)
-		return 0;
-	ch = tty->driver_data;
-	if (ch == NULL)
-		return 0;
-	return MoxaPortTxFree(ch);
-}
-
-static void moxa_flush_buffer(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-	MoxaPortFlushData(ch, 1);
-	tty_wakeup(tty);
-}
-
-static int moxa_chars_in_buffer(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-	int chars;
-
-	chars = MoxaPortTxQueue(ch);
-	if (chars)
-		/*
-		 * Make it possible to wakeup anything waiting for output
-		 * in tty_ioctl.c, etc.
-		 */
-        	set_bit(EMPTYWAIT, &ch->statusflags);
-	return chars;
-}
-
-static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct moxa_port *ch = tty->driver_data;
-	int flag = 0, dtr, rts;
-
-	MoxaPortGetLineOut(ch, &dtr, &rts);
-	if (dtr)
-		flag |= TIOCM_DTR;
-	if (rts)
-		flag |= TIOCM_RTS;
-	dtr = MoxaPortLineStatus(ch);
-	if (dtr & 1)
-		flag |= TIOCM_CTS;
-	if (dtr & 2)
-		flag |= TIOCM_DSR;
-	if (dtr & 4)
-		flag |= TIOCM_CD;
-	return flag;
-}
-
-static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear)
-{
-	struct moxa_port *ch;
-	int port;
-	int dtr, rts;
-
-	port = tty->index;
-	mutex_lock(&moxa_openlock);
-	ch = tty->driver_data;
-	if (!ch) {
-		mutex_unlock(&moxa_openlock);
-		return -EINVAL;
-	}
-
-	MoxaPortGetLineOut(ch, &dtr, &rts);
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-	MoxaPortLineCtrl(ch, dtr, rts);
-	mutex_unlock(&moxa_openlock);
-	return 0;
-}
-
-static void moxa_set_termios(struct tty_struct *tty,
-		struct ktermios *old_termios)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-	moxa_set_tty_param(tty, old_termios);
-	if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
-		wake_up_interruptible(&ch->port.open_wait);
-}
-
-static void moxa_stop(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-	MoxaPortTxDisable(ch);
-	set_bit(TXSTOPPED, &ch->statusflags);
-}
-
-
-static void moxa_start(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-
-	if (!(ch->statusflags & TXSTOPPED))
-		return;
-
-	MoxaPortTxEnable(ch);
-	clear_bit(TXSTOPPED, &ch->statusflags);
-}
-
-static void moxa_hangup(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-	tty_port_hangup(&ch->port);
-}
-
-static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
-{
-	struct tty_struct *tty;
-	unsigned long flags;
-	dcd = !!dcd;
-
-	spin_lock_irqsave(&p->port.lock, flags);
-	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);
-	}
-	else
-		spin_unlock_irqrestore(&p->port.lock, flags);
-}
-
-static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
-		u16 __iomem *ip)
-{
-	struct tty_struct *tty = tty_port_tty_get(&p->port);
-	void __iomem *ofsAddr;
-	unsigned int inited = p->port.flags & ASYNC_INITIALIZED;
-	u16 intr;
-
-	if (tty) {
-		if (test_bit(EMPTYWAIT, &p->statusflags) &&
-				MoxaPortTxQueue(p) == 0) {
-			clear_bit(EMPTYWAIT, &p->statusflags);
-			tty_wakeup(tty);
-		}
-		if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped &&
-				MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
-			clear_bit(LOWWAIT, &p->statusflags);
-			tty_wakeup(tty);
-		}
-
-		if (inited && !test_bit(TTY_THROTTLED, &tty->flags) &&
-				MoxaPortRxQueue(p) > 0) { /* RX */
-			MoxaPortReadData(p);
-			tty_schedule_flip(tty);
-		}
-	} else {
-		clear_bit(EMPTYWAIT, &p->statusflags);
-		MoxaPortFlushData(p, 0); /* flush RX */
-	}
-
-	if (!handle) /* nothing else to do */
-		goto put;
-
-	intr = readw(ip); /* port irq status */
-	if (intr == 0)
-		goto put;
-
-	writew(0, ip); /* ACK port */
-	ofsAddr = p->tableAddr;
-	if (intr & IntrTx) /* disable tx intr */
-		writew(readw(ofsAddr + HostStat) & ~WakeupTx,
-				ofsAddr + HostStat);
-
-	if (!inited)
-		goto put;
-
-	if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
-		tty_insert_flip_char(tty, 0, TTY_BREAK);
-		tty_schedule_flip(tty);
-	}
-
-	if (intr & IntrLine)
-		moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
-put:
-	tty_kref_put(tty);
-
-	return 0;
-}
-
-static void moxa_poll(unsigned long ignored)
-{
-	struct moxa_board_conf *brd;
-	u16 __iomem *ip;
-	unsigned int card, port, served = 0;
-
-	spin_lock(&moxa_lock);
-	for (card = 0; card < MAX_BOARDS; card++) {
-		brd = &moxa_boards[card];
-		if (!brd->ready)
-			continue;
-
-		served++;
-
-		ip = NULL;
-		if (readb(brd->intPend) == 0xff)
-			ip = brd->intTable + readb(brd->intNdx);
-
-		for (port = 0; port < brd->numPorts; port++)
-			moxa_poll_port(&brd->ports[port], !!ip, ip + port);
-
-		if (ip)
-			writeb(0, brd->intPend); /* ACK */
-
-		if (moxaLowWaterChk) {
-			struct moxa_port *p = brd->ports;
-			for (port = 0; port < brd->numPorts; port++, p++)
-				if (p->lowChkFlag) {
-					p->lowChkFlag = 0;
-					moxa_low_water_check(p->tableAddr);
-				}
-		}
-	}
-	moxaLowWaterChk = 0;
-
-	if (served)
-		mod_timer(&moxaTimer, jiffies + HZ / 50);
-	spin_unlock(&moxa_lock);
-}
-
-/******************************************************************************/
-
-static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	register struct ktermios *ts = tty->termios;
-	struct moxa_port *ch = tty->driver_data;
-	int rts, cts, txflow, rxflow, xany, baud;
-
-	rts = cts = txflow = rxflow = xany = 0;
-	if (ts->c_cflag & CRTSCTS)
-		rts = cts = 1;
-	if (ts->c_iflag & IXON)
-		txflow = 1;
-	if (ts->c_iflag & IXOFF)
-		rxflow = 1;
-	if (ts->c_iflag & IXANY)
-		xany = 1;
-
-	/* Clear the features we don't support */
-	ts->c_cflag &= ~CMSPAR;
-	MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
-	baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
-	if (baud == -1)
-		baud = tty_termios_baud_rate(old_termios);
-	/* Not put the baud rate into the termios data */
-	tty_encode_baud_rate(tty, baud, baud);
-}
-
-/*****************************************************************************
- *	Driver level functions: 					     *
- *****************************************************************************/
-
-static void MoxaPortFlushData(struct moxa_port *port, int mode)
-{
-	void __iomem *ofsAddr;
-	if (mode < 0 || mode > 2)
-		return;
-	ofsAddr = port->tableAddr;
-	moxafunc(ofsAddr, FC_FlushQueue, mode);
-	if (mode != 1) {
-		port->lowChkFlag = 0;
-		moxa_low_water_check(ofsAddr);
-	}
-}
-
-/*
- *    Moxa Port Number Description:
- *
- *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
- *      the port number using in MOXA driver functions will be 0 to 31 for
- *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
- *      to 127 for fourth. For example, if you setup three MOXA boards,
- *      first board is C218, second board is C320-16 and third board is
- *      C320-32. The port number of first board (C218 - 8 ports) is from
- *      0 to 7. The port number of second board (C320 - 16 ports) is form
- *      32 to 47. The port number of third board (C320 - 32 ports) is from
- *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
- *      127 will be invalid.
- *
- *
- *      Moxa Functions Description:
- *
- *      Function 1:     Driver initialization routine, this routine must be
- *                      called when initialized driver.
- *      Syntax:
- *      void MoxaDriverInit();
- *
- *
- *      Function 2:     Moxa driver private IOCTL command processing.
- *      Syntax:
- *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
- *
- *           unsigned int cmd   : IOCTL command
- *           unsigned long arg  : IOCTL argument
- *           int port           : port number (0 - 127)
- *
- *           return:    0  (OK)
- *                      -EINVAL
- *                      -ENOIOCTLCMD
- *
- *
- *      Function 6:     Enable this port to start Tx/Rx data.
- *      Syntax:
- *      void MoxaPortEnable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 7:     Disable this port
- *      Syntax:
- *      void MoxaPortDisable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 10:    Setting baud rate of this port.
- *      Syntax:
- *      speed_t MoxaPortSetBaud(int port, speed_t baud);
- *           int port           : port number (0 - 127)
- *           long baud          : baud rate (50 - 115200)
- *
- *           return:    0       : this port is invalid or baud < 50
- *                      50 - 115200 : the real baud rate set to the port, if
- *                                    the argument baud is large than maximun
- *                                    available baud rate, the real setting
- *                                    baud rate will be the maximun baud rate.
- *
- *
- *      Function 12:    Configure the port.
- *      Syntax:
- *      int  MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
- *           int port           : port number (0 - 127)
- *           struct ktermios * termio : termio structure pointer
- *	     speed_t baud	: baud rate
- *
- *           return:    -1      : this port is invalid or termio == NULL
- *                      0       : setting O.K.
- *
- *
- *      Function 13:    Get the DTR/RTS state of this port.
- *      Syntax:
- *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
- *           int port           : port number (0 - 127)
- *           int * dtrState     : pointer to INT to receive the current DTR
- *                                state. (if NULL, this function will not
- *                                write to this address)
- *           int * rtsState     : pointer to INT to receive the current RTS
- *                                state. (if NULL, this function will not
- *                                write to this address)
- *
- *           return:    -1      : this port is invalid
- *                      0       : O.K.
- *
- *
- *      Function 14:    Setting the DTR/RTS output state of this port.
- *      Syntax:
- *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
- *           int port           : port number (0 - 127)
- *           int dtrState       : DTR output state (0: off, 1: on)
- *           int rtsState       : RTS output state (0: off, 1: on)
- *
- *
- *      Function 15:    Setting the flow control of this port.
- *      Syntax:
- *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
- *                            int txFlow,int xany);
- *           int port           : port number (0 - 127)
- *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
- *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
- *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
- *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
- *           int xany           : S/W XANY flow control (0: no, 1: yes)
- *
- *
- *      Function 16:    Get ths line status of this port
- *      Syntax:
- *      int  MoxaPortLineStatus(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    Bit 0 - CTS state (0: off, 1: on)
- *                      Bit 1 - DSR state (0: off, 1: on)
- *                      Bit 2 - DCD state (0: off, 1: on)
- *
- *
- *      Function 19:    Flush the Rx/Tx buffer data of this port.
- *      Syntax:
- *      void MoxaPortFlushData(int port, int mode);
- *           int port           : port number (0 - 127)
- *           int mode    
- *                      0       : flush the Rx buffer 
- *                      1       : flush the Tx buffer 
- *                      2       : flush the Rx and Tx buffer 
- *
- *
- *      Function 20:    Write data.
- *      Syntax:
- *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
- *           int port           : port number (0 - 127)
- *           unsigned char * buffer     : pointer to write data buffer.
- *           int length         : write data length
- *
- *           return:    0 - length      : real write data length
- *
- *
- *      Function 21:    Read data.
- *      Syntax:
- *      int  MoxaPortReadData(int port, struct tty_struct *tty);
- *           int port           : port number (0 - 127)
- *	     struct tty_struct *tty : tty for data
- *
- *           return:    0 - length      : real read data length
- *
- *
- *      Function 24:    Get the Tx buffer current queued data bytes
- *      Syntax:
- *      int  MoxaPortTxQueue(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Tx buffer current queued data bytes
- *
- *
- *      Function 25:    Get the Tx buffer current free space
- *      Syntax:
- *      int  MoxaPortTxFree(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Tx buffer current free space
- *
- *
- *      Function 26:    Get the Rx buffer current queued data bytes
- *      Syntax:
- *      int  MoxaPortRxQueue(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Rx buffer current queued data bytes
- *
- *
- *      Function 28:    Disable port data transmission.
- *      Syntax:
- *      void MoxaPortTxDisable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 29:    Enable port data transmission.
- *      Syntax:
- *      void MoxaPortTxEnable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 31:    Get the received BREAK signal count and reset it.
- *      Syntax:
- *      int  MoxaPortResetBrkCnt(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0 - ..  : BREAK signal count
- *
- *
- */
-
-static void MoxaPortEnable(struct moxa_port *port)
-{
-	void __iomem *ofsAddr;
-	u16 lowwater = 512;
-
-	ofsAddr = port->tableAddr;
-	writew(lowwater, ofsAddr + Low_water);
-	if (MOXA_IS_320(port->board))
-		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
-	else
-		writew(readw(ofsAddr + HostStat) | WakeupBreak,
-				ofsAddr + HostStat);
-
-	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
-	moxafunc(ofsAddr, FC_FlushQueue, 2);
-
-	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
-	MoxaPortLineStatus(port);
-}
-
-static void MoxaPortDisable(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-
-	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
-	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
-	writew(0, ofsAddr + HostStat);
-	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
-}
-
-static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	unsigned int clock, val;
-	speed_t max;
-
-	max = MOXA_IS_320(port->board) ? 460800 : 921600;
-	if (baud < 50)
-		return 0;
-	if (baud > max)
-		baud = max;
-	clock = 921600;
-	val = clock / baud;
-	moxafunc(ofsAddr, FC_SetBaud, val);
-	baud = clock / val;
-	return baud;
-}
-
-static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
-		speed_t baud)
-{
-	void __iomem *ofsAddr;
-	tcflag_t cflag;
-	tcflag_t mode = 0;
-
-	ofsAddr = port->tableAddr;
-	cflag = termio->c_cflag;	/* termio->c_cflag */
-
-	mode = termio->c_cflag & CSIZE;
-	if (mode == CS5)
-		mode = MX_CS5;
-	else if (mode == CS6)
-		mode = MX_CS6;
-	else if (mode == CS7)
-		mode = MX_CS7;
-	else if (mode == CS8)
-		mode = MX_CS8;
-
-	if (termio->c_cflag & CSTOPB) {
-		if (mode == MX_CS5)
-			mode |= MX_STOP15;
-		else
-			mode |= MX_STOP2;
-	} else
-		mode |= MX_STOP1;
-
-	if (termio->c_cflag & PARENB) {
-		if (termio->c_cflag & PARODD)
-			mode |= MX_PARODD;
-		else
-			mode |= MX_PAREVEN;
-	} else
-		mode |= MX_PARNONE;
-
-	moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
-
-	if (MOXA_IS_320(port->board) && baud >= 921600)
-		return -1;
-
-	baud = MoxaPortSetBaud(port, baud);
-
-	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
-	        spin_lock_irq(&moxafunc_lock);
-		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
-		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
-		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
-		moxa_wait_finish(ofsAddr);
-		spin_unlock_irq(&moxafunc_lock);
-
-	}
-	return baud;
-}
-
-static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
-		int *rtsState)
-{
-	if (dtrState)
-		*dtrState = !!(port->lineCtrl & DTR_ON);
-	if (rtsState)
-		*rtsState = !!(port->lineCtrl & RTS_ON);
-
-	return 0;
-}
-
-static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
-{
-	u8 mode = 0;
-
-	if (dtr)
-		mode |= DTR_ON;
-	if (rts)
-		mode |= RTS_ON;
-	port->lineCtrl = mode;
-	moxafunc(port->tableAddr, FC_LineControl, mode);
-}
-
-static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
-		int txflow, int rxflow, int txany)
-{
-	int mode = 0;
-
-	if (rts)
-		mode |= RTS_FlowCtl;
-	if (cts)
-		mode |= CTS_FlowCtl;
-	if (txflow)
-		mode |= Tx_FlowCtl;
-	if (rxflow)
-		mode |= Rx_FlowCtl;
-	if (txany)
-		mode |= IXM_IXANY;
-	moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
-}
-
-static int MoxaPortLineStatus(struct moxa_port *port)
-{
-	void __iomem *ofsAddr;
-	int val;
-
-	ofsAddr = port->tableAddr;
-	if (MOXA_IS_320(port->board))
-		val = moxafuncret(ofsAddr, FC_LineStatus, 0);
-	else
-		val = readw(ofsAddr + FlagStat) >> 4;
-	val &= 0x0B;
-	if (val & 8)
-		val |= 4;
-	moxa_new_dcdstate(port, val & 8);
-	val &= 7;
-	return val;
-}
-
-static int MoxaPortWriteData(struct tty_struct *tty,
-		const unsigned char *buffer, int len)
-{
-	struct moxa_port *port = tty->driver_data;
-	void __iomem *baseAddr, *ofsAddr, *ofs;
-	unsigned int c, total;
-	u16 head, tail, tx_mask, spage, epage;
-	u16 pageno, pageofs, bufhead;
-
-	ofsAddr = port->tableAddr;
-	baseAddr = port->board->basemem;
-	tx_mask = readw(ofsAddr + TX_mask);
-	spage = readw(ofsAddr + Page_txb);
-	epage = readw(ofsAddr + EndPage_txb);
-	tail = readw(ofsAddr + TXwptr);
-	head = readw(ofsAddr + TXrptr);
-	c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
-	if (c > len)
-		c = len;
-	moxaLog.txcnt[port->port.tty->index] += c;
-	total = c;
-	if (spage == epage) {
-		bufhead = readw(ofsAddr + Ofs_txb);
-		writew(spage, baseAddr + Control_reg);
-		while (c > 0) {
-			if (head > tail)
-				len = head - tail - 1;
-			else
-				len = tx_mask + 1 - tail;
-			len = (c > len) ? len : c;
-			ofs = baseAddr + DynPage_addr + bufhead + tail;
-			memcpy_toio(ofs, buffer, len);
-			buffer += len;
-			tail = (tail + len) & tx_mask;
-			c -= len;
-		}
-	} else {
-		pageno = spage + (tail >> 13);
-		pageofs = tail & Page_mask;
-		while (c > 0) {
-			len = Page_size - pageofs;
-			if (len > c)
-				len = c;
-			writeb(pageno, baseAddr + Control_reg);
-			ofs = baseAddr + DynPage_addr + pageofs;
-			memcpy_toio(ofs, buffer, len);
-			buffer += len;
-			if (++pageno == epage)
-				pageno = spage;
-			pageofs = 0;
-			c -= len;
-		}
-		tail = (tail + total) & tx_mask;
-	}
-	writew(tail, ofsAddr + TXwptr);
-	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
-	return total;
-}
-
-static int MoxaPortReadData(struct moxa_port *port)
-{
-	struct tty_struct *tty = port->port.tty;
-	unsigned char *dst;
-	void __iomem *baseAddr, *ofsAddr, *ofs;
-	unsigned int count, len, total;
-	u16 tail, rx_mask, spage, epage;
-	u16 pageno, pageofs, bufhead, head;
-
-	ofsAddr = port->tableAddr;
-	baseAddr = port->board->basemem;
-	head = readw(ofsAddr + RXrptr);
-	tail = readw(ofsAddr + RXwptr);
-	rx_mask = readw(ofsAddr + RX_mask);
-	spage = readw(ofsAddr + Page_rxb);
-	epage = readw(ofsAddr + EndPage_rxb);
-	count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
-	if (count == 0)
-		return 0;
-
-	total = count;
-	moxaLog.rxcnt[tty->index] += total;
-	if (spage == epage) {
-		bufhead = readw(ofsAddr + Ofs_rxb);
-		writew(spage, baseAddr + Control_reg);
-		while (count > 0) {
-			ofs = baseAddr + DynPage_addr + bufhead + head;
-			len = (tail >= head) ? (tail - head) :
-					(rx_mask + 1 - head);
-			len = tty_prepare_flip_string(tty, &dst,
-					min(len, count));
-			memcpy_fromio(dst, ofs, len);
-			head = (head + len) & rx_mask;
-			count -= len;
-		}
-	} else {
-		pageno = spage + (head >> 13);
-		pageofs = head & Page_mask;
-		while (count > 0) {
-			writew(pageno, baseAddr + Control_reg);
-			ofs = baseAddr + DynPage_addr + pageofs;
-			len = tty_prepare_flip_string(tty, &dst,
-					min(Page_size - pageofs, count));
-			memcpy_fromio(dst, ofs, len);
-
-			count -= len;
-			pageofs = (pageofs + len) & Page_mask;
-			if (pageofs == 0 && ++pageno == epage)
-				pageno = spage;
-		}
-		head = (head + total) & rx_mask;
-	}
-	writew(head, ofsAddr + RXrptr);
-	if (readb(ofsAddr + FlagStat) & Xoff_state) {
-		moxaLowWaterChk = 1;
-		port->lowChkFlag = 1;
-	}
-	return total;
-}
-
-
-static int MoxaPortTxQueue(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	u16 rptr, wptr, mask;
-
-	rptr = readw(ofsAddr + TXrptr);
-	wptr = readw(ofsAddr + TXwptr);
-	mask = readw(ofsAddr + TX_mask);
-	return (wptr - rptr) & mask;
-}
-
-static int MoxaPortTxFree(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	u16 rptr, wptr, mask;
-
-	rptr = readw(ofsAddr + TXrptr);
-	wptr = readw(ofsAddr + TXwptr);
-	mask = readw(ofsAddr + TX_mask);
-	return mask - ((wptr - rptr) & mask);
-}
-
-static int MoxaPortRxQueue(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	u16 rptr, wptr, mask;
-
-	rptr = readw(ofsAddr + RXrptr);
-	wptr = readw(ofsAddr + RXwptr);
-	mask = readw(ofsAddr + RX_mask);
-	return (wptr - rptr) & mask;
-}
-
-static void MoxaPortTxDisable(struct moxa_port *port)
-{
-	moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
-}
-
-static void MoxaPortTxEnable(struct moxa_port *port)
-{
-	moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
-}
-
-static int moxa_get_serial_info(struct moxa_port *info,
-		struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp = {
-		.type = info->type,
-		.line = info->port.tty->index,
-		.flags = info->port.flags,
-		.baud_base = 921600,
-		.close_delay = info->port.close_delay
-	};
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-
-static int moxa_set_serial_info(struct moxa_port *info,
-		struct serial_struct __user *new_info)
-{
-	struct serial_struct new_serial;
-
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-
-	if (new_serial.irq != 0 || new_serial.port != 0 ||
-			new_serial.custom_divisor != 0 ||
-			new_serial.baud_base != 921600)
-		return -EPERM;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (info->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-	} else
-		info->port.close_delay = new_serial.close_delay * HZ / 100;
-
-	new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
-	new_serial.flags |= (info->port.flags & ASYNC_FLAGS);
-
-	MoxaSetFifo(info, new_serial.type == PORT_16550A);
-
-	info->type = new_serial.type;
-	return 0;
-}
-
-
-
-/*****************************************************************************
- *	Static local functions: 					     *
- *****************************************************************************/
-
-static void MoxaSetFifo(struct moxa_port *port, int enable)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-
-	if (!enable) {
-		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
-		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
-	} else {
-		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
-		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
-	}
-}
diff --git a/drivers/char/moxa.h b/drivers/char/moxa.h
deleted file mode 100644
index 87d16ce..0000000
--- a/drivers/char/moxa.h
+++ /dev/null
@@ -1,304 +0,0 @@
-#ifndef MOXA_H_FILE
-#define MOXA_H_FILE
-
-#define	MOXA		0x400
-#define MOXA_GET_IQUEUE 	(MOXA + 1)	/* get input buffered count */
-#define MOXA_GET_OQUEUE 	(MOXA + 2)	/* get output buffered count */
-#define MOXA_GETDATACOUNT       (MOXA + 23)
-#define MOXA_GET_IOQUEUE	(MOXA + 27)
-#define MOXA_FLUSH_QUEUE	(MOXA + 28)
-#define MOXA_GETMSTATUS         (MOXA + 65)
-
-/*
- *    System Configuration
- */
-
-#define Magic_code	0x404
-
-/*
- *    for C218 BIOS initialization
- */
-#define C218_ConfBase	0x800
-#define C218_status	(C218_ConfBase + 0)	/* BIOS running status    */
-#define C218_diag	(C218_ConfBase + 2)	/* diagnostic status      */
-#define C218_key	(C218_ConfBase + 4)	/* WORD (0x218 for C218) */
-#define C218DLoad_len	(C218_ConfBase + 6)	/* WORD           */
-#define C218check_sum	(C218_ConfBase + 8)	/* BYTE           */
-#define C218chksum_ok	(C218_ConfBase + 0x0a)	/* BYTE (1:ok)            */
-#define C218_TestRx	(C218_ConfBase + 0x10)	/* 8 bytes for 8 ports    */
-#define C218_TestTx	(C218_ConfBase + 0x18)	/* 8 bytes for 8 ports    */
-#define C218_RXerr	(C218_ConfBase + 0x20)	/* 8 bytes for 8 ports    */
-#define C218_ErrFlag	(C218_ConfBase + 0x28)	/* 8 bytes for 8 ports    */
-
-#define C218_LoadBuf	0x0F00
-#define C218_KeyCode	0x218
-#define CP204J_KeyCode	0x204
-
-/*
- *    for C320 BIOS initialization
- */
-#define C320_ConfBase	0x800
-#define C320_LoadBuf	0x0f00
-#define STS_init	0x05	/* for C320_status        */
-
-#define C320_status	C320_ConfBase + 0	/* BIOS running status    */
-#define C320_diag	C320_ConfBase + 2	/* diagnostic status      */
-#define C320_key	C320_ConfBase + 4	/* WORD (0320H for C320) */
-#define C320DLoad_len	C320_ConfBase + 6	/* WORD           */
-#define C320check_sum	C320_ConfBase + 8	/* WORD           */
-#define C320chksum_ok	C320_ConfBase + 0x0a	/* WORD (1:ok)            */
-#define C320bapi_len	C320_ConfBase + 0x0c	/* WORD           */
-#define C320UART_no	C320_ConfBase + 0x0e	/* WORD           */
-
-#define C320_KeyCode	0x320
-
-#define FixPage_addr	0x0000	/* starting addr of static page  */
-#define DynPage_addr	0x2000	/* starting addr of dynamic page */
-#define C218_start	0x3000	/* starting addr of C218 BIOS prg */
-#define Control_reg	0x1ff0	/* select page and reset control */
-#define HW_reset	0x80
-
-/*
- *    Function Codes
- */
-#define FC_CardReset	0x80
-#define FC_ChannelReset 1	/* C320 firmware not supported */
-#define FC_EnableCH	2
-#define FC_DisableCH	3
-#define FC_SetParam	4
-#define FC_SetMode	5
-#define FC_SetRate	6
-#define FC_LineControl	7
-#define FC_LineStatus	8
-#define FC_XmitControl	9
-#define FC_FlushQueue	10
-#define FC_SendBreak	11
-#define FC_StopBreak	12
-#define FC_LoopbackON	13
-#define FC_LoopbackOFF	14
-#define FC_ClrIrqTable	15
-#define FC_SendXon	16
-#define FC_SetTermIrq	17	/* C320 firmware not supported */
-#define FC_SetCntIrq	18	/* C320 firmware not supported */
-#define FC_SetBreakIrq	19
-#define FC_SetLineIrq	20
-#define FC_SetFlowCtl	21
-#define FC_GenIrq	22
-#define FC_InCD180	23
-#define FC_OutCD180	24
-#define FC_InUARTreg	23
-#define FC_OutUARTreg	24
-#define FC_SetXonXoff	25
-#define FC_OutCD180CCR	26
-#define FC_ExtIQueue	27
-#define FC_ExtOQueue	28
-#define FC_ClrLineIrq	29
-#define FC_HWFlowCtl	30
-#define FC_GetClockRate 35
-#define FC_SetBaud	36
-#define FC_SetDataMode  41
-#define FC_GetCCSR      43
-#define FC_GetDataError 45
-#define FC_RxControl	50
-#define FC_ImmSend	51
-#define FC_SetXonState	52
-#define FC_SetXoffState	53
-#define FC_SetRxFIFOTrig 54
-#define FC_SetTxFIFOCnt 55
-#define FC_UnixRate	56
-#define FC_UnixResetTimer 57
-
-#define	RxFIFOTrig1	0
-#define	RxFIFOTrig4	1
-#define	RxFIFOTrig8	2
-#define	RxFIFOTrig14	3
-
-/*
- *    Dual-Ported RAM
- */
-#define DRAM_global	0
-#define INT_data	(DRAM_global + 0)
-#define Config_base	(DRAM_global + 0x108)
-
-#define IRQindex	(INT_data + 0)
-#define IRQpending	(INT_data + 4)
-#define IRQtable	(INT_data + 8)
-
-/*
- *    Interrupt Status
- */
-#define IntrRx		0x01	/* receiver data O.K.             */
-#define IntrTx		0x02	/* transmit buffer empty  */
-#define IntrFunc	0x04	/* function complete              */
-#define IntrBreak	0x08	/* received break         */
-#define IntrLine	0x10	/* line status change
-				   for transmitter                */
-#define IntrIntr	0x20	/* received INTR code             */
-#define IntrQuit	0x40	/* received QUIT code             */
-#define IntrEOF 	0x80	/* received EOF code              */
-
-#define IntrRxTrigger 	0x100	/* rx data count reach tigger value */
-#define IntrTxTrigger 	0x200	/* tx data count below trigger value */
-
-#define Magic_no	(Config_base + 0)
-#define Card_model_no	(Config_base + 2)
-#define Total_ports	(Config_base + 4)
-#define Module_cnt	(Config_base + 8)
-#define Module_no	(Config_base + 10)
-#define Timer_10ms	(Config_base + 14)
-#define Disable_IRQ	(Config_base + 20)
-#define TMS320_PORT1	(Config_base + 22)
-#define TMS320_PORT2	(Config_base + 24)
-#define TMS320_CLOCK	(Config_base + 26)
-
-/*
- *    DATA BUFFER in DRAM
- */
-#define Extern_table	0x400	/* Base address of the external table
-				   (24 words *    64) total 3K bytes
-				   (24 words * 128) total 6K bytes */
-#define Extern_size	0x60	/* 96 bytes                       */
-#define RXrptr		0x00	/* read pointer for RX buffer     */
-#define RXwptr		0x02	/* write pointer for RX buffer    */
-#define TXrptr		0x04	/* read pointer for TX buffer     */
-#define TXwptr		0x06	/* write pointer for TX buffer    */
-#define HostStat	0x08	/* IRQ flag and general flag      */
-#define FlagStat	0x0A
-#define FlowControl	0x0C	/* B7 B6 B5 B4 B3 B2 B1 B0              */
-				/*  x  x  x  x  |  |  |  |            */
-				/*              |  |  |  + CTS flow   */
-				/*              |  |  +--- RTS flow   */
-				/*              |  +------ TX Xon/Xoff */
-				/*              +--------- RX Xon/Xoff */
-#define Break_cnt	0x0E	/* received break count   */
-#define CD180TXirq	0x10	/* if non-0: enable TX irq        */
-#define RX_mask 	0x12
-#define TX_mask 	0x14
-#define Ofs_rxb 	0x16
-#define Ofs_txb 	0x18
-#define Page_rxb	0x1A
-#define Page_txb	0x1C
-#define EndPage_rxb	0x1E
-#define EndPage_txb	0x20
-#define Data_error	0x22
-#define RxTrigger	0x28
-#define TxTrigger	0x2a
-
-#define rRXwptr 	0x34
-#define Low_water	0x36
-
-#define FuncCode	0x40
-#define FuncArg 	0x42
-#define FuncArg1	0x44
-
-#define C218rx_size	0x2000	/* 8K bytes */
-#define C218tx_size	0x8000	/* 32K bytes */
-
-#define C218rx_mask	(C218rx_size - 1)
-#define C218tx_mask	(C218tx_size - 1)
-
-#define C320p8rx_size	0x2000
-#define C320p8tx_size	0x8000
-#define C320p8rx_mask	(C320p8rx_size - 1)
-#define C320p8tx_mask	(C320p8tx_size - 1)
-
-#define C320p16rx_size	0x2000
-#define C320p16tx_size	0x4000
-#define C320p16rx_mask	(C320p16rx_size - 1)
-#define C320p16tx_mask	(C320p16tx_size - 1)
-
-#define C320p24rx_size	0x2000
-#define C320p24tx_size	0x2000
-#define C320p24rx_mask	(C320p24rx_size - 1)
-#define C320p24tx_mask	(C320p24tx_size - 1)
-
-#define C320p32rx_size	0x1000
-#define C320p32tx_size	0x1000
-#define C320p32rx_mask	(C320p32rx_size - 1)
-#define C320p32tx_mask	(C320p32tx_size - 1)
-
-#define Page_size	0x2000U
-#define Page_mask	(Page_size - 1)
-#define C218rx_spage	3
-#define C218tx_spage	4
-#define C218rx_pageno	1
-#define C218tx_pageno	4
-#define C218buf_pageno	5
-
-#define C320p8rx_spage	3
-#define C320p8tx_spage	4
-#define C320p8rx_pgno	1
-#define C320p8tx_pgno	4
-#define C320p8buf_pgno	5
-
-#define C320p16rx_spage 3
-#define C320p16tx_spage 4
-#define C320p16rx_pgno	1
-#define C320p16tx_pgno	2
-#define C320p16buf_pgno 3
-
-#define C320p24rx_spage 3
-#define C320p24tx_spage 4
-#define C320p24rx_pgno	1
-#define C320p24tx_pgno	1
-#define C320p24buf_pgno 2
-
-#define C320p32rx_spage 3
-#define C320p32tx_ofs	C320p32rx_size
-#define C320p32tx_spage 3
-#define C320p32buf_pgno 1
-
-/*
- *    Host Status
- */
-#define WakeupRx	0x01
-#define WakeupTx	0x02
-#define WakeupBreak	0x08
-#define WakeupLine	0x10
-#define WakeupIntr	0x20
-#define WakeupQuit	0x40
-#define WakeupEOF	0x80	/* used in VTIME control */
-#define WakeupRxTrigger	0x100
-#define WakeupTxTrigger	0x200
-/*
- *    Flag status
- */
-#define Rx_over		0x01
-#define Xoff_state	0x02
-#define Tx_flowOff	0x04
-#define Tx_enable	0x08
-#define CTS_state	0x10
-#define DSR_state	0x20
-#define DCD_state	0x80
-/*
- *    FlowControl
- */
-#define CTS_FlowCtl	1
-#define RTS_FlowCtl	2
-#define Tx_FlowCtl	4
-#define Rx_FlowCtl	8
-#define IXM_IXANY	0x10
-
-#define LowWater	128
-
-#define DTR_ON		1
-#define RTS_ON		2
-#define CTS_ON		1
-#define DSR_ON		2
-#define DCD_ON		8
-
-/* mode definition */
-#define	MX_CS8		0x03
-#define	MX_CS7		0x02
-#define	MX_CS6		0x01
-#define	MX_CS5		0x00
-
-#define	MX_STOP1	0x00
-#define	MX_STOP15	0x04
-#define	MX_STOP2	0x08
-
-#define	MX_PARNONE	0x00
-#define	MX_PAREVEN	0x40
-#define	MX_PARODD	0xC0
-
-#endif
diff --git a/drivers/char/mwave/Makefile b/drivers/char/mwave/Makefile
index 26b4fce..efa6a82 100644
--- a/drivers/char/mwave/Makefile
+++ b/drivers/char/mwave/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_MWAVE) += mwave.o
 mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o
 
 # To have the mwave driver disable other uarts if necessary
-# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES
+# ccflags-y := -DMWAVE_FUTZ_WITH_OTHER_DEVICES
 
 # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
-ccflags-y := -DMW_TRACE
+ccflags-y += -DMW_TRACE
diff --git a/drivers/char/mwave/README b/drivers/char/mwave/README
index 480251f..c2a58f4 100644
--- a/drivers/char/mwave/README
+++ b/drivers/char/mwave/README
@@ -11,7 +11,7 @@ are not saved by the BIOS and so do not persist after unload and reload.
 	0x0008 tp3780i tracing
 
         Tracing only occurs if the driver has been compiled with the
-        MW_TRACE macro #defined  (i.e. let EXTRA_CFLAGS += -DMW_TRACE
+        MW_TRACE macro #defined  (i.e. let ccflags-y := -DMW_TRACE
         in the Makefile).
 
   mwave_3780i_irq=5/7/10/11/15
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
deleted file mode 100644
index dd9d753..0000000
--- a/drivers/char/mxser.c
+++ /dev/null
@@ -1,2757 +0,0 @@
-/*
- *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver.
- *
- *      Copyright (C) 1999-2006  Moxa Technologies (support@moxa.com).
- *	Copyright (C) 2006-2008  Jiri Slaby <jirislaby@gmail.com>
- *
- *      This code is loosely based on the 1.8 moxa driver which is based on
- *	Linux serial driver, written by Linus Torvalds, Theodore T'so and
- *	others.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *	Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
- *	<alan@lxorguk.ukuu.org.uk>. The original 1.8 code is available on
- *	www.moxa.com.
- *	- Fixed x86_64 cleanness
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "mxser.h"
-
-#define	MXSER_VERSION	"2.0.5"		/* 1.14 */
-#define	MXSERMAJOR	 174
-
-#define MXSER_BOARDS		4	/* Max. boards */
-#define MXSER_PORTS_PER_BOARD	8	/* Max. ports per board */
-#define MXSER_PORTS		(MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
-#define MXSER_ISR_PASS_LIMIT	100
-
-/*CheckIsMoxaMust return value*/
-#define MOXA_OTHER_UART		0x00
-#define MOXA_MUST_MU150_HWID	0x01
-#define MOXA_MUST_MU860_HWID	0x02
-
-#define WAKEUP_CHARS		256
-
-#define UART_MCR_AFE		0x20
-#define UART_LSR_SPECIAL	0x1E
-
-#define PCI_DEVICE_ID_POS104UL	0x1044
-#define PCI_DEVICE_ID_CB108	0x1080
-#define PCI_DEVICE_ID_CP102UF	0x1023
-#define PCI_DEVICE_ID_CP112UL	0x1120
-#define PCI_DEVICE_ID_CB114	0x1142
-#define PCI_DEVICE_ID_CP114UL	0x1143
-#define PCI_DEVICE_ID_CB134I	0x1341
-#define PCI_DEVICE_ID_CP138U	0x1380
-
-
-#define C168_ASIC_ID    1
-#define C104_ASIC_ID    2
-#define C102_ASIC_ID	0xB
-#define CI132_ASIC_ID	4
-#define CI134_ASIC_ID	3
-#define CI104J_ASIC_ID  5
-
-#define MXSER_HIGHBAUD	1
-#define MXSER_HAS2	2
-
-/* This is only for PCI */
-static const struct {
-	int type;
-	int tx_fifo;
-	int rx_fifo;
-	int xmit_fifo_size;
-	int rx_high_water;
-	int rx_trigger;
-	int rx_low_water;
-	long max_baud;
-} Gpci_uart_info[] = {
-	{MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
-	{MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
-	{MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
-};
-#define UART_INFO_NUM	ARRAY_SIZE(Gpci_uart_info)
-
-struct mxser_cardinfo {
-	char *name;
-	unsigned int nports;
-	unsigned int flags;
-};
-
-static const struct mxser_cardinfo mxser_cards[] = {
-/* 0*/	{ "C168 series",	8, },
-	{ "C104 series",	4, },
-	{ "CI-104J series",	4, },
-	{ "C168H/PCI series",	8, },
-	{ "C104H/PCI series",	4, },
-/* 5*/	{ "C102 series",	4, MXSER_HAS2 },	/* C102-ISA */
-	{ "CI-132 series",	4, MXSER_HAS2 },
-	{ "CI-134 series",	4, },
-	{ "CP-132 series",	2, },
-	{ "CP-114 series",	4, },
-/*10*/	{ "CT-114 series",	4, },
-	{ "CP-102 series",	2, MXSER_HIGHBAUD },
-	{ "CP-104U series",	4, },
-	{ "CP-168U series",	8, },
-	{ "CP-132U series",	2, },
-/*15*/	{ "CP-134U series",	4, },
-	{ "CP-104JU series",	4, },
-	{ "Moxa UC7000 Serial",	8, },		/* RC7000 */
-	{ "CP-118U series",	8, },
-	{ "CP-102UL series",	2, },
-/*20*/	{ "CP-102U series",	2, },
-	{ "CP-118EL series",	8, },
-	{ "CP-168EL series",	8, },
-	{ "CP-104EL series",	4, },
-	{ "CB-108 series",	8, },
-/*25*/	{ "CB-114 series",	4, },
-	{ "CB-134I series",	4, },
-	{ "CP-138U series",	8, },
-	{ "POS-104UL series",	4, },
-	{ "CP-114UL series",	4, },
-/*30*/	{ "CP-102UF series",	2, },
-	{ "CP-112UL series",	2, },
-};
-
-/* driver_data correspond to the lines in the structure above
-   see also ISA probe function before you change something */
-static struct pci_device_id mxser_pcibrds[] = {
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168),	.driver_data = 3 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104),	.driver_data = 4 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132),	.driver_data = 8 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114),	.driver_data = 9 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114),	.driver_data = 10 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102),	.driver_data = 11 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U),	.driver_data = 12 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U),	.driver_data = 13 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U),	.driver_data = 14 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U),	.driver_data = 15 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000),	.driver_data = 17 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U),	.driver_data = 18 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U),	.driver_data = 20 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108),	.driver_data = 24 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114),	.driver_data = 25 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I),	.driver_data = 26 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U),	.driver_data = 27 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL),	.driver_data = 28 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL),	.driver_data = 29 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF),	.driver_data = 30 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL),	.driver_data = 31 },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
-
-static unsigned long ioaddr[MXSER_BOARDS];
-static int ttymajor = MXSERMAJOR;
-
-/* Variables for insmod */
-
-MODULE_AUTHOR("Casper Yang");
-MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-module_param_array(ioaddr, ulong, NULL, 0);
-MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");
-module_param(ttymajor, int, 0);
-MODULE_LICENSE("GPL");
-
-struct mxser_log {
-	int tick;
-	unsigned long rxcnt[MXSER_PORTS];
-	unsigned long txcnt[MXSER_PORTS];
-};
-
-struct mxser_mon {
-	unsigned long rxcnt;
-	unsigned long txcnt;
-	unsigned long up_rxcnt;
-	unsigned long up_txcnt;
-	int modem_status;
-	unsigned char hold_reason;
-};
-
-struct mxser_mon_ext {
-	unsigned long rx_cnt[32];
-	unsigned long tx_cnt[32];
-	unsigned long up_rxcnt[32];
-	unsigned long up_txcnt[32];
-	int modem_status[32];
-
-	long baudrate[32];
-	int databits[32];
-	int stopbits[32];
-	int parity[32];
-	int flowctrl[32];
-	int fifo[32];
-	int iftype[32];
-};
-
-struct mxser_board;
-
-struct mxser_port {
-	struct tty_port port;
-	struct mxser_board *board;
-
-	unsigned long ioaddr;
-	unsigned long opmode_ioaddr;
-	int max_baud;
-
-	int rx_high_water;
-	int rx_trigger;		/* Rx fifo trigger level */
-	int rx_low_water;
-	int baud_base;		/* max. speed */
-	int type;		/* UART type */
-
-	int x_char;		/* xon/xoff character */
-	int IER;		/* Interrupt Enable Register */
-	int MCR;		/* Modem control register */
-
-	unsigned char stop_rx;
-	unsigned char ldisc_stop_rx;
-
-	int custom_divisor;
-	unsigned char err_shadow;
-
-	struct async_icount icount; /* kernel counters for 4 input interrupts */
-	int timeout;
-
-	int read_status_mask;
-	int ignore_status_mask;
-	int xmit_fifo_size;
-	int xmit_head;
-	int xmit_tail;
-	int xmit_cnt;
-
-	struct ktermios normal_termios;
-
-	struct mxser_mon mon_data;
-
-	spinlock_t slock;
-};
-
-struct mxser_board {
-	unsigned int idx;
-	int irq;
-	const struct mxser_cardinfo *info;
-	unsigned long vector;
-	unsigned long vector_mask;
-
-	int chip_flag;
-	int uart_type;
-
-	struct mxser_port ports[MXSER_PORTS_PER_BOARD];
-};
-
-struct mxser_mstatus {
-	tcflag_t cflag;
-	int cts;
-	int dsr;
-	int ri;
-	int dcd;
-};
-
-static struct mxser_board mxser_boards[MXSER_BOARDS];
-static struct tty_driver *mxvar_sdriver;
-static struct mxser_log mxvar_log;
-static int mxser_set_baud_method[MXSER_PORTS + 1];
-
-static void mxser_enable_must_enchance_mode(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr |= MOXA_MUST_EFR_EFRB_ENABLE;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-#ifdef	CONFIG_PCI
-static void mxser_disable_must_enchance_mode(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-#endif
-
-static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK0;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(value, baseio + MOXA_MUST_XON1_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK0;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(value, baseio + MOXA_MUST_XOFF1_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_set_must_fifo_value(struct mxser_port *info)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(info->ioaddr + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR);
-
-	efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK1;
-
-	outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER);
-	outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER);
-	outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER);
-	outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER);
-	outb(oldlcr, info->ioaddr + UART_LCR);
-}
-
-static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK2;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(value, baseio + MOXA_MUST_ENUM_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-#ifdef CONFIG_PCI
-static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK2;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	*pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-#endif
-
-static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_MASK;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_enable_must_tx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
-	efr |= MOXA_MUST_EFR_SF_TX1;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_disable_must_tx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_enable_must_rx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
-	efr |= MOXA_MUST_EFR_SF_RX1;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-#ifdef CONFIG_PCI
-static int __devinit CheckIsMoxaMust(unsigned long io)
-{
-	u8 oldmcr, hwid;
-	int i;
-
-	outb(0, io + UART_LCR);
-	mxser_disable_must_enchance_mode(io);
-	oldmcr = inb(io + UART_MCR);
-	outb(0, io + UART_MCR);
-	mxser_set_must_xon1_value(io, 0x11);
-	if ((hwid = inb(io + UART_MCR)) != 0) {
-		outb(oldmcr, io + UART_MCR);
-		return MOXA_OTHER_UART;
-	}
-
-	mxser_get_must_hardware_id(io, &hwid);
-	for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
-		if (hwid == Gpci_uart_info[i].type)
-			return (int)hwid;
-	}
-	return MOXA_OTHER_UART;
-}
-#endif
-
-static void process_txrx_fifo(struct mxser_port *info)
-{
-	int i;
-
-	if ((info->type == PORT_16450) || (info->type == PORT_8250)) {
-		info->rx_trigger = 1;
-		info->rx_high_water = 1;
-		info->rx_low_water = 1;
-		info->xmit_fifo_size = 1;
-	} else
-		for (i = 0; i < UART_INFO_NUM; i++)
-			if (info->board->chip_flag == Gpci_uart_info[i].type) {
-				info->rx_trigger = Gpci_uart_info[i].rx_trigger;
-				info->rx_low_water = Gpci_uart_info[i].rx_low_water;
-				info->rx_high_water = Gpci_uart_info[i].rx_high_water;
-				info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;
-				break;
-			}
-}
-
-static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
-{
-	static unsigned char mxser_msr[MXSER_PORTS + 1];
-	unsigned char status = 0;
-
-	status = inb(baseaddr + UART_MSR);
-
-	mxser_msr[port] &= 0x0F;
-	mxser_msr[port] |= status;
-	status = mxser_msr[port];
-	if (mode)
-		mxser_msr[port] = 0;
-
-	return status;
-}
-
-static int mxser_carrier_raised(struct tty_port *port)
-{
-	struct mxser_port *mp = container_of(port, struct mxser_port, port);
-	return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
-}
-
-static void mxser_dtr_rts(struct tty_port *port, int on)
-{
-	struct mxser_port *mp = container_of(port, struct mxser_port, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&mp->slock, flags);
-	if (on)
-		outb(inb(mp->ioaddr + UART_MCR) |
-			UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
-	else
-		outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
-			mp->ioaddr + UART_MCR);
-	spin_unlock_irqrestore(&mp->slock, flags);
-}
-
-static int mxser_set_baud(struct tty_struct *tty, long newspd)
-{
-	struct mxser_port *info = tty->driver_data;
-	int quot = 0, baud;
-	unsigned char cval;
-
-	if (!info->ioaddr)
-		return -1;
-
-	if (newspd > info->max_baud)
-		return -1;
-
-	if (newspd == 134) {
-		quot = 2 * info->baud_base / 269;
-		tty_encode_baud_rate(tty, 134, 134);
-	} else if (newspd) {
-		quot = info->baud_base / newspd;
-		if (quot == 0)
-			quot = 1;
-		baud = info->baud_base/quot;
-		tty_encode_baud_rate(tty, baud, baud);
-	} else {
-		quot = 0;
-	}
-
-	info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
-	info->timeout += HZ / 50;	/* Add .02 seconds of slop */
-
-	if (quot) {
-		info->MCR |= UART_MCR_DTR;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-	} else {
-		info->MCR &= ~UART_MCR_DTR;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-		return 0;
-	}
-
-	cval = inb(info->ioaddr + UART_LCR);
-
-	outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR);	/* set DLAB */
-
-	outb(quot & 0xff, info->ioaddr + UART_DLL);	/* LS of divisor */
-	outb(quot >> 8, info->ioaddr + UART_DLM);	/* MS of divisor */
-	outb(cval, info->ioaddr + UART_LCR);	/* reset DLAB */
-
-#ifdef BOTHER
-	if (C_BAUD(tty) == BOTHER) {
-		quot = info->baud_base % newspd;
-		quot *= 8;
-		if (quot % newspd > newspd / 2) {
-			quot /= newspd;
-			quot++;
-		} else
-			quot /= newspd;
-
-		mxser_set_must_enum_value(info->ioaddr, quot);
-	} else
-#endif
-		mxser_set_must_enum_value(info->ioaddr, 0);
-
-	return 0;
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static int mxser_change_speed(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned cflag, cval, fcr;
-	int ret = 0;
-	unsigned char status;
-
-	cflag = tty->termios->c_cflag;
-	if (!info->ioaddr)
-		return ret;
-
-	if (mxser_set_baud_method[tty->index] == 0)
-		mxser_set_baud(tty, tty_get_baud_rate(tty));
-
-	/* byte size and parity */
-	switch (cflag & CSIZE) {
-	case CS5:
-		cval = 0x00;
-		break;
-	case CS6:
-		cval = 0x01;
-		break;
-	case CS7:
-		cval = 0x02;
-		break;
-	case CS8:
-		cval = 0x03;
-		break;
-	default:
-		cval = 0x00;
-		break;		/* too keep GCC shut... */
-	}
-	if (cflag & CSTOPB)
-		cval |= 0x04;
-	if (cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-	if (cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-
-	if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
-		if (info->board->chip_flag) {
-			fcr = UART_FCR_ENABLE_FIFO;
-			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
-			mxser_set_must_fifo_value(info);
-		} else
-			fcr = 0;
-	} else {
-		fcr = UART_FCR_ENABLE_FIFO;
-		if (info->board->chip_flag) {
-			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
-			mxser_set_must_fifo_value(info);
-		} else {
-			switch (info->rx_trigger) {
-			case 1:
-				fcr |= UART_FCR_TRIGGER_1;
-				break;
-			case 4:
-				fcr |= UART_FCR_TRIGGER_4;
-				break;
-			case 8:
-				fcr |= UART_FCR_TRIGGER_8;
-				break;
-			default:
-				fcr |= UART_FCR_TRIGGER_14;
-				break;
-			}
-		}
-	}
-
-	/* CTS flow control flag and modem status interrupts */
-	info->IER &= ~UART_IER_MSI;
-	info->MCR &= ~UART_MCR_AFE;
-	if (cflag & CRTSCTS) {
-		info->port.flags |= ASYNC_CTS_FLOW;
-		info->IER |= UART_IER_MSI;
-		if ((info->type == PORT_16550A) || (info->board->chip_flag)) {
-			info->MCR |= UART_MCR_AFE;
-		} else {
-			status = inb(info->ioaddr + UART_MSR);
-			if (tty->hw_stopped) {
-				if (status & UART_MSR_CTS) {
-					tty->hw_stopped = 0;
-					if (info->type != PORT_16550A &&
-							!info->board->chip_flag) {
-						outb(info->IER & ~UART_IER_THRI,
-							info->ioaddr +
-							UART_IER);
-						info->IER |= UART_IER_THRI;
-						outb(info->IER, info->ioaddr +
-								UART_IER);
-					}
-					tty_wakeup(tty);
-				}
-			} else {
-				if (!(status & UART_MSR_CTS)) {
-					tty->hw_stopped = 1;
-					if ((info->type != PORT_16550A) &&
-							(!info->board->chip_flag)) {
-						info->IER &= ~UART_IER_THRI;
-						outb(info->IER, info->ioaddr +
-								UART_IER);
-					}
-				}
-			}
-		}
-	} else {
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-	}
-	outb(info->MCR, info->ioaddr + UART_MCR);
-	if (cflag & CLOCAL) {
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	} else {
-		info->port.flags |= ASYNC_CHECK_CD;
-		info->IER |= UART_IER_MSI;
-	}
-	outb(info->IER, info->ioaddr + UART_IER);
-
-	/*
-	 * Set up parity check flag
-	 */
-	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (I_INPCK(tty))
-		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		info->read_status_mask |= UART_LSR_BI;
-
-	info->ignore_status_mask = 0;
-
-	if (I_IGNBRK(tty)) {
-		info->ignore_status_mask |= UART_LSR_BI;
-		info->read_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(tty)) {
-			info->ignore_status_mask |=
-						UART_LSR_OE |
-						UART_LSR_PE |
-						UART_LSR_FE;
-			info->read_status_mask |=
-						UART_LSR_OE |
-						UART_LSR_PE |
-						UART_LSR_FE;
-		}
-	}
-	if (info->board->chip_flag) {
-		mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty));
-		mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty));
-		if (I_IXON(tty)) {
-			mxser_enable_must_rx_software_flow_control(
-					info->ioaddr);
-		} else {
-			mxser_disable_must_rx_software_flow_control(
-					info->ioaddr);
-		}
-		if (I_IXOFF(tty)) {
-			mxser_enable_must_tx_software_flow_control(
-					info->ioaddr);
-		} else {
-			mxser_disable_must_tx_software_flow_control(
-					info->ioaddr);
-		}
-	}
-
-
-	outb(fcr, info->ioaddr + UART_FCR);	/* set fcr */
-	outb(cval, info->ioaddr + UART_LCR);
-
-	return ret;
-}
-
-static void mxser_check_modem_status(struct tty_struct *tty,
-				struct mxser_port *port, int status)
-{
-	/* update input line counters */
-	if (status & UART_MSR_TERI)
-		port->icount.rng++;
-	if (status & UART_MSR_DDSR)
-		port->icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		port->icount.dcd++;
-	if (status & UART_MSR_DCTS)
-		port->icount.cts++;
-	port->mon_data.modem_status = status;
-	wake_up_interruptible(&port->port.delta_msr_wait);
-
-	if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-		if (status & UART_MSR_DCD)
-			wake_up_interruptible(&port->port.open_wait);
-	}
-
-	if (port->port.flags & ASYNC_CTS_FLOW) {
-		if (tty->hw_stopped) {
-			if (status & UART_MSR_CTS) {
-				tty->hw_stopped = 0;
-
-				if ((port->type != PORT_16550A) &&
-						(!port->board->chip_flag)) {
-					outb(port->IER & ~UART_IER_THRI,
-						port->ioaddr + UART_IER);
-					port->IER |= UART_IER_THRI;
-					outb(port->IER, port->ioaddr +
-							UART_IER);
-				}
-				tty_wakeup(tty);
-			}
-		} else {
-			if (!(status & UART_MSR_CTS)) {
-				tty->hw_stopped = 1;
-				if (port->type != PORT_16550A &&
-						!port->board->chip_flag) {
-					port->IER &= ~UART_IER_THRI;
-					outb(port->IER, port->ioaddr +
-							UART_IER);
-				}
-			}
-		}
-	}
-}
-
-static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct mxser_port *info = container_of(port, struct mxser_port, port);
-	unsigned long page;
-	unsigned long flags;
-
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	if (!info->ioaddr || !info->type) {
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		free_page(page);
-		spin_unlock_irqrestore(&info->slock, flags);
-		return 0;
-	}
-	info->port.xmit_buf = (unsigned char *) page;
-
-	/*
-	 * Clear the FIFO buffers and disable them
-	 * (they will be reenabled in mxser_change_speed())
-	 */
-	if (info->board->chip_flag)
-		outb((UART_FCR_CLEAR_RCVR |
-			UART_FCR_CLEAR_XMIT |
-			MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
-	else
-		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
-			info->ioaddr + UART_FCR);
-
-	/*
-	 * At this point there's no way the LSR could still be 0xFF;
-	 * if it is, then bail out, because there's likely no UART
-	 * here.
-	 */
-	if (inb(info->ioaddr + UART_LSR) == 0xff) {
-		spin_unlock_irqrestore(&info->slock, flags);
-		if (capable(CAP_SYS_ADMIN)) {
-			set_bit(TTY_IO_ERROR, &tty->flags);
-			return 0;
-		} else
-			return -ENODEV;
-	}
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) inb(info->ioaddr + UART_LSR);
-	(void) inb(info->ioaddr + UART_RX);
-	(void) inb(info->ioaddr + UART_IIR);
-	(void) inb(info->ioaddr + UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR);	/* reset DLAB */
-	info->MCR = UART_MCR_DTR | UART_MCR_RTS;
-	outb(info->MCR, info->ioaddr + UART_MCR);
-
-	/*
-	 * Finally, enable interrupts
-	 */
-	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
-
-	if (info->board->chip_flag)
-		info->IER |= MOXA_MUST_IER_EGDAI;
-	outb(info->IER, info->ioaddr + UART_IER);	/* enable interrupts */
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) inb(info->ioaddr + UART_LSR);
-	(void) inb(info->ioaddr + UART_RX);
-	(void) inb(info->ioaddr + UART_IIR);
-	(void) inb(info->ioaddr + UART_MSR);
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	/*
-	 * and set the speed of the serial port
-	 */
-	mxser_change_speed(tty, NULL);
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	return 0;
-}
-
-/*
- * This routine will shutdown a serial port
- */
-static void mxser_shutdown_port(struct tty_port *port)
-{
-	struct mxser_port *info = container_of(port, struct mxser_port, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	/*
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
-	wake_up_interruptible(&info->port.delta_msr_wait);
-
-	/*
-	 * Free the xmit buffer, if necessary
-	 */
-	if (info->port.xmit_buf) {
-		free_page((unsigned long) info->port.xmit_buf);
-		info->port.xmit_buf = NULL;
-	}
-
-	info->IER = 0;
-	outb(0x00, info->ioaddr + UART_IER);
-
-	/* clear Rx/Tx FIFO's */
-	if (info->board->chip_flag)
-		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
-				MOXA_MUST_FCR_GDA_MODE_ENABLE,
-				info->ioaddr + UART_FCR);
-	else
-		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
-			info->ioaddr + UART_FCR);
-
-	/* read data port to reset things */
-	(void) inb(info->ioaddr + UART_RX);
-
-
-	if (info->board->chip_flag)
-		SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
-
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int mxser_open(struct tty_struct *tty, struct file *filp)
-{
-	struct mxser_port *info;
-	int line;
-
-	line = tty->index;
-	if (line == MXSER_PORTS)
-		return 0;
-	if (line < 0 || line > MXSER_PORTS)
-		return -ENODEV;
-	info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD];
-	if (!info->ioaddr)
-		return -ENODEV;
-
-	tty->driver_data = info;
-	return tty_port_open(&info->port, tty, filp);
-}
-
-static void mxser_flush_buffer(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	char fcr;
-	unsigned long flags;
-
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	fcr = inb(info->ioaddr + UART_FCR);
-	outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
-		info->ioaddr + UART_FCR);
-	outb(fcr, info->ioaddr + UART_FCR);
-
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	tty_wakeup(tty);
-}
-
-
-static void mxser_close_port(struct tty_port *port)
-{
-	struct mxser_port *info = container_of(port, struct mxser_port, port);
-	unsigned long timeout;
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	info->IER &= ~UART_IER_RLSI;
-	if (info->board->chip_flag)
-		info->IER &= ~MOXA_MUST_RECV_ISR;
-
-	outb(info->IER, info->ioaddr + UART_IER);
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = jiffies + HZ;
-	while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
-		schedule_timeout_interruptible(5);
-		if (time_after(jiffies, timeout))
-			break;
-	}
-}
-
-/*
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- */
-static void mxser_close(struct tty_struct *tty, struct file *filp)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-
-	if (tty->index == MXSER_PORTS || info == NULL)
-		return;
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-	mutex_lock(&port->mutex);
-	mxser_close_port(port);
-	mxser_flush_buffer(tty);
-	mxser_shutdown_port(port);
-	clear_bit(ASYNCB_INITIALIZED, &port->flags);
-	mutex_unlock(&port->mutex);
-	/* Right now the tty_port set is done outside of the close_end helper
-	   as we don't yet have everyone using refcounts */	
-	tty_port_close_end(port, tty);
-	tty_port_tty_set(port, NULL);
-}
-
-static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	int c, total = 0;
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	while (1) {
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
-
-		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
-		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_head = (info->xmit_head + c) &
-				  (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (info->xmit_cnt && !tty->stopped) {
-		if (!tty->hw_stopped ||
-				(info->type == PORT_16550A) ||
-				(info->board->chip_flag)) {
-			spin_lock_irqsave(&info->slock, flags);
-			outb(info->IER & ~UART_IER_THRI, info->ioaddr +
-					UART_IER);
-			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->ioaddr + UART_IER);
-			spin_unlock_irqrestore(&info->slock, flags);
-		}
-	}
-	return total;
-}
-
-static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
-		return 0;
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->port.xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	info->xmit_cnt++;
-	spin_unlock_irqrestore(&info->slock, flags);
-	if (!tty->stopped) {
-		if (!tty->hw_stopped ||
-				(info->type == PORT_16550A) ||
-				info->board->chip_flag) {
-			spin_lock_irqsave(&info->slock, flags);
-			outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
-			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->ioaddr + UART_IER);
-			spin_unlock_irqrestore(&info->slock, flags);
-		}
-	}
-	return 1;
-}
-
-
-static void mxser_flush_chars(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf ||
-			(tty->hw_stopped && info->type != PORT_16550A &&
-			 !info->board->chip_flag))
-		return;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
-	info->IER |= UART_IER_THRI;
-	outb(info->IER, info->ioaddr + UART_IER);
-
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static int mxser_write_room(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	int ret;
-
-	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-	return ret < 0 ? 0 : ret;
-}
-
-static int mxser_chars_in_buffer(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	return info->xmit_cnt;
-}
-
-/*
- * ------------------------------------------------------------
- * friends of mxser_ioctl()
- * ------------------------------------------------------------
- */
-static int mxser_get_serial_info(struct tty_struct *tty,
-		struct serial_struct __user *retinfo)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct serial_struct tmp = {
-		.type = info->type,
-		.line = tty->index,
-		.port = info->ioaddr,
-		.irq = info->board->irq,
-		.flags = info->port.flags,
-		.baud_base = info->baud_base,
-		.close_delay = info->port.close_delay,
-		.closing_wait = info->port.closing_wait,
-		.custom_divisor = info->custom_divisor,
-		.hub6 = 0
-	};
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int mxser_set_serial_info(struct tty_struct *tty,
-		struct serial_struct __user *new_info)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-	struct serial_struct new_serial;
-	speed_t baud;
-	unsigned long sl_flags;
-	unsigned int flags;
-	int retval = 0;
-
-	if (!new_info || !info->ioaddr)
-		return -ENODEV;
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-
-	if (new_serial.irq != info->board->irq ||
-			new_serial.port != info->ioaddr)
-		return -EINVAL;
-
-	flags = port->flags & ASYNC_SPD_MASK;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.baud_base != info->baud_base) ||
-				(new_serial.close_delay != info->port.close_delay) ||
-				((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
-				(new_serial.flags & ASYNC_USR_MASK));
-	} else {
-		/*
-		 * OK, past this point, all the error checking has been done.
-		 * At this point, we start making changes.....
-		 */
-		port->flags = ((port->flags & ~ASYNC_FLAGS) |
-				(new_serial.flags & ASYNC_FLAGS));
-		port->close_delay = new_serial.close_delay * HZ / 100;
-		port->closing_wait = new_serial.closing_wait * HZ / 100;
-		tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
-				(new_serial.baud_base != info->baud_base ||
-				new_serial.custom_divisor !=
-				info->custom_divisor)) {
-			if (new_serial.custom_divisor == 0)
-				return -EINVAL;
-			baud = new_serial.baud_base / new_serial.custom_divisor;
-			tty_encode_baud_rate(tty, baud, baud);
-		}
-	}
-
-	info->type = new_serial.type;
-
-	process_txrx_fifo(info);
-
-	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
-		if (flags != (port->flags & ASYNC_SPD_MASK)) {
-			spin_lock_irqsave(&info->slock, sl_flags);
-			mxser_change_speed(tty, NULL);
-			spin_unlock_irqrestore(&info->slock, sl_flags);
-		}
-	} else {
-		retval = mxser_activate(port, tty);
-		if (retval == 0)
-			set_bit(ASYNCB_INITIALIZED, &port->flags);
-	}
-	return retval;
-}
-
-/*
- * mxser_get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *	    is emptied.  On bus types like RS485, the transmitter must
- *	    release the bus after transmitting. This must be done when
- *	    the transmit shift register is empty, not be done when the
- *	    transmit holding register is empty.  This functionality
- *	    allows an RS485 driver to be written in user space.
- */
-static int mxser_get_lsr_info(struct mxser_port *info,
-		unsigned int __user *value)
-{
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	status = inb(info->ioaddr + UART_LSR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	return put_user(result, value);
-}
-
-static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned char control, status;
-	unsigned long flags;
-
-
-	if (tty->index == MXSER_PORTS)
-		return -ENOIOCTLCMD;
-	if (test_bit(TTY_IO_ERROR, &tty->flags))
-		return -EIO;
-
-	control = info->MCR;
-
-	spin_lock_irqsave(&info->slock, flags);
-	status = inb(info->ioaddr + UART_MSR);
-	if (status & UART_MSR_ANY_DELTA)
-		mxser_check_modem_status(tty, info, status);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
-		    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
-		    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
-		    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
-		    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
-		    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-}
-
-static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-
-	if (tty->index == MXSER_PORTS)
-		return -ENOIOCTLCMD;
-	if (test_bit(TTY_IO_ERROR, &tty->flags))
-		return -EIO;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	if (set & TIOCM_RTS)
-		info->MCR |= UART_MCR_RTS;
-	if (set & TIOCM_DTR)
-		info->MCR |= UART_MCR_DTR;
-
-	if (clear & TIOCM_RTS)
-		info->MCR &= ~UART_MCR_RTS;
-	if (clear & TIOCM_DTR)
-		info->MCR &= ~UART_MCR_DTR;
-
-	outb(info->MCR, info->ioaddr + UART_MCR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return 0;
-}
-
-static int __init mxser_program_mode(int port)
-{
-	int id, i, j, n;
-
-	outb(0, port);
-	outb(0, port);
-	outb(0, port);
-	(void)inb(port);
-	(void)inb(port);
-	outb(0, port);
-	(void)inb(port);
-
-	id = inb(port + 1) & 0x1F;
-	if ((id != C168_ASIC_ID) &&
-			(id != C104_ASIC_ID) &&
-			(id != C102_ASIC_ID) &&
-			(id != CI132_ASIC_ID) &&
-			(id != CI134_ASIC_ID) &&
-			(id != CI104J_ASIC_ID))
-		return -1;
-	for (i = 0, j = 0; i < 4; i++) {
-		n = inb(port + 2);
-		if (n == 'M') {
-			j = 1;
-		} else if ((j == 1) && (n == 1)) {
-			j = 2;
-			break;
-		} else
-			j = 0;
-	}
-	if (j != 2)
-		id = -2;
-	return id;
-}
-
-static void __init mxser_normal_mode(int port)
-{
-	int i, n;
-
-	outb(0xA5, port + 1);
-	outb(0x80, port + 3);
-	outb(12, port + 0);	/* 9600 bps */
-	outb(0, port + 1);
-	outb(0x03, port + 3);	/* 8 data bits */
-	outb(0x13, port + 4);	/* loop back mode */
-	for (i = 0; i < 16; i++) {
-		n = inb(port + 5);
-		if ((n & 0x61) == 0x60)
-			break;
-		if ((n & 1) == 1)
-			(void)inb(port);
-	}
-	outb(0x00, port + 4);
-}
-
-#define CHIP_SK 	0x01	/* Serial Data Clock  in Eprom */
-#define CHIP_DO 	0x02	/* Serial Data Output in Eprom */
-#define CHIP_CS 	0x04	/* Serial Chip Select in Eprom */
-#define CHIP_DI 	0x08	/* Serial Data Input  in Eprom */
-#define EN_CCMD 	0x000	/* Chip's command register     */
-#define EN0_RSARLO	0x008	/* Remote start address reg 0  */
-#define EN0_RSARHI	0x009	/* Remote start address reg 1  */
-#define EN0_RCNTLO	0x00A	/* Remote byte count reg WR    */
-#define EN0_RCNTHI	0x00B	/* Remote byte count reg WR    */
-#define EN0_DCFG	0x00E	/* Data configuration reg WR   */
-#define EN0_PORT	0x010	/* Rcv missed frame error counter RD */
-#define ENC_PAGE0	0x000	/* Select page 0 of chip registers   */
-#define ENC_PAGE3	0x0C0	/* Select page 3 of chip registers   */
-static int __init mxser_read_register(int port, unsigned short *regs)
-{
-	int i, k, value, id;
-	unsigned int j;
-
-	id = mxser_program_mode(port);
-	if (id < 0)
-		return id;
-	for (i = 0; i < 14; i++) {
-		k = (i & 0x3F) | 0x180;
-		for (j = 0x100; j > 0; j >>= 1) {
-			outb(CHIP_CS, port);
-			if (k & j) {
-				outb(CHIP_CS | CHIP_DO, port);
-				outb(CHIP_CS | CHIP_DO | CHIP_SK, port);	/* A? bit of read */
-			} else {
-				outb(CHIP_CS, port);
-				outb(CHIP_CS | CHIP_SK, port);	/* A? bit of read */
-			}
-		}
-		(void)inb(port);
-		value = 0;
-		for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
-			outb(CHIP_CS, port);
-			outb(CHIP_CS | CHIP_SK, port);
-			if (inb(port) & CHIP_DI)
-				value |= j;
-		}
-		regs[i] = value;
-		outb(0, port);
-	}
-	mxser_normal_mode(port);
-	return id;
-}
-
-static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
-{
-	struct mxser_port *ip;
-	struct tty_port *port;
-	struct tty_struct *tty;
-	int result, status;
-	unsigned int i, j;
-	int ret = 0;
-
-	switch (cmd) {
-	case MOXA_GET_MAJOR:
-		if (printk_ratelimit())
-			printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
-					"%x (GET_MAJOR), fix your userspace\n",
-					current->comm, cmd);
-		return put_user(ttymajor, (int __user *)argp);
-
-	case MOXA_CHKPORTENABLE:
-		result = 0;
-		for (i = 0; i < MXSER_BOARDS; i++)
-			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
-				if (mxser_boards[i].ports[j].ioaddr)
-					result |= (1 << i);
-		return put_user(result, (unsigned long __user *)argp);
-	case MOXA_GETDATACOUNT:
-		/* The receive side is locked by port->slock but it isn't
-		   clear that an exact snapshot is worth copying here */
-		if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
-			ret = -EFAULT;
-		return ret;
-	case MOXA_GETMSTATUS: {
-		struct mxser_mstatus ms, __user *msu = argp;
-		for (i = 0; i < MXSER_BOARDS; i++)
-			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
-				ip = &mxser_boards[i].ports[j];
-				port = &ip->port;
-				memset(&ms, 0, sizeof(ms));
-
-				mutex_lock(&port->mutex);
-				if (!ip->ioaddr)
-					goto copy;
-				
-				tty = tty_port_tty_get(port);
-
-				if (!tty || !tty->termios)
-					ms.cflag = ip->normal_termios.c_cflag;
-				else
-					ms.cflag = tty->termios->c_cflag;
-				tty_kref_put(tty);
-				spin_lock_irq(&ip->slock);
-				status = inb(ip->ioaddr + UART_MSR);
-				spin_unlock_irq(&ip->slock);
-				if (status & UART_MSR_DCD)
-					ms.dcd = 1;
-				if (status & UART_MSR_DSR)
-					ms.dsr = 1;
-				if (status & UART_MSR_CTS)
-					ms.cts = 1;
-			copy:
-				mutex_unlock(&port->mutex);
-				if (copy_to_user(msu, &ms, sizeof(ms)))
-					return -EFAULT;
-				msu++;
-			}
-		return 0;
-	}
-	case MOXA_ASPP_MON_EXT: {
-		struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */
-		unsigned int cflag, iflag, p;
-		u8 opmode;
-
-		me = kzalloc(sizeof(*me), GFP_KERNEL);
-		if (!me)
-			return -ENOMEM;
-
-		for (i = 0, p = 0; i < MXSER_BOARDS; i++) {
-			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) {
-				if (p >= ARRAY_SIZE(me->rx_cnt)) {
-					i = MXSER_BOARDS;
-					break;
-				}
-				ip = &mxser_boards[i].ports[j];
-				port = &ip->port;
-
-				mutex_lock(&port->mutex);
-				if (!ip->ioaddr) {
-					mutex_unlock(&port->mutex);
-					continue;
-				}
-
-				spin_lock_irq(&ip->slock);
-				status = mxser_get_msr(ip->ioaddr, 0, p);
-
-				if (status & UART_MSR_TERI)
-					ip->icount.rng++;
-				if (status & UART_MSR_DDSR)
-					ip->icount.dsr++;
-				if (status & UART_MSR_DDCD)
-					ip->icount.dcd++;
-				if (status & UART_MSR_DCTS)
-					ip->icount.cts++;
-
-				ip->mon_data.modem_status = status;
-				me->rx_cnt[p] = ip->mon_data.rxcnt;
-				me->tx_cnt[p] = ip->mon_data.txcnt;
-				me->up_rxcnt[p] = ip->mon_data.up_rxcnt;
-				me->up_txcnt[p] = ip->mon_data.up_txcnt;
-				me->modem_status[p] =
-					ip->mon_data.modem_status;
-				spin_unlock_irq(&ip->slock);
-
-				tty = tty_port_tty_get(&ip->port);
-
-				if (!tty || !tty->termios) {
-					cflag = ip->normal_termios.c_cflag;
-					iflag = ip->normal_termios.c_iflag;
-					me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
-				} else {
-					cflag = tty->termios->c_cflag;
-					iflag = tty->termios->c_iflag;
-					me->baudrate[p] = tty_get_baud_rate(tty);
-				}
-				tty_kref_put(tty);
-
-				me->databits[p] = cflag & CSIZE;
-				me->stopbits[p] = cflag & CSTOPB;
-				me->parity[p] = cflag & (PARENB | PARODD |
-						CMSPAR);
-
-				if (cflag & CRTSCTS)
-					me->flowctrl[p] |= 0x03;
-
-				if (iflag & (IXON | IXOFF))
-					me->flowctrl[p] |= 0x0C;
-
-				if (ip->type == PORT_16550A)
-					me->fifo[p] = 1;
-
-				opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
-				opmode &= OP_MODE_MASK;
-				me->iftype[p] = opmode;
-				mutex_unlock(&port->mutex);
-			}
-		}
-		if (copy_to_user(argp, me, sizeof(*me)))
-			ret = -EFAULT;
-		kfree(me);
-		return ret;
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg,
-		struct async_icount *cprev)
-{
-	struct async_icount cnow;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&info->slock, flags);
-	cnow = info->icount;	/* atomic copy */
-	spin_unlock_irqrestore(&info->slock, 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;
-}
-
-static int mxser_ioctl(struct tty_struct *tty, struct file *file,
-		unsigned int cmd, unsigned long arg)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-	struct async_icount cnow;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (tty->index == MXSER_PORTS)
-		return mxser_ioctl_special(cmd, argp);
-
-	if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
-		int p;
-		unsigned long opmode;
-		static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
-		int shiftbit;
-		unsigned char val, mask;
-
-		p = tty->index % 4;
-		if (cmd == MOXA_SET_OP_MODE) {
-			if (get_user(opmode, (int __user *) argp))
-				return -EFAULT;
-			if (opmode != RS232_MODE &&
-					opmode != RS485_2WIRE_MODE &&
-					opmode != RS422_MODE &&
-					opmode != RS485_4WIRE_MODE)
-				return -EFAULT;
-			mask = ModeMask[p];
-			shiftbit = p * 2;
-			spin_lock_irq(&info->slock);
-			val = inb(info->opmode_ioaddr);
-			val &= mask;
-			val |= (opmode << shiftbit);
-			outb(val, info->opmode_ioaddr);
-			spin_unlock_irq(&info->slock);
-		} else {
-			shiftbit = p * 2;
-			spin_lock_irq(&info->slock);
-			opmode = inb(info->opmode_ioaddr) >> shiftbit;
-			spin_unlock_irq(&info->slock);
-			opmode &= OP_MODE_MASK;
-			if (put_user(opmode, (int __user *)argp))
-				return -EFAULT;
-		}
-		return 0;
-	}
-
-	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
-			test_bit(TTY_IO_ERROR, &tty->flags))
-		return -EIO;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		mutex_lock(&port->mutex);
-		retval = mxser_get_serial_info(tty, argp);
-		mutex_unlock(&port->mutex);
-		return retval;
-	case TIOCSSERIAL:
-		mutex_lock(&port->mutex);
-		retval = mxser_set_serial_info(tty, argp);
-		mutex_unlock(&port->mutex);
-		return retval;
-	case TIOCSERGETLSR:	/* Get line status register */
-		return  mxser_get_lsr_info(info, argp);
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
-		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-	case TIOCMIWAIT:
-		spin_lock_irqsave(&info->slock, flags);
-		cnow = info->icount;	/* note the counters on entry */
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		return wait_event_interruptible(info->port.delta_msr_wait,
-				mxser_cflags_changed(info, arg, &cnow));
-	case MOXA_HighSpeedOn:
-		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
-	case MOXA_SDS_RSTICOUNTER:
-		spin_lock_irq(&info->slock);
-		info->mon_data.rxcnt = 0;
-		info->mon_data.txcnt = 0;
-		spin_unlock_irq(&info->slock);
-		return 0;
-
-	case MOXA_ASPP_OQUEUE:{
-		int len, lsr;
-
-		len = mxser_chars_in_buffer(tty);
-		spin_lock_irq(&info->slock);
-		lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE;
-		spin_unlock_irq(&info->slock);
-		len += (lsr ? 0 : 1);
-
-		return put_user(len, (int __user *)argp);
-	}
-	case MOXA_ASPP_MON: {
-		int mcr, status;
-
-		spin_lock_irq(&info->slock);
-		status = mxser_get_msr(info->ioaddr, 1, tty->index);
-		mxser_check_modem_status(tty, info, status);
-
-		mcr = inb(info->ioaddr + UART_MCR);
-		spin_unlock_irq(&info->slock);
-
-		if (mcr & MOXA_MUST_MCR_XON_FLAG)
-			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
-		else
-			info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;
-
-		if (mcr & MOXA_MUST_MCR_TX_XON)
-			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;
-		else
-			info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
-
-		if (tty->hw_stopped)
-			info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
-		else
-			info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
-
-		if (copy_to_user(argp, &info->mon_data,
-				sizeof(struct mxser_mon)))
-			return -EFAULT;
-
-		return 0;
-	}
-	case MOXA_ASPP_LSTATUS: {
-		if (put_user(info->err_shadow, (unsigned char __user *)argp))
-			return -EFAULT;
-
-		info->err_shadow = 0;
-		return 0;
-	}
-	case MOXA_SET_BAUD_METHOD: {
-		int method;
-
-		if (get_user(method, (int __user *)argp))
-			return -EFAULT;
-		mxser_set_baud_method[tty->index] = method;
-		return put_user(method, (int __user *)argp);
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-	/*
-	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-	 * Return: write counters to the user passed counter struct
-	 * NB: both 1->0 and 0->1 transitions are counted except for
-	 *     RI where only 0->1 is counted.
-	 */
-
-static int mxser_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount)
-
-{
-	struct mxser_port *info = tty->driver_data;
-	struct async_icount cnow;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	icount->frame = cnow.frame;
-	icount->brk = cnow.brk;
-	icount->overrun = cnow.overrun;
-	icount->buf_overrun = cnow.buf_overrun;
-	icount->parity = cnow.parity;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	return 0;
-}
-
-static void mxser_stoprx(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-
-	info->ldisc_stop_rx = 1;
-	if (I_IXOFF(tty)) {
-		if (info->board->chip_flag) {
-			info->IER &= ~MOXA_MUST_RECV_ISR;
-			outb(info->IER, info->ioaddr + UART_IER);
-		} else {
-			info->x_char = STOP_CHAR(tty);
-			outb(0, info->ioaddr + UART_IER);
-			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->ioaddr + UART_IER);
-		}
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		info->MCR &= ~UART_MCR_RTS;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-	}
-}
-
-/*
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- */
-static void mxser_throttle(struct tty_struct *tty)
-{
-	mxser_stoprx(tty);
-}
-
-static void mxser_unthrottle(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-
-	/* startrx */
-	info->ldisc_stop_rx = 0;
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else {
-			if (info->board->chip_flag) {
-				info->IER |= MOXA_MUST_RECV_ISR;
-				outb(info->IER, info->ioaddr + UART_IER);
-			} else {
-				info->x_char = START_CHAR(tty);
-				outb(0, info->ioaddr + UART_IER);
-				info->IER |= UART_IER_THRI;
-				outb(info->IER, info->ioaddr + UART_IER);
-			}
-		}
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		info->MCR |= UART_MCR_RTS;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-	}
-}
-
-/*
- * mxser_stop() and mxser_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- */
-static void mxser_stop(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (info->IER & UART_IER_THRI) {
-		info->IER &= ~UART_IER_THRI;
-		outb(info->IER, info->ioaddr + UART_IER);
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static void mxser_start(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (info->xmit_cnt && info->port.xmit_buf) {
-		outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
-		info->IER |= UART_IER_THRI;
-		outb(info->IER, info->ioaddr + UART_IER);
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	mxser_change_speed(tty, old_termios);
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		mxser_start(tty);
-	}
-
-	/* Handle sw stopped */
-	if ((old_termios->c_iflag & IXON) &&
-			!(tty->termios->c_iflag & IXON)) {
-		tty->stopped = 0;
-
-		if (info->board->chip_flag) {
-			spin_lock_irqsave(&info->slock, flags);
-			mxser_disable_must_rx_software_flow_control(
-					info->ioaddr);
-			spin_unlock_irqrestore(&info->slock, flags);
-		}
-
-		mxser_start(tty);
-	}
-}
-
-/*
- * mxser_wait_until_sent() --- wait until the transmitter is empty
- */
-static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	unsigned long flags;
-	int lsr;
-
-	if (info->type == PORT_UNKNOWN)
-		return;
-
-	if (info->xmit_fifo_size == 0)
-		return;		/* Just in case.... */
-
-	orig_jiffies = jiffies;
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 *
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
-	char_time = char_time / 5;
-	if (char_time == 0)
-		char_time = 1;
-	if (timeout && timeout < char_time)
-		char_time = timeout;
-	/*
-	 * If the transmitter hasn't cleared in twice the approximate
-	 * amount of time to send the entire FIFO, it probably won't
-	 * ever clear.  This assumes the UART isn't doing flow
-	 * control, which is currently the case.  Hence, if it ever
-	 * takes longer than info->timeout, this is probably due to a
-	 * UART bug of some kind.  So, we clamp the timeout parameter at
-	 * 2*info->timeout.
-	 */
-	if (!timeout || timeout > 2 * info->timeout)
-		timeout = 2 * info->timeout;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
-		timeout, char_time);
-	printk("jiff=%lu...", jiffies);
-#endif
-	spin_lock_irqsave(&info->slock, flags);
-	while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-		spin_unlock_irqrestore(&info->slock, flags);
-		schedule_timeout_interruptible(char_time);
-		spin_lock_irqsave(&info->slock, flags);
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-	set_current_state(TASK_RUNNING);
-
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * This routine is called by tty_hangup() when a hangup is signaled.
- */
-static void mxser_hangup(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-
-	mxser_flush_buffer(tty);
-	tty_port_hangup(&info->port);
-}
-
-/*
- * mxser_rs_break() --- routine which turns the break handling on or off
- */
-static int mxser_rs_break(struct tty_struct *tty, int break_state)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (break_state == -1)
-		outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
-			info->ioaddr + UART_LCR);
-	else
-		outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
-			info->ioaddr + UART_LCR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return 0;
-}
-
-static void mxser_receive_chars(struct tty_struct *tty,
-				struct mxser_port *port, int *status)
-{
-	unsigned char ch, gdl;
-	int ignored = 0;
-	int cnt = 0;
-	int recv_room;
-	int max = 256;
-
-	recv_room = tty->receive_room;
-	if (recv_room == 0 && !port->ldisc_stop_rx)
-		mxser_stoprx(tty);
-	if (port->board->chip_flag != MOXA_OTHER_UART) {
-
-		if (*status & UART_LSR_SPECIAL)
-			goto intr_old;
-		if (port->board->chip_flag == MOXA_MUST_MU860_HWID &&
-				(*status & MOXA_MUST_LSR_RERR))
-			goto intr_old;
-		if (*status & MOXA_MUST_LSR_RERR)
-			goto intr_old;
-
-		gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
-
-		if (port->board->chip_flag == MOXA_MUST_MU150_HWID)
-			gdl &= MOXA_MUST_GDL_MASK;
-		if (gdl >= recv_room) {
-			if (!port->ldisc_stop_rx)
-				mxser_stoprx(tty);
-		}
-		while (gdl--) {
-			ch = inb(port->ioaddr + UART_RX);
-			tty_insert_flip_char(tty, ch, 0);
-			cnt++;
-		}
-		goto end_intr;
-	}
-intr_old:
-
-	do {
-		if (max-- < 0)
-			break;
-
-		ch = inb(port->ioaddr + UART_RX);
-		if (port->board->chip_flag && (*status & UART_LSR_OE))
-			outb(0x23, port->ioaddr + UART_FCR);
-		*status &= port->read_status_mask;
-		if (*status & port->ignore_status_mask) {
-			if (++ignored > 100)
-				break;
-		} else {
-			char flag = 0;
-			if (*status & UART_LSR_SPECIAL) {
-				if (*status & UART_LSR_BI) {
-					flag = TTY_BREAK;
-					port->icount.brk++;
-
-					if (port->port.flags & ASYNC_SAK)
-						do_SAK(tty);
-				} else if (*status & UART_LSR_PE) {
-					flag = TTY_PARITY;
-					port->icount.parity++;
-				} else if (*status & UART_LSR_FE) {
-					flag = TTY_FRAME;
-					port->icount.frame++;
-				} else if (*status & UART_LSR_OE) {
-					flag = TTY_OVERRUN;
-					port->icount.overrun++;
-				} else
-					flag = TTY_BREAK;
-			}
-			tty_insert_flip_char(tty, ch, flag);
-			cnt++;
-			if (cnt >= recv_room) {
-				if (!port->ldisc_stop_rx)
-					mxser_stoprx(tty);
-				break;
-			}
-
-		}
-
-		if (port->board->chip_flag)
-			break;
-
-		*status = inb(port->ioaddr + UART_LSR);
-	} while (*status & UART_LSR_DR);
-
-end_intr:
-	mxvar_log.rxcnt[tty->index] += cnt;
-	port->mon_data.rxcnt += cnt;
-	port->mon_data.up_rxcnt += cnt;
-
-	/*
-	 * We are called from an interrupt context with &port->slock
-	 * being held. Drop it temporarily in order to prevent
-	 * recursive locking.
-	 */
-	spin_unlock(&port->slock);
-	tty_flip_buffer_push(tty);
-	spin_lock(&port->slock);
-}
-
-static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
-{
-	int count, cnt;
-
-	if (port->x_char) {
-		outb(port->x_char, port->ioaddr + UART_TX);
-		port->x_char = 0;
-		mxvar_log.txcnt[tty->index]++;
-		port->mon_data.txcnt++;
-		port->mon_data.up_txcnt++;
-		port->icount.tx++;
-		return;
-	}
-
-	if (port->port.xmit_buf == NULL)
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped ||
-			(tty->hw_stopped &&
-			(port->type != PORT_16550A) &&
-			(!port->board->chip_flag))) {
-		port->IER &= ~UART_IER_THRI;
-		outb(port->IER, port->ioaddr + UART_IER);
-		return;
-	}
-
-	cnt = port->xmit_cnt;
-	count = port->xmit_fifo_size;
-	do {
-		outb(port->port.xmit_buf[port->xmit_tail++],
-			port->ioaddr + UART_TX);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-	mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt);
-
-	port->mon_data.txcnt += (cnt - port->xmit_cnt);
-	port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
-	port->icount.tx += (cnt - port->xmit_cnt);
-
-	if (port->xmit_cnt < WAKEUP_CHARS)
-		tty_wakeup(tty);
-
-	if (port->xmit_cnt <= 0) {
-		port->IER &= ~UART_IER_THRI;
-		outb(port->IER, port->ioaddr + UART_IER);
-	}
-}
-
-/*
- * This is the serial driver's generic interrupt routine
- */
-static irqreturn_t mxser_interrupt(int irq, void *dev_id)
-{
-	int status, iir, i;
-	struct mxser_board *brd = NULL;
-	struct mxser_port *port;
-	int max, irqbits, bits, msr;
-	unsigned int int_cnt, pass_counter = 0;
-	int handled = IRQ_NONE;
-	struct tty_struct *tty;
-
-	for (i = 0; i < MXSER_BOARDS; i++)
-		if (dev_id == &mxser_boards[i]) {
-			brd = dev_id;
-			break;
-		}
-
-	if (i == MXSER_BOARDS)
-		goto irq_stop;
-	if (brd == NULL)
-		goto irq_stop;
-	max = brd->info->nports;
-	while (pass_counter++ < MXSER_ISR_PASS_LIMIT) {
-		irqbits = inb(brd->vector) & brd->vector_mask;
-		if (irqbits == brd->vector_mask)
-			break;
-
-		handled = IRQ_HANDLED;
-		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
-			if (irqbits == brd->vector_mask)
-				break;
-			if (bits & irqbits)
-				continue;
-			port = &brd->ports[i];
-
-			int_cnt = 0;
-			spin_lock(&port->slock);
-			do {
-				iir = inb(port->ioaddr + UART_IIR);
-				if (iir & UART_IIR_NO_INT)
-					break;
-				iir &= MOXA_MUST_IIR_MASK;
-				tty = tty_port_tty_get(&port->port);
-				if (!tty ||
-						(port->port.flags & ASYNC_CLOSING) ||
-						!(port->port.flags &
-							ASYNC_INITIALIZED)) {
-					status = inb(port->ioaddr + UART_LSR);
-					outb(0x27, port->ioaddr + UART_FCR);
-					inb(port->ioaddr + UART_MSR);
-					tty_kref_put(tty);
-					break;
-				}
-
-				status = inb(port->ioaddr + UART_LSR);
-
-				if (status & UART_LSR_PE)
-					port->err_shadow |= NPPI_NOTIFY_PARITY;
-				if (status & UART_LSR_FE)
-					port->err_shadow |= NPPI_NOTIFY_FRAMING;
-				if (status & UART_LSR_OE)
-					port->err_shadow |=
-						NPPI_NOTIFY_HW_OVERRUN;
-				if (status & UART_LSR_BI)
-					port->err_shadow |= NPPI_NOTIFY_BREAK;
-
-				if (port->board->chip_flag) {
-					if (iir == MOXA_MUST_IIR_GDA ||
-					    iir == MOXA_MUST_IIR_RDA ||
-					    iir == MOXA_MUST_IIR_RTO ||
-					    iir == MOXA_MUST_IIR_LSR)
-						mxser_receive_chars(tty, port,
-								&status);
-
-				} else {
-					status &= port->read_status_mask;
-					if (status & UART_LSR_DR)
-						mxser_receive_chars(tty, port,
-								&status);
-				}
-				msr = inb(port->ioaddr + UART_MSR);
-				if (msr & UART_MSR_ANY_DELTA)
-					mxser_check_modem_status(tty, port, msr);
-
-				if (port->board->chip_flag) {
-					if (iir == 0x02 && (status &
-								UART_LSR_THRE))
-						mxser_transmit_chars(tty, port);
-				} else {
-					if (status & UART_LSR_THRE)
-						mxser_transmit_chars(tty, port);
-				}
-				tty_kref_put(tty);
-			} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
-			spin_unlock(&port->slock);
-		}
-	}
-
-irq_stop:
-	return handled;
-}
-
-static const struct tty_operations mxser_ops = {
-	.open = mxser_open,
-	.close = mxser_close,
-	.write = mxser_write,
-	.put_char = mxser_put_char,
-	.flush_chars = mxser_flush_chars,
-	.write_room = mxser_write_room,
-	.chars_in_buffer = mxser_chars_in_buffer,
-	.flush_buffer = mxser_flush_buffer,
-	.ioctl = mxser_ioctl,
-	.throttle = mxser_throttle,
-	.unthrottle = mxser_unthrottle,
-	.set_termios = mxser_set_termios,
-	.stop = mxser_stop,
-	.start = mxser_start,
-	.hangup = mxser_hangup,
-	.break_ctl = mxser_rs_break,
-	.wait_until_sent = mxser_wait_until_sent,
-	.tiocmget = mxser_tiocmget,
-	.tiocmset = mxser_tiocmset,
-	.get_icount = mxser_get_icount,
-};
-
-struct tty_port_operations mxser_port_ops = {
-	.carrier_raised = mxser_carrier_raised,
-	.dtr_rts = mxser_dtr_rts,
-	.activate = mxser_activate,
-	.shutdown = mxser_shutdown_port,
-};
-
-/*
- * The MOXA Smartio/Industio serial driver boot-time initialization code!
- */
-
-static void mxser_release_ISA_res(struct mxser_board *brd)
-{
-	free_irq(brd->irq, brd);
-	release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-	release_region(brd->vector, 1);
-}
-
-static int __devinit mxser_initbrd(struct mxser_board *brd,
-		struct pci_dev *pdev)
-{
-	struct mxser_port *info;
-	unsigned int i;
-	int retval;
-
-	printk(KERN_INFO "mxser: max. baud rate = %d bps\n",
-			brd->ports[0].max_baud);
-
-	for (i = 0; i < brd->info->nports; i++) {
-		info = &brd->ports[i];
-		tty_port_init(&info->port);
-		info->port.ops = &mxser_port_ops;
-		info->board = brd;
-		info->stop_rx = 0;
-		info->ldisc_stop_rx = 0;
-
-		/* Enhance mode enabled here */
-		if (brd->chip_flag != MOXA_OTHER_UART)
-			mxser_enable_must_enchance_mode(info->ioaddr);
-
-		info->port.flags = ASYNC_SHARE_IRQ;
-		info->type = brd->uart_type;
-
-		process_txrx_fifo(info);
-
-		info->custom_divisor = info->baud_base * 16;
-		info->port.close_delay = 5 * HZ / 10;
-		info->port.closing_wait = 30 * HZ;
-		info->normal_termios = mxvar_sdriver->init_termios;
-		memset(&info->mon_data, 0, sizeof(struct mxser_mon));
-		info->err_shadow = 0;
-		spin_lock_init(&info->slock);
-
-		/* before set INT ISR, disable all int */
-		outb(inb(info->ioaddr + UART_IER) & 0xf0,
-			info->ioaddr + UART_IER);
-	}
-
-	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
-			brd);
-	if (retval)
-		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
-			"conflict with another device.\n",
-			brd->info->name, brd->irq);
-
-	return retval;
-}
-
-static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
-{
-	int id, i, bits;
-	unsigned short regs[16], irq;
-	unsigned char scratch, scratch2;
-
-	brd->chip_flag = MOXA_OTHER_UART;
-
-	id = mxser_read_register(cap, regs);
-	switch (id) {
-	case C168_ASIC_ID:
-		brd->info = &mxser_cards[0];
-		break;
-	case C104_ASIC_ID:
-		brd->info = &mxser_cards[1];
-		break;
-	case CI104J_ASIC_ID:
-		brd->info = &mxser_cards[2];
-		break;
-	case C102_ASIC_ID:
-		brd->info = &mxser_cards[5];
-		break;
-	case CI132_ASIC_ID:
-		brd->info = &mxser_cards[6];
-		break;
-	case CI134_ASIC_ID:
-		brd->info = &mxser_cards[7];
-		break;
-	default:
-		return 0;
-	}
-
-	irq = 0;
-	/* some ISA cards have 2 ports, but we want to see them as 4-port (why?)
-	   Flag-hack checks if configuration should be read as 2-port here. */
-	if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) {
-		irq = regs[9] & 0xF000;
-		irq = irq | (irq >> 4);
-		if (irq != (regs[9] & 0xFF00))
-			goto err_irqconflict;
-	} else if (brd->info->nports == 4) {
-		irq = regs[9] & 0xF000;
-		irq = irq | (irq >> 4);
-		irq = irq | (irq >> 8);
-		if (irq != regs[9])
-			goto err_irqconflict;
-	} else if (brd->info->nports == 8) {
-		irq = regs[9] & 0xF000;
-		irq = irq | (irq >> 4);
-		irq = irq | (irq >> 8);
-		if ((irq != regs[9]) || (irq != regs[10]))
-			goto err_irqconflict;
-	}
-
-	if (!irq) {
-		printk(KERN_ERR "mxser: interrupt number unset\n");
-		return -EIO;
-	}
-	brd->irq = ((int)(irq & 0xF000) >> 12);
-	for (i = 0; i < 8; i++)
-		brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
-	if ((regs[12] & 0x80) == 0) {
-		printk(KERN_ERR "mxser: invalid interrupt vector\n");
-		return -EIO;
-	}
-	brd->vector = (int)regs[11];	/* interrupt vector */
-	if (id == 1)
-		brd->vector_mask = 0x00FF;
-	else
-		brd->vector_mask = 0x000F;
-	for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
-		if (regs[12] & bits) {
-			brd->ports[i].baud_base = 921600;
-			brd->ports[i].max_baud = 921600;
-		} else {
-			brd->ports[i].baud_base = 115200;
-			brd->ports[i].max_baud = 115200;
-		}
-	}
-	scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
-	outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
-	outb(0, cap + UART_EFR);	/* EFR is the same as FCR */
-	outb(scratch2, cap + UART_LCR);
-	outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
-	scratch = inb(cap + UART_IIR);
-
-	if (scratch & 0xC0)
-		brd->uart_type = PORT_16550A;
-	else
-		brd->uart_type = PORT_16450;
-	if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
-			"mxser(IO)")) {
-		printk(KERN_ERR "mxser: can't request ports I/O region: "
-				"0x%.8lx-0x%.8lx\n",
-				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
-				8 * brd->info->nports - 1);
-		return -EIO;
-	}
-	if (!request_region(brd->vector, 1, "mxser(vector)")) {
-		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-		printk(KERN_ERR "mxser: can't request interrupt vector region: "
-				"0x%.8lx-0x%.8lx\n",
-				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
-				8 * brd->info->nports - 1);
-		return -EIO;
-	}
-	return brd->info->nports;
-
-err_irqconflict:
-	printk(KERN_ERR "mxser: invalid interrupt number\n");
-	return -EIO;
-}
-
-static int __devinit mxser_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-#ifdef CONFIG_PCI
-	struct mxser_board *brd;
-	unsigned int i, j;
-	unsigned long ioaddress;
-	int retval = -EINVAL;
-
-	for (i = 0; i < MXSER_BOARDS; i++)
-		if (mxser_boards[i].info == NULL)
-			break;
-
-	if (i >= MXSER_BOARDS) {
-		dev_err(&pdev->dev, "too many boards found (maximum %d), board "
-				"not configured\n", MXSER_BOARDS);
-		goto err;
-	}
-
-	brd = &mxser_boards[i];
-	brd->idx = i * MXSER_PORTS_PER_BOARD;
-	dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n",
-		mxser_cards[ent->driver_data].name,
-		pdev->bus->number, PCI_SLOT(pdev->devfn));
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "PCI enable failed\n");
-		goto err;
-	}
-
-	/* io address */
-	ioaddress = pci_resource_start(pdev, 2);
-	retval = pci_request_region(pdev, 2, "mxser(IO)");
-	if (retval)
-		goto err_dis;
-
-	brd->info = &mxser_cards[ent->driver_data];
-	for (i = 0; i < brd->info->nports; i++)
-		brd->ports[i].ioaddr = ioaddress + 8 * i;
-
-	/* vector */
-	ioaddress = pci_resource_start(pdev, 3);
-	retval = pci_request_region(pdev, 3, "mxser(vector)");
-	if (retval)
-		goto err_zero;
-	brd->vector = ioaddress;
-
-	/* irq */
-	brd->irq = pdev->irq;
-
-	brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr);
-	brd->uart_type = PORT_16550A;
-	brd->vector_mask = 0;
-
-	for (i = 0; i < brd->info->nports; i++) {
-		for (j = 0; j < UART_INFO_NUM; j++) {
-			if (Gpci_uart_info[j].type == brd->chip_flag) {
-				brd->ports[i].max_baud =
-					Gpci_uart_info[j].max_baud;
-
-				/* exception....CP-102 */
-				if (brd->info->flags & MXSER_HIGHBAUD)
-					brd->ports[i].max_baud = 921600;
-				break;
-			}
-		}
-	}
-
-	if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
-		for (i = 0; i < brd->info->nports; i++) {
-			if (i < 4)
-				brd->ports[i].opmode_ioaddr = ioaddress + 4;
-			else
-				brd->ports[i].opmode_ioaddr = ioaddress + 0x0c;
-		}
-		outb(0, ioaddress + 4);	/* default set to RS232 mode */
-		outb(0, ioaddress + 0x0c);	/* default set to RS232 mode */
-	}
-
-	for (i = 0; i < brd->info->nports; i++) {
-		brd->vector_mask |= (1 << i);
-		brd->ports[i].baud_base = 921600;
-	}
-
-	/* mxser_initbrd will hook ISR. */
-	retval = mxser_initbrd(brd, pdev);
-	if (retval)
-		goto err_rel3;
-
-	for (i = 0; i < brd->info->nports; i++)
-		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
-
-	pci_set_drvdata(pdev, brd);
-
-	return 0;
-err_rel3:
-	pci_release_region(pdev, 3);
-err_zero:
-	brd->info = NULL;
-	pci_release_region(pdev, 2);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return retval;
-#else
-	return -ENODEV;
-#endif
-}
-
-static void __devexit mxser_remove(struct pci_dev *pdev)
-{
-#ifdef CONFIG_PCI
-	struct mxser_board *brd = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	for (i = 0; i < brd->info->nports; i++)
-		tty_unregister_device(mxvar_sdriver, brd->idx + i);
-
-	free_irq(pdev->irq, brd);
-	pci_release_region(pdev, 2);
-	pci_release_region(pdev, 3);
-	pci_disable_device(pdev);
-	brd->info = NULL;
-#endif
-}
-
-static struct pci_driver mxser_driver = {
-	.name = "mxser",
-	.id_table = mxser_pcibrds,
-	.probe = mxser_probe,
-	.remove = __devexit_p(mxser_remove)
-};
-
-static int __init mxser_module_init(void)
-{
-	struct mxser_board *brd;
-	unsigned int b, i, m;
-	int retval;
-
-	mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
-	if (!mxvar_sdriver)
-		return -ENOMEM;
-
-	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
-		MXSER_VERSION);
-
-	/* Initialize the tty_driver structure */
-	mxvar_sdriver->owner = THIS_MODULE;
-	mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
-	mxvar_sdriver->name = "ttyMI";
-	mxvar_sdriver->major = ttymajor;
-	mxvar_sdriver->minor_start = 0;
-	mxvar_sdriver->num = MXSER_PORTS + 1;
-	mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
-	mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
-	mxvar_sdriver->init_termios = tty_std_termios;
-	mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-	mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(mxvar_sdriver, &mxser_ops);
-
-	retval = tty_register_driver(mxvar_sdriver);
-	if (retval) {
-		printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family "
-				"tty driver !\n");
-		goto err_put;
-	}
-
-	/* Start finding ISA boards here */
-	for (m = 0, b = 0; b < MXSER_BOARDS; b++) {
-		if (!ioaddr[b])
-			continue;
-
-		brd = &mxser_boards[m];
-		retval = mxser_get_ISA_conf(ioaddr[b], brd);
-		if (retval <= 0) {
-			brd->info = NULL;
-			continue;
-		}
-
-		printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n",
-				brd->info->name, ioaddr[b]);
-
-		/* mxser_initbrd will hook ISR. */
-		if (mxser_initbrd(brd, NULL) < 0) {
-			brd->info = NULL;
-			continue;
-		}
-
-		brd->idx = m * MXSER_PORTS_PER_BOARD;
-		for (i = 0; i < brd->info->nports; i++)
-			tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
-
-		m++;
-	}
-
-	retval = pci_register_driver(&mxser_driver);
-	if (retval) {
-		printk(KERN_ERR "mxser: can't register pci driver\n");
-		if (!m) {
-			retval = -ENODEV;
-			goto err_unr;
-		} /* else: we have some ISA cards under control */
-	}
-
-	return 0;
-err_unr:
-	tty_unregister_driver(mxvar_sdriver);
-err_put:
-	put_tty_driver(mxvar_sdriver);
-	return retval;
-}
-
-static void __exit mxser_module_exit(void)
-{
-	unsigned int i, j;
-
-	pci_unregister_driver(&mxser_driver);
-
-	for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
-		if (mxser_boards[i].info != NULL)
-			for (j = 0; j < mxser_boards[i].info->nports; j++)
-				tty_unregister_device(mxvar_sdriver,
-						mxser_boards[i].idx + j);
-	tty_unregister_driver(mxvar_sdriver);
-	put_tty_driver(mxvar_sdriver);
-
-	for (i = 0; i < MXSER_BOARDS; i++)
-		if (mxser_boards[i].info != NULL)
-			mxser_release_ISA_res(&mxser_boards[i]);
-}
-
-module_init(mxser_module_init);
-module_exit(mxser_module_exit);
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h
deleted file mode 100644
index 41878a6..0000000
--- a/drivers/char/mxser.h
+++ /dev/null
@@ -1,150 +0,0 @@
-#ifndef _MXSER_H
-#define _MXSER_H
-
-/*
- *	Semi-public control interfaces
- */
-
-/*
- *	MOXA ioctls
- */
-
-#define MOXA			0x400
-#define MOXA_GETDATACOUNT	(MOXA + 23)
-#define MOXA_DIAGNOSE		(MOXA + 50)
-#define MOXA_CHKPORTENABLE	(MOXA + 60)
-#define MOXA_HighSpeedOn	(MOXA + 61)
-#define MOXA_GET_MAJOR		(MOXA + 63)
-#define MOXA_GETMSTATUS		(MOXA + 65)
-#define MOXA_SET_OP_MODE	(MOXA + 66)
-#define MOXA_GET_OP_MODE	(MOXA + 67)
-
-#define RS232_MODE		0
-#define RS485_2WIRE_MODE	1
-#define RS422_MODE		2
-#define RS485_4WIRE_MODE	3
-#define OP_MODE_MASK		3
-
-#define MOXA_SDS_RSTICOUNTER	(MOXA + 69)
-#define MOXA_ASPP_OQUEUE  	(MOXA + 70)
-#define MOXA_ASPP_MON     	(MOXA + 73)
-#define MOXA_ASPP_LSTATUS 	(MOXA + 74)
-#define MOXA_ASPP_MON_EXT 	(MOXA + 75)
-#define MOXA_SET_BAUD_METHOD	(MOXA + 76)
-
-/* --------------------------------------------------- */
-
-#define NPPI_NOTIFY_PARITY	0x01
-#define NPPI_NOTIFY_FRAMING	0x02
-#define NPPI_NOTIFY_HW_OVERRUN	0x04
-#define NPPI_NOTIFY_SW_OVERRUN	0x08
-#define NPPI_NOTIFY_BREAK	0x10
-
-#define NPPI_NOTIFY_CTSHOLD         0x01	/* Tx hold by CTS low */
-#define NPPI_NOTIFY_DSRHOLD         0x02	/* Tx hold by DSR low */
-#define NPPI_NOTIFY_XOFFHOLD        0x08	/* Tx hold by Xoff received */
-#define NPPI_NOTIFY_XOFFXENT        0x10	/* Xoff Sent */
-
-/* follow just for Moxa Must chip define. */
-/* */
-/* when LCR register (offset 0x03) write following value, */
-/* the Must chip will enter enchance mode. And write value */
-/* on EFR (offset 0x02) bit 6,7 to change bank. */
-#define MOXA_MUST_ENTER_ENCHANCE	0xBF
-
-/* when enhance mode enable, access on general bank register */
-#define MOXA_MUST_GDL_REGISTER		0x07
-#define MOXA_MUST_GDL_MASK		0x7F
-#define MOXA_MUST_GDL_HAS_BAD_DATA	0x80
-
-#define MOXA_MUST_LSR_RERR		0x80	/* error in receive FIFO */
-/* enchance register bank select and enchance mode setting register */
-/* when LCR register equal to 0xBF */
-#define MOXA_MUST_EFR_REGISTER		0x02
-/* enchance mode enable */
-#define MOXA_MUST_EFR_EFRB_ENABLE	0x10
-/* enchance reister bank set 0, 1, 2 */
-#define MOXA_MUST_EFR_BANK0		0x00
-#define MOXA_MUST_EFR_BANK1		0x40
-#define MOXA_MUST_EFR_BANK2		0x80
-#define MOXA_MUST_EFR_BANK3		0xC0
-#define MOXA_MUST_EFR_BANK_MASK		0xC0
-
-/* set XON1 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XON1_REGISTER		0x04
-
-/* set XON2 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XON2_REGISTER		0x05
-
-/* set XOFF1 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XOFF1_REGISTER	0x06
-
-/* set XOFF2 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XOFF2_REGISTER	0x07
-
-#define MOXA_MUST_RBRTL_REGISTER	0x04
-#define MOXA_MUST_RBRTH_REGISTER	0x05
-#define MOXA_MUST_RBRTI_REGISTER	0x06
-#define MOXA_MUST_THRTL_REGISTER	0x07
-#define MOXA_MUST_ENUM_REGISTER		0x04
-#define MOXA_MUST_HWID_REGISTER		0x05
-#define MOXA_MUST_ECR_REGISTER		0x06
-#define MOXA_MUST_CSR_REGISTER		0x07
-
-/* good data mode enable */
-#define MOXA_MUST_FCR_GDA_MODE_ENABLE	0x20
-/* only good data put into RxFIFO */
-#define MOXA_MUST_FCR_GDA_ONLY_ENABLE	0x10
-
-/* enable CTS interrupt */
-#define MOXA_MUST_IER_ECTSI		0x80
-/* enable RTS interrupt */
-#define MOXA_MUST_IER_ERTSI		0x40
-/* enable Xon/Xoff interrupt */
-#define MOXA_MUST_IER_XINT		0x20
-/* enable GDA interrupt */
-#define MOXA_MUST_IER_EGDAI		0x10
-
-#define MOXA_MUST_RECV_ISR		(UART_IER_RDI | MOXA_MUST_IER_EGDAI)
-
-/* GDA interrupt pending */
-#define MOXA_MUST_IIR_GDA		0x1C
-#define MOXA_MUST_IIR_RDA		0x04
-#define MOXA_MUST_IIR_RTO		0x0C
-#define MOXA_MUST_IIR_LSR		0x06
-
-/* recieved Xon/Xoff or specical interrupt pending */
-#define MOXA_MUST_IIR_XSC		0x10
-
-/* RTS/CTS change state interrupt pending */
-#define MOXA_MUST_IIR_RTSCTS		0x20
-#define MOXA_MUST_IIR_MASK		0x3E
-
-#define MOXA_MUST_MCR_XON_FLAG		0x40
-#define MOXA_MUST_MCR_XON_ANY		0x80
-#define MOXA_MUST_MCR_TX_XON		0x08
-
-/* software flow control on chip mask value */
-#define MOXA_MUST_EFR_SF_MASK		0x0F
-/* send Xon1/Xoff1 */
-#define MOXA_MUST_EFR_SF_TX1		0x08
-/* send Xon2/Xoff2 */
-#define MOXA_MUST_EFR_SF_TX2		0x04
-/* send Xon1,Xon2/Xoff1,Xoff2 */
-#define MOXA_MUST_EFR_SF_TX12		0x0C
-/* don't send Xon/Xoff */
-#define MOXA_MUST_EFR_SF_TX_NO		0x00
-/* Tx software flow control mask */
-#define MOXA_MUST_EFR_SF_TX_MASK	0x0C
-/* don't receive Xon/Xoff */
-#define MOXA_MUST_EFR_SF_RX_NO		0x00
-/* receive Xon1/Xoff1 */
-#define MOXA_MUST_EFR_SF_RX1		0x02
-/* receive Xon2/Xoff2 */
-#define MOXA_MUST_EFR_SF_RX2		0x01
-/* receive Xon1,Xon2/Xoff1,Xoff2 */
-#define MOXA_MUST_EFR_SF_RX12		0x03
-/* Rx software flow control mask */
-#define MOXA_MUST_EFR_SF_RX_MASK	0x03
-
-#endif
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
deleted file mode 100644
index 294d03e..0000000
--- a/drivers/char/nozomi.c
+++ /dev/null
@@ -1,1993 +0,0 @@
-/*
- * nozomi.c  -- HSDPA driver Broadband Wireless Data Card - Globe Trotter
- *
- * Written by: Ulf Jakobsson,
- *             Jan Ăkerfeldt,
- *             Stefan Thomasson,
- *
- * Maintained by: Paul Hardwick (p.hardwick@option.com)
- *
- * Patches:
- *          Locking code changes for Vodafone by Sphere Systems Ltd,
- *                              Andrew Bird (ajb@spheresystems.co.uk )
- *                              & Phil Sanderson
- *
- * Source has been ported from an implementation made by Filip Aben @ Option
- *
- * --------------------------------------------------------------------------
- *
- * Copyright (c) 2005,2006 Option Wireless Sweden AB
- * Copyright (c) 2006 Sphere Systems Ltd
- * Copyright (c) 2006 Option Wireless n/v
- * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * --------------------------------------------------------------------------
- */
-
-/* Enable this to have a lot of debug printouts */
-#define DEBUG
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/interrupt.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/kfifo.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include <linux/delay.h>
-
-
-#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \
-					__DATE__ " " __TIME__ ")"
-
-/*    Macros definitions */
-
-/* Default debug printout level */
-#define NOZOMI_DEBUG_LEVEL 0x00
-
-#define P_BUF_SIZE 128
-#define NFO(_err_flag_, args...)				\
-do {								\
-	char tmp[P_BUF_SIZE];					\
-	snprintf(tmp, sizeof(tmp), ##args);			\
-	printk(_err_flag_ "[%d] %s(): %s\n", __LINE__,		\
-		__func__, tmp);				\
-} while (0)
-
-#define DBG1(args...) D_(0x01, ##args)
-#define DBG2(args...) D_(0x02, ##args)
-#define DBG3(args...) D_(0x04, ##args)
-#define DBG4(args...) D_(0x08, ##args)
-#define DBG5(args...) D_(0x10, ##args)
-#define DBG6(args...) D_(0x20, ##args)
-#define DBG7(args...) D_(0x40, ##args)
-#define DBG8(args...) D_(0x80, ##args)
-
-#ifdef DEBUG
-/* Do we need this settable at runtime? */
-static int debug = NOZOMI_DEBUG_LEVEL;
-
-#define D(lvl, args...)  do \
-			{if (lvl & debug) NFO(KERN_DEBUG, ##args); } \
-			while (0)
-#define D_(lvl, args...) D(lvl, ##args)
-
-/* These printouts are always printed */
-
-#else
-static int debug;
-#define D_(lvl, args...)
-#endif
-
-/* TODO: rewrite to optimize macros... */
-
-#define TMP_BUF_MAX 256
-
-#define DUMP(buf__,len__) \
-  do {  \
-    char tbuf[TMP_BUF_MAX] = {0};\
-    if (len__ > 1) {\
-	snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\
-	if (tbuf[len__-2] == '\r') {\
-		tbuf[len__-2] = 'r';\
-	} \
-	DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\
-    } else {\
-	DBG1("SENDING: '%s' (%d)", tbuf, len__);\
-    } \
-} while (0)
-
-/*    Defines */
-#define NOZOMI_NAME		"nozomi"
-#define NOZOMI_NAME_TTY		"nozomi_tty"
-#define DRIVER_DESC		"Nozomi driver"
-
-#define NTTY_TTY_MAXMINORS	256
-#define NTTY_FIFO_BUFFER_SIZE	8192
-
-/* Must be power of 2 */
-#define FIFO_BUFFER_SIZE_UL	8192
-
-/* Size of tmp send buffer to card */
-#define SEND_BUF_MAX		1024
-#define RECEIVE_BUF_MAX		4
-
-
-#define R_IIR		0x0000	/* Interrupt Identity Register */
-#define R_FCR		0x0000	/* Flow Control Register */
-#define R_IER		0x0004	/* Interrupt Enable Register */
-
-#define CONFIG_MAGIC	0xEFEFFEFE
-#define TOGGLE_VALID	0x0000
-
-/* Definition of interrupt tokens */
-#define MDM_DL1		0x0001
-#define MDM_UL1		0x0002
-#define MDM_DL2		0x0004
-#define MDM_UL2		0x0008
-#define DIAG_DL1	0x0010
-#define DIAG_DL2	0x0020
-#define DIAG_UL		0x0040
-#define APP1_DL		0x0080
-#define APP1_UL		0x0100
-#define APP2_DL		0x0200
-#define APP2_UL		0x0400
-#define CTRL_DL		0x0800
-#define CTRL_UL		0x1000
-#define RESET		0x8000
-
-#define MDM_DL		(MDM_DL1  | MDM_DL2)
-#define MDM_UL		(MDM_UL1  | MDM_UL2)
-#define DIAG_DL		(DIAG_DL1 | DIAG_DL2)
-
-/* modem signal definition */
-#define CTRL_DSR	0x0001
-#define CTRL_DCD	0x0002
-#define CTRL_RI		0x0004
-#define CTRL_CTS	0x0008
-
-#define CTRL_DTR	0x0001
-#define CTRL_RTS	0x0002
-
-#define MAX_PORT		4
-#define NOZOMI_MAX_PORTS	5
-#define NOZOMI_MAX_CARDS	(NTTY_TTY_MAXMINORS / MAX_PORT)
-
-/*    Type definitions */
-
-/*
- * There are two types of nozomi cards,
- * one with 2048 memory and with 8192 memory
- */
-enum card_type {
-	F32_2 = 2048,	/* 512 bytes downlink + uplink * 2 -> 2048 */
-	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
-};
-
-/* Initialization states a card can be in */
-enum card_state {
-	NOZOMI_STATE_UKNOWN	= 0,
-	NOZOMI_STATE_ENABLED	= 1,	/* pci device enabled */
-	NOZOMI_STATE_ALLOCATED	= 2,	/* config setup done */
-	NOZOMI_STATE_READY	= 3,	/* flowcontrols received */
-};
-
-/* Two different toggle channels exist */
-enum channel_type {
-	CH_A = 0,
-	CH_B = 1,
-};
-
-/* Port definition for the card regarding flow control */
-enum ctrl_port_type {
-	CTRL_CMD	= 0,
-	CTRL_MDM	= 1,
-	CTRL_DIAG	= 2,
-	CTRL_APP1	= 3,
-	CTRL_APP2	= 4,
-	CTRL_ERROR	= -1,
-};
-
-/* Ports that the nozomi has */
-enum port_type {
-	PORT_MDM	= 0,
-	PORT_DIAG	= 1,
-	PORT_APP1	= 2,
-	PORT_APP2	= 3,
-	PORT_CTRL	= 4,
-	PORT_ERROR	= -1,
-};
-
-#ifdef __BIG_ENDIAN
-/* Big endian */
-
-struct toggles {
-	unsigned int enabled:5;	/*
-				 * Toggle fields are valid if enabled is 0,
-				 * else A-channels must always be used.
-				 */
-	unsigned int diag_dl:1;
-	unsigned int mdm_dl:1;
-	unsigned int mdm_ul:1;
-} __attribute__ ((packed));
-
-/* Configuration table to read at startup of card */
-/* Is for now only needed during initialization phase */
-struct config_table {
-	u32 signature;
-	u16 product_information;
-	u16 version;
-	u8 pad3[3];
-	struct toggles toggle;
-	u8 pad1[4];
-	u16 dl_mdm_len1;	/*
-				 * If this is 64, it can hold
-				 * 60 bytes + 4 that is length field
-				 */
-	u16 dl_start;
-
-	u16 dl_diag_len1;
-	u16 dl_mdm_len2;	/*
-				 * If this is 64, it can hold
-				 * 60 bytes + 4 that is length field
-				 */
-	u16 dl_app1_len;
-
-	u16 dl_diag_len2;
-	u16 dl_ctrl_len;
-	u16 dl_app2_len;
-	u8 pad2[16];
-	u16 ul_mdm_len1;
-	u16 ul_start;
-	u16 ul_diag_len;
-	u16 ul_mdm_len2;
-	u16 ul_app1_len;
-	u16 ul_app2_len;
-	u16 ul_ctrl_len;
-} __attribute__ ((packed));
-
-/* This stores all control downlink flags */
-struct ctrl_dl {
-	u8 port;
-	unsigned int reserved:4;
-	unsigned int CTS:1;
-	unsigned int RI:1;
-	unsigned int DCD:1;
-	unsigned int DSR:1;
-} __attribute__ ((packed));
-
-/* This stores all control uplink flags */
-struct ctrl_ul {
-	u8 port;
-	unsigned int reserved:6;
-	unsigned int RTS:1;
-	unsigned int DTR:1;
-} __attribute__ ((packed));
-
-#else
-/* Little endian */
-
-/* This represents the toggle information */
-struct toggles {
-	unsigned int mdm_ul:1;
-	unsigned int mdm_dl:1;
-	unsigned int diag_dl:1;
-	unsigned int enabled:5;	/*
-				 * Toggle fields are valid if enabled is 0,
-				 * else A-channels must always be used.
-				 */
-} __attribute__ ((packed));
-
-/* Configuration table to read at startup of card */
-struct config_table {
-	u32 signature;
-	u16 version;
-	u16 product_information;
-	struct toggles toggle;
-	u8 pad1[7];
-	u16 dl_start;
-	u16 dl_mdm_len1;	/*
-				 * If this is 64, it can hold
-				 * 60 bytes + 4 that is length field
-				 */
-	u16 dl_mdm_len2;
-	u16 dl_diag_len1;
-	u16 dl_diag_len2;
-	u16 dl_app1_len;
-	u16 dl_app2_len;
-	u16 dl_ctrl_len;
-	u8 pad2[16];
-	u16 ul_start;
-	u16 ul_mdm_len2;
-	u16 ul_mdm_len1;
-	u16 ul_diag_len;
-	u16 ul_app1_len;
-	u16 ul_app2_len;
-	u16 ul_ctrl_len;
-} __attribute__ ((packed));
-
-/* This stores all control downlink flags */
-struct ctrl_dl {
-	unsigned int DSR:1;
-	unsigned int DCD:1;
-	unsigned int RI:1;
-	unsigned int CTS:1;
-	unsigned int reserverd:4;
-	u8 port;
-} __attribute__ ((packed));
-
-/* This stores all control uplink flags */
-struct ctrl_ul {
-	unsigned int DTR:1;
-	unsigned int RTS:1;
-	unsigned int reserved:6;
-	u8 port;
-} __attribute__ ((packed));
-#endif
-
-/* This holds all information that is needed regarding a port */
-struct port {
-	struct tty_port port;
-	u8 update_flow_control;
-	struct ctrl_ul ctrl_ul;
-	struct ctrl_dl ctrl_dl;
-	struct kfifo fifo_ul;
-	void __iomem *dl_addr[2];
-	u32 dl_size[2];
-	u8 toggle_dl;
-	void __iomem *ul_addr[2];
-	u32 ul_size[2];
-	u8 toggle_ul;
-	u16 token_dl;
-
-	/* mutex to ensure one access patch to this port */
-	struct mutex tty_sem;
-	wait_queue_head_t tty_wait;
-	struct async_icount tty_icount;
-
-	struct nozomi *dc;
-};
-
-/* Private data one for each card in the system */
-struct nozomi {
-	void __iomem *base_addr;
-	unsigned long flip;
-
-	/* Pointers to registers */
-	void __iomem *reg_iir;
-	void __iomem *reg_fcr;
-	void __iomem *reg_ier;
-
-	u16 last_ier;
-	enum card_type card_type;
-	struct config_table config_table;	/* Configuration table */
-	struct pci_dev *pdev;
-	struct port port[NOZOMI_MAX_PORTS];
-	u8 *send_buf;
-
-	spinlock_t spin_mutex;	/* secures access to registers and tty */
-
-	unsigned int index_start;
-	enum card_state state;
-	u32 open_ttys;
-};
-
-/* This is a data packet that is read or written to/from card */
-struct buffer {
-	u32 size;		/* size is the length of the data buffer */
-	u8 *data;
-} __attribute__ ((packed));
-
-/*    Global variables */
-static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
-	{PCI_DEVICE(0x1931, 0x000c)},	/* Nozomi HSDPA */
-	{},
-};
-
-MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
-
-static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
-static struct tty_driver *ntty_driver;
-
-static const struct tty_port_operations noz_tty_port_ops;
-
-/*
- * find card by tty_index
- */
-static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
-{
-	return tty ? ndevs[tty->index / MAX_PORT] : NULL;
-}
-
-static inline struct port *get_port_by_tty(const struct tty_struct *tty)
-{
-	struct nozomi *ndev = get_dc_by_tty(tty);
-	return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL;
-}
-
-/*
- * TODO:
- * -Optimize
- * -Rewrite cleaner
- */
-
-static void read_mem32(u32 *buf, const void __iomem *mem_addr_start,
-			u32 size_bytes)
-{
-	u32 i = 0;
-	const u32 __iomem *ptr = mem_addr_start;
-	u16 *buf16;
-
-	if (unlikely(!ptr || !buf))
-		goto out;
-
-	/* shortcut for extremely often used cases */
-	switch (size_bytes) {
-	case 2:	/* 2 bytes */
-		buf16 = (u16 *) buf;
-		*buf16 = __le16_to_cpu(readw(ptr));
-		goto out;
-		break;
-	case 4:	/* 4 bytes */
-		*(buf) = __le32_to_cpu(readl(ptr));
-		goto out;
-		break;
-	}
-
-	while (i < size_bytes) {
-		if (size_bytes - i == 2) {
-			/* Handle 2 bytes in the end */
-			buf16 = (u16 *) buf;
-			*(buf16) = __le16_to_cpu(readw(ptr));
-			i += 2;
-		} else {
-			/* Read 4 bytes */
-			*(buf) = __le32_to_cpu(readl(ptr));
-			i += 4;
-		}
-		buf++;
-		ptr++;
-	}
-out:
-	return;
-}
-
-/*
- * TODO:
- * -Optimize
- * -Rewrite cleaner
- */
-static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf,
-			u32 size_bytes)
-{
-	u32 i = 0;
-	u32 __iomem *ptr = mem_addr_start;
-	const u16 *buf16;
-
-	if (unlikely(!ptr || !buf))
-		return 0;
-
-	/* shortcut for extremely often used cases */
-	switch (size_bytes) {
-	case 2:	/* 2 bytes */
-		buf16 = (const u16 *)buf;
-		writew(__cpu_to_le16(*buf16), ptr);
-		return 2;
-		break;
-	case 1: /*
-		 * also needs to write 4 bytes in this case
-		 * so falling through..
-		 */
-	case 4: /* 4 bytes */
-		writel(__cpu_to_le32(*buf), ptr);
-		return 4;
-		break;
-	}
-
-	while (i < size_bytes) {
-		if (size_bytes - i == 2) {
-			/* 2 bytes */
-			buf16 = (const u16 *)buf;
-			writew(__cpu_to_le16(*buf16), ptr);
-			i += 2;
-		} else {
-			/* 4 bytes */
-			writel(__cpu_to_le32(*buf), ptr);
-			i += 4;
-		}
-		buf++;
-		ptr++;
-	}
-	return i;
-}
-
-/* Setup pointers to different channels and also setup buffer sizes. */
-static void setup_memory(struct nozomi *dc)
-{
-	void __iomem *offset = dc->base_addr + dc->config_table.dl_start;
-	/* The length reported is including the length field of 4 bytes,
-	 * hence subtract with 4.
-	 */
-	const u16 buff_offset = 4;
-
-	/* Modem port dl configuration */
-	dc->port[PORT_MDM].dl_addr[CH_A] = offset;
-	dc->port[PORT_MDM].dl_addr[CH_B] =
-				(offset += dc->config_table.dl_mdm_len1);
-	dc->port[PORT_MDM].dl_size[CH_A] =
-				dc->config_table.dl_mdm_len1 - buff_offset;
-	dc->port[PORT_MDM].dl_size[CH_B] =
-				dc->config_table.dl_mdm_len2 - buff_offset;
-
-	/* Diag port dl configuration */
-	dc->port[PORT_DIAG].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_mdm_len2);
-	dc->port[PORT_DIAG].dl_size[CH_A] =
-				dc->config_table.dl_diag_len1 - buff_offset;
-	dc->port[PORT_DIAG].dl_addr[CH_B] =
-				(offset += dc->config_table.dl_diag_len1);
-	dc->port[PORT_DIAG].dl_size[CH_B] =
-				dc->config_table.dl_diag_len2 - buff_offset;
-
-	/* App1 port dl configuration */
-	dc->port[PORT_APP1].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_diag_len2);
-	dc->port[PORT_APP1].dl_size[CH_A] =
-				dc->config_table.dl_app1_len - buff_offset;
-
-	/* App2 port dl configuration */
-	dc->port[PORT_APP2].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_app1_len);
-	dc->port[PORT_APP2].dl_size[CH_A] =
-				dc->config_table.dl_app2_len - buff_offset;
-
-	/* Ctrl dl configuration */
-	dc->port[PORT_CTRL].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_app2_len);
-	dc->port[PORT_CTRL].dl_size[CH_A] =
-				dc->config_table.dl_ctrl_len - buff_offset;
-
-	offset = dc->base_addr + dc->config_table.ul_start;
-
-	/* Modem Port ul configuration */
-	dc->port[PORT_MDM].ul_addr[CH_A] = offset;
-	dc->port[PORT_MDM].ul_size[CH_A] =
-				dc->config_table.ul_mdm_len1 - buff_offset;
-	dc->port[PORT_MDM].ul_addr[CH_B] =
-				(offset += dc->config_table.ul_mdm_len1);
-	dc->port[PORT_MDM].ul_size[CH_B] =
-				dc->config_table.ul_mdm_len2 - buff_offset;
-
-	/* Diag port ul configuration */
-	dc->port[PORT_DIAG].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_mdm_len2);
-	dc->port[PORT_DIAG].ul_size[CH_A] =
-				dc->config_table.ul_diag_len - buff_offset;
-
-	/* App1 port ul configuration */
-	dc->port[PORT_APP1].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_diag_len);
-	dc->port[PORT_APP1].ul_size[CH_A] =
-				dc->config_table.ul_app1_len - buff_offset;
-
-	/* App2 port ul configuration */
-	dc->port[PORT_APP2].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_app1_len);
-	dc->port[PORT_APP2].ul_size[CH_A] =
-				dc->config_table.ul_app2_len - buff_offset;
-
-	/* Ctrl ul configuration */
-	dc->port[PORT_CTRL].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_app2_len);
-	dc->port[PORT_CTRL].ul_size[CH_A] =
-				dc->config_table.ul_ctrl_len - buff_offset;
-}
-
-/* Dump config table under initalization phase */
-#ifdef DEBUG
-static void dump_table(const struct nozomi *dc)
-{
-	DBG3("signature: 0x%08X", dc->config_table.signature);
-	DBG3("version: 0x%04X", dc->config_table.version);
-	DBG3("product_information: 0x%04X", \
-				dc->config_table.product_information);
-	DBG3("toggle enabled: %d", dc->config_table.toggle.enabled);
-	DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul);
-	DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl);
-	DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl);
-
-	DBG3("dl_start: 0x%04X", dc->config_table.dl_start);
-	DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1,
-	   dc->config_table.dl_mdm_len1);
-	DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2,
-	   dc->config_table.dl_mdm_len2);
-	DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1,
-	   dc->config_table.dl_diag_len1);
-	DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2,
-	   dc->config_table.dl_diag_len2);
-	DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len,
-	   dc->config_table.dl_app1_len);
-	DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len,
-	   dc->config_table.dl_app2_len);
-	DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len,
-	   dc->config_table.dl_ctrl_len);
-	DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start,
-	   dc->config_table.ul_start);
-	DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1,
-	   dc->config_table.ul_mdm_len1);
-	DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2,
-	   dc->config_table.ul_mdm_len2);
-	DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len,
-	   dc->config_table.ul_diag_len);
-	DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len,
-	   dc->config_table.ul_app1_len);
-	DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len,
-	   dc->config_table.ul_app2_len);
-	DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len,
-	   dc->config_table.ul_ctrl_len);
-}
-#else
-static inline void dump_table(const struct nozomi *dc) { }
-#endif
-
-/*
- * Read configuration table from card under intalization phase
- * Returns 1 if ok, else 0
- */
-static int nozomi_read_config_table(struct nozomi *dc)
-{
-	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
-						sizeof(struct config_table));
-
-	if (dc->config_table.signature != CONFIG_MAGIC) {
-		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
-			dc->config_table.signature, CONFIG_MAGIC);
-		return 0;
-	}
-
-	if ((dc->config_table.version == 0)
-	    || (dc->config_table.toggle.enabled == TOGGLE_VALID)) {
-		int i;
-		DBG1("Second phase, configuring card");
-
-		setup_memory(dc);
-
-		dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
-		dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
-		dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl;
-		DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d",
-		   dc->port[PORT_MDM].toggle_ul,
-		   dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl);
-
-		dump_table(dc);
-
-		for (i = PORT_MDM; i < MAX_PORT; i++) {
-			memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
-			memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
-		}
-
-		/* Enable control channel */
-		dc->last_ier = dc->last_ier | CTRL_DL;
-		writew(dc->last_ier, dc->reg_ier);
-
-		dc->state = NOZOMI_STATE_ALLOCATED;
-		dev_info(&dc->pdev->dev, "Initialization OK!\n");
-		return 1;
-	}
-
-	if ((dc->config_table.version > 0)
-	    && (dc->config_table.toggle.enabled != TOGGLE_VALID)) {
-		u32 offset = 0;
-		DBG1("First phase: pushing upload buffers, clearing download");
-
-		dev_info(&dc->pdev->dev, "Version of card: %d\n",
-			 dc->config_table.version);
-
-		/* Here we should disable all I/O over F32. */
-		setup_memory(dc);
-
-		/*
-		 * We should send ALL channel pair tokens back along
-		 * with reset token
-		 */
-
-		/* push upload modem buffers */
-		write_mem32(dc->port[PORT_MDM].ul_addr[CH_A],
-			(u32 *) &offset, 4);
-		write_mem32(dc->port[PORT_MDM].ul_addr[CH_B],
-			(u32 *) &offset, 4);
-
-		writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr);
-
-		DBG1("First phase done");
-	}
-
-	return 1;
-}
-
-/* Enable uplink interrupts  */
-static void enable_transmit_ul(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier |= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/* Disable uplink interrupts  */
-static void disable_transmit_ul(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] =
-		{~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier &= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/* Enable downlink interrupts */
-static void enable_transmit_dl(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier |= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/* Disable downlink interrupts */
-static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] =
-		{~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier &= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/*
- * Return 1 - send buffer to card and ack.
- * Return 0 - don't ack, don't send buffer to card.
- */
-static int send_data(enum port_type index, struct nozomi *dc)
-{
-	u32 size = 0;
-	struct port *port = &dc->port[index];
-	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,
-			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
-
-	if (size == 0) {
-		DBG4("No more data to send, disable link:");
-		tty_kref_put(tty);
-		return 0;
-	}
-
-	/* DUMP(buf, size); */
-
-	/* Write length + data */
-	write_mem32(addr, (u32 *) &size, 4);
-	write_mem32(addr + 4, (u32 *) dc->send_buf, size);
-
-	if (tty)
-		tty_wakeup(tty);
-
-	tty_kref_put(tty);
-	return 1;
-}
-
-/* If all data has been read, return 1, else 0 */
-static int receive_data(enum port_type index, struct nozomi *dc)
-{
-	u8 buf[RECEIVE_BUF_MAX] = { 0 };
-	int size;
-	u32 offset = 4;
-	struct port *port = &dc->port[index];
-	void __iomem *addr = port->dl_addr[port->toggle_dl];
-	struct tty_struct *tty = tty_port_tty_get(&port->port);
-	int i, ret;
-
-	if (unlikely(!tty)) {
-		DBG1("tty not open for port: %d?", index);
-		return 1;
-	}
-
-	read_mem32((u32 *) &size, addr, 4);
-	/*  DBG1( "%d bytes port: %d", size, index); */
-
-	if (test_bit(TTY_THROTTLED, &tty->flags)) {
-		DBG1("No room in tty, don't read data, don't ack interrupt, "
-			"disable interrupt");
-
-		/* disable interrupt in downlink... */
-		disable_transmit_dl(index, dc);
-		ret = 0;
-		goto put;
-	}
-
-	if (unlikely(size == 0)) {
-		dev_err(&dc->pdev->dev, "size == 0?\n");
-		ret = 1;
-		goto put;
-	}
-
-	while (size > 0) {
-		read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
-
-		if (size == 1) {
-			tty_insert_flip_char(tty, buf[0], TTY_NORMAL);
-			size = 0;
-		} else if (size < RECEIVE_BUF_MAX) {
-			size -= tty_insert_flip_string(tty, (char *) buf, size);
-		} else {
-			i = tty_insert_flip_string(tty, \
-						(char *) buf, RECEIVE_BUF_MAX);
-			size -= i;
-			offset += i;
-		}
-	}
-
-	set_bit(index, &dc->flip);
-	ret = 1;
-put:
-	tty_kref_put(tty);
-	return ret;
-}
-
-/* Debug for interrupts */
-#ifdef DEBUG
-static char *interrupt2str(u16 interrupt)
-{
-	static char buf[TMP_BUF_MAX];
-	char *p = buf;
-
-	interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL;
-	interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"MDM_DL2 ") : NULL;
-
-	interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"MDM_UL1 ") : NULL;
-	interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"MDM_UL2 ") : NULL;
-
-	interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"DIAG_DL1 ") : NULL;
-	interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"DIAG_DL2 ") : NULL;
-
-	interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"DIAG_UL ") : NULL;
-
-	interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP1_DL ") : NULL;
-	interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP2_DL ") : NULL;
-
-	interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP1_UL ") : NULL;
-	interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP2_UL ") : NULL;
-
-	interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"CTRL_DL ") : NULL;
-	interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"CTRL_UL ") : NULL;
-
-	interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"RESET ") : NULL;
-
-	return buf;
-}
-#endif
-
-/*
- * Receive flow control
- * Return 1 - If ok, else 0
- */
-static int receive_flow_control(struct nozomi *dc)
-{
-	enum port_type port = PORT_MDM;
-	struct ctrl_dl ctrl_dl;
-	struct ctrl_dl old_ctrl;
-	u16 enable_ier = 0;
-
-	read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2);
-
-	switch (ctrl_dl.port) {
-	case CTRL_CMD:
-		DBG1("The Base Band sends this value as a response to a "
-			"request for IMSI detach sent over the control "
-			"channel uplink (see section 7.6.1).");
-		break;
-	case CTRL_MDM:
-		port = PORT_MDM;
-		enable_ier = MDM_DL;
-		break;
-	case CTRL_DIAG:
-		port = PORT_DIAG;
-		enable_ier = DIAG_DL;
-		break;
-	case CTRL_APP1:
-		port = PORT_APP1;
-		enable_ier = APP1_DL;
-		break;
-	case CTRL_APP2:
-		port = PORT_APP2;
-		enable_ier = APP2_DL;
-		if (dc->state == NOZOMI_STATE_ALLOCATED) {
-			/*
-			 * After card initialization the flow control
-			 * received for APP2 is always the last
-			 */
-			dc->state = NOZOMI_STATE_READY;
-			dev_info(&dc->pdev->dev, "Device READY!\n");
-		}
-		break;
-	default:
-		dev_err(&dc->pdev->dev,
-			"ERROR: flow control received for non-existing port\n");
-		return 0;
-	};
-
-	DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
-	   *((u16 *)&ctrl_dl));
-
-	old_ctrl = dc->port[port].ctrl_dl;
-	dc->port[port].ctrl_dl = ctrl_dl;
-
-	if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) {
-		DBG1("Disable interrupt (0x%04X) on port: %d",
-			enable_ier, port);
-		disable_transmit_ul(port, dc);
-
-	} else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
-
-		if (kfifo_len(&dc->port[port].fifo_ul)) {
-			DBG1("Enable interrupt (0x%04X) on port: %d",
-				enable_ier, port);
-			DBG1("Data in buffer [%d], enable transmit! ",
-				kfifo_len(&dc->port[port].fifo_ul));
-			enable_transmit_ul(port, dc);
-		} else {
-			DBG1("No data in buffer...");
-		}
-	}
-
-	if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) {
-		DBG1(" No change in mctrl");
-		return 1;
-	}
-	/* Update statistics */
-	if (old_ctrl.CTS != ctrl_dl.CTS)
-		dc->port[port].tty_icount.cts++;
-	if (old_ctrl.DSR != ctrl_dl.DSR)
-		dc->port[port].tty_icount.dsr++;
-	if (old_ctrl.RI != ctrl_dl.RI)
-		dc->port[port].tty_icount.rng++;
-	if (old_ctrl.DCD != ctrl_dl.DCD)
-		dc->port[port].tty_icount.dcd++;
-
-	wake_up_interruptible(&dc->port[port].tty_wait);
-
-	DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)",
-	   port,
-	   dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts,
-	   dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr);
-
-	return 1;
-}
-
-static enum ctrl_port_type port2ctrl(enum port_type port,
-					const struct nozomi *dc)
-{
-	switch (port) {
-	case PORT_MDM:
-		return CTRL_MDM;
-	case PORT_DIAG:
-		return CTRL_DIAG;
-	case PORT_APP1:
-		return CTRL_APP1;
-	case PORT_APP2:
-		return CTRL_APP2;
-	default:
-		dev_err(&dc->pdev->dev,
-			"ERROR: send flow control " \
-			"received for non-existing port\n");
-	};
-	return CTRL_ERROR;
-}
-
-/*
- * Send flow control, can only update one channel at a time
- * Return 0 - If we have updated all flow control
- * Return 1 - If we need to update more flow control, ack current enable more
- */
-static int send_flow_control(struct nozomi *dc)
-{
-	u32 i, more_flow_control_to_be_updated = 0;
-	u16 *ctrl;
-
-	for (i = PORT_MDM; i < MAX_PORT; i++) {
-		if (dc->port[i].update_flow_control) {
-			if (more_flow_control_to_be_updated) {
-				/* We have more flow control to be updated */
-				return 1;
-			}
-			dc->port[i].ctrl_ul.port = port2ctrl(i, dc);
-			ctrl = (u16 *)&dc->port[i].ctrl_ul;
-			write_mem32(dc->port[PORT_CTRL].ul_addr[0], \
-				(u32 *) ctrl, 2);
-			dc->port[i].update_flow_control = 0;
-			more_flow_control_to_be_updated = 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * Handle downlink data, ports that are handled are modem and diagnostics
- * Return 1 - ok
- * Return 0 - toggle fields are out of sync
- */
-static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle,
-			u16 read_iir, u16 mask1, u16 mask2)
-{
-	if (*toggle == 0 && read_iir & mask1) {
-		if (receive_data(port, dc)) {
-			writew(mask1, dc->reg_fcr);
-			*toggle = !(*toggle);
-		}
-
-		if (read_iir & mask2) {
-			if (receive_data(port, dc)) {
-				writew(mask2, dc->reg_fcr);
-				*toggle = !(*toggle);
-			}
-		}
-	} else if (*toggle == 1 && read_iir & mask2) {
-		if (receive_data(port, dc)) {
-			writew(mask2, dc->reg_fcr);
-			*toggle = !(*toggle);
-		}
-
-		if (read_iir & mask1) {
-			if (receive_data(port, dc)) {
-				writew(mask1, dc->reg_fcr);
-				*toggle = !(*toggle);
-			}
-		}
-	} else {
-		dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n",
-			*toggle);
-		return 0;
-	}
-	return 1;
-}
-
-/*
- * Handle uplink data, this is currently for the modem port
- * Return 1 - ok
- * Return 0 - toggle field are out of sync
- */
-static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir)
-{
-	u8 *toggle = &(dc->port[port].toggle_ul);
-
-	if (*toggle == 0 && read_iir & MDM_UL1) {
-		dc->last_ier &= ~MDM_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(port, dc)) {
-			writew(MDM_UL1, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			*toggle = !*toggle;
-		}
-
-		if (read_iir & MDM_UL2) {
-			dc->last_ier &= ~MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			if (send_data(port, dc)) {
-				writew(MDM_UL2, dc->reg_fcr);
-				dc->last_ier = dc->last_ier | MDM_UL;
-				writew(dc->last_ier, dc->reg_ier);
-				*toggle = !*toggle;
-			}
-		}
-
-	} else if (*toggle == 1 && read_iir & MDM_UL2) {
-		dc->last_ier &= ~MDM_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(port, dc)) {
-			writew(MDM_UL2, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			*toggle = !*toggle;
-		}
-
-		if (read_iir & MDM_UL1) {
-			dc->last_ier &= ~MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			if (send_data(port, dc)) {
-				writew(MDM_UL1, dc->reg_fcr);
-				dc->last_ier = dc->last_ier | MDM_UL;
-				writew(dc->last_ier, dc->reg_ier);
-				*toggle = !*toggle;
-			}
-		}
-	} else {
-		writew(read_iir & MDM_UL, dc->reg_fcr);
-		dev_err(&dc->pdev->dev, "port out of sync!\n");
-		return 0;
-	}
-	return 1;
-}
-
-static irqreturn_t interrupt_handler(int irq, void *dev_id)
-{
-	struct nozomi *dc = dev_id;
-	unsigned int a;
-	u16 read_iir;
-
-	if (!dc)
-		return IRQ_NONE;
-
-	spin_lock(&dc->spin_mutex);
-	read_iir = readw(dc->reg_iir);
-
-	/* Card removed */
-	if (read_iir == (u16)-1)
-		goto none;
-	/*
-	 * Just handle interrupt enabled in IER
-	 * (by masking with dc->last_ier)
-	 */
-	read_iir &= dc->last_ier;
-
-	if (read_iir == 0)
-		goto none;
-
-
-	DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir,
-		dc->last_ier);
-
-	if (read_iir & RESET) {
-		if (unlikely(!nozomi_read_config_table(dc))) {
-			dc->last_ier = 0x0;
-			writew(dc->last_ier, dc->reg_ier);
-			dev_err(&dc->pdev->dev, "Could not read status from "
-				"card, we should disable interface\n");
-		} else {
-			writew(RESET, dc->reg_fcr);
-		}
-		/* No more useful info if this was the reset interrupt. */
-		goto exit_handler;
-	}
-	if (read_iir & CTRL_UL) {
-		DBG1("CTRL_UL");
-		dc->last_ier &= ~CTRL_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_flow_control(dc)) {
-			writew(CTRL_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | CTRL_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-	if (read_iir & CTRL_DL) {
-		receive_flow_control(dc);
-		writew(CTRL_DL, dc->reg_fcr);
-	}
-	if (read_iir & MDM_DL) {
-		if (!handle_data_dl(dc, PORT_MDM,
-				&(dc->port[PORT_MDM].toggle_dl), read_iir,
-				MDM_DL1, MDM_DL2)) {
-			dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n");
-			goto exit_handler;
-		}
-	}
-	if (read_iir & MDM_UL) {
-		if (!handle_data_ul(dc, PORT_MDM, read_iir)) {
-			dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n");
-			goto exit_handler;
-		}
-	}
-	if (read_iir & DIAG_DL) {
-		if (!handle_data_dl(dc, PORT_DIAG,
-				&(dc->port[PORT_DIAG].toggle_dl), read_iir,
-				DIAG_DL1, DIAG_DL2)) {
-			dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n");
-			goto exit_handler;
-		}
-	}
-	if (read_iir & DIAG_UL) {
-		dc->last_ier &= ~DIAG_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(PORT_DIAG, dc)) {
-			writew(DIAG_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | DIAG_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-	if (read_iir & APP1_DL) {
-		if (receive_data(PORT_APP1, dc))
-			writew(APP1_DL, dc->reg_fcr);
-	}
-	if (read_iir & APP1_UL) {
-		dc->last_ier &= ~APP1_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(PORT_APP1, dc)) {
-			writew(APP1_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | APP1_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-	if (read_iir & APP2_DL) {
-		if (receive_data(PORT_APP2, dc))
-			writew(APP2_DL, dc->reg_fcr);
-	}
-	if (read_iir & APP2_UL) {
-		dc->last_ier &= ~APP2_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(PORT_APP2, dc)) {
-			writew(APP2_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | APP2_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-
-exit_handler:
-	spin_unlock(&dc->spin_mutex);
-	for (a = 0; a < NOZOMI_MAX_PORTS; a++) {
-		struct tty_struct *tty;
-		if (test_and_clear_bit(a, &dc->flip)) {
-			tty = tty_port_tty_get(&dc->port[a].port);
-			if (tty)
-				tty_flip_buffer_push(tty);
-			tty_kref_put(tty);
-		}
-	}
-	return IRQ_HANDLED;
-none:
-	spin_unlock(&dc->spin_mutex);
-	return IRQ_NONE;
-}
-
-static void nozomi_get_card_type(struct nozomi *dc)
-{
-	int i;
-	u32 size = 0;
-
-	for (i = 0; i < 6; i++)
-		size += pci_resource_len(dc->pdev, i);
-
-	/* Assume card type F32_8 if no match */
-	dc->card_type = size == 2048 ? F32_2 : F32_8;
-
-	dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type);
-}
-
-static void nozomi_setup_private_data(struct nozomi *dc)
-{
-	void __iomem *offset = dc->base_addr + dc->card_type / 2;
-	unsigned int i;
-
-	dc->reg_fcr = (void __iomem *)(offset + R_FCR);
-	dc->reg_iir = (void __iomem *)(offset + R_IIR);
-	dc->reg_ier = (void __iomem *)(offset + R_IER);
-	dc->last_ier = 0;
-	dc->flip = 0;
-
-	dc->port[PORT_MDM].token_dl = MDM_DL;
-	dc->port[PORT_DIAG].token_dl = DIAG_DL;
-	dc->port[PORT_APP1].token_dl = APP1_DL;
-	dc->port[PORT_APP2].token_dl = APP2_DL;
-
-	for (i = 0; i < MAX_PORT; i++)
-		init_waitqueue_head(&dc->port[i].tty_wait);
-}
-
-static ssize_t card_type_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
-
-	return sprintf(buf, "%d\n", dc->card_type);
-}
-static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL);
-
-static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
-
-	return sprintf(buf, "%u\n", dc->open_ttys);
-}
-static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL);
-
-static void make_sysfs_files(struct nozomi *dc)
-{
-	if (device_create_file(&dc->pdev->dev, &dev_attr_card_type))
-		dev_err(&dc->pdev->dev,
-			"Could not create sysfs file for card_type\n");
-	if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys))
-		dev_err(&dc->pdev->dev,
-			"Could not create sysfs file for open_ttys\n");
-}
-
-static void remove_sysfs_files(struct nozomi *dc)
-{
-	device_remove_file(&dc->pdev->dev, &dev_attr_card_type);
-	device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys);
-}
-
-/* Allocate memory for one device */
-static int __devinit nozomi_card_init(struct pci_dev *pdev,
-				      const struct pci_device_id *ent)
-{
-	resource_size_t start;
-	int ret;
-	struct nozomi *dc = NULL;
-	int ndev_idx;
-	int i;
-
-	dev_dbg(&pdev->dev, "Init, new card found\n");
-
-	for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
-		if (!ndevs[ndev_idx])
-			break;
-
-	if (ndev_idx >= ARRAY_SIZE(ndevs)) {
-		dev_err(&pdev->dev, "no free tty range for this card left\n");
-		ret = -EIO;
-		goto err;
-	}
-
-	dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
-	if (unlikely(!dc)) {
-		dev_err(&pdev->dev, "Could not allocate memory\n");
-		ret = -ENOMEM;
-		goto err_free;
-	}
-
-	dc->pdev = pdev;
-
-	ret = pci_enable_device(dc->pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
-		goto err_free;
-	}
-
-	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
-	if (ret) {
-		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
-			(int) /* nozomi_private.io_addr */ 0);
-		goto err_disable_device;
-	}
-
-	start = pci_resource_start(dc->pdev, 0);
-	if (start == 0) {
-		dev_err(&pdev->dev, "No I/O address for card detected\n");
-		ret = -ENODEV;
-		goto err_rel_regs;
-	}
-
-	/* Find out what card type it is */
-	nozomi_get_card_type(dc);
-
-	dc->base_addr = ioremap_nocache(start, dc->card_type);
-	if (!dc->base_addr) {
-		dev_err(&pdev->dev, "Unable to map card MMIO\n");
-		ret = -ENODEV;
-		goto err_rel_regs;
-	}
-
-	dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL);
-	if (!dc->send_buf) {
-		dev_err(&pdev->dev, "Could not allocate send buffer?\n");
-		ret = -ENOMEM;
-		goto err_free_sbuf;
-	}
-
-	for (i = PORT_MDM; i < MAX_PORT; i++) {
-		if (kfifo_alloc(&dc->port[i].fifo_ul,
-		      FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) {
-			dev_err(&pdev->dev,
-					"Could not allocate kfifo buffer\n");
-			ret = -ENOMEM;
-			goto err_free_kfifo;
-		}
-	}
-
-	spin_lock_init(&dc->spin_mutex);
-
-	nozomi_setup_private_data(dc);
-
-	/* Disable all interrupts */
-	dc->last_ier = 0;
-	writew(dc->last_ier, dc->reg_ier);
-
-	ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
-			NOZOMI_NAME, dc);
-	if (unlikely(ret)) {
-		dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
-		goto err_free_kfifo;
-	}
-
-	DBG1("base_addr: %p", dc->base_addr);
-
-	make_sysfs_files(dc);
-
-	dc->index_start = ndev_idx * MAX_PORT;
-	ndevs[ndev_idx] = dc;
-
-	pci_set_drvdata(pdev, dc);
-
-	/* Enable RESET interrupt */
-	dc->last_ier = RESET;
-	iowrite16(dc->last_ier, dc->reg_ier);
-
-	dc->state = NOZOMI_STATE_ENABLED;
-
-	for (i = 0; i < MAX_PORT; i++) {
-		struct device *tty_dev;
-		struct port *port = &dc->port[i];
-		port->dc = dc;
-		mutex_init(&port->tty_sem);
-		tty_port_init(&port->port);
-		port->port.ops = &noz_tty_port_ops;
-		tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
-							&pdev->dev);
-
-		if (IS_ERR(tty_dev)) {
-			ret = PTR_ERR(tty_dev);
-			dev_err(&pdev->dev, "Could not allocate tty?\n");
-			goto err_free_tty;
-		}
-	}
-
-	return 0;
-
-err_free_tty:
-	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-		tty_unregister_device(ntty_driver, i);
-err_free_kfifo:
-	for (i = 0; i < MAX_PORT; i++)
-		kfifo_free(&dc->port[i].fifo_ul);
-err_free_sbuf:
-	kfree(dc->send_buf);
-	iounmap(dc->base_addr);
-err_rel_regs:
-	pci_release_regions(pdev);
-err_disable_device:
-	pci_disable_device(pdev);
-err_free:
-	kfree(dc);
-err:
-	return ret;
-}
-
-static void __devexit tty_exit(struct nozomi *dc)
-{
-	unsigned int i;
-
-	DBG1(" ");
-
-	flush_scheduled_work();
-
-	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);
-	}
-	/* Racy below - surely should wait for scheduled work to be done or
-	   complete off a hangup method ? */
-	while (dc->open_ttys)
-		msleep(1);
-	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-		tty_unregister_device(ntty_driver, i);
-}
-
-/* Deallocate memory for one device */
-static void __devexit nozomi_card_exit(struct pci_dev *pdev)
-{
-	int i;
-	struct ctrl_ul ctrl;
-	struct nozomi *dc = pci_get_drvdata(pdev);
-
-	/* Disable all interrupts */
-	dc->last_ier = 0;
-	writew(dc->last_ier, dc->reg_ier);
-
-	tty_exit(dc);
-
-	/* Send 0x0001, command card to resend the reset token.  */
-	/* This is to get the reset when the module is reloaded. */
-	ctrl.port = 0x00;
-	ctrl.reserved = 0;
-	ctrl.RTS = 0;
-	ctrl.DTR = 1;
-	DBG1("sending flow control 0x%04X", *((u16 *)&ctrl));
-
-	/* Setup dc->reg addresses to we can use defines here */
-	write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2);
-	writew(CTRL_UL, dc->reg_fcr);	/* push the token to the card. */
-
-	remove_sysfs_files(dc);
-
-	free_irq(pdev->irq, dc);
-
-	for (i = 0; i < MAX_PORT; i++)
-		kfifo_free(&dc->port[i].fifo_ul);
-
-	kfree(dc->send_buf);
-
-	iounmap(dc->base_addr);
-
-	pci_release_regions(pdev);
-
-	pci_disable_device(pdev);
-
-	ndevs[dc->index_start / MAX_PORT] = NULL;
-
-	kfree(dc);
-}
-
-static void set_rts(const struct tty_struct *tty, int rts)
-{
-	struct port *port = get_port_by_tty(tty);
-
-	port->ctrl_ul.RTS = rts;
-	port->update_flow_control = 1;
-	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
-}
-
-static void set_dtr(const struct tty_struct *tty, int dtr)
-{
-	struct port *port = get_port_by_tty(tty);
-
-	DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr);
-
-	port->ctrl_ul.DTR = dtr;
-	port->update_flow_control = 1;
-	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
-}
-
-/*
- * ----------------------------------------------------------------------------
- * TTY code
- * ----------------------------------------------------------------------------
- */
-
-static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
-{
-	struct port *port = get_port_by_tty(tty);
-	struct nozomi *dc = get_dc_by_tty(tty);
-	int ret;
-	if (!port || !dc || dc->state != NOZOMI_STATE_READY)
-		return -ENODEV;
-	ret = tty_init_termios(tty);
-	if (ret == 0) {
-		tty_driver_kref_get(driver);
-		tty->count++;
-		tty->driver_data = port;
-		driver->ttys[tty->index] = tty;
-	}
-	return ret;
-}
-
-static void ntty_cleanup(struct tty_struct *tty)
-{
-	tty->driver_data = NULL;
-}
-
-static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
-{
-	struct port *port = container_of(tport, struct port, port);
-	struct nozomi *dc = port->dc;
-	unsigned long flags;
-
-	DBG1("open: %d", port->token_dl);
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	dc->last_ier = dc->last_ier | port->token_dl;
-	writew(dc->last_ier, dc->reg_ier);
-	dc->open_ttys++;
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-	printk("noz: activated %d: %p\n", tty->index, tport);
-	return 0;
-}
-
-static int ntty_open(struct tty_struct *tty, struct file *filp)
-{
-	struct port *port = tty->driver_data;
-	return tty_port_open(&port->port, tty, filp);
-}
-
-static void ntty_shutdown(struct tty_port *tport)
-{
-	struct port *port = container_of(tport, struct port, port);
-	struct nozomi *dc = port->dc;
-	unsigned long flags;
-
-	DBG1("close: %d", port->token_dl);
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	dc->last_ier &= ~(port->token_dl);
-	writew(dc->last_ier, dc->reg_ier);
-	dc->open_ttys--;
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-	printk("noz: shutdown %p\n", tport);
-}
-
-static void ntty_close(struct tty_struct *tty, struct file *filp)
-{
-	struct port *port = tty->driver_data;
-	if (port)
-		tty_port_close(&port->port, tty, filp);
-}
-
-static void ntty_hangup(struct tty_struct *tty)
-{
-	struct port *port = tty->driver_data;
-	tty_port_hangup(&port->port);
-}
-
-/*
- * called when the userspace process writes to the tty (/dev/noz*).
- * Data is inserted into a fifo, which is then read and transfered to the modem.
- */
-static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
-		      int count)
-{
-	int rval = -EINVAL;
-	struct nozomi *dc = get_dc_by_tty(tty);
-	struct port *port = tty->driver_data;
-	unsigned long flags;
-
-	/* DBG1( "WRITEx: %d, index = %d", count, index); */
-
-	if (!dc || !port)
-		return -ENODEV;
-
-	mutex_lock(&port->tty_sem);
-
-	if (unlikely(!port->port.count)) {
-		DBG1(" ");
-		goto exit;
-	}
-
-	rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
-
-	/* notify card */
-	if (unlikely(dc == NULL)) {
-		DBG1("No device context?");
-		goto exit;
-	}
-
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	/* CTS is only valid on the modem channel */
-	if (port == &(dc->port[PORT_MDM])) {
-		if (port->ctrl_dl.CTS) {
-			DBG4("Enable interrupt");
-			enable_transmit_ul(tty->index % MAX_PORT, dc);
-		} else {
-			dev_err(&dc->pdev->dev,
-				"CTS not active on modem port?\n");
-		}
-	} else {
-		enable_transmit_ul(tty->index % MAX_PORT, dc);
-	}
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-
-exit:
-	mutex_unlock(&port->tty_sem);
-	return rval;
-}
-
-/*
- * Calculate how much is left in device
- * This method is called by the upper tty layer.
- *   #according to sources N_TTY.c it expects a value >= 0 and
- *    does not check for negative values.
- *
- * If the port is unplugged report lots of room and let the bits
- * dribble away so we don't block anything.
- */
-static int ntty_write_room(struct tty_struct *tty)
-{
-	struct port *port = tty->driver_data;
-	int room = 4096;
-	const struct nozomi *dc = get_dc_by_tty(tty);
-
-	if (dc) {
-		mutex_lock(&port->tty_sem);
-		if (port->port.count)
-			room = kfifo_avail(&port->fifo_ul);
-		mutex_unlock(&port->tty_sem);
-	}
-	return room;
-}
-
-/* Gets io control parameters */
-static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	const struct port *port = tty->driver_data;
-	const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
-	const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
-
-	/* Note: these could change under us but it is not clear this
-	   matters if so */
-	return	(ctrl_ul->RTS ? TIOCM_RTS : 0) |
-		(ctrl_ul->DTR ? TIOCM_DTR : 0) |
-		(ctrl_dl->DCD ? TIOCM_CAR : 0) |
-		(ctrl_dl->RI  ? TIOCM_RNG : 0) |
-		(ctrl_dl->DSR ? TIOCM_DSR : 0) |
-		(ctrl_dl->CTS ? TIOCM_CTS : 0);
-}
-
-/* Sets io controls parameters */
-static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear)
-{
-	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	if (set & TIOCM_RTS)
-		set_rts(tty, 1);
-	else if (clear & TIOCM_RTS)
-		set_rts(tty, 0);
-
-	if (set & TIOCM_DTR)
-		set_dtr(tty, 1);
-	else if (clear & TIOCM_DTR)
-		set_dtr(tty, 0);
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-
-	return 0;
-}
-
-static int ntty_cflags_changed(struct port *port, unsigned long flags,
-		struct async_icount *cprev)
-{
-	const struct async_icount cnow = port->tty_icount;
-	int ret;
-
-	ret =	((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
-		((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
-		((flags & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
-		((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
-
-	*cprev = cnow;
-
-	return ret;
-}
-
-static int ntty_tiocgicount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct port *port = tty->driver_data;
-	const struct async_icount cnow = port->tty_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 ntty_ioctl(struct tty_struct *tty, struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	struct port *port = tty->driver_data;
-	int rval = -ENOIOCTLCMD;
-
-	DBG1("******** IOCTL, cmd: %d", cmd);
-
-	switch (cmd) {
-	case TIOCMIWAIT: {
-		struct async_icount cprev = port->tty_icount;
-
-		rval = wait_event_interruptible(port->tty_wait,
-				ntty_cflags_changed(port, arg, &cprev));
-		break;
-	}
-	default:
-		DBG1("ERR: 0x%08X, %d", cmd, cmd);
-		break;
-	};
-
-	return rval;
-}
-
-/*
- * Called by the upper tty layer when tty buffers are ready
- * to receive data again after a call to throttle.
- */
-static void ntty_unthrottle(struct tty_struct *tty)
-{
-	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
-	DBG1("UNTHROTTLE");
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	enable_transmit_dl(tty->index % MAX_PORT, dc);
-	set_rts(tty, 1);
-
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-}
-
-/*
- * Called by the upper tty layer when the tty buffers are almost full.
- * The driver should stop send more data.
- */
-static void ntty_throttle(struct tty_struct *tty)
-{
-	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
-	DBG1("THROTTLE");
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	set_rts(tty, 0);
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-}
-
-/* Returns number of chars in buffer, called by tty layer */
-static s32 ntty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct port *port = tty->driver_data;
-	struct nozomi *dc = get_dc_by_tty(tty);
-	s32 rval = 0;
-
-	if (unlikely(!dc || !port)) {
-		goto exit_in_buffer;
-	}
-
-	if (unlikely(!port->port.count)) {
-		dev_err(&dc->pdev->dev, "No tty open?\n");
-		goto exit_in_buffer;
-	}
-
-	rval = kfifo_len(&port->fifo_ul);
-
-exit_in_buffer:
-	return rval;
-}
-
-static const struct tty_port_operations noz_tty_port_ops = {
-	.activate = ntty_activate,
-	.shutdown = ntty_shutdown,
-};
-
-static const struct tty_operations tty_ops = {
-	.ioctl = ntty_ioctl,
-	.open = ntty_open,
-	.close = ntty_close,
-	.hangup = ntty_hangup,
-	.write = ntty_write,
-	.write_room = ntty_write_room,
-	.unthrottle = ntty_unthrottle,
-	.throttle = ntty_throttle,
-	.chars_in_buffer = ntty_chars_in_buffer,
-	.tiocmget = ntty_tiocmget,
-	.tiocmset = ntty_tiocmset,
-	.get_icount = ntty_tiocgicount,
-	.install = ntty_install,
-	.cleanup = ntty_cleanup,
-};
-
-/* Module initialization */
-static struct pci_driver nozomi_driver = {
-	.name = NOZOMI_NAME,
-	.id_table = nozomi_pci_tbl,
-	.probe = nozomi_card_init,
-	.remove = __devexit_p(nozomi_card_exit),
-};
-
-static __init int nozomi_init(void)
-{
-	int ret;
-
-	printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
-
-	ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
-	if (!ntty_driver)
-		return -ENOMEM;
-
-	ntty_driver->owner = THIS_MODULE;
-	ntty_driver->driver_name = NOZOMI_NAME_TTY;
-	ntty_driver->name = "noz";
-	ntty_driver->major = 0;
-	ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	ntty_driver->subtype = SERIAL_TYPE_NORMAL;
-	ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	ntty_driver->init_termios = tty_std_termios;
-	ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
-						HUPCL | CLOCAL;
-	ntty_driver->init_termios.c_ispeed = 115200;
-	ntty_driver->init_termios.c_ospeed = 115200;
-	tty_set_operations(ntty_driver, &tty_ops);
-
-	ret = tty_register_driver(ntty_driver);
-	if (ret) {
-		printk(KERN_ERR "Nozomi: failed to register ntty driver\n");
-		goto free_tty;
-	}
-
-	ret = pci_register_driver(&nozomi_driver);
-	if (ret) {
-		printk(KERN_ERR "Nozomi: can't register pci driver\n");
-		goto unr_tty;
-	}
-
-	return 0;
-unr_tty:
-	tty_unregister_driver(ntty_driver);
-free_tty:
-	put_tty_driver(ntty_driver);
-	return ret;
-}
-
-static __exit void nozomi_exit(void)
-{
-	printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
-	pci_unregister_driver(&nozomi_driver);
-	tty_unregister_driver(ntty_driver);
-	put_tty_driver(ntty_driver);
-}
-
-module_init(nozomi_init);
-module_exit(nozomi_exit);
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/char/pcmcia/Makefile b/drivers/char/pcmcia/Makefile
index be8f287..0aae209 100644
--- a/drivers/char/pcmcia/Makefile
+++ b/drivers/char/pcmcia/Makefile
@@ -4,8 +4,6 @@
 # Makefile for the Linux PCMCIA char device drivers.
 #
 
-obj-y += ipwireless/
-
 obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o
 obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o
 obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o
diff --git a/drivers/char/pcmcia/ipwireless/Makefile b/drivers/char/pcmcia/ipwireless/Makefile
deleted file mode 100644
index db80873..0000000
--- a/drivers/char/pcmcia/ipwireless/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# drivers/char/pcmcia/ipwireless/Makefile
-#
-# Makefile for the IPWireless driver
-#
-
-obj-$(CONFIG_IPWIRELESS) += ipwireless.o
-
-ipwireless-y := hardware.o main.o network.o tty.o
-
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c
deleted file mode 100644
index 0aeb5a3..0000000
--- a/drivers/char/pcmcia/ipwireless/hardware.c
+++ /dev/null
@@ -1,1764 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-
-#include "hardware.h"
-#include "setup_protocol.h"
-#include "network.h"
-#include "main.h"
-
-static void ipw_send_setup_packet(struct ipw_hardware *hw);
-static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
-					 unsigned int address,
-					 const unsigned char *data, int len,
-					 int is_last);
-static void ipwireless_setup_timer(unsigned long data);
-static void handle_received_CTRL_packet(struct ipw_hardware *hw,
-		unsigned int channel_idx, const unsigned char *data, int len);
-
-/*#define TIMING_DIAGNOSTICS*/
-
-#ifdef TIMING_DIAGNOSTICS
-
-static struct timing_stats {
-	unsigned long last_report_time;
-	unsigned long read_time;
-	unsigned long write_time;
-	unsigned long read_bytes;
-	unsigned long write_bytes;
-	unsigned long start_time;
-};
-
-static void start_timing(void)
-{
-	timing_stats.start_time = jiffies;
-}
-
-static void end_read_timing(unsigned length)
-{
-	timing_stats.read_time += (jiffies - start_time);
-	timing_stats.read_bytes += length + 2;
-	report_timing();
-}
-
-static void end_write_timing(unsigned length)
-{
-	timing_stats.write_time += (jiffies - start_time);
-	timing_stats.write_bytes += length + 2;
-	report_timing();
-}
-
-static void report_timing(void)
-{
-	unsigned long since = jiffies - timing_stats.last_report_time;
-
-	/* If it's been more than one second... */
-	if (since >= HZ) {
-		int first = (timing_stats.last_report_time == 0);
-
-		timing_stats.last_report_time = jiffies;
-		if (!first)
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n",
-			       jiffies_to_usecs(since),
-			       timing_stats.read_bytes,
-			       jiffies_to_usecs(timing_stats.read_time),
-			       timing_stats.write_bytes,
-			       jiffies_to_usecs(timing_stats.write_time));
-
-		timing_stats.read_time = 0;
-		timing_stats.write_time = 0;
-		timing_stats.read_bytes = 0;
-		timing_stats.write_bytes = 0;
-	}
-}
-#else
-static void start_timing(void) { }
-static void end_read_timing(unsigned length) { }
-static void end_write_timing(unsigned length) { }
-#endif
-
-/* Imported IPW definitions */
-
-#define LL_MTU_V1 318
-#define LL_MTU_V2 250
-#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2)
-
-#define PRIO_DATA  2
-#define PRIO_CTRL  1
-#define PRIO_SETUP 0
-
-/* Addresses */
-#define ADDR_SETUP_PROT 0
-
-/* Protocol ids */
-enum {
-	/* Identifier for the Com Data protocol */
-	TL_PROTOCOLID_COM_DATA = 0,
-
-	/* Identifier for the Com Control protocol */
-	TL_PROTOCOLID_COM_CTRL = 1,
-
-	/* Identifier for the Setup protocol */
-	TL_PROTOCOLID_SETUP = 2
-};
-
-/* Number of bytes in NL packet header (cannot do
- * sizeof(nl_packet_header) since it's a bitfield) */
-#define NL_FIRST_PACKET_HEADER_SIZE        3
-
-/* Number of bytes in NL packet header (cannot do
- * sizeof(nl_packet_header) since it's a bitfield) */
-#define NL_FOLLOWING_PACKET_HEADER_SIZE    1
-
-struct nl_first_packet_header {
-	unsigned char protocol:3;
-	unsigned char address:3;
-	unsigned char packet_rank:2;
-	unsigned char length_lsb;
-	unsigned char length_msb;
-};
-
-struct nl_packet_header {
-	unsigned char protocol:3;
-	unsigned char address:3;
-	unsigned char packet_rank:2;
-};
-
-/* Value of 'packet_rank' above */
-#define NL_INTERMEDIATE_PACKET    0x0
-#define NL_LAST_PACKET            0x1
-#define NL_FIRST_PACKET           0x2
-
-union nl_packet {
-	/* Network packet header of the first packet (a special case) */
-	struct nl_first_packet_header hdr_first;
-	/* Network packet header of the following packets (if any) */
-	struct nl_packet_header hdr;
-	/* Complete network packet (header + data) */
-	unsigned char rawpkt[LL_MTU_MAX];
-} __attribute__ ((__packed__));
-
-#define HW_VERSION_UNKNOWN -1
-#define HW_VERSION_1 1
-#define HW_VERSION_2 2
-
-/* IPW I/O ports */
-#define IOIER 0x00		/* Interrupt Enable Register */
-#define IOIR  0x02		/* Interrupt Source/ACK register */
-#define IODCR 0x04		/* Data Control Register */
-#define IODRR 0x06		/* Data Read Register */
-#define IODWR 0x08		/* Data Write Register */
-#define IOESR 0x0A		/* Embedded Driver Status Register */
-#define IORXR 0x0C		/* Rx Fifo Register (Host to Embedded) */
-#define IOTXR 0x0E		/* Tx Fifo Register (Embedded to Host) */
-
-/* I/O ports and bit definitions for version 1 of the hardware */
-
-/* IER bits*/
-#define IER_RXENABLED   0x1
-#define IER_TXENABLED   0x2
-
-/* ISR bits */
-#define IR_RXINTR       0x1
-#define IR_TXINTR       0x2
-
-/* DCR bits */
-#define DCR_RXDONE      0x1
-#define DCR_TXDONE      0x2
-#define DCR_RXRESET     0x4
-#define DCR_TXRESET     0x8
-
-/* I/O ports and bit definitions for version 2 of the hardware */
-
-struct MEMCCR {
-	unsigned short reg_config_option;	/* PCCOR: Configuration Option Register */
-	unsigned short reg_config_and_status;	/* PCCSR: Configuration and Status Register */
-	unsigned short reg_pin_replacement;	/* PCPRR: Pin Replacemant Register */
-	unsigned short reg_socket_and_copy;	/* PCSCR: Socket and Copy Register */
-	unsigned short reg_ext_status;		/* PCESR: Extendend Status Register */
-	unsigned short reg_io_base;		/* PCIOB: I/O Base Register */
-};
-
-struct MEMINFREG {
-	unsigned short memreg_tx_old;	/* TX Register (R/W) */
-	unsigned short pad1;
-	unsigned short memreg_rx_done;	/* RXDone Register (R/W) */
-	unsigned short pad2;
-	unsigned short memreg_rx;	/* RX Register (R/W) */
-	unsigned short pad3;
-	unsigned short memreg_pc_interrupt_ack;	/* PC intr Ack Register (W) */
-	unsigned short pad4;
-	unsigned long memreg_card_present;/* Mask for Host to check (R) for
-					   * CARD_PRESENT_VALUE */
-	unsigned short memreg_tx_new;	/* TX2 (new) Register (R/W) */
-};
-
-#define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
-
-#define MEMTX_TX                       0x0001
-#define MEMRX_RX                       0x0001
-#define MEMRX_RX_DONE                  0x0001
-#define MEMRX_PCINTACKK                0x0001
-
-#define NL_NUM_OF_PRIORITIES       3
-#define NL_NUM_OF_PROTOCOLS        3
-#define NL_NUM_OF_ADDRESSES        NO_OF_IPW_CHANNELS
-
-struct ipw_hardware {
-	unsigned int base_port;
-	short hw_version;
-	unsigned short ll_mtu;
-	spinlock_t lock;
-
-	int initializing;
-	int init_loops;
-	struct timer_list setup_timer;
-
-	/* Flag if hw is ready to send next packet */
-	int tx_ready;
-	/* Count of pending packets to be sent */
-	int tx_queued;
-	struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
-
-	int rx_bytes_queued;
-	struct list_head rx_queue;
-	/* Pool of rx_packet structures that are not currently used. */
-	struct list_head rx_pool;
-	int rx_pool_size;
-	/* True if reception of data is blocked while userspace processes it. */
-	int blocking_rx;
-	/* True if there is RX data ready on the hardware. */
-	int rx_ready;
-	unsigned short last_memtx_serial;
-	/*
-	 * Newer versions of the V2 card firmware send serial numbers in the
-	 * MemTX register. 'serial_number_detected' is set true when we detect
-	 * a non-zero serial number (indicating the new firmware).  Thereafter,
-	 * the driver can safely ignore the Timer Recovery re-sends to avoid
-	 * out-of-sync problems.
-	 */
-	int serial_number_detected;
-	struct work_struct work_rx;
-
-	/* True if we are to send the set-up data to the hardware. */
-	int to_setup;
-
-	/* Card has been removed */
-	int removed;
-	/* Saved irq value when we disable the interrupt. */
-	int irq;
-	/* True if this driver is shutting down. */
-	int shutting_down;
-	/* Modem control lines */
-	unsigned int control_lines[NL_NUM_OF_ADDRESSES];
-	struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES];
-
-	struct tasklet_struct tasklet;
-
-	/* The handle for the network layer, for the sending of events to it. */
-	struct ipw_network *network;
-	struct MEMINFREG __iomem *memory_info_regs;
-	struct MEMCCR __iomem *memregs_CCR;
-	void (*reboot_callback) (void *data);
-	void *reboot_callback_data;
-
-	unsigned short __iomem *memreg_tx;
-};
-
-/*
- * Packet info structure for tx packets.
- * Note: not all the fields defined here are required for all protocols
- */
-struct ipw_tx_packet {
-	struct list_head queue;
-	/* channel idx + 1 */
-	unsigned char dest_addr;
-	/* SETUP, CTRL or DATA */
-	unsigned char protocol;
-	/* Length of data block, which starts at the end of this structure */
-	unsigned short length;
-	/* Sending state */
-	/* Offset of where we've sent up to so far */
-	unsigned long offset;
-	/* Count of packet fragments, starting at 0 */
-	int fragment_count;
-
-	/* Called after packet is sent and before is freed */
-	void (*packet_callback) (void *cb_data, unsigned int packet_length);
-	void *callback_data;
-};
-
-/* Signals from DTE */
-#define COMCTRL_RTS	0
-#define COMCTRL_DTR	1
-
-/* Signals from DCE */
-#define COMCTRL_CTS	2
-#define COMCTRL_DCD	3
-#define COMCTRL_DSR	4
-#define COMCTRL_RI	5
-
-struct ipw_control_packet_body {
-	/* DTE signal or DCE signal */
-	unsigned char sig_no;
-	/* 0: set signal, 1: clear signal */
-	unsigned char value;
-} __attribute__ ((__packed__));
-
-struct ipw_control_packet {
-	struct ipw_tx_packet header;
-	struct ipw_control_packet_body body;
-};
-
-struct ipw_rx_packet {
-	struct list_head queue;
-	unsigned int capacity;
-	unsigned int length;
-	unsigned int protocol;
-	unsigned int channel_idx;
-};
-
-static char *data_type(const unsigned char *buf, unsigned length)
-{
-	struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
-
-	if (length == 0)
-		return "     ";
-
-	if (hdr->packet_rank & NL_FIRST_PACKET) {
-		switch (hdr->protocol) {
-		case TL_PROTOCOLID_COM_DATA:	return "DATA ";
-		case TL_PROTOCOLID_COM_CTRL:	return "CTRL ";
-		case TL_PROTOCOLID_SETUP:	return "SETUP";
-		default: return "???? ";
-		}
-	} else
-		return "     ";
-}
-
-#define DUMP_MAX_BYTES 64
-
-static void dump_data_bytes(const char *type, const unsigned char *data,
-			    unsigned length)
-{
-	char prefix[56];
-
-	sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ",
-			type, data_type(data, length));
-	print_hex_dump_bytes(prefix, 0, (void *)data,
-			length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
-}
-
-static void swap_packet_bitfield_to_le(unsigned char *data)
-{
-#ifdef __BIG_ENDIAN_BITFIELD
-	unsigned char tmp = *data, ret = 0;
-
-	/*
-	 * transform bits from aa.bbb.ccc to ccc.bbb.aa
-	 */
-	ret |= tmp & 0xc0 >> 6;
-	ret |= tmp & 0x38 >> 1;
-	ret |= tmp & 0x07 << 5;
-	*data = ret & 0xff;
-#endif
-}
-
-static void swap_packet_bitfield_from_le(unsigned char *data)
-{
-#ifdef __BIG_ENDIAN_BITFIELD
-	unsigned char tmp = *data, ret = 0;
-
-	/*
-	 * transform bits from ccc.bbb.aa to aa.bbb.ccc
-	 */
-	ret |= tmp & 0xe0 >> 5;
-	ret |= tmp & 0x1c << 1;
-	ret |= tmp & 0x03 << 6;
-	*data = ret & 0xff;
-#endif
-}
-
-static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data,
-			    unsigned length)
-{
-	unsigned i;
-	unsigned long flags;
-
-	start_timing();
-	BUG_ON(length > hw->ll_mtu);
-
-	if (ipwireless_debug)
-		dump_data_bytes("send", data, length);
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	hw->tx_ready = 0;
-	swap_packet_bitfield_to_le(data);
-
-	if (hw->hw_version == HW_VERSION_1) {
-		outw((unsigned short) length, hw->base_port + IODWR);
-
-		for (i = 0; i < length; i += 2) {
-			unsigned short d = data[i];
-			__le16 raw_data;
-
-			if (i + 1 < length)
-				d |= data[i + 1] << 8;
-			raw_data = cpu_to_le16(d);
-			outw(raw_data, hw->base_port + IODWR);
-		}
-
-		outw(DCR_TXDONE, hw->base_port + IODCR);
-	} else if (hw->hw_version == HW_VERSION_2) {
-		outw((unsigned short) length, hw->base_port);
-
-		for (i = 0; i < length; i += 2) {
-			unsigned short d = data[i];
-			__le16 raw_data;
-
-			if (i + 1 < length)
-				d |= data[i + 1] << 8;
-			raw_data = cpu_to_le16(d);
-			outw(raw_data, hw->base_port);
-		}
-		while ((i & 3) != 2) {
-			outw((unsigned short) 0xDEAD, hw->base_port);
-			i += 2;
-		}
-		writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
-	}
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	end_write_timing(length);
-}
-
-static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
-{
-	unsigned short fragment_data_len;
-	unsigned short data_left = packet->length - packet->offset;
-	unsigned short header_size;
-	union nl_packet pkt;
-
-	header_size =
-	    (packet->fragment_count == 0)
-	    ? NL_FIRST_PACKET_HEADER_SIZE
-	    : NL_FOLLOWING_PACKET_HEADER_SIZE;
-	fragment_data_len = hw->ll_mtu - header_size;
-	if (data_left < fragment_data_len)
-		fragment_data_len = data_left;
-
-	/*
-	 * hdr_first is now in machine bitfield order, which will be swapped
-	 * to le just before it goes to hw
-	 */
-	pkt.hdr_first.protocol = packet->protocol;
-	pkt.hdr_first.address = packet->dest_addr;
-	pkt.hdr_first.packet_rank = 0;
-
-	/* First packet? */
-	if (packet->fragment_count == 0) {
-		pkt.hdr_first.packet_rank |= NL_FIRST_PACKET;
-		pkt.hdr_first.length_lsb = (unsigned char) packet->length;
-		pkt.hdr_first.length_msb =
-			(unsigned char) (packet->length >> 8);
-	}
-
-	memcpy(pkt.rawpkt + header_size,
-	       ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) +
-	       packet->offset, fragment_data_len);
-	packet->offset += fragment_data_len;
-	packet->fragment_count++;
-
-	/* Last packet? (May also be first packet.) */
-	if (packet->offset == packet->length)
-		pkt.hdr_first.packet_rank |= NL_LAST_PACKET;
-	do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len);
-
-	/* If this packet has unsent data, then re-queue it. */
-	if (packet->offset < packet->length) {
-		/*
-		 * Re-queue it at the head of the highest priority queue so
-		 * it goes before all other packets
-		 */
-		unsigned long flags;
-
-		spin_lock_irqsave(&hw->lock, flags);
-		list_add(&packet->queue, &hw->tx_queue[0]);
-		hw->tx_queued++;
-		spin_unlock_irqrestore(&hw->lock, flags);
-	} else {
-		if (packet->packet_callback)
-			packet->packet_callback(packet->callback_data,
-					packet->length);
-		kfree(packet);
-	}
-}
-
-static void ipw_setup_hardware(struct ipw_hardware *hw)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	if (hw->hw_version == HW_VERSION_1) {
-		/* Reset RX FIFO */
-		outw(DCR_RXRESET, hw->base_port + IODCR);
-		/* SB: Reset TX FIFO */
-		outw(DCR_TXRESET, hw->base_port + IODCR);
-
-		/* Enable TX and RX interrupts. */
-		outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER);
-	} else {
-		/*
-		 * Set INTRACK bit (bit 0), which means we must explicitly
-		 * acknowledge interrupts by clearing bit 2 of reg_config_and_status.
-		 */
-		unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
-
-		csr |= 1;
-		writew(csr, &hw->memregs_CCR->reg_config_and_status);
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-/*
- * If 'packet' is NULL, then this function allocates a new packet, setting its
- * length to 0 and ensuring it has the specified minimum amount of free space.
- *
- * If 'packet' is not NULL, then this function enlarges it if it doesn't
- * have the specified minimum amount of free space.
- *
- */
-static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
-					   struct ipw_rx_packet *packet,
-					   int minimum_free_space)
-{
-
-	if (!packet) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&hw->lock, flags);
-		if (!list_empty(&hw->rx_pool)) {
-			packet = list_first_entry(&hw->rx_pool,
-					struct ipw_rx_packet, queue);
-			hw->rx_pool_size--;
-			spin_unlock_irqrestore(&hw->lock, flags);
-			list_del(&packet->queue);
-		} else {
-			const int min_capacity =
-				ipwireless_ppp_mru(hw->network) + 2;
-			int new_capacity;
-
-			spin_unlock_irqrestore(&hw->lock, flags);
-			new_capacity =
-				(minimum_free_space > min_capacity
-				 ? minimum_free_space
-				 : min_capacity);
-			packet = kmalloc(sizeof(struct ipw_rx_packet)
-					+ new_capacity, GFP_ATOMIC);
-			if (!packet)
-				return NULL;
-			packet->capacity = new_capacity;
-		}
-		packet->length = 0;
-	}
-
-	if (packet->length + minimum_free_space > packet->capacity) {
-		struct ipw_rx_packet *old_packet = packet;
-
-		packet = kmalloc(sizeof(struct ipw_rx_packet) +
-				old_packet->length + minimum_free_space,
-				GFP_ATOMIC);
-		if (!packet) {
-			kfree(old_packet);
-			return NULL;
-		}
-		memcpy(packet, old_packet,
-				sizeof(struct ipw_rx_packet)
-					+ old_packet->length);
-		packet->capacity = old_packet->length + minimum_free_space;
-		kfree(old_packet);
-	}
-
-	return packet;
-}
-
-static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet)
-{
-	if (hw->rx_pool_size > 6)
-		kfree(packet);
-	else {
-		hw->rx_pool_size++;
-		list_add(&packet->queue, &hw->rx_pool);
-	}
-}
-
-static void queue_received_packet(struct ipw_hardware *hw,
-				  unsigned int protocol,
-				  unsigned int address,
-				  const unsigned char *data, int length,
-				  int is_last)
-{
-	unsigned int channel_idx = address - 1;
-	struct ipw_rx_packet *packet = NULL;
-	unsigned long flags;
-
-	/* Discard packet if channel index is out of range. */
-	if (channel_idx >= NL_NUM_OF_ADDRESSES) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": data packet has bad address %u\n", address);
-		return;
-	}
-
-	/*
-	 * ->packet_assembler is safe to touch unlocked, this is the only place
-	 */
-	if (protocol == TL_PROTOCOLID_COM_DATA) {
-		struct ipw_rx_packet **assem =
-			&hw->packet_assembler[channel_idx];
-
-		/*
-		 * Create a new packet, or assembler already contains one
-		 * enlarge it by 'length' bytes.
-		 */
-		(*assem) = pool_allocate(hw, *assem, length);
-		if (!(*assem)) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-				": no memory for incomming data packet, dropped!\n");
-			return;
-		}
-		(*assem)->protocol = protocol;
-		(*assem)->channel_idx = channel_idx;
-
-		/* Append this packet data onto existing data. */
-		memcpy((unsigned char *)(*assem) +
-			       sizeof(struct ipw_rx_packet)
-				+ (*assem)->length, data, length);
-		(*assem)->length += length;
-		if (is_last) {
-			packet = *assem;
-			*assem = NULL;
-			/* Count queued DATA bytes only */
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->rx_bytes_queued += packet->length;
-			spin_unlock_irqrestore(&hw->lock, flags);
-		}
-	} else {
-		/* If it's a CTRL packet, don't assemble, just queue it. */
-		packet = pool_allocate(hw, NULL, length);
-		if (!packet) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-				": no memory for incomming ctrl packet, dropped!\n");
-			return;
-		}
-		packet->protocol = protocol;
-		packet->channel_idx = channel_idx;
-		memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet),
-				data, length);
-		packet->length = length;
-	}
-
-	/*
-	 * If this is the last packet, then send the assembled packet on to the
-	 * network layer.
-	 */
-	if (packet) {
-		spin_lock_irqsave(&hw->lock, flags);
-		list_add_tail(&packet->queue, &hw->rx_queue);
-		/* Block reception of incoming packets if queue is full. */
-		hw->blocking_rx =
-			(hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE);
-
-		spin_unlock_irqrestore(&hw->lock, flags);
-		schedule_work(&hw->work_rx);
-	}
-}
-
-/*
- * Workqueue callback
- */
-static void ipw_receive_data_work(struct work_struct *work_rx)
-{
-	struct ipw_hardware *hw =
-	    container_of(work_rx, struct ipw_hardware, work_rx);
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	while (!list_empty(&hw->rx_queue)) {
-		struct ipw_rx_packet *packet =
-			list_first_entry(&hw->rx_queue,
-					struct ipw_rx_packet, queue);
-
-		if (hw->shutting_down)
-			break;
-		list_del(&packet->queue);
-
-		/*
-		 * Note: ipwireless_network_packet_received must be called in a
-		 * process context (i.e. via schedule_work) because the tty
-		 * output code can sleep in the tty_flip_buffer_push call.
-		 */
-		if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
-			if (hw->network != NULL) {
-				/* If the network hasn't been disconnected. */
-				spin_unlock_irqrestore(&hw->lock, flags);
-				/*
-				 * This must run unlocked due to tty processing
-				 * and mutex locking
-				 */
-				ipwireless_network_packet_received(
-						hw->network,
-						packet->channel_idx,
-						(unsigned char *)packet
-						+ sizeof(struct ipw_rx_packet),
-						packet->length);
-				spin_lock_irqsave(&hw->lock, flags);
-			}
-			/* Count queued DATA bytes only */
-			hw->rx_bytes_queued -= packet->length;
-		} else {
-			/*
-			 * This is safe to be called locked, callchain does
-			 * not block
-			 */
-			handle_received_CTRL_packet(hw, packet->channel_idx,
-					(unsigned char *)packet
-					+ sizeof(struct ipw_rx_packet),
-					packet->length);
-		}
-		pool_free(hw, packet);
-		/*
-		 * Unblock reception of incoming packets if queue is no longer
-		 * full.
-		 */
-		hw->blocking_rx =
-			hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
-		if (hw->shutting_down)
-			break;
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void handle_received_CTRL_packet(struct ipw_hardware *hw,
-					unsigned int channel_idx,
-					const unsigned char *data, int len)
-{
-	const struct ipw_control_packet_body *body =
-		(const struct ipw_control_packet_body *) data;
-	unsigned int changed_mask;
-
-	if (len != sizeof(struct ipw_control_packet_body)) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": control packet was %d bytes - wrong size!\n",
-		       len);
-		return;
-	}
-
-	switch (body->sig_no) {
-	case COMCTRL_CTS:
-		changed_mask = IPW_CONTROL_LINE_CTS;
-		break;
-	case COMCTRL_DCD:
-		changed_mask = IPW_CONTROL_LINE_DCD;
-		break;
-	case COMCTRL_DSR:
-		changed_mask = IPW_CONTROL_LINE_DSR;
-		break;
-	case COMCTRL_RI:
-		changed_mask = IPW_CONTROL_LINE_RI;
-		break;
-	default:
-		changed_mask = 0;
-	}
-
-	if (changed_mask != 0) {
-		if (body->value)
-			hw->control_lines[channel_idx] |= changed_mask;
-		else
-			hw->control_lines[channel_idx] &= ~changed_mask;
-		if (hw->network)
-			ipwireless_network_notify_control_line_change(
-					hw->network,
-					channel_idx,
-					hw->control_lines[channel_idx],
-					changed_mask);
-	}
-}
-
-static void handle_received_packet(struct ipw_hardware *hw,
-				   const union nl_packet *packet,
-				   unsigned short len)
-{
-	unsigned int protocol = packet->hdr.protocol;
-	unsigned int address = packet->hdr.address;
-	unsigned int header_length;
-	const unsigned char *data;
-	unsigned int data_len;
-	int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
-
-	if (packet->hdr.packet_rank & NL_FIRST_PACKET)
-		header_length = NL_FIRST_PACKET_HEADER_SIZE;
-	else
-		header_length = NL_FOLLOWING_PACKET_HEADER_SIZE;
-
-	data = packet->rawpkt + header_length;
-	data_len = len - header_length;
-	switch (protocol) {
-	case TL_PROTOCOLID_COM_DATA:
-	case TL_PROTOCOLID_COM_CTRL:
-		queue_received_packet(hw, protocol, address, data, data_len,
-				is_last);
-		break;
-	case TL_PROTOCOLID_SETUP:
-		handle_received_SETUP_packet(hw, address, data, data_len,
-				is_last);
-		break;
-	}
-}
-
-static void acknowledge_data_read(struct ipw_hardware *hw)
-{
-	if (hw->hw_version == HW_VERSION_1)
-		outw(DCR_RXDONE, hw->base_port + IODCR);
-	else
-		writew(MEMRX_PCINTACKK,
-				&hw->memory_info_regs->memreg_pc_interrupt_ack);
-}
-
-/*
- * Retrieve a packet from the IPW hardware.
- */
-static void do_receive_packet(struct ipw_hardware *hw)
-{
-	unsigned len;
-	unsigned i;
-	unsigned char pkt[LL_MTU_MAX];
-
-	start_timing();
-
-	if (hw->hw_version == HW_VERSION_1) {
-		len = inw(hw->base_port + IODRR);
-		if (len > hw->ll_mtu) {
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": received a packet of %u bytes - longer than the MTU!\n", len);
-			outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
-			return;
-		}
-
-		for (i = 0; i < len; i += 2) {
-			__le16 raw_data = inw(hw->base_port + IODRR);
-			unsigned short data = le16_to_cpu(raw_data);
-
-			pkt[i] = (unsigned char) data;
-			pkt[i + 1] = (unsigned char) (data >> 8);
-		}
-	} else {
-		len = inw(hw->base_port);
-		if (len > hw->ll_mtu) {
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": received a packet of %u bytes - longer than the MTU!\n", len);
-			writew(MEMRX_PCINTACKK,
-				&hw->memory_info_regs->memreg_pc_interrupt_ack);
-			return;
-		}
-
-		for (i = 0; i < len; i += 2) {
-			__le16 raw_data = inw(hw->base_port);
-			unsigned short data = le16_to_cpu(raw_data);
-
-			pkt[i] = (unsigned char) data;
-			pkt[i + 1] = (unsigned char) (data >> 8);
-		}
-
-		while ((i & 3) != 2) {
-			inw(hw->base_port);
-			i += 2;
-		}
-	}
-
-	acknowledge_data_read(hw);
-
-	swap_packet_bitfield_from_le(pkt);
-
-	if (ipwireless_debug)
-		dump_data_bytes("recv", pkt, len);
-
-	handle_received_packet(hw, (union nl_packet *) pkt, len);
-
-	end_read_timing(len);
-}
-
-static int get_current_packet_priority(struct ipw_hardware *hw)
-{
-	/*
-	 * If we're initializing, don't send anything of higher priority than
-	 * PRIO_SETUP.  The network layer therefore need not care about
-	 * hardware initialization - any of its stuff will simply be queued
-	 * until setup is complete.
-	 */
-	return (hw->to_setup || hw->initializing
-			? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES);
-}
-
-/*
- * return 1 if something has been received from hw
- */
-static int get_packets_from_hw(struct ipw_hardware *hw)
-{
-	int received = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	while (hw->rx_ready && !hw->blocking_rx) {
-		received = 1;
-		hw->rx_ready--;
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		do_receive_packet(hw);
-
-		spin_lock_irqsave(&hw->lock, flags);
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	return received;
-}
-
-/*
- * Send pending packet up to given priority, prioritize SETUP data until
- * hardware is fully setup.
- *
- * return 1 if more packets can be sent
- */
-static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
-{
-	int more_to_send = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	if (hw->tx_queued && hw->tx_ready) {
-		int priority;
-		struct ipw_tx_packet *packet = NULL;
-
-		/* Pick a packet */
-		for (priority = 0; priority < priority_limit; priority++) {
-			if (!list_empty(&hw->tx_queue[priority])) {
-				packet = list_first_entry(
-						&hw->tx_queue[priority],
-						struct ipw_tx_packet,
-						queue);
-
-				hw->tx_queued--;
-				list_del(&packet->queue);
-
-				break;
-			}
-		}
-		if (!packet) {
-			hw->tx_queued = 0;
-			spin_unlock_irqrestore(&hw->lock, flags);
-			return 0;
-		}
-
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		/* Send */
-		do_send_packet(hw, packet);
-
-		/* Check if more to send */
-		spin_lock_irqsave(&hw->lock, flags);
-		for (priority = 0; priority < priority_limit; priority++)
-			if (!list_empty(&hw->tx_queue[priority])) {
-				more_to_send = 1;
-				break;
-			}
-
-		if (!more_to_send)
-			hw->tx_queued = 0;
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	return more_to_send;
-}
-
-/*
- * Send and receive all queued packets.
- */
-static void ipwireless_do_tasklet(unsigned long hw_)
-{
-	struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	if (hw->shutting_down) {
-		spin_unlock_irqrestore(&hw->lock, flags);
-		return;
-	}
-
-	if (hw->to_setup == 1) {
-		/*
-		 * Initial setup data sent to hardware
-		 */
-		hw->to_setup = 2;
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		ipw_setup_hardware(hw);
-		ipw_send_setup_packet(hw);
-
-		send_pending_packet(hw, PRIO_SETUP + 1);
-		get_packets_from_hw(hw);
-	} else {
-		int priority_limit = get_current_packet_priority(hw);
-		int again;
-
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		do {
-			again = send_pending_packet(hw, priority_limit);
-			again |= get_packets_from_hw(hw);
-		} while (again);
-	}
-}
-
-/*
- * return true if the card is physically present.
- */
-static int is_card_present(struct ipw_hardware *hw)
-{
-	if (hw->hw_version == HW_VERSION_1)
-		return inw(hw->base_port + IOIR) != 0xFFFF;
-	else
-		return readl(&hw->memory_info_regs->memreg_card_present) ==
-		    CARD_PRESENT_VALUE;
-}
-
-static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
-						  struct ipw_hardware *hw)
-{
-	unsigned short irqn;
-
-	irqn = inw(hw->base_port + IOIR);
-
-	/* Check if card is present */
-	if (irqn == 0xFFFF)
-		return IRQ_NONE;
-	else if (irqn != 0) {
-		unsigned short ack = 0;
-		unsigned long flags;
-
-		/* Transmit complete. */
-		if (irqn & IR_TXINTR) {
-			ack |= IR_TXINTR;
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->tx_ready = 1;
-			spin_unlock_irqrestore(&hw->lock, flags);
-		}
-		/* Received data */
-		if (irqn & IR_RXINTR) {
-			ack |= IR_RXINTR;
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->rx_ready++;
-			spin_unlock_irqrestore(&hw->lock, flags);
-		}
-		if (ack != 0) {
-			outw(ack, hw->base_port + IOIR);
-			tasklet_schedule(&hw->tasklet);
-		}
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw)
-{
-	unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
-
-	csr &= 0xfffd;
-	writew(csr, &hw->memregs_CCR->reg_config_and_status);
-}
-
-static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
-						     struct ipw_hardware *hw)
-{
-	int tx = 0;
-	int rx = 0;
-	int rx_repeat = 0;
-	int try_mem_tx_old;
-	unsigned long flags;
-
-	do {
-
-	unsigned short memtx = readw(hw->memreg_tx);
-	unsigned short memtx_serial;
-	unsigned short memrxdone =
-		readw(&hw->memory_info_regs->memreg_rx_done);
-
-	try_mem_tx_old = 0;
-
-	/* check whether the interrupt was generated by ipwireless card */
-	if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) {
-
-		/* check if the card uses memreg_tx_old register */
-		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
-			memtx = readw(&hw->memory_info_regs->memreg_tx_old);
-			if (memtx & MEMTX_TX) {
-				printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-					": Using memreg_tx_old\n");
-				hw->memreg_tx =
-					&hw->memory_info_regs->memreg_tx_old;
-			} else {
-				return IRQ_NONE;
-			}
-		} else
-			return IRQ_NONE;
-	}
-
-	/*
-	 * See if the card is physically present. Note that while it is
-	 * powering up, it appears not to be present.
-	 */
-	if (!is_card_present(hw)) {
-		acknowledge_pcmcia_interrupt(hw);
-		return IRQ_HANDLED;
-	}
-
-	memtx_serial = memtx & (unsigned short) 0xff00;
-	if (memtx & MEMTX_TX) {
-		writew(memtx_serial, hw->memreg_tx);
-
-		if (hw->serial_number_detected) {
-			if (memtx_serial != hw->last_memtx_serial) {
-				hw->last_memtx_serial = memtx_serial;
-				spin_lock_irqsave(&hw->lock, flags);
-				hw->rx_ready++;
-				spin_unlock_irqrestore(&hw->lock, flags);
-				rx = 1;
-			} else
-				/* Ignore 'Timer Recovery' duplicates. */
-				rx_repeat = 1;
-		} else {
-			/*
-			 * If a non-zero serial number is seen, then enable
-			 * serial number checking.
-			 */
-			if (memtx_serial != 0) {
-				hw->serial_number_detected = 1;
-				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-					": memreg_tx serial num detected\n");
-
-				spin_lock_irqsave(&hw->lock, flags);
-				hw->rx_ready++;
-				spin_unlock_irqrestore(&hw->lock, flags);
-			}
-			rx = 1;
-		}
-	}
-	if (memrxdone & MEMRX_RX_DONE) {
-		writew(0, &hw->memory_info_regs->memreg_rx_done);
-		spin_lock_irqsave(&hw->lock, flags);
-		hw->tx_ready = 1;
-		spin_unlock_irqrestore(&hw->lock, flags);
-		tx = 1;
-	}
-	if (tx)
-		writew(MEMRX_PCINTACKK,
-				&hw->memory_info_regs->memreg_pc_interrupt_ack);
-
-	acknowledge_pcmcia_interrupt(hw);
-
-	if (tx || rx)
-		tasklet_schedule(&hw->tasklet);
-	else if (!rx_repeat) {
-		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
-			if (hw->serial_number_detected)
-				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": spurious interrupt - new_tx mode\n");
-			else {
-				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": no valid memreg_tx value - switching to the old memreg_tx\n");
-				hw->memreg_tx =
-					&hw->memory_info_regs->memreg_tx_old;
-				try_mem_tx_old = 1;
-			}
-		} else
-			printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": spurious interrupt - old_tx mode\n");
-	}
-
-	} while (try_mem_tx_old == 1);
-
-	return IRQ_HANDLED;
-}
-
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id)
-{
-	struct ipw_dev *ipw = dev_id;
-
-	if (ipw->hardware->hw_version == HW_VERSION_1)
-		return ipwireless_handle_v1_interrupt(irq, ipw->hardware);
-	else
-		return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware);
-}
-
-static void flush_packets_to_hw(struct ipw_hardware *hw)
-{
-	int priority_limit;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	priority_limit = get_current_packet_priority(hw);
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	while (send_pending_packet(hw, priority_limit));
-}
-
-static void send_packet(struct ipw_hardware *hw, int priority,
-			struct ipw_tx_packet *packet)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	list_add_tail(&packet->queue, &hw->tx_queue[priority]);
-	hw->tx_queued++;
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	flush_packets_to_hw(hw);
-}
-
-/* Create data packet, non-atomic allocation */
-static void *alloc_data_packet(int data_size,
-				unsigned char dest_addr,
-				unsigned char protocol)
-{
-	struct ipw_tx_packet *packet = kzalloc(
-			sizeof(struct ipw_tx_packet) + data_size,
-			GFP_ATOMIC);
-
-	if (!packet)
-		return NULL;
-
-	INIT_LIST_HEAD(&packet->queue);
-	packet->dest_addr = dest_addr;
-	packet->protocol = protocol;
-	packet->length = data_size;
-
-	return packet;
-}
-
-static void *alloc_ctrl_packet(int header_size,
-			       unsigned char dest_addr,
-			       unsigned char protocol,
-			       unsigned char sig_no)
-{
-	/*
-	 * sig_no is located right after ipw_tx_packet struct in every
-	 * CTRL or SETUP packets, we can use ipw_control_packet as a
-	 * common struct
-	 */
-	struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC);
-
-	if (!packet)
-		return NULL;
-
-	INIT_LIST_HEAD(&packet->header.queue);
-	packet->header.dest_addr = dest_addr;
-	packet->header.protocol = protocol;
-	packet->header.length = header_size - sizeof(struct ipw_tx_packet);
-	packet->body.sig_no = sig_no;
-
-	return packet;
-}
-
-int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
-			    const unsigned char *data, unsigned int length,
-			    void (*callback) (void *cb, unsigned int length),
-			    void *callback_data)
-{
-	struct ipw_tx_packet *packet;
-
-	packet = alloc_data_packet(length, (channel_idx + 1),
-			TL_PROTOCOLID_COM_DATA);
-	if (!packet)
-		return -ENOMEM;
-	packet->packet_callback = callback;
-	packet->callback_data = callback_data;
-	memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data,
-			length);
-
-	send_packet(hw, PRIO_DATA, packet);
-	return 0;
-}
-
-static int set_control_line(struct ipw_hardware *hw, int prio,
-			   unsigned int channel_idx, int line, int state)
-{
-	struct ipw_control_packet *packet;
-	int protocolid = TL_PROTOCOLID_COM_CTRL;
-
-	if (prio == PRIO_SETUP)
-		protocolid = TL_PROTOCOLID_SETUP;
-
-	packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
-			(channel_idx + 1), protocolid, line);
-	if (!packet)
-		return -ENOMEM;
-	packet->header.length = sizeof(struct ipw_control_packet_body);
-	packet->body.value = (state == 0 ? 0 : 1);
-	send_packet(hw, prio, &packet->header);
-	return 0;
-}
-
-
-static int set_DTR(struct ipw_hardware *hw, int priority,
-		   unsigned int channel_idx, int state)
-{
-	if (state != 0)
-		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR;
-	else
-		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR;
-
-	return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state);
-}
-
-static int set_RTS(struct ipw_hardware *hw, int priority,
-		   unsigned int channel_idx, int state)
-{
-	if (state != 0)
-		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS;
-	else
-		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS;
-
-	return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state);
-}
-
-int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
-		       int state)
-{
-	return set_DTR(hw, PRIO_CTRL, channel_idx, state);
-}
-
-int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
-		       int state)
-{
-	return set_RTS(hw, PRIO_CTRL, channel_idx, state);
-}
-
-struct ipw_setup_get_version_query_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_get_version_qry body;
-};
-
-struct ipw_setup_config_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_config_msg body;
-};
-
-struct ipw_setup_config_done_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_config_done_msg body;
-};
-
-struct ipw_setup_open_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_open_msg body;
-};
-
-struct ipw_setup_info_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_info_msg body;
-};
-
-struct ipw_setup_reboot_msg_ack {
-	struct ipw_tx_packet header;
-	struct TlSetupRebootMsgAck body;
-};
-
-/* This handles the actual initialization of the card */
-static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
-{
-	struct ipw_setup_config_packet *config_packet;
-	struct ipw_setup_config_done_packet *config_done_packet;
-	struct ipw_setup_open_packet *open_packet;
-	struct ipw_setup_info_packet *info_packet;
-	int port;
-	unsigned int channel_idx;
-
-	/* generate config packet */
-	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
-		config_packet = alloc_ctrl_packet(
-				sizeof(struct ipw_setup_config_packet),
-				ADDR_SETUP_PROT,
-				TL_PROTOCOLID_SETUP,
-				TL_SETUP_SIGNO_CONFIG_MSG);
-		if (!config_packet)
-			goto exit_nomem;
-		config_packet->header.length = sizeof(struct tl_setup_config_msg);
-		config_packet->body.port_no = port;
-		config_packet->body.prio_data = PRIO_DATA;
-		config_packet->body.prio_ctrl = PRIO_CTRL;
-		send_packet(hw, PRIO_SETUP, &config_packet->header);
-	}
-	config_done_packet = alloc_ctrl_packet(
-			sizeof(struct ipw_setup_config_done_packet),
-			ADDR_SETUP_PROT,
-			TL_PROTOCOLID_SETUP,
-			TL_SETUP_SIGNO_CONFIG_DONE_MSG);
-	if (!config_done_packet)
-		goto exit_nomem;
-	config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg);
-	send_packet(hw, PRIO_SETUP, &config_done_packet->header);
-
-	/* generate open packet */
-	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
-		open_packet = alloc_ctrl_packet(
-				sizeof(struct ipw_setup_open_packet),
-				ADDR_SETUP_PROT,
-				TL_PROTOCOLID_SETUP,
-				TL_SETUP_SIGNO_OPEN_MSG);
-		if (!open_packet)
-			goto exit_nomem;
-		open_packet->header.length = sizeof(struct tl_setup_open_msg);
-		open_packet->body.port_no = port;
-		send_packet(hw, PRIO_SETUP, &open_packet->header);
-	}
-	for (channel_idx = 0;
-			channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) {
-		int ret;
-
-		ret = set_DTR(hw, PRIO_SETUP, channel_idx,
-			(hw->control_lines[channel_idx] &
-			 IPW_CONTROL_LINE_DTR) != 0);
-		if (ret) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-					": error setting DTR (%d)\n", ret);
-			return;
-		}
-
-		set_RTS(hw, PRIO_SETUP, channel_idx,
-			(hw->control_lines [channel_idx] &
-			 IPW_CONTROL_LINE_RTS) != 0);
-		if (ret) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-					": error setting RTS (%d)\n", ret);
-			return;
-		}
-	}
-	/*
-	 * For NDIS we assume that we are using sync PPP frames, for COM async.
-	 * This driver uses NDIS mode too. We don't bother with translation
-	 * from async -> sync PPP.
-	 */
-	info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet),
-			ADDR_SETUP_PROT,
-			TL_PROTOCOLID_SETUP,
-			TL_SETUP_SIGNO_INFO_MSG);
-	if (!info_packet)
-		goto exit_nomem;
-	info_packet->header.length = sizeof(struct tl_setup_info_msg);
-	info_packet->body.driver_type = NDISWAN_DRIVER;
-	info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION;
-	info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION;
-	send_packet(hw, PRIO_SETUP, &info_packet->header);
-
-	/* Initialization is now complete, so we clear the 'to_setup' flag */
-	hw->to_setup = 0;
-
-	return;
-
-exit_nomem:
-	printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-			": not enough memory to alloc control packet\n");
-	hw->to_setup = -1;
-}
-
-static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
-		unsigned char vers_no)
-{
-	del_timer(&hw->setup_timer);
-	hw->initializing = 0;
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n");
-
-	if (vers_no == TL_SETUP_VERSION)
-		__handle_setup_get_version_rsp(hw);
-	else
-		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-				": invalid hardware version no %u\n",
-				(unsigned int) vers_no);
-}
-
-static void ipw_send_setup_packet(struct ipw_hardware *hw)
-{
-	struct ipw_setup_get_version_query_packet *ver_packet;
-
-	ver_packet = alloc_ctrl_packet(
-			sizeof(struct ipw_setup_get_version_query_packet),
-			ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
-			TL_SETUP_SIGNO_GET_VERSION_QRY);
-	ver_packet->header.length = sizeof(struct tl_setup_get_version_qry);
-
-	/*
-	 * Response is handled in handle_received_SETUP_packet
-	 */
-	send_packet(hw, PRIO_SETUP, &ver_packet->header);
-}
-
-static void handle_received_SETUP_packet(struct ipw_hardware *hw,
-					 unsigned int address,
-					 const unsigned char *data, int len,
-					 int is_last)
-{
-	const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data;
-
-	if (address != ADDR_SETUP_PROT) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": setup packet has bad address %d\n", address);
-		return;
-	}
-
-	switch (rx_msg->sig_no) {
-	case TL_SETUP_SIGNO_GET_VERSION_RSP:
-		if (hw->to_setup)
-			handle_setup_get_version_rsp(hw,
-					rx_msg->version_rsp_msg.version);
-		break;
-
-	case TL_SETUP_SIGNO_OPEN_MSG:
-		if (ipwireless_debug) {
-			unsigned int channel_idx = rx_msg->open_msg.port_no - 1;
-
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": OPEN_MSG [channel %u] reply received\n",
-			       channel_idx);
-		}
-		break;
-
-	case TL_SETUP_SIGNO_INFO_MSG_ACK:
-		if (ipwireless_debug)
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-			       ": card successfully configured as NDISWAN\n");
-		break;
-
-	case TL_SETUP_SIGNO_REBOOT_MSG:
-		if (hw->to_setup)
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-			       ": Setup not completed - ignoring reboot msg\n");
-		else {
-			struct ipw_setup_reboot_msg_ack *packet;
-
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-			       ": Acknowledging REBOOT message\n");
-			packet = alloc_ctrl_packet(
-					sizeof(struct ipw_setup_reboot_msg_ack),
-					ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
-					TL_SETUP_SIGNO_REBOOT_MSG_ACK);
-			packet->header.length =
-				sizeof(struct TlSetupRebootMsgAck);
-			send_packet(hw, PRIO_SETUP, &packet->header);
-			if (hw->reboot_callback)
-				hw->reboot_callback(hw->reboot_callback_data);
-		}
-		break;
-
-	default:
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": unknown setup message %u received\n",
-		       (unsigned int) rx_msg->sig_no);
-	}
-}
-
-static void do_close_hardware(struct ipw_hardware *hw)
-{
-	unsigned int irqn;
-
-	if (hw->hw_version == HW_VERSION_1) {
-		/* Disable TX and RX interrupts. */
-		outw(0, hw->base_port + IOIER);
-
-		/* Acknowledge any outstanding interrupt requests */
-		irqn = inw(hw->base_port + IOIR);
-		if (irqn & IR_TXINTR)
-			outw(IR_TXINTR, hw->base_port + IOIR);
-		if (irqn & IR_RXINTR)
-			outw(IR_RXINTR, hw->base_port + IOIR);
-
-		synchronize_irq(hw->irq);
-	}
-}
-
-struct ipw_hardware *ipwireless_hardware_create(void)
-{
-	int i;
-	struct ipw_hardware *hw =
-		kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL);
-
-	if (!hw)
-		return NULL;
-
-	hw->irq = -1;
-	hw->initializing = 1;
-	hw->tx_ready = 1;
-	hw->rx_bytes_queued = 0;
-	hw->rx_pool_size = 0;
-	hw->last_memtx_serial = (unsigned short) 0xffff;
-	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
-		INIT_LIST_HEAD(&hw->tx_queue[i]);
-
-	INIT_LIST_HEAD(&hw->rx_queue);
-	INIT_LIST_HEAD(&hw->rx_pool);
-	spin_lock_init(&hw->lock);
-	tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
-	INIT_WORK(&hw->work_rx, ipw_receive_data_work);
-	setup_timer(&hw->setup_timer, ipwireless_setup_timer,
-			(unsigned long) hw);
-
-	return hw;
-}
-
-void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
-		unsigned int base_port,
-		void __iomem *attr_memory,
-		void __iomem *common_memory,
-		int is_v2_card,
-		void (*reboot_callback) (void *data),
-		void *reboot_callback_data)
-{
-	if (hw->removed) {
-		hw->removed = 0;
-		enable_irq(hw->irq);
-	}
-	hw->base_port = base_port;
-	hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1);
-	hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2);
-	hw->memregs_CCR = (struct MEMCCR __iomem *)
-			((unsigned short __iomem *) attr_memory + 0x200);
-	hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
-	hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new;
-	hw->reboot_callback = reboot_callback;
-	hw->reboot_callback_data = reboot_callback_data;
-}
-
-void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw)
-{
-	hw->initializing = 1;
-	hw->init_loops = 0;
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-	       ": waiting for card to start up...\n");
-	ipwireless_setup_timer((unsigned long) hw);
-}
-
-static void ipwireless_setup_timer(unsigned long data)
-{
-	struct ipw_hardware *hw = (struct ipw_hardware *) data;
-
-	hw->init_loops++;
-
-	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY &&
-			hw->hw_version == HW_VERSION_2 &&
-			hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-				": failed to startup using TX2, trying TX\n");
-
-		hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old;
-		hw->init_loops = 0;
-	}
-	/* Give up after a certain number of retries */
-	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": card failed to start up!\n");
-		hw->initializing = 0;
-	} else {
-		/* Do not attempt to write to the board if it is not present. */
-		if (is_card_present(hw)) {
-			unsigned long flags;
-
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->to_setup = 1;
-			hw->tx_ready = 1;
-			spin_unlock_irqrestore(&hw->lock, flags);
-			tasklet_schedule(&hw->tasklet);
-		}
-
-		mod_timer(&hw->setup_timer,
-			jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO));
-	}
-}
-
-/*
- * Stop any interrupts from executing so that, once this function returns,
- * other layers of the driver can be sure they won't get any more callbacks.
- * Thus must be called on a proper process context.
- */
-void ipwireless_stop_interrupts(struct ipw_hardware *hw)
-{
-	if (!hw->shutting_down) {
-		/* Tell everyone we are going down. */
-		hw->shutting_down = 1;
-		del_timer(&hw->setup_timer);
-
-		/* Prevent the hardware from sending any more interrupts */
-		do_close_hardware(hw);
-	}
-}
-
-void ipwireless_hardware_free(struct ipw_hardware *hw)
-{
-	int i;
-	struct ipw_rx_packet *rp, *rq;
-	struct ipw_tx_packet *tp, *tq;
-
-	ipwireless_stop_interrupts(hw);
-
-	flush_work_sync(&hw->work_rx);
-
-	for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
-		if (hw->packet_assembler[i] != NULL)
-			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) {
-			list_del(&tp->queue);
-			kfree(tp);
-		}
-
-	list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) {
-		list_del(&rp->queue);
-		kfree(rp);
-	}
-
-	list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) {
-		list_del(&rp->queue);
-		kfree(rp);
-	}
-	kfree(hw);
-}
-
-/*
- * Associate the specified network with this hardware, so it will receive events
- * from it.
- */
-void ipwireless_associate_network(struct ipw_hardware *hw,
-				  struct ipw_network *network)
-{
-	hw->network = network;
-}
diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h
deleted file mode 100644
index 90a8590..0000000
--- a/drivers/char/pcmcia/ipwireless/hardware.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_HARDWARE_H_
-#define _IPWIRELESS_CS_HARDWARE_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#define IPW_CONTROL_LINE_CTS 0x0001
-#define IPW_CONTROL_LINE_DCD 0x0002
-#define IPW_CONTROL_LINE_DSR 0x0004
-#define IPW_CONTROL_LINE_RI  0x0008
-#define IPW_CONTROL_LINE_DTR 0x0010
-#define IPW_CONTROL_LINE_RTS 0x0020
-
-struct ipw_hardware;
-struct ipw_network;
-
-struct ipw_hardware *ipwireless_hardware_create(void);
-void ipwireless_hardware_free(struct ipw_hardware *hw);
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id);
-int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
-		int state);
-int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
-		int state);
-int ipwireless_send_packet(struct ipw_hardware *hw,
-			    unsigned int channel_idx,
-			    const unsigned char *data,
-			    unsigned int length,
-			    void (*packet_sent_callback) (void *cb,
-							  unsigned int length),
-			    void *sent_cb_data);
-void ipwireless_associate_network(struct ipw_hardware *hw,
-		struct ipw_network *net);
-void ipwireless_stop_interrupts(struct ipw_hardware *hw);
-void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
-				 unsigned int base_port,
-				 void __iomem *attr_memory,
-				 void __iomem *common_memory,
-				 int is_v2_card,
-				 void (*reboot_cb) (void *data),
-				 void *reboot_cb_data);
-void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
-void ipwireless_sleep(unsigned int tenths);
-
-#endif
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
deleted file mode 100644
index 444155a..0000000
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include "hardware.h"
-#include "network.h"
-#include "main.h"
-#include "tty.h"
-
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <pcmcia/cisreg.h>
-#include <pcmcia/device_id.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/ds.h>
-
-static struct pcmcia_device_id ipw_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
-	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
-	PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
-
-static void ipwireless_detach(struct pcmcia_device *link);
-
-/*
- * Module params
- */
-/* Debug mode: more verbose, print sent/recv bytes */
-int ipwireless_debug;
-int ipwireless_loopback;
-int ipwireless_out_queue = 10;
-
-module_param_named(debug, ipwireless_debug, int, 0);
-module_param_named(loopback, ipwireless_loopback, int, 0);
-module_param_named(out_queue, ipwireless_out_queue, int, 0);
-MODULE_PARM_DESC(debug, "switch on debug messages [0]");
-MODULE_PARM_DESC(loopback,
-		"debug: enable ras_raw channel [0]");
-MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
-
-/* Executes in process context. */
-static void signalled_reboot_work(struct work_struct *work_reboot)
-{
-	struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
-			work_reboot);
-	struct pcmcia_device *link = ipw->link;
-	pcmcia_reset_card(link->socket);
-}
-
-static void signalled_reboot_callback(void *callback_data)
-{
-	struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
-
-	/* Delegate to process context. */
-	schedule_work(&ipw->work_reboot);
-}
-
-static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
-{
-	struct ipw_dev *ipw = priv_data;
-	int ret;
-
-	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-	/* 0x40 causes it to generate level mode interrupts. */
-	/* 0x04 enables IREQ pin. */
-	p_dev->config_index |= 0x44;
-	p_dev->io_lines = 16;
-	ret = pcmcia_request_io(p_dev);
-	if (ret)
-		return ret;
-
-	if (!request_region(p_dev->resource[0]->start,
-			    resource_size(p_dev->resource[0]),
-			    IPWIRELESS_PCCARD_NAME)) {
-		ret = -EBUSY;
-		goto exit;
-	}
-
-	p_dev->resource[2]->flags |=
-		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-
-	ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
-	if (ret != 0)
-		goto exit1;
-
-	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
-	if (ret != 0)
-		goto exit1;
-
-	ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
-
-	ipw->common_memory = ioremap(p_dev->resource[2]->start,
-				resource_size(p_dev->resource[2]));
-	if (!request_mem_region(p_dev->resource[2]->start,
-				resource_size(p_dev->resource[2]),
-				IPWIRELESS_PCCARD_NAME)) {
-		ret = -EBUSY;
-		goto exit2;
-	}
-
-	p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
-					WIN_ENABLE;
-	p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
-	ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
-	if (ret != 0)
-		goto exit3;
-
-	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
-	if (ret != 0)
-		goto exit3;
-
-	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
-				resource_size(p_dev->resource[3]));
-	if (!request_mem_region(p_dev->resource[3]->start,
-				resource_size(p_dev->resource[3]),
-				IPWIRELESS_PCCARD_NAME)) {
-		ret = -EBUSY;
-		goto exit4;
-	}
-
-	return 0;
-
-exit4:
-	iounmap(ipw->attr_memory);
-exit3:
-	release_mem_region(p_dev->resource[2]->start,
-			resource_size(p_dev->resource[2]));
-exit2:
-	iounmap(ipw->common_memory);
-exit1:
-	release_region(p_dev->resource[0]->start,
-		       resource_size(p_dev->resource[0]));
-exit:
-	pcmcia_disable_device(p_dev);
-	return ret;
-}
-
-static int config_ipwireless(struct ipw_dev *ipw)
-{
-	struct pcmcia_device *link = ipw->link;
-	int ret = 0;
-
-	ipw->is_v2_card = 0;
-	link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
-		CONF_ENABLE_IRQ;
-
-	ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
-	if (ret != 0)
-		return ret;
-
-	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
-
-	ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
-				    ipw->attr_memory, ipw->common_memory,
-				    ipw->is_v2_card, signalled_reboot_callback,
-				    ipw);
-
-	ret = pcmcia_request_irq(link, ipwireless_interrupt);
-	if (ret != 0)
-		goto exit;
-
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
-			ipw->is_v2_card ? "V2/V3" : "V1");
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		": I/O ports %pR, irq %d\n", link->resource[0],
-			(unsigned int) link->irq);
-	if (ipw->attr_memory && ipw->common_memory)
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			": attr memory %pR, common memory %pR\n",
-			link->resource[3],
-			link->resource[2]);
-
-	ipw->network = ipwireless_network_create(ipw->hardware);
-	if (!ipw->network)
-		goto exit;
-
-	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network);
-	if (!ipw->tty)
-		goto exit;
-
-	ipwireless_init_hardware_v2_v3(ipw->hardware);
-
-	/*
-	 * Do the RequestConfiguration last, because it enables interrupts.
-	 * Then we don't get any interrupts before we're ready for them.
-	 */
-	ret = pcmcia_enable_device(link);
-	if (ret != 0)
-		goto exit;
-
-	return 0;
-
-exit:
-	if (ipw->common_memory) {
-		release_mem_region(link->resource[2]->start,
-				resource_size(link->resource[2]));
-		iounmap(ipw->common_memory);
-	}
-	if (ipw->attr_memory) {
-		release_mem_region(link->resource[3]->start,
-				resource_size(link->resource[3]));
-		iounmap(ipw->attr_memory);
-	}
-	pcmcia_disable_device(link);
-	return -1;
-}
-
-static void release_ipwireless(struct ipw_dev *ipw)
-{
-	release_region(ipw->link->resource[0]->start,
-		       resource_size(ipw->link->resource[0]));
-	if (ipw->common_memory) {
-		release_mem_region(ipw->link->resource[2]->start,
-				resource_size(ipw->link->resource[2]));
-		iounmap(ipw->common_memory);
-	}
-	if (ipw->attr_memory) {
-		release_mem_region(ipw->link->resource[3]->start,
-				resource_size(ipw->link->resource[3]));
-		iounmap(ipw->attr_memory);
-	}
-	pcmcia_disable_device(ipw->link);
-}
-
-/*
- * ipwireless_attach() creates an "instance" of the driver, allocating
- * local data structures for one device (one interface).  The device
- * is registered with Card Services.
- *
- * The pcmcia_device structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a
- * card insertion event.
- */
-static int ipwireless_attach(struct pcmcia_device *link)
-{
-	struct ipw_dev *ipw;
-	int ret;
-
-	ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
-	if (!ipw)
-		return -ENOMEM;
-
-	ipw->link = link;
-	link->priv = ipw;
-
-	ipw->hardware = ipwireless_hardware_create();
-	if (!ipw->hardware) {
-		kfree(ipw);
-		return -ENOMEM;
-	}
-	/* RegisterClient will call config_ipwireless */
-
-	ret = config_ipwireless(ipw);
-
-	if (ret != 0) {
-		ipwireless_detach(link);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
-static void ipwireless_detach(struct pcmcia_device *link)
-{
-	struct ipw_dev *ipw = link->priv;
-
-	release_ipwireless(ipw);
-
-	if (ipw->tty != NULL)
-		ipwireless_tty_free(ipw->tty);
-	if (ipw->network != NULL)
-		ipwireless_network_free(ipw->network);
-	if (ipw->hardware != NULL)
-		ipwireless_hardware_free(ipw->hardware);
-	kfree(ipw);
-}
-
-static struct pcmcia_driver me = {
-	.owner		= THIS_MODULE,
-	.probe          = ipwireless_attach,
-	.remove         = ipwireless_detach,
-	.name		= IPWIRELESS_PCCARD_NAME,
-	.id_table       = ipw_ids
-};
-
-/*
- * Module insertion : initialisation of the module.
- * Register the card with cardmgr...
- */
-static int __init init_ipwireless(void)
-{
-	int ret;
-
-	ret = ipwireless_tty_init();
-	if (ret != 0)
-		return ret;
-
-	ret = pcmcia_register_driver(&me);
-	if (ret != 0)
-		ipwireless_tty_release();
-
-	return ret;
-}
-
-/*
- * Module removal
- */
-static void __exit exit_ipwireless(void)
-{
-	pcmcia_unregister_driver(&me);
-	ipwireless_tty_release();
-}
-
-module_init(init_ipwireless);
-module_exit(exit_ipwireless);
-
-MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
-MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
deleted file mode 100644
index f2cbb11..0000000
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_H_
-#define _IPWIRELESS_CS_H_
-
-#include <linux/sched.h>
-#include <linux/types.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include "hardware.h"
-
-#define IPWIRELESS_PCCARD_NAME		"ipwireless"
-#define IPWIRELESS_PCMCIA_VERSION	"1.1"
-#define IPWIRELESS_PCMCIA_AUTHOR        \
-	"Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba"
-
-#define IPWIRELESS_TX_QUEUE_SIZE  262144
-#define IPWIRELESS_RX_QUEUE_SIZE  262144
-
-#define IPWIRELESS_STATE_DEBUG
-
-struct ipw_hardware;
-struct ipw_network;
-struct ipw_tty;
-
-struct ipw_dev {
-	struct pcmcia_device *link;
-	int is_v2_card;
-
-	void __iomem *attr_memory;
-
-	void __iomem *common_memory;
-
-	/* Reference to attribute memory, containing CIS data */
-	void *attribute_memory;
-
-	/* Hardware context */
-	struct ipw_hardware *hardware;
-	/* Network layer context */
-	struct ipw_network *network;
-	/* TTY device context */
-	struct ipw_tty *tty;
-	struct work_struct work_reboot;
-};
-
-/* Module parametres */
-extern int ipwireless_debug;
-extern int ipwireless_loopback;
-extern int ipwireless_out_queue;
-
-#endif
diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c
deleted file mode 100644
index f7daeea..0000000
--- a/drivers/char/pcmcia/ipwireless/network.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/netdevice.h>
-#include <linux/ppp_channel.h>
-#include <linux/ppp_defs.h>
-#include <linux/slab.h>
-#include <linux/if_ppp.h>
-#include <linux/skbuff.h>
-
-#include "network.h"
-#include "hardware.h"
-#include "main.h"
-#include "tty.h"
-
-#define MAX_ASSOCIATED_TTYS 2
-
-#define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
-
-struct ipw_network {
-	/* Hardware context, used for calls to hardware layer. */
-	struct ipw_hardware *hardware;
-	/* Context for kernel 'generic_ppp' functionality */
-	struct ppp_channel *ppp_channel;
-	/* tty context connected with IPW console */
-	struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
-	/* True if ppp needs waking up once we're ready to xmit */
-	int ppp_blocked;
-	/* Number of packets queued up in hardware module. */
-	int outgoing_packets_queued;
-	/* Spinlock to avoid interrupts during shutdown */
-	spinlock_t lock;
-	struct mutex close_lock;
-
-	/* PPP ioctl data, not actually used anywere */
-	unsigned int flags;
-	unsigned int rbits;
-	u32 xaccm[8];
-	u32 raccm;
-	int mru;
-
-	int shutting_down;
-	unsigned int ras_control_lines;
-
-	struct work_struct work_go_online;
-	struct work_struct work_go_offline;
-};
-
-static void notify_packet_sent(void *callback_data, unsigned int packet_length)
-{
-	struct ipw_network *network = callback_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	network->outgoing_packets_queued--;
-	if (network->ppp_channel != NULL) {
-		if (network->ppp_blocked) {
-			network->ppp_blocked = 0;
-			spin_unlock_irqrestore(&network->lock, flags);
-			ppp_output_wakeup(network->ppp_channel);
-			if (ipwireless_debug)
-				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-				       ": ppp unblocked\n");
-		} else
-			spin_unlock_irqrestore(&network->lock, flags);
-	} else
-		spin_unlock_irqrestore(&network->lock, flags);
-}
-
-/*
- * Called by the ppp system when it has a packet to send to the hardware.
- */
-static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
-				     struct sk_buff *skb)
-{
-	struct ipw_network *network = ppp_channel->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->outgoing_packets_queued < ipwireless_out_queue) {
-		unsigned char *buf;
-		static unsigned char header[] = {
-			PPP_ALLSTATIONS, /* 0xff */
-			PPP_UI,		 /* 0x03 */
-		};
-		int ret;
-
-		network->outgoing_packets_queued++;
-		spin_unlock_irqrestore(&network->lock, flags);
-
-		/*
-		 * If we have the requested amount of headroom in the skb we
-		 * were handed, then we can add the header efficiently.
-		 */
-		if (skb_headroom(skb) >= 2) {
-			memcpy(skb_push(skb, 2), header, 2);
-			ret = ipwireless_send_packet(network->hardware,
-					       IPW_CHANNEL_RAS, skb->data,
-					       skb->len,
-					       notify_packet_sent,
-					       network);
-			if (ret == -1) {
-				skb_pull(skb, 2);
-				return 0;
-			}
-		} else {
-			/* Otherwise (rarely) we do it inefficiently. */
-			buf = kmalloc(skb->len + 2, GFP_ATOMIC);
-			if (!buf)
-				return 0;
-			memcpy(buf + 2, skb->data, skb->len);
-			memcpy(buf, header, 2);
-			ret = ipwireless_send_packet(network->hardware,
-					       IPW_CHANNEL_RAS, buf,
-					       skb->len + 2,
-					       notify_packet_sent,
-					       network);
-			kfree(buf);
-			if (ret == -1)
-				return 0;
-		}
-		kfree_skb(skb);
-		return 1;
-	} else {
-		/*
-		 * Otherwise reject the packet, and flag that the ppp system
-		 * needs to be unblocked once we are ready to send.
-		 */
-		network->ppp_blocked = 1;
-		spin_unlock_irqrestore(&network->lock, flags);
-		if (ipwireless_debug)
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
-		return 0;
-	}
-}
-
-/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
-static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
-				unsigned int cmd, unsigned long arg)
-{
-	struct ipw_network *network = ppp_channel->private;
-	int err, val;
-	u32 accm[8];
-	int __user *user_arg = (int __user *) arg;
-
-	err = -EFAULT;
-	switch (cmd) {
-	case PPPIOCGFLAGS:
-		val = network->flags | network->rbits;
-		if (put_user(val, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSFLAGS:
-		if (get_user(val, user_arg))
-			break;
-		network->flags = val & ~SC_RCV_BITS;
-		network->rbits = val & SC_RCV_BITS;
-		err = 0;
-		break;
-
-	case PPPIOCGASYNCMAP:
-		if (put_user(network->xaccm[0], user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSASYNCMAP:
-		if (get_user(network->xaccm[0], user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCGRASYNCMAP:
-		if (put_user(network->raccm, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSRASYNCMAP:
-		if (get_user(network->raccm, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCGXASYNCMAP:
-		if (copy_to_user((void __user *) arg, network->xaccm,
-					sizeof(network->xaccm)))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSXASYNCMAP:
-		if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
-			break;
-		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
-		accm[3] |= 0x60000000U;	/* must escape 0x7d, 0x7e */
-		memcpy(network->xaccm, accm, sizeof(network->xaccm));
-		err = 0;
-		break;
-
-	case PPPIOCGMRU:
-		if (put_user(network->mru, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSMRU:
-		if (get_user(val, user_arg))
-			break;
-		if (val < PPP_MRU)
-			val = PPP_MRU;
-		network->mru = val;
-		err = 0;
-		break;
-
-	default:
-		err = -ENOTTY;
-	}
-
-	return err;
-}
-
-static const struct ppp_channel_ops ipwireless_ppp_channel_ops = {
-	.start_xmit = ipwireless_ppp_start_xmit,
-	.ioctl      = ipwireless_ppp_ioctl
-};
-
-static void do_go_online(struct work_struct *work_go_online)
-{
-	struct ipw_network *network =
-		container_of(work_go_online, struct ipw_network,
-				work_go_online);
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (!network->ppp_channel) {
-		struct ppp_channel *channel;
-
-		spin_unlock_irqrestore(&network->lock, flags);
-		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
-		if (!channel) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-					": unable to allocate PPP channel\n");
-			return;
-		}
-		channel->private = network;
-		channel->mtu = 16384;	/* Wild guess */
-		channel->hdrlen = 2;
-		channel->ops = &ipwireless_ppp_channel_ops;
-
-		network->flags = 0;
-		network->rbits = 0;
-		network->mru = PPP_MRU;
-		memset(network->xaccm, 0, sizeof(network->xaccm));
-		network->xaccm[0] = ~0U;
-		network->xaccm[3] = 0x60000000U;
-		network->raccm = ~0U;
-		ppp_register_channel(channel);
-		spin_lock_irqsave(&network->lock, flags);
-		network->ppp_channel = channel;
-	}
-	spin_unlock_irqrestore(&network->lock, flags);
-}
-
-static void do_go_offline(struct work_struct *work_go_offline)
-{
-	struct ipw_network *network =
-		container_of(work_go_offline, struct ipw_network,
-				work_go_offline);
-	unsigned long flags;
-
-	mutex_lock(&network->close_lock);
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->ppp_channel != NULL) {
-		struct ppp_channel *channel = network->ppp_channel;
-
-		network->ppp_channel = NULL;
-		spin_unlock_irqrestore(&network->lock, flags);
-		mutex_unlock(&network->close_lock);
-		ppp_unregister_channel(channel);
-	} else {
-		spin_unlock_irqrestore(&network->lock, flags);
-		mutex_unlock(&network->close_lock);
-	}
-}
-
-void ipwireless_network_notify_control_line_change(struct ipw_network *network,
-						   unsigned int channel_idx,
-						   unsigned int control_lines,
-						   unsigned int changed_mask)
-{
-	int i;
-
-	if (channel_idx == IPW_CHANNEL_RAS)
-		network->ras_control_lines = control_lines;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
-		struct ipw_tty *tty =
-			network->associated_ttys[channel_idx][i];
-
-		/*
-		 * If it's associated with a tty (other than the RAS channel
-		 * when we're online), then send the data to that tty.  The RAS
-		 * channel's data is handled above - it always goes through
-		 * ppp_generic.
-		 */
-		if (tty)
-			ipwireless_tty_notify_control_line_change(tty,
-								  channel_idx,
-								  control_lines,
-								  changed_mask);
-	}
-}
-
-/*
- * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
- * bytes, which are required on sent packet, but not always present on received
- * packets
- */
-static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
-					       unsigned int length)
-{
-	struct sk_buff *skb;
-
-	if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
-		length -= 2;
-		data += 2;
-	}
-
-	skb = dev_alloc_skb(length + 4);
-	skb_reserve(skb, 2);
-	memcpy(skb_put(skb, length), data, length);
-
-	return skb;
-}
-
-void ipwireless_network_packet_received(struct ipw_network *network,
-					unsigned int channel_idx,
-					unsigned char *data,
-					unsigned int length)
-{
-	int i;
-	unsigned long flags;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
-		struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
-
-		if (!tty)
-			continue;
-
-		/*
-		 * If it's associated with a tty (other than the RAS channel
-		 * when we're online), then send the data to that tty.  The RAS
-		 * channel's data is handled above - it always goes through
-		 * ppp_generic.
-		 */
-		if (channel_idx == IPW_CHANNEL_RAS
-				&& (network->ras_control_lines &
-					IPW_CONTROL_LINE_DCD) != 0
-				&& ipwireless_tty_is_modem(tty)) {
-			/*
-			 * If data came in on the RAS channel and this tty is
-			 * the modem tty, and we are online, then we send it to
-			 * the PPP layer.
-			 */
-			mutex_lock(&network->close_lock);
-			spin_lock_irqsave(&network->lock, flags);
-			if (network->ppp_channel != NULL) {
-				struct sk_buff *skb;
-
-				spin_unlock_irqrestore(&network->lock,
-						flags);
-
-				/* Send the data to the ppp_generic module. */
-				skb = ipw_packet_received_skb(data, length);
-				ppp_input(network->ppp_channel, skb);
-			} else
-				spin_unlock_irqrestore(&network->lock,
-						flags);
-			mutex_unlock(&network->close_lock);
-		}
-		/* Otherwise we send it out the tty. */
-		else
-			ipwireless_tty_received(tty, data, length);
-	}
-}
-
-struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
-{
-	struct ipw_network *network =
-		kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
-
-	if (!network)
-		return NULL;
-
-	spin_lock_init(&network->lock);
-	mutex_init(&network->close_lock);
-
-	network->hardware = hw;
-
-	INIT_WORK(&network->work_go_online, do_go_online);
-	INIT_WORK(&network->work_go_offline, do_go_offline);
-
-	ipwireless_associate_network(hw, network);
-
-	return network;
-}
-
-void ipwireless_network_free(struct ipw_network *network)
-{
-	network->shutting_down = 1;
-
-	ipwireless_ppp_close(network);
-	flush_work_sync(&network->work_go_online);
-	flush_work_sync(&network->work_go_offline);
-
-	ipwireless_stop_interrupts(network->hardware);
-	ipwireless_associate_network(network->hardware, NULL);
-
-	kfree(network);
-}
-
-void ipwireless_associate_network_tty(struct ipw_network *network,
-				      unsigned int channel_idx,
-				      struct ipw_tty *tty)
-{
-	int i;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
-		if (network->associated_ttys[channel_idx][i] == NULL) {
-			network->associated_ttys[channel_idx][i] = tty;
-			break;
-		}
-}
-
-void ipwireless_disassociate_network_ttys(struct ipw_network *network,
-					  unsigned int channel_idx)
-{
-	int i;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
-		network->associated_ttys[channel_idx][i] = NULL;
-}
-
-void ipwireless_ppp_open(struct ipw_network *network)
-{
-	if (ipwireless_debug)
-		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
-	schedule_work(&network->work_go_online);
-}
-
-void ipwireless_ppp_close(struct ipw_network *network)
-{
-	/* Disconnect from the wireless network. */
-	if (ipwireless_debug)
-		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
-	schedule_work(&network->work_go_offline);
-}
-
-int ipwireless_ppp_channel_index(struct ipw_network *network)
-{
-	int ret = -1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->ppp_channel != NULL)
-		ret = ppp_channel_index(network->ppp_channel);
-	spin_unlock_irqrestore(&network->lock, flags);
-
-	return ret;
-}
-
-int ipwireless_ppp_unit_number(struct ipw_network *network)
-{
-	int ret = -1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->ppp_channel != NULL)
-		ret = ppp_unit_number(network->ppp_channel);
-	spin_unlock_irqrestore(&network->lock, flags);
-
-	return ret;
-}
-
-int ipwireless_ppp_mru(const struct ipw_network *network)
-{
-	return network->mru;
-}
diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h
deleted file mode 100644
index 561f765..0000000
--- a/drivers/char/pcmcia/ipwireless/network.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_NETWORK_H_
-#define _IPWIRELESS_CS_NETWORK_H_
-
-#include <linux/types.h>
-
-struct ipw_network;
-struct ipw_tty;
-struct ipw_hardware;
-
-/* Definitions of the different channels on the PCMCIA UE */
-#define IPW_CHANNEL_RAS      0
-#define IPW_CHANNEL_DIALLER  1
-#define IPW_CHANNEL_CONSOLE  2
-#define NO_OF_IPW_CHANNELS   5
-
-void ipwireless_network_notify_control_line_change(struct ipw_network *net,
-		unsigned int channel_idx, unsigned int control_lines,
-		unsigned int control_mask);
-void ipwireless_network_packet_received(struct ipw_network *net,
-		unsigned int channel_idx, unsigned char *data,
-		unsigned int length);
-struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw);
-void ipwireless_network_free(struct ipw_network *net);
-void ipwireless_associate_network_tty(struct ipw_network *net,
-		unsigned int channel_idx, struct ipw_tty *tty);
-void ipwireless_disassociate_network_ttys(struct ipw_network *net,
-		unsigned int channel_idx);
-
-void ipwireless_ppp_open(struct ipw_network *net);
-
-void ipwireless_ppp_close(struct ipw_network *net);
-int ipwireless_ppp_channel_index(struct ipw_network *net);
-int ipwireless_ppp_unit_number(struct ipw_network *net);
-int ipwireless_ppp_mru(const struct ipw_network *net);
-
-#endif
diff --git a/drivers/char/pcmcia/ipwireless/setup_protocol.h b/drivers/char/pcmcia/ipwireless/setup_protocol.h
deleted file mode 100644
index 9d6bcc7..0000000
--- a/drivers/char/pcmcia/ipwireless/setup_protocol.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_
-#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_
-
-/* Version of the setup protocol and transport protocols */
-#define TL_SETUP_VERSION		1
-
-#define TL_SETUP_VERSION_QRY_TMO	1000
-#define TL_SETUP_MAX_VERSION_QRY	30
-
-/* Message numbers 0-9 are obsoleted and must not be reused! */
-#define TL_SETUP_SIGNO_GET_VERSION_QRY	10
-#define TL_SETUP_SIGNO_GET_VERSION_RSP	11
-#define TL_SETUP_SIGNO_CONFIG_MSG	12
-#define TL_SETUP_SIGNO_CONFIG_DONE_MSG	13
-#define TL_SETUP_SIGNO_OPEN_MSG		14
-#define TL_SETUP_SIGNO_CLOSE_MSG	15
-
-#define TL_SETUP_SIGNO_INFO_MSG     20
-#define TL_SETUP_SIGNO_INFO_MSG_ACK 21
-
-#define TL_SETUP_SIGNO_REBOOT_MSG      22
-#define TL_SETUP_SIGNO_REBOOT_MSG_ACK  23
-
-/* Synchronous start-messages */
-struct tl_setup_get_version_qry {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_QRY */
-} __attribute__ ((__packed__));
-
-struct tl_setup_get_version_rsp {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_RSP */
-	unsigned char version;		/* TL_SETUP_VERSION */
-} __attribute__ ((__packed__));
-
-struct tl_setup_config_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_MSG */
-	unsigned char port_no;
-	unsigned char prio_data;
-	unsigned char prio_ctrl;
-} __attribute__ ((__packed__));
-
-struct tl_setup_config_done_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
-} __attribute__ ((__packed__));
-
-/* Asyncronous messages */
-struct tl_setup_open_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_OPEN_MSG */
-	unsigned char port_no;
-} __attribute__ ((__packed__));
-
-struct tl_setup_close_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_CLOSE_MSG */
-	unsigned char port_no;
-} __attribute__ ((__packed__));
-
-/* Driver type  - for use in tl_setup_info_msg.driver_type */
-#define COMM_DRIVER     0
-#define NDISWAN_DRIVER  1
-#define NDISWAN_DRIVER_MAJOR_VERSION  2
-#define NDISWAN_DRIVER_MINOR_VERSION  0
-
-/*
- * It should not matter when this message comes over as we just store the
- * results and send the ACK.
- */
-struct tl_setup_info_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG */
-	unsigned char driver_type;
-	unsigned char major_version;
-	unsigned char minor_version;
-} __attribute__ ((__packed__));
-
-struct tl_setup_info_msgAck {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG_ACK */
-} __attribute__ ((__packed__));
-
-struct TlSetupRebootMsgAck {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_REBOOT_MSG_ACK */
-} __attribute__ ((__packed__));
-
-/* Define a union of all the msgs that the driver can receive from the card.*/
-union ipw_setup_rx_msg {
-	unsigned char sig_no;
-	struct tl_setup_get_version_rsp version_rsp_msg;
-	struct tl_setup_open_msg open_msg;
-	struct tl_setup_close_msg close_msg;
-	struct tl_setup_info_msg InfoMsg;
-	struct tl_setup_info_msgAck info_msg_ack;
-} __attribute__ ((__packed__));
-
-#endif				/* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c
deleted file mode 100644
index f5eb28b..0000000
--- a/drivers/char/pcmcia/ipwireless/tty.c
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/ppp_defs.h>
-#include <linux/if.h>
-#include <linux/if_ppp.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/uaccess.h>
-
-#include "tty.h"
-#include "network.h"
-#include "hardware.h"
-#include "main.h"
-
-#define IPWIRELESS_PCMCIA_START 	(0)
-#define IPWIRELESS_PCMCIA_MINORS	(24)
-#define IPWIRELESS_PCMCIA_MINOR_RANGE	(8)
-
-#define TTYTYPE_MODEM    (0)
-#define TTYTYPE_MONITOR  (1)
-#define TTYTYPE_RAS_RAW  (2)
-
-struct ipw_tty {
-	int index;
-	struct ipw_hardware *hardware;
-	unsigned int channel_idx;
-	unsigned int secondary_channel_idx;
-	int tty_type;
-	struct ipw_network *network;
-	struct tty_struct *linux_tty;
-	int open_count;
-	unsigned int control_lines;
-	struct mutex ipw_tty_mutex;
-	int tx_bytes_queued;
-	int closing;
-};
-
-static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS];
-
-static struct tty_driver *ipw_tty_driver;
-
-static char *tty_type_name(int tty_type)
-{
-	static char *channel_names[] = {
-		"modem",
-		"monitor",
-		"RAS-raw"
-	};
-
-	return channel_names[tty_type];
-}
-
-static void report_registering(struct ipw_tty *tty)
-{
-	char *iftype = tty_type_name(tty->tty_type);
-
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-	       ": registering %s device ttyIPWp%d\n", iftype, tty->index);
-}
-
-static void report_deregistering(struct ipw_tty *tty)
-{
-	char *iftype = tty_type_name(tty->tty_type);
-
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-	       ": deregistering %s device ttyIPWp%d\n", iftype,
-	       tty->index);
-}
-
-static struct ipw_tty *get_tty(int minor)
-{
-	if (minor < ipw_tty_driver->minor_start
-			|| minor >= ipw_tty_driver->minor_start +
-			IPWIRELESS_PCMCIA_MINORS)
-		return NULL;
-	else {
-		int minor_offset = minor - ipw_tty_driver->minor_start;
-
-		/*
-		 * The 'ras_raw' channel is only available when 'loopback' mode
-		 * is enabled.
-		 * Number of minor starts with 16 (_RANGE * _RAS_RAW).
-		 */
-		if (!ipwireless_loopback &&
-				minor_offset >=
-				 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
-			return NULL;
-
-		return ttys[minor_offset];
-	}
-}
-
-static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
-{
-	int minor = linux_tty->index;
-	struct ipw_tty *tty = get_tty(minor);
-
-	if (!tty)
-		return -ENODEV;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-
-	if (tty->closing) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return -ENODEV;
-	}
-	if (tty->open_count == 0)
-		tty->tx_bytes_queued = 0;
-
-	tty->open_count++;
-
-	tty->linux_tty = linux_tty;
-	linux_tty->driver_data = tty;
-	linux_tty->low_latency = 1;
-
-	if (tty->tty_type == TTYTYPE_MODEM)
-		ipwireless_ppp_open(tty->network);
-
-	mutex_unlock(&tty->ipw_tty_mutex);
-
-	return 0;
-}
-
-static void do_ipw_close(struct ipw_tty *tty)
-{
-	tty->open_count--;
-
-	if (tty->open_count == 0) {
-		struct tty_struct *linux_tty = tty->linux_tty;
-
-		if (linux_tty != NULL) {
-			tty->linux_tty = NULL;
-			linux_tty->driver_data = NULL;
-
-			if (tty->tty_type == TTYTYPE_MODEM)
-				ipwireless_ppp_close(tty->network);
-		}
-	}
-}
-
-static void ipw_hangup(struct tty_struct *linux_tty)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-
-	if (!tty)
-		return;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-	if (tty->open_count == 0) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return;
-	}
-
-	do_ipw_close(tty);
-
-	mutex_unlock(&tty->ipw_tty_mutex);
-}
-
-static void ipw_close(struct tty_struct *linux_tty, struct file *filp)
-{
-	ipw_hangup(linux_tty);
-}
-
-/* Take data received from hardware, and send it out the tty */
-void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
-			unsigned int length)
-{
-	struct tty_struct *linux_tty;
-	int work = 0;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-	linux_tty = tty->linux_tty;
-	if (linux_tty == NULL) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return;
-	}
-
-	if (!tty->open_count) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return;
-	}
-	mutex_unlock(&tty->ipw_tty_mutex);
-
-	work = tty_insert_flip_string(linux_tty, data, length);
-
-	if (work != length)
-		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-				": %d chars not inserted to flip buffer!\n",
-				length - work);
-
-	/*
-	 * This may sleep if ->low_latency is set
-	 */
-	if (work)
-		tty_flip_buffer_push(linux_tty);
-}
-
-static void ipw_write_packet_sent_callback(void *callback_data,
-					   unsigned int packet_length)
-{
-	struct ipw_tty *tty = callback_data;
-
-	/*
-	 * Packet has been sent, so we subtract the number of bytes from our
-	 * tally of outstanding TX bytes.
-	 */
-	tty->tx_bytes_queued -= packet_length;
-}
-
-static int ipw_write(struct tty_struct *linux_tty,
-		     const unsigned char *buf, int count)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	int room, ret;
-
-	if (!tty)
-		return -ENODEV;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-	if (!tty->open_count) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return -EINVAL;
-	}
-
-	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
-	if (room < 0)
-		room = 0;
-	/* Don't allow caller to write any more than we have room for */
-	if (count > room)
-		count = room;
-
-	if (count == 0) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return 0;
-	}
-
-	ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
-			       buf, count,
-			       ipw_write_packet_sent_callback, tty);
-	if (ret == -1) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return 0;
-	}
-
-	tty->tx_bytes_queued += count;
-	mutex_unlock(&tty->ipw_tty_mutex);
-
-	return count;
-}
-
-static int ipw_write_room(struct tty_struct *linux_tty)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	int room;
-
-	/* FIXME: Exactly how is the tty object locked here .. */
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
-	if (room < 0)
-		room = 0;
-
-	return room;
-}
-
-static int ipwireless_get_serial_info(struct ipw_tty *tty,
-				      struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = PORT_UNKNOWN;
-	tmp.line = tty->index;
-	tmp.port = 0;
-	tmp.irq = 0;
-	tmp.flags = 0;
-	tmp.baud_base = 115200;
-	tmp.close_delay = 0;
-	tmp.closing_wait = 0;
-	tmp.custom_divisor = 0;
-	tmp.hub6 = 0;
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-
-	if (!tty)
-		return 0;
-
-	if (!tty->open_count)
-		return 0;
-
-	return tty->tx_bytes_queued;
-}
-
-static int get_control_lines(struct ipw_tty *tty)
-{
-	unsigned int my = tty->control_lines;
-	unsigned int out = 0;
-
-	if (my & IPW_CONTROL_LINE_RTS)
-		out |= TIOCM_RTS;
-	if (my & IPW_CONTROL_LINE_DTR)
-		out |= TIOCM_DTR;
-	if (my & IPW_CONTROL_LINE_CTS)
-		out |= TIOCM_CTS;
-	if (my & IPW_CONTROL_LINE_DSR)
-		out |= TIOCM_DSR;
-	if (my & IPW_CONTROL_LINE_DCD)
-		out |= TIOCM_CD;
-
-	return out;
-}
-
-static int set_control_lines(struct ipw_tty *tty, unsigned int set,
-			     unsigned int clear)
-{
-	int ret;
-
-	if (set & TIOCM_RTS) {
-		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1);
-		if (ret)
-			return ret;
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_RTS(tty->hardware,
-					  tty->secondary_channel_idx, 1);
-			if (ret)
-				return ret;
-		}
-	}
-	if (set & TIOCM_DTR) {
-		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1);
-		if (ret)
-			return ret;
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_DTR(tty->hardware,
-					  tty->secondary_channel_idx, 1);
-			if (ret)
-				return ret;
-		}
-	}
-	if (clear & TIOCM_RTS) {
-		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0);
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_RTS(tty->hardware,
-					  tty->secondary_channel_idx, 0);
-			if (ret)
-				return ret;
-		}
-	}
-	if (clear & TIOCM_DTR) {
-		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0);
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_DTR(tty->hardware,
-					  tty->secondary_channel_idx, 0);
-			if (ret)
-				return ret;
-		}
-	}
-	return 0;
-}
-
-static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	/* FIXME: Exactly how is the tty object locked here .. */
-
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	return get_control_lines(tty);
-}
-
-static int
-ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
-	     unsigned int set, unsigned int clear)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	/* FIXME: Exactly how is the tty object locked here .. */
-
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	return set_control_lines(tty, set, clear);
-}
-
-static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
-		     unsigned int cmd, unsigned long arg)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	/* FIXME: Exactly how is the tty object locked here .. */
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		return ipwireless_get_serial_info(tty, (void __user *) arg);
-
-	case TIOCSSERIAL:
-		return 0;	/* Keeps the PCMCIA scripts happy. */
-	}
-
-	if (tty->tty_type == TTYTYPE_MODEM) {
-		switch (cmd) {
-		case PPPIOCGCHAN:
-			{
-				int chan = ipwireless_ppp_channel_index(
-							tty->network);
-
-				if (chan < 0)
-					return -ENODEV;
-				if (put_user(chan, (int __user *) arg))
-					return -EFAULT;
-			}
-			return 0;
-
-		case PPPIOCGUNIT:
-			{
-				int unit = ipwireless_ppp_unit_number(
-						tty->network);
-
-				if (unit < 0)
-					return -ENODEV;
-				if (put_user(unit, (int __user *) arg))
-					return -EFAULT;
-			}
-			return 0;
-
-		case FIONREAD:
-			{
-				int val = 0;
-
-				if (put_user(val, (int __user *) arg))
-					return -EFAULT;
-			}
-			return 0;
-		case TCFLSH:
-			return tty_perform_flush(linux_tty, arg);
-		}
-	}
-	return tty_mode_ioctl(linux_tty, file, cmd , arg);
-}
-
-static int add_tty(int j,
-		    struct ipw_hardware *hardware,
-		    struct ipw_network *network, int channel_idx,
-		    int secondary_channel_idx, int tty_type)
-{
-	ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL);
-	if (!ttys[j])
-		return -ENOMEM;
-	ttys[j]->index = j;
-	ttys[j]->hardware = hardware;
-	ttys[j]->channel_idx = channel_idx;
-	ttys[j]->secondary_channel_idx = secondary_channel_idx;
-	ttys[j]->network = network;
-	ttys[j]->tty_type = tty_type;
-	mutex_init(&ttys[j]->ipw_tty_mutex);
-
-	tty_register_device(ipw_tty_driver, j, NULL);
-	ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
-
-	if (secondary_channel_idx != -1)
-		ipwireless_associate_network_tty(network,
-						 secondary_channel_idx,
-						 ttys[j]);
-	if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j])
-		report_registering(ttys[j]);
-	return 0;
-}
-
-struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware,
-				      struct ipw_network *network)
-{
-	int i, j;
-
-	for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) {
-		int allfree = 1;
-
-		for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
-				j += IPWIRELESS_PCMCIA_MINOR_RANGE)
-			if (ttys[j] != NULL) {
-				allfree = 0;
-				break;
-			}
-
-		if (allfree) {
-			j = i;
-
-			if (add_tty(j, hardware, network,
-					IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
-					TTYTYPE_MODEM))
-				return NULL;
-
-			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
-			if (add_tty(j, hardware, network,
-					IPW_CHANNEL_DIALLER, -1,
-					TTYTYPE_MONITOR))
-				return NULL;
-
-			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
-			if (add_tty(j, hardware, network,
-					IPW_CHANNEL_RAS, -1,
-					TTYTYPE_RAS_RAW))
-				return NULL;
-
-			return ttys[i];
-		}
-	}
-	return NULL;
-}
-
-/*
- * Must be called before ipwireless_network_free().
- */
-void ipwireless_tty_free(struct ipw_tty *tty)
-{
-	int j;
-	struct ipw_network *network = ttys[tty->index]->network;
-
-	for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS;
-			j += IPWIRELESS_PCMCIA_MINOR_RANGE) {
-		struct ipw_tty *ttyj = ttys[j];
-
-		if (ttyj) {
-			mutex_lock(&ttyj->ipw_tty_mutex);
-			if (get_tty(j + ipw_tty_driver->minor_start) == ttyj)
-				report_deregistering(ttyj);
-			ttyj->closing = 1;
-			if (ttyj->linux_tty != NULL) {
-				mutex_unlock(&ttyj->ipw_tty_mutex);
-				tty_hangup(ttyj->linux_tty);
-				/* Wait till the tty_hangup has completed */
-				flush_work_sync(&ttyj->linux_tty->hangup_work);
-				/* FIXME: Exactly how is the tty object locked here
-				   against a parallel ioctl etc */
-				mutex_lock(&ttyj->ipw_tty_mutex);
-			}
-			while (ttyj->open_count)
-				do_ipw_close(ttyj);
-			ipwireless_disassociate_network_ttys(network,
-							     ttyj->channel_idx);
-			tty_unregister_device(ipw_tty_driver, j);
-			ttys[j] = NULL;
-			mutex_unlock(&ttyj->ipw_tty_mutex);
-			kfree(ttyj);
-		}
-	}
-}
-
-static const struct tty_operations tty_ops = {
-	.open = ipw_open,
-	.close = ipw_close,
-	.hangup = ipw_hangup,
-	.write = ipw_write,
-	.write_room = ipw_write_room,
-	.ioctl = ipw_ioctl,
-	.chars_in_buffer = ipw_chars_in_buffer,
-	.tiocmget = ipw_tiocmget,
-	.tiocmset = ipw_tiocmset,
-};
-
-int ipwireless_tty_init(void)
-{
-	int result;
-
-	ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
-	if (!ipw_tty_driver)
-		return -ENOMEM;
-
-	ipw_tty_driver->owner = THIS_MODULE;
-	ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
-	ipw_tty_driver->name = "ttyIPWp";
-	ipw_tty_driver->major = 0;
-	ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
-	ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	ipw_tty_driver->init_termios = tty_std_termios;
-	ipw_tty_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	ipw_tty_driver->init_termios.c_ispeed = 9600;
-	ipw_tty_driver->init_termios.c_ospeed = 9600;
-	tty_set_operations(ipw_tty_driver, &tty_ops);
-	result = tty_register_driver(ipw_tty_driver);
-	if (result) {
-		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-		       ": failed to register tty driver\n");
-		put_tty_driver(ipw_tty_driver);
-		return result;
-	}
-
-	return 0;
-}
-
-void ipwireless_tty_release(void)
-{
-	int ret;
-
-	ret = tty_unregister_driver(ipw_tty_driver);
-	put_tty_driver(ipw_tty_driver);
-	if (ret != 0)
-		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-			": tty_unregister_driver failed with code %d\n", ret);
-}
-
-int ipwireless_tty_is_modem(struct ipw_tty *tty)
-{
-	return tty->tty_type == TTYTYPE_MODEM;
-}
-
-void
-ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
-					  unsigned int channel_idx,
-					  unsigned int control_lines,
-					  unsigned int changed_mask)
-{
-	unsigned int old_control_lines = tty->control_lines;
-
-	tty->control_lines = (tty->control_lines & ~changed_mask)
-		| (control_lines & changed_mask);
-
-	/*
-	 * If DCD is de-asserted, we close the tty so pppd can tell that we
-	 * have gone offline.
-	 */
-	if ((old_control_lines & IPW_CONTROL_LINE_DCD)
-			&& !(tty->control_lines & IPW_CONTROL_LINE_DCD)
-			&& tty->linux_tty) {
-		tty_hangup(tty->linux_tty);
-	}
-}
-
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h
deleted file mode 100644
index 747b2d6..0000000
--- a/drivers/char/pcmcia/ipwireless/tty.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_TTY_H_
-#define _IPWIRELESS_CS_TTY_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-struct ipw_tty;
-struct ipw_network;
-struct ipw_hardware;
-
-int ipwireless_tty_init(void);
-void ipwireless_tty_release(void);
-
-struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw,
-				      struct ipw_network *net);
-void ipwireless_tty_free(struct ipw_tty *tty);
-void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
-			     unsigned int length);
-int ipwireless_tty_is_modem(struct ipw_tty *tty);
-void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
-					       unsigned int channel_idx,
-					       unsigned int control_lines,
-					       unsigned int changed_mask);
-
-#endif
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index eaa4199..beca80b 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -418,9 +418,9 @@ static void bh_status(MGSLPC_INFO *info);
 /*
  * ioctl handlers
  */
-static int tiocmget(struct tty_struct *tty, struct file *file);
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear);
+static int tiocmget(struct tty_struct *tty);
+static int tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear);
 static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount);
 static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params);
 static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty);
@@ -2114,7 +2114,7 @@ static int modem_input_wait(MGSLPC_INFO *info,int arg)
 
 /* return the state of the serial control and status signals
  */
-static int tiocmget(struct tty_struct *tty, struct file *file)
+static int tiocmget(struct tty_struct *tty)
 {
 	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
 	unsigned int result;
@@ -2139,7 +2139,7 @@ static int tiocmget(struct tty_struct *tty, struct file *file)
 
 /* set modem control signals (DTR/RTS)
  */
-static int tiocmset(struct tty_struct *tty, struct file *file,
+static int tiocmset(struct tty_struct *tty,
 		    unsigned int set, unsigned int clear)
 {
 	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
@@ -2222,13 +2222,12 @@ static int mgslpc_get_icount(struct tty_struct *tty,
  * Arguments:
  *
  * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
  * 	cmd	IOCTL command code
  * 	arg	command argument/context
  *
  * Return Value:	0 if success, otherwise error code
  */
-static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
+static int mgslpc_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 72a4fcb..5e29e80 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -128,6 +128,7 @@
  * 	void add_input_randomness(unsigned int type, unsigned int code,
  *                                unsigned int value);
  * 	void add_interrupt_randomness(int irq);
+ * 	void add_disk_randomness(struct gendisk *disk);
  *
  * add_input_randomness() uses the input layer interrupt timing, as well as
  * the event type information from the hardware.
@@ -136,9 +137,15 @@
  * inputs to the entropy pool.  Note that not all interrupts are good
  * sources of randomness!  For example, the timer interrupts is not a
  * good choice, because the periodicity of the interrupts is too
- * regular, and hence predictable to an attacker.  Disk interrupts are
- * a better measure, since the timing of the disk interrupts are more
- * unpredictable.
+ * regular, and hence predictable to an attacker.  Network Interface
+ * Controller interrupts are a better measure, since the timing of the
+ * NIC interrupts are more unpredictable.
+ *
+ * add_disk_randomness() uses what amounts to the seek time of block
+ * layer request events, on a per-disk_devt basis, as input to the
+ * entropy pool. Note that high-speed solid state drives with very low
+ * seek times do not make for good sources of entropy, as their seek
+ * times are usually fairly consistent.
  *
  * All of these routines try to estimate how many bits of randomness a
  * particular randomness source.  They do this by keeping track of the
diff --git a/drivers/char/rio/Makefile b/drivers/char/rio/Makefile
deleted file mode 100644
index 1661875..0000000
--- a/drivers/char/rio/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for the linux rio-subsystem.
-#
-# (C) R.E.Wolff@BitWizard.nl 
-# 
-# This file is GPL. See other files for the full Blurb. I'm lazy today. 
-#
-
-obj-$(CONFIG_RIO) += rio.o
-
-rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
-            rioparam.o rioroute.o riotable.o riotty.o
diff --git a/drivers/char/rio/board.h b/drivers/char/rio/board.h
deleted file mode 100644
index bdea633..0000000
--- a/drivers/char/rio/board.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources. 
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: board.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:07
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)board.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_board_h__
-#define	__rio_board_h__
-
-/*
-** board.h contains the definitions for the *hardware* of the host cards.
-** It describes the memory overlay for the dual port RAM area.
-*/
-
-#define	DP_SRAM1_SIZE	0x7C00
-#define	DP_SRAM2_SIZE	0x0200
-#define	DP_SRAM3_SIZE	0x7000
-#define	DP_SCRATCH_SIZE	0x1000
-#define	DP_PARMMAP_ADDR	0x01FE	/* offset into SRAM2 */
-#define	DP_STARTUP_ADDR	0x01F8	/* offset into SRAM2 */
-
-/*
-**	The shape of the Host Control area, at offset 0x7C00, Write Only
-*/
-struct s_Ctrl {
-	u8 DpCtl;		/* 7C00 */
-	u8 Dp_Unused2_[127];
-	u8 DpIntSet;		/* 7C80 */
-	u8 Dp_Unused3_[127];
-	u8 DpTpuReset;	/* 7D00 */
-	u8 Dp_Unused4_[127];
-	u8 DpIntReset;	/* 7D80 */
-	u8 Dp_Unused5_[127];
-};
-
-/*
-** The PROM data area on the host (0x7C00), Read Only
-*/
-struct s_Prom {
-	u16 DpSlxCode[2];
-	u16 DpRev;
-	u16 Dp_Unused6_;
-	u16 DpUniq[4];
-	u16 DpJahre;
-	u16 DpWoche;
-	u16 DpHwFeature[5];
-	u16 DpOemId;
-	u16 DpSiggy[16];
-};
-
-/*
-** Union of the Ctrl and Prom areas
-*/
-union u_CtrlProm {		/* This is the control/PROM area (0x7C00) */
-	struct s_Ctrl DpCtrl;
-	struct s_Prom DpProm;
-};
-
-/*
-** The top end of memory!
-*/
-struct s_ParmMapS {		/* Area containing Parm Map Pointer */
-	u8 Dp_Unused8_[DP_PARMMAP_ADDR];
-	u16 DpParmMapAd;
-};
-
-struct s_StartUpS {
-	u8 Dp_Unused9_[DP_STARTUP_ADDR];
-	u8 Dp_LongJump[0x4];
-	u8 Dp_Unused10_[2];
-	u8 Dp_ShortJump[0x2];
-};
-
-union u_Sram2ParmMap {		/* This is the top of memory (0x7E00-0x7FFF) */
-	u8 DpSramMem[DP_SRAM2_SIZE];
-	struct s_ParmMapS DpParmMapS;
-	struct s_StartUpS DpStartUpS;
-};
-
-/*
-**	This is the DP RAM overlay.
-*/
-struct DpRam {
-	u8 DpSram1[DP_SRAM1_SIZE];	/* 0000 - 7BFF */
-	union u_CtrlProm DpCtrlProm;	/* 7C00 - 7DFF */
-	union u_Sram2ParmMap DpSram2ParmMap;	/* 7E00 - 7FFF */
-	u8 DpScratch[DP_SCRATCH_SIZE];	/* 8000 - 8FFF */
-	u8 DpSram3[DP_SRAM3_SIZE];	/* 9000 - FFFF */
-};
-
-#define	DpControl	DpCtrlProm.DpCtrl.DpCtl
-#define	DpSetInt	DpCtrlProm.DpCtrl.DpIntSet
-#define	DpResetTpu	DpCtrlProm.DpCtrl.DpTpuReset
-#define	DpResetInt	DpCtrlProm.DpCtrl.DpIntReset
-
-#define	DpSlx		DpCtrlProm.DpProm.DpSlxCode
-#define	DpRevision	DpCtrlProm.DpProm.DpRev
-#define	DpUnique	DpCtrlProm.DpProm.DpUniq
-#define	DpYear		DpCtrlProm.DpProm.DpJahre
-#define	DpWeek		DpCtrlProm.DpProm.DpWoche
-#define	DpSignature	DpCtrlProm.DpProm.DpSiggy
-
-#define	DpParmMapR	DpSram2ParmMap.DpParmMapS.DpParmMapAd
-#define	DpSram2		DpSram2ParmMap.DpSramMem
-
-#endif
diff --git a/drivers/char/rio/cirrus.h b/drivers/char/rio/cirrus.h
deleted file mode 100644
index 5ab5167..0000000
--- a/drivers/char/rio/cirrus.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******		CIRRUS.H				      *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Jeremy Rolls
- Date    : 3 Aug 1990
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _cirrus_h
-#define _cirrus_h 1
-
-/* Bit fields for particular registers shared with driver */
-
-/* COR1 - driver and RTA */
-#define RIOC_COR1_ODD		0x80	/* Odd parity */
-#define RIOC_COR1_EVEN		0x00	/* Even parity */
-#define RIOC_COR1_NOP		0x00	/* No parity */
-#define RIOC_COR1_FORCE		0x20	/* Force parity */
-#define RIOC_COR1_NORMAL	0x40	/* With parity */
-#define RIOC_COR1_1STOP		0x00	/* 1 stop bit */
-#define RIOC_COR1_15STOP	0x04	/* 1.5 stop bits */
-#define RIOC_COR1_2STOP		0x08	/* 2 stop bits */
-#define RIOC_COR1_5BITS		0x00	/* 5 data bits */
-#define RIOC_COR1_6BITS		0x01	/* 6 data bits */
-#define RIOC_COR1_7BITS		0x02	/* 7 data bits */
-#define RIOC_COR1_8BITS		0x03	/* 8 data bits */
-
-#define RIOC_COR1_HOST		0xef	/* Safe host bits */
-
-/* RTA only */
-#define RIOC_COR1_CINPCK	0x00	/* Check parity of received characters */
-#define RIOC_COR1_CNINPCK	0x10	/* Don't check parity */
-
-/* COR2 bits for both RTA and driver use */
-#define RIOC_COR2_IXANY		0x80	/* IXANY - any character is XON */
-#define RIOC_COR2_IXON		0x40	/* IXON - enable tx soft flowcontrol */
-#define RIOC_COR2_RTSFLOW	0x02	/* Enable tx hardware flow control */
-
-/* Additional driver bits */
-#define RIOC_COR2_HUPCL		0x20	/* Hang up on close */
-#define RIOC_COR2_CTSFLOW	0x04	/* Enable rx hardware flow control */
-#define RIOC_COR2_IXOFF		0x01	/* Enable rx software flow control */
-#define RIOC_COR2_DTRFLOW	0x08	/* Enable tx hardware flow control */
-
-/* RTA use only */
-#define RIOC_COR2_ETC		0x20	/* Embedded transmit options */
-#define RIOC_COR2_LOCAL		0x10	/* Local loopback mode */
-#define RIOC_COR2_REMOTE	0x08	/* Remote loopback mode */
-#define RIOC_COR2_HOST		0xc2	/* Safe host bits */
-
-/* COR3 - RTA use only */
-#define RIOC_COR3_SCDRNG	0x80	/* Enable special char detect for range */
-#define RIOC_COR3_SCD34		0x40	/* Special character detect for SCHR's 3 + 4 */
-#define RIOC_COR3_FCT		0x20	/* Flow control transparency */
-#define RIOC_COR3_SCD12		0x10	/* Special character detect for SCHR's 1 + 2 */
-#define RIOC_COR3_FIFO12	0x0c	/* 12 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO10	0x0a	/* 10 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO8		0x08	/* 8 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO6		0x06	/* 6 chars for receive FIFO threshold */
-
-#define RIOC_COR3_THRESHOLD	RIOC_COR3_FIFO8	/* MUST BE LESS THAN MCOR_THRESHOLD */
-
-#define RIOC_COR3_DEFAULT	(RIOC_COR3_FCT | RIOC_COR3_THRESHOLD)
-				/* Default bits for COR3 */
-
-/* COR4 driver and RTA use */
-#define RIOC_COR4_IGNCR		0x80	/* Throw away CR's on input */
-#define RIOC_COR4_ICRNL		0x40	/* Map CR -> NL on input */
-#define RIOC_COR4_INLCR		0x20	/* Map NL -> CR on input */
-#define RIOC_COR4_IGNBRK	0x10	/* Ignore Break */
-#define RIOC_COR4_NBRKINT	0x08	/* No interrupt on break (-BRKINT) */
-#define RIOC_COR4_RAISEMOD	0x01	/* Raise modem output lines on non-zero baud */
-
-
-/* COR4 driver only */
-#define RIOC_COR4_IGNPAR	0x04	/* IGNPAR (ignore characters with errors) */
-#define RIOC_COR4_PARMRK	0x02	/* PARMRK */
-
-#define RIOC_COR4_HOST		0xf8	/* Safe host bits */
-
-/* COR4 RTA only */
-#define RIOC_COR4_CIGNPAR	0x02	/* Thrown away bad characters */
-#define RIOC_COR4_CPARMRK	0x04	/* PARMRK characters */
-#define RIOC_COR4_CNPARMRK	0x03	/* Don't PARMRK */
-
-/* COR5 driver and RTA use */
-#define RIOC_COR5_ISTRIP	0x80	/* Strip input chars to 7 bits */
-#define RIOC_COR5_LNE		0x40	/* Enable LNEXT processing */
-#define RIOC_COR5_CMOE		0x20	/* Match good and errored characters */
-#define RIOC_COR5_ONLCR		0x02	/* NL -> CR NL on output */
-#define RIOC_COR5_OCRNL		0x01	/* CR -> NL on output */
-
-/*
-** Spare bits - these are not used in the CIRRUS registers, so we use
-** them to set various other features.
-*/
-/*
-** tstop and tbusy indication
-*/
-#define RIOC_COR5_TSTATE_ON	0x08	/* Turn on monitoring of tbusy and tstop */
-#define RIOC_COR5_TSTATE_OFF	0x04	/* Turn off monitoring of tbusy and tstop */
-/*
-** TAB3
-*/
-#define RIOC_COR5_TAB3		0x10	/* TAB3 mode */
-
-#define RIOC_COR5_HOST		0xc3	/* Safe host bits */
-
-/* CCSR */
-#define RIOC_CCSR_TXFLOFF	0x04	/* Tx is xoffed */
-
-/* MSVR1 */
-/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
-   RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
-   serial option.
-*/
-#define RIOC_MSVR1_CD		0x80	/* CD (DSR on Cirrus) */
-#define RIOC_MSVR1_RTS		0x40	/* RTS (CTS on Cirrus) */
-#define RIOC_MSVR1_RI		0x20	/* RI */
-#define RIOC_MSVR1_DTR		0x10	/* DTR (CD on Cirrus) */
-#define RIOC_MSVR1_CTS		0x01	/* CTS output pin (RTS on Cirrus) */
-/* Next two used to indicate state of tbusy and tstop to driver */
-#define RIOC_MSVR1_TSTOP	0x08	/* Set if port flow controlled */
-#define RIOC_MSVR1_TEMPTY	0x04	/* Set if port tx buffer empty */
-
-#define RIOC_MSVR1_HOST		0xf3	/* The bits the host wants */
-
-/* Defines for the subscripts of a CONFIG packet */
-#define RIOC_CONFIG_COR1	1	/* Option register 1 */
-#define RIOC_CONFIG_COR2	2	/* Option register 2 */
-#define RIOC_CONFIG_COR4	3	/* Option register 4 */
-#define RIOC_CONFIG_COR5	4	/* Option register 5 */
-#define RIOC_CONFIG_TXXON	5	/* Tx XON character */
-#define RIOC_CONFIG_TXXOFF	6	/* Tx XOFF character */
-#define RIOC_CONFIG_RXXON	7	/* Rx XON character */
-#define RIOC_CONFIG_RXXOFF	8	/* Rx XOFF character */
-#define RIOC_CONFIG_LNEXT	9	/* LNEXT character */
-#define RIOC_CONFIG_TXBAUD	10	/* Tx baud rate */
-#define RIOC_CONFIG_RXBAUD	11	/* Rx baud rate */
-
-#define RIOC_PRE_EMPTIVE	0x80	/* Pre-emptive bit in command field */
-
-/* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
-   CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
-   be used 
-*/
-#define RIOC_OPEN		0x00	/* Open a port */
-#define RIOC_CONFIG		0x01	/* Configure a port */
-#define RIOC_MOPEN		0x02	/* Modem open (block for DCD) */
-#define RIOC_CLOSE		0x03	/* Close a port */
-#define RIOC_WFLUSH		(0x04 | RIOC_PRE_EMPTIVE)	/* Write flush */
-#define RIOC_RFLUSH		(0x05 | RIOC_PRE_EMPTIVE)	/* Read flush */
-#define RIOC_RESUME		(0x06 | RIOC_PRE_EMPTIVE)	/* Resume if xoffed */
-#define RIOC_SBREAK		0x07	/* Start break */
-#define RIOC_EBREAK		0x08	/* End break */
-#define RIOC_SUSPEND		(0x09 | RIOC_PRE_EMPTIVE)	/* Susp op (behave as tho xoffed) */
-#define RIOC_FCLOSE		(0x0a | RIOC_PRE_EMPTIVE)	/* Force close */
-#define RIOC_XPRINT		0x0b	/* Xprint packet */
-#define RIOC_MBIS		(0x0c | RIOC_PRE_EMPTIVE)	/* Set modem lines */
-#define RIOC_MBIC		(0x0d | RIOC_PRE_EMPTIVE)	/* Clear modem lines */
-#define RIOC_MSET		(0x0e | RIOC_PRE_EMPTIVE)	/* Set modem lines */
-#define RIOC_PCLOSE		0x0f	/* Pseudo close - Leaves rx/tx enabled */
-#define RIOC_MGET		(0x10 | RIOC_PRE_EMPTIVE)	/* Force update of modem status */
-#define RIOC_MEMDUMP		(0x11 | RIOC_PRE_EMPTIVE)	/* Send back mem from addr supplied */
-#define RIOC_READ_REGISTER	(0x12 | RIOC_PRE_EMPTIVE)	/* Read CD1400 register (debug) */
-
-/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
-   use data[4] / data[3] to indicate current state and modem status respectively
-*/
-
-#define RIOC_COMPLETE		(0x20 | RIOC_PRE_EMPTIVE)
-				/* Command complete */
-#define RIOC_BREAK_RECEIVED	(0x21 | RIOC_PRE_EMPTIVE)
-				/* Break received */
-#define RIOC_MODEM_STATUS	(0x22 | RIOC_PRE_EMPTIVE)
-				/* Change in modem status */
-
-/* "Command" packet that could go either way - handshake wake-up */
-#define RIOC_HANDSHAKE		(0x23 | RIOC_PRE_EMPTIVE)
-				/* Wake-up to HOST / RTA */
-
-#endif
diff --git a/drivers/char/rio/cmdblk.h b/drivers/char/rio/cmdblk.h
deleted file mode 100644
index 9ed4f86..0000000
--- a/drivers/char/rio/cmdblk.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: cmdblk.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)cmdblk.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_cmdblk_h__
-#define __rio_cmdblk_h__
-
-/*
-** the structure of a command block, used to queue commands destined for
-** a rup.
-*/
-
-struct CmdBlk {
-	struct CmdBlk *NextP;	/* Pointer to next command block */
-	struct PKT Packet;	/* A packet, to copy to the rup */
-	/* The func to call to check if OK */
-	int (*PreFuncP) (unsigned long, struct CmdBlk *);
-	int PreArg;		/* The arg for the func */
-	/* The func to call when completed */
-	int (*PostFuncP) (unsigned long, struct CmdBlk *);
-	int PostArg;		/* The arg for the func */
-};
-
-#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
-#endif
diff --git a/drivers/char/rio/cmdpkt.h b/drivers/char/rio/cmdpkt.h
deleted file mode 100644
index c1e7a27..0000000
--- a/drivers/char/rio/cmdpkt.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: cmdpkt.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)cmdpkt.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-#ifndef __rio_cmdpkt_h__
-#define __rio_cmdpkt_h__
-
-/*
-** overlays for the data area of a packet. Used in both directions
-** (to build a packet to send, and to interpret a packet that arrives)
-** and is very inconvenient for MIPS, so they appear as two separate
-** structures - those used for modifying/reading packets on the card
-** and those for modifying/reading packets in real memory, which have an _M
-** suffix.
-*/
-
-#define	RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2)
-
-/*
-** The boot information packet looks like this:
-** This structure overlays a PktCmd->CmdData structure, and so starts
-** at Data[2] in the actual pkt!
-*/
-struct BootSequence {
-	u16 NumPackets;
-	u16 LoadBase;
-	u16 CodeSize;
-};
-
-#define	BOOT_SEQUENCE_LEN	8
-
-struct SamTop {
-	u8 Unit;
-	u8 Link;
-};
-
-struct CmdHdr {
-	u8 PcCommand;
-	union {
-		u8 PcPhbNum;
-		u8 PcLinkNum;
-		u8 PcIDNum;
-	} U0;
-};
-
-
-struct PktCmd {
-	union {
-		struct {
-			struct CmdHdr CmdHdr;
-			struct BootSequence PcBootSequence;
-		} S1;
-		struct {
-			u16 PcSequence;
-			u8 PcBootData[RTA_BOOT_DATA_SIZE];
-		} S2;
-		struct {
-			u16 __crud__;
-			u8 PcUniqNum[4];	/* this is really a uint. */
-			u8 PcModuleTypes;	/* what modules are fitted */
-		} S3;
-		struct {
-			struct CmdHdr CmdHdr;
-			u8 __undefined__;
-			u8 PcModemStatus;
-			u8 PcPortStatus;
-			u8 PcSubCommand;	/* commands like mem or register dump */
-			u16 PcSubAddr;	/* Address for command */
-			u8 PcSubData[64];	/* Date area for command */
-		} S4;
-		struct {
-			struct CmdHdr CmdHdr;
-			u8 PcCommandText[1];
-			u8 __crud__[20];
-			u8 PcIDNum2;	/* It had to go somewhere! */
-		} S5;
-		struct {
-			struct CmdHdr CmdHdr;
-			struct SamTop Topology[LINKS_PER_UNIT];
-		} S6;
-	} U1;
-};
-
-struct PktCmd_M {
-	union {
-		struct {
-			struct {
-				u8 PcCommand;
-				union {
-					u8 PcPhbNum;
-					u8 PcLinkNum;
-					u8 PcIDNum;
-				} U0;
-			} CmdHdr;
-			struct {
-				u16 NumPackets;
-				u16 LoadBase;
-				u16 CodeSize;
-			} PcBootSequence;
-		} S1;
-		struct {
-			u16 PcSequence;
-			u8 PcBootData[RTA_BOOT_DATA_SIZE];
-		} S2;
-		struct {
-			u16 __crud__;
-			u8 PcUniqNum[4];	/* this is really a uint. */
-			u8 PcModuleTypes;	/* what modules are fitted */
-		} S3;
-		struct {
-			u16 __cmd_hdr__;
-			u8 __undefined__;
-			u8 PcModemStatus;
-			u8 PcPortStatus;
-			u8 PcSubCommand;
-			u16 PcSubAddr;
-			u8 PcSubData[64];
-		} S4;
-		struct {
-			u16 __cmd_hdr__;
-			u8 PcCommandText[1];
-			u8 __crud__[20];
-			u8 PcIDNum2;	/* Tacked on end */
-		} S5;
-		struct {
-			u16 __cmd_hdr__;
-			struct Top Topology[LINKS_PER_UNIT];
-		} S6;
-	} U1;
-};
-
-#define Command		U1.S1.CmdHdr.PcCommand
-#define PhbNum		U1.S1.CmdHdr.U0.PcPhbNum
-#define IDNum		U1.S1.CmdHdr.U0.PcIDNum
-#define IDNum2		U1.S5.PcIDNum2
-#define LinkNum		U1.S1.CmdHdr.U0.PcLinkNum
-#define Sequence	U1.S2.PcSequence
-#define BootData	U1.S2.PcBootData
-#define BootSequence	U1.S1.PcBootSequence
-#define UniqNum		U1.S3.PcUniqNum
-#define ModemStatus	U1.S4.PcModemStatus
-#define PortStatus	U1.S4.PcPortStatus
-#define SubCommand	U1.S4.PcSubCommand
-#define SubAddr		U1.S4.PcSubAddr
-#define SubData		U1.S4.PcSubData
-#define CommandText	U1.S5.PcCommandText
-#define RouteTopology	U1.S6.Topology
-#define ModuleTypes	U1.S3.PcModuleTypes
-
-#endif
diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h
deleted file mode 100644
index 4af9032..0000000
--- a/drivers/char/rio/daemon.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: daemon.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)daemon.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_daemon_h__
-#define	__rio_daemon_h__
-
-
-/*
-** structures used on /dev/rio
-*/
-
-struct Error {
-	unsigned int Error;
-	unsigned int Entry;
-	unsigned int Other;
-};
-
-struct DownLoad {
-	char __user *DataP;
-	unsigned int Count;
-	unsigned int ProductCode;
-};
-
-/*
-** A few constants....
-*/
-#ifndef MAX_VERSION_LEN
-#define	MAX_VERSION_LEN	256
-#endif
-
-#ifndef MAX_XP_CTRL_LEN
-#define	MAX_XP_CTRL_LEN 16	/* ALSO IN PORT.H */
-#endif
-
-struct PortSetup {
-	unsigned int From;		/* Set/Clear XP & IXANY Control from this port.... */
-	unsigned int To;		/* .... to this port */
-	unsigned int XpCps;		/* at this speed */
-	char XpOn[MAX_XP_CTRL_LEN];	/* this is the start string */
-	char XpOff[MAX_XP_CTRL_LEN];	/* this is the stop string */
-	u8 IxAny;			/* enable/disable IXANY */
-	u8 IxOn;			/* enable/disable IXON */
-	u8 Lock;			/* lock port params */
-	u8 Store;			/* store params across closes */
-	u8 Drain;			/* close only when drained */
-};
-
-struct LpbReq {
-	unsigned int Host;
-	unsigned int Link;
-	struct LPB __user *LpbP;
-};
-
-struct RupReq {
-	unsigned int HostNum;
-	unsigned int RupNum;
-	struct RUP __user *RupP;
-};
-
-struct PortReq {
-	unsigned int SysPort;
-	struct Port __user *PortP;
-};
-
-struct StreamInfo {
-	unsigned int SysPort;
-	int RQueue;
-	int WQueue;
-};
-
-struct HostReq {
-	unsigned int HostNum;
-	struct Host __user *HostP;
-};
-
-struct HostDpRam {
-	unsigned int HostNum;
-	struct DpRam __user *DpRamP;
-};
-
-struct DebugCtrl {
-	unsigned int SysPort;
-	unsigned int Debug;
-	unsigned int Wait;
-};
-
-struct MapInfo {
-	unsigned int FirstPort;		/* 8 ports, starting from this (tty) number */
-	unsigned int RtaUnique;		/* reside on this RTA (unique number) */
-};
-
-struct MapIn {
-	unsigned int NumEntries;	/* How many port sets are we mapping? */
-	struct MapInfo *MapInfoP;	/* Pointer to (user space) info */
-};
-
-struct SendPack {
-	unsigned int PortNum;
-	unsigned char Len;
-	unsigned char Data[PKT_MAX_DATA_LEN];
-};
-
-struct SpecialRupCmd {
-	struct PKT Packet;
-	unsigned short Host;
-	unsigned short RupNum;
-};
-
-struct IdentifyRta {
-	unsigned long RtaUnique;
-	u8 ID;
-};
-
-struct KillNeighbour {
-	unsigned long UniqueNum;
-	u8 Link;
-};
-
-struct rioVersion {
-	char version[MAX_VERSION_LEN];
-	char relid[MAX_VERSION_LEN];
-	int buildLevel;
-	char buildDate[MAX_VERSION_LEN];
-};
-
-
-/*
-**	RIOC commands are for the daemon type operations
-**
-** 09.12.1998 ARG - ESIL 0776 part fix
-** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a
-** #ifndef here first.
-** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now
-** allowed to be used by customers.
-*/
-#ifndef RIOC
-#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
-#endif
-
-/*
-** Boot stuff
-*/
-#define	RIO_GET_TABLE     (RIOC | 100)
-#define RIO_PUT_TABLE     (RIOC | 101)
-#define RIO_ASSIGN_RTA    (RIOC | 102)
-#define RIO_DELETE_RTA    (RIOC | 103)
-#define	RIO_HOST_FOAD	  (RIOC | 104)
-#define	RIO_QUICK_CHECK	  (RIOC | 105)
-#define RIO_SIGNALS_ON    (RIOC | 106)
-#define RIO_SIGNALS_OFF   (RIOC | 107)
-#define	RIO_CHANGE_NAME   (RIOC | 108)
-#define RIO_DOWNLOAD      (RIOC | 109)
-#define	RIO_GET_LOG	  (RIOC | 110)
-#define	RIO_SETUP_PORTS   (RIOC | 111)
-#define RIO_ALL_MODEM     (RIOC | 112)
-
-/*
-** card state, debug stuff
-*/
-#define	RIO_NUM_HOSTS	  (RIOC | 120)
-#define	RIO_HOST_LPB	  (RIOC | 121)
-#define	RIO_HOST_RUP	  (RIOC | 122)
-#define	RIO_HOST_PORT	  (RIOC | 123)
-#define	RIO_PARMS 	  (RIOC | 124)
-#define RIO_HOST_REQ	  (RIOC | 125)
-#define	RIO_READ_CONFIG	  (RIOC | 126)
-#define	RIO_SET_CONFIG	  (RIOC | 127)
-#define	RIO_VERSID	  (RIOC | 128)
-#define	RIO_FLAGS	  (RIOC | 129)
-#define	RIO_SETDEBUG	  (RIOC | 130)
-#define	RIO_GETDEBUG	  (RIOC | 131)
-#define	RIO_READ_LEVELS   (RIOC | 132)
-#define	RIO_SET_FAST_BUS  (RIOC | 133)
-#define	RIO_SET_SLOW_BUS  (RIOC | 134)
-#define	RIO_SET_BYTE_MODE (RIOC | 135)
-#define	RIO_SET_WORD_MODE (RIOC | 136)
-#define RIO_STREAM_INFO   (RIOC | 137)
-#define	RIO_START_POLLER  (RIOC | 138)
-#define	RIO_STOP_POLLER   (RIOC | 139)
-#define	RIO_LAST_ERROR    (RIOC | 140)
-#define	RIO_TICK	  (RIOC | 141)
-#define	RIO_TOCK	  (RIOC | 241)	/* I did this on purpose, you know. */
-#define	RIO_SEND_PACKET   (RIOC | 142)
-#define	RIO_SET_BUSY	  (RIOC | 143)
-#define	SPECIAL_RUP_CMD   (RIOC | 144)
-#define	RIO_FOAD_RTA      (RIOC | 145)
-#define	RIO_ZOMBIE_RTA    (RIOC | 146)
-#define RIO_IDENTIFY_RTA  (RIOC | 147)
-#define RIO_KILL_NEIGHBOUR (RIOC | 148)
-#define RIO_DEBUG_MEM     (RIOC | 149)
-/*
-** 150 - 167 used.....   See below
-*/
-#define RIO_GET_PORT_SETUP (RIOC | 168)
-#define RIO_RESUME        (RIOC | 169)
-#define	RIO_MESG	(RIOC | 170)
-#define	RIO_NO_MESG	(RIOC | 171)
-#define	RIO_WHAT_MESG	(RIOC | 172)
-#define RIO_HOST_DPRAM	(RIOC | 173)
-#define RIO_MAP_B50_TO_50	(RIOC | 174)
-#define RIO_MAP_B50_TO_57600	(RIOC | 175)
-#define RIO_MAP_B110_TO_110	(RIOC | 176)
-#define RIO_MAP_B110_TO_115200	(RIOC | 177)
-#define RIO_GET_PORT_PARAMS	(RIOC | 178)
-#define RIO_SET_PORT_PARAMS	(RIOC | 179)
-#define RIO_GET_PORT_TTY	(RIOC | 180)
-#define RIO_SET_PORT_TTY	(RIOC | 181)
-#define RIO_SYSLOG_ONLY	(RIOC | 182)
-#define RIO_SYSLOG_CONS	(RIOC | 183)
-#define RIO_CONS_ONLY	(RIOC | 184)
-#define RIO_BLOCK_OPENS	(RIOC | 185)
-
-/*
-** 02.03.1999 ARG - ESIL 0820 fix :
-** RIOBootMode is no longer use by the driver, so these ioctls
-** are now obsolete :
-**
-#define RIO_GET_BOOT_MODE	(RIOC | 186)
-#define RIO_SET_BOOT_MODE	(RIOC | 187)
-**
-*/
-
-#define RIO_MEM_DUMP	(RIOC | 189)
-#define RIO_READ_REGISTER	(RIOC | 190)
-#define RIO_GET_MODTYPE	(RIOC | 191)
-#define RIO_SET_TIMER	(RIOC | 192)
-#define RIO_READ_CHECK	(RIOC | 196)
-#define RIO_WAITING_FOR_RESTART	(RIOC | 197)
-#define RIO_BIND_RTA	(RIOC | 198)
-#define RIO_GET_BINDINGS	(RIOC | 199)
-#define RIO_PUT_BINDINGS	(RIOC | 200)
-
-#define	RIO_MAKE_DEV		(RIOC | 201)
-#define	RIO_MINOR		(RIOC | 202)
-
-#define	RIO_IDENTIFY_DRIVER	(RIOC | 203)
-#define	RIO_DISPLAY_HOST_CFG	(RIOC | 204)
-
-
-/*
-** MAKE_DEV / MINOR stuff
-*/
-#define	RIO_DEV_DIRECT		0x0000
-#define	RIO_DEV_MODEM		0x0200
-#define	RIO_DEV_XPRINT		0x0400
-#define	RIO_DEV_MASK		0x0600
-
-/*
-** port management, xprint stuff
-*/
-#define	rIOCN(N)	(RIOC|(N))
-#define	rIOCR(N,T)	(RIOC|(N))
-#define	rIOCW(N,T)	(RIOC|(N))
-
-#define	RIO_GET_XP_ON     rIOCR(150,char[16])	/* start xprint string */
-#define	RIO_SET_XP_ON     rIOCW(151,char[16])
-#define	RIO_GET_XP_OFF    rIOCR(152,char[16])	/* finish xprint string */
-#define	RIO_SET_XP_OFF    rIOCW(153,char[16])
-#define	RIO_GET_XP_CPS    rIOCR(154,int)	/* xprint CPS */
-#define	RIO_SET_XP_CPS    rIOCW(155,int)
-#define RIO_GET_IXANY     rIOCR(156,int)	/* ixany allowed? */
-#define RIO_SET_IXANY     rIOCW(157,int)
-#define RIO_SET_IXANY_ON  rIOCN(158)	/* allow ixany */
-#define RIO_SET_IXANY_OFF rIOCN(159)	/* disallow ixany */
-#define RIO_GET_MODEM     rIOCR(160,int)	/* port is modem/direct line? */
-#define RIO_SET_MODEM     rIOCW(161,int)
-#define RIO_SET_MODEM_ON  rIOCN(162)	/* port is a modem */
-#define RIO_SET_MODEM_OFF rIOCN(163)	/* port is direct */
-#define RIO_GET_IXON      rIOCR(164,int)	/* ixon allowed? */
-#define RIO_SET_IXON      rIOCW(165,int)
-#define RIO_SET_IXON_ON   rIOCN(166)	/* allow ixon */
-#define RIO_SET_IXON_OFF  rIOCN(167)	/* disallow ixon */
-
-#define RIO_GET_SIVIEW	  ((('s')<<8) | 106)	/* backwards compatible with SI */
-
-#define	RIO_IOCTL_UNKNOWN	-2
-
-#endif
diff --git a/drivers/char/rio/errors.h b/drivers/char/rio/errors.h
deleted file mode 100644
index bdb0523..0000000
--- a/drivers/char/rio/errors.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: errors.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)errors.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_errors_h__
-#define	__rio_errors_h__
-
-/*
-** error codes
-*/
-
-#define	NOTHING_WRONG_AT_ALL		0
-#define	BAD_CHARACTER_IN_NAME		1
-#define	TABLE_ENTRY_ISNT_PROPERLY_NULL	2
-#define	UNKNOWN_HOST_NUMBER		3
-#define	ZERO_RTA_ID			4
-#define	BAD_RTA_ID			5
-#define	DUPLICATED_RTA_ID		6
-#define	DUPLICATE_UNIQUE_NUMBER		7
-#define	BAD_TTY_NUMBER			8
-#define	TTY_NUMBER_IN_USE		9
-#define	NAME_USED_TWICE			10
-#define	HOST_ID_NOT_ZERO		11
-#define	BOOT_IN_PROGRESS		12
-#define	COPYIN_FAILED			13
-#define	HOST_FILE_TOO_LARGE		14
-#define	COPYOUT_FAILED			15
-#define	NOT_SUPER_USER			16
-#define	RIO_ALREADY_POLLING		17
-
-#define	ID_NUMBER_OUT_OF_RANGE		18
-#define PORT_NUMBER_OUT_OF_RANGE	19
-#define	HOST_NUMBER_OUT_OF_RANGE	20
-#define	RUP_NUMBER_OUT_OF_RANGE		21
-#define	TTY_NUMBER_OUT_OF_RANGE		22
-#define	LINK_NUMBER_OUT_OF_RANGE	23
-
-#define	HOST_NOT_RUNNING		24
-#define	IOCTL_COMMAND_UNKNOWN		25
-#define	RIO_SYSTEM_HALTED		26
-#define	WAIT_FOR_DRAIN_BROKEN		27
-#define	PORT_NOT_MAPPED_INTO_SYSTEM	28
-#define	EXCLUSIVE_USE_SET		29
-#define	WAIT_FOR_NOT_CLOSING_BROKEN	30
-#define	WAIT_FOR_PORT_TO_OPEN_BROKEN	31
-#define	WAIT_FOR_CARRIER_BROKEN		32
-#define	WAIT_FOR_NOT_IN_USE_BROKEN	33
-#define	WAIT_FOR_CAN_ADD_COMMAND_BROKEN	34
-#define	WAIT_FOR_ADD_COMMAND_BROKEN	35
-#define	WAIT_FOR_NOT_PARAM_BROKEN	36
-#define	WAIT_FOR_RETRY_BROKEN		37
-#define	HOST_HAS_ALREADY_BEEN_BOOTED	38
-#define	UNIT_IS_IN_USE			39
-#define	COULDNT_FIND_ENTRY		40
-#define	RTA_UNIQUE_NUMBER_ZERO		41
-#define	CLOSE_COMMAND_FAILED		42
-#define	WAIT_FOR_CLOSE_BROKEN		43
-#define	CPS_VALUE_OUT_OF_RANGE		44
-#define	ID_ALREADY_IN_USE		45
-#define	SIGNALS_ALREADY_SET		46
-#define	NOT_RECEIVING_PROCESS		47
-#define	RTA_NUMBER_WRONG		48
-#define NO_SUCH_PRODUCT			49
-#define	HOST_SYSPORT_BAD		50
-#define	ID_NOT_TENTATIVE		51
-#define XPRINT_CPS_OUT_OF_RANGE		52
-#define	NOT_ENOUGH_CORE_FOR_PCI_COPY	53
-
-
-#endif				/* __rio_errors_h__ */
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
deleted file mode 100644
index 078d44f..0000000
--- a/drivers/char/rio/func.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: func.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)func.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __func_h_def
-#define __func_h_def
-
-#include <linux/kdev_t.h>
-
-/* rioboot.c */
-int RIOBootCodeRTA(struct rio_info *, struct DownLoad *);
-int RIOBootCodeHOST(struct rio_info *, struct DownLoad *);
-int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
-void msec_timeout(struct Host *);
-int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
-int RIOBootOk(struct rio_info *, struct Host *, unsigned long);
-int RIORtaBound(struct rio_info *, unsigned int);
-void rio_fill_host_slot(int, int, unsigned int, struct Host *);
-
-/* riocmd.c */
-int RIOFoadRta(struct Host *, struct Map *);
-int RIOZombieRta(struct Host *, struct Map *);
-int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *));
-int RIOIdentifyRta(struct rio_info *, void __user *);
-int RIOKillNeighbour(struct rio_info *, void __user *);
-int RIOSuspendBootRta(struct Host *, int, int);
-int RIOFoadWakeup(struct rio_info *);
-struct CmdBlk *RIOGetCmdBlk(void);
-void RIOFreeCmdBlk(struct CmdBlk *);
-int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *);
-void RIOPollHostCommands(struct rio_info *, struct Host *);
-int RIOWFlushMark(unsigned long, struct CmdBlk *);
-int RIORFlushEnable(unsigned long, struct CmdBlk *);
-int RIOUnUse(unsigned long, struct CmdBlk *);
-
-/* rioctrl.c */
-int riocontrol(struct rio_info *, dev_t, int, unsigned long, int);
-
-int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char);
-
-/* rioinit.c */
-void rioinit(struct rio_info *, struct RioHostInfo *);
-void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
-void RIOISAinit(struct rio_info *, int);
-int RIODoAT(struct rio_info *, int, int);
-caddr_t RIOCheckForATCard(int);
-int RIOAssignAT(struct rio_info *, int, void __iomem *, int);
-int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int);
-void RIOAllocDataStructs(struct rio_info *);
-void RIOSetupDataStructs(struct rio_info *);
-int RIODefaultName(struct rio_info *, struct Host *, unsigned int);
-struct rioVersion *RIOVersid(void);
-void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int);
-
-/* riointr.c */
-void RIOTxEnable(char *);
-void RIOServiceHost(struct rio_info *, struct Host *);
-int riotproc(struct rio_info *, struct ttystatics *, int, int);
-
-/* rioparam.c */
-int RIOParam(struct Port *, int, int, int);
-int RIODelay(struct Port *PortP, int);
-int RIODelay_ni(struct Port *PortP, int);
-void ms_timeout(struct Port *);
-int can_add_transmit(struct PKT __iomem **, struct Port *);
-void add_transmit(struct Port *);
-void put_free_end(struct Host *, struct PKT __iomem *);
-int can_remove_receive(struct PKT __iomem **, struct Port *);
-void remove_receive(struct Port *);
-
-/* rioroute.c */
-int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
-void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int);
-unsigned int GetUnitType(unsigned int);
-int RIOSetChange(struct rio_info *);
-int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *);
-
-
-/* riotty.c */
-
-int riotopen(struct tty_struct *tty, struct file *filp);
-int riotclose(void *ptr);
-int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t);
-void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
-
-/* riotable.c */
-int RIONewTable(struct rio_info *);
-int RIOApel(struct rio_info *);
-int RIODeleteRta(struct rio_info *, struct Map *);
-int RIOAssignRta(struct rio_info *, struct Map *);
-int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
-int RIOChangeName(struct rio_info *, struct Map *);
-
-#if 0
-/* riodrvr.c */
-struct rio_info *rio_install(struct RioHostInfo *);
-int rio_uninstall(struct rio_info *);
-int rio_open(struct rio_info *, int, struct file *);
-int rio_close(struct rio_info *, struct file *);
-int rio_read(struct rio_info *, struct file *, char *, int);
-int rio_write(struct rio_info *, struct file *f, char *, int);
-int rio_ioctl(struct rio_info *, struct file *, int, char *);
-int rio_select(struct rio_info *, struct file *f, int, struct sel *);
-int rio_intr(char *);
-int rio_isr_thread(char *);
-struct rio_info *rio_info_store(int cmd, struct rio_info *p);
-#endif
-
-extern void rio_copy_to_card(void *from, void __iomem *to, int len);
-extern int rio_minor(struct tty_struct *tty);
-extern int rio_ismodem(struct tty_struct *tty);
-
-extern void rio_start_card_running(struct Host *HostP);
-
-#endif				/* __func_h_def */
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
deleted file mode 100644
index 78f2454..0000000
--- a/drivers/char/rio/host.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: host.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)host.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_host_h__
-#define __rio_host_h__
-
-/*
-** the host structure - one per host card in the system.
-*/
-
-#define	MAX_EXTRA_UNITS	64
-
-/*
-**    Host data structure. This is used for the software equiv. of
-**    the host.
-*/
-struct Host {
-	struct pci_dev *pdev;
-	unsigned char Type;		/* RIO_EISA, RIO_MCA, ... */
-	unsigned char Ivec;		/* POLLED or ivec number */
-	unsigned char Mode;		/* Control stuff */
-	unsigned char Slot;		/* Slot */
-	void  __iomem *Caddr;		/* KV address of DPRAM */
-	struct DpRam __iomem *CardP;	/* KV address of DPRAM, with overlay */
-	unsigned long PaddrP;		/* Phys. address of DPRAM */
-	char Name[MAX_NAME_LEN];	/* The name of the host */
-	unsigned int UniqueNum;		/* host unique number */
-	spinlock_t HostLock;	/* Lock structure for MPX */
-	unsigned int WorkToBeDone;	/* set to true each interrupt */
-	unsigned int InIntr;		/* Being serviced? */
-	unsigned int IntSrvDone;	/* host's interrupt has been serviced */
-	void (*Copy) (void *, void __iomem *, int);	/* copy func */
-	struct timer_list timer;
-	/*
-	 **               I M P O R T A N T !
-	 **
-	 ** The rest of this data structure is cleared to zero after
-	 ** a RIO_HOST_FOAD command.
-	 */
-
-	unsigned long Flags;			/* Whats going down */
-#define RC_WAITING            0
-#define RC_STARTUP            1
-#define RC_RUNNING            2
-#define RC_STUFFED            3
-#define RC_READY              7
-#define RUN_STATE             7
-/*
-** Boot mode applies to the way in which hosts in this system will
-** boot RTAs
-*/
-#define RC_BOOT_ALL           0x8		/* Boot all RTAs attached */
-#define RC_BOOT_OWN           0x10		/* Only boot RTAs bound to this system */
-#define RC_BOOT_NONE          0x20		/* Don't boot any RTAs (slave mode) */
-
-	struct Top Topology[LINKS_PER_UNIT];	/* one per link */
-	struct Map Mapping[MAX_RUP];		/* Mappings for host */
-	struct PHB __iomem *PhbP;		/* Pointer to the PHB array */
-	unsigned short __iomem *PhbNumP;	/* Ptr to Number of PHB's */
-	struct LPB __iomem *LinkStrP;		/* Link Structure Array */
-	struct RUP __iomem *RupP;		/* Sixteen real rups here */
-	struct PARM_MAP __iomem *ParmMapP;	/* points to the parmmap */
-	unsigned int ExtraUnits[MAX_EXTRA_UNITS];	/* unknown things */
-	unsigned int NumExtraBooted;		/* how many of the above */
-	/*
-	 ** Twenty logical rups.
-	 ** The first sixteen are the real Rup entries (above), the last four
-	 ** are the link RUPs.
-	 */
-	struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT];
-	int timeout_id;				/* For calling 100 ms delays */
-	int timeout_sem;			/* For calling 100 ms delays */
-	unsigned long locks;			/* long req'd for set_bit --RR */
-	char ____end_marker____;
-};
-#define Control      CardP->DpControl
-#define SetInt       CardP->DpSetInt
-#define ResetTpu     CardP->DpResetTpu
-#define ResetInt     CardP->DpResetInt
-#define Signature    CardP->DpSignature
-#define Sram1        CardP->DpSram1
-#define Sram2        CardP->DpSram2
-#define Sram3        CardP->DpSram3
-#define Scratch      CardP->DpScratch
-#define __ParmMapR   CardP->DpParmMapR
-#define SLX          CardP->DpSlx
-#define Revision     CardP->DpRevision
-#define Unique       CardP->DpUnique
-#define Year         CardP->DpYear
-#define Week         CardP->DpWeek
-
-#define RIO_DUMBPARM 0x0860	/* what not to expect */
-
-#endif
diff --git a/drivers/char/rio/link.h b/drivers/char/rio/link.h
deleted file mode 100644
index f3bf11a0..0000000
--- a/drivers/char/rio/link.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                      L I N K
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _link_h
-#define _link_h 1
-
-/*************************************************
- * Define the Link Status stuff
- ************************************************/
-/* Boot request stuff */
-#define BOOT_REQUEST       ((ushort) 0)	/* Request for a boot */
-#define BOOT_ABORT         ((ushort) 1)	/* Abort a boot */
-#define BOOT_SEQUENCE      ((ushort) 2)	/* Packet with the number of packets
-					   and load address */
-#define BOOT_COMPLETED     ((ushort) 3)	/* Boot completed */
-
-
-struct LPB {
-	u16 link_number;	/* Link Number */
-	u16 in_ch;	/* Link In Channel */
-	u16 out_ch;	/* Link Out Channel */
-	u8 attached_serial[4];  /* Attached serial number */
-	u8 attached_host_serial[4];
-	/* Serial number of Host who
-	   booted the other end */
-	u16 descheduled;	/* Currently Descheduled */
-	u16 state;		/* Current state */
-	u16 send_poll;		/* Send a Poll Packet */
-	u16 ltt_p;	/* Process Descriptor */
-	u16 lrt_p;	/* Process Descriptor */
-	u16 lrt_status;		/* Current lrt status */
-	u16 ltt_status;		/* Current ltt status */
-	u16 timeout;		/* Timeout value */
-	u16 topology;		/* Topology bits */
-	u16 mon_ltt;
-	u16 mon_lrt;
-	u16 WaitNoBoot;	/* Secs to hold off booting */
-	u16 add_packet_list;	/* Add packets to here */
-	u16 remove_packet_list;	/* Send packets from here */
-
-	u16 lrt_fail_chan;	/* Lrt's failure channel */
-	u16 ltt_fail_chan;	/* Ltt's failure channel */
-
-	/* RUP structure for HOST to driver communications */
-	struct RUP rup;
-	struct RUP link_rup;	/* RUP for the link (POLL,
-				   topology etc.) */
-	u16 attached_link;	/* Number of attached link */
-	u16 csum_errors;	/* csum errors */
-	u16 num_disconnects;	/* number of disconnects */
-	u16 num_sync_rcvd;	/* # sync's received */
-	u16 num_sync_rqst;	/* # sync requests */
-	u16 num_tx;		/* Num pkts sent */
-	u16 num_rx;		/* Num pkts received */
-	u16 module_attached;	/* Module tpyes of attached */
-	u16 led_timeout;	/* LED timeout */
-	u16 first_port;		/* First port to service */
-	u16 last_port;		/* Last port to service */
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/linux_compat.h b/drivers/char/rio/linux_compat.h
deleted file mode 100644
index 34c0d28..0000000
--- a/drivers/char/rio/linux_compat.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * (C) 2000 R.E.Wolff@BitWizard.nl
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/interrupt.h>
-
-
-#define DEBUG_ALL
-
-struct ttystatics {
-	struct termios tm;
-};
-
-extern int rio_debug;
-
-#define RIO_DEBUG_INIT         0x000001
-#define RIO_DEBUG_BOOT         0x000002
-#define RIO_DEBUG_CMD          0x000004
-#define RIO_DEBUG_CTRL         0x000008
-#define RIO_DEBUG_INTR         0x000010
-#define RIO_DEBUG_PARAM        0x000020
-#define RIO_DEBUG_ROUTE        0x000040
-#define RIO_DEBUG_TABLE        0x000080
-#define RIO_DEBUG_TTY          0x000100
-#define RIO_DEBUG_FLOW         0x000200
-#define RIO_DEBUG_MODEMSIGNALS 0x000400
-#define RIO_DEBUG_PROBE        0x000800
-#define RIO_DEBUG_CLEANUP      0x001000
-#define RIO_DEBUG_IFLOW        0x002000
-#define RIO_DEBUG_PFE          0x004000
-#define RIO_DEBUG_REC          0x008000
-#define RIO_DEBUG_SPINLOCK     0x010000
-#define RIO_DEBUG_DELAY        0x020000
-#define RIO_DEBUG_MOD_COUNT    0x040000
-
-
-/* Copied over from riowinif.h . This is ugly. The winif file declares
-also much other stuff which is incompatible with the headers from
-the older driver. The older driver includes "brates.h" which shadows
-the definitions from Linux, and is incompatible... */
-
-/* RxBaud and TxBaud definitions... */
-#define	RIO_B0			0x00	/* RTS / DTR signals dropped */
-#define	RIO_B50			0x01	/* 50 baud */
-#define	RIO_B75			0x02	/* 75 baud */
-#define	RIO_B110		0x03	/* 110 baud */
-#define	RIO_B134		0x04	/* 134.5 baud */
-#define	RIO_B150		0x05	/* 150 baud */
-#define	RIO_B200		0x06	/* 200 baud */
-#define	RIO_B300		0x07	/* 300 baud */
-#define	RIO_B600		0x08	/* 600 baud */
-#define	RIO_B1200		0x09	/* 1200 baud */
-#define	RIO_B1800		0x0A	/* 1800 baud */
-#define	RIO_B2400		0x0B	/* 2400 baud */
-#define	RIO_B4800		0x0C	/* 4800 baud */
-#define	RIO_B9600		0x0D	/* 9600 baud */
-#define	RIO_B19200		0x0E	/* 19200 baud */
-#define	RIO_B38400		0x0F	/* 38400 baud */
-#define	RIO_B56000		0x10	/* 56000 baud */
-#define	RIO_B57600		0x11	/* 57600 baud */
-#define	RIO_B64000		0x12	/* 64000 baud */
-#define	RIO_B115200		0x13	/* 115200 baud */
-#define	RIO_B2000		0x14	/* 2000 baud */
diff --git a/drivers/char/rio/map.h b/drivers/char/rio/map.h
deleted file mode 100644
index 8366978..0000000
--- a/drivers/char/rio/map.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: map.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:11
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)map.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_map_h__
-#define __rio_map_h__
-
-/*
-** mapping structure passed to and from the config.rio program to
-** determine the current topology of the world
-*/
-
-#define MAX_MAP_ENTRY 17
-#define	TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
-#define	MAX_NAME_LEN 32
-
-struct Map {
-	unsigned int HostUniqueNum;	/* Supporting hosts unique number */
-	unsigned int RtaUniqueNum;	/* Unique number */
-	/*
-	 ** The next two IDs must be swapped on big-endian architectures
-	 ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
-	 ** upgrading for example).
-	 */
-	unsigned short ID;		/* ID used in the subnet */
-	unsigned short ID2;		/* ID of 2nd block of 8 for 16 port */
-	unsigned long Flags;		/* Booted, ID Given, Disconnected */
-	unsigned long SysPort;		/* First tty mapped to this port */
-	struct Top Topology[LINKS_PER_UNIT];	/* ID connected to each link */
-	char Name[MAX_NAME_LEN];	/* Cute name by which RTA is known */
-};
-
-/*
-** Flag values:
-*/
-#define	RTA_BOOTED		0x00000001
-#define RTA_NEWBOOT		0x00000010
-#define	MSG_DONE		0x00000020
-#define	RTA_INTERCONNECT	0x00000040
-#define	RTA16_SECOND_SLOT	0x00000080
-#define	BEEN_HERE		0x00000100
-#define SLOT_TENTATIVE		0x40000000
-#define SLOT_IN_USE		0x80000000
-
-/*
-** HostUniqueNum is the unique number from the host card that this RTA
-** is to be connected to.
-** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO
-** if the slot in the table is unused. If it is the same as the HostUniqueNum
-** then this slot represents a host card.
-** Flags contains current boot/route state info
-** SysPort is a value in the range 0-504, being the number of the first tty
-** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8.
-** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor
-** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256,
-** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511
-** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an
-** unused slot/unknown ID etc.
-** The Topology array contains the ID of the unit connected to each of the
-** four links on this unit. The entry will be 0xFFFF if NOTHING is connected
-** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link.
-** The Name field is a null-terminated string, upto 31 characters, containing
-** the 'cute' name that the sysadmin/users know the RTA by. It is permissible
-** for this string to contain any character in the range \040 to \176 inclusive.
-** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The
-** special character '%' IS allowable, and needs no special action.
-**
-*/
-
-#endif
diff --git a/drivers/char/rio/param.h b/drivers/char/rio/param.h
deleted file mode 100644
index 7e9b628..0000000
--- a/drivers/char/rio/param.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: param.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)param.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_param_h__
-#define __rio_param_h__
-
-/*
-** the param command block, as used in OPEN and PARAM calls.
-*/
-
-struct phb_param {
-	u8 Cmd;			/* It is very important that these line up */
-	u8 Cor1;		/* with what is expected at the other end. */
-	u8 Cor2;		/* to confirm that you've got it right,    */
-	u8 Cor4;		/* check with cirrus/cirrus.h              */
-	u8 Cor5;
-	u8 TxXon;		/* Transmit X-On character */
-	u8 TxXoff;		/* Transmit X-Off character */
-	u8 RxXon;		/* Receive X-On character */
-	u8 RxXoff;		/* Receive X-Off character */
-	u8 LNext;		/* Literal-next character */
-	u8 TxBaud;		/* Transmit baudrate */
-	u8 RxBaud;		/* Receive baudrate */
-};
-
-#endif
diff --git a/drivers/char/rio/parmmap.h b/drivers/char/rio/parmmap.h
deleted file mode 100644
index acc8fa4..0000000
--- a/drivers/char/rio/parmmap.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******               H O S T   M E M O R Y  M A P
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-6/4/1991   jonb		     Made changes to accommodate Mips R3230 bus
- ***************************************************************************/
-
-#ifndef _parmap_h
-#define _parmap_h
-
-typedef struct PARM_MAP PARM_MAP;
-
-struct PARM_MAP {
-	u16 phb_ptr;	/* Pointer to the PHB array */
-	u16 phb_num_ptr;	/* Ptr to Number of PHB's */
-	u16 free_list;	/* Free List pointer */
-	u16 free_list_end;	/* Free List End pointer */
-	u16 q_free_list_ptr;	/* Ptr to Q_BUF variable */
-	u16 unit_id_ptr;	/* Unit Id */
-	u16 link_str_ptr;	/* Link Structure Array */
-	u16 bootloader_1;	/* 1st Stage Boot Loader */
-	u16 bootloader_2;	/* 2nd Stage Boot Loader */
-	u16 port_route_map_ptr;	/* Port Route Map */
-	u16 route_ptr;		/* Unit Route Map */
-	u16 map_present;	/* Route Map present */
-	s16 pkt_num;		/* Total number of packets */
-	s16 q_num;		/* Total number of Q packets */
-	u16 buffers_per_port;	/* Number of buffers per port */
-	u16 heap_size;		/* Initial size of heap */
-	u16 heap_left;		/* Current Heap left */
-	u16 error;		/* Error code */
-	u16 tx_max;		/* Max number of tx pkts per phb */
-	u16 rx_max;		/* Max number of rx pkts per phb */
-	u16 rx_limit;		/* For high / low watermarks */
-	s16 links;		/* Links to use */
-	s16 timer;		/* Interrupts per second */
-	u16 rups;		/* Pointer to the RUPs */
-	u16 max_phb;		/* Mostly for debugging */
-	u16 living;		/* Just increments!! */
-	u16 init_done;		/* Initialisation over */
-	u16 booting_link;
-	u16 idle_count;		/* Idle time counter */
-	u16 busy_count;		/* Busy counter */
-	u16 idle_control;	/* Control Idle Process */
-	u16 tx_intr;		/* TX interrupt pending */
-	u16 rx_intr;		/* RX interrupt pending */
-	u16 rup_intr;		/* RUP interrupt pending */
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/pci.h b/drivers/char/rio/pci.h
deleted file mode 100644
index 6032f91..0000000
--- a/drivers/char/rio/pci.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: pci.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)pci.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_pci_h__
-#define	__rio_pci_h__
-
-/*
-** PCI stuff
-*/
-
-#define	PCITpFastClock		0x80
-#define	PCITpSlowClock		0x00
-#define	PCITpFastLinks	        0x40
-#define	PCITpSlowLinks	        0x00
-#define	PCITpIntEnable		0x04
-#define	PCITpIntDisable		0x00
-#define	PCITpBusEnable		0x02
-#define	PCITpBusDisable		0x00
-#define	PCITpBootFromRam	0x01
-#define	PCITpBootFromLink	0x00
-
-#define	RIO_PCI_VENDOR		0x11CB
-#define	RIO_PCI_DEVICE		0x8000
-#define	RIO_PCI_BASE_CLASS	0x02
-#define	RIO_PCI_SUB_CLASS	0x80
-#define	RIO_PCI_PROG_IFACE	0x00
-
-#define RIO_PCI_RID		0x0008
-#define RIO_PCI_BADR0		0x0010
-#define RIO_PCI_INTLN		0x003C
-#define RIO_PCI_INTPIN		0x003D
-
-#define	RIO_PCI_MEM_SIZE	65536
-
-#define	RIO_PCI_TURBO_TP	0x80
-#define	RIO_PCI_FAST_LINKS	0x40
-#define	RIO_PCI_INT_ENABLE	0x04
-#define	RIO_PCI_TP_BUS_ENABLE	0x02
-#define	RIO_PCI_BOOT_FROM_RAM	0x01
-
-#define	RIO_PCI_DEFAULT_MODE	0x05
-
-#endif				/* __rio_pci_h__ */
diff --git a/drivers/char/rio/phb.h b/drivers/char/rio/phb.h
deleted file mode 100644
index a4c48ae..0000000
--- a/drivers/char/rio/phb.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                 P H B     H E A D E R                        *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra, Jeremy Rolls
- Date    : 
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _phb_h
-#define _phb_h 1
-
-/*************************************************
- * Handshake asserted. Deasserted by the LTT(s)
- ************************************************/
-#define PHB_HANDSHAKE_SET      ((ushort) 0x001)	/* Set by LRT */
-
-#define PHB_HANDSHAKE_RESET     ((ushort) 0x002)	/* Set by ISR / driver */
-
-#define PHB_HANDSHAKE_FLAGS     (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
-						/* Reset by ltt */
-
-
-/*************************************************
- * Maximum number of PHB's
- ************************************************/
-#define MAX_PHB               ((ushort) 128)	/* range 0-127 */
-
-/*************************************************
- * Defines for the mode fields
- ************************************************/
-#define TXPKT_INCOMPLETE        0x0001	/* Previous tx packet not completed */
-#define TXINTR_ENABLED          0x0002	/* Tx interrupt is enabled */
-#define TX_TAB3                 0x0004	/* TAB3 mode */
-#define TX_OCRNL                0x0008	/* OCRNL mode */
-#define TX_ONLCR                0x0010	/* ONLCR mode */
-#define TX_SENDSPACES           0x0020	/* Send n spaces command needs
-					   completing */
-#define TX_SENDNULL             0x0040	/* Escaping NULL needs completing */
-#define TX_SENDLF               0x0080	/* LF -> CR LF needs completing */
-#define TX_PARALLELBUG          0x0100	/* CD1400 LF -> CR LF bug on parallel
-					   port */
-#define TX_HANGOVER             (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
-#define TX_DTRFLOW		0x0200	/* DTR tx flow control */
-#define	TX_DTRFLOWED		0x0400	/* DTR is low - don't allow more data
-					   into the FIFO */
-#define	TX_DATAINFIFO		0x0800	/* There is data in the FIFO */
-#define	TX_BUSY			0x1000	/* Data in FIFO, shift or holding regs */
-
-#define RX_SPARE	        0x0001	/* SPARE */
-#define RXINTR_ENABLED          0x0002	/* Rx interrupt enabled */
-#define RX_ICRNL                0x0008	/* ICRNL mode */
-#define RX_INLCR                0x0010	/* INLCR mode */
-#define RX_IGNCR                0x0020	/* IGNCR mode */
-#define RX_CTSFLOW              0x0040	/* CTSFLOW enabled */
-#define RX_IXOFF                0x0080	/* IXOFF enabled */
-#define RX_CTSFLOWED            0x0100	/* CTSFLOW and CTS dropped */
-#define RX_IXOFFED              0x0200	/* IXOFF and xoff sent */
-#define RX_BUFFERED		0x0400	/* Try and pass on complete packets */
-
-#define PORT_ISOPEN             0x0001	/* Port open? */
-#define PORT_HUPCL              0x0002	/* Hangup on close? */
-#define PORT_MOPENPEND          0x0004	/* Modem open pending */
-#define PORT_ISPARALLEL         0x0008	/* Parallel port */
-#define PORT_BREAK              0x0010	/* Port on break */
-#define PORT_STATUSPEND		0x0020	/* Status packet pending */
-#define PORT_BREAKPEND          0x0040	/* Break packet pending */
-#define PORT_MODEMPEND          0x0080	/* Modem status packet pending */
-#define PORT_PARALLELBUG        0x0100	/* CD1400 LF -> CR LF bug on parallel
-					   port */
-#define PORT_FULLMODEM          0x0200	/* Full modem signals */
-#define PORT_RJ45               0x0400	/* RJ45 connector - no RI signal */
-#define PORT_RESTRICTED         0x0600	/* Restricted connector - no RI / DTR */
-
-#define PORT_MODEMBITS          0x0600	/* Mask for modem fields */
-
-#define PORT_WCLOSE             0x0800	/* Waiting for close */
-#define	PORT_HANDSHAKEFIX	0x1000	/* Port has H/W flow control fix */
-#define	PORT_WASPCLOSED		0x2000	/* Port closed with PCLOSE */
-#define	DUMPMODE		0x4000	/* Dump RTA mem */
-#define	READ_REG		0x8000	/* Read CD1400 register */
-
-
-
-/**************************************************************************
- * PHB Structure
- * A  few words.
- *
- * Normally Packets are added to the end of the list and removed from
- * the start. The pointer tx_add points to a SPACE to put a Packet.
- * The pointer tx_remove points to the next Packet to remove
- *************************************************************************/
-
-struct PHB {
-	u8 source;
-	u8 handshake;
-	u8 status;
-	u16 timeout;		/* Maximum of 1.9 seconds */
-	u8 link;		/* Send down this link */
-	u8 destination;
-	u16 tx_start;
-	u16 tx_end;
-	u16 tx_add;
-	u16 tx_remove;
-
-	u16 rx_start;
-	u16 rx_end;
-	u16 rx_add;
-	u16 rx_remove;
-
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/pkt.h b/drivers/char/rio/pkt.h
deleted file mode 100644
index a945816..0000000
--- a/drivers/char/rio/pkt.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******            P A C K E T   H E A D E R   F I L E
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _pkt_h
-#define _pkt_h 1
-
-#define PKT_CMD_BIT     ((ushort) 0x080)
-#define PKT_CMD_DATA    ((ushort) 0x080)
-
-#define PKT_ACK         ((ushort) 0x040)
-
-#define PKT_TGL         ((ushort) 0x020)
-
-#define PKT_LEN_MASK    ((ushort) 0x07f)
-
-#define DATA_WNDW       ((ushort) 0x10)
-#define PKT_TTL_MASK    ((ushort) 0x0f)
-
-#define PKT_MAX_DATA_LEN   72
-
-#define PKT_LENGTH         sizeof(struct PKT)
-#define SYNC_PKT_LENGTH    (PKT_LENGTH + 4)
-
-#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK
-#define CONTROL_PKT_CMD_BIT  PKT_CMD_BIT
-#define CONTROL_PKT_ACK (PKT_ACK << 8)
-#define CONTROL_PKT_TGL (PKT_TGL << 8)
-#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
-#define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
-
-struct PKT {
-	u8 dest_unit;		/* Destination Unit Id */
-	u8 dest_port;		/* Destination POrt */
-	u8 src_unit;		/* Source Unit Id */
-	u8 src_port;		/* Source POrt */
-	u8 len;
-	u8 control;
-	u8 data[PKT_MAX_DATA_LEN];
-	/* Actual data :-) */
-	u16 csum;		/* C-SUM */
-};
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h
deleted file mode 100644
index 49cf6d1..0000000
--- a/drivers/char/rio/port.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: port.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)port.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_port_h__
-#define	__rio_port_h__
-
-/*
-**	Port data structure
-*/
-struct Port {
-	struct gs_port gs;
-	int PortNum;			/* RIO port no., 0-511 */
-	struct Host *HostP;
-	void __iomem *Caddr;
-	unsigned short HostPort;	/* Port number on host card */
-	unsigned char RupNum;		/* Number of RUP for port */
-	unsigned char ID2;		/* Second ID of RTA for port */
-	unsigned long State;		/* FLAGS for open & xopen */
-#define	RIO_LOPEN	0x00001		/* Local open */
-#define	RIO_MOPEN	0x00002		/* Modem open */
-#define	RIO_WOPEN	0x00004		/* Waiting for open */
-#define	RIO_CLOSING	0x00008		/* The port is being close */
-#define	RIO_XPBUSY	0x00010		/* Transparent printer busy */
-#define	RIO_BREAKING	0x00020		/* Break in progress */
-#define	RIO_DIRECT	0x00040		/* Doing Direct output */
-#define	RIO_EXCLUSIVE	0x00080		/* Stream open for exclusive use */
-#define	RIO_NDELAY	0x00100		/* Stream is open FNDELAY */
-#define	RIO_CARR_ON	0x00200		/* Stream has carrier present */
-#define	RIO_XPWANTR	0x00400		/* Stream wanted by Xprint */
-#define	RIO_RBLK	0x00800		/* Stream is read-blocked */
-#define	RIO_BUSY	0x01000		/* Stream is BUSY for write */
-#define	RIO_TIMEOUT	0x02000		/* Stream timeout in progress */
-#define	RIO_TXSTOP	0x04000		/* Stream output is stopped */
-#define	RIO_WAITFLUSH	0x08000		/* Stream waiting for flush */
-#define	RIO_DYNOROD	0x10000		/* Drain failed */
-#define	RIO_DELETED	0x20000		/* RTA has been deleted */
-#define RIO_ISSCANCODE	0x40000		/* This line is in scancode mode */
-#define	RIO_USING_EUC	0x100000	/* Using extended Unix chars */
-#define	RIO_CAN_COOK	0x200000	/* This line can do cooking */
-#define RIO_TRIAD_MODE  0x400000	/* Enable TRIAD special ops. */
-#define RIO_TRIAD_BLOCK 0x800000	/* Next read will block */
-#define RIO_TRIAD_FUNC  0x1000000	/* Seen a function key coming in */
-#define RIO_THROTTLE_RX 0x2000000	/* RX needs to be throttled. */
-
-	unsigned long Config;		/* FLAGS for NOREAD.... */
-#define	RIO_NOREAD	0x0001		/* Are not allowed to read port */
-#define	RIO_NOWRITE	0x0002		/* Are not allowed to write port */
-#define	RIO_NOXPRINT	0x0004		/* Are not allowed to xprint port */
-#define	RIO_NOMASK	0x0007		/* All not allowed things */
-#define RIO_IXANY	0x0008		/* Port is allowed ixany */
-#define	RIO_MODEM	0x0010		/* Stream is a modem device */
-#define	RIO_IXON	0x0020		/* Port is allowed ixon */
-#define RIO_WAITDRAIN	0x0040		/* Wait for port to completely drain */
-#define RIO_MAP_50_TO_50	0x0080	/* Map 50 baud to 50 baud */
-#define RIO_MAP_110_TO_110	0x0100	/* Map 110 baud to 110 baud */
-
-/*
-** 15.10.1998 ARG - ESIL 0761 prt fix
-** As LynxOS does not appear to support Hardware Flow Control .....
-** Define our own flow control flags in 'Config'.
-*/
-#define RIO_CTSFLOW	0x0200		/* RIO's own CTSFLOW flag */
-#define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
-
-
-	struct PHB __iomem *PhbP;	/* pointer to PHB for port */
-	u16 __iomem *TxAdd;		/* Add packets here */
-	u16 __iomem *TxStart;		/* Start of add array */
-	u16 __iomem *TxEnd;		/* End of add array */
-	u16 __iomem *RxRemove;		/* Remove packets here */
-	u16 __iomem *RxStart;		/* Start of remove array */
-	u16 __iomem *RxEnd;		/* End of remove array */
-	unsigned int RtaUniqueNum;	/* Unique number of RTA */
-	unsigned short PortState;	/* status of port */
-	unsigned short ModemState;	/* status of modem lines */
-	unsigned long ModemLines;	/* Modem bits sent to RTA */
-	unsigned char CookMode;		/* who expands CR/LF? */
-	unsigned char ParamSem;		/* Prevent write during param */
-	unsigned char Mapped;		/* if port mapped onto host */
-	unsigned char SecondBlock;	/* if port belongs to 2nd block
-				   		of 16 port RTA */
-	unsigned char InUse;		/* how many pre-emptive cmds */
-	unsigned char Lock;		/* if params locked */
-	unsigned char Store;		/* if params stored across closes */
-	unsigned char FirstOpen;	/* TRUE if first time port opened */
-	unsigned char FlushCmdBodge;	/* if doing a (non)flush */
-	unsigned char MagicFlags;	/* require intr processing */
-#define	MAGIC_FLUSH	0x01		/* mirror of WflushFlag */
-#define	MAGIC_REBOOT	0x02		/* RTA re-booted, re-open ports */
-#define	MORE_OUTPUT_EYGOR 0x04		/* riotproc failed to empty clists */
-	unsigned char WflushFlag;	/* 1 How many WFLUSHs active */
-/*
-** Transparent print stuff
-*/
-	struct Xprint {
-#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN		16	/* ALSO IN DAEMON.H */
-#endif
-		unsigned int XpCps;
-		char XpOn[MAX_XP_CTRL_LEN];
-		char XpOff[MAX_XP_CTRL_LEN];
-		unsigned short XpLen;	/* strlen(XpOn)+strlen(XpOff) */
-		unsigned char XpActive;
-		unsigned char XpLastTickOk;	/* TRUE if we can process */
-#define	XP_OPEN		00001
-#define	XP_RUNABLE	00002
-		struct ttystatics *XttyP;
-	} Xprint;
-	unsigned char RxDataStart;
-	unsigned char Cor2Copy;		/* copy of COR2 */
-	char *Name;			/* points to the Rta's name */
-	char *TxRingBuffer;
-	unsigned short TxBufferIn;	/* New data arrives here */
-	unsigned short TxBufferOut;	/* Intr removes data here */
-	unsigned short OldTxBufferOut;	/* Indicates if draining */
-	int TimeoutId;			/* Timeout ID */
-	unsigned int Debug;
-	unsigned char WaitUntilBooted;	/* True if open should block */
-	unsigned int statsGather;	/* True if gathering stats */
-	unsigned long txchars;		/* Chars transmitted */
-	unsigned long rxchars;		/* Chars received */
-	unsigned long opens;		/* port open count */
-	unsigned long closes;		/* port close count */
-	unsigned long ioctls;		/* ioctl count */
-	unsigned char LastRxTgl;	/* Last state of rx toggle bit */
-	spinlock_t portSem;		/* Lock using this sem */
-	int MonitorTstate;		/* Monitoring ? */
-	int timeout_id;			/* For calling 100 ms delays */
-	int timeout_sem;		/* For calling 100 ms delays */
-	int firstOpen;			/* First time open ? */
-	char *p;			/* save the global struc here .. */
-};
-
-struct ModuleInfo {
-	char *Name;
-	unsigned int Flags[4];		/* one per port on a module */
-};
-
-/*
-** This struct is required because trying to grab an entire Port structure
-** runs into problems with differing struct sizes between driver and config.
-*/
-struct PortParams {
-	unsigned int Port;
-	unsigned long Config;
-	unsigned long State;
-	struct ttystatics *TtyP;
-};
-
-#endif
diff --git a/drivers/char/rio/protsts.h b/drivers/char/rio/protsts.h
deleted file mode 100644
index 8ab7940..0000000
--- a/drivers/char/rio/protsts.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******      P R O T O C O L    S T A T U S   S T R U C T U R E      *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _protsts_h
-#define _protsts_h 1
-
-/*************************************************
- * ACK bit. Last Packet received OK. Set by
- * rxpkt to indicate that the Packet has been
- * received OK and that the LTT must set the ACK
- * bit in the next outward bound Packet
- * and re-set by LTT's after xmit.
- *
- * Gets shoved into rx_status
- ************************************************/
-#define PHB_RX_LAST_PKT_ACKED    ((ushort) 0x080)
-
-/*******************************************************
- * The Rx TOGGLE bit.
- * Stuffed into rx_status by RXPKT
- ******************************************************/
-#define PHB_RX_DATA_WNDW         ((ushort) 0x040)
-
-/*******************************************************
- * The Rx TOGGLE bit. Matches the setting in PKT.H
- * Stuffed into rx_status
- ******************************************************/
-#define PHB_RX_TGL               ((ushort) 0x2000)
-
-
-/*************************************************
- * This bit is set by the LRT to indicate that
- * an ACK (packet) must be returned.
- *
- * Gets shoved into tx_status
- ************************************************/
-#define PHB_TX_SEND_PKT_ACK      ((ushort) 0x08)
-
-/*************************************************
- * Set by LTT to indicate that an ACK is required
- *************************************************/
-#define PHB_TX_ACK_RQRD         ((ushort) 0x01)
-
-
-/*******************************************************
- * The Tx TOGGLE bit.
- * Stuffed into tx_status by RXPKT from the PKT WndW
- * field. Looked by the LTT when the NEXT Packet
- * is going to be sent.
- ******************************************************/
-#define PHB_TX_DATA_WNDW         ((ushort) 0x04)
-
-
-/*******************************************************
- * The Tx TOGGLE bit. Matches the setting in PKT.H
- * Stuffed into tx_status
- ******************************************************/
-#define PHB_TX_TGL               ((ushort) 0x02)
-
-/*******************************************************
- * Request intr bit. Set when the queue has gone quiet
- * and the PHB has requested an interrupt.
- ******************************************************/
-#define PHB_TX_INTR             ((ushort) 0x100)
-
-/*******************************************************
- * SET if the PHB cannot send any more data down the
- * Link
- ******************************************************/
-#define PHB_TX_HANDSHAKE         ((ushort) 0x010)
-
-
-#define RUP_SEND_WNDW		 ((ushort) 0x08) ;
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h
deleted file mode 100644
index 1bf3622..0000000
--- a/drivers/char/rio/rio.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rio.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)rio.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_rio_h__
-#define	__rio_rio_h__
-
-/*
-**	Maximum numbers of things
-*/
-#define	RIO_SLOTS	4	/* number of configuration slots */
-#define	RIO_HOSTS	4	/* number of hosts that can be found */
-#define	PORTS_PER_HOST	128	/* number of ports per host */
-#define	LINKS_PER_UNIT	4	/* number of links from a host */
-#define	RIO_PORTS	(PORTS_PER_HOST * RIO_HOSTS)	/* max. no. of ports */
-#define	RTAS_PER_HOST	(MAX_RUP)	/* number of RTAs per host */
-#define	PORTS_PER_RTA	(PORTS_PER_HOST/RTAS_PER_HOST)	/* ports on a rta */
-#define	PORTS_PER_MODULE 4	/* number of ports on a plug-in module */
-				/* number of modules on an RTA */
-#define	MODULES_PER_RTA	 (PORTS_PER_RTA/PORTS_PER_MODULE)
-#define MAX_PRODUCT	16	/* numbr of different product codes */
-#define MAX_MODULE_TYPES 16	/* number of different types of module */
-
-#define RIO_CONTROL_DEV	128	/* minor number of host/control device */
-#define RIO_INVALID_MAJOR 0	/* test first host card's major no for validity */
-
-/*
-** number of RTAs that can be bound to a master
-*/
-#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS)
-
-/*
-**	Unit types
-*/
-#define PC_RTA16	0x90000000
-#define PC_RTA8		0xe0000000
-#define TYPE_HOST	0
-#define TYPE_RTA8	1
-#define TYPE_RTA16	2
-
-/*
-**	Flag values returned by functions
-*/
-
-#define	RIO_FAIL	-1
-
-/*
-** SysPort value for something that hasn't any ports
-*/
-#define	NO_PORT	0xFFFFFFFF
-
-/*
-** Unit ID Of all hosts
-*/
-#define	HOST_ID	0
-
-/*
-** Break bytes into nybles
-*/
-#define	LONYBLE(X)	((X) & 0xF)
-#define	HINYBLE(X)	(((X)>>4) & 0xF)
-
-/*
-** Flag values passed into some functions
-*/
-#define	DONT_SLEEP	0
-#define	OK_TO_SLEEP	1
-
-#define	DONT_PRINT	1
-#define	DO_PRINT	0
-
-#define PRINT_TO_LOG_CONS	0
-#define PRINT_TO_CONS	1
-#define PRINT_TO_LOG	2
-
-/*
-** Timeout has trouble with times of less than 3 ticks...
-*/
-#define	MIN_TIMEOUT	3
-
-/*
-**	Generally useful constants
-*/
-
-#define	HUNDRED_MS		((HZ/10)?(HZ/10):1)
-#define	ONE_MEG			0x100000
-#define	SIXTY_FOUR_K		0x10000
-
-#define	RIO_AT_MEM_SIZE		SIXTY_FOUR_K
-#define	RIO_EISA_MEM_SIZE	SIXTY_FOUR_K
-#define	RIO_MCA_MEM_SIZE	SIXTY_FOUR_K
-
-#define	COOK_WELL		0
-#define	COOK_MEDIUM		1
-#define	COOK_RAW		2
-
-/*
-**	Pointer manipulation stuff
-**	RIO_PTR takes hostp->Caddr and the offset into the DP RAM area
-**	and produces a UNIX caddr_t (pointer) to the object
-**	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
-**	returns the offset into the DP RAM area.
-*/
-#define	RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O)))
-#define	RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C))
-
-/*
-**	How to convert from various different device number formats:
-**	DEV is a dev number, as passed to open, close etc - NOT a minor
-**	number!
-**/
-
-#define	RIO_MODEM_MASK		0x1FF
-#define	RIO_MODEM_BIT		0x200
-#define	RIO_UNMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_MASK)
-#define	RIO_ISMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_BIT)
-#define RIO_PORT(DEV,FIRST_MAJ)	( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
-					+ MINOR(DEV)
-#define CSUM(pkt_ptr)  (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \
-			((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \
-			((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \
-			((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \
-			((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] )
-
-#define	RIO_LINK_ENABLE	0x80FF	/* FF is a hack, mainly for Mips, to        */
-			       /* prevent a really stupid race condition.  */
-
-#define	NOT_INITIALISED	0
-#define	INITIALISED	1
-
-#define	NOT_POLLING	0
-#define	POLLING		1
-
-#define	NOT_CHANGED	0
-#define	CHANGED		1
-
-#define	NOT_INUSE	0
-
-#define	DISCONNECT	0
-#define	CONNECT		1
-
-/* ------ Control Codes ------ */
-
-#define	CONTROL		'^'
-#define IFOAD		( CONTROL + 1 )
-#define	IDENTIFY	( CONTROL + 2 )
-#define	ZOMBIE		( CONTROL + 3 )
-#define	UFOAD		( CONTROL + 4 )
-#define IWAIT		( CONTROL + 5 )
-
-#define	IFOAD_MAGIC	0xF0AD	/* of course */
-#define	ZOMBIE_MAGIC	(~0xDEAD)	/* not dead -> zombie */
-#define	UFOAD_MAGIC	0xD1E	/* kill-your-neighbour */
-#define	IWAIT_MAGIC	0xB1DE	/* Bide your time */
-
-/* ------ Error Codes ------ */
-
-#define E_NO_ERROR                       ((ushort) 0)
-
-/* ------ Free Lists ------ */
-
-struct rio_free_list {
-	u16 next;
-	u16 prev;
-};
-
-/* NULL for card side linked lists */
-#define	TPNULL	((ushort)(0x8000))
-/* We can add another packet to a transmit queue if the packet pointer pointed
- * to by the TxAdd pointer has PKT_IN_USE clear in its address. */
-#define PKT_IN_USE    0x1
-
-/* ------ Topology ------ */
-
-struct Top {
-	u8 Unit;
-	u8 Link;
-};
-
-#endif				/* __rio_h__ */
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
deleted file mode 100644
index 5e33293..0000000
--- a/drivers/char/rio/rio_linux.c
+++ /dev/null
@@ -1,1204 +0,0 @@
-
-/* rio_linux.c -- Linux driver for the Specialix RIO series cards. 
- *
- *
- *   (C) 1999 R.E.Wolff@BitWizard.nl
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (rio.txt) first.
- *
- *
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- *
- * */
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/miscdevice.h>
-#include <linux/init.h>
-
-#include <linux/generic_serial.h>
-#include <asm/uaccess.h>
-
-#include "linux_compat.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-#include "protsts.h"
-#include "rioboard.h"
-
-
-#include "rio_linux.h"
-
-/* I don't think that this driver can handle more than 512 ports on
-one machine.  Specialix specifies max 4 boards in one machine. I don't
-know why. If you want to try anyway you'll have to increase the number
-of boards in rio.h.  You'll have to allocate more majors if you need
-more than 512 ports.... */
-
-#ifndef RIO_NORMAL_MAJOR0
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define RIO_NORMAL_MAJOR0  154
-#define RIO_NORMAL_MAJOR1  156
-#endif
-
-#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
-#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
-#endif
-
-#ifndef RIO_WINDOW_LEN
-#define RIO_WINDOW_LEN 0x10000
-#endif
-
-
-/* Configurable options: 
-   (Don't be too sure that it'll work if you toggle them) */
-
-/* Am I paranoid or not ? ;-) */
-#undef RIO_PARANOIA_CHECK
-
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000
-   Hz, but it is user configurable. I don't recommend going above 1000
-   Hz. The interrupt ratelimit might trigger if the interrupt is
-   shared with a very active other device. 
-   undef this if you want to disable the check....
-*/
-#define IRQ_RATE_LIMIT 200
-
-
-/* These constants are derived from SCO Source */
-static DEFINE_MUTEX(rio_fw_mutex);
-static struct Conf
- RIOConf = {
-	/* locator */ "RIO Config here",
-					/* startuptime */ HZ * 2,
-					/* how long to wait for card to run */
-				/* slowcook */ 0,
-				/* TRUE -> always use line disc. */
-				/* intrpolltime */ 1,
-				/* The frequency of OUR polls */
-				/* breakinterval */ 25,
-				/* x10 mS XXX: units seem to be 1ms not 10! -- REW */
-				/* timer */ 10,
-				/* mS */
-	/* RtaLoadBase */ 0x7000,
-	/* HostLoadBase */ 0x7C00,
-				/* XpHz */ 5,
-				/* number of Xprint hits per second */
-				/* XpCps */ 120,
-				/* Xprint characters per second */
-				/* XpOn */ "\033d#",
-				/* start Xprint for a wyse 60 */
-				/* XpOff */ "\024",
-				/* end Xprint for a wyse 60 */
-				/* MaxXpCps */ 2000,
-				/* highest Xprint speed */
-				/* MinXpCps */ 10,
-				/* slowest Xprint speed */
-				/* SpinCmds */ 1,
-				/* non-zero for mega fast boots */
-					/* First Addr */ 0x0A0000,
-					/* First address to look at */
-					/* Last Addr */ 0xFF0000,
-					/* Last address looked at */
-				/* BufferSize */ 1024,
-				/* Bytes per port of buffering */
-				/* LowWater */ 256,
-				/* how much data left before wakeup */
-				/* LineLength */ 80,
-				/* how wide is the console? */
-				/* CmdTimeout */ HZ,
-				/* how long a close command may take */
-};
-
-
-
-
-/* Function prototypes */
-
-static void rio_disable_tx_interrupts(void *ptr);
-static void rio_enable_tx_interrupts(void *ptr);
-static void rio_disable_rx_interrupts(void *ptr);
-static void rio_enable_rx_interrupts(void *ptr);
-static int rio_carrier_raised(struct tty_port *port);
-static void rio_shutdown_port(void *ptr);
-static int rio_set_real_termios(void *ptr);
-static void rio_hungup(void *ptr);
-static void rio_close(void *ptr);
-static int rio_chars_in_buffer(void *ptr);
-static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-static int rio_init_drivers(void);
-
-static void my_hd(void *addr, int len);
-
-static struct tty_driver *rio_driver, *rio_driver2;
-
-/* The name "p" is a bit non-descript. But that's what the rio-lynxos
-sources use all over the place. */
-struct rio_info *p;
-
-int rio_debug;
-
-
-/* You can have the driver poll your card. 
-    - Set rio_poll to 1 to poll every timer tick (10ms on Intel). 
-      This is used when the card cannot use an interrupt for some reason.
-*/
-static int rio_poll = 1;
-
-
-/* These are the only open spaces in my computer. Yours may have more
-   or less.... */
-static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 };
-
-#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
-
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
-   Some architectures may need more. -- Changed to LONG to
-   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
-static long rio_irqmask = -1;
-
-MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");
-MODULE_DESCRIPTION("RIO driver");
-MODULE_LICENSE("GPL");
-module_param(rio_poll, int, 0);
-module_param(rio_debug, int, 0644);
-module_param(rio_irqmask, long, 0);
-
-static struct real_driver rio_real_driver = {
-	rio_disable_tx_interrupts,
-	rio_enable_tx_interrupts,
-	rio_disable_rx_interrupts,
-	rio_enable_rx_interrupts,
-	rio_shutdown_port,
-	rio_set_real_termios,
-	rio_chars_in_buffer,
-	rio_close,
-	rio_hungup,
-	NULL
-};
-
-/* 
- *  Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations rio_fw_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = rio_fw_ioctl,
-	.llseek = noop_llseek,
-};
-
-static struct miscdevice rio_fw_device = {
-	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops
-};
-
-
-
-
-
-#ifdef RIO_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine)
-{
-
-	static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != RIO_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-#else
-#define rio_paranoia_check(a,b,c) 0
-#endif
-
-
-#ifdef DEBUG
-static void my_hd(void *ad, int len)
-{
-	int i, j, ch;
-	unsigned char *addr = ad;
-
-	for (i = 0; i < len; i += 16) {
-		rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i);
-		for (j = 0; j < 16; j++) {
-			rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = addr[j + i];
-			rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch));
-		}
-		rio_dprintk(RIO_DEBUG_PARAM, "\n");
-	}
-}
-#else
-#define my_hd(ad,len) do{/* nothing*/ } while (0)
-#endif
-
-
-/* Delay a number of jiffies, allowing a signal to interrupt */
-int RIODelay(struct Port *PortP, int njiffies)
-{
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
-	msleep_interruptible(jiffies_to_msecs(njiffies));
-	func_exit();
-
-	if (signal_pending(current))
-		return RIO_FAIL;
-	else
-		return !RIO_FAIL;
-}
-
-
-/* Delay a number of jiffies, disallowing a signal to interrupt */
-int RIODelay_ni(struct Port *PortP, int njiffies)
-{
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
-	msleep(jiffies_to_msecs(njiffies));
-	func_exit();
-	return !RIO_FAIL;
-}
-
-void rio_copy_to_card(void *from, void __iomem *to, int len)
-{
-	rio_copy_toio(to, from, len);
-}
-
-int rio_minor(struct tty_struct *tty)
-{
-	return tty->index + ((tty->driver == rio_driver) ? 0 : 256);
-}
-
-static int rio_set_real_termios(void *ptr)
-{
-	return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1);
-}
-
-
-static void rio_reset_interrupt(struct Host *HostP)
-{
-	func_enter();
-
-	switch (HostP->Type) {
-	case RIO_AT:
-	case RIO_MCA:
-	case RIO_PCI:
-		writeb(0xFF, &HostP->ResetInt);
-	}
-
-	func_exit();
-}
-
-
-static irqreturn_t rio_interrupt(int irq, void *ptr)
-{
-	struct Host *HostP;
-	func_enter();
-
-	HostP = ptr;			/* &p->RIOHosts[(long)ptr]; */
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
-
-	/* AAargh! The order in which to do these things is essential and
-	   not trivial.
-
-	   - hardware twiddling goes before "recursive". Otherwise when we
-	   poll the card, and a recursive interrupt happens, we won't
-	   ack the card, so it might keep on interrupting us. (especially
-	   level sensitive interrupt systems like PCI).
-
-	   - Rate limit goes before hardware twiddling. Otherwise we won't
-	   catch a card that has gone bonkers.
-
-	   - The "initialized" test goes after the hardware twiddling. Otherwise
-	   the card will stick us in the interrupt routine again.
-
-	   - The initialized test goes before recursive.
-	 */
-
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
-	if (HostP->Ivec == irq) {
-		/* Tell the card we've noticed the interrupt. */
-		rio_reset_interrupt(HostP);
-	}
-
-	if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
-		return IRQ_HANDLED;
-
-	if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) {
-		printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec);
-		return IRQ_HANDLED;
-	}
-
-	RIOServiceHost(p, HostP);
-
-	rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type);
-
-	clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks);
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-
-static void rio_pollfunc(unsigned long data)
-{
-	func_enter();
-
-	rio_interrupt(0, &p->RIOHosts[data]);
-	mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll);
-
-	func_exit();
-}
-
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *              interface with the generic_serial driver                  *
- * ********************************************************************** */
-
-/* Ehhm. I don't know how to fiddle with interrupts on the Specialix 
-   cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */
-
-static void rio_disable_tx_interrupts(void *ptr)
-{
-	func_enter();
-
-	/*  port->gs.port.flags &= ~GS_TX_INTEN; */
-
-	func_exit();
-}
-
-
-static void rio_enable_tx_interrupts(void *ptr)
-{
-	struct Port *PortP = ptr;
-	/* int hn; */
-
-	func_enter();
-
-	/* hn = PortP->HostP - p->RIOHosts;
-
-	   rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
-	   rio_interrupt (-1,(void *) hn, NULL); */
-
-	RIOTxEnable((char *) PortP);
-
-	/*
-	 * In general we cannot count on "tx empty" interrupts, although
-	 * the interrupt routine seems to be able to tell the difference.
-	 */
-	PortP->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-
-static void rio_disable_rx_interrupts(void *ptr)
-{
-	func_enter();
-	func_exit();
-}
-
-static void rio_enable_rx_interrupts(void *ptr)
-{
-	/*  struct rio_port *port = ptr; */
-	func_enter();
-	func_exit();
-}
-
-
-/* Jeez. Isn't this simple?  */
-static int rio_carrier_raised(struct tty_port *port)
-{
-	struct Port *PortP = container_of(port, struct Port, gs.port);
-	int rv;
-
-	func_enter();
-	rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0;
-
-	rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
-
-	func_exit();
-	return rv;
-}
-
-
-/* Jeez. Isn't this simple? Actually, we can sync with the actual port
-   by just pushing stuff into the queue going to the port... */
-static int rio_chars_in_buffer(void *ptr)
-{
-	func_enter();
-
-	func_exit();
-	return 0;
-}
-
-
-/* Nothing special here... */
-static void rio_shutdown_port(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-	PortP->gs.port.tty = NULL;
-	func_exit();
-}
-
-
-/* I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-static void rio_hungup(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-	PortP->gs.port.tty = NULL;
-
-	func_exit();
-}
-
-
-/* The standard serial_close would become shorter if you'd wrap it like
-   this. 
-   rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
- */
-static void rio_close(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-
-	riotclose(ptr);
-
-	if (PortP->gs.port.count) {
-		printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.port.count);
-		PortP->gs.port.count = 0;
-	}
-
-	PortP->gs.port.tty = NULL;
-	func_exit();
-}
-
-
-
-static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int rc = 0;
-	func_enter();
-
-	/* The "dev" argument isn't used. */
-	mutex_lock(&rio_fw_mutex);
-	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
-	mutex_unlock(&rio_fw_mutex);
-
-	func_exit();
-	return rc;
-}
-
-extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-
-static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int rc;
-	struct Port *PortP;
-	int ival;
-
-	func_enter();
-
-	PortP = (struct Port *) tty->driver_data;
-
-	rc = 0;
-	switch (cmd) {
-	case TIOCSSOFTCAR:
-		if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
-			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
-		}
-		break;
-	case TIOCGSERIAL:
-		rc = -EFAULT;
-		if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct)))
-			rc = gs_getserial(&PortP->gs, argp);
-		break;
-	case TCSBRK:
-		if (PortP->State & RIO_DELETED) {
-			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
-			rc = -EIO;
-		} else {
-			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) ==
-					RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
-				rc = -EIO;
-			}
-		}
-		break;
-	case TCSBRKP:
-		if (PortP->State & RIO_DELETED) {
-			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
-			rc = -EIO;
-		} else {
-			int l;
-			l = arg ? arg * 100 : 250;
-			if (l > 255)
-				l = 255;
-			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2,
-					arg ? arg * 100 : 250) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
-				rc = -EIO;
-			}
-		}
-		break;
-	case TIOCSSERIAL:
-		rc = -EFAULT;
-		if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct)))
-			rc = gs_setserial(&PortP->gs, argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	func_exit();
-	return rc;
-}
-
-
-/* The throttle/unthrottle scheme for the Specialix card is different
- * from other drivers and deserves some explanation. 
- * The Specialix hardware takes care of XON/XOFF
- * and CTS/RTS flow control itself.  This means that all we have to
- * do when signalled by the upper tty layer to throttle/unthrottle is
- * to make a note of it here.  When we come to read characters from the
- * rx buffers on the card (rio_receive_chars()) we look to see if the
- * upper layer can accept more (as noted here in rio_rx_throt[]). 
- * If it can't we simply don't remove chars from the cards buffer. 
- * When the tty layer can accept chars, we again note that here and when
- * rio_receive_chars() is called it will remove them from the cards buffer.
- * The card will notice that a ports buffer has drained below some low
- * water mark and will unflow control the line itself, using whatever
- * flow control scheme is in use for that port. -- Simon Allen
- */
-
-static void rio_throttle(struct tty_struct *tty)
-{
-	struct Port *port = (struct Port *) tty->driver_data;
-
-	func_enter();
-	/* If the port is using any type of input flow
-	 * control then throttle the port.
-	 */
-
-	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-		port->State |= RIO_THROTTLE_RX;
-	}
-
-	func_exit();
-}
-
-
-static void rio_unthrottle(struct tty_struct *tty)
-{
-	struct Port *port = (struct Port *) tty->driver_data;
-
-	func_enter();
-	/* Always unthrottle even if flow control is not enabled on
-	 * this port in case we disabled flow control while the port
-	 * was throttled
-	 */
-
-	port->State &= ~RIO_THROTTLE_RX;
-
-	func_exit();
-	return;
-}
-
-
-
-
-
-/* ********************************************************************** *
- *                    Here are the initialization routines.               *
- * ********************************************************************** */
-
-
-static struct vpd_prom *get_VPD_PROM(struct Host *hp)
-{
-	static struct vpd_prom vpdp;
-	char *p;
-	int i;
-
-	func_enter();
-	rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM);
-
-	p = (char *) &vpdp;
-	for (i = 0; i < sizeof(struct vpd_prom); i++)
-		*p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2);
-	/* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
-
-	/* Terminate the identifier string.
-	 *** requires one extra byte in struct vpd_prom *** */
-	*p++ = 0;
-
-	if (rio_debug & RIO_DEBUG_PROBE)
-		my_hd((char *) &vpdp, 0x20);
-
-	func_exit();
-
-	return &vpdp;
-}
-
-static const struct tty_operations rio_ops = {
-	.open = riotopen,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = rio_ioctl,
-	.throttle = rio_throttle,
-	.unthrottle = rio_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-};
-
-static int rio_init_drivers(void)
-{
-	int error = -ENOMEM;
-
-	rio_driver = alloc_tty_driver(256);
-	if (!rio_driver)
-		goto out;
-	rio_driver2 = alloc_tty_driver(256);
-	if (!rio_driver2)
-		goto out1;
-
-	func_enter();
-
-	rio_driver->owner = THIS_MODULE;
-	rio_driver->driver_name = "specialix_rio";
-	rio_driver->name = "ttySR";
-	rio_driver->major = RIO_NORMAL_MAJOR0;
-	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	rio_driver->subtype = SERIAL_TYPE_NORMAL;
-	rio_driver->init_termios = tty_std_termios;
-	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rio_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(rio_driver, &rio_ops);
-
-	rio_driver2->owner = THIS_MODULE;
-	rio_driver2->driver_name = "specialix_rio";
-	rio_driver2->name = "ttySR";
-	rio_driver2->major = RIO_NORMAL_MAJOR1;
-	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;
-	rio_driver2->subtype = SERIAL_TYPE_NORMAL;
-	rio_driver2->init_termios = tty_std_termios;
-	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rio_driver2->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(rio_driver2, &rio_ops);
-
-	rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
-
-	if ((error = tty_register_driver(rio_driver)))
-		goto out2;
-	if ((error = tty_register_driver(rio_driver2)))
-		goto out3;
-	func_exit();
-	return 0;
-      out3:
-	tty_unregister_driver(rio_driver);
-      out2:
-	put_tty_driver(rio_driver2);
-      out1:
-	put_tty_driver(rio_driver);
-      out:
-	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error);
-	return 1;
-}
-
-static const struct tty_port_operations rio_port_ops = {
-	.carrier_raised = rio_carrier_raised,
-};
-
-static int rio_init_datastructures(void)
-{
-	int i;
-	struct Port *port;
-	func_enter();
-
-	/* Many drivers statically allocate the maximum number of ports
-	   There is no reason not to allocate them dynamically. Is there? -- REW */
-	/* However, the RIO driver allows users to configure their first
-	   RTA as the ports numbered 504-511. We therefore need to allocate
-	   the whole range. :-(   -- REW */
-
-#define RI_SZ   sizeof(struct rio_info)
-#define HOST_SZ sizeof(struct Host)
-#define PORT_SZ sizeof(struct Port *)
-#define TMIO_SZ sizeof(struct termios *)
-	rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
-
-	if (!(p = kzalloc(RI_SZ, GFP_KERNEL)))
-		goto free0;
-	if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL)))
-		goto free1;
-	if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL)))
-		goto free2;
-	p->RIOConf = RIOConf;
-	rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
-
-#if 1
-	for (i = 0; i < RIO_PORTS; i++) {
-		port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL);
-		if (!port) {
-			goto free6;
-		}
-		rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &rio_port_ops;
-		port->PortNum = i;
-		port->gs.magic = RIO_MAGIC;
-		port->gs.close_delay = HZ / 2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &rio_real_driver;
-		spin_lock_init(&port->portSem);
-	}
-#else
-	/* We could postpone initializing them to when they are configured. */
-#endif
-
-
-
-	if (rio_debug & RIO_DEBUG_INIT) {
-		my_hd(&rio_real_driver, sizeof(rio_real_driver));
-	}
-
-
-	func_exit();
-	return 0;
-
-      free6:for (i--; i >= 0; i--)
-		kfree(p->RIOPortp[i]);
-/*free5:
- free4:
- free3:*/ kfree(p->RIOPortp);
-      free2:kfree(p->RIOHosts);
-      free1:
-	rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
-	kfree(p);
-      free0:
-	return -ENOMEM;
-}
-
-static void __exit rio_release_drivers(void)
-{
-	func_enter();
-	tty_unregister_driver(rio_driver2);
-	tty_unregister_driver(rio_driver);
-	put_tty_driver(rio_driver2);
-	put_tty_driver(rio_driver);
-	func_exit();
-}
-
-
-#ifdef CONFIG_PCI
- /* This was written for SX, but applies to RIO too...
-    (including bugs....)
-
-    There is another bit besides Bit 17. Turning that bit off
-    (on boards shipped with the fix in the eeprom) results in a 
-    hang on the next access to the card. 
-  */
-
- /******************************************************** 
- * Setting bit 17 in the CNTRL register of the PLX 9050  * 
- * chip forces a retry on writes while a read is pending.*
- * This is to prevent the card locking up on Intel Xeon  *
- * multiprocessor systems with the NX chipset.    -- NV  *
- ********************************************************/
-
-/* Newer cards are produced with this bit set from the configuration
-   EEprom.  As the bit is read/write for the CPU, we can fix it here,
-   if we detect that it isn't set correctly. -- REW */
-
-static void fix_rio_pci(struct pci_dev *pdev)
-{
-	unsigned long hwbase;
-	unsigned char __iomem *rebase;
-	unsigned int t;
-
-#define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x18260000
-
-	hwbase = pci_resource_start(pdev, 0);
-	rebase = ioremap(hwbase, 0x80);
-	t = readl(rebase + CNTRL_REG_OFFSET);
-	if (t != CNTRL_REG_GOODVALUE) {
-		printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
-		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
-	}
-	iounmap(rebase);
-}
-#endif
-
-
-static int __init rio_init(void)
-{
-	int found = 0;
-	int i;
-	struct Host *hp;
-	int retval;
-	struct vpd_prom *vpdp;
-	int okboard;
-
-#ifdef CONFIG_PCI
-	struct pci_dev *pdev = NULL;
-	unsigned short tshort;
-#endif
-
-	func_enter();
-	rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug);
-
-	if (abs((long) (&rio_debug) - rio_debug) < 0x10000) {
-		printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
-		rio_debug = -1;
-	}
-
-	if (misc_register(&rio_fw_device) < 0) {
-		printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
-		return -EIO;
-	}
-
-	retval = rio_init_datastructures();
-	if (retval < 0) {
-		misc_deregister(&rio_fw_device);
-		return retval;
-	}
-#ifdef CONFIG_PCI
-	/* First look for the JET devices: */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) {
-		u32 tint;
-
-		if (pci_enable_device(pdev))
-			continue;
-
-		/* Specialix has a whole bunch of cards with
-		   0x2000 as the device ID. They say its because
-		   the standard requires it. Stupid standard. */
-		/* It seems that reading a word doesn't work reliably on 2.0.
-		   Also, reading a non-aligned dword doesn't work. So we read the
-		   whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
-		   ourselves */
-		pci_read_config_dword(pdev, 0x2c, &tint);
-		tshort = (tint >> 16) & 0xffff;
-		rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
-		if (tshort != 0x0100) {
-			rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort);
-			continue;
-		}
-		rio_dprintk(RIO_DEBUG_PROBE, "cp1\n");
-
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = pci_resource_start(pdev, 2);
-		hp->Ivec = pdev->irq;
-		if (((1 << hp->Ivec) & rio_irqmask) == 0)
-			hp->Ivec = 0;
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_PCI;
-		hp->Copy = rio_copy_to_card;
-		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
-		spin_lock_init(&hp->HostLock);
-		rio_reset_interrupt(hp);
-		rio_start_card_running(hp);
-
-		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
-		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
-			rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n");
-			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-			p->RIOHosts[p->RIONumHosts].UniqueNum =
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
-			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-			fix_rio_pci(pdev);
-
-			p->RIOHosts[p->RIONumHosts].pdev = pdev;
-			pci_dev_get(pdev);
-
-			p->RIOLastPCISearch = 0;
-			p->RIONumHosts++;
-			found++;
-		} else {
-			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
-			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
-		}
-	}
-
-	/* Then look for the older PCI card.... : */
-
-	/* These older PCI cards have problems (only byte-mode access is
-	   supported), which makes them a bit awkward to support.
-	   They also have problems sharing interrupts. Be careful.
-	   (The driver now refuses to share interrupts for these
-	   cards. This should be sufficient).
-	 */
-
-	/* Then look for the older RIO/PCI devices: */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) {
-		if (pci_enable_device(pdev))
-			continue;
-
-#ifdef CONFIG_RIO_OLDPCI
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = pci_resource_start(pdev, 0);
-		hp->Ivec = pdev->irq;
-		if (((1 << hp->Ivec) & rio_irqmask) == 0)
-			hp->Ivec = 0;
-		hp->Ivec |= 0x8000;	/* Mark as non-sharable */
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_PCI;
-		hp->Copy = rio_copy_to_card;
-		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
-		spin_lock_init(&hp->HostLock);
-
-		rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
-		rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
-
-		rio_reset_interrupt(hp);
-		rio_start_card_running(hp);
-		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
-		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
-			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-			p->RIOHosts[p->RIONumHosts].UniqueNum =
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
-			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-			p->RIOHosts[p->RIONumHosts].pdev = pdev;
-			pci_dev_get(pdev);
-
-			p->RIOLastPCISearch = 0;
-			p->RIONumHosts++;
-			found++;
-		} else {
-			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
-			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
-		}
-#else
-		printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
-#endif
-	}
-#endif				/* PCI */
-
-	/* Now probe for ISA cards... */
-	for (i = 0; i < NR_RIO_ADDRS; i++) {
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = rio_probe_addrs[i];
-		/* There was something about the IRQs of these cards. 'Forget what.--REW */
-		hp->Ivec = 0;
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_AT;
-		hp->Copy = rio_copy_to_card;	/* AT card PCI???? - PVDL
-                                         * -- YES! this is now a normal copy. Only the
-					 * old PCI card uses the special PCI copy.
-					 * Moreover, the ISA card will work with the
-					 * special PCI copy anyway. -- REW */
-		hp->Mode = 0;
-		spin_lock_init(&hp->HostLock);
-
-		vpdp = get_VPD_PROM(hp);
-		rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n");
-		okboard = 0;
-		if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
-			/* Board is present... */
-			if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) {
-				/* ... and feeling fine!!!! */
-				rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-				if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
-					rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum);
-					okboard++;
-					found++;
-				}
-			}
-
-			if (!okboard) {
-				iounmap(hp->Caddr);
-				hp->Caddr = NULL;
-			}
-		}
-	}
-
-
-	for (i = 0; i < p->RIONumHosts; i++) {
-		hp = &p->RIOHosts[i];
-		if (hp->Ivec) {
-			int mode = IRQF_SHARED;
-			if (hp->Ivec & 0x8000) {
-				mode = 0;
-				hp->Ivec &= 0x7fff;
-			}
-			rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode);
-			retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp);
-			rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
-			if (retval) {
-				printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
-				hp->Ivec = 0;
-			}
-			rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
-			if (hp->Ivec != 0) {
-				rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
-				hp->Mode |= RIO_PCI_INT_ENABLE;
-			} else
-				hp->Mode &= ~RIO_PCI_INT_ENABLE;
-			rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
-			rio_start_card_running(hp);
-		}
-		/* Init the timer "always" to make sure that it can safely be
-		   deleted when we unload... */
-
-		setup_timer(&hp->timer, rio_pollfunc, i);
-		if (!hp->Ivec) {
-			rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
-			mod_timer(&hp->timer, jiffies + rio_poll);
-		}
-	}
-
-	if (found) {
-		rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
-		rio_init_drivers();
-	} else {
-		/* deregister the misc device we created earlier */
-		misc_deregister(&rio_fw_device);
-	}
-
-	func_exit();
-	return found ? 0 : -EIO;
-}
-
-
-static void __exit rio_exit(void)
-{
-	int i;
-	struct Host *hp;
-
-	func_enter();
-
-	for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) {
-		RIOHostReset(hp->Type, hp->CardP, hp->Slot);
-		if (hp->Ivec) {
-			free_irq(hp->Ivec, hp);
-			rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
-		}
-		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer_sync(&hp->timer);
-		if (hp->Caddr)
-			iounmap(hp->Caddr);
-		if (hp->Type == RIO_PCI)
-			pci_dev_put(hp->pdev);
-	}
-
-	if (misc_deregister(&rio_fw_device) < 0) {
-		printk(KERN_INFO "rio: couldn't deregister control-device\n");
-	}
-
-
-	rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
-
-	rio_release_drivers();
-
-	/* Release dynamically allocated memory */
-	kfree(p->RIOPortp);
-	kfree(p->RIOHosts);
-	kfree(p);
-
-	func_exit();
-}
-
-module_init(rio_init);
-module_exit(rio_exit);
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
deleted file mode 100644
index 7f26cd7..0000000
--- a/drivers/char/rio/rio_linux.h
+++ /dev/null
@@ -1,197 +0,0 @@
-
-/*
- *  rio_linux.h
- *
- *  Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  RIO serial driver.
- *
- *  Version 1.0 -- July, 1999. 
- * 
- */
-
-#define RIO_NBOARDS        4
-#define RIO_PORTSPERBOARD 128
-#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
-
-#define MODEM_SUPPORT
-
-#ifdef __KERNEL__
-
-#define RIO_MAGIC 0x12345678
-
-
-struct vpd_prom {
-	unsigned short id;
-	char hwrev;
-	char hwass;
-	int uniqid;
-	char myear;
-	char mweek;
-	char hw_feature[5];
-	char oem_id;
-	char identifier[16];
-};
-
-
-#define RIO_DEBUG_ALL           0xffffffff
-
-#define O_OTHER(tty)    \
-      ((O_OLCUC(tty))  ||\
-      (O_ONLCR(tty))   ||\
-      (O_OCRNL(tty))   ||\
-      (O_ONOCR(tty))   ||\
-      (O_ONLRET(tty))  ||\
-      (O_OFILL(tty))   ||\
-      (O_OFDEL(tty))   ||\
-      (O_NLDLY(tty))   ||\
-      (O_CRDLY(tty))   ||\
-      (O_TABDLY(tty))  ||\
-      (O_BSDLY(tty))   ||\
-      (O_VTDLY(tty))   ||\
-      (O_FFDLY(tty)))
-
-/* Same for input. */
-#define I_OTHER(tty)    \
-      ((I_INLCR(tty))  ||\
-      (I_IGNCR(tty))   ||\
-      (I_ICRNL(tty))   ||\
-      (I_IUCLC(tty))   ||\
-      (L_ISIG(tty)))
-
-
-#endif				/* __KERNEL__ */
-
-
-#define RIO_BOARD_INTR_LOCK  1
-
-
-#ifndef RIOCTL_MISC_MINOR
-/* Allow others to gather this into "major.h" or something like that */
-#define RIOCTL_MISC_MINOR    169
-#endif
-
-
-/* Allow us to debug "in the field" without requiring clients to
-   recompile.... */
-#if 1
-#define rio_spin_lock_irqsave(sem, flags) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \
-	                                sem, __FILE__, __LINE__);\
-	spin_lock_irqsave(sem, flags);\
-	} while (0)
-
-#define rio_spin_unlock_irqrestore(sem, flags) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_unlock_irqrestore(sem, flags);\
-	} while (0)
-
-#define rio_spin_lock(sem) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_lock(sem);\
-	} while (0)
-
-#define rio_spin_unlock(sem) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_unlock(sem);\
-	} while (0)
-#else
-#define rio_spin_lock_irqsave(sem, flags) \
-            spin_lock_irqsave(sem, flags)
-
-#define rio_spin_unlock_irqrestore(sem, flags) \
-            spin_unlock_irqrestore(sem, flags)
-
-#define rio_spin_lock(sem) \
-            spin_lock(sem)
-
-#define rio_spin_unlock(sem) \
-            spin_unlock(sem)
-
-#endif
-
-
-
-#ifdef CONFIG_RIO_OLDPCI
-static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n)
-{
-	char __iomem *dst = dest;
-	char *src = source;
-
-	while (n--) {
-		writeb(*src++, dst++);
-		(void) readb(dummy);
-	}
-
-	return dest;
-}
-
-static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n)
-{
-	char __iomem *dst = dest;
-	char *src = source;
-
-	while (n--)
-		writeb(*src++, dst++);
-
-	return dest;
-}
-
-
-static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
-{
-	char *dst = dest;
-	char __iomem *src = source;
-
-	while (n--)
-		*dst++ = readb(src++);
-
-	return dest;
-}
-
-#else
-#define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
-#define rio_copy_toio   		       memcpy_toio
-#define rio_memcpy_fromio                      memcpy_fromio
-#endif
-
-#define DEBUG 1
-
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-
-#ifdef DEBUG
-#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__)
-#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __func__)
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line)
-#else
-#define rio_dprintk(f, str...)	/* nothing */
-#define func_enter()
-#define func_exit()
-#define func_enter2()
-#endif
diff --git a/drivers/char/rio/rioboard.h b/drivers/char/rio/rioboard.h
deleted file mode 100644
index 2522300..0000000
--- a/drivers/char/rio/rioboard.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	RIO Host Card Hardware Definitions	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	26th April 1999				*/
-/*									*/
-/*	Version		:	1.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1999	*
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the RIO board hardware	*/
-/*									*/
-/************************************************************************/
-
-#ifndef	_rioboard_h		/* If RIOBOARD.H not already defined */
-#define	_rioboard_h    1
-
-/*****************************************************************************
-***********************                                ***********************
-***********************   Hardware Control Registers   ***********************
-***********************                                ***********************
-*****************************************************************************/
-
-/* Hardware Registers... */
-
-#define	RIO_REG_BASE	0x7C00	/* Base of control registers */
-
-#define	RIO_CONFIG	RIO_REG_BASE + 0x0000	/* WRITE: Configuration Register */
-#define	RIO_INTSET	RIO_REG_BASE + 0x0080	/* WRITE: Interrupt Set */
-#define	RIO_RESET	RIO_REG_BASE + 0x0100	/* WRITE: Host Reset */
-#define	RIO_INTRESET	RIO_REG_BASE + 0x0180	/* WRITE: Interrupt Reset */
-
-#define	RIO_VPD_ROM	RIO_REG_BASE + 0x0000	/* READ: Vital Product Data ROM */
-#define	RIO_INTSTAT	RIO_REG_BASE + 0x0080	/* READ: Interrupt Status (Jet boards only) */
-#define	RIO_RESETSTAT	RIO_REG_BASE + 0x0100	/* READ: Reset Status (Jet boards only) */
-
-/* RIO_VPD_ROM definitions... */
-#define	VPD_SLX_ID1	0x00	/* READ: Specialix Identifier #1 */
-#define	VPD_SLX_ID2	0x01	/* READ: Specialix Identifier #2 */
-#define	VPD_HW_REV	0x02	/* READ: Hardware Revision */
-#define	VPD_HW_ASSEM	0x03	/* READ: Hardware Assembly Level */
-#define	VPD_UNIQUEID4	0x04	/* READ: Unique Identifier #4 */
-#define	VPD_UNIQUEID3	0x05	/* READ: Unique Identifier #3 */
-#define	VPD_UNIQUEID2	0x06	/* READ: Unique Identifier #2 */
-#define	VPD_UNIQUEID1	0x07	/* READ: Unique Identifier #1 */
-#define	VPD_MANU_YEAR	0x08	/* READ: Year Of Manufacture (0 = 1970) */
-#define	VPD_MANU_WEEK	0x09	/* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define	VPD_HWFEATURE1	0x0A	/* READ: Hardware Feature Byte 1 */
-#define	VPD_HWFEATURE2	0x0B	/* READ: Hardware Feature Byte 2 */
-#define	VPD_HWFEATURE3	0x0C	/* READ: Hardware Feature Byte 3 */
-#define	VPD_HWFEATURE4	0x0D	/* READ: Hardware Feature Byte 4 */
-#define	VPD_HWFEATURE5	0x0E	/* READ: Hardware Feature Byte 5 */
-#define	VPD_OEMID	0x0F	/* READ: OEM Identifier */
-#define	VPD_IDENT	0x10	/* READ: Identifier string (16 bytes) */
-#define	VPD_IDENT_LEN	0x10
-
-/* VPD ROM Definitions... */
-#define	SLX_ID1		0x4D
-#define	SLX_ID2		0x98
-
-#define	PRODUCT_ID(a)	((a>>4)&0xF)	/* Use to obtain Product ID from VPD_UNIQUEID1 */
-
-#define	ID_SX_ISA	0x2
-#define	ID_RIO_EISA	0x3
-#define	ID_SX_PCI	0x5
-#define	ID_SX_EISA	0x7
-#define	ID_RIO_RTA16	0x9
-#define	ID_RIO_ISA	0xA
-#define	ID_RIO_MCA	0xB
-#define	ID_RIO_SBUS	0xC
-#define	ID_RIO_PCI	0xD
-#define	ID_RIO_RTA8	0xE
-
-/* Transputer bootstrap definitions... */
-
-#define	BOOTLOADADDR		(0x8000 - 6)
-#define	BOOTINDICATE		(0x8000 - 2)
-
-/* Firmware load position... */
-
-#define	FIRMWARELOADADDR	0x7C00	/* Firmware is loaded _before_ this address */
-
-/*****************************************************************************
-*****************************                    *****************************
-*****************************   RIO (Rev1) ISA   *****************************
-*****************************                    *****************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_ISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_ISA_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA_CFG_IRQMASK	0x30	/* Interrupt mask */
-#define	  RIO_ISA_CFG_IRQ12	0x10	/* Interrupt Level 12 */
-#define	  RIO_ISA_CFG_IRQ11	0x20	/* Interrupt Level 11 */
-#define	  RIO_ISA_CFG_IRQ9	0x30	/* Interrupt Level 9 */
-#define	RIO_ISA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_ISA_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
-
-/*****************************************************************************
-*****************************                    *****************************
-*****************************   RIO (Rev2) ISA   *****************************
-*****************************                    *****************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA2_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_ISA2_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_ISA2_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_ISA2_CFG_16BIT	0x08	/* 16bit mode, else 8bit */
-#define	RIO_ISA2_CFG_IRQMASK	0x30	/* Interrupt mask */
-#define	  RIO_ISA2_CFG_IRQ15	0x00	/* Interrupt Level 15 */
-#define	  RIO_ISA2_CFG_IRQ12	0x10	/* Interrupt Level 12 */
-#define	  RIO_ISA2_CFG_IRQ11	0x20	/* Interrupt Level 11 */
-#define	  RIO_ISA2_CFG_IRQ9	0x30	/* Interrupt Level 9 */
-#define	RIO_ISA2_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_ISA2_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
-
-/*****************************************************************************
-*****************************                   ******************************
-*****************************   RIO (Jet) ISA   ******************************
-*****************************                   ******************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA3_IDENT	"JET HOST BY KEV#"
-
-#define	RIO_ISA3_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA3_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_ISA32_CFG_IRQMASK	0xF30	/* Interrupt mask */
-#define	  RIO_ISA3_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
-#define	  RIO_ISA3_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
-#define	  RIO_ISA3_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
-#define	  RIO_ISA3_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
-#define	  RIO_ISA3_CFG_IRQ9	0x90	/* Interrupt Level 9 */
-
-/*****************************************************************************
-*********************************             ********************************
-*********************************   RIO MCA   ********************************
-*********************************             ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_MCA_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_MCA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_MCA_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_MCA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   RIO EISA   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-/* EISA Configuration Space Definitions... */
-#define	EISA_PRODUCT_ID1	0xC80
-#define	EISA_PRODUCT_ID2	0xC81
-#define	EISA_PRODUCT_NUMBER	0xC82
-#define	EISA_REVISION_NUMBER	0xC83
-#define	EISA_CARD_ENABLE	0xC84
-#define	EISA_VPD_UNIQUEID4	0xC88	/* READ: Unique Identifier #4 */
-#define	EISA_VPD_UNIQUEID3	0xC8A	/* READ: Unique Identifier #3 */
-#define	EISA_VPD_UNIQUEID2	0xC90	/* READ: Unique Identifier #2 */
-#define	EISA_VPD_UNIQUEID1	0xC92	/* READ: Unique Identifier #1 */
-#define	EISA_VPD_MANU_YEAR	0xC98	/* READ: Year Of Manufacture (0 = 1970) */
-#define	EISA_VPD_MANU_WEEK	0xC9A	/* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define	EISA_MEM_ADDR_23_16	0xC00
-#define	EISA_MEM_ADDR_31_24	0xC01
-#define	EISA_RIO_CONFIG		0xC02	/* WRITE: Configuration Register */
-#define	EISA_RIO_INTSET		0xC03	/* WRITE: Interrupt Set */
-#define	EISA_RIO_INTRESET	0xC03	/* READ:  Interrupt Reset */
-
-/* Control Register Definitions... */
-#define	RIO_EISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_EISA_CFG_LINK20	0x02	/* 20Mbps link, else 10Mbps */
-#define	RIO_EISA_CFG_BUSENABLE	0x04	/* Enable processor bus */
-#define	RIO_EISA_CFG_PROCRUN	0x08	/* Processor running, else reset */
-#define	RIO_EISA_CFG_IRQMASK	0xF0	/* Interrupt mask */
-#define	  RIO_EISA_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
-#define	  RIO_EISA_CFG_IRQ14	0xE0	/* Interrupt Level 14 */
-#define	  RIO_EISA_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
-#define	  RIO_EISA_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
-#define	  RIO_EISA_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
-#define	  RIO_EISA_CFG_IRQ9	0x90	/* Interrupt Level 9 */
-#define	  RIO_EISA_CFG_IRQ7	0x70	/* Interrupt Level 7 */
-#define	  RIO_EISA_CFG_IRQ6	0x60	/* Interrupt Level 6 */
-#define	  RIO_EISA_CFG_IRQ5	0x50	/* Interrupt Level 5 */
-#define	  RIO_EISA_CFG_IRQ4	0x40	/* Interrupt Level 4 */
-#define	  RIO_EISA_CFG_IRQ3	0x30	/* Interrupt Level 3 */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   RIO SBus   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_SBUS_IDENT	"JBPGK#\0\0\0\0\0\0\0\0\0\0"
-
-#define	RIO_SBUS_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_SBUS_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_SBUS_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_SBUS_CFG_IRQMASK	0x38	/* Interrupt mask */
-#define	  RIO_SBUS_CFG_IRQNONE	0x00	/* No Interrupt */
-#define	  RIO_SBUS_CFG_IRQ7	0x38	/* Interrupt Level 7 */
-#define	  RIO_SBUS_CFG_IRQ6	0x30	/* Interrupt Level 6 */
-#define	  RIO_SBUS_CFG_IRQ5	0x28	/* Interrupt Level 5 */
-#define	  RIO_SBUS_CFG_IRQ4	0x20	/* Interrupt Level 4 */
-#define	  RIO_SBUS_CFG_IRQ3	0x18	/* Interrupt Level 3 */
-#define	  RIO_SBUS_CFG_IRQ2	0x10	/* Interrupt Level 2 */
-#define	  RIO_SBUS_CFG_IRQ1	0x08	/* Interrupt Level 1 */
-#define	RIO_SBUS_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_SBUS_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
-
-/*****************************************************************************
-*********************************             ********************************
-*********************************   RIO PCI   ********************************
-*********************************             ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_PCI_IDENT	"ECDDPGJGJHJRGSK#"
-
-#define	RIO_PCI_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_PCI_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_PCI_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_PCI_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_PCI_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
-
-/* PCI Definitions... */
-#define	SPX_VENDOR_ID		0x11CB	/* Assigned by the PCI SIG */
-#define	SPX_DEVICE_ID		0x8000	/* RIO bridge boards */
-#define	SPX_PLXDEVICE_ID	0x2000	/* PLX bridge boards */
-#define	SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
-#define	RIO_SUB_SYS_ID		0x0800	/* RIO PCI board */
-
-/*****************************************************************************
-*****************************                   ******************************
-*****************************   RIO (Jet) PCI   ******************************
-*****************************                   ******************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_PCI2_IDENT	"JET HOST BY KEV#"
-
-#define	RIO_PCI2_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_PCI2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-
-/* PCI Definitions... */
-#define	RIO2_SUB_SYS_ID		0x0100	/* RIO (Jet) PCI board */
-
-#endif						/*_rioboard_h */
-
-/* End of RIOBOARD.H */
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
deleted file mode 100644
index d956dd3..0000000
--- a/drivers/char/rio/rioboot.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioboot.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:36
-**	Retrieved	: 11/6/98 10:33:48
-**
-**  ident @(#)rioboot.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/termios.h>
-#include <linux/serial.h>
-#include <linux/vmalloc.h>
-#include <linux/generic_serial.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP);
-
-static const unsigned char RIOAtVec2Ctrl[] = {
-	/* 0 */ INTERRUPT_DISABLE,
-	/* 1 */ INTERRUPT_DISABLE,
-	/* 2 */ INTERRUPT_DISABLE,
-	/* 3 */ INTERRUPT_DISABLE,
-	/* 4 */ INTERRUPT_DISABLE,
-	/* 5 */ INTERRUPT_DISABLE,
-	/* 6 */ INTERRUPT_DISABLE,
-	/* 7 */ INTERRUPT_DISABLE,
-	/* 8 */ INTERRUPT_DISABLE,
-	/* 9 */ IRQ_9 | INTERRUPT_ENABLE,
-	/* 10 */ INTERRUPT_DISABLE,
-	/* 11 */ IRQ_11 | INTERRUPT_ENABLE,
-	/* 12 */ IRQ_12 | INTERRUPT_ENABLE,
-	/* 13 */ INTERRUPT_DISABLE,
-	/* 14 */ INTERRUPT_DISABLE,
-	/* 15 */ IRQ_15 | INTERRUPT_ENABLE
-};
-
-/**
- *	RIOBootCodeRTA		-	Load RTA boot code
- *	@p: RIO to load
- *	@rbp: Download descriptor
- *
- *	Called when the user process initiates booting of the card firmware.
- *	Lads the firmware
- */
-
-int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp)
-{
-	int offset;
-
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP);
-
-	/*
-	 ** Check that we have set asside enough memory for this
-	 */
-	if (rbp->Count > SIXTY_FOUR_K) {
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n");
-		p->RIOError.Error = HOST_FILE_TOO_LARGE;
-		func_exit();
-		return -ENOMEM;
-	}
-
-	if (p->RIOBooting) {
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n");
-		p->RIOError.Error = BOOT_IN_PROGRESS;
-		func_exit();
-		return -EBUSY;
-	}
-
-	/*
-	 ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
-	 ** so calculate how far we have to move the data up the buffer
-	 ** to achieve this.
-	 */
-	offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE;
-
-	/*
-	 ** Be clean, and clear the 'unused' portion of the boot buffer,
-	 ** because it will (eventually) be part of the Rta run time environment
-	 ** and so should be zeroed.
-	 */
-	memset(p->RIOBootPackets, 0, offset);
-
-	/*
-	 ** Copy the data from user space into the array
-	 */
-
-	if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		func_exit();
-		return -EFAULT;
-	}
-
-	/*
-	 ** Make sure that our copy of the size includes that offset we discussed
-	 ** earlier.
-	 */
-	p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE;
-	p->RIOBootCount = rbp->Count;
-
-	func_exit();
-	return 0;
-}
-
-/**
- *	rio_start_card_running		-	host card start
- *	@HostP: The RIO to kick off
- *
- *	Start a RIO processor unit running. Encapsulates the knowledge
- *	of the card type.
- */
-
-void rio_start_card_running(struct Host *HostP)
-{
-	switch (HostP->Type) {
-	case RIO_AT:
-		rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control);
-		break;
-	case RIO_PCI:
-		/*
-		 ** PCI is much the same as MCA. Everything is once again memory
-		 ** mapped, so we are writing to memory registers instead of io
-		 ** ports.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n");
-		writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control);
-		break;
-	default:
-		rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type);
-		break;
-	}
-	return;
-}
-
-/*
-** Load in the host boot code - load it directly onto all halted hosts
-** of the correct type.
-**
-** Put your rubber pants on before messing with this code - even the magic
-** numbers have trouble understanding what they are doing here.
-*/
-
-int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp)
-{
-	struct Host *HostP;
-	u8 __iomem *Cad;
-	PARM_MAP __iomem *ParmMapP;
-	int RupN;
-	int PortN;
-	unsigned int host;
-	u8 __iomem *StartP;
-	u8 __iomem *DestP;
-	int wait_count;
-	u16 OldParmMap;
-	u16 offset;		/* It is very important that this is a u16 */
-	u8 *DownCode = NULL;
-	unsigned long flags;
-
-	HostP = NULL;		/* Assure the compiler we've initialized it */
-
-
-	/* Walk the hosts */
-	for (host = 0; host < p->RIONumHosts; host++) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host);
-		HostP = &p->RIOHosts[host];
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
-
-		/* Don't boot hosts already running */
-		if ((HostP->Flags & RUN_STATE) != RC_WAITING) {
-			rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host);
-			continue;
-		}
-
-		/*
-		 ** Grab a pointer to the card (ioremapped)
-		 */
-		Cad = HostP->Caddr;
-
-		/*
-		 ** We are going to (try) and load in rbp->Count bytes.
-		 ** The last byte will reside at p->RIOConf.HostLoadBase-1;
-		 ** Therefore, we need to start copying at address
-		 ** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
-		 */
-		StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count];
-
-		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad);
-		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP);
-		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
-		rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count);
-
-		/* Make sure it fits */
-		if (p->RIOConf.HostLoadBase < rbp->Count) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n");
-			p->RIOError.Error = HOST_FILE_TOO_LARGE;
-			func_exit();
-			return -EFBIG;
-		}
-		/*
-		 ** Ensure that the host really is stopped.
-		 ** Disable it's external bus & twang its reset line.
-		 */
-		RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot);
-
-		/*
-		 ** Copy the data directly from user space to the SRAM.
-		 ** This ain't going to be none too clever if the download
-		 ** code is bigger than this segment.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n");
-
-		/* Buffer to local memory as we want to use I/O space and
-		   some cards only do 8 or 16 bit I/O */
-
-		DownCode = vmalloc(rbp->Count);
-		if (!DownCode) {
-			p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
-			func_exit();
-			return -ENOMEM;
-		}
-		if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) {
-			kfree(DownCode);
-			p->RIOError.Error = COPYIN_FAILED;
-			func_exit();
-			return -EFAULT;
-		}
-		HostP->Copy(DownCode, StartP, rbp->Count);
-		vfree(DownCode);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n");
-
-		/*
-		 **                     S T O P !
-		 **
-		 ** Upto this point the code has been fairly rational, and possibly
-		 ** even straight forward. What follows is a pile of crud that will
-		 ** magically turn into six bytes of transputer assembler. Normally
-		 ** you would expect an array or something, but, being me, I have
-		 ** chosen [been told] to use a technique whereby the startup code
-		 ** will be correct if we change the loadbase for the code. Which
-		 ** brings us onto another issue - the loadbase is the *end* of the
-		 ** code, not the start.
-		 **
-		 ** If I were you I wouldn't start from here.
-		 */
-
-		/*
-		 ** We now need to insert a short boot section into
-		 ** the memory at the end of Sram2. This is normally (de)composed
-		 ** of the last eight bytes of the download code. The
-		 ** download has been assembled/compiled to expect to be
-		 ** loaded from 0x7FFF downwards. We have loaded it
-		 ** at some other address. The startup code goes into the small
-		 ** ram window at Sram2, in the last 8 bytes, which are really
-		 ** at addresses 0x7FF8-0x7FFF.
-		 **
-		 ** If the loadbase is, say, 0x7C00, then we need to branch to
-		 ** address 0x7BFE to run the host.bin startup code. We assemble
-		 ** this jump manually.
-		 **
-		 ** The two byte sequence 60 08 is loaded into memory at address
-		 ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
-		 ** which adds '0' to the .O register, complements .O, and then shifts
-		 ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
-		 ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
-		 ** location. Now, the branch starts from the value of .PC (or .IP or
-		 ** whatever the bloody register is called on this chip), and the .PC
-		 ** will be pointing to the location AFTER the branch, in this case
-		 ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
-		 **
-		 ** A long branch is coded at 0x7FF8. This consists of loading a four
-		 ** byte offset into .O using nfix (as above) and pfix operators. The
-		 ** pfix operates in exactly the same way as the nfix operator, but
-		 ** without the complement operation. The offset, of course, must be
-		 ** relative to the address of the byte AFTER the branch instruction,
-		 ** which will be (urm) 0x7FFC, so, our final destination of the branch
-		 ** (loadbase-2), has to be reached from here. Imagine that the loadbase
-		 ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
-		 ** is the first byte of the initial two byte short local branch of the
-		 ** download code).
-		 **
-		 ** To code a jump from 0x7FFC (which is where the branch will start
-		 ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
-		 ** 0x7BFE.
-		 ** This will be coded as four bytes:
-		 ** 60 2C 20 02
-		 ** being nfix .O+0
-		 **        pfix .O+C
-		 **        pfix .O+0
-		 **        jump .O+2
-		 **
-		 ** The nfix operator is used, so that the startup code will be
-		 ** compatible with the whole Tp family. (lies, damn lies, it'll never
-		 ** work in a month of Sundays).
-		 **
-		 ** The nfix nyble is the 1s complement of the nyble value you
-		 ** want to load - in this case we wanted 'F' so we nfix loaded '0'.
-		 */
-
-
-		/*
-		 ** Dest points to the top 8 bytes of Sram2. The Tp jumps
-		 ** to 0x7FFE at reset time, and starts executing. This is
-		 ** a short branch to 0x7FF8, where a long branch is coded.
-		 */
-
-		DestP = &Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
-
-#define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
-#define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
-#define	JUMP(N)	(0x00 | (N))	/* .PC =   .PC + .O      */
-
-		/*
-		 ** 0x7FFC is the address of the location following the last byte of
-		 ** the four byte jump instruction.
-		 ** READ THE ABOVE COMMENTS
-		 **
-		 ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
-		 ** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
-		 ** cos I don't understand 2's complement).
-		 */
-		offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC;
-
-		writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP);
-		writeb(PFIX((offset >> 8) & 0xF), DestP + 1);
-		writeb(PFIX((offset >> 4) & 0xF), DestP + 2);
-		writeb(JUMP(offset & 0xF), DestP + 3);
-
-		writeb(NFIX(0), DestP + 6);
-		writeb(JUMP(8), DestP + 7);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
-		rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset);
-
-		/*
-		 ** Flag what is going on
-		 */
-		HostP->Flags &= ~RUN_STATE;
-		HostP->Flags |= RC_STARTUP;
-
-		/*
-		 ** Grab a copy of the current ParmMap pointer, so we
-		 ** can tell when it has changed.
-		 */
-		OldParmMap = readw(&HostP->__ParmMapR);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap);
-
-		/*
-		 ** And start it running (I hope).
-		 ** As there is nothing dodgy or obscure about the
-		 ** above code, this is guaranteed to work every time.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
-
-		rio_start_card_running(HostP);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n");
-
-		/*
-		 ** Now, wait for upto five seconds for the Tp to setup the parmmap
-		 ** pointer:
-		 */
-		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR));
-			mdelay(100);
-
-		}
-
-		/*
-		 ** If the parmmap pointer is unchanged, then the host code
-		 ** has crashed & burned in a really spectacular way
-		 */
-		if (readw(&HostP->__ParmMapR) == OldParmMap) {
-			rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR));
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n");
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR));
-
-		/*
-		 ** Well, the board thought it was OK, and setup its parmmap
-		 ** pointer. For the time being, we will pretend that this
-		 ** board is running, and check out what the error flag says.
-		 */
-
-		/*
-		 ** Grab a 32 bit pointer to the parmmap structure
-		 */
-		ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR));
-		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-		ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR));
-		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-
-		/*
-		 ** The links entry should be 0xFFFF; we set it up
-		 ** with a mask to say how many PHBs to use, and
-		 ** which links to use.
-		 */
-		if (readw(&ParmMapP->links) != 0xFFFF) {
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
-			rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links));
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		writew(RIO_LINK_ENABLE, &ParmMapP->links);
-
-		/*
-		 ** now wait for the card to set all the parmmap->XXX stuff
-		 ** this is a wait of upto two seconds....
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime);
-		HostP->timeout_id = 0;
-		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n");
-			mdelay(100);
-		}
-		rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n");
-
-		if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) {
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
-			rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n");
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n");
-
-		/*
-		 ** It runs! It runs!
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum);
-
-		/*
-		 ** set the time period between interrupts.
-		 */
-		writew(p->RIOConf.Timer, &ParmMapP->timer);
-
-		/*
-		 ** Translate all the 16 bit pointers in the __ParmMapR into
-		 ** 32 bit pointers for the driver in ioremap space.
-		 */
-		HostP->ParmMapP = ParmMapP;
-		HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr));
-		HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups));
-		HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr));
-		HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr));
-
-		/*
-		 ** point the UnixRups at the real Rups
-		 */
-		for (RupN = 0; RupN < MAX_RUP; RupN++) {
-			HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN];
-			HostP->UnixRups[RupN].Id = RupN + 1;
-			HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
-			spin_lock_init(&HostP->UnixRups[RupN].RupLock);
-		}
-
-		for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) {
-			HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup;
-			HostP->UnixRups[RupN + MAX_RUP].Id = 0;
-			HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT;
-			spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock);
-		}
-
-		/*
-		 ** point the PortP->Phbs at the real Phbs
-		 */
-		for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) {
-			if (p->RIOPortp[PortN]->HostP == HostP) {
-				struct Port *PortP = p->RIOPortp[PortN];
-				struct PHB __iomem *PhbP;
-				/* int oldspl; */
-
-				if (!PortP->Mapped)
-					continue;
-
-				PhbP = &HostP->PhbP[PortP->HostPort];
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-				PortP->PhbP = PhbP;
-
-				PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add));
-				PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start));
-				PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end));
-				PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove));
-				PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start));
-				PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end));
-
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				/*
-				 ** point the UnixRup at the base SysPort
-				 */
-				if (!(PortN % PORTS_PER_RTA))
-					HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
-			}
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n");
-		/*
-		 ** last thing - show the world that everything is in place
-		 */
-		HostP->Flags &= ~RUN_STATE;
-		HostP->Flags |= RC_RUNNING;
-	}
-	/*
-	 ** MPX always uses a poller. This is actually patched into the system
-	 ** configuration and called directly from each clock tick.
-	 **
-	 */
-	p->RIOPolling = 1;
-
-	p->RIOSystemUp++;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec);
-	func_exit();
-	return 0;
-}
-
-
-
-/**
- *	RIOBootRup		-	Boot an RTA
- *	@p: rio we are working with
- *	@Rup: Rup number
- *	@HostP: host object
- *	@PacketP: packet to use
- *
- *	If we have successfully processed this boot, then
- *	return 1. If we havent, then return 0.
- */
-
-int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
-	struct PktCmd_M *PktReplyP;
-	struct CmdBlk *CmdBlkP;
-	unsigned int sequence;
-
-	/*
-	 ** If we haven't been told what to boot, we can't boot it.
-	 */
-	if (p->RIONumBootPkts == 0) {
-		rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n");
-		return 0;
-	}
-
-	/*
-	 ** Special case of boot completed - if we get one of these then we
-	 ** don't need a command block. For all other cases we do, so handle
-	 ** this first and then get a command block, then handle every other
-	 ** case, relinquishing the command block if disaster strikes!
-	 */
-	if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED))
-		return RIOBootComplete(p, HostP, Rup, PktCmdP);
-
-	/*
-	 ** Try to allocate a command block. This is in kernel space
-	 */
-	if (!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n");
-		return 0;
-	}
-
-	/*
-	 ** Fill in the default info on the command block
-	 */
-	CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-
-	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
-	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
-
-	/*
-	 ** process COMMANDS on the boot rup!
-	 */
-	if (readb(&PacketP->len) & PKT_CMD_BIT) {
-		/*
-		 ** We only expect one type of command - a BOOT_REQUEST!
-		 */
-		if (readb(&PktCmdP->Command) != BOOT_REQUEST) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts);
-			RIOFreeCmdBlk(CmdBlkP);
-			return 1;
-		}
-
-		/*
-		 ** Build a Boot Sequence command block
-		 **
-		 ** We no longer need to use "Boot Mode", we'll always allow
-		 ** boot requests - the boot will not complete if the device
-		 ** appears in the bindings table.
-		 **
-		 ** We'll just (always) set the command field in packet reply
-		 ** to allow an attempted boot sequence :
-		 */
-		PktReplyP->Command = BOOT_SEQUENCE;
-
-		PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
-		PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase;
-		PktReplyP->BootSequence.CodeSize = p->RIOBootCount;
-
-		CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
-
-		memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase);
-
-		/*
-		 ** If this host is in slave mode, send the RTA an invalid boot
-		 ** sequence command block to force it to kill the boot. We wait
-		 ** for half a second before sending this packet to prevent the RTA
-		 ** attempting to boot too often. The master host should then grab
-		 ** the RTA and make it its own.
-		 */
-		p->RIOBooting++;
-		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-		return 1;
-	}
-
-	/*
-	 ** It is a request for boot data.
-	 */
-	sequence = readw(&PktCmdP->Sequence);
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup);
-
-	if (sequence >= p->RIONumBootPkts) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts);
-	}
-
-	PktReplyP->Sequence = sequence;
-	memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE);
-	CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
-	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-	return 1;
-}
-
-/**
- *	RIOBootComplete		-	RTA boot is done
- *	@p: RIO we are working with
- *	@HostP: Host structure
- *	@Rup: RUP being used
- *	@PktCmdP: Packet command that was used
- *
- *	This function is called when an RTA been booted.
- *	If booted by a host, HostP->HostUniqueNum is the booting host.
- *	If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
- *	RtaUniq is the booted RTA.
- */
-
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP)
-{
-	struct Map *MapP = NULL;
-	struct Map *MapP2 = NULL;
-	int Flag;
-	int found;
-	int host, rta;
-	int EmptySlot = -1;
-	int entry, entry2;
-	char *MyType, *MyName;
-	unsigned int MyLink;
-	unsigned short RtaType;
-	u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
-
-	p->RIOBooting = 0;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting);
-
-	/*
-	 ** Determine type of unit (16/8 port RTA).
-	 */
-
-	RtaType = GetUnitType(RtaUniq);
-	if (Rup >= (unsigned short) MAX_RUP)
-		rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
-	else
-		rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
-
-	rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq);
-
-	if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n");
-		return 1;
-	}
-
-	/*
-	 ** If this RTA has just booted an RTA which doesn't belong to this
-	 ** system, or the system is in slave mode, do not attempt to create
-	 ** a new table entry for it.
-	 */
-
-	if (!RIOBootOk(p, HostP, RtaUniq)) {
-		MyLink = readb(&PktCmdP->LinkNum);
-		if (Rup < (unsigned short) MAX_RUP) {
-			/*
-			 ** RtaUniq was clone booted (by this RTA). Instruct this RTA
-			 ** to hold off further attempts to boot on this link for 30
-			 ** seconds.
-			 */
-			if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) {
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink);
-			}
-		} else
-			/*
-			 ** RtaUniq was booted by this host. Set the booting link
-			 ** to hold off for 30 seconds to give another unit a
-			 ** chance to boot it.
-			 */
-			writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot);
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum);
-		return 1;
-	}
-
-	/*
-	 ** Check for a SLOT_IN_USE entry for this RTA attached to the
-	 ** current host card in the driver table.
-	 **
-	 ** If it exists, make a note that we have booted it. Other parts of
-	 ** the driver are interested in this information at a later date,
-	 ** in particular when the booting RTA asks for an ID for this unit,
-	 ** we must have set the BOOTED flag, and the NEWBOOT flag is used
-	 ** to force an open on any ports that where previously open on this
-	 ** unit.
-	 */
-	for (entry = 0; entry < MAX_RUP; entry++) {
-		unsigned int sysport;
-
-		if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
-			HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT;
-			if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) {
-				if (sysport < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = sysport;
-				if (sysport > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = sysport;
-				/*
-				 ** For a 16 port RTA, check the second bank of 8 ports
-				 */
-				if (RtaType == TYPE_RTA16) {
-					entry2 = HostP->Mapping[entry].ID2 - 1;
-					HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT;
-					sysport = HostP->Mapping[entry2].SysPort;
-					if (sysport < p->RIOFirstPortsBooted)
-						p->RIOFirstPortsBooted = sysport;
-					if (sysport > p->RIOLastPortsBooted)
-						p->RIOLastPortsBooted = sysport;
-				}
-			}
-			if (RtaType == TYPE_RTA16)
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1);
-			else
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1);
-			return 1;
-		}
-	}
-
-	rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n");
-
-	if (Rup >= (unsigned short) MAX_RUP) {
-		/*
-		 ** It was a host that did the booting
-		 */
-		MyType = "Host";
-		MyName = HostP->Name;
-	} else {
-		/*
-		 ** It was an RTA that did the booting
-		 */
-		MyType = "RTA";
-		MyName = HostP->Mapping[Rup].Name;
-	}
-	MyLink = readb(&PktCmdP->LinkNum);
-
-	/*
-	 ** There is no SLOT_IN_USE entry for this RTA attached to the current
-	 ** host card in the driver table.
-	 **
-	 ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
-	 ** current host card in the driver table.
-	 **
-	 ** If we find one, then we re-use that slot.
-	 */
-	for (entry = 0; entry < MAX_RUP; entry++) {
-		if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
-			if (RtaType == TYPE_RTA16) {
-				entry2 = HostP->Mapping[entry].ID2 - 1;
-				if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq))
-					rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2);
-				else
-					continue;
-			} else
-				rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry);
-			if (!p->RIONoMessage)
-				printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
-			return 1;
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
-	 ** host for this RTA in the driver table.
-	 **
-	 ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
-	 ** entry from the other host and add it to this host (using some of
-	 ** the functions from table.c which do this).
-	 ** For a SLOT_TENTATIVE entry on another host, we must cope with the
-	 ** following scenario:
-	 **
-	 ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
-	 **   in table)
-	 ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
-	 **   entries)
-	 ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
-	 ** + Unplug RTA and plug back into host A.
-	 ** + Configure RTA on host A. We now have the same RTA configured
-	 **   with different ports on two different hosts.
-	 */
-	rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq);
-	found = 0;
-	Flag = 0;		/* Convince the compiler this variable is initialized */
-	for (host = 0; !found && (host < p->RIONumHosts); host++) {
-		for (rta = 0; rta < MAX_RUP; rta++) {
-			if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) {
-				Flag = p->RIOHosts[host].Mapping[rta].Flags;
-				MapP = &p->RIOHosts[host].Mapping[rta];
-				if (RtaType == TYPE_RTA16) {
-					MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name);
-				} else
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name);
-				found = 1;
-				break;
-			}
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
-	 ** another host for this RTA in the driver table...
-	 **
-	 ** Check for a SLOT_IN_USE entry for this RTA in the config table.
-	 */
-	if (!MapP) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq);
-		for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum);
-
-			if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) {
-				MapP = &p->RIOSavedTable[rta];
-				Flag = p->RIOSavedTable[rta].Flags;
-				if (RtaType == TYPE_RTA16) {
-					for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) {
-						if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
-							break;
-					}
-					MapP2 = &p->RIOSavedTable[entry2];
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2);
-				} else
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta);
-				break;
-			}
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** We may have found a SLOT_IN_USE entry on another host for this
-	 ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
-	 ** on another host for this RTA in the driver table.
-	 **
-	 ** Check the driver table for room to fit this newly discovered RTA.
-	 ** RIOFindFreeID() first looks for free slots and if it does not
-	 ** find any free slots it will then attempt to oust any
-	 ** tentative entry in the table.
-	 */
-	EmptySlot = 1;
-	if (RtaType == TYPE_RTA16) {
-		if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) {
-			RIODefaultName(p, HostP, entry);
-			rio_fill_host_slot(entry, entry2, RtaUniq, HostP);
-			EmptySlot = 0;
-		}
-	} else {
-		if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) {
-			RIODefaultName(p, HostP, entry);
-			rio_fill_host_slot(entry, 0, RtaUniq, HostP);
-			EmptySlot = 0;
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** If we found a SLOT_IN_USE entry on another host for this
-	 ** RTA in the config or driver table, and there are enough free
-	 ** slots in the driver table, then we need to move it over and
-	 ** delete it from the other host.
-	 ** If we found a SLOT_TENTATIVE entry on another host for this
-	 ** RTA in the driver table, just delete the other host entry.
-	 */
-	if (EmptySlot == 0) {
-		if (MapP) {
-			if (Flag & SLOT_IN_USE) {
-				rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n");
-				HostP->Mapping[entry].SysPort = MapP->SysPort;
-				memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN);
-				HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
-				RIOReMapPorts(p, HostP, &HostP->Mapping[entry]);
-				if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
-				if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
-				rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name);
-			} else {
-				rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n");
-				HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
-			}
-			if (RtaType == TYPE_RTA16) {
-				if (Flag & SLOT_IN_USE) {
-					HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-					HostP->Mapping[entry2].SysPort = MapP2->SysPort;
-					/*
-					 ** Map second block of ttys for 16 port RTA
-					 */
-					RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]);
-					if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
-						p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
-					if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
-						p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
-					rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name);
-				} else
-					HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-				memset(MapP2, 0, sizeof(struct Map));
-			}
-			memset(MapP, 0, sizeof(struct Map));
-			if (!p->RIONoMessage)
-				printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A');
-		} else if (!p->RIONoMessage)
-			printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
-		RIOSetChange(p);
-		return 1;
-	}
-
-	/*
-	 ** There is no room in the driver table to make an entry for the
-	 ** booted RTA. Keep a note of its Uniq Num in the overflow table,
-	 ** so we can ignore it's ID requests.
-	 */
-	if (!p->RIONoMessage)
-		printk("The RTA connected to %s '%s' (%c) cannot be configured.  You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A');
-	for (entry = 0; entry < HostP->NumExtraBooted; entry++) {
-		if (HostP->ExtraUnits[entry] == RtaUniq) {
-			/*
-			 ** already got it!
-			 */
-			return 1;
-		}
-	}
-	/*
-	 ** If there is room, add the unit to the list of extras
-	 */
-	if (HostP->NumExtraBooted < MAX_EXTRA_UNITS)
-		HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
-	return 1;
-}
-
-
-/*
-** If the RTA or its host appears in the RIOBindTab[] structure then
-** we mustn't boot the RTA and should return 0.
-** This operation is slightly different from the other drivers for RIO
-** in that this is designed to work with the new utilities
-** not config.rio and is FAR SIMPLER.
-** We no longer support the RIOBootMode variable. It is all done from the
-** "boot/noboot" field in the rio.cf file.
-*/
-int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq)
-{
-	int Entry;
-	unsigned int HostUniq = HostP->UniqueNum;
-
-	/*
-	 ** Search bindings table for RTA or its parent.
-	 ** If it exists, return 0, else 1.
-	 */
-	for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) {
-		if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq))
-			return 0;
-	}
-	return 1;
-}
-
-/*
-** Make an empty slot tentative. If this is a 16 port RTA, make both
-** slots tentative, and the second one RTA_SECOND_SLOT as well.
-*/
-
-void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host)
-{
-	int link;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq);
-
-	host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
-	host->Mapping[entry].SysPort = NO_PORT;
-	host->Mapping[entry].RtaUniqueNum = rta_uniq;
-	host->Mapping[entry].HostUniqueNum = host->UniqueNum;
-	host->Mapping[entry].ID = entry + 1;
-	host->Mapping[entry].ID2 = 0;
-	if (entry2) {
-		host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT);
-		host->Mapping[entry2].SysPort = NO_PORT;
-		host->Mapping[entry2].RtaUniqueNum = rta_uniq;
-		host->Mapping[entry2].HostUniqueNum = host->UniqueNum;
-		host->Mapping[entry2].Name[0] = '\0';
-		host->Mapping[entry2].ID = entry2 + 1;
-		host->Mapping[entry2].ID2 = entry + 1;
-		host->Mapping[entry].ID2 = entry2 + 1;
-	}
-	/*
-	 ** Must set these up, so that utilities show
-	 ** topology of 16 port RTAs correctly
-	 */
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
-		host->Mapping[entry].Topology[link].Link = NO_LINK;
-		if (entry2) {
-			host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
-			host->Mapping[entry2].Topology[link].Link = NO_LINK;
-		}
-	}
-}
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
deleted file mode 100644
index f121357..0000000
--- a/drivers/char/rio/riocmd.c
+++ /dev/null
@@ -1,939 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  ported from the existing SCO driver source
-**
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riocmd.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:41
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)riocmd.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-
-
-static struct IdentifyRta IdRta;
-static struct KillNeighbour KillUnit;
-
-int RIOFoadRta(struct Host *HostP, struct Map *MapP)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = MapP->ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = IFOAD;
-	CmdBlkP->Packet.data[1] = 0;
-	CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOZombieRta(struct Host *HostP, struct Map *MapP)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = MapP->ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = ZOMBIE;
-	CmdBlkP->Packet.data[1] = 0;
-	CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP))
-{
-	unsigned int Host;
-
-	rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func);
-
-	if (!RtaUnique)
-		return (0);
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		unsigned int Rta;
-		struct Host *HostP = &p->RIOHosts[Host];
-
-		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
-			struct Map *MapP = &HostP->Mapping[Rta];
-
-			if (MapP->RtaUniqueNum == RtaUnique) {
-				uint Link;
-
-				/*
-				 ** now, lets just check we have a route to it...
-				 ** IF the routing stuff is working, then one of the
-				 ** topology entries for this unit will have a legit
-				 ** route *somewhere*. We care not where - if its got
-				 ** any connections, we can get to it.
-				 */
-				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
-					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
-						/*
-						 ** Its worth trying the operation...
-						 */
-						return (*func) (HostP, MapP);
-					}
-				}
-			}
-		}
-	}
-	return -ENXIO;
-}
-
-
-int RIOIdentifyRta(struct rio_info *p, void __user * arg)
-{
-	unsigned int Host;
-
-	if (copy_from_user(&IdRta, arg, sizeof(IdRta))) {
-		rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		return -EFAULT;
-	}
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		unsigned int Rta;
-		struct Host *HostP = &p->RIOHosts[Host];
-
-		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
-			struct Map *MapP = &HostP->Mapping[Rta];
-
-			if (MapP->RtaUniqueNum == IdRta.RtaUnique) {
-				uint Link;
-				/*
-				 ** now, lets just check we have a route to it...
-				 ** IF the routing stuff is working, then one of the
-				 ** topology entries for this unit will have a legit
-				 ** route *somewhere*. We care not where - if its got
-				 ** any connections, we can get to it.
-				 */
-				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
-					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
-						/*
-						 ** Its worth trying the operation...
-						 */
-						struct CmdBlk *CmdBlkP;
-
-						rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");
-
-						CmdBlkP = RIOGetCmdBlk();
-
-						if (!CmdBlkP) {
-							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
-							return -ENXIO;
-						}
-
-						CmdBlkP->Packet.dest_unit = MapP->ID;
-						CmdBlkP->Packet.dest_port = BOOT_RUP;
-						CmdBlkP->Packet.src_unit = 0;
-						CmdBlkP->Packet.src_port = BOOT_RUP;
-						CmdBlkP->Packet.len = 0x84;
-						CmdBlkP->Packet.data[0] = IDENTIFY;
-						CmdBlkP->Packet.data[1] = 0;
-						CmdBlkP->Packet.data[2] = IdRta.ID;
-
-						if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
-							return -EIO;
-						}
-						return 0;
-					}
-				}
-			}
-		}
-	}
-	return -ENOENT;
-}
-
-
-int RIOKillNeighbour(struct rio_info *p, void __user * arg)
-{
-	uint Host;
-	uint ID;
-	struct Host *HostP;
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
-
-	if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) {
-		rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		return -EFAULT;
-	}
-
-	if (KillUnit.Link > 3)
-		return -ENXIO;
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = 0;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = UFOAD;
-	CmdBlkP->Packet.data[1] = KillUnit.Link;
-	CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		ID = 0;
-		HostP = &p->RIOHosts[Host];
-
-		if (HostP->UniqueNum == KillUnit.UniqueNum) {
-			if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
-				return -EIO;
-			}
-			return 0;
-		}
-
-		for (ID = 0; ID < RTAS_PER_HOST; ID++) {
-			if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {
-				CmdBlkP->Packet.dest_unit = ID + 1;
-				if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {
-					rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
-					return -EIO;
-				}
-				return 0;
-			}
-		}
-	}
-	RIOFreeCmdBlk(CmdBlkP);
-	return -ENXIO;
-}
-
-int RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = IWAIT;
-	CmdBlkP->Packet.data[1] = Link;
-	CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOFoadWakeup(struct rio_info *p)
-{
-	int port;
-	struct Port *PortP;
-	unsigned long flags;
-
-	for (port = 0; port < RIO_PORTS; port++) {
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->Config = 0;
-		PortP->State = 0;
-		PortP->InUse = NOT_INUSE;
-		PortP->PortState = 0;
-		PortP->FlushCmdBodge = 0;
-		PortP->ModemLines = 0;
-		PortP->ModemState = 0;
-		PortP->CookMode = 0;
-		PortP->ParamSem = 0;
-		PortP->Mapped = 0;
-		PortP->WflushFlag = 0;
-		PortP->MagicFlags = 0;
-		PortP->RxDataStart = 0;
-		PortP->TxBufferIn = 0;
-		PortP->TxBufferOut = 0;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	}
-	return (0);
-}
-
-/*
-** Incoming command on the COMMAND_RUP to be processed.
-*/
-static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data;
-	struct Port *PortP;
-	struct UnixRup *UnixRupP;
-	unsigned short SysPort;
-	unsigned short ReportedModemStatus;
-	unsigned short rup;
-	unsigned short subCommand;
-	unsigned long flags;
-
-	func_enter();
-
-	/*
-	 ** 16 port RTA note:
-	 ** Command rup packets coming from the RTA will have pkt->data[1] (which
-	 ** translates to PktCmdP->PhbNum) set to the host port number for the
-	 ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
-	 ** we can use PhbNum to get the rup number for the appropriate 8 port
-	 ** block (for the first block, this should be equal to 'Rup').
-	 */
-	rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA;
-	UnixRupP = &HostP->UnixRups[rup];
-	SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA);
-	rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
-
-	if (UnixRupP->BaseSysPort == NO_PORT) {
-		rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
-		rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
-		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
-		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);
-
-		if (Rup < (unsigned short) MAX_RUP) {
-			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
-		} else
-			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
-
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum));
-		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command));
-		return 1;
-	}
-	PortP = p->RIOPortp[SysPort];
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	switch (readb(&PktCmdP->Command)) {
-	case RIOC_BREAK_RECEIVED:
-		rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
-		/* If the current line disc. is not multi-threading and
-		   the current processor is not the default, reset rup_intr
-		   and return 0 to ensure that the command packet is
-		   not freed. */
-		/* Call tmgr HANGUP HERE */
-		/* Fix this later when every thing works !!!! RAMRAJ */
-		gs_got_break(&PortP->gs);
-		break;
-
-	case RIOC_COMPLETE:
-		rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts);
-		subCommand = 1;
-		switch (readb(&PktCmdP->SubCommand)) {
-		case RIOC_MEMDUMP:
-			rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr));
-			break;
-		case RIOC_READ_REGISTER:
-			rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr));
-			p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST);
-			break;
-		default:
-			subCommand = 0;
-			break;
-		}
-		if (subCommand)
-			break;
-		rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState);
-		if (PortP->PortState != readb(&PktCmdP->PortStatus)) {
-			rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");
-			PortP->PortState = readb(&PktCmdP->PortStatus);
-			/* What should we do here ...
-			   wakeup( &PortP->PortState );
-			 */
-		} else
-			rio_dprintk(RIO_DEBUG_CMD, "No change\n");
-
-		/* FALLTHROUGH */
-	case RIOC_MODEM_STATUS:
-		/*
-		 ** Knock out the tbusy and tstop bits, as these are not relevant
-		 ** to the check for modem status change (they're just there because
-		 ** it's a convenient place to put them!).
-		 */
-		ReportedModemStatus = readb(&PktCmdP->ModemStatus);
-		if ((PortP->ModemState & RIOC_MSVR1_HOST) ==
-				(ReportedModemStatus & RIOC_MSVR1_HOST)) {
-			rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
-			/*
-			 ** Update ModemState just in case tbusy or tstop states have
-			 ** changed.
-			 */
-			PortP->ModemState = ReportedModemStatus;
-		} else {
-			rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);
-			PortP->ModemState = ReportedModemStatus;
-#ifdef MODEM_SUPPORT
-			if (PortP->Mapped) {
-				/***********************************************************\
-				*************************************************************
-				***													   ***
-				***		  M O D E M   S T A T E   C H A N G E		  ***
-				***													   ***
-				*************************************************************
-				\***********************************************************/
-				/*
-				 ** If the device is a modem, then check the modem
-				 ** carrier.
-				 */
-				if (PortP->gs.port.tty == NULL)
-					break;
-				if (PortP->gs.port.tty->termios == NULL)
-					break;
-
-				if (!(PortP->gs.port.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) {
-
-					rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n");
-					/*
-					 ** Is there a carrier?
-					 */
-					if (PortP->ModemState & RIOC_MSVR1_CD) {
-						/*
-						 ** Has carrier just appeared?
-						 */
-						if (!(PortP->State & RIO_CARR_ON)) {
-							rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n");
-							PortP->State |= RIO_CARR_ON;
-							/*
-							 ** wakeup anyone in WOPEN
-							 */
-							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN))
-								wake_up_interruptible(&PortP->gs.port.open_wait);
-						}
-					} else {
-						/*
-						 ** Has carrier just dropped?
-						 */
-						if (PortP->State & RIO_CARR_ON) {
-							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN))
-								tty_hangup(PortP->gs.port.tty);
-							PortP->State &= ~RIO_CARR_ON;
-							rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n");
-						}
-					}
-				}
-			}
-#endif
-		}
-		break;
-
-	default:
-		rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts);
-		break;
-	}
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	func_exit();
-
-	return 1;
-}
-
-/*
-** The command mechanism:
-**	Each rup has a chain of commands associated with it.
-**	This chain is maintained by routines in this file.
-**	Periodically we are called and we run a quick check of all the
-**	active chains to determine if there is a command to be executed,
-**	and if the rup is ready to accept it.
-**
-*/
-
-/*
-** Allocate an empty command block.
-*/
-struct CmdBlk *RIOGetCmdBlk(void)
-{
-	struct CmdBlk *CmdBlkP;
-
-	CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
-	return CmdBlkP;
-}
-
-/*
-** Return a block to the head of the free list.
-*/
-void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
-{
-	kfree(CmdBlkP);
-}
-
-/*
-** attach a command block to the list of commands to be performed for
-** a given rup.
-*/
-int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
-{
-	struct CmdBlk **Base;
-	struct UnixRup *UnixRupP;
-	unsigned long flags;
-
-	if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) {
-		rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
-		RIOFreeCmdBlk(CmdBlkP);
-		return RIO_FAIL;
-	}
-
-	UnixRupP = &HostP->UnixRups[Rup];
-
-	rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-
-	/*
-	 ** If the RUP is currently inactive, then put the request
-	 ** straight on the RUP....
-	 */
-	if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
-																	     : 1)) {
-		rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]);
-
-		/*
-		 ** Whammy! blat that pack!
-		 */
-		HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
-
-		/*
-		 ** place command packet on the pending position.
-		 */
-		UnixRupP->CmdPendingP = CmdBlkP;
-
-		/*
-		 ** set the command register
-		 */
-		writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
-
-		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-
-		return 0;
-	}
-	rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n");
-
-	if (UnixRupP->CmdsWaitingP != NULL)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n");
-	if (UnixRupP->CmdPendingP != NULL)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n");
-	if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
-
-	Base = &UnixRupP->CmdsWaitingP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base);
-
-	while (*Base) {
-		rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base);
-		Base = &((*Base)->NextP);
-		rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base);
-	}
-
-	rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base);
-
-	*Base = CmdBlkP;
-
-	CmdBlkP->NextP = NULL;
-
-	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-
-	return 0;
-}
-
-/*
-** Here we go - if there is an empty rup, fill it!
-** must be called at splrio() or higher.
-*/
-void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
-{
-	struct CmdBlk *CmdBlkP;
-	struct UnixRup *UnixRupP;
-	struct PKT __iomem *PacketP;
-	unsigned short Rup;
-	unsigned long flags;
-
-
-	Rup = MAX_RUP + LINKS_PER_UNIT;
-
-	do {			/* do this loop for each RUP */
-		/*
-		 ** locate the rup we are processing & lock it
-		 */
-		UnixRupP = &HostP->UnixRups[--Rup];
-
-		spin_lock_irqsave(&UnixRupP->RupLock, flags);
-
-		/*
-		 ** First check for incoming commands:
-		 */
-		if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
-			int FreeMe;
-
-			PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));
-
-			switch (readb(&PacketP->dest_port)) {
-			case BOOT_RUP:
-				rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0]));
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			case COMMAND_RUP:
-				/*
-				 ** Free the RUP lock as loss of carrier causes a
-				 ** ttyflush which will (eventually) call another
-				 ** routine that uses the RUP lock.
-				 */
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
-				if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) {
-					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
-					rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
-				}
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			case ROUTE_RUP:
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			default:
-				rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port));
-				FreeMe = 1;
-				break;
-			}
-
-			if (FreeMe) {
-				rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
-				put_free_end(HostP, PacketP);
-
-				writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol);
-
-				if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
-					rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
-					writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake);
-				}
-			}
-		}
-
-		/*
-		 ** IF a command was running on the port,
-		 ** and it has completed, then tidy it up.
-		 */
-		if ((CmdBlkP = UnixRupP->CmdPendingP) &&	/* ASSIGN! */
-		    (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
-			/*
-			 ** we are idle.
-			 ** there is a command in pending.
-			 ** Therefore, this command has finished.
-			 ** So, wakeup whoever is waiting for it (and tell them
-			 ** what happened).
-			 */
-			if (CmdBlkP->Packet.dest_port == BOOT_RUP)
-				rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);
-
-			rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP);
-
-			/*
-			 ** Clear the Rup lock to prevent mutual exclusion.
-			 */
-			if (CmdBlkP->PostFuncP) {
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-			}
-
-			/*
-			 ** ....clear the pending flag....
-			 */
-			UnixRupP->CmdPendingP = NULL;
-
-			/*
-			 ** ....and return the command block to the freelist.
-			 */
-			RIOFreeCmdBlk(CmdBlkP);
-		}
-
-		/*
-		 ** If there is a command for this rup, and the rup
-		 ** is idle, then process the command
-		 */
-		if ((CmdBlkP = UnixRupP->CmdsWaitingP) &&	/* ASSIGN! */
-		    (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
-			/*
-			 ** if the pre-function is non-zero, call it.
-			 ** If it returns RIO_FAIL then don't
-			 ** send this command yet!
-			 */
-			if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) {
-				rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP);
-			} else {
-				rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]);
-				/*
-				 ** Whammy! blat that pack!
-				 */
-				HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
-
-				/*
-				 ** remove the command from the rup command queue...
-				 */
-				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
-
-				/*
-				 ** ...and place it on the pending position.
-				 */
-				UnixRupP->CmdPendingP = CmdBlkP;
-
-				/*
-				 ** set the command register
-				 */
-				writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
-
-				/*
-				 ** the command block will be freed
-				 ** when the command has been processed.
-				 */
-			}
-		}
-		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-	} while (Rup);
-}
-
-int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	PortP->WflushFlag++;
-	PortP->MagicFlags |= MAGIC_FLUSH;
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return RIOUnUse(iPortP, CmdBlkP);
-}
-
-int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	struct PKT __iomem *PacketP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	while (can_remove_receive(&PacketP, PortP)) {
-		remove_receive(PortP);
-		put_free_end(PortP->HostP, PacketP);
-	}
-
-	if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) {
-		/*
-		 ** MAGIC! (Basically, handshake the RX buffer, so that
-		 ** the RTAs upstream can be re-enabled.)
-		 */
-		rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
-		writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
-	}
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return RIOUnUse(iPortP, CmdBlkP);
-}
-
-int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
-
-	if (PortP->InUse) {
-		if (--PortP->InUse != NOT_INUSE) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return 0;
-		}
-	}
-	/*
-	 ** While PortP->InUse is set (i.e. a preemptive command has been sent to
-	 ** the RTA and is awaiting completion), any transmit data is prevented from
-	 ** being transferred from the write queue into the transmit packets
-	 ** (add_transmit) and no furthur transmit interrupt will be sent for that
-	 ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
-	 ** twice a second as a saftey measure). This was the case when kermit was
-	 ** used to send data into a RIO port. After each packet was sent, TCFLSH
-	 ** was called to flush the read queue preemptively. PortP->InUse was
-	 ** incremented, thereby blocking the 6 byte acknowledgement packet
-	 ** transmitted back. This acknowledgment hung around for 500ms before
-	 ** being sent, thus reducing input performance substantially!.
-	 ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
-	 ** hanging around in the transmit buffer is sent immediately.
-	 */
-	writew(1, &PortP->HostP->ParmMapP->tx_intr);
-	/* What to do here ..
-	   wakeup( (caddr_t)&(PortP->InUse) );
-	 */
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return 0;
-}
-
-/*
-** 
-** How to use this file:
-** 
-** To send a command down a rup, you need to allocate a command block, fill
-** in the packet information, fill in the command number, fill in the pre-
-** and post- functions and arguments, and then add the command block to the
-** queue of command blocks for the port in question. When the port is idle,
-** then the pre-function will be called. If this returns RIO_FAIL then the
-** command will be re-queued and tried again at a later date (probably in one
-** clock tick). If the pre-function returns NOT RIO_FAIL, then the command
-** packet will be queued on the RUP, and the txcontrol field set to the
-** command number. When the txcontrol field has changed from being the
-** command number, then the post-function will be called, with the argument
-** specified earlier, a pointer to the command block, and the value of
-** txcontrol.
-** 
-** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer
-** to the command block structure allocated, or NULL if there aren't any.
-** The block will have been zeroed for you.
-** 
-** The structure has the following fields:
-** 
-** struct CmdBlk
-** {
-**	 struct CmdBlk *NextP;		  ** Pointer to next command block   **
-**	 struct PKT	 Packet;		** A packet, to copy to the rup	**
-**			int	 (*PreFuncP)();  ** The func to call to check if OK **
-**			int	 PreArg;		** The arg for the func			**
-**			int	 (*PostFuncP)(); ** The func to call when completed **
-**			int	 PostArg;	   ** The arg for the func			**
-** };
-** 
-** You need to fill in ALL fields EXCEPT NextP, which is used to link the
-** blocks together either on the free list or on the Rup list.
-** 
-** Packet is an actual packet structure to be filled in with the packet
-** information associated with the command. You need to fill in everything,
-** as the command processor doesn't process the command packet in any way.
-** 
-** The PreFuncP is called before the packet is enqueued on the host rup.
-** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
-** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL
-** if the packet is NOT to be queued.
-** 
-** The PostFuncP is called when the command has completed. It is called
-** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected
-** to return a value. PostFuncP does NOT need to free the command block,
-** as this happens automatically after PostFuncP returns.
-** 
-** Once the command block has been filled in, it is attached to the correct
-** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is
-** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer
-** to it!), and CmdBlkP is the pointer to the command block allocated using
-** RIOGetCmdBlk().
-** 
-*/
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
deleted file mode 100644
index 7805063..0000000
--- a/drivers/char/rio/rioctrl.c
+++ /dev/null
@@ -1,1504 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioctrl.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:42
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)rioctrl.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-
-
-static struct LpbReq LpbReq;
-static struct RupReq RupReq;
-static struct PortReq PortReq;
-static struct HostReq HostReq;	/* oh really?  global?  and no locking? */
-static struct HostDpRam HostDpRam;
-static struct DebugCtrl DebugCtrl;
-static struct Map MapEnt;
-static struct PortSetup PortSetup;
-static struct DownLoad DownLoad;
-static struct SendPack SendPack;
-/* static struct StreamInfo	StreamInfo; */
-/* static char modemtable[RIO_PORTS]; */
-static struct SpecialRupCmd SpecialRupCmd;
-static struct PortParams PortParams;
-static struct portStats portStats;
-
-static struct SubCmdStruct {
-	ushort Host;
-	ushort Rup;
-	ushort Port;
-	ushort Addr;
-} SubCmd;
-
-struct PortTty {
-	uint port;
-	struct ttystatics Tty;
-};
-
-static struct PortTty PortTty;
-typedef struct ttystatics TERMIO;
-
-/*
-** This table is used when the config.rio downloads bin code to the
-** driver. We index the table using the product code, 0-F, and call
-** the function pointed to by the entry, passing the information
-** about the boot.
-** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
-** process to bog off.
-*/
-static int
- (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
-					/* 0 */ RIOBootCodeHOST,
-					/* Host Card */
-					/* 1 */ RIOBootCodeRTA,
-					/* RTA */
-};
-
-#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
-
-static int copy_from_io(void __user *to, void __iomem *from, size_t size)
-{
-	void *buf = kmalloc(size, GFP_KERNEL);
-	int res = -ENOMEM;
-	if (buf) {
-		rio_memcpy_fromio(buf, from, size);
-		res = copy_to_user(to, buf, size);
-		kfree(buf);
-	}
-	return res;
-}
-
-int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su)
-{
-	uint Host;		/* leave me unsigned! */
-	uint port;		/* and me! */
-	struct Host *HostP;
-	ushort loop;
-	int Entry;
-	struct Port *PortP;
-	struct PKT __iomem *PacketP;
-	int retval = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	func_enter();
-
-	/* Confuse the compiler to think that we've initialized these */
-	Host = 0;
-	PortP = NULL;
-
-	rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp);
-
-	switch (cmd) {
-		/*
-		 ** RIO_SET_TIMER
-		 **
-		 ** Change the value of the host card interrupt timer.
-		 ** If the host card number is -1 then all host cards are changed
-		 ** otherwise just the specified host card will be changed.
-		 */
-	case RIO_SET_TIMER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg);
-		{
-			int host, value;
-			host = (arg >> 16) & 0x0000FFFF;
-			value = arg & 0x0000ffff;
-			if (host == -1) {
-				for (host = 0; host < p->RIONumHosts; host++) {
-					if (p->RIOHosts[host].Flags == RC_RUNNING) {
-						writew(value, &p->RIOHosts[host].ParmMapP->timer);
-					}
-				}
-			} else if (host >= p->RIONumHosts) {
-				return -EINVAL;
-			} else {
-				if (p->RIOHosts[host].Flags == RC_RUNNING) {
-					writew(value, &p->RIOHosts[host].ParmMapP->timer);
-				}
-			}
-		}
-		return 0;
-
-	case RIO_FOAD_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
-		return RIOCommandRta(p, arg, RIOFoadRta);
-
-	case RIO_ZOMBIE_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
-		return RIOCommandRta(p, arg, RIOZombieRta);
-
-	case RIO_IDENTIFY_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
-		return RIOIdentifyRta(p, argp);
-
-	case RIO_KILL_NEIGHBOUR:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
-		return RIOKillNeighbour(p, argp);
-
-	case SPECIAL_RUP_CMD:
-		{
-			struct CmdBlk *CmdBlkP;
-
-			rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
-			if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
-				p->RIOError.Error = COPYIN_FAILED;
-				return -EFAULT;
-			}
-			CmdBlkP = RIOGetCmdBlk();
-			if (!CmdBlkP) {
-				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
-				return -ENXIO;
-			}
-			CmdBlkP->Packet = SpecialRupCmd.Packet;
-			if (SpecialRupCmd.Host >= p->RIONumHosts)
-				SpecialRupCmd.Host = 0;
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
-			if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
-				printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n");
-			}
-			return 0;
-		}
-
-	case RIO_DEBUG_MEM:
-		return -EPERM;
-
-	case RIO_ALL_MODEM:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
-		p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
-		return -EINVAL;
-
-	case RIO_GET_TABLE:
-		/*
-		 ** Read the routing table from the device driver to user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
-
-		if ((retval = RIOApel(p)) != 0)
-			return retval;
-
-		if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-
-		{
-			int entry;
-			rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
-			for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-				if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
-					continue;
-
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
-			}
-			rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
-		}
-		p->RIOQuickCheck = NOT_CHANGED;	/* a table has been gotten */
-		return 0;
-
-	case RIO_PUT_TABLE:
-		/*
-		 ** Write the routing table to the device driver from user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-/*
-***********************************
-				{
-					int entry;
-					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
-					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
-					{
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
-					}
-					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
-				}
-***********************************
-*/
-		return RIONewTable(p);
-
-	case RIO_GET_BINDINGS:
-		/*
-		 ** Send bindings table, containing unique numbers of RTAs owned
-		 ** by this system to user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_PUT_BINDINGS:
-		/*
-		 ** Receive a bindings table, containing unique numbers of RTAs owned
-		 ** by this system
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_BIND_RTA:
-		{
-			int EmptySlot = -1;
-			/*
-			 ** Bind this RTA to host, so that it will be booted by
-			 ** host in 'boot owned RTAs' mode.
-			 */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
-
-			if (!su) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
-				p->RIOError.Error = NOT_SUPER_USER;
-				return -EPERM;
-			}
-			for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
-				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
-					EmptySlot = Entry;
-				else if (p->RIOBindTab[Entry] == arg) {
-					/*
-					 ** Already exists - delete
-					 */
-					p->RIOBindTab[Entry] = 0L;
-					rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg);
-					return 0;
-				}
-			}
-			/*
-			 ** Dosen't exist - add
-			 */
-			if (EmptySlot != -1) {
-				p->RIOBindTab[EmptySlot] = arg;
-				rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg);
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg);
-				return -ENOMEM;
-			}
-			return 0;
-		}
-
-	case RIO_RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
-		port = arg;
-		if ((port < 0) || (port > 511)) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		PortP = p->RIOPortp[port];
-		if (!PortP->Mapped) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
-			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
-			return -EINVAL;
-		}
-		if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
-			return -EINVAL;
-		}
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) ==
-				RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
-			PortP->State |= RIO_BUSY;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_ASSIGN_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIOAssignRta(p, &MapEnt);
-
-	case RIO_CHANGE_NAME:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIOChangeName(p, &MapEnt);
-
-	case RIO_DELETE_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIODeleteRta(p, &MapEnt);
-
-	case RIO_QUICK_CHECK:
-		if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_LAST_ERROR:
-		if (copy_to_user(argp, &p->RIOError, sizeof(struct Error)))
-			return -EFAULT;
-		return 0;
-
-	case RIO_GET_LOG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
-		return -EINVAL;
-
-	case RIO_GET_MODTYPE:
-		if (copy_from_user(&port, argp, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
-		if (port < 0 || port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		PortP = (p->RIOPortp[port]);
-		if (!PortP->Mapped) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
-			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
-			return -EINVAL;
-		}
-		/*
-		 ** Return module type of port
-		 */
-		port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
-		if (copy_to_user(argp, &port, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return (0);
-	case RIO_BLOCK_OPENS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
-		for (Entry = 0; Entry < RIO_PORTS; Entry++) {
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			p->RIOPortp[Entry]->WaitUntilBooted = 1;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		}
-		return 0;
-
-	case RIO_SETUP_PORTS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
-		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
-			return -EFAULT;
-		}
-		if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
-			return -ENXIO;
-		}
-		if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
-			p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
-			return -EINVAL;
-		}
-		if (!p->RIOPortp) {
-			printk(KERN_ERR "rio: No p->RIOPortp array!\n");
-			rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
-		for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
-			rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
-		rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
-		return retval;
-
-	case RIO_GET_PORT_SETUP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
-		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortSetup.From >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		port = PortSetup.To = PortSetup.From;
-		PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
-		PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
-		PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
-		PortSetup.Store = p->RIOPortp[port]->Store;
-		PortSetup.Lock = p->RIOPortp[port]->Lock;
-		PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
-		memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN);
-		memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN);
-		PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
-		PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
-
-		if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_GET_PORT_PARAMS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
-		if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortParams.Port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortParams.Port]);
-		PortParams.Config = PortP->Config;
-		PortParams.State = PortP->State;
-		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
-
-		if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_GET_PORT_TTY:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
-		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortTty.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
-		PortP = (p->RIOPortp[PortTty.port]);
-		if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_PORT_TTY:
-		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
-		if (PortTty.port >= (ushort) RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortTty.port]);
-		RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM,
-				OK_TO_SLEEP);
-		return retval;
-
-	case RIO_SET_PORT_PARAMS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
-		if (copy_from_user(&PortParams, argp, sizeof(PortParams))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortParams.Port >= (ushort) RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortParams.Port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->Config = PortParams.Config;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_GET_PORT_STATS:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
-		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[portStats.port]);
-		portStats.gather = PortP->statsGather;
-		portStats.txchars = PortP->txchars;
-		portStats.rxchars = PortP->rxchars;
-		portStats.opens = PortP->opens;
-		portStats.closes = PortP->closes;
-		portStats.ioctls = PortP->ioctls;
-		if (copy_to_user(argp, &portStats, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_RESET_PORT_STATS:
-		port = arg;
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
-		if (port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->txchars = 0;
-		PortP->rxchars = 0;
-		PortP->opens = 0;
-		PortP->closes = 0;
-		PortP->ioctls = 0;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_GATHER_PORT_STATS:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
-		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[portStats.port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->statsGather = portStats.gather;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_READ_CONFIG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
-		if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_CONFIG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
-		if (!su) {
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		/*
-		 ** move a few value around
-		 */
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
-				writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer);
-		return retval;
-
-	case RIO_START_POLLER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
-		return -EINVAL;
-
-	case RIO_STOP_POLLER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
-		if (!su) {
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		p->RIOPolling = NOT_POLLING;
-		return retval;
-
-	case RIO_SETDEBUG:
-	case RIO_GETDEBUG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
-		if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (DebugCtrl.SysPort == NO_PORT) {
-			if (cmd == RIO_SETDEBUG) {
-				if (!su) {
-					p->RIOError.Error = NOT_SUPER_USER;
-					return -EPERM;
-				}
-				p->rio_debug = DebugCtrl.Debug;
-				p->RIODebugWait = DebugCtrl.Wait;
-				rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
-				DebugCtrl.Debug = p->rio_debug;
-				DebugCtrl.Wait = p->RIODebugWait;
-				if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
-					rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
-					p->RIOError.Error = COPYOUT_FAILED;
-					return -EFAULT;
-				}
-			}
-		} else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		} else if (cmd == RIO_SETDEBUG) {
-			if (!su) {
-				p->RIOError.Error = NOT_SUPER_USER;
-				return -EPERM;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
-			DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
-			if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
-				p->RIOError.Error = COPYOUT_FAILED;
-				return -EFAULT;
-			}
-		}
-		return retval;
-
-	case RIO_VERSID:
-		/*
-		 ** Enquire about the release and version.
-		 ** We return MAX_VERSION_LEN bytes, being a
-		 ** textual null terminated string.
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
-		if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_NUM_HOSTS:
-		/*
-		 ** Enquire as to the number of hosts located
-		 ** at init time.
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
-		if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_FOAD:
-		/*
-		 ** Kill host. This may not be in the final version...
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg);
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		p->RIOHalted = 1;
-		p->RIOSystemUp = 0;
-
-		for (Host = 0; Host < p->RIONumHosts; Host++) {
-			(void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
-			memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags));
-			p->RIOHosts[Host].Flags = RC_WAITING;
-		}
-		RIOFoadWakeup(p);
-		p->RIONumBootPkts = 0;
-		p->RIOBooting = 0;
-		printk("HEEEEELP!\n");
-
-		for (loop = 0; loop < RIO_PORTS; loop++) {
-			spin_lock_init(&p->RIOPortp[loop]->portSem);
-			p->RIOPortp[loop]->InUse = NOT_INUSE;
-		}
-
-		p->RIOSystemUp = 0;
-		return retval;
-
-	case RIO_DOWNLOAD:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
-
-		/*
-		 ** It is important that the product code is an unsigned object!
-		 */
-		if (DownLoad.ProductCode >= MAX_PRODUCT) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
-			p->RIOError.Error = NO_SUCH_PRODUCT;
-			return -ENXIO;
-		}
-		/*
-		 ** do something!
-		 */
-		retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
-		/* <-- Panic */
-		p->RIOHalted = 0;
-		/*
-		 ** and go back, content with a job well completed.
-		 */
-		return retval;
-
-	case RIO_PARMS:
-		{
-			unsigned int host;
-
-			if (copy_from_user(&host, argp, sizeof(host))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
-				p->RIOError.Error = COPYIN_FAILED;
-				return -EFAULT;
-			}
-			/*
-			 ** Fetch the parmmap
-			 */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
-			if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
-				p->RIOError.Error = COPYOUT_FAILED;
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
-				return -EFAULT;
-			}
-		}
-		return retval;
-
-	case RIO_HOST_REQ:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
-		if (copy_from_user(&HostReq, argp, sizeof(HostReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (HostReq.HostNum >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
-
-		if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_DPRAM:
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
-		if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (HostDpRam.HostNum >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
-
-		if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
-			int off;
-			/* It's hardware like this that really gets on my tits. */
-			static unsigned char copy[sizeof(struct DpRam)];
-			for (off = 0; off < sizeof(struct DpRam); off++)
-				copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off);
-			if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {
-				p->RIOError.Error = COPYOUT_FAILED;
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
-				return -EFAULT;
-			}
-		} else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_BUSY:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
-		if (arg > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		p->RIOPortp[arg]->State |= RIO_BUSY;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_HOST_PORT:
-		/*
-		 ** The daemon want port information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
-		if (copy_from_user(&PortReq, argp, sizeof(PortReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-
-		if (PortReq.SysPort >= RIO_PORTS) {	/* SysPort is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
-		if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_RUP:
-		/*
-		 ** The daemon want rup information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
-		if (copy_from_user(&RupReq, argp, sizeof(RupReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (RupReq.HostNum >= p->RIONumHosts) {	/* host is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) {	/* eek! */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		HostP = &p->RIOHosts[RupReq.HostNum];
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
-			p->RIOError.Error = HOST_NOT_RUNNING;
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
-
-		if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_LPB:
-		/*
-		 ** The daemon want lpb information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
-		if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (LpbReq.Host >= p->RIONumHosts) {	/* host is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		if (LpbReq.Link >= LINKS_PER_UNIT) {	/* eek! */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
-			p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		HostP = &p->RIOHosts[LpbReq.Host];
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
-			p->RIOError.Error = HOST_NOT_RUNNING;
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
-
-		if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-		/*
-		 ** Here 3 IOCTL's that allow us to change the way in which
-		 ** rio logs errors. send them just to syslog or send them
-		 ** to both syslog and console or send them to just the console.
-		 **
-		 ** See RioStrBuf() in util.c for the other half.
-		 */
-	case RIO_SYSLOG_ONLY:
-		p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */
-		return 0;
-
-	case RIO_SYSLOG_CONS:
-		p->RIOPrintLogState = PRINT_TO_LOG_CONS;	/* syslog and console */
-		return 0;
-
-	case RIO_CONS_ONLY:
-		p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */
-		return 0;
-
-	case RIO_SIGNALS_ON:
-		if (p->RIOSignalProcess) {
-			p->RIOError.Error = SIGNALS_ALREADY_SET;
-			return -EBUSY;
-		}
-		/* FIXME: PID tracking */
-		p->RIOSignalProcess = current->pid;
-		p->RIOPrintDisabled = DONT_PRINT;
-		return retval;
-
-	case RIO_SIGNALS_OFF:
-		if (p->RIOSignalProcess != current->pid) {
-			p->RIOError.Error = NOT_RECEIVING_PROCESS;
-			return -EPERM;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
-		p->RIOSignalProcess = 0;
-		return retval;
-
-	case RIO_SET_BYTE_MODE:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
-		return retval;
-
-	case RIO_SET_WORD_MODE:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode |= WORD_OPERATION;
-		return retval;
-
-	case RIO_SET_FAST_BUS:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode |= FAST_AT_BUS;
-		return retval;
-
-	case RIO_SET_SLOW_BUS:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
-		return retval;
-
-	case RIO_MAP_B50_TO_50:
-	case RIO_MAP_B50_TO_57600:
-	case RIO_MAP_B110_TO_110:
-	case RIO_MAP_B110_TO_115200:
-		rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
-		port = arg;
-		if (port < 0 || port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		switch (cmd) {
-		case RIO_MAP_B50_TO_50:
-			p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
-			break;
-		case RIO_MAP_B50_TO_57600:
-			p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
-			break;
-		case RIO_MAP_B110_TO_110:
-			p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
-			break;
-		case RIO_MAP_B110_TO_115200:
-			p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
-			break;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_STREAM_INFO:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
-		return -EINVAL;
-
-	case RIO_SEND_PACKET:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
-		if (copy_from_user(&SendPack, argp, sizeof(SendPack))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (SendPack.PortNum >= 128) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		PortP = p->RIOPortp[SendPack.PortNum];
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (!can_add_transmit(&PacketP, PortP)) {
-			p->RIOError.Error = UNIT_IS_IN_USE;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -ENOSPC;
-		}
-
-		for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
-			writeb(SendPack.Data[loop], &PacketP->data[loop]);
-
-		writeb(SendPack.Len, &PacketP->len);
-
-		add_transmit(PortP);
-		/*
-		 ** Count characters transmitted for port statistics reporting
-		 */
-		if (PortP->statsGather)
-			PortP->txchars += (SendPack.Len & 127);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_NO_MESG:
-		if (su)
-			p->RIONoMessage = 1;
-		return su ? 0 : -EPERM;
-
-	case RIO_MESG:
-		if (su)
-			p->RIONoMessage = 0;
-		return su ? 0 : -EPERM;
-
-	case RIO_WHAT_MESG:
-		if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_MEM_DUMP:
-		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
-
-		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Host >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
-
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else
-			PortP->State |= RIO_BUSY;
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_TICK:
-		if (arg >= p->RIONumHosts)
-			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg);
-		writeb(0xFF, &p->RIOHosts[arg].SetInt);
-		return 0;
-
-	case RIO_TOCK:
-		if (arg >= p->RIONumHosts)
-			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg);
-		writeb(0xFF, &p->RIOHosts[arg].ResetInt);
-		return 0;
-
-	case RIO_READ_CHECK:
-		/* Check reads for pkts with data[0] the same */
-		p->RIOReadCheck = !p->RIOReadCheck;
-		if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_READ_REGISTER:
-		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
-
-		if (SubCmd.Port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Host >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) ==
-				RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else
-			PortP->State |= RIO_BUSY;
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-		/*
-		 ** rio_make_dev: given port number (0-511) ORed with port type
-		 ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
-		 ** value to pass to mknod to create the correct device node.
-		 */
-	case RIO_MAKE_DEV:
-		{
-			unsigned int port = arg & RIO_MODEM_MASK;
-			unsigned int ret;
-
-			switch (arg & RIO_DEV_MASK) {
-			case RIO_DEV_DIRECT:
-				ret = drv_makedev(MAJOR(dev), port);
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);
-				return ret;
-			case RIO_DEV_MODEM:
-				ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret);
-				return ret;
-			case RIO_DEV_XPRINT:
-				ret = drv_makedev(MAJOR(dev), port);
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret);
-				return ret;
-			}
-			rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
-			return -EINVAL;
-		}
-		/*
-		 ** rio_minor: given a dev_t from a stat() call, return
-		 ** the port number (0-511) ORed with the port type
-		 ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
-		 */
-	case RIO_MINOR:
-		{
-			dev_t dv;
-			int mino;
-			unsigned long ret;
-
-			dv = (dev_t) (arg);
-			mino = RIO_UNMODEM(dv);
-
-			if (RIO_ISMODEM(dv)) {
-				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
-				ret = mino | RIO_DEV_MODEM;
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
-				ret = mino | RIO_DEV_DIRECT;
-			}
-			return ret;
-		}
-	}
-	rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
-	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
-
-	func_exit();
-	return -EINVAL;
-}
-
-/*
-** Pre-emptive commands go on RUPs and are only one byte long.
-*/
-int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
-{
-	struct CmdBlk *CmdBlkP;
-	struct PktCmd_M *PktCmdP;
-	int Ret;
-	ushort rup;
-	int port;
-
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
-		return RIO_FAIL;
-	}
-
-	if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
-			!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
-			"for command %d on port %d\n", Cmd, PortP->PortNum);
-		return RIO_FAIL;
-	}
-
-	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
-			CmdBlkP, PortP->InUse);
-
-	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
-
-	CmdBlkP->Packet.src_unit = 0;
-	if (PortP->SecondBlock)
-		rup = PortP->ID2;
-	else
-		rup = PortP->RupNum;
-	CmdBlkP->Packet.dest_unit = rup;
-	CmdBlkP->Packet.src_port = COMMAND_RUP;
-	CmdBlkP->Packet.dest_port = COMMAND_RUP;
-	CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
-	CmdBlkP->PostFuncP = RIOUnUse;
-	CmdBlkP->PostArg = (unsigned long) PortP;
-	PktCmdP->Command = Cmd;
-	port = PortP->HostPort % (ushort) PORTS_PER_RTA;
-	/*
-	 ** Index ports 8-15 for 2nd block of 16 port RTA.
-	 */
-	if (PortP->SecondBlock)
-		port += (ushort) PORTS_PER_RTA;
-	PktCmdP->PhbNum = port;
-
-	switch (Cmd) {
-	case RIOC_MEMDUMP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
-				"(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
-		PktCmdP->SubCommand = RIOC_MEMDUMP;
-		PktCmdP->SubAddr = SubCmd.Addr;
-		break;
-	case RIOC_FCLOSE:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
-				CmdBlkP);
-		break;
-	case RIOC_READ_REGISTER:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
-				"command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
-		PktCmdP->SubCommand = RIOC_READ_REGISTER;
-		PktCmdP->SubAddr = SubCmd.Addr;
-		break;
-	case RIOC_RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
-				CmdBlkP);
-		break;
-	case RIOC_RFLUSH:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
-				CmdBlkP);
-		CmdBlkP->PostFuncP = RIORFlushEnable;
-		break;
-	case RIOC_SUSPEND:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
-				CmdBlkP);
-		break;
-
-	case RIOC_MGET:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
-				CmdBlkP);
-		break;
-
-	case RIOC_MSET:
-	case RIOC_MBIC:
-	case RIOC_MBIS:
-		CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
-				"blk %p\n", CmdBlkP);
-		break;
-
-	case RIOC_WFLUSH:
-		/*
-		 ** If we have queued up the maximum number of Write flushes
-		 ** allowed then we should not bother sending any more to the
-		 ** RTA.
-		 */
-		if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
-					"WflushFlag about to wrap!");
-			RIOFreeCmdBlk(CmdBlkP);
-			return (RIO_FAIL);
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
-					"blk %p\n", CmdBlkP);
-			CmdBlkP->PostFuncP = RIOWFlushMark;
-		}
-		break;
-	}
-
-	PortP->InUse++;
-
-	Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
-
-	return Ret;
-}
diff --git a/drivers/char/rio/riodrvr.h b/drivers/char/rio/riodrvr.h
deleted file mode 100644
index 0907e71..0000000
--- a/drivers/char/rio/riodrvr.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riodrvr.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 09:22:46
-**	Retrieved	: 11/6/98 09:22:46
-**
-**  ident @(#)riodrvr.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __riodrvr_h
-#define __riodrvr_h
-
-#include <asm/param.h>		/* for HZ */
-
-#define MEMDUMP_SIZE	32
-#define	MOD_DISABLE	(RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT)
-
-
-struct rio_info {
-	int mode;		/* Intr or polled, word/byte */
-	spinlock_t RIOIntrSem;	/* Interrupt thread sem */
-	int current_chan;	/* current channel */
-	int RIOFailed;		/* Not initialised ? */
-	int RIOInstallAttempts;	/* no. of rio-install() calls */
-	int RIOLastPCISearch;	/* status of last search */
-	int RIONumHosts;	/* Number of RIO Hosts */
-	struct Host *RIOHosts;	/* RIO Host values */
-	struct Port **RIOPortp;	/* RIO port values */
-/*
-** 02.03.1999 ARG - ESIL 0820 fix
-** We no longer use RIOBootMode
-**
-	int			RIOBootMode;		* RIO boot mode *
-**
-*/
-	int RIOPrintDisabled;	/* RIO printing disabled ? */
-	int RIOPrintLogState;	/* RIO printing state ? */
-	int RIOPolling;		/* Polling ? */
-/*
-** 09.12.1998 ARG - ESIL 0776 part fix
-** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
-** The fix for this ESIL introduces another member (RIORtaDisCons) here to be
-** updated in RIOConCon() - to keep track of RTA connections/disconnections.
-** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
-*/
-	int RIOHalted;		/* halted ? */
-	int RIORtaDisCons;	/* RTA connections/disconnections */
-	unsigned int RIOReadCheck;	/* Rio read check */
-	unsigned int RIONoMessage;	/* To display message or not */
-	unsigned int RIONumBootPkts;	/* how many packets for an RTA */
-	unsigned int RIOBootCount;	/* size of RTA code */
-	unsigned int RIOBooting;	/* count of outstanding boots */
-	unsigned int RIOSystemUp;	/* Booted ?? */
-	unsigned int RIOCounting;	/* for counting interrupts */
-	unsigned int RIOIntCount;	/* # of intr since last check */
-	unsigned int RIOTxCount;	/* number of xmit intrs  */
-	unsigned int RIORxCount;	/* number of rx intrs */
-	unsigned int RIORupCount;	/* number of rup intrs */
-	int RIXTimer;
-	int RIOBufferSize;	/* Buffersize */
-	int RIOBufferMask;	/* Buffersize */
-
-	int RIOFirstMajor;	/* First host card's major no */
-
-	unsigned int RIOLastPortsMapped;	/* highest port number known */
-	unsigned int RIOFirstPortsMapped;	/* lowest port number known */
-
-	unsigned int RIOLastPortsBooted;	/* highest port number running */
-	unsigned int RIOFirstPortsBooted;	/* lowest port number running */
-
-	unsigned int RIOLastPortsOpened;	/* highest port number running */
-	unsigned int RIOFirstPortsOpened;	/* lowest port number running */
-
-	/* Flag to say that the topology information has been changed. */
-	unsigned int RIOQuickCheck;
-	unsigned int CdRegister;	/* ??? */
-	int RIOSignalProcess;	/* Signalling process */
-	int rio_debug;		/* To debug ... */
-	int RIODebugWait;	/* For what ??? */
-	int tpri;		/* Thread prio */
-	int tid;		/* Thread id */
-	unsigned int _RIO_Polled;	/* Counter for polling */
-	unsigned int _RIO_Interrupted;	/* Counter for interrupt */
-	int intr_tid;		/* iointset return value */
-	int TxEnSem;		/* TxEnable Semaphore */
-
-
-	struct Error RIOError;	/* to Identify what went wrong */
-	struct Conf RIOConf;	/* Configuration ??? */
-	struct ttystatics channel[RIO_PORTS];	/* channel information */
-	char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)]
-	    [RTA_BOOT_DATA_SIZE];
-	struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
-	struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
-
-	/* RTA to host binding table for master/slave operation */
-	unsigned long RIOBindTab[MAX_RTA_BINDINGS];
-	/* RTA memory dump variable */
-	unsigned char RIOMemDump[MEMDUMP_SIZE];
-	struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
-
-};
-
-
-#ifdef linux
-#define debug(x)        printk x
-#else
-#define debug(x)	kkprintf x
-#endif
-
-
-
-#define RIO_RESET_INT	0x7d80
-
-#endif				/* __riodrvr.h */
diff --git a/drivers/char/rio/rioinfo.h b/drivers/char/rio/rioinfo.h
deleted file mode 100644
index 42ff1e7..0000000
--- a/drivers/char/rio/rioinfo.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioinfo.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 14:07:49
-**	Retrieved	: 11/6/98 14:07:50
-**
-**  ident @(#)rioinfo.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rioinfo_h
-#define __rioinfo_h
-
-/*
-** Host card data structure
-*/
-struct RioHostInfo {
-	long location;		/* RIO Card Base I/O address */
-	long vector;		/* RIO Card IRQ vector */
-	int bus;		/* ISA/EISA/MCA/PCI */
-	int mode;		/* pointer to host mode - INTERRUPT / POLLED */
-	struct old_sgttyb
-	*Sg;			/* pointer to default term characteristics */
-};
-
-
-/* Mode in rio device info */
-#define INTERRUPTED_MODE	0x01	/* Interrupt is generated */
-#define POLLED_MODE		0x02	/* No interrupt */
-#define AUTO_MODE		0x03	/* Auto mode */
-
-#define WORD_ACCESS_MODE	0x10	/* Word Access Mode */
-#define BYTE_ACCESS_MODE	0x20	/* Byte Access Mode */
-
-
-/* Bus type that RIO supports */
-#define ISA_BUS			0x01	/* The card is ISA */
-#define EISA_BUS		0x02	/* The card is EISA */
-#define MCA_BUS			0x04	/* The card is MCA */
-#define PCI_BUS			0x08	/* The card is PCI */
-
-/*
-** 11.11.1998 ARG - ESIL ???? part fix
-** Moved definition for 'CHAN' here from rioinfo.c (it is now
-** called 'DEF_TERM_CHARACTERISTICS').
-*/
-
-#define DEF_TERM_CHARACTERISTICS \
-{ \
-	B19200, B19200,				/* input and output speed */ \
-	'H' - '@',				/* erase char */ \
-	-1,					/* 2nd erase char */ \
-	'U' - '@',				/* kill char */ \
-	ECHO | CRMOD,				/* mode */ \
-	'C' - '@',				/* interrupt character */ \
-	'\\' - '@',				/* quit char */ \
-	'Q' - '@',				/* start char */ \
-	'S' - '@',				/* stop char */ \
-	'D' - '@',				/* EOF */ \
-	-1,					/* brk */ \
-	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ \
-	'Z' - '@',				/* process stop */ \
-	'Y' - '@',				/* delayed stop */ \
-	'R' - '@',				/* reprint line */ \
-	'O' - '@',				/* flush output */ \
-	'W' - '@',				/* word erase */ \
-	'V' - '@'				/* literal next char */ \
-}
-
-#endif				/* __rioinfo_h */
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
deleted file mode 100644
index 24a282b..0000000
--- a/drivers/char/rio/rioinit.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioinit.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:43
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)rioinit.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "rio_linux.h"
-
-int RIOPCIinit(struct rio_info *p, int Mode);
-
-static int RIOScrub(int, u8 __iomem *, int);
-
-
-/**
-** RIOAssignAT :
-**
-** Fill out the fields in the p->RIOHosts structure now we know we know
-** we have a board present.
-**
-** bits < 0 indicates 8 bit operation requested,
-** bits > 0 indicates 16 bit operation.
-*/
-
-int RIOAssignAT(struct rio_info *p, int	Base, void __iomem *virtAddr, int mode)
-{
-	int		bits;
-	struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr;
-
-	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
-		bits = BYTE_OPERATION;
-	else
-		bits = WORD_OPERATION;
-
-	/*
-	** Board has passed its scrub test. Fill in all the
-	** transient stuff.
-	*/
-	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
-	p->RIOHosts[p->RIONumHosts].CardP	= virtAddr;
-
-	/*
-	** Revision 01 AT host cards don't support WORD operations,
-	*/
-	if (readb(&cardp->DpRevision) == 01)
-		bits = BYTE_OPERATION;
-
-	p->RIOHosts[p->RIONumHosts].Type = RIO_AT;
-	p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card;
-											/* set this later */
-	p->RIOHosts[p->RIONumHosts].Slot = -1;
-	p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits;
-	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE ,
-		&p->RIOHosts[p->RIONumHosts].Control);
-	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE,
-		&p->RIOHosts[p->RIONumHosts].Control);
-	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-	p->RIOHosts[p->RIONumHosts].UniqueNum =
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-	p->RIONumHosts++;
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
-	return(1);
-}
-
-static	u8	val[] = {
-#ifdef VERY_LONG_TEST
-	  0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
-	  0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 
-#endif
-	  0xff, 0x00, 0x00 };
-
-#define	TEST_END sizeof(val)
-
-/*
-** RAM test a board. 
-** Nothing too complicated, just enough to check it out.
-*/
-int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot)
-{
-	struct DpRam __iomem *DpRam = caddr;
-	void __iomem *ram[4];
-	int  size[4];
-	int  op, bank;
-	int  nbanks;
-
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n",
-			type, DpRam, slot);
-
-	RIOHostReset(type, DpRam, slot);
-
-	/*
-	** Scrub the memory. This comes in several banks:
-	** DPsram1	- 7000h bytes
-	** DPsram2	- 200h  bytes
-	** DPsram3	- 7000h bytes
-	** scratch	- 1000h bytes
-	*/
-
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n");
-
-	size[0] = DP_SRAM1_SIZE;
-	size[1] = DP_SRAM2_SIZE;
-	size[2] = DP_SRAM3_SIZE;
-	size[3] = DP_SCRATCH_SIZE;
-
-	ram[0] = DpRam->DpSram1;
-	ram[1] = DpRam->DpSram2;
-	ram[2] = DpRam->DpSram3;
-	nbanks = (type == RIO_PCI) ? 3 : 4;
-	if (nbanks == 4)
-		ram[3] = DpRam->DpScratch;
-
-
-	if (nbanks == 3) {
-		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n",
-				ram[0], size[0], ram[1], size[1], ram[2], size[2]);
-	} else {
-		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n",
-				ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]);
-	}
-
-	/*
-	** This scrub operation will test for crosstalk between
-	** banks. TEST_END is a magic number, and relates to the offset
-	** within the 'val' array used by Scrub.
-	*/
-	for (op=0; op<TEST_END; op++) {
-		for (bank=0; bank<nbanks; bank++) {
-			if (RIOScrub(op, ram[bank], size[bank]) == RIO_FAIL) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 
-							bank, op);
-				return RIO_FAIL;
-			}
-		}
-	}
-
-	rio_dprintk (RIO_DEBUG_INIT, "Test completed\n");
-	return 0;
-}
-
-
-/*
-** Scrub an area of RAM.
-** Define PRETEST and POSTTEST for a more thorough checking of the
-** state of the memory.
-** Call with op set to an index into the above 'val' array to determine
-** which value will be written into memory.
-** Call with op set to zero means that the RAM will not be read and checked
-** before it is written.
-** Call with op not zero and the RAM will be read and compared with val[op-1]
-** to check that the data from the previous phase was retained.
-*/
-
-static int RIOScrub(int op, u8 __iomem *ram, int size)
-{
-	int off;
-	unsigned char	oldbyte;
-	unsigned char	newbyte;
-	unsigned char	invbyte;
-	unsigned short	oldword;
-	unsigned short	newword;
-	unsigned short	invword;
-	unsigned short	swapword;
-
-	if (op) {
-		oldbyte = val[op-1];
-		oldword = oldbyte | (oldbyte<<8);
-	} else
-	  oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */
-	newbyte = val[op];
-	newword = newbyte | (newbyte<<8);
-	invbyte = ~newbyte;
-	invword = invbyte | (invbyte<<8);
-
-	/*
-	** Check that the RAM contains the value that should have been left there
-	** by the previous test (not applicable for pass zero)
-	*/
-	if (op) {
-		for (off=0; off<size; off++) {
-			if (readb(ram + off) != oldbyte) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
-				return RIO_FAIL;
-			}
-		}
-		for (off=0; off<size; off+=2) {
-			if (readw(ram + off) != oldword) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword, readw(ram + off));
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
-				return RIO_FAIL;
-			}
-		}
-	}
-
-	/*
-	** Now write the INVERSE of the test data into every location, using
-	** BYTE write operations, first checking before each byte is written
-	** that the location contains the old value still, and checking after
-	** the write that the location contains the data specified - this is
-	** the BYTE read/write test.
-	*/
-	for (off=0; off<size; off++) {
-		if (op && (readb(ram + off) != oldbyte)) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-		writeb(invbyte, ram + off);
-		if (readb(ram + off) != invbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** now, use WORD operations to write the test value into every location,
-	** check as before that the location contains the previous test value
-	** before overwriting, and that it contains the data value written
-	** afterwards.
-	** This is the WORD operation test.
-	*/
-	for (off=0; off<size; off+=2) {
-		if (readw(ram + off) != invword) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
-			return RIO_FAIL;
-		}
-
-		writew(newword, ram + off);
-		if ( readw(ram + off) != newword ) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** now run through the block of memory again, first in byte mode
-	** then in word mode, and check that all the locations contain the
-	** required test data.
-	*/
-	for (off=0; off<size; off++) {
-		if (readb(ram + off) != newbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-	}
-
-	for (off=0; off<size; off+=2) {
-		if (readw(ram + off) != newword ) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** time to check out byte swapping errors
-	*/
-	swapword = invbyte | (newbyte << 8);
-
-	for (off=0; off<size; off+=2) {
-		writeb(invbyte, &ram[off]);
-		writeb(newbyte, &ram[off+1]);
-	}
-
-	for ( off=0; off<size; off+=2 ) {
-		if (readw(ram + off) != swapword) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-		writew(~swapword, ram + off);
-	}
-
-	for (off=0; off<size; off+=2) {
-		if (readb(ram + off) != newbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-		if (readb(ram + off + 1) != invbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-		writew(newword, ram + off);
-	}
-	return 0;
-}
-
-
-int RIODefaultName(struct rio_info *p, struct Host *HostP, unsigned int	UnitId)
-{
-	memcpy(HostP->Mapping[UnitId].Name, "UNKNOWN RTA X-XX", 17);
-	HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
-	if ((UnitId+1) > 9) {
-		HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10);
-		HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10);
-	}
-	else {
-		HostP->Mapping[UnitId].Name[14]='1'+UnitId;
-		HostP->Mapping[UnitId].Name[15]=0;
-	}
-	return 0;
-}
-
-#define RIO_RELEASE	"Linux"
-#define RELEASE_ID	"1.0"
-
-static struct rioVersion	stVersion;
-
-struct rioVersion *RIOVersid(void)
-{
-    strlcpy(stVersion.version, "RIO driver for linux V1.0",
-	    sizeof(stVersion.version));
-    strlcpy(stVersion.buildDate, __DATE__,
-	    sizeof(stVersion.buildDate));
-
-    return &stVersion;
-}
-
-void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot)
-{
-	/*
-	** Reset the Tpu
-	*/
-	rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: type 0x%x", Type);
-	switch ( Type ) {
-	case RIO_AT:
-		rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION |
-			SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(3);
-			rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: Don't know if it worked. Try reset again\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE |
-			BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(3);
-		break;
-	case RIO_PCI:
-		rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
-		writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetInt);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(100);
-		break;
-	default:
-		rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
-		break;
-	}
-	return;
-}
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
deleted file mode 100644
index 2e71aec..0000000
--- a/drivers/char/rio/riointr.c
+++ /dev/null
@@ -1,645 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riointr.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:44
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)riointr.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-#include <linux/delay.h>
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-
-
-static void RIOReceive(struct rio_info *, struct Port *);
-
-
-static char *firstchars(char *p, int nch)
-{
-	static char buf[2][128];
-	static int t = 0;
-	t = !t;
-	memcpy(buf[t], p, nch);
-	buf[t][nch] = 0;
-	return buf[t];
-}
-
-
-#define	INCR( P, I )	((P) = (((P)+(I)) & p->RIOBufferMask))
-/* Enable and start the transmission of packets */
-void RIOTxEnable(char *en)
-{
-	struct Port *PortP;
-	struct rio_info *p;
-	struct tty_struct *tty;
-	int c;
-	struct PKT __iomem *PacketP;
-	unsigned long flags;
-
-	PortP = (struct Port *) en;
-	p = (struct rio_info *) PortP->p;
-	tty = PortP->gs.port.tty;
-
-
-	rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
-
-	if (!PortP->gs.xmit_cnt)
-		return;
-
-
-	/* This routine is an order of magnitude simpler than the specialix
-	   version. One of the disadvantages is that this version will send
-	   an incomplete packet (usually 64 bytes instead of 72) once for
-	   every 4k worth of data. Let's just say that this won't influence
-	   performance significantly..... */
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	while (can_add_transmit(&PacketP, PortP)) {
-		c = PortP->gs.xmit_cnt;
-		if (c > PKT_MAX_DATA_LEN)
-			c = PKT_MAX_DATA_LEN;
-
-		/* Don't copy past the end of the source buffer */
-		if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
-			c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
-
-		{
-			int t;
-			t = (c > 10) ? 10 : c;
-
-			rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
-		}
-		/* If for one reason or another, we can't copy more data,
-		   we're done! */
-		if (c == 0)
-			break;
-
-		rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
-		/*    udelay (1); */
-
-		writeb(c, &(PacketP->len));
-		if (!(PortP->State & RIO_DELETED)) {
-			add_transmit(PortP);
-			/*
-			 ** Count chars tx'd for port statistics reporting
-			 */
-			if (PortP->statsGather)
-				PortP->txchars += c;
-		}
-		PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
-		PortP->gs.xmit_cnt -= c;
-	}
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN))
-		tty_wakeup(PortP->gs.port.tty);
-
-}
-
-
-/*
-** RIO Host Service routine. Does all the work traditionally associated with an
-** interrupt.
-*/
-static int RupIntr;
-static int RxIntr;
-static int TxIntr;
-
-void RIOServiceHost(struct rio_info *p, struct Host *HostP)
-{
-	rio_spin_lock(&HostP->HostLock);
-	if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-		static int t = 0;
-		rio_spin_unlock(&HostP->HostLock);
-		if ((t++ % 200) == 0)
-			rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
-		return;
-	}
-	rio_spin_unlock(&HostP->HostLock);
-
-	if (readw(&HostP->ParmMapP->rup_intr)) {
-		writew(0, &HostP->ParmMapP->rup_intr);
-		p->RIORupCount++;
-		RupIntr++;
-		rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts);
-		RIOPollHostCommands(p, HostP);
-	}
-
-	if (readw(&HostP->ParmMapP->rx_intr)) {
-		int port;
-
-		writew(0, &HostP->ParmMapP->rx_intr);
-		p->RIORxCount++;
-		RxIntr++;
-
-		rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts);
-		/*
-		 ** Loop through every port. If the port is mapped into
-		 ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
-		 ** worth checking. If the port isn't open, grab any packets
-		 ** hanging on its receive queue and stuff them on the free
-		 ** list; check for commands on the way.
-		 */
-		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
-			struct Port *PortP = p->RIOPortp[port];
-			struct tty_struct *ttyP;
-			struct PKT __iomem *PacketP;
-
-			/*
-			 ** not mapped in - most of the RIOPortp[] information
-			 ** has not been set up!
-			 ** Optimise: ports come in bundles of eight.
-			 */
-			if (!PortP->Mapped) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** If the host board isn't THIS host board, check the next one.
-			 ** optimise: ports come in bundles of eight.
-			 */
-			if (PortP->HostP != HostP) {
-				port += 7;
-				continue;
-			}
-
-			/*
-			 ** Let us see - is the port open? If not, then don't service it.
-			 */
-			if (!(PortP->PortState & PORT_ISOPEN)) {
-				continue;
-			}
-
-			/*
-			 ** find corresponding tty structure. The process of mapping
-			 ** the ports puts these here.
-			 */
-			ttyP = PortP->gs.port.tty;
-
-			/*
-			 ** Lock the port before we begin working on it.
-			 */
-			rio_spin_lock(&PortP->portSem);
-
-			/*
-			 ** Process received data if there is any.
-			 */
-			if (can_remove_receive(&PacketP, PortP))
-				RIOReceive(p, PortP);
-
-			/*
-			 ** If there is no data left to be read from the port, and
-			 ** it's handshake bit is set, then we must clear the handshake,
-			 ** so that that downstream RTA is re-enabled.
-			 */
-			if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
-				/*
-				 ** MAGIC! ( Basically, handshake the RX buffer, so that
-				 ** the RTAs upstream can be re-enabled. )
-				 */
-				rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
-				writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
-			}
-			rio_spin_unlock(&PortP->portSem);
-		}
-	}
-
-	if (readw(&HostP->ParmMapP->tx_intr)) {
-		int port;
-
-		writew(0, &HostP->ParmMapP->tx_intr);
-
-		p->RIOTxCount++;
-		TxIntr++;
-		rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts);
-
-		/*
-		 ** Loop through every port.
-		 ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
-		 ** associated ) then it is worth checking.
-		 */
-		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
-			struct Port *PortP = p->RIOPortp[port];
-			struct tty_struct *ttyP;
-			struct PKT __iomem *PacketP;
-
-			/*
-			 ** not mapped in - most of the RIOPortp[] information
-			 ** has not been set up!
-			 */
-			if (!PortP->Mapped) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** If the host board isn't running, then its data structures
-			 ** are no use to us - continue quietly.
-			 */
-			if (PortP->HostP != HostP) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** Let us see - is the port open? If not, then don't service it.
-			 */
-			if (!(PortP->PortState & PORT_ISOPEN)) {
-				continue;
-			}
-
-			rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
-			/*
-			 ** Lock the port before we begin working on it.
-			 */
-			rio_spin_lock(&PortP->portSem);
-
-			/*
-			 ** If we can't add anything to the transmit queue, then
-			 ** we need do none of this processing.
-			 */
-			if (!can_add_transmit(&PacketP, PortP)) {
-				rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-
-			/*
-			 ** find corresponding tty structure. The process of mapping
-			 ** the ports puts these here.
-			 */
-			ttyP = PortP->gs.port.tty;
-			/* If ttyP is NULL, the port is getting closed. Forget about it. */
-			if (!ttyP) {
-				rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-			/*
-			 ** If there is more room available we start up the transmit
-			 ** data process again. This can be direct I/O, if the cookmode
-			 ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
-			 ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
-			 ** characters via the line discipline. We must always call
-			 ** the line discipline,
-			 ** so that user input characters can be echoed correctly.
-			 **
-			 ** ++++ Update +++++
-			 ** With the advent of double buffering, we now see if
-			 ** TxBufferOut-In is non-zero. If so, then we copy a packet
-			 ** to the output place, and set it going. If this empties
-			 ** the buffer, then we must issue a wakeup( ) on OUT.
-			 ** If it frees space in the buffer then we must issue
-			 ** a wakeup( ) on IN.
-			 **
-			 ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
-			 ** have to send a WFLUSH command down the PHB, to mark the
-			 ** end point of a WFLUSH. We also need to clear out any
-			 ** data from the double buffer! ( note that WflushFlag is a
-			 ** *count* of the number of WFLUSH commands outstanding! )
-			 **
-			 ** ++++ And there's more!
-			 ** If an RTA is powered off, then on again, and rebooted,
-			 ** whilst it has ports open, then we need to re-open the ports.
-			 ** ( reasonable enough ). We can't do this when we spot the
-			 ** re-boot, in interrupt time, because the queue is probably
-			 ** full. So, when we come in here, we need to test if any
-			 ** ports are in this condition, and re-open the port before
-			 ** we try to send any more data to it. Now, the re-booted
-			 ** RTA will be discarding packets from the PHB until it
-			 ** receives this open packet, but don't worry tooo much
-			 ** about that. The one thing that is interesting is the
-			 ** combination of this effect and the WFLUSH effect!
-			 */
-			/* For now don't handle RTA reboots. -- REW.
-			   Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
-			if (PortP->MagicFlags) {
-				if (PortP->MagicFlags & MAGIC_REBOOT) {
-					/*
-					 ** well, the RTA has been rebooted, and there is room
-					 ** on its queue to add the open packet that is required.
-					 **
-					 ** The messy part of this line is trying to decide if
-					 ** we need to call the Param function as a tty or as
-					 ** a modem.
-					 ** DONT USE CLOCAL AS A TEST FOR THIS!
-					 **
-					 ** If we can't param the port, then move on to the
-					 ** next port.
-					 */
-					PortP->InUse = NOT_INUSE;
-
-					rio_spin_unlock(&PortP->portSem);
-					if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL)
-						continue;	/* with next port */
-					rio_spin_lock(&PortP->portSem);
-					PortP->MagicFlags &= ~MAGIC_REBOOT;
-				}
-
-				/*
-				 ** As mentioned above, this is a tacky hack to cope
-				 ** with WFLUSH
-				 */
-				if (PortP->WflushFlag) {
-					rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
-
-					if (PortP->InUse)
-						rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
-				}
-
-				while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
-					int p;
-					struct PktCmd __iomem *PktCmdP;
-
-					rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
-					/*
-					 ** make it look just like a WFLUSH command
-					 */
-					PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
-
-					writeb(RIOC_WFLUSH, &PktCmdP->Command);
-
-					p = PortP->HostPort % (u16) PORTS_PER_RTA;
-
-					/*
-					 ** If second block of ports for 16 port RTA, add 8
-					 ** to index 8-15.
-					 */
-					if (PortP->SecondBlock)
-						p += PORTS_PER_RTA;
-
-					writeb(p, &PktCmdP->PhbNum);
-
-					/*
-					 ** to make debuggery easier
-					 */
-					writeb('W', &PacketP->data[2]);
-					writeb('F', &PacketP->data[3]);
-					writeb('L', &PacketP->data[4]);
-					writeb('U', &PacketP->data[5]);
-					writeb('S', &PacketP->data[6]);
-					writeb('H', &PacketP->data[7]);
-					writeb(' ', &PacketP->data[8]);
-					writeb('0' + PortP->WflushFlag, &PacketP->data[9]);
-					writeb(' ', &PacketP->data[10]);
-					writeb(' ', &PacketP->data[11]);
-					writeb('\0', &PacketP->data[12]);
-
-					/*
-					 ** its two bytes long!
-					 */
-					writeb(PKT_CMD_BIT | 2, &PacketP->len);
-
-					/*
-					 ** queue it!
-					 */
-					if (!(PortP->State & RIO_DELETED)) {
-						add_transmit(PortP);
-						/*
-						 ** Count chars tx'd for port statistics reporting
-						 */
-						if (PortP->statsGather)
-							PortP->txchars += 2;
-					}
-
-					if (--(PortP->WflushFlag) == 0) {
-						PortP->MagicFlags &= ~MAGIC_FLUSH;
-					}
-
-					rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
-				}
-				if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
-					if (PortP->MagicFlags & MAGIC_FLUSH) {
-						PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
-					} else {
-						if (!can_add_transmit(&PacketP, PortP)) {
-							rio_spin_unlock(&PortP->portSem);
-							continue;
-						}
-						rio_spin_unlock(&PortP->portSem);
-						RIOTxEnable((char *) PortP);
-						rio_spin_lock(&PortP->portSem);
-						PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
-					}
-				}
-			}
-
-
-			/*
-			 ** If we can't add anything to the transmit queue, then
-			 ** we need do none of the remaining processing.
-			 */
-			if (!can_add_transmit(&PacketP, PortP)) {
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-
-			rio_spin_unlock(&PortP->portSem);
-			RIOTxEnable((char *) PortP);
-		}
-	}
-}
-
-/*
-** Routine for handling received data for tty drivers
-*/
-static void RIOReceive(struct rio_info *p, struct Port *PortP)
-{
-	struct tty_struct *TtyP;
-	unsigned short transCount;
-	struct PKT __iomem *PacketP;
-	register unsigned int DataCnt;
-	unsigned char __iomem *ptr;
-	unsigned char *buf;
-	int copied = 0;
-
-	static int intCount, RxIntCnt;
-
-	/*
-	 ** The receive data process is to remove packets from the
-	 ** PHB until there aren't any more or the current cblock
-	 ** is full. When this occurs, there will be some left over
-	 ** data in the packet, that we must do something with.
-	 ** As we haven't unhooked the packet from the read list
-	 ** yet, we can just leave the packet there, having first
-	 ** made a note of how far we got. This means that we need
-	 ** a pointer per port saying where we start taking the
-	 ** data from - this will normally be zero, but when we
-	 ** run out of space it will be set to the offset of the
-	 ** next byte to copy from the packet data area. The packet
-	 ** length field is decremented by the number of bytes that
-	 ** we successfully removed from the packet. When this reaches
-	 ** zero, we reset the offset pointer to be zero, and free
-	 ** the packet from the front of the queue.
-	 */
-
-	intCount++;
-
-	TtyP = PortP->gs.port.tty;
-	if (!TtyP) {
-		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
-		return;
-	}
-
-	if (PortP->State & RIO_THROTTLE_RX) {
-		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
-		return;
-	}
-
-	if (PortP->State & RIO_DELETED) {
-		while (can_remove_receive(&PacketP, PortP)) {
-			remove_receive(PortP);
-			put_free_end(PortP->HostP, PacketP);
-		}
-	} else {
-		/*
-		 ** loop, just so long as:
-		 **   i ) there's some data ( i.e. can_remove_receive )
-		 **  ii ) we haven't been blocked
-		 ** iii ) there's somewhere to put the data
-		 **  iv ) we haven't outstayed our welcome
-		 */
-		transCount = 1;
-		while (can_remove_receive(&PacketP, PortP)
-		       && transCount) {
-			RxIntCnt++;
-
-			/*
-			 ** check that it is not a command!
-			 */
-			if (readb(&PacketP->len) & PKT_CMD_BIT) {
-				rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
-				/*      rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
-				rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit));
-				rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port));
-				rio_dprintk(RIO_DEBUG_INTR, " src_unit  = %d\n", readb(&PacketP->src_unit));
-				rio_dprintk(RIO_DEBUG_INTR, " src_port  = %d\n", readb(&PacketP->src_port));
-				rio_dprintk(RIO_DEBUG_INTR, " len	   = %d\n", readb(&PacketP->len));
-				rio_dprintk(RIO_DEBUG_INTR, " control   = %d\n", readb(&PacketP->control));
-				rio_dprintk(RIO_DEBUG_INTR, " csum	   = %d\n", readw(&PacketP->csum));
-				rio_dprintk(RIO_DEBUG_INTR, "	 data bytes: ");
-				for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
-					rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt]));
-				remove_receive(PortP);
-				put_free_end(PortP->HostP, PacketP);
-				continue;	/* with next packet */
-			}
-
-			/*
-			 ** How many characters can we move 'upstream' ?
-			 **
-			 ** Determine the minimum of the amount of data
-			 ** available and the amount of space in which to
-			 ** put it.
-			 **
-			 ** 1.        Get the packet length by masking 'len'
-			 **   for only the length bits.
-			 ** 2.        Available space is [buffer size] - [space used]
-			 **
-			 ** Transfer count is the minimum of packet length
-			 ** and available space.
-			 */
-
-			transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK);
-			rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
-			/*
-			 ** To use the following 'kkprintfs' for debugging - change the '#undef'
-			 ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
-			 ** driver).
-			 */
-			ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart;
-
-			tty_prepare_flip_string(TtyP, &buf, transCount);
-			rio_memcpy_fromio(buf, ptr, transCount);
-			PortP->RxDataStart += transCount;
-			writeb(readb(&PacketP->len)-transCount, &PacketP->len);
-			copied += transCount;
-
-
-
-			if (readb(&PacketP->len) == 0) {
-				/*
-				 ** If we have emptied the packet, then we can
-				 ** free it, and reset the start pointer for
-				 ** the next packet.
-				 */
-				remove_receive(PortP);
-				put_free_end(PortP->HostP, PacketP);
-				PortP->RxDataStart = 0;
-			}
-		}
-	}
-	if (copied) {
-		rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
-		tty_flip_buffer_push(TtyP);
-	}
-
-	return;
-}
-
diff --git a/drivers/char/rio/rioioctl.h b/drivers/char/rio/rioioctl.h
deleted file mode 100644
index e8af5b3..0000000
--- a/drivers/char/rio/rioioctl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioioctl.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)rioioctl.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rioioctl_h__
-#define	__rioioctl_h__
-
-/*
-** RIO device driver - user ioctls and associated structures.
-*/
-
-struct portStats {
-	int port;
-	int gather;
-	unsigned long txchars;
-	unsigned long rxchars;
-	unsigned long opens;
-	unsigned long closes;
-	unsigned long ioctls;
-};
-
-#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
-
-#define	RIO_QUICK_CHECK	  	(RIOC | 105)
-#define RIO_GATHER_PORT_STATS	(RIOC | 193)
-#define RIO_RESET_PORT_STATS	(RIOC | 194)
-#define RIO_GET_PORT_STATS	(RIOC | 195)
-
-#endif				/* __rioioctl_h__ */
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
deleted file mode 100644
index 6415f3f..0000000
--- a/drivers/char/rio/rioparam.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioparam.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:45
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)rioparam.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-
-
-/*
-** The Scam, based on email from jeremyr@bugs.specialix.co.uk....
-**
-** To send a command on a particular port, you put a packet with the
-** command bit set onto the port. The command bit is in the len field,
-** and gets ORed in with the actual byte count.
-**
-** When you send a packet with the command bit set the first
-** data byte (data[0]) is interpreted as the command to execute.
-** It also governs what data structure overlay should accompany the packet.
-** Commands are defined in cirrus/cirrus.h
-**
-** If you want the command to pre-emt data already on the queue for the
-** port, set the pre-emptive bit in conjunction with the command bit.
-** It is not defined what will happen if you set the preemptive bit
-** on a packet that is NOT a command.
-**
-** Pre-emptive commands should be queued at the head of the queue using
-** add_start(), whereas normal commands and data are enqueued using
-** add_end().
-**
-** Most commands do not use the remaining bytes in the data array. The
-** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
-** OPEN are currently analogous). With these three commands the following
-** 11 data bytes are all used to pass config information such as baud rate etc.
-** The fields are also defined in cirrus.h. Some contain straightforward
-** information such as the transmit XON character. Two contain the transmit and
-** receive baud rates respectively. For most baud rates there is a direct
-** mapping between the rates defined in <sys/termio.h> and the byte in the
-** packet. There are additional (non UNIX-standard) rates defined in
-** /u/dos/rio/cirrus/h/brates.h.
-**
-** The rest of the data fields contain approximations to the Cirrus registers
-** that are used to program number of bits etc. Each registers bit fields is
-** defined in cirrus.h.
-** 
-** NB. Only use those bits that are defined as being driver specific
-** or common to the RTA and the driver.
-** 
-** All commands going from RTA->Host will be dealt with by the Host code - you
-** will never see them. As with the SI there will be three fields to look out
-** for in each phb (not yet defined - needs defining a.s.a.p).
-** 
-** modem_status	- current state of handshake pins.
-**
-** port_status	 - current port status - equivalent to hi_stat for SI, indicates
-** if port is IDLE_OPEN, IDLE_CLOSED etc.
-**
-** break_status	- bit X set if break has been received.
-** 
-** Happy hacking.
-** 
-*/
-
-/* 
-** RIOParam is used to open or configure a port. You pass it a PortP,
-** which will have a tty struct attached to it. You also pass a command,
-** either OPEN or CONFIG. The port's setup is taken from the t_ fields
-** of the tty struct inside the PortP, and the port is either opened
-** or re-configured. You must also tell RIOParam if the device is a modem
-** device or not (i.e. top bit of minor number set or clear - take special
-** care when deciding on this!).
-** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
-**
-** RIOParam assumes it will be called at splrio(), and also assumes
-** that CookMode is set correctly in the port structure.
-**
-** NB. for MPX
-**	tty lock must NOT have been previously acquired.
-*/
-int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
-{
-	struct tty_struct *TtyP;
-	int retval;
-	struct phb_param __iomem *phb_param_ptr;
-	struct PKT __iomem *PacketP;
-	int res;
-	u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
-	u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
-	u8 LNext = 0, TxBaud = 0, RxBaud = 0;
-	int retries = 0xff;
-	unsigned long flags;
-
-	func_enter();
-
-	TtyP = PortP->gs.port.tty;
-
-	rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
-
-	if (!TtyP) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
-
-		func_exit();
-
-		return RIO_FAIL;
-	}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	if (cmd == RIOC_OPEN) {
-		/*
-		 ** If the port is set to store or lock the parameters, and it is
-		 ** paramed with OPEN, we want to restore the saved port termio, but
-		 ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
-		 */
-	}
-
-	/*
-	 ** wait for space
-	 */
-	while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
-		if (retries-- <= 0) {
-			break;
-		}
-		if (PortP->InUse != NOT_INUSE) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
-		}
-
-		if (!res) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
-		}
-
-		if (SleepFlag != OK_TO_SLEEP) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-
-			return RIO_FAIL;
-		}
-
-		rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		retval = RIODelay(PortP, HUNDRED_MS);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		if (retval == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-			return -EINTR;
-		}
-		if (PortP->State & RIO_DELETED) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-			return 0;
-		}
-	}
-
-	if (!res) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		func_exit();
-
-		return RIO_FAIL;
-	}
-
-	rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
-	rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);
-
-	phb_param_ptr = (struct phb_param __iomem *) PacketP->data;
-
-
-	switch (TtyP->termios->c_cflag & CSIZE) {
-	case CS5:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
-			Cor1 |= RIOC_COR1_5BITS;
-			break;
-		}
-	case CS6:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
-			Cor1 |= RIOC_COR1_6BITS;
-			break;
-		}
-	case CS7:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
-			Cor1 |= RIOC_COR1_7BITS;
-			break;
-		}
-	case CS8:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
-			Cor1 |= RIOC_COR1_8BITS;
-			break;
-		}
-	}
-
-	if (TtyP->termios->c_cflag & CSTOPB) {
-		rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
-		Cor1 |= RIOC_COR1_2STOP;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
-		Cor1 |= RIOC_COR1_1STOP;
-	}
-
-	if (TtyP->termios->c_cflag & PARENB) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
-		Cor1 |= RIOC_COR1_NORMAL;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
-		Cor1 |= RIOC_COR1_NOP;
-	}
-	if (TtyP->termios->c_cflag & PARODD) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
-		Cor1 |= RIOC_COR1_ODD;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
-		Cor1 |= RIOC_COR1_EVEN;
-	}
-
-	/*
-	 ** COR 2
-	 */
-	if (TtyP->termios->c_iflag & IXON) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
-		Cor2 |= RIOC_COR2_IXON;
-	} else {
-		if (PortP->Config & RIO_IXON) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
-			Cor2 |= RIOC_COR2_IXON;
-		} else
-			rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
-	}
-
-	if (TtyP->termios->c_iflag & IXANY) {
-		if (PortP->Config & RIO_IXANY) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
-			Cor2 |= RIOC_COR2_IXANY;
-		} else
-			rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
-	}
-
-	if (TtyP->termios->c_iflag & IXOFF) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
-		Cor2 |= RIOC_COR2_IXOFF;
-	}
-
-	if (TtyP->termios->c_cflag & HUPCL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
-		Cor2 |= RIOC_COR2_HUPCL;
-	}
-
-	if (C_CRTSCTS(TtyP)) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
-		Cor2 |= RIOC_COR2_CTSFLOW;
-		Cor2 |= RIOC_COR2_RTSFLOW;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
-		Cor2 &= ~RIOC_COR2_CTSFLOW;
-		Cor2 &= ~RIOC_COR2_RTSFLOW;
-	}
-
-
-	if (TtyP->termios->c_cflag & CLOCAL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
-	}
-
-	/*
-	 ** COR 4 (there is no COR 3)
-	 */
-	if (TtyP->termios->c_iflag & IGNBRK) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
-		Cor4 |= RIOC_COR4_IGNBRK;
-	}
-	if (!(TtyP->termios->c_iflag & BRKINT)) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
-		Cor4 |= RIOC_COR4_NBRKINT;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on	break condition\n");
-	}
-
-	if (TtyP->termios->c_iflag & INLCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
-		Cor4 |= RIOC_COR4_INLCR;
-	}
-
-	if (TtyP->termios->c_iflag & IGNCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
-		Cor4 |= RIOC_COR4_IGNCR;
-	}
-
-	if (TtyP->termios->c_iflag & ICRNL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
-		Cor4 |= RIOC_COR4_ICRNL;
-	}
-	if (TtyP->termios->c_iflag & IGNPAR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
-		Cor4 |= RIOC_COR4_IGNPAR;
-	}
-	if (TtyP->termios->c_iflag & PARMRK) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
-		Cor4 |= RIOC_COR4_PARMRK;
-	}
-
-	/*
-	 ** Set the RAISEMOD flag to ensure that the modem lines are raised
-	 ** on reception of a config packet.
-	 ** The download code handles the zero baud condition.
-	 */
-	Cor4 |= RIOC_COR4_RAISEMOD;
-
-	/*
-	 ** COR 5
-	 */
-
-	Cor5 = RIOC_COR5_CMOE;
-
-	/*
-	 ** Set to monitor tbusy/tstop (or not).
-	 */
-
-	if (PortP->MonitorTstate)
-		Cor5 |= RIOC_COR5_TSTATE_ON;
-	else
-		Cor5 |= RIOC_COR5_TSTATE_OFF;
-
-	/*
-	 ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
-	 */
-	if (TtyP->termios->c_iflag & ISTRIP) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
-		if (!(PortP->State & RIO_TRIAD_MODE)) {
-			Cor5 |= RIOC_COR5_ISTRIP;
-		}
-	}
-
-	if (TtyP->termios->c_oflag & ONLCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_ONLCR;
-	}
-	if (TtyP->termios->c_oflag & OCRNL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_OCRNL;
-	}
-	if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_TAB3;
-	}
-
-	/*
-	 ** Flow control bytes.
-	 */
-	TxXon = TtyP->termios->c_cc[VSTART];
-	TxXoff = TtyP->termios->c_cc[VSTOP];
-	RxXon = TtyP->termios->c_cc[VSTART];
-	RxXoff = TtyP->termios->c_cc[VSTOP];
-	/*
-	 ** LNEXT byte
-	 */
-	LNext = 0;
-
-	/*
-	 ** Baud rate bytes
-	 */
-	rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);
-
-	switch (TtyP->termios->c_cflag & CBAUD) {
-#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
-		e(50);
-		e(75);
-		e(110);
-		e(134);
-		e(150);
-		e(200);
-		e(300);
-		e(600);
-		e(1200);
-		e(1800);
-		e(2400);
-		e(4800);
-		e(9600);
-		e(19200);
-		e(38400);
-		e(57600);
-		e(115200);	/* e(230400);e(460800); e(921600);  */
-	}
-
-	rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
-
-
-	/*
-	 ** Leftovers
-	 */
-	if (TtyP->termios->c_cflag & CREAD)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
-#ifdef RCV1EN
-	if (TtyP->termios->c_cflag & RCV1EN)
-		rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
-#endif
-#ifdef XMT1EN
-	if (TtyP->termios->c_cflag & XMT1EN)
-		rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
-#endif
-	if (TtyP->termios->c_lflag & ISIG)
-		rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
-	if (TtyP->termios->c_lflag & ICANON)
-		rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
-	if (TtyP->termios->c_lflag & XCASE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
-	if (TtyP->termios->c_lflag & ECHO)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
-	if (TtyP->termios->c_lflag & ECHOE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
-	if (TtyP->termios->c_lflag & ECHOK)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
-	if (TtyP->termios->c_lflag & ECHONL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
-	if (TtyP->termios->c_lflag & NOFLSH)
-		rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
-#ifdef TOSTOP
-	if (TtyP->termios->c_lflag & TOSTOP)
-		rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
-#endif
-#ifdef XCLUDE
-	if (TtyP->termios->c_lflag & XCLUDE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
-#endif
-	if (TtyP->termios->c_iflag & IUCLC)
-		rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
-	if (TtyP->termios->c_oflag & OPOST)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
-	if (TtyP->termios->c_oflag & OLCUC)
-		rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
-	if (TtyP->termios->c_oflag & ONOCR)
-		rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
-	if (TtyP->termios->c_oflag & ONLRET)
-		rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
-	if (TtyP->termios->c_oflag & OFILL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
-	if (TtyP->termios->c_oflag & OFDEL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
-	if (TtyP->termios->c_oflag & NLDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
-	if (TtyP->termios->c_oflag & CRDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
-	if (TtyP->termios->c_oflag & TABDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
-	/*
-	 ** These things are kind of useful in a later life!
-	 */
-	PortP->Cor2Copy = Cor2;
-
-	if (PortP->State & RIO_DELETED) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		func_exit();
-
-		return RIO_FAIL;
-	}
-
-	/*
-	 ** Actually write the info into the packet to be sent
-	 */
-	writeb(cmd, &phb_param_ptr->Cmd);
-	writeb(Cor1, &phb_param_ptr->Cor1);
-	writeb(Cor2, &phb_param_ptr->Cor2);
-	writeb(Cor4, &phb_param_ptr->Cor4);
-	writeb(Cor5, &phb_param_ptr->Cor5);
-	writeb(TxXon, &phb_param_ptr->TxXon);
-	writeb(RxXon, &phb_param_ptr->RxXon);
-	writeb(TxXoff, &phb_param_ptr->TxXoff);
-	writeb(RxXoff, &phb_param_ptr->RxXoff);
-	writeb(LNext, &phb_param_ptr->LNext);
-	writeb(TxBaud, &phb_param_ptr->TxBaud);
-	writeb(RxBaud, &phb_param_ptr->RxBaud);
-
-	/*
-	 ** Set the length/command field
-	 */
-	writeb(12 | PKT_CMD_BIT, &PacketP->len);
-
-	/*
-	 ** The packet is formed - now, whack it off
-	 ** to its final destination:
-	 */
-	add_transmit(PortP);
-	/*
-	 ** Count characters transmitted for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->txchars += 12;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
-	/*
-	 ** job done.
-	 */
-	func_exit();
-
-	return 0;
-}
-
-
-/*
-** We can add another packet to a transmit queue if the packet pointer pointed
-** to by the TxAdd pointer has PKT_IN_USE clear in its address.
-*/
-int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP)
-{
-	struct PKT __iomem *tp;
-
-	*PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));
-
-	return !((unsigned long) tp & PKT_IN_USE);
-}
-
-/*
-** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
-** and then move the TxAdd pointer along one position to point to the next
-** packet pointer. You must wrap the pointer from the end back to the start.
-*/
-void add_transmit(struct Port *PortP)
-{
-	if (readw(PortP->TxAdd) & PKT_IN_USE) {
-		rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
-	}
-	writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd);
-	PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1;
-	writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add);
-}
-
-/****************************************
- * Put a packet onto the end of the
- * free list
- ****************************************/
-void put_free_end(struct Host *HostP, struct PKT __iomem *PktP)
-{
-	struct rio_free_list __iomem *tmp_pointer;
-	unsigned short old_end, new_end;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-	 /*************************************************
-	* Put a packet back onto the back of the free list
-	*
-	************************************************/
-
-	rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP);
-
-	if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) {
-		new_end = RIO_OFF(HostP->Caddr, PktP);
-		tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end);
-		writew(new_end, &tmp_pointer->next);
-		writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev);
-		writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next);
-		writew(new_end, &HostP->ParmMapP->free_list_end);
-	} else {		/* First packet on the free list this should never happen! */
-		rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
-		writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end);
-		tmp_pointer = (struct rio_free_list __iomem *) PktP;
-		writew(TPNULL, &tmp_pointer->prev);
-		writew(TPNULL, &tmp_pointer->next);
-	}
-	rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
-	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-}
-
-/*
-** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
-** for the next packet on the queue. It will also set PktP to point to the
-** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
-** then can_remove_receive() returns 0.
-*/
-int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP)
-{
-	if (readw(PortP->RxRemove) & PKT_IN_USE) {
-		*PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
-		return 1;
-	}
-	return 0;
-}
-
-/*
-** To remove a packet from the receive queue you clear its PKT_IN_USE bit,
-** and then bump the pointers. Once the pointers get to the end, they must
-** be wrapped back to the start.
-*/
-void remove_receive(struct Port *PortP)
-{
-	writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove);
-	PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1;
-	writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove);
-}
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
deleted file mode 100644
index f9b936a..0000000
--- a/drivers/char/rio/rioroute.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: rioroute.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:46
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)rioroute.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int);
-static int RIOIsolate(struct rio_info *, struct Host *, unsigned int);
-static int RIOCheck(struct Host *, unsigned int);
-static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int);
-
-
-/*
-** Incoming on the ROUTE_RUP
-** I wrote this while I was tired. Forgive me.
-*/
-int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
-	struct PktCmd_M *PktReplyP;
-	struct CmdBlk *CmdBlkP;
-	struct Port *PortP;
-	struct Map *MapP;
-	struct Top *TopP;
-	int ThisLink, ThisLinkMin, ThisLinkMax;
-	int port;
-	int Mod, Mod1, Mod2;
-	unsigned short RtaType;
-	unsigned int RtaUniq;
-	unsigned int ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */
-	unsigned int OldUnit, NewUnit, OldLink, NewLink;
-	char *MyType, *MyName;
-	int Lies;
-	unsigned long flags;
-
-	/*
-	 ** Is this unit telling us it's current link topology?
-	 */
-	if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) {
-		MapP = HostP->Mapping;
-
-		/*
-		 ** The packet can be sent either by the host or by an RTA.
-		 ** If it comes from the host, then we need to fill in the
-		 ** Topology array in the host structure. If it came in
-		 ** from an RTA then we need to fill in the Mapping structure's
-		 ** Topology array for the unit.
-		 */
-		if (Rup >= (unsigned short) MAX_RUP) {
-			ThisUnit = HOST_ID;
-			TopP = HostP->Topology;
-			MyType = "Host";
-			MyName = HostP->Name;
-			ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
-		} else {
-			ThisUnit = Rup + 1;
-			TopP = HostP->Mapping[Rup].Topology;
-			MyType = "RTA";
-			MyName = HostP->Mapping[Rup].Name;
-			ThisLinkMin = 0;
-			ThisLinkMax = LINKS_PER_UNIT - 1;
-		}
-
-		/*
-		 ** Lies will not be tolerated.
-		 ** If any pair of links claim to be connected to the same
-		 ** place, then ignore this packet completely.
-		 */
-		Lies = 0;
-		for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
-			/*
-			 ** it won't lie about network interconnect, total disconnects
-			 ** and no-IDs. (or at least, it doesn't *matter* if it does)
-			 */
-			if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP)
-				continue;
-
-			for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
-				if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) {
-					Lies++;
-				}
-			}
-		}
-
-		if (Lies) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
-			rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
-				    readb(&PktCmdP->RouteTopology[0].Unit),
-				    'A' + readb(&PktCmdP->RouteTopology[0].Link),
-				    readb(&PktCmdP->RouteTopology[1].Unit),
-				    'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link));
-			return 1;
-		}
-
-		/*
-		 ** now, process each link.
-		 */
-		for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
-			/*
-			 ** this is what it was connected to
-			 */
-			OldUnit = TopP[ThisLink].Unit;
-			OldLink = TopP[ThisLink].Link;
-
-			/*
-			 ** this is what it is now connected to
-			 */
-			NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit);
-			NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link);
-
-			if (OldUnit != NewUnit || OldLink != NewLink) {
-				/*
-				 ** something has changed!
-				 */
-
-				if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
-					rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
-				} else {
-					/*
-					 ** put the new values in
-					 */
-					TopP[ThisLink].Unit = NewUnit;
-					TopP[ThisLink].Link = NewLink;
-
-					RIOSetChange(p);
-
-					if (OldUnit <= MAX_RUP) {
-						/*
-						 ** If something has become bust, then re-enable them messages
-						 */
-						if (!p->RIONoMessage)
-							RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
-					}
-
-					if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
-						RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
-
-					if (NewUnit == ROUTE_NO_ID)
-						rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
-
-					if (NewUnit == ROUTE_INTERCONNECT) {
-						if (!p->RIONoMessage)
-							printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
-					}
-
-					/*
-					 ** perform an update for 'the other end', so that these messages
-					 ** only appears once. Only disconnect the other end if it is pointing
-					 ** at us!
-					 */
-					if (OldUnit == HOST_ID) {
-						if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
-							HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
-							HostP->Topology[OldLink].Link = NO_LINK;
-						} else {
-							rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
-						}
-					} else if (OldUnit <= MAX_RUP) {
-						if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
-							HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
-							HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
-						} else {
-							rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
-						}
-					}
-					if (NewUnit == HOST_ID) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
-						HostP->Topology[NewLink].Unit = ThisUnit;
-						HostP->Topology[NewLink].Link = ThisLink;
-					} else if (NewUnit <= MAX_RUP) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
-						HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
-						HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
-					}
-				}
-				RIOSetChange(p);
-				RIOCheckIsolated(p, HostP, OldUnit);
-			}
-		}
-		return 1;
-	}
-
-	/*
-	 ** The only other command we recognise is a route_request command
-	 */
-	if (readb(&PktCmdP->Command) != ROUTE_REQUEST) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP);
-		return 1;
-	}
-
-	RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
-
-	/*
-	 ** Determine if 8 or 16 port RTA
-	 */
-	RtaType = GetUnitType(RtaUniq);
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
-
-	Mod = readb(&PktCmdP->ModuleTypes);
-	Mod1 = LONYBLE(Mod);
-	if (RtaType == TYPE_RTA16) {
-		/*
-		 ** Only one ident is set for a 16 port RTA. To make compatible
-		 ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
-		 */
-		Mod2 = Mod1;
-		rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
-	} else {
-		Mod2 = HINYBLE(Mod);
-		rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
-	}
-
-	/*
-	 ** try to unhook a command block from the command free list.
-	 */
-	if (!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
-		return 0;
-	}
-
-	/*
-	 ** Fill in the default info on the command block
-	 */
-	CmdBlkP->Packet.dest_unit = Rup;
-	CmdBlkP->Packet.dest_port = ROUTE_RUP;
-	CmdBlkP->Packet.src_unit = HOST_ID;
-	CmdBlkP->Packet.src_port = ROUTE_RUP;
-	CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
-	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
-	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
-
-	if (!RIOBootOk(p, HostP, RtaUniq)) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
-		PktReplyP->Command = ROUTE_FOAD;
-		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-		return 1;
-	}
-
-	/*
-	 ** Check to see if the RTA is configured for this host
-	 */
-	for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
-			    ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
-
-		/*
-		 ** We have an entry for it.
-		 */
-		if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
-			if (RtaType == TYPE_RTA16) {
-				ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
-				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
-			} else
-				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
-			/*
-			 ** If we have no knowledge of booting it, then the host has
-			 ** been re-booted, and so we must kill the RTA, so that it
-			 ** will be booted again (potentially with new bins)
-			 ** and it will then re-ask for an ID, which we will service.
-			 */
-			if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
-				if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
-					if (!p->RIONoMessage)
-						printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
-					HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
-				}
-				PktReplyP->Command = ROUTE_FOAD;
-				memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-				RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-				return 1;
-			}
-
-			/*
-			 ** Send the ID (entry) to this RTA. The ID number is implicit as
-			 ** the offset into the table. It is worth noting at this stage
-			 ** that offset zero in the table contains the entries for the
-			 ** RTA with ID 1!!!!
-			 */
-			PktReplyP->Command = ROUTE_ALLOCATE;
-			PktReplyP->IDNum = ThisUnit + 1;
-			if (RtaType == TYPE_RTA16) {
-				if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
-					/*
-					 ** Adjust the phb and tx pkt dest_units for 2nd block of 8
-					 ** only if the RTA has ports associated (SLOT_IN_USE)
-					 */
-					RIOFixPhbs(p, HostP, ThisUnit2);
-				PktReplyP->IDNum2 = ThisUnit2 + 1;
-				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
-			} else {
-				PktReplyP->IDNum2 = ROUTE_NO_ID;
-				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
-			}
-			memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10);
-
-			RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-
-			/*
-			 ** If this is a freshly booted RTA, then we need to re-open
-			 ** the ports, if any where open, so that data may once more
-			 ** flow around the system!
-			 */
-			if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
-				/*
-				 ** look at the ports associated with this beast and
-				 ** see if any where open. If they was, then re-open
-				 ** them, using the info from the tty flags.
-				 */
-				for (port = 0; port < PORTS_PER_RTA; port++) {
-					PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
-					if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
-						rio_spin_lock_irqsave(&PortP->portSem, flags);
-						PortP->MagicFlags |= MAGIC_REBOOT;
-						rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-					}
-				}
-				if (RtaType == TYPE_RTA16) {
-					for (port = 0; port < PORTS_PER_RTA; port++) {
-						PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
-						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
-							rio_spin_lock_irqsave(&PortP->portSem, flags);
-							PortP->MagicFlags |= MAGIC_REBOOT;
-							rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-						}
-					}
-				}
-			}
-
-			/*
-			 ** keep a copy of the module types!
-			 */
-			HostP->UnixRups[ThisUnit].ModTypes = Mod;
-			if (RtaType == TYPE_RTA16)
-				HostP->UnixRups[ThisUnit2].ModTypes = Mod;
-
-			/*
-			 ** If either of the modules on this unit is read-only or write-only
-			 ** or none-xprint, then we need to transfer that info over to the
-			 ** relevant ports.
-			 */
-			if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
-				for (port = 0; port < PORTS_PER_MODULE; port++) {
-					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
-					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
-					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
-					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
-				}
-				if (RtaType == TYPE_RTA16) {
-					for (port = 0; port < PORTS_PER_MODULE; port++) {
-						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
-						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
-						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
-						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
-					}
-				}
-			}
-
-			/*
-			 ** Job done, get on with the interrupts!
-			 */
-			return 1;
-		}
-	}
-	/*
-	 ** There is no table entry for this RTA at all.
-	 **
-	 ** Lets check to see if we actually booted this unit - if not,
-	 ** then we reset it and it will go round the loop of being booted
-	 ** we can then worry about trying to fit it into the table.
-	 */
-	for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
-		if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
-			break;
-	if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
-		/*
-		 ** if the unit wasn't in the table, and the table wasn't full, then
-		 ** we reset the unit, because we didn't boot it.
-		 ** However, if the table is full, it could be that we did boot
-		 ** this unit, and so we won't reboot it, because it isn't really
-		 ** all that disasterous to keep the old bins in most cases. This
-		 ** is a rather tacky feature, but we are on the edge of reallity
-		 ** here, because the implication is that someone has connected
-		 ** 16+MAX_EXTRA_UNITS onto one host.
-		 */
-		static int UnknownMesgDone = 0;
-
-		if (!UnknownMesgDone) {
-			if (!p->RIONoMessage)
-				printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n");
-			UnknownMesgDone = 1;
-		}
-
-		PktReplyP->Command = ROUTE_FOAD;
-		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-	} else {
-		/*
-		 ** we did boot it (as an extra), and there may now be a table
-		 ** slot free (because of a delete), so we will try to make
-		 ** a tentative entry for it, so that the configurator can see it
-		 ** and fill in the details for us.
-		 */
-		if (RtaType == TYPE_RTA16) {
-			if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
-				RIODefaultName(p, HostP, ThisUnit);
-				rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP);
-			}
-		} else {
-			if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
-				RIODefaultName(p, HostP, ThisUnit);
-				rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP);
-			}
-		}
-		PktReplyP->Command = ROUTE_USED;
-		memcpy(PktReplyP->CommandText, "RT_USED", 7);
-	}
-	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-	return 1;
-}
-
-
-void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit)
-{
-	unsigned short link, port;
-	struct Port *PortP;
-	unsigned long flags;
-	int PortN = HostP->Mapping[unit].SysPort;
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
-
-	if (PortN != -1) {
-		unsigned short dest_unit = HostP->Mapping[unit].ID2;
-
-		/*
-		 ** Get the link number used for the 1st 8 phbs on this unit.
-		 */
-		PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
-
-		link = readw(&PortP->PhbP->link);
-
-		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
-			unsigned short dest_port = port + 8;
-			u16 __iomem *TxPktP;
-			struct PKT __iomem *Pkt;
-
-			PortP = p->RIOPortp[PortN];
-
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			/*
-			 ** If RTA is not powered on, the tx packets will be
-			 ** unset, so go no further.
-			 */
-			if (!PortP->TxStart) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				break;
-			}
-
-			/*
-			 ** For the second slot of a 16 port RTA, the driver needs to
-			 ** sort out the phb to port mappings. The dest_unit for this
-			 ** group of 8 phbs is set to the dest_unit of the accompanying
-			 ** 8 port block. The dest_port of the second unit is set to
-			 ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
-			 ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
-			 ** (being the second map ID) will be sent to dest_unit 5, port
-			 ** 14. When this RTA is deleted, dest_unit for ID 6 will be
-			 ** restored, and the dest_port will be reduced by 8.
-			 ** Transmit packets also have a destination field which needs
-			 ** adjusting in the same manner.
-			 ** Note that the unit/port bytes in 'dest' are swapped.
-			 ** We also need to adjust the phb and rup link numbers for the
-			 ** second block of 8 ttys.
-			 */
-			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
-				/*
-				 ** *TxPktP is the pointer to the transmit packet on the host
-				 ** card. This needs to be translated into a 32 bit pointer
-				 ** so it can be accessed from the driver.
-				 */
-				Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));
-
-				/*
-				 ** If the packet is used, reset it.
-				 */
-				Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE);
-				writeb(dest_unit, &Pkt->dest_unit);
-				writeb(dest_port, &Pkt->dest_port);
-			}
-			rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
-			writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
-			writew(link, &PortP->PhbP->link);
-
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		}
-		/*
-		 ** Now make sure the range of ports to be serviced includes
-		 ** the 2nd 8 on this 16 port RTA.
-		 */
-		if (link > 3)
-			return;
-		if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
-			writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port);
-		}
-	}
-}
-
-/*
-** Check to see if the new disconnection has isolated this unit.
-** If it has, then invalidate all its link information, and tell
-** the world about it. This is done to ensure that the configurator
-** only gets up-to-date information about what is going on.
-*/
-static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
-{
-	unsigned long flags;
-	rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-	if (RIOCheck(HostP, UnitId)) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
-		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-		return (0);
-	}
-
-	RIOIsolate(p, HostP, UnitId);
-	RIOSetChange(p);
-	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-	return 1;
-}
-
-/*
-** Invalidate all the link interconnectivity of this unit, and of
-** all the units attached to it. This will mean that the entire
-** subnet will re-introduce itself.
-*/
-static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
-{
-	unsigned int link, unit;
-
-	UnitId--;		/* this trick relies on the Unit Id being UNSIGNED! */
-
-	if (UnitId >= MAX_RUP)	/* dontcha just lurv unsigned maths! */
-		return (0);
-
-	if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
-		return (0);
-
-	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
-
-	if (p->RIOPrintDisabled == DO_PRINT)
-		rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		unit = HostP->Mapping[UnitId].Topology[link].Unit;
-		HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
-		HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
-		RIOIsolate(p, HostP, unit);
-	}
-	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-	return 1;
-}
-
-static int RIOCheck(struct Host *HostP, unsigned int UnitId)
-{
-	unsigned char link;
-
-/* 	rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
-
-	if (UnitId == HOST_ID) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
-		return 1;
-	}
-
-	UnitId--;
-
-	if (UnitId >= MAX_RUP) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
-		return 0;
-	}
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
-			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", 
-			   UnitId, 'A'+link)); */
-			return 1;
-		}
-	}
-
-	if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
-		return 0;
-	}
-
-	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
-		if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
-			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
-			HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-			return 1;
-		}
-	}
-
-	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-
-	/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
-
-	return 0;
-}
-
-/*
-** Returns the type of unit (host, 16/8 port RTA)
-*/
-
-unsigned int GetUnitType(unsigned int Uniq)
-{
-	switch ((Uniq >> 28) & 0xf) {
-	case RIO_AT:
-	case RIO_MCA:
-	case RIO_EISA:
-	case RIO_PCI:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
-		return (TYPE_HOST);
-	case RIO_RTA_16:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
-		return (TYPE_RTA16);
-	case RIO_RTA:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
-		return (TYPE_RTA8);
-	default:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
-		return (99);
-	}
-}
-
-int RIOSetChange(struct rio_info *p)
-{
-	if (p->RIOQuickCheck != NOT_CHANGED)
-		return (0);
-	p->RIOQuickCheck = CHANGED;
-	if (p->RIOSignalProcess) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
-		/*
-		   psignal( RIOSignalProcess, SIGHUP );
-		 */
-	}
-	return (0);
-}
-
-static void RIOConCon(struct rio_info *p,
-		      struct Host *HostP,
-		      unsigned int FromId,
-		      unsigned int FromLink,
-		      unsigned int ToId,
-		      unsigned int ToLink,
-		      int Change)
-{
-	char *FromName;
-	char *FromType;
-	char *ToName;
-	char *ToType;
-	unsigned int tp;
-
-/*
-** 15.10.1998 ARG - ESIL 0759
-** (Part) fix for port being trashed when opened whilst RTA "disconnected"
-**
-** What's this doing in here anyway ?
-** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected"
-**
-** 09.12.1998 ARG - ESIL 0776 - part fix
-** Okay, We've found out what this was all about now !
-** Someone had botched this to use RIOHalted to indicated the number of RTAs
-** 'disconnected'. The value in RIOHalted was then being used in the
-** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA
-** is 'disconnected'. The change was put in to satisfy a customer's needs.
-** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for
-** the customer.
-**
-    if (Change == CONNECT) {
-		if (p->RIOHalted) p->RIOHalted --;
-	 }
-	 else {
-		p->RIOHalted ++;
-	 }
-**
-** So - we need to implement it slightly differently - a new member of the
-** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
-** connections and disconnections. 
-*/
-	if (Change == CONNECT) {
-		if (p->RIORtaDisCons)
-			p->RIORtaDisCons--;
-	} else {
-		p->RIORtaDisCons++;
-	}
-
-	if (p->RIOPrintDisabled == DONT_PRINT)
-		return;
-
-	if (FromId > ToId) {
-		tp = FromId;
-		FromId = ToId;
-		ToId = tp;
-		tp = FromLink;
-		FromLink = ToLink;
-		ToLink = tp;
-	}
-
-	FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
-	FromType = FromId ? "RTA" : "HOST";
-	ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
-	ToType = ToId ? "RTA" : "HOST";
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
-	printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
-}
-
-/*
-** RIORemoveFromSavedTable :
-**
-** Delete and RTA entry from the saved table given to us
-** by the configuration program.
-*/
-static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
-{
-	int entry;
-
-	/*
-	 ** We loop for all entries even after finding an entry and
-	 ** zeroing it because we may have two entries to delete if
-	 ** it's a 16 port RTA.
-	 */
-	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-		if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
-			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
-		}
-	}
-	return 0;
-}
-
-
-/*
-** RIOCheckDisconnected :
-**
-** Scan the unit links to and return zero if the unit is completely
-** disconnected.
-*/
-static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
-{
-	int link;
-
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
-	/*
-	 ** If the slot is tentative and does not belong to the
-	 ** second half of a 16 port RTA then scan to see if
-	 ** is disconnected.
-	 */
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
-			break;
-	}
-
-	/*
-	 ** If not all links are disconnected then we can forget about it.
-	 */
-	if (link < LINKS_PER_UNIT)
-		return 1;
-
-#ifdef NEED_TO_FIX_THIS
-	/* Ok so all the links are disconnected. But we may have only just
-	 ** made this slot tentative and not yet received a topology update.
-	 ** Lets check how long ago we made it tentative.
-	 */
-	rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
-	if (drv_getparm(LBOLT, (ulong_t *) & current_time))
-		rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
-
-	elapse_time = current_time - TentTime[unit];
-	rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
-	if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
-		return 1;
-	}
-#endif
-
-	/*
-	 ** We have found an usable slot.
-	 ** If it is half of a 16 port RTA then delete the other half.
-	 */
-	if (HostP->Mapping[unit].ID2 != 0) {
-		int nOther = (HostP->Mapping[unit].ID2) - 1;
-
-		rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
-		memset(&HostP->Mapping[nOther], 0, sizeof(struct Map));
-	}
-	RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
-
-	return 0;
-}
-
-
-/*
-** RIOFindFreeID :
-**
-** This function scans the given host table for either one
-** or two free unit ID's.
-*/
-
-int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2)
-{
-	int unit, tempID;
-
-	/*
-	 ** Initialise the ID's to MAX_RUP.
-	 ** We do this to make the loop for setting the ID's as simple as
-	 ** possible.
-	 */
-	*pID1 = MAX_RUP;
-	if (pID2 != NULL)
-		*pID2 = MAX_RUP;
-
-	/*
-	 ** Scan all entries of the host mapping table for free slots.
-	 ** We scan for free slots first and then if that is not successful
-	 ** we start all over again looking for tentative slots we can re-use.
-	 */
-	for (unit = 0; unit < MAX_RUP; unit++) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
-		/*
-		 ** If the flags are zero then the slot is empty.
-		 */
-		if (HostP->Mapping[unit].Flags == 0) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "      This slot is empty.\n");
-			/*
-			 ** If we haven't allocated the first ID then do it now.
-			 */
-			if (*pID1 == MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
-				*pID1 = unit;
-
-				/*
-				 ** If the second ID is not needed then we can return
-				 ** now.
-				 */
-				if (pID2 == NULL)
-					return 0;
-			} else {
-				/*
-				 ** Allocate the second slot and return.
-				 */
-				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
-				*pID2 = unit;
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 ** If we manage to come out of the free slot loop then we
-	 ** need to start all over again looking for tentative slots
-	 ** that we can re-use.
-	 */
-	rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
-	for (unit = 0; unit < MAX_RUP; unit++) {
-		if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "    Slot %d looks promising.\n", unit);
-
-			if (unit == *pID1) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "    No it isn't, its the 1st half\n");
-				continue;
-			}
-
-			/*
-			 ** Slot is Tentative or Empty, but not a tentative second
-			 ** slot of a 16 porter.
-			 ** Attempt to free up this slot (and its parnter if
-			 ** it is a 16 port slot. The second slot will become
-			 ** empty after a call to RIOFreeDisconnected so thats why
-			 ** we look for empty slots above  as well).
-			 */
-			if (HostP->Mapping[unit].Flags != 0)
-				if (RIOFreeDisconnected(p, HostP, unit) != 0)
-					continue;
-			/*
-			 ** If we haven't allocated the first ID then do it now.
-			 */
-			if (*pID1 == MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
-				*pID1 = unit;
-
-				/*
-				 ** Clear out this slot now that we intend to use it.
-				 */
-				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
-
-				/*
-				 ** If the second ID is not needed then we can return
-				 ** now.
-				 */
-				if (pID2 == NULL)
-					return 0;
-			} else {
-				/*
-				 ** Allocate the second slot and return.
-				 */
-				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty  entry for second unit %d\n", unit);
-				*pID2 = unit;
-
-				/*
-				 ** Clear out this slot now that we intend to use it.
-				 */
-				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
-
-				/* At this point under the right(wrong?) conditions
-				 ** we may have a first unit ID being higher than the
-				 ** second unit ID. This is a bad idea if we are about
-				 ** to fill the slots with a 16 port RTA.
-				 ** Better check and swap them over.
-				 */
-
-				if (*pID1 > *pID2) {
-					rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
-					tempID = *pID1;
-					*pID1 = *pID2;
-					*pID2 = tempID;
-				}
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 ** If we manage to get to the end of the second loop then we
-	 ** can give up and return a failure.
-	 */
-	return 1;
-}
-
-
-/*
-** The link switch scenario.
-**
-** Rta Wun (A) is connected to Tuw (A).
-** The tables are all up to date, and the system is OK.
-**
-** If Wun (A) is now moved to Wun (B) before Wun (A) can
-** become disconnected, then the follow happens:
-**
-** Tuw (A) spots the change of unit:link at the other end
-** of its link and Tuw sends a topology packet reflecting
-** the change: Tuw (A) now disconnected from Wun (A), and
-** this is closely followed by a packet indicating that 
-** Tuw (A) is now connected to Wun (B).
-**
-** Wun (B) will spot that it has now become connected, and
-** Wun will send a topology packet, which indicates that
-** both Wun (A) and Wun (B) is connected to Tuw (A).
-**
-** Eventually Wun (A) realises that it is now disconnected
-** and Wun will send out a topology packet indicating that
-** Wun (A) is now disconnected.
-*/
diff --git a/drivers/char/rio/riospace.h b/drivers/char/rio/riospace.h
deleted file mode 100644
index ffb31d4..0000000
--- a/drivers/char/rio/riospace.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riospace.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)riospace.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riospace_h__
-#define __rio_riospace_h__
-
-#define	RIO_LOCATOR_LEN	16
-#define	MAX_RIO_BOARDS	4
-
-/*
-** DONT change this file. At all. Unless you can rebuild the entire
-** device driver, which you probably can't, then the rest of the
-** driver won't see any changes you make here. So don't make any.
-** In particular, it won't be able to see changes to RIO_SLOTS
-*/
-
-struct Conf {
-	char Locator[24];
-	unsigned int StartupTime;
-	unsigned int SlowCook;
-	unsigned int IntrPollTime;
-	unsigned int BreakInterval;
-	unsigned int Timer;
-	unsigned int RtaLoadBase;
-	unsigned int HostLoadBase;
-	unsigned int XpHz;
-	unsigned int XpCps;
-	char *XpOn;
-	char *XpOff;
-	unsigned int MaxXpCps;
-	unsigned int MinXpCps;
-	unsigned int SpinCmds;
-	unsigned int FirstAddr;
-	unsigned int LastAddr;
-	unsigned int BufferSize;
-	unsigned int LowWater;
-	unsigned int LineLength;
-	unsigned int CmdTime;
-};
-
-/*
-**	Board types - these MUST correspond to product codes!
-*/
-#define	RIO_EMPTY	0x0
-#define	RIO_EISA	0x3
-#define	RIO_RTA_16	0x9
-#define	RIO_AT		0xA
-#define	RIO_MCA		0xB
-#define	RIO_PCI		0xD
-#define	RIO_RTA		0xE
-
-/*
-**	Board data structure. This is used for configuration info
-*/
-struct Brd {
-	unsigned char Type;	/* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
-	unsigned char Ivec;	/* POLLED or ivec number */
-	unsigned char Mode;	/* Control stuff, see below */
-};
-
-struct Board {
-	char Locator[RIO_LOCATOR_LEN];
-	int NumSlots;
-	struct Brd Boards[MAX_RIO_BOARDS];
-};
-
-#define	BOOT_FROM_LINK		0x00
-#define	BOOT_FROM_RAM		0x01
-#define	EXTERNAL_BUS_OFF	0x00
-#define	EXTERNAL_BUS_ON		0x02
-#define	INTERRUPT_DISABLE	0x00
-#define	INTERRUPT_ENABLE	0x04
-#define	BYTE_OPERATION		0x00
-#define	WORD_OPERATION		0x08
-#define	POLLED			INTERRUPT_DISABLE
-#define	IRQ_15			(0x00 | INTERRUPT_ENABLE)
-#define	IRQ_12			(0x10 | INTERRUPT_ENABLE)
-#define	IRQ_11			(0x20 | INTERRUPT_ENABLE)
-#define	IRQ_9			(0x30 | INTERRUPT_ENABLE)
-#define	SLOW_LINKS		0x00
-#define	FAST_LINKS		0x40
-#define	SLOW_AT_BUS		0x00
-#define	FAST_AT_BUS		0x80
-#define	SLOW_PCI_TP		0x00
-#define	FAST_PCI_TP		0x80
-/*
-**	Debug levels
-*/
-#define	DBG_NONE	0x00000000
-
-#define	DBG_INIT	0x00000001
-#define	DBG_OPEN	0x00000002
-#define	DBG_CLOSE	0x00000004
-#define	DBG_IOCTL	0x00000008
-
-#define	DBG_READ	0x00000010
-#define	DBG_WRITE	0x00000020
-#define	DBG_INTR	0x00000040
-#define	DBG_PROC	0x00000080
-
-#define	DBG_PARAM	0x00000100
-#define	DBG_CMD		0x00000200
-#define	DBG_XPRINT	0x00000400
-#define	DBG_POLL	0x00000800
-
-#define	DBG_DAEMON	0x00001000
-#define	DBG_FAIL	0x00002000
-#define DBG_MODEM	0x00004000
-#define	DBG_LIST	0x00008000
-
-#define	DBG_ROUTE	0x00010000
-#define DBG_UTIL        0x00020000
-#define DBG_BOOT	0x00040000
-#define DBG_BUFFER	0x00080000
-
-#define	DBG_MON		0x00100000
-#define DBG_SPECIAL     0x00200000
-#define	DBG_VPIX	0x00400000
-#define	DBG_FLUSH	0x00800000
-
-#define	DBG_QENABLE	0x01000000
-
-#define	DBG_ALWAYS	0x80000000
-
-#endif				/* __rio_riospace_h__ */
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
deleted file mode 100644
index 3d15802..0000000
--- a/drivers/char/rio/riotable.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riotable.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:47
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)riotable.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-#include "protsts.h"
-
-/*
-** A configuration table has been loaded. It is now up to us
-** to sort it out and use the information contained therein.
-*/
-int RIONewTable(struct rio_info *p)
-{
-	int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
-	struct Map *MapP;
-	struct Map *HostMapP;
-	struct Host *HostP;
-
-	char *cptr;
-
-	/*
-	 ** We have been sent a new table to install. We need to break
-	 ** it down into little bits and spread it around a bit to see
-	 ** what we have got.
-	 */
-	/*
-	 ** Things to check:
-	 ** (things marked 'xx' aren't checked any more!)
-	 ** (1) That there are no booted Hosts/RTAs out there.
-	 ** (2) That the names are properly formed
-	 ** (3) That blank entries really are.
-	 ** xx (4)      That hosts mentioned in the table actually exist. xx
-	 ** (5) That the IDs are unique (per host).
-	 ** (6) That host IDs are zero
-	 ** (7) That port numbers are valid
-	 ** (8) That port numbers aren't duplicated
-	 ** (9) That names aren't duplicated
-	 ** xx (10) That hosts that actually exist are mentioned in the table. xx
-	 */
-	rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
-	if (p->RIOSystemUp) {	/* (1) */
-		p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
-		return -EBUSY;
-	}
-
-	p->RIOError.Error = NOTHING_WRONG_AT_ALL;
-	p->RIOError.Entry = -1;
-	p->RIOError.Other = -1;
-
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		MapP = &p->RIOConnectTable[Entry];
-		if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
-			cptr = MapP->Name;	/* (2) */
-			cptr[MAX_NAME_LEN - 1] = '\0';
-			if (cptr[0] == '\0') {
-				memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA	NN" : "HOST NN", 8);
-				MapP->Name[5] = '0' + Entry / 10;
-				MapP->Name[6] = '0' + Entry % 10;
-			}
-			while (*cptr) {
-				if (*cptr < ' ' || *cptr > '~') {
-					p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-					p->RIOError.Entry = Entry;
-					return -ENXIO;
-				}
-				cptr++;
-			}
-		}
-
-		/*
-		 ** If the entry saved was a tentative entry then just forget
-		 ** about it.
-		 */
-		if (MapP->Flags & SLOT_TENTATIVE) {
-			MapP->HostUniqueNum = 0;
-			MapP->RtaUniqueNum = 0;
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
-		if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) {	/* (3) */
-			if (MapP->ID || MapP->SysPort || MapP->Flags) {
-				rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
-				p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
-		for (Host = 0; Host < p->RIONumHosts; Host++) {	/* (4) */
-			if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
-				HostP = &p->RIOHosts[Host];
-				/*
-				 ** having done the lookup, we don't really want to do
-				 ** it again, so hang the host number in a safe place
-				 */
-				MapP->Topology[0].Unit = Host;
-				break;
-			}
-		}
-
-		if (Host >= p->RIONumHosts) {
-			rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
-			MapP->HostUniqueNum = 0;
-			/* MapP->RtaUniqueNum   = 0; */
-			/* MapP->ID                     = 0; */
-			/* MapP->Flags           = 0; */
-			/* MapP->SysPort                 = 0; */
-			/* MapP->Name[0]                 = 0; */
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
-		if (MapP->RtaUniqueNum) {	/* (5) */
-			if (!MapP->ID) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
-				p->RIOError.Error = ZERO_RTA_ID;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			if (MapP->ID > MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
-				p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
-				if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
-					rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
-					p->RIOError.Error = DUPLICATED_RTA_ID;
-					p->RIOError.Entry = Entry;
-					p->RIOError.Other = SubEnt;
-					return -ENXIO;
-				}
-				/*
-				 ** If the RtaUniqueNum is the same, it may be looking at both
-				 ** entries for a 16 port RTA, so check the ids
-				 */
-				if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
-				    && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
-					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
-					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
-					p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
-					p->RIOError.Entry = Entry;
-					p->RIOError.Other = SubEnt;
-					return -ENXIO;
-				}
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
-			/* (7a) */
-			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
-				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
-				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
-			/* (7b) */
-			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
-				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
-				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
-				if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
-					continue;
-				if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
-					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
-					/* (8) */
-					if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
-						rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
-						p->RIOError.Error = TTY_NUMBER_IN_USE;
-						p->RIOError.Entry = Entry;
-						p->RIOError.Other = SubEnt;
-						return -ENXIO;
-					}
-					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
-					if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) {	/* (9) */
-						rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
-						p->RIOError.Error = NAME_USED_TWICE;
-						p->RIOError.Entry = Entry;
-						p->RIOError.Other = SubEnt;
-						return -ENXIO;
-					}
-				}
-			}
-		} else {	/* (6) */
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
-			if (MapP->ID) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
-				p->RIOError.Error = HOST_ID_NOT_ZERO;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			if (MapP->SysPort != NO_PORT) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
-				p->RIOError.Error = HOST_SYSPORT_BAD;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-		}
-	}
-
-	/*
-	 ** wow! if we get here then it's a goody!
-	 */
-
-	/*
-	 ** Zero the (old) entries for each host...
-	 */
-	for (Host = 0; Host < RIO_HOSTS; Host++) {
-		for (Entry = 0; Entry < MAX_RUP; Entry++) {
-			memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map));
-		}
-		memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name));
-	}
-
-	/*
-	 ** Copy in the new table entries
-	 */
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
-		MapP = &p->RIOConnectTable[Entry];
-
-		/*
-		 ** Now, if it is an empty slot ignore it!
-		 */
-		if (MapP->HostUniqueNum == 0)
-			continue;
-
-		/*
-		 ** we saved the host number earlier, so grab it back
-		 */
-		HostP = &p->RIOHosts[MapP->Topology[0].Unit];
-
-		/*
-		 ** If it is a host, then we only need to fill in the name field.
-		 */
-		if (MapP->ID == 0) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
-			memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN);
-			continue;
-		}
-
-		/*
-		 ** Its an RTA entry, so fill in the host mapping entries for it
-		 ** and the port mapping entries. Notice that entry zero is for
-		 ** ID one.
-		 */
-		HostMapP = &HostP->Mapping[MapP->ID - 1];
-
-		if (MapP->Flags & SLOT_IN_USE) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
-			/*
-			 ** structure assign, then sort out the bits we shouldn't have done
-			 */
-			*HostMapP = *MapP;
-
-			HostMapP->Flags = SLOT_IN_USE;
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				HostMapP->Flags |= RTA16_SECOND_SLOT;
-
-			RIOReMapPorts(p, HostP, HostMapP);
-		} else {
-			rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
-		}
-	}
-
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
-	}
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
-			p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
-			p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
-		}
-		for (Entry = 0; Entry < MAX_RUP; Entry++) {
-			for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
-				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
-				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
-			}
-		}
-		if (!p->RIOHosts[Host].Name[0]) {
-			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
-			p->RIOHosts[Host].Name[5] += Host;
-		}
-		/*
-		 ** Check that default name assigned is unique.
-		 */
-		Host1 = Host;
-		NameIsUnique = 0;
-		while (!NameIsUnique) {
-			NameIsUnique = 1;
-			for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
-				if (Host2 == Host)
-					continue;
-				if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
-				    == 0) {
-					NameIsUnique = 0;
-					Host1++;
-					if (Host1 >= p->RIONumHosts)
-						Host1 = 0;
-					p->RIOHosts[Host].Name[5] = '1' + Host1;
-				}
-			}
-		}
-		/*
-		 ** Rename host if name already used.
-		 */
-		if (Host1 != Host) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
-			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
-			p->RIOHosts[Host].Name[5] += Host1;
-		}
-		rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
-	}
-	return 0;
-}
-
-/*
-** User process needs the config table - build it from first
-** principles.
-**
-*	FIXME: SMP locking
-*/
-int RIOApel(struct rio_info *p)
-{
-	int Host;
-	int link;
-	int Rup;
-	int Next = 0;
-	struct Map *MapP;
-	struct Host *HostP;
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
-
-	memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES);
-
-	for (Host = 0; Host < RIO_HOSTS; Host++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
-		HostP = &p->RIOHosts[Host];
-		rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-		MapP = &p->RIOConnectTable[Next++];
-		MapP->HostUniqueNum = HostP->UniqueNum;
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-			continue;
-		}
-		MapP->RtaUniqueNum = 0;
-		MapP->ID = 0;
-		MapP->Flags = SLOT_IN_USE;
-		MapP->SysPort = NO_PORT;
-		for (link = 0; link < LINKS_PER_UNIT; link++)
-			MapP->Topology[link] = HostP->Topology[link];
-		memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN);
-		for (Rup = 0; Rup < MAX_RUP; Rup++) {
-			if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
-				p->RIOConnectTable[Next] = HostP->Mapping[Rup];
-				if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
-					p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
-				if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
-					p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
-				if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
-					p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
-				Next++;
-			}
-		}
-		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-	}
-	return 0;
-}
-
-/*
-** config.rio has taken a dislike to one of the gross maps entries.
-** if the entry is suitably inactive, then we can gob on it and remove
-** it from the table.
-*/
-int RIODeleteRta(struct rio_info *p, struct Map *MapP)
-{
-	int host, entry, port, link;
-	int SysPort;
-	struct Host *HostP;
-	struct Map *HostMapP;
-	struct Port *PortP;
-	int work_done = 0;
-	unsigned long lock_flags, sem_flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		HostP = &p->RIOHosts[host];
-
-		rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-			continue;
-		}
-
-		for (entry = 0; entry < MAX_RUP; entry++) {
-			if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
-				HostMapP = &HostP->Mapping[entry];
-				rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
-
-				/*
-				 ** Check all four links of the unit are disconnected
-				 */
-				for (link = 0; link < LINKS_PER_UNIT; link++) {
-					if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
-						rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
-						p->RIOError.Error = UNIT_IS_IN_USE;
-						rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-						return -EBUSY;
-					}
-				}
-				/*
-				 ** Slot has been allocated, BUT not booted/routed/
-				 ** connected/selected or anything else-ed
-				 */
-				SysPort = HostMapP->SysPort;
-
-				if (SysPort != NO_PORT) {
-					for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
-						PortP = p->RIOPortp[port];
-						rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
-
-						rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
-
-						PortP->Mapped = 0;
-
-						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-
-							rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
-							PortP->TxBufferIn = PortP->TxBufferOut = 0;
-							/* What should I do 
-							   wakeup( &PortP->TxBufferIn );
-							   wakeup( &PortP->TxBufferOut);
-							 */
-							PortP->InUse = NOT_INUSE;
-							/* What should I do 
-							   wakeup( &PortP->InUse );
-							   signal(PortP->TtyP->t_pgrp,SIGKILL);
-							   ttyflush(PortP->TtyP,(FREAD|FWRITE));
-							 */
-							PortP->State |= RIO_CLOSING | RIO_DELETED;
-						}
-
-						/*
-						 ** For the second slot of a 16 port RTA, the
-						 ** driver needs to reset the changes made to
-						 ** the phb to port mappings in RIORouteRup.
-						 */
-						if (PortP->SecondBlock) {
-							u16 dest_unit = HostMapP->ID;
-							u16 dest_port = port - SysPort;
-							u16 __iomem *TxPktP;
-							struct PKT __iomem *Pkt;
-
-							for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
-								/*
-								 ** *TxPktP is the pointer to the
-								 ** transmit packet on the host card.
-								 ** This needs to be translated into
-								 ** a 32 bit pointer so it can be
-								 ** accessed from the driver.
-								 */
-								Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
-								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port);
-								writew(dest_unit, &Pkt->dest_unit);
-								writew(dest_port, &Pkt->dest_port);
-							}
-							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
-							writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
-						}
-						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
-					}
-				}
-				rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
-				memset(HostMapP, 0, sizeof(struct Map));
-				work_done++;
-			}
-		}
-		rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-	}
-
-	/* XXXXX lock me up */
-	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-		if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
-			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
-			work_done++;
-		}
-		if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
-			memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map));
-			work_done++;
-		}
-	}
-	if (work_done)
-		return 0;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
-	p->RIOError.Error = COULDNT_FIND_ENTRY;
-	return -ENXIO;
-}
-
-int RIOAssignRta(struct rio_info *p, struct Map *MapP)
-{
-	int host;
-	struct Map *HostMapP;
-	char *sptr;
-	int link;
-
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
-
-	if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
-		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	if (MapP->RtaUniqueNum == 0) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
-		p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
-		return -EINVAL;
-	}
-	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
-		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
-		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/*
-	 ** Copy the name across to the map entry.
-	 */
-	MapP->Name[MAX_NAME_LEN - 1] = '\0';
-	sptr = MapP->Name;
-	while (*sptr) {
-		if (*sptr < ' ' || *sptr > '~') {
-			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
-			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-			return -EINVAL;
-		}
-		sptr++;
-	}
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
-			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
-				p->RIOError.Error = HOST_NOT_RUNNING;
-				return -ENXIO;
-			}
-
-			/*
-			 ** Now we have a host we need to allocate an ID
-			 ** if the entry does not already have one.
-			 */
-			if (MapP->ID == (u16) - 1) {
-				int nNewID;
-
-				rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
-				/*
-				 ** The idea here is to allow RTA's to be assigned
-				 ** before they actually appear on the network.
-				 ** This allows the addition of RTA's without having
-				 ** to plug them in.
-				 ** What we do is:
-				 **  - Find a free ID and allocate it to the RTA.
-				 **  - If this map entry is the second half of a
-				 **    16 port entry then find the other half and
-				 **    make sure the 2 cross reference each other.
-				 */
-				if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
-					p->RIOError.Error = COULDNT_FIND_ENTRY;
-					return -EBUSY;
-				}
-				MapP->ID = (u16) nNewID + 1;
-				rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
-				HostMapP = &p->RIOHosts[host].Mapping[nNewID];
-				HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
-				HostMapP->HostUniqueNum = MapP->HostUniqueNum;
-				HostMapP->ID = MapP->ID;
-				for (link = 0; link < LINKS_PER_UNIT; link++) {
-					HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
-					HostMapP->Topology[link].Link = NO_LINK;
-				}
-				if (MapP->Flags & RTA16_SECOND_SLOT) {
-					int unit;
-
-					for (unit = 0; unit < MAX_RUP; unit++)
-						if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
-							break;
-					if (unit == MAX_RUP) {
-						p->RIOError.Error = COULDNT_FIND_ENTRY;
-						return -EBUSY;
-					}
-					HostMapP->Flags |= RTA16_SECOND_SLOT;
-					HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
-					p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
-					rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
-				}
-			}
-
-			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
-
-			if (HostMapP->Flags & SLOT_IN_USE) {
-				rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
-				p->RIOError.Error = ID_ALREADY_IN_USE;
-				return -EBUSY;
-			}
-
-			/*
-			 ** Assign the sys ports and the name, and mark the slot as
-			 ** being in use.
-			 */
-			HostMapP->SysPort = MapP->SysPort;
-			if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
-				memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
-			HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
-#ifdef NEED_TO_FIX
-			RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
-#endif
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				HostMapP->Flags |= RTA16_SECOND_SLOT;
-
-			RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
-			/*
-			 ** Adjust 2nd block of 8 phbs
-			 */
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
-
-			if (HostMapP->SysPort != NO_PORT) {
-				if (HostMapP->SysPort < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = HostMapP->SysPort;
-				if (HostMapP->SysPort > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = HostMapP->SysPort;
-			}
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
-			else
-				rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
-			return 0;
-		}
-	}
-	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
-	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
-	return -ENXIO;
-}
-
-
-int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP)
-{
-	struct Port *PortP;
-	unsigned int SubEnt;
-	unsigned int HostPort;
-	unsigned int SysPort;
-	u16 RtaType;
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
-
-	/*
-	 ** We need to tell the UnixRups which sysport the rup corresponds to
-	 */
-	HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
-
-	if (HostMapP->SysPort == NO_PORT)
-		return (0);
-
-	RtaType = GetUnitType(HostMapP->RtaUniqueNum);
-	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
-
-	/*
-	 ** now map each of its eight ports
-	 */
-	for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
-		SysPort = HostMapP->SysPort + SubEnt;	/* portnumber within system */
-		/* portnumber on host */
-
-		HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
-
-		rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
-		PortP = p->RIOPortp[SysPort];
-		rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
-
-		/*
-		 ** Point at all the real neat data structures
-		 */
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->HostP = HostP;
-		PortP->Caddr = HostP->Caddr;
-
-		/*
-		 ** The PhbP cannot be filled in yet
-		 ** unless the host has been booted
-		 */
-		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
-			struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
-			PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
-			PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
-			PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
-			PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
-			PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
-			PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
-		} else
-			PortP->PhbP = NULL;
-
-		/*
-		 ** port related flags
-		 */
-		PortP->HostPort = HostPort;
-		/*
-		 ** For each part of a 16 port RTA, RupNum is ID - 1.
-		 */
-		PortP->RupNum = HostMapP->ID - 1;
-		if (HostMapP->Flags & RTA16_SECOND_SLOT) {
-			PortP->ID2 = HostMapP->ID2 - 1;
-			PortP->SecondBlock = 1;
-		} else {
-			PortP->ID2 = 0;
-			PortP->SecondBlock = 0;
-		}
-		PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
-
-		/*
-		 ** If the port was already mapped then thats all we need to do.
-		 */
-		if (PortP->Mapped) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			continue;
-		} else
-			HostMapP->Flags &= ~RTA_NEWBOOT;
-
-		PortP->State = 0;
-		PortP->Config = 0;
-		/*
-		 ** Check out the module type - if it is special (read only etc.)
-		 ** then we need to set flags in the PortP->Config.
-		 ** Note: For 16 port RTA, all ports are of the same type.
-		 */
-		if (RtaType == TYPE_RTA16) {
-			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
-		} else {
-			if (SubEnt < PORTS_PER_MODULE)
-				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
-			else
-				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
-		}
-
-		/*
-		 ** more port related flags
-		 */
-		PortP->PortState = 0;
-		PortP->ModemLines = 0;
-		PortP->ModemState = 0;
-		PortP->CookMode = COOK_WELL;
-		PortP->ParamSem = 0;
-		PortP->FlushCmdBodge = 0;
-		PortP->WflushFlag = 0;
-		PortP->MagicFlags = 0;
-		PortP->Lock = 0;
-		PortP->Store = 0;
-		PortP->FirstOpen = 1;
-
-		/*
-		 ** Buffers 'n things
-		 */
-		PortP->RxDataStart = 0;
-		PortP->Cor2Copy = 0;
-		PortP->Name = &HostMapP->Name[0];
-		PortP->statsGather = 0;
-		PortP->txchars = 0;
-		PortP->rxchars = 0;
-		PortP->opens = 0;
-		PortP->closes = 0;
-		PortP->ioctls = 0;
-		if (PortP->TxRingBuffer)
-			memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
-		else if (p->RIOBufferSize) {
-			PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL);
-		}
-		PortP->TxBufferOut = 0;
-		PortP->TxBufferIn = 0;
-		PortP->Debug = 0;
-		/*
-		 ** LastRxTgl stores the state of the rx toggle bit for this
-		 ** port, to be compared with the state of the next pkt received.
-		 ** If the same, we have received the same rx pkt from the RTA
-		 ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
-		 */
-		PortP->LastRxTgl = ~(u8) PHB_RX_TGL;
-
-		/*
-		 ** and mark the port as usable
-		 */
-		PortP->Mapped = 1;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	}
-	if (HostMapP->SysPort < p->RIOFirstPortsMapped)
-		p->RIOFirstPortsMapped = HostMapP->SysPort;
-	if (HostMapP->SysPort > p->RIOLastPortsMapped)
-		p->RIOLastPortsMapped = HostMapP->SysPort;
-
-	return 0;
-}
-
-int RIOChangeName(struct rio_info *p, struct Map *MapP)
-{
-	int host;
-	struct Map *HostMapP;
-	char *sptr;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
-
-	if (MapP->ID > MAX_RUP) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
-		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	MapP->Name[MAX_NAME_LEN - 1] = '\0';
-	sptr = MapP->Name;
-
-	while (*sptr) {
-		if (*sptr < ' ' || *sptr > '~') {
-			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
-			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-			return -EINVAL;
-		}
-		sptr++;
-	}
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
-			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
-				p->RIOError.Error = HOST_NOT_RUNNING;
-				return -ENXIO;
-			}
-			if (MapP->ID == 0) {
-				memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN);
-				return 0;
-			}
-
-			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
-
-			if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
-				p->RIOError.Error = RTA_NUMBER_WRONG;
-				return -ENXIO;
-			}
-			memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
-			return 0;
-		}
-	}
-	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
-	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
-	return -ENXIO;
-}
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
deleted file mode 100644
index 8a90393..0000000
--- a/drivers/char/rio/riotty.c
+++ /dev/null
@@ -1,654 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: riotty.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:47
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)riotty.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#define __EXPLICIT_DEF_H__
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-static void RIOClearUp(struct Port *PortP);
-
-/* Below belongs in func.h */
-int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-
-
-extern struct rio_info *p;
-
-
-int riotopen(struct tty_struct *tty, struct file *filp)
-{
-	unsigned int SysPort;
-	int repeat_this = 250;
-	struct Port *PortP;	/* pointer to the port structure */
-	unsigned long flags;
-	int retval = 0;
-
-	func_enter();
-
-	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
-	   is going to oops.
-	 */
-	tty->driver_data = NULL;
-
-	SysPort = rio_minor(tty);
-
-	if (p->RIOFailed) {
-		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped);
-
-	/*
-	 ** Validate that we have received a legitimate request.
-	 ** Currently, just check that we are opening a port on
-	 ** a host card that actually exists, and that the port
-	 ** has been mapped onto a host.
-	 */
-	if (SysPort >= RIO_PORTS) {	/* out of range ? */
-		rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
-		func_exit();
-		return -ENXIO;
-	}
-
-	/*
-	 ** Grab pointer to the port stucture
-	 */
-	PortP = p->RIOPortp[SysPort];	/* Get control struc */
-	rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
-	if (!PortP->Mapped) {	/* we aren't mapped yet! */
-		/*
-		 ** The system doesn't know which RTA this port
-		 ** corresponds to.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	tty->driver_data = PortP;
-
-	PortP->gs.port.tty = tty;
-	PortP->gs.port.count++;
-
-	rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);
-
-	retval = gs_init_port(&PortP->gs);
-	if (retval) {
-		PortP->gs.port.count--;
-		return -ENXIO;
-	}
-	/*
-	 ** If the host hasn't been booted yet, then
-	 ** fail
-	 */
-	if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
-		rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	/*
-	 ** If the RTA has not booted yet and the user has choosen to block
-	 ** until the RTA is present then we must spin here waiting for
-	 ** the RTA to boot.
-	 */
-	/* I find the above code a bit hairy. I find the below code
-	   easier to read and shorter. Now, if it works too that would
-	   be great... -- REW 
-	 */
-	rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
-	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
-		if (!PortP->WaitUntilBooted) {
-			rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
-			func_exit();
-			return -ENXIO;
-		}
-
-		/* Under Linux you'd normally use a wait instead of this
-		   busy-waiting. I'll stick with the old implementation for
-		   now. --REW
-		 */
-		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
-			func_exit();
-			return -EINTR;
-		}
-		if (repeat_this-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
-			func_exit();
-			return -EIO;
-		}
-	}
-	rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	if (p->RIOHalted) {
-		goto bombout;
-	}
-
-	/*
-	 ** If the port is in the final throws of being closed,
-	 ** we should wait here (politely), waiting
-	 ** for it to finish, so that it doesn't close us!
-	 */
-	while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
-		if (repeat_this-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-			RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-			retval = -EINTR;
-			goto bombout;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			retval = -EINTR;
-			goto bombout;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-
-	if (!PortP->Mapped) {
-		rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		retval = -ENXIO;
-		func_exit();
-		return retval;
-	}
-
-	if (p->RIOHalted) {
-		goto bombout;
-	}
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
-** we need to make sure that the flags are clear when the port is opened.
-*/
-	/* Uh? Suppose I turn these on and then another process opens
-	   the port again? The flags get cleared! Not good. -- REW */
-	if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
-	}
-
-	if (!(PortP->firstOpen)) {	/* First time ? */
-		rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");
-
-
-		PortP->firstOpen++;
-		PortP->CookMode = 0;	/* XXX RIOCookMode(tp); */
-		PortP->InUse = NOT_INUSE;
-
-		/* Tentative fix for bug PR27. Didn't work. */
-		/* PortP->gs.xmit_cnt = 0; */
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-		/* Someone explain to me why this delay/config is
-		   here. If I read the docs correctly the "open"
-		   command piggybacks the parameters immediately.
-		   -- REW */
-		RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		/*
-		 ** wait for the port to be not closed.
-		 */
-		while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				func_exit();
-				return -EINTR;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-
-		if (p->RIOHalted) {
-			retval = -EIO;
-		      bombout:
-			/*                    RIOClearUp( PortP ); */
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return retval;
-		}
-		rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
-	}
-	rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
-	/*
-	 ** ACTION
-	 ** insert test for carrier here. -- ???
-	 ** I already see that test here. What's the deal? -- REW
-	 */
-	if ((PortP->gs.port.tty->termios->c_cflag & CLOCAL) ||
-			(PortP->ModemState & RIOC_MSVR1_CD)) {
-		rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
-		/*
-		   tp->tm.c_state |= CARR_ON;
-		   wakeup((caddr_t) &tp->tm.c_canq);
-		 */
-		PortP->State |= RIO_CARR_ON;
-		wake_up_interruptible(&PortP->gs.port.open_wait);
-	} else {	/* no carrier - wait for DCD */
-			/*
-		   while (!(PortP->gs.port.tty->termios->c_state & CARR_ON) &&
-		   !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
-		 */
-		while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
-				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
-			/*
-			   PortP->gs.port.tty->termios->c_state |= WOPEN;
-			 */
-			PortP->State |= RIO_WOPEN;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				/*
-				 ** ACTION: verify that this is a good thing
-				 ** to do here. -- ???
-				 ** I think it's OK. -- REW
-				 */
-				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				/*
-				   tp->tm.c_state &= ~WOPEN;
-				 */
-				PortP->State &= ~RIO_WOPEN;
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				func_exit();
-				return -EINTR;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-		PortP->State &= ~RIO_WOPEN;
-	}
-	if (p->RIOHalted)
-		goto bombout;
-	rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
-	PortP->State |= RIO_MOPEN;
-
-	if (p->RIOHalted)
-		goto bombout;
-
-	rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");
-
-	/*
-	 ** Count opens for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->opens++;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
-	func_exit();
-	return 0;
-}
-
-/*
-** RIOClose the port.
-** The operating system thinks that this is last close for the device.
-** As there are two interfaces to the port (Modem and tty), we need to
-** check that both are closed before we close the device.
-*/
-int riotclose(void *ptr)
-{
-	struct Port *PortP = ptr;	/* pointer to the port structure */
-	int deleted = 0;
-	int try = -1;		/* Disable the timeouts by setting them to -1 */
-	int repeat_this = -1;	/* Congrats to those having 15 years of
-				   uptime! (You get to break the driver.) */
-	unsigned long end_time;
-	struct tty_struct *tty;
-	unsigned long flags;
-	int rv = 0;
-
-	rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);
-
-	/* PortP = p->RIOPortp[SysPort]; */
-	rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP);
-	/* tp = PortP->TtyP; *//* Get tty */
-	tty = PortP->gs.port.tty;
-	rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty);
-
-	if (PortP->gs.closing_wait)
-		end_time = jiffies + PortP->gs.closing_wait;
-	else
-		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	/*
-	 ** Setting this flag will make any process trying to open
-	 ** this port block until we are complete closing it.
-	 */
-	PortP->State |= RIO_CLOSING;
-
-	if ((PortP->State & RIO_DELETED)) {
-		rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
-		deleted = 1;
-	}
-
-	if (p->RIOHalted) {
-		RIOClearUp(PortP);
-		rv = -EIO;
-		goto close_end;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
-	/*
-	 ** clear the open bits for this device
-	 */
-	PortP->State &= ~RIO_MOPEN;
-	PortP->State &= ~RIO_CARR_ON;
-	PortP->ModemState &= ~RIOC_MSVR1_CD;
-	/*
-	 ** If the device was open as both a Modem and a tty line
-	 ** then we need to wimp out here, as the port has not really
-	 ** been finally closed (gee, whizz!) The test here uses the
-	 ** bit for the OTHER mode of operation, to see if THAT is
-	 ** still active!
-	 */
-	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		/*
-		 ** The port is still open for the other task -
-		 ** return, pretending that we are still active.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
-		PortP->State &= ~RIO_CLOSING;
-		if (PortP->firstOpen)
-			PortP->firstOpen--;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return -EIO;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");
-
-	PortP->State &= ~RIO_DYNOROD;
-
-	/*
-	 ** This is where we wait for the port
-	 ** to drain down before closing. Bye-bye....
-	 ** (We never meant to do this)
-	 */
-	rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");
-
-	if (!deleted)
-		while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
-			if (repeat_this-- <= 0) {
-				rv = -EINTR;
-				rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				goto close_end;
-			}
-			rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-				rv = -EINTR;
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				goto close_end;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-
-	PortP->TxBufferIn = PortP->TxBufferOut = 0;
-	repeat_this = 0xff;
-
-	PortP->InUse = 0;
-	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		/*
-		 ** The port has been re-opened for the other task -
-		 ** return, pretending that we are still active.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
-		PortP->State &= ~RIO_CLOSING;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (PortP->firstOpen)
-			PortP->firstOpen--;
-		return -EIO;
-	}
-
-	if (p->RIOHalted) {
-		RIOClearUp(PortP);
-		goto close_end;
-	}
-
-	/* Can't call RIOShortCommand with the port locked. */
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) {
-		RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		goto close_end;
-	}
-
-	if (!deleted)
-		while (try && (PortP->PortState & PORT_ISOPEN)) {
-			try--;
-			if (time_after(jiffies, end_time)) {
-				rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				break;
-			}
-			rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
-
-			if (p->RIOHalted) {
-				RIOClearUp(PortP);
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				goto close_end;
-			}
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				break;
-			}
-		}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
-
-	/* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
-*/
-	PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
-
-	/*
-	 ** Count opens for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->closes++;
-
-close_end:
-	/* XXX: Why would a "DELETED" flag be reset here? I'd have
-	   thought that a "deleted" flag means that the port was
-	   permanently gone, but here we can make it reappear by it
-	   being in close during the "deletion".
-	 */
-	PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
-	if (PortP->firstOpen)
-		PortP->firstOpen--;
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
-	return rv;
-}
-
-
-
-static void RIOClearUp(struct Port *PortP)
-{
-	rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
-	PortP->Config = 0;	/* Direct semaphore */
-	PortP->PortState = 0;
-	PortP->firstOpen = 0;
-	PortP->FlushCmdBodge = 0;
-	PortP->ModemState = PortP->CookMode = 0;
-	PortP->Mapped = 0;
-	PortP->WflushFlag = 0;
-	PortP->MagicFlags = 0;
-	PortP->RxDataStart = 0;
-	PortP->TxBufferIn = 0;
-	PortP->TxBufferOut = 0;
-}
-
-/*
-** Put a command onto a port.
-** The PortPointer, command, length and arg are passed.
-** The len is the length *inclusive* of the command byte,
-** and so for a command that takes no data, len==1.
-** The arg is a single byte, and is only used if len==2.
-** Other values of len aren't allowed, and will cause
-** a panic.
-*/
-int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
-{
-	struct PKT __iomem *PacketP;
-	int retries = 20;	/* at 10 per second -> 2 seconds */
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
-
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
-		return RIO_FAIL;
-	}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	/*
-	 ** If the port is in use for pre-emptive command, then wait for it to
-	 ** be free again.
-	 */
-	while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (retries-- <= 0) {
-			return RIO_FAIL;
-		}
-		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
-			return RIO_FAIL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return RIO_FAIL;
-	}
-
-	while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (retries-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
-			return RIO_FAIL;
-		}
-		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
-			return RIO_FAIL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-
-	if (p->RIOHalted) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return RIO_FAIL;
-	}
-
-	/*
-	 ** set the command byte and the argument byte
-	 */
-	writeb(command, &PacketP->data[0]);
-
-	if (len == 2)
-		writeb(arg, &PacketP->data[1]);
-
-	/*
-	 ** set the length of the packet and set the command bit.
-	 */
-	writeb(PKT_CMD_BIT | len, &PacketP->len);
-
-	add_transmit(PortP);
-	/*
-	 ** Count characters transmitted for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->txchars += len;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
-}
-
-
diff --git a/drivers/char/rio/route.h b/drivers/char/rio/route.h
deleted file mode 100644
index 46e9637..0000000
--- a/drivers/char/rio/route.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                 R O U T E     H E A D E R
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _route_h
-#define _route_h
-
-#define MAX_LINKS 4
-#define MAX_NODES 17		/* Maximum nodes in a subnet */
-#define NODE_BYTES ((MAX_NODES / 8) + 1)	/* Number of bytes needed for
-						   1 bit per node */
-#define ROUTE_DATA_SIZE  (NODE_BYTES + 2)	/* Number of bytes for complete
-						   info about cost etc. */
-#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
-					      /* Number of nodes we can squeeze
-					         into one packet */
-#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
-/************************************************
- * Define the types of command for the ROUTE RUP.
- ************************************************/
-#define ROUTE_REQUEST    0	/* Request an ID */
-#define ROUTE_FOAD       1	/* Kill the RTA */
-#define ROUTE_ALREADY    2	/* ID given already */
-#define ROUTE_USED       3	/* All ID's used */
-#define ROUTE_ALLOCATE   4	/* Here it is */
-#define ROUTE_REQ_TOP    5	/* I bet you didn't expect....
-				   the Topological Inquisition */
-#define ROUTE_TOPOLOGY   6	/* Topology request answered FD */
-/*******************************************************************
- * Define the Route Map Structure
- *
- * The route map gives a pointer to a Link Structure to use.
- * This allows Disconnected Links to be checked quickly
- ******************************************************************/
-typedef struct COST_ROUTE COST_ROUTE;
-struct COST_ROUTE {
-	unsigned char cost;	/* Cost down this link */
-	unsigned char route[NODE_BYTES];	/* Nodes through this route */
-};
-
-typedef struct ROUTE_STR ROUTE_STR;
-struct ROUTE_STR {
-	COST_ROUTE cost_route[MAX_LINKS];
-	/* cost / route for this link */
-	ushort favoured;	/* favoured link */
-};
-
-
-#define NO_LINK            (short) 5	/* Link unattached */
-#define ROUTE_NO_ID        (short) 100	/* No Id */
-#define ROUTE_DISCONNECT   (ushort) 0xff	/* Not connected */
-#define ROUTE_INTERCONNECT (ushort) 0x40	/* Sub-net interconnect */
-
-
-#define SYNC_RUP         (ushort) 255
-#define COMMAND_RUP      (ushort) 254
-#define ERROR_RUP        (ushort) 253
-#define POLL_RUP         (ushort) 252
-#define BOOT_RUP         (ushort) 251
-#define ROUTE_RUP        (ushort) 250
-#define STATUS_RUP       (ushort) 249
-#define POWER_RUP        (ushort) 248
-
-#define HIGHEST_RUP      (ushort) 255	/* Set to Top one */
-#define LOWEST_RUP       (ushort) 248	/* Set to bottom one */
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/rup.h b/drivers/char/rio/rup.h
deleted file mode 100644
index 4ae90cb..0000000
--- a/drivers/char/rio/rup.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******               R U P   S T R U C T U R E
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _rup_h
-#define _rup_h 1
-
-#define MAX_RUP          ((short) 16)
-#define PKTS_PER_RUP     ((short) 2)	/* They are always used in pairs */
-
-/*************************************************
- * Define all the  packet request stuff
- ************************************************/
-#define TX_RUP_INACTIVE          0	/* Nothing to transmit */
-#define TX_PACKET_READY          1	/* Transmit packet ready */
-#define TX_LOCK_RUP              2	/* Transmit side locked */
-
-#define RX_RUP_INACTIVE          0	/* Nothing received */
-#define RX_PACKET_READY          1	/* Packet received */
-
-#define RUP_NO_OWNER             0xff	/* RUP not owned by any process */
-
-struct RUP {
-	u16 txpkt;		/* Outgoing packet */
-	u16 rxpkt;		/* Incoming packet */
-	u16 link;		/* Which link to send down? */
-	u8 rup_dest_unit[2];	/* Destination unit */
-	u16 handshake;		/* For handshaking */
-	u16 timeout;		/* Timeout */
-	u16 status;		/* Status */
-	u16 txcontrol;		/* Transmit control */
-	u16 rxcontrol;		/* Receive control */
-};
-
-#endif
-
-/*********** end of file ***********/
diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h
deleted file mode 100644
index 7abf0cb..0000000
--- a/drivers/char/rio/unixrup.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-**
-**	Module		: unixrup.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:20
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)unixrup.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_unixrup_h__
-#define __rio_unixrup_h__
-
-/*
-**    UnixRup data structure. This contains pointers to actual RUPs on the
-**    host card, and all the command/boot control stuff.
-*/
-struct UnixRup {
-	struct CmdBlk *CmdsWaitingP;	/* Commands waiting to be done */
-	struct CmdBlk *CmdPendingP;	/* The command currently being sent */
-	struct RUP __iomem *RupP;	/* the Rup to send it to */
-	unsigned int Id;		/* Id number */
-	unsigned int BaseSysPort;	/* SysPort of first tty on this RTA */
-	unsigned int ModTypes;		/* Modules on this RTA */
-	spinlock_t RupLock;	/* Lock structure for MPX */
-	/*    struct lockb     RupLock;	*//* Lock structure for MPX */
-};
-
-#endif				/* __rio_unixrup_h__ */
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
deleted file mode 100644
index af4de1f..0000000
--- a/drivers/char/riscom8.c
+++ /dev/null
@@ -1,1560 +0,0 @@
-/*
- *      linux/drivers/char/riscom.c  -- RISCom/8 multiport serial driver.
- *
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card
- *      programming info was obtained from various drivers for other OSes
- *	(FreeBSD, ISC, etc), but no source code from those drivers were
- *	directly included in this driver.
- *
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *	Revision 1.1
- *
- *	ChangeLog:
- *	Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 27-Jun-2001
- *	- get rid of check_region and several cleanups
- */
-
-#include <linux/module.h>
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/tty_flip.h>
-#include <linux/spinlock.h>
-#include <linux/device.h>
-
-#include <linux/uaccess.h>
-
-#include "riscom8.h"
-#include "riscom8_reg.h"
-
-/* Am I paranoid or not ? ;-) */
-#define RISCOM_PARANOIA_CHECK
-
-/*
- * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
- * You can slightly speed up things by #undefing the following option,
- * if you are REALLY sure that your board is correct one.
- */
-
-#define RISCOM_BRAIN_DAMAGED_CTS
-
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#undef RC_REPORT_FIFO
-#undef RC_REPORT_OVERRUN
-
-
-#define RISCOM_LEGAL_FLAGS \
-	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
-	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
-	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
-
-static struct tty_driver *riscom_driver;
-
-static DEFINE_SPINLOCK(riscom_lock);
-
-static struct riscom_board rc_board[RC_NBOARD] =  {
-	{
-		.base	= RC_IOBASE1,
-	},
-	{
-		.base	= RC_IOBASE2,
-	},
-	{
-		.base	= RC_IOBASE3,
-	},
-	{
-		.base	= RC_IOBASE4,
-	},
-};
-
-static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
-
-/* RISCom/8 I/O ports addresses (without address translation) */
-static unsigned short rc_ioport[] =  {
-#if 1
-	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
-#else
-	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
-	0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
-	0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
-#endif
-};
-#define RC_NIOPORT	ARRAY_SIZE(rc_ioport)
-
-
-static int rc_paranoia_check(struct riscom_port const *port,
-				    char *name, const char *routine)
-{
-#ifdef RISCOM_PARANOIA_CHECK
-	static const char badmagic[] = KERN_INFO
-		"rc: Warning: bad riscom port magic number for device %s in %s\n";
-	static const char badinfo[] = KERN_INFO
-		"rc: Warning: null riscom port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != RISCOM8_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/*
- *
- *  Service functions for RISCom/8 driver.
- *
- */
-
-/* Get board number from pointer */
-static inline int board_No(struct riscom_board const *bp)
-{
-	return bp - rc_board;
-}
-
-/* Get port number from pointer */
-static inline int port_No(struct riscom_port const *port)
-{
-	return RC_PORT(port - rc_port);
-}
-
-/* Get pointer to board from pointer to port */
-static inline struct riscom_board *port_Board(struct riscom_port const *port)
-{
-	return &rc_board[RC_BOARD(port - rc_port)];
-}
-
-/* Input Byte from CL CD180 register */
-static inline unsigned char rc_in(struct riscom_board const *bp,
-							unsigned short reg)
-{
-	return inb(bp->base + RC_TO_ISA(reg));
-}
-
-/* Output Byte to CL CD180 register */
-static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
-			  unsigned char val)
-{
-	outb(val, bp->base + RC_TO_ISA(reg));
-}
-
-/* Wait for Channel Command Register ready */
-static void rc_wait_CCR(struct riscom_board const *bp)
-{
-	unsigned long delay;
-
-	/* FIXME: need something more descriptive then 100000 :) */
-	for (delay = 100000; delay; delay--)
-		if (!rc_in(bp, CD180_CCR))
-			return;
-
-	printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-/*
- *  RISCom/8 probe functions.
- */
-
-static int rc_request_io_range(struct riscom_board * const bp)
-{
-	int i;
-
-	for (i = 0; i < RC_NIOPORT; i++)
-		if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
-				   "RISCom/8"))  {
-			goto out_release;
-		}
-	return 0;
-out_release:
-	printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
-			 board_No(bp), bp->base);
-	while (--i >= 0)
-		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
-	return 1;
-}
-
-static void rc_release_io_range(struct riscom_board * const bp)
-{
-	int i;
-
-	for (i = 0; i < RC_NIOPORT; i++)
-		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
-}
-
-/* Reset and setup CD180 chip */
-static void __init rc_init_CD180(struct riscom_board const *bp)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	rc_out(bp, RC_CTOUT, 0);     	           /* Clear timeout        */
-	rc_wait_CCR(bp);			   /* Wait for CCR ready   */
-	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip     */
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	msleep(50);				   /* Delay 0.05 sec       */
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip */
-	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits       */
-	rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr  */
-	rc_out(bp, CD180_PILR2, RC_ACK_TINT);      /* Prio for tx intr     */
-	rc_out(bp, CD180_PILR3, RC_ACK_RINT);      /* Prio for rx intr	   */
-
-	/* Setting up prescaler. We need 4 ticks per 1 ms */
-	rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
-	rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-/* Main probing routine, also sets irq. */
-static int __init rc_probe(struct riscom_board *bp)
-{
-	unsigned char val1, val2;
-	int irqs = 0;
-	int retries;
-
-	bp->irq = 0;
-
-	if (rc_request_io_range(bp))
-		return 1;
-
-	/* Are the I/O ports here ? */
-	rc_out(bp, CD180_PPRL, 0x5a);
-	outb(0xff, 0x80);
-	val1 = rc_in(bp, CD180_PPRL);
-	rc_out(bp, CD180_PPRL, 0xa5);
-	outb(0x00, 0x80);
-	val2 = rc_in(bp, CD180_PPRL);
-
-	if ((val1 != 0x5a) || (val2 != 0xa5))  {
-		printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
-		       board_No(bp), bp->base);
-		goto out_release;
-	}
-
-	/* It's time to find IRQ for this board */
-	for (retries = 0; retries < 5 && irqs <= 0; retries++) {
-		irqs = probe_irq_on();
-		rc_init_CD180(bp);		 /* Reset CD180 chip	     */
-		rc_out(bp, CD180_CAR, 2);	 /* Select port 2	     */
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter	     */
-		rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr     */
-		msleep(50);
-		irqs = probe_irq_off(irqs);
-		val1 = rc_in(bp, RC_BSR);	/* Get Board Status reg	     */
-		val2 = rc_in(bp, RC_ACK_TINT);  /* ACK interrupt	     */
-		rc_init_CD180(bp);	       	/* Reset CD180 again	     */
-
-		if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX)))  {
-			printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
-					"found.\n", board_No(bp), bp->base);
-			goto out_release;
-		}
-	}
-
-	if (irqs <= 0)  {
-		printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
-				"at 0x%03x.\n", board_No(bp), bp->base);
-		goto out_release;
-	}
-	bp->irq = irqs;
-	bp->flags |= RC_BOARD_PRESENT;
-
-	printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
-			 "0x%03x, IRQ %d.\n",
-	       board_No(bp),
-	       (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A',   /* Board revision */
-	       bp->base, bp->irq);
-
-	return 0;
-out_release:
-	rc_release_io_range(bp);
-	return 1;
-}
-
-/*
- *
- *  Interrupt processing routines.
- *
- */
-
-static struct riscom_port *rc_get_port(struct riscom_board const *bp,
-					       unsigned char const *what)
-{
-	unsigned char channel;
-	struct riscom_port *port;
-
-	channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
-	if (channel < CD180_NCH)  {
-		port = &rc_port[board_No(bp) * RC_NPORT + channel];
-		if (port->port.flags & ASYNC_INITIALIZED)
-			return port;
-	}
-	printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
-	       board_No(bp), what, channel);
-	return NULL;
-}
-
-static void rc_receive_exc(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char status;
-	unsigned char ch, flag;
-
-	port = rc_get_port(bp, "Receive");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-#ifdef RC_REPORT_OVERRUN
-	status = rc_in(bp, CD180_RCSR);
-	if (status & RCSR_OE)
-		port->overrun++;
-	status &= port->mark_mask;
-#else
-	status = rc_in(bp, CD180_RCSR) & port->mark_mask;
-#endif
-	ch = rc_in(bp, CD180_RDR);
-	if (!status)
-		goto out;
-	if (status & RCSR_TOUT)  {
-		printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
-				    "Hardware problems ?\n",
-		       board_No(bp), port_No(port));
-		goto out;
-
-	} else if (status & RCSR_BREAK)  {
-		printk(KERN_INFO "rc%d: port %d: Handling break...\n",
-		       board_No(bp), port_No(port));
-		flag = TTY_BREAK;
-		if (tty && (port->port.flags & ASYNC_SAK))
-			do_SAK(tty);
-
-	} else if (status & RCSR_PE)
-		flag = TTY_PARITY;
-
-	else if (status & RCSR_FE)
-		flag = TTY_FRAME;
-
-	else if (status & RCSR_OE)
-		flag = TTY_OVERRUN;
-	else
-		flag = TTY_NORMAL;
-
-	if (tty) {
-		tty_insert_flip_char(tty, ch, flag);
-		tty_flip_buffer_push(tty);
-	}
-out:
-	tty_kref_put(tty);
-}
-
-static void rc_receive(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	port = rc_get_port(bp, "Receive");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	count = rc_in(bp, CD180_RDCR);
-
-#ifdef RC_REPORT_FIFO
-	port->hits[count > 8 ? 9 : count]++;
-#endif
-
-	while (count--)  {
-		u8 ch = rc_in(bp, CD180_RDR);
-		if (tty)
-			tty_insert_flip_char(tty, ch, TTY_NORMAL);
-	}
-	if (tty) {
-		tty_flip_buffer_push(tty);
-		tty_kref_put(tty);
-	}
-}
-
-static void rc_transmit(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	port = rc_get_port(bp, "Transmit");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	if (port->IER & IER_TXEMPTY) {
-		/* FIFO drained */
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXEMPTY;
-		rc_out(bp, CD180_IER, port->IER);
-		goto out;
-	}
-
-	if ((port->xmit_cnt <= 0 && !port->break_length)
-	    || (tty && (tty->stopped || tty->hw_stopped)))  {
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		rc_out(bp, CD180_IER, port->IER);
-		goto out;
-	}
-
-	if (port->break_length)  {
-		if (port->break_length > 0)  {
-			if (port->COR2 & COR2_ETC)  {
-				rc_out(bp, CD180_TDR, CD180_C_ESC);
-				rc_out(bp, CD180_TDR, CD180_C_SBRK);
-				port->COR2 &= ~COR2_ETC;
-			}
-			count = min_t(int, port->break_length, 0xff);
-			rc_out(bp, CD180_TDR, CD180_C_ESC);
-			rc_out(bp, CD180_TDR, CD180_C_DELAY);
-			rc_out(bp, CD180_TDR, count);
-			port->break_length -= count;
-			if (port->break_length == 0)
-				port->break_length--;
-		} else  {
-			rc_out(bp, CD180_TDR, CD180_C_ESC);
-			rc_out(bp, CD180_TDR, CD180_C_EBRK);
-			rc_out(bp, CD180_COR2, port->COR2);
-			rc_wait_CCR(bp);
-			rc_out(bp, CD180_CCR, CCR_CORCHG2);
-			port->break_length = 0;
-		}
-		goto out;
-	}
-
-	count = CD180_NFIFO;
-	do {
-		rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-
-	if (port->xmit_cnt <= 0)  {
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	if (tty && port->xmit_cnt <= port->wakeup_chars)
-		tty_wakeup(tty);
-out:
-	tty_kref_put(tty);
-}
-
-static void rc_check_modem(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char mcr;
-
-	port = rc_get_port(bp, "Modem");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	mcr = rc_in(bp, CD180_MCR);
-	if (mcr & MCR_CDCHG) {
-		if (rc_in(bp, CD180_MSVR) & MSVR_CD)
-			wake_up_interruptible(&port->port.open_wait);
-		else if (tty)
-			tty_hangup(tty);
-	}
-
-#ifdef RISCOM_BRAIN_DAMAGED_CTS
-	if (mcr & MCR_CTSCHG)  {
-		if (rc_in(bp, CD180_MSVR) & MSVR_CTS)  {
-			port->IER |= IER_TXRDY;
-			if (tty) {
-				tty->hw_stopped = 0;
-				if (port->xmit_cnt <= port->wakeup_chars)
-					tty_wakeup(tty);
-			}
-		} else  {
-			if (tty)
-				tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	if (mcr & MCR_DSRCHG)  {
-		if (rc_in(bp, CD180_MSVR) & MSVR_DSR)  {
-			port->IER |= IER_TXRDY;
-			if (tty) {
-				tty->hw_stopped = 0;
-				if (port->xmit_cnt <= port->wakeup_chars)
-					tty_wakeup(tty);
-			}
-		} else  {
-			if (tty)
-				tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		rc_out(bp, CD180_IER, port->IER);
-	}
-#endif /* RISCOM_BRAIN_DAMAGED_CTS */
-
-	/* Clear change bits */
-	rc_out(bp, CD180_MCR, 0);
-	tty_kref_put(tty);
-}
-
-/* The main interrupt processing routine */
-static irqreturn_t rc_interrupt(int dummy, void *dev_id)
-{
-	unsigned char status;
-	unsigned char ack;
-	struct riscom_board *bp = dev_id;
-	unsigned long loop = 0;
-	int handled = 0;
-
-	if (!(bp->flags & RC_BOARD_ACTIVE))
-		return IRQ_NONE;
-
-	while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &
-				 (RC_BSR_TOUT | RC_BSR_TINT |
-				  RC_BSR_MINT | RC_BSR_RINT))) {
-		handled = 1;
-		if (status & RC_BSR_TOUT)
-			printk(KERN_WARNING "rc%d: Got timeout. Hardware "
-					    "error?\n", board_No(bp));
-		else if (status & RC_BSR_RINT) {
-			ack = rc_in(bp, RC_ACK_RINT);
-			if (ack == (RC_ID | GIVR_IT_RCV))
-				rc_receive(bp);
-			else if (ack == (RC_ID | GIVR_IT_REXC))
-				rc_receive_exc(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad receive ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		} else if (status & RC_BSR_TINT) {
-			ack = rc_in(bp, RC_ACK_TINT);
-			if (ack == (RC_ID | GIVR_IT_TX))
-				rc_transmit(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad transmit ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		} else /* if (status & RC_BSR_MINT) */ {
-			ack = rc_in(bp, RC_ACK_MINT);
-			if (ack == (RC_ID | GIVR_IT_MODEM))
-				rc_check_modem(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad modem ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		}
-		rc_out(bp, CD180_EOIR, 0);   /* Mark end of interrupt */
-		rc_out(bp, RC_CTOUT, 0);     /* Clear timeout flag    */
-	}
-	return IRQ_RETVAL(handled);
-}
-
-/*
- *  Routines for open & close processing.
- */
-
-/* Called with disabled interrupts */
-static int rc_setup_board(struct riscom_board *bp)
-{
-	int error;
-
-	if (bp->flags & RC_BOARD_ACTIVE)
-		return 0;
-
-	error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
-			    "RISCom/8", bp);
-	if (error)
-		return error;
-
-	rc_out(bp, RC_CTOUT, 0);       		/* Just in case         */
-	bp->DTR = ~0;
-	rc_out(bp, RC_DTR, bp->DTR);	        /* Drop DTR on all ports */
-
-	bp->flags |= RC_BOARD_ACTIVE;
-
-	return 0;
-}
-
-/* Called with disabled interrupts */
-static void rc_shutdown_board(struct riscom_board *bp)
-{
-	if (!(bp->flags & RC_BOARD_ACTIVE))
-		return;
-
-	bp->flags &= ~RC_BOARD_ACTIVE;
-
-	free_irq(bp->irq, NULL);
-
-	bp->DTR = ~0;
-	rc_out(bp, RC_DTR, bp->DTR);	       /* Drop DTR on all ports */
-
-}
-
-/*
- * Setting up port characteristics.
- * Must be called with disabled interrupts
- */
-static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp,
-						struct riscom_port *port)
-{
-	unsigned long baud;
-	long tmp;
-	unsigned char cor1 = 0, cor3 = 0;
-	unsigned char mcor1 = 0, mcor2 = 0;
-
-	port->IER  = 0;
-	port->COR2 = 0;
-	port->MSVR = MSVR_RTS;
-
-	baud = tty_get_baud_rate(tty);
-
-	/* Select port on the board */
-	rc_out(bp, CD180_CAR, port_No(port));
-
-	if (!baud)  {
-		/* Drop DTR & exit */
-		bp->DTR |= (1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-		return;
-	} else  {
-		/* Set DTR on */
-		bp->DTR &= ~(1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-	}
-
-	/*
-	 * Now we must calculate some speed depended things
-	 */
-
-	/* Set baud rate for port */
-	tmp = (((RC_OSCFREQ + baud/2) / baud +
-		CD180_TPC/2) / CD180_TPC);
-
-	rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
-	rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
-	rc_out(bp, CD180_RBPRL, tmp & 0xff);
-	rc_out(bp, CD180_TBPRL, tmp & 0xff);
-
-	baud = (baud + 5) / 10;   /* Estimated CPS */
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
-	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-					      SERIAL_XMIT_SIZE - 1 : tmp);
-
-	/* Receiver timeout will be transmission time for 1.5 chars */
-	tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
-	tmp = (tmp > 0xff) ? 0xff : tmp;
-	rc_out(bp, CD180_RTPR, tmp);
-
-	switch (C_CSIZE(tty)) {
-	case CS5:
-		cor1 |= COR1_5BITS;
-		break;
-	case CS6:
-		cor1 |= COR1_6BITS;
-		break;
-	case CS7:
-		cor1 |= COR1_7BITS;
-		break;
-	case CS8:
-		cor1 |= COR1_8BITS;
-		break;
-	}
-	if (C_CSTOPB(tty))
-		cor1 |= COR1_2SB;
-
-	cor1 |= COR1_IGNORE;
-	if (C_PARENB(tty)) {
-		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty))
-			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty))
-			cor1 &= ~COR1_IGNORE;
-	}
-	/* Set marking of some errors */
-	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty))
-		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty))
-		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-	if (I_IGNBRK(tty)) {
-		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty))
-			/* Real raw mode. Ignore all */
-			port->mark_mask &= ~RCSR_OE;
-	}
-	/* Enable Hardware Flow Control */
-	if (C_CRTSCTS(tty))  {
-#ifdef RISCOM_BRAIN_DAMAGED_CTS
-		port->IER |= IER_DSR | IER_CTS;
-		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
-		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-		tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
-						(MSVR_CTS|MSVR_DSR));
-#else
-		port->COR2 |= COR2_CTSAE;
-#endif
-	}
-	/* Enable Software Flow Control. FIXME: I'm not sure about this */
-	/* Some people reported that it works, but I still doubt */
-	if (I_IXON(tty))  {
-		port->COR2 |= COR2_TXIBE;
-		cor3 |= (COR3_FCT | COR3_SCDE);
-		if (I_IXANY(tty))
-			port->COR2 |= COR2_IXM;
-		rc_out(bp, CD180_SCHR1, START_CHAR(tty));
-		rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));
-		rc_out(bp, CD180_SCHR3, START_CHAR(tty));
-		rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));
-	}
-	if (!C_CLOCAL(tty))  {
-		/* Enable CD check */
-		port->IER |= IER_CD;
-		mcor1 |= MCOR1_CDZD;
-		mcor2 |= MCOR2_CDOD;
-	}
-
-	if (C_CREAD(tty))
-		/* Enable receiver */
-		port->IER |= IER_RXD;
-
-	/* Set input FIFO size (1-8 bytes) */
-	cor3 |= RISCOM_RXFIFO;
-	/* Setting up CD180 channel registers */
-	rc_out(bp, CD180_COR1, cor1);
-	rc_out(bp, CD180_COR2, port->COR2);
-	rc_out(bp, CD180_COR3, cor3);
-	/* Make CD180 know about registers change */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
-	/* Setting up modem option registers */
-	rc_out(bp, CD180_MCOR1, mcor1);
-	rc_out(bp, CD180_MCOR2, mcor2);
-	/* Enable CD180 transmitter & receiver */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);
-	/* Enable interrupts */
-	rc_out(bp, CD180_IER, port->IER);
-	/* And finally set RTS on */
-	rc_out(bp, CD180_MSVR, port->MSVR);
-}
-
-/* Must be called with interrupts enabled */
-static int rc_activate_port(struct tty_port *port, struct tty_struct *tty)
-{
-	struct riscom_port *rp = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(rp);
-	unsigned long flags;
-
-	if (tty_port_alloc_xmit_buf(port) < 0)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	bp->count++;
-	rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0;
-	rc_change_speed(tty, bp, rp);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return 0;
-}
-
-/* Must be called with interrupts disabled */
-static void rc_shutdown_port(struct tty_struct *tty,
-			struct riscom_board *bp, struct riscom_port *port)
-{
-#ifdef RC_REPORT_OVERRUN
-	printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
-	       board_No(bp), port_No(port), port->overrun);
-#endif
-#ifdef RC_REPORT_FIFO
-	{
-		int i;
-
-		printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
-		       board_No(bp), port_No(port));
-		for (i = 0; i < 10; i++)
-			printk("%ld ", port->hits[i]);
-		printk("].\n");
-	}
-#endif
-	tty_port_free_xmit_buf(&port->port);
-
-	/* Select port */
-	rc_out(bp, CD180_CAR, port_No(port));
-	/* Reset port */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_SOFTRESET);
-	/* Disable all interrupts from this port */
-	port->IER = 0;
-	rc_out(bp, CD180_IER, port->IER);
-
-	set_bit(TTY_IO_ERROR, &tty->flags);
-
-	if (--bp->count < 0)  {
-		printk(KERN_INFO "rc%d: rc_shutdown_port: "
-				 "bad board count: %d\n",
-		       board_No(bp), bp->count);
-		bp->count = 0;
-	}
-	/*
-	 * If this is the last opened port on the board
-	 * shutdown whole board
-	 */
-	if (!bp->count)
-		rc_shutdown_board(bp);
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	struct riscom_port *p = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(p);
-	unsigned long flags;
-	int CD;
-	
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_out(bp, CD180_CAR, port_No(p));
-	CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
-	rc_out(bp, CD180_MSVR, MSVR_RTS);
-	bp->DTR &= ~(1u << port_No(p));
-	rc_out(bp, RC_DTR, bp->DTR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return CD;
-}
-
-static void dtr_rts(struct tty_port *port, int onoff)
-{
-	struct riscom_port *p = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(p);
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	bp->DTR &= ~(1u << port_No(p));
-	if (onoff == 0)
-		bp->DTR |= (1u << port_No(p));
-	rc_out(bp, RC_DTR, bp->DTR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static int rc_open(struct tty_struct *tty, struct file *filp)
-{
-	int board;
-	int error;
-	struct riscom_port *port;
-	struct riscom_board *bp;
-
-	board = RC_BOARD(tty->index);
-	if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
-		return -ENODEV;
-
-	bp = &rc_board[board];
-	port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
-	if (rc_paranoia_check(port, tty->name, "rc_open"))
-		return -ENODEV;
-
-	error = rc_setup_board(bp);
-	if (error)
-		return error;
-
-	tty->driver_data = port;
-	return tty_port_open(&port->port, tty, filp);
-}
-
-static void rc_flush_buffer(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	tty_wakeup(tty);
-}
-
-static void rc_close_port(struct tty_port *port)
-{
-	unsigned long flags;
-	struct riscom_port *rp = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(rp);
-	unsigned long timeout;
-	
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	rp->IER &= ~IER_RXD;
-
-	rp->IER &= ~IER_TXRDY;
-	rp->IER |= IER_TXEMPTY;
-	rc_out(bp, CD180_CAR, port_No(rp));
-	rc_out(bp, CD180_IER, rp->IER);
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = jiffies + HZ;
-	while (rp->IER & IER_TXEMPTY) {
-		spin_unlock_irqrestore(&riscom_lock, flags);
-		msleep_interruptible(jiffies_to_msecs(rp->timeout));
-		spin_lock_irqsave(&riscom_lock, flags);
-		if (time_after(jiffies, timeout))
-			break;
-	}
-	rc_shutdown_port(port->tty, bp, rp);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_close(struct tty_struct *tty, struct file *filp)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (!port || rc_paranoia_check(port, tty->name, "close"))
-		return;
-	tty_port_close(&port->port, tty, filp);
-}
-
-static int rc_write(struct tty_struct *tty,
-		    const unsigned char *buf, int count)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	int c, total = 0;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_write"))
-		return 0;
-
-	bp = port_Board(port);
-
-	while (1) {
-		spin_lock_irqsave(&riscom_lock, flags);
-
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;	/* lock continues to be held */
-
-		memcpy(port->port.xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-
-		spin_unlock_irqrestore(&riscom_lock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-	    !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		rc_out(bp, CD180_CAR, port_No(port));
-		rc_out(bp, CD180_IER, port->IER);
-	}
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	return total;
-}
-
-static int rc_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (rc_paranoia_check(port, tty->name, "rc_put_char"))
-		return 0;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
-		goto out;
-
-	port->port.xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;
-	ret = 1;
-
-out:
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return ret;
-}
-
-static void rc_flush_chars(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped)
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	port->IER |= IER_TXRDY;
-	rc_out(port_Board(port), CD180_CAR, port_No(port));
-	rc_out(port_Board(port), CD180_IER, port->IER);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static int rc_write_room(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	int	ret;
-
-	if (rc_paranoia_check(port, tty->name, "rc_write_room"))
-		return 0;
-
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}
-
-static int rc_chars_in_buffer(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
-		return 0;
-
-	return port->xmit_cnt;
-}
-
-static int rc_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, __func__))
-		return -ENODEV;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	rc_out(bp, CD180_CAR, port_No(port));
-	status = rc_in(bp, CD180_MSVR);
-	result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
-		| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
-		| ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-		| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
-		| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	return result;
-}
-
-static int rc_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-	struct riscom_board *bp;
-
-	if (rc_paranoia_check(port, tty->name, __func__))
-		return -ENODEV;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (set & TIOCM_RTS)
-		port->MSVR |= MSVR_RTS;
-	if (set & TIOCM_DTR)
-		bp->DTR &= ~(1u << port_No(port));
-
-	if (clear & TIOCM_RTS)
-		port->MSVR &= ~MSVR_RTS;
-	if (clear & TIOCM_DTR)
-		bp->DTR |= (1u << port_No(port));
-
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	rc_out(bp, RC_DTR, bp->DTR);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	return 0;
-}
-
-static int rc_send_break(struct tty_struct *tty, int length)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp = port_Board(port);
-	unsigned long flags;
-
-	if (length == 0 || length == -1)
-		return -EOPNOTSUPP;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	port->break_length = RISCOM_TPS / HZ * length;
-	port->COR2 |= COR2_ETC;
-	port->IER  |= IER_TXRDY;
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_COR2, port->COR2);
-	rc_out(bp, CD180_IER, port->IER);
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_CORCHG2);
-	rc_wait_CCR(bp);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return 0;
-}
-
-static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
-				     struct serial_struct __user *newinfo)
-{
-	struct serial_struct tmp;
-	struct riscom_board *bp = port_Board(port);
-	int change_speed;
-
-	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
-		return -EFAULT;
-
-	mutex_lock(&port->port.mutex);
-	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
-			(tmp.flags & ASYNC_SPD_MASK));
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((tmp.close_delay != port->port.close_delay) ||
-		    (tmp.closing_wait != port->port.closing_wait) ||
-		    ((tmp.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-			       (tmp.flags & ASYNC_USR_MASK));
-	} else  {
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-			       (tmp.flags & ASYNC_FLAGS));
-		port->port.close_delay = tmp.close_delay;
-		port->port.closing_wait = tmp.closing_wait;
-	}
-	if (change_speed)  {
-		unsigned long flags;
-
-		spin_lock_irqsave(&riscom_lock, flags);
-		rc_change_speed(tty, bp, port);
-		spin_unlock_irqrestore(&riscom_lock, flags);
-	}
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-static int rc_get_serial_info(struct riscom_port *port,
-				     struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-	struct riscom_board *bp = port_Board(port);
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = PORT_CIRRUS;
-	tmp.line = port - rc_port;
-
-	mutex_lock(&port->port.mutex);
-	tmp.port = bp->base;
-	tmp.irq  = bp->irq;
-	tmp.flags = port->port.flags;
-	tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
-	tmp.close_delay = port->port.close_delay * HZ/100;
-	tmp.closing_wait = port->port.closing_wait * HZ/100;
-	mutex_unlock(&port->port.mutex);
-	tmp.xmit_fifo_size = CD180_NFIFO;
-	return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
-}
-
-static int rc_ioctl(struct tty_struct *tty, struct file *filp,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct riscom_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
-		return -ENODEV;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		retval = rc_get_serial_info(port, argp);
-		break;
-	case TIOCSSERIAL:
-		retval = rc_set_serial_info(tty, port, argp);
-		break;
-	default:
-		retval = -ENOIOCTLCMD;
-	}
-	return retval;
-}
-
-static void rc_throttle(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_throttle"))
-		return;
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->MSVR &= ~MSVR_RTS;
-	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty)) {
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_SSCH2);
-		rc_wait_CCR(bp);
-	}
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_unthrottle(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
-		return;
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->MSVR |= MSVR_RTS;
-	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty))  {
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_SSCH1);
-		rc_wait_CCR(bp);
-	}
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_stop(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_stop"))
-		return;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->IER &= ~IER_TXRDY;
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_IER, port->IER);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_start(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_start"))
-		return;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		rc_out(bp, CD180_CAR, port_No(port));
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_hangup(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (rc_paranoia_check(port, tty->name, "rc_hangup"))
-		return;
-
-	tty_port_hangup(&port->port);
-}
-
-static void rc_set_termios(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_change_speed(tty, port_Board(port), port);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rc_start(tty);
-	}
-}
-
-static const struct tty_operations riscom_ops = {
-	.open  = rc_open,
-	.close = rc_close,
-	.write = rc_write,
-	.put_char = rc_put_char,
-	.flush_chars = rc_flush_chars,
-	.write_room = rc_write_room,
-	.chars_in_buffer = rc_chars_in_buffer,
-	.flush_buffer = rc_flush_buffer,
-	.ioctl = rc_ioctl,
-	.throttle = rc_throttle,
-	.unthrottle = rc_unthrottle,
-	.set_termios = rc_set_termios,
-	.stop = rc_stop,
-	.start = rc_start,
-	.hangup = rc_hangup,
-	.tiocmget = rc_tiocmget,
-	.tiocmset = rc_tiocmset,
-	.break_ctl = rc_send_break,
-};
-
-static const struct tty_port_operations riscom_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-	.shutdown = rc_close_port,
-	.activate = rc_activate_port,
-};
-
-
-static int __init rc_init_drivers(void)
-{
-	int error;
-	int i;
-
-	riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
-	if (!riscom_driver)
-		return -ENOMEM;
-
-	riscom_driver->owner = THIS_MODULE;
-	riscom_driver->name = "ttyL";
-	riscom_driver->major = RISCOM8_NORMAL_MAJOR;
-	riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	riscom_driver->subtype = SERIAL_TYPE_NORMAL;
-	riscom_driver->init_termios = tty_std_termios;
-	riscom_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	riscom_driver->init_termios.c_ispeed = 9600;
-	riscom_driver->init_termios.c_ospeed = 9600;
-	riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(riscom_driver, &riscom_ops);
-	error = tty_register_driver(riscom_driver);
-	if (error != 0) {
-		put_tty_driver(riscom_driver);
-		printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
-				"error = %d\n", error);
-		return 1;
-	}
-	memset(rc_port, 0, sizeof(rc_port));
-	for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
-		tty_port_init(&rc_port[i].port);
-		rc_port[i].port.ops = &riscom_port_ops;
-		rc_port[i].magic = RISCOM8_MAGIC;
-	}
-	return 0;
-}
-
-static void rc_release_drivers(void)
-{
-	tty_unregister_driver(riscom_driver);
-	put_tty_driver(riscom_driver);
-}
-
-#ifndef MODULE
-/*
- * Called at boot time.
- *
- * You can specify IO base for up to RC_NBOARD cards,
- * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
- * Note that there will be no probing at default
- * addresses in this case.
- *
- */
-static int __init riscom8_setup(char *str)
-{
-	int ints[RC_NBOARD];
-	int i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0; i < RC_NBOARD; i++) {
-		if (i < ints[0])
-			rc_board[i].base = ints[i+1];
-		else
-			rc_board[i].base = 0;
-	}
-	return 1;
-}
-
-__setup("riscom8=", riscom8_setup);
-#endif
-
-static char banner[] __initdata =
-	KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin "
-		  "1994-1996.\n";
-static char no_boards_msg[] __initdata =
-	KERN_INFO "rc: No RISCom/8 boards detected.\n";
-
-/*
- * This routine must be called by kernel at boot time
- */
-static int __init riscom8_init(void)
-{
-	int i;
-	int found = 0;
-
-	printk(banner);
-
-	if (rc_init_drivers())
-		return -EIO;
-
-	for (i = 0; i < RC_NBOARD; i++)
-		if (rc_board[i].base && !rc_probe(&rc_board[i]))
-			found++;
-	if (!found)  {
-		rc_release_drivers();
-		printk(no_boards_msg);
-		return -EIO;
-	}
-	return 0;
-}
-
-#ifdef MODULE
-static int iobase;
-static int iobase1;
-static int iobase2;
-static int iobase3;
-module_param(iobase, int, 0);
-module_param(iobase1, int, 0);
-module_param(iobase2, int, 0);
-module_param(iobase3, int, 0);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR);
-#endif /* MODULE */
-
-/*
- * You can setup up to 4 boards (current value of RC_NBOARD)
- * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
- *
- */
-static int __init riscom8_init_module(void)
-{
-#ifdef MODULE
-	int i;
-
-	if (iobase || iobase1 || iobase2 || iobase3) {
-		for (i = 0; i < RC_NBOARD; i++)
-			rc_board[i].base = 0;
-	}
-
-	if (iobase)
-		rc_board[0].base = iobase;
-	if (iobase1)
-		rc_board[1].base = iobase1;
-	if (iobase2)
-		rc_board[2].base = iobase2;
-	if (iobase3)
-		rc_board[3].base = iobase3;
-#endif /* MODULE */
-
-	return riscom8_init();
-}
-
-static void __exit riscom8_exit_module(void)
-{
-	int i;
-
-	rc_release_drivers();
-	for (i = 0; i < RC_NBOARD; i++)
-		if (rc_board[i].flags & RC_BOARD_PRESENT)
-			rc_release_io_range(&rc_board[i]);
-
-}
-
-module_init(riscom8_init_module);
-module_exit(riscom8_exit_module);
diff --git a/drivers/char/riscom8.h b/drivers/char/riscom8.h
deleted file mode 100644
index c9876b3..0000000
--- a/drivers/char/riscom8.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *      linux/drivers/char/riscom8.h  -- RISCom/8 multiport serial driver.
- *
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card 
- *      programming info was obtained from various drivers for other OSes 
- *	(FreeBSD, ISC, etc), but no source code from those drivers were 
- *	directly included in this driver.
- *
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __LINUX_RISCOM8_H
-#define __LINUX_RISCOM8_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-#define RC_NBOARD		4
-/* NOTE: RISCom decoder recognizes 16 addresses... */
-#define RC_NPORT        	8  
-#define RC_BOARD(line)		(((line) >> 3) & 0x07)
-#define RC_PORT(line)		((line) & (RC_NPORT - 1))
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define RISCOM_TPS		4000
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define RISCOM_RXFIFO		6	/* Max. receiver FIFO size (1-8) */
-
-#define RISCOM8_MAGIC		0x0907
-
-#define RC_IOBASE1	0x220
-#define RC_IOBASE2	0x240
-#define RC_IOBASE3	0x250
-#define RC_IOBASE4	0x260
-
-struct riscom_board {
-	unsigned long   flags;
-	unsigned short	base;
-	unsigned char 	irq;
-	signed   char	count;
-	unsigned char	DTR;
-};
-
-#define RC_BOARD_PRESENT	0x00000001
-#define RC_BOARD_ACTIVE		0x00000002
-	
-struct riscom_port {
-	int			magic;
-	struct			tty_port port;
-	int			baud_base;
-	int			timeout;
-	int			custom_divisor;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	short			wakeup_chars;
-	short			break_length;
-	unsigned char		mark_mask;
-	unsigned char		IER;
-	unsigned char		MSVR;
-	unsigned char		COR2;
-#ifdef RC_REPORT_OVERRUN
-	unsigned long		overrun;
-#endif	
-#ifdef RC_REPORT_FIFO
-	unsigned long		hits[10];
-#endif
-};
-
-#endif /* __KERNEL__ */
-#endif /* __LINUX_RISCOM8_H */
diff --git a/drivers/char/riscom8_reg.h b/drivers/char/riscom8_reg.h
deleted file mode 100644
index a32475e..0000000
--- a/drivers/char/riscom8_reg.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- *      linux/drivers/char/riscom8_reg.h  -- RISCom/8 multiport serial driver.
- */
-
-/*
- * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc.
- */
-
-/*
- * Address mapping between Cirrus Logic CD180 chip internal registers
- * and ISA port addresses:
- *
- *      CL-CD180                A6  A5   A4  A3                      A2 A1 A0
- *      ISA             A15 A14 A13 A12  A11 A10 A9 A8  A7 A6 A5 A4  A3 A2 A1 A0
- */
-#define RC_TO_ISA(r)    ((((r)&0x07)<<1) | (((r)&~0x07)<<7))
-
-
-/* RISCom/8 On-Board Registers (assuming address translation) */
-
-#define RC_RI           0x100   /* Ring Indicator Register (R/O)           */
-#define RC_DTR          0x100   /* DTR Register (W/O)                      */
-#define RC_BSR          0x101   /* Board Status Register (R/O)             */
-#define RC_CTOUT        0x101   /* Clear Timeout (W/O)                     */
-
-
-/* Board Status Register */
-
-#define RC_BSR_TOUT     0x08     /* Hardware Timeout                       */
-#define RC_BSR_RINT     0x04     /* Receiver Interrupt                     */
-#define RC_BSR_TINT     0x02     /* Transmitter Interrupt                  */
-#define RC_BSR_MINT     0x01     /* Modem Ctl Interrupt                    */
-
-
-/* On-board oscillator frequency (in Hz) */
-#define RC_OSCFREQ      9830400
-
-/* Values of choice for Interrupt ACKs */
-#define RC_ACK_MINT     0x81    /* goes to PILR1                           */
-#define RC_ACK_RINT     0x82    /* goes to PILR3                           */
-#define RC_ACK_TINT     0x84    /* goes to PILR2                           */
-
-/* Chip ID (sorry, only one chip now) */
-#define RC_ID           0x10
-
-/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */
- 
-#define CD180_NCH       8       /* Total number of channels                */
-#define CD180_TPC       16      /* Ticks per character                     */
-#define CD180_NFIFO	8	/* TX FIFO size                            */
-
-
-/* Global registers */
-
-#define CD180_GIVR      0x40    /* Global Interrupt Vector Register        */
-#define CD180_GICR      0x41    /* Global Interrupting Channel Register    */
-#define CD180_PILR1     0x61    /* Priority Interrupt Level Register 1     */
-#define CD180_PILR2     0x62    /* Priority Interrupt Level Register 2     */
-#define CD180_PILR3     0x63    /* Priority Interrupt Level Register 3     */
-#define CD180_CAR       0x64    /* Channel Access Register                 */
-#define CD180_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
-#define CD180_PPRH      0x70    /* Prescaler Period Register High          */
-#define CD180_PPRL      0x71    /* Prescaler Period Register Low           */
-#define CD180_RDR       0x78    /* Receiver Data Register                  */
-#define CD180_RCSR      0x7a    /* Receiver Character Status Register      */
-#define CD180_TDR       0x7b    /* Transmit Data Register                  */
-#define CD180_EOIR      0x7f    /* End of Interrupt Register               */
-
-
-/* Channel Registers */
-
-#define CD180_CCR       0x01    /* Channel Command Register                */
-#define CD180_IER       0x02    /* Interrupt Enable Register               */
-#define CD180_COR1      0x03    /* Channel Option Register 1               */
-#define CD180_COR2      0x04    /* Channel Option Register 2               */
-#define CD180_COR3      0x05    /* Channel Option Register 3               */
-#define CD180_CCSR      0x06    /* Channel Control Status Register         */
-#define CD180_RDCR      0x07    /* Receive Data Count Register             */
-#define CD180_SCHR1     0x09    /* Special Character Register 1            */
-#define CD180_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD180_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD180_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD180_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD180_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD180_MCR       0x12    /* Modem Change Register                   */
-#define CD180_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD180_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD180_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
-#define CD180_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
-#define CD180_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
-#define CD180_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
-
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
-#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
-#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
- 
-#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GICR_CHAN_OFF   2       /* Channel Number Offset                   */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Interrupt Enable Register (R/W) */
-
-#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define IER_CD          0x40    /* Enable interrupt on CD change           */
-#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Escape characters */
-
-#define CD180_C_ESC     0x00    /* Escape character                        */
-#define CD180_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD180_C_DELAY   0x82    /* Delay output                            */
-#define CD180_C_EBRK    0x83    /* Stop sending BREAK                      */
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
deleted file mode 100644
index 3e4e73a..0000000
--- a/drivers/char/rocket.c
+++ /dev/null
@@ -1,3199 +0,0 @@
-/*
- * RocketPort device driver for Linux
- *
- * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
- * 
- * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, 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.
- */
-
-/*
- * Kernel Synchronization:
- *
- * This driver has 2 kernel control paths - exception handlers (calls into the driver
- * from user mode) and the timer bottom half (tasklet).  This is a polled driver, interrupts
- * are not used.
- *
- * Critical data: 
- * -  rp_table[], accessed through passed "info" pointers, is a global (static) array of 
- *    serial port state information and the xmit_buf circular buffer.  Protected by 
- *    a per port spinlock.
- * -  xmit_flags[], an array of ints indexed by line (port) number, indicating that there
- *    is data to be transmitted.  Protected by atomic bit operations.
- * -  rp_num_ports, int indicating number of open ports, protected by atomic operations.
- * 
- * rp_write() and rp_write_char() functions use a per port semaphore to protect against
- * simultaneous access to the same port by more than one process.
- */
-
-/****** Defines ******/
-#define ROCKET_PARANOIA_CHECK
-#define ROCKET_DISABLE_SIMUSAGE
-
-#undef ROCKET_SOFT_FLOW
-#undef ROCKET_DEBUG_OPEN
-#undef ROCKET_DEBUG_INTR
-#undef ROCKET_DEBUG_WRITE
-#undef ROCKET_DEBUG_FLOW
-#undef ROCKET_DEBUG_THROTTLE
-#undef ROCKET_DEBUG_WAIT_UNTIL_SENT
-#undef ROCKET_DEBUG_RECEIVE
-#undef ROCKET_DEBUG_HANGUP
-#undef REV_PCI_ORDER
-#undef ROCKET_DEBUG_IO
-
-#define POLL_PERIOD HZ/100	/*  Polling period .01 seconds (10ms) */
-
-/****** Kernel includes ******/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mutex.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/wait.h>
-#include <linux/pci.h>
-#include <linux/uaccess.h>
-#include <asm/atomic.h>
-#include <asm/unaligned.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-
-/****** RocketPort includes ******/
-
-#include "rocket_int.h"
-#include "rocket.h"
-
-#define ROCKET_VERSION "2.09"
-#define ROCKET_DATE "12-June-2003"
-
-/****** RocketPort Local Variables ******/
-
-static void rp_do_poll(unsigned long dummy);
-
-static struct tty_driver *rocket_driver;
-
-static struct rocket_version driver_version = {	
-	ROCKET_VERSION, ROCKET_DATE
-};
-
-static struct r_port *rp_table[MAX_RP_PORTS];	       /*  The main repository of serial port state information. */
-static unsigned int xmit_flags[NUM_BOARDS];	       /*  Bit significant, indicates port had data to transmit. */
-						       /*  eg.  Bit 0 indicates port 0 has xmit data, ...        */
-static atomic_t rp_num_ports_open;	               /*  Number of serial ports open                           */
-static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0);
-
-static unsigned long board1;	                       /* ISA addresses, retrieved from rocketport.conf          */
-static unsigned long board2;
-static unsigned long board3;
-static unsigned long board4;
-static unsigned long controller;
-static int support_low_speed;
-static unsigned long modem1;
-static unsigned long modem2;
-static unsigned long modem3;
-static unsigned long modem4;
-static unsigned long pc104_1[8];
-static unsigned long pc104_2[8];
-static unsigned long pc104_3[8];
-static unsigned long pc104_4[8];
-static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
-
-static int rp_baud_base[NUM_BOARDS];	               /*  Board config info (Someday make a per-board structure)  */
-static unsigned long rcktpt_io_addr[NUM_BOARDS];
-static int rcktpt_type[NUM_BOARDS];
-static int is_PCI[NUM_BOARDS];
-static rocketModel_t rocketModel[NUM_BOARDS];
-static int max_board;
-static const struct tty_port_operations rocket_port_ops;
-
-/*
- * The following arrays define the interrupt bits corresponding to each AIOP.
- * These bits are different between the ISA and regular PCI boards and the
- * Universal PCI boards.
- */
-
-static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
-	AIOP_INTR_BIT_0,
-	AIOP_INTR_BIT_1,
-	AIOP_INTR_BIT_2,
-	AIOP_INTR_BIT_3
-};
-
-static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
-	UPCI_AIOP_INTR_BIT_0,
-	UPCI_AIOP_INTR_BIT_1,
-	UPCI_AIOP_INTR_BIT_2,
-	UPCI_AIOP_INTR_BIT_3
-};
-
-static Byte_t RData[RDATASIZE] = {
-	0x00, 0x09, 0xf6, 0x82,
-	0x02, 0x09, 0x86, 0xfb,
-	0x04, 0x09, 0x00, 0x0a,
-	0x06, 0x09, 0x01, 0x0a,
-	0x08, 0x09, 0x8a, 0x13,
-	0x0a, 0x09, 0xc5, 0x11,
-	0x0c, 0x09, 0x86, 0x85,
-	0x0e, 0x09, 0x20, 0x0a,
-	0x10, 0x09, 0x21, 0x0a,
-	0x12, 0x09, 0x41, 0xff,
-	0x14, 0x09, 0x82, 0x00,
-	0x16, 0x09, 0x82, 0x7b,
-	0x18, 0x09, 0x8a, 0x7d,
-	0x1a, 0x09, 0x88, 0x81,
-	0x1c, 0x09, 0x86, 0x7a,
-	0x1e, 0x09, 0x84, 0x81,
-	0x20, 0x09, 0x82, 0x7c,
-	0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE] = {
-	0x00, 0x09, 0xf6, 0x82,	/* 00: Stop Rx processor */
-	0x08, 0x09, 0x8a, 0x13,	/* 04: Tx software flow control */
-	0x0a, 0x09, 0xc5, 0x11,	/* 08: XON char */
-	0x0c, 0x09, 0x86, 0x85,	/* 0c: XANY */
-	0x12, 0x09, 0x41, 0xff,	/* 10: Rx mask char */
-	0x14, 0x09, 0x82, 0x00,	/* 14: Compare/Ignore #0 */
-	0x16, 0x09, 0x82, 0x7b,	/* 18: Compare #1 */
-	0x18, 0x09, 0x8a, 0x7d,	/* 1c: Compare #2 */
-	0x1a, 0x09, 0x88, 0x81,	/* 20: Interrupt #1 */
-	0x1c, 0x09, 0x86, 0x7a,	/* 24: Ignore/Replace #1 */
-	0x1e, 0x09, 0x84, 0x81,	/* 28: Interrupt #2 */
-	0x20, 0x09, 0x82, 0x7c,	/* 2c: Ignore/Replace #2 */
-	0x22, 0x09, 0x0a, 0x0a	/* 30: Rx FIFO Enable */
-};
-
-static CONTROLLER_T sController[CTL_SIZE] = {
-	{-1, -1, 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, 0, 0, 0}},
-	{-1, -1, 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, 0, 0, 0}},
-	{-1, -1, 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, 0, 0, 0}},
-	{-1, -1, 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, 0, 0, 0}}
-};
-
-static Byte_t sBitMapClrTbl[8] = {
-	0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
-};
-
-static Byte_t sBitMapSetTbl[8] = {
-	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-static int sClockPrescale = 0x14;
-
-/*
- *  Line number is the ttySIx number (x), the Minor number.  We 
- *  assign them sequentially, starting at zero.  The following 
- *  array keeps track of the line number assigned to a given board/aiop/channel.
- */
-static unsigned char lineNumbers[MAX_RP_PORTS];
-static unsigned long nextLineNumber;
-
-/*****  RocketPort Static Prototypes   *********/
-static int __init init_ISA(int i);
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void rp_flush_buffer(struct tty_struct *tty);
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
-static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
-static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
-static void rp_start(struct tty_struct *tty);
-static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
-		     int ChanNum);
-static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
-static void sFlushRxFIFO(CHANNEL_T * ChP);
-static void sFlushTxFIFO(CHANNEL_T * ChP);
-static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
-static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
-static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
-static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
-static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-			      ByteIO_t * AiopIOList, int AiopIOListSize,
-			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-			      int PeriodicOnly, int altChanRingIndicator,
-			      int UPCIRingInd);
-static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
-			   ByteIO_t * AiopIOList, int AiopIOListSize,
-			   int IRQNum, Byte_t Frequency, int PeriodicOnly);
-static int sReadAiopID(ByteIO_t io);
-static int sReadAiopNumChan(WordIO_t io);
-
-MODULE_AUTHOR("Theodore Ts'o");
-MODULE_DESCRIPTION("Comtrol RocketPort driver");
-module_param(board1, ulong, 0);
-MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
-module_param(board2, ulong, 0);
-MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
-module_param(board3, ulong, 0);
-MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
-module_param(board4, ulong, 0);
-MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
-module_param(controller, ulong, 0);
-MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
-module_param(support_low_speed, bool, 0);
-MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
-module_param(modem1, ulong, 0);
-MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
-module_param(modem2, ulong, 0);
-MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
-module_param(modem3, ulong, 0);
-MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
-module_param(modem4, ulong, 0);
-MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
-module_param_array(pc104_1, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
-module_param_array(pc104_2, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
-module_param_array(pc104_3, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
-module_param_array(pc104_4, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
-
-static int rp_init(void);
-static void rp_cleanup_module(void);
-
-module_init(rp_init);
-module_exit(rp_cleanup_module);
-
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*************************************************************************/
-/*                     Module code starts here                           */
-
-static inline int rocket_paranoia_check(struct r_port *info,
-					const char *routine)
-{
-#ifdef ROCKET_PARANOIA_CHECK
-	if (!info)
-		return 1;
-	if (info->magic != RPORT_MAGIC) {
-		printk(KERN_WARNING "Warning: bad magic number for rocketport "
-				"struct in %s\n", routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-
-/*  Serial port receive data function.  Called (from timer poll) when an AIOPIC signals 
- *  that receive data is present on a serial port.  Pulls data from FIFO, moves it into the 
- *  tty layer.  
- */
-static void rp_do_receive(struct r_port *info,
-			  struct tty_struct *tty,
-			  CHANNEL_t * cp, unsigned int ChanStatus)
-{
-	unsigned int CharNStat;
-	int ToRecv, wRecv, space;
-	unsigned char *cbuf;
-
-	ToRecv = sGetRxCnt(cp);
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv);
-#endif
-	if (ToRecv == 0)
-		return;
-
-	/*
-	 * if status indicates there are errored characters in the
-	 * FIFO, then enter status mode (a word in FIFO holds
-	 * character and status).
-	 */
-	if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
-		if (!(ChanStatus & STATMODE)) {
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "Entering STATMODE...\n");
-#endif
-			ChanStatus |= STATMODE;
-			sEnRxStatusMode(cp);
-		}
-	}
-
-	/* 
-	 * if we previously entered status mode, then read down the
-	 * FIFO one word at a time, pulling apart the character and
-	 * the status.  Update error counters depending on status
-	 */
-	if (ChanStatus & STATMODE) {
-#ifdef ROCKET_DEBUG_RECEIVE
-		printk(KERN_INFO "Ignore %x, read %x...\n",
-			info->ignore_status_mask, info->read_status_mask);
-#endif
-		while (ToRecv) {
-			char flag;
-
-			CharNStat = sInW(sGetTxRxDataIO(cp));
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "%x...\n", CharNStat);
-#endif
-			if (CharNStat & STMBREAKH)
-				CharNStat &= ~(STMFRAMEH | STMPARITYH);
-			if (CharNStat & info->ignore_status_mask) {
-				ToRecv--;
-				continue;
-			}
-			CharNStat &= info->read_status_mask;
-			if (CharNStat & STMBREAKH)
-				flag = TTY_BREAK;
-			else if (CharNStat & STMPARITYH)
-				flag = TTY_PARITY;
-			else if (CharNStat & STMFRAMEH)
-				flag = TTY_FRAME;
-			else if (CharNStat & STMRCVROVRH)
-				flag = TTY_OVERRUN;
-			else
-				flag = TTY_NORMAL;
-			tty_insert_flip_char(tty, CharNStat & 0xff, flag);
-			ToRecv--;
-		}
-
-		/*
-		 * after we've emptied the FIFO in status mode, turn
-		 * status mode back off
-		 */
-		if (sGetRxCnt(cp) == 0) {
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "Status mode off.\n");
-#endif
-			sDisRxStatusMode(cp);
-		}
-	} else {
-		/*
-		 * we aren't in status mode, so read down the FIFO two
-		 * characters at time by doing repeated word IO
-		 * transfer.
-		 */
-		space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
-		if (space < ToRecv) {
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
-#endif
-			if (space <= 0)
-				return;
-			ToRecv = space;
-		}
-		wRecv = ToRecv >> 1;
-		if (wRecv)
-			sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
-		if (ToRecv & 1)
-			cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
-	}
-	/*  Push the data up to the tty layer */
-	tty_flip_buffer_push(tty);
-}
-
-/*
- *  Serial port transmit data function.  Called from the timer polling loop as a 
- *  result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
- *  to be sent out the serial port.  Data is buffered in rp_table[line].xmit_buf, it is 
- *  moved to the port's xmit FIFO.  *info is critical data, protected by spinlocks.
- */
-static void rp_do_transmit(struct r_port *info)
-{
-	int c;
-	CHANNEL_t *cp = &info->channel;
-	struct tty_struct *tty;
-	unsigned long flags;
-
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_DEBUG "%s\n", __func__);
-#endif
-	if (!info)
-		return;
-	tty = tty_port_tty_get(&info->port);
-
-	if (tty == NULL) {
-		printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__);
-		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-		return;
-	}
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
-	/*  Loop sending data to FIFO until done or FIFO full */
-	while (1) {
-		if (tty->stopped || tty->hw_stopped)
-			break;
-		c = min(info->xmit_fifo_room, info->xmit_cnt);
-		c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
-		if (c <= 0 || info->xmit_fifo_room <= 0)
-			break;
-		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
-		if (c & 1)
-			sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
-		info->xmit_tail += c;
-		info->xmit_tail &= XMIT_BUF_SIZE - 1;
-		info->xmit_cnt -= c;
-		info->xmit_fifo_room -= c;
-#ifdef ROCKET_DEBUG_INTR
-		printk(KERN_INFO "tx %d chars...\n", c);
-#endif
-	}
-
-	if (info->xmit_cnt == 0)
-		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-	if (info->xmit_cnt < WAKEUP_CHARS) {
-		tty_wakeup(tty);
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
-		wake_up_interruptible(&tty->poll_wait);
-#endif
-	}
-
-	spin_unlock_irqrestore(&info->slock, flags);
-	tty_kref_put(tty);
-
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head,
-	       info->xmit_tail, info->xmit_fifo_room);
-#endif
-}
-
-/*
- *  Called when a serial port signals it has read data in it's RX FIFO.
- *  It checks what interrupts are pending and services them, including
- *  receiving serial data.  
- */
-static void rp_handle_port(struct r_port *info)
-{
-	CHANNEL_t *cp;
-	struct tty_struct *tty;
-	unsigned int IntMask, ChanStatus;
-
-	if (!info)
-		return;
-
-	if ((info->port.flags & ASYNC_INITIALIZED) == 0) {
-		printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
-				"info->flags & NOT_INIT\n");
-		return;
-	}
-	tty = tty_port_tty_get(&info->port);
-	if (!tty) {
-		printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
-				"tty==NULL\n");
-		return;
-	}
-	cp = &info->channel;
-
-	IntMask = sGetChanIntID(cp) & info->intmask;
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_INFO "rp_interrupt %02x...\n", IntMask);
-#endif
-	ChanStatus = sGetChanStatus(cp);
-	if (IntMask & RXF_TRIG) {	/* Rx FIFO trigger level */
-		rp_do_receive(info, tty, cp, ChanStatus);
-	}
-	if (IntMask & DELTA_CD) {	/* CD change  */
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
-		printk(KERN_INFO "ttyR%d CD now %s...\n", info->line,
-		       (ChanStatus & CD_ACT) ? "on" : "off");
-#endif
-		if (!(ChanStatus & CD_ACT) && info->cd_status) {
-#ifdef ROCKET_DEBUG_HANGUP
-			printk(KERN_INFO "CD drop, calling hangup.\n");
-#endif
-			tty_hangup(tty);
-		}
-		info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
-		wake_up_interruptible(&info->port.open_wait);
-	}
-#ifdef ROCKET_DEBUG_INTR
-	if (IntMask & DELTA_CTS) {	/* CTS change */
-		printk(KERN_INFO "CTS change...\n");
-	}
-	if (IntMask & DELTA_DSR) {	/* DSR change */
-		printk(KERN_INFO "DSR change...\n");
-	}
-#endif
-	tty_kref_put(tty);
-}
-
-/*
- *  The top level polling routine.  Repeats every 1/100 HZ (10ms).
- */
-static void rp_do_poll(unsigned long dummy)
-{
-	CONTROLLER_t *ctlp;
-	int ctrl, aiop, ch, line;
-	unsigned int xmitmask, i;
-	unsigned int CtlMask;
-	unsigned char AiopMask;
-	Word_t bit;
-
-	/*  Walk through all the boards (ctrl's) */
-	for (ctrl = 0; ctrl < max_board; ctrl++) {
-		if (rcktpt_io_addr[ctrl] <= 0)
-			continue;
-
-		/*  Get a ptr to the board's control struct */
-		ctlp = sCtlNumToCtlPtr(ctrl);
-
-		/*  Get the interrupt status from the board */
-#ifdef CONFIG_PCI
-		if (ctlp->BusType == isPCI)
-			CtlMask = sPCIGetControllerIntStatus(ctlp);
-		else
-#endif
-			CtlMask = sGetControllerIntStatus(ctlp);
-
-		/*  Check if any AIOP read bits are set */
-		for (aiop = 0; CtlMask; aiop++) {
-			bit = ctlp->AiopIntrBits[aiop];
-			if (CtlMask & bit) {
-				CtlMask &= ~bit;
-				AiopMask = sGetAiopIntStatus(ctlp, aiop);
-
-				/*  Check if any port read bits are set */
-				for (ch = 0; AiopMask;  AiopMask >>= 1, ch++) {
-					if (AiopMask & 1) {
-
-						/*  Get the line number (/dev/ttyRx number). */
-						/*  Read the data from the port. */
-						line = GetLineNumber(ctrl, aiop, ch);
-						rp_handle_port(rp_table[line]);
-					}
-				}
-			}
-		}
-
-		xmitmask = xmit_flags[ctrl];
-
-		/*
-		 *  xmit_flags contains bit-significant flags, indicating there is data
-		 *  to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port 
-		 *  1, ... (32 total possible).  The variable i has the aiop and ch 
-		 *  numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
-		 */
-		if (xmitmask) {
-			for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
-				if (xmitmask & (1 << i)) {
-					aiop = (i & 0x18) >> 3;
-					ch = i & 0x07;
-					line = GetLineNumber(ctrl, aiop, ch);
-					rp_do_transmit(rp_table[line]);
-				}
-			}
-		}
-	}
-
-	/*
-	 * Reset the timer so we get called at the next clock tick (10ms).
-	 */
-	if (atomic_read(&rp_num_ports_open))
-		mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-}
-
-/*
- *  Initializes the r_port structure for a port, as well as enabling the port on 
- *  the board.  
- *  Inputs:  board, aiop, chan numbers
- */
-static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
-{
-	unsigned rocketMode;
-	struct r_port *info;
-	int line;
-	CONTROLLER_T *ctlp;
-
-	/*  Get the next available line number */
-	line = SetLineNumber(board, aiop, chan);
-
-	ctlp = sCtlNumToCtlPtr(board);
-
-	/*  Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
-	info = kzalloc(sizeof (struct r_port), GFP_KERNEL);
-	if (!info) {
-		printk(KERN_ERR "Couldn't allocate info struct for line #%d\n",
-				line);
-		return;
-	}
-
-	info->magic = RPORT_MAGIC;
-	info->line = line;
-	info->ctlp = ctlp;
-	info->board = board;
-	info->aiop = aiop;
-	info->chan = chan;
-	tty_port_init(&info->port);
-	info->port.ops = &rocket_port_ops;
-	init_completion(&info->close_wait);
-	info->flags &= ~ROCKET_MODE_MASK;
-	switch (pc104[board][line]) {
-	case 422:
-		info->flags |= ROCKET_MODE_RS422;
-		break;
-	case 485:
-		info->flags |= ROCKET_MODE_RS485;
-		break;
-	case 232:
-	default:
-		info->flags |= ROCKET_MODE_RS232;
-		break;
-	}
-
-	info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
-	if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
-		printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
-				board, aiop, chan);
-		kfree(info);
-		return;
-	}
-
-	rocketMode = info->flags & ROCKET_MODE_MASK;
-
-	if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
-		sEnRTSToggle(&info->channel);
-	else
-		sDisRTSToggle(&info->channel);
-
-	if (ctlp->boardType == ROCKET_TYPE_PC104) {
-		switch (rocketMode) {
-		case ROCKET_MODE_RS485:
-			sSetInterfaceMode(&info->channel, InterfaceModeRS485);
-			break;
-		case ROCKET_MODE_RS422:
-			sSetInterfaceMode(&info->channel, InterfaceModeRS422);
-			break;
-		case ROCKET_MODE_RS232:
-		default:
-			if (info->flags & ROCKET_RTS_TOGGLE)
-				sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
-			else
-				sSetInterfaceMode(&info->channel, InterfaceModeRS232);
-			break;
-		}
-	}
-	spin_lock_init(&info->slock);
-	mutex_init(&info->write_mtx);
-	rp_table[line] = info;
-	tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
-			NULL);
-}
-
-/*
- *  Configures a rocketport port according to its termio settings.  Called from 
- *  user mode into the driver (exception handler).  *info CD manipulation is spinlock protected.
- */
-static void configure_r_port(struct tty_struct *tty, struct r_port *info,
-			     struct ktermios *old_termios)
-{
-	unsigned cflag;
-	unsigned long flags;
-	unsigned rocketMode;
-	int bits, baud, divisor;
-	CHANNEL_t *cp;
-	struct ktermios *t = tty->termios;
-
-	cp = &info->channel;
-	cflag = t->c_cflag;
-
-	/* Byte size and parity */
-	if ((cflag & CSIZE) == CS8) {
-		sSetData8(cp);
-		bits = 10;
-	} else {
-		sSetData7(cp);
-		bits = 9;
-	}
-	if (cflag & CSTOPB) {
-		sSetStop2(cp);
-		bits++;
-	} else {
-		sSetStop1(cp);
-	}
-
-	if (cflag & PARENB) {
-		sEnParity(cp);
-		bits++;
-		if (cflag & PARODD) {
-			sSetOddParity(cp);
-		} else {
-			sSetEvenParity(cp);
-		}
-	} else {
-		sDisParity(cp);
-	}
-
-	/* baud rate */
-	baud = tty_get_baud_rate(tty);
-	if (!baud)
-		baud = 9600;
-	divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
-	if ((divisor >= 8192 || divisor < 0) && old_termios) {
-		baud = tty_termios_baud_rate(old_termios);
-		if (!baud)
-			baud = 9600;
-		divisor = (rp_baud_base[info->board] / baud) - 1;
-	}
-	if (divisor >= 8192 || divisor < 0) {
-		baud = 9600;
-		divisor = (rp_baud_base[info->board] / baud) - 1;
-	}
-	info->cps = baud / bits;
-	sSetBaud(cp, divisor);
-
-	/* FIXME: Should really back compute a baud rate from the divisor */
-	tty_encode_baud_rate(tty, baud, baud);
-
-	if (cflag & CRTSCTS) {
-		info->intmask |= DELTA_CTS;
-		sEnCTSFlowCtl(cp);
-	} else {
-		info->intmask &= ~DELTA_CTS;
-		sDisCTSFlowCtl(cp);
-	}
-	if (cflag & CLOCAL) {
-		info->intmask &= ~DELTA_CD;
-	} else {
-		spin_lock_irqsave(&info->slock, flags);
-		if (sGetChanStatus(cp) & CD_ACT)
-			info->cd_status = 1;
-		else
-			info->cd_status = 0;
-		info->intmask |= DELTA_CD;
-		spin_unlock_irqrestore(&info->slock, flags);
-	}
-
-	/*
-	 * Handle software flow control in the board
-	 */
-#ifdef ROCKET_SOFT_FLOW
-	if (I_IXON(tty)) {
-		sEnTxSoftFlowCtl(cp);
-		if (I_IXANY(tty)) {
-			sEnIXANY(cp);
-		} else {
-			sDisIXANY(cp);
-		}
-		sSetTxXONChar(cp, START_CHAR(tty));
-		sSetTxXOFFChar(cp, STOP_CHAR(tty));
-	} else {
-		sDisTxSoftFlowCtl(cp);
-		sDisIXANY(cp);
-		sClrTxXOFF(cp);
-	}
-#endif
-
-	/*
-	 * Set up ignore/read mask words
-	 */
-	info->read_status_mask = STMRCVROVRH | 0xFF;
-	if (I_INPCK(tty))
-		info->read_status_mask |= STMFRAMEH | STMPARITYH;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		info->read_status_mask |= STMBREAKH;
-
-	/*
-	 * Characters to ignore
-	 */
-	info->ignore_status_mask = 0;
-	if (I_IGNPAR(tty))
-		info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
-	if (I_IGNBRK(tty)) {
-		info->ignore_status_mask |= STMBREAKH;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(tty))
-			info->ignore_status_mask |= STMRCVROVRH;
-	}
-
-	rocketMode = info->flags & ROCKET_MODE_MASK;
-
-	if ((info->flags & ROCKET_RTS_TOGGLE)
-	    || (rocketMode == ROCKET_MODE_RS485))
-		sEnRTSToggle(cp);
-	else
-		sDisRTSToggle(cp);
-
-	sSetRTS(&info->channel);
-
-	if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
-		switch (rocketMode) {
-		case ROCKET_MODE_RS485:
-			sSetInterfaceMode(cp, InterfaceModeRS485);
-			break;
-		case ROCKET_MODE_RS422:
-			sSetInterfaceMode(cp, InterfaceModeRS422);
-			break;
-		case ROCKET_MODE_RS232:
-		default:
-			if (info->flags & ROCKET_RTS_TOGGLE)
-				sSetInterfaceMode(cp, InterfaceModeRS232T);
-			else
-				sSetInterfaceMode(cp, InterfaceModeRS232);
-			break;
-		}
-	}
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	struct r_port *info = container_of(port, struct r_port, port);
-	return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
-}
-
-static void dtr_rts(struct tty_port *port, int on)
-{
-	struct r_port *info = container_of(port, struct r_port, port);
-	if (on) {
-		sSetDTR(&info->channel);
-		sSetRTS(&info->channel);
-	} else {
-		sClrDTR(&info->channel);
-		sClrRTS(&info->channel);
-	}
-}
-
-/*
- *  Exception handler that opens a serial port.  Creates xmit_buf storage, fills in 
- *  port's r_port struct.  Initializes the port hardware.  
- */
-static int rp_open(struct tty_struct *tty, struct file *filp)
-{
-	struct r_port *info;
-	struct tty_port *port;
-	int line = 0, retval;
-	CHANNEL_t *cp;
-	unsigned long page;
-
-	line = tty->index;
-	if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL))
-		return -ENXIO;
-	port = &info->port;
-	
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	if (port->flags & ASYNC_CLOSING) {
-		retval = wait_for_completion_interruptible(&info->close_wait);
-		free_page(page);
-		if (retval)
-			return retval;
-		return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
-	}
-
-	/*
-	 * We must not sleep from here until the port is marked fully in use.
-	 */
-	if (info->xmit_buf)
-		free_page(page);
-	else
-		info->xmit_buf = (unsigned char *) page;
-
-	tty->driver_data = info;
-	tty_port_tty_set(port, tty);
-
-	if (port->count++ == 0) {
-		atomic_inc(&rp_num_ports_open);
-
-#ifdef ROCKET_DEBUG_OPEN
-		printk(KERN_INFO "rocket mod++ = %d...\n",
-				atomic_read(&rp_num_ports_open));
-#endif
-	}
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count);
-#endif
-
-	/*
-	 * Info->count is now 1; so it's safe to sleep now.
-	 */
-	if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
-		cp = &info->channel;
-		sSetRxTrigger(cp, TRIG_1);
-		if (sGetChanStatus(cp) & CD_ACT)
-			info->cd_status = 1;
-		else
-			info->cd_status = 0;
-		sDisRxStatusMode(cp);
-		sFlushRxFIFO(cp);
-		sFlushTxFIFO(cp);
-
-		sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
-		sSetRxTrigger(cp, TRIG_1);
-
-		sGetChanStatus(cp);
-		sDisRxStatusMode(cp);
-		sClrTxXOFF(cp);
-
-		sDisCTSFlowCtl(cp);
-		sDisTxSoftFlowCtl(cp);
-
-		sEnRxFIFO(cp);
-		sEnTransmit(cp);
-
-		set_bit(ASYNCB_INITIALIZED, &info->port.flags);
-
-		/*
-		 * Set up the tty->alt_speed kludge
-		 */
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
-			tty->alt_speed = 57600;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
-			tty->alt_speed = 115200;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
-			tty->alt_speed = 230400;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
-			tty->alt_speed = 460800;
-
-		configure_r_port(tty, info, NULL);
-		if (tty->termios->c_cflag & CBAUD) {
-			sSetDTR(cp);
-			sSetRTS(cp);
-		}
-	}
-	/*  Starts (or resets) the maint polling loop */
-	mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-
-	retval = tty_port_block_til_ready(port, tty, filp);
-	if (retval) {
-#ifdef ROCKET_DEBUG_OPEN
-		printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
-#endif
-		return retval;
-	}
-	return 0;
-}
-
-/*
- *  Exception handler that closes a serial port. info->port.count is considered critical.
- */
-static void rp_close(struct tty_struct *tty, struct file *filp)
-{
-	struct r_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-	int timeout;
-	CHANNEL_t *cp;
-	
-	if (rocket_paranoia_check(info, "rp_close"))
-		return;
-
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count);
-#endif
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-
-	mutex_lock(&port->mutex);
-	cp = &info->channel;
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
-	if (timeout == 0)
-		timeout = 1;
-	rp_wait_until_sent(tty, timeout);
-	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-	sDisTransmit(cp);
-	sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
-	sDisCTSFlowCtl(cp);
-	sDisTxSoftFlowCtl(cp);
-	sClrTxXOFF(cp);
-	sFlushRxFIFO(cp);
-	sFlushTxFIFO(cp);
-	sClrRTS(cp);
-	if (C_HUPCL(tty))
-		sClrDTR(cp);
-
-	rp_flush_buffer(tty);
-		
-	tty_ldisc_flush(tty);
-
-	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-	/* We can't yet use tty_port_close_end as the buffer handling in this
-	   driver is a bit different to the usual */
-
-	if (port->blocked_open) {
-		if (port->close_delay) {
-			msleep_interruptible(jiffies_to_msecs(port->close_delay));
-		}
-		wake_up_interruptible(&port->open_wait);
-	} else {
-		if (info->xmit_buf) {
-			free_page((unsigned long) info->xmit_buf);
-			info->xmit_buf = NULL;
-		}
-	}
-	spin_lock_irq(&port->lock);
-	info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE);
-	tty->closing = 0;
-	spin_unlock_irq(&port->lock);
-	mutex_unlock(&port->mutex);
-	tty_port_tty_set(port, NULL);
-
-	wake_up_interruptible(&port->close_wait);
-	complete_all(&info->close_wait);
-	atomic_dec(&rp_num_ports_open);
-
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "rocket mod-- = %d...\n",
-			atomic_read(&rp_num_ports_open));
-	printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
-#endif
-
-}
-
-static void rp_set_termios(struct tty_struct *tty,
-			   struct ktermios *old_termios)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned cflag;
-
-	if (rocket_paranoia_check(info, "rp_set_termios"))
-		return;
-
-	cflag = tty->termios->c_cflag;
-
-	/*
-	 * This driver doesn't support CS5 or CS6
-	 */
-	if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
-		tty->termios->c_cflag =
-		    ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
-	/* Or CMSPAR */
-	tty->termios->c_cflag &= ~CMSPAR;
-
-	configure_r_port(tty, info, old_termios);
-
-	cp = &info->channel;
-
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
-		sClrDTR(cp);
-		sClrRTS(cp);
-	}
-
-	/* 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);
-		sSetDTR(cp);
-	}
-
-	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rp_start(tty);
-	}
-}
-
-static int rp_break(struct tty_struct *tty, int break_state)
-{
-	struct r_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_break"))
-		return -EINVAL;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (break_state == -1)
-		sSendBreak(&info->channel);
-	else
-		sClrBreak(&info->channel);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return 0;
-}
-
-/*
- * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
- * the UPCI boards was added, it was decided to make this a function because
- * the macro was getting too complicated. All cases except the first one
- * (UPCIRingInd) are taken directly from the original macro.
- */
-static int sGetChanRI(CHANNEL_T * ChP)
-{
-	CONTROLLER_t *CtlP = ChP->CtlP;
-	int ChanNum = ChP->ChanNum;
-	int RingInd = 0;
-
-	if (CtlP->UPCIRingInd)
-		RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
-	else if (CtlP->AltChanRingIndicator)
-		RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
-	else if (CtlP->boardType == ROCKET_TYPE_PC104)
-		RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
-
-	return RingInd;
-}
-
-/********************************************************************************************/
-/*  Here are the routines used by rp_ioctl.  These are all called from exception handlers.  */
-
-/*
- *  Returns the state of the serial modem control lines.  These next 2 functions 
- *  are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
- */
-static int rp_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct r_port *info = tty->driver_data;
-	unsigned int control, result, ChanStatus;
-
-	ChanStatus = sGetChanStatusLo(&info->channel);
-	control = info->channel.TxControl[3];
-	result = ((control & SET_RTS) ? TIOCM_RTS : 0) | 
-		((control & SET_DTR) ?  TIOCM_DTR : 0) |
-		((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
-		(sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
-		((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
-		((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
-
-	return result;
-}
-
-/* 
- *  Sets the modem control lines
- */
-static int rp_tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	struct r_port *info = tty->driver_data;
-
-	if (set & TIOCM_RTS)
-		info->channel.TxControl[3] |= SET_RTS;
-	if (set & TIOCM_DTR)
-		info->channel.TxControl[3] |= SET_DTR;
-	if (clear & TIOCM_RTS)
-		info->channel.TxControl[3] &= ~SET_RTS;
-	if (clear & TIOCM_DTR)
-		info->channel.TxControl[3] &= ~SET_DTR;
-
-	out32(info->channel.IndexAddr, info->channel.TxControl);
-	return 0;
-}
-
-static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
-{
-	struct rocket_config tmp;
-
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof (tmp));
-	mutex_lock(&info->port.mutex);
-	tmp.line = info->line;
-	tmp.flags = info->flags;
-	tmp.close_delay = info->port.close_delay;
-	tmp.closing_wait = info->port.closing_wait;
-	tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
-	mutex_unlock(&info->port.mutex);
-
-	if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_config(struct tty_struct *tty, struct r_port *info,
-					struct rocket_config __user *new_info)
-{
-	struct rocket_config new_serial;
-
-	if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
-		return -EFAULT;
-
-	mutex_lock(&info->port.mutex);
-	if (!capable(CAP_SYS_ADMIN))
-	{
-		if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) {
-			mutex_unlock(&info->port.mutex);
-			return -EPERM;
-		}
-		info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
-		configure_r_port(tty, info, NULL);
-		mutex_unlock(&info->port.mutex);
-		return 0;
-	}
-
-	info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
-	info->port.close_delay = new_serial.close_delay;
-	info->port.closing_wait = new_serial.closing_wait;
-
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
-		tty->alt_speed = 57600;
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
-		tty->alt_speed = 115200;
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
-		tty->alt_speed = 230400;
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
-		tty->alt_speed = 460800;
-	mutex_unlock(&info->port.mutex);
-
-	configure_r_port(tty, info, NULL);
-	return 0;
-}
-
-/*
- *  This function fills in a rocket_ports struct with information
- *  about what boards/ports are in the system.  This info is passed
- *  to user space.  See setrocket.c where the info is used to create
- *  the /dev/ttyRx ports.
- */
-static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
-{
-	struct rocket_ports tmp;
-	int board;
-
-	if (!retports)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof (tmp));
-	tmp.tty_major = rocket_driver->major;
-
-	for (board = 0; board < 4; board++) {
-		tmp.rocketModel[board].model = rocketModel[board].model;
-		strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
-		tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
-		tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
-		tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
-	}
-	if (copy_to_user(retports, &tmp, sizeof (*retports)))
-		return -EFAULT;
-	return 0;
-}
-
-static int reset_rm2(struct r_port *info, void __user *arg)
-{
-	int reset;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	if (copy_from_user(&reset, arg, sizeof (int)))
-		return -EFAULT;
-	if (reset)
-		reset = 1;
-
-	if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
-            rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
-		return -EINVAL;
-
-	if (info->ctlp->BusType == isISA)
-		sModemReset(info->ctlp, info->chan, reset);
-	else
-		sPCIModemReset(info->ctlp, info->chan, reset);
-
-	return 0;
-}
-
-static int get_version(struct r_port *info, struct rocket_version __user *retvers)
-{
-	if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
-		return -EFAULT;
-	return 0;
-}
-
-/*  IOCTL call handler into the driver */
-static int rp_ioctl(struct tty_struct *tty, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct r_port *info = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int ret = 0;
-
-	if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
-		return -ENXIO;
-
-	switch (cmd) {
-	case RCKP_GET_STRUCT:
-		if (copy_to_user(argp, info, sizeof (struct r_port)))
-			ret = -EFAULT;
-		break;
-	case RCKP_GET_CONFIG:
-		ret = get_config(info, argp);
-		break;
-	case RCKP_SET_CONFIG:
-		ret = set_config(tty, info, argp);
-		break;
-	case RCKP_GET_PORTS:
-		ret = get_ports(info, argp);
-		break;
-	case RCKP_RESET_RM2:
-		ret = reset_rm2(info, argp);
-		break;
-	case RCKP_GET_VERSION:
-		ret = get_version(info, argp);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-	return ret;
-}
-
-static void rp_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-
-	if (rocket_paranoia_check(info, "rp_send_xchar"))
-		return;
-
-	cp = &info->channel;
-	if (sGetTxCnt(cp))
-		sWriteTxPrioByte(cp, ch);
-	else
-		sWriteTxByte(sGetTxRxDataIO(cp), ch);
-}
-
-static void rp_throttle(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-
-#ifdef ROCKET_DEBUG_THROTTLE
-	printk(KERN_INFO "throttle %s: %d....\n", tty->name,
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (rocket_paranoia_check(info, "rp_throttle"))
-		return;
-
-	cp = &info->channel;
-	if (I_IXOFF(tty))
-		rp_send_xchar(tty, STOP_CHAR(tty));
-
-	sClrRTS(&info->channel);
-}
-
-static void rp_unthrottle(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-#ifdef ROCKET_DEBUG_THROTTLE
-	printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (rocket_paranoia_check(info, "rp_throttle"))
-		return;
-
-	cp = &info->channel;
-	if (I_IXOFF(tty))
-		rp_send_xchar(tty, START_CHAR(tty));
-
-	sSetRTS(&info->channel);
-}
-
-/*
- * ------------------------------------------------------------
- * rp_stop() and rp_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rp_stop(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_FLOW
-	printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
-	       info->xmit_cnt, info->xmit_fifo_room);
-#endif
-
-	if (rocket_paranoia_check(info, "rp_stop"))
-		return;
-
-	if (sGetTxCnt(&info->channel))
-		sDisTransmit(&info->channel);
-}
-
-static void rp_start(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_FLOW
-	printk(KERN_INFO "start %s: %d %d....\n", tty->name,
-	       info->xmit_cnt, info->xmit_fifo_room);
-#endif
-
-	if (rocket_paranoia_check(info, "rp_stop"))
-		return;
-
-	sEnTransmit(&info->channel);
-	set_bit((info->aiop * 8) + info->chan,
-		(void *) &xmit_flags[info->board]);
-}
-
-/*
- * rp_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned long orig_jiffies;
-	int check_time, exit_time;
-	int txcnt;
-
-	if (rocket_paranoia_check(info, "rp_wait_until_sent"))
-		return;
-
-	cp = &info->channel;
-
-	orig_jiffies = jiffies;
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout,
-	       jiffies);
-	printk(KERN_INFO "cps=%d...\n", info->cps);
-#endif
-	while (1) {
-		txcnt = sGetTxCnt(cp);
-		if (!txcnt) {
-			if (sGetChanStatusLo(cp) & TXSHRMT)
-				break;
-			check_time = (HZ / info->cps) / 5;
-		} else {
-			check_time = HZ * txcnt / info->cps;
-		}
-		if (timeout) {
-			exit_time = orig_jiffies + timeout - jiffies;
-			if (exit_time <= 0)
-				break;
-			if (exit_time < check_time)
-				check_time = exit_time;
-		}
-		if (check_time == 0)
-			check_time = 1;
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
-		printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt,
-				jiffies, check_time);
-#endif
-		msleep_interruptible(jiffies_to_msecs(check_time));
-		if (signal_pending(current))
-			break;
-	}
-	__set_current_state(TASK_RUNNING);
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
-#endif
-}
-
-/*
- * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rp_hangup(struct tty_struct *tty)
-{
-	CHANNEL_t *cp;
-	struct r_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_hangup"))
-		return;
-
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
-	printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
-#endif
-	rp_flush_buffer(tty);
-	spin_lock_irqsave(&info->port.lock, flags);
-	if (info->port.flags & ASYNC_CLOSING) {
-		spin_unlock_irqrestore(&info->port.lock, flags);
-		return;
-	}
-	if (info->port.count)
-		atomic_dec(&rp_num_ports_open);
-	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-	spin_unlock_irqrestore(&info->port.lock, flags);
-
-	tty_port_hangup(&info->port);
-
-	cp = &info->channel;
-	sDisRxFIFO(cp);
-	sDisTransmit(cp);
-	sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
-	sDisCTSFlowCtl(cp);
-	sDisTxSoftFlowCtl(cp);
-	sClrTxXOFF(cp);
-	clear_bit(ASYNCB_INITIALIZED, &info->port.flags);
-
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-/*
- *  Exception handler - write char routine.  The RocketPort driver uses a
- *  double-buffering strategy, with the twist that if the in-memory CPU
- *  buffer is empty, and there's space in the transmit FIFO, the
- *  writing routines will write directly to transmit FIFO.
- *  Write buffer and counters protected by spinlocks
- */
-static int rp_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_put_char"))
-		return 0;
-
-	/*
-	 * Grab the port write mutex, locking out other processes that try to
-	 * write to this port
-	 */
-	mutex_lock(&info->write_mtx);
-
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_put_char %c...\n", ch);
-#endif
-
-	spin_lock_irqsave(&info->slock, flags);
-	cp = &info->channel;
-
-	if (!tty->stopped && !tty->hw_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) {
-		info->xmit_buf[info->xmit_head++] = ch;
-		info->xmit_head &= XMIT_BUF_SIZE - 1;
-		info->xmit_cnt++;
-		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-	} else {
-		sOutB(sGetTxRxDataIO(cp), ch);
-		info->xmit_fifo_room--;
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-	mutex_unlock(&info->write_mtx);
-	return 1;
-}
-
-/*
- *  Exception handler - write routine, called when user app writes to the device.
- *  A per port write mutex is used to protect from another process writing to
- *  this port at the same time.  This other process could be running on the other CPU
- *  or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). 
- *  Spinlocks protect the info xmit members.
- */
-static int rp_write(struct tty_struct *tty,
-		    const unsigned char *buf, int count)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	const unsigned char *b;
-	int c, retval = 0;
-	unsigned long flags;
-
-	if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
-		return 0;
-
-	if (mutex_lock_interruptible(&info->write_mtx))
-		return -ERESTARTSYS;
-
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_write %d chars...\n", count);
-#endif
-	cp = &info->channel;
-
-	if (!tty->stopped && !tty->hw_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) {
-		c = min(count, info->xmit_fifo_room);
-		b = buf;
-
-		/*  Push data into FIFO, 2 bytes at a time */
-		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
-
-		/*  If there is a byte remaining, write it */
-		if (c & 1)
-			sOutB(sGetTxRxDataIO(cp), b[c - 1]);
-
-		retval += c;
-		buf += c;
-		count -= c;
-
-		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_fifo_room -= c;
-		spin_unlock_irqrestore(&info->slock, flags);
-	}
-
-	/* If count is zero, we wrote it all and are done */
-	if (!count)
-		goto end;
-
-	/*  Write remaining data into the port's xmit_buf */
-	while (1) {
-		/* Hung up ? */
-		if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags))
-			goto end;
-		c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
-		c = min(c, XMIT_BUF_SIZE - info->xmit_head);
-		if (c <= 0)
-			break;
-
-		b = buf;
-		memcpy(info->xmit_buf + info->xmit_head, b, c);
-
-		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_head =
-		    (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
-		info->xmit_cnt += c;
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		buf += c;
-		count -= c;
-		retval += c;
-	}
-
-	if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
-		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-	
-end:
- 	if (info->xmit_cnt < WAKEUP_CHARS) {
- 		tty_wakeup(tty);
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
-		wake_up_interruptible(&tty->poll_wait);
-#endif
-	}
-	mutex_unlock(&info->write_mtx);
-	return retval;
-}
-
-/*
- * Return the number of characters that can be sent.  We estimate
- * only using the in-memory transmit buffer only, and ignore the
- * potential space in the transmit FIFO.
- */
-static int rp_write_room(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	int ret;
-
-	if (rocket_paranoia_check(info, "rp_write_room"))
-		return 0;
-
-	ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_write_room returns %d...\n", ret);
-#endif
-	return ret;
-}
-
-/*
- * Return the number of characters in the buffer.  Again, this only
- * counts those characters in the in-memory transmit buffer.
- */
-static int rp_chars_in_buffer(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-
-	if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
-		return 0;
-
-	cp = &info->channel;
-
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
-#endif
-	return info->xmit_cnt;
-}
-
-/*
- *  Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
- *  r_port struct for the port.  Note that spinlock are used to protect info members,
- *  do not call this function if the spinlock is already held.
- */
-static void rp_flush_buffer(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	spin_unlock_irqrestore(&info->slock, flags);
-
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
-	wake_up_interruptible(&tty->poll_wait);
-#endif
-	tty_wakeup(tty);
-
-	cp = &info->channel;
-	sFlushTxFIFO(cp);
-}
-
-#ifdef CONFIG_PCI
-
-static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
-
-/*
- *  Called when a PCI card is found.  Retrieves and stores model information,
- *  init's aiopic and serial port hardware.
- *  Inputs:  i is the board number (0-n)
- */
-static __init int register_PCI(int i, struct pci_dev *dev)
-{
-	int num_aiops, aiop, max_num_aiops, num_chan, chan;
-	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
-	char *str, *board_type;
-	CONTROLLER_t *ctlp;
-
-	int fast_clock = 0;
-	int altChanRingIndicator = 0;
-	int ports_per_aiop = 8;
-	WordIO_t ConfigIO = 0;
-	ByteIO_t UPCIRingInd = 0;
-
-	if (!dev || pci_enable_device(dev))
-		return 0;
-
-	rcktpt_io_addr[i] = pci_resource_start(dev, 0);
-
-	rcktpt_type[i] = ROCKET_TYPE_NORMAL;
-	rocketModel[i].loadrm2 = 0;
-	rocketModel[i].startingPortNumber = nextLineNumber;
-
-	/*  Depending on the model, set up some config variables */
-	switch (dev->device) {
-	case PCI_DEVICE_ID_RP4QUAD:
-		str = "Quadcable";
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		rocketModel[i].model = MODEL_RP4QUAD;
-		strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
-		rocketModel[i].numPorts = 4;
-		break;
-	case PCI_DEVICE_ID_RP8OCTA:
-		str = "Octacable";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8OCTA;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_URP8OCTA:
-		str = "Octacable";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RP8OCTA;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP8INTF:
-		str = "8";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_URP8INTF:
-		str = "8";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RP8INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP8J:
-		str = "8J";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8J;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP4J:
-		str = "4J";
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		rocketModel[i].model = MODEL_RP4J;
-		strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
-		rocketModel[i].numPorts = 4;
-		break;
-	case PCI_DEVICE_ID_RP8SNI:
-		str = "8 (DB78 Custom)";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8SNI;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP16SNI:
-		str = "16 (DB78 Custom)";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_RP16SNI;
-		strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_RP16INTF:
-		str = "16";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_RP16INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_URP16INTF:
-		str = "16";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_UPCI_RP16INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_CRP16INTF:
-		str = "16";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_CPCI_RP16INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_RP32INTF:
-		str = "32";
-		max_num_aiops = 4;
-		rocketModel[i].model = MODEL_RP32INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
-		rocketModel[i].numPorts = 32;
-		break;
-	case PCI_DEVICE_ID_URP32INTF:
-		str = "32";
-		max_num_aiops = 4;
-		rocketModel[i].model = MODEL_UPCI_RP32INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
-		rocketModel[i].numPorts = 32;
-		break;
-	case PCI_DEVICE_ID_RPP4:
-		str = "Plus Quadcable";
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RPP4;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
-		rocketModel[i].numPorts = 4;
-		break;
-	case PCI_DEVICE_ID_RPP8:
-		str = "Plus Octacable";
-		max_num_aiops = 2;
-		ports_per_aiop = 4;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RPP8;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP2_232:
-		str = "Plus 2 (RS-232)";
-		max_num_aiops = 1;
-		ports_per_aiop = 2;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RP2_232;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
-		rocketModel[i].numPorts = 2;
-		break;
-	case PCI_DEVICE_ID_RP2_422:
-		str = "Plus 2 (RS-422)";
-		max_num_aiops = 1;
-		ports_per_aiop = 2;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RP2_422;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
-		rocketModel[i].numPorts = 2;
-		break;
-	case PCI_DEVICE_ID_RP6M:
-
-		max_num_aiops = 1;
-		ports_per_aiop = 6;
-		str = "6-port";
-
-		/*  If revision is 1, the rocketmodem flash must be loaded.
-		 *  If it is 2 it is a "socketed" version. */
-		if (dev->revision == 1) {
-			rcktpt_type[i] = ROCKET_TYPE_MODEMII;
-			rocketModel[i].loadrm2 = 1;
-		} else {
-			rcktpt_type[i] = ROCKET_TYPE_MODEM;
-		}
-
-		rocketModel[i].model = MODEL_RP6M;
-		strcpy(rocketModel[i].modelString, "RocketModem 6 port");
-		rocketModel[i].numPorts = 6;
-		break;
-	case PCI_DEVICE_ID_RP4M:
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		str = "4-port";
-		if (dev->revision == 1) {
-			rcktpt_type[i] = ROCKET_TYPE_MODEMII;
-			rocketModel[i].loadrm2 = 1;
-		} else {
-			rcktpt_type[i] = ROCKET_TYPE_MODEM;
-		}
-
-		rocketModel[i].model = MODEL_RP4M;
-		strcpy(rocketModel[i].modelString, "RocketModem 4 port");
-		rocketModel[i].numPorts = 4;
-		break;
-	default:
-		str = "(unknown/unsupported)";
-		max_num_aiops = 0;
-		break;
-	}
-
-	/*
-	 * Check for UPCI boards.
-	 */
-
-	switch (dev->device) {
-	case PCI_DEVICE_ID_URP32INTF:
-	case PCI_DEVICE_ID_URP8INTF:
-	case PCI_DEVICE_ID_URP16INTF:
-	case PCI_DEVICE_ID_CRP16INTF:
-	case PCI_DEVICE_ID_URP8OCTA:
-		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
-		ConfigIO = pci_resource_start(dev, 1);
-		if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
-			UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-
-			/*
-			 * Check for octa or quad cable.
-			 */
-			if (!
-			    (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
-			     PCI_GPIO_CTRL_8PORT)) {
-				str = "Quadcable";
-				ports_per_aiop = 4;
-				rocketModel[i].numPorts = 4;
-			}
-		}
-		break;
-	case PCI_DEVICE_ID_UPCI_RM3_8PORT:
-		str = "8 ports";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
-		strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
-		rocketModel[i].numPorts = 8;
-		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
-		UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-		ConfigIO = pci_resource_start(dev, 1);
-		rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
-		break;
-	case PCI_DEVICE_ID_UPCI_RM3_4PORT:
-		str = "4 ports";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
-		strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
-		rocketModel[i].numPorts = 4;
-		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
-		UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-		ConfigIO = pci_resource_start(dev, 1);
-		rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
-		break;
-	default:
-		break;
-	}
-
-	switch (rcktpt_type[i]) {
-	case ROCKET_TYPE_MODEM:
-		board_type = "RocketModem";
-		break;
-	case ROCKET_TYPE_MODEMII:
-		board_type = "RocketModem II";
-		break;
-	case ROCKET_TYPE_MODEMIII:
-		board_type = "RocketModem III";
-		break;
-	default:
-		board_type = "RocketPort";
-		break;
-	}
-
-	if (fast_clock) {
-		sClockPrescale = 0x12;	/* mod 2 (divide by 3) */
-		rp_baud_base[i] = 921600;
-	} else {
-		/*
-		 * If support_low_speed is set, use the slow clock
-		 * prescale, which supports 50 bps
-		 */
-		if (support_low_speed) {
-			/* mod 9 (divide by 10) prescale */
-			sClockPrescale = 0x19;
-			rp_baud_base[i] = 230400;
-		} else {
-			/* mod 4 (devide by 5) prescale */
-			sClockPrescale = 0x14;
-			rp_baud_base[i] = 460800;
-		}
-	}
-
-	for (aiop = 0; aiop < max_num_aiops; aiop++)
-		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
-	ctlp = sCtlNumToCtlPtr(i);
-	num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
-	for (aiop = 0; aiop < max_num_aiops; aiop++)
-		ctlp->AiopNumChan[aiop] = ports_per_aiop;
-
-	dev_info(&dev->dev, "comtrol PCI controller #%d found at "
-		"address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n",
-		i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString,
-		rocketModel[i].startingPortNumber,
-		rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1);
-
-	if (num_aiops <= 0) {
-		rcktpt_io_addr[i] = 0;
-		return (0);
-	}
-	is_PCI[i] = 1;
-
-	/*  Reset the AIOPIC, init the serial ports */
-	for (aiop = 0; aiop < num_aiops; aiop++) {
-		sResetAiopByNum(ctlp, aiop);
-		num_chan = ports_per_aiop;
-		for (chan = 0; chan < num_chan; chan++)
-			init_r_port(i, aiop, chan, dev);
-	}
-
-	/*  Rocket modems must be reset */
-	if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
-	    (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
-	    (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
-		num_chan = ports_per_aiop;
-		for (chan = 0; chan < num_chan; chan++)
-			sPCIModemReset(ctlp, chan, 1);
-		msleep(500);
-		for (chan = 0; chan < num_chan; chan++)
-			sPCIModemReset(ctlp, chan, 0);
-		msleep(500);
-		rmSpeakerReset(ctlp, rocketModel[i].model);
-	}
-	return (1);
-}
-
-/*
- *  Probes for PCI cards, inits them if found
- *  Input:   board_found = number of ISA boards already found, or the
- *           starting board number
- *  Returns: Number of PCI boards found
- */
-static int __init init_PCI(int boards_found)
-{
-	struct pci_dev *dev = NULL;
-	int count = 0;
-
-	/*  Work through the PCI device list, pulling out ours */
-	while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
-		if (register_PCI(count + boards_found, dev))
-			count++;
-	}
-	return (count);
-}
-
-#endif				/* CONFIG_PCI */
-
-/*
- *  Probes for ISA cards
- *  Input:   i = the board number to look for
- *  Returns: 1 if board found, 0 else
- */
-static int __init init_ISA(int i)
-{
-	int num_aiops, num_chan = 0, total_num_chan = 0;
-	int aiop, chan;
-	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
-	CONTROLLER_t *ctlp;
-	char *type_string;
-
-	/*  If io_addr is zero, no board configured */
-	if (rcktpt_io_addr[i] == 0)
-		return (0);
-
-	/*  Reserve the IO region */
-	if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
-		printk(KERN_ERR "Unable to reserve IO region for configured "
-				"ISA RocketPort at address 0x%lx, board not "
-				"installed...\n", rcktpt_io_addr[i]);
-		rcktpt_io_addr[i] = 0;
-		return (0);
-	}
-
-	ctlp = sCtlNumToCtlPtr(i);
-
-	ctlp->boardType = rcktpt_type[i];
-
-	switch (rcktpt_type[i]) {
-	case ROCKET_TYPE_PC104:
-		type_string = "(PC104)";
-		break;
-	case ROCKET_TYPE_MODEM:
-		type_string = "(RocketModem)";
-		break;
-	case ROCKET_TYPE_MODEMII:
-		type_string = "(RocketModem II)";
-		break;
-	default:
-		type_string = "";
-		break;
-	}
-
-	/*
-	 * If support_low_speed is set, use the slow clock prescale,
-	 * which supports 50 bps
-	 */
-	if (support_low_speed) {
-		sClockPrescale = 0x19;	/* mod 9 (divide by 10) prescale */
-		rp_baud_base[i] = 230400;
-	} else {
-		sClockPrescale = 0x14;	/* mod 4 (devide by 5) prescale */
-		rp_baud_base[i] = 460800;
-	}
-
-	for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
-		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
-
-	num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio,  MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
-
-	if (ctlp->boardType == ROCKET_TYPE_PC104) {
-		sEnAiop(ctlp, 2);	/* only one AIOPIC, but these */
-		sEnAiop(ctlp, 3);	/* CSels used for other stuff */
-	}
-
-	/*  If something went wrong initing the AIOP's release the ISA IO memory */
-	if (num_aiops <= 0) {
-		release_region(rcktpt_io_addr[i], 64);
-		rcktpt_io_addr[i] = 0;
-		return (0);
-	}
-  
-	rocketModel[i].startingPortNumber = nextLineNumber;
-
-	for (aiop = 0; aiop < num_aiops; aiop++) {
-		sResetAiopByNum(ctlp, aiop);
-		sEnAiop(ctlp, aiop);
-		num_chan = sGetAiopNumChan(ctlp, aiop);
-		total_num_chan += num_chan;
-		for (chan = 0; chan < num_chan; chan++)
-			init_r_port(i, aiop, chan, NULL);
-	}
-	is_PCI[i] = 0;
-	if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
-		num_chan = sGetAiopNumChan(ctlp, 0);
-		total_num_chan = num_chan;
-		for (chan = 0; chan < num_chan; chan++)
-			sModemReset(ctlp, chan, 1);
-		msleep(500);
-		for (chan = 0; chan < num_chan; chan++)
-			sModemReset(ctlp, chan, 0);
-		msleep(500);
-		strcpy(rocketModel[i].modelString, "RocketModem ISA");
-	} else {
-		strcpy(rocketModel[i].modelString, "RocketPort ISA");
-	}
-	rocketModel[i].numPorts = total_num_chan;
-	rocketModel[i].model = MODEL_ISA;
-
-	printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n", 
-	       i, rcktpt_io_addr[i], num_aiops, type_string);
-
-	printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
-	       rocketModel[i].modelString,
-	       rocketModel[i].startingPortNumber,
-	       rocketModel[i].startingPortNumber +
-	       rocketModel[i].numPorts - 1);
-
-	return (1);
-}
-
-static const struct tty_operations rocket_ops = {
-	.open = rp_open,
-	.close = rp_close,
-	.write = rp_write,
-	.put_char = rp_put_char,
-	.write_room = rp_write_room,
-	.chars_in_buffer = rp_chars_in_buffer,
-	.flush_buffer = rp_flush_buffer,
-	.ioctl = rp_ioctl,
-	.throttle = rp_throttle,
-	.unthrottle = rp_unthrottle,
-	.set_termios = rp_set_termios,
-	.stop = rp_stop,
-	.start = rp_start,
-	.hangup = rp_hangup,
-	.break_ctl = rp_break,
-	.send_xchar = rp_send_xchar,
-	.wait_until_sent = rp_wait_until_sent,
-	.tiocmget = rp_tiocmget,
-	.tiocmset = rp_tiocmset,
-};
-
-static const struct tty_port_operations rocket_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-/*
- * The module "startup" routine; it's run when the module is loaded.
- */
-static int __init rp_init(void)
-{
-	int ret = -ENOMEM, pci_boards_found, isa_boards_found, i;
-
-	printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
-	       ROCKET_VERSION, ROCKET_DATE);
-
-	rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
-	if (!rocket_driver)
-		goto err;
-
-	/*
-	 *  If board 1 is non-zero, there is at least one ISA configured.  If controller is 
-	 *  zero, use the default controller IO address of board1 + 0x40.
-	 */
-	if (board1) {
-		if (controller == 0)
-			controller = board1 + 0x40;
-	} else {
-		controller = 0;  /*  Used as a flag, meaning no ISA boards */
-	}
-
-	/*  If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
-	if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
-		printk(KERN_ERR "Unable to reserve IO region for first "
-			"configured ISA RocketPort controller 0x%lx.  "
-			"Driver exiting\n", controller);
-		ret = -EBUSY;
-		goto err_tty;
-	}
-
-	/*  Store ISA variable retrieved from command line or .conf file. */
-	rcktpt_io_addr[0] = board1;
-	rcktpt_io_addr[1] = board2;
-	rcktpt_io_addr[2] = board3;
-	rcktpt_io_addr[3] = board4;
-
-	rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
-	rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
-	rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
-	rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
-
-	/*
-	 * Set up the tty driver structure and then register this
-	 * driver with the tty layer.
-	 */
-
-	rocket_driver->owner = THIS_MODULE;
-	rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV;
-	rocket_driver->name = "ttyR";
-	rocket_driver->driver_name = "Comtrol RocketPort";
-	rocket_driver->major = TTY_ROCKET_MAJOR;
-	rocket_driver->minor_start = 0;
-	rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	rocket_driver->subtype = SERIAL_TYPE_NORMAL;
-	rocket_driver->init_termios = tty_std_termios;
-	rocket_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rocket_driver->init_termios.c_ispeed = 9600;
-	rocket_driver->init_termios.c_ospeed = 9600;
-#ifdef ROCKET_SOFT_FLOW
-	rocket_driver->flags |= TTY_DRIVER_REAL_RAW;
-#endif
-	tty_set_operations(rocket_driver, &rocket_ops);
-
-	ret = tty_register_driver(rocket_driver);
-	if (ret < 0) {
-		printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
-		goto err_controller;
-	}
-
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
-#endif
-
-	/*
-	 *  OK, let's probe each of the controllers looking for boards.  Any boards found
-         *  will be initialized here.
-	 */
-	isa_boards_found = 0;
-	pci_boards_found = 0;
-
-	for (i = 0; i < NUM_BOARDS; i++) {
-		if (init_ISA(i))
-			isa_boards_found++;
-	}
-
-#ifdef CONFIG_PCI
-	if (isa_boards_found < NUM_BOARDS)
-		pci_boards_found = init_PCI(isa_boards_found);
-#endif
-
-	max_board = pci_boards_found + isa_boards_found;
-
-	if (max_board == 0) {
-		printk(KERN_ERR "No rocketport ports found; unloading driver\n");
-		ret = -ENXIO;
-		goto err_ttyu;
-	}
-
-	return 0;
-err_ttyu:
-	tty_unregister_driver(rocket_driver);
-err_controller:
-	if (controller)
-		release_region(controller, 4);
-err_tty:
-	put_tty_driver(rocket_driver);
-err:
-	return ret;
-}
-
-
-static void rp_cleanup_module(void)
-{
-	int retval;
-	int i;
-
-	del_timer_sync(&rocket_timer);
-
-	retval = tty_unregister_driver(rocket_driver);
-	if (retval)
-		printk(KERN_ERR "Error %d while trying to unregister "
-		       "rocketport driver\n", -retval);
-
-	for (i = 0; i < MAX_RP_PORTS; i++)
-		if (rp_table[i]) {
-			tty_unregister_device(rocket_driver, i);
-			kfree(rp_table[i]);
-		}
-
-	put_tty_driver(rocket_driver);
-
-	for (i = 0; i < NUM_BOARDS; i++) {
-		if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
-			continue;
-		release_region(rcktpt_io_addr[i], 64);
-	}
-	if (controller)
-		release_region(controller, 4);
-}
-
-/***************************************************************************
-Function: sInitController
-Purpose:  Initialization of controller global registers and controller
-          structure.
-Call:     sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
-                          IRQNum,Frequency,PeriodicOnly)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int CtlNum; Controller number
-          ByteIO_t MudbacIO; Mudbac base I/O address.
-          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
-             This list must be in the order the AIOPs will be found on the
-             controller.  Once an AIOP in the list is not found, it is
-             assumed that there are no more AIOPs on the controller.
-          int AiopIOListSize; Number of addresses in AiopIOList
-          int IRQNum; Interrupt Request number.  Can be any of the following:
-                         0: Disable global interrupts
-                         3: IRQ 3
-                         4: IRQ 4
-                         5: IRQ 5
-                         9: IRQ 9
-                         10: IRQ 10
-                         11: IRQ 11
-                         12: IRQ 12
-                         15: IRQ 15
-          Byte_t Frequency: A flag identifying the frequency
-                   of the periodic interrupt, can be any one of the following:
-                      FREQ_DIS - periodic interrupt disabled
-                      FREQ_137HZ - 137 Hertz
-                      FREQ_69HZ - 69 Hertz
-                      FREQ_34HZ - 34 Hertz
-                      FREQ_17HZ - 17 Hertz
-                      FREQ_9HZ - 9 Hertz
-                      FREQ_4HZ - 4 Hertz
-                   If IRQNum is set to 0 the Frequency parameter is
-                   overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: 1 if all interrupts except the periodic
-                               interrupt are to be blocked.
-                            0 is both the periodic interrupt and
-                               other channel interrupts are allowed.
-                            If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of 0.
-Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
-               initialization failed.
-
-Comments:
-          If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
-          If interrupts are to be completely disabled set IRQNum to 0.
-
-          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
-          invalid combination.
-
-          This function performs initialization of global interrupt modes,
-          but it does not actually enable global interrupts.  To enable
-          and disable global interrupts use functions sEnGlobalInt() and
-          sDisGlobalInt().  Enabling of global interrupts is normally not
-          done until all other initializations are complete.
-
-          Even if interrupts are globally enabled, they must also be
-          individually enabled for each channel that is to generate
-          interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-
-          After this function all AIOPs on the controller are disabled,
-          they can be enabled with sEnAiop().
-*/
-static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
-			   ByteIO_t * AiopIOList, int AiopIOListSize,
-			   int IRQNum, Byte_t Frequency, int PeriodicOnly)
-{
-	int i;
-	ByteIO_t io;
-	int done;
-
-	CtlP->AiopIntrBits = aiop_intr_bits;
-	CtlP->AltChanRingIndicator = 0;
-	CtlP->CtlNum = CtlNum;
-	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
-	CtlP->BusType = isISA;
-	CtlP->MBaseIO = MudbacIO;
-	CtlP->MReg1IO = MudbacIO + 1;
-	CtlP->MReg2IO = MudbacIO + 2;
-	CtlP->MReg3IO = MudbacIO + 3;
-#if 1
-	CtlP->MReg2 = 0;	/* interrupt disable */
-	CtlP->MReg3 = 0;	/* no periodic interrupts */
-#else
-	if (sIRQMap[IRQNum] == 0) {	/* interrupts globally disabled */
-		CtlP->MReg2 = 0;	/* interrupt disable */
-		CtlP->MReg3 = 0;	/* no periodic interrupts */
-	} else {
-		CtlP->MReg2 = sIRQMap[IRQNum];	/* set IRQ number */
-		CtlP->MReg3 = Frequency;	/* set frequency */
-		if (PeriodicOnly) {	/* periodic interrupt only */
-			CtlP->MReg3 |= PERIODIC_ONLY;
-		}
-	}
-#endif
-	sOutB(CtlP->MReg2IO, CtlP->MReg2);
-	sOutB(CtlP->MReg3IO, CtlP->MReg3);
-	sControllerEOI(CtlP);	/* clear EOI if warm init */
-	/* Init AIOPs */
-	CtlP->NumAiop = 0;
-	for (i = done = 0; i < AiopIOListSize; i++) {
-		io = AiopIOList[i];
-		CtlP->AiopIO[i] = (WordIO_t) io;
-		CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-		sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03));	/* AIOP index */
-		sOutB(MudbacIO, (Byte_t) (io >> 6));	/* set up AIOP I/O in MUDBAC */
-		if (done)
-			continue;
-		sEnAiop(CtlP, i);	/* enable the AIOP */
-		CtlP->AiopID[i] = sReadAiopID(io);	/* read AIOP ID */
-		if (CtlP->AiopID[i] == AIOPID_NULL)	/* if AIOP does not exist */
-			done = 1;	/* done looking for AIOPs */
-		else {
-			CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io);	/* num channels in AIOP */
-			sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);	/* clock prescaler */
-			sOutB(io + _INDX_DATA, sClockPrescale);
-			CtlP->NumAiop++;	/* bump count of AIOPs */
-		}
-		sDisAiop(CtlP, i);	/* disable AIOP */
-	}
-
-	if (CtlP->NumAiop == 0)
-		return (-1);
-	else
-		return (CtlP->NumAiop);
-}
-
-/***************************************************************************
-Function: sPCIInitController
-Purpose:  Initialization of controller global registers and controller
-          structure.
-Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
-                          IRQNum,Frequency,PeriodicOnly)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int CtlNum; Controller number
-          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
-             This list must be in the order the AIOPs will be found on the
-             controller.  Once an AIOP in the list is not found, it is
-             assumed that there are no more AIOPs on the controller.
-          int AiopIOListSize; Number of addresses in AiopIOList
-          int IRQNum; Interrupt Request number.  Can be any of the following:
-                         0: Disable global interrupts
-                         3: IRQ 3
-                         4: IRQ 4
-                         5: IRQ 5
-                         9: IRQ 9
-                         10: IRQ 10
-                         11: IRQ 11
-                         12: IRQ 12
-                         15: IRQ 15
-          Byte_t Frequency: A flag identifying the frequency
-                   of the periodic interrupt, can be any one of the following:
-                      FREQ_DIS - periodic interrupt disabled
-                      FREQ_137HZ - 137 Hertz
-                      FREQ_69HZ - 69 Hertz
-                      FREQ_34HZ - 34 Hertz
-                      FREQ_17HZ - 17 Hertz
-                      FREQ_9HZ - 9 Hertz
-                      FREQ_4HZ - 4 Hertz
-                   If IRQNum is set to 0 the Frequency parameter is
-                   overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: 1 if all interrupts except the periodic
-                               interrupt are to be blocked.
-                            0 is both the periodic interrupt and
-                               other channel interrupts are allowed.
-                            If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of 0.
-Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
-               initialization failed.
-
-Comments:
-          If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
-          If interrupts are to be completely disabled set IRQNum to 0.
-
-          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
-          invalid combination.
-
-          This function performs initialization of global interrupt modes,
-          but it does not actually enable global interrupts.  To enable
-          and disable global interrupts use functions sEnGlobalInt() and
-          sDisGlobalInt().  Enabling of global interrupts is normally not
-          done until all other initializations are complete.
-
-          Even if interrupts are globally enabled, they must also be
-          individually enabled for each channel that is to generate
-          interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-
-          After this function all AIOPs on the controller are disabled,
-          they can be enabled with sEnAiop().
-*/
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-			      ByteIO_t * AiopIOList, int AiopIOListSize,
-			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-			      int PeriodicOnly, int altChanRingIndicator,
-			      int UPCIRingInd)
-{
-	int i;
-	ByteIO_t io;
-
-	CtlP->AltChanRingIndicator = altChanRingIndicator;
-	CtlP->UPCIRingInd = UPCIRingInd;
-	CtlP->CtlNum = CtlNum;
-	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
-	CtlP->BusType = isPCI;	/* controller release 1 */
-
-	if (ConfigIO) {
-		CtlP->isUPCI = 1;
-		CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
-		CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
-		CtlP->AiopIntrBits = upci_aiop_intr_bits;
-	} else {
-		CtlP->isUPCI = 0;
-		CtlP->PCIIO =
-		    (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
-		CtlP->AiopIntrBits = aiop_intr_bits;
-	}
-
-	sPCIControllerEOI(CtlP);	/* clear EOI if warm init */
-	/* Init AIOPs */
-	CtlP->NumAiop = 0;
-	for (i = 0; i < AiopIOListSize; i++) {
-		io = AiopIOList[i];
-		CtlP->AiopIO[i] = (WordIO_t) io;
-		CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-
-		CtlP->AiopID[i] = sReadAiopID(io);	/* read AIOP ID */
-		if (CtlP->AiopID[i] == AIOPID_NULL)	/* if AIOP does not exist */
-			break;	/* done looking for AIOPs */
-
-		CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io);	/* num channels in AIOP */
-		sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);	/* clock prescaler */
-		sOutB(io + _INDX_DATA, sClockPrescale);
-		CtlP->NumAiop++;	/* bump count of AIOPs */
-	}
-
-	if (CtlP->NumAiop == 0)
-		return (-1);
-	else
-		return (CtlP->NumAiop);
-}
-
-/***************************************************************************
-Function: sReadAiopID
-Purpose:  Read the AIOP idenfication number directly from an AIOP.
-Call:     sReadAiopID(io)
-          ByteIO_t io: AIOP base I/O address
-Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
-                 is replace by an identifying number.
-          Flag AIOPID_NULL if no valid AIOP is found
-Warnings: No context switches are allowed while executing this function.
-
-*/
-static int sReadAiopID(ByteIO_t io)
-{
-	Byte_t AiopID;		/* ID byte from AIOP */
-
-	sOutB(io + _CMD_REG, RESET_ALL);	/* reset AIOP */
-	sOutB(io + _CMD_REG, 0x0);
-	AiopID = sInW(io + _CHN_STAT0) & 0x07;
-	if (AiopID == 0x06)
-		return (1);
-	else			/* AIOP does not exist */
-		return (-1);
-}
-
-/***************************************************************************
-Function: sReadAiopNumChan
-Purpose:  Read the number of channels available in an AIOP directly from
-          an AIOP.
-Call:     sReadAiopNumChan(io)
-          WordIO_t io: AIOP base I/O address
-Return:   int: The number of channels available
-Comments: The number of channels is determined by write/reads from identical
-          offsets within the SRAM address spaces for channels 0 and 4.
-          If the channel 4 space is mirrored to channel 0 it is a 4 channel
-          AIOP, otherwise it is an 8 channel.
-Warnings: No context switches are allowed while executing this function.
-*/
-static int sReadAiopNumChan(WordIO_t io)
-{
-	Word_t x;
-	static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
-
-	/* write to chan 0 SRAM */
-	out32((DWordIO_t) io + _INDX_ADDR, R);
-	sOutW(io + _INDX_ADDR, 0);	/* read from SRAM, chan 0 */
-	x = sInW(io + _INDX_DATA);
-	sOutW(io + _INDX_ADDR, 0x4000);	/* read from SRAM, chan 4 */
-	if (x != sInW(io + _INDX_DATA))	/* if different must be 8 chan */
-		return (8);
-	else
-		return (4);
-}
-
-/***************************************************************************
-Function: sInitChan
-Purpose:  Initialization of a channel and channel structure
-Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          CHANNEL_T *ChP; Ptr to channel structure
-          int AiopNum; AIOP number within controller
-          int ChanNum; Channel number within AIOP
-Return:   int: 1 if initialization succeeded, 0 if it fails because channel
-               number exceeds number of channels available in AIOP.
-Comments: This function must be called before a channel can be used.
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-*/
-static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
-		     int ChanNum)
-{
-	int i;
-	WordIO_t AiopIO;
-	WordIO_t ChIOOff;
-	Byte_t *ChR;
-	Word_t ChOff;
-	static Byte_t R[4];
-	int brd9600;
-
-	if (ChanNum >= CtlP->AiopNumChan[AiopNum])
-		return 0;	/* exceeds num chans in AIOP */
-
-	/* Channel, AIOP, and controller identifiers */
-	ChP->CtlP = CtlP;
-	ChP->ChanID = CtlP->AiopID[AiopNum];
-	ChP->AiopNum = AiopNum;
-	ChP->ChanNum = ChanNum;
-
-	/* Global direct addresses */
-	AiopIO = CtlP->AiopIO[AiopNum];
-	ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
-	ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
-	ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
-	ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
-	ChP->IndexData = AiopIO + _INDX_DATA;
-
-	/* Channel direct addresses */
-	ChIOOff = AiopIO + ChP->ChanNum * 2;
-	ChP->TxRxData = ChIOOff + _TD0;
-	ChP->ChanStat = ChIOOff + _CHN_STAT0;
-	ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
-	ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
-
-	/* Initialize the channel from the RData array */
-	for (i = 0; i < RDATASIZE; i += 4) {
-		R[0] = RData[i];
-		R[1] = RData[i + 1] + 0x10 * ChanNum;
-		R[2] = RData[i + 2];
-		R[3] = RData[i + 3];
-		out32(ChP->IndexAddr, R);
-	}
-
-	ChR = ChP->R;
-	for (i = 0; i < RREGDATASIZE; i += 4) {
-		ChR[i] = RRegData[i];
-		ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
-		ChR[i + 2] = RRegData[i + 2];
-		ChR[i + 3] = RRegData[i + 3];
-	}
-
-	/* Indexed registers */
-	ChOff = (Word_t) ChanNum *0x1000;
-
-	if (sClockPrescale == 0x14)
-		brd9600 = 47;
-	else
-		brd9600 = 23;
-
-	ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
-	ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
-	ChP->BaudDiv[2] = (Byte_t) brd9600;
-	ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
-	out32(ChP->IndexAddr, ChP->BaudDiv);
-
-	ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
-	ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
-	ChP->TxControl[2] = 0;
-	ChP->TxControl[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxControl);
-
-	ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
-	ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
-	ChP->RxControl[2] = 0;
-	ChP->RxControl[3] = 0;
-	out32(ChP->IndexAddr, ChP->RxControl);
-
-	ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
-	ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
-	ChP->TxEnables[2] = 0;
-	ChP->TxEnables[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxEnables);
-
-	ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
-	ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
-	ChP->TxCompare[2] = 0;
-	ChP->TxCompare[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxCompare);
-
-	ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
-	ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
-	ChP->TxReplace1[2] = 0;
-	ChP->TxReplace1[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxReplace1);
-
-	ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
-	ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
-	ChP->TxReplace2[2] = 0;
-	ChP->TxReplace2[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxReplace2);
-
-	ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
-	ChP->TxFIFO = ChOff + _TX_FIFO;
-
-	sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT);	/* apply reset Tx FIFO count */
-	sOutB(ChP->Cmd, (Byte_t) ChanNum);	/* remove reset Tx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs);	/* clear Tx in/out ptrs */
-	sOutW(ChP->IndexData, 0);
-	ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
-	ChP->RxFIFO = ChOff + _RX_FIFO;
-
-	sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT);	/* apply reset Rx FIFO count */
-	sOutB(ChP->Cmd, (Byte_t) ChanNum);	/* remove reset Rx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs);	/* clear Rx out ptr */
-	sOutW(ChP->IndexData, 0);
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2);	/* clear Rx in ptr */
-	sOutW(ChP->IndexData, 0);
-	ChP->TxPrioCnt = ChOff + _TXP_CNT;
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
-	sOutB(ChP->IndexData, 0);
-	ChP->TxPrioPtr = ChOff + _TXP_PNTR;
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
-	sOutB(ChP->IndexData, 0);
-	ChP->TxPrioBuf = ChOff + _TXP_BUF;
-	sEnRxProcessor(ChP);	/* start the Rx processor */
-
-	return 1;
-}
-
-/***************************************************************************
-Function: sStopRxProcessor
-Purpose:  Stop the receive processor from processing a channel.
-Call:     sStopRxProcessor(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-
-Comments: The receive processor can be started again with sStartRxProcessor().
-          This function causes the receive processor to skip over the
-          stopped channel.  It does not stop it from processing other channels.
-
-Warnings: No context switches are allowed while executing this function.
-
-          Do not leave the receive processor stopped for more than one
-          character time.
-
-          After calling this function a delay of 4 uS is required to ensure
-          that the receive processor is no longer processing this channel.
-*/
-static void sStopRxProcessor(CHANNEL_T * ChP)
-{
-	Byte_t R[4];
-
-	R[0] = ChP->R[0];
-	R[1] = ChP->R[1];
-	R[2] = 0x0a;
-	R[3] = ChP->R[3];
-	out32(ChP->IndexAddr, R);
-}
-
-/***************************************************************************
-Function: sFlushRxFIFO
-Purpose:  Flush the Rx FIFO
-Call:     sFlushRxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   void
-Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
-          while it is being flushed the receive processor is stopped
-          and the transmitter is disabled.  After these operations a
-          4 uS delay is done before clearing the pointers to allow
-          the receive processor to stop.  These items are handled inside
-          this function.
-Warnings: No context switches are allowed while executing this function.
-*/
-static void sFlushRxFIFO(CHANNEL_T * ChP)
-{
-	int i;
-	Byte_t Ch;		/* channel number within AIOP */
-	int RxFIFOEnabled;	/* 1 if Rx FIFO enabled */
-
-	if (sGetRxCnt(ChP) == 0)	/* Rx FIFO empty */
-		return;		/* don't need to flush */
-
-	RxFIFOEnabled = 0;
-	if (ChP->R[0x32] == 0x08) {	/* Rx FIFO is enabled */
-		RxFIFOEnabled = 1;
-		sDisRxFIFO(ChP);	/* disable it */
-		for (i = 0; i < 2000 / 200; i++)	/* delay 2 uS to allow proc to disable FIFO */
-			sInB(ChP->IntChan);	/* depends on bus i/o timing */
-	}
-	sGetChanStatus(ChP);	/* clear any pending Rx errors in chan stat */
-	Ch = (Byte_t) sGetChanNum(ChP);
-	sOutB(ChP->Cmd, Ch | RESRXFCNT);	/* apply reset Rx FIFO count */
-	sOutB(ChP->Cmd, Ch);	/* remove reset Rx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs);	/* clear Rx out ptr */
-	sOutW(ChP->IndexData, 0);
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2);	/* clear Rx in ptr */
-	sOutW(ChP->IndexData, 0);
-	if (RxFIFOEnabled)
-		sEnRxFIFO(ChP);	/* enable Rx FIFO */
-}
-
-/***************************************************************************
-Function: sFlushTxFIFO
-Purpose:  Flush the Tx FIFO
-Call:     sFlushTxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   void
-Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
-          while it is being flushed the receive processor is stopped
-          and the transmitter is disabled.  After these operations a
-          4 uS delay is done before clearing the pointers to allow
-          the receive processor to stop.  These items are handled inside
-          this function.
-Warnings: No context switches are allowed while executing this function.
-*/
-static void sFlushTxFIFO(CHANNEL_T * ChP)
-{
-	int i;
-	Byte_t Ch;		/* channel number within AIOP */
-	int TxEnabled;		/* 1 if transmitter enabled */
-
-	if (sGetTxCnt(ChP) == 0)	/* Tx FIFO empty */
-		return;		/* don't need to flush */
-
-	TxEnabled = 0;
-	if (ChP->TxControl[3] & TX_ENABLE) {
-		TxEnabled = 1;
-		sDisTransmit(ChP);	/* disable transmitter */
-	}
-	sStopRxProcessor(ChP);	/* stop Rx processor */
-	for (i = 0; i < 4000 / 200; i++)	/* delay 4 uS to allow proc to stop */
-		sInB(ChP->IntChan);	/* depends on bus i/o timing */
-	Ch = (Byte_t) sGetChanNum(ChP);
-	sOutB(ChP->Cmd, Ch | RESTXFCNT);	/* apply reset Tx FIFO count */
-	sOutB(ChP->Cmd, Ch);	/* remove reset Tx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs);	/* clear Tx in/out ptrs */
-	sOutW(ChP->IndexData, 0);
-	if (TxEnabled)
-		sEnTransmit(ChP);	/* enable transmitter */
-	sStartRxProcessor(ChP);	/* restart Rx processor */
-}
-
-/***************************************************************************
-Function: sWriteTxPrioByte
-Purpose:  Write a byte of priority transmit data to a channel
-Call:     sWriteTxPrioByte(ChP,Data)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Data; The transmit data byte
-
-Return:   int: 1 if the bytes is successfully written, otherwise 0.
-
-Comments: The priority byte is transmitted before any data in the Tx FIFO.
-
-Warnings: No context switches are allowed while executing this function.
-*/
-static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
-{
-	Byte_t DWBuf[4];	/* buffer for double word writes */
-	Word_t *WordPtr;	/* must be far because Win SS != DS */
-	register DWordIO_t IndexAddr;
-
-	if (sGetTxCnt(ChP) > 1) {	/* write it to Tx priority buffer */
-		IndexAddr = ChP->IndexAddr;
-		sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt);	/* get priority buffer status */
-		if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND)	/* priority buffer busy */
-			return (0);	/* nothing sent */
-
-		WordPtr = (Word_t *) (&DWBuf[0]);
-		*WordPtr = ChP->TxPrioBuf;	/* data byte address */
-
-		DWBuf[2] = Data;	/* data byte value */
-		out32(IndexAddr, DWBuf);	/* write it out */
-
-		*WordPtr = ChP->TxPrioCnt;	/* Tx priority count address */
-
-		DWBuf[2] = PRI_PEND + 1;	/* indicate 1 byte pending */
-		DWBuf[3] = 0;	/* priority buffer pointer */
-		out32(IndexAddr, DWBuf);	/* write it out */
-	} else {		/* write it to Tx FIFO */
-
-		sWriteTxByte(sGetTxRxDataIO(ChP), Data);
-	}
-	return (1);		/* 1 byte sent */
-}
-
-/***************************************************************************
-Function: sEnInterrupts
-Purpose:  Enable one or more interrupts for a channel
-Call:     sEnInterrupts(ChP,Flags)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Word_t Flags: Interrupt enable flags, can be any combination
-             of the following flags:
-                TXINT_EN:   Interrupt on Tx FIFO empty
-                RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
-                            sSetRxTrigger())
-                SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
-                MCINT_EN:   Interrupt on modem input change
-                CHANINT_EN: Allow channel interrupt signal to the AIOP's
-                            Interrupt Channel Register.
-Return:   void
-Comments: If an interrupt enable flag is set in Flags, that interrupt will be
-          enabled.  If an interrupt enable flag is not set in Flags, that
-          interrupt will not be changed.  Interrupts can be disabled with
-          function sDisInterrupts().
-
-          This function sets the appropriate bit for the channel in the AIOP's
-          Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
-          this channel's bit to be set in the AIOP's Interrupt Channel Register.
-
-          Interrupts must also be globally enabled before channel interrupts
-          will be passed on to the host.  This is done with function
-          sEnGlobalInt().
-
-          In some cases it may be desirable to disable interrupts globally but
-          enable channel interrupts.  This would allow the global interrupt
-          status register to be used to determine which AIOPs need service.
-*/
-static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
-{
-	Byte_t Mask;		/* Interrupt Mask Register */
-
-	ChP->RxControl[2] |=
-	    ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
-
-	out32(ChP->IndexAddr, ChP->RxControl);
-
-	ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
-
-	out32(ChP->IndexAddr, ChP->TxControl);
-
-	if (Flags & CHANINT_EN) {
-		Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
-		sOutB(ChP->IntMask, Mask);
-	}
-}
-
-/***************************************************************************
-Function: sDisInterrupts
-Purpose:  Disable one or more interrupts for a channel
-Call:     sDisInterrupts(ChP,Flags)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Word_t Flags: Interrupt flags, can be any combination
-             of the following flags:
-                TXINT_EN:   Interrupt on Tx FIFO empty
-                RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
-                            sSetRxTrigger())
-                SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
-                MCINT_EN:   Interrupt on modem input change
-                CHANINT_EN: Disable channel interrupt signal to the
-                            AIOP's Interrupt Channel Register.
-Return:   void
-Comments: If an interrupt flag is set in Flags, that interrupt will be
-          disabled.  If an interrupt flag is not set in Flags, that
-          interrupt will not be changed.  Interrupts can be enabled with
-          function sEnInterrupts().
-
-          This function clears the appropriate bit for the channel in the AIOP's
-          Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
-          this channel's bit from being set in the AIOP's Interrupt Channel
-          Register.
-*/
-static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
-{
-	Byte_t Mask;		/* Interrupt Mask Register */
-
-	ChP->RxControl[2] &=
-	    ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
-	out32(ChP->IndexAddr, ChP->RxControl);
-	ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
-	out32(ChP->IndexAddr, ChP->TxControl);
-
-	if (Flags & CHANINT_EN) {
-		Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
-		sOutB(ChP->IntMask, Mask);
-	}
-}
-
-static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
-{
-	sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
-}
-
-/*
- *  Not an official SSCI function, but how to reset RocketModems.
- *  ISA bus version
- */
-static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
-{
-	ByteIO_t addr;
-	Byte_t val;
-
-	addr = CtlP->AiopIO[0] + 0x400;
-	val = sInB(CtlP->MReg3IO);
-	/* if AIOP[1] is not enabled, enable it */
-	if ((val & 2) == 0) {
-		val = sInB(CtlP->MReg2IO);
-		sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
-		sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
-	}
-
-	sEnAiop(CtlP, 1);
-	if (!on)
-		addr += 8;
-	sOutB(addr + chan, 0);	/* apply or remove reset */
-	sDisAiop(CtlP, 1);
-}
-
-/*
- *  Not an official SSCI function, but how to reset RocketModems.
- *  PCI bus version
- */
-static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
-{
-	ByteIO_t addr;
-
-	addr = CtlP->AiopIO[0] + 0x40;	/* 2nd AIOP */
-	if (!on)
-		addr += 8;
-	sOutB(addr + chan, 0);	/* apply or remove reset */
-}
-
-/*  Resets the speaker controller on RocketModem II and III devices */
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
-{
-	ByteIO_t addr;
-
-	/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
-	if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
-		addr = CtlP->AiopIO[0] + 0x4F;
-		sOutB(addr, 0);
-	}
-
-	/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
-	if ((model == MODEL_UPCI_RM3_8PORT)
-	    || (model == MODEL_UPCI_RM3_4PORT)) {
-		addr = CtlP->AiopIO[0] + 0x88;
-		sOutB(addr, 0);
-	}
-}
-
-/*  Returns the line number given the controller (board), aiop and channel number */
-static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
-{
-	return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
-}
-
-/*
- *  Stores the line number associated with a given controller (board), aiop
- *  and channel number.  
- *  Returns:  The line number assigned 
- */
-static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
-{
-	lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
-	return (nextLineNumber - 1);
-}
diff --git a/drivers/char/rocket.h b/drivers/char/rocket.h
deleted file mode 100644
index ec863f3..0000000
--- a/drivers/char/rocket.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * rocket.h --- the exported interface of the rocket driver to its configuration program.
- *
- * Written by Theodore Ts'o, Copyright 1997.
- * Copyright 1997 Comtrol Corporation. 
- *
- */
-
-/*  Model Information Struct */
-typedef struct {
-	unsigned long model;
-	char modelString[80];
-	unsigned long numPorts;
-	int loadrm2;
-	int startingPortNumber;
-} rocketModel_t;
-
-struct rocket_config {
-	int line;
-	int flags;
-	int closing_wait;
-	int close_delay;
-	int port;
-	int reserved[32];
-};
-
-struct rocket_ports {
-	int tty_major;
-	int callout_major;
-	rocketModel_t rocketModel[8];
-};
-
-struct rocket_version {
-	char rocket_version[32];
-	char rocket_date[32];
-	char reserved[64];
-};
-
-/*
- * Rocketport flags
- */
-/*#define ROCKET_CALLOUT_NOHUP    0x00000001 */
-#define ROCKET_FORCE_CD		0x00000002
-#define ROCKET_HUP_NOTIFY	0x00000004
-#define ROCKET_SPLIT_TERMIOS	0x00000008
-#define ROCKET_SPD_MASK		0x00000070
-#define ROCKET_SPD_HI		0x00000010	/* Use 56000 instead of 38400 bps */
-#define ROCKET_SPD_VHI		0x00000020	/* Use 115200 instead of 38400 bps */
-#define ROCKET_SPD_SHI		0x00000030	/* Use 230400 instead of 38400 bps */
-#define ROCKET_SPD_WARP	        0x00000040	/* Use 460800 instead of 38400 bps */
-#define ROCKET_SAK		0x00000080
-#define ROCKET_SESSION_LOCKOUT	0x00000100
-#define ROCKET_PGRP_LOCKOUT	0x00000200
-#define ROCKET_RTS_TOGGLE	0x00000400
-#define ROCKET_MODE_MASK        0x00003000
-#define ROCKET_MODE_RS232       0x00000000
-#define ROCKET_MODE_RS485       0x00001000
-#define ROCKET_MODE_RS422       0x00002000
-#define ROCKET_FLAGS		0x00003FFF
-
-#define ROCKET_USR_MASK 0x0071	/* Legal flags that non-privileged
-				 * users can set or reset */
-
-/*
- * For closing_wait and closing_wait2
- */
-#define ROCKET_CLOSING_WAIT_NONE	ASYNC_CLOSING_WAIT_NONE
-#define ROCKET_CLOSING_WAIT_INF		ASYNC_CLOSING_WAIT_INF
-
-/*
- * Rocketport ioctls -- "RP"
- */
-#define RCKP_GET_STRUCT		0x00525001
-#define RCKP_GET_CONFIG		0x00525002
-#define RCKP_SET_CONFIG		0x00525003
-#define RCKP_GET_PORTS		0x00525004
-#define RCKP_RESET_RM2		0x00525005
-#define RCKP_GET_VERSION	0x00525006
-
-/*  Rocketport Models */
-#define MODEL_RP32INTF        0x0001	/* RP 32 port w/external I/F   */
-#define MODEL_RP8INTF         0x0002	/* RP 8 port w/external I/F    */
-#define MODEL_RP16INTF        0x0003	/* RP 16 port w/external I/F   */
-#define MODEL_RP8OCTA         0x0005	/* RP 8 port w/octa cable      */
-#define MODEL_RP4QUAD         0x0004	/* RP 4 port w/quad cable      */
-#define MODEL_RP8J            0x0006	/* RP 8 port w/RJ11 connectors */
-#define MODEL_RP4J            0x0007	/* RP 4 port w/RJ45 connectors */
-#define MODEL_RP8SNI          0x0008	/* RP 8 port w/ DB78 SNI connector */
-#define MODEL_RP16SNI         0x0009	/* RP 16 port w/ DB78 SNI connector */
-#define MODEL_RPP4            0x000A	/* RP Plus 4 port              */
-#define MODEL_RPP8            0x000B	/* RP Plus 8 port              */
-#define MODEL_RP2_232         0x000E	/* RP Plus 2 port RS232        */
-#define MODEL_RP2_422         0x000F	/* RP Plus 2 port RS232        */
-
-/*  Rocketmodem II Models */
-#define MODEL_RP6M            0x000C	/* RM 6 port                   */
-#define MODEL_RP4M            0x000D	/* RM 4 port                   */
-
-/* Universal PCI boards */
-#define MODEL_UPCI_RP32INTF   0x0801	/* RP UPCI 32 port w/external I/F     */
-#define MODEL_UPCI_RP8INTF    0x0802	/* RP UPCI 8 port w/external I/F      */
-#define MODEL_UPCI_RP16INTF   0x0803	/* RP UPCI 16 port w/external I/F     */
-#define MODEL_UPCI_RP8OCTA    0x0805	/* RP UPCI 8 port w/octa cable        */ 
-#define MODEL_UPCI_RM3_8PORT  0x080C	/* RP UPCI Rocketmodem III 8 port     */
-#define MODEL_UPCI_RM3_4PORT  0x080C	/* RP UPCI Rocketmodem III 4 port     */
-
-/*  Compact PCI 16 port  */
-#define MODEL_CPCI_RP16INTF   0x0903	/* RP Compact PCI 16 port w/external I/F */
-
-/* All ISA boards */
-#define MODEL_ISA             0x1000
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
deleted file mode 100644
index 67e0f1e..0000000
--- a/drivers/char/rocket_int.h
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- * rocket_int.h --- internal header file for rocket.c
- *
- * Written by Theodore Ts'o, Copyright 1997.
- * Copyright 1997 Comtrol Corporation.  
- * 
- */
-
-/*
- * Definition of the types in rcktpt_type
- */
-#define ROCKET_TYPE_NORMAL	0
-#define ROCKET_TYPE_MODEM	1
-#define ROCKET_TYPE_MODEMII	2
-#define ROCKET_TYPE_MODEMIII	3
-#define ROCKET_TYPE_PC104       4
-
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-typedef unsigned char Byte_t;
-typedef unsigned int ByteIO_t;
-
-typedef unsigned int Word_t;
-typedef unsigned int WordIO_t;
-
-typedef unsigned int DWordIO_t;
-
-/*
- * Note!  Normally the Linux I/O macros already take care of
- * byte-swapping the I/O instructions.  However, all accesses using
- * sOutDW aren't really 32-bit accesses, but should be handled in byte
- * order.  Hence the use of the cpu_to_le32() macro to byte-swap
- * things to no-op the byte swapping done by the big-endian outl()
- * instruction.
- */
-
-static inline void sOutB(unsigned short port, unsigned char value)
-{
-#ifdef ROCKET_DEBUG_IO
-	printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value);
-#endif
-	outb_p(value, port);
-}
-
-static inline void sOutW(unsigned short port, unsigned short value)
-{
-#ifdef ROCKET_DEBUG_IO
-	printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value);
-#endif
-	outw_p(value, port);
-}
-
-static inline void out32(unsigned short port, Byte_t *p)
-{
-	u32 value = get_unaligned_le32(p);
-#ifdef ROCKET_DEBUG_IO
-	printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value);
-#endif
-	outl_p(value, port);
-}
-
-static inline unsigned char sInB(unsigned short port)
-{
-	return inb_p(port);
-}
-
-static inline unsigned short sInW(unsigned short port)
-{
-	return inw_p(port);
-}
-
-/* This is used to move arrays of bytes so byte swapping isn't appropriate. */
-#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count)
-#define sInStrW(port, addr, count) if (count) insw(port, addr, count)
-
-#define CTL_SIZE 8
-#define AIOP_CTL_SIZE 4
-#define CHAN_AIOP_SIZE 8
-#define MAX_PORTS_PER_AIOP 8
-#define MAX_AIOPS_PER_BOARD 4
-#define MAX_PORTS_PER_BOARD 32
-
-/* Bus type ID */
-#define	isISA	0
-#define	isPCI	1
-#define	isMC	2
-
-/* Controller ID numbers */
-#define CTLID_NULL  -1		/* no controller exists */
-#define CTLID_0001  0x0001	/* controller release 1 */
-
-/* AIOP ID numbers, identifies AIOP type implementing channel */
-#define AIOPID_NULL -1		/* no AIOP or channel exists */
-#define AIOPID_0001 0x0001	/* AIOP release 1 */
-
-/************************************************************************
- Global Register Offsets - Direct Access - Fixed values
-************************************************************************/
-
-#define _CMD_REG   0x38		/* Command Register            8    Write */
-#define _INT_CHAN  0x39		/* Interrupt Channel Register  8    Read */
-#define _INT_MASK  0x3A		/* Interrupt Mask Register     8    Read / Write */
-#define _UNUSED    0x3B		/* Unused                      8 */
-#define _INDX_ADDR 0x3C		/* Index Register Address      16   Write */
-#define _INDX_DATA 0x3E		/* Index Register Data         8/16 Read / Write */
-
-/************************************************************************
- Channel Register Offsets for 1st channel in AIOP - Direct Access
-************************************************************************/
-#define _TD0       0x00		/* Transmit Data               16   Write */
-#define _RD0       0x00		/* Receive Data                16   Read */
-#define _CHN_STAT0 0x20		/* Channel Status              8/16 Read / Write */
-#define _FIFO_CNT0 0x10		/* Transmit/Receive FIFO Count 16   Read */
-#define _INT_ID0   0x30		/* Interrupt Identification    8    Read */
-
-/************************************************************************
- Tx Control Register Offsets - Indexed - External - Fixed
-************************************************************************/
-#define _TX_ENBLS  0x980	/* Tx Processor Enables Register 8 Read / Write */
-#define _TXCMP1    0x988	/* Transmit Compare Value #1     8 Read / Write */
-#define _TXCMP2    0x989	/* Transmit Compare Value #2     8 Read / Write */
-#define _TXREP1B1  0x98A	/* Tx Replace Value #1 - Byte 1  8 Read / Write */
-#define _TXREP1B2  0x98B	/* Tx Replace Value #1 - Byte 2  8 Read / Write */
-#define _TXREP2    0x98C	/* Transmit Replace Value #2     8 Read / Write */
-
-/************************************************************************
-Memory Controller Register Offsets - Indexed - External - Fixed
-************************************************************************/
-#define _RX_FIFO    0x000	/* Rx FIFO */
-#define _TX_FIFO    0x800	/* Tx FIFO */
-#define _RXF_OUTP   0x990	/* Rx FIFO OUT pointer        16 Read / Write */
-#define _RXF_INP    0x992	/* Rx FIFO IN pointer         16 Read / Write */
-#define _TXF_OUTP   0x994	/* Tx FIFO OUT pointer        8  Read / Write */
-#define _TXF_INP    0x995	/* Tx FIFO IN pointer         8  Read / Write */
-#define _TXP_CNT    0x996	/* Tx Priority Count          8  Read / Write */
-#define _TXP_PNTR   0x997	/* Tx Priority Pointer        8  Read / Write */
-
-#define PRI_PEND    0x80	/* Priority data pending (bit7, Tx pri cnt) */
-#define TXFIFO_SIZE 255		/* size of Tx FIFO */
-#define RXFIFO_SIZE 1023	/* size of Rx FIFO */
-
-/************************************************************************
-Tx Priority Buffer - Indexed - External - Fixed
-************************************************************************/
-#define _TXP_BUF    0x9C0	/* Tx Priority Buffer  32  Bytes   Read / Write */
-#define TXP_SIZE    0x20	/* 32 bytes */
-
-/************************************************************************
-Channel Register Offsets - Indexed - Internal - Fixed
-************************************************************************/
-
-#define _TX_CTRL    0xFF0	/* Transmit Control               16  Write */
-#define _RX_CTRL    0xFF2	/* Receive Control                 8  Write */
-#define _BAUD       0xFF4	/* Baud Rate                      16  Write */
-#define _CLK_PRE    0xFF6	/* Clock Prescaler                 8  Write */
-
-#define STMBREAK   0x08		/* BREAK */
-#define STMFRAME   0x04		/* framing error */
-#define STMRCVROVR 0x02		/* receiver over run error */
-#define STMPARITY  0x01		/* parity error */
-#define STMERROR   (STMBREAK | STMFRAME | STMPARITY)
-#define STMBREAKH   0x800	/* BREAK */
-#define STMFRAMEH   0x400	/* framing error */
-#define STMRCVROVRH 0x200	/* receiver over run error */
-#define STMPARITYH  0x100	/* parity error */
-#define STMERRORH   (STMBREAKH | STMFRAMEH | STMPARITYH)
-
-#define CTS_ACT   0x20		/* CTS input asserted */
-#define DSR_ACT   0x10		/* DSR input asserted */
-#define CD_ACT    0x08		/* CD input asserted */
-#define TXFIFOMT  0x04		/* Tx FIFO is empty */
-#define TXSHRMT   0x02		/* Tx shift register is empty */
-#define RDA       0x01		/* Rx data available */
-#define DRAINED (TXFIFOMT | TXSHRMT)	/* indicates Tx is drained */
-
-#define STATMODE  0x8000	/* status mode enable bit */
-#define RXFOVERFL 0x2000	/* receive FIFO overflow */
-#define RX2MATCH  0x1000	/* receive compare byte 2 match */
-#define RX1MATCH  0x0800	/* receive compare byte 1 match */
-#define RXBREAK   0x0400	/* received BREAK */
-#define RXFRAME   0x0200	/* received framing error */
-#define RXPARITY  0x0100	/* received parity error */
-#define STATERROR (RXBREAK | RXFRAME | RXPARITY)
-
-#define CTSFC_EN  0x80		/* CTS flow control enable bit */
-#define RTSTOG_EN 0x40		/* RTS toggle enable bit */
-#define TXINT_EN  0x10		/* transmit interrupt enable */
-#define STOP2     0x08		/* enable 2 stop bits (0 = 1 stop) */
-#define PARITY_EN 0x04		/* enable parity (0 = no parity) */
-#define EVEN_PAR  0x02		/* even parity (0 = odd parity) */
-#define DATA8BIT  0x01		/* 8 bit data (0 = 7 bit data) */
-
-#define SETBREAK  0x10		/* send break condition (must clear) */
-#define LOCALLOOP 0x08		/* local loopback set for test */
-#define SET_DTR   0x04		/* assert DTR */
-#define SET_RTS   0x02		/* assert RTS */
-#define TX_ENABLE 0x01		/* enable transmitter */
-
-#define RTSFC_EN  0x40		/* RTS flow control enable */
-#define RXPROC_EN 0x20		/* receive processor enable */
-#define TRIG_NO   0x00		/* Rx FIFO trigger level 0 (no trigger) */
-#define TRIG_1    0x08		/* trigger level 1 char */
-#define TRIG_1_2  0x10		/* trigger level 1/2 */
-#define TRIG_7_8  0x18		/* trigger level 7/8 */
-#define TRIG_MASK 0x18		/* trigger level mask */
-#define SRCINT_EN 0x04		/* special Rx condition interrupt enable */
-#define RXINT_EN  0x02		/* Rx interrupt enable */
-#define MCINT_EN  0x01		/* modem change interrupt enable */
-
-#define RXF_TRIG  0x20		/* Rx FIFO trigger level interrupt */
-#define TXFIFO_MT 0x10		/* Tx FIFO empty interrupt */
-#define SRC_INT   0x08		/* special receive condition interrupt */
-#define DELTA_CD  0x04		/* CD change interrupt */
-#define DELTA_CTS 0x02		/* CTS change interrupt */
-#define DELTA_DSR 0x01		/* DSR change interrupt */
-
-#define REP1W2_EN 0x10		/* replace byte 1 with 2 bytes enable */
-#define IGN2_EN   0x08		/* ignore byte 2 enable */
-#define IGN1_EN   0x04		/* ignore byte 1 enable */
-#define COMP2_EN  0x02		/* compare byte 2 enable */
-#define COMP1_EN  0x01		/* compare byte 1 enable */
-
-#define RESET_ALL 0x80		/* reset AIOP (all channels) */
-#define TXOVERIDE 0x40		/* Transmit software off override */
-#define RESETUART 0x20		/* reset channel's UART */
-#define RESTXFCNT 0x10		/* reset channel's Tx FIFO count register */
-#define RESRXFCNT 0x08		/* reset channel's Rx FIFO count register */
-
-#define INTSTAT0  0x01		/* AIOP 0 interrupt status */
-#define INTSTAT1  0x02		/* AIOP 1 interrupt status */
-#define INTSTAT2  0x04		/* AIOP 2 interrupt status */
-#define INTSTAT3  0x08		/* AIOP 3 interrupt status */
-
-#define INTR_EN   0x08		/* allow interrupts to host */
-#define INT_STROB 0x04		/* strobe and clear interrupt line (EOI) */
-
-/**************************************************************************
- MUDBAC remapped for PCI
-**************************************************************************/
-
-#define _CFG_INT_PCI  0x40
-#define _PCI_INT_FUNC 0x3A
-
-#define PCI_STROB 0x2000	/* bit 13 of int aiop register */
-#define INTR_EN_PCI   0x0010	/* allow interrupts to host */
-
-/*
- * Definitions for Universal PCI board registers
- */
-#define _PCI_9030_INT_CTRL	0x4c          /* Offsets from BAR1 */
-#define _PCI_9030_GPIO_CTRL	0x54
-#define PCI_INT_CTRL_AIOP	0x0001
-#define PCI_GPIO_CTRL_8PORT	0x4000
-#define _PCI_9030_RING_IND	0xc0          /* Offsets from BAR1 */
-
-#define CHAN3_EN  0x08		/* enable AIOP 3 */
-#define CHAN2_EN  0x04		/* enable AIOP 2 */
-#define CHAN1_EN  0x02		/* enable AIOP 1 */
-#define CHAN0_EN  0x01		/* enable AIOP 0 */
-#define FREQ_DIS  0x00
-#define FREQ_274HZ 0x60
-#define FREQ_137HZ 0x50
-#define FREQ_69HZ  0x40
-#define FREQ_34HZ  0x30
-#define FREQ_17HZ  0x20
-#define FREQ_9HZ   0x10
-#define PERIODIC_ONLY 0x80	/* only PERIODIC interrupt */
-
-#define CHANINT_EN 0x0100	/* flags to enable/disable channel ints */
-
-#define RDATASIZE 72
-#define RREGDATASIZE 52
-
-/*
- * AIOP interrupt bits for ISA/PCI boards and UPCI boards.
- */
-#define AIOP_INTR_BIT_0		0x0001
-#define AIOP_INTR_BIT_1		0x0002
-#define AIOP_INTR_BIT_2		0x0004
-#define AIOP_INTR_BIT_3		0x0008
-
-#define AIOP_INTR_BITS ( \
-	AIOP_INTR_BIT_0 \
-	| AIOP_INTR_BIT_1 \
-	| AIOP_INTR_BIT_2 \
-	| AIOP_INTR_BIT_3)
-
-#define UPCI_AIOP_INTR_BIT_0	0x0004
-#define UPCI_AIOP_INTR_BIT_1	0x0020
-#define UPCI_AIOP_INTR_BIT_2	0x0100
-#define UPCI_AIOP_INTR_BIT_3	0x0800
-
-#define UPCI_AIOP_INTR_BITS ( \
-	UPCI_AIOP_INTR_BIT_0 \
-	| UPCI_AIOP_INTR_BIT_1 \
-	| UPCI_AIOP_INTR_BIT_2 \
-	| UPCI_AIOP_INTR_BIT_3)
-
-/* Controller level information structure */
-typedef struct {
-	int CtlID;
-	int CtlNum;
-	int BusType;
-	int boardType;
-	int isUPCI;
-	WordIO_t PCIIO;
-	WordIO_t PCIIO2;
-	ByteIO_t MBaseIO;
-	ByteIO_t MReg1IO;
-	ByteIO_t MReg2IO;
-	ByteIO_t MReg3IO;
-	Byte_t MReg2;
-	Byte_t MReg3;
-	int NumAiop;
-	int AltChanRingIndicator;
-	ByteIO_t UPCIRingInd;
-	WordIO_t AiopIO[AIOP_CTL_SIZE];
-	ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE];
-	int AiopID[AIOP_CTL_SIZE];
-	int AiopNumChan[AIOP_CTL_SIZE];
-	Word_t *AiopIntrBits;
-} CONTROLLER_T;
-
-typedef CONTROLLER_T CONTROLLER_t;
-
-/* Channel level information structure */
-typedef struct {
-	CONTROLLER_T *CtlP;
-	int AiopNum;
-	int ChanID;
-	int ChanNum;
-	int rtsToggle;
-
-	ByteIO_t Cmd;
-	ByteIO_t IntChan;
-	ByteIO_t IntMask;
-	DWordIO_t IndexAddr;
-	WordIO_t IndexData;
-
-	WordIO_t TxRxData;
-	WordIO_t ChanStat;
-	WordIO_t TxRxCount;
-	ByteIO_t IntID;
-
-	Word_t TxFIFO;
-	Word_t TxFIFOPtrs;
-	Word_t RxFIFO;
-	Word_t RxFIFOPtrs;
-	Word_t TxPrioCnt;
-	Word_t TxPrioPtr;
-	Word_t TxPrioBuf;
-
-	Byte_t R[RREGDATASIZE];
-
-	Byte_t BaudDiv[4];
-	Byte_t TxControl[4];
-	Byte_t RxControl[4];
-	Byte_t TxEnables[4];
-	Byte_t TxCompare[4];
-	Byte_t TxReplace1[4];
-	Byte_t TxReplace2[4];
-} CHANNEL_T;
-
-typedef CHANNEL_T CHANNEL_t;
-typedef CHANNEL_T *CHANPTR_T;
-
-#define InterfaceModeRS232  0x00
-#define InterfaceModeRS422  0x08
-#define InterfaceModeRS485  0x10
-#define InterfaceModeRS232T 0x18
-
-/***************************************************************************
-Function: sClrBreak
-Purpose:  Stop sending a transmit BREAK signal
-Call:     sClrBreak(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrBreak(ChP) \
-do { \
-   (ChP)->TxControl[3] &= ~SETBREAK; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrDTR
-Purpose:  Clr the DTR output
-Call:     sClrDTR(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrDTR(ChP) \
-do { \
-   (ChP)->TxControl[3] &= ~SET_DTR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrRTS
-Purpose:  Clr the RTS output
-Call:     sClrRTS(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrRTS(ChP) \
-do { \
-   if ((ChP)->rtsToggle) break; \
-   (ChP)->TxControl[3] &= ~SET_RTS; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrTxXOFF
-Purpose:  Clear any existing transmit software flow control off condition
-Call:     sClrTxXOFF(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrTxXOFF(ChP) \
-do { \
-   sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \
-   sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \
-} while (0)
-
-/***************************************************************************
-Function: sCtlNumToCtlPtr
-Purpose:  Convert a controller number to controller structure pointer
-Call:     sCtlNumToCtlPtr(CtlNum)
-          int CtlNum; Controller number
-Return:   CONTROLLER_T *: Ptr to controller structure
-*/
-#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM]
-
-/***************************************************************************
-Function: sControllerEOI
-Purpose:  Strobe the MUDBAC's End Of Interrupt bit.
-Call:     sControllerEOI(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-*/
-#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB)
-
-/***************************************************************************
-Function: sPCIControllerEOI
-Purpose:  Strobe the PCI End Of Interrupt bit.
-          For the UPCI boards, toggle the AIOP interrupt enable bit
-	  (this was taken from the Windows driver).
-Call:     sPCIControllerEOI(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-*/
-#define sPCIControllerEOI(CTLP) \
-do { \
-    if ((CTLP)->isUPCI) { \
-	Word_t w = sInW((CTLP)->PCIIO); \
-	sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \
-	sOutW((CTLP)->PCIIO, w); \
-    } \
-    else { \
-	sOutW((CTLP)->PCIIO, PCI_STROB); \
-    } \
-} while (0)
-
-/***************************************************************************
-Function: sDisAiop
-Purpose:  Disable I/O access to an AIOP
-Call:     sDisAiop(CltP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; Number of AIOP on controller
-*/
-#define sDisAiop(CTLP,AIOPNUM) \
-do { \
-   (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \
-   sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-} while (0)
-
-/***************************************************************************
-Function: sDisCTSFlowCtl
-Purpose:  Disable output flow control using CTS
-Call:     sDisCTSFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisCTSFlowCtl(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~CTSFC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisIXANY
-Purpose:  Disable IXANY Software Flow Control
-Call:     sDisIXANY(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisIXANY(ChP) \
-do { \
-   (ChP)->R[0x0e] = 0x86; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
-} while (0)
-
-/***************************************************************************
-Function: DisParity
-Purpose:  Disable parity
-Call:     sDisParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-*/
-#define sDisParity(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~PARITY_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisRTSToggle
-Purpose:  Disable RTS toggle
-Call:     sDisRTSToggle(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisRTSToggle(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~RTSTOG_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-   (ChP)->rtsToggle = 0; \
-} while (0)
-
-/***************************************************************************
-Function: sDisRxFIFO
-Purpose:  Disable Rx FIFO
-Call:     sDisRxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisRxFIFO(ChP) \
-do { \
-   (ChP)->R[0x32] = 0x0a; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
-} while (0)
-
-/***************************************************************************
-Function: sDisRxStatusMode
-Purpose:  Disable the Rx status mode
-Call:     sDisRxStatusMode(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This takes the channel out of the receive status mode.  All
-          subsequent reads of receive data using sReadRxWord() will return
-          two data bytes.
-*/
-#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0)
-
-/***************************************************************************
-Function: sDisTransmit
-Purpose:  Disable transmit
-Call:     sDisTransmit(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-          This disables movement of Tx data from the Tx FIFO into the 1 byte
-          Tx buffer.  Therefore there could be up to a 2 byte latency
-          between the time sDisTransmit() is called and the transmit buffer
-          and transmit shift register going completely empty.
-*/
-#define sDisTransmit(ChP) \
-do { \
-   (ChP)->TxControl[3] &= ~TX_ENABLE; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisTxSoftFlowCtl
-Purpose:  Disable Tx Software Flow Control
-Call:     sDisTxSoftFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisTxSoftFlowCtl(ChP) \
-do { \
-   (ChP)->R[0x06] = 0x8a; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sEnAiop
-Purpose:  Enable I/O access to an AIOP
-Call:     sEnAiop(CltP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; Number of AIOP on controller
-*/
-#define sEnAiop(CTLP,AIOPNUM) \
-do { \
-   (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \
-   sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-} while (0)
-
-/***************************************************************************
-Function: sEnCTSFlowCtl
-Purpose:  Enable output flow control using CTS
-Call:     sEnCTSFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnCTSFlowCtl(ChP) \
-do { \
-   (ChP)->TxControl[2] |= CTSFC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnIXANY
-Purpose:  Enable IXANY Software Flow Control
-Call:     sEnIXANY(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnIXANY(ChP) \
-do { \
-   (ChP)->R[0x0e] = 0x21; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
-} while (0)
-
-/***************************************************************************
-Function: EnParity
-Purpose:  Enable parity
-Call:     sEnParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: Before enabling parity odd or even parity should be chosen using
-          functions sSetOddParity() or sSetEvenParity().
-*/
-#define sEnParity(ChP) \
-do { \
-   (ChP)->TxControl[2] |= PARITY_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRTSToggle
-Purpose:  Enable RTS toggle
-Call:     sEnRTSToggle(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function will disable RTS flow control and clear the RTS
-          line to allow operation of RTS toggle.
-*/
-#define sEnRTSToggle(ChP) \
-do { \
-   (ChP)->RxControl[2] &= ~RTSFC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->RxControl); \
-   (ChP)->TxControl[2] |= RTSTOG_EN; \
-   (ChP)->TxControl[3] &= ~SET_RTS; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-   (ChP)->rtsToggle = 1; \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxFIFO
-Purpose:  Enable Rx FIFO
-Call:     sEnRxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnRxFIFO(ChP) \
-do { \
-   (ChP)->R[0x32] = 0x08; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxProcessor
-Purpose:  Enable the receive processor
-Call:     sEnRxProcessor(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function is used to start the receive processor.  When
-          the channel is in the reset state the receive processor is not
-          running.  This is done to prevent the receive processor from
-          executing invalid microcode instructions prior to the
-          downloading of the microcode.
-
-Warnings: This function must be called after valid microcode has been
-          downloaded to the AIOP, and it must not be called before the
-          microcode has been downloaded.
-*/
-#define sEnRxProcessor(ChP) \
-do { \
-   (ChP)->RxControl[2] |= RXPROC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->RxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxStatusMode
-Purpose:  Enable the Rx status mode
-Call:     sEnRxStatusMode(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This places the channel in the receive status mode.  All subsequent
-          reads of receive data using sReadRxWord() will return a data byte
-          in the low word and a status byte in the high word.
-
-*/
-#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE)
-
-/***************************************************************************
-Function: sEnTransmit
-Purpose:  Enable transmit
-Call:     sEnTransmit(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnTransmit(ChP) \
-do { \
-   (ChP)->TxControl[3] |= TX_ENABLE; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnTxSoftFlowCtl
-Purpose:  Enable Tx Software Flow Control
-Call:     sEnTxSoftFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnTxSoftFlowCtl(ChP) \
-do { \
-   (ChP)->R[0x06] = 0xc5; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sGetAiopIntStatus
-Purpose:  Get the AIOP interrupt status
-Call:     sGetAiopIntStatus(CtlP,AiopNum)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; AIOP number
-Return:   Byte_t: The AIOP interrupt status.  Bits 0 through 7
-                         represent channels 0 through 7 respectively.  If a
-                         bit is set that channel is interrupting.
-*/
-#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM])
-
-/***************************************************************************
-Function: sGetAiopNumChan
-Purpose:  Get the number of channels supported by an AIOP
-Call:     sGetAiopNumChan(CtlP,AiopNum)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; AIOP number
-Return:   int: The number of channels supported by the AIOP
-*/
-#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM]
-
-/***************************************************************************
-Function: sGetChanIntID
-Purpose:  Get a channel's interrupt identification byte
-Call:     sGetChanIntID(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Byte_t: The channel interrupt ID.  Can be any
-             combination of the following flags:
-                RXF_TRIG:     Rx FIFO trigger level interrupt
-                TXFIFO_MT:    Tx FIFO empty interrupt
-                SRC_INT:      Special receive condition interrupt
-                DELTA_CD:     CD change interrupt
-                DELTA_CTS:    CTS change interrupt
-                DELTA_DSR:    DSR change interrupt
-*/
-#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR))
-
-/***************************************************************************
-Function: sGetChanNum
-Purpose:  Get the number of a channel within an AIOP
-Call:     sGetChanNum(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   int: Channel number within AIOP, or NULLCHAN if channel does
-               not exist.
-*/
-#define sGetChanNum(ChP) (ChP)->ChanNum
-
-/***************************************************************************
-Function: sGetChanStatus
-Purpose:  Get the channel status
-Call:     sGetChanStatus(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Word_t: The channel status.  Can be any combination of
-             the following flags:
-                LOW BYTE FLAGS
-                CTS_ACT:      CTS input asserted
-                DSR_ACT:      DSR input asserted
-                CD_ACT:       CD input asserted
-                TXFIFOMT:     Tx FIFO is empty
-                TXSHRMT:      Tx shift register is empty
-                RDA:          Rx data available
-
-                HIGH BYTE FLAGS
-                STATMODE:     status mode enable bit
-                RXFOVERFL:    receive FIFO overflow
-                RX2MATCH:     receive compare byte 2 match
-                RX1MATCH:     receive compare byte 1 match
-                RXBREAK:      received BREAK
-                RXFRAME:      received framing error
-                RXPARITY:     received parity error
-Warnings: This function will clear the high byte flags in the Channel
-          Status Register.
-*/
-#define sGetChanStatus(ChP) sInW((ChP)->ChanStat)
-
-/***************************************************************************
-Function: sGetChanStatusLo
-Purpose:  Get the low byte only of the channel status
-Call:     sGetChanStatusLo(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Byte_t: The channel status low byte.  Can be any combination
-             of the following flags:
-                CTS_ACT:      CTS input asserted
-                DSR_ACT:      DSR input asserted
-                CD_ACT:       CD input asserted
-                TXFIFOMT:     Tx FIFO is empty
-                TXSHRMT:      Tx shift register is empty
-                RDA:          Rx data available
-*/
-#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat)
-
-/**********************************************************************
- * Get RI status of channel
- * Defined as a function in rocket.c   -aes
- */
-#if 0
-#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \
-                          (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \
-                            (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \
-                               (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \
-                             0))
-#endif
-
-/***************************************************************************
-Function: sGetControllerIntStatus
-Purpose:  Get the controller interrupt status
-Call:     sGetControllerIntStatus(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-Return:   Byte_t: The controller interrupt status in the lower 4
-                         bits.  Bits 0 through 3 represent AIOP's 0
-                         through 3 respectively.  If a bit is set that
-                         AIOP is interrupting.  Bits 4 through 7 will
-                         always be cleared.
-*/
-#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f)
-
-/***************************************************************************
-Function: sPCIGetControllerIntStatus
-Purpose:  Get the controller interrupt status
-Call:     sPCIGetControllerIntStatus(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-Return:   unsigned char: The controller interrupt status in the lower 4
-                         bits and bit 4.  Bits 0 through 3 represent AIOP's 0
-                         through 3 respectively. Bit 4 is set if the int 
-			 was generated from periodic. If a bit is set the
-			 AIOP is interrupting.
-*/
-#define sPCIGetControllerIntStatus(CTLP) \
-	((CTLP)->isUPCI ? \
-	  (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \
-	  ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS))
-
-/***************************************************************************
-
-Function: sGetRxCnt
-Purpose:  Get the number of data bytes in the Rx FIFO
-Call:     sGetRxCnt(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   int: The number of data bytes in the Rx FIFO.
-Comments: Byte read of count register is required to obtain Rx count.
-
-*/
-#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount)
-
-/***************************************************************************
-Function: sGetTxCnt
-Purpose:  Get the number of data bytes in the Tx FIFO
-Call:     sGetTxCnt(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Byte_t: The number of data bytes in the Tx FIFO.
-Comments: Byte read of count register is required to obtain Tx count.
-
-*/
-#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount)
-
-/*****************************************************************************
-Function: sGetTxRxDataIO
-Purpose:  Get the I/O address of a channel's TxRx Data register
-Call:     sGetTxRxDataIO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   WordIO_t: I/O address of a channel's TxRx Data register
-*/
-#define sGetTxRxDataIO(ChP) (ChP)->TxRxData
-
-/***************************************************************************
-Function: sInitChanDefaults
-Purpose:  Initialize a channel structure to it's default state.
-Call:     sInitChanDefaults(ChP)
-          CHANNEL_T *ChP; Ptr to the channel structure
-Comments: This function must be called once for every channel structure
-          that exists before any other SSCI calls can be made.
-
-*/
-#define sInitChanDefaults(ChP) \
-do { \
-   (ChP)->CtlP = NULLCTLPTR; \
-   (ChP)->AiopNum = NULLAIOP; \
-   (ChP)->ChanID = AIOPID_NULL; \
-   (ChP)->ChanNum = NULLCHAN; \
-} while (0)
-
-/***************************************************************************
-Function: sResetAiopByNum
-Purpose:  Reset the AIOP by number
-Call:     sResetAiopByNum(CTLP,AIOPNUM)
-	CONTROLLER_T CTLP; Ptr to controller structure
-	AIOPNUM; AIOP index 
-*/
-#define sResetAiopByNum(CTLP,AIOPNUM) \
-do { \
-   sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \
-   sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \
-} while (0)
-
-/***************************************************************************
-Function: sSendBreak
-Purpose:  Send a transmit BREAK signal
-Call:     sSendBreak(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSendBreak(ChP) \
-do { \
-   (ChP)->TxControl[3] |= SETBREAK; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetBaud
-Purpose:  Set baud rate
-Call:     sSetBaud(ChP,Divisor)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Word_t Divisor; 16 bit baud rate divisor for channel
-*/
-#define sSetBaud(ChP,DIVISOR) \
-do { \
-   (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \
-   (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \
-   out32((ChP)->IndexAddr,(ChP)->BaudDiv); \
-} while (0)
-
-/***************************************************************************
-Function: sSetData7
-Purpose:  Set data bits to 7
-Call:     sSetData7(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetData7(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~DATA8BIT; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetData8
-Purpose:  Set data bits to 8
-Call:     sSetData8(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetData8(ChP) \
-do { \
-   (ChP)->TxControl[2] |= DATA8BIT; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetDTR
-Purpose:  Set the DTR output
-Call:     sSetDTR(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetDTR(ChP) \
-do { \
-   (ChP)->TxControl[3] |= SET_DTR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetEvenParity
-Purpose:  Set even parity
-Call:     sSetEvenParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: This function has no effect unless parity is enabled with function
-          sEnParity().
-*/
-#define sSetEvenParity(ChP) \
-do { \
-   (ChP)->TxControl[2] |= EVEN_PAR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetOddParity
-Purpose:  Set odd parity
-Call:     sSetOddParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: This function has no effect unless parity is enabled with function
-          sEnParity().
-*/
-#define sSetOddParity(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~EVEN_PAR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetRTS
-Purpose:  Set the RTS output
-Call:     sSetRTS(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetRTS(ChP) \
-do { \
-   if ((ChP)->rtsToggle) break; \
-   (ChP)->TxControl[3] |= SET_RTS; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetRxTrigger
-Purpose:  Set the Rx FIFO trigger level
-Call:     sSetRxProcessor(ChP,Level)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Level; Number of characters in Rx FIFO at which the
-             interrupt will be generated.  Can be any of the following flags:
-
-             TRIG_NO:   no trigger
-             TRIG_1:    1 character in FIFO
-             TRIG_1_2:  FIFO 1/2 full
-             TRIG_7_8:  FIFO 7/8 full
-Comments: An interrupt will be generated when the trigger level is reached
-          only if function sEnInterrupt() has been called with flag
-          RXINT_EN set.  The RXF_TRIG flag in the Interrupt Idenfification
-          register will be set whenever the trigger level is reached
-          regardless of the setting of RXINT_EN.
-
-*/
-#define sSetRxTrigger(ChP,LEVEL) \
-do { \
-   (ChP)->RxControl[2] &= ~TRIG_MASK; \
-   (ChP)->RxControl[2] |= LEVEL; \
-   out32((ChP)->IndexAddr,(ChP)->RxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetStop1
-Purpose:  Set stop bits to 1
-Call:     sSetStop1(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetStop1(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~STOP2; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetStop2
-Purpose:  Set stop bits to 2
-Call:     sSetStop2(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetStop2(ChP) \
-do { \
-   (ChP)->TxControl[2] |= STOP2; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetTxXOFFChar
-Purpose:  Set the Tx XOFF flow control character
-Call:     sSetTxXOFFChar(ChP,Ch)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Ch; The value to set the Tx XOFF character to
-*/
-#define sSetTxXOFFChar(ChP,CH) \
-do { \
-   (ChP)->R[0x07] = (CH); \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sSetTxXONChar
-Purpose:  Set the Tx XON flow control character
-Call:     sSetTxXONChar(ChP,Ch)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Ch; The value to set the Tx XON character to
-*/
-#define sSetTxXONChar(ChP,CH) \
-do { \
-   (ChP)->R[0x0b] = (CH); \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \
-} while (0)
-
-/***************************************************************************
-Function: sStartRxProcessor
-Purpose:  Start a channel's receive processor
-Call:     sStartRxProcessor(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function is used to start a Rx processor after it was
-          stopped with sStopRxProcessor() or sStopSWInFlowCtl().  It
-          will restart both the Rx processor and software input flow control.
-
-*/
-#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0])
-
-/***************************************************************************
-Function: sWriteTxByte
-Purpose:  Write a transmit data byte to a channel.
-          ByteIO_t io: Channel transmit register I/O address.  This can
-                           be obtained with sGetTxRxDataIO().
-          Byte_t Data; The transmit data byte.
-Warnings: This function writes the data byte without checking to see if
-          sMaxTxSize is exceeded in the Tx FIFO.
-*/
-#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
-
-/*
- * Begin Linux specific definitions for the Rocketport driver
- *
- * This code is Copyright Theodore Ts'o, 1995-1997
- */
-
-struct r_port {
-	int magic;
-	struct tty_port port;
-	int line;
-	int flags;		/* Don't yet match the ASY_ flags!! */
-	unsigned int board:3;
-	unsigned int aiop:2;
-	unsigned int chan:3;
-	CONTROLLER_t *ctlp;
-	CHANNEL_t channel;
-	int intmask;
-	int xmit_fifo_room;	/* room in xmit fifo */
-	unsigned char *xmit_buf;
-	int xmit_head;
-	int xmit_tail;
-	int xmit_cnt;
-	int cd_status;
-	int ignore_status_mask;
-	int read_status_mask;
-	int cps;
-
-	struct completion close_wait;	/* Not yet matching the core */
-	spinlock_t slock;
-	struct mutex write_mtx;
-};
-
-#define RPORT_MAGIC 0x525001
-
-#define NUM_BOARDS 8
-#define MAX_RP_PORTS (32*NUM_BOARDS)
-
-/*
- * The size of the xmit buffer is 1 page, or 4096 bytes
- */
-#define XMIT_BUF_SIZE 4096
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/*
- * Assigned major numbers for the Comtrol Rocketport
- */
-#define TTY_ROCKET_MAJOR	46
-#define CUA_ROCKET_MAJOR	47
-
-#ifdef PCI_VENDOR_ID_RP
-#undef PCI_VENDOR_ID_RP
-#undef PCI_DEVICE_ID_RP8OCTA
-#undef PCI_DEVICE_ID_RP8INTF
-#undef PCI_DEVICE_ID_RP16INTF
-#undef PCI_DEVICE_ID_RP32INTF
-#undef PCI_DEVICE_ID_URP8OCTA
-#undef PCI_DEVICE_ID_URP8INTF
-#undef PCI_DEVICE_ID_URP16INTF
-#undef PCI_DEVICE_ID_CRP16INTF
-#undef PCI_DEVICE_ID_URP32INTF
-#endif
-
-/*  Comtrol PCI Vendor ID */
-#define PCI_VENDOR_ID_RP		0x11fe
-
-/*  Comtrol Device ID's */
-#define PCI_DEVICE_ID_RP32INTF		0x0001	/* Rocketport 32 port w/external I/F     */
-#define PCI_DEVICE_ID_RP8INTF		0x0002	/* Rocketport 8 port w/external I/F      */
-#define PCI_DEVICE_ID_RP16INTF		0x0003	/* Rocketport 16 port w/external I/F     */
-#define PCI_DEVICE_ID_RP4QUAD		0x0004	/* Rocketport 4 port w/quad cable        */
-#define PCI_DEVICE_ID_RP8OCTA		0x0005	/* Rocketport 8 port w/octa cable        */
-#define PCI_DEVICE_ID_RP8J		0x0006	/* Rocketport 8 port w/RJ11 connectors   */
-#define PCI_DEVICE_ID_RP4J		0x0007	/* Rocketport 4 port w/RJ11 connectors   */
-#define PCI_DEVICE_ID_RP8SNI		0x0008	/* Rocketport 8 port w/ DB78 SNI (Siemens) connector */
-#define PCI_DEVICE_ID_RP16SNI		0x0009	/* Rocketport 16 port w/ DB78 SNI (Siemens) connector   */
-#define PCI_DEVICE_ID_RPP4		0x000A	/* Rocketport Plus 4 port                */
-#define PCI_DEVICE_ID_RPP8		0x000B	/* Rocketport Plus 8 port                */
-#define PCI_DEVICE_ID_RP6M		0x000C	/* RocketModem 6 port                    */
-#define PCI_DEVICE_ID_RP4M		0x000D	/* RocketModem 4 port                    */
-#define PCI_DEVICE_ID_RP2_232           0x000E	/* Rocketport Plus 2 port RS232          */
-#define PCI_DEVICE_ID_RP2_422           0x000F	/* Rocketport Plus 2 port RS422          */ 
-
-/* Universal PCI boards  */
-#define PCI_DEVICE_ID_URP32INTF		0x0801	/* Rocketport UPCI 32 port w/external I/F */ 
-#define PCI_DEVICE_ID_URP8INTF		0x0802	/* Rocketport UPCI 8 port w/external I/F  */
-#define PCI_DEVICE_ID_URP16INTF		0x0803	/* Rocketport UPCI 16 port w/external I/F */
-#define PCI_DEVICE_ID_URP8OCTA		0x0805	/* Rocketport UPCI 8 port w/octa cable    */
-#define PCI_DEVICE_ID_UPCI_RM3_8PORT    0x080C	/* Rocketmodem III 8 port                 */
-#define PCI_DEVICE_ID_UPCI_RM3_4PORT    0x080D	/* Rocketmodem III 4 port                 */
-
-/* Compact PCI device */ 
-#define PCI_DEVICE_ID_CRP16INTF		0x0903	/* Rocketport Compact PCI 16 port w/external I/F */
-
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
deleted file mode 100644
index 9610861..0000000
--- a/drivers/char/ser_a2232.c
+++ /dev/null
@@ -1,831 +0,0 @@
-/* drivers/char/ser_a2232.c */
-
-/* $Id: ser_a2232.c,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/* Linux serial driver for the Amiga A2232 board */
-
-/* This driver is MAINTAINED. Before applying any changes, please contact
- * the author.
- */
-
-/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
- *                   alias The A2232 driver project <A2232@gmx.net>
- * All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/***************************** Documentation ************************/
-/*
- * This driver is in EXPERIMENTAL state. That means I could not find
- * someone with five A2232 boards with 35 ports running at 19200 bps
- * at the same time and test the machine's behaviour.
- * However, I know that you can performance-tweak this driver (see
- * the source code).
- * One thing to consider is the time this driver consumes during the
- * Amiga's vertical blank interrupt. Everything that is to be done
- * _IS DONE_ when entering the vertical blank interrupt handler of
- * this driver.
- * However, it would be more sane to only do the job for only ONE card
- * instead of ALL cards at a time; or, more generally, to handle only
- * SOME ports instead of ALL ports at a time.
- * However, as long as no-one runs into problems I guess I shouldn't
- * change the driver as it runs fine for me :) .
- *
- * Version history of this file:
- * 0.4	Resolved licensing issues.
- * 0.3	Inclusion in the Linux/m68k tree, small fixes.
- * 0.2	Added documentation, minor typo fixes.
- * 0.1	Initial release.
- *
- * TO DO:
- * -	Handle incoming BREAK events. I guess "Stevens: Advanced
- *	Programming in the UNIX(R) Environment" is a good reference
- *	on what is to be done.
- * -	When installing as a module, don't simply 'printk' text, but
- *	send it to the TTY used by the user.
- *
- * THANKS TO:
- * -	Jukka Marin (65EC02 code).
- * -	The other NetBSD developers on whose A2232 driver I had a
- *	pretty close look. However, I didn't copy any code so it
- *	is okay to put my code under the GPL and include it into
- *	Linux.
- */
-/***************************** End of Documentation *****************/
-
-/***************************** Defines ******************************/
-/*
- * Enables experimental 115200 (normal) 230400 (turbo) baud rate.
- * The A2232 specification states it can only operate at speeds up to
- * 19200 bits per second, and I was not able to send a file via
- * "sz"/"rz" and a null-modem cable from one A2232 port to another
- * at 115200 bits per second.
- * However, this might work for you.
- */
-#undef A2232_SPEEDHACK
-/*
- * Default is not to use RTS/CTS so you could be talked to death.
- */
-#define A2232_SUPPRESS_RTSCTS_WARNING
-/************************* End of Defines ***************************/
-
-/***************************** Includes *****************************/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-
-#include <asm/setup.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <linux/mutex.h>
-
-#include <linux/delay.h>
-
-#include <linux/serial.h>
-#include <linux/generic_serial.h>
-#include <linux/tty_flip.h>
-
-#include "ser_a2232.h"
-#include "ser_a2232fw.h"
-/************************* End of Includes **************************/
-
-/***************************** Prototypes ***************************/
-/* The interrupt service routine */
-static irqreturn_t a2232_vbl_inter(int irq, void *data);
-/* Initialize the port structures */
-static void a2232_init_portstructs(void);
-/* Initialize and register TTY drivers. */
-/* returns 0 IFF successful */
-static int a2232_init_drivers(void); 
-
-/* BEGIN GENERIC_SERIAL PROTOTYPES */
-static void a2232_disable_tx_interrupts(void *ptr);
-static void a2232_enable_tx_interrupts(void *ptr);
-static void a2232_disable_rx_interrupts(void *ptr);
-static void a2232_enable_rx_interrupts(void *ptr);
-static int  a2232_carrier_raised(struct tty_port *port);
-static void a2232_shutdown_port(void *ptr);
-static int  a2232_set_real_termios(void *ptr);
-static int  a2232_chars_in_buffer(void *ptr);
-static void a2232_close(void *ptr);
-static void a2232_hungup(void *ptr);
-/* static void a2232_getserial (void *ptr, struct serial_struct *sp); */
-/* END GENERIC_SERIAL PROTOTYPES */
-
-/* Functions that the TTY driver struct expects */
-static int  a2232_ioctl(struct tty_struct *tty, struct file *file,
-										unsigned int cmd, unsigned long arg);
-static void a2232_throttle(struct tty_struct *tty);
-static void a2232_unthrottle(struct tty_struct *tty);
-static int  a2232_open(struct tty_struct * tty, struct file * filp);
-/************************* End of Prototypes ************************/
-
-/***************************** Global variables *********************/
-/*---------------------------------------------------------------------------
- * Interface from generic_serial.c back here
- *--------------------------------------------------------------------------*/
-static struct real_driver a2232_real_driver = {
-        a2232_disable_tx_interrupts,
-        a2232_enable_tx_interrupts,
-        a2232_disable_rx_interrupts,
-        a2232_enable_rx_interrupts,
-        a2232_shutdown_port,
-        a2232_set_real_termios,
-        a2232_chars_in_buffer,
-        a2232_close,
-        a2232_hungup,
-	NULL	/* a2232_getserial */
-};
-
-static void *a2232_driver_ID = &a2232_driver_ID; // Some memory address WE own.
-
-/* Ports structs */
-static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES];
-
-/* TTY driver structs */
-static struct tty_driver *a2232_driver;
-
-/* nr of cards completely (all ports) and correctly configured */
-static int nr_a2232; 
-
-/* zorro_dev structs for the A2232's */
-static struct zorro_dev *zd_a2232[MAX_A2232_BOARDS]; 
-/***************************** End of Global variables **************/
-
-/* Helper functions */
-
-static inline volatile struct a2232memory *a2232mem(unsigned int board)
-{
-	return (volatile struct a2232memory *)ZTWO_VADDR(zd_a2232[board]->resource.start);
-}
-
-static inline volatile struct a2232status *a2232stat(unsigned int board,
-						     unsigned int portonboard)
-{
-	volatile struct a2232memory *mem = a2232mem(board);
-	return &(mem->Status[portonboard]);
-}
-
-static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
-{
-/* 	Mostly stolen from other drivers.
-	Maybe one could implement a more efficient version by not only
-	transferring one character at a time.
-*/
-	struct tty_struct *tty = port->gs.port.tty;
-
-#if 0
-	switch(err) {
-	case TTY_BREAK:
-		break;
-	case TTY_PARITY:
-		break;
-	case TTY_OVERRUN:
-		break;
-	case TTY_FRAME:
-		break;
-	}
-#endif
-
-	tty_insert_flip_char(tty, ch, err);
-	tty_flip_buffer_push(tty);
-}
-
-/***************************** Functions ****************************/
-/*** BEGIN OF REAL_DRIVER FUNCTIONS ***/
-
-static void a2232_disable_tx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-  
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	stat->OutDisable = -1;
-
-	/* Does this here really have to be? */
-	local_irq_save(flags);
-	port->gs.port.flags &= ~GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-static void a2232_enable_tx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	stat->OutDisable = 0;
-
-	/* Does this here really have to be? */
-	local_irq_save(flags);
-	port->gs.port.flags |= GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-static void a2232_disable_rx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	port = ptr;
-	port->disable_rx = -1;
-}
-
-static void a2232_enable_rx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	port = ptr;
-	port->disable_rx = 0;
-}
-
-static int  a2232_carrier_raised(struct tty_port *port)
-{
-	struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
-	return ap->cd_status;
-}
-
-static void a2232_shutdown_port(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-
-	local_irq_save(flags);
-
-	port->gs.port.flags &= ~GS_ACTIVE;
-	
-	if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
-		/* Set DTR and RTS to Low, flush output.
-		   The NetBSD driver "msc.c" does it this way. */
-		stat->Command = (	(stat->Command & ~A2232CMD_CMask) | 
-					A2232CMD_Close );
-		stat->OutFlush = -1;
-		stat->Setup = -1;
-	}
-
-	local_irq_restore(flags);
-	
-	/* After analyzing control flow, I think a2232_shutdown_port
-		is actually the last call from the system when at application
-		level someone issues a "echo Hello >>/dev/ttyY0".
-		Therefore I think the MOD_DEC_USE_COUNT should be here and
-		not in "a2232_close()". See the comment in "sx.c", too.
-		If you run into problems, compile this driver into the
-		kernel instead of compiling it as a module. */
-}
-
-static int  a2232_set_real_termios(void *ptr)
-{
-	unsigned int cflag, baud, chsize, stopb, parity, softflow;
-	int rate;
-	int a2232_param, a2232_cmd;
-	unsigned long flags;
-	unsigned int i;
-	struct a2232_port *port = ptr;
-	volatile struct a2232status *status;
-	volatile struct a2232memory *mem;
-
-	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
-
-	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	mem = a2232mem(port->which_a2232);
-	
-	a2232_param = a2232_cmd = 0;
-
-	// get baud rate
-	baud = port->gs.baud;
-	if (baud == 0) {
-		/* speed == 0 -> drop DTR, do nothing else */
-		local_irq_save(flags);
-		// Clear DTR (and RTS... mhhh).
-		status->Command = (	(status->Command & ~A2232CMD_CMask) |
-					A2232CMD_Close );
-		status->OutFlush = -1;
-		status->Setup = -1;
-		
-		local_irq_restore(flags);
-		return 0;
-	}
-	
-	rate = A2232_BAUD_TABLE_NOAVAIL;
-	for (i=0; i < A2232_BAUD_TABLE_NUM_RATES * 3; i += 3){
-		if (a2232_baud_table[i] == baud){
-			if (mem->Common.Crystal == A2232_TURBO) rate = a2232_baud_table[i+2];
-			else                                    rate = a2232_baud_table[i+1];
-		}
-	}
-	if (rate == A2232_BAUD_TABLE_NOAVAIL){
-		printk("a2232: Board %d Port %d unsupported baud rate: %d baud. Using another.\n",port->which_a2232,port->which_port_on_a2232,baud);
-		// This is useful for both (turbo or normal) Crystal versions.
-		rate = A2232PARAM_B9600;
-	}
-	a2232_param |= rate;
-
-	cflag  = port->gs.port.tty->termios->c_cflag;
-
-	// get character size
-	chsize = cflag & CSIZE;
-	switch (chsize){
-		case CS8: 	a2232_param |= A2232PARAM_8Bit; break;
-		case CS7: 	a2232_param |= A2232PARAM_7Bit; break;
-		case CS6: 	a2232_param |= A2232PARAM_6Bit; break;
-		case CS5: 	a2232_param |= A2232PARAM_5Bit; break;
-		default:	printk("a2232: Board %d Port %d unsupported character size: %d. Using 8 data bits.\n",
-					port->which_a2232,port->which_port_on_a2232,chsize);
-				a2232_param |= A2232PARAM_8Bit; break;
-	}
-
-	// get number of stop bits
-	stopb  = cflag & CSTOPB;
-	if (stopb){ // two stop bits instead of one
-		printk("a2232: Board %d Port %d 2 stop bits unsupported. Using 1 stop bit.\n",
-			port->which_a2232,port->which_port_on_a2232);
-	}
-
-	// Warn if RTS/CTS not wanted
-	if (!(cflag & CRTSCTS)){
-#ifndef A2232_SUPPRESS_RTSCTS_WARNING
-		printk("a2232: Board %d Port %d cannot switch off firmware-implemented RTS/CTS hardware flow control.\n",
-			port->which_a2232,port->which_port_on_a2232);
-#endif
-	}
-
-	/*	I think this is correct.
-		However, IXOFF means _input_ flow control and I wonder
-		if one should care about IXON _output_ flow control,
-		too. If this makes problems, one should turn the A2232
-		firmware XON/XOFF "SoftFlow" flow control off and use
-		the conventional way of inserting START/STOP characters
-		by hand in throttle()/unthrottle().
-	*/
-	softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF );
-
-	// get Parity (Enabled/Disabled? If Enabled, Odd or Even?)
-	parity = cflag & (PARENB | PARODD);
-	if (parity & PARENB){
-		if (parity & PARODD){
-			a2232_cmd |= A2232CMD_OddParity;
-		}
-		else{
-			a2232_cmd |= A2232CMD_EvenParity;
-		}
-	}
-	else a2232_cmd |= A2232CMD_NoParity;
-
-
-	/*	Hmm. Maybe an own a2232_port structure
-		member would be cleaner?	*/
-	if (cflag & CLOCAL)
-		port->gs.port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->gs.port.flags |= ASYNC_CHECK_CD;
-
-
-	/* Now we have all parameters and can go to set them: */
-	local_irq_save(flags);
-
-	status->Param = a2232_param | A2232PARAM_RcvBaud;
-	status->Command = a2232_cmd | A2232CMD_Open |  A2232CMD_Enable;
-	status->SoftFlow = softflow;
-	status->OutDisable = 0;
-	status->Setup = -1;
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int  a2232_chars_in_buffer(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *status; 
-	unsigned char ret; /* we need modulo-256 arithmetics */
-	port = ptr;
-	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
-#if A2232_IOBUFLEN != 256
-#error "Re-Implement a2232_chars_in_buffer()!"
-#endif
-	ret = (status->OutHead - status->OutTail);
-	return ret;
-}
-
-static void a2232_close(void *ptr)
-{
-	a2232_disable_tx_interrupts(ptr);
-	a2232_disable_rx_interrupts(ptr);
-	/* see the comment in a2232_shutdown_port above. */
-}
-
-static void a2232_hungup(void *ptr)
-{
-	a2232_close(ptr);
-}
-/*** END   OF REAL_DRIVER FUNCTIONS ***/
-
-/*** BEGIN  FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
-static int a2232_ioctl(	struct tty_struct *tty, struct file *file,
-			unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-static void a2232_throttle(struct tty_struct *tty)
-{
-/* Throttle: System cannot take another chars: Drop RTS or
-             send the STOP char or whatever.
-   The A2232 firmware does RTS/CTS anyway, and XON/XOFF
-   if switched on. So the only thing we can do at this
-   layer here is not taking any characters out of the
-   A2232 buffer any more. */
-	struct a2232_port *port = tty->driver_data;
-	port->throttle_input = -1;
-}
-
-static void a2232_unthrottle(struct tty_struct *tty)
-{
-/* Unthrottle: dual to "throttle()" above. */
-	struct a2232_port *port = tty->driver_data;
-	port->throttle_input = 0;
-}
-
-static int  a2232_open(struct tty_struct * tty, struct file * filp)
-{
-/* More or less stolen from other drivers. */
-	int line;
-	int retval;
-	struct a2232_port *port;
-
-	line = tty->index;
-	port = &a2232_ports[line];
-	
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	retval = gs_init_port(&port->gs);
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-	port->gs.port.flags |= GS_ACTIVE;
-	retval = gs_block_til_ready(port, filp);
-
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	a2232_enable_rx_interrupts(port);
-	
-	return 0;
-}
-/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
-
-static irqreturn_t a2232_vbl_inter(int irq, void *data)
-{
-#if A2232_IOBUFLEN != 256
-#error "Re-Implement a2232_vbl_inter()!"
-#endif
-
-struct a2232_port *port;
-volatile struct a2232memory *mem;
-volatile struct a2232status *status;
-unsigned char newhead;
-unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */
-unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */
-volatile u_char *ibuf, *cbuf, *obuf;
-int ch, err, n, p;
-	for (n = 0; n < nr_a2232; n++){		/* for every completely initialized A2232 board */
-		mem = a2232mem(n);
-		for (p = 0; p < NUMLINES; p++){	/* for every port on this board */
-			err = 0;
-			port = &a2232_ports[n*NUMLINES+p];
-			if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */
-
-				status = a2232stat(n,p);
-
-				if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */
-					newhead = status->InHead;               /* 65EC02 write pointer */
-					bufpos = status->InTail;
-
-					/* check for input for this port */
-					if (newhead != bufpos) {
-						/* buffer for input chars/events */
-						ibuf = mem->InBuf[p];
- 
-						/* data types of bytes in ibuf */
-						cbuf = mem->InCtl[p];
- 
-						/* do for all chars */
-						while (bufpos != newhead) {
-							/* which type of input data? */
-							switch (cbuf[bufpos]) {
-								/* switch on input event (CD, BREAK, etc.) */
-							case A2232INCTL_EVENT:
-								switch (ibuf[bufpos++]) {
-								case A2232EVENT_Break:
-									/* TODO: Handle BREAK signal */
-									break;
-									/*	A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are
-										handled in a separate queue and should not occur here. */
-								case A2232EVENT_Sync:
-									printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring.");
-									break;
-								default:
-									printk("A2232: 65EC02 software broken, unknown event type %d occurred.\n",ibuf[bufpos-1]);
-								} /* event type switch */
-								break;
- 							case A2232INCTL_CHAR:
-								/* Receive incoming char */
-								a2232_receive_char(port, ibuf[bufpos], err);
-								bufpos++;
-								break;
- 							default:
-								printk("A2232: 65EC02 software broken, unknown data type %d occurred.\n",cbuf[bufpos]);
-								bufpos++;
-							} /* switch on input data type */
-						} /* while there's something in the buffer */
-
-						status->InTail = bufpos;            /* tell 65EC02 what we've read */
-						
-					} /* if there was something in the buffer */                          
-				} /* If input is not disabled */
-
-				/* Now check if there's something to output */
-				obuf = mem->OutBuf[p];
-				bufpos = status->OutHead;
-				while ( (port->gs.xmit_cnt > 0)		&&
-					(!port->gs.port.tty->stopped)	&&
-					(!port->gs.port.tty->hw_stopped) ){	/* While there are chars to transmit */
-					if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */
-						ch = port->gs.xmit_buf[port->gs.xmit_tail];					/* get the next char to transmit */
-						port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */
-						obuf[bufpos++] = ch;																/* put it into the A2232 buffer */
-						port->gs.xmit_cnt--;
-					}
-					else{																									/* If A2232 the buffer is full */
-						break;																							/* simply stop filling it. */
-					}													
-				}					
-				status->OutHead = bufpos;
-					
-				/* WakeUp if output buffer runs low */
-				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
-					tty_wakeup(port->gs.port.tty);
-				}
-			} // if the port is used
-		} // for every port on the board
-			
-		/* Now check the CD message queue */
-		newhead = mem->Common.CDHead;
-		bufpos = mem->Common.CDTail;
-		if (newhead != bufpos){				/* There are CD events in queue */
-			ocd = mem->Common.CDStatus; 		/* get old status bits */
-			while (newhead != bufpos){		/* read all events */
-				ncd = mem->CDBuf[bufpos++]; 	/* get one event */
-				ccd = ncd ^ ocd; 		/* mask of changed lines */
-				ocd = ncd; 			/* save new status bits */
-				for(p=0; p < NUMLINES; p++){	/* for all ports */
-					if (ccd & 1){		/* this one changed */
-
-						struct a2232_port *port = &a2232_ports[n*7+p];
-						port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */
-
-						if (!(port->gs.port.flags & ASYNC_CHECK_CD))
-							;	/* Don't report DCD changes */
-						else if (port->cd_status) { // if DCD on: DCD went UP!
-							
-							/* Are we blocking in open?*/
-							wake_up_interruptible(&port->gs.port.open_wait);
-						}
-						else { // if DCD off: DCD went DOWN!
-							if (port->gs.port.tty)
-								tty_hangup (port->gs.port.tty);
-						}
-						
-					} // if CD changed for this port
-					ccd >>= 1;
-					ncd >>= 1;									/* Shift bits for next line */
-				} // for every port
-			} // while CD events in queue
-			mem->Common.CDStatus = ocd; /* save new status */
-			mem->Common.CDTail = bufpos; /* remove events */
-		} // if events in CD queue
-		
-	} // for every completely initialized A2232 board
-	return IRQ_HANDLED;
-}
-
-static const struct tty_port_operations a2232_port_ops = {
-	.carrier_raised = a2232_carrier_raised,
-};
-
-static void a2232_init_portstructs(void)
-{
-	struct a2232_port *port;
-	int i;
-
-	for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
-		port = a2232_ports + i;
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &a2232_port_ops;
-		port->which_a2232 = i/NUMLINES;
-		port->which_port_on_a2232 = i%NUMLINES;
-		port->disable_rx = port->throttle_input = port->cd_status = 0;
-		port->gs.magic = A2232_MAGIC;
-		port->gs.close_delay = HZ/2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &a2232_real_driver;
-	}
-}
-
-static const struct tty_operations a2232_ops = {
-	.open = a2232_open,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = a2232_ioctl,
-	.throttle = a2232_throttle,
-	.unthrottle = a2232_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-};
-
-static int a2232_init_drivers(void)
-{
-	int error;
-
-	a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232);
-	if (!a2232_driver)
-		return -ENOMEM;
-	a2232_driver->owner = THIS_MODULE;
-	a2232_driver->driver_name = "commodore_a2232";
-	a2232_driver->name = "ttyY";
-	a2232_driver->major = A2232_NORMAL_MAJOR;
-	a2232_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	a2232_driver->subtype = SERIAL_TYPE_NORMAL;
-	a2232_driver->init_termios = tty_std_termios;
-	a2232_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	a2232_driver->init_termios.c_ispeed = 9600;
-	a2232_driver->init_termios.c_ospeed = 9600;
-	a2232_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(a2232_driver, &a2232_ops);
-	if ((error = tty_register_driver(a2232_driver))) {
-		printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n",
-		       error);
-		put_tty_driver(a2232_driver);
-		return 1;
-	}
-	return 0;
-}
-
-static int __init a2232board_init(void)
-{
-	struct zorro_dev *z;
-
-	unsigned int boardaddr;
-	int bcount;
-	short start;
-	u_char *from;
-	volatile u_char *to;
-	volatile struct a2232memory *mem;
-	int error, i;
-
-#ifdef CONFIG_SMP
-	return -ENODEV;	/* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
-#endif
-
-	if (!MACH_IS_AMIGA){
-		return -ENODEV;
-	}
-
-	printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */
-
-	z = NULL;
-	nr_a2232 = 0;
-	while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){
-		if (	(z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && 
-			(z->id != ZORRO_PROD_CBM_A2232)	){
-			continue;	// The board found was no A2232
-		}
-		if (!zorro_request_device(z,"A2232 driver"))
-			continue;
-
-		printk("Commodore A2232 found (#%d).\n",nr_a2232);
-
-		zd_a2232[nr_a2232] = z;
-
-		boardaddr = ZTWO_VADDR( z->resource.start );
-		printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start)));
-
-		mem = (volatile struct a2232memory *) boardaddr;
-
-		(void) mem->Enable6502Reset;   /* copy the code across to the board */
-		to = (u_char *)mem;  from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2;
-		start = *(short *)from;
-		from += sizeof(start);
-		to += start;
-		while(bcount--) *to++ = *from++;
-		printk("65EC02 software uploaded to the A2232 memory.\n");
-  
-		mem->Common.Crystal = A2232_UNKNOWN;  /* use automatic speed check */
-  
-		/* start 6502 running */
-		(void) mem->ResetBoard;
-		printk("A2232's 65EC02 CPU up and running.\n");
-  
-		/* wait until speed detector has finished */
-		for (bcount = 0; bcount < 2000; bcount++) {
-			udelay(1000);
-			if (mem->Common.Crystal)
-				break;
-		}
-		printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: "));
-		switch (mem->Common.Crystal){
-		case A2232_UNKNOWN:
-			printk("Unknown crystal.\n");
-			break;
- 		case A2232_NORMAL:
-			printk ("Normal crystal.\n");
-			break;
-		case A2232_TURBO:
-			printk ("Turbo crystal.\n");
-			break;
-		default:
-			printk ("0x%x. Huh?\n",mem->Common.Crystal);
-		}
-
-		nr_a2232++;
-
-	}	
-
-	printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */
-
-	a2232_init_portstructs();
-
-	/*
-		a2232_init_drivers also registers the drivers. Must be here because all boards
-		have to be detected first.
-	*/
-	if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
-
-	error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
-			    "A2232 serial VBL", a2232_driver_ID);
-	if (error) {
-		for (i = 0; i < nr_a2232; i++)
-			zorro_release_device(zd_a2232[i]);
-		tty_unregister_driver(a2232_driver);
-		put_tty_driver(a2232_driver);
-	}
-	return error;
-}
-
-static void __exit a2232board_exit(void)
-{
-	int i;
-
-	for (i = 0; i < nr_a2232; i++) {
-		zorro_release_device(zd_a2232[i]);
-	}
-
-	tty_unregister_driver(a2232_driver);
-	put_tty_driver(a2232_driver);
-	free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID);
-}
-
-module_init(a2232board_init);
-module_exit(a2232board_exit);
-
-MODULE_AUTHOR("Enver Haase");
-MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/ser_a2232.h b/drivers/char/ser_a2232.h
deleted file mode 100644
index bc09eb9..0000000
--- a/drivers/char/ser_a2232.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/* drivers/char/ser_a2232.h */
-
-/* $Id: ser_a2232.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/* Linux serial driver for the Amiga A2232 board */
-
-/* This driver is MAINTAINED. Before applying any changes, please contact
- * the author.
- */
-   
-/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
- *                   alias The A2232 driver project <A2232@gmx.net>
- * All rights reserved.
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *  
- */
-
-#ifndef _SER_A2232_H_
-#define _SER_A2232_H_
-
-/*
-	How many boards are to be supported at maximum;
-	"up to five A2232 Multiport Serial Cards may be installed in a
-	single Amiga 2000" states the A2232 User's Guide. If you have
-	more slots available, you might want to change the value below.
-*/
-#define MAX_A2232_BOARDS 5
-
-#ifndef A2232_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define A2232_NORMAL_MAJOR  224	/* /dev/ttyY* */
-#define A2232_CALLOUT_MAJOR 225	/* /dev/cuy*  */
-#endif
-
-/* Some magic is always good - Who knows :) */
-#define A2232_MAGIC 0x000a2232
-
-/* A2232 port structure to keep track of the
-   status of every single line used */
-struct a2232_port{
-	struct gs_port gs;
-	unsigned int which_a2232;
-	unsigned int which_port_on_a2232;
-	short disable_rx;
-	short throttle_input;
-	short cd_status;
-};
-
-#define	NUMLINES		7	/* number of lines per board */
-#define	A2232_IOBUFLEN		256	/* number of bytes per buffer */
-#define	A2232_IOBUFLENMASK	0xff	/* mask for maximum number of bytes */
-
-
-#define	A2232_UNKNOWN	0	/* crystal not known */
-#define	A2232_NORMAL	1	/* normal A2232 (1.8432 MHz oscillator) */
-#define	A2232_TURBO	2	/* turbo A2232 (3.6864 MHz oscillator) */
-
-
-struct a2232common {
-	char   Crystal;	/* normal (1) or turbo (2) board? */
-	u_char Pad_a;
-	u_char TimerH;	/* timer value after speed check */
-	u_char TimerL;
-	u_char CDHead;	/* head pointer for CD message queue */
-	u_char CDTail;	/* tail pointer for CD message queue */
-	u_char CDStatus;
-	u_char Pad_b;
-};
-
-struct a2232status {
-	u_char InHead;		/* input queue head */
-	u_char InTail;		/* input queue tail */
-	u_char OutDisable;	/* disables output */
-	u_char OutHead;		/* output queue head */
-	u_char OutTail;		/* output queue tail */
-	u_char OutCtrl;		/* soft flow control character to send */
-	u_char OutFlush;	/* flushes output buffer */
-	u_char Setup;		/* causes reconfiguration */
-	u_char Param;		/* parameter byte - see A2232PARAM */
-	u_char Command;		/* command byte - see A2232CMD */
-	u_char SoftFlow;	/* enables xon/xoff flow control */
-	/* private 65EC02 fields: */
-	u_char XonOff;		/* stores XON/XOFF enable/disable */
-};
-
-#define	A2232_MEMPAD1	\
-	(0x0200 - NUMLINES * sizeof(struct a2232status)	-	\
-	sizeof(struct a2232common))
-#define	A2232_MEMPAD2	(0x2000 - NUMLINES * A2232_IOBUFLEN - A2232_IOBUFLEN)
-
-struct a2232memory {
-	struct a2232status Status[NUMLINES];	/* 0x0000-0x006f status areas */
-	struct a2232common Common;		/* 0x0070-0x0077 common flags */
-	u_char Dummy1[A2232_MEMPAD1];		/* 0x00XX-0x01ff */
-	u_char OutBuf[NUMLINES][A2232_IOBUFLEN];/* 0x0200-0x08ff output bufs */
-	u_char InBuf[NUMLINES][A2232_IOBUFLEN];	/* 0x0900-0x0fff input bufs */
-	u_char InCtl[NUMLINES][A2232_IOBUFLEN];	/* 0x1000-0x16ff control data */
-	u_char CDBuf[A2232_IOBUFLEN];		/* 0x1700-0x17ff CD event buffer */
-	u_char Dummy2[A2232_MEMPAD2];		/* 0x1800-0x2fff */
-	u_char Code[0x1000];			/* 0x3000-0x3fff code area */
-	u_short InterruptAck;			/* 0x4000        intr ack */
-	u_char Dummy3[0x3ffe];			/* 0x4002-0x7fff */
-	u_short Enable6502Reset;		/* 0x8000 Stop board, */
-						/*  6502 RESET line held low */
-	u_char Dummy4[0x3ffe];			/* 0x8002-0xbfff */
-	u_short ResetBoard;			/* 0xc000 reset board & run, */
-						/*  6502 RESET line held high */
-};
-
-#undef A2232_MEMPAD1
-#undef A2232_MEMPAD2
-
-#define	A2232INCTL_CHAR		0	/* corresponding byte in InBuf is a character */
-#define	A2232INCTL_EVENT	1	/* corresponding byte in InBuf is an event */
-
-#define	A2232EVENT_Break	1	/* break set */
-#define	A2232EVENT_CarrierOn	2	/* carrier raised */
-#define	A2232EVENT_CarrierOff	3	/* carrier dropped */
-#define A2232EVENT_Sync		4	/* don't know, defined in 2232.ax */
-
-#define	A2232CMD_Enable		0x1	/* enable/DTR bit */
-#define	A2232CMD_Close		0x2	/* close the device */
-#define	A2232CMD_Open		0xb	/* open the device */
-#define	A2232CMD_CMask		0xf	/* command mask */
-#define	A2232CMD_RTSOff		0x0  	/* turn off RTS */
-#define	A2232CMD_RTSOn		0x8	/* turn on RTS */
-#define	A2232CMD_Break		0xd	/* transmit a break */
-#define	A2232CMD_RTSMask	0xc	/* mask for RTS stuff */
-#define	A2232CMD_NoParity	0x00	/* don't use parity */
-#define	A2232CMD_OddParity	0x20	/* odd parity */
-#define	A2232CMD_EvenParity	0x60	/* even parity */
-#define	A2232CMD_ParityMask	0xe0	/* parity mask */
-
-#define	A2232PARAM_B115200	0x0	/* baud rates */
-#define	A2232PARAM_B50		0x1
-#define	A2232PARAM_B75		0x2
-#define	A2232PARAM_B110		0x3
-#define	A2232PARAM_B134		0x4
-#define	A2232PARAM_B150		0x5
-#define	A2232PARAM_B300		0x6
-#define	A2232PARAM_B600		0x7
-#define	A2232PARAM_B1200	0x8
-#define	A2232PARAM_B1800	0x9
-#define	A2232PARAM_B2400	0xa
-#define	A2232PARAM_B3600	0xb
-#define	A2232PARAM_B4800	0xc
-#define	A2232PARAM_B7200	0xd
-#define	A2232PARAM_B9600	0xe
-#define	A2232PARAM_B19200	0xf
-#define	A2232PARAM_BaudMask	0xf	/* baud rate mask */
-#define	A2232PARAM_RcvBaud	0x10	/* enable receive baud rate */
-#define	A2232PARAM_8Bit		0x00	/* numbers of bits */
-#define	A2232PARAM_7Bit		0x20
-#define	A2232PARAM_6Bit		0x40
-#define	A2232PARAM_5Bit		0x60
-#define	A2232PARAM_BitMask	0x60	/* numbers of bits mask */
-
-
-/* Standard speeds tables, -1 means unavailable, -2 means 0 baud: switch off line */
-#define A2232_BAUD_TABLE_NOAVAIL -1
-#define A2232_BAUD_TABLE_NUM_RATES (18)
-static int a2232_baud_table[A2232_BAUD_TABLE_NUM_RATES*3] = {
-	//Baud	//Normal			//Turbo
-	50,	A2232PARAM_B50,			A2232_BAUD_TABLE_NOAVAIL,
-	75,	A2232PARAM_B75,			A2232_BAUD_TABLE_NOAVAIL,
-	110,	A2232PARAM_B110,		A2232_BAUD_TABLE_NOAVAIL,
-	134,	A2232PARAM_B134,		A2232_BAUD_TABLE_NOAVAIL,
-	150,	A2232PARAM_B150,		A2232PARAM_B75,
-	200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-	300,	A2232PARAM_B300,		A2232PARAM_B150,
-	600,	A2232PARAM_B600,		A2232PARAM_B300,
-	1200,	A2232PARAM_B1200,		A2232PARAM_B600,
-	1800,	A2232PARAM_B1800,		A2232_BAUD_TABLE_NOAVAIL,
-	2400,	A2232PARAM_B2400,		A2232PARAM_B1200,
-	4800,	A2232PARAM_B4800,		A2232PARAM_B2400,
-	9600,	A2232PARAM_B9600,		A2232PARAM_B4800,
-	19200,	A2232PARAM_B19200,		A2232PARAM_B9600,
-	38400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B19200,
-	57600,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-#ifdef A2232_SPEEDHACK
-	115200,	A2232PARAM_B115200,		A2232_BAUD_TABLE_NOAVAIL,
-	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B115200
-#else
-	115200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL
-#endif
-};
-#endif
diff --git a/drivers/char/ser_a2232fw.ax b/drivers/char/ser_a2232fw.ax
deleted file mode 100644
index 7364380..0000000
--- a/drivers/char/ser_a2232fw.ax
+++ /dev/null
@@ -1,529 +0,0 @@
-;.lib "axm"
-;
-;begin
-;title "A2232 serial board driver"
-;
-;set modules "2232"
-;set executable "2232.bin"
-;
-;;;;set nolink
-;
-;set temporary directory "t:"
-;
-;set assembly options "-m6502 -l60:t:list"
-;set link options "bin"; loadadr"
-;;;bin2c 2232.bin msc6502.h msc6502code
-;end
-;
-;
-; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ###
-;
-; - Created 950501 by JM -
-;
-;
-; Serial board driver software.
-;
-;
-% Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
-% All rights reserved.
-%
-% Redistribution and use in source and binary forms, with or without
-% modification, are permitted provided that the following conditions
-% are met:
-% 1. Redistributions of source code must retain the above copyright
-%    notice, and the entire permission notice in its entirety,
-%    including the disclaimer of warranties.
-% 2. Redistributions in binary form must reproduce the above copyright
-%    notice, this list of conditions and the following disclaimer in the
-%    documentation and/or other materials provided with the distribution.
-% 3. The name of the author may not be used to endorse or promote
-%    products derived from this software without specific prior
-%    written permission.
-%
-% ALTERNATIVELY, this product may be distributed under the terms of
-% the GNU General Public License, in which case the provisions of the
-% GPL are required INSTEAD OF the above restrictions.  (This clause is
-% necessary due to a potential bad interaction between the GPL and
-% the restrictions contained in a BSD-style copyright.)
-%
-% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
-% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-% DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-% OF THE POSSIBILITY OF SUCH DAMAGE.
-;
-;
-; Bugs:
-;
-; - Can't send a break yet
-;
-;
-;
-; Edited:
-;
-; - 950501 by JM -> v0.1	- Created this file.
-; - 951029 by JM -> v1.3	- Carrier Detect events now queued in a separate
-;				  queue.
-;
-;
-
-
-CODE		equ	$3800		; start address for program code
-
-
-CTL_CHAR	equ	$00		; byte in ibuf is a character
-CTL_EVENT	equ	$01		; byte in ibuf is an event
-
-EVENT_BREAK	equ	$01
-EVENT_CDON	equ	$02
-EVENT_CDOFF	equ	$03
-EVENT_SYNC	equ	$04
-
-XON		equ	$11
-XOFF		equ	$13
-
-
-VARBASE		macro	*starting_address	; was VARINIT
-_varbase	set	\1
-		endm
-
-VARDEF		macro	*name space_needs
-\1		equ	_varbase
-_varbase	set	_varbase+\2
-		endm
-
-
-stz		macro	* address
-		 db	$64,\1
-		endm
-
-stzax		macro	* address
-		 db	$9e,<\1,>\1
-		endm
-
-
-biti		macro	* immediate value
-		db	$89,\1
-		endm
-
-smb0		macro	* address
-		db	$87,\1
-		endm
-smb1		macro	* address
-		db	$97,\1
-		endm
-smb2		macro	* address
-		db	$a7,\1
-		endm
-smb3		macro	* address
-		db	$b7,\1
-		endm
-smb4		macro	* address
-		db	$c7,\1
-		endm
-smb5		macro	* address
-		db	$d7,\1
-		endm
-smb6		macro	* address
-		db	$e7,\1
-		endm
-smb7		macro	* address
-		db	$f7,\1
-		endm
-
-
-
-;-----------------------------------------------------------------------;
-;									;
-; stuff common for all ports, non-critical (run once / loop)		;
-;									;
-DO_SLOW		macro	* port_number					;
-		.local			;				;
-		lda	CIA+C_PA	; check all CD inputs		;
-		cmp	CommonCDo	; changed from previous accptd?	;
-		beq	=over		; nope, do nothing else here	;
-					;				;
-		cmp	CommonCDb	; bouncing?			;
-		beq	=nobounce	; nope ->			;
-					;				;
-		sta	CommonCDb	; save current state		;
-		lda	#64		; reinitialize counter		;
-		sta	CommonCDc	;				;
-		jmp	=over		; skip CD save			;
-					;				;
-=nobounce	dec	CommonCDc	; no, decrement bounce counter	;
-		bpl	=over		; not done yet, so skip CD save	;
-					;				;
-=saveCD		ldx	CDHead		; get write index		;
-		sta	cdbuf,x		; save status in buffer		;
-		inx			;				;
-		cpx	CDTail		; buffer full?			;
-		.if	ne		; no: preserve status:		;
-		 stx	CDHead		; update index in RAM		;
-		 sta	CommonCDo	; save state for the next check	;
-		.end			;				;
-=over		.end	local						;
-		endm							;
-									;
-;-----------------------------------------------------------------------;
-
-
-; port specific stuff (no data transfer)
-
-DO_PORT		macro	* port_number
-		.local			;				;
-		lda	SetUp\1		; reconfiguration request?	;
-		.if	ne		; yes:				;
-		 lda	SoftFlow\1	; get XON/XOFF flag		;
-		 sta	XonOff\1	; save it			;
-		 lda	Param\1		; get parameter			;
-		 ora	#%00010000	; use baud generator for Rx	;
-		 sta	ACIA\1+A_CTRL	; store in control register	;
-		 stz	OutDisable\1	; enable transmit output	;
-		 stz	SetUp\1		; no reconfiguration no more	;
-		.end			;				;
-					;				;
-		lda	InHead\1	; get write index		;
-		sbc	InTail\1	; buffer full soon?		;
-		cmp	#200		; 200 chars or more in buffer?	;
-		lda	Command\1	; get Command reg value		;
-		and	#%11110011	; turn RTS OFF by default	;
-		.if	cc		; still room in buffer:		;
-		 ora	#%00001000	; turn RTS ON			;
-		.end			;				;
-		sta	ACIA\1+A_CMD	; set/clear RTS			;
-					;				;
-		lda	OutFlush\1	; request to flush output buffer;
-		.if	ne		; yessh!			;
-		 lda	OutHead\1	; get head			;
-		 sta	OutTail\1	; save as tail			;
-		 stz	OutDisable\1	; enable transmit output	;
-		 stz	OutFlush\1	; clear request			;
-		.end
-		.end	local
-		endm
-
-
-DO_DATA		macro	* port number
-		.local
-		lda	ACIA\1+A_SR	; read ACIA status register	;
-		biti	[1<<3]		; something received?		;
-		.if	ne		; yes:				;
-		 biti	[1<<1]		; framing error?		;
-		 .if	ne		; yes:				;
-		  lda	ACIA\1+A_DATA	; read received character	;
-		  bne	=SEND		; not break -> ignore it	;
-		  ldx	InHead\1	; get write pointer		;
-		  lda	#CTL_EVENT	; get type of byte		;
-		  sta	ictl\1,x	; save it in InCtl buffer	;
-		  lda	#EVENT_BREAK	; event code			;
-		  sta	ibuf\1,x	; save it as well		;
-		  inx			;				;
-		  cpx	InTail\1	; still room in buffer?		;
-		  .if	ne		; absolutely:			;
-		   stx	InHead\1	; update index in memory	;
-		  .end			;				;
-		  jmp	=SEND		; go check if anything to send	;
-		 .end			;				;
-		 			; normal char received:		;
-		 ldx	InHead\1	; get write index		;
-		 lda	ACIA\1+A_DATA	; read received character	;
-		 sta	ibuf\1,x	; save char in buffer		;
-		 stzax	ictl\1		; set type to CTL_CHAR		;
-		 inx			;				;
-		 cpx	InTail\1	; buffer full?			;
-		 .if	ne		; no: preserve character:	;
-		  stx	InHead\1	; update index in RAM		;
-		 .end			;				;
-		 and	#$7f		; mask off parity if any	;
-		 cmp	#XOFF		; XOFF from remote host?	;
-		 .if	eq		; yes:				;
-		  lda	XonOff\1	; if XON/XOFF handshaking..	;
-		  sta	OutDisable\1	; ..disable transmitter		;
-		 .end			;				;
-		.end			;				;
-					;				;
-					; BUFFER FULL CHECK WAS HERE	;
-					;				;
-=SEND		lda	ACIA\1+A_SR	; transmit register empty?	;
-		and	#[1<<4]		;				;
-		.if	ne		; yes:				;
-		 ldx	OutCtrl\1	; sending out XON/XOFF?		;
-		 .if	ne		; yes:				;
-		  lda	CIA+C_PB	; check CTS signal		;
-		  and	#[1<<\1]	; (for this port only)		;
-		  bne	=DONE		; not allowed to send -> done	;
-		  stx	ACIA\1+A_DATA	; transmit control char		;
-		  stz	OutCtrl\1	; clear flag			;
-		  jmp	=DONE		; and we're done		;
-		 .end			;				;
-					;				;
-		 ldx	OutTail\1	; anything to transmit?		;
-		 cpx	OutHead\1	;				;
-		 .if	ne		; yes:				;
-		  lda	OutDisable\1	; allowed to transmit?		;
-		  .if	eq		; yes:				;
-		   lda	CIA+C_PB	; check CTS signal		;
-		   and	#[1<<\1]	; (for this port only)		;
-		   bne	=DONE		; not allowed to send -> done	;
-		   lda	obuf\1,x	; get a char from buffer	;
-		   sta	ACIA\1+A_DATA	; send it away			;
-		   inc	OutTail\1	; update read index		;
-		  .end			;				;
-		 .end			;				;
-		.end			;				;
-=DONE		.end	local
-		endm
-
-
-
-PORTVAR		macro	* port number
-		VARDEF	InHead\1 1
-		VARDEF	InTail\1 1
-		VARDEF	OutDisable\1 1
-		VARDEF	OutHead\1 1
-		VARDEF	OutTail\1 1
-		VARDEF	OutCtrl\1 1
-		VARDEF	OutFlush\1 1
-		VARDEF	SetUp\1 1
-		VARDEF	Param\1 1
-		VARDEF	Command\1 1
-		VARDEF	SoftFlow\1 1
-		; private:
-		VARDEF	XonOff\1 1
-		endm
-
-
- VARBASE 0	; start variables at address $0000
- PORTVAR 0	; define variables for port 0
- PORTVAR 1	; define variables for port 1
- PORTVAR 2	; define variables for port 2
- PORTVAR 3	; define variables for port 3
- PORTVAR 4	; define variables for port 4
- PORTVAR 5	; define variables for port 5
- PORTVAR 6	; define variables for port 6
-
-
-
- VARDEF	Crystal	1	; 0 = unknown, 1 = normal, 2 = turbo
- VARDEF	Pad_a	1
- VARDEF	TimerH	1
- VARDEF	TimerL	1
- VARDEF	CDHead	1
- VARDEF	CDTail	1
- VARDEF	CDStatus 1
- VARDEF	Pad_b	1
-
- VARDEF	CommonCDo 1	; for carrier detect optimization
- VARDEF	CommonCDc 1	; for carrier detect debouncing
- VARDEF	CommonCDb 1	; for carrier detect debouncing
-
-
- VARBASE $0200
- VARDEF	obuf0 256	; output data (characters only)
- VARDEF	obuf1 256
- VARDEF	obuf2 256
- VARDEF	obuf3 256
- VARDEF	obuf4 256
- VARDEF	obuf5 256
- VARDEF	obuf6 256
-
- VARDEF	ibuf0 256	; input data (characters, events etc - see ictl)
- VARDEF	ibuf1 256
- VARDEF	ibuf2 256
- VARDEF	ibuf3 256
- VARDEF	ibuf4 256
- VARDEF	ibuf5 256
- VARDEF	ibuf6 256
-
- VARDEF	ictl0 256	; input control information (type of data in ibuf)
- VARDEF	ictl1 256
- VARDEF	ictl2 256
- VARDEF	ictl3 256
- VARDEF	ictl4 256
- VARDEF	ictl5 256
- VARDEF	ictl6 256
-
- VARDEF	cdbuf 256	; CD event queue
-
-
-ACIA0		equ	$4400
-ACIA1		equ	$4c00
-ACIA2		equ	$5400
-ACIA3		equ	$5c00
-ACIA4		equ	$6400
-ACIA5		equ	$6c00
-ACIA6		equ	$7400
-
-A_DATA		equ	$00
-A_SR		equ	$02
-A_CMD		equ	$04
-A_CTRL		equ	$06
-;  00	write transmit data	read received data
-;  02	reset ACIA		read status register
-;  04	write command register	read command register
-;  06	write control register	read control register
-
-CIA		equ	$7c00		; 8520 CIA
-C_PA		equ	$00		; port A data register
-C_PB		equ	$02		; port B data register
-C_DDRA		equ	$04		; data direction register for port A
-C_DDRB		equ	$06		; data direction register for port B
-C_TAL		equ	$08		; timer A
-C_TAH		equ	$0a
-C_TBL		equ	$0c		; timer B
-C_TBH		equ	$0e
-C_TODL		equ	$10		; TOD LSB
-C_TODM		equ	$12		; TOD middle byte
-C_TODH		equ	$14		; TOD MSB
-C_DATA		equ	$18		; serial data register
-C_INTCTRL	equ	$1a		; interrupt control register
-C_CTRLA		equ	$1c		; control register A
-C_CTRLB		equ	$1e		; control register B
-
-
-
-
-
-		section	main,code,CODE-2
-
-		db	>CODE,<CODE
-
-;-----------------------------------------------------------------------;
-; here's the initialization code:					;
-;									;
-R_RESET		ldx	#$ff						;
-		txs			; initialize stack pointer	;
-		cld			; in case a 6502 is used...	;
-		ldx	#0		;				;
-		lda	#0		;				;
-		ldy	#Crystal	; this many bytes to clear	;
-clr_loop	sta	0,x		; clear zero page variables	;
-		inx			;				;
-		dey			;				;
-		bne	clr_loop	;				;
-					;				;
-		stz	CommonCDo	; force CD test at boot		;
-		stz	CommonCDb	;				;
-		stz	CDHead		; clear queue			;
-		stz	CDTail		;				;
-					;				;
-		lda	#0		;				;
-		sta	Pad_a		;				;
-		lda	#170		; test cmp			;
-		cmp	#100		;				;
-		.if	cs		;				;
-		 inc	Pad_a		; C was set			;
-		.end			;				;
-									;
-;-----------------------------------------------------------------------;
-; Speed check								;
-;-----------------------------------------------------------------------;
-									;
-		lda	Crystal		; speed already set?		;
-		beq	DoSpeedy	;				;
-		jmp	LOOP		; yes, skip speed test		;
-					;				;
-DoSpeedy	lda	#%10011000	; 8N1, 1200/2400 bps		;
-		sta	ACIA0+A_CTRL	;				;
-		lda	#%00001011	; enable DTR			;
-		sta	ACIA0+A_CMD	;				;
-		lda	ACIA0+A_SR	; read status register		;
-					;				;
-		lda	#%10000000	; disable all ints (unnecessary);
-		sta	CIA+C_INTCTRL	;				;
-		lda	#255		; program the timer		;
-		sta	CIA+C_TAL	;				;
-		sta	CIA+C_TAH	;				;
-					;				;
-		ldx	#0		;				;
-		stx	ACIA0+A_DATA	; transmit a zero		;
-		nop			;				;
-		nop			;				;
-		lda	ACIA0+A_SR	; read status			;
-		nop			;				;
-		nop			;				;
-		stx	ACIA0+A_DATA	; transmit a zero		;
-Speedy1		lda	ACIA0+A_SR	; read status			;
-		and	#[1<<4]		; transmit data reg empty?	;
-		beq	Speedy1		; not yet, wait more		;
-					;				;
-		lda	#%00010001	; load & start the timer	;
-		stx	ACIA0+A_DATA	; transmit one more zero	;
-		sta	CIA+C_CTRLA	;				;
-Speedy2		lda	ACIA0+A_SR	; read status			;
-		and	#[1<<4]		; transmit data reg empty?	;
-		beq	Speedy2		; not yet, wait more		;
-		stx	CIA+C_CTRLA	; stop the timer		;
-					;				;
-		lda	CIA+C_TAL	; copy timer value for 68k	;
-		sta	TimerL		;				;
-		lda	CIA+C_TAH	;				;
-		sta	TimerH		;				;
-		cmp	#$d0		; turbo or normal?		;
-		.if	cs		;				;
-		 lda	#2		; turbo! :-)			;
-		.else			;				;
-		 lda	#1		; normal :-(			;
-		.end			;				;
-		sta	Crystal		;				;
-		lda	#0		;				;
-		sta	ACIA0+A_SR	;				;
-		sta	ACIA0+A_CTRL	; reset UART			;
-		sta	ACIA0+A_CMD	;				;
-									;
-		jmp	LOOP						;
-									;
-;									;
-;-----------------------------------------------------------------------;
-;									;
-; The Real Thing:							;
-;									;
-LOOP		DO_SLOW			; do non-critical things	;
-		jsr	do_input	; check for received data
-		DO_PORT	0
-		jsr	do_input
-		DO_PORT	1
-		jsr	do_input
-		DO_PORT	2
-		jsr	do_input
-		DO_PORT	3
-		jsr	do_input
-		DO_PORT	4
-		jsr	do_input
-		DO_PORT	5
-		jsr	do_input
-		DO_PORT	6
-		jsr	do_input
-		jmp	LOOP
-
-
-do_input	DO_DATA	0
-		DO_DATA	1
-		DO_DATA	2
-		DO_DATA	3
-		DO_DATA	4
-		DO_DATA	5
-		DO_DATA	6
-		rts
-
-
-;-----------------------------------------------------------------------;
-		section	vectors,data,$3ffa
-		dw	$d0d0
-		dw	R_RESET
-		dw	$c0ce
-;-----------------------------------------------------------------------;
-
-
-
-		end
-
-
-
diff --git a/drivers/char/ser_a2232fw.h b/drivers/char/ser_a2232fw.h
deleted file mode 100644
index e09a30a..0000000
--- a/drivers/char/ser_a2232fw.h
+++ /dev/null
@@ -1,306 +0,0 @@
-/* drivers/char/ser_a2232fw.h */
-
-/* $Id: ser_a2232fw.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/*
- * Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, and the entire permission notice in its entirety,
- *    including the disclaimer of warranties.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions.  (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-                                      
-/* This is the 65EC02 code by Jukka Marin that is executed by
-   the A2232's 65EC02 processor (base address: 0x3800)
-   Source file:	ser_a2232fw.ax
-   Version:	1.3 (951029)
-   Known Bugs:	Cannot send a break yet
-*/
-static unsigned char a2232_65EC02code[] = {
-	0x38, 0x00, 0xA2, 0xFF, 0x9A, 0xD8, 0xA2, 0x00, 
-	0xA9, 0x00, 0xA0, 0x54, 0x95, 0x00, 0xE8, 0x88, 
-	0xD0, 0xFA, 0x64, 0x5C, 0x64, 0x5E, 0x64, 0x58, 
-	0x64, 0x59, 0xA9, 0x00, 0x85, 0x55, 0xA9, 0xAA, 
-	0xC9, 0x64, 0x90, 0x02, 0xE6, 0x55, 0xA5, 0x54, 
-	0xF0, 0x03, 0x4C, 0x92, 0x38, 0xA9, 0x98, 0x8D, 
-	0x06, 0x44, 0xA9, 0x0B, 0x8D, 0x04, 0x44, 0xAD, 
-	0x02, 0x44, 0xA9, 0x80, 0x8D, 0x1A, 0x7C, 0xA9, 
-	0xFF, 0x8D, 0x08, 0x7C, 0x8D, 0x0A, 0x7C, 0xA2, 
-	0x00, 0x8E, 0x00, 0x44, 0xEA, 0xEA, 0xAD, 0x02, 
-	0x44, 0xEA, 0xEA, 0x8E, 0x00, 0x44, 0xAD, 0x02, 
-	0x44, 0x29, 0x10, 0xF0, 0xF9, 0xA9, 0x11, 0x8E, 
-	0x00, 0x44, 0x8D, 0x1C, 0x7C, 0xAD, 0x02, 0x44, 
-	0x29, 0x10, 0xF0, 0xF9, 0x8E, 0x1C, 0x7C, 0xAD, 
-	0x08, 0x7C, 0x85, 0x57, 0xAD, 0x0A, 0x7C, 0x85, 
-	0x56, 0xC9, 0xD0, 0x90, 0x05, 0xA9, 0x02, 0x4C, 
-	0x82, 0x38, 0xA9, 0x01, 0x85, 0x54, 0xA9, 0x00, 
-	0x8D, 0x02, 0x44, 0x8D, 0x06, 0x44, 0x8D, 0x04, 
-	0x44, 0x4C, 0x92, 0x38, 0xAD, 0x00, 0x7C, 0xC5, 
-	0x5C, 0xF0, 0x1F, 0xC5, 0x5E, 0xF0, 0x09, 0x85, 
-	0x5E, 0xA9, 0x40, 0x85, 0x5D, 0x4C, 0xB8, 0x38, 
-	0xC6, 0x5D, 0x10, 0x0E, 0xA6, 0x58, 0x9D, 0x00, 
-	0x17, 0xE8, 0xE4, 0x59, 0xF0, 0x04, 0x86, 0x58, 
-	0x85, 0x5C, 0x20, 0x23, 0x3A, 0xA5, 0x07, 0xF0, 
-	0x0F, 0xA5, 0x0A, 0x85, 0x0B, 0xA5, 0x08, 0x09, 
-	0x10, 0x8D, 0x06, 0x44, 0x64, 0x02, 0x64, 0x07, 
-	0xA5, 0x00, 0xE5, 0x01, 0xC9, 0xC8, 0xA5, 0x09, 
-	0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 
-	0x44, 0xA5, 0x06, 0xF0, 0x08, 0xA5, 0x03, 0x85, 
-	0x04, 0x64, 0x02, 0x64, 0x06, 0x20, 0x23, 0x3A, 
-	0xA5, 0x13, 0xF0, 0x0F, 0xA5, 0x16, 0x85, 0x17, 
-	0xA5, 0x14, 0x09, 0x10, 0x8D, 0x06, 0x4C, 0x64, 
-	0x0E, 0x64, 0x13, 0xA5, 0x0C, 0xE5, 0x0D, 0xC9, 
-	0xC8, 0xA5, 0x15, 0x29, 0xF3, 0xB0, 0x02, 0x09, 
-	0x08, 0x8D, 0x04, 0x4C, 0xA5, 0x12, 0xF0, 0x08, 
-	0xA5, 0x0F, 0x85, 0x10, 0x64, 0x0E, 0x64, 0x12, 
-	0x20, 0x23, 0x3A, 0xA5, 0x1F, 0xF0, 0x0F, 0xA5, 
-	0x22, 0x85, 0x23, 0xA5, 0x20, 0x09, 0x10, 0x8D, 
-	0x06, 0x54, 0x64, 0x1A, 0x64, 0x1F, 0xA5, 0x18, 
-	0xE5, 0x19, 0xC9, 0xC8, 0xA5, 0x21, 0x29, 0xF3, 
-	0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x54, 0xA5, 
-	0x1E, 0xF0, 0x08, 0xA5, 0x1B, 0x85, 0x1C, 0x64, 
-	0x1A, 0x64, 0x1E, 0x20, 0x23, 0x3A, 0xA5, 0x2B, 
-	0xF0, 0x0F, 0xA5, 0x2E, 0x85, 0x2F, 0xA5, 0x2C, 
-	0x09, 0x10, 0x8D, 0x06, 0x5C, 0x64, 0x26, 0x64, 
-	0x2B, 0xA5, 0x24, 0xE5, 0x25, 0xC9, 0xC8, 0xA5, 
-	0x2D, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 
-	0x04, 0x5C, 0xA5, 0x2A, 0xF0, 0x08, 0xA5, 0x27, 
-	0x85, 0x28, 0x64, 0x26, 0x64, 0x2A, 0x20, 0x23, 
-	0x3A, 0xA5, 0x37, 0xF0, 0x0F, 0xA5, 0x3A, 0x85, 
-	0x3B, 0xA5, 0x38, 0x09, 0x10, 0x8D, 0x06, 0x64, 
-	0x64, 0x32, 0x64, 0x37, 0xA5, 0x30, 0xE5, 0x31, 
-	0xC9, 0xC8, 0xA5, 0x39, 0x29, 0xF3, 0xB0, 0x02, 
-	0x09, 0x08, 0x8D, 0x04, 0x64, 0xA5, 0x36, 0xF0, 
-	0x08, 0xA5, 0x33, 0x85, 0x34, 0x64, 0x32, 0x64, 
-	0x36, 0x20, 0x23, 0x3A, 0xA5, 0x43, 0xF0, 0x0F, 
-	0xA5, 0x46, 0x85, 0x47, 0xA5, 0x44, 0x09, 0x10, 
-	0x8D, 0x06, 0x6C, 0x64, 0x3E, 0x64, 0x43, 0xA5, 
-	0x3C, 0xE5, 0x3D, 0xC9, 0xC8, 0xA5, 0x45, 0x29, 
-	0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x6C, 
-	0xA5, 0x42, 0xF0, 0x08, 0xA5, 0x3F, 0x85, 0x40, 
-	0x64, 0x3E, 0x64, 0x42, 0x20, 0x23, 0x3A, 0xA5, 
-	0x4F, 0xF0, 0x0F, 0xA5, 0x52, 0x85, 0x53, 0xA5, 
-	0x50, 0x09, 0x10, 0x8D, 0x06, 0x74, 0x64, 0x4A, 
-	0x64, 0x4F, 0xA5, 0x48, 0xE5, 0x49, 0xC9, 0xC8, 
-	0xA5, 0x51, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 
-	0x8D, 0x04, 0x74, 0xA5, 0x4E, 0xF0, 0x08, 0xA5, 
-	0x4B, 0x85, 0x4C, 0x64, 0x4A, 0x64, 0x4E, 0x20, 
-	0x23, 0x3A, 0x4C, 0x92, 0x38, 0xAD, 0x02, 0x44, 
-	0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 
-	0xAD, 0x00, 0x44, 0xD0, 0x32, 0xA6, 0x00, 0xA9, 
-	0x01, 0x9D, 0x00, 0x10, 0xA9, 0x01, 0x9D, 0x00, 
-	0x09, 0xE8, 0xE4, 0x01, 0xF0, 0x02, 0x86, 0x00, 
-	0x4C, 0x65, 0x3A, 0xA6, 0x00, 0xAD, 0x00, 0x44, 
-	0x9D, 0x00, 0x09, 0x9E, 0x00, 0x10, 0xE8, 0xE4, 
-	0x01, 0xF0, 0x02, 0x86, 0x00, 0x29, 0x7F, 0xC9, 
-	0x13, 0xD0, 0x04, 0xA5, 0x0B, 0x85, 0x02, 0xAD, 
-	0x02, 0x44, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x05, 
-	0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 0xD0, 
-	0x21, 0x8E, 0x00, 0x44, 0x64, 0x05, 0x4C, 0x98, 
-	0x3A, 0xA6, 0x04, 0xE4, 0x03, 0xF0, 0x13, 0xA5, 
-	0x02, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 
-	0xD0, 0x08, 0xBD, 0x00, 0x02, 0x8D, 0x00, 0x44, 
-	0xE6, 0x04, 0xAD, 0x02, 0x4C, 0x89, 0x08, 0xF0, 
-	0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x4C, 
-	0xD0, 0x32, 0xA6, 0x0C, 0xA9, 0x01, 0x9D, 0x00, 
-	0x11, 0xA9, 0x01, 0x9D, 0x00, 0x0A, 0xE8, 0xE4, 
-	0x0D, 0xF0, 0x02, 0x86, 0x0C, 0x4C, 0xDA, 0x3A, 
-	0xA6, 0x0C, 0xAD, 0x00, 0x4C, 0x9D, 0x00, 0x0A, 
-	0x9E, 0x00, 0x11, 0xE8, 0xE4, 0x0D, 0xF0, 0x02, 
-	0x86, 0x0C, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 
-	0xA5, 0x17, 0x85, 0x0E, 0xAD, 0x02, 0x4C, 0x29, 
-	0x10, 0xF0, 0x2C, 0xA6, 0x11, 0xF0, 0x0F, 0xAD, 
-	0x02, 0x7C, 0x29, 0x02, 0xD0, 0x21, 0x8E, 0x00, 
-	0x4C, 0x64, 0x11, 0x4C, 0x0D, 0x3B, 0xA6, 0x10, 
-	0xE4, 0x0F, 0xF0, 0x13, 0xA5, 0x0E, 0xD0, 0x0F, 
-	0xAD, 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x08, 0xBD, 
-	0x00, 0x03, 0x8D, 0x00, 0x4C, 0xE6, 0x10, 0xAD, 
-	0x02, 0x54, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 
-	0xF0, 0x1B, 0xAD, 0x00, 0x54, 0xD0, 0x32, 0xA6, 
-	0x18, 0xA9, 0x01, 0x9D, 0x00, 0x12, 0xA9, 0x01, 
-	0x9D, 0x00, 0x0B, 0xE8, 0xE4, 0x19, 0xF0, 0x02, 
-	0x86, 0x18, 0x4C, 0x4F, 0x3B, 0xA6, 0x18, 0xAD, 
-	0x00, 0x54, 0x9D, 0x00, 0x0B, 0x9E, 0x00, 0x12, 
-	0xE8, 0xE4, 0x19, 0xF0, 0x02, 0x86, 0x18, 0x29, 
-	0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x23, 0x85, 
-	0x1A, 0xAD, 0x02, 0x54, 0x29, 0x10, 0xF0, 0x2C, 
-	0xA6, 0x1D, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
-	0x04, 0xD0, 0x21, 0x8E, 0x00, 0x54, 0x64, 0x1D, 
-	0x4C, 0x82, 0x3B, 0xA6, 0x1C, 0xE4, 0x1B, 0xF0, 
-	0x13, 0xA5, 0x1A, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 
-	0x29, 0x04, 0xD0, 0x08, 0xBD, 0x00, 0x04, 0x8D, 
-	0x00, 0x54, 0xE6, 0x1C, 0xAD, 0x02, 0x5C, 0x89, 
-	0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 
-	0x00, 0x5C, 0xD0, 0x32, 0xA6, 0x24, 0xA9, 0x01, 
-	0x9D, 0x00, 0x13, 0xA9, 0x01, 0x9D, 0x00, 0x0C, 
-	0xE8, 0xE4, 0x25, 0xF0, 0x02, 0x86, 0x24, 0x4C, 
-	0xC4, 0x3B, 0xA6, 0x24, 0xAD, 0x00, 0x5C, 0x9D, 
-	0x00, 0x0C, 0x9E, 0x00, 0x13, 0xE8, 0xE4, 0x25, 
-	0xF0, 0x02, 0x86, 0x24, 0x29, 0x7F, 0xC9, 0x13, 
-	0xD0, 0x04, 0xA5, 0x2F, 0x85, 0x26, 0xAD, 0x02, 
-	0x5C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x29, 0xF0, 
-	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 0x21, 
-	0x8E, 0x00, 0x5C, 0x64, 0x29, 0x4C, 0xF7, 0x3B, 
-	0xA6, 0x28, 0xE4, 0x27, 0xF0, 0x13, 0xA5, 0x26, 
-	0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 
-	0x08, 0xBD, 0x00, 0x05, 0x8D, 0x00, 0x5C, 0xE6, 
-	0x28, 0xAD, 0x02, 0x64, 0x89, 0x08, 0xF0, 0x3B, 
-	0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x64, 0xD0, 
-	0x32, 0xA6, 0x30, 0xA9, 0x01, 0x9D, 0x00, 0x14, 
-	0xA9, 0x01, 0x9D, 0x00, 0x0D, 0xE8, 0xE4, 0x31, 
-	0xF0, 0x02, 0x86, 0x30, 0x4C, 0x39, 0x3C, 0xA6, 
-	0x30, 0xAD, 0x00, 0x64, 0x9D, 0x00, 0x0D, 0x9E, 
-	0x00, 0x14, 0xE8, 0xE4, 0x31, 0xF0, 0x02, 0x86, 
-	0x30, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 
-	0x3B, 0x85, 0x32, 0xAD, 0x02, 0x64, 0x29, 0x10, 
-	0xF0, 0x2C, 0xA6, 0x35, 0xF0, 0x0F, 0xAD, 0x02, 
-	0x7C, 0x29, 0x10, 0xD0, 0x21, 0x8E, 0x00, 0x64, 
-	0x64, 0x35, 0x4C, 0x6C, 0x3C, 0xA6, 0x34, 0xE4, 
-	0x33, 0xF0, 0x13, 0xA5, 0x32, 0xD0, 0x0F, 0xAD, 
-	0x02, 0x7C, 0x29, 0x10, 0xD0, 0x08, 0xBD, 0x00, 
-	0x06, 0x8D, 0x00, 0x64, 0xE6, 0x34, 0xAD, 0x02, 
-	0x6C, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 
-	0x1B, 0xAD, 0x00, 0x6C, 0xD0, 0x32, 0xA6, 0x3C, 
-	0xA9, 0x01, 0x9D, 0x00, 0x15, 0xA9, 0x01, 0x9D, 
-	0x00, 0x0E, 0xE8, 0xE4, 0x3D, 0xF0, 0x02, 0x86, 
-	0x3C, 0x4C, 0xAE, 0x3C, 0xA6, 0x3C, 0xAD, 0x00, 
-	0x6C, 0x9D, 0x00, 0x0E, 0x9E, 0x00, 0x15, 0xE8, 
-	0xE4, 0x3D, 0xF0, 0x02, 0x86, 0x3C, 0x29, 0x7F, 
-	0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x47, 0x85, 0x3E, 
-	0xAD, 0x02, 0x6C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 
-	0x41, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x20, 
-	0xD0, 0x21, 0x8E, 0x00, 0x6C, 0x64, 0x41, 0x4C, 
-	0xE1, 0x3C, 0xA6, 0x40, 0xE4, 0x3F, 0xF0, 0x13, 
-	0xA5, 0x3E, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
-	0x20, 0xD0, 0x08, 0xBD, 0x00, 0x07, 0x8D, 0x00, 
-	0x6C, 0xE6, 0x40, 0xAD, 0x02, 0x74, 0x89, 0x08, 
-	0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 
-	0x74, 0xD0, 0x32, 0xA6, 0x48, 0xA9, 0x01, 0x9D, 
-	0x00, 0x16, 0xA9, 0x01, 0x9D, 0x00, 0x0F, 0xE8, 
-	0xE4, 0x49, 0xF0, 0x02, 0x86, 0x48, 0x4C, 0x23, 
-	0x3D, 0xA6, 0x48, 0xAD, 0x00, 0x74, 0x9D, 0x00, 
-	0x0F, 0x9E, 0x00, 0x16, 0xE8, 0xE4, 0x49, 0xF0, 
-	0x02, 0x86, 0x48, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 
-	0x04, 0xA5, 0x53, 0x85, 0x4A, 0xAD, 0x02, 0x74, 
-	0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x4D, 0xF0, 0x0F, 
-	0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x21, 0x8E, 
-	0x00, 0x74, 0x64, 0x4D, 0x4C, 0x56, 0x3D, 0xA6, 
-	0x4C, 0xE4, 0x4B, 0xF0, 0x13, 0xA5, 0x4A, 0xD0, 
-	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x08, 
-	0xBD, 0x00, 0x08, 0x8D, 0x00, 0x74, 0xE6, 0x4C, 
-	0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xD0, 0x00, 0x38, 
-	0xCE, 0xC0, 
-};
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
deleted file mode 100644
index 748c3b0..0000000
--- a/drivers/char/serial167.c
+++ /dev/null
@@ -1,2490 +0,0 @@
-/*
- * linux/drivers/char/serial167.c
- *
- * Driver for MVME166/7 board serial ports, which are via a CD2401.
- * Based very much on cyclades.c.
- *
- * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * ==============================================================
- *
- * static char rcsid[] =
- * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
- *
- *  linux/kernel/cyclades.c
- *
- * Maintained by Marcio Saito (cyclades@netcom.com) and
- * Randolph Bentson (bentson@grieg.seaslug.org)
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- *
- * This version does not support shared irq's.
- *
- * $Log: cyclades.c,v $
- * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
- * disambiguate between Cyclom-16Y and Cyclom-32Ye;
- *
- * Changes:
- *
- * 200 lines of changes record removed - RGH 11-10-95, starting work on
- * converting this to drive serial ports on mvme166 (cd2401).
- *
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
- * - get rid of verify_area
- * - use get_user to access memory from userspace in set_threshold,
- *   set_default_threshold and set_timeout
- * - don't use the panic function in serial167_init
- * - do resource release on failure on serial167_init
- * - include missing restore_flags in mvme167_serial_console_setup
- *
- * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
- * - replace bottom half handler with task queue handler
- */
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/serial167.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/tty_flip.h>
-#include <linux/gfp.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mvme16xhw.h>
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include <asm/uaccess.h>
-#include <linux/init.h>
-
-#define SERIAL_PARANOIA_CHECK
-#undef  SERIAL_DEBUG_OPEN
-#undef  SERIAL_DEBUG_THROTTLE
-#undef  SERIAL_DEBUG_OTHER
-#undef  SERIAL_DEBUG_IO
-#undef  SERIAL_DEBUG_COUNT
-#undef  SERIAL_DEBUG_DTR
-#undef  CYCLOM_16Y_HACK
-#define  CYCLOM_ENABLE_MONITORING
-
-#define WAKEUP_CHARS 256
-
-#define STD_COM_FLAGS (0)
-
-static struct tty_driver *cy_serial_driver;
-extern int serial_console;
-static struct cyclades_port *serial_console_info = NULL;
-static unsigned int serial_console_cflag = 0;
-u_char initial_console_speed;
-
-/* Base address of cd2401 chip on mvme166/7 */
-
-#define BASE_ADDR (0xfff45000)
-#define pcc2chip	((volatile u_char *)0xfff42000)
-#define PccSCCMICR	0x1d
-#define PccSCCTICR	0x1e
-#define PccSCCRICR	0x1f
-#define PccTPIACKR	0x25
-#define PccRPIACKR	0x27
-#define PccIMLR		0x3f
-
-/* This is the per-port data structure */
-struct cyclades_port cy_port[] = {
-	/* CARD#  */
-	{-1},			/* ttyS0 */
-	{-1},			/* ttyS1 */
-	{-1},			/* ttyS2 */
-	{-1},			/* ttyS3 */
-};
-
-#define NR_PORTS        ARRAY_SIZE(cy_port)
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates.  The extra
- * are accessed via settings in info->flags.
- *         0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
- *        10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
- *                                                  HI            VHI
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
-	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
-	0
-};
-
-#if 0
-static char baud_co[] = {	/* 25 MHz clock option table */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
-	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static char baud_bpr[] = {	/* 25 MHz baud rate period table */
-	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
-	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-#endif
-
-/* I think 166 brd clocks 2401 at 20MHz.... */
-
-/* These values are written directly to tcor, and >> 5 for writing to rcor */
-static u_char baud_co[] = {	/* 20 MHz clock option table */
-	0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
-	0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* These values written directly to tbpr/rbpr */
-static u_char baud_bpr[] = {	/* 20 MHz baud rate period table */
-	0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
-	0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
-};
-
-static u_char baud_cor4[] = {	/* receive threshold */
-	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
-};
-
-static void shutdown(struct cyclades_port *);
-static int startup(struct cyclades_port *);
-static void cy_throttle(struct tty_struct *);
-static void cy_unthrottle(struct tty_struct *);
-static void config_setup(struct cyclades_port *);
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int);
-#endif
-
-/*
- * I have my own version of udelay(), as it is needed when initialising
- * the chip, before the delay loop has been calibrated.  Should probably
- * reference one of the vmechip2 or pccchip2 counter for an accurate
- * delay, but this wild guess will do for now.
- */
-
-void my_udelay(long us)
-{
-	u_char x;
-	volatile u_char *p = &x;
-	int i;
-
-	while (us--)
-		for (i = 100; i; i--)
-			x |= *p;
-}
-
-static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
-		const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	if (!info) {
-		printk("Warning: null cyclades_port for (%s) in %s\n", name,
-				routine);
-		return 1;
-	}
-
-	if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
-		printk("Warning: cyclades_port out of range for (%s) in %s\n",
-				name, routine);
-		return 1;
-	}
-
-	if (info->magic != CYCLADES_MAGIC) {
-		printk("Warning: bad magic number for serial struct (%s) in "
-				"%s\n", name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}				/* serial_paranoia_check */
-
-#if 0
-/* The following diagnostic routines allow the driver to spew
-   information on the screen, even (especially!) during interrupts.
- */
-void SP(char *data)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	printk(KERN_EMERG "%s", data);
-	local_irq_restore(flags);
-}
-
-char scrn[2];
-void CP(char data)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	scrn[0] = data;
-	printk(KERN_EMERG "%c", scrn);
-	local_irq_restore(flags);
-}				/* CP */
-
-void CP1(int data)
-{
-	(data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
-}				/* CP1 */
-void CP2(int data)
-{
-	CP1((data >> 4) & 0x0f);
-	CP1(data & 0x0f);
-}				/* CP2 */
-void CP4(int data)
-{
-	CP2((data >> 8) & 0xff);
-	CP2(data & 0xff);
-}				/* CP4 */
-void CP8(long data)
-{
-	CP4((data >> 16) & 0xffff);
-	CP4(data & 0xffff);
-}				/* CP8 */
-#endif
-
-/* This routine waits up to 1000 micro-seconds for the previous
-   command to the Cirrus chip to complete and then issues the
-   new command.  An error is returned if the previous command
-   didn't finish within the time limit.
- */
-u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
-{
-	unsigned long flags;
-	volatile int i;
-
-	local_irq_save(flags);
-	/* Check to see that the previous command has completed */
-	for (i = 0; i < 100; i++) {
-		if (base_addr[CyCCR] == 0) {
-			break;
-		}
-		my_udelay(10L);
-	}
-	/* if the CCR never cleared, the previous command
-	   didn't finish within the "reasonable time" */
-	if (i == 10) {
-		local_irq_restore(flags);
-		return (-1);
-	}
-
-	/* Issue the new command */
-	base_addr[CyCCR] = cmd;
-	local_irq_restore(flags);
-	return (0);
-}				/* write_cy_cmd */
-
-/* cy_start and cy_stop provide software output flow control as a
-   function of XON/XOFF, software CTS, and other such stuff. */
-
-static void cy_stop(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_stop %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_stop"))
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) (channel);	/* index channel */
-	base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-	local_irq_restore(flags);
-}				/* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_start %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_start"))
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) (channel);
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* cy_start */
-
-/* The real interrupt service routines are called
-   whenever the card wants its hand held--chars
-   received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
-{
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	unsigned char err, rfoc;
-	int channel;
-	char data;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-
-	if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
-		/* This is a receive timeout interrupt, ignore it */
-		base_addr[CyREOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-
-	/* Read a byte of data if there is any - assume the error
-	 * is associated with this character */
-
-	if ((rfoc = base_addr[CyRFOC]) != 0)
-		data = base_addr[CyRDR];
-	else
-		data = 0;
-
-	/* if there is nowhere to put the data, discard it */
-	if (info->tty == 0) {
-		base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-		return IRQ_HANDLED;
-	} else {		/* there is an open port for this data */
-		tty = info->tty;
-		if (err & info->ignore_status_mask) {
-			base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-			return IRQ_HANDLED;
-		}
-		if (tty_buffer_request_room(tty, 1) != 0) {
-			if (err & info->read_status_mask) {
-				if (err & CyBREAK) {
-					tty_insert_flip_char(tty, data,
-							     TTY_BREAK);
-					if (info->flags & ASYNC_SAK) {
-						do_SAK(tty);
-					}
-				} else if (err & CyFRAME) {
-					tty_insert_flip_char(tty, data,
-							     TTY_FRAME);
-				} else if (err & CyPARITY) {
-					tty_insert_flip_char(tty, data,
-							     TTY_PARITY);
-				} else if (err & CyOVERRUN) {
-					tty_insert_flip_char(tty, 0,
-							     TTY_OVERRUN);
-					/*
-					   If the flip buffer itself is
-					   overflowing, we still lose
-					   the next incoming character.
-					 */
-					if (tty_buffer_request_room(tty, 1) !=
-					    0) {
-						tty_insert_flip_char(tty, data,
-								     TTY_FRAME);
-					}
-					/* These two conditions may imply */
-					/* a normal read should be done. */
-					/* else if(data & CyTIMEOUT) */
-					/* else if(data & CySPECHAR) */
-				} else {
-					tty_insert_flip_char(tty, 0,
-							     TTY_NORMAL);
-				}
-			} else {
-				tty_insert_flip_char(tty, data, TTY_NORMAL);
-			}
-		} else {
-			/* there was a software buffer overrun
-			   and nothing could be done about it!!! */
-		}
-	}
-	tty_schedule_flip(tty);
-	/* end of service */
-	base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_rxerr_interrupt */
-
-static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	int mdm_change;
-	int mdm_status;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-
-	mdm_change = base_addr[CyMISR];
-	mdm_status = base_addr[CyMSVR1];
-
-	if (info->tty == 0) {	/* nowhere to put the data, ignore it */
-		;
-	} else {
-		if ((mdm_change & CyDCD)
-		    && (info->flags & ASYNC_CHECK_CD)) {
-			if (mdm_status & CyDCD) {
-/* CP('!'); */
-				wake_up_interruptible(&info->open_wait);
-			} else {
-/* CP('@'); */
-				tty_hangup(info->tty);
-				wake_up_interruptible(&info->open_wait);
-				info->flags &= ~ASYNC_NORMAL_ACTIVE;
-			}
-		}
-		if ((mdm_change & CyCTS)
-		    && (info->flags & ASYNC_CTS_FLOW)) {
-			if (info->tty->stopped) {
-				if (mdm_status & CyCTS) {
-					/* !!! cy_start isn't used because... */
-					info->tty->stopped = 0;
-					base_addr[CyIER] |= CyTxMpty;
-					tty_wakeup(info->tty);
-				}
-			} else {
-				if (!(mdm_status & CyCTS)) {
-					/* !!! cy_stop isn't used because... */
-					info->tty->stopped = 1;
-					base_addr[CyIER] &=
-					    ~(CyTxMpty | CyTxRdy);
-				}
-			}
-		}
-		if (mdm_status & CyDSR) {
-		}
-	}
-	base_addr[CyMEOIR] = 0;
-	return IRQ_HANDLED;
-}				/* cy_modem_interrupt */
-
-static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	int char_count, saved_cnt;
-	int outch;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-
-	/* validate the port number (as configured and open) */
-	if ((channel < 0) || (NR_PORTS <= channel)) {
-		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-		base_addr[CyTEOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-	if (info->tty == 0) {
-		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-		base_addr[CyTEOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-
-	/* load the on-chip space available for outbound data */
-	saved_cnt = char_count = base_addr[CyTFTC];
-
-	if (info->x_char) {	/* send special char */
-		outch = info->x_char;
-		base_addr[CyTDR] = outch;
-		char_count--;
-		info->x_char = 0;
-	}
-
-	if (info->x_break) {
-		/*  The Cirrus chip requires the "Embedded Transmit
-		   Commands" of start break, delay, and end break
-		   sequences to be sent.  The duration of the
-		   break is given in TICs, which runs at HZ
-		   (typically 100) and the PPR runs at 200 Hz,
-		   so the delay is duration * 200/HZ, and thus a
-		   break can run from 1/100 sec to about 5/4 sec.
-		   Need to check these values - RGH 141095.
-		 */
-		base_addr[CyTDR] = 0;	/* start break */
-		base_addr[CyTDR] = 0x81;
-		base_addr[CyTDR] = 0;	/* delay a bit */
-		base_addr[CyTDR] = 0x82;
-		base_addr[CyTDR] = info->x_break * 200 / HZ;
-		base_addr[CyTDR] = 0;	/* terminate break */
-		base_addr[CyTDR] = 0x83;
-		char_count -= 7;
-		info->x_break = 0;
-	}
-
-	while (char_count > 0) {
-		if (!info->xmit_cnt) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		if (info->xmit_buf == 0) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		if (info->tty->stopped || info->tty->hw_stopped) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		/* Because the Embedded Transmit Commands have been
-		   enabled, we must check to see if the escape
-		   character, NULL, is being sent.  If it is, we
-		   must ensure that there is room for it to be
-		   doubled in the output stream.  Therefore we
-		   no longer advance the pointer when the character
-		   is fetched, but rather wait until after the check
-		   for a NULL output character. (This is necessary
-		   because there may not be room for the two chars
-		   needed to send a NULL.
-		 */
-		outch = info->xmit_buf[info->xmit_tail];
-		if (outch) {
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1)
-			    & (PAGE_SIZE - 1);
-			base_addr[CyTDR] = outch;
-			char_count--;
-		} else {
-			if (char_count > 1) {
-				info->xmit_cnt--;
-				info->xmit_tail = (info->xmit_tail + 1)
-				    & (PAGE_SIZE - 1);
-				base_addr[CyTDR] = outch;
-				base_addr[CyTDR] = 0;
-				char_count--;
-				char_count--;
-			} else {
-				break;
-			}
-		}
-	}
-
-	if (info->xmit_cnt < WAKEUP_CHARS)
-		tty_wakeup(info->tty);
-
-	base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_tx_interrupt */
-
-static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
-{
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	char data;
-	int char_count;
-	int save_cnt;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-	save_cnt = char_count = base_addr[CyRFOC];
-
-		/* if there is nowhere to put the data, discard it */
-	if (info->tty == 0) {
-		while (char_count--) {
-			data = base_addr[CyRDR];
-		}
-	} else {		/* there is an open port for this data */
-		tty = info->tty;
-		/* load # characters available from the chip */
-
-#ifdef CYCLOM_ENABLE_MONITORING
-		++info->mon.int_count;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		while (char_count--) {
-			data = base_addr[CyRDR];
-			tty_insert_flip_char(tty, data, TTY_NORMAL);
-#ifdef CYCLOM_16Y_HACK
-			udelay(10L);
-#endif
-		}
-		tty_schedule_flip(tty);
-	}
-	/* end of service */
-	base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_rx_interrupt */
-
-/* This is called whenever a port becomes active;
-   interrupts are enabled and DTR & RTS are turned on.
- */
-static int startup(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		return 0;
-	}
-
-	if (!info->type) {
-		if (info->tty) {
-			set_bit(TTY_IO_ERROR, &info->tty->flags);
-		}
-		return 0;
-	}
-	if (!info->xmit_buf) {
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-		if (!info->xmit_buf) {
-			return -ENOMEM;
-		}
-	}
-
-	config_setup(info);
-
-	channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("startup channel %d\n", channel);
-#endif
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
-	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
-	base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('1'); */
-	base_addr[CyMSVR2] = CyDTR;
-
-#ifdef SERIAL_DEBUG_DTR
-	printk("cyc: %d: raising DTR\n", __LINE__);
-	printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-	       base_addr[CyMSVR2]);
-#endif
-
-	base_addr[CyIER] |= CyRxData;
-	info->flags |= ASYNC_INITIALIZED;
-
-	if (info->tty) {
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(" done\n");
-#endif
-	return 0;
-}				/* startup */
-
-void start_xmit(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-	channel = info->line;
-	local_irq_save(flags);
-	base_addr[CyCAR] = channel;
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-	if (!(info->flags & ASYNC_INITIALIZED)) {
-/* CP('$'); */
-		return;
-	}
-
-	channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("shutdown channel %d\n", channel);
-#endif
-
-	/* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
-	   SENT BEFORE DROPPING THE LINE !!!  (Perhaps
-	   set some flag that is read when XMTY happens.)
-	   Other choices are to delay some fixed interval
-	   or schedule some later processing.
-	 */
-	local_irq_save(flags);
-	if (info->xmit_buf) {
-		free_page((unsigned long)info->xmit_buf);
-		info->xmit_buf = NULL;
-	}
-
-	base_addr[CyCAR] = (u_char) channel;
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		base_addr[CyMSVR1] = 0;
-/* CP('C');CP('1'); */
-		base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	}
-	write_cy_cmd(base_addr, CyDIS_RCVR);
-	/* it may be appropriate to clear _XMIT at
-	   some later date (after testing)!!! */
-
-	if (info->tty) {
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-	info->flags &= ~ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(" done\n");
-#endif
-}				/* shutdown */
-
-/*
- * This routine finds or computes the various line characteristics.
- */
-static void config_setup(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned cflag;
-	int i;
-	unsigned char ti, need_init_chan = 0;
-
-	if (!info->tty || !info->tty->termios) {
-		return;
-	}
-	if (info->line == -1) {
-		return;
-	}
-	cflag = info->tty->termios->c_cflag;
-
-	/* baud rate */
-	i = cflag & CBAUD;
-#ifdef CBAUDEX
-/* Starting with kernel 1.1.65, there is direct support for
-   higher baud rates.  The following code supports those
-   changes.  The conditional aspect allows this driver to be
-   used for earlier as well as later kernel versions.  (The
-   mapping is slightly different from serial.c because there
-   is still the possibility of supporting 75 kbit/sec with
-   the Cyclades board.)
- */
-	if (i & CBAUDEX) {
-		if (i == B57600)
-			i = 16;
-		else if (i == B115200)
-			i = 18;
-#ifdef B78600
-		else if (i == B78600)
-			i = 17;
-#endif
-		else
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-	}
-#endif
-	if (i == 15) {
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			i += 1;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			i += 3;
-	}
-	/* Don't ever change the speed of the console port.  It will
-	 * run at the speed specified in bootinfo, or at 19.2K */
-	/* Actually, it should run at whatever speed 166Bug was using */
-	/* Note info->timeout isn't used at present */
-	if (info != serial_console_info) {
-		info->tbpr = baud_bpr[i];	/* Tx BPR */
-		info->tco = baud_co[i];	/* Tx CO */
-		info->rbpr = baud_bpr[i];	/* Rx BPR */
-		info->rco = baud_co[i] >> 5;	/* Rx CO */
-		if (baud_table[i] == 134) {
-			info->timeout =
-			    (info->xmit_fifo_size * HZ * 30 / 269) + 2;
-			/* get it right for 134.5 baud */
-		} else if (baud_table[i]) {
-			info->timeout =
-			    (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
-			    2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-	}
-	/* By tradition (is it a standard?) a baud rate of zero
-	   implies the line should be/has been closed.  A bit
-	   later in this routine such a test is performed. */
-
-	/* byte size and parity */
-	info->cor7 = 0;
-	info->cor6 = 0;
-	info->cor5 = 0;
-	info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]);	/* receive threshold */
-	/* Following two lines added 101295, RGH. */
-	/* It is obviously wrong to access CyCORx, and not info->corx here,
-	 * try and remember to fix it later! */
-	channel = info->line;
-	base_addr[CyCAR] = (u_char) channel;
-	if (C_CLOCAL(info->tty)) {
-		if (base_addr[CyIER] & CyMdmCh)
-			base_addr[CyIER] &= ~CyMdmCh;	/* without modem intr */
-		/* ignore 1->0 modem transitions */
-		if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
-		/* ignore 0->1 modem transitions */
-		if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
-	} else {
-		if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
-			base_addr[CyIER] |= CyMdmCh;	/* with modem intr */
-		/* act on 1->0 modem transitions */
-		if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
-		    (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
-		/* act on 0->1 modem transitions */
-		if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
-		    (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
-	}
-	info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
-	info->cor2 = CyETC;
-	switch (cflag & CSIZE) {
-	case CS5:
-		info->cor1 = Cy_5_BITS;
-		break;
-	case CS6:
-		info->cor1 = Cy_6_BITS;
-		break;
-	case CS7:
-		info->cor1 = Cy_7_BITS;
-		break;
-	case CS8:
-		info->cor1 = Cy_8_BITS;
-		break;
-	}
-	if (cflag & PARENB) {
-		if (cflag & PARODD) {
-			info->cor1 |= CyPARITY_O;
-		} else {
-			info->cor1 |= CyPARITY_E;
-		}
-	} else {
-		info->cor1 |= CyPARITY_NONE;
-	}
-
-	/* CTS flow control flag */
-#if 0
-	/* Don't complcate matters for now! RGH 141095 */
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->cor2 |= CyCtsAE;
-	} else {
-		info->flags &= ~ASYNC_CTS_FLOW;
-		info->cor2 &= ~CyCtsAE;
-	}
-#endif
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else
-		info->flags |= ASYNC_CHECK_CD;
-
-     /***********************************************
-	The hardware option, CyRtsAO, presents RTS when
-	the chip has characters to send.  Since most modems
-	use RTS as reverse (inbound) flow control, this
-	option is not used.  If inbound flow control is
-	necessary, DTR can be programmed to provide the
-	appropriate signals for use with a non-standard
-	cable.  Contact Marcio Saito for details.
-     ***********************************************/
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-
-	/* CyCMR set once only in mvme167_init_serial() */
-	if (base_addr[CyLICR] != channel << 2)
-		base_addr[CyLICR] = channel << 2;
-	if (base_addr[CyLIVR] != 0x5c)
-		base_addr[CyLIVR] = 0x5c;
-
-	/* tx and rx baud rate */
-
-	if (base_addr[CyCOR1] != info->cor1)
-		need_init_chan = 1;
-	if (base_addr[CyTCOR] != info->tco)
-		base_addr[CyTCOR] = info->tco;
-	if (base_addr[CyTBPR] != info->tbpr)
-		base_addr[CyTBPR] = info->tbpr;
-	if (base_addr[CyRCOR] != info->rco)
-		base_addr[CyRCOR] = info->rco;
-	if (base_addr[CyRBPR] != info->rbpr)
-		base_addr[CyRBPR] = info->rbpr;
-
-	/* set line characteristics  according configuration */
-
-	if (base_addr[CySCHR1] != START_CHAR(info->tty))
-		base_addr[CySCHR1] = START_CHAR(info->tty);
-	if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
-		base_addr[CySCHR2] = STOP_CHAR(info->tty);
-	if (base_addr[CySCRL] != START_CHAR(info->tty))
-		base_addr[CySCRL] = START_CHAR(info->tty);
-	if (base_addr[CySCRH] != START_CHAR(info->tty))
-		base_addr[CySCRH] = START_CHAR(info->tty);
-	if (base_addr[CyCOR1] != info->cor1)
-		base_addr[CyCOR1] = info->cor1;
-	if (base_addr[CyCOR2] != info->cor2)
-		base_addr[CyCOR2] = info->cor2;
-	if (base_addr[CyCOR3] != info->cor3)
-		base_addr[CyCOR3] = info->cor3;
-	if (base_addr[CyCOR4] != info->cor4)
-		base_addr[CyCOR4] = info->cor4;
-	if (base_addr[CyCOR5] != info->cor5)
-		base_addr[CyCOR5] = info->cor5;
-	if (base_addr[CyCOR6] != info->cor6)
-		base_addr[CyCOR6] = info->cor6;
-	if (base_addr[CyCOR7] != info->cor7)
-		base_addr[CyCOR7] = info->cor7;
-
-	if (need_init_chan)
-		write_cy_cmd(base_addr, CyINIT_CHAN);
-
-	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
-
-	/* 2ms default rx timeout */
-	ti = info->default_timeout ? info->default_timeout : 0x02;
-	if (base_addr[CyRTPRL] != ti)
-		base_addr[CyRTPRL] = ti;
-	if (base_addr[CyRTPRH] != 0)
-		base_addr[CyRTPRH] = 0;
-
-	/* Set up RTS here also ????? RGH 141095 */
-	if (i == 0) {		/* baud rate is zero, turn off line */
-		if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
-			base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	} else {
-		if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
-			base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	}
-
-	if (info->tty) {
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-
-	local_irq_restore(flags);
-
-}				/* config_setup */
-
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	local_irq_save(flags);
-	if (info->xmit_cnt >= PAGE_SIZE - 1) {
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	info->xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= PAGE_SIZE - 1;
-	info->xmit_cnt++;
-	local_irq_restore(flags);
-	return 1;
-}				/* cy_put_char */
-
-static void cy_flush_chars(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_flush_chars %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped
-	    || tty->hw_stopped || !info->xmit_buf)
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = channel;
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* cy_flush_chars */
-
-/* This routine gets called when tty_write has put something into
-    the write_queue.  If the port is not already transmitting stuff,
-    start it off by enabling interrupts.  The interrupt service
-    routine will then ensure that the characters are sent.  If the
-    port is already active, there is no need to kick it.
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	int c, total = 0;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_write %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write")) {
-		return 0;
-	}
-
-	if (!info->xmit_buf) {
-		return 0;
-	}
-
-	while (1) {
-		local_irq_save(flags);
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0) {
-			local_irq_restore(flags);
-			break;
-		}
-
-		memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head =
-		    (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		local_irq_restore(flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
-		start_xmit(info);
-	}
-	return total;
-}				/* cy_write */
-
-static int cy_write_room(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_write_room %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-		return 0;
-	ret = PAGE_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}				/* cy_write_room */
-
-static int cy_chars_in_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-		return 0;
-
-	return info->xmit_cnt;
-}				/* cy_chars_in_buffer */
-
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_flush_buffer %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-		return;
-	local_irq_save(flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	local_irq_restore(flags);
-	tty_wakeup(tty);
-}				/* cy_flush_buffer */
-
-/* This routine is called by the upper-layer tty layer to signal
-   that incoming characters should be throttled or that the
-   throttle should be released.
- */
-static void cy_throttle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_THROTTLE
-	char buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-	printk("cy_throttle %s\n", tty->name);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
-		return;
-	}
-
-	if (I_IXOFF(tty)) {
-		info->x_char = STOP_CHAR(tty);
-		/* Should use the "Send Special Character" feature!!! */
-	}
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	base_addr[CyMSVR1] = 0;
-	local_irq_restore(flags);
-}				/* cy_throttle */
-
-static void cy_unthrottle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_THROTTLE
-	char buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-	printk("cy_unthrottle %s\n", tty->name);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
-		return;
-	}
-
-	if (I_IXOFF(tty)) {
-		info->x_char = START_CHAR(tty);
-		/* Should use the "Send Special Character" feature!!! */
-	}
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	base_addr[CyMSVR1] = CyRTS;
-	local_irq_restore(flags);
-}				/* cy_unthrottle */
-
-static int
-get_serial_info(struct cyclades_port *info,
-		struct serial_struct __user * retinfo)
-{
-	struct serial_struct tmp;
-
-/* CP('g'); */
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = info->type;
-	tmp.line = info->line;
-	tmp.port = info->line;
-	tmp.irq = 0;
-	tmp.flags = info->flags;
-	tmp.baud_base = 0;	/*!!! */
-	tmp.close_delay = info->close_delay;
-	tmp.custom_divisor = 0;	/*!!! */
-	tmp.hub6 = 0;		/*!!! */
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}				/* get_serial_info */
-
-static int
-set_serial_info(struct cyclades_port *info,
-		struct serial_struct __user * new_info)
-{
-	struct serial_struct new_serial;
-	struct cyclades_port old_info;
-
-/* CP('s'); */
-	if (!new_info)
-		return -EFAULT;
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-	old_info = *info;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.close_delay != info->close_delay) ||
-		    ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
-		     (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	info->flags = ((info->flags & ~ASYNC_FLAGS) |
-		       (new_serial.flags & ASYNC_FLAGS));
-	info->close_delay = new_serial.close_delay;
-
-check_and_exit:
-	if (info->flags & ASYNC_INITIALIZED) {
-		config_setup(info);
-		return 0;
-	}
-	return startup(info);
-}				/* set_serial_info */
-
-static int cy_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-	unsigned char status;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
-	local_irq_restore(flags);
-
-	return ((status & CyRTS) ? TIOCM_RTS : 0)
-	    | ((status & CyDTR) ? TIOCM_DTR : 0)
-	    | ((status & CyDCD) ? TIOCM_CAR : 0)
-	    | ((status & CyDSR) ? TIOCM_DSR : 0)
-	    | ((status & CyCTS) ? TIOCM_CTS : 0);
-}				/* cy_tiocmget */
-
-static int
-cy_tiocmset(struct tty_struct *tty, struct file *file,
-	    unsigned int set, unsigned int clear)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-
-	channel = info->line;
-
-	if (set & TIOCM_RTS) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = CyRTS;
-		local_irq_restore(flags);
-	}
-	if (set & TIOCM_DTR) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('S');CP('2'); */
-		base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-	}
-
-	if (clear & TIOCM_RTS) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = 0;
-		local_irq_restore(flags);
-	}
-	if (clear & TIOCM_DTR) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('C');CP('2'); */
-		base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-	}
-
-	return 0;
-}				/* set_modem_info */
-
-static void send_break(struct cyclades_port *info, int duration)
-{				/* Let the transmit ISR take care of this (since it
-				   requires stuffing characters into the output stream).
-				 */
-	info->x_break = duration;
-	if (!info->xmit_cnt) {
-		start_xmit(info);
-	}
-}				/* send_break */
-
-static int
-get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
-{
-
-	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
-		return -EFAULT;
-	info->mon.int_count = 0;
-	info->mon.char_count = 0;
-	info->mon.char_max = 0;
-	info->mon.char_last = 0;
-	return 0;
-}
-
-static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long value;
-	int channel;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	channel = info->line;
-	info->cor4 &= ~CyREC_FIFO;
-	info->cor4 |= value & CyREC_FIFO;
-	base_addr[CyCOR4] = info->cor4;
-	return 0;
-}
-
-static int
-get_threshold(struct cyclades_port *info, unsigned long __user * value)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long tmp;
-
-	channel = info->line;
-
-	tmp = base_addr[CyCOR4] & CyREC_FIFO;
-	return put_user(tmp, value);
-}
-
-static int
-set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
-{
-	unsigned long value;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	info->default_threshold = value & 0x0f;
-	return 0;
-}
-
-static int
-get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
-{
-	return put_user(info->default_threshold, value);
-}
-
-static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long value;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	channel = info->line;
-
-	base_addr[CyRTPRL] = value & 0xff;
-	base_addr[CyRTPRH] = (value >> 8) & 0xff;
-	return 0;
-}
-
-static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long tmp;
-
-	channel = info->line;
-
-	tmp = base_addr[CyRTPRL];
-	return put_user(tmp, value);
-}
-
-static int set_default_timeout(struct cyclades_port *info, unsigned long value)
-{
-	info->default_timeout = value & 0xff;
-	return 0;
-}
-
-static int
-get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
-{
-	return put_user(info->default_timeout, value);
-}
-
-static int
-cy_ioctl(struct tty_struct *tty, struct file *file,
-	 unsigned int cmd, unsigned long arg)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret_val = 0;
-	void __user *argp = (void __user *)arg;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);	/* */
-#endif
-
-	tty_lock();
-
-	switch (cmd) {
-	case CYGETMON:
-		ret_val = get_mon_info(info, argp);
-		break;
-	case CYGETTHRESH:
-		ret_val = get_threshold(info, argp);
-		break;
-	case CYSETTHRESH:
-		ret_val = set_threshold(info, argp);
-		break;
-	case CYGETDEFTHRESH:
-		ret_val = get_default_threshold(info, argp);
-		break;
-	case CYSETDEFTHRESH:
-		ret_val = set_default_threshold(info, argp);
-		break;
-	case CYGETTIMEOUT:
-		ret_val = get_timeout(info, argp);
-		break;
-	case CYSETTIMEOUT:
-		ret_val = set_timeout(info, argp);
-		break;
-	case CYGETDEFTIMEOUT:
-		ret_val = get_default_timeout(info, argp);
-		break;
-	case CYSETDEFTIMEOUT:
-		ret_val = set_default_timeout(info, (unsigned long)arg);
-		break;
-	case TCSBRK:		/* SVID version: non-zero arg --> no break */
-		ret_val = tty_check_change(tty);
-		if (ret_val)
-			break;
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			send_break(info, HZ / 4);	/* 1/4 second */
-		break;
-	case TCSBRKP:		/* support for POSIX tcsendbreak() */
-		ret_val = tty_check_change(tty);
-		if (ret_val)
-			break;
-		tty_wait_until_sent(tty, 0);
-		send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
-		break;
-
-/* The following commands are incompletely implemented!!! */
-	case TIOCGSERIAL:
-		ret_val = get_serial_info(info, argp);
-		break;
-	case TIOCSSERIAL:
-		ret_val = set_serial_info(info, argp);
-		break;
-	default:
-		ret_val = -ENOIOCTLCMD;
-	}
-	tty_unlock();
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_ioctl done\n");
-#endif
-
-	return ret_val;
-}				/* cy_ioctl */
-
-static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_set_termios %s\n", tty->name);
-#endif
-
-	if (tty->termios->c_cflag == old_termios->c_cflag)
-		return;
-	config_setup(info);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->stopped = 0;
-		cy_start(tty);
-	}
-#ifdef tytso_patch_94Nov25_1726
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}				/* cy_set_termios */
-
-static void cy_close(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-/* CP('C'); */
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_close %s\n", tty->name);
-#endif
-
-	if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
-		return;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_close %s, count = %d\n", tty->name, info->count);
-#endif
-
-	if ((tty->count == 1) && (info->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Info->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("cy_close: bad serial port count; tty->count is 1, "
-		       "info->count is %d\n", info->count);
-		info->count = 1;
-	}
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: decrementing count to %d\n", __LINE__,
-	       info->count - 1);
-#endif
-	if (--info->count < 0) {
-		printk("cy_close: bad serial port count for ttys%d: %d\n",
-		       info->line, info->count);
-#ifdef SERIAL_DEBUG_COUNT
-		printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-		info->count = 0;
-	}
-	if (info->count)
-		return;
-	info->flags |= ASYNC_CLOSING;
-	if (info->flags & ASYNC_INITIALIZED)
-		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
-	shutdown(info);
-	cy_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	info->tty = NULL;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			msleep_interruptible(jiffies_to_msecs
-					     (info->close_delay));
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_close done\n");
-#endif
-}				/* cy_close */
-
-/*
- * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void cy_hangup(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_hangup %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-		return;
-
-	shutdown(info);
-#if 0
-	info->event = 0;
-	info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-	info->tty = 0;
-#endif
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-	wake_up_interruptible(&info->open_wait);
-}				/* cy_hangup */
-
-/*
- * ------------------------------------------------------------
- * cy_open() and friends
- * ------------------------------------------------------------
- */
-
-static int
-block_til_ready(struct tty_struct *tty, struct file *filp,
-		struct cyclades_port *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int channel;
-	int retval;
-	volatile u_char *base_addr = (u_char *) BASE_ADDR;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (info->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&info->close_wait);
-		if (info->flags & ASYNC_HUP_NOTIFY) {
-			return -EAGAIN;
-		} else {
-			return -ERESTARTSYS;
-		}
-	}
-
-	/*
-	 * If non-blocking mode is set, then make the check up front
-	 * and then exit.
-	 */
-	if (filp->f_flags & O_NONBLOCK) {
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * cy_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: %s, count = %d\n",
-	       tty->name, info->count);
-	/**/
-#endif
-	    info->count--;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
-#endif
-	info->blocked_open++;
-
-	channel = info->line;
-
-	while (1) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('4'); */
-		base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp)
-		    || !(info->flags & ASYNC_INITIALIZED)) {
-			if (info->flags & ASYNC_HUP_NOTIFY) {
-				retval = -EAGAIN;
-			} else {
-				retval = -ERESTARTSYS;
-			}
-			break;
-		}
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
-		if (!(info->flags & ASYNC_CLOSING)
-		    && (C_CLOCAL(tty)
-			|| (base_addr[CyMSVR1] & CyDCD))) {
-			local_irq_restore(flags);
-			break;
-		}
-		local_irq_restore(flags);
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: %s, count = %d\n",
-		       tty->name, info->count);
-		/**/
-#endif
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-	if (!tty_hung_up_p(filp)) {
-		info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-		printk("cyc: %d: incrementing count to %d\n", __LINE__,
-		       info->count);
-#endif
-	}
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: %s, count = %d\n",
-	       tty->name, info->count);
-	/**/
-#endif
-	    if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}				/* block_til_ready */
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * performs the serial-specific initialization for the tty structure.
- */
-int cy_open(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info;
-	int retval, line;
-
-/* CP('O'); */
-	line = tty->index;
-	if ((line < 0) || (NR_PORTS <= line)) {
-		return -ENODEV;
-	}
-	info = &cy_port[line];
-	if (info->line < 0) {
-		return -ENODEV;
-	}
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_open %s\n", tty->name);	/* */
-#endif
-	if (serial_paranoia_check(info, tty->name, "cy_open")) {
-		return -ENODEV;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open %s, count = %d\n", tty->name, info->count);
-	/**/
-#endif
-	    info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
-#endif
-	tty->driver_data = info;
-	info->tty = tty;
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval) {
-		return retval;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("cy_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open done\n");
-	/**/
-#endif
-	    return 0;
-}				/* cy_open */
-
-/*
- * ---------------------------------------------------------------------
- * serial167_init() and friends
- *
- * serial167_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static void show_version(void)
-{
-	printk("MVME166/167 cd2401 driver\n");
-}				/* show_version */
-
-/* initialize chips on card -- return number of valid
-   chips (which is number of ports/4) */
-
-/*
- * This initialises the hardware to a reasonable state.  It should
- * probe the chip first so as to copy 166-Bug setup as a default for
- * port 0.  It initialises CMR to CyASYNC; that is never done again, so
- * as to limit the number of CyINIT_CHAN commands in normal running.
- *
- * ... I wonder what I should do if this fails ...
- */
-
-void mvme167_serial_console_setup(int cflag)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int ch;
-	u_char spd;
-	u_char rcor, rbpr, badspeed = 0;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	/*
-	 * First probe channel zero of the chip, to see what speed has
-	 * been selected.
-	 */
-
-	base_addr[CyCAR] = 0;
-
-	rcor = base_addr[CyRCOR] << 5;
-	rbpr = base_addr[CyRBPR];
-
-	for (spd = 0; spd < sizeof(baud_bpr); spd++)
-		if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
-			break;
-	if (spd >= sizeof(baud_bpr)) {
-		spd = 14;	/* 19200 */
-		badspeed = 1;	/* Failed to identify speed */
-	}
-	initial_console_speed = spd;
-
-	/* OK, we have chosen a speed, now reset and reinitialise */
-
-	my_udelay(20000L);	/* Allow time for any active o/p to complete */
-	if (base_addr[CyCCR] != 0x00) {
-		local_irq_restore(flags);
-		/* printk(" chip is never idle (CCR != 0)\n"); */
-		return;
-	}
-
-	base_addr[CyCCR] = CyCHIP_RESET;	/* Reset the chip */
-	my_udelay(1000L);
-
-	if (base_addr[CyGFRCR] == 0x00) {
-		local_irq_restore(flags);
-		/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
-		return;
-	}
-
-	/*
-	 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
-	 * tick
-	 */
-
-	base_addr[CyTPR] = 10;
-
-	base_addr[CyPILR1] = 0x01;	/* Interrupt level for modem change */
-	base_addr[CyPILR2] = 0x02;	/* Interrupt level for tx ints */
-	base_addr[CyPILR3] = 0x03;	/* Interrupt level for rx ints */
-
-	/*
-	 * Attempt to set up all channels to something reasonable, and
-	 * bang out a INIT_CHAN command.  We should then be able to limit
-	 * the amount of fiddling we have to do in normal running.
-	 */
-
-	for (ch = 3; ch >= 0; ch--) {
-		base_addr[CyCAR] = (u_char) ch;
-		base_addr[CyIER] = 0;
-		base_addr[CyCMR] = CyASYNC;
-		base_addr[CyLICR] = (u_char) ch << 2;
-		base_addr[CyLIVR] = 0x5c;
-		base_addr[CyTCOR] = baud_co[spd];
-		base_addr[CyTBPR] = baud_bpr[spd];
-		base_addr[CyRCOR] = baud_co[spd] >> 5;
-		base_addr[CyRBPR] = baud_bpr[spd];
-		base_addr[CySCHR1] = 'Q' & 0x1f;
-		base_addr[CySCHR2] = 'X' & 0x1f;
-		base_addr[CySCRL] = 0;
-		base_addr[CySCRH] = 0;
-		base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
-		base_addr[CyCOR2] = 0;
-		base_addr[CyCOR3] = Cy_1_STOP;
-		base_addr[CyCOR4] = baud_cor4[spd];
-		base_addr[CyCOR5] = 0;
-		base_addr[CyCOR6] = 0;
-		base_addr[CyCOR7] = 0;
-		base_addr[CyRTPRL] = 2;
-		base_addr[CyRTPRH] = 0;
-		base_addr[CyMSVR1] = 0;
-		base_addr[CyMSVR2] = 0;
-		write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
-	}
-
-	/*
-	 * Now do specials for channel zero....
-	 */
-
-	base_addr[CyMSVR1] = CyRTS;
-	base_addr[CyMSVR2] = CyDTR;
-	base_addr[CyIER] = CyRxData;
-	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
-	local_irq_restore(flags);
-
-	my_udelay(20000L);	/* Let it all settle down */
-
-	printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
-	if (badspeed)
-		printk
-		    ("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
-		     rcor >> 5, rbpr);
-}				/* serial_console_init */
-
-static const struct tty_operations cy_ops = {
-	.open = cy_open,
-	.close = cy_close,
-	.write = cy_write,
-	.put_char = cy_put_char,
-	.flush_chars = cy_flush_chars,
-	.write_room = cy_write_room,
-	.chars_in_buffer = cy_chars_in_buffer,
-	.flush_buffer = cy_flush_buffer,
-	.ioctl = cy_ioctl,
-	.throttle = cy_throttle,
-	.unthrottle = cy_unthrottle,
-	.set_termios = cy_set_termios,
-	.stop = cy_stop,
-	.start = cy_start,
-	.hangup = cy_hangup,
-	.tiocmget = cy_tiocmget,
-	.tiocmset = cy_tiocmset,
-};
-
-/* The serial driver boot-time initialization code!
-    Hardware I/O ports are mapped to character special devices on a
-    first found, first allocated manner.  That is, this code searches
-    for Cyclom cards in the system.  As each is found, it is probed
-    to discover how many chips (and thus how many ports) are present.
-    These ports are mapped to the tty ports 64 and upward in monotonic
-    fashion.  If an 8-port card is replaced with a 16-port card, the
-    port mapping on a following card will shift.
-
-    This approach is different from what is used in the other serial
-    device driver because the Cyclom is more properly a multiplexer,
-    not just an aggregation of serial ports on one card.
-
-    If there are more cards with more ports than have been statically
-    allocated above, a warning is printed and the extra ports are ignored.
- */
-static int __init serial167_init(void)
-{
-	struct cyclades_port *info;
-	int ret = 0;
-	int good_ports = 0;
-	int port_num = 0;
-	int index;
-	int DefSpeed;
-#ifdef notyet
-	struct sigaction sa;
-#endif
-
-	if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
-		return 0;
-
-	cy_serial_driver = alloc_tty_driver(NR_PORTS);
-	if (!cy_serial_driver)
-		return -ENOMEM;
-
-#if 0
-	scrn[1] = '\0';
-#endif
-
-	show_version();
-
-	/* Has "console=0,9600n8" been used in bootinfo to change speed? */
-	if (serial_console_cflag)
-		DefSpeed = serial_console_cflag & 0017;
-	else {
-		DefSpeed = initial_console_speed;
-		serial_console_info = &cy_port[0];
-		serial_console_cflag = DefSpeed | CS8;
-#if 0
-		serial_console = 64;	/*callout_driver.minor_start */
-#endif
-	}
-
-	/* Initialize the tty_driver structure */
-
-	cy_serial_driver->owner = THIS_MODULE;
-	cy_serial_driver->name = "ttyS";
-	cy_serial_driver->major = TTY_MAJOR;
-	cy_serial_driver->minor_start = 64;
-	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	cy_serial_driver->init_termios = tty_std_termios;
-	cy_serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(cy_serial_driver, &cy_ops);
-
-	ret = tty_register_driver(cy_serial_driver);
-	if (ret) {
-		printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
-		put_tty_driver(cy_serial_driver);
-		return ret;
-	}
-
-	port_num = 0;
-	info = cy_port;
-	for (index = 0; index < 1; index++) {
-
-		good_ports = 4;
-
-		if (port_num < NR_PORTS) {
-			while (good_ports-- && port_num < NR_PORTS) {
-		/*** initialize port ***/
-				info->magic = CYCLADES_MAGIC;
-				info->type = PORT_CIRRUS;
-				info->card = index;
-				info->line = port_num;
-				info->flags = STD_COM_FLAGS;
-				info->tty = NULL;
-				info->xmit_fifo_size = 12;
-				info->cor1 = CyPARITY_NONE | Cy_8_BITS;
-				info->cor2 = CyETC;
-				info->cor3 = Cy_1_STOP;
-				info->cor4 = 0x08;	/* _very_ small receive threshold */
-				info->cor5 = 0;
-				info->cor6 = 0;
-				info->cor7 = 0;
-				info->tbpr = baud_bpr[DefSpeed];	/* Tx BPR */
-				info->tco = baud_co[DefSpeed];	/* Tx CO */
-				info->rbpr = baud_bpr[DefSpeed];	/* Rx BPR */
-				info->rco = baud_co[DefSpeed] >> 5;	/* Rx CO */
-				info->close_delay = 0;
-				info->x_char = 0;
-				info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-				printk("cyc: %d: setting count to 0\n",
-				       __LINE__);
-#endif
-				info->blocked_open = 0;
-				info->default_threshold = 0;
-				info->default_timeout = 0;
-				init_waitqueue_head(&info->open_wait);
-				init_waitqueue_head(&info->close_wait);
-				/* info->session */
-				/* info->pgrp */
-/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
-				info->read_status_mask =
-				    CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
-				    CyFRAME | CyOVERRUN;
-				/* info->timeout */
-
-				printk("ttyS%d ", info->line);
-				port_num++;
-				info++;
-				if (!(port_num & 7)) {
-					printk("\n               ");
-				}
-			}
-		}
-		printk("\n");
-	}
-	while (port_num < NR_PORTS) {
-		info->line = -1;
-		port_num++;
-		info++;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
-			  "cd2401_errors", cd2401_rxerr_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_errors IRQ");
-		goto cleanup_serial_driver;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
-			  "cd2401_modem", cd2401_modem_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_modem IRQ");
-		goto cleanup_irq_cd2401_errors;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
-			  "cd2401_txints", cd2401_tx_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_txints IRQ");
-		goto cleanup_irq_cd2401_modem;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
-			  "cd2401_rxints", cd2401_rx_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_rxints IRQ");
-		goto cleanup_irq_cd2401_txints;
-	}
-
-	/* Now we have registered the interrupt handlers, allow the interrupts */
-
-	pcc2chip[PccSCCMICR] = 0x15;	/* Serial ints are level 5 */
-	pcc2chip[PccSCCTICR] = 0x15;
-	pcc2chip[PccSCCRICR] = 0x15;
-
-	pcc2chip[PccIMLR] = 3;	/* Allow PCC2 ints above 3!? */
-
-	return 0;
-cleanup_irq_cd2401_txints:
-	free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
-cleanup_irq_cd2401_modem:
-	free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
-cleanup_irq_cd2401_errors:
-	free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
-cleanup_serial_driver:
-	if (tty_unregister_driver(cy_serial_driver))
-		printk(KERN_ERR
-		       "Couldn't unregister MVME166/7 serial driver\n");
-	put_tty_driver(cy_serial_driver);
-	return ret;
-}				/* serial167_init */
-
-module_init(serial167_init);
-
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int line_num)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	struct cyclades_port *info;
-	unsigned long flags;
-
-	info = &cy_port[line_num];
-	channel = info->line;
-	printk("  channel %d\n", channel);
-	/**/ printk(" cy_port\n");
-	printk("  card line flags = %d %d %x\n",
-	       info->card, info->line, info->flags);
-	printk
-	    ("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
-	     (long)info->tty, info->read_status_mask, info->timeout,
-	     info->xmit_fifo_size);
-	printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
-	       info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
-	       info->cor6, info->cor7);
-	printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
-	       info->rbpr, info->rco);
-	printk("  close_delay event count = %d %d %d\n", info->close_delay,
-	       info->event, info->count);
-	printk("  x_char blocked_open = %x %x\n", info->x_char,
-	       info->blocked_open);
-	printk("  open_wait = %lx %lx %lx\n", (long)info->open_wait);
-
-	local_irq_save(flags);
-
-/* Global Registers */
-
-	printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
-	printk(" CyCAR %x\n", base_addr[CyCAR]);
-	printk(" CyRISR %x\n", base_addr[CyRISR]);
-	printk(" CyTISR %x\n", base_addr[CyTISR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
-	printk(" CyRIR %x\n", base_addr[CyRIR]);
-	printk(" CyTIR %x\n", base_addr[CyTIR]);
-	printk(" CyMIR %x\n", base_addr[CyMIR]);
-	printk(" CyTPR %x\n", base_addr[CyTPR]);
-
-	base_addr[CyCAR] = (u_char) channel;
-
-/* Virtual Registers */
-
-#if 0
-	printk(" CyRIVR %x\n", base_addr[CyRIVR]);
-	printk(" CyTIVR %x\n", base_addr[CyTIVR]);
-	printk(" CyMIVR %x\n", base_addr[CyMIVR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
-#endif
-
-/* Channel Registers */
-
-	printk(" CyCCR %x\n", base_addr[CyCCR]);
-	printk(" CyIER %x\n", base_addr[CyIER]);
-	printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
-	printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
-	printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
-	printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
-	printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
-#if 0
-	printk(" CyCCSR %x\n", base_addr[CyCCSR]);
-	printk(" CyRDCR %x\n", base_addr[CyRDCR]);
-#endif
-	printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
-	printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
-#if 0
-	printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
-	printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
-	printk(" CySCRL %x\n", base_addr[CySCRL]);
-	printk(" CySCRH %x\n", base_addr[CySCRH]);
-	printk(" CyLNC %x\n", base_addr[CyLNC]);
-	printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
-	printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
-#endif
-	printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
-	printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
-	printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
-	printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
-	printk(" CyRBPR %x\n", base_addr[CyRBPR]);
-	printk(" CyRCOR %x\n", base_addr[CyRCOR]);
-	printk(" CyTBPR %x\n", base_addr[CyTBPR]);
-	printk(" CyTCOR %x\n", base_addr[CyTCOR]);
-
-	local_irq_restore(flags);
-}				/* show_status */
-#endif
-
-#if 0
-/* Dummy routine in mvme16x/config.c for now */
-
-/* Serial console setup. Called from linux/init/main.c */
-
-void console_setup(char *str, int *ints)
-{
-	char *s;
-	int baud, bits, parity;
-	int cflag = 0;
-
-	/* Sanity check. */
-	if (ints[0] > 3 || ints[1] > 3)
-		return;
-
-	/* Get baud, bits and parity */
-	baud = 2400;
-	bits = 8;
-	parity = 'n';
-	if (ints[2])
-		baud = ints[2];
-	if ((s = strchr(str, ','))) {
-		do {
-			s++;
-		} while (*s >= '0' && *s <= '9');
-		if (*s)
-			parity = *s++;
-		if (*s)
-			bits = *s - '0';
-	}
-
-	/* Now construct a cflag setting. */
-	switch (baud) {
-	case 1200:
-		cflag |= B1200;
-		break;
-	case 9600:
-		cflag |= B9600;
-		break;
-	case 19200:
-		cflag |= B19200;
-		break;
-	case 38400:
-		cflag |= B38400;
-		break;
-	case 2400:
-	default:
-		cflag |= B2400;
-		break;
-	}
-	switch (bits) {
-	case 7:
-		cflag |= CS7;
-		break;
-	default:
-	case 8:
-		cflag |= CS8;
-		break;
-	}
-	switch (parity) {
-	case 'o':
-	case 'O':
-		cflag |= PARODD;
-		break;
-	case 'e':
-	case 'E':
-		cflag |= PARENB;
-		break;
-	}
-
-	serial_console_info = &cy_port[ints[1]];
-	serial_console_cflag = cflag;
-	serial_console = ints[1] + 64;	/*callout_driver.minor_start */
-}
-#endif
-
-/*
- * The following is probably out of date for 2.1.x serial console stuff.
- *
- * The console is registered early on from arch/m68k/kernel/setup.c, and
- * it therefore relies on the chip being setup correctly by 166-Bug.  This
- * seems reasonable, as the serial port has been used to invoke the system
- * boot.  It also means that this function must not rely on any data
- * initialisation performed by serial167_init() etc.
- *
- * Of course, once the console has been registered, we had better ensure
- * that serial167_init() doesn't leave the chip non-functional.
- *
- * The console must be locked when we get here.
- */
-
-void serial167_console_write(struct console *co, const char *str,
-			     unsigned count)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-	volatile u_char sink;
-	u_char ier;
-	int port;
-	u_char do_lf = 0;
-	int i = 0;
-
-	local_irq_save(flags);
-
-	/* Ensure transmitter is enabled! */
-
-	port = 0;
-	base_addr[CyCAR] = (u_char) port;
-	while (base_addr[CyCCR])
-		;
-	base_addr[CyCCR] = CyENB_XMTR;
-
-	ier = base_addr[CyIER];
-	base_addr[CyIER] = CyTxMpty;
-
-	while (1) {
-		if (pcc2chip[PccSCCTICR] & 0x20) {
-			/* We have a Tx int. Acknowledge it */
-			sink = pcc2chip[PccTPIACKR];
-			if ((base_addr[CyLICR] >> 2) == port) {
-				if (i == count) {
-					/* Last char of string is now output */
-					base_addr[CyTEOIR] = CyNOTRANS;
-					break;
-				}
-				if (do_lf) {
-					base_addr[CyTDR] = '\n';
-					str++;
-					i++;
-					do_lf = 0;
-				} else if (*str == '\n') {
-					base_addr[CyTDR] = '\r';
-					do_lf = 1;
-				} else {
-					base_addr[CyTDR] = *str++;
-					i++;
-				}
-				base_addr[CyTEOIR] = 0;
-			} else
-				base_addr[CyTEOIR] = CyNOTRANS;
-		}
-	}
-
-	base_addr[CyIER] = ier;
-
-	local_irq_restore(flags);
-}
-
-static struct tty_driver *serial167_console_device(struct console *c,
-						   int *index)
-{
-	*index = c->index;
-	return cy_serial_driver;
-}
-
-static struct console sercons = {
-	.name = "ttyS",
-	.write = serial167_console_write,
-	.device = serial167_console_device,
-	.flags = CON_PRINTBUFFER,
-	.index = -1,
-};
-
-static int __init serial167_console_init(void)
-{
-	if (vme_brdtype == VME_TYPE_MVME166 ||
-	    vme_brdtype == VME_TYPE_MVME167 ||
-	    vme_brdtype == VME_TYPE_MVME177) {
-		mvme167_serial_console_setup(0);
-		register_console(&sercons);
-	}
-	return 0;
-}
-
-console_initcall(serial167_console_init);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
deleted file mode 100644
index c2bca3f..0000000
--- a/drivers/char/specialix.c
+++ /dev/null
@@ -1,2368 +0,0 @@
-/*
- *      specialix.c  -- specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997  Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support. But please read the documentation (specialix.txt)
- *      first.
- *
- *      This driver was developped in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- *      This code is firmly based on the riscom/8 serial driver,
- *      written by Dmitry Gorodchanin. The specialix IO8+ card
- *      programming information was obtained from the CL-CD1865 Data
- *      Book, and Specialix document number 6200059: IO8+ Hardware
- *      Functional Specification.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- *
- * Revision history:
- *
- * Revision 1.0:  April 1st 1997.
- *                Initial release for alpha testing.
- * Revision 1.1:  April 14th 1997.
- *                Incorporated Richard Hudsons suggestions,
- *                removed some debugging printk's.
- * Revision 1.2:  April 15th 1997.
- *                Ported to 2.1.x kernels.
- * Revision 1.3:  April 17th 1997
- *                Backported to 2.0. (Compatibility macros).
- * Revision 1.4:  April 18th 1997
- *                Fixed DTR/RTS bug that caused the card to indicate
- *                "don't send data" to a modem after the password prompt.
- *                Fixed bug for premature (fake) interrupts.
- * Revision 1.5:  April 19th 1997
- *                fixed a minor typo in the header file, cleanup a little.
- *                performance warnings are now MAXed at once per minute.
- * Revision 1.6:  May 23 1997
- *                Changed the specialix=... format to include interrupt.
- * Revision 1.7:  May 27 1997
- *                Made many more debug printk's a compile time option.
- * Revision 1.8:  Jul 1  1997
- *                port to linux-2.1.43 kernel.
- * Revision 1.9:  Oct 9  1998
- *                Added stuff for the IO8+/PCI version.
- * Revision 1.10: Oct 22  1999 / Jan 21 2000.
- *                Added stuff for setserial.
- *                Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
- *
- */
-
-#define VERSION "1.11"
-
-
-/*
- * There is a bunch of documentation about the card, jumpers, config
- * settings, restrictions, cables, device names and numbers in
- * Documentation/serial/specialix.txt
- */
-
-#include <linux/module.h>
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/uaccess.h>
-#include <linux/gfp.h>
-
-#include "specialix_io8.h"
-#include "cd1865.h"
-
-
-/*
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile...
-*/
-#define DEBUG
-
-static int sx_debug;
-static int sx_rxfifo = SPECIALIX_RXFIFO;
-static int sx_rtscts;
-
-#ifdef DEBUG
-#define dprintk(f, str...) if (sx_debug & f) printk(str)
-#else
-#define dprintk(f, str...) /* nothing */
-#endif
-
-#define SX_DEBUG_FLOW    0x0001
-#define SX_DEBUG_DATA    0x0002
-#define SX_DEBUG_PROBE   0x0004
-#define SX_DEBUG_CHAN    0x0008
-#define SX_DEBUG_INIT    0x0010
-#define SX_DEBUG_RX      0x0020
-#define SX_DEBUG_TX      0x0040
-#define SX_DEBUG_IRQ     0x0080
-#define SX_DEBUG_OPEN    0x0100
-#define SX_DEBUG_TERMIOS 0x0200
-#define SX_DEBUG_SIGNALS 0x0400
-#define SX_DEBUG_FIFO    0x0800
-
-
-#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
-#define func_exit()  dprintk(SX_DEBUG_FLOW, "io8: exit  %s\n", __func__)
-
-
-/* Configurable options: */
-
-/* Am I paranoid or not ? ;-) */
-#define SPECIALIX_PARANOIA_CHECK
-
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#undef SX_REPORT_FIFO
-#undef SX_REPORT_OVERRUN
-
-
-
-
-#define SPECIALIX_LEGAL_FLAGS \
-	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
-	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
-	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
-
-static struct tty_driver *specialix_driver;
-
-static struct specialix_board sx_board[SX_NBOARD] =  {
-	{ 0, SX_IOBASE1,  9, },
-	{ 0, SX_IOBASE2, 11, },
-	{ 0, SX_IOBASE3, 12, },
-	{ 0, SX_IOBASE4, 15, },
-};
-
-static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-
-
-static int sx_paranoia_check(struct specialix_port const *port,
-				    char *name, const char *routine)
-{
-#ifdef SPECIALIX_PARANOIA_CHECK
-	static const char *badmagic = KERN_ERR
-	  "sx: Warning: bad specialix port magic number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR
-	  "sx: Warning: null specialix port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != SPECIALIX_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-
-/*
- *
- *  Service functions for specialix IO8+ driver.
- *
- */
-
-/* Get board number from pointer */
-static inline int board_No(struct specialix_board *bp)
-{
-	return bp - sx_board;
-}
-
-
-/* Get port number from pointer */
-static inline int port_No(struct specialix_port const *port)
-{
-	return SX_PORT(port - sx_port);
-}
-
-
-/* Get pointer to board from pointer to port */
-static inline struct specialix_board *port_Board(
-					struct specialix_port const *port)
-{
-	return &sx_board[SX_BOARD(port - sx_port)];
-}
-
-
-/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in(struct specialix_board *bp,
-							unsigned short reg)
-{
-	bp->reg = reg | 0x80;
-	outb(reg | 0x80, bp->base + SX_ADDR_REG);
-	return inb(bp->base + SX_DATA_REG);
-}
-
-
-/* Output Byte to CL CD186x register */
-static inline void sx_out(struct specialix_board *bp, unsigned short reg,
-			  unsigned char val)
-{
-	bp->reg = reg | 0x80;
-	outb(reg | 0x80, bp->base + SX_ADDR_REG);
-	outb(val, bp->base + SX_DATA_REG);
-}
-
-
-/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in_off(struct specialix_board *bp,
-				unsigned short reg)
-{
-	bp->reg = reg;
-	outb(reg, bp->base + SX_ADDR_REG);
-	return inb(bp->base + SX_DATA_REG);
-}
-
-
-/* Output Byte to CL CD186x register */
-static inline void sx_out_off(struct specialix_board  *bp,
-				unsigned short reg, unsigned char val)
-{
-	bp->reg = reg;
-	outb(reg, bp->base + SX_ADDR_REG);
-	outb(val, bp->base + SX_DATA_REG);
-}
-
-
-/* Wait for Channel Command Register ready */
-static void sx_wait_CCR(struct specialix_board  *bp)
-{
-	unsigned long delay, flags;
-	unsigned char ccr;
-
-	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
-		spin_lock_irqsave(&bp->lock, flags);
-		ccr = sx_in(bp, CD186x_CCR);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		if (!ccr)
-			return;
-		udelay(1);
-	}
-
-	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-
-/* Wait for Channel Command Register ready */
-static void sx_wait_CCR_off(struct specialix_board  *bp)
-{
-	unsigned long delay;
-	unsigned char crr;
-	unsigned long flags;
-
-	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
-		spin_lock_irqsave(&bp->lock, flags);
-		crr = sx_in_off(bp, CD186x_CCR);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		if (!crr)
-			return;
-		udelay(1);
-	}
-
-	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-
-/*
- *  specialix IO8+ IO range functions.
- */
-
-static int sx_request_io_range(struct specialix_board *bp)
-{
-	return request_region(bp->base,
-		bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
-		"specialix IO8+") == NULL;
-}
-
-
-static void sx_release_io_range(struct specialix_board *bp)
-{
-	release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
-					SX_PCI_IO_SPACE : SX_IO_SPACE);
-}
-
-
-/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-static int sx_set_irq(struct specialix_board *bp)
-{
-	int virq;
-	int i;
-	unsigned long flags;
-
-	if (bp->flags & SX_BOARD_IS_PCI)
-		return 1;
-	switch (bp->irq) {
-	/* In the same order as in the docs... */
-	case 15:
-		virq = 0;
-		break;
-	case 12:
-		virq = 1;
-		break;
-	case 11:
-		virq = 2;
-		break;
-	case 9:
-		virq = 3;
-		break;
-	default:printk(KERN_ERR
-			    "Speclialix: cannot set irq to %d.\n", bp->irq);
-		return 0;
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	for (i = 0; i < 2; i++) {
-		sx_out(bp, CD186x_CAR, i);
-		sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	return 1;
-}
-
-
-/* Reset and setup CD186x chip */
-static int sx_init_CD186x(struct specialix_board  *bp)
-{
-	unsigned long flags;
-	int scaler;
-	int rv = 1;
-
-	func_enter();
-	sx_wait_CCR_off(bp);			   /* Wait for CCR ready        */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);      /* Reset CD186x chip          */
-	spin_unlock_irqrestore(&bp->lock, flags);
-	msleep(50);					/* Delay 0.05 sec            */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out_off(bp, CD186x_GIVR, SX_ID);             /* Set ID for this chip      */
-	sx_out_off(bp, CD186x_GICR, 0);                 /* Clear all bits            */
-	sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT);      /* Prio for modem intr       */
-	sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT);      /* Prio for transmitter intr */
-	sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT);      /* Prio for receiver intr    */
-	/* Set RegAckEn */
-	sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
-
-	/* Setting up prescaler. We need 4 ticks per 1 ms */
-	scaler =  SX_OSCFREQ/SPECIALIX_TPS;
-
-	sx_out_off(bp, CD186x_PPRH, scaler >> 8);
-	sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	if (!sx_set_irq(bp)) {
-		/* Figure out how to pass this along... */
-		printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
-		rv = 0;
-	}
-
-	func_exit();
-	return rv;
-}
-
-
-static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
-{
-	int i;
-	int t;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	for (i = 0, t = 0; i < 8; i++) {
-		sx_out_off(bp, CD186x_CAR, i);
-		if (sx_in_off(bp, reg) & bit)
-			t |= 1 << i;
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return t;
-}
-
-
-/* Main probing routine, also sets irq. */
-static int sx_probe(struct specialix_board *bp)
-{
-	unsigned char val1, val2;
-	int rev;
-	int chip;
-
-	func_enter();
-
-	if (sx_request_io_range(bp)) {
-		func_exit();
-		return 1;
-	}
-
-	/* Are the I/O ports here ? */
-	sx_out_off(bp, CD186x_PPRL, 0x5a);
-	udelay(1);
-	val1 = sx_in_off(bp, CD186x_PPRL);
-
-	sx_out_off(bp, CD186x_PPRL, 0xa5);
-	udelay(1);
-	val2 = sx_in_off(bp, CD186x_PPRL);
-
-
-	if (val1 != 0x5a || val2 != 0xa5) {
-		printk(KERN_INFO
-			"sx%d: specialix IO8+ Board at 0x%03x not found.\n",
-						board_No(bp), bp->base);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-	/* Check the DSR lines that Specialix uses as board
-	   identification */
-	val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
-	val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
-	dprintk(SX_DEBUG_INIT,
-			"sx%d: DSR lines are: %02x, rts lines are: %02x\n",
-					board_No(bp), val1, val2);
-
-	/* They managed to switch the bit order between the docs and
-	   the IO8+ card. The new PCI card now conforms to old docs.
-	   They changed the PCI docs to reflect the situation on the
-	   old card. */
-	val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
-	if (val1 != val2) {
-		printk(KERN_INFO
-		  "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
-		       board_No(bp), val2, bp->base, val1);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-
-	/* Reset CD186x again  */
-	if (!sx_init_CD186x(bp)) {
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-	sx_request_io_range(bp);
-	bp->flags |= SX_BOARD_PRESENT;
-
-	/* Chip           revcode   pkgtype
-			  GFRCR     SRCR bit 7
-	   CD180 rev B    0x81      0
-	   CD180 rev C    0x82      0
-	   CD1864 rev A   0x82      1
-	   CD1865 rev A   0x83      1  -- Do not use!!! Does not work.
-	   CD1865 rev B   0x84      1
-	 -- Thanks to Gwen Wang, Cirrus Logic.
-	 */
-
-	switch (sx_in_off(bp, CD186x_GFRCR)) {
-	case 0x82:
-		chip = 1864;
-		rev = 'A';
-		break;
-	case 0x83:
-		chip = 1865;
-		rev = 'A';
-		break;
-	case 0x84:
-		chip = 1865;
-		rev = 'B';
-		break;
-	case 0x85:
-		chip = 1865;
-		rev = 'C';
-		break; /* Does not exist at this time */
-	default:
-		chip = -1;
-		rev = 'x';
-	}
-
-	dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
-
-	printk(KERN_INFO
-    "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
-				board_No(bp), bp->base, bp->irq, chip, rev);
-
-	func_exit();
-	return 0;
-}
-
-/*
- *
- *  Interrupt processing routines.
- * */
-
-static struct specialix_port *sx_get_port(struct specialix_board *bp,
-					       unsigned char const *what)
-{
-	unsigned char channel;
-	struct specialix_port *port = NULL;
-
-	channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
-	dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
-	if (channel < CD186x_NCH) {
-		port = &sx_port[board_No(bp) * SX_NPORT + channel];
-		dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
-			board_No(bp) * SX_NPORT + channel,  port,
-			port->port.flags & ASYNC_INITIALIZED);
-
-		if (port->port.flags & ASYNC_INITIALIZED) {
-			dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
-			func_exit();
-			return port;
-		}
-	}
-	printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
-	       board_No(bp), what, channel);
-	return NULL;
-}
-
-
-static void sx_receive_exc(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char status;
-	unsigned char ch, flag;
-
-	func_enter();
-
-	port = sx_get_port(bp, "Receive");
-	if (!port) {
-		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
-		func_exit();
-		return;
-	}
-	tty = port->port.tty;
-
-	status = sx_in(bp, CD186x_RCSR);
-
-	dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
-	if (status & RCSR_OE) {
-		port->overrun++;
-		dprintk(SX_DEBUG_FIFO,
-			"sx%d: port %d: Overrun. Total %ld overruns.\n",
-				board_No(bp), port_No(port), port->overrun);
-	}
-	status &= port->mark_mask;
-
-	/* This flip buffer check needs to be below the reading of the
-	   status register to reset the chip's IRQ.... */
-	if (tty_buffer_request_room(tty, 1) == 0) {
-		dprintk(SX_DEBUG_FIFO,
-		    "sx%d: port %d: Working around flip buffer overflow.\n",
-					board_No(bp), port_No(port));
-		func_exit();
-		return;
-	}
-
-	ch = sx_in(bp, CD186x_RDR);
-	if (!status) {
-		func_exit();
-		return;
-	}
-	if (status & RCSR_TOUT) {
-		printk(KERN_INFO
-		    "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
-					board_No(bp), port_No(port));
-		func_exit();
-		return;
-
-	} else if (status & RCSR_BREAK) {
-		dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
-		       board_No(bp), port_No(port));
-		flag = TTY_BREAK;
-		if (port->port.flags & ASYNC_SAK)
-			do_SAK(tty);
-
-	} else if (status & RCSR_PE)
-		flag = TTY_PARITY;
-
-	else if (status & RCSR_FE)
-		flag = TTY_FRAME;
-
-	else if (status & RCSR_OE)
-		flag = TTY_OVERRUN;
-
-	else
-		flag = TTY_NORMAL;
-
-	if (tty_insert_flip_char(tty, ch, flag))
-		tty_flip_buffer_push(tty);
-	func_exit();
-}
-
-
-static void sx_receive(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	func_enter();
-
-	port = sx_get_port(bp, "Receive");
-	if (port == NULL) {
-		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
-		func_exit();
-		return;
-	}
-	tty = port->port.tty;
-
-	count = sx_in(bp, CD186x_RDCR);
-	dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
-	port->hits[count > 8 ? 9 : count]++;
-
-	while (count--)
-		tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
-	tty_flip_buffer_push(tty);
-	func_exit();
-}
-
-
-static void sx_transmit(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	func_enter();
-	port = sx_get_port(bp, "Transmit");
-	if (port == NULL) {
-		func_exit();
-		return;
-	}
-	dprintk(SX_DEBUG_TX, "port: %p\n", port);
-	tty = port->port.tty;
-
-	if (port->IER & IER_TXEMPTY) {
-		/* FIFO drained */
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXEMPTY;
-		sx_out(bp, CD186x_IER, port->IER);
-		func_exit();
-		return;
-	}
-
-	if ((port->xmit_cnt <= 0 && !port->break_length)
-	    || tty->stopped || tty->hw_stopped) {
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		sx_out(bp, CD186x_IER, port->IER);
-		func_exit();
-		return;
-	}
-
-	if (port->break_length) {
-		if (port->break_length > 0) {
-			if (port->COR2 & COR2_ETC) {
-				sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-				sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
-				port->COR2 &= ~COR2_ETC;
-			}
-			count = min_t(int, port->break_length, 0xff);
-			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
-			sx_out(bp, CD186x_TDR, count);
-			port->break_length -= count;
-			if (port->break_length == 0)
-				port->break_length--;
-		} else {
-			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-			sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
-			sx_out(bp, CD186x_COR2, port->COR2);
-			sx_wait_CCR(bp);
-			sx_out(bp, CD186x_CCR, CCR_CORCHG2);
-			port->break_length = 0;
-		}
-
-		func_exit();
-		return;
-	}
-
-	count = CD186x_NFIFO;
-	do {
-		sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-
-	if (port->xmit_cnt <= 0) {
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	if (port->xmit_cnt <= port->wakeup_chars)
-		tty_wakeup(tty);
-
-	func_exit();
-}
-
-
-static void sx_check_modem(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char mcr;
-	int msvr_cd;
-
-	dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
-	port = sx_get_port(bp, "Modem");
-	if (port == NULL)
-		return;
-
-	tty = port->port.tty;
-
-	mcr = sx_in(bp, CD186x_MCR);
-
-	if ((mcr & MCR_CDCHG)) {
-		dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
-		msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
-		if (msvr_cd) {
-			dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
-			wake_up_interruptible(&port->port.open_wait);
-		} else {
-			dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
-			tty_hangup(tty);
-		}
-	}
-
-#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
-	if (mcr & MCR_CTSCHG) {
-		if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
-			tty->hw_stopped = 0;
-			port->IER |= IER_TXRDY;
-			if (port->xmit_cnt <= port->wakeup_chars)
-				tty_wakeup(tty);
-		} else {
-			tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	if (mcr & MCR_DSSXHG) {
-		if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
-			tty->hw_stopped = 0;
-			port->IER |= IER_TXRDY;
-			if (port->xmit_cnt <= port->wakeup_chars)
-				tty_wakeup(tty);
-		} else {
-			tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
-
-	/* Clear change bits */
-	sx_out(bp, CD186x_MCR, 0);
-}
-
-
-/* The main interrupt processing routine */
-static irqreturn_t sx_interrupt(int dummy, void *dev_id)
-{
-	unsigned char status;
-	unsigned char ack;
-	struct specialix_board *bp = dev_id;
-	unsigned long loop = 0;
-	int saved_reg;
-	unsigned long flags;
-
-	func_enter();
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
-		port_No(sx_get_port(bp, "INT")),
-		SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
-	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
-								bp->irq);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		func_exit();
-		return IRQ_NONE;
-	}
-
-	saved_reg = bp->reg;
-
-	while (++loop < 16) {
-		status = sx_in(bp, CD186x_SRSR) &
-				(SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
-		if (status == 0)
-			break;
-		if (status & SRSR_RREQint) {
-			ack = sx_in(bp, CD186x_RRAR);
-
-			if (ack == (SX_ID | GIVR_IT_RCV))
-				sx_receive(bp);
-			else if (ack == (SX_ID | GIVR_IT_REXC))
-				sx_receive_exc(bp);
-			else
-				printk(KERN_ERR
-				"sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
-						board_No(bp), status, ack);
-
-		} else if (status & SRSR_TREQint) {
-			ack = sx_in(bp, CD186x_TRAR);
-
-			if (ack == (SX_ID | GIVR_IT_TX))
-				sx_transmit(bp);
-			else
-				printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
-					board_No(bp), status, ack,
-					port_No(sx_get_port(bp, "Int")));
-		} else if (status & SRSR_MREQint) {
-			ack = sx_in(bp, CD186x_MRAR);
-
-			if (ack == (SX_ID | GIVR_IT_MODEM))
-				sx_check_modem(bp);
-			else
-				printk(KERN_ERR
-				  "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
-				       board_No(bp), status, ack);
-
-		}
-
-		sx_out(bp, CD186x_EOIR, 0);   /* Mark end of interrupt */
-	}
-	bp->reg = saved_reg;
-	outb(bp->reg, bp->base + SX_ADDR_REG);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-
-/*
- *  Routines for open & close processing.
- */
-
-static void turn_ints_off(struct specialix_board *bp)
-{
-	unsigned long flags;
-
-	func_enter();
-	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in_off(bp, 0); /* Turn off interrupts. */
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-static void turn_ints_on(struct specialix_board *bp)
-{
-	unsigned long flags;
-
-	func_enter();
-
-	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in(bp, 0); /* Turn ON interrupts. */
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-/* Called with disabled interrupts */
-static int sx_setup_board(struct specialix_board *bp)
-{
-	int error;
-
-	if (bp->flags & SX_BOARD_ACTIVE)
-		return 0;
-
-	if (bp->flags & SX_BOARD_IS_PCI)
-		error = request_irq(bp->irq, sx_interrupt,
-			IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
-	else
-		error = request_irq(bp->irq, sx_interrupt,
-			IRQF_DISABLED, "specialix IO8+", bp);
-
-	if (error)
-		return error;
-
-	turn_ints_on(bp);
-	bp->flags |= SX_BOARD_ACTIVE;
-
-	return 0;
-}
-
-
-/* Called with disabled interrupts */
-static void sx_shutdown_board(struct specialix_board *bp)
-{
-	func_enter();
-
-	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		func_exit();
-		return;
-	}
-
-	bp->flags &= ~SX_BOARD_ACTIVE;
-
-	dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
-		 bp->irq, board_No(bp));
-	free_irq(bp->irq, bp);
-	turn_ints_off(bp);
-	func_exit();
-}
-
-static unsigned int sx_crtscts(struct tty_struct *tty)
-{
-	if (sx_rtscts)
-		return C_CRTSCTS(tty);
-	return 1;
-}
-
-/*
- * Setting up port characteristics.
- * Must be called with disabled interrupts
- */
-static void sx_change_speed(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	struct tty_struct *tty;
-	unsigned long baud;
-	long tmp;
-	unsigned char cor1 = 0, cor3 = 0;
-	unsigned char mcor1 = 0, mcor2 = 0;
-	static unsigned long again;
-	unsigned long flags;
-
-	func_enter();
-
-	tty = port->port.tty;
-	if (!tty || !tty->termios) {
-		func_exit();
-		return;
-	}
-
-	port->IER  = 0;
-	port->COR2 = 0;
-	/* Select port on the board */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-
-	/* The Specialix board doens't implement the RTS lines.
-	   They are used to set the IRQ level. Don't touch them. */
-	if (sx_crtscts(tty))
-		port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
-	else
-		port->MSVR =  (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
-	baud = tty_get_baud_rate(tty);
-
-	if (baud == 38400) {
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud = 57600;
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud = 115200;
-	}
-
-	if (!baud) {
-		/* Drop DTR & exit */
-		dprintk(SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
-		if (!sx_crtscts(tty)) {
-			port->MSVR &= ~MSVR_DTR;
-			spin_lock_irqsave(&bp->lock, flags);
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-			spin_unlock_irqrestore(&bp->lock, flags);
-		} else
-			dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
-		return;
-	} else {
-		/* Set DTR on */
-		if (!sx_crtscts(tty))
-			port->MSVR |= MSVR_DTR;
-	}
-
-	/*
-	 * Now we must calculate some speed depended things
-	 */
-
-	/* Set baud rate for port */
-	tmp = port->custom_divisor ;
-	if (tmp)
-		printk(KERN_INFO
-			"sx%d: Using custom baud rate divisor %ld. \n"
-			"This is an untested option, please be careful.\n",
-							port_No(port), tmp);
-	else
-		tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
-								CD186x_TPC);
-
-	if (tmp < 0x10 && time_before(again, jiffies)) {
-		again = jiffies + HZ * 60;
-		/* Page 48 of version 2.0 of the CL-CD1865 databook */
-		if (tmp >= 12) {
-			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
-				"Performance degradation is possible.\n"
-				"Read specialix.txt for more info.\n",
-						port_No(port), tmp);
-		} else {
-			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
-		"Warning: overstressing Cirrus chip. This might not work.\n"
-		"Read specialix.txt for more info.\n", port_No(port), tmp);
-		}
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
-	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
-	sx_out(bp, CD186x_RBPRL, tmp & 0xff);
-	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (port->custom_divisor)
-		baud = (SX_OSCFREQ + port->custom_divisor/2) /
-							port->custom_divisor;
-	baud = (baud + 5) / 10;		/* Estimated CPS */
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
-	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-					      SERIAL_XMIT_SIZE - 1 : tmp);
-
-	/* Receiver timeout will be transmission time for 1.5 chars */
-	tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
-	tmp = (tmp > 0xff) ? 0xff : tmp;
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RTPR, tmp);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	switch (C_CSIZE(tty)) {
-	case CS5:
-		cor1 |= COR1_5BITS;
-		break;
-	case CS6:
-		cor1 |= COR1_6BITS;
-		break;
-	case CS7:
-		cor1 |= COR1_7BITS;
-		break;
-	case CS8:
-		cor1 |= COR1_8BITS;
-		break;
-	}
-
-	if (C_CSTOPB(tty))
-		cor1 |= COR1_2SB;
-
-	cor1 |= COR1_IGNORE;
-	if (C_PARENB(tty)) {
-		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty))
-			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty))
-			cor1 &= ~COR1_IGNORE;
-	}
-	/* Set marking of some errors */
-	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty))
-		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty))
-		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-	if (I_IGNBRK(tty)) {
-		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty))
-			/* Real raw mode. Ignore all */
-			port->mark_mask &= ~RCSR_OE;
-	}
-	/* Enable Hardware Flow Control */
-	if (C_CRTSCTS(tty)) {
-#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
-		port->IER |= IER_DSR | IER_CTS;
-		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
-		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-		spin_lock_irqsave(&bp->lock, flags);
-		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
-							(MSVR_CTS|MSVR_DSR));
-		spin_unlock_irqrestore(&bp->lock, flags);
-#else
-		port->COR2 |= COR2_CTSAE;
-#endif
-	}
-	/* Enable Software Flow Control. FIXME: I'm not sure about this */
-	/* Some people reported that it works, but I still doubt it */
-	if (I_IXON(tty)) {
-		port->COR2 |= COR2_TXIBE;
-		cor3 |= (COR3_FCT | COR3_SCDE);
-		if (I_IXANY(tty))
-			port->COR2 |= COR2_IXM;
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
-		sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
-		sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
-		sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
-		spin_unlock_irqrestore(&bp->lock, flags);
-	}
-	if (!C_CLOCAL(tty)) {
-		/* Enable CD check */
-		port->IER |= IER_CD;
-		mcor1 |= MCOR1_CDZD;
-		mcor2 |= MCOR2_CDOD;
-	}
-
-	if (C_CREAD(tty))
-		/* Enable receiver */
-		port->IER |= IER_RXD;
-
-	/* Set input FIFO size (1-8 bytes) */
-	cor3 |= sx_rxfifo;
-	/* Setting up CD186x channel registers */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_COR1, cor1);
-	sx_out(bp, CD186x_COR2, port->COR2);
-	sx_out(bp, CD186x_COR3, cor3);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Make CD186x know about registers change */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
-	/* Setting up modem option registers */
-	dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
-								mcor1, mcor2);
-	sx_out(bp, CD186x_MCOR1, mcor1);
-	sx_out(bp, CD186x_MCOR2, mcor2);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Enable CD186x transmitter & receiver */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
-	/* Enable interrupts */
-	sx_out(bp, CD186x_IER, port->IER);
-	/* And finally set the modem lines... */
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-/* Must be called with interrupts enabled */
-static int sx_setup_port(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	unsigned long flags;
-
-	func_enter();
-
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		func_exit();
-		return 0;
-	}
-
-	if (!port->xmit_buf) {
-		/* We may sleep in get_zeroed_page() */
-		unsigned long tmp;
-
-		tmp = get_zeroed_page(GFP_KERNEL);
-		if (tmp == 0L) {
-			func_exit();
-			return -ENOMEM;
-		}
-
-		if (port->xmit_buf) {
-			free_page(tmp);
-			func_exit();
-			return -ERESTARTSYS;
-		}
-		port->xmit_buf = (unsigned char *) tmp;
-	}
-
-	spin_lock_irqsave(&port->lock, flags);
-
-	if (port->port.tty)
-		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
-
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	sx_change_speed(bp, port);
-	port->port.flags |= ASYNC_INITIALIZED;
-
-	spin_unlock_irqrestore(&port->lock, flags);
-
-
-	func_exit();
-	return 0;
-}
-
-
-/* Must be called with interrupts disabled */
-static void sx_shutdown_port(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	struct tty_struct *tty;
-	int i;
-	unsigned long flags;
-
-	func_enter();
-
-	if (!(port->port.flags & ASYNC_INITIALIZED)) {
-		func_exit();
-		return;
-	}
-
-	if (sx_debug & SX_DEBUG_FIFO) {
-		dprintk(SX_DEBUG_FIFO,
-			"sx%d: port %d: %ld overruns, FIFO hits [ ",
-				board_No(bp), port_No(port), port->overrun);
-		for (i = 0; i < 10; i++)
-			dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
-		dprintk(SX_DEBUG_FIFO, "].\n");
-	}
-
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}
-
-	/* Select port */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-
-	tty = port->port.tty;
-	if (tty == NULL || C_HUPCL(tty)) {
-		/* Drop DTR */
-		sx_out(bp, CD186x_MSVDTR, 0);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Reset port */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
-	/* Disable all interrupts from this port */
-	port->IER = 0;
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (tty)
-		set_bit(TTY_IO_ERROR, &tty->flags);
-	port->port.flags &= ~ASYNC_INITIALIZED;
-
-	if (!bp->count)
-		sx_shutdown_board(bp);
-	func_exit();
-}
-
-
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-						struct specialix_port *port)
-{
-	DECLARE_WAITQUEUE(wait,  current);
-	struct specialix_board *bp = port_Board(port);
-	int    retval;
-	int    do_clocal = 0;
-	int    CD;
-	unsigned long flags;
-
-	func_enter();
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->port.close_wait);
-		if (port->port.flags & ASYNC_HUP_NOTIFY) {
-			func_exit();
-			return -EAGAIN;
-		} else {
-			func_exit();
-			return -ERESTARTSYS;
-		}
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		port->port.flags |= ASYNC_NORMAL_ACTIVE;
-		func_exit();
-		return 0;
-	}
-
-	if (C_CLOCAL(tty))
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&port->port.open_wait, &wait);
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->port.count--;
-	spin_unlock_irqrestore(&port->lock, flags);
-	port->port.blocked_open++;
-	while (1) {
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
-		if (sx_crtscts(tty)) {
-			/* Activate RTS */
-			port->MSVR |= MSVR_DTR;		/* WTF? */
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-		} else {
-			/* Activate DTR */
-			port->MSVR |= MSVR_DTR;
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-		}
-		spin_unlock_irqrestore(&bp->lock, flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->port.flags & ASYNC_INITIALIZED)) {
-			if (port->port.flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-			break;
-		}
-		if (!(port->port.flags & ASYNC_CLOSING) &&
-		    (do_clocal || CD))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->port.open_wait, &wait);
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->port.count++;
-	port->port.blocked_open--;
-	spin_unlock_irqrestore(&port->lock, flags);
-	if (retval) {
-		func_exit();
-		return retval;
-	}
-
-	port->port.flags |= ASYNC_NORMAL_ACTIVE;
-	func_exit();
-	return 0;
-}
-
-
-static int sx_open(struct tty_struct *tty, struct file *filp)
-{
-	int board;
-	int error;
-	struct specialix_port *port;
-	struct specialix_board *bp;
-	int i;
-	unsigned long flags;
-
-	func_enter();
-
-	board = SX_BOARD(tty->index);
-
-	if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = &sx_board[board];
-	port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
-	port->overrun = 0;
-	for (i = 0; i < 10; i++)
-		port->hits[i] = 0;
-
-	dprintk(SX_DEBUG_OPEN,
-			"Board = %d, bp = %p, port = %p, portno = %d.\n",
-				 board, bp, port, SX_PORT(tty->index));
-
-	if (sx_paranoia_check(port, tty->name, "sx_open")) {
-		func_enter();
-		return -ENODEV;
-	}
-
-	error = sx_setup_board(bp);
-	if (error) {
-		func_exit();
-		return error;
-	}
-
-	spin_lock_irqsave(&bp->lock, flags);
-	port->port.count++;
-	bp->count++;
-	tty->driver_data = port;
-	port->port.tty = tty;
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	error = sx_setup_port(bp, port);
-	if (error) {
-		func_enter();
-		return error;
-	}
-
-	error = block_til_ready(tty, filp, port);
-	if (error) {
-		func_enter();
-		return error;
-	}
-
-	func_exit();
-	return 0;
-}
-
-static void sx_flush_buffer(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&port->lock, flags);
-	tty_wakeup(tty);
-
-	func_exit();
-}
-
-static void sx_close(struct tty_struct *tty, struct file *filp)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-	unsigned long timeout;
-
-	func_enter();
-	if (!port || sx_paranoia_check(port, tty->name, "close")) {
-		func_exit();
-		return;
-	}
-	spin_lock_irqsave(&port->lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-	if (tty->count == 1 && port->port.count != 1) {
-		printk(KERN_ERR "sx%d: sx_close: bad port count;"
-		       " tty->count is 1, port count is %d\n",
-		       board_No(bp), port->port.count);
-		port->port.count = 1;
-	}
-
-	if (port->port.count > 1) {
-		port->port.count--;
-		bp->count--;
-
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		func_exit();
-		return;
-	}
-	port->port.flags |= ASYNC_CLOSING;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	spin_unlock_irqrestore(&port->lock, flags);
-	dprintk(SX_DEBUG_OPEN, "Closing\n");
-	if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, port->port.closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	dprintk(SX_DEBUG_OPEN, "Closed\n");
-	port->IER &= ~IER_RXD;
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		port->IER &= ~IER_TXRDY;
-		port->IER |= IER_TXEMPTY;
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		timeout = jiffies+HZ;
-		while (port->IER & IER_TXEMPTY) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			msleep_interruptible(jiffies_to_msecs(port->timeout));
-			if (time_after(jiffies, timeout)) {
-				printk(KERN_INFO "Timeout waiting for close\n");
-				break;
-			}
-		}
-
-	}
-
-	if (--bp->count < 0) {
-		printk(KERN_ERR
-		    "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
-				board_No(bp), bp->count, tty->index);
-		bp->count = 0;
-	}
-	if (--port->port.count < 0) {
-		printk(KERN_ERR
-			"sx%d: sx_close: bad port count for tty%d: %d\n",
-				board_No(bp), port_No(port), port->port.count);
-		port->port.count = 0;
-	}
-
-	sx_shutdown_port(bp, port);
-	sx_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	spin_lock_irqsave(&port->lock, flags);
-	tty->closing = 0;
-	port->port.tty = NULL;
-	spin_unlock_irqrestore(&port->lock, flags);
-	if (port->port.blocked_open) {
-		if (port->port.close_delay)
-			msleep_interruptible(
-				jiffies_to_msecs(port->port.close_delay));
-		wake_up_interruptible(&port->port.open_wait);
-	}
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&port->port.close_wait);
-
-	func_exit();
-}
-
-
-static int sx_write(struct tty_struct *tty,
-					const unsigned char *buf, int count)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	int c, total = 0;
-	unsigned long flags;
-
-	func_enter();
-	if (sx_paranoia_check(port, tty->name, "sx_write")) {
-		func_exit();
-		return 0;
-	}
-
-	bp = port_Board(port);
-
-	if (!port->xmit_buf) {
-		func_exit();
-		return 0;
-	}
-
-	while (1) {
-		spin_lock_irqsave(&port->lock, flags);
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0) {
-			spin_unlock_irqrestore(&port->lock, flags);
-			break;
-		}
-		memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	spin_lock_irqsave(&bp->lock, flags);
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-	    !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	func_exit();
-
-	return total;
-}
-
-
-static int sx_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
-		func_exit();
-		return 0;
-	}
-	dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
-	if (!port->xmit_buf) {
-		func_exit();
-		return 0;
-	}
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-
-	dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
-					port->xmit_cnt, port->xmit_buf);
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		dprintk(SX_DEBUG_TX, "Exit size\n");
-		func_exit();
-		return 0;
-	}
-	dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
-	port->xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-	return 1;
-}
-
-
-static void sx_flush_chars(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp = port_Board(port);
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
-		func_exit();
-		return;
-	}
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !port->xmit_buf) {
-		func_exit();
-		return;
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	port->IER |= IER_TXRDY;
-	sx_out(port_Board(port), CD186x_CAR, port_No(port));
-	sx_out(port_Board(port), CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-static int sx_write_room(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	int	ret;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
-		func_exit();
-		return 0;
-	}
-
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-
-	func_exit();
-	return ret;
-}
-
-
-static int sx_chars_in_buffer(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
-		func_exit();
-		return 0;
-	}
-	func_exit();
-	return port->xmit_cnt;
-}
-
-static int sx_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, __func__)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	status = sx_in(bp, CD186x_MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
-			port_No(port), status, sx_in(bp, CD186x_CAR));
-	dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
-	if (sx_crtscts(port->port.tty)) {
-		result  = TIOCM_DTR | TIOCM_DSR
-			  |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
-			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	} else {
-		result  = TIOCM_RTS | TIOCM_DSR
-			  |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
-			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	}
-
-	func_exit();
-
-	return result;
-}
-
-
-static int sx_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, __func__)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (sx_crtscts(port->port.tty)) {
-		if (set & TIOCM_RTS)
-			port->MSVR |= MSVR_DTR;
-	} else {
-		if (set & TIOCM_DTR)
-			port->MSVR |= MSVR_DTR;
-	}
-	if (sx_crtscts(port->port.tty)) {
-		if (clear & TIOCM_RTS)
-			port->MSVR &= ~MSVR_DTR;
-	} else {
-		if (clear & TIOCM_DTR)
-			port->MSVR &= ~MSVR_DTR;
-	}
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	func_exit();
-	return 0;
-}
-
-
-static int sx_send_break(struct tty_struct *tty, int length)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp = port_Board(port);
-	unsigned long flags;
-
-	func_enter();
-	if (length == 0 || length == -1)
-		return -EOPNOTSUPP;
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->break_length = SPECIALIX_TPS / HZ * length;
-	port->COR2 |= COR2_ETC;
-	port->IER  |= IER_TXRDY;
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_COR2, port->COR2);
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_CORCHG2);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	sx_wait_CCR(bp);
-
-	func_exit();
-	return 0;
-}
-
-
-static int sx_set_serial_info(struct specialix_port *port,
-					struct serial_struct __user *newinfo)
-{
-	struct serial_struct tmp;
-	struct specialix_board *bp = port_Board(port);
-	int change_speed;
-
-	func_enter();
-
-	if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
-		func_enter();
-		return -EFAULT;
-	}
-
-	mutex_lock(&port->port.mutex);
-	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
-			(tmp.flags & ASYNC_SPD_MASK));
-	change_speed |= (tmp.custom_divisor != port->custom_divisor);
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((tmp.close_delay != port->port.close_delay) ||
-		    (tmp.closing_wait != port->port.closing_wait) ||
-		    ((tmp.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK))) {
-			func_exit();
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-						(tmp.flags & ASYNC_USR_MASK));
-		port->custom_divisor = tmp.custom_divisor;
-	} else {
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-						(tmp.flags & ASYNC_FLAGS));
-		port->port.close_delay = tmp.close_delay;
-		port->port.closing_wait = tmp.closing_wait;
-		port->custom_divisor = tmp.custom_divisor;
-	}
-	if (change_speed)
-		sx_change_speed(bp, port);
-
-	func_exit();
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-
-static int sx_get_serial_info(struct specialix_port *port,
-				     struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-	struct specialix_board *bp = port_Board(port);
-
-	func_enter();
-
-	memset(&tmp, 0, sizeof(tmp));
-	mutex_lock(&port->port.mutex);
-	tmp.type = PORT_CIRRUS;
-	tmp.line = port - sx_port;
-	tmp.port = bp->base;
-	tmp.irq  = bp->irq;
-	tmp.flags = port->port.flags;
-	tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
-	tmp.close_delay = port->port.close_delay * HZ/100;
-	tmp.closing_wait = port->port.closing_wait * HZ/100;
-	tmp.custom_divisor =  port->custom_divisor;
-	tmp.xmit_fifo_size = CD186x_NFIFO;
-	mutex_unlock(&port->port.mutex);
-	if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
-		func_exit();
-		return -EFAULT;
-	}
-
-	func_exit();
-	return 0;
-}
-
-
-static int sx_ioctl(struct tty_struct *tty, struct file *filp,
-				unsigned int cmd, unsigned long arg)
-{
-	struct specialix_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		func_exit();
-		return sx_get_serial_info(port, argp);
-	case TIOCSSERIAL:
-		func_exit();
-		return sx_set_serial_info(port, argp);
-	default:
-		func_exit();
-		return -ENOIOCTLCMD;
-	}
-	func_exit();
-	return 0;
-}
-
-
-static void sx_throttle(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	/* Use DTR instead of RTS ! */
-	if (sx_crtscts(tty))
-		port->MSVR &= ~MSVR_DTR;
-	else {
-		/* Auch!!! I think the system shouldn't call this then. */
-		/* Or maybe we're supposed (allowed?) to do our side of hw
-		   handshake anyway, even when hardware handshake is off.
-		   When you see this in your logs, please report.... */
-		printk(KERN_ERR
-		   "sx%d: Need to throttle, but can't (hardware hs is off)\n",
-							port_No(port));
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (I_IXOFF(tty)) {
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CCR, CCR_SSCH2);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		sx_wait_CCR(bp);
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_unthrottle(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	/* XXXX Use DTR INSTEAD???? */
-	if (sx_crtscts(tty))
-		port->MSVR |= MSVR_DTR;
-	/* Else clause: see remark in "sx_throttle"... */
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock(&bp->lock);
-	if (I_IXOFF(tty)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CCR, CCR_SSCH1);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&port->lock, flags);
-	}
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_stop(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_stop")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->IER &= ~IER_TXRDY;
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_start(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_start")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		spin_lock(&bp->lock);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock(&bp->lock);
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-static void sx_hangup(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	sx_shutdown_port(bp, port);
-	spin_lock_irqsave(&port->lock, flags);
-	bp->count -= port->port.count;
-	if (bp->count < 0) {
-		printk(KERN_ERR
-			"sx%d: sx_hangup: bad board count: %d port: %d\n",
-					board_No(bp), bp->count, tty->index);
-		bp->count = 0;
-	}
-	port->port.count = 0;
-	port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	port->port.tty = NULL;
-	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&port->port.open_wait);
-
-	func_exit();
-}
-
-
-static void sx_set_termios(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
-		return;
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-	sx_change_speed(port_Board(port), port);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		sx_start(tty);
-	}
-}
-
-static const struct tty_operations sx_ops = {
-	.open  = sx_open,
-	.close = sx_close,
-	.write = sx_write,
-	.put_char = sx_put_char,
-	.flush_chars = sx_flush_chars,
-	.write_room = sx_write_room,
-	.chars_in_buffer = sx_chars_in_buffer,
-	.flush_buffer = sx_flush_buffer,
-	.ioctl = sx_ioctl,
-	.throttle = sx_throttle,
-	.unthrottle = sx_unthrottle,
-	.set_termios = sx_set_termios,
-	.stop = sx_stop,
-	.start = sx_start,
-	.hangup = sx_hangup,
-	.tiocmget = sx_tiocmget,
-	.tiocmset = sx_tiocmset,
-	.break_ctl = sx_send_break,
-};
-
-static int sx_init_drivers(void)
-{
-	int error;
-	int i;
-
-	func_enter();
-
-	specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
-	if (!specialix_driver) {
-		printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
-		func_exit();
-		return 1;
-	}
-
-	specialix_driver->owner = THIS_MODULE;
-	specialix_driver->name = "ttyW";
-	specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
-	specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	specialix_driver->subtype = SERIAL_TYPE_NORMAL;
-	specialix_driver->init_termios = tty_std_termios;
-	specialix_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	specialix_driver->init_termios.c_ispeed = 9600;
-	specialix_driver->init_termios.c_ospeed = 9600;
-	specialix_driver->flags = TTY_DRIVER_REAL_RAW |
-						TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(specialix_driver, &sx_ops);
-
-	error = tty_register_driver(specialix_driver);
-	if (error) {
-		put_tty_driver(specialix_driver);
-		printk(KERN_ERR
-		  "sx: Couldn't register specialix IO8+ driver, error = %d\n",
-								error);
-		func_exit();
-		return 1;
-	}
-	memset(sx_port, 0, sizeof(sx_port));
-	for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
-		sx_port[i].magic = SPECIALIX_MAGIC;
-		tty_port_init(&sx_port[i].port);
-		spin_lock_init(&sx_port[i].lock);
-	}
-
-	func_exit();
-	return 0;
-}
-
-static void sx_release_drivers(void)
-{
-	func_enter();
-
-	tty_unregister_driver(specialix_driver);
-	put_tty_driver(specialix_driver);
-	func_exit();
-}
-
-/*
- * This routine must be called by kernel at boot time
- */
-static int __init specialix_init(void)
-{
-	int i;
-	int found = 0;
-
-	func_enter();
-
-	printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
-	printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
-	if (sx_rtscts)
-		printk(KERN_INFO
-			"sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
-	else
-		printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
-
-	for (i = 0; i < SX_NBOARD; i++)
-		spin_lock_init(&sx_board[i].lock);
-
-	if (sx_init_drivers()) {
-		func_exit();
-		return -EIO;
-	}
-
-	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].base && !sx_probe(&sx_board[i]))
-			found++;
-
-#ifdef CONFIG_PCI
-	{
-		struct pci_dev *pdev = NULL;
-
-		i = 0;
-		while (i < SX_NBOARD) {
-			if (sx_board[i].flags & SX_BOARD_PRESENT) {
-				i++;
-				continue;
-			}
-			pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
-					PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
-			if (!pdev)
-				break;
-
-			if (pci_enable_device(pdev))
-				continue;
-
-			sx_board[i].irq = pdev->irq;
-
-			sx_board[i].base = pci_resource_start(pdev, 2);
-
-			sx_board[i].flags |= SX_BOARD_IS_PCI;
-			if (!sx_probe(&sx_board[i]))
-				found++;
-		}
-		/* May exit pci_get sequence early with lots of boards */
-		if (pdev != NULL)
-			pci_dev_put(pdev);
-	}
-#endif
-
-	if (!found) {
-		sx_release_drivers();
-		printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
-		func_exit();
-		return -EIO;
-	}
-
-	func_exit();
-	return 0;
-}
-
-static int iobase[SX_NBOARD]  = {0,};
-static int irq[SX_NBOARD] = {0,};
-
-module_param_array(iobase, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param(sx_debug, int, 0);
-module_param(sx_rtscts, int, 0);
-module_param(sx_rxfifo, int, 0);
-
-/*
- * You can setup up to 4 boards.
- * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
- * You should specify the IRQs too in that case "irq=....,...".
- *
- * More than 4 boards in one computer is not possible, as the card can
- * only use 4 different interrupts.
- *
- */
-static int __init specialix_init_module(void)
-{
-	int i;
-
-	func_enter();
-
-	if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
-		for (i = 0; i < SX_NBOARD; i++) {
-			sx_board[i].base = iobase[i];
-			sx_board[i].irq = irq[i];
-			sx_board[i].count = 0;
-		}
-	}
-
-	func_exit();
-
-	return specialix_init();
-}
-
-static void __exit specialix_exit_module(void)
-{
-	int i;
-
-	func_enter();
-
-	sx_release_drivers();
-	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].flags & SX_BOARD_PRESENT)
-			sx_release_io_range(&sx_board[i]);
-	func_exit();
-}
-
-static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
-
-module_init(specialix_init_module);
-module_exit(specialix_exit_module);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR);
diff --git a/drivers/char/specialix_io8.h b/drivers/char/specialix_io8.h
deleted file mode 100644
index c630052..0000000
--- a/drivers/char/specialix_io8.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- *      linux/drivers/char/specialix_io8.h  -- 
- *                                   Specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support.
- *
- *      This driver was developped in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- *      This code is firmly based on the riscom/8 serial driver,
- *      written by Dmitry Gorodchanin. The specialix IO8+ card
- *      programming information was obtained from the CL-CD1865 Data
- *      Book, and Specialix document number 6200059: IO8+ Hardware
- *      Functional Specification.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- * */
-
-#ifndef __LINUX_SPECIALIX_H
-#define __LINUX_SPECIALIX_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-/* You can have max 4 ISA cards in one PC, and I recommend not much 
-more than a few  PCI versions of the card. */
-
-#define SX_NBOARD		8
-
-/* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */
-#define SX_IO_SPACE             4
-/* The PCI version decodes 8 addresses, but still only 2 are used. */
-#define SX_PCI_IO_SPACE         8
-
-/* eight ports per board. */
-#define SX_NPORT        	8
-#define SX_BOARD(line)		((line) / SX_NPORT)
-#define SX_PORT(line)		((line) & (SX_NPORT - 1))
-
-
-#define SX_DATA_REG 0     /* Base+0 : Data register */
-#define SX_ADDR_REG 1     /* base+1 : Address register. */
-
-#define MHz *1000000	/* I'm ashamed of myself. */
-
-/* On-board oscillator frequency */
-#define SX_OSCFREQ      (25 MHz/2)
-/* There is a 25MHz crystal on the board, but the chip is in /2 mode */
-
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define SPECIALIX_TPS		4000
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define SPECIALIX_RXFIFO	6	/* Max. receiver FIFO size (1-8) */
-
-#define SPECIALIX_MAGIC		0x0907
-
-#define SX_CCR_TIMEOUT 10000   /* CCR timeout. You may need to wait upto
-                                  10 milliseconds before the internal
-                                  processor is available again after
-                                  you give it a command */
-
-#define SX_IOBASE1	0x100
-#define SX_IOBASE2	0x180
-#define SX_IOBASE3	0x250
-#define SX_IOBASE4	0x260
-
-struct specialix_board {
-	unsigned long   flags;
-	unsigned short	base;
-	unsigned char 	irq;
-	//signed   char	count;
-	int count;
-	unsigned char	DTR;
-        int reg;
-	spinlock_t lock;
-};
-
-#define SX_BOARD_PRESENT	0x00000001
-#define SX_BOARD_ACTIVE		0x00000002
-#define SX_BOARD_IS_PCI		0x00000004
-
-
-struct specialix_port {
-	int			magic;
-	struct tty_port		port;
-	int			baud_base;
-	int			flags;
-	int			timeout;
-	unsigned char 		* xmit_buf;
-	int			custom_divisor;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	short			wakeup_chars;
-	short			break_length;
-	unsigned char		mark_mask;
-	unsigned char		IER;
-	unsigned char		MSVR;
-	unsigned char		COR2;
-	unsigned long		overrun;
-	unsigned long		hits[10];
-	spinlock_t lock;
-};
-
-#endif /* __KERNEL__ */
-#endif /* __LINUX_SPECIALIX_H */
-
-
-
-
-
-
-
-
-
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
deleted file mode 100644
index 461a5a0..0000000
--- a/drivers/char/stallion.c
+++ /dev/null
@@ -1,4652 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	stallion.c  -- stallion multiport serial driver.
- *
- *	Copyright (C) 1996-1999  Stallion Technologies
- *	Copyright (C) 1994-1996  Greg Ungerer.
- *
- *	This code is loosely based on the Linux serial driver, written by
- *	Linus Torvalds, Theodore T'so and others.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*****************************************************************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/seq_file.h>
-#include <linux/cd1400.h>
-#include <linux/sc26198.h>
-#include <linux/comstats.h>
-#include <linux/stallion.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/pci.h>
-
-/*****************************************************************************/
-
-/*
- *	Define different board types. Use the standard Stallion "assigned"
- *	board numbers. Boards supported in this driver are abbreviated as
- *	EIO = EasyIO and ECH = EasyConnection 8/32.
- */
-#define	BRD_EASYIO	20
-#define	BRD_ECH		21
-#define	BRD_ECHMC	22
-#define	BRD_ECHPCI	26
-#define	BRD_ECH64PCI	27
-#define	BRD_EASYIOPCI	28
-
-struct stlconf {
-	unsigned int	brdtype;
-	int		ioaddr1;
-	int		ioaddr2;
-	unsigned long	memaddr;
-	int		irq;
-	int		irqtype;
-};
-
-static unsigned int stl_nrbrds;
-
-/*****************************************************************************/
-
-/*
- *	Define some important driver characteristics. Device major numbers
- *	allocated as per Linux Device Registry.
- */
-#ifndef	STL_SIOMEMMAJOR
-#define	STL_SIOMEMMAJOR		28
-#endif
-#ifndef	STL_SERIALMAJOR
-#define	STL_SERIALMAJOR		24
-#endif
-#ifndef	STL_CALLOUTMAJOR
-#define	STL_CALLOUTMAJOR	25
-#endif
-
-/*
- *	Set the TX buffer size. Bigger is better, but we don't want
- *	to chew too much memory with buffers!
- */
-#define	STL_TXBUFLOW		512
-#define	STL_TXBUFSIZE		4096
-
-/*****************************************************************************/
-
-/*
- *	Define our local driver identity first. Set up stuff to deal with
- *	all the local structures required by a serial tty driver.
- */
-static char	*stl_drvtitle = "Stallion Multiport Serial Driver";
-static char	*stl_drvname = "stallion";
-static char	*stl_drvversion = "5.6.0";
-
-static struct tty_driver	*stl_serial;
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially. Basically all it defines is a raw port
- *	at 9600, 8 data bits, 1 stop bit.
- */
-static struct ktermios		stl_deftermios = {
-	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_cc		= INIT_C_CC,
-	.c_ispeed	= 9600,
-	.c_ospeed	= 9600,
-};
-
-/*
- *	Define global place to put buffer overflow characters.
- */
-static char		stl_unwanted[SC26198_RXFIFOSIZE];
-
-/*****************************************************************************/
-
-static DEFINE_MUTEX(stl_brdslock);
-static struct stlbrd		*stl_brds[STL_MAXBRDS];
-
-static const struct tty_port_operations stl_port_ops;
-
-/*
- *	Per board state flags. Used with the state field of the board struct.
- *	Not really much here!
- */
-#define	BRD_FOUND	0x1
-#define STL_PROBED	0x2
-
-
-/*
- *	Define the port structure istate flags. These set of flags are
- *	modified at interrupt time - so setting and reseting them needs
- *	to be atomic. Use the bit clear/setting routines for this.
- */
-#define	ASYI_TXBUSY	1
-#define	ASYI_TXLOW	2
-#define	ASYI_TXFLOWED	3
-
-/*
- *	Define an array of board names as printable strings. Handy for
- *	referencing boards when printing trace and stuff.
- */
-static char	*stl_brdnames[] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"EasyIO",
-	"EC8/32-AT",
-	"EC8/32-MC",
-	NULL,
-	NULL,
-	NULL,
-	"EC8/32-PCI",
-	"EC8/64-PCI",
-	"EasyIO-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *	Define some string labels for arguments passed from the module
- *	load line. These allow for easy board definitions, and easy
- *	modification of the io, memory and irq resoucres.
- */
-static unsigned int stl_nargs;
-static char	*board0[4];
-static char	*board1[4];
-static char	*board2[4];
-static char	*board3[4];
-
-static char	**stl_brdsp[] = {
-	(char **) &board0,
-	(char **) &board1,
-	(char **) &board2,
-	(char **) &board3
-};
-
-/*
- *	Define a set of common board names, and types. This is used to
- *	parse any module arguments.
- */
-
-static struct {
-	char	*name;
-	int	type;
-} stl_brdstr[] = {
-	{ "easyio", BRD_EASYIO },
-	{ "eio", BRD_EASYIO },
-	{ "20", BRD_EASYIO },
-	{ "ec8/32", BRD_ECH },
-	{ "ec8/32-at", BRD_ECH },
-	{ "ec8/32-isa", BRD_ECH },
-	{ "ech", BRD_ECH },
-	{ "echat", BRD_ECH },
-	{ "21", BRD_ECH },
-	{ "ec8/32-mc", BRD_ECHMC },
-	{ "ec8/32-mca", BRD_ECHMC },
-	{ "echmc", BRD_ECHMC },
-	{ "echmca", BRD_ECHMC },
-	{ "22", BRD_ECHMC },
-	{ "ec8/32-pc", BRD_ECHPCI },
-	{ "ec8/32-pci", BRD_ECHPCI },
-	{ "26", BRD_ECHPCI },
-	{ "ec8/64-pc", BRD_ECH64PCI },
-	{ "ec8/64-pci", BRD_ECH64PCI },
-	{ "ech-pci", BRD_ECH64PCI },
-	{ "echpci", BRD_ECH64PCI },
-	{ "echpc", BRD_ECH64PCI },
-	{ "27", BRD_ECH64PCI },
-	{ "easyio-pc", BRD_EASYIOPCI },
-	{ "easyio-pci", BRD_EASYIOPCI },
-	{ "eio-pci", BRD_EASYIOPCI },
-	{ "eiopci", BRD_EASYIOPCI },
-	{ "28", BRD_EASYIOPCI },
-};
-
-/*
- *	Define the module agruments.
- */
-
-module_param_array(board0, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board1, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board2, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board3, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
-
-/*****************************************************************************/
-
-/*
- *	Hardware ID bits for the EasyIO and ECH boards. These defines apply
- *	to the directly accessible io ports of these boards (not the uarts -
- *	they are in cd1400.h and sc26198.h).
- */
-#define	EIO_8PORTRS	0x04
-#define	EIO_4PORTRS	0x05
-#define	EIO_8PORTDI	0x00
-#define	EIO_8PORTM	0x06
-#define	EIO_MK3		0x03
-#define	EIO_IDBITMASK	0x07
-
-#define	EIO_BRDMASK	0xf0
-#define	ID_BRD4		0x10
-#define	ID_BRD8		0x20
-#define	ID_BRD16	0x30
-
-#define	EIO_INTRPEND	0x08
-#define	EIO_INTEDGE	0x00
-#define	EIO_INTLEVEL	0x08
-#define	EIO_0WS		0x10
-
-#define	ECH_ID		0xa0
-#define	ECH_IDBITMASK	0xe0
-#define	ECH_BRDENABLE	0x08
-#define	ECH_BRDDISABLE	0x00
-#define	ECH_INTENABLE	0x01
-#define	ECH_INTDISABLE	0x00
-#define	ECH_INTLEVEL	0x02
-#define	ECH_INTEDGE	0x00
-#define	ECH_INTRPEND	0x01
-#define	ECH_BRDRESET	0x01
-
-#define	ECHMC_INTENABLE	0x01
-#define	ECHMC_BRDRESET	0x02
-
-#define	ECH_PNLSTATUS	2
-#define	ECH_PNL16PORT	0x20
-#define	ECH_PNLIDMASK	0x07
-#define	ECH_PNLXPID	0x40
-#define	ECH_PNLINTRPEND	0x80
-
-#define	ECH_ADDR2MASK	0x1e0
-
-/*
- *	Define the vector mapping bits for the programmable interrupt board
- *	hardware. These bits encode the interrupt for the board to use - it
- *	is software selectable (except the EIO-8M).
- */
-static unsigned char	stl_vecmap[] = {
-	0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
-	0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
-};
-
-/*
- *	Lock ordering is that you may not take stallion_lock holding
- *	brd_lock.
- */
-
-static spinlock_t brd_lock; 		/* Guard the board mapping */
-static spinlock_t stallion_lock;	/* Guard the tty driver */
-
-/*
- *	Set up enable and disable macros for the ECH boards. They require
- *	the secondary io address space to be activated and deactivated.
- *	This way all ECH boards can share their secondary io region.
- *	If this is an ECH-PCI board then also need to set the page pointer
- *	to point to the correct page.
- */
-#define	BRDENABLE(brdnr,pagenr)						\
-	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
-		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE),	\
-			stl_brds[(brdnr)]->ioctrl);			\
-	else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI)		\
-		outb((pagenr), stl_brds[(brdnr)]->ioctrl);
-
-#define	BRDDISABLE(brdnr)						\
-	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
-		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE),	\
-			stl_brds[(brdnr)]->ioctrl);
-
-#define	STL_CD1400MAXBAUD	230400
-#define	STL_SC26198MAXBAUD	460800
-
-#define	STL_BAUDBASE		115200
-#define	STL_CLOSEDELAY		(5 * HZ / 10)
-
-/*****************************************************************************/
-
-/*
- *	Define the Stallion PCI vendor and device IDs.
- */
-#ifndef	PCI_VENDOR_ID_STALLION
-#define	PCI_VENDOR_ID_STALLION		0x124d
-#endif
-#ifndef PCI_DEVICE_ID_ECHPCI832
-#define	PCI_DEVICE_ID_ECHPCI832		0x0000
-#endif
-#ifndef PCI_DEVICE_ID_ECHPCI864
-#define	PCI_DEVICE_ID_ECHPCI864		0x0002
-#endif
-#ifndef PCI_DEVICE_ID_EIOPCI
-#define	PCI_DEVICE_ID_EIOPCI		0x0003
-#endif
-
-/*
- *	Define structure to hold all Stallion PCI boards.
- */
-
-static struct pci_device_id stl_pcibrds[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
-		.driver_data = BRD_ECH64PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
-		.driver_data = BRD_EASYIOPCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
-		.driver_data = BRD_ECHPCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
-		.driver_data = BRD_ECHPCI },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, stl_pcibrds);
-
-/*****************************************************************************/
-
-/*
- *	Define macros to extract a brd/port number from a minor number.
- */
-#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
-#define	MINOR2PORT(min)		((min) & 0x3f)
-
-/*
- *	Define a baud rate table that converts termios baud rate selector
- *	into the actual baud rate value. All baud rate calculations are
- *	based on the actual baud rate required.
- */
-static unsigned int	stl_baudrates[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
-};
-
-/*****************************************************************************/
-
-/*
- *	Declare all those functions in this driver!
- */
-
-static long	stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-static int	stl_brdinit(struct stlbrd *brdp);
-static int	stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
-static int	stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-
-/*
- *	CD1400 uart specific handling functions.
- */
-static void	stl_cd1400setreg(struct stlport *portp, int regnr, int value);
-static int	stl_cd1400getreg(struct stlport *portp, int regnr);
-static int	stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
-static int	stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
-static void	stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-static void	stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
-static int	stl_cd1400getsignals(struct stlport *portp);
-static void	stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
-static void	stl_cd1400ccrwait(struct stlport *portp);
-static void	stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
-static void	stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
-static void	stl_cd1400disableintrs(struct stlport *portp);
-static void	stl_cd1400sendbreak(struct stlport *portp, int len);
-static void	stl_cd1400flowctrl(struct stlport *portp, int state);
-static void	stl_cd1400sendflow(struct stlport *portp, int state);
-static void	stl_cd1400flush(struct stlport *portp);
-static int	stl_cd1400datastate(struct stlport *portp);
-static void	stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
-static void	stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
-static void	stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
-
-static inline int	stl_cd1400breakisr(struct stlport *portp, int ioaddr);
-
-/*
- *	SC26198 uart specific handling functions.
- */
-static void	stl_sc26198setreg(struct stlport *portp, int regnr, int value);
-static int	stl_sc26198getreg(struct stlport *portp, int regnr);
-static int	stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
-static int	stl_sc26198getglobreg(struct stlport *portp, int regnr);
-static int	stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
-static void	stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-static void	stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
-static int	stl_sc26198getsignals(struct stlport *portp);
-static void	stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
-static void	stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
-static void	stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
-static void	stl_sc26198disableintrs(struct stlport *portp);
-static void	stl_sc26198sendbreak(struct stlport *portp, int len);
-static void	stl_sc26198flowctrl(struct stlport *portp, int state);
-static void	stl_sc26198sendflow(struct stlport *portp, int state);
-static void	stl_sc26198flush(struct stlport *portp);
-static int	stl_sc26198datastate(struct stlport *portp);
-static void	stl_sc26198wait(struct stlport *portp);
-static void	stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
-static void	stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_sc26198txisr(struct stlport *port);
-static void	stl_sc26198rxisr(struct stlport *port, unsigned int iack);
-static void	stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
-static void	stl_sc26198rxbadchars(struct stlport *portp);
-static void	stl_sc26198otherisr(struct stlport *port, unsigned int iack);
-
-/*****************************************************************************/
-
-/*
- *	Generic UART support structure.
- */
-typedef struct uart {
-	int	(*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
-	void	(*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-	void	(*setport)(struct stlport *portp, struct ktermios *tiosp);
-	int	(*getsignals)(struct stlport *portp);
-	void	(*setsignals)(struct stlport *portp, int dtr, int rts);
-	void	(*enablerxtx)(struct stlport *portp, int rx, int tx);
-	void	(*startrxtx)(struct stlport *portp, int rx, int tx);
-	void	(*disableintrs)(struct stlport *portp);
-	void	(*sendbreak)(struct stlport *portp, int len);
-	void	(*flowctrl)(struct stlport *portp, int state);
-	void	(*sendflow)(struct stlport *portp, int state);
-	void	(*flush)(struct stlport *portp);
-	int	(*datastate)(struct stlport *portp);
-	void	(*intr)(struct stlpanel *panelp, unsigned int iobase);
-} uart_t;
-
-/*
- *	Define some macros to make calling these functions nice and clean.
- */
-#define	stl_panelinit		(* ((uart_t *) panelp->uartp)->panelinit)
-#define	stl_portinit		(* ((uart_t *) portp->uartp)->portinit)
-#define	stl_setport		(* ((uart_t *) portp->uartp)->setport)
-#define	stl_getsignals		(* ((uart_t *) portp->uartp)->getsignals)
-#define	stl_setsignals		(* ((uart_t *) portp->uartp)->setsignals)
-#define	stl_enablerxtx		(* ((uart_t *) portp->uartp)->enablerxtx)
-#define	stl_startrxtx		(* ((uart_t *) portp->uartp)->startrxtx)
-#define	stl_disableintrs	(* ((uart_t *) portp->uartp)->disableintrs)
-#define	stl_sendbreak		(* ((uart_t *) portp->uartp)->sendbreak)
-#define	stl_flowctrl		(* ((uart_t *) portp->uartp)->flowctrl)
-#define	stl_sendflow		(* ((uart_t *) portp->uartp)->sendflow)
-#define	stl_flush		(* ((uart_t *) portp->uartp)->flush)
-#define	stl_datastate		(* ((uart_t *) portp->uartp)->datastate)
-
-/*****************************************************************************/
-
-/*
- *	CD1400 UART specific data initialization.
- */
-static uart_t stl_cd1400uart = {
-	stl_cd1400panelinit,
-	stl_cd1400portinit,
-	stl_cd1400setport,
-	stl_cd1400getsignals,
-	stl_cd1400setsignals,
-	stl_cd1400enablerxtx,
-	stl_cd1400startrxtx,
-	stl_cd1400disableintrs,
-	stl_cd1400sendbreak,
-	stl_cd1400flowctrl,
-	stl_cd1400sendflow,
-	stl_cd1400flush,
-	stl_cd1400datastate,
-	stl_cd1400eiointr
-};
-
-/*
- *	Define the offsets within the register bank of a cd1400 based panel.
- *	These io address offsets are common to the EasyIO board as well.
- */
-#define	EREG_ADDR	0
-#define	EREG_DATA	4
-#define	EREG_RXACK	5
-#define	EREG_TXACK	6
-#define	EREG_MDACK	7
-
-#define	EREG_BANKSIZE	8
-
-#define	CD1400_CLK	25000000
-#define	CD1400_CLK8M	20000000
-
-/*
- *	Define the cd1400 baud rate clocks. These are used when calculating
- *	what clock and divisor to use for the required baud rate. Also
- *	define the maximum baud rate allowed, and the default base baud.
- */
-static int	stl_cd1400clkdivs[] = {
-	CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
-};
-
-/*****************************************************************************/
-
-/*
- *	SC26198 UART specific data initization.
- */
-static uart_t stl_sc26198uart = {
-	stl_sc26198panelinit,
-	stl_sc26198portinit,
-	stl_sc26198setport,
-	stl_sc26198getsignals,
-	stl_sc26198setsignals,
-	stl_sc26198enablerxtx,
-	stl_sc26198startrxtx,
-	stl_sc26198disableintrs,
-	stl_sc26198sendbreak,
-	stl_sc26198flowctrl,
-	stl_sc26198sendflow,
-	stl_sc26198flush,
-	stl_sc26198datastate,
-	stl_sc26198intr
-};
-
-/*
- *	Define the offsets within the register bank of a sc26198 based panel.
- */
-#define	XP_DATA		0
-#define	XP_ADDR		1
-#define	XP_MODID	2
-#define	XP_STATUS	2
-#define	XP_IACK		3
-
-#define	XP_BANKSIZE	4
-
-/*
- *	Define the sc26198 baud rate table. Offsets within the table
- *	represent the actual baud rate selector of sc26198 registers.
- */
-static unsigned int	sc26198_baudtable[] = {
-	50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
-	4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
-	230400, 460800, 921600
-};
-
-#define	SC26198_NRBAUDS		ARRAY_SIZE(sc26198_baudtable)
-
-/*****************************************************************************/
-
-/*
- *	Define the driver info for a user level control device. Used mainly
- *	to get at port stats - only not using the port device itself.
- */
-static const struct file_operations	stl_fsiomem = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= stl_memioctl,
-	.llseek		= noop_llseek,
-};
-
-static struct class *stallion_class;
-
-static void stl_cd_change(struct stlport *portp)
-{
-	unsigned int oldsigs = portp->sigs;
-	struct tty_struct *tty = tty_port_tty_get(&portp->port);
-
-	if (!tty)
-		return;
-
-	portp->sigs = stl_getsignals(portp);
-
-	if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
-		wake_up_interruptible(&portp->port.open_wait);
-
-	if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
-		if (portp->port.flags & ASYNC_CHECK_CD)
-			tty_hangup(tty);
-	tty_kref_put(tty);
-}
-
-/*
- *	Check for any arguments passed in on the module load command line.
- */
-
-/*****************************************************************************/
-
-/*
- *	Parse the supplied argument string, into the board conf struct.
- */
-
-static int __init stl_parsebrd(struct stlconf *confp, char **argp)
-{
-	char	*sp;
-	unsigned int i;
-
-	pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
-
-	if ((argp[0] == NULL) || (*argp[0] == 0))
-		return 0;
-
-	for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
-		*sp = tolower(*sp);
-
-	for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
-		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
-			break;
-
-	if (i == ARRAY_SIZE(stl_brdstr)) {
-		printk("STALLION: unknown board name, %s?\n", argp[0]);
-		return 0;
-	}
-
-	confp->brdtype = stl_brdstr[i].type;
-
-	i = 1;
-	if ((argp[i] != NULL) && (*argp[i] != 0))
-		confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
-	i++;
-	if (confp->brdtype == BRD_ECH) {
-		if ((argp[i] != NULL) && (*argp[i] != 0))
-			confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
-		i++;
-	}
-	if ((argp[i] != NULL) && (*argp[i] != 0))
-		confp->irq = simple_strtoul(argp[i], NULL, 0);
-	return 1;
-}
-
-/*****************************************************************************/
-
-/*
- *	Allocate a new board structure. Fill out the basic info in it.
- */
-
-static struct stlbrd *stl_allocbrd(void)
-{
-	struct stlbrd	*brdp;
-
-	brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
-	if (!brdp) {
-		printk("STALLION: failed to allocate memory (size=%Zd)\n",
-			sizeof(struct stlbrd));
-		return NULL;
-	}
-
-	brdp->magic = STL_BOARDMAGIC;
-	return brdp;
-}
-
-/*****************************************************************************/
-
-static int stl_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	if (!portp->tx.buf) {
-		portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
-		if (!portp->tx.buf)
-			return -ENOMEM;
-		portp->tx.head = portp->tx.buf;
-		portp->tx.tail = portp->tx.buf;
-	}
-	stl_setport(portp, tty->termios);
-	portp->sigs = stl_getsignals(portp);
-	stl_setsignals(portp, 1, 1);
-	stl_enablerxtx(portp, 1, 1);
-	stl_startrxtx(portp, 1, 0);
-	return 0;
-}
-
-static int stl_open(struct tty_struct *tty, struct file *filp)
-{
-	struct stlport	*portp;
-	struct stlbrd	*brdp;
-	unsigned int	minordev, brdnr, panelnr;
-	int		portnr;
-
-	pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
-
-	minordev = tty->index;
-	brdnr = MINOR2BRD(minordev);
-	if (brdnr >= stl_nrbrds)
-		return -ENODEV;
-	brdp = stl_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	minordev = MINOR2PORT(minordev);
-	for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
-		if (brdp->panels[panelnr] == NULL)
-			break;
-		if (minordev < brdp->panels[panelnr]->nrports) {
-			portnr = minordev;
-			break;
-		}
-		minordev -= brdp->panels[panelnr]->nrports;
-	}
-	if (portnr < 0)
-		return -ENODEV;
-
-	portp = brdp->panels[panelnr]->ports[portnr];
-	if (portp == NULL)
-		return -ENODEV;
-
-	tty->driver_data = portp;
-	return tty_port_open(&portp->port, tty, filp);
-
-}
-
-/*****************************************************************************/
-
-static int stl_carrier_raised(struct tty_port *port)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	return (portp->sigs & TIOCM_CD) ? 1 : 0;
-}
-
-static void stl_dtr_rts(struct tty_port *port, int on)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	/* Takes brd_lock internally */
-	stl_setsignals(portp, on, on);
-}
-
-/*****************************************************************************/
-
-static void stl_flushbuffer(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_flushbuffer(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	stl_flush(portp);
-	tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_waituntilsent(struct tty_struct *tty, int timeout)
-{
-	struct stlport	*portp;
-	unsigned long	tend;
-
-	pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (timeout == 0)
-		timeout = HZ;
-	tend = jiffies + timeout;
-
-	while (stl_datastate(portp)) {
-		if (signal_pending(current))
-			break;
-		msleep_interruptible(20);
-		if (time_after_eq(jiffies, tend))
-			break;
-	}
-}
-
-/*****************************************************************************/
-
-static void stl_shutdown(struct tty_port *port)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	stl_disableintrs(portp);
-	stl_enablerxtx(portp, 0, 0);
-	stl_flush(portp);
-	portp->istate = 0;
-	if (portp->tx.buf != NULL) {
-		kfree(portp->tx.buf);
-		portp->tx.buf = NULL;
-		portp->tx.head = NULL;
-		portp->tx.tail = NULL;
-	}
-}
-
-static void stl_close(struct tty_struct *tty, struct file *filp)
-{
-	struct stlport*portp;
-	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
-
-	portp = tty->driver_data;
-	if(portp == NULL)
-		return;
-	tty_port_close(&portp->port, tty, filp);
-}
-
-/*****************************************************************************/
-
-/*
- *	Write routine. Take data and stuff it in to the TX ring queue.
- *	If transmit interrupts are not running then start them.
- */
-
-static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct stlport	*portp;
-	unsigned int	len, stlen;
-	unsigned char	*chbuf;
-	char		*head, *tail;
-
-	pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-/*
- *	If copying direct from user space we must cater for page faults,
- *	causing us to "sleep" here for a while. To handle this copy in all
- *	the data we need now, into a local buffer. Then when we got it all
- *	copy it into the TX buffer.
- */
-	chbuf = (unsigned char *) buf;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	if (head >= tail) {
-		len = STL_TXBUFSIZE - (head - tail) - 1;
-		stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, (unsigned int)count);
-	count = 0;
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy(head, chbuf, stlen);
-		len -= stlen;
-		chbuf += stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
-			head = portp->tx.buf;
-			stlen = tail - head;
-		}
-	}
-	portp->tx.head = head;
-
-	clear_bit(ASYI_TXLOW, &portp->istate);
-	stl_startrxtx(portp, -1, 1);
-
-	return count;
-}
-
-/*****************************************************************************/
-
-static int stl_putchar(struct tty_struct *tty, unsigned char ch)
-{
-	struct stlport	*portp;
-	unsigned int	len;
-	char		*head, *tail;
-
-	pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-	if (portp->tx.buf == NULL)
-		return -EINVAL;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-
-	len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
-	len--;
-
-	if (len > 0) {
-		*head++ = ch;
-		if (head >= (portp->tx.buf + STL_TXBUFSIZE))
-			head = portp->tx.buf;
-	}	
-	portp->tx.head = head;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	If there are any characters in the buffer then make sure that TX
- *	interrupts are on and get'em out. Normally used after the putchar
- *	routine has been called.
- */
-
-static void stl_flushchars(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_flushchars(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->tx.buf == NULL)
-		return;
-
-	stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-static int stl_writeroom(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-	char		*head, *tail;
-
-	pr_debug("stl_writeroom(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return number of chars in the TX buffer. Normally we would just
- *	calculate the number of chars in the buffer and return that, but if
- *	the buffer is empty and TX interrupts are still on then we return
- *	that the buffer still has 1 char in it. This way whoever called us
- *	will not think that ALL chars have drained - since the UART still
- *	must have some chars in it (we are busy after all).
- */
-
-static int stl_charsinbuffer(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-	unsigned int	size;
-	char		*head, *tail;
-
-	pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
-		size = 1;
-	return size;
-}
-
-/*****************************************************************************/
-
-/*
- *	Generate the serial struct info.
- */
-
-static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
-{
-	struct serial_struct	sio;
-	struct stlbrd		*brdp;
-
-	pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-
-	mutex_lock(&portp->port.mutex);
-	sio.line = portp->portnr;
-	sio.port = portp->ioaddr;
-	sio.flags = portp->port.flags;
-	sio.baud_base = portp->baud_base;
-	sio.close_delay = portp->close_delay;
-	sio.closing_wait = portp->closing_wait;
-	sio.custom_divisor = portp->custom_divisor;
-	sio.hub6 = 0;
-	if (portp->uartp == &stl_cd1400uart) {
-		sio.type = PORT_CIRRUS;
-		sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
-	} else {
-		sio.type = PORT_UNKNOWN;
-		sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
-	}
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp != NULL)
-		sio.irq = brdp->irq;
-	mutex_unlock(&portp->port.mutex);
-
-	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Set port according to the serial struct info.
- *	At this point we do not do any auto-configure stuff, so we will
- *	just quietly ignore any requests to change irq, etc.
- */
-
-static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
-{
-	struct stlport *	portp = tty->driver_data;
-	struct serial_struct	sio;
-
-	pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return -EFAULT;
-	mutex_lock(&portp->port.mutex);
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != portp->baud_base) ||
-		    (sio.close_delay != portp->close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		    (portp->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&portp->port.mutex);
-			return -EPERM;
-		}
-	} 
-
-	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-	portp->baud_base = sio.baud_base;
-	portp->close_delay = sio.close_delay;
-	portp->closing_wait = sio.closing_wait;
-	portp->custom_divisor = sio.custom_divisor;
-	mutex_unlock(&portp->port.mutex);
-	stl_setport(portp, tty->termios);
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int stl_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct stlport	*portp;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	return stl_getsignals(portp);
-}
-
-static int stl_tiocmset(struct tty_struct *tty, struct file *file,
-			unsigned int set, unsigned int clear)
-{
-	struct stlport	*portp;
-	int rts = -1, dtr = -1;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	stl_setsignals(portp, dtr, rts);
-	return 0;
-}
-
-static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct stlport	*portp;
-	int		rc;
-	void __user *argp = (void __user *)arg;
-
-	pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
-			arg);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
-
-	rc = 0;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = stl_getserial(portp, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = stl_setserial(tty, argp);
-		break;
-	case COM_GETPORTSTATS:
-		rc = stl_getportstats(tty, portp, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stl_clrportstats(portp, argp);
-		break;
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERSWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Start the transmitter again. Just turn TX interrupts back on.
- */
-
-static void stl_start(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_start(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct stlport	*portp;
-	struct ktermios	*tiosp;
-
-	pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	tiosp = tty->termios;
-	if ((tiosp->c_cflag == old->c_cflag) &&
-	    (tiosp->c_iflag == old->c_iflag))
-		return;
-
-	stl_setport(portp, tiosp);
-	stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
-		-1);
-	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
-		tty->hw_stopped = 0;
-		stl_start(tty);
-	}
-	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
-		wake_up_interruptible(&portp->port.open_wait);
-}
-
-/*****************************************************************************/
-
-/*
- *	Attempt to flow control who ever is sending us data. Based on termios
- *	settings use software or/and hardware flow control.
- */
-
-static void stl_throttle(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_throttle(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_flowctrl(portp, 0);
-}
-
-/*****************************************************************************/
-
-/*
- *	Unflow control the device sending us data...
- */
-
-static void stl_unthrottle(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_unthrottle(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_flowctrl(portp, 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Stop the transmitter. Basically to do this we will just turn TX
- *	interrupts off.
- */
-
-static void stl_stop(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_stop(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_startrxtx(portp, -1, 0);
-}
-
-/*****************************************************************************/
-
-/*
- *	Hangup this port. This is pretty much like closing the port, only
- *	a little more brutal. No waiting for data to drain. Shutdown the
- *	port and maybe drop signals.
- */
-
-static void stl_hangup(struct tty_struct *tty)
-{
-	struct stlport	*portp = tty->driver_data;
-	pr_debug("stl_hangup(tty=%p)\n", tty);
-
-	if (portp == NULL)
-		return;
-	tty_port_hangup(&portp->port);
-}
-
-/*****************************************************************************/
-
-static int stl_breakctl(struct tty_struct *tty, int state)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-
-	stl_sendbreak(portp, ((state == -1) ? 1 : 2));
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void stl_sendxchar(struct tty_struct *tty, char ch)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (ch == STOP_CHAR(tty))
-		stl_sendflow(portp, 0);
-	else if (ch == START_CHAR(tty))
-		stl_sendflow(portp, 1);
-	else
-		stl_putchar(tty, ch);
-}
-
-static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
-{
-	int	sigs;
-	char sep;
-
-	seq_printf(m, "%d: uart:%s tx:%d rx:%d",
-		portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
-		(int) portp->stats.txtotal, (int) portp->stats.rxtotal);
-
-	if (portp->stats.rxframing)
-		seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
-	if (portp->stats.rxparity)
-		seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
-	if (portp->stats.rxbreaks)
-		seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
-	if (portp->stats.rxoverrun)
-		seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
-
-	sigs = stl_getsignals(portp);
-	sep = ' ';
-	if (sigs & TIOCM_RTS) {
-		seq_printf(m, "%c%s", sep, "RTS");
-		sep = '|';
-	}
-	if (sigs & TIOCM_CTS) {
-		seq_printf(m, "%c%s", sep, "CTS");
-		sep = '|';
-	}
-	if (sigs & TIOCM_DTR) {
-		seq_printf(m, "%c%s", sep, "DTR");
-		sep = '|';
-	}
-	if (sigs & TIOCM_CD) {
-		seq_printf(m, "%c%s", sep, "DCD");
-		sep = '|';
-	}
-	if (sigs & TIOCM_DSR) {
-		seq_printf(m, "%c%s", sep, "DSR");
-		sep = '|';
-	}
-	seq_putc(m, '\n');
-}
-
-/*****************************************************************************/
-
-/*
- *	Port info, read from the /proc file system.
- */
-
-static int stl_proc_show(struct seq_file *m, void *v)
-{
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-	struct stlport	*portp;
-	unsigned int	brdnr, panelnr, portnr;
-	int		totalport;
-
-	totalport = 0;
-
-	seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-/*
- *	We scan through for each board, panel and port. The offset is
- *	calculated on the fly, and irrelevant ports are skipped.
- */
-	for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
-		brdp = stl_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-
-		totalport = brdnr * STL_MAXPORTS;
-		for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
-			panelp = brdp->panels[panelnr];
-			if (panelp == NULL)
-				continue;
-
-			for (portnr = 0; portnr < panelp->nrports; portnr++,
-			    totalport++) {
-				portp = panelp->ports[portnr];
-				if (portp == NULL)
-					continue;
-				stl_portinfo(m, portp, totalport);
-			}
-		}
-	}
-	return 0;
-}
-
-static int stl_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, stl_proc_show, NULL);
-}
-
-static const struct file_operations stl_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= stl_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*****************************************************************************/
-
-/*
- *	All board interrupts are vectored through here first. This code then
- *	calls off to the approrpriate board interrupt handlers.
- */
-
-static irqreturn_t stl_intr(int irq, void *dev_id)
-{
-	struct stlbrd *brdp = dev_id;
-
-	pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
-
-	return IRQ_RETVAL((* brdp->isr)(brdp));
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for EasyIO board types.
- */
-
-static int stl_eiointr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	iobase;
-	int		handled = 0;
-
-	spin_lock(&brd_lock);
-	panelp = brdp->panels[0];
-	iobase = panelp->iobase;
-	while (inb(brdp->iostatus) & EIO_INTRPEND) {
-		handled = 1;
-		(* panelp->isr)(panelp, iobase);
-	}
-	spin_unlock(&brd_lock);
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-AT board types.
- */
-
-static int stl_echatintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
-
-	while (inb(brdp->iostatus) & ECH_INTRPEND) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-
-	outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
-
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-MCA board types.
- */
-
-static int stl_echmcaintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	while (inb(brdp->iostatus) & ECH_INTRPEND) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-PCI board types.
- */
-
-static int stl_echpciintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr, recheck;
-	int		handled = 0;
-
-	while (1) {
-		recheck = 0;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-				recheck++;
-				handled = 1;
-			}
-		}
-		if (! recheck)
-			break;
-	}
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-8/64-PCI board types.
- */
-
-static int stl_echpci64intr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	while (inb(brdp->ioctrl) & 0x1) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize all the ports on a panel.
- */
-
-static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	struct stlport *portp;
-	unsigned int i;
-	int chipmask;
-
-	pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	chipmask = stl_panelinit(brdp, panelp);
-
-/*
- *	All UART's are initialized (if found!). Now go through and setup
- *	each ports data structures.
- */
-	for (i = 0; i < panelp->nrports; i++) {
-		portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
-		if (!portp) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlport));
-			break;
-		}
-		tty_port_init(&portp->port);
-		portp->port.ops = &stl_port_ops;
-		portp->magic = STL_PORTMAGIC;
-		portp->portnr = i;
-		portp->brdnr = panelp->brdnr;
-		portp->panelnr = panelp->panelnr;
-		portp->uartp = panelp->uartp;
-		portp->clk = brdp->clk;
-		portp->baud_base = STL_BAUDBASE;
-		portp->close_delay = STL_CLOSEDELAY;
-		portp->closing_wait = 30 * HZ;
-		init_waitqueue_head(&portp->port.open_wait);
-		init_waitqueue_head(&portp->port.close_wait);
-		portp->stats.brd = portp->brdnr;
-		portp->stats.panel = portp->panelnr;
-		portp->stats.port = portp->portnr;
-		panelp->ports[i] = portp;
-		stl_portinit(brdp, panelp, portp);
-	}
-
-	return 0;
-}
-
-static void stl_cleanup_panels(struct stlbrd *brdp)
-{
-	struct stlpanel *panelp;
-	struct stlport *portp;
-	unsigned int j, k;
-	struct tty_struct *tty;
-
-	for (j = 0; j < STL_MAXPANELS; j++) {
-		panelp = brdp->panels[j];
-		if (panelp == NULL)
-			continue;
-		for (k = 0; k < STL_PORTSPERPANEL; k++) {
-			portp = panelp->ports[k];
-			if (portp == NULL)
-				continue;
-			tty = tty_port_tty_get(&portp->port);
-			if (tty != NULL) {
-				stl_hangup(tty);
-				tty_kref_put(tty);
-			}
-			kfree(portp->tx.buf);
-			kfree(portp);
-		}
-		kfree(panelp);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find and initialize an EasyIO board.
- */
-
-static int __devinit stl_initeio(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	status;
-	char		*name;
-	int		retval;
-
-	pr_debug("stl_initeio(brdp=%p)\n", brdp);
-
-	brdp->ioctrl = brdp->ioaddr1 + 1;
-	brdp->iostatus = brdp->ioaddr1 + 2;
-
-	status = inb(brdp->iostatus);
-	if ((status & EIO_IDBITMASK) == EIO_MK3)
-		brdp->ioctrl++;
-
-/*
- *	Handle board specific stuff now. The real difference is PCI
- *	or not PCI.
- */
-	if (brdp->brdtype == BRD_EASYIOPCI) {
-		brdp->iosize1 = 0x80;
-		brdp->iosize2 = 0x80;
-		name = "serial(EIO-PCI)";
-		outb(0x41, (brdp->ioaddr2 + 0x4c));
-	} else {
-		brdp->iosize1 = 8;
-		name = "serial(EIO)";
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		outb((stl_vecmap[brdp->irq] | EIO_0WS |
-			((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
-			brdp->ioctrl);
-	}
-
-	retval = -EBUSY;
-	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
-		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
-			"%x conflicts with another device\n", brdp->brdnr, 
-			brdp->ioaddr1);
-		goto err;
-	}
-	
-	if (brdp->iosize2 > 0)
-		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
-			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
-				"address %x conflicts with another device\n",
-				brdp->brdnr, brdp->ioaddr2);
-			printk(KERN_WARNING "STALLION: Warning, also "
-				"releasing board %d I/O address %x \n", 
-				brdp->brdnr, brdp->ioaddr1);
-			goto err_rel1;
-		}
-
-/*
- *	Everything looks OK, so let's go ahead and probe for the hardware.
- */
-	brdp->clk = CD1400_CLK;
-	brdp->isr = stl_eiointr;
-
-	retval = -ENODEV;
-	switch (status & EIO_IDBITMASK) {
-	case EIO_8PORTM:
-		brdp->clk = CD1400_CLK8M;
-		/* fall thru */
-	case EIO_8PORTRS:
-	case EIO_8PORTDI:
-		brdp->nrports = 8;
-		break;
-	case EIO_4PORTRS:
-		brdp->nrports = 4;
-		break;
-	case EIO_MK3:
-		switch (status & EIO_BRDMASK) {
-		case ID_BRD4:
-			brdp->nrports = 4;
-			break;
-		case ID_BRD8:
-			brdp->nrports = 8;
-			break;
-		case ID_BRD16:
-			brdp->nrports = 16;
-			break;
-		default:
-			goto err_rel2;
-		}
-		break;
-	default:
-		goto err_rel2;
-	}
-
-/*
- *	We have verified that the board is actually present, so now we
- *	can complete the setup.
- */
-
-	panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
-	if (!panelp) {
-		printk(KERN_WARNING "STALLION: failed to allocate memory "
-			"(size=%Zd)\n", sizeof(struct stlpanel));
-		retval = -ENOMEM;
-		goto err_rel2;
-	}
-
-	panelp->magic = STL_PANELMAGIC;
-	panelp->brdnr = brdp->brdnr;
-	panelp->panelnr = 0;
-	panelp->nrports = brdp->nrports;
-	panelp->iobase = brdp->ioaddr1;
-	panelp->hwid = status;
-	if ((status & EIO_IDBITMASK) == EIO_MK3) {
-		panelp->uartp = &stl_sc26198uart;
-		panelp->isr = stl_sc26198intr;
-	} else {
-		panelp->uartp = &stl_cd1400uart;
-		panelp->isr = stl_cd1400eiointr;
-	}
-
-	brdp->panels[0] = panelp;
-	brdp->nrpanels = 1;
-	brdp->state |= BRD_FOUND;
-	brdp->hwid = status;
-	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
-		printk("STALLION: failed to register interrupt "
-		    "routine for %s irq=%d\n", name, brdp->irq);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-
-	return 0;
-err_fr:
-	stl_cleanup_panels(brdp);
-err_rel2:
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err_rel1:
-	release_region(brdp->ioaddr1, brdp->iosize1);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ECH board and initialize it. This code is capable of
- *	dealing with all types of ECH board.
- */
-
-static int __devinit stl_initech(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	status, nxtid, ioaddr, conflict, panelnr, banknr, i;
-	int		retval;
-	char		*name;
-
-	pr_debug("stl_initech(brdp=%p)\n", brdp);
-
-	status = 0;
-	conflict = 0;
-
-/*
- *	Set up the initial board register contents for boards. This varies a
- *	bit between the different board types. So we need to handle each
- *	separately. Also do a check that the supplied IRQ is good.
- */
-	switch (brdp->brdtype) {
-
-	case BRD_ECH:
-		brdp->isr = stl_echatintr;
-		brdp->ioctrl = brdp->ioaddr1 + 1;
-		brdp->iostatus = brdp->ioaddr1 + 1;
-		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID) {
-			retval = -ENODEV;
-			goto err;
-		}
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
-		status |= (stl_vecmap[brdp->irq] << 1);
-		outb((status | ECH_BRDRESET), brdp->ioaddr1);
-		brdp->ioctrlval = ECH_INTENABLE |
-			((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
-		for (i = 0; i < 10; i++)
-			outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
-		brdp->iosize1 = 2;
-		brdp->iosize2 = 32;
-		name = "serial(EC8/32)";
-		outb(status, brdp->ioaddr1);
-		break;
-
-	case BRD_ECHMC:
-		brdp->isr = stl_echmcaintr;
-		brdp->ioctrl = brdp->ioaddr1 + 0x20;
-		brdp->iostatus = brdp->ioctrl;
-		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID) {
-			retval = -ENODEV;
-			goto err;
-		}
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		outb(ECHMC_BRDRESET, brdp->ioctrl);
-		outb(ECHMC_INTENABLE, brdp->ioctrl);
-		brdp->iosize1 = 64;
-		name = "serial(EC8/32-MC)";
-		break;
-
-	case BRD_ECHPCI:
-		brdp->isr = stl_echpciintr;
-		brdp->ioctrl = brdp->ioaddr1 + 2;
-		brdp->iosize1 = 4;
-		brdp->iosize2 = 8;
-		name = "serial(EC8/32-PCI)";
-		break;
-
-	case BRD_ECH64PCI:
-		brdp->isr = stl_echpci64intr;
-		brdp->ioctrl = brdp->ioaddr2 + 0x40;
-		outb(0x43, (brdp->ioaddr1 + 0x4c));
-		brdp->iosize1 = 0x80;
-		brdp->iosize2 = 0x80;
-		name = "serial(EC8/64-PCI)";
-		break;
-
-	default:
-		printk("STALLION: unknown board type=%d\n", brdp->brdtype);
-		retval = -EINVAL;
-		goto err;
-	}
-
-/*
- *	Check boards for possible IO address conflicts and return fail status 
- * 	if an IO conflict found.
- */
-	retval = -EBUSY;
-	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
-		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
-			"%x conflicts with another device\n", brdp->brdnr, 
-			brdp->ioaddr1);
-		goto err;
-	}
-	
-	if (brdp->iosize2 > 0)
-		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
-			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
-				"address %x conflicts with another device\n",
-				brdp->brdnr, brdp->ioaddr2);
-			printk(KERN_WARNING "STALLION: Warning, also "
-				"releasing board %d I/O address %x \n", 
-				brdp->brdnr, brdp->ioaddr1);
-			goto err_rel1;
-		}
-
-/*
- *	Scan through the secondary io address space looking for panels.
- *	As we find'em allocate and initialize panel structures for each.
- */
-	brdp->clk = CD1400_CLK;
-	brdp->hwid = status;
-
-	ioaddr = brdp->ioaddr2;
-	banknr = 0;
-	panelnr = 0;
-	nxtid = 0;
-
-	for (i = 0; i < STL_MAXPANELS; i++) {
-		if (brdp->brdtype == BRD_ECHPCI) {
-			outb(nxtid, brdp->ioctrl);
-			ioaddr = brdp->ioaddr2;
-		}
-		status = inb(ioaddr + ECH_PNLSTATUS);
-		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
-		panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
-		if (!panelp) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlpanel));
-			retval = -ENOMEM;
-			goto err_fr;
-		}
-		panelp->magic = STL_PANELMAGIC;
-		panelp->brdnr = brdp->brdnr;
-		panelp->panelnr = panelnr;
-		panelp->iobase = ioaddr;
-		panelp->pagenr = nxtid;
-		panelp->hwid = status;
-		brdp->bnk2panel[banknr] = panelp;
-		brdp->bnkpageaddr[banknr] = nxtid;
-		brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
-
-		if (status & ECH_PNLXPID) {
-			panelp->uartp = &stl_sc26198uart;
-			panelp->isr = stl_sc26198intr;
-			if (status & ECH_PNL16PORT) {
-				panelp->nrports = 16;
-				brdp->bnk2panel[banknr] = panelp;
-				brdp->bnkpageaddr[banknr] = nxtid;
-				brdp->bnkstataddr[banknr++] = ioaddr + 4 +
-					ECH_PNLSTATUS;
-			} else
-				panelp->nrports = 8;
-		} else {
-			panelp->uartp = &stl_cd1400uart;
-			panelp->isr = stl_cd1400echintr;
-			if (status & ECH_PNL16PORT) {
-				panelp->nrports = 16;
-				panelp->ackmask = 0x80;
-				if (brdp->brdtype != BRD_ECHPCI)
-					ioaddr += EREG_BANKSIZE;
-				brdp->bnk2panel[banknr] = panelp;
-				brdp->bnkpageaddr[banknr] = ++nxtid;
-				brdp->bnkstataddr[banknr++] = ioaddr +
-					ECH_PNLSTATUS;
-			} else {
-				panelp->nrports = 8;
-				panelp->ackmask = 0xc0;
-			}
-		}
-
-		nxtid++;
-		ioaddr += EREG_BANKSIZE;
-		brdp->nrports += panelp->nrports;
-		brdp->panels[panelnr++] = panelp;
-		if ((brdp->brdtype != BRD_ECHPCI) &&
-		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
-			retval = -EINVAL;
-			goto err_fr;
-		}
-	}
-
-	brdp->nrpanels = panelnr;
-	brdp->nrbnks = banknr;
-	if (brdp->brdtype == BRD_ECH)
-		outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
-
-	brdp->state |= BRD_FOUND;
-	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
-		printk("STALLION: failed to register interrupt "
-		    "routine for %s irq=%d\n", name, brdp->irq);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-
-	return 0;
-err_fr:
-	stl_cleanup_panels(brdp);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err_rel1:
-	release_region(brdp->ioaddr1, brdp->iosize1);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize and configure the specified board.
- *	Scan through all the boards in the configuration and see what we
- *	can find. Handle EIO and the ECH boards a little differently here
- *	since the initial search and setup is very different.
- */
-
-static int __devinit stl_brdinit(struct stlbrd *brdp)
-{
-	int i, retval;
-
-	pr_debug("stl_brdinit(brdp=%p)\n", brdp);
-
-	switch (brdp->brdtype) {
-	case BRD_EASYIO:
-	case BRD_EASYIOPCI:
-		retval = stl_initeio(brdp);
-		if (retval)
-			goto err;
-		break;
-	case BRD_ECH:
-	case BRD_ECHMC:
-	case BRD_ECHPCI:
-	case BRD_ECH64PCI:
-		retval = stl_initech(brdp);
-		if (retval)
-			goto err;
-		break;
-	default:
-		printk("STALLION: board=%d is unknown board type=%d\n",
-			brdp->brdnr, brdp->brdtype);
-		retval = -ENODEV;
-		goto err;
-	}
-
-	if ((brdp->state & BRD_FOUND) == 0) {
-		printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
-			stl_brdnames[brdp->brdtype], brdp->brdnr,
-			brdp->ioaddr1, brdp->irq);
-		goto err_free;
-	}
-
-	for (i = 0; i < STL_MAXPANELS; i++)
-		if (brdp->panels[i] != NULL)
-			stl_initports(brdp, brdp->panels[i]);
-
-	printk("STALLION: %s found, board=%d io=%x irq=%d "
-		"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
-		brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
-		brdp->nrports);
-
-	return 0;
-err_free:
-	free_irq(brdp->irq, brdp);
-
-	stl_cleanup_panels(brdp);
-
-	release_region(brdp->ioaddr1, brdp->iosize1);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Find the next available board number that is free.
- */
-
-static int __devinit stl_getbrdnr(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < STL_MAXBRDS; i++)
-		if (stl_brds[i] == NULL) {
-			if (i >= stl_nrbrds)
-				stl_nrbrds = i + 1;
-			return i;
-		}
-
-	return -1;
-}
-
-/*****************************************************************************/
-/*
- *	We have a Stallion board. Allocate a board structure and
- *	initialize it. Read its IO and IRQ resources from PCI
- *	configuration space.
- */
-
-static int __devinit stl_pciprobe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct stlbrd *brdp;
-	unsigned int i, brdtype = ent->driver_data;
-	int brdnr, retval = -ENODEV;
-
-	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
-		goto err;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err;
-	brdp = stl_allocbrd();
-	if (brdp == NULL) {
-		retval = -ENOMEM;
-		goto err;
-	}
-	mutex_lock(&stl_brdslock);
-	brdnr = stl_getbrdnr();
-	if (brdnr < 0) {
-		dev_err(&pdev->dev, "too many boards found, "
-			"maximum supported %d\n", STL_MAXBRDS);
-		mutex_unlock(&stl_brdslock);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-	brdp->brdnr = (unsigned int)brdnr;
-	stl_brds[brdp->brdnr] = brdp;
-	mutex_unlock(&stl_brdslock);
-
-	brdp->brdtype = brdtype;
-	brdp->state |= STL_PROBED;
-
-/*
- *	We have all resources from the board, so let's setup the actual
- *	board structure now.
- */
-	switch (brdtype) {
-	case BRD_ECHPCI:
-		brdp->ioaddr2 = pci_resource_start(pdev, 0);
-		brdp->ioaddr1 = pci_resource_start(pdev, 1);
-		break;
-	case BRD_ECH64PCI:
-		brdp->ioaddr2 = pci_resource_start(pdev, 2);
-		brdp->ioaddr1 = pci_resource_start(pdev, 1);
-		break;
-	case BRD_EASYIOPCI:
-		brdp->ioaddr1 = pci_resource_start(pdev, 2);
-		brdp->ioaddr2 = pci_resource_start(pdev, 1);
-		break;
-	default:
-		dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
-		break;
-	}
-
-	brdp->irq = pdev->irq;
-	retval = stl_brdinit(brdp);
-	if (retval)
-		goto err_null;
-
-	pci_set_drvdata(pdev, brdp);
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_register_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
-
-	return 0;
-err_null:
-	stl_brds[brdp->brdnr] = NULL;
-err_fr:
-	kfree(brdp);
-err:
-	return retval;
-}
-
-static void __devexit stl_pciremove(struct pci_dev *pdev)
-{
-	struct stlbrd *brdp = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	free_irq(brdp->irq, brdp);
-
-	stl_cleanup_panels(brdp);
-
-	release_region(brdp->ioaddr1, brdp->iosize1);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_unregister_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + i);
-
-	stl_brds[brdp->brdnr] = NULL;
-	kfree(brdp);
-}
-
-static struct pci_driver stl_pcidriver = {
-	.name = "stallion",
-	.id_table = stl_pcibrds,
-	.probe = stl_pciprobe,
-	.remove = __devexit_p(stl_pciremove)
-};
-
-/*****************************************************************************/
-
-/*
- *	Return the board stats structure to user app.
- */
-
-static int stl_getbrdstats(combrd_t __user *bp)
-{
-	combrd_t	stl_brdstats;
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-	unsigned int i;
-
-	if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
-		return -EFAULT;
-	if (stl_brdstats.brd >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stl_brds[stl_brdstats.brd];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	memset(&stl_brdstats, 0, sizeof(combrd_t));
-	stl_brdstats.brd = brdp->brdnr;
-	stl_brdstats.type = brdp->brdtype;
-	stl_brdstats.hwid = brdp->hwid;
-	stl_brdstats.state = brdp->state;
-	stl_brdstats.ioaddr = brdp->ioaddr1;
-	stl_brdstats.ioaddr2 = brdp->ioaddr2;
-	stl_brdstats.irq = brdp->irq;
-	stl_brdstats.nrpanels = brdp->nrpanels;
-	stl_brdstats.nrports = brdp->nrports;
-	for (i = 0; i < brdp->nrpanels; i++) {
-		panelp = brdp->panels[i];
-		stl_brdstats.panels[i].panel = i;
-		stl_brdstats.panels[i].hwid = panelp->hwid;
-		stl_brdstats.panels[i].nrports = panelp->nrports;
-	}
-
-	return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Resolve the referenced port number into a port struct pointer.
- */
-
-static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
-{
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-
-	if (brdnr < 0 || brdnr >= STL_MAXBRDS)
-		return NULL;
-	brdp = stl_brds[brdnr];
-	if (brdp == NULL)
-		return NULL;
-	if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
-		return NULL;
-	panelp = brdp->panels[panelnr];
-	if (panelp == NULL)
-		return NULL;
-	if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
-		return NULL;
-	return panelp->ports[portnr];
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
-{
-	comstats_t	stl_comstats;
-	unsigned char	*head, *tail;
-	unsigned long	flags;
-
-	if (!portp) {
-		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-			stl_comstats.port);
-		if (portp == NULL)
-			return -ENODEV;
-	}
-
-	mutex_lock(&portp->port.mutex);
-	portp->stats.state = portp->istate;
-	portp->stats.flags = portp->port.flags;
-	portp->stats.hwid = portp->hwid;
-
-	portp->stats.ttystate = 0;
-	portp->stats.cflags = 0;
-	portp->stats.iflags = 0;
-	portp->stats.oflags = 0;
-	portp->stats.lflags = 0;
-	portp->stats.rxbuffered = 0;
-
-	spin_lock_irqsave(&stallion_lock, flags);
-	if (tty != NULL && portp->port.tty == tty) {
-		portp->stats.ttystate = tty->flags;
-		/* No longer available as a statistic */
-		portp->stats.rxbuffered = 1; /*tty->flip.count; */
-		if (tty->termios != NULL) {
-			portp->stats.cflags = tty->termios->c_cflag;
-			portp->stats.iflags = tty->termios->c_iflag;
-			portp->stats.oflags = tty->termios->c_oflag;
-			portp->stats.lflags = tty->termios->c_lflag;
-		}
-	}
-	spin_unlock_irqrestore(&stallion_lock, flags);
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	portp->stats.txbuffered = (head >= tail) ? (head - tail) :
-		(STL_TXBUFSIZE - (tail - head));
-
-	portp->stats.signals = (unsigned long) stl_getsignals(portp);
-	mutex_unlock(&portp->port.mutex);
-
-	return copy_to_user(cp, &portp->stats,
-			    sizeof(comstats_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
-{
-	comstats_t	stl_comstats;
-
-	if (!portp) {
-		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-			stl_comstats.port);
-		if (portp == NULL)
-			return -ENODEV;
-	}
-
-	mutex_lock(&portp->port.mutex);
-	memset(&portp->stats, 0, sizeof(comstats_t));
-	portp->stats.brd = portp->brdnr;
-	portp->stats.panel = portp->panelnr;
-	portp->stats.port = portp->portnr;
-	mutex_unlock(&portp->port.mutex);
-	return copy_to_user(cp, &portp->stats,
-			    sizeof(comstats_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver ports structure to a user app.
- */
-
-static int stl_getportstruct(struct stlport __user *arg)
-{
-	struct stlport	stl_dummyport;
-	struct stlport	*portp;
-
-	if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
-		return -EFAULT;
-	portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
-		 stl_dummyport.portnr);
-	if (!portp)
-		return -ENODEV;
-	return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver board structure to a user app.
- */
-
-static int stl_getbrdstruct(struct stlbrd __user *arg)
-{
-	struct stlbrd	stl_dummybrd;
-	struct stlbrd	*brdp;
-
-	if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
-		return -EFAULT;
-	if (stl_dummybrd.brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stl_brds[stl_dummybrd.brdnr];
-	if (!brdp)
-		return -ENODEV;
-	return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	The "staliomem" device is also required to do some special operations
- *	on the board and/or ports. In this driver it is mostly used for stats
- *	collection.
- */
-
-static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
-	int	brdnr, rc;
-	void __user *argp = (void __user *)arg;
-
-	pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
-
-	brdnr = iminor(fp->f_dentry->d_inode);
-	if (brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	rc = 0;
-
-	switch (cmd) {
-	case COM_GETPORTSTATS:
-		rc = stl_getportstats(NULL, NULL, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stl_clrportstats(NULL, argp);
-		break;
-	case COM_GETBRDSTATS:
-		rc = stl_getbrdstats(argp);
-		break;
-	case COM_READPORT:
-		rc = stl_getportstruct(argp);
-		break;
-	case COM_READBOARD:
-		rc = stl_getbrdstruct(argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-static const struct tty_operations stl_ops = {
-	.open = stl_open,
-	.close = stl_close,
-	.write = stl_write,
-	.put_char = stl_putchar,
-	.flush_chars = stl_flushchars,
-	.write_room = stl_writeroom,
-	.chars_in_buffer = stl_charsinbuffer,
-	.ioctl = stl_ioctl,
-	.set_termios = stl_settermios,
-	.throttle = stl_throttle,
-	.unthrottle = stl_unthrottle,
-	.stop = stl_stop,
-	.start = stl_start,
-	.hangup = stl_hangup,
-	.flush_buffer = stl_flushbuffer,
-	.break_ctl = stl_breakctl,
-	.wait_until_sent = stl_waituntilsent,
-	.send_xchar = stl_sendxchar,
-	.tiocmget = stl_tiocmget,
-	.tiocmset = stl_tiocmset,
-	.proc_fops = &stl_proc_fops,
-};
-
-static const struct tty_port_operations stl_port_ops = {
-	.carrier_raised = stl_carrier_raised,
-	.dtr_rts = stl_dtr_rts,
-	.activate = stl_activate,
-	.shutdown = stl_shutdown,
-};
-
-/*****************************************************************************/
-/*                       CD1400 HARDWARE FUNCTIONS                           */
-/*****************************************************************************/
-
-/*
- *	These functions get/set/update the registers of the cd1400 UARTs.
- *	Access to the cd1400 registers is via an address/data io port pair.
- *	(Maybe should make this inline...)
- */
-
-static int stl_cd1400getreg(struct stlport *portp, int regnr)
-{
-	outb((regnr + portp->uartaddr), portp->ioaddr);
-	return inb(portp->ioaddr + EREG_DATA);
-}
-
-static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr + portp->uartaddr, portp->ioaddr);
-	outb(value, portp->ioaddr + EREG_DATA);
-}
-
-static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr + portp->uartaddr, portp->ioaddr);
-	if (inb(portp->ioaddr + EREG_DATA) != value) {
-		outb(value, portp->ioaddr + EREG_DATA);
-		return 1;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Inbitialize the UARTs in a panel. We don't care what sort of board
- *	these ports are on - since the port io registers are almost
- *	identical when dealing with ports.
- */
-
-static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	unsigned int	gfrcr;
-	int		chipmask, i, j;
-	int		nrchips, uartaddr, ioaddr;
-	unsigned long   flags;
-
-	pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- *	Check that each chip is present and started up OK.
- */
-	chipmask = 0;
-	nrchips = panelp->nrports / CD1400_PORTS;
-	for (i = 0; i < nrchips; i++) {
-		if (brdp->brdtype == BRD_ECHPCI) {
-			outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
-			ioaddr = panelp->iobase;
-		} else
-			ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
-		uartaddr = (i & 0x01) ? 0x080 : 0;
-		outb((GFRCR + uartaddr), ioaddr);
-		outb(0, (ioaddr + EREG_DATA));
-		outb((CCR + uartaddr), ioaddr);
-		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
-		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
-		outb((GFRCR + uartaddr), ioaddr);
-		for (j = 0; j < CCR_MAXWAIT; j++)
-			if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
-				break;
-
-		if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
-			printk("STALLION: cd1400 not responding, "
-				"brd=%d panel=%d chip=%d\n",
-				panelp->brdnr, panelp->panelnr, i);
-			continue;
-		}
-		chipmask |= (0x1 << i);
-		outb((PPR + uartaddr), ioaddr);
-		outb(PPR_SCALAR, (ioaddr + EREG_DATA));
-	}
-
-	BRDDISABLE(panelp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	return chipmask;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize hardware specific port registers.
- */
-
-static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
-{
-	unsigned long flags;
-	pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
-			panelp, portp);
-
-	if ((brdp == NULL) || (panelp == NULL) ||
-	    (portp == NULL))
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
-		(portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
-	portp->uartaddr = (portp->portnr & 0x04) << 5;
-	portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
-
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
-	portp->hwid = stl_cd1400getreg(portp, GFRCR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Wait for the command register to be ready. We will poll this,
- *	since it won't usually take too long to be ready.
- */
-
-static void stl_cd1400ccrwait(struct stlport *portp)
-{
-	int	i;
-
-	for (i = 0; i < CCR_MAXWAIT; i++)
-		if (stl_cd1400getreg(portp, CCR) == 0)
-			return;
-
-	printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up the cd1400 registers for a port based on the termios port
- *	settings.
- */
-
-static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
-{
-	struct stlbrd	*brdp;
-	unsigned long	flags;
-	unsigned int	clkdiv, baudrate;
-	unsigned char	cor1, cor2, cor3;
-	unsigned char	cor4, cor5, ccr;
-	unsigned char	srer, sreron, sreroff;
-	unsigned char	mcor1, mcor2, rtpr;
-	unsigned char	clk, div;
-
-	cor1 = 0;
-	cor2 = 0;
-	cor3 = 0;
-	cor4 = 0;
-	cor5 = 0;
-	ccr = 0;
-	rtpr = 0;
-	clk = 0;
-	div = 0;
-	mcor1 = 0;
-	mcor2 = 0;
-	sreron = 0;
-	sreroff = 0;
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-/*
- *	Set up the RX char ignore mask with those RX error types we
- *	can ignore. We can get the cd1400 to help us out a little here,
- *	it will ignore parity errors and breaks for us.
- */
-	portp->rxignoremsk = 0;
-	if (tiosp->c_iflag & IGNPAR) {
-		portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
-		cor1 |= COR1_PARIGNORE;
-	}
-	if (tiosp->c_iflag & IGNBRK) {
-		portp->rxignoremsk |= ST_BREAK;
-		cor4 |= COR4_IGNBRK;
-	}
-
-	portp->rxmarkmsk = ST_OVERRUN;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= ST_BREAK;
-
-/*
- *	Go through the char size, parity and stop bits and set all the
- *	option register appropriately.
- */
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		cor1 |= COR1_CHL5;
-		break;
-	case CS6:
-		cor1 |= COR1_CHL6;
-		break;
-	case CS7:
-		cor1 |= COR1_CHL7;
-		break;
-	default:
-		cor1 |= COR1_CHL8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		cor1 |= COR1_STOP2;
-	else
-		cor1 |= COR1_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			cor1 |= (COR1_PARENB | COR1_PARODD);
-		else
-			cor1 |= (COR1_PARENB | COR1_PAREVEN);
-	} else {
-		cor1 |= COR1_PARNONE;
-	}
-
-/*
- *	Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
- *	space for hardware flow control and the like. This should be set to
- *	VMIN. Also here we will set the RX data timeout to 10ms - this should
- *	really be based on VTIME.
- */
-	cor3 |= FIFO_RXTHRESHOLD;
-	rtpr = 2;
-
-/*
- *	Calculate the baud rate timers. For now we will just assume that
- *	the input and output baud are the same. Could have used a baud
- *	table here, but this way we can generate virtually any baud rate
- *	we like!
- */
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
-	baudrate = stl_baudrates[baudrate];
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (portp->baud_base / portp->custom_divisor);
-	}
-	if (baudrate > STL_CD1400MAXBAUD)
-		baudrate = STL_CD1400MAXBAUD;
-
-	if (baudrate > 0) {
-		for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
-			clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
-			if (clkdiv < 0x100)
-				break;
-		}
-		div = (unsigned char) clkdiv;
-	}
-
-/*
- *	Check what form of modem signaling is required and set it up.
- */
-	if ((tiosp->c_cflag & CLOCAL) == 0) {
-		mcor1 |= MCOR1_DCD;
-		mcor2 |= MCOR2_DCD;
-		sreron |= SRER_MODEM;
-		portp->port.flags |= ASYNC_CHECK_CD;
-	} else
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-
-/*
- *	Setup cd1400 enhanced modes if we can. In particular we want to
- *	handle as much of the flow control as possible automatically. As
- *	well as saving a few CPU cycles it will also greatly improve flow
- *	control reliability.
- */
-	if (tiosp->c_iflag & IXON) {
-		cor2 |= COR2_TXIBE;
-		cor3 |= COR3_SCD12;
-		if (tiosp->c_iflag & IXANY)
-			cor2 |= COR2_IXM;
-	}
-
-	if (tiosp->c_cflag & CRTSCTS) {
-		cor2 |= COR2_CTSAE;
-		mcor1 |= FIFO_RTSTHRESHOLD;
-	}
-
-/*
- *	All cd1400 register values calculated so go through and set
- *	them all up.
- */
-
-	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-	pr_debug("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
-		cor1, cor2, cor3, cor4, cor5);
-	pr_debug("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
-		mcor1, mcor2, rtpr, sreron, sreroff);
-	pr_debug("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
-	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-	srer = stl_cd1400getreg(portp, SRER);
-	stl_cd1400setreg(portp, SRER, 0);
-	if (stl_cd1400updatereg(portp, COR1, cor1))
-		ccr = 1;
-	if (stl_cd1400updatereg(portp, COR2, cor2))
-		ccr = 1;
-	if (stl_cd1400updatereg(portp, COR3, cor3))
-		ccr = 1;
-	if (ccr) {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
-	}
-	stl_cd1400setreg(portp, COR4, cor4);
-	stl_cd1400setreg(portp, COR5, cor5);
-	stl_cd1400setreg(portp, MCOR1, mcor1);
-	stl_cd1400setreg(portp, MCOR2, mcor2);
-	if (baudrate > 0) {
-		stl_cd1400setreg(portp, TCOR, clk);
-		stl_cd1400setreg(portp, TBPR, div);
-		stl_cd1400setreg(portp, RCOR, clk);
-		stl_cd1400setreg(portp, RBPR, div);
-	}
-	stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
-	stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
-	stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
-	stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
-	stl_cd1400setreg(portp, RTPR, rtpr);
-	mcor1 = stl_cd1400getreg(portp, MSVR1);
-	if (mcor1 & MSVR1_DCD)
-		portp->sigs |= TIOCM_CD;
-	else
-		portp->sigs &= ~TIOCM_CD;
-	stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set the state of the DTR and RTS signals.
- */
-
-static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
-{
-	unsigned char	msvr1, msvr2;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
-			portp, dtr, rts);
-
-	msvr1 = 0;
-	msvr2 = 0;
-	if (dtr > 0)
-		msvr1 = MSVR1_DTR;
-	if (rts > 0)
-		msvr2 = MSVR2_RTS;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	if (rts >= 0)
-		stl_cd1400setreg(portp, MSVR2, msvr2);
-	if (dtr >= 0)
-		stl_cd1400setreg(portp, MSVR1, msvr1);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the state of the signals.
- */
-
-static int stl_cd1400getsignals(struct stlport *portp)
-{
-	unsigned char	msvr1, msvr2;
-	unsigned long	flags;
-	int		sigs;
-
-	pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	msvr1 = stl_cd1400getreg(portp, MSVR1);
-	msvr2 = stl_cd1400getreg(portp, MSVR2);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	sigs = 0;
-	sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
-	sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
-	sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
-	sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
-#if 0
-	sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
-	sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
-#else
-	sigs |= TIOCM_DSR;
-#endif
-	return sigs;
-}
-
-/*****************************************************************************/
-
-/*
- *	Enable/Disable the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	ccr;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	ccr = 0;
-
-	if (tx == 0)
-		ccr |= CCR_TXDISABLE;
-	else if (tx > 0)
-		ccr |= CCR_TXENABLE;
-	if (rx == 0)
-		ccr |= CCR_RXDISABLE;
-	else if (rx > 0)
-		ccr |= CCR_RXENABLE;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400ccrwait(portp);
-	stl_cd1400setreg(portp, CCR, ccr);
-	stl_cd1400ccrwait(portp);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Start/stop the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	sreron, sreroff;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	sreron = 0;
-	sreroff = 0;
-	if (tx == 0)
-		sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
-	else if (tx == 1)
-		sreron |= SRER_TXDATA;
-	else if (tx >= 2)
-		sreron |= SRER_TXEMPTY;
-	if (rx == 0)
-		sreroff |= SRER_RXDATA;
-	else if (rx > 0)
-		sreron |= SRER_RXDATA;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER,
-		((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
-	BRDDISABLE(portp->brdnr);
-	if (tx > 0)
-		set_bit(ASYI_TXBUSY, &portp->istate);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Disable all interrupts from this port.
- */
-
-static void stl_cd1400disableintrs(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER, 0);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400sendbreak(struct stlport *portp, int len)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER,
-		((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
-		SRER_TXEMPTY));
-	BRDDISABLE(portp->brdnr);
-	portp->brklen = len;
-	if (len == 1)
-		portp->stats.txbreaks++;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Take flow control actions...
- */
-
-static void stl_cd1400flowctrl(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-
-	pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-
-	if (state) {
-		if (tty->termios->c_iflag & IXOFF) {
-			stl_cd1400ccrwait(portp);
-			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-			portp->stats.rxxon++;
-			stl_cd1400ccrwait(portp);
-		}
-/*
- *		Question: should we return RTS to what it was before? It may
- *		have been set by an ioctl... Suppose not, since if you have
- *		hardware flow control set then it is pretty silly to go and
- *		set the RTS line by hand.
- */
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_cd1400setreg(portp, MCOR1,
-				(stl_cd1400getreg(portp, MCOR1) |
-				FIFO_RTSTHRESHOLD));
-			stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
-			portp->stats.rxrtson++;
-		}
-	} else {
-		if (tty->termios->c_iflag & IXOFF) {
-			stl_cd1400ccrwait(portp);
-			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-			portp->stats.rxxoff++;
-			stl_cd1400ccrwait(portp);
-		}
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_cd1400setreg(portp, MCOR1,
-				(stl_cd1400getreg(portp, MCOR1) & 0xf0));
-			stl_cd1400setreg(portp, MSVR2, 0);
-			portp->stats.rxrtsoff++;
-		}
-	}
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a flow control character...
- */
-
-static void stl_cd1400sendflow(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-
-	pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	if (state) {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-		portp->stats.rxxon++;
-		stl_cd1400ccrwait(portp);
-	} else {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-		portp->stats.rxxoff++;
-		stl_cd1400ccrwait(portp);
-	}
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400flush(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400flush(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400ccrwait(portp);
-	stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
-	stl_cd1400ccrwait(portp);
-	portp->tx.tail = portp->tx.head;
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the current state of data flow on this port. This is only
- *	really interesting when determining if data has fully completed
- *	transmission or not... This is easy for the cd1400, it accurately
- *	maintains the busy port flag.
- */
-
-static int stl_cd1400datastate(struct stlport *portp)
-{
-	pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return 0;
-
-	return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for cd1400 EasyIO boards.
- */
-
-static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
-{
-	unsigned char	svrtype;
-
-	pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
-
-	spin_lock(&brd_lock);
-	outb(SVRR, iobase);
-	svrtype = inb(iobase + EREG_DATA);
-	if (panelp->nrports > 4) {
-		outb((SVRR + 0x80), iobase);
-		svrtype |= inb(iobase + EREG_DATA);
-	}
-
-	if (svrtype & SVRR_RX)
-		stl_cd1400rxisr(panelp, iobase);
-	else if (svrtype & SVRR_TX)
-		stl_cd1400txisr(panelp, iobase);
-	else if (svrtype & SVRR_MDM)
-		stl_cd1400mdmisr(panelp, iobase);
-
-	spin_unlock(&brd_lock);
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for cd1400 panels.
- */
-
-static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
-{
-	unsigned char	svrtype;
-
-	pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
-
-	outb(SVRR, iobase);
-	svrtype = inb(iobase + EREG_DATA);
-	outb((SVRR + 0x80), iobase);
-	svrtype |= inb(iobase + EREG_DATA);
-	if (svrtype & SVRR_RX)
-		stl_cd1400rxisr(panelp, iobase);
-	else if (svrtype & SVRR_TX)
-		stl_cd1400txisr(panelp, iobase);
-	else if (svrtype & SVRR_MDM)
-		stl_cd1400mdmisr(panelp, iobase);
-}
-
-
-/*****************************************************************************/
-
-/*
- *	Unfortunately we need to handle breaks in the TX data stream, since
- *	this is the only way to generate them on the cd1400.
- */
-
-static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
-{
-	if (portp->brklen == 1) {
-		outb((COR2 + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
-			(ioaddr + EREG_DATA));
-		outb((TDR + portp->uartaddr), ioaddr);
-		outb(ETC_CMD, (ioaddr + EREG_DATA));
-		outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
-		outb((SRER + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
-			(ioaddr + EREG_DATA));
-		return 1;
-	} else if (portp->brklen > 1) {
-		outb((TDR + portp->uartaddr), ioaddr);
-		outb(ETC_CMD, (ioaddr + EREG_DATA));
-		outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
-		portp->brklen = -1;
-		return 1;
-	} else {
-		outb((COR2 + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
-			(ioaddr + EREG_DATA));
-		portp->brklen = 0;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Transmit interrupt handler. This has gotta be fast!  Handling TX
- *	chars is pretty simple, stuff as many as possible from the TX buffer
- *	into the cd1400 FIFO. Must also handle TX breaks here, since they
- *	are embedded as commands in the data stream. Oh no, had to use a goto!
- *	This could be optimized more, will do when I get time...
- *	In practice it is possible that interrupts are enabled but that the
- *	port has been hung up. Need to handle not having any TX buffer here,
- *	this is done by using the side effect that head and tail will also
- *	be NULL if the buffer has been freed.
- */
-
-static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport	*portp;
-	int		len, stlen;
-	char		*head, *tail;
-	unsigned char	ioack, srer;
-	struct tty_struct *tty;
-
-	pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
-
-	ioack = inb(ioaddr + EREG_TXACK);
-	if (((ioack & panelp->ackmask) != 0) ||
-	    ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
-		printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-
-/*
- *	Unfortunately we need to handle breaks in the data stream, since
- *	this is the only way to generate them on the cd1400. Do it now if
- *	a break is to be sent.
- */
-	if (portp->brklen != 0)
-		if (stl_cd1400breakisr(portp, ioaddr))
-			goto stl_txalldone;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((len == 0) || ((len < STL_TXBUFLOW) &&
-	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
-		set_bit(ASYI_TXLOW, &portp->istate);
-		tty = tty_port_tty_get(&portp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
-
-	if (len == 0) {
-		outb((SRER + portp->uartaddr), ioaddr);
-		srer = inb(ioaddr + EREG_DATA);
-		if (srer & SRER_TXDATA) {
-			srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
-		} else {
-			srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
-			clear_bit(ASYI_TXBUSY, &portp->istate);
-		}
-		outb(srer, (ioaddr + EREG_DATA));
-	} else {
-		len = min(len, CD1400_TXFIFOSIZE);
-		portp->stats.txtotal += len;
-		stlen = min_t(unsigned int, len,
-				(portp->tx.buf + STL_TXBUFSIZE) - tail);
-		outb((TDR + portp->uartaddr), ioaddr);
-		outsb((ioaddr + EREG_DATA), tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
-			tail = portp->tx.buf;
-		if (len > 0) {
-			outsb((ioaddr + EREG_DATA), tail, len);
-			tail += len;
-		}
-		portp->tx.tail = tail;
-	}
-
-stl_txalldone:
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-/*
- *	Receive character interrupt handler. Determine if we have good chars
- *	or bad chars and then process appropriately. Good chars are easy
- *	just shove the lot into the RX buffer and set all status byte to 0.
- *	If a bad RX char then process as required. This routine needs to be
- *	fast!  In practice it is possible that we get an interrupt on a port
- *	that is closed. This can happen on hangups - since they completely
- *	shutdown a port not in user context. Need to handle this case.
- */
-
-static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport		*portp;
-	struct tty_struct	*tty;
-	unsigned int		ioack, len, buflen;
-	unsigned char		status;
-	char			ch;
-
-	pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
-
-	ioack = inb(ioaddr + EREG_RXACK);
-	if ((ioack & panelp->ackmask) != 0) {
-		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-	tty = tty_port_tty_get(&portp->port);
-
-	if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
-		outb((RDCR + portp->uartaddr), ioaddr);
-		len = inb(ioaddr + EREG_DATA);
-		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-			len = min_t(unsigned int, len, sizeof(stl_unwanted));
-			outb((RDSR + portp->uartaddr), ioaddr);
-			insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
-			portp->stats.rxlost += len;
-			portp->stats.rxtotal += len;
-		} else {
-			len = min(len, buflen);
-			if (len > 0) {
-				unsigned char *ptr;
-				outb((RDSR + portp->uartaddr), ioaddr);
-				tty_prepare_flip_string(tty, &ptr, len);
-				insb((ioaddr + EREG_DATA), ptr, len);
-				tty_schedule_flip(tty);
-				portp->stats.rxtotal += len;
-			}
-		}
-	} else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
-		outb((RDSR + portp->uartaddr), ioaddr);
-		status = inb(ioaddr + EREG_DATA);
-		ch = inb(ioaddr + EREG_DATA);
-		if (status & ST_PARITY)
-			portp->stats.rxparity++;
-		if (status & ST_FRAMING)
-			portp->stats.rxframing++;
-		if (status & ST_OVERRUN)
-			portp->stats.rxoverrun++;
-		if (status & ST_BREAK)
-			portp->stats.rxbreaks++;
-		if (status & ST_SCHARMASK) {
-			if ((status & ST_SCHARMASK) == ST_SCHAR1)
-				portp->stats.txxon++;
-			if ((status & ST_SCHARMASK) == ST_SCHAR2)
-				portp->stats.txxoff++;
-			goto stl_rxalldone;
-		}
-		if (tty != NULL && (portp->rxignoremsk & status) == 0) {
-			if (portp->rxmarkmsk & status) {
-				if (status & ST_BREAK) {
-					status = TTY_BREAK;
-					if (portp->port.flags & ASYNC_SAK) {
-						do_SAK(tty);
-						BRDENABLE(portp->brdnr, portp->pagenr);
-					}
-				} else if (status & ST_PARITY)
-					status = TTY_PARITY;
-				else if (status & ST_FRAMING)
-					status = TTY_FRAME;
-				else if(status & ST_OVERRUN)
-					status = TTY_OVERRUN;
-				else
-					status = 0;
-			} else
-				status = 0;
-			tty_insert_flip_char(tty, ch, status);
-			tty_schedule_flip(tty);
-		}
-	} else {
-		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
-		tty_kref_put(tty);
-		return;
-	}
-
-stl_rxalldone:
-	tty_kref_put(tty);
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-/*
- *	Modem interrupt handler. The is called when the modem signal line
- *	(DCD) has changed state. Leave most of the work to the off-level
- *	processing routine.
- */
-
-static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport	*portp;
-	unsigned int	ioack;
-	unsigned char	misr;
-
-	pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
-
-	ioack = inb(ioaddr + EREG_MDACK);
-	if (((ioack & panelp->ackmask) != 0) ||
-	    ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
-		printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-
-	outb((MISR + portp->uartaddr), ioaddr);
-	misr = inb(ioaddr + EREG_DATA);
-	if (misr & MISR_DCD) {
-		stl_cd_change(portp);
-		portp->stats.modem++;
-	}
-
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-/*                      SC26198 HARDWARE FUNCTIONS                           */
-/*****************************************************************************/
-
-/*
- *	These functions get/set/update the registers of the sc26198 UARTs.
- *	Access to the sc26198 registers is via an address/data io port pair.
- *	(Maybe should make this inline...)
- */
-
-static int stl_sc26198getreg(struct stlport *portp, int regnr)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	return inb(portp->ioaddr + XP_DATA);
-}
-
-static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	outb(value, (portp->ioaddr + XP_DATA));
-}
-
-static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	if (inb(portp->ioaddr + XP_DATA) != value) {
-		outb(value, (portp->ioaddr + XP_DATA));
-		return 1;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Functions to get and set the sc26198 global registers.
- */
-
-static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
-{
-	outb(regnr, (portp->ioaddr + XP_ADDR));
-	return inb(portp->ioaddr + XP_DATA);
-}
-
-#if 0
-static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr, (portp->ioaddr + XP_ADDR));
-	outb(value, (portp->ioaddr + XP_DATA));
-}
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Inbitialize the UARTs in a panel. We don't care what sort of board
- *	these ports are on - since the port io registers are almost
- *	identical when dealing with ports.
- */
-
-static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	int	chipmask, i;
-	int	nrchips, ioaddr;
-
-	pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- *	Check that each chip is present and started up OK.
- */
-	chipmask = 0;
-	nrchips = (panelp->nrports + 4) / SC26198_PORTS;
-	if (brdp->brdtype == BRD_ECHPCI)
-		outb(panelp->pagenr, brdp->ioctrl);
-
-	for (i = 0; i < nrchips; i++) {
-		ioaddr = panelp->iobase + (i * 4); 
-		outb(SCCR, (ioaddr + XP_ADDR));
-		outb(CR_RESETALL, (ioaddr + XP_DATA));
-		outb(TSTR, (ioaddr + XP_ADDR));
-		if (inb(ioaddr + XP_DATA) != 0) {
-			printk("STALLION: sc26198 not responding, "
-				"brd=%d panel=%d chip=%d\n",
-				panelp->brdnr, panelp->panelnr, i);
-			continue;
-		}
-		chipmask |= (0x1 << i);
-		outb(GCCR, (ioaddr + XP_ADDR));
-		outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
-		outb(WDTRCR, (ioaddr + XP_ADDR));
-		outb(0xff, (ioaddr + XP_DATA));
-	}
-
-	BRDDISABLE(panelp->brdnr);
-	return chipmask;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize hardware specific port registers.
- */
-
-static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
-{
-	pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
-			panelp, portp);
-
-	if ((brdp == NULL) || (panelp == NULL) ||
-	    (portp == NULL))
-		return;
-
-	portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
-	portp->uartaddr = (portp->portnr & 0x07) << 4;
-	portp->pagenr = panelp->pagenr;
-	portp->hwid = 0x1;
-
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
-	BRDDISABLE(portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up the sc26198 registers for a port based on the termios port
- *	settings.
- */
-
-static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
-{
-	struct stlbrd	*brdp;
-	unsigned long	flags;
-	unsigned int	baudrate;
-	unsigned char	mr0, mr1, mr2, clk;
-	unsigned char	imron, imroff, iopr, ipr;
-
-	mr0 = 0;
-	mr1 = 0;
-	mr2 = 0;
-	clk = 0;
-	iopr = 0;
-	imron = 0;
-	imroff = 0;
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-/*
- *	Set up the RX char ignore mask with those RX error types we
- *	can ignore.
- */
-	portp->rxignoremsk = 0;
-	if (tiosp->c_iflag & IGNPAR)
-		portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
-			SR_RXOVERRUN);
-	if (tiosp->c_iflag & IGNBRK)
-		portp->rxignoremsk |= SR_RXBREAK;
-
-	portp->rxmarkmsk = SR_RXOVERRUN;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= SR_RXBREAK;
-
-/*
- *	Go through the char size, parity and stop bits and set all the
- *	option register appropriately.
- */
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		mr1 |= MR1_CS5;
-		break;
-	case CS6:
-		mr1 |= MR1_CS6;
-		break;
-	case CS7:
-		mr1 |= MR1_CS7;
-		break;
-	default:
-		mr1 |= MR1_CS8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		mr2 |= MR2_STOP2;
-	else
-		mr2 |= MR2_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			mr1 |= (MR1_PARENB | MR1_PARODD);
-		else
-			mr1 |= (MR1_PARENB | MR1_PAREVEN);
-	} else
-		mr1 |= MR1_PARNONE;
-
-	mr1 |= MR1_ERRBLOCK;
-
-/*
- *	Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
- *	space for hardware flow control and the like. This should be set to
- *	VMIN.
- */
-	mr2 |= MR2_RXFIFOHALF;
-
-/*
- *	Calculate the baud rate timers. For now we will just assume that
- *	the input and output baud are the same. The sc26198 has a fixed
- *	baud rate table, so only discrete baud rates possible.
- */
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
-	baudrate = stl_baudrates[baudrate];
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (portp->baud_base / portp->custom_divisor);
-	}
-	if (baudrate > STL_SC26198MAXBAUD)
-		baudrate = STL_SC26198MAXBAUD;
-
-	if (baudrate > 0)
-		for (clk = 0; clk < SC26198_NRBAUDS; clk++)
-			if (baudrate <= sc26198_baudtable[clk])
-				break;
-
-/*
- *	Check what form of modem signaling is required and set it up.
- */
-	if (tiosp->c_cflag & CLOCAL) {
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-	} else {
-		iopr |= IOPR_DCDCOS;
-		imron |= IR_IOPORT;
-		portp->port.flags |= ASYNC_CHECK_CD;
-	}
-
-/*
- *	Setup sc26198 enhanced modes if we can. In particular we want to
- *	handle as much of the flow control as possible automatically. As
- *	well as saving a few CPU cycles it will also greatly improve flow
- *	control reliability.
- */
-	if (tiosp->c_iflag & IXON) {
-		mr0 |= MR0_SWFTX | MR0_SWFT;
-		imron |= IR_XONXOFF;
-	} else
-		imroff |= IR_XONXOFF;
-
-	if (tiosp->c_iflag & IXOFF)
-		mr0 |= MR0_SWFRX;
-
-	if (tiosp->c_cflag & CRTSCTS) {
-		mr2 |= MR2_AUTOCTS;
-		mr1 |= MR1_AUTORTS;
-	}
-
-/*
- *	All sc26198 register values calculated so go through and set
- *	them all up.
- */
-
-	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-	pr_debug("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
-	pr_debug("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
-	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IMR, 0);
-	stl_sc26198updatereg(portp, MR0, mr0);
-	stl_sc26198updatereg(portp, MR1, mr1);
-	stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
-	stl_sc26198updatereg(portp, MR2, mr2);
-	stl_sc26198updatereg(portp, IOPIOR,
-		((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
-
-	if (baudrate > 0) {
-		stl_sc26198setreg(portp, TXCSR, clk);
-		stl_sc26198setreg(portp, RXCSR, clk);
-	}
-
-	stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
-	stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
-
-	ipr = stl_sc26198getreg(portp, IPR);
-	if (ipr & IPR_DCD)
-		portp->sigs &= ~TIOCM_CD;
-	else
-		portp->sigs |= TIOCM_CD;
-
-	portp->imr = (portp->imr & ~imroff) | imron;
-	stl_sc26198setreg(portp, IMR, portp->imr);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set the state of the DTR and RTS signals.
- */
-
-static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
-{
-	unsigned char	iopioron, iopioroff;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
-			dtr, rts);
-
-	iopioron = 0;
-	iopioroff = 0;
-	if (dtr == 0)
-		iopioroff |= IPR_DTR;
-	else if (dtr > 0)
-		iopioron |= IPR_DTR;
-	if (rts == 0)
-		iopioroff |= IPR_RTS;
-	else if (rts > 0)
-		iopioron |= IPR_RTS;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IOPIOR,
-		((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the state of the signals.
- */
-
-static int stl_sc26198getsignals(struct stlport *portp)
-{
-	unsigned char	ipr;
-	unsigned long	flags;
-	int		sigs;
-
-	pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	ipr = stl_sc26198getreg(portp, IPR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	sigs = 0;
-	sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
-	sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
-	sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
-	sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
-	sigs |= TIOCM_DSR;
-	return sigs;
-}
-
-/*****************************************************************************/
-
-/*
- *	Enable/Disable the Transmitter and/or Receiver.
- */
-
-static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	ccr;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
-
-	ccr = portp->crenable;
-	if (tx == 0)
-		ccr &= ~CR_TXENABLE;
-	else if (tx > 0)
-		ccr |= CR_TXENABLE;
-	if (rx == 0)
-		ccr &= ~CR_RXENABLE;
-	else if (rx > 0)
-		ccr |= CR_RXENABLE;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, SCCR, ccr);
-	BRDDISABLE(portp->brdnr);
-	portp->crenable = ccr;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Start/stop the Transmitter and/or Receiver.
- */
-
-static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	imr;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	imr = portp->imr;
-	if (tx == 0)
-		imr &= ~IR_TXRDY;
-	else if (tx == 1)
-		imr |= IR_TXRDY;
-	if (rx == 0)
-		imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
-	else if (rx > 0)
-		imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IMR, imr);
-	BRDDISABLE(portp->brdnr);
-	portp->imr = imr;
-	if (tx > 0)
-		set_bit(ASYI_TXBUSY, &portp->istate);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Disable all interrupts from this port.
- */
-
-static void stl_sc26198disableintrs(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	portp->imr = 0;
-	stl_sc26198setreg(portp, IMR, 0);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static void stl_sc26198sendbreak(struct stlport *portp, int len)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	if (len == 1) {
-		stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
-		portp->stats.txbreaks++;
-	} else
-		stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Take flow control actions...
- */
-
-static void stl_sc26198flowctrl(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-	unsigned char		mr0;
-
-	pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-
-	if (state) {
-		if (tty->termios->c_iflag & IXOFF) {
-			mr0 = stl_sc26198getreg(portp, MR0);
-			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-			stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
-			mr0 |= MR0_SWFRX;
-			portp->stats.rxxon++;
-			stl_sc26198wait(portp);
-			stl_sc26198setreg(portp, MR0, mr0);
-		}
-/*
- *		Question: should we return RTS to what it was before? It may
- *		have been set by an ioctl... Suppose not, since if you have
- *		hardware flow control set then it is pretty silly to go and
- *		set the RTS line by hand.
- */
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_sc26198setreg(portp, MR1,
-				(stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
-			stl_sc26198setreg(portp, IOPIOR,
-				(stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
-			portp->stats.rxrtson++;
-		}
-	} else {
-		if (tty->termios->c_iflag & IXOFF) {
-			mr0 = stl_sc26198getreg(portp, MR0);
-			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-			stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
-			mr0 &= ~MR0_SWFRX;
-			portp->stats.rxxoff++;
-			stl_sc26198wait(portp);
-			stl_sc26198setreg(portp, MR0, mr0);
-		}
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_sc26198setreg(portp, MR1,
-				(stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
-			stl_sc26198setreg(portp, IOPIOR,
-				(stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
-			portp->stats.rxrtsoff++;
-		}
-	}
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a flow control character.
- */
-
-static void stl_sc26198sendflow(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-	unsigned char		mr0;
-
-	pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	if (state) {
-		mr0 = stl_sc26198getreg(portp, MR0);
-		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-		stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
-		mr0 |= MR0_SWFRX;
-		portp->stats.rxxon++;
-		stl_sc26198wait(portp);
-		stl_sc26198setreg(portp, MR0, mr0);
-	} else {
-		mr0 = stl_sc26198getreg(portp, MR0);
-		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-		stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
-		mr0 &= ~MR0_SWFRX;
-		portp->stats.rxxoff++;
-		stl_sc26198wait(portp);
-		stl_sc26198setreg(portp, MR0, mr0);
-	}
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_sc26198flush(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198flush(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, SCCR, CR_TXRESET);
-	stl_sc26198setreg(portp, SCCR, portp->crenable);
-	BRDDISABLE(portp->brdnr);
-	portp->tx.tail = portp->tx.head;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the current state of data flow on this port. This is only
- *	really interesting when determining if data has fully completed
- *	transmission or not... The sc26198 interrupt scheme cannot
- *	determine when all data has actually drained, so we need to
- *	check the port statusy register to be sure.
- */
-
-static int stl_sc26198datastate(struct stlport *portp)
-{
-	unsigned long	flags;
-	unsigned char	sr;
-
-	pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return 0;
-	if (test_bit(ASYI_TXBUSY, &portp->istate))
-		return 1;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	sr = stl_sc26198getreg(portp, SR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return (sr & SR_TXEMPTY) ? 0 : 1;
-}
-
-/*****************************************************************************/
-
-/*
- *	Delay for a small amount of time, to give the sc26198 a chance
- *	to process a command...
- */
-
-static void stl_sc26198wait(struct stlport *portp)
-{
-	int	i;
-
-	pr_debug("stl_sc26198wait(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	for (i = 0; i < 20; i++)
-		stl_sc26198getglobreg(portp, TSTR);
-}
-
-/*****************************************************************************/
-
-/*
- *	If we are TX flow controlled and in IXANY mode then we may
- *	need to unflow control here. We gotta do this because of the
- *	automatic flow control modes of the sc26198.
- */
-
-static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
-{
-	unsigned char	mr0;
-
-	mr0 = stl_sc26198getreg(portp, MR0);
-	stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-	stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
-	stl_sc26198wait(portp);
-	stl_sc26198setreg(portp, MR0, mr0);
-	clear_bit(ASYI_TXFLOWED, &portp->istate);
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for sc26198 panels.
- */
-
-static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
-{
-	struct stlport	*portp;
-	unsigned int	iack;
-
-	spin_lock(&brd_lock);
-
-/* 
- *	Work around bug in sc26198 chip... Cannot have A6 address
- *	line of UART high, else iack will be returned as 0.
- */
-	outb(0, (iobase + 1));
-
-	iack = inb(iobase + XP_IACK);
-	portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
-
-	if (iack & IVR_RXDATA)
-		stl_sc26198rxisr(portp, iack);
-	else if (iack & IVR_TXDATA)
-		stl_sc26198txisr(portp);
-	else
-		stl_sc26198otherisr(portp, iack);
-
-	spin_unlock(&brd_lock);
-}
-
-/*****************************************************************************/
-
-/*
- *	Transmit interrupt handler. This has gotta be fast!  Handling TX
- *	chars is pretty simple, stuff as many as possible from the TX buffer
- *	into the sc26198 FIFO.
- *	In practice it is possible that interrupts are enabled but that the
- *	port has been hung up. Need to handle not having any TX buffer here,
- *	this is done by using the side effect that head and tail will also
- *	be NULL if the buffer has been freed.
- */
-
-static void stl_sc26198txisr(struct stlport *portp)
-{
-	struct tty_struct *tty;
-	unsigned int	ioaddr;
-	unsigned char	mr0;
-	int		len, stlen;
-	char		*head, *tail;
-
-	pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
-
-	ioaddr = portp->ioaddr;
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((len == 0) || ((len < STL_TXBUFLOW) &&
-	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
-		set_bit(ASYI_TXLOW, &portp->istate);
-		tty = tty_port_tty_get(&portp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
-
-	if (len == 0) {
-		outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
-		mr0 = inb(ioaddr + XP_DATA);
-		if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
-			portp->imr &= ~IR_TXRDY;
-			outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
-			outb(portp->imr, (ioaddr + XP_DATA));
-			clear_bit(ASYI_TXBUSY, &portp->istate);
-		} else {
-			mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
-			outb(mr0, (ioaddr + XP_DATA));
-		}
-	} else {
-		len = min(len, SC26198_TXFIFOSIZE);
-		portp->stats.txtotal += len;
-		stlen = min_t(unsigned int, len,
-				(portp->tx.buf + STL_TXBUFSIZE) - tail);
-		outb(GTXFIFO, (ioaddr + XP_ADDR));
-		outsb((ioaddr + XP_DATA), tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
-			tail = portp->tx.buf;
-		if (len > 0) {
-			outsb((ioaddr + XP_DATA), tail, len);
-			tail += len;
-		}
-		portp->tx.tail = tail;
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Receive character interrupt handler. Determine if we have good chars
- *	or bad chars and then process appropriately. Good chars are easy
- *	just shove the lot into the RX buffer and set all status byte to 0.
- *	If a bad RX char then process as required. This routine needs to be
- *	fast!  In practice it is possible that we get an interrupt on a port
- *	that is closed. This can happen on hangups - since they completely
- *	shutdown a port not in user context. Need to handle this case.
- */
-
-static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
-{
-	struct tty_struct	*tty;
-	unsigned int		len, buflen, ioaddr;
-
-	pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
-
-	tty = tty_port_tty_get(&portp->port);
-	ioaddr = portp->ioaddr;
-	outb(GIBCR, (ioaddr + XP_ADDR));
-	len = inb(ioaddr + XP_DATA) + 1;
-
-	if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
-		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-			len = min_t(unsigned int, len, sizeof(stl_unwanted));
-			outb(GRXFIFO, (ioaddr + XP_ADDR));
-			insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
-			portp->stats.rxlost += len;
-			portp->stats.rxtotal += len;
-		} else {
-			len = min(len, buflen);
-			if (len > 0) {
-				unsigned char *ptr;
-				outb(GRXFIFO, (ioaddr + XP_ADDR));
-				tty_prepare_flip_string(tty, &ptr, len);
-				insb((ioaddr + XP_DATA), ptr, len);
-				tty_schedule_flip(tty);
-				portp->stats.rxtotal += len;
-			}
-		}
-	} else {
-		stl_sc26198rxbadchars(portp);
-	}
-
-/*
- *	If we are TX flow controlled and in IXANY mode then we may need
- *	to unflow control here. We gotta do this because of the automatic
- *	flow control modes of the sc26198.
- */
-	if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
-		if ((tty != NULL) &&
-		    (tty->termios != NULL) &&
-		    (tty->termios->c_iflag & IXANY)) {
-			stl_sc26198txunflow(portp, tty);
-		}
-	}
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Process an RX bad character.
- */
-
-static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
-{
-	struct tty_struct	*tty;
-	unsigned int		ioaddr;
-
-	tty = tty_port_tty_get(&portp->port);
-	ioaddr = portp->ioaddr;
-
-	if (status & SR_RXPARITY)
-		portp->stats.rxparity++;
-	if (status & SR_RXFRAMING)
-		portp->stats.rxframing++;
-	if (status & SR_RXOVERRUN)
-		portp->stats.rxoverrun++;
-	if (status & SR_RXBREAK)
-		portp->stats.rxbreaks++;
-
-	if ((tty != NULL) &&
-	    ((portp->rxignoremsk & status) == 0)) {
-		if (portp->rxmarkmsk & status) {
-			if (status & SR_RXBREAK) {
-				status = TTY_BREAK;
-				if (portp->port.flags & ASYNC_SAK) {
-					do_SAK(tty);
-					BRDENABLE(portp->brdnr, portp->pagenr);
-				}
-			} else if (status & SR_RXPARITY)
-				status = TTY_PARITY;
-			else if (status & SR_RXFRAMING)
-				status = TTY_FRAME;
-			else if(status & SR_RXOVERRUN)
-				status = TTY_OVERRUN;
-			else
-				status = 0;
-		} else
-			status = 0;
-
-		tty_insert_flip_char(tty, ch, status);
-		tty_schedule_flip(tty);
-
-		if (status == 0)
-			portp->stats.rxtotal++;
-	}
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Process all characters in the RX FIFO of the UART. Check all char
- *	status bytes as well, and process as required. We need to check
- *	all bytes in the FIFO, in case some more enter the FIFO while we
- *	are here. To get the exact character error type we need to switch
- *	into CHAR error mode (that is why we need to make sure we empty
- *	the FIFO).
- */
-
-static void stl_sc26198rxbadchars(struct stlport *portp)
-{
-	unsigned char	status, mr1;
-	char		ch;
-
-/*
- *	To get the precise error type for each character we must switch
- *	back into CHAR error mode.
- */
-	mr1 = stl_sc26198getreg(portp, MR1);
-	stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
-
-	while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
-		stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
-		ch = stl_sc26198getreg(portp, RXFIFO);
-		stl_sc26198rxbadch(portp, status, ch);
-	}
-
-/*
- *	To get correct interrupt class we must switch back into BLOCK
- *	error mode.
- */
-	stl_sc26198setreg(portp, MR1, mr1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Other interrupt handler. This includes modem signals, flow
- *	control actions, etc. Most stuff is left to off-level interrupt
- *	processing time.
- */
-
-static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
-{
-	unsigned char	cir, ipr, xisr;
-
-	pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
-
-	cir = stl_sc26198getglobreg(portp, CIR);
-
-	switch (cir & CIR_SUBTYPEMASK) {
-	case CIR_SUBCOS:
-		ipr = stl_sc26198getreg(portp, IPR);
-		if (ipr & IPR_DCDCHANGE) {
-			stl_cd_change(portp);
-			portp->stats.modem++;
-		}
-		break;
-	case CIR_SUBXONXOFF:
-		xisr = stl_sc26198getreg(portp, XISR);
-		if (xisr & XISR_RXXONGOT) {
-			set_bit(ASYI_TXFLOWED, &portp->istate);
-			portp->stats.txxoff++;
-		}
-		if (xisr & XISR_RXXOFFGOT) {
-			clear_bit(ASYI_TXFLOWED, &portp->istate);
-			portp->stats.txxon++;
-		}
-		break;
-	case CIR_SUBBREAK:
-		stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
-		stl_sc26198rxbadchars(portp);
-		break;
-	default:
-		break;
-	}
-}
-
-static void stl_free_isabrds(void)
-{
-	struct stlbrd *brdp;
-	unsigned int i;
-
-	for (i = 0; i < stl_nrbrds; i++) {
-		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
-			continue;
-
-		free_irq(brdp->irq, brdp);
-
-		stl_cleanup_panels(brdp);
-
-		release_region(brdp->ioaddr1, brdp->iosize1);
-		if (brdp->iosize2 > 0)
-			release_region(brdp->ioaddr2, brdp->iosize2);
-
-		kfree(brdp);
-		stl_brds[i] = NULL;
-	}
-}
-
-/*
- *	Loadable module initialization stuff.
- */
-static int __init stallion_module_init(void)
-{
-	struct stlbrd	*brdp;
-	struct stlconf	conf;
-	unsigned int i, j;
-	int retval;
-
-	printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-	spin_lock_init(&stallion_lock);
-	spin_lock_init(&brd_lock);
-
-	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stl_serial) {
-		retval = -ENOMEM;
-		goto err;
-	}
-
-	stl_serial->owner = THIS_MODULE;
-	stl_serial->driver_name = stl_drvname;
-	stl_serial->name = "ttyE";
-	stl_serial->major = STL_SERIALMAJOR;
-	stl_serial->minor_start = 0;
-	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stl_serial->subtype = SERIAL_TYPE_NORMAL;
-	stl_serial->init_termios = stl_deftermios;
-	stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stl_serial, &stl_ops);
-
-	retval = tty_register_driver(stl_serial);
-	if (retval) {
-		printk("STALLION: failed to register serial driver\n");
-		goto err_frtty;
-	}
-
-/*
- *	Find any dynamically supported boards. That is via module load
- *	line options.
- */
-	for (i = stl_nrbrds; i < stl_nargs; i++) {
-		memset(&conf, 0, sizeof(conf));
-		if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
-			continue;
-		if ((brdp = stl_allocbrd()) == NULL)
-			continue;
-		brdp->brdnr = i;
-		brdp->brdtype = conf.brdtype;
-		brdp->ioaddr1 = conf.ioaddr1;
-		brdp->ioaddr2 = conf.ioaddr2;
-		brdp->irq = conf.irq;
-		brdp->irqtype = conf.irqtype;
-		stl_brds[brdp->brdnr] = brdp;
-		if (stl_brdinit(brdp)) {
-			stl_brds[brdp->brdnr] = NULL;
-			kfree(brdp);
-		} else {
-			for (j = 0; j < brdp->nrports; j++)
-				tty_register_device(stl_serial,
-					brdp->brdnr * STL_MAXPORTS + j, NULL);
-			stl_nrbrds = i + 1;
-		}
-	}
-
-	/* this has to be _after_ isa finding because of locking */
-	retval = pci_register_driver(&stl_pcidriver);
-	if (retval && stl_nrbrds == 0) {
-		printk(KERN_ERR "STALLION: can't register pci driver\n");
-		goto err_unrtty;
-	}
-
-/*
- *	Set up a character driver for per board stuff. This is mainly used
- *	to do stats ioctls on the ports.
- */
-	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
-		printk("STALLION: failed to register serial board device\n");
-
-	stallion_class = class_create(THIS_MODULE, "staliomem");
-	if (IS_ERR(stallion_class))
-		printk("STALLION: failed to create class\n");
-	for (i = 0; i < 4; i++)
-		device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      NULL, "staliomem%d", i);
-
-	return 0;
-err_unrtty:
-	tty_unregister_driver(stl_serial);
-err_frtty:
-	put_tty_driver(stl_serial);
-err:
-	return retval;
-}
-
-static void __exit stallion_module_exit(void)
-{
-	struct stlbrd *brdp;
-	unsigned int i, j;
-
-	pr_debug("cleanup_module()\n");
-
-	printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
-		stl_drvversion);
-
-/*
- *	Free up all allocated resources used by the ports. This includes
- *	memory and interrupts. As part of this process we will also do
- *	a hangup on every open port - to try to flush out any processes
- *	hanging onto ports.
- */
-	for (i = 0; i < stl_nrbrds; i++) {
-		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
-			continue;
-		for (j = 0; j < brdp->nrports; j++)
-			tty_unregister_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + j);
-	}
-
-	for (i = 0; i < 4; i++)
-		device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
-	class_destroy(stallion_class);
-
-	pci_unregister_driver(&stl_pcidriver);
-
-	stl_free_isabrds();
-
-	tty_unregister_driver(stl_serial);
-	put_tty_driver(stl_serial);
-}
-
-module_init(stallion_module_init);
-module_exit(stallion_module_exit);
-
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
deleted file mode 100644
index a786326..0000000
--- a/drivers/char/sx.c
+++ /dev/null
@@ -1,2894 +0,0 @@
-/* sx.c -- driver for the Specialix SX series cards. 
- *
- *  This driver will also support the older SI, and XIO cards.
- *
- *
- *   (C) 1998 - 2004  R.E.Wolff@BitWizard.nl
- *
- *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
- *  version of this driver. Some fragments may have been copied. (none
- *  yet :-)
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (sx.txt) first.
- *
- *
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License as
- *      published by the Free Software Foundation; either version 2 of
- *      the License, or (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be
- *      useful, but WITHOUT ANY WARRANTY; without even the implied
- *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- *      PURPOSE.  See the GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public
- *      License along with this program; if not, write to the Free
- *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- *      USA.
- *
- * Revision history:
- * Revision 1.33  2000/03/09 10:00:00  pvdl,wolff
- * - Fixed module and port counting
- * - Fixed signal handling
- * - Fixed an Ooops
- * 
- * Revision 1.32  2000/03/07 09:00:00  wolff,pvdl
- * - Fixed some sx_dprintk typos
- * - added detection for an invalid board/module configuration
- *
- * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
- * - Added support for EISA
- *
- * Revision 1.30  2000/01/21 17:43:06  wolff
- * - Added support for SX+
- *
- * Revision 1.26  1999/08/05 15:22:14  wolff
- * - Port to 2.3.x
- * - Reformatted to Linus' liking.
- *
- * Revision 1.25  1999/07/30 14:24:08  wolff
- * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
- *
- * Revision 1.24  1999/07/28 09:41:52  wolff
- * - I noticed the remark about use-count straying in sx.txt. I checked
- *   sx_open, and found a few places where that could happen. I hope it's
- *   fixed now.
- *
- * Revision 1.23  1999/07/28 08:56:06  wolff
- * - Fixed crash when sx_firmware run twice.
- * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
- *   to change it from the default... )
- * - Fixed a stupid editing problem I introduced in 1.22.
- * - Fixed dropping characters on a termios change.
- *
- * Revision 1.22  1999/07/26 21:01:43  wolff
- * Russell Brown noticed that I had overlooked 4 out of six modem control
- * signals in sx_getsignals. Ooops.
- *
- * Revision 1.21  1999/07/23 09:11:33  wolff
- * I forgot to free dynamically allocated memory when the driver is unloaded.
- *
- * Revision 1.20  1999/07/20 06:25:26  wolff
- * The "closing wait" wasn't honoured. Thanks to James Griffiths for
- * reporting this.
- *
- * Revision 1.19  1999/07/11 08:59:59  wolff
- * Fixed an oops in close, when an open was pending. Changed the memtest
- * a bit. Should also test the board in word-mode, however my card fails the
- * memtest then. I still have to figure out what is wrong...
- *
- * Revision 1.18  1999/06/10 09:38:42  wolff
- * Changed the format of the firmware revision from %04x to %x.%02x .
- *
- * Revision 1.17  1999/06/04 09:44:35  wolff
- * fixed problem: reference to pci stuff when config_pci was off...
- * Thanks to Jorge Novo for noticing this.
- *
- * Revision 1.16  1999/06/02 08:30:15  wolff
- * added/removed the workaround for the DCD bug in the Firmware.
- * A bit more debugging code to locate that...
- *
- * Revision 1.15  1999/06/01 11:35:30  wolff
- * when DCD is left low (floating?), on TA's the firmware first tells us
- * that DCD is high, but after a short while suddenly comes to the
- * conclusion that it is low. All this would be fine, if it weren't that
- * Unix requires us to send a "hangup" signal in that case. This usually
- * all happens BEFORE the program has had a chance to ioctl the device
- * into clocal mode..
- *
- * Revision 1.14  1999/05/25 11:18:59  wolff
- * Added PCI-fix.
- * Added checks for return code of sx_sendcommand.
- * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
- *
- * Revision 1.13  1999/04/29 15:18:01  wolff
- * Fixed an "oops" that showed on SuSE 6.0 systems.
- * Activate DTR again after stty 0.
- *
- * Revision 1.12  1999/04/29 07:49:52  wolff
- * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
- *     the connection would be dropped anyway. That is not always the case,
- *     and confuses people).
- * Told the card to always monitor the modem signals.
- * Added support for dynamic  gs_debug adjustments.
- * Now tells the rest of the system the number of ports.
- *
- * Revision 1.11  1999/04/24 11:11:30  wolff
- * Fixed two stupid typos in the memory test.
- *
- * Revision 1.10  1999/04/24 10:53:39  wolff
- * Added some of Christian's suggestions.
- * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
- * card to send the signal to the process.....)
- *
- * Revision 1.9  1999/04/23 07:26:38  wolff
- * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
- *    assignment redesign.
- * Cleanup of some other stuff.
- *
- * Revision 1.8  1999/04/16 13:05:30  wolff
- * fixed a DCD change unnoticed bug.
- *
- * Revision 1.7  1999/04/14 22:19:51  wolff
- * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
- *
- * Revision 1.6  1999/04/13 18:40:20  wolff
- * changed misc-minor to 161, as assigned by HPA.
- *
- * Revision 1.5  1999/04/13 15:12:25  wolff
- * Fixed use-count leak when "hangup" occurred.
- * Added workaround for a stupid-PCIBIOS bug.
- *
- *
- * Revision 1.4  1999/04/01 22:47:40  wolff
- * Fixed < 1M linux-2.0 problem.
- * (vremap isn't compatible with ioremap in that case)
- *
- * Revision 1.3  1999/03/31 13:45:45  wolff
- * Firmware loading is now done through a separate IOCTL.
- *
- * Revision 1.2  1999/03/28 12:22:29  wolff
- * rcs cleanup
- *
- * Revision 1.1  1999/03/28 12:10:34  wolff
- * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). 
- *
- * Revision 0.12  1999/03/28 09:20:10  wolff
- * Fixed problem in 0.11, continueing cleanup.
- *
- * Revision 0.11  1999/03/28 08:46:44  wolff
- * cleanup. Not good.
- *
- * Revision 0.10  1999/03/28 08:09:43  wolff
- * Fixed loosing characters on close.
- *
- * Revision 0.9  1999/03/21 22:52:01  wolff
- * Ported back to 2.2.... (minor things)
- *
- * Revision 0.8  1999/03/21 22:40:33  wolff
- * Port to 2.0
- *
- * Revision 0.7  1999/03/21 19:06:34  wolff
- * Fixed hangup processing.
- *
- * Revision 0.6  1999/02/05 08:45:14  wolff
- * fixed real_raw problems. Inclusion into kernel imminent.
- *
- * Revision 0.5  1998/12/21 23:51:06  wolff
- * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
- * shouldn't have. THATs why I want to have transmit interrupts even when
- * the buffer is empty.
- *
- * Revision 0.4  1998/12/17 09:34:46  wolff
- * PPP works. ioctl works. Basically works!
- *
- * Revision 0.3  1998/12/15 13:05:18  wolff
- * It works! Wow! Gotta start implementing IOCTL and stuff....
- *
- * Revision 0.2  1998/12/01 08:33:53  wolff
- * moved over to 2.1.130
- *
- * Revision 0.1  1998/11/03 21:23:51  wolff
- * Initial revision. Detects SX card.
- *
- * */
-
-#define SX_VERSION	1.33
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/eisa.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* The 3.0.0 version of sxboards/sxwindow.h  uses BYTE and WORD.... */
-#define BYTE u8
-#define WORD u16
-
-/* .... but the 3.0.4 version uses _u8 and _u16. */
-#define _u8 u8
-#define _u16 u16
-
-#include "sxboards.h"
-#include "sxwindow.h"
-
-#include <linux/generic_serial.h>
-#include "sx.h"
-
-/* I don't think that this driver can handle more than 256 ports on
-   one machine. You'll have to increase the number of boards in sx.h
-   if you want more than 4 boards.  */
-
-#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
-#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
-#endif
-
-/* Configurable options: 
-   (Don't be too sure that it'll work if you toggle them) */
-
-/* Am I paranoid or not ? ;-) */
-#undef SX_PARANOIA_CHECK
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
-   Hz, but it is user configurable. I don't recommend going above 1000
-   Hz. The interrupt ratelimit might trigger if the interrupt is
-   shared with a very active other device. */
-#define IRQ_RATE_LIMIT 20
-
-/* Sharing interrupts is possible now. If the other device wants more
-   than 2000 interrupts per second, we'd gracefully decline further
-   interrupts. That's not what we want. On the other hand, if the
-   other device interrupts 2000 times a second, don't use the SX
-   interrupt. Use polling. */
-#undef IRQ_RATE_LIMIT
-
-#if 0
-/* Not implemented */
-/* 
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define SX_REPORT_FIFO
-#define SX_REPORT_OVERRUN
-#endif
-
-/* Function prototypes */
-static void sx_disable_tx_interrupts(void *ptr);
-static void sx_enable_tx_interrupts(void *ptr);
-static void sx_disable_rx_interrupts(void *ptr);
-static void sx_enable_rx_interrupts(void *ptr);
-static int sx_carrier_raised(struct tty_port *port);
-static void sx_shutdown_port(void *ptr);
-static int sx_set_real_termios(void *ptr);
-static void sx_close(void *ptr);
-static int sx_chars_in_buffer(void *ptr);
-static int sx_init_board(struct sx_board *board);
-static int sx_init_portstructs(int nboards, int nports);
-static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
-						unsigned long arg);
-static int sx_init_drivers(void);
-
-static struct tty_driver *sx_driver;
-
-static DEFINE_MUTEX(sx_boards_lock);
-static struct sx_board boards[SX_NBOARDS];
-static struct sx_port *sx_ports;
-static int sx_initialized;
-static int sx_nports;
-static int sx_debug;
-
-/* You can have the driver poll your card. 
-    - Set sx_poll to 1 to poll every timer tick (10ms on Intel). 
-      This is used when the card cannot use an interrupt for some reason.
-
-    - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If 
-      the driver misses an interrupt (report this if it DOES happen to you!)
-      everything will continue to work.... 
- */
-static int sx_poll = 1;
-static int sx_slowpoll;
-
-/* The card limits the number of interrupts per second. 
-   At 115k2 "100" should be sufficient. 
-   If you're using higher baudrates, you can increase this...
- */
-
-static int sx_maxints = 100;
-
-#ifdef CONFIG_ISA
-
-/* These are the only open spaces in my computer. Yours may have more
-   or less.... -- REW 
-   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
-*/
-static int sx_probe_addrs[] = {
-	0xc0000, 0xd0000, 0xe0000,
-	0xc8000, 0xd8000, 0xe8000
-};
-static int si_probe_addrs[] = {
-	0xc0000, 0xd0000, 0xe0000,
-	0xc8000, 0xd8000, 0xe8000, 0xa0000
-};
-static int si1_probe_addrs[] = {
-	0xd0000
-};
-
-#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
-#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
-#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
-
-module_param_array(sx_probe_addrs, int, NULL, 0);
-module_param_array(si_probe_addrs, int, NULL, 0);
-#endif
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
-   Some architectures may need more. */
-static int sx_irqmask = -1;
-
-module_param(sx_poll, int, 0);
-module_param(sx_slowpoll, int, 0);
-module_param(sx_maxints, int, 0);
-module_param(sx_debug, int, 0);
-module_param(sx_irqmask, int, 0);
-
-MODULE_LICENSE("GPL");
-
-static struct real_driver sx_real_driver = {
-	sx_disable_tx_interrupts,
-	sx_enable_tx_interrupts,
-	sx_disable_rx_interrupts,
-	sx_enable_rx_interrupts,
-	sx_shutdown_port,
-	sx_set_real_termios,
-	sx_chars_in_buffer,
-	sx_close,
-};
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define sx_dprintk(f, str...)	if (sx_debug & f) printk (str)
-#else
-#define sx_dprintk(f, str...)	/* nothing */
-#endif
-
-#define func_enter()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
-#define func_exit()	sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__func__)
-
-#define func_enter2()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
-				__func__, port->line)
-
-/* 
- *  Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations sx_fw_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = sx_fw_ioctl,
-	.llseek = noop_llseek,
-};
-
-static struct miscdevice sx_fw_device = {
-	SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
-};
-
-#ifdef SX_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int sx_paranoia_check(struct sx_port const *port,
-				    char *name, const char *routine)
-{
-	static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
-			"number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
-			"device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != SX_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-#else
-#define sx_paranoia_check(a,b,c) 0
-#endif
-
-/* The timeouts. First try 30 times as fast as possible. Then give
-   the card some time to breathe between accesses. (Otherwise the
-   processor on the card might not be able to access its OWN bus... */
-
-#define TIMEOUT_1 30
-#define TIMEOUT_2 1000000
-
-#ifdef DEBUG
-static void my_hd_io(void __iomem *p, int len)
-{
-	int i, j, ch;
-	unsigned char __iomem *addr = p;
-
-	for (i = 0; i < len; i += 16) {
-		printk("%p ", addr + i);
-		for (j = 0; j < 16; j++) {
-			printk("%02x %s", readb(addr + j + i),
-					(j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = readb(addr + j + i);
-			printk("%c", (ch < 0x20) ? '.' :
-					((ch > 0x7f) ? '.' : ch));
-		}
-		printk("\n");
-	}
-}
-static void my_hd(void *p, int len)
-{
-	int i, j, ch;
-	unsigned char *addr = p;
-
-	for (i = 0; i < len; i += 16) {
-		printk("%p ", addr + i);
-		for (j = 0; j < 16; j++) {
-			printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = addr[j + i];
-			printk("%c", (ch < 0x20) ? '.' :
-					((ch > 0x7f) ? '.' : ch));
-		}
-		printk("\n");
-	}
-}
-#endif
-
-/* This needs redoing for Alpha -- REW -- Done. */
-
-static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
-{
-	writeb(byte, board->base + offset);
-}
-
-static inline u8 read_sx_byte(struct sx_board *board, int offset)
-{
-	return readb(board->base + offset);
-}
-
-static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
-{
-	writew(word, board->base + offset);
-}
-
-static inline u16 read_sx_word(struct sx_board *board, int offset)
-{
-	return readw(board->base + offset);
-}
-
-static int sx_busy_wait_eq(struct sx_board *board,
-		int offset, int mask, int correctval)
-{
-	int i;
-
-	func_enter();
-
-	for (i = 0; i < TIMEOUT_1; i++)
-		if ((read_sx_byte(board, offset) & mask) == correctval) {
-			func_exit();
-			return 1;
-		}
-
-	for (i = 0; i < TIMEOUT_2; i++) {
-		if ((read_sx_byte(board, offset) & mask) == correctval) {
-			func_exit();
-			return 1;
-		}
-		udelay(1);
-	}
-
-	func_exit();
-	return 0;
-}
-
-static int sx_busy_wait_neq(struct sx_board *board,
-		int offset, int mask, int badval)
-{
-	int i;
-
-	func_enter();
-
-	for (i = 0; i < TIMEOUT_1; i++)
-		if ((read_sx_byte(board, offset) & mask) != badval) {
-			func_exit();
-			return 1;
-		}
-
-	for (i = 0; i < TIMEOUT_2; i++) {
-		if ((read_sx_byte(board, offset) & mask) != badval) {
-			func_exit();
-			return 1;
-		}
-		udelay(1);
-	}
-
-	func_exit();
-	return 0;
-}
-
-/* 5.6.4 of 6210028 r2.3 */
-static int sx_reset(struct sx_board *board)
-{
-	func_enter();
-
-	if (IS_SX_BOARD(board)) {
-
-		write_sx_byte(board, SX_CONFIG, 0);
-		write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
-
-		if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
-			printk(KERN_INFO "sx: Card doesn't respond to "
-					"reset...\n");
-			return 0;
-		}
-	} else if (IS_EISA_BOARD(board)) {
-		outb(board->irq << 4, board->eisa_base + 0xc02);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_RESET, 0);	/*value doesn't matter*/
-	} else {
-		/* Gory details of the SI/ISA board */
-		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
-		write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
-	}
-
-	func_exit();
-	return 1;
-}
-
-/* This doesn't work on machines where "NULL" isn't 0 */
-/* If you have one of those, someone will need to write 
-   the equivalent of this, which will amount to about 3 lines. I don't
-   want to complicate this right now. -- REW
-   (See, I do write comments every now and then :-) */
-#define OFFSETOF(strct, elem)	((long)&(((struct strct *)NULL)->elem))
-
-#define CHAN_OFFSET(port,elem)	(port->ch_base + OFFSETOF (_SXCHANNEL, elem))
-#define MODU_OFFSET(board,addr,elem)	(addr + OFFSETOF (_SXMODULE, elem))
-#define  BRD_OFFSET(board,elem)	(OFFSETOF (_SXCARD, elem))
-
-#define sx_write_channel_byte(port, elem, val) \
-	write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_byte(port, elem) \
-	read_sx_byte (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_channel_word(port, elem, val) \
-	write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_word(port, elem) \
-	read_sx_word (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_module_byte(board, addr, elem, val) \
-	write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_byte(board, addr, elem) \
-	read_sx_byte (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_module_word(board, addr, elem, val) \
-	write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_word(board, addr, elem) \
-	read_sx_word (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_board_byte(board, elem, val) \
-	write_sx_byte (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_byte(board, elem) \
-	read_sx_byte (board, BRD_OFFSET (board, elem))
-
-#define sx_write_board_word(board, elem, val) \
-	write_sx_word (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_word(board, elem) \
-	read_sx_word (board, BRD_OFFSET (board, elem))
-
-static int sx_start_board(struct sx_board *board)
-{
-	if (IS_SX_BOARD(board)) {
-		write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
-	} else if (IS_EISA_BOARD(board)) {
-		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
-		outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
-		write_sx_byte(board, SI1_ISA_INTCL, 0);
-	} else {
-		/* Don't bug me about the clear_set. 
-		   I haven't the foggiest idea what it's about -- REW */
-		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
-	}
-	return 1;
-}
-
-#define SX_IRQ_REG_VAL(board) \
-	((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
-
-/* Note. The SX register is write-only. Therefore, we have to enable the
-   bus too. This is a no-op, if you don't mess with this driver... */
-static int sx_start_interrupts(struct sx_board *board)
-{
-
-	/* Don't call this with board->irq == 0 */
-
-	if (IS_SX_BOARD(board)) {
-		write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
-				SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
-	} else if (IS_EISA_BOARD(board)) {
-		inb(board->eisa_base + 0xc03);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_INTCL, 0);
-		write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
-	} else {
-		switch (board->irq) {
-		case 11:
-			write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
-			break;
-		case 12:
-			write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
-			break;
-		case 15:
-			write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
-			break;
-		default:
-			printk(KERN_INFO "sx: SI/XIO card doesn't support "
-					"interrupt %d.\n", board->irq);
-			return 0;
-		}
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
-	}
-
-	return 1;
-}
-
-static int sx_send_command(struct sx_port *port,
-		int command, int mask, int newstat)
-{
-	func_enter2();
-	write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
-	func_exit();
-	return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
-			newstat);
-}
-
-static char *mod_type_s(int module_type)
-{
-	switch (module_type) {
-	case TA4:
-		return "TA4";
-	case TA8:
-		return "TA8";
-	case TA4_ASIC:
-		return "TA4_ASIC";
-	case TA8_ASIC:
-		return "TA8_ASIC";
-	case MTA_CD1400:
-		return "MTA_CD1400";
-	case SXDC:
-		return "SXDC";
-	default:
-		return "Unknown/invalid";
-	}
-}
-
-static char *pan_type_s(int pan_type)
-{
-	switch (pan_type) {
-	case MOD_RS232DB25:
-		return "MOD_RS232DB25";
-	case MOD_RS232RJ45:
-		return "MOD_RS232RJ45";
-	case MOD_RS422DB25:
-		return "MOD_RS422DB25";
-	case MOD_PARALLEL:
-		return "MOD_PARALLEL";
-	case MOD_2_RS232DB25:
-		return "MOD_2_RS232DB25";
-	case MOD_2_RS232RJ45:
-		return "MOD_2_RS232RJ45";
-	case MOD_2_RS422DB25:
-		return "MOD_2_RS422DB25";
-	case MOD_RS232DB25MALE:
-		return "MOD_RS232DB25MALE";
-	case MOD_2_PARALLEL:
-		return "MOD_2_PARALLEL";
-	case MOD_BLANK:
-		return "empty";
-	default:
-		return "invalid";
-	}
-}
-
-static int mod_compat_type(int module_type)
-{
-	return module_type >> 4;
-}
-
-static void sx_reconfigure_port(struct sx_port *port)
-{
-	if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
-		if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-			printk(KERN_WARNING "sx: Sent reconfigure command, but "
-					"card didn't react.\n");
-		}
-	} else {
-		sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
-				"port isn't open (%02x).\n",
-				sx_read_channel_byte(port, hi_hstat));
-	}
-}
-
-static void sx_setsignals(struct sx_port *port, int dtr, int rts)
-{
-	int t;
-	func_enter2();
-
-	t = sx_read_channel_byte(port, hi_op);
-	if (dtr >= 0)
-		t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
-	if (rts >= 0)
-		t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
-	sx_write_channel_byte(port, hi_op, t);
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
-
-	func_exit();
-}
-
-static int sx_getsignals(struct sx_port *port)
-{
-	int i_stat, o_stat;
-
-	o_stat = sx_read_channel_byte(port, hi_op);
-	i_stat = sx_read_channel_byte(port, hi_ip);
-
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d  (%d/%d) "
-			"%02x/%02x\n",
-			(o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
-			port->c_dcd, tty_port_carrier_raised(&port->gs.port),
-			sx_read_channel_byte(port, hi_ip),
-			sx_read_channel_byte(port, hi_state));
-
-	return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
-		((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
-		((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
-		((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
-		((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
-		((i_stat & IP_RI) ? TIOCM_RNG : 0));
-}
-
-static void sx_set_baud(struct sx_port *port)
-{
-	int t;
-
-	if (port->board->ta_type == MOD_SXDC) {
-		switch (port->gs.baud) {
-			/* Save some typing work... */
-#define e(x) case x: t = BAUD_ ## x; break
-			e(50);
-			e(75);
-			e(110);
-			e(150);
-			e(200);
-			e(300);
-			e(600);
-			e(1200);
-			e(1800);
-			e(2000);
-			e(2400);
-			e(4800);
-			e(7200);
-			e(9600);
-			e(14400);
-			e(19200);
-			e(28800);
-			e(38400);
-			e(56000);
-			e(57600);
-			e(64000);
-			e(76800);
-			e(115200);
-			e(128000);
-			e(150000);
-			e(230400);
-			e(256000);
-			e(460800);
-			e(921600);
-		case 134:
-			t = BAUD_134_5;
-			break;
-		case 0:
-			t = -1;
-			break;
-		default:
-			/* Can I return "invalid"? */
-			t = BAUD_9600;
-			printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
-					port->gs.baud);
-			break;
-		}
-#undef e
-		if (t > 0) {
-/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
-			sx_setsignals(port, 1, -1);
-			/* XXX This is not TA & MTA compatible */
-			sx_write_channel_byte(port, hi_csr, 0xff);
-
-			sx_write_channel_byte(port, hi_txbaud, t);
-			sx_write_channel_byte(port, hi_rxbaud, t);
-		} else {
-			sx_setsignals(port, 0, -1);
-		}
-	} else {
-		switch (port->gs.baud) {
-#define e(x) case x: t = CSR_ ## x; break
-			e(75);
-			e(150);
-			e(300);
-			e(600);
-			e(1200);
-			e(2400);
-			e(4800);
-			e(1800);
-			e(9600);
-			e(19200);
-			e(57600);
-			e(38400);
-/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
-		case 110:
-			if (port->board->ta_type == MOD_TA) {
-				t = CSR_110;
-				break;
-			} else {
-				t = CSR_9600;
-				printk(KERN_INFO "sx: Unsupported baud rate: "
-						"%d.\n", port->gs.baud);
-				break;
-			}
-		case 115200:
-			if (port->board->ta_type == MOD_TA) {
-				t = CSR_9600;
-				printk(KERN_INFO "sx: Unsupported baud rate: "
-						"%d.\n", port->gs.baud);
-				break;
-			} else {
-				t = CSR_110;
-				break;
-			}
-		case 0:
-			t = -1;
-			break;
-		default:
-			t = CSR_9600;
-			printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
-					port->gs.baud);
-			break;
-		}
-#undef e
-		if (t >= 0) {
-			sx_setsignals(port, 1, -1);
-			sx_write_channel_byte(port, hi_csr, t * 0x11);
-		} else {
-			sx_setsignals(port, 0, -1);
-		}
-	}
-}
-
-/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
-   better. -- REW */
-
-static int sx_set_real_termios(void *ptr)
-{
-	struct sx_port *port = ptr;
-
-	func_enter2();
-
-	if (!port->gs.port.tty)
-		return 0;
-
-	/* What is this doing here? -- REW
-	   Ha! figured it out. It is to allow you to get DTR active again
-	   if you've dropped it with stty 0. Moved to set_baud, where it
-	   belongs (next to the drop dtr if baud == 0) -- REW */
-	/* sx_setsignals (port, 1, -1); */
-
-	sx_set_baud(port);
-
-#define CFLAG port->gs.port.tty->termios->c_cflag
-	sx_write_channel_byte(port, hi_mr1,
-			(C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
-			(C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
-			(C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
-			(((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
-			(((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
-			(((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
-			(((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
-
-	sx_write_channel_byte(port, hi_mr2,
-			(C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
-			(C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
-			MR2_1_STOP));
-
-	switch (CFLAG & CSIZE) {
-	case CS8:
-		sx_write_channel_byte(port, hi_mask, 0xff);
-		break;
-	case CS7:
-		sx_write_channel_byte(port, hi_mask, 0x7f);
-		break;
-	case CS6:
-		sx_write_channel_byte(port, hi_mask, 0x3f);
-		break;
-	case CS5:
-		sx_write_channel_byte(port, hi_mask, 0x1f);
-		break;
-	default:
-		printk(KERN_INFO "sx: Invalid wordsize: %u\n",
-			(unsigned int)CFLAG & CSIZE);
-		break;
-	}
-
-	sx_write_channel_byte(port, hi_prtcl,
-			(I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
-			(I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
-			(I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
-
-	sx_write_channel_byte(port, hi_break,
-			(I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
-			I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
-
-	sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
-
-	sx_reconfigure_port(port);
-
-	/* Tell line discipline whether we will do input cooking */
-	if (I_OTHER(port->gs.port.tty)) {
-		clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
-	} else {
-		set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
-	}
-	sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
-			(unsigned int)port->gs.port.tty->termios->c_iflag,
-			I_OTHER(port->gs.port.tty));
-
-/* Tell line discipline whether we will do output cooking.
- * If OPOST is set and no other output flags are set then we can do output
- * processing.  Even if only *one* other flag in the O_OTHER group is set
- * we do cooking in software.
- */
-	if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
-		set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
-	} else {
-		clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
-	}
-	sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
-			(unsigned int)port->gs.port.tty->termios->c_oflag,
-			O_OTHER(port->gs.port.tty));
-	/* port->c_dcd = sx_get_CD (port); */
-	func_exit();
-	return 0;
-}
-
-/* ********************************************************************** *
- *                   the interrupt related routines                       *
- * ********************************************************************** */
-
-/* Note:
-   Other drivers use the macro "MIN" to calculate how much to copy.
-   This has the disadvantage that it will evaluate parts twice. That's
-   expensive when it's IO (and the compiler cannot optimize those away!).
-   Moreover, I'm not sure that you're race-free. 
-
-   I assign a value, and then only allow the value to decrease. This
-   is always safe. This makes the code a few lines longer, and you
-   know I'm dead against that, but I think it is required in this
-   case.  */
-
-static void sx_transmit_chars(struct sx_port *port)
-{
-	int c;
-	int tx_ip;
-	int txroom;
-
-	func_enter2();
-	sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
-			port, port->gs.xmit_cnt);
-
-	if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
-		return;
-	}
-
-	while (1) {
-		c = port->gs.xmit_cnt;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
-		tx_ip = sx_read_channel_byte(port, hi_txipos);
-
-		/* Took me 5 minutes to deduce this formula. 
-		   Luckily it is literally in the manual in section 6.5.4.3.5 */
-		txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
-				0xff;
-
-		/* Don't copy more bytes than there is room for in the buffer */
-		if (c > txroom)
-			c = txroom;
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
-
-		/* Don't copy past the end of the hardware transmit buffer */
-		if (c > 0x100 - tx_ip)
-			c = 0x100 - tx_ip;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
-
-		/* Don't copy pas the end of the source buffer */
-		if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
-			c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
-				c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
-
-		/* If for one reason or another, we can't copy more data, we're
-		   done! */
-		if (c == 0)
-			break;
-
-		memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
-			tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
-
-		/* Update the pointer in the card */
-		sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
-
-		/* Update the kernel buffer end */
-		port->gs.xmit_tail = (port->gs.xmit_tail + c) &
-				(SERIAL_XMIT_SIZE - 1);
-
-		/* This one last. (this is essential)
-		   It would allow others to start putting more data into the
-		   buffer! */
-		port->gs.xmit_cnt -= c;
-	}
-
-	if (port->gs.xmit_cnt == 0) {
-		sx_disable_tx_interrupts(port);
-	}
-
-	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
-		tty_wakeup(port->gs.port.tty);
-		sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
-				port->gs.wakeup_chars);
-	}
-
-	clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
-	func_exit();
-}
-
-/* Note the symmetry between receiving chars and transmitting them!
-   Note: The kernel should have implemented both a receive buffer and
-   a transmit buffer. */
-
-/* Inlined: Called only once. Remove the inline when you add another call */
-static inline void sx_receive_chars(struct sx_port *port)
-{
-	int c;
-	int rx_op;
-	struct tty_struct *tty;
-	int copied = 0;
-	unsigned char *rp;
-
-	func_enter2();
-	tty = port->gs.port.tty;
-	while (1) {
-		rx_op = sx_read_channel_byte(port, hi_rxopos);
-		c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
-
-		/* Don't copy past the end of the hardware receive buffer */
-		if (rx_op + c > 0x100)
-			c = 0x100 - rx_op;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
-		/* Don't copy more bytes than there is room for in the buffer */
-
-		c = tty_prepare_flip_string(tty, &rp, c);
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
-		/* If for one reason or another, we can't copy more data, we're done! */
-		if (c == 0)
-			break;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
-				"%d at %lx\n", c, read_sx_byte(port->board,
-					CHAN_OFFSET(port, hi_rxbuf) + rx_op),
-				CHAN_OFFSET(port, hi_rxbuf));
-		memcpy_fromio(rp, port->board->base +
-				CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
-
-		/* This one last. ( Not essential.)
-		   It allows the card to start putting more data into the
-		   buffer!
-		   Update the pointer in the card */
-		sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
-
-		copied += c;
-	}
-	if (copied) {
-		struct timeval tv;
-
-		do_gettimeofday(&tv);
-		sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
-				"chars): %d.%06d  (%d/%d)\n", port->line,
-				copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
-				tty->raw, tty->real_raw);
-
-		/* Tell the rest of the system the news. Great news. New
-		   characters! */
-		tty_flip_buffer_push(tty);
-		/*    tty_schedule_flip (tty); */
-	}
-
-	func_exit();
-}
-
-/* Inlined: it is called only once. Remove the inline if you add another 
-   call */
-static inline void sx_check_modem_signals(struct sx_port *port)
-{
-	int hi_state;
-	int c_dcd;
-
-	hi_state = sx_read_channel_byte(port, hi_state);
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
-			port->c_dcd, tty_port_carrier_raised(&port->gs.port));
-
-	if (hi_state & ST_BREAK) {
-		hi_state &= ~ST_BREAK;
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-		sx_write_channel_byte(port, hi_state, hi_state);
-		gs_got_break(&port->gs);
-	}
-	if (hi_state & ST_DCD) {
-		hi_state &= ~ST_DCD;
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
-		sx_write_channel_byte(port, hi_state, hi_state);
-		c_dcd = tty_port_carrier_raised(&port->gs.port);
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
-		if (c_dcd != port->c_dcd) {
-			port->c_dcd = c_dcd;
-			if (tty_port_carrier_raised(&port->gs.port)) {
-				/* DCD went UP */
-				if ((sx_read_channel_byte(port, hi_hstat) !=
-						HS_IDLE_CLOSED) &&
-						!(port->gs.port.tty->termios->
-							c_cflag & CLOCAL)) {
-					/* Are we blocking in open? */
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"active, unblocking open\n");
-					wake_up_interruptible(&port->gs.port.
-							open_wait);
-				} else {
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"raised. Ignoring.\n");
-				}
-			} else {
-				/* DCD went down! */
-				if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"dropped. hanging up....\n");
-					tty_hangup(port->gs.port.tty);
-				} else {
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"dropped. ignoring.\n");
-				}
-			}
-		} else {
-			sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
-				"DCD changed, but it didn't.\n");
-		}
-	}
-}
-
-/* This is what an interrupt routine should look like. 
- * Small, elegant, clear.
- */
-
-static irqreturn_t sx_interrupt(int irq, void *ptr)
-{
-	struct sx_board *board = ptr;
-	struct sx_port *port;
-	int i;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
-			board->irq);
-
-	/* AAargh! The order in which to do these things is essential and
-	   not trivial. 
-
-	   - Rate limit goes before "recursive". Otherwise a series of
-	   recursive calls will hang the machine in the interrupt routine.
-
-	   - hardware twiddling goes before "recursive". Otherwise when we
-	   poll the card, and a recursive interrupt happens, we won't
-	   ack the card, so it might keep on interrupting us. (especially
-	   level sensitive interrupt systems like PCI).
-
-	   - Rate limit goes before hardware twiddling. Otherwise we won't
-	   catch a card that has gone bonkers.
-
-	   - The "initialized" test goes after the hardware twiddling. Otherwise
-	   the card will stick us in the interrupt routine again.
-
-	   - The initialized test goes before recursive. 
-	 */
-
-#ifdef IRQ_RATE_LIMIT
-	/* Aaargh! I'm ashamed. This costs more lines-of-code than the
-	   actual interrupt routine!. (Well, used to when I wrote that
-	   comment) */
-	{
-		static int lastjif;
-		static int nintr = 0;
-
-		if (lastjif == jiffies) {
-			if (++nintr > IRQ_RATE_LIMIT) {
-				free_irq(board->irq, board);
-				printk(KERN_ERR "sx: Too many interrupts. "
-						"Turning off interrupt %d.\n",
-						board->irq);
-			}
-		} else {
-			lastjif = jiffies;
-			nintr = 0;
-		}
-	}
-#endif
-
-	if (board->irq == irq) {
-		/* Tell the card we've noticed the interrupt. */
-
-		sx_write_board_word(board, cc_int_pending, 0);
-		if (IS_SX_BOARD(board)) {
-			write_sx_byte(board, SX_RESET_IRQ, 1);
-		} else if (IS_EISA_BOARD(board)) {
-			inb(board->eisa_base + 0xc03);
-			write_sx_word(board, 8, 0);
-		} else {
-			write_sx_byte(board, SI2_ISA_INTCLEAR,
-					SI2_ISA_INTCLEAR_CLEAR);
-			write_sx_byte(board, SI2_ISA_INTCLEAR,
-					SI2_ISA_INTCLEAR_SET);
-		}
-	}
-
-	if (!sx_initialized)
-		return IRQ_HANDLED;
-	if (!(board->flags & SX_BOARD_INITIALIZED))
-		return IRQ_HANDLED;
-
-	if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
-		printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
-		return IRQ_HANDLED;
-	}
-
-	for (i = 0; i < board->nports; i++) {
-		port = &board->ports[i];
-		if (port->gs.port.flags & GS_ACTIVE) {
-			if (sx_read_channel_byte(port, hi_state)) {
-				sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
-						"modem signal change?... \n",i);
-				sx_check_modem_signals(port);
-			}
-			if (port->gs.xmit_cnt) {
-				sx_transmit_chars(port);
-			}
-			if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
-				sx_receive_chars(port);
-			}
-		}
-	}
-
-	clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
-
-	sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
-			board->irq);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-static void sx_pollfunc(unsigned long data)
-{
-	struct sx_board *board = (struct sx_board *)data;
-
-	func_enter();
-
-	sx_interrupt(0, board);
-
-	mod_timer(&board->timer, jiffies + sx_poll);
-	func_exit();
-}
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *              interface with the generic_serial driver                  *
- * ********************************************************************** */
-
-/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
-/* Hmm. Ok I figured it out. You don't.  */
-
-static void sx_disable_tx_interrupts(void *ptr)
-{
-	struct sx_port *port = ptr;
-	func_enter2();
-
-	port->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-static void sx_enable_tx_interrupts(void *ptr)
-{
-	struct sx_port *port = ptr;
-	int data_in_buffer;
-	func_enter2();
-
-	/* First transmit the characters that we're supposed to */
-	sx_transmit_chars(port);
-
-	/* The sx card will never interrupt us if we don't fill the buffer
-	   past 25%. So we keep considering interrupts off if that's the case. */
-	data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
-			  sx_read_channel_byte(port, hi_txopos)) & 0xff;
-
-	/* XXX Must be "HIGH_WATER" for SI card according to doc. */
-	if (data_in_buffer < LOW_WATER)
-		port->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-static void sx_disable_rx_interrupts(void *ptr)
-{
-	/*  struct sx_port *port = ptr; */
-	func_enter();
-
-	func_exit();
-}
-
-static void sx_enable_rx_interrupts(void *ptr)
-{
-	/*  struct sx_port *port = ptr; */
-	func_enter();
-
-	func_exit();
-}
-
-/* Jeez. Isn't this simple? */
-static int sx_carrier_raised(struct tty_port *port)
-{
-	struct sx_port *sp = container_of(port, struct sx_port, gs.port);
-	return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
-}
-
-/* Jeez. Isn't this simple? */
-static int sx_chars_in_buffer(void *ptr)
-{
-	struct sx_port *port = ptr;
-	func_enter2();
-
-	func_exit();
-	return ((sx_read_channel_byte(port, hi_txipos) -
-		 sx_read_channel_byte(port, hi_txopos)) & 0xff);
-}
-
-static void sx_shutdown_port(void *ptr)
-{
-	struct sx_port *port = ptr;
-
-	func_enter();
-
-	port->gs.port.flags &= ~GS_ACTIVE;
-	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
-		sx_setsignals(port, 0, 0);
-		sx_reconfigure_port(port);
-	}
-
-	func_exit();
-}
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *               interface with the rest of the system                    *
- * ********************************************************************** */
-
-static int sx_open(struct tty_struct *tty, struct file *filp)
-{
-	struct sx_port *port;
-	int retval, line;
-	unsigned long flags;
-
-	func_enter();
-
-	if (!sx_initialized) {
-		return -EIO;
-	}
-
-	line = tty->index;
-	sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
-			"np=%d)\n", task_pid_nr(current), line, tty,
-			current->signal->tty, sx_nports);
-
-	if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
-		return -ENODEV;
-
-	port = &sx_ports[line];
-	port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
-			    1 -> 0 transition. */
-
-	sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
-
-	spin_lock_irqsave(&port->gs.driver_lock, flags);
-
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	spin_unlock_irqrestore(&port->gs.driver_lock, flags);
-
-	sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
-
-	/*
-	 * Start up serial port
-	 */
-	retval = gs_init_port(&port->gs);
-	sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	port->gs.port.flags |= GS_ACTIVE;
-	if (port->gs.port.count <= 1)
-		sx_setsignals(port, 1, 1);
-
-#if 0
-	if (sx_debug & SX_DEBUG_OPEN)
-		my_hd(port, sizeof(*port));
-#else
-	if (sx_debug & SX_DEBUG_OPEN)
-		my_hd_io(port->board->base + port->ch_base, sizeof(*port));
-#endif
-
-	if (port->gs.port.count <= 1) {
-		if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
-			printk(KERN_ERR "sx: Card didn't respond to LOPEN "
-					"command.\n");
-			spin_lock_irqsave(&port->gs.driver_lock, flags);
-			port->gs.port.count--;
-			spin_unlock_irqrestore(&port->gs.driver_lock, flags);
-			return -EIO;
-		}
-	}
-
-	retval = gs_block_til_ready(port, filp);
-	sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
-			retval, port->gs.port.count);
-
-	if (retval) {
-/*
- * Don't lower gs.port.count here because sx_close() will be called later
- */
-
-		return retval;
-	}
-	/* tty->low_latency = 1; */
-
-	port->c_dcd = sx_carrier_raised(&port->gs.port);
-	sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
-
-	func_exit();
-	return 0;
-
-}
-
-static void sx_close(void *ptr)
-{
-	struct sx_port *port = ptr;
-	/* Give the port 5 seconds to close down. */
-	int to = 5 * HZ;
-
-	func_enter();
-
-	sx_setsignals(port, 0, 0);
-	sx_reconfigure_port(port);
-	sx_send_command(port, HS_CLOSE, 0, 0);
-
-	while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
-		if (msleep_interruptible(10))
-			break;
-	if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
-		if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
-				!= 1) {
-			printk(KERN_ERR "sx: sent the force_close command, but "
-					"card didn't react\n");
-		} else
-			sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
-					"command.\n");
-	}
-
-	sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
-			5 * HZ - to - 1, port->gs.port.count);
-
-	if (port->gs.port.count) {
-		sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
-				port->gs.port.count);
-		/*printk("%s SETTING port count to zero: %p count: %d\n",
-				__func__, port, port->gs.port.count);
-		port->gs.port.count = 0;*/
-	}
-
-	func_exit();
-}
-
-/* This is relatively thorough. But then again it is only 20 lines. */
-#define MARCHUP		for (i = min; i < max; i++)
-#define MARCHDOWN	for (i = max - 1; i >= min; i--)
-#define W0		write_sx_byte(board, i, 0x55)
-#define W1		write_sx_byte(board, i, 0xaa)
-#define R0		if (read_sx_byte(board, i) != 0x55) return 1
-#define R1		if (read_sx_byte(board, i) != 0xaa) return 1
-
-/* This memtest takes a human-noticable time. You normally only do it
-   once a boot, so I guess that it is worth it. */
-static int do_memtest(struct sx_board *board, int min, int max)
-{
-	int i;
-
-	/* This is a marchb. Theoretically, marchb catches much more than
-	   simpler tests. In practise, the longer test just catches more
-	   intermittent errors. -- REW
-	   (For the theory behind memory testing see: 
-	   Testing Semiconductor Memories by A.J. van de Goor.) */
-	MARCHUP {
-		W0;
-	}
-	MARCHUP {
-		R0;
-		W1;
-		R1;
-		W0;
-		R0;
-		W1;
-	}
-	MARCHUP {
-		R1;
-		W0;
-		W1;
-	}
-	MARCHDOWN {
-		R1;
-		W0;
-		W1;
-		W0;
-	}
-	MARCHDOWN {
-		R0;
-		W1;
-		W0;
-	}
-
-	return 0;
-}
-
-#undef MARCHUP
-#undef MARCHDOWN
-#undef W0
-#undef W1
-#undef R0
-#undef R1
-
-#define MARCHUP		for (i = min; i < max; i += 2)
-#define MARCHDOWN	for (i = max - 1; i >= min; i -= 2)
-#define W0		write_sx_word(board, i, 0x55aa)
-#define W1		write_sx_word(board, i, 0xaa55)
-#define R0		if (read_sx_word(board, i) != 0x55aa) return 1
-#define R1		if (read_sx_word(board, i) != 0xaa55) return 1
-
-#if 0
-/* This memtest takes a human-noticable time. You normally only do it
-   once a boot, so I guess that it is worth it. */
-static int do_memtest_w(struct sx_board *board, int min, int max)
-{
-	int i;
-
-	MARCHUP {
-		W0;
-	}
-	MARCHUP {
-		R0;
-		W1;
-		R1;
-		W0;
-		R0;
-		W1;
-	}
-	MARCHUP {
-		R1;
-		W0;
-		W1;
-	}
-	MARCHDOWN {
-		R1;
-		W0;
-		W1;
-		W0;
-	}
-	MARCHDOWN {
-		R0;
-		W1;
-		W0;
-	}
-
-	return 0;
-}
-#endif
-
-static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
-							unsigned long arg)
-{
-	long rc = 0;
-	int __user *descr = (int __user *)arg;
-	int i;
-	static struct sx_board *board = NULL;
-	int nbytes, offset;
-	unsigned long data;
-	char *tmp;
-
-	func_enter();
-
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
-	tty_lock();
-
-	sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
-
-	if (!board)
-		board = &boards[0];
-	if (board->flags & SX_BOARD_PRESENT) {
-		sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
-				board->flags);
-	} else {
-		sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
-				board->flags);
-		for (i = 0; i < SX_NBOARDS; i++)
-			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
-		sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
-		rc = -EIO;
-		goto out;
-	}
-
-	switch (cmd) {
-	case SXIO_SET_BOARD:
-		sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
-		rc = -EIO;
-		if (arg >= SX_NBOARDS)
-			break;
-		sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
-		if (!(boards[arg].flags & SX_BOARD_PRESENT))
-			break;
-		sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
-		board = &boards[arg];
-		rc = 0;
-		/* FIXME: And this does ... nothing?? */
-		break;
-	case SXIO_GET_TYPE:
-		rc = -ENOENT;	/* If we manage to miss one, return error. */
-		if (IS_SX_BOARD(board))
-			rc = SX_TYPE_SX;
-		if (IS_CF_BOARD(board))
-			rc = SX_TYPE_CF;
-		if (IS_SI_BOARD(board))
-			rc = SX_TYPE_SI;
-		if (IS_SI1_BOARD(board))
-			rc = SX_TYPE_SI;
-		if (IS_EISA_BOARD(board))
-			rc = SX_TYPE_SI;
-		sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
-		break;
-	case SXIO_DO_RAMTEST:
-		if (sx_initialized) {	/* Already initialized: better not ramtest the board.  */
-			rc = -EPERM;
-			break;
-		}
-		if (IS_SX_BOARD(board)) {
-			rc = do_memtest(board, 0, 0x7000);
-			if (!rc)
-				rc = do_memtest(board, 0, 0x7000);
-			/*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
-		} else {
-			rc = do_memtest(board, 0, 0x7ff8);
-			/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
-		}
-		sx_dprintk(SX_DEBUG_FIRMWARE,
-				"returning memtest result= %ld\n", rc);
-		break;
-	case SXIO_DOWNLOAD:
-		if (sx_initialized) {/* Already initialized */
-			rc = -EEXIST;
-			break;
-		}
-		if (!sx_reset(board)) {
-			rc = -EIO;
-			break;
-		}
-		sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-		tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
-		if (!tmp) {
-			rc = -ENOMEM;
-			break;
-		}
-		/* FIXME: check returns */
-		get_user(nbytes, descr++);
-		get_user(offset, descr++);
-		get_user(data, descr++);
-		while (nbytes && data) {
-			for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
-				if (copy_from_user(tmp, (char __user *)data + i,
-						(i + SX_CHUNK_SIZE > nbytes) ?
-						nbytes - i : SX_CHUNK_SIZE)) {
-					kfree(tmp);
-					rc = -EFAULT;
-					goto out;
-				}
-				memcpy_toio(board->base2 + offset + i, tmp,
-						(i + SX_CHUNK_SIZE > nbytes) ?
-						nbytes - i : SX_CHUNK_SIZE);
-			}
-
-			get_user(nbytes, descr++);
-			get_user(offset, descr++);
-			get_user(data, descr++);
-		}
-		kfree(tmp);
-		sx_nports += sx_init_board(board);
-		rc = sx_nports;
-		break;
-	case SXIO_INIT:
-		if (sx_initialized) {	/* Already initialized */
-			rc = -EEXIST;
-			break;
-		}
-		/* This is not allowed until all boards are initialized... */
-		for (i = 0; i < SX_NBOARDS; i++) {
-			if ((boards[i].flags & SX_BOARD_PRESENT) &&
-				!(boards[i].flags & SX_BOARD_INITIALIZED)) {
-				rc = -EIO;
-				break;
-			}
-		}
-		for (i = 0; i < SX_NBOARDS; i++)
-			if (!(boards[i].flags & SX_BOARD_PRESENT))
-				break;
-
-		sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
-				"%d channels, first board: %d ports\n",
-				i, sx_nports, boards[0].nports);
-		rc = sx_init_portstructs(i, sx_nports);
-		sx_init_drivers();
-		if (rc >= 0)
-			sx_initialized++;
-		break;
-	case SXIO_SETDEBUG:
-		sx_debug = arg;
-		break;
-	case SXIO_GETDEBUG:
-		rc = sx_debug;
-		break;
-	case SXIO_GETGSDEBUG:
-	case SXIO_SETGSDEBUG:
-		rc = -EINVAL;
-		break;
-	case SXIO_GETNPORTS:
-		rc = sx_nports;
-		break;
-	default:
-		rc = -ENOTTY;
-		break;
-	}
-out:
-	tty_unlock();
-	func_exit();
-	return rc;
-}
-
-static int sx_break(struct tty_struct *tty, int flag)
-{
-	struct sx_port *port = tty->driver_data;
-	int rv;
-
-	func_enter();
-	tty_lock();
-
-	if (flag)
-		rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
-	else
-		rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
-	if (rv != 1)
-		printk(KERN_ERR "sx: couldn't send break (%x).\n",
-			read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
-	tty_unlock();
-	func_exit();
-	return 0;
-}
-
-static int sx_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct sx_port *port = tty->driver_data;
-	return sx_getsignals(port);
-}
-
-static int sx_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct sx_port *port = tty->driver_data;
-	int rts = -1, dtr = -1;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	sx_setsignals(port, dtr, rts);
-	sx_reconfigure_port(port);
-	return 0;
-}
-
-static int sx_ioctl(struct tty_struct *tty, struct file *filp,
-		unsigned int cmd, unsigned long arg)
-{
-	int rc;
-	struct sx_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	/* func_enter2(); */
-
-	rc = 0;
-	tty_lock();
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = gs_getserial(&port->gs, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = gs_setserial(&port->gs, argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	tty_unlock();
-
-	/* func_exit(); */
-	return rc;
-}
-
-/* The throttle/unthrottle scheme for the Specialix card is different
- * from other drivers and deserves some explanation. 
- * The Specialix hardware takes care of XON/XOFF
- * and CTS/RTS flow control itself.  This means that all we have to
- * do when signalled by the upper tty layer to throttle/unthrottle is
- * to make a note of it here.  When we come to read characters from the
- * rx buffers on the card (sx_receive_chars()) we look to see if the
- * upper layer can accept more (as noted here in sx_rx_throt[]). 
- * If it can't we simply don't remove chars from the cards buffer. 
- * When the tty layer can accept chars, we again note that here and when
- * sx_receive_chars() is called it will remove them from the cards buffer.
- * The card will notice that a ports buffer has drained below some low
- * water mark and will unflow control the line itself, using whatever
- * flow control scheme is in use for that port. -- Simon Allen
- */
-
-static void sx_throttle(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-
-	func_enter2();
-	/* If the port is using any type of input flow
-	 * control then throttle the port.
-	 */
-	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-		port->gs.port.flags |= SX_RX_THROTTLE;
-	}
-	func_exit();
-}
-
-static void sx_unthrottle(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-
-	func_enter2();
-	/* Always unthrottle even if flow control is not enabled on
-	 * this port in case we disabled flow control while the port
-	 * was throttled
-	 */
-	port->gs.port.flags &= ~SX_RX_THROTTLE;
-	func_exit();
-	return;
-}
-
-/* ********************************************************************** *
- *                    Here are the initialization routines.               *
- * ********************************************************************** */
-
-static int sx_init_board(struct sx_board *board)
-{
-	int addr;
-	int chans;
-	int type;
-
-	func_enter();
-
-	/* This is preceded by downloading the download code. */
-
-	board->flags |= SX_BOARD_INITIALIZED;
-
-	if (read_sx_byte(board, 0))
-		/* CF boards may need this. */
-		write_sx_byte(board, 0, 0);
-
-	/* This resets the processor again, to make sure it didn't do any
-	   foolish things while we were downloading the image */
-	if (!sx_reset(board))
-		return 0;
-
-	sx_start_board(board);
-	udelay(10);
-	if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
-		printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
-		return 0;
-	}
-
-	/* Ok. So now the processor on the card is running. It gathered
-	   some info for us... */
-	sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
-	if (sx_debug & SX_DEBUG_INIT)
-		my_hd_io(board->base, 0x10);
-	sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
-	if (sx_debug & SX_DEBUG_INIT)
-		my_hd_io(board->base + 0x80, 0x30);
-
-	sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
-			"V%x.%02x,\n",
-			read_sx_byte(board, 0), read_sx_byte(board, 1),
-			read_sx_byte(board, 5), read_sx_byte(board, 4));
-
-	if (read_sx_byte(board, 0) == 0xff) {
-		printk(KERN_INFO "sx: No modules found. Sorry.\n");
-		board->nports = 0;
-		return 0;
-	}
-
-	chans = 0;
-
-	if (IS_SX_BOARD(board)) {
-		sx_write_board_word(board, cc_int_count, sx_maxints);
-	} else {
-		if (sx_maxints)
-			sx_write_board_word(board, cc_int_count,
-					SI_PROCESSOR_CLOCK / 8 / sx_maxints);
-	}
-
-	/* grab the first module type... */
-	/* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
-	board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
-				mc_chip));
-
-	/* XXX byteorder */
-	for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
-		type = sx_read_module_byte(board, addr, mc_chip);
-		sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
-				addr, read_sx_byte(board, addr + 2));
-
-		chans += sx_read_module_byte(board, addr, mc_type);
-
-		sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
-				"panels\n",
-				mod_type_s(type),
-				pan_type_s(sx_read_module_byte(board, addr,
-						mc_mods) & 0xf),
-				pan_type_s(sx_read_module_byte(board, addr,
-						mc_mods) >> 4));
-
-		sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
-			"version: %x\n",
-			sx_read_module_byte(board, addr, mc_rev1),
-			sx_read_module_byte(board, addr, mc_rev2),
-			sx_read_module_byte(board, addr, mc_mtaasic_rev));
-
-		/* The following combinations are illegal: It should theoretically
-		   work, but timing problems make the bus HANG. */
-
-		if (mod_compat_type(type) != board->ta_type) {
-			printk(KERN_ERR "sx: This is an invalid "
-				"configuration.\nDon't mix TA/MTA/SXDC on the "
-				"same hostadapter.\n");
-			chans = 0;
-			break;
-		}
-		if ((IS_EISA_BOARD(board) ||
-				IS_SI_BOARD(board)) &&
-				(mod_compat_type(type) == 4)) {
-			printk(KERN_ERR	"sx: This is an invalid "
-				"configuration.\nDon't use SXDCs on an SI/XIO "
-				"adapter.\n");
-			chans = 0;
-			break;
-		}
-#if 0				/* Problem fixed: firmware 3.05 */
-		if (IS_SX_BOARD(board) && (type == TA8)) {
-			/* There are some issues with the firmware and the DCD/RTS
-			   lines. It might work if you tie them together or something.
-			   It might also work if you get a newer sx_firmware.   Therefore
-			   this is just a warning. */
-			printk(KERN_WARNING
-			       "sx: The SX host doesn't work too well "
-			       "with the TA8 adapters.\nSpecialix is working on it.\n");
-		}
-#endif
-	}
-
-	if (chans) {
-		if (board->irq > 0) {
-			/* fixed irq, probably PCI */
-			if (sx_irqmask & (1 << board->irq)) {	/* may we use this irq? */
-				if (request_irq(board->irq, sx_interrupt,
-						IRQF_SHARED | IRQF_DISABLED,
-						"sx", board)) {
-					printk(KERN_ERR "sx: Cannot allocate "
-						"irq %d.\n", board->irq);
-					board->irq = 0;
-				}
-			} else
-				board->irq = 0;
-		} else if (board->irq < 0 && sx_irqmask) {
-			/* auto-allocate irq */
-			int irqnr;
-			int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
-					SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
-			for (irqnr = 15; irqnr > 0; irqnr--)
-				if (irqmask & (1 << irqnr))
-					if (!request_irq(irqnr, sx_interrupt,
-						IRQF_SHARED | IRQF_DISABLED,
-						"sx", board))
-						break;
-			if (!irqnr)
-				printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
-			board->irq = irqnr;
-		} else
-			board->irq = 0;
-
-		if (board->irq) {
-			/* Found a valid interrupt, start up interrupts! */
-			sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
-					board->irq);
-			sx_start_interrupts(board);
-			board->poll = sx_slowpoll;
-			board->flags |= SX_IRQ_ALLOCATED;
-		} else {
-			/* no irq: setup board for polled operation */
-			board->poll = sx_poll;
-			sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
-					board->poll);
-		}
-
-		/* The timer should be initialized anyway: That way we can
-		   safely del_timer it when the module is unloaded. */
-		setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
-
-		if (board->poll)
-			mod_timer(&board->timer, jiffies + board->poll);
-	} else {
-		board->irq = 0;
-	}
-
-	board->nports = chans;
-	sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
-
-	func_exit();
-	return chans;
-}
-
-static void __devinit printheader(void)
-{
-	static int header_printed;
-
-	if (!header_printed) {
-		printk(KERN_INFO "Specialix SX driver "
-			"(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
-		printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
-		header_printed = 1;
-	}
-}
-
-static int __devinit probe_sx(struct sx_board *board)
-{
-	struct vpd_prom vpdp;
-	char *p;
-	int i;
-
-	func_enter();
-
-	if (!IS_CF_BOARD(board)) {
-		sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
-				board->base + SX_VPD_ROM);
-
-		if (sx_debug & SX_DEBUG_PROBE)
-			my_hd_io(board->base + SX_VPD_ROM, 0x40);
-
-		p = (char *)&vpdp;
-		for (i = 0; i < sizeof(struct vpd_prom); i++)
-			*p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
-
-		if (sx_debug & SX_DEBUG_PROBE)
-			my_hd(&vpdp, 0x20);
-
-		sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
-
-		if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
-			sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
-					"'%s'\n", vpdp.identifier);
-			return 0;
-		}
-	}
-
-	printheader();
-
-	if (!IS_CF_BOARD(board)) {
-		printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
-			board->hw_base);
-		printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
-				"uniq ID:%08x, ",
-				vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
-		printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
-
-		if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
-				SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
-				SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
-			/* This might be a bit harsh. This was the primary
-			   reason the SX/ISA card didn't work at first... */
-			printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
-					"card. Sorry: giving up.\n");
-			return (0);
-		}
-
-		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
-				SX_ISA_UNIQUEID1) {
-			if (((unsigned long)board->hw_base) & 0x8000) {
-				printk(KERN_WARNING "sx: Warning: There may be "
-					"hardware problems with the card at "
-					"%lx.\n", board->hw_base);
-				printk(KERN_WARNING "sx: Read sx.txt for more "
-						"info.\n");
-			}
-		}
-	}
-
-	board->nports = -1;
-
-	/* This resets the processor, and keeps it off the bus. */
-	if (!sx_reset(board))
-		return 0;
-	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-	func_exit();
-	return 1;
-}
-
-#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
-
-/* Specialix probes for this card at 32k increments from 640k to 16M.
-   I consider machines with less than 16M unlikely nowadays, so I'm
-   not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
-   card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 
-   0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
-
-static int __devinit probe_si(struct sx_board *board)
-{
-	int i;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
-		"%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
-
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
-
-	if (!IS_EISA_BOARD(board)) {
-		if (IS_SI1_BOARD(board)) {
-			for (i = 0; i < 8; i++) {
-				write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
-			}
-		}
-		for (i = 0; i < 8; i++) {
-			if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
-					!= i) {
-				func_exit();
-				return 0;
-			}
-		}
-	}
-
-	/* Now we're pretty much convinced that there is an SI board here, 
-	   but to prevent trouble, we'd better double check that we don't
-	   have an SI1 board when we're probing for an SI2 board.... */
-
-	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
-	if (IS_SI1_BOARD(board)) {
-		/* This should be an SI1 board, which has this
-		   location writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
-			func_exit();
-			return 0;
-		}
-	} else {
-		/* This should be an SI2 board, which has the bottom
-		   3 bits non-writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
-			func_exit();
-			return 0;
-		}
-	}
-
-	/* Now we're pretty much convinced that there is an SI board here, 
-	   but to prevent trouble, we'd better double check that we don't
-	   have an SI1 board when we're probing for an SI2 board.... */
-
-	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
-	if (IS_SI1_BOARD(board)) {
-		/* This should be an SI1 board, which has this
-		   location writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
-			func_exit();
-			return 0;
-		}
-	} else {
-		/* This should be an SI2 board, which has the bottom
-		   3 bits non-writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
-			func_exit();
-			return 0;
-		}
-	}
-
-	printheader();
-
-	printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
-	/* Compared to the SX boards, it is a complete guess as to what
-	   this card is up to... */
-
-	board->nports = -1;
-
-	/* This resets the processor, and keeps it off the bus. */
-	if (!sx_reset(board))
-		return 0;
-	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-	func_exit();
-	return 1;
-}
-#endif
-
-static const struct tty_operations sx_ops = {
-	.break_ctl = sx_break,
-	.open = sx_open,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = sx_ioctl,
-	.throttle = sx_throttle,
-	.unthrottle = sx_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-	.tiocmget = sx_tiocmget,
-	.tiocmset = sx_tiocmset,
-};
-
-static const struct tty_port_operations sx_port_ops = {
-	.carrier_raised = sx_carrier_raised,
-};
-
-static int sx_init_drivers(void)
-{
-	int error;
-
-	func_enter();
-
-	sx_driver = alloc_tty_driver(sx_nports);
-	if (!sx_driver)
-		return 1;
-	sx_driver->owner = THIS_MODULE;
-	sx_driver->driver_name = "specialix_sx";
-	sx_driver->name = "ttyX";
-	sx_driver->major = SX_NORMAL_MAJOR;
-	sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	sx_driver->subtype = SERIAL_TYPE_NORMAL;
-	sx_driver->init_termios = tty_std_termios;
-	sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	sx_driver->init_termios.c_ispeed = 9600;
-	sx_driver->init_termios.c_ospeed = 9600;
-	sx_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(sx_driver, &sx_ops);
-
-	if ((error = tty_register_driver(sx_driver))) {
-		put_tty_driver(sx_driver);
-		printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
-			error);
-		return 1;
-	}
-	func_exit();
-	return 0;
-}
-
-static int sx_init_portstructs(int nboards, int nports)
-{
-	struct sx_board *board;
-	struct sx_port *port;
-	int i, j;
-	int addr, chans;
-	int portno;
-
-	func_enter();
-
-	/* Many drivers statically allocate the maximum number of ports
-	   There is no reason not to allocate them dynamically.
-	   Is there? -- REW */
-	sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
-	if (!sx_ports)
-		return -ENOMEM;
-
-	port = sx_ports;
-	for (i = 0; i < nboards; i++) {
-		board = &boards[i];
-		board->ports = port;
-		for (j = 0; j < boards[i].nports; j++) {
-			sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
-			tty_port_init(&port->gs.port);
-			port->gs.port.ops = &sx_port_ops;
-			port->gs.magic = SX_MAGIC;
-			port->gs.close_delay = HZ / 2;
-			port->gs.closing_wait = 30 * HZ;
-			port->board = board;
-			port->gs.rd = &sx_real_driver;
-#ifdef NEW_WRITE_LOCKING
-			port->gs.port_write_mutex = MUTEX;
-#endif
-			spin_lock_init(&port->gs.driver_lock);
-			/*
-			 * Initializing wait queue
-			 */
-			port++;
-		}
-	}
-
-	port = sx_ports;
-	portno = 0;
-	for (i = 0; i < nboards; i++) {
-		board = &boards[i];
-		board->port_base = portno;
-		/* Possibly the configuration was rejected. */
-		sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
-				board->nports);
-		if (board->nports <= 0)
-			continue;
-		/* XXX byteorder ?? */
-		for (addr = 0x80; addr != 0;
-				addr = read_sx_word(board, addr) & 0x7fff) {
-			chans = sx_read_module_byte(board, addr, mc_type);
-			sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
-					"channels\n", addr, chans);
-			sx_dprintk(SX_DEBUG_PROBE, "Port at");
-			for (j = 0; j < chans; j++) {
-				/* The "sx-way" is the way it SHOULD be done.
-				   That way in the future, the firmware may for
-				   example pack the structures a bit more
-				   efficient. Neil tells me it isn't going to
-				   happen anytime soon though. */
-				if (IS_SX_BOARD(board))
-					port->ch_base = sx_read_module_word(
-							board, addr + j * 2,
-							mc_chan_pointer);
-				else
-					port->ch_base = addr + 0x100 + 0x300 *j;
-
-				sx_dprintk(SX_DEBUG_PROBE, " %x",
-						port->ch_base);
-				port->line = portno++;
-				port++;
-			}
-			sx_dprintk(SX_DEBUG_PROBE, "\n");
-		}
-		/* This has to be done earlier. */
-		/* board->flags |= SX_BOARD_INITIALIZED; */
-	}
-
-	func_exit();
-	return 0;
-}
-
-static unsigned int sx_find_free_board(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < SX_NBOARDS; i++)
-		if (!(boards[i].flags & SX_BOARD_PRESENT))
-			break;
-
-	return i;
-}
-
-static void __exit sx_release_drivers(void)
-{
-	func_enter();
-	tty_unregister_driver(sx_driver);
-	put_tty_driver(sx_driver);
-	func_exit();
-}
-
-static void __devexit sx_remove_card(struct sx_board *board,
-		struct pci_dev *pdev)
-{
-	if (board->flags & SX_BOARD_INITIALIZED) {
-		/* The board should stop messing with us. (actually I mean the
-		   interrupt) */
-		sx_reset(board);
-		if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
-			free_irq(board->irq, board);
-
-		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer(&board->timer);
-		if (pdev) {
-#ifdef CONFIG_PCI
-			iounmap(board->base2);
-			pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
-#endif
-		} else {
-			iounmap(board->base);
-			release_region(board->hw_base, board->hw_len);
-		}
-
-		board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
-	}
-}
-
-#ifdef CONFIG_EISA
-
-static int __devinit sx_eisa_probe(struct device *dev)
-{
-	struct eisa_device *edev = to_eisa_device(dev);
-	struct sx_board *board;
-	unsigned long eisa_slot = edev->base_addr;
-	unsigned int i;
-	int retval = -EIO;
-
-	mutex_lock(&sx_boards_lock);
-	i = sx_find_free_board();
-	if (i == SX_NBOARDS) {
-		mutex_unlock(&sx_boards_lock);
-		goto err;
-	}
-	board = &boards[i];
-	board->flags |= SX_BOARD_PRESENT;
-	mutex_unlock(&sx_boards_lock);
-
-	dev_info(dev, "XIO : Signature found in EISA slot %lu, "
-		 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
-		 eisa_slot >> 12,
-		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
-		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
-
-	board->eisa_base = eisa_slot;
-	board->flags &= ~SX_BOARD_TYPE;
-	board->flags |= SI_EISA_BOARD;
-
-	board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
-			  inb(eisa_slot + 0xc00)) << 16;
-	board->hw_len = SI2_EISA_WINDOW_LEN;
-	if (!request_region(board->hw_base, board->hw_len, "sx")) {
-		dev_err(dev, "can't request region\n");
-		goto err_flag;
-	}
-	board->base2 =
-	board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
-	if (!board->base) {
-		dev_err(dev, "can't remap memory\n");
-		goto err_reg;
-	}
-
-	sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
-	sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
-	board->irq = inb(eisa_slot + 0xc02) >> 4;
-	sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
-
-	if (!probe_si(board))
-		goto err_unmap;
-
-	dev_set_drvdata(dev, board);
-
-	return 0;
-err_unmap:
-	iounmap(board->base);
-err_reg:
-	release_region(board->hw_base, board->hw_len);
-err_flag:
-	board->flags &= ~SX_BOARD_PRESENT;
-err:
-	return retval;
-}
-
-static int __devexit sx_eisa_remove(struct device *dev)
-{
-	struct sx_board *board = dev_get_drvdata(dev);
-
-	sx_remove_card(board, NULL);
-
-	return 0;
-}
-
-static struct eisa_device_id sx_eisa_tbl[] = {
-	{ "SLX" },
-	{ "" }
-};
-
-MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
-
-static struct eisa_driver sx_eisadriver = {
-	.id_table = sx_eisa_tbl,
-	.driver = {
-		.name = "sx",
-		.probe = sx_eisa_probe,
-		.remove = __devexit_p(sx_eisa_remove),
-	}
-};
-
-#endif
-
-#ifdef CONFIG_PCI
- /******************************************************** 
- * Setting bit 17 in the CNTRL register of the PLX 9050  * 
- * chip forces a retry on writes while a read is pending.*
- * This is to prevent the card locking up on Intel Xeon  *
- * multiprocessor systems with the NX chipset.    -- NV  *
- ********************************************************/
-
-/* Newer cards are produced with this bit set from the configuration
-   EEprom.  As the bit is read/write for the CPU, we can fix it here,
-   if we detect that it isn't set correctly. -- REW */
-
-static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
-{
-	unsigned int hwbase;
-	void __iomem *rebase;
-	unsigned int t;
-
-#define CNTRL_REG_OFFSET	0x50
-#define CNTRL_REG_GOODVALUE	0x18260000
-
-	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
-	hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
-	rebase = ioremap_nocache(hwbase, 0x80);
-	t = readl(rebase + CNTRL_REG_OFFSET);
-	if (t != CNTRL_REG_GOODVALUE) {
-		printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
-			"%08x\n", t, CNTRL_REG_GOODVALUE);
-		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
-	}
-	iounmap(rebase);
-}
-#endif
-
-static int __devinit sx_pci_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-#ifdef CONFIG_PCI
-	struct sx_board *board;
-	unsigned int i, reg;
-	int retval = -EIO;
-
-	mutex_lock(&sx_boards_lock);
-	i = sx_find_free_board();
-	if (i == SX_NBOARDS) {
-		mutex_unlock(&sx_boards_lock);
-		goto err;
-	}
-	board = &boards[i];
-	board->flags |= SX_BOARD_PRESENT;
-	mutex_unlock(&sx_boards_lock);
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err_flag;
-
-	board->flags &= ~SX_BOARD_TYPE;
-	board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
-		SX_CFPCI_BOARD;
-
-	/* CF boards use base address 3.... */
-	reg = IS_CF_BOARD(board) ? 3 : 2;
-	retval = pci_request_region(pdev, reg, "sx");
-	if (retval) {
-		dev_err(&pdev->dev, "can't request region\n");
-		goto err_flag;
-	}
-	board->hw_base = pci_resource_start(pdev, reg);
-	board->base2 =
-	board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
-	if (!board->base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		goto err_reg;
-	}
-
-	/* Most of the stuff on the CF board is offset by 0x18000 ....  */
-	if (IS_CF_BOARD(board))
-		board->base += 0x18000;
-
-	board->irq = pdev->irq;
-
-	dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
-		 board->irq, board->flags);
-
-	if (!probe_sx(board)) {
-		retval = -EIO;
-		goto err_unmap;
-	}
-
-	fix_sx_pci(pdev, board);
-
-	pci_set_drvdata(pdev, board);
-
-	return 0;
-err_unmap:
-	iounmap(board->base2);
-err_reg:
-	pci_release_region(pdev, reg);
-err_flag:
-	board->flags &= ~SX_BOARD_PRESENT;
-err:
-	return retval;
-#else
-	return -ENODEV;
-#endif
-}
-
-static void __devexit sx_pci_remove(struct pci_dev *pdev)
-{
-	struct sx_board *board = pci_get_drvdata(pdev);
-
-	sx_remove_card(board, pdev);
-}
-
-/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
-   its because the standard requires it. So check for SUBVENDOR_ID. */
-static struct pci_device_id sx_pci_tbl[] = {
-	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
-	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
-
-static struct pci_driver sx_pcidriver = {
-	.name = "sx",
-	.id_table = sx_pci_tbl,
-	.probe = sx_pci_probe,
-	.remove = __devexit_p(sx_pci_remove)
-};
-
-static int __init sx_init(void)
-{
-#ifdef CONFIG_EISA
-	int retval1;
-#endif
-#ifdef CONFIG_ISA
-	struct sx_board *board;
-	unsigned int i;
-#endif
-	unsigned int found = 0;
-	int retval;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
-			sx_debug);
-	if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
-		printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
-				"value. Assuming -1.\n(%p)\n", &sx_debug);
-		sx_debug = -1;
-	}
-
-	if (misc_register(&sx_fw_device) < 0) {
-		printk(KERN_ERR "SX: Unable to register firmware loader "
-				"driver.\n");
-		return -EIO;
-	}
-#ifdef CONFIG_ISA
-	for (i = 0; i < NR_SX_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = sx_probe_addrs[i];
-		board->hw_len = SX_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_sx_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SX_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_sx(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_sx_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-
-	for (i = 0; i < NR_SI_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = si_probe_addrs[i];
-		board->hw_len = SI2_ISA_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_si_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SI_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_si(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_si_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-	for (i = 0; i < NR_SI1_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = si1_probe_addrs[i];
-		board->hw_len = SI1_ISA_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_si1_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SI1_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_si(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_si1_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-#endif
-#ifdef CONFIG_EISA
-	retval1 = eisa_driver_register(&sx_eisadriver);
-#endif
-	retval = pci_register_driver(&sx_pcidriver);
-
-	if (found) {
-		printk(KERN_INFO "sx: total of %d boards detected.\n", found);
-		retval = 0;
-	} else if (retval) {
-#ifdef CONFIG_EISA
-		retval = retval1;
-		if (retval1)
-#endif
-			misc_deregister(&sx_fw_device);
-	}
-
-	func_exit();
-	return retval;
-}
-
-static void __exit sx_exit(void)
-{
-	int i;
-
-	func_enter();
-#ifdef CONFIG_EISA
-	eisa_driver_unregister(&sx_eisadriver);
-#endif
-	pci_unregister_driver(&sx_pcidriver);
-
-	for (i = 0; i < SX_NBOARDS; i++)
-		sx_remove_card(&boards[i], NULL);
-
-	if (misc_deregister(&sx_fw_device) < 0) {
-		printk(KERN_INFO "sx: couldn't deregister firmware loader "
-				"device\n");
-	}
-	sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
-			sx_initialized);
-	if (sx_initialized)
-		sx_release_drivers();
-
-	kfree(sx_ports);
-	func_exit();
-}
-
-module_init(sx_init);
-module_exit(sx_exit);
diff --git a/drivers/char/sx.h b/drivers/char/sx.h
deleted file mode 100644
index 87c2def..0000000
--- a/drivers/char/sx.h
+++ /dev/null
@@ -1,201 +0,0 @@
-
-/*
- *  sx.h
- *
- *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
- *
- *  SX serial driver.
- *  -- Supports SI, XIO and SX host cards. 
- *  -- Supports TAs, MTAs and SXDCs.
- *
- *  Version 1.3 -- March, 1999. 
- * 
- */
-
-#define SX_NBOARDS        4
-#define SX_PORTSPERBOARD 32
-#define SX_NPORTS        (SX_NBOARDS * SX_PORTSPERBOARD)
-
-#ifdef __KERNEL__
-
-#define SX_MAGIC 0x12345678
-
-struct sx_port {
-  struct gs_port          gs;
-  struct wait_queue       *shutdown_wait;
-  int                     ch_base;
-  int                     c_dcd;
-  struct sx_board         *board;
-  int                     line;
-  unsigned long           locks;
-};
-
-struct sx_board {
-  int magic;
-  void __iomem *base;
-  void __iomem *base2;
-  unsigned long hw_base;
-  resource_size_t hw_len;
-  int eisa_base;
-  int port_base; /* Number of the first port */
-  struct sx_port *ports;
-  int nports;
-  int flags;
-  int irq;
-  int poll;
-  int ta_type;
-  struct timer_list       timer;
-  unsigned long           locks;
-};
-
-struct vpd_prom {
-  unsigned short id;
-  char hwrev;
-  char hwass;
-  int uniqid;
-  char myear;
-  char mweek;
-  char hw_feature[5];
-  char oem_id;
-  char identifier[16];
-};
-
-#ifndef MOD_RS232DB25MALE
-#define MOD_RS232DB25MALE 0x0a
-#endif
-
-#define SI_ISA_BOARD         0x00000001
-#define SX_ISA_BOARD         0x00000002
-#define SX_PCI_BOARD         0x00000004
-#define SX_CFPCI_BOARD       0x00000008
-#define SX_CFISA_BOARD       0x00000010
-#define SI_EISA_BOARD        0x00000020
-#define SI1_ISA_BOARD        0x00000040
-
-#define SX_BOARD_PRESENT     0x00001000
-#define SX_BOARD_INITIALIZED 0x00002000
-#define SX_IRQ_ALLOCATED     0x00004000
-
-#define SX_BOARD_TYPE        0x000000ff
-
-#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \
-                                            SX_ISA_BOARD | SX_CFISA_BOARD))
-
-#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
-#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD)
-
-#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
-
-#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
-
-/* The SI processor clock is required to calculate the cc_int_count register
-   value for the SI cards. */
-#define SI_PROCESSOR_CLOCK 25000000
-
-
-/* port flags */
-/* Make sure these don't clash with gs flags or async flags */
-#define SX_RX_THROTTLE        0x0000001
-
-
-
-#define SX_PORT_TRANSMIT_LOCK  0
-#define SX_BOARD_INTR_LOCK     0
-
-
-
-/* Debug flags. Add these together to get more debug info. */
-
-#define SX_DEBUG_OPEN          0x00000001
-#define SX_DEBUG_SETTING       0x00000002
-#define SX_DEBUG_FLOW          0x00000004
-#define SX_DEBUG_MODEMSIGNALS  0x00000008
-#define SX_DEBUG_TERMIOS       0x00000010
-#define SX_DEBUG_TRANSMIT      0x00000020
-#define SX_DEBUG_RECEIVE       0x00000040
-#define SX_DEBUG_INTERRUPTS    0x00000080
-#define SX_DEBUG_PROBE         0x00000100
-#define SX_DEBUG_INIT          0x00000200
-#define SX_DEBUG_CLEANUP       0x00000400
-#define SX_DEBUG_CLOSE         0x00000800
-#define SX_DEBUG_FIRMWARE      0x00001000
-#define SX_DEBUG_MEMTEST       0x00002000
-
-#define SX_DEBUG_ALL           0xffffffff
-
-
-#define O_OTHER(tty)    \
-      ((O_OLCUC(tty))  ||\
-      (O_ONLCR(tty))   ||\
-      (O_OCRNL(tty))   ||\
-      (O_ONOCR(tty))   ||\
-      (O_ONLRET(tty))  ||\
-      (O_OFILL(tty))   ||\
-      (O_OFDEL(tty))   ||\
-      (O_NLDLY(tty))   ||\
-      (O_CRDLY(tty))   ||\
-      (O_TABDLY(tty))  ||\
-      (O_BSDLY(tty))   ||\
-      (O_VTDLY(tty))   ||\
-      (O_FFDLY(tty)))
-
-/* Same for input. */
-#define I_OTHER(tty)    \
-      ((I_INLCR(tty))  ||\
-      (I_IGNCR(tty))   ||\
-      (I_ICRNL(tty))   ||\
-      (I_IUCLC(tty))   ||\
-      (L_ISIG(tty)))
-
-#define MOD_TA   (        TA>>4)
-#define MOD_MTA  (MTA_CD1400>>4)
-#define MOD_SXDC (      SXDC>>4)
-
-
-/* We copy the download code over to the card in chunks of ... bytes */
-#define SX_CHUNK_SIZE 128
-
-#endif /* __KERNEL__ */
-
-
-
-/* Specialix document 6210046-11 page 3 */
-#define SPX(X) (('S'<<24) | ('P' << 16) | (X))
-
-/* Specialix-Linux specific IOCTLS. */
-#define SPXL(X) (SPX(('L' << 8) | (X)))
-
-
-#define SXIO_SET_BOARD      SPXL(0x01)
-#define SXIO_GET_TYPE       SPXL(0x02)
-#define SXIO_DOWNLOAD       SPXL(0x03)
-#define SXIO_INIT           SPXL(0x04)
-#define SXIO_SETDEBUG       SPXL(0x05)
-#define SXIO_GETDEBUG       SPXL(0x06)
-#define SXIO_DO_RAMTEST     SPXL(0x07)
-#define SXIO_SETGSDEBUG     SPXL(0x08)
-#define SXIO_GETGSDEBUG     SPXL(0x09)
-#define SXIO_GETNPORTS      SPXL(0x0a)
-
-
-#ifndef SXCTL_MISC_MINOR 
-/* Allow others to gather this into "major.h" or something like that */
-#define SXCTL_MISC_MINOR    167
-#endif
-
-#ifndef SX_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define SX_NORMAL_MAJOR  32
-#define SX_CALLOUT_MAJOR 33
-#endif
-
-
-#define SX_TYPE_SX          0x01
-#define SX_TYPE_SI          0x02
-#define SX_TYPE_CF          0x03
-
-
-#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN)
-/*                         Need a #define for ^^^^^^^ !!! */
-
diff --git a/drivers/char/sxboards.h b/drivers/char/sxboards.h
deleted file mode 100644
index 427927d..0000000
--- a/drivers/char/sxboards.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	SX/SI/XIO Board Hardware Definitions	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	16th March 1998				*/
-/*									*/
-/*	Version		:	3.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
-/*									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the SX/SI/XIO board hardware	*/
-/*									*/
-/************************************************************************/
-
-/* History...
-
-3.0.0	16/03/98 NPV	Creation.
-
-*/
-
-#ifndef	_sxboards_h				/* If SXBOARDS.H not already defined */
-#define	_sxboards_h    1
-
-/*****************************************************************************
-*******************************                 ******************************
-*******************************   Board Types   ******************************
-*******************************                 ******************************
-*****************************************************************************/
-
-/* BUS types... */
-#define		BUS_ISA		0
-#define		BUS_MCA		1
-#define		BUS_EISA	2
-#define		BUS_PCI		3
-
-/* Board phases... */
-#define		SI1_Z280	1
-#define		SI2_Z280	2
-#define		SI3_T225	3
-
-/* Board types... */
-#define		CARD_TYPE(bus,phase)	(bus<<4|phase)
-#define		CARD_BUS(type)		((type>>4)&0xF)
-#define		CARD_PHASE(type)	(type&0xF)
-
-#define		TYPE_SI1_ISA		CARD_TYPE(BUS_ISA,SI1_Z280)
-#define		TYPE_SI2_ISA		CARD_TYPE(BUS_ISA,SI2_Z280)
-#define		TYPE_SI2_EISA		CARD_TYPE(BUS_EISA,SI2_Z280)
-#define		TYPE_SI2_PCI		CARD_TYPE(BUS_PCI,SI2_Z280)
-
-#define		TYPE_SX_ISA		CARD_TYPE(BUS_ISA,SI3_T225)
-#define		TYPE_SX_PCI		CARD_TYPE(BUS_PCI,SI3_T225)
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 1 Z280   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* ISA board details... */
-#define		SI1_ISA_WINDOW_LEN	0x10000		/* 64 Kbyte shared memory window */
-//#define 	SI1_ISA_MEMORY_LEN	0x8000		/* Usable memory  - unused define*/
-//#define		SI1_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
-//#define		SI1_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-//#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
-//#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
-
-/* ISA board, register definitions... */
-//#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
-#define		SI1_ISA_RESET		0x8000		/* WRITE: Host Reset */
-#define		SI1_ISA_RESET_CLEAR	0xc000		/* WRITE: Host Reset clear*/
-#define		SI1_ISA_WAIT	        0x9000		/* WRITE: Host wait */
-#define		SI1_ISA_WAIT_CLEAR	0xd000		/* WRITE: Host wait clear */
-#define		SI1_ISA_INTCL        	0xa000		/* WRITE: Host Reset */
-#define		SI1_ISA_INTCL_CLEAR	0xe000		/* WRITE: Host Reset */
-
-
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 2 Z280   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* ISA board details... */
-#define		SI2_ISA_WINDOW_LEN	0x8000		/* 32 Kbyte shared memory window */
-#define 	SI2_ISA_MEMORY_LEN	0x7FF8		/* Usable memory */
-#define		SI2_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
-#define		SI2_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
-#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
-
-/* ISA board, register definitions... */
-#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
-#define		SI2_ISA_RESET		SI2_ISA_ID_BASE		/* WRITE: Host Reset */
-#define		SI2_ISA_IRQ11		(SI2_ISA_ID_BASE+1)	/* WRITE: Set IRQ11 */
-#define		SI2_ISA_IRQ12		(SI2_ISA_ID_BASE+2)	/* WRITE: Set IRQ12 */
-#define		SI2_ISA_IRQ15		(SI2_ISA_ID_BASE+3)	/* WRITE: Set IRQ15 */
-#define		SI2_ISA_IRQSET		(SI2_ISA_ID_BASE+4)	/* WRITE: Set Host Interrupt */
-#define		SI2_ISA_INTCLEAR	(SI2_ISA_ID_BASE+5)	/* WRITE: Enable Host Interrupt */
-
-#define		SI2_ISA_IRQ11_SET	0x10
-#define		SI2_ISA_IRQ11_CLEAR	0x00
-#define		SI2_ISA_IRQ12_SET	0x10
-#define		SI2_ISA_IRQ12_CLEAR	0x00
-#define		SI2_ISA_IRQ15_SET	0x10
-#define		SI2_ISA_IRQ15_CLEAR	0x00
-#define		SI2_ISA_INTCLEAR_SET	0x10
-#define		SI2_ISA_INTCLEAR_CLEAR	0x00
-#define		SI2_ISA_IRQSET_CLEAR	0x10
-#define		SI2_ISA_IRQSET_SET	0x00
-#define		SI2_ISA_RESET_SET	0x00
-#define		SI2_ISA_RESET_CLEAR	0x10
-
-/* PCI board details... */
-#define		SI2_PCI_WINDOW_LEN	0x100000	/* 1 Mbyte memory window */
-
-/* PCI board register definitions... */
-#define		SI2_PCI_SET_IRQ		0x40001		/* Set Host Interrupt  */
-#define		SI2_PCI_RESET		0xC0001		/* Host Reset */
-
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 3 T225   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* General board details... */
-#define		SX_WINDOW_LEN		64*1024		/* 64 Kbyte memory window */
-
-/* ISA board details... */
-#define		SX_ISA_ADDR_LOW		0x0A0000	/* Lowest address = 640 Kbyte */
-#define		SX_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-#define		SX_ISA_ADDR_STEP	SX_WINDOW_LEN	/* ISA board address step */
-#define		SX_ISA_IRQ_MASK		0x9E00		/* IRQs 15,12,11,10,9 */
-
-/* Hardware register definitions... */
-#define		SX_EVENT_STATUS		0x7800		/* READ:  T225 Event Status */
-#define		SX_EVENT_STROBE		0x7800		/* WRITE: T225 Event Strobe */
-#define		SX_EVENT_ENABLE		0x7880		/* WRITE: T225 Event Enable */
-#define		SX_VPD_ROM		0x7C00		/* READ:  Vital Product Data ROM */
-#define		SX_CONFIG		0x7C00		/* WRITE: Host Configuration Register */
-#define		SX_IRQ_STATUS		0x7C80		/* READ:  Host Interrupt Status */
-#define		SX_SET_IRQ		0x7C80		/* WRITE: Set Host Interrupt */
-#define		SX_RESET_STATUS		0x7D00		/* READ:  Host Reset Status */
-#define		SX_RESET		0x7D00		/* WRITE: Host Reset */
-#define		SX_RESET_IRQ		0x7D80		/* WRITE: Reset Host Interrupt */
-
-/* SX_VPD_ROM definitions... */
-#define		SX_VPD_SLX_ID1		0x00
-#define		SX_VPD_SLX_ID2		0x01
-#define		SX_VPD_HW_REV		0x02
-#define		SX_VPD_HW_ASSEM		0x03
-#define		SX_VPD_UNIQUEID4	0x04
-#define		SX_VPD_UNIQUEID3	0x05
-#define		SX_VPD_UNIQUEID2	0x06
-#define		SX_VPD_UNIQUEID1	0x07
-#define		SX_VPD_MANU_YEAR	0x08
-#define		SX_VPD_MANU_WEEK	0x09
-#define		SX_VPD_IDENT		0x10
-#define		SX_VPD_IDENT_STRING	"JET HOST BY KEV#"
-
-/* SX unique identifiers... */
-#define		SX_UNIQUEID_MASK	0xF0
-#define		SX_ISA_UNIQUEID1	0x20
-#define		SX_PCI_UNIQUEID1	0x50
-
-/* SX_CONFIG definitions... */
-#define		SX_CONF_BUSEN		0x02		/* Enable T225 memory and I/O */
-#define		SX_CONF_HOSTIRQ		0x04		/* Enable board to host interrupt */
-
-/* SX bootstrap... */
-#define		SX_BOOTSTRAP		"\x28\x20\x21\x02\x60\x0a"
-#define		SX_BOOTSTRAP_SIZE	6
-#define		SX_BOOTSTRAP_ADDR	(0x8000-SX_BOOTSTRAP_SIZE)
-
-/*****************************************************************************
-**********************************          **********************************
-**********************************   EISA   **********************************
-**********************************          **********************************
-*****************************************************************************/
-
-#define		SI2_EISA_OFF	 	0x42
-#define		SI2_EISA_VAL	 	0x01
-#define		SI2_EISA_WINDOW_LEN     0x10000
-
-/*****************************************************************************
-***********************************         **********************************
-***********************************   PCI   **********************************
-***********************************         **********************************
-*****************************************************************************/
-
-/* General definitions... */
-
-#define		SPX_VENDOR_ID		0x11CB		/* Assigned by the PCI SIG */
-#define		SPX_DEVICE_ID		0x4000		/* SI/XIO boards */
-#define		SPX_PLXDEVICE_ID	0x2000		/* SX boards */
-
-#define		SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
-#define		SI2_SUB_SYS_ID		0x400		/* Phase 2 (Z280) board */
-#define		SX_SUB_SYS_ID		0x200		/* Phase 3 (t225) board */
-
-#endif						/*_sxboards_h */
-
-/* End of SXBOARDS.H */
diff --git a/drivers/char/sxwindow.h b/drivers/char/sxwindow.h
deleted file mode 100644
index cf01b66..0000000
--- a/drivers/char/sxwindow.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	SX Shared Memory Window Structure	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	16th March 1998				*/
-/*									*/
-/*	Version		:	3.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
-/*									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the SX/SI/XIO cards shared	*/
-/*				memory window structure:		*/
-/*					SXCARD				*/
-/*					SXMODULE			*/
-/*					SXCHANNEL			*/
-/*									*/
-/************************************************************************/
-
-/* History...
-
-3.0.0	16/03/98 NPV	Creation. (based on STRUCT.H)
-
-*/
-
-#ifndef	_sxwindow_h				/* If SXWINDOW.H not already defined */
-#define	_sxwindow_h    1
-
-/*****************************************************************************
-***************************                        ***************************
-***************************   Common Definitions   ***************************
-***************************                        ***************************
-*****************************************************************************/
-
-typedef	struct	_SXCARD		*PSXCARD;	/* SXCARD structure pointer */
-typedef	struct	_SXMODULE	*PMOD;		/* SXMODULE structure pointer */
-typedef	struct	_SXCHANNEL	*PCHAN;		/* SXCHANNEL structure pointer */
-
-/*****************************************************************************
-*********************************            *********************************
-*********************************   SXCARD   *********************************
-*********************************            *********************************
-*****************************************************************************/
-
-typedef	struct	_SXCARD
-{
-	BYTE	cc_init_status;			/* 0x00 Initialisation status */
-	BYTE	cc_mem_size;			/* 0x01 Size of memory on card */
-	WORD	cc_int_count;			/* 0x02 Interrupt count */
-	WORD	cc_revision;			/* 0x04 Download code revision */
-	BYTE	cc_isr_count;			/* 0x06 Count when ISR is run */
-	BYTE	cc_main_count;			/* 0x07 Count when main loop is run */
-	WORD	cc_int_pending;			/* 0x08 Interrupt pending */
-	WORD	cc_poll_count;			/* 0x0A Count when poll is run */
-	BYTE	cc_int_set_count;		/* 0x0C Count when host interrupt is set */
-	BYTE	cc_rfu[0x80 - 0x0D];		/* 0x0D Pad structure to 128 bytes (0x80) */
-
-} SXCARD;
-
-/* SXCARD.cc_init_status definitions... */
-#define 	ADAPTERS_FOUND		(BYTE)0x01
-#define 	NO_ADAPTERS_FOUND	(BYTE)0xFF
-
-/* SXCARD.cc_mem_size definitions... */
-#define 	SX_MEMORY_SIZE		(BYTE)0x40
-
-/* SXCARD.cc_int_count definitions... */
-#define 	INT_COUNT_DEFAULT	100	/* Hz */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   SXMODULE   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-#define	TOP_POINTER(a)		((a)|0x8000)	/* Sets top bit of word */
-#define UNTOP_POINTER(a)	((a)&~0x8000)	/* Clears top bit of word */
-
-typedef	struct	_SXMODULE
-{
-	WORD	mc_next;			/* 0x00 Next module "pointer" (ORed with 0x8000) */
-	BYTE	mc_type;			/* 0x02 Type of TA in terms of number of channels */
-	BYTE	mc_mod_no;			/* 0x03 Module number on SI bus cable (0 closest to card) */
-	BYTE	mc_dtr;				/* 0x04 Private DTR copy (TA only) */
-	BYTE	mc_rfu1;			/* 0x05 Reserved */
-	WORD	mc_uart;			/* 0x06 UART base address for this module */
-	BYTE	mc_chip;			/* 0x08 Chip type / number of ports */
-	BYTE	mc_current_uart;		/* 0x09 Current uart selected for this module */
-#ifdef	DOWNLOAD
-	PCHAN	mc_chan_pointer[8];		/* 0x0A Pointer to each channel structure */
-#else
-	WORD	mc_chan_pointer[8];		/* 0x0A Define as WORD if not compiling into download */
-#endif
-	WORD	mc_rfu2;			/* 0x1A Reserved */
-	BYTE	mc_opens1;			/* 0x1C Number of open ports on first four ports on MTA/SXDC */
-	BYTE	mc_opens2;			/* 0x1D Number of open ports on second four ports on MTA/SXDC */
-	BYTE	mc_mods;			/* 0x1E Types of connector module attached to MTA/SXDC */
-	BYTE	mc_rev1;			/* 0x1F Revision of first CD1400 on MTA/SXDC */
-	BYTE	mc_rev2;			/* 0x20 Revision of second CD1400 on MTA/SXDC */
-	BYTE	mc_mtaasic_rev;			/* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */
-	BYTE	mc_rfu3[0x100 - 0x22];		/* 0x22 Pad structure to 256 bytes (0x100) */
-
-} SXMODULE;
-
-/* SXMODULE.mc_type definitions... */
-#define		FOUR_PORTS	(BYTE)4
-#define 	EIGHT_PORTS	(BYTE)8
-
-/* SXMODULE.mc_chip definitions... */
-#define 	CHIP_MASK	0xF0
-#define		TA		(BYTE)0
-#define 	TA4		(TA | FOUR_PORTS)
-#define 	TA8		(TA | EIGHT_PORTS)
-#define		TA4_ASIC	(BYTE)0x0A
-#define		TA8_ASIC	(BYTE)0x0B
-#define 	MTA_CD1400	(BYTE)0x28
-#define 	SXDC		(BYTE)0x48
-
-/* SXMODULE.mc_mods definitions... */
-#define		MOD_RS232DB25	0x00		/* RS232 DB25 (socket/plug) */
-#define		MOD_RS232RJ45	0x01		/* RS232 RJ45 (shielded/opto-isolated) */
-#define		MOD_RESERVED_2	0x02		/* Reserved (RS485) */
-#define		MOD_RS422DB25	0x03		/* RS422 DB25 Socket */
-#define		MOD_RESERVED_4	0x04		/* Reserved */
-#define		MOD_PARALLEL	0x05		/* Parallel */
-#define		MOD_RESERVED_6	0x06		/* Reserved (RS423) */
-#define		MOD_RESERVED_7	0x07		/* Reserved */
-#define		MOD_2_RS232DB25	0x08		/* Rev 2.0 RS232 DB25 (socket/plug) */
-#define		MOD_2_RS232RJ45	0x09		/* Rev 2.0 RS232 RJ45 */
-#define		MOD_RESERVED_A	0x0A		/* Rev 2.0 Reserved */
-#define		MOD_2_RS422DB25	0x0B		/* Rev 2.0 RS422 DB25 */
-#define		MOD_RESERVED_C	0x0C		/* Rev 2.0 Reserved */
-#define		MOD_2_PARALLEL	0x0D		/* Rev 2.0 Parallel */
-#define		MOD_RESERVED_E	0x0E		/* Rev 2.0 Reserved */
-#define		MOD_BLANK	0x0F		/* Blank Panel */
-
-/*****************************************************************************
-********************************               *******************************
-********************************   SXCHANNEL   *******************************
-********************************               *******************************
-*****************************************************************************/
-
-#define		TX_BUFF_OFFSET		0x60	/* Transmit buffer offset in channel structure */
-#define		BUFF_POINTER(a)		(((a)+TX_BUFF_OFFSET)|0x8000)
-#define		UNBUFF_POINTER(a)	(jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) 
-#define 	BUFFER_SIZE		256
-#define 	HIGH_WATER		((BUFFER_SIZE / 4) * 3)
-#define 	LOW_WATER		(BUFFER_SIZE / 4)
-
-typedef	struct	_SXCHANNEL
-{
-	WORD	next_item;			/* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */
-	WORD 	addr_uart;			/* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */
-	WORD	module;				/* 0x04 Offset from window base of parent SXMODULE structure */
-	BYTE 	type;				/* 0x06 Chip type / number of ports (copy of mc_chip) */
-	BYTE	chan_number;			/* 0x07 Channel number on the TA/MTA/SXDC */
-	WORD	xc_status;			/* 0x08 Flow control and I/O status */
-	BYTE	hi_rxipos;			/* 0x0A Receive buffer input index */
-	BYTE	hi_rxopos;			/* 0x0B Receive buffer output index */
-	BYTE	hi_txopos;			/* 0x0C Transmit buffer output index */
-	BYTE	hi_txipos;			/* 0x0D Transmit buffer input index */
-	BYTE	hi_hstat;			/* 0x0E Command register */
-	BYTE	dtr_bit;			/* 0x0F INTERNAL DTR control byte (TA only) */
-	BYTE	txon;				/* 0x10 INTERNAL copy of hi_txon */
-	BYTE	txoff;				/* 0x11 INTERNAL copy of hi_txoff */
-	BYTE	rxon;				/* 0x12 INTERNAL copy of hi_rxon */
-	BYTE	rxoff;				/* 0x13 INTERNAL copy of hi_rxoff */
-	BYTE	hi_mr1;				/* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/
-	BYTE	hi_mr2;				/* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/
-	BYTE	hi_csr;				/* 0x16 Clock Select Register (baud rate) */
-	BYTE	hi_op;				/* 0x17 Modem Output Signal */
-	BYTE	hi_ip;				/* 0x18 Modem Input Signal */
-	BYTE	hi_state;			/* 0x19 Channel status */
-	BYTE	hi_prtcl;			/* 0x1A Channel protocol (flow control) */
-	BYTE	hi_txon;			/* 0x1B Transmit XON character */
-	BYTE	hi_txoff;			/* 0x1C Transmit XOFF character */
-	BYTE	hi_rxon;			/* 0x1D Receive XON character */
-	BYTE	hi_rxoff;			/* 0x1E Receive XOFF character */
-	BYTE	close_prev;			/* 0x1F INTERNAL channel previously closed flag */
-	BYTE	hi_break;			/* 0x20 Break and error control */
-	BYTE	break_state;			/* 0x21 INTERNAL copy of hi_break */
-	BYTE	hi_mask;			/* 0x22 Mask for received data */
-	BYTE	mask;				/* 0x23 INTERNAL copy of hi_mask */
-	BYTE	mod_type;			/* 0x24 MTA/SXDC hardware module type */
-	BYTE	ccr_state;			/* 0x25 INTERNAL MTA/SXDC state of CCR register */
-	BYTE	ip_mask;			/* 0x26 Input handshake mask */
-	BYTE	hi_parallel;			/* 0x27 Parallel port flag */
-	BYTE	par_error;			/* 0x28 Error code for parallel loopback test */
-	BYTE	any_sent;			/* 0x29 INTERNAL data sent flag */
-	BYTE	asic_txfifo_size;		/* 0x2A INTERNAL SXDC transmit FIFO size */
-	BYTE	rfu1[2];			/* 0x2B Reserved */
-	BYTE	csr;				/* 0x2D INTERNAL copy of hi_csr */
-#ifdef	DOWNLOAD
-	PCHAN	nextp;				/* 0x2E Offset from window base of next channel structure */
-#else
-	WORD	nextp;				/* 0x2E Define as WORD if not compiling into download */
-#endif
-	BYTE	prtcl;				/* 0x30 INTERNAL copy of hi_prtcl */
-	BYTE	mr1;				/* 0x31 INTERNAL copy of hi_mr1 */
-	BYTE	mr2;				/* 0x32 INTERNAL copy of hi_mr2 */
-	BYTE	hi_txbaud;			/* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */
-	BYTE	hi_rxbaud;			/* 0x34 Extended receive baud rate  (SXDC only if((hi_csr&0xF0)==0xF0) */
-	BYTE	txbreak_state;			/* 0x35 INTERNAL MTA/SXDC transmit break state */
-	BYTE	txbaud;				/* 0x36 INTERNAL copy of hi_txbaud */
-	BYTE	rxbaud;				/* 0x37 INTERNAL copy of hi_rxbaud */
-	WORD	err_framing;			/* 0x38 Count of receive framing errors */
-	WORD	err_parity;			/* 0x3A Count of receive parity errors */
-	WORD	err_overrun;			/* 0x3C Count of receive overrun errors */
-	WORD	err_overflow;			/* 0x3E Count of receive buffer overflow errors */
-	BYTE	rfu2[TX_BUFF_OFFSET - 0x40];	/* 0x40 Reserved until hi_txbuf */
-	BYTE	hi_txbuf[BUFFER_SIZE];		/* 0x060 Transmit buffer */
-	BYTE	hi_rxbuf[BUFFER_SIZE];		/* 0x160 Receive buffer */
-	BYTE	rfu3[0x300 - 0x260];		/* 0x260 Reserved until 768 bytes (0x300) */
-
-} SXCHANNEL;
-
-/* SXCHANNEL.addr_uart definitions... */
-#define		FASTPATH	0x1000		/* Set to indicate fast rx/tx processing (TA only) */
-
-/* SXCHANNEL.xc_status definitions... */
-#define		X_TANY		0x0001		/* XON is any character (TA only) */
-#define		X_TION		0x0001		/* Tx interrupts on (MTA only) */
-#define		X_TXEN		0x0002		/* Tx XON/XOFF enabled (TA only) */
-#define		X_RTSEN		0x0002		/* RTS FLOW enabled (MTA only) */
-#define		X_TXRC		0x0004		/* XOFF received (TA only) */
-#define		X_RTSLOW	0x0004		/* RTS dropped (MTA only) */
-#define		X_RXEN		0x0008		/* Rx XON/XOFF enabled */
-#define		X_ANYXO		0x0010		/* XOFF pending/sent or RTS dropped */
-#define		X_RXSE		0x0020		/* Rx XOFF sent */
-#define		X_NPEND		0x0040		/* Rx XON pending or XOFF pending */
-#define		X_FPEND		0x0080		/* Rx XOFF pending */
-#define		C_CRSE		0x0100		/* Carriage return sent (TA only) */
-#define		C_TEMR		0x0100		/* Tx empty requested (MTA only) */
-#define		C_TEMA		0x0200		/* Tx empty acked (MTA only) */
-#define		C_ANYP		0x0200		/* Any protocol bar tx XON/XOFF (TA only) */
-#define		C_EN		0x0400		/* Cooking enabled (on MTA means port is also || */
-#define		C_HIGH		0x0800		/* Buffer previously hit high water */
-#define		C_CTSEN		0x1000		/* CTS automatic flow-control enabled */
-#define		C_DCDEN		0x2000		/* DCD/DTR checking enabled */
-#define		C_BREAK		0x4000		/* Break detected */
-#define		C_RTSEN		0x8000		/* RTS automatic flow control enabled (MTA only) */
-#define		C_PARITY	0x8000		/* Parity checking enabled (TA only) */
-
-/* SXCHANNEL.hi_hstat definitions... */
-#define		HS_IDLE_OPEN	0x00		/* Channel open state */
-#define		HS_LOPEN	0x02		/* Local open command (no modem monitoring) */
-#define		HS_MOPEN	0x04		/* Modem open command (wait for DCD signal) */
-#define		HS_IDLE_MPEND	0x06		/* Waiting for DCD signal state */
-#define		HS_CONFIG	0x08		/* Configuration command */
-#define		HS_CLOSE	0x0A		/* Close command */
-#define		HS_START	0x0C		/* Start transmit break command */
-#define		HS_STOP		0x0E		/* Stop transmit break command */
-#define		HS_IDLE_CLOSED	0x10		/* Closed channel state */
-#define		HS_IDLE_BREAK	0x12		/* Transmit break state */
-#define		HS_FORCE_CLOSED	0x14		/* Force close command */
-#define		HS_RESUME	0x16		/* Clear pending XOFF command */
-#define		HS_WFLUSH	0x18		/* Flush transmit buffer command */
-#define		HS_RFLUSH	0x1A		/* Flush receive buffer command */
-#define		HS_SUSPEND	0x1C		/* Suspend output command (like XOFF received) */
-#define		PARALLEL	0x1E		/* Parallel port loopback test command (Diagnostics Only) */
-#define		ENABLE_RX_INTS	0x20		/* Enable receive interrupts command (Diagnostics Only) */
-#define		ENABLE_TX_INTS	0x22		/* Enable transmit interrupts command (Diagnostics Only) */
-#define		ENABLE_MDM_INTS	0x24		/* Enable modem interrupts command (Diagnostics Only) */
-#define		DISABLE_INTS	0x26		/* Disable interrupts command (Diagnostics Only) */
-
-/* SXCHANNEL.hi_mr1 definitions... */
-#define		MR1_BITS	0x03		/* Data bits mask */
-#define		MR1_5_BITS	0x00		/* 5 data bits */
-#define		MR1_6_BITS	0x01		/* 6 data bits */
-#define		MR1_7_BITS	0x02		/* 7 data bits */
-#define		MR1_8_BITS	0x03		/* 8 data bits */
-#define		MR1_PARITY	0x1C		/* Parity mask */
-#define		MR1_ODD		0x04		/* Odd parity */
-#define		MR1_EVEN	0x00		/* Even parity */
-#define		MR1_WITH	0x00		/* Parity enabled */
-#define		MR1_FORCE	0x08		/* Force parity */
-#define		MR1_NONE	0x10		/* No parity */
-#define		MR1_NOPARITY	MR1_NONE		/* No parity */
-#define		MR1_ODDPARITY	(MR1_WITH|MR1_ODD)	/* Odd parity */
-#define		MR1_EVENPARITY	(MR1_WITH|MR1_EVEN)	/* Even parity */
-#define		MR1_MARKPARITY	(MR1_FORCE|MR1_ODD)	/* Mark parity */
-#define		MR1_SPACEPARITY	(MR1_FORCE|MR1_EVEN)	/* Space parity */
-#define		MR1_RTS_RXFLOW	0x80		/* RTS receive flow control */
-
-/* SXCHANNEL.hi_mr2 definitions... */
-#define		MR2_STOP	0x0F		/* Stop bits mask */
-#define		MR2_1_STOP	0x07		/* 1 stop bit */
-#define		MR2_2_STOP	0x0F		/* 2 stop bits */
-#define		MR2_CTS_TXFLOW	0x10		/* CTS transmit flow control */
-#define		MR2_RTS_TOGGLE	0x20		/* RTS toggle on transmit */
-#define		MR2_NORMAL	0x00		/* Normal mode */
-#define		MR2_AUTO	0x40		/* Auto-echo mode (TA only) */
-#define		MR2_LOCAL	0x80		/* Local echo mode */
-#define		MR2_REMOTE	0xC0		/* Remote echo mode (TA only) */
-
-/* SXCHANNEL.hi_csr definitions... */
-#define		CSR_75		0x0		/*    75 baud */
-#define		CSR_110		0x1		/*   110 baud (TA), 115200 (MTA/SXDC) */
-#define		CSR_38400	0x2		/* 38400 baud */
-#define		CSR_150		0x3		/*   150 baud */
-#define		CSR_300		0x4		/*   300 baud */
-#define		CSR_600		0x5		/*   600 baud */
-#define		CSR_1200	0x6		/*  1200 baud */
-#define		CSR_2000	0x7		/*  2000 baud */
-#define		CSR_2400	0x8		/*  2400 baud */
-#define		CSR_4800	0x9		/*  4800 baud */
-#define		CSR_1800	0xA		/*  1800 baud */
-#define		CSR_9600	0xB		/*  9600 baud */
-#define		CSR_19200	0xC		/* 19200 baud */
-#define		CSR_57600	0xD		/* 57600 baud */
-#define		CSR_EXTBAUD	0xF		/* Extended baud rate (hi_txbaud/hi_rxbaud) */
-
-/* SXCHANNEL.hi_op definitions... */
-#define		OP_RTS		0x01		/* RTS modem output signal */
-#define		OP_DTR		0x02		/* DTR modem output signal */
-
-/* SXCHANNEL.hi_ip definitions... */
-#define		IP_CTS		0x02		/* CTS modem input signal */
-#define		IP_DCD		0x04		/* DCD modem input signal */
-#define		IP_DSR		0x20		/* DTR modem input signal */
-#define		IP_RI		0x40		/* RI modem input signal */
-
-/* SXCHANNEL.hi_state definitions... */
-#define		ST_BREAK	0x01		/* Break received (clear with config) */
-#define		ST_DCD		0x02		/* DCD signal changed state */
-
-/* SXCHANNEL.hi_prtcl definitions... */
-#define		SP_TANY		0x01		/* Transmit XON/XANY (if SP_TXEN enabled) */
-#define		SP_TXEN		0x02		/* Transmit XON/XOFF flow control */
-#define		SP_CEN		0x04		/* Cooking enabled */
-#define		SP_RXEN		0x08		/* Rx XON/XOFF enabled */
-#define		SP_DCEN		0x20		/* DCD / DTR check */
-#define		SP_DTR_RXFLOW	0x40		/* DTR receive flow control */
-#define		SP_PAEN		0x80		/* Parity checking enabled */
-
-/* SXCHANNEL.hi_break definitions... */
-#define		BR_IGN		0x01		/* Ignore any received breaks */
-#define		BR_INT		0x02		/* Interrupt on received break */
-#define		BR_PARMRK	0x04		/* Enable parmrk parity error processing */
-#define		BR_PARIGN	0x08		/* Ignore chars with parity errors */
-#define 	BR_ERRINT	0x80		/* Treat parity/framing/overrun errors as exceptions */
-
-/* SXCHANNEL.par_error definitions.. */
-#define		DIAG_IRQ_RX	0x01		/* Indicate serial receive interrupt (diags only) */
-#define		DIAG_IRQ_TX	0x02		/* Indicate serial transmit interrupt (diags only) */
-#define		DIAG_IRQ_MD	0x04		/* Indicate serial modem interrupt (diags only) */
-
-/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */
-#define		BAUD_75		0x00		/*     75 baud */
-#define		BAUD_115200	0x01		/* 115200 baud */
-#define		BAUD_38400	0x02		/*  38400 baud */
-#define		BAUD_150	0x03		/*    150 baud */
-#define		BAUD_300	0x04		/*    300 baud */
-#define		BAUD_600	0x05		/*    600 baud */
-#define		BAUD_1200	0x06		/*   1200 baud */
-#define		BAUD_2000	0x07		/*   2000 baud */
-#define		BAUD_2400	0x08		/*   2400 baud */
-#define		BAUD_4800	0x09		/*   4800 baud */
-#define		BAUD_1800	0x0A		/*   1800 baud */
-#define		BAUD_9600	0x0B		/*   9600 baud */
-#define		BAUD_19200	0x0C		/*  19200 baud */
-#define		BAUD_57600	0x0D		/*  57600 baud */
-#define		BAUD_230400	0x0E		/* 230400 baud */
-#define		BAUD_460800	0x0F		/* 460800 baud */
-#define		BAUD_921600	0x10		/* 921600 baud */
-#define		BAUD_50		0x11    	/*     50 baud */
-#define		BAUD_110	0x12		/*    110 baud */
-#define		BAUD_134_5	0x13		/*  134.5 baud */
-#define		BAUD_200	0x14		/*    200 baud */
-#define		BAUD_7200	0x15		/*   7200 baud */
-#define		BAUD_56000	0x16		/*  56000 baud */
-#define		BAUD_64000	0x17		/*  64000 baud */
-#define		BAUD_76800	0x18		/*  76800 baud */
-#define		BAUD_128000	0x19		/* 128000 baud */
-#define		BAUD_150000	0x1A		/* 150000 baud */
-#define		BAUD_14400	0x1B		/*  14400 baud */
-#define		BAUD_256000	0x1C		/* 256000 baud */
-#define		BAUD_28800	0x1D		/*  28800 baud */
-
-/* SXCHANNEL.txbreak_state definiions... */
-#define		TXBREAK_OFF	0		/* Not sending break */
-#define		TXBREAK_START	1		/* Begin sending break */
-#define		TXBREAK_START1	2		/* Begin sending break, part 1 */
-#define		TXBREAK_ON	3		/* Sending break */
-#define		TXBREAK_STOP	4		/* Stop sending break */
-#define		TXBREAK_STOP1	5		/* Stop sending break, part 1 */
-
-#endif						/* _sxwindow_h */
-
-/* End of SXWINDOW.H */
-
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
deleted file mode 100644
index 3a6824f..0000000
--- a/drivers/char/synclink.c
+++ /dev/null
@@ -1,8120 +0,0 @@
-/*
- * linux/drivers/char/synclink.c
- *
- * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $
- *
- * Device driver for Microgate SyncLink ISA and PCI
- * high speed multiprotocol serial adapters.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * Derived from serial.c written by Theodore Ts'o and Linus Torvalds
- *
- * Original release 01/11/99
- *
- * This code is released under the GNU General Public License (GPL)
- *
- * This driver is primarily intended for use in synchronous
- * HDLC mode. Asynchronous mode is also provided.
- *
- * When operating in synchronous mode, each call to mgsl_write()
- * contains exactly one complete HDLC frame. Calling mgsl_put_char
- * will start assembling an HDLC frame that will not be sent until
- * mgsl_flush_chars or mgsl_write is called.
- * 
- * Synchronous receive data is reported as complete frames. To accomplish
- * this, the TTY flip buffer is bypassed (too small to hold largest
- * frame and may fragment frames) and the line discipline
- * receive entry point is called directly.
- *
- * This driver has been tested with a slightly modified ppp.c driver
- * for synchronous PPP.
- *
- * 2000/02/16
- * Added interface for syncppp.c driver (an alternate synchronous PPP
- * implementation that also supports Cisco HDLC). Each device instance
- * registers as a tty device AND a network device (if dosyncppp option
- * is set for the device). The functionality is determined by which
- * device interface is opened.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#if defined(__i386__)
-#  define BREAKPOINT() asm("   int $3");
-#else
-#  define BREAKPOINT() { }
-#endif
-
-#define MAX_ISA_DEVICES 10
-#define MAX_PCI_DEVICES 10
-#define MAX_TOTAL_DEVICES 20
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/ioctl.h>
-#include <linux/synclink.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <linux/bitops.h>
-#include <asm/types.h>
-#include <linux/termios.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/dma-mapping.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-#define GET_USER(error,value,addr) error = get_user(value,addr)
-#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
-#define PUT_USER(error,value,addr) error = put_user(value,addr)
-#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
-
-#include <asm/uaccess.h>
-
-#define RCLRVALUE 0xffff
-
-static MGSL_PARAMS default_params = {
-	MGSL_MODE_HDLC,			/* unsigned long mode */
-	0,				/* unsigned char loopback; */
-	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */
-	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */
-	0,				/* unsigned long clock_speed; */
-	0xff,				/* unsigned char addr_filter; */
-	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */
-	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */
-	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */
-	9600,				/* unsigned long data_rate; */
-	8,				/* unsigned char data_bits; */
-	1,				/* unsigned char stop_bits; */
-	ASYNC_PARITY_NONE		/* unsigned char parity; */
-};
-
-#define SHARED_MEM_ADDRESS_SIZE 0x40000
-#define BUFFERLISTSIZE 4096
-#define DMABUFFERSIZE 4096
-#define MAXRXFRAMES 7
-
-typedef struct _DMABUFFERENTRY
-{
-	u32 phys_addr;	/* 32-bit flat physical address of data buffer */
-	volatile u16 count;	/* buffer size/data count */
-	volatile u16 status;	/* Control/status field */
-	volatile u16 rcc;	/* character count field */
-	u16 reserved;	/* padding required by 16C32 */
-	u32 link;	/* 32-bit flat link to next buffer entry */
-	char *virt_addr;	/* virtual address of data buffer */
-	u32 phys_entry;	/* physical address of this buffer entry */
-	dma_addr_t dma_addr;
-} DMABUFFERENTRY, *DMAPBUFFERENTRY;
-
-/* The queue of BH actions to be performed */
-
-#define BH_RECEIVE  1
-#define BH_TRANSMIT 2
-#define BH_STATUS   4
-
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-struct	_input_signal_events {
-	int	ri_up;	
-	int	ri_down;
-	int	dsr_up;
-	int	dsr_down;
-	int	dcd_up;
-	int	dcd_down;
-	int	cts_up;
-	int	cts_down;
-};
-
-/* transmit holding buffer definitions*/
-#define MAX_TX_HOLDING_BUFFERS 5
-struct tx_holding_buffer {
-	int	buffer_size;
-	unsigned char *	buffer;
-};
-
-
-/*
- * Device instance data structure
- */
- 
-struct mgsl_struct {
-	int			magic;
-	struct tty_port		port;
-	int			line;
-	int                     hw_version;
-	
-	struct mgsl_icount	icount;
-	
-	int			timeout;
-	int			x_char;		/* xon/xoff character */
-	u16			read_status_mask;
-	u16			ignore_status_mask;	
-	unsigned char 		*xmit_buf;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	
-	wait_queue_head_t	status_event_wait_q;
-	wait_queue_head_t	event_wait_q;
-	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
-	struct mgsl_struct	*next_device;	/* device list link */
-	
-	spinlock_t irq_spinlock;		/* spinlock for synchronizing with ISR */
-	struct work_struct task;		/* task structure for scheduling bh */
-
-	u32 EventMask;			/* event trigger mask */
-	u32 RecordedEvents;		/* pending events */
-
-	u32 max_frame_size;		/* as set by device config */
-
-	u32 pending_bh;
-
-	bool bh_running;		/* Protection from multiple */
-	int isr_overflow;
-	bool bh_requested;
-	
-	int dcd_chkcount;		/* check counts to prevent */
-	int cts_chkcount;		/* too many IRQs if a signal */
-	int dsr_chkcount;		/* is floating */
-	int ri_chkcount;
-
-	char *buffer_list;		/* virtual address of Rx & Tx buffer lists */
-	u32 buffer_list_phys;
-	dma_addr_t buffer_list_dma_addr;
-
-	unsigned int rx_buffer_count;	/* count of total allocated Rx buffers */
-	DMABUFFERENTRY *rx_buffer_list;	/* list of receive buffer entries */
-	unsigned int current_rx_buffer;
-
-	int num_tx_dma_buffers;		/* number of tx dma frames required */
- 	int tx_dma_buffers_used;
-	unsigned int tx_buffer_count;	/* count of total allocated Tx buffers */
-	DMABUFFERENTRY *tx_buffer_list;	/* list of transmit buffer entries */
-	int start_tx_dma_buffer;	/* tx dma buffer to start tx dma operation */
-	int current_tx_buffer;          /* next tx dma buffer to be loaded */
-	
-	unsigned char *intermediate_rxbuffer;
-
-	int num_tx_holding_buffers;	/* number of tx holding buffer allocated */
-	int get_tx_holding_index;  	/* next tx holding buffer for adapter to load */
-	int put_tx_holding_index;  	/* next tx holding buffer to store user request */
-	int tx_holding_count;		/* number of tx holding buffers waiting */
-	struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS];
-
-	bool rx_enabled;
-	bool rx_overflow;
-	bool rx_rcc_underrun;
-
-	bool tx_enabled;
-	bool tx_active;
-	u32 idle_mode;
-
-	u16 cmr_value;
-	u16 tcsr_value;
-
-	char device_name[25];		/* device instance name */
-
-	unsigned int bus_type;	/* expansion bus type (ISA,EISA,PCI) */
-	unsigned char bus;		/* expansion bus number (zero based) */
-	unsigned char function;		/* PCI device number */
-
-	unsigned int io_base;		/* base I/O address of adapter */
-	unsigned int io_addr_size;	/* size of the I/O address range */
-	bool io_addr_requested;		/* true if I/O address requested */
-	
-	unsigned int irq_level;		/* interrupt level */
-	unsigned long irq_flags;
-	bool irq_requested;		/* true if IRQ requested */
-	
-	unsigned int dma_level;		/* DMA channel */
-	bool dma_requested;		/* true if dma channel requested */
-
-	u16 mbre_bit;
-	u16 loopback_bits;
-	u16 usc_idle_mode;
-
-	MGSL_PARAMS params;		/* communications parameters */
-
-	unsigned char serial_signals;	/* current serial signal states */
-
-	bool irq_occurred;		/* for diagnostics use */
-	unsigned int init_error;	/* Initialization startup error 		(DIAGS)	*/
-	int	fDiagnosticsmode;	/* Driver in Diagnostic mode?			(DIAGS)	*/
-
-	u32 last_mem_alloc;
-	unsigned char* memory_base;	/* shared memory address (PCI only) */
-	u32 phys_memory_base;
-	bool shared_mem_requested;
-
-	unsigned char* lcr_base;	/* local config registers (PCI only) */
-	u32 phys_lcr_base;
-	u32 lcr_offset;
-	bool lcr_mem_requested;
-
-	u32 misc_ctrl_value;
-	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
-	char char_buf[MAX_ASYNC_BUFFER_SIZE];	
-	bool drop_rts_on_tx_done;
-
-	bool loopmode_insert_requested;
-	bool loopmode_send_done_requested;
-	
-	struct	_input_signal_events	input_signal_events;
-
-	/* generic HDLC device parts */
-	int netcount;
-	spinlock_t netlock;
-
-#if SYNCLINK_GENERIC_HDLC
-	struct net_device *netdev;
-#endif
-};
-
-#define MGSL_MAGIC 0x5401
-
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#ifndef SERIAL_XMIT_SIZE
-#define SERIAL_XMIT_SIZE 4096
-#endif
-
-/*
- * These macros define the offsets used in calculating the
- * I/O address of the specified USC registers.
- */
-
-
-#define DCPIN 2		/* Bit 1 of I/O address */
-#define SDPIN 4		/* Bit 2 of I/O address */
-
-#define DCAR 0		/* DMA command/address register */
-#define CCAR SDPIN		/* channel command/address register */
-#define DATAREG DCPIN + SDPIN	/* serial data register */
-#define MSBONLY 0x41
-#define LSBONLY 0x40
-
-/*
- * These macros define the register address (ordinal number)
- * used for writing address/value pairs to the USC.
- */
-
-#define CMR	0x02	/* Channel mode Register */
-#define CCSR	0x04	/* Channel Command/status Register */
-#define CCR	0x06	/* Channel Control Register */
-#define PSR	0x08	/* Port status Register */
-#define PCR	0x0a	/* Port Control Register */
-#define TMDR	0x0c	/* Test mode Data Register */
-#define TMCR	0x0e	/* Test mode Control Register */
-#define CMCR	0x10	/* Clock mode Control Register */
-#define HCR	0x12	/* Hardware Configuration Register */
-#define IVR	0x14	/* Interrupt Vector Register */
-#define IOCR	0x16	/* Input/Output Control Register */
-#define ICR	0x18	/* Interrupt Control Register */
-#define DCCR	0x1a	/* Daisy Chain Control Register */
-#define MISR	0x1c	/* Misc Interrupt status Register */
-#define SICR	0x1e	/* status Interrupt Control Register */
-#define RDR	0x20	/* Receive Data Register */
-#define RMR	0x22	/* Receive mode Register */
-#define RCSR	0x24	/* Receive Command/status Register */
-#define RICR	0x26	/* Receive Interrupt Control Register */
-#define RSR	0x28	/* Receive Sync Register */
-#define RCLR	0x2a	/* Receive count Limit Register */
-#define RCCR	0x2c	/* Receive Character count Register */
-#define TC0R	0x2e	/* Time Constant 0 Register */
-#define TDR	0x30	/* Transmit Data Register */
-#define TMR	0x32	/* Transmit mode Register */
-#define TCSR	0x34	/* Transmit Command/status Register */
-#define TICR	0x36	/* Transmit Interrupt Control Register */
-#define TSR	0x38	/* Transmit Sync Register */
-#define TCLR	0x3a	/* Transmit count Limit Register */
-#define TCCR	0x3c	/* Transmit Character count Register */
-#define TC1R	0x3e	/* Time Constant 1 Register */
-
-
-/*
- * MACRO DEFINITIONS FOR DMA REGISTERS
- */
-
-#define DCR	0x06	/* DMA Control Register (shared) */
-#define DACR	0x08	/* DMA Array count Register (shared) */
-#define BDCR	0x12	/* Burst/Dwell Control Register (shared) */
-#define DIVR	0x14	/* DMA Interrupt Vector Register (shared) */	
-#define DICR	0x18	/* DMA Interrupt Control Register (shared) */
-#define CDIR	0x1a	/* Clear DMA Interrupt Register (shared) */
-#define SDIR	0x1c	/* Set DMA Interrupt Register (shared) */
-
-#define TDMR	0x02	/* Transmit DMA mode Register */
-#define TDIAR	0x1e	/* Transmit DMA Interrupt Arm Register */
-#define TBCR	0x2a	/* Transmit Byte count Register */
-#define TARL	0x2c	/* Transmit Address Register (low) */
-#define TARU	0x2e	/* Transmit Address Register (high) */
-#define NTBCR	0x3a	/* Next Transmit Byte count Register */
-#define NTARL	0x3c	/* Next Transmit Address Register (low) */
-#define NTARU	0x3e	/* Next Transmit Address Register (high) */
-
-#define RDMR	0x82	/* Receive DMA mode Register (non-shared) */
-#define RDIAR	0x9e	/* Receive DMA Interrupt Arm Register */
-#define RBCR	0xaa	/* Receive Byte count Register */
-#define RARL	0xac	/* Receive Address Register (low) */
-#define RARU	0xae	/* Receive Address Register (high) */
-#define NRBCR	0xba	/* Next Receive Byte count Register */
-#define NRARL	0xbc	/* Next Receive Address Register (low) */
-#define NRARU	0xbe	/* Next Receive Address Register (high) */
-
-
-/*
- * MACRO DEFINITIONS FOR MODEM STATUS BITS
- */
-
-#define MODEMSTATUS_DTR 0x80
-#define MODEMSTATUS_DSR 0x40
-#define MODEMSTATUS_RTS 0x20
-#define MODEMSTATUS_CTS 0x10
-#define MODEMSTATUS_RI  0x04
-#define MODEMSTATUS_DCD 0x01
-
-
-/*
- * Channel Command/Address Register (CCAR) Command Codes
- */
-
-#define RTCmd_Null			0x0000
-#define RTCmd_ResetHighestIus		0x1000
-#define RTCmd_TriggerChannelLoadDma	0x2000
-#define RTCmd_TriggerRxDma		0x2800
-#define RTCmd_TriggerTxDma		0x3000
-#define RTCmd_TriggerRxAndTxDma		0x3800
-#define RTCmd_PurgeRxFifo		0x4800
-#define RTCmd_PurgeTxFifo		0x5000
-#define RTCmd_PurgeRxAndTxFifo		0x5800
-#define RTCmd_LoadRcc			0x6800
-#define RTCmd_LoadTcc			0x7000
-#define RTCmd_LoadRccAndTcc		0x7800
-#define RTCmd_LoadTC0			0x8800
-#define RTCmd_LoadTC1			0x9000
-#define RTCmd_LoadTC0AndTC1		0x9800
-#define RTCmd_SerialDataLSBFirst	0xa000
-#define RTCmd_SerialDataMSBFirst	0xa800
-#define RTCmd_SelectBigEndian		0xb000
-#define RTCmd_SelectLittleEndian	0xb800
-
-
-/*
- * DMA Command/Address Register (DCAR) Command Codes
- */
-
-#define DmaCmd_Null			0x0000
-#define DmaCmd_ResetTxChannel		0x1000
-#define DmaCmd_ResetRxChannel		0x1200
-#define DmaCmd_StartTxChannel		0x2000
-#define DmaCmd_StartRxChannel		0x2200
-#define DmaCmd_ContinueTxChannel	0x3000
-#define DmaCmd_ContinueRxChannel	0x3200
-#define DmaCmd_PauseTxChannel		0x4000
-#define DmaCmd_PauseRxChannel		0x4200
-#define DmaCmd_AbortTxChannel		0x5000
-#define DmaCmd_AbortRxChannel		0x5200
-#define DmaCmd_InitTxChannel		0x7000
-#define DmaCmd_InitRxChannel		0x7200
-#define DmaCmd_ResetHighestDmaIus	0x8000
-#define DmaCmd_ResetAllChannels		0x9000
-#define DmaCmd_StartAllChannels		0xa000
-#define DmaCmd_ContinueAllChannels	0xb000
-#define DmaCmd_PauseAllChannels		0xc000
-#define DmaCmd_AbortAllChannels		0xd000
-#define DmaCmd_InitAllChannels		0xf000
-
-#define TCmd_Null			0x0000
-#define TCmd_ClearTxCRC			0x2000
-#define TCmd_SelectTicrTtsaData		0x4000
-#define TCmd_SelectTicrTxFifostatus	0x5000
-#define TCmd_SelectTicrIntLevel		0x6000
-#define TCmd_SelectTicrdma_level		0x7000
-#define TCmd_SendFrame			0x8000
-#define TCmd_SendAbort			0x9000
-#define TCmd_EnableDleInsertion		0xc000
-#define TCmd_DisableDleInsertion	0xd000
-#define TCmd_ClearEofEom		0xe000
-#define TCmd_SetEofEom			0xf000
-
-#define RCmd_Null			0x0000
-#define RCmd_ClearRxCRC			0x2000
-#define RCmd_EnterHuntmode		0x3000
-#define RCmd_SelectRicrRtsaData		0x4000
-#define RCmd_SelectRicrRxFifostatus	0x5000
-#define RCmd_SelectRicrIntLevel		0x6000
-#define RCmd_SelectRicrdma_level		0x7000
-
-/*
- * Bits for enabling and disabling IRQs in Interrupt Control Register (ICR)
- */
- 
-#define RECEIVE_STATUS		BIT5
-#define RECEIVE_DATA		BIT4
-#define TRANSMIT_STATUS		BIT3
-#define TRANSMIT_DATA		BIT2
-#define IO_PIN			BIT1
-#define MISC			BIT0
-
-
-/*
- * Receive status Bits in Receive Command/status Register RCSR
- */
-
-#define RXSTATUS_SHORT_FRAME		BIT8
-#define RXSTATUS_CODE_VIOLATION		BIT8
-#define RXSTATUS_EXITED_HUNT		BIT7
-#define RXSTATUS_IDLE_RECEIVED		BIT6
-#define RXSTATUS_BREAK_RECEIVED		BIT5
-#define RXSTATUS_ABORT_RECEIVED		BIT5
-#define RXSTATUS_RXBOUND		BIT4
-#define RXSTATUS_CRC_ERROR		BIT3
-#define RXSTATUS_FRAMING_ERROR		BIT3
-#define RXSTATUS_ABORT			BIT2
-#define RXSTATUS_PARITY_ERROR		BIT2
-#define RXSTATUS_OVERRUN		BIT1
-#define RXSTATUS_DATA_AVAILABLE		BIT0
-#define RXSTATUS_ALL			0x01f6
-#define usc_UnlatchRxstatusBits(a,b) usc_OutReg( (a), RCSR, (u16)((b) & RXSTATUS_ALL) )
-
-/*
- * Values for setting transmit idle mode in 
- * Transmit Control/status Register (TCSR)
- */
-#define IDLEMODE_FLAGS			0x0000
-#define IDLEMODE_ALT_ONE_ZERO		0x0100
-#define IDLEMODE_ZERO			0x0200
-#define IDLEMODE_ONE			0x0300
-#define IDLEMODE_ALT_MARK_SPACE		0x0500
-#define IDLEMODE_SPACE			0x0600
-#define IDLEMODE_MARK			0x0700
-#define IDLEMODE_MASK			0x0700
-
-/*
- * IUSC revision identifiers
- */
-#define	IUSC_SL1660			0x4d44
-#define IUSC_PRE_SL1660			0x4553
-
-/*
- * Transmit status Bits in Transmit Command/status Register (TCSR)
- */
-
-#define TCSR_PRESERVE			0x0F00
-
-#define TCSR_UNDERWAIT			BIT11
-#define TXSTATUS_PREAMBLE_SENT		BIT7
-#define TXSTATUS_IDLE_SENT		BIT6
-#define TXSTATUS_ABORT_SENT		BIT5
-#define TXSTATUS_EOF_SENT		BIT4
-#define TXSTATUS_EOM_SENT		BIT4
-#define TXSTATUS_CRC_SENT		BIT3
-#define TXSTATUS_ALL_SENT		BIT2
-#define TXSTATUS_UNDERRUN		BIT1
-#define TXSTATUS_FIFO_EMPTY		BIT0
-#define TXSTATUS_ALL			0x00fa
-#define usc_UnlatchTxstatusBits(a,b) usc_OutReg( (a), TCSR, (u16)((a)->tcsr_value + ((b) & 0x00FF)) )
-				
-
-#define MISCSTATUS_RXC_LATCHED		BIT15
-#define MISCSTATUS_RXC			BIT14
-#define MISCSTATUS_TXC_LATCHED		BIT13
-#define MISCSTATUS_TXC			BIT12
-#define MISCSTATUS_RI_LATCHED		BIT11
-#define MISCSTATUS_RI			BIT10
-#define MISCSTATUS_DSR_LATCHED		BIT9
-#define MISCSTATUS_DSR			BIT8
-#define MISCSTATUS_DCD_LATCHED		BIT7
-#define MISCSTATUS_DCD			BIT6
-#define MISCSTATUS_CTS_LATCHED		BIT5
-#define MISCSTATUS_CTS			BIT4
-#define MISCSTATUS_RCC_UNDERRUN		BIT3
-#define MISCSTATUS_DPLL_NO_SYNC		BIT2
-#define MISCSTATUS_BRG1_ZERO		BIT1
-#define MISCSTATUS_BRG0_ZERO		BIT0
-
-#define usc_UnlatchIostatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0xaaa0))
-#define usc_UnlatchMiscstatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0x000f))
-
-#define SICR_RXC_ACTIVE			BIT15
-#define SICR_RXC_INACTIVE		BIT14
-#define SICR_RXC			(BIT15+BIT14)
-#define SICR_TXC_ACTIVE			BIT13
-#define SICR_TXC_INACTIVE		BIT12
-#define SICR_TXC			(BIT13+BIT12)
-#define SICR_RI_ACTIVE			BIT11
-#define SICR_RI_INACTIVE		BIT10
-#define SICR_RI				(BIT11+BIT10)
-#define SICR_DSR_ACTIVE			BIT9
-#define SICR_DSR_INACTIVE		BIT8
-#define SICR_DSR			(BIT9+BIT8)
-#define SICR_DCD_ACTIVE			BIT7
-#define SICR_DCD_INACTIVE		BIT6
-#define SICR_DCD			(BIT7+BIT6)
-#define SICR_CTS_ACTIVE			BIT5
-#define SICR_CTS_INACTIVE		BIT4
-#define SICR_CTS			(BIT5+BIT4)
-#define SICR_RCC_UNDERFLOW		BIT3
-#define SICR_DPLL_NO_SYNC		BIT2
-#define SICR_BRG1_ZERO			BIT1
-#define SICR_BRG0_ZERO			BIT0
-
-void usc_DisableMasterIrqBit( struct mgsl_struct *info );
-void usc_EnableMasterIrqBit( struct mgsl_struct *info );
-void usc_EnableInterrupts( struct mgsl_struct *info, u16 IrqMask );
-void usc_DisableInterrupts( struct mgsl_struct *info, u16 IrqMask );
-void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask );
-
-#define usc_EnableInterrupts( a, b ) \
-	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0xc0 + (b)) )
-
-#define usc_DisableInterrupts( a, b ) \
-	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0x80 + (b)) )
-
-#define usc_EnableMasterIrqBit(a) \
-	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0x0f00) + 0xb000) )
-
-#define usc_DisableMasterIrqBit(a) \
-	usc_OutReg( (a), ICR, (u16)(usc_InReg((a),ICR) & 0x7f00) )
-
-#define usc_ClearIrqPendingBits( a, b ) usc_OutReg( (a), DCCR, 0x40 + (b) )
-
-/*
- * Transmit status Bits in Transmit Control status Register (TCSR)
- * and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0)
- */
-
-#define TXSTATUS_PREAMBLE_SENT	BIT7
-#define TXSTATUS_IDLE_SENT	BIT6
-#define TXSTATUS_ABORT_SENT	BIT5
-#define TXSTATUS_EOF		BIT4
-#define TXSTATUS_CRC_SENT	BIT3
-#define TXSTATUS_ALL_SENT	BIT2
-#define TXSTATUS_UNDERRUN	BIT1
-#define TXSTATUS_FIFO_EMPTY	BIT0
-
-#define DICR_MASTER		BIT15
-#define DICR_TRANSMIT		BIT0
-#define DICR_RECEIVE		BIT1
-
-#define usc_EnableDmaInterrupts(a,b) \
-	usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) | (b)) )
-
-#define usc_DisableDmaInterrupts(a,b) \
-	usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) & ~(b)) )
-
-#define usc_EnableStatusIrqs(a,b) \
-	usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) | (b)) )
-
-#define usc_DisablestatusIrqs(a,b) \
-	usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) & ~(b)) )
-
-/* Transmit status Bits in Transmit Control status Register (TCSR) */
-/* and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) */
-
-
-#define DISABLE_UNCONDITIONAL    0
-#define DISABLE_END_OF_FRAME     1
-#define ENABLE_UNCONDITIONAL     2
-#define ENABLE_AUTO_CTS          3
-#define ENABLE_AUTO_DCD          3
-#define usc_EnableTransmitter(a,b) \
-	usc_OutReg( (a), TMR, (u16)((usc_InReg((a),TMR) & 0xfffc) | (b)) )
-#define usc_EnableReceiver(a,b) \
-	usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) )
-
-static u16  usc_InDmaReg( struct mgsl_struct *info, u16 Port );
-static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
-static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
-
-static u16  usc_InReg( struct mgsl_struct *info, u16 Port );
-static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
-static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
-void usc_RCmd( struct mgsl_struct *info, u16 Cmd );
-void usc_TCmd( struct mgsl_struct *info, u16 Cmd );
-
-#define usc_TCmd(a,b) usc_OutReg((a), TCSR, (u16)((a)->tcsr_value + (b)))
-#define usc_RCmd(a,b) usc_OutReg((a), RCSR, (b))
-
-#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1))
-
-static void usc_process_rxoverrun_sync( struct mgsl_struct *info );
-static void usc_start_receiver( struct mgsl_struct *info );
-static void usc_stop_receiver( struct mgsl_struct *info );
-
-static void usc_start_transmitter( struct mgsl_struct *info );
-static void usc_stop_transmitter( struct mgsl_struct *info );
-static void usc_set_txidle( struct mgsl_struct *info );
-static void usc_load_txfifo( struct mgsl_struct *info );
-
-static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
-static void usc_enable_loopback( struct mgsl_struct *info, int enable );
-
-static void usc_get_serial_signals( struct mgsl_struct *info );
-static void usc_set_serial_signals( struct mgsl_struct *info );
-
-static void usc_reset( struct mgsl_struct *info );
-
-static void usc_set_sync_mode( struct mgsl_struct *info );
-static void usc_set_sdlc_mode( struct mgsl_struct *info );
-static void usc_set_async_mode( struct mgsl_struct *info );
-static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
-
-static void usc_loopback_frame( struct mgsl_struct *info );
-
-static void mgsl_tx_timeout(unsigned long context);
-
-
-static void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
-static void usc_loopmode_insert_request( struct mgsl_struct * info );
-static int usc_loopmode_active( struct mgsl_struct * info);
-static void usc_loopmode_send_done( struct mgsl_struct * info );
-
-static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
-
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(struct mgsl_struct *info);
-static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
-static int  hdlcdev_init(struct mgsl_struct *info);
-static void hdlcdev_exit(struct mgsl_struct *info);
-#endif
-
-/*
- * Defines a BUS descriptor value for the PCI adapter
- * local bus address ranges.
- */
-
-#define BUS_DESCRIPTOR( WrHold, WrDly, RdDly, Nwdd, Nwad, Nxda, Nrdd, Nrad ) \
-(0x00400020 + \
-((WrHold) << 30) + \
-((WrDly)  << 28) + \
-((RdDly)  << 26) + \
-((Nwdd)   << 20) + \
-((Nwad)   << 15) + \
-((Nxda)   << 13) + \
-((Nrdd)   << 11) + \
-((Nrad)   <<  6) )
-
-static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
-
-/*
- * Adapter diagnostic routines
- */
-static bool mgsl_register_test( struct mgsl_struct *info );
-static bool mgsl_irq_test( struct mgsl_struct *info );
-static bool mgsl_dma_test( struct mgsl_struct *info );
-static bool mgsl_memory_test( struct mgsl_struct *info );
-static int mgsl_adapter_test( struct mgsl_struct *info );
-
-/*
- * device and resource management routines
- */
-static int mgsl_claim_resources(struct mgsl_struct *info);
-static void mgsl_release_resources(struct mgsl_struct *info);
-static void mgsl_add_device(struct mgsl_struct *info);
-static struct mgsl_struct* mgsl_allocate_device(void);
-
-/*
- * DMA buffer manupulation functions.
- */
-static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
-static bool mgsl_get_rx_frame( struct mgsl_struct *info );
-static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info );
-static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
-static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
-static int num_free_tx_dma_buffers(struct mgsl_struct *info);
-static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
-static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
-
-/*
- * DMA and Shared Memory buffer allocation and formatting
- */
-static int  mgsl_allocate_dma_buffers(struct mgsl_struct *info);
-static void mgsl_free_dma_buffers(struct mgsl_struct *info);
-static int  mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-static int  mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
-static void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
-static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
-static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
-static bool load_next_tx_holding_buffer(struct mgsl_struct *info);
-static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
-
-/*
- * Bottom half interrupt handlers
- */
-static void mgsl_bh_handler(struct work_struct *work);
-static void mgsl_bh_receive(struct mgsl_struct *info);
-static void mgsl_bh_transmit(struct mgsl_struct *info);
-static void mgsl_bh_status(struct mgsl_struct *info);
-
-/*
- * Interrupt handler routines and dispatch table.
- */
-static void mgsl_isr_null( struct mgsl_struct *info );
-static void mgsl_isr_transmit_data( struct mgsl_struct *info );
-static void mgsl_isr_receive_data( struct mgsl_struct *info );
-static void mgsl_isr_receive_status( struct mgsl_struct *info );
-static void mgsl_isr_transmit_status( struct mgsl_struct *info );
-static void mgsl_isr_io_pin( struct mgsl_struct *info );
-static void mgsl_isr_misc( struct mgsl_struct *info );
-static void mgsl_isr_receive_dma( struct mgsl_struct *info );
-static void mgsl_isr_transmit_dma( struct mgsl_struct *info );
-
-typedef void (*isr_dispatch_func)(struct mgsl_struct *);
-
-static isr_dispatch_func UscIsrTable[7] =
-{
-	mgsl_isr_null,
-	mgsl_isr_misc,
-	mgsl_isr_io_pin,
-	mgsl_isr_transmit_data,
-	mgsl_isr_transmit_status,
-	mgsl_isr_receive_data,
-	mgsl_isr_receive_status
-};
-
-/*
- * ioctl call handlers
- */
-static int tiocmget(struct tty_struct *tty, struct file *file);
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear);
-static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount
-	__user *user_icount);
-static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS  __user *user_params);
-static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS  __user *new_params);
-static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode);
-static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode);
-static int mgsl_txenable(struct mgsl_struct * info, int enable);
-static int mgsl_txabort(struct mgsl_struct * info);
-static int mgsl_rxenable(struct mgsl_struct * info, int enable);
-static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
-static int mgsl_loopmode_send_done( struct mgsl_struct * info );
-
-/* set non-zero on successful registration with PCI subsystem */
-static bool pci_registered;
-
-/*
- * Global linked list of SyncLink devices
- */
-static struct mgsl_struct *mgsl_device_list;
-static int mgsl_device_count;
-
-/*
- * Set this param to non-zero to load eax with the
- * .text section address and breakpoint on module load.
- * This is useful for use with gdb and add-symbol-file command.
- */
-static int break_on_load;
-
-/*
- * Driver major number, defaults to zero to get auto
- * assigned major number. May be forced as module parameter.
- */
-static int ttymajor;
-
-/*
- * Array of user specified options for ISA adapters.
- */
-static int io[MAX_ISA_DEVICES];
-static int irq[MAX_ISA_DEVICES];
-static int dma[MAX_ISA_DEVICES];
-static int debug_level;
-static int maxframe[MAX_TOTAL_DEVICES];
-static int txdmabufs[MAX_TOTAL_DEVICES];
-static int txholdbufs[MAX_TOTAL_DEVICES];
-	
-module_param(break_on_load, bool, 0);
-module_param(ttymajor, int, 0);
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(dma, int, NULL, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-module_param_array(txdmabufs, int, NULL, 0);
-module_param_array(txholdbufs, int, NULL, 0);
-
-static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.38 $";
-
-static int synclink_init_one (struct pci_dev *dev,
-				     const struct pci_device_id *ent);
-static void synclink_remove_one (struct pci_dev *dev);
-
-static struct pci_device_id synclink_pci_tbl[] = {
-	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-static struct pci_driver synclink_pci_driver = {
-	.name		= "synclink",
-	.id_table	= synclink_pci_tbl,
-	.probe		= synclink_init_one,
-	.remove		= __devexit_p(synclink_remove_one),
-};
-
-static struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-
-static void mgsl_change_params(struct mgsl_struct *info);
-static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
-
-/*
- * 1st function defined in .text section. Calling this function in
- * init_module() followed by a breakpoint allows a remote debugger
- * (gdb) to get the .text address for the add-symbol-file command.
- * This allows remote debugging of dynamically loadable modules.
- */
-static void* mgsl_get_text_ptr(void)
-{
-	return mgsl_get_text_ptr;
-}
-
-static inline int mgsl_paranoia_check(struct mgsl_struct *info,
-					char *name, const char *routine)
-{
-#ifdef MGSL_PARANOIA_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for mgsl struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null mgsl_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != MGSL_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#else
-	if (!info)
-		return 1;
-#endif
-	return 0;
-}
-
-/**
- * line discipline callback wrappers
- *
- * The wrappers maintain line discipline references
- * while calling into the line discipline.
- *
- * ldisc_receive_buf  - pass receive data to line discipline
- */
-
-static void ldisc_receive_buf(struct tty_struct *tty,
-			      const __u8 *data, char *flags, int count)
-{
-	struct tty_ldisc *ld;
-	if (!tty)
-		return;
-	ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->receive_buf)
-			ld->ops->receive_buf(tty, data, flags, count);
-		tty_ldisc_deref(ld);
-	}
-}
-
-/* mgsl_stop()		throttle (stop) transmitter
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_stop(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_stop"))
-		return;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("mgsl_stop(%s)\n",info->device_name);	
-		
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (info->tx_enabled)
-	 	usc_stop_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-}	/* end of mgsl_stop() */
-
-/* mgsl_start()		release (start) transmitter
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_start(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_start"))
-		return;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("mgsl_start(%s)\n",info->device_name);	
-		
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (!info->tx_enabled)
-	 	usc_start_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-}	/* end of mgsl_start() */
-
-/*
- * Bottom half work queue access functions
- */
-
-/* mgsl_bh_action()	Return next bottom half action to perform.
- * Return Value:	BH action code or 0 if nothing to do.
- */
-static int mgsl_bh_action(struct mgsl_struct *info)
-{
-	unsigned long flags;
-	int rc = 0;
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	if (info->pending_bh & BH_RECEIVE) {
-		info->pending_bh &= ~BH_RECEIVE;
-		rc = BH_RECEIVE;
-	} else if (info->pending_bh & BH_TRANSMIT) {
-		info->pending_bh &= ~BH_TRANSMIT;
-		rc = BH_TRANSMIT;
-	} else if (info->pending_bh & BH_STATUS) {
-		info->pending_bh &= ~BH_STATUS;
-		rc = BH_STATUS;
-	}
-
-	if (!rc) {
-		/* Mark BH routine as complete */
-		info->bh_running = false;
-		info->bh_requested = false;
-	}
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	return rc;
-}
-
-/*
- * 	Perform bottom half processing of work items queued by ISR.
- */
-static void mgsl_bh_handler(struct work_struct *work)
-{
-	struct mgsl_struct *info =
-		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);
-	
-	info->bh_running = true;
-
-	while((action = mgsl_bh_action(info)) != 0) {
-	
-		/* Process work item */
-		if ( debug_level >= DEBUG_LEVEL_BH )
-			printk( "%s(%d):mgsl_bh_handler() work item action=%d\n",
-				__FILE__,__LINE__,action);
-
-		switch (action) {
-		
-		case BH_RECEIVE:
-			mgsl_bh_receive(info);
-			break;
-		case BH_TRANSMIT:
-			mgsl_bh_transmit(info);
-			break;
-		case BH_STATUS:
-			mgsl_bh_status(info);
-			break;
-		default:
-			/* unknown work item ID */
-			printk("Unknown work item ID=%08X!\n", action);
-			break;
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_handler(%s) exit\n",
-			__FILE__,__LINE__,info->device_name);
-}
-
-static void mgsl_bh_receive(struct mgsl_struct *info)
-{
-	bool (*get_rx_frame)(struct mgsl_struct *info) =
-		(info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_receive(%s)\n",
-			__FILE__,__LINE__,info->device_name);
-	
-	do
-	{
-		if (info->rx_rcc_underrun) {
-			unsigned long flags;
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			usc_start_receiver(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			return;
-		}
-	} while(get_rx_frame(info));
-}
-
-static void mgsl_bh_transmit(struct mgsl_struct *info)
-{
-	struct tty_struct *tty = info->port.tty;
-	unsigned long flags;
-	
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_transmit() entry on %s\n",
-			__FILE__,__LINE__,info->device_name);
-
-	if (tty)
-		tty_wakeup(tty);
-
-	/* if transmitter idle and loopmode_send_done_requested
-	 * then start echoing RxD to TxD
-	 */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	if ( !info->tx_active && info->loopmode_send_done_requested )
- 		usc_loopmode_send_done( info );
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-static void mgsl_bh_status(struct mgsl_struct *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_status() entry on %s\n",
-			__FILE__,__LINE__,info->device_name);
-
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-}
-
-/* mgsl_isr_receive_status()
- * 
- *	Service a receive status interrupt. The type of status
- *	interrupt is indicated by the state of the RCSR.
- *	This is only used for HDLC mode.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_receive_status( struct mgsl_struct *info )
-{
-	u16 status = usc_InReg( info, RCSR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_receive_status status=%04X\n",
-			__FILE__,__LINE__,status);
-			
- 	if ( (status & RXSTATUS_ABORT_RECEIVED) && 
-		info->loopmode_insert_requested &&
- 		usc_loopmode_active(info) )
- 	{
-		++info->icount.rxabort;
-	 	info->loopmode_insert_requested = false;
- 
- 		/* clear CMR:13 to start echoing RxD to TxD */
-		info->cmr_value &= ~BIT13;
- 		usc_OutReg(info, CMR, info->cmr_value);
- 
-		/* disable received abort irq (no longer required) */
-	 	usc_OutReg(info, RICR,
- 			(usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED));
- 	}
-
-	if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) {
-		if (status & RXSTATUS_EXITED_HUNT)
-			info->icount.exithunt++;
-		if (status & RXSTATUS_IDLE_RECEIVED)
-			info->icount.rxidle++;
-		wake_up_interruptible(&info->event_wait_q);
-	}
-
-	if (status & RXSTATUS_OVERRUN){
-		info->icount.rxover++;
-		usc_process_rxoverrun_sync( info );
-	}
-
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
-	usc_UnlatchRxstatusBits( info, status );
-
-}	/* end of mgsl_isr_receive_status() */
-
-/* mgsl_isr_transmit_status()
- * 
- * 	Service a transmit status interrupt
- *	HDLC mode :end of transmit frame
- *	Async mode:all data is sent
- * 	transmit status is indicated by bits in the TCSR.
- * 
- * Arguments:		info	       pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_transmit_status( struct mgsl_struct *info )
-{
-	u16 status = usc_InReg( info, TCSR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_transmit_status status=%04X\n",
-			__FILE__,__LINE__,status);
-	
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-	usc_UnlatchTxstatusBits( info, status );
-	
-	if ( status & (TXSTATUS_UNDERRUN | TXSTATUS_ABORT_SENT) )
-	{
-		/* finished sending HDLC abort. This may leave	*/
-		/* the TxFifo with data from the aborted frame	*/
-		/* so purge the TxFifo. Also shutdown the DMA	*/
-		/* channel in case there is data remaining in 	*/
-		/* the DMA buffer				*/
- 		usc_DmaCmd( info, DmaCmd_ResetTxChannel );
- 		usc_RTCmd( info, RTCmd_PurgeTxFifo );
-	}
- 
-	if ( status & TXSTATUS_EOF_SENT )
-		info->icount.txok++;
-	else if ( status & TXSTATUS_UNDERRUN )
-		info->icount.txunder++;
-	else if ( status & TXSTATUS_ABORT_SENT )
-		info->icount.txabort++;
-	else
-		info->icount.txunder++;
-			
-	info->tx_active = false;
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	del_timer(&info->tx_timer);	
-	
-	if ( info->drop_rts_on_tx_done ) {
-		usc_get_serial_signals( info );
-		if ( info->serial_signals & SerialSignal_RTS ) {
-			info->serial_signals &= ~SerialSignal_RTS;
-			usc_set_serial_signals( info );
-		}
-		info->drop_rts_on_tx_done = false;
-	}
-
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else 
-#endif
-	{
-		if (info->port.tty->stopped || info->port.tty->hw_stopped) {
-			usc_stop_transmitter(info);
-			return;
-		}
-		info->pending_bh |= BH_TRANSMIT;
-	}
-
-}	/* end of mgsl_isr_transmit_status() */
-
-/* mgsl_isr_io_pin()
- * 
- * 	Service an Input/Output pin interrupt. The type of
- * 	interrupt is indicated by bits in the MISR
- * 	
- * Arguments:		info	       pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_io_pin( struct mgsl_struct *info )
-{
- 	struct	mgsl_icount *icount;
-	u16 status = usc_InReg( info, MISR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_io_pin status=%04X\n",
-			__FILE__,__LINE__,status);
-			
-	usc_ClearIrqPendingBits( info, IO_PIN );
-	usc_UnlatchIostatusBits( info, status );
-
-	if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED |
-	              MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) {
-		icount = &info->icount;
-		/* update input line counters */
-		if (status & MISCSTATUS_RI_LATCHED) {
-			if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_RI);
-			icount->rng++;
-			if ( status & MISCSTATUS_RI )
-				info->input_signal_events.ri_up++;	
-			else
-				info->input_signal_events.ri_down++;	
-		}
-		if (status & MISCSTATUS_DSR_LATCHED) {
-			if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_DSR);
-			icount->dsr++;
-			if ( status & MISCSTATUS_DSR )
-				info->input_signal_events.dsr_up++;
-			else
-				info->input_signal_events.dsr_down++;
-		}
-		if (status & MISCSTATUS_DCD_LATCHED) {
-			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_DCD);
-			icount->dcd++;
-			if (status & MISCSTATUS_DCD) {
-				info->input_signal_events.dcd_up++;
-			} else
-				info->input_signal_events.dcd_down++;
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount) {
-				if (status & MISCSTATUS_DCD)
-					netif_carrier_on(info->netdev);
-				else
-					netif_carrier_off(info->netdev);
-			}
-#endif
-		}
-		if (status & MISCSTATUS_CTS_LATCHED)
-		{
-			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_CTS);
-			icount->cts++;
-			if ( status & MISCSTATUS_CTS )
-				info->input_signal_events.cts_up++;
-			else
-				info->input_signal_events.cts_down++;
-		}
-		wake_up_interruptible(&info->status_event_wait_q);
-		wake_up_interruptible(&info->event_wait_q);
-
-		if ( (info->port.flags & ASYNC_CHECK_CD) && 
-		     (status & MISCSTATUS_DCD_LATCHED) ) {
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s CD now %s...", info->device_name,
-				       (status & MISCSTATUS_DCD) ? "on" : "off");
-			if (status & MISCSTATUS_DCD)
-				wake_up_interruptible(&info->port.open_wait);
-			else {
-				if ( debug_level >= DEBUG_LEVEL_ISR )
-					printk("doing serial hangup...");
-				if (info->port.tty)
-					tty_hangup(info->port.tty);
-			}
-		}
-	
-		if ( (info->port.flags & ASYNC_CTS_FLOW) && 
-		     (status & MISCSTATUS_CTS_LATCHED) ) {
-			if (info->port.tty->hw_stopped) {
-				if (status & MISCSTATUS_CTS) {
-					if ( debug_level >= DEBUG_LEVEL_ISR )
-						printk("CTS tx start...");
-					if (info->port.tty)
-						info->port.tty->hw_stopped = 0;
-					usc_start_transmitter(info);
-					info->pending_bh |= BH_TRANSMIT;
-					return;
-				}
-			} else {
-				if (!(status & MISCSTATUS_CTS)) {
-					if ( debug_level >= DEBUG_LEVEL_ISR )
-						printk("CTS tx stop...");
-					if (info->port.tty)
-						info->port.tty->hw_stopped = 1;
-					usc_stop_transmitter(info);
-				}
-			}
-		}
-	}
-
-	info->pending_bh |= BH_STATUS;
-	
-	/* for diagnostics set IRQ flag */
-	if ( status & MISCSTATUS_TXC_LATCHED ){
-		usc_OutReg( info, SICR,
-			(unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) );
-		usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED );
-		info->irq_occurred = true;
-	}
-
-}	/* end of mgsl_isr_io_pin() */
-
-/* mgsl_isr_transmit_data()
- * 
- * 	Service a transmit data interrupt (async mode only).
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_transmit_data( struct mgsl_struct *info )
-{
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n",
-			__FILE__,__LINE__,info->xmit_cnt);
-			
-	usc_ClearIrqPendingBits( info, TRANSMIT_DATA );
-	
-	if (info->port.tty->stopped || info->port.tty->hw_stopped) {
-		usc_stop_transmitter(info);
-		return;
-	}
-	
-	if ( info->xmit_cnt )
-		usc_load_txfifo( info );
-	else
-		info->tx_active = false;
-		
-	if (info->xmit_cnt < WAKEUP_CHARS)
-		info->pending_bh |= BH_TRANSMIT;
-
-}	/* end of mgsl_isr_transmit_data() */
-
-/* mgsl_isr_receive_data()
- * 
- * 	Service a receive data interrupt. This occurs
- * 	when operating in asynchronous interrupt transfer mode.
- *	The receive data FIFO is flushed to the receive data buffers. 
- * 
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_receive_data( struct mgsl_struct *info )
-{
-	int Fifocount;
-	u16 status;
-	int work = 0;
-	unsigned char DataByte;
- 	struct tty_struct *tty = info->port.tty;
- 	struct	mgsl_icount *icount = &info->icount;
-	
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_receive_data\n",
-			__FILE__,__LINE__);
-
-	usc_ClearIrqPendingBits( info, RECEIVE_DATA );
-	
-	/* select FIFO status for RICR readback */
-	usc_RCmd( info, RCmd_SelectRicrRxFifostatus );
-
-	/* clear the Wordstatus bit so that status readback */
-	/* only reflects the status of this byte */
-	usc_OutReg( info, RICR+LSBONLY, (u16)(usc_InReg(info, RICR+LSBONLY) & ~BIT3 ));
-
-	/* flush the receive FIFO */
-
-	while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
-		int flag;
-
-		/* read one byte from RxFIFO */
-		outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
-		      info->io_base + CCAR );
-		DataByte = inb( info->io_base + CCAR );
-
-		/* get the status of the received byte */
-		status = usc_InReg(info, RCSR);
-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
-			usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
-		
-		icount->rx++;
-		
-		flag = 0;
-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
-			printk("rxerr=%04X\n",status);					
-			/* update error statistics */
-			if ( status & RXSTATUS_BREAK_RECEIVED ) {
-				status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR);
-				icount->brk++;
-			} else if (status & RXSTATUS_PARITY_ERROR) 
-				icount->parity++;
-			else if (status & RXSTATUS_FRAMING_ERROR)
-				icount->frame++;
-			else if (status & RXSTATUS_OVERRUN) {
-				/* must issue purge fifo cmd before */
-				/* 16C32 accepts more receive chars */
-				usc_RTCmd(info,RTCmd_PurgeRxFifo);
-				icount->overrun++;
-			}
-
-			/* discard char if tty control flags say so */					
-			if (status & info->ignore_status_mask)
-				continue;
-				
-			status &= info->read_status_mask;
-		
-			if (status & RXSTATUS_BREAK_RECEIVED) {
-				flag = TTY_BREAK;
-				if (info->port.flags & ASYNC_SAK)
-					do_SAK(tty);
-			} else if (status & RXSTATUS_PARITY_ERROR)
-				flag = TTY_PARITY;
-			else if (status & RXSTATUS_FRAMING_ERROR)
-				flag = TTY_FRAME;
-		}	/* end of if (error) */
-		tty_insert_flip_char(tty, DataByte, flag);
-		if (status & RXSTATUS_OVERRUN) {
-			/* Overrun is special, since it's
-			 * reported immediately, and doesn't
-			 * affect the current character
-			 */
-			work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_ISR ) {
-		printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
-			__FILE__,__LINE__,icount->rx,icount->brk,
-			icount->parity,icount->frame,icount->overrun);
-	}
-			
-	if(work)
-		tty_flip_buffer_push(tty);
-}
-
-/* mgsl_isr_misc()
- * 
- * 	Service a miscellaneous interrupt source.
- * 	
- * Arguments:		info		pointer to device extension (instance data)
- * Return Value:	None
- */
-static void mgsl_isr_misc( struct mgsl_struct *info )
-{
-	u16 status = usc_InReg( info, MISR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_misc status=%04X\n",
-			__FILE__,__LINE__,status);
-			
-	if ((status & MISCSTATUS_RCC_UNDERRUN) &&
-	    (info->params.mode == MGSL_MODE_HDLC)) {
-
-		/* turn off receiver and rx DMA */
-		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
-		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
-		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
-		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
-
-		/* schedule BH handler to restart receiver */
-		info->pending_bh |= BH_RECEIVE;
-		info->rx_rcc_underrun = true;
-	}
-
-	usc_ClearIrqPendingBits( info, MISC );
-	usc_UnlatchMiscstatusBits( info, status );
-
-}	/* end of mgsl_isr_misc() */
-
-/* mgsl_isr_null()
- *
- * 	Services undefined interrupt vectors from the
- * 	USC. (hence this function SHOULD never be called)
- * 
- * Arguments:		info		pointer to device extension (instance data)
- * Return Value:	None
- */
-static void mgsl_isr_null( struct mgsl_struct *info )
-{
-
-}	/* end of mgsl_isr_null() */
-
-/* mgsl_isr_receive_dma()
- * 
- * 	Service a receive DMA channel interrupt.
- * 	For this driver there are two sources of receive DMA interrupts
- * 	as identified in the Receive DMA mode Register (RDMR):
- * 
- * 	BIT3	EOA/EOL		End of List, all receive buffers in receive
- * 				buffer list have been filled (no more free buffers
- * 				available). The DMA controller has shut down.
- * 
- * 	BIT2	EOB		End of Buffer. This interrupt occurs when a receive
- * 				DMA buffer is terminated in response to completion
- * 				of a good frame or a frame with errors. The status
- * 				of the frame is stored in the buffer entry in the
- * 				list of receive buffer entries.
- * 
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_receive_dma( struct mgsl_struct *info )
-{
-	u16 status;
-	
-	/* clear interrupt pending and IUS bit for Rx DMA IRQ */
-	usc_OutDmaReg( info, CDIR, BIT9+BIT1 );
-
-	/* Read the receive DMA status to identify interrupt type. */
-	/* This also clears the status bits. */
-	status = usc_InDmaReg( info, RDMR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_receive_dma(%s) status=%04X\n",
-			__FILE__,__LINE__,info->device_name,status);
-			
-	info->pending_bh |= BH_RECEIVE;
-	
-	if ( status & BIT3 ) {
-		info->rx_overflow = true;
-		info->icount.buf_overrun++;
-	}
-
-}	/* end of mgsl_isr_receive_dma() */
-
-/* mgsl_isr_transmit_dma()
- *
- *	This function services a transmit DMA channel interrupt.
- *
- *	For this driver there is one source of transmit DMA interrupts
- *	as identified in the Transmit DMA Mode Register (TDMR):
- *
- *     	BIT2  EOB       End of Buffer. This interrupt occurs when a
- *     			transmit DMA buffer has been emptied.
- *
- *     	The driver maintains enough transmit DMA buffers to hold at least
- *     	one max frame size transmit frame. When operating in a buffered
- *     	transmit mode, there may be enough transmit DMA buffers to hold at
- *     	least two or more max frame size frames. On an EOB condition,
- *     	determine if there are any queued transmit buffers and copy into
- *     	transmit DMA buffers if we have room.
- *
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
-{
-	u16 status;
-
-	/* clear interrupt pending and IUS bit for Tx DMA IRQ */
-	usc_OutDmaReg(info, CDIR, BIT8+BIT0 );
-
-	/* Read the transmit DMA status to identify interrupt type. */
-	/* This also clears the status bits. */
-
-	status = usc_InDmaReg( info, TDMR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	if ( status & BIT2 ) {
-		--info->tx_dma_buffers_used;
-
-		/* if there are transmit frames queued,
-		 *  try to load the next one
-		 */
-		if ( load_next_tx_holding_buffer(info) ) {
-			/* if call returns non-zero value, we have
-			 * at least one free tx holding buffer
-			 */
-			info->pending_bh |= BH_TRANSMIT;
-		}
-	}
-
-}	/* end of mgsl_isr_transmit_dma() */
-
-/* mgsl_interrupt()
- * 
- * 	Interrupt service routine entry point.
- * 	
- * Arguments:
- * 
- * 	irq		interrupt number that caused interrupt
- * 	dev_id		device ID supplied during interrupt registration
- * 	
- * Return Value: None
- */
-static irqreturn_t mgsl_interrupt(int dummy, void *dev_id)
-{
-	struct mgsl_struct *info = dev_id;
-	u16 UscVector;
-	u16 DmaVector;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n",
-			__FILE__, __LINE__, info->irq_level);
-
-	spin_lock(&info->irq_spinlock);
-
-	for(;;) {
-		/* Read the interrupt vectors from hardware. */
-		UscVector = usc_InReg(info, IVR) >> 9;
-		DmaVector = usc_InDmaReg(info, DIVR);
-		
-		if ( debug_level >= DEBUG_LEVEL_ISR )	
-			printk("%s(%d):%s UscVector=%08X DmaVector=%08X\n",
-				__FILE__,__LINE__,info->device_name,UscVector,DmaVector);
-			
-		if ( !UscVector && !DmaVector )
-			break;
-			
-		/* Dispatch interrupt vector */
-		if ( UscVector )
-			(*UscIsrTable[UscVector])(info);
-		else if ( (DmaVector&(BIT10|BIT9)) == BIT10)
-			mgsl_isr_transmit_dma(info);
-		else
-			mgsl_isr_receive_dma(info);
-
-		if ( info->isr_overflow ) {
-			printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n",
-				__FILE__, __LINE__, info->device_name, info->irq_level);
-			usc_DisableMasterIrqBit(info);
-			usc_DisableDmaInterrupts(info,DICR_MASTER);
-			break;
-		}
-	}
-	
-	/* Request bottom half processing if there's something 
-	 * for it to do and the bh is not already running
-	 */
-
-	if ( info->pending_bh && !info->bh_running && !info->bh_requested ) {
-		if ( debug_level >= DEBUG_LEVEL_ISR )	
-			printk("%s(%d):%s queueing bh task.\n",
-				__FILE__,__LINE__,info->device_name);
-		schedule_work(&info->task);
-		info->bh_requested = true;
-	}
-
-	spin_unlock(&info->irq_spinlock);
-	
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n",
-			__FILE__, __LINE__, info->irq_level);
-
-	return IRQ_HANDLED;
-}	/* end of mgsl_interrupt() */
-
-/* startup()
- * 
- * 	Initialize and start device.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise error code
- */
-static int startup(struct mgsl_struct * info)
-{
-	int retval = 0;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name);
-		
-	if (info->port.flags & ASYNC_INITIALIZED)
-		return 0;
-	
-	if (!info->xmit_buf) {
-		/* allocate a page of memory for a transmit buffer */
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-		if (!info->xmit_buf) {
-			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
-				__FILE__,__LINE__,info->device_name);
-			return -ENOMEM;
-		}
-	}
-
-	info->pending_bh = 0;
-	
-	memset(&info->icount, 0, sizeof(info->icount));
-
-	setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info);
-	
-	/* Allocate and claim adapter resources */
-	retval = mgsl_claim_resources(info);
-	
-	/* perform existence check and diagnostics */
-	if ( !retval )
-		retval = mgsl_adapter_test(info);
-		
-	if ( retval ) {
-  		if (capable(CAP_SYS_ADMIN) && info->port.tty)
-			set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-		mgsl_release_resources(info);
-  		return retval;
-  	}
-
-	/* program hardware for current parameters */
-	mgsl_change_params(info);
-	
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags |= ASYNC_INITIALIZED;
-	
-	return 0;
-	
-}	/* end of startup() */
-
-/* shutdown()
- *
- * Called by mgsl_close() and mgsl_hangup() to shutdown hardware
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void shutdown(struct mgsl_struct * info)
-{
-	unsigned long flags;
-	
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_shutdown(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	/* clear status wait queue because status changes */
-	/* can't happen after shutting down the hardware */
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-
-	del_timer_sync(&info->tx_timer);
-
-	if (info->xmit_buf) {
-		free_page((unsigned long) info->xmit_buf);
-		info->xmit_buf = NULL;
-	}
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_DisableMasterIrqBit(info);
-	usc_stop_receiver(info);
-	usc_stop_transmitter(info);
-	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
-		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
-	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
-	
-	/* Disable DMAEN (Port 7, Bit 14) */
-	/* This disconnects the DMA request signal from the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
-	
-	/* Disable INTEN (Port 6, Bit12) */
-	/* This disconnects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));
-	
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
- 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		usc_set_serial_signals(info);
-	}
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	mgsl_release_resources(info);	
-	
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-	
-}	/* end of shutdown() */
-
-static void mgsl_program_hw(struct mgsl_struct *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
-	usc_stop_receiver(info);
-	usc_stop_transmitter(info);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	
-	if (info->params.mode == MGSL_MODE_HDLC ||
-	    info->params.mode == MGSL_MODE_RAW ||
-	    info->netcount)
-		usc_set_sync_mode(info);
-	else
-		usc_set_async_mode(info);
-		
-	usc_set_serial_signals(info);
-	
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-
-	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);		
-	usc_EnableInterrupts(info, IO_PIN);
-	usc_get_serial_signals(info);
-		
-	if (info->netcount || info->port.tty->termios->c_cflag & CREAD)
-		usc_start_receiver(info);
-		
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-/* Reconfigure adapter based on new parameters
- */
-static void mgsl_change_params(struct mgsl_struct *info)
-{
-	unsigned cflag;
-	int bits_per_char;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_change_params(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	cflag = info->port.tty->termios->c_cflag;
-
-	/* if B0 rate (hangup) specified then negate DTR and RTS */
-	/* otherwise assert DTR and RTS */
- 	if (cflag & CBAUD)
-		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-	
-	/* byte size and parity */
-	
-	switch (cflag & CSIZE) {
-	      case CS5: info->params.data_bits = 5; break;
-	      case CS6: info->params.data_bits = 6; break;
-	      case CS7: info->params.data_bits = 7; break;
-	      case CS8: info->params.data_bits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  info->params.data_bits = 7; break;
-	      }
-	      
-	if (cflag & CSTOPB)
-		info->params.stop_bits = 2;
-	else
-		info->params.stop_bits = 1;
-
-	info->params.parity = ASYNC_PARITY_NONE;
-	if (cflag & PARENB) {
-		if (cflag & PARODD)
-			info->params.parity = ASYNC_PARITY_ODD;
-		else
-			info->params.parity = ASYNC_PARITY_EVEN;
-#ifdef CMSPAR
-		if (cflag & CMSPAR)
-			info->params.parity = ASYNC_PARITY_SPACE;
-#endif
-	}
-
-	/* calculate number of jiffies to transmit a full
-	 * FIFO (32 bytes) at specified data rate
-	 */
-	bits_per_char = info->params.data_bits + 
-			info->params.stop_bits + 1;
-
-	/* if port data rate is set to 460800 or less then
-	 * allow tty settings to override, otherwise keep the
-	 * current data rate.
-	 */
-	if (info->params.data_rate <= 460800)
-		info->params.data_rate = tty_get_baud_rate(info->port.tty);
-	
-	if ( info->params.data_rate ) {
-		info->timeout = (32*HZ*bits_per_char) / 
-				info->params.data_rate;
-	}
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-		
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/* process tty input control flags */
-	
-	info->read_status_mask = RXSTATUS_OVERRUN;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;
- 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- 		info->read_status_mask |= RXSTATUS_BREAK_RECEIVED;
-	
-	if (I_IGNPAR(info->port.tty))
-		info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED;
-		/* If ignoring parity and break indicators, ignore 
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty))
-			info->ignore_status_mask |= RXSTATUS_OVERRUN;
-	}
-
-	mgsl_program_hw(info);
-
-}	/* end of mgsl_change_params() */
-
-/* mgsl_put_char()
- * 
- * 	Add a character to the transmit buffer.
- * 	
- * Arguments:		tty	pointer to tty information structure
- * 			ch	character to add to transmit buffer
- * 		
- * Return Value:	None
- */
-static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (debug_level >= DEBUG_LEVEL_INFO) {
-		printk(KERN_DEBUG "%s(%d):mgsl_put_char(%d) on %s\n",
-			__FILE__, __LINE__, ch, info->device_name);
-	}		
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->irq_spinlock, flags);
-	
-	if ((info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active) {
-		if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
-			info->xmit_buf[info->xmit_head++] = ch;
-			info->xmit_head &= SERIAL_XMIT_SIZE-1;
-			info->xmit_cnt++;
-			ret = 1;
-		}
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	return ret;
-	
-}	/* end of mgsl_put_char() */
-
-/* mgsl_flush_chars()
- * 
- * 	Enable transmitter so remaining characters in the
- * 	transmit buffer are sent.
- * 	
- * Arguments:		tty	pointer to tty information structure
- * Return Value:	None
- */
-static void mgsl_flush_chars(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-				
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n",
-			__FILE__,__LINE__,info->device_name,info->xmit_cnt);
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !info->xmit_buf)
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n",
-			__FILE__,__LINE__,info->device_name );
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
-	if (!info->tx_active) {
-		if ( (info->params.mode == MGSL_MODE_HDLC ||
-			info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) {
-			/* operating in synchronous (frame oriented) mode */
-			/* copy data from circular xmit_buf to */
-			/* transmit DMA buffer. */
-			mgsl_load_tx_dma_buffer(info,
-				 info->xmit_buf,info->xmit_cnt);
-		}
-	 	usc_start_transmitter(info);
-	}
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-}	/* end of mgsl_flush_chars() */
-
-/* mgsl_write()
- * 
- * 	Send a block of data
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty information structure
- * 	buf		pointer to buffer containing send data
- * 	count		size of send data in bytes
- * 	
- * Return Value:	number of characters written
- */
-static int mgsl_write(struct tty_struct * tty,
-		    const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_write(%s) count=%d\n",
-			__FILE__,__LINE__,info->device_name,count);
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
-		goto cleanup;
-
-	if (!info->xmit_buf)
-		goto cleanup;
-
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-			info->params.mode == MGSL_MODE_RAW ) {
-		/* operating in synchronous (frame oriented) mode */
-		/* operating in synchronous (frame oriented) mode */
-		if (info->tx_active) {
-
-			if ( info->params.mode == MGSL_MODE_HDLC ) {
-				ret = 0;
-				goto cleanup;
-			}
-			/* transmitter is actively sending data -
-			 * if we have multiple transmit dma and
-			 * holding buffers, attempt to queue this
-			 * frame for transmission at a later time.
-			 */
-			if (info->tx_holding_count >= info->num_tx_holding_buffers ) {
-				/* no tx holding buffers available */
-				ret = 0;
-				goto cleanup;
-			}
-
-			/* queue transmit frame request */
-			ret = count;
-			save_tx_buffer_request(info,buf,count);
-
-			/* if we have sufficient tx dma buffers,
-			 * load the next buffered tx request
-			 */
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			load_next_tx_holding_buffer(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			goto cleanup;
-		}
-	
-		/* if operating in HDLC LoopMode and the adapter  */
-		/* has yet to be inserted into the loop, we can't */
-		/* transmit					  */
-
-		if ( (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) &&
-			!usc_loopmode_active(info) )
-		{
-			ret = 0;
-			goto cleanup;
-		}
-
-		if ( info->xmit_cnt ) {
-			/* Send accumulated from send_char() calls */
-			/* as frame and wait before accepting more data. */
-			ret = 0;
-			
-			/* copy data from circular xmit_buf to */
-			/* transmit DMA buffer. */
-			mgsl_load_tx_dma_buffer(info,
-				info->xmit_buf,info->xmit_cnt);
-			if ( debug_level >= DEBUG_LEVEL_INFO )
-				printk( "%s(%d):mgsl_write(%s) sync xmit_cnt flushing\n",
-					__FILE__,__LINE__,info->device_name);
-		} else {
-			if ( debug_level >= DEBUG_LEVEL_INFO )
-				printk( "%s(%d):mgsl_write(%s) sync transmit accepted\n",
-					__FILE__,__LINE__,info->device_name);
-			ret = count;
-			info->xmit_cnt = count;
-			mgsl_load_tx_dma_buffer(info,buf,count);
-		}
-	} else {
-		while (1) {
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			c = min_t(int, count,
-				min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				    SERIAL_XMIT_SIZE - info->xmit_head));
-			if (c <= 0) {
-				spin_unlock_irqrestore(&info->irq_spinlock,flags);
-				break;
-			}
-			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-			info->xmit_head = ((info->xmit_head + c) &
-					   (SERIAL_XMIT_SIZE-1));
-			info->xmit_cnt += c;
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			buf += c;
-			count -= c;
-			ret += c;
-		}
-	}	
-	
- 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!info->tx_active)
-		 	usc_start_transmitter(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
- 	}
-cleanup:	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_write(%s) returning=%d\n",
-			__FILE__,__LINE__,info->device_name,ret);
-			
-	return ret;
-	
-}	/* end of mgsl_write() */
-
-/* mgsl_write_room()
- *
- *	Return the count of free bytes in transmit buffer
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static int mgsl_write_room(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	int	ret;
-				
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room"))
-		return 0;
-	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_write_room(%s)=%d\n",
-			 __FILE__,__LINE__, info->device_name,ret );
-			 
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		/* operating in synchronous (frame oriented) mode */
-		if ( info->tx_active )
-			return 0;
-		else
-			return HDLC_MAX_FRAME_SIZE;
-	}
-	
-	return ret;
-	
-}	/* end of mgsl_write_room() */
-
-/* mgsl_chars_in_buffer()
- *
- *	Return the count of bytes in transmit buffer
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static int mgsl_chars_in_buffer(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-			 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_chars_in_buffer(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_chars_in_buffer"))
-		return 0;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_chars_in_buffer(%s)=%d\n",
-			 __FILE__,__LINE__, info->device_name,info->xmit_cnt );
-			 
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		/* operating in synchronous (frame oriented) mode */
-		if ( info->tx_active )
-			return info->max_frame_size;
-		else
-			return 0;
-	}
-			 
-	return info->xmit_cnt;
-}	/* end of mgsl_chars_in_buffer() */
-
-/* mgsl_flush_buffer()
- *
- *	Discard all data in the send buffer
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_flush_buffer(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_flush_buffer(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_buffer"))
-		return;
-		
-	spin_lock_irqsave(&info->irq_spinlock,flags); 
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	del_timer(&info->tx_timer);	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	tty_wakeup(tty);
-}
-
-/* mgsl_send_xchar()
- *
- *	Send a high-priority XON/XOFF character
- * 	
- * Arguments:		tty	pointer to tty info structure
- *			ch	character to send
- * Return Value:	None
- */
-static void mgsl_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_send_xchar(%s,%d)\n",
-			 __FILE__,__LINE__, info->device_name, ch );
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_send_xchar"))
-		return;
-
-	info->x_char = ch;
-	if (ch) {
-		/* Make sure transmit interrupts are on */
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!info->tx_enabled)
-		 	usc_start_transmitter(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-}	/* end of mgsl_send_xchar() */
-
-/* mgsl_throttle()
- * 
- * 	Signal remote device to throttle send data (our receive data)
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_throttle(struct tty_struct * tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_throttle(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_throttle"))
-		return;
-	
-	if (I_IXOFF(tty))
-		mgsl_send_xchar(tty, STOP_CHAR(tty));
- 
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		info->serial_signals &= ~SerialSignal_RTS;
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-}	/* end of mgsl_throttle() */
-
-/* mgsl_unthrottle()
- * 
- * 	Signal remote device to stop throttling send data (our receive data)
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_unthrottle(struct tty_struct * tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_unthrottle(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_unthrottle"))
-		return;
-	
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			mgsl_send_xchar(tty, START_CHAR(tty));
-	}
-	
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		info->serial_signals |= SerialSignal_RTS;
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-	
-}	/* end of mgsl_unthrottle() */
-
-/* mgsl_get_stats()
- * 
- * 	get the current serial parameters information
- *
- * Arguments:	info		pointer to device instance data
- * 		user_icount	pointer to buffer to hold returned stats
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount)
-{
-	int err;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_get_params(%s)\n",
-			 __FILE__,__LINE__, info->device_name);
-			
-	if (!user_icount) {
-		memset(&info->icount, 0, sizeof(info->icount));
-	} else {
-		mutex_lock(&info->port.mutex);
-		COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
-		mutex_unlock(&info->port.mutex);
-		if (err)
-			return -EFAULT;
-	}
-	
-	return 0;
-	
-}	/* end of mgsl_get_stats() */
-
-/* mgsl_get_params()
- * 
- * 	get the current serial parameters information
- *
- * Arguments:	info		pointer to device instance data
- * 		user_params	pointer to buffer to hold returned params
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params)
-{
-	int err;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_get_params(%s)\n",
-			 __FILE__,__LINE__, info->device_name);
-			
-	mutex_lock(&info->port.mutex);
-	COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
-	mutex_unlock(&info->port.mutex);
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-	
-	return 0;
-	
-}	/* end of mgsl_get_params() */
-
-/* mgsl_set_params()
- * 
- * 	set the serial parameters
- * 	
- * Arguments:
- * 
- * 	info		pointer to device instance data
- * 	new_params	user buffer containing new serial params
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params)
-{
- 	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-	int err;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_set_params %s\n", __FILE__,__LINE__,
-			info->device_name );
-	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):mgsl_set_params(%s) user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-	
-	mutex_lock(&info->port.mutex);
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
- 	mgsl_change_params(info);
-	mutex_unlock(&info->port.mutex);
-	
-	return 0;
-	
-}	/* end of mgsl_set_params() */
-
-/* mgsl_get_txidle()
- * 
- * 	get the current transmit idle mode
- *
- * Arguments:	info		pointer to device instance data
- * 		idle_mode	pointer to buffer to hold returned idle mode
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode)
-{
-	int err;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_get_txidle(%s)=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->idle_mode);
-			
-	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):mgsl_get_txidle(%s) user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-	
-	return 0;
-	
-}	/* end of mgsl_get_txidle() */
-
-/* mgsl_set_txidle()	service ioctl to set transmit idle mode
- * 	
- * Arguments:	 	info		pointer to device instance data
- * 			idle_mode	new idle mode
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_set_txidle(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, idle_mode );
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	info->idle_mode = idle_mode;
-	usc_set_txidle( info );
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_set_txidle() */
-
-/* mgsl_txenable()
- * 
- * 	enable or disable the transmitter
- * 	
- * Arguments:
- * 
- * 	info		pointer to device instance data
- * 	enable		1 = enable, 0 = disable
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_txenable(struct mgsl_struct * info, int enable)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_txenable(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, enable);
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if ( enable ) {
-		if ( !info->tx_enabled ) {
-
-			usc_start_transmitter(info);
-			/*--------------------------------------------------
-			 * if HDLC/SDLC Loop mode, attempt to insert the
-			 * station in the 'loop' by setting CMR:13. Upon
-			 * receipt of the next GoAhead (RxAbort) sequence,
-			 * the OnLoop indicator (CCSR:7) should go active
-			 * to indicate that we are on the loop
-			 *--------------------------------------------------*/
-			if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
-				usc_loopmode_insert_request( info );
-		}
-	} else {
-		if ( info->tx_enabled )
-			usc_stop_transmitter(info);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_txenable() */
-
-/* mgsl_txabort()	abort send HDLC frame
- * 	
- * Arguments:	 	info		pointer to device instance data
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_txabort(struct mgsl_struct * info)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_txabort(%s)\n", __FILE__,__LINE__,
-			info->device_name);
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC )
-	{
-		if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
-			usc_loopmode_cancel_transmit( info );
-		else
-			usc_TCmd(info,TCmd_SendAbort);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_txabort() */
-
-/* mgsl_rxenable() 	enable or disable the receiver
- * 	
- * Arguments:	 	info		pointer to device instance data
- * 			enable		1 = enable, 0 = disable
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_rxenable(struct mgsl_struct * info, int enable)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_rxenable(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, enable);
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if ( enable ) {
-		if ( !info->rx_enabled )
-			usc_start_receiver(info);
-	} else {
-		if ( info->rx_enabled )
-			usc_stop_receiver(info);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_rxenable() */
-
-/* mgsl_wait_event() 	wait for specified event to occur
- * 	
- * Arguments:	 	info	pointer to device instance data
- * 			mask	pointer to bitmask of events to wait for
- * Return Value:	0 	if successful and bit mask updated with
- *				of events triggerred,
- * 			otherwise error code
- */
-static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
-{
- 	unsigned long flags;
-	int s;
-	int rc=0;
-	struct mgsl_icount cprev, cnow;
-	int events;
-	int mask;
-	struct	_input_signal_events oldsigs, newsigs;
-	DECLARE_WAITQUEUE(wait, current);
-
-	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
-	if (rc) {
-		return  -EFAULT;
-	}
-		 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_wait_event(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, mask);
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	/* return immediately if state matches requested events */
-	usc_get_serial_signals(info);
-	s = info->serial_signals;
-	events = mask &
-		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
- 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
-		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
-		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
-	if (events) {
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		goto exit;
-	}
-
-	/* save current irq counts */
-	cprev = info->icount;
-	oldsigs = info->input_signal_events;
-	
-	/* enable hunt and idle irqs if needed */
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		u16 oldreg = usc_InReg(info,RICR);
-		u16 newreg = oldreg +
-			 (mask & MgslEvent_ExitHuntMode ? RXSTATUS_EXITED_HUNT:0) +
-			 (mask & MgslEvent_IdleReceived ? RXSTATUS_IDLE_RECEIVED:0);
-		if (oldreg != newreg)
-			usc_OutReg(info, RICR, newreg);
-	}
-	
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&info->event_wait_q, &wait);
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-			
-		/* get current irq counts */
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		cnow = info->icount;
-		newsigs = info->input_signal_events;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
-		    newsigs.dsr_down == oldsigs.dsr_down &&
-		    newsigs.dcd_up   == oldsigs.dcd_up   &&
-		    newsigs.dcd_down == oldsigs.dcd_down &&
-		    newsigs.cts_up   == oldsigs.cts_up   &&
-		    newsigs.cts_down == oldsigs.cts_down &&
-		    newsigs.ri_up    == oldsigs.ri_up    &&
-		    newsigs.ri_down  == oldsigs.ri_down  &&
-		    cnow.exithunt    == cprev.exithunt   &&
-		    cnow.rxidle      == cprev.rxidle) {
-			rc = -EIO;
-			break;
-		}
-
-		events = mask &
-			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
-			(newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
-			(newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
-			(newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
-			(newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
-			(newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
-			(newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
-			(newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
-			(cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
-			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
-		if (events)
-			break;
-		
-		cprev = cnow;
-		oldsigs = newsigs;
-	}
-	
-	remove_wait_queue(&info->event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!waitqueue_active(&info->event_wait_q)) {
-			/* disable enable exit hunt mode/idle rcvd IRQs */
-			usc_OutReg(info, RICR, usc_InReg(info,RICR) &
-				~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED));
-		}
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-exit:
-	if ( rc == 0 )
-		PUT_USER(rc, events, mask_ptr);
-		
-	return rc;
-	
-}	/* end of mgsl_wait_event() */
-
-static int modem_input_wait(struct mgsl_struct *info,int arg)
-{
- 	unsigned long flags;
-	int rc;
-	struct mgsl_icount cprev, cnow;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* save current irq counts */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	cprev = info->icount;
-	add_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get new irq counts */
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		cnow = info->icount;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-			rc = -EIO;
-			break;
-		}
-
-		/* check for change in caller specified modem input */
-		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
-		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
-		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
-		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
-			rc = 0;
-			break;
-		}
-
-		cprev = cnow;
-	}
-	remove_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-	return rc;
-}
-
-/* return the state of the serial control and status signals
- */
-static int tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned int result;
- 	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
-		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
-		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
-		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
-		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
-		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmget() value=%08X\n",
-			 __FILE__,__LINE__, info->device_name, result );
-	return result;
-}
-
-/* set modem control signals (DTR/RTS)
- */
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	struct mgsl_struct *info = tty->driver_data;
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmset(%x,%x)\n",
-			__FILE__,__LINE__,info->device_name, set, clear);
-
-	if (set & TIOCM_RTS)
-		info->serial_signals |= SerialSignal_RTS;
-	if (set & TIOCM_DTR)
-		info->serial_signals |= SerialSignal_DTR;
-	if (clear & TIOCM_RTS)
-		info->serial_signals &= ~SerialSignal_RTS;
-	if (clear & TIOCM_DTR)
-		info->serial_signals &= ~SerialSignal_DTR;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	usc_set_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return 0;
-}
-
-/* mgsl_break()		Set or clear transmit break condition
- *
- * Arguments:		tty		pointer to tty instance data
- *			break_state	-1=set break condition, 0=clear
- * Return Value:	error code
- */
-static int mgsl_break(struct tty_struct *tty, int break_state)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_break(%s,%d)\n",
-			 __FILE__,__LINE__, info->device_name, break_state);
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
-		return -EINVAL;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	if (break_state == -1)
-		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) | BIT7));
-	else 
-		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_break() */
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- *     RI where only 0->1 is counted.
- */
-static int msgl_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-
-{
-	struct mgsl_struct * info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-/* mgsl_ioctl()	Service an IOCTL request
- * 	
- * Arguments:
- * 
- * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
- * 	cmd	IOCTL command code
- * 	arg	command argument/context
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->device_name, cmd );
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	return mgsl_ioctl_common(info, cmd, arg);
-}
-
-static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	
-	switch (cmd) {
-		case MGSL_IOCGPARAMS:
-			return mgsl_get_params(info, argp);
-		case MGSL_IOCSPARAMS:
-			return mgsl_set_params(info, argp);
-		case MGSL_IOCGTXIDLE:
-			return mgsl_get_txidle(info, argp);
-		case MGSL_IOCSTXIDLE:
-			return mgsl_set_txidle(info,(int)arg);
-		case MGSL_IOCTXENABLE:
-			return mgsl_txenable(info,(int)arg);
-		case MGSL_IOCRXENABLE:
-			return mgsl_rxenable(info,(int)arg);
-		case MGSL_IOCTXABORT:
-			return mgsl_txabort(info);
-		case MGSL_IOCGSTATS:
-			return mgsl_get_stats(info, argp);
-		case MGSL_IOCWAITEVENT:
-			return mgsl_wait_event(info, argp);
-		case MGSL_IOCLOOPTXDONE:
-			return mgsl_loopmode_send_done(info);
-		/* Wait for modem input (DCD,RI,DSR,CTS) change
-		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
-		 */
-		case TIOCMIWAIT:
-			return modem_input_wait(info,(int)arg);
-
-		default:
-			return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-/* mgsl_set_termios()
- * 
- * 	Set new termios settings
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty structure
- * 	termios		pointer to buffer to hold returned old termios
- * 	
- * Return Value:		None
- */
-static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
-			tty->driver->name );
-	
-	mgsl_change_params(info);
-
-	/* Handle transition to B0 status */
-	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-	
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
-		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) || 
- 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->serial_signals |= SerialSignal_RTS;
- 		}
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-	
-	/* Handle turning off CRTSCTS */
-	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		mgsl_start(tty);
-	}
-
-}	/* end of mgsl_set_termios() */
-
-/* mgsl_close()
- * 
- * 	Called when port is closed. Wait for remaining data to be
- * 	sent. Disable port and free resources.
- * 	
- * Arguments:
- * 
- * 	tty	pointer to open tty structure
- * 	filp	pointer to open file object
- * 	
- * Return Value:	None
- */
-static void mgsl_close(struct tty_struct *tty, struct file * filp)
-{
-	struct mgsl_struct * info = tty->driver_data;
-
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_close"))
-		return;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->port.count);
-
-	if (tty_port_close_start(&info->port, tty, filp) == 0)			 
-		goto cleanup;
-
-	mutex_lock(&info->port.mutex);
- 	if (info->port.flags & ASYNC_INITIALIZED)
- 		mgsl_wait_until_sent(tty, info->timeout);
-	mgsl_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	shutdown(info);
-	mutex_unlock(&info->port.mutex);
-
-	tty_port_close_end(&info->port, tty);	
-	info->port.tty = NULL;
-cleanup:			
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__,
-			tty->driver->name, info->port.count);
-			
-}	/* end of mgsl_close() */
-
-/* mgsl_wait_until_sent()
- *
- *	Wait until the transmitter is empty.
- *
- * Arguments:
- *
- *	tty		pointer to tty info structure
- *	timeout		time to wait for send completion
- *
- * Return Value:	None
- */
-static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-
-	if (!info )
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_wait_until_sent(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-      
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_wait_until_sent"))
-		return;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		goto exit;
-	 
-	orig_jiffies = jiffies;
-      
-	/* Set check interval to 1/5 of estimated time to
-	 * send a character, and make it at least 1. The check
-	 * interval should also be less than the timeout.
-	 * Note: use tight timings here to satisfy the NIST-PCTS.
-	 */ 
-
-	if ( info->params.data_rate ) {
-	       	char_time = info->timeout/(32 * 5);
-		if (!char_time)
-			char_time++;
-	} else
-		char_time = 1;
-		
-	if (timeout)
-		char_time = min_t(unsigned long, char_time, timeout);
-		
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		while (info->tx_active) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	} else {
-		while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) &&
-			info->tx_enabled) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	}
-      
-exit:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_wait_until_sent(%s) exit\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-}	/* end of mgsl_wait_until_sent() */
-
-/* mgsl_hangup()
- *
- *	Called by tty_hangup() when a hangup is signaled.
- *	This is the same as to closing all open files for the port.
- *
- * Arguments:		tty	pointer to associated tty object
- * Return Value:	None
- */
-static void mgsl_hangup(struct tty_struct *tty)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_hangup(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_hangup"))
-		return;
-
-	mgsl_flush_buffer(tty);
-	shutdown(info);
-	
-	info->port.count = 0;	
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-
-	wake_up_interruptible(&info->port.open_wait);
-	
-}	/* end of mgsl_hangup() */
-
-/*
- * carrier_raised()
- *
- *	Return true if carrier is raised
- */
-
-static int carrier_raised(struct tty_port *port)
-{
-	unsigned long flags;
-	struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
-	
-	spin_lock_irqsave(&info->irq_spinlock, flags);
- 	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
-}
-
-static void dtr_rts(struct tty_port *port, int on)
-{
-	struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (on)
-		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
- 	usc_set_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-
-/* block_til_ready()
- * 
- * 	Block the current process until the specified port
- * 	is ready to be opened.
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty info structure
- * 	filp		pointer to open file object
- * 	info		pointer to device instance data
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-			   struct mgsl_struct *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	bool		do_clocal = false;
-	bool		extra_count = false;
-	unsigned long	flags;
-	int		dcd;
-	struct tty_port *port = &info->port;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):block_til_ready on %s\n",
-			 __FILE__,__LINE__, tty->driver->name );
-
-	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-		/* nonblock mode is set or port is not enabled */
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = true;
-
-	/* Wait for carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * mgsl_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	 
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):block_til_ready before block on %s count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-
-	spin_lock_irqsave(&info->irq_spinlock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	port->blocked_open++;
-	
-	while (1) {
-		if (tty->termios->c_cflag & CBAUD)
-			tty_port_raise_dtr_rts(port);
-		
-		set_current_state(TASK_INTERRUPTIBLE);
-		
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
-			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-					-EAGAIN : -ERESTARTSYS;
-			break;
-		}
-		
-		dcd = tty_port_carrier_raised(&info->port);
-		
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
- 			break;
-			
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):block_til_ready blocking on %s count=%d\n",
-				 __FILE__,__LINE__, tty->driver->name, port->count );
-				 
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-	
-	/* FIXME: Racy on hangup during close wait */
-	if (extra_count)
-		port->count++;
-	port->blocked_open--;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-			 
-	if (!retval)
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		
-	return retval;
-	
-}	/* end of block_til_ready() */
-
-/* mgsl_open()
- *
- *	Called when a port is opened.  Init and enable port.
- *	Perform serial-specific initialization for the tty structure.
- *
- * Arguments:		tty	pointer to tty info structure
- *			filp	associated file pointer
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_open(struct tty_struct *tty, struct file * filp)
-{
-	struct mgsl_struct	*info;
-	int 			retval, line;
-	unsigned long flags;
-
-	/* verify range of specified line number */	
-	line = tty->index;
-	if ((line < 0) || (line >= mgsl_device_count)) {
-		printk("%s(%d):mgsl_open with invalid line #%d.\n",
-			__FILE__,__LINE__,line);
-		return -ENODEV;
-	}
-
-	/* find the info structure for the specified line */
-	info = mgsl_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
-		return -ENODEV;
-	
-	tty->driver_data = info;
-	info->port.tty = tty;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
-			 __FILE__,__LINE__,tty->driver->name, info->port.count);
-
-	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-		if (info->port.flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->port.close_wait);
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-	
-	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->netcount) {
-		retval = -EBUSY;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		goto cleanup;
-	}
-	info->port.count++;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	if (info->port.count == 1) {
-		/* 1st open on this device, init hardware */
-		retval = startup(info);
-		if (retval < 0)
-			goto cleanup;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):block_til_ready(%s) returned %d\n",
-				 __FILE__,__LINE__, info->device_name, retval);
-		goto cleanup;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_open(%s) success\n",
-			 __FILE__,__LINE__, info->device_name);
-	retval = 0;
-	
-cleanup:			
-	if (retval) {
-		if (tty->count == 1)
-			info->port.tty = NULL; /* tty layer will release tty struct */
-		if(info->port.count)
-			info->port.count--;
-	}
-	
-	return retval;
-	
-}	/* end of mgsl_open() */
-
-/*
- * /proc fs routines....
- */
-
-static inline void line_info(struct seq_file *m, struct mgsl_struct *info)
-{
-	char	stat_buf[30];
-	unsigned long flags;
-
-	if (info->bus_type == MGSL_BUS_TYPE_PCI) {
-		seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
-			info->device_name, info->io_base, info->irq_level,
-			info->phys_memory_base, info->phys_lcr_base);
-	} else {
-		seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d",
-			info->device_name, info->io_base, 
-			info->irq_level, info->dma_level);
-	}
-
-	/* output current serial signal states */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (info->serial_signals & SerialSignal_RTS)
-		strcat(stat_buf, "|RTS");
-	if (info->serial_signals & SerialSignal_CTS)
-		strcat(stat_buf, "|CTS");
-	if (info->serial_signals & SerialSignal_DTR)
-		strcat(stat_buf, "|DTR");
-	if (info->serial_signals & SerialSignal_DSR)
-		strcat(stat_buf, "|DSR");
-	if (info->serial_signals & SerialSignal_DCD)
-		strcat(stat_buf, "|CD");
-	if (info->serial_signals & SerialSignal_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->params.mode == MGSL_MODE_HDLC ||
-	    info->params.mode == MGSL_MODE_RAW ) {
-		seq_printf(m, " HDLC txok:%d rxok:%d",
-			      info->icount.txok, info->icount.rxok);
-		if (info->icount.txunder)
-			seq_printf(m, " txunder:%d", info->icount.txunder);
-		if (info->icount.txabort)
-			seq_printf(m, " txabort:%d", info->icount.txabort);
-		if (info->icount.rxshort)
-			seq_printf(m, " rxshort:%d", info->icount.rxshort);
-		if (info->icount.rxlong)
-			seq_printf(m, " rxlong:%d", info->icount.rxlong);
-		if (info->icount.rxover)
-			seq_printf(m, " rxover:%d", info->icount.rxover);
-		if (info->icount.rxcrc)
-			seq_printf(m, " rxcrc:%d", info->icount.rxcrc);
-	} else {
-		seq_printf(m, " ASYNC tx:%d rx:%d",
-			      info->icount.tx, info->icount.rx);
-		if (info->icount.frame)
-			seq_printf(m, " fe:%d", info->icount.frame);
-		if (info->icount.parity)
-			seq_printf(m, " pe:%d", info->icount.parity);
-		if (info->icount.brk)
-			seq_printf(m, " brk:%d", info->icount.brk);
-		if (info->icount.overrun)
-			seq_printf(m, " oe:%d", info->icount.overrun);
-	}
-	
-	/* Append serial signal status to end */
-	seq_printf(m, " %s\n", stat_buf+1);
-	
-	seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
-	 info->tx_active,info->bh_requested,info->bh_running,
-	 info->pending_bh);
-	 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	{	
-	u16 Tcsr = usc_InReg( info, TCSR );
-	u16 Tdmr = usc_InDmaReg( info, TDMR );
-	u16 Ticr = usc_InReg( info, TICR );
-	u16 Rscr = usc_InReg( info, RCSR );
-	u16 Rdmr = usc_InDmaReg( info, RDMR );
-	u16 Ricr = usc_InReg( info, RICR );
-	u16 Icr = usc_InReg( info, ICR );
-	u16 Dccr = usc_InReg( info, DCCR );
-	u16 Tmr = usc_InReg( info, TMR );
-	u16 Tccr = usc_InReg( info, TCCR );
-	u16 Ccar = inw( info->io_base + CCAR );
-	seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n"
-                        "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n",
-	 		Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar );
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-/* Called to print information about devices */
-static int mgsl_proc_show(struct seq_file *m, void *v)
-{
-	struct mgsl_struct *info;
-	
-	seq_printf(m, "synclink driver:%s\n", driver_version);
-	
-	info = mgsl_device_list;
-	while( info ) {
-		line_info(m, info);
-		info = info->next_device;
-	}
-	return 0;
-}
-
-static int mgsl_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, mgsl_proc_show, NULL);
-}
-
-static const struct file_operations mgsl_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= mgsl_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/* mgsl_allocate_dma_buffers()
- * 
- * 	Allocate and format DMA buffers (ISA adapter)
- * 	or format shared memory buffers (PCI adapter).
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise error
- */
-static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
-{
-	unsigned short BuffersPerFrame;
-
-	info->last_mem_alloc = 0;
-
-	/* Calculate the number of DMA buffers necessary to hold the */
-	/* largest allowable frame size. Note: If the max frame size is */
-	/* not an even multiple of the DMA buffer size then we need to */
-	/* round the buffer count per frame up one. */
-
-	BuffersPerFrame = (unsigned short)(info->max_frame_size/DMABUFFERSIZE);
-	if ( info->max_frame_size % DMABUFFERSIZE )
-		BuffersPerFrame++;
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/*
-		 * The PCI adapter has 256KBytes of shared memory to use.
-		 * This is 64 PAGE_SIZE buffers.
-		 *
-		 * The first page is used for padding at this time so the
-		 * buffer list does not begin at offset 0 of the PCI
-		 * adapter's shared memory.
-		 *
-		 * The 2nd page is used for the buffer list. A 4K buffer
-		 * list can hold 128 DMA_BUFFER structures at 32 bytes
-		 * each.
-		 *
-		 * This leaves 62 4K pages.
-		 *
-		 * The next N pages are used for transmit frame(s). We
-		 * reserve enough 4K page blocks to hold the required
-		 * number of transmit dma buffers (num_tx_dma_buffers),
-		 * each of MaxFrameSize size.
-		 *
-		 * Of the remaining pages (62-N), determine how many can
-		 * be used to receive full MaxFrameSize inbound frames
-		 */
-		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
-		info->rx_buffer_count = 62 - info->tx_buffer_count;
-	} else {
-		/* Calculate the number of PAGE_SIZE buffers needed for */
-		/* receive and transmit DMA buffers. */
-
-
-		/* Calculate the number of DMA buffers necessary to */
-		/* hold 7 max size receive frames and one max size transmit frame. */
-		/* The receive buffer count is bumped by one so we avoid an */
-		/* End of List condition if all receive buffers are used when */
-		/* using linked list DMA buffers. */
-
-		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
-		info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
-		
-		/* 
-		 * limit total TxBuffers & RxBuffers to 62 4K total 
-		 * (ala PCI Allocation) 
-		 */
-		
-		if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 )
-			info->rx_buffer_count = 62 - info->tx_buffer_count;
-
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",
-			__FILE__,__LINE__, info->tx_buffer_count,info->rx_buffer_count);
-	
-	if ( mgsl_alloc_buffer_list_memory( info ) < 0 ||
-		  mgsl_alloc_frame_memory(info, info->rx_buffer_list, info->rx_buffer_count) < 0 || 
-		  mgsl_alloc_frame_memory(info, info->tx_buffer_list, info->tx_buffer_count) < 0 || 
-		  mgsl_alloc_intermediate_rxbuffer_memory(info) < 0  ||
-		  mgsl_alloc_intermediate_txbuffer_memory(info) < 0 ) {
-		printk("%s(%d):Can't allocate DMA buffer memory\n",__FILE__,__LINE__);
-		return -ENOMEM;
-	}
-	
-	mgsl_reset_rx_dma_buffers( info );
-  	mgsl_reset_tx_dma_buffers( info );
-
-	return 0;
-
-}	/* end of mgsl_allocate_dma_buffers() */
-
-/*
- * mgsl_alloc_buffer_list_memory()
- * 
- * Allocate a common DMA buffer for use as the
- * receive and transmit buffer lists.
- * 
- * A buffer list is a set of buffer entries where each entry contains
- * a pointer to an actual buffer and a pointer to the next buffer entry
- * (plus some other info about the buffer).
- * 
- * The buffer entries for a list are built to form a circular list so
- * that when the entire list has been traversed you start back at the
- * beginning.
- * 
- * This function allocates memory for just the buffer entries.
- * The links (pointer to next entry) are filled in with the physical
- * address of the next entry so the adapter can navigate the list
- * using bus master DMA. The pointers to the actual buffers are filled
- * out later when the actual buffers are allocated.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise error
- */
-static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
-{
-	unsigned int i;
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* PCI adapter uses shared memory. */
-		info->buffer_list = info->memory_base + info->last_mem_alloc;
-		info->buffer_list_phys = info->last_mem_alloc;
-		info->last_mem_alloc += BUFFERLISTSIZE;
-	} else {
-		/* ISA adapter uses system memory. */
-		/* The buffer lists are allocated as a common buffer that both */
-		/* the processor and adapter can access. This allows the driver to */
-		/* inspect portions of the buffer while other portions are being */
-		/* updated by the adapter using Bus Master DMA. */
-
-		info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL);
-		if (info->buffer_list == NULL)
-			return -ENOMEM;
-		info->buffer_list_phys = (u32)(info->buffer_list_dma_addr);
-	}
-
-	/* We got the memory for the buffer entry lists. */
-	/* Initialize the memory block to all zeros. */
-	memset( info->buffer_list, 0, BUFFERLISTSIZE );
-
-	/* Save virtual address pointers to the receive and */
-	/* transmit buffer lists. (Receive 1st). These pointers will */
-	/* be used by the processor to access the lists. */
-	info->rx_buffer_list = (DMABUFFERENTRY *)info->buffer_list;
-	info->tx_buffer_list = (DMABUFFERENTRY *)info->buffer_list;
-	info->tx_buffer_list += info->rx_buffer_count;
-
-	/*
-	 * Build the links for the buffer entry lists such that
-	 * two circular lists are built. (Transmit and Receive).
-	 *
-	 * Note: the links are physical addresses
-	 * which are read by the adapter to determine the next
-	 * buffer entry to use.
-	 */
-
-	for ( i = 0; i < info->rx_buffer_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->rx_buffer_list[i].phys_entry =
-			info->buffer_list_phys + (i * sizeof(DMABUFFERENTRY));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-
-		info->rx_buffer_list[i].link = info->buffer_list_phys;
-
-		if ( i < info->rx_buffer_count - 1 )
-			info->rx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY);
-	}
-
-	for ( i = 0; i < info->tx_buffer_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->tx_buffer_list[i].phys_entry = info->buffer_list_phys +
-			((info->rx_buffer_count + i) * sizeof(DMABUFFERENTRY));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-
-		info->tx_buffer_list[i].link = info->buffer_list_phys +
-			info->rx_buffer_count * sizeof(DMABUFFERENTRY);
-
-		if ( i < info->tx_buffer_count - 1 )
-			info->tx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY);
-	}
-
-	return 0;
-
-}	/* end of mgsl_alloc_buffer_list_memory() */
-
-/* Free DMA buffers allocated for use as the
- * receive and transmit buffer lists.
- * Warning:
- * 
- * 	The data transfer buffers associated with the buffer list
- * 	MUST be freed before freeing the buffer list itself because
- * 	the buffer list contains the information necessary to free
- * 	the individual buffers!
- */
-static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
-{
-	if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI)
-		dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr);
-		
-	info->buffer_list = NULL;
-	info->rx_buffer_list = NULL;
-	info->tx_buffer_list = NULL;
-
-}	/* end of mgsl_free_buffer_list_memory() */
-
-/*
- * mgsl_alloc_frame_memory()
- * 
- * 	Allocate the frame DMA buffers used by the specified buffer list.
- * 	Each DMA buffer will be one memory page in size. This is necessary
- * 	because memory can fragment enough that it may be impossible
- * 	contiguous pages.
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 	BufferList	pointer to list of buffer entries
- * 	Buffercount	count of buffer entries in buffer list
- * 
- * Return Value:	0 if success, otherwise -ENOMEM
- */
-static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
-{
-	int i;
-	u32 phys_addr;
-
-	/* Allocate page sized buffers for the receive buffer list */
-
-	for ( i = 0; i < Buffercount; i++ ) {
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-			/* PCI adapter uses shared memory buffers. */
-			BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
-			phys_addr = info->last_mem_alloc;
-			info->last_mem_alloc += DMABUFFERSIZE;
-		} else {
-			/* ISA adapter uses system memory. */
-			BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL);
-			if (BufferList[i].virt_addr == NULL)
-				return -ENOMEM;
-			phys_addr = (u32)(BufferList[i].dma_addr);
-		}
-		BufferList[i].phys_addr = phys_addr;
-	}
-
-	return 0;
-
-}	/* end of mgsl_alloc_frame_memory() */
-
-/*
- * mgsl_free_frame_memory()
- * 
- * 	Free the buffers associated with
- * 	each buffer entry of a buffer list.
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 	BufferList	pointer to list of buffer entries
- * 	Buffercount	count of buffer entries in buffer list
- * 
- * Return Value:	None
- */
-static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
-{
-	int i;
-
-	if ( BufferList ) {
-		for ( i = 0 ; i < Buffercount ; i++ ) {
-			if ( BufferList[i].virt_addr ) {
-				if ( info->bus_type != MGSL_BUS_TYPE_PCI )
-					dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr);
-				BufferList[i].virt_addr = NULL;
-			}
-		}
-	}
-
-}	/* end of mgsl_free_frame_memory() */
-
-/* mgsl_free_dma_buffers()
- * 
- * 	Free DMA buffers
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_free_dma_buffers( struct mgsl_struct *info )
-{
-	mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count );
-	mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count );
-	mgsl_free_buffer_list_memory( info );
-
-}	/* end of mgsl_free_dma_buffers() */
-
-
-/*
- * mgsl_alloc_intermediate_rxbuffer_memory()
- * 
- * 	Allocate a buffer large enough to hold max_frame_size. This buffer
- *	is used to pass an assembled frame to the line discipline.
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 
- * Return Value:	0 if success, otherwise -ENOMEM
- */
-static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
-{
-	info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA);
-	if ( info->intermediate_rxbuffer == NULL )
-		return -ENOMEM;
-
-	return 0;
-
-}	/* end of mgsl_alloc_intermediate_rxbuffer_memory() */
-
-/*
- * mgsl_free_intermediate_rxbuffer_memory()
- * 
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 
- * Return Value:	None
- */
-static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
-{
-	kfree(info->intermediate_rxbuffer);
-	info->intermediate_rxbuffer = NULL;
-
-}	/* end of mgsl_free_intermediate_rxbuffer_memory() */
-
-/*
- * mgsl_alloc_intermediate_txbuffer_memory()
- *
- * 	Allocate intermdiate transmit buffer(s) large enough to hold max_frame_size.
- * 	This buffer is used to load transmit frames into the adapter's dma transfer
- * 	buffers when there is sufficient space.
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- *
- * Return Value:	0 if success, otherwise -ENOMEM
- */
-static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
-{
-	int i;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s %s(%d)  allocating %d tx holding buffers\n",
-				info->device_name, __FILE__,__LINE__,info->num_tx_holding_buffers);
-
-	memset(info->tx_holding_buffers,0,sizeof(info->tx_holding_buffers));
-
-	for ( i=0; i<info->num_tx_holding_buffers; ++i) {
-		info->tx_holding_buffers[i].buffer =
-			kmalloc(info->max_frame_size, GFP_KERNEL);
-		if (info->tx_holding_buffers[i].buffer == NULL) {
-			for (--i; i >= 0; i--) {
-				kfree(info->tx_holding_buffers[i].buffer);
-				info->tx_holding_buffers[i].buffer = NULL;
-			}
-			return -ENOMEM;
-		}
-	}
-
-	return 0;
-
-}	/* end of mgsl_alloc_intermediate_txbuffer_memory() */
-
-/*
- * mgsl_free_intermediate_txbuffer_memory()
- *
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- *
- * Return Value:	None
- */
-static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
-{
-	int i;
-
-	for ( i=0; i<info->num_tx_holding_buffers; ++i ) {
-		kfree(info->tx_holding_buffers[i].buffer);
-		info->tx_holding_buffers[i].buffer = NULL;
-	}
-
-	info->get_tx_holding_index = 0;
-	info->put_tx_holding_index = 0;
-	info->tx_holding_count = 0;
-
-}	/* end of mgsl_free_intermediate_txbuffer_memory() */
-
-
-/*
- * load_next_tx_holding_buffer()
- *
- * attempts to load the next buffered tx request into the
- * tx dma buffers
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- *
- * Return Value:	true if next buffered tx request loaded
- * 			into adapter's tx dma buffer,
- * 			false otherwise
- */
-static bool load_next_tx_holding_buffer(struct mgsl_struct *info)
-{
-	bool ret = false;
-
-	if ( info->tx_holding_count ) {
-		/* determine if we have enough tx dma buffers
-		 * to accommodate the next tx frame
-		 */
-		struct tx_holding_buffer *ptx =
-			&info->tx_holding_buffers[info->get_tx_holding_index];
-		int num_free = num_free_tx_dma_buffers(info);
-		int num_needed = ptx->buffer_size / DMABUFFERSIZE;
-		if ( ptx->buffer_size % DMABUFFERSIZE )
-			++num_needed;
-
-		if (num_needed <= num_free) {
-			info->xmit_cnt = ptx->buffer_size;
-			mgsl_load_tx_dma_buffer(info,ptx->buffer,ptx->buffer_size);
-
-			--info->tx_holding_count;
-			if ( ++info->get_tx_holding_index >= info->num_tx_holding_buffers)
-				info->get_tx_holding_index=0;
-
-			/* restart transmit timer */
-			mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
-
-			ret = true;
-		}
-	}
-
-	return ret;
-}
-
-/*
- * save_tx_buffer_request()
- *
- * attempt to store transmit frame request for later transmission
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- * 	Buffer		pointer to buffer containing frame to load
- * 	BufferSize	size in bytes of frame in Buffer
- *
- * Return Value:	1 if able to store, 0 otherwise
- */
-static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
-{
-	struct tx_holding_buffer *ptx;
-
-	if ( info->tx_holding_count >= info->num_tx_holding_buffers ) {
-		return 0;	        /* all buffers in use */
-	}
-
-	ptx = &info->tx_holding_buffers[info->put_tx_holding_index];
-	ptx->buffer_size = BufferSize;
-	memcpy( ptx->buffer, Buffer, BufferSize);
-
-	++info->tx_holding_count;
-	if ( ++info->put_tx_holding_index >= info->num_tx_holding_buffers)
-		info->put_tx_holding_index=0;
-
-	return 1;
-}
-
-static int mgsl_claim_resources(struct mgsl_struct *info)
-{
-	if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) {
-		printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->io_base);
-		return -ENODEV;
-	}
-	info->io_addr_requested = true;
-	
-	if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags,
-		info->device_name, info ) < 0 ) {
-		printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n",
-			__FILE__,__LINE__,info->device_name, info->irq_level );
-		goto errout;
-	}
-	info->irq_requested = true;
-	
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
-			printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_memory_base);
-			goto errout;
-		}
-		info->shared_mem_requested = true;
-		if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
-			printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
-			goto errout;
-		}
-		info->lcr_mem_requested = true;
-
-		info->memory_base = ioremap_nocache(info->phys_memory_base,
-								0x40000);
-		if (!info->memory_base) {
-			printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-			goto errout;
-		}
-		
-		if ( !mgsl_memory_test(info) ) {
-			printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-			goto errout;
-		}
-		
-		info->lcr_base = ioremap_nocache(info->phys_lcr_base,
-								PAGE_SIZE);
-		if (!info->lcr_base) {
-			printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
-			goto errout;
-		}
-		info->lcr_base += info->lcr_offset;
-		
-	} else {
-		/* claim DMA channel */
-		
-		if (request_dma(info->dma_level,info->device_name) < 0){
-			printk( "%s(%d):Cant request DMA channel on device %s DMA=%d\n",
-				__FILE__,__LINE__,info->device_name, info->dma_level );
-			mgsl_release_resources( info );
-			return -ENODEV;
-		}
-		info->dma_requested = true;
-
-		/* ISA adapter uses bus master DMA */		
-		set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
-		enable_dma(info->dma_level);
-	}
-	
-	if ( mgsl_allocate_dma_buffers(info) < 0 ) {
-		printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n",
-			__FILE__,__LINE__,info->device_name, info->dma_level );
-		goto errout;
-	}	
-	
-	return 0;
-errout:
-	mgsl_release_resources(info);
-	return -ENODEV;
-
-}	/* end of mgsl_claim_resources() */
-
-static void mgsl_release_resources(struct mgsl_struct *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_release_resources(%s) entry\n",
-			__FILE__,__LINE__,info->device_name );
-			
-	if ( info->irq_requested ) {
-		free_irq(info->irq_level, info);
-		info->irq_requested = false;
-	}
-	if ( info->dma_requested ) {
-		disable_dma(info->dma_level);
-		free_dma(info->dma_level);
-		info->dma_requested = false;
-	}
-	mgsl_free_dma_buffers(info);
-	mgsl_free_intermediate_rxbuffer_memory(info);
-     	mgsl_free_intermediate_txbuffer_memory(info);
-	
-	if ( info->io_addr_requested ) {
-		release_region(info->io_base,info->io_addr_size);
-		info->io_addr_requested = false;
-	}
-	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,0x40000);
-		info->shared_mem_requested = false;
-	}
-	if ( info->lcr_mem_requested ) {
-		release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
-		info->lcr_mem_requested = false;
-	}
-	if (info->memory_base){
-		iounmap(info->memory_base);
-		info->memory_base = NULL;
-	}
-	if (info->lcr_base){
-		iounmap(info->lcr_base - info->lcr_offset);
-		info->lcr_base = NULL;
-	}
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_release_resources(%s) exit\n",
-			__FILE__,__LINE__,info->device_name );
-			
-}	/* end of mgsl_release_resources() */
-
-/* mgsl_add_device()
- * 
- * 	Add the specified device instance data structure to the
- * 	global linked list of devices and increment the device count.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_add_device( struct mgsl_struct *info )
-{
-	info->next_device = NULL;
-	info->line = mgsl_device_count;
-	sprintf(info->device_name,"ttySL%d",info->line);
-	
-	if (info->line < MAX_TOTAL_DEVICES) {
-		if (maxframe[info->line])
-			info->max_frame_size = maxframe[info->line];
-
-		if (txdmabufs[info->line]) {
-			info->num_tx_dma_buffers = txdmabufs[info->line];
-			if (info->num_tx_dma_buffers < 1)
-				info->num_tx_dma_buffers = 1;
-		}
-
-		if (txholdbufs[info->line]) {
-			info->num_tx_holding_buffers = txholdbufs[info->line];
-			if (info->num_tx_holding_buffers < 1)
-				info->num_tx_holding_buffers = 1;
-			else if (info->num_tx_holding_buffers > MAX_TX_HOLDING_BUFFERS)
-				info->num_tx_holding_buffers = MAX_TX_HOLDING_BUFFERS;
-		}
-	}
-
-	mgsl_device_count++;
-	
-	if ( !mgsl_device_list )
-		mgsl_device_list = info;
-	else {	
-		struct mgsl_struct *current_dev = mgsl_device_list;
-		while( current_dev->next_device )
-			current_dev = current_dev->next_device;
-		current_dev->next_device = info;
-	}
-	
-	if ( info->max_frame_size < 4096 )
-		info->max_frame_size = 4096;
-	else if ( info->max_frame_size > 65535 )
-		info->max_frame_size = 65535;
-	
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
-			info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
-			info->phys_memory_base, info->phys_lcr_base,
-		     	info->max_frame_size );
-	} else {
-		printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
-			info->device_name, info->io_base, info->irq_level, info->dma_level,
-		     	info->max_frame_size );
-	}
-
-#if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
-#endif
-
-}	/* end of mgsl_add_device() */
-
-static const struct tty_port_operations mgsl_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-
-/* mgsl_allocate_device()
- * 
- * 	Allocate and initialize a device instance structure
- * 	
- * Arguments:		none
- * Return Value:	pointer to mgsl_struct if success, otherwise NULL
- */
-static struct mgsl_struct* mgsl_allocate_device(void)
-{
-	struct mgsl_struct *info;
-	
-	info = kzalloc(sizeof(struct mgsl_struct),
-		 GFP_KERNEL);
-		 
-	if (!info) {
-		printk("Error can't allocate device instance data\n");
-	} else {
-		tty_port_init(&info->port);
-		info->port.ops = &mgsl_port_ops;
-		info->magic = MGSL_MAGIC;
-		INIT_WORK(&info->task, mgsl_bh_handler);
-		info->max_frame_size = 4096;
-		info->port.close_delay = 5*HZ/10;
-		info->port.closing_wait = 30*HZ;
-		init_waitqueue_head(&info->status_event_wait_q);
-		init_waitqueue_head(&info->event_wait_q);
-		spin_lock_init(&info->irq_spinlock);
-		spin_lock_init(&info->netlock);
-		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;		
-		info->num_tx_dma_buffers = 1;
-		info->num_tx_holding_buffers = 0;
-	}
-	
-	return info;
-
-}	/* end of mgsl_allocate_device()*/
-
-static const struct tty_operations mgsl_ops = {
-	.open = mgsl_open,
-	.close = mgsl_close,
-	.write = mgsl_write,
-	.put_char = mgsl_put_char,
-	.flush_chars = mgsl_flush_chars,
-	.write_room = mgsl_write_room,
-	.chars_in_buffer = mgsl_chars_in_buffer,
-	.flush_buffer = mgsl_flush_buffer,
-	.ioctl = mgsl_ioctl,
-	.throttle = mgsl_throttle,
-	.unthrottle = mgsl_unthrottle,
-	.send_xchar = mgsl_send_xchar,
-	.break_ctl = mgsl_break,
-	.wait_until_sent = mgsl_wait_until_sent,
-	.set_termios = mgsl_set_termios,
-	.stop = mgsl_stop,
-	.start = mgsl_start,
-	.hangup = mgsl_hangup,
-	.tiocmget = tiocmget,
-	.tiocmset = tiocmset,
-	.get_icount = msgl_get_icount,
-	.proc_fops = &mgsl_proc_fops,
-};
-
-/*
- * perform tty device initialization
- */
-static int mgsl_init_tty(void)
-{
-	int rc;
-
-	serial_driver = alloc_tty_driver(128);
-	if (!serial_driver)
-		return -ENOMEM;
-	
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = "synclink";
-	serial_driver->name = "ttySL";
-	serial_driver->major = ttymajor;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->init_termios.c_ispeed = 9600;
-	serial_driver->init_termios.c_ospeed = 9600;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(serial_driver, &mgsl_ops);
-	if ((rc = tty_register_driver(serial_driver)) < 0) {
-		printk("%s(%d):Couldn't register serial driver\n",
-			__FILE__,__LINE__);
-		put_tty_driver(serial_driver);
-		serial_driver = NULL;
-		return rc;
-	}
-			
- 	printk("%s %s, tty major#%d\n",
-		driver_name, driver_version,
-		serial_driver->major);
-	return 0;
-}
-
-/* enumerate user specified ISA adapters
- */
-static void mgsl_enum_isa_devices(void)
-{
-	struct mgsl_struct *info;
-	int i;
-		
-	/* Check for user specified ISA devices */
-	
-	for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk("ISA device specified io=%04X,irq=%d,dma=%d\n",
-				io[i], irq[i], dma[i] );
-		
-		info = mgsl_allocate_device();
-		if ( !info ) {
-			/* error allocating device instance data */
-			if ( debug_level >= DEBUG_LEVEL_ERROR )
-				printk( "can't allocate device instance data.\n");
-			continue;
-		}
-		
-		/* Copy user configuration info to device instance data */
-		info->io_base = (unsigned int)io[i];
-		info->irq_level = (unsigned int)irq[i];
-		info->irq_level = irq_canonicalize(info->irq_level);
-		info->dma_level = (unsigned int)dma[i];
-		info->bus_type = MGSL_BUS_TYPE_ISA;
-		info->io_addr_size = 16;
-		info->irq_flags = 0;
-		
-		mgsl_add_device( info );
-	}
-}
-
-static void synclink_cleanup(void)
-{
-	int rc;
-	struct mgsl_struct *info;
-	struct mgsl_struct *tmp;
-
-	printk("Unloading %s: %s\n", driver_name, driver_version);
-
-	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
-			printk("%s(%d) failed to unregister tty driver err=%d\n",
-			       __FILE__,__LINE__,rc);
-		put_tty_driver(serial_driver);
-	}
-
-	info = mgsl_device_list;
-	while(info) {
-#if SYNCLINK_GENERIC_HDLC
-		hdlcdev_exit(info);
-#endif
-		mgsl_release_resources(info);
-		tmp = info;
-		info = info->next_device;
-		kfree(tmp);
-	}
-	
-	if (pci_registered)
-		pci_unregister_driver(&synclink_pci_driver);
-}
-
-static int __init synclink_init(void)
-{
-	int rc;
-
-	if (break_on_load) {
-	 	mgsl_get_text_ptr();
-  		BREAKPOINT();
-	}
-
- 	printk("%s %s\n", driver_name, driver_version);
-
-	mgsl_enum_isa_devices();
-	if ((rc = pci_register_driver(&synclink_pci_driver)) < 0)
-		printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
-	else
-		pci_registered = true;
-
-	if ((rc = mgsl_init_tty()) < 0)
-		goto error;
-
-	return 0;
-
-error:
-	synclink_cleanup();
-	return rc;
-}
-
-static void __exit synclink_exit(void)
-{
-	synclink_cleanup();
-}
-
-module_init(synclink_init);
-module_exit(synclink_exit);
-
-/*
- * usc_RTCmd()
- *
- * Issue a USC Receive/Transmit command to the
- * Channel Command/Address Register (CCAR).
- *
- * Notes:
- *
- *    The command is encoded in the most significant 5 bits <15..11>
- *    of the CCAR value. Bits <10..7> of the CCAR must be preserved
- *    and Bits <6..0> must be written as zeros.
- *
- * Arguments:
- *
- *    info   pointer to device information structure
- *    Cmd    command mask (use symbolic macros)
- *
- * Return Value:
- *
- *    None
- */
-static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
-{
-	/* output command to CCAR in bits <15..11> */
-	/* preserve bits <10..7>, bits <6..0> must be zero */
-
-	outw( Cmd + info->loopback_bits, info->io_base + CCAR );
-
-	/* Read to flush write to CCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base + CCAR );
-
-}	/* end of usc_RTCmd() */
-
-/*
- * usc_DmaCmd()
- *
- *    Issue a DMA command to the DMA Command/Address Register (DCAR).
- *
- * Arguments:
- *
- *    info   pointer to device information structure
- *    Cmd    DMA command mask (usc_DmaCmd_XX Macros)
- *
- * Return Value:
- *
- *       None
- */
-static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
-{
-	/* write command mask to DCAR */
-	outw( Cmd + info->mbre_bit, info->io_base );
-
-	/* Read to flush write to DCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base );
-
-}	/* end of usc_DmaCmd() */
-
-/*
- * usc_OutDmaReg()
- *
- *    Write a 16-bit value to a USC DMA register
- *
- * Arguments:
- *
- *    info      pointer to device info structure
- *    RegAddr   register address (number) for write
- *    RegValue  16-bit value to write to register
- *
- * Return Value:
- *
- *    None
- *
- */
-static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
-{
-	/* Note: The DCAR is located at the adapter base address */
-	/* Note: must preserve state of BIT8 in DCAR */
-
-	outw( RegAddr + info->mbre_bit, info->io_base );
-	outw( RegValue, info->io_base );
-
-	/* Read to flush write to DCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base );
-
-}	/* end of usc_OutDmaReg() */
- 
-/*
- * usc_InDmaReg()
- *
- *    Read a 16-bit value from a DMA register
- *
- * Arguments:
- *
- *    info     pointer to device info structure
- *    RegAddr  register address (number) to read from
- *
- * Return Value:
- *
- *    The 16-bit value read from register
- *
- */
-static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
-{
-	/* Note: The DCAR is located at the adapter base address */
-	/* Note: must preserve state of BIT8 in DCAR */
-
-	outw( RegAddr + info->mbre_bit, info->io_base );
-	return inw( info->io_base );
-
-}	/* end of usc_InDmaReg() */
-
-/*
- *
- * usc_OutReg()
- *
- *    Write a 16-bit value to a USC serial channel register 
- *
- * Arguments:
- *
- *    info      pointer to device info structure
- *    RegAddr   register address (number) to write to
- *    RegValue  16-bit value to write to register
- *
- * Return Value:
- *
- *    None
- *
- */
-static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
-{
-	outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
-	outw( RegValue, info->io_base + CCAR );
-
-	/* Read to flush write to CCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base + CCAR );
-
-}	/* end of usc_OutReg() */
-
-/*
- * usc_InReg()
- *
- *    Reads a 16-bit value from a USC serial channel register
- *
- * Arguments:
- *
- *    info       pointer to device extension
- *    RegAddr    register address (number) to read from
- *
- * Return Value:
- *
- *    16-bit value read from register
- */
-static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
-{
-	outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
-	return inw( info->io_base + CCAR );
-
-}	/* end of usc_InReg() */
-
-/* usc_set_sdlc_mode()
- *
- *    Set up the adapter for SDLC DMA communications.
- *
- * Arguments:		info    pointer to device instance data
- * Return Value: 	NONE
- */
-static void usc_set_sdlc_mode( struct mgsl_struct *info )
-{
-	u16 RegValue;
-	bool PreSL1660;
-	
-	/*
-	 * determine if the IUSC on the adapter is pre-SL1660. If
-	 * not, take advantage of the UnderWait feature of more
-	 * modern chips. If an underrun occurs and this bit is set,
-	 * the transmitter will idle the programmed idle pattern
-	 * until the driver has time to service the underrun. Otherwise,
-	 * the dma controller may get the cycles previously requested
-	 * and begin transmitting queued tx data.
-	 */
-	usc_OutReg(info,TMCR,0x1f);
-	RegValue=usc_InReg(info,TMDR);
-	PreSL1660 = (RegValue == IUSC_PRE_SL1660);
-
- 	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
- 	{
- 	   /*
- 	   ** Channel Mode Register (CMR)
- 	   **
- 	   ** <15..14>    10    Tx Sub Modes, Send Flag on Underrun
- 	   ** <13>        0     0 = Transmit Disabled (initially)
- 	   ** <12>        0     1 = Consecutive Idles share common 0
- 	   ** <11..8>     1110  Transmitter Mode = HDLC/SDLC Loop
- 	   ** <7..4>      0000  Rx Sub Modes, addr/ctrl field handling
- 	   ** <3..0>      0110  Receiver Mode = HDLC/SDLC
- 	   **
- 	   ** 1000 1110 0000 0110 = 0x8e06
- 	   */
- 	   RegValue = 0x8e06;
- 
- 	   /*--------------------------------------------------
- 	    * ignore user options for UnderRun Actions and
- 	    * preambles
- 	    *--------------------------------------------------*/
- 	}
- 	else
- 	{	
-		/* Channel mode Register (CMR)
-		 *
-		 * <15..14>  00    Tx Sub modes, Underrun Action
-		 * <13>      0     1 = Send Preamble before opening flag
-		 * <12>      0     1 = Consecutive Idles share common 0
-		 * <11..8>   0110  Transmitter mode = HDLC/SDLC
-		 * <7..4>    0000  Rx Sub modes, addr/ctrl field handling
-		 * <3..0>    0110  Receiver mode = HDLC/SDLC
-		 *
-		 * 0000 0110 0000 0110 = 0x0606
-		 */
-		if (info->params.mode == MGSL_MODE_RAW) {
-			RegValue = 0x0001;		/* Set Receive mode = external sync */
-
-			usc_OutReg( info, IOCR,		/* Set IOCR DCD is RxSync Detect Input */
-				(unsigned short)((usc_InReg(info, IOCR) & ~(BIT13|BIT12)) | BIT12));
-
-			/*
-			 * TxSubMode:
-			 * 	CMR <15>		0	Don't send CRC on Tx Underrun
-			 * 	CMR <14>		x	undefined
-			 * 	CMR <13>		0	Send preamble before openning sync
-			 * 	CMR <12>		0	Send 8-bit syncs, 1=send Syncs per TxLength
-			 *
-			 * TxMode:
-			 * 	CMR <11-8)	0100	MonoSync
-			 *
-			 * 	0x00 0100 xxxx xxxx  04xx
-			 */
-			RegValue |= 0x0400;
-		}
-		else {
-
-		RegValue = 0x0606;
-
-		if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 )
-			RegValue |= BIT14;
-		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
-			RegValue |= BIT15;
-		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
-			RegValue |= BIT15 + BIT14;
-		}
-
-		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
-			RegValue |= BIT13;
-	}
-
-	if ( info->params.mode == MGSL_MODE_HDLC &&
-		(info->params.flags & HDLC_FLAG_SHARE_ZERO) )
-		RegValue |= BIT12;
-
-	if ( info->params.addr_filter != 0xff )
-	{
-		/* set up receive address filtering */
-		usc_OutReg( info, RSR, info->params.addr_filter );
-		RegValue |= BIT4;
-	}
-
-	usc_OutReg( info, CMR, RegValue );
-	info->cmr_value = RegValue;
-
-	/* Receiver mode Register (RMR)
-	 *
-	 * <15..13>  000    encoding
-	 * <12..11>  00     FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1)
-	 * <10>      1      1 = Set CRC to all 1s (use for SDLC/HDLC)
-	 * <9>       0      1 = Include Receive chars in CRC
-	 * <8>       1      1 = Use Abort/PE bit as abort indicator
-	 * <7..6>    00     Even parity
-	 * <5>       0      parity disabled
-	 * <4..2>    000    Receive Char Length = 8 bits
-	 * <1..0>    00     Disable Receiver
-	 *
-	 * 0000 0101 0000 0000 = 0x0500
-	 */
-
-	RegValue = 0x0500;
-
-	switch ( info->params.encoding ) {
-	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
-	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
-	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
-	}
-
-	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
-		RegValue |= BIT9;
-	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
-		RegValue |= ( BIT12 | BIT10 | BIT9 );
-
-	usc_OutReg( info, RMR, RegValue );
-
-	/* Set the Receive count Limit Register (RCLR) to 0xffff. */
-	/* When an opening flag of an SDLC frame is recognized the */
-	/* Receive Character count (RCC) is loaded with the value in */
-	/* RCLR. The RCC is decremented for each received byte.  The */
-	/* value of RCC is stored after the closing flag of the frame */
-	/* allowing the frame size to be computed. */
-
-	usc_OutReg( info, RCLR, RCLRVALUE );
-
-	usc_RCmd( info, RCmd_SelectRicrdma_level );
-
-	/* Receive Interrupt Control Register (RICR)
-	 *
-	 * <15..8>	?	RxFIFO DMA Request Level
-	 * <7>		0	Exited Hunt IA (Interrupt Arm)
-	 * <6>		0	Idle Received IA
-	 * <5>		0	Break/Abort IA
-	 * <4>		0	Rx Bound IA
-	 * <3>		1	Queued status reflects oldest 2 bytes in FIFO
-	 * <2>		0	Abort/PE IA
-	 * <1>		1	Rx Overrun IA
-	 * <0>		0	Select TC0 value for readback
-	 *
-	 *	0000 0000 0000 1000 = 0x000a
-	 */
-
-	/* Carry over the Exit Hunt and Idle Received bits */
-	/* in case they have been armed by usc_ArmEvents.   */
-
-	RegValue = usc_InReg( info, RICR ) & 0xc0;
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
-	else
-		usc_OutReg( info, RICR, (u16)(0x140a | RegValue) );
-
-	/* Unlatch all Rx status bits and clear Rx status IRQ Pending */
-
-	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
-
-	/* Transmit mode Register (TMR)
-	 *	
-	 * <15..13>	000	encoding
-	 * <12..11>	00	FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1)
-	 * <10>		1	1 = Start CRC as all 1s (use for SDLC/HDLC)
-	 * <9>		0	1 = Tx CRC Enabled
-	 * <8>		0	1 = Append CRC to end of transmit frame
-	 * <7..6>	00	Transmit parity Even
-	 * <5>		0	Transmit parity Disabled
-	 * <4..2>	000	Tx Char Length = 8 bits
-	 * <1..0>	00	Disable Transmitter
-	 *
-	 * 	0000 0100 0000 0000 = 0x0400
-	 */
-
-	RegValue = 0x0400;
-
-	switch ( info->params.encoding ) {
-	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
-	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
-	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
-	}
-
-	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
-		RegValue |= BIT9 + BIT8;
-	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
-		RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8);
-
-	usc_OutReg( info, TMR, RegValue );
-
-	usc_set_txidle( info );
-
-
-	usc_TCmd( info, TCmd_SelectTicrdma_level );
-
-	/* Transmit Interrupt Control Register (TICR)
-	 *
-	 * <15..8>	?	Transmit FIFO DMA Level
-	 * <7>		0	Present IA (Interrupt Arm)
-	 * <6>		0	Idle Sent IA
-	 * <5>		1	Abort Sent IA
-	 * <4>		1	EOF/EOM Sent IA
-	 * <3>		0	CRC Sent IA
-	 * <2>		1	1 = Wait for SW Trigger to Start Frame
-	 * <1>		1	Tx Underrun IA
-	 * <0>		0	TC0 constant on read back
-	 *
-	 *	0000 0000 0011 0110 = 0x0036
-	 */
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		usc_OutReg( info, TICR, 0x0736 );
-	else								
-		usc_OutReg( info, TICR, 0x1436 );
-
-	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-
-	/*
-	** Transmit Command/Status Register (TCSR)
-	**
-	** <15..12>	0000	TCmd
-	** <11> 	0/1	UnderWait
-	** <10..08>	000	TxIdle
-	** <7>		x	PreSent
-	** <6>         	x	IdleSent
-	** <5>         	x	AbortSent
-	** <4>         	x	EOF/EOM Sent
-	** <3>         	x	CRC Sent
-	** <2>         	x	All Sent
-	** <1>         	x	TxUnder
-	** <0>         	x	TxEmpty
-	** 
-	** 0000 0000 0000 0000 = 0x0000
-	*/
-	info->tcsr_value = 0;
-
-	if ( !PreSL1660 )
-		info->tcsr_value |= TCSR_UNDERWAIT;
-		
-	usc_OutReg( info, TCSR, info->tcsr_value );
-
-	/* Clock mode Control Register (CMCR)
-	 *
-	 * <15..14>	00	counter 1 Source = Disabled
-	 * <13..12> 	00	counter 0 Source = Disabled
-	 * <11..10> 	11	BRG1 Input is TxC Pin
-	 * <9..8>	11	BRG0 Input is TxC Pin
-	 * <7..6>	01	DPLL Input is BRG1 Output
-	 * <5..3>	XXX	TxCLK comes from Port 0
-	 * <2..0>   	XXX	RxCLK comes from Port 1
-	 *
-	 *	0000 1111 0111 0111 = 0x0f77
-	 */
-
-	RegValue = 0x0f40;
-
-	if ( info->params.flags & HDLC_FLAG_RXC_DPLL )
-		RegValue |= 0x0003;	/* RxCLK from DPLL */
-	else if ( info->params.flags & HDLC_FLAG_RXC_BRG )
-		RegValue |= 0x0004;	/* RxCLK from BRG0 */
- 	else if ( info->params.flags & HDLC_FLAG_RXC_TXCPIN)
- 		RegValue |= 0x0006;	/* RxCLK from TXC Input */
-	else
-		RegValue |= 0x0007;	/* RxCLK from Port1 */
-
-	if ( info->params.flags & HDLC_FLAG_TXC_DPLL )
-		RegValue |= 0x0018;	/* TxCLK from DPLL */
-	else if ( info->params.flags & HDLC_FLAG_TXC_BRG )
-		RegValue |= 0x0020;	/* TxCLK from BRG0 */
- 	else if ( info->params.flags & HDLC_FLAG_TXC_RXCPIN)
- 		RegValue |= 0x0038;	/* RxCLK from TXC Input */
-	else
-		RegValue |= 0x0030;	/* TxCLK from Port0 */
-
-	usc_OutReg( info, CMCR, RegValue );
-
-
-	/* Hardware Configuration Register (HCR)
-	 *
-	 * <15..14>	00	CTR0 Divisor:00=32,01=16,10=8,11=4
-	 * <13>		0	CTR1DSel:0=CTR0Div determines CTR0Div
-	 * <12>		0	CVOK:0=report code violation in biphase
-	 * <11..10>	00	DPLL Divisor:00=32,01=16,10=8,11=4
-	 * <9..8>	XX	DPLL mode:00=disable,01=NRZ,10=Biphase,11=Biphase Level
-	 * <7..6>	00	reserved
-	 * <5>		0	BRG1 mode:0=continuous,1=single cycle
-	 * <4>		X	BRG1 Enable
-	 * <3..2>	00	reserved
-	 * <1>		0	BRG0 mode:0=continuous,1=single cycle
-	 * <0>		0	BRG0 Enable
-	 */
-
-	RegValue = 0x0000;
-
-	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) {
-		u32 XtalSpeed;
-		u32 DpllDivisor;
-		u16 Tc;
-
-		/*  DPLL is enabled. Use BRG1 to provide continuous reference clock  */
-		/*  for DPLL. DPLL mode in HCR is dependent on the encoding used. */
-
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			XtalSpeed = 11059200;
-		else
-			XtalSpeed = 14745600;
-
-		if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
-			DpllDivisor = 16;
-			RegValue |= BIT10;
-		}
-		else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) {
-			DpllDivisor = 8;
-			RegValue |= BIT11;
-		}
-		else
-			DpllDivisor = 32;
-
-		/*  Tc = (Xtal/Speed) - 1 */
-		/*  If twice the remainder of (Xtal/Speed) is greater than Speed */
-		/*  then rounding up gives a more precise time constant. Instead */
-		/*  of rounding up and then subtracting 1 we just don't subtract */
-		/*  the one in this case. */
-
- 		/*--------------------------------------------------
- 		 * ejz: for DPLL mode, application should use the
- 		 * same clock speed as the partner system, even 
- 		 * though clocking is derived from the input RxData.
- 		 * In case the user uses a 0 for the clock speed,
- 		 * default to 0xffffffff and don't try to divide by
- 		 * zero
- 		 *--------------------------------------------------*/
- 		if ( info->params.clock_speed )
- 		{
-			Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed);
-			if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2)
-			       / info->params.clock_speed) )
-				Tc--;
- 		}
- 		else
- 			Tc = -1;
- 				  
-
-		/* Write 16-bit Time Constant for BRG1 */
-		usc_OutReg( info, TC1R, Tc );
-
-		RegValue |= BIT4;		/* enable BRG1 */
-
-		switch ( info->params.encoding ) {
-		case HDLC_ENCODING_NRZ:
-		case HDLC_ENCODING_NRZB:
-		case HDLC_ENCODING_NRZI_MARK:
-		case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT8; break;
-		case HDLC_ENCODING_BIPHASE_MARK:
-		case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break;
-		case HDLC_ENCODING_BIPHASE_LEVEL:
-		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break;
-		}
-	}
-
-	usc_OutReg( info, HCR, RegValue );
-
-
-	/* Channel Control/status Register (CCSR)
-	 *
-	 * <15>		X	RCC FIFO Overflow status (RO)
-	 * <14>		X	RCC FIFO Not Empty status (RO)
-	 * <13>		0	1 = Clear RCC FIFO (WO)
-	 * <12>		X	DPLL Sync (RW)
-	 * <11>		X	DPLL 2 Missed Clocks status (RO)
-	 * <10>		X	DPLL 1 Missed Clock status (RO)
-	 * <9..8>	00	DPLL Resync on rising and falling edges (RW)
-	 * <7>		X	SDLC Loop On status (RO)
-	 * <6>		X	SDLC Loop Send status (RO)
-	 * <5>		1	Bypass counters for TxClk and RxClk (RW)
-	 * <4..2>   	000	Last Char of SDLC frame has 8 bits (RW)
-	 * <1..0>   	00	reserved
-	 *
-	 *	0000 0000 0010 0000 = 0x0020
-	 */
-
-	usc_OutReg( info, CCSR, 0x1020 );
-
-
-	if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) {
-		usc_OutReg( info, SICR,
-			    (u16)(usc_InReg(info,SICR) | SICR_CTS_INACTIVE) );
-	}
-	
-
-	/* enable Master Interrupt Enable bit (MIE) */
-	usc_EnableMasterIrqBit( info );
-
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
-				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
-
-	/* arm RCC underflow interrupt */
-	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
-	usc_EnableInterrupts(info, MISC);
-
-	info->mbre_bit = 0;
-	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
-	usc_DmaCmd( info, DmaCmd_ResetAllChannels );	/* disable both DMA channels */
-	info->mbre_bit = BIT8;
-	outw( BIT8, info->io_base );			/* set Master Bus Enable (DCAR) */
-
-	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
-		/* Enable DMAEN (Port 7, Bit 14) */
-		/* This connects the DMA request signal to the ISA bus */
-		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14));
-	}
-
-	/* DMA Control Register (DCR)
-	 *
-	 * <15..14>	10	Priority mode = Alternating Tx/Rx
-	 *		01	Rx has priority
-	 *		00	Tx has priority
-	 *
-	 * <13>		1	Enable Priority Preempt per DCR<15..14>
-	 *			(WARNING DCR<11..10> must be 00 when this is 1)
-	 *		0	Choose activate channel per DCR<11..10>
-	 *
-	 * <12>		0	Little Endian for Array/List
-	 * <11..10>	00	Both Channels can use each bus grant
-	 * <9..6>	0000	reserved
-	 * <5>		0	7 CLK - Minimum Bus Re-request Interval
-	 * <4>		0	1 = drive D/C and S/D pins
-	 * <3>		1	1 = Add one wait state to all DMA cycles.
-	 * <2>		0	1 = Strobe /UAS on every transfer.
-	 * <1..0>	11	Addr incrementing only affects LS24 bits
-	 *
-	 *	0110 0000 0000 1011 = 0x600b
-	 */
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* PCI adapter does not need DMA wait state */
-		usc_OutDmaReg( info, DCR, 0xa00b );
-	}
-	else
-		usc_OutDmaReg( info, DCR, 0x800b );
-
-
-	/* Receive DMA mode Register (RDMR)
-	 *
-	 * <15..14>	11	DMA mode = Linked List Buffer mode
-	 * <13>		1	RSBinA/L = store Rx status Block in Arrary/List entry
-	 * <12>		1	Clear count of List Entry after fetching
-	 * <11..10>	00	Address mode = Increment
-	 * <9>		1	Terminate Buffer on RxBound
-	 * <8>		0	Bus Width = 16bits
-	 * <7..0>	?	status Bits (write as 0s)
-	 *
-	 * 1111 0010 0000 0000 = 0xf200
-	 */
-
-	usc_OutDmaReg( info, RDMR, 0xf200 );
-
-
-	/* Transmit DMA mode Register (TDMR)
-	 *
-	 * <15..14>	11	DMA mode = Linked List Buffer mode
-	 * <13>		1	TCBinA/L = fetch Tx Control Block from List entry
-	 * <12>		1	Clear count of List Entry after fetching
-	 * <11..10>	00	Address mode = Increment
-	 * <9>		1	Terminate Buffer on end of frame
-	 * <8>		0	Bus Width = 16bits
-	 * <7..0>	?	status Bits (Read Only so write as 0)
-	 *
-	 *	1111 0010 0000 0000 = 0xf200
-	 */
-
-	usc_OutDmaReg( info, TDMR, 0xf200 );
-
-
-	/* DMA Interrupt Control Register (DICR)
-	 *
-	 * <15>		1	DMA Interrupt Enable
-	 * <14>		0	1 = Disable IEO from USC
-	 * <13>		0	1 = Don't provide vector during IntAck
-	 * <12>		1	1 = Include status in Vector
-	 * <10..2>	0	reserved, Must be 0s
-	 * <1>		0	1 = Rx DMA Interrupt Enabled
-	 * <0>		0	1 = Tx DMA Interrupt Enabled
-	 *
-	 *	1001 0000 0000 0000 = 0x9000
-	 */
-
-	usc_OutDmaReg( info, DICR, 0x9000 );
-
-	usc_InDmaReg( info, RDMR );		/* clear pending receive DMA IRQ bits */
-	usc_InDmaReg( info, TDMR );		/* clear pending transmit DMA IRQ bits */
-	usc_OutDmaReg( info, CDIR, 0x0303 );	/* clear IUS and Pending for Tx and Rx */
-
-	/* Channel Control Register (CCR)
-	 *
-	 * <15..14>	10	Use 32-bit Tx Control Blocks (TCBs)
-	 * <13>		0	Trigger Tx on SW Command Disabled
-	 * <12>		0	Flag Preamble Disabled
-	 * <11..10>	00	Preamble Length
-	 * <9..8>	00	Preamble Pattern
-	 * <7..6>	10	Use 32-bit Rx status Blocks (RSBs)
-	 * <5>		0	Trigger Rx on SW Command Disabled
-	 * <4..0>	0	reserved
-	 *
-	 *	1000 0000 1000 0000 = 0x8080
-	 */
-
-	RegValue = 0x8080;
-
-	switch ( info->params.preamble_length ) {
-	case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break;
-	case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break;
-	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break;
-	}
-
-	switch ( info->params.preamble ) {
-	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break;
-	case HDLC_PREAMBLE_PATTERN_ONES:  RegValue |= BIT8; break;
-	case HDLC_PREAMBLE_PATTERN_10:    RegValue |= BIT9; break;
-	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 + BIT8; break;
-	}
-
-	usc_OutReg( info, CCR, RegValue );
-
-
-	/*
-	 * Burst/Dwell Control Register
-	 *
-	 * <15..8>	0x20	Maximum number of transfers per bus grant
-	 * <7..0>	0x00	Maximum number of clock cycles per bus grant
-	 */
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* don't limit bus occupancy on PCI adapter */
-		usc_OutDmaReg( info, BDCR, 0x0000 );
-	}
-	else
-		usc_OutDmaReg( info, BDCR, 0x2000 );
-
-	usc_stop_transmitter(info);
-	usc_stop_receiver(info);
-	
-}	/* end of usc_set_sdlc_mode() */
-
-/* usc_enable_loopback()
- *
- * Set the 16C32 for internal loopback mode.
- * The TxCLK and RxCLK signals are generated from the BRG0 and
- * the TxD is looped back to the RxD internally.
- *
- * Arguments:		info	pointer to device instance data
- *			enable	1 = enable loopback, 0 = disable
- * Return Value:	None
- */
-static void usc_enable_loopback(struct mgsl_struct *info, int enable)
-{
-	if (enable) {
-		/* blank external TXD output */
-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6));
-	
-		/* Clock mode Control Register (CMCR)
-		 *
-		 * <15..14>	00	counter 1 Disabled
-		 * <13..12> 	00	counter 0 Disabled
-		 * <11..10> 	11	BRG1 Input is TxC Pin
-		 * <9..8>	11	BRG0 Input is TxC Pin
-		 * <7..6>	01	DPLL Input is BRG1 Output
-		 * <5..3>	100	TxCLK comes from BRG0
-		 * <2..0>   	100	RxCLK comes from BRG0
-		 *
-		 * 0000 1111 0110 0100 = 0x0f64
-		 */
-
-		usc_OutReg( info, CMCR, 0x0f64 );
-
-		/* Write 16-bit Time Constant for BRG0 */
-		/* use clock speed if available, otherwise use 8 for diagnostics */
-		if (info->params.clock_speed) {
-			if (info->bus_type == MGSL_BUS_TYPE_PCI)
-				usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
-			else
-				usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1));
-		} else
-			usc_OutReg(info, TC0R, (u16)8);
-
-		/* Hardware Configuration Register (HCR) Clear Bit 1, BRG0
-		   mode = Continuous Set Bit 0 to enable BRG0.  */
-		usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
-
-		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
-		usc_OutReg(info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004));
-
-		/* set Internal Data loopback mode */
-		info->loopback_bits = 0x300;
-		outw( 0x0300, info->io_base + CCAR );
-	} else {
-		/* enable external TXD output */
-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6));
-	
-		/* clear Internal Data loopback mode */
-		info->loopback_bits = 0;
-		outw( 0,info->io_base + CCAR );
-	}
-	
-}	/* end of usc_enable_loopback() */
-
-/* usc_enable_aux_clock()
- *
- * Enabled the AUX clock output at the specified frequency.
- *
- * Arguments:
- *
- *	info		pointer to device extension
- *	data_rate	data rate of clock in bits per second
- *			A data rate of 0 disables the AUX clock.
- *
- * Return Value:	None
- */
-static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
-{
-	u32 XtalSpeed;
-	u16 Tc;
-
-	if ( data_rate ) {
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			XtalSpeed = 11059200;
-		else
-			XtalSpeed = 14745600;
-
-
-		/* Tc = (Xtal/Speed) - 1 */
-		/* If twice the remainder of (Xtal/Speed) is greater than Speed */
-		/* then rounding up gives a more precise time constant. Instead */
-		/* of rounding up and then subtracting 1 we just don't subtract */
-		/* the one in this case. */
-
-
-		Tc = (u16)(XtalSpeed/data_rate);
-		if ( !(((XtalSpeed % data_rate) * 2) / data_rate) )
-			Tc--;
-
-		/* Write 16-bit Time Constant for BRG0 */
-		usc_OutReg( info, TC0R, Tc );
-
-		/*
-		 * Hardware Configuration Register (HCR)
-		 * Clear Bit 1, BRG0 mode = Continuous
-		 * Set Bit 0 to enable BRG0.
-		 */
-
-		usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
-
-		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
-		usc_OutReg( info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) );
-	} else {
-		/* data rate == 0 so turn off BRG0 */
-		usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) );
-	}
-
-}	/* end of usc_enable_aux_clock() */
-
-/*
- *
- * usc_process_rxoverrun_sync()
- *
- *		This function processes a receive overrun by resetting the
- *		receive DMA buffers and issuing a Purge Rx FIFO command
- *		to allow the receiver to continue receiving.
- *
- * Arguments:
- *
- *	info		pointer to device extension
- *
- * Return Value: None
- */
-static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
-{
-	int start_index;
-	int end_index;
-	int frame_start_index;
-	bool start_of_frame_found = false;
-	bool end_of_frame_found = false;
-	bool reprogram_dma = false;
-
-	DMABUFFERENTRY *buffer_list = info->rx_buffer_list;
-	u32 phys_addr;
-
-	usc_DmaCmd( info, DmaCmd_PauseRxChannel );
-	usc_RCmd( info, RCmd_EnterHuntmode );
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	/* CurrentRxBuffer points to the 1st buffer of the next */
-	/* possibly available receive frame. */
-	
-	frame_start_index = start_index = end_index = info->current_rx_buffer;
-
-	/* Search for an unfinished string of buffers. This means */
-	/* that a receive frame started (at least one buffer with */
-	/* count set to zero) but there is no terminiting buffer */
-	/* (status set to non-zero). */
-
-	while( !buffer_list[end_index].count )
-	{
-		/* Count field has been reset to zero by 16C32. */
-		/* This buffer is currently in use. */
-
-		if ( !start_of_frame_found )
-		{
-			start_of_frame_found = true;
-			frame_start_index = end_index;
-			end_of_frame_found = false;
-		}
-
-		if ( buffer_list[end_index].status )
-		{
-			/* Status field has been set by 16C32. */
-			/* This is the last buffer of a received frame. */
-
-			/* We want to leave the buffers for this frame intact. */
-			/* Move on to next possible frame. */
-
-			start_of_frame_found = false;
-			end_of_frame_found = true;
-		}
-
-  		/* advance to next buffer entry in linked list */
-  		end_index++;
-  		if ( end_index == info->rx_buffer_count )
-  			end_index = 0;
-
-		if ( start_index == end_index )
-		{
-			/* The entire list has been searched with all Counts == 0 and */
-			/* all Status == 0. The receive buffers are */
-			/* completely screwed, reset all receive buffers! */
-			mgsl_reset_rx_dma_buffers( info );
-			frame_start_index = 0;
-			start_of_frame_found = false;
-			reprogram_dma = true;
-			break;
-		}
-	}
-
-	if ( start_of_frame_found && !end_of_frame_found )
-	{
-		/* There is an unfinished string of receive DMA buffers */
-		/* as a result of the receiver overrun. */
-
-		/* Reset the buffers for the unfinished frame */
-		/* and reprogram the receive DMA controller to start */
-		/* at the 1st buffer of unfinished frame. */
-
-		start_index = frame_start_index;
-
-		do
-		{
-			*((unsigned long *)&(info->rx_buffer_list[start_index++].count)) = DMABUFFERSIZE;
-
-  			/* Adjust index for wrap around. */
-  			if ( start_index == info->rx_buffer_count )
-  				start_index = 0;
-
-		} while( start_index != end_index );
-
-		reprogram_dma = true;
-	}
-
-	if ( reprogram_dma )
-	{
-		usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA|RECEIVE_STATUS);
-		usc_UnlatchRxstatusBits(info, RECEIVE_DATA|RECEIVE_STATUS);
-		
-		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
-		
-		/* This empties the receive FIFO and loads the RCC with RCLR */
-		usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-
-		/* program 16C32 with physical address of 1st DMA buffer entry */
-		phys_addr = info->rx_buffer_list[frame_start_index].phys_entry;
-		usc_OutDmaReg( info, NRARL, (u16)phys_addr );
-		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
-
-		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-		usc_EnableInterrupts( info, RECEIVE_STATUS );
-
-		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
-		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
-
-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
-		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
-		usc_DmaCmd( info, DmaCmd_InitRxChannel );
-		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
-			usc_EnableReceiver(info,ENABLE_AUTO_DCD);
-		else
-			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-	}
-	else
-	{
-		/* This empties the receive FIFO and loads the RCC with RCLR */
-		usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-		usc_RTCmd( info, RTCmd_PurgeRxFifo );
-	}
-
-}	/* end of usc_process_rxoverrun_sync() */
-
-/* usc_stop_receiver()
- *
- *	Disable USC receiver
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_stop_receiver( struct mgsl_struct *info )
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_stop_receiver(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	/* Disable receive DMA channel. */
-	/* This also disables receive DMA channel interrupts */
-	usc_DmaCmd( info, DmaCmd_ResetRxChannel );
-
-	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-	usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS );
-
-	usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
-
-	/* This empties the receive FIFO and loads the RCC with RCLR */
-	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	info->rx_enabled = false;
-	info->rx_overflow = false;
-	info->rx_rcc_underrun = false;
-	
-}	/* end of stop_receiver() */
-
-/* usc_start_receiver()
- *
- *	Enable the USC receiver 
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_start_receiver( struct mgsl_struct *info )
-{
-	u32 phys_addr;
-	
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_start_receiver(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	mgsl_reset_rx_dma_buffers( info );
-	usc_stop_receiver( info );
-
-	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		/* DMA mode Transfers */
-		/* Program the DMA controller. */
-		/* Enable the DMA controller end of buffer interrupt. */
-
-		/* program 16C32 with physical address of 1st DMA buffer entry */
-		phys_addr = info->rx_buffer_list[0].phys_entry;
-		usc_OutDmaReg( info, NRARL, (u16)phys_addr );
-		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
-
-		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-		usc_EnableInterrupts( info, RECEIVE_STATUS );
-
-		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
-		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
-
-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
-		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
-		usc_DmaCmd( info, DmaCmd_InitRxChannel );
-		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
-			usc_EnableReceiver(info,ENABLE_AUTO_DCD);
-		else
-			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-	} else {
-		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
-		usc_EnableInterrupts(info, RECEIVE_DATA);
-
-		usc_RTCmd( info, RTCmd_PurgeRxFifo );
-		usc_RCmd( info, RCmd_EnterHuntmode );
-
-		usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-	}
-
-	usc_OutReg( info, CCSR, 0x1020 );
-
-	info->rx_enabled = true;
-
-}	/* end of usc_start_receiver() */
-
-/* usc_start_transmitter()
- *
- *	Enable the USC transmitter and send a transmit frame if
- *	one is loaded in the DMA buffers.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_start_transmitter( struct mgsl_struct *info )
-{
-	u32 phys_addr;
-	unsigned int FrameSize;
-
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_start_transmitter(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	if ( info->xmit_cnt ) {
-
-		/* If auto RTS enabled and RTS is inactive, then assert */
-		/* RTS and set a flag indicating that the driver should */
-		/* negate RTS when the transmission completes. */
-
-		info->drop_rts_on_tx_done = false;
-
-		if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
-			usc_get_serial_signals( info );
-			if ( !(info->serial_signals & SerialSignal_RTS) ) {
-				info->serial_signals |= SerialSignal_RTS;
-				usc_set_serial_signals( info );
-				info->drop_rts_on_tx_done = true;
-			}
-		}
-
-
-		if ( info->params.mode == MGSL_MODE_ASYNC ) {
-			if ( !info->tx_active ) {
-				usc_UnlatchTxstatusBits(info, TXSTATUS_ALL);
-				usc_ClearIrqPendingBits(info, TRANSMIT_STATUS + TRANSMIT_DATA);
-				usc_EnableInterrupts(info, TRANSMIT_DATA);
-				usc_load_txfifo(info);
-			}
-		} else {
-			/* Disable transmit DMA controller while programming. */
-			usc_DmaCmd( info, DmaCmd_ResetTxChannel );
-			
-			/* Transmit DMA buffer is loaded, so program USC */
-			/* to send the frame contained in the buffers.	 */
-
-			FrameSize = info->tx_buffer_list[info->start_tx_dma_buffer].rcc;
-
-			/* if operating in Raw sync mode, reset the rcc component
-			 * of the tx dma buffer entry, otherwise, the serial controller
-			 * will send a closing sync char after this count.
-			 */
-	    		if ( info->params.mode == MGSL_MODE_RAW )
-				info->tx_buffer_list[info->start_tx_dma_buffer].rcc = 0;
-
-			/* Program the Transmit Character Length Register (TCLR) */
-			/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
-			usc_OutReg( info, TCLR, (u16)FrameSize );
-
-			usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-			/* Program the address of the 1st DMA Buffer Entry in linked list */
-			phys_addr = info->tx_buffer_list[info->start_tx_dma_buffer].phys_entry;
-			usc_OutDmaReg( info, NTARL, (u16)phys_addr );
-			usc_OutDmaReg( info, NTARU, (u16)(phys_addr >> 16) );
-
-			usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-			usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-			usc_EnableInterrupts( info, TRANSMIT_STATUS );
-
-			if ( info->params.mode == MGSL_MODE_RAW &&
-					info->num_tx_dma_buffers > 1 ) {
-			   /* When running external sync mode, attempt to 'stream' transmit  */
-			   /* by filling tx dma buffers as they become available. To do this */
-			   /* we need to enable Tx DMA EOB Status interrupts :               */
-			   /*                                                                */
-			   /* 1. Arm End of Buffer (EOB) Transmit DMA Interrupt (BIT2 of TDIAR) */
-			   /* 2. Enable Transmit DMA Interrupts (BIT0 of DICR) */
-
-			   usc_OutDmaReg( info, TDIAR, BIT2|BIT3 );
-			   usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT0) );
-			}
-
-			/* Initialize Transmit DMA Channel */
-			usc_DmaCmd( info, DmaCmd_InitTxChannel );
-			
-			usc_TCmd( info, TCmd_SendFrame );
-			
-			mod_timer(&info->tx_timer, jiffies +
-					msecs_to_jiffies(5000));
-		}
-		info->tx_active = true;
-	}
-
-	if ( !info->tx_enabled ) {
-		info->tx_enabled = true;
-		if ( info->params.flags & HDLC_FLAG_AUTO_CTS )
-			usc_EnableTransmitter(info,ENABLE_AUTO_CTS);
-		else
-			usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL);
-	}
-
-}	/* end of usc_start_transmitter() */
-
-/* usc_stop_transmitter()
- *
- *	Stops the transmitter and DMA
- *
- * Arguments:		info	pointer to device isntance data
- * Return Value:	None
- */
-static void usc_stop_transmitter( struct mgsl_struct *info )
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_stop_transmitter(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	del_timer(&info->tx_timer);	
-			 
-	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA );
-	usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA );
-
-	usc_EnableTransmitter(info,DISABLE_UNCONDITIONAL);
-	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
-	usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-	info->tx_enabled = false;
-	info->tx_active = false;
-
-}	/* end of usc_stop_transmitter() */
-
-/* usc_load_txfifo()
- *
- *	Fill the transmit FIFO until the FIFO is full or
- *	there is no more data to load.
- *
- * Arguments:		info	pointer to device extension (instance data)
- * Return Value:	None
- */
-static void usc_load_txfifo( struct mgsl_struct *info )
-{
-	int Fifocount;
-	u8 TwoBytes[2];
-	
-	if ( !info->xmit_cnt && !info->x_char )
-		return; 
-		
-	/* Select transmit FIFO status readback in TICR */
-	usc_TCmd( info, TCmd_SelectTicrTxFifostatus );
-
-	/* load the Transmit FIFO until FIFOs full or all data sent */
-
-	while( (Fifocount = usc_InReg(info, TICR) >> 8) && info->xmit_cnt ) {
-		/* there is more space in the transmit FIFO and */
-		/* there is more data in transmit buffer */
-
-		if ( (info->xmit_cnt > 1) && (Fifocount > 1) && !info->x_char ) {
- 			/* write a 16-bit word from transmit buffer to 16C32 */
-				
-			TwoBytes[0] = info->xmit_buf[info->xmit_tail++];
-			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-			TwoBytes[1] = info->xmit_buf[info->xmit_tail++];
-			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-			
-			outw( *((u16 *)TwoBytes), info->io_base + DATAREG);
-				
-			info->xmit_cnt -= 2;
-			info->icount.tx += 2;
-		} else {
-			/* only 1 byte left to transmit or 1 FIFO slot left */
-			
-			outw( (inw( info->io_base + CCAR) & 0x0780) | (TDR+LSBONLY),
-				info->io_base + CCAR );
-			
-			if (info->x_char) {
-				/* transmit pending high priority char */
-				outw( info->x_char,info->io_base + CCAR );
-				info->x_char = 0;
-			} else {
-				outw( info->xmit_buf[info->xmit_tail++],info->io_base + CCAR );
-				info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-				info->xmit_cnt--;
-			}
-			info->icount.tx++;
-		}
-	}
-
-}	/* end of usc_load_txfifo() */
-
-/* usc_reset()
- *
- *	Reset the adapter to a known state and prepare it for further use.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_reset( struct mgsl_struct *info )
-{
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		int i;
-		u32 readval;
-
-		/* Set BIT30 of Misc Control Register */
-		/* (Local Control Register 0x50) to force reset of USC. */
-
-		volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
-		u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);
-
-		info->misc_ctrl_value |= BIT30;
-		*MiscCtrl = info->misc_ctrl_value;
-
-		/*
-		 * Force at least 170ns delay before clearing 
-		 * reset bit. Each read from LCR takes at least 
-		 * 30ns so 10 times for 300ns to be safe.
-		 */
-		for(i=0;i<10;i++)
-			readval = *MiscCtrl;
-
-		info->misc_ctrl_value &= ~BIT30;
-		*MiscCtrl = info->misc_ctrl_value;
-
-		*LCR0BRDR = BUS_DESCRIPTOR(
-			1,		// Write Strobe Hold (0-3)
-			2,		// Write Strobe Delay (0-3)
-			2,		// Read Strobe Delay  (0-3)
-			0,		// NWDD (Write data-data) (0-3)
-			4,		// NWAD (Write Addr-data) (0-31)
-			0,		// NXDA (Read/Write Data-Addr) (0-3)
-			0,		// NRDD (Read Data-Data) (0-3)
-			5		// NRAD (Read Addr-Data) (0-31)
-			);
-	} else {
-		/* do HW reset */
-		outb( 0,info->io_base + 8 );
-	}
-
-	info->mbre_bit = 0;
-	info->loopback_bits = 0;
-	info->usc_idle_mode = 0;
-
-	/*
-	 * Program the Bus Configuration Register (BCR)
-	 *
-	 * <15>		0	Don't use separate address
-	 * <14..6>	0	reserved
-	 * <5..4>	00	IAckmode = Default, don't care
-	 * <3>		1	Bus Request Totem Pole output
-	 * <2>		1	Use 16 Bit data bus
-	 * <1>		0	IRQ Totem Pole output
-	 * <0>		0	Don't Shift Right Addr
-	 *
-	 * 0000 0000 0000 1100 = 0x000c
-	 *
-	 * By writing to io_base + SDPIN the Wait/Ack pin is
-	 * programmed to work as a Wait pin.
-	 */
-	
-	outw( 0x000c,info->io_base + SDPIN );
-
-
-	outw( 0,info->io_base );
-	outw( 0,info->io_base + CCAR );
-
-	/* select little endian byte ordering */
-	usc_RTCmd( info, RTCmd_SelectLittleEndian );
-
-
-	/* Port Control Register (PCR)
-	 *
-	 * <15..14>	11	Port 7 is Output (~DMAEN, Bit 14 : 0 = Enabled)
-	 * <13..12>	11	Port 6 is Output (~INTEN, Bit 12 : 0 = Enabled)
-	 * <11..10> 	00	Port 5 is Input (No Connect, Don't Care)
-	 * <9..8> 	00	Port 4 is Input (No Connect, Don't Care)
-	 * <7..6>	11	Port 3 is Output (~RTS, Bit 6 : 0 = Enabled )
-	 * <5..4>	11	Port 2 is Output (~DTR, Bit 4 : 0 = Enabled )
-	 * <3..2>	01	Port 1 is Input (Dedicated RxC)
-	 * <1..0>	01	Port 0 is Input (Dedicated TxC)
-	 *
-	 *	1111 0000 1111 0101 = 0xf0f5
-	 */
-
-	usc_OutReg( info, PCR, 0xf0f5 );
-
-
-	/*
-	 * Input/Output Control Register
-	 *
-	 * <15..14>	00	CTS is active low input
-	 * <13..12>	00	DCD is active low input
-	 * <11..10>	00	TxREQ pin is input (DSR)
-	 * <9..8>	00	RxREQ pin is input (RI)
-	 * <7..6>	00	TxD is output (Transmit Data)
-	 * <5..3>	000	TxC Pin in Input (14.7456MHz Clock)
-	 * <2..0>	100	RxC is Output (drive with BRG0)
-	 *
-	 *	0000 0000 0000 0100 = 0x0004
-	 */
-
-	usc_OutReg( info, IOCR, 0x0004 );
-
-}	/* end of usc_reset() */
-
-/* usc_set_async_mode()
- *
- *	Program adapter for asynchronous communications.
- *
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void usc_set_async_mode( struct mgsl_struct *info )
-{
-	u16 RegValue;
-
-	/* disable interrupts while programming USC */
-	usc_DisableMasterIrqBit( info );
-
-	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
-	usc_DmaCmd( info, DmaCmd_ResetAllChannels );	/* disable both DMA channels */
-
-	usc_loopback_frame( info );
-
-	/* Channel mode Register (CMR)
-	 *
-	 * <15..14>	00	Tx Sub modes, 00 = 1 Stop Bit
-	 * <13..12>	00	              00 = 16X Clock
-	 * <11..8>	0000	Transmitter mode = Asynchronous
-	 * <7..6>	00	reserved?
-	 * <5..4>	00	Rx Sub modes, 00 = 16X Clock
-	 * <3..0>	0000	Receiver mode = Asynchronous
-	 *
-	 * 0000 0000 0000 0000 = 0x0
-	 */
-
-	RegValue = 0;
-	if ( info->params.stop_bits != 1 )
-		RegValue |= BIT14;
-	usc_OutReg( info, CMR, RegValue );
-
-	
-	/* Receiver mode Register (RMR)
-	 *
-	 * <15..13>	000	encoding = None
-	 * <12..08>	00000	reserved (Sync Only)
-	 * <7..6>   	00	Even parity
-	 * <5>		0	parity disabled
-	 * <4..2>	000	Receive Char Length = 8 bits
-	 * <1..0>	00	Disable Receiver
-	 *
-	 * 0000 0000 0000 0000 = 0x0
-	 */
-
-	RegValue = 0;
-
-	if ( info->params.data_bits != 8 )
-		RegValue |= BIT4+BIT3+BIT2;
-
-	if ( info->params.parity != ASYNC_PARITY_NONE ) {
-		RegValue |= BIT5;
-		if ( info->params.parity != ASYNC_PARITY_ODD )
-			RegValue |= BIT6;
-	}
-
-	usc_OutReg( info, RMR, RegValue );
-
-
-	/* Set IRQ trigger level */
-
-	usc_RCmd( info, RCmd_SelectRicrIntLevel );
-
-	
-	/* Receive Interrupt Control Register (RICR)
-	 *
-	 * <15..8>	?		RxFIFO IRQ Request Level
-	 *
-	 * Note: For async mode the receive FIFO level must be set
-	 * to 0 to avoid the situation where the FIFO contains fewer bytes
-	 * than the trigger level and no more data is expected.
-	 *
-	 * <7>		0		Exited Hunt IA (Interrupt Arm)
-	 * <6>		0		Idle Received IA
-	 * <5>		0		Break/Abort IA
-	 * <4>		0		Rx Bound IA
-	 * <3>		0		Queued status reflects oldest byte in FIFO
-	 * <2>		0		Abort/PE IA
-	 * <1>		0		Rx Overrun IA
-	 * <0>		0		Select TC0 value for readback
-	 *
-	 * 0000 0000 0100 0000 = 0x0000 + (FIFOLEVEL in MSB)
-	 */
-	
-	usc_OutReg( info, RICR, 0x0000 );
-
-	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
-
-	
-	/* Transmit mode Register (TMR)
-	 *
-	 * <15..13>	000	encoding = None
-	 * <12..08>	00000	reserved (Sync Only)
-	 * <7..6>	00	Transmit parity Even
-	 * <5>		0	Transmit parity Disabled
-	 * <4..2>	000	Tx Char Length = 8 bits
-	 * <1..0>	00	Disable Transmitter
-	 *
-	 * 0000 0000 0000 0000 = 0x0
-	 */
-
-	RegValue = 0;
-
-	if ( info->params.data_bits != 8 )
-		RegValue |= BIT4+BIT3+BIT2;
-
-	if ( info->params.parity != ASYNC_PARITY_NONE ) {
-		RegValue |= BIT5;
-		if ( info->params.parity != ASYNC_PARITY_ODD )
-			RegValue |= BIT6;
-	}
-
-	usc_OutReg( info, TMR, RegValue );
-
-	usc_set_txidle( info );
-
-
-	/* Set IRQ trigger level */
-
-	usc_TCmd( info, TCmd_SelectTicrIntLevel );
-
-	
-	/* Transmit Interrupt Control Register (TICR)
-	 *
-	 * <15..8>	?	Transmit FIFO IRQ Level
-	 * <7>		0	Present IA (Interrupt Arm)
-	 * <6>		1	Idle Sent IA
-	 * <5>		0	Abort Sent IA
-	 * <4>		0	EOF/EOM Sent IA
-	 * <3>		0	CRC Sent IA
-	 * <2>		0	1 = Wait for SW Trigger to Start Frame
-	 * <1>		0	Tx Underrun IA
-	 * <0>		0	TC0 constant on read back
-	 *
-	 *	0000 0000 0100 0000 = 0x0040
-	 */
-
-	usc_OutReg( info, TICR, 0x1f40 );
-
-	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-
-	usc_enable_async_clock( info, info->params.data_rate );
-
-	
-	/* Channel Control/status Register (CCSR)
-	 *
-	 * <15>		X	RCC FIFO Overflow status (RO)
-	 * <14>		X	RCC FIFO Not Empty status (RO)
-	 * <13>		0	1 = Clear RCC FIFO (WO)
-	 * <12>		X	DPLL in Sync status (RO)
-	 * <11>		X	DPLL 2 Missed Clocks status (RO)
-	 * <10>		X	DPLL 1 Missed Clock status (RO)
-	 * <9..8>	00	DPLL Resync on rising and falling edges (RW)
-	 * <7>		X	SDLC Loop On status (RO)
-	 * <6>		X	SDLC Loop Send status (RO)
-	 * <5>		1	Bypass counters for TxClk and RxClk (RW)
-	 * <4..2>   	000	Last Char of SDLC frame has 8 bits (RW)
-	 * <1..0>   	00	reserved
-	 *
-	 *	0000 0000 0010 0000 = 0x0020
-	 */
-	
-	usc_OutReg( info, CCSR, 0x0020 );
-
-	usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA +
-			      RECEIVE_DATA + RECEIVE_STATUS );
-
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA +
-				RECEIVE_DATA + RECEIVE_STATUS );
-
-	usc_EnableMasterIrqBit( info );
-
-	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
-		/* Enable INTEN (Port 6, Bit12) */
-		/* This connects the IRQ request signal to the ISA bus */
-		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
-	}
-
-	if (info->params.loopback) {
-		info->loopback_bits = 0x300;
-		outw(0x0300, info->io_base + CCAR);
-	}
-
-}	/* end of usc_set_async_mode() */
-
-/* usc_loopback_frame()
- *
- *	Loop back a small (2 byte) dummy SDLC frame.
- *	Interrupts and DMA are NOT used. The purpose of this is to
- *	clear any 'stale' status info left over from running in	async mode.
- *
- *	The 16C32 shows the strange behaviour of marking the 1st
- *	received SDLC frame with a CRC error even when there is no
- *	CRC error. To get around this a small dummy from of 2 bytes
- *	is looped back when switching from async to sync mode.
- *
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void usc_loopback_frame( struct mgsl_struct *info )
-{
-	int i;
-	unsigned long oldmode = info->params.mode;
-
-	info->params.mode = MGSL_MODE_HDLC;
-	
-	usc_DisableMasterIrqBit( info );
-
-	usc_set_sdlc_mode( info );
-	usc_enable_loopback( info, 1 );
-
-	/* Write 16-bit Time Constant for BRG0 */
-	usc_OutReg( info, TC0R, 0 );
-	
-	/* Channel Control Register (CCR)
-	 *
-	 * <15..14>	00	Don't use 32-bit Tx Control Blocks (TCBs)
-	 * <13>		0	Trigger Tx on SW Command Disabled
-	 * <12>		0	Flag Preamble Disabled
-	 * <11..10>	00	Preamble Length = 8-Bits
-	 * <9..8>	01	Preamble Pattern = flags
-	 * <7..6>	10	Don't use 32-bit Rx status Blocks (RSBs)
-	 * <5>		0	Trigger Rx on SW Command Disabled
-	 * <4..0>	0	reserved
-	 *
-	 *	0000 0001 0000 0000 = 0x0100
-	 */
-
-	usc_OutReg( info, CCR, 0x0100 );
-
-	/* SETUP RECEIVER */
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-	usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-
-	/* SETUP TRANSMITTER */
-	/* Program the Transmit Character Length Register (TCLR) */
-	/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
-	usc_OutReg( info, TCLR, 2 );
-	usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-	/* unlatch Tx status bits, and start transmit channel. */
-	usc_UnlatchTxstatusBits(info,TXSTATUS_ALL);
-	outw(0,info->io_base + DATAREG);
-
-	/* ENABLE TRANSMITTER */
-	usc_TCmd( info, TCmd_SendFrame );
-	usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL);
-							
-	/* WAIT FOR RECEIVE COMPLETE */
-	for (i=0 ; i<1000 ; i++)
-		if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1))
-			break;
-
-	/* clear Internal Data loopback mode */
-	usc_enable_loopback(info, 0);
-
-	usc_EnableMasterIrqBit(info);
-
-	info->params.mode = oldmode;
-
-}	/* end of usc_loopback_frame() */
-
-/* usc_set_sync_mode()	Programs the USC for SDLC communications.
- *
- * Arguments:		info	pointer to adapter info structure
- * Return Value:	None
- */
-static void usc_set_sync_mode( struct mgsl_struct *info )
-{
-	usc_loopback_frame( info );
-	usc_set_sdlc_mode( info );
-
-	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
-		/* Enable INTEN (Port 6, Bit12) */
-		/* This connects the IRQ request signal to the ISA bus */
-		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
-	}
-
-	usc_enable_aux_clock(info, info->params.clock_speed);
-
-	if (info->params.loopback)
-		usc_enable_loopback(info,1);
-
-}	/* end of mgsl_set_sync_mode() */
-
-/* usc_set_txidle()	Set the HDLC idle mode for the transmitter.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_set_txidle( struct mgsl_struct *info )
-{
-	u16 usc_idle_mode = IDLEMODE_FLAGS;
-
-	/* Map API idle mode to USC register bits */
-
-	switch( info->idle_mode ){
-	case HDLC_TXIDLE_FLAGS:			usc_idle_mode = IDLEMODE_FLAGS; break;
-	case HDLC_TXIDLE_ALT_ZEROS_ONES:	usc_idle_mode = IDLEMODE_ALT_ONE_ZERO; break;
-	case HDLC_TXIDLE_ZEROS:			usc_idle_mode = IDLEMODE_ZERO; break;
-	case HDLC_TXIDLE_ONES:			usc_idle_mode = IDLEMODE_ONE; break;
-	case HDLC_TXIDLE_ALT_MARK_SPACE:	usc_idle_mode = IDLEMODE_ALT_MARK_SPACE; break;
-	case HDLC_TXIDLE_SPACE:			usc_idle_mode = IDLEMODE_SPACE; break;
-	case HDLC_TXIDLE_MARK:			usc_idle_mode = IDLEMODE_MARK; break;
-	}
-
-	info->usc_idle_mode = usc_idle_mode;
-	//usc_OutReg(info, TCSR, usc_idle_mode);
-	info->tcsr_value &= ~IDLEMODE_MASK;	/* clear idle mode bits */
-	info->tcsr_value += usc_idle_mode;
-	usc_OutReg(info, TCSR, info->tcsr_value);
-
-	/*
-	 * if SyncLink WAN adapter is running in external sync mode, the
-	 * transmitter has been set to Monosync in order to try to mimic
-	 * a true raw outbound bit stream. Monosync still sends an open/close
-	 * sync char at the start/end of a frame. Try to match those sync
-	 * patterns to the idle mode set here
-	 */
-	if ( info->params.mode == MGSL_MODE_RAW ) {
-		unsigned char syncpat = 0;
-		switch( info->idle_mode ) {
-		case HDLC_TXIDLE_FLAGS:
-			syncpat = 0x7e;
-			break;
-		case HDLC_TXIDLE_ALT_ZEROS_ONES:
-			syncpat = 0x55;
-			break;
-		case HDLC_TXIDLE_ZEROS:
-		case HDLC_TXIDLE_SPACE:
-			syncpat = 0x00;
-			break;
-		case HDLC_TXIDLE_ONES:
-		case HDLC_TXIDLE_MARK:
-			syncpat = 0xff;
-			break;
-		case HDLC_TXIDLE_ALT_MARK_SPACE:
-			syncpat = 0xaa;
-			break;
-		}
-
-		usc_SetTransmitSyncChars(info,syncpat,syncpat);
-	}
-
-}	/* end of usc_set_txidle() */
-
-/* usc_get_serial_signals()
- *
- *	Query the adapter for the state of the V24 status (input) signals.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_get_serial_signals( struct mgsl_struct *info )
-{
-	u16 status;
-
-	/* clear all serial signals except DTR and RTS */
-	info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
-
-	/* Read the Misc Interrupt status Register (MISR) to get */
-	/* the V24 status signals. */
-
-	status = usc_InReg( info, MISR );
-
-	/* set serial signal bits to reflect MISR */
-
-	if ( status & MISCSTATUS_CTS )
-		info->serial_signals |= SerialSignal_CTS;
-
-	if ( status & MISCSTATUS_DCD )
-		info->serial_signals |= SerialSignal_DCD;
-
-	if ( status & MISCSTATUS_RI )
-		info->serial_signals |= SerialSignal_RI;
-
-	if ( status & MISCSTATUS_DSR )
-		info->serial_signals |= SerialSignal_DSR;
-
-}	/* end of usc_get_serial_signals() */
-
-/* usc_set_serial_signals()
- *
- *	Set the state of DTR and RTS based on contents of
- *	serial_signals member of device extension.
- *	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_set_serial_signals( struct mgsl_struct *info )
-{
-	u16 Control;
-	unsigned char V24Out = info->serial_signals;
-
-	/* get the current value of the Port Control Register (PCR) */
-
-	Control = usc_InReg( info, PCR );
-
-	if ( V24Out & SerialSignal_RTS )
-		Control &= ~(BIT6);
-	else
-		Control |= BIT6;
-
-	if ( V24Out & SerialSignal_DTR )
-		Control &= ~(BIT4);
-	else
-		Control |= BIT4;
-
-	usc_OutReg( info, PCR, Control );
-
-}	/* end of usc_set_serial_signals() */
-
-/* usc_enable_async_clock()
- *
- *	Enable the async clock at the specified frequency.
- *
- * Arguments:		info		pointer to device instance data
- *			data_rate	data rate of clock in bps
- *					0 disables the AUX clock.
- * Return Value:	None
- */
-static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
-{
-	if ( data_rate )	{
-		/*
-		 * Clock mode Control Register (CMCR)
-		 * 
-		 * <15..14>     00      counter 1 Disabled
-		 * <13..12>     00      counter 0 Disabled
-		 * <11..10>     11      BRG1 Input is TxC Pin
-		 * <9..8>       11      BRG0 Input is TxC Pin
-		 * <7..6>       01      DPLL Input is BRG1 Output
-		 * <5..3>       100     TxCLK comes from BRG0
-		 * <2..0>       100     RxCLK comes from BRG0
-		 *
-		 * 0000 1111 0110 0100 = 0x0f64
-		 */
-		
-		usc_OutReg( info, CMCR, 0x0f64 );
-
-
-		/*
-		 * Write 16-bit Time Constant for BRG0
-		 * Time Constant = (ClkSpeed / data_rate) - 1
-		 * ClkSpeed = 921600 (ISA), 691200 (PCI)
-		 */
-
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
-		else
-			usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) );
-
-		
-		/*
-		 * Hardware Configuration Register (HCR)
-		 * Clear Bit 1, BRG0 mode = Continuous
-		 * Set Bit 0 to enable BRG0.
-		 */
-
-		usc_OutReg( info, HCR,
-			    (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
-
-
-		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
-
-		usc_OutReg( info, IOCR,
-			    (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) );
-	} else {
-		/* data rate == 0 so turn off BRG0 */
-		usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) );
-	}
-
-}	/* end of usc_enable_async_clock() */
-
-/*
- * Buffer Structures:
- *
- * Normal memory access uses virtual addresses that can make discontiguous
- * physical memory pages appear to be contiguous in the virtual address
- * space (the processors memory mapping handles the conversions).
- *
- * DMA transfers require physically contiguous memory. This is because
- * the DMA system controller and DMA bus masters deal with memory using
- * only physical addresses.
- *
- * This causes a problem under Windows NT when large DMA buffers are
- * needed. Fragmentation of the nonpaged pool prevents allocations of
- * physically contiguous buffers larger than the PAGE_SIZE.
- *
- * However the 16C32 supports Bus Master Scatter/Gather DMA which
- * allows DMA transfers to physically discontiguous buffers. Information
- * about each data transfer buffer is contained in a memory structure
- * called a 'buffer entry'. A list of buffer entries is maintained
- * to track and control the use of the data transfer buffers.
- *
- * To support this strategy we will allocate sufficient PAGE_SIZE
- * contiguous memory buffers to allow for the total required buffer
- * space.
- *
- * The 16C32 accesses the list of buffer entries using Bus Master
- * DMA. Control information is read from the buffer entries by the
- * 16C32 to control data transfers. status information is written to
- * the buffer entries by the 16C32 to indicate the status of completed
- * transfers.
- *
- * The CPU writes control information to the buffer entries to control
- * the 16C32 and reads status information from the buffer entries to
- * determine information about received and transmitted frames.
- *
- * Because the CPU and 16C32 (adapter) both need simultaneous access
- * to the buffer entries, the buffer entry memory is allocated with
- * HalAllocateCommonBuffer(). This restricts the size of the buffer
- * entry list to PAGE_SIZE.
- *
- * The actual data buffers on the other hand will only be accessed
- * by the CPU or the adapter but not by both simultaneously. This allows
- * Scatter/Gather packet based DMA procedures for using physically
- * discontiguous pages.
- */
-
-/*
- * mgsl_reset_tx_dma_buffers()
- *
- * 	Set the count for all transmit buffers to 0 to indicate the
- * 	buffer is available for use and set the current buffer to the
- * 	first buffer. This effectively makes all buffers free and
- * 	discards any data in buffers.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
-{
-	unsigned int i;
-
-	for ( i = 0; i < info->tx_buffer_count; i++ ) {
-		*((unsigned long *)&(info->tx_buffer_list[i].count)) = 0;
-	}
-
-	info->current_tx_buffer = 0;
-	info->start_tx_dma_buffer = 0;
-	info->tx_dma_buffers_used = 0;
-
-	info->get_tx_holding_index = 0;
-	info->put_tx_holding_index = 0;
-	info->tx_holding_count = 0;
-
-}	/* end of mgsl_reset_tx_dma_buffers() */
-
-/*
- * num_free_tx_dma_buffers()
- *
- * 	returns the number of free tx dma buffers available
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	number of free tx dma buffers
- */
-static int num_free_tx_dma_buffers(struct mgsl_struct *info)
-{
-	return info->tx_buffer_count - info->tx_dma_buffers_used;
-}
-
-/*
- * mgsl_reset_rx_dma_buffers()
- * 
- * 	Set the count for all receive buffers to DMABUFFERSIZE
- * 	and set the current buffer to the first buffer. This effectively
- * 	makes all buffers free and discards any data in buffers.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
-{
-	unsigned int i;
-
-	for ( i = 0; i < info->rx_buffer_count; i++ ) {
-		*((unsigned long *)&(info->rx_buffer_list[i].count)) = DMABUFFERSIZE;
-//		info->rx_buffer_list[i].count = DMABUFFERSIZE;
-//		info->rx_buffer_list[i].status = 0;
-	}
-
-	info->current_rx_buffer = 0;
-
-}	/* end of mgsl_reset_rx_dma_buffers() */
-
-/*
- * mgsl_free_rx_frame_buffers()
- * 
- * 	Free the receive buffers used by a received SDLC
- * 	frame such that the buffers can be reused.
- * 
- * Arguments:
- * 
- * 	info			pointer to device instance data
- * 	StartIndex		index of 1st receive buffer of frame
- * 	EndIndex		index of last receive buffer of frame
- * 
- * Return Value:	None
- */
-static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
-{
-	bool Done = false;
-	DMABUFFERENTRY *pBufEntry;
-	unsigned int Index;
-
-	/* Starting with 1st buffer entry of the frame clear the status */
-	/* field and set the count field to DMA Buffer Size. */
-
-	Index = StartIndex;
-
-	while( !Done ) {
-		pBufEntry = &(info->rx_buffer_list[Index]);
-
-		if ( Index == EndIndex ) {
-			/* This is the last buffer of the frame! */
-			Done = true;
-		}
-
-		/* reset current buffer for reuse */
-//		pBufEntry->status = 0;
-//		pBufEntry->count = DMABUFFERSIZE;
-		*((unsigned long *)&(pBufEntry->count)) = DMABUFFERSIZE;
-
-		/* advance to next buffer entry in linked list */
-		Index++;
-		if ( Index == info->rx_buffer_count )
-			Index = 0;
-	}
-
-	/* set current buffer to next buffer after last buffer of frame */
-	info->current_rx_buffer = Index;
-
-}	/* end of free_rx_frame_buffers() */
-
-/* mgsl_get_rx_frame()
- * 
- * 	This function attempts to return a received SDLC frame from the
- * 	receive DMA buffers. Only frames received without errors are returned.
- *
- * Arguments:	 	info	pointer to device extension
- * Return Value:	true if frame returned, otherwise false
- */
-static bool mgsl_get_rx_frame(struct mgsl_struct *info)
-{
-	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
-	unsigned short status;
-	DMABUFFERENTRY *pBufEntry;
-	unsigned int framesize = 0;
-	bool ReturnCode = false;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-	bool return_frame = false;
-	
-	/*
-	 * current_rx_buffer points to the 1st buffer of the next available
-	 * receive frame. To find the last buffer of the frame look for
-	 * a non-zero status field in the buffer entries. (The status
-	 * field is set by the 16C32 after completing a receive frame.
-	 */
-
-	StartIndex = EndIndex = info->current_rx_buffer;
-
-	while( !info->rx_buffer_list[EndIndex].status ) {
-		/*
-		 * If the count field of the buffer entry is non-zero then
-		 * this buffer has not been used. (The 16C32 clears the count
-		 * field when it starts using the buffer.) If an unused buffer
-		 * is encountered then there are no frames available.
-		 */
-
-		if ( info->rx_buffer_list[EndIndex].count )
-			goto Cleanup;
-
-		/* advance to next buffer entry in linked list */
-		EndIndex++;
-		if ( EndIndex == info->rx_buffer_count )
-			EndIndex = 0;
-
-		/* if entire list searched then no frame available */
-		if ( EndIndex == StartIndex ) {
-			/* If this occurs then something bad happened,
-			 * all buffers have been 'used' but none mark
-			 * the end of a frame. Reset buffers and receiver.
-			 */
-
-			if ( info->rx_enabled ){
-				spin_lock_irqsave(&info->irq_spinlock,flags);
-				usc_start_receiver(info);
-				spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			}
-			goto Cleanup;
-		}
-	}
-
-
-	/* check status of receive frame */
-	
-	status = info->rx_buffer_list[EndIndex].status;
-
-	if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
-			RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
-		if ( status & RXSTATUS_SHORT_FRAME )
-			info->icount.rxshort++;
-		else if ( status & RXSTATUS_ABORT )
-			info->icount.rxabort++;
-		else if ( status & RXSTATUS_OVERRUN )
-			info->icount.rxover++;
-		else {
-			info->icount.rxcrc++;
-			if ( info->params.crc_type & HDLC_CRC_RETURN_EX )
-				return_frame = true;
-		}
-		framesize = 0;
-#if SYNCLINK_GENERIC_HDLC
-		{
-			info->netdev->stats.rx_errors++;
-			info->netdev->stats.rx_frame_errors++;
-		}
-#endif
-	} else
-		return_frame = true;
-
-	if ( return_frame ) {
-		/* receive frame has no errors, get frame size.
-		 * The frame size is the starting value of the RCC (which was
-		 * set to 0xffff) minus the ending value of the RCC (decremented
-		 * once for each receive character) minus 2 for the 16-bit CRC.
-		 */
-
-		framesize = RCLRVALUE - info->rx_buffer_list[EndIndex].rcc;
-
-		/* adjust frame size for CRC if any */
-		if ( info->params.crc_type == HDLC_CRC_16_CCITT )
-			framesize -= 2;
-		else if ( info->params.crc_type == HDLC_CRC_32_CCITT )
-			framesize -= 4;		
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk("%s(%d):mgsl_get_rx_frame(%s) status=%04X size=%d\n",
-			__FILE__,__LINE__,info->device_name,status,framesize);
-			
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
-			min_t(int, framesize, DMABUFFERSIZE),0);
-		
-	if (framesize) {
-		if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
-				((framesize+1) > info->max_frame_size) ) ||
-			(framesize > info->max_frame_size) )
-			info->icount.rxlong++;
-		else {
-			/* copy dma buffer(s) to contiguous intermediate buffer */
-			int copy_count = framesize;
-			int index = StartIndex;
-			unsigned char *ptmp = info->intermediate_rxbuffer;
-
-			if ( !(status & RXSTATUS_CRC_ERROR))
-			info->icount.rxok++;
-			
-			while(copy_count) {
-				int partial_count;
-				if ( copy_count > DMABUFFERSIZE )
-					partial_count = DMABUFFERSIZE;
-				else
-					partial_count = copy_count;
-			
-				pBufEntry = &(info->rx_buffer_list[index]);
-				memcpy( ptmp, pBufEntry->virt_addr, partial_count );
-				ptmp += partial_count;
-				copy_count -= partial_count;
-				
-				if ( ++index == info->rx_buffer_count )
-					index = 0;
-			}
-
-			if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) {
-				++framesize;
-				*ptmp = (status & RXSTATUS_CRC_ERROR ?
-						RX_CRC_ERROR :
-						RX_OK);
-
-				if ( debug_level >= DEBUG_LEVEL_DATA )
-					printk("%s(%d):mgsl_get_rx_frame(%s) rx frame status=%d\n",
-						__FILE__,__LINE__,info->device_name,
-						*ptmp);
-			}
-
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount)
-				hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
-			else
-#endif
-				ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-		}
-	}
-	/* Free the buffers used by this frame. */
-	mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex );
-
-	ReturnCode = true;
-
-Cleanup:
-
-	if ( info->rx_enabled && info->rx_overflow ) {
-		/* The receiver needs to restarted because of 
-		 * a receive overflow (buffer or FIFO). If the 
-		 * receive buffers are now empty, then restart receiver.
-		 */
-
-		if ( !info->rx_buffer_list[EndIndex].status &&
-			info->rx_buffer_list[EndIndex].count ) {
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			usc_start_receiver(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		}
-	}
-
-	return ReturnCode;
-
-}	/* end of mgsl_get_rx_frame() */
-
-/* mgsl_get_raw_rx_frame()
- *
- *     	This function attempts to return a received frame from the
- *	receive DMA buffers when running in external loop mode. In this mode,
- *	we will return at most one DMABUFFERSIZE frame to the application.
- *	The USC receiver is triggering off of DCD going active to start a new
- *	frame, and DCD going inactive to terminate the frame (similar to
- *	processing a closing flag character).
- *
- *	In this routine, we will return DMABUFFERSIZE "chunks" at a time.
- *	If DCD goes inactive, the last Rx DMA Buffer will have a non-zero
- * 	status field and the RCC field will indicate the length of the
- *	entire received frame. We take this RCC field and get the modulus
- *	of RCC and DMABUFFERSIZE to determine if number of bytes in the
- *	last Rx DMA buffer and return that last portion of the frame.
- *
- * Arguments:	 	info	pointer to device extension
- * Return Value:	true if frame returned, otherwise false
- */
-static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info)
-{
-	unsigned int CurrentIndex, NextIndex;
-	unsigned short status;
-	DMABUFFERENTRY *pBufEntry;
-	unsigned int framesize = 0;
-	bool ReturnCode = false;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-
-	/*
- 	 * current_rx_buffer points to the 1st buffer of the next available
-	 * receive frame. The status field is set by the 16C32 after
-	 * completing a receive frame. If the status field of this buffer
-	 * is zero, either the USC is still filling this buffer or this
-	 * is one of a series of buffers making up a received frame.
-	 *
-	 * If the count field of this buffer is zero, the USC is either
-	 * using this buffer or has used this buffer. Look at the count
-	 * field of the next buffer. If that next buffer's count is
-	 * non-zero, the USC is still actively using the current buffer.
-	 * Otherwise, if the next buffer's count field is zero, the
-	 * current buffer is complete and the USC is using the next
-	 * buffer.
-	 */
-	CurrentIndex = NextIndex = info->current_rx_buffer;
-	++NextIndex;
-	if ( NextIndex == info->rx_buffer_count )
-		NextIndex = 0;
-
-	if ( info->rx_buffer_list[CurrentIndex].status != 0 ||
-		(info->rx_buffer_list[CurrentIndex].count == 0 &&
-			info->rx_buffer_list[NextIndex].count == 0)) {
-		/*
-	 	 * Either the status field of this dma buffer is non-zero
-		 * (indicating the last buffer of a receive frame) or the next
-	 	 * buffer is marked as in use -- implying this buffer is complete
-		 * and an intermediate buffer for this received frame.
-	 	 */
-
-		status = info->rx_buffer_list[CurrentIndex].status;
-
-		if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
-				RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
-			if ( status & RXSTATUS_SHORT_FRAME )
-				info->icount.rxshort++;
-			else if ( status & RXSTATUS_ABORT )
-				info->icount.rxabort++;
-			else if ( status & RXSTATUS_OVERRUN )
-				info->icount.rxover++;
-			else
-				info->icount.rxcrc++;
-			framesize = 0;
-		} else {
-			/*
-			 * A receive frame is available, get frame size and status.
-			 *
-			 * The frame size is the starting value of the RCC (which was
-			 * set to 0xffff) minus the ending value of the RCC (decremented
-			 * once for each receive character) minus 2 or 4 for the 16-bit
-			 * or 32-bit CRC.
-			 *
-			 * If the status field is zero, this is an intermediate buffer.
-			 * It's size is 4K.
-			 *
-			 * If the DMA Buffer Entry's Status field is non-zero, the
-			 * receive operation completed normally (ie: DCD dropped). The
-			 * RCC field is valid and holds the received frame size.
-			 * It is possible that the RCC field will be zero on a DMA buffer
-			 * entry with a non-zero status. This can occur if the total
-			 * frame size (number of bytes between the time DCD goes active
-			 * to the time DCD goes inactive) exceeds 65535 bytes. In this
-			 * case the 16C32 has underrun on the RCC count and appears to
-			 * stop updating this counter to let us know the actual received
-			 * frame size. If this happens (non-zero status and zero RCC),
-			 * simply return the entire RxDMA Buffer
-			 */
-			if ( status ) {
-				/*
-				 * In the event that the final RxDMA Buffer is
-				 * terminated with a non-zero status and the RCC
-				 * field is zero, we interpret this as the RCC
-				 * having underflowed (received frame > 65535 bytes).
-				 *
-				 * Signal the event to the user by passing back
-				 * a status of RxStatus_CrcError returning the full
-				 * buffer and let the app figure out what data is
-				 * actually valid
-				 */
-				if ( info->rx_buffer_list[CurrentIndex].rcc )
-					framesize = RCLRVALUE - info->rx_buffer_list[CurrentIndex].rcc;
-				else
-					framesize = DMABUFFERSIZE;
-			}
-			else
-				framesize = DMABUFFERSIZE;
-		}
-
-		if ( framesize > DMABUFFERSIZE ) {
-			/*
-			 * if running in raw sync mode, ISR handler for
-			 * End Of Buffer events terminates all buffers at 4K.
-			 * If this frame size is said to be >4K, get the
-			 * actual number of bytes of the frame in this buffer.
-			 */
-			framesize = framesize % DMABUFFERSIZE;
-		}
-
-
-		if ( debug_level >= DEBUG_LEVEL_BH )
-			printk("%s(%d):mgsl_get_raw_rx_frame(%s) status=%04X size=%d\n",
-				__FILE__,__LINE__,info->device_name,status,framesize);
-
-		if ( debug_level >= DEBUG_LEVEL_DATA )
-			mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
-				min_t(int, framesize, DMABUFFERSIZE),0);
-
-		if (framesize) {
-			/* copy dma buffer(s) to contiguous intermediate buffer */
-			/* NOTE: we never copy more than DMABUFFERSIZE bytes	*/
-
-			pBufEntry = &(info->rx_buffer_list[CurrentIndex]);
-			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
-			info->icount.rxok++;
-
-			ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-		}
-
-		/* Free the buffers used by this frame. */
-		mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex );
-
-		ReturnCode = true;
-	}
-
-
-	if ( info->rx_enabled && info->rx_overflow ) {
-		/* The receiver needs to restarted because of
-		 * a receive overflow (buffer or FIFO). If the
-		 * receive buffers are now empty, then restart receiver.
-		 */
-
-		if ( !info->rx_buffer_list[CurrentIndex].status &&
-			info->rx_buffer_list[CurrentIndex].count ) {
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			usc_start_receiver(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		}
-	}
-
-	return ReturnCode;
-
-}	/* end of mgsl_get_raw_rx_frame() */
-
-/* mgsl_load_tx_dma_buffer()
- * 
- * 	Load the transmit DMA buffer with the specified data.
- * 
- * Arguments:
- * 
- * 	info		pointer to device extension
- * 	Buffer		pointer to buffer containing frame to load
- * 	BufferSize	size in bytes of frame in Buffer
- * 
- * Return Value: 	None
- */
-static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
-		const char *Buffer, unsigned int BufferSize)
-{
-	unsigned short Copycount;
-	unsigned int i = 0;
-	DMABUFFERENTRY *pBufEntry;
-	
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
-
-	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
-		/* set CMR:13 to start transmit when
-		 * next GoAhead (abort) is received
-		 */
-	 	info->cmr_value |= BIT13;			  
-	}
-		
-	/* begin loading the frame in the next available tx dma
-	 * buffer, remember it's starting location for setting
-	 * up tx dma operation
-	 */
-	i = info->current_tx_buffer;
-	info->start_tx_dma_buffer = i;
-
-	/* Setup the status and RCC (Frame Size) fields of the 1st */
-	/* buffer entry in the transmit DMA buffer list. */
-
-	info->tx_buffer_list[i].status = info->cmr_value & 0xf000;
-	info->tx_buffer_list[i].rcc    = BufferSize;
-	info->tx_buffer_list[i].count  = BufferSize;
-
-	/* Copy frame data from 1st source buffer to the DMA buffers. */
-	/* The frame data may span multiple DMA buffers. */
-
-	while( BufferSize ){
-		/* Get a pointer to next DMA buffer entry. */
-		pBufEntry = &info->tx_buffer_list[i++];
-			
-		if ( i == info->tx_buffer_count )
-			i=0;
-
-		/* Calculate the number of bytes that can be copied from */
-		/* the source buffer to this DMA buffer. */
-		if ( BufferSize > DMABUFFERSIZE )
-			Copycount = DMABUFFERSIZE;
-		else
-			Copycount = BufferSize;
-
-		/* Actually copy data from source buffer to DMA buffer. */
-		/* Also set the data count for this individual DMA buffer. */
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
-		else
-			memcpy(pBufEntry->virt_addr, Buffer, Copycount);
-
-		pBufEntry->count = Copycount;
-
-		/* Advance source pointer and reduce remaining data count. */
-		Buffer += Copycount;
-		BufferSize -= Copycount;
-
-		++info->tx_dma_buffers_used;
-	}
-
-	/* remember next available tx dma buffer */
-	info->current_tx_buffer = i;
-
-}	/* end of mgsl_load_tx_dma_buffer() */
-
-/*
- * mgsl_register_test()
- * 
- * 	Performs a register test of the 16C32.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:		true if test passed, otherwise false
- */
-static bool mgsl_register_test( struct mgsl_struct *info )
-{
-	static unsigned short BitPatterns[] =
-		{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
-	static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
-	unsigned int i;
-	bool rc = true;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset(info);
-
-	/* Verify the reset state of some registers. */
-
-	if ( (usc_InReg( info, SICR ) != 0) ||
-		  (usc_InReg( info, IVR  ) != 0) ||
-		  (usc_InDmaReg( info, DIVR ) != 0) ){
-		rc = false;
-	}
-
-	if ( rc ){
-		/* Write bit patterns to various registers but do it out of */
-		/* sync, then read back and verify values. */
-
-		for ( i = 0 ; i < Patterncount ; i++ ) {
-			usc_OutReg( info, TC0R, BitPatterns[i] );
-			usc_OutReg( info, TC1R, BitPatterns[(i+1)%Patterncount] );
-			usc_OutReg( info, TCLR, BitPatterns[(i+2)%Patterncount] );
-			usc_OutReg( info, RCLR, BitPatterns[(i+3)%Patterncount] );
-			usc_OutReg( info, RSR,  BitPatterns[(i+4)%Patterncount] );
-			usc_OutDmaReg( info, TBCR, BitPatterns[(i+5)%Patterncount] );
-
-			if ( (usc_InReg( info, TC0R ) != BitPatterns[i]) ||
-				  (usc_InReg( info, TC1R ) != BitPatterns[(i+1)%Patterncount]) ||
-				  (usc_InReg( info, TCLR ) != BitPatterns[(i+2)%Patterncount]) ||
-				  (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) ||
-				  (usc_InReg( info, RSR )  != BitPatterns[(i+4)%Patterncount]) ||
-				  (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){
-				rc = false;
-				break;
-			}
-		}
-	}
-
-	usc_reset(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return rc;
-
-}	/* end of mgsl_register_test() */
-
-/* mgsl_irq_test() 	Perform interrupt test of the 16C32.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	true if test passed, otherwise false
- */
-static bool mgsl_irq_test( struct mgsl_struct *info )
-{
-	unsigned long EndTime;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset(info);
-
-	/*
-	 * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition. 
-	 * The ISR sets irq_occurred to true.
-	 */
-
-	info->irq_occurred = false;
-
-	/* Enable INTEN gate for ISA adapter (Port 6, Bit12) */
-	/* Enable INTEN (Port 6, Bit12) */
-	/* This connects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg( info, PCR, (unsigned short)((usc_InReg(info, PCR) | BIT13) & ~BIT12) );
-
-	usc_EnableMasterIrqBit(info);
-	usc_EnableInterrupts(info, IO_PIN);
-	usc_ClearIrqPendingBits(info, IO_PIN);
-	
-	usc_UnlatchIostatusBits(info, MISCSTATUS_TXC_LATCHED);
-	usc_EnableStatusIrqs(info, SICR_TXC_ACTIVE + SICR_TXC_INACTIVE);
-
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	EndTime=100;
-	while( EndTime-- && !info->irq_occurred ) {
-		msleep_interruptible(10);
-	}
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	return info->irq_occurred;
-
-}	/* end of mgsl_irq_test() */
-
-/* mgsl_dma_test()
- * 
- * 	Perform a DMA test of the 16C32. A small frame is
- * 	transmitted via DMA from a transmit buffer to a receive buffer
- * 	using single buffer DMA mode.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	true if test passed, otherwise false
- */
-static bool mgsl_dma_test( struct mgsl_struct *info )
-{
-	unsigned short FifoLevel;
-	unsigned long phys_addr;
-	unsigned int FrameSize;
-	unsigned int i;
-	char *TmpPtr;
-	bool rc = true;
-	unsigned short status=0;
-	unsigned long EndTime;
-	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-
-	/* save current port options */
-	memcpy(&tmp_params,&info->params,sizeof(MGSL_PARAMS));
-	/* load default port options */
-	memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-	
-#define TESTFRAMESIZE 40
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
-	/* setup 16C32 for SDLC DMA transfer mode */
-
-	usc_reset(info);
-	usc_set_sdlc_mode(info);
-	usc_enable_loopback(info,1);
-	
-	/* Reprogram the RDMR so that the 16C32 does NOT clear the count
-	 * field of the buffer entry after fetching buffer address. This
-	 * way we can detect a DMA failure for a DMA read (which should be
-	 * non-destructive to system memory) before we try and write to
-	 * memory (where a failure could corrupt system memory).
-	 */
-
-	/* Receive DMA mode Register (RDMR)
-	 * 
-	 * <15..14>	11	DMA mode = Linked List Buffer mode
-	 * <13>		1	RSBinA/L = store Rx status Block in List entry
-	 * <12>		0	1 = Clear count of List Entry after fetching
-	 * <11..10>	00	Address mode = Increment
-	 * <9>		1	Terminate Buffer on RxBound
-	 * <8>		0	Bus Width = 16bits
-	 * <7..0>		?	status Bits (write as 0s)
-	 * 
-	 * 1110 0010 0000 0000 = 0xe200
-	 */
-
-	usc_OutDmaReg( info, RDMR, 0xe200 );
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-
-	/* SETUP TRANSMIT AND RECEIVE DMA BUFFERS */
-
-	FrameSize = TESTFRAMESIZE;
-
-	/* setup 1st transmit buffer entry: */
-	/* with frame size and transmit control word */
-
-	info->tx_buffer_list[0].count  = FrameSize;
-	info->tx_buffer_list[0].rcc    = FrameSize;
-	info->tx_buffer_list[0].status = 0x4000;
-
-	/* build a transmit frame in 1st transmit DMA buffer */
-
-	TmpPtr = info->tx_buffer_list[0].virt_addr;
-	for (i = 0; i < FrameSize; i++ )
-		*TmpPtr++ = i;
-
-	/* setup 1st receive buffer entry: */
-	/* clear status, set max receive buffer size */
-
-	info->rx_buffer_list[0].status = 0;
-	info->rx_buffer_list[0].count = FrameSize + 4;
-
-	/* zero out the 1st receive buffer */
-
-	memset( info->rx_buffer_list[0].virt_addr, 0, FrameSize + 4 );
-
-	/* Set count field of next buffer entries to prevent */
-	/* 16C32 from using buffers after the 1st one. */
-
-	info->tx_buffer_list[1].count = 0;
-	info->rx_buffer_list[1].count = 0;
-	
-
-	/***************************/
-	/* Program 16C32 receiver. */
-	/***************************/
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	/* setup DMA transfers */
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	/* program 16C32 receiver with physical address of 1st DMA buffer entry */
-	phys_addr = info->rx_buffer_list[0].phys_entry;
-	usc_OutDmaReg( info, NRARL, (unsigned short)phys_addr );
-	usc_OutDmaReg( info, NRARU, (unsigned short)(phys_addr >> 16) );
-
-	/* Clear the Rx DMA status bits (read RDMR) and start channel */
-	usc_InDmaReg( info, RDMR );
-	usc_DmaCmd( info, DmaCmd_InitRxChannel );
-
-	/* Enable Receiver (RMR <1..0> = 10) */
-	usc_OutReg( info, RMR, (unsigned short)((usc_InReg(info, RMR) & 0xfffc) | 0x0002) );
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-
-	/*************************************************************/
-	/* WAIT FOR RECEIVER TO DMA ALL PARAMETERS FROM BUFFER ENTRY */
-	/*************************************************************/
-
-	/* Wait 100ms for interrupt. */
-	EndTime = jiffies + msecs_to_jiffies(100);
-
-	for(;;) {
-		if (time_after(jiffies, EndTime)) {
-			rc = false;
-			break;
-		}
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		status = usc_InDmaReg( info, RDMR );
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		if ( !(status & BIT4) && (status & BIT5) ) {
-			/* INITG (BIT 4) is inactive (no entry read in progress) AND */
-			/* BUSY  (BIT 5) is active (channel still active). */
-			/* This means the buffer entry read has completed. */
-			break;
-		}
-	}
-
-
-	/******************************/
-	/* Program 16C32 transmitter. */
-	/******************************/
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	/* Program the Transmit Character Length Register (TCLR) */
-	/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
-
-	usc_OutReg( info, TCLR, (unsigned short)info->tx_buffer_list[0].count );
-	usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-	/* Program the address of the 1st DMA Buffer Entry in linked list */
-
-	phys_addr = info->tx_buffer_list[0].phys_entry;
-	usc_OutDmaReg( info, NTARL, (unsigned short)phys_addr );
-	usc_OutDmaReg( info, NTARU, (unsigned short)(phys_addr >> 16) );
-
-	/* unlatch Tx status bits, and start transmit channel. */
-
-	usc_OutReg( info, TCSR, (unsigned short)(( usc_InReg(info, TCSR) & 0x0f00) | 0xfa) );
-	usc_DmaCmd( info, DmaCmd_InitTxChannel );
-
-	/* wait for DMA controller to fill transmit FIFO */
-
-	usc_TCmd( info, TCmd_SelectTicrTxFifostatus );
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-
-	/**********************************/
-	/* WAIT FOR TRANSMIT FIFO TO FILL */
-	/**********************************/
-	
-	/* Wait 100ms */
-	EndTime = jiffies + msecs_to_jiffies(100);
-
-	for(;;) {
-		if (time_after(jiffies, EndTime)) {
-			rc = false;
-			break;
-		}
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		FifoLevel = usc_InReg(info, TICR) >> 8;
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			
-		if ( FifoLevel < 16 )
-			break;
-		else
-			if ( FrameSize < 32 ) {
-				/* This frame is smaller than the entire transmit FIFO */
-				/* so wait for the entire frame to be loaded. */
-				if ( FifoLevel <= (32 - FrameSize) )
-					break;
-			}
-	}
-
-
-	if ( rc )
-	{
-		/* Enable 16C32 transmitter. */
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		
-		/* Transmit mode Register (TMR), <1..0> = 10, Enable Transmitter */
-		usc_TCmd( info, TCmd_SendFrame );
-		usc_OutReg( info, TMR, (unsigned short)((usc_InReg(info, TMR) & 0xfffc) | 0x0002) );
-		
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-						
-		/******************************/
-		/* WAIT FOR TRANSMIT COMPLETE */
-		/******************************/
-
-		/* Wait 100ms */
-		EndTime = jiffies + msecs_to_jiffies(100);
-
-		/* While timer not expired wait for transmit complete */
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		status = usc_InReg( info, TCSR );
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
-			if (time_after(jiffies, EndTime)) {
-				rc = false;
-				break;
-			}
-
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			status = usc_InReg( info, TCSR );
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		}
-	}
-
-
-	if ( rc ){
-		/* CHECK FOR TRANSMIT ERRORS */
-		if ( status & (BIT5 + BIT1) ) 
-			rc = false;
-	}
-
-	if ( rc ) {
-		/* WAIT FOR RECEIVE COMPLETE */
-
-		/* Wait 100ms */
-		EndTime = jiffies + msecs_to_jiffies(100);
-
-		/* Wait for 16C32 to write receive status to buffer entry. */
-		status=info->rx_buffer_list[0].status;
-		while ( status == 0 ) {
-			if (time_after(jiffies, EndTime)) {
-				rc = false;
-				break;
-			}
-			status=info->rx_buffer_list[0].status;
-		}
-	}
-
-
-	if ( rc ) {
-		/* CHECK FOR RECEIVE ERRORS */
-		status = info->rx_buffer_list[0].status;
-
-		if ( status & (BIT8 + BIT3 + BIT1) ) {
-			/* receive error has occurred */
-			rc = false;
-		} else {
-			if ( memcmp( info->tx_buffer_list[0].virt_addr ,
-				info->rx_buffer_list[0].virt_addr, FrameSize ) ){
-				rc = false;
-			}
-		}
-	}
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset( info );
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	/* restore current port options */
-	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
-	
-	return rc;
-
-}	/* end of mgsl_dma_test() */
-
-/* mgsl_adapter_test()
- * 
- * 	Perform the register, IRQ, and DMA tests for the 16C32.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise -ENODEV
- */
-static int mgsl_adapter_test( struct mgsl_struct *info )
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):Testing device %s\n",
-			__FILE__,__LINE__,info->device_name );
-			
-	if ( !mgsl_register_test( info ) ) {
-		info->init_error = DiagStatus_AddressFailure;
-		printk( "%s(%d):Register test failure for device %s Addr=%04X\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) );
-		return -ENODEV;
-	}
-
-	if ( !mgsl_irq_test( info ) ) {
-		info->init_error = DiagStatus_IrqFailure;
-		printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );
-		return -ENODEV;
-	}
-
-	if ( !mgsl_dma_test( info ) ) {
-		info->init_error = DiagStatus_DmaFailure;
-		printk( "%s(%d):DMA test failure for device %s DMA=%d\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->dma_level) );
-		return -ENODEV;
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):device %s passed diagnostics\n",
-			__FILE__,__LINE__,info->device_name );
-			
-	return 0;
-
-}	/* end of mgsl_adapter_test() */
-
-/* mgsl_memory_test()
- * 
- * 	Test the shared memory on a PCI adapter.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	true if test passed, otherwise false
- */
-static bool mgsl_memory_test( struct mgsl_struct *info )
-{
-	static unsigned long BitPatterns[] =
-		{ 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
-	unsigned long Patterncount = ARRAY_SIZE(BitPatterns);
-	unsigned long i;
-	unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
-	unsigned long * TestAddr;
-
-	if ( info->bus_type != MGSL_BUS_TYPE_PCI )
-		return true;
-
-	TestAddr = (unsigned long *)info->memory_base;
-
-	/* Test data lines with test pattern at one location. */
-
-	for ( i = 0 ; i < Patterncount ; i++ ) {
-		*TestAddr = BitPatterns[i];
-		if ( *TestAddr != BitPatterns[i] )
-			return false;
-	}
-
-	/* Test address lines with incrementing pattern over */
-	/* entire address range. */
-
-	for ( i = 0 ; i < TestLimit ; i++ ) {
-		*TestAddr = i * 4;
-		TestAddr++;
-	}
-
-	TestAddr = (unsigned long *)info->memory_base;
-
-	for ( i = 0 ; i < TestLimit ; i++ ) {
-		if ( *TestAddr != i * 4 )
-			return false;
-		TestAddr++;
-	}
-
-	memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE );
-
-	return true;
-
-}	/* End Of mgsl_memory_test() */
-
-
-/* mgsl_load_pci_memory()
- * 
- * 	Load a large block of data into the PCI shared memory.
- * 	Use this instead of memcpy() or memmove() to move data
- * 	into the PCI shared memory.
- * 
- * Notes:
- * 
- * 	This function prevents the PCI9050 interface chip from hogging
- * 	the adapter local bus, which can starve the 16C32 by preventing
- * 	16C32 bus master cycles.
- * 
- * 	The PCI9050 documentation says that the 9050 will always release
- * 	control of the local bus after completing the current read
- * 	or write operation.
- * 
- * 	It appears that as long as the PCI9050 write FIFO is full, the
- * 	PCI9050 treats all of the writes as a single burst transaction
- * 	and will not release the bus. This causes DMA latency problems
- * 	at high speeds when copying large data blocks to the shared
- * 	memory.
- * 
- * 	This function in effect, breaks the a large shared memory write
- * 	into multiple transations by interleaving a shared memory read
- * 	which will flush the write FIFO and 'complete' the write
- * 	transation. This allows any pending DMA request to gain control
- * 	of the local bus in a timely fasion.
- * 
- * Arguments:
- * 
- * 	TargetPtr	pointer to target address in PCI shared memory
- * 	SourcePtr	pointer to source buffer for data
- * 	count		count in bytes of data to copy
- *
- * Return Value:	None
- */
-static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
-	unsigned short count )
-{
-	/* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */
-#define PCI_LOAD_INTERVAL 64
-
-	unsigned short Intervalcount = count / PCI_LOAD_INTERVAL;
-	unsigned short Index;
-	unsigned long Dummy;
-
-	for ( Index = 0 ; Index < Intervalcount ; Index++ )
-	{
-		memcpy(TargetPtr, SourcePtr, PCI_LOAD_INTERVAL);
-		Dummy = *((volatile unsigned long *)TargetPtr);
-		TargetPtr += PCI_LOAD_INTERVAL;
-		SourcePtr += PCI_LOAD_INTERVAL;
-	}
-
-	memcpy( TargetPtr, SourcePtr, count % PCI_LOAD_INTERVAL );
-
-}	/* End Of mgsl_load_pci_memory() */
-
-static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
-{
-	int i;
-	int linecount;
-	if (xmit)
-		printk("%s tx data:\n",info->device_name);
-	else
-		printk("%s rx data:\n",info->device_name);
-		
-	while(count) {
-		if (count > 16)
-			linecount = 16;
-		else
-			linecount = count;
-			
-		for(i=0;i<linecount;i++)
-			printk("%02X ",(unsigned char)data[i]);
-		for(;i<17;i++)
-			printk("   ");
-		for(i=0;i<linecount;i++) {
-			if (data[i]>=040 && data[i]<=0176)
-				printk("%c",data[i]);
-			else
-				printk(".");
-		}
-		printk("\n");
-		
-		data  += linecount;
-		count -= linecount;
-	}
-}	/* end of mgsl_trace_block() */
-
-/* mgsl_tx_timeout()
- * 
- * 	called when HDLC frame times out
- * 	update stats and do tx completion processing
- * 	
- * Arguments:	context		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_tx_timeout(unsigned long context)
-{
-	struct mgsl_struct *info = (struct mgsl_struct*)context;
-	unsigned long flags;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_tx_timeout(%s)\n",
-			__FILE__,__LINE__,info->device_name);
-	if(info->tx_active &&
-	   (info->params.mode == MGSL_MODE_HDLC ||
-	    info->params.mode == MGSL_MODE_RAW) ) {
-		info->icount.txtimeout++;
-	}
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	info->tx_active = false;
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
-		usc_loopmode_cancel_transmit( info );
-
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else
-#endif
-		mgsl_bh_transmit(info);
-	
-}	/* end of mgsl_tx_timeout() */
-
-/* signal that there are no more frames to send, so that
- * line is 'released' by echoing RxD to TxD when current
- * transmission is complete (or immediately if no tx in progress).
- */
-static int mgsl_loopmode_send_done( struct mgsl_struct * info )
-{
-	unsigned long flags;
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
-		if (info->tx_active)
-			info->loopmode_send_done_requested = true;
-		else
-			usc_loopmode_send_done(info);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return 0;
-}
-
-/* release the line by echoing RxD to TxD
- * upon completion of a transmit frame
- */
-static void usc_loopmode_send_done( struct mgsl_struct * info )
-{
- 	info->loopmode_send_done_requested = false;
- 	/* clear CMR:13 to 0 to start echoing RxData to TxData */
- 	info->cmr_value &= ~BIT13;			  
- 	usc_OutReg(info, CMR, info->cmr_value);
-}
-
-/* abort a transmit in progress while in HDLC LoopMode
- */
-static void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
-{
- 	/* reset tx dma channel and purge TxFifo */
- 	usc_RTCmd( info, RTCmd_PurgeTxFifo );
- 	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
-  	usc_loopmode_send_done( info );
-}
-
-/* for HDLC/SDLC LoopMode, setting CMR:13 after the transmitter is enabled
- * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort)
- * we must clear CMR:13 to begin repeating TxData to RxData
- */
-static void usc_loopmode_insert_request( struct mgsl_struct * info )
-{
- 	info->loopmode_insert_requested = true;
- 
- 	/* enable RxAbort irq. On next RxAbort, clear CMR:13 to
- 	 * begin repeating TxData on RxData (complete insertion)
-	 */
- 	usc_OutReg( info, RICR, 
-		(usc_InReg( info, RICR ) | RXSTATUS_ABORT_RECEIVED ) );
-		
-	/* set CMR:13 to insert into loop on next GoAhead (RxAbort) */
-	info->cmr_value |= BIT13;
- 	usc_OutReg(info, CMR, info->cmr_value);
-}
-
-/* return 1 if station is inserted into the loop, otherwise 0
- */
-static int usc_loopmode_active( struct mgsl_struct * info)
-{
- 	return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
-}
-
-#if SYNCLINK_GENERIC_HDLC
-
-/**
- * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
- * set encoding and frame check sequence (FCS) options
- *
- * dev       pointer to network device structure
- * encoding  serial encoding setting
- * parity    FCS setting
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
-			  unsigned short parity)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned char  new_encoding;
-	unsigned short new_crctype;
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	switch (encoding)
-	{
-	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
-	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
-	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
-	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
-	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
-	default: return -EINVAL;
-	}
-
-	switch (parity)
-	{
-	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
-	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
-	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
-	default: return -EINVAL;
-	}
-
-	info->params.encoding = new_encoding;
-	info->params.crc_type = new_crctype;
-
-	/* if network interface up, reprogram hardware */
-	if (info->netcount)
-		mgsl_program_hw(info);
-
-	return 0;
-}
-
-/**
- * called by generic HDLC layer to send frame
- *
- * skb  socket buffer containing HDLC frame
- * dev  pointer to network device structure
- */
-static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
-
-	/* stop sending until this frame completes */
-	netif_stop_queue(dev);
-
-	/* copy data to device buffers */
-	info->xmit_cnt = skb->len;
-	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
-
-	/* update network statistics */
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
-	/* save start time for transmit timeout detection */
-	dev->trans_start = jiffies;
-
-	/* start hardware transmitter if necessary */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (!info->tx_active)
-	 	usc_start_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * called by network layer when interface enabled
- * claim resources and initialize hardware
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_open(struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	int rc;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
-
-	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
-		return rc;
-
-	/* arbitrate between network and tty opens */
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->port.count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return -EBUSY;
-	}
-	info->netcount=1;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	/* claim resources and init adapter */
-	if ((rc = startup(info)) != 0) {
-		spin_lock_irqsave(&info->netlock, flags);
-		info->netcount=0;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return rc;
-	}
-
-	/* assert DTR and RTS, apply hardware settings */
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	mgsl_program_hw(info);
-
-	/* enable network layer transmit */
-	dev->trans_start = jiffies;
-	netif_start_queue(dev);
-
-	/* inform generic HDLC layer of current DCD status */
-	spin_lock_irqsave(&info->irq_spinlock, flags);
-	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	if (info->serial_signals & SerialSignal_DCD)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-	return 0;
-}
-
-/**
- * called by network layer when interface is disabled
- * shutdown hardware and release resources
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_close(struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
-
-	netif_stop_queue(dev);
-
-	/* shutdown adapter and release resources */
-	shutdown(info);
-
-	hdlc_close(dev);
-
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	return 0;
-}
-
-/**
- * called by network layer to process IOCTL call to network device
- *
- * dev  pointer to network device structure
- * ifr  pointer to network interface request structure
- * cmd  IOCTL command code
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line;
-	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned int flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	if (cmd != SIOCWANDEV)
-		return hdlc_ioctl(dev, ifr, cmd);
-
-	switch(ifr->ifr_settings.type) {
-	case IF_GET_IFACE: /* return current sync_serial_settings */
-
-		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
-		if (ifr->ifr_settings.size < size) {
-			ifr->ifr_settings.size = size; /* data size wanted */
-			return -ENOBUFS;
-		}
-
-		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-
-		switch (flags){
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
-		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
-		default: new_line.clock_type = CLOCK_DEFAULT;
-		}
-
-		new_line.clock_rate = info->params.clock_speed;
-		new_line.loopback   = info->params.loopback ? 1:0;
-
-		if (copy_to_user(line, &new_line, size))
-			return -EFAULT;
-		return 0;
-
-	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
-
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&new_line, line, size))
-			return -EFAULT;
-
-		switch (new_line.clock_type)
-		{
-		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
-		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
-		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_DEFAULT:  flags = info->params.flags &
-					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
-		default: return -EINVAL;
-		}
-
-		if (new_line.loopback != 0 && new_line.loopback != 1)
-			return -EINVAL;
-
-		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-		info->params.flags |= flags;
-
-		info->params.loopback = new_line.loopback;
-
-		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
-			info->params.clock_speed = new_line.clock_rate;
-		else
-			info->params.clock_speed = 0;
-
-		/* if network interface up, reprogram hardware */
-		if (info->netcount)
-			mgsl_program_hw(info);
-		return 0;
-
-	default:
-		return hdlc_ioctl(dev, ifr, cmd);
-	}
-}
-
-/**
- * called by network layer when transmit timeout is detected
- *
- * dev  pointer to network device structure
- */
-static void hdlcdev_tx_timeout(struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
-
-	dev->stats.tx_errors++;
-	dev->stats.tx_aborted_errors++;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_stop_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	netif_wake_queue(dev);
-}
-
-/**
- * called by device driver when transmit completes
- * reenable network layer transmit if stopped
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_tx_done(struct mgsl_struct *info)
-{
-	if (netif_queue_stopped(info->netdev))
-		netif_wake_queue(info->netdev);
-}
-
-/**
- * called by device driver when frame received
- * pass frame to network layer
- *
- * info  pointer to device instance information
- * buf   pointer to buffer contianing frame data
- * size  count of data bytes in buf
- */
-static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size);
-	struct net_device *dev = info->netdev;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_rx(%s)\n", dev->name);
-
-	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-		       dev->name);
-		dev->stats.rx_dropped++;
-		return;
-	}
-
-	memcpy(skb_put(skb, size), buf, size);
-
-	skb->protocol = hdlc_type_trans(skb, dev);
-
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += size;
-
-	netif_rx(skb);
-}
-
-static const struct net_device_ops hdlcdev_ops = {
-	.ndo_open       = hdlcdev_open,
-	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
-	.ndo_start_xmit = hdlc_start_xmit,
-	.ndo_do_ioctl   = hdlcdev_ioctl,
-	.ndo_tx_timeout = hdlcdev_tx_timeout,
-};
-
-/**
- * called by device driver when adding device instance
- * do generic HDLC initialization
- *
- * info  pointer to device instance information
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_init(struct mgsl_struct *info)
-{
-	int rc;
-	struct net_device *dev;
-	hdlc_device *hdlc;
-
-	/* allocate and initialize network and HDLC layer objects */
-
-	if (!(dev = alloc_hdlcdev(info))) {
-		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
-		return -ENOMEM;
-	}
-
-	/* for network layer reporting purposes only */
-	dev->base_addr = info->io_base;
-	dev->irq       = info->irq_level;
-	dev->dma       = info->dma_level;
-
-	/* network layer callbacks and settings */
-	dev->netdev_ops     = &hdlcdev_ops;
-	dev->watchdog_timeo = 10 * HZ;
-	dev->tx_queue_len   = 50;
-
-	/* generic HDLC layer callbacks and settings */
-	hdlc         = dev_to_hdlc(dev);
-	hdlc->attach = hdlcdev_attach;
-	hdlc->xmit   = hdlcdev_xmit;
-
-	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
-		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
-		free_netdev(dev);
-		return rc;
-	}
-
-	info->netdev = dev;
-	return 0;
-}
-
-/**
- * called by device driver when removing device instance
- * do generic HDLC cleanup
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_exit(struct mgsl_struct *info)
-{
-	unregister_hdlc_device(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-}
-
-#endif /* CONFIG_HDLC */
-
-
-static int __devinit synclink_init_one (struct pci_dev *dev,
-					const struct pci_device_id *ent)
-{
-	struct mgsl_struct *info;
-
-	if (pci_enable_device(dev)) {
-		printk("error enabling pci device %p\n", dev);
-		return -EIO;
-	}
-
-	if (!(info = mgsl_allocate_device())) {
-		printk("can't allocate device instance data.\n");
-		return -EIO;
-	}
-
-        /* Copy user configuration info to device instance data */
-		
-	info->io_base = pci_resource_start(dev, 2);
-	info->irq_level = dev->irq;
-	info->phys_memory_base = pci_resource_start(dev, 3);
-				
-        /* Because veremap only works on page boundaries we must map
-	 * a larger area than is actually implemented for the LCR
-	 * memory range. We map a full page starting at the page boundary.
-	 */
-	info->phys_lcr_base = pci_resource_start(dev, 0);
-	info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
-	info->phys_lcr_base &= ~(PAGE_SIZE-1);
-				
-	info->bus_type = MGSL_BUS_TYPE_PCI;
-	info->io_addr_size = 8;
-	info->irq_flags = IRQF_SHARED;
-
-	if (dev->device == 0x0210) {
-		/* Version 1 PCI9030 based universal PCI adapter */
-		info->misc_ctrl_value = 0x007c4080;
-		info->hw_version = 1;
-	} else {
-		/* Version 0 PCI9050 based 5V PCI adapter
-		 * A PCI9050 bug prevents reading LCR registers if 
-		 * LCR base address bit 7 is set. Maintain shadow
-		 * value so we can write to LCR misc control reg.
-		 */
-		info->misc_ctrl_value = 0x087e4546;
-		info->hw_version = 0;
-	}
-				
-	mgsl_add_device(info);
-
-	return 0;
-}
-
-static void __devexit synclink_remove_one (struct pci_dev *dev)
-{
-}
-
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
deleted file mode 100644
index d01fffe..0000000
--- a/drivers/char/synclink_gt.c
+++ /dev/null
@@ -1,5162 +0,0 @@
-/*
- * Device driver for Microgate SyncLink GT serial adapters.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * This code is released under the GNU General Public License (GPL)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * DEBUG OUTPUT DEFINITIONS
- *
- * uncomment lines below to enable specific types of debug output
- *
- * DBGINFO   information - most verbose output
- * DBGERR    serious errors
- * DBGBH     bottom half service routine debugging
- * DBGISR    interrupt service routine debugging
- * DBGDATA   output receive and transmit data
- * DBGTBUF   output transmit DMA buffers and registers
- * DBGRBUF   output receive DMA buffers and registers
- */
-
-#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt
-#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt
-#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
-#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
-#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
-/*#define DBGTBUF(info) dump_tbufs(info)*/
-/*#define DBGRBUF(info) dump_rbufs(info)*/
-
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-#include <linux/termios.h>
-#include <linux/bitops.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/synclink.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/types.h>
-#include <asm/uaccess.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-/*
- * module identification
- */
-static char *driver_name     = "SyncLink GT";
-static char *tty_driver_name = "synclink_gt";
-static char *tty_dev_prefix  = "ttySLG";
-MODULE_LICENSE("GPL");
-#define MGSL_MAGIC 0x5401
-#define MAX_DEVICES 32
-
-static struct pci_device_id pci_table[] = {
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{0,}, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, pci_table);
-
-static int  init_one(struct pci_dev *dev,const struct pci_device_id *ent);
-static void remove_one(struct pci_dev *dev);
-static struct pci_driver pci_driver = {
-	.name		= "synclink_gt",
-	.id_table	= pci_table,
-	.probe		= init_one,
-	.remove		= __devexit_p(remove_one),
-};
-
-static bool pci_registered;
-
-/*
- * module configuration and status
- */
-static struct slgt_info *slgt_device_list;
-static int slgt_device_count;
-
-static int ttymajor;
-static int debug_level;
-static int maxframe[MAX_DEVICES];
-
-module_param(ttymajor, int, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-
-MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned");
-MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail");
-MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
-
-/*
- * tty support and callbacks
- */
-static struct tty_driver *serial_driver;
-
-static int  open(struct tty_struct *tty, struct file * filp);
-static void close(struct tty_struct *tty, struct file * filp);
-static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-
-static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int put_char(struct tty_struct *tty, unsigned char ch);
-static void send_xchar(struct tty_struct *tty, char ch);
-static void wait_until_sent(struct tty_struct *tty, int timeout);
-static int  write_room(struct tty_struct *tty);
-static void flush_chars(struct tty_struct *tty);
-static void flush_buffer(struct tty_struct *tty);
-static void tx_hold(struct tty_struct *tty);
-static void tx_release(struct tty_struct *tty);
-
-static int  ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static int  chars_in_buffer(struct tty_struct *tty);
-static void throttle(struct tty_struct * tty);
-static void unthrottle(struct tty_struct * tty);
-static int set_break(struct tty_struct *tty, int break_state);
-
-/*
- * generic HDLC support and callbacks
- */
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(struct slgt_info *info);
-static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
-static int  hdlcdev_init(struct slgt_info *info);
-static void hdlcdev_exit(struct slgt_info *info);
-#endif
-
-
-/*
- * device specific structures, macros and functions
- */
-
-#define SLGT_MAX_PORTS 4
-#define SLGT_REG_SIZE  256
-
-/*
- * conditional wait facility
- */
-struct cond_wait {
-	struct cond_wait *next;
-	wait_queue_head_t q;
-	wait_queue_t wait;
-	unsigned int data;
-};
-static void init_cond_wait(struct cond_wait *w, unsigned int data);
-static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void flush_cond_wait(struct cond_wait **head);
-
-/*
- * DMA buffer descriptor and access macros
- */
-struct slgt_desc
-{
-	__le16 count;
-	__le16 status;
-	__le32 pbuf;  /* physical address of data buffer */
-	__le32 next;  /* physical address of next descriptor */
-
-	/* driver book keeping */
-	char *buf;          /* virtual  address of data buffer */
-    	unsigned int pdesc; /* physical address of this descriptor */
-	dma_addr_t buf_dma_addr;
-	unsigned short buf_count;
-};
-
-#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
-#define set_desc_next(a,b) (a).next   = cpu_to_le32((unsigned int)(b))
-#define set_desc_count(a,b)(a).count  = cpu_to_le16((unsigned short)(b))
-#define set_desc_eof(a,b)  (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
-#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b))
-#define desc_count(a)      (le16_to_cpu((a).count))
-#define desc_status(a)     (le16_to_cpu((a).status))
-#define desc_complete(a)   (le16_to_cpu((a).status) & BIT15)
-#define desc_eof(a)        (le16_to_cpu((a).status) & BIT2)
-#define desc_crc_error(a)  (le16_to_cpu((a).status) & BIT1)
-#define desc_abort(a)      (le16_to_cpu((a).status) & BIT0)
-#define desc_residue(a)    ((le16_to_cpu((a).status) & 0x38) >> 3)
-
-struct _input_signal_events {
-	int ri_up;
-	int ri_down;
-	int dsr_up;
-	int dsr_down;
-	int dcd_up;
-	int dcd_down;
-	int cts_up;
-	int cts_down;
-};
-
-/*
- * device instance data structure
- */
-struct slgt_info {
-	void *if_ptr;		/* General purpose pointer (used by SPPP) */
-	struct tty_port port;
-
-	struct slgt_info *next_device;	/* device list link */
-
-	int magic;
-
-	char device_name[25];
-	struct pci_dev *pdev;
-
-	int port_count;  /* count of ports on adapter */
-	int adapter_num; /* adapter instance number */
-	int port_num;    /* port instance number */
-
-	/* array of pointers to port contexts on this adapter */
-	struct slgt_info *port_array[SLGT_MAX_PORTS];
-
-	int			line;		/* tty line instance number */
-
-	struct mgsl_icount	icount;
-
-	int			timeout;
-	int			x_char;		/* xon/xoff character */
-	unsigned int		read_status_mask;
-	unsigned int 		ignore_status_mask;
-
-	wait_queue_head_t	status_event_wait_q;
-	wait_queue_head_t	event_wait_q;
-	struct timer_list	tx_timer;
-	struct timer_list	rx_timer;
-
-	unsigned int            gpio_present;
-	struct cond_wait        *gpio_wait_q;
-
-	spinlock_t lock;	/* spinlock for synchronizing with ISR */
-
-	struct work_struct task;
-	u32 pending_bh;
-	bool bh_requested;
-	bool bh_running;
-
-	int isr_overflow;
-	bool irq_requested;	/* true if IRQ requested */
-	bool irq_occurred;	/* for diagnostics use */
-
-	/* device configuration */
-
-	unsigned int bus_type;
-	unsigned int irq_level;
-	unsigned long irq_flags;
-
-	unsigned char __iomem * reg_addr;  /* memory mapped registers address */
-	u32 phys_reg_addr;
-	bool reg_addr_requested;
-
-	MGSL_PARAMS params;       /* communications parameters */
-	u32 idle_mode;
-	u32 max_frame_size;       /* as set by device config */
-
-	unsigned int rbuf_fill_level;
-	unsigned int rx_pio;
-	unsigned int if_mode;
-	unsigned int base_clock;
-	unsigned int xsync;
-	unsigned int xctrl;
-
-	/* device status */
-
-	bool rx_enabled;
-	bool rx_restart;
-
-	bool tx_enabled;
-	bool tx_active;
-
-	unsigned char signals;    /* serial signal states */
-	int init_error;  /* initialization error */
-
-	unsigned char *tx_buf;
-	int tx_count;
-
-	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
-	char char_buf[MAX_ASYNC_BUFFER_SIZE];
-	bool drop_rts_on_tx_done;
-	struct	_input_signal_events	input_signal_events;
-
-	int dcd_chkcount;	/* check counts to prevent */
-	int cts_chkcount;	/* too many IRQs if a signal */
-	int dsr_chkcount;	/* is floating */
-	int ri_chkcount;
-
-	char *bufs;		/* virtual address of DMA buffer lists */
-	dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */
-
-	unsigned int rbuf_count;
-	struct slgt_desc *rbufs;
-	unsigned int rbuf_current;
-	unsigned int rbuf_index;
-	unsigned int rbuf_fill_index;
-	unsigned short rbuf_fill_count;
-
-	unsigned int tbuf_count;
-	struct slgt_desc *tbufs;
-	unsigned int tbuf_current;
-	unsigned int tbuf_start;
-
-	unsigned char *tmp_rbuf;
-	unsigned int tmp_rbuf_count;
-
-	/* SPPP/Cisco HDLC device parts */
-
-	int netcount;
-	spinlock_t netlock;
-#if SYNCLINK_GENERIC_HDLC
-	struct net_device *netdev;
-#endif
-
-};
-
-static MGSL_PARAMS default_params = {
-	.mode            = MGSL_MODE_HDLC,
-	.loopback        = 0,
-	.flags           = HDLC_FLAG_UNDERRUN_ABORT15,
-	.encoding        = HDLC_ENCODING_NRZI_SPACE,
-	.clock_speed     = 0,
-	.addr_filter     = 0xff,
-	.crc_type        = HDLC_CRC_16_CCITT,
-	.preamble_length = HDLC_PREAMBLE_LENGTH_8BITS,
-	.preamble        = HDLC_PREAMBLE_PATTERN_NONE,
-	.data_rate       = 9600,
-	.data_bits       = 8,
-	.stop_bits       = 1,
-	.parity          = ASYNC_PARITY_NONE
-};
-
-
-#define BH_RECEIVE  1
-#define BH_TRANSMIT 2
-#define BH_STATUS   4
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-#define DMABUFSIZE 256
-#define DESC_LIST_SIZE 4096
-
-#define MASK_PARITY  BIT1
-#define MASK_FRAMING BIT0
-#define MASK_BREAK   BIT14
-#define MASK_OVERRUN BIT4
-
-#define GSR   0x00 /* global status */
-#define JCR   0x04 /* JTAG control */
-#define IODR  0x08 /* GPIO direction */
-#define IOER  0x0c /* GPIO interrupt enable */
-#define IOVR  0x10 /* GPIO value */
-#define IOSR  0x14 /* GPIO interrupt status */
-#define TDR   0x80 /* tx data */
-#define RDR   0x80 /* rx data */
-#define TCR   0x82 /* tx control */
-#define TIR   0x84 /* tx idle */
-#define TPR   0x85 /* tx preamble */
-#define RCR   0x86 /* rx control */
-#define VCR   0x88 /* V.24 control */
-#define CCR   0x89 /* clock control */
-#define BDR   0x8a /* baud divisor */
-#define SCR   0x8c /* serial control */
-#define SSR   0x8e /* serial status */
-#define RDCSR 0x90 /* rx DMA control/status */
-#define TDCSR 0x94 /* tx DMA control/status */
-#define RDDAR 0x98 /* rx DMA descriptor address */
-#define TDDAR 0x9c /* tx DMA descriptor address */
-#define XSR   0x40 /* extended sync pattern */
-#define XCR   0x44 /* extended control */
-
-#define RXIDLE      BIT14
-#define RXBREAK     BIT14
-#define IRQ_TXDATA  BIT13
-#define IRQ_TXIDLE  BIT12
-#define IRQ_TXUNDER BIT11 /* HDLC */
-#define IRQ_RXDATA  BIT10
-#define IRQ_RXIDLE  BIT9  /* HDLC */
-#define IRQ_RXBREAK BIT9  /* async */
-#define IRQ_RXOVER  BIT8
-#define IRQ_DSR     BIT7
-#define IRQ_CTS     BIT6
-#define IRQ_DCD     BIT5
-#define IRQ_RI      BIT4
-#define IRQ_ALL     0x3ff0
-#define IRQ_MASTER  BIT0
-
-#define slgt_irq_on(info, mask) \
-	wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask)))
-#define slgt_irq_off(info, mask) \
-	wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask)))
-
-static __u8  rd_reg8(struct slgt_info *info, unsigned int addr);
-static void  wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value);
-static __u16 rd_reg16(struct slgt_info *info, unsigned int addr);
-static void  wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value);
-static __u32 rd_reg32(struct slgt_info *info, unsigned int addr);
-static void  wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
-
-static void  msc_set_vcr(struct slgt_info *info);
-
-static int  startup(struct slgt_info *info);
-static int  block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
-static void shutdown(struct slgt_info *info);
-static void program_hw(struct slgt_info *info);
-static void change_params(struct slgt_info *info);
-
-static int  register_test(struct slgt_info *info);
-static int  irq_test(struct slgt_info *info);
-static int  loopback_test(struct slgt_info *info);
-static int  adapter_test(struct slgt_info *info);
-
-static void reset_adapter(struct slgt_info *info);
-static void reset_port(struct slgt_info *info);
-static void async_mode(struct slgt_info *info);
-static void sync_mode(struct slgt_info *info);
-
-static void rx_stop(struct slgt_info *info);
-static void rx_start(struct slgt_info *info);
-static void reset_rbufs(struct slgt_info *info);
-static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
-static void rdma_reset(struct slgt_info *info);
-static bool rx_get_frame(struct slgt_info *info);
-static bool rx_get_buf(struct slgt_info *info);
-
-static void tx_start(struct slgt_info *info);
-static void tx_stop(struct slgt_info *info);
-static void tx_set_idle(struct slgt_info *info);
-static unsigned int free_tbuf_count(struct slgt_info *info);
-static unsigned int tbuf_bytes(struct slgt_info *info);
-static void reset_tbufs(struct slgt_info *info);
-static void tdma_reset(struct slgt_info *info);
-static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
-
-static void get_signals(struct slgt_info *info);
-static void set_signals(struct slgt_info *info);
-static void enable_loopback(struct slgt_info *info);
-static void set_rate(struct slgt_info *info, u32 data_rate);
-
-static int  bh_action(struct slgt_info *info);
-static void bh_handler(struct work_struct *work);
-static void bh_transmit(struct slgt_info *info);
-static void isr_serial(struct slgt_info *info);
-static void isr_rdma(struct slgt_info *info);
-static void isr_txeom(struct slgt_info *info, unsigned short status);
-static void isr_tdma(struct slgt_info *info);
-
-static int  alloc_dma_bufs(struct slgt_info *info);
-static void free_dma_bufs(struct slgt_info *info);
-static int  alloc_desc(struct slgt_info *info);
-static void free_desc(struct slgt_info *info);
-static int  alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-
-static int  alloc_tmp_rbuf(struct slgt_info *info);
-static void free_tmp_rbuf(struct slgt_info *info);
-
-static void tx_timeout(unsigned long context);
-static void rx_timeout(unsigned long context);
-
-/*
- * ioctl handlers
- */
-static int  get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount);
-static int  get_params(struct slgt_info *info, MGSL_PARAMS __user *params);
-static int  set_params(struct slgt_info *info, MGSL_PARAMS __user *params);
-static int  get_txidle(struct slgt_info *info, int __user *idle_mode);
-static int  set_txidle(struct slgt_info *info, int idle_mode);
-static int  tx_enable(struct slgt_info *info, int enable);
-static int  tx_abort(struct slgt_info *info);
-static int  rx_enable(struct slgt_info *info, int enable);
-static int  modem_input_wait(struct slgt_info *info,int arg);
-static int  wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
-static int  tiocmget(struct tty_struct *tty, struct file *file);
-static int  tiocmset(struct tty_struct *tty, struct file *file,
-		     unsigned int set, unsigned int clear);
-static int set_break(struct tty_struct *tty, int break_state);
-static int  get_interface(struct slgt_info *info, int __user *if_mode);
-static int  set_interface(struct slgt_info *info, int if_mode);
-static int  set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int  get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int  wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int  get_xsync(struct slgt_info *info, int __user *if_mode);
-static int  set_xsync(struct slgt_info *info, int if_mode);
-static int  get_xctrl(struct slgt_info *info, int __user *if_mode);
-static int  set_xctrl(struct slgt_info *info, int if_mode);
-
-/*
- * driver functions
- */
-static void add_device(struct slgt_info *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
-static int  claim_resources(struct slgt_info *info);
-static void release_resources(struct slgt_info *info);
-
-/*
- * DEBUG OUTPUT CODE
- */
-#ifndef DBGINFO
-#define DBGINFO(fmt)
-#endif
-#ifndef DBGERR
-#define DBGERR(fmt)
-#endif
-#ifndef DBGBH
-#define DBGBH(fmt)
-#endif
-#ifndef DBGISR
-#define DBGISR(fmt)
-#endif
-
-#ifdef DBGDATA
-static void trace_block(struct slgt_info *info, const char *data, int count, const char *label)
-{
-	int i;
-	int linecount;
-	printk("%s %s data:\n",info->device_name, label);
-	while(count) {
-		linecount = (count > 16) ? 16 : count;
-		for(i=0; i < linecount; i++)
-			printk("%02X ",(unsigned char)data[i]);
-		for(;i<17;i++)
-			printk("   ");
-		for(i=0;i<linecount;i++) {
-			if (data[i]>=040 && data[i]<=0176)
-				printk("%c",data[i]);
-			else
-				printk(".");
-		}
-		printk("\n");
-		data  += linecount;
-		count -= linecount;
-	}
-}
-#else
-#define DBGDATA(info, buf, size, label)
-#endif
-
-#ifdef DBGTBUF
-static void dump_tbufs(struct slgt_info *info)
-{
-	int i;
-	printk("tbuf_current=%d\n", info->tbuf_current);
-	for (i=0 ; i < info->tbuf_count ; i++) {
-		printk("%d: count=%04X status=%04X\n",
-			i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status));
-	}
-}
-#else
-#define DBGTBUF(info)
-#endif
-
-#ifdef DBGRBUF
-static void dump_rbufs(struct slgt_info *info)
-{
-	int i;
-	printk("rbuf_current=%d\n", info->rbuf_current);
-	for (i=0 ; i < info->rbuf_count ; i++) {
-		printk("%d: count=%04X status=%04X\n",
-			i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status));
-	}
-}
-#else
-#define DBGRBUF(info)
-#endif
-
-static inline int sanity_check(struct slgt_info *info, char *devname, const char *name)
-{
-#ifdef SANITY_CHECK
-	if (!info) {
-		printk("null struct slgt_info for (%s) in %s\n", devname, name);
-		return 1;
-	}
-	if (info->magic != MGSL_MAGIC) {
-		printk("bad magic number struct slgt_info (%s) in %s\n", devname, name);
-		return 1;
-	}
-#else
-	if (!info)
-		return 1;
-#endif
-	return 0;
-}
-
-/**
- * line discipline callback wrappers
- *
- * The wrappers maintain line discipline references
- * while calling into the line discipline.
- *
- * ldisc_receive_buf  - pass receive data to line discipline
- */
-static void ldisc_receive_buf(struct tty_struct *tty,
-			      const __u8 *data, char *flags, int count)
-{
-	struct tty_ldisc *ld;
-	if (!tty)
-		return;
-	ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->receive_buf)
-			ld->ops->receive_buf(tty, data, flags, count);
-		tty_ldisc_deref(ld);
-	}
-}
-
-/* tty callbacks */
-
-static int open(struct tty_struct *tty, struct file *filp)
-{
-	struct slgt_info *info;
-	int retval, line;
-	unsigned long flags;
-
-	line = tty->index;
-	if ((line < 0) || (line >= slgt_device_count)) {
-		DBGERR(("%s: open with invalid line #%d.\n", driver_name, line));
-		return -ENODEV;
-	}
-
-	info = slgt_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (sanity_check(info, tty->name, "open"))
-		return -ENODEV;
-	if (info->init_error) {
-		DBGERR(("%s init error=%d\n", info->device_name, info->init_error));
-		return -ENODEV;
-	}
-
-	tty->driver_data = info;
-	info->port.tty = tty;
-
-	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
-
-	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-		if (info->port.flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->port.close_wait);
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
-	mutex_lock(&info->port.mutex);
-	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->netcount) {
-		retval = -EBUSY;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		mutex_unlock(&info->port.mutex);
-		goto cleanup;
-	}
-	info->port.count++;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	if (info->port.count == 1) {
-		/* 1st open on this device, init hardware */
-		retval = startup(info);
-		if (retval < 0) {
-			mutex_unlock(&info->port.mutex);
-			goto cleanup;
-		}
-	}
-	mutex_unlock(&info->port.mutex);
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
-		goto cleanup;
-	}
-
-	retval = 0;
-
-cleanup:
-	if (retval) {
-		if (tty->count == 1)
-			info->port.tty = NULL; /* tty layer will release tty struct */
-		if(info->port.count)
-			info->port.count--;
-	}
-
-	DBGINFO(("%s open rc=%d\n", info->device_name, retval));
-	return retval;
-}
-
-static void close(struct tty_struct *tty, struct file *filp)
-{
-	struct slgt_info *info = tty->driver_data;
-
-	if (sanity_check(info, tty->name, "close"))
-		return;
-	DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count));
-
-	if (tty_port_close_start(&info->port, tty, filp) == 0)
-		goto cleanup;
-
-	mutex_lock(&info->port.mutex);
- 	if (info->port.flags & ASYNC_INITIALIZED)
- 		wait_until_sent(tty, info->timeout);
-	flush_buffer(tty);
-	tty_ldisc_flush(tty);
-
-	shutdown(info);
-	mutex_unlock(&info->port.mutex);
-
-	tty_port_close_end(&info->port, tty);
-	info->port.tty = NULL;
-cleanup:
-	DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count));
-}
-
-static void hangup(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "hangup"))
-		return;
-	DBGINFO(("%s hangup\n", info->device_name));
-
-	flush_buffer(tty);
-
-	mutex_lock(&info->port.mutex);
-	shutdown(info);
-
-	spin_lock_irqsave(&info->port.lock, flags);
-	info->port.count = 0;
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-	spin_unlock_irqrestore(&info->port.lock, flags);
-	mutex_unlock(&info->port.mutex);
-
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	DBGINFO(("%s set_termios\n", tty->driver->name));
-
-	change_params(info);
-
-	/* Handle transition to B0 status */
-	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-		spin_lock_irqsave(&info->lock,flags);
-		set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
-		info->signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
- 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->signals |= SerialSignal_RTS;
- 		}
-		spin_lock_irqsave(&info->lock,flags);
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		tx_release(tty);
-	}
-}
-
-static void update_tx_timer(struct slgt_info *info)
-{
-	/*
-	 * use worst case speed of 1200bps to calculate transmit timeout
-	 * based on data in buffers (tbuf_bytes) and FIFO (128 bytes)
-	 */
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		int timeout  = (tbuf_bytes(info) * 7) + 1000;
-		mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout));
-	}
-}
-
-static int write(struct tty_struct *tty,
-		 const unsigned char *buf, int count)
-{
-	int ret = 0;
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "write"))
-		return -EIO;
-
-	DBGINFO(("%s write count=%d\n", info->device_name, count));
-
-	if (!info->tx_buf || (count > info->max_frame_size))
-		return -EIO;
-
-	if (!count || tty->stopped || tty->hw_stopped)
-		return 0;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (info->tx_count) {
-		/* send accumulated data from send_char() */
-		if (!tx_load(info, info->tx_buf, info->tx_count))
-			goto cleanup;
-		info->tx_count = 0;
-	}
-
-	if (tx_load(info, buf, count))
-		ret = count;
-
-cleanup:
-	spin_unlock_irqrestore(&info->lock, flags);
-	DBGINFO(("%s write rc=%d\n", info->device_name, ret));
-	return ret;
-}
-
-static int put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (sanity_check(info, tty->name, "put_char"))
-		return 0;
-	DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
-	if (!info->tx_buf)
-		return 0;
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_count < info->max_frame_size) {
-		info->tx_buf[info->tx_count++] = ch;
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return ret;
-}
-
-static void send_xchar(struct tty_struct *tty, char ch)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "send_xchar"))
-		return;
-	DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch));
-	info->x_char = ch;
-	if (ch) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_enabled)
-		 	tx_start(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-static void wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-
-	if (!info )
-		return;
-	if (sanity_check(info, tty->name, "wait_until_sent"))
-		return;
-	DBGINFO(("%s wait_until_sent entry\n", info->device_name));
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		goto exit;
-
-	orig_jiffies = jiffies;
-
-	/* Set check interval to 1/5 of estimated time to
-	 * send a character, and make it at least 1. The check
-	 * interval should also be less than the timeout.
-	 * Note: use tight timings here to satisfy the NIST-PCTS.
-	 */
-
-	if (info->params.data_rate) {
-	       	char_time = info->timeout/(32 * 5);
-		if (!char_time)
-			char_time++;
-	} else
-		char_time = 1;
-
-	if (timeout)
-		char_time = min_t(unsigned long, char_time, timeout);
-
-	while (info->tx_active) {
-		msleep_interruptible(jiffies_to_msecs(char_time));
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-exit:
-	DBGINFO(("%s wait_until_sent exit\n", info->device_name));
-}
-
-static int write_room(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	int ret;
-
-	if (sanity_check(info, tty->name, "write_room"))
-		return 0;
-	ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
-	DBGINFO(("%s write_room=%d\n", info->device_name, ret));
-	return ret;
-}
-
-static void flush_chars(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "flush_chars"))
-		return;
-	DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));
-
-	if (info->tx_count <= 0 || tty->stopped ||
-	    tty->hw_stopped || !info->tx_buf)
-		return;
-
-	DBGINFO(("%s flush_chars start transmit\n", info->device_name));
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
-		info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-static void flush_buffer(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "flush_buffer"))
-		return;
-	DBGINFO(("%s flush_buffer\n", info->device_name));
-
-	spin_lock_irqsave(&info->lock, flags);
-	info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	tty_wakeup(tty);
-}
-
-/*
- * throttle (stop) transmitter
- */
-static void tx_hold(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_hold"))
-		return;
-	DBGINFO(("%s tx_hold\n", info->device_name));
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)
-	 	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/*
- * release (start) transmitter
- */
-static void tx_release(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_release"))
-		return;
-	DBGINFO(("%s tx_release\n", info->device_name));
-	spin_lock_irqsave(&info->lock, flags);
-	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
-		info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-/*
- * Service an IOCTL request
- *
- * Arguments
- *
- * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
- * 	cmd	IOCTL command code
- * 	arg	command argument/context
- *
- * Return 0 if success, otherwise error code
- */
-static int ioctl(struct tty_struct *tty, struct file *file,
-		 unsigned int cmd, unsigned long arg)
-{
-	struct slgt_info *info = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int ret;
-
-	if (sanity_check(info, tty->name, "ioctl"))
-		return -ENODEV;
-	DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-	case MGSL_IOCWAITEVENT:
-		return wait_mgsl_event(info, argp);
-	case TIOCMIWAIT:
-		return modem_input_wait(info,(int)arg);
-	case MGSL_IOCSGPIO:
-		return set_gpio(info, argp);
-	case MGSL_IOCGGPIO:
-		return get_gpio(info, argp);
-	case MGSL_IOCWAITGPIO:
-		return wait_gpio(info, argp);
-	case MGSL_IOCGXSYNC:
-		return get_xsync(info, argp);
-	case MGSL_IOCSXSYNC:
-		return set_xsync(info, (int)arg);
-	case MGSL_IOCGXCTRL:
-		return get_xctrl(info, argp);
-	case MGSL_IOCSXCTRL:
-		return set_xctrl(info, (int)arg);
-	}
-	mutex_lock(&info->port.mutex);
-	switch (cmd) {
-	case MGSL_IOCGPARAMS:
-		ret = get_params(info, argp);
-		break;
-	case MGSL_IOCSPARAMS:
-		ret = set_params(info, argp);
-		break;
-	case MGSL_IOCGTXIDLE:
-		ret = get_txidle(info, argp);
-		break;
-	case MGSL_IOCSTXIDLE:
-		ret = set_txidle(info, (int)arg);
-		break;
-	case MGSL_IOCTXENABLE:
-		ret = tx_enable(info, (int)arg);
-		break;
-	case MGSL_IOCRXENABLE:
-		ret = rx_enable(info, (int)arg);
-		break;
-	case MGSL_IOCTXABORT:
-		ret = tx_abort(info);
-		break;
-	case MGSL_IOCGSTATS:
-		ret = get_stats(info, argp);
-		break;
-	case MGSL_IOCGIF:
-		ret = get_interface(info, argp);
-		break;
-	case MGSL_IOCSIF:
-		ret = set_interface(info,(int)arg);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-	mutex_unlock(&info->port.mutex);
-	return ret;
-}
-
-static int get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-
-{
-	struct slgt_info *info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-/*
- * support for 32 bit ioctl calls on 64 bit systems
- */
-#ifdef CONFIG_COMPAT
-static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params)
-{
-	struct MGSL_PARAMS32 tmp_params;
-
-	DBGINFO(("%s get_params32\n", info->device_name));
-	memset(&tmp_params, 0, sizeof(tmp_params));
-	tmp_params.mode            = (compat_ulong_t)info->params.mode;
-	tmp_params.loopback        = info->params.loopback;
-	tmp_params.flags           = info->params.flags;
-	tmp_params.encoding        = info->params.encoding;
-	tmp_params.clock_speed     = (compat_ulong_t)info->params.clock_speed;
-	tmp_params.addr_filter     = info->params.addr_filter;
-	tmp_params.crc_type        = info->params.crc_type;
-	tmp_params.preamble_length = info->params.preamble_length;
-	tmp_params.preamble        = info->params.preamble;
-	tmp_params.data_rate       = (compat_ulong_t)info->params.data_rate;
-	tmp_params.data_bits       = info->params.data_bits;
-	tmp_params.stop_bits       = info->params.stop_bits;
-	tmp_params.parity          = info->params.parity;
-	if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32)))
-		return -EFAULT;
-	return 0;
-}
-
-static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params)
-{
-	struct MGSL_PARAMS32 tmp_params;
-
-	DBGINFO(("%s set_params32\n", info->device_name));
-	if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32)))
-		return -EFAULT;
-
-	spin_lock(&info->lock);
-	if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) {
-		info->base_clock = tmp_params.clock_speed;
-	} else {
-		info->params.mode            = tmp_params.mode;
-		info->params.loopback        = tmp_params.loopback;
-		info->params.flags           = tmp_params.flags;
-		info->params.encoding        = tmp_params.encoding;
-		info->params.clock_speed     = tmp_params.clock_speed;
-		info->params.addr_filter     = tmp_params.addr_filter;
-		info->params.crc_type        = tmp_params.crc_type;
-		info->params.preamble_length = tmp_params.preamble_length;
-		info->params.preamble        = tmp_params.preamble;
-		info->params.data_rate       = tmp_params.data_rate;
-		info->params.data_bits       = tmp_params.data_bits;
-		info->params.stop_bits       = tmp_params.stop_bits;
-		info->params.parity          = tmp_params.parity;
-	}
-	spin_unlock(&info->lock);
-
-	program_hw(info);
-
-	return 0;
-}
-
-static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct slgt_info *info = tty->driver_data;
-	int rc = -ENOIOCTLCMD;
-
-	if (sanity_check(info, tty->name, "compat_ioctl"))
-		return -ENODEV;
-	DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
-
-	switch (cmd) {
-
-	case MGSL_IOCSPARAMS32:
-		rc = set_params32(info, compat_ptr(arg));
-		break;
-
-	case MGSL_IOCGPARAMS32:
-		rc = get_params32(info, compat_ptr(arg));
-		break;
-
-	case MGSL_IOCGPARAMS:
-	case MGSL_IOCSPARAMS:
-	case MGSL_IOCGTXIDLE:
-	case MGSL_IOCGSTATS:
-	case MGSL_IOCWAITEVENT:
-	case MGSL_IOCGIF:
-	case MGSL_IOCSGPIO:
-	case MGSL_IOCGGPIO:
-	case MGSL_IOCWAITGPIO:
-	case MGSL_IOCGXSYNC:
-	case MGSL_IOCGXCTRL:
-	case MGSL_IOCSTXIDLE:
-	case MGSL_IOCTXENABLE:
-	case MGSL_IOCRXENABLE:
-	case MGSL_IOCTXABORT:
-	case TIOCMIWAIT:
-	case MGSL_IOCSIF:
-	case MGSL_IOCSXSYNC:
-	case MGSL_IOCSXCTRL:
-		rc = ioctl(tty, file, cmd, arg);
-		break;
-	}
-
-	DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
-	return rc;
-}
-#else
-#define slgt_compat_ioctl NULL
-#endif /* ifdef CONFIG_COMPAT */
-
-/*
- * proc fs support
- */
-static inline void line_info(struct seq_file *m, struct slgt_info *info)
-{
-	char stat_buf[30];
-	unsigned long flags;
-
-	seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n",
-		      info->device_name, info->phys_reg_addr,
-		      info->irq_level, info->max_frame_size);
-
-	/* output current serial signal states */
-	spin_lock_irqsave(&info->lock,flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (info->signals & SerialSignal_RTS)
-		strcat(stat_buf, "|RTS");
-	if (info->signals & SerialSignal_CTS)
-		strcat(stat_buf, "|CTS");
-	if (info->signals & SerialSignal_DTR)
-		strcat(stat_buf, "|DTR");
-	if (info->signals & SerialSignal_DSR)
-		strcat(stat_buf, "|DSR");
-	if (info->signals & SerialSignal_DCD)
-		strcat(stat_buf, "|CD");
-	if (info->signals & SerialSignal_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		seq_printf(m, "\tHDLC txok:%d rxok:%d",
-			       info->icount.txok, info->icount.rxok);
-		if (info->icount.txunder)
-			seq_printf(m, " txunder:%d", info->icount.txunder);
-		if (info->icount.txabort)
-			seq_printf(m, " txabort:%d", info->icount.txabort);
-		if (info->icount.rxshort)
-			seq_printf(m, " rxshort:%d", info->icount.rxshort);
-		if (info->icount.rxlong)
-			seq_printf(m, " rxlong:%d", info->icount.rxlong);
-		if (info->icount.rxover)
-			seq_printf(m, " rxover:%d", info->icount.rxover);
-		if (info->icount.rxcrc)
-			seq_printf(m, " rxcrc:%d", info->icount.rxcrc);
-	} else {
-		seq_printf(m, "\tASYNC tx:%d rx:%d",
-			       info->icount.tx, info->icount.rx);
-		if (info->icount.frame)
-			seq_printf(m, " fe:%d", info->icount.frame);
-		if (info->icount.parity)
-			seq_printf(m, " pe:%d", info->icount.parity);
-		if (info->icount.brk)
-			seq_printf(m, " brk:%d", info->icount.brk);
-		if (info->icount.overrun)
-			seq_printf(m, " oe:%d", info->icount.overrun);
-	}
-
-	/* Append serial signal status to end */
-	seq_printf(m, " %s\n", stat_buf+1);
-
-	seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
-		       info->tx_active,info->bh_requested,info->bh_running,
-		       info->pending_bh);
-}
-
-/* Called to print information about devices
- */
-static int synclink_gt_proc_show(struct seq_file *m, void *v)
-{
-	struct slgt_info *info;
-
-	seq_puts(m, "synclink_gt driver\n");
-
-	info = slgt_device_list;
-	while( info ) {
-		line_info(m, info);
-		info = info->next_device;
-	}
-	return 0;
-}
-
-static int synclink_gt_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, synclink_gt_proc_show, NULL);
-}
-
-static const struct file_operations synclink_gt_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= synclink_gt_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * return count of bytes in transmit buffer
- */
-static int chars_in_buffer(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	int count;
-	if (sanity_check(info, tty->name, "chars_in_buffer"))
-		return 0;
-	count = tbuf_bytes(info);
-	DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count));
-	return count;
-}
-
-/*
- * signal remote device to throttle send data (our receive data)
- */
-static void throttle(struct tty_struct * tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "throttle"))
-		return;
-	DBGINFO(("%s throttle\n", info->device_name));
-	if (I_IXOFF(tty))
-		send_xchar(tty, STOP_CHAR(tty));
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->signals &= ~SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/*
- * signal remote device to stop throttling send data (our receive data)
- */
-static void unthrottle(struct tty_struct * tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "unthrottle"))
-		return;
-	DBGINFO(("%s unthrottle\n", info->device_name));
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			send_xchar(tty, START_CHAR(tty));
-	}
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->signals |= SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/*
- * set or clear transmit break condition
- * break_state	-1=set break condition, 0=clear
- */
-static int set_break(struct tty_struct *tty, int break_state)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned short value;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "set_break"))
-		return -EINVAL;
-	DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
-
-	spin_lock_irqsave(&info->lock,flags);
-	value = rd_reg16(info, TCR);
- 	if (break_state == -1)
-		value |= BIT6;
-	else
-		value &= ~BIT6;
-	wr_reg16(info, TCR, value);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-#if SYNCLINK_GENERIC_HDLC
-
-/**
- * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
- * set encoding and frame check sequence (FCS) options
- *
- * dev       pointer to network device structure
- * encoding  serial encoding setting
- * parity    FCS setting
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
-			  unsigned short parity)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned char  new_encoding;
-	unsigned short new_crctype;
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	DBGINFO(("%s hdlcdev_attach\n", info->device_name));
-
-	switch (encoding)
-	{
-	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
-	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
-	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
-	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
-	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
-	default: return -EINVAL;
-	}
-
-	switch (parity)
-	{
-	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
-	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
-	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
-	default: return -EINVAL;
-	}
-
-	info->params.encoding = new_encoding;
-	info->params.crc_type = new_crctype;
-
-	/* if network interface up, reprogram hardware */
-	if (info->netcount)
-		program_hw(info);
-
-	return 0;
-}
-
-/**
- * called by generic HDLC layer to send frame
- *
- * skb  socket buffer containing HDLC frame
- * dev  pointer to network device structure
- */
-static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned long flags;
-
-	DBGINFO(("%s hdlc_xmit\n", dev->name));
-
-	if (!skb->len)
-		return NETDEV_TX_OK;
-
-	/* stop sending until this frame completes */
-	netif_stop_queue(dev);
-
-	/* update network statistics */
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* save start time for transmit timeout detection */
-	dev->trans_start = jiffies;
-
-	spin_lock_irqsave(&info->lock, flags);
-	tx_load(info, skb->data, skb->len);
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * called by network layer when interface enabled
- * claim resources and initialize hardware
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_open(struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	int rc;
-	unsigned long flags;
-
-	if (!try_module_get(THIS_MODULE))
-		return -EBUSY;
-
-	DBGINFO(("%s hdlcdev_open\n", dev->name));
-
-	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
-		return rc;
-
-	/* arbitrate between network and tty opens */
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->port.count != 0 || info->netcount != 0) {
-		DBGINFO(("%s hdlc_open busy\n", dev->name));
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return -EBUSY;
-	}
-	info->netcount=1;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	/* claim resources and init adapter */
-	if ((rc = startup(info)) != 0) {
-		spin_lock_irqsave(&info->netlock, flags);
-		info->netcount=0;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return rc;
-	}
-
-	/* assert DTR and RTS, apply hardware settings */
-	info->signals |= SerialSignal_RTS + SerialSignal_DTR;
-	program_hw(info);
-
-	/* enable network layer transmit */
-	dev->trans_start = jiffies;
-	netif_start_queue(dev);
-
-	/* inform generic HDLC layer of current DCD status */
-	spin_lock_irqsave(&info->lock, flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock, flags);
-	if (info->signals & SerialSignal_DCD)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-	return 0;
-}
-
-/**
- * called by network layer when interface is disabled
- * shutdown hardware and release resources
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_close(struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned long flags;
-
-	DBGINFO(("%s hdlcdev_close\n", dev->name));
-
-	netif_stop_queue(dev);
-
-	/* shutdown adapter and release resources */
-	shutdown(info);
-
-	hdlc_close(dev);
-
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	module_put(THIS_MODULE);
-	return 0;
-}
-
-/**
- * called by network layer to process IOCTL call to network device
- *
- * dev  pointer to network device structure
- * ifr  pointer to network interface request structure
- * cmd  IOCTL command code
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line;
-	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned int flags;
-
-	DBGINFO(("%s hdlcdev_ioctl\n", dev->name));
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	if (cmd != SIOCWANDEV)
-		return hdlc_ioctl(dev, ifr, cmd);
-
-	memset(&new_line, 0, sizeof(new_line));
-
-	switch(ifr->ifr_settings.type) {
-	case IF_GET_IFACE: /* return current sync_serial_settings */
-
-		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
-		if (ifr->ifr_settings.size < size) {
-			ifr->ifr_settings.size = size; /* data size wanted */
-			return -ENOBUFS;
-		}
-
-		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-
-		switch (flags){
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
-		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
-		default: new_line.clock_type = CLOCK_DEFAULT;
-		}
-
-		new_line.clock_rate = info->params.clock_speed;
-		new_line.loopback   = info->params.loopback ? 1:0;
-
-		if (copy_to_user(line, &new_line, size))
-			return -EFAULT;
-		return 0;
-
-	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
-
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&new_line, line, size))
-			return -EFAULT;
-
-		switch (new_line.clock_type)
-		{
-		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
-		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
-		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_DEFAULT:  flags = info->params.flags &
-					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
-		default: return -EINVAL;
-		}
-
-		if (new_line.loopback != 0 && new_line.loopback != 1)
-			return -EINVAL;
-
-		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-		info->params.flags |= flags;
-
-		info->params.loopback = new_line.loopback;
-
-		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
-			info->params.clock_speed = new_line.clock_rate;
-		else
-			info->params.clock_speed = 0;
-
-		/* if network interface up, reprogram hardware */
-		if (info->netcount)
-			program_hw(info);
-		return 0;
-
-	default:
-		return hdlc_ioctl(dev, ifr, cmd);
-	}
-}
-
-/**
- * called by network layer when transmit timeout is detected
- *
- * dev  pointer to network device structure
- */
-static void hdlcdev_tx_timeout(struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned long flags;
-
-	DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name));
-
-	dev->stats.tx_errors++;
-	dev->stats.tx_aborted_errors++;
-
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	netif_wake_queue(dev);
-}
-
-/**
- * called by device driver when transmit completes
- * reenable network layer transmit if stopped
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_tx_done(struct slgt_info *info)
-{
-	if (netif_queue_stopped(info->netdev))
-		netif_wake_queue(info->netdev);
-}
-
-/**
- * called by device driver when frame received
- * pass frame to network layer
- *
- * info  pointer to device instance information
- * buf   pointer to buffer contianing frame data
- * size  count of data bytes in buf
- */
-static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size);
-	struct net_device *dev = info->netdev;
-
-	DBGINFO(("%s hdlcdev_rx\n", dev->name));
-
-	if (skb == NULL) {
-		DBGERR(("%s: can't alloc skb, drop packet\n", dev->name));
-		dev->stats.rx_dropped++;
-		return;
-	}
-
-	memcpy(skb_put(skb, size), buf, size);
-
-	skb->protocol = hdlc_type_trans(skb, dev);
-
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += size;
-
-	netif_rx(skb);
-}
-
-static const struct net_device_ops hdlcdev_ops = {
-	.ndo_open       = hdlcdev_open,
-	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
-	.ndo_start_xmit = hdlc_start_xmit,
-	.ndo_do_ioctl   = hdlcdev_ioctl,
-	.ndo_tx_timeout = hdlcdev_tx_timeout,
-};
-
-/**
- * called by device driver when adding device instance
- * do generic HDLC initialization
- *
- * info  pointer to device instance information
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_init(struct slgt_info *info)
-{
-	int rc;
-	struct net_device *dev;
-	hdlc_device *hdlc;
-
-	/* allocate and initialize network and HDLC layer objects */
-
-	if (!(dev = alloc_hdlcdev(info))) {
-		printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
-		return -ENOMEM;
-	}
-
-	/* for network layer reporting purposes only */
-	dev->mem_start = info->phys_reg_addr;
-	dev->mem_end   = info->phys_reg_addr + SLGT_REG_SIZE - 1;
-	dev->irq       = info->irq_level;
-
-	/* network layer callbacks and settings */
-	dev->netdev_ops	    = &hdlcdev_ops;
-	dev->watchdog_timeo = 10 * HZ;
-	dev->tx_queue_len   = 50;
-
-	/* generic HDLC layer callbacks and settings */
-	hdlc         = dev_to_hdlc(dev);
-	hdlc->attach = hdlcdev_attach;
-	hdlc->xmit   = hdlcdev_xmit;
-
-	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
-		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
-		free_netdev(dev);
-		return rc;
-	}
-
-	info->netdev = dev;
-	return 0;
-}
-
-/**
- * called by device driver when removing device instance
- * do generic HDLC cleanup
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_exit(struct slgt_info *info)
-{
-	unregister_hdlc_device(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-}
-
-#endif /* ifdef CONFIG_HDLC */
-
-/*
- * get async data from rx DMA buffers
- */
-static void rx_async(struct slgt_info *info)
-{
- 	struct tty_struct *tty = info->port.tty;
- 	struct mgsl_icount *icount = &info->icount;
-	unsigned int start, end;
-	unsigned char *p;
-	unsigned char status;
-	struct slgt_desc *bufs = info->rbufs;
-	int i, count;
-	int chars = 0;
-	int stat;
-	unsigned char ch;
-
-	start = end = info->rbuf_current;
-
-	while(desc_complete(bufs[end])) {
-		count = desc_count(bufs[end]) - info->rbuf_index;
-		p     = bufs[end].buf + info->rbuf_index;
-
-		DBGISR(("%s rx_async count=%d\n", info->device_name, count));
-		DBGDATA(info, p, count, "rx");
-
-		for(i=0 ; i < count; i+=2, p+=2) {
-			ch = *p;
-			icount->rx++;
-
-			stat = 0;
-
-			if ((status = *(p+1) & (BIT1 + BIT0))) {
-				if (status & BIT1)
-					icount->parity++;
-				else if (status & BIT0)
-					icount->frame++;
-				/* discard char if tty control flags say so */
-				if (status & info->ignore_status_mask)
-					continue;
-				if (status & BIT1)
-					stat = TTY_PARITY;
-				else if (status & BIT0)
-					stat = TTY_FRAME;
-			}
-			if (tty) {
-				tty_insert_flip_char(tty, ch, stat);
-				chars++;
-			}
-		}
-
-		if (i < count) {
-			/* receive buffer not completed */
-			info->rbuf_index += i;
-			mod_timer(&info->rx_timer, jiffies + 1);
-			break;
-		}
-
-		info->rbuf_index = 0;
-		free_rbufs(info, end, end);
-
-		if (++end == info->rbuf_count)
-			end = 0;
-
-		/* if entire list searched then no frame available */
-		if (end == start)
-			break;
-	}
-
-	if (tty && chars)
-		tty_flip_buffer_push(tty);
-}
-
-/*
- * return next bottom half action to perform
- */
-static int bh_action(struct slgt_info *info)
-{
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if (info->pending_bh & BH_RECEIVE) {
-		info->pending_bh &= ~BH_RECEIVE;
-		rc = BH_RECEIVE;
-	} else if (info->pending_bh & BH_TRANSMIT) {
-		info->pending_bh &= ~BH_TRANSMIT;
-		rc = BH_TRANSMIT;
-	} else if (info->pending_bh & BH_STATUS) {
-		info->pending_bh &= ~BH_STATUS;
-		rc = BH_STATUS;
-	} else {
-		/* Mark BH routine as complete */
-		info->bh_running = false;
-		info->bh_requested = false;
-		rc = 0;
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return rc;
-}
-
-/*
- * perform bottom half processing
- */
-static void bh_handler(struct work_struct *work)
-{
-	struct slgt_info *info = container_of(work, struct slgt_info, task);
-	int action;
-
-	if (!info)
-		return;
-	info->bh_running = true;
-
-	while((action = bh_action(info))) {
-		switch (action) {
-		case BH_RECEIVE:
-			DBGBH(("%s bh receive\n", info->device_name));
-			switch(info->params.mode) {
-			case MGSL_MODE_ASYNC:
-				rx_async(info);
-				break;
-			case MGSL_MODE_HDLC:
-				while(rx_get_frame(info));
-				break;
-			case MGSL_MODE_RAW:
-			case MGSL_MODE_MONOSYNC:
-			case MGSL_MODE_BISYNC:
-			case MGSL_MODE_XSYNC:
-				while(rx_get_buf(info));
-				break;
-			}
-			/* restart receiver if rx DMA buffers exhausted */
-			if (info->rx_restart)
-				rx_start(info);
-			break;
-		case BH_TRANSMIT:
-			bh_transmit(info);
-			break;
-		case BH_STATUS:
-			DBGBH(("%s bh status\n", info->device_name));
-			info->ri_chkcount = 0;
-			info->dsr_chkcount = 0;
-			info->dcd_chkcount = 0;
-			info->cts_chkcount = 0;
-			break;
-		default:
-			DBGBH(("%s unknown action\n", info->device_name));
-			break;
-		}
-	}
-	DBGBH(("%s bh_handler exit\n", info->device_name));
-}
-
-static void bh_transmit(struct slgt_info *info)
-{
-	struct tty_struct *tty = info->port.tty;
-
-	DBGBH(("%s bh_transmit\n", info->device_name));
-	if (tty)
-		tty_wakeup(tty);
-}
-
-static void dsr_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT3) {
-		info->signals |= SerialSignal_DSR;
-		info->input_signal_events.dsr_up++;
-	} else {
-		info->signals &= ~SerialSignal_DSR;
-		info->input_signal_events.dsr_down++;
-	}
-	DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_DSR);
-		return;
-	}
-	info->icount.dsr++;
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-}
-
-static void cts_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT2) {
-		info->signals |= SerialSignal_CTS;
-		info->input_signal_events.cts_up++;
-	} else {
-		info->signals &= ~SerialSignal_CTS;
-		info->input_signal_events.cts_down++;
-	}
-	DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_CTS);
-		return;
-	}
-	info->icount.cts++;
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-
-	if (info->port.flags & ASYNC_CTS_FLOW) {
-		if (info->port.tty) {
-			if (info->port.tty->hw_stopped) {
-				if (info->signals & SerialSignal_CTS) {
-		 			info->port.tty->hw_stopped = 0;
-					info->pending_bh |= BH_TRANSMIT;
-					return;
-				}
-			} else {
-				if (!(info->signals & SerialSignal_CTS))
-		 			info->port.tty->hw_stopped = 1;
-			}
-		}
-	}
-}
-
-static void dcd_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT1) {
-		info->signals |= SerialSignal_DCD;
-		info->input_signal_events.dcd_up++;
-	} else {
-		info->signals &= ~SerialSignal_DCD;
-		info->input_signal_events.dcd_down++;
-	}
-	DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_DCD);
-		return;
-	}
-	info->icount.dcd++;
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount) {
-		if (info->signals & SerialSignal_DCD)
-			netif_carrier_on(info->netdev);
-		else
-			netif_carrier_off(info->netdev);
-	}
-#endif
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-
-	if (info->port.flags & ASYNC_CHECK_CD) {
-		if (info->signals & SerialSignal_DCD)
-			wake_up_interruptible(&info->port.open_wait);
-		else {
-			if (info->port.tty)
-				tty_hangup(info->port.tty);
-		}
-	}
-}
-
-static void ri_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT0) {
-		info->signals |= SerialSignal_RI;
-		info->input_signal_events.ri_up++;
-	} else {
-		info->signals &= ~SerialSignal_RI;
-		info->input_signal_events.ri_down++;
-	}
-	DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_RI);
-		return;
-	}
-	info->icount.rng++;
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-}
-
-static void isr_rxdata(struct slgt_info *info)
-{
-	unsigned int count = info->rbuf_fill_count;
-	unsigned int i = info->rbuf_fill_index;
-	unsigned short reg;
-
-	while (rd_reg16(info, SSR) & IRQ_RXDATA) {
-		reg = rd_reg16(info, RDR);
-		DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg));
-		if (desc_complete(info->rbufs[i])) {
-			/* all buffers full */
-			rx_stop(info);
-			info->rx_restart = 1;
-			continue;
-		}
-		info->rbufs[i].buf[count++] = (unsigned char)reg;
-		/* async mode saves status byte to buffer for each data byte */
-		if (info->params.mode == MGSL_MODE_ASYNC)
-			info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8);
-		if (count == info->rbuf_fill_level || (reg & BIT10)) {
-			/* buffer full or end of frame */
-			set_desc_count(info->rbufs[i], count);
-			set_desc_status(info->rbufs[i], BIT15 | (reg >> 8));
-			info->rbuf_fill_count = count = 0;
-			if (++i == info->rbuf_count)
-				i = 0;
-			info->pending_bh |= BH_RECEIVE;
-		}
-	}
-
-	info->rbuf_fill_index = i;
-	info->rbuf_fill_count = count;
-}
-
-static void isr_serial(struct slgt_info *info)
-{
-	unsigned short status = rd_reg16(info, SSR);
-
-	DBGISR(("%s isr_serial status=%04X\n", info->device_name, status));
-
-	wr_reg16(info, SSR, status); /* clear pending */
-
-	info->irq_occurred = true;
-
-	if (info->params.mode == MGSL_MODE_ASYNC) {
-		if (status & IRQ_TXIDLE) {
-			if (info->tx_active)
-				isr_txeom(info, status);
-		}
-		if (info->rx_pio && (status & IRQ_RXDATA))
-			isr_rxdata(info);
-		if ((status & IRQ_RXBREAK) && (status & RXBREAK)) {
-			info->icount.brk++;
-			/* process break detection if tty control allows */
-			if (info->port.tty) {
-				if (!(status & info->ignore_status_mask)) {
-					if (info->read_status_mask & MASK_BREAK) {
-						tty_insert_flip_char(info->port.tty, 0, TTY_BREAK);
-						if (info->port.flags & ASYNC_SAK)
-							do_SAK(info->port.tty);
-					}
-				}
-			}
-		}
-	} else {
-		if (status & (IRQ_TXIDLE + IRQ_TXUNDER))
-			isr_txeom(info, status);
-		if (info->rx_pio && (status & IRQ_RXDATA))
-			isr_rxdata(info);
-		if (status & IRQ_RXIDLE) {
-			if (status & RXIDLE)
-				info->icount.rxidle++;
-			else
-				info->icount.exithunt++;
-			wake_up_interruptible(&info->event_wait_q);
-		}
-
-		if (status & IRQ_RXOVER)
-			rx_start(info);
-	}
-
-	if (status & IRQ_DSR)
-		dsr_change(info, status);
-	if (status & IRQ_CTS)
-		cts_change(info, status);
-	if (status & IRQ_DCD)
-		dcd_change(info, status);
-	if (status & IRQ_RI)
-		ri_change(info, status);
-}
-
-static void isr_rdma(struct slgt_info *info)
-{
-	unsigned int status = rd_reg32(info, RDCSR);
-
-	DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status));
-
-	/* RDCSR (rx DMA control/status)
-	 *
-	 * 31..07  reserved
-	 * 06      save status byte to DMA buffer
-	 * 05      error
-	 * 04      eol (end of list)
-	 * 03      eob (end of buffer)
-	 * 02      IRQ enable
-	 * 01      reset
-	 * 00      enable
-	 */
-	wr_reg32(info, RDCSR, status);	/* clear pending */
-
-	if (status & (BIT5 + BIT4)) {
-		DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
-		info->rx_restart = true;
-	}
-	info->pending_bh |= BH_RECEIVE;
-}
-
-static void isr_tdma(struct slgt_info *info)
-{
-	unsigned int status = rd_reg32(info, TDCSR);
-
-	DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status));
-
-	/* TDCSR (tx DMA control/status)
-	 *
-	 * 31..06  reserved
-	 * 05      error
-	 * 04      eol (end of list)
-	 * 03      eob (end of buffer)
-	 * 02      IRQ enable
-	 * 01      reset
-	 * 00      enable
-	 */
-	wr_reg32(info, TDCSR, status);	/* clear pending */
-
-	if (status & (BIT5 + BIT4 + BIT3)) {
-		// another transmit buffer has completed
-		// run bottom half to get more send data from user
-		info->pending_bh |= BH_TRANSMIT;
-	}
-}
-
-/*
- * return true if there are unsent tx DMA buffers, otherwise false
- *
- * if there are unsent buffers then info->tbuf_start
- * is set to index of first unsent buffer
- */
-static bool unsent_tbufs(struct slgt_info *info)
-{
-	unsigned int i = info->tbuf_current;
-	bool rc = false;
-
-	/*
-	 * search backwards from last loaded buffer (precedes tbuf_current)
-	 * for first unsent buffer (desc_count > 0)
-	 */
-
-	do {
-		if (i)
-			i--;
-		else
-			i = info->tbuf_count - 1;
-		if (!desc_count(info->tbufs[i]))
-			break;
-		info->tbuf_start = i;
-		rc = true;
-	} while (i != info->tbuf_current);
-
-	return rc;
-}
-
-static void isr_txeom(struct slgt_info *info, unsigned short status)
-{
-	DBGISR(("%s txeom status=%04x\n", info->device_name, status));
-
-	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
-	tdma_reset(info);
-	if (status & IRQ_TXUNDER) {
-		unsigned short val = rd_reg16(info, TCR);
-		wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-		wr_reg16(info, TCR, val); /* clear reset bit */
-	}
-
-	if (info->tx_active) {
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			if (status & IRQ_TXUNDER)
-				info->icount.txunder++;
-			else if (status & IRQ_TXIDLE)
-				info->icount.txok++;
-		}
-
-		if (unsent_tbufs(info)) {
-			tx_start(info);
-			update_tx_timer(info);
-			return;
-		}
-		info->tx_active = false;
-
-		del_timer(&info->tx_timer);
-
-		if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
-			info->signals &= ~SerialSignal_RTS;
-			info->drop_rts_on_tx_done = false;
-			set_signals(info);
-		}
-
-#if SYNCLINK_GENERIC_HDLC
-		if (info->netcount)
-			hdlcdev_tx_done(info);
-		else
-#endif
-		{
-			if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
-				tx_stop(info);
-				return;
-			}
-			info->pending_bh |= BH_TRANSMIT;
-		}
-	}
-}
-
-static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state)
-{
-	struct cond_wait *w, *prev;
-
-	/* wake processes waiting for specific transitions */
-	for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) {
-		if (w->data & changed) {
-			w->data = state;
-			wake_up_interruptible(&w->q);
-			if (prev != NULL)
-				prev->next = w->next;
-			else
-				info->gpio_wait_q = w->next;
-		} else
-			prev = w;
-	}
-}
-
-/* interrupt service routine
- *
- * 	irq	interrupt number
- * 	dev_id	device ID supplied during interrupt registration
- */
-static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
-{
-	struct slgt_info *info = dev_id;
-	unsigned int gsr;
-	unsigned int i;
-
-	DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
-
-	while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
-		DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
-		info->irq_occurred = true;
-		for(i=0; i < info->port_count ; i++) {
-			if (info->port_array[i] == NULL)
-				continue;
-			spin_lock(&info->port_array[i]->lock);
-			if (gsr & (BIT8 << i))
-				isr_serial(info->port_array[i]);
-			if (gsr & (BIT16 << (i*2)))
-				isr_rdma(info->port_array[i]);
-			if (gsr & (BIT17 << (i*2)))
-				isr_tdma(info->port_array[i]);
-			spin_unlock(&info->port_array[i]->lock);
-		}
-	}
-
-	if (info->gpio_present) {
-		unsigned int state;
-		unsigned int changed;
-		spin_lock(&info->lock);
-		while ((changed = rd_reg32(info, IOSR)) != 0) {
-			DBGISR(("%s iosr=%08x\n", info->device_name, changed));
-			/* read latched state of GPIO signals */
-			state = rd_reg32(info, IOVR);
-			/* clear pending GPIO interrupt bits */
-			wr_reg32(info, IOSR, changed);
-			for (i=0 ; i < info->port_count ; i++) {
-				if (info->port_array[i] != NULL)
-					isr_gpio(info->port_array[i], changed, state);
-			}
-		}
-		spin_unlock(&info->lock);
-	}
-
-	for(i=0; i < info->port_count ; i++) {
-		struct slgt_info *port = info->port_array[i];
-		if (port == NULL)
-			continue;
-		spin_lock(&port->lock);
-		if ((port->port.count || port->netcount) &&
-		    port->pending_bh && !port->bh_running &&
-		    !port->bh_requested) {
-			DBGISR(("%s bh queued\n", port->device_name));
-			schedule_work(&port->task);
-			port->bh_requested = true;
-		}
-		spin_unlock(&port->lock);
-	}
-
-	DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
-	return IRQ_HANDLED;
-}
-
-static int startup(struct slgt_info *info)
-{
-	DBGINFO(("%s startup\n", info->device_name));
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		return 0;
-
-	if (!info->tx_buf) {
-		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
-		if (!info->tx_buf) {
-			DBGERR(("%s can't allocate tx buffer\n", info->device_name));
-			return -ENOMEM;
-		}
-	}
-
-	info->pending_bh = 0;
-
-	memset(&info->icount, 0, sizeof(info->icount));
-
-	/* program hardware for current parameters */
-	change_params(info);
-
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags |= ASYNC_INITIALIZED;
-
-	return 0;
-}
-
-/*
- *  called by close() and hangup() to shutdown hardware
- */
-static void shutdown(struct slgt_info *info)
-{
-	unsigned long flags;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	DBGINFO(("%s shutdown\n", info->device_name));
-
-	/* clear status wait queue because status changes */
-	/* can't happen after shutting down the hardware */
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-
-	del_timer_sync(&info->tx_timer);
-	del_timer_sync(&info->rx_timer);
-
-	kfree(info->tx_buf);
-	info->tx_buf = NULL;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	tx_stop(info);
-	rx_stop(info);
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
- 		info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		set_signals(info);
-	}
-
-	flush_cond_wait(&info->gpio_wait_q);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-}
-
-static void program_hw(struct slgt_info *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	rx_stop(info);
-	tx_stop(info);
-
-	if (info->params.mode != MGSL_MODE_ASYNC ||
-	    info->netcount)
-		sync_mode(info);
-	else
-		async_mode(info);
-
-	set_signals(info);
-
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-
-	slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI);
-	get_signals(info);
-
-	if (info->netcount ||
-	    (info->port.tty && info->port.tty->termios->c_cflag & CREAD))
-		rx_start(info);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/*
- * reconfigure adapter based on new parameters
- */
-static void change_params(struct slgt_info *info)
-{
-	unsigned cflag;
-	int bits_per_char;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-	DBGINFO(("%s change_params\n", info->device_name));
-
-	cflag = info->port.tty->termios->c_cflag;
-
-	/* if B0 rate (hangup) specified then negate DTR and RTS */
-	/* otherwise assert DTR and RTS */
- 	if (cflag & CBAUD)
-		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-
-	/* byte size and parity */
-
-	switch (cflag & CSIZE) {
-	case CS5: info->params.data_bits = 5; break;
-	case CS6: info->params.data_bits = 6; break;
-	case CS7: info->params.data_bits = 7; break;
-	case CS8: info->params.data_bits = 8; break;
-	default:  info->params.data_bits = 7; break;
-	}
-
-	info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1;
-
-	if (cflag & PARENB)
-		info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN;
-	else
-		info->params.parity = ASYNC_PARITY_NONE;
-
-	/* calculate number of jiffies to transmit a full
-	 * FIFO (32 bytes) at specified data rate
-	 */
-	bits_per_char = info->params.data_bits +
-			info->params.stop_bits + 1;
-
-	info->params.data_rate = tty_get_baud_rate(info->port.tty);
-
-	if (info->params.data_rate) {
-		info->timeout = (32*HZ*bits_per_char) /
-				info->params.data_rate;
-	}
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/* process tty input control flags */
-
-	info->read_status_mask = IRQ_RXOVER;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask |= MASK_PARITY | MASK_FRAMING;
- 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- 		info->read_status_mask |= MASK_BREAK;
-	if (I_IGNPAR(info->port.tty))
-		info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING;
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask |= MASK_BREAK;
-		/* If ignoring parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty))
-			info->ignore_status_mask |= MASK_OVERRUN;
-	}
-
-	program_hw(info);
-}
-
-static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount)
-{
-	DBGINFO(("%s get_stats\n",  info->device_name));
-	if (!user_icount) {
-		memset(&info->icount, 0, sizeof(info->icount));
-	} else {
-		if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount)))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params)
-{
-	DBGINFO(("%s get_params\n", info->device_name));
-	if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params)
-{
- 	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-
-	DBGINFO(("%s set_params\n", info->device_name));
-	if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS)))
-		return -EFAULT;
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (tmp_params.mode == MGSL_MODE_BASE_CLOCK)
-		info->base_clock = tmp_params.clock_speed;
-	else
-		memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS));
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	program_hw(info);
-
-	return 0;
-}
-
-static int get_txidle(struct slgt_info *info, int __user *idle_mode)
-{
-	DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode));
-	if (put_user(info->idle_mode, idle_mode))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_txidle(struct slgt_info *info, int idle_mode)
-{
- 	unsigned long flags;
-	DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
-	spin_lock_irqsave(&info->lock,flags);
-	info->idle_mode = idle_mode;
-	if (info->params.mode != MGSL_MODE_ASYNC)
-		tx_set_idle(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int tx_enable(struct slgt_info *info, int enable)
-{
- 	unsigned long flags;
-	DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable));
-	spin_lock_irqsave(&info->lock,flags);
-	if (enable) {
-		if (!info->tx_enabled)
-			tx_start(info);
-	} else {
-		if (info->tx_enabled)
-			tx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/*
- * abort transmit HDLC frame
- */
-static int tx_abort(struct slgt_info *info)
-{
- 	unsigned long flags;
-	DBGINFO(("%s tx_abort\n", info->device_name));
-	spin_lock_irqsave(&info->lock,flags);
-	tdma_reset(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int rx_enable(struct slgt_info *info, int enable)
-{
- 	unsigned long flags;
-	unsigned int rbuf_fill_level;
-	DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable));
-	spin_lock_irqsave(&info->lock,flags);
-	/*
-	 * enable[31..16] = receive DMA buffer fill level
-	 * 0 = noop (leave fill level unchanged)
-	 * fill level must be multiple of 4 and <= buffer size
-	 */
-	rbuf_fill_level = ((unsigned int)enable) >> 16;
-	if (rbuf_fill_level) {
-		if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) {
-			spin_unlock_irqrestore(&info->lock, flags);
-			return -EINVAL;
-		}
-		info->rbuf_fill_level = rbuf_fill_level;
-		if (rbuf_fill_level < 128)
-			info->rx_pio = 1; /* PIO mode */
-		else
-			info->rx_pio = 0; /* DMA mode */
-		rx_stop(info); /* restart receiver to use new fill level */
-	}
-
-	/*
-	 * enable[1..0] = receiver enable command
-	 * 0 = disable
-	 * 1 = enable
-	 * 2 = enable or force hunt mode if already enabled
-	 */
-	enable &= 3;
-	if (enable) {
-		if (!info->rx_enabled)
-			rx_start(info);
-		else if (enable == 2) {
-			/* force hunt mode (write 1 to RCR[3]) */
-			wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
-		}
-	} else {
-		if (info->rx_enabled)
-			rx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/*
- *  wait for specified event to occur
- */
-static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr)
-{
- 	unsigned long flags;
-	int s;
-	int rc=0;
-	struct mgsl_icount cprev, cnow;
-	int events;
-	int mask;
-	struct	_input_signal_events oldsigs, newsigs;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (get_user(mask, mask_ptr))
-		return -EFAULT;
-
-	DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask));
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	/* return immediately if state matches requested events */
-	get_signals(info);
-	s = info->signals;
-
-	events = mask &
-		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
- 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
-		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
-		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
-	if (events) {
-		spin_unlock_irqrestore(&info->lock,flags);
-		goto exit;
-	}
-
-	/* save current irq counts */
-	cprev = info->icount;
-	oldsigs = info->input_signal_events;
-
-	/* enable hunt and idle irqs if needed */
-	if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
-		unsigned short val = rd_reg16(info, SCR);
-		if (!(val & IRQ_RXIDLE))
-			wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE));
-	}
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&info->event_wait_q, &wait);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get current irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		newsigs = info->input_signal_events;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
-		    newsigs.dsr_down == oldsigs.dsr_down &&
-		    newsigs.dcd_up   == oldsigs.dcd_up   &&
-		    newsigs.dcd_down == oldsigs.dcd_down &&
-		    newsigs.cts_up   == oldsigs.cts_up   &&
-		    newsigs.cts_down == oldsigs.cts_down &&
-		    newsigs.ri_up    == oldsigs.ri_up    &&
-		    newsigs.ri_down  == oldsigs.ri_down  &&
-		    cnow.exithunt    == cprev.exithunt   &&
-		    cnow.rxidle      == cprev.rxidle) {
-			rc = -EIO;
-			break;
-		}
-
-		events = mask &
-			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
-			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
-			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
-			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
-			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
-			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
-			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
-			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
-			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
-			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
-		if (events)
-			break;
-
-		cprev = cnow;
-		oldsigs = newsigs;
-	}
-
-	remove_wait_queue(&info->event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-
-
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!waitqueue_active(&info->event_wait_q)) {
-			/* disable enable exit hunt mode/idle rcvd IRQs */
-			wr_reg16(info, SCR,
-				(unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE));
-		}
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-exit:
-	if (rc == 0)
-		rc = put_user(events, mask_ptr);
-	return rc;
-}
-
-static int get_interface(struct slgt_info *info, int __user *if_mode)
-{
-	DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode));
-	if (put_user(info->if_mode, if_mode))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_interface(struct slgt_info *info, int if_mode)
-{
- 	unsigned long flags;
-	unsigned short val;
-
-	DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
-	spin_lock_irqsave(&info->lock,flags);
-	info->if_mode = if_mode;
-
-	msc_set_vcr(info);
-
-	/* TCR (tx control) 07  1=RTS driver control */
-	val = rd_reg16(info, TCR);
-	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
-		val |= BIT7;
-	else
-		val &= ~BIT7;
-	wr_reg16(info, TCR, val);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int get_xsync(struct slgt_info *info, int __user *xsync)
-{
-	DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync));
-	if (put_user(info->xsync, xsync))
-		return -EFAULT;
-	return 0;
-}
-
-/*
- * set extended sync pattern (1 to 4 bytes) for extended sync mode
- *
- * sync pattern is contained in least significant bytes of value
- * most significant byte of sync pattern is oldest (1st sent/detected)
- */
-static int set_xsync(struct slgt_info *info, int xsync)
-{
-	unsigned long flags;
-
-	DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync));
-	spin_lock_irqsave(&info->lock, flags);
-	info->xsync = xsync;
-	wr_reg32(info, XSR, xsync);
-	spin_unlock_irqrestore(&info->lock, flags);
-	return 0;
-}
-
-static int get_xctrl(struct slgt_info *info, int __user *xctrl)
-{
-	DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl));
-	if (put_user(info->xctrl, xctrl))
-		return -EFAULT;
-	return 0;
-}
-
-/*
- * set extended control options
- *
- * xctrl[31:19] reserved, must be zero
- * xctrl[18:17] extended sync pattern length in bytes
- *              00 = 1 byte  in xsr[7:0]
- *              01 = 2 bytes in xsr[15:0]
- *              10 = 3 bytes in xsr[23:0]
- *              11 = 4 bytes in xsr[31:0]
- * xctrl[16]    1 = enable terminal count, 0=disabled
- * xctrl[15:0]  receive terminal count for fixed length packets
- *              value is count minus one (0 = 1 byte packet)
- *              when terminal count is reached, receiver
- *              automatically returns to hunt mode and receive
- *              FIFO contents are flushed to DMA buffers with
- *              end of frame (EOF) status
- */
-static int set_xctrl(struct slgt_info *info, int xctrl)
-{
-	unsigned long flags;
-
-	DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl));
-	spin_lock_irqsave(&info->lock, flags);
-	info->xctrl = xctrl;
-	wr_reg32(info, XCR, xctrl);
-	spin_unlock_irqrestore(&info->lock, flags);
-	return 0;
-}
-
-/*
- * set general purpose IO pin state and direction
- *
- * user_gpio fields:
- * state   each bit indicates a pin state
- * smask   set bit indicates pin state to set
- * dir     each bit indicates a pin direction (0=input, 1=output)
- * dmask   set bit indicates pin direction to set
- */
-static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
-{
- 	unsigned long flags;
-	struct gpio_desc gpio;
-	__u32 data;
-
-	if (!info->gpio_present)
-		return -EINVAL;
-	if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
-		return -EFAULT;
-	DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n",
-		 info->device_name, gpio.state, gpio.smask,
-		 gpio.dir, gpio.dmask));
-
-	spin_lock_irqsave(&info->port_array[0]->lock, flags);
-	if (gpio.dmask) {
-		data = rd_reg32(info, IODR);
-		data |= gpio.dmask & gpio.dir;
-		data &= ~(gpio.dmask & ~gpio.dir);
-		wr_reg32(info, IODR, data);
-	}
-	if (gpio.smask) {
-		data = rd_reg32(info, IOVR);
-		data |= gpio.smask & gpio.state;
-		data &= ~(gpio.smask & ~gpio.state);
-		wr_reg32(info, IOVR, data);
-	}
-	spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
-
-	return 0;
-}
-
-/*
- * get general purpose IO pin state and direction
- */
-static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
-{
-	struct gpio_desc gpio;
-	if (!info->gpio_present)
-		return -EINVAL;
-	gpio.state = rd_reg32(info, IOVR);
-	gpio.smask = 0xffffffff;
-	gpio.dir   = rd_reg32(info, IODR);
-	gpio.dmask = 0xffffffff;
-	if (copy_to_user(user_gpio, &gpio, sizeof(gpio)))
-		return -EFAULT;
-	DBGINFO(("%s get_gpio state=%08x dir=%08x\n",
-		 info->device_name, gpio.state, gpio.dir));
-	return 0;
-}
-
-/*
- * conditional wait facility
- */
-static void init_cond_wait(struct cond_wait *w, unsigned int data)
-{
-	init_waitqueue_head(&w->q);
-	init_waitqueue_entry(&w->wait, current);
-	w->data = data;
-}
-
-static void add_cond_wait(struct cond_wait **head, struct cond_wait *w)
-{
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&w->q, &w->wait);
-	w->next = *head;
-	*head = w;
-}
-
-static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw)
-{
-	struct cond_wait *w, *prev;
-	remove_wait_queue(&cw->q, &cw->wait);
-	set_current_state(TASK_RUNNING);
-	for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) {
-		if (w == cw) {
-			if (prev != NULL)
-				prev->next = w->next;
-			else
-				*head = w->next;
-			break;
-		}
-	}
-}
-
-static void flush_cond_wait(struct cond_wait **head)
-{
-	while (*head != NULL) {
-		wake_up_interruptible(&(*head)->q);
-		*head = (*head)->next;
-	}
-}
-
-/*
- * wait for general purpose I/O pin(s) to enter specified state
- *
- * user_gpio fields:
- * state - bit indicates target pin state
- * smask - set bit indicates watched pin
- *
- * The wait ends when at least one watched pin enters the specified
- * state. When 0 (no error) is returned, user_gpio->state is set to the
- * state of all GPIO pins when the wait ends.
- *
- * Note: Each pin may be a dedicated input, dedicated output, or
- * configurable input/output. The number and configuration of pins
- * varies with the specific adapter model. Only input pins (dedicated
- * or configured) can be monitored with this function.
- */
-static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
-{
- 	unsigned long flags;
-	int rc = 0;
-	struct gpio_desc gpio;
-	struct cond_wait wait;
-	u32 state;
-
-	if (!info->gpio_present)
-		return -EINVAL;
-	if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
-		return -EFAULT;
-	DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n",
-		 info->device_name, gpio.state, gpio.smask));
-	/* ignore output pins identified by set IODR bit */
-	if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0)
-		return -EINVAL;
-	init_cond_wait(&wait, gpio.smask);
-
-	spin_lock_irqsave(&info->port_array[0]->lock, flags);
-	/* enable interrupts for watched pins */
-	wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
-	/* get current pin states */
-	state = rd_reg32(info, IOVR);
-
-	if (gpio.smask & ~(state ^ gpio.state)) {
-		/* already in target state */
-		gpio.state = state;
-	} else {
-		/* wait for target state */
-		add_cond_wait(&info->gpio_wait_q, &wait);
-		spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
-		schedule();
-		if (signal_pending(current))
-			rc = -ERESTARTSYS;
-		else
-			gpio.state = wait.data;
-		spin_lock_irqsave(&info->port_array[0]->lock, flags);
-		remove_cond_wait(&info->gpio_wait_q, &wait);
-	}
-
-	/* disable all GPIO interrupts if no waiting processes */
-	if (info->gpio_wait_q == NULL)
-		wr_reg32(info, IOER, 0);
-	spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
-
-	if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
-		rc = -EFAULT;
-	return rc;
-}
-
-static int modem_input_wait(struct slgt_info *info,int arg)
-{
- 	unsigned long flags;
-	int rc;
-	struct mgsl_icount cprev, cnow;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* save current irq counts */
-	spin_lock_irqsave(&info->lock,flags);
-	cprev = info->icount;
-	add_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get new irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-			rc = -EIO;
-			break;
-		}
-
-		/* check for change in caller specified modem input */
-		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
-		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
-		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
-		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
-			rc = 0;
-			break;
-		}
-
-		cprev = cnow;
-	}
-	remove_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-	return rc;
-}
-
-/*
- *  return state of serial control and status signals
- */
-static int tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned int result;
- 	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
-		((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
-		((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
-		((info->signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
-		((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
-		((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0);
-
-	DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result));
-	return result;
-}
-
-/*
- * set modem control signals (DTR/RTS)
- *
- * 	cmd	signal command: TIOCMBIS = set bit TIOCMBIC = clear bit
- *		TIOCMSET = set/clear signal values
- * 	value	bit mask for command
- */
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	struct slgt_info *info = tty->driver_data;
- 	unsigned long flags;
-
-	DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear));
-
-	if (set & TIOCM_RTS)
-		info->signals |= SerialSignal_RTS;
-	if (set & TIOCM_DTR)
-		info->signals |= SerialSignal_DTR;
-	if (clear & TIOCM_RTS)
-		info->signals &= ~SerialSignal_RTS;
-	if (clear & TIOCM_DTR)
-		info->signals &= ~SerialSignal_DTR;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	unsigned long flags;
-	struct slgt_info *info = container_of(port, struct slgt_info, port);
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return (info->signals & SerialSignal_DCD) ? 1 : 0;
-}
-
-static void dtr_rts(struct tty_port *port, int on)
-{
-	unsigned long flags;
-	struct slgt_info *info = container_of(port, struct slgt_info, port);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (on)
-		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-
-/*
- *  block current process until the device is ready to open
- */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-			   struct slgt_info *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	bool		do_clocal = false;
-	bool		extra_count = false;
-	unsigned long	flags;
-	int		cd;
-	struct tty_port *port = &info->port;
-
-	DBGINFO(("%s block_til_ready\n", tty->driver->name));
-
-	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-		/* nonblock mode is set or port is not enabled */
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = true;
-
-	/* Wait for carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-	port->blocked_open++;
-
-	while (1) {
-		if ((tty->termios->c_cflag & CBAUD))
-			tty_port_raise_dtr_rts(port);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
-			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-					-EAGAIN : -ERESTARTSYS;
-			break;
-		}
-
-		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
- 			break;
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-		DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-
-	if (extra_count)
-		port->count++;
-	port->blocked_open--;
-
-	if (!retval)
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-
-	DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
-	return retval;
-}
-
-static int alloc_tmp_rbuf(struct slgt_info *info)
-{
-	info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
-	if (info->tmp_rbuf == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-static void free_tmp_rbuf(struct slgt_info *info)
-{
-	kfree(info->tmp_rbuf);
-	info->tmp_rbuf = NULL;
-}
-
-/*
- * allocate DMA descriptor lists.
- */
-static int alloc_desc(struct slgt_info *info)
-{
-	unsigned int i;
-	unsigned int pbufs;
-
-	/* allocate memory to hold descriptor lists */
-	info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr);
-	if (info->bufs == NULL)
-		return -ENOMEM;
-
-	memset(info->bufs, 0, DESC_LIST_SIZE);
-
-	info->rbufs = (struct slgt_desc*)info->bufs;
-	info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count;
-
-	pbufs = (unsigned int)info->bufs_dma_addr;
-
-	/*
-	 * Build circular lists of descriptors
-	 */
-
-	for (i=0; i < info->rbuf_count; i++) {
-		/* physical address of this descriptor */
-		info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc));
-
-		/* physical address of next descriptor */
-		if (i == info->rbuf_count - 1)
-			info->rbufs[i].next = cpu_to_le32(pbufs);
-		else
-			info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc)));
-		set_desc_count(info->rbufs[i], DMABUFSIZE);
-	}
-
-	for (i=0; i < info->tbuf_count; i++) {
-		/* physical address of this descriptor */
-		info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc));
-
-		/* physical address of next descriptor */
-		if (i == info->tbuf_count - 1)
-			info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc));
-		else
-			info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc)));
-	}
-
-	return 0;
-}
-
-static void free_desc(struct slgt_info *info)
-{
-	if (info->bufs != NULL) {
-		pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr);
-		info->bufs  = NULL;
-		info->rbufs = NULL;
-		info->tbufs = NULL;
-	}
-}
-
-static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
-{
-	int i;
-	for (i=0; i < count; i++) {
-		if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL)
-			return -ENOMEM;
-		bufs[i].pbuf  = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr);
-	}
-	return 0;
-}
-
-static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
-{
-	int i;
-	for (i=0; i < count; i++) {
-		if (bufs[i].buf == NULL)
-			continue;
-		pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr);
-		bufs[i].buf = NULL;
-	}
-}
-
-static int alloc_dma_bufs(struct slgt_info *info)
-{
-	info->rbuf_count = 32;
-	info->tbuf_count = 32;
-
-	if (alloc_desc(info) < 0 ||
-	    alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 ||
-	    alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 ||
-	    alloc_tmp_rbuf(info) < 0) {
-		DBGERR(("%s DMA buffer alloc fail\n", info->device_name));
-		return -ENOMEM;
-	}
-	reset_rbufs(info);
-	return 0;
-}
-
-static void free_dma_bufs(struct slgt_info *info)
-{
-	if (info->bufs) {
-		free_bufs(info, info->rbufs, info->rbuf_count);
-		free_bufs(info, info->tbufs, info->tbuf_count);
-		free_desc(info);
-	}
-	free_tmp_rbuf(info);
-}
-
-static int claim_resources(struct slgt_info *info)
-{
-	if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) {
-		DBGERR(("%s reg addr conflict, addr=%08X\n",
-			info->device_name, info->phys_reg_addr));
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->reg_addr_requested = true;
-
-	info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE);
-	if (!info->reg_addr) {
-		DBGERR(("%s cant map device registers, addr=%08X\n",
-			info->device_name, info->phys_reg_addr));
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	return 0;
-
-errout:
-	release_resources(info);
-	return -ENODEV;
-}
-
-static void release_resources(struct slgt_info *info)
-{
-	if (info->irq_requested) {
-		free_irq(info->irq_level, info);
-		info->irq_requested = false;
-	}
-
-	if (info->reg_addr_requested) {
-		release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
-		info->reg_addr_requested = false;
-	}
-
-	if (info->reg_addr) {
-		iounmap(info->reg_addr);
-		info->reg_addr = NULL;
-	}
-}
-
-/* Add the specified device instance data structure to the
- * global linked list of devices and increment the device count.
- */
-static void add_device(struct slgt_info *info)
-{
-	char *devstr;
-
-	info->next_device = NULL;
-	info->line = slgt_device_count;
-	sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line);
-
-	if (info->line < MAX_DEVICES) {
-		if (maxframe[info->line])
-			info->max_frame_size = maxframe[info->line];
-	}
-
-	slgt_device_count++;
-
-	if (!slgt_device_list)
-		slgt_device_list = info;
-	else {
-		struct slgt_info *current_dev = slgt_device_list;
-		while(current_dev->next_device)
-			current_dev = current_dev->next_device;
-		current_dev->next_device = info;
-	}
-
-	if (info->max_frame_size < 4096)
-		info->max_frame_size = 4096;
-	else if (info->max_frame_size > 65535)
-		info->max_frame_size = 65535;
-
-	switch(info->pdev->device) {
-	case SYNCLINK_GT_DEVICE_ID:
-		devstr = "GT";
-		break;
-	case SYNCLINK_GT2_DEVICE_ID:
-		devstr = "GT2";
-		break;
-	case SYNCLINK_GT4_DEVICE_ID:
-		devstr = "GT4";
-		break;
-	case SYNCLINK_AC_DEVICE_ID:
-		devstr = "AC";
-		info->params.mode = MGSL_MODE_ASYNC;
-		break;
-	default:
-		devstr = "(unknown model)";
-	}
-	printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n",
-		devstr, info->device_name, info->phys_reg_addr,
-		info->irq_level, info->max_frame_size);
-
-#if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
-#endif
-}
-
-static const struct tty_port_operations slgt_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-/*
- *  allocate device instance structure, return NULL on failure
- */
-static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
-{
-	struct slgt_info *info;
-
-	info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL);
-
-	if (!info) {
-		DBGERR(("%s device alloc failed adapter=%d port=%d\n",
-			driver_name, adapter_num, port_num));
-	} else {
-		tty_port_init(&info->port);
-		info->port.ops = &slgt_port_ops;
-		info->magic = MGSL_MAGIC;
-		INIT_WORK(&info->task, bh_handler);
-		info->max_frame_size = 4096;
-		info->base_clock = 14745600;
-		info->rbuf_fill_level = DMABUFSIZE;
-		info->port.close_delay = 5*HZ/10;
-		info->port.closing_wait = 30*HZ;
-		init_waitqueue_head(&info->status_event_wait_q);
-		init_waitqueue_head(&info->event_wait_q);
-		spin_lock_init(&info->netlock);
-		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;
-		info->adapter_num = adapter_num;
-		info->port_num = port_num;
-
-		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
-		setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info);
-
-		/* Copy configuration info to device instance data */
-		info->pdev = pdev;
-		info->irq_level = pdev->irq;
-		info->phys_reg_addr = pci_resource_start(pdev,0);
-
-		info->bus_type = MGSL_BUS_TYPE_PCI;
-		info->irq_flags = IRQF_SHARED;
-
-		info->init_error = -1; /* assume error, set to 0 on successful init */
-	}
-
-	return info;
-}
-
-static void device_init(int adapter_num, struct pci_dev *pdev)
-{
-	struct slgt_info *port_array[SLGT_MAX_PORTS];
-	int i;
-	int port_count = 1;
-
-	if (pdev->device == SYNCLINK_GT2_DEVICE_ID)
-		port_count = 2;
-	else if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
-		port_count = 4;
-
-	/* allocate device instances for all ports */
-	for (i=0; i < port_count; ++i) {
-		port_array[i] = alloc_dev(adapter_num, i, pdev);
-		if (port_array[i] == NULL) {
-			for (--i; i >= 0; --i)
-				kfree(port_array[i]);
-			return;
-		}
-	}
-
-	/* give copy of port_array to all ports and add to device list  */
-	for (i=0; i < port_count; ++i) {
-		memcpy(port_array[i]->port_array, port_array, sizeof(port_array));
-		add_device(port_array[i]);
-		port_array[i]->port_count = port_count;
-		spin_lock_init(&port_array[i]->lock);
-	}
-
-	/* Allocate and claim adapter resources */
-	if (!claim_resources(port_array[0])) {
-
-		alloc_dma_bufs(port_array[0]);
-
-		/* copy resource information from first port to others */
-		for (i = 1; i < port_count; ++i) {
-			port_array[i]->irq_level = port_array[0]->irq_level;
-			port_array[i]->reg_addr  = port_array[0]->reg_addr;
-			alloc_dma_bufs(port_array[i]);
-		}
-
-		if (request_irq(port_array[0]->irq_level,
-					slgt_interrupt,
-					port_array[0]->irq_flags,
-					port_array[0]->device_name,
-					port_array[0]) < 0) {
-			DBGERR(("%s request_irq failed IRQ=%d\n",
-				port_array[0]->device_name,
-				port_array[0]->irq_level));
-		} else {
-			port_array[0]->irq_requested = true;
-			adapter_test(port_array[0]);
-			for (i=1 ; i < port_count ; i++) {
-				port_array[i]->init_error = port_array[0]->init_error;
-				port_array[i]->gpio_present = port_array[0]->gpio_present;
-			}
-		}
-	}
-
-	for (i=0; i < port_count; ++i)
-		tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
-}
-
-static int __devinit init_one(struct pci_dev *dev,
-			      const struct pci_device_id *ent)
-{
-	if (pci_enable_device(dev)) {
-		printk("error enabling pci device %p\n", dev);
-		return -EIO;
-	}
-	pci_set_master(dev);
-	device_init(slgt_device_count, dev);
-	return 0;
-}
-
-static void __devexit remove_one(struct pci_dev *dev)
-{
-}
-
-static const struct tty_operations ops = {
-	.open = open,
-	.close = close,
-	.write = write,
-	.put_char = put_char,
-	.flush_chars = flush_chars,
-	.write_room = write_room,
-	.chars_in_buffer = chars_in_buffer,
-	.flush_buffer = flush_buffer,
-	.ioctl = ioctl,
-	.compat_ioctl = slgt_compat_ioctl,
-	.throttle = throttle,
-	.unthrottle = unthrottle,
-	.send_xchar = send_xchar,
-	.break_ctl = set_break,
-	.wait_until_sent = wait_until_sent,
-	.set_termios = set_termios,
-	.stop = tx_hold,
-	.start = tx_release,
-	.hangup = hangup,
-	.tiocmget = tiocmget,
-	.tiocmset = tiocmset,
-	.get_icount = get_icount,
-	.proc_fops = &synclink_gt_proc_fops,
-};
-
-static void slgt_cleanup(void)
-{
-	int rc;
-	struct slgt_info *info;
-	struct slgt_info *tmp;
-
-	printk(KERN_INFO "unload %s\n", driver_name);
-
-	if (serial_driver) {
-		for (info=slgt_device_list ; info != NULL ; info=info->next_device)
-			tty_unregister_device(serial_driver, info->line);
-		if ((rc = tty_unregister_driver(serial_driver)))
-			DBGERR(("tty_unregister_driver error=%d\n", rc));
-		put_tty_driver(serial_driver);
-	}
-
-	/* reset devices */
-	info = slgt_device_list;
-	while(info) {
-		reset_port(info);
-		info = info->next_device;
-	}
-
-	/* release devices */
-	info = slgt_device_list;
-	while(info) {
-#if SYNCLINK_GENERIC_HDLC
-		hdlcdev_exit(info);
-#endif
-		free_dma_bufs(info);
-		free_tmp_rbuf(info);
-		if (info->port_num == 0)
-			release_resources(info);
-		tmp = info;
-		info = info->next_device;
-		kfree(tmp);
-	}
-
-	if (pci_registered)
-		pci_unregister_driver(&pci_driver);
-}
-
-/*
- *  Driver initialization entry point.
- */
-static int __init slgt_init(void)
-{
-	int rc;
-
-	printk(KERN_INFO "%s\n", driver_name);
-
-	serial_driver = alloc_tty_driver(MAX_DEVICES);
-	if (!serial_driver) {
-		printk("%s can't allocate tty driver\n", driver_name);
-		return -ENOMEM;
-	}
-
-	/* Initialize the tty_driver structure */
-
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = tty_driver_name;
-	serial_driver->name = tty_dev_prefix;
-	serial_driver->major = ttymajor;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->init_termios.c_ispeed = 9600;
-	serial_driver->init_termios.c_ospeed = 9600;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(serial_driver, &ops);
-	if ((rc = tty_register_driver(serial_driver)) < 0) {
-		DBGERR(("%s can't register serial driver\n", driver_name));
-		put_tty_driver(serial_driver);
-		serial_driver = NULL;
-		goto error;
-	}
-
-	printk(KERN_INFO "%s, tty major#%d\n",
-	       driver_name, serial_driver->major);
-
-	slgt_device_count = 0;
-	if ((rc = pci_register_driver(&pci_driver)) < 0) {
-		printk("%s pci_register_driver error=%d\n", driver_name, rc);
-		goto error;
-	}
-	pci_registered = true;
-
-	if (!slgt_device_list)
-		printk("%s no devices found\n",driver_name);
-
-	return 0;
-
-error:
-	slgt_cleanup();
-	return rc;
-}
-
-static void __exit slgt_exit(void)
-{
-	slgt_cleanup();
-}
-
-module_init(slgt_init);
-module_exit(slgt_exit);
-
-/*
- * register access routines
- */
-
-#define CALC_REGADDR() \
-	unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
-	if (addr >= 0x80) \
-		reg_addr += (info->port_num) * 32; \
-	else if (addr >= 0x40)	\
-		reg_addr += (info->port_num) * 16;
-
-static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
-{
-	CALC_REGADDR();
-	return readb((void __iomem *)reg_addr);
-}
-
-static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value)
-{
-	CALC_REGADDR();
-	writeb(value, (void __iomem *)reg_addr);
-}
-
-static __u16 rd_reg16(struct slgt_info *info, unsigned int addr)
-{
-	CALC_REGADDR();
-	return readw((void __iomem *)reg_addr);
-}
-
-static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value)
-{
-	CALC_REGADDR();
-	writew(value, (void __iomem *)reg_addr);
-}
-
-static __u32 rd_reg32(struct slgt_info *info, unsigned int addr)
-{
-	CALC_REGADDR();
-	return readl((void __iomem *)reg_addr);
-}
-
-static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value)
-{
-	CALC_REGADDR();
-	writel(value, (void __iomem *)reg_addr);
-}
-
-static void rdma_reset(struct slgt_info *info)
-{
-	unsigned int i;
-
-	/* set reset bit */
-	wr_reg32(info, RDCSR, BIT1);
-
-	/* wait for enable bit cleared */
-	for(i=0 ; i < 1000 ; i++)
-		if (!(rd_reg32(info, RDCSR) & BIT0))
-			break;
-}
-
-static void tdma_reset(struct slgt_info *info)
-{
-	unsigned int i;
-
-	/* set reset bit */
-	wr_reg32(info, TDCSR, BIT1);
-
-	/* wait for enable bit cleared */
-	for(i=0 ; i < 1000 ; i++)
-		if (!(rd_reg32(info, TDCSR) & BIT0))
-			break;
-}
-
-/*
- * enable internal loopback
- * TxCLK and RxCLK are generated from BRG
- * and TxD is looped back to RxD internally.
- */
-static void enable_loopback(struct slgt_info *info)
-{
-	/* SCR (serial control) BIT2=looopback enable */
-	wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2));
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		/* CCR (clock control)
-		 * 07..05  tx clock source (010 = BRG)
-		 * 04..02  rx clock source (010 = BRG)
-		 * 01      auxclk enable   (0 = disable)
-		 * 00      BRG enable      (1 = enable)
-		 *
-		 * 0100 1001
-		 */
-		wr_reg8(info, CCR, 0x49);
-
-		/* set speed if available, otherwise use default */
-		if (info->params.clock_speed)
-			set_rate(info, info->params.clock_speed);
-		else
-			set_rate(info, 3686400);
-	}
-}
-
-/*
- *  set baud rate generator to specified rate
- */
-static void set_rate(struct slgt_info *info, u32 rate)
-{
-	unsigned int div;
-	unsigned int osc = info->base_clock;
-
-	/* div = osc/rate - 1
-	 *
-	 * Round div up if osc/rate is not integer to
-	 * force to next slowest rate.
-	 */
-
-	if (rate) {
-		div = osc/rate;
-		if (!(osc % rate) && div)
-			div--;
-		wr_reg16(info, BDR, (unsigned short)div);
-	}
-}
-
-static void rx_stop(struct slgt_info *info)
-{
-	unsigned short val;
-
-	/* disable and reset receiver */
-	val = rd_reg16(info, RCR) & ~BIT1;          /* clear enable bit */
-	wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
-	wr_reg16(info, RCR, val);                  /* clear reset bit */
-
-	slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE);
-
-	/* clear pending rx interrupts */
-	wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER);
-
-	rdma_reset(info);
-
-	info->rx_enabled = false;
-	info->rx_restart = false;
-}
-
-static void rx_start(struct slgt_info *info)
-{
-	unsigned short val;
-
-	slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA);
-
-	/* clear pending rx overrun IRQ */
-	wr_reg16(info, SSR, IRQ_RXOVER);
-
-	/* reset and disable receiver */
-	val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
-	wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
-	wr_reg16(info, RCR, val);                  /* clear reset bit */
-
-	rdma_reset(info);
-	reset_rbufs(info);
-
-	if (info->rx_pio) {
-		/* rx request when rx FIFO not empty */
-		wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14));
-		slgt_irq_on(info, IRQ_RXDATA);
-		if (info->params.mode == MGSL_MODE_ASYNC) {
-			/* enable saving of rx status */
-			wr_reg32(info, RDCSR, BIT6);
-		}
-	} else {
-		/* rx request when rx FIFO half full */
-		wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14));
-		/* set 1st descriptor address */
-		wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
-
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			/* enable rx DMA and DMA interrupt */
-			wr_reg32(info, RDCSR, (BIT2 + BIT0));
-		} else {
-			/* enable saving of rx status, rx DMA and DMA interrupt */
-			wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
-		}
-	}
-
-	slgt_irq_on(info, IRQ_RXOVER);
-
-	/* enable receiver */
-	wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
-
-	info->rx_restart = false;
-	info->rx_enabled = true;
-}
-
-static void tx_start(struct slgt_info *info)
-{
-	if (!info->tx_enabled) {
-		wr_reg16(info, TCR,
-			 (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
-		info->tx_enabled = true;
-	}
-
-	if (desc_count(info->tbufs[info->tbuf_start])) {
-		info->drop_rts_on_tx_done = false;
-
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
-				get_signals(info);
-				if (!(info->signals & SerialSignal_RTS)) {
-					info->signals |= SerialSignal_RTS;
-					set_signals(info);
-					info->drop_rts_on_tx_done = true;
-				}
-			}
-
-			slgt_irq_off(info, IRQ_TXDATA);
-			slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE);
-			/* clear tx idle and underrun status bits */
-			wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
-		} else {
-			slgt_irq_off(info, IRQ_TXDATA);
-			slgt_irq_on(info, IRQ_TXIDLE);
-			/* clear tx idle status bit */
-			wr_reg16(info, SSR, IRQ_TXIDLE);
-		}
-		/* set 1st descriptor address and start DMA */
-		wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
-		wr_reg32(info, TDCSR, BIT2 + BIT0);
-		info->tx_active = true;
-	}
-}
-
-static void tx_stop(struct slgt_info *info)
-{
-	unsigned short val;
-
-	del_timer(&info->tx_timer);
-
-	tdma_reset(info);
-
-	/* reset and disable transmitter */
-	val = rd_reg16(info, TCR) & ~BIT1;          /* clear enable bit */
-	wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-
-	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
-
-	/* clear tx idle and underrun status bit */
-	wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
-
-	reset_tbufs(info);
-
-	info->tx_enabled = false;
-	info->tx_active = false;
-}
-
-static void reset_port(struct slgt_info *info)
-{
-	if (!info->reg_addr)
-		return;
-
-	tx_stop(info);
-	rx_stop(info);
-
-	info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-	set_signals(info);
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-}
-
-static void reset_adapter(struct slgt_info *info)
-{
-	int i;
-	for (i=0; i < info->port_count; ++i) {
-		if (info->port_array[i])
-			reset_port(info->port_array[i]);
-	}
-}
-
-static void async_mode(struct slgt_info *info)
-{
-  	unsigned short val;
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-	tx_stop(info);
-	rx_stop(info);
-
-	/* TCR (tx control)
-	 *
-	 * 15..13  mode, 010=async
-	 * 12..10  encoding, 000=NRZ
-	 * 09      parity enable
-	 * 08      1=odd parity, 0=even parity
-	 * 07      1=RTS driver control
-	 * 06      1=break enable
-	 * 05..04  character length
-	 *         00=5 bits
-	 *         01=6 bits
-	 *         10=7 bits
-	 *         11=8 bits
-	 * 03      0=1 stop bit, 1=2 stop bits
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-CTS enable
-	 */
-	val = 0x4000;
-
-	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
-		val |= BIT7;
-
-	if (info->params.parity != ASYNC_PARITY_NONE) {
-		val |= BIT9;
-		if (info->params.parity == ASYNC_PARITY_ODD)
-			val |= BIT8;
-	}
-
-	switch (info->params.data_bits)
-	{
-	case 6: val |= BIT4; break;
-	case 7: val |= BIT5; break;
-	case 8: val |= BIT5 + BIT4; break;
-	}
-
-	if (info->params.stop_bits != 1)
-		val |= BIT3;
-
-	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
-		val |= BIT0;
-
-	wr_reg16(info, TCR, val);
-
-	/* RCR (rx control)
-	 *
-	 * 15..13  mode, 010=async
-	 * 12..10  encoding, 000=NRZ
-	 * 09      parity enable
-	 * 08      1=odd parity, 0=even parity
-	 * 07..06  reserved, must be 0
-	 * 05..04  character length
-	 *         00=5 bits
-	 *         01=6 bits
-	 *         10=7 bits
-	 *         11=8 bits
-	 * 03      reserved, must be zero
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-DCD enable
-	 */
-	val = 0x4000;
-
-	if (info->params.parity != ASYNC_PARITY_NONE) {
-		val |= BIT9;
-		if (info->params.parity == ASYNC_PARITY_ODD)
-			val |= BIT8;
-	}
-
-	switch (info->params.data_bits)
-	{
-	case 6: val |= BIT4; break;
-	case 7: val |= BIT5; break;
-	case 8: val |= BIT5 + BIT4; break;
-	}
-
-	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
-		val |= BIT0;
-
-	wr_reg16(info, RCR, val);
-
-	/* CCR (clock control)
-	 *
-	 * 07..05  011 = tx clock source is BRG/16
-	 * 04..02  010 = rx clock source is BRG
-	 * 01      0 = auxclk disabled
-	 * 00      1 = BRG enabled
-	 *
-	 * 0110 1001
-	 */
-	wr_reg8(info, CCR, 0x69);
-
-	msc_set_vcr(info);
-
-	/* SCR (serial control)
-	 *
-	 * 15  1=tx req on FIFO half empty
-	 * 14  1=rx req on FIFO half full
-	 * 13  tx data  IRQ enable
-	 * 12  tx idle  IRQ enable
-	 * 11  rx break on IRQ enable
-	 * 10  rx data  IRQ enable
-	 * 09  rx break off IRQ enable
-	 * 08  overrun  IRQ enable
-	 * 07  DSR      IRQ enable
-	 * 06  CTS      IRQ enable
-	 * 05  DCD      IRQ enable
-	 * 04  RI       IRQ enable
-	 * 03  0=16x sampling, 1=8x sampling
-	 * 02  1=txd->rxd internal loopback enable
-	 * 01  reserved, must be zero
-	 * 00  1=master IRQ enable
-	 */
-	val = BIT15 + BIT14 + BIT0;
-	/* JCR[8] : 1 = x8 async mode feature available */
-	if ((rd_reg32(info, JCR) & BIT8) && info->params.data_rate &&
-	    ((info->base_clock < (info->params.data_rate * 16)) ||
-	     (info->base_clock % (info->params.data_rate * 16)))) {
-		/* use 8x sampling */
-		val |= BIT3;
-		set_rate(info, info->params.data_rate * 8);
-	} else {
-		/* use 16x sampling */
-		set_rate(info, info->params.data_rate * 16);
-	}
-	wr_reg16(info, SCR, val);
-
-	slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER);
-
-	if (info->params.loopback)
-		enable_loopback(info);
-}
-
-static void sync_mode(struct slgt_info *info)
-{
-	unsigned short val;
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-	tx_stop(info);
-	rx_stop(info);
-
-	/* TCR (tx control)
-	 *
-	 * 15..13  mode
-	 *         000=HDLC/SDLC
-	 *         001=raw bit synchronous
-	 *         010=asynchronous/isochronous
-	 *         011=monosync byte synchronous
-	 *         100=bisync byte synchronous
-	 *         101=xsync byte synchronous
-	 * 12..10  encoding
-	 * 09      CRC enable
-	 * 08      CRC32
-	 * 07      1=RTS driver control
-	 * 06      preamble enable
-	 * 05..04  preamble length
-	 * 03      share open/close flag
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-CTS enable
-	 */
-	val = BIT2;
-
-	switch(info->params.mode) {
-	case MGSL_MODE_XSYNC:
-		val |= BIT15 + BIT13;
-		break;
-	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
-	case MGSL_MODE_BISYNC:   val |= BIT15; break;
-	case MGSL_MODE_RAW:      val |= BIT13; break;
-	}
-	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
-		val |= BIT7;
-
-	switch(info->params.encoding)
-	{
-	case HDLC_ENCODING_NRZB:          val |= BIT10; break;
-	case HDLC_ENCODING_NRZI_MARK:     val |= BIT11; break;
-	case HDLC_ENCODING_NRZI:          val |= BIT11 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_MARK:  val |= BIT12; break;
-	case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
-	}
-
-	switch (info->params.crc_type & HDLC_CRC_MASK)
-	{
-	case HDLC_CRC_16_CCITT: val |= BIT9; break;
-	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
-	}
-
-	if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
-		val |= BIT6;
-
-	switch (info->params.preamble_length)
-	{
-	case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break;
-	case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break;
-	case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break;
-	}
-
-	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
-		val |= BIT0;
-
-	wr_reg16(info, TCR, val);
-
-	/* TPR (transmit preamble) */
-
-	switch (info->params.preamble)
-	{
-	case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break;
-	case HDLC_PREAMBLE_PATTERN_ONES:  val = 0xff; break;
-	case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break;
-	case HDLC_PREAMBLE_PATTERN_10:    val = 0x55; break;
-	case HDLC_PREAMBLE_PATTERN_01:    val = 0xaa; break;
-	default:                          val = 0x7e; break;
-	}
-	wr_reg8(info, TPR, (unsigned char)val);
-
-	/* RCR (rx control)
-	 *
-	 * 15..13  mode
-	 *         000=HDLC/SDLC
-	 *         001=raw bit synchronous
-	 *         010=asynchronous/isochronous
-	 *         011=monosync byte synchronous
-	 *         100=bisync byte synchronous
-	 *         101=xsync byte synchronous
-	 * 12..10  encoding
-	 * 09      CRC enable
-	 * 08      CRC32
-	 * 07..03  reserved, must be 0
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-DCD enable
-	 */
-	val = 0;
-
-	switch(info->params.mode) {
-	case MGSL_MODE_XSYNC:
-		val |= BIT15 + BIT13;
-		break;
-	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
-	case MGSL_MODE_BISYNC:   val |= BIT15; break;
-	case MGSL_MODE_RAW:      val |= BIT13; break;
-	}
-
-	switch(info->params.encoding)
-	{
-	case HDLC_ENCODING_NRZB:          val |= BIT10; break;
-	case HDLC_ENCODING_NRZI_MARK:     val |= BIT11; break;
-	case HDLC_ENCODING_NRZI:          val |= BIT11 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_MARK:  val |= BIT12; break;
-	case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
-	}
-
-	switch (info->params.crc_type & HDLC_CRC_MASK)
-	{
-	case HDLC_CRC_16_CCITT: val |= BIT9; break;
-	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
-	}
-
-	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
-		val |= BIT0;
-
-	wr_reg16(info, RCR, val);
-
-	/* CCR (clock control)
-	 *
-	 * 07..05  tx clock source
-	 * 04..02  rx clock source
-	 * 01      auxclk enable
-	 * 00      BRG enable
-	 */
-	val = 0;
-
-	if (info->params.flags & HDLC_FLAG_TXC_BRG)
-	{
-		// when RxC source is DPLL, BRG generates 16X DPLL
-		// reference clock, so take TxC from BRG/16 to get
-		// transmit clock at actual data rate
-		if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-			val |= BIT6 + BIT5;	/* 011, txclk = BRG/16 */
-		else
-			val |= BIT6;	/* 010, txclk = BRG */
-	}
-	else if (info->params.flags & HDLC_FLAG_TXC_DPLL)
-		val |= BIT7;	/* 100, txclk = DPLL Input */
-	else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN)
-		val |= BIT5;	/* 001, txclk = RXC Input */
-
-	if (info->params.flags & HDLC_FLAG_RXC_BRG)
-		val |= BIT3;	/* 010, rxclk = BRG */
-	else if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-		val |= BIT4;	/* 100, rxclk = DPLL */
-	else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN)
-		val |= BIT2;	/* 001, rxclk = TXC Input */
-
-	if (info->params.clock_speed)
-		val |= BIT1 + BIT0;
-
-	wr_reg8(info, CCR, (unsigned char)val);
-
-	if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL))
-	{
-		// program DPLL mode
-		switch(info->params.encoding)
-		{
-		case HDLC_ENCODING_BIPHASE_MARK:
-		case HDLC_ENCODING_BIPHASE_SPACE:
-			val = BIT7; break;
-		case HDLC_ENCODING_BIPHASE_LEVEL:
-		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL:
-			val = BIT7 + BIT6; break;
-		default: val = BIT6;	// NRZ encodings
-		}
-		wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val));
-
-		// DPLL requires a 16X reference clock from BRG
-		set_rate(info, info->params.clock_speed * 16);
-	}
-	else
-		set_rate(info, info->params.clock_speed);
-
-	tx_set_idle(info);
-
-	msc_set_vcr(info);
-
-	/* SCR (serial control)
-	 *
-	 * 15  1=tx req on FIFO half empty
-	 * 14  1=rx req on FIFO half full
-	 * 13  tx data  IRQ enable
-	 * 12  tx idle  IRQ enable
-	 * 11  underrun IRQ enable
-	 * 10  rx data  IRQ enable
-	 * 09  rx idle  IRQ enable
-	 * 08  overrun  IRQ enable
-	 * 07  DSR      IRQ enable
-	 * 06  CTS      IRQ enable
-	 * 05  DCD      IRQ enable
-	 * 04  RI       IRQ enable
-	 * 03  reserved, must be zero
-	 * 02  1=txd->rxd internal loopback enable
-	 * 01  reserved, must be zero
-	 * 00  1=master IRQ enable
-	 */
-	wr_reg16(info, SCR, BIT15 + BIT14 + BIT0);
-
-	if (info->params.loopback)
-		enable_loopback(info);
-}
-
-/*
- *  set transmit idle mode
- */
-static void tx_set_idle(struct slgt_info *info)
-{
-	unsigned char val;
-	unsigned short tcr;
-
-	/* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits
-	 * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits
-	 */
-	tcr = rd_reg16(info, TCR);
-	if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) {
-		/* disable preamble, set idle size to 16 bits */
-		tcr = (tcr & ~(BIT6 + BIT5)) | BIT4;
-		/* MSB of 16 bit idle specified in tx preamble register (TPR) */
-		wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff));
-	} else if (!(tcr & BIT6)) {
-		/* preamble is disabled, set idle size to 8 bits */
-		tcr &= ~(BIT5 + BIT4);
-	}
-	wr_reg16(info, TCR, tcr);
-
-	if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) {
-		/* LSB of custom tx idle specified in tx idle register */
-		val = (unsigned char)(info->idle_mode & 0xff);
-	} else {
-		/* standard 8 bit idle patterns */
-		switch(info->idle_mode)
-		{
-		case HDLC_TXIDLE_FLAGS:          val = 0x7e; break;
-		case HDLC_TXIDLE_ALT_ZEROS_ONES:
-		case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
-		case HDLC_TXIDLE_ZEROS:
-		case HDLC_TXIDLE_SPACE:          val = 0x00; break;
-		default:                         val = 0xff;
-		}
-	}
-
-	wr_reg8(info, TIR, val);
-}
-
-/*
- * get state of V24 status (input) signals
- */
-static void get_signals(struct slgt_info *info)
-{
-	unsigned short status = rd_reg16(info, SSR);
-
-	/* clear all serial signals except DTR and RTS */
-	info->signals &= SerialSignal_DTR + SerialSignal_RTS;
-
-	if (status & BIT3)
-		info->signals |= SerialSignal_DSR;
-	if (status & BIT2)
-		info->signals |= SerialSignal_CTS;
-	if (status & BIT1)
-		info->signals |= SerialSignal_DCD;
-	if (status & BIT0)
-		info->signals |= SerialSignal_RI;
-}
-
-/*
- * set V.24 Control Register based on current configuration
- */
-static void msc_set_vcr(struct slgt_info *info)
-{
-	unsigned char val = 0;
-
-	/* VCR (V.24 control)
-	 *
-	 * 07..04  serial IF select
-	 * 03      DTR
-	 * 02      RTS
-	 * 01      LL
-	 * 00      RL
-	 */
-
-	switch(info->if_mode & MGSL_INTERFACE_MASK)
-	{
-	case MGSL_INTERFACE_RS232:
-		val |= BIT5; /* 0010 */
-		break;
-	case MGSL_INTERFACE_V35:
-		val |= BIT7 + BIT6 + BIT5; /* 1110 */
-		break;
-	case MGSL_INTERFACE_RS422:
-		val |= BIT6; /* 0100 */
-		break;
-	}
-
-	if (info->if_mode & MGSL_INTERFACE_MSB_FIRST)
-		val |= BIT4;
-	if (info->signals & SerialSignal_DTR)
-		val |= BIT3;
-	if (info->signals & SerialSignal_RTS)
-		val |= BIT2;
-	if (info->if_mode & MGSL_INTERFACE_LL)
-		val |= BIT1;
-	if (info->if_mode & MGSL_INTERFACE_RL)
-		val |= BIT0;
-	wr_reg8(info, VCR, val);
-}
-
-/*
- * set state of V24 control (output) signals
- */
-static void set_signals(struct slgt_info *info)
-{
-	unsigned char val = rd_reg8(info, VCR);
-	if (info->signals & SerialSignal_DTR)
-		val |= BIT3;
-	else
-		val &= ~BIT3;
-	if (info->signals & SerialSignal_RTS)
-		val |= BIT2;
-	else
-		val &= ~BIT2;
-	wr_reg8(info, VCR, val);
-}
-
-/*
- * free range of receive DMA buffers (i to last)
- */
-static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last)
-{
-	int done = 0;
-
-	while(!done) {
-		/* reset current buffer for reuse */
-		info->rbufs[i].status = 0;
-		set_desc_count(info->rbufs[i], info->rbuf_fill_level);
-		if (i == last)
-			done = 1;
-		if (++i == info->rbuf_count)
-			i = 0;
-	}
-	info->rbuf_current = i;
-}
-
-/*
- * mark all receive DMA buffers as free
- */
-static void reset_rbufs(struct slgt_info *info)
-{
-	free_rbufs(info, 0, info->rbuf_count - 1);
-	info->rbuf_fill_index = 0;
-	info->rbuf_fill_count = 0;
-}
-
-/*
- * pass receive HDLC frame to upper layer
- *
- * return true if frame available, otherwise false
- */
-static bool rx_get_frame(struct slgt_info *info)
-{
-	unsigned int start, end;
-	unsigned short status;
-	unsigned int framesize = 0;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-	unsigned char addr_field = 0xff;
-	unsigned int crc_size = 0;
-
-	switch (info->params.crc_type & HDLC_CRC_MASK) {
-	case HDLC_CRC_16_CCITT: crc_size = 2; break;
-	case HDLC_CRC_32_CCITT: crc_size = 4; break;
-	}
-
-check_again:
-
-	framesize = 0;
-	addr_field = 0xff;
-	start = end = info->rbuf_current;
-
-	for (;;) {
-		if (!desc_complete(info->rbufs[end]))
-			goto cleanup;
-
-		if (framesize == 0 && info->params.addr_filter != 0xff)
-			addr_field = info->rbufs[end].buf[0];
-
-		framesize += desc_count(info->rbufs[end]);
-
-		if (desc_eof(info->rbufs[end]))
-			break;
-
-		if (++end == info->rbuf_count)
-			end = 0;
-
-		if (end == info->rbuf_current) {
-			if (info->rx_enabled){
-				spin_lock_irqsave(&info->lock,flags);
-				rx_start(info);
-				spin_unlock_irqrestore(&info->lock,flags);
-			}
-			goto cleanup;
-		}
-	}
-
-	/* status
-	 *
-	 * 15      buffer complete
-	 * 14..06  reserved
-	 * 05..04  residue
-	 * 02      eof (end of frame)
-	 * 01      CRC error
-	 * 00      abort
-	 */
-	status = desc_status(info->rbufs[end]);
-
-	/* ignore CRC bit if not using CRC (bit is undefined) */
-	if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE)
-		status &= ~BIT1;
-
-	if (framesize == 0 ||
-		 (addr_field != 0xff && addr_field != info->params.addr_filter)) {
-		free_rbufs(info, start, end);
-		goto check_again;
-	}
-
-	if (framesize < (2 + crc_size) || status & BIT0) {
-		info->icount.rxshort++;
-		framesize = 0;
-	} else if (status & BIT1) {
-		info->icount.rxcrc++;
-		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX))
-			framesize = 0;
-	}
-
-#if SYNCLINK_GENERIC_HDLC
-	if (framesize == 0) {
-		info->netdev->stats.rx_errors++;
-		info->netdev->stats.rx_frame_errors++;
-	}
-#endif
-
-	DBGBH(("%s rx frame status=%04X size=%d\n",
-		info->device_name, status, framesize));
-	DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
-
-	if (framesize) {
-		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
-			framesize -= crc_size;
-			crc_size = 0;
-		}
-
-		if (framesize > info->max_frame_size + crc_size)
-			info->icount.rxlong++;
-		else {
-			/* copy dma buffer(s) to contiguous temp buffer */
-			int copy_count = framesize;
-			int i = start;
-			unsigned char *p = info->tmp_rbuf;
-			info->tmp_rbuf_count = framesize;
-
-			info->icount.rxok++;
-
-			while(copy_count) {
-				int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
-				memcpy(p, info->rbufs[i].buf, partial_count);
-				p += partial_count;
-				copy_count -= partial_count;
-				if (++i == info->rbuf_count)
-					i = 0;
-			}
-
-			if (info->params.crc_type & HDLC_CRC_RETURN_EX) {
-				*p = (status & BIT1) ? RX_CRC_ERROR : RX_OK;
-				framesize++;
-			}
-
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount)
-				hdlcdev_rx(info,info->tmp_rbuf, framesize);
-			else
-#endif
-				ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize);
-		}
-	}
-	free_rbufs(info, start, end);
-	return true;
-
-cleanup:
-	return false;
-}
-
-/*
- * pass receive buffer (RAW synchronous mode) to tty layer
- * return true if buffer available, otherwise false
- */
-static bool rx_get_buf(struct slgt_info *info)
-{
-	unsigned int i = info->rbuf_current;
-	unsigned int count;
-
-	if (!desc_complete(info->rbufs[i]))
-		return false;
-	count = desc_count(info->rbufs[i]);
-	switch(info->params.mode) {
-	case MGSL_MODE_MONOSYNC:
-	case MGSL_MODE_BISYNC:
-	case MGSL_MODE_XSYNC:
-		/* ignore residue in byte synchronous modes */
-		if (desc_residue(info->rbufs[i]))
-			count--;
-		break;
-	}
-	DBGDATA(info, info->rbufs[i].buf, count, "rx");
-	DBGINFO(("rx_get_buf size=%d\n", count));
-	if (count)
-		ldisc_receive_buf(info->port.tty, info->rbufs[i].buf,
-				  info->flag_buf, count);
-	free_rbufs(info, i, i);
-	return true;
-}
-
-static void reset_tbufs(struct slgt_info *info)
-{
-	unsigned int i;
-	info->tbuf_current = 0;
-	for (i=0 ; i < info->tbuf_count ; i++) {
-		info->tbufs[i].status = 0;
-		info->tbufs[i].count  = 0;
-	}
-}
-
-/*
- * return number of free transmit DMA buffers
- */
-static unsigned int free_tbuf_count(struct slgt_info *info)
-{
-	unsigned int count = 0;
-	unsigned int i = info->tbuf_current;
-
-	do
-	{
-		if (desc_count(info->tbufs[i]))
-			break; /* buffer in use */
-		++count;
-		if (++i == info->tbuf_count)
-			i=0;
-	} while (i != info->tbuf_current);
-
-	/* if tx DMA active, last zero count buffer is in use */
-	if (count && (rd_reg32(info, TDCSR) & BIT0))
-		--count;
-
-	return count;
-}
-
-/*
- * return number of bytes in unsent transmit DMA buffers
- * and the serial controller tx FIFO
- */
-static unsigned int tbuf_bytes(struct slgt_info *info)
-{
-	unsigned int total_count = 0;
-	unsigned int i = info->tbuf_current;
-	unsigned int reg_value;
-	unsigned int count;
-	unsigned int active_buf_count = 0;
-
-	/*
-	 * Add descriptor counts for all tx DMA buffers.
-	 * If count is zero (cleared by DMA controller after read),
-	 * the buffer is complete or is actively being read from.
-	 *
-	 * Record buf_count of last buffer with zero count starting
-	 * from current ring position. buf_count is mirror
-	 * copy of count and is not cleared by serial controller.
-	 * If DMA controller is active, that buffer is actively
-	 * being read so add to total.
-	 */
-	do {
-		count = desc_count(info->tbufs[i]);
-		if (count)
-			total_count += count;
-		else if (!total_count)
-			active_buf_count = info->tbufs[i].buf_count;
-		if (++i == info->tbuf_count)
-			i = 0;
-	} while (i != info->tbuf_current);
-
-	/* read tx DMA status register */
-	reg_value = rd_reg32(info, TDCSR);
-
-	/* if tx DMA active, last zero count buffer is in use */
-	if (reg_value & BIT0)
-		total_count += active_buf_count;
-
-	/* add tx FIFO count = reg_value[15..8] */
-	total_count += (reg_value >> 8) & 0xff;
-
-	/* if transmitter active add one byte for shift register */
-	if (info->tx_active)
-		total_count++;
-
-	return total_count;
-}
-
-/*
- * load data into transmit DMA buffer ring and start transmitter if needed
- * return true if data accepted, otherwise false (buffers full)
- */
-static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size)
-{
-	unsigned short count;
-	unsigned int i;
-	struct slgt_desc *d;
-
-	/* check required buffer space */
-	if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info))
-		return false;
-
-	DBGDATA(info, buf, size, "tx");
-
-	/*
-	 * copy data to one or more DMA buffers in circular ring
-	 * tbuf_start   = first buffer for this data
-	 * tbuf_current = next free buffer
-	 *
-	 * Copy all data before making data visible to DMA controller by
-	 * setting descriptor count of the first buffer.
-	 * This prevents an active DMA controller from reading the first DMA
-	 * buffers of a frame and stopping before the final buffers are filled.
-	 */
-
-	info->tbuf_start = i = info->tbuf_current;
-
-	while (size) {
-		d = &info->tbufs[i];
-
-		count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
-		memcpy(d->buf, buf, count);
-
-		size -= count;
-		buf  += count;
-
-		/*
-		 * set EOF bit for last buffer of HDLC frame or
-		 * for every buffer in raw mode
-		 */
-		if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
-		    info->params.mode == MGSL_MODE_RAW)
-			set_desc_eof(*d, 1);
-		else
-			set_desc_eof(*d, 0);
-
-		/* set descriptor count for all but first buffer */
-		if (i != info->tbuf_start)
-			set_desc_count(*d, count);
-		d->buf_count = count;
-
-		if (++i == info->tbuf_count)
-			i = 0;
-	}
-
-	info->tbuf_current = i;
-
-	/* set first buffer count to make new data visible to DMA controller */
-	d = &info->tbufs[info->tbuf_start];
-	set_desc_count(*d, d->buf_count);
-
-	/* start transmitter if needed and update transmit timeout */
-	if (!info->tx_active)
-		tx_start(info);
-	update_tx_timer(info);
-
-	return true;
-}
-
-static int register_test(struct slgt_info *info)
-{
-	static unsigned short patterns[] =
-		{0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696};
-	static unsigned int count = ARRAY_SIZE(patterns);
-	unsigned int i;
-	int rc = 0;
-
-	for (i=0 ; i < count ; i++) {
-		wr_reg16(info, TIR, patterns[i]);
-		wr_reg16(info, BDR, patterns[(i+1)%count]);
-		if ((rd_reg16(info, TIR) != patterns[i]) ||
-		    (rd_reg16(info, BDR) != patterns[(i+1)%count])) {
-			rc = -ENODEV;
-			break;
-		}
-	}
-	info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0;
-	info->init_error = rc ? 0 : DiagStatus_AddressFailure;
-	return rc;
-}
-
-static int irq_test(struct slgt_info *info)
-{
-	unsigned long timeout;
-	unsigned long flags;
-	struct tty_struct *oldtty = info->port.tty;
-	u32 speed = info->params.data_rate;
-
-	info->params.data_rate = 921600;
-	info->port.tty = NULL;
-
-	spin_lock_irqsave(&info->lock, flags);
-	async_mode(info);
-	slgt_irq_on(info, IRQ_TXIDLE);
-
-	/* enable transmitter */
-	wr_reg16(info, TCR,
-		(unsigned short)(rd_reg16(info, TCR) | BIT1));
-
-	/* write one byte and wait for tx idle */
-	wr_reg16(info, TDR, 0);
-
-	/* assume failure */
-	info->init_error = DiagStatus_IrqFailure;
-	info->irq_occurred = false;
-
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	timeout=100;
-	while(timeout-- && !info->irq_occurred)
-		msleep_interruptible(10);
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	info->params.data_rate = speed;
-	info->port.tty = oldtty;
-
-	info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure;
-	return info->irq_occurred ? 0 : -ENODEV;
-}
-
-static int loopback_test_rx(struct slgt_info *info)
-{
-	unsigned char *src, *dest;
-	int count;
-
-	if (desc_complete(info->rbufs[0])) {
-		count = desc_count(info->rbufs[0]);
-		src   = info->rbufs[0].buf;
-		dest  = info->tmp_rbuf;
-
-		for( ; count ; count-=2, src+=2) {
-			/* src=data byte (src+1)=status byte */
-			if (!(*(src+1) & (BIT9 + BIT8))) {
-				*dest = *src;
-				dest++;
-				info->tmp_rbuf_count++;
-			}
-		}
-		DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx");
-		return 1;
-	}
-	return 0;
-}
-
-static int loopback_test(struct slgt_info *info)
-{
-#define TESTFRAMESIZE 20
-
-	unsigned long timeout;
-	u16 count = TESTFRAMESIZE;
-	unsigned char buf[TESTFRAMESIZE];
-	int rc = -ENODEV;
-	unsigned long flags;
-
-	struct tty_struct *oldtty = info->port.tty;
-	MGSL_PARAMS params;
-
-	memcpy(&params, &info->params, sizeof(params));
-
-	info->params.mode = MGSL_MODE_ASYNC;
-	info->params.data_rate = 921600;
-	info->params.loopback = 1;
-	info->port.tty = NULL;
-
-	/* build and send transmit frame */
-	for (count = 0; count < TESTFRAMESIZE; ++count)
-		buf[count] = (unsigned char)count;
-
-	info->tmp_rbuf_count = 0;
-	memset(info->tmp_rbuf, 0, TESTFRAMESIZE);
-
-	/* program hardware for HDLC and enabled receiver */
-	spin_lock_irqsave(&info->lock,flags);
-	async_mode(info);
-	rx_start(info);
-	tx_load(info, buf, count);
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/* wait for receive complete */
-	for (timeout = 100; timeout; --timeout) {
-		msleep_interruptible(10);
-		if (loopback_test_rx(info)) {
-			rc = 0;
-			break;
-		}
-	}
-
-	/* verify received frame length and contents */
-	if (!rc && (info->tmp_rbuf_count != count ||
-		  memcmp(buf, info->tmp_rbuf, count))) {
-		rc = -ENODEV;
-	}
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_adapter(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	memcpy(&info->params, &params, sizeof(info->params));
-	info->port.tty = oldtty;
-
-	info->init_error = rc ? DiagStatus_DmaFailure : 0;
-	return rc;
-}
-
-static int adapter_test(struct slgt_info *info)
-{
-	DBGINFO(("testing %s\n", info->device_name));
-	if (register_test(info) < 0) {
-		printk("register test failure %s addr=%08X\n",
-			info->device_name, info->phys_reg_addr);
-	} else if (irq_test(info) < 0) {
-		printk("IRQ test failure %s IRQ=%d\n",
-			info->device_name, info->irq_level);
-	} else if (loopback_test(info) < 0) {
-		printk("loopback test failure %s\n", info->device_name);
-	}
-	return info->init_error;
-}
-
-/*
- * transmit timeout handler
- */
-static void tx_timeout(unsigned long context)
-{
-	struct slgt_info *info = (struct slgt_info*)context;
-	unsigned long flags;
-
-	DBGINFO(("%s tx_timeout\n", info->device_name));
-	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
-		info->icount.txtimeout++;
-	}
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else
-#endif
-		bh_transmit(info);
-}
-
-/*
- * receive buffer polling timer
- */
-static void rx_timeout(unsigned long context)
-{
-	struct slgt_info *info = (struct slgt_info*)context;
-	unsigned long flags;
-
-	DBGINFO(("%s rx_timeout\n", info->device_name));
-	spin_lock_irqsave(&info->lock, flags);
-	info->pending_bh |= BH_RECEIVE;
-	spin_unlock_irqrestore(&info->lock, flags);
-	bh_handler(&info->task);
-}
-
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
deleted file mode 100644
index 2f9eb4b..0000000
--- a/drivers/char/synclinkmp.c
+++ /dev/null
@@ -1,5601 +0,0 @@
-/*
- * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $
- *
- * Device driver for Microgate SyncLink Multiport
- * high speed multiprotocol serial adapter.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * Derived from serial.c written by Theodore Ts'o and Linus Torvalds
- * This code is released under the GNU General Public License (GPL)
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
-#if defined(__i386__)
-#  define BREAKPOINT() asm("   int $3");
-#else
-#  define BREAKPOINT() { }
-#endif
-
-#define MAX_DEVICES 12
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <linux/bitops.h>
-#include <asm/types.h>
-#include <linux/termios.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/synclink.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-#define GET_USER(error,value,addr) error = get_user(value,addr)
-#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
-#define PUT_USER(error,value,addr) error = put_user(value,addr)
-#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
-
-#include <asm/uaccess.h>
-
-static MGSL_PARAMS default_params = {
-	MGSL_MODE_HDLC,			/* unsigned long mode */
-	0,				/* unsigned char loopback; */
-	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */
-	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */
-	0,				/* unsigned long clock_speed; */
-	0xff,				/* unsigned char addr_filter; */
-	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */
-	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */
-	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */
-	9600,				/* unsigned long data_rate; */
-	8,				/* unsigned char data_bits; */
-	1,				/* unsigned char stop_bits; */
-	ASYNC_PARITY_NONE		/* unsigned char parity; */
-};
-
-/* size in bytes of DMA data buffers */
-#define SCABUFSIZE 	1024
-#define SCA_MEM_SIZE	0x40000
-#define SCA_BASE_SIZE   512
-#define SCA_REG_SIZE    16
-#define SCA_MAX_PORTS   4
-#define SCAMAXDESC 	128
-
-#define	BUFFERLISTSIZE	4096
-
-/* SCA-I style DMA buffer descriptor */
-typedef struct _SCADESC
-{
-	u16	next;		/* lower l6 bits of next descriptor addr */
-	u16	buf_ptr;	/* lower 16 bits of buffer addr */
-	u8	buf_base;	/* upper 8 bits of buffer addr */
-	u8	pad1;
-	u16	length;		/* length of buffer */
-	u8	status;		/* status of buffer */
-	u8	pad2;
-} SCADESC, *PSCADESC;
-
-typedef struct _SCADESC_EX
-{
-	/* device driver bookkeeping section */
-	char 	*virt_addr;    	/* virtual address of data buffer */
-	u16	phys_entry;	/* lower 16-bits of physical address of this descriptor */
-} SCADESC_EX, *PSCADESC_EX;
-
-/* The queue of BH actions to be performed */
-
-#define BH_RECEIVE  1
-#define BH_TRANSMIT 2
-#define BH_STATUS   4
-
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-struct	_input_signal_events {
-	int	ri_up;
-	int	ri_down;
-	int	dsr_up;
-	int	dsr_down;
-	int	dcd_up;
-	int	dcd_down;
-	int	cts_up;
-	int	cts_down;
-};
-
-/*
- * Device instance data structure
- */
-typedef struct _synclinkmp_info {
-	void *if_ptr;				/* General purpose pointer (used by SPPP) */
-	int			magic;
-	struct tty_port		port;
-	int			line;
-	unsigned short		close_delay;
-	unsigned short		closing_wait;	/* time to wait before closing */
-
-	struct mgsl_icount	icount;
-
-	int			timeout;
-	int			x_char;		/* xon/xoff character */
-	u16			read_status_mask1;  /* break detection (SR1 indications) */
-	u16			read_status_mask2;  /* parity/framing/overun (SR2 indications) */
-	unsigned char 		ignore_status_mask1;  /* break detection (SR1 indications) */
-	unsigned char		ignore_status_mask2;  /* parity/framing/overun (SR2 indications) */
-	unsigned char 		*tx_buf;
-	int			tx_put;
-	int			tx_get;
-	int			tx_count;
-
-	wait_queue_head_t	status_event_wait_q;
-	wait_queue_head_t	event_wait_q;
-	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
-	struct _synclinkmp_info	*next_device;	/* device list link */
-	struct timer_list	status_timer;	/* input signal status check timer */
-
-	spinlock_t lock;		/* spinlock for synchronizing with ISR */
-	struct work_struct task;	 		/* task structure for scheduling bh */
-
-	u32 max_frame_size;			/* as set by device config */
-
-	u32 pending_bh;
-
-	bool bh_running;				/* Protection from multiple */
-	int isr_overflow;
-	bool bh_requested;
-
-	int dcd_chkcount;			/* check counts to prevent */
-	int cts_chkcount;			/* too many IRQs if a signal */
-	int dsr_chkcount;			/* is floating */
-	int ri_chkcount;
-
-	char *buffer_list;			/* virtual address of Rx & Tx buffer lists */
-	unsigned long buffer_list_phys;
-
-	unsigned int rx_buf_count;		/* count of total allocated Rx buffers */
-	SCADESC *rx_buf_list;   		/* list of receive buffer entries */
-	SCADESC_EX rx_buf_list_ex[SCAMAXDESC]; /* list of receive buffer entries */
-	unsigned int current_rx_buf;
-
-	unsigned int tx_buf_count;		/* count of total allocated Tx buffers */
-	SCADESC *tx_buf_list;		/* list of transmit buffer entries */
-	SCADESC_EX tx_buf_list_ex[SCAMAXDESC]; /* list of transmit buffer entries */
-	unsigned int last_tx_buf;
-
-	unsigned char *tmp_rx_buf;
-	unsigned int tmp_rx_buf_count;
-
-	bool rx_enabled;
-	bool rx_overflow;
-
-	bool tx_enabled;
-	bool tx_active;
-	u32 idle_mode;
-
-	unsigned char ie0_value;
-	unsigned char ie1_value;
-	unsigned char ie2_value;
-	unsigned char ctrlreg_value;
-	unsigned char old_signals;
-
-	char device_name[25];			/* device instance name */
-
-	int port_count;
-	int adapter_num;
-	int port_num;
-
-	struct _synclinkmp_info *port_array[SCA_MAX_PORTS];
-
-	unsigned int bus_type;			/* expansion bus type (ISA,EISA,PCI) */
-
-	unsigned int irq_level;			/* interrupt level */
-	unsigned long irq_flags;
-	bool irq_requested;			/* true if IRQ requested */
-
-	MGSL_PARAMS params;			/* communications parameters */
-
-	unsigned char serial_signals;		/* current serial signal states */
-
-	bool irq_occurred;			/* for diagnostics use */
-	unsigned int init_error;		/* Initialization startup error */
-
-	u32 last_mem_alloc;
-	unsigned char* memory_base;		/* shared memory address (PCI only) */
-	u32 phys_memory_base;
-    	int shared_mem_requested;
-
-	unsigned char* sca_base;		/* HD64570 SCA Memory address */
-	u32 phys_sca_base;
-	u32 sca_offset;
-	bool sca_base_requested;
-
-	unsigned char* lcr_base;		/* local config registers (PCI only) */
-	u32 phys_lcr_base;
-	u32 lcr_offset;
-	int lcr_mem_requested;
-
-	unsigned char* statctrl_base;		/* status/control register memory */
-	u32 phys_statctrl_base;
-	u32 statctrl_offset;
-	bool sca_statctrl_requested;
-
-	u32 misc_ctrl_value;
-	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
-	char char_buf[MAX_ASYNC_BUFFER_SIZE];
-	bool drop_rts_on_tx_done;
-
-	struct	_input_signal_events	input_signal_events;
-
-	/* SPPP/Cisco HDLC device parts */
-	int netcount;
-	spinlock_t netlock;
-
-#if SYNCLINK_GENERIC_HDLC
-	struct net_device *netdev;
-#endif
-
-} SLMP_INFO;
-
-#define MGSL_MAGIC 0x5401
-
-/*
- * define serial signal status change macros
- */
-#define	MISCSTATUS_DCD_LATCHED	(SerialSignal_DCD<<8)	/* indicates change in DCD */
-#define MISCSTATUS_RI_LATCHED	(SerialSignal_RI<<8)	/* indicates change in RI */
-#define MISCSTATUS_CTS_LATCHED	(SerialSignal_CTS<<8)	/* indicates change in CTS */
-#define MISCSTATUS_DSR_LATCHED	(SerialSignal_DSR<<8)	/* change in DSR */
-
-/* Common Register macros */
-#define LPR	0x00
-#define PABR0	0x02
-#define PABR1	0x03
-#define WCRL	0x04
-#define WCRM	0x05
-#define WCRH	0x06
-#define DPCR	0x08
-#define DMER	0x09
-#define ISR0	0x10
-#define ISR1	0x11
-#define ISR2	0x12
-#define IER0	0x14
-#define IER1	0x15
-#define IER2	0x16
-#define ITCR	0x18
-#define INTVR 	0x1a
-#define IMVR	0x1c
-
-/* MSCI Register macros */
-#define TRB	0x20
-#define TRBL	0x20
-#define TRBH	0x21
-#define SR0	0x22
-#define SR1	0x23
-#define SR2	0x24
-#define SR3	0x25
-#define FST	0x26
-#define IE0	0x28
-#define IE1	0x29
-#define IE2	0x2a
-#define FIE	0x2b
-#define CMD	0x2c
-#define MD0	0x2e
-#define MD1	0x2f
-#define MD2	0x30
-#define CTL	0x31
-#define SA0	0x32
-#define SA1	0x33
-#define IDL	0x34
-#define TMC	0x35
-#define RXS	0x36
-#define TXS	0x37
-#define TRC0	0x38
-#define TRC1	0x39
-#define RRC	0x3a
-#define CST0	0x3c
-#define CST1	0x3d
-
-/* Timer Register Macros */
-#define TCNT	0x60
-#define TCNTL	0x60
-#define TCNTH	0x61
-#define TCONR	0x62
-#define TCONRL	0x62
-#define TCONRH	0x63
-#define TMCS	0x64
-#define TEPR	0x65
-
-/* DMA Controller Register macros */
-#define DARL	0x80
-#define DARH	0x81
-#define DARB	0x82
-#define BAR	0x80
-#define BARL	0x80
-#define BARH	0x81
-#define BARB	0x82
-#define SAR	0x84
-#define SARL	0x84
-#define SARH	0x85
-#define SARB	0x86
-#define CPB	0x86
-#define CDA	0x88
-#define CDAL	0x88
-#define CDAH	0x89
-#define EDA	0x8a
-#define EDAL	0x8a
-#define EDAH	0x8b
-#define BFL	0x8c
-#define BFLL	0x8c
-#define BFLH	0x8d
-#define BCR	0x8e
-#define BCRL	0x8e
-#define BCRH	0x8f
-#define DSR	0x90
-#define DMR	0x91
-#define FCT	0x93
-#define DIR	0x94
-#define DCMD	0x95
-
-/* combine with timer or DMA register address */
-#define TIMER0	0x00
-#define TIMER1	0x08
-#define TIMER2	0x10
-#define TIMER3	0x18
-#define RXDMA 	0x00
-#define TXDMA 	0x20
-
-/* SCA Command Codes */
-#define NOOP		0x00
-#define TXRESET		0x01
-#define TXENABLE	0x02
-#define TXDISABLE	0x03
-#define TXCRCINIT	0x04
-#define TXCRCEXCL	0x05
-#define TXEOM		0x06
-#define TXABORT		0x07
-#define MPON		0x08
-#define TXBUFCLR	0x09
-#define RXRESET		0x11
-#define RXENABLE	0x12
-#define RXDISABLE	0x13
-#define RXCRCINIT	0x14
-#define RXREJECT	0x15
-#define SEARCHMP	0x16
-#define RXCRCEXCL	0x17
-#define RXCRCCALC	0x18
-#define CHRESET		0x21
-#define HUNT		0x31
-
-/* DMA command codes */
-#define SWABORT		0x01
-#define FEICLEAR	0x02
-
-/* IE0 */
-#define TXINTE 		BIT7
-#define RXINTE 		BIT6
-#define TXRDYE 		BIT1
-#define RXRDYE 		BIT0
-
-/* IE1 & SR1 */
-#define UDRN   	BIT7
-#define IDLE   	BIT6
-#define SYNCD  	BIT4
-#define FLGD   	BIT4
-#define CCTS   	BIT3
-#define CDCD   	BIT2
-#define BRKD   	BIT1
-#define ABTD   	BIT1
-#define GAPD   	BIT1
-#define BRKE   	BIT0
-#define IDLD	BIT0
-
-/* IE2 & SR2 */
-#define EOM	BIT7
-#define PMP	BIT6
-#define SHRT	BIT6
-#define PE	BIT5
-#define ABT	BIT5
-#define FRME	BIT4
-#define RBIT	BIT4
-#define OVRN	BIT3
-#define CRCE	BIT2
-
-
-/*
- * Global linked list of SyncLink devices
- */
-static SLMP_INFO *synclinkmp_device_list = NULL;
-static int synclinkmp_adapter_count = -1;
-static int synclinkmp_device_count = 0;
-
-/*
- * Set this param to non-zero to load eax with the
- * .text section address and breakpoint on module load.
- * This is useful for use with gdb and add-symbol-file command.
- */
-static int break_on_load = 0;
-
-/*
- * Driver major number, defaults to zero to get auto
- * assigned major number. May be forced as module parameter.
- */
-static int ttymajor = 0;
-
-/*
- * Array of user specified options for ISA adapters.
- */
-static int debug_level = 0;
-static int maxframe[MAX_DEVICES] = {0,};
-
-module_param(break_on_load, bool, 0);
-module_param(ttymajor, int, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-
-static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.38 $";
-
-static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
-static void synclinkmp_remove_one(struct pci_dev *dev);
-
-static struct pci_device_id synclinkmp_pci_tbl[] = {
-	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_SCA, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-static struct pci_driver synclinkmp_pci_driver = {
-	.name		= "synclinkmp",
-	.id_table	= synclinkmp_pci_tbl,
-	.probe		= synclinkmp_init_one,
-	.remove		= __devexit_p(synclinkmp_remove_one),
-};
-
-
-static struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-
-/* tty callbacks */
-
-static int  open(struct tty_struct *tty, struct file * filp);
-static void close(struct tty_struct *tty, struct file * filp);
-static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-
-static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int put_char(struct tty_struct *tty, unsigned char ch);
-static void send_xchar(struct tty_struct *tty, char ch);
-static void wait_until_sent(struct tty_struct *tty, int timeout);
-static int  write_room(struct tty_struct *tty);
-static void flush_chars(struct tty_struct *tty);
-static void flush_buffer(struct tty_struct *tty);
-static void tx_hold(struct tty_struct *tty);
-static void tx_release(struct tty_struct *tty);
-
-static int  ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static int  chars_in_buffer(struct tty_struct *tty);
-static void throttle(struct tty_struct * tty);
-static void unthrottle(struct tty_struct * tty);
-static int set_break(struct tty_struct *tty, int break_state);
-
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(SLMP_INFO *info);
-static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
-static int  hdlcdev_init(SLMP_INFO *info);
-static void hdlcdev_exit(SLMP_INFO *info);
-#endif
-
-/* ioctl handlers */
-
-static int  get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount);
-static int  get_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
-static int  set_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
-static int  get_txidle(SLMP_INFO *info, int __user *idle_mode);
-static int  set_txidle(SLMP_INFO *info, int idle_mode);
-static int  tx_enable(SLMP_INFO *info, int enable);
-static int  tx_abort(SLMP_INFO *info);
-static int  rx_enable(SLMP_INFO *info, int enable);
-static int  modem_input_wait(SLMP_INFO *info,int arg);
-static int  wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
-static int  tiocmget(struct tty_struct *tty, struct file *file);
-static int  tiocmset(struct tty_struct *tty, struct file *file,
-		     unsigned int set, unsigned int clear);
-static int  set_break(struct tty_struct *tty, int break_state);
-
-static void add_device(SLMP_INFO *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
-static int  claim_resources(SLMP_INFO *info);
-static void release_resources(SLMP_INFO *info);
-
-static int  startup(SLMP_INFO *info);
-static int  block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info);
-static int carrier_raised(struct tty_port *port);
-static void shutdown(SLMP_INFO *info);
-static void program_hw(SLMP_INFO *info);
-static void change_params(SLMP_INFO *info);
-
-static bool init_adapter(SLMP_INFO *info);
-static bool register_test(SLMP_INFO *info);
-static bool irq_test(SLMP_INFO *info);
-static bool loopback_test(SLMP_INFO *info);
-static int  adapter_test(SLMP_INFO *info);
-static bool memory_test(SLMP_INFO *info);
-
-static void reset_adapter(SLMP_INFO *info);
-static void reset_port(SLMP_INFO *info);
-static void async_mode(SLMP_INFO *info);
-static void hdlc_mode(SLMP_INFO *info);
-
-static void rx_stop(SLMP_INFO *info);
-static void rx_start(SLMP_INFO *info);
-static void rx_reset_buffers(SLMP_INFO *info);
-static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last);
-static bool rx_get_frame(SLMP_INFO *info);
-
-static void tx_start(SLMP_INFO *info);
-static void tx_stop(SLMP_INFO *info);
-static void tx_load_fifo(SLMP_INFO *info);
-static void tx_set_idle(SLMP_INFO *info);
-static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count);
-
-static void get_signals(SLMP_INFO *info);
-static void set_signals(SLMP_INFO *info);
-static void enable_loopback(SLMP_INFO *info, int enable);
-static void set_rate(SLMP_INFO *info, u32 data_rate);
-
-static int  bh_action(SLMP_INFO *info);
-static void bh_handler(struct work_struct *work);
-static void bh_receive(SLMP_INFO *info);
-static void bh_transmit(SLMP_INFO *info);
-static void bh_status(SLMP_INFO *info);
-static void isr_timer(SLMP_INFO *info);
-static void isr_rxint(SLMP_INFO *info);
-static void isr_rxrdy(SLMP_INFO *info);
-static void isr_txint(SLMP_INFO *info);
-static void isr_txrdy(SLMP_INFO *info);
-static void isr_rxdmaok(SLMP_INFO *info);
-static void isr_rxdmaerror(SLMP_INFO *info);
-static void isr_txdmaok(SLMP_INFO *info);
-static void isr_txdmaerror(SLMP_INFO *info);
-static void isr_io_pin(SLMP_INFO *info, u16 status);
-
-static int  alloc_dma_bufs(SLMP_INFO *info);
-static void free_dma_bufs(SLMP_INFO *info);
-static int  alloc_buf_list(SLMP_INFO *info);
-static int  alloc_frame_bufs(SLMP_INFO *info, SCADESC *list, SCADESC_EX *list_ex,int count);
-static int  alloc_tmp_rx_buf(SLMP_INFO *info);
-static void free_tmp_rx_buf(SLMP_INFO *info);
-
-static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count);
-static void trace_block(SLMP_INFO *info, const char* data, int count, int xmit);
-static void tx_timeout(unsigned long context);
-static void status_timeout(unsigned long context);
-
-static unsigned char read_reg(SLMP_INFO *info, unsigned char addr);
-static void write_reg(SLMP_INFO *info, unsigned char addr, unsigned char val);
-static u16 read_reg16(SLMP_INFO *info, unsigned char addr);
-static void write_reg16(SLMP_INFO *info, unsigned char addr, u16 val);
-static unsigned char read_status_reg(SLMP_INFO * info);
-static void write_control_reg(SLMP_INFO * info);
-
-
-static unsigned char rx_active_fifo_level = 16;	// rx request FIFO activation level in bytes
-static unsigned char tx_active_fifo_level = 16;	// tx request FIFO activation level in bytes
-static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
-
-static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x00800028;
-
-static u32 read_ahead_count = 8;
-
-/* DPCR, DMA Priority Control
- *
- * 07..05  Not used, must be 0
- * 04      BRC, bus release condition: 0=all transfers complete
- *              1=release after 1 xfer on all channels
- * 03      CCC, channel change condition: 0=every cycle
- *              1=after each channel completes all xfers
- * 02..00  PR<2..0>, priority 100=round robin
- *
- * 00000100 = 0x00
- */
-static unsigned char dma_priority = 0x04;
-
-// Number of bytes that can be written to shared RAM
-// in a single write operation
-static u32 sca_pci_load_interval = 64;
-
-/*
- * 1st function defined in .text section. Calling this function in
- * init_module() followed by a breakpoint allows a remote debugger
- * (gdb) to get the .text address for the add-symbol-file command.
- * This allows remote debugging of dynamically loadable modules.
- */
-static void* synclinkmp_get_text_ptr(void);
-static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;}
-
-static inline int sanity_check(SLMP_INFO *info,
-			       char *name, const char *routine)
-{
-#ifdef SANITY_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for synclinkmp_struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null synclinkmp_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != MGSL_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#else
-	if (!info)
-		return 1;
-#endif
-	return 0;
-}
-
-/**
- * line discipline callback wrappers
- *
- * The wrappers maintain line discipline references
- * while calling into the line discipline.
- *
- * ldisc_receive_buf  - pass receive data to line discipline
- */
-
-static void ldisc_receive_buf(struct tty_struct *tty,
-			      const __u8 *data, char *flags, int count)
-{
-	struct tty_ldisc *ld;
-	if (!tty)
-		return;
-	ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->receive_buf)
-			ld->ops->receive_buf(tty, data, flags, count);
-		tty_ldisc_deref(ld);
-	}
-}
-
-/* tty callbacks */
-
-/* Called when a port is opened.  Init and enable port.
- */
-static int open(struct tty_struct *tty, struct file *filp)
-{
-	SLMP_INFO *info;
-	int retval, line;
-	unsigned long flags;
-
-	line = tty->index;
-	if ((line < 0) || (line >= synclinkmp_device_count)) {
-		printk("%s(%d): open with invalid line #%d.\n",
-			__FILE__,__LINE__,line);
-		return -ENODEV;
-	}
-
-	info = synclinkmp_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (sanity_check(info, tty->name, "open"))
-		return -ENODEV;
-	if ( info->init_error ) {
-		printk("%s(%d):%s device is not allocated, init error=%d\n",
-			__FILE__,__LINE__,info->device_name,info->init_error);
-		return -ENODEV;
-	}
-
-	tty->driver_data = info;
-	info->port.tty = tty;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s open(), old ref count = %d\n",
-			 __FILE__,__LINE__,tty->driver->name, info->port.count);
-
-	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-		if (info->port.flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->port.close_wait);
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
-	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->netcount) {
-		retval = -EBUSY;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		goto cleanup;
-	}
-	info->port.count++;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	if (info->port.count == 1) {
-		/* 1st open on this device, init hardware */
-		retval = startup(info);
-		if (retval < 0)
-			goto cleanup;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):%s block_til_ready() returned %d\n",
-				 __FILE__,__LINE__, info->device_name, retval);
-		goto cleanup;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s open() success\n",
-			 __FILE__,__LINE__, info->device_name);
-	retval = 0;
-
-cleanup:
-	if (retval) {
-		if (tty->count == 1)
-			info->port.tty = NULL; /* tty layer will release tty struct */
-		if(info->port.count)
-			info->port.count--;
-	}
-
-	return retval;
-}
-
-/* Called when port is closed. Wait for remaining data to be
- * sent. Disable port and free resources.
- */
-static void close(struct tty_struct *tty, struct file *filp)
-{
-	SLMP_INFO * info = tty->driver_data;
-
-	if (sanity_check(info, tty->name, "close"))
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s close() entry, count=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->port.count);
-
-	if (tty_port_close_start(&info->port, tty, filp) == 0)
-		goto cleanup;
-
-	mutex_lock(&info->port.mutex);
- 	if (info->port.flags & ASYNC_INITIALIZED)
- 		wait_until_sent(tty, info->timeout);
-
-	flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	shutdown(info);
-	mutex_unlock(&info->port.mutex);
-
-	tty_port_close_end(&info->port, tty);
-	info->port.tty = NULL;
-cleanup:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__,
-			tty->driver->name, info->port.count);
-}
-
-/* Called by tty_hangup() when a hangup is signaled.
- * This is the same as closing all open descriptors for the port.
- */
-static void hangup(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s hangup()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "hangup"))
-		return;
-
-	mutex_lock(&info->port.mutex);
-	flush_buffer(tty);
-	shutdown(info);
-
-	spin_lock_irqsave(&info->port.lock, flags);
-	info->port.count = 0;
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-	spin_unlock_irqrestore(&info->port.lock, flags);
-	mutex_unlock(&info->port.mutex);
-
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-/* Set new termios settings
- */
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
-			tty->driver->name );
-
-	change_params(info);
-
-	/* Handle transition to B0 status */
-	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-		spin_lock_irqsave(&info->lock,flags);
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
-		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
- 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->serial_signals |= SerialSignal_RTS;
- 		}
-		spin_lock_irqsave(&info->lock,flags);
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		tx_release(tty);
-	}
-}
-
-/* Send a block of data
- *
- * Arguments:
- *
- * 	tty		pointer to tty information structure
- * 	buf		pointer to buffer containing send data
- * 	count		size of send data in bytes
- *
- * Return Value:	number of characters written
- */
-static int write(struct tty_struct *tty,
-		 const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s write() count=%d\n",
-		       __FILE__,__LINE__,info->device_name,count);
-
-	if (sanity_check(info, tty->name, "write"))
-		goto cleanup;
-
-	if (!info->tx_buf)
-		goto cleanup;
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		if (count > info->max_frame_size) {
-			ret = -EIO;
-			goto cleanup;
-		}
-		if (info->tx_active)
-			goto cleanup;
-		if (info->tx_count) {
-			/* send accumulated data from send_char() calls */
-			/* as frame and wait before accepting more data. */
-			tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
-			goto start;
-		}
-		ret = info->tx_count = count;
-		tx_load_dma_buffer(info, buf, count);
-		goto start;
-	}
-
-	for (;;) {
-		c = min_t(int, count,
-			min(info->max_frame_size - info->tx_count - 1,
-			    info->max_frame_size - info->tx_put));
-		if (c <= 0)
-			break;
-			
-		memcpy(info->tx_buf + info->tx_put, buf, c);
-
-		spin_lock_irqsave(&info->lock,flags);
-		info->tx_put += c;
-		if (info->tx_put >= info->max_frame_size)
-			info->tx_put -= info->max_frame_size;
-		info->tx_count += c;
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		if (count) {
-			ret = info->tx_count = 0;
-			goto cleanup;
-		}
-		tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
-	}
-start:
- 	if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_active)
-		 	tx_start(info);
-		spin_unlock_irqrestore(&info->lock,flags);
- 	}
-
-cleanup:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk( "%s(%d):%s write() returning=%d\n",
-			__FILE__,__LINE__,info->device_name,ret);
-	return ret;
-}
-
-/* Add a character to the transmit buffer.
- */
-static int put_char(struct tty_struct *tty, unsigned char ch)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO ) {
-		printk( "%s(%d):%s put_char(%d)\n",
-			__FILE__,__LINE__,info->device_name,ch);
-	}
-
-	if (sanity_check(info, tty->name, "put_char"))
-		return 0;
-
-	if (!info->tx_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if ( (info->params.mode != MGSL_MODE_HDLC) ||
-	     !info->tx_active ) {
-
-		if (info->tx_count < info->max_frame_size - 1) {
-			info->tx_buf[info->tx_put++] = ch;
-			if (info->tx_put >= info->max_frame_size)
-				info->tx_put -= info->max_frame_size;
-			info->tx_count++;
-			ret = 1;
-		}
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-	return ret;
-}
-
-/* Send a high-priority XON/XOFF character
- */
-static void send_xchar(struct tty_struct *tty, char ch)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s send_xchar(%d)\n",
-			 __FILE__,__LINE__, info->device_name, ch );
-
-	if (sanity_check(info, tty->name, "send_xchar"))
-		return;
-
-	info->x_char = ch;
-	if (ch) {
-		/* Make sure transmit interrupts are on */
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_enabled)
-		 	tx_start(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/* Wait until the transmitter is empty.
- */
-static void wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	SLMP_INFO * info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-
-	if (!info )
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s wait_until_sent() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "wait_until_sent"))
-		return;
-
-	if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags))
-		goto exit;
-
-	orig_jiffies = jiffies;
-
-	/* Set check interval to 1/5 of estimated time to
-	 * send a character, and make it at least 1. The check
-	 * interval should also be less than the timeout.
-	 * Note: use tight timings here to satisfy the NIST-PCTS.
-	 */
-
-	if ( info->params.data_rate ) {
-	       	char_time = info->timeout/(32 * 5);
-		if (!char_time)
-			char_time++;
-	} else
-		char_time = 1;
-
-	if (timeout)
-		char_time = min_t(unsigned long, char_time, timeout);
-
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
-		while (info->tx_active) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	} else {
-		/*
-		 * TODO: determine if there is something similar to USC16C32
-		 * 	 TXSTATUS_ALL_SENT status
-		 */
-		while ( info->tx_active && info->tx_enabled) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	}
-
-exit:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s wait_until_sent() exit\n",
-			 __FILE__,__LINE__, info->device_name );
-}
-
-/* Return the count of free bytes in transmit buffer
- */
-static int write_room(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	int ret;
-
-	if (sanity_check(info, tty->name, "write_room"))
-		return 0;
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
-	} else {
-		ret = info->max_frame_size - info->tx_count - 1;
-		if (ret < 0)
-			ret = 0;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s write_room()=%d\n",
-		       __FILE__, __LINE__, info->device_name, ret);
-
-	return ret;
-}
-
-/* enable transmitter and send remaining buffered characters
- */
-static void flush_chars(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s flush_chars() entry tx_count=%d\n",
-			__FILE__,__LINE__,info->device_name,info->tx_count);
-
-	if (sanity_check(info, tty->name, "flush_chars"))
-		return;
-
-	if (info->tx_count <= 0 || tty->stopped || tty->hw_stopped ||
-	    !info->tx_buf)
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s flush_chars() entry, starting transmitter\n",
-			__FILE__,__LINE__,info->device_name );
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if (!info->tx_active) {
-		if ( (info->params.mode == MGSL_MODE_HDLC) &&
-			info->tx_count ) {
-			/* operating in synchronous (frame oriented) mode */
-			/* copy data from circular tx_buf to */
-			/* transmit DMA buffer. */
-			tx_load_dma_buffer(info,
-				 info->tx_buf,info->tx_count);
-		}
-	 	tx_start(info);
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Discard all data in the send buffer
- */
-static void flush_buffer(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s flush_buffer() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&info->lock,flags);
-	info->tx_count = info->tx_put = info->tx_get = 0;
-	del_timer(&info->tx_timer);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	tty_wakeup(tty);
-}
-
-/* throttle (stop) transmitter
- */
-static void tx_hold(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_hold"))
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s tx_hold()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_enabled)
-	 	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* release (start) transmitter
- */
-static void tx_release(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_release"))
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s tx_release()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_enabled)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Service an IOCTL request
- *
- * Arguments:
- *
- * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
- * 	cmd	IOCTL command code
- * 	arg	command argument/context
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int ioctl(struct tty_struct *tty, struct file *file,
-		 unsigned int cmd, unsigned long arg)
-{
-	SLMP_INFO *info = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__,
-			info->device_name, cmd );
-
-	if (sanity_check(info, tty->name, "ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-	case MGSL_IOCGPARAMS:
-		return get_params(info, argp);
-	case MGSL_IOCSPARAMS:
-		return set_params(info, argp);
-	case MGSL_IOCGTXIDLE:
-		return get_txidle(info, argp);
-	case MGSL_IOCSTXIDLE:
-		return set_txidle(info, (int)arg);
-	case MGSL_IOCTXENABLE:
-		return tx_enable(info, (int)arg);
-	case MGSL_IOCRXENABLE:
-		return rx_enable(info, (int)arg);
-	case MGSL_IOCTXABORT:
-		return tx_abort(info);
-	case MGSL_IOCGSTATS:
-		return get_stats(info, argp);
-	case MGSL_IOCWAITEVENT:
-		return wait_mgsl_event(info, argp);
-	case MGSL_IOCLOOPTXDONE:
-		return 0; // TODO: Not supported, need to document
-		/* Wait for modem input (DCD,RI,DSR,CTS) change
-		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
-		 */
-	case TIOCMIWAIT:
-		return modem_input_wait(info,(int)arg);
-		
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static int get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	SLMP_INFO *info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline void line_info(struct seq_file *m, SLMP_INFO *info)
-{
-	char	stat_buf[30];
-	unsigned long flags;
-
-	seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n"
-		       "\tIRQ=%d MaxFrameSize=%u\n",
-		info->device_name,
-		info->phys_sca_base,
-		info->phys_memory_base,
-		info->phys_statctrl_base,
-		info->phys_lcr_base,
-		info->irq_level,
-		info->max_frame_size );
-
-	/* output current serial signal states */
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (info->serial_signals & SerialSignal_RTS)
-		strcat(stat_buf, "|RTS");
-	if (info->serial_signals & SerialSignal_CTS)
-		strcat(stat_buf, "|CTS");
-	if (info->serial_signals & SerialSignal_DTR)
-		strcat(stat_buf, "|DTR");
-	if (info->serial_signals & SerialSignal_DSR)
-		strcat(stat_buf, "|DSR");
-	if (info->serial_signals & SerialSignal_DCD)
-		strcat(stat_buf, "|CD");
-	if (info->serial_signals & SerialSignal_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		seq_printf(m, "\tHDLC txok:%d rxok:%d",
-			      info->icount.txok, info->icount.rxok);
-		if (info->icount.txunder)
-			seq_printf(m, " txunder:%d", info->icount.txunder);
-		if (info->icount.txabort)
-			seq_printf(m, " txabort:%d", info->icount.txabort);
-		if (info->icount.rxshort)
-			seq_printf(m, " rxshort:%d", info->icount.rxshort);
-		if (info->icount.rxlong)
-			seq_printf(m, " rxlong:%d", info->icount.rxlong);
-		if (info->icount.rxover)
-			seq_printf(m, " rxover:%d", info->icount.rxover);
-		if (info->icount.rxcrc)
-			seq_printf(m, " rxlong:%d", info->icount.rxcrc);
-	} else {
-		seq_printf(m, "\tASYNC tx:%d rx:%d",
-			      info->icount.tx, info->icount.rx);
-		if (info->icount.frame)
-			seq_printf(m, " fe:%d", info->icount.frame);
-		if (info->icount.parity)
-			seq_printf(m, " pe:%d", info->icount.parity);
-		if (info->icount.brk)
-			seq_printf(m, " brk:%d", info->icount.brk);
-		if (info->icount.overrun)
-			seq_printf(m, " oe:%d", info->icount.overrun);
-	}
-
-	/* Append serial signal status to end */
-	seq_printf(m, " %s\n", stat_buf+1);
-
-	seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
-	 info->tx_active,info->bh_requested,info->bh_running,
-	 info->pending_bh);
-}
-
-/* Called to print information about devices
- */
-static int synclinkmp_proc_show(struct seq_file *m, void *v)
-{
-	SLMP_INFO *info;
-
-	seq_printf(m, "synclinkmp driver:%s\n", driver_version);
-
-	info = synclinkmp_device_list;
-	while( info ) {
-		line_info(m, info);
-		info = info->next_device;
-	}
-	return 0;
-}
-
-static int synclinkmp_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, synclinkmp_proc_show, NULL);
-}
-
-static const struct file_operations synclinkmp_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= synclinkmp_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/* Return the count of bytes in transmit buffer
- */
-static int chars_in_buffer(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-
-	if (sanity_check(info, tty->name, "chars_in_buffer"))
-		return 0;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s chars_in_buffer()=%d\n",
-		       __FILE__, __LINE__, info->device_name, info->tx_count);
-
-	return info->tx_count;
-}
-
-/* Signal remote device to throttle send data (our receive data)
- */
-static void throttle(struct tty_struct * tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s throttle() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "throttle"))
-		return;
-
-	if (I_IXOFF(tty))
-		send_xchar(tty, STOP_CHAR(tty));
-
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->serial_signals &= ~SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/* Signal remote device to stop throttling send data (our receive data)
- */
-static void unthrottle(struct tty_struct * tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s unthrottle() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			send_xchar(tty, START_CHAR(tty));
-	}
-
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->serial_signals |= SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/* set or clear transmit break condition
- * break_state	-1=set break condition, 0=clear
- */
-static int set_break(struct tty_struct *tty, int break_state)
-{
-	unsigned char RegValue;
-	SLMP_INFO * info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_break(%d)\n",
-			 __FILE__,__LINE__, info->device_name, break_state);
-
-	if (sanity_check(info, tty->name, "set_break"))
-		return -EINVAL;
-
-	spin_lock_irqsave(&info->lock,flags);
-	RegValue = read_reg(info, CTL);
- 	if (break_state == -1)
-		RegValue |= BIT3;
-	else
-		RegValue &= ~BIT3;
-	write_reg(info, CTL, RegValue);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-#if SYNCLINK_GENERIC_HDLC
-
-/**
- * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
- * set encoding and frame check sequence (FCS) options
- *
- * dev       pointer to network device structure
- * encoding  serial encoding setting
- * parity    FCS setting
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
-			  unsigned short parity)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned char  new_encoding;
-	unsigned short new_crctype;
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	switch (encoding)
-	{
-	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
-	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
-	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
-	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
-	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
-	default: return -EINVAL;
-	}
-
-	switch (parity)
-	{
-	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
-	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
-	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
-	default: return -EINVAL;
-	}
-
-	info->params.encoding = new_encoding;
-	info->params.crc_type = new_crctype;
-
-	/* if network interface up, reprogram hardware */
-	if (info->netcount)
-		program_hw(info);
-
-	return 0;
-}
-
-/**
- * called by generic HDLC layer to send frame
- *
- * skb  socket buffer containing HDLC frame
- * dev  pointer to network device structure
- */
-static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
-
-	/* stop sending until this frame completes */
-	netif_stop_queue(dev);
-
-	/* copy data to device buffers */
-	info->tx_count = skb->len;
-	tx_load_dma_buffer(info, skb->data, skb->len);
-
-	/* update network statistics */
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
-	/* save start time for transmit timeout detection */
-	dev->trans_start = jiffies;
-
-	/* start hardware transmitter if necessary */
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_active)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * called by network layer when interface enabled
- * claim resources and initialize hardware
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_open(struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	int rc;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
-
-	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
-		return rc;
-
-	/* arbitrate between network and tty opens */
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->port.count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return -EBUSY;
-	}
-	info->netcount=1;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	/* claim resources and init adapter */
-	if ((rc = startup(info)) != 0) {
-		spin_lock_irqsave(&info->netlock, flags);
-		info->netcount=0;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return rc;
-	}
-
-	/* assert DTR and RTS, apply hardware settings */
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	program_hw(info);
-
-	/* enable network layer transmit */
-	dev->trans_start = jiffies;
-	netif_start_queue(dev);
-
-	/* inform generic HDLC layer of current DCD status */
-	spin_lock_irqsave(&info->lock, flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock, flags);
-	if (info->serial_signals & SerialSignal_DCD)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-	return 0;
-}
-
-/**
- * called by network layer when interface is disabled
- * shutdown hardware and release resources
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_close(struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
-
-	netif_stop_queue(dev);
-
-	/* shutdown adapter and release resources */
-	shutdown(info);
-
-	hdlc_close(dev);
-
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	return 0;
-}
-
-/**
- * called by network layer to process IOCTL call to network device
- *
- * dev  pointer to network device structure
- * ifr  pointer to network interface request structure
- * cmd  IOCTL command code
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line;
-	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned int flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	if (cmd != SIOCWANDEV)
-		return hdlc_ioctl(dev, ifr, cmd);
-
-	switch(ifr->ifr_settings.type) {
-	case IF_GET_IFACE: /* return current sync_serial_settings */
-
-		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
-		if (ifr->ifr_settings.size < size) {
-			ifr->ifr_settings.size = size; /* data size wanted */
-			return -ENOBUFS;
-		}
-
-		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-
-		switch (flags){
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
-		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
-		default: new_line.clock_type = CLOCK_DEFAULT;
-		}
-
-		new_line.clock_rate = info->params.clock_speed;
-		new_line.loopback   = info->params.loopback ? 1:0;
-
-		if (copy_to_user(line, &new_line, size))
-			return -EFAULT;
-		return 0;
-
-	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
-
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&new_line, line, size))
-			return -EFAULT;
-
-		switch (new_line.clock_type)
-		{
-		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
-		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
-		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_DEFAULT:  flags = info->params.flags &
-					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
-		default: return -EINVAL;
-		}
-
-		if (new_line.loopback != 0 && new_line.loopback != 1)
-			return -EINVAL;
-
-		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-		info->params.flags |= flags;
-
-		info->params.loopback = new_line.loopback;
-
-		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
-			info->params.clock_speed = new_line.clock_rate;
-		else
-			info->params.clock_speed = 0;
-
-		/* if network interface up, reprogram hardware */
-		if (info->netcount)
-			program_hw(info);
-		return 0;
-
-	default:
-		return hdlc_ioctl(dev, ifr, cmd);
-	}
-}
-
-/**
- * called by network layer when transmit timeout is detected
- *
- * dev  pointer to network device structure
- */
-static void hdlcdev_tx_timeout(struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
-
-	dev->stats.tx_errors++;
-	dev->stats.tx_aborted_errors++;
-
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	netif_wake_queue(dev);
-}
-
-/**
- * called by device driver when transmit completes
- * reenable network layer transmit if stopped
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_tx_done(SLMP_INFO *info)
-{
-	if (netif_queue_stopped(info->netdev))
-		netif_wake_queue(info->netdev);
-}
-
-/**
- * called by device driver when frame received
- * pass frame to network layer
- *
- * info  pointer to device instance information
- * buf   pointer to buffer contianing frame data
- * size  count of data bytes in buf
- */
-static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size);
-	struct net_device *dev = info->netdev;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_rx(%s)\n",dev->name);
-
-	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-		       dev->name);
-		dev->stats.rx_dropped++;
-		return;
-	}
-
-	memcpy(skb_put(skb, size), buf, size);
-
-	skb->protocol = hdlc_type_trans(skb, dev);
-
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += size;
-
-	netif_rx(skb);
-}
-
-static const struct net_device_ops hdlcdev_ops = {
-	.ndo_open       = hdlcdev_open,
-	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
-	.ndo_start_xmit = hdlc_start_xmit,
-	.ndo_do_ioctl   = hdlcdev_ioctl,
-	.ndo_tx_timeout = hdlcdev_tx_timeout,
-};
-
-/**
- * called by device driver when adding device instance
- * do generic HDLC initialization
- *
- * info  pointer to device instance information
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_init(SLMP_INFO *info)
-{
-	int rc;
-	struct net_device *dev;
-	hdlc_device *hdlc;
-
-	/* allocate and initialize network and HDLC layer objects */
-
-	if (!(dev = alloc_hdlcdev(info))) {
-		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
-		return -ENOMEM;
-	}
-
-	/* for network layer reporting purposes only */
-	dev->mem_start = info->phys_sca_base;
-	dev->mem_end   = info->phys_sca_base + SCA_BASE_SIZE - 1;
-	dev->irq       = info->irq_level;
-
-	/* network layer callbacks and settings */
-	dev->netdev_ops	    = &hdlcdev_ops;
-	dev->watchdog_timeo = 10 * HZ;
-	dev->tx_queue_len   = 50;
-
-	/* generic HDLC layer callbacks and settings */
-	hdlc         = dev_to_hdlc(dev);
-	hdlc->attach = hdlcdev_attach;
-	hdlc->xmit   = hdlcdev_xmit;
-
-	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
-		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
-		free_netdev(dev);
-		return rc;
-	}
-
-	info->netdev = dev;
-	return 0;
-}
-
-/**
- * called by device driver when removing device instance
- * do generic HDLC cleanup
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_exit(SLMP_INFO *info)
-{
-	unregister_hdlc_device(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-}
-
-#endif /* CONFIG_HDLC */
-
-
-/* Return next bottom half action to perform.
- * Return Value:	BH action code or 0 if nothing to do.
- */
-static int bh_action(SLMP_INFO *info)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if (info->pending_bh & BH_RECEIVE) {
-		info->pending_bh &= ~BH_RECEIVE;
-		rc = BH_RECEIVE;
-	} else if (info->pending_bh & BH_TRANSMIT) {
-		info->pending_bh &= ~BH_TRANSMIT;
-		rc = BH_TRANSMIT;
-	} else if (info->pending_bh & BH_STATUS) {
-		info->pending_bh &= ~BH_STATUS;
-		rc = BH_STATUS;
-	}
-
-	if (!rc) {
-		/* Mark BH routine as complete */
-		info->bh_running = false;
-		info->bh_requested = false;
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return rc;
-}
-
-/* Perform bottom half processing of work items queued by ISR.
- */
-static void bh_handler(struct work_struct *work)
-{
-	SLMP_INFO *info = container_of(work, SLMP_INFO, task);
-	int action;
-
-	if (!info)
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_handler() entry\n",
-			__FILE__,__LINE__,info->device_name);
-
-	info->bh_running = true;
-
-	while((action = bh_action(info)) != 0) {
-
-		/* Process work item */
-		if ( debug_level >= DEBUG_LEVEL_BH )
-			printk( "%s(%d):%s bh_handler() work item action=%d\n",
-				__FILE__,__LINE__,info->device_name, action);
-
-		switch (action) {
-
-		case BH_RECEIVE:
-			bh_receive(info);
-			break;
-		case BH_TRANSMIT:
-			bh_transmit(info);
-			break;
-		case BH_STATUS:
-			bh_status(info);
-			break;
-		default:
-			/* unknown work item ID */
-			printk("%s(%d):%s Unknown work item ID=%08X!\n",
-				__FILE__,__LINE__,info->device_name,action);
-			break;
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_handler() exit\n",
-			__FILE__,__LINE__,info->device_name);
-}
-
-static void bh_receive(SLMP_INFO *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_receive()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	while( rx_get_frame(info) );
-}
-
-static void bh_transmit(SLMP_INFO *info)
-{
-	struct tty_struct *tty = info->port.tty;
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_transmit() entry\n",
-			__FILE__,__LINE__,info->device_name);
-
-	if (tty)
-		tty_wakeup(tty);
-}
-
-static void bh_status(SLMP_INFO *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_status() entry\n",
-			__FILE__,__LINE__,info->device_name);
-
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-}
-
-static void isr_timer(SLMP_INFO * info)
-{
-	unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
-
-	/* IER2<7..4> = timer<3..0> interrupt enables (0=disabled) */
-	write_reg(info, IER2, 0);
-
-	/* TMCS, Timer Control/Status Register
-	 *
-	 * 07      CMF, Compare match flag (read only) 1=match
-	 * 06      ECMI, CMF Interrupt Enable: 0=disabled
-	 * 05      Reserved, must be 0
-	 * 04      TME, Timer Enable
-	 * 03..00  Reserved, must be 0
-	 *
-	 * 0000 0000
-	 */
-	write_reg(info, (unsigned char)(timer + TMCS), 0);
-
-	info->irq_occurred = true;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_timer()\n",
-			__FILE__,__LINE__,info->device_name);
-}
-
-static void isr_rxint(SLMP_INFO * info)
-{
- 	struct tty_struct *tty = info->port.tty;
- 	struct	mgsl_icount *icount = &info->icount;
-	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
-	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
-
-	/* clear status bits */
-	if (status)
-		write_reg(info, SR1, status);
-
-	if (status2)
-		write_reg(info, SR2, status2);
-	
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
-			__FILE__,__LINE__,info->device_name,status,status2);
-
-	if (info->params.mode == MGSL_MODE_ASYNC) {
-		if (status & BRKD) {
-			icount->brk++;
-
-			/* process break detection if tty control
-			 * is not set to ignore it
-			 */
-			if ( tty ) {
-				if (!(status & info->ignore_status_mask1)) {
-					if (info->read_status_mask1 & BRKD) {
-						tty_insert_flip_char(tty, 0, TTY_BREAK);
-						if (info->port.flags & ASYNC_SAK)
-							do_SAK(tty);
-					}
-				}
-			}
-		}
-	}
-	else {
-		if (status & (FLGD|IDLD)) {
-			if (status & FLGD)
-				info->icount.exithunt++;
-			else if (status & IDLD)
-				info->icount.rxidle++;
-			wake_up_interruptible(&info->event_wait_q);
-		}
-	}
-
-	if (status & CDCD) {
-		/* simulate a common modem status change interrupt
-		 * for our handler
-		 */
-		get_signals( info );
-		isr_io_pin(info,
-			MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD));
-	}
-}
-
-/*
- * handle async rx data interrupts
- */
-static void isr_rxrdy(SLMP_INFO * info)
-{
-	u16 status;
-	unsigned char DataByte;
- 	struct tty_struct *tty = info->port.tty;
- 	struct	mgsl_icount *icount = &info->icount;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxrdy\n",
-			__FILE__,__LINE__,info->device_name);
-
-	while((status = read_reg(info,CST0)) & BIT0)
-	{
-		int flag = 0;
-		bool over = false;
-		DataByte = read_reg(info,TRB);
-
-		icount->rx++;
-
-		if ( status & (PE + FRME + OVRN) ) {
-			printk("%s(%d):%s rxerr=%04X\n",
-				__FILE__,__LINE__,info->device_name,status);
-
-			/* update error statistics */
-			if (status & PE)
-				icount->parity++;
-			else if (status & FRME)
-				icount->frame++;
-			else if (status & OVRN)
-				icount->overrun++;
-
-			/* discard char if tty control flags say so */
-			if (status & info->ignore_status_mask2)
-				continue;
-
-			status &= info->read_status_mask2;
-
-			if ( tty ) {
-				if (status & PE)
-					flag = TTY_PARITY;
-				else if (status & FRME)
-					flag = TTY_FRAME;
-				if (status & OVRN) {
-					/* Overrun is special, since it's
-					 * reported immediately, and doesn't
-					 * affect the current character
-					 */
-					over = true;
-				}
-			}
-		}	/* end of if (error) */
-
-		if ( tty ) {
-			tty_insert_flip_char(tty, DataByte, flag);
-			if (over)
-				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_ISR ) {
-		printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
-			__FILE__,__LINE__,info->device_name,
-			icount->rx,icount->brk,icount->parity,
-			icount->frame,icount->overrun);
-	}
-
-	if ( tty )
-		tty_flip_buffer_push(tty);
-}
-
-static void isr_txeom(SLMP_INFO * info, unsigned char status)
-{
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txeom status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
-	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
-	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-	if (status & UDRN) {
-		write_reg(info, CMD, TXRESET);
-		write_reg(info, CMD, TXENABLE);
-	} else
-		write_reg(info, CMD, TXBUFCLR);
-
-	/* disable and clear tx interrupts */
-	info->ie0_value &= ~TXRDYE;
-	info->ie1_value &= ~(IDLE + UDRN);
-	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
-	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
-	if ( info->tx_active ) {
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			if (status & UDRN)
-				info->icount.txunder++;
-			else if (status & IDLE)
-				info->icount.txok++;
-		}
-
-		info->tx_active = false;
-		info->tx_count = info->tx_put = info->tx_get = 0;
-
-		del_timer(&info->tx_timer);
-
-		if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) {
-			info->serial_signals &= ~SerialSignal_RTS;
-			info->drop_rts_on_tx_done = false;
-			set_signals(info);
-		}
-
-#if SYNCLINK_GENERIC_HDLC
-		if (info->netcount)
-			hdlcdev_tx_done(info);
-		else
-#endif
-		{
-			if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
-				tx_stop(info);
-				return;
-			}
-			info->pending_bh |= BH_TRANSMIT;
-		}
-	}
-}
-
-
-/*
- * handle tx status interrupts
- */
-static void isr_txint(SLMP_INFO * info)
-{
-	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
-
-	/* clear status bits */
-	write_reg(info, SR1, status);
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txint status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	if (status & (UDRN + IDLE))
-		isr_txeom(info, status);
-
-	if (status & CCTS) {
-		/* simulate a common modem status change interrupt
-		 * for our handler
-		 */
-		get_signals( info );
-		isr_io_pin(info,
-			MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS));
-
-	}
-}
-
-/*
- * handle async tx data interrupts
- */
-static void isr_txrdy(SLMP_INFO * info)
-{
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
-			__FILE__,__LINE__,info->device_name,info->tx_count);
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		/* disable TXRDY IRQ, enable IDLE IRQ */
-		info->ie0_value &= ~TXRDYE;
-		info->ie1_value |= IDLE;
-		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
-		return;
-	}
-
-	if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
-		tx_stop(info);
-		return;
-	}
-
-	if ( info->tx_count )
-		tx_load_fifo( info );
-	else {
-		info->tx_active = false;
-		info->ie0_value &= ~TXRDYE;
-		write_reg(info, IE0, info->ie0_value);
-	}
-
-	if (info->tx_count < WAKEUP_CHARS)
-		info->pending_bh |= BH_TRANSMIT;
-}
-
-static void isr_rxdmaok(SLMP_INFO * info)
-{
-	/* BIT7 = EOT (end of transfer)
-	 * BIT6 = EOM (end of message/frame)
-	 */
-	unsigned char status = read_reg(info,RXDMA + DSR) & 0xc0;
-
-	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
-	write_reg(info, RXDMA + DSR, (unsigned char)(status | 1));
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxdmaok(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	info->pending_bh |= BH_RECEIVE;
-}
-
-static void isr_rxdmaerror(SLMP_INFO * info)
-{
-	/* BIT5 = BOF (buffer overflow)
-	 * BIT4 = COF (counter overflow)
-	 */
-	unsigned char status = read_reg(info,RXDMA + DSR) & 0x30;
-
-	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
-	write_reg(info, RXDMA + DSR, (unsigned char)(status | 1));
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	info->rx_overflow = true;
-	info->pending_bh |= BH_RECEIVE;
-}
-
-static void isr_txdmaok(SLMP_INFO * info)
-{
-	unsigned char status_reg1 = read_reg(info, SR1);
-
-	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
-	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
-	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status_reg1);
-
-	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
-	write_reg16(info, TRC0, 0);
-	info->ie0_value |= TXRDYE;
-	write_reg(info, IE0, info->ie0_value);
-}
-
-static void isr_txdmaerror(SLMP_INFO * info)
-{
-	/* BIT5 = BOF (buffer overflow)
-	 * BIT4 = COF (counter overflow)
-	 */
-	unsigned char status = read_reg(info,TXDMA + DSR) & 0x30;
-
-	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
-	write_reg(info, TXDMA + DSR, (unsigned char)(status | 1));
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txdmaerror(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-}
-
-/* handle input serial signal changes
- */
-static void isr_io_pin( SLMP_INFO *info, u16 status )
-{
- 	struct	mgsl_icount *icount;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):isr_io_pin status=%04X\n",
-			__FILE__,__LINE__,status);
-
-	if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED |
-	              MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) {
-		icount = &info->icount;
-		/* update input line counters */
-		if (status & MISCSTATUS_RI_LATCHED) {
-			icount->rng++;
-			if ( status & SerialSignal_RI )
-				info->input_signal_events.ri_up++;
-			else
-				info->input_signal_events.ri_down++;
-		}
-		if (status & MISCSTATUS_DSR_LATCHED) {
-			icount->dsr++;
-			if ( status & SerialSignal_DSR )
-				info->input_signal_events.dsr_up++;
-			else
-				info->input_signal_events.dsr_down++;
-		}
-		if (status & MISCSTATUS_DCD_LATCHED) {
-			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) {
-				info->ie1_value &= ~CDCD;
-				write_reg(info, IE1, info->ie1_value);
-			}
-			icount->dcd++;
-			if (status & SerialSignal_DCD) {
-				info->input_signal_events.dcd_up++;
-			} else
-				info->input_signal_events.dcd_down++;
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount) {
-				if (status & SerialSignal_DCD)
-					netif_carrier_on(info->netdev);
-				else
-					netif_carrier_off(info->netdev);
-			}
-#endif
-		}
-		if (status & MISCSTATUS_CTS_LATCHED)
-		{
-			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) {
-				info->ie1_value &= ~CCTS;
-				write_reg(info, IE1, info->ie1_value);
-			}
-			icount->cts++;
-			if ( status & SerialSignal_CTS )
-				info->input_signal_events.cts_up++;
-			else
-				info->input_signal_events.cts_down++;
-		}
-		wake_up_interruptible(&info->status_event_wait_q);
-		wake_up_interruptible(&info->event_wait_q);
-
-		if ( (info->port.flags & ASYNC_CHECK_CD) &&
-		     (status & MISCSTATUS_DCD_LATCHED) ) {
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s CD now %s...", info->device_name,
-				       (status & SerialSignal_DCD) ? "on" : "off");
-			if (status & SerialSignal_DCD)
-				wake_up_interruptible(&info->port.open_wait);
-			else {
-				if ( debug_level >= DEBUG_LEVEL_ISR )
-					printk("doing serial hangup...");
-				if (info->port.tty)
-					tty_hangup(info->port.tty);
-			}
-		}
-
-		if ( (info->port.flags & ASYNC_CTS_FLOW) &&
-		     (status & MISCSTATUS_CTS_LATCHED) ) {
-			if ( info->port.tty ) {
-				if (info->port.tty->hw_stopped) {
-					if (status & SerialSignal_CTS) {
-						if ( debug_level >= DEBUG_LEVEL_ISR )
-							printk("CTS tx start...");
-			 			info->port.tty->hw_stopped = 0;
-						tx_start(info);
-						info->pending_bh |= BH_TRANSMIT;
-						return;
-					}
-				} else {
-					if (!(status & SerialSignal_CTS)) {
-						if ( debug_level >= DEBUG_LEVEL_ISR )
-							printk("CTS tx stop...");
-			 			info->port.tty->hw_stopped = 1;
-						tx_stop(info);
-					}
-				}
-			}
-		}
-	}
-
-	info->pending_bh |= BH_STATUS;
-}
-
-/* Interrupt service routine entry point.
- *
- * Arguments:
- * 	irq		interrupt number that caused interrupt
- * 	dev_id		device ID supplied during interrupt registration
- * 	regs		interrupted processor context
- */
-static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id)
-{
-	SLMP_INFO *info = dev_id;
-	unsigned char status, status0, status1=0;
-	unsigned char dmastatus, dmastatus0, dmastatus1=0;
-	unsigned char timerstatus0, timerstatus1=0;
-	unsigned char shift;
-	unsigned int i;
-	unsigned short tmp;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n",
-			__FILE__, __LINE__, info->irq_level);
-
-	spin_lock(&info->lock);
-
-	for(;;) {
-
-		/* get status for SCA0 (ports 0-1) */
-		tmp = read_reg16(info, ISR0);	/* get ISR0 and ISR1 in one read */
-		status0 = (unsigned char)tmp;
-		dmastatus0 = (unsigned char)(tmp>>8);
-		timerstatus0 = read_reg(info, ISR2);
-
-		if ( debug_level >= DEBUG_LEVEL_ISR )
-			printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
-				__FILE__, __LINE__, info->device_name,
-				status0, dmastatus0, timerstatus0);
-
-		if (info->port_count == 4) {
-			/* get status for SCA1 (ports 2-3) */
-			tmp = read_reg16(info->port_array[2], ISR0);
-			status1 = (unsigned char)tmp;
-			dmastatus1 = (unsigned char)(tmp>>8);
-			timerstatus1 = read_reg(info->port_array[2], ISR2);
-
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s(%d):%s status1=%02x, dmastatus1=%02x, timerstatus1=%02x\n",
-					__FILE__,__LINE__,info->device_name,
-					status1,dmastatus1,timerstatus1);
-		}
-
-		if (!status0 && !dmastatus0 && !timerstatus0 &&
-			 !status1 && !dmastatus1 && !timerstatus1)
-			break;
-
-		for(i=0; i < info->port_count ; i++) {
-			if (info->port_array[i] == NULL)
-				continue;
-			if (i < 2) {
-				status = status0;
-				dmastatus = dmastatus0;
-			} else {
-				status = status1;
-				dmastatus = dmastatus1;
-			}
-
-			shift = i & 1 ? 4 :0;
-
-			if (status & BIT0 << shift)
-				isr_rxrdy(info->port_array[i]);
-			if (status & BIT1 << shift)
-				isr_txrdy(info->port_array[i]);
-			if (status & BIT2 << shift)
-				isr_rxint(info->port_array[i]);
-			if (status & BIT3 << shift)
-				isr_txint(info->port_array[i]);
-
-			if (dmastatus & BIT0 << shift)
-				isr_rxdmaerror(info->port_array[i]);
-			if (dmastatus & BIT1 << shift)
-				isr_rxdmaok(info->port_array[i]);
-			if (dmastatus & BIT2 << shift)
-				isr_txdmaerror(info->port_array[i]);
-			if (dmastatus & BIT3 << shift)
-				isr_txdmaok(info->port_array[i]);
-		}
-
-		if (timerstatus0 & (BIT5 | BIT4))
-			isr_timer(info->port_array[0]);
-		if (timerstatus0 & (BIT7 | BIT6))
-			isr_timer(info->port_array[1]);
-		if (timerstatus1 & (BIT5 | BIT4))
-			isr_timer(info->port_array[2]);
-		if (timerstatus1 & (BIT7 | BIT6))
-			isr_timer(info->port_array[3]);
-	}
-
-	for(i=0; i < info->port_count ; i++) {
-		SLMP_INFO * port = info->port_array[i];
-
-		/* Request bottom half processing if there's something
-		 * for it to do and the bh is not already running.
-		 *
-		 * Note: startup adapter diags require interrupts.
-		 * do not request bottom half processing if the
-		 * device is not open in a normal mode.
-		 */
-		if ( port && (port->port.count || port->netcount) &&
-		     port->pending_bh && !port->bh_running &&
-		     !port->bh_requested ) {
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s(%d):%s queueing bh task.\n",
-					__FILE__,__LINE__,port->device_name);
-			schedule_work(&port->task);
-			port->bh_requested = true;
-		}
-	}
-
-	spin_unlock(&info->lock);
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n",
-			__FILE__, __LINE__, info->irq_level);
-	return IRQ_HANDLED;
-}
-
-/* Initialize and start device.
- */
-static int startup(SLMP_INFO * info)
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s tx_releaseup()\n",__FILE__,__LINE__,info->device_name);
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		return 0;
-
-	if (!info->tx_buf) {
-		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
-		if (!info->tx_buf) {
-			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
-				__FILE__,__LINE__,info->device_name);
-			return -ENOMEM;
-		}
-	}
-
-	info->pending_bh = 0;
-
-	memset(&info->icount, 0, sizeof(info->icount));
-
-	/* program hardware for current parameters */
-	reset_port(info);
-
-	change_params(info);
-
-	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
-
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags |= ASYNC_INITIALIZED;
-
-	return 0;
-}
-
-/* Called by close() and hangup() to shutdown hardware
- */
-static void shutdown(SLMP_INFO * info)
-{
-	unsigned long flags;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s synclinkmp_shutdown()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	/* clear status wait queue because status changes */
-	/* can't happen after shutting down the hardware */
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-
-	del_timer(&info->tx_timer);
-	del_timer(&info->status_timer);
-
-	kfree(info->tx_buf);
-	info->tx_buf = NULL;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	reset_port(info);
-
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
- 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		set_signals(info);
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-}
-
-static void program_hw(SLMP_INFO *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	rx_stop(info);
-	tx_stop(info);
-
-	info->tx_count = info->tx_put = info->tx_get = 0;
-
-	if (info->params.mode == MGSL_MODE_HDLC || info->netcount)
-		hdlc_mode(info);
-	else
-		async_mode(info);
-
-	set_signals(info);
-
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-
-	info->ie1_value |= (CDCD|CCTS);
-	write_reg(info, IE1, info->ie1_value);
-
-	get_signals(info);
-
-	if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) )
-		rx_start(info);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Reconfigure adapter based on new parameters
- */
-static void change_params(SLMP_INFO *info)
-{
-	unsigned cflag;
-	int bits_per_char;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s change_params()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	cflag = info->port.tty->termios->c_cflag;
-
-	/* if B0 rate (hangup) specified then negate DTR and RTS */
-	/* otherwise assert DTR and RTS */
- 	if (cflag & CBAUD)
-		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-
-	/* byte size and parity */
-
-	switch (cflag & CSIZE) {
-	      case CS5: info->params.data_bits = 5; break;
-	      case CS6: info->params.data_bits = 6; break;
-	      case CS7: info->params.data_bits = 7; break;
-	      case CS8: info->params.data_bits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  info->params.data_bits = 7; break;
-	      }
-
-	if (cflag & CSTOPB)
-		info->params.stop_bits = 2;
-	else
-		info->params.stop_bits = 1;
-
-	info->params.parity = ASYNC_PARITY_NONE;
-	if (cflag & PARENB) {
-		if (cflag & PARODD)
-			info->params.parity = ASYNC_PARITY_ODD;
-		else
-			info->params.parity = ASYNC_PARITY_EVEN;
-#ifdef CMSPAR
-		if (cflag & CMSPAR)
-			info->params.parity = ASYNC_PARITY_SPACE;
-#endif
-	}
-
-	/* calculate number of jiffies to transmit a full
-	 * FIFO (32 bytes) at specified data rate
-	 */
-	bits_per_char = info->params.data_bits +
-			info->params.stop_bits + 1;
-
-	/* if port data rate is set to 460800 or less then
-	 * allow tty settings to override, otherwise keep the
-	 * current data rate.
-	 */
-	if (info->params.data_rate <= 460800) {
-		info->params.data_rate = tty_get_baud_rate(info->port.tty);
-	}
-
-	if ( info->params.data_rate ) {
-		info->timeout = (32*HZ*bits_per_char) /
-				info->params.data_rate;
-	}
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/* process tty input control flags */
-
-	info->read_status_mask2 = OVRN;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask2 |= PE | FRME;
- 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- 		info->read_status_mask1 |= BRKD;
-	if (I_IGNPAR(info->port.tty))
-		info->ignore_status_mask2 |= PE | FRME;
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask1 |= BRKD;
-		/* If ignoring parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty))
-			info->ignore_status_mask2 |= OVRN;
-	}
-
-	program_hw(info);
-}
-
-static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
-{
-	int err;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s get_params()\n",
-			 __FILE__,__LINE__, info->device_name);
-
-	if (!user_icount) {
-		memset(&info->icount, 0, sizeof(info->icount));
-	} else {
-		mutex_lock(&info->port.mutex);
-		COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
-		mutex_unlock(&info->port.mutex);
-		if (err)
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)
-{
-	int err;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s get_params()\n",
-			 __FILE__,__LINE__, info->device_name);
-
-	mutex_lock(&info->port.mutex);
-	COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
-	mutex_unlock(&info->port.mutex);
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):%s get_params() user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)
-{
- 	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-	int err;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_params\n",
-			__FILE__,__LINE__,info->device_name );
-	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):%s set_params() user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-
-	mutex_lock(&info->port.mutex);
-	spin_lock_irqsave(&info->lock,flags);
-	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
-	spin_unlock_irqrestore(&info->lock,flags);
-
- 	change_params(info);
-	mutex_unlock(&info->port.mutex);
-
-	return 0;
-}
-
-static int get_txidle(SLMP_INFO * info, int __user *idle_mode)
-{
-	int err;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s get_txidle()=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->idle_mode);
-
-	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):%s get_txidle() user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int set_txidle(SLMP_INFO * info, int idle_mode)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_txidle(%d)\n",
-			__FILE__,__LINE__,info->device_name, idle_mode );
-
-	spin_lock_irqsave(&info->lock,flags);
-	info->idle_mode = idle_mode;
-	tx_set_idle( info );
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int tx_enable(SLMP_INFO * info, int enable)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tx_enable(%d)\n",
-			__FILE__,__LINE__,info->device_name, enable);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if ( enable ) {
-		if ( !info->tx_enabled ) {
-			tx_start(info);
-		}
-	} else {
-		if ( info->tx_enabled )
-			tx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/* abort send HDLC frame
- */
-static int tx_abort(SLMP_INFO * info)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tx_abort()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) {
-		info->ie1_value &= ~UDRN;
-		info->ie1_value |= IDLE;
-		write_reg(info, IE1, info->ie1_value);	/* disable tx status interrupts */
-		write_reg(info, SR1, (unsigned char)(IDLE + UDRN));	/* clear pending */
-
-		write_reg(info, TXDMA + DSR, 0);		/* disable DMA channel */
-		write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-   		write_reg(info, CMD, TXABORT);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int rx_enable(SLMP_INFO * info, int enable)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s rx_enable(%d)\n",
-			__FILE__,__LINE__,info->device_name,enable);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if ( enable ) {
-		if ( !info->rx_enabled )
-			rx_start(info);
-	} else {
-		if ( info->rx_enabled )
-			rx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/* wait for specified event to occur
- */
-static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
-{
- 	unsigned long flags;
-	int s;
-	int rc=0;
-	struct mgsl_icount cprev, cnow;
-	int events;
-	int mask;
-	struct	_input_signal_events oldsigs, newsigs;
-	DECLARE_WAITQUEUE(wait, current);
-
-	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
-	if (rc) {
-		return  -EFAULT;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s wait_mgsl_event(%d)\n",
-			__FILE__,__LINE__,info->device_name,mask);
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	/* return immediately if state matches requested events */
-	get_signals(info);
-	s = info->serial_signals;
-
-	events = mask &
-		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
- 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
-		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
-		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
-	if (events) {
-		spin_unlock_irqrestore(&info->lock,flags);
-		goto exit;
-	}
-
-	/* save current irq counts */
-	cprev = info->icount;
-	oldsigs = info->input_signal_events;
-
-	/* enable hunt and idle irqs if needed */
-	if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
-		unsigned char oldval = info->ie1_value;
-		unsigned char newval = oldval +
-			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-			 (mask & MgslEvent_IdleReceived ? IDLD:0);
-		if ( oldval != newval ) {
-			info->ie1_value = newval;
-			write_reg(info, IE1, info->ie1_value);
-		}
-	}
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&info->event_wait_q, &wait);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get current irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		newsigs = info->input_signal_events;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
-		    newsigs.dsr_down == oldsigs.dsr_down &&
-		    newsigs.dcd_up   == oldsigs.dcd_up   &&
-		    newsigs.dcd_down == oldsigs.dcd_down &&
-		    newsigs.cts_up   == oldsigs.cts_up   &&
-		    newsigs.cts_down == oldsigs.cts_down &&
-		    newsigs.ri_up    == oldsigs.ri_up    &&
-		    newsigs.ri_down  == oldsigs.ri_down  &&
-		    cnow.exithunt    == cprev.exithunt   &&
-		    cnow.rxidle      == cprev.rxidle) {
-			rc = -EIO;
-			break;
-		}
-
-		events = mask &
-			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
-			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
-			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
-			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
-			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
-			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
-			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
-			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
-			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
-			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
-		if (events)
-			break;
-
-		cprev = cnow;
-		oldsigs = newsigs;
-	}
-
-	remove_wait_queue(&info->event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-
-
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!waitqueue_active(&info->event_wait_q)) {
-			/* disable enable exit hunt mode/idle rcvd IRQs */
-			info->ie1_value &= ~(FLGD|IDLD);
-			write_reg(info, IE1, info->ie1_value);
-		}
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-exit:
-	if ( rc == 0 )
-		PUT_USER(rc, events, mask_ptr);
-
-	return rc;
-}
-
-static int modem_input_wait(SLMP_INFO *info,int arg)
-{
- 	unsigned long flags;
-	int rc;
-	struct mgsl_icount cprev, cnow;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* save current irq counts */
-	spin_lock_irqsave(&info->lock,flags);
-	cprev = info->icount;
-	add_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get new irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-			rc = -EIO;
-			break;
-		}
-
-		/* check for change in caller specified modem input */
-		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
-		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
-		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
-		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
-			rc = 0;
-			break;
-		}
-
-		cprev = cnow;
-	}
-	remove_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-	return rc;
-}
-
-/* return the state of the serial control and status signals
- */
-static int tiocmget(struct tty_struct *tty, struct file *file)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned int result;
- 	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
-		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
-		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
-		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
-		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
-		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmget() value=%08X\n",
-			 __FILE__,__LINE__, info->device_name, result );
-	return result;
-}
-
-/* set modem control signals (DTR/RTS)
- */
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	SLMP_INFO *info = tty->driver_data;
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmset(%x,%x)\n",
-			__FILE__,__LINE__,info->device_name, set, clear);
-
-	if (set & TIOCM_RTS)
-		info->serial_signals |= SerialSignal_RTS;
-	if (set & TIOCM_DTR)
-		info->serial_signals |= SerialSignal_DTR;
-	if (clear & TIOCM_RTS)
-		info->serial_signals &= ~SerialSignal_RTS;
-	if (clear & TIOCM_DTR)
-		info->serial_signals &= ~SerialSignal_DTR;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return 0;
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	SLMP_INFO *info = container_of(port, SLMP_INFO, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
-}
-
-static void dtr_rts(struct tty_port *port, int on)
-{
-	SLMP_INFO *info = container_of(port, SLMP_INFO, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (on)
-		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Block the current process until the specified port is ready to open.
- */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-			   SLMP_INFO *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	bool		do_clocal = false;
-	bool		extra_count = false;
-	unsigned long	flags;
-	int		cd;
-	struct tty_port *port = &info->port;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s block_til_ready()\n",
-			 __FILE__,__LINE__, tty->driver->name );
-
-	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-		/* nonblock mode is set or port is not enabled */
-		/* just verify that callout device is not active */
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = true;
-
-	/* Wait for carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s block_til_ready() before block, count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-	port->blocked_open++;
-
-	while (1) {
-		if (tty->termios->c_cflag & CBAUD)
-			tty_port_raise_dtr_rts(port);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
-			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-					-EAGAIN : -ERESTARTSYS;
-			break;
-		}
-
-		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
- 			break;
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):%s block_til_ready() count=%d\n",
-				 __FILE__,__LINE__, tty->driver->name, port->count );
-
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-
-	if (extra_count)
-		port->count++;
-	port->blocked_open--;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s block_til_ready() after, count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-
-	if (!retval)
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-
-	return retval;
-}
-
-static int alloc_dma_bufs(SLMP_INFO *info)
-{
-	unsigned short BuffersPerFrame;
-	unsigned short BufferCount;
-
-	// Force allocation to start at 64K boundary for each port.
-	// This is necessary because *all* buffer descriptors for a port
-	// *must* be in the same 64K block. All descriptors on a port
-	// share a common 'base' address (upper 8 bits of 24 bits) programmed
-	// into the CBP register.
-	info->port_array[0]->last_mem_alloc = (SCA_MEM_SIZE/4) * info->port_num;
-
-	/* Calculate the number of DMA buffers necessary to hold the */
-	/* largest allowable frame size. Note: If the max frame size is */
-	/* not an even multiple of the DMA buffer size then we need to */
-	/* round the buffer count per frame up one. */
-
-	BuffersPerFrame = (unsigned short)(info->max_frame_size/SCABUFSIZE);
-	if ( info->max_frame_size % SCABUFSIZE )
-		BuffersPerFrame++;
-
-	/* calculate total number of data buffers (SCABUFSIZE) possible
-	 * in one ports memory (SCA_MEM_SIZE/4) after allocating memory
-	 * for the descriptor list (BUFFERLISTSIZE).
-	 */
-	BufferCount = (SCA_MEM_SIZE/4 - BUFFERLISTSIZE)/SCABUFSIZE;
-
-	/* limit number of buffers to maximum amount of descriptors */
-	if (BufferCount > BUFFERLISTSIZE/sizeof(SCADESC))
-		BufferCount = BUFFERLISTSIZE/sizeof(SCADESC);
-
-	/* use enough buffers to transmit one max size frame */
-	info->tx_buf_count = BuffersPerFrame + 1;
-
-	/* never use more than half the available buffers for transmit */
-	if (info->tx_buf_count > (BufferCount/2))
-		info->tx_buf_count = BufferCount/2;
-
-	if (info->tx_buf_count > SCAMAXDESC)
-		info->tx_buf_count = SCAMAXDESC;
-
-	/* use remaining buffers for receive */
-	info->rx_buf_count = BufferCount - info->tx_buf_count;
-
-	if (info->rx_buf_count > SCAMAXDESC)
-		info->rx_buf_count = SCAMAXDESC;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s Allocating %d TX and %d RX DMA buffers.\n",
-			__FILE__,__LINE__, info->device_name,
-			info->tx_buf_count,info->rx_buf_count);
-
-	if ( alloc_buf_list( info ) < 0 ||
-		alloc_frame_bufs(info,
-		  			info->rx_buf_list,
-		  			info->rx_buf_list_ex,
-					info->rx_buf_count) < 0 ||
-		alloc_frame_bufs(info,
-					info->tx_buf_list,
-					info->tx_buf_list_ex,
-					info->tx_buf_count) < 0 ||
-		alloc_tmp_rx_buf(info) < 0 ) {
-		printk("%s(%d):%s Can't allocate DMA buffer memory\n",
-			__FILE__,__LINE__, info->device_name);
-		return -ENOMEM;
-	}
-
-	rx_reset_buffers( info );
-
-	return 0;
-}
-
-/* Allocate DMA buffers for the transmit and receive descriptor lists.
- */
-static int alloc_buf_list(SLMP_INFO *info)
-{
-	unsigned int i;
-
-	/* build list in adapter shared memory */
-	info->buffer_list = info->memory_base + info->port_array[0]->last_mem_alloc;
-	info->buffer_list_phys = info->port_array[0]->last_mem_alloc;
-	info->port_array[0]->last_mem_alloc += BUFFERLISTSIZE;
-
-	memset(info->buffer_list, 0, BUFFERLISTSIZE);
-
-	/* Save virtual address pointers to the receive and */
-	/* transmit buffer lists. (Receive 1st). These pointers will */
-	/* be used by the processor to access the lists. */
-	info->rx_buf_list = (SCADESC *)info->buffer_list;
-
-	info->tx_buf_list = (SCADESC *)info->buffer_list;
-	info->tx_buf_list += info->rx_buf_count;
-
-	/* Build links for circular buffer entry lists (tx and rx)
-	 *
-	 * Note: links are physical addresses read by the SCA device
-	 * to determine the next buffer entry to use.
-	 */
-
-	for ( i = 0; i < info->rx_buf_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->rx_buf_list_ex[i].phys_entry =
-			info->buffer_list_phys + (i * sizeof(SCABUFSIZE));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-		info->rx_buf_list[i].next = info->buffer_list_phys;
-		if ( i < info->rx_buf_count - 1 )
-			info->rx_buf_list[i].next += (i + 1) * sizeof(SCADESC);
-
-		info->rx_buf_list[i].length = SCABUFSIZE;
-	}
-
-	for ( i = 0; i < info->tx_buf_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->tx_buf_list_ex[i].phys_entry = info->buffer_list_phys +
-			((info->rx_buf_count + i) * sizeof(SCADESC));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-
-		info->tx_buf_list[i].next = info->buffer_list_phys +
-			info->rx_buf_count * sizeof(SCADESC);
-
-		if ( i < info->tx_buf_count - 1 )
-			info->tx_buf_list[i].next += (i + 1) * sizeof(SCADESC);
-	}
-
-	return 0;
-}
-
-/* Allocate the frame DMA buffers used by the specified buffer list.
- */
-static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count)
-{
-	int i;
-	unsigned long phys_addr;
-
-	for ( i = 0; i < count; i++ ) {
-		buf_list_ex[i].virt_addr = info->memory_base + info->port_array[0]->last_mem_alloc;
-		phys_addr = info->port_array[0]->last_mem_alloc;
-		info->port_array[0]->last_mem_alloc += SCABUFSIZE;
-
-		buf_list[i].buf_ptr  = (unsigned short)phys_addr;
-		buf_list[i].buf_base = (unsigned char)(phys_addr >> 16);
-	}
-
-	return 0;
-}
-
-static void free_dma_bufs(SLMP_INFO *info)
-{
-	info->buffer_list = NULL;
-	info->rx_buf_list = NULL;
-	info->tx_buf_list = NULL;
-}
-
-/* allocate buffer large enough to hold max_frame_size.
- * This buffer is used to pass an assembled frame to the line discipline.
- */
-static int alloc_tmp_rx_buf(SLMP_INFO *info)
-{
-	info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
-	if (info->tmp_rx_buf == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-static void free_tmp_rx_buf(SLMP_INFO *info)
-{
-	kfree(info->tmp_rx_buf);
-	info->tmp_rx_buf = NULL;
-}
-
-static int claim_resources(SLMP_INFO *info)
-{
-	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->shared_mem_requested = true;
-
-	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->lcr_mem_requested = true;
-
-	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->sca_base_requested = true;
-
-	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->sca_statctrl_requested = true;
-
-	info->memory_base = ioremap_nocache(info->phys_memory_base,
-								SCA_MEM_SIZE);
-	if (!info->memory_base) {
-		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-
-	info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE);
-	if (!info->lcr_base) {
-		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	info->lcr_base += info->lcr_offset;
-
-	info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE);
-	if (!info->sca_base) {
-		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	info->sca_base += info->sca_offset;
-
-	info->statctrl_base = ioremap_nocache(info->phys_statctrl_base,
-								PAGE_SIZE);
-	if (!info->statctrl_base) {
-		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	info->statctrl_base += info->statctrl_offset;
-
-	if ( !memory_test(info) ) {
-		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		info->init_error = DiagStatus_MemoryError;
-		goto errout;
-	}
-
-	return 0;
-
-errout:
-	release_resources( info );
-	return -ENODEV;
-}
-
-static void release_resources(SLMP_INFO *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s release_resources() entry\n",
-			__FILE__,__LINE__,info->device_name );
-
-	if ( info->irq_requested ) {
-		free_irq(info->irq_level, info);
-		info->irq_requested = false;
-	}
-
-	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
-		info->shared_mem_requested = false;
-	}
-	if ( info->lcr_mem_requested ) {
-		release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
-		info->lcr_mem_requested = false;
-	}
-	if ( info->sca_base_requested ) {
-		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
-		info->sca_base_requested = false;
-	}
-	if ( info->sca_statctrl_requested ) {
-		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
-		info->sca_statctrl_requested = false;
-	}
-
-	if (info->memory_base){
-		iounmap(info->memory_base);
-		info->memory_base = NULL;
-	}
-
-	if (info->sca_base) {
-		iounmap(info->sca_base - info->sca_offset);
-		info->sca_base=NULL;
-	}
-
-	if (info->statctrl_base) {
-		iounmap(info->statctrl_base - info->statctrl_offset);
-		info->statctrl_base=NULL;
-	}
-
-	if (info->lcr_base){
-		iounmap(info->lcr_base - info->lcr_offset);
-		info->lcr_base = NULL;
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s release_resources() exit\n",
-			__FILE__,__LINE__,info->device_name );
-}
-
-/* Add the specified device instance data structure to the
- * global linked list of devices and increment the device count.
- */
-static void add_device(SLMP_INFO *info)
-{
-	info->next_device = NULL;
-	info->line = synclinkmp_device_count;
-	sprintf(info->device_name,"ttySLM%dp%d",info->adapter_num,info->port_num);
-
-	if (info->line < MAX_DEVICES) {
-		if (maxframe[info->line])
-			info->max_frame_size = maxframe[info->line];
-	}
-
-	synclinkmp_device_count++;
-
-	if ( !synclinkmp_device_list )
-		synclinkmp_device_list = info;
-	else {
-		SLMP_INFO *current_dev = synclinkmp_device_list;
-		while( current_dev->next_device )
-			current_dev = current_dev->next_device;
-		current_dev->next_device = info;
-	}
-
-	if ( info->max_frame_size < 4096 )
-		info->max_frame_size = 4096;
-	else if ( info->max_frame_size > 65535 )
-		info->max_frame_size = 65535;
-
-	printk( "SyncLink MultiPort %s: "
-		"Mem=(%08x %08X %08x %08X) IRQ=%d MaxFrameSize=%u\n",
-		info->device_name,
-		info->phys_sca_base,
-		info->phys_memory_base,
-		info->phys_statctrl_base,
-		info->phys_lcr_base,
-		info->irq_level,
-		info->max_frame_size );
-
-#if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
-#endif
-}
-
-static const struct tty_port_operations port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-/* Allocate and initialize a device instance structure
- *
- * Return Value:	pointer to SLMP_INFO if success, otherwise NULL
- */
-static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
-{
-	SLMP_INFO *info;
-
-	info = kzalloc(sizeof(SLMP_INFO),
-		 GFP_KERNEL);
-
-	if (!info) {
-		printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n",
-			__FILE__,__LINE__, adapter_num, port_num);
-	} else {
-		tty_port_init(&info->port);
-		info->port.ops = &port_ops;
-		info->magic = MGSL_MAGIC;
-		INIT_WORK(&info->task, bh_handler);
-		info->max_frame_size = 4096;
-		info->port.close_delay = 5*HZ/10;
-		info->port.closing_wait = 30*HZ;
-		init_waitqueue_head(&info->status_event_wait_q);
-		init_waitqueue_head(&info->event_wait_q);
-		spin_lock_init(&info->netlock);
-		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;
-		info->adapter_num = adapter_num;
-		info->port_num = port_num;
-
-		/* Copy configuration info to device instance data */
-		info->irq_level = pdev->irq;
-		info->phys_lcr_base = pci_resource_start(pdev,0);
-		info->phys_sca_base = pci_resource_start(pdev,2);
-		info->phys_memory_base = pci_resource_start(pdev,3);
-		info->phys_statctrl_base = pci_resource_start(pdev,4);
-
-		/* Because veremap only works on page boundaries we must map
-		 * a larger area than is actually implemented for the LCR
-		 * memory range. We map a full page starting at the page boundary.
-		 */
-		info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
-		info->phys_lcr_base &= ~(PAGE_SIZE-1);
-
-		info->sca_offset    = info->phys_sca_base & (PAGE_SIZE-1);
-		info->phys_sca_base &= ~(PAGE_SIZE-1);
-
-		info->statctrl_offset    = info->phys_statctrl_base & (PAGE_SIZE-1);
-		info->phys_statctrl_base &= ~(PAGE_SIZE-1);
-
-		info->bus_type = MGSL_BUS_TYPE_PCI;
-		info->irq_flags = IRQF_SHARED;
-
-		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
-		setup_timer(&info->status_timer, status_timeout,
-				(unsigned long)info);
-
-		/* Store the PCI9050 misc control register value because a flaw
-		 * in the PCI9050 prevents LCR registers from being read if
-		 * BIOS assigns an LCR base address with bit 7 set.
-		 *
-		 * Only the misc control register is accessed for which only
-		 * write access is needed, so set an initial value and change
-		 * bits to the device instance data as we write the value
-		 * to the actual misc control register.
-		 */
-		info->misc_ctrl_value = 0x087e4546;
-
-		/* initial port state is unknown - if startup errors
-		 * occur, init_error will be set to indicate the
-		 * problem. Once the port is fully initialized,
-		 * this value will be set to 0 to indicate the
-		 * port is available.
-		 */
-		info->init_error = -1;
-	}
-
-	return info;
-}
-
-static void device_init(int adapter_num, struct pci_dev *pdev)
-{
-	SLMP_INFO *port_array[SCA_MAX_PORTS];
-	int port;
-
-	/* allocate device instances for up to SCA_MAX_PORTS devices */
-	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
-		port_array[port] = alloc_dev(adapter_num,port,pdev);
-		if( port_array[port] == NULL ) {
-			for ( --port; port >= 0; --port )
-				kfree(port_array[port]);
-			return;
-		}
-	}
-
-	/* give copy of port_array to all ports and add to device list  */
-	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
-		memcpy(port_array[port]->port_array,port_array,sizeof(port_array));
-		add_device( port_array[port] );
-		spin_lock_init(&port_array[port]->lock);
-	}
-
-	/* Allocate and claim adapter resources */
-	if ( !claim_resources(port_array[0]) ) {
-
-		alloc_dma_bufs(port_array[0]);
-
-		/* copy resource information from first port to others */
-		for ( port = 1; port < SCA_MAX_PORTS; ++port ) {
-			port_array[port]->lock  = port_array[0]->lock;
-			port_array[port]->irq_level     = port_array[0]->irq_level;
-			port_array[port]->memory_base   = port_array[0]->memory_base;
-			port_array[port]->sca_base      = port_array[0]->sca_base;
-			port_array[port]->statctrl_base = port_array[0]->statctrl_base;
-			port_array[port]->lcr_base      = port_array[0]->lcr_base;
-			alloc_dma_bufs(port_array[port]);
-		}
-
-		if ( request_irq(port_array[0]->irq_level,
-					synclinkmp_interrupt,
-					port_array[0]->irq_flags,
-					port_array[0]->device_name,
-					port_array[0]) < 0 ) {
-			printk( "%s(%d):%s Cant request interrupt, IRQ=%d\n",
-				__FILE__,__LINE__,
-				port_array[0]->device_name,
-				port_array[0]->irq_level );
-		}
-		else {
-			port_array[0]->irq_requested = true;
-			adapter_test(port_array[0]);
-		}
-	}
-}
-
-static const struct tty_operations ops = {
-	.open = open,
-	.close = close,
-	.write = write,
-	.put_char = put_char,
-	.flush_chars = flush_chars,
-	.write_room = write_room,
-	.chars_in_buffer = chars_in_buffer,
-	.flush_buffer = flush_buffer,
-	.ioctl = ioctl,
-	.throttle = throttle,
-	.unthrottle = unthrottle,
-	.send_xchar = send_xchar,
-	.break_ctl = set_break,
-	.wait_until_sent = wait_until_sent,
-	.set_termios = set_termios,
-	.stop = tx_hold,
-	.start = tx_release,
-	.hangup = hangup,
-	.tiocmget = tiocmget,
-	.tiocmset = tiocmset,
-	.get_icount = get_icount,
-	.proc_fops = &synclinkmp_proc_fops,
-};
-
-
-static void synclinkmp_cleanup(void)
-{
-	int rc;
-	SLMP_INFO *info;
-	SLMP_INFO *tmp;
-
-	printk("Unloading %s %s\n", driver_name, driver_version);
-
-	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
-			printk("%s(%d) failed to unregister tty driver err=%d\n",
-			       __FILE__,__LINE__,rc);
-		put_tty_driver(serial_driver);
-	}
-
-	/* reset devices */
-	info = synclinkmp_device_list;
-	while(info) {
-		reset_port(info);
-		info = info->next_device;
-	}
-
-	/* release devices */
-	info = synclinkmp_device_list;
-	while(info) {
-#if SYNCLINK_GENERIC_HDLC
-		hdlcdev_exit(info);
-#endif
-		free_dma_bufs(info);
-		free_tmp_rx_buf(info);
-		if ( info->port_num == 0 ) {
-			if (info->sca_base)
-				write_reg(info, LPR, 1); /* set low power mode */
-			release_resources(info);
-		}
-		tmp = info;
-		info = info->next_device;
-		kfree(tmp);
-	}
-
-	pci_unregister_driver(&synclinkmp_pci_driver);
-}
-
-/* Driver initialization entry point.
- */
-
-static int __init synclinkmp_init(void)
-{
-	int rc;
-
-	if (break_on_load) {
-	 	synclinkmp_get_text_ptr();
-  		BREAKPOINT();
-	}
-
- 	printk("%s %s\n", driver_name, driver_version);
-
-	if ((rc = pci_register_driver(&synclinkmp_pci_driver)) < 0) {
-		printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
-		return rc;
-	}
-
-	serial_driver = alloc_tty_driver(128);
-	if (!serial_driver) {
-		rc = -ENOMEM;
-		goto error;
-	}
-
-	/* Initialize the tty_driver structure */
-
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = "synclinkmp";
-	serial_driver->name = "ttySLM";
-	serial_driver->major = ttymajor;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->init_termios.c_ispeed = 9600;
-	serial_driver->init_termios.c_ospeed = 9600;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(serial_driver, &ops);
-	if ((rc = tty_register_driver(serial_driver)) < 0) {
-		printk("%s(%d):Couldn't register serial driver\n",
-			__FILE__,__LINE__);
-		put_tty_driver(serial_driver);
-		serial_driver = NULL;
-		goto error;
-	}
-
- 	printk("%s %s, tty major#%d\n",
-		driver_name, driver_version,
-		serial_driver->major);
-
-	return 0;
-
-error:
-	synclinkmp_cleanup();
-	return rc;
-}
-
-static void __exit synclinkmp_exit(void)
-{
-	synclinkmp_cleanup();
-}
-
-module_init(synclinkmp_init);
-module_exit(synclinkmp_exit);
-
-/* Set the port for internal loopback mode.
- * The TxCLK and RxCLK signals are generated from the BRG and
- * the TxD is looped back to the RxD internally.
- */
-static void enable_loopback(SLMP_INFO *info, int enable)
-{
-	if (enable) {
-		/* MD2 (Mode Register 2)
-		 * 01..00  CNCT<1..0> Channel Connection 11=Local Loopback
-		 */
-		write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) | (BIT1 + BIT0)));
-
-		/* degate external TxC clock source */
-		info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
-		write_control_reg(info);
-
-		/* RXS/TXS (Rx/Tx clock source)
-		 * 07      Reserved, must be 0
-		 * 06..04  Clock Source, 100=BRG
-		 * 03..00  Clock Divisor, 0000=1
-		 */
-		write_reg(info, RXS, 0x40);
-		write_reg(info, TXS, 0x40);
-
-	} else {
-		/* MD2 (Mode Register 2)
-	 	 * 01..00  CNCT<1..0> Channel connection, 0=normal
-		 */
-		write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) & ~(BIT1 + BIT0)));
-
-		/* RXS/TXS (Rx/Tx clock source)
-		 * 07      Reserved, must be 0
-		 * 06..04  Clock Source, 000=RxC/TxC Pin
-		 * 03..00  Clock Divisor, 0000=1
-		 */
-		write_reg(info, RXS, 0x00);
-		write_reg(info, TXS, 0x00);
-	}
-
-	/* set LinkSpeed if available, otherwise default to 2Mbps */
-	if (info->params.clock_speed)
-		set_rate(info, info->params.clock_speed);
-	else
-		set_rate(info, 3686400);
-}
-
-/* Set the baud rate register to the desired speed
- *
- *	data_rate	data rate of clock in bits per second
- *			A data rate of 0 disables the AUX clock.
- */
-static void set_rate( SLMP_INFO *info, u32 data_rate )
-{
-       	u32 TMCValue;
-       	unsigned char BRValue;
-	u32 Divisor=0;
-
-	/* fBRG = fCLK/(TMC * 2^BR)
-	 */
-	if (data_rate != 0) {
-		Divisor = 14745600/data_rate;
-		if (!Divisor)
-			Divisor = 1;
-
-		TMCValue = Divisor;
-
-		BRValue = 0;
-		if (TMCValue != 1 && TMCValue != 2) {
-			/* BRValue of 0 provides 50/50 duty cycle *only* when
-			 * TMCValue is 1 or 2. BRValue of 1 to 9 always provides
-			 * 50/50 duty cycle.
-			 */
-			BRValue = 1;
-			TMCValue >>= 1;
-		}
-
-		/* while TMCValue is too big for TMC register, divide
-		 * by 2 and increment BR exponent.
-		 */
-		for(; TMCValue > 256 && BRValue < 10; BRValue++)
-			TMCValue >>= 1;
-
-		write_reg(info, TXS,
-			(unsigned char)((read_reg(info, TXS) & 0xf0) | BRValue));
-		write_reg(info, RXS,
-			(unsigned char)((read_reg(info, RXS) & 0xf0) | BRValue));
-		write_reg(info, TMC, (unsigned char)TMCValue);
-	}
-	else {
-		write_reg(info, TXS,0);
-		write_reg(info, RXS,0);
-		write_reg(info, TMC, 0);
-	}
-}
-
-/* Disable receiver
- */
-static void rx_stop(SLMP_INFO *info)
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s rx_stop()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	write_reg(info, CMD, RXRESET);
-
-	info->ie0_value &= ~RXRDYE;
-	write_reg(info, IE0, info->ie0_value);	/* disable Rx data interrupts */
-
-	write_reg(info, RXDMA + DSR, 0);	/* disable Rx DMA */
-	write_reg(info, RXDMA + DCMD, SWABORT);	/* reset/init Rx DMA */
-	write_reg(info, RXDMA + DIR, 0);	/* disable Rx DMA interrupts */
-
-	info->rx_enabled = false;
-	info->rx_overflow = false;
-}
-
-/* enable the receiver
- */
-static void rx_start(SLMP_INFO *info)
-{
-	int i;
-
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s rx_start()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	write_reg(info, CMD, RXRESET);
-
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
-		/* HDLC, disabe IRQ on rxdata */
-		info->ie0_value &= ~RXRDYE;
-		write_reg(info, IE0, info->ie0_value);
-
-		/* Reset all Rx DMA buffers and program rx dma */
-		write_reg(info, RXDMA + DSR, 0);		/* disable Rx DMA */
-		write_reg(info, RXDMA + DCMD, SWABORT);	/* reset/init Rx DMA */
-
-		for (i = 0; i < info->rx_buf_count; i++) {
-			info->rx_buf_list[i].status = 0xff;
-
-			// throttle to 4 shared memory writes at a time to prevent
-			// hogging local bus (keep latency time for DMA requests low).
-			if (!(i % 4))
-				read_status_reg(info);
-		}
-		info->current_rx_buf = 0;
-
-		/* set current/1st descriptor address */
-		write_reg16(info, RXDMA + CDA,
-			info->rx_buf_list_ex[0].phys_entry);
-
-		/* set new last rx descriptor address */
-		write_reg16(info, RXDMA + EDA,
-			info->rx_buf_list_ex[info->rx_buf_count - 1].phys_entry);
-
-		/* set buffer length (shared by all rx dma data buffers) */
-		write_reg16(info, RXDMA + BFL, SCABUFSIZE);
-
-		write_reg(info, RXDMA + DIR, 0x60);	/* enable Rx DMA interrupts (EOM/BOF) */
-		write_reg(info, RXDMA + DSR, 0xf2);	/* clear Rx DMA IRQs, enable Rx DMA */
-	} else {
-		/* async, enable IRQ on rxdata */
-		info->ie0_value |= RXRDYE;
-		write_reg(info, IE0, info->ie0_value);
-	}
-
-	write_reg(info, CMD, RXENABLE);
-
-	info->rx_overflow = false;
-	info->rx_enabled = true;
-}
-
-/* Enable the transmitter and send a transmit frame if
- * one is loaded in the DMA buffers.
- */
-static void tx_start(SLMP_INFO *info)
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s tx_start() tx_count=%d\n",
-			 __FILE__,__LINE__, info->device_name,info->tx_count );
-
-	if (!info->tx_enabled ) {
-		write_reg(info, CMD, TXRESET);
-		write_reg(info, CMD, TXENABLE);
-		info->tx_enabled = true;
-	}
-
-	if ( info->tx_count ) {
-
-		/* If auto RTS enabled and RTS is inactive, then assert */
-		/* RTS and set a flag indicating that the driver should */
-		/* negate RTS when the transmission completes. */
-
-		info->drop_rts_on_tx_done = false;
-
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-
-			if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
-				get_signals( info );
-				if ( !(info->serial_signals & SerialSignal_RTS) ) {
-					info->serial_signals |= SerialSignal_RTS;
-					set_signals( info );
-					info->drop_rts_on_tx_done = true;
-				}
-			}
-
-			write_reg16(info, TRC0,
-				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
-
-			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
-			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-	
-			/* set TX CDA (current descriptor address) */
-			write_reg16(info, TXDMA + CDA,
-				info->tx_buf_list_ex[0].phys_entry);
-	
-			/* set TX EDA (last descriptor address) */
-			write_reg16(info, TXDMA + EDA,
-				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
-	
-			/* enable underrun IRQ */
-			info->ie1_value &= ~IDLE;
-			info->ie1_value |= UDRN;
-			write_reg(info, IE1, info->ie1_value);
-			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
-	
-			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
-			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
-	
-			mod_timer(&info->tx_timer, jiffies +
-					msecs_to_jiffies(5000));
-		}
-		else {
-			tx_load_fifo(info);
-			/* async, enable IRQ on txdata */
-			info->ie0_value |= TXRDYE;
-			write_reg(info, IE0, info->ie0_value);
-		}
-
-		info->tx_active = true;
-	}
-}
-
-/* stop the transmitter and DMA
- */
-static void tx_stop( SLMP_INFO *info )
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s tx_stop()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	del_timer(&info->tx_timer);
-
-	write_reg(info, TXDMA + DSR, 0);		/* disable DMA channel */
-	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-	write_reg(info, CMD, TXRESET);
-
-	info->ie1_value &= ~(UDRN + IDLE);
-	write_reg(info, IE1, info->ie1_value);	/* disable tx status interrupts */
-	write_reg(info, SR1, (unsigned char)(IDLE + UDRN));	/* clear pending */
-
-	info->ie0_value &= ~TXRDYE;
-	write_reg(info, IE0, info->ie0_value);	/* disable tx data interrupts */
-
-	info->tx_enabled = false;
-	info->tx_active = false;
-}
-
-/* Fill the transmit FIFO until the FIFO is full or
- * there is no more data to load.
- */
-static void tx_load_fifo(SLMP_INFO *info)
-{
-	u8 TwoBytes[2];
-
-	/* do nothing is now tx data available and no XON/XOFF pending */
-
-	if ( !info->tx_count && !info->x_char )
-		return;
-
-	/* load the Transmit FIFO until FIFOs full or all data sent */
-
-	while( info->tx_count && (read_reg(info,SR0) & BIT1) ) {
-
-		/* there is more space in the transmit FIFO and */
-		/* there is more data in transmit buffer */
-
-		if ( (info->tx_count > 1) && !info->x_char ) {
- 			/* write 16-bits */
-			TwoBytes[0] = info->tx_buf[info->tx_get++];
-			if (info->tx_get >= info->max_frame_size)
-				info->tx_get -= info->max_frame_size;
-			TwoBytes[1] = info->tx_buf[info->tx_get++];
-			if (info->tx_get >= info->max_frame_size)
-				info->tx_get -= info->max_frame_size;
-
-			write_reg16(info, TRB, *((u16 *)TwoBytes));
-
-			info->tx_count -= 2;
-			info->icount.tx += 2;
-		} else {
-			/* only 1 byte left to transmit or 1 FIFO slot left */
-
-			if (info->x_char) {
-				/* transmit pending high priority char */
-				write_reg(info, TRB, info->x_char);
-				info->x_char = 0;
-			} else {
-				write_reg(info, TRB, info->tx_buf[info->tx_get++]);
-				if (info->tx_get >= info->max_frame_size)
-					info->tx_get -= info->max_frame_size;
-				info->tx_count--;
-			}
-			info->icount.tx++;
-		}
-	}
-}
-
-/* Reset a port to a known state
- */
-static void reset_port(SLMP_INFO *info)
-{
-	if (info->sca_base) {
-
-		tx_stop(info);
-		rx_stop(info);
-
-		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		set_signals(info);
-
-		/* disable all port interrupts */
-		info->ie0_value = 0;
-		info->ie1_value = 0;
-		info->ie2_value = 0;
-		write_reg(info, IE0, info->ie0_value);
-		write_reg(info, IE1, info->ie1_value);
-		write_reg(info, IE2, info->ie2_value);
-
-		write_reg(info, CMD, CHRESET);
-	}
-}
-
-/* Reset all the ports to a known state.
- */
-static void reset_adapter(SLMP_INFO *info)
-{
-	int i;
-
-	for ( i=0; i < SCA_MAX_PORTS; ++i) {
-		if (info->port_array[i])
-			reset_port(info->port_array[i]);
-	}
-}
-
-/* Program port for asynchronous communications.
- */
-static void async_mode(SLMP_INFO *info)
-{
-
-  	unsigned char RegValue;
-
-	tx_stop(info);
-	rx_stop(info);
-
-	/* MD0, Mode Register 0
-	 *
-	 * 07..05  PRCTL<2..0>, Protocol Mode, 000=async
-	 * 04      AUTO, Auto-enable (RTS/CTS/DCD)
-	 * 03      Reserved, must be 0
-	 * 02      CRCCC, CRC Calculation, 0=disabled
-	 * 01..00  STOP<1..0> Stop bits (00=1,10=2)
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	if (info->params.stop_bits != 1)
-		RegValue |= BIT1;
-	write_reg(info, MD0, RegValue);
-
-	/* MD1, Mode Register 1
-	 *
-	 * 07..06  BRATE<1..0>, bit rate, 00=1/1 01=1/16 10=1/32 11=1/64
-	 * 05..04  TXCHR<1..0>, tx char size, 00=8 bits,01=7,10=6,11=5
-	 * 03..02  RXCHR<1..0>, rx char size
-	 * 01..00  PMPM<1..0>, Parity mode, 00=none 10=even 11=odd
-	 *
-	 * 0100 0000
-	 */
-	RegValue = 0x40;
-	switch (info->params.data_bits) {
-	case 7: RegValue |= BIT4 + BIT2; break;
-	case 6: RegValue |= BIT5 + BIT3; break;
-	case 5: RegValue |= BIT5 + BIT4 + BIT3 + BIT2; break;
-	}
-	if (info->params.parity != ASYNC_PARITY_NONE) {
-		RegValue |= BIT1;
-		if (info->params.parity == ASYNC_PARITY_ODD)
-			RegValue |= BIT0;
-	}
-	write_reg(info, MD1, RegValue);
-
-	/* MD2, Mode Register 2
-	 *
-	 * 07..02  Reserved, must be 0
-	 * 01..00  CNCT<1..0> Channel connection, 00=normal 11=local loopback
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	if (info->params.loopback)
-		RegValue |= (BIT1 + BIT0);
-	write_reg(info, MD2, RegValue);
-
-	/* RXS, Receive clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=BIT6;
-	write_reg(info, RXS, RegValue);
-
-	/* TXS, Transmit clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=BIT6;
-	write_reg(info, TXS, RegValue);
-
-	/* Control Register
-	 *
-	 * 6,4,2,0  CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out
-	 */
-	info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
-	write_control_reg(info);
-
-	tx_set_idle(info);
-
-	/* RRC Receive Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte
-	 */
-	write_reg(info, RRC, 0x00);
-
-	/* TRC0 Transmit Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger active 0x10 = 16 bytes
-	 */
-	write_reg(info, TRC0, 0x10);
-
-	/* TRC1 Transmit Ready Control 1
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger inactive 0x1e = 31 bytes (full-1)
-	 */
-	write_reg(info, TRC1, 0x1e);
-
-	/* CTL, MSCI control register
-	 *
-	 * 07..06  Reserved, set to 0
-	 * 05      UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC)
-	 * 04      IDLC, idle control, 0=mark 1=idle register
-	 * 03      BRK, break, 0=off 1 =on (async)
-	 * 02      SYNCLD, sync char load enable (BSC) 1=enabled
-	 * 01      GOP, go active on poll (LOOP mode) 1=enabled
-	 * 00      RTS, RTS output control, 0=active 1=inactive
-	 *
-	 * 0001 0001
-	 */
-	RegValue = 0x10;
-	if (!(info->serial_signals & SerialSignal_RTS))
-		RegValue |= 0x01;
-	write_reg(info, CTL, RegValue);
-
-	/* enable status interrupts */
-	info->ie0_value |= TXINTE + RXINTE;
-	write_reg(info, IE0, info->ie0_value);
-
-	/* enable break detect interrupt */
-	info->ie1_value = BRKD;
-	write_reg(info, IE1, info->ie1_value);
-
-	/* enable rx overrun interrupt */
-	info->ie2_value = OVRN;
-	write_reg(info, IE2, info->ie2_value);
-
-	set_rate( info, info->params.data_rate * 16 );
-}
-
-/* Program the SCA for HDLC communications.
- */
-static void hdlc_mode(SLMP_INFO *info)
-{
-	unsigned char RegValue;
-	u32 DpllDivisor;
-
-	// Can't use DPLL because SCA outputs recovered clock on RxC when
-	// DPLL mode selected. This causes output contention with RxC receiver.
-	// Use of DPLL would require external hardware to disable RxC receiver
-	// when DPLL mode selected.
-	info->params.flags &= ~(HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL);
-
-	/* disable DMA interrupts */
-	write_reg(info, TXDMA + DIR, 0);
-	write_reg(info, RXDMA + DIR, 0);
-
-	/* MD0, Mode Register 0
-	 *
-	 * 07..05  PRCTL<2..0>, Protocol Mode, 100=HDLC
-	 * 04      AUTO, Auto-enable (RTS/CTS/DCD)
-	 * 03      Reserved, must be 0
-	 * 02      CRCCC, CRC Calculation, 1=enabled
-	 * 01      CRC1, CRC selection, 0=CRC-16,1=CRC-CCITT-16
-	 * 00      CRC0, CRC initial value, 1 = all 1s
-	 *
-	 * 1000 0001
-	 */
-	RegValue = 0x81;
-	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
-		RegValue |= BIT4;
-	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
-		RegValue |= BIT4;
-	if (info->params.crc_type == HDLC_CRC_16_CCITT)
-		RegValue |= BIT2 + BIT1;
-	write_reg(info, MD0, RegValue);
-
-	/* MD1, Mode Register 1
-	 *
-	 * 07..06  ADDRS<1..0>, Address detect, 00=no addr check
-	 * 05..04  TXCHR<1..0>, tx char size, 00=8 bits
-	 * 03..02  RXCHR<1..0>, rx char size, 00=8 bits
-	 * 01..00  PMPM<1..0>, Parity mode, 00=no parity
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	write_reg(info, MD1, RegValue);
-
-	/* MD2, Mode Register 2
-	 *
-	 * 07      NRZFM, 0=NRZ, 1=FM
-	 * 06..05  CODE<1..0> Encoding, 00=NRZ
-	 * 04..03  DRATE<1..0> DPLL Divisor, 00=8
-	 * 02      Reserved, must be 0
-	 * 01..00  CNCT<1..0> Channel connection, 0=normal
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	switch(info->params.encoding) {
-	case HDLC_ENCODING_NRZI:	  RegValue |= BIT5; break;
-	case HDLC_ENCODING_BIPHASE_MARK:  RegValue |= BIT7 + BIT5; break; /* aka FM1 */
-	case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT7 + BIT6; break; /* aka FM0 */
-	case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT7; break; 	/* aka Manchester */
-#if 0
-	case HDLC_ENCODING_NRZB:	       				/* not supported */
-	case HDLC_ENCODING_NRZI_MARK:          				/* not supported */
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: 				/* not supported */
-#endif
-	}
-	if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
-		DpllDivisor = 16;
-		RegValue |= BIT3;
-	} else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) {
-		DpllDivisor = 8;
-	} else {
-		DpllDivisor = 32;
-		RegValue |= BIT4;
-	}
-	write_reg(info, MD2, RegValue);
-
-
-	/* RXS, Receive clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=0;
-	if (info->params.flags & HDLC_FLAG_RXC_BRG)
-		RegValue |= BIT6;
-	if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-		RegValue |= BIT6 + BIT5;
-	write_reg(info, RXS, RegValue);
-
-	/* TXS, Transmit clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=0;
-	if (info->params.flags & HDLC_FLAG_TXC_BRG)
-		RegValue |= BIT6;
-	if (info->params.flags & HDLC_FLAG_TXC_DPLL)
-		RegValue |= BIT6 + BIT5;
-	write_reg(info, TXS, RegValue);
-
-	if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-		set_rate(info, info->params.clock_speed * DpllDivisor);
-	else
-		set_rate(info, info->params.clock_speed);
-
-	/* GPDATA (General Purpose I/O Data Register)
-	 *
-	 * 6,4,2,0  CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out
-	 */
-	if (info->params.flags & HDLC_FLAG_TXC_BRG)
-		info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
-	else
-		info->port_array[0]->ctrlreg_value &= ~(BIT0 << (info->port_num * 2));
-	write_control_reg(info);
-
-	/* RRC Receive Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  RRC<4..0> Rx FIFO trigger active
-	 */
-	write_reg(info, RRC, rx_active_fifo_level);
-
-	/* TRC0 Transmit Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger active
-	 */
-	write_reg(info, TRC0, tx_active_fifo_level);
-
-	/* TRC1 Transmit Ready Control 1
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger inactive 0x1f = 32 bytes (full)
-	 */
-	write_reg(info, TRC1, (unsigned char)(tx_negate_fifo_level - 1));
-
-	/* DMR, DMA Mode Register
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04      TMOD, Transfer Mode: 1=chained-block
-	 * 03      Reserved, must be 0
-	 * 02      NF, Number of Frames: 1=multi-frame
-	 * 01      CNTE, Frame End IRQ Counter enable: 0=disabled
-	 * 00      Reserved, must be 0
-	 *
-	 * 0001 0100
-	 */
-	write_reg(info, TXDMA + DMR, 0x14);
-	write_reg(info, RXDMA + DMR, 0x14);
-
-	/* Set chain pointer base (upper 8 bits of 24 bit addr) */
-	write_reg(info, RXDMA + CPB,
-		(unsigned char)(info->buffer_list_phys >> 16));
-
-	/* Set chain pointer base (upper 8 bits of 24 bit addr) */
-	write_reg(info, TXDMA + CPB,
-		(unsigned char)(info->buffer_list_phys >> 16));
-
-	/* enable status interrupts. other code enables/disables
-	 * the individual sources for these two interrupt classes.
-	 */
-	info->ie0_value |= TXINTE + RXINTE;
-	write_reg(info, IE0, info->ie0_value);
-
-	/* CTL, MSCI control register
-	 *
-	 * 07..06  Reserved, set to 0
-	 * 05      UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC)
-	 * 04      IDLC, idle control, 0=mark 1=idle register
-	 * 03      BRK, break, 0=off 1 =on (async)
-	 * 02      SYNCLD, sync char load enable (BSC) 1=enabled
-	 * 01      GOP, go active on poll (LOOP mode) 1=enabled
-	 * 00      RTS, RTS output control, 0=active 1=inactive
-	 *
-	 * 0001 0001
-	 */
-	RegValue = 0x10;
-	if (!(info->serial_signals & SerialSignal_RTS))
-		RegValue |= 0x01;
-	write_reg(info, CTL, RegValue);
-
-	/* preamble not supported ! */
-
-	tx_set_idle(info);
-	tx_stop(info);
-	rx_stop(info);
-
-	set_rate(info, info->params.clock_speed);
-
-	if (info->params.loopback)
-		enable_loopback(info,1);
-}
-
-/* Set the transmit HDLC idle mode
- */
-static void tx_set_idle(SLMP_INFO *info)
-{
-	unsigned char RegValue = 0xff;
-
-	/* Map API idle mode to SCA register bits */
-	switch(info->idle_mode) {
-	case HDLC_TXIDLE_FLAGS:			RegValue = 0x7e; break;
-	case HDLC_TXIDLE_ALT_ZEROS_ONES:	RegValue = 0xaa; break;
-	case HDLC_TXIDLE_ZEROS:			RegValue = 0x00; break;
-	case HDLC_TXIDLE_ONES:			RegValue = 0xff; break;
-	case HDLC_TXIDLE_ALT_MARK_SPACE:	RegValue = 0xaa; break;
-	case HDLC_TXIDLE_SPACE:			RegValue = 0x00; break;
-	case HDLC_TXIDLE_MARK:			RegValue = 0xff; break;
-	}
-
-	write_reg(info, IDL, RegValue);
-}
-
-/* Query the adapter for the state of the V24 status (input) signals.
- */
-static void get_signals(SLMP_INFO *info)
-{
-	u16 status = read_reg(info, SR3);
-	u16 gpstatus = read_status_reg(info);
-	u16 testbit;
-
-	/* clear all serial signals except DTR and RTS */
-	info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
-
-	/* set serial signal bits to reflect MISR */
-
-	if (!(status & BIT3))
-		info->serial_signals |= SerialSignal_CTS;
-
-	if ( !(status & BIT2))
-		info->serial_signals |= SerialSignal_DCD;
-
-	testbit = BIT1 << (info->port_num * 2); // Port 0..3 RI is GPDATA<1,3,5,7>
-	if (!(gpstatus & testbit))
-		info->serial_signals |= SerialSignal_RI;
-
-	testbit = BIT0 << (info->port_num * 2); // Port 0..3 DSR is GPDATA<0,2,4,6>
-	if (!(gpstatus & testbit))
-		info->serial_signals |= SerialSignal_DSR;
-}
-
-/* Set the state of DTR and RTS based on contents of
- * serial_signals member of device context.
- */
-static void set_signals(SLMP_INFO *info)
-{
-	unsigned char RegValue;
-	u16 EnableBit;
-
-	RegValue = read_reg(info, CTL);
-	if (info->serial_signals & SerialSignal_RTS)
-		RegValue &= ~BIT0;
-	else
-		RegValue |= BIT0;
-	write_reg(info, CTL, RegValue);
-
-	// Port 0..3 DTR is ctrl reg <1,3,5,7>
-	EnableBit = BIT1 << (info->port_num*2);
-	if (info->serial_signals & SerialSignal_DTR)
-		info->port_array[0]->ctrlreg_value &= ~EnableBit;
-	else
-		info->port_array[0]->ctrlreg_value |= EnableBit;
-	write_control_reg(info);
-}
-
-/*******************/
-/* DMA Buffer Code */
-/*******************/
-
-/* Set the count for all receive buffers to SCABUFSIZE
- * and set the current buffer to the first buffer. This effectively
- * makes all buffers free and discards any data in buffers.
- */
-static void rx_reset_buffers(SLMP_INFO *info)
-{
-	rx_free_frame_buffers(info, 0, info->rx_buf_count - 1);
-}
-
-/* Free the buffers used by a received frame
- *
- * info   pointer to device instance data
- * first  index of 1st receive buffer of frame
- * last   index of last receive buffer of frame
- */
-static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last)
-{
-	bool done = false;
-
-	while(!done) {
-	        /* reset current buffer for reuse */
-		info->rx_buf_list[first].status = 0xff;
-
-	        if (first == last) {
-	                done = true;
-	                /* set new last rx descriptor address */
-			write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry);
-	        }
-
-	        first++;
-		if (first == info->rx_buf_count)
-			first = 0;
-	}
-
-	/* set current buffer to next buffer after last buffer of frame */
-	info->current_rx_buf = first;
-}
-
-/* Return a received frame from the receive DMA buffers.
- * Only frames received without errors are returned.
- *
- * Return Value:	true if frame returned, otherwise false
- */
-static bool rx_get_frame(SLMP_INFO *info)
-{
-	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
-	unsigned short status;
-	unsigned int framesize = 0;
-	bool ReturnCode = false;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-	unsigned char addr_field = 0xff;
-   	SCADESC *desc;
-	SCADESC_EX *desc_ex;
-
-CheckAgain:
-	/* assume no frame returned, set zero length */
-	framesize = 0;
-	addr_field = 0xff;
-
-	/*
-	 * current_rx_buf points to the 1st buffer of the next available
-	 * receive frame. To find the last buffer of the frame look for
-	 * a non-zero status field in the buffer entries. (The status
-	 * field is set by the 16C32 after completing a receive frame.
-	 */
-	StartIndex = EndIndex = info->current_rx_buf;
-
-	for ( ;; ) {
-		desc = &info->rx_buf_list[EndIndex];
-		desc_ex = &info->rx_buf_list_ex[EndIndex];
-
-		if (desc->status == 0xff)
-			goto Cleanup;	/* current desc still in use, no frames available */
-
-		if (framesize == 0 && info->params.addr_filter != 0xff)
-			addr_field = desc_ex->virt_addr[0];
-
-		framesize += desc->length;
-
-		/* Status != 0 means last buffer of frame */
-		if (desc->status)
-			break;
-
-		EndIndex++;
-		if (EndIndex == info->rx_buf_count)
-			EndIndex = 0;
-
-		if (EndIndex == info->current_rx_buf) {
-			/* all buffers have been 'used' but none mark	   */
-			/* the end of a frame. Reset buffers and receiver. */
-			if ( info->rx_enabled ){
-				spin_lock_irqsave(&info->lock,flags);
-				rx_start(info);
-				spin_unlock_irqrestore(&info->lock,flags);
-			}
-			goto Cleanup;
-		}
-
-	}
-
-	/* check status of receive frame */
-
-	/* frame status is byte stored after frame data
-	 *
-	 * 7 EOM (end of msg), 1 = last buffer of frame
-	 * 6 Short Frame, 1 = short frame
-	 * 5 Abort, 1 = frame aborted
-	 * 4 Residue, 1 = last byte is partial
-	 * 3 Overrun, 1 = overrun occurred during frame reception
-	 * 2 CRC,     1 = CRC error detected
-	 *
-	 */
-	status = desc->status;
-
-	/* ignore CRC bit if not using CRC (bit is undefined) */
-	/* Note:CRC is not save to data buffer */
-	if (info->params.crc_type == HDLC_CRC_NONE)
-		status &= ~BIT2;
-
-	if (framesize == 0 ||
-		 (addr_field != 0xff && addr_field != info->params.addr_filter)) {
-		/* discard 0 byte frames, this seems to occur sometime
-		 * when remote is idling flags.
-		 */
-		rx_free_frame_buffers(info, StartIndex, EndIndex);
-		goto CheckAgain;
-	}
-
-	if (framesize < 2)
-		status |= BIT6;
-
-	if (status & (BIT6+BIT5+BIT3+BIT2)) {
-		/* received frame has errors,
-		 * update counts and mark frame size as 0
-		 */
-		if (status & BIT6)
-			info->icount.rxshort++;
-		else if (status & BIT5)
-			info->icount.rxabort++;
-		else if (status & BIT3)
-			info->icount.rxover++;
-		else
-			info->icount.rxcrc++;
-
-		framesize = 0;
-#if SYNCLINK_GENERIC_HDLC
-		{
-			info->netdev->stats.rx_errors++;
-			info->netdev->stats.rx_frame_errors++;
-		}
-#endif
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk("%s(%d):%s rx_get_frame() status=%04X size=%d\n",
-			__FILE__,__LINE__,info->device_name,status,framesize);
-
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr,
-			min_t(int, framesize,SCABUFSIZE),0);
-
-	if (framesize) {
-		if (framesize > info->max_frame_size)
-			info->icount.rxlong++;
-		else {
-			/* copy dma buffer(s) to contiguous intermediate buffer */
-			int copy_count = framesize;
-			int index = StartIndex;
-			unsigned char *ptmp = info->tmp_rx_buf;
-			info->tmp_rx_buf_count = framesize;
-
-			info->icount.rxok++;
-
-			while(copy_count) {
-				int partial_count = min(copy_count,SCABUFSIZE);
-				memcpy( ptmp,
-					info->rx_buf_list_ex[index].virt_addr,
-					partial_count );
-				ptmp += partial_count;
-				copy_count -= partial_count;
-
-				if ( ++index == info->rx_buf_count )
-					index = 0;
-			}
-
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount)
-				hdlcdev_rx(info,info->tmp_rx_buf,framesize);
-			else
-#endif
-				ldisc_receive_buf(tty,info->tmp_rx_buf,
-						  info->flag_buf, framesize);
-		}
-	}
-	/* Free the buffers used by this frame. */
-	rx_free_frame_buffers( info, StartIndex, EndIndex );
-
-	ReturnCode = true;
-
-Cleanup:
-	if ( info->rx_enabled && info->rx_overflow ) {
-		/* Receiver is enabled, but needs to restarted due to
-		 * rx buffer overflow. If buffers are empty, restart receiver.
-		 */
-		if (info->rx_buf_list[EndIndex].status == 0xff) {
-			spin_lock_irqsave(&info->lock,flags);
-			rx_start(info);
-			spin_unlock_irqrestore(&info->lock,flags);
-		}
-	}
-
-	return ReturnCode;
-}
-
-/* load the transmit DMA buffer with data
- */
-static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
-{
-	unsigned short copy_count;
-	unsigned int i = 0;
-	SCADESC *desc;
-	SCADESC_EX *desc_ex;
-
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1);
-
-	/* Copy source buffer to one or more DMA buffers, starting with
-	 * the first transmit dma buffer.
-	 */
-	for(i=0;;)
-	{
-		copy_count = min_t(unsigned short,count,SCABUFSIZE);
-
-		desc = &info->tx_buf_list[i];
-		desc_ex = &info->tx_buf_list_ex[i];
-
-		load_pci_memory(info, desc_ex->virt_addr,buf,copy_count);
-
-		desc->length = copy_count;
-		desc->status = 0;
-
-		buf += copy_count;
-		count -= copy_count;
-
-		if (!count)
-			break;
-
-		i++;
-		if (i >= info->tx_buf_count)
-			i = 0;
-	}
-
-	info->tx_buf_list[i].status = 0x81;	/* set EOM and EOT status */
-	info->last_tx_buf = ++i;
-}
-
-static bool register_test(SLMP_INFO *info)
-{
-	static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
-	static unsigned int count = ARRAY_SIZE(testval);
-	unsigned int i;
-	bool rc = true;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-
-	/* assume failure */
-	info->init_error = DiagStatus_AddressFailure;
-
-	/* Write bit patterns to various registers but do it out of */
-	/* sync, then read back and verify values. */
-
-	for (i = 0 ; i < count ; i++) {
-		write_reg(info, TMC, testval[i]);
-		write_reg(info, IDL, testval[(i+1)%count]);
-		write_reg(info, SA0, testval[(i+2)%count]);
-		write_reg(info, SA1, testval[(i+3)%count]);
-
-		if ( (read_reg(info, TMC) != testval[i]) ||
-			  (read_reg(info, IDL) != testval[(i+1)%count]) ||
-			  (read_reg(info, SA0) != testval[(i+2)%count]) ||
-			  (read_reg(info, SA1) != testval[(i+3)%count]) )
-		{
-			rc = false;
-			break;
-		}
-	}
-
-	reset_port(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return rc;
-}
-
-static bool irq_test(SLMP_INFO *info)
-{
-	unsigned long timeout;
-	unsigned long flags;
-
-	unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-
-	/* assume failure */
-	info->init_error = DiagStatus_IrqFailure;
-	info->irq_occurred = false;
-
-	/* setup timer0 on SCA0 to interrupt */
-
-	/* IER2<7..4> = timer<3..0> interrupt enables (1=enabled) */
-	write_reg(info, IER2, (unsigned char)((info->port_num & 1) ? BIT6 : BIT4));
-
-	write_reg(info, (unsigned char)(timer + TEPR), 0);	/* timer expand prescale */
-	write_reg16(info, (unsigned char)(timer + TCONR), 1);	/* timer constant */
-
-
-	/* TMCS, Timer Control/Status Register
-	 *
-	 * 07      CMF, Compare match flag (read only) 1=match
-	 * 06      ECMI, CMF Interrupt Enable: 1=enabled
-	 * 05      Reserved, must be 0
-	 * 04      TME, Timer Enable
-	 * 03..00  Reserved, must be 0
-	 *
-	 * 0101 0000
-	 */
-	write_reg(info, (unsigned char)(timer + TMCS), 0x50);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	timeout=100;
-	while( timeout-- && !info->irq_occurred ) {
-		msleep_interruptible(10);
-	}
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return info->irq_occurred;
-}
-
-/* initialize individual SCA device (2 ports)
- */
-static bool sca_init(SLMP_INFO *info)
-{
-	/* set wait controller to single mem partition (low), no wait states */
-	write_reg(info, PABR0, 0);	/* wait controller addr boundary 0 */
-	write_reg(info, PABR1, 0);	/* wait controller addr boundary 1 */
-	write_reg(info, WCRL, 0);	/* wait controller low range */
-	write_reg(info, WCRM, 0);	/* wait controller mid range */
-	write_reg(info, WCRH, 0);	/* wait controller high range */
-
-	/* DPCR, DMA Priority Control
-	 *
-	 * 07..05  Not used, must be 0
-	 * 04      BRC, bus release condition: 0=all transfers complete
-	 * 03      CCC, channel change condition: 0=every cycle
-	 * 02..00  PR<2..0>, priority 100=round robin
-	 *
-	 * 00000100 = 0x04
-	 */
-	write_reg(info, DPCR, dma_priority);
-
-	/* DMA Master Enable, BIT7: 1=enable all channels */
-	write_reg(info, DMER, 0x80);
-
-	/* enable all interrupt classes */
-	write_reg(info, IER0, 0xff);	/* TxRDY,RxRDY,TxINT,RxINT (ports 0-1) */
-	write_reg(info, IER1, 0xff);	/* DMIB,DMIA (channels 0-3) */
-	write_reg(info, IER2, 0xf0);	/* TIRQ (timers 0-3) */
-
-	/* ITCR, interrupt control register
-	 * 07      IPC, interrupt priority, 0=MSCI->DMA
-	 * 06..05  IAK<1..0>, Acknowledge cycle, 00=non-ack cycle
-	 * 04      VOS, Vector Output, 0=unmodified vector
-	 * 03..00  Reserved, must be 0
-	 */
-	write_reg(info, ITCR, 0);
-
-	return true;
-}
-
-/* initialize adapter hardware
- */
-static bool init_adapter(SLMP_INFO *info)
-{
-	int i;
-
-	/* Set BIT30 of Local Control Reg 0x50 to reset SCA */
-	volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
-	u32 readval;
-
-	info->misc_ctrl_value |= BIT30;
-	*MiscCtrl = info->misc_ctrl_value;
-
-	/*
-	 * Force at least 170ns delay before clearing
-	 * reset bit. Each read from LCR takes at least
-	 * 30ns so 10 times for 300ns to be safe.
-	 */
-	for(i=0;i<10;i++)
-		readval = *MiscCtrl;
-
-	info->misc_ctrl_value &= ~BIT30;
-	*MiscCtrl = info->misc_ctrl_value;
-
-	/* init control reg (all DTRs off, all clksel=input) */
-	info->ctrlreg_value = 0xaa;
-	write_control_reg(info);
-
-	{
-		volatile u32 *LCR1BRDR = (u32 *)(info->lcr_base + 0x2c);
-		lcr1_brdr_value &= ~(BIT5 + BIT4 + BIT3);
-
-		switch(read_ahead_count)
-		{
-		case 16:
-			lcr1_brdr_value |= BIT5 + BIT4 + BIT3;
-			break;
-		case 8:
-			lcr1_brdr_value |= BIT5 + BIT4;
-			break;
-		case 4:
-			lcr1_brdr_value |= BIT5 + BIT3;
-			break;
-		case 0:
-			lcr1_brdr_value |= BIT5;
-			break;
-		}
-
-		*LCR1BRDR = lcr1_brdr_value;
-		*MiscCtrl = misc_ctrl_value;
-	}
-
-	sca_init(info->port_array[0]);
-	sca_init(info->port_array[2]);
-
-	return true;
-}
-
-/* Loopback an HDLC frame to test the hardware
- * interrupt and DMA functions.
- */
-static bool loopback_test(SLMP_INFO *info)
-{
-#define TESTFRAMESIZE 20
-
-	unsigned long timeout;
-	u16 count = TESTFRAMESIZE;
-	unsigned char buf[TESTFRAMESIZE];
-	bool rc = false;
-	unsigned long flags;
-
-	struct tty_struct *oldtty = info->port.tty;
-	u32 speed = info->params.clock_speed;
-
-	info->params.clock_speed = 3686400;
-	info->port.tty = NULL;
-
-	/* assume failure */
-	info->init_error = DiagStatus_DmaFailure;
-
-	/* build and send transmit frame */
-	for (count = 0; count < TESTFRAMESIZE;++count)
-		buf[count] = (unsigned char)count;
-
-	memset(info->tmp_rx_buf,0,TESTFRAMESIZE);
-
-	/* program hardware for HDLC and enabled receiver */
-	spin_lock_irqsave(&info->lock,flags);
-	hdlc_mode(info);
-	enable_loopback(info,1);
-       	rx_start(info);
-	info->tx_count = count;
-	tx_load_dma_buffer(info,buf,count);
-	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	/* wait for receive complete */
-	/* Set a timeout for waiting for interrupt. */
-	for ( timeout = 100; timeout; --timeout ) {
-		msleep_interruptible(10);
-
-		if (rx_get_frame(info)) {
-			rc = true;
-			break;
-		}
-	}
-
-	/* verify received frame length and contents */
-	if (rc &&
-	    ( info->tmp_rx_buf_count != count ||
-	      memcmp(buf, info->tmp_rx_buf,count))) {
-		rc = false;
-	}
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_adapter(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	info->params.clock_speed = speed;
-	info->port.tty = oldtty;
-
-	return rc;
-}
-
-/* Perform diagnostics on hardware
- */
-static int adapter_test( SLMP_INFO *info )
-{
-	unsigned long flags;
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):Testing device %s\n",
-			__FILE__,__LINE__,info->device_name );
-
-	spin_lock_irqsave(&info->lock,flags);
-	init_adapter(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	info->port_array[0]->port_count = 0;
-
-	if ( register_test(info->port_array[0]) &&
-		register_test(info->port_array[1])) {
-
-		info->port_array[0]->port_count = 2;
-
-		if ( register_test(info->port_array[2]) &&
-			register_test(info->port_array[3]) )
-			info->port_array[0]->port_count += 2;
-	}
-	else {
-		printk( "%s(%d):Register test failure for device %s Addr=%08lX\n",
-			__FILE__,__LINE__,info->device_name, (unsigned long)(info->phys_sca_base));
-		return -ENODEV;
-	}
-
-	if ( !irq_test(info->port_array[0]) ||
-		!irq_test(info->port_array[1]) ||
-		 (info->port_count == 4 && !irq_test(info->port_array[2])) ||
-		 (info->port_count == 4 && !irq_test(info->port_array[3]))) {
-		printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );
-		return -ENODEV;
-	}
-
-	if (!loopback_test(info->port_array[0]) ||
-		!loopback_test(info->port_array[1]) ||
-		 (info->port_count == 4 && !loopback_test(info->port_array[2])) ||
-		 (info->port_count == 4 && !loopback_test(info->port_array[3]))) {
-		printk( "%s(%d):DMA test failure for device %s\n",
-			__FILE__,__LINE__,info->device_name);
-		return -ENODEV;
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):device %s passed diagnostics\n",
-			__FILE__,__LINE__,info->device_name );
-
-	info->port_array[0]->init_error = 0;
-	info->port_array[1]->init_error = 0;
-	if ( info->port_count > 2 ) {
-		info->port_array[2]->init_error = 0;
-		info->port_array[3]->init_error = 0;
-	}
-
-	return 0;
-}
-
-/* Test the shared memory on a PCI adapter.
- */
-static bool memory_test(SLMP_INFO *info)
-{
-	static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
-		0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
-	unsigned long count = ARRAY_SIZE(testval);
-	unsigned long i;
-	unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long);
-	unsigned long * addr = (unsigned long *)info->memory_base;
-
-	/* Test data lines with test pattern at one location. */
-
-	for ( i = 0 ; i < count ; i++ ) {
-		*addr = testval[i];
-		if ( *addr != testval[i] )
-			return false;
-	}
-
-	/* Test address lines with incrementing pattern over */
-	/* entire address range. */
-
-	for ( i = 0 ; i < limit ; i++ ) {
-		*addr = i * 4;
-		addr++;
-	}
-
-	addr = (unsigned long *)info->memory_base;
-
-	for ( i = 0 ; i < limit ; i++ ) {
-		if ( *addr != i * 4 )
-			return false;
-		addr++;
-	}
-
-	memset( info->memory_base, 0, SCA_MEM_SIZE );
-	return true;
-}
-
-/* Load data into PCI adapter shared memory.
- *
- * The PCI9050 releases control of the local bus
- * after completing the current read or write operation.
- *
- * While the PCI9050 write FIFO not empty, the
- * PCI9050 treats all of the writes as a single transaction
- * and does not release the bus. This causes DMA latency problems
- * at high speeds when copying large data blocks to the shared memory.
- *
- * This function breaks a write into multiple transations by
- * interleaving a read which flushes the write FIFO and 'completes'
- * the write transation. This allows any pending DMA request to gain control
- * of the local bus in a timely fasion.
- */
-static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count)
-{
-	/* A load interval of 16 allows for 4 32-bit writes at */
-	/* 136ns each for a maximum latency of 542ns on the local bus.*/
-
-	unsigned short interval = count / sca_pci_load_interval;
-	unsigned short i;
-
-	for ( i = 0 ; i < interval ; i++ )
-	{
-		memcpy(dest, src, sca_pci_load_interval);
-		read_status_reg(info);
-		dest += sca_pci_load_interval;
-		src += sca_pci_load_interval;
-	}
-
-	memcpy(dest, src, count % sca_pci_load_interval);
-}
-
-static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit)
-{
-	int i;
-	int linecount;
-	if (xmit)
-		printk("%s tx data:\n",info->device_name);
-	else
-		printk("%s rx data:\n",info->device_name);
-
-	while(count) {
-		if (count > 16)
-			linecount = 16;
-		else
-			linecount = count;
-
-		for(i=0;i<linecount;i++)
-			printk("%02X ",(unsigned char)data[i]);
-		for(;i<17;i++)
-			printk("   ");
-		for(i=0;i<linecount;i++) {
-			if (data[i]>=040 && data[i]<=0176)
-				printk("%c",data[i]);
-			else
-				printk(".");
-		}
-		printk("\n");
-
-		data  += linecount;
-		count -= linecount;
-	}
-}	/* end of trace_block() */
-
-/* called when HDLC frame times out
- * update stats and do tx completion processing
- */
-static void tx_timeout(unsigned long context)
-{
-	SLMP_INFO *info = (SLMP_INFO*)context;
-	unsigned long flags;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s tx_timeout()\n",
-			__FILE__,__LINE__,info->device_name);
-	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
-		info->icount.txtimeout++;
-	}
-	spin_lock_irqsave(&info->lock,flags);
-	info->tx_active = false;
-	info->tx_count = info->tx_put = info->tx_get = 0;
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else
-#endif
-		bh_transmit(info);
-}
-
-/* called to periodically check the DSR/RI modem signal input status
- */
-static void status_timeout(unsigned long context)
-{
-	u16 status = 0;
-	SLMP_INFO *info = (SLMP_INFO*)context;
-	unsigned long flags;
-	unsigned char delta;
-
-
-	spin_lock_irqsave(&info->lock,flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	/* check for DSR/RI state change */
-
-	delta = info->old_signals ^ info->serial_signals;
-	info->old_signals = info->serial_signals;
-
-	if (delta & SerialSignal_DSR)
-		status |= MISCSTATUS_DSR_LATCHED|(info->serial_signals&SerialSignal_DSR);
-
-	if (delta & SerialSignal_RI)
-		status |= MISCSTATUS_RI_LATCHED|(info->serial_signals&SerialSignal_RI);
-
-	if (delta & SerialSignal_DCD)
-		status |= MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD);
-
-	if (delta & SerialSignal_CTS)
-		status |= MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS);
-
-	if (status)
-		isr_io_pin(info,status);
-
-	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
-}
-
-
-/* Register Access Routines -
- * All registers are memory mapped
- */
-#define CALC_REGADDR() \
-	unsigned char * RegAddr = (unsigned char*)(info->sca_base + Addr); \
-	if (info->port_num > 1) \
-		RegAddr += 256;	    		/* port 0-1 SCA0, 2-3 SCA1 */ \
-	if ( info->port_num & 1) { \
-		if (Addr > 0x7f) \
-			RegAddr += 0x40;	/* DMA access */ \
-		else if (Addr > 0x1f && Addr < 0x60) \
-			RegAddr += 0x20;	/* MSCI access */ \
-	}
-
-
-static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr)
-{
-	CALC_REGADDR();
-	return *RegAddr;
-}
-static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value)
-{
-	CALC_REGADDR();
-	*RegAddr = Value;
-}
-
-static u16 read_reg16(SLMP_INFO * info, unsigned char Addr)
-{
-	CALC_REGADDR();
-	return *((u16 *)RegAddr);
-}
-
-static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value)
-{
-	CALC_REGADDR();
-	*((u16 *)RegAddr) = Value;
-}
-
-static unsigned char read_status_reg(SLMP_INFO * info)
-{
-	unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
-	return *RegAddr;
-}
-
-static void write_control_reg(SLMP_INFO * info)
-{
-	unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
-	*RegAddr = info->port_array[0]->ctrlreg_value;
-}
-
-
-static int __devinit synclinkmp_init_one (struct pci_dev *dev,
-					  const struct pci_device_id *ent)
-{
-	if (pci_enable_device(dev)) {
-		printk("error enabling pci device %p\n", dev);
-		return -EIO;
-	}
-	device_init( ++synclinkmp_adapter_count, dev );
-	return 0;
-}
-
-static void __devexit synclinkmp_remove_one (struct pci_dev *dev)
-{
-}
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
index c40c161..a1f68af 100644
--- a/drivers/char/ttyprintk.c
+++ b/drivers/char/ttyprintk.c
@@ -144,7 +144,7 @@ static int tpk_write_room(struct tty_struct *tty)
 /*
  * TTY operations ioctl function.
  */
-static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+static int tpk_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	struct ttyprintk_port *tpkp = tty->driver_data;
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
deleted file mode 100644
index 12de120..0000000
--- a/drivers/char/vme_scc.c
+++ /dev/null
@@ -1,1145 +0,0 @@
-/*
- * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
- * implementation.
- * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
- *
- * Based on atari_SCC.c which was
- *   Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <asm/setup.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_MVME147_SCC
-#include <asm/mvme147hw.h>
-#endif
-#ifdef CONFIG_MVME162_SCC
-#include <asm/mvme16xhw.h>
-#endif
-#ifdef CONFIG_BVME6000_SCC
-#include <asm/bvme6000hw.h>
-#endif
-
-#include <linux/generic_serial.h>
-#include "scc.h"
-
-
-#define CHANNEL_A	0
-#define CHANNEL_B	1
-
-#define SCC_MINOR_BASE	64
-
-/* Shadows for all SCC write registers */
-static unsigned char scc_shadow[2][16];
-
-/* Location to access for SCC register access delay */
-static volatile unsigned char *scc_del = NULL;
-
-/* To keep track of STATUS_REG state for detection of Ext/Status int source */
-static unsigned char scc_last_status_reg[2];
-
-/***************************** Prototypes *****************************/
-
-/* Function prototypes */
-static void scc_disable_tx_interrupts(void * ptr);
-static void scc_enable_tx_interrupts(void * ptr);
-static void scc_disable_rx_interrupts(void * ptr);
-static void scc_enable_rx_interrupts(void * ptr);
-static int  scc_carrier_raised(struct tty_port *port);
-static void scc_shutdown_port(void * ptr);
-static int scc_set_real_termios(void  *ptr);
-static void scc_hungup(void  *ptr);
-static void scc_close(void  *ptr);
-static int scc_chars_in_buffer(void * ptr);
-static int scc_open(struct tty_struct * tty, struct file * filp);
-static int scc_ioctl(struct tty_struct * tty, struct file * filp,
-                     unsigned int cmd, unsigned long arg);
-static void scc_throttle(struct tty_struct *tty);
-static void scc_unthrottle(struct tty_struct *tty);
-static irqreturn_t scc_tx_int(int irq, void *data);
-static irqreturn_t scc_rx_int(int irq, void *data);
-static irqreturn_t scc_stat_int(int irq, void *data);
-static irqreturn_t scc_spcond_int(int irq, void *data);
-static void scc_setsignals(struct scc_port *port, int dtr, int rts);
-static int scc_break_ctl(struct tty_struct *tty, int break_state);
-
-static struct tty_driver *scc_driver;
-
-static struct scc_port scc_ports[2];
-
-/*---------------------------------------------------------------------------
- * Interface from generic_serial.c back here
- *--------------------------------------------------------------------------*/
-
-static struct real_driver scc_real_driver = {
-        scc_disable_tx_interrupts,
-        scc_enable_tx_interrupts,
-        scc_disable_rx_interrupts,
-        scc_enable_rx_interrupts,
-        scc_shutdown_port,
-        scc_set_real_termios,
-        scc_chars_in_buffer,
-        scc_close,
-        scc_hungup,
-        NULL
-};
-
-
-static const struct tty_operations scc_ops = {
-	.open	= scc_open,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = scc_ioctl,
-	.throttle = scc_throttle,
-	.unthrottle = scc_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-	.break_ctl = scc_break_ctl,
-};
-
-static const struct tty_port_operations scc_port_ops = {
-	.carrier_raised = scc_carrier_raised,
-};
-
-/*----------------------------------------------------------------------------
- * vme_scc_init() and support functions
- *---------------------------------------------------------------------------*/
-
-static int __init scc_init_drivers(void)
-{
-	int error;
-
-	scc_driver = alloc_tty_driver(2);
-	if (!scc_driver)
-		return -ENOMEM;
-	scc_driver->owner = THIS_MODULE;
-	scc_driver->driver_name = "scc";
-	scc_driver->name = "ttyS";
-	scc_driver->major = TTY_MAJOR;
-	scc_driver->minor_start = SCC_MINOR_BASE;
-	scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	scc_driver->subtype = SERIAL_TYPE_NORMAL;
-	scc_driver->init_termios = tty_std_termios;
-	scc_driver->init_termios.c_cflag =
-	  B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	scc_driver->init_termios.c_ispeed = 9600;
-	scc_driver->init_termios.c_ospeed = 9600;
-	scc_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(scc_driver, &scc_ops);
-
-	if ((error = tty_register_driver(scc_driver))) {
-		printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
-		       error);
-		put_tty_driver(scc_driver);
-		return 1;
-	}
-
-	return 0;
-}
-
-
-/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
- */
-
-static void __init scc_init_portstructs(void)
-{
-	struct scc_port *port;
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		port = scc_ports + i;
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &scc_port_ops;
-		port->gs.magic = SCC_MAGIC;
-		port->gs.close_delay = HZ/2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &scc_real_driver;
-#ifdef NEW_WRITE_LOCKING
-		port->gs.port_write_mutex = MUTEX;
-#endif
-		init_waitqueue_head(&port->gs.port.open_wait);
-		init_waitqueue_head(&port->gs.port.close_wait);
-	}
-}
-
-
-#ifdef CONFIG_MVME147_SCC
-static int __init mvme147_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
-	port->datap = port->ctrlp + 1;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
-	port->datap = port->ctrlp + 1;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-        /* Ensure interrupts are enabled in the PCC chip */
-        m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail_free_b_rx:
-	free_irq(MVME147_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(MVME147_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(MVME147_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(MVME147_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(MVME147_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(MVME147_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(MVME147_IRQ_SCCA_TX, port);
-fail:
-	return error;
-}
-#endif
-
-
-#ifdef CONFIG_MVME162_SCC
-static int __init mvme162_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
-		return (-ENODEV);
-
-	printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
-	port->datap = port->ctrlp + 2;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
-	port->datap = port->ctrlp + 2;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);	/* Either channel will do */
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-        /* Ensure interrupts are enabled in the MC2 chip */
-        *(volatile char *)0xfff4201d = 0x14;
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail_free_b_rx:
-	free_irq(MVME162_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(MVME162_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(MVME162_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(MVME162_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(MVME162_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(MVME162_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(MVME162_IRQ_SCCA_TX, port);
-fail:
-	return error;
-}
-#endif
-
-
-#ifdef CONFIG_BVME6000_SCC
-static int __init bvme6000_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
-	port->datap = port->ctrlp + 4;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
-	port->datap = port->ctrlp + 4;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);	/* Either channel will do */
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail:
-	free_irq(BVME_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(BVME_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(BVME_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(BVME_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(BVME_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(BVME_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(BVME_IRQ_SCCB_SPCOND, port);
-fail_free_b_rx:
-	return error;
-}
-#endif
-
-
-static int __init vme_scc_init(void)
-{
-	int res = -ENODEV;
-
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		res = mvme147_scc_init();
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		res = mvme162_scc_init();
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		res = bvme6000_scc_init();
-#endif
-	return res;
-}
-
-module_init(vme_scc_init);
-
-
-/*---------------------------------------------------------------------------
- * Interrupt handlers
- *--------------------------------------------------------------------------*/
-
-static irqreturn_t scc_rx_int(int irq, void *data)
-{
-	unsigned char	ch;
-	struct scc_port *port = data;
-	struct tty_struct *tty = port->gs.port.tty;
-	SCC_ACCESS_INIT(port);
-
-	ch = SCCread_NB(RX_DATA_REG);
-	if (!tty) {
-		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	tty_insert_flip_char(tty, ch, 0);
-
-	/* Check if another character is already ready; in that case, the
-	 * spcond_int() function must be used, because this character may have an
-	 * error condition that isn't signalled by the interrupt vector used!
-	 */
-	if (SCCread(INT_PENDING_REG) &
-	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
-		scc_spcond_int (irq, data);
-		return IRQ_HANDLED;
-	}
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_spcond_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	struct tty_struct *tty = port->gs.port.tty;
-	unsigned char	stat, ch, err;
-	int		int_pending_mask = port->channel == CHANNEL_A ?
-			                   IPR_A_RX : IPR_B_RX;
-	SCC_ACCESS_INIT(port);
-	
-	if (!tty) {
-		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
-		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	do {
-		stat = SCCread(SPCOND_STATUS_REG);
-		ch = SCCread_NB(RX_DATA_REG);
-
-		if (stat & SCSR_RX_OVERRUN)
-			err = TTY_OVERRUN;
-		else if (stat & SCSR_PARITY_ERR)
-			err = TTY_PARITY;
-		else if (stat & SCSR_CRC_FRAME_ERR)
-			err = TTY_FRAME;
-		else
-			err = 0;
-
-		tty_insert_flip_char(tty, ch, err);
-
-		/* ++TeSche: *All* errors have to be cleared manually,
-		 * else the condition persists for the next chars
-		 */
-		if (err)
-		  SCCwrite(COMMAND_REG, CR_ERROR_RESET);
-
-	} while(SCCread(INT_PENDING_REG) & int_pending_mask);
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_tx_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	SCC_ACCESS_INIT(port);
-
-	if (!port->gs.port.tty) {
-		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
-		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
-		if (port->x_char) {
-			SCCwrite(TX_DATA_REG, port->x_char);
-			port->x_char = 0;
-		}
-		else if ((port->gs.xmit_cnt <= 0) ||
-			 port->gs.port.tty->stopped ||
-			 port->gs.port.tty->hw_stopped)
-			break;
-		else {
-			SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
-			port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
-			if (--port->gs.xmit_cnt <= 0)
-				break;
-		}
-	}
-	if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
-	    port->gs.port.tty->hw_stopped) {
-		/* disable tx interrupts */
-		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
-		port->gs.port.flags &= ~GS_TX_INTEN;
-	}
-	if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
-		tty_wakeup(port->gs.port.tty);
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_stat_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	unsigned channel = port->channel;
-	unsigned char	last_sr, sr, changed;
-	SCC_ACCESS_INIT(port);
-
-	last_sr = scc_last_status_reg[channel];
-	sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
-	changed = last_sr ^ sr;
-
-	if (changed & SR_DCD) {
-		port->c_dcd = !!(sr & SR_DCD);
-		if (!(port->gs.port.flags & ASYNC_CHECK_CD))
-			;	/* Don't report DCD changes */
-		else if (port->c_dcd) {
-			wake_up_interruptible(&port->gs.port.open_wait);
-		}
-		else {
-			if (port->gs.port.tty)
-				tty_hangup (port->gs.port.tty);
-		}
-	}
-	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-	return IRQ_HANDLED;
-}
-
-
-/*---------------------------------------------------------------------------
- * generic_serial.c callback funtions
- *--------------------------------------------------------------------------*/
-
-static void scc_disable_tx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-	port->gs.port.flags &= ~GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-
-static void scc_enable_tx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
-	/* restart the transmitter */
-	scc_tx_int (0, port);
-	local_irq_restore(flags);
-}
-
-
-static void scc_disable_rx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG,
-	    ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
-	local_irq_restore(flags);
-}
-
-
-static void scc_enable_rx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, 0xff,
-		IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
-	local_irq_restore(flags);
-}
-
-
-static int scc_carrier_raised(struct tty_port *port)
-{
-	struct scc_port *sc = container_of(port, struct scc_port, gs.port);
-	unsigned channel = sc->channel;
-
-	return !!(scc_last_status_reg[channel] & SR_DCD);
-}
-
-
-static void scc_shutdown_port(void *ptr)
-{
-	struct scc_port *port = ptr;
-
-	port->gs.port.flags &= ~ GS_ACTIVE;
-	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
-		scc_setsignals (port, 0, 0);
-	}
-}
-
-
-static int scc_set_real_termios (void *ptr)
-{
-	/* the SCC has char sizes 5,7,6,8 in that order! */
-	static int chsize_map[4] = { 0, 2, 1, 3 };
-	unsigned cflag, baud, chsize, channel, brgval = 0;
-	unsigned long flags;
-	struct scc_port *port = ptr;
-	SCC_ACCESS_INIT(port);
-
-	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
-
-	channel = port->channel;
-
-	if (channel == CHANNEL_A)
-		return 0;		/* Settings controlled by boot PROM */
-
-	cflag  = port->gs.port.tty->termios->c_cflag;
-	baud = port->gs.baud;
-	chsize = (cflag & CSIZE) >> 4;
-
-	if (baud == 0) {
-		/* speed == 0 -> drop DTR */
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
-		local_irq_restore(flags);
-		return 0;
-	}
-	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
-		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
-		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
-		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
-		return 0;
-	}
-
-	if (cflag & CLOCAL)
-		port->gs.port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->gs.port.flags |= ASYNC_CHECK_CD;
-
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
-#endif
-	/* Now we have all parameters and can go to set them: */
-	local_irq_save(flags);
-
-	/* receiver's character size and auto-enables */
-	SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
-			(chsize_map[chsize] << 6) |
-			((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
-	/* parity and stop bits (both, Tx and Rx), clock mode never changes */
-	SCCmod (AUX1_CTRL_REG,
-		~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
-		((cflag & PARENB
-		  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
-		  : A1CR_PARITY_NONE)
-		 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
-	/* sender's character size, set DTR for valid baud rate */
-	SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
-	/* clock sources never change */
-	/* disable BRG before changing the value */
-	SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
-	/* BRG value */
-	SCCwrite(TIMER_LOW_REG, brgval & 0xff);
-	SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
-	/* BRG enable, and clock source never changes */
-	SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-static int scc_chars_in_buffer (void *ptr)
-{
-	struct scc_port *port = ptr;
-	SCC_ACCESS_INIT(port);
-
-	return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
-}
-
-
-/* Comment taken from sx.c (2.4.0):
-   I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-
-static void scc_hungup(void *ptr)
-{
-	scc_disable_tx_interrupts(ptr);
-	scc_disable_rx_interrupts(ptr);
-}
-
-
-static void scc_close(void *ptr)
-{
-	scc_disable_tx_interrupts(ptr);
-	scc_disable_rx_interrupts(ptr);
-}
-
-
-/*---------------------------------------------------------------------------
- * Internal support functions
- *--------------------------------------------------------------------------*/
-
-static void scc_setsignals(struct scc_port *port, int dtr, int rts)
-{
-	unsigned long flags;
-	unsigned char t;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	t = SCCread(TX_CTRL_REG);
-	if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
-	if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
-	SCCwrite(TX_CTRL_REG, t);
-	local_irq_restore(flags);
-}
-
-
-static void scc_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct scc_port *port = tty->driver_data;
-
-	port->x_char = ch;
-	if (ch)
-		scc_enable_tx_interrupts(port);
-}
-
-
-/*---------------------------------------------------------------------------
- * Driver entrypoints referenced from above
- *--------------------------------------------------------------------------*/
-
-static int scc_open (struct tty_struct * tty, struct file * filp)
-{
-	int line = tty->index;
-	int retval;
-	struct scc_port *port = &scc_ports[line];
-	int i, channel = port->channel;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
-	static const struct {
-		unsigned reg, val;
-	} mvme_init_tab[] = {
-		/* Values for MVME162 and MVME147 */
-		/* no parity, 1 stop bit, async, 1:16 */
-		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
-		/* parity error is special cond, ints disabled, no DMA */
-		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
-		/* Rx 8 bits/char, no auto enable, Rx off */
-		{ RX_CTRL_REG, RCR_CHSIZE_8 },
-		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
-		{ TX_CTRL_REG, TCR_CHSIZE_8 },
-		/* special features off */
-		{ AUX2_CTRL_REG, 0 },
-		{ CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
-		{ DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
-		/* Start Rx */
-		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
-		/* Start Tx */
-		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
-		/* Ext/Stat ints: DCD only */
-		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
-		/* Reset Ext/Stat ints */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-		/* ...again */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-	};
-#endif
-#if defined(CONFIG_BVME6000_SCC)
-	static const struct {
-		unsigned reg, val;
-	} bvme_init_tab[] = {
-		/* Values for BVME6000 */
-		/* no parity, 1 stop bit, async, 1:16 */
-		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
-		/* parity error is special cond, ints disabled, no DMA */
-		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
-		/* Rx 8 bits/char, no auto enable, Rx off */
-		{ RX_CTRL_REG, RCR_CHSIZE_8 },
-		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
-		{ TX_CTRL_REG, TCR_CHSIZE_8 },
-		/* special features off */
-		{ AUX2_CTRL_REG, 0 },
-		{ CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
-		{ DPLL_CTRL_REG, DCR_BRG_ENAB },
-		/* Start Rx */
-		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
-		/* Start Tx */
-		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
-		/* Ext/Stat ints: DCD only */
-		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
-		/* Reset Ext/Stat ints */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-		/* ...again */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-	};
-#endif
-	if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
-		local_irq_save(flags);
-#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
-		if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
-			for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
-				SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
-		}
-#endif
-#if defined(CONFIG_BVME6000_SCC)
-		if (MACH_IS_BVME6000) {
-			for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
-				SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
-		}
-#endif
-
-		/* remember status register for detection of DCD and CTS changes */
-		scc_last_status_reg[channel] = SCCread(STATUS_REG);
-
-		port->c_dcd = 0;	/* Prevent initial 1->0 interrupt */
-		scc_setsignals (port, 1,1);
-		local_irq_restore(flags);
-	}
-
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	retval = gs_init_port(&port->gs);
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-	port->gs.port.flags |= GS_ACTIVE;
-	retval = gs_block_til_ready(port, filp);
-
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	port->c_dcd = tty_port_carrier_raised(&port->gs.port);
-
-	scc_enable_rx_interrupts(port);
-
-	return 0;
-}
-
-
-static void scc_throttle (struct tty_struct * tty)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
-		local_irq_restore(flags);
-	}
-	if (I_IXOFF(tty))
-		scc_send_xchar(tty, STOP_CHAR(tty));
-}
-
-
-static void scc_unthrottle (struct tty_struct * tty)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
-		local_irq_restore(flags);
-	}
-	if (I_IXOFF(tty))
-		scc_send_xchar(tty, START_CHAR(tty));
-}
-
-
-static int scc_ioctl(struct tty_struct *tty, struct file *file,
-		     unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-
-static int scc_break_ctl(struct tty_struct *tty, int break_state)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 
-			break_state ? TCR_SEND_BREAK : 0);
-	local_irq_restore(flags);
-	return 0;
-}
-
-
-/*---------------------------------------------------------------------------
- * Serial console stuff...
- *--------------------------------------------------------------------------*/
-
-#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
-
-static void scc_ch_write (char ch)
-{
-	volatile char *p = NULL;
-	
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		p = (volatile char *)M147_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		p = (volatile char *)MVME_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		p = (volatile char *)BVME_SCC_A_ADDR;
-#endif
-
-	do {
-		scc_delay();
-	}
-	while (!(*p & 4));
-	scc_delay();
-	*p = 8;
-	scc_delay();
-	*p = ch;
-}
-
-/* The console must be locked when we get here. */
-
-static void scc_console_write (struct console *co, const char *str, unsigned count)
-{
-	unsigned long	flags;
-
-	local_irq_save(flags);
-
-	while (count--)
-	{
-		if (*str == '\n')
-			scc_ch_write ('\r');
-		scc_ch_write (*str++);
-	}
-	local_irq_restore(flags);
-}
-
-static struct tty_driver *scc_console_device(struct console *c, int *index)
-{
-	*index = c->index;
-	return scc_driver;
-}
-
-static struct console sercons = {
-	.name		= "ttyS",
-	.write		= scc_console_write,
-	.device		= scc_console_device,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-
-static int __init vme_scc_console_init(void)
-{
-	if (vme_brdtype == VME_TYPE_MVME147 ||
-			vme_brdtype == VME_TYPE_MVME162 ||
-			vme_brdtype == VME_TYPE_MVME172 ||
-			vme_brdtype == VME_TYPE_BVME4000 ||
-			vme_brdtype == VME_TYPE_BVME6000)
-		register_console(&sercons);
-	return 0;
-}
-console_initcall(vme_scc_console_init);
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 9f2272e..d3c9d75 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -714,20 +714,29 @@ static int __devexit hwicap_remove(struct device *dev)
 	return 0;		/* success */
 }
 
-static int __devinit hwicap_drv_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int __devinit hwicap_of_probe(struct platform_device *op)
 {
-	struct resource *res;
-	const struct config_registers *regs;
+	struct resource res;
+	const unsigned int *id;
 	const char *family;
+	int rc;
+	const struct hwicap_driver_config *config = op->dev.of_match->data;
+	const struct config_registers *regs;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
+
+	rc = of_address_to_resource(op->dev.of_node, 0, &res);
+	if (rc) {
+		dev_err(&op->dev, "invalid address\n");
+		return rc;
+	}
+
+	id = of_get_property(op->dev.of_node, "port-number", NULL);
 
 	/* It's most likely that we're using V4, if the family is not
 	   specified */
 	regs = &v4_config_registers;
-	family = pdev->dev.platform_data;
+	family = of_get_property(op->dev.of_node, "xlnx,family", NULL);
 
 	if (family) {
 		if (!strcmp(family, "virtex2p")) {
@@ -738,54 +747,33 @@ static int __devinit hwicap_drv_probe(struct platform_device *pdev)
 			regs = &v5_config_registers;
 		}
 	}
-
-	return hwicap_setup(&pdev->dev, pdev->id, res,
-			&buffer_icap_config, regs);
+	return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
+			regs);
 }
-
-static int __devexit hwicap_drv_remove(struct platform_device *pdev)
+#else
+static inline int hwicap_of_probe(struct platform_device *op)
 {
-	return hwicap_remove(&pdev->dev);
+	return -EINVAL;
 }
+#endif /* CONFIG_OF */
 
-static struct platform_driver hwicap_platform_driver = {
-	.probe = hwicap_drv_probe,
-	.remove = hwicap_drv_remove,
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = DRIVER_NAME,
-	},
-};
-
-/* ---------------------------------------------------------------------
- * OF bus binding
- */
-
-#if defined(CONFIG_OF)
-static int __devinit
-hwicap_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit hwicap_drv_probe(struct platform_device *pdev)
 {
-	struct resource res;
-	const unsigned int *id;
-	const char *family;
-	int rc;
-	const struct hwicap_driver_config *config = match->data;
+	struct resource *res;
 	const struct config_registers *regs;
+	const char *family;
 
-	dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match);
-
-	rc = of_address_to_resource(op->dev.of_node, 0, &res);
-	if (rc) {
-		dev_err(&op->dev, "invalid address\n");
-		return rc;
-	}
+	if (pdev->dev.of_match)
+		return hwicap_of_probe(pdev);
 
-	id = of_get_property(op->dev.of_node, "port-number", NULL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
 
 	/* It's most likely that we're using V4, if the family is not
 	   specified */
 	regs = &v4_config_registers;
-	family = of_get_property(op->dev.of_node, "xlnx,family", NULL);
+	family = pdev->dev.platform_data;
 
 	if (family) {
 		if (!strcmp(family, "virtex2p")) {
@@ -796,50 +784,38 @@ hwicap_of_probe(struct platform_device *op, const struct of_device_id *match)
 			regs = &v5_config_registers;
 		}
 	}
-	return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
-			regs);
+
+	return hwicap_setup(&pdev->dev, pdev->id, res,
+			&buffer_icap_config, regs);
 }
 
-static int __devexit hwicap_of_remove(struct platform_device *op)
+static int __devexit hwicap_drv_remove(struct platform_device *pdev)
 {
-	return hwicap_remove(&op->dev);
+	return hwicap_remove(&pdev->dev);
 }
 
-/* Match table for of_platform binding */
+#ifdef CONFIG_OF
+/* Match table for device tree binding */
 static const struct of_device_id __devinitconst hwicap_of_match[] = {
 	{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
 	{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
 	{},
 };
 MODULE_DEVICE_TABLE(of, hwicap_of_match);
+#else
+#define hwicap_of_match NULL
+#endif
 
-static struct of_platform_driver hwicap_of_driver = {
-	.probe = hwicap_of_probe,
-	.remove = __devexit_p(hwicap_of_remove),
+static struct platform_driver hwicap_platform_driver = {
+	.probe = hwicap_drv_probe,
+	.remove = hwicap_drv_remove,
 	.driver = {
-		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
 		.of_match_table = hwicap_of_match,
 	},
 };
 
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init hwicap_of_register(void)
-{
-	pr_debug("hwicap: calling of_register_platform_driver()\n");
-	return of_register_platform_driver(&hwicap_of_driver);
-}
-
-static inline void __exit hwicap_of_unregister(void)
-{
-	of_unregister_platform_driver(&hwicap_of_driver);
-}
-#else /* CONFIG_OF */
-/* CONFIG_OF not enabled; do nothing helpers */
-static inline int __init hwicap_of_register(void) { return 0; }
-static inline void __exit hwicap_of_unregister(void) { }
-#endif /* CONFIG_OF */
-
 static int __init hwicap_module_init(void)
 {
 	dev_t devt;
@@ -856,21 +832,12 @@ static int __init hwicap_module_init(void)
 		return retval;
 
 	retval = platform_driver_register(&hwicap_platform_driver);
-
-	if (retval)
-		goto failed1;
-
-	retval = hwicap_of_register();
-
 	if (retval)
-		goto failed2;
+		goto failed;
 
 	return retval;
 
- failed2:
-	platform_driver_unregister(&hwicap_platform_driver);
-
- failed1:
+ failed:
 	unregister_chrdev_region(devt, HWICAP_DEVICES);
 
 	return retval;
@@ -884,8 +851,6 @@ static void __exit hwicap_module_cleanup(void)
 
 	platform_driver_unregister(&hwicap_platform_driver);
 
-	hwicap_of_unregister();
-
 	unregister_chrdev_region(devt, HWICAP_DEVICES);
 }
 
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index 81270d2..55653ab 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -48,7 +48,7 @@ void cn_queue_wrapper(struct work_struct *work)
 }
 
 static struct cn_callback_entry *
-cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
+cn_queue_alloc_callback_entry(const char *name, struct cb_id *id,
 			      void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
 {
 	struct cn_callback_entry *cbq;
@@ -78,7 +78,8 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2)
 	return ((i1->idx == i2->idx) && (i1->val == i2->val));
 }
 
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
+int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
+			  struct cb_id *id,
 			  void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
 {
 	struct cn_callback_entry *cbq, *__cbq;
@@ -135,7 +136,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id)
 	}
 }
 
-struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
+struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *nls)
 {
 	struct cn_queue_dev *dev;
 
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 05117f1..f7554de 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -205,7 +205,7 @@ static void cn_rx_skb(struct sk_buff *__skb)
  *
  * May sleep.
  */
-int cn_add_callback(struct cb_id *id, char *name,
+int cn_add_callback(struct cb_id *id, const char *name,
 		    void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
 {
 	int err;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 5cb4d09..0f17ad8 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1371,7 +1371,7 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
 		goto out;
 
 	if (cpufreq_driver->suspend) {
-		ret = cpufreq_driver->suspend(cpu_policy, pmsg);
+		ret = cpufreq_driver->suspend(cpu_policy);
 		if (ret)
 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
 					"step on CPU %u\n", cpu_policy->cpu);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 526bfbf..33b56e5 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -76,13 +76,10 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, cs_cpu_dbs_info);
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
- * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
- * different CPUs. It protects dbs_enable in governor start/stop.
+ * dbs_mutex protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
-static struct workqueue_struct	*kconservative_wq;
-
 static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
@@ -118,7 +115,7 @@ static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu,
 	if (wall)
 		*wall = (cputime64_t)jiffies_to_usecs(cur_wall_time);
 
-	return (cputime64_t)jiffies_to_usecs(idle_time);;
+	return (cputime64_t)jiffies_to_usecs(idle_time);
 }
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
@@ -164,21 +161,12 @@ static struct notifier_block dbs_cpufreq_notifier_block = {
 };
 
 /************************** sysfs interface ************************/
-static ssize_t show_sampling_rate_max(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
-{
-	printk_once(KERN_INFO "CPUFREQ: conservative sampling_rate_max "
-		    "sysfs file is deprecated - used by: %s\n", current->comm);
-	return sprintf(buf, "%u\n", -1U);
-}
-
 static ssize_t show_sampling_rate_min(struct kobject *kobj,
 				      struct attribute *attr, char *buf)
 {
 	return sprintf(buf, "%u\n", min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_max);
 define_one_global_ro(sampling_rate_min);
 
 /* cpufreq_conservative Governor Tunables */
@@ -195,33 +183,6 @@ show_one(down_threshold, down_threshold);
 show_one(ignore_nice_load, ignore_nice);
 show_one(freq_step, freq_step);
 
-/*** delete after deprecation time ***/
-#define DEPRECATION_MSG(file_name)					\
-	printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs "	\
-		"interface is deprecated - " #file_name "\n");
-
-#define show_one_old(file_name)						\
-static ssize_t show_##file_name##_old					\
-(struct cpufreq_policy *unused, char *buf)				\
-{									\
-	printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs "	\
-		"interface is deprecated - " #file_name "\n");		\
-	return show_##file_name(NULL, NULL, buf);			\
-}
-show_one_old(sampling_rate);
-show_one_old(sampling_down_factor);
-show_one_old(up_threshold);
-show_one_old(down_threshold);
-show_one_old(ignore_nice_load);
-show_one_old(freq_step);
-show_one_old(sampling_rate_min);
-show_one_old(sampling_rate_max);
-
-cpufreq_freq_attr_ro_old(sampling_rate_min);
-cpufreq_freq_attr_ro_old(sampling_rate_max);
-
-/*** delete after deprecation time ***/
-
 static ssize_t store_sampling_down_factor(struct kobject *a,
 					  struct attribute *b,
 					  const char *buf, size_t count)
@@ -233,10 +194,7 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
 
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_down_factor = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -250,10 +208,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 	if (ret != 1)
 		return -EINVAL;
 
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -264,16 +219,11 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	mutex_lock(&dbs_mutex);
 	if (ret != 1 || input > 100 ||
-			input <= dbs_tuners_ins.down_threshold) {
-		mutex_unlock(&dbs_mutex);
+			input <= dbs_tuners_ins.down_threshold)
 		return -EINVAL;
-	}
 
 	dbs_tuners_ins.up_threshold = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -284,17 +234,12 @@ static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	mutex_lock(&dbs_mutex);
 	/* cannot be lower than 11 otherwise freq will not fall */
 	if (ret != 1 || input < 11 || input > 100 ||
-			input >= dbs_tuners_ins.up_threshold) {
-		mutex_unlock(&dbs_mutex);
+			input >= dbs_tuners_ins.up_threshold)
 		return -EINVAL;
-	}
 
 	dbs_tuners_ins.down_threshold = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -313,11 +258,9 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	mutex_lock(&dbs_mutex);
-	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
-		mutex_unlock(&dbs_mutex);
+	if (input == dbs_tuners_ins.ignore_nice) /* nothing to do */
 		return count;
-	}
+
 	dbs_tuners_ins.ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
@@ -329,8 +272,6 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 		if (dbs_tuners_ins.ignore_nice)
 			dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
 	}
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -349,10 +290,7 @@ 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 :) */
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.freq_step = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -364,7 +302,6 @@ define_one_global_rw(ignore_nice_load);
 define_one_global_rw(freq_step);
 
 static struct attribute *dbs_attributes[] = {
-	&sampling_rate_max.attr,
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
 	&sampling_down_factor.attr,
@@ -380,49 +317,6 @@ static struct attribute_group dbs_attr_group = {
 	.name = "conservative",
 };
 
-/*** delete after deprecation time ***/
-
-#define write_one_old(file_name)					\
-static ssize_t store_##file_name##_old					\
-(struct cpufreq_policy *unused, const char *buf, size_t count)		\
-{									\
-	printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs "	\
-		"interface is deprecated - " #file_name "\n");	\
-	return store_##file_name(NULL, NULL, buf, count);		\
-}
-write_one_old(sampling_rate);
-write_one_old(sampling_down_factor);
-write_one_old(up_threshold);
-write_one_old(down_threshold);
-write_one_old(ignore_nice_load);
-write_one_old(freq_step);
-
-cpufreq_freq_attr_rw_old(sampling_rate);
-cpufreq_freq_attr_rw_old(sampling_down_factor);
-cpufreq_freq_attr_rw_old(up_threshold);
-cpufreq_freq_attr_rw_old(down_threshold);
-cpufreq_freq_attr_rw_old(ignore_nice_load);
-cpufreq_freq_attr_rw_old(freq_step);
-
-static struct attribute *dbs_attributes_old[] = {
-	&sampling_rate_max_old.attr,
-	&sampling_rate_min_old.attr,
-	&sampling_rate_old.attr,
-	&sampling_down_factor_old.attr,
-	&up_threshold_old.attr,
-	&down_threshold_old.attr,
-	&ignore_nice_load_old.attr,
-	&freq_step_old.attr,
-	NULL
-};
-
-static struct attribute_group dbs_attr_group_old = {
-	.attrs = dbs_attributes_old,
-	.name = "conservative",
-};
-
-/*** delete after deprecation time ***/
-
 /************************** sysfs end ************************/
 
 static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
@@ -560,7 +454,7 @@ static void do_dbs_timer(struct work_struct *work)
 
 	dbs_check_cpu(dbs_info);
 
-	queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay);
+	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
 	mutex_unlock(&dbs_info->timer_mutex);
 }
 
@@ -572,8 +466,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 
 	dbs_info->enable = 1;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
-	queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work,
-				delay);
+	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -599,12 +492,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 
 		mutex_lock(&dbs_mutex);
 
-		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group_old);
-		if (rc) {
-			mutex_unlock(&dbs_mutex);
-			return rc;
-		}
-
 		for_each_cpu(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
 			j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
@@ -667,7 +554,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		dbs_timer_exit(this_dbs_info);
 
 		mutex_lock(&dbs_mutex);
-		sysfs_remove_group(&policy->kobj, &dbs_attr_group_old);
 		dbs_enable--;
 		mutex_destroy(&this_dbs_info->timer_mutex);
 
@@ -716,25 +602,12 @@ struct cpufreq_governor cpufreq_gov_conservative = {
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	int err;
-
-	kconservative_wq = create_workqueue("kconservative");
-	if (!kconservative_wq) {
-		printk(KERN_ERR "Creation of kconservative failed\n");
-		return -EFAULT;
-	}
-
-	err = cpufreq_register_governor(&cpufreq_gov_conservative);
-	if (err)
-		destroy_workqueue(kconservative_wq);
-
-	return err;
+	return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_conservative);
-	destroy_workqueue(kconservative_wq);
 }
 
 
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index c631f27..891360e 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -99,13 +99,10 @@ static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info);
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
- * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
- * different CPUs. It protects dbs_enable in governor start/stop.
+ * dbs_mutex protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
-static struct workqueue_struct	*kondemand_wq;
-
 static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int up_threshold;
@@ -237,21 +234,12 @@ static void ondemand_powersave_bias_init(void)
 
 /************************** sysfs interface ************************/
 
-static ssize_t show_sampling_rate_max(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
-{
-	printk_once(KERN_INFO "CPUFREQ: ondemand sampling_rate_max "
-	       "sysfs file is deprecated - used by: %s\n", current->comm);
-	return sprintf(buf, "%u\n", -1U);
-}
-
 static ssize_t show_sampling_rate_min(struct kobject *kobj,
 				      struct attribute *attr, char *buf)
 {
 	return sprintf(buf, "%u\n", min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_max);
 define_one_global_ro(sampling_rate_min);
 
 /* cpufreq_ondemand Governor Tunables */
@@ -268,32 +256,6 @@ show_one(sampling_down_factor, sampling_down_factor);
 show_one(ignore_nice_load, ignore_nice);
 show_one(powersave_bias, powersave_bias);
 
-/*** delete after deprecation time ***/
-
-#define DEPRECATION_MSG(file_name)					\
-	printk_once(KERN_INFO "CPUFREQ: Per core ondemand sysfs "	\
-		    "interface is deprecated - " #file_name "\n");
-
-#define show_one_old(file_name)						\
-static ssize_t show_##file_name##_old					\
-(struct cpufreq_policy *unused, char *buf)				\
-{									\
-	printk_once(KERN_INFO "CPUFREQ: Per core ondemand sysfs "	\
-		    "interface is deprecated - " #file_name "\n");	\
-	return show_##file_name(NULL, NULL, buf);			\
-}
-show_one_old(sampling_rate);
-show_one_old(up_threshold);
-show_one_old(ignore_nice_load);
-show_one_old(powersave_bias);
-show_one_old(sampling_rate_min);
-show_one_old(sampling_rate_max);
-
-cpufreq_freq_attr_ro_old(sampling_rate_min);
-cpufreq_freq_attr_ro_old(sampling_rate_max);
-
-/*** delete after deprecation time ***/
-
 static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 				   const char *buf, size_t count)
 {
@@ -302,11 +264,7 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -319,11 +277,7 @@ static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.io_is_busy = !!input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -338,11 +292,7 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
 			input < MIN_FREQUENCY_UP_THRESHOLD) {
 		return -EINVAL;
 	}
-
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.up_threshold = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -355,7 +305,6 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_down_factor = input;
 
 	/* Reset down sampling multiplier in case it was active */
@@ -364,8 +313,6 @@ static ssize_t store_sampling_down_factor(struct kobject *a,
 		dbs_info = &per_cpu(od_cpu_dbs_info, j);
 		dbs_info->rate_mult = 1;
 	}
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -384,9 +331,7 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 	if (input > 1)
 		input = 1;
 
-	mutex_lock(&dbs_mutex);
 	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
-		mutex_unlock(&dbs_mutex);
 		return count;
 	}
 	dbs_tuners_ins.ignore_nice = input;
@@ -401,8 +346,6 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
 			dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
 
 	}
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -419,11 +362,8 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 	if (input > 1000)
 		input = 1000;
 
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.powersave_bias = input;
 	ondemand_powersave_bias_init();
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -435,7 +375,6 @@ define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
 
 static struct attribute *dbs_attributes[] = {
-	&sampling_rate_max.attr,
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
 	&up_threshold.attr,
@@ -451,43 +390,6 @@ static struct attribute_group dbs_attr_group = {
 	.name = "ondemand",
 };
 
-/*** delete after deprecation time ***/
-
-#define write_one_old(file_name)					\
-static ssize_t store_##file_name##_old					\
-(struct cpufreq_policy *unused, const char *buf, size_t count)		\
-{									\
-       printk_once(KERN_INFO "CPUFREQ: Per core ondemand sysfs "	\
-		   "interface is deprecated - " #file_name "\n");	\
-       return store_##file_name(NULL, NULL, buf, count);		\
-}
-write_one_old(sampling_rate);
-write_one_old(up_threshold);
-write_one_old(ignore_nice_load);
-write_one_old(powersave_bias);
-
-cpufreq_freq_attr_rw_old(sampling_rate);
-cpufreq_freq_attr_rw_old(up_threshold);
-cpufreq_freq_attr_rw_old(ignore_nice_load);
-cpufreq_freq_attr_rw_old(powersave_bias);
-
-static struct attribute *dbs_attributes_old[] = {
-       &sampling_rate_max_old.attr,
-       &sampling_rate_min_old.attr,
-       &sampling_rate_old.attr,
-       &up_threshold_old.attr,
-       &ignore_nice_load_old.attr,
-       &powersave_bias_old.attr,
-       NULL
-};
-
-static struct attribute_group dbs_attr_group_old = {
-       .attrs = dbs_attributes_old,
-       .name = "ondemand",
-};
-
-/*** delete after deprecation time ***/
-
 /************************** sysfs end ************************/
 
 static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
@@ -644,12 +546,7 @@ static void do_dbs_timer(struct work_struct *work)
 	unsigned int cpu = dbs_info->cpu;
 	int sample_type = dbs_info->sample_type;
 
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
-		* dbs_info->rate_mult);
-
-	if (num_online_cpus() > 1)
-		delay -= jiffies % delay;
+	int delay;
 
 	mutex_lock(&dbs_info->timer_mutex);
 
@@ -662,12 +559,22 @@ static void do_dbs_timer(struct work_struct *work)
 			/* Setup timer for SUB_SAMPLE */
 			dbs_info->sample_type = DBS_SUB_SAMPLE;
 			delay = dbs_info->freq_hi_jiffies;
+		} else {
+			/* We want all CPUs to do sampling nearly on
+			 * same jiffy
+			 */
+			delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
+				* dbs_info->rate_mult);
+
+			if (num_online_cpus() > 1)
+				delay -= jiffies % delay;
 		}
 	} else {
 		__cpufreq_driver_target(dbs_info->cur_policy,
 			dbs_info->freq_lo, CPUFREQ_RELATION_H);
+		delay = dbs_info->freq_lo_jiffies;
 	}
-	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
 	mutex_unlock(&dbs_info->timer_mutex);
 }
 
@@ -681,8 +588,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
 
 	dbs_info->sample_type = DBS_NORMAL_SAMPLE;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
-	queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work,
-		delay);
+	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -730,12 +636,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 
 		mutex_lock(&dbs_mutex);
 
-		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group_old);
-		if (rc) {
-			mutex_unlock(&dbs_mutex);
-			return rc;
-		}
-
 		dbs_enable++;
 		for_each_cpu(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
@@ -788,7 +688,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 		dbs_timer_exit(this_dbs_info);
 
 		mutex_lock(&dbs_mutex);
-		sysfs_remove_group(&policy->kobj, &dbs_attr_group_old);
 		mutex_destroy(&this_dbs_info->timer_mutex);
 		dbs_enable--;
 		mutex_unlock(&dbs_mutex);
@@ -814,7 +713,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	int err;
 	cputime64_t wall;
 	u64 idle_time;
 	int cpu = get_cpu();
@@ -838,22 +736,12 @@ static int __init cpufreq_gov_dbs_init(void)
 			MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
 	}
 
-	kondemand_wq = create_workqueue("kondemand");
-	if (!kondemand_wq) {
-		printk(KERN_ERR "Creation of kondemand failed\n");
-		return -EFAULT;
-	}
-	err = cpufreq_register_governor(&cpufreq_gov_ondemand);
-	if (err)
-		destroy_workqueue(kondemand_wq);
-
-	return err;
+	return cpufreq_register_governor(&cpufreq_gov_ondemand);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_ondemand);
-	destroy_workqueue(kondemand_wq);
 }
 
 
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 0310ffa..be7917ec 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -300,7 +300,7 @@ static struct kobj_type ktype_state_cpuidle = {
 	.release = cpuidle_state_sysfs_release,
 };
 
-static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
 {
 	kobject_put(&device->kobjs[i]->kobj);
 	wait_for_completion(&device->kobjs[i]->kobj_unregister);
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index eab2cf7..e541852 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -252,4 +252,21 @@ config CRYPTO_DEV_OMAP_AES
 	  OMAP processors have AES module accelerator. Select this if you
 	  want to use the OMAP module for AES algorithms.
 
+config CRYPTO_DEV_PICOXCELL
+	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
+	depends on ARCH_PICOXCELL
+	select CRYPTO_AES
+	select CRYPTO_AUTHENC
+	select CRYPTO_ALGAPI
+	select CRYPTO_DES
+	select CRYPTO_CBC
+	select CRYPTO_ECB
+	select CRYPTO_SEQIV
+	help
+	  This option enables support for the hardware offload engines in the
+	  Picochip picoXcell SoC devices. Select this for IPSEC ESP offload
+	  and for 3gpp Layer 2 ciphering support.
+
+	  Saying m here will build a module named pipcoxcell_crypto.
+
 endif # CRYPTO_HW
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 2566973..5203e34 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -10,4 +10,4 @@ obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o
 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
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 2b1baee..1891252 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1150,8 +1150,7 @@ struct crypto4xx_alg_common crypto4xx_alg[] = {
 /**
  * Module Initialization Routine
  */
-static int __init crypto4xx_probe(struct platform_device *ofdev,
-				  const struct of_device_id *match)
+static int __init crypto4xx_probe(struct platform_device *ofdev)
 {
 	int rc;
 	struct resource res;
@@ -1280,7 +1279,7 @@ static const struct of_device_id crypto4xx_match[] = {
 	{ },
 };
 
-static struct of_platform_driver crypto4xx_driver = {
+static struct platform_driver crypto4xx_driver = {
 	.driver = {
 		.name = "crypto4xx",
 		.owner = THIS_MODULE,
@@ -1292,12 +1291,12 @@ static struct of_platform_driver crypto4xx_driver = {
 
 static int __init crypto4xx_init(void)
 {
-	return of_register_platform_driver(&crypto4xx_driver);
+	return platform_driver_register(&crypto4xx_driver);
 }
 
 static void __exit crypto4xx_exit(void)
 {
-	of_unregister_platform_driver(&crypto4xx_driver);
+	platform_driver_unregister(&crypto4xx_driver);
 }
 
 module_init(crypto4xx_init);
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 80dc094..2e5b204 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -2004,8 +2004,7 @@ static void __devinit n2_spu_driver_version(void)
 		pr_info("%s", version);
 }
 
-static int __devinit n2_crypto_probe(struct platform_device *dev,
-				     const struct of_device_id *match)
+static int __devinit n2_crypto_probe(struct platform_device *dev)
 {
 	struct mdesc_handle *mdesc;
 	const char *full_name;
@@ -2116,8 +2115,7 @@ static void free_ncp(struct n2_mau *mp)
 	kfree(mp);
 }
 
-static int __devinit n2_mau_probe(struct platform_device *dev,
-				     const struct of_device_id *match)
+static int __devinit n2_mau_probe(struct platform_device *dev)
 {
 	struct mdesc_handle *mdesc;
 	const char *full_name;
@@ -2211,7 +2209,7 @@ static struct of_device_id n2_crypto_match[] = {
 
 MODULE_DEVICE_TABLE(of, n2_crypto_match);
 
-static struct of_platform_driver n2_crypto_driver = {
+static struct platform_driver n2_crypto_driver = {
 	.driver = {
 		.name		=	"n2cp",
 		.owner		=	THIS_MODULE,
@@ -2235,7 +2233,7 @@ static struct of_device_id n2_mau_match[] = {
 
 MODULE_DEVICE_TABLE(of, n2_mau_match);
 
-static struct of_platform_driver n2_mau_driver = {
+static struct platform_driver n2_mau_driver = {
 	.driver = {
 		.name		=	"ncp",
 		.owner		=	THIS_MODULE,
@@ -2247,20 +2245,20 @@ static struct of_platform_driver n2_mau_driver = {
 
 static int __init n2_init(void)
 {
-	int err = of_register_platform_driver(&n2_crypto_driver);
+	int err = platform_driver_register(&n2_crypto_driver);
 
 	if (!err) {
-		err = of_register_platform_driver(&n2_mau_driver);
+		err = platform_driver_register(&n2_mau_driver);
 		if (err)
-			of_unregister_platform_driver(&n2_crypto_driver);
+			platform_driver_unregister(&n2_crypto_driver);
 	}
 	return err;
 }
 
 static void __exit n2_exit(void)
 {
-	of_unregister_platform_driver(&n2_mau_driver);
-	of_unregister_platform_driver(&n2_crypto_driver);
+	platform_driver_unregister(&n2_mau_driver);
+	platform_driver_unregister(&n2_crypto_driver);
 }
 
 module_init(n2_init);
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index add2a1a..5b970d9 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -839,9 +839,9 @@ static int omap_aes_probe(struct platform_device *pdev)
 
 	/* Initializing the clock */
 	dd->iclk = clk_get(dev, "ick");
-	if (!dd->iclk) {
+	if (IS_ERR(dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
-		err = -ENODEV;
+		err = PTR_ERR(dd->iclk);
 		goto err_res;
 	}
 
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index 2e71123..465cde3 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -1206,9 +1206,9 @@ static int __devinit omap_sham_probe(struct platform_device *pdev)
 
 	/* Initializing the clock */
 	dd->iclk = clk_get(dev, "ick");
-	if (!dd->iclk) {
+	if (IS_ERR(dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
-		err = -ENODEV;
+		err = PTR_ERR(dd->iclk);
 		goto clk_err;
 	}
 
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
new file mode 100644
index 0000000..b092d0a
--- /dev/null
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -0,0 +1,1867 @@
+/*
+ * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 <crypto/aead.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/authenc.h>
+#include <crypto/des.h>
+#include <crypto/md5.h>
+#include <crypto/sha.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/rtnetlink.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+
+#include "picoxcell_crypto_regs.h"
+
+/*
+ * The threshold for the number of entries in the CMD FIFO available before
+ * the CMD0_CNT interrupt is raised. Increasing this value will reduce the
+ * number of interrupts raised to the CPU.
+ */
+#define CMD0_IRQ_THRESHOLD   1
+
+/*
+ * The timeout period (in jiffies) for a PDU. When the the number of PDUs in
+ * flight is greater than the STAT_IRQ_THRESHOLD or 0 the timer is disabled.
+ * When there are packets in flight but lower than the threshold, we enable
+ * the timer and at expiry, attempt to remove any processed packets from the
+ * queue and if there are still packets left, schedule the timer again.
+ */
+#define PACKET_TIMEOUT	    1
+
+/* The priority to register each algorithm with. */
+#define SPACC_CRYPTO_ALG_PRIORITY	10000
+
+#define SPACC_CRYPTO_KASUMI_F8_KEY_LEN	16
+#define SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ 64
+#define SPACC_CRYPTO_IPSEC_HASH_PG_SZ	64
+#define SPACC_CRYPTO_IPSEC_MAX_CTXS	32
+#define SPACC_CRYPTO_IPSEC_FIFO_SZ	32
+#define SPACC_CRYPTO_L2_CIPHER_PG_SZ	64
+#define SPACC_CRYPTO_L2_HASH_PG_SZ	64
+#define SPACC_CRYPTO_L2_MAX_CTXS	128
+#define SPACC_CRYPTO_L2_FIFO_SZ		128
+
+#define MAX_DDT_LEN			16
+
+/* DDT format. This must match the hardware DDT format exactly. */
+struct spacc_ddt {
+	dma_addr_t	p;
+	u32		len;
+};
+
+/*
+ * Asynchronous crypto request structure.
+ *
+ * This structure defines a request that is either queued for processing or
+ * being processed.
+ */
+struct spacc_req {
+	struct list_head		list;
+	struct spacc_engine		*engine;
+	struct crypto_async_request	*req;
+	int				result;
+	bool				is_encrypt;
+	unsigned			ctx_id;
+	dma_addr_t			src_addr, dst_addr;
+	struct spacc_ddt		*src_ddt, *dst_ddt;
+	void				(*complete)(struct spacc_req *req);
+
+	/* AEAD specific bits. */
+	u8				*giv;
+	size_t				giv_len;
+	dma_addr_t			giv_pa;
+};
+
+struct spacc_engine {
+	void __iomem			*regs;
+	struct list_head		pending;
+	int				next_ctx;
+	spinlock_t			hw_lock;
+	int				in_flight;
+	struct list_head		completed;
+	struct list_head		in_progress;
+	struct tasklet_struct		complete;
+	unsigned long			fifo_sz;
+	void __iomem			*cipher_ctx_base;
+	void __iomem			*hash_key_base;
+	struct spacc_alg		*algs;
+	unsigned			num_algs;
+	struct list_head		registered_algs;
+	size_t				cipher_pg_sz;
+	size_t				hash_pg_sz;
+	const char			*name;
+	struct clk			*clk;
+	struct device			*dev;
+	unsigned			max_ctxs;
+	struct timer_list		packet_timeout;
+	unsigned			stat_irq_thresh;
+	struct dma_pool			*req_pool;
+};
+
+/* Algorithm type mask. */
+#define SPACC_CRYPTO_ALG_MASK		0x7
+
+/* SPACC definition of a crypto algorithm. */
+struct spacc_alg {
+	unsigned long			ctrl_default;
+	unsigned long			type;
+	struct crypto_alg		alg;
+	struct spacc_engine		*engine;
+	struct list_head		entry;
+	int				key_offs;
+	int				iv_offs;
+};
+
+/* Generic context structure for any algorithm type. */
+struct spacc_generic_ctx {
+	struct spacc_engine		*engine;
+	int				flags;
+	int				key_offs;
+	int				iv_offs;
+};
+
+/* Block cipher context. */
+struct spacc_ablk_ctx {
+	struct spacc_generic_ctx	generic;
+	u8				key[AES_MAX_KEY_SIZE];
+	u8				key_len;
+	/*
+	 * The fallback cipher. If the operation can't be done in hardware,
+	 * fallback to a software version.
+	 */
+	struct crypto_ablkcipher	*sw_cipher;
+};
+
+/* AEAD cipher context. */
+struct spacc_aead_ctx {
+	struct spacc_generic_ctx	generic;
+	u8				cipher_key[AES_MAX_KEY_SIZE];
+	u8				hash_ctx[SPACC_CRYPTO_IPSEC_HASH_PG_SZ];
+	u8				cipher_key_len;
+	u8				hash_key_len;
+	struct crypto_aead		*sw_cipher;
+	size_t				auth_size;
+	u8				salt[AES_BLOCK_SIZE];
+};
+
+static inline struct spacc_alg *to_spacc_alg(struct crypto_alg *alg)
+{
+	return alg ? container_of(alg, struct spacc_alg, alg) : NULL;
+}
+
+static inline int spacc_fifo_cmd_full(struct spacc_engine *engine)
+{
+	u32 fifo_stat = readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET);
+
+	return fifo_stat & SPA_FIFO_CMD_FULL;
+}
+
+/*
+ * Given a cipher context, and a context number, get the base address of the
+ * context page.
+ *
+ * Returns the address of the context page where the key/context may
+ * be written.
+ */
+static inline void __iomem *spacc_ctx_page_addr(struct spacc_generic_ctx *ctx,
+						unsigned indx,
+						bool is_cipher_ctx)
+{
+	return is_cipher_ctx ? ctx->engine->cipher_ctx_base +
+			(indx * ctx->engine->cipher_pg_sz) :
+		ctx->engine->hash_key_base + (indx * ctx->engine->hash_pg_sz);
+}
+
+/* The context pages can only be written with 32-bit accesses. */
+static inline void memcpy_toio32(u32 __iomem *dst, const void *src,
+				 unsigned count)
+{
+	const u32 *src32 = (const u32 *) src;
+
+	while (count--)
+		writel(*src32++, dst++);
+}
+
+static void spacc_cipher_write_ctx(struct spacc_generic_ctx *ctx,
+				   void __iomem *page_addr, const u8 *key,
+				   size_t key_len, const u8 *iv, size_t iv_len)
+{
+	void __iomem *key_ptr = page_addr + ctx->key_offs;
+	void __iomem *iv_ptr = page_addr + ctx->iv_offs;
+
+	memcpy_toio32(key_ptr, key, key_len / 4);
+	memcpy_toio32(iv_ptr, iv, iv_len / 4);
+}
+
+/*
+ * Load a context into the engines context memory.
+ *
+ * Returns the index of the context page where the context was loaded.
+ */
+static unsigned spacc_load_ctx(struct spacc_generic_ctx *ctx,
+			       const u8 *ciph_key, size_t ciph_len,
+			       const u8 *iv, size_t ivlen, const u8 *hash_key,
+			       size_t hash_len)
+{
+	unsigned indx = ctx->engine->next_ctx++;
+	void __iomem *ciph_page_addr, *hash_page_addr;
+
+	ciph_page_addr = spacc_ctx_page_addr(ctx, indx, 1);
+	hash_page_addr = spacc_ctx_page_addr(ctx, indx, 0);
+
+	ctx->engine->next_ctx &= ctx->engine->fifo_sz - 1;
+	spacc_cipher_write_ctx(ctx, ciph_page_addr, ciph_key, ciph_len, iv,
+			       ivlen);
+	writel(ciph_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET) |
+	       (1 << SPA_KEY_SZ_CIPHER_OFFSET),
+	       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
+
+	if (hash_key) {
+		memcpy_toio32(hash_page_addr, hash_key, hash_len / 4);
+		writel(hash_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET),
+		       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
+	}
+
+	return indx;
+}
+
+/* Count the number of scatterlist entries in a scatterlist. */
+static int sg_count(struct scatterlist *sg_list, int nbytes)
+{
+	struct scatterlist *sg = sg_list;
+	int sg_nents = 0;
+
+	while (nbytes > 0) {
+		++sg_nents;
+		nbytes -= sg->length;
+		sg = sg_next(sg);
+	}
+
+	return sg_nents;
+}
+
+static inline void ddt_set(struct spacc_ddt *ddt, dma_addr_t phys, size_t len)
+{
+	ddt->p = phys;
+	ddt->len = len;
+}
+
+/*
+ * Take a crypto request and scatterlists for the data and turn them into DDTs
+ * for passing to the crypto engines. This also DMA maps the data so that the
+ * crypto engines can DMA to/from them.
+ */
+static struct spacc_ddt *spacc_sg_to_ddt(struct spacc_engine *engine,
+					 struct scatterlist *payload,
+					 unsigned nbytes,
+					 enum dma_data_direction dir,
+					 dma_addr_t *ddt_phys)
+{
+	unsigned nents, mapped_ents;
+	struct scatterlist *cur;
+	struct spacc_ddt *ddt;
+	int i;
+
+	nents = sg_count(payload, nbytes);
+	mapped_ents = dma_map_sg(engine->dev, payload, nents, dir);
+
+	if (mapped_ents + 1 > MAX_DDT_LEN)
+		goto out;
+
+	ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, ddt_phys);
+	if (!ddt)
+		goto out;
+
+	for_each_sg(payload, cur, mapped_ents, i)
+		ddt_set(&ddt[i], sg_dma_address(cur), sg_dma_len(cur));
+	ddt_set(&ddt[mapped_ents], 0, 0);
+
+	return ddt;
+
+out:
+	dma_unmap_sg(engine->dev, payload, nents, dir);
+	return NULL;
+}
+
+static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
+{
+	struct aead_request *areq = container_of(req->req, struct aead_request,
+						 base);
+	struct spacc_engine *engine = req->engine;
+	struct spacc_ddt *src_ddt, *dst_ddt;
+	unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(areq));
+	unsigned nents = sg_count(areq->src, areq->cryptlen);
+	dma_addr_t iv_addr;
+	struct scatterlist *cur;
+	int i, dst_ents, src_ents, assoc_ents;
+	u8 *iv = giv ? giv : areq->iv;
+
+	src_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->src_addr);
+	if (!src_ddt)
+		return -ENOMEM;
+
+	dst_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->dst_addr);
+	if (!dst_ddt) {
+		dma_pool_free(engine->req_pool, src_ddt, req->src_addr);
+		return -ENOMEM;
+	}
+
+	req->src_ddt = src_ddt;
+	req->dst_ddt = dst_ddt;
+
+	assoc_ents = dma_map_sg(engine->dev, areq->assoc,
+		sg_count(areq->assoc, areq->assoclen), DMA_TO_DEVICE);
+	if (areq->src != areq->dst) {
+		src_ents = dma_map_sg(engine->dev, areq->src, nents,
+				      DMA_TO_DEVICE);
+		dst_ents = dma_map_sg(engine->dev, areq->dst, nents,
+				      DMA_FROM_DEVICE);
+	} else {
+		src_ents = dma_map_sg(engine->dev, areq->src, nents,
+				      DMA_BIDIRECTIONAL);
+		dst_ents = 0;
+	}
+
+	/*
+	 * Map the IV/GIV. For the GIV it needs to be bidirectional as it is
+	 * formed by the crypto block and sent as the ESP IV for IPSEC.
+	 */
+	iv_addr = dma_map_single(engine->dev, iv, ivsize,
+				 giv ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+	req->giv_pa = iv_addr;
+
+	/*
+	 * Map the associated data. For decryption we don't copy the
+	 * associated data.
+	 */
+	for_each_sg(areq->assoc, cur, assoc_ents, i) {
+		ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
+		if (req->is_encrypt)
+			ddt_set(dst_ddt++, sg_dma_address(cur),
+				sg_dma_len(cur));
+	}
+	ddt_set(src_ddt++, iv_addr, ivsize);
+
+	if (giv || req->is_encrypt)
+		ddt_set(dst_ddt++, iv_addr, ivsize);
+
+	/*
+	 * Now map in the payload for the source and destination and terminate
+	 * with the NULL pointers.
+	 */
+	for_each_sg(areq->src, cur, src_ents, i) {
+		ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
+		if (areq->src == areq->dst)
+			ddt_set(dst_ddt++, sg_dma_address(cur),
+				sg_dma_len(cur));
+	}
+
+	for_each_sg(areq->dst, cur, dst_ents, i)
+		ddt_set(dst_ddt++, sg_dma_address(cur),
+			sg_dma_len(cur));
+
+	ddt_set(src_ddt, 0, 0);
+	ddt_set(dst_ddt, 0, 0);
+
+	return 0;
+}
+
+static void spacc_aead_free_ddts(struct spacc_req *req)
+{
+	struct aead_request *areq = container_of(req->req, struct aead_request,
+						 base);
+	struct spacc_alg *alg = to_spacc_alg(req->req->tfm->__crt_alg);
+	struct spacc_ablk_ctx *aead_ctx = crypto_tfm_ctx(req->req->tfm);
+	struct spacc_engine *engine = aead_ctx->generic.engine;
+	unsigned ivsize = alg->alg.cra_aead.ivsize;
+	unsigned nents = sg_count(areq->src, areq->cryptlen);
+
+	if (areq->src != areq->dst) {
+		dma_unmap_sg(engine->dev, areq->src, nents, DMA_TO_DEVICE);
+		dma_unmap_sg(engine->dev, areq->dst,
+			     sg_count(areq->dst, areq->cryptlen),
+			     DMA_FROM_DEVICE);
+	} else
+		dma_unmap_sg(engine->dev, areq->src, nents, DMA_BIDIRECTIONAL);
+
+	dma_unmap_sg(engine->dev, areq->assoc,
+		     sg_count(areq->assoc, areq->assoclen), DMA_TO_DEVICE);
+
+	dma_unmap_single(engine->dev, req->giv_pa, ivsize, DMA_BIDIRECTIONAL);
+
+	dma_pool_free(engine->req_pool, req->src_ddt, req->src_addr);
+	dma_pool_free(engine->req_pool, req->dst_ddt, req->dst_addr);
+}
+
+static void spacc_free_ddt(struct spacc_req *req, struct spacc_ddt *ddt,
+			   dma_addr_t ddt_addr, struct scatterlist *payload,
+			   unsigned nbytes, enum dma_data_direction dir)
+{
+	unsigned nents = sg_count(payload, nbytes);
+
+	dma_unmap_sg(req->engine->dev, payload, nents, dir);
+	dma_pool_free(req->engine->req_pool, ddt, ddt_addr);
+}
+
+/*
+ * Set key for a DES operation in an AEAD cipher. This also performs weak key
+ * checking if required.
+ */
+static int spacc_aead_des_setkey(struct crypto_aead *aead, const u8 *key,
+				 unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 tmp[DES_EXPKEY_WORDS];
+
+	if (unlikely(!des_ekey(tmp, key)) &&
+	    (crypto_aead_get_flags(aead)) & CRYPTO_TFM_REQ_WEAK_KEY) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
+	memcpy(ctx->cipher_key, key, len);
+	ctx->cipher_key_len = len;
+
+	return 0;
+}
+
+/* Set the key for the AES block cipher component of the AEAD transform. */
+static int spacc_aead_aes_setkey(struct crypto_aead *aead, const u8 *key,
+				 unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	/*
+	 * IPSec engine only supports 128 and 256 bit AES keys. If we get a
+	 * request for any other size (192 bits) then we need to do a software
+	 * fallback.
+	 */
+	if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256) {
+		/*
+		 * Set the fallback transform to use the same request flags as
+		 * the hardware transform.
+		 */
+		ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+		ctx->sw_cipher->base.crt_flags |=
+			tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
+		return crypto_aead_setkey(ctx->sw_cipher, key, len);
+	}
+
+	memcpy(ctx->cipher_key, key, len);
+	ctx->cipher_key_len = len;
+
+	return 0;
+}
+
+static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
+			     unsigned int keylen)
+{
+	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+	struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
+	struct rtattr *rta = (void *)key;
+	struct crypto_authenc_key_param *param;
+	unsigned int authkeylen, enckeylen;
+	int err = -EINVAL;
+
+	if (!RTA_OK(rta, keylen))
+		goto badkey;
+
+	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+		goto badkey;
+
+	if (RTA_PAYLOAD(rta) < sizeof(*param))
+		goto badkey;
+
+	param = RTA_DATA(rta);
+	enckeylen = be32_to_cpu(param->enckeylen);
+
+	key += RTA_ALIGN(rta->rta_len);
+	keylen -= RTA_ALIGN(rta->rta_len);
+
+	if (keylen < enckeylen)
+		goto badkey;
+
+	authkeylen = keylen - enckeylen;
+
+	if (enckeylen > AES_MAX_KEY_SIZE)
+		goto badkey;
+
+	if ((alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
+	    SPA_CTRL_CIPH_ALG_AES)
+		err = spacc_aead_aes_setkey(tfm, key + authkeylen, enckeylen);
+	else
+		err = spacc_aead_des_setkey(tfm, key + authkeylen, enckeylen);
+
+	if (err)
+		goto badkey;
+
+	memcpy(ctx->hash_ctx, key, authkeylen);
+	ctx->hash_key_len = authkeylen;
+
+	return 0;
+
+badkey:
+	crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	return -EINVAL;
+}
+
+static int spacc_aead_setauthsize(struct crypto_aead *tfm,
+				  unsigned int authsize)
+{
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(crypto_aead_tfm(tfm));
+
+	ctx->auth_size = authsize;
+
+	return 0;
+}
+
+/*
+ * Check if an AEAD request requires a fallback operation. Some requests can't
+ * be completed in hardware because the hardware may not support certain key
+ * sizes. In these cases we need to complete the request in software.
+ */
+static int spacc_aead_need_fallback(struct spacc_req *req)
+{
+	struct aead_request *aead_req;
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	aead_req = container_of(req->req, struct aead_request, base);
+	/*
+	 * If we have a non-supported key-length, then we need to do a
+	 * software fallback.
+	 */
+	if ((spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
+	    SPA_CTRL_CIPH_ALG_AES &&
+	    ctx->cipher_key_len != AES_KEYSIZE_128 &&
+	    ctx->cipher_key_len != AES_KEYSIZE_256)
+		return 1;
+
+	return 0;
+}
+
+static int spacc_aead_do_fallback(struct aead_request *req, unsigned alg_type,
+				  bool is_encrypt)
+{
+	struct crypto_tfm *old_tfm = crypto_aead_tfm(crypto_aead_reqtfm(req));
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(old_tfm);
+	int err;
+
+	if (ctx->sw_cipher) {
+		/*
+		 * Change the request to use the software fallback transform,
+		 * and once the ciphering has completed, put the old transform
+		 * back into the request.
+		 */
+		aead_request_set_tfm(req, ctx->sw_cipher);
+		err = is_encrypt ? crypto_aead_encrypt(req) :
+		    crypto_aead_decrypt(req);
+		aead_request_set_tfm(req, __crypto_aead_cast(old_tfm));
+	} else
+		err = -EINVAL;
+
+	return err;
+}
+
+static void spacc_aead_complete(struct spacc_req *req)
+{
+	spacc_aead_free_ddts(req);
+	req->req->complete(req->req, req->result);
+}
+
+static int spacc_aead_submit(struct spacc_req *req)
+{
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = ctx->generic.engine;
+	u32 ctrl, proc_len, assoc_len;
+	struct aead_request *aead_req =
+		container_of(req->req, struct aead_request, base);
+
+	req->result = -EINPROGRESS;
+	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->cipher_key,
+		ctx->cipher_key_len, aead_req->iv, alg->cra_aead.ivsize,
+		ctx->hash_ctx, ctx->hash_key_len);
+
+	/* Set the source and destination DDT pointers. */
+	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
+	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
+	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
+
+	assoc_len = aead_req->assoclen;
+	proc_len = aead_req->cryptlen + assoc_len;
+
+	/*
+	 * If we aren't generating an IV, then we need to include the IV in the
+	 * associated data so that it is included in the hash.
+	 */
+	if (!req->giv) {
+		assoc_len += crypto_aead_ivsize(crypto_aead_reqtfm(aead_req));
+		proc_len += crypto_aead_ivsize(crypto_aead_reqtfm(aead_req));
+	} else
+		proc_len += req->giv_len;
+
+	/*
+	 * If we are decrypting, we need to take the length of the ICV out of
+	 * the processing length.
+	 */
+	if (!req->is_encrypt)
+		proc_len -= ctx->auth_size;
+
+	writel(proc_len, engine->regs + SPA_PROC_LEN_REG_OFFSET);
+	writel(assoc_len, engine->regs + SPA_AAD_LEN_REG_OFFSET);
+	writel(ctx->auth_size, engine->regs + SPA_ICV_LEN_REG_OFFSET);
+	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
+	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
+
+	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
+		(1 << SPA_CTRL_ICV_APPEND);
+	if (req->is_encrypt)
+		ctrl |= (1 << SPA_CTRL_ENCRYPT_IDX) | (1 << SPA_CTRL_AAD_COPY);
+	else
+		ctrl |= (1 << SPA_CTRL_KEY_EXP);
+
+	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
+
+	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
+
+	return -EINPROGRESS;
+}
+
+/*
+ * Setup an AEAD request for processing. This will configure the engine, load
+ * the context and then start the packet processing.
+ *
+ * @giv Pointer to destination address for a generated IV. If the
+ *	request does not need to generate an IV then this should be set to NULL.
+ */
+static int spacc_aead_setup(struct aead_request *req, u8 *giv,
+			    unsigned alg_type, bool is_encrypt)
+{
+	struct crypto_alg *alg = req->base.tfm->__crt_alg;
+	struct spacc_engine *engine = to_spacc_alg(alg)->engine;
+	struct spacc_req *dev_req = aead_request_ctx(req);
+	int err = -EINPROGRESS;
+	unsigned long flags;
+	unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(req));
+
+	dev_req->giv		= giv;
+	dev_req->giv_len	= ivsize;
+	dev_req->req		= &req->base;
+	dev_req->is_encrypt	= is_encrypt;
+	dev_req->result		= -EBUSY;
+	dev_req->engine		= engine;
+	dev_req->complete	= spacc_aead_complete;
+
+	if (unlikely(spacc_aead_need_fallback(dev_req)))
+		return spacc_aead_do_fallback(req, alg_type, is_encrypt);
+
+	spacc_aead_make_ddts(dev_req, dev_req->giv);
+
+	err = -EINPROGRESS;
+	spin_lock_irqsave(&engine->hw_lock, flags);
+	if (unlikely(spacc_fifo_cmd_full(engine))) {
+		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
+			err = -EBUSY;
+			spin_unlock_irqrestore(&engine->hw_lock, flags);
+			goto out_free_ddts;
+		}
+		list_add_tail(&dev_req->list, &engine->pending);
+	} else {
+		++engine->in_flight;
+		list_add_tail(&dev_req->list, &engine->in_progress);
+		spacc_aead_submit(dev_req);
+	}
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+
+	goto out;
+
+out_free_ddts:
+	spacc_aead_free_ddts(dev_req);
+out:
+	return err;
+}
+
+static int spacc_aead_encrypt(struct aead_request *req)
+{
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_aead_setup(req, NULL, alg->type, 1);
+}
+
+static int spacc_aead_givencrypt(struct aead_givcrypt_request *req)
+{
+	struct crypto_aead *tfm = aead_givcrypt_reqtfm(req);
+	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+	size_t ivsize = crypto_aead_ivsize(tfm);
+	struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
+	unsigned len;
+	__be64 seq;
+
+	memcpy(req->areq.iv, ctx->salt, ivsize);
+	len = ivsize;
+	if (ivsize > sizeof(u64)) {
+		memset(req->giv, 0, ivsize - sizeof(u64));
+		len = sizeof(u64);
+	}
+	seq = cpu_to_be64(req->seq);
+	memcpy(req->giv + ivsize - len, &seq, len);
+
+	return spacc_aead_setup(&req->areq, req->giv, alg->type, 1);
+}
+
+static int spacc_aead_decrypt(struct aead_request *req)
+{
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_aead_setup(req, NULL, alg->type, 0);
+}
+
+/*
+ * Initialise a new AEAD context. This is responsible for allocating the
+ * fallback cipher and initialising the context.
+ */
+static int spacc_aead_cra_init(struct crypto_tfm *tfm)
+{
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = spacc_alg->engine;
+
+	ctx->generic.flags = spacc_alg->type;
+	ctx->generic.engine = engine;
+	ctx->sw_cipher = crypto_alloc_aead(alg->cra_name, 0,
+					   CRYPTO_ALG_ASYNC |
+					   CRYPTO_ALG_NEED_FALLBACK);
+	if (IS_ERR(ctx->sw_cipher)) {
+		dev_warn(engine->dev, "failed to allocate fallback for %s\n",
+			 alg->cra_name);
+		ctx->sw_cipher = NULL;
+	}
+	ctx->generic.key_offs = spacc_alg->key_offs;
+	ctx->generic.iv_offs = spacc_alg->iv_offs;
+
+	get_random_bytes(ctx->salt, sizeof(ctx->salt));
+
+	tfm->crt_aead.reqsize = sizeof(struct spacc_req);
+
+	return 0;
+}
+
+/*
+ * Destructor for an AEAD context. This is called when the transform is freed
+ * and must free the fallback cipher.
+ */
+static void spacc_aead_cra_exit(struct crypto_tfm *tfm)
+{
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->sw_cipher)
+		crypto_free_aead(ctx->sw_cipher);
+	ctx->sw_cipher = NULL;
+}
+
+/*
+ * Set the DES key for a block cipher transform. This also performs weak key
+ * checking if the transform has requested it.
+ */
+static int spacc_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
+			    unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 tmp[DES_EXPKEY_WORDS];
+
+	if (len > DES3_EDE_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	if (unlikely(!des_ekey(tmp, key)) &&
+	    (crypto_ablkcipher_get_flags(cipher) & CRYPTO_TFM_REQ_WEAK_KEY)) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
+	memcpy(ctx->key, key, len);
+	ctx->key_len = len;
+
+	return 0;
+}
+
+/*
+ * Set the key for an AES block cipher. Some key lengths are not supported in
+ * hardware so this must also check whether a fallback is needed.
+ */
+static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
+			    unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	int err = 0;
+
+	if (len > AES_MAX_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	/*
+	 * IPSec engine only supports 128 and 256 bit AES keys. If we get a
+	 * request for any other size (192 bits) then we need to do a software
+	 * fallback.
+	 */
+	if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+	    ctx->sw_cipher) {
+		/*
+		 * Set the fallback transform to use the same request flags as
+		 * the hardware transform.
+		 */
+		ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+		ctx->sw_cipher->base.crt_flags |=
+			cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK;
+
+		err = crypto_ablkcipher_setkey(ctx->sw_cipher, key, len);
+		if (err)
+			goto sw_setkey_failed;
+	} else if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+		   !ctx->sw_cipher)
+		err = -EINVAL;
+
+	memcpy(ctx->key, key, len);
+	ctx->key_len = len;
+
+sw_setkey_failed:
+	if (err && ctx->sw_cipher) {
+		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+		tfm->crt_flags |=
+			ctx->sw_cipher->base.crt_flags & CRYPTO_TFM_RES_MASK;
+	}
+
+	return err;
+}
+
+static int spacc_kasumi_f8_setkey(struct crypto_ablkcipher *cipher,
+				  const u8 *key, unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	int err = 0;
+
+	if (len > AES_MAX_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		err = -EINVAL;
+		goto out;
+	}
+
+	memcpy(ctx->key, key, len);
+	ctx->key_len = len;
+
+out:
+	return err;
+}
+
+static int spacc_ablk_need_fallback(struct spacc_req *req)
+{
+	struct spacc_ablk_ctx *ctx;
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+
+	ctx = crypto_tfm_ctx(tfm);
+
+	return (spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
+			SPA_CTRL_CIPH_ALG_AES &&
+			ctx->key_len != AES_KEYSIZE_128 &&
+			ctx->key_len != AES_KEYSIZE_256;
+}
+
+static void spacc_ablk_complete(struct spacc_req *req)
+{
+	struct ablkcipher_request *ablk_req =
+		container_of(req->req, struct ablkcipher_request, base);
+
+	if (ablk_req->src != ablk_req->dst) {
+		spacc_free_ddt(req, req->src_ddt, req->src_addr, ablk_req->src,
+			       ablk_req->nbytes, DMA_TO_DEVICE);
+		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
+			       ablk_req->nbytes, DMA_FROM_DEVICE);
+	} else
+		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
+			       ablk_req->nbytes, DMA_BIDIRECTIONAL);
+
+	req->req->complete(req->req, req->result);
+}
+
+static int spacc_ablk_submit(struct spacc_req *req)
+{
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct ablkcipher_request *ablk_req = ablkcipher_request_cast(req->req);
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = ctx->generic.engine;
+	u32 ctrl;
+
+	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->key,
+		ctx->key_len, ablk_req->info, alg->cra_ablkcipher.ivsize,
+		NULL, 0);
+
+	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
+	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
+	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
+
+	writel(ablk_req->nbytes, engine->regs + SPA_PROC_LEN_REG_OFFSET);
+	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
+	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
+	writel(0, engine->regs + SPA_AAD_LEN_REG_OFFSET);
+
+	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
+		(req->is_encrypt ? (1 << SPA_CTRL_ENCRYPT_IDX) :
+		 (1 << SPA_CTRL_KEY_EXP));
+
+	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
+
+	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
+
+	return -EINPROGRESS;
+}
+
+static int spacc_ablk_do_fallback(struct ablkcipher_request *req,
+				  unsigned alg_type, bool is_encrypt)
+{
+	struct crypto_tfm *old_tfm =
+	    crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(old_tfm);
+	int err;
+
+	if (!ctx->sw_cipher)
+		return -EINVAL;
+
+	/*
+	 * Change the request to use the software fallback transform, and once
+	 * the ciphering has completed, put the old transform back into the
+	 * request.
+	 */
+	ablkcipher_request_set_tfm(req, ctx->sw_cipher);
+	err = is_encrypt ? crypto_ablkcipher_encrypt(req) :
+		crypto_ablkcipher_decrypt(req);
+	ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(old_tfm));
+
+	return err;
+}
+
+static int spacc_ablk_setup(struct ablkcipher_request *req, unsigned alg_type,
+			    bool is_encrypt)
+{
+	struct crypto_alg *alg = req->base.tfm->__crt_alg;
+	struct spacc_engine *engine = to_spacc_alg(alg)->engine;
+	struct spacc_req *dev_req = ablkcipher_request_ctx(req);
+	unsigned long flags;
+	int err = -ENOMEM;
+
+	dev_req->req		= &req->base;
+	dev_req->is_encrypt	= is_encrypt;
+	dev_req->engine		= engine;
+	dev_req->complete	= spacc_ablk_complete;
+	dev_req->result		= -EINPROGRESS;
+
+	if (unlikely(spacc_ablk_need_fallback(dev_req)))
+		return spacc_ablk_do_fallback(req, alg_type, is_encrypt);
+
+	/*
+	 * Create the DDT's for the engine. If we share the same source and
+	 * destination then we can optimize by reusing the DDT's.
+	 */
+	if (req->src != req->dst) {
+		dev_req->src_ddt = spacc_sg_to_ddt(engine, req->src,
+			req->nbytes, DMA_TO_DEVICE, &dev_req->src_addr);
+		if (!dev_req->src_ddt)
+			goto out;
+
+		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
+			req->nbytes, DMA_FROM_DEVICE, &dev_req->dst_addr);
+		if (!dev_req->dst_ddt)
+			goto out_free_src;
+	} else {
+		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
+			req->nbytes, DMA_BIDIRECTIONAL, &dev_req->dst_addr);
+		if (!dev_req->dst_ddt)
+			goto out;
+
+		dev_req->src_ddt = NULL;
+		dev_req->src_addr = dev_req->dst_addr;
+	}
+
+	err = -EINPROGRESS;
+	spin_lock_irqsave(&engine->hw_lock, flags);
+	/*
+	 * Check if the engine will accept the operation now. If it won't then
+	 * we either stick it on the end of a pending list if we can backlog,
+	 * or bailout with an error if not.
+	 */
+	if (unlikely(spacc_fifo_cmd_full(engine))) {
+		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
+			err = -EBUSY;
+			spin_unlock_irqrestore(&engine->hw_lock, flags);
+			goto out_free_ddts;
+		}
+		list_add_tail(&dev_req->list, &engine->pending);
+	} else {
+		++engine->in_flight;
+		list_add_tail(&dev_req->list, &engine->in_progress);
+		spacc_ablk_submit(dev_req);
+	}
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+
+	goto out;
+
+out_free_ddts:
+	spacc_free_ddt(dev_req, dev_req->dst_ddt, dev_req->dst_addr, req->dst,
+		       req->nbytes, req->src == req->dst ?
+		       DMA_BIDIRECTIONAL : DMA_FROM_DEVICE);
+out_free_src:
+	if (req->src != req->dst)
+		spacc_free_ddt(dev_req, dev_req->src_ddt, dev_req->src_addr,
+			       req->src, req->nbytes, DMA_TO_DEVICE);
+out:
+	return err;
+}
+
+static int spacc_ablk_cra_init(struct crypto_tfm *tfm)
+{
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = spacc_alg->engine;
+
+	ctx->generic.flags = spacc_alg->type;
+	ctx->generic.engine = engine;
+	if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
+		ctx->sw_cipher = crypto_alloc_ablkcipher(alg->cra_name, 0,
+				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+		if (IS_ERR(ctx->sw_cipher)) {
+			dev_warn(engine->dev, "failed to allocate fallback for %s\n",
+				 alg->cra_name);
+			ctx->sw_cipher = NULL;
+		}
+	}
+	ctx->generic.key_offs = spacc_alg->key_offs;
+	ctx->generic.iv_offs = spacc_alg->iv_offs;
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct spacc_req);
+
+	return 0;
+}
+
+static void spacc_ablk_cra_exit(struct crypto_tfm *tfm)
+{
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->sw_cipher)
+		crypto_free_ablkcipher(ctx->sw_cipher);
+	ctx->sw_cipher = NULL;
+}
+
+static int spacc_ablk_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_ablk_setup(req, alg->type, 1);
+}
+
+static int spacc_ablk_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_ablk_setup(req, alg->type, 0);
+}
+
+static inline int spacc_fifo_stat_empty(struct spacc_engine *engine)
+{
+	return readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET) &
+		SPA_FIFO_STAT_EMPTY;
+}
+
+static void spacc_process_done(struct spacc_engine *engine)
+{
+	struct spacc_req *req;
+	unsigned long flags;
+
+	spin_lock_irqsave(&engine->hw_lock, flags);
+
+	while (!spacc_fifo_stat_empty(engine)) {
+		req = list_first_entry(&engine->in_progress, struct spacc_req,
+				       list);
+		list_move_tail(&req->list, &engine->completed);
+
+		/* POP the status register. */
+		writel(~0, engine->regs + SPA_STAT_POP_REG_OFFSET);
+		req->result = (readl(engine->regs + SPA_STATUS_REG_OFFSET) &
+		     SPA_STATUS_RES_CODE_MASK) >> SPA_STATUS_RES_CODE_OFFSET;
+
+		/*
+		 * Convert the SPAcc error status into the standard POSIX error
+		 * codes.
+		 */
+		if (unlikely(req->result)) {
+			switch (req->result) {
+			case SPA_STATUS_ICV_FAIL:
+				req->result = -EBADMSG;
+				break;
+
+			case SPA_STATUS_MEMORY_ERROR:
+				dev_warn(engine->dev,
+					 "memory error triggered\n");
+				req->result = -EFAULT;
+				break;
+
+			case SPA_STATUS_BLOCK_ERROR:
+				dev_warn(engine->dev,
+					 "block error triggered\n");
+				req->result = -EIO;
+				break;
+			}
+		}
+	}
+
+	tasklet_schedule(&engine->complete);
+
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+}
+
+static irqreturn_t spacc_spacc_irq(int irq, void *dev)
+{
+	struct spacc_engine *engine = (struct spacc_engine *)dev;
+	u32 spacc_irq_stat = readl(engine->regs + SPA_IRQ_STAT_REG_OFFSET);
+
+	writel(spacc_irq_stat, engine->regs + SPA_IRQ_STAT_REG_OFFSET);
+	spacc_process_done(engine);
+
+	return IRQ_HANDLED;
+}
+
+static void spacc_packet_timeout(unsigned long data)
+{
+	struct spacc_engine *engine = (struct spacc_engine *)data;
+
+	spacc_process_done(engine);
+}
+
+static int spacc_req_submit(struct spacc_req *req)
+{
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+
+	if (CRYPTO_ALG_TYPE_AEAD == (CRYPTO_ALG_TYPE_MASK & alg->cra_flags))
+		return spacc_aead_submit(req);
+	else
+		return spacc_ablk_submit(req);
+}
+
+static void spacc_spacc_complete(unsigned long data)
+{
+	struct spacc_engine *engine = (struct spacc_engine *)data;
+	struct spacc_req *req, *tmp;
+	unsigned long flags;
+	int num_removed = 0;
+	LIST_HEAD(completed);
+
+	spin_lock_irqsave(&engine->hw_lock, flags);
+	list_splice_init(&engine->completed, &completed);
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+
+	list_for_each_entry_safe(req, tmp, &completed, list) {
+		++num_removed;
+		req->complete(req);
+	}
+
+	/* Try and fill the engine back up again. */
+	spin_lock_irqsave(&engine->hw_lock, flags);
+
+	engine->in_flight -= num_removed;
+
+	list_for_each_entry_safe(req, tmp, &engine->pending, list) {
+		if (spacc_fifo_cmd_full(engine))
+			break;
+
+		list_move_tail(&req->list, &engine->in_progress);
+		++engine->in_flight;
+		req->result = spacc_req_submit(req);
+	}
+
+	if (engine->in_flight)
+		mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
+
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+}
+
+#ifdef CONFIG_PM
+static int spacc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct spacc_engine *engine = platform_get_drvdata(pdev);
+
+	/*
+	 * We only support standby mode. All we have to do is gate the clock to
+	 * the spacc. The hardware will preserve state until we turn it back
+	 * on again.
+	 */
+	clk_disable(engine->clk);
+
+	return 0;
+}
+
+static int spacc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct spacc_engine *engine = platform_get_drvdata(pdev);
+
+	return clk_enable(engine->clk);
+}
+
+static const struct dev_pm_ops spacc_pm_ops = {
+	.suspend	= spacc_suspend,
+	.resume		= spacc_resume,
+};
+#endif /* CONFIG_PM */
+
+static inline struct spacc_engine *spacc_dev_to_engine(struct device *dev)
+{
+	return dev ? platform_get_drvdata(to_platform_device(dev)) : NULL;
+}
+
+static ssize_t spacc_stat_irq_thresh_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct spacc_engine *engine = spacc_dev_to_engine(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", engine->stat_irq_thresh);
+}
+
+static ssize_t spacc_stat_irq_thresh_store(struct device *dev,
+					   struct device_attribute *attr,
+					   const char *buf, size_t len)
+{
+	struct spacc_engine *engine = spacc_dev_to_engine(dev);
+	unsigned long thresh;
+
+	if (strict_strtoul(buf, 0, &thresh))
+		return -EINVAL;
+
+	thresh = clamp(thresh, 1UL, engine->fifo_sz - 1);
+
+	engine->stat_irq_thresh = thresh;
+	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
+	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
+
+	return len;
+}
+static DEVICE_ATTR(stat_irq_thresh, 0644, spacc_stat_irq_thresh_show,
+		   spacc_stat_irq_thresh_store);
+
+static struct spacc_alg ipsec_engine_algs[] = {
+	{
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC,
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.alg = {
+			.cra_name = "cbc(aes)",
+			.cra_driver_name = "cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				     CRYPTO_ALG_ASYNC |
+				     CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_aes_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = AES_MIN_KEY_SIZE,
+				.max_keysize = AES_MAX_KEY_SIZE,
+				.ivsize = AES_BLOCK_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_ECB,
+		.alg = {
+			.cra_name = "ecb(aes)",
+			.cra_driver_name = "ecb-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_aes_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = AES_MIN_KEY_SIZE,
+				.max_keysize = AES_MAX_KEY_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
+		.alg = {
+			.cra_name = "cbc(des)",
+			.cra_driver_name = "cbc-des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES_KEY_SIZE,
+				.max_keysize = DES_KEY_SIZE,
+				.ivsize = DES_BLOCK_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
+		.alg = {
+			.cra_name = "ecb(des)",
+			.cra_driver_name = "ecb-des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES_KEY_SIZE,
+				.max_keysize = DES_KEY_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
+		.alg = {
+			.cra_name = "cbc(des3_ede)",
+			.cra_driver_name = "cbc-des3-ede-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES3_EDE_KEY_SIZE,
+				.max_keysize = DES3_EDE_KEY_SIZE,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
+		.alg = {
+			.cra_name = "ecb(des3_ede)",
+			.cra_driver_name = "ecb-des3-ede-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES3_EDE_KEY_SIZE,
+				.max_keysize = DES3_EDE_KEY_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA | SPA_CTRL_HASH_MODE_HMAC,
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.alg = {
+			.cra_name = "authenc(hmac(sha1),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = SHA1_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA256 |
+				SPA_CTRL_HASH_MODE_HMAC,
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.alg = {
+			.cra_name = "authenc(hmac(sha256),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = SHA256_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_MD5 | SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(md5),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-md5-cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = MD5_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA | SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-sha1-cbc-3des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = SHA1_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA256 |
+				SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-sha256-cbc-3des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = SHA256_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_MD5 | SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-md5-cbc-3des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = MD5_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+};
+
+static struct spacc_alg l2_engine_algs[] = {
+	{
+		.key_offs = 0,
+		.iv_offs = SPACC_CRYPTO_KASUMI_F8_KEY_LEN,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_KASUMI |
+				SPA_CTRL_CIPH_MODE_F8,
+		.alg = {
+			.cra_name = "f8(kasumi)",
+			.cra_driver_name = "f8-kasumi-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = 8,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_kasumi_f8_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = 16,
+				.max_keysize = 16,
+				.ivsize = 8,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+};
+
+static int __devinit spacc_probe(struct platform_device *pdev,
+				 unsigned max_ctxs, size_t cipher_pg_sz,
+				 size_t hash_pg_sz, size_t fifo_sz,
+				 struct spacc_alg *algs, size_t num_algs)
+{
+	int i, err, ret = -EINVAL;
+	struct resource *mem, *irq;
+	struct spacc_engine *engine = devm_kzalloc(&pdev->dev, sizeof(*engine),
+						   GFP_KERNEL);
+	if (!engine)
+		return -ENOMEM;
+
+	engine->max_ctxs	= max_ctxs;
+	engine->cipher_pg_sz	= cipher_pg_sz;
+	engine->hash_pg_sz	= hash_pg_sz;
+	engine->fifo_sz		= fifo_sz;
+	engine->algs		= algs;
+	engine->num_algs	= num_algs;
+	engine->name		= dev_name(&pdev->dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mem || !irq) {
+		dev_err(&pdev->dev, "no memory/irq resource for engine\n");
+		return -ENXIO;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+				     engine->name))
+		return -ENOMEM;
+
+	engine->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!engine->regs) {
+		dev_err(&pdev->dev, "memory map failed\n");
+		return -ENOMEM;
+	}
+
+	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
+			     engine->name, engine)) {
+		dev_err(engine->dev, "failed to request IRQ\n");
+		return -EBUSY;
+	}
+
+	engine->dev		= &pdev->dev;
+	engine->cipher_ctx_base = engine->regs + SPA_CIPH_KEY_BASE_REG_OFFSET;
+	engine->hash_key_base	= engine->regs + SPA_HASH_KEY_BASE_REG_OFFSET;
+
+	engine->req_pool = dmam_pool_create(engine->name, engine->dev,
+		MAX_DDT_LEN * sizeof(struct spacc_ddt), 8, SZ_64K);
+	if (!engine->req_pool)
+		return -ENOMEM;
+
+	spin_lock_init(&engine->hw_lock);
+
+	engine->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(engine->clk)) {
+		dev_info(&pdev->dev, "clk unavailable\n");
+		device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+		return PTR_ERR(engine->clk);
+	}
+
+	if (clk_enable(engine->clk)) {
+		dev_info(&pdev->dev, "unable to enable clk\n");
+		clk_put(engine->clk);
+		return -EIO;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+	if (err) {
+		clk_disable(engine->clk);
+		clk_put(engine->clk);
+		return err;
+	}
+
+
+	/*
+	 * Use an IRQ threshold of 50% as a default. This seems to be a
+	 * reasonable trade off of latency against throughput but can be
+	 * changed at runtime.
+	 */
+	engine->stat_irq_thresh = (engine->fifo_sz / 2);
+
+	/*
+	 * Configure the interrupts. We only use the STAT_CNT interrupt as we
+	 * only submit a new packet for processing when we complete another in
+	 * the queue. This minimizes time spent in the interrupt handler.
+	 */
+	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
+	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
+	writel(SPA_IRQ_EN_STAT_EN | SPA_IRQ_EN_GLBL_EN,
+	       engine->regs + SPA_IRQ_EN_REG_OFFSET);
+
+	setup_timer(&engine->packet_timeout, spacc_packet_timeout,
+		    (unsigned long)engine);
+
+	INIT_LIST_HEAD(&engine->pending);
+	INIT_LIST_HEAD(&engine->completed);
+	INIT_LIST_HEAD(&engine->in_progress);
+	engine->in_flight = 0;
+	tasklet_init(&engine->complete, spacc_spacc_complete,
+		     (unsigned long)engine);
+
+	platform_set_drvdata(pdev, engine);
+
+	INIT_LIST_HEAD(&engine->registered_algs);
+	for (i = 0; i < engine->num_algs; ++i) {
+		engine->algs[i].engine = engine;
+		err = crypto_register_alg(&engine->algs[i].alg);
+		if (!err) {
+			list_add_tail(&engine->algs[i].entry,
+				      &engine->registered_algs);
+			ret = 0;
+		}
+		if (err)
+			dev_err(engine->dev, "failed to register alg \"%s\"\n",
+				engine->algs[i].alg.cra_name);
+		else
+			dev_dbg(engine->dev, "registered alg \"%s\"\n",
+				engine->algs[i].alg.cra_name);
+	}
+
+	return ret;
+}
+
+static int __devexit spacc_remove(struct platform_device *pdev)
+{
+	struct spacc_alg *alg, *next;
+	struct spacc_engine *engine = platform_get_drvdata(pdev);
+
+	del_timer_sync(&engine->packet_timeout);
+	device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+
+	list_for_each_entry_safe(alg, next, &engine->registered_algs, entry) {
+		list_del(&alg->entry);
+		crypto_unregister_alg(&alg->alg);
+	}
+
+	clk_disable(engine->clk);
+	clk_put(engine->clk);
+
+	return 0;
+}
+
+static int __devinit ipsec_probe(struct platform_device *pdev)
+{
+	return spacc_probe(pdev, SPACC_CRYPTO_IPSEC_MAX_CTXS,
+			   SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ,
+			   SPACC_CRYPTO_IPSEC_HASH_PG_SZ,
+			   SPACC_CRYPTO_IPSEC_FIFO_SZ, ipsec_engine_algs,
+			   ARRAY_SIZE(ipsec_engine_algs));
+}
+
+static struct platform_driver ipsec_driver = {
+	.probe		= ipsec_probe,
+	.remove		= __devexit_p(spacc_remove),
+	.driver		= {
+		.name	= "picoxcell-ipsec",
+#ifdef CONFIG_PM
+		.pm	= &spacc_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __devinit l2_probe(struct platform_device *pdev)
+{
+	return spacc_probe(pdev, SPACC_CRYPTO_L2_MAX_CTXS,
+			   SPACC_CRYPTO_L2_CIPHER_PG_SZ,
+			   SPACC_CRYPTO_L2_HASH_PG_SZ, SPACC_CRYPTO_L2_FIFO_SZ,
+			   l2_engine_algs, ARRAY_SIZE(l2_engine_algs));
+}
+
+static struct platform_driver l2_driver = {
+	.probe		= l2_probe,
+	.remove		= __devexit_p(spacc_remove),
+	.driver		= {
+		.name	= "picoxcell-l2",
+#ifdef CONFIG_PM
+		.pm	= &spacc_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init spacc_init(void)
+{
+	int ret = platform_driver_register(&ipsec_driver);
+	if (ret) {
+		pr_err("failed to register ipsec spacc driver");
+		goto out;
+	}
+
+	ret = platform_driver_register(&l2_driver);
+	if (ret) {
+		pr_err("failed to register l2 spacc driver");
+		goto l2_failed;
+	}
+
+	return 0;
+
+l2_failed:
+	platform_driver_unregister(&ipsec_driver);
+out:
+	return ret;
+}
+module_init(spacc_init);
+
+static void __exit spacc_exit(void)
+{
+	platform_driver_unregister(&ipsec_driver);
+	platform_driver_unregister(&l2_driver);
+}
+module_exit(spacc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
diff --git a/drivers/crypto/picoxcell_crypto_regs.h b/drivers/crypto/picoxcell_crypto_regs.h
new file mode 100644
index 0000000..af93442
--- /dev/null
+++ b/drivers/crypto/picoxcell_crypto_regs.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 __PICOXCELL_CRYPTO_REGS_H__
+#define __PICOXCELL_CRYPTO_REGS_H__
+
+#define SPA_STATUS_OK			0
+#define SPA_STATUS_ICV_FAIL		1
+#define SPA_STATUS_MEMORY_ERROR		2
+#define SPA_STATUS_BLOCK_ERROR		3
+
+#define SPA_IRQ_CTRL_STAT_CNT_OFFSET	16
+#define SPA_IRQ_STAT_STAT_MASK		(1 << 4)
+#define SPA_FIFO_STAT_STAT_OFFSET	16
+#define SPA_FIFO_STAT_STAT_CNT_MASK	(0x3F << SPA_FIFO_STAT_STAT_OFFSET)
+#define SPA_STATUS_RES_CODE_OFFSET	24
+#define SPA_STATUS_RES_CODE_MASK	(0x3 << SPA_STATUS_RES_CODE_OFFSET)
+#define SPA_KEY_SZ_CTX_INDEX_OFFSET	8
+#define SPA_KEY_SZ_CIPHER_OFFSET	31
+
+#define SPA_IRQ_EN_REG_OFFSET		0x00000000
+#define SPA_IRQ_STAT_REG_OFFSET		0x00000004
+#define SPA_IRQ_CTRL_REG_OFFSET		0x00000008
+#define SPA_FIFO_STAT_REG_OFFSET	0x0000000C
+#define SPA_SDMA_BRST_SZ_REG_OFFSET	0x00000010
+#define SPA_SRC_PTR_REG_OFFSET		0x00000020
+#define SPA_DST_PTR_REG_OFFSET		0x00000024
+#define SPA_OFFSET_REG_OFFSET		0x00000028
+#define SPA_AAD_LEN_REG_OFFSET		0x0000002C
+#define SPA_PROC_LEN_REG_OFFSET		0x00000030
+#define SPA_ICV_LEN_REG_OFFSET		0x00000034
+#define SPA_ICV_OFFSET_REG_OFFSET	0x00000038
+#define SPA_SW_CTRL_REG_OFFSET		0x0000003C
+#define SPA_CTRL_REG_OFFSET		0x00000040
+#define SPA_AUX_INFO_REG_OFFSET		0x0000004C
+#define SPA_STAT_POP_REG_OFFSET		0x00000050
+#define SPA_STATUS_REG_OFFSET		0x00000054
+#define SPA_KEY_SZ_REG_OFFSET		0x00000100
+#define SPA_CIPH_KEY_BASE_REG_OFFSET	0x00004000
+#define SPA_HASH_KEY_BASE_REG_OFFSET	0x00008000
+#define SPA_RC4_CTX_BASE_REG_OFFSET	0x00020000
+
+#define SPA_IRQ_EN_REG_RESET		0x00000000
+#define SPA_IRQ_CTRL_REG_RESET		0x00000000
+#define SPA_FIFO_STAT_REG_RESET		0x00000000
+#define SPA_SDMA_BRST_SZ_REG_RESET	0x00000000
+#define SPA_SRC_PTR_REG_RESET		0x00000000
+#define SPA_DST_PTR_REG_RESET		0x00000000
+#define SPA_OFFSET_REG_RESET		0x00000000
+#define SPA_AAD_LEN_REG_RESET		0x00000000
+#define SPA_PROC_LEN_REG_RESET		0x00000000
+#define SPA_ICV_LEN_REG_RESET		0x00000000
+#define SPA_ICV_OFFSET_REG_RESET	0x00000000
+#define SPA_SW_CTRL_REG_RESET		0x00000000
+#define SPA_CTRL_REG_RESET		0x00000000
+#define SPA_AUX_INFO_REG_RESET		0x00000000
+#define SPA_STAT_POP_REG_RESET		0x00000000
+#define SPA_STATUS_REG_RESET		0x00000000
+#define SPA_KEY_SZ_REG_RESET		0x00000000
+
+#define SPA_CTRL_HASH_ALG_IDX		4
+#define SPA_CTRL_CIPH_MODE_IDX		8
+#define SPA_CTRL_HASH_MODE_IDX		12
+#define SPA_CTRL_CTX_IDX		16
+#define SPA_CTRL_ENCRYPT_IDX		24
+#define SPA_CTRL_AAD_COPY		25
+#define SPA_CTRL_ICV_PT			26
+#define SPA_CTRL_ICV_ENC		27
+#define SPA_CTRL_ICV_APPEND		28
+#define SPA_CTRL_KEY_EXP		29
+
+#define SPA_KEY_SZ_CXT_IDX		8
+#define SPA_KEY_SZ_CIPHER_IDX		31
+
+#define SPA_IRQ_EN_CMD0_EN		(1 << 0)
+#define SPA_IRQ_EN_STAT_EN		(1 << 4)
+#define SPA_IRQ_EN_GLBL_EN		(1 << 31)
+
+#define SPA_CTRL_CIPH_ALG_NULL		0x00
+#define SPA_CTRL_CIPH_ALG_DES		0x01
+#define SPA_CTRL_CIPH_ALG_AES		0x02
+#define SPA_CTRL_CIPH_ALG_RC4		0x03
+#define SPA_CTRL_CIPH_ALG_MULTI2	0x04
+#define SPA_CTRL_CIPH_ALG_KASUMI	0x05
+
+#define SPA_CTRL_HASH_ALG_NULL		(0x00 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_MD5		(0x01 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA		(0x02 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA224	(0x03 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA256	(0x04 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA384	(0x05 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA512	(0x06 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_AESMAC	(0x07 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_AESCMAC	(0x08 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_KASF9		(0x09 << SPA_CTRL_HASH_ALG_IDX)
+
+#define SPA_CTRL_CIPH_MODE_NULL		(0x00 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_ECB		(0x00 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CBC		(0x01 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CTR		(0x02 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CCM		(0x03 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_GCM		(0x05 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_OFB		(0x07 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CFB		(0x08 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_F8		(0x09 << SPA_CTRL_CIPH_MODE_IDX)
+
+#define SPA_CTRL_HASH_MODE_RAW		(0x00 << SPA_CTRL_HASH_MODE_IDX)
+#define SPA_CTRL_HASH_MODE_SSLMAC	(0x01 << SPA_CTRL_HASH_MODE_IDX)
+#define SPA_CTRL_HASH_MODE_HMAC		(0x02 << SPA_CTRL_HASH_MODE_IDX)
+
+#define SPA_FIFO_STAT_EMPTY		(1 << 31)
+#define SPA_FIFO_CMD_FULL		(1 << 7)
+
+#endif /* __PICOXCELL_CRYPTO_REGS_H__ */
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index b879c3f..854e263 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -2402,8 +2402,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
 	return t_alg;
 }
 
-static int talitos_probe(struct platform_device *ofdev,
-			 const struct of_device_id *match)
+static int talitos_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -2580,7 +2579,7 @@ static const struct of_device_id talitos_match[] = {
 };
 MODULE_DEVICE_TABLE(of, talitos_match);
 
-static struct of_platform_driver talitos_driver = {
+static struct platform_driver talitos_driver = {
 	.driver = {
 		.name = "talitos",
 		.owner = THIS_MODULE,
@@ -2592,13 +2591,13 @@ static struct of_platform_driver talitos_driver = {
 
 static int __init talitos_init(void)
 {
-	return of_register_platform_driver(&talitos_driver);
+	return platform_driver_register(&talitos_driver);
 }
 module_init(talitos_init);
 
 static void __exit talitos_exit(void)
 {
-	of_unregister_platform_driver(&talitos_driver);
+	platform_driver_unregister(&talitos_driver);
 }
 module_exit(talitos_exit);
 
diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c
index c461eda..4abd089 100644
--- a/drivers/dca/dca-core.c
+++ b/drivers/dca/dca-core.c
@@ -111,10 +111,8 @@ static void unregister_dca_providers(void)
 	/* at this point only one domain in the list is expected */
 	domain = list_first_entry(&dca_domains, struct dca_domain, node);
 
-	list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) {
-		list_del(&dca->node);
-		list_add(&dca->node, &unregistered_providers);
-	}
+	list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node)
+		list_move(&dca->node, &unregistered_providers);
 
 	dca_free_domain(domain);
 
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 1c28816..a572600 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -82,7 +82,7 @@ config INTEL_IOP_ADMA
 
 config DW_DMAC
 	tristate "Synopsys DesignWare AHB DMA support"
-	depends on AVR32
+	depends on HAVE_CLK
 	select DMA_ENGINE
 	default y if CPU_AT32AP7000
 	help
@@ -221,12 +221,20 @@ config IMX_SDMA
 
 config IMX_DMA
 	tristate "i.MX DMA support"
-	depends on ARCH_MX1 || ARCH_MX21 || MACH_MX27
+	depends on IMX_HAVE_DMA_V1
 	select DMA_ENGINE
 	help
 	  Support the i.MX DMA engine. This engine is integrated into
 	  Freescale i.MX1/21/27 chips.
 
+config MXS_DMA
+	bool "MXS DMA support"
+	depends on SOC_IMX23 || SOC_IMX28
+	select DMA_ENGINE
+	help
+	  Support the MXS DMA engine. This engine including APBH-DMA
+	  and APBX-DMA is integrated into Freescale i.MX23/28 chips.
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 64b21f5..836095a 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -1,9 +1,5 @@
-ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-	ccflags-y	+= -DDEBUG
-endif
-ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-	ccflags-y	+= -DVERBOSE_DEBUG
-endif
+ccflags-$(CONFIG_DMADEVICES_DEBUG)  := -DDEBUG
+ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
@@ -23,6 +19,7 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o
 obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
 obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
 obj-$(CONFIG_IMX_DMA) += imx-dma.o
+obj-$(CONFIG_MXS_DMA) += mxs-dma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 07bca49..e6d7228 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1845,7 +1845,7 @@ static inline void init_pl08x_debugfs(struct pl08x_driver_data *pl08x)
 }
 #endif
 
-static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
+static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct pl08x_driver_data *pl08x;
 	const struct vendor_data *vd = id->data;
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index a665683..00deabd 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -849,7 +849,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 
 				/* Must clear TC interrupt before calling
 				 * dma_tc_handle
-				 * in case tc_handle initate a new dma job
+				 * in case tc_handle initiate a new dma job
 				 */
 				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
 
@@ -894,7 +894,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id)
 				}
 				/* Must clear TC interrupt before calling
 				 * dma_tc_handle
-				 * in case tc_handle initate a new dma job
+				 * in case tc_handle initiate a new dma job
 				 */
 				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
 
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 5589358..e0888cb 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -54,6 +54,11 @@ module_param(pq_sources, uint, S_IRUGO);
 MODULE_PARM_DESC(pq_sources,
 		"Number of p+q source buffers (default: 3)");
 
+static int timeout = 3000;
+module_param(timeout, uint, S_IRUGO);
+MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), \
+		Pass -1 for infinite timeout");
+
 /*
  * Initialization patterns. All bytes in the source buffer has bit 7
  * set, all bytes in the destination buffer has bit 7 cleared.
@@ -285,7 +290,12 @@ static int dmatest_func(void *data)
 
 	set_user_nice(current, 10);
 
-	flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT;
+	/*
+	 * src buffers are freed by the DMAEngine code with dma_unmap_single()
+	 * dst buffers are freed by ourselves below
+	 */
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT
+	      | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
 
 	while (!kthread_should_stop()
 	       && !(iterations && total_tests >= iterations)) {
@@ -294,7 +304,7 @@ static int dmatest_func(void *data)
 		dma_addr_t dma_srcs[src_cnt];
 		dma_addr_t dma_dsts[dst_cnt];
 		struct completion cmp;
-		unsigned long tmo = msecs_to_jiffies(3000);
+		unsigned long tmo = msecs_to_jiffies(timeout);
 		u8 align = 0;
 
 		total_tests++;
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index a3991ab..9c25c7d 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -32,26 +32,30 @@
  * which does not support descriptor writeback.
  */
 
-/* NOTE:  DMS+SMS is system-specific. We should get this information
- * from the platform code somehow.
- */
-#define DWC_DEFAULT_CTLLO	(DWC_CTLL_DST_MSIZE(0)		\
-				| DWC_CTLL_SRC_MSIZE(0)		\
-				| DWC_CTLL_DMS(0)		\
-				| DWC_CTLL_SMS(1)		\
-				| DWC_CTLL_LLP_D_EN		\
-				| DWC_CTLL_LLP_S_EN)
+#define DWC_DEFAULT_CTLLO(private) ({				\
+		struct dw_dma_slave *__slave = (private);	\
+		int dms = __slave ? __slave->dst_master : 0;	\
+		int sms = __slave ? __slave->src_master : 1;	\
+		u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \
+		u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \
+								\
+		(DWC_CTLL_DST_MSIZE(dmsize)			\
+		 | DWC_CTLL_SRC_MSIZE(smsize)			\
+		 | DWC_CTLL_LLP_D_EN				\
+		 | DWC_CTLL_LLP_S_EN				\
+		 | DWC_CTLL_DMS(dms)				\
+		 | DWC_CTLL_SMS(sms));				\
+	})
 
 /*
  * This is configuration-dependent and usually a funny size like 4095.
- * Let's round it down to the nearest power of two.
  *
  * Note that this is a transfer count, i.e. if we transfer 32-bit
- * words, we can do 8192 bytes per descriptor.
+ * words, we can do 16380 bytes per descriptor.
  *
  * This parameter is also system-specific.
  */
-#define DWC_MAX_COUNT	2048U
+#define DWC_MAX_COUNT	4095U
 
 /*
  * Number of descriptors to allocate for each channel. This should be
@@ -84,11 +88,6 @@ static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc)
 	return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
 }
 
-static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
-{
-	return list_entry(dwc->queue.next, struct dw_desc, desc_node);
-}
-
 static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
 {
 	struct dw_desc *desc, *_desc;
@@ -201,6 +200,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
 	dma_async_tx_callback		callback;
 	void				*param;
 	struct dma_async_tx_descriptor	*txd = &desc->txd;
+	struct dw_desc			*child;
 
 	dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
 
@@ -209,6 +209,12 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc)
 	param = txd->callback_param;
 
 	dwc_sync_desc_for_cpu(dwc, desc);
+
+	/* async_tx_ack */
+	list_for_each_entry(child, &desc->tx_list, desc_node)
+		async_tx_ack(&child->txd);
+	async_tx_ack(&desc->txd);
+
 	list_splice_init(&desc->tx_list, &dwc->free_list);
 	list_move(&desc->desc_node, &dwc->free_list);
 
@@ -259,10 +265,11 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc)
 	 * Submit queued descriptors ASAP, i.e. before we go through
 	 * the completed ones.
 	 */
-	if (!list_empty(&dwc->queue))
-		dwc_dostart(dwc, dwc_first_queued(dwc));
 	list_splice_init(&dwc->active_list, &list);
-	list_splice_init(&dwc->queue, &dwc->active_list);
+	if (!list_empty(&dwc->queue)) {
+		list_move(dwc->queue.next, &dwc->active_list);
+		dwc_dostart(dwc, dwc_first_active(dwc));
+	}
 
 	list_for_each_entry_safe(desc, _desc, &list, desc_node)
 		dwc_descriptor_complete(dwc, desc);
@@ -291,6 +298,9 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 		return;
 	}
 
+	if (list_empty(&dwc->active_list))
+		return;
+
 	dev_vdbg(chan2dev(&dwc->chan), "scan_descriptors: llp=0x%x\n", llp);
 
 	list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
@@ -319,8 +329,8 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
 		cpu_relax();
 
 	if (!list_empty(&dwc->queue)) {
-		dwc_dostart(dwc, dwc_first_queued(dwc));
-		list_splice_init(&dwc->queue, &dwc->active_list);
+		list_move(dwc->queue.next, &dwc->active_list);
+		dwc_dostart(dwc, dwc_first_active(dwc));
 	}
 }
 
@@ -346,7 +356,7 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc)
 	 */
 	bad_desc = dwc_first_active(dwc);
 	list_del_init(&bad_desc->desc_node);
-	list_splice_init(&dwc->queue, dwc->active_list.prev);
+	list_move(dwc->queue.next, dwc->active_list.prev);
 
 	/* Clear the error flag and try to restart the controller */
 	dma_writel(dw, CLEAR.ERROR, dwc->mask);
@@ -541,8 +551,8 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx)
 	if (list_empty(&dwc->active_list)) {
 		dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
 				desc->txd.cookie);
-		dwc_dostart(dwc, desc);
 		list_add_tail(&desc->desc_node, &dwc->active_list);
+		dwc_dostart(dwc, dwc_first_active(dwc));
 	} else {
 		dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
 				desc->txd.cookie);
@@ -581,14 +591,16 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
 	 * We can be a lot more clever here, but this should take care
 	 * of the most common optimization.
 	 */
-	if (!((src | dest  | len) & 3))
+	if (!((src | dest  | len) & 7))
+		src_width = dst_width = 3;
+	else if (!((src | dest  | len) & 3))
 		src_width = dst_width = 2;
 	else if (!((src | dest | len) & 1))
 		src_width = dst_width = 1;
 	else
 		src_width = dst_width = 0;
 
-	ctllo = DWC_DEFAULT_CTLLO
+	ctllo = DWC_DEFAULT_CTLLO(chan->private)
 			| DWC_CTLL_DST_WIDTH(dst_width)
 			| DWC_CTLL_SRC_WIDTH(src_width)
 			| DWC_CTLL_DST_INC
@@ -669,11 +681,11 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
 	switch (direction) {
 	case DMA_TO_DEVICE:
-		ctllo = (DWC_DEFAULT_CTLLO
+		ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 				| DWC_CTLL_DST_WIDTH(reg_width)
 				| DWC_CTLL_DST_FIX
 				| DWC_CTLL_SRC_INC
-				| DWC_CTLL_FC_M2P);
+				| DWC_CTLL_FC(dws->fc));
 		reg = dws->tx_reg;
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -714,11 +726,11 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 		}
 		break;
 	case DMA_FROM_DEVICE:
-		ctllo = (DWC_DEFAULT_CTLLO
+		ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 				| DWC_CTLL_SRC_WIDTH(reg_width)
 				| DWC_CTLL_DST_INC
 				| DWC_CTLL_SRC_FIX
-				| DWC_CTLL_FC_P2M);
+				| DWC_CTLL_FC(dws->fc));
 
 		reg = dws->rx_reg;
 		for_each_sg(sgl, sg, sg_len, i) {
@@ -834,7 +846,9 @@ dwc_tx_status(struct dma_chan *chan,
 
 	ret = dma_async_is_complete(cookie, last_complete, last_used);
 	if (ret != DMA_SUCCESS) {
+		spin_lock_bh(&dwc->lock);
 		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+		spin_unlock_bh(&dwc->lock);
 
 		last_complete = dwc->completed;
 		last_used = chan->cookie;
@@ -889,8 +903,11 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
 		BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
 
 		cfghi = dws->cfg_hi;
-		cfglo = dws->cfg_lo;
+		cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
 	}
+
+	cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority);
+
 	channel_writel(dwc, CFG_LO, cfglo);
 	channel_writel(dwc, CFG_HI, cfghi);
 
@@ -1126,23 +1143,23 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
 		case DMA_TO_DEVICE:
 			desc->lli.dar = dws->tx_reg;
 			desc->lli.sar = buf_addr + (period_len * i);
-			desc->lli.ctllo = (DWC_DEFAULT_CTLLO
+			desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 					| DWC_CTLL_DST_WIDTH(reg_width)
 					| DWC_CTLL_SRC_WIDTH(reg_width)
 					| DWC_CTLL_DST_FIX
 					| DWC_CTLL_SRC_INC
-					| DWC_CTLL_FC_M2P
+					| DWC_CTLL_FC(dws->fc)
 					| DWC_CTLL_INT_EN);
 			break;
 		case DMA_FROM_DEVICE:
 			desc->lli.dar = buf_addr + (period_len * i);
 			desc->lli.sar = dws->rx_reg;
-			desc->lli.ctllo = (DWC_DEFAULT_CTLLO
+			desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 					| DWC_CTLL_SRC_WIDTH(reg_width)
 					| DWC_CTLL_DST_WIDTH(reg_width)
 					| DWC_CTLL_DST_INC
 					| DWC_CTLL_SRC_FIX
-					| DWC_CTLL_FC_P2M
+					| DWC_CTLL_FC(dws->fc)
 					| DWC_CTLL_INT_EN);
 			break;
 		default:
@@ -1307,7 +1324,17 @@ static int __init dw_probe(struct platform_device *pdev)
 		dwc->chan.device = &dw->dma;
 		dwc->chan.cookie = dwc->completed = 1;
 		dwc->chan.chan_id = i;
-		list_add_tail(&dwc->chan.device_node, &dw->dma.channels);
+		if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
+			list_add_tail(&dwc->chan.device_node,
+					&dw->dma.channels);
+		else
+			list_add(&dwc->chan.device_node, &dw->dma.channels);
+
+		/* 7 is highest priority & 0 is lowest. */
+		if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
+			dwc->priority = 7 - i;
+		else
+			dwc->priority = i;
 
 		dwc->ch_regs = &__dw_regs(dw)->CHAN[i];
 		spin_lock_init(&dwc->lock);
@@ -1335,6 +1362,8 @@ static int __init dw_probe(struct platform_device *pdev)
 
 	dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
 	dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
+	if (pdata->is_private)
+		dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask);
 	dw->dma.dev = &pdev->dev;
 	dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
 	dw->dma.device_free_chan_resources = dwc_free_chan_resources;
@@ -1447,7 +1476,7 @@ static int __init dw_init(void)
 {
 	return platform_driver_probe(&dw_driver, dw_probe);
 }
-module_init(dw_init);
+subsys_initcall(dw_init);
 
 static void __exit dw_exit(void)
 {
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index d9a939f..720f821 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -86,6 +86,7 @@ struct dw_dma_regs {
 #define DWC_CTLL_SRC_MSIZE(n)	((n)<<14)
 #define DWC_CTLL_S_GATH_EN	(1 << 17)	/* src gather, !FIX */
 #define DWC_CTLL_D_SCAT_EN	(1 << 18)	/* dst scatter, !FIX */
+#define DWC_CTLL_FC(n)		((n) << 20)
 #define DWC_CTLL_FC_M2M		(0 << 20)	/* mem-to-mem */
 #define DWC_CTLL_FC_M2P		(1 << 20)	/* mem-to-periph */
 #define DWC_CTLL_FC_P2M		(2 << 20)	/* periph-to-mem */
@@ -101,6 +102,8 @@ struct dw_dma_regs {
 #define DWC_CTLH_BLOCK_TS_MASK	0x00000fff
 
 /* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGL_CH_PRIOR_MASK	(0x7 << 5)	/* priority mask */
+#define DWC_CFGL_CH_PRIOR(x)	((x) << 5)	/* priority */
 #define DWC_CFGL_CH_SUSP	(1 << 8)	/* pause xfer */
 #define DWC_CFGL_FIFO_EMPTY	(1 << 9)	/* pause xfer */
 #define DWC_CFGL_HS_DST		(1 << 10)	/* handshake w/dst */
@@ -134,6 +137,7 @@ struct dw_dma_chan {
 	struct dma_chan		chan;
 	void __iomem		*ch_regs;
 	u8			mask;
+	u8			priority;
 
 	spinlock_t		lock;
 
@@ -155,9 +159,9 @@ __dwc_regs(struct dw_dma_chan *dwc)
 }
 
 #define channel_readl(dwc, name) \
-	__raw_readl(&(__dwc_regs(dwc)->name))
+	readl(&(__dwc_regs(dwc)->name))
 #define channel_writel(dwc, name, val) \
-	__raw_writel((val), &(__dwc_regs(dwc)->name))
+	writel((val), &(__dwc_regs(dwc)->name))
 
 static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
 {
@@ -181,9 +185,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
 }
 
 #define dma_readl(dw, name) \
-	__raw_readl(&(__dw_regs(dw)->name))
+	readl(&(__dw_regs(dw)->name))
 #define dma_writel(dw, name, val) \
-	__raw_writel((val), &(__dw_regs(dw)->name))
+	writel((val), &(__dw_regs(dw)->name))
 
 #define channel_set_bit(dw, reg, mask) \
 	dma_writel(dw, reg, ((mask) << 8) | (mask))
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index 4de947a..6b39675 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -37,35 +37,16 @@
 
 #include "fsldma.h"
 
-static const char msg_ld_oom[] = "No free memory for link descriptor\n";
+#define chan_dbg(chan, fmt, arg...)					\
+	dev_dbg(chan->dev, "%s: " fmt, chan->name, ##arg)
+#define chan_err(chan, fmt, arg...)					\
+	dev_err(chan->dev, "%s: " fmt, chan->name, ##arg)
 
-static void dma_init(struct fsldma_chan *chan)
-{
-	/* Reset the channel */
-	DMA_OUT(chan, &chan->regs->mr, 0, 32);
+static const char msg_ld_oom[] = "No free memory for link descriptor";
 
-	switch (chan->feature & FSL_DMA_IP_MASK) {
-	case FSL_DMA_IP_85XX:
-		/* Set the channel to below modes:
-		 * EIE - Error interrupt enable
-		 * EOSIE - End of segments interrupt enable (basic mode)
-		 * EOLNIE - End of links interrupt enable
-		 * BWC - Bandwidth sharing among channels
-		 */
-		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
-				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
-				| FSL_DMA_MR_EOSIE, 32);
-		break;
-	case FSL_DMA_IP_83XX:
-		/* Set the channel to below modes:
-		 * EOTIE - End-of-transfer interrupt enable
-		 * PRC_RM - PCI read multiple
-		 */
-		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
-				| FSL_DMA_MR_PRC_RM, 32);
-		break;
-	}
-}
+/*
+ * Register Helpers
+ */
 
 static void set_sr(struct fsldma_chan *chan, u32 val)
 {
@@ -77,14 +58,38 @@ static u32 get_sr(struct fsldma_chan *chan)
 	return DMA_IN(chan, &chan->regs->sr, 32);
 }
 
+static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
+{
+	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+}
+
+static dma_addr_t get_cdar(struct fsldma_chan *chan)
+{
+	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+}
+
+static u32 get_bcr(struct fsldma_chan *chan)
+{
+	return DMA_IN(chan, &chan->regs->bcr, 32);
+}
+
+/*
+ * Descriptor Helpers
+ */
+
 static void set_desc_cnt(struct fsldma_chan *chan,
 				struct fsl_dma_ld_hw *hw, u32 count)
 {
 	hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
+static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
+{
+	return DMA_TO_CPU(chan, desc->hw.count, 32);
+}
+
 static void set_desc_src(struct fsldma_chan *chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t src)
+			 struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
 	u64 snoop_bits;
 
@@ -93,8 +98,18 @@ static void set_desc_src(struct fsldma_chan *chan,
 	hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
+static dma_addr_t get_desc_src(struct fsldma_chan *chan,
+			       struct fsl_desc_sw *desc)
+{
+	u64 snoop_bits;
+
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+		? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
+	return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
+}
+
 static void set_desc_dst(struct fsldma_chan *chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
+			 struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
 	u64 snoop_bits;
 
@@ -103,8 +118,18 @@ static void set_desc_dst(struct fsldma_chan *chan,
 	hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
+static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
+			       struct fsl_desc_sw *desc)
+{
+	u64 snoop_bits;
+
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
+	return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
+}
+
 static void set_desc_next(struct fsldma_chan *chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t next)
+			  struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
 	u64 snoop_bits;
 
@@ -113,24 +138,46 @@ static void set_desc_next(struct fsldma_chan *chan,
 	hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64);
 }
 
-static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
+static void set_ld_eol(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
 {
-	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
-}
+	u64 snoop_bits;
 
-static dma_addr_t get_cdar(struct fsldma_chan *chan)
-{
-	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
-}
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+		? FSL_DMA_SNEN : 0;
 
-static dma_addr_t get_ndar(struct fsldma_chan *chan)
-{
-	return DMA_IN(chan, &chan->regs->ndar, 64);
+	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
+		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+			| snoop_bits, 64);
 }
 
-static u32 get_bcr(struct fsldma_chan *chan)
+/*
+ * DMA Engine Hardware Control Helpers
+ */
+
+static void dma_init(struct fsldma_chan *chan)
 {
-	return DMA_IN(chan, &chan->regs->bcr, 32);
+	/* Reset the channel */
+	DMA_OUT(chan, &chan->regs->mr, 0, 32);
+
+	switch (chan->feature & FSL_DMA_IP_MASK) {
+	case FSL_DMA_IP_85XX:
+		/* Set the channel to below modes:
+		 * EIE - Error interrupt enable
+		 * EOLNIE - End of links interrupt enable
+		 * BWC - Bandwidth sharing among channels
+		 */
+		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE, 32);
+		break;
+	case FSL_DMA_IP_83XX:
+		/* Set the channel to below modes:
+		 * EOTIE - End-of-transfer interrupt enable
+		 * PRC_RM - PCI read multiple
+		 */
+		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
+				| FSL_DMA_MR_PRC_RM, 32);
+		break;
+	}
 }
 
 static int dma_is_idle(struct fsldma_chan *chan)
@@ -139,25 +186,32 @@ static int dma_is_idle(struct fsldma_chan *chan)
 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
 }
 
+/*
+ * Start the DMA controller
+ *
+ * Preconditions:
+ * - the CDAR register must point to the start descriptor
+ * - the MRn[CS] bit must be cleared
+ */
 static void dma_start(struct fsldma_chan *chan)
 {
 	u32 mode;
 
 	mode = DMA_IN(chan, &chan->regs->mr, 32);
 
-	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
-		if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-			DMA_OUT(chan, &chan->regs->bcr, 0, 32);
-			mode |= FSL_DMA_MR_EMP_EN;
-		} else {
-			mode &= ~FSL_DMA_MR_EMP_EN;
-		}
+	if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+		DMA_OUT(chan, &chan->regs->bcr, 0, 32);
+		mode |= FSL_DMA_MR_EMP_EN;
+	} else {
+		mode &= ~FSL_DMA_MR_EMP_EN;
 	}
 
-	if (chan->feature & FSL_DMA_CHAN_START_EXT)
+	if (chan->feature & FSL_DMA_CHAN_START_EXT) {
 		mode |= FSL_DMA_MR_EMS_EN;
-	else
+	} else {
+		mode &= ~FSL_DMA_MR_EMS_EN;
 		mode |= FSL_DMA_MR_CS;
+	}
 
 	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 }
@@ -167,13 +221,26 @@ static void dma_halt(struct fsldma_chan *chan)
 	u32 mode;
 	int i;
 
+	/* read the mode register */
 	mode = DMA_IN(chan, &chan->regs->mr, 32);
-	mode |= FSL_DMA_MR_CA;
-	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 
-	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
+	/*
+	 * The 85xx controller supports channel abort, which will stop
+	 * the current transfer. On 83xx, this bit is the transfer error
+	 * mask bit, which should not be changed.
+	 */
+	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		mode |= FSL_DMA_MR_CA;
+		DMA_OUT(chan, &chan->regs->mr, mode, 32);
+
+		mode &= ~FSL_DMA_MR_CA;
+	}
+
+	/* stop the DMA controller */
+	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN);
 	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 
+	/* wait for the DMA controller to become idle */
 	for (i = 0; i < 100; i++) {
 		if (dma_is_idle(chan))
 			return;
@@ -182,20 +249,7 @@ static void dma_halt(struct fsldma_chan *chan)
 	}
 
 	if (!dma_is_idle(chan))
-		dev_err(chan->dev, "DMA halt timeout!\n");
-}
-
-static void set_ld_eol(struct fsldma_chan *chan,
-			struct fsl_desc_sw *desc)
-{
-	u64 snoop_bits;
-
-	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
-		? FSL_DMA_SNEN : 0;
-
-	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
-		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
-			| snoop_bits, 64);
+		chan_err(chan, "DMA halt timeout!\n");
 }
 
 /**
@@ -321,8 +375,7 @@ static void fsl_chan_toggle_ext_start(struct fsldma_chan *chan, int enable)
 		chan->feature &= ~FSL_DMA_CHAN_START_EXT;
 }
 
-static void append_ld_queue(struct fsldma_chan *chan,
-			    struct fsl_desc_sw *desc)
+static void append_ld_queue(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
 {
 	struct fsl_desc_sw *tail = to_fsl_desc(chan->ld_pending.prev);
 
@@ -363,8 +416,8 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
 	cookie = chan->common.cookie;
 	list_for_each_entry(child, &desc->tx_list, node) {
 		cookie++;
-		if (cookie < 0)
-			cookie = 1;
+		if (cookie < DMA_MIN_COOKIE)
+			cookie = DMA_MIN_COOKIE;
 
 		child->async_tx.cookie = cookie;
 	}
@@ -385,15 +438,14 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx)
  *
  * Return - The descriptor allocated. NULL for failed.
  */
-static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
-					struct fsldma_chan *chan)
+static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
 {
 	struct fsl_desc_sw *desc;
 	dma_addr_t pdesc;
 
 	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
 	if (!desc) {
-		dev_dbg(chan->dev, "out of memory for link desc\n");
+		chan_dbg(chan, "out of memory for link descriptor\n");
 		return NULL;
 	}
 
@@ -403,10 +455,13 @@ static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
 	desc->async_tx.tx_submit = fsl_dma_tx_submit;
 	desc->async_tx.phys = pdesc;
 
+#ifdef FSL_DMA_LD_DEBUG
+	chan_dbg(chan, "LD %p allocated\n", desc);
+#endif
+
 	return desc;
 }
 
-
 /**
  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
  * @chan : Freescale DMA channel
@@ -427,13 +482,11 @@ static int fsl_dma_alloc_chan_resources(struct dma_chan *dchan)
 	 * We need the descriptor to be aligned to 32bytes
 	 * for meeting FSL DMA specification requirement.
 	 */
-	chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
-					  chan->dev,
+	chan->desc_pool = dma_pool_create(chan->name, chan->dev,
 					  sizeof(struct fsl_desc_sw),
 					  __alignof__(struct fsl_desc_sw), 0);
 	if (!chan->desc_pool) {
-		dev_err(chan->dev, "unable to allocate channel %d "
-				   "descriptor pool\n", chan->id);
+		chan_err(chan, "unable to allocate descriptor pool\n");
 		return -ENOMEM;
 	}
 
@@ -455,6 +508,9 @@ static void fsldma_free_desc_list(struct fsldma_chan *chan,
 
 	list_for_each_entry_safe(desc, _desc, list, node) {
 		list_del(&desc->node);
+#ifdef FSL_DMA_LD_DEBUG
+		chan_dbg(chan, "LD %p free\n", desc);
+#endif
 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
 	}
 }
@@ -466,6 +522,9 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan,
 
 	list_for_each_entry_safe_reverse(desc, _desc, list, node) {
 		list_del(&desc->node);
+#ifdef FSL_DMA_LD_DEBUG
+		chan_dbg(chan, "LD %p free\n", desc);
+#endif
 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
 	}
 }
@@ -479,7 +538,7 @@ static void fsl_dma_free_chan_resources(struct dma_chan *dchan)
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
 	unsigned long flags;
 
-	dev_dbg(chan->dev, "Free all channel resources.\n");
+	chan_dbg(chan, "free all channel resources\n");
 	spin_lock_irqsave(&chan->desc_lock, flags);
 	fsldma_free_desc_list(chan, &chan->ld_pending);
 	fsldma_free_desc_list(chan, &chan->ld_running);
@@ -502,7 +561,7 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
 
 	new = fsl_dma_alloc_descriptor(chan);
 	if (!new) {
-		dev_err(chan->dev, msg_ld_oom);
+		chan_err(chan, "%s\n", msg_ld_oom);
 		return NULL;
 	}
 
@@ -512,14 +571,15 @@ fsl_dma_prep_interrupt(struct dma_chan *dchan, unsigned long flags)
 	/* Insert the link descriptor to the LD ring */
 	list_add_tail(&new->node, &new->tx_list);
 
-	/* Set End-of-link to the last link descriptor of new list*/
+	/* Set End-of-link to the last link descriptor of new list */
 	set_ld_eol(chan, new);
 
 	return &new->async_tx;
 }
 
-static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
-	struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src,
+static struct dma_async_tx_descriptor *
+fsl_dma_prep_memcpy(struct dma_chan *dchan,
+	dma_addr_t dma_dst, dma_addr_t dma_src,
 	size_t len, unsigned long flags)
 {
 	struct fsldma_chan *chan;
@@ -539,12 +599,9 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 		/* Allocate the link descriptor from DMA pool */
 		new = fsl_dma_alloc_descriptor(chan);
 		if (!new) {
-			dev_err(chan->dev, msg_ld_oom);
+			chan_err(chan, "%s\n", msg_ld_oom);
 			goto fail;
 		}
-#ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
-#endif
 
 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
 
@@ -572,7 +629,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
 	new->async_tx.flags = flags; /* client is in control of this ack */
 	new->async_tx.cookie = -EBUSY;
 
-	/* Set End-of-link to the last link descriptor of new list*/
+	/* Set End-of-link to the last link descriptor of new list */
 	set_ld_eol(chan, new);
 
 	return &first->async_tx;
@@ -627,12 +684,9 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_sg(struct dma_chan *dchan,
 		/* allocate and populate the descriptor */
 		new = fsl_dma_alloc_descriptor(chan);
 		if (!new) {
-			dev_err(chan->dev, msg_ld_oom);
+			chan_err(chan, "%s\n", msg_ld_oom);
 			goto fail;
 		}
-#ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
-#endif
 
 		set_desc_cnt(chan, &new->hw, len);
 		set_desc_src(chan, &new->hw, src);
@@ -744,14 +798,15 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
 
 	switch (cmd) {
 	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&chan->desc_lock, flags);
+
 		/* Halt the DMA engine */
 		dma_halt(chan);
 
-		spin_lock_irqsave(&chan->desc_lock, flags);
-
 		/* Remove and free all of the descriptors in the LD queue */
 		fsldma_free_desc_list(chan, &chan->ld_pending);
 		fsldma_free_desc_list(chan, &chan->ld_running);
+		chan->idle = true;
 
 		spin_unlock_irqrestore(&chan->desc_lock, flags);
 		return 0;
@@ -789,140 +844,87 @@ static int fsl_dma_device_control(struct dma_chan *dchan,
 }
 
 /**
- * fsl_dma_update_completed_cookie - Update the completed cookie.
- * @chan : Freescale DMA channel
- *
- * CONTEXT: hardirq
- */
-static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
-{
-	struct fsl_desc_sw *desc;
-	unsigned long flags;
-	dma_cookie_t cookie;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
-
-	if (list_empty(&chan->ld_running)) {
-		dev_dbg(chan->dev, "no running descriptors\n");
-		goto out_unlock;
-	}
-
-	/* Get the last descriptor, update the cookie to that */
-	desc = to_fsl_desc(chan->ld_running.prev);
-	if (dma_is_idle(chan))
-		cookie = desc->async_tx.cookie;
-	else {
-		cookie = desc->async_tx.cookie - 1;
-		if (unlikely(cookie < DMA_MIN_COOKIE))
-			cookie = DMA_MAX_COOKIE;
-	}
-
-	chan->completed_cookie = cookie;
-
-out_unlock:
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
-}
-
-/**
- * fsldma_desc_status - Check the status of a descriptor
+ * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
  * @chan: Freescale DMA channel
- * @desc: DMA SW descriptor
- *
- * This function will return the status of the given descriptor
- */
-static enum dma_status fsldma_desc_status(struct fsldma_chan *chan,
-					  struct fsl_desc_sw *desc)
-{
-	return dma_async_is_complete(desc->async_tx.cookie,
-				     chan->completed_cookie,
-				     chan->common.cookie);
-}
-
-/**
- * fsl_chan_ld_cleanup - Clean up link descriptors
- * @chan : Freescale DMA channel
+ * @desc: descriptor to cleanup and free
  *
- * This function clean up the ld_queue of DMA channel.
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, and then
+ * free the descriptor.
  */
-static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
+				      struct fsl_desc_sw *desc)
 {
-	struct fsl_desc_sw *desc, *_desc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
-
-	dev_dbg(chan->dev, "chan completed_cookie = %d\n", chan->completed_cookie);
-	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
-		dma_async_tx_callback callback;
-		void *callback_param;
-
-		if (fsldma_desc_status(chan, desc) == DMA_IN_PROGRESS)
-			break;
+	struct dma_async_tx_descriptor *txd = &desc->async_tx;
+	struct device *dev = chan->common.device->dev;
+	dma_addr_t src = get_desc_src(chan, desc);
+	dma_addr_t dst = get_desc_dst(chan, desc);
+	u32 len = get_desc_cnt(chan, desc);
+
+	/* Run the link descriptor callback function */
+	if (txd->callback) {
+#ifdef FSL_DMA_LD_DEBUG
+		chan_dbg(chan, "LD %p callback\n", desc);
+#endif
+		txd->callback(txd->callback_param);
+	}
 
-		/* Remove from the list of running transactions */
-		list_del(&desc->node);
+	/* Run any dependencies */
+	dma_run_dependencies(txd);
 
-		/* Run the link descriptor callback function */
-		callback = desc->async_tx.callback;
-		callback_param = desc->async_tx.callback_param;
-		if (callback) {
-			spin_unlock_irqrestore(&chan->desc_lock, flags);
-			dev_dbg(chan->dev, "LD %p callback\n", desc);
-			callback(callback_param);
-			spin_lock_irqsave(&chan->desc_lock, flags);
-		}
+	/* Unmap the dst buffer, if requested */
+	if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+			dma_unmap_single(dev, dst, len, DMA_FROM_DEVICE);
+		else
+			dma_unmap_page(dev, dst, len, DMA_FROM_DEVICE);
+	}
 
-		/* Run any dependencies, then free the descriptor */
-		dma_run_dependencies(&desc->async_tx);
-		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+	/* Unmap the src buffer, if requested */
+	if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+			dma_unmap_single(dev, src, len, DMA_TO_DEVICE);
+		else
+			dma_unmap_page(dev, src, len, DMA_TO_DEVICE);
 	}
 
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+#ifdef FSL_DMA_LD_DEBUG
+	chan_dbg(chan, "LD %p free\n", desc);
+#endif
+	dma_pool_free(chan->desc_pool, desc, txd->phys);
 }
 
 /**
  * fsl_chan_xfer_ld_queue - transfer any pending transactions
  * @chan : Freescale DMA channel
  *
- * This will make sure that any pending transactions will be run.
- * If the DMA controller is idle, it will be started. Otherwise,
- * the DMA controller's interrupt handler will start any pending
- * transactions when it becomes idle.
+ * HARDWARE STATE: idle
+ * LOCKING: must hold chan->desc_lock
  */
 static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
 {
 	struct fsl_desc_sw *desc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
 
 	/*
 	 * If the list of pending descriptors is empty, then we
 	 * don't need to do any work at all
 	 */
 	if (list_empty(&chan->ld_pending)) {
-		dev_dbg(chan->dev, "no pending LDs\n");
-		goto out_unlock;
+		chan_dbg(chan, "no pending LDs\n");
+		return;
 	}
 
 	/*
-	 * The DMA controller is not idle, which means the interrupt
-	 * handler will start any queued transactions when it runs
-	 * at the end of the current transaction
+	 * The DMA controller is not idle, which means that the interrupt
+	 * handler will start any queued transactions when it runs after
+	 * this transaction finishes
 	 */
-	if (!dma_is_idle(chan)) {
-		dev_dbg(chan->dev, "DMA controller still busy\n");
-		goto out_unlock;
+	if (!chan->idle) {
+		chan_dbg(chan, "DMA controller still busy\n");
+		return;
 	}
 
 	/*
-	 * TODO:
-	 * make sure the dma_halt() function really un-wedges the
-	 * controller as much as possible
-	 */
-	dma_halt(chan);
-
-	/*
 	 * If there are some link descriptors which have not been
 	 * transferred, we need to start the controller
 	 */
@@ -931,18 +933,32 @@ static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
 	 * Move all elements from the queue of pending transactions
 	 * onto the list of running transactions
 	 */
+	chan_dbg(chan, "idle, starting controller\n");
 	desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
 	list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
 
 	/*
+	 * The 85xx DMA controller doesn't clear the channel start bit
+	 * automatically at the end of a transfer. Therefore we must clear
+	 * it in software before starting the transfer.
+	 */
+	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		u32 mode;
+
+		mode = DMA_IN(chan, &chan->regs->mr, 32);
+		mode &= ~FSL_DMA_MR_CS;
+		DMA_OUT(chan, &chan->regs->mr, mode, 32);
+	}
+
+	/*
 	 * Program the descriptor's address into the DMA controller,
 	 * then start the DMA transaction
 	 */
 	set_cdar(chan, desc->async_tx.phys);
-	dma_start(chan);
+	get_cdar(chan);
 
-out_unlock:
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+	dma_start(chan);
+	chan->idle = false;
 }
 
 /**
@@ -952,7 +968,11 @@ out_unlock:
 static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
 {
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
 	fsl_chan_xfer_ld_queue(chan);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 }
 
 /**
@@ -964,16 +984,18 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
 					struct dma_tx_state *txstate)
 {
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
-	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
+	dma_cookie_t last_used;
+	unsigned long flags;
 
-	fsl_chan_ld_cleanup(chan);
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
-	last_used = dchan->cookie;
 	last_complete = chan->completed_cookie;
+	last_used = dchan->cookie;
 
-	dma_set_tx_state(txstate, last_complete, last_used, 0);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 
+	dma_set_tx_state(txstate, last_complete, last_used, 0);
 	return dma_async_is_complete(cookie, last_complete, last_used);
 }
 
@@ -984,21 +1006,20 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan,
 static irqreturn_t fsldma_chan_irq(int irq, void *data)
 {
 	struct fsldma_chan *chan = data;
-	int update_cookie = 0;
-	int xfer_ld_q = 0;
 	u32 stat;
 
 	/* save and clear the status register */
 	stat = get_sr(chan);
 	set_sr(chan, stat);
-	dev_dbg(chan->dev, "irq: channel %d, stat = 0x%x\n", chan->id, stat);
+	chan_dbg(chan, "irq: stat = 0x%x\n", stat);
 
+	/* check that this was really our device */
 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
 	if (!stat)
 		return IRQ_NONE;
 
 	if (stat & FSL_DMA_SR_TE)
-		dev_err(chan->dev, "Transfer Error!\n");
+		chan_err(chan, "Transfer Error!\n");
 
 	/*
 	 * Programming Error
@@ -1006,29 +1027,10 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	 * triger a PE interrupt.
 	 */
 	if (stat & FSL_DMA_SR_PE) {
-		dev_dbg(chan->dev, "irq: Programming Error INT\n");
-		if (get_bcr(chan) == 0) {
-			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
-			 * Now, update the completed cookie, and continue the
-			 * next uncompleted transfer.
-			 */
-			update_cookie = 1;
-			xfer_ld_q = 1;
-		}
+		chan_dbg(chan, "irq: Programming Error INT\n");
 		stat &= ~FSL_DMA_SR_PE;
-	}
-
-	/*
-	 * If the link descriptor segment transfer finishes,
-	 * we will recycle the used descriptor.
-	 */
-	if (stat & FSL_DMA_SR_EOSI) {
-		dev_dbg(chan->dev, "irq: End-of-segments INT\n");
-		dev_dbg(chan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n",
-			(unsigned long long)get_cdar(chan),
-			(unsigned long long)get_ndar(chan));
-		stat &= ~FSL_DMA_SR_EOSI;
-		update_cookie = 1;
+		if (get_bcr(chan) != 0)
+			chan_err(chan, "Programming Error!\n");
 	}
 
 	/*
@@ -1036,10 +1038,8 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	 * and start the next transfer if it exist.
 	 */
 	if (stat & FSL_DMA_SR_EOCDI) {
-		dev_dbg(chan->dev, "irq: End-of-Chain link INT\n");
+		chan_dbg(chan, "irq: End-of-Chain link INT\n");
 		stat &= ~FSL_DMA_SR_EOCDI;
-		update_cookie = 1;
-		xfer_ld_q = 1;
 	}
 
 	/*
@@ -1048,27 +1048,79 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data)
 	 * prepare next transfer.
 	 */
 	if (stat & FSL_DMA_SR_EOLNI) {
-		dev_dbg(chan->dev, "irq: End-of-link INT\n");
+		chan_dbg(chan, "irq: End-of-link INT\n");
 		stat &= ~FSL_DMA_SR_EOLNI;
-		xfer_ld_q = 1;
 	}
 
-	if (update_cookie)
-		fsl_dma_update_completed_cookie(chan);
-	if (xfer_ld_q)
-		fsl_chan_xfer_ld_queue(chan);
+	/* check that the DMA controller is really idle */
+	if (!dma_is_idle(chan))
+		chan_err(chan, "irq: controller not idle!\n");
+
+	/* check that we handled all of the bits */
 	if (stat)
-		dev_dbg(chan->dev, "irq: unhandled sr 0x%02x\n", stat);
+		chan_err(chan, "irq: unhandled sr 0x%08x\n", stat);
 
-	dev_dbg(chan->dev, "irq: Exit\n");
+	/*
+	 * Schedule the tasklet to handle all cleanup of the current
+	 * transaction. It will start a new transaction if there is
+	 * one pending.
+	 */
 	tasklet_schedule(&chan->tasklet);
+	chan_dbg(chan, "irq: Exit\n");
 	return IRQ_HANDLED;
 }
 
 static void dma_do_tasklet(unsigned long data)
 {
 	struct fsldma_chan *chan = (struct fsldma_chan *)data;
-	fsl_chan_ld_cleanup(chan);
+	struct fsl_desc_sw *desc, *_desc;
+	LIST_HEAD(ld_cleanup);
+	unsigned long flags;
+
+	chan_dbg(chan, "tasklet entry\n");
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+
+	/* update the cookie if we have some descriptors to cleanup */
+	if (!list_empty(&chan->ld_running)) {
+		dma_cookie_t cookie;
+
+		desc = to_fsl_desc(chan->ld_running.prev);
+		cookie = desc->async_tx.cookie;
+
+		chan->completed_cookie = cookie;
+		chan_dbg(chan, "completed_cookie=%d\n", cookie);
+	}
+
+	/*
+	 * move the descriptors to a temporary list so we can drop the lock
+	 * during the entire cleanup operation
+	 */
+	list_splice_tail_init(&chan->ld_running, &ld_cleanup);
+
+	/* the hardware is now idle and ready for more */
+	chan->idle = true;
+
+	/*
+	 * Start any pending transactions automatically
+	 *
+	 * In the ideal case, we keep the DMA controller busy while we go
+	 * ahead and free the descriptors below.
+	 */
+	fsl_chan_xfer_ld_queue(chan);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+	/* Run the callback for each descriptor, in order */
+	list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
+
+		/* Remove from the list of transactions */
+		list_del(&desc->node);
+
+		/* Run all cleanup for this descriptor */
+		fsldma_cleanup_descriptor(chan, desc);
+	}
+
+	chan_dbg(chan, "tasklet exit\n");
 }
 
 static irqreturn_t fsldma_ctrl_irq(int irq, void *data)
@@ -1116,7 +1168,7 @@ static void fsldma_free_irqs(struct fsldma_device *fdev)
 	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
 		chan = fdev->chan[i];
 		if (chan && chan->irq != NO_IRQ) {
-			dev_dbg(fdev->dev, "free channel %d IRQ\n", chan->id);
+			chan_dbg(chan, "free per-channel IRQ\n");
 			free_irq(chan->irq, chan);
 		}
 	}
@@ -1143,19 +1195,16 @@ static int fsldma_request_irqs(struct fsldma_device *fdev)
 			continue;
 
 		if (chan->irq == NO_IRQ) {
-			dev_err(fdev->dev, "no interrupts property defined for "
-					   "DMA channel %d. Please fix your "
-					   "device tree\n", chan->id);
+			chan_err(chan, "interrupts property missing in device tree\n");
 			ret = -ENODEV;
 			goto out_unwind;
 		}
 
-		dev_dbg(fdev->dev, "request channel %d IRQ\n", chan->id);
+		chan_dbg(chan, "request per-channel IRQ\n");
 		ret = request_irq(chan->irq, fsldma_chan_irq, IRQF_SHARED,
 				  "fsldma-chan", chan);
 		if (ret) {
-			dev_err(fdev->dev, "unable to request IRQ for DMA "
-					   "channel %d\n", chan->id);
+			chan_err(chan, "unable to request per-channel IRQ\n");
 			goto out_unwind;
 		}
 	}
@@ -1230,6 +1279,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 
 	fdev->chan[chan->id] = chan;
 	tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
+	snprintf(chan->name, sizeof(chan->name), "chan%d", chan->id);
 
 	/* Initialize the channel */
 	dma_init(chan);
@@ -1250,6 +1300,7 @@ static int __devinit fsl_dma_chan_probe(struct fsldma_device *fdev,
 	spin_lock_init(&chan->desc_lock);
 	INIT_LIST_HEAD(&chan->ld_pending);
 	INIT_LIST_HEAD(&chan->ld_running);
+	chan->idle = true;
 
 	chan->common.device = &fdev->common;
 
@@ -1281,8 +1332,7 @@ static void fsl_dma_chan_remove(struct fsldma_chan *chan)
 	kfree(chan);
 }
 
-static int __devinit fsldma_of_probe(struct platform_device *op,
-			const struct of_device_id *match)
+static int __devinit fsldma_of_probe(struct platform_device *op)
 {
 	struct fsldma_device *fdev;
 	struct device_node *child;
@@ -1414,20 +1464,13 @@ static struct of_platform_driver fsldma_of_driver = {
 
 static __init int fsldma_init(void)
 {
-	int ret;
-
 	pr_info("Freescale Elo / Elo Plus DMA driver\n");
-
-	ret = of_register_platform_driver(&fsldma_of_driver);
-	if (ret)
-		pr_err("fsldma: failed to register platform driver\n");
-
-	return ret;
+	return platform_driver_register(&fsldma_of_driver);
 }
 
 static void __exit fsldma_exit(void)
 {
-	of_unregister_platform_driver(&fsldma_of_driver);
+	platform_driver_unregister(&fsldma_of_driver);
 }
 
 subsys_initcall(fsldma_init);
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index ba9f403..9cb5aa5 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -102,8 +102,8 @@ struct fsl_desc_sw {
 } __attribute__((aligned(32)));
 
 struct fsldma_chan_regs {
-	u32 mr;	/* 0x00 - Mode Register */
-	u32 sr;	/* 0x04 - Status Register */
+	u32 mr;		/* 0x00 - Mode Register */
+	u32 sr;		/* 0x04 - Status Register */
 	u64 cdar;	/* 0x08 - Current descriptor address register */
 	u64 sar;	/* 0x10 - Source Address Register */
 	u64 dar;	/* 0x18 - Destination Address Register */
@@ -135,6 +135,7 @@ struct fsldma_device {
 #define FSL_DMA_CHAN_START_EXT	0x00002000
 
 struct fsldma_chan {
+	char name[8];			/* Channel name */
 	struct fsldma_chan_regs __iomem *regs;
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
@@ -147,6 +148,7 @@ struct fsldma_chan {
 	int id;				/* Raw id of this channel */
 	struct tasklet_struct tasklet;
 	u32 feature;
+	bool idle;			/* DMA controller is idle */
 
 	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
 	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c
index 59c2701..4f95d31 100644
--- a/drivers/dma/mpc512x_dma.c
+++ b/drivers/dma/mpc512x_dma.c
@@ -649,8 +649,7 @@ mpc_dma_prep_memcpy(struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
 	return &mdesc->desc;
 }
 
-static int __devinit mpc_dma_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc_dma_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -827,7 +826,7 @@ static struct of_device_id mpc_dma_match[] = {
 	{},
 };
 
-static struct of_platform_driver mpc_dma_driver = {
+static struct platform_driver mpc_dma_driver = {
 	.probe		= mpc_dma_probe,
 	.remove		= __devexit_p(mpc_dma_remove),
 	.driver = {
@@ -839,13 +838,13 @@ static struct of_platform_driver mpc_dma_driver = {
 
 static int __init mpc_dma_init(void)
 {
-	return of_register_platform_driver(&mpc_dma_driver);
+	return platform_driver_register(&mpc_dma_driver);
 }
 module_init(mpc_dma_init);
 
 static void __exit mpc_dma_exit(void)
 {
-	of_unregister_platform_driver(&mpc_dma_driver);
+	platform_driver_unregister(&mpc_dma_driver);
 }
 module_exit(mpc_dma_exit);
 
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
new file mode 100644
index 0000000..88aad4f
--- /dev/null
+++ b/drivers/dma/mxs-dma.c
@@ -0,0 +1,724 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Refer to drivers/dma/imx-sdma.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/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+
+#include <asm/irq.h>
+#include <mach/mxs.h>
+#include <mach/dma.h>
+#include <mach/common.h>
+
+/*
+ * NOTE: The term "PIO" throughout the mxs-dma implementation means
+ * PIO mode of mxs apbh-dma and apbx-dma.  With this working mode,
+ * dma can program the controller registers of peripheral devices.
+ */
+
+#define MXS_DMA_APBH		0
+#define MXS_DMA_APBX		1
+#define dma_is_apbh()		(mxs_dma->dev_id == MXS_DMA_APBH)
+
+#define APBH_VERSION_LATEST	3
+#define apbh_is_old()		(mxs_dma->version < APBH_VERSION_LATEST)
+
+#define HW_APBHX_CTRL0				0x000
+#define BM_APBH_CTRL0_APB_BURST8_EN		(1 << 29)
+#define BM_APBH_CTRL0_APB_BURST_EN		(1 << 28)
+#define BP_APBH_CTRL0_CLKGATE_CHANNEL		8
+#define BP_APBH_CTRL0_RESET_CHANNEL		16
+#define HW_APBHX_CTRL1				0x010
+#define HW_APBHX_CTRL2				0x020
+#define HW_APBHX_CHANNEL_CTRL			0x030
+#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL	16
+#define HW_APBH_VERSION				(cpu_is_mx23() ? 0x3f0 : 0x800)
+#define HW_APBX_VERSION				0x800
+#define BP_APBHX_VERSION_MAJOR			24
+#define HW_APBHX_CHn_NXTCMDAR(n) \
+	(((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70)
+#define HW_APBHX_CHn_SEMA(n) \
+	(((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70)
+
+/*
+ * ccw bits definitions
+ *
+ * COMMAND:		0..1	(2)
+ * CHAIN:		2	(1)
+ * IRQ:			3	(1)
+ * NAND_LOCK:		4	(1) - not implemented
+ * NAND_WAIT4READY:	5	(1) - not implemented
+ * DEC_SEM:		6	(1)
+ * WAIT4END:		7	(1)
+ * HALT_ON_TERMINATE:	8	(1)
+ * TERMINATE_FLUSH:	9	(1)
+ * RESERVED:		10..11	(2)
+ * PIO_NUM:		12..15	(4)
+ */
+#define BP_CCW_COMMAND		0
+#define BM_CCW_COMMAND		(3 << 0)
+#define CCW_CHAIN		(1 << 2)
+#define CCW_IRQ			(1 << 3)
+#define CCW_DEC_SEM		(1 << 6)
+#define CCW_WAIT4END		(1 << 7)
+#define CCW_HALT_ON_TERM	(1 << 8)
+#define CCW_TERM_FLUSH		(1 << 9)
+#define BP_CCW_PIO_NUM		12
+#define BM_CCW_PIO_NUM		(0xf << 12)
+
+#define BF_CCW(value, field)	(((value) << BP_CCW_##field) & BM_CCW_##field)
+
+#define MXS_DMA_CMD_NO_XFER	0
+#define MXS_DMA_CMD_WRITE	1
+#define MXS_DMA_CMD_READ	2
+#define MXS_DMA_CMD_DMA_SENSE	3	/* not implemented */
+
+struct mxs_dma_ccw {
+	u32		next;
+	u16		bits;
+	u16		xfer_bytes;
+#define MAX_XFER_BYTES	0xff00
+	u32		bufaddr;
+#define MXS_PIO_WORDS	16
+	u32		pio_words[MXS_PIO_WORDS];
+};
+
+#define NUM_CCW	(int)(PAGE_SIZE / sizeof(struct mxs_dma_ccw))
+
+struct mxs_dma_chan {
+	struct mxs_dma_engine		*mxs_dma;
+	struct dma_chan			chan;
+	struct dma_async_tx_descriptor	desc;
+	struct tasklet_struct		tasklet;
+	int				chan_irq;
+	struct mxs_dma_ccw		*ccw;
+	dma_addr_t			ccw_phys;
+	dma_cookie_t			last_completed;
+	enum dma_status			status;
+	unsigned int			flags;
+#define MXS_DMA_SG_LOOP			(1 << 0)
+};
+
+#define MXS_DMA_CHANNELS		16
+#define MXS_DMA_CHANNELS_MASK		0xffff
+
+struct mxs_dma_engine {
+	int				dev_id;
+	unsigned int			version;
+	void __iomem			*base;
+	struct clk			*clk;
+	struct dma_device		dma_device;
+	struct device_dma_parameters	dma_parms;
+	struct mxs_dma_chan		mxs_chans[MXS_DMA_CHANNELS];
+};
+
+static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL),
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	else
+		writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
+}
+
+static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* set cmd_addr up */
+	writel(mxs_chan->ccw_phys,
+		mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
+
+	/* enable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+	}
+
+	/* write 1 to SEMA to kick off the channel */
+	writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
+}
+
+static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* disable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	}
+
+	mxs_chan->status = DMA_SUCCESS;
+}
+
+static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* freeze the channel */
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	else
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
+
+	mxs_chan->status = DMA_PAUSED;
+}
+
+static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* unfreeze the channel */
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+	else
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR);
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+}
+
+static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
+{
+	dma_cookie_t cookie = mxs_chan->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	mxs_chan->chan.cookie = cookie;
+	mxs_chan->desc.cookie = cookie;
+
+	return cookie;
+}
+
+static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct mxs_dma_chan, chan);
+}
+
+static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
+
+	mxs_dma_enable_chan(mxs_chan);
+
+	return mxs_dma_assign_cookie(mxs_chan);
+}
+
+static void mxs_dma_tasklet(unsigned long data)
+{
+	struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data;
+
+	if (mxs_chan->desc.callback)
+		mxs_chan->desc.callback(mxs_chan->desc.callback_param);
+}
+
+static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
+{
+	struct mxs_dma_engine *mxs_dma = dev_id;
+	u32 stat1, stat2;
+
+	/* completion status */
+	stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1);
+	stat1 &= MXS_DMA_CHANNELS_MASK;
+	writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR);
+
+	/* error status */
+	stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2);
+	writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR);
+
+	/*
+	 * When both completion and error of termination bits set at the
+	 * same time, we do not take it as an error.  IOW, it only becomes
+	 * an error we need to handler here in case of ether it's (1) an bus
+	 * error or (2) a termination error with no completion.
+	 */
+	stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */
+		(~(stat2 >> MXS_DMA_CHANNELS) & stat2 & ~stat1); /* (2) */
+
+	/* combine error and completion status for checking */
+	stat1 = (stat2 << MXS_DMA_CHANNELS) | stat1;
+	while (stat1) {
+		int channel = fls(stat1) - 1;
+		struct mxs_dma_chan *mxs_chan =
+			&mxs_dma->mxs_chans[channel % MXS_DMA_CHANNELS];
+
+		if (channel >= MXS_DMA_CHANNELS) {
+			dev_dbg(mxs_dma->dma_device.dev,
+				"%s: error in channel %d\n", __func__,
+				channel - MXS_DMA_CHANNELS);
+			mxs_chan->status = DMA_ERROR;
+			mxs_dma_reset_chan(mxs_chan);
+		} else {
+			if (mxs_chan->flags & MXS_DMA_SG_LOOP)
+				mxs_chan->status = DMA_IN_PROGRESS;
+			else
+				mxs_chan->status = DMA_SUCCESS;
+		}
+
+		stat1 &= ~(1 << channel);
+
+		if (mxs_chan->status == DMA_SUCCESS)
+			mxs_chan->last_completed = mxs_chan->desc.cookie;
+
+		/* schedule tasklet on this channel */
+		tasklet_schedule(&mxs_chan->tasklet);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_data *data = chan->private;
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int ret;
+
+	if (!data)
+		return -EINVAL;
+
+	mxs_chan->chan_irq = data->chan_irq;
+
+	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+				&mxs_chan->ccw_phys, GFP_KERNEL);
+	if (!mxs_chan->ccw) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	memset(mxs_chan->ccw, 0, PAGE_SIZE);
+
+	ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
+				0, "mxs-dma", mxs_dma);
+	if (ret)
+		goto err_irq;
+
+	ret = clk_enable(mxs_dma->clk);
+	if (ret)
+		goto err_clk;
+
+	mxs_dma_reset_chan(mxs_chan);
+
+	dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
+	mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
+
+	/* the descriptor is ready */
+	async_tx_ack(&mxs_chan->desc);
+
+	return 0;
+
+err_clk:
+	free_irq(mxs_chan->chan_irq, mxs_dma);
+err_irq:
+	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+			mxs_chan->ccw, mxs_chan->ccw_phys);
+err_alloc:
+	return ret;
+}
+
+static void mxs_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+
+	mxs_dma_disable_chan(mxs_chan);
+
+	free_irq(mxs_chan->chan_irq, mxs_dma);
+
+	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+			mxs_chan->ccw, mxs_chan->ccw_phys);
+
+	clk_disable(mxs_dma->clk);
+}
+
+static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long append)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	struct mxs_dma_ccw *ccw;
+	struct scatterlist *sg;
+	int i, j;
+	u32 *pio;
+	static int idx;
+
+	if (mxs_chan->status == DMA_IN_PROGRESS && !append)
+		return NULL;
+
+	if (sg_len + (append ? idx : 0) > NUM_CCW) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum number of sg exceeded: %d > %d\n",
+				sg_len, NUM_CCW);
+		goto err_out;
+	}
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+	mxs_chan->flags = 0;
+
+	/*
+	 * If the sg is prepared with append flag set, the sg
+	 * will be appended to the last prepared sg.
+	 */
+	if (append) {
+		BUG_ON(idx < 1);
+		ccw = &mxs_chan->ccw[idx - 1];
+		ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
+		ccw->bits |= CCW_CHAIN;
+		ccw->bits &= ~CCW_IRQ;
+		ccw->bits &= ~CCW_DEC_SEM;
+		ccw->bits &= ~CCW_WAIT4END;
+	} else {
+		idx = 0;
+	}
+
+	if (direction == DMA_NONE) {
+		ccw = &mxs_chan->ccw[idx++];
+		pio = (u32 *) sgl;
+
+		for (j = 0; j < sg_len;)
+			ccw->pio_words[j++] = *pio++;
+
+		ccw->bits = 0;
+		ccw->bits |= CCW_IRQ;
+		ccw->bits |= CCW_DEC_SEM;
+		ccw->bits |= CCW_WAIT4END;
+		ccw->bits |= CCW_HALT_ON_TERM;
+		ccw->bits |= CCW_TERM_FLUSH;
+		ccw->bits |= BF_CCW(sg_len, PIO_NUM);
+		ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND);
+	} else {
+		for_each_sg(sgl, sg, sg_len, i) {
+			if (sg->length > MAX_XFER_BYTES) {
+				dev_err(mxs_dma->dma_device.dev, "maximum bytes for sg entry exceeded: %d > %d\n",
+						sg->length, MAX_XFER_BYTES);
+				goto err_out;
+			}
+
+			ccw = &mxs_chan->ccw[idx++];
+
+			ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
+			ccw->bufaddr = sg->dma_address;
+			ccw->xfer_bytes = sg->length;
+
+			ccw->bits = 0;
+			ccw->bits |= CCW_CHAIN;
+			ccw->bits |= CCW_HALT_ON_TERM;
+			ccw->bits |= CCW_TERM_FLUSH;
+			ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+					MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ,
+					COMMAND);
+
+			if (i + 1 == sg_len) {
+				ccw->bits &= ~CCW_CHAIN;
+				ccw->bits |= CCW_IRQ;
+				ccw->bits |= CCW_DEC_SEM;
+				ccw->bits |= CCW_WAIT4END;
+			}
+		}
+	}
+
+	return &mxs_chan->desc;
+
+err_out:
+	mxs_chan->status = DMA_ERROR;
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int num_periods = buf_len / period_len;
+	int i = 0, buf = 0;
+
+	if (mxs_chan->status == DMA_IN_PROGRESS)
+		return NULL;
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+	mxs_chan->flags |= MXS_DMA_SG_LOOP;
+
+	if (num_periods > NUM_CCW) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum number of sg exceeded: %d > %d\n",
+				num_periods, NUM_CCW);
+		goto err_out;
+	}
+
+	if (period_len > MAX_XFER_BYTES) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum period size exceeded: %d > %d\n",
+				period_len, MAX_XFER_BYTES);
+		goto err_out;
+	}
+
+	while (buf < buf_len) {
+		struct mxs_dma_ccw *ccw = &mxs_chan->ccw[i];
+
+		if (i + 1 == num_periods)
+			ccw->next = mxs_chan->ccw_phys;
+		else
+			ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * (i + 1);
+
+		ccw->bufaddr = dma_addr;
+		ccw->xfer_bytes = period_len;
+
+		ccw->bits = 0;
+		ccw->bits |= CCW_CHAIN;
+		ccw->bits |= CCW_IRQ;
+		ccw->bits |= CCW_HALT_ON_TERM;
+		ccw->bits |= CCW_TERM_FLUSH;
+		ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+				MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND);
+
+		dma_addr += period_len;
+		buf += period_len;
+
+		i++;
+	}
+
+	return &mxs_chan->desc;
+
+err_out:
+	mxs_chan->status = DMA_ERROR;
+	return NULL;
+}
+
+static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+		unsigned long arg)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	int ret = 0;
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		mxs_dma_disable_chan(mxs_chan);
+		break;
+	case DMA_PAUSE:
+		mxs_dma_pause_chan(mxs_chan);
+		break;
+	case DMA_RESUME:
+		mxs_dma_resume_chan(mxs_chan);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	return ret;
+}
+
+static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
+			dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	dma_cookie_t last_used;
+
+	last_used = chan->cookie;
+	dma_set_tx_state(txstate, mxs_chan->last_completed, last_used, 0);
+
+	return mxs_chan->status;
+}
+
+static void mxs_dma_issue_pending(struct dma_chan *chan)
+{
+	/*
+	 * Nothing to do. We only have a single descriptor.
+	 */
+}
+
+static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
+{
+	int ret;
+
+	ret = clk_enable(mxs_dma->clk);
+	if (ret)
+		goto err_out;
+
+	ret = mxs_reset_block(mxs_dma->base);
+	if (ret)
+		goto err_out;
+
+	/* only major version matters */
+	mxs_dma->version = readl(mxs_dma->base +
+				((mxs_dma->dev_id == MXS_DMA_APBX) ?
+				HW_APBX_VERSION : HW_APBH_VERSION)) >>
+				BP_APBHX_VERSION_MAJOR;
+
+	/* enable apbh burst */
+	if (dma_is_apbh()) {
+		writel(BM_APBH_CTRL0_APB_BURST_EN,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+		writel(BM_APBH_CTRL0_APB_BURST8_EN,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	}
+
+	/* enable irq for all the channels */
+	writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS,
+		mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR);
+
+	clk_disable(mxs_dma->clk);
+
+	return 0;
+
+err_out:
+	return ret;
+}
+
+static int __init mxs_dma_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(pdev);
+	struct mxs_dma_engine *mxs_dma;
+	struct resource *iores;
+	int ret, i;
+
+	mxs_dma = kzalloc(sizeof(*mxs_dma), GFP_KERNEL);
+	if (!mxs_dma)
+		return -ENOMEM;
+
+	mxs_dma->dev_id = id_entry->driver_data;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	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;
+	}
+
+	dma_cap_set(DMA_SLAVE, mxs_dma->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, mxs_dma->dma_device.cap_mask);
+
+	INIT_LIST_HEAD(&mxs_dma->dma_device.channels);
+
+	/* Initialize channel parameters */
+	for (i = 0; i < MXS_DMA_CHANNELS; i++) {
+		struct mxs_dma_chan *mxs_chan = &mxs_dma->mxs_chans[i];
+
+		mxs_chan->mxs_dma = mxs_dma;
+		mxs_chan->chan.device = &mxs_dma->dma_device;
+
+		tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet,
+			     (unsigned long) mxs_chan);
+
+
+		/* Add the channel to mxs_chan list */
+		list_add_tail(&mxs_chan->chan.device_node,
+			&mxs_dma->dma_device.channels);
+	}
+
+	ret = mxs_dma_init(mxs_dma);
+	if (ret)
+		goto err_init;
+
+	mxs_dma->dma_device.dev = &pdev->dev;
+
+	/* mxs_dma gets 65535 bytes maximum sg size */
+	mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms;
+	dma_set_max_seg_size(mxs_dma->dma_device.dev, MAX_XFER_BYTES);
+
+	mxs_dma->dma_device.device_alloc_chan_resources = mxs_dma_alloc_chan_resources;
+	mxs_dma->dma_device.device_free_chan_resources = mxs_dma_free_chan_resources;
+	mxs_dma->dma_device.device_tx_status = mxs_dma_tx_status;
+	mxs_dma->dma_device.device_prep_slave_sg = mxs_dma_prep_slave_sg;
+	mxs_dma->dma_device.device_prep_dma_cyclic = mxs_dma_prep_dma_cyclic;
+	mxs_dma->dma_device.device_control = mxs_dma_control;
+	mxs_dma->dma_device.device_issue_pending = mxs_dma_issue_pending;
+
+	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;
+	}
+
+	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_device_id mxs_dma_type[] = {
+	{
+		.name = "mxs-dma-apbh",
+		.driver_data = MXS_DMA_APBH,
+	}, {
+		.name = "mxs-dma-apbx",
+		.driver_data = MXS_DMA_APBX,
+	}
+};
+
+static struct platform_driver mxs_dma_driver = {
+	.driver		= {
+		.name	= "mxs-dma",
+	},
+	.id_table	= mxs_dma_type,
+};
+
+static int __init mxs_dma_module_init(void)
+{
+	return platform_driver_probe(&mxs_dma_driver, mxs_dma_probe);
+}
+subsys_initcall(mxs_dma_module_init);
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 1c38418..8d8fef1 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -82,7 +82,7 @@ struct pch_dma_regs {
 	u32	dma_sts1;
 	u32	reserved2;
 	u32	reserved3;
-	struct pch_dma_desc_regs desc[0];
+	struct pch_dma_desc_regs desc[MAX_CHAN_NR];
 };
 
 struct pch_dma_desc {
@@ -124,7 +124,7 @@ struct pch_dma {
 	struct pci_pool		*pool;
 	struct pch_dma_regs	regs;
 	struct pch_dma_desc_regs ch_regs[MAX_CHAN_NR];
-	struct pch_dma_chan	channels[0];
+	struct pch_dma_chan	channels[MAX_CHAN_NR];
 };
 
 #define PCH_DMA_CTL0	0x00
@@ -366,7 +366,7 @@ static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd)
 	struct pch_dma_chan *pd_chan = to_pd_chan(txd->chan);
 	dma_cookie_t cookie;
 
-	spin_lock_bh(&pd_chan->lock);
+	spin_lock(&pd_chan->lock);
 	cookie = pdc_assign_cookie(pd_chan, desc);
 
 	if (list_empty(&pd_chan->active_list)) {
@@ -376,7 +376,7 @@ static dma_cookie_t pd_tx_submit(struct dma_async_tx_descriptor *txd)
 		list_add_tail(&desc->desc_node, &pd_chan->queue);
 	}
 
-	spin_unlock_bh(&pd_chan->lock);
+	spin_unlock(&pd_chan->lock);
 	return 0;
 }
 
@@ -386,7 +386,7 @@ static struct pch_dma_desc *pdc_alloc_desc(struct dma_chan *chan, gfp_t flags)
 	struct pch_dma *pd = to_pd(chan->device);
 	dma_addr_t addr;
 
-	desc = pci_pool_alloc(pd->pool, GFP_KERNEL, &addr);
+	desc = pci_pool_alloc(pd->pool, flags, &addr);
 	if (desc) {
 		memset(desc, 0, sizeof(struct pch_dma_desc));
 		INIT_LIST_HEAD(&desc->tx_list);
@@ -405,7 +405,7 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan)
 	struct pch_dma_desc *ret = NULL;
 	int i;
 
-	spin_lock_bh(&pd_chan->lock);
+	spin_lock(&pd_chan->lock);
 	list_for_each_entry_safe(desc, _d, &pd_chan->free_list, desc_node) {
 		i++;
 		if (async_tx_test_ack(&desc->txd)) {
@@ -415,15 +415,15 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan)
 		}
 		dev_dbg(chan2dev(&pd_chan->chan), "desc %p not ACKed\n", desc);
 	}
-	spin_unlock_bh(&pd_chan->lock);
+	spin_unlock(&pd_chan->lock);
 	dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i);
 
 	if (!ret) {
 		ret = pdc_alloc_desc(&pd_chan->chan, GFP_NOIO);
 		if (ret) {
-			spin_lock_bh(&pd_chan->lock);
+			spin_lock(&pd_chan->lock);
 			pd_chan->descs_allocated++;
-			spin_unlock_bh(&pd_chan->lock);
+			spin_unlock(&pd_chan->lock);
 		} else {
 			dev_err(chan2dev(&pd_chan->chan),
 				"failed to alloc desc\n");
@@ -437,10 +437,10 @@ static void pdc_desc_put(struct pch_dma_chan *pd_chan,
 			 struct pch_dma_desc *desc)
 {
 	if (desc) {
-		spin_lock_bh(&pd_chan->lock);
+		spin_lock(&pd_chan->lock);
 		list_splice_init(&desc->tx_list, &pd_chan->free_list);
 		list_add(&desc->desc_node, &pd_chan->free_list);
-		spin_unlock_bh(&pd_chan->lock);
+		spin_unlock(&pd_chan->lock);
 	}
 }
 
@@ -530,9 +530,9 @@ static void pd_issue_pending(struct dma_chan *chan)
 	struct pch_dma_chan *pd_chan = to_pd_chan(chan);
 
 	if (pdc_is_idle(pd_chan)) {
-		spin_lock_bh(&pd_chan->lock);
+		spin_lock(&pd_chan->lock);
 		pdc_advance_work(pd_chan);
-		spin_unlock_bh(&pd_chan->lock);
+		spin_unlock(&pd_chan->lock);
 	}
 }
 
@@ -592,7 +592,6 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan,
 			goto err_desc_get;
 		}
 
-
 		if (!first) {
 			first = desc;
 		} else {
@@ -641,13 +640,13 @@ static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 
 	spin_unlock_bh(&pd_chan->lock);
 
-
 	return 0;
 }
 
 static void pdc_tasklet(unsigned long data)
 {
 	struct pch_dma_chan *pd_chan = (struct pch_dma_chan *)data;
+	unsigned long flags;
 
 	if (!pdc_is_idle(pd_chan)) {
 		dev_err(chan2dev(&pd_chan->chan),
@@ -655,12 +654,12 @@ static void pdc_tasklet(unsigned long data)
 		return;
 	}
 
-	spin_lock_bh(&pd_chan->lock);
+	spin_lock_irqsave(&pd_chan->lock, flags);
 	if (test_and_clear_bit(0, &pd_chan->err_status))
 		pdc_handle_error(pd_chan);
 	else
 		pdc_advance_work(pd_chan);
-	spin_unlock_bh(&pd_chan->lock);
+	spin_unlock_irqrestore(&pd_chan->lock, flags);
 }
 
 static irqreturn_t pd_irq(int irq, void *devid)
@@ -694,6 +693,7 @@ static irqreturn_t pd_irq(int irq, void *devid)
 	return ret;
 }
 
+#ifdef	CONFIG_PM
 static void pch_dma_save_regs(struct pch_dma *pd)
 {
 	struct pch_dma_chan *pd_chan;
@@ -771,6 +771,7 @@ static int pch_dma_resume(struct pci_dev *pdev)
 
 	return 0;
 }
+#endif
 
 static int __devinit pch_dma_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *id)
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 7c50f6d..6abe1ec 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -657,7 +657,7 @@ static irqreturn_t pl330_irq_handler(int irq, void *data)
 }
 
 static int __devinit
-pl330_probe(struct amba_device *adev, struct amba_id *id)
+pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct dma_pl330_platdata *pdat;
 	struct dma_pl330_dmac *pdmac;
diff --git a/drivers/dma/ppc4xx/adma.c b/drivers/dma/ppc4xx/adma.c
index cef5845..3b0247e 100644
--- a/drivers/dma/ppc4xx/adma.c
+++ b/drivers/dma/ppc4xx/adma.c
@@ -4393,8 +4393,7 @@ static void ppc440spe_adma_release_irqs(struct ppc440spe_adma_device *adev,
 /**
  * ppc440spe_adma_probe - probe the asynch device
  */
-static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev,
-					  const struct of_device_id *match)
+static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct resource res;
@@ -4944,7 +4943,7 @@ static const struct of_device_id ppc440spe_adma_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
 
-static struct of_platform_driver ppc440spe_adma_driver = {
+static struct platform_driver ppc440spe_adma_driver = {
 	.probe = ppc440spe_adma_probe,
 	.remove = __devexit_p(ppc440spe_adma_remove),
 	.driver = {
@@ -4962,7 +4961,7 @@ static __init int ppc440spe_adma_init(void)
 	if (ret)
 		return ret;
 
-	ret = of_register_platform_driver(&ppc440spe_adma_driver);
+	ret = platform_driver_register(&ppc440spe_adma_driver);
 	if (ret) {
 		pr_err("%s: failed to register platform driver\n",
 			__func__);
@@ -4996,7 +4995,7 @@ out_dev:
 	/* User will not be able to enable h/w RAID-6 */
 	pr_err("%s: failed to create RAID-6 driver interface\n",
 		__func__);
-	of_unregister_platform_driver(&ppc440spe_adma_driver);
+	platform_driver_unregister(&ppc440spe_adma_driver);
 out_reg:
 	dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len);
 	kfree(ppc440spe_dma_fifo_buf);
@@ -5011,7 +5010,7 @@ static void __exit ppc440spe_adma_exit(void)
 			   &driver_attr_enable);
 	driver_remove_file(&ppc440spe_adma_driver.driver,
 			   &driver_attr_devices);
-	of_unregister_platform_driver(&ppc440spe_adma_driver);
+	platform_driver_unregister(&ppc440spe_adma_driver);
 	dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len);
 	kfree(ppc440spe_dma_fifo_buf);
 }
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 28720d3..6451b58 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -750,7 +750,7 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
 		return;
 	}
 
-	/* Find the first not transferred desciptor */
+	/* Find the first not transferred descriptor */
 	list_for_each_entry(desc, &sh_chan->ld_queue, node)
 		if (desc->mark == DESC_SUBMITTED) {
 			dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 6e1d46a..af955de 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -68,6 +68,7 @@ enum d40_command {
  * @base: Pointer to memory area when the pre_alloc_lli's are not large
  * enough, IE bigger than the most common case, 1 dst and 1 src. NULL if
  * pre_alloc_lli is used.
+ * @dma_addr: DMA address, if mapped
  * @size: The size in bytes of the memory at base or the size of pre_alloc_lli.
  * @pre_alloc_lli: Pre allocated area for the most common case of transfers,
  * one buffer to one buffer.
@@ -75,6 +76,7 @@ enum d40_command {
 struct d40_lli_pool {
 	void	*base;
 	int	 size;
+	dma_addr_t	dma_addr;
 	/* Space for dst and src, plus an extra for padding */
 	u8	 pre_alloc_lli[3 * sizeof(struct d40_phy_lli)];
 };
@@ -94,7 +96,6 @@ struct d40_lli_pool {
  * during a transfer.
  * @node: List entry.
  * @is_in_client_list: true if the client owns this descriptor.
- * @is_hw_linked: true if this job will automatically be continued for
  * the previous one.
  *
  * This descriptor is used for both logical and physical transfers.
@@ -114,7 +115,7 @@ struct d40_desc {
 	struct list_head		 node;
 
 	bool				 is_in_client_list;
-	bool				 is_hw_linked;
+	bool				 cyclic;
 };
 
 /**
@@ -130,6 +131,7 @@ struct d40_desc {
  */
 struct d40_lcla_pool {
 	void		*base;
+	dma_addr_t	dma_addr;
 	void		*base_unaligned;
 	int		 pages;
 	spinlock_t	 lock;
@@ -303,9 +305,37 @@ struct d40_reg_val {
 	unsigned int val;
 };
 
-static int d40_pool_lli_alloc(struct d40_desc *d40d,
-			      int lli_len, bool is_log)
+static struct device *chan2dev(struct d40_chan *d40c)
 {
+	return &d40c->chan.dev->device;
+}
+
+static bool chan_is_physical(struct d40_chan *chan)
+{
+	return chan->log_num == D40_PHY_CHAN;
+}
+
+static bool chan_is_logical(struct d40_chan *chan)
+{
+	return !chan_is_physical(chan);
+}
+
+static void __iomem *chan_base(struct d40_chan *chan)
+{
+	return chan->base->virtbase + D40_DREG_PCBASE +
+	       chan->phy_chan->num * D40_DREG_PCDELTA;
+}
+
+#define d40_err(dev, format, arg...)		\
+	dev_err(dev, "[%s] " format, __func__, ## arg)
+
+#define chan_err(d40c, format, arg...)		\
+	d40_err(chan2dev(d40c), format, ## arg)
+
+static int d40_pool_lli_alloc(struct d40_chan *d40c, struct d40_desc *d40d,
+			      int lli_len)
+{
+	bool is_log = chan_is_logical(d40c);
 	u32 align;
 	void *base;
 
@@ -319,7 +349,7 @@ static int d40_pool_lli_alloc(struct d40_desc *d40d,
 		d40d->lli_pool.size = sizeof(d40d->lli_pool.pre_alloc_lli);
 		d40d->lli_pool.base = NULL;
 	} else {
-		d40d->lli_pool.size = ALIGN(lli_len * 2 * align, align);
+		d40d->lli_pool.size = lli_len * 2 * align;
 
 		base = kmalloc(d40d->lli_pool.size + align, GFP_NOWAIT);
 		d40d->lli_pool.base = base;
@@ -329,22 +359,37 @@ static int d40_pool_lli_alloc(struct d40_desc *d40d,
 	}
 
 	if (is_log) {
-		d40d->lli_log.src = PTR_ALIGN((struct d40_log_lli *) base,
-					      align);
-		d40d->lli_log.dst = PTR_ALIGN(d40d->lli_log.src + lli_len,
-					      align);
+		d40d->lli_log.src = PTR_ALIGN(base, align);
+		d40d->lli_log.dst = d40d->lli_log.src + lli_len;
+
+		d40d->lli_pool.dma_addr = 0;
 	} else {
-		d40d->lli_phy.src = PTR_ALIGN((struct d40_phy_lli *)base,
-					      align);
-		d40d->lli_phy.dst = PTR_ALIGN(d40d->lli_phy.src + lli_len,
-					      align);
+		d40d->lli_phy.src = PTR_ALIGN(base, align);
+		d40d->lli_phy.dst = d40d->lli_phy.src + lli_len;
+
+		d40d->lli_pool.dma_addr = dma_map_single(d40c->base->dev,
+							 d40d->lli_phy.src,
+							 d40d->lli_pool.size,
+							 DMA_TO_DEVICE);
+
+		if (dma_mapping_error(d40c->base->dev,
+				      d40d->lli_pool.dma_addr)) {
+			kfree(d40d->lli_pool.base);
+			d40d->lli_pool.base = NULL;
+			d40d->lli_pool.dma_addr = 0;
+			return -ENOMEM;
+		}
 	}
 
 	return 0;
 }
 
-static void d40_pool_lli_free(struct d40_desc *d40d)
+static void d40_pool_lli_free(struct d40_chan *d40c, struct d40_desc *d40d)
 {
+	if (d40d->lli_pool.dma_addr)
+		dma_unmap_single(d40c->base->dev, d40d->lli_pool.dma_addr,
+				 d40d->lli_pool.size, DMA_TO_DEVICE);
+
 	kfree(d40d->lli_pool.base);
 	d40d->lli_pool.base = NULL;
 	d40d->lli_pool.size = 0;
@@ -391,7 +436,7 @@ static int d40_lcla_free_all(struct d40_chan *d40c,
 	int i;
 	int ret = -EINVAL;
 
-	if (d40c->log_num == D40_PHY_CHAN)
+	if (chan_is_physical(d40c))
 		return 0;
 
 	spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags);
@@ -430,7 +475,7 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c)
 
 		list_for_each_entry_safe(d, _d, &d40c->client, node)
 			if (async_tx_test_ack(&d->txd)) {
-				d40_pool_lli_free(d);
+				d40_pool_lli_free(d40c, d);
 				d40_desc_remove(d);
 				desc = d;
 				memset(desc, 0, sizeof(*desc));
@@ -450,6 +495,7 @@ static struct d40_desc *d40_desc_get(struct d40_chan *d40c)
 static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d)
 {
 
+	d40_pool_lli_free(d40c, d40d);
 	d40_lcla_free_all(d40c, d40d);
 	kmem_cache_free(d40c->base->desc_slab, d40d);
 }
@@ -459,57 +505,128 @@ static void d40_desc_submit(struct d40_chan *d40c, struct d40_desc *desc)
 	list_add_tail(&desc->node, &d40c->active);
 }
 
-static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d)
+static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc)
 {
-	int curr_lcla = -EINVAL, next_lcla;
+	struct d40_phy_lli *lli_dst = desc->lli_phy.dst;
+	struct d40_phy_lli *lli_src = desc->lli_phy.src;
+	void __iomem *base = chan_base(chan);
+
+	writel(lli_src->reg_cfg, base + D40_CHAN_REG_SSCFG);
+	writel(lli_src->reg_elt, base + D40_CHAN_REG_SSELT);
+	writel(lli_src->reg_ptr, base + D40_CHAN_REG_SSPTR);
+	writel(lli_src->reg_lnk, base + D40_CHAN_REG_SSLNK);
+
+	writel(lli_dst->reg_cfg, base + D40_CHAN_REG_SDCFG);
+	writel(lli_dst->reg_elt, base + D40_CHAN_REG_SDELT);
+	writel(lli_dst->reg_ptr, base + D40_CHAN_REG_SDPTR);
+	writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK);
+}
 
-	if (d40c->log_num == D40_PHY_CHAN) {
-		d40_phy_lli_write(d40c->base->virtbase,
-				  d40c->phy_chan->num,
-				  d40d->lli_phy.dst,
-				  d40d->lli_phy.src);
-		d40d->lli_current = d40d->lli_len;
-	} else {
+static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
+{
+	struct d40_lcla_pool *pool = &chan->base->lcla_pool;
+	struct d40_log_lli_bidir *lli = &desc->lli_log;
+	int lli_current = desc->lli_current;
+	int lli_len = desc->lli_len;
+	bool cyclic = desc->cyclic;
+	int curr_lcla = -EINVAL;
+	int first_lcla = 0;
+	bool linkback;
 
-		if ((d40d->lli_len - d40d->lli_current) > 1)
-			curr_lcla = d40_lcla_alloc_one(d40c, d40d);
+	/*
+	 * We may have partially running cyclic transfers, in case we did't get
+	 * enough LCLA entries.
+	 */
+	linkback = cyclic && lli_current == 0;
 
-		d40_log_lli_lcpa_write(d40c->lcpa,
-				       &d40d->lli_log.dst[d40d->lli_current],
-				       &d40d->lli_log.src[d40d->lli_current],
-				       curr_lcla);
+	/*
+	 * For linkback, we need one LCLA even with only one link, because we
+	 * can't link back to the one in LCPA space
+	 */
+	if (linkback || (lli_len - lli_current > 1)) {
+		curr_lcla = d40_lcla_alloc_one(chan, desc);
+		first_lcla = curr_lcla;
+	}
 
-		d40d->lli_current++;
-		for (; d40d->lli_current < d40d->lli_len; d40d->lli_current++) {
-			struct d40_log_lli *lcla;
+	/*
+	 * For linkback, we normally load the LCPA in the loop since we need to
+	 * link it to the second LCLA and not the first.  However, if we
+	 * couldn't even get a first LCLA, then we have to run in LCPA and
+	 * reload manually.
+	 */
+	if (!linkback || curr_lcla == -EINVAL) {
+		unsigned int flags = 0;
 
-			if (d40d->lli_current + 1 < d40d->lli_len)
-				next_lcla = d40_lcla_alloc_one(d40c, d40d);
-			else
-				next_lcla = -EINVAL;
+		if (curr_lcla == -EINVAL)
+			flags |= LLI_TERM_INT;
 
-			lcla = d40c->base->lcla_pool.base +
-				d40c->phy_chan->num * 1024 +
-				8 * curr_lcla * 2;
+		d40_log_lli_lcpa_write(chan->lcpa,
+				       &lli->dst[lli_current],
+				       &lli->src[lli_current],
+				       curr_lcla,
+				       flags);
+		lli_current++;
+	}
 
-			d40_log_lli_lcla_write(lcla,
-					       &d40d->lli_log.dst[d40d->lli_current],
-					       &d40d->lli_log.src[d40d->lli_current],
-					       next_lcla);
+	if (curr_lcla < 0)
+		goto out;
 
-			(void) dma_map_single(d40c->base->dev, lcla,
-					      2 * sizeof(struct d40_log_lli),
-					      DMA_TO_DEVICE);
+	for (; lli_current < lli_len; lli_current++) {
+		unsigned int lcla_offset = chan->phy_chan->num * 1024 +
+					   8 * curr_lcla * 2;
+		struct d40_log_lli *lcla = pool->base + lcla_offset;
+		unsigned int flags = 0;
+		int next_lcla;
 
-			curr_lcla = next_lcla;
+		if (lli_current + 1 < lli_len)
+			next_lcla = d40_lcla_alloc_one(chan, desc);
+		else
+			next_lcla = linkback ? first_lcla : -EINVAL;
 
-			if (curr_lcla == -EINVAL) {
-				d40d->lli_current++;
-				break;
-			}
+		if (cyclic || next_lcla == -EINVAL)
+			flags |= LLI_TERM_INT;
+
+		if (linkback && curr_lcla == first_lcla) {
+			/* First link goes in both LCPA and LCLA */
+			d40_log_lli_lcpa_write(chan->lcpa,
+					       &lli->dst[lli_current],
+					       &lli->src[lli_current],
+					       next_lcla, flags);
+		}
+
+		/*
+		 * One unused LCLA in the cyclic case if the very first
+		 * next_lcla fails...
+		 */
+		d40_log_lli_lcla_write(lcla,
+				       &lli->dst[lli_current],
+				       &lli->src[lli_current],
+				       next_lcla, flags);
+
+		dma_sync_single_range_for_device(chan->base->dev,
+					pool->dma_addr, lcla_offset,
+					2 * sizeof(struct d40_log_lli),
+					DMA_TO_DEVICE);
 
+		curr_lcla = next_lcla;
+
+		if (curr_lcla == -EINVAL || curr_lcla == first_lcla) {
+			lli_current++;
+			break;
 		}
 	}
+
+out:
+	desc->lli_current = lli_current;
+}
+
+static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d)
+{
+	if (chan_is_physical(d40c)) {
+		d40_phy_lli_load(d40c, d40d);
+		d40d->lli_current = d40d->lli_len;
+	} else
+		d40_log_lli_to_lcxa(d40c, d40d);
 }
 
 static struct d40_desc *d40_first_active_get(struct d40_chan *d40c)
@@ -543,18 +660,6 @@ static struct d40_desc *d40_first_queued(struct d40_chan *d40c)
 	return d;
 }
 
-static struct d40_desc *d40_last_queued(struct d40_chan *d40c)
-{
-	struct d40_desc *d;
-
-	if (list_empty(&d40c->queue))
-		return NULL;
-	list_for_each_entry(d, &d40c->queue, node)
-		if (list_is_last(&d->node, &d40c->queue))
-			break;
-	return d;
-}
-
 static int d40_psize_2_burst_size(bool is_log, int psize)
 {
 	if (is_log) {
@@ -666,9 +771,9 @@ static int d40_channel_execute_command(struct d40_chan *d40c,
 		}
 
 		if (i == D40_SUSPEND_MAX_IT) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s]: unable to suspend the chl %d (log: %d) status %x\n",
-				__func__, d40c->phy_chan->num, d40c->log_num,
+			chan_err(d40c,
+				"unable to suspend the chl %d (log: %d) status %x\n",
+				d40c->phy_chan->num, d40c->log_num,
 				status);
 			dump_stack();
 			ret = -EBUSY;
@@ -701,17 +806,45 @@ static void d40_term_all(struct d40_chan *d40c)
 	d40c->busy = false;
 }
 
+static void __d40_config_set_event(struct d40_chan *d40c, bool enable,
+				   u32 event, int reg)
+{
+	void __iomem *addr = chan_base(d40c) + reg;
+	int tries;
+
+	if (!enable) {
+		writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
+		       | ~D40_EVENTLINE_MASK(event), addr);
+		return;
+	}
+
+	/*
+	 * The hardware sometimes doesn't register the enable when src and dst
+	 * event lines are active on the same logical channel.  Retry to ensure
+	 * it does.  Usually only one retry is sufficient.
+	 */
+	tries = 100;
+	while (--tries) {
+		writel((D40_ACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
+		       | ~D40_EVENTLINE_MASK(event), addr);
+
+		if (readl(addr) & D40_EVENTLINE_MASK(event))
+			break;
+	}
+
+	if (tries != 99)
+		dev_dbg(chan2dev(d40c),
+			"[%s] workaround enable S%cLNK (%d tries)\n",
+			__func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D',
+			100 - tries);
+
+	WARN_ON(!tries);
+}
+
 static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
 {
-	u32 val;
 	unsigned long flags;
 
-	/* Notice, that disable requires the physical channel to be stopped */
-	if (do_enable)
-		val = D40_ACTIVATE_EVENTLINE;
-	else
-		val = D40_DEACTIVATE_EVENTLINE;
-
 	spin_lock_irqsave(&d40c->phy_chan->lock, flags);
 
 	/* Enable event line connected to device (or memcpy) */
@@ -719,20 +852,15 @@ static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
 	    (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) {
 		u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
 
-		writel((val << D40_EVENTLINE_POS(event)) |
-		       ~D40_EVENTLINE_MASK(event),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSLNK);
+		__d40_config_set_event(d40c, do_enable, event,
+				       D40_CHAN_REG_SSLNK);
 	}
+
 	if (d40c->dma_cfg.dir !=  STEDMA40_PERIPH_TO_MEM) {
 		u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
 
-		writel((val << D40_EVENTLINE_POS(event)) |
-		       ~D40_EVENTLINE_MASK(event),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDLNK);
+		__d40_config_set_event(d40c, do_enable, event,
+				       D40_CHAN_REG_SDLNK);
 	}
 
 	spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
@@ -740,15 +868,12 @@ static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
 
 static u32 d40_chan_has_events(struct d40_chan *d40c)
 {
+	void __iomem *chanbase = chan_base(d40c);
 	u32 val;
 
-	val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		    d40c->phy_chan->num * D40_DREG_PCDELTA +
-		    D40_CHAN_REG_SSLNK);
+	val = readl(chanbase + D40_CHAN_REG_SSLNK);
+	val |= readl(chanbase + D40_CHAN_REG_SDLNK);
 
-	val |= readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		     d40c->phy_chan->num * D40_DREG_PCDELTA +
-		     D40_CHAN_REG_SDLNK);
 	return val;
 }
 
@@ -771,7 +896,7 @@ static u32 d40_get_prmo(struct d40_chan *d40c)
 			= D40_DREG_PRMO_LCHAN_SRC_LOG_DST_LOG,
 	};
 
-	if (d40c->log_num == D40_PHY_CHAN)
+	if (chan_is_physical(d40c))
 		return phy_map[d40c->dma_cfg.mode_opt];
 	else
 		return log_map[d40c->dma_cfg.mode_opt];
@@ -785,7 +910,7 @@ static void d40_config_write(struct d40_chan *d40c)
 	/* Odd addresses are even addresses + 4 */
 	addr_base = (d40c->phy_chan->num % 2) * 4;
 	/* Setup channel mode to logical or physical */
-	var = ((u32)(d40c->log_num != D40_PHY_CHAN) + 1) <<
+	var = ((u32)(chan_is_logical(d40c)) + 1) <<
 		D40_CHAN_POS(d40c->phy_chan->num);
 	writel(var, d40c->base->virtbase + D40_DREG_PRMSE + addr_base);
 
@@ -794,30 +919,18 @@ static void d40_config_write(struct d40_chan *d40c)
 
 	writel(var, d40c->base->virtbase + D40_DREG_PRMOE + addr_base);
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	if (chan_is_logical(d40c)) {
+		int lidx = (d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS)
+			   & D40_SREG_ELEM_LOG_LIDX_MASK;
+		void __iomem *chanbase = chan_base(d40c);
+
 		/* Set default config for CFG reg */
-		writel(d40c->src_def_cfg,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSCFG);
-		writel(d40c->dst_def_cfg,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDCFG);
+		writel(d40c->src_def_cfg, chanbase + D40_CHAN_REG_SSCFG);
+		writel(d40c->dst_def_cfg, chanbase + D40_CHAN_REG_SDCFG);
 
 		/* Set LIDX for lcla */
-		writel((d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) &
-		       D40_SREG_ELEM_LOG_LIDX_MASK,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDELT);
-
-		writel((d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) &
-		       D40_SREG_ELEM_LOG_LIDX_MASK,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSELT);
-
+		writel(lidx, chanbase + D40_CHAN_REG_SSELT);
+		writel(lidx, chanbase + D40_CHAN_REG_SDELT);
 	}
 }
 
@@ -825,15 +938,15 @@ static u32 d40_residue(struct d40_chan *d40c)
 {
 	u32 num_elt;
 
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		num_elt = (readl(&d40c->lcpa->lcsp2) & D40_MEM_LCSP2_ECNT_MASK)
 			>> D40_MEM_LCSP2_ECNT_POS;
-	else
-		num_elt = (readl(d40c->base->virtbase + D40_DREG_PCBASE +
-				 d40c->phy_chan->num * D40_DREG_PCDELTA +
-				 D40_CHAN_REG_SDELT) &
-			   D40_SREG_ELEM_PHY_ECNT_MASK) >>
-			D40_SREG_ELEM_PHY_ECNT_POS;
+	else {
+		u32 val = readl(chan_base(d40c) + D40_CHAN_REG_SDELT);
+		num_elt = (val & D40_SREG_ELEM_PHY_ECNT_MASK)
+			  >> D40_SREG_ELEM_PHY_ECNT_POS;
+	}
+
 	return num_elt * (1 << d40c->dma_cfg.dst_info.data_width);
 }
 
@@ -841,20 +954,17 @@ static bool d40_tx_is_linked(struct d40_chan *d40c)
 {
 	bool is_link;
 
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		is_link = readl(&d40c->lcpa->lcsp3) &  D40_MEM_LCSP3_DLOS_MASK;
 	else
-		is_link = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-				d40c->phy_chan->num * D40_DREG_PCDELTA +
-				D40_CHAN_REG_SDLNK) &
-			D40_SREG_LNK_PHYS_LNK_MASK;
+		is_link = readl(chan_base(d40c) + D40_CHAN_REG_SDLNK)
+			  & D40_SREG_LNK_PHYS_LNK_MASK;
+
 	return is_link;
 }
 
-static int d40_pause(struct dma_chan *chan)
+static int d40_pause(struct d40_chan *d40c)
 {
-	struct d40_chan *d40c =
-		container_of(chan, struct d40_chan, chan);
 	int res = 0;
 	unsigned long flags;
 
@@ -865,7 +975,7 @@ static int d40_pause(struct dma_chan *chan)
 
 	res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
 	if (res == 0) {
-		if (d40c->log_num != D40_PHY_CHAN) {
+		if (chan_is_logical(d40c)) {
 			d40_config_set_event(d40c, false);
 			/* Resume the other logical channels if any */
 			if (d40_chan_has_events(d40c))
@@ -878,10 +988,8 @@ static int d40_pause(struct dma_chan *chan)
 	return res;
 }
 
-static int d40_resume(struct dma_chan *chan)
+static int d40_resume(struct d40_chan *d40c)
 {
-	struct d40_chan *d40c =
-		container_of(chan, struct d40_chan, chan);
 	int res = 0;
 	unsigned long flags;
 
@@ -891,7 +999,7 @@ static int d40_resume(struct dma_chan *chan)
 	spin_lock_irqsave(&d40c->lock, flags);
 
 	if (d40c->base->rev == 0)
-		if (d40c->log_num != D40_PHY_CHAN) {
+		if (chan_is_logical(d40c)) {
 			res = d40_channel_execute_command(d40c,
 							  D40_DMA_SUSPEND_REQ);
 			goto no_suspend;
@@ -900,7 +1008,7 @@ static int d40_resume(struct dma_chan *chan)
 	/* If bytes left to transfer or linked tx resume job */
 	if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
 
-		if (d40c->log_num != D40_PHY_CHAN)
+		if (chan_is_logical(d40c))
 			d40_config_set_event(d40c, true);
 
 		res = d40_channel_execute_command(d40c, D40_DMA_RUN);
@@ -911,75 +1019,20 @@ no_suspend:
 	return res;
 }
 
-static void d40_tx_submit_log(struct d40_chan *d40c, struct d40_desc *d40d)
+static int d40_terminate_all(struct d40_chan *chan)
 {
-	/* TODO: Write */
-}
-
-static void d40_tx_submit_phy(struct d40_chan *d40c, struct d40_desc *d40d)
-{
-	struct d40_desc *d40d_prev = NULL;
-	int i;
-	u32 val;
-
-	if (!list_empty(&d40c->queue))
-		d40d_prev = d40_last_queued(d40c);
-	else if (!list_empty(&d40c->active))
-		d40d_prev = d40_first_active_get(d40c);
-
-	if (!d40d_prev)
-		return;
-
-	/* Here we try to join this job with previous jobs */
-	val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		    d40c->phy_chan->num * D40_DREG_PCDELTA +
-		    D40_CHAN_REG_SSLNK);
-
-	/* Figure out which link we're currently transmitting */
-	for (i = 0; i < d40d_prev->lli_len; i++)
-		if (val == d40d_prev->lli_phy.src[i].reg_lnk)
-			break;
-
-	val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		    d40c->phy_chan->num * D40_DREG_PCDELTA +
-		    D40_CHAN_REG_SSELT) >> D40_SREG_ELEM_LOG_ECNT_POS;
-
-	if (i == (d40d_prev->lli_len - 1) && val > 0) {
-		/* Change the current one */
-		writel(virt_to_phys(d40d->lli_phy.src),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSLNK);
-		writel(virt_to_phys(d40d->lli_phy.dst),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDLNK);
-
-		d40d->is_hw_linked = true;
-
-	} else if (i < d40d_prev->lli_len) {
-		(void) dma_unmap_single(d40c->base->dev,
-					virt_to_phys(d40d_prev->lli_phy.src),
-					d40d_prev->lli_pool.size,
-					DMA_TO_DEVICE);
+	unsigned long flags;
+	int ret = 0;
 
-		/* Keep the settings */
-		val = d40d_prev->lli_phy.src[d40d_prev->lli_len - 1].reg_lnk &
-			~D40_SREG_LNK_PHYS_LNK_MASK;
-		d40d_prev->lli_phy.src[d40d_prev->lli_len - 1].reg_lnk =
-			val | virt_to_phys(d40d->lli_phy.src);
+	ret = d40_pause(chan);
+	if (!ret && chan_is_physical(chan))
+		ret = d40_channel_execute_command(chan, D40_DMA_STOP);
 
-		val = d40d_prev->lli_phy.dst[d40d_prev->lli_len - 1].reg_lnk &
-			~D40_SREG_LNK_PHYS_LNK_MASK;
-		d40d_prev->lli_phy.dst[d40d_prev->lli_len - 1].reg_lnk =
-			val | virt_to_phys(d40d->lli_phy.dst);
+	spin_lock_irqsave(&chan->lock, flags);
+	d40_term_all(chan);
+	spin_unlock_irqrestore(&chan->lock, flags);
 
-		(void) dma_map_single(d40c->base->dev,
-				      d40d_prev->lli_phy.src,
-				      d40d_prev->lli_pool.size,
-				      DMA_TO_DEVICE);
-		d40d->is_hw_linked = true;
-	}
+	return ret;
 }
 
 static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
@@ -990,8 +1043,6 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
 	struct d40_desc *d40d = container_of(tx, struct d40_desc, txd);
 	unsigned long flags;
 
-	(void) d40_pause(&d40c->chan);
-
 	spin_lock_irqsave(&d40c->lock, flags);
 
 	d40c->chan.cookie++;
@@ -1001,17 +1052,10 @@ static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
 
 	d40d->txd.cookie = d40c->chan.cookie;
 
-	if (d40c->log_num == D40_PHY_CHAN)
-		d40_tx_submit_phy(d40c, d40d);
-	else
-		d40_tx_submit_log(d40c, d40d);
-
 	d40_desc_queue(d40c, d40d);
 
 	spin_unlock_irqrestore(&d40c->lock, flags);
 
-	(void) d40_resume(&d40c->chan);
-
 	return tx->cookie;
 }
 
@@ -1020,7 +1064,7 @@ static int d40_start(struct d40_chan *d40c)
 	if (d40c->base->rev == 0) {
 		int err;
 
-		if (d40c->log_num != D40_PHY_CHAN) {
+		if (chan_is_logical(d40c)) {
 			err = d40_channel_execute_command(d40c,
 							  D40_DMA_SUSPEND_REQ);
 			if (err)
@@ -1028,7 +1072,7 @@ static int d40_start(struct d40_chan *d40c)
 		}
 	}
 
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		d40_config_set_event(d40c, true);
 
 	return d40_channel_execute_command(d40c, D40_DMA_RUN);
@@ -1051,21 +1095,14 @@ static struct d40_desc *d40_queue_start(struct d40_chan *d40c)
 		/* Add to active queue */
 		d40_desc_submit(d40c, d40d);
 
-		/*
-		 * If this job is already linked in hw,
-		 * do not submit it.
-		 */
-
-		if (!d40d->is_hw_linked) {
-			/* Initiate DMA job */
-			d40_desc_load(d40c, d40d);
+		/* Initiate DMA job */
+		d40_desc_load(d40c, d40d);
 
-			/* Start dma job */
-			err = d40_start(d40c);
+		/* Start dma job */
+		err = d40_start(d40c);
 
-			if (err)
-				return NULL;
-		}
+		if (err)
+			return NULL;
 	}
 
 	return d40d;
@@ -1082,17 +1119,36 @@ static void dma_tc_handle(struct d40_chan *d40c)
 	if (d40d == NULL)
 		return;
 
-	d40_lcla_free_all(d40c, d40d);
+	if (d40d->cyclic) {
+		/*
+		 * If this was a paritially loaded list, we need to reloaded
+		 * it, and only when the list is completed.  We need to check
+		 * for done because the interrupt will hit for every link, and
+		 * not just the last one.
+		 */
+		if (d40d->lli_current < d40d->lli_len
+		    && !d40_tx_is_linked(d40c)
+		    && !d40_residue(d40c)) {
+			d40_lcla_free_all(d40c, d40d);
+			d40_desc_load(d40c, d40d);
+			(void) d40_start(d40c);
 
-	if (d40d->lli_current < d40d->lli_len) {
-		d40_desc_load(d40c, d40d);
-		/* Start dma job */
-		(void) d40_start(d40c);
-		return;
-	}
+			if (d40d->lli_current == d40d->lli_len)
+				d40d->lli_current = 0;
+		}
+	} else {
+		d40_lcla_free_all(d40c, d40d);
 
-	if (d40_queue_start(d40c) == NULL)
-		d40c->busy = false;
+		if (d40d->lli_current < d40d->lli_len) {
+			d40_desc_load(d40c, d40d);
+			/* Start dma job */
+			(void) d40_start(d40c);
+			return;
+		}
+
+		if (d40_queue_start(d40c) == NULL)
+			d40c->busy = false;
+	}
 
 	d40c->pending_tx++;
 	tasklet_schedule(&d40c->tasklet);
@@ -1111,11 +1167,11 @@ static void dma_tasklet(unsigned long data)
 
 	/* Get first active entry from list */
 	d40d = d40_first_active_get(d40c);
-
 	if (d40d == NULL)
 		goto err;
 
-	d40c->completed = d40d->txd.cookie;
+	if (!d40d->cyclic)
+		d40c->completed = d40d->txd.cookie;
 
 	/*
 	 * If terminating a channel pending_tx is set to zero.
@@ -1130,16 +1186,18 @@ static void dma_tasklet(unsigned long data)
 	callback = d40d->txd.callback;
 	callback_param = d40d->txd.callback_param;
 
-	if (async_tx_test_ack(&d40d->txd)) {
-		d40_pool_lli_free(d40d);
-		d40_desc_remove(d40d);
-		d40_desc_free(d40c, d40d);
-	} else {
-		if (!d40d->is_in_client_list) {
+	if (!d40d->cyclic) {
+		if (async_tx_test_ack(&d40d->txd)) {
+			d40_pool_lli_free(d40c, d40d);
 			d40_desc_remove(d40d);
-			d40_lcla_free_all(d40c, d40d);
-			list_add_tail(&d40d->node, &d40c->client);
-			d40d->is_in_client_list = true;
+			d40_desc_free(d40c, d40d);
+		} else {
+			if (!d40d->is_in_client_list) {
+				d40_desc_remove(d40d);
+				d40_lcla_free_all(d40c, d40d);
+				list_add_tail(&d40d->node, &d40c->client);
+				d40d->is_in_client_list = true;
+			}
 		}
 	}
 
@@ -1216,9 +1274,8 @@ static irqreturn_t d40_handle_interrupt(int irq, void *data)
 		if (!il[row].is_error)
 			dma_tc_handle(d40c);
 		else
-			dev_err(base->dev,
-				"[%s] IRQ chan: %ld offset %d idx %d\n",
-				__func__, chan, il[row].offset, idx);
+			d40_err(base->dev, "IRQ chan: %ld offset %d idx %d\n",
+				chan, il[row].offset, idx);
 
 		spin_unlock(&d40c->lock);
 	}
@@ -1237,8 +1294,7 @@ static int d40_validate_conf(struct d40_chan *d40c,
 	bool is_log = conf->mode == STEDMA40_MODE_LOGICAL;
 
 	if (!conf->dir) {
-		dev_err(&d40c->chan.dev->device, "[%s] Invalid direction.\n",
-			__func__);
+		chan_err(d40c, "Invalid direction.\n");
 		res = -EINVAL;
 	}
 
@@ -1246,46 +1302,40 @@ static int d40_validate_conf(struct d40_chan *d40c,
 	    d40c->base->plat_data->dev_tx[conf->dst_dev_type] == 0 &&
 	    d40c->runtime_addr == 0) {
 
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Invalid TX channel address (%d)\n",
-			__func__, conf->dst_dev_type);
+		chan_err(d40c, "Invalid TX channel address (%d)\n",
+			 conf->dst_dev_type);
 		res = -EINVAL;
 	}
 
 	if (conf->src_dev_type != STEDMA40_DEV_SRC_MEMORY &&
 	    d40c->base->plat_data->dev_rx[conf->src_dev_type] == 0 &&
 	    d40c->runtime_addr == 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Invalid RX channel address (%d)\n",
-			__func__, conf->src_dev_type);
+		chan_err(d40c, "Invalid RX channel address (%d)\n",
+			conf->src_dev_type);
 		res = -EINVAL;
 	}
 
 	if (conf->dir == STEDMA40_MEM_TO_PERIPH &&
 	    dst_event_group == STEDMA40_DEV_DST_MEMORY) {
-		dev_err(&d40c->chan.dev->device, "[%s] Invalid dst\n",
-			__func__);
+		chan_err(d40c, "Invalid dst\n");
 		res = -EINVAL;
 	}
 
 	if (conf->dir == STEDMA40_PERIPH_TO_MEM &&
 	    src_event_group == STEDMA40_DEV_SRC_MEMORY) {
-		dev_err(&d40c->chan.dev->device, "[%s] Invalid src\n",
-			__func__);
+		chan_err(d40c, "Invalid src\n");
 		res = -EINVAL;
 	}
 
 	if (src_event_group == STEDMA40_DEV_SRC_MEMORY &&
 	    dst_event_group == STEDMA40_DEV_DST_MEMORY && is_log) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] No event line\n", __func__);
+		chan_err(d40c, "No event line\n");
 		res = -EINVAL;
 	}
 
 	if (conf->dir == STEDMA40_PERIPH_TO_PERIPH &&
 	    (src_event_group != dst_event_group)) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Invalid event group\n", __func__);
+		chan_err(d40c, "Invalid event group\n");
 		res = -EINVAL;
 	}
 
@@ -1294,9 +1344,7 @@ static int d40_validate_conf(struct d40_chan *d40c,
 		 * DMAC HW supports it. Will be added to this driver,
 		 * in case any dma client requires it.
 		 */
-		dev_err(&d40c->chan.dev->device,
-			"[%s] periph to periph not supported\n",
-			__func__);
+		chan_err(d40c, "periph to periph not supported\n");
 		res = -EINVAL;
 	}
 
@@ -1309,9 +1357,7 @@ static int d40_validate_conf(struct d40_chan *d40c,
 		 * src (burst x width) == dst (burst x width)
 		 */
 
-		dev_err(&d40c->chan.dev->device,
-			"[%s] src (burst x width) != dst (burst x width)\n",
-			__func__);
+		chan_err(d40c, "src (burst x width) != dst (burst x width)\n");
 		res = -EINVAL;
 	}
 
@@ -1514,8 +1560,7 @@ static int d40_config_memcpy(struct d40_chan *d40c)
 		   dma_has_cap(DMA_SLAVE, cap)) {
 		d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_phy;
 	} else {
-		dev_err(&d40c->chan.dev->device, "[%s] No memcpy\n",
-			__func__);
+		chan_err(d40c, "No memcpy\n");
 		return -EINVAL;
 	}
 
@@ -1540,21 +1585,19 @@ static int d40_free_dma(struct d40_chan *d40c)
 	/* Release client owned descriptors */
 	if (!list_empty(&d40c->client))
 		list_for_each_entry_safe(d, _d, &d40c->client, node) {
-			d40_pool_lli_free(d);
+			d40_pool_lli_free(d40c, d);
 			d40_desc_remove(d);
 			d40_desc_free(d40c, d);
 		}
 
 	if (phy == NULL) {
-		dev_err(&d40c->chan.dev->device, "[%s] phy == null\n",
-			__func__);
+		chan_err(d40c, "phy == null\n");
 		return -EINVAL;
 	}
 
 	if (phy->allocated_src == D40_ALLOC_FREE &&
 	    phy->allocated_dst == D40_ALLOC_FREE) {
-		dev_err(&d40c->chan.dev->device, "[%s] channel already free\n",
-			__func__);
+		chan_err(d40c, "channel already free\n");
 		return -EINVAL;
 	}
 
@@ -1566,19 +1609,17 @@ static int d40_free_dma(struct d40_chan *d40c)
 		event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
 		is_src = true;
 	} else {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unknown direction\n", __func__);
+		chan_err(d40c, "Unknown direction\n");
 		return -EINVAL;
 	}
 
 	res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
 	if (res) {
-		dev_err(&d40c->chan.dev->device, "[%s] suspend failed\n",
-			__func__);
+		chan_err(d40c, "suspend failed\n");
 		return res;
 	}
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	if (chan_is_logical(d40c)) {
 		/* Release logical channel, deactivate the event line */
 
 		d40_config_set_event(d40c, false);
@@ -1594,9 +1635,8 @@ static int d40_free_dma(struct d40_chan *d40c)
 				res = d40_channel_execute_command(d40c,
 								  D40_DMA_RUN);
 				if (res) {
-					dev_err(&d40c->chan.dev->device,
-						"[%s] Executing RUN command\n",
-						__func__);
+					chan_err(d40c,
+						"Executing RUN command\n");
 					return res;
 				}
 			}
@@ -1609,8 +1649,7 @@ static int d40_free_dma(struct d40_chan *d40c)
 	/* Release physical channel */
 	res = d40_channel_execute_command(d40c, D40_DMA_STOP);
 	if (res) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to stop channel\n", __func__);
+		chan_err(d40c, "Failed to stop channel\n");
 		return res;
 	}
 	d40c->phy_chan = NULL;
@@ -1622,6 +1661,7 @@ static int d40_free_dma(struct d40_chan *d40c)
 
 static bool d40_is_paused(struct d40_chan *d40c)
 {
+	void __iomem *chanbase = chan_base(d40c);
 	bool is_paused = false;
 	unsigned long flags;
 	void __iomem *active_reg;
@@ -1630,7 +1670,7 @@ static bool d40_is_paused(struct d40_chan *d40c)
 
 	spin_lock_irqsave(&d40c->lock, flags);
 
-	if (d40c->log_num == D40_PHY_CHAN) {
+	if (chan_is_physical(d40c)) {
 		if (d40c->phy_chan->num % 2 == 0)
 			active_reg = d40c->base->virtbase + D40_DREG_ACTIVE;
 		else
@@ -1648,17 +1688,12 @@ static bool d40_is_paused(struct d40_chan *d40c)
 	if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH ||
 	    d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
 		event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
-		status = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-			       d40c->phy_chan->num * D40_DREG_PCDELTA +
-			       D40_CHAN_REG_SDLNK);
+		status = readl(chanbase + D40_CHAN_REG_SDLNK);
 	} else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
 		event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
-		status = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-			       d40c->phy_chan->num * D40_DREG_PCDELTA +
-			       D40_CHAN_REG_SSLNK);
+		status = readl(chanbase + D40_CHAN_REG_SSLNK);
 	} else {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unknown direction\n", __func__);
+		chan_err(d40c, "Unknown direction\n");
 		goto _exit;
 	}
 
@@ -1688,114 +1723,184 @@ static u32 stedma40_residue(struct dma_chan *chan)
 	return bytes_left;
 }
 
-struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan,
-						   struct scatterlist *sgl_dst,
-						   struct scatterlist *sgl_src,
-						   unsigned int sgl_len,
-						   unsigned long dma_flags)
+static int
+d40_prep_sg_log(struct d40_chan *chan, struct d40_desc *desc,
+		struct scatterlist *sg_src, struct scatterlist *sg_dst,
+		unsigned int sg_len, dma_addr_t src_dev_addr,
+		dma_addr_t dst_dev_addr)
 {
-	int res;
-	struct d40_desc *d40d;
-	struct d40_chan *d40c = container_of(chan, struct d40_chan,
-					     chan);
-	unsigned long flags;
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	struct stedma40_half_channel_info *src_info = &cfg->src_info;
+	struct stedma40_half_channel_info *dst_info = &cfg->dst_info;
+	int ret;
 
-	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unallocated channel.\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
+	ret = d40_log_sg_to_lli(sg_src, sg_len,
+				src_dev_addr,
+				desc->lli_log.src,
+				chan->log_def.lcsp1,
+				src_info->data_width,
+				dst_info->data_width);
 
-	spin_lock_irqsave(&d40c->lock, flags);
-	d40d = d40_desc_get(d40c);
+	ret = d40_log_sg_to_lli(sg_dst, sg_len,
+				dst_dev_addr,
+				desc->lli_log.dst,
+				chan->log_def.lcsp3,
+				dst_info->data_width,
+				src_info->data_width);
 
-	if (d40d == NULL)
+	return ret < 0 ? ret : 0;
+}
+
+static int
+d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc,
+		struct scatterlist *sg_src, struct scatterlist *sg_dst,
+		unsigned int sg_len, dma_addr_t src_dev_addr,
+		dma_addr_t dst_dev_addr)
+{
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	struct stedma40_half_channel_info *src_info = &cfg->src_info;
+	struct stedma40_half_channel_info *dst_info = &cfg->dst_info;
+	unsigned long flags = 0;
+	int ret;
+
+	if (desc->cyclic)
+		flags |= LLI_CYCLIC | LLI_TERM_INT;
+
+	ret = d40_phy_sg_to_lli(sg_src, sg_len, src_dev_addr,
+				desc->lli_phy.src,
+				virt_to_phys(desc->lli_phy.src),
+				chan->src_def_cfg,
+				src_info, dst_info, flags);
+
+	ret = d40_phy_sg_to_lli(sg_dst, sg_len, dst_dev_addr,
+				desc->lli_phy.dst,
+				virt_to_phys(desc->lli_phy.dst),
+				chan->dst_def_cfg,
+				dst_info, src_info, flags);
+
+	dma_sync_single_for_device(chan->base->dev, desc->lli_pool.dma_addr,
+				   desc->lli_pool.size, DMA_TO_DEVICE);
+
+	return ret < 0 ? ret : 0;
+}
+
+
+static struct d40_desc *
+d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
+	      unsigned int sg_len, unsigned long dma_flags)
+{
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	struct d40_desc *desc;
+	int ret;
+
+	desc = d40_desc_get(chan);
+	if (!desc)
+		return NULL;
+
+	desc->lli_len = d40_sg_2_dmalen(sg, sg_len, cfg->src_info.data_width,
+					cfg->dst_info.data_width);
+	if (desc->lli_len < 0) {
+		chan_err(chan, "Unaligned size\n");
 		goto err;
+	}
 
-	d40d->lli_len = d40_sg_2_dmalen(sgl_dst, sgl_len,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
+	ret = d40_pool_lli_alloc(chan, desc, desc->lli_len);
+	if (ret < 0) {
+		chan_err(chan, "Could not allocate lli\n");
 		goto err;
 	}
 
-	d40d->lli_current = 0;
-	d40d->txd.flags = dma_flags;
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	desc->lli_current = 0;
+	desc->txd.flags = dma_flags;
+	desc->txd.tx_submit = d40_tx_submit;
 
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
+	dma_async_tx_descriptor_init(&desc->txd, &chan->chan);
 
-		(void) d40_log_sg_to_lli(sgl_src,
-					 sgl_len,
-					 d40d->lli_log.src,
-					 d40c->log_def.lcsp1,
-					 d40c->dma_cfg.src_info.data_width,
-					 d40c->dma_cfg.dst_info.data_width);
-
-		(void) d40_log_sg_to_lli(sgl_dst,
-					 sgl_len,
-					 d40d->lli_log.dst,
-					 d40c->log_def.lcsp3,
-					 d40c->dma_cfg.dst_info.data_width,
-					 d40c->dma_cfg.src_info.data_width);
-	} else {
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
+	return desc;
+
+err:
+	d40_desc_free(chan, desc);
+	return NULL;
+}
+
+static dma_addr_t
+d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
+{
+	struct stedma40_platform_data *plat = chan->base->plat_data;
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	dma_addr_t addr;
 
-		res = d40_phy_sg_to_lli(sgl_src,
-					sgl_len,
-					0,
-					d40d->lli_phy.src,
-					virt_to_phys(d40d->lli_phy.src),
-					d40c->src_def_cfg,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width,
-					d40c->dma_cfg.src_info.psize);
+	if (chan->runtime_addr)
+		return chan->runtime_addr;
 
-		if (res < 0)
-			goto err;
+	if (direction == DMA_FROM_DEVICE)
+		addr = plat->dev_rx[cfg->src_dev_type];
+	else if (direction == DMA_TO_DEVICE)
+		addr = plat->dev_tx[cfg->dst_dev_type];
 
-		res = d40_phy_sg_to_lli(sgl_dst,
-					sgl_len,
-					0,
-					d40d->lli_phy.dst,
-					virt_to_phys(d40d->lli_phy.dst),
-					d40c->dst_def_cfg,
-					d40c->dma_cfg.dst_info.data_width,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.psize);
+	return addr;
+}
 
-		if (res < 0)
-			goto err;
+static struct dma_async_tx_descriptor *
+d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
+	    struct scatterlist *sg_dst, unsigned int sg_len,
+	    enum dma_data_direction direction, unsigned long dma_flags)
+{
+	struct d40_chan *chan = container_of(dchan, struct d40_chan, chan);
+	dma_addr_t src_dev_addr = 0;
+	dma_addr_t dst_dev_addr = 0;
+	struct d40_desc *desc;
+	unsigned long flags;
+	int ret;
 
-		(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
-				      d40d->lli_pool.size, DMA_TO_DEVICE);
+	if (!chan->phy_chan) {
+		chan_err(chan, "Cannot prepare unallocated channel\n");
+		return NULL;
 	}
 
-	dma_async_tx_descriptor_init(&d40d->txd, chan);
 
-	d40d->txd.tx_submit = d40_tx_submit;
+	spin_lock_irqsave(&chan->lock, flags);
 
-	spin_unlock_irqrestore(&d40c->lock, flags);
+	desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
+	if (desc == NULL)
+		goto err;
+
+	if (sg_next(&sg_src[sg_len - 1]) == sg_src)
+		desc->cyclic = true;
+
+	if (direction != DMA_NONE) {
+		dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
+
+		if (direction == DMA_FROM_DEVICE)
+			src_dev_addr = dev_addr;
+		else if (direction == DMA_TO_DEVICE)
+			dst_dev_addr = dev_addr;
+	}
+
+	if (chan_is_logical(chan))
+		ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst,
+				      sg_len, src_dev_addr, dst_dev_addr);
+	else
+		ret = d40_prep_sg_phy(chan, desc, sg_src, sg_dst,
+				      sg_len, src_dev_addr, dst_dev_addr);
+
+	if (ret) {
+		chan_err(chan, "Failed to prepare %s sg job: %d\n",
+			 chan_is_logical(chan) ? "log" : "phy", ret);
+		goto err;
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return &desc->txd;
 
-	return &d40d->txd;
 err:
-	if (d40d)
-		d40_desc_free(d40c, d40d);
-	spin_unlock_irqrestore(&d40c->lock, flags);
+	if (desc)
+		d40_desc_free(chan, desc);
+	spin_unlock_irqrestore(&chan->lock, flags);
 	return NULL;
 }
-EXPORT_SYMBOL(stedma40_memcpy_sg);
 
 bool stedma40_filter(struct dma_chan *chan, void *data)
 {
@@ -1818,6 +1923,38 @@ bool stedma40_filter(struct dma_chan *chan, void *data)
 }
 EXPORT_SYMBOL(stedma40_filter);
 
+static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
+{
+	bool realtime = d40c->dma_cfg.realtime;
+	bool highprio = d40c->dma_cfg.high_priority;
+	u32 prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
+	u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1;
+	u32 event = D40_TYPE_TO_EVENT(dev_type);
+	u32 group = D40_TYPE_TO_GROUP(dev_type);
+	u32 bit = 1 << event;
+
+	/* Destination event lines are stored in the upper halfword */
+	if (!src)
+		bit <<= 16;
+
+	writel(bit, d40c->base->virtbase + prioreg + group * 4);
+	writel(bit, d40c->base->virtbase + rtreg + group * 4);
+}
+
+static void d40_set_prio_realtime(struct d40_chan *d40c)
+{
+	if (d40c->base->rev < 3)
+		return;
+
+	if ((d40c->dma_cfg.dir ==  STEDMA40_PERIPH_TO_MEM) ||
+	    (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
+		__d40_set_prio_rt(d40c, d40c->dma_cfg.src_dev_type, true);
+
+	if ((d40c->dma_cfg.dir ==  STEDMA40_MEM_TO_PERIPH) ||
+	    (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
+		__d40_set_prio_rt(d40c, d40c->dma_cfg.dst_dev_type, false);
+}
+
 /* DMA ENGINE functions */
 static int d40_alloc_chan_resources(struct dma_chan *chan)
 {
@@ -1834,9 +1971,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
 	if (!d40c->configured) {
 		err = d40_config_memcpy(d40c);
 		if (err) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Failed to configure memcpy channel\n",
-				__func__);
+			chan_err(d40c, "Failed to configure memcpy channel\n");
 			goto fail;
 		}
 	}
@@ -1844,16 +1979,17 @@ static int d40_alloc_chan_resources(struct dma_chan *chan)
 
 	err = d40_allocate_channel(d40c);
 	if (err) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to allocate channel\n", __func__);
+		chan_err(d40c, "Failed to allocate channel\n");
 		goto fail;
 	}
 
 	/* Fill in basic CFG register values */
 	d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg,
-		    &d40c->dst_def_cfg, d40c->log_num != D40_PHY_CHAN);
+		    &d40c->dst_def_cfg, chan_is_logical(d40c));
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	d40_set_prio_realtime(d40c);
+
+	if (chan_is_logical(d40c)) {
 		d40_log_cfg(&d40c->dma_cfg,
 			    &d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
 
@@ -1886,8 +2022,7 @@ static void d40_free_chan_resources(struct dma_chan *chan)
 	unsigned long flags;
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Cannot free unallocated channel\n", __func__);
+		chan_err(d40c, "Cannot free unallocated channel\n");
 		return;
 	}
 
@@ -1897,8 +2032,7 @@ static void d40_free_chan_resources(struct dma_chan *chan)
 	err = d40_free_dma(d40c);
 
 	if (err)
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to free channel\n", __func__);
+		chan_err(d40c, "Failed to free channel\n");
 	spin_unlock_irqrestore(&d40c->lock, flags);
 }
 
@@ -1908,251 +2042,31 @@ static struct dma_async_tx_descriptor *d40_prep_memcpy(struct dma_chan *chan,
 						       size_t size,
 						       unsigned long dma_flags)
 {
-	struct d40_desc *d40d;
-	struct d40_chan *d40c = container_of(chan, struct d40_chan,
-					     chan);
-	unsigned long flags;
-
-	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Channel is not allocated.\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	spin_lock_irqsave(&d40c->lock, flags);
-	d40d = d40_desc_get(d40c);
-
-	if (d40d == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Descriptor is NULL\n", __func__);
-		goto err;
-	}
+	struct scatterlist dst_sg;
+	struct scatterlist src_sg;
 
-	d40d->txd.flags = dma_flags;
-	d40d->lli_len = d40_size_2_dmalen(size,
-					  d40c->dma_cfg.src_info.data_width,
-					  d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
-		goto err;
-	}
+	sg_init_table(&dst_sg, 1);
+	sg_init_table(&src_sg, 1);
 
+	sg_dma_address(&dst_sg) = dst;
+	sg_dma_address(&src_sg) = src;
 
-	dma_async_tx_descriptor_init(&d40d->txd, chan);
+	sg_dma_len(&dst_sg) = size;
+	sg_dma_len(&src_sg) = size;
 
-	d40d->txd.tx_submit = d40_tx_submit;
-
-	if (d40c->log_num != D40_PHY_CHAN) {
-
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
-		d40d->lli_current = 0;
-
-		if (d40_log_buf_to_lli(d40d->lli_log.src,
-				       src,
-				       size,
-				       d40c->log_def.lcsp1,
-				       d40c->dma_cfg.src_info.data_width,
-				       d40c->dma_cfg.dst_info.data_width,
-				       true) == NULL)
-			goto err;
-
-		if (d40_log_buf_to_lli(d40d->lli_log.dst,
-				       dst,
-				       size,
-				       d40c->log_def.lcsp3,
-				       d40c->dma_cfg.dst_info.data_width,
-				       d40c->dma_cfg.src_info.data_width,
-				       true) == NULL)
-			goto err;
-
-	} else {
-
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
-
-		if (d40_phy_buf_to_lli(d40d->lli_phy.src,
-				       src,
-				       size,
-				       d40c->dma_cfg.src_info.psize,
-				       0,
-				       d40c->src_def_cfg,
-				       true,
-				       d40c->dma_cfg.src_info.data_width,
-				       d40c->dma_cfg.dst_info.data_width,
-				       false) == NULL)
-			goto err;
-
-		if (d40_phy_buf_to_lli(d40d->lli_phy.dst,
-				       dst,
-				       size,
-				       d40c->dma_cfg.dst_info.psize,
-				       0,
-				       d40c->dst_def_cfg,
-				       true,
-				       d40c->dma_cfg.dst_info.data_width,
-				       d40c->dma_cfg.src_info.data_width,
-				       false) == NULL)
-			goto err;
-
-		(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
-				      d40d->lli_pool.size, DMA_TO_DEVICE);
-	}
-
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return &d40d->txd;
-
-err:
-	if (d40d)
-		d40_desc_free(d40c, d40d);
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return NULL;
+	return d40_prep_sg(chan, &src_sg, &dst_sg, 1, DMA_NONE, dma_flags);
 }
 
 static struct dma_async_tx_descriptor *
-d40_prep_sg(struct dma_chan *chan,
-	    struct scatterlist *dst_sg, unsigned int dst_nents,
-	    struct scatterlist *src_sg, unsigned int src_nents,
-	    unsigned long dma_flags)
+d40_prep_memcpy_sg(struct dma_chan *chan,
+		   struct scatterlist *dst_sg, unsigned int dst_nents,
+		   struct scatterlist *src_sg, unsigned int src_nents,
+		   unsigned long dma_flags)
 {
 	if (dst_nents != src_nents)
 		return NULL;
 
-	return stedma40_memcpy_sg(chan, dst_sg, src_sg, dst_nents, dma_flags);
-}
-
-static int d40_prep_slave_sg_log(struct d40_desc *d40d,
-				 struct d40_chan *d40c,
-				 struct scatterlist *sgl,
-				 unsigned int sg_len,
-				 enum dma_data_direction direction,
-				 unsigned long dma_flags)
-{
-	dma_addr_t dev_addr = 0;
-	int total_size;
-
-	d40d->lli_len = d40_sg_2_dmalen(sgl, sg_len,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
-		return -EINVAL;
-	}
-
-	if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Out of memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	d40d->lli_current = 0;
-
-	if (direction == DMA_FROM_DEVICE)
-		if (d40c->runtime_addr)
-			dev_addr = d40c->runtime_addr;
-		else
-			dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type];
-	else if (direction == DMA_TO_DEVICE)
-		if (d40c->runtime_addr)
-			dev_addr = d40c->runtime_addr;
-		else
-			dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type];
-
-	else
-		return -EINVAL;
-
-	total_size = d40_log_sg_to_dev(sgl, sg_len,
-				       &d40d->lli_log,
-				       &d40c->log_def,
-				       d40c->dma_cfg.src_info.data_width,
-				       d40c->dma_cfg.dst_info.data_width,
-				       direction,
-				       dev_addr);
-
-	if (total_size < 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int d40_prep_slave_sg_phy(struct d40_desc *d40d,
-				 struct d40_chan *d40c,
-				 struct scatterlist *sgl,
-				 unsigned int sgl_len,
-				 enum dma_data_direction direction,
-				 unsigned long dma_flags)
-{
-	dma_addr_t src_dev_addr;
-	dma_addr_t dst_dev_addr;
-	int res;
-
-	d40d->lli_len = d40_sg_2_dmalen(sgl, sgl_len,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
-		return -EINVAL;
-	}
-
-	if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Out of memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	d40d->lli_current = 0;
-
-	if (direction == DMA_FROM_DEVICE) {
-		dst_dev_addr = 0;
-		if (d40c->runtime_addr)
-			src_dev_addr = d40c->runtime_addr;
-		else
-			src_dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type];
-	} else if (direction == DMA_TO_DEVICE) {
-		if (d40c->runtime_addr)
-			dst_dev_addr = d40c->runtime_addr;
-		else
-			dst_dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type];
-		src_dev_addr = 0;
-	} else
-		return -EINVAL;
-
-	res = d40_phy_sg_to_lli(sgl,
-				sgl_len,
-				src_dev_addr,
-				d40d->lli_phy.src,
-				virt_to_phys(d40d->lli_phy.src),
-				d40c->src_def_cfg,
-				d40c->dma_cfg.src_info.data_width,
-				d40c->dma_cfg.dst_info.data_width,
-				d40c->dma_cfg.src_info.psize);
-	if (res < 0)
-		return res;
-
-	res = d40_phy_sg_to_lli(sgl,
-				sgl_len,
-				dst_dev_addr,
-				d40d->lli_phy.dst,
-				virt_to_phys(d40d->lli_phy.dst),
-				d40c->dst_def_cfg,
-				d40c->dma_cfg.dst_info.data_width,
-				d40c->dma_cfg.src_info.data_width,
-				d40c->dma_cfg.dst_info.psize);
-	if (res < 0)
-		return res;
-
-	(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
-			      d40d->lli_pool.size, DMA_TO_DEVICE);
-	return 0;
+	return d40_prep_sg(chan, src_sg, dst_sg, src_nents, DMA_NONE, dma_flags);
 }
 
 static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
@@ -2161,52 +2075,40 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
 							 enum dma_data_direction direction,
 							 unsigned long dma_flags)
 {
-	struct d40_desc *d40d;
-	struct d40_chan *d40c = container_of(chan, struct d40_chan,
-					     chan);
-	unsigned long flags;
-	int err;
-
-	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Cannot prepare unallocated channel\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
+	if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE)
+		return NULL;
 
-	spin_lock_irqsave(&d40c->lock, flags);
-	d40d = d40_desc_get(d40c);
+	return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags);
+}
 
-	if (d40d == NULL)
-		goto err;
+static struct dma_async_tx_descriptor *
+dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
+		     size_t buf_len, size_t period_len,
+		     enum dma_data_direction direction)
+{
+	unsigned int periods = buf_len / period_len;
+	struct dma_async_tx_descriptor *txd;
+	struct scatterlist *sg;
+	int i;
 
-	if (d40c->log_num != D40_PHY_CHAN)
-		err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len,
-					    direction, dma_flags);
-	else
-		err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len,
-					    direction, dma_flags);
-	if (err) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to prepare %s slave sg job: %d\n",
-			__func__,
-			d40c->log_num != D40_PHY_CHAN ? "log" : "phy", err);
-		goto err;
+	sg = kcalloc(periods + 1, sizeof(struct scatterlist), GFP_KERNEL);
+	for (i = 0; i < periods; i++) {
+		sg_dma_address(&sg[i]) = dma_addr;
+		sg_dma_len(&sg[i]) = period_len;
+		dma_addr += period_len;
 	}
 
-	d40d->txd.flags = dma_flags;
+	sg[periods].offset = 0;
+	sg[periods].length = 0;
+	sg[periods].page_link =
+		((unsigned long)sg | 0x01) & ~0x02;
 
-	dma_async_tx_descriptor_init(&d40d->txd, chan);
+	txd = d40_prep_sg(chan, sg, sg, periods, direction,
+			  DMA_PREP_INTERRUPT);
 
-	d40d->txd.tx_submit = d40_tx_submit;
+	kfree(sg);
 
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return &d40d->txd;
-
-err:
-	if (d40d)
-		d40_desc_free(d40c, d40d);
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return NULL;
+	return txd;
 }
 
 static enum dma_status d40_tx_status(struct dma_chan *chan,
@@ -2219,9 +2121,7 @@ static enum dma_status d40_tx_status(struct dma_chan *chan,
 	int ret;
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Cannot read status of unallocated channel\n",
-			__func__);
+		chan_err(d40c, "Cannot read status of unallocated channel\n");
 		return -EINVAL;
 	}
 
@@ -2245,8 +2145,7 @@ static void d40_issue_pending(struct dma_chan *chan)
 	unsigned long flags;
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Channel is not allocated!\n", __func__);
+		chan_err(d40c, "Channel is not allocated!\n");
 		return;
 	}
 
@@ -2339,7 +2238,7 @@ static void d40_set_runtime_config(struct dma_chan *chan,
 		return;
 	}
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	if (chan_is_logical(d40c)) {
 		if (config_maxburst >= 16)
 			psize = STEDMA40_PSIZE_LOG_16;
 		else if (config_maxburst >= 8)
@@ -2372,7 +2271,7 @@ static void d40_set_runtime_config(struct dma_chan *chan,
 	cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL;
 
 	/* Fill in register values */
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
 	else
 		d40_phy_cfg(cfg, &d40c->src_def_cfg,
@@ -2393,25 +2292,20 @@ static void d40_set_runtime_config(struct dma_chan *chan,
 static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 		       unsigned long arg)
 {
-	unsigned long flags;
 	struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Channel is not allocated!\n", __func__);
+		chan_err(d40c, "Channel is not allocated!\n");
 		return -EINVAL;
 	}
 
 	switch (cmd) {
 	case DMA_TERMINATE_ALL:
-		spin_lock_irqsave(&d40c->lock, flags);
-		d40_term_all(d40c);
-		spin_unlock_irqrestore(&d40c->lock, flags);
-		return 0;
+		return d40_terminate_all(d40c);
 	case DMA_PAUSE:
-		return d40_pause(chan);
+		return d40_pause(d40c);
 	case DMA_RESUME:
-		return d40_resume(chan);
+		return d40_resume(d40c);
 	case DMA_SLAVE_CONFIG:
 		d40_set_runtime_config(chan,
 			(struct dma_slave_config *) arg);
@@ -2456,6 +2350,35 @@ static void __init d40_chan_init(struct d40_base *base, struct dma_device *dma,
 	}
 }
 
+static void d40_ops_init(struct d40_base *base, struct dma_device *dev)
+{
+	if (dma_has_cap(DMA_SLAVE, dev->cap_mask))
+		dev->device_prep_slave_sg = d40_prep_slave_sg;
+
+	if (dma_has_cap(DMA_MEMCPY, dev->cap_mask)) {
+		dev->device_prep_dma_memcpy = d40_prep_memcpy;
+
+		/*
+		 * This controller can only access address at even
+		 * 32bit boundaries, i.e. 2^2
+		 */
+		dev->copy_align = 2;
+	}
+
+	if (dma_has_cap(DMA_SG, dev->cap_mask))
+		dev->device_prep_dma_sg = d40_prep_memcpy_sg;
+
+	if (dma_has_cap(DMA_CYCLIC, dev->cap_mask))
+		dev->device_prep_dma_cyclic = dma40_prep_dma_cyclic;
+
+	dev->device_alloc_chan_resources = d40_alloc_chan_resources;
+	dev->device_free_chan_resources = d40_free_chan_resources;
+	dev->device_issue_pending = d40_issue_pending;
+	dev->device_tx_status = d40_tx_status;
+	dev->device_control = d40_control;
+	dev->dev = base->dev;
+}
+
 static int __init d40_dmaengine_init(struct d40_base *base,
 				     int num_reserved_chans)
 {
@@ -2466,23 +2389,14 @@ static int __init d40_dmaengine_init(struct d40_base *base,
 
 	dma_cap_zero(base->dma_slave.cap_mask);
 	dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask);
+	dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask);
 
-	base->dma_slave.device_alloc_chan_resources = d40_alloc_chan_resources;
-	base->dma_slave.device_free_chan_resources = d40_free_chan_resources;
-	base->dma_slave.device_prep_dma_memcpy = d40_prep_memcpy;
-	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
-	base->dma_slave.device_prep_slave_sg = d40_prep_slave_sg;
-	base->dma_slave.device_tx_status = d40_tx_status;
-	base->dma_slave.device_issue_pending = d40_issue_pending;
-	base->dma_slave.device_control = d40_control;
-	base->dma_slave.dev = base->dev;
+	d40_ops_init(base, &base->dma_slave);
 
 	err = dma_async_device_register(&base->dma_slave);
 
 	if (err) {
-		dev_err(base->dev,
-			"[%s] Failed to register slave channels\n",
-			__func__);
+		d40_err(base->dev, "Failed to register slave channels\n");
 		goto failure1;
 	}
 
@@ -2491,29 +2405,15 @@ static int __init d40_dmaengine_init(struct d40_base *base,
 
 	dma_cap_zero(base->dma_memcpy.cap_mask);
 	dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
-	dma_cap_set(DMA_SG, base->dma_slave.cap_mask);
-
-	base->dma_memcpy.device_alloc_chan_resources = d40_alloc_chan_resources;
-	base->dma_memcpy.device_free_chan_resources = d40_free_chan_resources;
-	base->dma_memcpy.device_prep_dma_memcpy = d40_prep_memcpy;
-	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
-	base->dma_memcpy.device_prep_slave_sg = d40_prep_slave_sg;
-	base->dma_memcpy.device_tx_status = d40_tx_status;
-	base->dma_memcpy.device_issue_pending = d40_issue_pending;
-	base->dma_memcpy.device_control = d40_control;
-	base->dma_memcpy.dev = base->dev;
-	/*
-	 * This controller can only access address at even
-	 * 32bit boundaries, i.e. 2^2
-	 */
-	base->dma_memcpy.copy_align = 2;
+	dma_cap_set(DMA_SG, base->dma_memcpy.cap_mask);
+
+	d40_ops_init(base, &base->dma_memcpy);
 
 	err = dma_async_device_register(&base->dma_memcpy);
 
 	if (err) {
-		dev_err(base->dev,
-			"[%s] Failed to regsiter memcpy only channels\n",
-			__func__);
+		d40_err(base->dev,
+			"Failed to regsiter memcpy only channels\n");
 		goto failure2;
 	}
 
@@ -2523,24 +2423,15 @@ static int __init d40_dmaengine_init(struct d40_base *base,
 	dma_cap_zero(base->dma_both.cap_mask);
 	dma_cap_set(DMA_SLAVE, base->dma_both.cap_mask);
 	dma_cap_set(DMA_MEMCPY, base->dma_both.cap_mask);
-	dma_cap_set(DMA_SG, base->dma_slave.cap_mask);
-
-	base->dma_both.device_alloc_chan_resources = d40_alloc_chan_resources;
-	base->dma_both.device_free_chan_resources = d40_free_chan_resources;
-	base->dma_both.device_prep_dma_memcpy = d40_prep_memcpy;
-	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
-	base->dma_both.device_prep_slave_sg = d40_prep_slave_sg;
-	base->dma_both.device_tx_status = d40_tx_status;
-	base->dma_both.device_issue_pending = d40_issue_pending;
-	base->dma_both.device_control = d40_control;
-	base->dma_both.dev = base->dev;
-	base->dma_both.copy_align = 2;
+	dma_cap_set(DMA_SG, base->dma_both.cap_mask);
+	dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask);
+
+	d40_ops_init(base, &base->dma_both);
 	err = dma_async_device_register(&base->dma_both);
 
 	if (err) {
-		dev_err(base->dev,
-			"[%s] Failed to register logical and physical capable channels\n",
-			__func__);
+		d40_err(base->dev,
+			"Failed to register logical and physical capable channels\n");
 		goto failure3;
 	}
 	return 0;
@@ -2616,9 +2507,10 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 		{ .reg = D40_DREG_PERIPHID1, .val = 0x0000},
 		/*
 		 * D40_DREG_PERIPHID2 Depends on HW revision:
-		 *  MOP500/HREF ED has 0x0008,
+		 *  DB8500ed has 0x0008,
 		 *  ? has 0x0018,
-		 *  HREF V1 has 0x0028
+		 *  DB8500v1 has 0x0028
+		 *  DB8500v2 has 0x0038
 		 */
 		{ .reg = D40_DREG_PERIPHID3, .val = 0x0000},
 
@@ -2642,8 +2534,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 	clk = clk_get(&pdev->dev, NULL);
 
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "[%s] No matching clock found\n",
-			__func__);
+		d40_err(&pdev->dev, "No matching clock found\n");
 		goto failure;
 	}
 
@@ -2666,9 +2557,8 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(dma_id_regs); i++) {
 		if (dma_id_regs[i].val !=
 		    readl(virtbase + dma_id_regs[i].reg)) {
-			dev_err(&pdev->dev,
-				"[%s] Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n",
-				__func__,
+			d40_err(&pdev->dev,
+				"Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n",
 				dma_id_regs[i].val,
 				dma_id_regs[i].reg,
 				readl(virtbase + dma_id_regs[i].reg));
@@ -2681,9 +2571,8 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 
 	if ((val & D40_DREG_PERIPHID2_DESIGNER_MASK) !=
 	    D40_HW_DESIGNER) {
-		dev_err(&pdev->dev,
-			"[%s] Unknown designer! Got %x wanted %x\n",
-			__func__, val & D40_DREG_PERIPHID2_DESIGNER_MASK,
+		d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n",
+			val & D40_DREG_PERIPHID2_DESIGNER_MASK,
 			D40_HW_DESIGNER);
 		goto failure;
 	}
@@ -2713,7 +2602,7 @@ static struct d40_base * __init d40_hw_detect_init(struct platform_device *pdev)
 		       sizeof(struct d40_chan), GFP_KERNEL);
 
 	if (base == NULL) {
-		dev_err(&pdev->dev, "[%s] Out of memory\n", __func__);
+		d40_err(&pdev->dev, "Out of memory\n");
 		goto failure;
 	}
 
@@ -2860,6 +2749,7 @@ static void __init d40_hw_init(struct d40_base *base)
 
 static int __init d40_lcla_allocate(struct d40_base *base)
 {
+	struct d40_lcla_pool *pool = &base->lcla_pool;
 	unsigned long *page_list;
 	int i, j;
 	int ret = 0;
@@ -2885,9 +2775,8 @@ static int __init d40_lcla_allocate(struct d40_base *base)
 						base->lcla_pool.pages);
 		if (!page_list[i]) {
 
-			dev_err(base->dev,
-				"[%s] Failed to allocate %d pages.\n",
-				__func__, base->lcla_pool.pages);
+			d40_err(base->dev, "Failed to allocate %d pages.\n",
+				base->lcla_pool.pages);
 
 			for (j = 0; j < i; j++)
 				free_pages(page_list[j], base->lcla_pool.pages);
@@ -2925,6 +2814,15 @@ static int __init d40_lcla_allocate(struct d40_base *base)
 						 LCLA_ALIGNMENT);
 	}
 
+	pool->dma_addr = dma_map_single(base->dev, pool->base,
+					SZ_1K * base->num_phy_chans,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(base->dev, pool->dma_addr)) {
+		pool->dma_addr = 0;
+		ret = -ENOMEM;
+		goto failure;
+	}
+
 	writel(virt_to_phys(base->lcla_pool.base),
 	       base->virtbase + D40_DREG_LCLA);
 failure:
@@ -2957,9 +2855,7 @@ static int __init d40_probe(struct platform_device *pdev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcpa");
 	if (!res) {
 		ret = -ENOENT;
-		dev_err(&pdev->dev,
-			"[%s] No \"lcpa\" memory resource\n",
-			__func__);
+		d40_err(&pdev->dev, "No \"lcpa\" memory resource\n");
 		goto failure;
 	}
 	base->lcpa_size = resource_size(res);
@@ -2968,9 +2864,9 @@ static int __init d40_probe(struct platform_device *pdev)
 	if (request_mem_region(res->start, resource_size(res),
 			       D40_NAME " I/O lcpa") == NULL) {
 		ret = -EBUSY;
-		dev_err(&pdev->dev,
-			"[%s] Failed to request LCPA region 0x%x-0x%x\n",
-			__func__, res->start, res->end);
+		d40_err(&pdev->dev,
+			"Failed to request LCPA region 0x%x-0x%x\n",
+			res->start, res->end);
 		goto failure;
 	}
 
@@ -2986,16 +2882,13 @@ static int __init d40_probe(struct platform_device *pdev)
 	base->lcpa_base = ioremap(res->start, resource_size(res));
 	if (!base->lcpa_base) {
 		ret = -ENOMEM;
-		dev_err(&pdev->dev,
-			"[%s] Failed to ioremap LCPA region\n",
-			__func__);
+		d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
 		goto failure;
 	}
 
 	ret = d40_lcla_allocate(base);
 	if (ret) {
-		dev_err(&pdev->dev, "[%s] Failed to allocate LCLA area\n",
-			__func__);
+		d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
 		goto failure;
 	}
 
@@ -3004,9 +2897,8 @@ static int __init d40_probe(struct platform_device *pdev)
 	base->irq = platform_get_irq(pdev, 0);
 
 	ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base);
-
 	if (ret) {
-		dev_err(&pdev->dev, "[%s] No IRQ defined\n", __func__);
+		d40_err(&pdev->dev, "No IRQ defined\n");
 		goto failure;
 	}
 
@@ -3025,6 +2917,12 @@ failure:
 			kmem_cache_destroy(base->desc_slab);
 		if (base->virtbase)
 			iounmap(base->virtbase);
+
+		if (base->lcla_pool.dma_addr)
+			dma_unmap_single(base->dev, base->lcla_pool.dma_addr,
+					 SZ_1K * base->num_phy_chans,
+					 DMA_TO_DEVICE);
+
 		if (!base->lcla_pool.base_unaligned && base->lcla_pool.base)
 			free_pages((unsigned long)base->lcla_pool.base,
 				   base->lcla_pool.pages);
@@ -3049,7 +2947,7 @@ failure:
 		kfree(base);
 	}
 
-	dev_err(&pdev->dev, "[%s] probe failed\n", __func__);
+	d40_err(&pdev->dev, "probe failed\n");
 	return ret;
 }
 
@@ -3060,7 +2958,7 @@ static struct platform_driver d40_driver = {
 	},
 };
 
-int __init stedma40_init(void)
+static int __init stedma40_init(void)
 {
 	return platform_driver_probe(&d40_driver, d40_probe);
 }
diff --git a/drivers/dma/ste_dma40_ll.c b/drivers/dma/ste_dma40_ll.c
index 0b096a3..cad9e1d 100644
--- a/drivers/dma/ste_dma40_ll.c
+++ b/drivers/dma/ste_dma40_ll.c
@@ -125,13 +125,15 @@ void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
 static int d40_phy_fill_lli(struct d40_phy_lli *lli,
 			    dma_addr_t data,
 			    u32 data_size,
-			    int psize,
 			    dma_addr_t next_lli,
 			    u32 reg_cfg,
-			    bool term_int,
-			    u32 data_width,
-			    bool is_device)
+			    struct stedma40_half_channel_info *info,
+			    unsigned int flags)
 {
+	bool addr_inc = flags & LLI_ADDR_INC;
+	bool term_int = flags & LLI_TERM_INT;
+	unsigned int data_width = info->data_width;
+	int psize = info->psize;
 	int num_elems;
 
 	if (psize == STEDMA40_PSIZE_PHY_1)
@@ -154,7 +156,7 @@ static int d40_phy_fill_lli(struct d40_phy_lli *lli,
 	 * Distance to next element sized entry.
 	 * Usually the size of the element unless you want gaps.
 	 */
-	if (!is_device)
+	if (addr_inc)
 		lli->reg_elt |= (0x1 << data_width) <<
 			D40_SREG_ELEM_PHY_EIDX_POS;
 
@@ -198,47 +200,51 @@ static int d40_seg_size(int size, int data_width1, int data_width2)
 	return seg_max;
 }
 
-struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli,
-				       dma_addr_t addr,
-				       u32 size,
-				       int psize,
-				       dma_addr_t lli_phys,
-				       u32 reg_cfg,
-				       bool term_int,
-				       u32 data_width1,
-				       u32 data_width2,
-				       bool is_device)
+static struct d40_phy_lli *
+d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
+		   dma_addr_t lli_phys, dma_addr_t first_phys, u32 reg_cfg,
+		   struct stedma40_half_channel_info *info,
+		   struct stedma40_half_channel_info *otherinfo,
+		   unsigned long flags)
 {
+	bool lastlink = flags & LLI_LAST_LINK;
+	bool addr_inc = flags & LLI_ADDR_INC;
+	bool term_int = flags & LLI_TERM_INT;
+	bool cyclic = flags & LLI_CYCLIC;
 	int err;
 	dma_addr_t next = lli_phys;
 	int size_rest = size;
 	int size_seg = 0;
 
+	/*
+	 * This piece may be split up based on d40_seg_size(); we only want the
+	 * term int on the last part.
+	 */
+	if (term_int)
+		flags &= ~LLI_TERM_INT;
+
 	do {
-		size_seg = d40_seg_size(size_rest, data_width1, data_width2);
+		size_seg = d40_seg_size(size_rest, info->data_width,
+					otherinfo->data_width);
 		size_rest -= size_seg;
 
-		if (term_int && size_rest == 0)
-			next = 0;
+		if (size_rest == 0 && term_int)
+			flags |= LLI_TERM_INT;
+
+		if (size_rest == 0 && lastlink)
+			next = cyclic ? first_phys : 0;
 		else
 			next = ALIGN(next + sizeof(struct d40_phy_lli),
 				     D40_LLI_ALIGN);
 
-		err = d40_phy_fill_lli(lli,
-				       addr,
-				       size_seg,
-				       psize,
-				       next,
-				       reg_cfg,
-				       !next,
-				       data_width1,
-				       is_device);
+		err = d40_phy_fill_lli(lli, addr, size_seg, next,
+				       reg_cfg, info, flags);
 
 		if (err)
 			goto err;
 
 		lli++;
-		if (!is_device)
+		if (addr_inc)
 			addr += size_seg;
 	} while (size_rest);
 
@@ -254,39 +260,35 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
 		      struct d40_phy_lli *lli_sg,
 		      dma_addr_t lli_phys,
 		      u32 reg_cfg,
-		      u32 data_width1,
-		      u32 data_width2,
-		      int psize)
+		      struct stedma40_half_channel_info *info,
+		      struct stedma40_half_channel_info *otherinfo,
+		      unsigned long flags)
 {
 	int total_size = 0;
 	int i;
 	struct scatterlist *current_sg = sg;
-	dma_addr_t dst;
 	struct d40_phy_lli *lli = lli_sg;
 	dma_addr_t l_phys = lli_phys;
 
+	if (!target)
+		flags |= LLI_ADDR_INC;
+
 	for_each_sg(sg, current_sg, sg_len, i) {
+		dma_addr_t sg_addr = sg_dma_address(current_sg);
+		unsigned int len = sg_dma_len(current_sg);
+		dma_addr_t dst = target ?: sg_addr;
 
 		total_size += sg_dma_len(current_sg);
 
-		if (target)
-			dst = target;
-		else
-			dst = sg_phys(current_sg);
+		if (i == sg_len - 1)
+			flags |= LLI_TERM_INT | LLI_LAST_LINK;
 
 		l_phys = ALIGN(lli_phys + (lli - lli_sg) *
 			       sizeof(struct d40_phy_lli), D40_LLI_ALIGN);
 
-		lli = d40_phy_buf_to_lli(lli,
-					 dst,
-					 sg_dma_len(current_sg),
-					 psize,
-					 l_phys,
-					 reg_cfg,
-					 sg_len - 1 == i,
-					 data_width1,
-					 data_width2,
-					 target == dst);
+		lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, lli_phys,
+					 reg_cfg, info, otherinfo, flags);
+
 		if (lli == NULL)
 			return -EINVAL;
 	}
@@ -295,45 +297,22 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
 }
 
 
-void d40_phy_lli_write(void __iomem *virtbase,
-		       u32 phy_chan_num,
-		       struct d40_phy_lli *lli_dst,
-		       struct d40_phy_lli *lli_src)
-{
-
-	writel(lli_src->reg_cfg, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSCFG);
-	writel(lli_src->reg_elt, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSELT);
-	writel(lli_src->reg_ptr, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSPTR);
-	writel(lli_src->reg_lnk, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSLNK);
-
-	writel(lli_dst->reg_cfg, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDCFG);
-	writel(lli_dst->reg_elt, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDELT);
-	writel(lli_dst->reg_ptr, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDPTR);
-	writel(lli_dst->reg_lnk, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDLNK);
-
-}
-
 /* DMA logical lli operations */
 
 static void d40_log_lli_link(struct d40_log_lli *lli_dst,
 			     struct d40_log_lli *lli_src,
-			     int next)
+			     int next, unsigned int flags)
 {
+	bool interrupt = flags & LLI_TERM_INT;
 	u32 slos = 0;
 	u32 dlos = 0;
 
 	if (next != -EINVAL) {
 		slos = next * 2;
 		dlos = next * 2 + 1;
-	} else {
+	}
+
+	if (interrupt) {
 		lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
 		lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
 	}
@@ -348,9 +327,9 @@ static void d40_log_lli_link(struct d40_log_lli *lli_dst,
 void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
 			   struct d40_log_lli *lli_dst,
 			   struct d40_log_lli *lli_src,
-			   int next)
+			   int next, unsigned int flags)
 {
-	d40_log_lli_link(lli_dst, lli_src, next);
+	d40_log_lli_link(lli_dst, lli_src, next, flags);
 
 	writel(lli_src->lcsp02, &lcpa[0].lcsp0);
 	writel(lli_src->lcsp13, &lcpa[0].lcsp1);
@@ -361,9 +340,9 @@ void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
 void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
 			   struct d40_log_lli *lli_dst,
 			   struct d40_log_lli *lli_src,
-			   int next)
+			   int next, unsigned int flags)
 {
-	d40_log_lli_link(lli_dst, lli_src, next);
+	d40_log_lli_link(lli_dst, lli_src, next, flags);
 
 	writel(lli_src->lcsp02, &lcla[0].lcsp02);
 	writel(lli_src->lcsp13, &lcla[0].lcsp13);
@@ -375,8 +354,10 @@ static void d40_log_fill_lli(struct d40_log_lli *lli,
 			     dma_addr_t data, u32 data_size,
 			     u32 reg_cfg,
 			     u32 data_width,
-			     bool addr_inc)
+			     unsigned int flags)
 {
+	bool addr_inc = flags & LLI_ADDR_INC;
+
 	lli->lcsp13 = reg_cfg;
 
 	/* The number of elements to transfer */
@@ -395,67 +376,15 @@ static void d40_log_fill_lli(struct d40_log_lli *lli,
 
 }
 
-int d40_log_sg_to_dev(struct scatterlist *sg,
-		      int sg_len,
-		      struct d40_log_lli_bidir *lli,
-		      struct d40_def_lcsp *lcsp,
-		      u32 src_data_width,
-		      u32 dst_data_width,
-		      enum dma_data_direction direction,
-		      dma_addr_t dev_addr)
-{
-	int total_size = 0;
-	struct scatterlist *current_sg = sg;
-	int i;
-	struct d40_log_lli *lli_src = lli->src;
-	struct d40_log_lli *lli_dst = lli->dst;
-
-	for_each_sg(sg, current_sg, sg_len, i) {
-		total_size += sg_dma_len(current_sg);
-
-		if (direction == DMA_TO_DEVICE) {
-			lli_src =
-				d40_log_buf_to_lli(lli_src,
-						   sg_phys(current_sg),
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp1, src_data_width,
-						   dst_data_width,
-						   true);
-			lli_dst =
-				d40_log_buf_to_lli(lli_dst,
-						   dev_addr,
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp3, dst_data_width,
-						   src_data_width,
-						   false);
-		} else {
-			lli_dst =
-				d40_log_buf_to_lli(lli_dst,
-						   sg_phys(current_sg),
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp3, dst_data_width,
-						   src_data_width,
-						   true);
-			lli_src =
-				d40_log_buf_to_lli(lli_src,
-						   dev_addr,
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp1, src_data_width,
-						   dst_data_width,
-						   false);
-		}
-	}
-	return total_size;
-}
-
-struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
+static struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
 				       dma_addr_t addr,
 				       int size,
 				       u32 lcsp13, /* src or dst*/
 				       u32 data_width1,
 				       u32 data_width2,
-				       bool addr_inc)
+				       unsigned int flags)
 {
+	bool addr_inc = flags & LLI_ADDR_INC;
 	struct d40_log_lli *lli = lli_sg;
 	int size_rest = size;
 	int size_seg = 0;
@@ -468,7 +397,7 @@ struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
 				 addr,
 				 size_seg,
 				 lcsp13, data_width1,
-				 addr_inc);
+				 flags);
 		if (addr_inc)
 			addr += size_seg;
 		lli++;
@@ -479,6 +408,7 @@ struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
 
 int d40_log_sg_to_lli(struct scatterlist *sg,
 		      int sg_len,
+		      dma_addr_t dev_addr,
 		      struct d40_log_lli *lli_sg,
 		      u32 lcsp13, /* src or dst*/
 		      u32 data_width1, u32 data_width2)
@@ -487,14 +417,24 @@ int d40_log_sg_to_lli(struct scatterlist *sg,
 	struct scatterlist *current_sg = sg;
 	int i;
 	struct d40_log_lli *lli = lli_sg;
+	unsigned long flags = 0;
+
+	if (!dev_addr)
+		flags |= LLI_ADDR_INC;
 
 	for_each_sg(sg, current_sg, sg_len, i) {
+		dma_addr_t sg_addr = sg_dma_address(current_sg);
+		unsigned int len = sg_dma_len(current_sg);
+		dma_addr_t addr = dev_addr ?: sg_addr;
+
 		total_size += sg_dma_len(current_sg);
-		lli = d40_log_buf_to_lli(lli,
-					 sg_phys(current_sg),
-					 sg_dma_len(current_sg),
+
+		lli = d40_log_buf_to_lli(lli, addr, len,
 					 lcsp13,
-					 data_width1, data_width2, true);
+					 data_width1,
+					 data_width2,
+					 flags);
 	}
+
 	return total_size;
 }
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h
index 9cc4349..195ee65 100644
--- a/drivers/dma/ste_dma40_ll.h
+++ b/drivers/dma/ste_dma40_ll.h
@@ -163,6 +163,22 @@
 #define D40_DREG_LCEIS1		0x0B4
 #define D40_DREG_LCEIS2		0x0B8
 #define D40_DREG_LCEIS3		0x0BC
+#define D40_DREG_PSEG1		0x110
+#define D40_DREG_PSEG2		0x114
+#define D40_DREG_PSEG3		0x118
+#define D40_DREG_PSEG4		0x11C
+#define D40_DREG_PCEG1		0x120
+#define D40_DREG_PCEG2		0x124
+#define D40_DREG_PCEG3		0x128
+#define D40_DREG_PCEG4		0x12C
+#define D40_DREG_RSEG1		0x130
+#define D40_DREG_RSEG2		0x134
+#define D40_DREG_RSEG3		0x138
+#define D40_DREG_RSEG4		0x13C
+#define D40_DREG_RCEG1		0x140
+#define D40_DREG_RCEG2		0x144
+#define D40_DREG_RCEG3		0x148
+#define D40_DREG_RCEG4		0x14C
 #define D40_DREG_STFU		0xFC8
 #define D40_DREG_ICFG		0xFCC
 #define D40_DREG_PERIPHID0	0xFE0
@@ -277,6 +293,13 @@ struct d40_def_lcsp {
 
 /* Physical channels */
 
+enum d40_lli_flags {
+	LLI_ADDR_INC	= 1 << 0,
+	LLI_TERM_INT	= 1 << 1,
+	LLI_CYCLIC	= 1 << 2,
+	LLI_LAST_LINK	= 1 << 3,
+};
+
 void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
 		 u32 *src_cfg,
 		 u32 *dst_cfg,
@@ -292,46 +315,15 @@ int d40_phy_sg_to_lli(struct scatterlist *sg,
 		      struct d40_phy_lli *lli,
 		      dma_addr_t lli_phys,
 		      u32 reg_cfg,
-		      u32 data_width1,
-		      u32 data_width2,
-		      int psize);
-
-struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli,
-				       dma_addr_t data,
-				       u32 data_size,
-				       int psize,
-				       dma_addr_t next_lli,
-				       u32 reg_cfg,
-				       bool term_int,
-				       u32 data_width1,
-				       u32 data_width2,
-				       bool is_device);
-
-void d40_phy_lli_write(void __iomem *virtbase,
-		       u32 phy_chan_num,
-		       struct d40_phy_lli *lli_dst,
-		       struct d40_phy_lli *lli_src);
+		      struct stedma40_half_channel_info *info,
+		      struct stedma40_half_channel_info *otherinfo,
+		      unsigned long flags);
 
 /* Logical channels */
 
-struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
-				       dma_addr_t addr,
-				       int size,
-				       u32 lcsp13, /* src or dst*/
-				       u32 data_width1, u32 data_width2,
-				       bool addr_inc);
-
-int d40_log_sg_to_dev(struct scatterlist *sg,
-		      int sg_len,
-		      struct d40_log_lli_bidir *lli,
-		      struct d40_def_lcsp *lcsp,
-		      u32 src_data_width,
-		      u32 dst_data_width,
-		      enum dma_data_direction direction,
-		      dma_addr_t dev_addr);
-
 int d40_log_sg_to_lli(struct scatterlist *sg,
 		      int sg_len,
+		      dma_addr_t dev_addr,
 		      struct d40_log_lli *lli_sg,
 		      u32 lcsp13, /* src or dst*/
 		      u32 data_width1, u32 data_width2);
@@ -339,11 +331,11 @@ int d40_log_sg_to_lli(struct scatterlist *sg,
 void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
 			    struct d40_log_lli *lli_dst,
 			    struct d40_log_lli *lli_src,
-			    int next);
+			    int next, unsigned int flags);
 
 void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
 			    struct d40_log_lli *lli_dst,
 			    struct d40_log_lli *lli_src,
-			    int next);
+			    int next, unsigned int flags);
 
 #endif /* STE_DMA40_LLI_H */
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 3b88a4e..f69f90a 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -629,7 +629,7 @@ static int td_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 		desc_node)
 		list_move(&td_desc->desc_node, &td_chan->free_list);
 
-	/* now tear down the runnning */
+	/* now tear down the running */
 	__td_finish(td_chan);
 	spin_unlock_bh(&td_chan->lock);
 
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index fe70a34..fac1a20 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -7,7 +7,7 @@
 menuconfig EDAC
 	bool "EDAC (Error Detection And Correction) reporting"
 	depends on HAS_IOMEM
-	depends on X86 || PPC
+	depends on X86 || PPC || TILE
 	help
 	  EDAC is designed to report errors in the core system.
 	  These are low-level errors that are reported in the CPU or
@@ -282,4 +282,12 @@ config EDAC_CPC925
 	  a companion chip to the PowerPC 970 family of
 	  processors.
 
+config EDAC_TILE
+	tristate "Tilera Memory Controller"
+	depends on EDAC_MM_EDAC && TILE
+	default y
+	help
+	  Support for error detection and correction on the
+	  Tilera memory controller.
+
 endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index ba2898b..3e23913 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_EDAC_PPC4XX)		+= ppc4xx_edac.o
 obj-$(CONFIG_EDAC_AMD8111)		+= amd8111_edac.o
 obj-$(CONFIG_EDAC_AMD8131)		+= amd8131_edac.o
 
+obj-$(CONFIG_EDAC_TILE)			+= tile_edac.o
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 23e0355..0be30e9 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -25,59 +25,12 @@ static struct mem_ctl_info **mcis;
 static struct ecc_settings **ecc_stngs;
 
 /*
- * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and
- * later.
- */
-static int ddr2_dbam_revCG[] = {
-			   [0]		= 32,
-			   [1]		= 64,
-			   [2]		= 128,
-			   [3]		= 256,
-			   [4]		= 512,
-			   [5]		= 1024,
-			   [6]		= 2048,
-};
-
-static int ddr2_dbam_revD[] = {
-			   [0]		= 32,
-			   [1]		= 64,
-			   [2 ... 3]	= 128,
-			   [4]		= 256,
-			   [5]		= 512,
-			   [6]		= 256,
-			   [7]		= 512,
-			   [8 ... 9]	= 1024,
-			   [10]		= 2048,
-};
-
-static int ddr2_dbam[] = { [0]		= 128,
-			   [1]		= 256,
-			   [2 ... 4]	= 512,
-			   [5 ... 6]	= 1024,
-			   [7 ... 8]	= 2048,
-			   [9 ... 10]	= 4096,
-			   [11]		= 8192,
-};
-
-static int ddr3_dbam[] = { [0]		= -1,
-			   [1]		= 256,
-			   [2]		= 512,
-			   [3 ... 4]	= -1,
-			   [5 ... 6]	= 1024,
-			   [7 ... 8]	= 2048,
-			   [9 ... 10]	= 4096,
-			   [11]		= 8192,
-};
-
-/*
  * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing
  * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching-
  * or higher value'.
  *
  *FIXME: Produce a better mapping/linearisation.
  */
-
-
 struct scrubrate {
        u32 scrubval;           /* bit pattern for scrub rate */
        u32 bandwidth;          /* bandwidth consumed (bytes/sec) */
@@ -107,6 +60,79 @@ struct scrubrate {
 	{ 0x00, 0UL},        /* scrubbing off */
 };
 
+static int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+				      u32 *val, const char *func)
+{
+	int err = 0;
+
+	err = pci_read_config_dword(pdev, offset, val);
+	if (err)
+		amd64_warn("%s: error reading F%dx%03x.\n",
+			   func, PCI_FUNC(pdev->devfn), offset);
+
+	return err;
+}
+
+int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
+				u32 val, const char *func)
+{
+	int err = 0;
+
+	err = pci_write_config_dword(pdev, offset, val);
+	if (err)
+		amd64_warn("%s: error writing to F%dx%03x.\n",
+			   func, PCI_FUNC(pdev->devfn), offset);
+
+	return err;
+}
+
+/*
+ *
+ * Depending on the family, F2 DCT reads need special handling:
+ *
+ * K8: has a single DCT only
+ *
+ * F10h: each DCT has its own set of regs
+ *	DCT0 -> F2x040..
+ *	DCT1 -> F2x140..
+ *
+ * F15h: we select which DCT we access using F1x10C[DctCfgSel]
+ *
+ */
+static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
+			       const char *func)
+{
+	if (addr >= 0x100)
+		return -EINVAL;
+
+	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
+}
+
+static int f10_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
+				 const char *func)
+{
+	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
+}
+
+static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
+				 const char *func)
+{
+	u32 reg = 0;
+	u8 dct  = 0;
+
+	if (addr >= 0x140 && addr <= 0x1a0) {
+		dct   = 1;
+		addr -= 0x100;
+	}
+
+	amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
+	reg &= 0xfffffffe;
+	reg |= dct;
+	amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+
+	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
+}
+
 /*
  * Memory scrubber control interface. For K8, memory scrubbing is handled by
  * hardware and can involve L2 cache, dcache as well as the main memory. With
@@ -156,7 +182,7 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 
 	scrubval = scrubrates[i].scrubval;
 
-	pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F);
+	pci_write_bits32(ctl, SCRCTRL, scrubval, 0x001F);
 
 	if (scrubval)
 		return scrubrates[i].bandwidth;
@@ -167,8 +193,12 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 min_scrubrate = 0x5;
+
+	if (boot_cpu_data.x86 == 0xf)
+		min_scrubrate = 0x0;
 
-	return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate);
+	return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
 }
 
 static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
@@ -177,7 +207,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
 	u32 scrubval = 0;
 	int i, retval = -EINVAL;
 
-	amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval);
+	amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
 
 	scrubval = scrubval & 0x001F;
 
@@ -192,63 +222,14 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
 	return retval;
 }
 
-/* Map from a CSROW entry to the mask entry that operates on it */
-static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow)
-{
-	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F)
-		return csrow;
-	else
-		return csrow >> 1;
-}
-
-/* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */
-static u32 amd64_get_dct_base(struct amd64_pvt *pvt, int dct, int csrow)
-{
-	if (dct == 0)
-		return pvt->dcsb0[csrow];
-	else
-		return pvt->dcsb1[csrow];
-}
-
-/*
- * Return the 'mask' address the i'th CS entry. This function is needed because
- * there number of DCSM registers on Rev E and prior vs Rev F and later is
- * different.
- */
-static u32 amd64_get_dct_mask(struct amd64_pvt *pvt, int dct, int csrow)
-{
-	if (dct == 0)
-		return pvt->dcsm0[amd64_map_to_dcs_mask(pvt, csrow)];
-	else
-		return pvt->dcsm1[amd64_map_to_dcs_mask(pvt, csrow)];
-}
-
-
 /*
- * In *base and *limit, pass back the full 40-bit base and limit physical
- * addresses for the node given by node_id.  This information is obtained from
- * DRAM Base (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers. The
- * base and limit addresses are of type SysAddr, as defined at the start of
- * section 3.4.4 (p. 70).  They are the lowest and highest physical addresses
- * in the address range they represent.
+ * returns true if the SysAddr given by sys_addr matches the
+ * DRAM base/limit associated with node_id
  */
-static void amd64_get_base_and_limit(struct amd64_pvt *pvt, int node_id,
-			       u64 *base, u64 *limit)
+static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr,
+				   unsigned nid)
 {
-	*base = pvt->dram_base[node_id];
-	*limit = pvt->dram_limit[node_id];
-}
-
-/*
- * Return 1 if the SysAddr given by sys_addr matches the base/limit associated
- * with node_id
- */
-static int amd64_base_limit_match(struct amd64_pvt *pvt,
-					u64 sys_addr, int node_id)
-{
-	u64 base, limit, addr;
-
-	amd64_get_base_and_limit(pvt, node_id, &base, &limit);
+	u64 addr;
 
 	/* The K8 treats this as a 40-bit value.  However, bits 63-40 will be
 	 * all ones if the most significant implemented address bit is 1.
@@ -258,7 +239,8 @@ static int amd64_base_limit_match(struct amd64_pvt *pvt,
 	 */
 	addr = sys_addr & 0x000000ffffffffffull;
 
-	return (addr >= base) && (addr <= limit);
+	return ((addr >= get_dram_base(pvt, nid)) &&
+		(addr <= get_dram_limit(pvt, nid)));
 }
 
 /*
@@ -271,7 +253,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
 						u64 sys_addr)
 {
 	struct amd64_pvt *pvt;
-	int node_id;
+	unsigned node_id;
 	u32 intlv_en, bits;
 
 	/*
@@ -285,10 +267,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
 	 * registers.  Therefore we arbitrarily choose to read it from the
 	 * register for node 0.
 	 */
-	intlv_en = pvt->dram_IntlvEn[0];
+	intlv_en = dram_intlv_en(pvt, 0);
 
 	if (intlv_en == 0) {
-		for (node_id = 0; node_id < DRAM_REG_COUNT; node_id++) {
+		for (node_id = 0; node_id < DRAM_RANGES; node_id++) {
 			if (amd64_base_limit_match(pvt, sys_addr, node_id))
 				goto found;
 		}
@@ -305,10 +287,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
 	bits = (((u32) sys_addr) >> 12) & intlv_en;
 
 	for (node_id = 0; ; ) {
-		if ((pvt->dram_IntlvSel[node_id] & intlv_en) == bits)
+		if ((dram_intlv_sel(pvt, node_id) & intlv_en) == bits)
 			break;	/* intlv_sel field matches */
 
-		if (++node_id >= DRAM_REG_COUNT)
+		if (++node_id >= DRAM_RANGES)
 			goto err_no_match;
 	}
 
@@ -321,7 +303,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
 	}
 
 found:
-	return edac_mc_find(node_id);
+	return edac_mc_find((int)node_id);
 
 err_no_match:
 	debugf2("sys_addr 0x%lx doesn't match any node\n",
@@ -331,37 +313,50 @@ err_no_match:
 }
 
 /*
- * Extract the DRAM CS base address from selected csrow register.
+ * compute the CS base address of the @csrow on the DRAM controller @dct.
+ * For details see F2x[5C:40] in the processor's BKDG
  */
-static u64 base_from_dct_base(struct amd64_pvt *pvt, int csrow)
+static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
+				 u64 *base, u64 *mask)
 {
-	return ((u64) (amd64_get_dct_base(pvt, 0, csrow) & pvt->dcsb_base)) <<
-				pvt->dcs_shift;
-}
+	u64 csbase, csmask, base_bits, mask_bits;
+	u8 addr_shift;
 
-/*
- * Extract the mask from the dcsb0[csrow] entry in a CPU revision-specific way.
- */
-static u64 mask_from_dct_mask(struct amd64_pvt *pvt, int csrow)
-{
-	u64 dcsm_bits, other_bits;
-	u64 mask;
-
-	/* Extract bits from DRAM CS Mask. */
-	dcsm_bits = amd64_get_dct_mask(pvt, 0, csrow) & pvt->dcsm_mask;
+	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) {
+		csbase		= pvt->csels[dct].csbases[csrow];
+		csmask		= pvt->csels[dct].csmasks[csrow];
+		base_bits	= GENMASK(21, 31) | GENMASK(9, 15);
+		mask_bits	= GENMASK(21, 29) | GENMASK(9, 15);
+		addr_shift	= 4;
+	} else {
+		csbase		= pvt->csels[dct].csbases[csrow];
+		csmask		= pvt->csels[dct].csmasks[csrow >> 1];
+		addr_shift	= 8;
 
-	other_bits = pvt->dcsm_mask;
-	other_bits = ~(other_bits << pvt->dcs_shift);
+		if (boot_cpu_data.x86 == 0x15)
+			base_bits = mask_bits = GENMASK(19,30) | GENMASK(5,13);
+		else
+			base_bits = mask_bits = GENMASK(19,28) | GENMASK(5,13);
+	}
 
-	/*
-	 * The extracted bits from DCSM belong in the spaces represented by
-	 * the cleared bits in other_bits.
-	 */
-	mask = (dcsm_bits << pvt->dcs_shift) | other_bits;
+	*base  = (csbase & base_bits) << addr_shift;
 
-	return mask;
+	*mask  = ~0ULL;
+	/* poke holes for the csmask */
+	*mask &= ~(mask_bits << addr_shift);
+	/* OR them in */
+	*mask |= (csmask & mask_bits) << addr_shift;
 }
 
+#define for_each_chip_select(i, dct, pvt) \
+	for (i = 0; i < pvt->csels[dct].b_cnt; i++)
+
+#define chip_select_base(i, dct, pvt) \
+	pvt->csels[dct].csbases[i]
+
+#define for_each_chip_select_mask(i, dct, pvt) \
+	for (i = 0; i < pvt->csels[dct].m_cnt; i++)
+
 /*
  * @input_addr is an InputAddr associated with the node given by mci. Return the
  * csrow that input_addr maps to, or -1 on failure (no csrow claims input_addr).
@@ -374,19 +369,13 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr)
 
 	pvt = mci->pvt_info;
 
-	/*
-	 * Here we use the DRAM CS Base and DRAM CS Mask registers. For each CS
-	 * base/mask register pair, test the condition shown near the start of
-	 * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E).
-	 */
-	for (csrow = 0; csrow < pvt->cs_count; csrow++) {
-
-		/* This DRAM chip select is disabled on this node */
-		if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0)
+	for_each_chip_select(csrow, 0, pvt) {
+		if (!csrow_enabled(csrow, 0, pvt))
 			continue;
 
-		base = base_from_dct_base(pvt, csrow);
-		mask = ~mask_from_dct_mask(pvt, csrow);
+		get_cs_base_and_mask(pvt, csrow, 0, &base, &mask);
+
+		mask = ~mask;
 
 		if ((input_addr & mask) == (base & mask)) {
 			debugf2("InputAddr 0x%lx matches csrow %d (node %d)\n",
@@ -396,7 +385,6 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr)
 			return csrow;
 		}
 	}
-
 	debugf2("no matching csrow for InputAddr 0x%lx (MC node %d)\n",
 		(unsigned long)input_addr, pvt->mc_node_id);
 
@@ -404,19 +392,6 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr)
 }
 
 /*
- * Return the base value defined by the DRAM Base register for the node
- * represented by mci.  This function returns the full 40-bit value despite the
- * fact that the register only stores bits 39-24 of the value. See section
- * 3.4.4.1 (BKDG #26094, K8, revA-E)
- */
-static inline u64 get_dram_base(struct mem_ctl_info *mci)
-{
-	struct amd64_pvt *pvt = mci->pvt_info;
-
-	return pvt->dram_base[pvt->mc_node_id];
-}
-
-/*
  * Obtain info from the DRAM Hole Address Register (section 3.4.8, pub #26094)
  * for the node represented by mci. Info is passed back in *hole_base,
  * *hole_offset, and *hole_size.  Function returns 0 if info is valid or 1 if
@@ -445,14 +420,13 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 		return 1;
 	}
 
-	/* only valid for Fam10h */
-	if (boot_cpu_data.x86 == 0x10 &&
-	    (pvt->dhar & F10_DRAM_MEM_HOIST_VALID) == 0) {
+	/* valid for Fam10h and above */
+	if (boot_cpu_data.x86 >= 0x10 && !dhar_mem_hoist_valid(pvt)) {
 		debugf1("  Dram Memory Hoisting is DISABLED on this system\n");
 		return 1;
 	}
 
-	if ((pvt->dhar & DHAR_VALID) == 0) {
+	if (!dhar_valid(pvt)) {
 		debugf1("  Dram Memory Hoisting is DISABLED on this node %d\n",
 			pvt->mc_node_id);
 		return 1;
@@ -476,15 +450,15 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 	 * addresses in the hole so that they start at 0x100000000.
 	 */
 
-	base = dhar_base(pvt->dhar);
+	base = dhar_base(pvt);
 
 	*hole_base = base;
 	*hole_size = (0x1ull << 32) - base;
 
 	if (boot_cpu_data.x86 > 0xf)
-		*hole_offset = f10_dhar_offset(pvt->dhar);
+		*hole_offset = f10_dhar_offset(pvt);
 	else
-		*hole_offset = k8_dhar_offset(pvt->dhar);
+		*hole_offset = k8_dhar_offset(pvt);
 
 	debugf1("  DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n",
 		pvt->mc_node_id, (unsigned long)*hole_base,
@@ -525,10 +499,11 @@ EXPORT_SYMBOL_GPL(amd64_get_dram_hole_info);
  */
 static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
 {
+	struct amd64_pvt *pvt = mci->pvt_info;
 	u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
 	int ret = 0;
 
-	dram_base = get_dram_base(mci);
+	dram_base = get_dram_base(pvt, pvt->mc_node_id);
 
 	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
 				      &hole_size);
@@ -556,7 +531,7 @@ static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
 	 * section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture
 	 * Programmer's Manual Volume 1 Application Programming.
 	 */
-	dram_addr = (sys_addr & 0xffffffffffull) - dram_base;
+	dram_addr = (sys_addr & GENMASK(0, 39)) - dram_base;
 
 	debugf2("using DRAM Base register to translate SysAddr 0x%lx to "
 		"DramAddr 0x%lx\n", (unsigned long)sys_addr,
@@ -592,9 +567,9 @@ static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr)
 	 * See the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E)
 	 * concerning translating a DramAddr to an InputAddr.
 	 */
-	intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]);
-	input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) +
-	    (dram_addr & 0xfff);
+	intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
+	input_addr = ((dram_addr >> intlv_shift) & GENMASK(12, 35)) +
+		      (dram_addr & 0xfff);
 
 	debugf2("  Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n",
 		intlv_shift, (unsigned long)dram_addr,
@@ -628,7 +603,7 @@ static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr)
 static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
 {
 	struct amd64_pvt *pvt;
-	int node_id, intlv_shift;
+	unsigned node_id, intlv_shift;
 	u64 bits, dram_addr;
 	u32 intlv_sel;
 
@@ -642,10 +617,10 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
 	 */
 	pvt = mci->pvt_info;
 	node_id = pvt->mc_node_id;
-	BUG_ON((node_id < 0) || (node_id > 7));
 
-	intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]);
+	BUG_ON(node_id > 7);
 
+	intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
 	if (intlv_shift == 0) {
 		debugf1("    InputAddr 0x%lx translates to DramAddr of "
 			"same value\n",	(unsigned long)input_addr);
@@ -653,10 +628,10 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
 		return input_addr;
 	}
 
-	bits = ((input_addr & 0xffffff000ull) << intlv_shift) +
-	    (input_addr & 0xfff);
+	bits = ((input_addr & GENMASK(12, 35)) << intlv_shift) +
+		(input_addr & 0xfff);
 
-	intlv_sel = pvt->dram_IntlvSel[node_id] & ((1 << intlv_shift) - 1);
+	intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1);
 	dram_addr = bits + (intlv_sel << 12);
 
 	debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx "
@@ -673,7 +648,7 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
 static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 hole_base, hole_offset, hole_size, base, limit, sys_addr;
+	u64 hole_base, hole_offset, hole_size, base, sys_addr;
 	int ret = 0;
 
 	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
@@ -691,7 +666,7 @@ static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr)
 		}
 	}
 
-	amd64_get_base_and_limit(pvt, pvt->mc_node_id, &base, &limit);
+	base     = get_dram_base(pvt, pvt->mc_node_id);
 	sys_addr = dram_addr + base;
 
 	/*
@@ -736,13 +711,12 @@ static void find_csrow_limits(struct mem_ctl_info *mci, int csrow,
 	u64 base, mask;
 
 	pvt = mci->pvt_info;
-	BUG_ON((csrow < 0) || (csrow >= pvt->cs_count));
+	BUG_ON((csrow < 0) || (csrow >= pvt->csels[0].b_cnt));
 
-	base = base_from_dct_base(pvt, csrow);
-	mask = mask_from_dct_mask(pvt, csrow);
+	get_cs_base_and_mask(pvt, csrow, 0, &base, &mask);
 
 	*input_addr_min = base & ~mask;
-	*input_addr_max = base | mask | pvt->dcs_mask_notused;
+	*input_addr_max = base | mask;
 }
 
 /* Map the Error address to a PAGE and PAGE OFFSET. */
@@ -775,18 +749,13 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr)
 
 static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
 
-static u16 extract_syndrome(struct err_regs *err)
-{
-	return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00);
-}
-
 /*
  * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs
  * are ECC capable.
  */
 static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt)
 {
-	int bit;
+	u8 bit;
 	enum dev_type edac_cap = EDAC_FLAG_NONE;
 
 	bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F)
@@ -799,8 +768,7 @@ static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt)
 	return edac_cap;
 }
 
-
-static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt);
+static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8);
 
 static void amd64_dump_dramcfg_low(u32 dclr, int chan)
 {
@@ -813,8 +781,9 @@ static void amd64_dump_dramcfg_low(u32 dclr, int chan)
 	debugf1("  PAR/ERR parity: %s\n",
 		(dclr & BIT(8)) ?  "enabled" : "disabled");
 
-	debugf1("  DCT 128bit mode width: %s\n",
-		(dclr & BIT(11)) ?  "128b" : "64b");
+	if (boot_cpu_data.x86 == 0x10)
+		debugf1("  DCT 128bit mode width: %s\n",
+			(dclr & BIT(11)) ?  "128b" : "64b");
 
 	debugf1("  x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n",
 		(dclr & BIT(12)) ?  "yes" : "no",
@@ -824,16 +793,16 @@ static void amd64_dump_dramcfg_low(u32 dclr, int chan)
 }
 
 /* Display and decode various NB registers for debug purposes. */
-static void amd64_dump_misc_regs(struct amd64_pvt *pvt)
+static void dump_misc_regs(struct amd64_pvt *pvt)
 {
 	debugf1("F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap);
 
 	debugf1("  NB two channel DRAM capable: %s\n",
-		(pvt->nbcap & K8_NBCAP_DCT_DUAL) ? "yes" : "no");
+		(pvt->nbcap & NBCAP_DCT_DUAL) ? "yes" : "no");
 
 	debugf1("  ECC capable: %s, ChipKill ECC capable: %s\n",
-		(pvt->nbcap & K8_NBCAP_SECDED) ? "yes" : "no",
-		(pvt->nbcap & K8_NBCAP_CHIPKILL) ? "yes" : "no");
+		(pvt->nbcap & NBCAP_SECDED) ? "yes" : "no",
+		(pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no");
 
 	amd64_dump_dramcfg_low(pvt->dclr0, 0);
 
@@ -841,130 +810,84 @@ static void amd64_dump_misc_regs(struct amd64_pvt *pvt)
 
 	debugf1("F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, "
 			"offset: 0x%08x\n",
-			pvt->dhar,
-			dhar_base(pvt->dhar),
-			(boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt->dhar)
-						   : f10_dhar_offset(pvt->dhar));
+			pvt->dhar, dhar_base(pvt),
+			(boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt)
+						   : f10_dhar_offset(pvt));
 
-	debugf1("  DramHoleValid: %s\n",
-		(pvt->dhar & DHAR_VALID) ? "yes" : "no");
+	debugf1("  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
 
-	amd64_debug_display_dimm_sizes(0, pvt);
+	amd64_debug_display_dimm_sizes(pvt, 0);
 
 	/* everything below this point is Fam10h and above */
 	if (boot_cpu_data.x86 == 0xf)
 		return;
 
-	amd64_debug_display_dimm_sizes(1, pvt);
+	amd64_debug_display_dimm_sizes(pvt, 1);
 
-	amd64_info("using %s syndromes.\n", ((pvt->syn_type == 8) ? "x8" : "x4"));
+	amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
 
 	/* Only if NOT ganged does dclr1 have valid info */
 	if (!dct_ganging_enabled(pvt))
 		amd64_dump_dramcfg_low(pvt->dclr1, 1);
 }
 
-/* Read in both of DBAM registers */
-static void amd64_read_dbam_reg(struct amd64_pvt *pvt)
-{
-	amd64_read_pci_cfg(pvt->F2, DBAM0, &pvt->dbam0);
-
-	if (boot_cpu_data.x86 >= 0x10)
-		amd64_read_pci_cfg(pvt->F2, DBAM1, &pvt->dbam1);
-}
-
 /*
- * NOTE: CPU Revision Dependent code: Rev E and Rev F
- *
- * Set the DCSB and DCSM mask values depending on the CPU revision value. Also
- * set the shift factor for the DCSB and DCSM values.
- *
- * ->dcs_mask_notused, RevE:
- *
- * To find the max InputAddr for the csrow, start with the base address and set
- * all bits that are "don't care" bits in the test at the start of section
- * 3.5.4 (p. 84).
- *
- * The "don't care" bits are all set bits in the mask and all bits in the gaps
- * between bit ranges [35:25] and [19:13]. The value REV_E_DCS_NOTUSED_BITS
- * represents bits [24:20] and [12:0], which are all bits in the above-mentioned
- * gaps.
- *
- * ->dcs_mask_notused, RevF and later:
- *
- * To find the max InputAddr for the csrow, start with the base address and set
- * all bits that are "don't care" bits in the test at the start of NPT section
- * 4.5.4 (p. 87).
- *
- * The "don't care" bits are all set bits in the mask and all bits in the gaps
- * between bit ranges [36:27] and [21:13].
- *
- * The value REV_F_F1Xh_DCS_NOTUSED_BITS represents bits [26:22] and [12:0],
- * which are all bits in the above-mentioned gaps.
+ * see BKDG, F2x[1,0][5C:40], F2[1,0][6C:60]
  */
-static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt)
+static void prep_chip_selects(struct amd64_pvt *pvt)
 {
-
 	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) {
-		pvt->dcsb_base		= REV_E_DCSB_BASE_BITS;
-		pvt->dcsm_mask		= REV_E_DCSM_MASK_BITS;
-		pvt->dcs_mask_notused	= REV_E_DCS_NOTUSED_BITS;
-		pvt->dcs_shift		= REV_E_DCS_SHIFT;
-		pvt->cs_count		= 8;
-		pvt->num_dcsm		= 8;
+		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
+		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8;
 	} else {
-		pvt->dcsb_base		= REV_F_F1Xh_DCSB_BASE_BITS;
-		pvt->dcsm_mask		= REV_F_F1Xh_DCSM_MASK_BITS;
-		pvt->dcs_mask_notused	= REV_F_F1Xh_DCS_NOTUSED_BITS;
-		pvt->dcs_shift		= REV_F_F1Xh_DCS_SHIFT;
-		pvt->cs_count		= 8;
-		pvt->num_dcsm		= 4;
+		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
+		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4;
 	}
 }
 
 /*
- * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask hw registers
+ * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers
  */
-static void amd64_read_dct_base_mask(struct amd64_pvt *pvt)
+static void read_dct_base_mask(struct amd64_pvt *pvt)
 {
-	int cs, reg;
+	int cs;
 
-	amd64_set_dct_base_and_mask(pvt);
+	prep_chip_selects(pvt);
 
-	for (cs = 0; cs < pvt->cs_count; cs++) {
-		reg = K8_DCSB0 + (cs * 4);
-		if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsb0[cs]))
+	for_each_chip_select(cs, 0, pvt) {
+		int reg0   = DCSB0 + (cs * 4);
+		int reg1   = DCSB1 + (cs * 4);
+		u32 *base0 = &pvt->csels[0].csbases[cs];
+		u32 *base1 = &pvt->csels[1].csbases[cs];
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg0, base0))
 			debugf0("  DCSB0[%d]=0x%08x reg: F2x%x\n",
-				cs, pvt->dcsb0[cs], reg);
-
-		/* If DCT are NOT ganged, then read in DCT1's base */
-		if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
-			reg = F10_DCSB1 + (cs * 4);
-			if (!amd64_read_pci_cfg(pvt->F2, reg,
-						&pvt->dcsb1[cs]))
-				debugf0("  DCSB1[%d]=0x%08x reg: F2x%x\n",
-					cs, pvt->dcsb1[cs], reg);
-		} else {
-			pvt->dcsb1[cs] = 0;
-		}
+				cs, *base0, reg0);
+
+		if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt))
+			continue;
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg1, base1))
+			debugf0("  DCSB1[%d]=0x%08x reg: F2x%x\n",
+				cs, *base1, reg1);
 	}
 
-	for (cs = 0; cs < pvt->num_dcsm; cs++) {
-		reg = K8_DCSM0 + (cs * 4);
-		if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsm0[cs]))
+	for_each_chip_select_mask(cs, 0, pvt) {
+		int reg0   = DCSM0 + (cs * 4);
+		int reg1   = DCSM1 + (cs * 4);
+		u32 *mask0 = &pvt->csels[0].csmasks[cs];
+		u32 *mask1 = &pvt->csels[1].csmasks[cs];
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg0, mask0))
 			debugf0("    DCSM0[%d]=0x%08x reg: F2x%x\n",
-				cs, pvt->dcsm0[cs], reg);
-
-		/* If DCT are NOT ganged, then read in DCT1's mask */
-		if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) {
-			reg = F10_DCSM1 + (cs * 4);
-			if (!amd64_read_pci_cfg(pvt->F2, reg,
-						&pvt->dcsm1[cs]))
-				debugf0("    DCSM1[%d]=0x%08x reg: F2x%x\n",
-					cs, pvt->dcsm1[cs], reg);
-		} else {
-			pvt->dcsm1[cs] = 0;
-		}
+				cs, *mask0, reg0);
+
+		if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt))
+			continue;
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg1, mask1))
+			debugf0("    DCSM1[%d]=0x%08x reg: F2x%x\n",
+				cs, *mask1, reg1);
 	}
 }
 
@@ -972,7 +895,10 @@ static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs)
 {
 	enum mem_type type;
 
-	if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= K8_REV_F) {
+	/* F15h supports only DDR3 */
+	if (boot_cpu_data.x86 >= 0x15)
+		type = (pvt->dclr0 & BIT(16)) ?	MEM_DDR3 : MEM_RDDR3;
+	else if (boot_cpu_data.x86 == 0x10 || pvt->ext_model >= K8_REV_F) {
 		if (pvt->dchr0 & DDR3_MODE)
 			type = (pvt->dclr0 & BIT(16)) ?	MEM_DDR3 : MEM_RDDR3;
 		else
@@ -986,26 +912,14 @@ static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs)
 	return type;
 }
 
-/*
- * Read the DRAM Configuration Low register. It differs between CG, D & E revs
- * and the later RevF memory controllers (DDR vs DDR2)
- *
- * Return:
- *      number of memory channels in operation
- * Pass back:
- *      contents of the DCL0_LOW register
- */
+/* Get the number of DCT channels the memory controller is using. */
 static int k8_early_channel_count(struct amd64_pvt *pvt)
 {
-	int flag, err = 0;
-
-	err = amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0);
-	if (err)
-		return err;
+	int flag;
 
 	if (pvt->ext_model >= K8_REV_F)
 		/* RevF (NPT) and later */
-		flag = pvt->dclr0 & F10_WIDTH_128;
+		flag = pvt->dclr0 & WIDTH_128;
 	else
 		/* RevE and earlier */
 		flag = pvt->dclr0 & REVE_WIDTH_128;
@@ -1016,55 +930,47 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
 	return (flag) ? 2 : 1;
 }
 
-/* extract the ERROR ADDRESS for the K8 CPUs */
-static u64 k8_get_error_address(struct mem_ctl_info *mci,
-				struct err_regs *info)
+/* On F10h and later ErrAddr is MC4_ADDR[47:1] */
+static u64 get_error_address(struct mce *m)
 {
-	return (((u64) (info->nbeah & 0xff)) << 32) +
-			(info->nbeal & ~0x03);
+	u8 start_bit = 1;
+	u8 end_bit   = 47;
+
+	if (boot_cpu_data.x86 == 0xf) {
+		start_bit = 3;
+		end_bit   = 39;
+	}
+
+	return m->addr & GENMASK(start_bit, end_bit);
 }
 
-/*
- * Read the Base and Limit registers for K8 based Memory controllers; extract
- * fields from the 'raw' reg into separate data fields
- *
- * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN
- */
-static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
+static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 {
-	u32 low;
-	u32 off = dram << 3;	/* 8 bytes between DRAM entries */
+	int off = range << 3;
 
-	amd64_read_pci_cfg(pvt->F1, K8_DRAM_BASE_LOW + off, &low);
+	amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off,  &pvt->ranges[range].base.lo);
+	amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo);
 
-	/* Extract parts into separate data entries */
-	pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8;
-	pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7;
-	pvt->dram_rw_en[dram] = (low & 0x3);
+	if (boot_cpu_data.x86 == 0xf)
+		return;
 
-	amd64_read_pci_cfg(pvt->F1, K8_DRAM_LIMIT_LOW + off, &low);
+	if (!dram_rw(pvt, range))
+		return;
 
-	/*
-	 * Extract parts into separate data entries. Limit is the HIGHEST memory
-	 * location of the region, so lower 24 bits need to be all ones
-	 */
-	pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 8) | 0x00FFFFFF;
-	pvt->dram_IntlvSel[dram] = (low >> 8) & 0x7;
-	pvt->dram_DstNode[dram] = (low & 0x7);
+	amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off,  &pvt->ranges[range].base.hi);
+	amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi);
 }
 
-static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
-				    struct err_regs *err_info, u64 sys_addr)
+static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
+				    u16 syndrome)
 {
 	struct mem_ctl_info *src_mci;
+	struct amd64_pvt *pvt = mci->pvt_info;
 	int channel, csrow;
 	u32 page, offset;
-	u16 syndrome;
-
-	syndrome = extract_syndrome(err_info);
 
 	/* CHIPKILL enabled */
-	if (err_info->nbcfg & K8_NBCFG_CHIPKILL) {
+	if (pvt->nbcfg & NBCFG_CHIPKILL) {
 		channel = get_channel_from_ecc_syndrome(mci, syndrome);
 		if (channel < 0) {
 			/*
@@ -1113,18 +1019,41 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
 	}
 }
 
-static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode)
+static int ddr2_cs_size(unsigned i, bool dct_width)
 {
-	int *dbam_map;
+	unsigned shift = 0;
 
-	if (pvt->ext_model >= K8_REV_F)
-		dbam_map = ddr2_dbam;
-	else if (pvt->ext_model >= K8_REV_D)
-		dbam_map = ddr2_dbam_revD;
+	if (i <= 2)
+		shift = i;
+	else if (!(i & 0x1))
+		shift = i >> 1;
 	else
-		dbam_map = ddr2_dbam_revCG;
+		shift = (i + 1) >> 1;
 
-	return dbam_map[cs_mode];
+	return 128 << (shift + !!dct_width);
+}
+
+static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+				  unsigned cs_mode)
+{
+	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
+
+	if (pvt->ext_model >= K8_REV_F) {
+		WARN_ON(cs_mode > 11);
+		return ddr2_cs_size(cs_mode, dclr & WIDTH_128);
+	}
+	else if (pvt->ext_model >= K8_REV_D) {
+		WARN_ON(cs_mode > 10);
+
+		if (cs_mode == 3 || cs_mode == 8)
+			return 32 << (cs_mode - 1);
+		else
+			return 32 << cs_mode;
+	}
+	else {
+		WARN_ON(cs_mode > 6);
+		return 32 << cs_mode;
+	}
 }
 
 /*
@@ -1135,17 +1064,13 @@ static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode)
  * Pass back:
  *	contents of the DCL0_LOW register
  */
-static int f10_early_channel_count(struct amd64_pvt *pvt)
+static int f1x_early_channel_count(struct amd64_pvt *pvt)
 {
-	int dbams[] = { DBAM0, DBAM1 };
 	int i, j, channels = 0;
-	u32 dbam;
 
-	/* If we are in 128 bit mode, then we are using 2 channels */
-	if (pvt->dclr0 & F10_WIDTH_128) {
-		channels = 2;
-		return channels;
-	}
+	/* On F10h, if we are in 128 bit mode, then we are using 2 channels */
+	if (boot_cpu_data.x86 == 0x10 && (pvt->dclr0 & WIDTH_128))
+		return 2;
 
 	/*
 	 * Need to check if in unganged mode: In such, there are 2 channels,
@@ -1162,9 +1087,8 @@ static int f10_early_channel_count(struct amd64_pvt *pvt)
 	 * is more than just one DIMM present in unganged mode. Need to check
 	 * both controllers since DIMMs can be placed in either one.
 	 */
-	for (i = 0; i < ARRAY_SIZE(dbams); i++) {
-		if (amd64_read_pci_cfg(pvt->F2, dbams[i], &dbam))
-			goto err_reg;
+	for (i = 0; i < 2; i++) {
+		u32 dbam = (i ? pvt->dbam1 : pvt->dbam0);
 
 		for (j = 0; j < 4; j++) {
 			if (DBAM_DIMM(j, dbam) > 0) {
@@ -1180,216 +1104,191 @@ static int f10_early_channel_count(struct amd64_pvt *pvt)
 	amd64_info("MCT channel count: %d\n", channels);
 
 	return channels;
-
-err_reg:
-	return -1;
-
 }
 
-static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode)
+static int ddr3_cs_size(unsigned i, bool dct_width)
 {
-	int *dbam_map;
+	unsigned shift = 0;
+	int cs_size = 0;
 
-	if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE)
-		dbam_map = ddr3_dbam;
+	if (i == 0 || i == 3 || i == 4)
+		cs_size = -1;
+	else if (i <= 2)
+		shift = i;
+	else if (i == 12)
+		shift = 7;
+	else if (!(i & 0x1))
+		shift = i >> 1;
 	else
-		dbam_map = ddr2_dbam;
+		shift = (i + 1) >> 1;
+
+	if (cs_size != -1)
+		cs_size = (128 * (1 << !!dct_width)) << shift;
 
-	return dbam_map[cs_mode];
+	return cs_size;
 }
 
-static u64 f10_get_error_address(struct mem_ctl_info *mci,
-			struct err_regs *info)
+static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+				   unsigned cs_mode)
 {
-	return (((u64) (info->nbeah & 0xffff)) << 32) +
-			(info->nbeal & ~0x01);
+	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
+
+	WARN_ON(cs_mode > 11);
+
+	if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE)
+		return ddr3_cs_size(cs_mode, dclr & WIDTH_128);
+	else
+		return ddr2_cs_size(cs_mode, dclr & WIDTH_128);
 }
 
 /*
- * Read the Base and Limit registers for F10 based Memory controllers. Extract
- * fields from the 'raw' reg into separate data fields.
- *
- * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN.
+ * F15h supports only 64bit DCT interfaces
  */
-static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
+static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+				   unsigned cs_mode)
 {
-	u32 high_offset, low_offset, high_base, low_base, high_limit, low_limit;
-
-	low_offset = K8_DRAM_BASE_LOW + (dram << 3);
-	high_offset = F10_DRAM_BASE_HIGH + (dram << 3);
-
-	/* read the 'raw' DRAM BASE Address register */
-	amd64_read_pci_cfg(pvt->F1, low_offset, &low_base);
-	amd64_read_pci_cfg(pvt->F1, high_offset, &high_base);
-
-	/* Extract parts into separate data entries */
-	pvt->dram_rw_en[dram] = (low_base & 0x3);
-
-	if (pvt->dram_rw_en[dram] == 0)
-		return;
-
-	pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7;
-
-	pvt->dram_base[dram] = (((u64)high_base & 0x000000FF) << 40) |
-			       (((u64)low_base  & 0xFFFF0000) << 8);
-
-	low_offset = K8_DRAM_LIMIT_LOW + (dram << 3);
-	high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3);
-
-	/* read the 'raw' LIMIT registers */
-	amd64_read_pci_cfg(pvt->F1, low_offset, &low_limit);
-	amd64_read_pci_cfg(pvt->F1, high_offset, &high_limit);
-
-	pvt->dram_DstNode[dram] = (low_limit & 0x7);
-	pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7;
+	WARN_ON(cs_mode > 12);
 
-	/*
-	 * Extract address values and form a LIMIT address. Limit is the HIGHEST
-	 * memory location of the region, so low 24 bits need to be all ones.
-	 */
-	pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) |
-				(((u64) low_limit & 0xFFFF0000) << 8) |
-				0x00FFFFFF;
+	return ddr3_cs_size(cs_mode, false);
 }
 
-static void f10_read_dram_ctl_register(struct amd64_pvt *pvt)
+static void read_dram_ctl_register(struct amd64_pvt *pvt)
 {
 
-	if (!amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_LOW,
-				&pvt->dram_ctl_select_low)) {
-		debugf0("F2x110 (DCTL Sel. Low): 0x%08x, "
-			"High range addresses at: 0x%x\n",
-			pvt->dram_ctl_select_low,
-			dct_sel_baseaddr(pvt));
+	if (boot_cpu_data.x86 == 0xf)
+		return;
+
+	if (!amd64_read_dct_pci_cfg(pvt, DCT_SEL_LO, &pvt->dct_sel_lo)) {
+		debugf0("F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n",
+			pvt->dct_sel_lo, dct_sel_baseaddr(pvt));
 
-		debugf0("  DCT mode: %s, All DCTs on: %s\n",
-			(dct_ganging_enabled(pvt) ? "ganged" : "unganged"),
-			(dct_dram_enabled(pvt) ? "yes"   : "no"));
+		debugf0("  DCTs operate in %s mode.\n",
+			(dct_ganging_enabled(pvt) ? "ganged" : "unganged"));
 
 		if (!dct_ganging_enabled(pvt))
 			debugf0("  Address range split per DCT: %s\n",
 				(dct_high_range_enabled(pvt) ? "yes" : "no"));
 
-		debugf0("  DCT data interleave for ECC: %s, "
+		debugf0("  data interleave for ECC: %s, "
 			"DRAM cleared since last warm reset: %s\n",
 			(dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"),
 			(dct_memory_cleared(pvt) ? "yes" : "no"));
 
-		debugf0("  DCT channel interleave: %s, "
-			"DCT interleave bits selector: 0x%x\n",
+		debugf0("  channel interleave: %s, "
+			"interleave bits selector: 0x%x\n",
 			(dct_interleave_enabled(pvt) ? "enabled" : "disabled"),
 			dct_sel_interleave_addr(pvt));
 	}
 
-	amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_HIGH,
-			   &pvt->dram_ctl_select_high);
+	amd64_read_dct_pci_cfg(pvt, DCT_SEL_HI, &pvt->dct_sel_hi);
 }
 
 /*
- * determine channel based on the interleaving mode: F10h BKDG, 2.8.9 Memory
+ * Determine channel (DCT) based on the interleaving mode: F10h BKDG, 2.8.9 Memory
  * Interleaving Modes.
  */
-static u32 f10_determine_channel(struct amd64_pvt *pvt, u64 sys_addr,
-				int hi_range_sel, u32 intlv_en)
+static u8 f1x_determine_channel(struct amd64_pvt *pvt, u64 sys_addr,
+				bool hi_range_sel, u8 intlv_en)
 {
-	u32 cs, temp, dct_sel_high = (pvt->dram_ctl_select_low >> 1) & 1;
+	u8 dct_sel_high = (pvt->dct_sel_lo >> 1) & 1;
 
 	if (dct_ganging_enabled(pvt))
-		cs = 0;
-	else if (hi_range_sel)
-		cs = dct_sel_high;
-	else if (dct_interleave_enabled(pvt)) {
-		/*
-		 * see F2x110[DctSelIntLvAddr] - channel interleave mode
-		 */
-		if (dct_sel_interleave_addr(pvt) == 0)
-			cs = sys_addr >> 6 & 1;
-		else if ((dct_sel_interleave_addr(pvt) >> 1) & 1) {
-			temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) % 2;
+		return 0;
 
-			if (dct_sel_interleave_addr(pvt) & 1)
-				cs = (sys_addr >> 9 & 1) ^ temp;
-			else
-				cs = (sys_addr >> 6 & 1) ^ temp;
-		} else if (intlv_en & 4)
-			cs = sys_addr >> 15 & 1;
-		else if (intlv_en & 2)
-			cs = sys_addr >> 14 & 1;
-		else if (intlv_en & 1)
-			cs = sys_addr >> 13 & 1;
-		else
-			cs = sys_addr >> 12 & 1;
-	} else if (dct_high_range_enabled(pvt) && !dct_ganging_enabled(pvt))
-		cs = ~dct_sel_high & 1;
-	else
-		cs = 0;
+	if (hi_range_sel)
+		return dct_sel_high;
 
-	return cs;
-}
+	/*
+	 * see F2x110[DctSelIntLvAddr] - channel interleave mode
+	 */
+	if (dct_interleave_enabled(pvt)) {
+		u8 intlv_addr = dct_sel_interleave_addr(pvt);
 
-static inline u32 f10_map_intlv_en_to_shift(u32 intlv_en)
-{
-	if (intlv_en == 1)
-		return 1;
-	else if (intlv_en == 3)
-		return 2;
-	else if (intlv_en == 7)
-		return 3;
+		/* return DCT select function: 0=DCT0, 1=DCT1 */
+		if (!intlv_addr)
+			return sys_addr >> 6 & 1;
+
+		if (intlv_addr & 0x2) {
+			u8 shift = intlv_addr & 0x1 ? 9 : 6;
+			u32 temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) % 2;
+
+			return ((sys_addr >> shift) & 1) ^ temp;
+		}
+
+		return (sys_addr >> (12 + hweight8(intlv_en))) & 1;
+	}
+
+	if (dct_high_range_enabled(pvt))
+		return ~dct_sel_high & 1;
 
 	return 0;
 }
 
-/* See F10h BKDG, 2.8.10.2 DctSelBaseOffset Programming */
-static inline u64 f10_get_base_addr_offset(u64 sys_addr, int hi_range_sel,
-						 u32 dct_sel_base_addr,
-						 u64 dct_sel_base_off,
-						 u32 hole_valid, u32 hole_off,
-						 u64 dram_base)
+/* Convert the sys_addr to the normalized DCT address */
+static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, unsigned range,
+				 u64 sys_addr, bool hi_rng,
+				 u32 dct_sel_base_addr)
 {
 	u64 chan_off;
+	u64 dram_base		= get_dram_base(pvt, range);
+	u64 hole_off		= f10_dhar_offset(pvt);
+	u64 dct_sel_base_off	= (pvt->dct_sel_hi & 0xFFFFFC00) << 16;
 
-	if (hi_range_sel) {
-		if (!(dct_sel_base_addr & 0xFFFF0000) &&
-		   hole_valid && (sys_addr >= 0x100000000ULL))
-			chan_off = hole_off << 16;
+	if (hi_rng) {
+		/*
+		 * if
+		 * base address of high range is below 4Gb
+		 * (bits [47:27] at [31:11])
+		 * DRAM address space on this DCT is hoisted above 4Gb	&&
+		 * sys_addr > 4Gb
+		 *
+		 *	remove hole offset from sys_addr
+		 * else
+		 *	remove high range offset from sys_addr
+		 */
+		if ((!(dct_sel_base_addr >> 16) ||
+		     dct_sel_base_addr < dhar_base(pvt)) &&
+		    dhar_valid(pvt) &&
+		    (sys_addr >= BIT_64(32)))
+			chan_off = hole_off;
 		else
 			chan_off = dct_sel_base_off;
 	} else {
-		if (hole_valid && (sys_addr >= 0x100000000ULL))
-			chan_off = hole_off << 16;
+		/*
+		 * if
+		 * we have a valid hole		&&
+		 * sys_addr > 4Gb
+		 *
+		 *	remove hole
+		 * else
+		 *	remove dram base to normalize to DCT address
+		 */
+		if (dhar_valid(pvt) && (sys_addr >= BIT_64(32)))
+			chan_off = hole_off;
 		else
-			chan_off = dram_base & 0xFFFFF8000000ULL;
+			chan_off = dram_base;
 	}
 
-	return (sys_addr & 0x0000FFFFFFFFFFC0ULL) -
-			(chan_off & 0x0000FFFFFF800000ULL);
+	return (sys_addr & GENMASK(6,47)) - (chan_off & GENMASK(23,47));
 }
 
-/* Hack for the time being - Can we get this from BIOS?? */
-#define	CH0SPARE_RANK	0
-#define	CH1SPARE_RANK	1
-
 /*
  * checks if the csrow passed in is marked as SPARED, if so returns the new
  * spare row
  */
-static inline int f10_process_possible_spare(int csrow,
-				u32 cs, struct amd64_pvt *pvt)
-{
-	u32 swap_done;
-	u32 bad_dram_cs;
-
-	/* Depending on channel, isolate respective SPARING info */
-	if (cs) {
-		swap_done = F10_ONLINE_SPARE_SWAPDONE1(pvt->online_spare);
-		bad_dram_cs = F10_ONLINE_SPARE_BADDRAM_CS1(pvt->online_spare);
-		if (swap_done && (csrow == bad_dram_cs))
-			csrow = CH1SPARE_RANK;
-	} else {
-		swap_done = F10_ONLINE_SPARE_SWAPDONE0(pvt->online_spare);
-		bad_dram_cs = F10_ONLINE_SPARE_BADDRAM_CS0(pvt->online_spare);
-		if (swap_done && (csrow == bad_dram_cs))
-			csrow = CH0SPARE_RANK;
+static int f10_process_possible_spare(struct amd64_pvt *pvt, u8 dct, int csrow)
+{
+	int tmp_cs;
+
+	if (online_spare_swap_done(pvt, dct) &&
+	    csrow == online_spare_bad_dramcs(pvt, dct)) {
+
+		for_each_chip_select(tmp_cs, dct, pvt) {
+			if (chip_select_base(tmp_cs, dct, pvt) & 0x2) {
+				csrow = tmp_cs;
+				break;
+			}
+		}
 	}
 	return csrow;
 }
@@ -1402,11 +1301,11 @@ static inline int f10_process_possible_spare(int csrow,
  *	-EINVAL:  NOT FOUND
  *	0..csrow = Chip-Select Row
  */
-static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs)
+static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct)
 {
 	struct mem_ctl_info *mci;
 	struct amd64_pvt *pvt;
-	u32 cs_base, cs_mask;
+	u64 cs_base, cs_mask;
 	int cs_found = -EINVAL;
 	int csrow;
 
@@ -1416,39 +1315,25 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs)
 
 	pvt = mci->pvt_info;
 
-	debugf1("InputAddr=0x%x  channelselect=%d\n", in_addr, cs);
-
-	for (csrow = 0; csrow < pvt->cs_count; csrow++) {
+	debugf1("input addr: 0x%llx, DCT: %d\n", in_addr, dct);
 
-		cs_base = amd64_get_dct_base(pvt, cs, csrow);
-		if (!(cs_base & K8_DCSB_CS_ENABLE))
+	for_each_chip_select(csrow, dct, pvt) {
+		if (!csrow_enabled(csrow, dct, pvt))
 			continue;
 
-		/*
-		 * We have an ENABLED CSROW, Isolate just the MASK bits of the
-		 * target: [28:19] and [13:5], which map to [36:27] and [21:13]
-		 * of the actual address.
-		 */
-		cs_base &= REV_F_F1Xh_DCSB_BASE_BITS;
-
-		/*
-		 * Get the DCT Mask, and ENABLE the reserved bits: [18:16] and
-		 * [4:0] to become ON. Then mask off bits [28:0] ([36:8])
-		 */
-		cs_mask = amd64_get_dct_mask(pvt, cs, csrow);
+		get_cs_base_and_mask(pvt, csrow, dct, &cs_base, &cs_mask);
 
-		debugf1("    CSROW=%d CSBase=0x%x RAW CSMask=0x%x\n",
-				csrow, cs_base, cs_mask);
+		debugf1("    CSROW=%d CSBase=0x%llx CSMask=0x%llx\n",
+			csrow, cs_base, cs_mask);
 
-		cs_mask = (cs_mask | 0x0007C01F) & 0x1FFFFFFF;
+		cs_mask = ~cs_mask;
 
-		debugf1("              Final CSMask=0x%x\n", cs_mask);
-		debugf1("    (InputAddr & ~CSMask)=0x%x "
-				"(CSBase & ~CSMask)=0x%x\n",
-				(in_addr & ~cs_mask), (cs_base & ~cs_mask));
+		debugf1("    (InputAddr & ~CSMask)=0x%llx "
+			"(CSBase & ~CSMask)=0x%llx\n",
+			(in_addr & cs_mask), (cs_base & cs_mask));
 
-		if ((in_addr & ~cs_mask) == (cs_base & ~cs_mask)) {
-			cs_found = f10_process_possible_spare(csrow, cs, pvt);
+		if ((in_addr & cs_mask) == (cs_base & cs_mask)) {
+			cs_found = f10_process_possible_spare(pvt, dct, csrow);
 
 			debugf1(" MATCH csrow=%d\n", cs_found);
 			break;
@@ -1457,38 +1342,75 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs)
 	return cs_found;
 }
 
-/* For a given @dram_range, check if @sys_addr falls within it. */
-static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
-				  u64 sys_addr, int *nid, int *chan_sel)
+/*
+ * See F2x10C. Non-interleaved graphics framebuffer memory under the 16G is
+ * swapped with a region located at the bottom of memory so that the GPU can use
+ * the interleaved region and thus two channels.
+ */
+static u64 f1x_swap_interleaved_region(struct amd64_pvt *pvt, u64 sys_addr)
 {
-	int node_id, cs_found = -EINVAL, high_range = 0;
-	u32 intlv_en, intlv_sel, intlv_shift, hole_off;
-	u32 hole_valid, tmp, dct_sel_base, channel;
-	u64 dram_base, chan_addr, dct_sel_base_off;
+	u32 swap_reg, swap_base, swap_limit, rgn_size, tmp_addr;
 
-	dram_base = pvt->dram_base[dram_range];
-	intlv_en = pvt->dram_IntlvEn[dram_range];
+	if (boot_cpu_data.x86 == 0x10) {
+		/* only revC3 and revE have that feature */
+		if (boot_cpu_data.x86_model < 4 ||
+		    (boot_cpu_data.x86_model < 0xa &&
+		     boot_cpu_data.x86_mask < 3))
+			return sys_addr;
+	}
 
-	node_id = pvt->dram_DstNode[dram_range];
-	intlv_sel = pvt->dram_IntlvSel[dram_range];
+	amd64_read_dct_pci_cfg(pvt, SWAP_INTLV_REG, &swap_reg);
 
-	debugf1("(dram=%d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n",
-		dram_range, dram_base, sys_addr, pvt->dram_limit[dram_range]);
+	if (!(swap_reg & 0x1))
+		return sys_addr;
 
-	/*
-	 * This assumes that one node's DHAR is the same as all the other
-	 * nodes' DHAR.
-	 */
-	hole_off = (pvt->dhar & 0x0000FF80);
-	hole_valid = (pvt->dhar & 0x1);
-	dct_sel_base_off = (pvt->dram_ctl_select_high & 0xFFFFFC00) << 16;
+	swap_base	= (swap_reg >> 3) & 0x7f;
+	swap_limit	= (swap_reg >> 11) & 0x7f;
+	rgn_size	= (swap_reg >> 20) & 0x7f;
+	tmp_addr	= sys_addr >> 27;
 
-	debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
-			hole_off, hole_valid, intlv_sel);
+	if (!(sys_addr >> 34) &&
+	    (((tmp_addr >= swap_base) &&
+	     (tmp_addr <= swap_limit)) ||
+	     (tmp_addr < rgn_size)))
+		return sys_addr ^ (u64)swap_base << 27;
+
+	return sys_addr;
+}
+
+/* For a given @dram_range, check if @sys_addr falls within it. */
+static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
+				  u64 sys_addr, int *nid, int *chan_sel)
+{
+	int cs_found = -EINVAL;
+	u64 chan_addr;
+	u32 dct_sel_base;
+	u8 channel;
+	bool high_range = false;
+
+	u8 node_id    = dram_dst_node(pvt, range);
+	u8 intlv_en   = dram_intlv_en(pvt, range);
+	u32 intlv_sel = dram_intlv_sel(pvt, range);
+
+	debugf1("(range %d) SystemAddr= 0x%llx Limit=0x%llx\n",
+		range, sys_addr, get_dram_limit(pvt, range));
+
+	if (dhar_valid(pvt) &&
+	    dhar_base(pvt) <= sys_addr &&
+	    sys_addr < BIT_64(32)) {
+		amd64_warn("Huh? Address is in the MMIO hole: 0x%016llx\n",
+			    sys_addr);
+		return -EINVAL;
+	}
 
 	if (intlv_en &&
-	    (intlv_sel != ((sys_addr >> 12) & intlv_en)))
+	    (intlv_sel != ((sys_addr >> 12) & intlv_en))) {
+		amd64_warn("Botched intlv bits, en: 0x%x, sel: 0x%x\n",
+			   intlv_en, intlv_sel);
 		return -EINVAL;
+	}
+
+	sys_addr = f1x_swap_interleaved_region(pvt, sys_addr);
 
 	dct_sel_base = dct_sel_baseaddr(pvt);
 
@@ -1499,38 +1421,41 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
 	if (dct_high_range_enabled(pvt) &&
 	   !dct_ganging_enabled(pvt) &&
 	   ((sys_addr >> 27) >= (dct_sel_base >> 11)))
-		high_range = 1;
-
-	channel = f10_determine_channel(pvt, sys_addr, high_range, intlv_en);
+		high_range = true;
 
-	chan_addr = f10_get_base_addr_offset(sys_addr, high_range, dct_sel_base,
-					     dct_sel_base_off, hole_valid,
-					     hole_off, dram_base);
+	channel = f1x_determine_channel(pvt, sys_addr, high_range, intlv_en);
 
-	intlv_shift = f10_map_intlv_en_to_shift(intlv_en);
+	chan_addr = f1x_get_norm_dct_addr(pvt, range, sys_addr,
+					  high_range, dct_sel_base);
 
-	/* remove Node ID (in case of memory interleaving) */
-	tmp = chan_addr & 0xFC0;
+	/* Remove node interleaving, see F1x120 */
+	if (intlv_en)
+		chan_addr = ((chan_addr >> (12 + hweight8(intlv_en))) << 12) |
+			    (chan_addr & 0xfff);
 
-	chan_addr = ((chan_addr >> intlv_shift) & 0xFFFFFFFFF000ULL) | tmp;
-
-	/* remove channel interleave and hash */
+	/* remove channel interleave */
 	if (dct_interleave_enabled(pvt) &&
 	   !dct_high_range_enabled(pvt) &&
 	   !dct_ganging_enabled(pvt)) {
-		if (dct_sel_interleave_addr(pvt) != 1)
-			chan_addr = (chan_addr >> 1) & 0xFFFFFFFFFFFFFFC0ULL;
-		else {
-			tmp = chan_addr & 0xFC0;
-			chan_addr = ((chan_addr & 0xFFFFFFFFFFFFC000ULL) >> 1)
-					| tmp;
-		}
+
+		if (dct_sel_interleave_addr(pvt) != 1) {
+			if (dct_sel_interleave_addr(pvt) == 0x3)
+				/* hash 9 */
+				chan_addr = ((chan_addr >> 10) << 9) |
+					     (chan_addr & 0x1ff);
+			else
+				/* A[6] or hash 6 */
+				chan_addr = ((chan_addr >> 7) << 6) |
+					     (chan_addr & 0x3f);
+		} else
+			/* A[12] */
+			chan_addr = ((chan_addr >> 13) << 12) |
+				     (chan_addr & 0xfff);
 	}
 
-	debugf1("   (ChannelAddrLong=0x%llx) >> 8 becomes InputAddr=0x%x\n",
-		chan_addr, (u32)(chan_addr >> 8));
+	debugf1("   Normalized DCT addr: 0x%llx\n", chan_addr);
 
-	cs_found = f10_lookup_addr_in_dct(chan_addr >> 8, node_id, channel);
+	cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel);
 
 	if (cs_found >= 0) {
 		*nid = node_id;
@@ -1539,23 +1464,21 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range,
 	return cs_found;
 }
 
-static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
+static int f1x_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
 				       int *node, int *chan_sel)
 {
-	int dram_range, cs_found = -EINVAL;
-	u64 dram_base, dram_limit;
+	int cs_found = -EINVAL;
+	unsigned range;
 
-	for (dram_range = 0; dram_range < DRAM_REG_COUNT; dram_range++) {
+	for (range = 0; range < DRAM_RANGES; range++) {
 
-		if (!pvt->dram_rw_en[dram_range])
+		if (!dram_rw(pvt, range))
 			continue;
 
-		dram_base = pvt->dram_base[dram_range];
-		dram_limit = pvt->dram_limit[dram_range];
+		if ((get_dram_base(pvt, range)  <= sys_addr) &&
+		    (get_dram_limit(pvt, range) >= sys_addr)) {
 
-		if ((dram_base <= sys_addr) && (sys_addr <= dram_limit)) {
-
-			cs_found = f10_match_to_this_node(pvt, dram_range,
+			cs_found = f1x_match_to_this_node(pvt, range,
 							  sys_addr, node,
 							  chan_sel);
 			if (cs_found >= 0)
@@ -1572,16 +1495,14 @@ static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
  * The @sys_addr is usually an error address received from the hardware
  * (MCX_ADDR).
  */
-static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
-				     struct err_regs *err_info,
-				     u64 sys_addr)
+static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
+				     u16 syndrome)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u32 page, offset;
 	int nid, csrow, chan = 0;
-	u16 syndrome;
 
-	csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
+	csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
 
 	if (csrow < 0) {
 		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
@@ -1590,14 +1511,12 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
 
 	error_address_to_page_and_offset(sys_addr, &page, &offset);
 
-	syndrome = extract_syndrome(err_info);
-
 	/*
 	 * We need the syndromes for channel detection only when we're
 	 * ganged. Otherwise @chan should already contain the channel at
 	 * this point.
 	 */
-	if (dct_ganging_enabled(pvt) && (pvt->nbcfg & K8_NBCFG_CHIPKILL))
+	if (dct_ganging_enabled(pvt))
 		chan = get_channel_from_ecc_syndrome(mci, syndrome);
 
 	if (chan >= 0)
@@ -1614,16 +1533,16 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
 
 /*
  * debug routine to display the memory sizes of all logical DIMMs and its
- * CSROWs as well
+ * CSROWs
  */
-static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt)
+static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 {
 	int dimm, size0, size1, factor = 0;
-	u32 dbam;
-	u32 *dcsb;
+	u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
+	u32 dbam  = ctrl ? pvt->dbam1 : pvt->dbam0;
 
 	if (boot_cpu_data.x86 == 0xf) {
-		if (pvt->dclr0 & F10_WIDTH_128)
+		if (pvt->dclr0 & WIDTH_128)
 			factor = 1;
 
 		/* K8 families < revF not supported yet */
@@ -1634,7 +1553,8 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt)
 	}
 
 	dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1 : pvt->dbam0;
-	dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dcsb1 : pvt->dcsb0;
+	dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->csels[1].csbases
+						   : pvt->csels[0].csbases;
 
 	debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", ctrl, dbam);
 
@@ -1644,12 +1564,14 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt)
 	for (dimm = 0; dimm < 4; dimm++) {
 
 		size0 = 0;
-		if (dcsb[dimm*2] & K8_DCSB_CS_ENABLE)
-			size0 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam));
+		if (dcsb[dimm*2] & DCSB_CS_ENABLE)
+			size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
+						     DBAM_DIMM(dimm, dbam));
 
 		size1 = 0;
-		if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE)
-			size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam));
+		if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
+			size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
+						     DBAM_DIMM(dimm, dbam));
 
 		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
 				dimm * 2,     size0 << factor,
@@ -1664,10 +1586,9 @@ static struct amd64_family_type amd64_family_types[] = {
 		.f3_id = PCI_DEVICE_ID_AMD_K8_NB_MISC,
 		.ops = {
 			.early_channel_count	= k8_early_channel_count,
-			.get_error_address	= k8_get_error_address,
-			.read_dram_base_limit	= k8_read_dram_base_limit,
 			.map_sysaddr_to_csrow	= k8_map_sysaddr_to_csrow,
 			.dbam_to_cs		= k8_dbam_to_chip_select,
+			.read_dct_pci_cfg	= k8_read_dct_pci_cfg,
 		}
 	},
 	[F10_CPUS] = {
@@ -1675,12 +1596,21 @@ static struct amd64_family_type amd64_family_types[] = {
 		.f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP,
 		.f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC,
 		.ops = {
-			.early_channel_count	= f10_early_channel_count,
-			.get_error_address	= f10_get_error_address,
-			.read_dram_base_limit	= f10_read_dram_base_limit,
-			.read_dram_ctl_register	= f10_read_dram_ctl_register,
-			.map_sysaddr_to_csrow	= f10_map_sysaddr_to_csrow,
+			.early_channel_count	= f1x_early_channel_count,
+			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
 			.dbam_to_cs		= f10_dbam_to_chip_select,
+			.read_dct_pci_cfg	= f10_read_dct_pci_cfg,
+		}
+	},
+	[F15_CPUS] = {
+		.ctl_name = "F15h",
+		.f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1,
+		.f3_id = PCI_DEVICE_ID_AMD_15H_NB_F3,
+		.ops = {
+			.early_channel_count	= f1x_early_channel_count,
+			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
+			.dbam_to_cs		= f15_dbam_to_chip_select,
+			.read_dct_pci_cfg	= f15_read_dct_pci_cfg,
 		}
 	},
 };
@@ -1770,15 +1700,15 @@ static u16 x8_vectors[] = {
 	0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
 };
 
-static int decode_syndrome(u16 syndrome, u16 *vectors, int num_vecs,
-			   int v_dim)
+static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs,
+			   unsigned v_dim)
 {
 	unsigned int i, err_sym;
 
 	for (err_sym = 0; err_sym < num_vecs / v_dim; err_sym++) {
 		u16 s = syndrome;
-		int v_idx =  err_sym * v_dim;
-		int v_end = (err_sym + 1) * v_dim;
+		unsigned v_idx =  err_sym * v_dim;
+		unsigned v_end = (err_sym + 1) * v_dim;
 
 		/* walk over all 16 bits of the syndrome */
 		for (i = 1; i < (1U << 16); i <<= 1) {
@@ -1850,51 +1780,50 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome)
 	struct amd64_pvt *pvt = mci->pvt_info;
 	int err_sym = -1;
 
-	if (pvt->syn_type == 8)
+	if (pvt->ecc_sym_sz == 8)
 		err_sym = decode_syndrome(syndrome, x8_vectors,
 					  ARRAY_SIZE(x8_vectors),
-					  pvt->syn_type);
-	else if (pvt->syn_type == 4)
+					  pvt->ecc_sym_sz);
+	else if (pvt->ecc_sym_sz == 4)
 		err_sym = decode_syndrome(syndrome, x4_vectors,
 					  ARRAY_SIZE(x4_vectors),
-					  pvt->syn_type);
+					  pvt->ecc_sym_sz);
 	else {
-		amd64_warn("Illegal syndrome type: %u\n", pvt->syn_type);
+		amd64_warn("Illegal syndrome type: %u\n", pvt->ecc_sym_sz);
 		return err_sym;
 	}
 
-	return map_err_sym_to_channel(err_sym, pvt->syn_type);
+	return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
 }
 
 /*
  * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR
  * ADDRESS and process.
  */
-static void amd64_handle_ce(struct mem_ctl_info *mci,
-			    struct err_regs *info)
+static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u64 sys_addr;
+	u16 syndrome;
 
 	/* Ensure that the Error Address is VALID */
-	if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) {
+	if (!(m->status & MCI_STATUS_ADDRV)) {
 		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
 		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
 		return;
 	}
 
-	sys_addr = pvt->ops->get_error_address(mci, info);
+	sys_addr = get_error_address(m);
+	syndrome = extract_syndrome(m->status);
 
 	amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
 
-	pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr);
+	pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, syndrome);
 }
 
 /* Handle any Un-correctable Errors (UEs) */
-static void amd64_handle_ue(struct mem_ctl_info *mci,
-			    struct err_regs *info)
+static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m)
 {
-	struct amd64_pvt *pvt = mci->pvt_info;
 	struct mem_ctl_info *log_mci, *src_mci = NULL;
 	int csrow;
 	u64 sys_addr;
@@ -1902,13 +1831,13 @@ static void amd64_handle_ue(struct mem_ctl_info *mci,
 
 	log_mci = mci;
 
-	if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) {
+	if (!(m->status & MCI_STATUS_ADDRV)) {
 		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
 		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
 		return;
 	}
 
-	sys_addr = pvt->ops->get_error_address(mci, info);
+	sys_addr = get_error_address(m);
 
 	/*
 	 * Find out which node the error address belongs to. This may be
@@ -1936,14 +1865,14 @@ static void amd64_handle_ue(struct mem_ctl_info *mci,
 }
 
 static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
-					    struct err_regs *info)
+					    struct mce *m)
 {
-	u16 ec = EC(info->nbsl);
-	u8 xec = XEC(info->nbsl, 0x1f);
-	int ecc_type = (info->nbsh >> 13) & 0x3;
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, 0x1f);
+	u8 ecc_type = (m->status >> 45) & 0x3;
 
 	/* Bail early out if this was an 'observed' error */
-	if (PP(ec) == K8_NBSL_PP_OBS)
+	if (PP(ec) == NBSL_PP_OBS)
 		return;
 
 	/* Do only ECC errors */
@@ -1951,34 +1880,16 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
 		return;
 
 	if (ecc_type == 2)
-		amd64_handle_ce(mci, info);
+		amd64_handle_ce(mci, m);
 	else if (ecc_type == 1)
-		amd64_handle_ue(mci, info);
+		amd64_handle_ue(mci, m);
 }
 
 void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
 {
 	struct mem_ctl_info *mci = mcis[node_id];
-	struct err_regs regs;
-
-	regs.nbsl  = (u32) m->status;
-	regs.nbsh  = (u32)(m->status >> 32);
-	regs.nbeal = (u32) m->addr;
-	regs.nbeah = (u32)(m->addr >> 32);
-	regs.nbcfg = nbcfg;
-
-	__amd64_decode_bus_error(mci, &regs);
-
-	/*
-	 * Check the UE bit of the NB status high register, if set generate some
-	 * logs. If NOT a GART error, then process the event as a NO-INFO event.
-	 * If it was a GART error, skip that process.
-	 *
-	 * FIXME: this should go somewhere else, if at all.
-	 */
-	if (regs.nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
-		edac_mc_handle_ue_no_info(mci, "UE bit is set");
 
+	__amd64_decode_bus_error(mci, m);
 }
 
 /*
@@ -2027,9 +1938,10 @@ static void free_mc_sibling_devs(struct amd64_pvt *pvt)
  */
 static void read_mc_regs(struct amd64_pvt *pvt)
 {
+	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u64 msr_val;
 	u32 tmp;
-	int dram;
+	unsigned range;
 
 	/*
 	 * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since
@@ -2046,75 +1958,66 @@ static void read_mc_regs(struct amd64_pvt *pvt)
 	} else
 		debugf0("  TOP_MEM2 disabled.\n");
 
-	amd64_read_pci_cfg(pvt->F3, K8_NBCAP, &pvt->nbcap);
+	amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap);
 
-	if (pvt->ops->read_dram_ctl_register)
-		pvt->ops->read_dram_ctl_register(pvt);
+	read_dram_ctl_register(pvt);
 
-	for (dram = 0; dram < DRAM_REG_COUNT; dram++) {
-		/*
-		 * Call CPU specific READ function to get the DRAM Base and
-		 * Limit values from the DCT.
-		 */
-		pvt->ops->read_dram_base_limit(pvt, dram);
+	for (range = 0; range < DRAM_RANGES; range++) {
+		u8 rw;
 
-		/*
-		 * Only print out debug info on rows with both R and W Enabled.
-		 * Normal processing, compiler should optimize this whole 'if'
-		 * debug output block away.
-		 */
-		if (pvt->dram_rw_en[dram] != 0) {
-			debugf1("  DRAM-BASE[%d]: 0x%016llx "
-				"DRAM-LIMIT:  0x%016llx\n",
-				dram,
-				pvt->dram_base[dram],
-				pvt->dram_limit[dram]);
-
-			debugf1("        IntlvEn=%s %s %s "
-				"IntlvSel=%d DstNode=%d\n",
-				pvt->dram_IntlvEn[dram] ?
-					"Enabled" : "Disabled",
-				(pvt->dram_rw_en[dram] & 0x2) ? "W" : "!W",
-				(pvt->dram_rw_en[dram] & 0x1) ? "R" : "!R",
-				pvt->dram_IntlvSel[dram],
-				pvt->dram_DstNode[dram]);
-		}
+		/* read settings for this DRAM range */
+		read_dram_base_limit_regs(pvt, range);
+
+		rw = dram_rw(pvt, range);
+		if (!rw)
+			continue;
+
+		debugf1("  DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n",
+			range,
+			get_dram_base(pvt, range),
+			get_dram_limit(pvt, range));
+
+		debugf1("   IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n",
+			dram_intlv_en(pvt, range) ? "Enabled" : "Disabled",
+			(rw & 0x1) ? "R" : "-",
+			(rw & 0x2) ? "W" : "-",
+			dram_intlv_sel(pvt, range),
+			dram_dst_node(pvt, range));
 	}
 
-	amd64_read_dct_base_mask(pvt);
+	read_dct_base_mask(pvt);
 
-	amd64_read_pci_cfg(pvt->F1, K8_DHAR, &pvt->dhar);
-	amd64_read_dbam_reg(pvt);
+	amd64_read_pci_cfg(pvt->F1, DHAR, &pvt->dhar);
+	amd64_read_dct_pci_cfg(pvt, DBAM0, &pvt->dbam0);
 
 	amd64_read_pci_cfg(pvt->F3, F10_ONLINE_SPARE, &pvt->online_spare);
 
-	amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0);
-	amd64_read_pci_cfg(pvt->F2, F10_DCHR_0, &pvt->dchr0);
+	amd64_read_dct_pci_cfg(pvt, DCLR0, &pvt->dclr0);
+	amd64_read_dct_pci_cfg(pvt, DCHR0, &pvt->dchr0);
 
-	if (boot_cpu_data.x86 >= 0x10) {
-		if (!dct_ganging_enabled(pvt)) {
-			amd64_read_pci_cfg(pvt->F2, F10_DCLR_1, &pvt->dclr1);
-			amd64_read_pci_cfg(pvt->F2, F10_DCHR_1, &pvt->dchr1);
-		}
-		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
+	if (!dct_ganging_enabled(pvt)) {
+		amd64_read_dct_pci_cfg(pvt, DCLR1, &pvt->dclr1);
+		amd64_read_dct_pci_cfg(pvt, DCHR1, &pvt->dchr1);
 	}
 
-	if (boot_cpu_data.x86 == 0x10 &&
-	    boot_cpu_data.x86_model > 7 &&
-	    /* F3x180[EccSymbolSize]=1 => x8 symbols */
-	    tmp & BIT(25))
-		pvt->syn_type = 8;
-	else
-		pvt->syn_type = 4;
+	pvt->ecc_sym_sz = 4;
 
-	amd64_dump_misc_regs(pvt);
+	if (c->x86 >= 0x10) {
+		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
+		amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1);
+
+		/* F10h, revD and later can do x8 ECC too */
+		if ((c->x86 > 0x10 || c->x86_model > 7) && tmp & BIT(25))
+			pvt->ecc_sym_sz = 8;
+	}
+	dump_misc_regs(pvt);
 }
 
 /*
  * NOTE: CPU Revision Dependent code
  *
  * Input:
- *	@csrow_nr ChipSelect Row Number (0..pvt->cs_count-1)
+ *	@csrow_nr ChipSelect Row Number (0..NUM_CHIPSELECTS-1)
  *	k8 private pointer to -->
  *			DRAM Bank Address mapping register
  *			node_id
@@ -2144,7 +2047,7 @@ static void read_mc_regs(struct amd64_pvt *pvt)
  *	encompasses
  *
  */
-static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt)
+static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
 {
 	u32 cs_mode, nr_pages;
 
@@ -2157,7 +2060,7 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt)
 	 */
 	cs_mode = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF;
 
-	nr_pages = pvt->ops->dbam_to_cs(pvt, cs_mode) << (20 - PAGE_SHIFT);
+	nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
 
 	/*
 	 * If dual channel then double the memory size of single channel.
@@ -2180,23 +2083,22 @@ static int init_csrows(struct mem_ctl_info *mci)
 {
 	struct csrow_info *csrow;
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 input_addr_min, input_addr_max, sys_addr;
+	u64 input_addr_min, input_addr_max, sys_addr, base, mask;
 	u32 val;
 	int i, empty = 1;
 
-	amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &val);
+	amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
 
 	pvt->nbcfg = val;
-	pvt->ctl_error_info.nbcfg = val;
 
 	debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
 		pvt->mc_node_id, val,
-		!!(val & K8_NBCFG_CHIPKILL), !!(val & K8_NBCFG_ECC_ENABLE));
+		!!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
 
-	for (i = 0; i < pvt->cs_count; i++) {
+	for_each_chip_select(i, 0, pvt) {
 		csrow = &mci->csrows[i];
 
-		if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) {
+		if (!csrow_enabled(i, 0, pvt)) {
 			debugf1("----CSROW %d EMPTY for node %d\n", i,
 				pvt->mc_node_id);
 			continue;
@@ -2206,13 +2108,15 @@ static int init_csrows(struct mem_ctl_info *mci)
 			i, pvt->mc_node_id);
 
 		empty = 0;
-		csrow->nr_pages = amd64_csrow_nr_pages(i, pvt);
+		csrow->nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
 		find_csrow_limits(mci, i, &input_addr_min, &input_addr_max);
 		sys_addr = input_addr_to_sys_addr(mci, input_addr_min);
 		csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT);
 		sys_addr = input_addr_to_sys_addr(mci, input_addr_max);
 		csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT);
-		csrow->page_mask = ~mask_from_dct_mask(pvt, i);
+
+		get_cs_base_and_mask(pvt, i, 0, &base, &mask);
+		csrow->page_mask = ~mask;
 		/* 8 bytes of resolution */
 
 		csrow->mtype = amd64_determine_memory_type(pvt, i);
@@ -2231,9 +2135,9 @@ static int init_csrows(struct mem_ctl_info *mci)
 		/*
 		 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
 		 */
-		if (pvt->nbcfg & K8_NBCFG_ECC_ENABLE)
+		if (pvt->nbcfg & NBCFG_ECC_ENABLE)
 			csrow->edac_mode =
-			    (pvt->nbcfg & K8_NBCFG_CHIPKILL) ?
+			    (pvt->nbcfg & NBCFG_CHIPKILL) ?
 			    EDAC_S4ECD4ED : EDAC_SECDED;
 		else
 			csrow->edac_mode = EDAC_NONE;
@@ -2243,7 +2147,7 @@ static int init_csrows(struct mem_ctl_info *mci)
 }
 
 /* get all cores on this DCT */
-static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid)
+static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid)
 {
 	int cpu;
 
@@ -2253,7 +2157,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid)
 }
 
 /* check MCG_CTL on all the cpus on this node */
-static bool amd64_nb_mce_bank_enabled_on_node(int nid)
+static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid)
 {
 	cpumask_var_t mask;
 	int cpu, nbe;
@@ -2270,7 +2174,7 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid)
 
 	for_each_cpu(cpu, mask) {
 		struct msr *reg = per_cpu_ptr(msrs, cpu);
-		nbe = reg->l & K8_MSR_MCGCTL_NBE;
+		nbe = reg->l & MSR_MCGCTL_NBE;
 
 		debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n",
 			cpu, reg->q,
@@ -2305,16 +2209,16 @@ static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on)
 		struct msr *reg = per_cpu_ptr(msrs, cpu);
 
 		if (on) {
-			if (reg->l & K8_MSR_MCGCTL_NBE)
+			if (reg->l & MSR_MCGCTL_NBE)
 				s->flags.nb_mce_enable = 1;
 
-			reg->l |= K8_MSR_MCGCTL_NBE;
+			reg->l |= MSR_MCGCTL_NBE;
 		} else {
 			/*
 			 * Turn off NB MCE reporting only when it was off before
 			 */
 			if (!s->flags.nb_mce_enable)
-				reg->l &= ~K8_MSR_MCGCTL_NBE;
+				reg->l &= ~MSR_MCGCTL_NBE;
 		}
 	}
 	wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
@@ -2328,40 +2232,38 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid,
 				       struct pci_dev *F3)
 {
 	bool ret = true;
-	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+	u32 value, mask = 0x3;		/* UECC/CECC enable */
 
 	if (toggle_ecc_err_reporting(s, nid, ON)) {
 		amd64_warn("Error enabling ECC reporting over MCGCTL!\n");
 		return false;
 	}
 
-	amd64_read_pci_cfg(F3, K8_NBCTL, &value);
+	amd64_read_pci_cfg(F3, NBCTL, &value);
 
-	/* turn on UECCEn and CECCEn bits */
 	s->old_nbctl   = value & mask;
 	s->nbctl_valid = true;
 
 	value |= mask;
-	pci_write_config_dword(F3, K8_NBCTL, value);
+	amd64_write_pci_cfg(F3, NBCTL, value);
 
-	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
+	amd64_read_pci_cfg(F3, NBCFG, &value);
 
-	debugf0("1: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
-		nid, value,
-		!!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE));
+	debugf0("1: node %d, NBCFG=0x%08x[DramEccEn: %d]\n",
+		nid, value, !!(value & NBCFG_ECC_ENABLE));
 
-	if (!(value & K8_NBCFG_ECC_ENABLE)) {
+	if (!(value & NBCFG_ECC_ENABLE)) {
 		amd64_warn("DRAM ECC disabled on this node, enabling...\n");
 
 		s->flags.nb_ecc_prev = 0;
 
 		/* Attempt to turn on DRAM ECC Enable */
-		value |= K8_NBCFG_ECC_ENABLE;
-		pci_write_config_dword(F3, K8_NBCFG, value);
+		value |= NBCFG_ECC_ENABLE;
+		amd64_write_pci_cfg(F3, NBCFG, value);
 
-		amd64_read_pci_cfg(F3, K8_NBCFG, &value);
+		amd64_read_pci_cfg(F3, NBCFG, &value);
 
-		if (!(value & K8_NBCFG_ECC_ENABLE)) {
+		if (!(value & NBCFG_ECC_ENABLE)) {
 			amd64_warn("Hardware rejected DRAM ECC enable,"
 				   "check memory DIMM configuration.\n");
 			ret = false;
@@ -2372,9 +2274,8 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid,
 		s->flags.nb_ecc_prev = 1;
 	}
 
-	debugf0("2: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
-		nid, value,
-		!!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE));
+	debugf0("2: node %d, NBCFG=0x%08x[DramEccEn: %d]\n",
+		nid, value, !!(value & NBCFG_ECC_ENABLE));
 
 	return ret;
 }
@@ -2382,22 +2283,23 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid,
 static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid,
 					struct pci_dev *F3)
 {
-	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+	u32 value, mask = 0x3;		/* UECC/CECC enable */
+
 
 	if (!s->nbctl_valid)
 		return;
 
-	amd64_read_pci_cfg(F3, K8_NBCTL, &value);
+	amd64_read_pci_cfg(F3, NBCTL, &value);
 	value &= ~mask;
 	value |= s->old_nbctl;
 
-	pci_write_config_dword(F3, K8_NBCTL, value);
+	amd64_write_pci_cfg(F3, NBCTL, value);
 
 	/* restore previous BIOS DRAM ECC "off" setting we force-enabled */
 	if (!s->flags.nb_ecc_prev) {
-		amd64_read_pci_cfg(F3, K8_NBCFG, &value);
-		value &= ~K8_NBCFG_ECC_ENABLE;
-		pci_write_config_dword(F3, K8_NBCFG, value);
+		amd64_read_pci_cfg(F3, NBCFG, &value);
+		value &= ~NBCFG_ECC_ENABLE;
+		amd64_write_pci_cfg(F3, NBCFG, value);
 	}
 
 	/* restore the NB Enable MCGCTL bit */
@@ -2423,9 +2325,9 @@ static bool ecc_enabled(struct pci_dev *F3, u8 nid)
 	u8 ecc_en = 0;
 	bool nb_mce_en = false;
 
-	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
+	amd64_read_pci_cfg(F3, NBCFG, &value);
 
-	ecc_en = !!(value & K8_NBCFG_ECC_ENABLE);
+	ecc_en = !!(value & NBCFG_ECC_ENABLE);
 	amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
 
 	nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid);
@@ -2463,23 +2365,24 @@ static void set_mc_sysfs_attrs(struct mem_ctl_info *mci)
 	mci->mc_driver_sysfs_attributes = sysfs_attrs;
 }
 
-static void setup_mci_misc_attrs(struct mem_ctl_info *mci)
+static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
+				 struct amd64_family_type *fam)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 
 	mci->mtype_cap		= MEM_FLAG_DDR2 | MEM_FLAG_RDDR2;
 	mci->edac_ctl_cap	= EDAC_FLAG_NONE;
 
-	if (pvt->nbcap & K8_NBCAP_SECDED)
+	if (pvt->nbcap & NBCAP_SECDED)
 		mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
 
-	if (pvt->nbcap & K8_NBCAP_CHIPKILL)
+	if (pvt->nbcap & NBCAP_CHIPKILL)
 		mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED;
 
 	mci->edac_cap		= amd64_determine_edac_cap(pvt);
 	mci->mod_name		= EDAC_MOD_STR;
 	mci->mod_ver		= EDAC_AMD64_VERSION;
-	mci->ctl_name		= pvt->ctl_name;
+	mci->ctl_name		= fam->ctl_name;
 	mci->dev_name		= pci_name(pvt->F2);
 	mci->ctl_page_to_phys	= NULL;
 
@@ -2500,14 +2403,16 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
 	case 0xf:
 		fam_type		= &amd64_family_types[K8_CPUS];
 		pvt->ops		= &amd64_family_types[K8_CPUS].ops;
-		pvt->ctl_name		= fam_type->ctl_name;
-		pvt->min_scrubrate	= K8_MIN_SCRUB_RATE_BITS;
 		break;
+
 	case 0x10:
 		fam_type		= &amd64_family_types[F10_CPUS];
 		pvt->ops		= &amd64_family_types[F10_CPUS].ops;
-		pvt->ctl_name		= fam_type->ctl_name;
-		pvt->min_scrubrate	= F10_MIN_SCRUB_RATE_BITS;
+		break;
+
+	case 0x15:
+		fam_type		= &amd64_family_types[F15_CPUS];
+		pvt->ops		= &amd64_family_types[F15_CPUS].ops;
 		break;
 
 	default:
@@ -2517,7 +2422,7 @@ static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt)
 
 	pvt->ext_model = boot_cpu_data.x86_model >> 4;
 
-	amd64_info("%s %sdetected (node %d).\n", pvt->ctl_name,
+	amd64_info("%s %sdetected (node %d).\n", fam_type->ctl_name,
 		     (fam == 0xf ?
 				(pvt->ext_model >= K8_REV_F  ? "revF or later "
 							     : "revE or earlier ")
@@ -2564,14 +2469,14 @@ static int amd64_init_one_instance(struct pci_dev *F2)
 		goto err_siblings;
 
 	ret = -ENOMEM;
-	mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, nid);
+	mci = edac_mc_alloc(0, pvt->csels[0].b_cnt, pvt->channel_count, nid);
 	if (!mci)
 		goto err_siblings;
 
 	mci->pvt_info = pvt;
 	mci->dev = &pvt->F2->dev;
 
-	setup_mci_misc_attrs(mci);
+	setup_mci_misc_attrs(mci, fam_type);
 
 	if (init_csrows(mci))
 		mci->edac_cap = EDAC_FLAG_NONE;
@@ -2714,6 +2619,15 @@ static const struct pci_device_id amd64_pci_table[] __devinitdata = {
 		.class		= 0,
 		.class_mask	= 0,
 	},
+	{
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_15H_NB_F2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= 0,
+		.class_mask	= 0,
+	},
+
 	{0, }
 };
 MODULE_DEVICE_TABLE(pci, amd64_pci_table);
@@ -2754,7 +2668,7 @@ static int __init amd64_edac_init(void)
 {
 	int err = -ENODEV;
 
-	edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");
+	printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION);
 
 	opstate_init();
 
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index 613ec72..11be36a 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -144,7 +144,7 @@
  *         sections 3.5.4 and 3.5.5 for more information.
  */
 
-#define EDAC_AMD64_VERSION		"v3.3.0"
+#define EDAC_AMD64_VERSION		"3.4.0"
 #define EDAC_MOD_STR			"amd64_edac"
 
 /* Extended Model from CPUID, for CPU Revision numbers */
@@ -153,85 +153,64 @@
 #define K8_REV_F			4
 
 /* Hardware limit on ChipSelect rows per MC and processors per system */
-#define MAX_CS_COUNT			8
-#define DRAM_REG_COUNT			8
+#define NUM_CHIPSELECTS			8
+#define DRAM_RANGES			8
 
 #define ON true
 #define OFF false
 
 /*
+ * Create a contiguous bitmask starting at bit position @lo and ending at
+ * position @hi. For example
+ *
+ * GENMASK(21, 39) gives us the 64bit vector 0x000000ffffe00000.
+ */
+#define GENMASK(lo, hi)			(((1ULL << ((hi) - (lo) + 1)) - 1) << (lo))
+
+/*
  * PCI-defined configuration space registers
  */
+#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
+#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
 
 
 /*
  * Function 1 - Address Map
  */
-#define K8_DRAM_BASE_LOW		0x40
-#define K8_DRAM_LIMIT_LOW		0x44
-#define K8_DHAR				0xf0
-
-#define DHAR_VALID			BIT(0)
-#define F10_DRAM_MEM_HOIST_VALID	BIT(1)
+#define DRAM_BASE_LO			0x40
+#define DRAM_LIMIT_LO			0x44
 
-#define DHAR_BASE_MASK			0xff000000
-#define dhar_base(dhar)			(dhar & DHAR_BASE_MASK)
+#define dram_intlv_en(pvt, i)		((u8)((pvt->ranges[i].base.lo >> 8) & 0x7))
+#define dram_rw(pvt, i)			((u8)(pvt->ranges[i].base.lo & 0x3))
+#define dram_intlv_sel(pvt, i)		((u8)((pvt->ranges[i].lim.lo >> 8) & 0x7))
+#define dram_dst_node(pvt, i)		((u8)(pvt->ranges[i].lim.lo & 0x7))
 
-#define K8_DHAR_OFFSET_MASK		0x0000ff00
-#define k8_dhar_offset(dhar)		((dhar & K8_DHAR_OFFSET_MASK) << 16)
+#define DHAR				0xf0
+#define dhar_valid(pvt)			((pvt)->dhar & BIT(0))
+#define dhar_mem_hoist_valid(pvt)	((pvt)->dhar & BIT(1))
+#define dhar_base(pvt)			((pvt)->dhar & 0xff000000)
+#define k8_dhar_offset(pvt)		(((pvt)->dhar & 0x0000ff00) << 16)
 
-#define F10_DHAR_OFFSET_MASK		0x0000ff80
 					/* NOTE: Extra mask bit vs K8 */
-#define f10_dhar_offset(dhar)		((dhar & F10_DHAR_OFFSET_MASK) << 16)
+#define f10_dhar_offset(pvt)		(((pvt)->dhar & 0x0000ff80) << 16)
 
+#define DCT_CFG_SEL			0x10C
 
-/* F10 High BASE/LIMIT registers */
-#define F10_DRAM_BASE_HIGH		0x140
-#define F10_DRAM_LIMIT_HIGH		0x144
+#define DRAM_BASE_HI			0x140
+#define DRAM_LIMIT_HI			0x144
 
 
 /*
  * Function 2 - DRAM controller
  */
-#define K8_DCSB0			0x40
-#define F10_DCSB1			0x140
+#define DCSB0				0x40
+#define DCSB1				0x140
+#define DCSB_CS_ENABLE			BIT(0)
 
-#define K8_DCSB_CS_ENABLE		BIT(0)
-#define K8_DCSB_NPT_SPARE		BIT(1)
-#define K8_DCSB_NPT_TESTFAIL		BIT(2)
+#define DCSM0				0x60
+#define DCSM1				0x160
 
-/*
- * REV E: select [31:21] and [15:9] from DCSB and the shift amount to form
- * the address
- */
-#define REV_E_DCSB_BASE_BITS		(0xFFE0FE00ULL)
-#define REV_E_DCS_SHIFT			4
-
-#define REV_F_F1Xh_DCSB_BASE_BITS	(0x1FF83FE0ULL)
-#define REV_F_F1Xh_DCS_SHIFT		8
-
-/*
- * REV F and later: selects [28:19] and [13:5] from DCSB and the shift amount
- * to form the address
- */
-#define REV_F_DCSB_BASE_BITS		(0x1FF83FE0ULL)
-#define REV_F_DCS_SHIFT			8
-
-/* DRAM CS Mask Registers */
-#define K8_DCSM0			0x60
-#define F10_DCSM1			0x160
-
-/* REV E: select [29:21] and [15:9] from DCSM */
-#define REV_E_DCSM_MASK_BITS		0x3FE0FE00
-
-/* unused bits [24:20] and [12:0] */
-#define REV_E_DCS_NOTUSED_BITS		0x01F01FFF
-
-/* REV F and later: select [28:19] and [13:5] from DCSM */
-#define REV_F_F1Xh_DCSM_MASK_BITS	0x1FF83FE0
-
-/* unused bits [26:22] and [12:0] */
-#define REV_F_F1Xh_DCS_NOTUSED_BITS	0x07C01FFF
+#define csrow_enabled(i, dct, pvt)	((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
 
 #define DBAM0				0x80
 #define DBAM1				0x180
@@ -241,148 +220,84 @@
 
 #define DBAM_MAX_VALUE			11
 
-
-#define F10_DCLR_0			0x90
-#define F10_DCLR_1			0x190
+#define DCLR0				0x90
+#define DCLR1				0x190
 #define REVE_WIDTH_128			BIT(16)
-#define F10_WIDTH_128			BIT(11)
+#define WIDTH_128			BIT(11)
 
+#define DCHR0				0x94
+#define DCHR1				0x194
+#define DDR3_MODE			BIT(8)
 
-#define F10_DCHR_0			0x94
-#define F10_DCHR_1			0x194
+#define DCT_SEL_LO			0x110
+#define dct_sel_baseaddr(pvt)		((pvt)->dct_sel_lo & 0xFFFFF800)
+#define dct_sel_interleave_addr(pvt)	(((pvt)->dct_sel_lo >> 6) & 0x3)
+#define dct_high_range_enabled(pvt)	((pvt)->dct_sel_lo & BIT(0))
+#define dct_interleave_enabled(pvt)	((pvt)->dct_sel_lo & BIT(2))
 
-#define F10_DCHR_FOUR_RANK_DIMM		BIT(18)
-#define DDR3_MODE			BIT(8)
-#define F10_DCHR_MblMode		BIT(6)
+#define dct_ganging_enabled(pvt)	((boot_cpu_data.x86 == 0x10) && ((pvt)->dct_sel_lo & BIT(4)))
 
+#define dct_data_intlv_enabled(pvt)	((pvt)->dct_sel_lo & BIT(5))
+#define dct_memory_cleared(pvt)		((pvt)->dct_sel_lo & BIT(10))
 
-#define F10_DCTL_SEL_LOW		0x110
-#define dct_sel_baseaddr(pvt)		((pvt->dram_ctl_select_low) & 0xFFFFF800)
-#define dct_sel_interleave_addr(pvt)	(((pvt->dram_ctl_select_low) >> 6) & 0x3)
-#define dct_high_range_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(0))
-#define dct_interleave_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(2))
-#define dct_ganging_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(4))
-#define dct_data_intlv_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(5))
-#define dct_dram_enabled(pvt)		(pvt->dram_ctl_select_low & BIT(8))
-#define dct_memory_cleared(pvt)		(pvt->dram_ctl_select_low & BIT(10))
+#define SWAP_INTLV_REG			0x10c
 
-#define F10_DCTL_SEL_HIGH		0x114
+#define DCT_SEL_HI			0x114
 
 /*
  * Function 3 - Misc Control
  */
-#define K8_NBCTL			0x40
-
-/* Correctable ECC error reporting enable */
-#define K8_NBCTL_CECCEn			BIT(0)
-
-/* UnCorrectable ECC error reporting enable */
-#define K8_NBCTL_UECCEn			BIT(1)
+#define NBCTL				0x40
 
-#define K8_NBCFG			0x44
-#define K8_NBCFG_CHIPKILL		BIT(23)
-#define K8_NBCFG_ECC_ENABLE		BIT(22)
+#define NBCFG				0x44
+#define NBCFG_CHIPKILL			BIT(23)
+#define NBCFG_ECC_ENABLE		BIT(22)
 
-#define K8_NBSL				0x48
-
-
-/* Family F10h: Normalized Extended Error Codes */
-#define F10_NBSL_EXT_ERR_RES		0x0
+/* F3x48: NBSL */
 #define F10_NBSL_EXT_ERR_ECC		0x8
+#define NBSL_PP_OBS			0x2
 
-/* Next two are overloaded values */
-#define F10_NBSL_EXT_ERR_LINK_PROTO	0xB
-#define F10_NBSL_EXT_ERR_L3_PROTO	0xB
-
-#define F10_NBSL_EXT_ERR_NB_ARRAY	0xC
-#define F10_NBSL_EXT_ERR_DRAM_PARITY	0xD
-#define F10_NBSL_EXT_ERR_LINK_RETRY	0xE
-
-/* Next two are overloaded values */
-#define F10_NBSL_EXT_ERR_GART_WALK	0xF
-#define F10_NBSL_EXT_ERR_DEV_WALK	0xF
-
-/* 0x10 to 0x1B: Reserved */
-#define F10_NBSL_EXT_ERR_L3_DATA	0x1C
-#define F10_NBSL_EXT_ERR_L3_TAG		0x1D
-#define F10_NBSL_EXT_ERR_L3_LRU		0x1E
-
-/* K8: Normalized Extended Error Codes */
-#define K8_NBSL_EXT_ERR_ECC		0x0
-#define K8_NBSL_EXT_ERR_CRC		0x1
-#define K8_NBSL_EXT_ERR_SYNC		0x2
-#define K8_NBSL_EXT_ERR_MST		0x3
-#define K8_NBSL_EXT_ERR_TGT		0x4
-#define K8_NBSL_EXT_ERR_GART		0x5
-#define K8_NBSL_EXT_ERR_RMW		0x6
-#define K8_NBSL_EXT_ERR_WDT		0x7
-#define K8_NBSL_EXT_ERR_CHIPKILL_ECC	0x8
-#define K8_NBSL_EXT_ERR_DRAM_PARITY	0xD
-
-/*
- * The following are for BUS type errors AFTER values have been normalized by
- * shifting right
- */
-#define K8_NBSL_PP_SRC			0x0
-#define K8_NBSL_PP_RES			0x1
-#define K8_NBSL_PP_OBS			0x2
-#define K8_NBSL_PP_GENERIC		0x3
-
-#define EXTRACT_ERR_CPU_MAP(x)		((x) & 0xF)
-
-#define K8_NBEAL			0x50
-#define K8_NBEAH			0x54
-#define K8_SCRCTRL			0x58
-
-#define F10_NB_CFG_LOW			0x88
+#define SCRCTRL				0x58
 
 #define F10_ONLINE_SPARE		0xB0
-#define F10_ONLINE_SPARE_SWAPDONE0(x)	((x) & BIT(1))
-#define F10_ONLINE_SPARE_SWAPDONE1(x)	((x) & BIT(3))
-#define F10_ONLINE_SPARE_BADDRAM_CS0(x) (((x) >> 4) & 0x00000007)
-#define F10_ONLINE_SPARE_BADDRAM_CS1(x) (((x) >> 8) & 0x00000007)
+#define online_spare_swap_done(pvt, c)	(((pvt)->online_spare >> (1 + 2 * (c))) & 0x1)
+#define online_spare_bad_dramcs(pvt, c)	(((pvt)->online_spare >> (4 + 4 * (c))) & 0x7)
 
 #define F10_NB_ARRAY_ADDR		0xB8
-
-#define F10_NB_ARRAY_DRAM_ECC		0x80000000
+#define F10_NB_ARRAY_DRAM_ECC		BIT(31)
 
 /* Bits [2:1] are used to select 16-byte section within a 64-byte cacheline  */
 #define SET_NB_ARRAY_ADDRESS(section)	(((section) & 0x3) << 1)
 
 #define F10_NB_ARRAY_DATA		0xBC
-
 #define SET_NB_DRAM_INJECTION_WRITE(word, bits)  \
 					(BIT(((word) & 0xF) + 20) | \
 					BIT(17) | bits)
-
 #define SET_NB_DRAM_INJECTION_READ(word, bits)  \
 					(BIT(((word) & 0xF) + 20) | \
 					BIT(16) |  bits)
 
-#define K8_NBCAP			0xE8
-#define K8_NBCAP_CORES			(BIT(12)|BIT(13))
-#define K8_NBCAP_CHIPKILL		BIT(4)
-#define K8_NBCAP_SECDED			BIT(3)
-#define K8_NBCAP_DCT_DUAL		BIT(0)
+#define NBCAP				0xE8
+#define NBCAP_CHIPKILL			BIT(4)
+#define NBCAP_SECDED			BIT(3)
+#define NBCAP_DCT_DUAL			BIT(0)
 
 #define EXT_NB_MCA_CFG			0x180
 
 /* MSRs */
-#define K8_MSR_MCGCTL_NBE		BIT(4)
-
-#define K8_MSR_MC4CTL			0x0410
-#define K8_MSR_MC4STAT			0x0411
-#define K8_MSR_MC4ADDR			0x0412
+#define MSR_MCGCTL_NBE			BIT(4)
 
 /* AMD sets the first MC device at device ID 0x18. */
-static inline int get_node_id(struct pci_dev *pdev)
+static inline u8 get_node_id(struct pci_dev *pdev)
 {
 	return PCI_SLOT(pdev->devfn) - 0x18;
 }
 
-enum amd64_chipset_families {
+enum amd_families {
 	K8_CPUS = 0,
 	F10_CPUS,
+	F15_CPUS,
+	NUM_FAMILIES,
 };
 
 /* Error injection control structure */
@@ -392,13 +307,35 @@ struct error_injection {
 	u32	bit_map;
 };
 
+/* low and high part of PCI config space regs */
+struct reg_pair {
+	u32 lo, hi;
+};
+
+/*
+ * See F1x[1, 0][7C:40] DRAM Base/Limit Registers
+ */
+struct dram_range {
+	struct reg_pair base;
+	struct reg_pair lim;
+};
+
+/* A DCT chip selects collection */
+struct chip_select {
+	u32 csbases[NUM_CHIPSELECTS];
+	u8 b_cnt;
+
+	u32 csmasks[NUM_CHIPSELECTS];
+	u8 m_cnt;
+};
+
 struct amd64_pvt {
 	struct low_ops *ops;
 
 	/* pci_device handles which we utilize */
 	struct pci_dev *F1, *F2, *F3;
 
-	int mc_node_id;		/* MC index of this MC node */
+	unsigned mc_node_id;	/* MC index of this MC node */
 	int ext_model;		/* extended model value of this node */
 	int channel_count;
 
@@ -414,60 +351,50 @@ struct amd64_pvt {
 	u32 dbam0;		/* DRAM Base Address Mapping reg for DCT0 */
 	u32 dbam1;		/* DRAM Base Address Mapping reg for DCT1 */
 
-	/* DRAM CS Base Address Registers F2x[1,0][5C:40] */
-	u32 dcsb0[MAX_CS_COUNT];
-	u32 dcsb1[MAX_CS_COUNT];
-
-	/* DRAM CS Mask Registers F2x[1,0][6C:60] */
-	u32 dcsm0[MAX_CS_COUNT];
-	u32 dcsm1[MAX_CS_COUNT];
-
-	/*
-	 * Decoded parts of DRAM BASE and LIMIT Registers
-	 * F1x[78,70,68,60,58,50,48,40]
-	 */
-	u64 dram_base[DRAM_REG_COUNT];
-	u64 dram_limit[DRAM_REG_COUNT];
-	u8  dram_IntlvSel[DRAM_REG_COUNT];
-	u8  dram_IntlvEn[DRAM_REG_COUNT];
-	u8  dram_DstNode[DRAM_REG_COUNT];
-	u8  dram_rw_en[DRAM_REG_COUNT];
-
-	/*
-	 * The following fields are set at (load) run time, after CPU revision
-	 * has been determined, since the dct_base and dct_mask registers vary
-	 * based on revision
-	 */
-	u32 dcsb_base;		/* DCSB base bits */
-	u32 dcsm_mask;		/* DCSM mask bits */
-	u32 cs_count;		/* num chip selects (== num DCSB registers) */
-	u32 num_dcsm;		/* Number of DCSM registers */
-	u32 dcs_mask_notused;	/* DCSM notused mask bits */
-	u32 dcs_shift;		/* DCSB and DCSM shift value */
+	/* one for each DCT */
+	struct chip_select csels[2];
+
+	/* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */
+	struct dram_range ranges[DRAM_RANGES];
 
 	u64 top_mem;		/* top of memory below 4GB */
 	u64 top_mem2;		/* top of memory above 4GB */
 
-	u32 dram_ctl_select_low;	/* DRAM Controller Select Low Reg */
-	u32 dram_ctl_select_high;	/* DRAM Controller Select High Reg */
-	u32 online_spare;               /* On-Line spare Reg */
+	u32 dct_sel_lo;		/* DRAM Controller Select Low */
+	u32 dct_sel_hi;		/* DRAM Controller Select High */
+	u32 online_spare;	/* On-Line spare Reg */
 
 	/* x4 or x8 syndromes in use */
-	u8 syn_type;
-
-	/* temp storage for when input is received from sysfs */
-	struct err_regs ctl_error_info;
+	u8 ecc_sym_sz;
 
 	/* place to store error injection parameters prior to issue */
 	struct error_injection injection;
+};
 
-	/* DCT per-family scrubrate setting */
-	u32 min_scrubrate;
+static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i)
+{
+	u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
 
-	/* family name this instance is running on */
-	const char *ctl_name;
+	if (boot_cpu_data.x86 == 0xf)
+		return addr;
 
-};
+	return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr;
+}
+
+static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i)
+{
+	u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff;
+
+	if (boot_cpu_data.x86 == 0xf)
+		return lim;
+
+	return (((u64)pvt->ranges[i].lim.hi & 0x000000ff) << 40) | lim;
+}
+
+static inline u16 extract_syndrome(u64 status)
+{
+	return ((status >> 47) & 0xff) | ((status >> 16) & 0xff00);
+}
 
 /*
  * per-node ECC settings descriptor
@@ -482,14 +409,6 @@ struct ecc_settings {
 	} flags;
 };
 
-extern const char *tt_msgs[4];
-extern const char *ll_msgs[4];
-extern const char *rrrr_msgs[16];
-extern const char *to_msgs[2];
-extern const char *pp_msgs[4];
-extern const char *ii_msgs[4];
-extern const char *htlink_msgs[8];
-
 #ifdef CONFIG_EDAC_DEBUG
 #define NUM_DBG_ATTRS 5
 #else
@@ -511,14 +430,11 @@ extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS],
  */
 struct low_ops {
 	int (*early_channel_count)	(struct amd64_pvt *pvt);
-
-	u64 (*get_error_address)	(struct mem_ctl_info *mci,
-					 struct err_regs *info);
-	void (*read_dram_base_limit)	(struct amd64_pvt *pvt, int dram);
-	void (*read_dram_ctl_register)	(struct amd64_pvt *pvt);
-	void (*map_sysaddr_to_csrow)	(struct mem_ctl_info *mci,
-					 struct err_regs *info, u64 SystemAddr);
-	int (*dbam_to_cs)		(struct amd64_pvt *pvt, int cs_mode);
+	void (*map_sysaddr_to_csrow)	(struct mem_ctl_info *mci, u64 sys_addr,
+					 u16 syndrome);
+	int (*dbam_to_cs)		(struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
+	int (*read_dct_pci_cfg)		(struct amd64_pvt *pvt, int offset,
+					 u32 *val, const char *func);
 };
 
 struct amd64_family_type {
@@ -527,28 +443,17 @@ struct amd64_family_type {
 	struct low_ops ops;
 };
 
-static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
-					   u32 *val, const char *func)
-{
-	int err = 0;
-
-	err = pci_read_config_dword(pdev, offset, val);
-	if (err)
-		amd64_warn("%s: error reading F%dx%x.\n",
-			   func, PCI_FUNC(pdev->devfn), offset);
-
-	return err;
-}
+int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
+				u32 val, const char *func);
 
 #define amd64_read_pci_cfg(pdev, offset, val)	\
-	amd64_read_pci_cfg_dword(pdev, offset, val, __func__)
+	__amd64_read_pci_cfg_dword(pdev, offset, val, __func__)
 
-/*
- * For future CPU versions, verify the following as new 'slow' rates appear and
- * modify the necessary skip values for the supported CPU.
- */
-#define K8_MIN_SCRUB_RATE_BITS	0x0
-#define F10_MIN_SCRUB_RATE_BITS	0x5
+#define amd64_write_pci_cfg(pdev, offset, val)	\
+	__amd64_write_pci_cfg_dword(pdev, offset, val, __func__)
+
+#define amd64_read_dct_pci_cfg(pvt, offset, val) \
+	pvt->ops->read_dct_pci_cfg(pvt, offset, val, __func__)
 
 int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base,
 			     u64 *hole_offset, u64 *hole_size);
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c
index 688478d..303f10e 100644
--- a/drivers/edac/amd64_edac_inj.c
+++ b/drivers/edac/amd64_edac_inj.c
@@ -117,13 +117,13 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
 		/* Form value to choose 16-byte section of cacheline */
 		section = F10_NB_ARRAY_DRAM_ECC |
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
+		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
 		word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
 						pvt->injection.bit_map);
 
 		/* Issue 'word' and 'bit' along with the READ request */
-		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
@@ -150,13 +150,13 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
 		/* Form value to choose 16-byte section of cacheline */
 		section = F10_NB_ARRAY_DRAM_ECC |
 				SET_NB_ARRAY_ADDRESS(pvt->injection.section);
-		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section);
+		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_ADDR, section);
 
 		word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
 						pvt->injection.bit_map);
 
 		/* Issue 'word' and 'bit' along with the READ request */
-		pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
+		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 39d97cf..73196f7 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -785,10 +785,10 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
 {
 	int err;
 
-	debugf1("%s()\n", __func__);
+	debugf4("%s()\n", __func__);
 
 	while (sysfs_attrib) {
-		debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
+		debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 		if (sysfs_attrib->grp) {
 			struct mcidev_sysfs_group_kobj *grp_kobj;
 
@@ -818,7 +818,7 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
 			if (err < 0)
 				return err;
 		} else if (sysfs_attrib->attr.name) {
-			debugf0("%s() file %s\n", __func__,
+			debugf4("%s() file %s\n", __func__,
 				sysfs_attrib->attr.name);
 
 			err = sysfs_create_file(kobj, &sysfs_attrib->attr);
@@ -853,26 +853,26 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
 	 * Remove first all the atributes
 	 */
 	while (sysfs_attrib) {
-		debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
+		debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 		if (sysfs_attrib->grp) {
-			debugf1("%s() seeking for group %s\n",
+			debugf4("%s() seeking for group %s\n",
 				__func__, sysfs_attrib->grp->name);
 			list_for_each_entry(grp_kobj,
 					    &mci->grp_kobj_list, list) {
-				debugf1("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
+				debugf4("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
 				if (grp_kobj->grp == sysfs_attrib->grp) {
 					edac_remove_mci_instance_attributes(mci,
 						    grp_kobj->grp->mcidev_attr,
 						    &grp_kobj->kobj, count + 1);
-					debugf0("%s() group %s\n", __func__,
+					debugf4("%s() group %s\n", __func__,
 						sysfs_attrib->grp->name);
 					kobject_put(&grp_kobj->kobj);
 				}
 			}
-			debugf1("%s() end of seeking for group %s\n",
+			debugf4("%s() end of seeking for group %s\n",
 				__func__, sysfs_attrib->grp->name);
 		} else if (sysfs_attrib->attr.name) {
-			debugf0("%s() file %s\n", __func__,
+			debugf4("%s() file %s\n", __func__,
 				sysfs_attrib->attr.name);
 			sysfs_remove_file(kobj, &sysfs_attrib->attr);
 		} else
@@ -979,7 +979,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
 	debugf0("%s()\n", __func__);
 
 	/* remove all csrow kobjects */
-	debugf0("%s()  unregister this mci kobj\n", __func__);
+	debugf4("%s()  unregister this mci kobj\n", __func__);
 	for (i = 0; i < mci->nr_csrows; i++) {
 		if (mci->csrows[i].nr_pages > 0) {
 			debugf0("%s()  unreg csrow-%d\n", __func__, i);
@@ -989,18 +989,18 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
 
 	/* remove this mci instance's attribtes */
 	if (mci->mc_driver_sysfs_attributes) {
-		debugf0("%s()  unregister mci private attributes\n", __func__);
+		debugf4("%s()  unregister mci private attributes\n", __func__);
 		edac_remove_mci_instance_attributes(mci,
 						mci->mc_driver_sysfs_attributes,
 						&mci->edac_mci_kobj, 0);
 	}
 
 	/* remove the symlink */
-	debugf0("%s()  remove_link\n", __func__);
+	debugf4("%s()  remove_link\n", __func__);
 	sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
 
 	/* unregister this instance's kobject */
-	debugf0("%s()  remove_mci_instance\n", __func__);
+	debugf4("%s()  remove_mci_instance\n", __func__);
 	kobject_put(&mci->edac_mci_kobj);
 }
 
diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c
index 05523b5..76d1f57 100644
--- a/drivers/edac/i7300_edac.c
+++ b/drivers/edac/i7300_edac.c
@@ -162,7 +162,7 @@ static struct edac_pci_ctl_info *i7300_pci;
 #define AMBPRESENT_0	0x64
 #define AMBPRESENT_1	0x66
 
-const static u16 mtr_regs[MAX_SLOTS] = {
+static const u16 mtr_regs[MAX_SLOTS] = {
 	0x80, 0x84, 0x88, 0x8c,
 	0x82, 0x86, 0x8a, 0x8e
 };
diff --git a/drivers/edac/i82975x_edac.c b/drivers/edac/i82975x_edac.c
index 3218819..92e65e7 100644
--- a/drivers/edac/i82975x_edac.c
+++ b/drivers/edac/i82975x_edac.c
@@ -160,8 +160,8 @@ NOTE: Only ONE of the three must be enabled
 					 * 3:2  Rank 1 architecture
 					 * 1:0  Rank 0 architecture
 					 *
-					 * 00 => x16 devices; i.e 4 banks
-					 * 01 => x8  devices; i.e 8 banks
+					 * 00 => 4 banks
+					 * 01 => 8 banks
 					 */
 #define I82975X_C0BNKARC	0x10e
 #define I82975X_C1BNKARC	0x18e
@@ -278,6 +278,7 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci,
 		struct i82975x_error_info *info, int handle_errors)
 {
 	int row, multi_chan, chan;
+	unsigned long offst, page;
 
 	multi_chan = mci->csrows[0].nr_channels - 1;
 
@@ -292,17 +293,19 @@ static int i82975x_process_error_info(struct mem_ctl_info *mci,
 		info->errsts = info->errsts2;
 	}
 
-	chan = info->eap & 1;
-	info->eap >>= 1;
-	if (info->xeap )
-		info->eap |= 0x80000000;
-	info->eap >>= PAGE_SHIFT;
-	row = edac_mc_find_csrow_by_page(mci, info->eap);
+	page = (unsigned long) info->eap;
+	if (info->xeap & 1)
+		page |= 0x100000000ul;
+	chan = page & 1;
+	page >>= 1;
+	offst = page & ((1 << PAGE_SHIFT) - 1);
+	page >>= PAGE_SHIFT;
+	row = edac_mc_find_csrow_by_page(mci, page);
 
 	if (info->errsts & 0x0002)
-		edac_mc_handle_ue(mci, info->eap, 0, row, "i82975x UE");
+		edac_mc_handle_ue(mci, page, offst , row, "i82975x UE");
 	else
-		edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+		edac_mc_handle_ce(mci, page, offst, info->derrsyn, row,
 				multi_chan ? chan : 0,
 				"i82975x CE");
 
@@ -344,11 +347,7 @@ static int dual_channel_active(void __iomem *mch_window)
 static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
 {
 	/*
-	 * ASUS P5W DH either does not program this register or programs
-	 * it wrong!
-	 * ECC is possible on i92975x ONLY with DEV_X8 which should mean 'val'
-	 * for each rank should be 01b - the LSB of the word should be 0x55;
-	 * but it reads 0!
+	 * ECC is possible on i92975x ONLY with DEV_X8
 	 */
 	return DEV_X8;
 }
@@ -356,11 +355,15 @@ static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
 static void i82975x_init_csrows(struct mem_ctl_info *mci,
 		struct pci_dev *pdev, void __iomem *mch_window)
 {
+	static const char *labels[4] = {
+							"DIMM A1", "DIMM A2",
+							"DIMM B1", "DIMM B2"
+						};
 	struct csrow_info *csrow;
 	unsigned long last_cumul_size;
 	u8 value;
 	u32 cumul_size;
-	int index;
+	int index, chan;
 
 	last_cumul_size = 0;
 
@@ -369,11 +372,7 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
 	 * The dram row boundary (DRB) reg values are boundary address
 	 * for each DRAM row with a granularity of 32 or 64MB (single/dual
 	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
-	 * contain the total memory contained in all eight rows.
-	 *
-	 * FIXME:
-	 *  EDAC currently works for Dual-channel Interleaved configuration.
-	 *  Other configurations, which the chip supports, need fixing/testing.
+	 * contain the total memory contained in all rows.
 	 *
 	 */
 
@@ -384,8 +383,26 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
 					((index >= 4) ? 0x80 : 0));
 		cumul_size = value;
 		cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT);
+		/*
+		 * Adjust cumul_size w.r.t number of channels
+		 *
+		 */
+		if (csrow->nr_channels > 1)
+			cumul_size <<= 1;
 		debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
 			cumul_size);
+
+		/*
+		 * Initialise dram labels
+		 * index values:
+		 *   [0-7] for single-channel; i.e. csrow->nr_channels = 1
+		 *   [0-3] for dual-channel; i.e. csrow->nr_channels = 2
+		 */
+		for (chan = 0; chan < csrow->nr_channels; chan++)
+			strncpy(csrow->channels[chan].label,
+					labels[(index >> 1) + (chan * 2)],
+					EDAC_MC_LABEL_LEN);
+
 		if (cumul_size == last_cumul_size)
 			continue;	/* not populated */
 
@@ -393,8 +410,8 @@ static void i82975x_init_csrows(struct mem_ctl_info *mci,
 		csrow->last_page = cumul_size - 1;
 		csrow->nr_pages = cumul_size - last_cumul_size;
 		last_cumul_size = cumul_size;
-		csrow->grain = 1 << 7;	/* I82975X_EAP has 128B resolution */
-		csrow->mtype = MEM_DDR; /* i82975x supports only DDR2 */
+		csrow->grain = 1 << 6;	/* I82975X_EAP has 64B resolution */
+		csrow->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
 		csrow->dtype = i82975x_dram_type(mch_window, index);
 		csrow->edac_mode = EDAC_SECDED; /* only supported */
 	}
@@ -515,18 +532,20 @@ static int i82975x_probe1(struct pci_dev *pdev, int dev_idx)
 
 	debugf3("%s(): init mci\n", __func__);
 	mci->dev = &pdev->dev;
-	mci->mtype_cap = MEM_FLAG_DDR;
+	mci->mtype_cap = MEM_FLAG_DDR2;
 	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
 	mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
 	mci->mod_name = EDAC_MOD_STR;
 	mci->mod_ver = I82975X_REVISION;
 	mci->ctl_name = i82975x_devs[dev_idx].ctl_name;
+	mci->dev_name = pci_name(pdev);
 	mci->edac_check = i82975x_check;
 	mci->ctl_page_to_phys = NULL;
 	debugf3("%s(): init pvt\n", __func__);
 	pvt = (struct i82975x_pvt *) mci->pvt_info;
 	pvt->mch_window = mch_window;
 	i82975x_init_csrows(mci, pdev, mch_window);
+	mci->scrub_mode = SCRUB_HW_SRC;
 	i82975x_get_error_info(mci, &discard);  /* clear counters */
 
 	/* finalize this instance of memory controller with edac core */
@@ -664,7 +683,7 @@ module_init(i82975x_init);
 module_exit(i82975x_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arvind R. <arvind@acarlab.com>");
+MODULE_AUTHOR("Arvind R. <arvino55@gmail.com>");
 MODULE_DESCRIPTION("MC support for Intel 82975 memory hub controllers");
 
 module_param(edac_op_state, int, 0444);
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index f6cf73d..795cfbc 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -594,6 +594,7 @@ static bool nb_noop_mce(u16 ec, u8 xec)
 
 void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
 {
+	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u16 ec   = EC(m->status);
 	u8 xec   = XEC(m->status, 0x1f);
 	u32 nbsh = (u32)(m->status >> 32);
@@ -602,9 +603,8 @@ void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
 	pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
 
 	/* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
-	if ((boot_cpu_data.x86 == 0x10) &&
-	    (boot_cpu_data.x86_model > 7)) {
-		if (nbsh & K8_NBSH_ERR_CPU_VAL)
+	if (c->x86 == 0x10 && c->x86_model > 7) {
+		if (nbsh & NBSH_ERR_CPU_VAL)
 			core = nbsh & nb_err_cpumask;
 	} else {
 		u8 assoc_cpus = nbsh & nb_err_cpumask;
@@ -646,7 +646,7 @@ void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
 	if (!fam_ops->nb_mce(ec, xec))
 		goto wrong_nb_mce;
 
-	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
+	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15)
 		if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
 			nb_bus_decoder(node_id, m, nbcfg);
 
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h
index 45dda47..795a320 100644
--- a/drivers/edac/mce_amd.h
+++ b/drivers/edac/mce_amd.h
@@ -31,19 +31,10 @@
 #define R4(x)				(((x) >> 4) & 0xf)
 #define R4_MSG(x)			((R4(x) < 9) ?  rrrr_msgs[R4(x)] : "Wrong R4!")
 
-#define K8_NBSH				0x4C
-
-#define K8_NBSH_VALID_BIT		BIT(31)
-#define K8_NBSH_OVERFLOW		BIT(30)
-#define K8_NBSH_UC_ERR			BIT(29)
-#define K8_NBSH_ERR_EN			BIT(28)
-#define K8_NBSH_MISCV			BIT(27)
-#define K8_NBSH_VALID_ERROR_ADDR	BIT(26)
-#define K8_NBSH_PCC			BIT(25)
-#define K8_NBSH_ERR_CPU_VAL		BIT(24)
-#define K8_NBSH_CECC			BIT(14)
-#define K8_NBSH_UECC			BIT(13)
-#define K8_NBSH_ERR_SCRUBER		BIT(8)
+/*
+ * F3x4C bits (MCi_STATUS' high half)
+ */
+#define NBSH_ERR_CPU_VAL		BIT(24)
 
 enum tt_ids {
 	TT_INSTR = 0,
@@ -86,17 +77,6 @@ extern const char *to_msgs[];
 extern const char *ii_msgs[];
 
 /*
- * relevant NB regs
- */
-struct err_regs {
-	u32 nbcfg;
-	u32 nbsh;
-	u32 nbsl;
-	u32 nbeah;
-	u32 nbeal;
-};
-
-/*
  * per-family decoder ops
  */
 struct amd_decoder_ops {
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index b123bb3..ffb5ad0 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -200,8 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op,
-					   const struct of_device_id *match)
+static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
 	struct edac_pci_ctl_info *pci;
 	struct mpc85xx_pci_pdata *pdata;
@@ -338,7 +337,7 @@ static struct of_device_id mpc85xx_pci_err_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
 
-static struct of_platform_driver mpc85xx_pci_err_driver = {
+static struct platform_driver mpc85xx_pci_err_driver = {
 	.probe = mpc85xx_pci_err_probe,
 	.remove = __devexit_p(mpc85xx_pci_err_remove),
 	.driver = {
@@ -503,8 +502,7 @@ static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_l2_err_probe(struct platform_device *op,
-					  const struct of_device_id *match)
+static int __devinit mpc85xx_l2_err_probe(struct platform_device *op)
 {
 	struct edac_device_ctl_info *edac_dev;
 	struct mpc85xx_l2_pdata *pdata;
@@ -656,7 +654,7 @@ static struct of_device_id mpc85xx_l2_err_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
 
-static struct of_platform_driver mpc85xx_l2_err_driver = {
+static struct platform_driver mpc85xx_l2_err_driver = {
 	.probe = mpc85xx_l2_err_probe,
 	.remove = mpc85xx_l2_err_remove,
 	.driver = {
@@ -956,8 +954,7 @@ static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci)
 	}
 }
 
-static int __devinit mpc85xx_mc_err_probe(struct platform_device *op,
-					  const struct of_device_id *match)
+static int __devinit mpc85xx_mc_err_probe(struct platform_device *op)
 {
 	struct mem_ctl_info *mci;
 	struct mpc85xx_mc_pdata *pdata;
@@ -1136,7 +1133,7 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
 
-static struct of_platform_driver mpc85xx_mc_err_driver = {
+static struct platform_driver mpc85xx_mc_err_driver = {
 	.probe = mpc85xx_mc_err_probe,
 	.remove = mpc85xx_mc_err_remove,
 	.driver = {
@@ -1171,16 +1168,16 @@ static int __init mpc85xx_mc_init(void)
 		break;
 	}
 
-	res = of_register_platform_driver(&mpc85xx_mc_err_driver);
+	res = platform_driver_register(&mpc85xx_mc_err_driver);
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "MC fails to register\n");
 
-	res = of_register_platform_driver(&mpc85xx_l2_err_driver);
+	res = platform_driver_register(&mpc85xx_l2_err_driver);
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
 
 #ifdef CONFIG_PCI
-	res = of_register_platform_driver(&mpc85xx_pci_err_driver);
+	res = platform_driver_register(&mpc85xx_pci_err_driver);
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
 #endif
@@ -1212,10 +1209,10 @@ static void __exit mpc85xx_mc_exit(void)
 	on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
 #endif
 #ifdef CONFIG_PCI
-	of_unregister_platform_driver(&mpc85xx_pci_err_driver);
+	platform_driver_unregister(&mpc85xx_pci_err_driver);
 #endif
-	of_unregister_platform_driver(&mpc85xx_l2_err_driver);
-	of_unregister_platform_driver(&mpc85xx_mc_err_driver);
+	platform_driver_unregister(&mpc85xx_l2_err_driver);
+	platform_driver_unregister(&mpc85xx_mc_err_driver);
 }
 
 module_exit(mpc85xx_mc_exit);
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c
index b9f0c20..c1f0045 100644
--- a/drivers/edac/ppc4xx_edac.c
+++ b/drivers/edac/ppc4xx_edac.c
@@ -184,8 +184,7 @@ struct ppc4xx_ecc_status {
 
 /* Function Prototypes */
 
-static int ppc4xx_edac_probe(struct platform_device *device,
-			     const struct of_device_id *device_id);
+static int ppc4xx_edac_probe(struct platform_device *device)
 static int ppc4xx_edac_remove(struct platform_device *device);
 
 /* Global Variables */
@@ -201,7 +200,7 @@ static struct of_device_id ppc4xx_edac_match[] = {
 	{ }
 };
 
-static struct of_platform_driver ppc4xx_edac_driver = {
+static struct platform_driver ppc4xx_edac_driver = {
 	.probe			= ppc4xx_edac_probe,
 	.remove			= ppc4xx_edac_remove,
 	.driver = {
@@ -997,9 +996,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
  *       initialized.
  * @op: A pointer to the OpenFirmware device tree node associated
  *      with the controller this EDAC instance is bound to.
- * @match: A pointer to the OpenFirmware device tree match
- *         information associated with the controller this EDAC instance
- *         is bound to.
  * @dcr_host: A pointer to the DCR data containing the DCR mapping
  *            for this controller instance.
  * @mcopt1: The 32-bit Memory Controller Option 1 register value
@@ -1015,7 +1011,6 @@ ppc4xx_edac_init_csrows(struct mem_ctl_info *mci, u32 mcopt1)
 static int __devinit
 ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
 		    struct platform_device *op,
-		    const struct of_device_id *match,
 		    const dcr_host_t *dcr_host,
 		    u32 mcopt1)
 {
@@ -1024,7 +1019,7 @@ ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
 	struct ppc4xx_edac_pdata *pdata = NULL;
 	const struct device_node *np = op->dev.of_node;
 
-	if (match == NULL)
+	if (op->dev.of_match == NULL)
 		return -EINVAL;
 
 	/* Initial driver pointers and private data */
@@ -1227,9 +1222,6 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host)
  * ppc4xx_edac_probe - check controller and bind driver
  * @op: A pointer to the OpenFirmware device tree node associated
  *      with the controller being probed for driver binding.
- * @match: A pointer to the OpenFirmware device tree match
- *         information associated with the controller being probed
- *         for driver binding.
  *
  * This routine probes a specific ibm,sdram-4xx-ddr2 controller
  * instance for binding with the driver.
@@ -1237,8 +1229,7 @@ ppc4xx_edac_map_dcrs(const struct device_node *np, dcr_host_t *dcr_host)
  * Returns 0 if the controller instance was successfully bound to the
  * driver; otherwise, < 0 on error.
  */
-static int __devinit
-ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ppc4xx_edac_probe(struct platform_device *op)
 {
 	int status = 0;
 	u32 mcopt1, memcheck;
@@ -1304,7 +1295,7 @@ ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match)
 		goto done;
 	}
 
-	status = ppc4xx_edac_mc_init(mci, op, match, &dcr_host, mcopt1);
+	status = ppc4xx_edac_mc_init(mci, op, &dcr_host, mcopt1);
 
 	if (status) {
 		ppc4xx_edac_mc_printk(KERN_ERR, mci,
@@ -1421,7 +1412,7 @@ ppc4xx_edac_init(void)
 
 	ppc4xx_edac_opstate_init();
 
-	return of_register_platform_driver(&ppc4xx_edac_driver);
+	return platform_driver_register(&ppc4xx_edac_driver);
 }
 
 /**
@@ -1434,7 +1425,7 @@ ppc4xx_edac_init(void)
 static void __exit
 ppc4xx_edac_exit(void)
 {
-	of_unregister_platform_driver(&ppc4xx_edac_driver);
+	platform_driver_unregister(&ppc4xx_edac_driver);
 }
 
 module_init(ppc4xx_edac_init);
diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c
new file mode 100644
index 0000000..1d5cf06
--- /dev/null
+++ b/drivers/edac/tile_edac.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2011 Tilera Corporation. All Rights Reserved.
+ *
+ *   This program is free software; you can redistribute it and/or
+ *   modify it under the terms of the GNU General Public License
+ *   as published by the Free Software Foundation, 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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ * Tilera-specific EDAC driver.
+ *
+ * This source code is derived from the following driver:
+ *
+ * Cell MIC driver for ECC counting
+ *
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ *                <benh@kernel.crashing.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/edac.h>
+#include <hv/hypervisor.h>
+#include <hv/drv_mshim_intf.h>
+
+#include "edac_core.h"
+
+#define DRV_NAME	"tile-edac"
+
+/* Number of cs_rows needed per memory controller on TILEPro. */
+#define TILE_EDAC_NR_CSROWS	1
+
+/* Number of channels per memory controller on TILEPro. */
+#define TILE_EDAC_NR_CHANS	1
+
+/* Granularity of reported error in bytes on TILEPro. */
+#define TILE_EDAC_ERROR_GRAIN	8
+
+/* TILE processor has multiple independent memory controllers. */
+struct platform_device *mshim_pdev[TILE_MAX_MSHIMS];
+
+struct tile_edac_priv {
+	int		hv_devhdl;	/* Hypervisor device handle. */
+	int		node;		/* Memory controller instance #. */
+	unsigned int	ce_count;	/*
+					 * Correctable-error counter
+					 * kept by the driver.
+					 */
+};
+
+static void tile_edac_check(struct mem_ctl_info *mci)
+{
+	struct tile_edac_priv	*priv = mci->pvt_info;
+	struct mshim_mem_error	mem_error;
+
+	if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_error,
+		sizeof(struct mshim_mem_error), MSHIM_MEM_ERROR_OFF) !=
+		sizeof(struct mshim_mem_error)) {
+		pr_err(DRV_NAME ": MSHIM_MEM_ERROR_OFF pread failure.\n");
+		return;
+	}
+
+	/* Check if the current error count is different from the saved one. */
+	if (mem_error.sbe_count != priv->ce_count) {
+		dev_dbg(mci->dev, "ECC CE err on node %d\n", priv->node);
+		priv->ce_count = mem_error.sbe_count;
+		edac_mc_handle_ce(mci, 0, 0, 0, 0, 0, mci->ctl_name);
+	}
+}
+
+/*
+ * Initialize the 'csrows' table within the mci control structure with the
+ * addressing of memory.
+ */
+static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
+{
+	struct csrow_info	*csrow = &mci->csrows[0];
+	struct tile_edac_priv	*priv = mci->pvt_info;
+	struct mshim_mem_info	mem_info;
+
+	if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
+		sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) !=
+		sizeof(struct mshim_mem_info)) {
+		pr_err(DRV_NAME ": MSHIM_MEM_INFO_OFF pread failure.\n");
+		return -1;
+	}
+
+	if (mem_info.mem_ecc)
+		csrow->edac_mode = EDAC_SECDED;
+	else
+		csrow->edac_mode = EDAC_NONE;
+	switch (mem_info.mem_type) {
+	case DDR2:
+		csrow->mtype = MEM_DDR2;
+		break;
+
+	case DDR3:
+		csrow->mtype = MEM_DDR3;
+		break;
+
+	default:
+		return -1;
+	}
+
+	csrow->first_page = 0;
+	csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT;
+	csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+	csrow->grain = TILE_EDAC_ERROR_GRAIN;
+	csrow->dtype = DEV_UNKNOWN;
+
+	return 0;
+}
+
+static int __devinit tile_edac_mc_probe(struct platform_device *pdev)
+{
+	char			hv_file[32];
+	int			hv_devhdl;
+	struct mem_ctl_info	*mci;
+	struct tile_edac_priv	*priv;
+	int			rc;
+
+	sprintf(hv_file, "mshim/%d", pdev->id);
+	hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0);
+	if (hv_devhdl < 0)
+		return -EINVAL;
+
+	/* A TILE MC has a single channel and one chip-select row. */
+	mci = edac_mc_alloc(sizeof(struct tile_edac_priv),
+		TILE_EDAC_NR_CSROWS, TILE_EDAC_NR_CHANS, pdev->id);
+	if (mci == NULL)
+		return -ENOMEM;
+	priv = mci->pvt_info;
+	priv->node = pdev->id;
+	priv->hv_devhdl = hv_devhdl;
+
+	mci->dev = &pdev->dev;
+	mci->mtype_cap = MEM_FLAG_DDR2;
+	mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+
+	mci->mod_name = DRV_NAME;
+	mci->ctl_name = "TILEPro_Memory_Controller";
+	mci->dev_name = dev_name(&pdev->dev);
+	mci->edac_check = tile_edac_check;
+
+	/*
+	 * Initialize the MC control structure 'csrows' table
+	 * with the mapping and control information.
+	 */
+	if (tile_edac_init_csrows(mci)) {
+		/* No csrows found. */
+		mci->edac_cap = EDAC_FLAG_NONE;
+	} else {
+		mci->edac_cap = EDAC_FLAG_SECDED;
+	}
+
+	platform_set_drvdata(pdev, mci);
+
+	/* Register with EDAC core */
+	rc = edac_mc_add_mc(mci);
+	if (rc) {
+		dev_err(&pdev->dev, "failed to register with EDAC core\n");
+		edac_mc_free(mci);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int __devexit tile_edac_mc_remove(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+	edac_mc_del_mc(&pdev->dev);
+	if (mci)
+		edac_mc_free(mci);
+	return 0;
+}
+
+static struct platform_driver tile_edac_mc_driver = {
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tile_edac_mc_probe,
+	.remove		= __devexit_p(tile_edac_mc_remove),
+};
+
+/*
+ * Driver init routine.
+ */
+static int __init tile_edac_init(void)
+{
+	char	hv_file[32];
+	struct platform_device *pdev;
+	int i, err, num = 0;
+
+	/* Only support POLL mode. */
+	edac_op_state = EDAC_OPSTATE_POLL;
+
+	err = platform_driver_register(&tile_edac_mc_driver);
+	if (err)
+		return err;
+
+	for (i = 0; i < TILE_MAX_MSHIMS; i++) {
+		/*
+		 * Not all memory controllers are configured such as in the
+		 * case of a simulator. So we register only those mshims
+		 * that are configured by the hypervisor.
+		 */
+		sprintf(hv_file, "mshim/%d", i);
+		if (hv_dev_open((HV_VirtAddr)hv_file, 0) < 0)
+			continue;
+
+		pdev = platform_device_register_simple(DRV_NAME, i, NULL, 0);
+		if (IS_ERR(pdev))
+			continue;
+		mshim_pdev[i] = pdev;
+		num++;
+	}
+
+	if (num == 0) {
+		platform_driver_unregister(&tile_edac_mc_driver);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/*
+ * Driver cleanup routine.
+ */
+static void __exit tile_edac_exit(void)
+{
+	int i;
+
+	for (i = 0; i < TILE_MAX_MSHIMS; i++) {
+		struct platform_device *pdev = mshim_pdev[i];
+		if (!pdev)
+			continue;
+
+		platform_set_drvdata(pdev, NULL);
+		platform_device_unregister(pdev);
+	}
+	platform_driver_unregister(&tile_edac_mc_driver);
+}
+
+module_init(tile_edac_init);
+module_exit(tile_edac_exit);
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 0c56989..2be6f45 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -75,7 +75,8 @@ config FIREWIRE_NOSY
 	  The following cards are known to be based on PCILynx or PCILynx-2:
 	  IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-2
 	  (PCI card), Newer Technology FireWire 2 Go (CardBus card),
-	  Apple Power Mac G3 blue & white (onboard controller).
+	  Apple Power Mac G3 blue & white and G4 with PCI graphics
+	  (onboard controller).
 
 	  To compile this driver as a module, say M here:  The module will be
 	  called nosy.  Source code of a userspace interface to nosy, called
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index 24ff355..3c44fbc 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -75,6 +75,13 @@ static size_t config_rom_length = 1 + 4 + 1 + 1;
 #define BIB_IRMC		((1) << 31)
 #define NODE_CAPABILITIES	0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
 
+/*
+ * IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms),
+ * but we have to make it longer because there are many devices whose firmware
+ * is just too slow for that.
+ */
+#define DEFAULT_SPLIT_TIMEOUT	(2 * 8000)
+
 #define CANON_OUI		0x000085
 
 static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
@@ -233,7 +240,7 @@ static void br_work(struct work_struct *work)
 
 	/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
 	if (card->reset_jiffies != 0 &&
-	    time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {
+	    time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
 		if (!schedule_delayed_work(&card->br_work, 2 * HZ))
 			fw_card_put(card);
 		return;
@@ -316,7 +323,8 @@ static void bm_work(struct work_struct *work)
 	irm_id   = card->irm_node->node_id;
 	local_id = card->local_node->node_id;
 
-	grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
+	grace = time_after64(get_jiffies_64(),
+			     card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
 
 	if ((is_next_generation(generation, card->bm_generation) &&
 	     !card->bm_abdicate) ||
@@ -511,10 +519,11 @@ void fw_card_initialize(struct fw_card *card,
 	card->device = device;
 	card->current_tlabel = 0;
 	card->tlabel_mask = 0;
-	card->split_timeout_hi = 0;
-	card->split_timeout_lo = 800 << 19;
-	card->split_timeout_cycles = 800;
-	card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10);
+	card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000;
+	card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19;
+	card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT;
+	card->split_timeout_jiffies =
+			DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000);
 	card->color = 0;
 	card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;
 
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 48ae712..62ac111 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -64,6 +64,7 @@ struct client {
 	struct idr resource_idr;
 	struct list_head event_list;
 	wait_queue_head_t wait;
+	wait_queue_head_t tx_flush_wait;
 	u64 bus_reset_closure;
 
 	struct fw_iso_context *iso_context;
@@ -251,6 +252,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
 	idr_init(&client->resource_idr);
 	INIT_LIST_HEAD(&client->event_list);
 	init_waitqueue_head(&client->wait);
+	init_waitqueue_head(&client->tx_flush_wait);
 	INIT_LIST_HEAD(&client->phy_receiver_link);
 	kref_init(&client->kref);
 
@@ -520,10 +522,6 @@ static int release_client_resource(struct client *client, u32 handle,
 static void release_transaction(struct client *client,
 				struct client_resource *resource)
 {
-	struct outbound_transaction_resource *r = container_of(resource,
-			struct outbound_transaction_resource, resource);
-
-	fw_cancel_transaction(client->device->card, &r->transaction);
 }
 
 static void complete_transaction(struct fw_card *card, int rcode,
@@ -540,22 +538,9 @@ static void complete_transaction(struct fw_card *card, int rcode,
 		memcpy(rsp->data, payload, rsp->length);
 
 	spin_lock_irqsave(&client->lock, flags);
-	/*
-	 * 1. If called while in shutdown, the idr tree must be left untouched.
-	 *    The idr handle will be removed and the client reference will be
-	 *    dropped later.
-	 * 2. If the call chain was release_client_resource ->
-	 *    release_transaction -> complete_transaction (instead of a normal
-	 *    conclusion of the transaction), i.e. if this resource was already
-	 *    unregistered from the idr, the client reference will be dropped
-	 *    by release_client_resource and we must not drop it here.
-	 */
-	if (!client->in_shutdown &&
-	    idr_find(&client->resource_idr, e->r.resource.handle)) {
-		idr_remove(&client->resource_idr, e->r.resource.handle);
-		/* Drop the idr's reference */
-		client_put(client);
-	}
+	idr_remove(&client->resource_idr, e->r.resource.handle);
+	if (client->in_shutdown)
+		wake_up(&client->tx_flush_wait);
 	spin_unlock_irqrestore(&client->lock, flags);
 
 	rsp->type = FW_CDEV_EVENT_RESPONSE;
@@ -575,7 +560,7 @@ static void complete_transaction(struct fw_card *card, int rcode,
 		queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
 			    NULL, 0);
 
-	/* Drop the transaction callback's reference */
+	/* Drop the idr's reference */
 	client_put(client);
 }
 
@@ -614,9 +599,6 @@ static int init_request(struct client *client,
 	if (ret < 0)
 		goto failed;
 
-	/* Get a reference for the transaction callback */
-	client_get(client);
-
 	fw_send_request(client->device->card, &e->r.transaction,
 			request->tcode, destination_id, request->generation,
 			speed, request->offset, e->response.data,
@@ -1223,7 +1205,8 @@ static void iso_resource_work(struct work_struct *work)
 	todo = r->todo;
 	/* Allow 1000ms grace period for other reallocations. */
 	if (todo == ISO_RES_ALLOC &&
-	    time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
+	    time_before64(get_jiffies_64(),
+			  client->device->card->reset_jiffies + HZ)) {
 		schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
 		skip = true;
 	} else {
@@ -1678,6 +1661,25 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
 	return ret;
 }
 
+static int is_outbound_transaction_resource(int id, void *p, void *data)
+{
+	struct client_resource *resource = p;
+
+	return resource->release == release_transaction;
+}
+
+static int has_outbound_transactions(struct client *client)
+{
+	int ret;
+
+	spin_lock_irq(&client->lock);
+	ret = idr_for_each(&client->resource_idr,
+			   is_outbound_transaction_resource, NULL);
+	spin_unlock_irq(&client->lock);
+
+	return ret;
+}
+
 static int shutdown_resource(int id, void *p, void *data)
 {
 	struct client_resource *resource = p;
@@ -1713,6 +1715,8 @@ static int fw_device_op_release(struct inode *inode, struct file *file)
 	client->in_shutdown = true;
 	spin_unlock_irq(&client->lock);
 
+	wait_event(client->tx_flush_wait, !has_outbound_transactions(client));
+
 	idr_for_each(&client->resource_idr, shutdown_resource, client);
 	idr_remove_all(&client->resource_idr);
 	idr_destroy(&client->resource_idr);
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 6113b89..9a26243 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -747,7 +747,8 @@ static void fw_device_shutdown(struct work_struct *work)
 		container_of(work, struct fw_device, work.work);
 	int minor = MINOR(device->device.devt);
 
-	if (time_is_after_jiffies(device->card->reset_jiffies + SHUTDOWN_DELAY)
+	if (time_before64(get_jiffies_64(),
+			  device->card->reset_jiffies + SHUTDOWN_DELAY)
 	    && !list_empty(&device->card->link)) {
 		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
 		return;
@@ -954,8 +955,9 @@ static void fw_device_init(struct work_struct *work)
 			device->config_rom_retries++;
 			schedule_delayed_work(&device->work, RETRY_DELAY);
 		} else {
-			fw_notify("giving up on config rom for node id %x\n",
-				  device->node_id);
+			if (device->node->link_on)
+				fw_notify("giving up on config rom for node id %x\n",
+					  device->node_id);
 			if (device->node == device->card->root_node)
 				fw_schedule_bm_work(device->card, 0);
 			fw_device_release(&device->device);
@@ -1168,9 +1170,12 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
 
 	switch (event) {
 	case FW_NODE_CREATED:
-	case FW_NODE_LINK_ON:
-		if (!node->link_on)
-			break;
+		/*
+		 * Attempt to scan the node, regardless whether its self ID has
+		 * the L (link active) flag set or not.  Some broken devices
+		 * send L=0 but have an up-and-running link; others send L=1
+		 * without actually having a link.
+		 */
  create:
 		device = kzalloc(sizeof(*device), GFP_ATOMIC);
 		if (device == NULL)
@@ -1213,6 +1218,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
 		break;
 
 	case FW_NODE_INITIATED_RESET:
+	case FW_NODE_LINK_ON:
 		device = node->data;
 		if (device == NULL)
 			goto create;
@@ -1230,10 +1236,10 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
 		break;
 
 	case FW_NODE_UPDATED:
-		if (!node->link_on || node->data == NULL)
+		device = node->data;
+		if (device == NULL)
 			break;
 
-		device = node->data;
 		device->node_id = node->node_id;
 		smp_wmb();  /* update node_id before generation */
 		device->generation = card->generation;
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index c003fa4..481056d 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -235,45 +235,45 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation,
 static int manage_channel(struct fw_card *card, int irm_id, int generation,
 		u32 channels_mask, u64 offset, bool allocate, __be32 data[2])
 {
-	__be32 c, all, old;
-	int i, ret = -EIO, retry = 5;
+	__be32 bit, all, old;
+	int channel, ret = -EIO, retry = 5;
 
 	old = all = allocate ? cpu_to_be32(~0) : 0;
 
-	for (i = 0; i < 32; i++) {
-		if (!(channels_mask & 1 << i))
+	for (channel = 0; channel < 32; channel++) {
+		if (!(channels_mask & 1 << channel))
 			continue;
 
 		ret = -EBUSY;
 
-		c = cpu_to_be32(1 << (31 - i));
-		if ((old & c) != (all & c))
+		bit = cpu_to_be32(1 << (31 - channel));
+		if ((old & bit) != (all & bit))
 			continue;
 
 		data[0] = old;
-		data[1] = old ^ c;
+		data[1] = old ^ bit;
 		switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP,
 					   irm_id, generation, SCODE_100,
 					   offset, data, 8)) {
 		case RCODE_GENERATION:
 			/* A generation change frees all channels. */
-			return allocate ? -EAGAIN : i;
+			return allocate ? -EAGAIN : channel;
 
 		case RCODE_COMPLETE:
 			if (data[0] == old)
-				return i;
+				return channel;
 
 			old = data[0];
 
 			/* Is the IRM 1394a-2000 compliant? */
-			if ((data[0] & c) == (data[1] & c))
+			if ((data[0] & bit) == (data[1] & bit))
 				continue;
 
 			/* 1394-1995 IRM, fall through to retry. */
 		default:
 			if (retry) {
 				retry--;
-				i--;
+				channel--;
 			} else {
 				ret = -EIO;
 			}
@@ -362,3 +362,4 @@ void fw_iso_resource_manage(struct fw_card *card, int generation,
 		*channel = ret;
 	}
 }
+EXPORT_SYMBOL(fw_iso_resource_manage);
diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c
index 09be1a6..193ed92 100644
--- a/drivers/firewire/core-topology.c
+++ b/drivers/firewire/core-topology.c
@@ -545,7 +545,7 @@ void fw_core_handle_bus_reset(struct fw_card *card, int node_id, int generation,
 	 */
 	smp_wmb();
 	card->generation = generation;
-	card->reset_jiffies = jiffies;
+	card->reset_jiffies = get_jiffies_64();
 	card->bm_node_id  = 0xffff;
 	card->bm_abdicate = bm_abdicate;
 	fw_schedule_bm_work(card, 0);
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index f8dfcf1..25e729c 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -147,9 +147,6 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event);
 /* -iso */
 
 int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
-void fw_iso_resource_manage(struct fw_card *card, int generation,
-			    u64 channels_mask, int *channel, int *bandwidth,
-			    bool allocate, __be32 buffer[2]);
 
 
 /* -topology */
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index bd3c61b..f903d7b6 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -208,9 +208,11 @@ struct fw_ohci {
 	struct context at_request_ctx;
 	struct context at_response_ctx;
 
+	u32 it_context_support;
 	u32 it_context_mask;     /* unoccupied IT contexts */
 	struct iso_context *it_context_list;
 	u64 ir_context_channels; /* unoccupied channels */
+	u32 ir_context_support;
 	u32 ir_context_mask;     /* unoccupied IR contexts */
 	struct iso_context *ir_context_list;
 	u64 mc_channels; /* channels in use by the multichannel IR context */
@@ -338,7 +340,7 @@ static void log_irqs(u32 evt)
 	    !(evt & OHCI1394_busReset))
 		return;
 
-	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
 	    evt & OHCI1394_selfIDComplete	? " selfID"		: "",
 	    evt & OHCI1394_RQPkt		? " AR_req"		: "",
 	    evt & OHCI1394_RSPkt		? " AR_resp"		: "",
@@ -351,6 +353,7 @@ static void log_irqs(u32 evt)
 	    evt & OHCI1394_cycle64Seconds	? " cycle64Seconds"	: "",
 	    evt & OHCI1394_cycleInconsistent	? " cycleInconsistent"	: "",
 	    evt & OHCI1394_regAccessFail	? " regAccessFail"	: "",
+	    evt & OHCI1394_unrecoverableError	? " unrecoverableError"	: "",
 	    evt & OHCI1394_busReset		? " busReset"		: "",
 	    evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
 		    OHCI1394_RSPkt | OHCI1394_reqTxComplete |
@@ -1326,21 +1329,8 @@ static int at_context_queue_packet(struct context *ctx,
 				     DESCRIPTOR_IRQ_ALWAYS |
 				     DESCRIPTOR_BRANCH_ALWAYS);
 
-	/*
-	 * If the controller and packet generations don't match, we need to
-	 * bail out and try again.  If IntEvent.busReset is set, the AT context
-	 * is halted, so appending to the context and trying to run it is
-	 * futile.  Most controllers do the right thing and just flush the AT
-	 * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
-	 * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
-	 * up stalling out.  So we just bail out in software and try again
-	 * later, and everyone is happy.
-	 * FIXME: Test of IntEvent.busReset may no longer be necessary since we
-	 *        flush AT queues in bus_reset_tasklet.
-	 * FIXME: Document how the locking works.
-	 */
-	if (ohci->generation != packet->generation ||
-	    reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+	/* FIXME: Document how the locking works. */
+	if (ohci->generation != packet->generation) {
 		if (packet->payload_mapped)
 			dma_unmap_single(ohci->card.device, payload_bus,
 					 packet->payload_length, DMA_TO_DEVICE);
@@ -1590,6 +1580,47 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
 
 }
 
+static void detect_dead_context(struct fw_ohci *ohci,
+				const char *name, unsigned int regs)
+{
+	u32 ctl;
+
+	ctl = reg_read(ohci, CONTROL_SET(regs));
+	if (ctl & CONTEXT_DEAD) {
+#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
+		fw_error("DMA context %s has stopped, error code: %s\n",
+			 name, evts[ctl & 0x1f]);
+#else
+		fw_error("DMA context %s has stopped, error code: %#x\n",
+			 name, ctl & 0x1f);
+#endif
+	}
+}
+
+static void handle_dead_contexts(struct fw_ohci *ohci)
+{
+	unsigned int i;
+	char name[8];
+
+	detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase);
+	detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase);
+	detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase);
+	detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase);
+	for (i = 0; i < 32; ++i) {
+		if (!(ohci->it_context_support & (1 << i)))
+			continue;
+		sprintf(name, "IT%u", i);
+		detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i));
+	}
+	for (i = 0; i < 32; ++i) {
+		if (!(ohci->ir_context_support & (1 << i)))
+			continue;
+		sprintf(name, "IR%u", i);
+		detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i));
+	}
+	/* TODO: maybe try to flush and restart the dead contexts */
+}
+
 static u32 cycle_timer_ticks(u32 cycle_timer)
 {
 	u32 ticks;
@@ -1904,6 +1935,9 @@ static irqreturn_t irq_handler(int irq, void *data)
 			fw_notify("isochronous cycle inconsistent\n");
 	}
 
+	if (unlikely(event & OHCI1394_unrecoverableError))
+		handle_dead_contexts(ohci);
+
 	if (event & OHCI1394_cycle64Seconds) {
 		spin_lock(&ohci->lock);
 		update_bus_time(ohci);
@@ -2141,7 +2175,9 @@ static int ohci_enable(struct fw_card *card,
 		OHCI1394_selfIDComplete |
 		OHCI1394_regAccessFail |
 		OHCI1394_cycle64Seconds |
-		OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong |
+		OHCI1394_cycleInconsistent |
+		OHCI1394_unrecoverableError |
+		OHCI1394_cycleTooLong |
 		OHCI1394_masterIntEnable;
 	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
 		irqs |= OHCI1394_busReset;
@@ -2657,6 +2693,10 @@ static int ohci_start_iso(struct fw_iso_context *base,
 	u32 control = IR_CONTEXT_ISOCH_HEADER, match;
 	int index;
 
+	/* the controller cannot start without any queued packets */
+	if (ctx->context.last->branch_address == 0)
+		return -ENODATA;
+
 	switch (ctx->base.type) {
 	case FW_ISO_CONTEXT_TRANSMIT:
 		index = ctx - ohci->it_context_list;
@@ -2715,6 +2755,7 @@ static int ohci_stop_iso(struct fw_iso_context *base)
 	}
 	flush_writes(ohci);
 	context_stop(&ctx->context);
+	tasklet_kill(&ctx->context.tasklet);
 
 	return 0;
 }
@@ -3207,15 +3248,17 @@ static int __devinit pci_probe(struct pci_dev *dev,
 
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
 	ohci->ir_context_channels = ~0ULL;
-	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+	ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
+	ohci->ir_context_mask = ohci->ir_context_support;
 	ohci->n_ir = hweight32(ohci->ir_context_mask);
 	size = sizeof(struct iso_context) * ohci->n_ir;
 	ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
 
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
-	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+	ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
+	ohci->it_context_mask = ohci->it_context_support;
 	ohci->n_it = hweight32(ohci->it_context_mask);
 	size = sizeof(struct iso_context) * ohci->n_it;
 	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
@@ -3266,7 +3309,7 @@ static int __devinit pci_probe(struct pci_dev *dev,
  fail_disable:
 	pci_disable_device(dev);
  fail_free:
-	kfree(&ohci->card);
+	kfree(ohci);
 	pmac_ohci_off(dev);
  fail:
 	if (err == -ENOMEM)
@@ -3310,7 +3353,7 @@ static void pci_remove(struct pci_dev *dev)
 	pci_iounmap(dev, ohci->registers);
 	pci_release_region(dev, 0);
 	pci_disable_device(dev);
-	kfree(&ohci->card);
+	kfree(ohci);
 	pmac_ohci_off(dev);
 
 	fw_notify("Removed fw-ohci device.\n");
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index afa576a..77ed589 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -472,18 +472,12 @@ static void complete_transaction(struct fw_card *card, int rcode,
 	 * So this callback only sets the rcode if it hasn't already
 	 * been set and only does the cleanup if the transaction
 	 * failed and we didn't already get a status write.
-	 *
-	 * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some
-	 * OXUF936QSE firmwares occasionally respond after Split_Timeout and
-	 * complete the ORB just fine.  Note, we also get RCODE_CANCELLED
-	 * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0.
 	 */
 	spin_lock_irqsave(&card->lock, flags);
 
 	if (orb->rcode == -1)
 		orb->rcode = rcode;
-
-	if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) {
+	if (orb->rcode != RCODE_COMPLETE) {
 		list_del(&orb->link);
 		spin_unlock_irqrestore(&card->lock, flags);
 
@@ -532,7 +526,8 @@ static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
 
 	list_for_each_entry_safe(orb, next, &list, link) {
 		retval = 0;
-		fw_cancel_transaction(device->card, &orb->t);
+		if (fw_cancel_transaction(device->card, &orb->t) == 0)
+			continue;
 
 		orb->rcode = RCODE_CANCELLED;
 		orb->callback(orb, NULL);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index e710424..b3a25a5 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -113,6 +113,17 @@ config DMIID
 	  information from userspace through /sys/class/dmi/id/ or if you want
 	  DMI-based module auto-loading.
 
+config DMI_SYSFS
+	tristate "DMI table support in sysfs"
+	depends on SYSFS && DMI
+	default n
+	help
+	  Say Y or M here to enable the exporting of the raw DMI table
+	  data via sysfs.  This is useful for consuming the data without
+	  requiring any access to /dev/mem at all.  Tables are found
+	  under /sys/firmware/dmi when this option is enabled and
+	  loaded.
+
 config ISCSI_IBFT_FIND
 	bool "iSCSI Boot Firmware Table Attributes"
 	depends on X86
@@ -134,4 +145,16 @@ config ISCSI_IBFT
 	  detect iSCSI boot parameters dynamically during system boot, say Y.
 	  Otherwise, say N.
 
+config SIGMA
+	tristate "SigmaStudio firmware loader"
+	depends on I2C
+	select CRC32
+	default n
+	help
+	  Enable helper functions for working with Analog Devices SigmaDSP
+	  parts and binary firmwares produced by Analog Devices SigmaStudio.
+
+	  If unsure, say N here.  Drivers that need these helpers will select
+	  this option automatically.
+
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 1c3c173..00bb0b8 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the linux kernel.
 #
 obj-$(CONFIG_DMI)		+= dmi_scan.o
+obj-$(CONFIG_DMI_SYSFS)		+= dmi-sysfs.o
 obj-$(CONFIG_EDD)		+= edd.o
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_EFI_PCDP)		+= pcdp.o
@@ -11,3 +12,4 @@ obj-$(CONFIG_DMIID)		+= dmi-id.o
 obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
+obj-$(CONFIG_SIGMA)		+= sigma.o
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c
index 69ad529..ea5ac2d 100644
--- a/drivers/firmware/dcdbas.c
+++ b/drivers/firmware/dcdbas.c
@@ -268,8 +268,10 @@ int dcdbas_smi_request(struct smi_cmd *smi_cmd)
 	}
 
 	/* generate SMI */
+	/* inb to force posted write through and make SMI happen now */
 	asm volatile (
-		"outb %b0,%w1"
+		"outb %b0,%w1\n"
+		"inb %w1"
 		: /* no output args */
 		: "a" (smi_cmd->command_code),
 		  "d" (smi_cmd->command_address),
diff --git a/drivers/firmware/dmi-sysfs.c b/drivers/firmware/dmi-sysfs.c
new file mode 100644
index 0000000..eb26d62
--- /dev/null
+++ b/drivers/firmware/dmi-sysfs.c
@@ -0,0 +1,696 @@
+/*
+ * dmi-sysfs.c
+ *
+ * This module exports the DMI tables read-only to userspace through the
+ * sysfs file system.
+ *
+ * Data is currently found below
+ *    /sys/firmware/dmi/...
+ *
+ * DMI attributes are presented in attribute files with names
+ * formatted using %d-%d, so that the first integer indicates the
+ * structure type (0-255), and the second field is the instance of that
+ * entry.
+ *
+ * Copyright 2011 Google, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kobject.h>
+#include <linux/dmi.h>
+#include <linux/capability.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#define MAX_ENTRY_TYPE 255 /* Most of these aren't used, but we consider
+			      the top entry type is only 8 bits */
+
+struct dmi_sysfs_entry {
+	struct dmi_header dh;
+	struct kobject kobj;
+	int instance;
+	int position;
+	struct list_head list;
+	struct kobject *child;
+};
+
+/*
+ * Global list of dmi_sysfs_entry.  Even though this should only be
+ * manipulated at setup and teardown, the lazy nature of the kobject
+ * system means we get lazy removes.
+ */
+static LIST_HEAD(entry_list);
+static DEFINE_SPINLOCK(entry_list_lock);
+
+/* dmi_sysfs_attribute - Top level attribute. used by all entries. */
+struct dmi_sysfs_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct dmi_sysfs_entry *entry, char *buf);
+};
+
+#define DMI_SYSFS_ATTR(_entry, _name) \
+struct dmi_sysfs_attribute dmi_sysfs_attr_##_entry##_##_name = { \
+	.attr = {.name = __stringify(_name), .mode = 0400}, \
+	.show = dmi_sysfs_##_entry##_##_name, \
+}
+
+/*
+ * dmi_sysfs_mapped_attribute - Attribute where we require the entry be
+ * mapped in.  Use in conjunction with dmi_sysfs_specialize_attr_ops.
+ */
+struct dmi_sysfs_mapped_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct dmi_sysfs_entry *entry,
+			const struct dmi_header *dh,
+			char *buf);
+};
+
+#define DMI_SYSFS_MAPPED_ATTR(_entry, _name) \
+struct dmi_sysfs_mapped_attribute dmi_sysfs_attr_##_entry##_##_name = { \
+	.attr = {.name = __stringify(_name), .mode = 0400}, \
+	.show = dmi_sysfs_##_entry##_##_name, \
+}
+
+/*************************************************
+ * Generic DMI entry support.
+ *************************************************/
+static void dmi_entry_free(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
+static struct dmi_sysfs_entry *to_entry(struct kobject *kobj)
+{
+	return container_of(kobj, struct dmi_sysfs_entry, kobj);
+}
+
+static struct dmi_sysfs_attribute *to_attr(struct attribute *attr)
+{
+	return container_of(attr, struct dmi_sysfs_attribute, attr);
+}
+
+static ssize_t dmi_sysfs_attr_show(struct kobject *kobj,
+				   struct attribute *_attr, char *buf)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj);
+	struct dmi_sysfs_attribute *attr = to_attr(_attr);
+
+	/* DMI stuff is only ever admin visible */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	return attr->show(entry, buf);
+}
+
+static const struct sysfs_ops dmi_sysfs_attr_ops = {
+	.show = dmi_sysfs_attr_show,
+};
+
+typedef ssize_t (*dmi_callback)(struct dmi_sysfs_entry *,
+				const struct dmi_header *dh, void *);
+
+struct find_dmi_data {
+	struct dmi_sysfs_entry	*entry;
+	dmi_callback		callback;
+	void			*private;
+	int			instance_countdown;
+	ssize_t			ret;
+};
+
+static void find_dmi_entry_helper(const struct dmi_header *dh,
+				  void *_data)
+{
+	struct find_dmi_data *data = _data;
+	struct dmi_sysfs_entry *entry = data->entry;
+
+	/* Is this the entry we want? */
+	if (dh->type != entry->dh.type)
+		return;
+
+	if (data->instance_countdown != 0) {
+		/* try the next instance? */
+		data->instance_countdown--;
+		return;
+	}
+
+	/*
+	 * Don't ever revisit the instance.  Short circuit later
+	 * instances by letting the instance_countdown run negative
+	 */
+	data->instance_countdown--;
+
+	/* Found the entry */
+	data->ret = data->callback(entry, dh, data->private);
+}
+
+/* State for passing the read parameters through dmi_find_entry() */
+struct dmi_read_state {
+	char *buf;
+	loff_t pos;
+	size_t count;
+};
+
+static ssize_t find_dmi_entry(struct dmi_sysfs_entry *entry,
+			      dmi_callback callback, void *private)
+{
+	struct find_dmi_data data = {
+		.entry = entry,
+		.callback = callback,
+		.private = private,
+		.instance_countdown = entry->instance,
+		.ret = -EIO,  /* To signal the entry disappeared */
+	};
+	int ret;
+
+	ret = dmi_walk(find_dmi_entry_helper, &data);
+	/* This shouldn't happen, but just in case. */
+	if (ret)
+		return -EINVAL;
+	return data.ret;
+}
+
+/*
+ * Calculate and return the byte length of the dmi entry identified by
+ * dh.  This includes both the formatted portion as well as the
+ * unformatted string space, including the two trailing nul characters.
+ */
+static size_t dmi_entry_length(const struct dmi_header *dh)
+{
+	const char *p = (const char *)dh;
+
+	p += dh->length;
+
+	while (p[0] || p[1])
+		p++;
+
+	return 2 + p - (const char *)dh;
+}
+
+/*************************************************
+ * Support bits for specialized DMI entry support
+ *************************************************/
+struct dmi_entry_attr_show_data {
+	struct attribute *attr;
+	char *buf;
+};
+
+static ssize_t dmi_entry_attr_show_helper(struct dmi_sysfs_entry *entry,
+					  const struct dmi_header *dh,
+					  void *_data)
+{
+	struct dmi_entry_attr_show_data *data = _data;
+	struct dmi_sysfs_mapped_attribute *attr;
+
+	attr = container_of(data->attr,
+			    struct dmi_sysfs_mapped_attribute, attr);
+	return attr->show(entry, dh, data->buf);
+}
+
+static ssize_t dmi_entry_attr_show(struct kobject *kobj,
+				   struct attribute *attr,
+				   char *buf)
+{
+	struct dmi_entry_attr_show_data data = {
+		.attr = attr,
+		.buf  = buf,
+	};
+	/* Find the entry according to our parent and call the
+	 * normalized show method hanging off of the attribute */
+	return find_dmi_entry(to_entry(kobj->parent),
+			      dmi_entry_attr_show_helper, &data);
+}
+
+static const struct sysfs_ops dmi_sysfs_specialize_attr_ops = {
+	.show = dmi_entry_attr_show,
+};
+
+/*************************************************
+ * Specialized DMI entry support.
+ *************************************************/
+
+/*** Type 15 - System Event Table ***/
+
+#define DMI_SEL_ACCESS_METHOD_IO8	0x00
+#define DMI_SEL_ACCESS_METHOD_IO2x8	0x01
+#define DMI_SEL_ACCESS_METHOD_IO16	0x02
+#define DMI_SEL_ACCESS_METHOD_PHYS32	0x03
+#define DMI_SEL_ACCESS_METHOD_GPNV	0x04
+
+struct dmi_system_event_log {
+	struct dmi_header header;
+	u16	area_length;
+	u16	header_start_offset;
+	u16	data_start_offset;
+	u8	access_method;
+	u8	status;
+	u32	change_token;
+	union {
+		struct {
+			u16 index_addr;
+			u16 data_addr;
+		} io;
+		u32	phys_addr32;
+		u16	gpnv_handle;
+		u32	access_method_address;
+	};
+	u8	header_format;
+	u8	type_descriptors_supported_count;
+	u8	per_log_type_descriptor_length;
+	u8	supported_log_type_descriptos[0];
+} __packed;
+
+#define DMI_SYSFS_SEL_FIELD(_field) \
+static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \
+				      const struct dmi_header *dh, \
+				      char *buf) \
+{ \
+	struct dmi_system_event_log sel; \
+	if (sizeof(sel) > dmi_entry_length(dh)) \
+		return -EIO; \
+	memcpy(&sel, dh, sizeof(sel)); \
+	return sprintf(buf, "%u\n", sel._field); \
+} \
+static DMI_SYSFS_MAPPED_ATTR(sel, _field)
+
+DMI_SYSFS_SEL_FIELD(area_length);
+DMI_SYSFS_SEL_FIELD(header_start_offset);
+DMI_SYSFS_SEL_FIELD(data_start_offset);
+DMI_SYSFS_SEL_FIELD(access_method);
+DMI_SYSFS_SEL_FIELD(status);
+DMI_SYSFS_SEL_FIELD(change_token);
+DMI_SYSFS_SEL_FIELD(access_method_address);
+DMI_SYSFS_SEL_FIELD(header_format);
+DMI_SYSFS_SEL_FIELD(type_descriptors_supported_count);
+DMI_SYSFS_SEL_FIELD(per_log_type_descriptor_length);
+
+static struct attribute *dmi_sysfs_sel_attrs[] = {
+	&dmi_sysfs_attr_sel_area_length.attr,
+	&dmi_sysfs_attr_sel_header_start_offset.attr,
+	&dmi_sysfs_attr_sel_data_start_offset.attr,
+	&dmi_sysfs_attr_sel_access_method.attr,
+	&dmi_sysfs_attr_sel_status.attr,
+	&dmi_sysfs_attr_sel_change_token.attr,
+	&dmi_sysfs_attr_sel_access_method_address.attr,
+	&dmi_sysfs_attr_sel_header_format.attr,
+	&dmi_sysfs_attr_sel_type_descriptors_supported_count.attr,
+	&dmi_sysfs_attr_sel_per_log_type_descriptor_length.attr,
+	NULL,
+};
+
+
+static struct kobj_type dmi_system_event_log_ktype = {
+	.release = dmi_entry_free,
+	.sysfs_ops = &dmi_sysfs_specialize_attr_ops,
+	.default_attrs = dmi_sysfs_sel_attrs,
+};
+
+typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
+			    loff_t offset);
+
+static DEFINE_MUTEX(io_port_lock);
+
+static u8 read_sel_8bit_indexed_io(const struct dmi_system_event_log *sel,
+				   loff_t offset)
+{
+	u8 ret;
+
+	mutex_lock(&io_port_lock);
+	outb((u8)offset, sel->io.index_addr);
+	ret = inb(sel->io.data_addr);
+	mutex_unlock(&io_port_lock);
+	return ret;
+}
+
+static u8 read_sel_2x8bit_indexed_io(const struct dmi_system_event_log *sel,
+				     loff_t offset)
+{
+	u8 ret;
+
+	mutex_lock(&io_port_lock);
+	outb((u8)offset, sel->io.index_addr);
+	outb((u8)(offset >> 8), sel->io.index_addr + 1);
+	ret = inb(sel->io.data_addr);
+	mutex_unlock(&io_port_lock);
+	return ret;
+}
+
+static u8 read_sel_16bit_indexed_io(const struct dmi_system_event_log *sel,
+				    loff_t offset)
+{
+	u8 ret;
+
+	mutex_lock(&io_port_lock);
+	outw((u16)offset, sel->io.index_addr);
+	ret = inb(sel->io.data_addr);
+	mutex_unlock(&io_port_lock);
+	return ret;
+}
+
+static sel_io_reader sel_io_readers[] = {
+	[DMI_SEL_ACCESS_METHOD_IO8]	= read_sel_8bit_indexed_io,
+	[DMI_SEL_ACCESS_METHOD_IO2x8]	= read_sel_2x8bit_indexed_io,
+	[DMI_SEL_ACCESS_METHOD_IO16]	= read_sel_16bit_indexed_io,
+};
+
+static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
+				   const struct dmi_system_event_log *sel,
+				   char *buf, loff_t pos, size_t count)
+{
+	ssize_t wrote = 0;
+
+	sel_io_reader io_reader = sel_io_readers[sel->access_method];
+
+	while (count && pos < sel->area_length) {
+		count--;
+		*(buf++) = io_reader(sel, pos++);
+		wrote++;
+	}
+
+	return wrote;
+}
+
+static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
+				       const struct dmi_system_event_log *sel,
+				       char *buf, loff_t pos, size_t count)
+{
+	u8 __iomem *mapped;
+	ssize_t wrote = 0;
+
+	mapped = ioremap(sel->access_method_address, sel->area_length);
+	if (!mapped)
+		return -EIO;
+
+	while (count && pos < sel->area_length) {
+		count--;
+		*(buf++) = readb(mapped + pos++);
+		wrote++;
+	}
+
+	iounmap(mapped);
+	return wrote;
+}
+
+static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
+				       const struct dmi_header *dh,
+				       void *_state)
+{
+	struct dmi_read_state *state = _state;
+	struct dmi_system_event_log sel;
+
+	if (sizeof(sel) > dmi_entry_length(dh))
+		return -EIO;
+
+	memcpy(&sel, dh, sizeof(sel));
+
+	switch (sel.access_method) {
+	case DMI_SEL_ACCESS_METHOD_IO8:
+	case DMI_SEL_ACCESS_METHOD_IO2x8:
+	case DMI_SEL_ACCESS_METHOD_IO16:
+		return dmi_sel_raw_read_io(entry, &sel, state->buf,
+					   state->pos, state->count);
+	case DMI_SEL_ACCESS_METHOD_PHYS32:
+		return dmi_sel_raw_read_phys32(entry, &sel, state->buf,
+					       state->pos, state->count);
+	case DMI_SEL_ACCESS_METHOD_GPNV:
+		pr_info("dmi-sysfs: GPNV support missing.\n");
+		return -EIO;
+	default:
+		pr_info("dmi-sysfs: Unknown access method %02x\n",
+			sel.access_method);
+		return -EIO;
+	}
+}
+
+static ssize_t dmi_sel_raw_read(struct file *filp, struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t count)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj->parent);
+	struct dmi_read_state state = {
+		.buf = buf,
+		.pos = pos,
+		.count = count,
+	};
+
+	return find_dmi_entry(entry, dmi_sel_raw_read_helper, &state);
+}
+
+static struct bin_attribute dmi_sel_raw_attr = {
+	.attr = {.name = "raw_event_log", .mode = 0400},
+	.read = dmi_sel_raw_read,
+};
+
+static int dmi_system_event_log(struct dmi_sysfs_entry *entry)
+{
+	int ret;
+
+	entry->child = kzalloc(sizeof(*entry->child), GFP_KERNEL);
+	if (!entry->child)
+		return -ENOMEM;
+	ret = kobject_init_and_add(entry->child,
+				   &dmi_system_event_log_ktype,
+				   &entry->kobj,
+				   "system_event_log");
+	if (ret)
+		goto out_free;
+
+	ret = sysfs_create_bin_file(entry->child, &dmi_sel_raw_attr);
+	if (ret)
+		goto out_del;
+
+	return 0;
+
+out_del:
+	kobject_del(entry->child);
+out_free:
+	kfree(entry->child);
+	return ret;
+}
+
+/*************************************************
+ * Generic DMI entry support.
+ *************************************************/
+
+static ssize_t dmi_sysfs_entry_length(struct dmi_sysfs_entry *entry, char *buf)
+{
+	return sprintf(buf, "%d\n", entry->dh.length);
+}
+
+static ssize_t dmi_sysfs_entry_handle(struct dmi_sysfs_entry *entry, char *buf)
+{
+	return sprintf(buf, "%d\n", entry->dh.handle);
+}
+
+static ssize_t dmi_sysfs_entry_type(struct dmi_sysfs_entry *entry, char *buf)
+{
+	return sprintf(buf, "%d\n", entry->dh.type);
+}
+
+static ssize_t dmi_sysfs_entry_instance(struct dmi_sysfs_entry *entry,
+					char *buf)
+{
+	return sprintf(buf, "%d\n", entry->instance);
+}
+
+static ssize_t dmi_sysfs_entry_position(struct dmi_sysfs_entry *entry,
+					char *buf)
+{
+	return sprintf(buf, "%d\n", entry->position);
+}
+
+static DMI_SYSFS_ATTR(entry, length);
+static DMI_SYSFS_ATTR(entry, handle);
+static DMI_SYSFS_ATTR(entry, type);
+static DMI_SYSFS_ATTR(entry, instance);
+static DMI_SYSFS_ATTR(entry, position);
+
+static struct attribute *dmi_sysfs_entry_attrs[] = {
+	&dmi_sysfs_attr_entry_length.attr,
+	&dmi_sysfs_attr_entry_handle.attr,
+	&dmi_sysfs_attr_entry_type.attr,
+	&dmi_sysfs_attr_entry_instance.attr,
+	&dmi_sysfs_attr_entry_position.attr,
+	NULL,
+};
+
+static ssize_t dmi_entry_raw_read_helper(struct dmi_sysfs_entry *entry,
+					 const struct dmi_header *dh,
+					 void *_state)
+{
+	struct dmi_read_state *state = _state;
+	size_t entry_length;
+
+	entry_length = dmi_entry_length(dh);
+
+	return memory_read_from_buffer(state->buf, state->count,
+				       &state->pos, dh, entry_length);
+}
+
+static ssize_t dmi_entry_raw_read(struct file *filp,
+				  struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buf, loff_t pos, size_t count)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj);
+	struct dmi_read_state state = {
+		.buf = buf,
+		.pos = pos,
+		.count = count,
+	};
+
+	return find_dmi_entry(entry, dmi_entry_raw_read_helper, &state);
+}
+
+static const struct bin_attribute dmi_entry_raw_attr = {
+	.attr = {.name = "raw", .mode = 0400},
+	.read = dmi_entry_raw_read,
+};
+
+static void dmi_sysfs_entry_release(struct kobject *kobj)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj);
+	sysfs_remove_bin_file(&entry->kobj, &dmi_entry_raw_attr);
+	spin_lock(&entry_list_lock);
+	list_del(&entry->list);
+	spin_unlock(&entry_list_lock);
+	kfree(entry);
+}
+
+static struct kobj_type dmi_sysfs_entry_ktype = {
+	.release = dmi_sysfs_entry_release,
+	.sysfs_ops = &dmi_sysfs_attr_ops,
+	.default_attrs = dmi_sysfs_entry_attrs,
+};
+
+static struct kobject *dmi_kobj;
+static struct kset *dmi_kset;
+
+/* Global count of all instances seen.  Only for setup */
+static int __initdata instance_counts[MAX_ENTRY_TYPE + 1];
+
+/* Global positional count of all entries seen.  Only for setup */
+static int __initdata position_count;
+
+static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,
+					     void *_ret)
+{
+	struct dmi_sysfs_entry *entry;
+	int *ret = _ret;
+
+	/* If a previous entry saw an error, short circuit */
+	if (*ret)
+		return;
+
+	/* Allocate and register a new entry into the entries set */
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		*ret = -ENOMEM;
+		return;
+	}
+
+	/* Set the key */
+	memcpy(&entry->dh, dh, sizeof(*dh));
+	entry->instance = instance_counts[dh->type]++;
+	entry->position = position_count++;
+
+	entry->kobj.kset = dmi_kset;
+	*ret = kobject_init_and_add(&entry->kobj, &dmi_sysfs_entry_ktype, NULL,
+				    "%d-%d", dh->type, entry->instance);
+
+	if (*ret) {
+		kfree(entry);
+		return;
+	}
+
+	/* Thread on the global list for cleanup */
+	spin_lock(&entry_list_lock);
+	list_add_tail(&entry->list, &entry_list);
+	spin_unlock(&entry_list_lock);
+
+	/* Handle specializations by type */
+	switch (dh->type) {
+	case DMI_ENTRY_SYSTEM_EVENT_LOG:
+		*ret = dmi_system_event_log(entry);
+		break;
+	default:
+		/* No specialization */
+		break;
+	}
+	if (*ret)
+		goto out_err;
+
+	/* Create the raw binary file to access the entry */
+	*ret = sysfs_create_bin_file(&entry->kobj, &dmi_entry_raw_attr);
+	if (*ret)
+		goto out_err;
+
+	return;
+out_err:
+	kobject_put(entry->child);
+	kobject_put(&entry->kobj);
+	return;
+}
+
+static void cleanup_entry_list(void)
+{
+	struct dmi_sysfs_entry *entry, *next;
+
+	/* No locks, we are on our way out */
+	list_for_each_entry_safe(entry, next, &entry_list, list) {
+		kobject_put(entry->child);
+		kobject_put(&entry->kobj);
+	}
+}
+
+static int __init dmi_sysfs_init(void)
+{
+	int error = -ENOMEM;
+	int val;
+
+	/* Set up our directory */
+	dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
+	if (!dmi_kobj)
+		goto err;
+
+	dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
+	if (!dmi_kset)
+		goto err;
+
+	val = 0;
+	error = dmi_walk(dmi_sysfs_register_handle, &val);
+	if (error)
+		goto err;
+	if (val) {
+		error = val;
+		goto err;
+	}
+
+	pr_debug("dmi-sysfs: loaded.\n");
+
+	return 0;
+err:
+	cleanup_entry_list();
+	kset_unregister(dmi_kset);
+	kobject_put(dmi_kobj);
+	return error;
+}
+
+/* clean up everything. */
+static void __exit dmi_sysfs_exit(void)
+{
+	pr_debug("dmi-sysfs: unloading.\n");
+	cleanup_entry_list();
+	kset_unregister(dmi_kset);
+	kobject_put(dmi_kobj);
+}
+
+module_init(dmi_sysfs_init);
+module_exit(dmi_sysfs_exit);
+
+MODULE_AUTHOR("Mike Waychison <mikew@google.com>");
+MODULE_DESCRIPTION("DMI sysfs support");
+MODULE_LICENSE("GPL");
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 2a62ec6..ff0c373 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -90,17 +90,6 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(EFIVARS_VERSION);
 
 /*
- * efivars_lock protects two things:
- * 1) efivar_list - adds, removals, reads, writes
- * 2) efi.[gs]et_variable() calls.
- * It must not be held when creating sysfs entries or calling kmalloc.
- * efi.get_next_variable() is only called from efivars_init(),
- * which is protected by the BKL, so that path is safe.
- */
-static DEFINE_SPINLOCK(efivars_lock);
-static LIST_HEAD(efivar_list);
-
-/*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
  * space in each part of the structure,
@@ -118,6 +107,7 @@ struct efi_variable {
 
 
 struct efivar_entry {
+	struct efivars *efivars;
 	struct efi_variable var;
 	struct list_head list;
 	struct kobject kobj;
@@ -144,9 +134,10 @@ struct efivar_attribute efivar_attr_##_name = { \
  * Prototype for sysfs creation function
  */
 static int
-efivar_create_sysfs_entry(unsigned long variable_name_size,
-				efi_char16_t *variable_name,
-				efi_guid_t *vendor_guid);
+efivar_create_sysfs_entry(struct efivars *efivars,
+			  unsigned long variable_name_size,
+			  efi_char16_t *variable_name,
+			  efi_guid_t *vendor_guid);
 
 /* Return the number of unicode characters in data */
 static unsigned long
@@ -170,18 +161,18 @@ utf8_strsize(efi_char16_t *data, unsigned long maxlength)
 }
 
 static efi_status_t
-get_var_data(struct efi_variable *var)
+get_var_data(struct efivars *efivars, struct efi_variable *var)
 {
 	efi_status_t status;
 
-	spin_lock(&efivars_lock);
+	spin_lock(&efivars->lock);
 	var->DataSize = 1024;
-	status = efi.get_variable(var->VariableName,
-				&var->VendorGuid,
-				&var->Attributes,
-				&var->DataSize,
-				var->Data);
-	spin_unlock(&efivars_lock);
+	status = efivars->ops->get_variable(var->VariableName,
+					    &var->VendorGuid,
+					    &var->Attributes,
+					    &var->DataSize,
+					    var->Data);
+	spin_unlock(&efivars->lock);
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
 			status);
@@ -215,7 +206,7 @@ efivar_attr_read(struct efivar_entry *entry, char *buf)
 	if (!entry || !buf)
 		return -EINVAL;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -238,7 +229,7 @@ efivar_size_read(struct efivar_entry *entry, char *buf)
 	if (!entry || !buf)
 		return -EINVAL;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -255,7 +246,7 @@ efivar_data_read(struct efivar_entry *entry, char *buf)
 	if (!entry || !buf)
 		return -EINVAL;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -270,6 +261,7 @@ static ssize_t
 efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
 {
 	struct efi_variable *new_var, *var = &entry->var;
+	struct efivars *efivars = entry->efivars;
 	efi_status_t status = EFI_NOT_FOUND;
 
 	if (count != sizeof(struct efi_variable))
@@ -291,14 +283,14 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
 		return -EINVAL;
 	}
 
-	spin_lock(&efivars_lock);
-	status = efi.set_variable(new_var->VariableName,
-					&new_var->VendorGuid,
-					new_var->Attributes,
-					new_var->DataSize,
-					new_var->Data);
+	spin_lock(&efivars->lock);
+	status = efivars->ops->set_variable(new_var->VariableName,
+					    &new_var->VendorGuid,
+					    new_var->Attributes,
+					    new_var->DataSize,
+					    new_var->Data);
 
-	spin_unlock(&efivars_lock);
+	spin_unlock(&efivars->lock);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -319,7 +311,7 @@ efivar_show_raw(struct efivar_entry *entry, char *buf)
 	if (!entry || !buf)
 		return 0;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -407,6 +399,7 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 			     char *buf, loff_t pos, size_t count)
 {
 	struct efi_variable *new_var = (struct efi_variable *)buf;
+	struct efivars *efivars = bin_attr->private;
 	struct efivar_entry *search_efivar, *n;
 	unsigned long strsize1, strsize2;
 	efi_status_t status = EFI_NOT_FOUND;
@@ -415,12 +408,12 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	spin_lock(&efivars_lock);
+	spin_lock(&efivars->lock);
 
 	/*
 	 * Does this variable already exist?
 	 */
-	list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
+	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
 		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 		strsize2 = utf8_strsize(new_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
@@ -433,28 +426,31 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 		}
 	}
 	if (found) {
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EINVAL;
 	}
 
 	/* now *really* create the variable via EFI */
-	status = efi.set_variable(new_var->VariableName,
-			&new_var->VendorGuid,
-			new_var->Attributes,
-			new_var->DataSize,
-			new_var->Data);
+	status = efivars->ops->set_variable(new_var->VariableName,
+					    &new_var->VendorGuid,
+					    new_var->Attributes,
+					    new_var->DataSize,
+					    new_var->Data);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 			status);
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EIO;
 	}
-	spin_unlock(&efivars_lock);
+	spin_unlock(&efivars->lock);
 
 	/* Create the entry in sysfs.  Locking is not required here */
-	status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName,
-			1024), new_var->VariableName, &new_var->VendorGuid);
+	status = efivar_create_sysfs_entry(efivars,
+					   utf8_strsize(new_var->VariableName,
+							1024),
+					   new_var->VariableName,
+					   &new_var->VendorGuid);
 	if (status) {
 		printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n");
 	}
@@ -466,6 +462,7 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
 			     char *buf, loff_t pos, size_t count)
 {
 	struct efi_variable *del_var = (struct efi_variable *)buf;
+	struct efivars *efivars = bin_attr->private;
 	struct efivar_entry *search_efivar, *n;
 	unsigned long strsize1, strsize2;
 	efi_status_t status = EFI_NOT_FOUND;
@@ -474,12 +471,12 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	spin_lock(&efivars_lock);
+	spin_lock(&efivars->lock);
 
 	/*
 	 * Does this variable already exist?
 	 */
-	list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
+	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
 		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 		strsize2 = utf8_strsize(del_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
@@ -492,44 +489,34 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
 		}
 	}
 	if (!found) {
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EINVAL;
 	}
 	/* force the Attributes/DataSize to 0 to ensure deletion */
 	del_var->Attributes = 0;
 	del_var->DataSize = 0;
 
-	status = efi.set_variable(del_var->VariableName,
-			&del_var->VendorGuid,
-			del_var->Attributes,
-			del_var->DataSize,
-			del_var->Data);
+	status = efivars->ops->set_variable(del_var->VariableName,
+					    &del_var->VendorGuid,
+					    del_var->Attributes,
+					    del_var->DataSize,
+					    del_var->Data);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 			status);
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EIO;
 	}
 	list_del(&search_efivar->list);
 	/* We need to release this lock before unregistering. */
-	spin_unlock(&efivars_lock);
+	spin_unlock(&efivars->lock);
 	efivar_unregister(search_efivar);
 
 	/* It's dead Jim.... */
 	return count;
 }
 
-static struct bin_attribute var_subsys_attr_new_var = {
-	.attr = {.name = "new_var", .mode = 0200},
-	.write = efivar_create,
-};
-
-static struct bin_attribute var_subsys_attr_del_var = {
-	.attr = {.name = "del_var", .mode = 0200},
-	.write = efivar_delete,
-};
-
 /*
  * Let's not leave out systab information that snuck into
  * the efivars driver
@@ -572,8 +559,6 @@ static struct attribute_group efi_subsys_attr_group = {
 	.attrs = efi_subsys_attrs,
 };
 
-
-static struct kset *vars_kset;
 static struct kobject *efi_kobj;
 
 /*
@@ -582,13 +567,14 @@ static struct kobject *efi_kobj;
  *    variable_name_size = number of bytes required to hold
  *                         variable_name (not counting the NULL
  *                         character at the end.
- *    efivars_lock is not held on entry or exit.
+ *    efivars->lock is not held on entry or exit.
  * Returns 1 on failure, 0 on success
  */
 static int
-efivar_create_sysfs_entry(unsigned long variable_name_size,
-			efi_char16_t *variable_name,
-			efi_guid_t *vendor_guid)
+efivar_create_sysfs_entry(struct efivars *efivars,
+			  unsigned long variable_name_size,
+			  efi_char16_t *variable_name,
+			  efi_guid_t *vendor_guid)
 {
 	int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
 	char *short_name;
@@ -603,6 +589,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
 		return 1;
 	}
 
+	new_efivar->efivars = efivars;
 	memcpy(new_efivar->var.VariableName, variable_name,
 		variable_name_size);
 	memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
@@ -618,7 +605,7 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
 	*(short_name + strlen(short_name)) = '-';
 	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
 
-	new_efivar->kobj.kset = vars_kset;
+	new_efivar->kobj.kset = efivars->kset;
 	i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL,
 				 "%s", short_name);
 	if (i) {
@@ -631,22 +618,95 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
 	kfree(short_name);
 	short_name = NULL;
 
-	spin_lock(&efivars_lock);
-	list_add(&new_efivar->list, &efivar_list);
-	spin_unlock(&efivars_lock);
+	spin_lock(&efivars->lock);
+	list_add(&new_efivar->list, &efivars->list);
+	spin_unlock(&efivars->lock);
 
 	return 0;
 }
-/*
- * For now we register the efi subsystem with the firmware subsystem
- * and the vars subsystem with the efi subsystem.  In the future, it
- * might make sense to split off the efi subsystem into its own
- * driver, but for now only efivars will register with it, so just
- * include it here.
- */
 
-static int __init
-efivars_init(void)
+static int
+create_efivars_bin_attributes(struct efivars *efivars)
+{
+	struct bin_attribute *attr;
+	int error;
+
+	/* new_var */
+	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr)
+		return -ENOMEM;
+
+	attr->attr.name = "new_var";
+	attr->attr.mode = 0200;
+	attr->write = efivar_create;
+	attr->private = efivars;
+	efivars->new_var = attr;
+
+	/* del_var */
+	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr) {
+		error = -ENOMEM;
+		goto out_free;
+	}
+	attr->attr.name = "del_var";
+	attr->attr.mode = 0200;
+	attr->write = efivar_delete;
+	attr->private = efivars;
+	efivars->del_var = attr;
+
+	sysfs_bin_attr_init(efivars->new_var);
+	sysfs_bin_attr_init(efivars->del_var);
+
+	/* Register */
+	error = sysfs_create_bin_file(&efivars->kset->kobj,
+				      efivars->new_var);
+	if (error) {
+		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
+			" due to error %d\n", error);
+		goto out_free;
+	}
+	error = sysfs_create_bin_file(&efivars->kset->kobj,
+				      efivars->del_var);
+	if (error) {
+		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
+			" due to error %d\n", error);
+		sysfs_remove_bin_file(&efivars->kset->kobj,
+				      efivars->new_var);
+		goto out_free;
+	}
+
+	return 0;
+out_free:
+	kfree(efivars->new_var);
+	efivars->new_var = NULL;
+	kfree(efivars->new_var);
+	efivars->new_var = NULL;
+	return error;
+}
+
+void unregister_efivars(struct efivars *efivars)
+{
+	struct efivar_entry *entry, *n;
+
+	list_for_each_entry_safe(entry, n, &efivars->list, list) {
+		spin_lock(&efivars->lock);
+		list_del(&entry->list);
+		spin_unlock(&efivars->lock);
+		efivar_unregister(entry);
+	}
+	if (efivars->new_var)
+		sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var);
+	if (efivars->del_var)
+		sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
+	kfree(efivars->new_var);
+	kfree(efivars->del_var);
+	kset_unregister(efivars->kset);
+}
+EXPORT_SYMBOL_GPL(unregister_efivars);
+
+int register_efivars(struct efivars *efivars,
+		     const struct efivar_operations *ops,
+		     struct kobject *parent_kobj)
 {
 	efi_status_t status = EFI_NOT_FOUND;
 	efi_guid_t vendor_guid;
@@ -654,31 +714,21 @@ efivars_init(void)
 	unsigned long variable_name_size = 1024;
 	int error = 0;
 
-	if (!efi_enabled)
-		return -ENODEV;
-
 	variable_name = kzalloc(variable_name_size, GFP_KERNEL);
 	if (!variable_name) {
 		printk(KERN_ERR "efivars: Memory allocation failed.\n");
 		return -ENOMEM;
 	}
 
-	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
-	       EFIVARS_DATE);
+	spin_lock_init(&efivars->lock);
+	INIT_LIST_HEAD(&efivars->list);
+	efivars->ops = ops;
 
-	/* For now we'll register the efi directory at /sys/firmware/efi */
-	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
-	if (!efi_kobj) {
-		printk(KERN_ERR "efivars: Firmware registration failed.\n");
-		error = -ENOMEM;
-		goto out_free;
-	}
-
-	vars_kset = kset_create_and_add("vars", NULL, efi_kobj);
-	if (!vars_kset) {
+	efivars->kset = kset_create_and_add("vars", NULL, parent_kobj);
+	if (!efivars->kset) {
 		printk(KERN_ERR "efivars: Subsystem registration failed.\n");
 		error = -ENOMEM;
-		goto out_firmware_unregister;
+		goto out;
 	}
 
 	/*
@@ -689,14 +739,15 @@ efivars_init(void)
 	do {
 		variable_name_size = 1024;
 
-		status = efi.get_next_variable(&variable_name_size,
+		status = ops->get_next_variable(&variable_name_size,
 						variable_name,
 						&vendor_guid);
 		switch (status) {
 		case EFI_SUCCESS:
-			efivar_create_sysfs_entry(variable_name_size,
-							variable_name,
-							&vendor_guid);
+			efivar_create_sysfs_entry(efivars,
+						  variable_name_size,
+						  variable_name,
+						  &vendor_guid);
 			break;
 		case EFI_NOT_FOUND:
 			break;
@@ -708,35 +759,60 @@ efivars_init(void)
 		}
 	} while (status != EFI_NOT_FOUND);
 
-	/*
-	 * Now add attributes to allow creation of new vars
-	 * and deletion of existing ones...
-	 */
-	error = sysfs_create_bin_file(&vars_kset->kobj,
-				      &var_subsys_attr_new_var);
-	if (error)
-		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
-			" due to error %d\n", error);
-	error = sysfs_create_bin_file(&vars_kset->kobj,
-				      &var_subsys_attr_del_var);
+	error = create_efivars_bin_attributes(efivars);
 	if (error)
-		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
-			" due to error %d\n", error);
+		unregister_efivars(efivars);
 
-	/* Don't forget the systab entry */
-	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
-	if (error)
-		printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
-	else
-		goto out_free;
+out:
+	kfree(variable_name);
 
-	kset_unregister(vars_kset);
+	return error;
+}
+EXPORT_SYMBOL_GPL(register_efivars);
 
-out_firmware_unregister:
-	kobject_put(efi_kobj);
+static struct efivars __efivars;
+static struct efivar_operations ops;
 
-out_free:
-	kfree(variable_name);
+/*
+ * For now we register the efi subsystem with the firmware subsystem
+ * and the vars subsystem with the efi subsystem.  In the future, it
+ * might make sense to split off the efi subsystem into its own
+ * driver, but for now only efivars will register with it, so just
+ * include it here.
+ */
+
+static int __init
+efivars_init(void)
+{
+	int error = 0;
+
+	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
+	       EFIVARS_DATE);
+
+	if (!efi_enabled)
+		return 0;
+
+	/* For now we'll register the efi directory at /sys/firmware/efi */
+	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
+	if (!efi_kobj) {
+		printk(KERN_ERR "efivars: Firmware registration failed.\n");
+		return -ENOMEM;
+	}
+
+	ops.get_variable = efi.get_variable;
+	ops.set_variable = efi.set_variable;
+	ops.get_next_variable = efi.get_next_variable;
+	error = register_efivars(&__efivars, &ops, efi_kobj);
+
+	/* Don't forget the systab entry */
+	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
+	if (error) {
+		printk(KERN_ERR
+		       "efivars: Sysfs attribute export failed with error %d.\n",
+		       error);
+		unregister_efivars(&__efivars);
+		kobject_put(efi_kobj);
+	}
 
 	return error;
 }
@@ -744,16 +820,7 @@ out_free:
 static void __exit
 efivars_exit(void)
 {
-	struct efivar_entry *entry, *n;
-
-	list_for_each_entry_safe(entry, n, &efivar_list, list) {
-		spin_lock(&efivars_lock);
-		list_del(&entry->list);
-		spin_unlock(&efivars_lock);
-		efivar_unregister(entry);
-	}
-
-	kset_unregister(vars_kset);
+	unregister_efivars(&__efivars);
 	kobject_put(efi_kobj);
 }
 
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
new file mode 100644
index 0000000..c19cd2c
--- /dev/null
+++ b/drivers/firmware/sigma.c
@@ -0,0 +1,115 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/sigma.h>
+
+/* Return: 0==OK, <0==error, =1 ==no more actions */
+static int
+process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)
+{
+	struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);
+	size_t len = sigma_action_len(sa);
+	int ret = 0;
+
+	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
+		sa->instr, sa->addr, len);
+
+	switch (sa->instr) {
+	case SIGMA_ACTION_WRITEXBYTES:
+	case SIGMA_ACTION_WRITESINGLE:
+	case SIGMA_ACTION_WRITESAFELOAD:
+		if (ssfw->fw->size < ssfw->pos + len)
+			return -EINVAL;
+		ret = i2c_master_send(client, (void *)&sa->addr, len);
+		if (ret < 0)
+			return -EINVAL;
+		break;
+
+	case SIGMA_ACTION_DELAY:
+		ret = 0;
+		udelay(len);
+		len = 0;
+		break;
+
+	case SIGMA_ACTION_END:
+		return 1;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* when arrive here ret=0 or sent data */
+	ssfw->pos += sigma_action_size(sa, len);
+	return ssfw->pos == ssfw->fw->size;
+}
+
+static int
+process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
+{
+	pr_debug("%s: processing %p\n", __func__, ssfw);
+
+	while (1) {
+		int ret = process_sigma_action(client, ssfw);
+		pr_debug("%s: action returned %i\n", __func__, ret);
+		if (ret == 1)
+			return 0;
+		else if (ret)
+			return ret;
+	}
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+	int ret;
+	struct sigma_firmware_header *ssfw_head;
+	struct sigma_firmware ssfw;
+	const struct firmware *fw;
+	u32 crc;
+
+	pr_debug("%s: loading firmware %s\n", __func__, name);
+
+	/* first load the blob */
+	ret = request_firmware(&fw, name, &client->dev);
+	if (ret) {
+		pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
+		return ret;
+	}
+	ssfw.fw = fw;
+
+	/* then verify the header */
+	ret = -EINVAL;
+	if (fw->size < sizeof(*ssfw_head))
+		goto done;
+
+	ssfw_head = (void *)fw->data;
+	if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
+		goto done;
+
+	crc = crc32(0, fw->data, fw->size);
+	pr_debug("%s: crc=%x\n", __func__, crc);
+	if (crc != ssfw_head->crc)
+		goto done;
+
+	ssfw.pos = sizeof(*ssfw_head);
+
+	/* finally process all of the actions */
+	ret = process_sigma_actions(client, &ssfw);
+
+ done:
+	release_firmware(fw);
+
+	pr_debug("%s: loaded %s\n", __func__, name);
+
+	return ret;
+}
+EXPORT_SYMBOL(process_sigma_firmware);
diff --git a/drivers/gpio/74x164.c b/drivers/gpio/74x164.c
index d91ff4c..84e0702 100644
--- a/drivers/gpio/74x164.c
+++ b/drivers/gpio/74x164.c
@@ -133,7 +133,7 @@ exit_destroy:
 	return ret;
 }
 
-static int gen_74x164_remove(struct spi_device *spi)
+static int __devexit gen_74x164_remove(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
 	int ret;
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 664660e..b46442d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -101,7 +101,7 @@ config GPIO_VR41XX
 
 config GPIO_SCH
 	tristate "Intel SCH GPIO"
-	depends on GPIOLIB && PCI
+	depends on GPIOLIB && PCI && X86
 	select MFD_CORE
 	select LPC_SCH
 	help
@@ -321,13 +321,13 @@ config GPIO_BT8XX
 
 config GPIO_LANGWELL
 	bool "Intel Langwell/Penwell GPIO support"
-	depends on PCI
+	depends on PCI && X86
 	help
 	  Say Y here to support Intel Langwell/Penwell GPIO.
 
 config GPIO_PCH
 	tristate "PCH GPIO of Intel Topcliff"
-	depends on PCI
+	depends on PCI && X86
 	help
 	  This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -368,11 +368,11 @@ config GPIO_MAX7301
 	  GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
 
 config GPIO_MCP23S08
-	tristate "Microchip MCP23S08 I/O expander"
+	tristate "Microchip MCP23Sxx I/O expander"
 	depends on SPI_MASTER
 	help
-	  SPI driver for Microchip MCP23S08 I/O expander.  This provides
-	  a GPIO interface supporting inputs and outputs.
+	  SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
+	  This provides a GPIO interface supporting inputs and outputs.
 
 config GPIO_MC33880
 	tristate "Freescale MC33880 high-side/low-side switch"
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index 0d05ea7..6e16cba 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -373,7 +373,7 @@ static int __devexit cs5535_gpio_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static struct platform_driver cs5535_gpio_drv = {
+static struct platform_driver cs5535_gpio_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -384,12 +384,12 @@ static struct platform_driver cs5535_gpio_drv = {
 
 static int __init cs5535_gpio_init(void)
 {
-	return platform_driver_register(&cs5535_gpio_drv);
+	return platform_driver_register(&cs5535_gpio_driver);
 }
 
 static void __exit cs5535_gpio_exit(void)
 {
-	platform_driver_unregister(&cs5535_gpio_drv);
+	platform_driver_unregister(&cs5535_gpio_driver);
 }
 
 module_init(cs5535_gpio_init);
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c
index 54d70a4..560ab64 100644
--- a/drivers/gpio/langwell_gpio.c
+++ b/drivers/gpio/langwell_gpio.c
@@ -187,31 +187,28 @@ MODULE_DEVICE_TABLE(pci, lnw_gpio_ids);
 
 static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct lnw_gpio *lnw = get_irq_data(irq);
-	u32 base, gpio;
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	u32 base, gpio, mask;
+	unsigned long pending;
 	void __iomem *gedr;
-	u32 gedr_v;
 
 	/* check GPIO controller to check which pin triggered the interrupt */
 	for (base = 0; base < lnw->chip.ngpio; base += 32) {
 		gedr = gpio_reg(&lnw->chip, base, GEDR);
-		gedr_v = readl(gedr);
-		if (!gedr_v)
-			continue;
-		for (gpio = base; gpio < base + 32; gpio++)
-			if (gedr_v & BIT(gpio % 32)) {
-				pr_debug("pin %d triggered\n", gpio);
-				generic_handle_irq(lnw->irq_base + gpio);
-			}
-		/* clear the edge detect status bit */
-		writel(gedr_v, gedr);
+		pending = readl(gedr);
+		while (pending) {
+			gpio = __ffs(pending) - 1;
+			mask = BIT(gpio);
+			pending &= ~mask;
+			/* Clear before handling so we can't lose an edge */
+			writel(mask, gedr);
+			generic_handle_irq(lnw->irq_base + base + gpio);
+		}
 	}
 
-	if (desc->chip->irq_eoi)
-		desc->chip->irq_eoi(irq_get_irq_data(irq));
-	else
-		dev_warn(lnw->chip.dev, "missing EOI handler for irq %d\n", irq);
-
+	chip->irq_eoi(data);
 }
 
 static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
@@ -279,12 +276,12 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
 		dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
 		goto err5;
 	}
-	set_irq_data(pdev->irq, lnw);
-	set_irq_chained_handler(pdev->irq, lnw_irq_handler);
+	irq_set_handler_data(pdev->irq, lnw);
+	irq_set_chained_handler(pdev->irq, lnw_irq_handler);
 	for (i = 0; i < lnw->chip.ngpio; i++) {
-		set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
-					handle_simple_irq, "demux");
-		set_irq_chip_data(i + lnw->irq_base, lnw);
+		irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
+					      handle_simple_irq, "demux");
+		irq_set_chip_data(i + lnw->irq_base, lnw);
 	}
 
 	spin_lock_init(&lnw->lock);
diff --git a/drivers/gpio/mc33880.c b/drivers/gpio/mc33880.c
index 935479d..00f6d24 100644
--- a/drivers/gpio/mc33880.c
+++ b/drivers/gpio/mc33880.c
@@ -146,7 +146,7 @@ exit_destroy:
 	return ret;
 }
 
-static int mc33880_remove(struct spi_device *spi)
+static int __devexit mc33880_remove(struct spi_device *spi)
 {
 	struct mc33880 *mc;
 	int ret;
diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
index 69f6f19..40e0760 100644
--- a/drivers/gpio/mcp23s08.c
+++ b/drivers/gpio/mcp23s08.c
@@ -10,7 +10,13 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/mcp23s08.h>
 #include <linux/slab.h>
+#include <asm/byteorder.h>
 
+/**
+ * MCP types supported by driver
+ */
+#define MCP_TYPE_S08	0
+#define MCP_TYPE_S17	1
 
 /* Registers are all 8 bits wide.
  *
@@ -35,27 +41,38 @@
 #define MCP_GPIO	0x09
 #define MCP_OLAT	0x0a
 
+struct mcp23s08;
+
+struct mcp23s08_ops {
+	int	(*read)(struct mcp23s08 *mcp, unsigned reg);
+	int	(*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
+	int	(*read_regs)(struct mcp23s08 *mcp, unsigned reg,
+			     u16 *vals, unsigned n);
+};
+
 struct mcp23s08 {
 	struct spi_device	*spi;
 	u8			addr;
 
-	u8			cache[11];
+	u16			cache[11];
 	/* lock protects the cached values */
 	struct mutex		lock;
 
 	struct gpio_chip	chip;
 
 	struct work_struct	work;
+
+	const struct mcp23s08_ops	*ops;
 };
 
-/* A given spi_device can represent up to four mcp23s08 chips
+/* A given spi_device can represent up to eight mcp23sxx chips
  * sharing the same chipselect but using different addresses
  * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
  * Driver data holds all the per-chip data.
  */
 struct mcp23s08_driver_data {
 	unsigned		ngpio;
-	struct mcp23s08		*mcp[4];
+	struct mcp23s08		*mcp[8];
 	struct mcp23s08		chip[];
 };
 
@@ -70,7 +87,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
 	return (status < 0) ? status : rx[0];
 }
 
-static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
+static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
 {
 	u8	tx[3];
 
@@ -81,17 +98,81 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
 }
 
 static int
-mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u8 *vals, unsigned n)
+mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
 {
-	u8	tx[2];
+	u8	tx[2], *tmp;
+	int	status;
 
 	if ((n + reg) > sizeof mcp->cache)
 		return -EINVAL;
 	tx[0] = mcp->addr | 0x01;
 	tx[1] = reg;
-	return spi_write_then_read(mcp->spi, tx, sizeof tx, vals, n);
+
+	tmp = (u8 *)vals;
+	status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
+	if (status >= 0) {
+		while (n--)
+			vals[n] = tmp[n]; /* expand to 16bit */
+	}
+	return status;
+}
+
+static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
+{
+	u8	tx[2], rx[2];
+	int	status;
+
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg << 1;
+	status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
+	return (status < 0) ? status : (rx[0] | (rx[1] << 8));
+}
+
+static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+	u8	tx[4];
+
+	tx[0] = mcp->addr;
+	tx[1] = reg << 1;
+	tx[2] = val;
+	tx[3] = val >> 8;
+	return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+}
+
+static int
+mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+	u8	tx[2];
+	int	status;
+
+	if ((n + reg) > sizeof mcp->cache)
+		return -EINVAL;
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg << 1;
+
+	status = spi_write_then_read(mcp->spi, tx, sizeof tx,
+				     (u8 *)vals, n * 2);
+	if (status >= 0) {
+		while (n--)
+			vals[n] = __le16_to_cpu((__le16)vals[n]);
+	}
+
+	return status;
 }
 
+static const struct mcp23s08_ops mcp23s08_ops = {
+	.read		= mcp23s08_read,
+	.write		= mcp23s08_write,
+	.read_regs	= mcp23s08_read_regs,
+};
+
+static const struct mcp23s08_ops mcp23s17_ops = {
+	.read		= mcp23s17_read,
+	.write		= mcp23s17_write,
+	.read_regs	= mcp23s17_read_regs,
+};
+
+
 /*----------------------------------------------------------------------*/
 
 static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -101,7 +182,7 @@ static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
 
 	mutex_lock(&mcp->lock);
 	mcp->cache[MCP_IODIR] |= (1 << offset);
-	status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+	status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 	mutex_unlock(&mcp->lock);
 	return status;
 }
@@ -114,7 +195,7 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
 	mutex_lock(&mcp->lock);
 
 	/* REVISIT reading this clears any IRQ ... */
-	status = mcp23s08_read(mcp, MCP_GPIO);
+	status = mcp->ops->read(mcp, MCP_GPIO);
 	if (status < 0)
 		status = 0;
 	else {
@@ -127,20 +208,20 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
 
 static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
 {
-	u8 olat = mcp->cache[MCP_OLAT];
+	unsigned olat = mcp->cache[MCP_OLAT];
 
 	if (value)
 		olat |= mask;
 	else
 		olat &= ~mask;
 	mcp->cache[MCP_OLAT] = olat;
-	return mcp23s08_write(mcp, MCP_OLAT, olat);
+	return mcp->ops->write(mcp, MCP_OLAT, olat);
 }
 
 static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	u8 mask = 1 << offset;
+	unsigned mask = 1 << offset;
 
 	mutex_lock(&mcp->lock);
 	__mcp23s08_set(mcp, mask, value);
@@ -151,14 +232,14 @@ static int
 mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	u8 mask = 1 << offset;
+	unsigned mask = 1 << offset;
 	int status;
 
 	mutex_lock(&mcp->lock);
 	status = __mcp23s08_set(mcp, mask, value);
 	if (status == 0) {
 		mcp->cache[MCP_IODIR] &= ~mask;
-		status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+		status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 	}
 	mutex_unlock(&mcp->lock);
 	return status;
@@ -184,16 +265,16 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	mcp = container_of(chip, struct mcp23s08, chip);
 
 	/* NOTE: we only handle one bank for now ... */
-	bank = '0' + ((mcp->addr >> 1) & 0x3);
+	bank = '0' + ((mcp->addr >> 1) & 0x7);
 
 	mutex_lock(&mcp->lock);
-	t = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
+	t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
 	if (t < 0) {
 		seq_printf(s, " I/O ERROR %d\n", t);
 		goto done;
 	}
 
-	for (t = 0, mask = 1; t < 8; t++, mask <<= 1) {
+	for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
 		const char	*label;
 
 		label = gpiochip_is_requested(chip, t);
@@ -219,28 +300,33 @@ done:
 /*----------------------------------------------------------------------*/
 
 static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
-		unsigned base, unsigned pullups)
+			      unsigned type, unsigned base, unsigned pullups)
 {
 	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
 	struct mcp23s08			*mcp = data->mcp[addr];
 	int				status;
-	int				do_update = 0;
 
 	mutex_init(&mcp->lock);
 
 	mcp->spi = spi;
 	mcp->addr = 0x40 | (addr << 1);
 
-	mcp->chip.label = "mcp23s08",
-
 	mcp->chip.direction_input = mcp23s08_direction_input;
 	mcp->chip.get = mcp23s08_get;
 	mcp->chip.direction_output = mcp23s08_direction_output;
 	mcp->chip.set = mcp23s08_set;
 	mcp->chip.dbg_show = mcp23s08_dbg_show;
 
+	if (type == MCP_TYPE_S17) {
+		mcp->ops = &mcp23s17_ops;
+		mcp->chip.ngpio = 16;
+		mcp->chip.label = "mcp23s17";
+	} else {
+		mcp->ops = &mcp23s08_ops;
+		mcp->chip.ngpio = 8;
+		mcp->chip.label = "mcp23s08";
+	}
 	mcp->chip.base = base;
-	mcp->chip.ngpio = 8;
 	mcp->chip.can_sleep = 1;
 	mcp->chip.dev = &spi->dev;
 	mcp->chip.owner = THIS_MODULE;
@@ -248,45 +334,39 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
 	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
 	 * and MCP_IOCON.HAEN = 1, so we work with all chips.
 	 */
-	status = mcp23s08_read(mcp, MCP_IOCON);
+	status = mcp->ops->read(mcp, MCP_IOCON);
 	if (status < 0)
 		goto fail;
 	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
-		status &= ~IOCON_SEQOP;
-		status |= IOCON_HAEN;
-		status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
+		/* mcp23s17 has IOCON twice, make sure they are in sync */
+		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
+		status |= IOCON_HAEN | (IOCON_HAEN << 8);
+		status = mcp->ops->write(mcp, MCP_IOCON, status);
 		if (status < 0)
 			goto fail;
 	}
 
 	/* configure ~100K pullups */
-	status = mcp23s08_write(mcp, MCP_GPPU, pullups);
+	status = mcp->ops->write(mcp, MCP_GPPU, pullups);
 	if (status < 0)
 		goto fail;
 
-	status = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
+	status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
 	if (status < 0)
 		goto fail;
 
 	/* disable inverter on input */
 	if (mcp->cache[MCP_IPOL] != 0) {
 		mcp->cache[MCP_IPOL] = 0;
-		do_update = 1;
+		status = mcp->ops->write(mcp, MCP_IPOL, 0);
+		if (status < 0)
+			goto fail;
 	}
 
 	/* disable irqs */
 	if (mcp->cache[MCP_GPINTEN] != 0) {
 		mcp->cache[MCP_GPINTEN] = 0;
-		do_update = 1;
-	}
-
-	if (do_update) {
-		u8 tx[4];
-
-		tx[0] = mcp->addr;
-		tx[1] = MCP_IPOL;
-		memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
-		status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+		status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
 		if (status < 0)
 			goto fail;
 	}
@@ -305,19 +385,26 @@ static int mcp23s08_probe(struct spi_device *spi)
 	unsigned			addr;
 	unsigned			chips = 0;
 	struct mcp23s08_driver_data	*data;
-	int				status;
+	int				status, type;
 	unsigned			base;
 
+	type = spi_get_device_id(spi)->driver_data;
+
 	pdata = spi->dev.platform_data;
 	if (!pdata || !gpio_is_valid(pdata->base)) {
 		dev_dbg(&spi->dev, "invalid or missing platform data\n");
 		return -EINVAL;
 	}
 
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
 		if (!pdata->chip[addr].is_present)
 			continue;
 		chips++;
+		if ((type == MCP_TYPE_S08) && (addr > 3)) {
+			dev_err(&spi->dev,
+				"mcp23s08 only supports address 0..3\n");
+			return -EINVAL;
+		}
 	}
 	if (!chips)
 		return -ENODEV;
@@ -329,16 +416,17 @@ static int mcp23s08_probe(struct spi_device *spi)
 	spi_set_drvdata(spi, data);
 
 	base = pdata->base;
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
 		if (!pdata->chip[addr].is_present)
 			continue;
 		chips--;
 		data->mcp[addr] = &data->chip[chips];
-		status = mcp23s08_probe_one(spi, addr, base,
-				pdata->chip[addr].pullups);
+		status = mcp23s08_probe_one(spi, addr, type, base,
+					    pdata->chip[addr].pullups);
 		if (status < 0)
 			goto fail;
-		base += 8;
+
+		base += (type == MCP_TYPE_S17) ? 16 : 8;
 	}
 	data->ngpio = base - pdata->base;
 
@@ -358,7 +446,7 @@ static int mcp23s08_probe(struct spi_device *spi)
 	return 0;
 
 fail:
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
 		int tmp;
 
 		if (!data->mcp[addr])
@@ -388,7 +476,7 @@ static int mcp23s08_remove(struct spi_device *spi)
 		}
 	}
 
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
 		int tmp;
 
 		if (!data->mcp[addr])
@@ -405,9 +493,17 @@ static int mcp23s08_remove(struct spi_device *spi)
 	return status;
 }
 
+static const struct spi_device_id mcp23s08_ids[] = {
+	{ "mcp23s08", MCP_TYPE_S08 },
+	{ "mcp23s17", MCP_TYPE_S17 },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
+
 static struct spi_driver mcp23s08_driver = {
 	.probe		= mcp23s08_probe,
 	.remove		= mcp23s08_remove,
+	.id_table	= mcp23s08_ids,
 	.driver = {
 		.name	= "mcp23s08",
 		.owner	= THIS_MODULE,
@@ -432,4 +528,3 @@ static void __exit mcp23s08_exit(void)
 module_exit(mcp23s08_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:mcp23s08");
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index b473429e..2fc25de 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -462,7 +462,8 @@ pca953x_get_alt_pdata(struct i2c_client *client)
 {
 	struct pca953x_platform_data *pdata;
 	struct device_node *node;
-	const uint16_t *val;
+	const __be32 *val;
+	int size;
 
 	node = client->dev.of_node;
 	if (node == NULL)
@@ -475,13 +476,13 @@ pca953x_get_alt_pdata(struct i2c_client *client)
 	}
 
 	pdata->gpio_base = -1;
-	val = of_get_property(node, "linux,gpio-base", NULL);
+	val = of_get_property(node, "linux,gpio-base", &size);
 	if (val) {
-		if (*val < 0)
-			dev_warn(&client->dev,
-				 "invalid gpio-base in device tree\n");
+		if (size != sizeof(*val))
+			dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
+				 node->full_name);
 		else
-			pdata->gpio_base = *val;
+			pdata->gpio_base = be32_to_cpup(val);
 	}
 
 	val = of_get_property(node, "polarity", NULL);
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
index 2975d22..838ddbd 100644
--- a/drivers/gpio/pl061.c
+++ b/drivers/gpio/pl061.c
@@ -232,7 +232,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
 	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
-static int pl061_probe(struct amba_device *dev, struct amba_id *id)
+static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct pl061_platform_data *pdata;
 	struct pl061_gpio *chip;
diff --git a/drivers/gpio/sx150x.c b/drivers/gpio/sx150x.c
index e60be00..d2f874c 100644
--- a/drivers/gpio/sx150x.c
+++ b/drivers/gpio/sx150x.c
@@ -25,6 +25,8 @@
 #include <linux/workqueue.h>
 #include <linux/i2c/sx150x.h>
 
+#define NO_UPDATE_PENDING	-1
+
 struct sx150x_device_data {
 	u8 reg_pullup;
 	u8 reg_pulldn;
@@ -47,8 +49,11 @@ struct sx150x_chip {
 	const struct sx150x_device_data *dev_cfg;
 	int                              irq_summary;
 	int                              irq_base;
+	int				 irq_update;
 	u32                              irq_sense;
-	unsigned long                    irq_set_type_pending;
+	u32				 irq_masked;
+	u32				 dev_sense;
+	u32				 dev_masked;
 	struct irq_chip                  irq_chip;
 	struct mutex                     lock;
 };
@@ -312,9 +317,8 @@ static void sx150x_irq_mask(struct irq_data *d)
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
-
-	sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
-	sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
+	chip->irq_masked |= (1 << n);
+	chip->irq_update = n;
 }
 
 static void sx150x_irq_unmask(struct irq_data *d)
@@ -326,9 +330,8 @@ static void sx150x_irq_unmask(struct irq_data *d)
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
 
-	sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
-	sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
-			 chip->irq_sense >> (n * 2));
+	chip->irq_masked &= ~(1 << n);
+	chip->irq_update = n;
 }
 
 static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
@@ -350,7 +353,7 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 
 	chip->irq_sense &= ~(3UL << (n * 2));
 	chip->irq_sense |= val << (n * 2);
-	chip->irq_set_type_pending |= BIT(n);
+	chip->irq_update = n;
 	return 0;
 }
 
@@ -404,15 +407,29 @@ static void sx150x_irq_bus_sync_unlock(struct irq_data *d)
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
 
-	while (chip->irq_set_type_pending) {
-		n = __ffs(chip->irq_set_type_pending);
-		chip->irq_set_type_pending &= ~BIT(n);
-		if (!(irq_to_desc(n + chip->irq_base)->status & IRQ_MASKED))
-			sx150x_write_cfg(chip, n, 2,
-					chip->dev_cfg->reg_sense,
-					chip->irq_sense >> (n * 2));
-	}
+	if (chip->irq_update == NO_UPDATE_PENDING)
+		goto out;
+
+	n = chip->irq_update;
+	chip->irq_update = NO_UPDATE_PENDING;
 
+	/* Avoid updates if nothing changed */
+	if (chip->dev_sense == chip->irq_sense &&
+	    chip->dev_sense == chip->irq_masked)
+		goto out;
+
+	chip->dev_sense = chip->irq_sense;
+	chip->dev_masked = chip->irq_masked;
+
+	if (chip->irq_masked & (1 << n)) {
+		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
+		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
+	} else {
+		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
+		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
+				 chip->irq_sense >> (n * 2));
+	}
+out:
 	mutex_unlock(&chip->lock);
 }
 
@@ -445,8 +462,11 @@ static void sx150x_init_chip(struct sx150x_chip *chip,
 	chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
 	chip->irq_summary                  = -1;
 	chip->irq_base                     = -1;
+	chip->irq_masked                   = ~0;
 	chip->irq_sense                    = 0;
-	chip->irq_set_type_pending         = 0;
+	chip->dev_masked                   = ~0;
+	chip->dev_sense                    = 0;
+	chip->irq_update		   = NO_UPDATE_PENDING;
 }
 
 static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 0902d44..a6feb78c 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -73,32 +73,17 @@ source "drivers/gpu/drm/radeon/Kconfig"
 
 config DRM_I810
 	tristate "Intel I810"
-	# BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
-	depends on DRM && AGP && AGP_INTEL && BKL
+	# !PREEMPT because of missing ioctl locking
+	depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
 	help
 	  Choose this option if you have an Intel I810 graphics card.  If M is
 	  selected, the module will be called i810.  AGP support is required
 	  for this driver to work.
 
-choice
-	prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
-	depends on DRM && AGP && AGP_INTEL
-	optional
-
-config DRM_I830
-	tristate "i830 driver"
-	# BKL usage in order to avoid AB-BA deadlocks, i830 may get removed
-	depends on BKL
-	help
-	  Choose this option if you have a system that has Intel 830M, 845G,
-	  852GM, 855GM or 865G integrated graphics.  If M is selected, the
-	  module will be called i830.  AGP support is required for this driver
-	  to work. This driver is used by the older X releases X.org 6.7 and
-	  XFree86 4.3. If unsure, build this and i915 as modules and the X server
-	  will load the correct one.
-
 config DRM_I915
-	tristate "i915 driver"
+	tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
+	depends on DRM
+	depends on AGP
 	depends on AGP_INTEL
 	# we need shmfs for the swappable backing store, and in particular
 	# the shmem_readpage() which depends upon tmpfs
@@ -115,12 +100,20 @@ config DRM_I915
 	select ACPI_VIDEO if ACPI
 	select ACPI_BUTTON if ACPI
 	help
-	  Choose this option if you have a system that has Intel 830M, 845G,
-	  852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
-	  module will be called i915.  AGP support is required for this driver
-	  to work. This driver is used by the Intel driver in X.org 6.8 and
-	  XFree86 4.4 and above. If unsure, build this and i830 as modules and
-	  the X server will load the correct one.
+	  Choose this option if you have a system that has "Intel Graphics
+	  Media Accelerator" or "HD Graphics" integrated graphics,
+	  including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G,
+	  G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3,
+	  Core i5, Core i7 as well as Atom CPUs with integrated graphics.
+	  If M is selected, the module will be called i915.  AGP support
+	  is required for this driver to work. This driver is used by
+	  the Intel driver in X.org 6.8 and XFree86 4.4 and above. It
+	  replaces the older i830 module that supported a subset of the
+	  hardware in older X.org releases.
+
+	  Note that the older i810/i815 chipsets require the use of the
+	  i810 driver instead, and the Atom z5xx series has an entirely
+	  different implementation.
 
 config DRM_I915_KMS
 	bool "Enable modesetting on intel by default"
@@ -132,8 +125,6 @@ config DRM_I915_KMS
 	  the driver to bind to PCI devices, which precludes loading things
 	  like intelfb.
 
-endchoice
-
 config DRM_MGA
 	tristate "Matrox g200/g400"
 	depends on DRM && PCI
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 997c43d..89cf05a 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -12,7 +12,7 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
-		drm_trace_points.o drm_global.o
+		drm_trace_points.o drm_global.o drm_usb.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
@@ -29,7 +29,6 @@ obj-$(CONFIG_DRM_R128)	+= r128/
 obj-$(CONFIG_DRM_RADEON)+= radeon/
 obj-$(CONFIG_DRM_MGA)	+= mga/
 obj-$(CONFIG_DRM_I810)	+= i810/
-obj-$(CONFIG_DRM_I830)	+= i830/
 obj-$(CONFIG_DRM_I915)  += i915/
 obj-$(CONFIG_DRM_SIS)   += sis/
 obj-$(CONFIG_DRM_SAVAGE)+= savage/
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 654faa8..4c95b5f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2694,3 +2694,36 @@ void drm_mode_config_reset(struct drm_device *dev)
 			connector->funcs->reset(connector);
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
+
+int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_create_dumb *args = data;
+
+	if (!dev->driver->dumb_create)
+		return -ENOSYS;
+	return dev->driver->dumb_create(file_priv, dev, args);
+}
+
+int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_map_dumb *args = data;
+
+	/* call driver ioctl to get mmap offset */
+	if (!dev->driver->dumb_map_offset)
+		return -ENOSYS;
+
+	return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
+}
+
+int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+				void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_destroy_dumb *args = data;
+
+	if (!dev->driver->dumb_destroy)
+		return -ENOSYS;
+
+	return dev->driver->dumb_destroy(file_priv, dev, args->handle);
+}
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 271835a..93a112d 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -67,6 +67,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -150,7 +151,10 @@ static struct drm_ioctl_desc drm_ioctls[] = {
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
@@ -234,49 +238,6 @@ int drm_lastclose(struct drm_device * dev)
 	return 0;
 }
 
-/**
- * Module initialization. Called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported).
- *
- * \return zero on success or a negative number on failure.
- *
- * Initializes an array of drm_device structures, and attempts to
- * initialize all available devices, using consecutive minors, registering the
- * stubs and initializing the device.
- *
- * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- * after the initialization for driver customization.
- */
-int drm_init(struct drm_driver *driver)
-{
-	DRM_DEBUG("\n");
-	INIT_LIST_HEAD(&driver->device_list);
-
-	if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
-		return drm_platform_init(driver);
-	else
-		return drm_pci_init(driver);
-}
-
-EXPORT_SYMBOL(drm_init);
-
-void drm_exit(struct drm_driver *driver)
-{
-	struct drm_device *dev, *tmp;
-	DRM_DEBUG("\n");
-
-	if (driver->driver_features & DRIVER_MODESET) {
-		pci_unregister_driver(&driver->pci_driver);
-	} else {
-		list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-			drm_put_dev(dev);
-	}
-
-	DRM_INFO("Module unloaded\n");
-}
-
-EXPORT_SYMBOL(drm_exit);
-
 /** File operations structure */
 static const struct file_operations drm_stub_fops = {
 	.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a245d17..9c595e3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -230,24 +230,32 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
 		      int block, int len)
 {
 	unsigned char start = block * EDID_LENGTH;
-	struct i2c_msg msgs[] = {
-		{
-			.addr	= DDC_ADDR,
-			.flags	= 0,
-			.len	= 1,
-			.buf	= &start,
-		}, {
-			.addr	= DDC_ADDR,
-			.flags	= I2C_M_RD,
-			.len	= len,
-			.buf	= buf,
-		}
-	};
+	int ret, retries = 5;
 
-	if (i2c_transfer(adapter, msgs, 2) == 2)
-		return 0;
+	/* The core i2c driver will automatically retry the transfer if the
+	 * adapter reports EAGAIN. However, we find that bit-banging transfers
+	 * are susceptible to errors under a heavily loaded machine and
+	 * generate spurious NAKs and timeouts. Retrying the transfer
+	 * of the individual block a few times seems to overcome this.
+	 */
+	do {
+		struct i2c_msg msgs[] = {
+			{
+				.addr	= DDC_ADDR,
+				.flags	= 0,
+				.len	= 1,
+				.buf	= &start,
+			}, {
+				.addr	= DDC_ADDR,
+				.flags	= I2C_M_RD,
+				.len	= len,
+				.buf	= buf,
+			}
+		};
+		ret = i2c_transfer(adapter, msgs, 2);
+	} while (ret != 2 && --retries);
 
-	return -1;
+	return ret == 2 ? 0 : -1;
 }
 
 static u8 *
@@ -449,12 +457,11 @@ static void edid_fixup_preferred(struct drm_connector *connector,
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh)
 {
+	struct drm_display_mode *mode = NULL;
 	int i;
-	struct drm_display_mode *ptr, *mode;
 
-	mode = NULL;
 	for (i = 0; i < drm_num_dmt_modes; i++) {
-		ptr = &drm_dmt_modes[i];
+		const struct drm_display_mode *ptr = &drm_dmt_modes[i];
 		if (hsize == ptr->hdisplay &&
 			vsize == ptr->vdisplay &&
 			fresh == drm_mode_vrefresh(ptr)) {
@@ -885,7 +892,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 }
 
 static bool
-mode_is_rb(struct drm_display_mode *mode)
+mode_is_rb(const struct drm_display_mode *mode)
 {
 	return (mode->htotal - mode->hdisplay == 160) &&
 	       (mode->hsync_end - mode->hdisplay == 80) &&
@@ -894,7 +901,8 @@ mode_is_rb(struct drm_display_mode *mode)
 }
 
 static bool
-mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
+mode_in_hsync_range(const struct drm_display_mode *mode,
+		    struct edid *edid, u8 *t)
 {
 	int hsync, hmin, hmax;
 
@@ -910,7 +918,8 @@ mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
 }
 
 static bool
-mode_in_vsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
+mode_in_vsync_range(const struct drm_display_mode *mode,
+		    struct edid *edid, u8 *t)
 {
 	int vsync, vmin, vmax;
 
@@ -941,7 +950,7 @@ range_pixel_clock(struct edid *edid, u8 *t)
 }
 
 static bool
-mode_in_range(struct drm_display_mode *mode, struct edid *edid,
+mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
 	      struct detailed_timing *timing)
 {
 	u32 max_clock;
@@ -1472,7 +1481,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
 			int hdisplay, int vdisplay)
 {
 	int i, count, num_modes = 0;
-	struct drm_display_mode *mode, *ptr;
+	struct drm_display_mode *mode;
 	struct drm_device *dev = connector->dev;
 
 	count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
@@ -1482,7 +1491,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
 		vdisplay = 0;
 
 	for (i = 0; i < count; i++) {
-		ptr = &drm_dmt_modes[i];
+		const struct drm_display_mode *ptr = &drm_dmt_modes[i];
 		if (hdisplay && vdisplay) {
 			/*
 			 * Only when two are valid, they will be used to check
diff --git a/drivers/gpu/drm/drm_edid_modes.h b/drivers/gpu/drm/drm_edid_modes.h
index 6eb7592..5f20644 100644
--- a/drivers/gpu/drm/drm_edid_modes.h
+++ b/drivers/gpu/drm/drm_edid_modes.h
@@ -32,7 +32,7 @@
  * This table is copied from xfree86/modes/xf86EdidModes.c.
  * But the mode with Reduced blank feature is deleted.
  */
-static struct drm_display_mode drm_dmt_modes[] = {
+static const struct drm_display_mode drm_dmt_modes[] = {
 	/* 640x350@85Hz */
 	{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
 		   736, 832, 0, 350, 382, 385, 445, 0,
@@ -266,7 +266,7 @@ static struct drm_display_mode drm_dmt_modes[] = {
 static const int drm_num_dmt_modes =
 	sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
 
-static struct drm_display_mode edid_est_modes[] = {
+static const struct drm_display_mode edid_est_modes[] = {
 	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
 		   968, 1056, 0, 600, 601, 605, 628, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index f73ef43..9507204 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -627,6 +627,11 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
 		value = (red << info->var.red.offset) |
 			(green << info->var.green.offset) |
 			(blue << info->var.blue.offset);
+		if (info->var.transp.length > 0) {
+			u32 mask = (1 << info->var.transp.length) - 1;
+			mask <<= info->var.transp.offset;
+			value |= mask;
+		}
 		palette[regno] = value;
 		return 0;
 	}
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index ea1c4b0..57ce27c 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -101,7 +101,7 @@ drm_gem_init(struct drm_device *dev)
 
 	dev->mm_private = mm;
 
-	if (drm_ht_create(&mm->offset_hash, 19)) {
+	if (drm_ht_create(&mm->offset_hash, 12)) {
 		kfree(mm);
 		return -ENOMEM;
 	}
@@ -181,7 +181,7 @@ EXPORT_SYMBOL(drm_gem_object_alloc);
 /**
  * Removes the mapping from handle to filp for this object.
  */
-static int
+int
 drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 {
 	struct drm_device *dev;
@@ -214,6 +214,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 
 	return 0;
 }
+EXPORT_SYMBOL(drm_gem_handle_delete);
 
 /**
  * Create a handle for this object. This adds a handle reference
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index a93d7b4..e3a7568 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -39,27 +39,18 @@
 
 int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
-	unsigned int i;
+	unsigned int size = 1 << order;
 
-	ht->size = 1 << order;
 	ht->order = order;
-	ht->fill = 0;
 	ht->table = NULL;
-	ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
-	if (!ht->use_vmalloc) {
-		ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL);
-	}
-	if (!ht->table) {
-		ht->use_vmalloc = 1;
-		ht->table = vmalloc(ht->size*sizeof(*ht->table));
-	}
+	if (size <= PAGE_SIZE / sizeof(*ht->table))
+		ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
+	else
+		ht->table = vzalloc(size*sizeof(*ht->table));
 	if (!ht->table) {
 		DRM_ERROR("Out of memory for hash table\n");
 		return -ENOMEM;
 	}
-	for (i=0; i< ht->size; ++i) {
-		INIT_HLIST_HEAD(&ht->table[i]);
-	}
 	return 0;
 }
 EXPORT_SYMBOL(drm_ht_create);
@@ -180,7 +171,6 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 	list = drm_ht_find_key(ht, key);
 	if (list) {
 		hlist_del_init(list);
-		ht->fill--;
 		return 0;
 	}
 	return -EINVAL;
@@ -189,7 +179,6 @@ int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key)
 int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
 	hlist_del_init(&item->head);
-	ht->fill--;
 	return 0;
 }
 EXPORT_SYMBOL(drm_ht_remove_item);
@@ -197,10 +186,10 @@ EXPORT_SYMBOL(drm_ht_remove_item);
 void drm_ht_remove(struct drm_open_hash *ht)
 {
 	if (ht->table) {
-		if (ht->use_vmalloc)
-			vfree(ht->table);
-		else
+		if ((PAGE_SIZE / sizeof(*ht->table)) >> ht->order)
 			kfree(ht->table);
+		else
+			vfree(ht->table);
 		ht->table = NULL;
 	}
 }
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c
index be9a9c0..ab1162d 100644
--- a/drivers/gpu/drm/drm_info.c
+++ b/drivers/gpu/drm/drm_info.c
@@ -47,30 +47,19 @@ int drm_name_info(struct seq_file *m, void *data)
 	struct drm_minor *minor = node->minor;
 	struct drm_device *dev = minor->dev;
 	struct drm_master *master = minor->master;
-
+	const char *bus_name;
 	if (!master)
 		return 0;
 
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
-		if (master->unique) {
-			seq_printf(m, "%s %s %s\n",
-					dev->driver->platform_device->name,
-					dev_name(dev->dev), master->unique);
-		} else {
-			seq_printf(m, "%s\n",
-				dev->driver->platform_device->name);
-		}
+	bus_name = dev->driver->bus->get_name(dev);
+	if (master->unique) {
+		seq_printf(m, "%s %s %s\n",
+			   bus_name,
+			   dev_name(dev->dev), master->unique);
 	} else {
-		if (master->unique) {
-			seq_printf(m, "%s %s %s\n",
-				dev->driver->pci_driver.name,
-				dev_name(dev->dev), master->unique);
-		} else {
-			seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
-				dev_name(dev->dev));
-		}
+		seq_printf(m, "%s %s\n",
+			   bus_name, dev_name(dev->dev));
 	}
-
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 47db4df..7f6912a 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -96,7 +96,7 @@ int drm_setunique(struct drm_device *dev, void *data,
 {
 	struct drm_unique *u = data;
 	struct drm_master *master = file_priv->master;
-	int domain, bus, slot, func, ret;
+	int ret;
 
 	if (master->unique_len || master->unique)
 		return -EBUSY;
@@ -104,50 +104,12 @@ int drm_setunique(struct drm_device *dev, void *data,
 	if (!u->unique_len || u->unique_len > 1024)
 		return -EINVAL;
 
-	master->unique_len = u->unique_len;
-	master->unique_size = u->unique_len + 1;
-	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-	if (!master->unique) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	if (copy_from_user(master->unique, u->unique, master->unique_len)) {
-		ret = -EFAULT;
-		goto err;
-	}
-
-	master->unique[master->unique_len] = '\0';
-
-	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
-			       strlen(master->unique) + 2, GFP_KERNEL);
-	if (!dev->devname) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-		master->unique);
+	if (!dev->driver->bus->set_unique)
+		return -EINVAL;
 
-	/* Return error if the busid submitted doesn't match the device's actual
-	 * busid.
-	 */
-	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
-	if (ret != 3) {
-		ret = -EINVAL;
+	ret = dev->driver->bus->set_unique(dev, master, u);
+	if (ret)
 		goto err;
-	}
-
-	domain = bus >> 8;
-	bus &= 0xff;
-
-	if ((domain != drm_get_pci_domain(dev)) ||
-	    (bus != dev->pdev->bus->number) ||
-	    (slot != PCI_SLOT(dev->pdev->devfn)) ||
-	    (func != PCI_FUNC(dev->pdev->devfn))) {
-		ret = -EINVAL;
-		goto err;
-	}
 
 	return 0;
 
@@ -159,74 +121,15 @@ err:
 static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 {
 	struct drm_master *master = file_priv->master;
-	int len, ret;
+	int ret;
 
 	if (master->unique != NULL)
 		drm_unset_busid(dev, master);
 
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
-		master->unique_len = 10 + strlen(dev->platformdev->name);
-		master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
-
-		if (master->unique == NULL)
-			return -ENOMEM;
-
-		len = snprintf(master->unique, master->unique_len,
-			"platform:%s", dev->platformdev->name);
-
-		if (len > master->unique_len) {
-			DRM_ERROR("Unique buffer overflowed\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		dev->devname =
-			kmalloc(strlen(dev->platformdev->name) +
-				master->unique_len + 2, GFP_KERNEL);
-
-		if (dev->devname == NULL) {
-			ret = -ENOMEM;
-			goto err;
-		}
-
-		sprintf(dev->devname, "%s@%s", dev->platformdev->name,
-			master->unique);
-
-	} else {
-		master->unique_len = 40;
-		master->unique_size = master->unique_len;
-		master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-		if (master->unique == NULL)
-			return -ENOMEM;
-
-		len = snprintf(master->unique, master->unique_len,
-			"pci:%04x:%02x:%02x.%d",
-			drm_get_pci_domain(dev),
-			dev->pdev->bus->number,
-			PCI_SLOT(dev->pdev->devfn),
-			PCI_FUNC(dev->pdev->devfn));
-		if (len >= master->unique_len) {
-			DRM_ERROR("buffer overflow");
-			ret = -EINVAL;
-			goto err;
-		} else
-			master->unique_len = len;
-
-		dev->devname =
-			kmalloc(strlen(dev->driver->pci_driver.name) +
-				master->unique_len + 2, GFP_KERNEL);
-
-		if (dev->devname == NULL) {
-			ret = -ENOMEM;
-			goto err;
-		}
-
-		sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-			master->unique);
-	}
-
+	ret = dev->driver->bus->set_busid(dev, master);
+	if (ret)
+		goto err;
 	return 0;
-
 err:
 	drm_unset_busid(dev, master);
 	return ret;
@@ -365,6 +268,25 @@ int drm_getstats(struct drm_device *dev, void *data,
 }
 
 /**
+ * Get device/driver capabilities
+ */
+int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+	struct drm_get_cap *req = data;
+
+	req->value = 0;
+	switch (req->capability) {
+	case DRM_CAP_DUMB_BUFFER:
+		if (dev->driver->dumb_create)
+			req->value = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/**
  * Setversion ioctl.
  *
  * \param inode device inode.
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 28d1d3c..a34ef97 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -74,23 +74,13 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
 {
 	struct drm_irq_busid *p = data;
 
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
+	if (!dev->driver->bus->irq_by_busid)
 		return -EINVAL;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 
-	if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
-	    (p->busnum & 0xff) != dev->pdev->bus->number ||
-	    p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
-		return -EINVAL;
-
-	p->irq = dev->pdev->irq;
-
-	DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
-		  p->irq);
-
-	return 0;
+	return dev->driver->bus->irq_by_busid(dev, p);
 }
 
 /*
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index c59515b..add1737 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -64,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
 		else {
 			child =
 			    list_entry(mm->unused_nodes.next,
-				       struct drm_mm_node, free_stack);
-			list_del(&child->free_stack);
+				       struct drm_mm_node, node_list);
+			list_del(&child->node_list);
 			--mm->num_unused;
 		}
 		spin_unlock(&mm->unused_lock);
@@ -94,195 +94,242 @@ int drm_mm_pre_get(struct drm_mm *mm)
 			return ret;
 		}
 		++mm->num_unused;
-		list_add_tail(&node->free_stack, &mm->unused_nodes);
+		list_add_tail(&node->node_list, &mm->unused_nodes);
 	}
 	spin_unlock(&mm->unused_lock);
 	return 0;
 }
 EXPORT_SYMBOL(drm_mm_pre_get);
 
-static int drm_mm_create_tail_node(struct drm_mm *mm,
-				   unsigned long start,
-				   unsigned long size, int atomic)
+static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
 {
-	struct drm_mm_node *child;
-
-	child = drm_mm_kmalloc(mm, atomic);
-	if (unlikely(child == NULL))
-		return -ENOMEM;
-
-	child->free = 1;
-	child->size = size;
-	child->start = start;
-	child->mm = mm;
+	return hole_node->start + hole_node->size;
+}
 
-	list_add_tail(&child->node_list, &mm->node_list);
-	list_add_tail(&child->free_stack, &mm->free_stack);
+static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
+{
+	struct drm_mm_node *next_node =
+		list_entry(hole_node->node_list.next, struct drm_mm_node,
+			   node_list);
 
-	return 0;
+	return next_node->start;
 }
 
-static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
-						 unsigned long size,
-						 int atomic)
+static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
+				 struct drm_mm_node *node,
+				 unsigned long size, unsigned alignment)
 {
-	struct drm_mm_node *child;
+	struct drm_mm *mm = hole_node->mm;
+	unsigned long tmp = 0, wasted = 0;
+	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
+	unsigned long hole_end = drm_mm_hole_node_end(hole_node);
 
-	child = drm_mm_kmalloc(parent->mm, atomic);
-	if (unlikely(child == NULL))
-		return NULL;
+	BUG_ON(!hole_node->hole_follows || node->allocated);
 
-	INIT_LIST_HEAD(&child->free_stack);
+	if (alignment)
+		tmp = hole_start % alignment;
 
-	child->size = size;
-	child->start = parent->start;
-	child->mm = parent->mm;
+	if (!tmp) {
+		hole_node->hole_follows = 0;
+		list_del_init(&hole_node->hole_stack);
+	} else
+		wasted = alignment - tmp;
 
-	list_add_tail(&child->node_list, &parent->node_list);
-	INIT_LIST_HEAD(&child->free_stack);
+	node->start = hole_start + wasted;
+	node->size = size;
+	node->mm = mm;
+	node->allocated = 1;
 
-	parent->size -= size;
-	parent->start += size;
-	return child;
-}
+	INIT_LIST_HEAD(&node->hole_stack);
+	list_add(&node->node_list, &hole_node->node_list);
+
+	BUG_ON(node->start + node->size > hole_end);
 
+	if (node->start + node->size < hole_end) {
+		list_add(&node->hole_stack, &mm->hole_stack);
+		node->hole_follows = 1;
+	} else {
+		node->hole_follows = 0;
+	}
+}
 
-struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
+struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
 					     unsigned long size,
 					     unsigned alignment,
 					     int atomic)
 {
+	struct drm_mm_node *node;
 
-	struct drm_mm_node *align_splitoff = NULL;
-	unsigned tmp = 0;
+	node = drm_mm_kmalloc(hole_node->mm, atomic);
+	if (unlikely(node == NULL))
+		return NULL;
 
-	if (alignment)
-		tmp = node->start % alignment;
+	drm_mm_insert_helper(hole_node, node, size, alignment);
 
-	if (tmp) {
-		align_splitoff =
-		    drm_mm_split_at_start(node, alignment - tmp, atomic);
-		if (unlikely(align_splitoff == NULL))
-			return NULL;
-	}
+	return node;
+}
+EXPORT_SYMBOL(drm_mm_get_block_generic);
 
-	if (node->size == size) {
-		list_del_init(&node->free_stack);
-		node->free = 0;
-	} else {
-		node = drm_mm_split_at_start(node, size, atomic);
-	}
+/**
+ * Search for free space and insert a preallocated memory node. Returns
+ * -ENOSPC if no suitable free area is available. The preallocated memory node
+ * must be cleared.
+ */
+int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
+		       unsigned long size, unsigned alignment)
+{
+	struct drm_mm_node *hole_node;
 
-	if (align_splitoff)
-		drm_mm_put_block(align_splitoff);
+	hole_node = drm_mm_search_free(mm, size, alignment, 0);
+	if (!hole_node)
+		return -ENOSPC;
 
-	return node;
+	drm_mm_insert_helper(hole_node, node, size, alignment);
+
+	return 0;
 }
-EXPORT_SYMBOL(drm_mm_get_block_generic);
+EXPORT_SYMBOL(drm_mm_insert_node);
 
-struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long start,
-						unsigned long end,
-						int atomic)
+static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
+				       struct drm_mm_node *node,
+				       unsigned long size, unsigned alignment,
+				       unsigned long start, unsigned long end)
 {
-	struct drm_mm_node *align_splitoff = NULL;
-	unsigned tmp = 0;
-	unsigned wasted = 0;
+	struct drm_mm *mm = hole_node->mm;
+	unsigned long tmp = 0, wasted = 0;
+	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
+	unsigned long hole_end = drm_mm_hole_node_end(hole_node);
+
+	BUG_ON(!hole_node->hole_follows || node->allocated);
 
-	if (node->start < start)
-		wasted += start - node->start;
+	if (hole_start < start)
+		wasted += start - hole_start;
 	if (alignment)
-		tmp = ((node->start + wasted) % alignment);
+		tmp = (hole_start + wasted) % alignment;
 
 	if (tmp)
 		wasted += alignment - tmp;
-	if (wasted) {
-		align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
-		if (unlikely(align_splitoff == NULL))
-			return NULL;
+
+	if (!wasted) {
+		hole_node->hole_follows = 0;
+		list_del_init(&hole_node->hole_stack);
 	}
 
-	if (node->size == size) {
-		list_del_init(&node->free_stack);
-		node->free = 0;
+	node->start = hole_start + wasted;
+	node->size = size;
+	node->mm = mm;
+	node->allocated = 1;
+
+	INIT_LIST_HEAD(&node->hole_stack);
+	list_add(&node->node_list, &hole_node->node_list);
+
+	BUG_ON(node->start + node->size > hole_end);
+	BUG_ON(node->start + node->size > end);
+
+	if (node->start + node->size < hole_end) {
+		list_add(&node->hole_stack, &mm->hole_stack);
+		node->hole_follows = 1;
 	} else {
-		node = drm_mm_split_at_start(node, size, atomic);
+		node->hole_follows = 0;
 	}
+}
 
-	if (align_splitoff)
-		drm_mm_put_block(align_splitoff);
+struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end,
+						int atomic)
+{
+	struct drm_mm_node *node;
+
+	node = drm_mm_kmalloc(hole_node->mm, atomic);
+	if (unlikely(node == NULL))
+		return NULL;
+
+	drm_mm_insert_helper_range(hole_node, node, size, alignment,
+				   start, end);
 
 	return node;
 }
 EXPORT_SYMBOL(drm_mm_get_block_range_generic);
 
-/*
- * Put a block. Merge with the previous and / or next block if they are free.
- * Otherwise add to the free stack.
+/**
+ * Search for free space and insert a preallocated memory node. Returns
+ * -ENOSPC if no suitable free area is available. This is for range
+ * restricted allocations. The preallocated memory node must be cleared.
  */
-
-void drm_mm_put_block(struct drm_mm_node *cur)
+int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
+				unsigned long size, unsigned alignment,
+				unsigned long start, unsigned long end)
 {
+	struct drm_mm_node *hole_node;
 
-	struct drm_mm *mm = cur->mm;
-	struct list_head *cur_head = &cur->node_list;
-	struct list_head *root_head = &mm->node_list;
-	struct drm_mm_node *prev_node = NULL;
-	struct drm_mm_node *next_node;
+	hole_node = drm_mm_search_free_in_range(mm, size, alignment,
+						start, end, 0);
+	if (!hole_node)
+		return -ENOSPC;
 
-	int merged = 0;
+	drm_mm_insert_helper_range(hole_node, node, size, alignment,
+				   start, end);
 
-	BUG_ON(cur->scanned_block || cur->scanned_prev_free
-				  || cur->scanned_next_free);
+	return 0;
+}
+EXPORT_SYMBOL(drm_mm_insert_node_in_range);
 
-	if (cur_head->prev != root_head) {
-		prev_node =
-		    list_entry(cur_head->prev, struct drm_mm_node, node_list);
-		if (prev_node->free) {
-			prev_node->size += cur->size;
-			merged = 1;
-		}
-	}
-	if (cur_head->next != root_head) {
-		next_node =
-		    list_entry(cur_head->next, struct drm_mm_node, node_list);
-		if (next_node->free) {
-			if (merged) {
-				prev_node->size += next_node->size;
-				list_del(&next_node->node_list);
-				list_del(&next_node->free_stack);
-				spin_lock(&mm->unused_lock);
-				if (mm->num_unused < MM_UNUSED_TARGET) {
-					list_add(&next_node->free_stack,
-						 &mm->unused_nodes);
-					++mm->num_unused;
-				} else
-					kfree(next_node);
-				spin_unlock(&mm->unused_lock);
-			} else {
-				next_node->size += cur->size;
-				next_node->start = cur->start;
-				merged = 1;
-			}
-		}
-	}
-	if (!merged) {
-		cur->free = 1;
-		list_add(&cur->free_stack, &mm->free_stack);
-	} else {
-		list_del(&cur->node_list);
-		spin_lock(&mm->unused_lock);
-		if (mm->num_unused < MM_UNUSED_TARGET) {
-			list_add(&cur->free_stack, &mm->unused_nodes);
-			++mm->num_unused;
-		} else
-			kfree(cur);
-		spin_unlock(&mm->unused_lock);
-	}
+/**
+ * Remove a memory node from the allocator.
+ */
+void drm_mm_remove_node(struct drm_mm_node *node)
+{
+	struct drm_mm *mm = node->mm;
+	struct drm_mm_node *prev_node;
+
+	BUG_ON(node->scanned_block || node->scanned_prev_free
+				   || node->scanned_next_free);
+
+	prev_node =
+	    list_entry(node->node_list.prev, struct drm_mm_node, node_list);
+
+	if (node->hole_follows) {
+		BUG_ON(drm_mm_hole_node_start(node)
+				== drm_mm_hole_node_end(node));
+		list_del(&node->hole_stack);
+	} else
+		BUG_ON(drm_mm_hole_node_start(node)
+				!= drm_mm_hole_node_end(node));
+
+	if (!prev_node->hole_follows) {
+		prev_node->hole_follows = 1;
+		list_add(&prev_node->hole_stack, &mm->hole_stack);
+	} else
+		list_move(&prev_node->hole_stack, &mm->hole_stack);
+
+	list_del(&node->node_list);
+	node->allocated = 0;
 }
+EXPORT_SYMBOL(drm_mm_remove_node);
+
+/*
+ * Remove a memory node from the allocator and free the allocated struct
+ * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
+ * drm_mm_get_block functions.
+ */
+void drm_mm_put_block(struct drm_mm_node *node)
+{
 
+	struct drm_mm *mm = node->mm;
+
+	drm_mm_remove_node(node);
+
+	spin_lock(&mm->unused_lock);
+	if (mm->num_unused < MM_UNUSED_TARGET) {
+		list_add(&node->node_list, &mm->unused_nodes);
+		++mm->num_unused;
+	} else
+		kfree(node);
+	spin_unlock(&mm->unused_lock);
+}
 EXPORT_SYMBOL(drm_mm_put_block);
 
 static int check_free_hole(unsigned long start, unsigned long end,
@@ -319,8 +366,10 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
 	best = NULL;
 	best_size = ~0UL;
 
-	list_for_each_entry(entry, &mm->free_stack, free_stack) {
-		if (!check_free_hole(entry->start, entry->start + entry->size,
+	list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
+		BUG_ON(!entry->hole_follows);
+		if (!check_free_hole(drm_mm_hole_node_start(entry),
+				     drm_mm_hole_node_end(entry),
 				     size, alignment))
 			continue;
 
@@ -353,12 +402,13 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
 	best = NULL;
 	best_size = ~0UL;
 
-	list_for_each_entry(entry, &mm->free_stack, free_stack) {
-		unsigned long adj_start = entry->start < start ?
-			start : entry->start;
-		unsigned long adj_end = entry->start + entry->size > end ?
-			end : entry->start + entry->size;
+	list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
+		unsigned long adj_start = drm_mm_hole_node_start(entry) < start ?
+			start : drm_mm_hole_node_start(entry);
+		unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
+			end : drm_mm_hole_node_end(entry);
 
+		BUG_ON(!entry->hole_follows);
 		if (!check_free_hole(adj_start, adj_end, size, alignment))
 			continue;
 
@@ -376,6 +426,23 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
 EXPORT_SYMBOL(drm_mm_search_free_in_range);
 
 /**
+ * Moves an allocation. To be used with embedded struct drm_mm_node.
+ */
+void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
+{
+	list_replace(&old->node_list, &new->node_list);
+	list_replace(&old->node_list, &new->hole_stack);
+	new->hole_follows = old->hole_follows;
+	new->mm = old->mm;
+	new->start = old->start;
+	new->size = old->size;
+
+	old->allocated = 0;
+	new->allocated = 1;
+}
+EXPORT_SYMBOL(drm_mm_replace_node);
+
+/**
  * Initializa lru scanning.
  *
  * This simply sets up the scanning routines with the parameters for the desired
@@ -393,6 +460,7 @@ void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
 	mm->scan_hit_start = 0;
 	mm->scan_hit_size = 0;
 	mm->scan_check_range = 0;
+	mm->prev_scanned_node = NULL;
 }
 EXPORT_SYMBOL(drm_mm_init_scan);
 
@@ -418,6 +486,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size,
 	mm->scan_start = start;
 	mm->scan_end = end;
 	mm->scan_check_range = 1;
+	mm->prev_scanned_node = NULL;
 }
 EXPORT_SYMBOL(drm_mm_init_scan_with_range);
 
@@ -430,70 +499,42 @@ EXPORT_SYMBOL(drm_mm_init_scan_with_range);
 int drm_mm_scan_add_block(struct drm_mm_node *node)
 {
 	struct drm_mm *mm = node->mm;
-	struct list_head *prev_free, *next_free;
-	struct drm_mm_node *prev_node, *next_node;
+	struct drm_mm_node *prev_node;
+	unsigned long hole_start, hole_end;
 	unsigned long adj_start;
 	unsigned long adj_end;
 
 	mm->scanned_blocks++;
 
-	prev_free = next_free = NULL;
-
-	BUG_ON(node->free);
+	BUG_ON(node->scanned_block);
 	node->scanned_block = 1;
-	node->free = 1;
-
-	if (node->node_list.prev != &mm->node_list) {
-		prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
-				       node_list);
-
-		if (prev_node->free) {
-			list_del(&prev_node->node_list);
 
-			node->start = prev_node->start;
-			node->size += prev_node->size;
+	prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
+			       node_list);
 
-			prev_node->scanned_prev_free = 1;
-
-			prev_free = &prev_node->free_stack;
-		}
-	}
-
-	if (node->node_list.next != &mm->node_list) {
-		next_node = list_entry(node->node_list.next, struct drm_mm_node,
-				       node_list);
-
-		if (next_node->free) {
-			list_del(&next_node->node_list);
-
-			node->size += next_node->size;
-
-			next_node->scanned_next_free = 1;
-
-			next_free = &next_node->free_stack;
-		}
-	}
-
-	/* The free_stack list is not used for allocated objects, so these two
-	 * pointers can be abused (as long as no allocations in this memory
-	 * manager happens). */
-	node->free_stack.prev = prev_free;
-	node->free_stack.next = next_free;
+	node->scanned_preceeds_hole = prev_node->hole_follows;
+	prev_node->hole_follows = 1;
+	list_del(&node->node_list);
+	node->node_list.prev = &prev_node->node_list;
+	node->node_list.next = &mm->prev_scanned_node->node_list;
+	mm->prev_scanned_node = node;
 
+	hole_start = drm_mm_hole_node_start(prev_node);
+	hole_end = drm_mm_hole_node_end(prev_node);
 	if (mm->scan_check_range) {
-		adj_start = node->start < mm->scan_start ?
-			mm->scan_start : node->start;
-		adj_end = node->start + node->size > mm->scan_end ?
-			mm->scan_end : node->start + node->size;
+		adj_start = hole_start < mm->scan_start ?
+			mm->scan_start : hole_start;
+		adj_end = hole_end > mm->scan_end ?
+			mm->scan_end : hole_end;
 	} else {
-		adj_start = node->start;
-		adj_end = node->start + node->size;
+		adj_start = hole_start;
+		adj_end = hole_end;
 	}
 
 	if (check_free_hole(adj_start , adj_end,
 			    mm->scan_size, mm->scan_alignment)) {
-		mm->scan_hit_start = node->start;
-		mm->scan_hit_size = node->size;
+		mm->scan_hit_start = hole_start;
+		mm->scan_hit_size = hole_end;
 
 		return 1;
 	}
@@ -519,39 +560,19 @@ EXPORT_SYMBOL(drm_mm_scan_add_block);
 int drm_mm_scan_remove_block(struct drm_mm_node *node)
 {
 	struct drm_mm *mm = node->mm;
-	struct drm_mm_node *prev_node, *next_node;
+	struct drm_mm_node *prev_node;
 
 	mm->scanned_blocks--;
 
 	BUG_ON(!node->scanned_block);
 	node->scanned_block = 0;
-	node->free = 0;
-
-	prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
-			       free_stack);
-	next_node = list_entry(node->free_stack.next, struct drm_mm_node,
-			       free_stack);
 
-	if (prev_node) {
-		BUG_ON(!prev_node->scanned_prev_free);
-		prev_node->scanned_prev_free = 0;
-
-		list_add_tail(&prev_node->node_list, &node->node_list);
-
-		node->start = prev_node->start + prev_node->size;
-		node->size -= prev_node->size;
-	}
+	prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
+			       node_list);
 
-	if (next_node) {
-		BUG_ON(!next_node->scanned_next_free);
-		next_node->scanned_next_free = 0;
-
-		list_add(&next_node->node_list, &node->node_list);
-
-		node->size -= next_node->size;
-	}
-
-	INIT_LIST_HEAD(&node->free_stack);
+	prev_node->hole_follows = node->scanned_preceeds_hole;
+	INIT_LIST_HEAD(&node->node_list);
+	list_add(&node->node_list, &prev_node->node_list);
 
 	/* Only need to check for containement because start&size for the
 	 * complete resulting free block (not just the desired part) is
@@ -568,7 +589,7 @@ EXPORT_SYMBOL(drm_mm_scan_remove_block);
 
 int drm_mm_clean(struct drm_mm * mm)
 {
-	struct list_head *head = &mm->node_list;
+	struct list_head *head = &mm->head_node.node_list;
 
 	return (head->next->next == head);
 }
@@ -576,38 +597,40 @@ EXPORT_SYMBOL(drm_mm_clean);
 
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
-	INIT_LIST_HEAD(&mm->node_list);
-	INIT_LIST_HEAD(&mm->free_stack);
+	INIT_LIST_HEAD(&mm->hole_stack);
 	INIT_LIST_HEAD(&mm->unused_nodes);
 	mm->num_unused = 0;
 	mm->scanned_blocks = 0;
 	spin_lock_init(&mm->unused_lock);
 
-	return drm_mm_create_tail_node(mm, start, size, 0);
+	/* Clever trick to avoid a special case in the free hole tracking. */
+	INIT_LIST_HEAD(&mm->head_node.node_list);
+	INIT_LIST_HEAD(&mm->head_node.hole_stack);
+	mm->head_node.hole_follows = 1;
+	mm->head_node.scanned_block = 0;
+	mm->head_node.scanned_prev_free = 0;
+	mm->head_node.scanned_next_free = 0;
+	mm->head_node.mm = mm;
+	mm->head_node.start = start + size;
+	mm->head_node.size = start - mm->head_node.start;
+	list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_mm_init);
 
 void drm_mm_takedown(struct drm_mm * mm)
 {
-	struct list_head *bnode = mm->free_stack.next;
-	struct drm_mm_node *entry;
-	struct drm_mm_node *next;
+	struct drm_mm_node *entry, *next;
 
-	entry = list_entry(bnode, struct drm_mm_node, free_stack);
-
-	if (entry->node_list.next != &mm->node_list ||
-	    entry->free_stack.next != &mm->free_stack) {
+	if (!list_empty(&mm->head_node.node_list)) {
 		DRM_ERROR("Memory manager not clean. Delaying takedown\n");
 		return;
 	}
 
-	list_del(&entry->free_stack);
-	list_del(&entry->node_list);
-	kfree(entry);
-
 	spin_lock(&mm->unused_lock);
-	list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
-		list_del(&entry->free_stack);
+	list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) {
+		list_del(&entry->node_list);
 		kfree(entry);
 		--mm->num_unused;
 	}
@@ -620,19 +643,37 @@ EXPORT_SYMBOL(drm_mm_takedown);
 void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
 {
 	struct drm_mm_node *entry;
-	int total_used = 0, total_free = 0, total = 0;
-
-	list_for_each_entry(entry, &mm->node_list, node_list) {
-		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
+	unsigned long total_used = 0, total_free = 0, total = 0;
+	unsigned long hole_start, hole_end, hole_size;
+
+	hole_start = drm_mm_hole_node_start(&mm->head_node);
+	hole_end = drm_mm_hole_node_end(&mm->head_node);
+	hole_size = hole_end - hole_start;
+	if (hole_size)
+		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
+			prefix, hole_start, hole_end,
+			hole_size);
+	total_free += hole_size;
+
+	drm_mm_for_each_node(entry, mm) {
+		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
 			prefix, entry->start, entry->start + entry->size,
-			entry->size, entry->free ? "free" : "used");
-		total += entry->size;
-		if (entry->free)
-			total_free += entry->size;
-		else
-			total_used += entry->size;
+			entry->size);
+		total_used += entry->size;
+
+		if (entry->hole_follows) {
+			hole_start = drm_mm_hole_node_start(entry);
+			hole_end = drm_mm_hole_node_end(entry);
+			hole_size = hole_end - hole_start;
+			printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
+				prefix, hole_start, hole_end,
+				hole_size);
+			total_free += hole_size;
+		}
 	}
-	printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
+	total = total_free + total_used;
+
+	printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
 		total_used, total_free);
 }
 EXPORT_SYMBOL(drm_mm_debug_table);
@@ -641,17 +682,34 @@ EXPORT_SYMBOL(drm_mm_debug_table);
 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
 {
 	struct drm_mm_node *entry;
-	int total_used = 0, total_free = 0, total = 0;
-
-	list_for_each_entry(entry, &mm->node_list, node_list) {
-		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
-		total += entry->size;
-		if (entry->free)
-			total_free += entry->size;
-		else
-			total_used += entry->size;
+	unsigned long total_used = 0, total_free = 0, total = 0;
+	unsigned long hole_start, hole_end, hole_size;
+
+	hole_start = drm_mm_hole_node_start(&mm->head_node);
+	hole_end = drm_mm_hole_node_end(&mm->head_node);
+	hole_size = hole_end - hole_start;
+	if (hole_size)
+		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
+				hole_start, hole_end, hole_size);
+	total_free += hole_size;
+
+	drm_mm_for_each_node(entry, mm) {
+		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
+				entry->start, entry->start + entry->size,
+				entry->size);
+		total_used += entry->size;
+		if (entry->hole_follows) {
+			hole_start = drm_mm_hole_node_start(&mm->head_node);
+			hole_end = drm_mm_hole_node_end(&mm->head_node);
+			hole_size = hole_end - hole_start;
+			seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
+					hole_start, hole_end, hole_size);
+			total_free += hole_size;
+		}
 	}
-	seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
+	total = total_free + total_used;
+
+	seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
 	return 0;
 }
 EXPORT_SYMBOL(drm_mm_dump_table);
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 58e65f9..25bf873 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -593,7 +593,7 @@ EXPORT_SYMBOL(drm_mode_height);
  *
  * Return @modes's hsync rate in kHz, rounded to the nearest int.
  */
-int drm_mode_hsync(struct drm_display_mode *mode)
+int drm_mode_hsync(const struct drm_display_mode *mode)
 {
 	unsigned int calc_val;
 
@@ -627,7 +627,7 @@ EXPORT_SYMBOL(drm_mode_hsync);
  * If it is 70.288, it will return 70Hz.
  * If it is 59.6, it will return 60Hz.
  */
-int drm_mode_vrefresh(struct drm_display_mode *mode)
+int drm_mode_vrefresh(const struct drm_display_mode *mode)
 {
 	int refresh = 0;
 	unsigned int calc_val;
@@ -725,7 +725,7 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo);
  * a pointer to it.  Used to create new instances of established modes.
  */
 struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
-					    struct drm_display_mode *mode)
+					    const struct drm_display_mode *mode)
 {
 	struct drm_display_mode *nmode;
 	int new_id;
diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
index f5bd9e5..e1aee4f 100644
--- a/drivers/gpu/drm/drm_pci.c
+++ b/drivers/gpu/drm/drm_pci.c
@@ -125,6 +125,176 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 EXPORT_SYMBOL(drm_pci_free);
 
 #ifdef CONFIG_PCI
+
+static int drm_get_pci_domain(struct drm_device *dev)
+{
+#ifndef __alpha__
+	/* For historical reasons, drm_get_pci_domain() is busticated
+	 * on most archs and has to remain so for userspace interface
+	 * < 1.4, except on alpha which was right from the beginning
+	 */
+	if (dev->if_version < 0x10004)
+		return 0;
+#endif /* __alpha__ */
+
+	return pci_domain_nr(dev->pdev->bus);
+}
+
+static int drm_pci_get_irq(struct drm_device *dev)
+{
+	return dev->pdev->irq;
+}
+
+static const char *drm_pci_get_name(struct drm_device *dev)
+{
+	struct pci_driver *pdriver = dev->driver->kdriver.pci;
+	return pdriver->name;
+}
+
+int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
+{
+	int len, ret;
+	struct pci_driver *pdriver = dev->driver->kdriver.pci;
+	master->unique_len = 40;
+	master->unique_size = master->unique_len;
+	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+	if (master->unique == NULL)
+		return -ENOMEM;
+
+
+	len = snprintf(master->unique, master->unique_len,
+		       "pci:%04x:%02x:%02x.%d",
+		       drm_get_pci_domain(dev),
+		       dev->pdev->bus->number,
+		       PCI_SLOT(dev->pdev->devfn),
+		       PCI_FUNC(dev->pdev->devfn));
+
+	if (len >= master->unique_len) {
+		DRM_ERROR("buffer overflow");
+		ret = -EINVAL;
+		goto err;
+	} else
+		master->unique_len = len;
+
+	dev->devname =
+		kmalloc(strlen(pdriver->name) +
+			master->unique_len + 2, GFP_KERNEL);
+
+	if (dev->devname == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sprintf(dev->devname, "%s@%s", pdriver->name,
+		master->unique);
+
+	return 0;
+err:
+	return ret;
+}
+
+int drm_pci_set_unique(struct drm_device *dev,
+		       struct drm_master *master,
+		       struct drm_unique *u)
+{
+	int domain, bus, slot, func, ret;
+	const char *bus_name;
+
+	master->unique_len = u->unique_len;
+	master->unique_size = u->unique_len + 1;
+	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+	if (!master->unique) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (copy_from_user(master->unique, u->unique, master->unique_len)) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	master->unique[master->unique_len] = '\0';
+
+	bus_name = dev->driver->bus->get_name(dev);
+	dev->devname = kmalloc(strlen(bus_name) +
+			       strlen(master->unique) + 2, GFP_KERNEL);
+	if (!dev->devname) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sprintf(dev->devname, "%s@%s", bus_name,
+		master->unique);
+
+	/* Return error if the busid submitted doesn't match the device's actual
+	 * busid.
+	 */
+	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+	if (ret != 3) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	domain = bus >> 8;
+	bus &= 0xff;
+
+	if ((domain != drm_get_pci_domain(dev)) ||
+	    (bus != dev->pdev->bus->number) ||
+	    (slot != PCI_SLOT(dev->pdev->devfn)) ||
+	    (func != PCI_FUNC(dev->pdev->devfn))) {
+		ret = -EINVAL;
+		goto err;
+	}
+	return 0;
+err:
+	return ret;
+}
+
+
+int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
+{
+	if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+	    (p->busnum & 0xff) != dev->pdev->bus->number ||
+	    p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
+		return -EINVAL;
+
+	p->irq = dev->pdev->irq;
+
+	DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
+		  p->irq);
+	return 0;
+}
+
+int drm_pci_agp_init(struct drm_device *dev)
+{
+	if (drm_core_has_AGP(dev)) {
+		if (drm_pci_device_is_agp(dev))
+			dev->agp = drm_agp_init(dev);
+		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
+		    && (dev->agp == NULL)) {
+			DRM_ERROR("Cannot initialize the agpgart module.\n");
+			return -EINVAL;
+		}
+		if (drm_core_has_MTRR(dev)) {
+			if (dev->agp)
+				dev->agp->agp_mtrr =
+					mtrr_add(dev->agp->agp_info.aper_base,
+						 dev->agp->agp_info.aper_size *
+						 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+		}
+	}
+	return 0;
+}
+
+static struct drm_bus drm_pci_bus = {
+	.bus_type = DRIVER_BUS_PCI,
+	.get_irq = drm_pci_get_irq,
+	.get_name = drm_pci_get_name,
+	.set_busid = drm_pci_set_busid,
+	.set_unique = drm_pci_set_unique,
+	.agp_init = drm_pci_agp_init,
+};
+
 /**
  * Register.
  *
@@ -219,7 +389,7 @@ err_g1:
 EXPORT_SYMBOL(drm_get_pci_dev);
 
 /**
- * PCI device initialization. Called via drm_init at module load time,
+ * PCI device initialization. Called direct from modules at load time.
  *
  * \return zero on success or a negative number on failure.
  *
@@ -229,18 +399,24 @@ EXPORT_SYMBOL(drm_get_pci_dev);
  * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
  * after the initialization for driver customization.
  */
-int drm_pci_init(struct drm_driver *driver)
+int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 {
 	struct pci_dev *pdev = NULL;
 	const struct pci_device_id *pid;
 	int i;
 
+	DRM_DEBUG("\n");
+
+	INIT_LIST_HEAD(&driver->device_list);
+	driver->kdriver.pci = pdriver;
+	driver->bus = &drm_pci_bus;
+
 	if (driver->driver_features & DRIVER_MODESET)
-		return pci_register_driver(&driver->pci_driver);
+		return pci_register_driver(pdriver);
 
 	/* If not using KMS, fall back to stealth mode manual scanning. */
-	for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
-		pid = &driver->pci_driver.id_table[i];
+	for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
+		pid = &pdriver->id_table[i];
 
 		/* Loop around setting up a DRM device for each PCI device
 		 * matching our ID and device class.  If we had the internal
@@ -265,10 +441,27 @@ int drm_pci_init(struct drm_driver *driver)
 
 #else
 
-int drm_pci_init(struct drm_driver *driver)
+int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 {
 	return -1;
 }
 
 #endif
+
+EXPORT_SYMBOL(drm_pci_init);
+
 /*@}*/
+void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
+{
+	struct drm_device *dev, *tmp;
+	DRM_DEBUG("\n");
+
+	if (driver->driver_features & DRIVER_MODESET) {
+		pci_unregister_driver(pdriver);
+	} else {
+		list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+			drm_put_dev(dev);
+	}
+	DRM_INFO("Module unloaded\n");
+}
+EXPORT_SYMBOL(drm_pci_exit);
diff --git a/drivers/gpu/drm/drm_platform.c b/drivers/gpu/drm/drm_platform.c
index 92d1d0f..7223f06 100644
--- a/drivers/gpu/drm/drm_platform.c
+++ b/drivers/gpu/drm/drm_platform.c
@@ -109,8 +109,60 @@ err_g1:
 }
 EXPORT_SYMBOL(drm_get_platform_dev);
 
+static int drm_platform_get_irq(struct drm_device *dev)
+{
+	return platform_get_irq(dev->platformdev, 0);
+}
+
+static const char *drm_platform_get_name(struct drm_device *dev)
+{
+	return dev->platformdev->name;
+}
+
+static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master)
+{
+	int len, ret;
+
+	master->unique_len = 10 + strlen(dev->platformdev->name);
+	master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
+
+	if (master->unique == NULL)
+		return -ENOMEM;
+
+	len = snprintf(master->unique, master->unique_len,
+		       "platform:%s", dev->platformdev->name);
+
+	if (len > master->unique_len) {
+		DRM_ERROR("Unique buffer overflowed\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	dev->devname =
+		kmalloc(strlen(dev->platformdev->name) +
+			master->unique_len + 2, GFP_KERNEL);
+
+	if (dev->devname == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sprintf(dev->devname, "%s@%s", dev->platformdev->name,
+		master->unique);
+	return 0;
+err:
+	return ret;
+}
+
+static struct drm_bus drm_platform_bus = {
+	.bus_type = DRIVER_BUS_PLATFORM,
+	.get_irq = drm_platform_get_irq,
+	.get_name = drm_platform_get_name,
+	.set_busid = drm_platform_set_busid,
+};
+
 /**
- * Platform device initialization. Called via drm_init at module load time,
+ * Platform device initialization. Called direct from modules.
  *
  * \return zero on success or a negative number on failure.
  *
@@ -121,7 +173,24 @@ EXPORT_SYMBOL(drm_get_platform_dev);
  * after the initialization for driver customization.
  */
 
-int drm_platform_init(struct drm_driver *driver)
+int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device)
 {
-	return drm_get_platform_dev(driver->platform_device, driver);
+	DRM_DEBUG("\n");
+
+	driver->kdriver.platform_device = platform_device;
+	driver->bus = &drm_platform_bus;
+	INIT_LIST_HEAD(&driver->device_list);
+	return drm_get_platform_dev(platform_device, driver);
+}
+EXPORT_SYMBOL(drm_platform_init);
+
+void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device)
+{
+	struct drm_device *dev, *tmp;
+	DRM_DEBUG("\n");
+
+	list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+		drm_put_dev(dev);
+	DRM_INFO("Module unloaded\n");
 }
+EXPORT_SYMBOL(drm_platform_exit);
diff --git a/drivers/gpu/drm/drm_sman.c b/drivers/gpu/drm/drm_sman.c
index 463aed9..3466458 100644
--- a/drivers/gpu/drm/drm_sman.c
+++ b/drivers/gpu/drm/drm_sman.c
@@ -59,9 +59,7 @@ drm_sman_init(struct drm_sman * sman, unsigned int num_managers,
 {
 	int ret = 0;
 
-	sman->mm = (struct drm_sman_mm *) kcalloc(num_managers,
-						  sizeof(*sman->mm),
-						  GFP_KERNEL);
+	sman->mm = kcalloc(num_managers, sizeof(*sman->mm), GFP_KERNEL);
 	if (!sman->mm) {
 		ret = -ENOMEM;
 		goto out;
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index d59edc1..001273d 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -269,25 +269,14 @@ int drm_fill_in_dev(struct drm_device *dev,
 
 	dev->driver = driver;
 
-	if (drm_core_has_AGP(dev)) {
-		if (drm_device_is_agp(dev))
-			dev->agp = drm_agp_init(dev);
-		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
-		    && (dev->agp == NULL)) {
-			DRM_ERROR("Cannot initialize the agpgart module.\n");
-			retcode = -EINVAL;
+	if (dev->driver->bus->agp_init) {
+		retcode = dev->driver->bus->agp_init(dev);
+		if (retcode)
 			goto error_out_unreg;
-		}
-		if (drm_core_has_MTRR(dev)) {
-			if (dev->agp)
-				dev->agp->agp_mtrr =
-				    mtrr_add(dev->agp->agp_info.aper_base,
-					     dev->agp->agp_info.aper_size *
-					     1024 * 1024, MTRR_TYPE_WRCOMB, 1);
-		}
 	}
 
 
+
 	retcode = drm_ctxbitmap_init(dev);
 	if (retcode) {
 		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
@@ -425,7 +414,6 @@ int drm_put_minor(struct drm_minor **minor_p)
  *
  * Cleans up all DRM device, calling drm_lastclose().
  *
- * \sa drm_init
  */
 void drm_put_dev(struct drm_device *dev)
 {
@@ -475,6 +463,7 @@ void drm_put_dev(struct drm_device *dev)
 
 	drm_put_minor(&dev->primary);
 
+	list_del(&dev->driver_item);
 	if (dev->devname) {
 		kfree(dev->devname);
 		dev->devname = NULL;
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 85da4c4..2eee8e0 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -158,8 +158,15 @@ static ssize_t status_show(struct device *device,
 {
 	struct drm_connector *connector = to_drm_connector(device);
 	enum drm_connector_status status;
+	int ret;
+
+	ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex);
+	if (ret)
+		return ret;
 
 	status = connector->funcs->detect(connector, true);
+	mutex_unlock(&connector->dev->mode_config.mutex);
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",
 			drm_get_connector_status_name(status));
 }
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c
new file mode 100644
index 0000000..206d230
--- /dev/null
+++ b/drivers/gpu/drm/drm_usb.c
@@ -0,0 +1,117 @@
+#include "drmP.h"
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB
+int drm_get_usb_dev(struct usb_interface *interface,
+		    const struct usb_device_id *id,
+		    struct drm_driver *driver)
+{
+	struct drm_device *dev;
+	struct usb_device *usbdev;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	usbdev = interface_to_usbdev(interface);
+	dev->usbdev = usbdev;
+	dev->dev = &usbdev->dev;
+
+	mutex_lock(&drm_global_mutex);
+
+	ret = drm_fill_in_dev(dev, NULL, driver);
+	if (ret) {
+		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+		goto err_g1;
+	}
+
+	usb_set_intfdata(interface, dev);
+	ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+	if (ret)
+		goto err_g1;
+
+	ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
+	if (ret)
+		goto err_g2;
+
+	if (dev->driver->load) {
+		ret = dev->driver->load(dev, 0);
+		if (ret)
+			goto err_g3;
+	}
+
+	/* setup the grouping for the legacy output */
+	ret = drm_mode_group_init_legacy_group(dev,
+					       &dev->primary->mode_group);
+	if (ret)
+		goto err_g3;
+
+	list_add_tail(&dev->driver_item, &driver->device_list);
+
+	mutex_unlock(&drm_global_mutex);
+
+	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+		 driver->name, driver->major, driver->minor, driver->patchlevel,
+		 driver->date, dev->primary->index);
+
+	return 0;
+
+err_g3:
+	drm_put_minor(&dev->primary);
+err_g2:
+	drm_put_minor(&dev->control);
+err_g1:
+	kfree(dev);
+	mutex_unlock(&drm_global_mutex);
+	return ret;
+
+}
+EXPORT_SYMBOL(drm_get_usb_dev);
+
+static int drm_usb_get_irq(struct drm_device *dev)
+{
+	return 0;
+}
+
+static const char *drm_usb_get_name(struct drm_device *dev)
+{
+	return "USB";
+}
+
+static int drm_usb_set_busid(struct drm_device *dev,
+			       struct drm_master *master)
+{
+	return 0;
+}
+
+static struct drm_bus drm_usb_bus = {
+	.bus_type = DRIVER_BUS_USB,
+	.get_irq = drm_usb_get_irq,
+	.get_name = drm_usb_get_name,
+	.set_busid = drm_usb_set_busid,
+};
+    
+int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver)
+{
+	int res;
+	DRM_DEBUG("\n");
+
+	INIT_LIST_HEAD(&driver->device_list);
+	driver->kdriver.usb = udriver;
+	driver->bus = &drm_usb_bus;
+
+	res = usb_register(udriver);
+	return res;
+}
+EXPORT_SYMBOL(drm_usb_init);
+
+void drm_usb_exit(struct drm_driver *driver,
+		  struct usb_driver *udriver)
+{
+	usb_deregister(udriver);
+}
+EXPORT_SYMBOL(drm_usb_exit);
+#endif
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index ff33e53..8f371e8 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -37,7 +37,6 @@
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 
 #define I810_BUF_FREE		2
@@ -94,7 +93,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 	struct drm_buf *buf;
 	drm_i810_buf_priv_t *buf_priv;
 
-	lock_kernel();
 	dev = priv->minor->dev;
 	dev_priv = dev->dev_private;
 	buf = dev_priv->mmap_buffer;
@@ -104,7 +102,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 	vma->vm_file = filp;
 
 	buf_priv->currently_mapped = I810_BUF_MAPPED;
-	unlock_kernel();
 
 	if (io_remap_pfn_range(vma, vma->vm_start,
 			       vma->vm_pgoff,
@@ -116,7 +113,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
 static const struct file_operations i810_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
-	.unlocked_ioctl = i810_ioctl,
+	.unlocked_ioctl = drm_ioctl,
 	.mmap = i810_mmap_buffers,
 	.fasync = drm_fasync,
 	.llseek = noop_llseek,
@@ -1242,19 +1239,6 @@ int i810_driver_dma_quiescent(struct drm_device *dev)
 	return 0;
 }
 
-/*
- * call the drm_ioctl under the big kernel lock because
- * to lock against the i810_mmap_buffers function.
- */
-long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	lock_kernel();
-	ret = drm_ioctl(file, cmd, arg);
-	unlock_kernel();
-	return ret;
-}
-
 struct drm_ioctl_desc i810_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
index 88bcd33..6f98d05 100644
--- a/drivers/gpu/drm/i810/i810_drv.c
+++ b/drivers/gpu/drm/i810/i810_drv.c
@@ -57,18 +57,13 @@ static struct drm_driver driver = {
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .unlocked_ioctl = i810_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -77,15 +72,24 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver i810_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init i810_init(void)
 {
+	if (num_possible_cpus() > 1) {
+		pr_err("drm/i810 does not support SMP\n");
+		return -EINVAL;
+	}
 	driver.num_ioctls = i810_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &i810_pci_driver);
 }
 
 static void __exit i810_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &i810_pci_driver);
 }
 
 module_init(i810_init);
diff --git a/drivers/gpu/drm/i830/Makefile b/drivers/gpu/drm/i830/Makefile
deleted file mode 100644
index c642ee0..0000000
--- a/drivers/gpu/drm/i830/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the drm device driver.  This driver provides support for the
-# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-
-ccflags-y := -Iinclude/drm
-i830-y := i830_drv.o i830_dma.o i830_irq.o
-
-obj-$(CONFIG_DRM_I830) += i830.o
diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c
deleted file mode 100644
index ca6f31f..0000000
--- a/drivers/gpu/drm/i830/i830_dma.c
+++ /dev/null
@@ -1,1560 +0,0 @@
-/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *	    Keith Whitwell <keith@tungstengraphics.com>
- *	    Abraham vd Merwe <abraham@2d3d.co.za>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/smp_lock.h>
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
-#define I830_BUF_FREE		2
-#define I830_BUF_CLIENT		1
-#define I830_BUF_HARDWARE	0
-
-#define I830_BUF_UNMAPPED 0
-#define I830_BUF_MAPPED   1
-
-static struct drm_buf *i830_freelist_get(struct drm_device * dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int i;
-	int used;
-
-	/* Linear search might not be the best solution */
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-		/* In use is already a pointer */
-		used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
-			       I830_BUF_CLIENT);
-		if (used == I830_BUF_FREE)
-			return buf;
-	}
-	return NULL;
-}
-
-/* This should only be called if the buffer is not sent to the hardware
- * yet, the hardware updates in use for us once its on the ring buffer.
- */
-
-static int i830_freelist_put(struct drm_device *dev, struct drm_buf *buf)
-{
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	int used;
-
-	/* In use is already a pointer */
-	used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
-	if (used != I830_BUF_CLIENT) {
-		DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
-{
-	struct drm_file *priv = filp->private_data;
-	struct drm_device *dev;
-	drm_i830_private_t *dev_priv;
-	struct drm_buf *buf;
-	drm_i830_buf_priv_t *buf_priv;
-
-	lock_kernel();
-	dev = priv->minor->dev;
-	dev_priv = dev->dev_private;
-	buf = dev_priv->mmap_buffer;
-	buf_priv = buf->dev_private;
-
-	vma->vm_flags |= (VM_IO | VM_DONTCOPY);
-	vma->vm_file = filp;
-
-	buf_priv->currently_mapped = I830_BUF_MAPPED;
-	unlock_kernel();
-
-	if (io_remap_pfn_range(vma, vma->vm_start,
-			       vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start, vma->vm_page_prot))
-		return -EAGAIN;
-	return 0;
-}
-
-static const struct file_operations i830_buffer_fops = {
-	.open = drm_open,
-	.release = drm_release,
-	.unlocked_ioctl = i830_ioctl,
-	.mmap = i830_mmap_buffers,
-	.fasync = drm_fasync,
-	.llseek = noop_llseek,
-};
-
-static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
-{
-	struct drm_device *dev = file_priv->minor->dev;
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	const struct file_operations *old_fops;
-	unsigned long virtual;
-	int retcode = 0;
-
-	if (buf_priv->currently_mapped == I830_BUF_MAPPED)
-		return -EINVAL;
-
-	down_write(&current->mm->mmap_sem);
-	old_fops = file_priv->filp->f_op;
-	file_priv->filp->f_op = &i830_buffer_fops;
-	dev_priv->mmap_buffer = buf;
-	virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE,
-			  MAP_SHARED, buf->bus_address);
-	dev_priv->mmap_buffer = NULL;
-	file_priv->filp->f_op = old_fops;
-	if (IS_ERR((void *)virtual)) {	/* ugh */
-		/* Real error */
-		DRM_ERROR("mmap error\n");
-		retcode = PTR_ERR((void *)virtual);
-		buf_priv->virtual = NULL;
-	} else {
-		buf_priv->virtual = (void __user *)virtual;
-	}
-	up_write(&current->mm->mmap_sem);
-
-	return retcode;
-}
-
-static int i830_unmap_buffer(struct drm_buf *buf)
-{
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	int retcode = 0;
-
-	if (buf_priv->currently_mapped != I830_BUF_MAPPED)
-		return -EINVAL;
-
-	down_write(&current->mm->mmap_sem);
-	retcode = do_munmap(current->mm,
-			    (unsigned long)buf_priv->virtual,
-			    (size_t) buf->total);
-	up_write(&current->mm->mmap_sem);
-
-	buf_priv->currently_mapped = I830_BUF_UNMAPPED;
-	buf_priv->virtual = NULL;
-
-	return retcode;
-}
-
-static int i830_dma_get_buffer(struct drm_device *dev, drm_i830_dma_t *d,
-			       struct drm_file *file_priv)
-{
-	struct drm_buf *buf;
-	drm_i830_buf_priv_t *buf_priv;
-	int retcode = 0;
-
-	buf = i830_freelist_get(dev);
-	if (!buf) {
-		retcode = -ENOMEM;
-		DRM_DEBUG("retcode=%d\n", retcode);
-		return retcode;
-	}
-
-	retcode = i830_map_buffer(buf, file_priv);
-	if (retcode) {
-		i830_freelist_put(dev, buf);
-		DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
-		return retcode;
-	}
-	buf->file_priv = file_priv;
-	buf_priv = buf->dev_private;
-	d->granted = 1;
-	d->request_idx = buf->idx;
-	d->request_size = buf->total;
-	d->virtual = buf_priv->virtual;
-
-	return retcode;
-}
-
-static int i830_dma_cleanup(struct drm_device *dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
-	if (dev->dev_private) {
-		int i;
-		drm_i830_private_t *dev_priv =
-		    (drm_i830_private_t *) dev->dev_private;
-
-		if (dev_priv->ring.virtual_start)
-			drm_core_ioremapfree(&dev_priv->ring.map, dev);
-		if (dev_priv->hw_status_page) {
-			pci_free_consistent(dev->pdev, PAGE_SIZE,
-					    dev_priv->hw_status_page,
-					    dev_priv->dma_status_page);
-			/* Need to rewrite hardware status page */
-			I830_WRITE(0x02080, 0x1ffff000);
-		}
-
-		kfree(dev->dev_private);
-		dev->dev_private = NULL;
-
-		for (i = 0; i < dma->buf_count; i++) {
-			struct drm_buf *buf = dma->buflist[i];
-			drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-			if (buf_priv->kernel_virtual && buf->total)
-				drm_core_ioremapfree(&buf_priv->map, dev);
-		}
-	}
-	return 0;
-}
-
-int i830_wait_ring(struct drm_device *dev, int n, const char *caller)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-	int iters = 0;
-	unsigned long end;
-	unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-
-	end = jiffies + (HZ * 3);
-	while (ring->space < n) {
-		ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-		ring->space = ring->head - (ring->tail + 8);
-		if (ring->space < 0)
-			ring->space += ring->Size;
-
-		if (ring->head != last_head) {
-			end = jiffies + (HZ * 3);
-			last_head = ring->head;
-		}
-
-		iters++;
-		if (time_before(end, jiffies)) {
-			DRM_ERROR("space: %d wanted %d\n", ring->space, n);
-			DRM_ERROR("lockup\n");
-			goto out_wait_ring;
-		}
-		udelay(1);
-		dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
-	}
-
-out_wait_ring:
-	return iters;
-}
-
-static void i830_kernel_lost_context(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-
-	ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-	ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
-	ring->space = ring->head - (ring->tail + 8);
-	if (ring->space < 0)
-		ring->space += ring->Size;
-
-	if (ring->head == ring->tail)
-		dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
-}
-
-static int i830_freelist_init(struct drm_device *dev, drm_i830_private_t *dev_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int my_idx = 36;
-	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
-	int i;
-
-	if (dma->buf_count > 1019) {
-		/* Not enough space in the status page for the freelist */
-		return -EINVAL;
-	}
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-		buf_priv->in_use = hw_status++;
-		buf_priv->my_use_idx = my_idx;
-		my_idx += 4;
-
-		*buf_priv->in_use = I830_BUF_FREE;
-
-		buf_priv->map.offset = buf->bus_address;
-		buf_priv->map.size = buf->total;
-		buf_priv->map.type = _DRM_AGP;
-		buf_priv->map.flags = 0;
-		buf_priv->map.mtrr = 0;
-
-		drm_core_ioremap(&buf_priv->map, dev);
-		buf_priv->kernel_virtual = buf_priv->map.handle;
-	}
-	return 0;
-}
-
-static int i830_dma_initialize(struct drm_device *dev,
-			       drm_i830_private_t *dev_priv,
-			       drm_i830_init_t *init)
-{
-	struct drm_map_list *r_list;
-
-	memset(dev_priv, 0, sizeof(drm_i830_private_t));
-
-	list_for_each_entry(r_list, &dev->maplist, head) {
-		if (r_list->map &&
-		    r_list->map->type == _DRM_SHM &&
-		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
-			dev_priv->sarea_map = r_list->map;
-			break;
-		}
-	}
-
-	if (!dev_priv->sarea_map) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not find sarea!\n");
-		return -EINVAL;
-	}
-	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-	if (!dev_priv->mmio_map) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not find mmio map!\n");
-		return -EINVAL;
-	}
-	dev->agp_buffer_token = init->buffers_offset;
-	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-	if (!dev->agp_buffer_map) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not find dma buffer map!\n");
-		return -EINVAL;
-	}
-
-	dev_priv->sarea_priv = (drm_i830_sarea_t *)
-	    ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
-
-	dev_priv->ring.Start = init->ring_start;
-	dev_priv->ring.End = init->ring_end;
-	dev_priv->ring.Size = init->ring_size;
-
-	dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
-	dev_priv->ring.map.size = init->ring_size;
-	dev_priv->ring.map.type = _DRM_AGP;
-	dev_priv->ring.map.flags = 0;
-	dev_priv->ring.map.mtrr = 0;
-
-	drm_core_ioremap(&dev_priv->ring.map, dev);
-
-	if (dev_priv->ring.map.handle == NULL) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not ioremap virtual address for"
-			  " ring buffer\n");
-		return -ENOMEM;
-	}
-
-	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
-	dev_priv->w = init->w;
-	dev_priv->h = init->h;
-	dev_priv->pitch = init->pitch;
-	dev_priv->back_offset = init->back_offset;
-	dev_priv->depth_offset = init->depth_offset;
-	dev_priv->front_offset = init->front_offset;
-
-	dev_priv->front_di1 = init->front_offset | init->pitch_bits;
-	dev_priv->back_di1 = init->back_offset | init->pitch_bits;
-	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
-
-	DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
-	DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
-	DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
-	DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
-
-	dev_priv->cpp = init->cpp;
-	/* We are using separate values as placeholders for mechanisms for
-	 * private backbuffer/depthbuffer usage.
-	 */
-
-	dev_priv->back_pitch = init->back_pitch;
-	dev_priv->depth_pitch = init->depth_pitch;
-	dev_priv->do_boxes = 0;
-	dev_priv->use_mi_batchbuffer_start = 0;
-
-	/* Program Hardware Status Page */
-	dev_priv->hw_status_page =
-	    pci_alloc_consistent(dev->pdev, PAGE_SIZE,
-				 &dev_priv->dma_status_page);
-	if (!dev_priv->hw_status_page) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("Can not allocate hardware status page\n");
-		return -ENOMEM;
-	}
-	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
-	I830_WRITE(0x02080, dev_priv->dma_status_page);
-	DRM_DEBUG("Enabled hardware status page\n");
-
-	/* Now we need to init our freelist */
-	if (i830_freelist_init(dev, dev_priv) != 0) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("Not enough space in the status page for"
-			  " the freelist\n");
-		return -ENOMEM;
-	}
-	dev->dev_private = (void *)dev_priv;
-
-	return 0;
-}
-
-static int i830_dma_init(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv;
-	drm_i830_init_t *init = data;
-	int retcode = 0;
-
-	switch (init->func) {
-	case I830_INIT_DMA:
-		dev_priv = kmalloc(sizeof(drm_i830_private_t), GFP_KERNEL);
-		if (dev_priv == NULL)
-			return -ENOMEM;
-		retcode = i830_dma_initialize(dev, dev_priv, init);
-		break;
-	case I830_CLEANUP_DMA:
-		retcode = i830_dma_cleanup(dev);
-		break;
-	default:
-		retcode = -EINVAL;
-		break;
-	}
-
-	return retcode;
-}
-
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define ST1_ENABLE               (1<<16)
-#define ST1_MASK                 (0xffff)
-
-/* Most efficient way to verify state for the i830 is as it is
- * emitted.  Non-conformant state is silently dropped.
- */
-static void i830EmitContextVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i, j = 0;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4);
-
-	for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) {
-		tmp = code[i];
-		if ((tmp & (7 << 29)) == CMD_3D &&
-		    (tmp & (0x1f << 24)) < (0x1d << 24)) {
-			OUT_RING(tmp);
-			j++;
-		} else {
-			DRM_ERROR("Skipping %d\n", i);
-		}
-	}
-
-	OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
-	OUT_RING(code[I830_CTXREG_BLENDCOLR]);
-	j += 2;
-
-	for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) {
-		tmp = code[i];
-		if ((tmp & (7 << 29)) == CMD_3D &&
-		    (tmp & (0x1f << 24)) < (0x1d << 24)) {
-			OUT_RING(tmp);
-			j++;
-		} else {
-			DRM_ERROR("Skipping %d\n", i);
-		}
-	}
-
-	OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
-	OUT_RING(code[I830_CTXREG_MCSB1]);
-	j += 2;
-
-	if (j & 1)
-		OUT_RING(0);
-
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitTexVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i, j = 0;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
-	    (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) ==
-	    (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) {
-
-		BEGIN_LP_RING(I830_TEX_SETUP_SIZE);
-
-		OUT_RING(code[I830_TEXREG_MI0]);	/* TM0LI */
-		OUT_RING(code[I830_TEXREG_MI1]);	/* TM0S0 */
-		OUT_RING(code[I830_TEXREG_MI2]);	/* TM0S1 */
-		OUT_RING(code[I830_TEXREG_MI3]);	/* TM0S2 */
-		OUT_RING(code[I830_TEXREG_MI4]);	/* TM0S3 */
-		OUT_RING(code[I830_TEXREG_MI5]);	/* TM0S4 */
-
-		for (i = 6; i < I830_TEX_SETUP_SIZE; i++) {
-			tmp = code[i];
-			OUT_RING(tmp);
-			j++;
-		}
-
-		if (j & 1)
-			OUT_RING(0);
-
-		ADVANCE_LP_RING();
-	} else
-		printk("rejected packet %x\n", code[0]);
-}
-
-static void i830EmitTexBlendVerified(struct drm_device *dev,
-				     unsigned int *code, unsigned int num)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i, j = 0;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	if (!num)
-		return;
-
-	BEGIN_LP_RING(num + 1);
-
-	for (i = 0; i < num; i++) {
-		tmp = code[i];
-		OUT_RING(tmp);
-		j++;
-	}
-
-	if (j & 1)
-		OUT_RING(0);
-
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitTexPalette(struct drm_device *dev,
-			       unsigned int *palette, int number, int is_shared)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i;
-	RING_LOCALS;
-
-	return;
-
-	BEGIN_LP_RING(258);
-
-	if (is_shared == 1) {
-		OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
-			 MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH);
-	} else {
-		OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
-	}
-	for (i = 0; i < 256; i++)
-		OUT_RING(palette[i]);
-	OUT_RING(0);
-	/* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop!
-	 */
-}
-
-/* Need to do some additional checking when setting the dest buffer.
- */
-static void i830EmitDestVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10);
-
-	tmp = code[I830_DESTREG_CBUFADDR];
-	if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
-		if (((int)outring) & 8) {
-			OUT_RING(0);
-			OUT_RING(0);
-		}
-
-		OUT_RING(CMD_OP_DESTBUFFER_INFO);
-		OUT_RING(BUF_3D_ID_COLOR_BACK |
-			 BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
-			 BUF_3D_USE_FENCE);
-		OUT_RING(tmp);
-		OUT_RING(0);
-
-		OUT_RING(CMD_OP_DESTBUFFER_INFO);
-		OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
-			 BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
-		OUT_RING(dev_priv->zi1);
-		OUT_RING(0);
-	} else {
-		DRM_ERROR("bad di1 %x (allow %x or %x)\n",
-			  tmp, dev_priv->front_di1, dev_priv->back_di1);
-	}
-
-	/* invarient:
-	 */
-
-	OUT_RING(GFX_OP_DESTBUFFER_VARS);
-	OUT_RING(code[I830_DESTREG_DV1]);
-
-	OUT_RING(GFX_OP_DRAWRECT_INFO);
-	OUT_RING(code[I830_DESTREG_DR1]);
-	OUT_RING(code[I830_DESTREG_DR2]);
-	OUT_RING(code[I830_DESTREG_DR3]);
-	OUT_RING(code[I830_DESTREG_DR4]);
-
-	/* Need to verify this */
-	tmp = code[I830_DESTREG_SENABLE];
-	if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
-		OUT_RING(tmp);
-	} else {
-		DRM_ERROR("bad scissor enable\n");
-		OUT_RING(0);
-	}
-
-	OUT_RING(GFX_OP_SCISSOR_RECT);
-	OUT_RING(code[I830_DESTREG_SR1]);
-	OUT_RING(code[I830_DESTREG_SR2]);
-	OUT_RING(0);
-
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitStippleVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	BEGIN_LP_RING(2);
-	OUT_RING(GFX_OP_STIPPLE);
-	OUT_RING(code[1]);
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitState(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int dirty = sarea_priv->dirty;
-
-	DRM_DEBUG("%s %x\n", __func__, dirty);
-
-	if (dirty & I830_UPLOAD_BUFFERS) {
-		i830EmitDestVerified(dev, sarea_priv->BufferState);
-		sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
-	}
-
-	if (dirty & I830_UPLOAD_CTX) {
-		i830EmitContextVerified(dev, sarea_priv->ContextState);
-		sarea_priv->dirty &= ~I830_UPLOAD_CTX;
-	}
-
-	if (dirty & I830_UPLOAD_TEX0) {
-		i830EmitTexVerified(dev, sarea_priv->TexState[0]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
-	}
-
-	if (dirty & I830_UPLOAD_TEX1) {
-		i830EmitTexVerified(dev, sarea_priv->TexState[1]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND0) {
-		i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0],
-					 sarea_priv->TexBlendStateWordsUsed[0]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND1) {
-		i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1],
-					 sarea_priv->TexBlendStateWordsUsed[1]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
-	}
-
-	if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
-		i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
-	} else {
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
-		}
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
-		}
-
-		/* 1.3:
-		 */
-#if 0
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
-		}
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
-		}
-#endif
-	}
-
-	/* 1.3:
-	 */
-	if (dirty & I830_UPLOAD_STIPPLE) {
-		i830EmitStippleVerified(dev, sarea_priv->StippleState);
-		sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
-	}
-
-	if (dirty & I830_UPLOAD_TEX2) {
-		i830EmitTexVerified(dev, sarea_priv->TexState2);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
-	}
-
-	if (dirty & I830_UPLOAD_TEX3) {
-		i830EmitTexVerified(dev, sarea_priv->TexState3);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND2) {
-		i830EmitTexBlendVerified(dev,
-					 sarea_priv->TexBlendState2,
-					 sarea_priv->TexBlendStateWordsUsed2);
-
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND3) {
-		i830EmitTexBlendVerified(dev,
-					 sarea_priv->TexBlendState3,
-					 sarea_priv->TexBlendStateWordsUsed3);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
-	}
-}
-
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void i830_fill_box(struct drm_device *dev,
-			  int x, int y, int w, int h, int r, int g, int b)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	u32 color;
-	unsigned int BR13, CMD;
-	RING_LOCALS;
-
-	BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24);
-	CMD = XY_COLOR_BLT_CMD;
-	x += dev_priv->sarea_priv->boxes[0].x1;
-	y += dev_priv->sarea_priv->boxes[0].y1;
-
-	if (dev_priv->cpp == 4) {
-		BR13 |= (1 << 25);
-		CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
-		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
-	} else {
-		color = (((r & 0xf8) << 8) |
-			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
-	}
-
-	BEGIN_LP_RING(6);
-	OUT_RING(CMD);
-	OUT_RING(BR13);
-	OUT_RING((y << 16) | x);
-	OUT_RING(((y + h) << 16) | (x + w));
-
-	if (dev_priv->current_page == 1)
-		OUT_RING(dev_priv->front_offset);
-	else
-		OUT_RING(dev_priv->back_offset);
-
-	OUT_RING(color);
-	ADVANCE_LP_RING();
-}
-
-static void i830_cp_performance_boxes(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	/* Purple box for page flipping
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP)
-		i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255);
-
-	/* Red box if we have to wait for idle at any point
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT)
-		i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0);
-
-	/* Blue box: lost context?
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT)
-		i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255);
-
-	/* Yellow box for texture swaps
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD)
-		i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0);
-
-	/* Green box if hardware never idles (as far as we can tell)
-	 */
-	if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY))
-		i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0);
-
-	/* Draw bars indicating number of buffers allocated
-	 * (not a great measure, easily confused)
-	 */
-	if (dev_priv->dma_used) {
-		int bar = dev_priv->dma_used / 10240;
-		if (bar > 100)
-			bar = 100;
-		if (bar < 1)
-			bar = 1;
-		i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128);
-		dev_priv->dma_used = 0;
-	}
-
-	dev_priv->sarea_priv->perf_boxes = 0;
-}
-
-static void i830_dma_dispatch_clear(struct drm_device *dev, int flags,
-				    unsigned int clear_color,
-				    unsigned int clear_zval,
-				    unsigned int clear_depthmask)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	int pitch = dev_priv->pitch;
-	int cpp = dev_priv->cpp;
-	int i;
-	unsigned int BR13, CMD, D_CMD;
-	RING_LOCALS;
-
-	if (dev_priv->current_page == 1) {
-		unsigned int tmp = flags;
-
-		flags &= ~(I830_FRONT | I830_BACK);
-		if (tmp & I830_FRONT)
-			flags |= I830_BACK;
-		if (tmp & I830_BACK)
-			flags |= I830_FRONT;
-	}
-
-	i830_kernel_lost_context(dev);
-
-	switch (cpp) {
-	case 2:
-		BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
-		D_CMD = CMD = XY_COLOR_BLT_CMD;
-		break;
-	case 4:
-		BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
-		CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
-		       XY_COLOR_BLT_WRITE_RGB);
-		D_CMD = XY_COLOR_BLT_CMD;
-		if (clear_depthmask & 0x00ffffff)
-			D_CMD |= XY_COLOR_BLT_WRITE_RGB;
-		if (clear_depthmask & 0xff000000)
-			D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
-		break;
-	default:
-		BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
-		D_CMD = CMD = XY_COLOR_BLT_CMD;
-		break;
-	}
-
-	if (nbox > I830_NR_SAREA_CLIPRECTS)
-		nbox = I830_NR_SAREA_CLIPRECTS;
-
-	for (i = 0; i < nbox; i++, pbox++) {
-		if (pbox->x1 > pbox->x2 ||
-		    pbox->y1 > pbox->y2 ||
-		    pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-			continue;
-
-		if (flags & I830_FRONT) {
-			DRM_DEBUG("clear front\n");
-			BEGIN_LP_RING(6);
-			OUT_RING(CMD);
-			OUT_RING(BR13);
-			OUT_RING((pbox->y1 << 16) | pbox->x1);
-			OUT_RING((pbox->y2 << 16) | pbox->x2);
-			OUT_RING(dev_priv->front_offset);
-			OUT_RING(clear_color);
-			ADVANCE_LP_RING();
-		}
-
-		if (flags & I830_BACK) {
-			DRM_DEBUG("clear back\n");
-			BEGIN_LP_RING(6);
-			OUT_RING(CMD);
-			OUT_RING(BR13);
-			OUT_RING((pbox->y1 << 16) | pbox->x1);
-			OUT_RING((pbox->y2 << 16) | pbox->x2);
-			OUT_RING(dev_priv->back_offset);
-			OUT_RING(clear_color);
-			ADVANCE_LP_RING();
-		}
-
-		if (flags & I830_DEPTH) {
-			DRM_DEBUG("clear depth\n");
-			BEGIN_LP_RING(6);
-			OUT_RING(D_CMD);
-			OUT_RING(BR13);
-			OUT_RING((pbox->y1 << 16) | pbox->x1);
-			OUT_RING((pbox->y2 << 16) | pbox->x2);
-			OUT_RING(dev_priv->depth_offset);
-			OUT_RING(clear_zval);
-			ADVANCE_LP_RING();
-		}
-	}
-}
-
-static void i830_dma_dispatch_swap(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	int pitch = dev_priv->pitch;
-	int cpp = dev_priv->cpp;
-	int i;
-	unsigned int CMD, BR13;
-	RING_LOCALS;
-
-	DRM_DEBUG("swapbuffers\n");
-
-	i830_kernel_lost_context(dev);
-
-	if (dev_priv->do_boxes)
-		i830_cp_performance_boxes(dev);
-
-	switch (cpp) {
-	case 2:
-		BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
-		CMD = XY_SRC_COPY_BLT_CMD;
-		break;
-	case 4:
-		BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
-		CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-		       XY_SRC_COPY_BLT_WRITE_RGB);
-		break;
-	default:
-		BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
-		CMD = XY_SRC_COPY_BLT_CMD;
-		break;
-	}
-
-	if (nbox > I830_NR_SAREA_CLIPRECTS)
-		nbox = I830_NR_SAREA_CLIPRECTS;
-
-	for (i = 0; i < nbox; i++, pbox++) {
-		if (pbox->x1 > pbox->x2 ||
-		    pbox->y1 > pbox->y2 ||
-		    pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-			continue;
-
-		DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
-			  pbox->x1, pbox->y1, pbox->x2, pbox->y2);
-
-		BEGIN_LP_RING(8);
-		OUT_RING(CMD);
-		OUT_RING(BR13);
-		OUT_RING((pbox->y1 << 16) | pbox->x1);
-		OUT_RING((pbox->y2 << 16) | pbox->x2);
-
-		if (dev_priv->current_page == 0)
-			OUT_RING(dev_priv->front_offset);
-		else
-			OUT_RING(dev_priv->back_offset);
-
-		OUT_RING((pbox->y1 << 16) | pbox->x1);
-		OUT_RING(BR13 & 0xffff);
-
-		if (dev_priv->current_page == 0)
-			OUT_RING(dev_priv->back_offset);
-		else
-			OUT_RING(dev_priv->front_offset);
-
-		ADVANCE_LP_RING();
-	}
-}
-
-static void i830_dma_dispatch_flip(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-		  __func__,
-		  dev_priv->current_page,
-		  dev_priv->sarea_priv->pf_current_page);
-
-	i830_kernel_lost_context(dev);
-
-	if (dev_priv->do_boxes) {
-		dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
-		i830_cp_performance_boxes(dev);
-	}
-
-	BEGIN_LP_RING(2);
-	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	BEGIN_LP_RING(6);
-	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
-	OUT_RING(0);
-	if (dev_priv->current_page == 0) {
-		OUT_RING(dev_priv->back_offset);
-		dev_priv->current_page = 1;
-	} else {
-		OUT_RING(dev_priv->front_offset);
-		dev_priv->current_page = 0;
-	}
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	BEGIN_LP_RING(2);
-	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static void i830_dma_dispatch_vertex(struct drm_device *dev,
-				     struct drm_buf *buf, int discard, int used)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	struct drm_clip_rect *box = sarea_priv->boxes;
-	int nbox = sarea_priv->nbox;
-	unsigned long address = (unsigned long)buf->bus_address;
-	unsigned long start = address - dev->agp->base;
-	int i = 0, u;
-	RING_LOCALS;
-
-	i830_kernel_lost_context(dev);
-
-	if (nbox > I830_NR_SAREA_CLIPRECTS)
-		nbox = I830_NR_SAREA_CLIPRECTS;
-
-	if (discard) {
-		u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-			    I830_BUF_HARDWARE);
-		if (u != I830_BUF_CLIENT)
-			DRM_DEBUG("xxxx 2\n");
-	}
-
-	if (used > 4 * 1023)
-		used = 0;
-
-	if (sarea_priv->dirty)
-		i830EmitState(dev);
-
-	DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
-		  address, used, nbox);
-
-	dev_priv->counter++;
-	DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
-	DRM_DEBUG("i830_dma_dispatch\n");
-	DRM_DEBUG("start : %lx\n", start);
-	DRM_DEBUG("used : %d\n", used);
-	DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
-
-	if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
-		u32 *vp = buf_priv->kernel_virtual;
-
-		vp[0] = (GFX_OP_PRIMITIVE |
-			 sarea_priv->vertex_prim | ((used / 4) - 2));
-
-		if (dev_priv->use_mi_batchbuffer_start) {
-			vp[used / 4] = MI_BATCH_BUFFER_END;
-			used += 4;
-		}
-
-		if (used & 4) {
-			vp[used / 4] = 0;
-			used += 4;
-		}
-
-		i830_unmap_buffer(buf);
-	}
-
-	if (used) {
-		do {
-			if (i < nbox) {
-				BEGIN_LP_RING(6);
-				OUT_RING(GFX_OP_DRAWRECT_INFO);
-				OUT_RING(sarea_priv->
-					 BufferState[I830_DESTREG_DR1]);
-				OUT_RING(box[i].x1 | (box[i].y1 << 16));
-				OUT_RING(box[i].x2 | (box[i].y2 << 16));
-				OUT_RING(sarea_priv->
-					 BufferState[I830_DESTREG_DR4]);
-				OUT_RING(0);
-				ADVANCE_LP_RING();
-			}
-
-			if (dev_priv->use_mi_batchbuffer_start) {
-				BEGIN_LP_RING(2);
-				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-				OUT_RING(start | MI_BATCH_NON_SECURE);
-				ADVANCE_LP_RING();
-			} else {
-				BEGIN_LP_RING(4);
-				OUT_RING(MI_BATCH_BUFFER);
-				OUT_RING(start | MI_BATCH_NON_SECURE);
-				OUT_RING(start + used - 4);
-				OUT_RING(0);
-				ADVANCE_LP_RING();
-			}
-
-		} while (++i < nbox);
-	}
-
-	if (discard) {
-		dev_priv->counter++;
-
-		(void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-			      I830_BUF_HARDWARE);
-
-		BEGIN_LP_RING(8);
-		OUT_RING(CMD_STORE_DWORD_IDX);
-		OUT_RING(20);
-		OUT_RING(dev_priv->counter);
-		OUT_RING(CMD_STORE_DWORD_IDX);
-		OUT_RING(buf_priv->my_use_idx);
-		OUT_RING(I830_BUF_FREE);
-		OUT_RING(CMD_REPORT_HEAD);
-		OUT_RING(0);
-		ADVANCE_LP_RING();
-	}
-}
-
-static void i830_dma_quiescent(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	i830_kernel_lost_context(dev);
-
-	BEGIN_LP_RING(4);
-	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-	OUT_RING(CMD_REPORT_HEAD);
-	OUT_RING(0);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-}
-
-static int i830_flush_queue(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	struct drm_device_dma *dma = dev->dma;
-	int i, ret = 0;
-	RING_LOCALS;
-
-	i830_kernel_lost_context(dev);
-
-	BEGIN_LP_RING(2);
-	OUT_RING(CMD_REPORT_HEAD);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-		int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
-				   I830_BUF_FREE);
-
-		if (used == I830_BUF_HARDWARE)
-			DRM_DEBUG("reclaimed from HARDWARE\n");
-		if (used == I830_BUF_CLIENT)
-			DRM_DEBUG("still on client\n");
-	}
-
-	return ret;
-}
-
-/* Must be called with the lock held */
-static void i830_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int i;
-
-	if (!dma)
-		return;
-	if (!dev->dev_private)
-		return;
-	if (!dma->buflist)
-		return;
-
-	i830_flush_queue(dev);
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-		if (buf->file_priv == file_priv && buf_priv) {
-			int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-					   I830_BUF_FREE);
-
-			if (used == I830_BUF_CLIENT)
-				DRM_DEBUG("reclaimed from client\n");
-			if (buf_priv->currently_mapped == I830_BUF_MAPPED)
-				buf_priv->currently_mapped = I830_BUF_UNMAPPED;
-		}
-	}
-}
-
-static int i830_flush_ioctl(struct drm_device *dev, void *data,
-			    struct drm_file *file_priv)
-{
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	i830_flush_queue(dev);
-	return 0;
-}
-
-static int i830_dma_vertex(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u32 *hw_status = dev_priv->hw_status_page;
-	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-	    dev_priv->sarea_priv;
-	drm_i830_vertex_t *vertex = data;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
-		  vertex->idx, vertex->used, vertex->discard);
-
-	if (vertex->idx < 0 || vertex->idx > dma->buf_count)
-		return -EINVAL;
-
-	i830_dma_dispatch_vertex(dev,
-				 dma->buflist[vertex->idx],
-				 vertex->discard, vertex->used);
-
-	sarea_priv->last_enqueue = dev_priv->counter - 1;
-	sarea_priv->last_dispatch = (int)hw_status[5];
-
-	return 0;
-}
-
-static int i830_clear_bufs(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	drm_i830_clear_t *clear = data;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	/* GH: Someone's doing nasty things... */
-	if (!dev->dev_private)
-		return -EINVAL;
-
-	i830_dma_dispatch_clear(dev, clear->flags,
-				clear->clear_color,
-				clear->clear_depth, clear->clear_depthmask);
-	return 0;
-}
-
-static int i830_swap_bufs(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
-{
-	DRM_DEBUG("i830_swap_bufs\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	i830_dma_dispatch_swap(dev);
-	return 0;
-}
-
-/* Not sure why this isn't set all the time:
- */
-static void i830_do_init_pageflip(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("%s\n", __func__);
-	dev_priv->page_flipping = 1;
-	dev_priv->current_page = 0;
-	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static int i830_do_cleanup_pageflip(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("%s\n", __func__);
-	if (dev_priv->current_page != 0)
-		i830_dma_dispatch_flip(dev);
-
-	dev_priv->page_flipping = 0;
-	return 0;
-}
-
-static int i830_flip_bufs(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (!dev_priv->page_flipping)
-		i830_do_init_pageflip(dev);
-
-	i830_dma_dispatch_flip(dev);
-	return 0;
-}
-
-static int i830_getage(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u32 *hw_status = dev_priv->hw_status_page;
-	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-	    dev_priv->sarea_priv;
-
-	sarea_priv->last_dispatch = (int)hw_status[5];
-	return 0;
-}
-
-static int i830_getbuf(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	int retcode = 0;
-	drm_i830_dma_t *d = data;
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u32 *hw_status = dev_priv->hw_status_page;
-	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-	    dev_priv->sarea_priv;
-
-	DRM_DEBUG("getbuf\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	d->granted = 0;
-
-	retcode = i830_dma_get_buffer(dev, d, file_priv);
-
-	DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
-		  task_pid_nr(current), retcode, d->granted);
-
-	sarea_priv->last_dispatch = (int)hw_status[5];
-
-	return retcode;
-}
-
-static int i830_copybuf(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	/* Never copy - 2.4.x doesn't need it */
-	return 0;
-}
-
-static int i830_docopy(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	return 0;
-}
-
-static int i830_getparam(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_getparam_t *param = data;
-	int value;
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	switch (param->param) {
-	case I830_PARAM_IRQ_ACTIVE:
-		value = dev->irq_enabled;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (copy_to_user(param->value, &value, sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int i830_setparam(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_setparam_t *param = data;
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	switch (param->param) {
-	case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
-		dev_priv->use_mi_batchbuffer_start = param->value;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int i830_driver_load(struct drm_device *dev, unsigned long flags)
-{
-	/* i830 has 4 more counters */
-	dev->counters += 4;
-	dev->types[6] = _DRM_STAT_IRQ;
-	dev->types[7] = _DRM_STAT_PRIMARY;
-	dev->types[8] = _DRM_STAT_SECONDARY;
-	dev->types[9] = _DRM_STAT_DMA;
-
-	return 0;
-}
-
-void i830_driver_lastclose(struct drm_device *dev)
-{
-	i830_dma_cleanup(dev);
-}
-
-void i830_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-	if (dev->dev_private) {
-		drm_i830_private_t *dev_priv = dev->dev_private;
-		if (dev_priv->page_flipping)
-			i830_do_cleanup_pageflip(dev);
-	}
-}
-
-void i830_driver_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv)
-{
-	i830_reclaim_buffers(dev, file_priv);
-}
-
-int i830_driver_dma_quiescent(struct drm_device *dev)
-{
-	i830_dma_quiescent(dev);
-	return 0;
-}
-
-/*
- * call the drm_ioctl under the big kernel lock because
- * to lock against the i830_mmap_buffers function.
- */
-long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	lock_kernel();
-	ret = drm_ioctl(file, cmd, arg);
-	unlock_kernel();
-	return ret;
-}
-
-struct drm_ioctl_desc i830_ioctls[] = {
-	DRM_IOCTL_DEF_DRV(I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED),
-};
-
-int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
-
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i8xx is AGP.
- */
-int i830_driver_device_is_agp(struct drm_device *dev)
-{
-	return 1;
-}
diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c
deleted file mode 100644
index f655ab7..0000000
--- a/drivers/gpu/drm/i830/i830_drv.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* i830_drv.c -- I810 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *    Abraham vd Merwe <abraham@2d3d.co.za>
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-	i830_PCI_IDS
-};
-
-static struct drm_driver driver = {
-	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
-	    DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
-#if USE_IRQS
-	.driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
-#endif
-	.dev_priv_size = sizeof(drm_i830_buf_priv_t),
-	.load = i830_driver_load,
-	.lastclose = i830_driver_lastclose,
-	.preclose = i830_driver_preclose,
-	.device_is_agp = i830_driver_device_is_agp,
-	.reclaim_buffers_locked = i830_driver_reclaim_buffers_locked,
-	.dma_quiescent = i830_driver_dma_quiescent,
-#if USE_IRQS
-	.irq_preinstall = i830_driver_irq_preinstall,
-	.irq_postinstall = i830_driver_irq_postinstall,
-	.irq_uninstall = i830_driver_irq_uninstall,
-	.irq_handler = i830_driver_irq_handler,
-#endif
-	.ioctls = i830_ioctls,
-	.fops = {
-		 .owner = THIS_MODULE,
-		 .open = drm_open,
-		 .release = drm_release,
-		 .unlocked_ioctl = i830_ioctl,
-		 .mmap = drm_mmap,
-		 .poll = drm_poll,
-		 .fasync = drm_fasync,
-		 .llseek = noop_llseek,
-	},
-
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
-	.name = DRIVER_NAME,
-	.desc = DRIVER_DESC,
-	.date = DRIVER_DATE,
-	.major = DRIVER_MAJOR,
-	.minor = DRIVER_MINOR,
-	.patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init i830_init(void)
-{
-	driver.num_ioctls = i830_max_ioctl;
-	return drm_init(&driver);
-}
-
-static void __exit i830_exit(void)
-{
-	drm_exit(&driver);
-}
-
-module_init(i830_init);
-module_exit(i830_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/i830/i830_drv.h b/drivers/gpu/drm/i830/i830_drv.h
deleted file mode 100644
index 0df1c72..0000000
--- a/drivers/gpu/drm/i830/i830_drv.h
+++ /dev/null
@@ -1,295 +0,0 @@
-/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
- * All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#ifndef _I830_DRV_H_
-#define _I830_DRV_H_
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"i830"
-#define DRIVER_DESC		"Intel 830M"
-#define DRIVER_DATE		"20021108"
-
-/* Interface history:
- *
- * 1.1: Original.
- * 1.2: ?
- * 1.3: New irq emit/wait ioctls.
- *      New pageflip ioctl.
- *      New getparam ioctl.
- *      State for texunits 3&4 in sarea.
- *      New (alternative) layout for texture state.
- */
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		3
-#define DRIVER_PATCHLEVEL	2
-
-/* Driver will work either way: IRQ's save cpu time when waiting for
- * the card, but are subject to subtle interactions between bios,
- * hardware and the driver.
- */
-/* XXX: Add vblank support? */
-#define USE_IRQS 0
-
-typedef struct drm_i830_buf_priv {
-	u32 *in_use;
-	int my_use_idx;
-	int currently_mapped;
-	void __user *virtual;
-	void *kernel_virtual;
-	drm_local_map_t map;
-} drm_i830_buf_priv_t;
-
-typedef struct _drm_i830_ring_buffer {
-	int tail_mask;
-	unsigned long Start;
-	unsigned long End;
-	unsigned long Size;
-	u8 *virtual_start;
-	int head;
-	int tail;
-	int space;
-	drm_local_map_t map;
-} drm_i830_ring_buffer_t;
-
-typedef struct drm_i830_private {
-	struct drm_local_map *sarea_map;
-	struct drm_local_map *mmio_map;
-
-	drm_i830_sarea_t *sarea_priv;
-	drm_i830_ring_buffer_t ring;
-
-	void *hw_status_page;
-	unsigned long counter;
-
-	dma_addr_t dma_status_page;
-
-	struct drm_buf *mmap_buffer;
-
-	u32 front_di1, back_di1, zi1;
-
-	int back_offset;
-	int depth_offset;
-	int front_offset;
-	int w, h;
-	int pitch;
-	int back_pitch;
-	int depth_pitch;
-	unsigned int cpp;
-
-	int do_boxes;
-	int dma_used;
-
-	int current_page;
-	int page_flipping;
-
-	wait_queue_head_t irq_queue;
-	atomic_t irq_received;
-	atomic_t irq_emitted;
-
-	int use_mi_batchbuffer_start;
-
-} drm_i830_private_t;
-
-long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-extern struct drm_ioctl_desc i830_ioctls[];
-extern int i830_max_ioctl;
-
-/* i830_irq.c */
-extern int i830_irq_emit(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv);
-extern int i830_irq_wait(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv);
-
-extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i830_driver_irq_preinstall(struct drm_device *dev);
-extern void i830_driver_irq_postinstall(struct drm_device *dev);
-extern void i830_driver_irq_uninstall(struct drm_device *dev);
-extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(struct drm_device *dev,
-				 struct drm_file *file_priv);
-extern void i830_driver_lastclose(struct drm_device *dev);
-extern void i830_driver_reclaim_buffers_locked(struct drm_device *dev,
-					       struct drm_file *file_priv);
-extern int i830_driver_dma_quiescent(struct drm_device *dev);
-extern int i830_driver_device_is_agp(struct drm_device *dev);
-
-#define I830_READ(reg)		DRM_READ32(dev_priv->mmio_map, reg)
-#define I830_WRITE(reg, val)	DRM_WRITE32(dev_priv->mmio_map, reg, val)
-#define I830_READ16(reg)	DRM_READ16(dev_priv->mmio_map, reg)
-#define I830_WRITE16(reg, val)	DRM_WRITE16(dev_priv->mmio_map, reg, val)
-
-#define I830_VERBOSE 0
-
-#define RING_LOCALS	unsigned int outring, ringmask, outcount; \
-			volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {				\
-	if (I830_VERBOSE)				\
-		printk("BEGIN_LP_RING(%d)\n", (n));	\
-	if (dev_priv->ring.space < n*4)			\
-		i830_wait_ring(dev, n*4, __func__);	\
-	outcount = 0;					\
-	outring = dev_priv->ring.tail;			\
-	ringmask = dev_priv->ring.tail_mask;		\
-	virt = dev_priv->ring.virtual_start;		\
-} while (0)
-
-#define OUT_RING(n) do {					\
-	if (I830_VERBOSE)					\
-		printk("   OUT_RING %x\n", (int)(n));		\
-	*(volatile unsigned int *)(virt + outring) = n;		\
-	outcount++;						\
-	outring += 4;						\
-	outring &= ringmask;					\
-} while (0)
-
-#define ADVANCE_LP_RING() do {					\
-	if (I830_VERBOSE)					\
-		printk("ADVANCE_LP_RING %x\n", outring);	\
-	dev_priv->ring.tail = outring;				\
-	dev_priv->ring.space -= outcount * 4;			\
-	I830_WRITE(LP_RING + RING_TAIL, outring);		\
-} while (0)
-
-extern int i830_wait_ring(struct drm_device *dev, int n, const char *caller);
-
-#define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD			(7<<23)
-#define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
-
-#define STATE3D_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
-#define LOAD_TEXTURE_MAP0                   (1<<11)
-
-#define INST_PARSER_CLIENT   0x00000000
-#define INST_OP_FLUSH        0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
-
-#define I830REG_HWSTAM		0x02098
-#define I830REG_INT_IDENTITY_R	0x020a4
-#define I830REG_INT_MASK_R	0x020a8
-#define I830REG_INT_ENABLE_R	0x020a0
-
-#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
-
-#define LP_RING			0x2030
-#define HP_RING			0x2040
-#define RING_TAIL		0x00
-#define TAIL_ADDR		0x001FFFF8
-#define RING_HEAD		0x04
-#define HEAD_WRAP_COUNT		0xFFE00000
-#define HEAD_WRAP_ONE		0x00200000
-#define HEAD_ADDR		0x001FFFFC
-#define RING_START		0x08
-#define START_ADDR		0x0xFFFFF000
-#define RING_LEN		0x0C
-#define RING_NR_PAGES		0x001FF000
-#define RING_REPORT_MASK	0x00000006
-#define RING_REPORT_64K		0x00000002
-#define RING_REPORT_128K	0x00000004
-#define RING_NO_REPORT		0x00000000
-#define RING_VALID_MASK		0x00000001
-#define RING_VALID		0x00000001
-#define RING_INVALID		0x00000000
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
-
-#define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP                (1<<22)
-
-#define CMD_3D                          (0x3<<29)
-#define STATE3D_CONST_BLEND_COLOR_CMD   (CMD_3D|(0x1d<<24)|(0x88<<16))
-#define STATE3D_MAP_COORD_SETBIND_CMD   (CMD_3D|(0x1d<<24)|(0x02<<16))
-
-#define BR00_BITBLT_CLIENT   0x40000000
-#define BR00_OP_COLOR_BLT    0x10000000
-#define BR00_OP_SRC_COPY_BLT 0x10C00000
-#define BR13_SOLID_PATTERN   0x80000000
-
-#define BUF_3D_ID_COLOR_BACK    (0x3<<24)
-#define BUF_3D_ID_DEPTH         (0x7<<24)
-#define BUF_3D_USE_FENCE        (1<<23)
-#define BUF_3D_PITCH(x)         (((x)/4)<<2)
-
-#define CMD_OP_MAP_PALETTE_LOAD	((3<<29)|(0x1d<<24)|(0x82<<16)|255)
-#define MAP_PALETTE_NUM(x)	((x<<8) & (1<<8))
-#define MAP_PALETTE_BOTH	(1<<11)
-
-#define XY_COLOR_BLT_CMD		((2<<29)|(0x50<<22)|0x4)
-#define XY_COLOR_BLT_WRITE_ALPHA	(1<<21)
-#define XY_COLOR_BLT_WRITE_RGB		(1<<20)
-
-#define XY_SRC_COPY_BLT_CMD             ((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
-
-#define MI_BATCH_BUFFER		((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START	(0x31<<23)
-#define MI_BATCH_BUFFER_END	(0xA<<23)
-#define MI_BATCH_NON_SECURE	(1)
-
-#define MI_WAIT_FOR_EVENT       ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
-
-#endif
diff --git a/drivers/gpu/drm/i830/i830_irq.c b/drivers/gpu/drm/i830/i830_irq.c
deleted file mode 100644
index d1a6b95..0000000
--- a/drivers/gpu/drm/i830/i830_irq.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
- *
- * Copyright 2002 Tungsten Graphics, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Authors: Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/delay.h>
-
-irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
-{
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u16 temp;
-
-	temp = I830_READ16(I830REG_INT_IDENTITY_R);
-	DRM_DEBUG("%x\n", temp);
-
-	if (!(temp & 2))
-		return IRQ_NONE;
-
-	I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
-
-	atomic_inc(&dev_priv->irq_received);
-	wake_up_interruptible(&dev_priv->irq_queue);
-
-	return IRQ_HANDLED;
-}
-
-static int i830_emit_irq(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	atomic_inc(&dev_priv->irq_emitted);
-
-	BEGIN_LP_RING(2);
-	OUT_RING(0);
-	OUT_RING(GFX_OP_USER_INTERRUPT);
-	ADVANCE_LP_RING();
-
-	return atomic_read(&dev_priv->irq_emitted);
-}
-
-static int i830_wait_irq(struct drm_device *dev, int irq_nr)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	DECLARE_WAITQUEUE(entry, current);
-	unsigned long end = jiffies + HZ * 3;
-	int ret = 0;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	if (atomic_read(&dev_priv->irq_received) >= irq_nr)
-		return 0;
-
-	dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
-
-	add_wait_queue(&dev_priv->irq_queue, &entry);
-
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if (atomic_read(&dev_priv->irq_received) >= irq_nr)
-			break;
-		if ((signed)(end - jiffies) <= 0) {
-			DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
-				  I830_READ16(I830REG_INT_IDENTITY_R),
-				  I830_READ16(I830REG_INT_MASK_R),
-				  I830_READ16(I830REG_INT_ENABLE_R),
-				  I830_READ16(I830REG_HWSTAM));
-
-			ret = -EBUSY;	/* Lockup?  Missed irq? */
-			break;
-		}
-		schedule_timeout(HZ * 3);
-		if (signal_pending(current)) {
-			ret = -EINTR;
-			break;
-		}
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&dev_priv->irq_queue, &entry);
-	return ret;
-}
-
-/* Needs the lock as it touches the ring.
- */
-int i830_irq_emit(struct drm_device *dev, void *data,
-		  struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_irq_emit_t *emit = data;
-	int result;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	result = i830_emit_irq(dev);
-
-	if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int i830_irq_wait(struct drm_device *dev, void *data,
-		  struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_irq_wait_t *irqwait = data;
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	return i830_wait_irq(dev, irqwait->irq_seq);
-}
-
-/* drm_dma.h hooks
-*/
-void i830_driver_irq_preinstall(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-
-	I830_WRITE16(I830REG_HWSTAM, 0xffff);
-	I830_WRITE16(I830REG_INT_MASK_R, 0x0);
-	I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
-	atomic_set(&dev_priv->irq_received, 0);
-	atomic_set(&dev_priv->irq_emitted, 0);
-	init_waitqueue_head(&dev_priv->irq_queue);
-}
-
-void i830_driver_irq_postinstall(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-
-	I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
-}
-
-void i830_driver_irq_uninstall(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	if (!dev_priv)
-		return;
-
-	I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
-	I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
-}
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 4ff9b6c..09e0327 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -326,21 +326,21 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
 	struct intel_crtc *crtc;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
-		const char *pipe = crtc->pipe ? "B" : "A";
-		const char *plane = crtc->plane ? "B" : "A";
+		const char pipe = pipe_name(crtc->pipe);
+		const char plane = plane_name(crtc->plane);
 		struct intel_unpin_work *work;
 
 		spin_lock_irqsave(&dev->event_lock, flags);
 		work = crtc->unpin_work;
 		if (work == NULL) {
-			seq_printf(m, "No flip due on pipe %s (plane %s)\n",
+			seq_printf(m, "No flip due on pipe %c (plane %c)\n",
 				   pipe, plane);
 		} else {
 			if (!work->pending) {
-				seq_printf(m, "Flip queued on pipe %s (plane %s)\n",
+				seq_printf(m, "Flip queued on pipe %c (plane %c)\n",
 					   pipe, plane);
 			} else {
-				seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n",
+				seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n",
 					   pipe, plane);
 			}
 			if (work->enable_stall_check)
@@ -458,7 +458,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	int ret, i;
+	int ret, i, pipe;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
@@ -471,10 +471,10 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
 			   I915_READ(IIR));
 		seq_printf(m, "Interrupt mask:      %08x\n",
 			   I915_READ(IMR));
-		seq_printf(m, "Pipe A stat:         %08x\n",
-			   I915_READ(PIPEASTAT));
-		seq_printf(m, "Pipe B stat:         %08x\n",
-			   I915_READ(PIPEBSTAT));
+		for_each_pipe(pipe)
+			seq_printf(m, "Pipe %c stat:         %08x\n",
+				   pipe_name(pipe),
+				   I915_READ(PIPESTAT(pipe)));
 	} else {
 		seq_printf(m, "North Display Interrupt enable:		%08x\n",
 			   I915_READ(DEIER));
@@ -544,11 +544,11 @@ static int i915_hws_info(struct seq_file *m, void *data)
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	volatile u32 *hws;
+	const volatile u32 __iomem *hws;
 	int i;
 
 	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-	hws = (volatile u32 *)ring->status_page.page_addr;
+	hws = (volatile u32 __iomem *)ring->status_page.page_addr;
 	if (hws == NULL)
 		return 0;
 
@@ -615,7 +615,7 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
 	if (!ring->obj) {
 		seq_printf(m, "No ringbuffer setup\n");
 	} else {
-		u8 *virt = ring->virtual_start;
+		const u8 __iomem *virt = ring->virtual_start;
 		uint32_t off;
 
 		for (off = 0; off < ring->size; off += 4) {
@@ -805,15 +805,20 @@ static int i915_error_state(struct seq_file *m, void *unused)
 		}
 	}
 
-	if (error->ringbuffer) {
-		struct drm_i915_error_object *obj = error->ringbuffer;
-
-		seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset);
-		offset = 0;
-		for (page = 0; page < obj->page_count; page++) {
-			for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-				seq_printf(m, "%08x :  %08x\n", offset, obj->pages[page][elt]);
-				offset += 4;
+	for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) {
+		if (error->ringbuffer[i]) {
+			struct drm_i915_error_object *obj = error->ringbuffer[i];
+			seq_printf(m, "%s --- ringbuffer = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
+			offset = 0;
+			for (page = 0; page < obj->page_count; page++) {
+				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
+					seq_printf(m, "%08x :  %08x\n",
+						   offset,
+						   obj->pages[page][elt]);
+					offset += 4;
+				}
 			}
 		}
 	}
@@ -862,19 +867,44 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		u32 rpstat;
+		u32 rpupei, rpcurup, rpprevup;
+		u32 rpdownei, rpcurdown, rpprevdown;
 		int max_freq;
 
 		/* RPSTAT1 is in the GT power well */
 		__gen6_gt_force_wake_get(dev_priv);
 
+		rpstat = I915_READ(GEN6_RPSTAT1);
+		rpupei = I915_READ(GEN6_RP_CUR_UP_EI);
+		rpcurup = I915_READ(GEN6_RP_CUR_UP);
+		rpprevup = I915_READ(GEN6_RP_PREV_UP);
+		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
+		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
+		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
+
 		seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
-		seq_printf(m, "RPSTAT1: 0x%08x\n", I915_READ(GEN6_RPSTAT1));
+		seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat);
 		seq_printf(m, "Render p-state ratio: %d\n",
 			   (gt_perf_status & 0xff00) >> 8);
 		seq_printf(m, "Render p-state VID: %d\n",
 			   gt_perf_status & 0xff);
 		seq_printf(m, "Render p-state limit: %d\n",
 			   rp_state_limits & 0xff);
+		seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >>
+						GEN6_CAGF_SHIFT) * 100);
+		seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
+			   GEN6_CURICONT_MASK);
+		seq_printf(m, "RP CUR UP: %dus\n", rpcurup &
+			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP PREV UP: %dus\n", rpprevup &
+			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei &
+			   GEN6_CURIAVG_MASK);
+		seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown &
+			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown &
+			   GEN6_CURBSYTAVG_MASK);
 
 		max_freq = (rp_state_cap & 0xff0000) >> 16;
 		seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
@@ -1259,7 +1289,7 @@ static int i915_wedged_create(struct dentry *root, struct drm_minor *minor)
 }
 
 static struct drm_info_list i915_debugfs_list[] = {
-	{"i915_capabilities", i915_capabilities, 0, 0},
+	{"i915_capabilities", i915_capabilities, 0},
 	{"i915_gem_objects", i915_gem_object_info, 0},
 	{"i915_gem_gtt", i915_gem_gtt_info, 0},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e33d9be..7273037 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -43,6 +43,17 @@
 #include <linux/slab.h>
 #include <acpi/video.h>
 
+static void i915_write_hws_pga(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 addr;
+
+	addr = dev_priv->status_page_dmah->busaddr;
+	if (INTEL_INFO(dev)->gen >= 4)
+		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
+	I915_WRITE(HWS_PGA, addr);
+}
+
 /**
  * Sets up the hardware status page for devices that need a physical address
  * in the register.
@@ -60,16 +71,13 @@ static int i915_init_phys_hws(struct drm_device *dev)
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
-	ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
-	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+	ring->status_page.page_addr =
+		(void __force __iomem *)dev_priv->status_page_dmah->vaddr;
 
-	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+	memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
 
-	if (INTEL_INFO(dev)->gen >= 4)
-		dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
-					     0xf0;
+	i915_write_hws_pga(dev);
 
-	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
 	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 	return 0;
 }
@@ -216,7 +224,7 @@ static int i915_dma_resume(struct drm_device * dev)
 	if (ring->status_page.gfx_addr != 0)
 		intel_ring_setup_status_page(ring);
 	else
-		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
+		i915_write_hws_pga(dev);
 
 	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 
@@ -771,6 +779,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
 	case I915_PARAM_HAS_EXEC_CONSTANTS:
 		value = INTEL_INFO(dev)->gen >= 4;
 		break;
+	case I915_PARAM_HAS_RELAXED_DELTA:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
@@ -859,8 +870,9 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
 				" G33 hw status page\n");
 		return -ENOMEM;
 	}
-	ring->status_page.page_addr = dev_priv->hws_map.handle;
-	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+	ring->status_page.page_addr =
+		(void __force __iomem *)dev_priv->hws_map.handle;
+	memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
 	I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
 
 	DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
@@ -2013,9 +2025,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->error_lock);
-	dev_priv->trace_irq_seqno = 0;
 
-	ret = drm_vblank_init(dev, I915_NUM_PIPE);
+	if (IS_MOBILE(dev) || !IS_GEN2(dev))
+		dev_priv->num_pipe = 2;
+	else
+		dev_priv->num_pipe = 1;
+
+	ret = drm_vblank_init(dev, dev_priv->num_pipe);
 	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 22ec066..c34a8dd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -43,10 +43,13 @@ module_param_named(modeset, i915_modeset, int, 0400);
 unsigned int i915_fbpercrtc = 0;
 module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
 
+int i915_panel_ignore_lid = 0;
+module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+
 unsigned int i915_powersave = 1;
 module_param_named(powersave, i915_powersave, int, 0600);
 
-unsigned int i915_semaphores = 0;
+unsigned int i915_semaphores = 1;
 module_param_named(semaphores, i915_semaphores, int, 0600);
 
 unsigned int i915_enable_rc6 = 0;
@@ -58,7 +61,10 @@ module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
 unsigned int i915_panel_use_ssc = 1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 
-bool i915_try_reset = true;
+int i915_vbt_sdvo_panel_type = -1;
+module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
+
+static bool i915_try_reset = true;
 module_param_named(reset, i915_try_reset, bool, 0600);
 
 static struct drm_driver driver;
@@ -716,6 +722,9 @@ static struct drm_driver driver = {
 	.gem_init_object = i915_gem_init_object,
 	.gem_free_object = i915_gem_free_object,
 	.gem_vm_ops = &i915_gem_vm_ops,
+	.dumb_create = i915_gem_dumb_create,
+	.dumb_map_offset = i915_gem_mmap_gtt,
+	.dumb_destroy = i915_gem_dumb_destroy,
 	.ioctls = i915_ioctls,
 	.fops = {
 		 .owner = THIS_MODULE,
@@ -732,14 +741,6 @@ static struct drm_driver driver = {
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-		 .probe = i915_pci_probe,
-		 .remove = i915_pci_remove,
-		 .driver.pm = &i915_pm_ops,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -748,6 +749,14 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver i915_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+	.probe = i915_pci_probe,
+	.remove = i915_pci_remove,
+	.driver.pm = &i915_pm_ops,
+};
+
 static int __init i915_init(void)
 {
 	if (!intel_agp_enabled) {
@@ -781,12 +790,12 @@ static int __init i915_init(void)
 	if (!(driver.driver_features & DRIVER_MODESET))
 		driver.get_vblank_timestamp = NULL;
 
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &i915_pci_driver);
 }
 
 static void __exit i915_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &i915_pci_driver);
 }
 
 module_init(i915_init);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 456f404..4496505 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -49,17 +49,22 @@
 enum pipe {
 	PIPE_A = 0,
 	PIPE_B,
+	PIPE_C,
+	I915_MAX_PIPES
 };
+#define pipe_name(p) ((p) + 'A')
 
 enum plane {
 	PLANE_A = 0,
 	PLANE_B,
+	PLANE_C,
 };
-
-#define I915_NUM_PIPE	2
+#define plane_name(p) ((p) + 'A')
 
 #define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
 
+#define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -75,10 +80,7 @@ enum plane {
 #define DRIVER_PATCHLEVEL	0
 
 #define WATCH_COHERENCY	0
-#define WATCH_EXEC	0
-#define WATCH_RELOC	0
 #define WATCH_LISTS	0
-#define WATCH_PWRITE	0
 
 #define I915_GEM_PHYS_CURSOR_0 1
 #define I915_GEM_PHYS_CURSOR_1 2
@@ -111,6 +113,7 @@ struct intel_opregion {
 	struct opregion_swsci *swsci;
 	struct opregion_asle *asle;
 	void *vbt;
+	u32 __iomem *lid_state;
 };
 #define OPREGION_SIZE            (8*1024)
 
@@ -144,8 +147,7 @@ struct intel_display_error_state;
 struct drm_i915_error_state {
 	u32 eir;
 	u32 pgtbl_er;
-	u32 pipeastat;
-	u32 pipebstat;
+	u32 pipestat[I915_MAX_PIPES];
 	u32 ipeir;
 	u32 ipehr;
 	u32 instdone;
@@ -172,7 +174,7 @@ struct drm_i915_error_state {
 		int page_count;
 		u32 gtt_offset;
 		u32 *pages[0];
-	} *ringbuffer, *batchbuffer[I915_NUM_RINGS];
+	} *ringbuffer[I915_NUM_RINGS], *batchbuffer[I915_NUM_RINGS];
 	struct drm_i915_error_buffer {
 		u32 size;
 		u32 name;
@@ -200,9 +202,7 @@ struct drm_i915_display_funcs {
 	void (*disable_fbc)(struct drm_device *dev);
 	int (*get_display_clock_speed)(struct drm_device *dev);
 	int (*get_fifo_size)(struct drm_device *dev, int plane);
-	void (*update_wm)(struct drm_device *dev, int planea_clock,
-			  int planeb_clock, int sr_hdisplay, int sr_htotal,
-			  int pixel_size);
+	void (*update_wm)(struct drm_device *dev);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
@@ -274,7 +274,6 @@ typedef struct drm_i915_private {
 	uint32_t next_seqno;
 
 	drm_dma_handle_t *status_page_dmah;
-	dma_addr_t dma_status_page;
 	uint32_t counter;
 	drm_local_map_t hws_map;
 	struct drm_i915_gem_object *pwrctx;
@@ -289,7 +288,6 @@ typedef struct drm_i915_private {
 	int page_flipping;
 
 	atomic_t irq_received;
-	u32 trace_irq_seqno;
 
 	/* protects the irq masks */
 	spinlock_t irq_lock;
@@ -324,8 +322,6 @@ typedef struct drm_i915_private {
 	int cfb_plane;
 	int cfb_y;
 
-	int irq_enabled;
-
 	struct intel_opregion opregion;
 
 	/* overlay */
@@ -387,7 +383,6 @@ typedef struct drm_i915_private {
 	u32 saveDSPACNTR;
 	u32 saveDSPBCNTR;
 	u32 saveDSPARB;
-	u32 saveHWS;
 	u32 savePIPEACONF;
 	u32 savePIPEBCONF;
 	u32 savePIPEASRC;
@@ -615,6 +610,12 @@ typedef struct drm_i915_private {
 		struct delayed_work retire_work;
 
 		/**
+		 * Are we in a non-interruptible section of code like
+		 * modesetting?
+		 */
+		bool interruptible;
+
+		/**
 		 * Flag if the X Server, and thus DRM, is not currently in
 		 * control of the device.
 		 *
@@ -652,6 +653,7 @@ typedef struct drm_i915_private {
 	unsigned int lvds_border_bits;
 	/* Panel fitter placement and size for Ironlake+ */
 	u32 pch_pf_pos, pch_pf_size;
+	int panel_t3, panel_t12;
 
 	struct drm_crtc *plane_to_crtc_mapping[2];
 	struct drm_crtc *pipe_to_crtc_mapping[2];
@@ -698,6 +700,8 @@ typedef struct drm_i915_private {
 
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
+
+	struct drm_property *broadcast_rgb_property;
 } drm_i915_private_t;
 
 struct drm_i915_gem_object {
@@ -955,10 +959,12 @@ enum intel_chip_family {
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc;
+extern int i915_panel_ignore_lid;
 extern unsigned int i915_powersave;
 extern unsigned int i915_semaphores;
 extern unsigned int i915_lvds_downclock;
 extern unsigned int i915_panel_use_ssc;
+extern int i915_vbt_sdvo_panel_type;
 extern unsigned int i915_enable_rc6;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
@@ -998,8 +1004,6 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int i915_irq_wait(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
-void i915_trace_irq_get(struct drm_device *dev, u32 seqno);
-extern void i915_enable_interrupt (struct drm_device *dev);
 
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(struct drm_device * dev);
@@ -1051,7 +1055,6 @@ extern void i915_mem_takedown(struct mem_block **heap);
 extern void i915_mem_release(struct drm_device * dev,
 			     struct drm_file *file_priv, struct mem_block *heap);
 /* i915_gem.c */
-int i915_gem_check_is_wedged(struct drm_device *dev);
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 int i915_gem_create_ioctl(struct drm_device *dev, void *data,
@@ -1094,8 +1097,7 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
-int __must_check i915_gem_flush_ring(struct drm_device *dev,
-				     struct intel_ring_buffer *ring,
+int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring,
 				     uint32_t invalidate_domains,
 				     uint32_t flush_domains);
 struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
@@ -1110,12 +1112,18 @@ void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 
 int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
-int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
-						bool interruptible);
+int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj);
 void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
 				    struct intel_ring_buffer *ring,
 				    u32 seqno);
 
+int i915_gem_dumb_create(struct drm_file *file_priv,
+			 struct drm_device *dev,
+			 struct drm_mode_create_dumb *args);
+int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
+		      uint32_t handle, uint64_t *offset);
+int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
+			  uint32_t handle);			  
 /**
  * Returns true if seq1 is later than seq2.
  */
@@ -1126,16 +1134,14 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
 }
 
 static inline u32
-i915_gem_next_request_seqno(struct drm_device *dev,
-			    struct intel_ring_buffer *ring)
+i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	return ring->outstanding_lazy_request = dev_priv->next_seqno;
 }
 
 int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
-					   struct intel_ring_buffer *pipelined,
-					   bool interruptible);
+					   struct intel_ring_buffer *pipelined);
 int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
 
 void i915_gem_retire_requests(struct drm_device *dev);
@@ -1144,8 +1150,7 @@ void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
 					    uint32_t read_domains,
 					    uint32_t write_domain);
-int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
-					   bool interruptible);
+int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 void i915_gem_do_init(struct drm_device *dev,
@@ -1154,14 +1159,11 @@ void i915_gem_do_init(struct drm_device *dev,
 		      unsigned long end);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
-int __must_check i915_add_request(struct drm_device *dev,
-				  struct drm_file *file_priv,
-				  struct drm_i915_gem_request *request,
-				  struct intel_ring_buffer *ring);
-int __must_check i915_do_wait_request(struct drm_device *dev,
-				      uint32_t seqno,
-				      bool interruptible,
-				      struct intel_ring_buffer *ring);
+int __must_check i915_add_request(struct intel_ring_buffer *ring,
+				  struct drm_file *file,
+				  struct drm_i915_gem_request *request);
+int __must_check i915_wait_request(struct intel_ring_buffer *ring,
+				   uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
@@ -1313,7 +1315,7 @@ extern void intel_display_print_error_state(struct seq_file *m,
 #define __i915_read(x, y) \
 static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
 	u##x val = read##y(dev_priv->regs + reg); \
-	trace_i915_reg_rw('R', reg, val, sizeof(val)); \
+	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
 	return val; \
 }
 __i915_read(8, b)
@@ -1324,7 +1326,7 @@ __i915_read(64, q)
 
 #define __i915_write(x, y) \
 static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
-	trace_i915_reg_rw('W', reg, val, sizeof(val)); \
+	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
 	write##y(val, dev_priv->regs + reg); \
 }
 __i915_write(8, b)
@@ -1382,47 +1384,4 @@ static inline void i915_gt_write(struct drm_i915_private *dev_priv,
 		__gen6_gt_wait_for_fifo(dev_priv);
 	I915_WRITE(reg, val);
 }
-
-static inline void
-i915_write(struct drm_i915_private *dev_priv, u32 reg, u64 val, int len)
-{
-       /* Trace down the write operation before the real write */
-       trace_i915_reg_rw('W', reg, val, len);
-       switch (len) {
-       case 8:
-               writeq(val, dev_priv->regs + reg);
-               break;
-       case 4:
-               writel(val, dev_priv->regs + reg);
-               break;
-       case 2:
-               writew(val, dev_priv->regs + reg);
-               break;
-       case 1:
-               writeb(val, dev_priv->regs + reg);
-               break;
-       }
-}
-
-/**
- * Reads a dword out of the status page, which is written to from the command
- * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
- * MI_STORE_DATA_IMM.
- *
- * The following dwords have a reserved meaning:
- * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
- * 0x04: ring 0 head pointer
- * 0x05: ring 1 head pointer (915-class)
- * 0x06: ring 2 head pointer (915-class)
- * 0x10-0x1b: Context status DWords (GM45)
- * 0x1f: Last written status offset. (GM45)
- *
- * The area from dword 0x20 to 0x3ff is available for driver usage.
- */
-#define READ_HWSP(dev_priv, reg)  (((volatile u32 *)\
-			(LP_RING(dev_priv)->status_page.page_addr))[reg])
-#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
-#define I915_GEM_HWS_INDEX		0x20
-#define I915_BREADCRUMB_INDEX		0x21
-
 #endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 36e66cc..c4c2855 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -75,8 +75,8 @@ static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
 	dev_priv->mm.object_memory -= size;
 }
 
-int
-i915_gem_check_is_wedged(struct drm_device *dev)
+static int
+i915_gem_wait_for_error(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct completion *x = &dev_priv->error_completion;
@@ -90,27 +90,24 @@ i915_gem_check_is_wedged(struct drm_device *dev)
 	if (ret)
 		return ret;
 
-	/* Success, we reset the GPU! */
-	if (!atomic_read(&dev_priv->mm.wedged))
-		return 0;
-
-	/* GPU is hung, bump the completion count to account for
-	 * the token we just consumed so that we never hit zero and
-	 * end up waiting upon a subsequent completion event that
-	 * will never happen.
-	 */
-	spin_lock_irqsave(&x->wait.lock, flags);
-	x->done++;
-	spin_unlock_irqrestore(&x->wait.lock, flags);
-	return -EIO;
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		/* GPU is hung, bump the completion count to account for
+		 * the token we just consumed so that we never hit zero and
+		 * end up waiting upon a subsequent completion event that
+		 * will never happen.
+		 */
+		spin_lock_irqsave(&x->wait.lock, flags);
+		x->done++;
+		spin_unlock_irqrestore(&x->wait.lock, flags);
+	}
+	return 0;
 }
 
 int i915_mutex_lock_interruptible(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = i915_gem_check_is_wedged(dev);
+	ret = i915_gem_wait_for_error(dev);
 	if (ret)
 		return ret;
 
@@ -118,11 +115,6 @@ int i915_mutex_lock_interruptible(struct drm_device *dev)
 	if (ret)
 		return ret;
 
-	if (atomic_read(&dev_priv->mm.wedged)) {
-		mutex_unlock(&dev->struct_mutex);
-		return -EAGAIN;
-	}
-
 	WARN_ON(i915_verify_lists(dev));
 	return 0;
 }
@@ -193,22 +185,20 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 	return 0;
 }
 
-/**
- * Creates a new mm object and returns a handle to it.
- */
-int
-i915_gem_create_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file)
+static int
+i915_gem_create(struct drm_file *file,
+		struct drm_device *dev,
+		uint64_t size,
+		uint32_t *handle_p)
 {
-	struct drm_i915_gem_create *args = data;
 	struct drm_i915_gem_object *obj;
 	int ret;
 	u32 handle;
 
-	args->size = roundup(args->size, PAGE_SIZE);
+	size = roundup(size, PAGE_SIZE);
 
 	/* Allocate the new object */
-	obj = i915_gem_alloc_object(dev, args->size);
+	obj = i915_gem_alloc_object(dev, size);
 	if (obj == NULL)
 		return -ENOMEM;
 
@@ -224,10 +214,41 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
 	drm_gem_object_unreference(&obj->base);
 	trace_i915_gem_object_create(obj);
 
-	args->handle = handle;
+	*handle_p = handle;
 	return 0;
 }
 
+int
+i915_gem_dumb_create(struct drm_file *file,
+		     struct drm_device *dev,
+		     struct drm_mode_create_dumb *args)
+{
+	/* have to work out size/pitch and return them */
+	args->pitch = ALIGN(args->width & ((args->bpp + 1) / 8), 64);
+	args->size = args->pitch * args->height;
+	return i915_gem_create(file, dev,
+			       args->size, &args->handle);
+}
+
+int i915_gem_dumb_destroy(struct drm_file *file,
+			  struct drm_device *dev,
+			  uint32_t handle)
+{
+	return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
+int
+i915_gem_create_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file)
+{
+	struct drm_i915_gem_create *args = data;
+	return i915_gem_create(file, dev,
+			       args->size, &args->handle);
+}
+
 static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
 	drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
@@ -514,7 +535,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -526,6 +547,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 		goto out;
 	}
 
+	trace_i915_gem_object_pread(obj, args->offset, args->size);
+
 	ret = i915_gem_object_set_cpu_read_domain_range(obj,
 							args->offset,
 							args->size);
@@ -955,7 +978,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -967,6 +990,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		goto out;
 	}
 
+	trace_i915_gem_object_pwrite(obj, args->offset, args->size);
+
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
 	 * it would end up going through the fenced access, and we'll get
 	 * different detiling behavior between reading and writing.
@@ -1049,7 +1074,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -1092,7 +1117,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -1121,7 +1146,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_mmap *args = data;
 	struct drm_gem_object *obj;
-	loff_t offset;
 	unsigned long addr;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM))
@@ -1136,8 +1160,6 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 		return -E2BIG;
 	}
 
-	offset = args->offset;
-
 	down_write(&current->mm->mmap_sem);
 	addr = do_mmap(obj->filp, 0, args->size,
 		       PROT_READ | PROT_WRITE, MAP_SHARED,
@@ -1182,9 +1204,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
 		PAGE_SHIFT;
 
-	/* Now bind it into the GTT if needed */
-	mutex_lock(&dev->struct_mutex);
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		goto out;
 
+	trace_i915_gem_object_fault(obj, page_offset, true, write);
+
+	/* Now bind it into the GTT if needed */
 	if (!obj->map_and_fenceable) {
 		ret = i915_gem_object_unbind(obj);
 		if (ret)
@@ -1203,7 +1229,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	if (obj->tiling_mode == I915_TILING_NONE)
 		ret = i915_gem_object_put_fence(obj);
 	else
-		ret = i915_gem_object_get_fence(obj, NULL, true);
+		ret = i915_gem_object_get_fence(obj, NULL);
 	if (ret)
 		goto unlock;
 
@@ -1219,12 +1245,21 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
-
+out:
 	switch (ret) {
+	case -EIO:
 	case -EAGAIN:
+		/* Give the error handler a chance to run and move the
+		 * objects off the GPU active list. Next time we service the
+		 * fault, we should be able to transition the page into the
+		 * GTT without touching the GPU (and so avoid further
+		 * EIO/EGAIN). If the GPU is wedged, then there is no issue
+		 * with coherency, just lost writes.
+		 */
 		set_need_resched();
 	case 0:
 	case -ERESTARTSYS:
+	case -EINTR:
 		return VM_FAULT_NOPAGE;
 	case -ENOMEM:
 		return VM_FAULT_OOM;
@@ -1425,27 +1460,13 @@ i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj)
 	return tile_height * obj->stride * 2;
 }
 
-/**
- * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
- * @dev: DRM device
- * @data: GTT mapping ioctl data
- * @file: GEM object info
- *
- * Simply returns the fake offset to userspace so it can mmap it.
- * The mmap call will end up in drm_gem_mmap(), which will set things
- * up so we can get faults in the handler above.
- *
- * The fault handler will take care of binding the object into the GTT
- * (since it may have been evicted to make room for something), allocating
- * a fence register, and mapping the appropriate aperture address into
- * userspace.
- */
 int
-i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file)
+i915_gem_mmap_gtt(struct drm_file *file,
+		  struct drm_device *dev,
+		  uint32_t handle,
+		  uint64_t *offset)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_mmap_gtt *args = data;
 	struct drm_i915_gem_object *obj;
 	int ret;
 
@@ -1456,8 +1477,8 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -1479,7 +1500,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
 			goto out;
 	}
 
-	args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
+	*offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
 
 out:
 	drm_gem_object_unreference(&obj->base);
@@ -1488,6 +1509,34 @@ unlock:
 	return ret;
 }
 
+/**
+ * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
+ * @dev: DRM device
+ * @data: GTT mapping ioctl data
+ * @file: GEM object info
+ *
+ * Simply returns the fake offset to userspace so it can mmap it.
+ * The mmap call will end up in drm_gem_mmap(), which will set things
+ * up so we can get faults in the handler above.
+ *
+ * The fault handler will take care of binding the object into the GTT
+ * (since it may have been evicted to make room for something), allocating
+ * a fence register, and mapping the appropriate aperture address into
+ * userspace.
+ */
+int
+i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file)
+{
+	struct drm_i915_gem_mmap_gtt *args = data;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
+}
+
+
 static int
 i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
 			      gfp_t gfpmask)
@@ -1669,9 +1718,8 @@ i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
 }
 
 static void
-i915_gem_process_flushing_list(struct drm_device *dev,
-			       uint32_t flush_domains,
-			       struct intel_ring_buffer *ring)
+i915_gem_process_flushing_list(struct intel_ring_buffer *ring,
+			       uint32_t flush_domains)
 {
 	struct drm_i915_gem_object *obj, *next;
 
@@ -1684,7 +1732,7 @@ i915_gem_process_flushing_list(struct drm_device *dev,
 			obj->base.write_domain = 0;
 			list_del_init(&obj->gpu_write_list);
 			i915_gem_object_move_to_active(obj, ring,
-						       i915_gem_next_request_seqno(dev, ring));
+						       i915_gem_next_request_seqno(ring));
 
 			trace_i915_gem_object_change_domain(obj,
 							    obj->base.read_domains,
@@ -1694,27 +1742,22 @@ i915_gem_process_flushing_list(struct drm_device *dev,
 }
 
 int
-i915_add_request(struct drm_device *dev,
+i915_add_request(struct intel_ring_buffer *ring,
 		 struct drm_file *file,
-		 struct drm_i915_gem_request *request,
-		 struct intel_ring_buffer *ring)
+		 struct drm_i915_gem_request *request)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_file_private *file_priv = NULL;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	uint32_t seqno;
 	int was_empty;
 	int ret;
 
 	BUG_ON(request == NULL);
 
-	if (file != NULL)
-		file_priv = file->driver_priv;
-
 	ret = ring->add_request(ring, &seqno);
 	if (ret)
 	    return ret;
 
-	ring->outstanding_lazy_request = false;
+	trace_i915_gem_request_add(ring, seqno);
 
 	request->seqno = seqno;
 	request->ring = ring;
@@ -1722,7 +1765,9 @@ i915_add_request(struct drm_device *dev,
 	was_empty = list_empty(&ring->request_list);
 	list_add_tail(&request->list, &ring->request_list);
 
-	if (file_priv) {
+	if (file) {
+		struct drm_i915_file_private *file_priv = file->driver_priv;
+
 		spin_lock(&file_priv->mm.lock);
 		request->file_priv = file_priv;
 		list_add_tail(&request->client_list,
@@ -1730,6 +1775,8 @@ i915_add_request(struct drm_device *dev,
 		spin_unlock(&file_priv->mm.lock);
 	}
 
+	ring->outstanding_lazy_request = false;
+
 	if (!dev_priv->mm.suspended) {
 		mod_timer(&dev_priv->hangcheck_timer,
 			  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
@@ -1846,18 +1893,15 @@ void i915_gem_reset(struct drm_device *dev)
  * This function clears the request list as sequence numbers are passed.
  */
 static void
-i915_gem_retire_requests_ring(struct drm_device *dev,
-			      struct intel_ring_buffer *ring)
+i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t seqno;
 	int i;
 
-	if (!ring->status_page.page_addr ||
-	    list_empty(&ring->request_list))
+	if (list_empty(&ring->request_list))
 		return;
 
-	WARN_ON(i915_verify_lists(dev));
+	WARN_ON(i915_verify_lists(ring->dev));
 
 	seqno = ring->get_seqno(ring);
 
@@ -1875,7 +1919,7 @@ i915_gem_retire_requests_ring(struct drm_device *dev,
 		if (!i915_seqno_passed(seqno, request->seqno))
 			break;
 
-		trace_i915_gem_request_retire(dev, request->seqno);
+		trace_i915_gem_request_retire(ring, request->seqno);
 
 		list_del(&request->list);
 		i915_gem_request_remove_from_client(request);
@@ -1901,13 +1945,13 @@ i915_gem_retire_requests_ring(struct drm_device *dev,
 			i915_gem_object_move_to_inactive(obj);
 	}
 
-	if (unlikely (dev_priv->trace_irq_seqno &&
-		      i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
+	if (unlikely(ring->trace_irq_seqno &&
+		     i915_seqno_passed(seqno, ring->trace_irq_seqno))) {
 		ring->irq_put(ring);
-		dev_priv->trace_irq_seqno = 0;
+		ring->trace_irq_seqno = 0;
 	}
 
-	WARN_ON(i915_verify_lists(dev));
+	WARN_ON(i915_verify_lists(ring->dev));
 }
 
 void
@@ -1931,7 +1975,7 @@ i915_gem_retire_requests(struct drm_device *dev)
 	}
 
 	for (i = 0; i < I915_NUM_RINGS; i++)
-		i915_gem_retire_requests_ring(dev, &dev_priv->ring[i]);
+		i915_gem_retire_requests_ring(&dev_priv->ring[i]);
 }
 
 static void
@@ -1965,11 +2009,11 @@ i915_gem_retire_work_handler(struct work_struct *work)
 			struct drm_i915_gem_request *request;
 			int ret;
 
-			ret = i915_gem_flush_ring(dev, ring, 0,
-						  I915_GEM_GPU_DOMAINS);
+			ret = i915_gem_flush_ring(ring,
+						  0, I915_GEM_GPU_DOMAINS);
 			request = kzalloc(sizeof(*request), GFP_KERNEL);
 			if (ret || request == NULL ||
-			    i915_add_request(dev, NULL, request, ring))
+			    i915_add_request(ring, NULL, request))
 			    kfree(request);
 		}
 
@@ -1982,18 +2026,32 @@ i915_gem_retire_work_handler(struct work_struct *work)
 	mutex_unlock(&dev->struct_mutex);
 }
 
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
 int
-i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
-		     bool interruptible, struct intel_ring_buffer *ring)
+i915_wait_request(struct intel_ring_buffer *ring,
+		  uint32_t seqno)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	u32 ier;
 	int ret = 0;
 
 	BUG_ON(seqno == 0);
 
-	if (atomic_read(&dev_priv->mm.wedged))
-		return -EAGAIN;
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		struct completion *x = &dev_priv->error_completion;
+		bool recovery_complete;
+		unsigned long flags;
+
+		/* Give the error handler a chance to run. */
+		spin_lock_irqsave(&x->wait.lock, flags);
+		recovery_complete = x->done > 0;
+		spin_unlock_irqrestore(&x->wait.lock, flags);
+
+		return recovery_complete ? -EIO : -EAGAIN;
+	}
 
 	if (seqno == ring->outstanding_lazy_request) {
 		struct drm_i915_gem_request *request;
@@ -2002,7 +2060,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
 		if (request == NULL)
 			return -ENOMEM;
 
-		ret = i915_add_request(dev, NULL, request, ring);
+		ret = i915_add_request(ring, NULL, request);
 		if (ret) {
 			kfree(request);
 			return ret;
@@ -2012,22 +2070,22 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
 	}
 
 	if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
-		if (HAS_PCH_SPLIT(dev))
+		if (HAS_PCH_SPLIT(ring->dev))
 			ier = I915_READ(DEIER) | I915_READ(GTIER);
 		else
 			ier = I915_READ(IER);
 		if (!ier) {
 			DRM_ERROR("something (likely vbetool) disabled "
 				  "interrupts, re-enabling\n");
-			i915_driver_irq_preinstall(dev);
-			i915_driver_irq_postinstall(dev);
+			i915_driver_irq_preinstall(ring->dev);
+			i915_driver_irq_postinstall(ring->dev);
 		}
 
-		trace_i915_gem_request_wait_begin(dev, seqno);
+		trace_i915_gem_request_wait_begin(ring, seqno);
 
 		ring->waiting_seqno = seqno;
 		if (ring->irq_get(ring)) {
-			if (interruptible)
+			if (dev_priv->mm.interruptible)
 				ret = wait_event_interruptible(ring->irq_queue,
 							       i915_seqno_passed(ring->get_seqno(ring), seqno)
 							       || atomic_read(&dev_priv->mm.wedged));
@@ -2043,7 +2101,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
 			ret = -EBUSY;
 		ring->waiting_seqno = 0;
 
-		trace_i915_gem_request_wait_end(dev, seqno);
+		trace_i915_gem_request_wait_end(ring, seqno);
 	}
 	if (atomic_read(&dev_priv->mm.wedged))
 		ret = -EAGAIN;
@@ -2059,31 +2117,18 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
 	 * a separate wait queue to handle that.
 	 */
 	if (ret == 0)
-		i915_gem_retire_requests_ring(dev, ring);
+		i915_gem_retire_requests_ring(ring);
 
 	return ret;
 }
 
 /**
- * Waits for a sequence number to be signaled, and cleans up the
- * request and object lists appropriately for that event.
- */
-static int
-i915_wait_request(struct drm_device *dev, uint32_t seqno,
-		  struct intel_ring_buffer *ring)
-{
-	return i915_do_wait_request(dev, seqno, 1, ring);
-}
-
-/**
  * Ensures that all rendering to the object has completed and the object is
  * safe to unbind from the GTT or access from the CPU.
  */
 int
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
-			       bool interruptible)
+i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
 	int ret;
 
 	/* This function only exists to support waiting for existing rendering,
@@ -2095,10 +2140,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
 	 * it.
 	 */
 	if (obj->active) {
-		ret = i915_do_wait_request(dev,
-					   obj->last_rendering_seqno,
-					   interruptible,
-					   obj->ring);
+		ret = i915_wait_request(obj->ring, obj->last_rendering_seqno);
 		if (ret)
 			return ret;
 	}
@@ -2148,6 +2190,8 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	if (ret == -ERESTARTSYS)
 		return ret;
 
+	trace_i915_gem_object_unbind(obj);
+
 	i915_gem_gtt_unbind_object(obj);
 	i915_gem_object_put_pages_gtt(obj);
 
@@ -2163,29 +2207,27 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
 	if (i915_gem_object_is_purgeable(obj))
 		i915_gem_object_truncate(obj);
 
-	trace_i915_gem_object_unbind(obj);
-
 	return ret;
 }
 
 int
-i915_gem_flush_ring(struct drm_device *dev,
-		    struct intel_ring_buffer *ring,
+i915_gem_flush_ring(struct intel_ring_buffer *ring,
 		    uint32_t invalidate_domains,
 		    uint32_t flush_domains)
 {
 	int ret;
 
+	trace_i915_gem_ring_flush(ring, invalidate_domains, flush_domains);
+
 	ret = ring->flush(ring, invalidate_domains, flush_domains);
 	if (ret)
 		return ret;
 
-	i915_gem_process_flushing_list(dev, flush_domains, ring);
+	i915_gem_process_flushing_list(ring, flush_domains);
 	return 0;
 }
 
-static int i915_ring_idle(struct drm_device *dev,
-			  struct intel_ring_buffer *ring)
+static int i915_ring_idle(struct intel_ring_buffer *ring)
 {
 	int ret;
 
@@ -2193,15 +2235,13 @@ static int i915_ring_idle(struct drm_device *dev,
 		return 0;
 
 	if (!list_empty(&ring->gpu_write_list)) {
-		ret = i915_gem_flush_ring(dev, ring,
+		ret = i915_gem_flush_ring(ring,
 				    I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 		if (ret)
 			return ret;
 	}
 
-	return i915_wait_request(dev,
-				 i915_gem_next_request_seqno(dev, ring),
-				 ring);
+	return i915_wait_request(ring, i915_gem_next_request_seqno(ring));
 }
 
 int
@@ -2218,7 +2258,7 @@ i915_gpu_idle(struct drm_device *dev)
 
 	/* Flush everything onto the inactive list. */
 	for (i = 0; i < I915_NUM_RINGS; i++) {
-		ret = i915_ring_idle(dev, &dev_priv->ring[i]);
+		ret = i915_ring_idle(&dev_priv->ring[i]);
 		if (ret)
 			return ret;
 	}
@@ -2402,15 +2442,13 @@ static bool ring_passed_seqno(struct intel_ring_buffer *ring, u32 seqno)
 
 static int
 i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
-			    struct intel_ring_buffer *pipelined,
-			    bool interruptible)
+			    struct intel_ring_buffer *pipelined)
 {
 	int ret;
 
 	if (obj->fenced_gpu_access) {
 		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-			ret = i915_gem_flush_ring(obj->base.dev,
-						  obj->last_fenced_ring,
+			ret = i915_gem_flush_ring(obj->last_fenced_ring,
 						  0, obj->base.write_domain);
 			if (ret)
 				return ret;
@@ -2422,10 +2460,8 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
 	if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) {
 		if (!ring_passed_seqno(obj->last_fenced_ring,
 				       obj->last_fenced_seqno)) {
-			ret = i915_do_wait_request(obj->base.dev,
-						   obj->last_fenced_seqno,
-						   interruptible,
-						   obj->last_fenced_ring);
+			ret = i915_wait_request(obj->last_fenced_ring,
+						obj->last_fenced_seqno);
 			if (ret)
 				return ret;
 		}
@@ -2451,7 +2487,7 @@ i915_gem_object_put_fence(struct drm_i915_gem_object *obj)
 	if (obj->tiling_mode)
 		i915_gem_release_mmap(obj);
 
-	ret = i915_gem_object_flush_fence(obj, NULL, true);
+	ret = i915_gem_object_flush_fence(obj, NULL);
 	if (ret)
 		return ret;
 
@@ -2528,8 +2564,7 @@ i915_find_fence_reg(struct drm_device *dev,
  */
 int
 i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
-			  struct intel_ring_buffer *pipelined,
-			  bool interruptible)
+			  struct intel_ring_buffer *pipelined)
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2551,10 +2586,8 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 			if (reg->setup_seqno) {
 				if (!ring_passed_seqno(obj->last_fenced_ring,
 						       reg->setup_seqno)) {
-					ret = i915_do_wait_request(obj->base.dev,
-								   reg->setup_seqno,
-								   interruptible,
-								   obj->last_fenced_ring);
+					ret = i915_wait_request(obj->last_fenced_ring,
+								reg->setup_seqno);
 					if (ret)
 						return ret;
 				}
@@ -2563,15 +2596,13 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 			}
 		} else if (obj->last_fenced_ring &&
 			   obj->last_fenced_ring != pipelined) {
-			ret = i915_gem_object_flush_fence(obj,
-							  pipelined,
-							  interruptible);
+			ret = i915_gem_object_flush_fence(obj, pipelined);
 			if (ret)
 				return ret;
 		} else if (obj->tiling_changed) {
 			if (obj->fenced_gpu_access) {
 				if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-					ret = i915_gem_flush_ring(obj->base.dev, obj->ring,
+					ret = i915_gem_flush_ring(obj->ring,
 								  0, obj->base.write_domain);
 					if (ret)
 						return ret;
@@ -2588,7 +2619,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 		if (obj->tiling_changed) {
 			if (pipelined) {
 				reg->setup_seqno =
-					i915_gem_next_request_seqno(dev, pipelined);
+					i915_gem_next_request_seqno(pipelined);
 				obj->last_fenced_seqno = reg->setup_seqno;
 				obj->last_fenced_ring = pipelined;
 			}
@@ -2602,7 +2633,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 	if (reg == NULL)
 		return -ENOSPC;
 
-	ret = i915_gem_object_flush_fence(obj, pipelined, interruptible);
+	ret = i915_gem_object_flush_fence(obj, pipelined);
 	if (ret)
 		return ret;
 
@@ -2614,9 +2645,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 		if (old->tiling_mode)
 			i915_gem_release_mmap(old);
 
-		ret = i915_gem_object_flush_fence(old,
-						  pipelined,
-						  interruptible);
+		ret = i915_gem_object_flush_fence(old, pipelined);
 		if (ret) {
 			drm_gem_object_unreference(&old->base);
 			return ret;
@@ -2628,7 +2657,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 		old->fence_reg = I915_FENCE_REG_NONE;
 		old->last_fenced_ring = pipelined;
 		old->last_fenced_seqno =
-			pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0;
+			pipelined ? i915_gem_next_request_seqno(pipelined) : 0;
 
 		drm_gem_object_unreference(&old->base);
 	} else if (obj->last_fenced_seqno == 0)
@@ -2640,7 +2669,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
 	obj->last_fenced_ring = pipelined;
 
 	reg->setup_seqno =
-		pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0;
+		pipelined ? i915_gem_next_request_seqno(pipelined) : 0;
 	obj->last_fenced_seqno = reg->setup_seqno;
 
 update:
@@ -2837,7 +2866,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
 
 	obj->map_and_fenceable = mappable && fenceable;
 
-	trace_i915_gem_object_bind(obj, obj->gtt_offset, map_and_fenceable);
+	trace_i915_gem_object_bind(obj, map_and_fenceable);
 	return 0;
 }
 
@@ -2860,13 +2889,11 @@ i915_gem_clflush_object(struct drm_i915_gem_object *obj)
 static int
 i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-
 	if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
 		return 0;
 
 	/* Queue the GPU write cache flushing we need. */
-	return i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain);
+	return i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
 }
 
 /** Flushes the GTT write domain for the object if it's dirty. */
@@ -2933,12 +2960,15 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
 	if (obj->gtt_space == NULL)
 		return -EINVAL;
 
+	if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
+		return 0;
+
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
 	if (ret)
 		return ret;
 
 	if (obj->pending_gpu_write || write) {
-		ret = i915_gem_object_wait_rendering(obj, true);
+		ret = i915_gem_object_wait_rendering(obj);
 		if (ret)
 			return ret;
 	}
@@ -2988,7 +3018,7 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
 
 	/* Currently, we are always called from an non-interruptible context. */
 	if (pipelined != obj->ring) {
-		ret = i915_gem_object_wait_rendering(obj, false);
+		ret = i915_gem_object_wait_rendering(obj);
 		if (ret)
 			return ret;
 	}
@@ -3006,8 +3036,7 @@ i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj,
 }
 
 int
-i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
-			  bool interruptible)
+i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
 {
 	int ret;
 
@@ -3015,13 +3044,12 @@ i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
 		return 0;
 
 	if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-		ret = i915_gem_flush_ring(obj->base.dev, obj->ring,
-					  0, obj->base.write_domain);
+		ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
 		if (ret)
 			return ret;
 	}
 
-	return i915_gem_object_wait_rendering(obj, interruptible);
+	return i915_gem_object_wait_rendering(obj);
 }
 
 /**
@@ -3036,11 +3064,14 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 
+	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU)
+		return 0;
+
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_wait_rendering(obj, true);
+	ret = i915_gem_object_wait_rendering(obj);
 	if (ret)
 		return ret;
 
@@ -3138,7 +3169,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj,
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_wait_rendering(obj, true);
+	ret = i915_gem_object_wait_rendering(obj);
 	if (ret)
 		return ret;
 
@@ -3209,6 +3240,9 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
 	u32 seqno = 0;
 	int ret;
 
+	if (atomic_read(&dev_priv->mm.wedged))
+		return -EIO;
+
 	spin_lock(&file_priv->mm.lock);
 	list_for_each_entry(request, &file_priv->mm.request_list, client_list) {
 		if (time_after_eq(request->emitted_jiffies, recent_enough))
@@ -3324,7 +3358,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3375,7 +3409,7 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3412,7 +3446,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3430,7 +3464,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 		 * flush earlier is beneficial.
 		 */
 		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-			ret = i915_gem_flush_ring(dev, obj->ring,
+			ret = i915_gem_flush_ring(obj->ring,
 						  0, obj->base.write_domain);
 		} else if (obj->ring->outstanding_lazy_request ==
 			   obj->last_rendering_seqno) {
@@ -3441,9 +3475,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 			 */
 			request = kzalloc(sizeof(*request), GFP_KERNEL);
 			if (request)
-				ret = i915_add_request(dev,
-						       NULL, request,
-						       obj->ring);
+				ret = i915_add_request(obj->ring, NULL,request);
 			else
 				ret = -ENOMEM;
 		}
@@ -3453,7 +3485,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 		 * are actually unmasked, and our working set ends up being
 		 * larger than required.
 		 */
-		i915_gem_retire_requests_ring(dev, obj->ring);
+		i915_gem_retire_requests_ring(obj->ring);
 
 		args->busy = obj->active;
 	}
@@ -3492,7 +3524,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3583,6 +3615,8 @@ static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj)
 	kfree(obj->page_cpu_valid);
 	kfree(obj->bit_17);
 	kfree(obj);
+
+	trace_i915_gem_object_destroy(obj);
 }
 
 void i915_gem_free_object(struct drm_gem_object *gem_obj)
@@ -3590,8 +3624,6 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
 	struct drm_device *dev = obj->base.dev;
 
-	trace_i915_gem_object_destroy(obj);
-
 	while (obj->pin_count > 0)
 		i915_gem_object_unpin(obj);
 
@@ -3837,6 +3869,8 @@ i915_gem_load(struct drm_device *dev)
 	i915_gem_detect_bit_6_swizzle(dev);
 	init_waitqueue_head(&dev_priv->pending_flip_queue);
 
+	dev_priv->mm.interruptible = true;
+
 	dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink;
 	dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS;
 	register_shrinker(&dev_priv->mm.inactive_shrinker);
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c
index 29d014c..8da1899 100644
--- a/drivers/gpu/drm/i915/i915_gem_debug.c
+++ b/drivers/gpu/drm/i915/i915_gem_debug.c
@@ -134,51 +134,6 @@ i915_verify_lists(struct drm_device *dev)
 }
 #endif /* WATCH_INACTIVE */
 
-
-#if WATCH_EXEC | WATCH_PWRITE
-static void
-i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
-		   uint32_t bias, uint32_t mark)
-{
-	uint32_t *mem = kmap_atomic(page, KM_USER0);
-	int i;
-	for (i = start; i < end; i += 4)
-		DRM_INFO("%08x: %08x%s\n",
-			  (int) (bias + i), mem[i / 4],
-			  (bias + i == mark) ? " ********" : "");
-	kunmap_atomic(mem, KM_USER0);
-	/* give syslog time to catch up */
-	msleep(1);
-}
-
-void
-i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
-		     const char *where, uint32_t mark)
-{
-	int page;
-
-	DRM_INFO("%s: object at offset %08x\n", where, obj->gtt_offset);
-	for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
-		int page_len, chunk, chunk_len;
-
-		page_len = len - page * PAGE_SIZE;
-		if (page_len > PAGE_SIZE)
-			page_len = PAGE_SIZE;
-
-		for (chunk = 0; chunk < page_len; chunk += 128) {
-			chunk_len = page_len - chunk;
-			if (chunk_len > 128)
-				chunk_len = 128;
-			i915_gem_dump_page(obj->pages[page],
-					   chunk, chunk + chunk_len,
-					   obj->gtt_offset +
-					   page * PAGE_SIZE,
-					   mark);
-		}
-	}
-}
-#endif
-
 #if WATCH_COHERENCY
 void
 i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 3d39005..da05a26 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -30,6 +30,7 @@
 #include "drm.h"
 #include "i915_drv.h"
 #include "i915_drm.h"
+#include "i915_trace.h"
 
 static bool
 mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
@@ -63,6 +64,8 @@ i915_gem_evict_something(struct drm_device *dev, int min_size,
 			return 0;
 	}
 
+	trace_i915_gem_evict(dev, min_size, alignment, mappable);
+
 	/*
 	 * The goal is to evict objects and amalgamate space in LRU order.
 	 * The oldest idle objects reside on the inactive list, which is in
@@ -189,6 +192,8 @@ i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only)
 	if (lists_empty)
 		return -ENOSPC;
 
+	trace_i915_gem_evict_everything(dev, purgeable_only);
+
 	/* Flush everything (on to the inactive lists) and evict */
 	ret = i915_gpu_idle(dev);
 	if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 50ab161..7ff7f93 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -37,6 +37,7 @@ struct change_domains {
 	uint32_t invalidate_domains;
 	uint32_t flush_domains;
 	uint32_t flush_rings;
+	uint32_t flips;
 };
 
 /*
@@ -190,6 +191,9 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,
 	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT)
 		i915_gem_release_mmap(obj);
 
+	if (obj->base.pending_write_domain)
+		cd->flips |= atomic_read(&obj->pending_flip);
+
 	/* The actual obj->write_domain will be updated with
 	 * pending_write_domain after we emit the accumulated flush for all
 	 * of our domain changes in execbuffers (which clears objects'
@@ -282,21 +286,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 
 	target_offset = to_intel_bo(target_obj)->gtt_offset;
 
-#if WATCH_RELOC
-	DRM_INFO("%s: obj %p offset %08x target %d "
-		 "read %08x write %08x gtt %08x "
-		 "presumed %08x delta %08x\n",
-		 __func__,
-		 obj,
-		 (int) reloc->offset,
-		 (int) reloc->target_handle,
-		 (int) reloc->read_domains,
-		 (int) reloc->write_domain,
-		 (int) target_offset,
-		 (int) reloc->presumed_offset,
-		 reloc->delta);
-#endif
-
 	/* The target buffer should have appeared before us in the
 	 * exec_object list, so it should have a GTT space bound by now.
 	 */
@@ -365,16 +354,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 		return ret;
 	}
 
-	/* and points to somewhere within the target object. */
-	if (unlikely(reloc->delta >= target_obj->size)) {
-		DRM_ERROR("Relocation beyond target object bounds: "
-			  "obj %p target %d delta %d size %d.\n",
-			  obj, reloc->target_handle,
-			  (int) reloc->delta,
-			  (int) target_obj->size);
-		return ret;
-	}
-
 	reloc->delta += target_offset;
 	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
 		uint32_t page_offset = reloc->offset & ~PAGE_MASK;
@@ -575,7 +554,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
 
 			if (has_fenced_gpu_access) {
 				if (need_fence) {
-					ret = i915_gem_object_get_fence(obj, ring, 1);
+					ret = i915_gem_object_get_fence(obj, ring);
 					if (ret)
 						break;
 				} else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
@@ -690,11 +669,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
 	/* reacquire the objects */
 	eb_reset(eb);
 	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_object *obj;
-
 		obj = to_intel_bo(drm_gem_object_lookup(dev, file,
 							exec[i].handle));
-		if (obj == NULL) {
+		if (&obj->base == NULL) {
 			DRM_ERROR("Invalid object handle %d at index %d\n",
 				   exec[i].handle, i);
 			ret = -ENOENT;
@@ -749,8 +726,7 @@ i915_gem_execbuffer_flush(struct drm_device *dev,
 	if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) {
 		for (i = 0; i < I915_NUM_RINGS; i++)
 			if (flush_rings & (1 << i)) {
-				ret = i915_gem_flush_ring(dev,
-							  &dev_priv->ring[i],
+				ret = i915_gem_flush_ring(&dev_priv->ring[i],
 							  invalidate_domains,
 							  flush_domains);
 				if (ret)
@@ -774,7 +750,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
 
 	/* XXX gpu semaphores are implicated in various hard hangs on SNB */
 	if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores)
-		return i915_gem_object_wait_rendering(obj, true);
+		return i915_gem_object_wait_rendering(obj);
 
 	idx = intel_ring_sync_index(from, to);
 
@@ -789,7 +765,7 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
 		if (request == NULL)
 			return -ENOMEM;
 
-		ret = i915_add_request(obj->base.dev, NULL, request, from);
+		ret = i915_add_request(from, NULL, request);
 		if (ret) {
 			kfree(request);
 			return ret;
@@ -803,6 +779,39 @@ i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj,
 }
 
 static int
+i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
+{
+	u32 plane, flip_mask;
+	int ret;
+
+	/* Check for any pending flips. As we only maintain a flip queue depth
+	 * of 1, we can simply insert a WAIT for the next display flip prior
+	 * to executing the batch and avoid stalling the CPU.
+	 */
+
+	for (plane = 0; flips >> plane; plane++) {
+		if (((flips >> plane) & 1) == 0)
+			continue;
+
+		if (plane)
+			flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+		else
+			flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+
+		ret = intel_ring_begin(ring, 2);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_advance(ring);
+	}
+
+	return 0;
+}
+
+
+static int
 i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 				struct list_head *objects)
 {
@@ -810,19 +819,11 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 	struct change_domains cd;
 	int ret;
 
-	cd.invalidate_domains = 0;
-	cd.flush_domains = 0;
-	cd.flush_rings = 0;
+	memset(&cd, 0, sizeof(cd));
 	list_for_each_entry(obj, objects, exec_list)
 		i915_gem_object_set_to_gpu_domain(obj, ring, &cd);
 
 	if (cd.invalidate_domains | cd.flush_domains) {
-#if WATCH_EXEC
-		DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
-			  __func__,
-			 cd.invalidate_domains,
-			 cd.flush_domains);
-#endif
 		ret = i915_gem_execbuffer_flush(ring->dev,
 						cd.invalidate_domains,
 						cd.flush_domains,
@@ -831,6 +832,12 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 			return ret;
 	}
 
+	if (cd.flips) {
+		ret = i915_gem_execbuffer_wait_for_flips(ring, cd.flips);
+		if (ret)
+			return ret;
+	}
+
 	list_for_each_entry(obj, objects, exec_list) {
 		ret = i915_gem_execbuffer_sync_rings(obj, ring);
 		if (ret)
@@ -877,47 +884,6 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 	return 0;
 }
 
-static int
-i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring,
-				   struct list_head *objects)
-{
-	struct drm_i915_gem_object *obj;
-	int flips;
-
-	/* Check for any pending flips. As we only maintain a flip queue depth
-	 * of 1, we can simply insert a WAIT for the next display flip prior
-	 * to executing the batch and avoid stalling the CPU.
-	 */
-	flips = 0;
-	list_for_each_entry(obj, objects, exec_list) {
-		if (obj->base.write_domain)
-			flips |= atomic_read(&obj->pending_flip);
-	}
-	if (flips) {
-		int plane, flip_mask, ret;
-
-		for (plane = 0; flips >> plane; plane++) {
-			if (((flips >> plane) & 1) == 0)
-				continue;
-
-			if (plane)
-				flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-			else
-				flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-
-			ret = intel_ring_begin(ring, 2);
-			if (ret)
-				return ret;
-
-			intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
-			intel_ring_emit(ring, MI_NOOP);
-			intel_ring_advance(ring);
-		}
-	}
-
-	return 0;
-}
-
 static void
 i915_gem_execbuffer_move_to_active(struct list_head *objects,
 				   struct intel_ring_buffer *ring,
@@ -926,6 +892,10 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 	struct drm_i915_gem_object *obj;
 
 	list_for_each_entry(obj, objects, exec_list) {
+		  u32 old_read = obj->base.read_domains;
+		  u32 old_write = obj->base.write_domain;
+
+
 		obj->base.read_domains = obj->base.pending_read_domains;
 		obj->base.write_domain = obj->base.pending_write_domain;
 		obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
@@ -939,9 +909,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
 			intel_mark_busy(ring->dev, obj);
 		}
 
-		trace_i915_gem_object_change_domain(obj,
-						    obj->base.read_domains,
-						    obj->base.write_domain);
+		trace_i915_gem_object_change_domain(obj, old_read, old_write);
 	}
 }
 
@@ -963,14 +931,14 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
 	if (INTEL_INFO(dev)->gen >= 4)
 		invalidate |= I915_GEM_DOMAIN_SAMPLER;
 	if (ring->flush(ring, invalidate, 0)) {
-		i915_gem_next_request_seqno(dev, ring);
+		i915_gem_next_request_seqno(ring);
 		return;
 	}
 
 	/* Add a breadcrumb for the completion of the batch buffer */
 	request = kzalloc(sizeof(*request), GFP_KERNEL);
-	if (request == NULL || i915_add_request(dev, file, request, ring)) {
-		i915_gem_next_request_seqno(dev, ring);
+	if (request == NULL || i915_add_request(ring, file, request)) {
+		i915_gem_next_request_seqno(ring);
 		kfree(request);
 	}
 }
@@ -1000,10 +968,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		return ret;
 
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
 	switch (args->flags & I915_EXEC_RING_MASK) {
 	case I915_EXEC_DEFAULT:
 	case I915_EXEC_RENDER:
@@ -1113,7 +1077,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
 		obj = to_intel_bo(drm_gem_object_lookup(dev, file,
 							exec[i].handle));
-		if (obj == NULL) {
+		if (&obj->base == NULL) {
 			DRM_ERROR("Invalid object handle %d at index %d\n",
 				   exec[i].handle, i);
 			/* prevent error path from reading uninitialized data */
@@ -1170,11 +1134,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	if (ret)
 		goto err;
 
-	ret = i915_gem_execbuffer_wait_for_flips(ring, &objects);
-	if (ret)
-		goto err;
-
-	seqno = i915_gem_next_request_seqno(dev, ring);
+	seqno = i915_gem_next_request_seqno(ring);
 	for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++) {
 		if (seqno < ring->sync_seqno[i]) {
 			/* The GPU can not handle its semaphore value wrapping,
@@ -1189,6 +1149,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 		}
 	}
 
+	trace_i915_gem_ring_dispatch(ring, seqno);
+
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
 	exec_len = args->batch_len;
 	if (cliprects) {
@@ -1245,11 +1207,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 	int ret, i;
 
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-
 	if (args->buffer_count < 1) {
 		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
 		return -EINVAL;
@@ -1330,17 +1287,16 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 	int ret;
 
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-
 	if (args->buffer_count < 1) {
 		DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
 		return -EINVAL;
 	}
 
-	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+	exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count,
+			     GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+	if (exec2_list == NULL)
+		exec2_list = drm_malloc_ab(sizeof(*exec2_list),
+					   args->buffer_count);
 	if (exec2_list == NULL) {
 		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
 			  args->buffer_count);
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index d64843e..281ad3d 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -284,14 +284,10 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
 	struct drm_i915_gem_set_tiling *args = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
-	int ret;
-
-	ret = i915_gem_check_is_wedged(dev);
-	if (ret)
-		return ret;
+	int ret = 0;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL)
+	if (&obj->base == NULL)
 		return -ENOENT;
 
 	if (!i915_tiling_ok(dev,
@@ -384,7 +380,7 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
 	struct drm_i915_gem_object *obj;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL)
+	if (&obj->base == NULL)
 		return -ENOENT;
 
 	mutex_lock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8a9e08b..188b497 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -85,21 +85,11 @@ ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 	}
 }
 
-static inline u32
-i915_pipestat(int pipe)
-{
-	if (pipe == 0)
-		return PIPEASTAT;
-	if (pipe == 1)
-		return PIPEBSTAT;
-	BUG();
-}
-
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 {
 	if ((dev_priv->pipestat[pipe] & mask) != mask) {
-		u32 reg = i915_pipestat(pipe);
+		u32 reg = PIPESTAT(pipe);
 
 		dev_priv->pipestat[pipe] |= mask;
 		/* Enable the interrupt, clear any pending status */
@@ -112,7 +102,7 @@ void
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 {
 	if ((dev_priv->pipestat[pipe] & mask) != 0) {
-		u32 reg = i915_pipestat(pipe);
+		u32 reg = PIPESTAT(pipe);
 
 		dev_priv->pipestat[pipe] &= ~mask;
 		I915_WRITE(reg, dev_priv->pipestat[pipe]);
@@ -171,12 +161,12 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
-				"pipe %d\n", pipe);
+				"pipe %c\n", pipe_name(pipe));
 		return 0;
 	}
 
-	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
-	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+	high_frame = PIPEFRAME(pipe);
+	low_frame = PIPEFRAMEPIXEL(pipe);
 
 	/*
 	 * High & low register fields aren't synchronized, so make sure
@@ -197,11 +187,11 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
 u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
+	int reg = PIPE_FRMCOUNT_GM45(pipe);
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
-					"pipe %d\n", pipe);
+				 "pipe %c\n", pipe_name(pipe));
 		return 0;
 	}
 
@@ -219,7 +209,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
-					"pipe %d\n", pipe);
+				 "pipe %c\n", pipe_name(pipe));
 		return 0;
 	}
 
@@ -367,7 +357,7 @@ static void notify_ring(struct drm_device *dev,
 		return;
 
 	seqno = ring->get_seqno(ring);
-	trace_i915_gem_request_complete(dev, seqno);
+	trace_i915_gem_request_complete(ring, seqno);
 
 	ring->irq_seqno = seqno;
 	wake_up_all(&ring->irq_queue);
@@ -419,6 +409,7 @@ static void pch_irq_handler(struct drm_device *dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 pch_iir;
+	int pipe;
 
 	pch_iir = I915_READ(SDEIIR);
 
@@ -439,13 +430,11 @@ static void pch_irq_handler(struct drm_device *dev)
 	if (pch_iir & SDE_POISON)
 		DRM_ERROR("PCH poison interrupt\n");
 
-	if (pch_iir & SDE_FDI_MASK) {
-		u32 fdia, fdib;
-
-		fdia = I915_READ(FDI_RXA_IIR);
-		fdib = I915_READ(FDI_RXB_IIR);
-		DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib);
-	}
+	if (pch_iir & SDE_FDI_MASK)
+		for_each_pipe(pipe)
+			DRM_DEBUG_DRIVER("  pipe %c FDI IIR: 0x%08x\n",
+					 pipe_name(pipe),
+					 I915_READ(FDI_RX_IIR(pipe)));
 
 	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
 		DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n");
@@ -650,9 +639,14 @@ static void
 i915_error_state_free(struct drm_device *dev,
 		      struct drm_i915_error_state *error)
 {
-	i915_error_object_free(error->batchbuffer[0]);
-	i915_error_object_free(error->batchbuffer[1]);
-	i915_error_object_free(error->ringbuffer);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++)
+		i915_error_object_free(error->batchbuffer[i]);
+
+	for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++)
+		i915_error_object_free(error->ringbuffer[i]);
+
 	kfree(error->active_bo);
 	kfree(error->overlay);
 	kfree(error);
@@ -767,7 +761,7 @@ static void i915_capture_error_state(struct drm_device *dev)
 	struct drm_i915_gem_object *obj;
 	struct drm_i915_error_state *error;
 	unsigned long flags;
-	int i;
+	int i, pipe;
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
 	error = dev_priv->first_error;
@@ -775,19 +769,21 @@ static void i915_capture_error_state(struct drm_device *dev)
 	if (error)
 		return;
 
+	/* Account for pipe specific data like PIPE*STAT */
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
 	if (!error) {
 		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
 		return;
 	}
 
-	DRM_DEBUG_DRIVER("generating error event\n");
+	DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n",
+		 dev->primary->index);
 
 	error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]);
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
-	error->pipeastat = I915_READ(PIPEASTAT);
-	error->pipebstat = I915_READ(PIPEBSTAT);
+	for_each_pipe(pipe)
+		error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 	error->instpm = I915_READ(INSTPM);
 	error->error = 0;
 	if (INTEL_INFO(dev)->gen >= 6) {
@@ -826,15 +822,16 @@ static void i915_capture_error_state(struct drm_device *dev)
 	}
 	i915_gem_record_fences(dev, error);
 
-	/* Record the active batchbuffers */
-	for (i = 0; i < I915_NUM_RINGS; i++)
+	/* Record the active batch and ring buffers */
+	for (i = 0; i < I915_NUM_RINGS; i++) {
 		error->batchbuffer[i] =
 			i915_error_first_batchbuffer(dev_priv,
 						     &dev_priv->ring[i]);
 
-	/* Record the ringbuffer */
-	error->ringbuffer = i915_error_object_create(dev_priv,
-						     dev_priv->ring[RCS].obj);
+		error->ringbuffer[i] =
+			i915_error_object_create(dev_priv,
+						 dev_priv->ring[i].obj);
+	}
 
 	/* Record buffers on the active and pinned lists. */
 	error->active_bo = NULL;
@@ -907,6 +904,7 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 eir = I915_READ(EIR);
+	int pipe;
 
 	if (!eir)
 		return;
@@ -955,14 +953,10 @@ static void i915_report_and_clear_eir(struct drm_device *dev)
 	}
 
 	if (eir & I915_ERROR_MEMORY_REFRESH) {
-		u32 pipea_stats = I915_READ(PIPEASTAT);
-		u32 pipeb_stats = I915_READ(PIPEBSTAT);
-
-		printk(KERN_ERR "memory refresh error\n");
-		printk(KERN_ERR "PIPEASTAT: 0x%08x\n",
-		       pipea_stats);
-		printk(KERN_ERR "PIPEBSTAT: 0x%08x\n",
-		       pipeb_stats);
+		printk(KERN_ERR "memory refresh error:\n");
+		for_each_pipe(pipe)
+			printk(KERN_ERR "pipe %c stat: 0x%08x\n",
+			       pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
 		/* pipestat has already been acked */
 	}
 	if (eir & I915_ERROR_INSTRUCTION) {
@@ -1076,10 +1070,10 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)
 	/* Potential stall - if we see that the flip has happened, assume a missed interrupt */
 	obj = work->pending_flip_obj;
 	if (INTEL_INFO(dev)->gen >= 4) {
-		int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
+		int dspsurf = DSPSURF(intel_crtc->plane);
 		stall_detected = I915_READ(dspsurf) == obj->gtt_offset;
 	} else {
-		int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR;
+		int dspaddr = DSPADDR(intel_crtc->plane);
 		stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
 							crtc->y * crtc->fb->pitch +
 							crtc->x * crtc->fb->bits_per_pixel/8);
@@ -1099,12 +1093,13 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	u32 iir, new_iir;
-	u32 pipea_stats, pipeb_stats;
+	u32 pipe_stats[I915_MAX_PIPES];
 	u32 vblank_status;
 	int vblank = 0;
 	unsigned long irqflags;
 	int irq_received;
-	int ret = IRQ_NONE;
+	int ret = IRQ_NONE, pipe;
+	bool blc_event = false;
 
 	atomic_inc(&dev_priv->irq_received);
 
@@ -1127,27 +1122,23 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 		 * interrupts (for non-MSI).
 		 */
 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-		pipea_stats = I915_READ(PIPEASTAT);
-		pipeb_stats = I915_READ(PIPEBSTAT);
-
 		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 			i915_handle_error(dev, false);
 
-		/*
-		 * Clear the PIPE(A|B)STAT regs before the IIR
-		 */
-		if (pipea_stats & 0x8000ffff) {
-			if (pipea_stats &  PIPE_FIFO_UNDERRUN_STATUS)
-				DRM_DEBUG_DRIVER("pipe a underrun\n");
-			I915_WRITE(PIPEASTAT, pipea_stats);
-			irq_received = 1;
-		}
-
-		if (pipeb_stats & 0x8000ffff) {
-			if (pipeb_stats &  PIPE_FIFO_UNDERRUN_STATUS)
-				DRM_DEBUG_DRIVER("pipe b underrun\n");
-			I915_WRITE(PIPEBSTAT, pipeb_stats);
-			irq_received = 1;
+		for_each_pipe(pipe) {
+			int reg = PIPESTAT(pipe);
+			pipe_stats[pipe] = I915_READ(reg);
+
+			/*
+			 * Clear the PIPE*STAT regs before the IIR
+			 */
+			if (pipe_stats[pipe] & 0x8000ffff) {
+				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+					DRM_DEBUG_DRIVER("pipe %c underrun\n",
+							 pipe_name(pipe));
+				I915_WRITE(reg, pipe_stats[pipe]);
+				irq_received = 1;
+			}
 		}
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -1198,27 +1189,22 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 				intel_finish_page_flip_plane(dev, 1);
 		}
 
-		if (pipea_stats & vblank_status &&
-		    drm_handle_vblank(dev, 0)) {
-			vblank++;
-			if (!dev_priv->flip_pending_is_done) {
-				i915_pageflip_stall_check(dev, 0);
-				intel_finish_page_flip(dev, 0);
+		for_each_pipe(pipe) {
+			if (pipe_stats[pipe] & vblank_status &&
+			    drm_handle_vblank(dev, pipe)) {
+				vblank++;
+				if (!dev_priv->flip_pending_is_done) {
+					i915_pageflip_stall_check(dev, pipe);
+					intel_finish_page_flip(dev, pipe);
+				}
 			}
-		}
 
-		if (pipeb_stats & vblank_status &&
-		    drm_handle_vblank(dev, 1)) {
-			vblank++;
-			if (!dev_priv->flip_pending_is_done) {
-				i915_pageflip_stall_check(dev, 1);
-				intel_finish_page_flip(dev, 1);
-			}
+			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+				blc_event = true;
 		}
 
-		if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
-		    (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
-		    (iir & I915_ASLE_INTERRUPT))
+
+		if (blc_event || (iir & I915_ASLE_INTERRUPT))
 			intel_opregion_asle_intr(dev);
 
 		/* With MSI, interrupts are only generated when iir
@@ -1268,16 +1254,6 @@ static int i915_emit_irq(struct drm_device * dev)
 	return dev_priv->counter;
 }
 
-void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	struct intel_ring_buffer *ring = LP_RING(dev_priv);
-
-	if (dev_priv->trace_irq_seqno == 0 &&
-	    ring->irq_get(ring))
-		dev_priv->trace_irq_seqno = seqno;
-}
-
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1377,7 +1353,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
 	else
 		i915_enable_pipestat(dev_priv, pipe,
 				     PIPE_VBLANK_INTERRUPT_ENABLE);
+
+	/* maintain vblank delivery even in deep C-states */
+	if (dev_priv->info->gen == 3)
+		I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
 	return 0;
 }
 
@@ -1390,6 +1371,10 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	if (dev_priv->info->gen == 3)
+		I915_WRITE(INSTPM,
+			   INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS);
+
 	if (HAS_PCH_SPLIT(dev))
 		ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
 					     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
@@ -1400,16 +1385,6 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-void i915_enable_interrupt (struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (!HAS_PCH_SPLIT(dev))
-		intel_opregion_enable_asle(dev);
-	dev_priv->irq_enabled = 1;
-}
-
-
 /* Set the vblank monitor pipe
  */
 int i915_vblank_pipe_set(struct drm_device *dev, void *data,
@@ -1646,12 +1621,16 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 	POSTING_READ(GTIER);
 
 	if (HAS_PCH_CPT(dev)) {
-		hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT  |
-			       SDE_PORTC_HOTPLUG_CPT | SDE_PORTD_HOTPLUG_CPT ;
+		hotplug_mask = (SDE_CRT_HOTPLUG_CPT |
+				SDE_PORTB_HOTPLUG_CPT |
+				SDE_PORTC_HOTPLUG_CPT |
+				SDE_PORTD_HOTPLUG_CPT);
 	} else {
-		hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
-			       SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
-		hotplug_mask |= SDE_AUX_MASK;
+		hotplug_mask = (SDE_CRT_HOTPLUG |
+				SDE_PORTB_HOTPLUG |
+				SDE_PORTC_HOTPLUG |
+				SDE_PORTD_HOTPLUG |
+				SDE_AUX_MASK);
 	}
 
 	dev_priv->pch_irq_mask = ~hotplug_mask;
@@ -1674,6 +1653,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
 void i915_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
 
 	atomic_set(&dev_priv->irq_received, 0);
 
@@ -1691,8 +1671,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
 	}
 
 	I915_WRITE(HWSTAM, 0xeffe);
-	I915_WRITE(PIPEASTAT, 0);
-	I915_WRITE(PIPEBSTAT, 0);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 	POSTING_READ(IER);
@@ -1804,6 +1784,7 @@ static void ironlake_irq_uninstall(struct drm_device *dev)
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
 
 	if (!dev_priv)
 		return;
@@ -1821,12 +1802,13 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
 	}
 
 	I915_WRITE(HWSTAM, 0xffffffff);
-	I915_WRITE(PIPEASTAT, 0);
-	I915_WRITE(PIPEBSTAT, 0);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 
-	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
-	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe),
+			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
 	I915_WRITE(IIR, I915_READ(IIR));
 }
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 2abe240..f39ac3a 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -405,9 +405,12 @@
 #define   I915_ERROR_INSTRUCTION			(1<<0)
 #define INSTPM	        0x020c0
 #define   INSTPM_SELF_EN (1<<12) /* 915GM only */
+#define   INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts
+					will not assert AGPBUSY# and will only
+					be delivered when out of C3. */
 #define ACTHD	        0x020c8
 #define FW_BLC		0x020d8
-#define FW_BLC2	 	0x020dc
+#define FW_BLC2		0x020dc
 #define FW_BLC_SELF	0x020e0 /* 915+ only */
 #define   FW_BLC_SELF_EN_MASK      (1<<31)
 #define   FW_BLC_SELF_FIFO_MASK    (1<<16) /* 945 only */
@@ -706,9 +709,9 @@
 #define   VGA1_PD_P1_DIV_2	(1 << 13)
 #define   VGA1_PD_P1_SHIFT	8
 #define   VGA1_PD_P1_MASK	(0x1f << 8)
-#define DPLL_A	0x06014
-#define DPLL_B	0x06018
-#define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B)
+#define _DPLL_A	0x06014
+#define _DPLL_B	0x06018
+#define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B)
 #define   DPLL_VCO_ENABLE		(1 << 31)
 #define   DPLL_DVO_HIGH_SPEED		(1 << 30)
 #define   DPLL_SYNCLOCK_ENABLE		(1 << 29)
@@ -779,7 +782,7 @@
 #define   SDVO_MULTIPLIER_MASK			0x000000ff
 #define   SDVO_MULTIPLIER_SHIFT_HIRES		4
 #define   SDVO_MULTIPLIER_SHIFT_VGA		0
-#define DPLL_A_MD 0x0601c /* 965+ only */
+#define _DPLL_A_MD 0x0601c /* 965+ only */
 /*
  * UDI pixel divider, controlling how many pixels are stuffed into a packet.
  *
@@ -816,14 +819,14 @@
  */
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
-#define DPLL_B_MD 0x06020 /* 965+ only */
-#define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD)
-#define FPA0	0x06040
-#define FPA1	0x06044
-#define FPB0	0x06048
-#define FPB1	0x0604c
-#define FP0(pipe) _PIPE(pipe, FPA0, FPB0)
-#define FP1(pipe) _PIPE(pipe, FPA1, FPB1)
+#define _DPLL_B_MD 0x06020 /* 965+ only */
+#define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD)
+#define _FPA0	0x06040
+#define _FPA1	0x06044
+#define _FPB0	0x06048
+#define _FPB1	0x0604c
+#define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0)
+#define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1)
 #define   FP_N_DIV_MASK		0x003f0000
 #define   FP_N_PINEVIEW_DIV_MASK	0x00ff0000
 #define   FP_N_DIV_SHIFT		16
@@ -962,8 +965,9 @@
  * Palette regs
  */
 
-#define PALETTE_A		0x0a000
-#define PALETTE_B		0x0a800
+#define _PALETTE_A		0x0a000
+#define _PALETTE_B		0x0a800
+#define PALETTE(pipe) _PIPE(pipe, _PALETTE_A, _PALETTE_B)
 
 /* MCH MMIO space */
 
@@ -1267,32 +1271,32 @@
  */
 
 /* Pipe A timing regs */
-#define HTOTAL_A	0x60000
-#define HBLANK_A	0x60004
-#define HSYNC_A		0x60008
-#define VTOTAL_A	0x6000c
-#define VBLANK_A	0x60010
-#define VSYNC_A		0x60014
-#define PIPEASRC	0x6001c
-#define BCLRPAT_A	0x60020
+#define _HTOTAL_A	0x60000
+#define _HBLANK_A	0x60004
+#define _HSYNC_A		0x60008
+#define _VTOTAL_A	0x6000c
+#define _VBLANK_A	0x60010
+#define _VSYNC_A		0x60014
+#define _PIPEASRC	0x6001c
+#define _BCLRPAT_A	0x60020
 
 /* Pipe B timing regs */
-#define HTOTAL_B	0x61000
-#define HBLANK_B	0x61004
-#define HSYNC_B		0x61008
-#define VTOTAL_B	0x6100c
-#define VBLANK_B	0x61010
-#define VSYNC_B		0x61014
-#define PIPEBSRC	0x6101c
-#define BCLRPAT_B	0x61020
-
-#define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B)
-#define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B)
-#define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B)
-#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
-#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
-#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
-#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
+#define _HTOTAL_B	0x61000
+#define _HBLANK_B	0x61004
+#define _HSYNC_B		0x61008
+#define _VTOTAL_B	0x6100c
+#define _VBLANK_B	0x61010
+#define _VSYNC_B		0x61014
+#define _PIPEBSRC	0x6101c
+#define _BCLRPAT_B	0x61020
+
+#define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
+#define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
+#define HSYNC(pipe) _PIPE(pipe, _HSYNC_A, _HSYNC_B)
+#define VTOTAL(pipe) _PIPE(pipe, _VTOTAL_A, _VTOTAL_B)
+#define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
+#define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
+#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
 
 /* VGA port control */
 #define ADPA			0x61100
@@ -1386,6 +1390,7 @@
 #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 */
@@ -1441,8 +1446,13 @@
 #define   LVDS_PORT_EN			(1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
 #define   LVDS_PIPEB_SELECT		(1 << 30)
+#define   LVDS_PIPE_MASK		(1 << 30)
 /* LVDS dithering flag on 965/g4x platform */
 #define   LVDS_ENABLE_DITHER		(1 << 25)
+/* LVDS sync polarity flags. Set to invert (i.e. negative) */
+#define   LVDS_VSYNC_POLARITY		(1 << 21)
+#define   LVDS_HSYNC_POLARITY		(1 << 20)
+
 /* Enable border for unscaled (or aspect-scaled) display */
 #define   LVDS_BORDER_ENABLE		(1 << 15)
 /*
@@ -1476,6 +1486,9 @@
 #define   LVDS_B0B3_POWER_DOWN		(0 << 2)
 #define   LVDS_B0B3_POWER_UP		(3 << 2)
 
+#define LVDS_PIPE_ENABLED(V, P) \
+	(((V) & (LVDS_PIPE_MASK | LVDS_PORT_EN)) == ((P) << 30 | LVDS_PORT_EN))
+
 /* Video Data Island Packet control */
 #define VIDEO_DIP_DATA		0x61178
 #define VIDEO_DIP_CTL		0x61170
@@ -2064,6 +2077,10 @@
 
 #define   DP_PORT_EN			(1 << 31)
 #define   DP_PIPEB_SELECT		(1 << 30)
+#define   DP_PIPE_MASK			(1 << 30)
+
+#define DP_PIPE_ENABLED(V, P) \
+	(((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN))
 
 /* Link training mode - select a suitable mode for each stage */
 #define   DP_LINK_TRAIN_PAT_1		(0 << 28)
@@ -2206,8 +2223,8 @@
  * which is after the LUTs, so we want the bytes for our color format.
  * For our current usage, this is always 3, one byte for R, G and B.
  */
-#define PIPEA_GMCH_DATA_M			0x70050
-#define PIPEB_GMCH_DATA_M			0x71050
+#define _PIPEA_GMCH_DATA_M			0x70050
+#define _PIPEB_GMCH_DATA_M			0x71050
 
 /* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */
 #define   PIPE_GMCH_DATA_M_TU_SIZE_MASK		(0x3f << 25)
@@ -2215,8 +2232,8 @@
 
 #define   PIPE_GMCH_DATA_M_MASK			(0xffffff)
 
-#define PIPEA_GMCH_DATA_N			0x70054
-#define PIPEB_GMCH_DATA_N			0x71054
+#define _PIPEA_GMCH_DATA_N			0x70054
+#define _PIPEB_GMCH_DATA_N			0x71054
 #define   PIPE_GMCH_DATA_N_MASK			(0xffffff)
 
 /*
@@ -2230,20 +2247,25 @@
  * Attributes and VB-ID.
  */
 
-#define PIPEA_DP_LINK_M				0x70060
-#define PIPEB_DP_LINK_M				0x71060
+#define _PIPEA_DP_LINK_M				0x70060
+#define _PIPEB_DP_LINK_M				0x71060
 #define   PIPEA_DP_LINK_M_MASK			(0xffffff)
 
-#define PIPEA_DP_LINK_N				0x70064
-#define PIPEB_DP_LINK_N				0x71064
+#define _PIPEA_DP_LINK_N				0x70064
+#define _PIPEB_DP_LINK_N				0x71064
 #define   PIPEA_DP_LINK_N_MASK			(0xffffff)
 
+#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M)
+#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N)
+#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M)
+#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N)
+
 /* Display & cursor control */
 
 /* Pipe A */
-#define PIPEADSL		0x70000
+#define _PIPEADSL		0x70000
 #define   DSL_LINEMASK		0x00000fff
-#define PIPEACONF		0x70008
+#define _PIPEACONF		0x70008
 #define   PIPECONF_ENABLE	(1<<31)
 #define   PIPECONF_DISABLE	0
 #define   PIPECONF_DOUBLE_WIDE	(1<<30)
@@ -2269,7 +2291,7 @@
 #define   PIPECONF_DITHER_TYPE_ST1 (1<<2)
 #define   PIPECONF_DITHER_TYPE_ST2 (2<<2)
 #define   PIPECONF_DITHER_TYPE_TEMP (3<<2)
-#define PIPEASTAT		0x70024
+#define _PIPEASTAT		0x70024
 #define   PIPE_FIFO_UNDERRUN_STATUS		(1UL<<31)
 #define   PIPE_CRC_ERROR_ENABLE			(1UL<<29)
 #define   PIPE_CRC_DONE_ENABLE			(1UL<<28)
@@ -2305,10 +2327,12 @@
 #define   PIPE_6BPC				(2 << 5)
 #define   PIPE_12BPC				(3 << 5)
 
-#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
-#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
-#define PIPEDSL(pipe)  _PIPE(pipe, PIPEADSL, PIPEBDSL)
-#define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, PIPEAFRAMEPIXEL, PIPEBFRAMEPIXEL)
+#define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)
+#define PIPECONF(pipe) _PIPE(pipe, _PIPEACONF, _PIPEBCONF)
+#define PIPEDSL(pipe)  _PIPE(pipe, _PIPEADSL, _PIPEBDSL)
+#define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH)
+#define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)
+#define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT)
 
 #define DSPARB			0x70030
 #define   DSPARB_CSTART_MASK	(0x7f << 7)
@@ -2470,20 +2494,21 @@
  *  } while (high1 != high2);
  *  frame = (high1 << 8) | low1;
  */
-#define PIPEAFRAMEHIGH          0x70040
+#define _PIPEAFRAMEHIGH          0x70040
 #define   PIPE_FRAME_HIGH_MASK    0x0000ffff
 #define   PIPE_FRAME_HIGH_SHIFT   0
-#define PIPEAFRAMEPIXEL         0x70044
+#define _PIPEAFRAMEPIXEL         0x70044
 #define   PIPE_FRAME_LOW_MASK     0xff000000
 #define   PIPE_FRAME_LOW_SHIFT    24
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_SHIFT        0
 /* GM45+ just has to be different */
-#define PIPEA_FRMCOUNT_GM45	0x70040
-#define PIPEA_FLIPCOUNT_GM45	0x70044
+#define _PIPEA_FRMCOUNT_GM45	0x70040
+#define _PIPEA_FLIPCOUNT_GM45	0x70044
+#define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45)
 
 /* Cursor A & B regs */
-#define CURACNTR		0x70080
+#define _CURACNTR		0x70080
 /* Old style CUR*CNTR flags (desktop 8xx) */
 #define   CURSOR_ENABLE		0x80000000
 #define   CURSOR_GAMMA_ENABLE	0x40000000
@@ -2504,23 +2529,23 @@
 #define   MCURSOR_PIPE_A	0x00
 #define   MCURSOR_PIPE_B	(1 << 28)
 #define   MCURSOR_GAMMA_ENABLE  (1 << 26)
-#define CURABASE		0x70084
-#define CURAPOS			0x70088
+#define _CURABASE		0x70084
+#define _CURAPOS			0x70088
 #define   CURSOR_POS_MASK       0x007FF
 #define   CURSOR_POS_SIGN       0x8000
 #define   CURSOR_X_SHIFT        0
 #define   CURSOR_Y_SHIFT        16
 #define CURSIZE			0x700a0
-#define CURBCNTR		0x700c0
-#define CURBBASE		0x700c4
-#define CURBPOS			0x700c8
+#define _CURBCNTR		0x700c0
+#define _CURBBASE		0x700c4
+#define _CURBPOS			0x700c8
 
-#define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR)
-#define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE)
-#define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS)
+#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
+#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
+#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
 
 /* Display A control */
-#define DSPACNTR                0x70180
+#define _DSPACNTR                0x70180
 #define   DISPLAY_PLANE_ENABLE			(1<<31)
 #define   DISPLAY_PLANE_DISABLE			0
 #define   DISPPLANE_GAMMA_ENABLE		(1<<30)
@@ -2534,9 +2559,10 @@
 #define   DISPPLANE_32BPP_30BIT_NO_ALPHA	(0xa<<26)
 #define   DISPPLANE_STEREO_ENABLE		(1<<25)
 #define   DISPPLANE_STEREO_DISABLE		0
-#define   DISPPLANE_SEL_PIPE_MASK		(1<<24)
+#define   DISPPLANE_SEL_PIPE_SHIFT		24
+#define   DISPPLANE_SEL_PIPE_MASK		(3<<DISPPLANE_SEL_PIPE_SHIFT)
 #define   DISPPLANE_SEL_PIPE_A			0
-#define   DISPPLANE_SEL_PIPE_B			(1<<24)
+#define   DISPPLANE_SEL_PIPE_B			(1<<DISPPLANE_SEL_PIPE_SHIFT)
 #define   DISPPLANE_SRC_KEY_ENABLE		(1<<22)
 #define   DISPPLANE_SRC_KEY_DISABLE		0
 #define   DISPPLANE_LINE_DOUBLE			(1<<20)
@@ -2545,20 +2571,20 @@
 #define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
 #define   DISPPLANE_TRICKLE_FEED_DISABLE	(1<<14) /* Ironlake */
 #define   DISPPLANE_TILED			(1<<10)
-#define DSPAADDR		0x70184
-#define DSPASTRIDE		0x70188
-#define DSPAPOS			0x7018C /* reserved */
-#define DSPASIZE		0x70190
-#define DSPASURF		0x7019C /* 965+ only */
-#define DSPATILEOFF		0x701A4 /* 965+ only */
-
-#define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR)
-#define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR)
-#define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE)
-#define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS)
-#define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE)
-#define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF)
-#define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF)
+#define _DSPAADDR		0x70184
+#define _DSPASTRIDE		0x70188
+#define _DSPAPOS			0x7018C /* reserved */
+#define _DSPASIZE		0x70190
+#define _DSPASURF		0x7019C /* 965+ only */
+#define _DSPATILEOFF		0x701A4 /* 965+ only */
+
+#define DSPCNTR(plane) _PIPE(plane, _DSPACNTR, _DSPBCNTR)
+#define DSPADDR(plane) _PIPE(plane, _DSPAADDR, _DSPBADDR)
+#define DSPSTRIDE(plane) _PIPE(plane, _DSPASTRIDE, _DSPBSTRIDE)
+#define DSPPOS(plane) _PIPE(plane, _DSPAPOS, _DSPBPOS)
+#define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE)
+#define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF)
+#define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF)
 
 /* VBIOS flags */
 #define SWF00			0x71410
@@ -2576,27 +2602,27 @@
 #define SWF32			0x7241c
 
 /* Pipe B */
-#define PIPEBDSL		0x71000
-#define PIPEBCONF		0x71008
-#define PIPEBSTAT		0x71024
-#define PIPEBFRAMEHIGH		0x71040
-#define PIPEBFRAMEPIXEL		0x71044
-#define PIPEB_FRMCOUNT_GM45	0x71040
-#define PIPEB_FLIPCOUNT_GM45	0x71044
+#define _PIPEBDSL		0x71000
+#define _PIPEBCONF		0x71008
+#define _PIPEBSTAT		0x71024
+#define _PIPEBFRAMEHIGH		0x71040
+#define _PIPEBFRAMEPIXEL		0x71044
+#define _PIPEB_FRMCOUNT_GM45	0x71040
+#define _PIPEB_FLIPCOUNT_GM45	0x71044
 
 
 /* Display B control */
-#define DSPBCNTR		0x71180
+#define _DSPBCNTR		0x71180
 #define   DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
 #define   DISPPLANE_ALPHA_TRANS_DISABLE		0
 #define   DISPPLANE_SPRITE_ABOVE_DISPLAY	0
 #define   DISPPLANE_SPRITE_ABOVE_OVERLAY	(1)
-#define DSPBADDR		0x71184
-#define DSPBSTRIDE		0x71188
-#define DSPBPOS			0x7118C
-#define DSPBSIZE		0x71190
-#define DSPBSURF		0x7119C
-#define DSPBTILEOFF		0x711A4
+#define _DSPBADDR		0x71184
+#define _DSPBSTRIDE		0x71188
+#define _DSPBPOS			0x7118C
+#define _DSPBSIZE		0x71190
+#define _DSPBSURF		0x7119C
+#define _DSPBTILEOFF		0x711A4
 
 /* VBIOS regs */
 #define VGACNTRL		0x71400
@@ -2650,68 +2676,80 @@
 #define  FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK  0xff
 
 
-#define PIPEA_DATA_M1           0x60030
+#define _PIPEA_DATA_M1           0x60030
 #define  TU_SIZE(x)             (((x)-1) << 25) /* default size 64 */
 #define  TU_SIZE_MASK           0x7e000000
 #define  PIPE_DATA_M1_OFFSET    0
-#define PIPEA_DATA_N1           0x60034
+#define _PIPEA_DATA_N1           0x60034
 #define  PIPE_DATA_N1_OFFSET    0
 
-#define PIPEA_DATA_M2           0x60038
+#define _PIPEA_DATA_M2           0x60038
 #define  PIPE_DATA_M2_OFFSET    0
-#define PIPEA_DATA_N2           0x6003c
+#define _PIPEA_DATA_N2           0x6003c
 #define  PIPE_DATA_N2_OFFSET    0
 
-#define PIPEA_LINK_M1           0x60040
+#define _PIPEA_LINK_M1           0x60040
 #define  PIPE_LINK_M1_OFFSET    0
-#define PIPEA_LINK_N1           0x60044
+#define _PIPEA_LINK_N1           0x60044
 #define  PIPE_LINK_N1_OFFSET    0
 
-#define PIPEA_LINK_M2           0x60048
+#define _PIPEA_LINK_M2           0x60048
 #define  PIPE_LINK_M2_OFFSET    0
-#define PIPEA_LINK_N2           0x6004c
+#define _PIPEA_LINK_N2           0x6004c
 #define  PIPE_LINK_N2_OFFSET    0
 
 /* PIPEB timing regs are same start from 0x61000 */
 
-#define PIPEB_DATA_M1           0x61030
-#define PIPEB_DATA_N1           0x61034
+#define _PIPEB_DATA_M1           0x61030
+#define _PIPEB_DATA_N1           0x61034
 
-#define PIPEB_DATA_M2           0x61038
-#define PIPEB_DATA_N2           0x6103c
+#define _PIPEB_DATA_M2           0x61038
+#define _PIPEB_DATA_N2           0x6103c
 
-#define PIPEB_LINK_M1           0x61040
-#define PIPEB_LINK_N1           0x61044
+#define _PIPEB_LINK_M1           0x61040
+#define _PIPEB_LINK_N1           0x61044
 
-#define PIPEB_LINK_M2           0x61048
-#define PIPEB_LINK_N2           0x6104c
+#define _PIPEB_LINK_M2           0x61048
+#define _PIPEB_LINK_N2           0x6104c
 
-#define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1)
-#define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1)
-#define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2)
-#define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2)
-#define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1)
-#define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1)
-#define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2)
-#define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2)
+#define PIPE_DATA_M1(pipe) _PIPE(pipe, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
+#define PIPE_DATA_N1(pipe) _PIPE(pipe, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
+#define PIPE_DATA_M2(pipe) _PIPE(pipe, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
+#define PIPE_DATA_N2(pipe) _PIPE(pipe, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
+#define PIPE_LINK_M1(pipe) _PIPE(pipe, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
+#define PIPE_LINK_N1(pipe) _PIPE(pipe, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
+#define PIPE_LINK_M2(pipe) _PIPE(pipe, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
+#define PIPE_LINK_N2(pipe) _PIPE(pipe, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
 
 /* CPU panel fitter */
-#define PFA_CTL_1               0x68080
-#define PFB_CTL_1               0x68880
+/* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
+#define _PFA_CTL_1               0x68080
+#define _PFB_CTL_1               0x68880
 #define  PF_ENABLE              (1<<31)
 #define  PF_FILTER_MASK		(3<<23)
 #define  PF_FILTER_PROGRAMMED	(0<<23)
 #define  PF_FILTER_MED_3x3	(1<<23)
 #define  PF_FILTER_EDGE_ENHANCE	(2<<23)
 #define  PF_FILTER_EDGE_SOFTEN	(3<<23)
-#define PFA_WIN_SZ		0x68074
-#define PFB_WIN_SZ		0x68874
-#define PFA_WIN_POS		0x68070
-#define PFB_WIN_POS		0x68870
+#define _PFA_WIN_SZ		0x68074
+#define _PFB_WIN_SZ		0x68874
+#define _PFA_WIN_POS		0x68070
+#define _PFB_WIN_POS		0x68870
+#define _PFA_VSCALE		0x68084
+#define _PFB_VSCALE		0x68884
+#define _PFA_HSCALE		0x68090
+#define _PFB_HSCALE		0x68890
+
+#define PF_CTL(pipe)		_PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1)
+#define PF_WIN_SZ(pipe)		_PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ)
+#define PF_WIN_POS(pipe)	_PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS)
+#define PF_VSCALE(pipe)		_PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE)
+#define PF_HSCALE(pipe)		_PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE)
 
 /* legacy palette */
-#define LGC_PALETTE_A           0x4a000
-#define LGC_PALETTE_B           0x4a800
+#define _LGC_PALETTE_A           0x4a000
+#define _LGC_PALETTE_B           0x4a800
+#define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
 
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
@@ -2877,17 +2915,17 @@
 #define PCH_GMBUS4		0xc5110
 #define PCH_GMBUS5		0xc5120
 
-#define PCH_DPLL_A              0xc6014
-#define PCH_DPLL_B              0xc6018
-#define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B)
+#define _PCH_DPLL_A              0xc6014
+#define _PCH_DPLL_B              0xc6018
+#define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B)
 
-#define PCH_FPA0                0xc6040
+#define _PCH_FPA0                0xc6040
 #define  FP_CB_TUNE		(0x3<<22)
-#define PCH_FPA1                0xc6044
-#define PCH_FPB0                0xc6048
-#define PCH_FPB1                0xc604c
-#define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0)
-#define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1)
+#define _PCH_FPA1                0xc6044
+#define _PCH_FPB0                0xc6048
+#define _PCH_FPB1                0xc604c
+#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0)
+#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1)
 
 #define PCH_DPLL_TEST           0xc606c
 
@@ -2906,6 +2944,7 @@
 #define  DREF_NONSPREAD_SOURCE_MASK		(3<<9)
 #define  DREF_SUPERSPREAD_SOURCE_DISABLE        (0<<7)
 #define  DREF_SUPERSPREAD_SOURCE_ENABLE         (2<<7)
+#define  DREF_SUPERSPREAD_SOURCE_MASK		(3<<7)
 #define  DREF_SSC4_DOWNSPREAD                   (0<<6)
 #define  DREF_SSC4_CENTERSPREAD                 (1<<6)
 #define  DREF_SSC1_DISABLE                      (0<<1)
@@ -2938,60 +2977,69 @@
 
 /* transcoder */
 
-#define TRANS_HTOTAL_A          0xe0000
+#define _TRANS_HTOTAL_A          0xe0000
 #define  TRANS_HTOTAL_SHIFT     16
 #define  TRANS_HACTIVE_SHIFT    0
-#define TRANS_HBLANK_A          0xe0004
+#define _TRANS_HBLANK_A          0xe0004
 #define  TRANS_HBLANK_END_SHIFT 16
 #define  TRANS_HBLANK_START_SHIFT 0
-#define TRANS_HSYNC_A           0xe0008
+#define _TRANS_HSYNC_A           0xe0008
 #define  TRANS_HSYNC_END_SHIFT  16
 #define  TRANS_HSYNC_START_SHIFT 0
-#define TRANS_VTOTAL_A          0xe000c
+#define _TRANS_VTOTAL_A          0xe000c
 #define  TRANS_VTOTAL_SHIFT     16
 #define  TRANS_VACTIVE_SHIFT    0
-#define TRANS_VBLANK_A          0xe0010
+#define _TRANS_VBLANK_A          0xe0010
 #define  TRANS_VBLANK_END_SHIFT 16
 #define  TRANS_VBLANK_START_SHIFT 0
-#define TRANS_VSYNC_A           0xe0014
+#define _TRANS_VSYNC_A           0xe0014
 #define  TRANS_VSYNC_END_SHIFT  16
 #define  TRANS_VSYNC_START_SHIFT 0
 
-#define TRANSA_DATA_M1          0xe0030
-#define TRANSA_DATA_N1          0xe0034
-#define TRANSA_DATA_M2          0xe0038
-#define TRANSA_DATA_N2          0xe003c
-#define TRANSA_DP_LINK_M1       0xe0040
-#define TRANSA_DP_LINK_N1       0xe0044
-#define TRANSA_DP_LINK_M2       0xe0048
-#define TRANSA_DP_LINK_N2       0xe004c
-
-#define TRANS_HTOTAL_B          0xe1000
-#define TRANS_HBLANK_B          0xe1004
-#define TRANS_HSYNC_B           0xe1008
-#define TRANS_VTOTAL_B          0xe100c
-#define TRANS_VBLANK_B          0xe1010
-#define TRANS_VSYNC_B           0xe1014
-
-#define TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B)
-#define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B)
-#define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B)
-#define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B)
-#define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B)
-#define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B)
-
-#define TRANSB_DATA_M1          0xe1030
-#define TRANSB_DATA_N1          0xe1034
-#define TRANSB_DATA_M2          0xe1038
-#define TRANSB_DATA_N2          0xe103c
-#define TRANSB_DP_LINK_M1       0xe1040
-#define TRANSB_DP_LINK_N1       0xe1044
-#define TRANSB_DP_LINK_M2       0xe1048
-#define TRANSB_DP_LINK_N2       0xe104c
-
-#define TRANSACONF              0xf0008
-#define TRANSBCONF              0xf1008
-#define TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF)
+#define _TRANSA_DATA_M1          0xe0030
+#define _TRANSA_DATA_N1          0xe0034
+#define _TRANSA_DATA_M2          0xe0038
+#define _TRANSA_DATA_N2          0xe003c
+#define _TRANSA_DP_LINK_M1       0xe0040
+#define _TRANSA_DP_LINK_N1       0xe0044
+#define _TRANSA_DP_LINK_M2       0xe0048
+#define _TRANSA_DP_LINK_N2       0xe004c
+
+#define _TRANS_HTOTAL_B          0xe1000
+#define _TRANS_HBLANK_B          0xe1004
+#define _TRANS_HSYNC_B           0xe1008
+#define _TRANS_VTOTAL_B          0xe100c
+#define _TRANS_VBLANK_B          0xe1010
+#define _TRANS_VSYNC_B           0xe1014
+
+#define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B)
+#define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B)
+#define TRANS_HSYNC(pipe) _PIPE(pipe, _TRANS_HSYNC_A, _TRANS_HSYNC_B)
+#define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B)
+#define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B)
+#define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B)
+
+#define _TRANSB_DATA_M1          0xe1030
+#define _TRANSB_DATA_N1          0xe1034
+#define _TRANSB_DATA_M2          0xe1038
+#define _TRANSB_DATA_N2          0xe103c
+#define _TRANSB_DP_LINK_M1       0xe1040
+#define _TRANSB_DP_LINK_N1       0xe1044
+#define _TRANSB_DP_LINK_M2       0xe1048
+#define _TRANSB_DP_LINK_N2       0xe104c
+
+#define TRANSDATA_M1(pipe) _PIPE(pipe, _TRANSA_DATA_M1, _TRANSB_DATA_M1)
+#define TRANSDATA_N1(pipe) _PIPE(pipe, _TRANSA_DATA_N1, _TRANSB_DATA_N1)
+#define TRANSDATA_M2(pipe) _PIPE(pipe, _TRANSA_DATA_M2, _TRANSB_DATA_M2)
+#define TRANSDATA_N2(pipe) _PIPE(pipe, _TRANSA_DATA_N2, _TRANSB_DATA_N2)
+#define TRANSDPLINK_M1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M1, _TRANSB_DP_LINK_M1)
+#define TRANSDPLINK_N1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N1, _TRANSB_DP_LINK_N1)
+#define TRANSDPLINK_M2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M2, _TRANSB_DP_LINK_M2)
+#define TRANSDPLINK_N2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N2, _TRANSB_DP_LINK_N2)
+
+#define _TRANSACONF              0xf0008
+#define _TRANSBCONF              0xf1008
+#define TRANSCONF(plane) _PIPE(plane, _TRANSACONF, _TRANSBCONF)
 #define  TRANS_DISABLE          (0<<31)
 #define  TRANS_ENABLE           (1<<31)
 #define  TRANS_STATE_MASK       (1<<30)
@@ -3009,18 +3057,19 @@
 #define  TRANS_6BPC             (2<<5)
 #define  TRANS_12BPC            (3<<5)
 
-#define FDI_RXA_CHICKEN         0xc200c
-#define FDI_RXB_CHICKEN         0xc2010
-#define  FDI_RX_PHASE_SYNC_POINTER_ENABLE       (1)
-#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, FDI_RXA_CHICKEN, FDI_RXB_CHICKEN)
+#define _FDI_RXA_CHICKEN         0xc200c
+#define _FDI_RXB_CHICKEN         0xc2010
+#define  FDI_RX_PHASE_SYNC_POINTER_OVR	(1<<1)
+#define  FDI_RX_PHASE_SYNC_POINTER_EN	(1<<0)
+#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
 
 #define SOUTH_DSPCLK_GATE_D	0xc2020
 #define  PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
 
 /* CPU: FDI_TX */
-#define FDI_TXA_CTL             0x60100
-#define FDI_TXB_CTL             0x61100
-#define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL)
+#define _FDI_TXA_CTL             0x60100
+#define _FDI_TXB_CTL             0x61100
+#define FDI_TX_CTL(pipe) _PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL)
 #define  FDI_TX_DISABLE         (0<<31)
 #define  FDI_TX_ENABLE          (1<<31)
 #define  FDI_LINK_TRAIN_PATTERN_1       (0<<28)
@@ -3060,9 +3109,9 @@
 #define  FDI_SCRAMBLING_DISABLE         (1<<7)
 
 /* FDI_RX, FDI_X is hard-wired to Transcoder_X */
-#define FDI_RXA_CTL             0xf000c
-#define FDI_RXB_CTL             0xf100c
-#define FDI_RX_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL)
+#define _FDI_RXA_CTL             0xf000c
+#define _FDI_RXB_CTL             0xf100c
+#define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL)
 #define  FDI_RX_ENABLE          (1<<31)
 /* train, dp width same as FDI_TX */
 #define  FDI_DP_PORT_WIDTH_X8           (7<<19)
@@ -3087,15 +3136,15 @@
 #define  FDI_LINK_TRAIN_NORMAL_CPT		(3<<8)
 #define  FDI_LINK_TRAIN_PATTERN_MASK_CPT	(3<<8)
 
-#define FDI_RXA_MISC            0xf0010
-#define FDI_RXB_MISC            0xf1010
-#define FDI_RXA_TUSIZE1         0xf0030
-#define FDI_RXA_TUSIZE2         0xf0038
-#define FDI_RXB_TUSIZE1         0xf1030
-#define FDI_RXB_TUSIZE2         0xf1038
-#define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC)
-#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1)
-#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2)
+#define _FDI_RXA_MISC            0xf0010
+#define _FDI_RXB_MISC            0xf1010
+#define _FDI_RXA_TUSIZE1         0xf0030
+#define _FDI_RXA_TUSIZE2         0xf0038
+#define _FDI_RXB_TUSIZE1         0xf1030
+#define _FDI_RXB_TUSIZE2         0xf1038
+#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
+#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
+#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
 
 /* FDI_RX interrupt register format */
 #define FDI_RX_INTER_LANE_ALIGN         (1<<10)
@@ -3110,12 +3159,12 @@
 #define FDI_RX_CROSS_CLOCK_OVERFLOW     (1<<1)
 #define FDI_RX_SYMBOL_QUEUE_OVERFLOW    (1<<0)
 
-#define FDI_RXA_IIR             0xf0014
-#define FDI_RXA_IMR             0xf0018
-#define FDI_RXB_IIR             0xf1014
-#define FDI_RXB_IMR             0xf1018
-#define FDI_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR)
-#define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR)
+#define _FDI_RXA_IIR             0xf0014
+#define _FDI_RXA_IMR             0xf0018
+#define _FDI_RXB_IIR             0xf1014
+#define _FDI_RXB_IMR             0xf1018
+#define FDI_RX_IIR(pipe) _PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR)
+#define FDI_RX_IMR(pipe) _PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR)
 
 #define FDI_PLL_CTL_1           0xfe000
 #define FDI_PLL_CTL_2           0xfe004
@@ -3145,11 +3194,15 @@
 #define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
 #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 
+#define ADPA_PIPE_ENABLED(V, P) \
+	(((V) & (ADPA_TRANS_SELECT_MASK | ADPA_DAC_ENABLE)) == ((P) << 30 | ADPA_DAC_ENABLE))
+
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
 #define  TRANSCODER_A   (0)
 #define  TRANSCODER_B   (1 << 30)
+#define  TRANSCODER_MASK   (1 << 30)
 #define  COLOR_FORMAT_8bpc      (0)
 #define  COLOR_FORMAT_12bpc     (3 << 26)
 #define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
@@ -3165,6 +3218,9 @@
 #define  HSYNC_ACTIVE_HIGH      (1 << 3)
 #define  PORT_DETECTED          (1 << 2)
 
+#define HDMI_PIPE_ENABLED(V, P) \
+	(((V) & (TRANSCODER_MASK | PORT_ENABLE)) == ((P) << 30 | PORT_ENABLE))
+
 /* PCH SDVOB multiplex with HDMIB */
 #define PCH_SDVOB	HDMIB
 
@@ -3240,6 +3296,7 @@
 #define  TRANS_DP_PORT_SEL_B	(0<<29)
 #define  TRANS_DP_PORT_SEL_C	(1<<29)
 #define  TRANS_DP_PORT_SEL_D	(2<<29)
+#define  TRANS_DP_PORT_SEL_NONE	(3<<29)
 #define  TRANS_DP_PORT_SEL_MASK	(3<<29)
 #define  TRANS_DP_AUDIO_ONLY	(1<<26)
 #define  TRANS_DP_ENH_FRAMING	(1<<18)
@@ -3290,15 +3347,28 @@
 #define GEN6_RP_DOWN_TIMEOUT			0xA010
 #define GEN6_RP_INTERRUPT_LIMITS		0xA014
 #define GEN6_RPSTAT1				0xA01C
+#define   GEN6_CAGF_SHIFT			8
+#define   GEN6_CAGF_MASK			(0x7f << GEN6_CAGF_SHIFT)
 #define GEN6_RP_CONTROL				0xA024
 #define   GEN6_RP_MEDIA_TURBO			(1<<11)
 #define   GEN6_RP_USE_NORMAL_FREQ		(1<<9)
 #define   GEN6_RP_MEDIA_IS_GFX			(1<<8)
 #define   GEN6_RP_ENABLE			(1<<7)
-#define   GEN6_RP_UP_BUSY_MAX			(0x2<<3)
-#define   GEN6_RP_DOWN_BUSY_MIN			(0x2<<0)
+#define   GEN6_RP_UP_IDLE_MIN			(0x1<<3)
+#define   GEN6_RP_UP_BUSY_AVG			(0x2<<3)
+#define   GEN6_RP_UP_BUSY_CONT			(0x4<<3)
+#define   GEN6_RP_DOWN_IDLE_CONT		(0x1<<0)
 #define GEN6_RP_UP_THRESHOLD			0xA02C
 #define GEN6_RP_DOWN_THRESHOLD			0xA030
+#define GEN6_RP_CUR_UP_EI			0xA050
+#define   GEN6_CURICONT_MASK			0xffffff
+#define GEN6_RP_CUR_UP				0xA054
+#define   GEN6_CURBSYTAVG_MASK			0xffffff
+#define GEN6_RP_PREV_UP				0xA058
+#define GEN6_RP_CUR_DOWN_EI			0xA05C
+#define   GEN6_CURIAVG_MASK			0xffffff
+#define GEN6_RP_CUR_DOWN			0xA060
+#define GEN6_RP_PREV_DOWN			0xA064
 #define GEN6_RP_UP_EI				0xA068
 #define GEN6_RP_DOWN_EI				0xA06C
 #define GEN6_RP_IDLE_HYSTERSIS			0xA070
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 0521ecf..7e992a8 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -34,11 +34,10 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32	dpll_reg;
 
-	if (HAS_PCH_SPLIT(dev)) {
-		dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B;
-	} else {
-		dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B;
-	}
+	if (HAS_PCH_SPLIT(dev))
+		dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
+	else
+		dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
 
 	return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE);
 }
@@ -46,7 +45,7 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
 static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
 	u32 *array;
 	int i;
 
@@ -54,7 +53,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
 		return;
 
 	if (HAS_PCH_SPLIT(dev))
-		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
 		array = dev_priv->save_palette_a;
@@ -68,7 +67,7 @@ static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
 static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
 	u32 *array;
 	int i;
 
@@ -76,7 +75,7 @@ static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
 		return;
 
 	if (HAS_PCH_SPLIT(dev))
-		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
 		array = dev_priv->save_palette_a;
@@ -241,12 +240,12 @@ static void i915_save_modeset_reg(struct drm_device *dev)
 		return;
 
 	/* Cursor state */
-	dev_priv->saveCURACNTR = I915_READ(CURACNTR);
-	dev_priv->saveCURAPOS = I915_READ(CURAPOS);
-	dev_priv->saveCURABASE = I915_READ(CURABASE);
-	dev_priv->saveCURBCNTR = I915_READ(CURBCNTR);
-	dev_priv->saveCURBPOS = I915_READ(CURBPOS);
-	dev_priv->saveCURBBASE = I915_READ(CURBBASE);
+	dev_priv->saveCURACNTR = I915_READ(_CURACNTR);
+	dev_priv->saveCURAPOS = I915_READ(_CURAPOS);
+	dev_priv->saveCURABASE = I915_READ(_CURABASE);
+	dev_priv->saveCURBCNTR = I915_READ(_CURBCNTR);
+	dev_priv->saveCURBPOS = I915_READ(_CURBPOS);
+	dev_priv->saveCURBBASE = I915_READ(_CURBBASE);
 	if (IS_GEN2(dev))
 		dev_priv->saveCURSIZE = I915_READ(CURSIZE);
 
@@ -256,118 +255,118 @@ static void i915_save_modeset_reg(struct drm_device *dev)
 	}
 
 	/* Pipe & plane A info */
-	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
-	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+	dev_priv->savePIPEACONF = I915_READ(_PIPEACONF);
+	dev_priv->savePIPEASRC = I915_READ(_PIPEASRC);
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
-		dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
-		dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
+		dev_priv->saveFPA0 = I915_READ(_PCH_FPA0);
+		dev_priv->saveFPA1 = I915_READ(_PCH_FPA1);
+		dev_priv->saveDPLL_A = I915_READ(_PCH_DPLL_A);
 	} else {
-		dev_priv->saveFPA0 = I915_READ(FPA0);
-		dev_priv->saveFPA1 = I915_READ(FPA1);
-		dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+		dev_priv->saveFPA0 = I915_READ(_FPA0);
+		dev_priv->saveFPA1 = I915_READ(_FPA1);
+		dev_priv->saveDPLL_A = I915_READ(_DPLL_A);
 	}
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
-	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
-	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
-	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
-	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
-	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
-	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+		dev_priv->saveDPLL_A_MD = I915_READ(_DPLL_A_MD);
+	dev_priv->saveHTOTAL_A = I915_READ(_HTOTAL_A);
+	dev_priv->saveHBLANK_A = I915_READ(_HBLANK_A);
+	dev_priv->saveHSYNC_A = I915_READ(_HSYNC_A);
+	dev_priv->saveVTOTAL_A = I915_READ(_VTOTAL_A);
+	dev_priv->saveVBLANK_A = I915_READ(_VBLANK_A);
+	dev_priv->saveVSYNC_A = I915_READ(_VSYNC_A);
 	if (!HAS_PCH_SPLIT(dev))
-		dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+		dev_priv->saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1);
-		dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1);
-		dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1);
-		dev_priv->savePIPEA_LINK_N1 = I915_READ(PIPEA_LINK_N1);
-
-		dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL);
-		dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL);
-
-		dev_priv->savePFA_CTL_1 = I915_READ(PFA_CTL_1);
-		dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ);
-		dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS);
-
-		dev_priv->saveTRANSACONF = I915_READ(TRANSACONF);
-		dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A);
-		dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A);
-		dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A);
-		dev_priv->saveTRANS_VTOTAL_A = I915_READ(TRANS_VTOTAL_A);
-		dev_priv->saveTRANS_VBLANK_A = I915_READ(TRANS_VBLANK_A);
-		dev_priv->saveTRANS_VSYNC_A = I915_READ(TRANS_VSYNC_A);
-	}
-
-	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
-	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
-	dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
+		dev_priv->savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
+		dev_priv->savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
+		dev_priv->savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
+		dev_priv->savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);
+
+		dev_priv->saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL);
+		dev_priv->saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL);
+
+		dev_priv->savePFA_CTL_1 = I915_READ(_PFA_CTL_1);
+		dev_priv->savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
+		dev_priv->savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
+
+		dev_priv->saveTRANSACONF = I915_READ(_TRANSACONF);
+		dev_priv->saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
+		dev_priv->saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
+		dev_priv->saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
+		dev_priv->saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
+		dev_priv->saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
+		dev_priv->saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
+	}
+
+	dev_priv->saveDSPACNTR = I915_READ(_DSPACNTR);
+	dev_priv->saveDSPASTRIDE = I915_READ(_DSPASTRIDE);
+	dev_priv->saveDSPASIZE = I915_READ(_DSPASIZE);
+	dev_priv->saveDSPAPOS = I915_READ(_DSPAPOS);
+	dev_priv->saveDSPAADDR = I915_READ(_DSPAADDR);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+		dev_priv->saveDSPASURF = I915_READ(_DSPASURF);
+		dev_priv->saveDSPATILEOFF = I915_READ(_DSPATILEOFF);
 	}
 	i915_save_palette(dev, PIPE_A);
-	dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
+	dev_priv->savePIPEASTAT = I915_READ(_PIPEASTAT);
 
 	/* Pipe & plane B info */
-	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+	dev_priv->savePIPEBCONF = I915_READ(_PIPEBCONF);
+	dev_priv->savePIPEBSRC = I915_READ(_PIPEBSRC);
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveFPB0 = I915_READ(PCH_FPB0);
-		dev_priv->saveFPB1 = I915_READ(PCH_FPB1);
-		dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B);
+		dev_priv->saveFPB0 = I915_READ(_PCH_FPB0);
+		dev_priv->saveFPB1 = I915_READ(_PCH_FPB1);
+		dev_priv->saveDPLL_B = I915_READ(_PCH_DPLL_B);
 	} else {
-		dev_priv->saveFPB0 = I915_READ(FPB0);
-		dev_priv->saveFPB1 = I915_READ(FPB1);
-		dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+		dev_priv->saveFPB0 = I915_READ(_FPB0);
+		dev_priv->saveFPB1 = I915_READ(_FPB1);
+		dev_priv->saveDPLL_B = I915_READ(_DPLL_B);
 	}
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
-	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
-	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
-	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
-	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
-	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
-	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+		dev_priv->saveDPLL_B_MD = I915_READ(_DPLL_B_MD);
+	dev_priv->saveHTOTAL_B = I915_READ(_HTOTAL_B);
+	dev_priv->saveHBLANK_B = I915_READ(_HBLANK_B);
+	dev_priv->saveHSYNC_B = I915_READ(_HSYNC_B);
+	dev_priv->saveVTOTAL_B = I915_READ(_VTOTAL_B);
+	dev_priv->saveVBLANK_B = I915_READ(_VBLANK_B);
+	dev_priv->saveVSYNC_B = I915_READ(_VSYNC_B);
 	if (!HAS_PCH_SPLIT(dev))
-		dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B);
+		dev_priv->saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1);
-		dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1);
-		dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1);
-		dev_priv->savePIPEB_LINK_N1 = I915_READ(PIPEB_LINK_N1);
-
-		dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL);
-		dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL);
-
-		dev_priv->savePFB_CTL_1 = I915_READ(PFB_CTL_1);
-		dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ);
-		dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS);
-
-		dev_priv->saveTRANSBCONF = I915_READ(TRANSBCONF);
-		dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B);
-		dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B);
-		dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B);
-		dev_priv->saveTRANS_VTOTAL_B = I915_READ(TRANS_VTOTAL_B);
-		dev_priv->saveTRANS_VBLANK_B = I915_READ(TRANS_VBLANK_B);
-		dev_priv->saveTRANS_VSYNC_B = I915_READ(TRANS_VSYNC_B);
-	}
-
-	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
-	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
-	dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
+		dev_priv->savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
+		dev_priv->savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
+		dev_priv->savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
+		dev_priv->savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);
+
+		dev_priv->saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL);
+		dev_priv->saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL);
+
+		dev_priv->savePFB_CTL_1 = I915_READ(_PFB_CTL_1);
+		dev_priv->savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
+		dev_priv->savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
+
+		dev_priv->saveTRANSBCONF = I915_READ(_TRANSBCONF);
+		dev_priv->saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
+		dev_priv->saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
+		dev_priv->saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
+		dev_priv->saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
+		dev_priv->saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
+		dev_priv->saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
+	}
+
+	dev_priv->saveDSPBCNTR = I915_READ(_DSPBCNTR);
+	dev_priv->saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE);
+	dev_priv->saveDSPBSIZE = I915_READ(_DSPBSIZE);
+	dev_priv->saveDSPBPOS = I915_READ(_DSPBPOS);
+	dev_priv->saveDSPBADDR = I915_READ(_DSPBADDR);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+		dev_priv->saveDSPBSURF = I915_READ(_DSPBSURF);
+		dev_priv->saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF);
 	}
 	i915_save_palette(dev, PIPE_B);
-	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+	dev_priv->savePIPEBSTAT = I915_READ(_PIPEBSTAT);
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
@@ -426,19 +425,19 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dpll_a_reg = PCH_DPLL_A;
-		dpll_b_reg = PCH_DPLL_B;
-		fpa0_reg = PCH_FPA0;
-		fpb0_reg = PCH_FPB0;
-		fpa1_reg = PCH_FPA1;
-		fpb1_reg = PCH_FPB1;
+		dpll_a_reg = _PCH_DPLL_A;
+		dpll_b_reg = _PCH_DPLL_B;
+		fpa0_reg = _PCH_FPA0;
+		fpb0_reg = _PCH_FPB0;
+		fpa1_reg = _PCH_FPA1;
+		fpb1_reg = _PCH_FPB1;
 	} else {
-		dpll_a_reg = DPLL_A;
-		dpll_b_reg = DPLL_B;
-		fpa0_reg = FPA0;
-		fpb0_reg = FPB0;
-		fpa1_reg = FPA1;
-		fpb1_reg = FPB1;
+		dpll_a_reg = _DPLL_A;
+		dpll_b_reg = _DPLL_B;
+		fpa0_reg = _FPA0;
+		fpb0_reg = _FPB0;
+		fpa1_reg = _FPA1;
+		fpb1_reg = _FPB1;
 	}
 
 	if (HAS_PCH_SPLIT(dev)) {
@@ -461,60 +460,60 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 	POSTING_READ(dpll_a_reg);
 	udelay(150);
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-		POSTING_READ(DPLL_A_MD);
+		I915_WRITE(_DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+		POSTING_READ(_DPLL_A_MD);
 	}
 	udelay(150);
 
 	/* Restore mode */
-	I915_WRITE(HTOTAL_A, dev_priv->saveHTOTAL_A);
-	I915_WRITE(HBLANK_A, dev_priv->saveHBLANK_A);
-	I915_WRITE(HSYNC_A, dev_priv->saveHSYNC_A);
-	I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
-	I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
-	I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
+	I915_WRITE(_HTOTAL_A, dev_priv->saveHTOTAL_A);
+	I915_WRITE(_HBLANK_A, dev_priv->saveHBLANK_A);
+	I915_WRITE(_HSYNC_A, dev_priv->saveHSYNC_A);
+	I915_WRITE(_VTOTAL_A, dev_priv->saveVTOTAL_A);
+	I915_WRITE(_VBLANK_A, dev_priv->saveVBLANK_A);
+	I915_WRITE(_VSYNC_A, dev_priv->saveVSYNC_A);
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+		I915_WRITE(_BCLRPAT_A, dev_priv->saveBCLRPAT_A);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
-		I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
-		I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
-		I915_WRITE(PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
+		I915_WRITE(_PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
+		I915_WRITE(_PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
+		I915_WRITE(_PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
+		I915_WRITE(_PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
 
-		I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
-		I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
+		I915_WRITE(_FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
+		I915_WRITE(_FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
 
-		I915_WRITE(PFA_CTL_1, dev_priv->savePFA_CTL_1);
-		I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
-		I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
+		I915_WRITE(_PFA_CTL_1, dev_priv->savePFA_CTL_1);
+		I915_WRITE(_PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
+		I915_WRITE(_PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
 
-		I915_WRITE(TRANSACONF, dev_priv->saveTRANSACONF);
-		I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
-		I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
-		I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
-		I915_WRITE(TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
-		I915_WRITE(TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
-		I915_WRITE(TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
+		I915_WRITE(_TRANSACONF, dev_priv->saveTRANSACONF);
+		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
+		I915_WRITE(_TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
+		I915_WRITE(_TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
+		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
+		I915_WRITE(_TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
+		I915_WRITE(_TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
 	}
 
 	/* Restore plane info */
-	I915_WRITE(DSPASIZE, dev_priv->saveDSPASIZE);
-	I915_WRITE(DSPAPOS, dev_priv->saveDSPAPOS);
-	I915_WRITE(PIPEASRC, dev_priv->savePIPEASRC);
-	I915_WRITE(DSPAADDR, dev_priv->saveDSPAADDR);
-	I915_WRITE(DSPASTRIDE, dev_priv->saveDSPASTRIDE);
+	I915_WRITE(_DSPASIZE, dev_priv->saveDSPASIZE);
+	I915_WRITE(_DSPAPOS, dev_priv->saveDSPAPOS);
+	I915_WRITE(_PIPEASRC, dev_priv->savePIPEASRC);
+	I915_WRITE(_DSPAADDR, dev_priv->saveDSPAADDR);
+	I915_WRITE(_DSPASTRIDE, dev_priv->saveDSPASTRIDE);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+		I915_WRITE(_DSPASURF, dev_priv->saveDSPASURF);
+		I915_WRITE(_DSPATILEOFF, dev_priv->saveDSPATILEOFF);
 	}
 
-	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+	I915_WRITE(_PIPEACONF, dev_priv->savePIPEACONF);
 
 	i915_restore_palette(dev, PIPE_A);
 	/* Enable the plane */
-	I915_WRITE(DSPACNTR, dev_priv->saveDSPACNTR);
-	I915_WRITE(DSPAADDR, I915_READ(DSPAADDR));
+	I915_WRITE(_DSPACNTR, dev_priv->saveDSPACNTR);
+	I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR));
 
 	/* Pipe & plane B info */
 	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
@@ -530,68 +529,68 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 	POSTING_READ(dpll_b_reg);
 	udelay(150);
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-		POSTING_READ(DPLL_B_MD);
+		I915_WRITE(_DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+		POSTING_READ(_DPLL_B_MD);
 	}
 	udelay(150);
 
 	/* Restore mode */
-	I915_WRITE(HTOTAL_B, dev_priv->saveHTOTAL_B);
-	I915_WRITE(HBLANK_B, dev_priv->saveHBLANK_B);
-	I915_WRITE(HSYNC_B, dev_priv->saveHSYNC_B);
-	I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
-	I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
-	I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
+	I915_WRITE(_HTOTAL_B, dev_priv->saveHTOTAL_B);
+	I915_WRITE(_HBLANK_B, dev_priv->saveHBLANK_B);
+	I915_WRITE(_HSYNC_B, dev_priv->saveHSYNC_B);
+	I915_WRITE(_VTOTAL_B, dev_priv->saveVTOTAL_B);
+	I915_WRITE(_VBLANK_B, dev_priv->saveVBLANK_B);
+	I915_WRITE(_VSYNC_B, dev_priv->saveVSYNC_B);
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+		I915_WRITE(_BCLRPAT_B, dev_priv->saveBCLRPAT_B);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
-		I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
-		I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
-		I915_WRITE(PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
+		I915_WRITE(_PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
+		I915_WRITE(_PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
+		I915_WRITE(_PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
+		I915_WRITE(_PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
 
-		I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
-		I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
+		I915_WRITE(_FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
+		I915_WRITE(_FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
 
-		I915_WRITE(PFB_CTL_1, dev_priv->savePFB_CTL_1);
-		I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
-		I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
+		I915_WRITE(_PFB_CTL_1, dev_priv->savePFB_CTL_1);
+		I915_WRITE(_PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
+		I915_WRITE(_PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
 
-		I915_WRITE(TRANSBCONF, dev_priv->saveTRANSBCONF);
-		I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
-		I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
-		I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
-		I915_WRITE(TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
-		I915_WRITE(TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
-		I915_WRITE(TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
+		I915_WRITE(_TRANSBCONF, dev_priv->saveTRANSBCONF);
+		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
+		I915_WRITE(_TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
+		I915_WRITE(_TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
+		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
+		I915_WRITE(_TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
+		I915_WRITE(_TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
 	}
 
 	/* Restore plane info */
-	I915_WRITE(DSPBSIZE, dev_priv->saveDSPBSIZE);
-	I915_WRITE(DSPBPOS, dev_priv->saveDSPBPOS);
-	I915_WRITE(PIPEBSRC, dev_priv->savePIPEBSRC);
-	I915_WRITE(DSPBADDR, dev_priv->saveDSPBADDR);
-	I915_WRITE(DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
+	I915_WRITE(_DSPBSIZE, dev_priv->saveDSPBSIZE);
+	I915_WRITE(_DSPBPOS, dev_priv->saveDSPBPOS);
+	I915_WRITE(_PIPEBSRC, dev_priv->savePIPEBSRC);
+	I915_WRITE(_DSPBADDR, dev_priv->saveDSPBADDR);
+	I915_WRITE(_DSPBSTRIDE, dev_priv->saveDSPBSTRIDE);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+		I915_WRITE(_DSPBSURF, dev_priv->saveDSPBSURF);
+		I915_WRITE(_DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
 	}
 
-	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+	I915_WRITE(_PIPEBCONF, dev_priv->savePIPEBCONF);
 
 	i915_restore_palette(dev, PIPE_B);
 	/* Enable the plane */
-	I915_WRITE(DSPBCNTR, dev_priv->saveDSPBCNTR);
-	I915_WRITE(DSPBADDR, I915_READ(DSPBADDR));
+	I915_WRITE(_DSPBCNTR, dev_priv->saveDSPBCNTR);
+	I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR));
 
 	/* Cursor state */
-	I915_WRITE(CURAPOS, dev_priv->saveCURAPOS);
-	I915_WRITE(CURACNTR, dev_priv->saveCURACNTR);
-	I915_WRITE(CURABASE, dev_priv->saveCURABASE);
-	I915_WRITE(CURBPOS, dev_priv->saveCURBPOS);
-	I915_WRITE(CURBCNTR, dev_priv->saveCURBCNTR);
-	I915_WRITE(CURBBASE, dev_priv->saveCURBBASE);
+	I915_WRITE(_CURAPOS, dev_priv->saveCURAPOS);
+	I915_WRITE(_CURACNTR, dev_priv->saveCURACNTR);
+	I915_WRITE(_CURABASE, dev_priv->saveCURABASE);
+	I915_WRITE(_CURBPOS, dev_priv->saveCURBPOS);
+	I915_WRITE(_CURBCNTR, dev_priv->saveCURBCNTR);
+	I915_WRITE(_CURBBASE, dev_priv->saveCURBBASE);
 	if (IS_GEN2(dev))
 		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
 
@@ -653,14 +652,14 @@ void i915_save_display(struct drm_device *dev)
 		dev_priv->saveDP_B = I915_READ(DP_B);
 		dev_priv->saveDP_C = I915_READ(DP_C);
 		dev_priv->saveDP_D = I915_READ(DP_D);
-		dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M);
-		dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M);
-		dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N);
-		dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N);
-		dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M);
-		dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M);
-		dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N);
-		dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N);
+		dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(_PIPEA_GMCH_DATA_M);
+		dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(_PIPEB_GMCH_DATA_M);
+		dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(_PIPEA_GMCH_DATA_N);
+		dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(_PIPEB_GMCH_DATA_N);
+		dev_priv->savePIPEA_DP_LINK_M = I915_READ(_PIPEA_DP_LINK_M);
+		dev_priv->savePIPEB_DP_LINK_M = I915_READ(_PIPEB_DP_LINK_M);
+		dev_priv->savePIPEA_DP_LINK_N = I915_READ(_PIPEA_DP_LINK_N);
+		dev_priv->savePIPEB_DP_LINK_N = I915_READ(_PIPEB_DP_LINK_N);
 	}
 	/* FIXME: save TV & SDVO state */
 
@@ -699,14 +698,14 @@ void i915_restore_display(struct drm_device *dev)
 
 	/* Display port ratios (must be done before clock is set) */
 	if (SUPPORTS_INTEGRATED_DP(dev)) {
-		I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
-		I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
-		I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
-		I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
-		I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
-		I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
-		I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
-		I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
+		I915_WRITE(_PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M);
+		I915_WRITE(_PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M);
+		I915_WRITE(_PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N);
+		I915_WRITE(_PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N);
+		I915_WRITE(_PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M);
+		I915_WRITE(_PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M);
+		I915_WRITE(_PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N);
+		I915_WRITE(_PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N);
 	}
 
 	/* This is only meaningful in non-KMS mode */
@@ -797,9 +796,6 @@ int i915_save_state(struct drm_device *dev)
 
 	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
 
-	/* Hardware status page */
-	dev_priv->saveHWS = I915_READ(HWS_PGA);
-
 	i915_save_display(dev);
 
 	/* Interrupt state */
@@ -808,8 +804,8 @@ int i915_save_state(struct drm_device *dev)
 		dev_priv->saveDEIMR = I915_READ(DEIMR);
 		dev_priv->saveGTIER = I915_READ(GTIER);
 		dev_priv->saveGTIMR = I915_READ(GTIMR);
-		dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
-		dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
+		dev_priv->saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
+		dev_priv->saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
 		dev_priv->saveMCHBAR_RENDER_STANDBY =
 			I915_READ(RSTDBYCTL);
 	} else {
@@ -846,9 +842,6 @@ int i915_restore_state(struct drm_device *dev)
 
 	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
 
-	/* Hardware status page */
-	I915_WRITE(HWS_PGA, dev_priv->saveHWS);
-
 	i915_restore_display(dev);
 
 	/* Interrupt state */
@@ -857,11 +850,11 @@ int i915_restore_state(struct drm_device *dev)
 		I915_WRITE(DEIMR, dev_priv->saveDEIMR);
 		I915_WRITE(GTIER, dev_priv->saveGTIER);
 		I915_WRITE(GTIMR, dev_priv->saveGTIMR);
-		I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
-		I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
+		I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
+		I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
 	} else {
-		I915_WRITE (IER, dev_priv->saveIER);
-		I915_WRITE (IMR,  dev_priv->saveIMR);
+		I915_WRITE(IER, dev_priv->saveIER);
+		I915_WRITE(IMR, dev_priv->saveIMR);
 	}
 
 	/* Clock gating state */
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 7f0fc3e..d623fef 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -7,6 +7,7 @@
 
 #include <drm/drmP.h>
 #include "i915_drv.h"
+#include "intel_ringbuffer.h"
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM i915
@@ -16,9 +17,7 @@
 /* object tracking */
 
 TRACE_EVENT(i915_gem_object_create,
-
 	    TP_PROTO(struct drm_i915_gem_object *obj),
-
 	    TP_ARGS(obj),
 
 	    TP_STRUCT__entry(
@@ -35,33 +34,51 @@ TRACE_EVENT(i915_gem_object_create,
 );
 
 TRACE_EVENT(i915_gem_object_bind,
-
-	    TP_PROTO(struct drm_i915_gem_object *obj, u32 gtt_offset, bool mappable),
-
-	    TP_ARGS(obj, gtt_offset, mappable),
+	    TP_PROTO(struct drm_i915_gem_object *obj, bool mappable),
+	    TP_ARGS(obj, mappable),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
-			     __field(u32, gtt_offset)
+			     __field(u32, offset)
+			     __field(u32, size)
 			     __field(bool, mappable)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
-			   __entry->gtt_offset = gtt_offset;
+			   __entry->offset = obj->gtt_space->start;
+			   __entry->size = obj->gtt_space->size;
 			   __entry->mappable = mappable;
 			   ),
 
-	    TP_printk("obj=%p, gtt_offset=%08x%s",
-		      __entry->obj, __entry->gtt_offset,
+	    TP_printk("obj=%p, offset=%08x size=%x%s",
+		      __entry->obj, __entry->offset, __entry->size,
 		      __entry->mappable ? ", mappable" : "")
 );
 
-TRACE_EVENT(i915_gem_object_change_domain,
+TRACE_EVENT(i915_gem_object_unbind,
+	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_ARGS(obj),
+
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, offset)
+			     __field(u32, size)
+			     ),
 
-	    TP_PROTO(struct drm_i915_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain),
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->offset = obj->gtt_space->start;
+			   __entry->size = obj->gtt_space->size;
+			   ),
 
-	    TP_ARGS(obj, old_read_domains, old_write_domain),
+	    TP_printk("obj=%p, offset=%08x size=%x",
+		      __entry->obj, __entry->offset, __entry->size)
+);
+
+TRACE_EVENT(i915_gem_object_change_domain,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 old_read, u32 old_write),
+	    TP_ARGS(obj, old_read, old_write),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
@@ -71,177 +88,264 @@ TRACE_EVENT(i915_gem_object_change_domain,
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
-			   __entry->read_domains = obj->base.read_domains | (old_read_domains << 16);
-			   __entry->write_domain = obj->base.write_domain | (old_write_domain << 16);
+			   __entry->read_domains = obj->base.read_domains | (old_read << 16);
+			   __entry->write_domain = obj->base.write_domain | (old_write << 16);
 			   ),
 
-	    TP_printk("obj=%p, read=%04x, write=%04x",
+	    TP_printk("obj=%p, read=%02x=>%02x, write=%02x=>%02x",
 		      __entry->obj,
-		      __entry->read_domains, __entry->write_domain)
+		      __entry->read_domains >> 16,
+		      __entry->read_domains & 0xffff,
+		      __entry->write_domain >> 16,
+		      __entry->write_domain & 0xffff)
 );
 
-DECLARE_EVENT_CLASS(i915_gem_object,
+TRACE_EVENT(i915_gem_object_pwrite,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len),
+	    TP_ARGS(obj, offset, len),
 
-	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, offset)
+			     __field(u32, len)
+			     ),
 
-	    TP_ARGS(obj),
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->offset = offset;
+			   __entry->len = len;
+			   ),
+
+	    TP_printk("obj=%p, offset=%u, len=%u",
+		      __entry->obj, __entry->offset, __entry->len)
+);
+
+TRACE_EVENT(i915_gem_object_pread,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len),
+	    TP_ARGS(obj, offset, len),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, offset)
+			     __field(u32, len)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
+			   __entry->offset = offset;
+			   __entry->len = len;
 			   ),
 
-	    TP_printk("obj=%p", __entry->obj)
+	    TP_printk("obj=%p, offset=%u, len=%u",
+		      __entry->obj, __entry->offset, __entry->len)
 );
 
-DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
+TRACE_EVENT(i915_gem_object_fault,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 index, bool gtt, bool write),
+	    TP_ARGS(obj, index, gtt, write),
+
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, index)
+			     __field(bool, gtt)
+			     __field(bool, write)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->index = index;
+			   __entry->gtt = gtt;
+			   __entry->write = write;
+			   ),
 
+	    TP_printk("obj=%p, %s index=%u %s",
+		      __entry->obj,
+		      __entry->gtt ? "GTT" : "CPU",
+		      __entry->index,
+		      __entry->write ? ", writable" : "")
+);
+
+DECLARE_EVENT_CLASS(i915_gem_object,
 	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_ARGS(obj),
 
-	    TP_ARGS(obj)
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   ),
+
+	    TP_printk("obj=%p", __entry->obj)
 );
 
-DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
+DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
+	     TP_PROTO(struct drm_i915_gem_object *obj),
+	     TP_ARGS(obj)
+);
 
+DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
 	    TP_PROTO(struct drm_i915_gem_object *obj),
-
 	    TP_ARGS(obj)
 );
 
-DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
+TRACE_EVENT(i915_gem_evict,
+	    TP_PROTO(struct drm_device *dev, u32 size, u32 align, bool mappable),
+	    TP_ARGS(dev, size, align, mappable),
 
-	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_STRUCT__entry(
+			     __field(u32, dev)
+			     __field(u32, size)
+			     __field(u32, align)
+			     __field(bool, mappable)
+			    ),
 
-	    TP_ARGS(obj)
+	    TP_fast_assign(
+			   __entry->dev = dev->primary->index;
+			   __entry->size = size;
+			   __entry->align = align;
+			   __entry->mappable = mappable;
+			  ),
+
+	    TP_printk("dev=%d, size=%d, align=%d %s",
+		      __entry->dev, __entry->size, __entry->align,
+		      __entry->mappable ? ", mappable" : "")
 );
 
-/* batch tracing */
+TRACE_EVENT(i915_gem_evict_everything,
+	    TP_PROTO(struct drm_device *dev, bool purgeable),
+	    TP_ARGS(dev, purgeable),
 
-TRACE_EVENT(i915_gem_request_submit,
+	    TP_STRUCT__entry(
+			     __field(u32, dev)
+			     __field(bool, purgeable)
+			    ),
+
+	    TP_fast_assign(
+			   __entry->dev = dev->primary->index;
+			   __entry->purgeable = purgeable;
+			  ),
 
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+	    TP_printk("dev=%d%s",
+		      __entry->dev,
+		      __entry->purgeable ? ", purgeable only" : "")
+);
 
-	    TP_ARGS(dev, seqno),
+TRACE_EVENT(i915_gem_ring_dispatch,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(u32, ring)
 			     __field(u32, seqno)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
 			   __entry->seqno = seqno;
-			   i915_trace_irq_get(dev, seqno);
+			   i915_trace_irq_get(ring, seqno);
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
+	    TP_printk("dev=%u, ring=%u, seqno=%u",
+		      __entry->dev, __entry->ring, __entry->seqno)
 );
 
-TRACE_EVENT(i915_gem_request_flush,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno,
-		     u32 flush_domains, u32 invalidate_domains),
-
-	    TP_ARGS(dev, seqno, flush_domains, invalidate_domains),
+TRACE_EVENT(i915_gem_ring_flush,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 invalidate, u32 flush),
+	    TP_ARGS(ring, invalidate, flush),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
-			     __field(u32, seqno)
-			     __field(u32, flush_domains)
-			     __field(u32, invalidate_domains)
+			     __field(u32, ring)
+			     __field(u32, invalidate)
+			     __field(u32, flush)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
-			   __entry->seqno = seqno;
-			   __entry->flush_domains = flush_domains;
-			   __entry->invalidate_domains = invalidate_domains;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
+			   __entry->invalidate = invalidate;
+			   __entry->flush = flush;
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u, flush=%04x, invalidate=%04x",
-		      __entry->dev, __entry->seqno,
-		      __entry->flush_domains, __entry->invalidate_domains)
+	    TP_printk("dev=%u, ring=%x, invalidate=%04x, flush=%04x",
+		      __entry->dev, __entry->ring,
+		      __entry->invalidate, __entry->flush)
 );
 
 DECLARE_EVENT_CLASS(i915_gem_request,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno),
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(u32, ring)
 			     __field(u32, seqno)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
 			   __entry->seqno = seqno;
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
+	    TP_printk("dev=%u, ring=%u, seqno=%u",
+		      __entry->dev, __entry->ring, __entry->seqno)
 );
 
-DEFINE_EVENT(i915_gem_request, i915_gem_request_complete,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
+);
 
-	    TP_ARGS(dev, seqno)
+DEFINE_EVENT(i915_gem_request, i915_gem_request_complete,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno)
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno)
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno)
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DECLARE_EVENT_CLASS(i915_ring,
-
-	    TP_PROTO(struct drm_device *dev),
-
-	    TP_ARGS(dev),
+	    TP_PROTO(struct intel_ring_buffer *ring),
+	    TP_ARGS(ring),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(u32, ring)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
 			   ),
 
-	    TP_printk("dev=%u", __entry->dev)
+	    TP_printk("dev=%u, ring=%u", __entry->dev, __entry->ring)
 );
 
 DEFINE_EVENT(i915_ring, i915_ring_wait_begin,
-
-	    TP_PROTO(struct drm_device *dev),
-
-	    TP_ARGS(dev)
+	    TP_PROTO(struct intel_ring_buffer *ring),
+	    TP_ARGS(ring)
 );
 
 DEFINE_EVENT(i915_ring, i915_ring_wait_end,
-
-	    TP_PROTO(struct drm_device *dev),
-
-	    TP_ARGS(dev)
+	    TP_PROTO(struct intel_ring_buffer *ring),
+	    TP_ARGS(ring)
 );
 
 TRACE_EVENT(i915_flip_request,
@@ -281,26 +385,29 @@ TRACE_EVENT(i915_flip_complete,
 );
 
 TRACE_EVENT(i915_reg_rw,
-           TP_PROTO(int cmd, uint32_t reg, uint64_t val, int len),
+           TP_PROTO(bool write, u32 reg, u64 val, int len),
 
-           TP_ARGS(cmd, reg, val, len),
+           TP_ARGS(write, reg, val, len),
 
            TP_STRUCT__entry(
-                   __field(int, cmd)
-                   __field(uint32_t, reg)
-                   __field(uint64_t, val)
-                   __field(int, len)
+                   __field(u64, val)
+                   __field(u32, reg)
+                   __field(u16, write)
+                   __field(u16, len)
                    ),
 
            TP_fast_assign(
-                   __entry->cmd = cmd;
+                   __entry->val = (u64)val;
                    __entry->reg = reg;
-                   __entry->val = (uint64_t)val;
+                   __entry->write = write;
                    __entry->len = len;
                    ),
 
-           TP_printk("cmd=%c, reg=0x%x, val=0x%llx, len=%d",
-                     __entry->cmd, __entry->reg, __entry->val, __entry->len)
+           TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
+                     __entry->write ? "write" : "read",
+		     __entry->reg, __entry->len,
+		     (u32)(__entry->val & 0xffffffff),
+		     (u32)(__entry->val >> 32))
 );
 
 #endif /* _I915_TRACE_H_ */
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 0b44956..fb5b4d4 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -226,29 +226,49 @@ static void
 parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
 		      struct bdb_header *bdb)
 {
-	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 	struct lvds_dvo_timing *dvo_timing;
 	struct drm_display_mode *panel_fixed_mode;
+	int index;
 
-	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
-	if (!sdvo_lvds_options)
-		return;
+	index = i915_vbt_sdvo_panel_type;
+	if (index == -1) {
+		struct bdb_sdvo_lvds_options *sdvo_lvds_options;
+
+		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+		if (!sdvo_lvds_options)
+			return;
+
+		index = sdvo_lvds_options->panel_type;
+	}
 
 	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
 	if (!dvo_timing)
 		return;
 
 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
-
 	if (!panel_fixed_mode)
 		return;
 
-	fill_detail_timing_data(panel_fixed_mode,
-			dvo_timing + sdvo_lvds_options->panel_type);
+	fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);
 
 	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
 
-	return;
+	DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");
+	drm_mode_debug_printmodeline(panel_fixed_mode);
+}
+
+static int intel_bios_ssc_frequency(struct drm_device *dev,
+				    bool alternate)
+{
+	switch (INTEL_INFO(dev)->gen) {
+	case 2:
+		return alternate ? 66 : 48;
+	case 3:
+	case 4:
+		return alternate ? 100 : 96;
+	default:
+		return alternate ? 100 : 120;
+	}
 }
 
 static void
@@ -263,13 +283,8 @@ parse_general_features(struct drm_i915_private *dev_priv,
 		dev_priv->int_tv_support = general->int_tv_support;
 		dev_priv->int_crt_support = general->int_crt_support;
 		dev_priv->lvds_use_ssc = general->enable_ssc;
-
-		if (IS_I85X(dev))
-			dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
-		else if (IS_GEN5(dev) || IS_GEN6(dev))
-			dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 120;
-		else
-			dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+		dev_priv->lvds_ssc_freq =
+			intel_bios_ssc_frequency(dev, general->ssc_freq);
 	}
 }
 
@@ -553,6 +568,8 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
 static void
 init_vbt_defaults(struct drm_i915_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
+
 	dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
 
 	/* LFP panel data */
@@ -565,7 +582,11 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
 	/* general features */
 	dev_priv->int_tv_support = 1;
 	dev_priv->int_crt_support = 1;
-	dev_priv->lvds_use_ssc = 0;
+
+	/* Default to using SSC */
+	dev_priv->lvds_use_ssc = 1;
+	dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
+	DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
 
 	/* eDP data */
 	dev_priv->edp.bpp = 18;
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 8a77ff4..8342259 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -129,10 +129,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 	u32 adpa, dpll_md;
 	u32 adpa_reg;
 
-	if (intel_crtc->pipe == 0)
-		dpll_md_reg = DPLL_A_MD;
-	else
-		dpll_md_reg = DPLL_B_MD;
+	dpll_md_reg = DPLL_MD(intel_crtc->pipe);
 
 	if (HAS_PCH_SPLIT(dev))
 		adpa_reg = PCH_ADPA;
@@ -160,17 +157,16 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
 			adpa |= PORT_TRANS_A_SEL_CPT;
 		else
 			adpa |= ADPA_PIPE_A_SELECT;
-		if (!HAS_PCH_SPLIT(dev))
-			I915_WRITE(BCLRPAT_A, 0);
 	} else {
 		if (HAS_PCH_CPT(dev))
 			adpa |= PORT_TRANS_B_SEL_CPT;
 		else
 			adpa |= ADPA_PIPE_B_SELECT;
-		if (!HAS_PCH_SPLIT(dev))
-			I915_WRITE(BCLRPAT_B, 0);
 	}
 
+	if (!HAS_PCH_SPLIT(dev))
+		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
+
 	I915_WRITE(adpa_reg, adpa);
 }
 
@@ -353,21 +349,12 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_crt *crt)
 
 	DRM_DEBUG_KMS("starting load-detect on CRT\n");
 
-	if (pipe == 0) {
-		bclrpat_reg = BCLRPAT_A;
-		vtotal_reg = VTOTAL_A;
-		vblank_reg = VBLANK_A;
-		vsync_reg = VSYNC_A;
-		pipeconf_reg = PIPEACONF;
-		pipe_dsl_reg = PIPEADSL;
-	} else {
-		bclrpat_reg = BCLRPAT_B;
-		vtotal_reg = VTOTAL_B;
-		vblank_reg = VBLANK_B;
-		vsync_reg = VSYNC_B;
-		pipeconf_reg = PIPEBCONF;
-		pipe_dsl_reg = PIPEBDSL;
-	}
+	bclrpat_reg = BCLRPAT(pipe);
+	vtotal_reg = VTOTAL(pipe);
+	vblank_reg = VBLANK(pipe);
+	vsync_reg = VSYNC(pipe);
+	pipeconf_reg = PIPECONF(pipe);
+	pipe_dsl_reg = PIPEDSL(pipe);
 
 	save_bclrpat = I915_READ(bclrpat_reg);
 	save_vtotal = I915_READ(vtotal_reg);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 49fb54f..3106c0d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -989,7 +989,7 @@ intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc,
 void intel_wait_for_vblank(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT);
+	int pipestat_reg = PIPESTAT(pipe);
 
 	/* Clear existing vblank status. Note this will clear any other
 	 * sticky status fields as well.
@@ -1058,6 +1058,612 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)
 	}
 }
 
+static const char *state_string(bool enabled)
+{
+	return enabled ? "on" : "off";
+}
+
+/* Only for pre-ILK configs */
+static void assert_pll(struct drm_i915_private *dev_priv,
+		       enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = DPLL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & DPLL_VCO_ENABLE);
+	WARN(cur_state != state,
+	     "PLL state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_pll_enabled(d, p) assert_pll(d, p, true)
+#define assert_pll_disabled(d, p) assert_pll(d, p, false)
+
+/* For ILK+ */
+static void assert_pch_pll(struct drm_i915_private *dev_priv,
+			   enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = PCH_DPLL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & DPLL_VCO_ENABLE);
+	WARN(cur_state != state,
+	     "PCH PLL state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_pch_pll_enabled(d, p) assert_pch_pll(d, p, true)
+#define assert_pch_pll_disabled(d, p) assert_pch_pll(d, p, false)
+
+static void assert_fdi_tx(struct drm_i915_private *dev_priv,
+			  enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = FDI_TX_CTL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & FDI_TX_ENABLE);
+	WARN(cur_state != state,
+	     "FDI TX state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
+#define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
+
+static void assert_fdi_rx(struct drm_i915_private *dev_priv,
+			  enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = FDI_RX_CTL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & FDI_RX_ENABLE);
+	WARN(cur_state != state,
+	     "FDI RX state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
+#define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
+
+static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* ILK FDI PLL is always enabled */
+	if (dev_priv->info->gen == 5)
+		return;
+
+	reg = FDI_TX_CTL(pipe);
+	val = I915_READ(reg);
+	WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
+}
+
+static void assert_fdi_rx_pll_enabled(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	reg = FDI_RX_CTL(pipe);
+	val = I915_READ(reg);
+	WARN(!(val & FDI_RX_PLL_ENABLE), "FDI RX PLL assertion failure, should be active but is disabled\n");
+}
+
+static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
+				  enum pipe pipe)
+{
+	int pp_reg, lvds_reg;
+	u32 val;
+	enum pipe panel_pipe = PIPE_A;
+	bool locked = locked;
+
+	if (HAS_PCH_SPLIT(dev_priv->dev)) {
+		pp_reg = PCH_PP_CONTROL;
+		lvds_reg = PCH_LVDS;
+	} else {
+		pp_reg = PP_CONTROL;
+		lvds_reg = LVDS;
+	}
+
+	val = I915_READ(pp_reg);
+	if (!(val & PANEL_POWER_ON) ||
+	    ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS))
+		locked = false;
+
+	if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT)
+		panel_pipe = PIPE_B;
+
+	WARN(panel_pipe == pipe && locked,
+	     "panel assertion failure, pipe %c regs locked\n",
+	     pipe_name(pipe));
+}
+
+static void assert_pipe(struct drm_i915_private *dev_priv,
+			enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = PIPECONF(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & PIPECONF_ENABLE);
+	WARN(cur_state != state,
+	     "pipe %c assertion failure (expected %s, current %s)\n",
+	     pipe_name(pipe), state_string(state), state_string(cur_state));
+}
+#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
+#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
+
+static void assert_plane_enabled(struct drm_i915_private *dev_priv,
+				 enum plane plane)
+{
+	int reg;
+	u32 val;
+
+	reg = DSPCNTR(plane);
+	val = I915_READ(reg);
+	WARN(!(val & DISPLAY_PLANE_ENABLE),
+	     "plane %c assertion failure, should be active but is disabled\n",
+	     plane_name(plane));
+}
+
+static void assert_planes_disabled(struct drm_i915_private *dev_priv,
+				   enum pipe pipe)
+{
+	int reg, i;
+	u32 val;
+	int cur_pipe;
+
+	/* Planes are fixed to pipes on ILK+ */
+	if (HAS_PCH_SPLIT(dev_priv->dev))
+		return;
+
+	/* Need to check both planes against the pipe */
+	for (i = 0; i < 2; i++) {
+		reg = DSPCNTR(i);
+		val = I915_READ(reg);
+		cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
+			DISPPLANE_SEL_PIPE_SHIFT;
+		WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
+		     "plane %c assertion failure, should be off on pipe %c but is still active\n",
+		     plane_name(i), pipe_name(pipe));
+	}
+}
+
+static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+	bool enabled;
+
+	val = I915_READ(PCH_DREF_CONTROL);
+	enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
+			    DREF_SUPERSPREAD_SOURCE_MASK));
+	WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
+}
+
+static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
+				       enum pipe pipe)
+{
+	int reg;
+	u32 val;
+	bool enabled;
+
+	reg = TRANSCONF(pipe);
+	val = I915_READ(reg);
+	enabled = !!(val & TRANS_ENABLE);
+	WARN(enabled,
+	     "transcoder assertion failed, should be off on pipe %c but is still active\n",
+	     pipe_name(pipe));
+}
+
+static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
+				   enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	WARN(DP_PIPE_ENABLED(val, pipe),
+	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
+	     reg, pipe_name(pipe));
+}
+
+static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
+				     enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	WARN(HDMI_PIPE_ENABLED(val, pipe),
+	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
+	     reg, pipe_name(pipe));
+}
+
+static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B);
+	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C);
+	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D);
+
+	reg = PCH_ADPA;
+	val = I915_READ(reg);
+	WARN(ADPA_PIPE_ENABLED(val, pipe),
+	     "PCH VGA enabled on transcoder %c, should be disabled\n",
+	     pipe_name(pipe));
+
+	reg = PCH_LVDS;
+	val = I915_READ(reg);
+	WARN(LVDS_PIPE_ENABLED(val, pipe),
+	     "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);
+}
+
+/**
+ * intel_enable_pll - enable a PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * Enable @pipe's PLL so we can start pumping pixels from a plane.  Check to
+ * make sure the PLL reg is writable first though, since the panel write
+ * protect mechanism may be enabled.
+ *
+ * Note!  This is for pre-ILK only.
+ */
+static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* No really, not for ILK+ */
+	BUG_ON(dev_priv->info->gen >= 5);
+
+	/* PLL is protected by panel, make sure we can write it */
+	if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
+		assert_panel_unlocked(dev_priv, pipe);
+
+	reg = DPLL(pipe);
+	val = I915_READ(reg);
+	val |= DPLL_VCO_ENABLE;
+
+	/* We do this three times for luck */
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+}
+
+/**
+ * intel_disable_pll - disable a PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to disable
+ *
+ * Disable the PLL for @pipe, making sure the pipe is off first.
+ *
+ * Note!  This is for pre-ILK only.
+ */
+static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* Don't disable pipe A or pipe A PLLs if needed */
+	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+		return;
+
+	/* Make sure the pipe isn't still relying on us */
+	assert_pipe_disabled(dev_priv, pipe);
+
+	reg = DPLL(pipe);
+	val = I915_READ(reg);
+	val &= ~DPLL_VCO_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+}
+
+/**
+ * intel_enable_pch_pll - enable PCH PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * The PCH PLL needs to be enabled before the PCH transcoder, since it
+ * drives the transcoder clock.
+ */
+static void intel_enable_pch_pll(struct drm_i915_private *dev_priv,
+				 enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* PCH refclock must be enabled first */
+	assert_pch_refclk_enabled(dev_priv);
+
+	reg = PCH_DPLL(pipe);
+	val = I915_READ(reg);
+	val |= DPLL_VCO_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(200);
+}
+
+static void intel_disable_pch_pll(struct drm_i915_private *dev_priv,
+				  enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* Make sure transcoder isn't still depending on us */
+	assert_transcoder_disabled(dev_priv, pipe);
+
+	reg = PCH_DPLL(pipe);
+	val = I915_READ(reg);
+	val &= ~DPLL_VCO_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(200);
+}
+
+static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
+				    enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* Make sure PCH DPLL is enabled */
+	assert_pch_pll_enabled(dev_priv, pipe);
+
+	/* FDI must be feeding us bits for PCH ports */
+	assert_fdi_tx_enabled(dev_priv, pipe);
+	assert_fdi_rx_enabled(dev_priv, pipe);
+
+	reg = TRANSCONF(pipe);
+	val = I915_READ(reg);
+	/*
+	 * make the BPC in transcoder be consistent with
+	 * that in pipeconf reg.
+	 */
+	val &= ~PIPE_BPC_MASK;
+	val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+	I915_WRITE(reg, val | TRANS_ENABLE);
+	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
+		DRM_ERROR("failed to enable transcoder %d\n", pipe);
+}
+
+static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
+				     enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* FDI relies on the transcoder */
+	assert_fdi_tx_disabled(dev_priv, pipe);
+	assert_fdi_rx_disabled(dev_priv, pipe);
+
+	/* Ports must be off as well */
+	assert_pch_ports_disabled(dev_priv, pipe);
+
+	reg = TRANSCONF(pipe);
+	val = I915_READ(reg);
+	val &= ~TRANS_ENABLE;
+	I915_WRITE(reg, val);
+	/* wait for PCH transcoder off, transcoder state */
+	if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
+		DRM_ERROR("failed to disable transcoder\n");
+}
+
+/**
+ * intel_enable_pipe - enable a pipe, asserting requirements
+ * @dev_priv: i915 private structure
+ * @pipe: pipe to enable
+ * @pch_port: on ILK+, is this pipe driving a PCH port or not
+ *
+ * Enable @pipe, making sure that various hardware specific requirements
+ * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
+ *
+ * @pipe should be %PIPE_A or %PIPE_B.
+ *
+ * Will wait until the pipe is actually running (i.e. first vblank) before
+ * returning.
+ */
+static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
+			      bool pch_port)
+{
+	int reg;
+	u32 val;
+
+	/*
+	 * A pipe without a PLL won't actually be able to drive bits from
+	 * a plane.  On ILK+ the pipe PLLs are integrated, so we don't
+	 * need the check.
+	 */
+	if (!HAS_PCH_SPLIT(dev_priv->dev))
+		assert_pll_enabled(dev_priv, pipe);
+	else {
+		if (pch_port) {
+			/* if driving the PCH, we need FDI enabled */
+			assert_fdi_rx_pll_enabled(dev_priv, pipe);
+			assert_fdi_tx_pll_enabled(dev_priv, pipe);
+		}
+		/* FIXME: assert CPU port conditions for SNB+ */
+	}
+
+	reg = PIPECONF(pipe);
+	val = I915_READ(reg);
+	val |= PIPECONF_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
+}
+
+/**
+ * intel_disable_pipe - disable a pipe, asserting requirements
+ * @dev_priv: i915 private structure
+ * @pipe: pipe to disable
+ *
+ * Disable @pipe, making sure that various hardware specific requirements
+ * are met, if applicable, e.g. plane disabled, panel fitter off, etc.
+ *
+ * @pipe should be %PIPE_A or %PIPE_B.
+ *
+ * Will wait until the pipe has shut down before returning.
+ */
+static void intel_disable_pipe(struct drm_i915_private *dev_priv,
+			       enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/*
+	 * Make sure planes won't keep trying to pump pixels to us,
+	 * or we might hang the display.
+	 */
+	assert_planes_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))
+		return;
+
+	reg = PIPECONF(pipe);
+	val = I915_READ(reg);
+	val &= ~PIPECONF_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	intel_wait_for_pipe_off(dev_priv->dev, pipe);
+}
+
+/**
+ * intel_enable_plane - enable a display plane on a given pipe
+ * @dev_priv: i915 private structure
+ * @plane: plane to enable
+ * @pipe: pipe being fed
+ *
+ * Enable @plane on @pipe, making sure that @pipe is running first.
+ */
+static void intel_enable_plane(struct drm_i915_private *dev_priv,
+			       enum plane plane, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* If the pipe isn't enabled, we can't pump pixels and may hang */
+	assert_pipe_enabled(dev_priv, pipe);
+
+	reg = DSPCNTR(plane);
+	val = I915_READ(reg);
+	val |= DISPLAY_PLANE_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
+}
+
+/*
+ * Plane regs are double buffered, going from enabled->disabled needs a
+ * trigger in order to latch.  The display address reg provides this.
+ */
+static void intel_flush_display_plane(struct drm_i915_private *dev_priv,
+				      enum plane plane)
+{
+	u32 reg = DSPADDR(plane);
+	I915_WRITE(reg, I915_READ(reg));
+}
+
+/**
+ * intel_disable_plane - disable a display plane
+ * @dev_priv: i915 private structure
+ * @plane: plane to disable
+ * @pipe: pipe consuming the data
+ *
+ * Disable @plane; should be an independent operation.
+ */
+static void intel_disable_plane(struct drm_i915_private *dev_priv,
+				enum plane plane, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	reg = DSPCNTR(plane);
+	val = I915_READ(reg);
+	val &= ~DISPLAY_PLANE_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	intel_flush_display_plane(dev_priv, plane);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
+}
+
+static void disable_pch_dp(struct drm_i915_private *dev_priv,
+			   enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	if (DP_PIPE_ENABLED(val, pipe))
+		I915_WRITE(reg, val & ~DP_PORT_EN);
+}
+
+static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
+			     enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	if (HDMI_PIPE_ENABLED(val, pipe))
+		I915_WRITE(reg, val & ~PORT_ENABLE);
+}
+
+/* Disable any ports connected to this transcoder */
+static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
+				    enum pipe pipe)
+{
+	u32 reg, val;
+
+	val = I915_READ(PCH_PP_CONTROL);
+	I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS);
+
+	disable_pch_dp(dev_priv, pipe, PCH_DP_B);
+	disable_pch_dp(dev_priv, pipe, PCH_DP_C);
+	disable_pch_dp(dev_priv, pipe, PCH_DP_D);
+
+	reg = PCH_ADPA;
+	val = I915_READ(reg);
+	if (ADPA_PIPE_ENABLED(val, pipe))
+		I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
+
+	reg = PCH_LVDS;
+	val = I915_READ(reg);
+	if (LVDS_PIPE_ENABLED(val, pipe)) {
+		I915_WRITE(reg, val & ~LVDS_PORT_EN);
+		POSTING_READ(reg);
+		udelay(100);
+	}
+
+	disable_pch_hdmi(dev_priv, pipe, HDMIB);
+	disable_pch_hdmi(dev_priv, pipe, HDMIC);
+	disable_pch_hdmi(dev_priv, pipe, HDMID);
+}
+
 static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 {
 	struct drm_device *dev = crtc->dev;
@@ -1390,7 +1996,7 @@ static void intel_update_fbc(struct drm_device *dev)
 	 *   - going to an unsupported config (interlace, pixel multiply, etc.)
 	 */
 	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-		if (tmp_crtc->enabled) {
+		if (tmp_crtc->enabled && tmp_crtc->fb) {
 			if (crtc) {
 				DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
 				dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
@@ -1461,6 +2067,7 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
 			   struct drm_i915_gem_object *obj,
 			   struct intel_ring_buffer *pipelined)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 alignment;
 	int ret;
 
@@ -1485,9 +2092,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
 		BUG();
 	}
 
+	dev_priv->mm.interruptible = false;
 	ret = i915_gem_object_pin(obj, alignment, true);
 	if (ret)
-		return ret;
+		goto err_interruptible;
 
 	ret = i915_gem_object_set_to_display_plane(obj, pipelined);
 	if (ret)
@@ -1499,15 +2107,18 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
 	 * a fence as the cost is not that onerous.
 	 */
 	if (obj->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence(obj, pipelined, false);
+		ret = i915_gem_object_get_fence(obj, pipelined);
 		if (ret)
 			goto err_unpin;
 	}
 
+	dev_priv->mm.interruptible = true;
 	return 0;
 
 err_unpin:
 	i915_gem_object_unpin(obj);
+err_interruptible:
+	dev_priv->mm.interruptible = true;
 	return ret;
 }
 
@@ -1641,7 +2252,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
 		 * This should only fail upon a hung GPU, in which case we
 		 * can safely continue.
 		 */
-		ret = i915_gem_object_flush_gpu(obj, false);
+		ret = i915_gem_object_flush_gpu(obj);
 		(void) ret;
 	}
 
@@ -1753,8 +2364,13 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
+	int plane = intel_crtc->plane;
 	u32 reg, temp, tries;
 
+	/* FDI needs bits from pipe & plane first */
+	assert_pipe_enabled(dev_priv, pipe);
+	assert_plane_enabled(dev_priv, plane);
+
 	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
 	   for train result */
 	reg = FDI_RX_IMR(pipe);
@@ -1784,7 +2400,11 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 	udelay(150);
 
 	/* Ironlake workaround, enable clock pointer after FDI enable*/
-	I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_ENABLE);
+	if (HAS_PCH_IBX(dev)) {
+		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
+		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR |
+			   FDI_RX_PHASE_SYNC_POINTER_EN);
+	}
 
 	reg = FDI_RX_IIR(pipe);
 	for (tries = 0; tries < 5; tries++) {
@@ -1834,7 +2454,7 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc)
 
 }
 
-static const int const snb_b_fdi_train_param [] = {
+static const int snb_b_fdi_train_param [] = {
 	FDI_LINK_TRAIN_400MV_0DB_SNB_B,
 	FDI_LINK_TRAIN_400MV_6DB_SNB_B,
 	FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
@@ -2003,12 +2623,60 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc)
 	}
 }
 
-static void intel_flush_display_plane(struct drm_device *dev,
-				      int plane)
+static void ironlake_fdi_disable(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 reg = DSPADDR(plane);
-	I915_WRITE(reg, I915_READ(reg));
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	u32 reg, temp;
+
+	/* disable CPU FDI tx and PCH FDI rx */
+	reg = FDI_TX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
+	POSTING_READ(reg);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	temp &= ~(0x7 << 16);
+	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
+
+	POSTING_READ(reg);
+	udelay(100);
+
+	/* Ironlake workaround, disable clock pointer after downing FDI */
+	if (HAS_PCH_IBX(dev)) {
+		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
+		I915_WRITE(FDI_RX_CHICKEN(pipe),
+			   I915_READ(FDI_RX_CHICKEN(pipe) &
+				     ~FDI_RX_PHASE_SYNC_POINTER_EN));
+	}
+
+	/* still set train pattern 1 */
+	reg = FDI_TX_CTL(pipe);
+	temp = I915_READ(reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_1;
+	I915_WRITE(reg, temp);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	if (HAS_PCH_CPT(dev)) {
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+	}
+	/* BPC in FDI rx is consistent with that in PIPECONF */
+	temp &= ~(0x07 << 16);
+	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	I915_WRITE(reg, temp);
+
+	POSTING_READ(reg);
+	udelay(100);
 }
 
 /*
@@ -2070,114 +2738,21 @@ static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
 	return true;
 }
 
-static void ironlake_crtc_enable(struct drm_crtc *crtc)
+/*
+ * Enable PCH resources required for PCH ports:
+ *   - PCH PLLs
+ *   - FDI training & RX/TX
+ *   - update transcoder timings
+ *   - DP transcoding bits
+ *   - transcoder
+ */
+static void ironlake_pch_enable(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->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 plane = intel_crtc->plane;
 	u32 reg, temp;
-	bool is_pch_port = false;
-
-	if (intel_crtc->active)
-		return;
-
-	intel_crtc->active = true;
-	intel_update_watermarks(dev);
-
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		temp = I915_READ(PCH_LVDS);
-		if ((temp & LVDS_PORT_EN) == 0)
-			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
-	}
-
-	is_pch_port = intel_crtc_driving_pch(crtc);
-
-	if (is_pch_port)
-		ironlake_fdi_enable(crtc);
-	else {
-		/* disable CPU FDI tx and PCH FDI rx */
-		reg = FDI_TX_CTL(pipe);
-		temp = I915_READ(reg);
-		I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
-		POSTING_READ(reg);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = I915_READ(reg);
-		temp &= ~(0x7 << 16);
-		temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-		I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
-
-		POSTING_READ(reg);
-		udelay(100);
-
-		/* Ironlake workaround, disable clock pointer after downing FDI */
-		if (HAS_PCH_IBX(dev))
-			I915_WRITE(FDI_RX_CHICKEN(pipe),
-				   I915_READ(FDI_RX_CHICKEN(pipe) &
-					     ~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
-
-		/* still set train pattern 1 */
-		reg = FDI_TX_CTL(pipe);
-		temp = I915_READ(reg);
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_1;
-		I915_WRITE(reg, temp);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = I915_READ(reg);
-		if (HAS_PCH_CPT(dev)) {
-			temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-			temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-		} else {
-			temp &= ~FDI_LINK_TRAIN_NONE;
-			temp |= FDI_LINK_TRAIN_PATTERN_1;
-		}
-		/* BPC in FDI rx is consistent with that in PIPECONF */
-		temp &= ~(0x07 << 16);
-		temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-		I915_WRITE(reg, temp);
-
-		POSTING_READ(reg);
-		udelay(100);
-	}
-
-	/* Enable panel fitting for LVDS */
-	if (dev_priv->pch_pf_size &&
-	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
-		/* Force use of hard-coded filter coefficients
-		 * as some pre-programmed values are broken,
-		 * e.g. x201.
-		 */
-		I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1,
-			   PF_ENABLE | PF_FILTER_MED_3x3);
-		I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS,
-			   dev_priv->pch_pf_pos);
-		I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ,
-			   dev_priv->pch_pf_size);
-	}
-
-	/* Enable CPU pipe */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if ((temp & PIPECONF_ENABLE) == 0) {
-		I915_WRITE(reg, temp | PIPECONF_ENABLE);
-		POSTING_READ(reg);
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
-	}
-
-	/* configure and enable CPU plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-		I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
-		intel_flush_display_plane(dev, plane);
-	}
-
-	/* Skip the PCH stuff if possible */
-	if (!is_pch_port)
-		goto done;
 
 	/* For PCH output, training FDI link */
 	if (IS_GEN6(dev))
@@ -2185,14 +2760,7 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 	else
 		ironlake_fdi_link_train(crtc);
 
-	/* enable PCH DPLL */
-	reg = PCH_DPLL(pipe);
-	temp = I915_READ(reg);
-	if ((temp & DPLL_VCO_ENABLE) == 0) {
-		I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-		POSTING_READ(reg);
-		udelay(200);
-	}
+	intel_enable_pch_pll(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
 		/* Be sure PCH DPLL SEL is set */
@@ -2204,7 +2772,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
-	/* set transcoder timing */
+	/* set transcoder timing, panel must allow it */
+	assert_panel_unlocked(dev_priv, pipe);
 	I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe)));
 	I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe)));
 	I915_WRITE(TRANS_HSYNC(pipe),  I915_READ(HSYNC(pipe)));
@@ -2251,19 +2820,56 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 		I915_WRITE(reg, temp);
 	}
 
-	/* enable PCH transcoder */
-	reg = TRANSCONF(pipe);
-	temp = I915_READ(reg);
-	/*
-	 * make the BPC in transcoder be consistent with
-	 * that in pipeconf reg.
-	 */
-	temp &= ~PIPE_BPC_MASK;
-	temp |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
-	I915_WRITE(reg, temp | TRANS_ENABLE);
-	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
-		DRM_ERROR("failed to enable transcoder %d\n", pipe);
-done:
+	intel_enable_transcoder(dev_priv, pipe);
+}
+
+static void ironlake_crtc_enable(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->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 plane = intel_crtc->plane;
+	u32 temp;
+	bool is_pch_port;
+
+	if (intel_crtc->active)
+		return;
+
+	intel_crtc->active = true;
+	intel_update_watermarks(dev);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		temp = I915_READ(PCH_LVDS);
+		if ((temp & LVDS_PORT_EN) == 0)
+			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
+	}
+
+	is_pch_port = intel_crtc_driving_pch(crtc);
+
+	if (is_pch_port)
+		ironlake_fdi_enable(crtc);
+	else
+		ironlake_fdi_disable(crtc);
+
+	/* Enable panel fitting for LVDS */
+	if (dev_priv->pch_pf_size &&
+	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
+		/* Force use of hard-coded filter coefficients
+		 * as some pre-programmed values are broken,
+		 * e.g. x201.
+		 */
+		I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
+		I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
+		I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
+	}
+
+	intel_enable_pipe(dev_priv, pipe, is_pch_port);
+	intel_enable_plane(dev_priv, plane, pipe);
+
+	if (is_pch_port)
+		ironlake_pch_enable(crtc);
+
 	intel_crtc_load_lut(crtc);
 	intel_update_fbc(dev);
 	intel_crtc_update_cursor(crtc, true);
@@ -2285,116 +2891,58 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
 
-	/* Disable display plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if (temp & DISPLAY_PLANE_ENABLE) {
-		I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
-		intel_flush_display_plane(dev, plane);
-	}
+	intel_disable_plane(dev_priv, plane, pipe);
 
 	if (dev_priv->cfb_plane == plane &&
 	    dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
 
-	/* disable cpu pipe, disable after all planes disabled */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if (temp & PIPECONF_ENABLE) {
-		I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
-		POSTING_READ(reg);
-		/* wait for cpu pipe off, pipe state */
-		intel_wait_for_pipe_off(dev, intel_crtc->pipe);
-	}
+	intel_disable_pipe(dev_priv, pipe);
 
 	/* Disable PF */
-	I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
-	I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0);
-
-	/* disable CPU FDI tx and PCH FDI rx */
-	reg = FDI_TX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
-	POSTING_READ(reg);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	temp &= ~(0x7 << 16);
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-	I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
-
-	POSTING_READ(reg);
-	udelay(100);
-
-	/* Ironlake workaround, disable clock pointer after downing FDI */
-	if (HAS_PCH_IBX(dev))
-		I915_WRITE(FDI_RX_CHICKEN(pipe),
-			   I915_READ(FDI_RX_CHICKEN(pipe) &
-				     ~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
-
-	/* still set train pattern 1 */
-	reg = FDI_TX_CTL(pipe);
-	temp = I915_READ(reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_1;
-	I915_WRITE(reg, temp);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	if (HAS_PCH_CPT(dev)) {
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_1;
-	}
-	/* BPC in FDI rx is consistent with that in PIPECONF */
-	temp &= ~(0x07 << 16);
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-	I915_WRITE(reg, temp);
+	I915_WRITE(PF_CTL(pipe), 0);
+	I915_WRITE(PF_WIN_SZ(pipe), 0);
 
-	POSTING_READ(reg);
-	udelay(100);
+	ironlake_fdi_disable(crtc);
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		temp = I915_READ(PCH_LVDS);
-		if (temp & LVDS_PORT_EN) {
-			I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
-			POSTING_READ(PCH_LVDS);
-			udelay(100);
-		}
-	}
+	/* This is a horrible layering violation; we should be doing this in
+	 * the connector/encoder ->prepare instead, but we don't always have
+	 * enough information there about the config to know whether it will
+	 * actually be necessary or just cause undesired flicker.
+	 */
+	intel_disable_pch_ports(dev_priv, pipe);
 
-	/* disable PCH transcoder */
-	reg = TRANSCONF(plane);
-	temp = I915_READ(reg);
-	if (temp & TRANS_ENABLE) {
-		I915_WRITE(reg, temp & ~TRANS_ENABLE);
-		/* wait for PCH transcoder off, transcoder state */
-		if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
-			DRM_ERROR("failed to disable transcoder\n");
-	}
+	intel_disable_transcoder(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
 		/* disable TRANS_DP_CTL */
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
+		temp |= TRANS_DP_PORT_SEL_NONE;
 		I915_WRITE(reg, temp);
 
 		/* disable DPLL_SEL */
 		temp = I915_READ(PCH_DPLL_SEL);
-		if (pipe == 0)
-			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
-		else
+		switch (pipe) {
+		case 0:
+			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
+			break;
+		case 1:
 			temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
+			break;
+		case 2:
+			/* FIXME: manage transcoder PLLs? */
+			temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
+			break;
+		default:
+			BUG(); /* wtf */
+		}
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
 	/* disable PCH DPLL */
-	reg = PCH_DPLL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
+	intel_disable_pch_pll(dev_priv, pipe);
 
 	/* Switch from PCDclk to Rawclk */
 	reg = FDI_RX_CTL(pipe);
@@ -2451,9 +2999,12 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
 {
 	if (!enable && intel_crtc->overlay) {
 		struct drm_device *dev = intel_crtc->base.dev;
+		struct drm_i915_private *dev_priv = dev->dev_private;
 
 		mutex_lock(&dev->struct_mutex);
-		(void) intel_overlay_switch_off(intel_crtc->overlay, false);
+		dev_priv->mm.interruptible = false;
+		(void) intel_overlay_switch_off(intel_crtc->overlay);
+		dev_priv->mm.interruptible = true;
 		mutex_unlock(&dev->struct_mutex);
 	}
 
@@ -2469,7 +3020,6 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
-	u32 reg, temp;
 
 	if (intel_crtc->active)
 		return;
@@ -2477,42 +3027,9 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
 
-	/* Enable the DPLL */
-	reg = DPLL(pipe);
-	temp = I915_READ(reg);
-	if ((temp & DPLL_VCO_ENABLE) == 0) {
-		I915_WRITE(reg, temp);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(reg);
-		udelay(150);
-
-		I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(reg);
-		udelay(150);
-
-		I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(reg);
-		udelay(150);
-	}
-
-	/* Enable the pipe */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if ((temp & PIPECONF_ENABLE) == 0)
-		I915_WRITE(reg, temp | PIPECONF_ENABLE);
-
-	/* Enable the plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-		I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
-		intel_flush_display_plane(dev, plane);
-	}
+	intel_enable_pll(dev_priv, pipe);
+	intel_enable_pipe(dev_priv, pipe, false);
+	intel_enable_plane(dev_priv, plane, pipe);
 
 	intel_crtc_load_lut(crtc);
 	intel_update_fbc(dev);
@@ -2529,7 +3046,6 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
-	u32 reg, temp;
 
 	if (!intel_crtc->active)
 		return;
@@ -2544,45 +3060,10 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc)
 	    dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
 
-	/* Disable display plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if (temp & DISPLAY_PLANE_ENABLE) {
-		I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
-		/* Flush the plane changes */
-		intel_flush_display_plane(dev, plane);
-
-		/* Wait for vblank for the disable to take effect */
-		if (IS_GEN2(dev))
-			intel_wait_for_vblank(dev, pipe);
-	}
-
-	/* Don't disable pipe A or pipe A PLLs if needed */
-	if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
-		goto done;
-
-	/* Next, disable display pipes */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if (temp & PIPECONF_ENABLE) {
-		I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
-
-		/* Wait for the pipe to turn off */
-		POSTING_READ(reg);
-		intel_wait_for_pipe_off(dev, pipe);
-	}
-
-	reg = DPLL(pipe);
-	temp = I915_READ(reg);
-	if (temp & DPLL_VCO_ENABLE) {
-		I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
-
-		/* Wait for the clocks to turn off. */
-		POSTING_READ(reg);
-		udelay(150);
-	}
+	intel_disable_plane(dev_priv, plane, pipe);
+	intel_disable_pipe(dev_priv, pipe);
+	intel_disable_pll(dev_priv, pipe);
 
-done:
 	intel_crtc->active = false;
 	intel_update_fbc(dev);
 	intel_update_watermarks(dev);
@@ -2644,7 +3125,7 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
 		master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
 		break;
 	default:
-		DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+		DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe));
 		break;
 	}
 }
@@ -2841,77 +3322,77 @@ struct intel_watermark_params {
 };
 
 /* Pineview has different values for various configs */
-static struct intel_watermark_params pineview_display_wm = {
+static const struct intel_watermark_params pineview_display_wm = {
 	PINEVIEW_DISPLAY_FIFO,
 	PINEVIEW_MAX_WM,
 	PINEVIEW_DFT_WM,
 	PINEVIEW_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params pineview_display_hplloff_wm = {
+static const struct intel_watermark_params pineview_display_hplloff_wm = {
 	PINEVIEW_DISPLAY_FIFO,
 	PINEVIEW_MAX_WM,
 	PINEVIEW_DFT_HPLLOFF_WM,
 	PINEVIEW_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params pineview_cursor_wm = {
+static const struct intel_watermark_params pineview_cursor_wm = {
 	PINEVIEW_CURSOR_FIFO,
 	PINEVIEW_CURSOR_MAX_WM,
 	PINEVIEW_CURSOR_DFT_WM,
 	PINEVIEW_CURSOR_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params pineview_cursor_hplloff_wm = {
+static const struct intel_watermark_params pineview_cursor_hplloff_wm = {
 	PINEVIEW_CURSOR_FIFO,
 	PINEVIEW_CURSOR_MAX_WM,
 	PINEVIEW_CURSOR_DFT_WM,
 	PINEVIEW_CURSOR_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params g4x_wm_info = {
+static const struct intel_watermark_params g4x_wm_info = {
 	G4X_FIFO_SIZE,
 	G4X_MAX_WM,
 	G4X_MAX_WM,
 	2,
 	G4X_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params g4x_cursor_wm_info = {
+static const struct intel_watermark_params g4x_cursor_wm_info = {
 	I965_CURSOR_FIFO,
 	I965_CURSOR_MAX_WM,
 	I965_CURSOR_DFT_WM,
 	2,
 	G4X_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params i965_cursor_wm_info = {
+static const struct intel_watermark_params i965_cursor_wm_info = {
 	I965_CURSOR_FIFO,
 	I965_CURSOR_MAX_WM,
 	I965_CURSOR_DFT_WM,
 	2,
 	I915_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params i945_wm_info = {
+static const struct intel_watermark_params i945_wm_info = {
 	I945_FIFO_SIZE,
 	I915_MAX_WM,
 	1,
 	2,
 	I915_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params i915_wm_info = {
+static const struct intel_watermark_params i915_wm_info = {
 	I915_FIFO_SIZE,
 	I915_MAX_WM,
 	1,
 	2,
 	I915_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params i855_wm_info = {
+static const struct intel_watermark_params i855_wm_info = {
 	I855GM_FIFO_SIZE,
 	I915_MAX_WM,
 	1,
 	2,
 	I830_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params i830_wm_info = {
+static const struct intel_watermark_params i830_wm_info = {
 	I830_FIFO_SIZE,
 	I915_MAX_WM,
 	1,
@@ -2919,31 +3400,28 @@ static struct intel_watermark_params i830_wm_info = {
 	I830_FIFO_LINE_SIZE
 };
 
-static struct intel_watermark_params ironlake_display_wm_info = {
+static const struct intel_watermark_params ironlake_display_wm_info = {
 	ILK_DISPLAY_FIFO,
 	ILK_DISPLAY_MAXWM,
 	ILK_DISPLAY_DFTWM,
 	2,
 	ILK_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params ironlake_cursor_wm_info = {
+static const struct intel_watermark_params ironlake_cursor_wm_info = {
 	ILK_CURSOR_FIFO,
 	ILK_CURSOR_MAXWM,
 	ILK_CURSOR_DFTWM,
 	2,
 	ILK_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params ironlake_display_srwm_info = {
+static const struct intel_watermark_params ironlake_display_srwm_info = {
 	ILK_DISPLAY_SR_FIFO,
 	ILK_DISPLAY_MAX_SRWM,
 	ILK_DISPLAY_DFT_SRWM,
 	2,
 	ILK_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params ironlake_cursor_srwm_info = {
+static const struct intel_watermark_params ironlake_cursor_srwm_info = {
 	ILK_CURSOR_SR_FIFO,
 	ILK_CURSOR_MAX_SRWM,
 	ILK_CURSOR_DFT_SRWM,
@@ -2951,31 +3429,28 @@ static struct intel_watermark_params ironlake_cursor_srwm_info = {
 	ILK_FIFO_LINE_SIZE
 };
 
-static struct intel_watermark_params sandybridge_display_wm_info = {
+static const struct intel_watermark_params sandybridge_display_wm_info = {
 	SNB_DISPLAY_FIFO,
 	SNB_DISPLAY_MAXWM,
 	SNB_DISPLAY_DFTWM,
 	2,
 	SNB_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params sandybridge_cursor_wm_info = {
+static const struct intel_watermark_params sandybridge_cursor_wm_info = {
 	SNB_CURSOR_FIFO,
 	SNB_CURSOR_MAXWM,
 	SNB_CURSOR_DFTWM,
 	2,
 	SNB_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params sandybridge_display_srwm_info = {
+static const struct intel_watermark_params sandybridge_display_srwm_info = {
 	SNB_DISPLAY_SR_FIFO,
 	SNB_DISPLAY_MAX_SRWM,
 	SNB_DISPLAY_DFT_SRWM,
 	2,
 	SNB_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params sandybridge_cursor_srwm_info = {
+static const struct intel_watermark_params sandybridge_cursor_srwm_info = {
 	SNB_CURSOR_SR_FIFO,
 	SNB_CURSOR_MAX_SRWM,
 	SNB_CURSOR_DFT_SRWM,
@@ -3003,7 +3478,8 @@ static struct intel_watermark_params sandybridge_cursor_srwm_info = {
  * will occur, and a display engine hang could result.
  */
 static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
-					struct intel_watermark_params *wm,
+					const struct intel_watermark_params *wm,
+					int fifo_size,
 					int pixel_size,
 					unsigned long latency_ns)
 {
@@ -3021,7 +3497,7 @@ static unsigned long intel_calculate_wm(unsigned long clock_in_khz,
 
 	DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required);
 
-	wm_size = wm->fifo_size - (entries_required + wm->guard_size);
+	wm_size = fifo_size - (entries_required + wm->guard_size);
 
 	DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size);
 
@@ -3194,15 +3670,28 @@ static int i830_get_fifo_size(struct drm_device *dev, int plane)
 	return size;
 }
 
-static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
-			       int planeb_clock, int sr_hdisplay, int unused,
-			       int pixel_size)
+static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
+{
+	struct drm_crtc *crtc, *enabled = NULL;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc->enabled && crtc->fb) {
+			if (enabled)
+				return NULL;
+			enabled = crtc;
+		}
+	}
+
+	return enabled;
+}
+
+static void pineview_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
 	const struct cxsr_latency *latency;
 	u32 reg;
 	unsigned long wm;
-	int sr_clock;
 
 	latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
 					 dev_priv->fsb_freq, dev_priv->mem_freq);
@@ -3212,11 +3701,14 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
 		return;
 	}
 
-	if (!planea_clock || !planeb_clock) {
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
+	crtc = single_enabled_crtc(dev);
+	if (crtc) {
+		int clock = crtc->mode.clock;
+		int pixel_size = crtc->fb->bits_per_pixel / 8;
 
 		/* Display SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_display_wm,
+		wm = intel_calculate_wm(clock, &pineview_display_wm,
+					pineview_display_wm.fifo_size,
 					pixel_size, latency->display_sr);
 		reg = I915_READ(DSPFW1);
 		reg &= ~DSPFW_SR_MASK;
@@ -3225,7 +3717,8 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
 		DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
 
 		/* cursor SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_cursor_wm,
+		wm = intel_calculate_wm(clock, &pineview_cursor_wm,
+					pineview_display_wm.fifo_size,
 					pixel_size, latency->cursor_sr);
 		reg = I915_READ(DSPFW3);
 		reg &= ~DSPFW_CURSOR_SR_MASK;
@@ -3233,7 +3726,8 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
 		I915_WRITE(DSPFW3, reg);
 
 		/* Display HPLL off SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_display_hplloff_wm,
+		wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
+					pineview_display_hplloff_wm.fifo_size,
 					pixel_size, latency->display_hpll_disable);
 		reg = I915_READ(DSPFW3);
 		reg &= ~DSPFW_HPLL_SR_MASK;
@@ -3241,7 +3735,8 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
 		I915_WRITE(DSPFW3, reg);
 
 		/* cursor HPLL off SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_cursor_hplloff_wm,
+		wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm,
+					pineview_display_hplloff_wm.fifo_size,
 					pixel_size, latency->cursor_hpll_disable);
 		reg = I915_READ(DSPFW3);
 		reg &= ~DSPFW_HPLL_CURSOR_MASK;
@@ -3259,125 +3754,229 @@ static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
 	}
 }
 
-static void g4x_update_wm(struct drm_device *dev,  int planea_clock,
-			  int planeb_clock, int sr_hdisplay, int sr_htotal,
-			  int pixel_size)
+static bool g4x_compute_wm0(struct drm_device *dev,
+			    int plane,
+			    const struct intel_watermark_params *display,
+			    int display_latency_ns,
+			    const struct intel_watermark_params *cursor,
+			    int cursor_latency_ns,
+			    int *plane_wm,
+			    int *cursor_wm)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int total_size, cacheline_size;
-	int planea_wm, planeb_wm, cursora_wm, cursorb_wm, cursor_sr;
-	struct intel_watermark_params planea_params, planeb_params;
-	unsigned long line_time_us;
-	int sr_clock, sr_entries = 0, entries_required;
+	struct drm_crtc *crtc;
+	int htotal, hdisplay, clock, pixel_size;
+	int line_time_us, line_count;
+	int entries, tlb_miss;
 
-	/* Create copies of the base settings for each pipe */
-	planea_params = planeb_params = g4x_wm_info;
+	crtc = intel_get_crtc_for_plane(dev, plane);
+	if (crtc->fb == NULL || !crtc->enabled)
+		return false;
 
-	/* Grab a couple of global values before we overwrite them */
-	total_size = planea_params.fifo_size;
-	cacheline_size = planea_params.cacheline_size;
+	htotal = crtc->mode.htotal;
+	hdisplay = crtc->mode.hdisplay;
+	clock = crtc->mode.clock;
+	pixel_size = crtc->fb->bits_per_pixel / 8;
 
-	/*
-	 * Note: we need to make sure we don't overflow for various clock &
-	 * latency values.
-	 * clocks go from a few thousand to several hundred thousand.
-	 * latency is usually a few thousand
-	 */
-	entries_required = ((planea_clock / 1000) * pixel_size * latency_ns) /
-		1000;
-	entries_required = DIV_ROUND_UP(entries_required, G4X_FIFO_LINE_SIZE);
-	planea_wm = entries_required + planea_params.guard_size;
+	/* Use the small buffer method to calculate plane watermark */
+	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
+	tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
+	if (tlb_miss > 0)
+		entries += tlb_miss;
+	entries = DIV_ROUND_UP(entries, display->cacheline_size);
+	*plane_wm = entries + display->guard_size;
+	if (*plane_wm > (int)display->max_wm)
+		*plane_wm = display->max_wm;
 
-	entries_required = ((planeb_clock / 1000) * pixel_size * latency_ns) /
-		1000;
-	entries_required = DIV_ROUND_UP(entries_required, G4X_FIFO_LINE_SIZE);
-	planeb_wm = entries_required + planeb_params.guard_size;
+	/* Use the large buffer method to calculate cursor watermark */
+	line_time_us = ((htotal * 1000) / clock);
+	line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
+	entries = line_count * 64 * pixel_size;
+	tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
+	if (tlb_miss > 0)
+		entries += tlb_miss;
+	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+	*cursor_wm = entries + cursor->guard_size;
+	if (*cursor_wm > (int)cursor->max_wm)
+		*cursor_wm = (int)cursor->max_wm;
 
-	cursora_wm = cursorb_wm = 16;
-	cursor_sr = 32;
+	return true;
+}
 
-	DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+/*
+ * Check the wm result.
+ *
+ * If any calculated watermark values is larger than the maximum value that
+ * can be programmed into the associated watermark register, that watermark
+ * must be disabled.
+ */
+static bool g4x_check_srwm(struct drm_device *dev,
+			   int display_wm, int cursor_wm,
+			   const struct intel_watermark_params *display,
+			   const struct intel_watermark_params *cursor)
+{
+	DRM_DEBUG_KMS("SR watermark: display plane %d, cursor %d\n",
+		      display_wm, cursor_wm);
 
-	/* Calc sr entries for one plane configs */
-	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
-		/* self-refresh has much higher latency */
-		static const int sr_latency_ns = 12000;
+	if (display_wm > display->max_wm) {
+		DRM_DEBUG_KMS("display watermark is too large(%d), disabling\n",
+			      display_wm, display->max_wm);
+		return false;
+	}
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = ((sr_htotal * 1000) / sr_clock);
+	if (cursor_wm > cursor->max_wm) {
+		DRM_DEBUG_KMS("cursor watermark is too large(%d), disabling\n",
+			      cursor_wm, cursor->max_wm);
+		return false;
+	}
 
-		/* Use ns/us then divide to preserve precision */
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			pixel_size * sr_hdisplay;
-		sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size);
-
-		entries_required = (((sr_latency_ns / line_time_us) +
-				     1000) / 1000) * pixel_size * 64;
-		entries_required = DIV_ROUND_UP(entries_required,
-						g4x_cursor_wm_info.cacheline_size);
-		cursor_sr = entries_required + g4x_cursor_wm_info.guard_size;
-
-		if (cursor_sr > g4x_cursor_wm_info.max_wm)
-			cursor_sr = g4x_cursor_wm_info.max_wm;
-		DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
-			      "cursor %d\n", sr_entries, cursor_sr);
+	if (!(display_wm || cursor_wm)) {
+		DRM_DEBUG_KMS("SR latency is 0, disabling\n");
+		return false;
+	}
 
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
-	} else {
-		/* Turn off self refresh if both pipes are enabled */
-		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-			   & ~FW_BLC_SELF_EN);
+	return true;
+}
+
+static bool g4x_compute_srwm(struct drm_device *dev,
+			     int plane,
+			     int latency_ns,
+			     const struct intel_watermark_params *display,
+			     const struct intel_watermark_params *cursor,
+			     int *display_wm, int *cursor_wm)
+{
+	struct drm_crtc *crtc;
+	int hdisplay, htotal, pixel_size, clock;
+	unsigned long line_time_us;
+	int line_count, line_size;
+	int small, large;
+	int entries;
+
+	if (!latency_ns) {
+		*display_wm = *cursor_wm = 0;
+		return false;
 	}
 
-	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
-		  planea_wm, planeb_wm, sr_entries);
+	crtc = intel_get_crtc_for_plane(dev, plane);
+	hdisplay = crtc->mode.hdisplay;
+	htotal = crtc->mode.htotal;
+	clock = crtc->mode.clock;
+	pixel_size = crtc->fb->bits_per_pixel / 8;
+
+	line_time_us = (htotal * 1000) / clock;
+	line_count = (latency_ns / line_time_us + 1000) / 1000;
+	line_size = hdisplay * pixel_size;
+
+	/* Use the minimum of the small and large buffer method for primary */
+	small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
+	large = line_count * line_size;
+
+	entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
+	*display_wm = entries + display->guard_size;
+
+	/* calculate the self-refresh watermark for display cursor */
+	entries = line_count * pixel_size * 64;
+	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+	*cursor_wm = entries + cursor->guard_size;
+
+	return g4x_check_srwm(dev,
+			      *display_wm, *cursor_wm,
+			      display, cursor);
+}
+
+static inline bool single_plane_enabled(unsigned int mask)
+{
+	return mask && (mask & -mask) == 0;
+}
 
-	planea_wm &= 0x3f;
-	planeb_wm &= 0x3f;
+static void g4x_update_wm(struct drm_device *dev)
+{
+	static const int sr_latency_ns = 12000;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
+	int plane_sr, cursor_sr;
+	unsigned int enabled = 0;
+
+	if (g4x_compute_wm0(dev, 0,
+			    &g4x_wm_info, latency_ns,
+			    &g4x_cursor_wm_info, latency_ns,
+			    &planea_wm, &cursora_wm))
+		enabled |= 1;
+
+	if (g4x_compute_wm0(dev, 1,
+			    &g4x_wm_info, latency_ns,
+			    &g4x_cursor_wm_info, latency_ns,
+			    &planeb_wm, &cursorb_wm))
+		enabled |= 2;
+
+	plane_sr = cursor_sr = 0;
+	if (single_plane_enabled(enabled) &&
+	    g4x_compute_srwm(dev, ffs(enabled) - 1,
+			     sr_latency_ns,
+			     &g4x_wm_info,
+			     &g4x_cursor_wm_info,
+			     &plane_sr, &cursor_sr))
+		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	else
+		I915_WRITE(FW_BLC_SELF,
+			   I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
 
-	I915_WRITE(DSPFW1, (sr_entries << DSPFW_SR_SHIFT) |
+	DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
+		      planea_wm, cursora_wm,
+		      planeb_wm, cursorb_wm,
+		      plane_sr, cursor_sr);
+
+	I915_WRITE(DSPFW1,
+		   (plane_sr << DSPFW_SR_SHIFT) |
 		   (cursorb_wm << DSPFW_CURSORB_SHIFT) |
-		   (planeb_wm << DSPFW_PLANEB_SHIFT) | planea_wm);
-	I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
+		   (planeb_wm << DSPFW_PLANEB_SHIFT) |
+		   planea_wm);
+	I915_WRITE(DSPFW2,
+		   (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
 		   (cursora_wm << DSPFW_CURSORA_SHIFT));
 	/* HPLL off in SR has some issues on G4x... disable it */
-	I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
+	I915_WRITE(DSPFW3,
+		   (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i965_update_wm(struct drm_device *dev, int planea_clock,
-			   int planeb_clock, int sr_hdisplay, int sr_htotal,
-			   int pixel_size)
+static void i965_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long line_time_us;
-	int sr_clock, sr_entries, srwm = 1;
+	struct drm_crtc *crtc;
+	int srwm = 1;
 	int cursor_sr = 16;
 
 	/* Calc sr entries for one plane configs */
-	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+	crtc = single_enabled_crtc(dev);
+	if (crtc) {
 		/* self-refresh has much higher latency */
 		static const int sr_latency_ns = 12000;
+		int clock = crtc->mode.clock;
+		int htotal = crtc->mode.htotal;
+		int hdisplay = crtc->mode.hdisplay;
+		int pixel_size = crtc->fb->bits_per_pixel / 8;
+		unsigned long line_time_us;
+		int entries;
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = ((sr_htotal * 1000) / sr_clock);
+		line_time_us = ((htotal * 1000) / clock);
 
 		/* Use ns/us then divide to preserve precision */
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			pixel_size * sr_hdisplay;
-		sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE);
-		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
-		srwm = I965_FIFO_SIZE - sr_entries;
+		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+			pixel_size * hdisplay;
+		entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE);
+		srwm = I965_FIFO_SIZE - entries;
 		if (srwm < 0)
 			srwm = 1;
 		srwm &= 0x1ff;
+		DRM_DEBUG_KMS("self-refresh entries: %d, wm: %d\n",
+			      entries, srwm);
 
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
 			pixel_size * 64;
-		sr_entries = DIV_ROUND_UP(sr_entries,
+		entries = DIV_ROUND_UP(entries,
 					  i965_cursor_wm_info.cacheline_size);
 		cursor_sr = i965_cursor_wm_info.fifo_size -
-			(sr_entries + i965_cursor_wm_info.guard_size);
+			(entries + i965_cursor_wm_info.guard_size);
 
 		if (cursor_sr > i965_cursor_wm_info.max_wm)
 			cursor_sr = i965_cursor_wm_info.max_wm;
@@ -3398,46 +3997,56 @@ static void i965_update_wm(struct drm_device *dev, int planea_clock,
 		      srwm);
 
 	/* 965 has limitations... */
-	I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) |
-		   (8 << 0));
+	I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) |
+		   (8 << 16) | (8 << 8) | (8 << 0));
 	I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
 	/* update cursor SR watermark */
 	I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
-			   int planeb_clock, int sr_hdisplay, int sr_htotal,
-			   int pixel_size)
+static void i9xx_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	const struct intel_watermark_params *wm_info;
 	uint32_t fwater_lo;
 	uint32_t fwater_hi;
-	int total_size, cacheline_size, cwm, srwm = 1;
+	int cwm, srwm = 1;
+	int fifo_size;
 	int planea_wm, planeb_wm;
-	struct intel_watermark_params planea_params, planeb_params;
-	unsigned long line_time_us;
-	int sr_clock, sr_entries = 0;
+	struct drm_crtc *crtc, *enabled = NULL;
 
-	/* Create copies of the base settings for each pipe */
-	if (IS_CRESTLINE(dev) || IS_I945GM(dev))
-		planea_params = planeb_params = i945_wm_info;
+	if (IS_I945GM(dev))
+		wm_info = &i945_wm_info;
 	else if (!IS_GEN2(dev))
-		planea_params = planeb_params = i915_wm_info;
+		wm_info = &i915_wm_info;
 	else
-		planea_params = planeb_params = i855_wm_info;
-
-	/* Grab a couple of global values before we overwrite them */
-	total_size = planea_params.fifo_size;
-	cacheline_size = planea_params.cacheline_size;
-
-	/* Update per-plane FIFO sizes */
-	planea_params.fifo_size = dev_priv->display.get_fifo_size(dev, 0);
-	planeb_params.fifo_size = dev_priv->display.get_fifo_size(dev, 1);
+		wm_info = &i855_wm_info;
+
+	fifo_size = dev_priv->display.get_fifo_size(dev, 0);
+	crtc = intel_get_crtc_for_plane(dev, 0);
+	if (crtc->enabled && crtc->fb) {
+		planea_wm = intel_calculate_wm(crtc->mode.clock,
+					       wm_info, fifo_size,
+					       crtc->fb->bits_per_pixel / 8,
+					       latency_ns);
+		enabled = crtc;
+	} else
+		planea_wm = fifo_size - wm_info->guard_size;
+
+	fifo_size = dev_priv->display.get_fifo_size(dev, 1);
+	crtc = intel_get_crtc_for_plane(dev, 1);
+	if (crtc->enabled && crtc->fb) {
+		planeb_wm = intel_calculate_wm(crtc->mode.clock,
+					       wm_info, fifo_size,
+					       crtc->fb->bits_per_pixel / 8,
+					       latency_ns);
+		if (enabled == NULL)
+			enabled = crtc;
+		else
+			enabled = NULL;
+	} else
+		planeb_wm = fifo_size - wm_info->guard_size;
 
-	planea_wm = intel_calculate_wm(planea_clock, &planea_params,
-				       pixel_size, latency_ns);
-	planeb_wm = intel_calculate_wm(planeb_clock, &planeb_params,
-				       pixel_size, latency_ns);
 	DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
 
 	/*
@@ -3445,39 +4054,39 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
 	 */
 	cwm = 2;
 
+	/* Play safe and disable self-refresh before adjusting watermarks. */
+	if (IS_I945G(dev) || IS_I945GM(dev))
+		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
+	else if (IS_I915GM(dev))
+		I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
+
 	/* Calc sr entries for one plane configs */
-	if (HAS_FW_BLC(dev) && sr_hdisplay &&
-	    (!planea_clock || !planeb_clock)) {
+	if (HAS_FW_BLC(dev) && enabled) {
 		/* self-refresh has much higher latency */
 		static const int sr_latency_ns = 6000;
+		int clock = enabled->mode.clock;
+		int htotal = enabled->mode.htotal;
+		int hdisplay = enabled->mode.hdisplay;
+		int pixel_size = enabled->fb->bits_per_pixel / 8;
+		unsigned long line_time_us;
+		int entries;
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = ((sr_htotal * 1000) / sr_clock);
+		line_time_us = (htotal * 1000) / clock;
 
 		/* Use ns/us then divide to preserve precision */
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			pixel_size * sr_hdisplay;
-		sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size);
-		DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries);
-		srwm = total_size - sr_entries;
+		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+			pixel_size * hdisplay;
+		entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
+		DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
+		srwm = wm_info->fifo_size - entries;
 		if (srwm < 0)
 			srwm = 1;
 
 		if (IS_I945G(dev) || IS_I945GM(dev))
-			I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
-		else if (IS_I915GM(dev)) {
-			/* 915M has a smaller SRWM field */
+			I915_WRITE(FW_BLC_SELF,
+				   FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
+		else if (IS_I915GM(dev))
 			I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
-			I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
-		}
-	} else {
-		/* Turn off self refresh if both pipes are enabled */
-		if (IS_I945G(dev) || IS_I945GM(dev)) {
-			I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-				   & ~FW_BLC_SELF_EN);
-		} else if (IS_I915GM(dev)) {
-			I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
-		}
 	}
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
@@ -3492,19 +4101,36 @@ static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
 
 	I915_WRITE(FW_BLC, fwater_lo);
 	I915_WRITE(FW_BLC2, fwater_hi);
+
+	if (HAS_FW_BLC(dev)) {
+		if (enabled) {
+			if (IS_I945G(dev) || IS_I945GM(dev))
+				I915_WRITE(FW_BLC_SELF,
+					   FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
+			else if (IS_I915GM(dev))
+				I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
+			DRM_DEBUG_KMS("memory self refresh enabled\n");
+		} else
+			DRM_DEBUG_KMS("memory self refresh disabled\n");
+	}
 }
 
-static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
-			   int unused2, int unused3, int pixel_size)
+static void i830_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff;
+	struct drm_crtc *crtc;
+	uint32_t fwater_lo;
 	int planea_wm;
 
-	i830_wm_info.fifo_size = dev_priv->display.get_fifo_size(dev, 0);
+	crtc = single_enabled_crtc(dev);
+	if (crtc == NULL)
+		return;
 
-	planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info,
-				       pixel_size, latency_ns);
+	planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info,
+				       dev_priv->display.get_fifo_size(dev, 0),
+				       crtc->fb->bits_per_pixel / 8,
+				       latency_ns);
+	fwater_lo = I915_READ(FW_BLC) & ~0xfff;
 	fwater_lo |= (3<<8) | planea_wm;
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm);
@@ -3613,15 +4239,15 @@ static bool ironlake_check_srwm(struct drm_device *dev, int level,
 /*
  * Compute watermark values of WM[1-3],
  */
-static bool ironlake_compute_srwm(struct drm_device *dev, int level,
-				  int hdisplay, int htotal,
-				  int pixel_size, int clock, int latency_ns,
+static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
+				  int latency_ns,
 				  const struct intel_watermark_params *display,
 				  const struct intel_watermark_params *cursor,
 				  int *fbc_wm, int *display_wm, int *cursor_wm)
 {
-
+	struct drm_crtc *crtc;
 	unsigned long line_time_us;
+	int hdisplay, htotal, pixel_size, clock;
 	int line_count, line_size;
 	int small, large;
 	int entries;
@@ -3631,6 +4257,12 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level,
 		return false;
 	}
 
+	crtc = intel_get_crtc_for_plane(dev, plane);
+	hdisplay = crtc->mode.hdisplay;
+	htotal = crtc->mode.htotal;
+	clock = crtc->mode.clock;
+	pixel_size = crtc->fb->bits_per_pixel / 8;
+
 	line_time_us = (htotal * 1000) / clock;
 	line_count = (latency_ns / line_time_us + 1000) / 1000;
 	line_size = hdisplay * pixel_size;
@@ -3658,14 +4290,11 @@ static bool ironlake_compute_srwm(struct drm_device *dev, int level,
 				   display, cursor);
 }
 
-static void ironlake_update_wm(struct drm_device *dev,
-			       int planea_clock, int planeb_clock,
-			       int hdisplay, int htotal,
-			       int pixel_size)
+static void ironlake_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int fbc_wm, plane_wm, cursor_wm, enabled;
-	int clock;
+	int fbc_wm, plane_wm, cursor_wm;
+	unsigned int enabled;
 
 	enabled = 0;
 	if (ironlake_compute_wm0(dev, 0,
@@ -3679,7 +4308,7 @@ static void ironlake_update_wm(struct drm_device *dev,
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 1;
 	}
 
 	if (ironlake_compute_wm0(dev, 1,
@@ -3693,7 +4322,7 @@ static void ironlake_update_wm(struct drm_device *dev,
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 2;
 	}
 
 	/*
@@ -3704,14 +4333,13 @@ static void ironlake_update_wm(struct drm_device *dev,
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
-	if (enabled != 1)
+	if (!single_plane_enabled(enabled))
 		return;
-
-	clock = planea_clock ? planea_clock : planeb_clock;
+	enabled = ffs(enabled) - 1;
 
 	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
-				   clock, ILK_READ_WM1_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 1, enabled,
+				   ILK_READ_WM1_LATENCY() * 500,
 				   &ironlake_display_srwm_info,
 				   &ironlake_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3725,8 +4353,8 @@ static void ironlake_update_wm(struct drm_device *dev,
 		   cursor_wm);
 
 	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size,
-				   clock, ILK_READ_WM2_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 2, enabled,
+				   ILK_READ_WM2_LATENCY() * 500,
 				   &ironlake_display_srwm_info,
 				   &ironlake_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3745,15 +4373,12 @@ static void ironlake_update_wm(struct drm_device *dev,
 	 */
 }
 
-static void sandybridge_update_wm(struct drm_device *dev,
-			       int planea_clock, int planeb_clock,
-			       int hdisplay, int htotal,
-			       int pixel_size)
+static void sandybridge_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
-	int fbc_wm, plane_wm, cursor_wm, enabled;
-	int clock;
+	int fbc_wm, plane_wm, cursor_wm;
+	unsigned int enabled;
 
 	enabled = 0;
 	if (ironlake_compute_wm0(dev, 0,
@@ -3765,7 +4390,7 @@ static void sandybridge_update_wm(struct drm_device *dev,
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 1;
 	}
 
 	if (ironlake_compute_wm0(dev, 1,
@@ -3777,7 +4402,7 @@ static void sandybridge_update_wm(struct drm_device *dev,
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 2;
 	}
 
 	/*
@@ -3794,14 +4419,13 @@ static void sandybridge_update_wm(struct drm_device *dev,
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
-	if (enabled != 1)
+	if (!single_plane_enabled(enabled))
 		return;
-
-	clock = planea_clock ? planea_clock : planeb_clock;
+	enabled = ffs(enabled) - 1;
 
 	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
-				   clock, SNB_READ_WM1_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 1, enabled,
+				   SNB_READ_WM1_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3815,9 +4439,8 @@ static void sandybridge_update_wm(struct drm_device *dev,
 		   cursor_wm);
 
 	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2,
-				   hdisplay, htotal, pixel_size,
-				   clock, SNB_READ_WM2_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 2, enabled,
+				   SNB_READ_WM2_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3831,9 +4454,8 @@ static void sandybridge_update_wm(struct drm_device *dev,
 		   cursor_wm);
 
 	/* WM3 */
-	if (!ironlake_compute_srwm(dev, 3,
-				   hdisplay, htotal, pixel_size,
-				   clock, SNB_READ_WM3_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 3, enabled,
+				   SNB_READ_WM3_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3882,44 +4504,9 @@ static void sandybridge_update_wm(struct drm_device *dev,
 static void intel_update_watermarks(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	int sr_hdisplay = 0;
-	unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
-	int enabled = 0, pixel_size = 0;
-	int sr_htotal = 0;
-
-	if (!dev_priv->display.update_wm)
-		return;
-
-	/* Get the clock config from both planes */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		if (intel_crtc->active) {
-			enabled++;
-			if (intel_crtc->plane == 0) {
-				DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n",
-					      intel_crtc->pipe, crtc->mode.clock);
-				planea_clock = crtc->mode.clock;
-			} else {
-				DRM_DEBUG_KMS("plane B (pipe %d) clock: %d\n",
-					      intel_crtc->pipe, crtc->mode.clock);
-				planeb_clock = crtc->mode.clock;
-			}
-			sr_hdisplay = crtc->mode.hdisplay;
-			sr_clock = crtc->mode.clock;
-			sr_htotal = crtc->mode.htotal;
-			if (crtc->fb)
-				pixel_size = crtc->fb->bits_per_pixel / 8;
-			else
-				pixel_size = 4; /* by default */
-		}
-	}
-
-	if (enabled <= 0)
-		return;
 
-	dev_priv->display.update_wm(dev, planea_clock, planeb_clock,
-				    sr_hdisplay, sr_htotal, pixel_size);
+	if (dev_priv->display.update_wm)
+		dev_priv->display.update_wm(dev);
 }
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
@@ -3951,6 +4538,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	int ret;
 	struct fdi_m_n m_n = {0};
 	u32 reg, temp;
+	u32 lvds_sync = 0;
 	int target_clock;
 
 	drm_vblank_pre_modeset(dev, pipe);
@@ -4322,9 +4910,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			pipeconf &= ~PIPECONF_DOUBLE_WIDE;
 	}
 
-	dspcntr |= DISPLAY_PLANE_ENABLE;
-	pipeconf |= PIPECONF_ENABLE;
-	dpll |= DPLL_VCO_ENABLE;
+	if (!HAS_PCH_SPLIT(dev))
+		dpll |= DPLL_VCO_ENABLE;
 
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
@@ -4350,10 +4937,20 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	/* enable transcoder DPLL */
 	if (HAS_PCH_CPT(dev)) {
 		temp = I915_READ(PCH_DPLL_SEL);
-		if (pipe == 0)
+		switch (pipe) {
+		case 0:
 			temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
-		else
+			break;
+		case 1:
 			temp |=	TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
+			break;
+		case 2:
+			/* FIXME: manage transcoder PLLs? */
+			temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
+			break;
+		default:
+			BUG();
+		}
 		I915_WRITE(PCH_DPLL_SEL, temp);
 
 		POSTING_READ(PCH_DPLL_SEL);
@@ -4403,6 +5000,22 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 			else
 				temp &= ~LVDS_ENABLE_DITHER;
 		}
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+			lvds_sync |= LVDS_HSYNC_POLARITY;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+			lvds_sync |= LVDS_VSYNC_POLARITY;
+		if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY))
+		    != lvds_sync) {
+			char flags[2] = "-+";
+			DRM_INFO("Changing LVDS panel from "
+				 "(%chsync, %cvsync) to (%chsync, %cvsync)\n",
+				 flags[!(temp & LVDS_HSYNC_POLARITY)],
+				 flags[!(temp & LVDS_VSYNC_POLARITY)],
+				 flags[!(lvds_sync & LVDS_HSYNC_POLARITY)],
+				 flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]);
+			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+			temp |= lvds_sync;
+		}
 		I915_WRITE(reg, temp);
 	}
 
@@ -4420,17 +5033,10 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 	} else if (HAS_PCH_SPLIT(dev)) {
 		/* For non-DP output, clear any trans DP clock recovery setting.*/
-		if (pipe == 0) {
-			I915_WRITE(TRANSA_DATA_M1, 0);
-			I915_WRITE(TRANSA_DATA_N1, 0);
-			I915_WRITE(TRANSA_DP_LINK_M1, 0);
-			I915_WRITE(TRANSA_DP_LINK_N1, 0);
-		} else {
-			I915_WRITE(TRANSB_DATA_M1, 0);
-			I915_WRITE(TRANSB_DATA_N1, 0);
-			I915_WRITE(TRANSB_DP_LINK_M1, 0);
-			I915_WRITE(TRANSB_DP_LINK_N1, 0);
-		}
+		I915_WRITE(TRANSDATA_M1(pipe), 0);
+		I915_WRITE(TRANSDATA_N1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
 	}
 
 	if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
@@ -4533,6 +5139,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 
 	I915_WRITE(PIPECONF(pipe), pipeconf);
 	POSTING_READ(PIPECONF(pipe));
+	if (!HAS_PCH_SPLIT(dev))
+		intel_enable_pipe(dev_priv, pipe, false);
 
 	intel_wait_for_vblank(dev, pipe);
 
@@ -4543,6 +5151,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
 	}
 
 	I915_WRITE(DSPCNTR(plane), dspcntr);
+	POSTING_READ(DSPCNTR(plane));
+	if (!HAS_PCH_SPLIT(dev))
+		intel_enable_plane(dev_priv, plane, pipe);
 
 	ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
@@ -4559,7 +5170,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
+	int palreg = PALETTE(intel_crtc->pipe);
 	int i;
 
 	/* The clocks have to be on to load the palette. */
@@ -4568,8 +5179,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
 
 	/* use legacy palette for Ironlake */
 	if (HAS_PCH_SPLIT(dev))
-		palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
-						   LGC_PALETTE_B;
+		palreg = LGC_PALETTE(intel_crtc->pipe);
 
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
@@ -4590,12 +5200,12 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
 	if (intel_crtc->cursor_visible == visible)
 		return;
 
-	cntl = I915_READ(CURACNTR);
+	cntl = I915_READ(_CURACNTR);
 	if (visible) {
 		/* On these chipsets we can only modify the base whilst
 		 * the cursor is disabled.
 		 */
-		I915_WRITE(CURABASE, base);
+		I915_WRITE(_CURABASE, base);
 
 		cntl &= ~(CURSOR_FORMAT_MASK);
 		/* XXX width must be 64, stride 256 => 0x00 << 28 */
@@ -4604,7 +5214,7 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
 			CURSOR_FORMAT_ARGB;
 	} else
 		cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
-	I915_WRITE(CURACNTR, cntl);
+	I915_WRITE(_CURACNTR, cntl);
 
 	intel_crtc->cursor_visible = visible;
 }
@@ -4618,7 +5228,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
 	bool visible = base != 0;
 
 	if (intel_crtc->cursor_visible != visible) {
-		uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR);
+		uint32_t cntl = I915_READ(CURCNTR(pipe));
 		if (base) {
 			cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 			cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
@@ -4627,12 +5237,12 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
 			cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
 			cntl |= CURSOR_MODE_DISABLE;
 		}
-		I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl);
+		I915_WRITE(CURCNTR(pipe), cntl);
 
 		intel_crtc->cursor_visible = visible;
 	}
 	/* and commit changes on next vblank */
-	I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base);
+	I915_WRITE(CURBASE(pipe), base);
 }
 
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
@@ -4682,7 +5292,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 	if (!visible && !intel_crtc->cursor_visible)
 		return;
 
-	I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos);
+	I915_WRITE(CURPOS(pipe), pos);
 	if (IS_845G(dev) || IS_I865G(dev))
 		i845_update_cursor(crtc, base);
 	else
@@ -4722,7 +5332,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
 	}
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
-	if (!obj)
+	if (&obj->base == NULL)
 		return -ENOENT;
 
 	if (obj->base.size < width * height * 4) {
@@ -4988,14 +5598,14 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B);
+	u32 dpll = I915_READ(DPLL(pipe));
 	u32 fp;
 	intel_clock_t clock;
 
 	if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-		fp = I915_READ((pipe == 0) ? FPA0 : FPB0);
+		fp = FP0(pipe);
 	else
-		fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
+		fp = FP1(pipe);
 
 	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
 	if (IS_PINEVIEW(dev)) {
@@ -5077,10 +5687,10 @@ struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	struct drm_display_mode *mode;
-	int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
-	int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
-	int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
-	int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+	int htot = I915_READ(HTOTAL(pipe));
+	int hsync = I915_READ(HSYNC(pipe));
+	int vtot = I915_READ(VTOTAL(pipe));
+	int vsync = I915_READ(VSYNC(pipe));
 
 	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 	if (!mode)
@@ -5189,7 +5799,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dpll_reg = DPLL(pipe);
 	int dpll = I915_READ(dpll_reg);
 
 	if (HAS_PCH_SPLIT(dev))
@@ -5237,7 +5847,6 @@ static void intel_idle_update(struct work_struct *work)
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_crtc *crtc;
 	struct intel_crtc *intel_crtc;
-	int enabled = 0;
 
 	if (!i915_powersave)
 		return;
@@ -5251,16 +5860,11 @@ static void intel_idle_update(struct work_struct *work)
 		if (!crtc->fb)
 			continue;
 
-		enabled++;
 		intel_crtc = to_intel_crtc(crtc);
 		if (!intel_crtc->busy)
 			intel_decrease_pllclock(crtc);
 	}
 
-	if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
-		DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
-	}
 
 	mutex_unlock(&dev->struct_mutex);
 }
@@ -5285,17 +5889,9 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	if (!dev_priv->busy) {
-		if (IS_I945G(dev) || IS_I945GM(dev)) {
-			u32 fw_blc_self;
-
-			DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
-			fw_blc_self = I915_READ(FW_BLC_SELF);
-			fw_blc_self &= ~FW_BLC_SELF_EN;
-			I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
-		}
+	if (!dev_priv->busy)
 		dev_priv->busy = true;
-	} else
+	else
 		mod_timer(&dev_priv->idle_timer, jiffies +
 			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 
@@ -5307,14 +5903,6 @@ void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj)
 		intel_fb = to_intel_framebuffer(crtc->fb);
 		if (intel_fb->obj == obj) {
 			if (!intel_crtc->busy) {
-				if (IS_I945G(dev) || IS_I945GM(dev)) {
-					u32 fw_blc_self;
-
-					DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
-					fw_blc_self = I915_READ(FW_BLC_SELF);
-					fw_blc_self &= ~FW_BLC_SELF_EN;
-					I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
-				}
 				/* Non-busy -> busy, upclock */
 				intel_increase_pllclock(crtc);
 				intel_crtc->busy = true;
@@ -5592,7 +6180,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 		 * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
 		 */
 		pf = 0;
-		pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
+		pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff;
 		OUT_RING(pf | pipesrc);
 		break;
 
@@ -5602,8 +6190,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
 		OUT_RING(fb->pitch | obj->tiling_mode);
 		OUT_RING(obj->gtt_offset);
 
-		pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
-		pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
+		pf = I915_READ(PF_CTL(pipe)) & PF_ENABLE;
+		pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff;
 		OUT_RING(pf | pipesrc);
 		break;
 	}
@@ -5692,22 +6280,8 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
 	pipe = !pipe;
 
 	/* Disable the plane and wait for it to stop reading from the pipe. */
-	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
-	intel_flush_display_plane(dev, plane);
-
-	if (IS_GEN2(dev))
-		intel_wait_for_vblank(dev, pipe);
-
-	if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
-		return;
-
-	/* Switch off the pipe. */
-	reg = PIPECONF(pipe);
-	val = I915_READ(reg);
-	if (val & PIPECONF_ENABLE) {
-		I915_WRITE(reg, val & ~PIPECONF_ENABLE);
-		intel_wait_for_pipe_off(dev, pipe);
-	}
+	intel_disable_plane(dev_priv, plane, pipe);
+	intel_disable_pipe(dev_priv, pipe);
 }
 
 static void intel_crtc_init(struct drm_device *dev, int pipe)
@@ -5997,7 +6571,7 @@ intel_user_framebuffer_create(struct drm_device *dev,
 	int ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle));
-	if (!obj)
+	if (&obj->base == NULL)
 		return ERR_PTR(-ENOENT);
 
 	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
@@ -6319,18 +6893,18 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
 		   18 << 24 |
 		   6 << 16);
-	I915_WRITE(GEN6_RP_UP_THRESHOLD, 90000);
-	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 100000);
+	I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000);
+	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000);
 	I915_WRITE(GEN6_RP_UP_EI, 100000);
-	I915_WRITE(GEN6_RP_DOWN_EI, 300000);
+	I915_WRITE(GEN6_RP_DOWN_EI, 5000000);
 	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
 	I915_WRITE(GEN6_RP_CONTROL,
 		   GEN6_RP_MEDIA_TURBO |
 		   GEN6_RP_USE_NORMAL_FREQ |
 		   GEN6_RP_MEDIA_IS_GFX |
 		   GEN6_RP_ENABLE |
-		   GEN6_RP_UP_BUSY_MAX |
-		   GEN6_RP_DOWN_BUSY_MIN);
+		   GEN6_RP_UP_BUSY_AVG |
+		   GEN6_RP_DOWN_IDLE_CONT);
 
 	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
 		     500))
@@ -6386,6 +6960,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)
 void intel_enable_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe;
 
 	/*
 	 * Disable clock gating reported to work incorrectly according to the
@@ -6495,12 +7070,10 @@ void intel_enable_clock_gating(struct drm_device *dev)
 				   ILK_DPARB_CLK_GATE  |
 				   ILK_DPFD_CLK_GATE);
 
-			I915_WRITE(DSPACNTR,
-				   I915_READ(DSPACNTR) |
-				   DISPPLANE_TRICKLE_FEED_DISABLE);
-			I915_WRITE(DSPBCNTR,
-				   I915_READ(DSPBCNTR) |
-				   DISPPLANE_TRICKLE_FEED_DISABLE);
+			for_each_pipe(pipe)
+				I915_WRITE(DSPCNTR(pipe),
+					   I915_READ(DSPCNTR(pipe)) |
+					   DISPPLANE_TRICKLE_FEED_DISABLE);
 		}
 	} else if (IS_G4X(dev)) {
 		uint32_t dspclk_gate;
@@ -6855,10 +7428,6 @@ void intel_modeset_init(struct drm_device *dev)
 	}
 	dev->mode_config.fb_base = dev->agp->base;
 
-	if (IS_MOBILE(dev) || !IS_GEN2(dev))
-		dev_priv->num_pipe = 2;
-	else
-		dev_priv->num_pipe = 1;
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
 		      dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 51cb4e3..d29e33f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -49,6 +49,7 @@ struct intel_dp {
 	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 	bool has_audio;
 	int force_audio;
+	uint32_t color_range;
 	int dpms_mode;
 	uint8_t link_bw;
 	uint8_t lane_count;
@@ -685,6 +686,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int lane_count = 4, bpp = 24;
 	struct intel_dp_m_n m_n;
+	int pipe = intel_crtc->pipe;
 
 	/*
 	 * Find the lane count in the intel_encoder private
@@ -715,39 +717,19 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 			     mode->clock, adjusted_mode->clock, &m_n);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		if (intel_crtc->pipe == 0) {
-			I915_WRITE(TRANSA_DATA_M1,
-				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-				   m_n.gmch_m);
-			I915_WRITE(TRANSA_DATA_N1, m_n.gmch_n);
-			I915_WRITE(TRANSA_DP_LINK_M1, m_n.link_m);
-			I915_WRITE(TRANSA_DP_LINK_N1, m_n.link_n);
-		} else {
-			I915_WRITE(TRANSB_DATA_M1,
-				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-				   m_n.gmch_m);
-			I915_WRITE(TRANSB_DATA_N1, m_n.gmch_n);
-			I915_WRITE(TRANSB_DP_LINK_M1, m_n.link_m);
-			I915_WRITE(TRANSB_DP_LINK_N1, m_n.link_n);
-		}
+		I915_WRITE(TRANSDATA_M1(pipe),
+			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+			   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 (intel_crtc->pipe == 0) {
-			I915_WRITE(PIPEA_GMCH_DATA_M,
-				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-				   m_n.gmch_m);
-			I915_WRITE(PIPEA_GMCH_DATA_N,
-				   m_n.gmch_n);
-			I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m);
-			I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n);
-		} else {
-			I915_WRITE(PIPEB_GMCH_DATA_M,
-				   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
-				   m_n.gmch_m);
-			I915_WRITE(PIPEB_GMCH_DATA_N,
-					m_n.gmch_n);
-			I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m);
-			I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n);
-		}
+		I915_WRITE(PIPE_GMCH_DATA_M(pipe),
+			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+			   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);
 	}
 }
 
@@ -760,8 +742,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	intel_dp->DP = (DP_VOLTAGE_0_4 |
-		       DP_PRE_EMPHASIS_0);
+	intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+	intel_dp->DP |= intel_dp->color_range;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 		intel_dp->DP |= DP_SYNC_HS_HIGH;
@@ -813,6 +795,40 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	}
 }
 
+static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp;
+
+	/*
+	 * If the panel wasn't on, make sure there's not a currently
+	 * active PP sequence before enabling AUX VDD.
+	 */
+	if (!(I915_READ(PCH_PP_STATUS) & PP_ON))
+		msleep(dev_priv->panel_t3);
+
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp |= EDP_FORCE_VDD;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
+}
+
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp;
+
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp &= ~EDP_FORCE_VDD;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
+
+	/* Make sure sequencer is idle before allowing subsequent activity */
+	msleep(dev_priv->panel_t12);
+}
+
 /* Returns true if the panel was already on when called */
 static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
 {
@@ -834,11 +850,6 @@ static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
 
-	/* Ouch. We need to wait here for some panels, like Dell e6510
-	 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
-	 */
-	msleep(300);
-
 	if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
 		     5000))
 		DRM_ERROR("panel on wait timed out: 0x%08x\n",
@@ -875,11 +886,6 @@ static void ironlake_edp_panel_off (struct drm_device *dev)
 	pp |= PANEL_POWER_RESET; /* restore panel reset bit */
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
-
-	/* Ouch. We need to wait here for some panels, like Dell e6510
-	 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
-	 */
-	msleep(300);
 }
 
 static void ironlake_edp_backlight_on (struct drm_device *dev)
@@ -945,7 +951,7 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 
 	if (is_edp(intel_dp)) {
 		ironlake_edp_backlight_off(dev);
-		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_off(dev);
 		if (!is_pch_edp(intel_dp))
 			ironlake_edp_pll_on(encoder);
 		else
@@ -959,10 +965,15 @@ static void intel_dp_commit(struct drm_encoder *encoder)
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_device *dev = encoder->dev;
 
+	if (is_edp(intel_dp))
+		ironlake_edp_panel_vdd_on(intel_dp);
+
 	intel_dp_start_link_train(intel_dp);
 
-	if (is_edp(intel_dp))
+	if (is_edp(intel_dp)) {
 		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp);
+	}
 
 	intel_dp_complete_link_train(intel_dp);
 
@@ -988,9 +999,13 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
 			ironlake_edp_pll_off(encoder);
 	} else {
 		if (is_edp(intel_dp))
-			ironlake_edp_panel_on(intel_dp);
+			ironlake_edp_panel_vdd_on(intel_dp);
 		if (!(dp_reg & DP_PORT_EN)) {
 			intel_dp_start_link_train(intel_dp);
+			if (is_edp(intel_dp)) {
+				ironlake_edp_panel_on(intel_dp);
+				ironlake_edp_panel_vdd_off(intel_dp);
+			}
 			intel_dp_complete_link_train(intel_dp);
 		}
 		if (is_edp(intel_dp))
@@ -1508,9 +1523,13 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
 {
 	enum drm_connector_status status;
 
-	/* Can't disconnect eDP */
-	if (is_edp(intel_dp))
-		return connector_status_connected;
+	/* Can't disconnect eDP, but you can close the lid... */
+	if (is_edp(intel_dp)) {
+		status = intel_panel_detect(intel_dp->base.base.dev);
+		if (status == connector_status_unknown)
+			status = connector_status_connected;
+		return status;
+	}
 
 	status = connector_status_disconnected;
 	if (intel_dp_aux_native_read(intel_dp,
@@ -1662,6 +1681,7 @@ intel_dp_set_property(struct drm_connector *connector,
 		      struct drm_property *property,
 		      uint64_t val)
 {
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	int ret;
 
@@ -1690,6 +1710,14 @@ intel_dp_set_property(struct drm_connector *connector,
 		goto done;
 	}
 
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_dp->color_range)
+			return 0;
+
+		intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
@@ -1809,6 +1837,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 		intel_dp->force_audio_property->values[1] = 1;
 		drm_connector_attach_property(connector, intel_dp->force_audio_property, 0);
 	}
+
+	intel_attach_broadcast_rgb_property(connector);
 }
 
 void
@@ -1826,6 +1856,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	if (!intel_dp)
 		return;
 
+	intel_dp->output_reg = output_reg;
+	intel_dp->dpms_mode = -1;
+
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
 		kfree(intel_dp);
@@ -1865,10 +1898,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
-	intel_dp->output_reg = output_reg;
-	intel_dp->has_audio = false;
-	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
-
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
@@ -1906,21 +1935,33 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	/* Cache some DPCD data in the eDP case */
 	if (is_edp(intel_dp)) {
 		int ret;
-		bool was_on;
+		u32 pp_on, pp_div;
 
-		was_on = ironlake_edp_panel_on(intel_dp);
+		pp_on = I915_READ(PCH_PP_ON_DELAYS);
+		pp_div = I915_READ(PCH_PP_DIVISOR);
+
+		/* Get T3 & T12 values (note: VESA not bspec terminology) */
+		dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16;
+		dev_priv->panel_t3 /= 10; /* t3 in 100us units */
+		dev_priv->panel_t12 = pp_div & 0xf;
+		dev_priv->panel_t12 *= 100; /* t12 in 100ms units */
+
+		ironlake_edp_panel_vdd_on(intel_dp);
 		ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV,
 					       intel_dp->dpcd,
 					       sizeof(intel_dp->dpcd));
+		ironlake_edp_panel_vdd_off(intel_dp);
 		if (ret == sizeof(intel_dp->dpcd)) {
 			if (intel_dp->dpcd[0] >= 0x11)
 				dev_priv->no_aux_handshake = intel_dp->dpcd[3] &
 					DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
 		} else {
+			/* if this fails, presume the device is a ghost */
 			DRM_ERROR("failed to retrieve link info\n");
+			intel_dp_destroy(&intel_connector->base);
+			intel_dp_encoder_destroy(&intel_dp->base.base);
+			return;
 		}
-		if (!was_on)
-			ironlake_edp_panel_off(dev);
 	}
 
 	intel_encoder->hot_plug = intel_dp_hot_plug;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 2c43104..5daa991 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -217,6 +217,13 @@ intel_get_crtc_for_pipe(struct drm_device *dev, int pipe)
 	return dev_priv->pipe_to_crtc_mapping[pipe];
 }
 
+static inline struct drm_crtc *
+intel_get_crtc_for_plane(struct drm_device *dev, int plane)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	return dev_priv->plane_to_crtc_mapping[plane];
+}
+
 struct intel_unpin_work {
 	struct work_struct work;
 	struct drm_device *dev;
@@ -230,6 +237,8 @@ struct intel_unpin_work {
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
 
+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);
 void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
@@ -260,6 +269,7 @@ extern void intel_panel_set_backlight(struct drm_device *dev, u32 level);
 extern void intel_panel_setup_backlight(struct drm_device *dev);
 extern void intel_panel_enable_backlight(struct drm_device *dev);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
+extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
@@ -321,8 +331,7 @@ extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
 
 extern void intel_setup_overlay(struct drm_device *dev);
 extern void intel_cleanup_overlay(struct drm_device *dev);
-extern int intel_overlay_switch_off(struct intel_overlay *overlay,
-				    bool interruptible);
+extern int intel_overlay_switch_off(struct intel_overlay *overlay);
 extern int intel_overlay_put_image(struct drm_device *dev, void *data,
 				   struct drm_file *file_priv);
 extern int intel_overlay_attrs(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index ea37328..6eda1b5 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -178,7 +178,7 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
 	int pipe = intel_crtc->pipe;
 	u32 dvo_val;
 	u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
-	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dpll_reg = DPLL(pipe);
 
 	switch (dvo_reg) {
 	case DVOA:
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index c635c9e..f289b86 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -41,6 +41,7 @@ struct intel_hdmi {
 	struct intel_encoder base;
 	u32 sdvox_reg;
 	int ddc_bus;
+	uint32_t color_range;
 	bool has_hdmi_sink;
 	bool has_audio;
 	int force_audio;
@@ -124,6 +125,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	u32 sdvox;
 
 	sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
+	sdvox |= intel_hdmi->color_range;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -278,6 +280,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
 		      uint64_t val)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
 
 	ret = drm_connector_property_set_value(connector, property, val);
@@ -305,6 +308,14 @@ intel_hdmi_set_property(struct drm_connector *connector,
 		goto done;
 	}
 
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_hdmi->color_range)
+			return 0;
+
+		intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
@@ -363,6 +374,8 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 		intel_hdmi->force_audio_property->values[1] = 1;
 		drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0);
 	}
+
+	intel_attach_broadcast_rgb_property(connector);
 }
 
 void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 58040f6..82d04c5 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -384,7 +384,8 @@ int intel_setup_gmbus(struct drm_device *dev)
 		bus->reg0 = i | GMBUS_RATE_100KHZ;
 
 		/* XXX force bit banging until GMBUS is fully debugged */
-		bus->force_bit = intel_gpio_create(dev_priv, i);
+		if (IS_GEN2(dev))
+			bus->force_bit = intel_gpio_create(dev_priv, i);
 	}
 
 	intel_i2c_reset(dev_priv->dev);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index bcdba7b..1a311ad 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -231,6 +231,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 	struct drm_encoder *tmp_encoder;
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
+	int pipe;
 
 	/* Should never happen!! */
 	if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
@@ -277,8 +278,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	 * to register description and PRM.
 	 * Change the value here to see the borders for debugging
 	 */
-	I915_WRITE(BCLRPAT_A, 0);
-	I915_WRITE(BCLRPAT_B, 0);
+	for_each_pipe(pipe)
+		I915_WRITE(BCLRPAT(pipe), 0);
 
 	switch (intel_lvds->fitting_mode) {
 	case DRM_MODE_SCALE_CENTER:
@@ -474,6 +475,10 @@ intel_lvds_detect(struct drm_connector *connector, bool force)
 	struct drm_device *dev = connector->dev;
 	enum drm_connector_status status = connector_status_connected;
 
+	status = intel_panel_detect(dev);
+	if (status != connector_status_unknown)
+		return status;
+
 	/* ACPI lid methods were generally unreliable in this generation, so
 	 * don't even bother.
 	 */
@@ -496,7 +501,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
 		return drm_add_edid_modes(connector, intel_lvds->edid);
 
 	mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
-	if (mode == 0)
+	if (mode == NULL)
 		return 0;
 
 	drm_mode_probed_add(connector, mode);
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c
index f70b7cf..9034dd8f 100644
--- a/drivers/gpu/drm/i915/intel_modes.c
+++ b/drivers/gpu/drm/i915/intel_modes.c
@@ -80,3 +80,33 @@ int intel_ddc_get_modes(struct drm_connector *connector,
 
 	return ret;
 }
+
+static const char *broadcast_rgb_names[] = {
+	"Full",
+	"Limited 16:235",
+};
+
+void
+intel_attach_broadcast_rgb_property(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_property *prop;
+	int i;
+
+	prop = dev_priv->broadcast_rgb_property;
+	if (prop == NULL) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
+					   "Broadcast RGB",
+					   ARRAY_SIZE(broadcast_rgb_names));
+		if (prop == NULL)
+			return;
+
+		for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
+			drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
+
+		dev_priv->broadcast_rgb_property = prop;
+	}
+
+	drm_connector_attach_property(connector, prop, 0);
+}
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 64fd644..d2c7104 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -39,6 +39,8 @@
 
 #define OPREGION_HEADER_OFFSET 0
 #define OPREGION_ACPI_OFFSET   0x100
+#define   ACPI_CLID 0x01ac /* current lid state indicator */
+#define   ACPI_CDCK 0x01b0 /* current docking state indicator */
 #define OPREGION_SWSCI_OFFSET  0x200
 #define OPREGION_ASLE_OFFSET   0x300
 #define OPREGION_VBT_OFFSET    0x400
@@ -489,6 +491,8 @@ int intel_opregion_setup(struct drm_device *dev)
 	opregion->header = base;
 	opregion->vbt = base + OPREGION_VBT_OFFSET;
 
+	opregion->lid_state = base + ACPI_CLID;
+
 	mboxes = opregion->header->mboxes;
 	if (mboxes & MBOX_ACPI) {
 		DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 3fbb98b..a670c00 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -213,7 +213,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
 
 static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
 					 struct drm_i915_gem_request *request,
-					 bool interruptible,
 					 void (*tail)(struct intel_overlay *))
 {
 	struct drm_device *dev = overlay->dev;
@@ -221,16 +220,14 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
 	int ret;
 
 	BUG_ON(overlay->last_flip_req);
-	ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
 	if (ret) {
 	    kfree(request);
 	    return ret;
 	}
 	overlay->last_flip_req = request->seqno;
 	overlay->flip_tail = tail;
-	ret = i915_do_wait_request(dev,
-				   overlay->last_flip_req, true,
-				   LP_RING(dev_priv));
+	ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req);
 	if (ret)
 		return ret;
 
@@ -256,7 +253,7 @@ i830_activate_pipe_a(struct drm_device *dev)
 		return 0;
 
 	/* most i8xx have pipe a forced on, so don't trust dpms mode */
-	if (I915_READ(PIPEACONF) & PIPECONF_ENABLE)
+	if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
 		return 0;
 
 	crtc_funcs = crtc->base.helper_private;
@@ -322,7 +319,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
 
-	ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
+	ret = intel_overlay_do_wait_request(overlay, request, NULL);
 out:
 	if (pipe_a_quirk)
 		i830_deactivate_pipe_a(dev);
@@ -364,7 +361,7 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
 	OUT_RING(flip_addr);
         ADVANCE_LP_RING();
 
-	ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
 	if (ret) {
 		kfree(request);
 		return ret;
@@ -401,8 +398,7 @@ static void intel_overlay_off_tail(struct intel_overlay *overlay)
 }
 
 /* overlay needs to be disabled in OCMD reg */
-static int intel_overlay_off(struct intel_overlay *overlay,
-			     bool interruptible)
+static int intel_overlay_off(struct intel_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -437,14 +433,13 @@ static int intel_overlay_off(struct intel_overlay *overlay,
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	ADVANCE_LP_RING();
 
-	return intel_overlay_do_wait_request(overlay, request, interruptible,
+	return intel_overlay_do_wait_request(overlay, request,
 					     intel_overlay_off_tail);
 }
 
 /* recover from an interruption due to a signal
  * We have to be careful not to repeat work forever an make forward progess. */
-static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
-						bool interruptible)
+static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -453,8 +448,7 @@ static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
 	if (overlay->last_flip_req == 0)
 		return 0;
 
-	ret = i915_do_wait_request(dev, overlay->last_flip_req,
-				   interruptible, LP_RING(dev_priv));
+	ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req);
 	if (ret)
 		return ret;
 
@@ -499,7 +493,7 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
 		OUT_RING(MI_NOOP);
 		ADVANCE_LP_RING();
 
-		ret = intel_overlay_do_wait_request(overlay, request, true,
+		ret = intel_overlay_do_wait_request(overlay, request,
 						    intel_overlay_release_old_vid_tail);
 		if (ret)
 			return ret;
@@ -868,8 +862,7 @@ out_unpin:
 	return ret;
 }
 
-int intel_overlay_switch_off(struct intel_overlay *overlay,
-			     bool interruptible)
+int intel_overlay_switch_off(struct intel_overlay *overlay)
 {
 	struct overlay_registers *regs;
 	struct drm_device *dev = overlay->dev;
@@ -878,7 +871,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay,
 	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
-	ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
+	ret = intel_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
 		return ret;
 
@@ -893,7 +886,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay,
 	regs->OCMD = 0;
 	intel_overlay_unmap_regs(overlay, regs);
 
-	ret = intel_overlay_off(overlay, interruptible);
+	ret = intel_overlay_off(overlay);
 	if (ret != 0)
 		return ret;
 
@@ -1135,7 +1128,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 		mutex_lock(&dev->mode_config.mutex);
 		mutex_lock(&dev->struct_mutex);
 
-		ret = intel_overlay_switch_off(overlay, true);
+		ret = intel_overlay_switch_off(overlay);
 
 		mutex_unlock(&dev->struct_mutex);
 		mutex_unlock(&dev->mode_config.mutex);
@@ -1157,7 +1150,7 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 
 	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
 						   put_image_rec->bo_handle));
-	if (!new_bo) {
+	if (&new_bo->base == NULL) {
 		ret = -ENOENT;
 		goto out_free;
 	}
@@ -1171,13 +1164,13 @@ int intel_overlay_put_image(struct drm_device *dev, void *data,
 		goto out_unlock;
 	}
 
-	ret = intel_overlay_recover_from_interrupt(overlay, true);
+	ret = intel_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
 		goto out_unlock;
 
 	if (overlay->crtc != crtc) {
 		struct drm_display_mode *mode = &crtc->base.mode;
-		ret = intel_overlay_switch_off(overlay, true);
+		ret = intel_overlay_switch_off(overlay);
 		if (ret != 0)
 			goto out_unlock;
 
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index f8f86e5..a06ff07 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -280,3 +280,28 @@ void intel_panel_setup_backlight(struct drm_device *dev)
 	dev_priv->backlight_level = intel_panel_get_backlight(dev);
 	dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
 }
+
+enum drm_connector_status
+intel_panel_detect(struct drm_device *dev)
+{
+#if 0
+	struct drm_i915_private *dev_priv = dev->dev_private;
+#endif
+
+	if (i915_panel_ignore_lid)
+		return i915_panel_ignore_lid > 0 ?
+			connector_status_connected :
+			connector_status_disconnected;
+
+	/* opregion lid state on HP 2540p is wrong at boot up,
+	 * appears to be either the BIOS or Linux ACPI fault */
+#if 0
+	/* Assume that the BIOS does not lie through the OpRegion... */
+	if (dev_priv->opregion.lid_state)
+		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
+			connector_status_connected :
+			connector_status_disconnected;
+#endif
+
+	return connector_status_unknown;
+}
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 445f27e..789c478 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -62,18 +62,9 @@ render_ring_flush(struct intel_ring_buffer *ring,
 		  u32	flush_domains)
 {
 	struct drm_device *dev = ring->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 cmd;
 	int ret;
 
-#if WATCH_EXEC
-	DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
-		  invalidate_domains, flush_domains);
-#endif
-
-	trace_i915_gem_request_flush(dev, dev_priv->next_seqno,
-				     invalidate_domains, flush_domains);
-
 	if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
 		/*
 		 * read/write caches:
@@ -122,9 +113,6 @@ render_ring_flush(struct intel_ring_buffer *ring,
 		    (IS_G4X(dev) || IS_GEN5(dev)))
 			cmd |= MI_INVALIDATE_ISP;
 
-#if WATCH_EXEC
-		DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
-#endif
 		ret = intel_ring_begin(ring, 2);
 		if (ret)
 			return ret;
@@ -612,7 +600,6 @@ ring_add_request(struct intel_ring_buffer *ring,
 	intel_ring_emit(ring, MI_USER_INTERRUPT);
 	intel_ring_advance(ring);
 
-	DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
 	*result = seqno;
 	return 0;
 }
@@ -715,11 +702,8 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
 				u32 offset, u32 len)
 {
 	struct drm_device *dev = ring->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
 
-	trace_i915_gem_request_submit(dev, dev_priv->next_seqno + 1);
-
 	if (IS_I830(dev) || IS_845G(dev)) {
 		ret = intel_ring_begin(ring, 4);
 		if (ret)
@@ -894,6 +878,10 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
 	/* Disable the ring buffer. The ring must be idle at this point */
 	dev_priv = ring->dev->dev_private;
 	ret = intel_wait_ring_buffer(ring, ring->size - 8);
+	if (ret)
+		DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
+			  ring->name, ret);
+
 	I915_WRITE_CTL(ring, 0);
 
 	drm_core_ioremapfree(&ring->map, ring->dev);
@@ -950,13 +938,13 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
 			return 0;
 	}
 
-	trace_i915_ring_wait_begin (dev);
+	trace_i915_ring_wait_begin(ring);
 	end = jiffies + 3 * HZ;
 	do {
 		ring->head = I915_READ_HEAD(ring);
 		ring->space = ring_space(ring);
 		if (ring->space >= n) {
-			trace_i915_ring_wait_end(dev);
+			trace_i915_ring_wait_end(ring);
 			return 0;
 		}
 
@@ -970,16 +958,20 @@ int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n)
 		if (atomic_read(&dev_priv->mm.wedged))
 			return -EAGAIN;
 	} while (!time_after(jiffies, end));
-	trace_i915_ring_wait_end (dev);
+	trace_i915_ring_wait_end(ring);
 	return -EBUSY;
 }
 
 int intel_ring_begin(struct intel_ring_buffer *ring,
 		     int num_dwords)
 {
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	int n = 4*num_dwords;
 	int ret;
 
+	if (unlikely(atomic_read(&dev_priv->mm.wedged)))
+		return -EIO;
+
 	if (unlikely(ring->tail + n > ring->effective_size)) {
 		ret = intel_wrap_ring_buffer(ring);
 		if (unlikely(ret))
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 3430686..f23cc5f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -44,7 +44,7 @@ struct  intel_ring_buffer {
 		RING_BLT = 0x4,
 	} id;
 	u32		mmio_base;
-	void		*virtual_start;
+	void		__iomem *virtual_start;
 	struct		drm_device *dev;
 	struct		drm_i915_gem_object *obj;
 
@@ -59,6 +59,7 @@ struct  intel_ring_buffer {
 	u32		irq_refcount;
 	u32		irq_mask;
 	u32		irq_seqno;		/* last seq seem at irq time */
+	u32		trace_irq_seqno;
 	u32		waiting_seqno;
 	u32		sync_seqno[I915_NUM_RINGS-1];
 	bool __must_check (*irq_get)(struct intel_ring_buffer *ring);
@@ -142,6 +143,26 @@ intel_read_status_page(struct intel_ring_buffer *ring,
 	return ioread32(ring->status_page.page_addr + reg);
 }
 
+/**
+ * Reads a dword out of the status page, which is written to from the command
+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
+ * MI_STORE_DATA_IMM.
+ *
+ * The following dwords have a reserved meaning:
+ * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
+ * 0x04: ring 0 head pointer
+ * 0x05: ring 1 head pointer (915-class)
+ * 0x06: ring 2 head pointer (915-class)
+ * 0x10-0x1b: Context status DWords (GM45)
+ * 0x1f: Last written status offset. (GM45)
+ *
+ * The area from dword 0x20 to 0x3ff is available for driver usage.
+ */
+#define READ_HWSP(dev_priv, reg) intel_read_status_page(LP_RING(dev_priv), reg)
+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
+#define I915_GEM_HWS_INDEX		0x20
+#define I915_BREADCRUMB_INDEX		0x21
+
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n);
 int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
@@ -167,6 +188,12 @@ int intel_init_blt_ring_buffer(struct drm_device *dev);
 u32 intel_ring_get_active_head(struct intel_ring_buffer *ring);
 void intel_ring_setup_status_page(struct intel_ring_buffer *ring);
 
+static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno)
+{
+	if (ring->trace_irq_seqno == 0 && ring->irq_get(ring))
+		ring->trace_irq_seqno = seqno;
+}
+
 /* DRI warts */
 int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size);
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 7c50cdc..4324f33 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -93,6 +93,12 @@ struct intel_sdvo {
 	uint16_t attached_output;
 
 	/**
+	 * This is used to select the color range of RBG outputs in HDMI mode.
+	 * It is only valid when using TMDS encoding and 8 bit per color mode.
+	 */
+	uint32_t color_range;
+
+	/**
 	 * This is set if we're going to treat the device as TV-out.
 	 *
 	 * While we have these nice friendly flags for output types that ought
@@ -585,6 +591,7 @@ static bool intel_sdvo_get_trained_inputs(struct intel_sdvo *intel_sdvo, bool *i
 {
 	struct intel_sdvo_get_trained_inputs_response response;
 
+	BUILD_BUG_ON(sizeof(response) != 1);
 	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_TRAINED_INPUTS,
 				  &response, sizeof(response)))
 		return false;
@@ -632,6 +639,7 @@ static bool intel_sdvo_get_input_pixel_clock_range(struct intel_sdvo *intel_sdvo
 {
 	struct intel_sdvo_pixel_clock_range clocks;
 
+	BUILD_BUG_ON(sizeof(clocks) != 4);
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
 				  &clocks, sizeof(clocks)))
@@ -699,6 +707,8 @@ intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo,
 static bool intel_sdvo_get_preferred_input_timing(struct intel_sdvo *intel_sdvo,
 						  struct intel_sdvo_dtd *dtd)
 {
+	BUILD_BUG_ON(sizeof(dtd->part1) != 8);
+	BUILD_BUG_ON(sizeof(dtd->part2) != 8);
 	return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
 				    &dtd->part1, sizeof(dtd->part1)) &&
 		intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
@@ -796,6 +806,7 @@ static bool intel_sdvo_check_supp_encode(struct intel_sdvo *intel_sdvo)
 {
 	struct intel_sdvo_encode encode;
 
+	BUILD_BUG_ON(sizeof(encode) != 2);
 	return intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_SUPP_ENCODE,
 				  &encode, sizeof(encode));
@@ -1051,6 +1062,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 	/* Set the SDVO control regs. */
 	if (INTEL_INFO(dev)->gen >= 4) {
 		sdvox = 0;
+		if (intel_sdvo->is_hdmi)
+			sdvox |= intel_sdvo->color_range;
 		if (INTEL_INFO(dev)->gen < 5)
 			sdvox |= SDVO_BORDER_ENABLE;
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -1162,6 +1175,7 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector,
 
 static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps)
 {
+	BUILD_BUG_ON(sizeof(*caps) != 8);
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_DEVICE_CAPS,
 				  caps, sizeof(*caps)))
@@ -1268,33 +1282,9 @@ void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
 static bool
 intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
 {
-	int caps = 0;
-
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1))
-		caps++;
-
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1))
-		caps++;
-
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1))
-		caps++;
-
-	return (caps > 1);
+	/* Is there more than one type of output? */
+	int caps = intel_sdvo->caps.output_flags & 0xf;
+	return caps & -caps;
 }
 
 static struct edid *
@@ -1482,7 +1472,7 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
  * Note!  This is in reply order (see loop in get_tv_modes).
  * XXX: all 60Hz refresh?
  */
-struct drm_display_mode sdvo_tv_modes[] = {
+static const struct drm_display_mode sdvo_tv_modes[] = {
 	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384,
 		   416, 0, 200, 201, 232, 233, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -1713,6 +1703,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
 {
 	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 	struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	uint16_t temp_value;
 	uint8_t cmd;
 	int ret;
@@ -1742,6 +1733,14 @@ intel_sdvo_set_property(struct drm_connector *connector,
 		goto done;
 	}
 
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_sdvo->color_range)
+			return 0;
+
+		intel_sdvo->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
 #define CHECK_PROPERTY(name, NAME) \
 	if (intel_sdvo_connector->name == property) { \
 		if (intel_sdvo_connector->cur_##name == temp_value) return 0; \
@@ -2046,6 +2045,9 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector)
 		drm_connector_attach_property(&connector->base.base,
 					      connector->force_audio_property, 0);
 	}
+
+	if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev))
+		intel_attach_broadcast_rgb_property(&connector->base.base);
 }
 
 static bool
@@ -2268,6 +2270,7 @@ static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
 	if (!intel_sdvo_set_target_output(intel_sdvo, type))
 		return false;
 
+	BUILD_BUG_ON(sizeof(format) != 6);
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_SUPPORTED_TV_FORMATS,
 				  &format, sizeof(format)))
@@ -2474,6 +2477,8 @@ static bool intel_sdvo_create_enhance_property(struct intel_sdvo *intel_sdvo,
 		uint16_t response;
 	} enhancements;
 
+	BUILD_BUG_ON(sizeof(enhancements) != 2);
+
 	enhancements.response = 0;
 	intel_sdvo_get_value(intel_sdvo,
 			     SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index fe4a53a..4256b8e 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1006,6 +1006,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 	const struct video_levels *video_levels;
 	const struct color_conversion *color_conversion;
 	bool burst_ena;
+	int pipe = intel_crtc->pipe;
 
 	if (!tv_mode)
 		return;	/* can't happen (mode_prepare prevents this) */
@@ -1149,14 +1150,11 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 			   ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
 			    (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
 	{
-		int pipeconf_reg = (intel_crtc->pipe == 0) ?
-			PIPEACONF : PIPEBCONF;
-		int dspcntr_reg = (intel_crtc->plane == 0) ?
-			DSPACNTR : DSPBCNTR;
+		int pipeconf_reg = PIPECONF(pipe);
+		int dspcntr_reg = DSPCNTR(pipe);
 		int pipeconf = I915_READ(pipeconf_reg);
 		int dspcntr = I915_READ(dspcntr_reg);
-		int dspbase_reg = (intel_crtc->plane == 0) ?
-			DSPAADDR : DSPBADDR;
+		int dspbase_reg = DSPADDR(pipe);
 		int xpos = 0x0, ypos = 0x0;
 		unsigned int xsize, ysize;
 		/* Pipe must be off here */
diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c
index 08868ac..1e1eb1d 100644
--- a/drivers/gpu/drm/mga/mga_dma.c
+++ b/drivers/gpu/drm/mga/mga_dma.c
@@ -703,7 +703,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device *dev,
 static int mga_do_dma_bootstrap(struct drm_device *dev,
 				drm_mga_dma_bootstrap_t *dma_bs)
 {
-	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+	const int is_agp = (dma_bs->agp_mode != 0) && drm_pci_device_is_agp(dev);
 	int err;
 	drm_mga_private_t *const dev_priv =
 	    (drm_mga_private_t *) dev->dev_private;
diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c
index 0aaf5f6..42d3187 100644
--- a/drivers/gpu/drm/mga/mga_drv.c
+++ b/drivers/gpu/drm/mga/mga_drv.c
@@ -75,10 +75,6 @@ static struct drm_driver driver = {
 #endif
 		.llseek = noop_llseek,
 	},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -88,15 +84,20 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver mga_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init mga_init(void)
 {
 	driver.num_ioctls = mga_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &mga_pci_driver);
 }
 
 static void __exit mga_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &mga_pci_driver);
 }
 
 module_init(mga_init);
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index d3a9c6e..00a55df 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -88,18 +88,20 @@ static const struct backlight_ops nv50_bl_ops = {
 	.update_status = nv50_set_intensity,
 };
 
-static int nouveau_nv40_backlight_init(struct drm_device *dev)
+static int nouveau_nv40_backlight_init(struct drm_connector *connector)
 {
-	struct backlight_properties props;
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
 	struct backlight_device *bd;
 
 	if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
 				       &nv40_bl_ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -111,18 +113,20 @@ static int nouveau_nv40_backlight_init(struct drm_device *dev)
 	return 0;
 }
 
-static int nouveau_nv50_backlight_init(struct drm_device *dev)
+static int nouveau_nv50_backlight_init(struct drm_connector *connector)
 {
-	struct backlight_properties props;
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
 	struct backlight_device *bd;
 
 	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 1025;
-	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
 				       &nv50_bl_ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -133,8 +137,9 @@ static int nouveau_nv50_backlight_init(struct drm_device *dev)
 	return 0;
 }
 
-int nouveau_backlight_init(struct drm_device *dev)
+int nouveau_backlight_init(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 #ifdef CONFIG_ACPI
@@ -147,9 +152,9 @@ int nouveau_backlight_init(struct drm_device *dev)
 
 	switch (dev_priv->card_type) {
 	case NV_40:
-		return nouveau_nv40_backlight_init(dev);
+		return nouveau_nv40_backlight_init(connector);
 	case NV_50:
-		return nouveau_nv50_backlight_init(dev);
+		return nouveau_nv50_backlight_init(connector);
 	default:
 		break;
 	}
@@ -157,8 +162,9 @@ int nouveau_backlight_init(struct drm_device *dev)
 	return 0;
 }
 
-void nouveau_backlight_exit(struct drm_device *dev)
+void nouveau_backlight_exit(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->backlight) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 6bdab89..8314a49 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -282,7 +282,7 @@ static void still_alive(void)
 {
 #if 0
 	sync();
-	msleep(2);
+	mdelay(2);
 #endif
 }
 
@@ -1904,7 +1904,7 @@ init_condition_time(struct nvbios *bios, uint16_t offset,
 			BIOSLOG(bios, "0x%04X: "
 				"Condition not met, sleeping for 20ms\n",
 								offset);
-			msleep(20);
+			mdelay(20);
 		}
 	}
 
@@ -1938,7 +1938,7 @@ init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 	BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n",
 		offset, time);
 
-	msleep(time);
+	mdelay(time);
 
 	return 3;
 }
@@ -2962,7 +2962,7 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 	if (time < 1000)
 		udelay(time);
 	else
-		msleep((time + 900) / 1000);
+		mdelay((time + 900) / 1000);
 
 	return 3;
 }
@@ -3856,7 +3856,7 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr
 
 	if (script == LVDS_PANEL_OFF) {
 		/* off-on delay in ms */
-		msleep(ROM16(bios->data[bios->fp.xlated_entry + 7]));
+		mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7]));
 	}
 #ifdef __powerpc__
 	/* Powerbook specific quirks */
@@ -5950,6 +5950,11 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
 	}
 }
 
+static const u8 hpd_gpio[16] = {
+	0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60,
+};
+
 static void
 parse_dcb_connector_table(struct nvbios *bios)
 {
@@ -5986,23 +5991,9 @@ parse_dcb_connector_table(struct nvbios *bios)
 
 		cte->type  = (cte->entry & 0x000000ff) >> 0;
 		cte->index2 = (cte->entry & 0x00000f00) >> 8;
-		switch (cte->entry & 0x00033000) {
-		case 0x00001000:
-			cte->gpio_tag = 0x07;
-			break;
-		case 0x00002000:
-			cte->gpio_tag = 0x08;
-			break;
-		case 0x00010000:
-			cte->gpio_tag = 0x51;
-			break;
-		case 0x00020000:
-			cte->gpio_tag = 0x52;
-			break;
-		default:
-			cte->gpio_tag = 0xff;
-			break;
-		}
+
+		cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12);
+		cte->gpio_tag = hpd_gpio[cte->gpio_tag];
 
 		if (cte->type == 0xff)
 			continue;
@@ -6702,11 +6693,11 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
 	struct nvbios *bios = &dev_priv->vbios;
 	struct init_exec iexec = { true, false };
 
-	mutex_lock(&bios->lock);
+	spin_lock_bh(&bios->lock);
 	bios->display.output = dcbent;
 	parse_init_table(bios, table, &iexec);
 	bios->display.output = NULL;
-	mutex_unlock(&bios->lock);
+	spin_unlock_bh(&bios->lock);
 }
 
 static bool NVInitVBIOS(struct drm_device *dev)
@@ -6715,7 +6706,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
 	struct nvbios *bios = &dev_priv->vbios;
 
 	memset(bios, 0, sizeof(struct nvbios));
-	mutex_init(&bios->lock);
+	spin_lock_init(&bios->lock);
 	bios->dev = dev;
 
 	if (!NVShadowVBIOS(dev, bios->data))
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 50a648e..8a54fa7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -251,7 +251,7 @@ struct nvbios {
 	uint8_t digital_min_front_porch;
 	bool fp_no_ddc;
 
-	struct mutex lock;
+	spinlock_t lock;
 
 	uint8_t data[NV_PROM_SIZE];
 	unsigned int length;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index a521840..2ad49cb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -57,8 +57,8 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
 }
 
 static void
-nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size,
-		       int *page_shift)
+nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
+		       int *align, int *size, int *page_shift)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
 
@@ -83,7 +83,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size,
 		}
 	} else {
 		if (likely(dev_priv->chan_vm)) {
-			if (*size > 256 * 1024)
+			if (!(flags & TTM_PL_FLAG_TT) &&  *size > 256 * 1024)
 				*page_shift = dev_priv->chan_vm->lpg_shift;
 			else
 				*page_shift = dev_priv->chan_vm->spg_shift;
@@ -101,8 +101,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size,
 int
 nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
 	       int size, int align, uint32_t flags, uint32_t tile_mode,
-	       uint32_t tile_flags, bool no_vm, bool mappable,
-	       struct nouveau_bo **pnvbo)
+	       uint32_t tile_flags, struct nouveau_bo **pnvbo)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
@@ -113,16 +112,14 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
 		return -ENOMEM;
 	INIT_LIST_HEAD(&nvbo->head);
 	INIT_LIST_HEAD(&nvbo->entry);
-	nvbo->mappable = mappable;
-	nvbo->no_vm = no_vm;
 	nvbo->tile_mode = tile_mode;
 	nvbo->tile_flags = tile_flags;
 	nvbo->bo.bdev = &dev_priv->ttm.bdev;
 
-	nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift);
+	nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift);
 	align >>= PAGE_SHIFT;
 
-	if (!nvbo->no_vm && dev_priv->chan_vm) {
+	if (dev_priv->chan_vm) {
 		ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
 				     NV_MEM_ACCESS_RW, &nvbo->vma);
 		if (ret) {
@@ -144,11 +141,8 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
 	}
 	nvbo->channel = NULL;
 
-	if (nvbo->vma.node) {
-		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
-			nvbo->bo.offset = nvbo->vma.offset;
-	}
-
+	if (nvbo->vma.node)
+		nvbo->bo.offset = nvbo->vma.offset;
 	*pnvbo = nvbo;
 	return 0;
 }
@@ -318,11 +312,8 @@ nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
 	if (ret)
 		return ret;
 
-	if (nvbo->vma.node) {
-		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
-			nvbo->bo.offset = nvbo->vma.offset;
-	}
-
+	if (nvbo->vma.node)
+		nvbo->bo.offset = nvbo->vma.offset;
 	return 0;
 }
 
@@ -385,7 +376,8 @@ nouveau_bo_create_ttm_backend_entry(struct ttm_bo_device *bdev)
 	case NOUVEAU_GART_AGP:
 		return ttm_agp_backend_init(bdev, dev->agp->bridge);
 #endif
-	case NOUVEAU_GART_SGDMA:
+	case NOUVEAU_GART_PDMA:
+	case NOUVEAU_GART_HW:
 		return nouveau_sgdma_init_ttm(dev);
 	default:
 		NV_ERROR(dev, "Unknown GART type %d\n",
@@ -431,7 +423,10 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
 		man->default_caching = TTM_PL_FLAG_WC;
 		break;
 	case TTM_PL_TT:
-		man->func = &ttm_bo_manager_func;
+		if (dev_priv->card_type >= NV_50)
+			man->func = &nouveau_gart_manager;
+		else
+			man->func = &ttm_bo_manager_func;
 		switch (dev_priv->gart_info.type) {
 		case NOUVEAU_GART_AGP:
 			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
@@ -439,7 +434,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
 				TTM_PL_FLAG_WC;
 			man->default_caching = TTM_PL_FLAG_WC;
 			break;
-		case NOUVEAU_GART_SGDMA:
+		case NOUVEAU_GART_PDMA:
+		case NOUVEAU_GART_HW:
 			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
 				     TTM_MEMTYPE_FLAG_CMA;
 			man->available_caching = TTM_PL_MASK_CACHING;
@@ -501,45 +497,22 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
 	return ret;
 }
 
-static inline uint32_t
-nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
-		      struct nouveau_channel *chan, struct ttm_mem_reg *mem)
-{
-	struct nouveau_bo *nvbo = nouveau_bo(bo);
-
-	if (nvbo->no_vm) {
-		if (mem->mem_type == TTM_PL_TT)
-			return NvDmaGART;
-		return NvDmaVRAM;
-	}
-
-	if (mem->mem_type == TTM_PL_TT)
-		return chan->gart_handle;
-	return chan->vram_handle;
-}
-
 static int
 nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_mem *old_node = old_mem->mm_node;
+	struct nouveau_mem *new_node = new_mem->mm_node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	u64 src_offset = old_mem->start << PAGE_SHIFT;
-	u64 dst_offset = new_mem->start << PAGE_SHIFT;
 	u32 page_count = new_mem->num_pages;
+	u64 src_offset, dst_offset;
 	int ret;
 
-	if (!nvbo->no_vm) {
-		if (old_mem->mem_type == TTM_PL_VRAM)
-			src_offset  = nvbo->vma.offset;
-		else
-			src_offset += dev_priv->gart_info.aper_base;
-
-		if (new_mem->mem_type == TTM_PL_VRAM)
-			dst_offset  = nvbo->vma.offset;
-		else
-			dst_offset += dev_priv->gart_info.aper_base;
-	}
+	src_offset = old_node->tmp_vma.offset;
+	if (new_node->tmp_vma.node)
+		dst_offset = new_node->tmp_vma.offset;
+	else
+		dst_offset = nvbo->vma.offset;
 
 	page_count = new_mem->num_pages;
 	while (page_count) {
@@ -574,33 +547,18 @@ static int
 nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_mem *old_node = old_mem->mm_node;
+	struct nouveau_mem *new_node = new_mem->mm_node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	u64 length = (new_mem->num_pages << PAGE_SHIFT);
 	u64 src_offset, dst_offset;
 	int ret;
 
-	src_offset = old_mem->start << PAGE_SHIFT;
-	dst_offset = new_mem->start << PAGE_SHIFT;
-	if (!nvbo->no_vm) {
-		if (old_mem->mem_type == TTM_PL_VRAM)
-			src_offset  = nvbo->vma.offset;
-		else
-			src_offset += dev_priv->gart_info.aper_base;
-
-		if (new_mem->mem_type == TTM_PL_VRAM)
-			dst_offset  = nvbo->vma.offset;
-		else
-			dst_offset += dev_priv->gart_info.aper_base;
-	}
-
-	ret = RING_SPACE(chan, 3);
-	if (ret)
-		return ret;
-
-	BEGIN_RING(chan, NvSubM2MF, 0x0184, 2);
-	OUT_RING  (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem));
-	OUT_RING  (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem));
+	src_offset = old_node->tmp_vma.offset;
+	if (new_node->tmp_vma.node)
+		dst_offset = new_node->tmp_vma.offset;
+	else
+		dst_offset = nvbo->vma.offset;
 
 	while (length) {
 		u32 amount, stride, height;
@@ -681,6 +639,15 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 	return 0;
 }
 
+static inline uint32_t
+nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
+		      struct nouveau_channel *chan, struct ttm_mem_reg *mem)
+{
+	if (mem->mem_type == TTM_PL_TT)
+		return chan->gart_handle;
+	return chan->vram_handle;
+}
+
 static int
 nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
@@ -734,15 +701,43 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct ttm_mem_reg *old_mem = &bo->mem;
 	struct nouveau_channel *chan;
 	int ret;
 
 	chan = nvbo->channel;
-	if (!chan || nvbo->no_vm) {
+	if (!chan) {
 		chan = dev_priv->channel;
 		mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
 	}
 
+	/* create temporary vma for old memory, this will get cleaned
+	 * up after ttm destroys the ttm_mem_reg
+	 */
+	if (dev_priv->card_type >= NV_50) {
+		struct nouveau_mem *node = old_mem->mm_node;
+		if (!node->tmp_vma.node) {
+			u32 page_shift = nvbo->vma.node->type;
+			if (old_mem->mem_type == TTM_PL_TT)
+				page_shift = nvbo->vma.vm->spg_shift;
+
+			ret = nouveau_vm_get(chan->vm,
+					     old_mem->num_pages << PAGE_SHIFT,
+					     page_shift, NV_MEM_ACCESS_RO,
+					     &node->tmp_vma);
+			if (ret)
+				goto out;
+		}
+
+		if (old_mem->mem_type == TTM_PL_VRAM)
+			nouveau_vm_map(&node->tmp_vma, node);
+		else {
+			nouveau_vm_map_sg(&node->tmp_vma, 0,
+					  old_mem->num_pages << PAGE_SHIFT,
+					  node, node->pages);
+		}
+	}
+
 	if (dev_priv->card_type < NV_50)
 		ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
 	else
@@ -756,6 +751,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
 						    no_wait_gpu, new_mem);
 	}
 
+out:
 	if (chan == dev_priv->channel)
 		mutex_unlock(&chan->mutex);
 	return ret;
@@ -766,6 +762,7 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
 		      bool no_wait_reserve, bool no_wait_gpu,
 		      struct ttm_mem_reg *new_mem)
 {
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
 	struct ttm_placement placement;
 	struct ttm_mem_reg tmp_mem;
@@ -785,7 +782,23 @@ nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
 	if (ret)
 		goto out;
 
+	if (dev_priv->card_type >= NV_50) {
+		struct nouveau_bo *nvbo = nouveau_bo(bo);
+		struct nouveau_mem *node = tmp_mem.mm_node;
+		struct nouveau_vma *vma = &nvbo->vma;
+		if (vma->node->type != vma->vm->spg_shift)
+			vma = &node->tmp_vma;
+		nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT,
+				  node, node->pages);
+	}
+
 	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
+
+	if (dev_priv->card_type >= NV_50) {
+		struct nouveau_bo *nvbo = nouveau_bo(bo);
+		nouveau_vm_unmap(&nvbo->vma);
+	}
+
 	if (ret)
 		goto out;
 
@@ -828,6 +841,36 @@ out:
 	return ret;
 }
 
+static void
+nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_mem *node = new_mem->mm_node;
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct nouveau_vma *vma = &nvbo->vma;
+	struct nouveau_vm *vm = vma->vm;
+
+	if (dev_priv->card_type < NV_50)
+		return;
+
+	switch (new_mem->mem_type) {
+	case TTM_PL_VRAM:
+		nouveau_vm_map(vma, node);
+		break;
+	case TTM_PL_TT:
+		if (vma->node->type != vm->spg_shift) {
+			nouveau_vm_unmap(vma);
+			vma = &node->tmp_vma;
+		}
+		nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT,
+				  node, node->pages);
+		break;
+	default:
+		nouveau_vm_unmap(&nvbo->vma);
+		break;
+	}
+}
+
 static int
 nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
 		   struct nouveau_tile_reg **new_tile)
@@ -835,19 +878,13 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = dev_priv->dev;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	uint64_t offset;
+	u64 offset = new_mem->start << PAGE_SHIFT;
 
-	if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
-		/* Nothing to do. */
-		*new_tile = NULL;
+	*new_tile = NULL;
+	if (new_mem->mem_type != TTM_PL_VRAM)
 		return 0;
-	}
-
-	offset = new_mem->start << PAGE_SHIFT;
 
-	if (dev_priv->chan_vm) {
-		nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
-	} else if (dev_priv->card_type >= NV_10) {
+	if (dev_priv->card_type >= NV_10) {
 		*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
 						nvbo->tile_mode,
 						nvbo->tile_flags);
@@ -864,11 +901,8 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = dev_priv->dev;
 
-	if (dev_priv->card_type >= NV_10 &&
-	    dev_priv->card_type < NV_50) {
-		nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
-		*old_tile = new_tile;
-	}
+	nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
+	*old_tile = new_tile;
 }
 
 static int
@@ -882,9 +916,11 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
 	struct nouveau_tile_reg *new_tile = NULL;
 	int ret = 0;
 
-	ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
-	if (ret)
-		return ret;
+	if (dev_priv->card_type < NV_50) {
+		ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
+		if (ret)
+			return ret;
+	}
 
 	/* Fake bo copy. */
 	if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
@@ -915,10 +951,12 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
 	ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
 
 out:
-	if (ret)
-		nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
-	else
-		nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+	if (dev_priv->card_type < NV_50) {
+		if (ret)
+			nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
+		else
+			nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+	}
 
 	return ret;
 }
@@ -959,7 +997,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 		break;
 	case TTM_PL_VRAM:
 	{
-		struct nouveau_vram *vram = mem->mm_node;
+		struct nouveau_mem *node = mem->mm_node;
 		u8 page_shift;
 
 		if (!dev_priv->bar1_vm) {
@@ -970,23 +1008,23 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 		}
 
 		if (dev_priv->card_type == NV_C0)
-			page_shift = vram->page_shift;
+			page_shift = node->page_shift;
 		else
 			page_shift = 12;
 
 		ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size,
 				     page_shift, NV_MEM_ACCESS_RW,
-				     &vram->bar_vma);
+				     &node->bar_vma);
 		if (ret)
 			return ret;
 
-		nouveau_vm_map(&vram->bar_vma, vram);
+		nouveau_vm_map(&node->bar_vma, node);
 		if (ret) {
-			nouveau_vm_put(&vram->bar_vma);
+			nouveau_vm_put(&node->bar_vma);
 			return ret;
 		}
 
-		mem->bus.offset = vram->bar_vma.offset;
+		mem->bus.offset = node->bar_vma.offset;
 		if (dev_priv->card_type == NV_50) /*XXX*/
 			mem->bus.offset -= 0x0020000000ULL;
 		mem->bus.base = pci_resource_start(dev->pdev, 1);
@@ -1003,16 +1041,16 @@ static void
 nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
-	struct nouveau_vram *vram = mem->mm_node;
+	struct nouveau_mem *node = mem->mm_node;
 
 	if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM)
 		return;
 
-	if (!vram->bar_vma.node)
+	if (!node->bar_vma.node)
 		return;
 
-	nouveau_vm_unmap(&vram->bar_vma);
-	nouveau_vm_put(&vram->bar_vma);
+	nouveau_vm_unmap(&node->bar_vma);
+	nouveau_vm_put(&node->bar_vma);
 }
 
 static int
@@ -1062,6 +1100,7 @@ struct ttm_bo_driver nouveau_bo_driver = {
 	.invalidate_caches = nouveau_bo_invalidate_caches,
 	.init_mem_type = nouveau_bo_init_mem_type,
 	.evict_flags = nouveau_bo_evict_flags,
+	.move_notify = nouveau_bo_move_ntfy,
 	.move = nouveau_bo_move,
 	.verify_access = nouveau_bo_verify_access,
 	.sync_obj_signaled = __nouveau_fence_signalled,
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 3960d66..3837090 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -35,7 +35,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *pb = chan->pushbuf_bo;
 	struct nouveau_gpuobj *pushbuf = NULL;
-	int ret;
+	int ret = 0;
 
 	if (dev_priv->card_type >= NV_50) {
 		if (dev_priv->card_type < NV_C0) {
@@ -90,8 +90,7 @@ nouveau_channel_user_pushbuf_alloc(struct drm_device *dev)
 	else
 		location = TTM_PL_FLAG_TT;
 
-	ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false,
-			     true, &pushbuf);
+	ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf);
 	if (ret) {
 		NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
 		return NULL;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 390d82c..7ae1511 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -116,6 +116,10 @@ nouveau_connector_destroy(struct drm_connector *connector)
 				      nouveau_connector_hotplug, connector);
 	}
 
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nouveau_backlight_exit(connector);
+
 	kfree(nv_connector->edid);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -894,6 +898,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
 	}
 
 	drm_sysfs_connector_add(connector);
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nouveau_backlight_init(connector);
+
 	dcb->drm = connector;
 	return dcb->drm;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 505c6bf..764c15d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -32,6 +32,7 @@
 #include "nouveau_hw.h"
 #include "nouveau_crtc.h"
 #include "nouveau_dma.h"
+#include "nv50_display.h"
 
 static void
 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
@@ -61,18 +62,59 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
 };
 
 int
-nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
-			 struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo)
+nouveau_framebuffer_init(struct drm_device *dev,
+			 struct nouveau_framebuffer *nv_fb,
+			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct nouveau_bo *nvbo)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_framebuffer *fb = &nv_fb->base;
 	int ret;
 
-	ret = drm_framebuffer_init(dev, &nouveau_fb->base, &nouveau_framebuffer_funcs);
+	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
 	if (ret) {
 		return ret;
 	}
 
-	drm_helper_mode_fill_fb_struct(&nouveau_fb->base, mode_cmd);
-	nouveau_fb->nvbo = nvbo;
+	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+	nv_fb->nvbo = nvbo;
+
+	if (dev_priv->card_type >= NV_50) {
+		u32 tile_flags = nouveau_bo_tile_layout(nvbo);
+		if (tile_flags == 0x7a00 ||
+		    tile_flags == 0xfe00)
+			nv_fb->r_dma = NvEvoFB32;
+		else
+		if (tile_flags == 0x7000)
+			nv_fb->r_dma = NvEvoFB16;
+		else
+			nv_fb->r_dma = NvEvoVRAM_LP;
+
+		switch (fb->depth) {
+		case  8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break;
+		case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break;
+		case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break;
+		case 24:
+		case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break;
+		case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break;
+		default:
+			 NV_ERROR(dev, "unknown depth %d\n", fb->depth);
+			 return -EINVAL;
+		}
+
+		if (dev_priv->chipset == 0x50)
+			nv_fb->r_format |= (tile_flags << 8);
+
+		if (!tile_flags)
+			nv_fb->r_pitch = 0x00100000 | fb->pitch;
+		else {
+			u32 mode = nvbo->tile_mode;
+			if (dev_priv->card_type >= NV_C0)
+				mode >>= 4;
+			nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode;
+		}
+	}
+
 	return 0;
 }
 
@@ -182,6 +224,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
 		       struct nouveau_page_flip_state *s,
 		       struct nouveau_fence **pfence)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
 	unsigned long flags;
 	int ret;
@@ -201,9 +244,12 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
 	if (ret)
 		goto fail;
 
-	BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
-	OUT_RING(chan, 0);
-	FIRE_RING(chan);
+	if (dev_priv->card_type < NV_C0)
+		BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
+	else
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1);
+	OUT_RING  (chan, 0);
+	FIRE_RING (chan);
 
 	ret = nouveau_fence_new(chan, pfence, true);
 	if (ret)
@@ -244,7 +290,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 
 	/* Initialize a page flip struct */
 	*s = (struct nouveau_page_flip_state)
-		{ { }, s->event, nouveau_crtc(crtc)->index,
+		{ { }, event, nouveau_crtc(crtc)->index,
 		  fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
 		  new_bo->bo.offset };
 
@@ -255,6 +301,14 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
 	mutex_lock(&chan->mutex);
 
 	/* Emit a page flip */
+	if (dev_priv->card_type >= NV_50) {
+		ret = nv50_display_flip_next(crtc, fb, chan);
+		if (ret) {
+			nouveau_channel_put(&chan);
+			goto fail_unreserve;
+		}
+	}
+
 	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
 	nouveau_channel_put(&chan);
 	if (ret)
@@ -305,7 +359,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
 	}
 
 	list_del(&s->head);
-	*ps = *s;
+	if (ps)
+		*ps = *s;
 	kfree(s);
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index b368ed7..ce38e97 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -97,13 +97,15 @@ nouveau_dma_init(struct nouveau_channel *chan)
 		OUT_RING(chan, 0);
 
 	/* Initialise NV_MEMORY_TO_MEMORY_FORMAT */
-	ret = RING_SPACE(chan, 4);
+	ret = RING_SPACE(chan, 6);
 	if (ret)
 		return ret;
 	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
-	OUT_RING(chan, NvM2MF);
-	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
-	OUT_RING(chan, NvNotify0);
+	OUT_RING  (chan, NvM2MF);
+	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
+	OUT_RING  (chan, NvNotify0);
+	OUT_RING  (chan, chan->vram_handle);
+	OUT_RING  (chan, chan->gart_handle);
 
 	/* Sit back and pray the channel works.. */
 	FIRE_RING(chan);
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index c36f176..23d4edf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -61,8 +61,6 @@ enum {
 	NvM2MF		= 0x80000001,
 	NvDmaFB		= 0x80000002,
 	NvDmaTT		= 0x80000003,
-	NvDmaVRAM	= 0x80000004,
-	NvDmaGART	= 0x80000005,
 	NvNotify0       = 0x80000006,
 	Nv2D		= 0x80000007,
 	NvCtxSurf2D	= 0x80000008,
@@ -73,12 +71,15 @@ enum {
 	NvImageBlit	= 0x8000000d,
 	NvSw		= 0x8000000e,
 	NvSema		= 0x8000000f,
+	NvEvoSema0	= 0x80000010,
+	NvEvoSema1	= 0x80000011,
 
 	/* G80+ display objects */
 	NvEvoVRAM	= 0x01000000,
 	NvEvoFB16	= 0x01000001,
 	NvEvoFB32	= 0x01000002,
-	NvEvoVRAM_LP	= 0x01000003
+	NvEvoVRAM_LP	= 0x01000003,
+	NvEvoSync	= 0xcafe0000
 };
 
 #define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 38d5995..7beb82a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -175,7 +175,6 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table_entry *dpse;
 	struct bit_displayport_encoder_table *dpe;
 	int ret, i, dpe_headerlen, vs = 0, pre = 0;
 	uint8_t request[2];
@@ -183,7 +182,6 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config)
 	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
 	if (!dpe)
 		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
 
 	ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
 	if (ret)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index f658a04..155ebdc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -408,14 +408,6 @@ static struct drm_driver driver = {
 #endif
 		.llseek = noop_llseek,
 	},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-		.probe = nouveau_pci_probe,
-		.remove = nouveau_pci_remove,
-		.suspend = nouveau_pci_suspend,
-		.resume = nouveau_pci_resume
-	},
 
 	.gem_init_object = nouveau_gem_object_new,
 	.gem_free_object = nouveau_gem_object_del,
@@ -432,6 +424,15 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver nouveau_pci_driver = {
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
+		.probe = nouveau_pci_probe,
+		.remove = nouveau_pci_remove,
+		.suspend = nouveau_pci_suspend,
+		.resume = nouveau_pci_resume
+};
+
 static int __init nouveau_init(void)
 {
 	driver.num_ioctls = nouveau_max_ioctl;
@@ -449,7 +450,7 @@ static int __init nouveau_init(void)
 		return 0;
 
 	nouveau_register_dsm_handler();
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &nouveau_pci_driver);
 }
 
 static void __exit nouveau_exit(void)
@@ -457,7 +458,7 @@ static void __exit nouveau_exit(void)
 	if (!nouveau_modeset)
 		return;
 
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &nouveau_pci_driver);
 	nouveau_unregister_dsm_handler();
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 982d70b..fff180a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -57,7 +57,7 @@ struct nouveau_fpriv {
 #include "nouveau_util.h"
 
 struct nouveau_grctx;
-struct nouveau_vram;
+struct nouveau_mem;
 #include "nouveau_vm.h"
 
 #define MAX_NUM_DCB_ENTRIES 16
@@ -65,13 +65,16 @@ struct nouveau_vram;
 #define NOUVEAU_MAX_CHANNEL_NR 128
 #define NOUVEAU_MAX_TILE_NR 15
 
-struct nouveau_vram {
+struct nouveau_mem {
 	struct drm_device *dev;
 
 	struct nouveau_vma bar_vma;
+	struct nouveau_vma tmp_vma;
 	u8  page_shift;
 
+	struct drm_mm_node *tag;
 	struct list_head regions;
+	dma_addr_t *pages;
 	u32 memtype;
 	u64 offset;
 	u64 size;
@@ -90,6 +93,7 @@ struct nouveau_tile_reg {
 struct nouveau_bo {
 	struct ttm_buffer_object bo;
 	struct ttm_placement placement;
+	u32 valid_domains;
 	u32 placements[3];
 	u32 busy_placements[3];
 	struct ttm_bo_kmap_obj kmap;
@@ -104,8 +108,6 @@ struct nouveau_bo {
 	struct nouveau_channel *channel;
 
 	struct nouveau_vma vma;
-	bool mappable;
-	bool no_vm;
 
 	uint32_t tile_mode;
 	uint32_t tile_flags;
@@ -387,6 +389,7 @@ struct nouveau_pgraph_engine {
 };
 
 struct nouveau_display_engine {
+	void *priv;
 	int (*early_init)(struct drm_device *);
 	void (*late_takedown)(struct drm_device *);
 	int (*create)(struct drm_device *);
@@ -509,8 +512,8 @@ struct nouveau_crypt_engine {
 struct nouveau_vram_engine {
 	int  (*init)(struct drm_device *);
 	int  (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
-		    u32 type, struct nouveau_vram **);
-	void (*put)(struct drm_device *, struct nouveau_vram **);
+		    u32 type, struct nouveau_mem **);
+	void (*put)(struct drm_device *, struct nouveau_mem **);
 
 	bool (*flags_valid)(struct drm_device *, u32 tile_flags);
 };
@@ -652,8 +655,6 @@ struct drm_nouveau_private {
 	/* interrupt handling */
 	void (*irq_handler[32])(struct drm_device *);
 	bool msi_enabled;
-	struct workqueue_struct *wq;
-	struct work_struct irq_work;
 
 	struct list_head vbl_waiting;
 
@@ -691,15 +692,22 @@ struct drm_nouveau_private {
 	struct {
 		enum {
 			NOUVEAU_GART_NONE = 0,
-			NOUVEAU_GART_AGP,
-			NOUVEAU_GART_SGDMA
+			NOUVEAU_GART_AGP,	/* AGP */
+			NOUVEAU_GART_PDMA,	/* paged dma object */
+			NOUVEAU_GART_HW		/* on-chip gart/vm */
 		} type;
 		uint64_t aper_base;
 		uint64_t aper_size;
 		uint64_t aper_free;
 
+		struct ttm_backend_func *func;
+
+		struct {
+			struct page *page;
+			dma_addr_t   addr;
+		} dummy;
+
 		struct nouveau_gpuobj *sg_ctxdma;
-		struct nouveau_vma vma;
 	} gart_info;
 
 	/* nv10-nv40 tiling regions */
@@ -740,14 +748,6 @@ struct drm_nouveau_private {
 
 	struct backlight_device *backlight;
 
-	struct nouveau_channel *evo;
-	u32 evo_alloc;
-	struct {
-		struct dcb_entry *dcb;
-		u16 script;
-		u32 pclk;
-	} evo_irq;
-
 	struct {
 		struct dentry *channel_root;
 	} debugfs;
@@ -847,6 +847,7 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev,
 				     struct nouveau_tile_reg *tile,
 				     struct nouveau_fence *fence);
 extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
+extern const struct ttm_mem_type_manager_func nouveau_gart_manager;
 
 /* nouveau_notifier.c */
 extern int  nouveau_notifier_init_channel(struct nouveau_channel *);
@@ -998,15 +999,15 @@ static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector
 
 /* nouveau_backlight.c */
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_exit(struct drm_connector *);
 #else
-static inline int nouveau_backlight_init(struct drm_device *dev)
+static inline int nouveau_backlight_init(struct drm_connector *dev)
 {
 	return 0;
 }
 
-static inline void nouveau_backlight_exit(struct drm_device *dev) { }
+static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
 #endif
 
 /* nouveau_bios.c */
@@ -1076,7 +1077,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
 /* nv50_fb.c */
 extern int  nv50_fb_init(struct drm_device *);
 extern void nv50_fb_takedown(struct drm_device *);
-extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *);
+extern void nv50_fb_vm_trap(struct drm_device *, int display);
 
 /* nvc0_fb.c */
 extern int  nvc0_fb_init(struct drm_device *);
@@ -1295,7 +1296,7 @@ extern struct ttm_bo_driver nouveau_bo_driver;
 extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *,
 			  int size, int align, uint32_t flags,
 			  uint32_t tile_mode, uint32_t tile_flags,
-			  bool no_vm, bool mappable, struct nouveau_bo **);
+			  struct nouveau_bo **);
 extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
 extern int nouveau_bo_unpin(struct nouveau_bo *);
 extern int nouveau_bo_map(struct nouveau_bo *);
@@ -1356,9 +1357,9 @@ static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj)
 
 /* nouveau_gem.c */
 extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
-			   int size, int align, uint32_t flags,
+			   int size, int align, uint32_t domain,
 			   uint32_t tile_mode, uint32_t tile_flags,
-			   bool no_vm, bool mappable, struct nouveau_bo **);
+			   struct nouveau_bo **);
 extern int nouveau_gem_object_new(struct drm_gem_object *);
 extern void nouveau_gem_object_del(struct drm_gem_object *);
 extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
diff --git a/drivers/gpu/drm/nouveau/nouveau_fb.h b/drivers/gpu/drm/nouveau/nouveau_fb.h
index d432134..a3a88ad 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fb.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fb.h
@@ -30,6 +30,9 @@
 struct nouveau_framebuffer {
 	struct drm_framebuffer base;
 	struct nouveau_bo *nvbo;
+	u32 r_dma;
+	u32 r_format;
+	u32 r_pitch;
 };
 
 static inline struct nouveau_framebuffer *
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 60769d2..889c445 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -296,8 +296,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
 	size = mode_cmd.pitch * mode_cmd.height;
 	size = roundup(size, PAGE_SIZE);
 
-	ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM,
-			      0, 0x0000, false, true, &nvbo);
+	ret = nouveau_gem_new(dev, dev_priv->channel, size, 0,
+			      NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
 	if (ret) {
 		NV_ERROR(dev, "failed to allocate framebuffer\n");
 		goto out;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index 221b846..4b9f449 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -27,13 +27,15 @@
 #include "drmP.h"
 #include "drm.h"
 
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+
 #include "nouveau_drv.h"
 #include "nouveau_ramht.h"
 #include "nouveau_dma.h"
 
 #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
-#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \
-		       nouveau_private(dev)->card_type < NV_C0)
+#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)
 
 struct nouveau_fence {
 	struct nouveau_channel *channel;
@@ -230,7 +232,8 @@ int
 __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 {
 	unsigned long timeout = jiffies + (3 * DRM_HZ);
-	unsigned long sleep_time = jiffies + 1;
+	unsigned long sleep_time = NSEC_PER_MSEC / 1000;
+	ktime_t t;
 	int ret = 0;
 
 	while (1) {
@@ -244,8 +247,13 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 
 		__set_current_state(intr ? TASK_INTERRUPTIBLE
 			: TASK_UNINTERRUPTIBLE);
-		if (lazy && time_after_eq(jiffies, sleep_time))
-			schedule_timeout(1);
+		if (lazy) {
+			t = ktime_set(0, sleep_time);
+			schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+			sleep_time *= 2;
+			if (sleep_time > NSEC_PER_MSEC)
+				sleep_time = NSEC_PER_MSEC;
+		}
 
 		if (intr && signal_pending(current)) {
 			ret = -ERESTARTSYS;
@@ -259,11 +267,12 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 }
 
 static struct nouveau_semaphore *
-alloc_semaphore(struct drm_device *dev)
+semaphore_alloc(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_semaphore *sema;
-	int ret;
+	int size = (dev_priv->chipset < 0x84) ? 4 : 16;
+	int ret, i;
 
 	if (!USE_SEMA(dev))
 		return NULL;
@@ -277,9 +286,9 @@ alloc_semaphore(struct drm_device *dev)
 		goto fail;
 
 	spin_lock(&dev_priv->fence.lock);
-	sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0);
+	sema->mem = drm_mm_search_free(&dev_priv->fence.heap, size, 0, 0);
 	if (sema->mem)
-		sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0);
+		sema->mem = drm_mm_get_block_atomic(sema->mem, size, 0);
 	spin_unlock(&dev_priv->fence.lock);
 
 	if (!sema->mem)
@@ -287,7 +296,8 @@ alloc_semaphore(struct drm_device *dev)
 
 	kref_init(&sema->ref);
 	sema->dev = dev;
-	nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0);
+	for (i = sema->mem->start; i < sema->mem->start + size; i += 4)
+		nouveau_bo_wr32(dev_priv->fence.bo, i / 4, 0);
 
 	return sema;
 fail:
@@ -296,7 +306,7 @@ fail:
 }
 
 static void
-free_semaphore(struct kref *ref)
+semaphore_free(struct kref *ref)
 {
 	struct nouveau_semaphore *sema =
 		container_of(ref, struct nouveau_semaphore, ref);
@@ -318,61 +328,107 @@ semaphore_work(void *priv, bool signalled)
 	if (unlikely(!signalled))
 		nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1);
 
-	kref_put(&sema->ref, free_semaphore);
+	kref_put(&sema->ref, semaphore_free);
 }
 
 static int
-emit_semaphore(struct nouveau_channel *chan, int method,
-	       struct nouveau_semaphore *sema)
+semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 {
-	struct drm_nouveau_private *dev_priv = sema->dev->dev_private;
-	struct nouveau_fence *fence;
-	bool smart = (dev_priv->card_type >= NV_50);
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_fence *fence = NULL;
 	int ret;
 
-	ret = RING_SPACE(chan, smart ? 8 : 4);
+	if (dev_priv->chipset < 0x84) {
+		ret = RING_SPACE(chan, 3);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2);
+		OUT_RING  (chan, sema->mem->start);
+		OUT_RING  (chan, 1);
+	} else
+	if (dev_priv->chipset < 0xc0) {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 1); /* ACQUIRE_EQ */
+	} else {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0x1001); /* ACQUIRE_EQ */
+	}
+
+	/* Delay semaphore destruction until its work is done */
+	ret = nouveau_fence_new(chan, &fence, true);
 	if (ret)
 		return ret;
 
-	if (smart) {
-		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
-		OUT_RING(chan, NvSema);
-	}
-	BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1);
-	OUT_RING(chan, sema->mem->start);
-
-	if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) {
-		/*
-		 * NV50 tries to be too smart and context-switch
-		 * between semaphores instead of doing a "first come,
-		 * first served" strategy like previous cards
-		 * do.
-		 *
-		 * That's bad because the ACQUIRE latency can get as
-		 * large as the PFIFO context time slice in the
-		 * typical DRI2 case where you have several
-		 * outstanding semaphores at the same moment.
-		 *
-		 * If we're going to ACQUIRE, force the card to
-		 * context switch before, just in case the matching
-		 * RELEASE is already scheduled to be executed in
-		 * another channel.
-		 */
-		BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1);
-		OUT_RING(chan, 0);
-	}
+	kref_get(&sema->ref);
+	nouveau_fence_work(fence, semaphore_work, sema);
+	nouveau_fence_unref(&fence);
+	return 0;
+}
+
+static int
+semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_fence *fence = NULL;
+	int ret;
+
+	if (dev_priv->chipset < 0x84) {
+		ret = RING_SPACE(chan, 4);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1);
+		OUT_RING  (chan, sema->mem->start);
+		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
+		OUT_RING  (chan, 1);
+	} else
+	if (dev_priv->chipset < 0xc0) {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 2); /* RELEASE */
+	} else {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
 
-	BEGIN_RING(chan, NvSubSw, method, 1);
-	OUT_RING(chan, 1);
-
-	if (smart && method == NV_SW_SEMAPHORE_RELEASE) {
-		/*
-		 * Force the card to context switch, there may be
-		 * another channel waiting for the semaphore we just
-		 * released.
-		 */
-		BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1);
-		OUT_RING(chan, 0);
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0x1002); /* RELEASE */
 	}
 
 	/* Delay semaphore destruction until its work is done */
@@ -383,7 +439,6 @@ emit_semaphore(struct nouveau_channel *chan, int method,
 	kref_get(&sema->ref);
 	nouveau_fence_work(fence, semaphore_work, sema);
 	nouveau_fence_unref(&fence);
-
 	return 0;
 }
 
@@ -400,7 +455,7 @@ nouveau_fence_sync(struct nouveau_fence *fence,
 		   nouveau_fence_signalled(fence)))
 		goto out;
 
-	sema = alloc_semaphore(dev);
+	sema = semaphore_alloc(dev);
 	if (!sema) {
 		/* Early card or broken userspace, fall back to
 		 * software sync. */
@@ -418,17 +473,17 @@ nouveau_fence_sync(struct nouveau_fence *fence,
 	}
 
 	/* Make wchan wait until it gets signalled */
-	ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema);
+	ret = semaphore_acquire(wchan, sema);
 	if (ret)
 		goto out_unlock;
 
 	/* Signal the semaphore from chan */
-	ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema);
+	ret = semaphore_release(chan, sema);
 
 out_unlock:
 	mutex_unlock(&chan->mutex);
 out_unref:
-	kref_put(&sema->ref, free_semaphore);
+	kref_put(&sema->ref, semaphore_free);
 out:
 	if (chan)
 		nouveau_channel_put_unlocked(&chan);
@@ -449,22 +504,23 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 	struct nouveau_gpuobj *obj = NULL;
 	int ret;
 
+	if (dev_priv->card_type >= NV_C0)
+		goto out_initialised;
+
 	/* Create an NV_SW object for various sync purposes */
 	ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
 	if (ret)
 		return ret;
 
 	/* we leave subchannel empty for nvc0 */
-	if (dev_priv->card_type < NV_C0) {
-		ret = RING_SPACE(chan, 2);
-		if (ret)
-			return ret;
-		BEGIN_RING(chan, NvSubSw, 0, 1);
-		OUT_RING(chan, NvSw);
-	}
+	ret = RING_SPACE(chan, 2);
+	if (ret)
+		return ret;
+	BEGIN_RING(chan, NvSubSw, 0, 1);
+	OUT_RING(chan, NvSw);
 
 	/* Create a DMA object for the shared cross-channel sync area. */
-	if (USE_SEMA(dev)) {
+	if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
 		struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
 
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
@@ -484,14 +540,20 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
 			return ret;
 		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
 		OUT_RING(chan, NvSema);
+	} else {
+		ret = RING_SPACE(chan, 2);
+		if (ret)
+			return ret;
+		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
+		OUT_RING  (chan, chan->vram_handle); /* whole VM */
 	}
 
 	FIRE_RING(chan);
 
+out_initialised:
 	INIT_LIST_HEAD(&chan->fence.pending);
 	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
-
 	return 0;
 }
 
@@ -519,12 +581,13 @@ int
 nouveau_fence_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int size = (dev_priv->chipset < 0x84) ? 4096 : 16384;
 	int ret;
 
 	/* Create a shared VRAM heap for cross-channel sync. */
 	if (USE_SEMA(dev)) {
-		ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM,
-				     0, 0, false, true, &dev_priv->fence.bo);
+		ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM,
+				     0, 0, &dev_priv->fence.bo);
 		if (ret)
 			return ret;
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 506c508..e8b04f4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -61,19 +61,36 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
 
 int
 nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
-		int size, int align, uint32_t flags, uint32_t tile_mode,
-		uint32_t tile_flags, bool no_vm, bool mappable,
-		struct nouveau_bo **pnvbo)
+		int size, int align, uint32_t domain, uint32_t tile_mode,
+		uint32_t tile_flags, struct nouveau_bo **pnvbo)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
+	u32 flags = 0;
 	int ret;
 
+	if (domain & NOUVEAU_GEM_DOMAIN_VRAM)
+		flags |= TTM_PL_FLAG_VRAM;
+	if (domain & NOUVEAU_GEM_DOMAIN_GART)
+		flags |= TTM_PL_FLAG_TT;
+	if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
+		flags |= TTM_PL_FLAG_SYSTEM;
+
 	ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode,
-			     tile_flags, no_vm, mappable, pnvbo);
+			     tile_flags, pnvbo);
 	if (ret)
 		return ret;
 	nvbo = *pnvbo;
 
+	/* we restrict allowed domains on nv50+ to only the types
+	 * that were requested at creation time.  not possibly on
+	 * earlier chips without busting the ABI.
+	 */
+	nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM |
+			      NOUVEAU_GEM_DOMAIN_GART;
+	if (dev_priv->card_type >= NV_50)
+		nvbo->valid_domains &= domain;
+
 	nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size);
 	if (!nvbo->gem) {
 		nouveau_bo_ref(NULL, pnvbo);
@@ -97,7 +114,7 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep)
 
 	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
 	rep->offset = nvbo->bo.offset;
-	rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0;
+	rep->map_handle = nvbo->bo.addr_space_offset;
 	rep->tile_mode = nvbo->tile_mode;
 	rep->tile_flags = nvbo->tile_flags;
 	return 0;
@@ -111,19 +128,11 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
 	struct drm_nouveau_gem_new *req = data;
 	struct nouveau_bo *nvbo = NULL;
 	struct nouveau_channel *chan = NULL;
-	uint32_t flags = 0;
 	int ret = 0;
 
 	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
 		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
 
-	if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM)
-		flags |= TTM_PL_FLAG_VRAM;
-	if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART)
-		flags |= TTM_PL_FLAG_TT;
-	if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU)
-		flags |= TTM_PL_FLAG_SYSTEM;
-
 	if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) {
 		NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags);
 		return -EINVAL;
@@ -135,10 +144,9 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
 			return PTR_ERR(chan);
 	}
 
-	ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags,
-			      req->info.tile_mode, req->info.tile_flags, false,
-			      (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE),
-			      &nvbo);
+	ret = nouveau_gem_new(dev, chan, req->info.size, req->align,
+			      req->info.domain, req->info.tile_mode,
+			      req->info.tile_flags, &nvbo);
 	if (chan)
 		nouveau_channel_put(&chan);
 	if (ret)
@@ -161,7 +169,7 @@ nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains,
 {
 	struct nouveau_bo *nvbo = gem->driver_private;
 	struct ttm_buffer_object *bo = &nvbo->bo;
-	uint32_t domains = valid_domains &
+	uint32_t domains = valid_domains & nvbo->valid_domains &
 		(write_domains ? write_domains : read_domains);
 	uint32_t pref_flags = 0, valid_flags = 0;
 
@@ -592,7 +600,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 		if (push[i].bo_index >= req->nr_buffers) {
 			NV_ERROR(dev, "push %d buffer not in list\n", i);
 			ret = -EINVAL;
-			goto out;
+			goto out_prevalid;
 		}
 
 		bo[push[i].bo_index].read_domains |= (1 << 31);
@@ -604,7 +612,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 	if (ret) {
 		if (ret != -ERESTARTSYS)
 			NV_ERROR(dev, "validate: %d\n", ret);
-		goto out;
+		goto out_prevalid;
 	}
 
 	/* Apply any relocations that are required */
@@ -697,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 out:
 	validate_fini(&op, fence);
 	nouveau_fence_unref(&fence);
+
+out_prevalid:
 	kfree(bo);
 	kfree(push);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index b0fb9bd..2683377 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -152,7 +152,6 @@ nouveau_mem_vram_fini(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-	nouveau_bo_unpin(dev_priv->vga_ram);
 	nouveau_bo_ref(NULL, &dev_priv->vga_ram);
 
 	ttm_bo_device_release(&dev_priv->ttm.bdev);
@@ -393,11 +392,17 @@ nouveau_mem_vram_init(struct drm_device *dev)
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	int ret, dma_bits;
 
-	if (dev_priv->card_type >= NV_50 &&
-	    pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
-		dma_bits = 40;
-	else
-		dma_bits = 32;
+	dma_bits = 32;
+	if (dev_priv->card_type >= NV_50) {
+		if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
+			dma_bits = 40;
+	} else
+	if (drm_pci_device_is_pcie(dev) &&
+	    dev_priv->chipset != 0x40 &&
+	    dev_priv->chipset != 0x45) {
+		if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
+			dma_bits = 39;
+	}
 
 	ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits));
 	if (ret)
@@ -419,14 +424,32 @@ nouveau_mem_vram_init(struct drm_device *dev)
 	}
 
 	/* reserve space at end of VRAM for PRAMIN */
-	if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 ||
-	    dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b)
-		dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024);
-	else
-	if (dev_priv->card_type >= NV_40)
-		dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024);
-	else
-		dev_priv->ramin_rsvd_vram = (512 * 1024);
+	if (dev_priv->card_type >= NV_50) {
+		dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
+	} else
+	if (dev_priv->card_type >= NV_40) {
+		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
+		u32 rsvd;
+
+		/* estimate grctx size, the magics come from nv40_grctx.c */
+		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
+		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
+		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
+		else				    rsvd = 0x4a40 * vs;
+		rsvd += 16 * 1024;
+		rsvd *= dev_priv->engine.fifo.channels;
+
+		/* pciegart table */
+		if (drm_pci_device_is_pcie(dev))
+			rsvd += 512 * 1024;
+
+		/* object storage */
+		rsvd += 512 * 1024;
+
+		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
+	} else {
+		dev_priv->ramin_rsvd_vram = 512 * 1024;
+	}
 
 	ret = dev_priv->engine.vram.init(dev);
 	if (ret)
@@ -455,13 +478,17 @@ nouveau_mem_vram_init(struct drm_device *dev)
 		return ret;
 	}
 
-	ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
-			     0, 0, true, true, &dev_priv->vga_ram);
-	if (ret == 0)
-		ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
-	if (ret) {
-		NV_WARN(dev, "failed to reserve VGA memory\n");
-		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+	if (dev_priv->card_type < NV_50) {
+		ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+				     0, 0, &dev_priv->vga_ram);
+		if (ret == 0)
+			ret = nouveau_bo_pin(dev_priv->vga_ram,
+					     TTM_PL_FLAG_VRAM);
+
+		if (ret) {
+			NV_WARN(dev, "failed to reserve VGA memory\n");
+			nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+		}
 	}
 
 	dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
@@ -480,7 +507,7 @@ nouveau_mem_gart_init(struct drm_device *dev)
 	dev_priv->gart_info.type = NOUVEAU_GART_NONE;
 
 #if !defined(__powerpc__) && !defined(__ia64__)
-	if (drm_device_is_agp(dev) && dev->agp && nouveau_agpmode) {
+	if (drm_pci_device_is_agp(dev) && dev->agp && nouveau_agpmode) {
 		ret = nouveau_mem_init_agp(dev);
 		if (ret)
 			NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
@@ -666,13 +693,14 @@ nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 	struct nouveau_mm *mm;
-	u32 b_size;
+	u64 size, block, rsvd;
 	int ret;
 
-	p_size = (p_size << PAGE_SHIFT) >> 12;
-	b_size = dev_priv->vram_rblock_size >> 12;
+	rsvd  = (256 * 1024); /* vga memory */
+	size  = (p_size << PAGE_SHIFT) - rsvd;
+	block = dev_priv->vram_rblock_size;
 
-	ret = nouveau_mm_init(&mm, 0, p_size, b_size);
+	ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
 	if (ret)
 		return ret;
 
@@ -700,9 +728,15 @@ nouveau_vram_manager_del(struct ttm_mem_type_manager *man,
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	struct nouveau_mem *node = mem->mm_node;
 	struct drm_device *dev = dev_priv->dev;
 
-	vram->put(dev, (struct nouveau_vram **)&mem->mm_node);
+	if (node->tmp_vma.node) {
+		nouveau_vm_unmap(&node->tmp_vma);
+		nouveau_vm_put(&node->tmp_vma);
+	}
+
+	vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
 }
 
 static int
@@ -715,7 +749,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
 	struct drm_device *dev = dev_priv->dev;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	struct nouveau_vram *node;
+	struct nouveau_mem *node;
 	u32 size_nc = 0;
 	int ret;
 
@@ -724,7 +758,7 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man,
 
 	ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
 			mem->page_alignment << PAGE_SHIFT, size_nc,
-			(nvbo->tile_flags >> 8) & 0xff, &node);
+			(nvbo->tile_flags >> 8) & 0x3ff, &node);
 	if (ret) {
 		mem->mm_node = NULL;
 		return (ret == -ENOSPC) ? 0 : ret;
@@ -771,3 +805,84 @@ const struct ttm_mem_type_manager_func nouveau_vram_manager = {
 	nouveau_vram_manager_del,
 	nouveau_vram_manager_debug
 };
+
+static int
+nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
+{
+	return 0;
+}
+
+static int
+nouveau_gart_manager_fini(struct ttm_mem_type_manager *man)
+{
+	return 0;
+}
+
+static void
+nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
+			 struct ttm_mem_reg *mem)
+{
+	struct nouveau_mem *node = mem->mm_node;
+
+	if (node->tmp_vma.node) {
+		nouveau_vm_unmap(&node->tmp_vma);
+		nouveau_vm_put(&node->tmp_vma);
+	}
+	mem->mm_node = NULL;
+}
+
+static int
+nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
+			 struct ttm_buffer_object *bo,
+			 struct ttm_placement *placement,
+			 struct ttm_mem_reg *mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct nouveau_vma *vma = &nvbo->vma;
+	struct nouveau_vm *vm = vma->vm;
+	struct nouveau_mem *node;
+	int ret;
+
+	if (unlikely((mem->num_pages << PAGE_SHIFT) >=
+		     dev_priv->gart_info.aper_size))
+		return -ENOMEM;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+
+	/* This node must be for evicting large-paged VRAM
+	 * to system memory.  Due to a nv50 limitation of
+	 * not being able to mix large/small pages within
+	 * the same PDE, we need to create a temporary
+	 * small-paged VMA for the eviction.
+	 */
+	if (vma->node->type != vm->spg_shift) {
+		ret = nouveau_vm_get(vm, (u64)vma->node->length << 12,
+				     vm->spg_shift, NV_MEM_ACCESS_RW,
+				     &node->tmp_vma);
+		if (ret) {
+			kfree(node);
+			return ret;
+		}
+	}
+
+	node->page_shift = nvbo->vma.node->type;
+	mem->mm_node = node;
+	mem->start   = 0;
+	return 0;
+}
+
+void
+nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix)
+{
+}
+
+const struct ttm_mem_type_manager_func nouveau_gart_manager = {
+	nouveau_gart_manager_init,
+	nouveau_gart_manager_fini,
+	nouveau_gart_manager_new,
+	nouveau_gart_manager_del,
+	nouveau_gart_manager_debug
+};
diff --git a/drivers/gpu/drm/nouveau/nouveau_mm.h b/drivers/gpu/drm/nouveau/nouveau_mm.h
index 798eaf3..1f7483a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_mm.h
@@ -53,13 +53,13 @@ void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *);
 
 int  nv50_vram_init(struct drm_device *);
 int  nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
-		    u32 memtype, struct nouveau_vram **);
-void nv50_vram_del(struct drm_device *, struct nouveau_vram **);
+		    u32 memtype, struct nouveau_mem **);
+void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
 bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);
 
 int  nvc0_vram_init(struct drm_device *);
 int  nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin,
-		    u32 memtype, struct nouveau_vram **);
+		    u32 memtype, struct nouveau_mem **);
 bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_notifier.c b/drivers/gpu/drm/nouveau/nouveau_notifier.c
index 5ea1676..7ba3fc0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_notifier.c
+++ b/drivers/gpu/drm/nouveau/nouveau_notifier.c
@@ -39,12 +39,11 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
 	int ret;
 
 	if (nouveau_vram_notify)
-		flags = TTM_PL_FLAG_VRAM;
+		flags = NOUVEAU_GEM_DOMAIN_VRAM;
 	else
-		flags = TTM_PL_FLAG_TT;
+		flags = NOUVEAU_GEM_DOMAIN_GART;
 
-	ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags,
-			      0, 0x0000, false, true, &ntfy);
+	ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
 	if (ret)
 		return ret;
 
@@ -100,6 +99,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
 		       uint32_t *b_offset)
 {
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *nobj = NULL;
 	struct drm_mm_node *mem;
 	uint32_t offset;
@@ -114,11 +114,16 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
 		return -ENOMEM;
 	}
 
-	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM)
-		target = NV_MEM_TARGET_VRAM;
-	else
-		target = NV_MEM_TARGET_GART;
-	offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+	if (dev_priv->card_type < NV_50) {
+		if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM)
+			target = NV_MEM_TARGET_VRAM;
+		else
+			target = NV_MEM_TARGET_GART;
+		offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+	} else {
+		target = NV_MEM_TARGET_VM;
+		offset = chan->notifier_bo->vma.offset;
+	}
 	offset += mem->start;
 
 	ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset,
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c
index 30b6544..4f00c87 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -36,6 +36,7 @@
 #include "nouveau_drm.h"
 #include "nouveau_ramht.h"
 #include "nouveau_vm.h"
+#include "nv50_display.h"
 
 struct nouveau_gpuobj_method {
 	struct list_head head;
@@ -490,16 +491,22 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base,
 	}
 
 	if (target == NV_MEM_TARGET_GART) {
-		if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
-			target = NV_MEM_TARGET_PCI_NOSNOOP;
-			base  += dev_priv->gart_info.aper_base;
-		} else
-		if (base != 0) {
-			base = nouveau_sgdma_get_physical(dev, base);
+		struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
+
+		if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) {
+			if (base == 0) {
+				nouveau_gpuobj_ref(gart, pobj);
+				return 0;
+			}
+
+			base   = nouveau_sgdma_get_physical(dev, base);
 			target = NV_MEM_TARGET_PCI;
 		} else {
-			nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj);
-			return 0;
+			base += dev_priv->gart_info.aper_base;
+			if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
+				target = NV_MEM_TARGET_PCI_NOSNOOP;
+			else
+				target = NV_MEM_TARGET_PCI;
 		}
 	}
 
@@ -776,7 +783,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *vram = NULL, *tt = NULL;
-	int ret;
+	int ret, i;
 
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
 
@@ -841,6 +848,25 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 		nouveau_gpuobj_ref(NULL, &ramht);
 		if (ret)
 			return ret;
+
+		/* dma objects for display sync channel semaphore blocks */
+		for (i = 0; i < 2; i++) {
+			struct nouveau_gpuobj *sem = NULL;
+			struct nv50_display_crtc *dispc =
+				&nv50_display(dev)->crtc[i];
+			u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+
+			ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff,
+						     NV_MEM_ACCESS_RW,
+						     NV_MEM_TARGET_VRAM, &sem);
+			if (ret)
+				return ret;
+
+			ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem);
+			nouveau_gpuobj_ref(NULL, &sem);
+			if (ret)
+				return ret;
+		}
 	}
 
 	/* VRAM ctxdma */
@@ -909,7 +935,7 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
 	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
 
-	if (chan->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
 }
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c
index bef3e69..a24a81f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ramht.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c
@@ -114,7 +114,9 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle,
 		      (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
 	} else {
 		if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) {
-			ctx = (gpuobj->cinst << 10) | chan->id;
+			ctx = (gpuobj->cinst << 10) |
+			      (chan->id << 28) |
+			      chan->id; /* HASH_TAG */
 		} else {
 			ctx = (gpuobj->cinst >> 4) |
 			      ((gpuobj->engine <<
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 9a250eb..a33fe40 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -12,6 +12,7 @@ struct nouveau_sgdma_be {
 	struct drm_device *dev;
 
 	dma_addr_t *pages;
+	bool *ttm_alloced;
 	unsigned nr_pages;
 
 	u64 offset;
@@ -20,7 +21,8 @@ struct nouveau_sgdma_be {
 
 static int
 nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
-		       struct page **pages, struct page *dummy_read_page)
+		       struct page **pages, struct page *dummy_read_page,
+		       dma_addr_t *dma_addrs)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
@@ -34,15 +36,25 @@ nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
 	if (!nvbe->pages)
 		return -ENOMEM;
 
+	nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
+	if (!nvbe->ttm_alloced)
+		return -ENOMEM;
+
 	nvbe->nr_pages = 0;
 	while (num_pages--) {
-		nvbe->pages[nvbe->nr_pages] =
-			pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
+		if (dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE) {
+			nvbe->pages[nvbe->nr_pages] =
+					dma_addrs[nvbe->nr_pages];
+		 	nvbe->ttm_alloced[nvbe->nr_pages] = true;
+		} else {
+			nvbe->pages[nvbe->nr_pages] =
+				pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
 				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(dev->pdev,
-					  nvbe->pages[nvbe->nr_pages])) {
-			be->func->clear(be);
-			return -EFAULT;
+			if (pci_dma_mapping_error(dev->pdev,
+						  nvbe->pages[nvbe->nr_pages])) {
+				be->func->clear(be);
+				return -EFAULT;
+			}
 		}
 
 		nvbe->nr_pages++;
@@ -65,17 +77,36 @@ nouveau_sgdma_clear(struct ttm_backend *be)
 			be->func->unbind(be);
 
 		while (nvbe->nr_pages--) {
-			pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
+			if (!nvbe->ttm_alloced[nvbe->nr_pages])
+				pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
 				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 		}
 		kfree(nvbe->pages);
+		kfree(nvbe->ttm_alloced);
 		nvbe->pages = NULL;
+		nvbe->ttm_alloced = NULL;
 		nvbe->nr_pages = 0;
 	}
 }
 
+static void
+nouveau_sgdma_destroy(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+
+	if (be) {
+		NV_DEBUG(nvbe->dev, "\n");
+
+		if (nvbe) {
+			if (nvbe->pages)
+				be->func->clear(be);
+			kfree(nvbe);
+		}
+	}
+}
+
 static int
-nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
@@ -102,7 +133,7 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 }
 
 static int
-nouveau_sgdma_unbind(struct ttm_backend *be)
+nv04_sgdma_unbind(struct ttm_backend *be)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
@@ -125,59 +156,245 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
 	return 0;
 }
 
+static struct ttm_backend_func nv04_sgdma_backend = {
+	.populate		= nouveau_sgdma_populate,
+	.clear			= nouveau_sgdma_clear,
+	.bind			= nv04_sgdma_bind,
+	.unbind			= nv04_sgdma_unbind,
+	.destroy		= nouveau_sgdma_destroy
+};
+
 static void
-nouveau_sgdma_destroy(struct ttm_backend *be)
+nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe)
+{
+	struct drm_device *dev = nvbe->dev;
+
+	nv_wr32(dev, 0x100810, 0x00000022);
+	if (!nv_wait(dev, 0x100810, 0x00000100, 0x00000100))
+		NV_ERROR(dev, "vm flush timeout: 0x%08x\n",
+			 nv_rd32(dev, 0x100810));
+	nv_wr32(dev, 0x100810, 0x00000000);
+}
+
+static int
+nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	dma_addr_t *list = nvbe->pages;
+	u32 pte = mem->start << 2;
+	u32 cnt = nvbe->nr_pages;
 
-	if (be) {
-		NV_DEBUG(nvbe->dev, "\n");
+	nvbe->offset = mem->start << PAGE_SHIFT;
 
-		if (nvbe) {
-			if (nvbe->pages)
-				be->func->clear(be);
-			kfree(nvbe);
+	while (cnt--) {
+		nv_wo32(pgt, pte, (*list++ >> 7) | 1);
+		pte += 4;
+	}
+
+	nv41_sgdma_flush(nvbe);
+	nvbe->bound = true;
+	return 0;
+}
+
+static int
+nv41_sgdma_unbind(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	u32 pte = (nvbe->offset >> 12) << 2;
+	u32 cnt = nvbe->nr_pages;
+
+	while (cnt--) {
+		nv_wo32(pgt, pte, 0x00000000);
+		pte += 4;
+	}
+
+	nv41_sgdma_flush(nvbe);
+	nvbe->bound = false;
+	return 0;
+}
+
+static struct ttm_backend_func nv41_sgdma_backend = {
+	.populate		= nouveau_sgdma_populate,
+	.clear			= nouveau_sgdma_clear,
+	.bind			= nv41_sgdma_bind,
+	.unbind			= nv41_sgdma_unbind,
+	.destroy		= nouveau_sgdma_destroy
+};
+
+static void
+nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe)
+{
+	struct drm_device *dev = nvbe->dev;
+
+	nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12);
+	nv_wr32(dev, 0x100808, nvbe->offset | 0x20);
+	if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001))
+		NV_ERROR(dev, "gart flush timeout: 0x%08x\n",
+			 nv_rd32(dev, 0x100808));
+	nv_wr32(dev, 0x100808, 0x00000000);
+}
+
+static void
+nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt)
+{
+	struct drm_nouveau_private *dev_priv = pgt->dev->dev_private;
+	dma_addr_t dummy = dev_priv->gart_info.dummy.addr;
+	u32 pte, tmp[4];
+
+	pte   = base >> 2;
+	base &= ~0x0000000f;
+
+	tmp[0] = nv_ro32(pgt, base + 0x0);
+	tmp[1] = nv_ro32(pgt, base + 0x4);
+	tmp[2] = nv_ro32(pgt, base + 0x8);
+	tmp[3] = nv_ro32(pgt, base + 0xc);
+	while (cnt--) {
+		u32 addr = list ? (*list++ >> 12) : (dummy >> 12);
+		switch (pte++ & 0x3) {
+		case 0:
+			tmp[0] &= ~0x07ffffff;
+			tmp[0] |= addr;
+			break;
+		case 1:
+			tmp[0] &= ~0xf8000000;
+			tmp[0] |= addr << 27;
+			tmp[1] &= ~0x003fffff;
+			tmp[1] |= addr >> 5;
+			break;
+		case 2:
+			tmp[1] &= ~0xffc00000;
+			tmp[1] |= addr << 22;
+			tmp[2] &= ~0x0001ffff;
+			tmp[2] |= addr >> 10;
+			break;
+		case 3:
+			tmp[2] &= ~0xfffe0000;
+			tmp[2] |= addr << 17;
+			tmp[3] &= ~0x00000fff;
+			tmp[3] |= addr >> 15;
+			break;
 		}
 	}
+
+	tmp[3] |= 0x40000000;
+
+	nv_wo32(pgt, base + 0x0, tmp[0]);
+	nv_wo32(pgt, base + 0x4, tmp[1]);
+	nv_wo32(pgt, base + 0x8, tmp[2]);
+	nv_wo32(pgt, base + 0xc, tmp[3]);
 }
 
 static int
-nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	dma_addr_t *list = nvbe->pages;
+	u32 pte = mem->start << 2, tmp[4];
+	u32 cnt = nvbe->nr_pages;
+	int i;
 
 	nvbe->offset = mem->start << PAGE_SHIFT;
 
-	nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset,
-			  nvbe->nr_pages << PAGE_SHIFT, nvbe->pages);
+	if (pte & 0x0000000c) {
+		u32  max = 4 - ((pte >> 2) & 0x3);
+		u32 part = (cnt > max) ? max : cnt;
+		nv44_sgdma_fill(pgt, list, pte, part);
+		pte  += (part << 2);
+		list += part;
+		cnt  -= part;
+	}
+
+	while (cnt >= 4) {
+		for (i = 0; i < 4; i++)
+			tmp[i] = *list++ >> 12;
+		nv_wo32(pgt, pte + 0x0, tmp[0] >>  0 | tmp[1] << 27);
+		nv_wo32(pgt, pte + 0x4, tmp[1] >>  5 | tmp[2] << 22);
+		nv_wo32(pgt, pte + 0x8, tmp[2] >> 10 | tmp[3] << 17);
+		nv_wo32(pgt, pte + 0xc, tmp[3] >> 15 | 0x40000000);
+		pte  += 0x10;
+		cnt  -= 4;
+	}
+
+	if (cnt)
+		nv44_sgdma_fill(pgt, list, pte, cnt);
+
+	nv44_sgdma_flush(nvbe);
 	nvbe->bound = true;
 	return 0;
 }
 
 static int
-nv50_sgdma_unbind(struct ttm_backend *be)
+nv44_sgdma_unbind(struct ttm_backend *be)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	u32 pte = (nvbe->offset >> 12) << 2;
+	u32 cnt = nvbe->nr_pages;
+
+	if (pte & 0x0000000c) {
+		u32  max = 4 - ((pte >> 2) & 0x3);
+		u32 part = (cnt > max) ? max : cnt;
+		nv44_sgdma_fill(pgt, NULL, pte, part);
+		pte  += (part << 2);
+		cnt  -= part;
+	}
 
-	if (!nvbe->bound)
-		return 0;
+	while (cnt >= 4) {
+		nv_wo32(pgt, pte + 0x0, 0x00000000);
+		nv_wo32(pgt, pte + 0x4, 0x00000000);
+		nv_wo32(pgt, pte + 0x8, 0x00000000);
+		nv_wo32(pgt, pte + 0xc, 0x00000000);
+		pte  += 0x10;
+		cnt  -= 4;
+	}
+
+	if (cnt)
+		nv44_sgdma_fill(pgt, NULL, pte, cnt);
 
-	nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset,
-			    nvbe->nr_pages << PAGE_SHIFT);
+	nv44_sgdma_flush(nvbe);
 	nvbe->bound = false;
 	return 0;
 }
 
-static struct ttm_backend_func nouveau_sgdma_backend = {
+static struct ttm_backend_func nv44_sgdma_backend = {
 	.populate		= nouveau_sgdma_populate,
 	.clear			= nouveau_sgdma_clear,
-	.bind			= nouveau_sgdma_bind,
-	.unbind			= nouveau_sgdma_unbind,
+	.bind			= nv44_sgdma_bind,
+	.unbind			= nv44_sgdma_unbind,
 	.destroy		= nouveau_sgdma_destroy
 };
 
+static int
+nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct nouveau_mem *node = mem->mm_node;
+	/* noop: bound in move_notify() */
+	node->pages = nvbe->pages;
+	nvbe->pages = (dma_addr_t *)node;
+	nvbe->bound = true;
+	return 0;
+}
+
+static int
+nv50_sgdma_unbind(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages;
+	/* noop: unbound in move_notify() */
+	nvbe->pages = node->pages;
+	node->pages = NULL;
+	nvbe->bound = false;
+	return 0;
+}
+
 static struct ttm_backend_func nv50_sgdma_backend = {
 	.populate		= nouveau_sgdma_populate,
 	.clear			= nouveau_sgdma_clear,
@@ -198,10 +415,7 @@ nouveau_sgdma_init_ttm(struct drm_device *dev)
 
 	nvbe->dev = dev;
 
-	if (dev_priv->card_type < NV_50)
-		nvbe->backend.func = &nouveau_sgdma_backend;
-	else
-		nvbe->backend.func = &nv50_sgdma_backend;
+	nvbe->backend.func = dev_priv->gart_info.func;
 	return &nvbe->backend;
 }
 
@@ -210,21 +424,64 @@ nouveau_sgdma_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *gpuobj = NULL;
-	uint32_t aper_size, obj_size;
-	int i, ret;
+	u32 aper_size, align;
+	int ret;
 
-	if (dev_priv->card_type < NV_50) {
-		if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024)
-			aper_size = 64 * 1024 * 1024;
-		else
-			aper_size = 512 * 1024 * 1024;
+	if (dev_priv->card_type >= NV_50 || drm_pci_device_is_pcie(dev))
+		aper_size = 512 * 1024 * 1024;
+	else
+		aper_size = 64 * 1024 * 1024;
+
+	/* Dear NVIDIA, NV44+ would like proper present bits in PTEs for
+	 * christmas.  The cards before it have them, the cards after
+	 * it have them, why is NV44 so unloved?
+	 */
+	dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL);
+	if (!dev_priv->gart_info.dummy.page)
+		return -ENOMEM;
+
+	dev_priv->gart_info.dummy.addr =
+		pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page,
+			     0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	if (pci_dma_mapping_error(dev->pdev, dev_priv->gart_info.dummy.addr)) {
+		NV_ERROR(dev, "error mapping dummy page\n");
+		__free_page(dev_priv->gart_info.dummy.page);
+		dev_priv->gart_info.dummy.page = NULL;
+		return -ENOMEM;
+	}
+
+	if (dev_priv->card_type >= NV_50) {
+		dev_priv->gart_info.aper_base = 0;
+		dev_priv->gart_info.aper_size = aper_size;
+		dev_priv->gart_info.type = NOUVEAU_GART_HW;
+		dev_priv->gart_info.func = &nv50_sgdma_backend;
+	} else
+	if (drm_pci_device_is_pcie(dev) &&
+	    dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
+		if (nv44_graph_class(dev)) {
+			dev_priv->gart_info.func = &nv44_sgdma_backend;
+			align = 512 * 1024;
+		} else {
+			dev_priv->gart_info.func = &nv41_sgdma_backend;
+			align = 16;
+		}
 
-		obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
-		obj_size += 8; /* ctxdma header */
+		ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align,
+					 NVOBJ_FLAG_ZERO_ALLOC |
+					 NVOBJ_FLAG_ZERO_FREE, &gpuobj);
+		if (ret) {
+			NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
+			return ret;
+		}
 
-		ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
-					      NVOBJ_FLAG_ZERO_ALLOC |
-					      NVOBJ_FLAG_ZERO_FREE, &gpuobj);
+		dev_priv->gart_info.sg_ctxdma = gpuobj;
+		dev_priv->gart_info.aper_base = 0;
+		dev_priv->gart_info.aper_size = aper_size;
+		dev_priv->gart_info.type = NOUVEAU_GART_HW;
+	} else {
+		ret = nouveau_gpuobj_new(dev, NULL, (aper_size / 1024) + 8, 16,
+					 NVOBJ_FLAG_ZERO_ALLOC |
+					 NVOBJ_FLAG_ZERO_FREE, &gpuobj);
 		if (ret) {
 			NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
 			return ret;
@@ -236,25 +493,14 @@ nouveau_sgdma_init(struct drm_device *dev)
 				   (0 << 14) /* RW */ |
 				   (2 << 16) /* PCI */);
 		nv_wo32(gpuobj, 4, aper_size - 1);
-		for (i = 2; i < 2 + (aper_size >> 12); i++)
-			nv_wo32(gpuobj, i * 4, 0x00000000);
 
 		dev_priv->gart_info.sg_ctxdma = gpuobj;
 		dev_priv->gart_info.aper_base = 0;
 		dev_priv->gart_info.aper_size = aper_size;
-	} else
-	if (dev_priv->chan_vm) {
-		ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024,
-				     12, NV_MEM_ACCESS_RW,
-				     &dev_priv->gart_info.vma);
-		if (ret)
-			return ret;
-
-		dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset;
-		dev_priv->gart_info.aper_size = 512 * 1024 * 1024;
+		dev_priv->gart_info.type = NOUVEAU_GART_PDMA;
+		dev_priv->gart_info.func = &nv04_sgdma_backend;
 	}
 
-	dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
 	return 0;
 }
 
@@ -264,7 +510,13 @@ nouveau_sgdma_takedown(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma);
-	nouveau_vm_put(&dev_priv->gart_info.vma);
+
+	if (dev_priv->gart_info.dummy.page) {
+		pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr,
+			       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		__free_page(dev_priv->gart_info.dummy.page);
+		dev_priv->gart_info.dummy.page = NULL;
+	}
 }
 
 uint32_t
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index a54fc43..4fcbd09 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -544,7 +544,6 @@ static int
 nouveau_card_init_channel(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *gpuobj = NULL;
 	int ret;
 
 	ret = nouveau_channel_alloc(dev, &dev_priv->channel,
@@ -552,41 +551,8 @@ nouveau_card_init_channel(struct drm_device *dev)
 	if (ret)
 		return ret;
 
-	/* no dma objects on fermi... */
-	if (dev_priv->card_type >= NV_C0)
-		goto out_done;
-
-	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
-				     0, dev_priv->vram_size,
-				     NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM,
-				     &gpuobj);
-	if (ret)
-		goto out_err;
-
-	ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj);
-	nouveau_gpuobj_ref(NULL, &gpuobj);
-	if (ret)
-		goto out_err;
-
-	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
-				     0, dev_priv->gart_info.aper_size,
-				     NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART,
-				     &gpuobj);
-	if (ret)
-		goto out_err;
-
-	ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj);
-	nouveau_gpuobj_ref(NULL, &gpuobj);
-	if (ret)
-		goto out_err;
-
-out_done:
 	mutex_unlock(&dev_priv->channel->mutex);
 	return 0;
-
-out_err:
-	nouveau_channel_put(&dev_priv->channel);
-	return ret;
 }
 
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
@@ -738,10 +704,6 @@ nouveau_card_init(struct drm_device *dev)
 			goto out_fence;
 	}
 
-	ret = nouveau_backlight_init(dev);
-	if (ret)
-		NV_ERROR(dev, "Error %d registering backlight\n", ret);
-
 	nouveau_fbcon_init(dev);
 	drm_kms_helper_poll_init(dev);
 	return 0;
@@ -793,8 +755,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
 
-	nouveau_backlight_exit(dev);
-
 	if (!engine->graph.accel_blocked) {
 		nouveau_fence_fini(dev);
 		nouveau_channel_put_unlocked(&dev_priv->channel);
@@ -929,12 +889,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
 		 dev->pci_vendor, dev->pci_device, dev->pdev->class);
 
-	dev_priv->wq = create_workqueue("nouveau");
-	if (!dev_priv->wq) {
-		ret = -EINVAL;
-		goto err_priv;
-	}
-
 	/* resource 0 is mmio regs */
 	/* resource 1 is linear FB */
 	/* resource 2 is RAMIN (mmio regs + 0x1000000) */
@@ -947,7 +901,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 		NV_ERROR(dev, "Unable to initialize the mmio mapping. "
 			 "Please report your setup to " DRIVER_EMAIL "\n");
 		ret = -EINVAL;
-		goto err_wq;
+		goto err_priv;
 	}
 	NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
 					(unsigned long long)mmio_start_offs);
@@ -1054,8 +1008,6 @@ err_ramin:
 	iounmap(dev_priv->ramin);
 err_mmio:
 	iounmap(dev_priv->mmio);
-err_wq:
-	destroy_workqueue(dev_priv->wq);
 err_priv:
 	kfree(dev_priv);
 	dev->dev_private = NULL;
@@ -1103,9 +1055,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
 		getparam->value = dev->pci_device;
 		break;
 	case NOUVEAU_GETPARAM_BUS_TYPE:
-		if (drm_device_is_agp(dev))
+		if (drm_pci_device_is_agp(dev))
 			getparam->value = NV_AGP;
-		else if (drm_device_is_pcie(dev))
+		else if (drm_pci_device_is_pcie(dev))
 			getparam->value = NV_PCIE;
 		else
 			getparam->value = NV_PCI;
@@ -1126,7 +1078,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
 		getparam->value = 1;
 		break;
 	case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
-		getparam->value = (dev_priv->card_type < NV_50);
+		getparam->value = 1;
 		break;
 	case NOUVEAU_GETPARAM_GRAPH_UNITS:
 		/* NV40 and NV50 versions are quite different, but register
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c
index 8d9968e..649b041 100644
--- a/drivers/gpu/drm/nouveau/nouveau_temp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_temp.c
@@ -239,11 +239,9 @@ static bool
 probe_monitoring_device(struct nouveau_i2c_chan *i2c,
 			struct i2c_board_info *info)
 {
-	char modalias[16] = "i2c:";
 	struct i2c_client *client;
 
-	strlcat(modalias, info->type, sizeof(modalias));
-	request_module(modalias);
+	request_module("%s%s", I2C_MODULE_PREFIX, info->type);
 
 	client = i2c_new_device(&i2c->adapter, info);
 	if (!client)
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c
index fbe0fb1..e51b515 100644
--- a/drivers/gpu/drm/nouveau/nouveau_util.c
+++ b/drivers/gpu/drm/nouveau/nouveau_util.c
@@ -47,18 +47,27 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value)
 		printk(" (unknown bits 0x%08x)", value);
 }
 
-void
-nouveau_enum_print(const struct nouveau_enum *en, u32 value)
+const struct nouveau_enum *
+nouveau_enum_find(const struct nouveau_enum *en, u32 value)
 {
 	while (en->name) {
-		if (value == en->value) {
-			printk("%s", en->name);
-			return;
-		}
-
+		if (en->value == value)
+			return en;
 		en++;
 	}
 
+	return NULL;
+}
+
+void
+nouveau_enum_print(const struct nouveau_enum *en, u32 value)
+{
+	en = nouveau_enum_find(en, value);
+	if (en) {
+		printk("%s", en->name);
+		return;
+	}
+
 	printk("(unknown enum 0x%08x)", value);
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h
index d9ceaea..b97719f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_util.h
+++ b/drivers/gpu/drm/nouveau/nouveau_util.h
@@ -36,10 +36,14 @@ struct nouveau_bitfield {
 struct nouveau_enum {
 	u32 value;
 	const char *name;
+	void *data;
 };
 
 void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value);
 void nouveau_enum_print(const struct nouveau_enum *, u32 value);
+const struct nouveau_enum *
+nouveau_enum_find(const struct nouveau_enum *, u32 value);
+
 int nouveau_ratelimit(void);
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
index 97d82ae..0059e6f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -28,7 +28,7 @@
 #include "nouveau_vm.h"
 
 void
-nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
+nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
 {
 	struct nouveau_vm *vm = vma->vm;
 	struct nouveau_mm_node *r;
@@ -40,7 +40,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
 	u32 max  = 1 << (vm->pgt_bits - bits);
 	u32 end, len;
 
-	list_for_each_entry(r, &vram->regions, rl_entry) {
+	delta = 0;
+	list_for_each_entry(r, &node->regions, rl_entry) {
 		u64 phys = (u64)r->offset << 12;
 		u32 num  = r->length >> bits;
 
@@ -52,7 +53,7 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
 				end = max;
 			len = end - pte;
 
-			vm->map(vma, pgt, vram, pte, len, phys);
+			vm->map(vma, pgt, node, pte, len, phys, delta);
 
 			num -= len;
 			pte += len;
@@ -60,6 +61,8 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
 				pde++;
 				pte = 0;
 			}
+
+			delta += (u64)len << vma->node->type;
 		}
 	}
 
@@ -67,14 +70,14 @@ nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
 }
 
 void
-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram)
+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
 {
-	nouveau_vm_map_at(vma, 0, vram);
+	nouveau_vm_map_at(vma, 0, node);
 }
 
 void
 nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
-		  dma_addr_t *list)
+		  struct nouveau_mem *mem, dma_addr_t *list)
 {
 	struct nouveau_vm *vm = vma->vm;
 	int big = vma->node->type != vm->spg_shift;
@@ -94,7 +97,7 @@ nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
 			end = max;
 		len = end - pte;
 
-		vm->map_sg(vma, pgt, pte, list, len);
+		vm->map_sg(vma, pgt, mem, pte, len, list);
 
 		num  -= len;
 		pte  += len;
@@ -311,18 +314,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset,
 		vm->spg_shift = 12;
 		vm->lpg_shift = 17;
 		pgt_bits = 27;
-
-		/* Should be 4096 everywhere, this is a hack that's
-		 * currently necessary to avoid an elusive bug that
-		 * causes corruption when mixing small/large pages
-		 */
-		if (length < (1ULL << 40))
-			block = 4096;
-		else {
-			block = (1 << pgt_bits);
-			if (length < block)
-				block = length;
-		}
+		block = 4096;
 	} else {
 		kfree(vm);
 		return -ENOSYS;
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index e119351..2e06b55 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -67,9 +67,10 @@ struct nouveau_vm {
 	void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde,
 			struct nouveau_gpuobj *pgt[2]);
 	void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *,
-		    struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+		    struct nouveau_mem *, u32 pte, u32 cnt,
+		    u64 phys, u64 delta);
 	void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
-		       u32 pte, dma_addr_t *, u32 cnt);
+		       struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
 	void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt);
 	void (*flush)(struct nouveau_vm *);
 };
@@ -82,20 +83,20 @@ int  nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **,
 int  nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift,
 		    u32 access, struct nouveau_vma *);
 void nouveau_vm_put(struct nouveau_vma *);
-void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *);
-void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *);
+void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);
+void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);
 void nouveau_vm_unmap(struct nouveau_vma *);
 void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
 void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
-		       dma_addr_t *);
+		       struct nouveau_mem *, dma_addr_t *);
 
 /* nv50_vm.c */
 void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 		     struct nouveau_gpuobj *pgt[2]);
 void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
-		 struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+		 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
 void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
-		    u32 pte, dma_addr_t *, u32 cnt);
+		    struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
 void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
 void nv50_vm_flush(struct nouveau_vm *);
 void nv50_vm_flush_engine(struct drm_device *, int engine);
@@ -104,9 +105,9 @@ void nv50_vm_flush_engine(struct drm_device *, int engine);
 void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 		     struct nouveau_gpuobj *pgt[2]);
 void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
-		 struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+		 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
 void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
-		    u32 pte, dma_addr_t *, u32 cnt);
+		    struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
 void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
 void nvc0_vm_flush(struct nouveau_vm *);
 
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index 297505e..a260fbb 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -1031,7 +1031,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
 	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
-			     0, 0x0000, false, true, &nv_crtc->cursor.nvbo);
+			     0, 0x0000, &nv_crtc->cursor.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c
index f89d104..db465a3 100644
--- a/drivers/gpu/drm/nouveau/nv04_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv04_fifo.c
@@ -379,6 +379,15 @@ out:
 	return handled;
 }
 
+static const char *nv_dma_state_err(u32 state)
+{
+	static const char * const desc[] = {
+		"NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE",
+		"INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK"
+	};
+	return desc[(state >> 29) & 0x7];
+}
+
 void
 nv04_fifo_isr(struct drm_device *dev)
 {
@@ -460,9 +469,10 @@ nv04_fifo_isr(struct drm_device *dev)
 				if (nouveau_ratelimit())
 					NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
 					     "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
-					     "State 0x%08x Push 0x%08x\n",
+					     "State 0x%08x (err: %s) Push 0x%08x\n",
 						chid, ho_get, dma_get, ho_put,
 						dma_put, ib_get, ib_put, state,
+						nv_dma_state_err(state),
 						push);
 
 				/* METHOD_COUNT, in DMA_STATE on earlier chipsets */
@@ -476,8 +486,9 @@ nv04_fifo_isr(struct drm_device *dev)
 				}
 			} else {
 				NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
-					     "Put 0x%08x State 0x%08x Push 0x%08x\n",
-					chid, dma_get, dma_put, state, push);
+					     "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
+					chid, dma_get, dma_put, state,
+					nv_dma_state_err(state), push);
 
 				if (dma_get != dma_put)
 					nv_wr32(dev, 0x003244, dma_put);
@@ -505,7 +516,7 @@ nv04_fifo_isr(struct drm_device *dev)
 
 		if (dev_priv->card_type == NV_50) {
 			if (status & 0x00000010) {
-				nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
+				nv50_fb_vm_trap(dev, nouveau_ratelimit());
 				status &= ~0x00000010;
 				nv_wr32(dev, 0x002100, 0x00000010);
 			}
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c
index 28119fd..3900ceb 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.c
+++ b/drivers/gpu/drm/nouveau/nv17_tv.c
@@ -197,10 +197,12 @@ static int nv17_tv_get_ld_modes(struct drm_encoder *encoder,
 				struct drm_connector *connector)
 {
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
-	struct drm_display_mode *mode, *tv_mode;
+	const struct drm_display_mode *tv_mode;
 	int n = 0;
 
 	for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) {
+		struct drm_display_mode *mode;
+
 		mode = drm_mode_duplicate(encoder->dev, tv_mode);
 
 		mode->clock = tv_norm->tv_enc_mode.vrefresh *
diff --git a/drivers/gpu/drm/nouveau/nv17_tv.h b/drivers/gpu/drm/nouveau/nv17_tv.h
index 6bf0384..622e722 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv.h
+++ b/drivers/gpu/drm/nouveau/nv17_tv.h
@@ -112,7 +112,7 @@ extern struct nv17_tv_norm_params {
 } nv17_tv_norms[NUM_TV_NORMS];
 #define get_tv_norm(enc) (&nv17_tv_norms[to_tv_enc(enc)->tv_norm])
 
-extern struct drm_display_mode nv17_tv_modes[];
+extern const struct drm_display_mode nv17_tv_modes[];
 
 static inline int interpolate(int y0, int y1, int y2, int x)
 {
diff --git a/drivers/gpu/drm/nouveau/nv17_tv_modes.c b/drivers/gpu/drm/nouveau/nv17_tv_modes.c
index 9d3893c..4d1d29f 100644
--- a/drivers/gpu/drm/nouveau/nv17_tv_modes.c
+++ b/drivers/gpu/drm/nouveau/nv17_tv_modes.c
@@ -438,7 +438,7 @@ void nv17_tv_state_load(struct drm_device *dev, struct nv17_tv_state *state)
 
 /* Timings similar to the ones the blob sets */
 
-struct drm_display_mode nv17_tv_modes[] = {
+const struct drm_display_mode nv17_tv_modes[] = {
 	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0,
 		   320, 344, 392, 560, 0, 200, 200, 202, 220, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC
diff --git a/drivers/gpu/drm/nouveau/nv40_fb.c b/drivers/gpu/drm/nouveau/nv40_fb.c
index f3d9c05..f0ac2a7 100644
--- a/drivers/gpu/drm/nouveau/nv40_fb.c
+++ b/drivers/gpu/drm/nouveau/nv40_fb.c
@@ -24,6 +24,53 @@ nv40_fb_set_tile_region(struct drm_device *dev, int i)
 	}
 }
 
+static void
+nv40_fb_init_gart(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
+
+	if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
+		nv_wr32(dev, 0x100800, 0x00000001);
+		return;
+	}
+
+	nv_wr32(dev, 0x100800, gart->pinst | 0x00000002);
+	nv_mask(dev, 0x10008c, 0x00000100, 0x00000100);
+	nv_wr32(dev, 0x100820, 0x00000000);
+}
+
+static void
+nv44_fb_init_gart(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
+	u32 vinst;
+
+	if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
+		nv_wr32(dev, 0x100850, 0x80000000);
+		nv_wr32(dev, 0x100800, 0x00000001);
+		return;
+	}
+
+	/* calculate vram address of this PRAMIN block, object
+	 * must be allocated on 512KiB alignment, and not exceed
+	 * a total size of 512KiB for this to work correctly
+	 */
+	vinst  = nv_rd32(dev, 0x10020c);
+	vinst -= ((gart->pinst >> 19) + 1) << 19;
+
+	nv_wr32(dev, 0x100850, 0x80000000);
+	nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr);
+
+	nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size);
+	nv_wr32(dev, 0x100850, 0x00008000);
+	nv_mask(dev, 0x10008c, 0x00000200, 0x00000200);
+	nv_wr32(dev, 0x100820, 0x00000000);
+	nv_wr32(dev, 0x10082c, 0x00000001);
+	nv_wr32(dev, 0x100800, vinst | 0x00000010);
+}
+
 int
 nv40_fb_init(struct drm_device *dev)
 {
@@ -32,12 +79,12 @@ nv40_fb_init(struct drm_device *dev)
 	uint32_t tmp;
 	int i;
 
-	/* This is strictly a NV4x register (don't know about NV5x). */
-	/* The blob sets these to all kinds of values, and they mess up our setup. */
-	/* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */
-	/* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */
-	/* Any idea what this is? */
-	nv_wr32(dev, NV40_PFB_UNK_800, 0x1);
+	if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
+		if (nv44_graph_class(dev))
+			nv44_fb_init_gart(dev);
+		else
+			nv40_fb_init_gart(dev);
+	}
 
 	switch (dev_priv->chipset) {
 	case 0x40:
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index 9023c4d..2b99840 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -65,7 +65,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked)
 {
 	struct drm_device *dev = nv_crtc->base.dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int index = nv_crtc->index, ret;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
@@ -135,8 +135,7 @@ static int
 nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
 {
 	struct drm_device *dev = nv_crtc->base.dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "\n");
@@ -186,8 +185,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update)
 	struct nouveau_connector *nv_connector =
 		nouveau_crtc_connector_get(nv_crtc);
 	struct drm_device *dev = nv_crtc->base.dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct drm_display_mode *native_mode = NULL;
 	struct drm_display_mode *mode = &nv_crtc->base.mode;
 	uint32_t outX, outY, horiz, vert;
@@ -445,6 +443,42 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 }
 
+static int
+nv50_crtc_wait_complete(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	struct nv50_display *disp = nv50_display(dev);
+	struct nouveau_channel *evo = disp->master;
+	u64 start;
+	int ret;
+
+	ret = RING_SPACE(evo, 6);
+	if (ret)
+		return ret;
+	BEGIN_RING(evo, 0, 0x0084, 1);
+	OUT_RING  (evo, 0x80000000);
+	BEGIN_RING(evo, 0, 0x0080, 1);
+	OUT_RING  (evo, 0);
+	BEGIN_RING(evo, 0, 0x0084, 1);
+	OUT_RING  (evo, 0x00000000);
+
+	nv_wo32(disp->ntfy, 0x000, 0x00000000);
+	FIRE_RING (evo);
+
+	start = ptimer->read(dev);
+	do {
+		nv_wr32(dev, 0x61002c, 0x370);
+		nv_wr32(dev, 0x000140, 1);
+
+		if (nv_ro32(disp->ntfy, 0x000))
+			return 0;
+	} while (ptimer->read(dev) - start < 2000000000ULL);
+
+	return -EBUSY;
+}
+
 static void
 nv50_crtc_prepare(struct drm_crtc *crtc)
 {
@@ -453,6 +487,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc)
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
+	nv50_display_flip_stop(crtc);
 	drm_vblank_pre_modeset(dev, nv_crtc->index);
 	nv50_crtc_blank(nv_crtc, true);
 }
@@ -461,24 +496,14 @@ static void
 nv50_crtc_commit(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	int ret;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
 	nv50_crtc_blank(nv_crtc, false);
 	drm_vblank_post_modeset(dev, nv_crtc->index);
-
-	ret = RING_SPACE(evo, 2);
-	if (ret) {
-		NV_ERROR(dev, "no space while committing crtc\n");
-		return;
-	}
-	BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
-	OUT_RING  (evo, 0);
-	FIRE_RING (evo);
+	nv50_crtc_wait_complete(crtc);
+	nv50_display_flip_next(crtc, crtc->fb, NULL);
 }
 
 static bool
@@ -491,15 +516,15 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode,
 static int
 nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
 			   struct drm_framebuffer *passed_fb,
-			   int x, int y, bool update, bool atomic)
+			   int x, int y, bool atomic)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct drm_device *dev = nv_crtc->base.dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct drm_framebuffer *drm_fb = nv_crtc->base.fb;
 	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
-	int ret, format;
+	int ret;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
@@ -525,28 +550,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
 		}
 	}
 
-	switch (drm_fb->depth) {
-	case  8:
-		format = NV50_EVO_CRTC_FB_DEPTH_8;
-		break;
-	case 15:
-		format = NV50_EVO_CRTC_FB_DEPTH_15;
-		break;
-	case 16:
-		format = NV50_EVO_CRTC_FB_DEPTH_16;
-		break;
-	case 24:
-	case 32:
-		format = NV50_EVO_CRTC_FB_DEPTH_24;
-		break;
-	case 30:
-		format = NV50_EVO_CRTC_FB_DEPTH_30;
-		break;
-	default:
-		 NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth);
-		 return -EINVAL;
-	}
-
 	nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
 	nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
 	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
@@ -556,14 +559,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
 			return ret;
 
 		BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
-		if (nv_crtc->fb.tile_flags == 0x7a00 ||
-		    nv_crtc->fb.tile_flags == 0xfe00)
-			OUT_RING(evo, NvEvoFB32);
-		else
-		if (nv_crtc->fb.tile_flags == 0x7000)
-			OUT_RING(evo, NvEvoFB16);
-		else
-			OUT_RING(evo, NvEvoVRAM_LP);
+		OUT_RING  (evo, fb->r_dma);
 	}
 
 	ret = RING_SPACE(evo, 12);
@@ -571,45 +567,26 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
 		return ret;
 
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5);
-	OUT_RING(evo, nv_crtc->fb.offset >> 8);
-	OUT_RING(evo, 0);
-	OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width);
-	if (!nv_crtc->fb.tile_flags) {
-		OUT_RING(evo, drm_fb->pitch | (1 << 20));
-	} else {
-		u32 tile_mode = fb->nvbo->tile_mode;
-		if (dev_priv->card_type >= NV_C0)
-			tile_mode >>= 4;
-		OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode);
-	}
-	if (dev_priv->chipset == 0x50)
-		OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format);
-	else
-		OUT_RING(evo, format);
+	OUT_RING  (evo, nv_crtc->fb.offset >> 8);
+	OUT_RING  (evo, 0);
+	OUT_RING  (evo, (drm_fb->height << 16) | drm_fb->width);
+	OUT_RING  (evo, fb->r_pitch);
+	OUT_RING  (evo, fb->r_format);
 
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1);
-	OUT_RING(evo, fb->base.depth == 8 ?
-		 NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
+	OUT_RING  (evo, fb->base.depth == 8 ?
+		   NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
 
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
-	OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
+	OUT_RING  (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
-	OUT_RING(evo, (y << 16) | x);
+	OUT_RING  (evo, (y << 16) | x);
 
 	if (nv_crtc->lut.depth != fb->base.depth) {
 		nv_crtc->lut.depth = fb->base.depth;
 		nv50_crtc_lut_load(crtc);
 	}
 
-	if (update) {
-		ret = RING_SPACE(evo, 2);
-		if (ret)
-			return ret;
-		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
-		OUT_RING(evo, 0);
-		FIRE_RING(evo);
-	}
-
 	return 0;
 }
 
@@ -619,8 +596,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		   struct drm_framebuffer *old_fb)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nouveau_connector *nv_connector = NULL;
 	uint32_t hsync_dur,  vsync_dur, hsync_start_to_end, vsync_start_to_end;
@@ -700,14 +676,25 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false);
 	nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false);
 
-	return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false);
+	return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
 
 static int
 nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 			struct drm_framebuffer *old_fb)
 {
-	return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false);
+	int ret;
+
+	nv50_display_flip_stop(crtc);
+	ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
+	if (ret)
+		return ret;
+
+	ret = nv50_crtc_wait_complete(crtc);
+	if (ret)
+		return ret;
+
+	return nv50_display_flip_next(crtc, crtc->fb, NULL);
 }
 
 static int
@@ -715,7 +702,14 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
 			       struct drm_framebuffer *fb,
 			       int x, int y, enum mode_set_atomic state)
 {
-	return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true);
+	int ret;
+
+	nv50_display_flip_stop(crtc);
+	ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true);
+	if (ret)
+		return ret;
+
+	return nv50_crtc_wait_complete(crtc);
 }
 
 static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
@@ -758,7 +752,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
 	nv_crtc->lut.depth = 0;
 
 	ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM,
-			     0, 0x0000, false, true, &nv_crtc->lut.nvbo);
+			     0, 0x0000, &nv_crtc->lut.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
@@ -784,7 +778,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
 	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
-			     0, 0x0000, false, true, &nv_crtc->cursor.nvbo);
+			     0, 0x0000, &nv_crtc->cursor.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c
index 1b9ce30..9752c35 100644
--- a/drivers/gpu/drm/nouveau/nv50_cursor.c
+++ b/drivers/gpu/drm/nouveau/nv50_cursor.c
@@ -36,9 +36,9 @@
 static void
 nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
 {
-	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "\n");
@@ -71,9 +71,9 @@ nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
 static void
 nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
 {
-	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "\n");
diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c
index 875414b..808f3ec 100644
--- a/drivers/gpu/drm/nouveau/nv50_dac.c
+++ b/drivers/gpu/drm/nouveau/nv50_dac.c
@@ -41,8 +41,7 @@ nv50_dac_disconnect(struct drm_encoder *encoder)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	if (!nv_encoder->crtc)
@@ -216,8 +215,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
 	uint32_t mode_ctl = 0, mode_ctl2 = 0;
 	int ret;
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7cc94ed..75a376c 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -24,6 +24,7 @@
  *
  */
 
+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
 #include "nv50_display.h"
 #include "nouveau_crtc.h"
 #include "nouveau_encoder.h"
@@ -34,6 +35,7 @@
 #include "drm_crtc_helper.h"
 
 static void nv50_display_isr(struct drm_device *);
+static void nv50_display_bh(unsigned long);
 
 static inline int
 nv50_sor_nr(struct drm_device *dev)
@@ -172,16 +174,16 @@ nv50_display_init(struct drm_device *dev)
 	ret = nv50_evo_init(dev);
 	if (ret)
 		return ret;
-	evo = dev_priv->evo;
+	evo = nv50_display(dev)->master;
 
 	nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9);
 
-	ret = RING_SPACE(evo, 11);
+	ret = RING_SPACE(evo, 15);
 	if (ret)
 		return ret;
 	BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2);
 	OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED);
-	OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE);
+	OUT_RING(evo, NvEvoSync);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1);
 	OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1);
@@ -190,6 +192,11 @@ nv50_display_init(struct drm_device *dev)
 	OUT_RING(evo, 0);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1);
 	OUT_RING(evo, 0);
+	/* required to make display sync channels not hate life */
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1);
+	OUT_RING  (evo, 0x00000311);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1);
+	OUT_RING  (evo, 0x00000311);
 	FIRE_RING(evo);
 	if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2))
 		NV_ERROR(dev, "evo pushbuf stalled\n");
@@ -201,6 +208,8 @@ nv50_display_init(struct drm_device *dev)
 static int nv50_display_disable(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
+	struct nouveau_channel *evo = disp->master;
 	struct drm_crtc *drm_crtc;
 	int ret, i;
 
@@ -212,12 +221,12 @@ static int nv50_display_disable(struct drm_device *dev)
 		nv50_crtc_blank(crtc, true);
 	}
 
-	ret = RING_SPACE(dev_priv->evo, 2);
+	ret = RING_SPACE(evo, 2);
 	if (ret == 0) {
-		BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1);
-		OUT_RING(dev_priv->evo, 0);
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
 	}
-	FIRE_RING(dev_priv->evo);
+	FIRE_RING(evo);
 
 	/* Almost like ack'ing a vblank interrupt, maybe in the spirit of
 	 * cleaning up?
@@ -267,10 +276,16 @@ int nv50_display_create(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct dcb_table *dcb = &dev_priv->vbios.dcb;
 	struct drm_connector *connector, *ct;
+	struct nv50_display *priv;
 	int ret, i;
 
 	NV_DEBUG_KMS(dev, "\n");
 
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	dev_priv->engine.display.priv = priv;
+
 	/* init basic kernel modesetting */
 	drm_mode_config_init(dev);
 
@@ -330,7 +345,7 @@ int nv50_display_create(struct drm_device *dev)
 		}
 	}
 
-	INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
+	tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev);
 	nouveau_irq_register(dev, 26, nv50_display_isr);
 
 	ret = nv50_display_init(dev);
@@ -345,12 +360,131 @@ int nv50_display_create(struct drm_device *dev)
 void
 nv50_display_destroy(struct drm_device *dev)
 {
+	struct nv50_display *disp = nv50_display(dev);
+
 	NV_DEBUG_KMS(dev, "\n");
 
 	drm_mode_config_cleanup(dev);
 
 	nv50_display_disable(dev);
 	nouveau_irq_unregister(dev, 26);
+	kfree(disp);
+}
+
+void
+nv50_display_flip_stop(struct drm_crtc *crtc)
+{
+	struct nv50_display *disp = nv50_display(crtc->dev);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index];
+	struct nouveau_channel *evo = dispc->sync;
+	int ret;
+
+	ret = RING_SPACE(evo, 8);
+	if (ret) {
+		WARN_ON(1);
+		return;
+	}
+
+	BEGIN_RING(evo, 0, 0x0084, 1);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x0094, 1);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x00c0, 1);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x0080, 1);
+	OUT_RING  (evo, 0x00000000);
+	FIRE_RING (evo);
+}
+
+int
+nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+		       struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+	struct nv50_display *disp = nv50_display(crtc->dev);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index];
+	struct nouveau_channel *evo = dispc->sync;
+	int ret;
+
+	ret = RING_SPACE(evo, 24);
+	if (unlikely(ret))
+		return ret;
+
+	/* synchronise with the rendering channel, if necessary */
+	if (likely(chan)) {
+		u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset;
+
+		ret = RING_SPACE(chan, 10);
+		if (ret) {
+			WIND_RING(evo);
+			return ret;
+		}
+
+		if (dev_priv->chipset < 0xc0) {
+			BEGIN_RING(chan, NvSubSw, 0x0060, 2);
+			OUT_RING  (chan, NvEvoSema0 + nv_crtc->index);
+			OUT_RING  (chan, dispc->sem.offset);
+			BEGIN_RING(chan, NvSubSw, 0x006c, 1);
+			OUT_RING  (chan, 0xf00d0000 | dispc->sem.value);
+			BEGIN_RING(chan, NvSubSw, 0x0064, 2);
+			OUT_RING  (chan, dispc->sem.offset ^ 0x10);
+			OUT_RING  (chan, 0x74b1e000);
+			BEGIN_RING(chan, NvSubSw, 0x0060, 1);
+			if (dev_priv->chipset < 0x84)
+				OUT_RING  (chan, NvSema);
+			else
+				OUT_RING  (chan, chan->vram_handle);
+		} else {
+			BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+			OUT_RING  (chan, upper_32_bits(offset));
+			OUT_RING  (chan, lower_32_bits(offset));
+			OUT_RING  (chan, 0xf00d0000 | dispc->sem.value);
+			OUT_RING  (chan, 0x1002);
+			BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+			OUT_RING  (chan, upper_32_bits(offset));
+			OUT_RING  (chan, lower_32_bits(offset ^ 0x10));
+			OUT_RING  (chan, 0x74b1e000);
+			OUT_RING  (chan, 0x1001);
+		}
+		FIRE_RING (chan);
+	} else {
+		nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4,
+				0xf00d0000 | dispc->sem.value);
+	}
+
+	/* queue the flip on the crtc's "display sync" channel */
+	BEGIN_RING(evo, 0, 0x0100, 1);
+	OUT_RING  (evo, 0xfffe0000);
+	BEGIN_RING(evo, 0, 0x0084, 5);
+	OUT_RING  (evo, chan ? 0x00000100 : 0x00000010);
+	OUT_RING  (evo, dispc->sem.offset);
+	OUT_RING  (evo, 0xf00d0000 | dispc->sem.value);
+	OUT_RING  (evo, 0x74b1e000);
+	OUT_RING  (evo, NvEvoSync);
+	BEGIN_RING(evo, 0, 0x00a0, 2);
+	OUT_RING  (evo, 0x00000000);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x00c0, 1);
+	OUT_RING  (evo, nv_fb->r_dma);
+	BEGIN_RING(evo, 0, 0x0110, 2);
+	OUT_RING  (evo, 0x00000000);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x0800, 5);
+	OUT_RING  (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+	OUT_RING  (evo, 0);
+	OUT_RING  (evo, (fb->height << 16) | fb->width);
+	OUT_RING  (evo, nv_fb->r_pitch);
+	OUT_RING  (evo, nv_fb->r_format);
+	BEGIN_RING(evo, 0, 0x0080, 1);
+	OUT_RING  (evo, 0x00000000);
+	FIRE_RING (evo);
+
+	dispc->sem.offset ^= 0x10;
+	dispc->sem.value++;
+	return 0;
 }
 
 static u16
@@ -466,11 +600,12 @@ static void
 nv50_display_unk10_handler(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	u32 unk30 = nv_rd32(dev, 0x610030), mc;
 	int i, crtc, or, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
-	dev_priv->evo_irq.dcb = NULL;
+	disp->irq.dcb = NULL;
 
 	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8);
 
@@ -541,7 +676,7 @@ nv50_display_unk10_handler(struct drm_device *dev)
 
 		if (dcb->type == type && (dcb->or & (1 << or))) {
 			nouveau_bios_run_display_table(dev, dcb, 0, -1);
-			dev_priv->evo_irq.dcb = dcb;
+			disp->irq.dcb = dcb;
 			goto ack;
 		}
 	}
@@ -587,15 +722,16 @@ static void
 nv50_display_unk20_handler(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc;
+	struct nv50_display *disp = nv50_display(dev);
+	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0;
 	struct dcb_entry *dcb;
 	int i, crtc, or, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
-	dcb = dev_priv->evo_irq.dcb;
+	dcb = disp->irq.dcb;
 	if (dcb) {
 		nouveau_bios_run_display_table(dev, dcb, 0, -2);
-		dev_priv->evo_irq.dcb = NULL;
+		disp->irq.dcb = NULL;
 	}
 
 	/* CRTC clock change requested? */
@@ -692,9 +828,9 @@ nv50_display_unk20_handler(struct drm_device *dev)
 		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0);
 	}
 
-	dev_priv->evo_irq.dcb = dcb;
-	dev_priv->evo_irq.pclk = pclk;
-	dev_priv->evo_irq.script = script;
+	disp->irq.dcb = dcb;
+	disp->irq.pclk = pclk;
+	disp->irq.script = script;
 
 ack:
 	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20);
@@ -735,13 +871,13 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_entry *dcb)
 static void
 nv50_display_unk40_handler(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct dcb_entry *dcb = dev_priv->evo_irq.dcb;
-	u16 script = dev_priv->evo_irq.script;
-	u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk;
+	struct nv50_display *disp = nv50_display(dev);
+	struct dcb_entry *dcb = disp->irq.dcb;
+	u16 script = disp->irq.script;
+	u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
-	dev_priv->evo_irq.dcb = NULL;
+	disp->irq.dcb = NULL;
 	if (!dcb)
 		goto ack;
 
@@ -754,12 +890,10 @@ ack:
 	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8);
 }
 
-void
-nv50_display_irq_handler_bh(struct work_struct *work)
+static void
+nv50_display_bh(unsigned long data)
 {
-	struct drm_nouveau_private *dev_priv =
-		container_of(work, struct drm_nouveau_private, irq_work);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = (struct drm_device *)data;
 
 	for (;;) {
 		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
@@ -807,7 +941,7 @@ nv50_display_error_handler(struct drm_device *dev)
 static void
 nv50_display_isr(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	uint32_t delayed = 0;
 
 	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
@@ -835,8 +969,7 @@ nv50_display_isr(struct drm_device *dev)
 				  NV50_PDISPLAY_INTR_1_CLK_UNK40));
 		if (clock) {
 			nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
-			if (!work_pending(&dev_priv->irq_work))
-				queue_work(dev_priv->wq, &dev_priv->irq_work);
+			tasklet_schedule(&disp->tasklet);
 			delayed |= clock;
 			intr1 &= ~clock;
 		}
diff --git a/drivers/gpu/drm/nouveau/nv50_display.h b/drivers/gpu/drm/nouveau/nv50_display.h
index f0e30b78..c2da503 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.h
+++ b/drivers/gpu/drm/nouveau/nv50_display.h
@@ -35,7 +35,36 @@
 #include "nouveau_crtc.h"
 #include "nv50_evo.h"
 
-void nv50_display_irq_handler_bh(struct work_struct *work);
+struct nv50_display_crtc {
+	struct nouveau_channel *sync;
+	struct {
+		struct nouveau_bo *bo;
+		u32 offset;
+		u16 value;
+	} sem;
+};
+
+struct nv50_display {
+	struct nouveau_channel *master;
+	struct nouveau_gpuobj *ntfy;
+
+	struct nv50_display_crtc crtc[2];
+
+	struct tasklet_struct tasklet;
+	struct {
+		struct dcb_entry *dcb;
+		u16 script;
+		u32 pclk;
+	} irq;
+};
+
+static inline struct nv50_display *
+nv50_display(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return dev_priv->engine.display.priv;
+}
+
 int nv50_display_early_init(struct drm_device *dev);
 void nv50_display_late_takedown(struct drm_device *dev);
 int nv50_display_create(struct drm_device *dev);
@@ -44,4 +73,15 @@ void nv50_display_destroy(struct drm_device *dev);
 int nv50_crtc_blank(struct nouveau_crtc *, bool blank);
 int nv50_crtc_set_clock(struct drm_device *, int head, int pclk);
 
+int  nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
+			    struct nouveau_channel *chan);
+void nv50_display_flip_stop(struct drm_crtc *);
+
+int  nv50_evo_init(struct drm_device *dev);
+void nv50_evo_fini(struct drm_device *dev);
+void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base,
+			  u64 size);
+int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype,
+			 u64 base, u64 size, struct nouveau_gpuobj **);
+
 #endif /* __NV50_DISPLAY_H__ */
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c
index 0ea090f..a2cfaa6 100644
--- a/drivers/gpu/drm/nouveau/nv50_evo.c
+++ b/drivers/gpu/drm/nouveau/nv50_evo.c
@@ -27,20 +27,17 @@
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_ramht.h"
+#include "nv50_display.h"
 
 static void
 nv50_evo_channel_del(struct nouveau_channel **pevo)
 {
-	struct drm_nouveau_private *dev_priv;
 	struct nouveau_channel *evo = *pevo;
 
 	if (!evo)
 		return;
 	*pevo = NULL;
 
-	dev_priv = evo->dev->dev_private;
-	dev_priv->evo_alloc &= ~(1 << evo->id);
-
 	nouveau_gpuobj_channel_takedown(evo);
 	nouveau_bo_unmap(evo->pushbuf_bo);
 	nouveau_bo_ref(NULL, &evo->pushbuf_bo);
@@ -51,42 +48,61 @@ nv50_evo_channel_del(struct nouveau_channel **pevo)
 	kfree(evo);
 }
 
+void
+nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size)
+{
+	struct drm_nouveau_private *dev_priv = obj->dev->dev_private;
+	u32 flags5;
+
+	if (dev_priv->chipset < 0xc0) {
+		/* not supported on 0x50, specified in format mthd */
+		if (dev_priv->chipset == 0x50)
+			memtype = 0;
+		flags5 = 0x00010000;
+	} else {
+		if (memtype & 0x80000000)
+			flags5 = 0x00000000; /* large pages */
+		else
+			flags5 = 0x00020000;
+	}
+
+	nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM,
+			     NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0);
+	nv_wo32(obj, 0x14, flags5);
+	dev_priv->engine.instmem.flush(obj->dev);
+}
+
 int
-nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
-		    u32 tile_flags, u32 magic_flags, u32 offset, u32 limit,
-		    u32 flags5)
+nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype,
+		    u64 base, u64 size, struct nouveau_gpuobj **pobj)
 {
-	struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
-	struct drm_device *dev = evo->dev;
+	struct nv50_display *disp = nv50_display(evo->dev);
 	struct nouveau_gpuobj *obj = NULL;
 	int ret;
 
-	ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj);
+	ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj);
 	if (ret)
 		return ret;
 	obj->engine = NVOBJ_ENGINE_DISPLAY;
 
-	nv_wo32(obj,  0, (tile_flags << 22) | (magic_flags << 16) | class);
-	nv_wo32(obj,  4, limit);
-	nv_wo32(obj,  8, offset);
-	nv_wo32(obj, 12, 0x00000000);
-	nv_wo32(obj, 16, 0x00000000);
-	nv_wo32(obj, 20, flags5);
-	dev_priv->engine.instmem.flush(dev);
+	nv50_evo_dmaobj_init(obj, memtype, base, size);
 
-	ret = nouveau_ramht_insert(evo, name, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	if (ret) {
-		return ret;
-	}
+	ret = nouveau_ramht_insert(evo, handle, obj);
+	if (ret)
+		goto out;
 
-	return 0;
+	if (pobj)
+		nouveau_gpuobj_ref(obj, pobj);
+out:
+	nouveau_gpuobj_ref(NULL, &obj);
+	return ret;
 }
 
 static int
-nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo)
+nv50_evo_channel_new(struct drm_device *dev, int chid,
+		     struct nouveau_channel **pevo)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	struct nouveau_channel *evo;
 	int ret;
 
@@ -95,25 +111,13 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo)
 		return -ENOMEM;
 	*pevo = evo;
 
-	for (evo->id = 0; evo->id < 5; evo->id++) {
-		if (dev_priv->evo_alloc & (1 << evo->id))
-			continue;
-
-		dev_priv->evo_alloc |= (1 << evo->id);
-		break;
-	}
-
-	if (evo->id == 5) {
-		kfree(evo);
-		return -ENODEV;
-	}
-
+	evo->id = chid;
 	evo->dev = dev;
 	evo->user_get = 4;
 	evo->user_put = 0;
 
 	ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
-			     false, true, &evo->pushbuf_bo);
+			     &evo->pushbuf_bo);
 	if (ret == 0)
 		ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
 	if (ret) {
@@ -138,8 +142,8 @@ nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo)
 	}
 
 	/* bind primary evo channel's ramht to the channel */
-	if (dev_priv->evo && evo != dev_priv->evo)
-		nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL);
+	if (disp->master && evo != disp->master)
+		nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL);
 
 	return 0;
 }
@@ -212,21 +216,39 @@ nv50_evo_channel_fini(struct nouveau_channel *evo)
 	}
 }
 
+static void
+nv50_evo_destroy(struct drm_device *dev)
+{
+	struct nv50_display *disp = nv50_display(dev);
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		if (disp->crtc[i].sem.bo) {
+			nouveau_bo_unmap(disp->crtc[i].sem.bo);
+			nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo);
+		}
+		nv50_evo_channel_del(&disp->crtc[i].sync);
+	}
+	nouveau_gpuobj_ref(NULL, &disp->ntfy);
+	nv50_evo_channel_del(&disp->master);
+}
+
 static int
 nv50_evo_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	struct nouveau_gpuobj *ramht = NULL;
 	struct nouveau_channel *evo;
-	int ret;
+	int ret, i, j;
 
 	/* create primary evo channel, the one we use for modesetting
 	 * purporses
 	 */
-	ret = nv50_evo_channel_new(dev, &dev_priv->evo);
+	ret = nv50_evo_channel_new(dev, 0, &disp->master);
 	if (ret)
 		return ret;
-	evo = dev_priv->evo;
+	evo = disp->master;
 
 	/* setup object management on it, any other evo channel will
 	 * use this also as there's no per-channel support on the
@@ -236,109 +258,167 @@ nv50_evo_create(struct drm_device *dev)
 				 NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin);
 	if (ret) {
 		NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret);
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
+		goto err;
 	}
 
 	ret = drm_mm_init(&evo->ramin_heap, 0, 32768);
 	if (ret) {
 		NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret);
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
+		goto err;
 	}
 
 	ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht);
 	if (ret) {
 		NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret);
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
+		goto err;
 	}
 
 	ret = nouveau_ramht_new(dev, ramht, &evo->ramht);
 	nouveau_gpuobj_ref(NULL, &ramht);
-	if (ret) {
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
-	}
+	if (ret)
+		goto err;
+
+	/* not sure exactly what this is..
+	 *
+	 * the first dword of the structure is used by nvidia to wait on
+	 * full completion of an EVO "update" command.
+	 *
+	 * method 0x8c on the master evo channel will fill a lot more of
+	 * this structure with some undefined info
+	 */
+	ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0,
+				 NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy);
+	if (ret)
+		goto err;
+
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000,
+				  disp->ntfy->vinst, disp->ntfy->size, NULL);
+	if (ret)
+		goto err;
 
 	/* create some default objects for the scanout memtypes we support */
-	if (dev_priv->card_type >= NV_C0) {
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19,
-					  0, 0xffffffff, 0x00000000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000,
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00020000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000,
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00000000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
-	} else {
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19,
-					  0, 0xffffffff, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 |
+				  (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00),
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 |
+				  (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00),
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19,
-					  0, 0xffffffff, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	/* create "display sync" channels and other structures we need
+	 * to implement page flipping
+	 */
+	for (i = 0; i < 2; i++) {
+		struct nv50_display_crtc *dispc = &disp->crtc[i];
+		u64 offset;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
+		ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync);
+		if (ret)
+			goto err;
+
+		ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+				     0, 0x0000, &dispc->sem.bo);
+		if (!ret) {
+			offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+
+			ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
+			if (!ret)
+				ret = nouveau_bo_map(dispc->sem.bo);
+			if (ret)
+				nouveau_bo_ref(NULL, &dispc->sem.bo);
 		}
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000,
+					  offset, 4096, NULL);
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000,
+					  0, dev_priv->vram_size, NULL);
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 |
+					  (dev_priv->chipset < 0xc0 ?
+					  0x7a00 : 0xfe00),
+					  0, dev_priv->vram_size, NULL);
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 |
+					  (dev_priv->chipset < 0xc0 ?
+					  0x7000 : 0xfe00),
+					  0, dev_priv->vram_size, NULL);
+		if (ret)
+			goto err;
+
+		for (j = 0; j < 4096; j += 4)
+			nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000);
+		dispc->sem.offset = 0;
 	}
 
 	return 0;
+
+err:
+	nv50_evo_destroy(dev);
+	return ret;
 }
 
 int
 nv50_evo_init(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int ret;
+	struct nv50_display *disp = nv50_display(dev);
+	int ret, i;
 
-	if (!dev_priv->evo) {
+	if (!disp->master) {
 		ret = nv50_evo_create(dev);
 		if (ret)
 			return ret;
 	}
 
-	return nv50_evo_channel_init(dev_priv->evo);
+	ret = nv50_evo_channel_init(disp->master);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < 2; i++) {
+		ret = nv50_evo_channel_init(disp->crtc[i].sync);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 void
 nv50_evo_fini(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
+	int i;
 
-	if (dev_priv->evo) {
-		nv50_evo_channel_fini(dev_priv->evo);
-		nv50_evo_channel_del(&dev_priv->evo);
+	for (i = 0; i < 2; i++) {
+		if (disp->crtc[i].sync)
+			nv50_evo_channel_fini(disp->crtc[i].sync);
 	}
+
+	if (disp->master)
+		nv50_evo_channel_fini(disp->master);
+
+	nv50_evo_destroy(dev);
 }
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.h b/drivers/gpu/drm/nouveau/nv50_evo.h
index aa4f0d3..3860ca6 100644
--- a/drivers/gpu/drm/nouveau/nv50_evo.h
+++ b/drivers/gpu/drm/nouveau/nv50_evo.h
@@ -27,12 +27,6 @@
 #ifndef __NV50_EVO_H__
 #define __NV50_EVO_H__
 
-int  nv50_evo_init(struct drm_device *dev);
-void nv50_evo_fini(struct drm_device *dev);
-int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name,
-			 u32 tile_flags, u32 magic_flags,
-			 u32 offset, u32 limit);
-
 #define NV50_EVO_UPDATE                                              0x00000080
 #define NV50_EVO_UNK84                                               0x00000084
 #define NV50_EVO_UNK84_NOTIFY                                        0x40000000
@@ -119,5 +113,7 @@ int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name,
 /* Both of these are needed, otherwise nothing happens. */
 #define NV50_EVO_CRTC_SCALE_RES1                                     0x000008d8
 #define NV50_EVO_CRTC_SCALE_RES2                                     0x000008dc
+#define NV50_EVO_CRTC_UNK900                                         0x00000900
+#define NV50_EVO_CRTC_UNK904                                         0x00000904
 
 #endif
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c
index 50290de..bdd2afe 100644
--- a/drivers/gpu/drm/nouveau/nv50_fb.c
+++ b/drivers/gpu/drm/nouveau/nv50_fb.c
@@ -8,31 +8,61 @@ struct nv50_fb_priv {
 	dma_addr_t r100c08;
 };
 
+static void
+nv50_fb_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nv50_fb_priv *priv = pfb->priv;
+
+	if (drm_mm_initialized(&pfb->tag_heap))
+		drm_mm_takedown(&pfb->tag_heap);
+
+	if (priv->r100c08_page) {
+		pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
+			       PCI_DMA_BIDIRECTIONAL);
+		__free_page(priv->r100c08_page);
+	}
+
+	kfree(priv);
+	pfb->priv = NULL;
+}
+
 static int
 nv50_fb_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nv50_fb_priv *priv;
+	u32 tagmem;
+	int ret;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
+	pfb->priv = priv;
 
 	priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
 	if (!priv->r100c08_page) {
-		kfree(priv);
+		nv50_fb_destroy(dev);
 		return -ENOMEM;
 	}
 
 	priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
 				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 	if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
-		__free_page(priv->r100c08_page);
-		kfree(priv);
+		nv50_fb_destroy(dev);
 		return -EFAULT;
 	}
 
-	dev_priv->engine.fb.priv = priv;
+	tagmem = nv_rd32(dev, 0x100320);
+	NV_DEBUG(dev, "%d tags available\n", tagmem);
+	ret = drm_mm_init(&pfb->tag_heap, 0, tagmem);
+	if (ret) {
+		nv50_fb_destroy(dev);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -81,26 +111,112 @@ nv50_fb_init(struct drm_device *dev)
 void
 nv50_fb_takedown(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nv50_fb_priv *priv;
+	nv50_fb_destroy(dev);
+}
 
-	priv = dev_priv->engine.fb.priv;
-	if (!priv)
-		return;
-	dev_priv->engine.fb.priv = NULL;
+static struct nouveau_enum vm_dispatch_subclients[] = {
+	{ 0x00000000, "GRCTX", NULL },
+	{ 0x00000001, "NOTIFY", NULL },
+	{ 0x00000002, "QUERY", NULL },
+	{ 0x00000003, "COND", NULL },
+	{ 0x00000004, "M2M_IN", NULL },
+	{ 0x00000005, "M2M_OUT", NULL },
+	{ 0x00000006, "M2M_NOTIFY", NULL },
+	{}
+};
 
-	pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
-		       PCI_DMA_BIDIRECTIONAL);
-	__free_page(priv->r100c08_page);
-	kfree(priv);
-}
+static struct nouveau_enum vm_ccache_subclients[] = {
+	{ 0x00000000, "CB", NULL },
+	{ 0x00000001, "TIC", NULL },
+	{ 0x00000002, "TSC", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_prop_subclients[] = {
+	{ 0x00000000, "RT0", NULL },
+	{ 0x00000001, "RT1", NULL },
+	{ 0x00000002, "RT2", NULL },
+	{ 0x00000003, "RT3", NULL },
+	{ 0x00000004, "RT4", NULL },
+	{ 0x00000005, "RT5", NULL },
+	{ 0x00000006, "RT6", NULL },
+	{ 0x00000007, "RT7", NULL },
+	{ 0x00000008, "ZETA", NULL },
+	{ 0x00000009, "LOCAL", NULL },
+	{ 0x0000000a, "GLOBAL", NULL },
+	{ 0x0000000b, "STACK", NULL },
+	{ 0x0000000c, "DST2D", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_pfifo_subclients[] = {
+	{ 0x00000000, "PUSHBUF", NULL },
+	{ 0x00000001, "SEMAPHORE", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_bar_subclients[] = {
+	{ 0x00000000, "FB", NULL },
+	{ 0x00000001, "IN", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_client[] = {
+	{ 0x00000000, "STRMOUT", NULL },
+	{ 0x00000003, "DISPATCH", vm_dispatch_subclients },
+	{ 0x00000004, "PFIFO_WRITE", NULL },
+	{ 0x00000005, "CCACHE", vm_ccache_subclients },
+	{ 0x00000006, "PPPP", NULL },
+	{ 0x00000007, "CLIPID", NULL },
+	{ 0x00000008, "PFIFO_READ", NULL },
+	{ 0x00000009, "VFETCH", NULL },
+	{ 0x0000000a, "TEXTURE", NULL },
+	{ 0x0000000b, "PROP", vm_prop_subclients },
+	{ 0x0000000c, "PVP", NULL },
+	{ 0x0000000d, "PBSP", NULL },
+	{ 0x0000000e, "PCRYPT", NULL },
+	{ 0x0000000f, "PCOUNTER", NULL },
+	{ 0x00000011, "PDAEMON", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_engine[] = {
+	{ 0x00000000, "PGRAPH", NULL },
+	{ 0x00000001, "PVP", NULL },
+	{ 0x00000004, "PEEPHOLE", NULL },
+	{ 0x00000005, "PFIFO", vm_pfifo_subclients },
+	{ 0x00000006, "BAR", vm_bar_subclients },
+	{ 0x00000008, "PPPP", NULL },
+	{ 0x00000009, "PBSP", NULL },
+	{ 0x0000000a, "PCRYPT", NULL },
+	{ 0x0000000b, "PCOUNTER", NULL },
+	{ 0x0000000c, "SEMAPHORE_BG", NULL },
+	{ 0x0000000d, "PCOPY", NULL },
+	{ 0x0000000e, "PDAEMON", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_fault[] = {
+	{ 0x00000000, "PT_NOT_PRESENT", NULL },
+	{ 0x00000001, "PT_TOO_SHORT", NULL },
+	{ 0x00000002, "PAGE_NOT_PRESENT", NULL },
+	{ 0x00000003, "PAGE_SYSTEM_ONLY", NULL },
+	{ 0x00000004, "PAGE_READ_ONLY", NULL },
+	{ 0x00000006, "NULL_DMAOBJ", NULL },
+	{ 0x00000007, "WRONG_MEMTYPE", NULL },
+	{ 0x0000000b, "VRAM_LIMIT", NULL },
+	{ 0x0000000f, "DMAOBJ_LIMIT", NULL },
+	{}
+};
 
 void
-nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
+nv50_fb_vm_trap(struct drm_device *dev, int display)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	const struct nouveau_enum *en, *cl;
 	unsigned long flags;
 	u32 trap[6], idx, chinst;
+	u8 st0, st1, st2, st3;
 	int i, ch;
 
 	idx = nv_rd32(dev, 0x100c90);
@@ -117,8 +233,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
 	if (!display)
 		return;
 
+	/* lookup channel id */
 	chinst = (trap[2] << 16) | trap[1];
-
 	spin_lock_irqsave(&dev_priv->channels.lock, flags);
 	for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
 		struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
@@ -131,9 +247,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
 	}
 	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
 
-	NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x "
-		     "channel %d (0x%08x)\n",
-		name, (trap[5] & 0x100 ? "read" : "write"),
-		trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
-		trap[0], ch, chinst);
+	/* decode status bits into something more useful */
+	if (dev_priv->chipset  < 0xa3 ||
+	    dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
+		st0 = (trap[0] & 0x0000000f) >> 0;
+		st1 = (trap[0] & 0x000000f0) >> 4;
+		st2 = (trap[0] & 0x00000f00) >> 8;
+		st3 = (trap[0] & 0x0000f000) >> 12;
+	} else {
+		st0 = (trap[0] & 0x000000ff) >> 0;
+		st1 = (trap[0] & 0x0000ff00) >> 8;
+		st2 = (trap[0] & 0x00ff0000) >> 16;
+		st3 = (trap[0] & 0xff000000) >> 24;
+	}
+
+	NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ",
+		(trap[5] & 0x00000100) ? "read" : "write",
+		trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst);
+
+	en = nouveau_enum_find(vm_engine, st0);
+	if (en)
+		printk("%s/", en->name);
+	else
+		printk("%02x/", st0);
+
+	cl = nouveau_enum_find(vm_client, st2);
+	if (cl)
+		printk("%s/", cl->name);
+	else
+		printk("%02x/", st2);
+
+	if      (cl && cl->data) cl = nouveau_enum_find(cl->data, st3);
+	else if (en && en->data) cl = nouveau_enum_find(en->data, st3);
+	else                     cl = NULL;
+	if (cl)
+		printk("%s", cl->name);
+	else
+		printk("%02x", st3);
+
+	printk(" reason: ");
+	en = nouveau_enum_find(vm_fault, st1);
+	if (en)
+		printk("%s\n", en->name);
+	else
+		printk("0x%08x\n", st1);
 }
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c
index 8dd04c5..c34a074 100644
--- a/drivers/gpu/drm/nouveau/nv50_fifo.c
+++ b/drivers/gpu/drm/nouveau/nv50_fifo.c
@@ -149,6 +149,7 @@ nv50_fifo_init_regs(struct drm_device *dev)
 	nv_wr32(dev, 0x3204, 0);
 	nv_wr32(dev, 0x3210, 0);
 	nv_wr32(dev, 0x3270, 0);
+	nv_wr32(dev, 0x2044, 0x01003fff);
 
 	/* Enable dummy channels setup by nv50_instmem.c */
 	nv50_fifo_channel_enable(dev, 0);
@@ -273,7 +274,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
 	nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
 			     (4 << 24) /* SEARCH_FULL */ |
 			     (chan->ramht->gpuobj->cinst >> 4));
-	nv_wo32(ramfc, 0x44, 0x2101ffff);
+	nv_wo32(ramfc, 0x44, 0x01003fff);
 	nv_wo32(ramfc, 0x60, 0x7fffffff);
 	nv_wo32(ramfc, 0x40, 0x00000000);
 	nv_wo32(ramfc, 0x7c, 0x30000001);
diff --git a/drivers/gpu/drm/nouveau/nv50_gpio.c b/drivers/gpu/drm/nouveau/nv50_gpio.c
index 6b149c0..d4f4206 100644
--- a/drivers/gpu/drm/nouveau/nv50_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv50_gpio.c
@@ -137,6 +137,7 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag,
 	struct nv50_gpio_priv *priv = pgpio->priv;
 	struct nv50_gpio_handler *gpioh, *tmp;
 	struct dcb_gpio_entry *gpio;
+	LIST_HEAD(tofree);
 	unsigned long flags;
 
 	gpio = nouveau_bios_gpio_entry(dev, tag);
@@ -149,10 +150,14 @@ nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag,
 		    gpioh->handler != handler ||
 		    gpioh->data != data)
 			continue;
-		list_del(&gpioh->head);
-		kfree(gpioh);
+		list_move(&gpioh->head, &tofree);
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	list_for_each_entry_safe(gpioh, tmp, &tofree, head) {
+		flush_work_sync(&gpioh->work);
+		kfree(gpioh);
+	}
 }
 
 bool
@@ -205,7 +210,6 @@ nv50_gpio_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	struct nv50_gpio_priv *priv;
 	int ret;
 
 	if (!pgpio->priv) {
@@ -213,7 +217,6 @@ nv50_gpio_init(struct drm_device *dev)
 		if (ret)
 			return ret;
 	}
-	priv = pgpio->priv;
 
 	/* disable, and ack any pending gpio interrupts */
 	nv_wr32(dev, 0xe050, 0x00000000);
@@ -293,7 +296,7 @@ nv50_gpio_isr(struct drm_device *dev)
 			continue;
 		gpioh->inhibit = true;
 
-		queue_work(dev_priv->wq, &gpioh->work);
+		schedule_work(&gpioh->work);
 	}
 	spin_unlock(&priv->lock);
 }
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index 37e21d2..8675b00 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -95,13 +95,41 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
 }
 
 static void
-nv50_graph_init_regs(struct drm_device *dev)
+nv50_graph_init_zcull(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i;
+
 	NV_DEBUG(dev, "\n");
 
-	nv_wr32(dev, NV04_PGRAPH_DEBUG_3,
-				(1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */);
-	nv_wr32(dev, 0x402ca8, 0x800);
+	switch (dev_priv->chipset & 0xf0) {
+	case 0x50:
+	case 0x80:
+	case 0x90:
+		nv_wr32(dev, 0x402ca8, 0x00000800);
+		break;
+	case 0xa0:
+	default:
+		nv_wr32(dev, 0x402cc0, 0x00000000);
+		if (dev_priv->chipset == 0xa0 ||
+		    dev_priv->chipset == 0xaa ||
+		    dev_priv->chipset == 0xac) {
+			nv_wr32(dev, 0x402ca8, 0x00000802);
+		} else {
+			nv_wr32(dev, 0x402cc0, 0x00000000);
+			nv_wr32(dev, 0x402ca8, 0x00000002);
+		}
+
+		break;
+	}
+
+	/* zero out zcull regions */
+	for (i = 0; i < 8; i++) {
+		nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000);
+		nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000);
+		nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
+		nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
+	}
 }
 
 static int
@@ -136,6 +164,7 @@ nv50_graph_init_ctxctl(struct drm_device *dev)
 	}
 	kfree(cp);
 
+	nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
 	nv_wr32(dev, 0x400320, 4);
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
 	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
@@ -151,7 +180,7 @@ nv50_graph_init(struct drm_device *dev)
 
 	nv50_graph_init_reset(dev);
 	nv50_graph_init_regs__nv(dev);
-	nv50_graph_init_regs(dev);
+	nv50_graph_init_zcull(dev);
 
 	ret = nv50_graph_init_ctxctl(dev);
 	if (ret)
@@ -409,12 +438,7 @@ static int
 nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan,
 			       u32 class, u32 mthd, u32 data)
 {
-	struct nouveau_page_flip_state s;
-
-	if (!nouveau_finish_page_flip(chan, &s)) {
-		/* XXX - Do something here */
-	}
-
+	nouveau_finish_page_flip(chan, NULL);
 	return 0;
 }
 
@@ -526,11 +550,11 @@ nv86_graph_tlb_flush(struct drm_device *dev)
 
 static struct nouveau_enum nv50_mp_exec_error_names[] =
 {
-	{ 3, "STACK_UNDERFLOW" },
-	{ 4, "QUADON_ACTIVE" },
-	{ 8, "TIMEOUT" },
-	{ 0x10, "INVALID_OPCODE" },
-	{ 0x40, "BREAKPOINT" },
+	{ 3, "STACK_UNDERFLOW", NULL },
+	{ 4, "QUADON_ACTIVE", NULL },
+	{ 8, "TIMEOUT", NULL },
+	{ 0x10, "INVALID_OPCODE", NULL },
+	{ 0x40, "BREAKPOINT", NULL },
 	{}
 };
 
@@ -558,47 +582,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = {
 
 /* There must be a *lot* of these. Will take some time to gather them up. */
 struct nouveau_enum nv50_data_error_names[] = {
-	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE" },
-	{ 0x00000004, "INVALID_VALUE" },
-	{ 0x00000005, "INVALID_ENUM" },
-	{ 0x00000008, "INVALID_OBJECT" },
-	{ 0x00000009, "READ_ONLY_OBJECT" },
-	{ 0x0000000a, "SUPERVISOR_OBJECT" },
-	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" },
-	{ 0x0000000c, "INVALID_BITFIELD" },
-	{ 0x0000000d, "BEGIN_END_ACTIVE" },
-	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" },
-	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP" },
-	{ 0x00000010, "RT_DOUBLE_BIND" },
-	{ 0x00000011, "RT_TYPES_MISMATCH" },
-	{ 0x00000012, "RT_LINEAR_WITH_ZETA" },
-	{ 0x00000015, "FP_TOO_FEW_REGS" },
-	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" },
-	{ 0x00000017, "RT_LINEAR_WITH_MSAA" },
-	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" },
-	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" },
-	{ 0x0000001a, "RT_INVALID_ALIGNMENT" },
-	{ 0x0000001b, "SAMPLER_OVER_LIMIT" },
-	{ 0x0000001c, "TEXTURE_OVER_LIMIT" },
-	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS" },
-	{ 0x0000001f, "RT_BPP128_WITH_MS8" },
-	{ 0x00000021, "Z_OUT_OF_BOUNDS" },
-	{ 0x00000023, "XY_OUT_OF_BOUNDS" },
-	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" },
-	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED" },
-	{ 0x00000029, "CP_NO_REG_SPACE_PACKED" },
-	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS" },
-	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" },
-	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" },
-	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" },
-	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH" },
-	{ 0x00000031, "ENG2D_FORMAT_MISMATCH" },
-	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" },
-	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" },
-	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" },
-	{ 0x00000046, "LAYER_ID_NEEDS_GP" },
-	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" },
-	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" },
+	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL },
+	{ 0x00000004, "INVALID_VALUE", NULL },
+	{ 0x00000005, "INVALID_ENUM", NULL },
+	{ 0x00000008, "INVALID_OBJECT", NULL },
+	{ 0x00000009, "READ_ONLY_OBJECT", NULL },
+	{ 0x0000000a, "SUPERVISOR_OBJECT", NULL },
+	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
+	{ 0x0000000c, "INVALID_BITFIELD", NULL },
+	{ 0x0000000d, "BEGIN_END_ACTIVE", NULL },
+	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
+	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
+	{ 0x00000010, "RT_DOUBLE_BIND", NULL },
+	{ 0x00000011, "RT_TYPES_MISMATCH", NULL },
+	{ 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
+	{ 0x00000015, "FP_TOO_FEW_REGS", NULL },
+	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
+	{ 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
+	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
+	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
+	{ 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
+	{ 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
+	{ 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
+	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
+	{ 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
+	{ 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
+	{ 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
+	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
+	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
+	{ 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
+	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
+	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
+	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
+	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
+	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
+	{ 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
+	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
+	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
+	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
+	{ 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
+	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
+	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
 	{}
 };
 
@@ -678,7 +702,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
 		tps++;
 		switch (type) {
 		case 6: /* texture error... unknown for now */
-			nv50_fb_vm_trap(dev, display, name);
 			if (display) {
 				NV_ERROR(dev, "magic set %d:\n", i);
 				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
@@ -701,7 +724,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old,
 			uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
 			uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
 			uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
-			nv50_fb_vm_trap(dev, display, name);
 			/* 2d engine destination */
 			if (ustatus & 0x00000010) {
 				if (display) {
@@ -912,10 +934,10 @@ nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid
 			printk("\n");
 			NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x"
 				     " %08x %08x %08x\n",
-				nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804),
-				nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c),
-				nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814),
-				nv_rd32(dev, 0x40581c));
+				nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004),
+				nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c),
+				nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014),
+				nv_rd32(dev, 0x40501c));
 
 		}
 
@@ -1044,6 +1066,7 @@ nv50_graph_isr(struct drm_device *dev)
 			NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d "
 				     "class 0x%04x mthd 0x%04x data 0x%08x\n",
 				chid, inst, subc, class, mthd, data);
+			nv50_fb_vm_trap(dev, 1);
 		}
 	}
 
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c
index e57caa2..a6f8aa6 100644
--- a/drivers/gpu/drm/nouveau/nv50_instmem.c
+++ b/drivers/gpu/drm/nouveau/nv50_instmem.c
@@ -56,7 +56,7 @@ nv50_channel_del(struct nouveau_channel **pchan)
 	nouveau_gpuobj_ref(NULL, &chan->ramfc);
 	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
 	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
-	if (chan->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
 	kfree(chan);
@@ -259,7 +259,7 @@ nv50_instmem_takedown(struct drm_device *dev)
 	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
 	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
 
-	if (dev_priv->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&dev_priv->ramin_heap))
 		drm_mm_takedown(&dev_priv->ramin_heap);
 
 	dev_priv->engine.instmem.priv = NULL;
@@ -300,7 +300,7 @@ nv50_instmem_resume(struct drm_device *dev)
 }
 
 struct nv50_gpuobj_node {
-	struct nouveau_vram *vram;
+	struct nouveau_mem *vram;
 	struct nouveau_vma chan_vma;
 	u32 align;
 };
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index b4a5ecb..c25c593 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -41,8 +41,7 @@ nv50_sor_disconnect(struct drm_encoder *encoder)
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	if (!nv_encoder->crtc)
@@ -184,8 +183,7 @@ static void
 nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
 {
-	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(encoder->dev)->master;
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c
index 6144156..4fd3432 100644
--- a/drivers/gpu/drm/nouveau/nv50_vm.c
+++ b/drivers/gpu/drm/nouveau/nv50_vm.c
@@ -31,7 +31,6 @@ void
 nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 		struct nouveau_gpuobj *pgt[2])
 {
-	struct drm_nouveau_private *dev_priv = pgd->dev->dev_private;
 	u64 phys = 0xdeadcafe00000000ULL;
 	u32 coverage = 0;
 
@@ -58,10 +57,9 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 }
 
 static inline u64
-nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	     u64 phys, u32 memtype, u32 target)
+nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
 {
-	struct drm_nouveau_private *dev_priv = pgt->dev->dev_private;
+	struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private;
 
 	phys |= 1; /* present */
 	phys |= (u64)memtype << 40;
@@ -85,12 +83,13 @@ nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
 
 void
 nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	    struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys)
+	    struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
 {
+	u32 comp = (mem->memtype & 0x180) >> 7;
 	u32 block;
 	int i;
 
-	phys  = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0);
+	phys  = nv50_vm_addr(vma, phys, mem->memtype, 0);
 	pte <<= 3;
 	cnt <<= 3;
 
@@ -107,6 +106,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
 
 		phys += block << (vma->node->type - 3);
 		cnt  -= block;
+		if (comp) {
+			u32 tag = mem->tag->start + ((delta >> 16) * comp);
+			offset_h |= (tag << 17);
+			delta    += block << (vma->node->type - 3);
+		}
 
 		while (block) {
 			nv_wo32(pgt, pte + 0, offset_l);
@@ -119,11 +123,11 @@ nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
 
 void
 nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	       u32 pte, dma_addr_t *list, u32 cnt)
+	       struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
 	pte <<= 3;
 	while (cnt--) {
-		u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2);
+		u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2);
 		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
 		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
 		pte += 8;
diff --git a/drivers/gpu/drm/nouveau/nv50_vram.c b/drivers/gpu/drm/nouveau/nv50_vram.c
index 58e98ad..ffbc3d8 100644
--- a/drivers/gpu/drm/nouveau/nv50_vram.c
+++ b/drivers/gpu/drm/nouveau/nv50_vram.c
@@ -48,42 +48,49 @@ nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
 }
 
 void
-nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram)
+nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
 	struct nouveau_mm *mm = man->priv;
 	struct nouveau_mm_node *this;
-	struct nouveau_vram *vram;
+	struct nouveau_mem *mem;
 
-	vram = *pvram;
-	*pvram = NULL;
-	if (unlikely(vram == NULL))
+	mem = *pmem;
+	*pmem = NULL;
+	if (unlikely(mem == NULL))
 		return;
 
 	mutex_lock(&mm->mutex);
-	while (!list_empty(&vram->regions)) {
-		this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
+	while (!list_empty(&mem->regions)) {
+		this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
 
 		list_del(&this->rl_entry);
 		nouveau_mm_put(mm, this);
 	}
+
+	if (mem->tag) {
+		drm_mm_put_block(mem->tag);
+		mem->tag = NULL;
+	}
 	mutex_unlock(&mm->mutex);
 
-	kfree(vram);
+	kfree(mem);
 }
 
 int
 nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
-	      u32 type, struct nouveau_vram **pvram)
+	      u32 memtype, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
 	struct nouveau_mm *mm = man->priv;
 	struct nouveau_mm_node *r;
-	struct nouveau_vram *vram;
+	struct nouveau_mem *mem;
+	int comp = (memtype & 0x300) >> 8;
+	int type = (memtype & 0x07f);
 	int ret;
 
 	if (!types[type])
@@ -92,32 +99,46 @@ nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
 	align >>= 12;
 	size_nc >>= 12;
 
-	vram = kzalloc(sizeof(*vram), GFP_KERNEL);
-	if (!vram)
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&vram->regions);
-	vram->dev = dev_priv->dev;
-	vram->memtype = type;
-	vram->size = size;
-
 	mutex_lock(&mm->mutex);
+	if (comp) {
+		if (align == 16) {
+			struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+			int n = (size >> 4) * comp;
+
+			mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0);
+			if (mem->tag)
+				mem->tag = drm_mm_get_block(mem->tag, n, 0);
+		}
+
+		if (unlikely(!mem->tag))
+			comp = 0;
+	}
+
+	INIT_LIST_HEAD(&mem->regions);
+	mem->dev = dev_priv->dev;
+	mem->memtype = (comp << 7) | type;
+	mem->size = size;
+
 	do {
 		ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r);
 		if (ret) {
 			mutex_unlock(&mm->mutex);
-			nv50_vram_del(dev, &vram);
+			nv50_vram_del(dev, &mem);
 			return ret;
 		}
 
-		list_add_tail(&r->rl_entry, &vram->regions);
+		list_add_tail(&r->rl_entry, &mem->regions);
 		size -= r->length;
 	} while (size);
 	mutex_unlock(&mm->mutex);
 
-	r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
-	vram->offset = (u64)r->offset << 12;
-	*pvram = vram;
+	r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
+	mem->offset = (u64)r->offset << 12;
+	*pmem = mem;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c
index ec18ae1..fabc7fd 100644
--- a/drivers/gpu/drm/nouveau/nv84_crypt.c
+++ b/drivers/gpu/drm/nouveau/nv84_crypt.c
@@ -136,5 +136,5 @@ nv84_crypt_isr(struct drm_device *dev)
 	nv_wr32(dev, 0x102130, stat);
 	nv_wr32(dev, 0x10200c, 0x10);
 
-	nv50_fb_vm_trap(dev, show, "PCRYPT");
+	nv50_fb_vm_trap(dev, show);
 }
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c
index e6f92c5..2886f27 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fifo.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c
@@ -116,7 +116,7 @@ nvc0_fifo_create_context(struct nouveau_channel *chan)
 
 	/* allocate vram for control regs, map into polling area */
 	ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM,
-			     0, 0, true, true, &fifoch->user);
+			     0, 0, &fifoch->user);
 	if (ret)
 		goto error;
 
@@ -418,6 +418,12 @@ nvc0_fifo_isr(struct drm_device *dev)
 {
 	u32 stat = nv_rd32(dev, 0x002100);
 
+	if (stat & 0x00000100) {
+		NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
+		nv_wr32(dev, 0x002100, 0x00000100);
+		stat &= ~0x00000100;
+	}
+
 	if (stat & 0x10000000) {
 		u32 units = nv_rd32(dev, 0x00259c);
 		u32 u = units;
@@ -446,10 +452,15 @@ nvc0_fifo_isr(struct drm_device *dev)
 		stat &= ~0x20000000;
 	}
 
+	if (stat & 0x40000000) {
+		NV_INFO(dev, "PFIFO: unknown status 0x40000000\n");
+		nv_mask(dev, 0x002a00, 0x00000000, 0x00000000);
+		stat &= ~0x40000000;
+	}
+
 	if (stat) {
 		NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat);
 		nv_wr32(dev, 0x002100, stat);
+		nv_wr32(dev, 0x002140, 0);
 	}
-
-	nv_wr32(dev, 0x2140, 0);
 }
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c
index eb18a7e..3de9b72 100644
--- a/drivers/gpu/drm/nouveau/nvc0_graph.c
+++ b/drivers/gpu/drm/nouveau/nvc0_graph.c
@@ -299,6 +299,14 @@ nvc0_graph_takedown(struct drm_device *dev)
 }
 
 static int
+nvc0_graph_mthd_page_flip(struct nouveau_channel *chan,
+			  u32 class, u32 mthd, u32 data)
+{
+	nouveau_finish_page_flip(chan, NULL);
+	return 0;
+}
+
+static int
 nvc0_graph_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -395,6 +403,7 @@ nvc0_graph_create(struct drm_device *dev)
 	nouveau_irq_register(dev, 25, nvc0_runk140_isr);
 	NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
 	NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
+	NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
 	NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
 	NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
 	return 0;
@@ -640,7 +649,6 @@ nvc0_graph_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	struct nvc0_graph_priv *priv;
 	int ret;
 
 	dev_priv->engine.graph.accel_blocked = true;
@@ -665,7 +673,6 @@ nvc0_graph_init(struct drm_device *dev)
 		if (ret)
 			return ret;
 	}
-	priv = pgraph->priv;
 
 	nvc0_graph_init_obj418880(dev);
 	nvc0_graph_init_regs(dev);
@@ -730,9 +737,12 @@ nvc0_graph_isr(struct drm_device *dev)
 	u32 class = nv_rd32(dev, 0x404200 + (subc * 4));
 
 	if (stat & 0x00000010) {
-		NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d "
-			     "class 0x%04x mthd 0x%04x data 0x%08x\n",
-			chid, inst, subc, class, mthd, data);
+		if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) {
+			NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] "
+				     "subc %d class 0x%04x mthd 0x%04x "
+				     "data 0x%08x\n",
+				chid, inst, subc, class, mthd, data);
+		}
 		nv_wr32(dev, 0x400100, 0x00000010);
 		stat &= ~0x00000010;
 	}
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c
index c090917..82357d2 100644
--- a/drivers/gpu/drm/nouveau/nvc0_instmem.c
+++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c
@@ -67,7 +67,7 @@ nvc0_channel_del(struct nouveau_channel **pchan)
 		return;
 
 	nouveau_vm_ref(NULL, &chan->vm, NULL);
-	if (chan->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
 	kfree(chan);
diff --git a/drivers/gpu/drm/nouveau/nvc0_vm.c b/drivers/gpu/drm/nouveau/nvc0_vm.c
index e4e83c2..69af0ba 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vm.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vm.c
@@ -59,7 +59,7 @@ nvc0_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
 
 void
 nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	    struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys)
+	    struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
 {
 	u32 next = 1 << (vma->node->type - 8);
 
@@ -75,11 +75,11 @@ nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
 
 void
 nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	       u32 pte, dma_addr_t *list, u32 cnt)
+	       struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
 	pte <<= 3;
 	while (cnt--) {
-		u64 phys = nvc0_vm_addr(vma, *list++, 0, 5);
+		u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5);
 		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
 		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
 		pte += 8;
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index 858eda5..67c6ec6 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -26,64 +26,78 @@
 #include "nouveau_drv.h"
 #include "nouveau_mm.h"
 
+/* 0 = unsupported
+ * 1 = non-compressed
+ * 3 = compressed
+ */
+static const u8 types[256] = {
+	1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
+	0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
+	3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 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, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+	3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
+	3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
+	3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
+};
+
 bool
 nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
 {
-	switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
-	case 0x0000:
-	case 0xfe00:
-	case 0xdb00:
-	case 0x1100:
-		return true;
-	default:
-		break;
-	}
-
-	return false;
+	u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
+	return likely((types[memtype] == 1));
 }
 
 int
 nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
-	      u32 type, struct nouveau_vram **pvram)
+	      u32 type, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
 	struct nouveau_mm *mm = man->priv;
 	struct nouveau_mm_node *r;
-	struct nouveau_vram *vram;
+	struct nouveau_mem *mem;
 	int ret;
 
 	size  >>= 12;
 	align >>= 12;
 	ncmin >>= 12;
 
-	vram = kzalloc(sizeof(*vram), GFP_KERNEL);
-	if (!vram)
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&vram->regions);
-	vram->dev = dev_priv->dev;
-	vram->memtype = type;
-	vram->size = size;
+	INIT_LIST_HEAD(&mem->regions);
+	mem->dev = dev_priv->dev;
+	mem->memtype = (type & 0xff);
+	mem->size = size;
 
 	mutex_lock(&mm->mutex);
 	do {
 		ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r);
 		if (ret) {
 			mutex_unlock(&mm->mutex);
-			nv50_vram_del(dev, &vram);
+			nv50_vram_del(dev, &mem);
 			return ret;
 		}
 
-		list_add_tail(&r->rl_entry, &vram->regions);
+		list_add_tail(&r->rl_entry, &mem->regions);
 		size -= r->length;
 	} while (size);
 	mutex_unlock(&mm->mutex);
 
-	r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
-	vram->offset = (u64)r->offset << 12;
-	*pvram = vram;
+	r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
+	mem->offset = (u64)r->offset << 12;
+	*pmem = mem;
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c
index 18c3c71..b9e8efd 100644
--- a/drivers/gpu/drm/r128/r128_drv.c
+++ b/drivers/gpu/drm/r128/r128_drv.c
@@ -71,10 +71,7 @@ static struct drm_driver driver = {
 #endif
 		.llseek = noop_llseek,
 	},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-	},
+
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -89,16 +86,21 @@ int r128_driver_load(struct drm_device *dev, unsigned long flags)
 	return drm_vblank_init(dev, 1);
 }
 
+static struct pci_driver r128_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init r128_init(void)
 {
 	driver.num_ioctls = r128_max_ioctl;
 
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &r128_pci_driver);
 }
 
 static void __exit r128_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &r128_pci_driver);
 }
 
 module_init(r128_init);
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 1c02d23..9746fee 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -1,6 +1,7 @@
 config DRM_RADEON_KMS
 	bool "Enable modesetting on radeon by default - NEW DRIVER"
 	depends on DRM_RADEON
+	select BACKLIGHT_CLASS_DEVICE
 	help
 	  Choose this option if you want kernel modesetting enabled by default.
 
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile
index e47eecf..3896ef8 100644
--- a/drivers/gpu/drm/radeon/Makefile
+++ b/drivers/gpu/drm/radeon/Makefile
@@ -36,6 +36,9 @@ $(obj)/r600_reg_safe.h: $(src)/reg_srcs/r600 $(obj)/mkregtable
 $(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
 	$(call if_changed,mkregtable)
 
+$(obj)/cayman_reg_safe.h: $(src)/reg_srcs/cayman $(obj)/mkregtable
+	$(call if_changed,mkregtable)
+
 $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
 
 $(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -50,7 +53,7 @@ $(obj)/rs600.o: $(obj)/rs600_reg_safe.h
 
 $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
 
-$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
+$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h $(obj)/cayman_reg_safe.h
 
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
 	radeon_irq.o r300_cmdbuf.o r600_cp.o
@@ -66,7 +69,7 @@ radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
 	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
 	evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
-	radeon_trace_points.o ni.o
+	radeon_trace_points.o ni.o cayman_blit_shaders.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index a4e5e53..3cd3234 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -61,8 +61,8 @@ static void atombios_overscan_setup(struct drm_crtc *crtc,
 			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 		} else if (a2 > a1) {
-			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
-			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
 		}
 		break;
 	case RMX_FULL:
@@ -1026,7 +1026,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 	 * just update base pointers
 	 */
 	obj = radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -1135,7 +1135,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
 
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
-		rbo = radeon_fb->obj->driver_private;
+		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r != 0))
 			return r;
@@ -1181,7 +1181,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 	}
 
 	obj = radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -1292,7 +1292,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
 
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
-		rbo = radeon_fb->obj->driver_private;
+		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r != 0))
 			return r;
diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.c b/drivers/gpu/drm/radeon/cayman_blit_shaders.c
new file mode 100644
index 0000000..e148ab0
--- /dev/null
+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     Alex Deucher <alexander.deucher@amd.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+/*
+ * evergreen cards need to use the 3D engine to blit data which requires
+ * quite a bit of hw state setup.  Rather than pull the whole 3D driver
+ * (which normally generates the 3D state) into the DRM, we opt to use
+ * statically generated state tables.  The regsiter state and shaders
+ * were hand generated to support blitting functionality.  See the 3D
+ * driver or documentation for descriptions of the registers and
+ * shader instructions.
+ */
+
+const u32 cayman_default_state[] =
+{
+	/* XXX fill in additional blit state */
+
+	0xc0026900,
+	0x00000316,
+	0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */
+	0x00000010, /*  */
+
+	0xc0026900,
+	0x000000d9,
+	0x00000000, /* CP_RINGID */
+	0x00000000, /* CP_VMID */
+};
+
+const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state);
diff --git a/drivers/gpu/drm/radeon/cayman_blit_shaders.h b/drivers/gpu/drm/radeon/cayman_blit_shaders.h
new file mode 100644
index 0000000..33b75e5d
--- /dev/null
+++ b/drivers/gpu/drm/radeon/cayman_blit_shaders.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS 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 CAYMAN_BLIT_SHADERS_H
+#define CAYMAN_BLIT_SHADERS_H
+
+extern const u32 cayman_default_state[];
+
+extern const u32 cayman_default_size;
+
+#endif
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 6140ea1..941080a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -804,7 +804,7 @@ void evergreen_bandwidth_update(struct radeon_device *rdev)
 	}
 }
 
-static int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
+int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
 {
 	unsigned i;
 	u32 tmp;
@@ -957,7 +957,7 @@ void evergreen_agp_enable(struct radeon_device *rdev)
 	WREG32(VM_CONTEXT1_CNTL, 0);
 }
 
-static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
+void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
 {
 	save->vga_control[0] = RREG32(D1VGA_CONTROL);
 	save->vga_control[1] = RREG32(D2VGA_CONTROL);
@@ -1011,7 +1011,7 @@ static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_sa
 	WREG32(EVERGREEN_D6VGA_CONTROL, 0);
 }
 
-static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
+void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
 {
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
 	       upper_32_bits(rdev->mc.vram_start));
@@ -1108,7 +1108,7 @@ static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_
 	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
 }
 
-static void evergreen_mc_program(struct radeon_device *rdev)
+void evergreen_mc_program(struct radeon_device *rdev)
 {
 	struct evergreen_mc_save save;
 	u32 tmp;
@@ -2576,7 +2576,7 @@ void evergreen_irq_disable(struct radeon_device *rdev)
 	evergreen_disable_interrupt_state(rdev);
 }
 
-static void evergreen_irq_suspend(struct radeon_device *rdev)
+void evergreen_irq_suspend(struct radeon_device *rdev)
 {
 	evergreen_irq_disable(rdev);
 	r600_rlc_stop(rdev);
@@ -2899,7 +2899,7 @@ static int evergreen_startup(struct radeon_device *rdev)
 				return r;
 			}
 		}
-		r = btc_mc_load_microcode(rdev);
+		r = ni_mc_load_microcode(rdev);
 		if (r) {
 			DRM_ERROR("Failed to load MC firmware!\n");
 			return r;
@@ -2981,13 +2981,13 @@ int evergreen_resume(struct radeon_device *rdev)
 
 	r = evergreen_startup(rdev);
 	if (r) {
-		DRM_ERROR("r600 startup failed on resume\n");
+		DRM_ERROR("evergreen startup failed on resume\n");
 		return r;
 	}
 
 	r = r600_ib_test(rdev);
 	if (r) {
-		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		DRM_ERROR("radeon: failed testing IB (%d).\n", r);
 		return r;
 	}
 
@@ -3061,7 +3061,7 @@ int evergreen_init(struct radeon_device *rdev)
 	}
 	/* Must be an ATOMBIOS */
 	if (!rdev->is_atom_bios) {
-		dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
+		dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n");
 		return -EINVAL;
 	}
 	r = radeon_atombios_init(rdev);
diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
index 2be698e..ba06a69 100644
--- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c
+++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c
@@ -579,7 +579,7 @@ int evergreen_blit_init(struct radeon_device *rdev)
 	obj_size += evergreen_ps_size * 4;
 	obj_size = ALIGN(obj_size, 256);
 
-	r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				&rdev->r600_blit.shader_obj);
 	if (r) {
 		DRM_ERROR("evergreen failed to allocate shader\n");
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 345a75a..edde90b 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -29,6 +29,7 @@
 #include "radeon.h"
 #include "evergreend.h"
 #include "evergreen_reg_safe.h"
+#include "cayman_reg_safe.h"
 
 static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
 					  struct radeon_cs_reloc **cs_reloc);
@@ -292,33 +293,28 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
 	if (wait_reg_mem.type != PACKET_TYPE3 ||
 	    wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
 		DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
 	/* bit 4 is reg (0) or mem (1) */
 	if (wait_reg_mem_info & 0x10) {
 		DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	/* waiting for value to be equal */
 	if ((wait_reg_mem_info & 0x7) != 0x3) {
 		DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
 		DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
 		DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	/* jump over the NOP */
@@ -336,8 +332,7 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
 	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
 		DRM_ERROR("cannot find crtc %d\n", crtc_id);
-		r = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
@@ -362,12 +357,10 @@ static int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p)
 			break;
 		default:
 			DRM_ERROR("unknown crtc reloc\n");
-			r = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 	}
-out:
-	return r;
+	return 0;
 }
 
 static int evergreen_packet0_check(struct radeon_cs_parser *p,
@@ -425,18 +418,28 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
 {
 	struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
 	struct radeon_cs_reloc *reloc;
-	u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+	u32 last_reg;
 	u32 m, i, tmp, *ib;
 	int r;
 
+	if (p->rdev->family >= CHIP_CAYMAN)
+		last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
+	else
+		last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+
 	i = (reg >> 7);
 	if (i > last_reg) {
 		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 		return -EINVAL;
 	}
 	m = 1 << ((reg >> 2) & 31);
-	if (!(evergreen_reg_safe_bm[i] & m))
-		return 0;
+	if (p->rdev->family >= CHIP_CAYMAN) {
+		if (!(cayman_reg_safe_bm[i] & m))
+			return 0;
+	} else {
+		if (!(evergreen_reg_safe_bm[i] & m))
+			return 0;
+	}
 	ib = p->ib->ptr;
 	switch (reg) {
 	/* force following reg to 0 in an attemp to disable out buffer
@@ -468,12 +471,42 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
 	case SQ_VSTMP_RING_ITEMSIZE:
 	case VGT_TF_RING_SIZE:
 		/* get value to populate the IB don't remove */
-		tmp =radeon_get_ib_value(p, idx);
-		ib[idx] = 0;
+		/*tmp =radeon_get_ib_value(p, idx);
+		  ib[idx] = 0;*/
+		break;
+	case SQ_ESGS_RING_BASE:
+	case SQ_GSVS_RING_BASE:
+	case SQ_ESTMP_RING_BASE:
+	case SQ_GSTMP_RING_BASE:
+	case SQ_HSTMP_RING_BASE:
+	case SQ_LSTMP_RING_BASE:
+	case SQ_PSTMP_RING_BASE:
+	case SQ_VSTMP_RING_BASE:
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 		break;
 	case DB_DEPTH_CONTROL:
 		track->db_depth_control = radeon_get_ib_value(p, idx);
 		break;
+	case CAYMAN_DB_EQAA:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		break;
+	case CAYMAN_DB_DEPTH_INFO:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		break;
 	case DB_Z_INFO:
 		r = evergreen_cs_packet_next_reloc(p, &reloc);
 		if (r) {
@@ -559,9 +592,23 @@ static inline int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u3
 		track->cb_shader_mask = radeon_get_ib_value(p, idx);
 		break;
 	case PA_SC_AA_CONFIG:
+		if (p->rdev->family >= CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
 		tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
 		track->nsamples = 1 << tmp;
 		break;
+	case CAYMAN_PA_SC_AA_CONFIG:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
+		track->nsamples = 1 << tmp;
+		break;
 	case CB_COLOR0_VIEW:
 	case CB_COLOR1_VIEW:
 	case CB_COLOR2_VIEW:
@@ -942,6 +989,37 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 	idx_value = radeon_get_ib_value(p, idx);
 
 	switch (pkt->opcode) {
+	case PACKET3_SET_PREDICATION:
+	{
+		int pred_op;
+		int tmp;
+		if (pkt->count != 1) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		tmp = radeon_get_ib_value(p, idx + 1);
+		pred_op = (tmp >> 16) & 0x7;
+
+		/* for the clear predicate operation */
+		if (pred_op == 0)
+			return 0;
+
+		if (pred_op > 2) {
+			DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
+			return -EINVAL;
+		}
+
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+		ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);
+	}
+	break;
 	case PACKET3_CONTEXT_CONTROL:
 		if (pkt->count != 1) {
 			DRM_ERROR("bad CONTEXT_CONTROL\n");
@@ -956,6 +1034,16 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
 			return -EINVAL;
 		}
 		break;
+	case CAYMAN_PACKET3_DEALLOC_STATE:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");
+			return -EINVAL;
+		}
+		if (pkt->count) {
+			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
+			return -EINVAL;
+		}
+		break;
 	case PACKET3_INDEX_BASE:
 		if (pkt->count != 1) {
 			DRM_ERROR("bad INDEX_BASE\n");
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index eb4acf4..9aaa3f0 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -755,13 +755,21 @@
 
 #define SQ_CONST_MEM_BASE				0x8df8
 
+#define SQ_ESGS_RING_BASE				0x8c40
 #define SQ_ESGS_RING_SIZE				0x8c44
+#define SQ_GSVS_RING_BASE				0x8c48
 #define SQ_GSVS_RING_SIZE				0x8c4c
+#define SQ_ESTMP_RING_BASE				0x8c50
 #define SQ_ESTMP_RING_SIZE				0x8c54
+#define SQ_GSTMP_RING_BASE				0x8c58
 #define SQ_GSTMP_RING_SIZE				0x8c5c
+#define SQ_VSTMP_RING_BASE				0x8c60
 #define SQ_VSTMP_RING_SIZE				0x8c64
+#define SQ_PSTMP_RING_BASE				0x8c68
 #define SQ_PSTMP_RING_SIZE				0x8c6c
+#define SQ_LSTMP_RING_BASE				0x8e10
 #define SQ_LSTMP_RING_SIZE				0x8e14
+#define SQ_HSTMP_RING_BASE				0x8e18
 #define SQ_HSTMP_RING_SIZE				0x8e1c
 #define VGT_TF_RING_SIZE				0x8988
 
@@ -1093,5 +1101,14 @@
 #define SQ_TEX_RESOURCE_WORD6_0                         0x30018
 #define SQ_TEX_RESOURCE_WORD7_0                         0x3001c
 
+/* cayman 3D regs */
+#define CAYMAN_VGT_OFFCHIP_LDS_BASE			0x89B0
+#define CAYMAN_DB_EQAA					0x28804
+#define CAYMAN_DB_DEPTH_INFO				0x2803C
+#define CAYMAN_PA_SC_AA_CONFIG				0x28BE0
+#define         CAYMAN_MSAA_NUM_SAMPLES_SHIFT           0
+#define         CAYMAN_MSAA_NUM_SAMPLES_MASK            0x7
+/* cayman packet3 addition */
+#define	CAYMAN_PACKET3_DEALLOC_STATE			0x14
 
 #endif
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 5e0bef8..7aade20 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -31,12 +31,25 @@
 #include "nid.h"
 #include "atom.h"
 #include "ni_reg.h"
+#include "cayman_blit_shaders.h"
+
+extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
+extern void evergreen_mc_program(struct radeon_device *rdev);
+extern void evergreen_irq_suspend(struct radeon_device *rdev);
+extern int evergreen_mc_init(struct radeon_device *rdev);
 
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
 #define EVERGREEN_RLC_UCODE_SIZE 768
 #define BTC_MC_UCODE_SIZE 6024
 
+#define CAYMAN_PFP_UCODE_SIZE 2176
+#define CAYMAN_PM4_UCODE_SIZE 2176
+#define CAYMAN_RLC_UCODE_SIZE 1024
+#define CAYMAN_MC_UCODE_SIZE 6037
+
 /* Firmware Names */
 MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
 MODULE_FIRMWARE("radeon/BARTS_me.bin");
@@ -48,6 +61,10 @@ MODULE_FIRMWARE("radeon/TURKS_mc.bin");
 MODULE_FIRMWARE("radeon/CAICOS_pfp.bin");
 MODULE_FIRMWARE("radeon/CAICOS_me.bin");
 MODULE_FIRMWARE("radeon/CAICOS_mc.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_pfp.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_me.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_mc.bin");
+MODULE_FIRMWARE("radeon/CAYMAN_rlc.bin");
 
 #define BTC_IO_MC_REGS_SIZE 29
 
@@ -147,12 +164,44 @@ static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
 	{0x0000009f, 0x00916a00}
 };
 
-int btc_mc_load_microcode(struct radeon_device *rdev)
+static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
+	{0x00000077, 0xff010100},
+	{0x00000078, 0x00000000},
+	{0x00000079, 0x00001434},
+	{0x0000007a, 0xcc08ec08},
+	{0x0000007b, 0x00040000},
+	{0x0000007c, 0x000080c0},
+	{0x0000007d, 0x09000000},
+	{0x0000007e, 0x00210404},
+	{0x00000081, 0x08a8e800},
+	{0x00000082, 0x00030444},
+	{0x00000083, 0x00000000},
+	{0x00000085, 0x00000001},
+	{0x00000086, 0x00000002},
+	{0x00000087, 0x48490000},
+	{0x00000088, 0x20244647},
+	{0x00000089, 0x00000005},
+	{0x0000008b, 0x66030000},
+	{0x0000008c, 0x00006603},
+	{0x0000008d, 0x00000100},
+	{0x0000008f, 0x00001c0a},
+	{0x00000090, 0xff000001},
+	{0x00000094, 0x00101101},
+	{0x00000095, 0x00000fff},
+	{0x00000096, 0x00116fff},
+	{0x00000097, 0x60010000},
+	{0x00000098, 0x10010000},
+	{0x00000099, 0x00006000},
+	{0x0000009a, 0x00001000},
+	{0x0000009f, 0x00976b00}
+};
+
+int ni_mc_load_microcode(struct radeon_device *rdev)
 {
 	const __be32 *fw_data;
 	u32 mem_type, running, blackout = 0;
 	u32 *io_mc_regs;
-	int i;
+	int i, ucode_size, regs_size;
 
 	if (!rdev->mc_fw)
 		return -EINVAL;
@@ -160,13 +209,24 @@ int btc_mc_load_microcode(struct radeon_device *rdev)
 	switch (rdev->family) {
 	case CHIP_BARTS:
 		io_mc_regs = (u32 *)&barts_io_mc_regs;
+		ucode_size = BTC_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_TURKS:
 		io_mc_regs = (u32 *)&turks_io_mc_regs;
+		ucode_size = BTC_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_CAICOS:
 	default:
 		io_mc_regs = (u32 *)&caicos_io_mc_regs;
+		ucode_size = BTC_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
+		break;
+	case CHIP_CAYMAN:
+		io_mc_regs = (u32 *)&cayman_io_mc_regs;
+		ucode_size = CAYMAN_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
 		break;
 	}
 
@@ -184,13 +244,13 @@ int btc_mc_load_microcode(struct radeon_device *rdev)
 		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
 
 		/* load mc io regs */
-		for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) {
+		for (i = 0; i < regs_size; i++) {
 			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
 			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
 		}
 		/* load the MC ucode */
 		fw_data = (const __be32 *)rdev->mc_fw->data;
-		for (i = 0; i < BTC_MC_UCODE_SIZE; i++)
+		for (i = 0; i < ucode_size; i++)
 			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
 
 		/* put the engine back into the active state */
@@ -231,23 +291,38 @@ int ni_init_microcode(struct radeon_device *rdev)
 	case CHIP_BARTS:
 		chip_name = "BARTS";
 		rlc_chip_name = "BTC";
+		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+		mc_req_size = BTC_MC_UCODE_SIZE * 4;
 		break;
 	case CHIP_TURKS:
 		chip_name = "TURKS";
 		rlc_chip_name = "BTC";
+		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+		mc_req_size = BTC_MC_UCODE_SIZE * 4;
 		break;
 	case CHIP_CAICOS:
 		chip_name = "CAICOS";
 		rlc_chip_name = "BTC";
+		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+		mc_req_size = BTC_MC_UCODE_SIZE * 4;
+		break;
+	case CHIP_CAYMAN:
+		chip_name = "CAYMAN";
+		rlc_chip_name = "CAYMAN";
+		pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
+		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
+		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
 		break;
 	default: BUG();
 	}
 
-	pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
-	me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
-	rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
-	mc_req_size = BTC_MC_UCODE_SIZE * 4;
-
 	DRM_INFO("Loading %s Microcode\n", chip_name);
 
 	snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
@@ -314,3 +389,1204 @@ out:
 	return err;
 }
 
+/*
+ * Core functions
+ */
+static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
+					       u32 num_tile_pipes,
+					       u32 num_backends_per_asic,
+					       u32 *backend_disable_mask_per_asic,
+					       u32 num_shader_engines)
+{
+	u32 backend_map = 0;
+	u32 enabled_backends_mask = 0;
+	u32 enabled_backends_count = 0;
+	u32 num_backends_per_se;
+	u32 cur_pipe;
+	u32 swizzle_pipe[CAYMAN_MAX_PIPES];
+	u32 cur_backend = 0;
+	u32 i;
+	bool force_no_swizzle;
+
+	/* force legal values */
+	if (num_tile_pipes < 1)
+		num_tile_pipes = 1;
+	if (num_tile_pipes > rdev->config.cayman.max_tile_pipes)
+		num_tile_pipes = rdev->config.cayman.max_tile_pipes;
+	if (num_shader_engines < 1)
+		num_shader_engines = 1;
+	if (num_shader_engines > rdev->config.cayman.max_shader_engines)
+		num_shader_engines = rdev->config.cayman.max_shader_engines;
+	if (num_backends_per_asic > num_shader_engines)
+		num_backends_per_asic = num_shader_engines;
+	if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines))
+		num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines;
+
+	/* make sure we have the same number of backends per se */
+	num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines);
+	/* set up the number of backends per se */
+	num_backends_per_se = num_backends_per_asic / num_shader_engines;
+	if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) {
+		num_backends_per_se = rdev->config.cayman.max_backends_per_se;
+		num_backends_per_asic = num_backends_per_se * num_shader_engines;
+	}
+
+	/* create enable mask and count for enabled backends */
+	for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) {
+		if (((*backend_disable_mask_per_asic >> i) & 1) == 0) {
+			enabled_backends_mask |= (1 << i);
+			++enabled_backends_count;
+		}
+		if (enabled_backends_count == num_backends_per_asic)
+			break;
+	}
+
+	/* force the backends mask to match the current number of backends */
+	if (enabled_backends_count != num_backends_per_asic) {
+		u32 this_backend_enabled;
+		u32 shader_engine;
+		u32 backend_per_se;
+
+		enabled_backends_mask = 0;
+		enabled_backends_count = 0;
+		*backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK;
+		for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) {
+			/* calc the current se */
+			shader_engine = i / rdev->config.cayman.max_backends_per_se;
+			/* calc the backend per se */
+			backend_per_se = i % rdev->config.cayman.max_backends_per_se;
+			/* default to not enabled */
+			this_backend_enabled = 0;
+			if ((shader_engine < num_shader_engines) &&
+			    (backend_per_se < num_backends_per_se))
+				this_backend_enabled = 1;
+			if (this_backend_enabled) {
+				enabled_backends_mask |= (1 << i);
+				*backend_disable_mask_per_asic &= ~(1 << i);
+				++enabled_backends_count;
+			}
+		}
+	}
+
+
+	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES);
+	switch (rdev->family) {
+	case CHIP_CAYMAN:
+		force_no_swizzle = true;
+		break;
+	default:
+		force_no_swizzle = false;
+		break;
+	}
+	if (force_no_swizzle) {
+		bool last_backend_enabled = false;
+
+		force_no_swizzle = false;
+		for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) {
+			if (((enabled_backends_mask >> i) & 1) == 1) {
+				if (last_backend_enabled)
+					force_no_swizzle = true;
+				last_backend_enabled = true;
+			} else
+				last_backend_enabled = false;
+		}
+	}
+
+	switch (num_tile_pipes) {
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+		DRM_ERROR("odd number of pipes!\n");
+		break;
+	case 2:
+		swizzle_pipe[0] = 0;
+		swizzle_pipe[1] = 1;
+		break;
+	case 4:
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 1;
+			swizzle_pipe[3] = 3;
+		}
+		break;
+	case 6:
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 1;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 5;
+		}
+		break;
+	case 8:
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+			swizzle_pipe[6] = 6;
+			swizzle_pipe[7] = 7;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 6;
+			swizzle_pipe[4] = 1;
+			swizzle_pipe[5] = 3;
+			swizzle_pipe[6] = 5;
+			swizzle_pipe[7] = 7;
+		}
+		break;
+	}
+
+	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
+		while (((1 << cur_backend) & enabled_backends_mask) == 0)
+			cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS;
+
+		backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4)));
+
+		cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS;
+	}
+
+	return backend_map;
+}
+
+static void cayman_program_channel_remap(struct radeon_device *rdev)
+{
+	u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp;
+
+	tmp = RREG32(MC_SHARED_CHMAP);
+	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	default:
+		/* default mapping */
+		mc_shared_chremap = 0x00fac688;
+		break;
+	}
+
+	switch (rdev->family) {
+	case CHIP_CAYMAN:
+	default:
+		//tcp_chan_steer_lo = 0x54763210
+		tcp_chan_steer_lo = 0x76543210;
+		tcp_chan_steer_hi = 0x0000ba98;
+		break;
+	}
+
+	WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo);
+	WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi);
+	WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
+}
+
+static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev,
+					    u32 disable_mask_per_se,
+					    u32 max_disable_mask_per_se,
+					    u32 num_shader_engines)
+{
+	u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se);
+	u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se;
+
+	if (num_shader_engines == 1)
+		return disable_mask_per_asic;
+	else if (num_shader_engines == 2)
+		return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se);
+	else
+		return 0xffffffff;
+}
+
+static void cayman_gpu_init(struct radeon_device *rdev)
+{
+	u32 cc_rb_backend_disable = 0;
+	u32 cc_gc_shader_pipe_config;
+	u32 gb_addr_config = 0;
+	u32 mc_shared_chmap, mc_arb_ramcfg;
+	u32 gb_backend_map;
+	u32 cgts_tcc_disable;
+	u32 sx_debug_1;
+	u32 smx_dc_ctl0;
+	u32 gc_user_shader_pipe_config;
+	u32 gc_user_rb_backend_disable;
+	u32 cgts_user_tcc_disable;
+	u32 cgts_sm_ctrl_reg;
+	u32 hdp_host_path_cntl;
+	u32 tmp;
+	int i, j;
+
+	switch (rdev->family) {
+	case CHIP_CAYMAN:
+	default:
+		rdev->config.cayman.max_shader_engines = 2;
+		rdev->config.cayman.max_pipes_per_simd = 4;
+		rdev->config.cayman.max_tile_pipes = 8;
+		rdev->config.cayman.max_simds_per_se = 12;
+		rdev->config.cayman.max_backends_per_se = 4;
+		rdev->config.cayman.max_texture_channel_caches = 8;
+		rdev->config.cayman.max_gprs = 256;
+		rdev->config.cayman.max_threads = 256;
+		rdev->config.cayman.max_gs_threads = 32;
+		rdev->config.cayman.max_stack_entries = 512;
+		rdev->config.cayman.sx_num_of_sets = 8;
+		rdev->config.cayman.sx_max_export_size = 256;
+		rdev->config.cayman.sx_max_export_pos_size = 64;
+		rdev->config.cayman.sx_max_export_smx_size = 192;
+		rdev->config.cayman.max_hw_contexts = 8;
+		rdev->config.cayman.sq_num_cf_insts = 2;
+
+		rdev->config.cayman.sc_prim_fifo_size = 0x100;
+		rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30;
+		rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130;
+		break;
+	}
+
+	/* Initialize HDP */
+	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
+		WREG32((0x2c14 + j), 0x00000000);
+		WREG32((0x2c18 + j), 0x00000000);
+		WREG32((0x2c1c + j), 0x00000000);
+		WREG32((0x2c20 + j), 0x00000000);
+		WREG32((0x2c24 + j), 0x00000000);
+	}
+
+	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
+
+	mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
+	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
+
+	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE);
+	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG);
+	cgts_tcc_disable = RREG32(CGTS_TCC_DISABLE);
+	gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE);
+	gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG);
+	cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE);
+
+	rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines;
+	tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT;
+	rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp);
+	rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes;
+	tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT;
+	rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp);
+	tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT;
+	rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp);
+	tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT;
+	rdev->config.cayman.backend_disable_mask_per_asic =
+		cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK,
+						 rdev->config.cayman.num_shader_engines);
+	rdev->config.cayman.backend_map =
+		cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes,
+						    rdev->config.cayman.num_backends_per_se *
+						    rdev->config.cayman.num_shader_engines,
+						    &rdev->config.cayman.backend_disable_mask_per_asic,
+						    rdev->config.cayman.num_shader_engines);
+	tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT;
+	rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp);
+	tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT;
+	rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256;
+	if (rdev->config.cayman.mem_max_burst_length_bytes > 512)
+		rdev->config.cayman.mem_max_burst_length_bytes = 512;
+	tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
+	rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
+	if (rdev->config.cayman.mem_row_size_in_kb > 4)
+		rdev->config.cayman.mem_row_size_in_kb = 4;
+	/* XXX use MC settings? */
+	rdev->config.cayman.shader_engine_tile_size = 32;
+	rdev->config.cayman.num_gpus = 1;
+	rdev->config.cayman.multi_gpu_tile_size = 64;
+
+	//gb_addr_config = 0x02011003
+#if 0
+	gb_addr_config = RREG32(GB_ADDR_CONFIG);
+#else
+	gb_addr_config = 0;
+	switch (rdev->config.cayman.num_tile_pipes) {
+	case 1:
+	default:
+		gb_addr_config |= NUM_PIPES(0);
+		break;
+	case 2:
+		gb_addr_config |= NUM_PIPES(1);
+		break;
+	case 4:
+		gb_addr_config |= NUM_PIPES(2);
+		break;
+	case 8:
+		gb_addr_config |= NUM_PIPES(3);
+		break;
+	}
+
+	tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1;
+	gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp);
+	gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1);
+	tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1;
+	gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp);
+	switch (rdev->config.cayman.num_gpus) {
+	case 1:
+	default:
+		gb_addr_config |= NUM_GPUS(0);
+		break;
+	case 2:
+		gb_addr_config |= NUM_GPUS(1);
+		break;
+	case 4:
+		gb_addr_config |= NUM_GPUS(2);
+		break;
+	}
+	switch (rdev->config.cayman.multi_gpu_tile_size) {
+	case 16:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(0);
+		break;
+	case 32:
+	default:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(1);
+		break;
+	case 64:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(2);
+		break;
+	case 128:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(3);
+		break;
+	}
+	switch (rdev->config.cayman.mem_row_size_in_kb) {
+	case 1:
+	default:
+		gb_addr_config |= ROW_SIZE(0);
+		break;
+	case 2:
+		gb_addr_config |= ROW_SIZE(1);
+		break;
+	case 4:
+		gb_addr_config |= ROW_SIZE(2);
+		break;
+	}
+#endif
+
+	tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT;
+	rdev->config.cayman.num_tile_pipes = (1 << tmp);
+	tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
+	rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256;
+	tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT;
+	rdev->config.cayman.num_shader_engines = tmp + 1;
+	tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT;
+	rdev->config.cayman.num_gpus = tmp + 1;
+	tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT;
+	rdev->config.cayman.multi_gpu_tile_size = 1 << tmp;
+	tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT;
+	rdev->config.cayman.mem_row_size_in_kb = 1 << tmp;
+
+	//gb_backend_map = 0x76541032;
+#if 0
+	gb_backend_map = RREG32(GB_BACKEND_MAP);
+#else
+	gb_backend_map =
+		cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes,
+						    rdev->config.cayman.num_backends_per_se *
+						    rdev->config.cayman.num_shader_engines,
+						    &rdev->config.cayman.backend_disable_mask_per_asic,
+						    rdev->config.cayman.num_shader_engines);
+#endif
+	/* setup tiling info dword.  gb_addr_config is not adequate since it does
+	 * not have bank info, so create a custom tiling dword.
+	 * bits 3:0   num_pipes
+	 * bits 7:4   num_banks
+	 * bits 11:8  group_size
+	 * bits 15:12 row_size
+	 */
+	rdev->config.cayman.tile_config = 0;
+	switch (rdev->config.cayman.num_tile_pipes) {
+	case 1:
+	default:
+		rdev->config.cayman.tile_config |= (0 << 0);
+		break;
+	case 2:
+		rdev->config.cayman.tile_config |= (1 << 0);
+		break;
+	case 4:
+		rdev->config.cayman.tile_config |= (2 << 0);
+		break;
+	case 8:
+		rdev->config.cayman.tile_config |= (3 << 0);
+		break;
+	}
+	rdev->config.cayman.tile_config |=
+		((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+	rdev->config.cayman.tile_config |=
+		(gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
+	rdev->config.cayman.tile_config |=
+		((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
+
+	WREG32(GB_BACKEND_MAP, gb_backend_map);
+	WREG32(GB_ADDR_CONFIG, gb_addr_config);
+	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
+	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
+
+	cayman_program_channel_remap(rdev);
+
+	/* primary versions */
+	WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+
+	WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable);
+	WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable);
+
+	/* user versions */
+	WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+
+	WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable);
+	WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable);
+
+	/* reprogram the shader complex */
+	cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG);
+	for (i = 0; i < 16; i++)
+		WREG32(CGTS_SM_CTRL_REG, OVERRIDE);
+	WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg);
+
+	/* set HW defaults for 3D engine */
+	WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
+
+	sx_debug_1 = RREG32(SX_DEBUG_1);
+	sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
+	WREG32(SX_DEBUG_1, sx_debug_1);
+
+	smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
+	smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff);
+	smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets);
+	WREG32(SMX_DC_CTL0, smx_dc_ctl0);
+
+	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE);
+
+	/* need to be explicitly zero-ed */
+	WREG32(VGT_OFFCHIP_LDS_BASE, 0);
+	WREG32(SQ_LSTMP_RING_BASE, 0);
+	WREG32(SQ_HSTMP_RING_BASE, 0);
+	WREG32(SQ_ESTMP_RING_BASE, 0);
+	WREG32(SQ_GSTMP_RING_BASE, 0);
+	WREG32(SQ_VSTMP_RING_BASE, 0);
+	WREG32(SQ_PSTMP_RING_BASE, 0);
+
+	WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO);
+
+	WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) |
+					POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) |
+					SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1)));
+
+	WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.evergreen.sc_prim_fifo_size) |
+				 SC_HIZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_hiz_tile_fifo_size) |
+				 SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.evergreen.sc_earlyz_tile_fifo_size)));
+
+
+	WREG32(VGT_NUM_INSTANCES, 1);
+
+	WREG32(CP_PERFMON_CNTL, 0);
+
+	WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.evergreen.sq_num_cf_insts) |
+				  FETCH_FIFO_HIWATER(0x4) |
+				  DONE_FIFO_HIWATER(0xe0) |
+				  ALU_UPDATE_FIFO_HIWATER(0x8)));
+
+	WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4));
+	WREG32(SQ_CONFIG, (VC_ENABLE |
+			   EXPORT_SRC_C |
+			   GFX_PRIO(0) |
+			   CS1_PRIO(0) |
+			   CS2_PRIO(1)));
+	WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE);
+
+	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
+					  FORCE_EOV_MAX_REZ_CNT(255)));
+
+	WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
+	       AUTO_INVLD_EN(ES_AND_GS_AUTO));
+
+	WREG32(VGT_GS_VERTEX_REUSE, 16);
+	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
+
+	WREG32(CB_PERF_CTR0_SEL_0, 0);
+	WREG32(CB_PERF_CTR0_SEL_1, 0);
+	WREG32(CB_PERF_CTR1_SEL_0, 0);
+	WREG32(CB_PERF_CTR1_SEL_1, 0);
+	WREG32(CB_PERF_CTR2_SEL_0, 0);
+	WREG32(CB_PERF_CTR2_SEL_1, 0);
+	WREG32(CB_PERF_CTR3_SEL_0, 0);
+	WREG32(CB_PERF_CTR3_SEL_1, 0);
+
+	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
+	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
+
+	WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
+
+	udelay(50);
+}
+
+/*
+ * GART
+ */
+void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev)
+{
+	/* flush hdp cache */
+	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+
+	/* bits 0-7 are the VM contexts0-7 */
+	WREG32(VM_INVALIDATE_REQUEST, 1);
+}
+
+int cayman_pcie_gart_enable(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->gart.table.vram.robj == NULL) {
+		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
+		return -EINVAL;
+	}
+	r = radeon_gart_table_vram_pin(rdev);
+	if (r)
+		return r;
+	radeon_gart_restore(rdev);
+	/* Setup TLB control */
+	WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB |
+	       ENABLE_L1_FRAGMENT_PROCESSING |
+	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
+	       ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
+	       EFFECTIVE_L2_QUEUE_SIZE(7) |
+	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
+	WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
+	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
+	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
+	/* setup context0 */
+	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
+	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
+			(u32)(rdev->dummy_page.addr >> 12));
+	WREG32(VM_CONTEXT0_CNTL2, 0);
+	WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
+				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
+	/* disable context1-7 */
+	WREG32(VM_CONTEXT1_CNTL2, 0);
+	WREG32(VM_CONTEXT1_CNTL, 0);
+
+	cayman_pcie_gart_tlb_flush(rdev);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void cayman_pcie_gart_disable(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Disable all tables */
+	WREG32(VM_CONTEXT0_CNTL, 0);
+	WREG32(VM_CONTEXT1_CNTL, 0);
+	/* Setup TLB control */
+	WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING |
+	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
+	       EFFECTIVE_L2_QUEUE_SIZE(7) |
+	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
+	WREG32(VM_L2_CNTL2, 0);
+	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
+	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
+	if (rdev->gart.table.vram.robj) {
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
+	}
+}
+
+void cayman_pcie_gart_fini(struct radeon_device *rdev)
+{
+	cayman_pcie_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+/*
+ * CP.
+ */
+static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
+{
+	if (enable)
+		WREG32(CP_ME_CNTL, 0);
+	else {
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
+		WREG32(SCRATCH_UMSK, 0);
+	}
+}
+
+static int cayman_cp_load_microcode(struct radeon_device *rdev)
+{
+	const __be32 *fw_data;
+	int i;
+
+	if (!rdev->me_fw || !rdev->pfp_fw)
+		return -EINVAL;
+
+	cayman_cp_enable(rdev, false);
+
+	fw_data = (const __be32 *)rdev->pfp_fw->data;
+	WREG32(CP_PFP_UCODE_ADDR, 0);
+	for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++)
+		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+	WREG32(CP_PFP_UCODE_ADDR, 0);
+
+	fw_data = (const __be32 *)rdev->me_fw->data;
+	WREG32(CP_ME_RAM_WADDR, 0);
+	for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++)
+		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+
+	WREG32(CP_PFP_UCODE_ADDR, 0);
+	WREG32(CP_ME_RAM_WADDR, 0);
+	WREG32(CP_ME_RAM_RADDR, 0);
+	return 0;
+}
+
+static int cayman_cp_start(struct radeon_device *rdev)
+{
+	int r, i;
+
+	r = radeon_ring_lock(rdev, 7);
+	if (r) {
+		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+		return r;
+	}
+	radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5));
+	radeon_ring_write(rdev, 0x1);
+	radeon_ring_write(rdev, 0x0);
+	radeon_ring_write(rdev, rdev->config.cayman.max_hw_contexts - 1);
+	radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, 0);
+	radeon_ring_unlock_commit(rdev);
+
+	cayman_cp_enable(rdev, true);
+
+	r = radeon_ring_lock(rdev, cayman_default_size + 19);
+	if (r) {
+		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+		return r;
+	}
+
+	/* setup clear context state */
+	radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
+	radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
+
+	for (i = 0; i < cayman_default_size; i++)
+		radeon_ring_write(rdev, cayman_default_state[i]);
+
+	radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
+	radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE);
+
+	/* set clear context state */
+	radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0));
+	radeon_ring_write(rdev, 0);
+
+	/* SQ_VTX_BASE_VTX_LOC */
+	radeon_ring_write(rdev, 0xc0026f00);
+	radeon_ring_write(rdev, 0x00000000);
+	radeon_ring_write(rdev, 0x00000000);
+	radeon_ring_write(rdev, 0x00000000);
+
+	/* Clear consts */
+	radeon_ring_write(rdev, 0xc0036f00);
+	radeon_ring_write(rdev, 0x00000bc4);
+	radeon_ring_write(rdev, 0xffffffff);
+	radeon_ring_write(rdev, 0xffffffff);
+	radeon_ring_write(rdev, 0xffffffff);
+
+	radeon_ring_write(rdev, 0xc0026900);
+	radeon_ring_write(rdev, 0x00000316);
+	radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
+	radeon_ring_write(rdev, 0x00000010); /*  */
+
+	radeon_ring_unlock_commit(rdev);
+
+	/* XXX init other rings */
+
+	return 0;
+}
+
+static void cayman_cp_fini(struct radeon_device *rdev)
+{
+	cayman_cp_enable(rdev, false);
+	radeon_ring_fini(rdev);
+}
+
+int cayman_cp_resume(struct radeon_device *rdev)
+{
+	u32 tmp;
+	u32 rb_bufsz;
+	int r;
+
+	/* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */
+	WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP |
+				 SOFT_RESET_PA |
+				 SOFT_RESET_SH |
+				 SOFT_RESET_VGT |
+				 SOFT_RESET_SX));
+	RREG32(GRBM_SOFT_RESET);
+	mdelay(15);
+	WREG32(GRBM_SOFT_RESET, 0);
+	RREG32(GRBM_SOFT_RESET);
+
+	WREG32(CP_SEM_WAIT_TIMER, 0x4);
+
+	/* Set the write pointer delay */
+	WREG32(CP_RB_WPTR_DELAY, 0);
+
+	WREG32(CP_DEBUG, (1 << 27));
+
+	/* ring 0 - compute and gfx */
+	/* Set ring buffer size */
+	rb_bufsz = drm_order(rdev->cp.ring_size / 8);
+	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+	tmp |= BUF_SWAP_32BIT;
+#endif
+	WREG32(CP_RB0_CNTL, tmp);
+
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(CP_RB0_WPTR, 0);
+
+	/* set the wb address wether it's enabled or not */
+	WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
+	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
+
+	if (rdev->wb.enabled)
+		WREG32(SCRATCH_UMSK, 0xff);
+	else {
+		tmp |= RB_NO_UPDATE;
+		WREG32(SCRATCH_UMSK, 0);
+	}
+
+	mdelay(1);
+	WREG32(CP_RB0_CNTL, tmp);
+
+	WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8);
+
+	rdev->cp.rptr = RREG32(CP_RB0_RPTR);
+	rdev->cp.wptr = RREG32(CP_RB0_WPTR);
+
+	/* ring1  - compute only */
+	/* Set ring buffer size */
+	rb_bufsz = drm_order(rdev->cp1.ring_size / 8);
+	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+	tmp |= BUF_SWAP_32BIT;
+#endif
+	WREG32(CP_RB1_CNTL, tmp);
+
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(CP_RB1_WPTR, 0);
+
+	/* set the wb address wether it's enabled or not */
+	WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
+
+	mdelay(1);
+	WREG32(CP_RB1_CNTL, tmp);
+
+	WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8);
+
+	rdev->cp1.rptr = RREG32(CP_RB1_RPTR);
+	rdev->cp1.wptr = RREG32(CP_RB1_WPTR);
+
+	/* ring2 - compute only */
+	/* Set ring buffer size */
+	rb_bufsz = drm_order(rdev->cp2.ring_size / 8);
+	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+	tmp |= BUF_SWAP_32BIT;
+#endif
+	WREG32(CP_RB2_CNTL, tmp);
+
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(CP_RB2_WPTR, 0);
+
+	/* set the wb address wether it's enabled or not */
+	WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
+
+	mdelay(1);
+	WREG32(CP_RB2_CNTL, tmp);
+
+	WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8);
+
+	rdev->cp2.rptr = RREG32(CP_RB2_RPTR);
+	rdev->cp2.wptr = RREG32(CP_RB2_WPTR);
+
+	/* start the rings */
+	cayman_cp_start(rdev);
+	rdev->cp.ready = true;
+	rdev->cp1.ready = true;
+	rdev->cp2.ready = true;
+	/* this only test cp0 */
+	r = radeon_ring_test(rdev);
+	if (r) {
+		rdev->cp.ready = false;
+		rdev->cp1.ready = false;
+		rdev->cp2.ready = false;
+		return r;
+	}
+
+	return 0;
+}
+
+bool cayman_gpu_is_lockup(struct radeon_device *rdev)
+{
+	u32 srbm_status;
+	u32 grbm_status;
+	u32 grbm_status_se0, grbm_status_se1;
+	struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup;
+	int r;
+
+	srbm_status = RREG32(SRBM_STATUS);
+	grbm_status = RREG32(GRBM_STATUS);
+	grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
+	grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
+	if (!(grbm_status & GUI_ACTIVE)) {
+		r100_gpu_lockup_update(lockup, &rdev->cp);
+		return false;
+	}
+	/* force CP activities */
+	r = radeon_ring_lock(rdev, 2);
+	if (!r) {
+		/* PACKET2 NOP */
+		radeon_ring_write(rdev, 0x80000000);
+		radeon_ring_write(rdev, 0x80000000);
+		radeon_ring_unlock_commit(rdev);
+	}
+	/* XXX deal with CP0,1,2 */
+	rdev->cp.rptr = RREG32(CP_RB0_RPTR);
+	return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp);
+}
+
+static int cayman_gpu_soft_reset(struct radeon_device *rdev)
+{
+	struct evergreen_mc_save save;
+	u32 grbm_reset = 0;
+
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		return 0;
+
+	dev_info(rdev->dev, "GPU softreset \n");
+	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+		RREG32(GRBM_STATUS));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+		RREG32(GRBM_STATUS_SE0));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+		RREG32(GRBM_STATUS_SE1));
+	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+		RREG32(SRBM_STATUS));
+	evergreen_mc_stop(rdev, &save);
+	if (evergreen_mc_wait_for_idle(rdev)) {
+		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+	}
+	/* Disable CP parsing/prefetching */
+	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+
+	/* reset all the gfx blocks */
+	grbm_reset = (SOFT_RESET_CP |
+		      SOFT_RESET_CB |
+		      SOFT_RESET_DB |
+		      SOFT_RESET_GDS |
+		      SOFT_RESET_PA |
+		      SOFT_RESET_SC |
+		      SOFT_RESET_SPI |
+		      SOFT_RESET_SH |
+		      SOFT_RESET_SX |
+		      SOFT_RESET_TC |
+		      SOFT_RESET_TA |
+		      SOFT_RESET_VGT |
+		      SOFT_RESET_IA);
+
+	dev_info(rdev->dev, "  GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
+	WREG32(GRBM_SOFT_RESET, grbm_reset);
+	(void)RREG32(GRBM_SOFT_RESET);
+	udelay(50);
+	WREG32(GRBM_SOFT_RESET, 0);
+	(void)RREG32(GRBM_SOFT_RESET);
+	/* Wait a little for things to settle down */
+	udelay(50);
+	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+		RREG32(GRBM_STATUS));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+		RREG32(GRBM_STATUS_SE0));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+		RREG32(GRBM_STATUS_SE1));
+	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+		RREG32(SRBM_STATUS));
+	evergreen_mc_resume(rdev, &save);
+	return 0;
+}
+
+int cayman_asic_reset(struct radeon_device *rdev)
+{
+	return cayman_gpu_soft_reset(rdev);
+}
+
+static int cayman_startup(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+		r = ni_init_microcode(rdev);
+		if (r) {
+			DRM_ERROR("Failed to load firmware!\n");
+			return r;
+		}
+	}
+	r = ni_mc_load_microcode(rdev);
+	if (r) {
+		DRM_ERROR("Failed to load MC firmware!\n");
+		return r;
+	}
+
+	evergreen_mc_program(rdev);
+	r = cayman_pcie_gart_enable(rdev);
+	if (r)
+		return r;
+	cayman_gpu_init(rdev);
+
+#if 0
+	r = cayman_blit_init(rdev);
+	if (r) {
+		cayman_blit_fini(rdev);
+		rdev->asic->copy = NULL;
+		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
+	}
+#endif
+
+	/* allocate wb buffer */
+	r = radeon_wb_init(rdev);
+	if (r)
+		return r;
+
+	/* Enable IRQ */
+	r = r600_irq_init(rdev);
+	if (r) {
+		DRM_ERROR("radeon: IH init failed (%d).\n", r);
+		radeon_irq_kms_fini(rdev);
+		return r;
+	}
+	evergreen_irq_set(rdev);
+
+	r = radeon_ring_init(rdev, rdev->cp.ring_size);
+	if (r)
+		return r;
+	r = cayman_cp_load_microcode(rdev);
+	if (r)
+		return r;
+	r = cayman_cp_resume(rdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+int cayman_resume(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
+	 * posting will perform necessary task to bring back GPU into good
+	 * shape.
+	 */
+	/* post card */
+	atom_asic_init(rdev->mode_info.atom_context);
+
+	r = cayman_startup(rdev);
+	if (r) {
+		DRM_ERROR("cayman startup failed on resume\n");
+		return r;
+	}
+
+	r = r600_ib_test(rdev);
+	if (r) {
+		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		return r;
+	}
+
+	return r;
+
+}
+
+int cayman_suspend(struct radeon_device *rdev)
+{
+	/* int r; */
+
+	/* FIXME: we should wait for ring to be empty */
+	cayman_cp_enable(rdev, false);
+	rdev->cp.ready = false;
+	evergreen_irq_suspend(rdev);
+	radeon_wb_disable(rdev);
+	cayman_pcie_gart_disable(rdev);
+
+#if 0
+	/* unpin shaders bo */
+	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+	if (likely(r == 0)) {
+		radeon_bo_unpin(rdev->r600_blit.shader_obj);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	}
+#endif
+	return 0;
+}
+
+/* Plan is to move initialization in that function and use
+ * helper function so that radeon_device_init pretty much
+ * do nothing more than calling asic specific function. This
+ * should also allow to remove a bunch of callback function
+ * like vram_info.
+ */
+int cayman_init(struct radeon_device *rdev)
+{
+	int r;
+
+	/* This don't do much */
+	r = radeon_gem_init(rdev);
+	if (r)
+		return r;
+	/* Read BIOS */
+	if (!radeon_get_bios(rdev)) {
+		if (ASIC_IS_AVIVO(rdev))
+			return -EINVAL;
+	}
+	/* Must be an ATOMBIOS */
+	if (!rdev->is_atom_bios) {
+		dev_err(rdev->dev, "Expecting atombios for cayman GPU\n");
+		return -EINVAL;
+	}
+	r = radeon_atombios_init(rdev);
+	if (r)
+		return r;
+
+	/* Post card if necessary */
+	if (!radeon_card_posted(rdev)) {
+		if (!rdev->bios) {
+			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+			return -EINVAL;
+		}
+		DRM_INFO("GPU not posted. posting now...\n");
+		atom_asic_init(rdev->mode_info.atom_context);
+	}
+	/* Initialize scratch registers */
+	r600_scratch_init(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
+	/* Initialize clocks */
+	radeon_get_clock_info(rdev->ddev);
+	/* Fence driver */
+	r = radeon_fence_driver_init(rdev);
+	if (r)
+		return r;
+	/* initialize memory controller */
+	r = evergreen_mc_init(rdev);
+	if (r)
+		return r;
+	/* Memory manager */
+	r = radeon_bo_init(rdev);
+	if (r)
+		return r;
+
+	r = radeon_irq_kms_init(rdev);
+	if (r)
+		return r;
+
+	rdev->cp.ring_obj = NULL;
+	r600_ring_init(rdev, 1024 * 1024);
+
+	rdev->ih.ring_obj = NULL;
+	r600_ih_ring_init(rdev, 64 * 1024);
+
+	r = r600_pcie_gart_init(rdev);
+	if (r)
+		return r;
+
+	rdev->accel_working = true;
+	r = cayman_startup(rdev);
+	if (r) {
+		dev_err(rdev->dev, "disabling GPU acceleration\n");
+		cayman_cp_fini(rdev);
+		r600_irq_fini(rdev);
+		radeon_wb_fini(rdev);
+		radeon_irq_kms_fini(rdev);
+		cayman_pcie_gart_fini(rdev);
+		rdev->accel_working = false;
+	}
+	if (rdev->accel_working) {
+		r = radeon_ib_pool_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
+			rdev->accel_working = false;
+		}
+		r = r600_ib_test(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed testing IB (%d).\n", r);
+			rdev->accel_working = false;
+		}
+	}
+
+	/* Don't start up if the MC ucode is missing.
+	 * The default clocks and voltages before the MC ucode
+	 * is loaded are not suffient for advanced operations.
+	 */
+	if (!rdev->mc_fw) {
+		DRM_ERROR("radeon: MC ucode required for NI+.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void cayman_fini(struct radeon_device *rdev)
+{
+	/* cayman_blit_fini(rdev); */
+	cayman_cp_fini(rdev);
+	r600_irq_fini(rdev);
+	radeon_wb_fini(rdev);
+	radeon_irq_kms_fini(rdev);
+	cayman_pcie_gart_fini(rdev);
+	radeon_gem_fini(rdev);
+	radeon_fence_driver_fini(rdev);
+	radeon_bo_fini(rdev);
+	radeon_atombios_fini(rdev);
+	kfree(rdev->bios);
+	rdev->bios = NULL;
+}
+
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h
index f7b4453..0f9a08b 100644
--- a/drivers/gpu/drm/radeon/nid.h
+++ b/drivers/gpu/drm/radeon/nid.h
@@ -24,7 +24,101 @@
 #ifndef NI_H
 #define NI_H
 
+#define CAYMAN_MAX_SH_GPRS           256
+#define CAYMAN_MAX_TEMP_GPRS         16
+#define CAYMAN_MAX_SH_THREADS        256
+#define CAYMAN_MAX_SH_STACK_ENTRIES  4096
+#define CAYMAN_MAX_FRC_EOV_CNT       16384
+#define CAYMAN_MAX_BACKENDS          8
+#define CAYMAN_MAX_BACKENDS_MASK     0xFF
+#define CAYMAN_MAX_BACKENDS_PER_SE_MASK 0xF
+#define CAYMAN_MAX_SIMDS             16
+#define CAYMAN_MAX_SIMDS_MASK        0xFFFF
+#define CAYMAN_MAX_SIMDS_PER_SE_MASK 0xFFF
+#define CAYMAN_MAX_PIPES             8
+#define CAYMAN_MAX_PIPES_MASK        0xFF
+#define CAYMAN_MAX_LDS_NUM           0xFFFF
+#define CAYMAN_MAX_TCC               16
+#define CAYMAN_MAX_TCC_MASK          0xFF
+
+#define DMIF_ADDR_CONFIG  				0xBD4
+#define	SRBM_STATUS				        0x0E50
+
+#define VM_CONTEXT0_REQUEST_RESPONSE			0x1470
+#define		REQUEST_TYPE(x)					(((x) & 0xf) << 0)
+#define		RESPONSE_TYPE_MASK				0x000000F0
+#define		RESPONSE_TYPE_SHIFT				4
+#define VM_L2_CNTL					0x1400
+#define		ENABLE_L2_CACHE					(1 << 0)
+#define		ENABLE_L2_FRAGMENT_PROCESSING			(1 << 1)
+#define		ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE		(1 << 9)
+#define		ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE	(1 << 10)
+#define		EFFECTIVE_L2_QUEUE_SIZE(x)			(((x) & 7) << 14)
+#define		CONTEXT1_IDENTITY_ACCESS_MODE(x)		(((x) & 3) << 18)
+/* CONTEXT1_IDENTITY_ACCESS_MODE
+ * 0 physical = logical
+ * 1 logical via context1 page table
+ * 2 inside identity aperture use translation, outside physical = logical
+ * 3 inside identity aperture physical = logical, outside use translation
+ */
+#define VM_L2_CNTL2					0x1404
+#define		INVALIDATE_ALL_L1_TLBS				(1 << 0)
+#define		INVALIDATE_L2_CACHE				(1 << 1)
+#define VM_L2_CNTL3					0x1408
+#define		BANK_SELECT(x)					((x) << 0)
+#define		CACHE_UPDATE_MODE(x)				((x) << 6)
+#define		L2_CACHE_BIGK_ASSOCIATIVITY			(1 << 20)
+#define		L2_CACHE_BIGK_FRAGMENT_SIZE(x)			((x) << 15)
+#define	VM_L2_STATUS					0x140C
+#define		L2_BUSY						(1 << 0)
+#define VM_CONTEXT0_CNTL				0x1410
+#define		ENABLE_CONTEXT					(1 << 0)
+#define		PAGE_TABLE_DEPTH(x)				(((x) & 3) << 1)
+#define		RANGE_PROTECTION_FAULT_ENABLE_DEFAULT		(1 << 4)
+#define VM_CONTEXT1_CNTL				0x1414
+#define VM_CONTEXT0_CNTL2				0x1430
+#define VM_CONTEXT1_CNTL2				0x1434
+#define VM_INVALIDATE_REQUEST				0x1478
+#define VM_INVALIDATE_RESPONSE				0x147c
+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR	0x1518
+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR	0x151c
+#define	VM_CONTEXT0_PAGE_TABLE_BASE_ADDR		0x153C
+#define	VM_CONTEXT0_PAGE_TABLE_START_ADDR		0x155C
+#define	VM_CONTEXT0_PAGE_TABLE_END_ADDR			0x157C
+
+#define MC_SHARED_CHMAP						0x2004
+#define		NOOFCHAN_SHIFT					12
+#define		NOOFCHAN_MASK					0x00003000
+#define MC_SHARED_CHREMAP					0x2008
+
+#define	MC_VM_SYSTEM_APERTURE_LOW_ADDR			0x2034
+#define	MC_VM_SYSTEM_APERTURE_HIGH_ADDR			0x2038
+#define	MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR		0x203C
+#define	MC_VM_MX_L1_TLB_CNTL				0x2064
+#define		ENABLE_L1_TLB					(1 << 0)
+#define		ENABLE_L1_FRAGMENT_PROCESSING			(1 << 1)
+#define		SYSTEM_ACCESS_MODE_PA_ONLY			(0 << 3)
+#define		SYSTEM_ACCESS_MODE_USE_SYS_MAP			(1 << 3)
+#define		SYSTEM_ACCESS_MODE_IN_SYS			(2 << 3)
+#define		SYSTEM_ACCESS_MODE_NOT_IN_SYS			(3 << 3)
+#define		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU	(0 << 5)
+#define		ENABLE_ADVANCED_DRIVER_MODEL			(1 << 6)
+
 #define MC_SHARED_BLACKOUT_CNTL           		0x20ac
+#define	MC_ARB_RAMCFG					0x2760
+#define		NOOFBANK_SHIFT					0
+#define		NOOFBANK_MASK					0x00000003
+#define		NOOFRANK_SHIFT					2
+#define		NOOFRANK_MASK					0x00000004
+#define		NOOFROWS_SHIFT					3
+#define		NOOFROWS_MASK					0x00000038
+#define		NOOFCOLS_SHIFT					6
+#define		NOOFCOLS_MASK					0x000000C0
+#define		CHANSIZE_SHIFT					8
+#define		CHANSIZE_MASK					0x00000100
+#define		BURSTLENGTH_SHIFT				9
+#define		BURSTLENGTH_MASK				0x00000200
+#define		CHANSIZE_OVERRIDE				(1 << 11)
 #define MC_SEQ_SUP_CNTL           			0x28c8
 #define		RUN_MASK      				(1 << 0)
 #define MC_SEQ_SUP_PGM           			0x28cc
@@ -37,5 +131,406 @@
 #define MC_SEQ_IO_DEBUG_INDEX           		0x2a44
 #define MC_SEQ_IO_DEBUG_DATA           			0x2a48
 
+#define	HDP_HOST_PATH_CNTL				0x2C00
+#define	HDP_NONSURFACE_BASE				0x2C04
+#define	HDP_NONSURFACE_INFO				0x2C08
+#define	HDP_NONSURFACE_SIZE				0x2C0C
+#define HDP_ADDR_CONFIG  				0x2F48
+
+#define	CC_SYS_RB_BACKEND_DISABLE			0x3F88
+#define	GC_USER_SYS_RB_BACKEND_DISABLE			0x3F8C
+#define	CGTS_SYS_TCC_DISABLE				0x3F90
+#define	CGTS_USER_SYS_TCC_DISABLE			0x3F94
+
+#define	CONFIG_MEMSIZE					0x5428
+
+#define HDP_MEM_COHERENCY_FLUSH_CNTL			0x5480
+#define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0
+
+#define	GRBM_CNTL					0x8000
+#define		GRBM_READ_TIMEOUT(x)				((x) << 0)
+#define	GRBM_STATUS					0x8010
+#define		CMDFIFO_AVAIL_MASK				0x0000000F
+#define		RING2_RQ_PENDING				(1 << 4)
+#define		SRBM_RQ_PENDING					(1 << 5)
+#define		RING1_RQ_PENDING				(1 << 6)
+#define		CF_RQ_PENDING					(1 << 7)
+#define		PF_RQ_PENDING					(1 << 8)
+#define		GDS_DMA_RQ_PENDING				(1 << 9)
+#define		GRBM_EE_BUSY					(1 << 10)
+#define		SX_CLEAN					(1 << 11)
+#define		DB_CLEAN					(1 << 12)
+#define		CB_CLEAN					(1 << 13)
+#define		TA_BUSY 					(1 << 14)
+#define		GDS_BUSY 					(1 << 15)
+#define		VGT_BUSY_NO_DMA					(1 << 16)
+#define		VGT_BUSY					(1 << 17)
+#define		IA_BUSY_NO_DMA					(1 << 18)
+#define		IA_BUSY						(1 << 19)
+#define		SX_BUSY 					(1 << 20)
+#define		SH_BUSY 					(1 << 21)
+#define		SPI_BUSY					(1 << 22)
+#define		SC_BUSY 					(1 << 24)
+#define		PA_BUSY 					(1 << 25)
+#define		DB_BUSY 					(1 << 26)
+#define		CP_COHERENCY_BUSY      				(1 << 28)
+#define		CP_BUSY 					(1 << 29)
+#define		CB_BUSY 					(1 << 30)
+#define		GUI_ACTIVE					(1 << 31)
+#define	GRBM_STATUS_SE0					0x8014
+#define	GRBM_STATUS_SE1					0x8018
+#define		SE_SX_CLEAN					(1 << 0)
+#define		SE_DB_CLEAN					(1 << 1)
+#define		SE_CB_CLEAN					(1 << 2)
+#define		SE_VGT_BUSY					(1 << 23)
+#define		SE_PA_BUSY					(1 << 24)
+#define		SE_TA_BUSY					(1 << 25)
+#define		SE_SX_BUSY					(1 << 26)
+#define		SE_SPI_BUSY					(1 << 27)
+#define		SE_SH_BUSY					(1 << 28)
+#define		SE_SC_BUSY					(1 << 29)
+#define		SE_DB_BUSY					(1 << 30)
+#define		SE_CB_BUSY					(1 << 31)
+#define	GRBM_SOFT_RESET					0x8020
+#define		SOFT_RESET_CP					(1 << 0)
+#define		SOFT_RESET_CB					(1 << 1)
+#define		SOFT_RESET_DB					(1 << 3)
+#define		SOFT_RESET_GDS					(1 << 4)
+#define		SOFT_RESET_PA					(1 << 5)
+#define		SOFT_RESET_SC					(1 << 6)
+#define		SOFT_RESET_SPI					(1 << 8)
+#define		SOFT_RESET_SH					(1 << 9)
+#define		SOFT_RESET_SX					(1 << 10)
+#define		SOFT_RESET_TC					(1 << 11)
+#define		SOFT_RESET_TA					(1 << 12)
+#define		SOFT_RESET_VGT					(1 << 14)
+#define		SOFT_RESET_IA					(1 << 15)
+
+#define	SCRATCH_REG0					0x8500
+#define	SCRATCH_REG1					0x8504
+#define	SCRATCH_REG2					0x8508
+#define	SCRATCH_REG3					0x850C
+#define	SCRATCH_REG4					0x8510
+#define	SCRATCH_REG5					0x8514
+#define	SCRATCH_REG6					0x8518
+#define	SCRATCH_REG7					0x851C
+#define	SCRATCH_UMSK					0x8540
+#define	SCRATCH_ADDR					0x8544
+#define	CP_SEM_WAIT_TIMER				0x85BC
+#define CP_ME_CNTL					0x86D8
+#define		CP_ME_HALT					(1 << 28)
+#define		CP_PFP_HALT					(1 << 26)
+#define	CP_RB2_RPTR					0x86f8
+#define	CP_RB1_RPTR					0x86fc
+#define	CP_RB0_RPTR					0x8700
+#define	CP_RB_WPTR_DELAY				0x8704
+#define CP_MEQ_THRESHOLDS				0x8764
+#define		MEQ1_START(x)				((x) << 0)
+#define		MEQ2_START(x)				((x) << 8)
+#define	CP_PERFMON_CNTL					0x87FC
+
+#define	VGT_CACHE_INVALIDATION				0x88C4
+#define		CACHE_INVALIDATION(x)				((x) << 0)
+#define			VC_ONLY						0
+#define			TC_ONLY						1
+#define			VC_AND_TC					2
+#define		AUTO_INVLD_EN(x)				((x) << 6)
+#define			NO_AUTO						0
+#define			ES_AUTO						1
+#define			GS_AUTO						2
+#define			ES_AND_GS_AUTO					3
+#define	VGT_GS_VERTEX_REUSE				0x88D4
+
+#define CC_GC_SHADER_PIPE_CONFIG			0x8950
+#define	GC_USER_SHADER_PIPE_CONFIG			0x8954
+#define		INACTIVE_QD_PIPES(x)				((x) << 8)
+#define		INACTIVE_QD_PIPES_MASK				0x0000FF00
+#define		INACTIVE_QD_PIPES_SHIFT				8
+#define		INACTIVE_SIMDS(x)				((x) << 16)
+#define		INACTIVE_SIMDS_MASK				0xFFFF0000
+#define		INACTIVE_SIMDS_SHIFT				16
+
+#define VGT_PRIMITIVE_TYPE                              0x8958
+#define	VGT_NUM_INSTANCES				0x8974
+#define VGT_TF_RING_SIZE				0x8988
+#define VGT_OFFCHIP_LDS_BASE				0x89b4
+
+#define	PA_SC_LINE_STIPPLE_STATE			0x8B10
+#define	PA_CL_ENHANCE					0x8A14
+#define		CLIP_VTX_REORDER_ENA				(1 << 0)
+#define		NUM_CLIP_SEQ(x)					((x) << 1)
+#define	PA_SC_FIFO_SIZE					0x8BCC
+#define		SC_PRIM_FIFO_SIZE(x)				((x) << 0)
+#define		SC_HIZ_TILE_FIFO_SIZE(x)			((x) << 12)
+#define		SC_EARLYZ_TILE_FIFO_SIZE(x)			((x) << 20)
+#define	PA_SC_FORCE_EOV_MAX_CNTS			0x8B24
+#define		FORCE_EOV_MAX_CLK_CNT(x)			((x) << 0)
+#define		FORCE_EOV_MAX_REZ_CNT(x)			((x) << 16)
+
+#define	SQ_CONFIG					0x8C00
+#define		VC_ENABLE					(1 << 0)
+#define		EXPORT_SRC_C					(1 << 1)
+#define		GFX_PRIO(x)					((x) << 2)
+#define		CS1_PRIO(x)					((x) << 4)
+#define		CS2_PRIO(x)					((x) << 6)
+#define	SQ_GPR_RESOURCE_MGMT_1				0x8C04
+#define		NUM_PS_GPRS(x)					((x) << 0)
+#define		NUM_VS_GPRS(x)					((x) << 16)
+#define		NUM_CLAUSE_TEMP_GPRS(x)				((x) << 28)
+#define SQ_ESGS_RING_SIZE				0x8c44
+#define SQ_GSVS_RING_SIZE				0x8c4c
+#define SQ_ESTMP_RING_BASE				0x8c50
+#define SQ_ESTMP_RING_SIZE				0x8c54
+#define SQ_GSTMP_RING_BASE				0x8c58
+#define SQ_GSTMP_RING_SIZE				0x8c5c
+#define SQ_VSTMP_RING_BASE				0x8c60
+#define SQ_VSTMP_RING_SIZE				0x8c64
+#define SQ_PSTMP_RING_BASE				0x8c68
+#define SQ_PSTMP_RING_SIZE				0x8c6c
+#define	SQ_MS_FIFO_SIZES				0x8CF0
+#define		CACHE_FIFO_SIZE(x)				((x) << 0)
+#define		FETCH_FIFO_HIWATER(x)				((x) << 8)
+#define		DONE_FIFO_HIWATER(x)				((x) << 16)
+#define		ALU_UPDATE_FIFO_HIWATER(x)			((x) << 24)
+#define SQ_LSTMP_RING_BASE				0x8e10
+#define SQ_LSTMP_RING_SIZE				0x8e14
+#define SQ_HSTMP_RING_BASE				0x8e18
+#define SQ_HSTMP_RING_SIZE				0x8e1c
+#define	SQ_DYN_GPR_CNTL_PS_FLUSH_REQ    		0x8D8C
+#define		DYN_GPR_ENABLE					(1 << 8)
+#define SQ_CONST_MEM_BASE				0x8df8
+
+#define	SX_EXPORT_BUFFER_SIZES				0x900C
+#define		COLOR_BUFFER_SIZE(x)				((x) << 0)
+#define		POSITION_BUFFER_SIZE(x)				((x) << 8)
+#define		SMX_BUFFER_SIZE(x)				((x) << 16)
+#define	SX_DEBUG_1					0x9058
+#define		ENABLE_NEW_SMX_ADDRESS				(1 << 16)
+
+#define	SPI_CONFIG_CNTL					0x9100
+#define		GPR_WRITE_PRIORITY(x)				((x) << 0)
+#define	SPI_CONFIG_CNTL_1				0x913C
+#define		VTX_DONE_DELAY(x)				((x) << 0)
+#define		INTERP_ONE_PRIM_PER_ROW				(1 << 4)
+#define		CRC_SIMD_ID_WADDR_DISABLE			(1 << 8)
+
+#define	CGTS_TCC_DISABLE				0x9148
+#define	CGTS_USER_TCC_DISABLE				0x914C
+#define		TCC_DISABLE_MASK				0xFFFF0000
+#define		TCC_DISABLE_SHIFT				16
+#define	CGTS_SM_CTRL_REG				0x915C
+#define		OVERRIDE				(1 << 21)
+
+#define	TA_CNTL_AUX					0x9508
+#define		DISABLE_CUBE_WRAP				(1 << 0)
+#define		DISABLE_CUBE_ANISO				(1 << 1)
+
+#define	TCP_CHAN_STEER_LO				0x960c
+#define	TCP_CHAN_STEER_HI				0x9610
+
+#define CC_RB_BACKEND_DISABLE				0x98F4
+#define		BACKEND_DISABLE(x)     			((x) << 16)
+#define GB_ADDR_CONFIG  				0x98F8
+#define		NUM_PIPES(x)				((x) << 0)
+#define		NUM_PIPES_MASK				0x00000007
+#define		NUM_PIPES_SHIFT				0
+#define		PIPE_INTERLEAVE_SIZE(x)			((x) << 4)
+#define		PIPE_INTERLEAVE_SIZE_MASK		0x00000070
+#define		PIPE_INTERLEAVE_SIZE_SHIFT		4
+#define		BANK_INTERLEAVE_SIZE(x)			((x) << 8)
+#define		NUM_SHADER_ENGINES(x)			((x) << 12)
+#define		NUM_SHADER_ENGINES_MASK			0x00003000
+#define		NUM_SHADER_ENGINES_SHIFT		12
+#define		SHADER_ENGINE_TILE_SIZE(x)     		((x) << 16)
+#define		SHADER_ENGINE_TILE_SIZE_MASK		0x00070000
+#define		SHADER_ENGINE_TILE_SIZE_SHIFT		16
+#define		NUM_GPUS(x)     			((x) << 20)
+#define		NUM_GPUS_MASK				0x00700000
+#define		NUM_GPUS_SHIFT				20
+#define		MULTI_GPU_TILE_SIZE(x)     		((x) << 24)
+#define		MULTI_GPU_TILE_SIZE_MASK		0x03000000
+#define		MULTI_GPU_TILE_SIZE_SHIFT		24
+#define		ROW_SIZE(x)             		((x) << 28)
+#define		ROW_SIZE_MASK				0x30000007
+#define		ROW_SIZE_SHIFT				28
+#define		NUM_LOWER_PIPES(x)			((x) << 30)
+#define		NUM_LOWER_PIPES_MASK			0x40000000
+#define		NUM_LOWER_PIPES_SHIFT			30
+#define GB_BACKEND_MAP  				0x98FC
+
+#define CB_PERF_CTR0_SEL_0				0x9A20
+#define CB_PERF_CTR0_SEL_1				0x9A24
+#define CB_PERF_CTR1_SEL_0				0x9A28
+#define CB_PERF_CTR1_SEL_1				0x9A2C
+#define CB_PERF_CTR2_SEL_0				0x9A30
+#define CB_PERF_CTR2_SEL_1				0x9A34
+#define CB_PERF_CTR3_SEL_0				0x9A38
+#define CB_PERF_CTR3_SEL_1				0x9A3C
+
+#define	GC_USER_RB_BACKEND_DISABLE			0x9B7C
+#define		BACKEND_DISABLE_MASK			0x00FF0000
+#define		BACKEND_DISABLE_SHIFT			16
+
+#define	SMX_DC_CTL0					0xA020
+#define		USE_HASH_FUNCTION				(1 << 0)
+#define		NUMBER_OF_SETS(x)				((x) << 1)
+#define		FLUSH_ALL_ON_EVENT				(1 << 10)
+#define		STALL_ON_EVENT					(1 << 11)
+#define	SMX_EVENT_CTL					0xA02C
+#define		ES_FLUSH_CTL(x)					((x) << 0)
+#define		GS_FLUSH_CTL(x)					((x) << 3)
+#define		ACK_FLUSH_CTL(x)				((x) << 6)
+#define		SYNC_FLUSH_CTL					(1 << 8)
+
+#define	CP_RB0_BASE					0xC100
+#define	CP_RB0_CNTL					0xC104
+#define		RB_BUFSZ(x)					((x) << 0)
+#define		RB_BLKSZ(x)					((x) << 8)
+#define		RB_NO_UPDATE					(1 << 27)
+#define		RB_RPTR_WR_ENA					(1 << 31)
+#define		BUF_SWAP_32BIT					(2 << 16)
+#define	CP_RB0_RPTR_ADDR				0xC10C
+#define	CP_RB0_RPTR_ADDR_HI				0xC110
+#define	CP_RB0_WPTR					0xC114
+#define	CP_RB1_BASE					0xC180
+#define	CP_RB1_CNTL					0xC184
+#define	CP_RB1_RPTR_ADDR				0xC188
+#define	CP_RB1_RPTR_ADDR_HI				0xC18C
+#define	CP_RB1_WPTR					0xC190
+#define	CP_RB2_BASE					0xC194
+#define	CP_RB2_CNTL					0xC198
+#define	CP_RB2_RPTR_ADDR				0xC19C
+#define	CP_RB2_RPTR_ADDR_HI				0xC1A0
+#define	CP_RB2_WPTR					0xC1A4
+#define	CP_PFP_UCODE_ADDR				0xC150
+#define	CP_PFP_UCODE_DATA				0xC154
+#define	CP_ME_RAM_RADDR					0xC158
+#define	CP_ME_RAM_WADDR					0xC15C
+#define	CP_ME_RAM_DATA					0xC160
+#define	CP_DEBUG					0xC1FC
+
+/*
+ * PM4
+ */
+#define	PACKET_TYPE0	0
+#define	PACKET_TYPE1	1
+#define	PACKET_TYPE2	2
+#define	PACKET_TYPE3	3
+
+#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
+#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
+#define CP_PACKET0_GET_REG(h) (((h) & 0xFFFF) << 2)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define PACKET0(reg, n)	((PACKET_TYPE0 << 30) |				\
+			 (((reg) >> 2) & 0xFFFF) |			\
+			 ((n) & 0x3FFF) << 16)
+#define CP_PACKET2			0x80000000
+#define		PACKET2_PAD_SHIFT		0
+#define		PACKET2_PAD_MASK		(0x3fffffff << 0)
+
+#define PACKET2(v)	(CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+
+#define PACKET3(op, n)	((PACKET_TYPE3 << 30) |				\
+			 (((op) & 0xFF) << 8) |				\
+			 ((n) & 0x3FFF) << 16)
+
+/* Packet 3 types */
+#define	PACKET3_NOP					0x10
+#define	PACKET3_SET_BASE				0x11
+#define	PACKET3_CLEAR_STATE				0x12
+#define	PACKET3_INDEX_BUFFER_SIZE			0x13
+#define	PACKET3_DEALLOC_STATE				0x14
+#define	PACKET3_DISPATCH_DIRECT				0x15
+#define	PACKET3_DISPATCH_INDIRECT			0x16
+#define	PACKET3_INDIRECT_BUFFER_END			0x17
+#define	PACKET3_SET_PREDICATION				0x20
+#define	PACKET3_REG_RMW					0x21
+#define	PACKET3_COND_EXEC				0x22
+#define	PACKET3_PRED_EXEC				0x23
+#define	PACKET3_DRAW_INDIRECT				0x24
+#define	PACKET3_DRAW_INDEX_INDIRECT			0x25
+#define	PACKET3_INDEX_BASE				0x26
+#define	PACKET3_DRAW_INDEX_2				0x27
+#define	PACKET3_CONTEXT_CONTROL				0x28
+#define	PACKET3_DRAW_INDEX_OFFSET			0x29
+#define	PACKET3_INDEX_TYPE				0x2A
+#define	PACKET3_DRAW_INDEX				0x2B
+#define	PACKET3_DRAW_INDEX_AUTO				0x2D
+#define	PACKET3_DRAW_INDEX_IMMD				0x2E
+#define	PACKET3_NUM_INSTANCES				0x2F
+#define	PACKET3_DRAW_INDEX_MULTI_AUTO			0x30
+#define	PACKET3_INDIRECT_BUFFER				0x32
+#define	PACKET3_STRMOUT_BUFFER_UPDATE			0x34
+#define	PACKET3_DRAW_INDEX_OFFSET_2			0x35
+#define	PACKET3_DRAW_INDEX_MULTI_ELEMENT		0x36
+#define	PACKET3_WRITE_DATA				0x37
+#define	PACKET3_MEM_SEMAPHORE				0x39
+#define	PACKET3_MPEG_INDEX				0x3A
+#define	PACKET3_WAIT_REG_MEM				0x3C
+#define	PACKET3_MEM_WRITE				0x3D
+#define	PACKET3_SURFACE_SYNC				0x43
+#              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
+#              define PACKET3_CB2_DEST_BASE_ENA    (1 << 8)
+#              define PACKET3_CB3_DEST_BASE_ENA    (1 << 9)
+#              define PACKET3_CB4_DEST_BASE_ENA    (1 << 10)
+#              define PACKET3_CB5_DEST_BASE_ENA    (1 << 11)
+#              define PACKET3_CB6_DEST_BASE_ENA    (1 << 12)
+#              define PACKET3_CB7_DEST_BASE_ENA    (1 << 13)
+#              define PACKET3_DB_DEST_BASE_ENA     (1 << 14)
+#              define PACKET3_CB8_DEST_BASE_ENA    (1 << 15)
+#              define PACKET3_CB9_DEST_BASE_ENA    (1 << 16)
+#              define PACKET3_CB10_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_CB11_DEST_BASE_ENA   (1 << 18)
+#              define PACKET3_FULL_CACHE_ENA       (1 << 20)
+#              define PACKET3_TC_ACTION_ENA        (1 << 23)
+#              define PACKET3_CB_ACTION_ENA        (1 << 25)
+#              define PACKET3_DB_ACTION_ENA        (1 << 26)
+#              define PACKET3_SH_ACTION_ENA        (1 << 27)
+#              define PACKET3_SX_ACTION_ENA        (1 << 28)
+#define	PACKET3_ME_INITIALIZE				0x44
+#define		PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define	PACKET3_COND_WRITE				0x45
+#define	PACKET3_EVENT_WRITE				0x46
+#define	PACKET3_EVENT_WRITE_EOP				0x47
+#define	PACKET3_EVENT_WRITE_EOS				0x48
+#define	PACKET3_PREAMBLE_CNTL				0x4A
+#              define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE     (2 << 28)
+#              define PACKET3_PREAMBLE_END_CLEAR_STATE       (3 << 28)
+#define	PACKET3_ALU_PS_CONST_BUFFER_COPY		0x4C
+#define	PACKET3_ALU_VS_CONST_BUFFER_COPY		0x4D
+#define	PACKET3_ALU_PS_CONST_UPDATE		        0x4E
+#define	PACKET3_ALU_VS_CONST_UPDATE		        0x4F
+#define	PACKET3_ONE_REG_WRITE				0x57
+#define	PACKET3_SET_CONFIG_REG				0x68
+#define		PACKET3_SET_CONFIG_REG_START			0x00008000
+#define		PACKET3_SET_CONFIG_REG_END			0x0000ac00
+#define	PACKET3_SET_CONTEXT_REG				0x69
+#define		PACKET3_SET_CONTEXT_REG_START			0x00028000
+#define		PACKET3_SET_CONTEXT_REG_END			0x00029000
+#define	PACKET3_SET_ALU_CONST				0x6A
+/* alu const buffers only; no reg file */
+#define	PACKET3_SET_BOOL_CONST				0x6B
+#define		PACKET3_SET_BOOL_CONST_START			0x0003a500
+#define		PACKET3_SET_BOOL_CONST_END			0x0003a518
+#define	PACKET3_SET_LOOP_CONST				0x6C
+#define		PACKET3_SET_LOOP_CONST_START			0x0003a200
+#define		PACKET3_SET_LOOP_CONST_END			0x0003a500
+#define	PACKET3_SET_RESOURCE				0x6D
+#define		PACKET3_SET_RESOURCE_START			0x00030000
+#define		PACKET3_SET_RESOURCE_END			0x00038000
+#define	PACKET3_SET_SAMPLER				0x6E
+#define		PACKET3_SET_SAMPLER_START			0x0003c000
+#define		PACKET3_SET_SAMPLER_END				0x0003c600
+#define	PACKET3_SET_CTL_CONST				0x6F
+#define		PACKET3_SET_CTL_CONST_START			0x0003cff0
+#define		PACKET3_SET_CTL_CONST_END			0x0003ff0c
+#define	PACKET3_SET_RESOURCE_OFFSET			0x70
+#define	PACKET3_SET_ALU_CONST_VS			0x71
+#define	PACKET3_SET_ALU_CONST_DI			0x72
+#define	PACKET3_SET_CONTEXT_REG_INDIRECT		0x73
+#define	PACKET3_SET_RESOURCE_INDIRECT			0x74
+#define	PACKET3_SET_APPEND_CNT			        0x75
+
 #endif
 
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index e372f9e..f2204cb 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1205,14 +1205,12 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
 	if (waitreloc.reg != RADEON_WAIT_UNTIL ||
 	    waitreloc.count != 0) {
 		DRM_ERROR("vline wait had illegal wait until segment\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) {
 		DRM_ERROR("vline wait had illegal wait until\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	/* jump over the NOP */
@@ -1230,8 +1228,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
 	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
 		DRM_ERROR("cannot find crtc %d\n", crtc_id);
-		r = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
@@ -1253,14 +1250,13 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
 			break;
 		default:
 			DRM_ERROR("unknown crtc reloc\n");
-			r = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 		ib[h_idx] = header;
 		ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
 	}
-out:
-	return r;
+
+	return 0;
 }
 
 /**
@@ -3621,7 +3617,7 @@ int r100_ib_test(struct radeon_device *rdev)
 	if (i < rdev->usec_timeout) {
 		DRM_INFO("ib test succeeded in %u usecs\n", i);
 	} else {
-		DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
+		DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n",
 			  scratch, tmp);
 		r = -EINVAL;
 	}
@@ -3641,13 +3637,13 @@ int r100_ib_init(struct radeon_device *rdev)
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB pool (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB pool (%d).\n", r);
 		r100_ib_fini(rdev);
 		return r;
 	}
 	r = r100_ib_test(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled testing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed testing IB (%d).\n", r);
 		r100_ib_fini(rdev);
 		return r;
 	}
@@ -3803,12 +3799,12 @@ static int r100_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 069efa8..8713731 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -1401,12 +1401,12 @@ static int r300_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c
index 0b59ed7..417fab8 100644
--- a/drivers/gpu/drm/radeon/r420.c
+++ b/drivers/gpu/drm/radeon/r420.c
@@ -260,13 +260,13 @@ static int r420_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r420_cp_errata_init(rdev);
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c
index 2ce80d9..3081d07 100644
--- a/drivers/gpu/drm/radeon/r520.c
+++ b/drivers/gpu/drm/radeon/r520.c
@@ -193,12 +193,12 @@ static int r520_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 9b3fad2..be271c4 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -47,6 +47,7 @@
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
 #define EVERGREEN_RLC_UCODE_SIZE 768
+#define CAYMAN_RLC_UCODE_SIZE 1024
 
 /* Firmware Names */
 MODULE_FIRMWARE("radeon/R600_pfp.bin");
@@ -2463,7 +2464,7 @@ int r600_resume(struct radeon_device *rdev)
 
 	r = r600_ib_test(rdev);
 	if (r) {
-		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		DRM_ERROR("radeon: failed testing IB (%d).\n", r);
 		return r;
 	}
 
@@ -2739,7 +2740,7 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev)
 
 	/* Allocate ring buffer */
 	if (rdev->ih.ring_obj == NULL) {
-		r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
+		r = radeon_bo_create(rdev, rdev->ih.ring_size,
 				     PAGE_SIZE, true,
 				     RADEON_GEM_DOMAIN_GTT,
 				     &rdev->ih.ring_obj);
@@ -2820,13 +2821,20 @@ static int r600_rlc_init(struct radeon_device *rdev)
 	WREG32(RLC_HB_CNTL, 0);
 	WREG32(RLC_HB_RPTR, 0);
 	WREG32(RLC_HB_WPTR, 0);
-	WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
-	WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
+	if (rdev->family <= CHIP_CAICOS) {
+		WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
+		WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
+	}
 	WREG32(RLC_MC_CNTL, 0);
 	WREG32(RLC_UCODE_CNTL, 0);
 
 	fw_data = (const __be32 *)rdev->rlc_fw->data;
-	if (rdev->family >= CHIP_CEDAR) {
+	if (rdev->family >= CHIP_CAYMAN) {
+		for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) {
+			WREG32(RLC_UCODE_ADDR, i);
+			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+		}
+	} else if (rdev->family >= CHIP_CEDAR) {
 		for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) {
 			WREG32(RLC_UCODE_ADDR, i);
 			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c
index b5443fe..846fae5 100644
--- a/drivers/gpu/drm/radeon/r600_audio.c
+++ b/drivers/gpu/drm/radeon/r600_audio.c
@@ -26,6 +26,7 @@
 #include "drmP.h"
 #include "radeon.h"
 #include "radeon_reg.h"
+#include "radeon_asic.h"
 #include "atom.h"
 
 #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index df68d91..9aa74c3 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -512,7 +512,7 @@ int r600_blit_init(struct radeon_device *rdev)
 	obj_size += r6xx_ps_size * 4;
 	obj_size = ALIGN(obj_size, 256);
 
-	r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				&rdev->r600_blit.shader_obj);
 	if (r) {
 		DRM_ERROR("r600 failed to allocate shader\n");
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 153095f..3324620 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -71,75 +71,167 @@ struct r600_cs_track {
 	u64			db_bo_mc;
 };
 
+#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc }
+#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc }
+#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 }
+#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc }
+#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 }
+#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc }
+#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 }
+#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc }
+
+struct gpu_formats {
+	unsigned blockwidth;
+	unsigned blockheight;
+	unsigned blocksize;
+	unsigned valid_color;
+};
+
+static const struct gpu_formats color_formats_table[] = {
+	/* 8 bit */
+	FMT_8_BIT(V_038004_COLOR_8, 1),
+	FMT_8_BIT(V_038004_COLOR_4_4, 1),
+	FMT_8_BIT(V_038004_COLOR_3_3_2, 1),
+	FMT_8_BIT(V_038004_FMT_1, 0),
+
+	/* 16-bit */
+	FMT_16_BIT(V_038004_COLOR_16, 1),
+	FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1),
+	FMT_16_BIT(V_038004_COLOR_8_8, 1),
+	FMT_16_BIT(V_038004_COLOR_5_6_5, 1),
+	FMT_16_BIT(V_038004_COLOR_6_5_5, 1),
+	FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1),
+	FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1),
+	FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1),
+
+	/* 24-bit */
+	FMT_24_BIT(V_038004_FMT_8_8_8),
+					       
+	/* 32-bit */
+	FMT_32_BIT(V_038004_COLOR_32, 1),
+	FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_16_16, 1),
+	FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_8_24, 1),
+	FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_24_8, 1),
+	FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_10_11_11, 1),
+	FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_11_11_10, 1),
+	FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1),
+	FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1),
+	FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1),
+	FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0),
+	FMT_32_BIT(V_038004_FMT_32_AS_8, 0),
+	FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0),
+
+	/* 48-bit */
+	FMT_48_BIT(V_038004_FMT_16_16_16),
+	FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT),
+
+	/* 64-bit */
+	FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1),
+	FMT_64_BIT(V_038004_COLOR_32_32, 1),
+	FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1),
+	FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1),
+	FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1),
+
+	FMT_96_BIT(V_038004_FMT_32_32_32),
+	FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT),
+
+	/* 128-bit */
+	FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1),
+	FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1),
+
+	[V_038004_FMT_GB_GR] = { 2, 1, 4, 0 },
+	[V_038004_FMT_BG_RG] = { 2, 1, 4, 0 },
+
+	/* block compressed formats */
+	[V_038004_FMT_BC1] = { 4, 4, 8, 0 },
+	[V_038004_FMT_BC2] = { 4, 4, 16, 0 },
+	[V_038004_FMT_BC3] = { 4, 4, 16, 0 },
+	[V_038004_FMT_BC4] = { 4, 4, 8, 0 },
+	[V_038004_FMT_BC5] = { 4, 4, 16, 0},
+
+};
+
+static inline bool fmt_is_valid_color(u32 format)
+{
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return false;
+	
+	if (color_formats_table[format].valid_color)
+		return true;
+
+	return false;
+}
+
+static inline bool fmt_is_valid_texture(u32 format)
+{
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return false;
+	
+	if (color_formats_table[format].blockwidth > 0)
+		return true;
+
+	return false;
+}
+
+static inline int fmt_get_blocksize(u32 format)
+{
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return 0;
+
+	return color_formats_table[format].blocksize;
+}
+
+static inline int fmt_get_nblocksx(u32 format, u32 w)
+{
+	unsigned bw;
+
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return 0;
+
+	bw = color_formats_table[format].blockwidth;
+	if (bw == 0)
+		return 0;
+
+	return (w + bw - 1) / bw;
+}
+
+static inline int fmt_get_nblocksy(u32 format, u32 h)
+{
+	unsigned bh;
+
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return 0;
+
+	bh = color_formats_table[format].blockheight;
+	if (bh == 0)
+		return 0;
+
+	return (h + bh - 1) / bh;
+}
+
 static inline int r600_bpe_from_format(u32 *bpe, u32 format)
 {
-	switch (format) {
-	case V_038004_COLOR_8:
-	case V_038004_COLOR_4_4:
-	case V_038004_COLOR_3_3_2:
-	case V_038004_FMT_1:
-		*bpe = 1;
-		break;
-	case V_038004_COLOR_16:
-	case V_038004_COLOR_16_FLOAT:
-	case V_038004_COLOR_8_8:
-	case V_038004_COLOR_5_6_5:
-	case V_038004_COLOR_6_5_5:
-	case V_038004_COLOR_1_5_5_5:
-	case V_038004_COLOR_4_4_4_4:
-	case V_038004_COLOR_5_5_5_1:
-		*bpe = 2;
-		break;
-	case V_038004_FMT_8_8_8:
-		*bpe = 3;
-		break;
-	case V_038004_COLOR_32:
-	case V_038004_COLOR_32_FLOAT:
-	case V_038004_COLOR_16_16:
-	case V_038004_COLOR_16_16_FLOAT:
-	case V_038004_COLOR_8_24:
-	case V_038004_COLOR_8_24_FLOAT:
-	case V_038004_COLOR_24_8:
-	case V_038004_COLOR_24_8_FLOAT:
-	case V_038004_COLOR_10_11_11:
-	case V_038004_COLOR_10_11_11_FLOAT:
-	case V_038004_COLOR_11_11_10:
-	case V_038004_COLOR_11_11_10_FLOAT:
-	case V_038004_COLOR_2_10_10_10:
-	case V_038004_COLOR_8_8_8_8:
-	case V_038004_COLOR_10_10_10_2:
-	case V_038004_FMT_5_9_9_9_SHAREDEXP:
-	case V_038004_FMT_32_AS_8:
-	case V_038004_FMT_32_AS_8_8:
-		*bpe = 4;
-		break;
-	case V_038004_COLOR_X24_8_32_FLOAT:
-	case V_038004_COLOR_32_32:
-	case V_038004_COLOR_32_32_FLOAT:
-	case V_038004_COLOR_16_16_16_16:
-	case V_038004_COLOR_16_16_16_16_FLOAT:
-		*bpe = 8;
-		break;
-	case V_038004_FMT_16_16_16:
-	case V_038004_FMT_16_16_16_FLOAT:
-		*bpe = 6;
-		break;
-	case V_038004_FMT_32_32_32:
-	case V_038004_FMT_32_32_32_FLOAT:
-		*bpe = 12;
-		break;
-	case V_038004_COLOR_32_32_32_32:
-	case V_038004_COLOR_32_32_32_32_FLOAT:
-		*bpe = 16;
-		break;
-	case V_038004_FMT_GB_GR:
-	case V_038004_FMT_BG_RG:
-	case V_038004_COLOR_INVALID:
-	default:
-		*bpe = 16;
-		return -EINVAL;
-	}
+ 	unsigned res;
+
+	if (format >= ARRAY_SIZE(color_formats_table))
+		goto fail;
+
+	res = color_formats_table[format].blocksize;
+	if (res == 0)
+		goto fail;
+
+	*bpe = res;
 	return 0;
+
+fail:
+	*bpe = 16;
+	return -EINVAL;
 }
 
 struct array_mode_checker {
@@ -148,7 +240,7 @@ struct array_mode_checker {
 	u32 nbanks;
 	u32 npipes;
 	u32 nsamples;
-	u32 bpe;
+	u32 blocksize;
 };
 
 /* returns alignment in pixels for pitch/height/depth and bytes for base */
@@ -162,7 +254,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value
 	u32 tile_height = 8;
 	u32 macro_tile_width = values->nbanks;
 	u32 macro_tile_height = values->npipes;
-	u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples;
+	u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples;
 	u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
 
 	switch (values->array_mode) {
@@ -174,7 +266,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value
 		*base_align = 1;
 		break;
 	case ARRAY_LINEAR_ALIGNED:
-		*pitch_align = max((u32)64, (u32)(values->group_size / values->bpe));
+		*pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize));
 		*height_align = tile_height;
 		*depth_align = 1;
 		*base_align = values->group_size;
@@ -182,7 +274,7 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value
 	case ARRAY_1D_TILED_THIN1:
 		*pitch_align = max((u32)tile_width,
 				   (u32)(values->group_size /
-					 (tile_height * values->bpe * values->nsamples)));
+					 (tile_height * values->blocksize * values->nsamples)));
 		*height_align = tile_height;
 		*depth_align = 1;
 		*base_align = values->group_size;
@@ -190,12 +282,12 @@ static inline int r600_get_array_mode_alignment(struct array_mode_checker *value
 	case ARRAY_2D_TILED_THIN1:
 		*pitch_align = max((u32)macro_tile_width,
 				  (u32)(((values->group_size / tile_height) /
-					 (values->bpe * values->nsamples)) *
+					 (values->blocksize * values->nsamples)) *
 					values->nbanks)) * tile_width;
 		*height_align = macro_tile_height * tile_height;
 		*depth_align = 1;
 		*base_align = max(macro_tile_bytes,
-				  (*pitch_align) * values->bpe * (*height_align) * values->nsamples);
+				  (*pitch_align) * values->blocksize * (*height_align) * values->nsamples);
 		break;
 	default:
 		return -EINVAL;
@@ -234,21 +326,22 @@ static void r600_cs_track_init(struct r600_cs_track *track)
 static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 {
 	struct r600_cs_track *track = p->track;
-	u32 bpe = 0, slice_tile_max, size, tmp;
+	u32 slice_tile_max, size, tmp;
 	u32 height, height_align, pitch, pitch_align, depth_align;
 	u64 base_offset, base_align;
 	struct array_mode_checker array_check;
 	volatile u32 *ib = p->ib->ptr;
 	unsigned array_mode;
-
+	u32 format;
 	if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
 		dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
 		return -EINVAL;
 	}
 	size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
-	if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
+	format = G_0280A0_FORMAT(track->cb_color_info[i]);
+	if (!fmt_is_valid_color(format)) {
 		dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
-			 __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
+			 __func__, __LINE__, format,
 			i, track->cb_color_info[i]);
 		return -EINVAL;
 	}
@@ -267,7 +360,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 	array_check.nbanks = track->nbanks;
 	array_check.npipes = track->npipes;
 	array_check.nsamples = track->nsamples;
-	array_check.bpe = bpe;
+	array_check.blocksize = fmt_get_blocksize(format);
 	if (r600_get_array_mode_alignment(&array_check,
 					  &pitch_align, &height_align, &depth_align, &base_align)) {
 		dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
@@ -311,7 +404,7 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 	}
 
 	/* check offset */
-	tmp = height * pitch * bpe;
+	tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format);
 	if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
 		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
 			/* the initial DDX does bad things with the CB size occasionally */
@@ -436,7 +529,7 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
 			array_check.nbanks = track->nbanks;
 			array_check.npipes = track->npipes;
 			array_check.nsamples = track->nsamples;
-			array_check.bpe = bpe;
+			array_check.blocksize = bpe;
 			if (r600_get_array_mode_alignment(&array_check,
 							  &pitch_align, &height_align, &depth_align, &base_align)) {
 				dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
@@ -687,33 +780,28 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
 	if (wait_reg_mem.type != PACKET_TYPE3 ||
 	    wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
 		DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
 	/* bit 4 is reg (0) or mem (1) */
 	if (wait_reg_mem_info & 0x10) {
 		DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	/* waiting for value to be equal */
 	if ((wait_reg_mem_info & 0x7) != 0x3) {
 		DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
 		DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
 		DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	/* jump over the NOP */
@@ -732,8 +820,7 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
 	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
 		DRM_ERROR("cannot find crtc %d\n", crtc_id);
-		r = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
@@ -756,14 +843,13 @@ static int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
 			break;
 		default:
 			DRM_ERROR("unknown crtc reloc\n");
-			r = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 		ib[h_idx] = header;
 		ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
 	}
-out:
-	return r;
+
+	return 0;
 }
 
 static int r600_packet0_check(struct radeon_cs_parser *p,
@@ -1113,39 +1199,61 @@ static inline int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx
 	return 0;
 }
 
-static inline unsigned minify(unsigned size, unsigned levels)
+static inline unsigned mip_minify(unsigned size, unsigned level)
 {
-	size = size >> levels;
-	if (size < 1)
-		size = 1;
-	return size;
+	unsigned val;
+
+	val = max(1U, size >> level);
+	if (level > 0)
+		val = roundup_pow_of_two(val);
+	return val;
 }
 
-static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels,
-			      unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
-			      unsigned pitch_align,
+static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
+			      unsigned w0, unsigned h0, unsigned d0, unsigned format,
+			      unsigned block_align, unsigned height_align, unsigned base_align,
 			      unsigned *l0_size, unsigned *mipmap_size)
 {
-	unsigned offset, i, level, face;
-	unsigned width, height, depth, rowstride, size;
-
-	w0 = minify(w0, 0);
-	h0 = minify(h0, 0);
-	d0 = minify(d0, 0);
+	unsigned offset, i, level;
+	unsigned width, height, depth, size;
+	unsigned blocksize;
+	unsigned nbx, nby;
+	unsigned nlevels = llevel - blevel + 1;
+
+	*l0_size = -1;
+	blocksize = fmt_get_blocksize(format);
+
+	w0 = mip_minify(w0, 0);
+	h0 = mip_minify(h0, 0);
+	d0 = mip_minify(d0, 0);
 	for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
-		width = minify(w0, i);
-		height = minify(h0, i);
-		depth = minify(d0, i);
-		for(face = 0; face < nfaces; face++) {
-			rowstride = ALIGN((width * bpe), pitch_align);
-			size = height * rowstride * depth;
-			offset += size;
-			offset = (offset + 0x1f) & ~0x1f;
-		}
+		width = mip_minify(w0, i);
+		nbx = fmt_get_nblocksx(format, width);
+
+		nbx = round_up(nbx, block_align);
+
+		height = mip_minify(h0, i);
+		nby = fmt_get_nblocksy(format, height);
+		nby = round_up(nby, height_align);
+
+		depth = mip_minify(d0, i);
+
+		size = nbx * nby * blocksize;
+		if (nfaces)
+			size *= nfaces;
+		else
+			size *= depth;
+
+		if (i == 0)
+			*l0_size = size;
+
+		if (i == 0 || i == 1)
+			offset = round_up(offset, base_align);
+
+		offset += size;
 	}
-	*l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0;
 	*mipmap_size = offset;
-	if (!nlevels)
+	if (llevel == 0)
 		*mipmap_size = *l0_size;
 	if (!blevel)
 		*mipmap_size -= *l0_size;
@@ -1169,11 +1277,13 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
 					      u32 tiling_flags)
 {
 	struct r600_cs_track *track = p->track;
-	u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
-	u32 word0, word1, l0_size, mipmap_size;
+	u32 nfaces, llevel, blevel, w0, h0, d0;
+	u32 word0, word1, l0_size, mipmap_size, word2, word3;
 	u32 height_align, pitch, pitch_align, depth_align;
+	u32 array, barray, larray;
 	u64 base_align;
 	struct array_mode_checker array_check;
+	u32 format;
 
 	/* on legacy kernel we don't perform advanced check */
 	if (p->rdev == NULL)
@@ -1199,19 +1309,25 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
 	case V_038000_SQ_TEX_DIM_3D:
 		break;
 	case V_038000_SQ_TEX_DIM_CUBEMAP:
-		nfaces = 6;
+		if (p->family >= CHIP_RV770)
+			nfaces = 8;
+		else
+			nfaces = 6;
 		break;
 	case V_038000_SQ_TEX_DIM_1D_ARRAY:
 	case V_038000_SQ_TEX_DIM_2D_ARRAY:
+		array = 1;
+		break;
 	case V_038000_SQ_TEX_DIM_2D_MSAA:
 	case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
 	default:
 		dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
 		return -EINVAL;
 	}
-	if (r600_bpe_from_format(&bpe,  G_038004_DATA_FORMAT(word1))) {
+	format = G_038004_DATA_FORMAT(word1);
+	if (!fmt_is_valid_texture(format)) {
 		dev_warn(p->dev, "%s:%d texture invalid format %d\n",
-			 __func__, __LINE__, G_038004_DATA_FORMAT(word1));
+			 __func__, __LINE__, format);
 		return -EINVAL;
 	}
 
@@ -1222,7 +1338,7 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
 	array_check.nbanks = track->nbanks;
 	array_check.npipes = track->npipes;
 	array_check.nsamples = 1;
-	array_check.bpe = bpe;
+	array_check.blocksize = fmt_get_blocksize(format);
 	if (r600_get_array_mode_alignment(&array_check,
 					  &pitch_align, &height_align, &depth_align, &base_align)) {
 		dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
@@ -1248,25 +1364,34 @@ static inline int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 i
 		return -EINVAL;
 	}
 
+	word2 = radeon_get_ib_value(p, idx + 2) << 8;
+	word3 = radeon_get_ib_value(p, idx + 3) << 8;
+
 	word0 = radeon_get_ib_value(p, idx + 4);
 	word1 = radeon_get_ib_value(p, idx + 5);
 	blevel = G_038010_BASE_LEVEL(word0);
-	nlevels = G_038014_LAST_LEVEL(word1);
-	r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe,
-			  (pitch_align * bpe),
+	llevel = G_038014_LAST_LEVEL(word1);
+	if (array == 1) {
+		barray = G_038014_BASE_ARRAY(word1);
+		larray = G_038014_LAST_ARRAY(word1);
+
+		nfaces = larray - barray + 1;
+	}
+	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format,
+			  pitch_align, height_align, base_align,
 			  &l0_size, &mipmap_size);
 	/* using get ib will give us the offset into the texture bo */
-	word0 = radeon_get_ib_value(p, idx + 2) << 8;
-	if ((l0_size + word0) > radeon_bo_size(texture)) {
+	if ((l0_size + word2) > radeon_bo_size(texture)) {
 		dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
-			w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
+			w0, h0, format, word2, l0_size, radeon_bo_size(texture));
+		dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align);
 		return -EINVAL;
 	}
 	/* using get ib will give us the offset into the mipmap bo */
-	word0 = radeon_get_ib_value(p, idx + 3) << 8;
-	if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
+	word3 = radeon_get_ib_value(p, idx + 3) << 8;
+	if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {
 		/*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
-		  w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/
+		  w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
 	}
 	return 0;
 }
@@ -1289,6 +1414,38 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
 	idx_value = radeon_get_ib_value(p, idx);
 
 	switch (pkt->opcode) {
+	case PACKET3_SET_PREDICATION:
+	{
+		int pred_op;
+		int tmp;
+		if (pkt->count != 1) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		tmp = radeon_get_ib_value(p, idx + 1);
+		pred_op = (tmp >> 16) & 0x7;
+
+		/* for the clear predicate operation */
+		if (pred_op == 0)
+			return 0;
+
+		if (pred_op > 2) {
+			DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
+			return -EINVAL;
+		}
+
+		r = r600_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+		ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);
+	}
+	break;
+
 	case PACKET3_START_3D_CMDBUF:
 		if (p->family >= CHIP_RV770 || pkt->count) {
 			DRM_ERROR("bad START_3D\n");
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index e6a58ed..50db6d6 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -26,6 +26,7 @@
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 
 /*
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
index 04bac0b..b2b944b 100644
--- a/drivers/gpu/drm/radeon/r600d.h
+++ b/drivers/gpu/drm/radeon/r600d.h
@@ -1304,6 +1304,11 @@
 #define     V_038004_FMT_16_16_16_FLOAT                0x0000002E
 #define     V_038004_FMT_32_32_32                      0x0000002F
 #define     V_038004_FMT_32_32_32_FLOAT                0x00000030
+#define     V_038004_FMT_BC1                           0x00000031
+#define     V_038004_FMT_BC2                           0x00000032
+#define     V_038004_FMT_BC3                           0x00000033
+#define     V_038004_FMT_BC4                           0x00000034
+#define     V_038004_FMT_BC5                           0x00000035
 #define R_038010_SQ_TEX_RESOURCE_WORD4_0             0x038010
 #define   S_038010_FORMAT_COMP_X(x)                    (((x) & 0x3) << 0)
 #define   G_038010_FORMAT_COMP_X(x)                    (((x) >> 0) & 0x3)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 6b34294..cfe3af1 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -258,8 +258,9 @@ struct radeon_bo {
 	int				surface_reg;
 	/* Constant after initialization */
 	struct radeon_device		*rdev;
-	struct drm_gem_object		*gobj;
+	struct drm_gem_object		gem_base;
 };
+#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
 
 struct radeon_bo_list {
 	struct ttm_validate_buffer tv;
@@ -288,6 +289,15 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
 			  uint64_t *gpu_addr);
 void radeon_gem_object_unpin(struct drm_gem_object *obj);
 
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    struct drm_mode_create_dumb *args);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+			  struct drm_device *dev,
+			  uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+			     struct drm_device *dev,
+			     uint32_t handle);
 
 /*
  * GART structures, functions & helpers
@@ -319,6 +329,7 @@ struct radeon_gart {
 	union radeon_gart_table		table;
 	struct page			**pages;
 	dma_addr_t			*pages_addr;
+	bool				*ttm_alloced;
 	bool				ready;
 };
 
@@ -331,7 +342,8 @@ void radeon_gart_fini(struct radeon_device *rdev);
 void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
 			int pages);
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
-		     int pages, struct page **pagelist);
+		     int pages, struct page **pagelist,
+		     dma_addr_t *dma_addr);
 
 
 /*
@@ -651,6 +663,8 @@ struct radeon_wb {
 
 #define RADEON_WB_SCRATCH_OFFSET 0
 #define RADEON_WB_CP_RPTR_OFFSET 1024
+#define RADEON_WB_CP1_RPTR_OFFSET 1280
+#define RADEON_WB_CP2_RPTR_OFFSET 1536
 #define R600_WB_IH_WPTR_OFFSET   2048
 #define R600_WB_EVENT_OFFSET     3072
 
@@ -1037,12 +1051,52 @@ struct evergreen_asic {
 	struct r100_gpu_lockup	lockup;
 };
 
+struct cayman_asic {
+	unsigned max_shader_engines;
+	unsigned max_pipes_per_simd;
+	unsigned max_tile_pipes;
+	unsigned max_simds_per_se;
+	unsigned max_backends_per_se;
+	unsigned max_texture_channel_caches;
+	unsigned max_gprs;
+	unsigned max_threads;
+	unsigned max_gs_threads;
+	unsigned max_stack_entries;
+	unsigned sx_num_of_sets;
+	unsigned sx_max_export_size;
+	unsigned sx_max_export_pos_size;
+	unsigned sx_max_export_smx_size;
+	unsigned max_hw_contexts;
+	unsigned sq_num_cf_insts;
+	unsigned sc_prim_fifo_size;
+	unsigned sc_hiz_tile_fifo_size;
+	unsigned sc_earlyz_tile_fifo_size;
+
+	unsigned num_shader_engines;
+	unsigned num_shader_pipes_per_simd;
+	unsigned num_tile_pipes;
+	unsigned num_simds_per_se;
+	unsigned num_backends_per_se;
+	unsigned backend_disable_mask_per_asic;
+	unsigned backend_map;
+	unsigned num_texture_channel_caches;
+	unsigned mem_max_burst_length_bytes;
+	unsigned mem_row_size_in_kb;
+	unsigned shader_engine_tile_size;
+	unsigned num_gpus;
+	unsigned multi_gpu_tile_size;
+
+	unsigned tile_config;
+	struct r100_gpu_lockup	lockup;
+};
+
 union radeon_asic_config {
 	struct r300_asic	r300;
 	struct r100_asic	r100;
 	struct r600_asic	r600;
 	struct rv770_asic	rv770;
 	struct evergreen_asic	evergreen;
+	struct cayman_asic	cayman;
 };
 
 /*
@@ -1133,6 +1187,9 @@ struct radeon_device {
 	struct radeon_mman		mman;
 	struct radeon_fence_driver	fence_drv;
 	struct radeon_cp		cp;
+	/* cayman compute rings */
+	struct radeon_cp		cp1;
+	struct radeon_cp		cp2;
 	struct radeon_ib_pool		ib_pool;
 	struct radeon_irq		irq;
 	struct radeon_asic		*asic;
@@ -1185,19 +1242,6 @@ int radeon_device_init(struct radeon_device *rdev,
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-/* r600 blit */
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
-void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
-void r600_kms_blit_copy(struct radeon_device *rdev,
-			u64 src_gpu_addr, u64 dst_gpu_addr,
-			int size_bytes);
-/* evergreen blit */
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
-			     u64 src_gpu_addr, u64 dst_gpu_addr,
-			     int size_bytes);
-
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
 	if (reg < rdev->rmmio_size)
@@ -1449,62 +1493,15 @@ extern int radeon_resume_kms(struct drm_device *dev);
 extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 
-/* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
-extern bool r600_card_posted(struct radeon_device *rdev);
-extern void r600_cp_stop(struct radeon_device *rdev);
-extern int r600_cp_start(struct radeon_device *rdev);
-extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
-extern int r600_cp_resume(struct radeon_device *rdev);
-extern void r600_cp_fini(struct radeon_device *rdev);
-extern int r600_count_pipe_bits(uint32_t val);
-extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
-extern int r600_pcie_gart_init(struct radeon_device *rdev);
-extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
-extern int r600_ib_test(struct radeon_device *rdev);
-extern int r600_ring_test(struct radeon_device *rdev);
-extern void r600_scratch_init(struct radeon_device *rdev);
-extern int r600_blit_init(struct radeon_device *rdev);
-extern void r600_blit_fini(struct radeon_device *rdev);
-extern int r600_init_microcode(struct radeon_device *rdev);
-extern int r600_asic_reset(struct radeon_device *rdev);
-/* r600 irq */
-extern int r600_irq_init(struct radeon_device *rdev);
-extern void r600_irq_fini(struct radeon_device *rdev);
-extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
-extern int r600_irq_set(struct radeon_device *rdev);
-extern void r600_irq_suspend(struct radeon_device *rdev);
-extern void r600_disable_interrupts(struct radeon_device *rdev);
-extern void r600_rlc_stop(struct radeon_device *rdev);
-/* r600 audio */
-extern int r600_audio_init(struct radeon_device *rdev);
-extern int r600_audio_tmds_index(struct drm_encoder *encoder);
-extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
-extern int r600_audio_channels(struct radeon_device *rdev);
-extern int r600_audio_bits_per_sample(struct radeon_device *rdev);
-extern int r600_audio_rate(struct radeon_device *rdev);
-extern uint8_t r600_audio_status_bits(struct radeon_device *rdev);
-extern uint8_t r600_audio_category_code(struct radeon_device *rdev);
-extern void r600_audio_schedule_polling(struct radeon_device *rdev);
-extern void r600_audio_enable_polling(struct drm_encoder *encoder);
-extern void r600_audio_disable_polling(struct drm_encoder *encoder);
-extern void r600_audio_fini(struct radeon_device *rdev);
-extern void r600_hdmi_init(struct drm_encoder *encoder);
+/*
+ * r600 functions used by radeon_encoder.c
+ */
 extern void r600_hdmi_enable(struct drm_encoder *encoder);
 extern void r600_hdmi_disable(struct drm_encoder *encoder);
 extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
-extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
-extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
-
-extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
-extern void r700_cp_stop(struct radeon_device *rdev);
-extern void r700_cp_fini(struct radeon_device *rdev);
-extern void evergreen_disable_interrupt_state(struct radeon_device *rdev);
-extern int evergreen_irq_set(struct radeon_device *rdev);
-extern int evergreen_blit_init(struct radeon_device *rdev);
-extern void evergreen_blit_fini(struct radeon_device *rdev);
 
 extern int ni_init_microcode(struct radeon_device *rdev);
-extern int btc_mc_load_microcode(struct radeon_device *rdev);
+extern int ni_mc_load_microcode(struct radeon_device *rdev);
 
 /* radeon_acpi.c */ 
 #if defined(CONFIG_ACPI) 
@@ -1513,14 +1510,6 @@ extern int radeon_acpi_init(struct radeon_device *rdev);
 static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; } 
 #endif 
 
-/* evergreen */
-struct evergreen_mc_save {
-	u32 vga_control[6];
-	u32 vga_render_control;
-	u32 vga_hdp_control;
-	u32 crtc_control[6];
-};
-
 #include "radeon_object.h"
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
index 793c5e6..eb888ee 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.c
+++ b/drivers/gpu/drm/radeon/radeon_asic.c
@@ -885,6 +885,52 @@ static struct radeon_asic btc_asic = {
 	.post_page_flip = &evergreen_post_page_flip,
 };
 
+static struct radeon_asic cayman_asic = {
+	.init = &cayman_init,
+	.fini = &cayman_fini,
+	.suspend = &cayman_suspend,
+	.resume = &cayman_resume,
+	.cp_commit = &r600_cp_commit,
+	.gpu_is_lockup = &cayman_gpu_is_lockup,
+	.asic_reset = &cayman_asic_reset,
+	.vga_set_state = &r600_vga_set_state,
+	.gart_tlb_flush = &cayman_pcie_gart_tlb_flush,
+	.gart_set_page = &rs600_gart_set_page,
+	.ring_test = &r600_ring_test,
+	.ring_ib_execute = &evergreen_ring_ib_execute,
+	.irq_set = &evergreen_irq_set,
+	.irq_process = &evergreen_irq_process,
+	.get_vblank_counter = &evergreen_get_vblank_counter,
+	.fence_ring_emit = &r600_fence_ring_emit,
+	.cs_parse = &evergreen_cs_parse,
+	.copy_blit = NULL,
+	.copy_dma = NULL,
+	.copy = NULL,
+	.get_engine_clock = &radeon_atom_get_engine_clock,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.get_memory_clock = &radeon_atom_get_memory_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = NULL,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = NULL,
+	.set_surface_reg = r600_set_surface_reg,
+	.clear_surface_reg = r600_clear_surface_reg,
+	.bandwidth_update = &evergreen_bandwidth_update,
+	.hpd_init = &evergreen_hpd_init,
+	.hpd_fini = &evergreen_hpd_fini,
+	.hpd_sense = &evergreen_hpd_sense,
+	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.gui_idle = &r600_gui_idle,
+	.pm_misc = &evergreen_pm_misc,
+	.pm_prepare = &evergreen_pm_prepare,
+	.pm_finish = &evergreen_pm_finish,
+	.pm_init_profile = &r600_pm_init_profile,
+	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &evergreen_pre_page_flip,
+	.page_flip = &evergreen_page_flip,
+	.post_page_flip = &evergreen_post_page_flip,
+};
+
 int radeon_asic_init(struct radeon_device *rdev)
 {
 	radeon_register_accessor_init(rdev);
@@ -977,6 +1023,9 @@ int radeon_asic_init(struct radeon_device *rdev)
 	case CHIP_CAICOS:
 		rdev->asic = &btc_asic;
 		break;
+	case CHIP_CAYMAN:
+		rdev->asic = &cayman_asic;
+		break;
 	default:
 		/* FIXME: not supported yet */
 		return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
index c59bd98..3d7a0d7 100644
--- a/drivers/gpu/drm/radeon/radeon_asic.h
+++ b/drivers/gpu/drm/radeon/radeon_asic.h
@@ -57,8 +57,6 @@ int r100_init(struct radeon_device *rdev);
 void r100_fini(struct radeon_device *rdev);
 int r100_suspend(struct radeon_device *rdev);
 int r100_resume(struct radeon_device *rdev);
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void r100_vga_set_state(struct radeon_device *rdev, bool state);
 bool r100_gpu_is_lockup(struct radeon_device *rdev);
 int r100_asic_reset(struct radeon_device *rdev);
@@ -164,8 +162,6 @@ extern void r300_fence_ring_emit(struct radeon_device *rdev,
 extern int r300_cs_parse(struct radeon_cs_parser *p);
 extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
 extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
-extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
-extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
 extern void r300_set_reg_safe(struct radeon_device *rdev);
@@ -208,7 +204,6 @@ void rs400_gart_adjust_size(struct radeon_device *rdev);
 void rs400_gart_disable(struct radeon_device *rdev);
 void rs400_gart_fini(struct radeon_device *rdev);
 
-
 /*
  * rs600.
  */
@@ -270,8 +265,6 @@ void rv515_fini(struct radeon_device *rdev);
 uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg);
 void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rv515_ring_start(struct radeon_device *rdev);
-uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
-void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 void rv515_bandwidth_update(struct radeon_device *rdev);
 int rv515_resume(struct radeon_device *rdev);
 int rv515_suspend(struct radeon_device *rdev);
@@ -307,14 +300,13 @@ void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 int r600_cs_parse(struct radeon_cs_parser *p);
 void r600_fence_ring_emit(struct radeon_device *rdev,
 			  struct radeon_fence *fence);
-int r600_irq_process(struct radeon_device *rdev);
-int r600_irq_set(struct radeon_device *rdev);
 bool r600_gpu_is_lockup(struct radeon_device *rdev);
 int r600_asic_reset(struct radeon_device *rdev);
 int r600_set_surface_reg(struct radeon_device *rdev, int reg,
 			 uint32_t tiling_flags, uint32_t pitch,
 			 uint32_t offset, uint32_t obj_size);
 void r600_clear_surface_reg(struct radeon_device *rdev, int reg);
+int r600_ib_test(struct radeon_device *rdev);
 void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r600_ring_test(struct radeon_device *rdev);
 int r600_copy_blit(struct radeon_device *rdev,
@@ -333,6 +325,50 @@ extern void rs780_pm_init_profile(struct radeon_device *rdev);
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int r600_get_pcie_lanes(struct radeon_device *rdev);
+bool r600_card_posted(struct radeon_device *rdev);
+void r600_cp_stop(struct radeon_device *rdev);
+int r600_cp_start(struct radeon_device *rdev);
+void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
+int r600_cp_resume(struct radeon_device *rdev);
+void r600_cp_fini(struct radeon_device *rdev);
+int r600_count_pipe_bits(uint32_t val);
+int r600_mc_wait_for_idle(struct radeon_device *rdev);
+int r600_pcie_gart_init(struct radeon_device *rdev);
+void r600_scratch_init(struct radeon_device *rdev);
+int r600_blit_init(struct radeon_device *rdev);
+void r600_blit_fini(struct radeon_device *rdev);
+int r600_init_microcode(struct radeon_device *rdev);
+/* r600 irq */
+int r600_irq_process(struct radeon_device *rdev);
+int r600_irq_init(struct radeon_device *rdev);
+void r600_irq_fini(struct radeon_device *rdev);
+void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
+int r600_irq_set(struct radeon_device *rdev);
+void r600_irq_suspend(struct radeon_device *rdev);
+void r600_disable_interrupts(struct radeon_device *rdev);
+void r600_rlc_stop(struct radeon_device *rdev);
+/* r600 audio */
+int r600_audio_init(struct radeon_device *rdev);
+int r600_audio_tmds_index(struct drm_encoder *encoder);
+void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
+int r600_audio_channels(struct radeon_device *rdev);
+int r600_audio_bits_per_sample(struct radeon_device *rdev);
+int r600_audio_rate(struct radeon_device *rdev);
+uint8_t r600_audio_status_bits(struct radeon_device *rdev);
+uint8_t r600_audio_category_code(struct radeon_device *rdev);
+void r600_audio_schedule_polling(struct radeon_device *rdev);
+void r600_audio_enable_polling(struct drm_encoder *encoder);
+void r600_audio_disable_polling(struct drm_encoder *encoder);
+void r600_audio_fini(struct radeon_device *rdev);
+void r600_hdmi_init(struct drm_encoder *encoder);
+int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
+void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
+/* r600 blit */
+int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
+void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
+void r600_kms_blit_copy(struct radeon_device *rdev,
+			u64 src_gpu_addr, u64 dst_gpu_addr,
+			int size_bytes);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -341,12 +377,21 @@ int rv770_init(struct radeon_device *rdev);
 void rv770_fini(struct radeon_device *rdev);
 int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
-extern void rv770_pm_misc(struct radeon_device *rdev);
-extern u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+void rv770_pm_misc(struct radeon_device *rdev);
+u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
+void r700_cp_stop(struct radeon_device *rdev);
+void r700_cp_fini(struct radeon_device *rdev);
 
 /*
  * evergreen
  */
+struct evergreen_mc_save {
+	u32 vga_control[6];
+	u32 vga_render_control;
+	u32 vga_hdp_control;
+	u32 crtc_control[6];
+};
 void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev);
 int evergreen_init(struct radeon_device *rdev);
 void evergreen_fini(struct radeon_device *rdev);
@@ -374,5 +419,25 @@ extern void evergreen_pm_finish(struct radeon_device *rdev);
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
+void evergreen_disable_interrupt_state(struct radeon_device *rdev);
+int evergreen_blit_init(struct radeon_device *rdev);
+void evergreen_blit_fini(struct radeon_device *rdev);
+/* evergreen blit */
+int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
+void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
+void evergreen_kms_blit_copy(struct radeon_device *rdev,
+			     u64 src_gpu_addr, u64 dst_gpu_addr,
+			     int size_bytes);
+
+/*
+ * cayman
+ */
+void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev);
+int cayman_init(struct radeon_device *rdev);
+void cayman_fini(struct radeon_device *rdev);
+int cayman_suspend(struct radeon_device *rdev);
+int cayman_resume(struct radeon_device *rdev);
+bool cayman_gpu_is_lockup(struct radeon_device *rdev);
+int cayman_asic_reset(struct radeon_device *rdev);
 
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c
index c558685..10191d9 100644
--- a/drivers/gpu/drm/radeon/radeon_benchmark.c
+++ b/drivers/gpu/drm/radeon/radeon_benchmark.c
@@ -41,7 +41,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
 
 	size = bsize;
 	n = 1024;
-	r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, sdomain, &sobj);
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
 	if (r) {
 		goto out_cleanup;
 	}
@@ -53,7 +53,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
 	if (r) {
 		goto out_cleanup;
 	}
-	r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, ddomain, &dobj);
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, &dobj);
 	if (r) {
 		goto out_cleanup;
 	}
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 22b7e3d..28c7961 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -40,6 +40,10 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector,
 				       struct drm_encoder *encoder,
 				       bool connected);
 
+extern void
+radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+			     struct drm_connector *drm_connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -972,7 +976,16 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
 			return MODE_OK;
-		else
+		else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) {
+			if (ASIC_IS_DCE3(rdev)) {
+				/* HDMI 1.3+ supports max clock of 340 Mhz */
+				if (mode->clock > 340000)
+					return MODE_CLOCK_HIGH;
+				else
+					return MODE_OK;
+			} else
+				return MODE_CLOCK_HIGH;
+		} else
 			return MODE_CLOCK_HIGH;
 	}
 	return MODE_OK;
@@ -1517,6 +1530,17 @@ radeon_add_legacy_connector(struct drm_device *dev,
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_sysfs_connector_add(connector);
+	if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
+		struct drm_encoder *drm_encoder;
+
+		list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+			struct radeon_encoder *radeon_encoder;
+
+			radeon_encoder = to_radeon_encoder(drm_encoder);
+			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
+				radeon_legacy_backlight_init(radeon_encoder, connector);
+		}
+	}
 	return;
 
 failed:
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index eb6b9ee..3d599e3 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -2113,9 +2113,9 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags)
 		break;
 	}
 
-	if (drm_device_is_agp(dev))
+	if (drm_pci_device_is_agp(dev))
 		dev_priv->flags |= RADEON_IS_AGP;
-	else if (drm_device_is_pcie(dev))
+	else if (drm_pci_device_is_pcie(dev))
 		dev_priv->flags |= RADEON_IS_PCIE;
 	else
 		dev_priv->flags |= RADEON_IS_PCI;
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 35b5eb8..8c19169 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -75,7 +75,7 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
 				return -ENOENT;
 			}
 			p->relocs_ptr[i] = &p->relocs[i];
-			p->relocs[i].robj = p->relocs[i].gobj->driver_private;
+			p->relocs[i].robj = gem_to_radeon_bo(p->relocs[i].gobj);
 			p->relocs[i].lobj.bo = p->relocs[i].robj;
 			p->relocs[i].lobj.wdomain = r->write_domain;
 			p->relocs[i].lobj.rdomain = r->read_domains;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 4954e2d..f0209be 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -85,6 +85,7 @@ static const char radeon_family_name[][16] = {
 	"BARTS",
 	"TURKS",
 	"CAICOS",
+	"CAYMAN",
 	"LAST",
 };
 
@@ -184,7 +185,7 @@ int radeon_wb_init(struct radeon_device *rdev)
 	int r;
 
 	if (rdev->wb.wb_obj == NULL) {
-		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
+		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
 				RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj);
 		if (r) {
 			dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
@@ -860,7 +861,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
 		if (rfb == NULL || rfb->obj == NULL) {
 			continue;
 		}
-		robj = rfb->obj->driver_private;
+		robj = gem_to_radeon_bo(rfb->obj);
 		/* don't unpin kernel fb objects */
 		if (!radeon_fbdev_robj_is_fb(rdev, robj)) {
 			r = radeon_bo_reserve(robj, false);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 3e7e7f9..4be5879 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -371,7 +371,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 	new_radeon_fb = to_radeon_framebuffer(fb);
 	/* schedule unpin of the old buffer */
 	obj = old_radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	work->old_rbo = rbo;
 	INIT_WORK(&work->work, radeon_unpin_work_func);
 
@@ -391,7 +391,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
 
 	/* pin the new buffer */
 	obj = new_radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 
 	DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
 			 work->old_rbo, rbo);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 275b26a..63d2de8 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -49,9 +49,10 @@
  * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
  *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
+ *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	8
+#define KMS_DRIVER_MINOR	9
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
@@ -84,6 +85,16 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc,
 extern struct drm_ioctl_desc radeon_ioctls_kms[];
 extern int radeon_max_kms_ioctl;
 int radeon_mmap(struct file *filp, struct vm_area_struct *vma);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+			  struct drm_device *dev,
+			  uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    struct drm_mode_create_dumb *args);
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+			     struct drm_device *dev,
+			     uint32_t handle);
+
 #if defined(CONFIG_DEBUG_FS)
 int radeon_debugfs_init(struct drm_minor *minor);
 void radeon_debugfs_cleanup(struct drm_minor *minor);
@@ -228,11 +239,6 @@ static struct drm_driver driver_old = {
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -322,6 +328,9 @@ static struct drm_driver kms_driver = {
 	.gem_init_object = radeon_gem_object_init,
 	.gem_free_object = radeon_gem_object_free,
 	.dma_ioctl = radeon_dma_ioctl_kms,
+	.dumb_create = radeon_mode_dumb_create,
+	.dumb_map_offset = radeon_mode_dumb_mmap,
+	.dumb_destroy = radeon_mode_dumb_destroy,
 	.fops = {
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
@@ -336,15 +345,6 @@ static struct drm_driver kms_driver = {
 #endif
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-		 .probe = radeon_pci_probe,
-		 .remove = radeon_pci_remove,
-		 .suspend = radeon_pci_suspend,
-		 .resume = radeon_pci_resume,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -354,15 +354,32 @@ static struct drm_driver kms_driver = {
 };
 
 static struct drm_driver *driver;
+static struct pci_driver *pdriver;
+
+static struct pci_driver radeon_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
+static struct pci_driver radeon_kms_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+	.probe = radeon_pci_probe,
+	.remove = radeon_pci_remove,
+	.suspend = radeon_pci_suspend,
+	.resume = radeon_pci_resume,
+};
 
 static int __init radeon_init(void)
 {
 	driver = &driver_old;
+	pdriver = &radeon_pci_driver;
 	driver->num_ioctls = radeon_max_ioctl;
 #ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && radeon_modeset == -1) {
 		DRM_INFO("VGACON disable radeon kernel modesetting.\n");
 		driver = &driver_old;
+		pdriver = &radeon_pci_driver;
 		driver->driver_features &= ~DRIVER_MODESET;
 		radeon_modeset = 0;
 	}
@@ -380,18 +397,19 @@ static int __init radeon_init(void)
 	if (radeon_modeset == 1) {
 		DRM_INFO("radeon kernel modesetting enabled.\n");
 		driver = &kms_driver;
+		pdriver = &radeon_kms_pci_driver;
 		driver->driver_features |= DRIVER_MODESET;
 		driver->num_ioctls = radeon_max_kms_ioctl;
 		radeon_register_atpx_handler();
 	}
 	/* if the vga console setting is enabled still
 	 * let modprobe override it */
-	return drm_init(driver);
+	return drm_pci_init(driver, pdriver);
 }
 
 static void __exit radeon_exit(void)
 {
-	drm_exit(driver);
+	drm_pci_exit(driver, pdriver);
 	radeon_unregister_atpx_handler();
 }
 
diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h
index 1ca55eb..6f1d9e5 100644
--- a/drivers/gpu/drm/radeon/radeon_family.h
+++ b/drivers/gpu/drm/radeon/radeon_family.h
@@ -84,6 +84,7 @@ enum radeon_family {
 	CHIP_BARTS,
 	CHIP_TURKS,
 	CHIP_CAICOS,
+	CHIP_CAYMAN,
 	CHIP_LAST,
 };
 
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index cc44bdf..0b7b486 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -64,7 +64,7 @@ static struct fb_ops radeonfb_ops = {
 };
 
 
-static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
+int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
 {
 	int aligned = width;
 	int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
@@ -90,7 +90,7 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo
 
 static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
 {
-	struct radeon_bo *rbo = gobj->driver_private;
+	struct radeon_bo *rbo = gem_to_radeon_bo(gobj);
 	int ret;
 
 	ret = radeon_bo_reserve(rbo, false);
@@ -131,7 +131,7 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
 		       aligned_size);
 		return -ENOMEM;
 	}
-	rbo = gobj->driver_private;
+	rbo = gem_to_radeon_bo(gobj);
 
 	if (fb_tiled)
 		tiling_flags = RADEON_TILING_MACRO;
@@ -205,7 +205,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 	mode_cmd.depth = sizes->surface_depth;
 
 	ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
-	rbo = gobj->driver_private;
+	rbo = gem_to_radeon_bo(gobj);
 
 	/* okay we have an object now allocate the framebuffer */
 	info = framebuffer_alloc(0, device);
@@ -406,14 +406,14 @@ int radeon_fbdev_total_size(struct radeon_device *rdev)
 	struct radeon_bo *robj;
 	int size = 0;
 
-	robj = rdev->mode_info.rfbdev->rfb.obj->driver_private;
+	robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj);
 	size += radeon_bo_size(robj);
 	return size;
 }
 
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
 {
-	if (robj == rdev->mode_info.rfbdev->rfb.obj->driver_private)
+	if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj))
 		return true;
 	return false;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c
index 171b0b2..9e59868 100644
--- a/drivers/gpu/drm/radeon/radeon_fence.c
+++ b/drivers/gpu/drm/radeon/radeon_fence.c
@@ -60,8 +60,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
 
 	trace_radeon_fence_emit(rdev->ddev, fence->seq);
 	fence->emited = true;
-	list_del(&fence->list);
-	list_add_tail(&fence->list, &rdev->fence_drv.emited);
+	list_move_tail(&fence->list, &rdev->fence_drv.emited);
 	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
 	return 0;
 }
@@ -121,8 +120,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev)
 		i = n;
 		do {
 			n = i->prev;
-			list_del(i);
-			list_add_tail(i, &rdev->fence_drv.signaled);
+			list_move_tail(i, &rdev->fence_drv.signaled);
 			fence = list_entry(i, struct radeon_fence, list);
 			fence->signaled = true;
 			i = n;
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index 6501611..f0534ef 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -78,7 +78,7 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
 	int r;
 
 	if (rdev->gart.table.vram.robj == NULL) {
-		r = radeon_bo_create(rdev, NULL, rdev->gart.table_size,
+		r = radeon_bo_create(rdev, rdev->gart.table_size,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				     &rdev->gart.table.vram.robj);
 		if (r) {
@@ -149,8 +149,9 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
 	p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 	for (i = 0; i < pages; i++, p++) {
 		if (rdev->gart.pages[p]) {
-			pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
-				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+			if (!rdev->gart.ttm_alloced[p])
+				pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p],
+				       		PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 			rdev->gart.pages[p] = NULL;
 			rdev->gart.pages_addr[p] = rdev->dummy_page.addr;
 			page_base = rdev->gart.pages_addr[p];
@@ -165,7 +166,7 @@ void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset,
 }
 
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
-		     int pages, struct page **pagelist)
+		     int pages, struct page **pagelist, dma_addr_t *dma_addr)
 {
 	unsigned t;
 	unsigned p;
@@ -180,15 +181,22 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
 	p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 
 	for (i = 0; i < pages; i++, p++) {
-		/* we need to support large memory configurations */
-		/* assume that unbind have already been call on the range */
-		rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i],
+		/* On TTM path, we only use the DMA API if TTM_PAGE_FLAG_DMA32
+		 * is requested. */
+		if (dma_addr[i] != DMA_ERROR_CODE) {
+			rdev->gart.ttm_alloced[p] = true;
+			rdev->gart.pages_addr[p] = dma_addr[i];
+		} else {
+			/* we need to support large memory configurations */
+			/* assume that unbind have already been call on the range */
+			rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i],
 							0, PAGE_SIZE,
 							PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
-			/* FIXME: failed to map page (return -ENOMEM?) */
-			radeon_gart_unbind(rdev, offset, pages);
-			return -ENOMEM;
+			if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) {
+				/* FIXME: failed to map page (return -ENOMEM?) */
+				radeon_gart_unbind(rdev, offset, pages);
+				return -ENOMEM;
+			}
 		}
 		rdev->gart.pages[p] = pagelist[i];
 		page_base = rdev->gart.pages_addr[p];
@@ -251,6 +259,12 @@ int radeon_gart_init(struct radeon_device *rdev)
 		radeon_gart_fini(rdev);
 		return -ENOMEM;
 	}
+	rdev->gart.ttm_alloced = kzalloc(sizeof(bool) *
+					 rdev->gart.num_cpu_pages, GFP_KERNEL);
+	if (rdev->gart.ttm_alloced == NULL) {
+		radeon_gart_fini(rdev);
+		return -ENOMEM;
+	}
 	/* set GART entry to point to the dummy page by default */
 	for (i = 0; i < rdev->gart.num_cpu_pages; i++) {
 		rdev->gart.pages_addr[i] = rdev->dummy_page.addr;
@@ -267,6 +281,8 @@ void radeon_gart_fini(struct radeon_device *rdev)
 	rdev->gart.ready = false;
 	kfree(rdev->gart.pages);
 	kfree(rdev->gart.pages_addr);
+	kfree(rdev->gart.ttm_alloced);
 	rdev->gart.pages = NULL;
 	rdev->gart.pages_addr = NULL;
+	rdev->gart.ttm_alloced = NULL;
 }
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c
index 1fe95df..aa1ca2d 100644
--- a/drivers/gpu/drm/radeon/radeon_gem.c
+++ b/drivers/gpu/drm/radeon/radeon_gem.c
@@ -32,21 +32,18 @@
 
 int radeon_gem_object_init(struct drm_gem_object *obj)
 {
-	/* we do nothings here */
+	BUG();
+
 	return 0;
 }
 
 void radeon_gem_object_free(struct drm_gem_object *gobj)
 {
-	struct radeon_bo *robj = gobj->driver_private;
+	struct radeon_bo *robj = gem_to_radeon_bo(gobj);
 
-	gobj->driver_private = NULL;
 	if (robj) {
 		radeon_bo_unref(&robj);
 	}
-
-	drm_gem_object_release(gobj);
-	kfree(gobj);
 }
 
 int radeon_gem_object_create(struct radeon_device *rdev, int size,
@@ -54,36 +51,34 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
 				bool discardable, bool kernel,
 				struct drm_gem_object **obj)
 {
-	struct drm_gem_object *gobj;
 	struct radeon_bo *robj;
 	int r;
 
 	*obj = NULL;
-	gobj = drm_gem_object_alloc(rdev->ddev, size);
-	if (!gobj) {
-		return -ENOMEM;
-	}
 	/* At least align on page size */
 	if (alignment < PAGE_SIZE) {
 		alignment = PAGE_SIZE;
 	}
-	r = radeon_bo_create(rdev, gobj, size, alignment, kernel, initial_domain, &robj);
+	r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, &robj);
 	if (r) {
 		if (r != -ERESTARTSYS)
 			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
 				  size, initial_domain, alignment, r);
-		drm_gem_object_unreference_unlocked(gobj);
 		return r;
 	}
-	gobj->driver_private = robj;
-	*obj = gobj;
+	*obj = &robj->gem_base;
+
+	mutex_lock(&rdev->gem.mutex);
+	list_add_tail(&robj->list, &rdev->gem.objects);
+	mutex_unlock(&rdev->gem.mutex);
+
 	return 0;
 }
 
 int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
 			  uint64_t *gpu_addr)
 {
-	struct radeon_bo *robj = obj->driver_private;
+	struct radeon_bo *robj = gem_to_radeon_bo(obj);
 	int r;
 
 	r = radeon_bo_reserve(robj, false);
@@ -96,7 +91,7 @@ int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
 
 void radeon_gem_object_unpin(struct drm_gem_object *obj)
 {
-	struct radeon_bo *robj = obj->driver_private;
+	struct radeon_bo *robj = gem_to_radeon_bo(obj);
 	int r;
 
 	r = radeon_bo_reserve(robj, false);
@@ -114,7 +109,7 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj,
 	int r;
 
 	/* FIXME: reeimplement */
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	/* work out where to validate the buffer to */
 	domain = wdomain;
 	if (!domain) {
@@ -231,7 +226,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 
 	r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
 
@@ -239,23 +234,31 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
 	return r;
 }
 
-int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *filp)
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+			  struct drm_device *dev,
+			  uint32_t handle, uint64_t *offset_p)
 {
-	struct drm_radeon_gem_mmap *args = data;
 	struct drm_gem_object *gobj;
 	struct radeon_bo *robj;
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(dev, filp, handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
-	args->addr_ptr = radeon_bo_mmap_offset(robj);
+	robj = gem_to_radeon_bo(gobj);
+	*offset_p = radeon_bo_mmap_offset(robj);
 	drm_gem_object_unreference_unlocked(gobj);
 	return 0;
 }
 
+int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp)
+{
+	struct drm_radeon_gem_mmap *args = data;
+
+	return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr);
+}
+
 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *filp)
 {
@@ -269,7 +272,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	r = radeon_bo_wait(robj, &cur_placement, true);
 	switch (cur_placement) {
 	case TTM_PL_VRAM:
@@ -299,7 +302,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	r = radeon_bo_wait(robj, NULL, false);
 	/* callback hw specific functions if any */
 	if (robj->rdev->asic->ioctl_wait_idle)
@@ -320,7 +323,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch);
 	drm_gem_object_unreference_unlocked(gobj);
 	return r;
@@ -338,7 +341,7 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
-	rbo = gobj->driver_private;
+	rbo = gem_to_radeon_bo(gobj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		goto out;
@@ -348,3 +351,40 @@ out:
 	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
+
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    struct drm_mode_create_dumb *args)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_gem_object *gobj;
+	uint32_t handle;
+	int r;
+
+	args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+	args->size = args->pitch * args->height;
+	args->size = ALIGN(args->size, PAGE_SIZE);
+
+	r = radeon_gem_object_create(rdev, args->size, 0,
+				     RADEON_GEM_DOMAIN_VRAM,
+				     false, ttm_bo_type_device,
+				     &gobj);
+	if (r)
+		return -ENOMEM;
+
+	r = drm_gem_handle_create(file_priv, gobj, &handle);
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(gobj);
+	if (r) {
+		return r;
+	}
+	args->handle = handle;
+	return 0;
+}
+
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+			     struct drm_device *dev,
+			     uint32_t handle)
+{
+	return drm_gem_handle_delete(file_priv, handle);
+}
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 8387d32..bf7d4c0 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -58,9 +58,9 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
 	dev->dev_private = (void *)rdev;
 
 	/* update BUS flag */
-	if (drm_device_is_agp(dev)) {
+	if (drm_pci_device_is_agp(dev)) {
 		flags |= RADEON_IS_AGP;
-	} else if (drm_device_is_pcie(dev)) {
+	} else if (drm_pci_device_is_pcie(dev)) {
 		flags |= RADEON_IS_PCIE;
 	} else {
 		flags |= RADEON_IS_PCI;
@@ -169,7 +169,9 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 		value = rdev->accel_working;
 		break;
 	case RADEON_INFO_TILING_CONFIG:
-		if (rdev->family >= CHIP_CEDAR)
+		if (rdev->family >= CHIP_CAYMAN)
+			value = rdev->config.cayman.tile_config;
+		else if (rdev->family >= CHIP_CEDAR)
 			value = rdev->config.evergreen.tile_config;
 		else if (rdev->family >= CHIP_RV770)
 			value = rdev->config.rv770.tile_config;
@@ -205,6 +207,20 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 		/* return clock value in KHz */
 		value = rdev->clock.spll.reference_freq * 10;
 		break;
+	case RADEON_INFO_NUM_BACKENDS:
+		if (rdev->family >= CHIP_CAYMAN)
+			value = rdev->config.cayman.max_backends_per_se *
+				rdev->config.cayman.max_shader_engines;
+		else if (rdev->family >= CHIP_CEDAR)
+			value = rdev->config.evergreen.max_backends;
+		else if (rdev->family >= CHIP_RV770)
+			value = rdev->config.rv770.max_backends;
+		else if (rdev->family >= CHIP_R600)
+			value = rdev->config.r600.max_backends;
+		else {
+			return -EINVAL;
+		}
+		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		return -EINVAL;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 78968b7..66c9af1 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -415,7 +415,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 
 	/* Pin framebuffer & get tilling informations */
 	obj = radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -521,7 +521,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
 
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
-		rbo = radeon_fb->obj->driver_private;
+		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r != 0))
 			return r;
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 59f834b..5b54268 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -28,6 +28,10 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 #include "atom.h"
+#include <linux/backlight.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 {
@@ -39,7 +43,7 @@ static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 	radeon_encoder->active_device = 0;
 }
 
-static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -47,15 +51,23 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
 	int panel_pwr_delay = 2000;
 	bool is_mac = false;
+	uint8_t backlight_level;
 	DRM_DEBUG_KMS("\n");
 
+	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
 	if (radeon_encoder->enc_priv) {
 		if (rdev->is_atom_bios) {
 			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		} else {
 			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		}
 	}
 
@@ -82,11 +94,13 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 		lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
 		WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
 
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
-		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON);
+		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS |
+				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
+				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
+				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
 		if (is_mac)
 			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
-		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		break;
@@ -95,7 +109,6 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_OFF:
 		pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
 		WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb);
-		lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
 		lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
 		if (is_mac) {
 			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
@@ -119,6 +132,25 @@ static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
 
 }
 
+static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DRM_DEBUG("\n");
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		}
+	}
+
+	radeon_legacy_lvds_update(encoder, mode);
+}
+
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
@@ -237,9 +269,222 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
 	.disable = radeon_legacy_encoder_disable,
 };
 
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+
+#define MAX_RADEON_LEVEL 0xFF
+
+struct radeon_backlight_privdata {
+	struct radeon_encoder *encoder;
+	uint8_t negative;
+};
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	uint8_t level;
+
+	/* Convert brightness to hardware level */
+	if (bd->props.brightness < 0)
+		level = 0;
+	else if (bd->props.brightness > MAX_RADEON_LEVEL)
+		level = MAX_RADEON_LEVEL;
+	else
+		level = bd->props.brightness;
+
+	if (pdata->negative)
+		level = MAX_RADEON_LEVEL - level;
+
+	return level;
+}
+
+static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		}
+	}
+
+	if (bd->props.brightness > 0)
+		radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
+	else
+		radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
+
+	return 0;
+}
+
+static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint8_t backlight_level;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
+}
+
+static const struct backlight_ops radeon_backlight_ops = {
+	.get_brightness = radeon_legacy_backlight_get_brightness,
+	.update_status	= radeon_legacy_backlight_update_status,
+};
+
+void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+				  struct drm_connector *drm_connector)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	struct radeon_backlight_privdata *pdata;
+	uint8_t backlight_level;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
+	if (!pdata) {
+		DRM_ERROR("Memory allocation failed\n");
+		goto error;
+	}
+
+	props.max_brightness = MAX_RADEON_LEVEL;
+	props.type = BACKLIGHT_RAW;
+	bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+				       pdata, &radeon_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		DRM_ERROR("Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->encoder = radeon_encoder;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	/* First, try to detect backlight level sense based on the assumption
+	 * that firmware set it up at full brightness
+	 */
+	if (backlight_level == 0)
+		pdata->negative = true;
+	else if (backlight_level == 0xff)
+		pdata->negative = false;
+	else {
+		/* XXX hack... maybe some day we can figure out in what direction
+		 * backlight should work on a given panel?
+		 */
+		pdata->negative = (rdev->family != CHIP_RV200 &&
+				   rdev->family != CHIP_RV250 &&
+				   rdev->family != CHIP_RV280 &&
+				   rdev->family != CHIP_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+		pdata->negative = (pdata->negative ||
+				   of_machine_is_compatible("PowerBook4,3") ||
+				   of_machine_is_compatible("PowerBook6,3") ||
+				   of_machine_is_compatible("PowerBook6,5"));
+#endif
+	}
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	}
+
+	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	DRM_INFO("radeon legacy LVDS backlight initialized\n");
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd = NULL;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	}
+
+	if (bd) {
+		struct radeon_legacy_backlight_privdata *pdata;
+
+		pdata = bl_get_data(bd);
+		backlight_device_unregister(bd);
+		kfree(pdata);
+
+		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
+	}
+}
+
+#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
+{
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
+{
+}
+
+#endif
+
+
+static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->enc_priv) {
+		radeon_legacy_backlight_exit(radeon_encoder);
+		kfree(radeon_encoder->enc_priv);
+	}
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
 
 static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
-	.destroy = radeon_enc_destroy,
+	.destroy = radeon_lvds_enc_destroy,
 };
 
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index a670caa..e458281 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -302,6 +302,9 @@ struct radeon_encoder_lvds {
 	uint32_t lvds_gen_cntl;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int      dpms_mode;
+	uint8_t  backlight_level;
 };
 
 struct radeon_encoder_tv_dac {
@@ -355,6 +358,9 @@ struct radeon_encoder_atom_dig {
 	uint32_t lcd_ss_id;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int dpms_mode;
+	uint8_t backlight_level;
 };
 
 struct radeon_encoder_atom_dac {
@@ -676,4 +682,5 @@ void radeon_fb_output_poll_changed(struct radeon_device *rdev);
 
 void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
 
+int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
 #endif
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 7d6b8e8..976c3b1 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -55,6 +55,7 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
 	list_del_init(&bo->list);
 	mutex_unlock(&bo->rdev->gem.mutex);
 	radeon_bo_clear_surface_reg(bo);
+	drm_gem_object_release(&bo->gem_base);
 	kfree(bo);
 }
 
@@ -86,7 +87,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
 	rbo->placement.num_busy_placement = c;
 }
 
-int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
+int radeon_bo_create(struct radeon_device *rdev,
 		     unsigned long size, int byte_align, bool kernel, u32 domain,
 		     struct radeon_bo **bo_ptr)
 {
@@ -96,6 +97,8 @@ int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
 	unsigned long max_size = 0;
 	int r;
 
+	size = ALIGN(size, PAGE_SIZE);
+
 	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
 		rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
 	}
@@ -118,8 +121,13 @@ retry:
 	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
 	if (bo == NULL)
 		return -ENOMEM;
+	r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size);
+	if (unlikely(r)) {
+		kfree(bo);
+		return r;
+	}
 	bo->rdev = rdev;
-	bo->gobj = gobj;
+	bo->gem_base.driver_private = NULL;
 	bo->surface_reg = -1;
 	INIT_LIST_HEAD(&bo->list);
 	radeon_ttm_placement_from_domain(bo, domain);
@@ -142,12 +150,9 @@ retry:
 		return r;
 	}
 	*bo_ptr = bo;
-	if (gobj) {
-		mutex_lock(&bo->rdev->gem.mutex);
-		list_add_tail(&bo->list, &rdev->gem.objects);
-		mutex_unlock(&bo->rdev->gem.mutex);
-	}
+
 	trace_radeon_bo_create(bo);
+
 	return 0;
 }
 
@@ -260,7 +265,6 @@ int radeon_bo_evict_vram(struct radeon_device *rdev)
 void radeon_bo_force_delete(struct radeon_device *rdev)
 {
 	struct radeon_bo *bo, *n;
-	struct drm_gem_object *gobj;
 
 	if (list_empty(&rdev->gem.objects)) {
 		return;
@@ -268,16 +272,14 @@ void radeon_bo_force_delete(struct radeon_device *rdev)
 	dev_err(rdev->dev, "Userspace still has active objects !\n");
 	list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
 		mutex_lock(&rdev->ddev->struct_mutex);
-		gobj = bo->gobj;
 		dev_err(rdev->dev, "%p %p %lu %lu force free\n",
-			gobj, bo, (unsigned long)gobj->size,
-			*((unsigned long *)&gobj->refcount));
+			&bo->gem_base, bo, (unsigned long)bo->gem_base.size,
+			*((unsigned long *)&bo->gem_base.refcount));
 		mutex_lock(&bo->rdev->gem.mutex);
 		list_del_init(&bo->list);
 		mutex_unlock(&bo->rdev->gem.mutex);
-		radeon_bo_unref(&bo);
-		gobj->driver_private = NULL;
-		drm_gem_object_unreference(gobj);
+		/* this should unref the ttm bo */
+		drm_gem_object_unreference(&bo->gem_base);
 		mutex_unlock(&rdev->ddev->struct_mutex);
 	}
 }
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index 22d4c23..7f8e778 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -137,10 +137,9 @@ static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
 }
 
 extern int radeon_bo_create(struct radeon_device *rdev,
-			    struct drm_gem_object *gobj, unsigned long size,
-			    int byte_align,
-			    bool kernel, u32 domain,
-			    struct radeon_bo **bo_ptr);
+				unsigned long size, int byte_align,
+				bool kernel, u32 domain,
+				struct radeon_bo **bo_ptr);
 extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
 extern void radeon_bo_kunmap(struct radeon_bo *bo);
 extern void radeon_bo_unref(struct radeon_bo **bo);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 06e7982..bbc9cd8 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -151,7 +151,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
 	/* 64 dwords should be enough for fence too */
 	r = radeon_ring_lock(rdev, 64);
 	if (r) {
-		DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
+		DRM_ERROR("radeon: scheduling IB failed (%d).\n", r);
 		return r;
 	}
 	radeon_ring_ib_execute(rdev, ib);
@@ -175,7 +175,7 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
 		return 0;
 	INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
 	/* Allocate 1M object buffer */
-	r = radeon_bo_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
+	r = radeon_bo_create(rdev, RADEON_IB_POOL_SIZE*64*1024,
 			     PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT,
 			     &rdev->ib_pool.robj);
 	if (r) {
@@ -332,7 +332,7 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
 	rdev->cp.ring_size = ring_size;
 	/* Allocate ring buffer */
 	if (rdev->cp.ring_obj == NULL) {
-		r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, PAGE_SIZE, true,
+		r = radeon_bo_create(rdev, rdev->cp.ring_size, PAGE_SIZE, true,
 					RADEON_GEM_DOMAIN_GTT,
 					&rdev->cp.ring_obj);
 		if (r) {
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index 5b44f65..dee4a0c 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -52,7 +52,7 @@ void radeon_test_moves(struct radeon_device *rdev)
 		goto out_cleanup;
 	}
 
-	r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				&vram_obj);
 	if (r) {
 		DRM_ERROR("Failed to create VRAM object\n");
@@ -71,7 +71,7 @@ void radeon_test_moves(struct radeon_device *rdev)
 		void **gtt_start, **gtt_end;
 		void **vram_start, **vram_end;
 
-		r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true,
+		r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
 					 RADEON_GEM_DOMAIN_GTT, gtt_obj + i);
 		if (r) {
 			DRM_ERROR("Failed to create GTT object %d\n", i);
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 8389b4c..60125dd 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -529,7 +529,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
 		DRM_ERROR("Failed initializing VRAM heap.\n");
 		return r;
 	}
-	r = radeon_bo_create(rdev, NULL, 256 * 1024, PAGE_SIZE, true,
+	r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true,
 				RADEON_GEM_DOMAIN_VRAM,
 				&rdev->stollen_vga_memory);
 	if (r) {
@@ -661,6 +661,7 @@ struct radeon_ttm_backend {
 	unsigned long			num_pages;
 	struct page			**pages;
 	struct page			*dummy_read_page;
+	dma_addr_t			*dma_addrs;
 	bool				populated;
 	bool				bound;
 	unsigned			offset;
@@ -669,12 +670,14 @@ struct radeon_ttm_backend {
 static int radeon_ttm_backend_populate(struct ttm_backend *backend,
 				       unsigned long num_pages,
 				       struct page **pages,
-				       struct page *dummy_read_page)
+				       struct page *dummy_read_page,
+				       dma_addr_t *dma_addrs)
 {
 	struct radeon_ttm_backend *gtt;
 
 	gtt = container_of(backend, struct radeon_ttm_backend, backend);
 	gtt->pages = pages;
+	gtt->dma_addrs = dma_addrs;
 	gtt->num_pages = num_pages;
 	gtt->dummy_read_page = dummy_read_page;
 	gtt->populated = true;
@@ -687,6 +690,7 @@ static void radeon_ttm_backend_clear(struct ttm_backend *backend)
 
 	gtt = container_of(backend, struct radeon_ttm_backend, backend);
 	gtt->pages = NULL;
+	gtt->dma_addrs = NULL;
 	gtt->num_pages = 0;
 	gtt->dummy_read_page = NULL;
 	gtt->populated = false;
@@ -707,7 +711,7 @@ static int radeon_ttm_backend_bind(struct ttm_backend *backend,
 		     gtt->num_pages, bo_mem, backend);
 	}
 	r = radeon_gart_bind(gtt->rdev, gtt->offset,
-			     gtt->num_pages, gtt->pages);
+			     gtt->num_pages, gtt->pages, gtt->dma_addrs);
 	if (r) {
 		DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
 			  gtt->num_pages, gtt->offset);
diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman
new file mode 100644
index 0000000..6334f8a
--- /dev/null
+++ b/drivers/gpu/drm/radeon/reg_srcs/cayman
@@ -0,0 +1,619 @@
+cayman 0x9400
+0x0000802C GRBM_GFX_INDEX
+0x000088B0 VGT_VTX_VECT_EJECT_REG
+0x000088C4 VGT_CACHE_INVALIDATION
+0x000088D4 VGT_GS_VERTEX_REUSE
+0x00008958 VGT_PRIMITIVE_TYPE
+0x0000895C VGT_INDEX_TYPE
+0x00008970 VGT_NUM_INDICES
+0x00008974 VGT_NUM_INSTANCES
+0x00008990 VGT_COMPUTE_DIM_X
+0x00008994 VGT_COMPUTE_DIM_Y
+0x00008998 VGT_COMPUTE_DIM_Z
+0x0000899C VGT_COMPUTE_START_X
+0x000089A0 VGT_COMPUTE_START_Y
+0x000089A4 VGT_COMPUTE_START_Z
+0x000089A8 VGT_COMPUTE_INDEX
+0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
+0x000089B0 VGT_HS_OFFCHIP_PARAM
+0x00008A14 PA_CL_ENHANCE
+0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008B10 PA_SC_LINE_STIPPLE_STATE
+0x00008BF0 PA_SC_ENHANCE
+0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
+0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN
+0x00008C00 SQ_CONFIG
+0x00008C04 SQ_GPR_RESOURCE_MGMT_1
+0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1
+0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2
+0x00008DF8 SQ_CONST_MEM_BASE
+0x00008E20 SQ_STATIC_THREAD_MGMT_1
+0x00008E24 SQ_STATIC_THREAD_MGMT_2
+0x00008E28 SQ_STATIC_THREAD_MGMT_3
+0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009100 SPI_CONFIG_CNTL
+0x0000913C SPI_CONFIG_CNTL_1
+0x00009830 DB_DEBUG
+0x00009834 DB_DEBUG2
+0x00009838 DB_DEBUG3
+0x0000983C DB_DEBUG4
+0x00009854 DB_WATERMARKS
+0x0000A400 TD_PS_BORDER_COLOR_INDEX
+0x0000A404 TD_PS_BORDER_COLOR_RED
+0x0000A408 TD_PS_BORDER_COLOR_GREEN
+0x0000A40C TD_PS_BORDER_COLOR_BLUE
+0x0000A410 TD_PS_BORDER_COLOR_ALPHA
+0x0000A414 TD_VS_BORDER_COLOR_INDEX
+0x0000A418 TD_VS_BORDER_COLOR_RED
+0x0000A41C TD_VS_BORDER_COLOR_GREEN
+0x0000A420 TD_VS_BORDER_COLOR_BLUE
+0x0000A424 TD_VS_BORDER_COLOR_ALPHA
+0x0000A428 TD_GS_BORDER_COLOR_INDEX
+0x0000A42C TD_GS_BORDER_COLOR_RED
+0x0000A430 TD_GS_BORDER_COLOR_GREEN
+0x0000A434 TD_GS_BORDER_COLOR_BLUE
+0x0000A438 TD_GS_BORDER_COLOR_ALPHA
+0x0000A43C TD_HS_BORDER_COLOR_INDEX
+0x0000A440 TD_HS_BORDER_COLOR_RED
+0x0000A444 TD_HS_BORDER_COLOR_GREEN
+0x0000A448 TD_HS_BORDER_COLOR_BLUE
+0x0000A44C TD_HS_BORDER_COLOR_ALPHA
+0x0000A450 TD_LS_BORDER_COLOR_INDEX
+0x0000A454 TD_LS_BORDER_COLOR_RED
+0x0000A458 TD_LS_BORDER_COLOR_GREEN
+0x0000A45C TD_LS_BORDER_COLOR_BLUE
+0x0000A460 TD_LS_BORDER_COLOR_ALPHA
+0x0000A464 TD_CS_BORDER_COLOR_INDEX
+0x0000A468 TD_CS_BORDER_COLOR_RED
+0x0000A46C TD_CS_BORDER_COLOR_GREEN
+0x0000A470 TD_CS_BORDER_COLOR_BLUE
+0x0000A474 TD_CS_BORDER_COLOR_ALPHA
+0x00028000 DB_RENDER_CONTROL
+0x00028004 DB_COUNT_CONTROL
+0x0002800C DB_RENDER_OVERRIDE
+0x00028010 DB_RENDER_OVERRIDE2
+0x00028028 DB_STENCIL_CLEAR
+0x0002802C DB_DEPTH_CLEAR
+0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
+0x0002805C DB_DEPTH_SLICE
+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
+0x00028200 PA_SC_WINDOW_OFFSET
+0x00028204 PA_SC_WINDOW_SCISSOR_TL
+0x00028208 PA_SC_WINDOW_SCISSOR_BR
+0x0002820C PA_SC_CLIPRECT_RULE
+0x00028210 PA_SC_CLIPRECT_0_TL
+0x00028214 PA_SC_CLIPRECT_0_BR
+0x00028218 PA_SC_CLIPRECT_1_TL
+0x0002821C PA_SC_CLIPRECT_1_BR
+0x00028220 PA_SC_CLIPRECT_2_TL
+0x00028224 PA_SC_CLIPRECT_2_BR
+0x00028228 PA_SC_CLIPRECT_3_TL
+0x0002822C PA_SC_CLIPRECT_3_BR
+0x00028230 PA_SC_EDGERULE
+0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET
+0x00028240 PA_SC_GENERIC_SCISSOR_TL
+0x00028244 PA_SC_GENERIC_SCISSOR_BR
+0x00028250 PA_SC_VPORT_SCISSOR_0_TL
+0x00028254 PA_SC_VPORT_SCISSOR_0_BR
+0x00028258 PA_SC_VPORT_SCISSOR_1_TL
+0x0002825C PA_SC_VPORT_SCISSOR_1_BR
+0x00028260 PA_SC_VPORT_SCISSOR_2_TL
+0x00028264 PA_SC_VPORT_SCISSOR_2_BR
+0x00028268 PA_SC_VPORT_SCISSOR_3_TL
+0x0002826C PA_SC_VPORT_SCISSOR_3_BR
+0x00028270 PA_SC_VPORT_SCISSOR_4_TL
+0x00028274 PA_SC_VPORT_SCISSOR_4_BR
+0x00028278 PA_SC_VPORT_SCISSOR_5_TL
+0x0002827C PA_SC_VPORT_SCISSOR_5_BR
+0x00028280 PA_SC_VPORT_SCISSOR_6_TL
+0x00028284 PA_SC_VPORT_SCISSOR_6_BR
+0x00028288 PA_SC_VPORT_SCISSOR_7_TL
+0x0002828C PA_SC_VPORT_SCISSOR_7_BR
+0x00028290 PA_SC_VPORT_SCISSOR_8_TL
+0x00028294 PA_SC_VPORT_SCISSOR_8_BR
+0x00028298 PA_SC_VPORT_SCISSOR_9_TL
+0x0002829C PA_SC_VPORT_SCISSOR_9_BR
+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
+0x000282AC PA_SC_VPORT_SCISSOR_11_BR
+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
+0x000282BC PA_SC_VPORT_SCISSOR_13_BR
+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
+0x000282CC PA_SC_VPORT_SCISSOR_15_BR
+0x000282D0 PA_SC_VPORT_ZMIN_0
+0x000282D4 PA_SC_VPORT_ZMAX_0
+0x000282D8 PA_SC_VPORT_ZMIN_1
+0x000282DC PA_SC_VPORT_ZMAX_1
+0x000282E0 PA_SC_VPORT_ZMIN_2
+0x000282E4 PA_SC_VPORT_ZMAX_2
+0x000282E8 PA_SC_VPORT_ZMIN_3
+0x000282EC PA_SC_VPORT_ZMAX_3
+0x000282F0 PA_SC_VPORT_ZMIN_4
+0x000282F4 PA_SC_VPORT_ZMAX_4
+0x000282F8 PA_SC_VPORT_ZMIN_5
+0x000282FC PA_SC_VPORT_ZMAX_5
+0x00028300 PA_SC_VPORT_ZMIN_6
+0x00028304 PA_SC_VPORT_ZMAX_6
+0x00028308 PA_SC_VPORT_ZMIN_7
+0x0002830C PA_SC_VPORT_ZMAX_7
+0x00028310 PA_SC_VPORT_ZMIN_8
+0x00028314 PA_SC_VPORT_ZMAX_8
+0x00028318 PA_SC_VPORT_ZMIN_9
+0x0002831C PA_SC_VPORT_ZMAX_9
+0x00028320 PA_SC_VPORT_ZMIN_10
+0x00028324 PA_SC_VPORT_ZMAX_10
+0x00028328 PA_SC_VPORT_ZMIN_11
+0x0002832C PA_SC_VPORT_ZMAX_11
+0x00028330 PA_SC_VPORT_ZMIN_12
+0x00028334 PA_SC_VPORT_ZMAX_12
+0x00028338 PA_SC_VPORT_ZMIN_13
+0x0002833C PA_SC_VPORT_ZMAX_13
+0x00028340 PA_SC_VPORT_ZMIN_14
+0x00028344 PA_SC_VPORT_ZMAX_14
+0x00028348 PA_SC_VPORT_ZMIN_15
+0x0002834C PA_SC_VPORT_ZMAX_15
+0x00028350 SX_MISC
+0x00028354 SX_SURFACE_SYNC
+0x00028380 SQ_VTX_SEMANTIC_0
+0x00028384 SQ_VTX_SEMANTIC_1
+0x00028388 SQ_VTX_SEMANTIC_2
+0x0002838C SQ_VTX_SEMANTIC_3
+0x00028390 SQ_VTX_SEMANTIC_4
+0x00028394 SQ_VTX_SEMANTIC_5
+0x00028398 SQ_VTX_SEMANTIC_6
+0x0002839C SQ_VTX_SEMANTIC_7
+0x000283A0 SQ_VTX_SEMANTIC_8
+0x000283A4 SQ_VTX_SEMANTIC_9
+0x000283A8 SQ_VTX_SEMANTIC_10
+0x000283AC SQ_VTX_SEMANTIC_11
+0x000283B0 SQ_VTX_SEMANTIC_12
+0x000283B4 SQ_VTX_SEMANTIC_13
+0x000283B8 SQ_VTX_SEMANTIC_14
+0x000283BC SQ_VTX_SEMANTIC_15
+0x000283C0 SQ_VTX_SEMANTIC_16
+0x000283C4 SQ_VTX_SEMANTIC_17
+0x000283C8 SQ_VTX_SEMANTIC_18
+0x000283CC SQ_VTX_SEMANTIC_19
+0x000283D0 SQ_VTX_SEMANTIC_20
+0x000283D4 SQ_VTX_SEMANTIC_21
+0x000283D8 SQ_VTX_SEMANTIC_22
+0x000283DC SQ_VTX_SEMANTIC_23
+0x000283E0 SQ_VTX_SEMANTIC_24
+0x000283E4 SQ_VTX_SEMANTIC_25
+0x000283E8 SQ_VTX_SEMANTIC_26
+0x000283EC SQ_VTX_SEMANTIC_27
+0x000283F0 SQ_VTX_SEMANTIC_28
+0x000283F4 SQ_VTX_SEMANTIC_29
+0x000283F8 SQ_VTX_SEMANTIC_30
+0x000283FC SQ_VTX_SEMANTIC_31
+0x00028400 VGT_MAX_VTX_INDX
+0x00028404 VGT_MIN_VTX_INDX
+0x00028408 VGT_INDX_OFFSET
+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
+0x00028410 SX_ALPHA_TEST_CONTROL
+0x00028414 CB_BLEND_RED
+0x00028418 CB_BLEND_GREEN
+0x0002841C CB_BLEND_BLUE
+0x00028420 CB_BLEND_ALPHA
+0x00028430 DB_STENCILREFMASK
+0x00028434 DB_STENCILREFMASK_BF
+0x00028438 SX_ALPHA_REF
+0x0002843C PA_CL_VPORT_XSCALE_0
+0x00028440 PA_CL_VPORT_XOFFSET_0
+0x00028444 PA_CL_VPORT_YSCALE_0
+0x00028448 PA_CL_VPORT_YOFFSET_0
+0x0002844C PA_CL_VPORT_ZSCALE_0
+0x00028450 PA_CL_VPORT_ZOFFSET_0
+0x00028454 PA_CL_VPORT_XSCALE_1
+0x00028458 PA_CL_VPORT_XOFFSET_1
+0x0002845C PA_CL_VPORT_YSCALE_1
+0x00028460 PA_CL_VPORT_YOFFSET_1
+0x00028464 PA_CL_VPORT_ZSCALE_1
+0x00028468 PA_CL_VPORT_ZOFFSET_1
+0x0002846C PA_CL_VPORT_XSCALE_2
+0x00028470 PA_CL_VPORT_XOFFSET_2
+0x00028474 PA_CL_VPORT_YSCALE_2
+0x00028478 PA_CL_VPORT_YOFFSET_2
+0x0002847C PA_CL_VPORT_ZSCALE_2
+0x00028480 PA_CL_VPORT_ZOFFSET_2
+0x00028484 PA_CL_VPORT_XSCALE_3
+0x00028488 PA_CL_VPORT_XOFFSET_3
+0x0002848C PA_CL_VPORT_YSCALE_3
+0x00028490 PA_CL_VPORT_YOFFSET_3
+0x00028494 PA_CL_VPORT_ZSCALE_3
+0x00028498 PA_CL_VPORT_ZOFFSET_3
+0x0002849C PA_CL_VPORT_XSCALE_4
+0x000284A0 PA_CL_VPORT_XOFFSET_4
+0x000284A4 PA_CL_VPORT_YSCALE_4
+0x000284A8 PA_CL_VPORT_YOFFSET_4
+0x000284AC PA_CL_VPORT_ZSCALE_4
+0x000284B0 PA_CL_VPORT_ZOFFSET_4
+0x000284B4 PA_CL_VPORT_XSCALE_5
+0x000284B8 PA_CL_VPORT_XOFFSET_5
+0x000284BC PA_CL_VPORT_YSCALE_5
+0x000284C0 PA_CL_VPORT_YOFFSET_5
+0x000284C4 PA_CL_VPORT_ZSCALE_5
+0x000284C8 PA_CL_VPORT_ZOFFSET_5
+0x000284CC PA_CL_VPORT_XSCALE_6
+0x000284D0 PA_CL_VPORT_XOFFSET_6
+0x000284D4 PA_CL_VPORT_YSCALE_6
+0x000284D8 PA_CL_VPORT_YOFFSET_6
+0x000284DC PA_CL_VPORT_ZSCALE_6
+0x000284E0 PA_CL_VPORT_ZOFFSET_6
+0x000284E4 PA_CL_VPORT_XSCALE_7
+0x000284E8 PA_CL_VPORT_XOFFSET_7
+0x000284EC PA_CL_VPORT_YSCALE_7
+0x000284F0 PA_CL_VPORT_YOFFSET_7
+0x000284F4 PA_CL_VPORT_ZSCALE_7
+0x000284F8 PA_CL_VPORT_ZOFFSET_7
+0x000284FC PA_CL_VPORT_XSCALE_8
+0x00028500 PA_CL_VPORT_XOFFSET_8
+0x00028504 PA_CL_VPORT_YSCALE_8
+0x00028508 PA_CL_VPORT_YOFFSET_8
+0x0002850C PA_CL_VPORT_ZSCALE_8
+0x00028510 PA_CL_VPORT_ZOFFSET_8
+0x00028514 PA_CL_VPORT_XSCALE_9
+0x00028518 PA_CL_VPORT_XOFFSET_9
+0x0002851C PA_CL_VPORT_YSCALE_9
+0x00028520 PA_CL_VPORT_YOFFSET_9
+0x00028524 PA_CL_VPORT_ZSCALE_9
+0x00028528 PA_CL_VPORT_ZOFFSET_9
+0x0002852C PA_CL_VPORT_XSCALE_10
+0x00028530 PA_CL_VPORT_XOFFSET_10
+0x00028534 PA_CL_VPORT_YSCALE_10
+0x00028538 PA_CL_VPORT_YOFFSET_10
+0x0002853C PA_CL_VPORT_ZSCALE_10
+0x00028540 PA_CL_VPORT_ZOFFSET_10
+0x00028544 PA_CL_VPORT_XSCALE_11
+0x00028548 PA_CL_VPORT_XOFFSET_11
+0x0002854C PA_CL_VPORT_YSCALE_11
+0x00028550 PA_CL_VPORT_YOFFSET_11
+0x00028554 PA_CL_VPORT_ZSCALE_11
+0x00028558 PA_CL_VPORT_ZOFFSET_11
+0x0002855C PA_CL_VPORT_XSCALE_12
+0x00028560 PA_CL_VPORT_XOFFSET_12
+0x00028564 PA_CL_VPORT_YSCALE_12
+0x00028568 PA_CL_VPORT_YOFFSET_12
+0x0002856C PA_CL_VPORT_ZSCALE_12
+0x00028570 PA_CL_VPORT_ZOFFSET_12
+0x00028574 PA_CL_VPORT_XSCALE_13
+0x00028578 PA_CL_VPORT_XOFFSET_13
+0x0002857C PA_CL_VPORT_YSCALE_13
+0x00028580 PA_CL_VPORT_YOFFSET_13
+0x00028584 PA_CL_VPORT_ZSCALE_13
+0x00028588 PA_CL_VPORT_ZOFFSET_13
+0x0002858C PA_CL_VPORT_XSCALE_14
+0x00028590 PA_CL_VPORT_XOFFSET_14
+0x00028594 PA_CL_VPORT_YSCALE_14
+0x00028598 PA_CL_VPORT_YOFFSET_14
+0x0002859C PA_CL_VPORT_ZSCALE_14
+0x000285A0 PA_CL_VPORT_ZOFFSET_14
+0x000285A4 PA_CL_VPORT_XSCALE_15
+0x000285A8 PA_CL_VPORT_XOFFSET_15
+0x000285AC PA_CL_VPORT_YSCALE_15
+0x000285B0 PA_CL_VPORT_YOFFSET_15
+0x000285B4 PA_CL_VPORT_ZSCALE_15
+0x000285B8 PA_CL_VPORT_ZOFFSET_15
+0x000285BC PA_CL_UCP_0_X
+0x000285C0 PA_CL_UCP_0_Y
+0x000285C4 PA_CL_UCP_0_Z
+0x000285C8 PA_CL_UCP_0_W
+0x000285CC PA_CL_UCP_1_X
+0x000285D0 PA_CL_UCP_1_Y
+0x000285D4 PA_CL_UCP_1_Z
+0x000285D8 PA_CL_UCP_1_W
+0x000285DC PA_CL_UCP_2_X
+0x000285E0 PA_CL_UCP_2_Y
+0x000285E4 PA_CL_UCP_2_Z
+0x000285E8 PA_CL_UCP_2_W
+0x000285EC PA_CL_UCP_3_X
+0x000285F0 PA_CL_UCP_3_Y
+0x000285F4 PA_CL_UCP_3_Z
+0x000285F8 PA_CL_UCP_3_W
+0x000285FC PA_CL_UCP_4_X
+0x00028600 PA_CL_UCP_4_Y
+0x00028604 PA_CL_UCP_4_Z
+0x00028608 PA_CL_UCP_4_W
+0x0002860C PA_CL_UCP_5_X
+0x00028610 PA_CL_UCP_5_Y
+0x00028614 PA_CL_UCP_5_Z
+0x00028618 PA_CL_UCP_5_W
+0x0002861C SPI_VS_OUT_ID_0
+0x00028620 SPI_VS_OUT_ID_1
+0x00028624 SPI_VS_OUT_ID_2
+0x00028628 SPI_VS_OUT_ID_3
+0x0002862C SPI_VS_OUT_ID_4
+0x00028630 SPI_VS_OUT_ID_5
+0x00028634 SPI_VS_OUT_ID_6
+0x00028638 SPI_VS_OUT_ID_7
+0x0002863C SPI_VS_OUT_ID_8
+0x00028640 SPI_VS_OUT_ID_9
+0x00028644 SPI_PS_INPUT_CNTL_0
+0x00028648 SPI_PS_INPUT_CNTL_1
+0x0002864C SPI_PS_INPUT_CNTL_2
+0x00028650 SPI_PS_INPUT_CNTL_3
+0x00028654 SPI_PS_INPUT_CNTL_4
+0x00028658 SPI_PS_INPUT_CNTL_5
+0x0002865C SPI_PS_INPUT_CNTL_6
+0x00028660 SPI_PS_INPUT_CNTL_7
+0x00028664 SPI_PS_INPUT_CNTL_8
+0x00028668 SPI_PS_INPUT_CNTL_9
+0x0002866C SPI_PS_INPUT_CNTL_10
+0x00028670 SPI_PS_INPUT_CNTL_11
+0x00028674 SPI_PS_INPUT_CNTL_12
+0x00028678 SPI_PS_INPUT_CNTL_13
+0x0002867C SPI_PS_INPUT_CNTL_14
+0x00028680 SPI_PS_INPUT_CNTL_15
+0x00028684 SPI_PS_INPUT_CNTL_16
+0x00028688 SPI_PS_INPUT_CNTL_17
+0x0002868C SPI_PS_INPUT_CNTL_18
+0x00028690 SPI_PS_INPUT_CNTL_19
+0x00028694 SPI_PS_INPUT_CNTL_20
+0x00028698 SPI_PS_INPUT_CNTL_21
+0x0002869C SPI_PS_INPUT_CNTL_22
+0x000286A0 SPI_PS_INPUT_CNTL_23
+0x000286A4 SPI_PS_INPUT_CNTL_24
+0x000286A8 SPI_PS_INPUT_CNTL_25
+0x000286AC SPI_PS_INPUT_CNTL_26
+0x000286B0 SPI_PS_INPUT_CNTL_27
+0x000286B4 SPI_PS_INPUT_CNTL_28
+0x000286B8 SPI_PS_INPUT_CNTL_29
+0x000286BC SPI_PS_INPUT_CNTL_30
+0x000286C0 SPI_PS_INPUT_CNTL_31
+0x000286C4 SPI_VS_OUT_CONFIG
+0x000286C8 SPI_THREAD_GROUPING
+0x000286CC SPI_PS_IN_CONTROL_0
+0x000286D0 SPI_PS_IN_CONTROL_1
+0x000286D4 SPI_INTERP_CONTROL_0
+0x000286D8 SPI_INPUT_Z
+0x000286DC SPI_FOG_CNTL
+0x000286E0 SPI_BARYC_CNTL
+0x000286E4 SPI_PS_IN_CONTROL_2
+0x000286E8 SPI_COMPUTE_INPUT_CNTL
+0x000286EC SPI_COMPUTE_NUM_THREAD_X
+0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
+0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x000286F8 SPI_GPR_MGMT
+0x000286FC SPI_LDS_MGMT
+0x00028700 SPI_STACK_MGMT
+0x00028704 SPI_WAVE_MGMT_1
+0x00028708 SPI_WAVE_MGMT_2
+0x00028724 GDS_ADDR_SIZE
+0x00028780 CB_BLEND0_CONTROL
+0x00028784 CB_BLEND1_CONTROL
+0x00028788 CB_BLEND2_CONTROL
+0x0002878C CB_BLEND3_CONTROL
+0x00028790 CB_BLEND4_CONTROL
+0x00028794 CB_BLEND5_CONTROL
+0x00028798 CB_BLEND6_CONTROL
+0x0002879C CB_BLEND7_CONTROL
+0x000287CC CS_COPY_STATE
+0x000287D0 GFX_COPY_STATE
+0x000287D4 PA_CL_POINT_X_RAD
+0x000287D8 PA_CL_POINT_Y_RAD
+0x000287DC PA_CL_POINT_SIZE
+0x000287E0 PA_CL_POINT_CULL_RAD
+0x00028808 CB_COLOR_CONTROL
+0x0002880C DB_SHADER_CONTROL
+0x00028810 PA_CL_CLIP_CNTL
+0x00028814 PA_SU_SC_MODE_CNTL
+0x00028818 PA_CL_VTE_CNTL
+0x0002881C PA_CL_VS_OUT_CNTL
+0x00028820 PA_CL_NANINF_CNTL
+0x00028824 PA_SU_LINE_STIPPLE_CNTL
+0x00028828 PA_SU_LINE_STIPPLE_SCALE
+0x0002882C PA_SU_PRIM_FILTER_CNTL
+0x00028844 SQ_PGM_RESOURCES_PS
+0x00028848 SQ_PGM_RESOURCES_2_PS
+0x0002884C SQ_PGM_EXPORTS_PS
+0x00028860 SQ_PGM_RESOURCES_VS
+0x00028864 SQ_PGM_RESOURCES_2_VS
+0x00028878 SQ_PGM_RESOURCES_GS
+0x0002887C SQ_PGM_RESOURCES_2_GS
+0x00028890 SQ_PGM_RESOURCES_ES
+0x00028894 SQ_PGM_RESOURCES_2_ES
+0x000288A8 SQ_PGM_RESOURCES_FS
+0x000288BC SQ_PGM_RESOURCES_HS
+0x000288C0 SQ_PGM_RESOURCES_2_HS
+0x000288D4 SQ_PGM_RESOURCES_LS
+0x000288D8 SQ_PGM_RESOURCES_2_LS
+0x000288E8 SQ_LDS_ALLOC
+0x000288EC SQ_LDS_ALLOC_PS
+0x000288F0 SQ_VTX_SEMANTIC_CLEAR
+0x00028A00 PA_SU_POINT_SIZE
+0x00028A04 PA_SU_POINT_MINMAX
+0x00028A08 PA_SU_LINE_CNTL
+0x00028A0C PA_SC_LINE_STIPPLE
+0x00028A10 VGT_OUTPUT_PATH_CNTL
+0x00028A14 VGT_HOS_CNTL
+0x00028A18 VGT_HOS_MAX_TESS_LEVEL
+0x00028A1C VGT_HOS_MIN_TESS_LEVEL
+0x00028A20 VGT_HOS_REUSE_DEPTH
+0x00028A24 VGT_GROUP_PRIM_TYPE
+0x00028A28 VGT_GROUP_FIRST_DECR
+0x00028A2C VGT_GROUP_DECR
+0x00028A30 VGT_GROUP_VECT_0_CNTL
+0x00028A34 VGT_GROUP_VECT_1_CNTL
+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
+0x00028A40 VGT_GS_MODE
+0x00028A48 PA_SC_MODE_CNTL_0
+0x00028A4C PA_SC_MODE_CNTL_1
+0x00028A50 VGT_ENHANCE
+0x00028A54 VGT_GS_PER_ES
+0x00028A58 VGT_ES_PER_GS
+0x00028A5C VGT_GS_PER_VS
+0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x00028A70 IA_ENHANCE
+0x00028A84 VGT_PRIMITIVEID_EN
+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
+0x00028AA0 VGT_INSTANCE_STEP_RATE_0
+0x00028AA4 VGT_INSTANCE_STEP_RATE_1
+0x00028AA8 IA_MULTI_VGT_PARAM
+0x00028AB4 VGT_REUSE_OFF
+0x00028AB8 VGT_VTX_CNT_EN
+0x00028ABC DB_HTILE_SURFACE
+0x00028AC0 DB_SRESULTS_COMPARE_STATE0
+0x00028AC4 DB_SRESULTS_COMPARE_STATE1
+0x00028AC8 DB_PRELOAD_CONTROL
+0x00028B38 VGT_GS_MAX_VERT_OUT
+0x00028B54 VGT_SHADER_STAGES_EN
+0x00028B58 VGT_LS_HS_CONFIG
+0x00028B6C VGT_TF_PARAM
+0x00028B70 DB_ALPHA_TO_MASK
+0x00028B74 VGT_DISPATCH_INITIATOR
+0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL
+0x00028B7C PA_SU_POLY_OFFSET_CLAMP
+0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE
+0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
+0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
+0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
+0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028BD4 PA_SC_CENTROID_PRIORITY_0
+0x00028BD8 PA_SC_CENTROID_PRIORITY_1
+0x00028BDC PA_SC_LINE_CNTL
+0x00028BE4 PA_SU_VTX_CNTL
+0x00028BE8 PA_CL_GB_VERT_CLIP_ADJ
+0x00028BEC PA_CL_GB_VERT_DISC_ADJ
+0x00028BF0 PA_CL_GB_HORZ_CLIP_ADJ
+0x00028BF4 PA_CL_GB_HORZ_DISC_ADJ
+0x00028BF8 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_0
+0x00028BFC PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_1
+0x00028C00 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_2
+0x00028C04 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_3
+0x00028C08 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_0
+0x00028C0C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_1
+0x00028C10 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_2
+0x00028C14 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_3
+0x00028C18 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_0
+0x00028C1C PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_1
+0x00028C20 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_2
+0x00028C24 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_3
+0x00028C28 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_0
+0x00028C2C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_1
+0x00028C30 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_2
+0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3
+0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0
+0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1
+0x00028C8C CB_COLOR0_CLEAR_WORD0
+0x00028C90 CB_COLOR0_CLEAR_WORD1
+0x00028C94 CB_COLOR0_CLEAR_WORD2
+0x00028C98 CB_COLOR0_CLEAR_WORD3
+0x00028CC8 CB_COLOR1_CLEAR_WORD0
+0x00028CCC CB_COLOR1_CLEAR_WORD1
+0x00028CD0 CB_COLOR1_CLEAR_WORD2
+0x00028CD4 CB_COLOR1_CLEAR_WORD3
+0x00028D04 CB_COLOR2_CLEAR_WORD0
+0x00028D08 CB_COLOR2_CLEAR_WORD1
+0x00028D0C CB_COLOR2_CLEAR_WORD2
+0x00028D10 CB_COLOR2_CLEAR_WORD3
+0x00028D40 CB_COLOR3_CLEAR_WORD0
+0x00028D44 CB_COLOR3_CLEAR_WORD1
+0x00028D48 CB_COLOR3_CLEAR_WORD2
+0x00028D4C CB_COLOR3_CLEAR_WORD3
+0x00028D7C CB_COLOR4_CLEAR_WORD0
+0x00028D80 CB_COLOR4_CLEAR_WORD1
+0x00028D84 CB_COLOR4_CLEAR_WORD2
+0x00028D88 CB_COLOR4_CLEAR_WORD3
+0x00028DB8 CB_COLOR5_CLEAR_WORD0
+0x00028DBC CB_COLOR5_CLEAR_WORD1
+0x00028DC0 CB_COLOR5_CLEAR_WORD2
+0x00028DC4 CB_COLOR5_CLEAR_WORD3
+0x00028DF4 CB_COLOR6_CLEAR_WORD0
+0x00028DF8 CB_COLOR6_CLEAR_WORD1
+0x00028DFC CB_COLOR6_CLEAR_WORD2
+0x00028E00 CB_COLOR6_CLEAR_WORD3
+0x00028E30 CB_COLOR7_CLEAR_WORD0
+0x00028E34 CB_COLOR7_CLEAR_WORD1
+0x00028E38 CB_COLOR7_CLEAR_WORD2
+0x00028E3C CB_COLOR7_CLEAR_WORD3
+0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0
+0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1
+0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2
+0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3
+0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4
+0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5
+0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6
+0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7
+0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8
+0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9
+0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10
+0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11
+0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12
+0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13
+0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14
+0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15
+0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0
+0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1
+0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2
+0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3
+0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4
+0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5
+0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6
+0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7
+0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8
+0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9
+0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10
+0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11
+0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12
+0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13
+0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14
+0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15
+0x0003CFF0 SQ_VTX_BASE_VTX_LOC
+0x0003CFF4 SQ_VTX_START_INST_LOC
+0x0003FF00 SQ_TEX_SAMPLER_CLEAR
+0x0003FF04 SQ_TEX_RESOURCE_CLEAR
+0x0003FF08 SQ_LOOP_BOOL_CLEAR
diff --git a/drivers/gpu/drm/radeon/reg_srcs/evergreen b/drivers/gpu/drm/radeon/reg_srcs/evergreen
index 9177f91..7e16371 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/evergreen
+++ b/drivers/gpu/drm/radeon/reg_srcs/evergreen
@@ -1,4 +1,5 @@
 evergreen 0x9400
+0x0000802C GRBM_GFX_INDEX
 0x00008040 WAIT_UNTIL
 0x00008044 WAIT_UNTIL_POLL_CNTL
 0x00008048 WAIT_UNTIL_POLL_MASK
@@ -220,6 +221,7 @@ evergreen 0x9400
 0x00028348 PA_SC_VPORT_ZMIN_15
 0x0002834C PA_SC_VPORT_ZMAX_15
 0x00028350 SX_MISC
+0x00028354 SX_SURFACE_SYNC
 0x00028380 SQ_VTX_SEMANTIC_0
 0x00028384 SQ_VTX_SEMANTIC_1
 0x00028388 SQ_VTX_SEMANTIC_2
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c
index c76283d..aa6a66e 100644
--- a/drivers/gpu/drm/radeon/rs400.c
+++ b/drivers/gpu/drm/radeon/rs400.c
@@ -412,12 +412,12 @@ static int rs400_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index 8af4679..19763f5 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -865,12 +865,12 @@ static int rs600_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c
index 66c949b..a9049ed 100644
--- a/drivers/gpu/drm/radeon/rs690.c
+++ b/drivers/gpu/drm/radeon/rs690.c
@@ -627,12 +627,12 @@ static int rs690_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c
index 64b57af..6613ee9 100644
--- a/drivers/gpu/drm/radeon/rv515.c
+++ b/drivers/gpu/drm/radeon/rv515.c
@@ -398,12 +398,12 @@ static int rv515_startup(struct radeon_device *rdev)
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 714ad45..b974ac7 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -1003,7 +1003,7 @@ static int rv770_vram_scratch_init(struct radeon_device *rdev)
 	u64 gpu_addr;
 
 	if (rdev->vram_scratch.robj == NULL) {
-		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
+		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				     &rdev->vram_scratch.robj);
 		if (r) {
@@ -1209,7 +1209,7 @@ int rv770_resume(struct radeon_device *rdev)
 
 	r = r600_ib_test(rdev);
 	if (r) {
-		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		DRM_ERROR("radeon: failed testing IB (%d).\n", r);
 		return r;
 	}
 
diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c
index fa64d25..6464490 100644
--- a/drivers/gpu/drm/savage/savage_drv.c
+++ b/drivers/gpu/drm/savage/savage_drv.c
@@ -55,11 +55,6 @@ static struct drm_driver driver = {
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -68,15 +63,20 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver savage_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init savage_init(void)
 {
 	driver.num_ioctls = savage_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &savage_pci_driver);
 }
 
 static void __exit savage_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &savage_pci_driver);
 }
 
 module_init(savage_init);
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 4caf5d0..46d5be6 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -82,10 +82,6 @@ static struct drm_driver driver = {
 		 .fasync = drm_fasync,
 		 .llseek = noop_llseek,
 	},
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -95,15 +91,20 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver sis_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init sis_init(void)
 {
 	driver.num_ioctls = sis_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &sis_pci_driver);
 }
 
 static void __exit sis_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &sis_pci_driver);
 }
 
 module_init(sis_init);
diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c
index b70fa91..8bf9881 100644
--- a/drivers/gpu/drm/tdfx/tdfx_drv.c
+++ b/drivers/gpu/drm/tdfx/tdfx_drv.c
@@ -52,10 +52,6 @@ static struct drm_driver driver = {
 		 .fasync = drm_fasync,
 		 .llseek = noop_llseek,
 	},
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -65,14 +61,19 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver tdfx_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init tdfx_init(void)
 {
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &tdfx_pci_driver);
 }
 
 static void __exit tdfx_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &tdfx_pci_driver);
 }
 
 module_init(tdfx_init);
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c
index f999e36..1c4a72f 100644
--- a/drivers/gpu/drm/ttm/ttm_agp_backend.c
+++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c
@@ -47,7 +47,8 @@ struct ttm_agp_backend {
 
 static int ttm_agp_populate(struct ttm_backend *backend,
 			    unsigned long num_pages, struct page **pages,
-			    struct page *dummy_read_page)
+			    struct page *dummy_read_page,
+			    dma_addr_t *dma_addrs)
 {
 	struct ttm_agp_backend *agp_be =
 	    container_of(backend, struct ttm_agp_backend, backend);
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index af61fc2..0b6a55a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -406,11 +406,12 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
 		}
 
 		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+			if (bdev->driver->move_notify)
+				bdev->driver->move_notify(bo, mem);
 			bo->mem = *mem;
 			mem->mm_node = NULL;
 			goto moved;
 		}
-
 	}
 
 	if (bdev->driver->move_notify)
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index b1e02ff..737a2a2 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -38,6 +38,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h> /* for seq_printf */
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/atomic.h>
 
@@ -662,7 +663,8 @@ out:
  * cached pages.
  */
 int ttm_get_pages(struct list_head *pages, int flags,
-		enum ttm_caching_state cstate, unsigned count)
+		  enum ttm_caching_state cstate, unsigned count,
+		  dma_addr_t *dma_address)
 {
 	struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
 	struct page *p = NULL;
@@ -681,14 +683,22 @@ int ttm_get_pages(struct list_head *pages, int flags,
 			gfp_flags |= GFP_HIGHUSER;
 
 		for (r = 0; r < count; ++r) {
-			p = alloc_page(gfp_flags);
+			if ((flags & TTM_PAGE_FLAG_DMA32) && dma_address) {
+				void *addr;
+				addr = dma_alloc_coherent(NULL, PAGE_SIZE,
+							  &dma_address[r],
+							  gfp_flags);
+				if (addr == NULL)
+					return -ENOMEM;
+				p = virt_to_page(addr);
+			} else
+				p = alloc_page(gfp_flags);
 			if (!p) {
 
 				printk(KERN_ERR TTM_PFX
 				       "Unable to allocate page.");
 				return -ENOMEM;
 			}
-
 			list_add(&p->lru, pages);
 		}
 		return 0;
@@ -720,7 +730,7 @@ int ttm_get_pages(struct list_head *pages, int flags,
 			printk(KERN_ERR TTM_PFX
 			       "Failed to allocate extra pages "
 			       "for large request.");
-			ttm_put_pages(pages, 0, flags, cstate);
+			ttm_put_pages(pages, 0, flags, cstate, NULL);
 			return r;
 		}
 	}
@@ -731,17 +741,29 @@ int ttm_get_pages(struct list_head *pages, int flags,
 
 /* Put all pages in pages list to correct pool to wait for reuse */
 void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags,
-		enum ttm_caching_state cstate)
+		   enum ttm_caching_state cstate, dma_addr_t *dma_address)
 {
 	unsigned long irq_flags;
 	struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
 	struct page *p, *tmp;
+	unsigned r;
 
 	if (pool == NULL) {
 		/* No pool for this memory type so free the pages */
 
+		r = page_count-1;
 		list_for_each_entry_safe(p, tmp, pages, lru) {
-			__free_page(p);
+			if ((flags & TTM_PAGE_FLAG_DMA32) && dma_address) {
+				void *addr = page_address(p);
+				WARN_ON(!addr || !dma_address[r]);
+				if (addr)
+					dma_free_coherent(NULL, PAGE_SIZE,
+							  addr,
+							  dma_address[r]);
+				dma_address[r] = 0;
+			} else
+				__free_page(p);
+			r--;
 		}
 		/* Make the pages list empty */
 		INIT_LIST_HEAD(pages);
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
index af789dc..86d5b17 100644
--- a/drivers/gpu/drm/ttm/ttm_tt.c
+++ b/drivers/gpu/drm/ttm/ttm_tt.c
@@ -49,12 +49,16 @@ static int ttm_tt_swapin(struct ttm_tt *ttm);
 static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
 {
 	ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(*ttm->pages));
+	ttm->dma_address = drm_calloc_large(ttm->num_pages,
+					    sizeof(*ttm->dma_address));
 }
 
 static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
 {
 	drm_free_large(ttm->pages);
 	ttm->pages = NULL;
+	drm_free_large(ttm->dma_address);
+	ttm->dma_address = NULL;
 }
 
 static void ttm_tt_free_user_pages(struct ttm_tt *ttm)
@@ -105,7 +109,8 @@ static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index)
 
 		INIT_LIST_HEAD(&h);
 
-		ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1);
+		ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1,
+				    &ttm->dma_address[index]);
 
 		if (ret != 0)
 			return NULL;
@@ -164,7 +169,7 @@ int ttm_tt_populate(struct ttm_tt *ttm)
 	}
 
 	be->func->populate(be, ttm->num_pages, ttm->pages,
-			   ttm->dummy_read_page);
+			   ttm->dummy_read_page, ttm->dma_address);
 	ttm->state = tt_unbound;
 	return 0;
 }
@@ -298,7 +303,8 @@ static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm)
 			count++;
 		}
 	}
-	ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state);
+	ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state,
+		      ttm->dma_address);
 	ttm->state = tt_unpopulated;
 	ttm->first_himem_page = ttm->num_pages;
 	ttm->last_lomem_page = -1;
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index e1ff4e7..920a552 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -62,10 +62,6 @@ static struct drm_driver driver = {
 		.fasync = drm_fasync,
 		.llseek = noop_llseek,
 		},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -75,16 +71,21 @@ static struct drm_driver driver = {
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver via_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init via_init(void)
 {
 	driver.num_ioctls = via_max_ioctl;
 	via_init_command_verifier();
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &via_pci_driver);
 }
 
 static void __exit via_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &via_pci_driver);
 }
 
 module_init(via_init);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
index 80bc37b..87e43e0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
@@ -102,7 +102,8 @@ struct vmw_ttm_backend {
 
 static int vmw_ttm_populate(struct ttm_backend *backend,
 			    unsigned long num_pages, struct page **pages,
-			    struct page *dummy_read_page)
+			    struct page *dummy_read_page,
+			    dma_addr_t *dma_addrs)
 {
 	struct vmw_ttm_backend *vmw_be =
 	    container_of(backend, struct vmw_ttm_backend, backend);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 10ca97e..96949b9 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -909,15 +909,6 @@ static struct drm_driver driver = {
 #endif
 		 .llseek = noop_llseek,
 	},
-	.pci_driver = {
-		 .name = VMWGFX_DRIVER_NAME,
-		 .id_table = vmw_pci_id_list,
-		 .probe = vmw_probe,
-		 .remove = vmw_remove,
-		 .driver = {
-			 .pm = &vmw_pm_ops
-		 }
-	 },
 	.name = VMWGFX_DRIVER_NAME,
 	.desc = VMWGFX_DRIVER_DESC,
 	.date = VMWGFX_DRIVER_DATE,
@@ -926,6 +917,16 @@ static struct drm_driver driver = {
 	.patchlevel = VMWGFX_DRIVER_PATCHLEVEL
 };
 
+static struct pci_driver vmw_pci_driver = {
+	.name = VMWGFX_DRIVER_NAME,
+	.id_table = vmw_pci_id_list,
+	.probe = vmw_probe,
+	.remove = vmw_remove,
+	.driver = {
+		.pm = &vmw_pm_ops
+	}
+};
+
 static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	return drm_get_pci_dev(pdev, ent, &driver);
@@ -934,7 +935,7 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 static int __init vmwgfx_init(void)
 {
 	int ret;
-	ret = drm_init(&driver);
+	ret = drm_pci_init(&driver, &vmw_pci_driver);
 	if (ret)
 		DRM_ERROR("Failed initializing DRM.\n");
 	return ret;
@@ -942,7 +943,7 @@ static int __init vmwgfx_init(void)
 
 static void __exit vmwgfx_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &vmw_pci_driver);
 }
 
 module_init(vmwgfx_init);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 29113c9..b3a2cd5 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -345,7 +345,7 @@ static enum drm_connector_status
 	return connector_status_disconnected;
 }
 
-static struct drm_display_mode vmw_ldu_connector_builtin[] = {
+static const struct drm_display_mode vmw_ldu_connector_builtin[] = {
 	/* 640x480@60Hz */
 	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
 		   752, 800, 0, 480, 489, 492, 525, 0,
@@ -429,7 +429,6 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
 	struct drm_device *dev = connector->dev;
 	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct drm_display_mode *mode = NULL;
-	struct drm_display_mode *bmode;
 	struct drm_display_mode prefmode = { DRM_MODE("preferred",
 		DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -459,6 +458,8 @@ static int vmw_ldu_connector_fill_modes(struct drm_connector *connector,
 	}
 
 	for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
+		const struct drm_display_mode *bmode;
+
 		bmode = &vmw_ldu_connector_builtin[i];
 		if (bmode->hdisplay > max_width ||
 		    bmode->vdisplay > max_height)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 2560f01..b7ec405 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -68,9 +68,15 @@ config HID_A4TECH
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
-config HID_ACRUX_FF
-	tristate "ACRUX force feedback"
+config HID_ACRUX
+	tristate "ACRUX game controller support"
 	depends on USB_HID
+	---help---
+	Say Y here if you want to enable support for ACRUX game controllers.
+
+config HID_ACRUX_FF
+	tristate "ACRUX force feedback support"
+	depends on HID_ACRUX
 	select INPUT_FF_MEMLESS
 	---help---
 	Say Y here if you want to enable force feedback support for ACRUX
@@ -140,7 +146,12 @@ config HID_DRAGONRISE
 	tristate "DragonRise Inc. game controller"
 	depends on USB_HID
 	---help---
-	Say Y here if you have DragonRise Inc.game controllers.
+	Say Y here if you have DragonRise Inc. game controllers.
+	These might be branded as:
+	- Tesun USB-703
+	- Media-tech MT1504 "Rogue"
+	- DVTech JS19 "Gear"
+	- Defender Game Master
 
 config DRAGONRISE_FF
 	bool "DragonRise Inc. force feedback"
@@ -160,13 +171,6 @@ config HID_EMS_FF
 	Currently the following devices are known to be supported:
 	 - Trio Linker Plus II
 
-config HID_EGALAX
-	tristate "eGalax multi-touch panel"
-	depends on USB_HID
-	---help---
-	Support for the eGalax dual-touch panels, including the
-	Joojoo and Wetab tablets.
-
 config HID_ELECOM
 	tristate "ELECOM BM084 bluetooth mouse"
 	depends on BT_HIDP
@@ -180,6 +184,14 @@ config HID_EZKEY
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
 
+config HID_KEYTOUCH
+	tristate "Keyoutch HID devices"
+	depends on USB_HID
+	---help---
+	Support for Keytouch HID devices not fully compliant with
+	the specification. Currently supported:
+		- Keytouch IEC 60945
+
 config HID_KYE
 	tristate "Kye/Genius Ergo Mouse" if EXPERT
 	depends on USB_HID
@@ -218,6 +230,12 @@ config HID_KENSINGTON
 	---help---
 	Support for Kensington Slimblade Trackball.
 
+config HID_LCPOWER
+	tristate "LC-Power"
+	depends on USB_HID
+	---help---
+	Support for LC-Power RC1000MCE RF remote control.
+
 config HID_LOGITECH
 	tristate "Logitech devices" if EXPERT
 	depends on USB_HID
@@ -304,8 +322,11 @@ config HID_MULTITOUCH
 	  Say Y here if you have one of the following devices:
 	  - Cypress TrueTouch panels
 	  - Hanvon dual touch panels
+	  - IrTouch Infrared USB panels
 	  - Pixcir dual touch panels
 	  - 'Sensing Win7-TwoFinger' panel by GeneralTouch
+          - eGalax dual-touch panels, including the
+	    Joojoo and Wetab tablets
 
 	  If unsure, say N.
 
@@ -319,10 +340,10 @@ config HID_NTRIG
 	Support for N-Trig touch screen.
 
 config HID_ORTEK
-	tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad"
+	tristate "Ortek PKB-1700/WKB-2000 wireless keyboard and mouse trackpad"
 	depends on USB_HID
 	---help---
-	Support for Ortek WKB-2000 wireless keyboard + mouse trackpad.
+	Support for Ortek PKB-1700/WKB-2000 wireless keyboard + mouse trackpad.
 
 config HID_PANTHERLORD
 	tristate "Pantherlord/GreenAsia game controller"
@@ -417,10 +438,22 @@ config HID_ROCCAT
 	Say Y here if you have a Roccat mouse or keyboard and want OSD or
 	macro execution support.
 
+config HID_ROCCAT_COMMON
+	tristate
+
+config HID_ROCCAT_ARVO
+	tristate "Roccat Arvo keyboard support"
+	depends on USB_HID
+	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
+	---help---
+	Support for Roccat Arvo keyboard.
+
 config HID_ROCCAT_KONE
 	tristate "Roccat Kone Mouse support"
 	depends on USB_HID
 	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat Kone mouse.
 
@@ -428,13 +461,23 @@ config HID_ROCCAT_KONEPLUS
 	tristate "Roccat Kone[+] mouse support"
 	depends on USB_HID
 	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat Kone[+] mouse.
 
+config HID_ROCCAT_KOVAPLUS
+	tristate "Roccat Kova[+] mouse support"
+	depends on USB_HID
+	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
+	---help---
+	Support for Roccat Kova[+] mouse.
+
 config HID_ROCCAT_PYRA
 	tristate "Roccat Pyra mouse support"
 	depends on USB_HID
 	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat Pyra mouse.
 
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 6efc2a0..06c68ae 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -27,21 +27,22 @@ endif
 
 obj-$(CONFIG_HID_3M_PCT)	+= hid-3m-pct.o
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
-obj-$(CONFIG_HID_ACRUX_FF)	+= hid-axff.o
+obj-$(CONFIG_HID_ACRUX)		+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
 obj-$(CONFIG_HID_CANDO)		+= hid-cando.o
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
-obj-$(CONFIG_HID_DRAGONRISE)	+= hid-drff.o
+obj-$(CONFIG_HID_DRAGONRISE)	+= hid-dr.o
 obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
-obj-$(CONFIG_HID_EGALAX)	+= hid-egalax.o
 obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
+obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
+obj-$(CONFIG_HID_LCPOWER)       += hid-lcpower.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
@@ -56,8 +57,11 @@ obj-$(CONFIG_HID_PANTHERLORD)	+= hid-pl.o
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o
+obj-$(CONFIG_HID_ROCCAT_COMMON)	+= hid-roccat-common.o
+obj-$(CONFIG_HID_ROCCAT_ARVO)	+= hid-roccat-arvo.o
 obj-$(CONFIG_HID_ROCCAT_KONE)	+= hid-roccat-kone.o
 obj-$(CONFIG_HID_ROCCAT_KONEPLUS)	+= hid-roccat-koneplus.o
+obj-$(CONFIG_HID_ROCCAT_KOVAPLUS)	+= hid-roccat-kovaplus.o
 obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.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 61aa712..b85744f 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -481,6 +481,12 @@ static const struct hid_device_id apple_devices[] = {
 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c
index e5b961d..b455428 100644
--- a/drivers/hid/hid-axff.c
+++ b/drivers/hid/hid-axff.c
@@ -33,6 +33,8 @@
 #include <linux/hid.h>
 
 #include "hid-ids.h"
+
+#ifdef CONFIG_HID_ACRUX_FF
 #include "usbhid/usbhid.h"
 
 struct axff_device {
@@ -109,6 +111,12 @@ err_free_mem:
 	kfree(axff);
 	return error;
 }
+#else
+static inline int axff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
 
 static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
@@ -139,9 +147,25 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
 			 error);
 	}
 
+	/*
+	 * We need to start polling device right away, otherwise
+	 * it will go into a coma.
+	 */
+	error = hid_hw_open(hdev);
+	if (error) {
+		dev_err(&hdev->dev, "hw open failed\n");
+		return error;
+	}
+
 	return 0;
 }
 
+static void ax_remove(struct hid_device *hdev)
+{
+	hid_hw_close(hdev);
+	hid_hw_stop(hdev);
+}
+
 static const struct hid_device_id ax_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), },
 	{ }
@@ -149,9 +173,10 @@ static const struct hid_device_id ax_devices[] = {
 MODULE_DEVICE_TABLE(hid, ax_devices);
 
 static struct hid_driver ax_driver = {
-	.name = "acrux",
-	.id_table = ax_devices,
-	.probe = ax_probe,
+	.name		= "acrux",
+	.id_table	= ax_devices,
+	.probe		= ax_probe,
+	.remove		= ax_remove,
 };
 
 static int __init ax_init(void)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index d678cf3..e968776 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1159,6 +1159,32 @@ static bool hid_hiddev(struct hid_device *hdev)
 	return !!hid_match_id(hdev, hid_hiddev_list);
 }
 
+
+static ssize_t
+read_report_descriptor(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+	if (off >= hdev->rsize)
+		return 0;
+
+	if (off + count > hdev->rsize)
+		count = hdev->rsize - off;
+
+	memcpy(buf, hdev->rdesc + off, count);
+
+	return count;
+}
+
+static struct bin_attribute dev_bin_attr_report_desc = {
+	.attr = { .name = "report_descriptor", .mode = 0444 },
+	.read = read_report_descriptor,
+	.size = HID_MAX_DESCRIPTOR_SIZE,
+};
+
 int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
 {
 	static const char *types[] = { "Device", "Pointer", "Mouse", "Device",
@@ -1169,6 +1195,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
 	char buf[64];
 	unsigned int i;
 	int len;
+	int ret;
 
 	if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE)
 		connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV);
@@ -1230,6 +1257,11 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
 		bus = "<UNKNOWN>";
 	}
 
+	ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
+	if (ret)
+		hid_warn(hdev,
+			 "can't create sysfs report descriptor attribute err: %d\n", ret);
+
 	hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
 		 buf, bus, hdev->version >> 8, hdev->version & 0xff,
 		 type, hdev->name, hdev->phys);
@@ -1240,6 +1272,7 @@ EXPORT_SYMBOL_GPL(hid_connect);
 
 void hid_disconnect(struct hid_device *hdev)
 {
+	device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
 	if (hdev->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hdev);
 	if (hdev->claimed & HID_CLAIMED_HIDDEV)
@@ -1256,9 +1289,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
-#if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
-#endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
@@ -1302,6 +1333,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -1328,6 +1362,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
@@ -1345,9 +1380,12 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1368,6 +1406,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
@@ -1400,12 +1439,15 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
@@ -1801,6 +1843,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ }
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c
new file mode 100644
index 0000000..61eece4
--- /dev/null
+++ b/drivers/hid/hid-dr.c
@@ -0,0 +1,312 @@
+/*
+ * Force feedback support for DragonRise Inc. game controllers
+ *
+ * From what I have gathered, these devices are mass produced in China and are
+ * distributed under several vendors. They often share the same design as
+ * the original PlayStation DualShock controller.
+ *
+ * 0079:0006 "DragonRise Inc.   Generic   USB  Joystick  "
+ *  - tested with a Tesun USB-703 game controller.
+ *
+ * Copyright (c) 2009 Richard Walmsley <richwalm@gmail.com>
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "hid-ids.h"
+
+#ifdef CONFIG_DRAGONRISE_FF
+#include "usbhid/usbhid.h"
+
+struct drff_device {
+	struct hid_report *report;
+};
+
+static int drff_play(struct input_dev *dev, void *data,
+				 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct drff_device *drff = data;
+	int strong, weak;
+
+	strong = effect->u.rumble.strong_magnitude;
+	weak = effect->u.rumble.weak_magnitude;
+
+	dbg_hid("called with 0x%04x 0x%04x", strong, weak);
+
+	if (strong || weak) {
+		strong = strong * 0xff / 0xffff;
+		weak = weak * 0xff / 0xffff;
+
+		/* While reverse engineering this device, I found that when
+		   this value is set, it causes the strong rumble to function
+		   at a near maximum speed, so we'll bypass it. */
+		if (weak == 0x0a)
+			weak = 0x0b;
+
+		drff->report->field[0]->value[0] = 0x51;
+		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);
+
+		drff->report->field[0]->value[0] = 0xfa;
+		drff->report->field[0]->value[1] = 0xfe;
+	} else {
+		drff->report->field[0]->value[0] = 0xf3;
+		drff->report->field[0]->value[1] = 0x00;
+	}
+
+	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);
+
+	return 0;
+}
+
+static int drff_init(struct hid_device *hid)
+{
+	struct drff_device *drff;
+	struct hid_report *report;
+	struct hid_input *hidinput = list_first_entry(&hid->inputs,
+						struct hid_input, list);
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct input_dev *dev = hidinput->input;
+	int error;
+
+	if (list_empty(report_list)) {
+		hid_err(hid, "no output reports found\n");
+		return -ENODEV;
+	}
+
+	report = list_first_entry(report_list, struct hid_report, list);
+	if (report->maxfield < 1) {
+		hid_err(hid, "no fields in the report\n");
+		return -ENODEV;
+	}
+
+	if (report->field[0]->report_count < 7) {
+		hid_err(hid, "not enough values in the field\n");
+		return -ENODEV;
+	}
+
+	drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL);
+	if (!drff)
+		return -ENOMEM;
+
+	set_bit(FF_RUMBLE, dev->ffbit);
+
+	error = input_ff_create_memless(dev, drff, drff_play);
+	if (error) {
+		kfree(drff);
+		return error;
+	}
+
+	drff->report = report;
+	drff->report->field[0]->value[0] = 0xf3;
+	drff->report->field[0]->value[1] = 0x00;
+	drff->report->field[0]->value[2] = 0x00;
+	drff->report->field[0]->value[3] = 0x00;
+	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_info(hid, "Force Feedback for DragonRise Inc. "
+		 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
+
+	return 0;
+}
+#else
+static inline int drff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
+
+/*
+ * The original descriptor of joystick with PID 0x0011, represented by DVTech PC
+ * JS19. It seems both copied from another device and a result of confusion
+ * either about the specification or about the program used to create the
+ * descriptor. In any case, it's a wonder it works on Windows.
+ *
+ *  Usage Page (Desktop),             ; Generic desktop controls (01h)
+ *  Usage (Joystik),                  ; Joystik (04h, application collection)
+ *  Collection (Application),
+ *    Collection (Logical),
+ *      Report Size (8),
+ *      Report Count (5),
+ *      Logical Minimum (0),
+ *      Logical Maximum (255),
+ *      Physical Minimum (0),
+ *      Physical Maximum (255),
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (Y),                    ; Y (31h, dynamic value)
+ *      Input (Variable),
+ *      Report Size (4),
+ *      Report Count (1),
+ *      Logical Maximum (7),
+ *      Physical Maximum (315),
+ *      Unit (Degrees),
+ *      Usage (00h),
+ *      Input (Variable, Null State),
+ *      Unit,
+ *      Report Size (1),
+ *      Report Count (10),
+ *      Logical Maximum (1),
+ *      Physical Maximum (1),
+ *      Usage Page (Button),          ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (0Ah),
+ *      Input (Variable),
+ *      Usage Page (FF00h),           ; FF00h, vendor-defined
+ *      Report Size (1),
+ *      Report Count (10),
+ *      Logical Maximum (1),
+ *      Physical Maximum (1),
+ *      Usage (01h),
+ *      Input (Variable),
+ *    End Collection,
+ *    Collection (Logical),
+ *      Report Size (8),
+ *      Report Count (4),
+ *      Physical Maximum (255),
+ *      Logical Maximum (255),
+ *      Usage (02h),
+ *      Output (Variable),
+ *    End Collection,
+ *  End Collection
+ */
+
+/* Size of the original descriptor of the PID 0x0011 joystick */
+#define PID0011_RDESC_ORIG_SIZE	101
+
+/* Fixed report descriptor for PID 0x011 joystick */
+static __u8 pid0011_rdesc_fixed[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),           */
+	0x09, 0x04,         /*  Usage (Joystik),                */
+	0xA1, 0x01,         /*  Collection (Application),       */
+	0xA1, 0x02,         /*      Collection (Logical),       */
+	0x14,               /*          Logical Minimum (0),    */
+	0x75, 0x08,         /*          Report Size (8),        */
+	0x95, 0x03,         /*          Report Count (3),       */
+	0x81, 0x01,         /*          Input (Constant),       */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),  */
+	0x95, 0x02,         /*          Report Count (2),       */
+	0x09, 0x30,         /*          Usage (X),              */
+	0x09, 0x31,         /*          Usage (Y),              */
+	0x81, 0x02,         /*          Input (Variable),       */
+	0x75, 0x01,         /*          Report Size (1),        */
+	0x95, 0x04,         /*          Report Count (4),       */
+	0x81, 0x01,         /*          Input (Constant),       */
+	0x25, 0x01,         /*          Logical Maximum (1),    */
+	0x95, 0x0A,         /*          Report Count (10),      */
+	0x05, 0x09,         /*          Usage Page (Button),    */
+	0x19, 0x01,         /*          Usage Minimum (01h),    */
+	0x29, 0x0A,         /*          Usage Maximum (0Ah),    */
+	0x81, 0x02,         /*          Input (Variable),       */
+	0x95, 0x0A,         /*          Report Count (10),      */
+	0x81, 0x01,         /*          Input (Constant),       */
+	0xC0,               /*      End Collection,             */
+	0xC0                /*  End Collection                  */
+};
+
+static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+				unsigned int *rsize)
+{
+	switch (hdev->product) {
+	case 0x0011:
+		if (*rsize == PID0011_RDESC_ORIG_SIZE) {
+			rdesc = pid0011_rdesc_fixed;
+			*rsize = sizeof(pid0011_rdesc_fixed);
+		}
+		break;
+	}
+	return rdesc;
+}
+
+static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe...");
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		goto err;
+	}
+
+	switch (hdev->product) {
+	case 0x0006:
+		ret = drff_init(hdev);
+		if (ret) {
+			dev_err(&hdev->dev, "force feedback init failed\n");
+			hid_hw_stop(hdev);
+			goto err;
+		}
+		break;
+	}
+
+	return 0;
+err:
+	return ret;
+}
+
+static const struct hid_device_id dr_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006),  },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011),  },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, dr_devices);
+
+static struct hid_driver dr_driver = {
+	.name = "dragonrise",
+	.id_table = dr_devices,
+	.report_fixup = dr_report_fixup,
+	.probe = dr_probe,
+};
+
+static int __init dr_init(void)
+{
+	return hid_register_driver(&dr_driver);
+}
+
+static void __exit dr_exit(void)
+{
+	hid_unregister_driver(&dr_driver);
+}
+
+module_init(dr_init);
+module_exit(dr_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-drff.c b/drivers/hid/hid-drff.c
deleted file mode 100644
index afcf3d6..0000000
--- a/drivers/hid/hid-drff.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Force feedback support for DragonRise Inc. game controllers
- *
- * From what I have gathered, these devices are mass produced in China and are
- * distributed under several vendors. They often share the same design as
- * the original PlayStation DualShock controller.
- *
- * 0079:0006 "DragonRise Inc.   Generic   USB  Joystick  "
- *  - tested with a Tesun USB-703 game controller.
- *
- * Copyright (c) 2009 Richard Walmsley <richwalm@gmail.com>
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-
-#include "hid-ids.h"
-
-#ifdef CONFIG_DRAGONRISE_FF
-#include "usbhid/usbhid.h"
-
-struct drff_device {
-	struct hid_report *report;
-};
-
-static int drff_play(struct input_dev *dev, void *data,
-				 struct ff_effect *effect)
-{
-	struct hid_device *hid = input_get_drvdata(dev);
-	struct drff_device *drff = data;
-	int strong, weak;
-
-	strong = effect->u.rumble.strong_magnitude;
-	weak = effect->u.rumble.weak_magnitude;
-
-	dbg_hid("called with 0x%04x 0x%04x", strong, weak);
-
-	if (strong || weak) {
-		strong = strong * 0xff / 0xffff;
-		weak = weak * 0xff / 0xffff;
-
-		/* While reverse engineering this device, I found that when
-		   this value is set, it causes the strong rumble to function
-		   at a near maximum speed, so we'll bypass it. */
-		if (weak == 0x0a)
-			weak = 0x0b;
-
-		drff->report->field[0]->value[0] = 0x51;
-		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);
-
-		drff->report->field[0]->value[0] = 0xfa;
-		drff->report->field[0]->value[1] = 0xfe;
-	} else {
-		drff->report->field[0]->value[0] = 0xf3;
-		drff->report->field[0]->value[1] = 0x00;
-	}
-
-	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);
-
-	return 0;
-}
-
-static int drff_init(struct hid_device *hid)
-{
-	struct drff_device *drff;
-	struct hid_report *report;
-	struct hid_input *hidinput = list_first_entry(&hid->inputs,
-						struct hid_input, list);
-	struct list_head *report_list =
-			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct input_dev *dev = hidinput->input;
-	int error;
-
-	if (list_empty(report_list)) {
-		hid_err(hid, "no output reports found\n");
-		return -ENODEV;
-	}
-
-	report = list_first_entry(report_list, struct hid_report, list);
-	if (report->maxfield < 1) {
-		hid_err(hid, "no fields in the report\n");
-		return -ENODEV;
-	}
-
-	if (report->field[0]->report_count < 7) {
-		hid_err(hid, "not enough values in the field\n");
-		return -ENODEV;
-	}
-
-	drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL);
-	if (!drff)
-		return -ENOMEM;
-
-	set_bit(FF_RUMBLE, dev->ffbit);
-
-	error = input_ff_create_memless(dev, drff, drff_play);
-	if (error) {
-		kfree(drff);
-		return error;
-	}
-
-	drff->report = report;
-	drff->report->field[0]->value[0] = 0xf3;
-	drff->report->field[0]->value[1] = 0x00;
-	drff->report->field[0]->value[2] = 0x00;
-	drff->report->field[0]->value[3] = 0x00;
-	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_info(hid, "Force Feedback for DragonRise Inc. "
-		 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
-
-	return 0;
-}
-#else
-static inline int drff_init(struct hid_device *hid)
-{
-	return 0;
-}
-#endif
-
-static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-
-	dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe...");
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		hid_err(hdev, "parse failed\n");
-		goto err;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
-	if (ret) {
-		hid_err(hdev, "hw start failed\n");
-		goto err;
-	}
-
-	drff_init(hdev);
-
-	return 0;
-err:
-	return ret;
-}
-
-static const struct hid_device_id dr_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006),  },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, dr_devices);
-
-static struct hid_driver dr_driver = {
-	.name = "dragonrise",
-	.id_table = dr_devices,
-	.probe = dr_probe,
-};
-
-static int __init dr_init(void)
-{
-	return hid_register_driver(&dr_driver);
-}
-
-static void __exit dr_exit(void)
-{
-	hid_unregister_driver(&dr_driver);
-}
-
-module_init(dr_init);
-module_exit(dr_exit);
-MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-egalax.c b/drivers/hid/hid-egalax.c
deleted file mode 100644
index 03bee19..0000000
--- a/drivers/hid/hid-egalax.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- *  HID driver for eGalax dual-touch panels
- *
- *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
- *  Copyright (c) 2010 Canonical, Ltd.
- *
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/input/mt.h>
-#include <linux/slab.h>
-#include "usbhid/usbhid.h"
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("eGalax dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-#define MAX_SLOTS		2
-
-/* estimated signal-to-noise ratios */
-#define SN_MOVE			4096
-#define SN_PRESSURE		32
-
-struct egalax_data {
-	int valid;
-	int slot;
-	int touch;
-	int x, y, z;
-};
-
-static void set_abs(struct input_dev *input, unsigned int code,
-		    struct hid_field *field, int snratio)
-{
-	int fmin = field->logical_minimum;
-	int fmax = field->logical_maximum;
-	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
-	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
-}
-
-static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	struct input_dev *input = hi->input;
-
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			field->logical_maximum = 32760;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
-			/* touchscreen emulation */
-			set_abs(input, ABS_X, field, SN_MOVE);
-			return 1;
-		case HID_GD_Y:
-			field->logical_maximum = 32760;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
-			/* touchscreen emulation */
-			set_abs(input, ABS_Y, field, SN_MOVE);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_TIPSWITCH:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			input_set_capability(input, EV_KEY, BTN_TOUCH);
-			return 1;
-		case HID_DG_INRANGE:
-		case HID_DG_CONFIDENCE:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-			return -1;
-		case HID_DG_CONTACTID:
-			input_mt_init_slots(input, MAX_SLOTS);
-			return 1;
-		case HID_DG_TIPPRESSURE:
-			field->logical_minimum = 0;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_PRESSURE);
-			set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
-			/* touchscreen emulation */
-			set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
-			return 1;
-		}
-		return 0;
-	}
-
-	/* ignore others (from other reports we won't get anyway) */
-	return -1;
-}
-
-static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	/* tell hid-input to skip setup of these event types */
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		set_bit(usage->type, hi->input->evbit);
-	return -1;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
-{
-	input_mt_slot(input, td->slot);
-	input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
-	if (td->touch) {
-		input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-		input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-		input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
-	}
-	input_mt_report_pointer_emulation(input, true);
-}
-
-static int egalax_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct egalax_data *td = hid_get_drvdata(hid);
-
-	/* Note, eGalax has two product lines: the first is resistive and
-	 * uses a standard parallel multitouch protocol (product ID ==
-	 * 48xx).  The second is capacitive and uses an unusual "serial"
-	 * protocol with a different message for each multitouch finger
-	 * (product ID == 72xx).
-	 */
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = value;
-			break;
-		case HID_DG_CONFIDENCE:
-			/* avoid interference from generic hidinput handling */
-			break;
-		case HID_DG_TIPSWITCH:
-			td->touch = value;
-			break;
-		case HID_DG_TIPPRESSURE:
-			td->z = value;
-			break;
-		case HID_DG_CONTACTID:
-			td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			/* this is the last field in a finger */
-			if (td->valid)
-				egalax_filter_event(td, input);
-			break;
-		case HID_DG_CONTACTCOUNT:
-			/* touch emulation: this is the last field in a frame */
-			break;
-
-		default:
-			/* fallback to the generic hidinput handling */
-			return 0;
-		}
-	}
-
-	/* we have handled the hidinput part, now remains hiddev */
-	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-		hid->hiddev_hid_event(hid, field, usage, value);
-
-	return 1;
-}
-
-static int egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct egalax_data *td;
-	struct hid_report *report;
-
-	td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
-	if (!td) {
-		hid_err(hdev, "cannot allocate eGalax data\n");
-		return -ENOMEM;
-	}
-	hid_set_drvdata(hdev, td);
-
-	ret = hid_parse(hdev);
-	if (ret)
-		goto end;
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret)
-		goto end;
-
-	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; 
-	if (report) {
-		report->field[0]->value[0] = 2;
-		usbhid_submit_report(hdev, report, USB_DIR_OUT);
-	}
-
-end:
-	if (ret)
-		kfree(td);
-
-	return ret;
-}
-
-static void egalax_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id egalax_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, egalax_devices);
-
-static const struct hid_usage_id egalax_grabbed_usages[] = {
-	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
-};
-
-static struct hid_driver egalax_driver = {
-	.name = "egalax-touch",
-	.id_table = egalax_devices,
-	.probe = egalax_probe,
-	.remove = egalax_remove,
-	.input_mapping = egalax_input_mapping,
-	.input_mapped = egalax_input_mapped,
-	.usage_table = egalax_grabbed_usages,
-	.event = egalax_event,
-};
-
-static int __init egalax_init(void)
-{
-	return hid_register_driver(&egalax_driver);
-}
-
-static void __exit egalax_exit(void)
-{
-	hid_unregister_driver(&egalax_driver);
-}
-
-module_init(egalax_init);
-module_exit(egalax_exit);
-
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c
index 3975e03..e88b951 100644
--- a/drivers/hid/hid-gyration.c
+++ b/drivers/hid/hid-gyration.c
@@ -43,6 +43,11 @@ static int gyration_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 	case 0x048: gy_map_key_clear(KEY_MEDIA);	break;
 	case 0x049: gy_map_key_clear(KEY_CAMERA);	break;
 	case 0x04a: gy_map_key_clear(KEY_VIDEO);	break;
+	case 0x05a: gy_map_key_clear(KEY_TEXT);		break;
+	case 0x05b: gy_map_key_clear(KEY_RED);		break;
+	case 0x05c: gy_map_key_clear(KEY_GREEN);	break;
+	case 0x05d: gy_map_key_clear(KEY_YELLOW);	break;
+	case 0x05e: gy_map_key_clear(KEY_BLUE);		break;
 
 	default:
 		return 0;
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 92a0d61..65ac53d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -103,6 +103,9 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI	0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO	0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS	0x0247
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
@@ -333,6 +336,9 @@
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
 
+#define USB_VENDOR_ID_IRTOUCHSYSTEMS	0x6615
+#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB	0x0070
+
 #define USB_VENDOR_ID_JESS		0x0c45
 #define USB_DEVICE_ID_JESS_YUREX	0x1010
 
@@ -345,6 +351,9 @@
 #define USB_VENDOR_ID_KWORLD		0x1b80
 #define USB_DEVICE_ID_KWORLD_RADIO_FM700	0xd700
 
+#define USB_VENDOR_ID_KEYTOUCH		0x0926
+#define USB_DEVICE_ID_KEYTOUCH_IEC	0x3333
+
 #define USB_VENDOR_ID_KYE		0x0458
 #define USB_DEVICE_ID_KYE_ERGO_525V	0x0087
 #define USB_DEVICE_ID_KYE_GPEN_560	0x5003
@@ -352,6 +361,9 @@
 #define USB_VENDOR_ID_LABTEC		0x1020
 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD	0x0006
 
+#define USB_VENDOR_ID_LCPOWER		0x1241
+#define USB_DEVICE_ID_LCPOWER_LC1000	0xf767
+
 #define USB_VENDOR_ID_LD		0x0f11
 #define USB_DEVICE_ID_LD_CASSY		0x1000
 #define USB_DEVICE_ID_LD_POCKETCASSY	0x1010
@@ -383,6 +395,7 @@
 #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG	0xc293
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
+#define USB_DEVICE_ID_LOGITECH_DFP_WHEEL	0xc298
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL	0xc299
 #define USB_DEVICE_ID_LOGITECH_WII_WHEEL	0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
@@ -466,6 +479,7 @@
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
 #define USB_VENDOR_ID_ORTEK		0x05a4
+#define USB_DEVICE_ID_ORTEK_PKB1700	0x1700
 #define USB_DEVICE_ID_ORTEK_WKB2000	0x2000
 
 #define USB_VENDOR_ID_PANJIT		0x134c
@@ -496,8 +510,10 @@
 #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN	0x3001
 
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
+#define USB_DEVICE_ID_ROCCAT_ARVO	0x30d4
 #define USB_DEVICE_ID_ROCCAT_KONE	0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS	0x2d51
+#define USB_DEVICE_ID_ROCCAT_KOVAPLUS	0x2d50
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED	0x2c24
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS	0x2cf6
 
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 7f552bf..33dde87 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -290,14 +290,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
 		goto ignore;
 	}
 
-	if (field->report_type == HID_FEATURE_REPORT) {
-		if (device->driver->feature_mapping) {
-			device->driver->feature_mapping(device, hidinput, field,
-				usage);
-		}
-		goto ignore;
-	}
-
 	if (device->driver->input_mapping) {
 		int ret = device->driver->input_mapping(device, hidinput, field,
 				usage, &bit, &max);
@@ -835,6 +827,24 @@ static void hidinput_close(struct input_dev *dev)
 	hid_hw_close(hid);
 }
 
+static void report_features(struct hid_device *hid)
+{
+	struct hid_driver *drv = hid->driver;
+	struct hid_report_enum *rep_enum;
+	struct hid_report *rep;
+	int i, j;
+
+	if (!drv->feature_mapping)
+		return;
+
+	rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
+	list_for_each_entry(rep, &rep_enum->report_list, list)
+		for (i = 0; i < rep->maxfield; i++)
+			for (j = 0; j < rep->field[i]->maxusage; j++)
+				drv->feature_mapping(hid, rep->field[i],
+						     rep->field[i]->usage + j);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -863,7 +873,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 			return -1;
 	}
 
-	for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) {
+	report_features(hid);
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
 		if (k == HID_OUTPUT_REPORT &&
 			hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
 			continue;
@@ -888,8 +900,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 					hid->ll_driver->hidinput_input_event;
 				input_dev->open = hidinput_open;
 				input_dev->close = hidinput_close;
-				input_dev->setkeycode_new = hidinput_setkeycode;
-				input_dev->getkeycode_new = hidinput_getkeycode;
+				input_dev->setkeycode = hidinput_setkeycode;
+				input_dev->getkeycode = hidinput_getkeycode;
 
 				input_dev->name = hid->name;
 				input_dev->phys = hid->phys;
@@ -928,6 +940,7 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
 	return 0;
 
 out_cleanup:
+	list_del(&hidinput->list);
 	input_free_device(hidinput->input);
 	kfree(hidinput);
 out_unwind:
diff --git a/drivers/hid/hid-keytouch.c b/drivers/hid/hid-keytouch.c
new file mode 100644
index 0000000..07cd825
--- /dev/null
+++ b/drivers/hid/hid-keytouch.c
@@ -0,0 +1,66 @@
+/*
+ *  HID driver for Keytouch devices not fully compliant with HID standard
+ *
+ *  Copyright (c) 2011 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+/* Replace the broken report descriptor of this device with rather
+ * a default one */
+static __u8 keytouch_fixed_rdesc[] = {
+0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15,
+0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08,
+0x81, 0x01, 0x95, 0x03, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91,
+0x02, 0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00,
+0x26, 0xff, 0x00, 0x05, 0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00, 0xc0
+};
+
+static __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int *rsize)
+{
+	hid_info(hdev, "fixing up Keytouch IEC report descriptor\n");
+
+	rdesc = keytouch_fixed_rdesc;
+	*rsize = sizeof(keytouch_fixed_rdesc);
+
+	return rdesc;
+}
+
+static const struct hid_device_id keytouch_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, keytouch_devices);
+
+static struct hid_driver keytouch_driver = {
+	.name = "keytouch",
+	.id_table = keytouch_devices,
+	.report_fixup = keytouch_report_fixup,
+};
+
+static int __init keytouch_init(void)
+{
+	return hid_register_driver(&keytouch_driver);
+}
+
+static void __exit keytouch_exit(void)
+{
+	hid_unregister_driver(&keytouch_driver);
+}
+
+module_init(keytouch_init);
+module_exit(keytouch_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jiri Kosina");
diff --git a/drivers/hid/hid-lcpower.c b/drivers/hid/hid-lcpower.c
new file mode 100644
index 0000000..c4fe9bd0
--- /dev/null
+++ b/drivers/hid/hid-lcpower.c
@@ -0,0 +1,70 @@
+/*
+ *  HID driver for LC Power Model RC1000MCE
+ *
+ *  Copyright (c) 2011 Chris Schlund 
+ *  based on hid-topseed module
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+#define ts_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
+					EV_KEY, (c))
+static int ts_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+		struct hid_field *field, struct hid_usage *usage,
+		unsigned long **bit, int *max)
+{
+	if ((usage->hid & HID_USAGE_PAGE) != 0x0ffbc0000)
+		return 0;
+
+	switch (usage->hid & HID_USAGE) {
+        case 0x046: ts_map_key_clear(KEY_YELLOW);         break;
+        case 0x047: ts_map_key_clear(KEY_GREEN);          break;
+        case 0x049: ts_map_key_clear(KEY_BLUE);           break;
+        case 0x04a: ts_map_key_clear(KEY_RED);		  break;
+        case 0x00d: ts_map_key_clear(KEY_HOME);           break;
+        case 0x025: ts_map_key_clear(KEY_TV);             break;
+        case 0x048: ts_map_key_clear(KEY_VCR);            break;
+        case 0x024: ts_map_key_clear(KEY_MENU);           break;
+        default:
+        return 0;
+	}
+
+	return 1;
+}
+
+static const struct hid_device_id ts_devices[] = {
+	{ HID_USB_DEVICE( USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ts_devices);
+
+static struct hid_driver ts_driver = {
+	.name = "LC RC1000MCE",
+	.id_table = ts_devices,
+	.input_mapping = ts_input_mapping,
+};
+
+static int __init ts_init(void)
+{
+	return hid_register_driver(&ts_driver);
+}
+
+static void __exit ts_exit(void)
+{
+	hid_unregister_driver(&ts_driver);
+}
+
+module_init(ts_init);
+module_exit(ts_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c
index aef4104..3da9040 100644
--- a/drivers/hid/hid-lg.c
+++ b/drivers/hid/hid-lg.c
@@ -377,6 +377,8 @@ static const struct hid_device_id lg_devices[] = {
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
 		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
+		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
 		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
index 698e645..318cc40 100644
--- a/drivers/hid/hid-magicmouse.c
+++ b/drivers/hid/hid-magicmouse.c
@@ -258,7 +258,7 @@ static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tda
 		input_report_abs(input, ABS_MT_TRACKING_ID, id);
 		input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2);
 		input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2);
-		input_report_abs(input, ABS_MT_ORIENTATION, orientation);
+		input_report_abs(input, ABS_MT_ORIENTATION, -orientation);
 		input_report_abs(input, ABS_MT_POSITION_X, x);
 		input_report_abs(input, ABS_MT_POSITION_Y, y);
 
@@ -397,7 +397,7 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
 		input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0);
 		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0);
 		input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0);
-		input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0);
+		input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
 
 		/* Note: Touch Y position from the device is inverted relative
 		 * to how pointer motion is reported (and relative to how USB
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 07d3183..ee01e65 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -5,6 +5,12 @@
  *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
  *  Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France
  *
+ *  This code is partly based on hid-egalax.c:
+ *
+ *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
+ *  Copyright (c) 2010 Canonical, Ltd.
+ *
  */
 
 /*
@@ -24,6 +30,7 @@
 
 
 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
 MODULE_DESCRIPTION("HID multitouch panels");
 MODULE_LICENSE("GPL");
 
@@ -36,6 +43,7 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	(1 << 3)
 #define MT_QUIRK_VALID_IS_INRANGE	(1 << 4)
 #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 5)
+#define MT_QUIRK_EGALAX_XYZ_FIXUP	(1 << 6)
 
 struct mt_slot {
 	__s32 x, y, p, w, h;
@@ -65,10 +73,11 @@ struct mt_class {
 };
 
 /* classes of device behavior */
-#define MT_CLS_DEFAULT	1
-#define MT_CLS_DUAL1	2
-#define MT_CLS_DUAL2	3
-#define MT_CLS_CYPRESS	4
+#define MT_CLS_DEFAULT				1
+#define MT_CLS_DUAL_INRANGE_CONTACTID		2
+#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	3
+#define MT_CLS_CYPRESS				4
+#define MT_CLS_EGALAX				5
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -104,13 +113,13 @@ static int find_slot_from_contactid(struct mt_device *td)
 
 struct mt_class mt_classes[] = {
 	{ .name = MT_CLS_DEFAULT,
-		.quirks = MT_QUIRK_VALID_IS_INRANGE,
+		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
 		.maxcontacts = 10 },
-	{ .name = MT_CLS_DUAL1,
+	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
 			MT_QUIRK_SLOT_IS_CONTACTID,
 		.maxcontacts = 2 },
-	{ .name = MT_CLS_DUAL2,
+	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
 			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
 		.maxcontacts = 2 },
@@ -119,10 +128,18 @@ struct mt_class mt_classes[] = {
 			MT_QUIRK_CYPRESS,
 		.maxcontacts = 10 },
 
+	{ .name = MT_CLS_EGALAX,
+		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
+			MT_QUIRK_VALID_IS_INRANGE |
+			MT_QUIRK_EGALAX_XYZ_FIXUP,
+		.maxcontacts = 2,
+		.sn_move = 4096,
+		.sn_pressure = 32,
+	},
 	{ }
 };
 
-static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
+static void mt_feature_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
 	if (usage->hid == HID_DG_INPUTMODE) {
@@ -146,11 +163,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 {
 	struct mt_device *td = hid_get_drvdata(hdev);
 	struct mt_class *cls = td->mtclass;
+	__s32 quirks = cls->quirks;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_GENDESK:
 		switch (usage->hid) {
 		case HID_GD_X:
+			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
+				field->logical_maximum = 32760;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_X);
 			set_abs(hi->input, ABS_MT_POSITION_X, field,
@@ -160,6 +181,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			td->last_slot_field = usage->hid;
 			return 1;
 		case HID_GD_Y:
+			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
+				field->logical_maximum = 32760;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_Y);
 			set_abs(hi->input, ABS_MT_POSITION_Y, field,
@@ -203,6 +226,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 			td->last_slot_field = usage->hid;
 			return 1;
 		case HID_DG_TIPPRESSURE:
+			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
+				field->logical_minimum = 0;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_PRESSURE);
 			set_abs(hi->input, ABS_MT_PRESSURE, field,
@@ -363,8 +388,11 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
 			return 0;
 		}
 
-		if (usage->hid == td->last_slot_field)
+		if (usage->hid == td->last_slot_field) {
 			mt_complete_slot(td);
+			if (!td->last_field_index)
+				mt_emit_event(td, field->hidinput->input);
+		}
 
 		if (field->index == td->last_field_index
 			&& td->num_received >= td->num_expected)
@@ -466,18 +494,42 @@ static const struct hid_device_id mt_devices[] = {
 			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 
 	/* GeneralTouch panel */
-	{ .driver_data = MT_CLS_DUAL2,
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
 		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
 			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 
+	/* IRTOUCH panels */
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
+		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
+			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
+
 	/* PixCir-based panels */
-	{ .driver_data = MT_CLS_DUAL1,
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
 		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
 			USB_DEVICE_ID_HANVON_MULTITOUCH) },
-	{ .driver_data = MT_CLS_DUAL1,
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
+	/* Resistive eGalax devices */
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
+
+	/* Capacitive eGalax devices */
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c
index beb4034..9fae2eb 100644
--- a/drivers/hid/hid-ntrig.c
+++ b/drivers/hid/hid-ntrig.c
@@ -110,6 +110,36 @@ static int ntrig_version_string(unsigned char *raw, char *buf)
 	return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e);
 }
 
+static inline int ntrig_get_mode(struct hid_device *hdev)
+{
+	struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT].
+				    report_id_hash[0x0d];
+
+	if (!report)
+		return -EINVAL;
+
+	usbhid_submit_report(hdev, report, USB_DIR_IN);
+	usbhid_wait_io(hdev);
+	return (int)report->field[0]->value[0];
+}
+
+static inline void ntrig_set_mode(struct hid_device *hdev, const int mode)
+{
+	struct hid_report *report;
+	__u8 mode_commands[4] = { 0xe, 0xf, 0x1b, 0x10 };
+
+	if (mode < 0 || mode > 3)
+		return;
+
+	report = hdev->report_enum[HID_FEATURE_REPORT].
+		 report_id_hash[mode_commands[mode]];
+
+	if (!report)
+		return;
+
+	usbhid_submit_report(hdev, report, USB_DIR_IN);
+}
+
 static void ntrig_report_version(struct hid_device *hdev)
 {
 	int ret;
@@ -539,277 +569,288 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 static int ntrig_event (struct hid_device *hid, struct hid_field *field,
 			struct hid_usage *usage, __s32 value)
 {
-	struct input_dev *input = field->hidinput->input;
 	struct ntrig_data *nd = hid_get_drvdata(hid);
+	struct input_dev *input;
+
+	/* Skip processing if not a claimed input */
+	if (!(hid->claimed & HID_CLAIMED_INPUT))
+		goto not_claimed_input;
+
+	/* This function is being called before the structures are fully
+	 * initialized */
+	if(!(field->hidinput && field->hidinput->input))
+		return -EINVAL;
+
+	input = field->hidinput->input;
 
 	/* No special handling needed for the pen */
 	if (field->application == HID_DG_PEN)
 		return 0;
 
-        if (hid->claimed & HID_CLAIMED_INPUT) {
-		switch (usage->hid) {
-		case 0xff000001:
-			/* Tag indicating the start of a multitouch group */
-			nd->reading_mt = 1;
-			nd->first_contact_touch = 0;
-			break;
-		case HID_DG_TIPSWITCH:
-			nd->tipswitch = value;
-			/* Prevent emission of touch until validated */
-			return 1;
-		case HID_DG_CONFIDENCE:
-			nd->confidence = value;
-			break;
-		case HID_GD_X:
-			nd->x = value;
-			/* Clear the contact footer */
-			nd->mt_foot_count = 0;
-			break;
-		case HID_GD_Y:
-			nd->y = value;
-			break;
-		case HID_DG_CONTACTID:
-			nd->id = value;
-			break;
-		case HID_DG_WIDTH:
-			nd->w = value;
-			break;
-		case HID_DG_HEIGHT:
-			nd->h = value;
+	switch (usage->hid) {
+	case 0xff000001:
+		/* Tag indicating the start of a multitouch group */
+		nd->reading_mt = 1;
+		nd->first_contact_touch = 0;
+		break;
+	case HID_DG_TIPSWITCH:
+		nd->tipswitch = value;
+		/* Prevent emission of touch until validated */
+		return 1;
+	case HID_DG_CONFIDENCE:
+		nd->confidence = value;
+		break;
+	case HID_GD_X:
+		nd->x = value;
+		/* Clear the contact footer */
+		nd->mt_foot_count = 0;
+		break;
+	case HID_GD_Y:
+		nd->y = value;
+		break;
+	case HID_DG_CONTACTID:
+		nd->id = value;
+		break;
+	case HID_DG_WIDTH:
+		nd->w = value;
+		break;
+	case HID_DG_HEIGHT:
+		nd->h = value;
+		/*
+		 * when in single touch mode, this is the last
+		 * report received in a finger event. We want
+		 * to emit a normal (X, Y) position
+		 */
+		if (!nd->reading_mt) {
 			/*
-			 * when in single touch mode, this is the last
-			 * report received in a finger event. We want
-			 * to emit a normal (X, Y) position
+			 * TipSwitch indicates the presence of a
+			 * finger in single touch mode.
 			 */
-			if (!nd->reading_mt) {
-				/*
-				 * TipSwitch indicates the presence of a
-				 * finger in single touch mode.
-				 */
-				input_report_key(input, BTN_TOUCH,
-						 nd->tipswitch);
-				input_report_key(input, BTN_TOOL_DOUBLETAP,
-						 nd->tipswitch);
-				input_event(input, EV_ABS, ABS_X, nd->x);
-				input_event(input, EV_ABS, ABS_Y, nd->y);
-			}
+			input_report_key(input, BTN_TOUCH,
+					 nd->tipswitch);
+			input_report_key(input, BTN_TOOL_DOUBLETAP,
+					 nd->tipswitch);
+			input_event(input, EV_ABS, ABS_X, nd->x);
+			input_event(input, EV_ABS, ABS_Y, nd->y);
+		}
+		break;
+	case 0xff000002:
+		/*
+		 * we receive this when the device is in multitouch
+		 * mode. The first of the three values tagged with
+		 * this usage tells if the contact point is real
+		 * or a placeholder
+		 */
+
+		/* Shouldn't get more than 4 footer packets, so skip */
+		if (nd->mt_foot_count >= 4)
 			break;
-		case 0xff000002:
-			/*
-			 * we receive this when the device is in multitouch
-			 * mode. The first of the three values tagged with
-			 * this usage tells if the contact point is real
-			 * or a placeholder
-			 */
 
-			/* Shouldn't get more than 4 footer packets, so skip */
-			if (nd->mt_foot_count >= 4)
-				break;
+		nd->mt_footer[nd->mt_foot_count++] = value;
 
-			nd->mt_footer[nd->mt_foot_count++] = value;
+		/* if the footer isn't complete break */
+		if (nd->mt_foot_count != 4)
+			break;
 
-			/* if the footer isn't complete break */
-			if (nd->mt_foot_count != 4)
-				break;
+		/* Pen activity signal. */
+		if (nd->mt_footer[2]) {
+			/*
+			 * When the pen deactivates touch, we see a
+			 * bogus frame with ContactCount > 0.
+			 * We can
+			 * save a bit of work by ensuring act_state < 0
+			 * even if deactivation slack is turned off.
+			 */
+			nd->act_state = deactivate_slack - 1;
+			nd->confidence = 0;
+			break;
+		}
 
-			/* Pen activity signal. */
-			if (nd->mt_footer[2]) {
-				/*
-				 * When the pen deactivates touch, we see a
-				 * bogus frame with ContactCount > 0.
-				 * We can
-				 * save a bit of work by ensuring act_state < 0
-				 * even if deactivation slack is turned off.
-				 */
-				nd->act_state = deactivate_slack - 1;
+		/*
+		 * The first footer value indicates the presence of a
+		 * finger.
+		 */
+		if (nd->mt_footer[0]) {
+			/*
+			 * We do not want to process contacts under
+			 * the size threshold, but do not want to
+			 * ignore them for activation state
+			 */
+			if (nd->w < nd->min_width ||
+			    nd->h < nd->min_height)
 				nd->confidence = 0;
-				break;
-			}
+		} else
+			break;
 
+		if (nd->act_state > 0) {
 			/*
-			 * The first footer value indicates the presence of a
-			 * finger.
+			 * Contact meets the activation size threshold
 			 */
-			if (nd->mt_footer[0]) {
-				/*
-				 * We do not want to process contacts under
-				 * the size threshold, but do not want to
-				 * ignore them for activation state
-				 */
-				if (nd->w < nd->min_width ||
-				    nd->h < nd->min_height)
-					nd->confidence = 0;
-			} else
-				break;
-
-			if (nd->act_state > 0) {
-				/*
-				 * Contact meets the activation size threshold
-				 */
-				if (nd->w >= nd->activation_width &&
-				    nd->h >= nd->activation_height) {
-					if (nd->id)
-						/*
-						 * first contact, activate now
-						 */
-						nd->act_state = 0;
-					else {
-						/*
-						 * avoid corrupting this frame
-						 * but ensure next frame will
-						 * be active
-						 */
-						nd->act_state = 1;
-						break;
-					}
-				} else
+			if (nd->w >= nd->activation_width &&
+			    nd->h >= nd->activation_height) {
+				if (nd->id)
 					/*
-					 * Defer adjusting the activation state
-					 * until the end of the frame.
+					 * first contact, activate now
 					 */
+					nd->act_state = 0;
+				else {
+					/*
+					 * avoid corrupting this frame
+					 * but ensure next frame will
+					 * be active
+					 */
+					nd->act_state = 1;
 					break;
-			}
-
-			/* Discarding this contact */
-			if (!nd->confidence)
-				break;
-
-			/* emit a normal (X, Y) for the first point only */
-			if (nd->id == 0) {
+				}
+			} else
 				/*
-				 * TipSwitch is superfluous in multitouch
-				 * mode.  The footer events tell us
-				 * if there is a finger on the screen or
-				 * not.
+				 * Defer adjusting the activation state
+				 * until the end of the frame.
 				 */
-				nd->first_contact_touch = nd->confidence;
-				input_event(input, EV_ABS, ABS_X, nd->x);
-				input_event(input, EV_ABS, ABS_Y, nd->y);
-			}
+				break;
+		}
 
-			/* Emit MT events */
-			input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
-			input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
+		/* Discarding this contact */
+		if (!nd->confidence)
+			break;
 
+		/* emit a normal (X, Y) for the first point only */
+		if (nd->id == 0) {
 			/*
-			 * Translate from height and width to size
-			 * and orientation.
+			 * TipSwitch is superfluous in multitouch
+			 * mode.  The footer events tell us
+			 * if there is a finger on the screen or
+			 * not.
 			 */
-			if (nd->w > nd->h) {
-				input_event(input, EV_ABS,
-						ABS_MT_ORIENTATION, 1);
-				input_event(input, EV_ABS,
-						ABS_MT_TOUCH_MAJOR, nd->w);
-				input_event(input, EV_ABS,
-						ABS_MT_TOUCH_MINOR, nd->h);
-			} else {
-				input_event(input, EV_ABS,
-						ABS_MT_ORIENTATION, 0);
-				input_event(input, EV_ABS,
-						ABS_MT_TOUCH_MAJOR, nd->h);
-				input_event(input, EV_ABS,
-						ABS_MT_TOUCH_MINOR, nd->w);
-			}
-			input_mt_sync(field->hidinput->input);
-			break;
+			nd->first_contact_touch = nd->confidence;
+			input_event(input, EV_ABS, ABS_X, nd->x);
+			input_event(input, EV_ABS, ABS_Y, nd->y);
+		}
 
-		case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
-			if (!nd->reading_mt) /* Just to be sure */
-				break;
+		/* Emit MT events */
+		input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
+		input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
+
+		/*
+		 * Translate from height and width to size
+		 * and orientation.
+		 */
+		if (nd->w > nd->h) {
+			input_event(input, EV_ABS,
+					ABS_MT_ORIENTATION, 1);
+			input_event(input, EV_ABS,
+					ABS_MT_TOUCH_MAJOR, nd->w);
+			input_event(input, EV_ABS,
+					ABS_MT_TOUCH_MINOR, nd->h);
+		} else {
+			input_event(input, EV_ABS,
+					ABS_MT_ORIENTATION, 0);
+			input_event(input, EV_ABS,
+					ABS_MT_TOUCH_MAJOR, nd->h);
+			input_event(input, EV_ABS,
+					ABS_MT_TOUCH_MINOR, nd->w);
+		}
+		input_mt_sync(field->hidinput->input);
+		break;
 
-			nd->reading_mt = 0;
+	case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
+		if (!nd->reading_mt) /* Just to be sure */
+			break;
 
+		nd->reading_mt = 0;
+
+
+		/*
+		 * Activation state machine logic:
+		 *
+		 * Fundamental states:
+		 *	state >  0: Inactive
+		 *	state <= 0: Active
+		 *	state <  -deactivate_slack:
+		 *		 Pen termination of touch
+		 *
+		 * Specific values of interest
+		 *	state == activate_slack
+		 *		 no valid input since the last reset
+		 *
+		 *	state == 0
+		 *		 general operational state
+		 *
+		 *	state == -deactivate_slack
+		 *		 read sufficient empty frames to accept
+		 *		 the end of input and reset
+		 */
+
+		if (nd->act_state > 0) { /* Currently inactive */
+			if (value)
+				/*
+				 * Consider each live contact as
+				 * evidence of intentional activity.
+				 */
+				nd->act_state = (nd->act_state > value)
+						? nd->act_state - value
+						: 0;
+			else
+				/*
+				 * Empty frame before we hit the
+				 * activity threshold, reset.
+				 */
+				nd->act_state = nd->activate_slack;
 
 			/*
-			 * Activation state machine logic:
-			 *
-			 * Fundamental states:
-			 *	state >  0: Inactive
-			 *	state <= 0: Active
-			 *	state <  -deactivate_slack:
-			 *		 Pen termination of touch
-			 *
-			 * Specific values of interest
-			 *	state == activate_slack
-			 *		 no valid input since the last reset
-			 *
-			 *	state == 0
-			 *		 general operational state
-			 *
-			 *	state == -deactivate_slack
-			 *		 read sufficient empty frames to accept
-			 *		 the end of input and reset
+			 * Entered this block inactive and no
+			 * coordinates sent this frame, so hold off
+			 * on button state.
 			 */
-
-			if (nd->act_state > 0) { /* Currently inactive */
-				if (value)
-					/*
-					 * Consider each live contact as
-					 * evidence of intentional activity.
-					 */
-					nd->act_state = (nd->act_state > value)
-							? nd->act_state - value
-							: 0;
-				else
-					/*
-					 * Empty frame before we hit the
-					 * activity threshold, reset.
-					 */
-					nd->act_state = nd->activate_slack;
-
+			break;
+		} else { /* Currently active */
+			if (value && nd->act_state >=
+				     nd->deactivate_slack)
 				/*
-				 * Entered this block inactive and no
-				 * coordinates sent this frame, so hold off
-				 * on button state.
+				 * Live point: clear accumulated
+				 * deactivation count.
 				 */
-				break;
-			} else { /* Currently active */
-				if (value && nd->act_state >=
-					     nd->deactivate_slack)
-					/*
-					 * Live point: clear accumulated
-					 * deactivation count.
-					 */
-					nd->act_state = 0;
-				else if (nd->act_state <= nd->deactivate_slack)
-					/*
-					 * We've consumed the deactivation
-					 * slack, time to deactivate and reset.
-					 */
-					nd->act_state =
-						nd->activate_slack;
-				else { /* Move towards deactivation */
-					nd->act_state--;
-					break;
-				}
-			}
-
-			if (nd->first_contact_touch && nd->act_state <= 0) {
+				nd->act_state = 0;
+			else if (nd->act_state <= nd->deactivate_slack)
 				/*
-				 * Check to see if we're ready to start
-				 * emitting touch events.
-				 *
-				 * Note: activation slack will decrease over
-				 * the course of the frame, and it will be
-				 * inconsistent from the start to the end of
-				 * the frame.  However if the frame starts
-				 * with slack, first_contact_touch will still
-				 * be 0 and we will not get to this point.
+				 * We've consumed the deactivation
+				 * slack, time to deactivate and reset.
 				 */
-				input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
-				input_report_key(input, BTN_TOUCH, 1);
-			} else {
-				input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
-				input_report_key(input, BTN_TOUCH, 0);
+				nd->act_state =
+					nd->activate_slack;
+			else { /* Move towards deactivation */
+				nd->act_state--;
+				break;
 			}
-			break;
+		}
 
-		default:
-			/* fall-back to the generic hidinput handling */
-			return 0;
+		if (nd->first_contact_touch && nd->act_state <= 0) {
+			/*
+			 * Check to see if we're ready to start
+			 * emitting touch events.
+			 *
+			 * Note: activation slack will decrease over
+			 * the course of the frame, and it will be
+			 * inconsistent from the start to the end of
+			 * the frame.  However if the frame starts
+			 * with slack, first_contact_touch will still
+			 * be 0 and we will not get to this point.
+			 */
+			input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
+			input_report_key(input, BTN_TOUCH, 1);
+		} else {
+			input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
+			input_report_key(input, BTN_TOUCH, 0);
 		}
+		break;
+
+	default:
+		/* fall-back to the generic hidinput handling */
+		return 0;
 	}
 
+not_claimed_input:
+
 	/* we have handled the hidinput part, now remains hiddev */
 	if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_hid_event)
 		hid->hiddev_hid_event(hid, field, usage, value);
@@ -826,7 +867,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	struct hid_report *report;
 
 	if (id->driver_data)
-		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+		hdev->quirks |= HID_QUIRK_MULTI_INPUT
+				| HID_QUIRK_NO_INIT_REPORTS;
 
 	nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
 	if (!nd) {
@@ -893,8 +935,19 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	/* This is needed for devices with more recent firmware versions */
 	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
-	if (report)
-		usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	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);
+
+		/*
+		 * Sanity check: if the current mode is invalid reset it to
+		 * something reasonable.
+		 */
+		if (ntrig_get_mode(hdev) >= 4)
+			ntrig_set_mode(hdev, 3);
+	}
 
 	ntrig_report_version(hdev);
 
diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c
index e90edfc..f9b7dd4 100644
--- a/drivers/hid/hid-ortek.c
+++ b/drivers/hid/hid-ortek.c
@@ -1,7 +1,6 @@
 /*
- *  HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad).
- *  Fixes LogicalMaximum error in USB report description, see
- *  http://bugzilla.kernel.org/show_bug.cgi?id=14787
+ *  HID driver for Ortek PKB-1700/WKB-2000 (wireless keyboard + mouse trackpad).
+ *  Fixes LogicalMaximum error in HID report description.
  *
  *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
  */
@@ -30,6 +29,7 @@ static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 }
 
 static const struct hid_device_id ortek_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ }
 };
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index de9cf21b..657da5a 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -944,6 +944,7 @@ static int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *
 	}
 
 	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bdev = backlight_device_register(dev_name(dev), dev, data,
 			&picolcd_blops, &props);
diff --git a/drivers/hid/hid-roccat-arvo.c b/drivers/hid/hid-roccat-arvo.c
new file mode 100644
index 0000000..2307471
--- /dev/null
+++ b/drivers/hid/hid-roccat-arvo.c
@@ -0,0 +1,450 @@
+/*
+ * Roccat Arvo driver for Linux
+ *
+ * Copyright (c) 2011 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 Arvo is a gamer keyboard with 5 macro keys that can be configured in
+ * 5 profiles.
+ */
+
+#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-arvo.h"
+
+static struct class *arvo_class;
+
+static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_mode_key temp_buf;
+	int retval;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+			&temp_buf, sizeof(struct arvo_mode_key));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.state);
+}
+
+static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_mode_key temp_buf;
+	unsigned long state;
+	int retval;
+
+	retval = strict_strtoul(buf, 10, &state);
+	if (retval)
+		return retval;
+
+	temp_buf.command = ARVO_COMMAND_MODE_KEY;
+	temp_buf.state = state;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+			&temp_buf, sizeof(struct arvo_mode_key));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_key_mask temp_buf;
+	int retval;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+			&temp_buf, sizeof(struct arvo_key_mask));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.key_mask);
+}
+
+static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_key_mask temp_buf;
+	unsigned long key_mask;
+	int retval;
+
+	retval = strict_strtoul(buf, 10, &key_mask);
+	if (retval)
+		return retval;
+
+	temp_buf.command = ARVO_COMMAND_KEY_MASK;
+	temp_buf.key_mask = key_mask;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+			&temp_buf, sizeof(struct arvo_key_mask));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+/* retval is 1-5 on success, < 0 on error */
+static int arvo_get_actual_profile(struct usb_device *usb_dev)
+{
+	struct arvo_actual_profile temp_buf;
+	int retval;
+
+	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+			&temp_buf, sizeof(struct arvo_actual_profile));
+
+	if (retval)
+		return retval;
+
+	return temp_buf.actual_profile;
+}
+
+static ssize_t arvo_sysfs_show_actual_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", arvo->actual_profile);
+}
+
+static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_actual_profile temp_buf;
+	unsigned long profile;
+	int retval;
+
+	retval = strict_strtoul(buf, 10, &profile);
+	if (retval)
+		return retval;
+
+	temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE;
+	temp_buf.actual_profile = profile;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+			&temp_buf, sizeof(struct arvo_actual_profile));
+	if (!retval) {
+		arvo->actual_profile = profile;
+		retval = size;
+	}
+	mutex_unlock(&arvo->arvo_lock);
+	return retval;
+}
+
+static ssize_t arvo_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 arvo_device *arvo = 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(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, command, buf, real_size);
+	mutex_unlock(&arvo->arvo_lock);
+
+	return (retval ? retval : real_size);
+}
+
+static ssize_t arvo_sysfs_read(struct file *fp,
+		struct kobject *kobj, void *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 arvo_device *arvo = 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(&arvo->arvo_lock);
+	retval = roccat_common_receive(usb_dev, command, buf, real_size);
+	mutex_unlock(&arvo->arvo_lock);
+
+	return (retval ? retval : real_size);
+}
+
+static ssize_t arvo_sysfs_write_button(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return arvo_sysfs_write(fp, kobj, buf, off, count,
+			sizeof(struct arvo_button), ARVO_USB_COMMAND_BUTTON);
+}
+
+static ssize_t arvo_sysfs_read_info(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return arvo_sysfs_read(fp, kobj, buf, off, count,
+			sizeof(struct arvo_info), ARVO_USB_COMMAND_INFO);
+}
+
+
+static struct device_attribute arvo_attributes[] = {
+	__ATTR(mode_key, 0660,
+			arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key),
+	__ATTR(key_mask, 0660,
+			arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask),
+	__ATTR(actual_profile, 0660,
+			arvo_sysfs_show_actual_profile,
+			arvo_sysfs_set_actual_profile),
+	__ATTR_NULL
+};
+
+static struct bin_attribute arvo_bin_attributes[] = {
+	{
+		.attr = { .name = "button", .mode = 0220 },
+		.size = sizeof(struct arvo_button),
+		.write = arvo_sysfs_write_button
+	},
+	{
+		.attr = { .name = "info", .mode = 0440 },
+		.size = sizeof(struct arvo_info),
+		.read = arvo_sysfs_read_info
+	},
+	__ATTR_NULL
+};
+
+static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
+		struct arvo_device *arvo)
+{
+	int retval;
+
+	mutex_init(&arvo->arvo_lock);
+
+	retval = arvo_get_actual_profile(usb_dev);
+	if (retval < 0)
+		return retval;
+	arvo->actual_profile = retval;
+
+	return 0;
+}
+
+static int arvo_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 arvo_device *arvo;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_KEYBOARD) {
+		hid_set_drvdata(hdev, NULL);
+		return 0;
+	}
+
+	arvo = kzalloc(sizeof(*arvo), GFP_KERNEL);
+	if (!arvo) {
+		hid_err(hdev, "can't alloc device descriptor\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, arvo);
+
+	retval = arvo_init_arvo_device_struct(usb_dev, arvo);
+	if (retval) {
+		hid_err(hdev, "couldn't init struct arvo_device\n");
+		goto exit_free;
+	}
+
+	retval = roccat_connect(arvo_class, hdev,
+			sizeof(struct arvo_roccat_report));
+	if (retval < 0) {
+		hid_err(hdev, "couldn't init char dev\n");
+	} else {
+		arvo->chrdev_minor = retval;
+		arvo->roccat_claimed = 1;
+	}
+
+	return 0;
+exit_free:
+	kfree(arvo);
+	return retval;
+}
+
+static void arvo_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct arvo_device *arvo;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_KEYBOARD)
+		return;
+
+	arvo = hid_get_drvdata(hdev);
+	if (arvo->roccat_claimed)
+		roccat_disconnect(arvo->chrdev_minor);
+	kfree(arvo);
+}
+
+static int arvo_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 = arvo_init_specials(hdev);
+	if (retval) {
+		hid_err(hdev, "couldn't install keyboard\n");
+		goto exit_stop;
+	}
+
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void arvo_remove(struct hid_device *hdev)
+{
+	arvo_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static void arvo_report_to_chrdev(struct arvo_device const *arvo,
+		u8 const *data)
+{
+	struct arvo_special_report const *special_report;
+	struct arvo_roccat_report roccat_report;
+
+	special_report = (struct arvo_special_report const *)data;
+
+	roccat_report.profile = arvo->actual_profile;
+	roccat_report.button = special_report->event &
+			ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON;
+	if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) ==
+			ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS)
+		roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS;
+	else
+		roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE;
+
+	roccat_report_event(arvo->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+}
+
+static int arvo_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	struct arvo_device *arvo = hid_get_drvdata(hdev);
+
+	if (size != 3)
+		return 0;
+
+	if (arvo->roccat_claimed)
+		arvo_report_to_chrdev(arvo, data);
+
+	return 0;
+}
+
+static const struct hid_device_id arvo_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, arvo_devices);
+
+static struct hid_driver arvo_driver = {
+	.name = "arvo",
+	.id_table = arvo_devices,
+	.probe = arvo_probe,
+	.remove = arvo_remove,
+	.raw_event = arvo_raw_event
+};
+
+static int __init arvo_init(void)
+{
+	int retval;
+
+	arvo_class = class_create(THIS_MODULE, "arvo");
+	if (IS_ERR(arvo_class))
+		return PTR_ERR(arvo_class);
+	arvo_class->dev_attrs = arvo_attributes;
+	arvo_class->dev_bin_attrs = arvo_bin_attributes;
+
+	retval = hid_register_driver(&arvo_driver);
+	if (retval)
+		class_destroy(arvo_class);
+	return retval;
+}
+
+static void __exit arvo_exit(void)
+{
+	hid_unregister_driver(&arvo_driver);
+	class_destroy(arvo_class);
+}
+
+module_init(arvo_init);
+module_exit(arvo_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Arvo driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-arvo.h b/drivers/hid/hid-roccat-arvo.h
new file mode 100644
index 0000000..d284a78
--- /dev/null
+++ b/drivers/hid/hid-roccat-arvo.h
@@ -0,0 +1,98 @@
+#ifndef __HID_ROCCAT_ARVO_H
+#define __HID_ROCCAT_ARVO_H
+
+/*
+ * Copyright (c) 2011 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>
+
+struct arvo_mode_key { /* 2 bytes */
+	uint8_t command; /* ARVO_COMMAND_MODE_KEY */
+	uint8_t state;
+} __packed;
+
+struct arvo_button {
+	uint8_t unknown[24];
+} __packed;
+
+struct arvo_info {
+	uint8_t unknown[8];
+} __packed;
+
+struct arvo_key_mask { /* 2 bytes */
+	uint8_t command; /* ARVO_COMMAND_KEY_MASK */
+	uint8_t key_mask;
+} __packed;
+
+/* selected profile is persistent */
+struct arvo_actual_profile { /* 2 bytes */
+	uint8_t command; /* ARVO_COMMAND_ACTUAL_PROFILE */
+	uint8_t actual_profile;
+} __packed;
+
+enum arvo_commands {
+	ARVO_COMMAND_MODE_KEY = 0x3,
+	ARVO_COMMAND_BUTTON = 0x4,
+	ARVO_COMMAND_INFO = 0x5,
+	ARVO_COMMAND_KEY_MASK = 0x6,
+	ARVO_COMMAND_ACTUAL_PROFILE = 0x7,
+};
+
+enum arvo_usb_commands {
+	ARVO_USB_COMMAND_MODE_KEY = 0x303,
+	/*
+	 * read/write
+	 * Read uses both index bytes as profile/key indexes
+	 * Write has index 0, profile/key is determined by payload
+	 */
+	ARVO_USB_COMMAND_BUTTON = 0x304,
+	ARVO_USB_COMMAND_INFO = 0x305,
+	ARVO_USB_COMMAND_KEY_MASK = 0x306,
+	ARVO_USB_COMMAND_ACTUAL_PROFILE = 0x307,
+};
+
+struct arvo_special_report {
+	uint8_t unknown1; /* always 0x01 */
+	uint8_t event;
+	uint8_t unknown2; /* always 0x70 */
+} __packed;
+
+enum arvo_special_report_events {
+	ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS = 0x10,
+	ARVO_SPECIAL_REPORT_EVENT_ACTION_RELEASE = 0x0,
+};
+
+enum arvo_special_report_event_masks {
+	ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION = 0xf0,
+	ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON = 0x0f,
+};
+
+struct arvo_roccat_report {
+	uint8_t profile;
+	uint8_t button;
+	uint8_t action;
+} __packed;
+
+enum arvo_roccat_report_action {
+	ARVO_ROCCAT_REPORT_ACTION_RELEASE = 0,
+	ARVO_ROCCAT_REPORT_ACTION_PRESS = 1,
+};
+
+struct arvo_device {
+	int roccat_claimed;
+	int chrdev_minor;
+
+	struct mutex arvo_lock;
+
+	int actual_profile;
+};
+
+#endif
diff --git a/drivers/hid/hid-roccat-common.c b/drivers/hid/hid-roccat-common.c
new file mode 100644
index 0000000..13b1eb0
--- /dev/null
+++ b/drivers/hid/hid-roccat-common.c
@@ -0,0 +1,62 @@
+/*
+ * Roccat common functions for device specific drivers
+ *
+ * Copyright (c) 2011 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/slab.h>
+#include "hid-roccat-common.h"
+
+int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+		void *data, uint size)
+{
+	char *buf;
+	int len;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			USB_REQ_CLEAR_FEATURE,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	memcpy(data, buf, size);
+	kfree(buf);
+	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+EXPORT_SYMBOL_GPL(roccat_common_receive);
+
+int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+		void const *data, uint size)
+{
+	char *buf;
+	int len;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	memcpy(buf, data, size);
+
+	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			USB_REQ_SET_CONFIGURATION,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	kfree(buf);
+	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+EXPORT_SYMBOL_GPL(roccat_common_send);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat common driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-common.h b/drivers/hid/hid-roccat-common.h
new file mode 100644
index 0000000..fe45fae
--- /dev/null
+++ b/drivers/hid/hid-roccat-common.h
@@ -0,0 +1,23 @@
+#ifndef __HID_ROCCAT_COMMON_H
+#define __HID_ROCCAT_COMMON_H
+
+/*
+ * Copyright (c) 2011 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/usb.h>
+#include <linux/types.h>
+
+int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+		void *data, uint size);
+int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+		void const *data, uint size);
+
+#endif
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c
index cbd8cc4..a57838d 100644
--- a/drivers/hid/hid-roccat-kone.c
+++ b/drivers/hid/hid-roccat-kone.c
@@ -28,11 +28,11 @@
 #include <linux/device.h>
 #include <linux/input.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/hid-roccat.h>
 #include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
 #include "hid-roccat-kone.h"
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -58,12 +58,8 @@ static void kone_set_settings_checksum(struct kone_settings *settings)
  */
 static int kone_check_write(struct usb_device *usb_dev)
 {
-	int len;
-	unsigned char *data;
-
-	data = kmalloc(1, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	int retval;
+	uint8_t data;
 
 	do {
 		/*
@@ -72,56 +68,36 @@ static int kone_check_write(struct usb_device *usb_dev)
 		 */
 		msleep(80);
 
-		len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-				USB_REQ_CLEAR_FEATURE,
-				USB_TYPE_CLASS | USB_RECIP_INTERFACE |
-				USB_DIR_IN,
-				kone_command_confirm_write, 0, data, 1,
-				USB_CTRL_SET_TIMEOUT);
-
-		if (len != 1) {
-			kfree(data);
-			return -EIO;
-		}
+		retval = roccat_common_receive(usb_dev,
+				kone_command_confirm_write, &data, 1);
+		if (retval)
+			return retval;
 
 		/*
 		 * value of 3 seems to mean something like
 		 * "not finished yet, but it looks good"
 		 * So check again after a moment.
 		 */
-	} while (*data == 3);
+	} while (data == 3);
 
-	if (*data == 1) { /* everything alright */
-		kfree(data);
+	if (data == 1) /* everything alright */
 		return 0;
-	} else { /* unknown answer */
-		hid_err(usb_dev, "got retval %d when checking write\n", *data);
-		kfree(data);
-		return -EIO;
-	}
+
+	/* unknown answer */
+	hid_err(usb_dev, "got retval %d when checking write\n", data);
+	return -EIO;
 }
 
 /*
  * Reads settings from mouse and stores it in @buf
- * @buf has to be alloced with GFP_KERNEL
  * On success returns 0
  * On failure returns errno
  */
 static int kone_get_settings(struct usb_device *usb_dev,
 		struct kone_settings *buf)
 {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			kone_command_settings, 0, buf,
-			sizeof(struct kone_settings), USB_CTRL_SET_TIMEOUT);
-
-	if (len != sizeof(struct kone_settings))
-		return -EIO;
-
-	return 0;
+	return roccat_common_receive(usb_dev, kone_command_settings, buf,
+			sizeof(struct kone_settings));
 }
 
 /*
@@ -132,22 +108,12 @@ static int kone_get_settings(struct usb_device *usb_dev,
 static int kone_set_settings(struct usb_device *usb_dev,
 		struct kone_settings const *settings)
 {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			kone_command_settings, 0, (char *)settings,
-			sizeof(struct kone_settings),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (len != sizeof(struct kone_settings))
-		return -EIO;
-
-	if (kone_check_write(usb_dev))
-		return -EIO;
-
-	return 0;
+	int retval;
+	retval = roccat_common_send(usb_dev, kone_command_settings,
+			settings, sizeof(struct kone_settings));
+	if (retval)
+		return retval;
+	return kone_check_write(usb_dev);
 }
 
 /*
@@ -193,7 +159,7 @@ static int kone_set_profile(struct usb_device *usb_dev,
 	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
 			USB_REQ_SET_CONFIGURATION,
 			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			kone_command_profile, number, (char *)profile,
+			kone_command_profile, number, (void *)profile,
 			sizeof(struct kone_profile),
 			USB_CTRL_SET_TIMEOUT);
 
@@ -213,24 +179,15 @@ static int kone_set_profile(struct usb_device *usb_dev,
  */
 static int kone_get_weight(struct usb_device *usb_dev, int *result)
 {
-	int len;
-	uint8_t *data;
+	int retval;
+	uint8_t data;
 
-	data = kmalloc(1, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
 
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			kone_command_weight, 0, data, 1, USB_CTRL_SET_TIMEOUT);
+	if (retval)
+		return retval;
 
-	if (len != 1) {
-		kfree(data);
-		return -EIO;
-	}
-	*result = (int)*data;
-	kfree(data);
+	*result = (int)data;
 	return 0;
 }
 
@@ -241,25 +198,15 @@ static int kone_get_weight(struct usb_device *usb_dev, int *result)
  */
 static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
 {
-	int len;
-	unsigned char *data;
-
-	data = kmalloc(2, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	int retval;
+	uint16_t data;
 
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			kone_command_firmware_version, 0, data, 2,
-			USB_CTRL_SET_TIMEOUT);
+	retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
+			&data, 2);
+	if (retval)
+		return retval;
 
-	if (len != 2) {
-		kfree(data);
-		return -EIO;
-	}
-	*result = le16_to_cpu(*data);
-	kfree(data);
+	*result = le16_to_cpu(data);
 	return 0;
 }
 
@@ -435,23 +382,9 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev,
 
 static int kone_tcu_command(struct usb_device *usb_dev, int number)
 {
-	int len;
-	char *value;
-
-	value = kmalloc(1, GFP_KERNEL);
-	if (!value)
-		return -ENOMEM;
-
-	*value = number;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			kone_command_calibrate, 0, value, 1,
-			USB_CTRL_SET_TIMEOUT);
-
-	kfree(value);
-	return ((len != 1) ? -EIO : 0);
+	unsigned char value;
+	value = number;
+	return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
 }
 
 /*
@@ -727,7 +660,8 @@ static int kone_init_specials(struct hid_device *hdev)
 			goto exit_free;
 		}
 
-		retval = roccat_connect(kone_class, hdev);
+		retval = roccat_connect(kone_class, hdev,
+				sizeof(struct kone_roccat_report));
 		if (retval < 0) {
 			hid_err(hdev, "couldn't init char dev\n");
 			/* be tolerant about not getting chrdev */
@@ -827,8 +761,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone,
 		roccat_report.value = event->value;
 		roccat_report.key = 0;
 		roccat_report_event(kone->chrdev_minor,
-				(uint8_t *)&roccat_report,
-				sizeof(struct kone_roccat_report));
+				(uint8_t *)&roccat_report);
 		break;
 	case kone_mouse_event_call_overlong_macro:
 		if (event->value == kone_keystroke_action_press) {
@@ -836,8 +769,7 @@ static void kone_report_to_chrdev(struct kone_device const *kone,
 			roccat_report.value = kone->actual_profile;
 			roccat_report.key = event->macro_key;
 			roccat_report_event(kone->chrdev_minor,
-					(uint8_t *)&roccat_report,
-					sizeof(struct kone_roccat_report));
+					(uint8_t *)&roccat_report);
 		}
 		break;
 	}
@@ -912,8 +844,8 @@ static int __init kone_init(void)
 
 static void __exit kone_exit(void)
 {
-	class_destroy(kone_class);
 	hid_unregister_driver(&kone_driver);
+	class_destroy(kone_class);
 }
 
 module_init(kone_init);
diff --git a/drivers/hid/hid-roccat-koneplus.c b/drivers/hid/hid-roccat-koneplus.c
index 1608c8d..33eec74 100644
--- a/drivers/hid/hid-roccat-koneplus.c
+++ b/drivers/hid/hid-roccat-koneplus.c
@@ -19,11 +19,11 @@
 #include <linux/device.h>
 #include <linux/input.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/hid-roccat.h>
 #include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
 #include "hid-roccat-koneplus.h"
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -39,110 +39,63 @@ static void koneplus_profile_activated(struct koneplus_device *koneplus,
 static int koneplus_send_control(struct usb_device *usb_dev, uint value,
 		enum koneplus_control_requests request)
 {
-	int len;
-	struct koneplus_control *control;
+	struct koneplus_control control;
 
 	if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
 			request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
 			value > 4)
 		return -EINVAL;
 
-	control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
-	if (!control)
-		return -ENOMEM;
+	control.command = KONEPLUS_COMMAND_CONTROL;
+	control.value = value;
+	control.request = request;
 
-	control->command = KONEPLUS_COMMAND_CONTROL;
-	control->value = value;
-	control->request = request;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			KONEPLUS_USB_COMMAND_CONTROL, 0, control,
-			sizeof(struct koneplus_control),
-			USB_CTRL_SET_TIMEOUT);
-
-	kfree(control);
-
-	if (len != sizeof(struct koneplus_control))
-		return len;
-
-	return 0;
-}
-
-static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
-		void *buf, uint size) {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
-
-	return (len != size) ? -EIO : 0;
+	return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+			&control, sizeof(struct koneplus_control));
 }
 
 static int koneplus_receive_control_status(struct usb_device *usb_dev)
 {
 	int retval;
-	struct koneplus_control *control;
-
-	control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
-	if (!control)
-		return -ENOMEM;
+	struct koneplus_control control;
 
 	do {
-		retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
-				control, sizeof(struct koneplus_control));
+		retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+				&control, sizeof(struct koneplus_control));
 
 		/* check if we get a completely wrong answer */
 		if (retval)
-			goto out;
+			return retval;
 
-		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) {
-			retval = 0;
-			goto out;
-		}
+		if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK)
+			return 0;
 
 		/* indicates that hardware needs some more time to complete action */
-		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
+		if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
 			msleep(500); /* windows driver uses 1000 */
 			continue;
 		}
 
 		/* seems to be critical - replug necessary */
-		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) {
-			retval = -EINVAL;
-			goto out;
-		}
-
-		dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
-				"unknown response value 0x%x\n", control->value);
-		retval = -EINVAL;
-		goto out;
+		if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
+			return -EINVAL;
 
+		hid_err(usb_dev, "koneplus_receive_control_status: "
+				"unknown response value 0x%x\n", control.value);
+		return -EINVAL;
 	} while (1);
-out:
-	kfree(control);
-	return retval;
 }
 
 static int koneplus_send(struct usb_device *usb_dev, uint command,
-		void *buf, uint size) {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
-
-	if (len != size)
-		return -EIO;
+		void const *buf, uint size)
+{
+	int retval;
 
-	if (koneplus_receive_control_status(usb_dev))
-		return -EIO;
+	retval = roccat_common_send(usb_dev, command, buf, size);
+	if (retval)
+		return retval;
 
-	return 0;
+	return koneplus_receive_control_status(usb_dev);
 }
 
 static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
@@ -167,7 +120,7 @@ static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
 static int koneplus_get_info(struct usb_device *usb_dev,
 		struct koneplus_info *buf)
 {
-	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
+	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
 			buf, sizeof(struct koneplus_info));
 }
 
@@ -181,7 +134,7 @@ static int koneplus_get_profile_settings(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 
-	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
 			buf, sizeof(struct koneplus_profile_settings));
 }
 
@@ -189,7 +142,7 @@ static int koneplus_set_profile_settings(struct usb_device *usb_dev,
 		struct koneplus_profile_settings const *settings)
 {
 	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
-			(void *)settings, sizeof(struct koneplus_profile_settings));
+			settings, sizeof(struct koneplus_profile_settings));
 }
 
 static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -202,7 +155,7 @@ static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
 	if (retval)
 		return retval;
 
-	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
 			buf, sizeof(struct koneplus_profile_buttons));
 }
 
@@ -210,27 +163,19 @@ static int koneplus_set_profile_buttons(struct usb_device *usb_dev,
 		struct koneplus_profile_buttons const *buttons)
 {
 	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
-			(void *)buttons, sizeof(struct koneplus_profile_buttons));
+			buttons, sizeof(struct koneplus_profile_buttons));
 }
 
 /* retval is 0-4 on success, < 0 on error */
 static int koneplus_get_startup_profile(struct usb_device *usb_dev)
 {
-	struct koneplus_startup_profile *buf;
+	struct koneplus_startup_profile buf;
 	int retval;
 
-	buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL);
+	retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
+			&buf, sizeof(struct koneplus_startup_profile));
 
-	retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
-			buf, sizeof(struct koneplus_startup_profile));
-
-	if (retval)
-		goto out;
-
-	retval = buf->startup_profile;
-out:
-	kfree(buf);
-	return retval;
+	return retval ? retval : buf.startup_profile;
 }
 
 static int koneplus_set_startup_profile(struct usb_device *usb_dev,
@@ -243,7 +188,7 @@ static int koneplus_set_startup_profile(struct usb_device *usb_dev,
 	buf.startup_profile = startup_profile;
 
 	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
-			(char *)&buf, sizeof(struct koneplus_profile_buttons));
+			&buf, sizeof(struct koneplus_profile_buttons));
 }
 
 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -256,11 +201,14 @@ static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
 	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(&koneplus->koneplus_lock);
-	retval = koneplus_receive(usb_dev, command, buf, real_size);
+	retval = roccat_common_receive(usb_dev, command, buf, real_size);
 	mutex_unlock(&koneplus->koneplus_lock);
 
 	if (retval)
@@ -283,7 +231,7 @@ static ssize_t koneplus_sysfs_write(struct file *fp, struct kobject *kobj,
 		return -EINVAL;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	retval = koneplus_send(usb_dev, command, (void *)buf, real_size);
+	retval = koneplus_send(usb_dev, command, buf, real_size);
 	mutex_unlock(&koneplus->koneplus_lock);
 
 	if (retval)
@@ -347,7 +295,7 @@ static ssize_t koneplus_sysfs_read_profilex_settings(struct file *fp,
 		count = sizeof(struct koneplus_profile_settings) - off;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
+	memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
 			count);
 	mutex_unlock(&koneplus->koneplus_lock);
 
@@ -406,7 +354,7 @@ static ssize_t koneplus_sysfs_read_profilex_buttons(struct file *fp,
 		count = sizeof(struct koneplus_profile_buttons) - off;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
+	memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
 			count);
 	mutex_unlock(&koneplus->koneplus_lock);
 
@@ -512,7 +460,7 @@ static struct device_attribute koneplus_attributes[] = {
 
 static struct bin_attribute koneplus_bin_attributes[] = {
 	{
-		.attr = { .name = "sensor", .mode = 0220 },
+		.attr = { .name = "sensor", .mode = 0660 },
 		.size = sizeof(struct koneplus_sensor),
 		.read = koneplus_sysfs_read_sensor,
 		.write = koneplus_sysfs_write_sensor
@@ -609,11 +557,13 @@ static int koneplus_init_koneplus_device_struct(struct usb_device *usb_dev,
 		struct koneplus_device *koneplus)
 {
 	int retval, i;
-	static uint wait = 70; /* device will freeze with just 60 */
+	static uint wait = 100; /* device will freeze with just 60 */
 
 	mutex_init(&koneplus->koneplus_lock);
 
 	koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
+	if (koneplus->startup_profile < 0)
+		return koneplus->startup_profile;
 
 	msleep(wait);
 	retval = koneplus_get_info(usb_dev, &koneplus->info);
@@ -651,21 +601,21 @@ static int koneplus_init_specials(struct hid_device *hdev)
 
 		koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
 		if (!koneplus) {
-			dev_err(&hdev->dev, "can't alloc device descriptor\n");
+			hid_err(hdev, "can't alloc device descriptor\n");
 			return -ENOMEM;
 		}
 		hid_set_drvdata(hdev, koneplus);
 
 		retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
 		if (retval) {
-			dev_err(&hdev->dev,
-					"couldn't init struct koneplus_device\n");
+			hid_err(hdev, "couldn't init struct koneplus_device\n");
 			goto exit_free;
 		}
 
-		retval = roccat_connect(koneplus_class, hdev);
+		retval = roccat_connect(koneplus_class, hdev,
+				sizeof(struct koneplus_roccat_report));
 		if (retval < 0) {
-			dev_err(&hdev->dev, "couldn't init char dev\n");
+			hid_err(hdev, "couldn't init char dev\n");
 		} else {
 			koneplus->chrdev_minor = retval;
 			koneplus->roccat_claimed = 1;
@@ -701,19 +651,19 @@ static int koneplus_probe(struct hid_device *hdev,
 
 	retval = hid_parse(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto exit;
 	}
 
 	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (retval) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto exit;
 	}
 
 	retval = koneplus_init_specials(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "couldn't install mouse\n");
+		hid_err(hdev, "couldn't install mouse\n");
 		goto exit_stop;
 	}
 
@@ -769,8 +719,7 @@ static void koneplus_report_to_chrdev(struct koneplus_device const *koneplus,
 	roccat_report.data2 = button_report->data2;
 	roccat_report.profile = koneplus->actual_profile + 1;
 	roccat_report_event(koneplus->chrdev_minor,
-			(uint8_t const *)&roccat_report,
-			sizeof(struct koneplus_roccat_report));
+			(uint8_t const *)&roccat_report);
 }
 
 static int koneplus_raw_event(struct hid_device *hdev,
@@ -825,8 +774,8 @@ static int __init koneplus_init(void)
 
 static void __exit koneplus_exit(void)
 {
-	class_destroy(koneplus_class);
 	hid_unregister_driver(&koneplus_driver);
+	class_destroy(koneplus_class);
 }
 
 module_init(koneplus_init);
diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c
new file mode 100644
index 0000000..984be2f
--- /dev/null
+++ b/drivers/hid/hid-roccat-kovaplus.c
@@ -0,0 +1,715 @@
+/*
+ * Roccat Kova[+] driver for Linux
+ *
+ * Copyright (c) 2011 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 Kova[+] is a bigger version of the Pyra with two more side buttons.
+ */
+
+#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-kovaplus.h"
+
+static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+
+static struct class *kovaplus_class;
+
+static uint kovaplus_convert_event_cpi(uint value)
+{
+	return (value == 7 ? 4 : (value == 4 ? 3 : value));
+}
+
+static void kovaplus_profile_activated(struct kovaplus_device *kovaplus,
+		uint new_profile_index)
+{
+	kovaplus->actual_profile = new_profile_index;
+	kovaplus->actual_cpi = kovaplus->profile_settings[new_profile_index].cpi_startup_level;
+	kovaplus->actual_x_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_x;
+	kovaplus->actual_y_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_y;
+}
+
+static int kovaplus_send_control(struct usb_device *usb_dev, uint value,
+		enum kovaplus_control_requests request)
+{
+	int retval;
+	struct kovaplus_control control;
+
+	if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
+			request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
+			value > 4)
+		return -EINVAL;
+
+	control.command = KOVAPLUS_COMMAND_CONTROL;
+	control.value = value;
+	control.request = request;
+
+	retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+			&control, sizeof(struct kovaplus_control));
+
+	return retval;
+}
+
+static int kovaplus_receive_control_status(struct usb_device *usb_dev)
+{
+	int retval;
+	struct kovaplus_control control;
+
+	do {
+		retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+				&control, sizeof(struct kovaplus_control));
+
+		/* check if we get a completely wrong answer */
+		if (retval)
+			return retval;
+
+		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK)
+			return 0;
+
+		/* indicates that hardware needs some more time to complete action */
+		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) {
+			msleep(500); /* windows driver uses 1000 */
+			continue;
+		}
+
+		/* seems to be critical - replug necessary */
+		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
+			return -EINVAL;
+
+		hid_err(usb_dev, "kovaplus_receive_control_status: "
+				"unknown response value 0x%x\n", control.value);
+		return -EINVAL;
+	} while (1);
+}
+
+static int kovaplus_send(struct usb_device *usb_dev, uint command,
+		void const *buf, uint size)
+{
+	int retval;
+
+	retval = roccat_common_send(usb_dev, command, buf, size);
+	if (retval)
+		return retval;
+
+	msleep(100);
+
+	return kovaplus_receive_control_status(usb_dev);
+}
+
+static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
+		enum kovaplus_control_requests request)
+{
+	return kovaplus_send_control(usb_dev, number, request);
+}
+
+static int kovaplus_get_info(struct usb_device *usb_dev,
+		struct kovaplus_info *buf)
+{
+	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO,
+			buf, sizeof(struct kovaplus_info));
+}
+
+static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
+		struct kovaplus_profile_settings *buf, uint number)
+{
+	int retval;
+
+	retval = kovaplus_select_profile(usb_dev, number,
+			KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
+	if (retval)
+		return retval;
+
+	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+			buf, sizeof(struct kovaplus_profile_settings));
+}
+
+static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
+		struct kovaplus_profile_settings const *settings)
+{
+	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+			settings, sizeof(struct kovaplus_profile_settings));
+}
+
+static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
+		struct kovaplus_profile_buttons *buf, int number)
+{
+	int retval;
+
+	retval = kovaplus_select_profile(usb_dev, number,
+			KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
+	if (retval)
+		return retval;
+
+	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+			buf, sizeof(struct kovaplus_profile_buttons));
+}
+
+static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
+		struct kovaplus_profile_buttons const *buttons)
+{
+	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+			buttons, sizeof(struct kovaplus_profile_buttons));
+}
+
+/* retval is 0-4 on success, < 0 on error */
+static int kovaplus_get_actual_profile(struct usb_device *usb_dev)
+{
+	struct kovaplus_actual_profile buf;
+	int retval;
+
+	retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+			&buf, sizeof(struct kovaplus_actual_profile));
+
+	return retval ? retval : buf.actual_profile;
+}
+
+static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
+		int new_profile)
+{
+	struct kovaplus_actual_profile buf;
+
+	buf.command = KOVAPLUS_COMMAND_ACTUAL_PROFILE;
+	buf.size = sizeof(struct kovaplus_actual_profile);
+	buf.actual_profile = new_profile;
+
+	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+			&buf, sizeof(struct kovaplus_actual_profile));
+}
+
+static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct kovaplus_profile_settings))
+		return 0;
+
+	if (off + count > sizeof(struct kovaplus_profile_settings))
+		count = sizeof(struct kovaplus_profile_settings) - off;
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off,
+			count);
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	return count;
+}
+
+static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+	int profile_index;
+	struct kovaplus_profile_settings *profile_settings;
+
+	if (off != 0 || count != sizeof(struct kovaplus_profile_settings))
+		return -EINVAL;
+
+	profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index;
+	profile_settings = &kovaplus->profile_settings[profile_index];
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	difference = memcmp(buf, profile_settings,
+			sizeof(struct kovaplus_profile_settings));
+	if (difference) {
+		retval = kovaplus_set_profile_settings(usb_dev,
+				(struct kovaplus_profile_settings const *)buf);
+		if (!retval)
+			memcpy(profile_settings, buf,
+					sizeof(struct kovaplus_profile_settings));
+	}
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct kovaplus_profile_settings);
+}
+
+static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct kovaplus_profile_buttons))
+		return 0;
+
+	if (off + count > sizeof(struct kovaplus_profile_buttons))
+		count = sizeof(struct kovaplus_profile_buttons) - off;
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off,
+			count);
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	return count;
+}
+
+static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+	uint profile_index;
+	struct kovaplus_profile_buttons *profile_buttons;
+
+	if (off != 0 || count != sizeof(struct kovaplus_profile_buttons))
+		return -EINVAL;
+
+	profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index;
+	profile_buttons = &kovaplus->profile_buttons[profile_index];
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	difference = memcmp(buf, profile_buttons,
+			sizeof(struct kovaplus_profile_buttons));
+	if (difference) {
+		retval = kovaplus_set_profile_buttons(usb_dev,
+				(struct kovaplus_profile_buttons const *)buf);
+		if (!retval)
+			memcpy(profile_buttons, buf,
+					sizeof(struct kovaplus_profile_buttons));
+	}
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct kovaplus_profile_buttons);
+}
+
+static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_profile);
+}
+
+static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct kovaplus_device *kovaplus;
+	struct usb_device *usb_dev;
+	unsigned long profile;
+	int retval;
+
+	dev = dev->parent->parent;
+	kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+	retval = strict_strtoul(buf, 10, &profile);
+	if (retval)
+		return retval;
+
+	if (profile >= 5)
+		return -EINVAL;
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	retval = kovaplus_set_actual_profile(usb_dev, profile);
+	kovaplus->actual_profile = profile;
+	mutex_unlock(&kovaplus->kovaplus_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi);
+}
+
+static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity);
+}
+
+static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity);
+}
+
+static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version);
+}
+
+static struct device_attribute kovaplus_attributes[] = {
+	__ATTR(actual_cpi, 0440,
+		kovaplus_sysfs_show_actual_cpi, NULL),
+	__ATTR(firmware_version, 0440,
+		kovaplus_sysfs_show_firmware_version, NULL),
+	__ATTR(actual_profile, 0660,
+		kovaplus_sysfs_show_actual_profile,
+		kovaplus_sysfs_set_actual_profile),
+	__ATTR(actual_sensitivity_x, 0440,
+		kovaplus_sysfs_show_actual_sensitivity_x, NULL),
+	__ATTR(actual_sensitivity_y, 0440,
+		kovaplus_sysfs_show_actual_sensitivity_y, NULL),
+	__ATTR_NULL
+};
+
+static struct bin_attribute kovaplus_bin_attributes[] = {
+	{
+		.attr = { .name = "profile_settings", .mode = 0220 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.write = kovaplus_sysfs_write_profile_settings
+	},
+	{
+		.attr = { .name = "profile1_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[4]
+	},
+	{
+		.attr = { .name = "profile_buttons", .mode = 0220 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.write = kovaplus_sysfs_write_profile_buttons
+	},
+	{
+		.attr = { .name = "profile1_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[4]
+	},
+	__ATTR_NULL
+};
+
+static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
+		struct kovaplus_device *kovaplus)
+{
+	int retval, i;
+	static uint wait = 70; /* device will freeze with just 60 */
+
+	mutex_init(&kovaplus->kovaplus_lock);
+
+	retval = kovaplus_get_info(usb_dev, &kovaplus->info);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < 5; ++i) {
+		msleep(wait);
+		retval = kovaplus_get_profile_settings(usb_dev,
+				&kovaplus->profile_settings[i], i);
+		if (retval)
+			return retval;
+
+		msleep(wait);
+		retval = kovaplus_get_profile_buttons(usb_dev,
+				&kovaplus->profile_buttons[i], i);
+		if (retval)
+			return retval;
+	}
+
+	msleep(wait);
+	retval = kovaplus_get_actual_profile(usb_dev);
+	if (retval < 0)
+		return retval;
+	kovaplus_profile_activated(kovaplus, retval);
+
+	return 0;
+}
+
+static int kovaplus_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 kovaplus_device *kovaplus;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+
+		kovaplus = kzalloc(sizeof(*kovaplus), GFP_KERNEL);
+		if (!kovaplus) {
+			hid_err(hdev, "can't alloc device descriptor\n");
+			return -ENOMEM;
+		}
+		hid_set_drvdata(hdev, kovaplus);
+
+		retval = kovaplus_init_kovaplus_device_struct(usb_dev, kovaplus);
+		if (retval) {
+			hid_err(hdev, "couldn't init struct kovaplus_device\n");
+			goto exit_free;
+		}
+
+		retval = roccat_connect(kovaplus_class, hdev,
+				sizeof(struct kovaplus_roccat_report));
+		if (retval < 0) {
+			hid_err(hdev, "couldn't init char dev\n");
+		} else {
+			kovaplus->chrdev_minor = retval;
+			kovaplus->roccat_claimed = 1;
+		}
+
+	} else {
+		hid_set_drvdata(hdev, NULL);
+	}
+
+	return 0;
+exit_free:
+	kfree(kovaplus);
+	return retval;
+}
+
+static void kovaplus_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct kovaplus_device *kovaplus;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+		kovaplus = hid_get_drvdata(hdev);
+		if (kovaplus->roccat_claimed)
+			roccat_disconnect(kovaplus->chrdev_minor);
+		kfree(kovaplus);
+	}
+}
+
+static int kovaplus_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 = kovaplus_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 kovaplus_remove(struct hid_device *hdev)
+{
+	kovaplus_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus,
+		u8 const *data)
+{
+	struct kovaplus_mouse_report_button const *button_report;
+
+	if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON)
+		return;
+
+	button_report = (struct kovaplus_mouse_report_button const *)data;
+
+	switch (button_report->type) {
+	case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1:
+		kovaplus_profile_activated(kovaplus, button_report->data1 - 1);
+		break;
+	case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI:
+		kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1);
+	case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY:
+		kovaplus->actual_x_sensitivity = button_report->data1;
+		kovaplus->actual_y_sensitivity = button_report->data2;
+	}
+}
+
+static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus,
+		u8 const *data)
+{
+	struct kovaplus_roccat_report roccat_report;
+	struct kovaplus_mouse_report_button const *button_report;
+
+	if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON)
+		return;
+
+	button_report = (struct kovaplus_mouse_report_button const *)data;
+
+	if (button_report->type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2)
+		return;
+
+	roccat_report.type = button_report->type;
+	roccat_report.profile = kovaplus->actual_profile + 1;
+
+	if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO ||
+			roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT ||
+			roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
+			roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER)
+		roccat_report.button = button_report->data1;
+	else
+		roccat_report.button = 0;
+
+	if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI)
+		roccat_report.data1 = kovaplus_convert_event_cpi(button_report->data1);
+	else
+		roccat_report.data1 = button_report->data1;
+
+	roccat_report.data2 = button_report->data2;
+
+	roccat_report_event(kovaplus->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+}
+
+static int kovaplus_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 kovaplus_device *kovaplus = hid_get_drvdata(hdev);
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE)
+		return 0;
+
+	kovaplus_keep_values_up_to_date(kovaplus, data);
+
+	if (kovaplus->roccat_claimed)
+		kovaplus_report_to_chrdev(kovaplus, data);
+
+	return 0;
+}
+
+static const struct hid_device_id kovaplus_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, kovaplus_devices);
+
+static struct hid_driver kovaplus_driver = {
+		.name = "kovaplus",
+		.id_table = kovaplus_devices,
+		.probe = kovaplus_probe,
+		.remove = kovaplus_remove,
+		.raw_event = kovaplus_raw_event
+};
+
+static int __init kovaplus_init(void)
+{
+	int retval;
+
+	kovaplus_class = class_create(THIS_MODULE, "kovaplus");
+	if (IS_ERR(kovaplus_class))
+		return PTR_ERR(kovaplus_class);
+	kovaplus_class->dev_attrs = kovaplus_attributes;
+	kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes;
+
+	retval = hid_register_driver(&kovaplus_driver);
+	if (retval)
+		class_destroy(kovaplus_class);
+	return retval;
+}
+
+static void __exit kovaplus_exit(void)
+{
+	hid_unregister_driver(&kovaplus_driver);
+	class_destroy(kovaplus_class);
+}
+
+module_init(kovaplus_init);
+module_exit(kovaplus_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Kova[+] driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hid/hid-roccat-kovaplus.h b/drivers/hid/hid-roccat-kovaplus.h
new file mode 100644
index 0000000..ce40607
--- /dev/null
+++ b/drivers/hid/hid-roccat-kovaplus.h
@@ -0,0 +1,157 @@
+#ifndef __HID_ROCCAT_KOVAPLUS_H
+#define __HID_ROCCAT_KOVAPLUS_H
+
+/*
+ * Copyright (c) 2010 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>
+
+struct kovaplus_control {
+	uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */
+	uint8_t value;
+	uint8_t request;
+} __packed;
+
+enum kovaplus_control_requests {
+	/* read after write; value = 1 */
+	KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0,
+	/* write; value = profile number range 0-4 */
+	KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
+	/* write; value = profile number range 0-4 */
+	KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20,
+};
+
+enum kovaplus_control_values {
+	KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */
+	KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1,
+	KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */
+};
+
+struct kovaplus_actual_profile {
+	uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */
+	uint8_t size; /* always 3 */
+	uint8_t actual_profile; /* Range 0-4! */
+} __packed;
+
+struct kovaplus_profile_settings {
+	uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_SETTINGS */
+	uint8_t size; /* 16 */
+	uint8_t profile_index; /* range 0-4 */
+	uint8_t unknown1;
+	uint8_t sensitivity_x; /* range 1-10 */
+	uint8_t sensitivity_y; /* range 1-10 */
+	uint8_t cpi_levels_enabled;
+	uint8_t cpi_startup_level; /* range 1-4 */
+	uint8_t data[8];
+} __packed;
+
+struct kovaplus_profile_buttons {
+	uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_BUTTONS */
+	uint8_t size; /* 23 */
+	uint8_t profile_index; /* range 0-4 */
+	uint8_t data[20];
+} __packed;
+
+struct kovaplus_info {
+	uint8_t command; /* KOVAPLUS_COMMAND_INFO */
+	uint8_t size; /* 6 */
+	uint8_t firmware_version;
+	uint8_t unknown[3];
+} __packed;
+
+/* writes 1 on plugin */
+struct kovaplus_a {
+	uint8_t command; /* KOVAPLUS_COMMAND_A */
+	uint8_t size; /* 3 */
+	uint8_t unknown;
+} __packed;
+
+enum kovaplus_commands {
+	KOVAPLUS_COMMAND_CONTROL = 0x4,
+	KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+	KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
+	KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
+	KOVAPLUS_COMMAND_INFO = 0x9,
+	KOVAPLUS_COMMAND_A = 0xa,
+};
+
+enum kovaplus_usb_commands {
+	KOVAPLUS_USB_COMMAND_CONTROL = 0x304,
+	KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
+	KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
+	KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
+	KOVAPLUS_USB_COMMAND_INFO = 0x309,
+	KOVAPLUS_USB_COMMAND_A = 0x30a,
+};
+
+enum kovaplus_mouse_report_numbers {
+	KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1,
+	KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
+	KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3,
+	KOVAPLUS_MOUSE_REPORT_NUMBER_KBD = 4,
+};
+
+struct kovaplus_mouse_report_button {
+	uint8_t report_number; /* KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON */
+	uint8_t unknown1;
+	uint8_t type;
+	uint8_t data1;
+	uint8_t data2;
+} __packed;
+
+enum kovaplus_mouse_report_button_types {
+	/* data1 = profile_number range 1-5; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1 = 0x20,
+	/* data1 = profile_number range 1-5; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2 = 0x30,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO = 0x40,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT = 0x50,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
+	/* data1 = 1 = 400, 2 = 800, 4 = 1600, 7 = 3200; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
+	/* data1 + data2 = sense range 1-10; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
+	/* data1 = type as in profile_buttons; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
+};
+
+enum kovaplus_mouse_report_button_actions {
+	KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
+	KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
+};
+
+struct kovaplus_roccat_report {
+	uint8_t type;
+	uint8_t profile;
+	uint8_t button;
+	uint8_t data1;
+	uint8_t data2;
+} __packed;
+
+struct kovaplus_device {
+	int actual_profile;
+	int actual_cpi;
+	int actual_x_sensitivity;
+	int actual_y_sensitivity;
+	int roccat_claimed;
+	int chrdev_minor;
+	struct mutex kovaplus_lock;
+	struct kovaplus_info info;
+	struct kovaplus_profile_settings profile_settings[5];
+	struct kovaplus_profile_buttons profile_buttons[5];
+};
+
+#endif
diff --git a/drivers/hid/hid-roccat-pyra.c b/drivers/hid/hid-roccat-pyra.c
index 02c58e0..160f481 100644
--- a/drivers/hid/hid-roccat-pyra.c
+++ b/drivers/hid/hid-roccat-pyra.c
@@ -20,11 +20,11 @@
 #include <linux/device.h>
 #include <linux/input.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/hid-roccat.h>
 #include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
 #include "hid-roccat-pyra.h"
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -42,7 +42,6 @@ static void profile_activated(struct pyra_device *pyra,
 static int pyra_send_control(struct usb_device *usb_dev, int value,
 		enum pyra_control_requests request)
 {
-	int len;
 	struct pyra_control control;
 
 	if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS ||
@@ -54,47 +53,31 @@ static int pyra_send_control(struct usb_device *usb_dev, int value,
 	control.value = value;
 	control.request = request;
 
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_CONTROL, 0, (char *)&control,
-			sizeof(struct pyra_control),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (len != sizeof(struct pyra_control))
-		return len;
-
-	return 0;
+	return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL,
+			&control, sizeof(struct pyra_control));
 }
 
 static int pyra_receive_control_status(struct usb_device *usb_dev)
 {
-	int len;
+	int retval;
 	struct pyra_control control;
 
 	do {
 		msleep(10);
-
-		len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-				USB_REQ_CLEAR_FEATURE,
-				USB_TYPE_CLASS | USB_RECIP_INTERFACE |
-				USB_DIR_IN,
-				PYRA_USB_COMMAND_CONTROL, 0, (char *)&control,
-				sizeof(struct pyra_control),
-				USB_CTRL_SET_TIMEOUT);
+		retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL,
+				&control, sizeof(struct pyra_control));
 
 		/* requested too early, try again */
-	} while (len == -EPROTO);
+	} while (retval == -EPROTO);
 
-	if (len == sizeof(struct pyra_control) &&
-			control.command == PYRA_COMMAND_CONTROL &&
+	if (!retval && control.command == PYRA_COMMAND_CONTROL &&
 			control.request == PYRA_CONTROL_REQUEST_STATUS &&
 			control.value == 1)
-			return 0;
+		return 0;
 	else {
 		hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n",
 			control.request, control.value);
-		return -EINVAL;
+		return retval ? retval : -EINVAL;
 	}
 }
 
@@ -102,125 +85,72 @@ static int pyra_get_profile_settings(struct usb_device *usb_dev,
 		struct pyra_profile_settings *buf, int number)
 {
 	int retval;
-
 	retval = pyra_send_control(usb_dev, number,
 			PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
-
 	if (retval)
 		return retval;
-
-	retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)buf,
-			sizeof(struct pyra_profile_settings),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (retval != sizeof(struct pyra_profile_settings))
-		return retval;
-
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS,
+			buf, sizeof(struct pyra_profile_settings));
 }
 
 static int pyra_get_profile_buttons(struct usb_device *usb_dev,
 		struct pyra_profile_buttons *buf, int number)
 {
 	int retval;
-
 	retval = pyra_send_control(usb_dev, number,
 			PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
-
 	if (retval)
 		return retval;
-
-	retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buf,
-			sizeof(struct pyra_profile_buttons),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (retval != sizeof(struct pyra_profile_buttons))
-		return retval;
-
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS,
+			buf, sizeof(struct pyra_profile_buttons));
 }
 
 static int pyra_get_settings(struct usb_device *usb_dev,
 		struct pyra_settings *buf)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_SETTINGS, 0, buf,
-			sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_settings))
-		return -EIO;
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS,
+			buf, sizeof(struct pyra_settings));
 }
 
 static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_INFO, 0, buf,
-			sizeof(struct pyra_info), USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_info))
-		return -EIO;
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO,
+			buf, sizeof(struct pyra_info));
+}
+
+static int pyra_send(struct usb_device *usb_dev, uint command,
+		void const *buf, uint size)
+{
+	int retval;
+	retval = roccat_common_send(usb_dev, command, buf, size);
+	if (retval)
+		return retval;
+	return pyra_receive_control_status(usb_dev);
 }
 
 static int pyra_set_profile_settings(struct usb_device *usb_dev,
 		struct pyra_profile_settings const *settings)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)settings,
-			sizeof(struct pyra_profile_settings),
-			USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_profile_settings))
-		return -EIO;
-	if (pyra_receive_control_status(usb_dev))
-		return -EIO;
-	return 0;
+	return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings,
+			sizeof(struct pyra_profile_settings));
 }
 
 static int pyra_set_profile_buttons(struct usb_device *usb_dev,
 		struct pyra_profile_buttons const *buttons)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buttons,
-			sizeof(struct pyra_profile_buttons),
-			USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_profile_buttons))
-		return -EIO;
-	if (pyra_receive_control_status(usb_dev))
-		return -EIO;
-	return 0;
+	return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons,
+			sizeof(struct pyra_profile_buttons));
 }
 
 static int pyra_set_settings(struct usb_device *usb_dev,
 		struct pyra_settings const *settings)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_SETTINGS, 0, (char *)settings,
-			sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_settings))
-		return -EIO;
-	if (pyra_receive_control_status(usb_dev))
-		return -EIO;
-	return 0;
+	int retval;
+	retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings,
+			sizeof(struct pyra_settings));
+	if (retval)
+		return retval;
+	return pyra_receive_control_status(usb_dev);
 }
 
 static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
@@ -521,21 +451,16 @@ static struct bin_attribute pyra_bin_attributes[] = {
 static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
 		struct pyra_device *pyra)
 {
-	struct pyra_info *info;
+	struct pyra_info info;
 	int retval, i;
 
 	mutex_init(&pyra->pyra_lock);
 
-	info = kmalloc(sizeof(struct pyra_info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-	retval = pyra_get_info(usb_dev, info);
-	if (retval) {
-		kfree(info);
+	retval = pyra_get_info(usb_dev, &info);
+	if (retval)
 		return retval;
-	}
-	pyra->firmware_version = info->firmware_version;
-	kfree(info);
+
+	pyra->firmware_version = info.firmware_version;
 
 	retval = pyra_get_settings(usb_dev, &pyra->settings);
 	if (retval)
@@ -581,7 +506,8 @@ static int pyra_init_specials(struct hid_device *hdev)
 			goto exit_free;
 		}
 
-		retval = roccat_connect(pyra_class, hdev);
+		retval = roccat_connect(pyra_class, hdev,
+				sizeof(struct pyra_roccat_report));
 		if (retval < 0) {
 			hid_err(hdev, "couldn't init char dev\n");
 		} else {
@@ -685,8 +611,7 @@ static void pyra_report_to_chrdev(struct pyra_device const *pyra,
 		roccat_report.value = button_event->data1;
 		roccat_report.key = 0;
 		roccat_report_event(pyra->chrdev_minor,
-				(uint8_t const *)&roccat_report,
-				sizeof(struct pyra_roccat_report));
+				(uint8_t const *)&roccat_report);
 		break;
 	case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO:
 	case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT:
@@ -700,8 +625,7 @@ static void pyra_report_to_chrdev(struct pyra_device const *pyra,
 			 */
 			roccat_report.value = pyra->actual_profile + 1;
 			roccat_report_event(pyra->chrdev_minor,
-					(uint8_t const *)&roccat_report,
-					sizeof(struct pyra_roccat_report));
+					(uint8_t const *)&roccat_report);
 		}
 		break;
 	}
@@ -761,8 +685,8 @@ static int __init pyra_init(void)
 
 static void __exit pyra_exit(void)
 {
-	class_destroy(pyra_class);
 	hid_unregister_driver(&pyra_driver);
+	class_destroy(pyra_class);
 }
 
 module_init(pyra_init);
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index a14c579..5666e75 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -26,8 +26,7 @@
 #include <linux/cdev.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
-
-#include "hid-roccat.h"
+#include <linux/hid-roccat.h>
 
 #define ROCCAT_FIRST_MINOR 0
 #define ROCCAT_MAX_DEVICES 8
@@ -37,11 +36,11 @@
 
 struct roccat_report {
 	uint8_t *value;
-	int len;
 };
 
 struct roccat_device {
 	unsigned int minor;
+	int report_size;
 	int open;
 	int exist;
 	wait_queue_head_t wait;
@@ -123,7 +122,7 @@ static ssize_t roccat_read(struct file *file, char __user *buffer,
 	 * If report is larger than requested amount of data, rest of report
 	 * is lost!
 	 */
-	len = report->len > count ? count : report->len;
+	len = device->report_size > count ? count : device->report_size;
 
 	if (copy_to_user(buffer, report->value, len)) {
 		retval = -EFAULT;
@@ -248,26 +247,25 @@ static int roccat_release(struct inode *inode, struct file *file)
  *
  * This is called from interrupt handler.
  */
-int roccat_report_event(int minor, u8 const *data, int len)
+int roccat_report_event(int minor, u8 const *data)
 {
 	struct roccat_device *device;
 	struct roccat_reader *reader;
 	struct roccat_report *report;
 	uint8_t *new_value;
 
-	new_value = kmemdup(data, len, GFP_ATOMIC);
+	device = devices[minor];
+
+	new_value = kmemdup(data, device->report_size, GFP_ATOMIC);
 	if (!new_value)
 		return -ENOMEM;
 
-	device = devices[minor];
-
 	report = &device->cbuf[device->cbuf_end];
 
 	/* passing NULL is safe */
 	kfree(report->value);
 
 	report->value = new_value;
-	report->len = len;
 	device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE;
 
 	list_for_each_entry(reader, &device->readers, node) {
@@ -295,7 +293,7 @@ EXPORT_SYMBOL_GPL(roccat_report_event);
  * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
  * success, a negative error code on failure.
  */
-int roccat_connect(struct class *klass, struct hid_device *hid)
+int roccat_connect(struct class *klass, struct hid_device *hid, int report_size)
 {
 	unsigned int minor;
 	struct roccat_device *device;
@@ -343,6 +341,7 @@ int roccat_connect(struct class *klass, struct hid_device *hid)
 	device->hid = hid;
 	device->exist = 1;
 	device->cbuf_end = 0;
+	device->report_size = report_size;
 
 	return minor;
 }
@@ -357,13 +356,16 @@ void roccat_disconnect(int minor)
 
 	mutex_lock(&devices_lock);
 	device = devices[minor];
-	devices[minor] = NULL;
 	mutex_unlock(&devices_lock);
 
 	device->exist = 0; /* TODO exist maybe not needed */
 
 	device_destroy(device->dev->class, MKDEV(roccat_major, minor));
 
+	mutex_lock(&devices_lock);
+	devices[minor] = NULL;
+	mutex_unlock(&devices_lock);
+	
 	if (device->open) {
 		hid_hw_close(device->hid);
 		wake_up_interruptible(&device->wait);
@@ -373,6 +375,34 @@ void roccat_disconnect(int minor)
 }
 EXPORT_SYMBOL_GPL(roccat_disconnect);
 
+static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct roccat_device *device;
+	unsigned int minor = iminor(inode);
+	long retval = 0;
+
+	mutex_lock(&devices_lock);
+
+	device = devices[minor];
+	if (!device) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case ROCCATIOCGREPSIZE:
+		if (put_user(device->report_size, (int __user *)arg))
+			retval = -EFAULT;
+		break;
+	default:
+		retval = -ENOTTY;
+	}
+out:
+	mutex_unlock(&devices_lock);
+	return retval;
+}
+
 static const struct file_operations roccat_ops = {
 	.owner = THIS_MODULE,
 	.read = roccat_read,
@@ -380,6 +410,7 @@ static const struct file_operations roccat_ops = {
 	.open = roccat_open,
 	.release = roccat_release,
 	.llseek = noop_llseek,
+	.unlocked_ioctl = roccat_ioctl,
 };
 
 static int __init roccat_init(void)
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h
deleted file mode 100644
index 5784281..0000000
--- a/drivers/hid/hid-roccat.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#ifndef __HID_ROCCAT_H
-#define __HID_ROCCAT_H
-
-/*
- * Copyright (c) 2010 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/hid.h>
-#include <linux/types.h>
-
-#if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE)
-int roccat_connect(struct class *klass, struct hid_device *hid);
-void roccat_disconnect(int minor);
-int roccat_report_event(int minor, u8 const *data, int len);
-#else
-static inline int roccat_connect(struct class *klass,
-		struct hid_device *hid) { return -1; }
-static inline void roccat_disconnect(int minor) {}
-static inline int roccat_report_event(int minor, u8 const *data, int len)
-{
-	return 0;
-}
-#endif
-
-#endif
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 68d7b36..93819a0 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -46,6 +46,16 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 	return rdesc;
 }
 
+/*
+ * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
+ * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
+ * so we need to override that forcing HID Output Reports on the Control EP.
+ *
+ * There is also another issue about HID Output Reports via USB, the Sixaxis
+ * does not want the report_id as part of the data packet, so we have to
+ * discard buf[0] when sending the actual control message, even for numbered
+ * reports, humpf!
+ */
 static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
 		size_t count, unsigned char report_type)
 {
@@ -55,6 +65,12 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
 	int report_id = buf[0];
 	int ret;
 
+	if (report_type == HID_OUTPUT_REPORT) {
+		/* Don't send the Report ID */
+		buf++;
+		count--;
+	}
+
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 		HID_REQ_SET_REPORT,
 		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
@@ -62,6 +78,10 @@ static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
 		interface->desc.bInterfaceNumber, buf, count,
 		USB_CTRL_SET_TIMEOUT);
 
+	/* Count also the Report ID, in case of an Output report. */
+	if (ret > 0 && report_type == HID_OUTPUT_REPORT)
+		ret++;
+
 	return ret;
 }
 
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 468e87b..54409cb 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -91,7 +91,7 @@ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count,
 			ret = -EFAULT;
 			goto out;
 		}
-		ret += len;
+		ret = len;
 
 		kfree(list->buffer[list->tail].value);
 		list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
@@ -102,15 +102,14 @@ out:
 }
 
 /* the first byte is expected to be a report number */
-static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+/* This function is to be called with the minors_lock mutex held */
+static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
 {
 	unsigned int minor = iminor(file->f_path.dentry->d_inode);
 	struct hid_device *dev;
 	__u8 *buf;
 	int ret = 0;
 
-	mutex_lock(&minors_lock);
-
 	if (!hidraw_table[minor]) {
 		ret = -ENODEV;
 		goto out;
@@ -148,14 +147,92 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
 		goto out_free;
 	}
 
-	ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);
+	ret = dev->hid_output_raw_report(dev, buf, count, report_type);
 out_free:
 	kfree(buf);
 out:
+	return ret;
+}
+
+/* the first byte is expected to be a report number */
+static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+{
+	ssize_t ret;
+	mutex_lock(&minors_lock);
+	ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
 	mutex_unlock(&minors_lock);
 	return ret;
 }
 
+
+/* This function performs a Get_Report transfer over the control endpoint
+   per section 7.2.1 of the HID specification, version 1.1.  The first byte
+   of buffer is the report number to request, or 0x0 if the defice does not
+   use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
+   or HID_INPUT_REPORT.  This function is to be called with the minors_lock
+   mutex held.  */
+static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
+{
+	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+	struct hid_device *dev;
+	__u8 *buf;
+	int ret = 0, len;
+	unsigned char report_number;
+
+	dev = hidraw_table[minor]->hid;
+
+	if (!dev->hid_get_raw_report) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (count > HID_MAX_BUFFER_SIZE) {
+		printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
+				task_pid_nr(current));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (count < 2) {
+		printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
+				task_pid_nr(current));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Read the first byte from the user. This is the report number,
+	   which is passed to dev->hid_get_raw_report(). */
+	if (copy_from_user(&report_number, buffer, 1)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type);
+
+	if (ret < 0)
+		goto out_free;
+
+	len = (ret < count) ? ret : count;
+
+	if (copy_to_user(buffer, buf, len)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	ret = len;
+
+out_free:
+	kfree(buf);
+out:
+	return ret;
+}
+
 static unsigned int hidraw_poll(struct file *file, poll_table *wait)
 {
 	struct hidraw_list *list = file->private_data;
@@ -295,7 +372,24 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
 		default:
 			{
 				struct hid_device *hid = dev->hid;
-				if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
+				if (_IOC_TYPE(cmd) != 'H') {
+					ret = -EINVAL;
+					break;
+				}
+
+				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
+					int len = _IOC_SIZE(cmd);
+					ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
+					break;
+				}
+				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
+					int len = _IOC_SIZE(cmd);
+					ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
+					break;
+				}
+
+				/* Begin Read-only ioctls. */
+				if (_IOC_DIR(cmd) != _IOC_READ) {
 					ret = -EINVAL;
 					break;
 				}
@@ -327,7 +421,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
 						-EFAULT : len;
 					break;
 				}
-		}
+			}
 
 		ret = -ENOTTY;
 	}
@@ -428,12 +522,12 @@ void hidraw_disconnect(struct hid_device *hid)
 
 	hidraw->exist = 0;
 
+	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+
 	mutex_lock(&minors_lock);
 	hidraw_table[hidraw->minor] = NULL;
 	mutex_unlock(&minors_lock);
 
-	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-
 	if (hidraw->open) {
 		hid_hw_close(hid);
 		wake_up_interruptible(&hidraw->wait);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index b336dd8..38c261a 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -799,6 +799,40 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 	return 0;
 }
 
+static int usbhid_get_raw_report(struct hid_device *hid,
+		unsigned char report_number, __u8 *buf, size_t count,
+		unsigned char report_type)
+{
+	struct usbhid_device *usbhid = hid->driver_data;
+	struct usb_device *dev = hid_to_usb_dev(hid);
+	struct usb_interface *intf = usbhid->intf;
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	int skipped_report_id = 0;
+	int ret;
+
+	/* Byte 0 is the report number. Report data starts at byte 1.*/
+	buf[0] = report_number;
+	if (report_number == 0x0) {
+		/* Offset the return buffer by 1, so that the report ID
+		   will remain in byte 0. */
+		buf++;
+		count--;
+		skipped_report_id = 1;
+	}
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		HID_REQ_GET_REPORT,
+		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		((report_type + 1) << 8) | report_number,
+		interface->desc.bInterfaceNumber, buf, count,
+		USB_CTRL_SET_TIMEOUT);
+
+	/* count also the report id */
+	if (ret > 0 && skipped_report_id)
+		ret++;
+
+	return ret;
+}
+
 static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
 		unsigned char report_type)
 {
@@ -1139,6 +1173,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 
 	usb_set_intfdata(intf, hid);
 	hid->ll_driver = &usb_hid_driver;
+	hid->hid_get_raw_report = usbhid_get_raw_report;
 	hid->hid_output_raw_report = usbhid_output_raw_report;
 	hid->ff_init = hid_pidff_init;
 #ifdef CONFIG_USB_HIDDEV
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 297bc9a..e4bd13b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -467,6 +467,17 @@ config SENSORS_JC42
 	  This driver can also be built as a module.  If so, the module
 	  will be called jc42.
 
+config SENSORS_LINEAGE
+	tristate "Lineage Compact Power Line Power Entry Module"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Lineage Compact Power Line
+	  series of DC/DC and AC/DC converters such as CP1800, CP2000AC,
+	  CP2000DC, CP2725, and others.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lineage-pem.
+
 config SENSORS_LM63
 	tristate "National Semiconductor LM63 and LM64"
 	depends on I2C
@@ -510,7 +521,7 @@ config SENSORS_LM75
 		- Dallas Semiconductor DS75 and DS1775
 		- Maxim MAX6625 and MAX6626
 		- Microchip MCP980x
-		- National Semiconductor LM75
+		- National Semiconductor LM75, LM75A
 		- NXP's LM75A
 		- ST Microelectronics STDS75
 		- TelCom (now Microchip) TCN75
@@ -625,6 +636,17 @@ config SENSORS_LM93
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm93.
 
+config SENSORS_LTC4151
+	tristate "Linear Technology LTC4151"
+	depends on I2C
+	default n
+	help
+	  If you say yes here you get support for Linear Technology LTC4151
+	  High Voltage I2C Current and Voltage Monitor interface.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4151.
+
 config SENSORS_LTC4215
 	tristate "Linear Technology LTC4215"
 	depends on I2C && EXPERIMENTAL
@@ -685,6 +707,16 @@ config SENSORS_MAX1619
 	  This driver can also be built as a module.  If so, the module
 	  will be called max1619.
 
+config SENSORS_MAX6639
+	tristate "Maxim MAX6639 sensor chip"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the MAX6639
+	  sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called max6639.
+
 config SENSORS_MAX6650
 	tristate "Maxim MAX6650 sensor chip"
 	depends on I2C && EXPERIMENTAL
@@ -735,6 +767,61 @@ config SENSORS_PCF8591
 	  These devices are hard to detect and rarely found on mainstream
 	  hardware.  If unsure, say N.
 
+config PMBUS
+	tristate "PMBus support"
+	depends on I2C && EXPERIMENTAL
+	default n
+	help
+	  Say yes here if you want to enable PMBus support.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called pmbus_core.
+
+if PMBUS
+
+config SENSORS_PMBUS
+	tristate "Generic PMBus devices"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for generic
+	  PMBus devices, including but not limited to BMR450, BMR451, BMR453,
+	  BMR454, and LTC2978.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called pmbus.
+
+config SENSORS_MAX16064
+	tristate "Maxim MAX16064"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Maxim
+	  MAX16064.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max16064.
+
+config SENSORS_MAX34440
+	tristate "Maxim MAX34440/MAX34441"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Maxim
+	  MAX34440 and MAX34441.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max34440.
+
+config SENSORS_MAX8688
+	tristate "Maxim MAX8688"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Maxim
+	  MAX8688.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max8688.
+
+endif # PMBUS
+
 config SENSORS_SHT15
 	tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
 	depends on GENERIC_GPIO
@@ -872,6 +959,25 @@ config SENSORS_SMSC47B397
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47b397.
 
+config SENSORS_SCH5627
+	tristate "SMSC SCH5627"
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  features of the SMSC SCH5627 Super-I/O chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called sch5627.
+
+config SENSORS_ADS1015
+	tristate "Texas Instruments ADS1015"
+	depends on I2C
+	help
+	  If you say yes here you get support for Texas Instruments ADS1015
+	  12-bit 4-input ADC device.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ads1015.
+
 config SENSORS_ADS7828
 	tristate "Texas Instruments ADS7828"
 	depends on I2C
@@ -1083,7 +1189,7 @@ config SENSORS_W83627HF
 	  will be called w83627hf.
 
 config SENSORS_W83627EHF
-	tristate "Winbond W83627EHF/EHG/DHG, W83667HG"
+	tristate "Winbond W83627EHF/EHG/DHG, W83667HG, NCT6775F, NCT6776F"
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware
@@ -1094,7 +1200,8 @@ config SENSORS_W83627EHF
 	  chip suited for specific Intel processors that use PECI such as
 	  the Core 2 Duo.
 
-	  This driver also supports the W83667HG chip.
+	  This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F
+	  (also known as W83667HG-I), and NCT6776F.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627ehf.
@@ -1127,40 +1234,6 @@ config SENSORS_ULTRA45
 	  This driver provides support for the Ultra45 workstation environmental
 	  sensors.
 
-config SENSORS_LIS3_SPI
-	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
-	depends on !ACPI && SPI_MASTER && INPUT
-	select INPUT_POLLDEV
-	default n
-	help
-	  This driver provides support for the LIS3LV02Dx accelerometer connected
-	  via SPI. The accelerometer data is readable via
-	  /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  the laptop to act as a pinball machine-esque joystick.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for the SPI transport
-	  is called lis3lv02d_spi.
-
-config SENSORS_LIS3_I2C
-	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
-	depends on I2C && INPUT
-	select INPUT_POLLDEV
-	default n
-	help
-	  This driver provides support for the LIS3LV02Dx accelerometer connected
-	  via I2C. The accelerometer data is readable via
-	  /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  the device to act as a pinball machine-esque joystick.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for the I2C transport
-	  is called lis3lv02d_i2c.
-
 config SENSORS_APPLESMC
 	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
 	depends on INPUT && X86
@@ -1208,36 +1281,6 @@ config SENSORS_ATK0110
 	  This driver can also be built as a module. If so, the module
 	  will be called asus_atk0110.
 
-config SENSORS_LIS3LV02D
-	tristate "STMicroeletronics LIS3* three-axis digital accelerometer"
-	depends on INPUT
-	select INPUT_POLLDEV
-	select NEW_LEDS
-	select LEDS_CLASS
-	default n
-	help
-	  This driver provides support for the LIS3* accelerometers, such as the
-	  LIS3LV02DL or the LIS331DL. In particular, it can be found in a number
-	  of HP laptops, which have the "Mobile Data Protection System 3D" or
-	  "3D DriveGuard" feature. On such systems the driver should load
-	  automatically (via ACPI alias). The accelerometer might also be found
-	  in other systems, connected via SPI or I2C. The accelerometer data is
-	  readable via /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  a laptop to act as a pinball machine-esque joystick. It provides also
-	  a misc device which can be used to detect free-fall. On HP laptops,
-	  if the led infrastructure is activated, support for a led indicating
-	  disk protection will be provided as hp::hddprotect. For more
-	  information on the feature, refer to Documentation/hwmon/lis3lv02d.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for HP laptops will be
-	  called hp_accel.
-
-	  Say Y here if you have an applicable laptop and want to experience
-	  the awesome power of lis3lv02d.
-
 endif # ACPI
 
 endif # HWMON
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index dde02d9..54ca593 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_SENSORS_ADM1026)	+= adm1026.o
 obj-$(CONFIG_SENSORS_ADM1029)	+= adm1029.o
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
 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_ADT7411)	+= adt7411.o
@@ -62,9 +63,7 @@ obj-$(CONFIG_SENSORS_JC42)	+= jc42.o
 obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-hwmon.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
-obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
-obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
-obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
+obj-$(CONFIG_SENSORS_LINEAGE)	+= lineage-pem.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
 obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
@@ -79,17 +78,20 @@ obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
 obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
+obj-$(CONFIG_SENSORS_LTC4151)	+= ltc4151.o
 obj-$(CONFIG_SENSORS_LTC4215)	+= ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o
 obj-$(CONFIG_SENSORS_LTC4261)	+= ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
+obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
+obj-$(CONFIG_SENSORS_SCH5627)	+= sch5627.o
 obj-$(CONFIG_SENSORS_SHT15)	+= sht15.o
 obj-$(CONFIG_SENSORS_SHT21)	+= sht21.o
 obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
@@ -112,7 +114,12 @@ obj-$(CONFIG_SENSORS_W83L786NG)	+= w83l786ng.o
 obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
 
-ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+# PMBus drivers
+obj-$(CONFIG_PMBUS)		+= pmbus_core.o
+obj-$(CONFIG_SENSORS_PMBUS)	+= pmbus.o
+obj-$(CONFIG_SENSORS_MAX16064)	+= max16064.o
+obj-$(CONFIG_SENSORS_MAX34440)	+= max34440.o
+obj-$(CONFIG_SENSORS_MAX8688)	+= max8688.o
+
+ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
 
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index 8f07a9d..0e05aa1 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -1,5 +1,5 @@
 /*
-    abituguru.c Copyright (c) 2005-2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+    abituguru.c Copyright (c) 2005-2006 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
@@ -1505,7 +1505,7 @@ static void __exit abituguru_exit(void)
 	platform_driver_unregister(&abituguru_driver);
 }
 
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Abit uGuru Sensor device");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
index 48d21e2..034cebf 100644
--- a/drivers/hwmon/abituguru3.c
+++ b/drivers/hwmon/abituguru3.c
@@ -1,7 +1,7 @@
 /*
     abituguru3.c
 
-    Copyright (c) 2006-2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+    Copyright (c) 2006-2008 Hans de Goede <hdegoede@redhat.com>
     Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
 
     This program is free software; you can redistribute it and/or modify
@@ -1266,7 +1266,7 @@ static void __exit abituguru3_exit(void)
 	platform_driver_unregister(&abituguru3_driver);
 }
 
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
new file mode 100644
index 0000000..e9beeda
--- /dev/null
+++ b/drivers/hwmon/ads1015.c
@@ -0,0 +1,337 @@
+/*
+ * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+ *
+ * Based on the ads7828 driver by Steve Hardy.
+ *
+ * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/delay.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+#include <linux/i2c/ads1015.h>
+
+/* ADS1015 registers */
+enum {
+	ADS1015_CONVERSION = 0,
+	ADS1015_CONFIG = 1,
+};
+
+/* PGA fullscale voltages in mV */
+static const unsigned int fullscale_table[8] = {
+	6144, 4096, 2048, 1024, 512, 256, 256, 256 };
+
+/* Data rates in samples per second */
+static const unsigned int data_rate_table[8] = {
+	128, 250, 490, 920, 1600, 2400, 3300, 3300 };
+
+#define ADS1015_DEFAULT_CHANNELS 0xff
+#define ADS1015_DEFAULT_PGA 2
+#define ADS1015_DEFAULT_DATA_RATE 4
+
+struct ads1015_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock; /* mutex protect updates */
+	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+};
+
+static s32 ads1015_read_reg(struct i2c_client *client, unsigned int reg)
+{
+	s32 data = i2c_smbus_read_word_data(client, reg);
+
+	return (data < 0) ? data : swab16(data);
+}
+
+static s32 ads1015_write_reg(struct i2c_client *client, unsigned int reg,
+			     u16 val)
+{
+	return i2c_smbus_write_word_data(client, reg, swab16(val));
+}
+
+static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
+			      int *value)
+{
+	u16 config;
+	s16 conversion;
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	unsigned int pga = data->channel_data[channel].pga;
+	int fullscale;
+	unsigned int data_rate = data->channel_data[channel].data_rate;
+	unsigned int conversion_time_ms;
+	int res;
+
+	mutex_lock(&data->update_lock);
+
+	/* get channel parameters */
+	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	if (res < 0)
+		goto err_unlock;
+	config = res;
+	fullscale = fullscale_table[pga];
+	conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
+
+	/* setup and start single conversion */
+	config &= 0x001f;
+	config |= (1 << 15) | (1 << 8);
+	config |= (channel & 0x0007) << 12;
+	config |= (pga & 0x0007) << 9;
+	config |= (data_rate & 0x0007) << 5;
+
+	res = ads1015_write_reg(client, ADS1015_CONFIG, config);
+	if (res < 0)
+		goto err_unlock;
+
+	/* wait until conversion finished */
+	msleep(conversion_time_ms);
+	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	if (res < 0)
+		goto err_unlock;
+	config = res;
+	if (!(config & (1 << 15))) {
+		/* conversion not finished in time */
+		res = -EIO;
+		goto err_unlock;
+	}
+
+	res = ads1015_read_reg(client, ADS1015_CONVERSION);
+	if (res < 0)
+		goto err_unlock;
+	conversion = res;
+
+	mutex_unlock(&data->update_lock);
+
+	*value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);
+
+	return 0;
+
+err_unlock:
+	mutex_unlock(&data->update_lock);
+	return res;
+}
+
+/* sysfs callback function */
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+	char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	int in;
+	int res;
+
+	res = ads1015_read_value(client, attr->index, &in);
+
+	return (res < 0) ? res : sprintf(buf, "%d\n", in);
+}
+
+static const struct sensor_device_attribute ads1015_in[] = {
+	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+};
+
+/*
+ * Driver interface
+ */
+
+static int ads1015_remove(struct i2c_client *client)
+{
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	int k;
+
+	hwmon_device_unregister(data->hwmon_dev);
+	for (k = 0; k < ADS1015_CHANNELS; ++k)
+		device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
+	kfree(data);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static int ads1015_get_channels_config_of(struct i2c_client *client)
+{
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	struct device_node *node;
+
+	if (!client->dev.of_node
+	    || !of_get_next_child(client->dev.of_node, NULL))
+		return -EINVAL;
+
+	for_each_child_of_node(client->dev.of_node, node) {
+		const __be32 *property;
+		int len;
+		unsigned int channel;
+		unsigned int pga = ADS1015_DEFAULT_PGA;
+		unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
+
+		property = of_get_property(node, "reg", &len);
+		if (!property || len != sizeof(int)) {
+			dev_err(&client->dev, "invalid reg on %s\n",
+				node->full_name);
+			continue;
+		}
+
+		channel = be32_to_cpup(property);
+		if (channel > ADS1015_CHANNELS) {
+			dev_err(&client->dev,
+				"invalid channel index %d on %s\n",
+				channel, node->full_name);
+			continue;
+		}
+
+		property = of_get_property(node, "ti,gain", &len);
+		if (property && len == sizeof(int)) {
+			pga = be32_to_cpup(property);
+			if (pga > 6) {
+				dev_err(&client->dev,
+					"invalid gain on %s\n",
+					node->full_name);
+			}
+		}
+
+		property = of_get_property(node, "ti,datarate", &len);
+		if (property && len == sizeof(int)) {
+			data_rate = be32_to_cpup(property);
+			if (data_rate > 7) {
+				dev_err(&client->dev,
+					"invalid data_rate on %s\n",
+					node->full_name);
+			}
+		}
+
+		data->channel_data[channel].enabled = true;
+		data->channel_data[channel].pga = pga;
+		data->channel_data[channel].data_rate = data_rate;
+	}
+
+	return 0;
+}
+#endif
+
+static void ads1015_get_channels_config(struct i2c_client *client)
+{
+	unsigned int k;
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev);
+
+	/* prefer platform data */
+	if (pdata) {
+		memcpy(data->channel_data, pdata->channel_data,
+		       sizeof(data->channel_data));
+		return;
+	}
+
+#ifdef CONFIG_OF
+	if (!ads1015_get_channels_config_of(client))
+		return;
+#endif
+
+	/* fallback on default configuration */
+	for (k = 0; k < ADS1015_CHANNELS; ++k) {
+		data->channel_data[k].enabled = true;
+		data->channel_data[k].pga = ADS1015_DEFAULT_PGA;
+		data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE;
+	}
+}
+
+static int ads1015_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct ads1015_data *data;
+	int err;
+	unsigned int k;
+
+	data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* build sysfs attribute group */
+	ads1015_get_channels_config(client);
+	for (k = 0; k < ADS1015_CHANNELS; ++k) {
+		if (!data->channel_data[k].enabled)
+			continue;
+		err = device_create_file(&client->dev, &ads1015_in[k].dev_attr);
+		if (err)
+			goto exit_free;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	for (k = 0; k < ADS1015_CHANNELS; ++k)
+		device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static const struct i2c_device_id ads1015_id[] = {
+	{ "ads1015", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ads1015_id);
+
+static struct i2c_driver ads1015_driver = {
+	.driver = {
+		.name = "ads1015",
+	},
+	.probe = ads1015_probe,
+	.remove = ads1015_remove,
+	.id_table = ads1015_id,
+};
+
+static int __init sensors_ads1015_init(void)
+{
+	return i2c_add_driver(&ads1015_driver);
+}
+
+static void __exit sensors_ads1015_exit(void)
+{
+	i2c_del_driver(&ads1015_driver);
+}
+
+MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>");
+MODULE_DESCRIPTION("ADS1015 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_ads1015_init);
+module_exit(sensors_ads1015_exit);
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 6e06019..a4d430e 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -1,6 +1,6 @@
 /***************************************************************************
  *   Copyright (C) 2006 by Hans Edgington <hans@edgington.nl>              *
- *   Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com>           *
+ *   Copyright (C) 2007-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  *
@@ -47,22 +47,23 @@
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 
 #define SIO_FINTEK_ID		0x1934	/* Manufacturers ID */
+#define SIO_F71808E_ID		0x0901	/* Chipset ID */
 #define SIO_F71858_ID		0x0507  /* Chipset ID */
 #define SIO_F71862_ID		0x0601	/* Chipset ID */
+#define SIO_F71869_ID		0x0814	/* Chipset ID */
 #define SIO_F71882_ID		0x0541	/* Chipset ID */
 #define SIO_F71889_ID		0x0723	/* Chipset ID */
+#define SIO_F71889E_ID		0x0909	/* Chipset ID */
 #define SIO_F8000_ID		0x0581	/* Chipset ID */
 
 #define REGION_LENGTH		8
 #define ADDR_REG_OFFSET		5
 #define DATA_REG_OFFSET		6
 
-#define F71882FG_REG_PECI		0x0A
-
-#define F71882FG_REG_IN_STATUS		0x12 /* f71882fg only */
-#define F71882FG_REG_IN_BEEP		0x13 /* f71882fg only */
+#define F71882FG_REG_IN_STATUS		0x12 /* f7188x only */
+#define F71882FG_REG_IN_BEEP		0x13 /* f7188x only */
 #define F71882FG_REG_IN(nr)		(0x20  + (nr))
-#define F71882FG_REG_IN1_HIGH		0x32 /* f71882fg only */
+#define F71882FG_REG_IN1_HIGH		0x32 /* f7188x only */
 
 #define F71882FG_REG_FAN(nr)		(0xA0 + (16 * (nr)))
 #define F71882FG_REG_FAN_TARGET(nr)	(0xA2 + (16 * (nr)))
@@ -86,28 +87,71 @@
 
 #define F71882FG_REG_FAN_HYST(nr)	(0x98 + (nr))
 
+#define F71882FG_REG_FAN_FAULT_T	0x9F
+#define F71882FG_FAN_NEG_TEMP_EN	0x20
+#define F71882FG_FAN_PROG_SEL		0x80
+
 #define F71882FG_REG_POINT_PWM(pwm, point)	(0xAA + (point) + (16 * (pwm)))
 #define F71882FG_REG_POINT_TEMP(pwm, point)	(0xA6 + (point) + (16 * (pwm)))
 #define F71882FG_REG_POINT_MAPPING(nr)		(0xAF + 16 * (nr))
 
 #define	F71882FG_REG_START		0x01
 
+#define F71882FG_MAX_INS		9
+
 #define FAN_MIN_DETECT			366 /* Lowest detectable fanspeed */
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 };
+enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
+	     f71889ed, f8000 };
 
 static const char *f71882fg_names[] = {
+	"f71808e",
 	"f71858fg",
 	"f71862fg",
+	"f71869", /* Both f71869f and f71869e, reg. compatible and same id */
 	"f71882fg",
 	"f71889fg",
+	"f71889ed",
 	"f8000",
 };
 
+static const char f71882fg_has_in[8][F71882FG_MAX_INS] = {
+	{ 1, 1, 1, 1, 1, 1, 0, 1, 1 }, /* f71808e */
+	{ 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f71858fg */
+	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71862fg */
+	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71869 */
+	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71882fg */
+	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889fg */
+	{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }, /* f71889ed */
+	{ 1, 1, 1, 0, 0, 0, 0, 0, 0 }, /* f8000 */
+};
+
+static const char f71882fg_has_in1_alarm[8] = {
+	0, /* f71808e */
+	0, /* f71858fg */
+	0, /* f71862fg */
+	0, /* f71869 */
+	1, /* f71882fg */
+	1, /* f71889fg */
+	1, /* f71889ed */
+	0, /* f8000 */
+};
+
+static const char f71882fg_has_beep[8] = {
+	0, /* f71808e */
+	0, /* f71858fg */
+	1, /* f71862fg */
+	1, /* f71869 */
+	1, /* f71882fg */
+	1, /* f71889fg */
+	1, /* f71889ed */
+	0, /* f8000 */
+};
+
 static struct platform_device *f71882fg_pdev;
 
 /* Super-I/O Function prototypes */
@@ -129,11 +173,12 @@ struct f71882fg_data {
 	struct mutex update_lock;
 	int temp_start;			/* temp numbering start (0 or 1) */
 	char valid;			/* !=0 if following fields are valid */
+	char auto_point_temp_signed;
 	unsigned long last_updated;	/* In jiffies */
 	unsigned long last_limits;	/* In jiffies */
 
 	/* Register Values */
-	u8	in[9];
+	u8	in[F71882FG_MAX_INS];
 	u8	in1_max;
 	u8	in_status;
 	u8	in_beep;
@@ -142,7 +187,7 @@ struct f71882fg_data {
 	u16	fan_full_speed[4];
 	u8	fan_status;
 	u8	fan_beep;
-	/* Note: all models have only 3 temperature channels, but on some
+	/* Note: all models have max 3 temperature channels, but on some
 	   they are addressed as 0-2 and on others as 1-3, so for coding
 	   convenience we reserve space for 4 channels */
 	u16	temp[4];
@@ -262,13 +307,9 @@ static struct platform_driver f71882fg_driver = {
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-/* Temp and in attr for the f71858fg, the f71858fg is special as it
-   has its temperature indexes start at 0 (the others start at 1) and
-   it only has 3 voltage inputs */
-static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = {
-	SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
-	SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
-	SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
+/* Temp attr for the f71858fg, the f71858fg is special as it has its
+   temperature indexes start at 0 (the others start at 1) */
+static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
 	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
 	SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 0),
@@ -292,7 +333,6 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = {
 	SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 1),
 	SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
-	SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
 	SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
 	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
 	SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
@@ -308,17 +348,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = {
 	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
 };
 
-/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */
-static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = {
-	SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
-	SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
-	SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
-	SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
-	SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
-	SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
-	SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
-	SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
-	SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+/* Temp attr for the standard models */
+static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
 	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
 	SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 1),
@@ -328,17 +359,14 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = {
 	   the max and crit alarms separately and lm_sensors v2 depends on the
 	   presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
 	SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
-	SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 1),
 	SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 1),
 	SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 1),
 	SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
-	SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 5),
 	SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
 	SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
+}, {
 	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
 	SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 2),
@@ -346,17 +374,14 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = {
 		store_temp_max_hyst, 0, 2),
 	/* Should be temp2_max_alarm, see temp1_alarm note */
 	SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
-	SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 2),
 	SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 2),
 	SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 2),
 	SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
-	SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 6),
 	SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
 	SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
+}, {
 	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
 	SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 3),
@@ -364,37 +389,39 @@ static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = {
 		store_temp_max_hyst, 0, 3),
 	/* Should be temp3_max_alarm, see temp1_alarm note */
 	SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
-	SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 3),
 	SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 3),
 	SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 3),
 	SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
-	SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 7),
 	SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
 	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
-};
+} };
 
-/* For models with in1 alarm capability */
-static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
-	SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
-		0, 1),
-	SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
-		0, 1),
-	SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
-};
+/* Temp attr for models which can beep on temp alarm */
+static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
+	SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 1),
+	SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 5),
+}, {
+	SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 2),
+	SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 6),
+}, {
+	SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 3),
+	SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 7),
+} };
 
-/* Temp and in attr for the f8000
+/* Temp attr for the f8000
    Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
    is used as hysteresis value to clear alarms
    Also like the f71858fg its temperature indexes start at 0
  */
-static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
-	SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
-	SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
-	SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
+static struct sensor_device_attribute_2 f8000_temp_attr[] = {
 	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
 	SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 0),
@@ -408,7 +435,6 @@ static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
 	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 1),
 	SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
-	SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 1),
 	SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
 	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2),
 	SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit,
@@ -419,6 +445,28 @@ static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
 	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
 };
 
+/* in attr for all models */
+static struct sensor_device_attribute_2 fxxxx_in_attr[] = {
+	SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
+	SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
+	SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
+	SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3),
+	SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
+	SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
+	SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
+	SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
+	SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+};
+
+/* For models with in1 alarm capability */
+static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
+	SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
+		0, 1),
+	SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
+		0, 1),
+	SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
+};
+
 /* Fan / PWM attr common to all models */
 static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
 	SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
@@ -479,7 +527,7 @@ static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
 };
 
 /* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
-   f71858fg / f71882fg / f71889fg */
+   standard models */
 static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
@@ -548,7 +596,87 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
 };
 
-/* PWM attr common to the f71858fg, f71882fg and f71889fg */
+/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
+   pwm setting when the temperature is above the pwmX_auto_point1_temp can be
+   programmed instead of being hardcoded to 0xff */
+static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
+	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_channel,
+		      store_pwm_auto_point_channel, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      1, 0),
+	SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      4, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      3, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp_hyst,
+		      store_pwm_auto_point_temp_hyst,
+		      0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
+		      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
+
+	SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_channel,
+		      store_pwm_auto_point_channel, 0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      4, 1),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      3, 1),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp_hyst,
+		      store_pwm_auto_point_temp_hyst,
+		      0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
+		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
+
+	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_channel,
+		      store_pwm_auto_point_channel, 0, 2),
+	SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      0, 2),
+	SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      1, 2),
+	SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      4, 2),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      0, 2),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      3, 2),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp_hyst,
+		      store_pwm_auto_point_temp_hyst,
+		      0, 2),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
+		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
+};
+
+/* PWM attr for the standard models */
 static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
@@ -943,16 +1071,16 @@ static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr)
 static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 {
 	struct f71882fg_data *data = dev_get_drvdata(dev);
-	int nr, reg = 0, reg2;
+	int nr, reg, point;
 	int nr_fans = (data->type == f71882fg) ? 4 : 3;
-	int nr_ins = (data->type == f71858fg || data->type == f8000) ? 3 : 9;
+	int nr_temps = (data->type == f71808e) ? 2 : 3;
 
 	mutex_lock(&data->update_lock);
 
 	/* Update once every 60 seconds */
 	if (time_after(jiffies, data->last_limits + 60 * HZ) ||
 			!data->valid) {
-		if (data->type == f71882fg || data->type == f71889fg) {
+		if (f71882fg_has_in1_alarm[data->type]) {
 			data->in1_max =
 				f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
 			data->in_beep =
@@ -960,7 +1088,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 		}
 
 		/* Get High & boundary temps*/
-		for (nr = data->temp_start; nr < 3 + data->temp_start; nr++) {
+		for (nr = data->temp_start; nr < nr_temps + data->temp_start;
+									nr++) {
 			data->temp_ovt[nr] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_OVT(nr));
 			data->temp_high[nr] = f71882fg_read8(data,
@@ -973,44 +1102,19 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 			data->temp_hyst[1] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_HYST(1));
 		}
+		/* All but the f71858fg / f8000 have this register */
+		if ((data->type != f71858fg) && (data->type != f8000)) {
+			reg  = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
+			data->temp_type[1] = (reg & 0x02) ? 2 : 4;
+			data->temp_type[2] = (reg & 0x04) ? 2 : 4;
+			data->temp_type[3] = (reg & 0x08) ? 2 : 4;
+		}
 
-		if (data->type == f71862fg || data->type == f71882fg ||
-		    data->type == f71889fg) {
+		if (f71882fg_has_beep[data->type]) {
 			data->fan_beep = f71882fg_read8(data,
 						F71882FG_REG_FAN_BEEP);
 			data->temp_beep = f71882fg_read8(data,
 						F71882FG_REG_TEMP_BEEP);
-			/* Have to hardcode type, because temp1 is special */
-			reg  = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
-			data->temp_type[2] = (reg & 0x04) ? 2 : 4;
-			data->temp_type[3] = (reg & 0x08) ? 2 : 4;
-		}
-		/* Determine temp index 1 sensor type */
-		if (data->type == f71889fg) {
-			reg2 = f71882fg_read8(data, F71882FG_REG_START);
-			switch ((reg2 & 0x60) >> 5) {
-			case 0x00: /* BJT / Thermistor */
-				data->temp_type[1] = (reg & 0x02) ? 2 : 4;
-				break;
-			case 0x01: /* AMDSI */
-				data->temp_type[1] = 5;
-				break;
-			case 0x02: /* PECI */
-			case 0x03: /* Ibex Peak ?? Report as PECI for now */
-				data->temp_type[1] = 6;
-				break;
-			}
-		} else {
-			reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
-			if ((reg2 & 0x03) == 0x01)
-				data->temp_type[1] = 6; /* PECI */
-			else if ((reg2 & 0x03) == 0x02)
-				data->temp_type[1] = 5; /* AMDSI */
-			else if (data->type == f71862fg ||
-				 data->type == f71882fg)
-				data->temp_type[1] = (reg & 0x02) ? 2 : 4;
-			else /* f71858fg and f8000 only support BJT */
-				data->temp_type[1] = 2;
 		}
 
 		data->pwm_enable = f71882fg_read8(data,
@@ -1025,8 +1129,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 			    f71882fg_read8(data,
 					   F71882FG_REG_POINT_MAPPING(nr));
 
-			if (data->type != f71862fg) {
-				int point;
+			switch (data->type) {
+			default:
 				for (point = 0; point < 5; point++) {
 					data->pwm_auto_point_pwm[nr][point] =
 						f71882fg_read8(data,
@@ -1039,7 +1143,14 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 							F71882FG_REG_POINT_TEMP
 							(nr, point));
 				}
-			} else {
+				break;
+			case f71808e:
+			case f71869:
+				data->pwm_auto_point_pwm[nr][0] =
+					f71882fg_read8(data,
+						F71882FG_REG_POINT_PWM(nr, 0));
+				/* Fall through */
+			case f71862fg:
 				data->pwm_auto_point_pwm[nr][1] =
 					f71882fg_read8(data,
 						F71882FG_REG_POINT_PWM
@@ -1056,6 +1167,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 					f71882fg_read8(data,
 						F71882FG_REG_POINT_TEMP
 						(nr, 3));
+				break;
 			}
 		}
 		data->last_limits = jiffies;
@@ -1067,7 +1179,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 						F71882FG_REG_TEMP_STATUS);
 		data->temp_diode_open = f71882fg_read8(data,
 						F71882FG_REG_TEMP_DIODE_OPEN);
-		for (nr = data->temp_start; nr < 3 + data->temp_start; nr++)
+		for (nr = data->temp_start; nr < nr_temps + data->temp_start;
+									nr++)
 			data->temp[nr] = f71882fg_read_temp(data, nr);
 
 		data->fan_status = f71882fg_read8(data,
@@ -1083,17 +1196,18 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
 			data->pwm[nr] =
 			    f71882fg_read8(data, F71882FG_REG_PWM(nr));
 		}
-
 		/* The f8000 can monitor 1 more fan, but has no pwm for it */
 		if (data->type == f8000)
 			data->fan[3] = f71882fg_read16(data,
 						F71882FG_REG_FAN(3));
-		if (data->type == f71882fg || data->type == f71889fg)
+
+		if (f71882fg_has_in1_alarm[data->type])
 			data->in_status = f71882fg_read8(data,
 						F71882FG_REG_IN_STATUS);
-		for (nr = 0; nr < nr_ins; nr++)
-			data->in[nr] = f71882fg_read8(data,
-						F71882FG_REG_IN(nr));
+		for (nr = 0; nr < F71882FG_MAX_INS; nr++)
+			if (f71882fg_has_in[data->type][nr])
+				data->in[nr] = f71882fg_read8(data,
+							F71882FG_REG_IN(nr));
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -1882,7 +1996,7 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
 
 	val /= 1000;
 
-	if (data->type == f71889fg)
+	if (data->auto_point_temp_signed)
 		val = SENSORS_LIMIT(val, -128, 127);
 	else
 		val = SENSORS_LIMIT(val, 0, 127);
@@ -1929,7 +2043,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 	struct f71882fg_data *data;
 	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
 	int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3;
-	u8 start_reg;
+	int nr_temps = (sio_data->type == f71808e) ? 2 : 3;
+	u8 start_reg, reg;
 
 	data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
 	if (!data)
@@ -1968,37 +2083,72 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 				/* The f71858fg temperature alarms behave as
 				   the f8000 alarms in this mode */
 				err = f71882fg_create_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			else
 				err = f71882fg_create_sysfs_files(pdev,
-					f71858fg_in_temp_attr,
-					ARRAY_SIZE(f71858fg_in_temp_attr));
-			break;
-		case f71882fg:
-		case f71889fg:
-			err = f71882fg_create_sysfs_files(pdev,
-					fxxxx_in1_alarm_attr,
-					ARRAY_SIZE(fxxxx_in1_alarm_attr));
-			if (err)
-				goto exit_unregister_sysfs;
-			/* fall through! */
-		case f71862fg:
-			err = f71882fg_create_sysfs_files(pdev,
-					fxxxx_in_temp_attr,
-					ARRAY_SIZE(fxxxx_in_temp_attr));
+					f71858fg_temp_attr,
+					ARRAY_SIZE(f71858fg_temp_attr));
 			break;
 		case f8000:
 			err = f71882fg_create_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			break;
+		default:
+			err = f71882fg_create_sysfs_files(pdev,
+				&fxxxx_temp_attr[0][0],
+				ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
 		}
 		if (err)
 			goto exit_unregister_sysfs;
+
+		if (f71882fg_has_beep[data->type]) {
+			err = f71882fg_create_sysfs_files(pdev,
+					&fxxxx_temp_beep_attr[0][0],
+					ARRAY_SIZE(fxxxx_temp_beep_attr[0])
+						* nr_temps);
+			if (err)
+				goto exit_unregister_sysfs;
+		}
+
+		for (i = 0; i < F71882FG_MAX_INS; i++) {
+			if (f71882fg_has_in[data->type][i]) {
+				err = device_create_file(&pdev->dev,
+						&fxxxx_in_attr[i].dev_attr);
+				if (err)
+					goto exit_unregister_sysfs;
+			}
+		}
+		if (f71882fg_has_in1_alarm[data->type]) {
+			err = f71882fg_create_sysfs_files(pdev,
+					fxxxx_in1_alarm_attr,
+					ARRAY_SIZE(fxxxx_in1_alarm_attr));
+			if (err)
+				goto exit_unregister_sysfs;
+		}
 	}
 
 	if (start_reg & 0x02) {
+		switch (data->type) {
+		case f71808e:
+		case f71869:
+			/* These always have signed auto point temps */
+			data->auto_point_temp_signed = 1;
+			/* Fall through to select correct fan/pwm reg bank! */
+		case f71889fg:
+		case f71889ed:
+			reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
+			if (reg & F71882FG_FAN_NEG_TEMP_EN)
+				data->auto_point_temp_signed = 1;
+			/* Ensure banked pwm registers point to right bank */
+			reg &= ~F71882FG_FAN_PROG_SEL;
+			f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
+			break;
+		default:
+			break;
+		}
+
 		data->pwm_enable =
 			f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
 
@@ -2013,8 +2163,11 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 		case f71862fg:
 			err = (data->pwm_enable & 0x15) != 0x15;
 			break;
+		case f71808e:
+		case f71869:
 		case f71882fg:
 		case f71889fg:
+		case f71889ed:
 			err = 0;
 			break;
 		case f8000:
@@ -2034,8 +2187,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 		if (err)
 			goto exit_unregister_sysfs;
 
-		if (data->type == f71862fg || data->type == f71882fg ||
-		    data->type == f71889fg) {
+		if (f71882fg_has_beep[data->type]) {
 			err = f71882fg_create_sysfs_files(pdev,
 					fxxxx_fan_beep_attr, nr_fans);
 			if (err)
@@ -2043,11 +2195,42 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 		}
 
 		switch (data->type) {
+		case f71808e:
+		case f71869:
+		case f71889fg:
+		case f71889ed:
+			for (i = 0; i < nr_fans; i++) {
+				data->pwm_auto_point_mapping[i] =
+					f71882fg_read8(data,
+						F71882FG_REG_POINT_MAPPING(i));
+				if ((data->pwm_auto_point_mapping[i] & 0x80) ||
+				    (data->pwm_auto_point_mapping[i] & 3) == 0)
+					break;
+			}
+			if (i != nr_fans) {
+				dev_warn(&pdev->dev,
+					 "Auto pwm controlled by raw digital "
+					 "data, disabling pwm auto_point "
+					 "sysfs attributes\n");
+				goto no_pwm_auto_point;
+			}
+			break;
+		default:
+			break;
+		}
+
+		switch (data->type) {
 		case f71862fg:
 			err = f71882fg_create_sysfs_files(pdev,
 					f71862fg_auto_pwm_attr,
 					ARRAY_SIZE(f71862fg_auto_pwm_attr));
 			break;
+		case f71808e:
+		case f71869:
+			err = f71882fg_create_sysfs_files(pdev,
+					f71869_auto_pwm_attr,
+					ARRAY_SIZE(f71869_auto_pwm_attr));
+			break;
 		case f8000:
 			err = f71882fg_create_sysfs_files(pdev,
 					f8000_fan_attr,
@@ -2058,23 +2241,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 					f8000_auto_pwm_attr,
 					ARRAY_SIZE(f8000_auto_pwm_attr));
 			break;
-		case f71889fg:
-			for (i = 0; i < nr_fans; i++) {
-				data->pwm_auto_point_mapping[i] =
-					f71882fg_read8(data,
-						F71882FG_REG_POINT_MAPPING(i));
-				if (data->pwm_auto_point_mapping[i] & 0x80)
-					break;
-			}
-			if (i != nr_fans) {
-				dev_warn(&pdev->dev,
-					 "Auto pwm controlled by raw digital "
-					 "data, disabling pwm auto_point "
-					 "sysfs attributes\n");
-				break;
-			}
-			/* fall through */
-		default: /* f71858fg / f71882fg */
+		default:
 			err = f71882fg_create_sysfs_files(pdev,
 				&fxxxx_auto_pwm_attr[0][0],
 				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
@@ -2082,6 +2249,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
 		if (err)
 			goto exit_unregister_sysfs;
 
+no_pwm_auto_point:
 		for (i = 0; i < nr_fans; i++)
 			dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
 				 (data->pwm_enable & (1 << 2 * i)) ?
@@ -2108,7 +2276,8 @@ exit_free:
 static int f71882fg_remove(struct platform_device *pdev)
 {
 	struct f71882fg_data *data = platform_get_drvdata(pdev);
-	int nr_fans = (data->type == f71882fg) ? 4 : 3;
+	int i, nr_fans = (data->type == f71882fg) ? 4 : 3;
+	int nr_temps = (data->type == f71808e) ? 2 : 3;
 	u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
 
 	if (data->hwmon_dev)
@@ -2121,29 +2290,39 @@ static int f71882fg_remove(struct platform_device *pdev)
 		case f71858fg:
 			if (data->temp_config & 0x10)
 				f71882fg_remove_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			else
 				f71882fg_remove_sysfs_files(pdev,
-					f71858fg_in_temp_attr,
-					ARRAY_SIZE(f71858fg_in_temp_attr));
-			break;
-		case f71882fg:
-		case f71889fg:
-			f71882fg_remove_sysfs_files(pdev,
-					fxxxx_in1_alarm_attr,
-					ARRAY_SIZE(fxxxx_in1_alarm_attr));
-			/* fall through! */
-		case f71862fg:
-			f71882fg_remove_sysfs_files(pdev,
-					fxxxx_in_temp_attr,
-					ARRAY_SIZE(fxxxx_in_temp_attr));
+					f71858fg_temp_attr,
+					ARRAY_SIZE(f71858fg_temp_attr));
 			break;
 		case f8000:
 			f71882fg_remove_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			break;
+		default:
+			f71882fg_remove_sysfs_files(pdev,
+				&fxxxx_temp_attr[0][0],
+				ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
+		}
+		if (f71882fg_has_beep[data->type]) {
+			f71882fg_remove_sysfs_files(pdev,
+			       &fxxxx_temp_beep_attr[0][0],
+			       ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
+		}
+
+		for (i = 0; i < F71882FG_MAX_INS; i++) {
+			if (f71882fg_has_in[data->type][i]) {
+				device_remove_file(&pdev->dev,
+						&fxxxx_in_attr[i].dev_attr);
+			}
+		}
+		if (f71882fg_has_in1_alarm[data->type]) {
+			f71882fg_remove_sysfs_files(pdev,
+					fxxxx_in1_alarm_attr,
+					ARRAY_SIZE(fxxxx_in1_alarm_attr));
 		}
 	}
 
@@ -2151,10 +2330,10 @@ static int f71882fg_remove(struct platform_device *pdev)
 		f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
 				ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
 
-		if (data->type == f71862fg || data->type == f71882fg ||
-		    data->type == f71889fg)
+		if (f71882fg_has_beep[data->type]) {
 			f71882fg_remove_sysfs_files(pdev,
 					fxxxx_fan_beep_attr, nr_fans);
+		}
 
 		switch (data->type) {
 		case f71862fg:
@@ -2162,6 +2341,12 @@ static int f71882fg_remove(struct platform_device *pdev)
 					f71862fg_auto_pwm_attr,
 					ARRAY_SIZE(f71862fg_auto_pwm_attr));
 			break;
+		case f71808e:
+		case f71869:
+			f71882fg_remove_sysfs_files(pdev,
+					f71869_auto_pwm_attr,
+					ARRAY_SIZE(f71869_auto_pwm_attr));
+			break;
 		case f8000:
 			f71882fg_remove_sysfs_files(pdev,
 					f8000_fan_attr,
@@ -2170,7 +2355,7 @@ static int f71882fg_remove(struct platform_device *pdev)
 					f8000_auto_pwm_attr,
 					ARRAY_SIZE(f8000_auto_pwm_attr));
 			break;
-		default: /* f71858fg / f71882fg / f71889fg */
+		default:
 			f71882fg_remove_sysfs_files(pdev,
 				&fxxxx_auto_pwm_attr[0][0],
 				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
@@ -2200,18 +2385,27 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
 
 	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
 	switch (devid) {
+	case SIO_F71808E_ID:
+		sio_data->type = f71808e;
+		break;
 	case SIO_F71858_ID:
 		sio_data->type = f71858fg;
 		break;
 	case SIO_F71862_ID:
 		sio_data->type = f71862fg;
 		break;
+	case SIO_F71869_ID:
+		sio_data->type = f71869;
+		break;
 	case SIO_F71882_ID:
 		sio_data->type = f71882fg;
 		break;
 	case SIO_F71889_ID:
 		sio_data->type = f71889fg;
 		break;
+	case SIO_F71889E_ID:
+		sio_data->type = f71889ed;
+		break;
 	case SIO_F8000_ID:
 		sio_data->type = f8000;
 		break;
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
deleted file mode 100644
index 3d21fa2..0000000
--- a/drivers/hwmon/hp_accel.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- *  hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008-2009 Pavel Machek
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/leds.h>
-#include <acpi/acpi_drivers.h>
-#include <asm/atomic.h>
-#include "lis3lv02d.h"
-
-#define DRIVER_NAME     "lis3lv02d"
-#define ACPI_MDPS_CLASS "accelerometer"
-
-/* Delayed LEDs infrastructure ------------------------------------ */
-
-/* Special LED class that can defer work */
-struct delayed_led_classdev {
-	struct led_classdev led_classdev;
-	struct work_struct work;
-	enum led_brightness new_brightness;
-
-	unsigned int led;		/* For driver */
-	void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
-};
-
-static inline void delayed_set_status_worker(struct work_struct *work)
-{
-	struct delayed_led_classdev *data =
-			container_of(work, struct delayed_led_classdev, work);
-
-	data->set_brightness(data, data->new_brightness);
-}
-
-static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
-			      enum led_brightness brightness)
-{
-	struct delayed_led_classdev *data = container_of(led_cdev,
-			     struct delayed_led_classdev, led_classdev);
-	data->new_brightness = brightness;
-	schedule_work(&data->work);
-}
-
-/* HP-specific accelerometer driver ------------------------------------ */
-
-/* For automatic insertion of the module */
-static struct acpi_device_id lis3lv02d_device_ids[] = {
-	{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
-	{"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
-
-
-/**
- * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
- * @lis3: pointer to the device struct
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
-{
-	struct acpi_device *dev = lis3->bus_priv;
-	if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
-				 NULL, NULL) != AE_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * lis3lv02d_acpi_read - ACPI ALRD method: read a register
- * @lis3: pointer to the device struct
- * @reg:    the register to read
- * @ret:    result of the operation
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
-{
-	struct acpi_device *dev = lis3->bus_priv;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list args = { 1, &arg0 };
-	unsigned long long lret;
-	acpi_status status;
-
-	arg0.integer.value = reg;
-
-	status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
-	*ret = lret;
-	return (status != AE_OK) ? -EINVAL : 0;
-}
-
-/**
- * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
- * @lis3: pointer to the device struct
- * @reg:    the register to write to
- * @val:    the value to write
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
-{
-	struct acpi_device *dev = lis3->bus_priv;
-	unsigned long long ret; /* Not used when writting */
-	union acpi_object in_obj[2];
-	struct acpi_object_list args = { 2, in_obj };
-
-	in_obj[0].type          = ACPI_TYPE_INTEGER;
-	in_obj[0].integer.value = reg;
-	in_obj[1].type          = ACPI_TYPE_INTEGER;
-	in_obj[1].integer.value = val;
-
-	if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
-{
-	lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
-	pr_info("hardware type %s found\n", dmi->ident);
-
-	return 1;
-}
-
-/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
- * If the value is negative, the opposite of the hw value is used. */
-#define DEFINE_CONV(name, x, y, z)			      \
-	static union axis_conversion lis3lv02d_axis_##name = \
-		{ .as_array = { x, y, z } }
-DEFINE_CONV(normal, 1, 2, 3);
-DEFINE_CONV(y_inverted, 1, -2, 3);
-DEFINE_CONV(x_inverted, -1, 2, 3);
-DEFINE_CONV(z_inverted, 1, 2, -3);
-DEFINE_CONV(xy_swap, 2, 1, 3);
-DEFINE_CONV(xy_rotated_left, -2, 1, 3);
-DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
-DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
-DEFINE_CONV(xy_rotated_right, 2, -1, 3);
-DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
-
-#define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
-	.ident = _ident,				\
-	.callback = lis3lv02d_dmi_matched,		\
-	.matches = {					\
-		DMI_MATCH(DMI_PRODUCT_NAME, _name)	\
-	},						\
-	.driver_data = &lis3lv02d_axis_##_axis		\
-}
-
-#define AXIS_DMI_MATCH2(_ident, _class1, _name1,	\
-				_class2, _name2,	\
-				_axis) {		\
-	.ident = _ident,				\
-	.callback = lis3lv02d_dmi_matched,		\
-	.matches = {					\
-		DMI_MATCH(DMI_##_class1, _name1),	\
-		DMI_MATCH(DMI_##_class2, _name2),	\
-	},						\
-	.driver_data = &lis3lv02d_axis_##_axis		\
-}
-static struct dmi_system_id lis3lv02d_dmi_ids[] = {
-	/* product names are truncated to match all kinds of a same model */
-	AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
-	AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
-	AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
-	AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
-	AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
-	AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
-	AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
-	AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
-	AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
-	AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
-	AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
-	AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
-	AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
-	AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
-	AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
-	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
-	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
-	/* Intel-based HP Pavilion dv5 */
-	AXIS_DMI_MATCH2("HPDV5_I",
-			PRODUCT_NAME, "HP Pavilion dv5",
-			BOARD_NAME, "3603",
-			x_inverted),
-	/* AMD-based HP Pavilion dv5 */
-	AXIS_DMI_MATCH2("HPDV5_A",
-			PRODUCT_NAME, "HP Pavilion dv5",
-			BOARD_NAME, "3600",
-			y_inverted),
-	AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
-	AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
-	AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
-	AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
-	AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
-	AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
-	AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
-	AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
-	AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
-	{ NULL, }
-/* Laptop models without axis info (yet):
- * "NC6910" "HP Compaq 6910"
- * "NC2400" "HP Compaq nc2400"
- * "NX74x0" "HP Compaq nx74"
- * "NX6325" "HP Compaq nx6325"
- * "NC4400" "HP Compaq nc4400"
- */
-};
-
-static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
-{
-	struct acpi_device *dev = lis3_dev.bus_priv;
-	unsigned long long ret; /* Not used when writing */
-	union acpi_object in_obj[1];
-	struct acpi_object_list args = { 1, in_obj };
-
-	in_obj[0].type          = ACPI_TYPE_INTEGER;
-	in_obj[0].integer.value = !!value;
-
-	acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
-}
-
-static struct delayed_led_classdev hpled_led = {
-	.led_classdev = {
-		.name			= "hp::hddprotect",
-		.default_trigger	= "none",
-		.brightness_set		= delayed_sysfs_set,
-		.flags                  = LED_CORE_SUSPENDRESUME,
-	},
-	.set_brightness = hpled_set,
-};
-
-static acpi_status
-lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
-{
-	if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
-		struct acpi_resource_extended_irq *irq;
-		u32 *device_irq = context;
-
-		irq = &resource->data.extended_irq;
-		*device_irq = irq->interrupts[0];
-	}
-
-	return AE_OK;
-}
-
-static void lis3lv02d_enum_resources(struct acpi_device *device)
-{
-	acpi_status status;
-
-	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-					lis3lv02d_get_resource, &lis3_dev.irq);
-	if (ACPI_FAILURE(status))
-		printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
-}
-
-static int lis3lv02d_add(struct acpi_device *device)
-{
-	int ret;
-
-	if (!device)
-		return -EINVAL;
-
-	lis3_dev.bus_priv = device;
-	lis3_dev.init = lis3lv02d_acpi_init;
-	lis3_dev.read = lis3lv02d_acpi_read;
-	lis3_dev.write = lis3lv02d_acpi_write;
-	strcpy(acpi_device_name(device), DRIVER_NAME);
-	strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
-	device->driver_data = &lis3_dev;
-
-	/* obtain IRQ number of our device from ACPI */
-	lis3lv02d_enum_resources(device);
-
-	/* If possible use a "standard" axes order */
-	if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
-		pr_info("Using custom axes %d,%d,%d\n",
-			lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
-	} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
-		pr_info("laptop model unknown, using default axes configuration\n");
-		lis3_dev.ac = lis3lv02d_axis_normal;
-	}
-
-	/* call the core layer do its init */
-	ret = lis3lv02d_init_device(&lis3_dev);
-	if (ret)
-		return ret;
-
-	INIT_WORK(&hpled_led.work, delayed_set_status_worker);
-	ret = led_classdev_register(NULL, &hpled_led.led_classdev);
-	if (ret) {
-		lis3lv02d_joystick_disable();
-		lis3lv02d_poweroff(&lis3_dev);
-		flush_work(&hpled_led.work);
-		return ret;
-	}
-
-	return ret;
-}
-
-static int lis3lv02d_remove(struct acpi_device *device, int type)
-{
-	if (!device)
-		return -EINVAL;
-
-	lis3lv02d_joystick_disable();
-	lis3lv02d_poweroff(&lis3_dev);
-
-	led_classdev_unregister(&hpled_led.led_classdev);
-	flush_work(&hpled_led.work);
-
-	return lis3lv02d_remove_fs(&lis3_dev);
-}
-
-
-#ifdef CONFIG_PM
-static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
-{
-	/* make sure the device is off when we suspend */
-	lis3lv02d_poweroff(&lis3_dev);
-	return 0;
-}
-
-static int lis3lv02d_resume(struct acpi_device *device)
-{
-	lis3lv02d_poweron(&lis3_dev);
-	return 0;
-}
-#else
-#define lis3lv02d_suspend NULL
-#define lis3lv02d_resume NULL
-#endif
-
-/* For the HP MDPS aka 3D Driveguard */
-static struct acpi_driver lis3lv02d_driver = {
-	.name  = DRIVER_NAME,
-	.class = ACPI_MDPS_CLASS,
-	.ids   = lis3lv02d_device_ids,
-	.ops = {
-		.add     = lis3lv02d_add,
-		.remove  = lis3lv02d_remove,
-		.suspend = lis3lv02d_suspend,
-		.resume  = lis3lv02d_resume,
-	}
-};
-
-static int __init lis3lv02d_init_module(void)
-{
-	int ret;
-
-	if (acpi_disabled)
-		return -ENODEV;
-
-	ret = acpi_bus_register_driver(&lis3lv02d_driver);
-	if (ret < 0)
-		return ret;
-
-	pr_info("driver loaded\n");
-
-	return 0;
-}
-
-static void __exit lis3lv02d_exit_module(void)
-{
-	acpi_bus_unregister_driver(&lis3lv02d_driver);
-}
-
-MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
-MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
-MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init_module);
-module_exit(lis3lv02d_exit_module);
-
diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c
new file mode 100644
index 0000000..58eded2
--- /dev/null
+++ b/drivers/hwmon/lineage-pem.c
@@ -0,0 +1,586 @@
+/*
+ * Driver for Lineage Compact Power Line series of power entry modules.
+ *
+ * Copyright (C) 2010, 2011 Ericsson AB.
+ *
+ * Documentation:
+ *  http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/*
+ * This driver supports various Lineage Compact Power Line DC/DC and AC/DC
+ * converters such as CP1800, CP2000AC, CP2000DC, CP2100DC, and others.
+ *
+ * The devices are nominally PMBus compliant. However, most standard PMBus
+ * commands are not supported. Specifically, all hardware monitoring and
+ * status reporting commands are non-standard. For this reason, a standard
+ * PMBus driver can not be used.
+ *
+ * All Lineage CPL devices have a built-in I2C bus master selector (PCA9541).
+ * To ensure device access, this driver should only be used as client driver
+ * to the pca9541 I2C master selector driver.
+ */
+
+/* Command codes */
+#define PEM_OPERATION		0x01
+#define PEM_CLEAR_INFO_FLAGS	0x03
+#define PEM_VOUT_COMMAND	0x21
+#define PEM_VOUT_OV_FAULT_LIMIT	0x40
+#define PEM_READ_DATA_STRING	0xd0
+#define PEM_READ_INPUT_STRING	0xdc
+#define PEM_READ_FIRMWARE_REV	0xdd
+#define PEM_READ_RUN_TIMER	0xde
+#define PEM_FAN_HI_SPEED	0xdf
+#define PEM_FAN_NORMAL_SPEED	0xe0
+#define PEM_READ_FAN_SPEED	0xe1
+
+/* offsets in data string */
+#define PEM_DATA_STATUS_2	0
+#define PEM_DATA_STATUS_1	1
+#define PEM_DATA_ALARM_2	2
+#define PEM_DATA_ALARM_1	3
+#define PEM_DATA_VOUT_LSB	4
+#define PEM_DATA_VOUT_MSB	5
+#define PEM_DATA_CURRENT	6
+#define PEM_DATA_TEMP		7
+
+/* Virtual entries, to report constants */
+#define PEM_DATA_TEMP_MAX	10
+#define PEM_DATA_TEMP_CRIT	11
+
+/* offsets in input string */
+#define PEM_INPUT_VOLTAGE	0
+#define PEM_INPUT_POWER_LSB	1
+#define PEM_INPUT_POWER_MSB	2
+
+/* offsets in fan data */
+#define PEM_FAN_ADJUSTMENT	0
+#define PEM_FAN_FAN1		1
+#define PEM_FAN_FAN2		2
+#define PEM_FAN_FAN3		3
+
+/* Status register bits */
+#define STS1_OUTPUT_ON		(1 << 0)
+#define STS1_LEDS_FLASHING	(1 << 1)
+#define STS1_EXT_FAULT		(1 << 2)
+#define STS1_SERVICE_LED_ON	(1 << 3)
+#define STS1_SHUTDOWN_OCCURRED	(1 << 4)
+#define STS1_INT_FAULT		(1 << 5)
+#define STS1_ISOLATION_TEST_OK	(1 << 6)
+
+#define STS2_ENABLE_PIN_HI	(1 << 0)
+#define STS2_DATA_OUT_RANGE	(1 << 1)
+#define STS2_RESTARTED_OK	(1 << 1)
+#define STS2_ISOLATION_TEST_FAIL (1 << 3)
+#define STS2_HIGH_POWER_CAP	(1 << 4)
+#define STS2_INVALID_INSTR	(1 << 5)
+#define STS2_WILL_RESTART	(1 << 6)
+#define STS2_PEC_ERR		(1 << 7)
+
+/* Alarm register bits */
+#define ALRM1_VIN_OUT_LIMIT	(1 << 0)
+#define ALRM1_VOUT_OUT_LIMIT	(1 << 1)
+#define ALRM1_OV_VOLT_SHUTDOWN	(1 << 2)
+#define ALRM1_VIN_OVERCURRENT	(1 << 3)
+#define ALRM1_TEMP_WARNING	(1 << 4)
+#define ALRM1_TEMP_SHUTDOWN	(1 << 5)
+#define ALRM1_PRIMARY_FAULT	(1 << 6)
+#define ALRM1_POWER_LIMIT	(1 << 7)
+
+#define ALRM2_5V_OUT_LIMIT	(1 << 1)
+#define ALRM2_TEMP_FAULT	(1 << 2)
+#define ALRM2_OV_LOW		(1 << 3)
+#define ALRM2_DCDC_TEMP_HIGH	(1 << 4)
+#define ALRM2_PRI_TEMP_HIGH	(1 << 5)
+#define ALRM2_NO_PRIMARY	(1 << 6)
+#define ALRM2_FAN_FAULT		(1 << 7)
+
+#define FIRMWARE_REV_LEN	4
+#define DATA_STRING_LEN		9
+#define INPUT_STRING_LEN	5	/* 4 for most devices	*/
+#define FAN_SPEED_LEN		5
+
+struct pem_data {
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	bool valid;
+	bool fans_supported;
+	int input_length;
+	unsigned long last_updated;	/* in jiffies */
+
+	u8 firmware_rev[FIRMWARE_REV_LEN];
+	u8 data_string[DATA_STRING_LEN];
+	u8 input_string[INPUT_STRING_LEN];
+	u8 fan_speed[FAN_SPEED_LEN];
+};
+
+static int pem_read_block(struct i2c_client *client, u8 command, u8 *data,
+			  int data_len)
+{
+	u8 block_buffer[I2C_SMBUS_BLOCK_MAX];
+	int result;
+
+	result = i2c_smbus_read_block_data(client, command, block_buffer);
+	if (unlikely(result < 0))
+		goto abort;
+	if (unlikely(result == 0xff || result != data_len)) {
+		result = -EIO;
+		goto abort;
+	}
+	memcpy(data, block_buffer, data_len);
+	result = 0;
+abort:
+	return result;
+}
+
+static struct pem_data *pem_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pem_data *data = i2c_get_clientdata(client);
+	struct pem_data *ret = data;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		int result;
+
+		/* Read data string */
+		result = pem_read_block(client, PEM_READ_DATA_STRING,
+					data->data_string,
+					sizeof(data->data_string));
+		if (unlikely(result < 0)) {
+			ret = ERR_PTR(result);
+			goto abort;
+		}
+
+		/* Read input string */
+		if (data->input_length) {
+			result = pem_read_block(client, PEM_READ_INPUT_STRING,
+						data->input_string,
+						data->input_length);
+			if (unlikely(result < 0)) {
+				ret = ERR_PTR(result);
+				goto abort;
+			}
+		}
+
+		/* Read fan speeds */
+		if (data->fans_supported) {
+			result = pem_read_block(client, PEM_READ_FAN_SPEED,
+						data->fan_speed,
+						sizeof(data->fan_speed));
+			if (unlikely(result < 0)) {
+				ret = ERR_PTR(result);
+				goto abort;
+			}
+		}
+
+		i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static long pem_get_data(u8 *data, int len, int index)
+{
+	long val;
+
+	switch (index) {
+	case PEM_DATA_VOUT_LSB:
+		val = (data[index] + (data[index+1] << 8)) * 5 / 2;
+		break;
+	case PEM_DATA_CURRENT:
+		val = data[index] * 200;
+		break;
+	case PEM_DATA_TEMP:
+		val = data[index] * 1000;
+		break;
+	case PEM_DATA_TEMP_MAX:
+		val = 97 * 1000;	/* 97 degrees C per datasheet */
+		break;
+	case PEM_DATA_TEMP_CRIT:
+		val = 107 * 1000;	/* 107 degrees C per datasheet */
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		val = 0;
+	}
+	return val;
+}
+
+static long pem_get_input(u8 *data, int len, int index)
+{
+	long val;
+
+	switch (index) {
+	case PEM_INPUT_VOLTAGE:
+		if (len == INPUT_STRING_LEN)
+			val = (data[index] + (data[index+1] << 8) - 75) * 1000;
+		else
+			val = (data[index] - 75) * 1000;
+		break;
+	case PEM_INPUT_POWER_LSB:
+		if (len == INPUT_STRING_LEN)
+			index++;
+		val = (data[index] + (data[index+1] << 8)) * 1000000L;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		val = 0;
+	}
+	return val;
+}
+
+static long pem_get_fan(u8 *data, int len, int index)
+{
+	long val;
+
+	switch (index) {
+	case PEM_FAN_FAN1:
+	case PEM_FAN_FAN2:
+	case PEM_FAN_FAN3:
+		val = data[index] * 100;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		val = 0;
+	}
+	return val;
+}
+
+/*
+ * Show boolean, either a fault or an alarm.
+ * .nr points to the register, .index is the bit mask to check
+ */
+static ssize_t pem_show_bool(struct device *dev,
+			     struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+	struct pem_data *data = pem_update_device(dev);
+	u8 status;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	status = data->data_string[attr->nr] & attr->index;
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!status);
+}
+
+static ssize_t pem_show_data(struct device *dev, struct device_attribute *da,
+			     char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pem_data *data = pem_update_device(dev);
+	long value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = pem_get_data(data->data_string, sizeof(data->data_string),
+			     attr->index);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+}
+
+static ssize_t pem_show_input(struct device *dev, struct device_attribute *da,
+			      char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pem_data *data = pem_update_device(dev);
+	long value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = pem_get_input(data->input_string, sizeof(data->input_string),
+			      attr->index);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+}
+
+static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da,
+			    char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pem_data *data = pem_update_device(dev);
+	long value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = pem_get_fan(data->fan_speed, sizeof(data->fan_speed),
+			    attr->index);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+}
+
+/* Voltages */
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_VOUT_LSB);
+static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_VOUT_OUT_LIMIT);
+static SENSOR_DEVICE_ATTR_2(in1_crit_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_OV_VOLT_SHUTDOWN);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, pem_show_input, NULL,
+			  PEM_INPUT_VOLTAGE);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1,
+			    ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT);
+
+/* Currents */
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_CURRENT);
+static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_VIN_OVERCURRENT);
+
+/* Power */
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pem_show_input, NULL,
+			  PEM_INPUT_POWER_LSB);
+static SENSOR_DEVICE_ATTR_2(power1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_POWER_LIMIT);
+
+/* Fans */
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pem_show_fan, NULL,
+			  PEM_FAN_FAN1);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, pem_show_fan, NULL,
+			  PEM_FAN_FAN2);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, pem_show_fan, NULL,
+			  PEM_FAN_FAN3);
+static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_2, ALRM2_FAN_FAULT);
+
+/* Temperatures */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_TEMP_MAX);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_TEMP_CRIT);
+static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_TEMP_WARNING);
+static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_TEMP_SHUTDOWN);
+static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_2, ALRM2_TEMP_FAULT);
+
+static struct attribute *pem_attributes[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_power1_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
+
+	NULL,
+};
+
+static const struct attribute_group pem_group = {
+	.attrs = pem_attributes,
+};
+
+static struct attribute *pem_input_attributes[] = {
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	&sensor_dev_attr_power1_input.dev_attr.attr,
+};
+
+static const struct attribute_group pem_input_group = {
+	.attrs = pem_input_attributes,
+};
+
+static struct attribute *pem_fan_attributes[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+};
+
+static const struct attribute_group pem_fan_group = {
+	.attrs = pem_fan_attributes,
+};
+
+static int pem_probe(struct i2c_client *client,
+		     const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct pem_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA
+				     | I2C_FUNC_SMBUS_WRITE_BYTE))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/*
+	 * We use the next two commands to determine if the device is really
+	 * there.
+	 */
+	ret = pem_read_block(client, PEM_READ_FIRMWARE_REV,
+			     data->firmware_rev, sizeof(data->firmware_rev));
+	if (ret < 0)
+		goto out_kfree;
+
+	ret = i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);
+	if (ret < 0)
+		goto out_kfree;
+
+	dev_info(&client->dev, "Firmware revision %d.%d.%d\n",
+		 data->firmware_rev[0], data->firmware_rev[1],
+		 data->firmware_rev[2]);
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&client->dev.kobj, &pem_group);
+	if (ret)
+		goto out_kfree;
+
+	/*
+	 * Check if input readings are supported.
+	 * This is the case if we can read input data,
+	 * and if the returned data is not all zeros.
+	 * Note that input alarms are always supported.
+	 */
+	ret = pem_read_block(client, PEM_READ_INPUT_STRING,
+			     data->input_string,
+			     sizeof(data->input_string) - 1);
+	if (!ret && (data->input_string[0] || data->input_string[1] ||
+		     data->input_string[2]))
+		data->input_length = sizeof(data->input_string) - 1;
+	else if (ret < 0) {
+		/* Input string is one byte longer for some devices */
+		ret = pem_read_block(client, PEM_READ_INPUT_STRING,
+				    data->input_string,
+				    sizeof(data->input_string));
+		if (!ret && (data->input_string[0] || data->input_string[1] ||
+			    data->input_string[2] || data->input_string[3]))
+			data->input_length = sizeof(data->input_string);
+	}
+	ret = 0;
+	if (data->input_length) {
+		ret = sysfs_create_group(&client->dev.kobj, &pem_input_group);
+		if (ret)
+			goto out_remove_groups;
+	}
+
+	/*
+	 * Check if fan speed readings are supported.
+	 * This is the case if we can read fan speed data,
+	 * and if the returned data is not all zeros.
+	 * Note that the fan alarm is always supported.
+	 */
+	ret = pem_read_block(client, PEM_READ_FAN_SPEED,
+			     data->fan_speed,
+			     sizeof(data->fan_speed));
+	if (!ret && (data->fan_speed[0] || data->fan_speed[1] ||
+		     data->fan_speed[2] || data->fan_speed[3])) {
+		data->fans_supported = true;
+		ret = sysfs_create_group(&client->dev.kobj, &pem_fan_group);
+		if (ret)
+			goto out_remove_groups;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto out_remove_groups;
+	}
+
+	return 0;
+
+out_remove_groups:
+	sysfs_remove_group(&client->dev.kobj, &pem_input_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_group);
+out_kfree:
+	kfree(data);
+	return ret;
+}
+
+static int pem_remove(struct i2c_client *client)
+{
+	struct pem_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+
+	sysfs_remove_group(&client->dev.kobj, &pem_input_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_group);
+
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id pem_id[] = {
+	{"lineage_pem", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, pem_id);
+
+static struct i2c_driver pem_driver = {
+	.driver = {
+		   .name = "lineage_pem",
+		   },
+	.probe = pem_probe,
+	.remove = pem_remove,
+	.id_table = pem_id,
+};
+
+static int __init pem_init(void)
+{
+	return i2c_add_driver(&pem_driver);
+}
+
+static void __exit pem_exit(void)
+{
+	i2c_del_driver(&pem_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION("Lineage CPL PEM hardware monitoring driver");
+MODULE_LICENSE("GPL");
+
+module_init(pem_init);
+module_exit(pem_exit);
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
deleted file mode 100644
index d805e8e..0000000
--- a/drivers/hwmon/lis3lv02d.c
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*
- *  lis3lv02d.c - ST LIS3LV02DL accelerometer driver
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008-2009 Pavel Machek
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/input-polldev.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/pm_runtime.h>
-#include <asm/atomic.h>
-#include "lis3lv02d.h"
-
-#define DRIVER_NAME     "lis3lv02d"
-
-/* joystick device poll interval in milliseconds */
-#define MDPS_POLL_INTERVAL 50
-#define MDPS_POLL_MIN	   0
-#define MDPS_POLL_MAX	   2000
-
-#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
-
-#define SELFTEST_OK	       0
-#define SELFTEST_FAIL	       -1
-#define SELFTEST_IRQ	       -2
-
-#define IRQ_LINE0	       0
-#define IRQ_LINE1	       1
-
-/*
- * The sensor can also generate interrupts (DRDY) but it's pretty pointless
- * because they are generated even if the data do not change. So it's better
- * to keep the interrupt for the free-fall event. The values are updated at
- * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
- * some low processor, we poll the sensor only at 20Hz... enough for the
- * joystick.
- */
-
-#define LIS3_PWRON_DELAY_WAI_12B	(5000)
-#define LIS3_PWRON_DELAY_WAI_8B		(3000)
-
-/*
- * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
- * LIS302D spec says: 18 mG / digit
- * LIS3_ACCURACY is used to increase accuracy of the intermediate
- * calculation results.
- */
-#define LIS3_ACCURACY			1024
-/* Sensitivity values for -2G +2G scale */
-#define LIS3_SENSITIVITY_12B		((LIS3_ACCURACY * 1000) / 1024)
-#define LIS3_SENSITIVITY_8B		(18 * LIS3_ACCURACY)
-
-#define LIS3_DEFAULT_FUZZ_12B		3
-#define LIS3_DEFAULT_FLAT_12B		3
-#define LIS3_DEFAULT_FUZZ_8B		1
-#define LIS3_DEFAULT_FLAT_8B		1
-
-struct lis3lv02d lis3_dev = {
-	.misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
-};
-
-EXPORT_SYMBOL_GPL(lis3_dev);
-
-/* just like param_set_int() but does sanity-check so that it won't point
- * over the axis array size
- */
-static int param_set_axis(const char *val, const struct kernel_param *kp)
-{
-	int ret = param_set_int(val, kp);
-	if (!ret) {
-		int val = *(int *)kp->arg;
-		if (val < 0)
-			val = -val;
-		if (!val || val > 3)
-			return -EINVAL;
-	}
-	return ret;
-}
-
-static struct kernel_param_ops param_ops_axis = {
-	.set = param_set_axis,
-	.get = param_get_int,
-};
-
-module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
-MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
-
-static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
-{
-	s8 lo;
-	if (lis3->read(lis3, reg, &lo) < 0)
-		return 0;
-
-	return lo;
-}
-
-static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
-{
-	u8 lo, hi;
-
-	lis3->read(lis3, reg - 1, &lo);
-	lis3->read(lis3, reg, &hi);
-	/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
-	return (s16)((hi << 8) | lo);
-}
-
-/**
- * lis3lv02d_get_axis - For the given axis, give the value converted
- * @axis:      1,2,3 - can also be negative
- * @hw_values: raw values returned by the hardware
- *
- * Returns the converted value.
- */
-static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
-{
-	if (axis > 0)
-		return hw_values[axis - 1];
-	else
-		return -hw_values[-axis - 1];
-}
-
-/**
- * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
- * @lis3: pointer to the device struct
- * @x:    where to store the X axis value
- * @y:    where to store the Y axis value
- * @z:    where to store the Z axis value
- *
- * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
- */
-static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
-{
-	int position[3];
-	int i;
-
-	if (lis3->blkread) {
-		if (lis3_dev.whoami == WAI_12B) {
-			u16 data[3];
-			lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
-			for (i = 0; i < 3; i++)
-				position[i] = (s16)le16_to_cpu(data[i]);
-		} else {
-			u8 data[5];
-			/* Data: x, dummy, y, dummy, z */
-			lis3->blkread(lis3, OUTX, 5, data);
-			for (i = 0; i < 3; i++)
-				position[i] = (s8)data[i * 2];
-		}
-	} else {
-		position[0] = lis3->read_data(lis3, OUTX);
-		position[1] = lis3->read_data(lis3, OUTY);
-		position[2] = lis3->read_data(lis3, OUTZ);
-	}
-
-	for (i = 0; i < 3; i++)
-		position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
-
-	*x = lis3lv02d_get_axis(lis3->ac.x, position);
-	*y = lis3lv02d_get_axis(lis3->ac.y, position);
-	*z = lis3lv02d_get_axis(lis3->ac.z, position);
-}
-
-/* conversion btw sampling rate and the register values */
-static int lis3_12_rates[4] = {40, 160, 640, 2560};
-static int lis3_8_rates[2] = {100, 400};
-static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
-
-/* ODR is Output Data Rate */
-static int lis3lv02d_get_odr(void)
-{
-	u8 ctrl;
-	int shift;
-
-	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-	ctrl &= lis3_dev.odr_mask;
-	shift = ffs(lis3_dev.odr_mask) - 1;
-	return lis3_dev.odrs[(ctrl >> shift)];
-}
-
-static int lis3lv02d_set_odr(int rate)
-{
-	u8 ctrl;
-	int i, len, shift;
-
-	if (!rate)
-		return -EINVAL;
-
-	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-	ctrl &= ~lis3_dev.odr_mask;
-	len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
-	shift = ffs(lis3_dev.odr_mask) - 1;
-
-	for (i = 0; i < len; i++)
-		if (lis3_dev.odrs[i] == rate) {
-			lis3_dev.write(&lis3_dev, CTRL_REG1,
-					ctrl | (i << shift));
-			return 0;
-		}
-	return -EINVAL;
-}
-
-static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
-{
-	u8 ctlreg, reg;
-	s16 x, y, z;
-	u8 selftest;
-	int ret;
-	u8 ctrl_reg_data;
-	unsigned char irq_cfg;
-
-	mutex_lock(&lis3->mutex);
-
-	irq_cfg = lis3->irq_cfg;
-	if (lis3_dev.whoami == WAI_8B) {
-		lis3->data_ready_count[IRQ_LINE0] = 0;
-		lis3->data_ready_count[IRQ_LINE1] = 0;
-
-		/* Change interrupt cfg to data ready for selftest */
-		atomic_inc(&lis3_dev.wake_thread);
-		lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
-		lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
-		lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
-				~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
-				(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
-	}
-
-	if (lis3_dev.whoami == WAI_3DC) {
-		ctlreg = CTRL_REG4;
-		selftest = CTRL4_ST0;
-	} else {
-		ctlreg = CTRL_REG1;
-		if (lis3_dev.whoami == WAI_12B)
-			selftest = CTRL1_ST;
-		else
-			selftest = CTRL1_STP;
-	}
-
-	lis3->read(lis3, ctlreg, &reg);
-	lis3->write(lis3, ctlreg, (reg | selftest));
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-	/* Read directly to avoid axis remap */
-	x = lis3->read_data(lis3, OUTX);
-	y = lis3->read_data(lis3, OUTY);
-	z = lis3->read_data(lis3, OUTZ);
-
-	/* back to normal settings */
-	lis3->write(lis3, ctlreg, reg);
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-	results[0] = x - lis3->read_data(lis3, OUTX);
-	results[1] = y - lis3->read_data(lis3, OUTY);
-	results[2] = z - lis3->read_data(lis3, OUTZ);
-
-	ret = 0;
-
-	if (lis3_dev.whoami == WAI_8B) {
-		/* Restore original interrupt configuration */
-		atomic_dec(&lis3_dev.wake_thread);
-		lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
-		lis3->irq_cfg = irq_cfg;
-
-		if ((irq_cfg & LIS3_IRQ1_MASK) &&
-			lis3->data_ready_count[IRQ_LINE0] < 2) {
-			ret = SELFTEST_IRQ;
-			goto fail;
-		}
-
-		if ((irq_cfg & LIS3_IRQ2_MASK) &&
-			lis3->data_ready_count[IRQ_LINE1] < 2) {
-			ret = SELFTEST_IRQ;
-			goto fail;
-		}
-	}
-
-	if (lis3->pdata) {
-		int i;
-		for (i = 0; i < 3; i++) {
-			/* Check against selftest acceptance limits */
-			if ((results[i] < lis3->pdata->st_min_limits[i]) ||
-			    (results[i] > lis3->pdata->st_max_limits[i])) {
-				ret = SELFTEST_FAIL;
-				goto fail;
-			}
-		}
-	}
-
-	/* test passed */
-fail:
-	mutex_unlock(&lis3->mutex);
-	return ret;
-}
-
-/*
- * Order of registers in the list affects to order of the restore process.
- * Perhaps it is a good idea to set interrupt enable register as a last one
- * after all other configurations
- */
-static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
-			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
-			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
-			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
-			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
-
-static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
-			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
-			       DD_THSE_L, DD_THSE_H,
-			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
-
-static inline void lis3_context_save(struct lis3lv02d *lis3)
-{
-	int i;
-	for (i = 0; i < lis3->regs_size; i++)
-		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
-	lis3->regs_stored = true;
-}
-
-static inline void lis3_context_restore(struct lis3lv02d *lis3)
-{
-	int i;
-	if (lis3->regs_stored)
-		for (i = 0; i < lis3->regs_size; i++)
-			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
-}
-
-void lis3lv02d_poweroff(struct lis3lv02d *lis3)
-{
-	if (lis3->reg_ctrl)
-		lis3_context_save(lis3);
-	/* disable X,Y,Z axis and power down */
-	lis3->write(lis3, CTRL_REG1, 0x00);
-	if (lis3->reg_ctrl)
-		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
-
-void lis3lv02d_poweron(struct lis3lv02d *lis3)
-{
-	u8 reg;
-
-	lis3->init(lis3);
-
-	/*
-	 * Common configuration
-	 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
-	 *      both have been read. So the value read will always be correct.
-	 * Set BOOT bit to refresh factory tuning values.
-	 */
-	lis3->read(lis3, CTRL_REG2, &reg);
-	if (lis3->whoami ==  WAI_12B)
-		reg |= CTRL2_BDU | CTRL2_BOOT;
-	else
-		reg |= CTRL2_BOOT_8B;
-	lis3->write(lis3, CTRL_REG2, reg);
-
-	/* LIS3 power on delay is quite long */
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-	if (lis3->reg_ctrl)
-		lis3_context_restore(lis3);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
-
-
-static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
-{
-	int x, y, z;
-
-	mutex_lock(&lis3_dev.mutex);
-	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-	input_report_abs(pidev->input, ABS_X, x);
-	input_report_abs(pidev->input, ABS_Y, y);
-	input_report_abs(pidev->input, ABS_Z, z);
-	input_sync(pidev->input);
-	mutex_unlock(&lis3_dev.mutex);
-}
-
-static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
-{
-	if (lis3_dev.pm_dev)
-		pm_runtime_get_sync(lis3_dev.pm_dev);
-
-	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
-		atomic_set(&lis3_dev.wake_thread, 1);
-	/*
-	 * Update coordinates for the case where poll interval is 0 and
-	 * the chip in running purely under interrupt control
-	 */
-	lis3lv02d_joystick_poll(pidev);
-}
-
-static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
-{
-	atomic_set(&lis3_dev.wake_thread, 0);
-	if (lis3_dev.pm_dev)
-		pm_runtime_put(lis3_dev.pm_dev);
-}
-
-static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
-{
-	if (!test_bit(0, &lis3_dev.misc_opened))
-		goto out;
-
-	/*
-	 * Be careful: on some HP laptops the bios force DD when on battery and
-	 * the lid is closed. This leads to interrupts as soon as a little move
-	 * is done.
-	 */
-	atomic_inc(&lis3_dev.count);
-
-	wake_up_interruptible(&lis3_dev.misc_wait);
-	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
-out:
-	if (atomic_read(&lis3_dev.wake_thread))
-		return IRQ_WAKE_THREAD;
-	return IRQ_HANDLED;
-}
-
-static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
-{
-	struct input_dev *dev = lis3->idev->input;
-	u8 click_src;
-
-	mutex_lock(&lis3->mutex);
-	lis3->read(lis3, CLICK_SRC, &click_src);
-
-	if (click_src & CLICK_SINGLE_X) {
-		input_report_key(dev, lis3->mapped_btns[0], 1);
-		input_report_key(dev, lis3->mapped_btns[0], 0);
-	}
-
-	if (click_src & CLICK_SINGLE_Y) {
-		input_report_key(dev, lis3->mapped_btns[1], 1);
-		input_report_key(dev, lis3->mapped_btns[1], 0);
-	}
-
-	if (click_src & CLICK_SINGLE_Z) {
-		input_report_key(dev, lis3->mapped_btns[2], 1);
-		input_report_key(dev, lis3->mapped_btns[2], 0);
-	}
-	input_sync(dev);
-	mutex_unlock(&lis3->mutex);
-}
-
-static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
-{
-	int dummy;
-
-	/* Dummy read to ack interrupt */
-	lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
-	lis3->data_ready_count[index]++;
-}
-
-static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
-{
-	struct lis3lv02d *lis3 = data;
-	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
-
-	if (irq_cfg == LIS3_IRQ1_CLICK)
-		lis302dl_interrupt_handle_click(lis3);
-	else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
-		lis302dl_data_ready(lis3, IRQ_LINE0);
-	else
-		lis3lv02d_joystick_poll(lis3->idev);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
-{
-	struct lis3lv02d *lis3 = data;
-	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
-
-	if (irq_cfg == LIS3_IRQ2_CLICK)
-		lis302dl_interrupt_handle_click(lis3);
-	else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
-		lis302dl_data_ready(lis3, IRQ_LINE1);
-	else
-		lis3lv02d_joystick_poll(lis3->idev);
-
-	return IRQ_HANDLED;
-}
-
-static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
-{
-	if (test_and_set_bit(0, &lis3_dev.misc_opened))
-		return -EBUSY; /* already open */
-
-	if (lis3_dev.pm_dev)
-		pm_runtime_get_sync(lis3_dev.pm_dev);
-
-	atomic_set(&lis3_dev.count, 0);
-	return 0;
-}
-
-static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
-{
-	fasync_helper(-1, file, 0, &lis3_dev.async_queue);
-	clear_bit(0, &lis3_dev.misc_opened); /* release the device */
-	if (lis3_dev.pm_dev)
-		pm_runtime_put(lis3_dev.pm_dev);
-	return 0;
-}
-
-static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
-				size_t count, loff_t *pos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	u32 data;
-	unsigned char byte_data;
-	ssize_t retval = 1;
-
-	if (count < 1)
-		return -EINVAL;
-
-	add_wait_queue(&lis3_dev.misc_wait, &wait);
-	while (true) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		data = atomic_xchg(&lis3_dev.count, 0);
-		if (data)
-			break;
-
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto out;
-		}
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			goto out;
-		}
-
-		schedule();
-	}
-
-	if (data < 255)
-		byte_data = data;
-	else
-		byte_data = 255;
-
-	/* make sure we are not going into copy_to_user() with
-	 * TASK_INTERRUPTIBLE state */
-	set_current_state(TASK_RUNNING);
-	if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
-		retval = -EFAULT;
-
-out:
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&lis3_dev.misc_wait, &wait);
-
-	return retval;
-}
-
-static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
-{
-	poll_wait(file, &lis3_dev.misc_wait, wait);
-	if (atomic_read(&lis3_dev.count))
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
-{
-	return fasync_helper(fd, file, on, &lis3_dev.async_queue);
-}
-
-static const struct file_operations lis3lv02d_misc_fops = {
-	.owner   = THIS_MODULE,
-	.llseek  = no_llseek,
-	.read    = lis3lv02d_misc_read,
-	.open    = lis3lv02d_misc_open,
-	.release = lis3lv02d_misc_release,
-	.poll    = lis3lv02d_misc_poll,
-	.fasync  = lis3lv02d_misc_fasync,
-};
-
-static struct miscdevice lis3lv02d_misc_device = {
-	.minor   = MISC_DYNAMIC_MINOR,
-	.name    = "freefall",
-	.fops    = &lis3lv02d_misc_fops,
-};
-
-int lis3lv02d_joystick_enable(void)
-{
-	struct input_dev *input_dev;
-	int err;
-	int max_val, fuzz, flat;
-	int btns[] = {BTN_X, BTN_Y, BTN_Z};
-
-	if (lis3_dev.idev)
-		return -EINVAL;
-
-	lis3_dev.idev = input_allocate_polled_device();
-	if (!lis3_dev.idev)
-		return -ENOMEM;
-
-	lis3_dev.idev->poll = lis3lv02d_joystick_poll;
-	lis3_dev.idev->open = lis3lv02d_joystick_open;
-	lis3_dev.idev->close = lis3lv02d_joystick_close;
-	lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
-	lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
-	lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
-	input_dev = lis3_dev.idev->input;
-
-	input_dev->name       = "ST LIS3LV02DL Accelerometer";
-	input_dev->phys       = DRIVER_NAME "/input0";
-	input_dev->id.bustype = BUS_HOST;
-	input_dev->id.vendor  = 0;
-	input_dev->dev.parent = &lis3_dev.pdev->dev;
-
-	set_bit(EV_ABS, input_dev->evbit);
-	max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
-	if (lis3_dev.whoami == WAI_12B) {
-		fuzz = LIS3_DEFAULT_FUZZ_12B;
-		flat = LIS3_DEFAULT_FLAT_12B;
-	} else {
-		fuzz = LIS3_DEFAULT_FUZZ_8B;
-		flat = LIS3_DEFAULT_FLAT_8B;
-	}
-	fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
-	flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
-
-	input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
-	input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
-	input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
-
-	lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
-	lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
-	lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
-
-	err = input_register_polled_device(lis3_dev.idev);
-	if (err) {
-		input_free_polled_device(lis3_dev.idev);
-		lis3_dev.idev = NULL;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
-
-void lis3lv02d_joystick_disable(void)
-{
-	if (lis3_dev.irq)
-		free_irq(lis3_dev.irq, &lis3_dev);
-	if (lis3_dev.pdata && lis3_dev.pdata->irq2)
-		free_irq(lis3_dev.pdata->irq2, &lis3_dev);
-
-	if (!lis3_dev.idev)
-		return;
-
-	if (lis3_dev.irq)
-		misc_deregister(&lis3lv02d_misc_device);
-	input_unregister_polled_device(lis3_dev.idev);
-	input_free_polled_device(lis3_dev.idev);
-	lis3_dev.idev = NULL;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
-
-/* Sysfs stuff */
-static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
-{
-	/*
-	 * SYSFS functions are fast visitors so put-call
-	 * immediately after the get-call. However, keep
-	 * chip running for a while and schedule delayed
-	 * suspend. This way periodic sysfs calls doesn't
-	 * suffer from relatively long power up time.
-	 */
-
-	if (lis3->pm_dev) {
-		pm_runtime_get_sync(lis3->pm_dev);
-		pm_runtime_put_noidle(lis3->pm_dev);
-		pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
-	}
-}
-
-static ssize_t lis3lv02d_selftest_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	s16 values[3];
-
-	static const char ok[] = "OK";
-	static const char fail[] = "FAIL";
-	static const char irq[] = "FAIL_IRQ";
-	const char *res;
-
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	switch (lis3lv02d_selftest(&lis3_dev, values)) {
-	case SELFTEST_FAIL:
-		res = fail;
-		break;
-	case SELFTEST_IRQ:
-		res = irq;
-		break;
-	case SELFTEST_OK:
-	default:
-		res = ok;
-		break;
-	}
-	return sprintf(buf, "%s %d %d %d\n", res,
-		values[0], values[1], values[2]);
-}
-
-static ssize_t lis3lv02d_position_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	int x, y, z;
-
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	mutex_lock(&lis3_dev.mutex);
-	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-	mutex_unlock(&lis3_dev.mutex);
-	return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
-}
-
-static ssize_t lis3lv02d_rate_show(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	return sprintf(buf, "%d\n", lis3lv02d_get_odr());
-}
-
-static ssize_t lis3lv02d_rate_set(struct device *dev,
-				struct device_attribute *attr, const char *buf,
-				size_t count)
-{
-	unsigned long rate;
-
-	if (strict_strtoul(buf, 0, &rate))
-		return -EINVAL;
-
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	if (lis3lv02d_set_odr(rate))
-		return -EINVAL;
-
-	return count;
-}
-
-static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
-static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
-static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
-					    lis3lv02d_rate_set);
-
-static struct attribute *lis3lv02d_attributes[] = {
-	&dev_attr_selftest.attr,
-	&dev_attr_position.attr,
-	&dev_attr_rate.attr,
-	NULL
-};
-
-static struct attribute_group lis3lv02d_attribute_group = {
-	.attrs = lis3lv02d_attributes
-};
-
-
-static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
-{
-	lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
-	if (IS_ERR(lis3->pdev))
-		return PTR_ERR(lis3->pdev);
-
-	return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
-}
-
-int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
-{
-	sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
-	platform_device_unregister(lis3->pdev);
-	if (lis3->pm_dev) {
-		/* Barrier after the sysfs remove */
-		pm_runtime_barrier(lis3->pm_dev);
-
-		/* SYSFS may have left chip running. Turn off if necessary */
-		if (!pm_runtime_suspended(lis3->pm_dev))
-			lis3lv02d_poweroff(&lis3_dev);
-
-		pm_runtime_disable(lis3->pm_dev);
-		pm_runtime_set_suspended(lis3->pm_dev);
-	}
-	kfree(lis3->reg_cache);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
-
-static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
-				struct lis3lv02d_platform_data *p)
-{
-	int err;
-	int ctrl2 = p->hipass_ctrl;
-
-	if (p->click_flags) {
-		dev->write(dev, CLICK_CFG, p->click_flags);
-		dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
-		dev->write(dev, CLICK_LATENCY, p->click_latency);
-		dev->write(dev, CLICK_WINDOW, p->click_window);
-		dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
-		dev->write(dev, CLICK_THSY_X,
-			(p->click_thresh_x & 0xf) |
-			(p->click_thresh_y << 4));
-
-		if (dev->idev) {
-			struct input_dev *input_dev = lis3_dev.idev->input;
-			input_set_capability(input_dev, EV_KEY, BTN_X);
-			input_set_capability(input_dev, EV_KEY, BTN_Y);
-			input_set_capability(input_dev, EV_KEY, BTN_Z);
-		}
-	}
-
-	if (p->wakeup_flags) {
-		dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
-		dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
-		/* pdata value + 1 to keep this backward compatible*/
-		dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
-		ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
-	}
-
-	if (p->wakeup_flags2) {
-		dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
-		dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
-		/* pdata value + 1 to keep this backward compatible*/
-		dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
-		ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
-	}
-	/* Configure hipass filters */
-	dev->write(dev, CTRL_REG2, ctrl2);
-
-	if (p->irq2) {
-		err = request_threaded_irq(p->irq2,
-					NULL,
-					lis302dl_interrupt_thread2_8b,
-					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
-					(p->irq_flags2 & IRQF_TRIGGER_MASK),
-					DRIVER_NAME, &lis3_dev);
-		if (err < 0)
-			pr_err("No second IRQ. Limited functionality\n");
-	}
-}
-
-/*
- * Initialise the accelerometer and the various subsystems.
- * Should be rather independent of the bus system.
- */
-int lis3lv02d_init_device(struct lis3lv02d *dev)
-{
-	int err;
-	irq_handler_t thread_fn;
-	int irq_flags = 0;
-
-	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
-
-	switch (dev->whoami) {
-	case WAI_12B:
-		pr_info("12 bits sensor found\n");
-		dev->read_data = lis3lv02d_read_12;
-		dev->mdps_max_val = 2048;
-		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
-		dev->odrs = lis3_12_rates;
-		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
-		dev->scale = LIS3_SENSITIVITY_12B;
-		dev->regs = lis3_wai12_regs;
-		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
-		break;
-	case WAI_8B:
-		pr_info("8 bits sensor found\n");
-		dev->read_data = lis3lv02d_read_8;
-		dev->mdps_max_val = 128;
-		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
-		dev->odrs = lis3_8_rates;
-		dev->odr_mask = CTRL1_DR;
-		dev->scale = LIS3_SENSITIVITY_8B;
-		dev->regs = lis3_wai8_regs;
-		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
-		break;
-	case WAI_3DC:
-		pr_info("8 bits 3DC sensor found\n");
-		dev->read_data = lis3lv02d_read_8;
-		dev->mdps_max_val = 128;
-		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
-		dev->odrs = lis3_3dc_rates;
-		dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
-		dev->scale = LIS3_SENSITIVITY_8B;
-		break;
-	default:
-		pr_err("unknown sensor type 0x%X\n", dev->whoami);
-		return -EINVAL;
-	}
-
-	dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
-				     sizeof(lis3_wai12_regs)), GFP_KERNEL);
-
-	if (dev->reg_cache == NULL) {
-		printk(KERN_ERR DRIVER_NAME "out of memory\n");
-		return -ENOMEM;
-	}
-
-	mutex_init(&dev->mutex);
-	atomic_set(&dev->wake_thread, 0);
-
-	lis3lv02d_add_fs(dev);
-	lis3lv02d_poweron(dev);
-
-	if (dev->pm_dev) {
-		pm_runtime_set_active(dev->pm_dev);
-		pm_runtime_enable(dev->pm_dev);
-	}
-
-	if (lis3lv02d_joystick_enable())
-		pr_err("joystick initialization failed\n");
-
-	/* passing in platform specific data is purely optional and only
-	 * used by the SPI transport layer at the moment */
-	if (dev->pdata) {
-		struct lis3lv02d_platform_data *p = dev->pdata;
-
-		if (dev->whoami == WAI_8B)
-			lis3lv02d_8b_configure(dev, p);
-
-		irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
-
-		dev->irq_cfg = p->irq_cfg;
-		if (p->irq_cfg)
-			dev->write(dev, CTRL_REG3, p->irq_cfg);
-
-		if (p->default_rate)
-			lis3lv02d_set_odr(p->default_rate);
-	}
-
-	/* bail if we did not get an IRQ from the bus layer */
-	if (!dev->irq) {
-		pr_debug("No IRQ. Disabling /dev/freefall\n");
-		goto out;
-	}
-
-	/*
-	 * The sensor can generate interrupts for free-fall and direction
-	 * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
-	 * the things simple and _fast_ we activate it only for free-fall, so
-	 * no need to read register (very slow with ACPI). For the same reason,
-	 * we forbid shared interrupts.
-	 *
-	 * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
-	 * io-apic is not configurable (and generates a warning) but I keep it
-	 * in case of support for other hardware.
-	 */
-	if (dev->pdata && dev->whoami == WAI_8B)
-		thread_fn = lis302dl_interrupt_thread1_8b;
-	else
-		thread_fn = NULL;
-
-	err = request_threaded_irq(dev->irq, lis302dl_interrupt,
-				thread_fn,
-				IRQF_TRIGGER_RISING | IRQF_ONESHOT |
-				irq_flags,
-				DRIVER_NAME, &lis3_dev);
-
-	if (err < 0) {
-		pr_err("Cannot get IRQ\n");
-		goto out;
-	}
-
-	if (misc_register(&lis3lv02d_misc_device))
-		pr_err("misc_register failed\n");
-out:
-	return 0;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
-
-MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
-MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
deleted file mode 100644
index a193958..0000000
--- a/drivers/hwmon/lis3lv02d.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008-2009 Eric Piel
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You 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/platform_device.h>
-#include <linux/input-polldev.h>
-#include <linux/regulator/consumer.h>
-
-/*
- * This driver tries to support the "digital" accelerometer chips from
- * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
- * LIS35DE, or LIS202DL. They are very similar in terms of programming, with
- * almost the same registers. In addition to differing on physical properties,
- * they differ on the number of axes (2/3), precision (8/12 bits), and special
- * features (freefall detection, click...). Unfortunately, not all the
- * differences can be probed via a register.
- * They can be connected either via IÂ˛C or SPI.
- */
-
-#include <linux/lis3lv02d.h>
-
-enum lis3_reg {
-	WHO_AM_I	= 0x0F,
-	OFFSET_X	= 0x16,
-	OFFSET_Y	= 0x17,
-	OFFSET_Z	= 0x18,
-	GAIN_X		= 0x19,
-	GAIN_Y		= 0x1A,
-	GAIN_Z		= 0x1B,
-	CTRL_REG1	= 0x20,
-	CTRL_REG2	= 0x21,
-	CTRL_REG3	= 0x22,
-	CTRL_REG4	= 0x23,
-	HP_FILTER_RESET	= 0x23,
-	STATUS_REG	= 0x27,
-	OUTX_L		= 0x28,
-	OUTX_H		= 0x29,
-	OUTX		= 0x29,
-	OUTY_L		= 0x2A,
-	OUTY_H		= 0x2B,
-	OUTY		= 0x2B,
-	OUTZ_L		= 0x2C,
-	OUTZ_H		= 0x2D,
-	OUTZ		= 0x2D,
-};
-
-enum lis302d_reg {
-	FF_WU_CFG_1	= 0x30,
-	FF_WU_SRC_1	= 0x31,
-	FF_WU_THS_1	= 0x32,
-	FF_WU_DURATION_1 = 0x33,
-	FF_WU_CFG_2	= 0x34,
-	FF_WU_SRC_2	= 0x35,
-	FF_WU_THS_2	= 0x36,
-	FF_WU_DURATION_2 = 0x37,
-	CLICK_CFG	= 0x38,
-	CLICK_SRC	= 0x39,
-	CLICK_THSY_X	= 0x3B,
-	CLICK_THSZ	= 0x3C,
-	CLICK_TIMELIMIT	= 0x3D,
-	CLICK_LATENCY	= 0x3E,
-	CLICK_WINDOW	= 0x3F,
-};
-
-enum lis3lv02d_reg {
-	FF_WU_CFG	= 0x30,
-	FF_WU_SRC	= 0x31,
-	FF_WU_ACK	= 0x32,
-	FF_WU_THS_L	= 0x34,
-	FF_WU_THS_H	= 0x35,
-	FF_WU_DURATION	= 0x36,
-	DD_CFG		= 0x38,
-	DD_SRC		= 0x39,
-	DD_ACK		= 0x3A,
-	DD_THSI_L	= 0x3C,
-	DD_THSI_H	= 0x3D,
-	DD_THSE_L	= 0x3E,
-	DD_THSE_H	= 0x3F,
-};
-
-enum lis3_who_am_i {
-	WAI_3DC		= 0x33,	/* 8 bits: LIS3DC, HP3DC */
-	WAI_12B		= 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
-	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
-	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
-};
-
-enum lis3lv02d_ctrl1_12b {
-	CTRL1_Xen	= 0x01,
-	CTRL1_Yen	= 0x02,
-	CTRL1_Zen	= 0x04,
-	CTRL1_ST	= 0x08,
-	CTRL1_DF0	= 0x10,
-	CTRL1_DF1	= 0x20,
-	CTRL1_PD0	= 0x40,
-	CTRL1_PD1	= 0x80,
-};
-
-/* Delta to ctrl1_12b version */
-enum lis3lv02d_ctrl1_8b {
-	CTRL1_STM	= 0x08,
-	CTRL1_STP	= 0x10,
-	CTRL1_FS	= 0x20,
-	CTRL1_PD	= 0x40,
-	CTRL1_DR	= 0x80,
-};
-
-enum lis3lv02d_ctrl1_3dc {
-	CTRL1_ODR0	= 0x10,
-	CTRL1_ODR1	= 0x20,
-	CTRL1_ODR2	= 0x40,
-	CTRL1_ODR3	= 0x80,
-};
-
-enum lis3lv02d_ctrl2 {
-	CTRL2_DAS	= 0x01,
-	CTRL2_SIM	= 0x02,
-	CTRL2_DRDY	= 0x04,
-	CTRL2_IEN	= 0x08,
-	CTRL2_BOOT	= 0x10,
-	CTRL2_BLE	= 0x20,
-	CTRL2_BDU	= 0x40, /* Block Data Update */
-	CTRL2_FS	= 0x80, /* Full Scale selection */
-};
-
-enum lis3lv02d_ctrl4_3dc {
-	CTRL4_SIM	= 0x01,
-	CTRL4_ST0	= 0x02,
-	CTRL4_ST1	= 0x04,
-	CTRL4_FS0	= 0x10,
-	CTRL4_FS1	= 0x20,
-};
-
-enum lis302d_ctrl2 {
-	HP_FF_WU2	= 0x08,
-	HP_FF_WU1	= 0x04,
-	CTRL2_BOOT_8B   = 0x40,
-};
-
-enum lis3lv02d_ctrl3 {
-	CTRL3_CFS0	= 0x01,
-	CTRL3_CFS1	= 0x02,
-	CTRL3_FDS	= 0x10,
-	CTRL3_HPFF	= 0x20,
-	CTRL3_HPDD	= 0x40,
-	CTRL3_ECK	= 0x80,
-};
-
-enum lis3lv02d_status_reg {
-	STATUS_XDA	= 0x01,
-	STATUS_YDA	= 0x02,
-	STATUS_ZDA	= 0x04,
-	STATUS_XYZDA	= 0x08,
-	STATUS_XOR	= 0x10,
-	STATUS_YOR	= 0x20,
-	STATUS_ZOR	= 0x40,
-	STATUS_XYZOR	= 0x80,
-};
-
-enum lis3lv02d_ff_wu_cfg {
-	FF_WU_CFG_XLIE	= 0x01,
-	FF_WU_CFG_XHIE	= 0x02,
-	FF_WU_CFG_YLIE	= 0x04,
-	FF_WU_CFG_YHIE	= 0x08,
-	FF_WU_CFG_ZLIE	= 0x10,
-	FF_WU_CFG_ZHIE	= 0x20,
-	FF_WU_CFG_LIR	= 0x40,
-	FF_WU_CFG_AOI	= 0x80,
-};
-
-enum lis3lv02d_ff_wu_src {
-	FF_WU_SRC_XL	= 0x01,
-	FF_WU_SRC_XH	= 0x02,
-	FF_WU_SRC_YL	= 0x04,
-	FF_WU_SRC_YH	= 0x08,
-	FF_WU_SRC_ZL	= 0x10,
-	FF_WU_SRC_ZH	= 0x20,
-	FF_WU_SRC_IA	= 0x40,
-};
-
-enum lis3lv02d_dd_cfg {
-	DD_CFG_XLIE	= 0x01,
-	DD_CFG_XHIE	= 0x02,
-	DD_CFG_YLIE	= 0x04,
-	DD_CFG_YHIE	= 0x08,
-	DD_CFG_ZLIE	= 0x10,
-	DD_CFG_ZHIE	= 0x20,
-	DD_CFG_LIR	= 0x40,
-	DD_CFG_IEND	= 0x80,
-};
-
-enum lis3lv02d_dd_src {
-	DD_SRC_XL	= 0x01,
-	DD_SRC_XH	= 0x02,
-	DD_SRC_YL	= 0x04,
-	DD_SRC_YH	= 0x08,
-	DD_SRC_ZL	= 0x10,
-	DD_SRC_ZH	= 0x20,
-	DD_SRC_IA	= 0x40,
-};
-
-enum lis3lv02d_click_src_8b {
-	CLICK_SINGLE_X	= 0x01,
-	CLICK_DOUBLE_X	= 0x02,
-	CLICK_SINGLE_Y	= 0x04,
-	CLICK_DOUBLE_Y	= 0x08,
-	CLICK_SINGLE_Z	= 0x10,
-	CLICK_DOUBLE_Z	= 0x20,
-	CLICK_IA	= 0x40,
-};
-
-enum lis3lv02d_reg_state {
-	LIS3_REG_OFF	= 0x00,
-	LIS3_REG_ON	= 0x01,
-};
-
-union axis_conversion {
-	struct {
-		int x, y, z;
-	};
-	int as_array[3];
-
-};
-
-struct lis3lv02d {
-	void			*bus_priv; /* used by the bus layer only */
-	struct device		*pm_dev; /* for pm_runtime purposes */
-	int (*init) (struct lis3lv02d *lis3);
-	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
-	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
-	int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
-	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
-
-	int                     *odrs;     /* Supported output data rates */
-	u8			*regs;	   /* Regs to store / restore */
-	int			regs_size;
-	u8                      *reg_cache;
-	bool			regs_stored;
-	u8                      odr_mask;  /* ODR bit mask */
-	u8			whoami;    /* indicates measurement precision */
-	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
-	int			mdps_max_val;
-	int			pwron_delay;
-	int                     scale; /*
-					* relationship between 1 LBS and mG
-					* (1/1000th of earth gravity)
-					*/
-
-	struct input_polled_dev	*idev;     /* input device */
-	struct platform_device	*pdev;     /* platform device */
-	struct regulator_bulk_data regulators[2];
-	atomic_t		count;     /* interrupt count after last read */
-	union axis_conversion	ac;        /* hw -> logical axis */
-	int			mapped_btns[3];
-
-	u32			irq;       /* IRQ number */
-	struct fasync_struct	*async_queue; /* queue for the misc device */
-	wait_queue_head_t	misc_wait; /* Wait queue for the misc device */
-	unsigned long		misc_opened; /* bit0: whether the device is open */
-	int                     data_ready_count[2];
-	atomic_t		wake_thread;
-	unsigned char           irq_cfg;
-
-	struct lis3lv02d_platform_data *pdata;	/* for passing board config */
-	struct mutex		mutex;     /* Serialize poll and selftest */
-};
-
-int lis3lv02d_init_device(struct lis3lv02d *lis3);
-int lis3lv02d_joystick_enable(void);
-void lis3lv02d_joystick_disable(void);
-void lis3lv02d_poweroff(struct lis3lv02d *lis3);
-void lis3lv02d_poweron(struct lis3lv02d *lis3);
-int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
-
-extern struct lis3lv02d lis3_dev;
diff --git a/drivers/hwmon/lis3lv02d_i2c.c b/drivers/hwmon/lis3lv02d_i2c.c
deleted file mode 100644
index 8853afc..0000000
--- a/drivers/hwmon/lis3lv02d_i2c.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * drivers/hwmon/lis3lv02d_i2c.c
- *
- * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
- * Driver is based on corresponding SPI driver written by Daniel Mack
- * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
- *
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include "lis3lv02d.h"
-
-#define DRV_NAME 	"lis3lv02d_i2c"
-
-static const char reg_vdd[]    = "Vdd";
-static const char reg_vdd_io[] = "Vdd_IO";
-
-static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
-{
-	int ret;
-	if (state == LIS3_REG_OFF) {
-		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
-					lis3->regulators);
-	} else {
-		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
-					lis3->regulators);
-		/* Chip needs time to wakeup. Not mentioned in datasheet */
-		usleep_range(10000, 20000);
-	}
-	return ret;
-}
-
-static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
-{
-	struct i2c_client *c = lis3->bus_priv;
-	return i2c_smbus_write_byte_data(c, reg, value);
-}
-
-static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
-{
-	struct i2c_client *c = lis3->bus_priv;
-	*v = i2c_smbus_read_byte_data(c, reg);
-	return 0;
-}
-
-static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
-				u8 *v)
-{
-	struct i2c_client *c = lis3->bus_priv;
-	reg |= (1 << 7); /* 7th bit enables address auto incrementation */
-	return i2c_smbus_read_i2c_block_data(c, reg, len, v);
-}
-
-static int lis3_i2c_init(struct lis3lv02d *lis3)
-{
-	u8 reg;
-	int ret;
-
-	if (lis3->reg_ctrl)
-		lis3_reg_ctrl(lis3, LIS3_REG_ON);
-
-	lis3->read(lis3, WHO_AM_I, &reg);
-	if (reg != lis3->whoami)
-		printk(KERN_ERR "lis3: power on failure\n");
-
-	/* power up the device */
-	ret = lis3->read(lis3, CTRL_REG1, &reg);
-	if (ret < 0)
-		return ret;
-
-	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
-	return lis3->write(lis3, CTRL_REG1, reg);
-}
-
-/* Default axis mapping but it can be overwritten by platform data */
-static union axis_conversion lis3lv02d_axis_map =
-	{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
-
-static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
-					const struct i2c_device_id *id)
-{
-	int ret = 0;
-	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
-
-	if (pdata) {
-		/* Regulator control is optional */
-		if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
-			lis3_dev.reg_ctrl = lis3_reg_ctrl;
-
-		if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
-			(i2c_check_functionality(client->adapter,
-						I2C_FUNC_SMBUS_I2C_BLOCK)))
-			lis3_dev.blkread  = lis3_i2c_blockread;
-
-		if (pdata->axis_x)
-			lis3lv02d_axis_map.x = pdata->axis_x;
-
-		if (pdata->axis_y)
-			lis3lv02d_axis_map.y = pdata->axis_y;
-
-		if (pdata->axis_z)
-			lis3lv02d_axis_map.z = pdata->axis_z;
-
-		if (pdata->setup_resources)
-			ret = pdata->setup_resources();
-
-		if (ret)
-			goto fail;
-	}
-
-	if (lis3_dev.reg_ctrl) {
-		lis3_dev.regulators[0].supply = reg_vdd;
-		lis3_dev.regulators[1].supply = reg_vdd_io;
-		ret = regulator_bulk_get(&client->dev,
-					ARRAY_SIZE(lis3_dev.regulators),
-					lis3_dev.regulators);
-		if (ret < 0)
-			goto fail;
-	}
-
-	lis3_dev.pdata	  = pdata;
-	lis3_dev.bus_priv = client;
-	lis3_dev.init	  = lis3_i2c_init;
-	lis3_dev.read	  = lis3_i2c_read;
-	lis3_dev.write	  = lis3_i2c_write;
-	lis3_dev.irq	  = client->irq;
-	lis3_dev.ac	  = lis3lv02d_axis_map;
-	lis3_dev.pm_dev	  = &client->dev;
-
-	i2c_set_clientdata(client, &lis3_dev);
-
-	/* Provide power over the init call */
-	if (lis3_dev.reg_ctrl)
-		lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
-
-	ret = lis3lv02d_init_device(&lis3_dev);
-
-	if (lis3_dev.reg_ctrl)
-		lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
-
-	if (ret == 0)
-		return 0;
-fail:
-	if (pdata && pdata->release_resources)
-		pdata->release_resources();
-	return ret;
-}
-
-static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
-{
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
-
-	if (pdata && pdata->release_resources)
-		pdata->release_resources();
-
-	lis3lv02d_joystick_disable();
-	lis3lv02d_remove_fs(&lis3_dev);
-
-	if (lis3_dev.reg_ctrl)
-		regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
-				lis3_dev.regulators);
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int lis3lv02d_i2c_suspend(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-		lis3lv02d_poweroff(lis3);
-	return 0;
-}
-
-static int lis3lv02d_i2c_resume(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	/*
-	 * pm_runtime documentation says that devices should always
-	 * be powered on at resume. Pm_runtime turns them off after system
-	 * wide resume is complete.
-	 */
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
-		pm_runtime_suspended(dev))
-		lis3lv02d_poweron(lis3);
-
-	return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_PM_RUNTIME
-static int lis3_i2c_runtime_suspend(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	lis3lv02d_poweroff(lis3);
-	return 0;
-}
-
-static int lis3_i2c_runtime_resume(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	lis3lv02d_poweron(lis3);
-	return 0;
-}
-#endif /* CONFIG_PM_RUNTIME */
-
-static const struct i2c_device_id lis3lv02d_id[] = {
-	{"lis3lv02d", 0 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
-
-static const struct dev_pm_ops lis3_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
-				lis3lv02d_i2c_resume)
-	SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
-			   lis3_i2c_runtime_resume,
-			   NULL)
-};
-
-static struct i2c_driver lis3lv02d_i2c_driver = {
-	.driver	 = {
-		.name   = DRV_NAME,
-		.owner  = THIS_MODULE,
-		.pm     = &lis3_pm_ops,
-	},
-	.probe	= lis3lv02d_i2c_probe,
-	.remove	= __devexit_p(lis3lv02d_i2c_remove),
-	.id_table = lis3lv02d_id,
-};
-
-static int __init lis3lv02d_init(void)
-{
-	return i2c_add_driver(&lis3lv02d_i2c_driver);
-}
-
-static void __exit lis3lv02d_exit(void)
-{
-	i2c_del_driver(&lis3lv02d_i2c_driver);
-}
-
-MODULE_AUTHOR("Nokia Corporation");
-MODULE_DESCRIPTION("lis3lv02d I2C interface");
-MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init);
-module_exit(lis3lv02d_exit);
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c
deleted file mode 100644
index 2549de1..0000000
--- a/drivers/hwmon/lis3lv02d_spi.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * lis3lv02d_spi - SPI glue layer for lis3lv02d
- *
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.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
- *  publishhed by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/spi/spi.h>
-
-#include "lis3lv02d.h"
-
-#define DRV_NAME 	"lis3lv02d_spi"
-#define LIS3_SPI_READ	0x80
-
-static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
-{
-	struct spi_device *spi = lis3->bus_priv;
-	int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
-	if (ret < 0)
-		return -EINVAL;
-
-	*v = (u8) ret;
-	return 0;
-}
-
-static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
-{
-	u8 tmp[2] = { reg, val };
-	struct spi_device *spi = lis3->bus_priv;
-	return spi_write(spi, tmp, sizeof(tmp));
-}
-
-static int lis3_spi_init(struct lis3lv02d *lis3)
-{
-	u8 reg;
-	int ret;
-
-	/* power up the device */
-	ret = lis3->read(lis3, CTRL_REG1, &reg);
-	if (ret < 0)
-		return ret;
-
-	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
-	return lis3->write(lis3, CTRL_REG1, reg);
-}
-
-static union axis_conversion lis3lv02d_axis_normal =
-	{ .as_array = { 1, 2, 3 } };
-
-static int __devinit lis302dl_spi_probe(struct spi_device *spi)
-{
-	int ret;
-
-	spi->bits_per_word = 8;
-	spi->mode = SPI_MODE_0;
-	ret = spi_setup(spi);
-	if (ret < 0)
-		return ret;
-
-	lis3_dev.bus_priv	= spi;
-	lis3_dev.init		= lis3_spi_init;
-	lis3_dev.read		= lis3_spi_read;
-	lis3_dev.write		= lis3_spi_write;
-	lis3_dev.irq		= spi->irq;
-	lis3_dev.ac		= lis3lv02d_axis_normal;
-	lis3_dev.pdata		= spi->dev.platform_data;
-	spi_set_drvdata(spi, &lis3_dev);
-
-	return lis3lv02d_init_device(&lis3_dev);
-}
-
-static int __devexit lis302dl_spi_remove(struct spi_device *spi)
-{
-	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-	lis3lv02d_joystick_disable();
-	lis3lv02d_poweroff(lis3);
-
-	return lis3lv02d_remove_fs(&lis3_dev);
-}
-
-#ifdef CONFIG_PM
-static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg)
-{
-	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-		lis3lv02d_poweroff(&lis3_dev);
-
-	return 0;
-}
-
-static int lis3lv02d_spi_resume(struct spi_device *spi)
-{
-	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-		lis3lv02d_poweron(lis3);
-
-	return 0;
-}
-
-#else
-#define lis3lv02d_spi_suspend	NULL
-#define lis3lv02d_spi_resume	NULL
-#endif
-
-static struct spi_driver lis302dl_spi_driver = {
-	.driver	 = {
-		.name   = DRV_NAME,
-		.owner  = THIS_MODULE,
-	},
-	.probe	= lis302dl_spi_probe,
-	.remove	= __devexit_p(lis302dl_spi_remove),
-	.suspend = lis3lv02d_spi_suspend,
-	.resume  = lis3lv02d_spi_resume,
-};
-
-static int __init lis302dl_init(void)
-{
-	return spi_register_driver(&lis302dl_spi_driver);
-}
-
-static void __exit lis302dl_exit(void)
-{
-	spi_unregister_driver(&lis302dl_spi_driver);
-}
-
-module_init(lis302dl_init);
-module_exit(lis302dl_exit);
-
-MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c
index f36eb80..ef902d5 100644
--- a/drivers/hwmon/lm75.c
+++ b/drivers/hwmon/lm75.c
@@ -232,13 +232,16 @@ static const struct i2c_device_id lm75_ids[] = {
 };
 MODULE_DEVICE_TABLE(i2c, lm75_ids);
 
+#define LM75A_ID 0xA1
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm75_detect(struct i2c_client *new_client,
 		       struct i2c_board_info *info)
 {
 	struct i2c_adapter *adapter = new_client->adapter;
 	int i;
-	int cur, conf, hyst, os;
+	int conf, hyst, os;
+	bool is_lm75a = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 				     I2C_FUNC_SMBUS_WORD_DATA))
@@ -250,37 +253,58 @@ static int lm75_detect(struct i2c_client *new_client,
 	   addresses 0x04-0x07 returning the last read value.
 	   The cycling+unused addresses combination is not tested,
 	   since it would significantly slow the detection down and would
-	   hardly add any value. */
+	   hardly add any value.
 
-	/* Unused addresses */
-	cur = i2c_smbus_read_word_data(new_client, 0);
-	conf = i2c_smbus_read_byte_data(new_client, 1);
-	hyst = i2c_smbus_read_word_data(new_client, 2);
-	if (i2c_smbus_read_word_data(new_client, 4) != hyst
-	 || i2c_smbus_read_word_data(new_client, 5) != hyst
-	 || i2c_smbus_read_word_data(new_client, 6) != hyst
-	 || i2c_smbus_read_word_data(new_client, 7) != hyst)
-		return -ENODEV;
-	os = i2c_smbus_read_word_data(new_client, 3);
-	if (i2c_smbus_read_word_data(new_client, 4) != os
-	 || i2c_smbus_read_word_data(new_client, 5) != os
-	 || i2c_smbus_read_word_data(new_client, 6) != os
-	 || i2c_smbus_read_word_data(new_client, 7) != os)
-		return -ENODEV;
+	   The National Semiconductor LM75A is different than earlier
+	   LM75s.  It has an ID byte of 0xaX (where X is the chip
+	   revision, with 1 being the only revision in existence) in
+	   register 7, and unused registers return 0xff rather than the
+	   last read value. */
 
 	/* Unused bits */
+	conf = i2c_smbus_read_byte_data(new_client, 1);
 	if (conf & 0xe0)
 		return -ENODEV;
 
+	/* First check for LM75A */
+	if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) {
+		/* LM75A returns 0xff on unused registers so
+		   just to be sure we check for that too. */
+		if (i2c_smbus_read_byte_data(new_client, 4) != 0xff
+		 || i2c_smbus_read_byte_data(new_client, 5) != 0xff
+		 || i2c_smbus_read_byte_data(new_client, 6) != 0xff)
+			return -ENODEV;
+		is_lm75a = 1;
+		hyst = i2c_smbus_read_byte_data(new_client, 2);
+		os = i2c_smbus_read_byte_data(new_client, 3);
+	} else { /* Traditional style LM75 detection */
+		/* Unused addresses */
+		hyst = i2c_smbus_read_byte_data(new_client, 2);
+		if (i2c_smbus_read_byte_data(new_client, 4) != hyst
+		 || i2c_smbus_read_byte_data(new_client, 5) != hyst
+		 || i2c_smbus_read_byte_data(new_client, 6) != hyst
+		 || i2c_smbus_read_byte_data(new_client, 7) != hyst)
+			return -ENODEV;
+		os = i2c_smbus_read_byte_data(new_client, 3);
+		if (i2c_smbus_read_byte_data(new_client, 4) != os
+		 || i2c_smbus_read_byte_data(new_client, 5) != os
+		 || i2c_smbus_read_byte_data(new_client, 6) != os
+		 || i2c_smbus_read_byte_data(new_client, 7) != os)
+			return -ENODEV;
+	}
+
 	/* Addresses cycling */
-	for (i = 8; i < 0xff; i += 8) {
+	for (i = 8; i <= 248; i += 40) {
 		if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
-		 || i2c_smbus_read_word_data(new_client, i + 2) != hyst
-		 || i2c_smbus_read_word_data(new_client, i + 3) != os)
+		 || i2c_smbus_read_byte_data(new_client, i + 2) != hyst
+		 || i2c_smbus_read_byte_data(new_client, i + 3) != os)
+			return -ENODEV;
+		if (is_lm75a && i2c_smbus_read_byte_data(new_client, i + 7)
+				!= LM75A_ID)
 			return -ENODEV;
 	}
 
-	strlcpy(info->type, "lm75", I2C_NAME_SIZE);
+	strlcpy(info->type, is_lm75a ? "lm75a" : "lm75", I2C_NAME_SIZE);
 
 	return 0;
 }
diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c
index d2cc286..cf47e6e 100644
--- a/drivers/hwmon/lm85.c
+++ b/drivers/hwmon/lm85.c
@@ -41,7 +41,7 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
 enum chips {
 	any_chip, lm85b, lm85c,
 	adm1027, adt7463, adt7468,
-	emc6d100, emc6d102, emc6d103
+	emc6d100, emc6d102, emc6d103, emc6d103s
 };
 
 /* The LM85 registers */
@@ -283,10 +283,6 @@ struct lm85_zone {
 	u8 hyst;	/* Low limit hysteresis. (0-15) */
 	u8 range;	/* Temp range, encoded */
 	s8 critical;	/* "All fans ON" temp limit */
-	u8 off_desired; /* Actual "off" temperature specified.  Preserved
-			 * to prevent "drift" as other autofan control
-			 * values change.
-			 */
 	u8 max_desired; /* Actual "max" temperature specified.  Preserved
 			 * to prevent "drift" as other autofan control
 			 * values change.
@@ -306,6 +302,8 @@ struct lm85_data {
 	const int *freq_map;
 	enum chips type;
 
+	bool has_vid5;	/* true if VID5 is configured for ADT7463 or ADT7468 */
+
 	struct mutex update_lock;
 	int valid;		/* !=0 if following fields are valid */
 	unsigned long last_reading;	/* In jiffies */
@@ -352,6 +350,7 @@ static const struct i2c_device_id lm85_id[] = {
 	{ "emc6d101", emc6d100 },
 	{ "emc6d102", emc6d102 },
 	{ "emc6d103", emc6d103 },
+	{ "emc6d103s", emc6d103s },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm85_id);
@@ -420,8 +419,7 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
 	struct lm85_data *data = lm85_update_device(dev);
 	int vid;
 
-	if ((data->type == adt7463 || data->type == adt7468) &&
-	    (data->vid & 0x80)) {
+	if (data->has_vid5) {
 		/* 6-pin VID (VRM 10) */
 		vid = vid_from_reg(data->vid & 0x3f, data->vrm);
 	} else {
@@ -891,7 +889,6 @@ static ssize_t set_temp_auto_temp_off(struct device *dev,
 
 	mutex_lock(&data->update_lock);
 	min = TEMP_FROM_REG(data->zone[nr].limit);
-	data->zone[nr].off_desired = TEMP_TO_REG(val);
 	data->zone[nr].hyst = HYST_TO_REG(min - val);
 	if (nr == 0 || nr == 1) {
 		lm85_write_value(client, LM85_REG_AFAN_HYST1,
@@ -934,18 +931,6 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
 		((data->zone[nr].range & 0x0f) << 4)
 		| (data->pwm_freq[nr] & 0x07));
 
-/* Update temp_auto_hyst and temp_auto_off */
-	data->zone[nr].hyst = HYST_TO_REG(TEMP_FROM_REG(
-		data->zone[nr].limit) - TEMP_FROM_REG(
-		data->zone[nr].off_desired));
-	if (nr == 0 || nr == 1) {
-		lm85_write_value(client, LM85_REG_AFAN_HYST1,
-			(data->zone[0].hyst << 4)
-			| data->zone[1].hyst);
-	} else {
-		lm85_write_value(client, LM85_REG_AFAN_HYST2,
-			(data->zone[2].hyst << 4));
-	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1084,13 +1069,7 @@ static struct attribute *lm85_attributes[] = {
 	&sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
-	&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
-	&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
-	&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
 
-	&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
-	&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
 	&sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr,
 	&sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr,
 	&sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr,
@@ -1111,6 +1090,26 @@ static const struct attribute_group lm85_group = {
 	.attrs = lm85_attributes,
 };
 
+static struct attribute *lm85_attributes_minctl[] = {
+	&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
+};
+
+static const struct attribute_group lm85_group_minctl = {
+	.attrs = lm85_attributes_minctl,
+};
+
+static struct attribute *lm85_attributes_temp_off[] = {
+	&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
+};
+
+static const struct attribute_group lm85_group_temp_off = {
+	.attrs = lm85_attributes_temp_off,
+};
+
 static struct attribute *lm85_attributes_in4[] = {
 	&sensor_dev_attr_in4_input.dev_attr.attr,
 	&sensor_dev_attr_in4_min.dev_attr.attr,
@@ -1258,16 +1257,9 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
 		case LM85_VERSTEP_EMC6D103_A1:
 			type_name = "emc6d103";
 			break;
-		/*
-		 * Registers apparently missing in EMC6D103S/EMC6D103:A2
-		 * compared to EMC6D103:A0, EMC6D103:A1, and EMC6D102
-		 * (according to the data sheets), but used unconditionally
-		 * in the driver: 62[5:7], 6D[0:7], and 6E[0:7].
-		 * So skip EMC6D103S for now.
 		case LM85_VERSTEP_EMC6D103S:
 			type_name = "emc6d103s";
 			break;
-		 */
 		}
 	} else {
 		dev_dbg(&adapter->dev,
@@ -1280,6 +1272,19 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info)
 	return 0;
 }
 
+static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
+{
+	sysfs_remove_group(&client->dev.kobj, &lm85_group);
+	if (data->type != emc6d103s) {
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl);
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off);
+	}
+	if (!data->has_vid5)
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
+	if (data->type == emc6d100)
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
+}
+
 static int lm85_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
@@ -1302,6 +1307,7 @@ static int lm85_probe(struct i2c_client *client,
 	case emc6d100:
 	case emc6d102:
 	case emc6d103:
+	case emc6d103s:
 		data->freq_map = adm1027_freq_map;
 		break;
 	default:
@@ -1319,11 +1325,26 @@ static int lm85_probe(struct i2c_client *client,
 	if (err)
 		goto err_kfree;
 
+	/* minctl and temp_off exist on all chips except emc6d103s */
+	if (data->type != emc6d103s) {
+		err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
+		if (err)
+			goto err_kfree;
+		err = sysfs_create_group(&client->dev.kobj,
+					 &lm85_group_temp_off);
+		if (err)
+			goto err_kfree;
+	}
+
 	/* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
 	   as a sixth digital VID input rather than an analog input. */
-	data->vid = lm85_read_value(client, LM85_REG_VID);
-	if (!((data->type == adt7463 || data->type == adt7468) &&
-	    (data->vid & 0x80)))
+	if (data->type == adt7463 || data->type == adt7468) {
+		u8 vid = lm85_read_value(client, LM85_REG_VID);
+		if (vid & 0x80)
+			data->has_vid5 = true;
+	}
+
+	if (!data->has_vid5)
 		if ((err = sysfs_create_group(&client->dev.kobj,
 					&lm85_group_in4)))
 			goto err_remove_files;
@@ -1344,10 +1365,7 @@ static int lm85_probe(struct i2c_client *client,
 
 	/* Error out and cleanup code */
  err_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &lm85_group);
-	sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
-	if (data->type == emc6d100)
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
+	lm85_remove_files(client, data);
  err_kfree:
 	kfree(data);
 	return err;
@@ -1357,10 +1375,7 @@ static int lm85_remove(struct i2c_client *client)
 {
 	struct lm85_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm85_group);
-	sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
-	if (data->type == emc6d100)
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
+	lm85_remove_files(client, data);
 	kfree(data);
 	return 0;
 }
@@ -1457,11 +1472,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 			    lm85_read_value(client, LM85_REG_FAN(i));
 		}
 
-		if (!((data->type == adt7463 || data->type == adt7468) &&
-		    (data->vid & 0x80))) {
-			data->in[4] = lm85_read_value(client,
-				      LM85_REG_IN(4));
-		}
+		if (!data->has_vid5)
+			data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
 
 		if (data->type == adt7468)
 			data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
@@ -1487,7 +1499,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 			/* More alarm bits */
 			data->alarms |= lm85_read_value(client,
 						EMC6D100_REG_ALARM3) << 16;
-		} else if (data->type == emc6d102 || data->type == emc6d103) {
+		} else if (data->type == emc6d102 || data->type == emc6d103 ||
+			   data->type == emc6d103s) {
 			/* Have to read LSB bits after the MSB ones because
 			   the reading of the MSB bits has frozen the
 			   LSBs (backward from the ADM1027).
@@ -1528,8 +1541,7 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 			    lm85_read_value(client, LM85_REG_FAN_MIN(i));
 		}
 
-		if (!((data->type == adt7463 || data->type == adt7468) &&
-		    (data->vid & 0x80))) {
+		if (!data->has_vid5)  {
 			data->in_min[4] = lm85_read_value(client,
 					  LM85_REG_IN_MIN(4));
 			data->in_max[4] = lm85_read_value(client,
@@ -1573,17 +1585,19 @@ static struct lm85_data *lm85_update_device(struct device *dev)
 			}
 		}
 
-		i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
-		data->autofan[0].min_off = (i & 0x20) != 0;
-		data->autofan[1].min_off = (i & 0x40) != 0;
-		data->autofan[2].min_off = (i & 0x80) != 0;
+		if (data->type != emc6d103s) {
+			i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+			data->autofan[0].min_off = (i & 0x20) != 0;
+			data->autofan[1].min_off = (i & 0x40) != 0;
+			data->autofan[2].min_off = (i & 0x80) != 0;
 
-		i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
-		data->zone[0].hyst = i >> 4;
-		data->zone[1].hyst = i & 0x0f;
+			i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+			data->zone[0].hyst = i >> 4;
+			data->zone[1].hyst = i & 0x0f;
 
-		i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
-		data->zone[2].hyst = i >> 4;
+			i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+			data->zone[2].hyst = i >> 4;
+		}
 
 		data->last_config = jiffies;
 	}  /* last_config */
diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c
new file mode 100644
index 0000000..4ac06b7
--- /dev/null
+++ b/drivers/hwmon/ltc4151.c
@@ -0,0 +1,256 @@
+/*
+ * Driver for Linear Technology LTC4151 High Voltage I2C Current
+ * and Voltage Monitor
+ *
+ * Copyright (C) 2011 AppearTV AS
+ *
+ * Derived from:
+ *
+ *  Driver for Linear Technology LTC4261 I2C Negative Voltage Hot
+ *  Swap Controller
+ *  Copyright (C) 2010 Ericsson AB.
+ *
+ * Datasheet: http://www.linear.com/docs/Datasheet/4151fc.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/* chip registers */
+#define LTC4151_SENSE_H	0x00
+#define LTC4151_SENSE_L	0x01
+#define LTC4151_VIN_H	0x02
+#define LTC4151_VIN_L	0x03
+#define LTC4151_ADIN_H	0x04
+#define LTC4151_ADIN_L	0x05
+
+struct ltc4151_data {
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	bool valid;
+	unsigned long last_updated; /* in jiffies */
+
+	/* Registers */
+	u8 regs[6];
+};
+
+static struct ltc4151_data *ltc4151_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ltc4151_data *data = i2c_get_clientdata(client);
+	struct ltc4151_data *ret = data;
+
+	mutex_lock(&data->update_lock);
+
+	/*
+	 * The chip's A/D updates 6 times per second
+	 * (Conversion Rate 6 - 9 Hz)
+	 */
+	if (time_after(jiffies, data->last_updated + HZ / 6) || !data->valid) {
+		int i;
+
+		dev_dbg(&client->dev, "Starting ltc4151 update\n");
+
+		/* Read all registers */
+		for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
+			int val;
+
+			val = i2c_smbus_read_byte_data(client, i);
+			if (unlikely(val < 0)) {
+				dev_dbg(dev,
+					"Failed to read ADC value: error %d\n",
+					val);
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->regs[i] = val;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+/* Return the voltage from the given register in mV */
+static int ltc4151_get_value(struct ltc4151_data *data, u8 reg)
+{
+	u32 val;
+
+	val = (data->regs[reg] << 4) + (data->regs[reg + 1] >> 4);
+
+	switch (reg) {
+	case LTC4151_ADIN_H:
+		/* 500uV resolution. Convert to mV. */
+		val = val * 500 / 1000;
+		break;
+	case LTC4151_SENSE_H:
+		/*
+		 * 20uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA.
+		 */
+		val = val * 20;
+		break;
+	case LTC4151_VIN_H:
+		/* 25 mV per increment */
+		val = val * 25;
+		break;
+	default:
+		/* If we get here, the developer messed up */
+		WARN_ON_ONCE(1);
+		val = 0;
+		break;
+	}
+
+	return val;
+}
+
+static ssize_t ltc4151_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ltc4151_data *data = ltc4151_update_device(dev);
+	int value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = ltc4151_get_value(data, attr->index);
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+/*
+ * 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);
+
+/* Currents (via sense resistor) */
+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,
+ * as required for sysfs_create_group()
+ */
+static struct attribute *ltc4151_attributes[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+
+	NULL,
+};
+
+static const struct attribute_group ltc4151_group = {
+	.attrs = ltc4151_attributes,
+};
+
+static int ltc4151_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct ltc4151_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out_kzalloc;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&client->dev.kobj, &ltc4151_group);
+	if (ret)
+		goto out_sysfs_create_group;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto out_hwmon_device_register;
+	}
+
+	return 0;
+
+out_hwmon_device_register:
+	sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
+out_sysfs_create_group:
+	kfree(data);
+out_kzalloc:
+	return ret;
+}
+
+static int ltc4151_remove(struct i2c_client *client)
+{
+	struct ltc4151_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
+
+	kfree(data);
+
+	return 0;
+}
+
+static const struct i2c_device_id ltc4151_id[] = {
+	{ "ltc4151", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ltc4151_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc4151_driver = {
+	.driver = {
+		.name	= "ltc4151",
+	},
+	.probe		= ltc4151_probe,
+	.remove		= ltc4151_remove,
+	.id_table	= ltc4151_id,
+};
+
+static int __init ltc4151_init(void)
+{
+	return i2c_add_driver(&ltc4151_driver);
+}
+
+static void __exit ltc4151_exit(void)
+{
+	i2c_del_driver(&ltc4151_driver);
+}
+
+MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
+MODULE_DESCRIPTION("LTC4151 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ltc4151_init);
+module_exit(ltc4151_exit);
diff --git a/drivers/hwmon/max16064.c b/drivers/hwmon/max16064.c
new file mode 100644
index 0000000..1d6d717
--- /dev/null
+++ b/drivers/hwmon/max16064.c
@@ -0,0 +1,91 @@
+/*
+ * Hardware monitoring driver for Maxim MAX16064
+ *
+ * Copyright (c) 2011 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.
+ *
+ * You 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/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info max16064_info = {
+	.pages = 4,
+	.direct[PSC_VOLTAGE_IN] = true,
+	.direct[PSC_VOLTAGE_OUT] = true,
+	.direct[PSC_TEMPERATURE] = true,
+	.m[PSC_VOLTAGE_IN] = 19995,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = -1,
+	.m[PSC_VOLTAGE_OUT] = 19995,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = -1,
+	.m[PSC_TEMPERATURE] = -7612,
+	.b[PSC_TEMPERATURE] = 335,
+	.R[PSC_TEMPERATURE] = -3,
+	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP
+		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP,
+	.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+	.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+	.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+};
+
+static int max16064_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &max16064_info);
+}
+
+static int max16064_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id max16064_id[] = {
+	{"max16064", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, max16064_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max16064_driver = {
+	.driver = {
+		   .name = "max16064",
+		   },
+	.probe = max16064_probe,
+	.remove = max16064_remove,
+	.id_table = max16064_id,
+};
+
+static int __init max16064_init(void)
+{
+	return i2c_add_driver(&max16064_driver);
+}
+
+static void __exit max16064_exit(void)
+{
+	i2c_del_driver(&max16064_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
+MODULE_LICENSE("GPL");
+module_init(max16064_init);
+module_exit(max16064_exit);
diff --git a/drivers/hwmon/max34440.c b/drivers/hwmon/max34440.c
new file mode 100644
index 0000000..992b701
--- /dev/null
+++ b/drivers/hwmon/max34440.c
@@ -0,0 +1,199 @@
+/*
+ * Hardware monitoring driver for Maxim MAX34440/MAX34441
+ *
+ * Copyright (c) 2011 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.
+ *
+ * You 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/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+enum chips { max34440, max34441 };
+
+#define MAX34440_STATUS_OC_WARN		(1 << 0)
+#define MAX34440_STATUS_OC_FAULT	(1 << 1)
+#define MAX34440_STATUS_OT_FAULT	(1 << 5)
+#define MAX34440_STATUS_OT_WARN		(1 << 6)
+
+static int max34440_get_status(struct i2c_client *client, int page, int reg)
+{
+	int ret;
+	int mfg_status;
+
+	ret = pmbus_set_page(client, page);
+	if (ret < 0)
+		return ret;
+
+	switch (reg) {
+	case PMBUS_STATUS_IOUT:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  PMBUS_STATUS_MFR_SPECIFIC);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX34440_STATUS_OC_WARN)
+			ret |= PB_IOUT_OC_WARNING;
+		if (mfg_status & MAX34440_STATUS_OC_FAULT)
+			ret |= PB_IOUT_OC_FAULT;
+		break;
+	case PMBUS_STATUS_TEMPERATURE:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  PMBUS_STATUS_MFR_SPECIFIC);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX34440_STATUS_OT_WARN)
+			ret |= PB_TEMP_OT_WARNING;
+		if (mfg_status & MAX34440_STATUS_OT_FAULT)
+			ret |= PB_TEMP_OT_FAULT;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static struct pmbus_driver_info max34440_info[] = {
+	[max34440] = {
+		.pages = 14,
+		.direct[PSC_VOLTAGE_IN] = true,
+		.direct[PSC_VOLTAGE_OUT] = true,
+		.direct[PSC_TEMPERATURE] = true,
+		.direct[PSC_CURRENT_OUT] = true,
+		.m[PSC_VOLTAGE_IN] = 1,
+		.b[PSC_VOLTAGE_IN] = 0,
+		.R[PSC_VOLTAGE_IN] = 3,	    /* R = 0 in datasheet reflects mV */
+		.m[PSC_VOLTAGE_OUT] = 1,
+		.b[PSC_VOLTAGE_OUT] = 0,
+		.R[PSC_VOLTAGE_OUT] = 3,    /* R = 0 in datasheet reflects mV */
+		.m[PSC_CURRENT_OUT] = 1,
+		.b[PSC_CURRENT_OUT] = 0,
+		.R[PSC_CURRENT_OUT] = 3,    /* R = 0 in datasheet reflects mA */
+		.m[PSC_TEMPERATURE] = 1,
+		.b[PSC_TEMPERATURE] = 0,
+		.R[PSC_TEMPERATURE] = 2,
+		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.get_status = max34440_get_status,
+	},
+	[max34441] = {
+		.pages = 12,
+		.direct[PSC_VOLTAGE_IN] = true,
+		.direct[PSC_VOLTAGE_OUT] = true,
+		.direct[PSC_TEMPERATURE] = true,
+		.direct[PSC_CURRENT_OUT] = true,
+		.direct[PSC_FAN] = true,
+		.m[PSC_VOLTAGE_IN] = 1,
+		.b[PSC_VOLTAGE_IN] = 0,
+		.R[PSC_VOLTAGE_IN] = 3,
+		.m[PSC_VOLTAGE_OUT] = 1,
+		.b[PSC_VOLTAGE_OUT] = 0,
+		.R[PSC_VOLTAGE_OUT] = 3,
+		.m[PSC_CURRENT_OUT] = 1,
+		.b[PSC_CURRENT_OUT] = 0,
+		.R[PSC_CURRENT_OUT] = 3,
+		.m[PSC_TEMPERATURE] = 1,
+		.b[PSC_TEMPERATURE] = 0,
+		.R[PSC_TEMPERATURE] = 2,
+		.m[PSC_FAN] = 1,
+		.b[PSC_FAN] = 0,
+		.R[PSC_FAN] = 0,
+		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
+		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.get_status = max34440_get_status,
+	},
+};
+
+static int max34440_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &max34440_info[id->driver_data]);
+}
+
+static int max34440_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id max34440_id[] = {
+	{"max34440", max34440},
+	{"max34441", max34441},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, max34440_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max34440_driver = {
+	.driver = {
+		   .name = "max34440",
+		   },
+	.probe = max34440_probe,
+	.remove = max34440_remove,
+	.id_table = max34440_id,
+};
+
+static int __init max34440_init(void)
+{
+	return i2c_add_driver(&max34440_driver);
+}
+
+static void __exit max34440_exit(void)
+{
+	i2c_del_driver(&max34440_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
+MODULE_LICENSE("GPL");
+module_init(max34440_init);
+module_exit(max34440_exit);
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
new file mode 100644
index 0000000..f20d997
--- /dev/null
+++ b/drivers/hwmon/max6639.c
@@ -0,0 +1,653 @@
+/*
+ * max6639.c - Support for Maxim MAX6639
+ *
+ * 2-Channel Temperature Monitor with Dual PWM Fan-Speed Controller
+ *
+ * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
+ *
+ * based on the initial MAX6639 support from semptian.net
+ * by He Changqing <hechangqing@semptian.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/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/i2c/max6639.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* The MAX6639 registers, valid channel numbers: 0, 1 */
+#define MAX6639_REG_TEMP(ch)			(0x00 + (ch))
+#define MAX6639_REG_STATUS			0x02
+#define MAX6639_REG_OUTPUT_MASK			0x03
+#define MAX6639_REG_GCONFIG			0x04
+#define MAX6639_REG_TEMP_EXT(ch)		(0x05 + (ch))
+#define MAX6639_REG_ALERT_LIMIT(ch)		(0x08 + (ch))
+#define MAX6639_REG_OT_LIMIT(ch)		(0x0A + (ch))
+#define MAX6639_REG_THERM_LIMIT(ch)		(0x0C + (ch))
+#define MAX6639_REG_FAN_CONFIG1(ch)		(0x10 + (ch) * 4)
+#define MAX6639_REG_FAN_CONFIG2a(ch)		(0x11 + (ch) * 4)
+#define MAX6639_REG_FAN_CONFIG2b(ch)		(0x12 + (ch) * 4)
+#define MAX6639_REG_FAN_CONFIG3(ch)		(0x13 + (ch) * 4)
+#define MAX6639_REG_FAN_CNT(ch)			(0x20 + (ch))
+#define MAX6639_REG_TARGET_CNT(ch)		(0x22 + (ch))
+#define MAX6639_REG_FAN_PPR(ch)			(0x24 + (ch))
+#define MAX6639_REG_TARGTDUTY(ch)		(0x26 + (ch))
+#define MAX6639_REG_FAN_START_TEMP(ch)		(0x28 + (ch))
+#define MAX6639_REG_DEVID			0x3D
+#define MAX6639_REG_MANUID			0x3E
+#define MAX6639_REG_DEVREV			0x3F
+
+/* Register bits */
+#define MAX6639_GCONFIG_STANDBY			0x80
+#define MAX6639_GCONFIG_POR			0x40
+#define MAX6639_GCONFIG_DISABLE_TIMEOUT		0x20
+#define MAX6639_GCONFIG_CH2_LOCAL		0x10
+#define MAX6639_GCONFIG_PWM_FREQ_HI		0x08
+
+#define MAX6639_FAN_CONFIG1_PWM			0x80
+
+#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED	0x40
+
+static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
+
+#define FAN_FROM_REG(val, div, rpm_range)	((val) == 0 ? -1 : \
+	(val) == 255 ? 0 : (rpm_ranges[rpm_range] * 30) / ((div + 1) * (val)))
+#define TEMP_LIMIT_TO_REG(val)	SENSORS_LIMIT((val) / 1000, 0, 255)
+
+/*
+ * Client data (each client gets its own)
+ */
+struct max6639_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* Register values sampled regularly */
+	u16 temp[2];		/* Temperature, in 1/8 C, 0..255 C */
+	bool temp_fault[2];	/* Detected temperature diode failure */
+	u8 fan[2];		/* Register value: TACH count for fans >=30 */
+	u8 status;		/* Detected channel alarms and fan failures */
+
+	/* Register values only written to */
+	u8 pwm[2];		/* Register value: Duty cycle 0..120 */
+	u8 temp_therm[2];	/* THERM Temperature, 0..255 C (->_max) */
+	u8 temp_alert[2];	/* ALERT Temperature, 0..255 C (->_crit) */
+	u8 temp_ot[2];		/* OT Temperature, 0..255 C (->_emergency) */
+
+	/* Register values initialized only once */
+	u8 ppr;			/* Pulses per rotation 0..3 for 1..4 ppr */
+	u8 rpm_range;		/* Index in above rpm_ranges table */
+};
+
+static struct max6639_data *max6639_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct max6639_data *ret = data;
+	int i;
+	int status_reg;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
+		int res;
+
+		dev_dbg(&client->dev, "Starting max6639 update\n");
+
+		status_reg = i2c_smbus_read_byte_data(client,
+						      MAX6639_REG_STATUS);
+		if (status_reg < 0) {
+			ret = ERR_PTR(status_reg);
+			goto abort;
+		}
+
+		data->status = status_reg;
+
+		for (i = 0; i < 2; i++) {
+			res = i2c_smbus_read_byte_data(client,
+					MAX6639_REG_FAN_CNT(i));
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+			data->fan[i] = res;
+
+			res = i2c_smbus_read_byte_data(client,
+					MAX6639_REG_TEMP_EXT(i));
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+			data->temp[i] = res >> 5;
+			data->temp_fault[i] = res & 0x01;
+
+			res = i2c_smbus_read_byte_data(client,
+					MAX6639_REG_TEMP(i));
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+			data->temp[i] |= res << 3;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+
+	return ret;
+}
+
+static ssize_t show_temp_input(struct device *dev,
+			       struct device_attribute *dev_attr, char *buf)
+{
+	long temp;
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	temp = data->temp[attr->index] * 125;
+	return sprintf(buf, "%ld\n", temp);
+}
+
+static ssize_t show_temp_fault(struct device *dev,
+			       struct device_attribute *dev_attr, char *buf)
+{
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", data->temp_fault[attr->index]);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *dev_attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000));
+}
+
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *dev_attr,
+			    const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	mutex_lock(&data->update_lock);
+	data->temp_therm[attr->index] = TEMP_LIMIT_TO_REG(val);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_THERM_LIMIT(attr->index),
+				  data->temp_therm[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp_crit(struct device *dev,
+			      struct device_attribute *dev_attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000));
+}
+
+static ssize_t set_temp_crit(struct device *dev,
+			     struct device_attribute *dev_attr,
+			     const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	mutex_lock(&data->update_lock);
+	data->temp_alert[attr->index] = TEMP_LIMIT_TO_REG(val);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_ALERT_LIMIT(attr->index),
+				  data->temp_alert[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp_emergency(struct device *dev,
+				   struct device_attribute *dev_attr,
+				   char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000));
+}
+
+static ssize_t set_temp_emergency(struct device *dev,
+				  struct device_attribute *dev_attr,
+				  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	mutex_lock(&data->update_lock);
+	data->temp_ot[attr->index] = TEMP_LIMIT_TO_REG(val);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_OT_LIMIT(attr->index),
+				  data->temp_ot[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_pwm(struct device *dev,
+			struct device_attribute *dev_attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120);
+}
+
+static ssize_t set_pwm(struct device *dev,
+		       struct device_attribute *dev_attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	val = SENSORS_LIMIT(val, 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->pwm[attr->index] = (u8)(val * 120 / 255);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_TARGTDUTY(attr->index),
+				  data->pwm[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_fan_input(struct device *dev,
+			      struct device_attribute *dev_attr, char *buf)
+{
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
+		       data->ppr, data->rpm_range));
+}
+
+static ssize_t show_alarm(struct device *dev,
+			  struct device_attribute *dev_attr, char *buf)
+{
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", !!(data->status & (1 << attr->index)));
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+		set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
+		set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit,
+		set_temp_crit, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit,
+		set_temp_crit, 1);
+static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO,
+		show_temp_emergency, set_temp_emergency, 0);
+static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO,
+		show_temp_emergency, set_temp_emergency, 1);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 4);
+
+
+static struct attribute *max6639_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
+	&sensor_dev_attr_temp2_emergency.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
+	&sensor_dev_attr_fan2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group max6639_group = {
+	.attrs = max6639_attributes,
+};
+
+/*
+ *  returns respective index in rpm_ranges table
+ *  1 by default on invalid range
+ */
+static int rpm_range_to_reg(int range)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rpm_ranges); i++) {
+		if (rpm_ranges[i] == range)
+			return i;
+	}
+
+	return 1; /* default: 4000 RPM */
+}
+
+static int max6639_init_client(struct i2c_client *client)
+{
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct max6639_platform_data *max6639_info =
+		client->dev.platform_data;
+	int i = 0;
+	int rpm_range = 1; /* default: 4000 RPM */
+	int err = 0;
+
+	/* Reset chip to default values, see below for GCONFIG setup */
+	err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG,
+				  MAX6639_GCONFIG_POR);
+	if (err)
+		goto exit;
+
+	/* Fans pulse per revolution is 2 by default */
+	if (max6639_info && max6639_info->ppr > 0 &&
+			max6639_info->ppr < 5)
+		data->ppr = max6639_info->ppr;
+	else
+		data->ppr = 2;
+	data->ppr -= 1;
+	err = i2c_smbus_write_byte_data(client,
+			MAX6639_REG_FAN_PPR(i),
+			data->ppr << 5);
+	if (err)
+		goto exit;
+
+	if (max6639_info)
+		rpm_range = rpm_range_to_reg(max6639_info->rpm_range);
+	data->rpm_range = rpm_range;
+
+	for (i = 0; i < 2; i++) {
+
+		/* Fans config PWM, RPM */
+		err = i2c_smbus_write_byte_data(client,
+			MAX6639_REG_FAN_CONFIG1(i),
+			MAX6639_FAN_CONFIG1_PWM | rpm_range);
+		if (err)
+			goto exit;
+
+		/* Fans PWM polarity high by default */
+		if (max6639_info && max6639_info->pwm_polarity == 0)
+			err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_FAN_CONFIG2a(i), 0x00);
+		else
+			err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_FAN_CONFIG2a(i), 0x02);
+		if (err)
+			goto exit;
+
+		/*
+		 * /THERM full speed enable,
+		 * PWM frequency 25kHz, see also GCONFIG below
+		 */
+		err = i2c_smbus_write_byte_data(client,
+			MAX6639_REG_FAN_CONFIG3(i),
+			MAX6639_FAN_CONFIG3_THERM_FULL_SPEED | 0x03);
+		if (err)
+			goto exit;
+
+		/* Max. temp. 80C/90C/100C */
+		data->temp_therm[i] = 80;
+		data->temp_alert[i] = 90;
+		data->temp_ot[i] = 100;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_THERM_LIMIT(i),
+				data->temp_therm[i]);
+		if (err)
+			goto exit;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_ALERT_LIMIT(i),
+				data->temp_alert[i]);
+		if (err)
+			goto exit;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_OT_LIMIT(i), data->temp_ot[i]);
+		if (err)
+			goto exit;
+
+		/* PWM 120/120 (i.e. 100%) */
+		data->pwm[i] = 120;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_TARGTDUTY(i), data->pwm[i]);
+		if (err)
+			goto exit;
+	}
+	/* Start monitoring */
+	err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG,
+		MAX6639_GCONFIG_DISABLE_TIMEOUT | MAX6639_GCONFIG_CH2_LOCAL |
+		MAX6639_GCONFIG_PWM_FREQ_HI);
+exit:
+	return err;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max6639_detect(struct i2c_client *client,
+			  struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int dev_id, manu_id;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	/* Actual detection via device and manufacturer ID */
+	dev_id = i2c_smbus_read_byte_data(client, MAX6639_REG_DEVID);
+	manu_id = i2c_smbus_read_byte_data(client, MAX6639_REG_MANUID);
+	if (dev_id != 0x58 || manu_id != 0x4D)
+		return -ENODEV;
+
+	strlcpy(info->type, "max6639", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static int max6639_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct max6639_data *data;
+	int err;
+
+	data = kzalloc(sizeof(struct max6639_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Initialize the max6639 chip */
+	err = max6639_init_client(client);
+	if (err < 0)
+		goto error_free;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&client->dev.kobj, &max6639_group);
+	if (err)
+		goto error_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto error_remove;
+	}
+
+	dev_info(&client->dev, "temperature sensor and fan control found\n");
+
+	return 0;
+
+error_remove:
+	sysfs_remove_group(&client->dev.kobj, &max6639_group);
+error_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int max6639_remove(struct i2c_client *client)
+{
+	struct max6639_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &max6639_group);
+
+	kfree(data);
+	return 0;
+}
+
+static int max6639_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
+	if (data < 0)
+		return data;
+
+	return i2c_smbus_write_byte_data(client,
+			MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY);
+}
+
+static int max6639_resume(struct i2c_client *client)
+{
+	int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
+	if (data < 0)
+		return data;
+
+	return i2c_smbus_write_byte_data(client,
+			MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY);
+}
+
+static const struct i2c_device_id max6639_id[] = {
+	{"max6639", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, max6639_id);
+
+static struct i2c_driver max6639_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		   .name = "max6639",
+		   },
+	.probe = max6639_probe,
+	.remove = max6639_remove,
+	.suspend = max6639_suspend,
+	.resume = max6639_resume,
+	.id_table = max6639_id,
+	.detect = max6639_detect,
+	.address_list = normal_i2c,
+};
+
+static int __init max6639_init(void)
+{
+	return i2c_add_driver(&max6639_driver);
+}
+
+static void __exit max6639_exit(void)
+{
+	i2c_del_driver(&max6639_driver);
+}
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("max6639 driver");
+MODULE_LICENSE("GPL");
+
+module_init(max6639_init);
+module_exit(max6639_exit);
diff --git a/drivers/hwmon/max8688.c b/drivers/hwmon/max8688.c
new file mode 100644
index 0000000..8ebfef2
--- /dev/null
+++ b/drivers/hwmon/max8688.c
@@ -0,0 +1,158 @@
+/*
+ * Hardware monitoring driver for Maxim MAX8688
+ *
+ * Copyright (c) 2011 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.
+ *
+ * You 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/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+#define MAX8688_MFG_STATUS		0xd8
+
+#define MAX8688_STATUS_OC_FAULT		(1 << 4)
+#define MAX8688_STATUS_OV_FAULT		(1 << 5)
+#define MAX8688_STATUS_OV_WARNING	(1 << 8)
+#define MAX8688_STATUS_UV_FAULT		(1 << 9)
+#define MAX8688_STATUS_UV_WARNING	(1 << 10)
+#define MAX8688_STATUS_UC_FAULT		(1 << 11)
+#define MAX8688_STATUS_OC_WARNING	(1 << 12)
+#define MAX8688_STATUS_OT_FAULT		(1 << 13)
+#define MAX8688_STATUS_OT_WARNING	(1 << 14)
+
+static int max8688_get_status(struct i2c_client *client, int page, int reg)
+{
+	int ret = 0;
+	int mfg_status;
+
+	if (page)
+		return -EINVAL;
+
+	switch (reg) {
+	case PMBUS_STATUS_VOUT:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  MAX8688_MFG_STATUS);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX8688_STATUS_UV_WARNING)
+			ret |= PB_VOLTAGE_UV_WARNING;
+		if (mfg_status & MAX8688_STATUS_UV_FAULT)
+			ret |= PB_VOLTAGE_UV_FAULT;
+		if (mfg_status & MAX8688_STATUS_OV_WARNING)
+			ret |= PB_VOLTAGE_OV_WARNING;
+		if (mfg_status & MAX8688_STATUS_OV_FAULT)
+			ret |= PB_VOLTAGE_OV_FAULT;
+		break;
+	case PMBUS_STATUS_IOUT:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  MAX8688_MFG_STATUS);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX8688_STATUS_UC_FAULT)
+			ret |= PB_IOUT_UC_FAULT;
+		if (mfg_status & MAX8688_STATUS_OC_WARNING)
+			ret |= PB_IOUT_OC_WARNING;
+		if (mfg_status & MAX8688_STATUS_OC_FAULT)
+			ret |= PB_IOUT_OC_FAULT;
+		break;
+	case PMBUS_STATUS_TEMPERATURE:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  MAX8688_MFG_STATUS);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX8688_STATUS_OT_WARNING)
+			ret |= PB_TEMP_OT_WARNING;
+		if (mfg_status & MAX8688_STATUS_OT_FAULT)
+			ret |= PB_TEMP_OT_FAULT;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static struct pmbus_driver_info max8688_info = {
+	.pages = 1,
+	.direct[PSC_VOLTAGE_IN] = true,
+	.direct[PSC_VOLTAGE_OUT] = true,
+	.direct[PSC_TEMPERATURE] = true,
+	.direct[PSC_CURRENT_OUT] = true,
+	.m[PSC_VOLTAGE_IN] = 19995,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = -1,
+	.m[PSC_VOLTAGE_OUT] = 19995,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = -1,
+	.m[PSC_CURRENT_OUT] = 23109,
+	.b[PSC_CURRENT_OUT] = 0,
+	.R[PSC_CURRENT_OUT] = -2,
+	.m[PSC_TEMPERATURE] = -7612,
+	.b[PSC_TEMPERATURE] = 335,
+	.R[PSC_TEMPERATURE] = -3,
+	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
+		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+		| PMBUS_HAVE_STATUS_TEMP,
+	.get_status = max8688_get_status,
+};
+
+static int max8688_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &max8688_info);
+}
+
+static int max8688_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id max8688_id[] = {
+	{"max8688", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, max8688_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max8688_driver = {
+	.driver = {
+		   .name = "max8688",
+		   },
+	.probe = max8688_probe,
+	.remove = max8688_remove,
+	.id_table = max8688_id,
+};
+
+static int __init max8688_init(void)
+{
+	return i2c_add_driver(&max8688_driver);
+}
+
+static void __exit max8688_exit(void)
+{
+	i2c_del_driver(&max8688_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
+MODULE_LICENSE("GPL");
+module_init(max8688_init);
+module_exit(max8688_exit);
diff --git a/drivers/hwmon/pmbus.c b/drivers/hwmon/pmbus.c
new file mode 100644
index 0000000..98e2e28
--- /dev/null
+++ b/drivers/hwmon/pmbus.c
@@ -0,0 +1,203 @@
+/*
+ * Hardware monitoring driver for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 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.
+ *
+ * You 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/err.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+/*
+ * Find sensor groups and status registers on each page.
+ */
+static void pmbus_find_sensor_groups(struct i2c_client *client,
+				     struct pmbus_driver_info *info)
+{
+	int page;
+
+	/* Sensors detected on page 0 only */
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN))
+		info->func[0] |= PMBUS_HAVE_VIN;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP))
+		info->func[0] |= PMBUS_HAVE_VCAP;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN))
+		info->func[0] |= PMBUS_HAVE_IIN;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN))
+		info->func[0] |= PMBUS_HAVE_PIN;
+	if (info->func[0]
+	    && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
+		info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
+		info->func[0] |= PMBUS_HAVE_FAN12;
+		if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
+			info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
+	}
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
+		info->func[0] |= PMBUS_HAVE_FAN34;
+		if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
+			info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
+	}
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) {
+		info->func[0] |= PMBUS_HAVE_TEMP;
+		if (pmbus_check_byte_register(client, 0,
+					      PMBUS_STATUS_TEMPERATURE))
+			info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
+	}
+
+	/* Sensors detected on all pages */
+	for (page = 0; page < info->pages; page++) {
+		if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) {
+			info->func[page] |= PMBUS_HAVE_VOUT;
+			if (pmbus_check_byte_register(client, page,
+						      PMBUS_STATUS_VOUT))
+				info->func[page] |= PMBUS_HAVE_STATUS_VOUT;
+		}
+		if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) {
+			info->func[page] |= PMBUS_HAVE_IOUT;
+			if (pmbus_check_byte_register(client, 0,
+						      PMBUS_STATUS_IOUT))
+				info->func[page] |= PMBUS_HAVE_STATUS_IOUT;
+		}
+		if (pmbus_check_word_register(client, page, PMBUS_READ_POUT))
+			info->func[page] |= PMBUS_HAVE_POUT;
+	}
+}
+
+/*
+ * Identify chip parameters.
+ */
+static int pmbus_identify(struct i2c_client *client,
+			  struct pmbus_driver_info *info)
+{
+	if (!info->pages) {
+		/*
+		 * Check if the PAGE command is supported. If it is,
+		 * keep setting the page number until it fails or until the
+		 * maximum number of pages has been reached. Assume that
+		 * this is the number of pages supported by the chip.
+		 */
+		if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) {
+			int page;
+
+			for (page = 1; page < PMBUS_PAGES; page++) {
+				if (pmbus_set_page(client, page) < 0)
+					break;
+			}
+			pmbus_set_page(client, 0);
+			info->pages = page;
+		} else {
+			info->pages = 1;
+		}
+	}
+
+	/*
+	 * We should check if the COEFFICIENTS register is supported.
+	 * If it is, and the chip is configured for direct mode, we can read
+	 * the coefficients from the chip, one set per group of sensor
+	 * registers.
+	 *
+	 * To do this, we will need access to a chip which actually supports the
+	 * COEFFICIENTS command, since the command is too complex to implement
+	 * without testing it.
+	 */
+
+	/* Try to find sensor groups  */
+	pmbus_find_sensor_groups(client, info);
+
+	return 0;
+}
+
+static int pmbus_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct pmbus_driver_info *info;
+	int ret;
+
+	info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->pages = id->driver_data;
+	info->identify = pmbus_identify;
+
+	ret = pmbus_do_probe(client, id, info);
+	if (ret < 0)
+		goto out;
+	return 0;
+
+out:
+	kfree(info);
+	return ret;
+}
+
+static int pmbus_remove(struct i2c_client *client)
+{
+	int ret;
+	const struct pmbus_driver_info *info;
+
+	info = pmbus_get_driver_info(client);
+	ret = pmbus_do_remove(client);
+	kfree(info);
+	return ret;
+}
+
+/*
+ * Use driver_data to set the number of pages supported by the chip.
+ */
+static const struct i2c_device_id pmbus_id[] = {
+	{"bmr450", 1},
+	{"bmr451", 1},
+	{"bmr453", 1},
+	{"bmr454", 1},
+	{"ltc2978", 8},
+	{"pmbus", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, pmbus_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pmbus_driver = {
+	.driver = {
+		   .name = "pmbus",
+		   },
+	.probe = pmbus_probe,
+	.remove = pmbus_remove,
+	.id_table = pmbus_id,
+};
+
+static int __init pmbus_init(void)
+{
+	return i2c_add_driver(&pmbus_driver);
+}
+
+static void __exit pmbus_exit(void)
+{
+	i2c_del_driver(&pmbus_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("Generic PMBus driver");
+MODULE_LICENSE("GPL");
+module_init(pmbus_init);
+module_exit(pmbus_exit);
diff --git a/drivers/hwmon/pmbus.h b/drivers/hwmon/pmbus.h
new file mode 100644
index 0000000..a81f7f2
--- /dev/null
+++ b/drivers/hwmon/pmbus.h
@@ -0,0 +1,313 @@
+/*
+ * pmbus.h - Common defines and structures for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 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.
+ *
+ * You 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 PMBUS_H
+#define PMBUS_H
+
+/*
+ * Registers
+ */
+#define PMBUS_PAGE			0x00
+#define PMBUS_OPERATION			0x01
+#define PMBUS_ON_OFF_CONFIG		0x02
+#define PMBUS_CLEAR_FAULTS		0x03
+#define PMBUS_PHASE			0x04
+
+#define PMBUS_CAPABILITY		0x19
+#define PMBUS_QUERY			0x1A
+
+#define PMBUS_VOUT_MODE			0x20
+#define PMBUS_VOUT_COMMAND		0x21
+#define PMBUS_VOUT_TRIM			0x22
+#define PMBUS_VOUT_CAL_OFFSET		0x23
+#define PMBUS_VOUT_MAX			0x24
+#define PMBUS_VOUT_MARGIN_HIGH		0x25
+#define PMBUS_VOUT_MARGIN_LOW		0x26
+#define PMBUS_VOUT_TRANSITION_RATE	0x27
+#define PMBUS_VOUT_DROOP		0x28
+#define PMBUS_VOUT_SCALE_LOOP		0x29
+#define PMBUS_VOUT_SCALE_MONITOR	0x2A
+
+#define PMBUS_COEFFICIENTS		0x30
+#define PMBUS_POUT_MAX			0x31
+
+#define PMBUS_FAN_CONFIG_12		0x3A
+#define PMBUS_FAN_COMMAND_1		0x3B
+#define PMBUS_FAN_COMMAND_2		0x3C
+#define PMBUS_FAN_CONFIG_34		0x3D
+#define PMBUS_FAN_COMMAND_3		0x3E
+#define PMBUS_FAN_COMMAND_4		0x3F
+
+#define PMBUS_VOUT_OV_FAULT_LIMIT	0x40
+#define PMBUS_VOUT_OV_FAULT_RESPONSE	0x41
+#define PMBUS_VOUT_OV_WARN_LIMIT	0x42
+#define PMBUS_VOUT_UV_WARN_LIMIT	0x43
+#define PMBUS_VOUT_UV_FAULT_LIMIT	0x44
+#define PMBUS_VOUT_UV_FAULT_RESPONSE	0x45
+#define PMBUS_IOUT_OC_FAULT_LIMIT	0x46
+#define PMBUS_IOUT_OC_FAULT_RESPONSE	0x47
+#define PMBUS_IOUT_OC_LV_FAULT_LIMIT	0x48
+#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE	0x49
+#define PMBUS_IOUT_OC_WARN_LIMIT	0x4A
+#define PMBUS_IOUT_UC_FAULT_LIMIT	0x4B
+#define PMBUS_IOUT_UC_FAULT_RESPONSE	0x4C
+
+#define PMBUS_OT_FAULT_LIMIT		0x4F
+#define PMBUS_OT_FAULT_RESPONSE		0x50
+#define PMBUS_OT_WARN_LIMIT		0x51
+#define PMBUS_UT_WARN_LIMIT		0x52
+#define PMBUS_UT_FAULT_LIMIT		0x53
+#define PMBUS_UT_FAULT_RESPONSE		0x54
+#define PMBUS_VIN_OV_FAULT_LIMIT	0x55
+#define PMBUS_VIN_OV_FAULT_RESPONSE	0x56
+#define PMBUS_VIN_OV_WARN_LIMIT		0x57
+#define PMBUS_VIN_UV_WARN_LIMIT		0x58
+#define PMBUS_VIN_UV_FAULT_LIMIT	0x59
+
+#define PMBUS_IIN_OC_FAULT_LIMIT	0x5B
+#define PMBUS_IIN_OC_WARN_LIMIT		0x5D
+
+#define PMBUS_POUT_OP_FAULT_LIMIT	0x68
+#define PMBUS_POUT_OP_WARN_LIMIT	0x6A
+#define PMBUS_PIN_OP_WARN_LIMIT		0x6B
+
+#define PMBUS_STATUS_BYTE		0x78
+#define PMBUS_STATUS_WORD		0x79
+#define PMBUS_STATUS_VOUT		0x7A
+#define PMBUS_STATUS_IOUT		0x7B
+#define PMBUS_STATUS_INPUT		0x7C
+#define PMBUS_STATUS_TEMPERATURE	0x7D
+#define PMBUS_STATUS_CML		0x7E
+#define PMBUS_STATUS_OTHER		0x7F
+#define PMBUS_STATUS_MFR_SPECIFIC	0x80
+#define PMBUS_STATUS_FAN_12		0x81
+#define PMBUS_STATUS_FAN_34		0x82
+
+#define PMBUS_READ_VIN			0x88
+#define PMBUS_READ_IIN			0x89
+#define PMBUS_READ_VCAP			0x8A
+#define PMBUS_READ_VOUT			0x8B
+#define PMBUS_READ_IOUT			0x8C
+#define PMBUS_READ_TEMPERATURE_1	0x8D
+#define PMBUS_READ_TEMPERATURE_2	0x8E
+#define PMBUS_READ_TEMPERATURE_3	0x8F
+#define PMBUS_READ_FAN_SPEED_1		0x90
+#define PMBUS_READ_FAN_SPEED_2		0x91
+#define PMBUS_READ_FAN_SPEED_3		0x92
+#define PMBUS_READ_FAN_SPEED_4		0x93
+#define PMBUS_READ_DUTY_CYCLE		0x94
+#define PMBUS_READ_FREQUENCY		0x95
+#define PMBUS_READ_POUT			0x96
+#define PMBUS_READ_PIN			0x97
+
+#define PMBUS_REVISION			0x98
+#define PMBUS_MFR_ID			0x99
+#define PMBUS_MFR_MODEL			0x9A
+#define PMBUS_MFR_REVISION		0x9B
+#define PMBUS_MFR_LOCATION		0x9C
+#define PMBUS_MFR_DATE			0x9D
+#define PMBUS_MFR_SERIAL		0x9E
+
+/*
+ * CAPABILITY
+ */
+#define PB_CAPABILITY_SMBALERT		(1<<4)
+#define PB_CAPABILITY_ERROR_CHECK	(1<<7)
+
+/*
+ * VOUT_MODE
+ */
+#define PB_VOUT_MODE_MODE_MASK		0xe0
+#define PB_VOUT_MODE_PARAM_MASK		0x1f
+
+#define PB_VOUT_MODE_LINEAR		0x00
+#define PB_VOUT_MODE_VID		0x20
+#define PB_VOUT_MODE_DIRECT		0x40
+
+/*
+ * Fan configuration
+ */
+#define PB_FAN_2_PULSE_MASK		((1 << 0) | (1 << 1))
+#define PB_FAN_2_RPM			(1 << 2)
+#define PB_FAN_2_INSTALLED		(1 << 3)
+#define PB_FAN_1_PULSE_MASK		((1 << 4) | (1 << 5))
+#define PB_FAN_1_RPM			(1 << 6)
+#define PB_FAN_1_INSTALLED		(1 << 7)
+
+/*
+ * STATUS_BYTE, STATUS_WORD (lower)
+ */
+#define PB_STATUS_NONE_ABOVE		(1<<0)
+#define PB_STATUS_CML			(1<<1)
+#define PB_STATUS_TEMPERATURE		(1<<2)
+#define PB_STATUS_VIN_UV		(1<<3)
+#define PB_STATUS_IOUT_OC		(1<<4)
+#define PB_STATUS_VOUT_OV		(1<<5)
+#define PB_STATUS_OFF			(1<<6)
+#define PB_STATUS_BUSY			(1<<7)
+
+/*
+ * STATUS_WORD (upper)
+ */
+#define PB_STATUS_UNKNOWN		(1<<8)
+#define PB_STATUS_OTHER			(1<<9)
+#define PB_STATUS_FANS			(1<<10)
+#define PB_STATUS_POWER_GOOD_N		(1<<11)
+#define PB_STATUS_WORD_MFR		(1<<12)
+#define PB_STATUS_INPUT			(1<<13)
+#define PB_STATUS_IOUT_POUT		(1<<14)
+#define PB_STATUS_VOUT			(1<<15)
+
+/*
+ * STATUS_IOUT
+ */
+#define PB_POUT_OP_WARNING		(1<<0)
+#define PB_POUT_OP_FAULT		(1<<1)
+#define PB_POWER_LIMITING		(1<<2)
+#define PB_CURRENT_SHARE_FAULT		(1<<3)
+#define PB_IOUT_UC_FAULT		(1<<4)
+#define PB_IOUT_OC_WARNING		(1<<5)
+#define PB_IOUT_OC_LV_FAULT		(1<<6)
+#define PB_IOUT_OC_FAULT		(1<<7)
+
+/*
+ * STATUS_VOUT, STATUS_INPUT
+ */
+#define PB_VOLTAGE_UV_FAULT		(1<<4)
+#define PB_VOLTAGE_UV_WARNING		(1<<5)
+#define PB_VOLTAGE_OV_WARNING		(1<<6)
+#define PB_VOLTAGE_OV_FAULT		(1<<7)
+
+/*
+ * STATUS_INPUT
+ */
+#define PB_PIN_OP_WARNING		(1<<0)
+#define PB_IIN_OC_WARNING		(1<<1)
+#define PB_IIN_OC_FAULT			(1<<2)
+
+/*
+ * STATUS_TEMPERATURE
+ */
+#define PB_TEMP_UT_FAULT		(1<<4)
+#define PB_TEMP_UT_WARNING		(1<<5)
+#define PB_TEMP_OT_WARNING		(1<<6)
+#define PB_TEMP_OT_FAULT		(1<<7)
+
+/*
+ * STATUS_FAN
+ */
+#define PB_FAN_AIRFLOW_WARNING		(1<<0)
+#define PB_FAN_AIRFLOW_FAULT		(1<<1)
+#define PB_FAN_FAN2_SPEED_OVERRIDE	(1<<2)
+#define PB_FAN_FAN1_SPEED_OVERRIDE	(1<<3)
+#define PB_FAN_FAN2_WARNING		(1<<4)
+#define PB_FAN_FAN1_WARNING		(1<<5)
+#define PB_FAN_FAN2_FAULT		(1<<6)
+#define PB_FAN_FAN1_FAULT		(1<<7)
+
+/*
+ * CML_FAULT_STATUS
+ */
+#define PB_CML_FAULT_OTHER_MEM_LOGIC	(1<<0)
+#define PB_CML_FAULT_OTHER_COMM		(1<<1)
+#define PB_CML_FAULT_PROCESSOR		(1<<3)
+#define PB_CML_FAULT_MEMORY		(1<<4)
+#define PB_CML_FAULT_PACKET_ERROR	(1<<5)
+#define PB_CML_FAULT_INVALID_DATA	(1<<6)
+#define PB_CML_FAULT_INVALID_COMMAND	(1<<7)
+
+enum pmbus_sensor_classes {
+	PSC_VOLTAGE_IN = 0,
+	PSC_VOLTAGE_OUT,
+	PSC_CURRENT_IN,
+	PSC_CURRENT_OUT,
+	PSC_POWER,
+	PSC_TEMPERATURE,
+	PSC_FAN,
+	PSC_NUM_CLASSES		/* Number of power sensor classes */
+};
+
+#define PMBUS_PAGES	32	/* Per PMBus specification */
+
+/* Functionality bit mask */
+#define PMBUS_HAVE_VIN		(1 << 0)
+#define PMBUS_HAVE_VCAP		(1 << 1)
+#define PMBUS_HAVE_VOUT		(1 << 2)
+#define PMBUS_HAVE_IIN		(1 << 3)
+#define PMBUS_HAVE_IOUT		(1 << 4)
+#define PMBUS_HAVE_PIN		(1 << 5)
+#define PMBUS_HAVE_POUT		(1 << 6)
+#define PMBUS_HAVE_FAN12	(1 << 7)
+#define PMBUS_HAVE_FAN34	(1 << 8)
+#define PMBUS_HAVE_TEMP		(1 << 9)
+#define PMBUS_HAVE_TEMP2	(1 << 10)
+#define PMBUS_HAVE_TEMP3	(1 << 11)
+#define PMBUS_HAVE_STATUS_VOUT	(1 << 12)
+#define PMBUS_HAVE_STATUS_IOUT	(1 << 13)
+#define PMBUS_HAVE_STATUS_INPUT	(1 << 14)
+#define PMBUS_HAVE_STATUS_TEMP	(1 << 15)
+#define PMBUS_HAVE_STATUS_FAN12	(1 << 16)
+#define PMBUS_HAVE_STATUS_FAN34	(1 << 17)
+
+struct pmbus_driver_info {
+	int pages;		/* Total number of pages */
+	bool direct[PSC_NUM_CLASSES];
+				/* true if device uses direct data format
+				   for the given sensor class */
+	/*
+	 * Support one set of coefficients for each sensor type
+	 * Used for chips providing data in direct mode.
+	 */
+	int m[PSC_NUM_CLASSES];	/* mantissa for direct data format */
+	int b[PSC_NUM_CLASSES];	/* offset */
+	int R[PSC_NUM_CLASSES];	/* exponent */
+
+	u32 func[PMBUS_PAGES];	/* Functionality, per page */
+	/*
+	 * The get_status function maps manufacturing specific status values
+	 * into PMBus standard status values.
+	 * This function is optional and only necessary if chip specific status
+	 * register values have to be mapped into standard PMBus status register
+	 * values.
+	 */
+	int (*get_status)(struct i2c_client *client, int page, int reg);
+	/*
+	 * The identify function determines supported PMBus functionality.
+	 * This function is only necessary if a chip driver supports multiple
+	 * chips, and the chip functionality is not pre-determined.
+	 */
+	int (*identify)(struct i2c_client *client,
+			struct pmbus_driver_info *info);
+};
+
+/* Function declarations */
+
+int pmbus_set_page(struct i2c_client *client, u8 page);
+int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
+void pmbus_clear_faults(struct i2c_client *client);
+bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
+bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
+int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+		   struct pmbus_driver_info *info);
+int pmbus_do_remove(struct i2c_client *client);
+const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
+						      *client);
+
+#endif /* PMBUS_H */
diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c
new file mode 100644
index 0000000..6474512
--- /dev/null
+++ b/drivers/hwmon/pmbus_core.c
@@ -0,0 +1,1658 @@
+/*
+ * Hardware monitoring driver for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 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.
+ *
+ * You 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/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/delay.h>
+#include <linux/i2c/pmbus.h>
+#include "pmbus.h"
+
+/*
+ * Constants needed to determine number of sensors, booleans, and labels.
+ */
+#define PMBUS_MAX_INPUT_SENSORS		11	/* 6*volt, 3*curr, 2*power */
+#define PMBUS_VOUT_SENSORS_PER_PAGE	5	/* input, min, max, lcrit,
+						   crit */
+#define PMBUS_IOUT_SENSORS_PER_PAGE	4	/* input, min, max, crit */
+#define PMBUS_POUT_SENSORS_PER_PAGE	4	/* input, cap, max, crit */
+#define PMBUS_MAX_SENSORS_PER_FAN	1	/* input */
+#define PMBUS_MAX_SENSORS_PER_TEMP	5	/* input, min, max, lcrit,
+						   crit */
+
+#define PMBUS_MAX_INPUT_BOOLEANS	7	/* v: min_alarm, max_alarm,
+						   lcrit_alarm, crit_alarm;
+						   c: alarm, crit_alarm;
+						   p: crit_alarm */
+#define PMBUS_VOUT_BOOLEANS_PER_PAGE	4	/* min_alarm, max_alarm,
+						   lcrit_alarm, crit_alarm */
+#define PMBUS_IOUT_BOOLEANS_PER_PAGE	3	/* alarm, lcrit_alarm,
+						   crit_alarm */
+#define PMBUS_POUT_BOOLEANS_PER_PAGE	2	/* alarm, crit_alarm */
+#define PMBUS_MAX_BOOLEANS_PER_FAN	2	/* alarm, fault */
+#define PMBUS_MAX_BOOLEANS_PER_TEMP	4	/* min_alarm, max_alarm,
+						   lcrit_alarm, crit_alarm */
+
+#define PMBUS_MAX_INPUT_LABELS		4	/* vin, vcap, iin, pin */
+
+/*
+ * status, status_vout, status_iout, status_fans, status_fan34, and status_temp
+ * are paged. status_input is unpaged.
+ */
+#define PB_NUM_STATUS_REG	(PMBUS_PAGES * 6 + 1)
+
+/*
+ * Index into status register array, per status register group
+ */
+#define PB_STATUS_BASE		0
+#define PB_STATUS_VOUT_BASE	(PB_STATUS_BASE + PMBUS_PAGES)
+#define PB_STATUS_IOUT_BASE	(PB_STATUS_VOUT_BASE + PMBUS_PAGES)
+#define PB_STATUS_FAN_BASE	(PB_STATUS_IOUT_BASE + PMBUS_PAGES)
+#define PB_STATUS_FAN34_BASE	(PB_STATUS_FAN_BASE + PMBUS_PAGES)
+#define PB_STATUS_INPUT_BASE	(PB_STATUS_FAN34_BASE + PMBUS_PAGES)
+#define PB_STATUS_TEMP_BASE	(PB_STATUS_INPUT_BASE + 1)
+
+struct pmbus_sensor {
+	char name[I2C_NAME_SIZE];	/* sysfs sensor name */
+	struct sensor_device_attribute attribute;
+	u8 page;		/* page number */
+	u8 reg;			/* register */
+	enum pmbus_sensor_classes class;	/* sensor class */
+	bool update;		/* runtime sensor update needed */
+	int data;		/* Sensor data.
+				   Negative if there was a read error */
+};
+
+struct pmbus_boolean {
+	char name[I2C_NAME_SIZE];	/* sysfs boolean name */
+	struct sensor_device_attribute attribute;
+};
+
+struct pmbus_label {
+	char name[I2C_NAME_SIZE];	/* sysfs label name */
+	struct sensor_device_attribute attribute;
+	char label[I2C_NAME_SIZE];	/* label */
+};
+
+struct pmbus_data {
+	struct device *hwmon_dev;
+
+	u32 flags;		/* from platform data */
+
+	int exponent;		/* linear mode: exponent for output voltages */
+
+	const struct pmbus_driver_info *info;
+
+	int max_attributes;
+	int num_attributes;
+	struct attribute **attributes;
+	struct attribute_group group;
+
+	/*
+	 * Sensors cover both sensor and limit registers.
+	 */
+	int max_sensors;
+	int num_sensors;
+	struct pmbus_sensor *sensors;
+	/*
+	 * Booleans are used for alarms.
+	 * Values are determined from status registers.
+	 */
+	int max_booleans;
+	int num_booleans;
+	struct pmbus_boolean *booleans;
+	/*
+	 * Labels are used to map generic names (e.g., "in1")
+	 * to PMBus specific names (e.g., "vin" or "vout1").
+	 */
+	int max_labels;
+	int num_labels;
+	struct pmbus_label *labels;
+
+	struct mutex update_lock;
+	bool valid;
+	unsigned long last_updated;	/* in jiffies */
+
+	/*
+	 * A single status register covers multiple attributes,
+	 * so we keep them all together.
+	 */
+	u8 status_bits;
+	u8 status[PB_NUM_STATUS_REG];
+
+	u8 currpage;
+};
+
+int pmbus_set_page(struct i2c_client *client, u8 page)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	int rv = 0;
+	int newpage;
+
+	if (page != data->currpage) {
+		rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
+		newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
+		if (newpage != page)
+			rv = -EINVAL;
+		else
+			data->currpage = page;
+	}
+	return rv;
+}
+EXPORT_SYMBOL_GPL(pmbus_set_page);
+
+static int pmbus_write_byte(struct i2c_client *client, u8 page, u8 value)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_write_byte(client, value);
+}
+
+static int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
+				 u16 word)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_write_word_data(client, reg, word);
+}
+
+int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_read_word_data(client, reg);
+}
+EXPORT_SYMBOL_GPL(pmbus_read_word_data);
+
+static int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static void pmbus_clear_fault_page(struct i2c_client *client, int page)
+{
+	pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+}
+
+void pmbus_clear_faults(struct i2c_client *client)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	int i;
+
+	for (i = 0; i < data->info->pages; i++)
+		pmbus_clear_fault_page(client, i);
+}
+EXPORT_SYMBOL_GPL(pmbus_clear_faults);
+
+static int pmbus_check_status_cml(struct i2c_client *client, int page)
+{
+	int status, status2;
+
+	status = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE);
+	if (status < 0 || (status & PB_STATUS_CML)) {
+		status2 = pmbus_read_byte_data(client, page, PMBUS_STATUS_CML);
+		if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
+			return -EINVAL;
+	}
+	return 0;
+}
+
+bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
+{
+	int rv;
+	struct pmbus_data *data = i2c_get_clientdata(client);
+
+	rv = pmbus_read_byte_data(client, page, reg);
+	if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
+		rv = pmbus_check_status_cml(client, page);
+	pmbus_clear_fault_page(client, page);
+	return rv >= 0;
+}
+EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
+
+bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
+{
+	int rv;
+	struct pmbus_data *data = i2c_get_clientdata(client);
+
+	rv = pmbus_read_word_data(client, page, reg);
+	if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
+		rv = pmbus_check_status_cml(client, page);
+	pmbus_clear_fault_page(client, page);
+	return rv >= 0;
+}
+EXPORT_SYMBOL_GPL(pmbus_check_word_register);
+
+const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+
+	return data->info;
+}
+EXPORT_SYMBOL_GPL(pmbus_get_driver_info);
+
+static int pmbus_get_status(struct i2c_client *client, int page, int reg)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	const struct pmbus_driver_info *info = data->info;
+	int status;
+
+	if (info->get_status) {
+		status = info->get_status(client, page, reg);
+		if (status != -ENODATA)
+			return status;
+	}
+	return  pmbus_read_byte_data(client, page, reg);
+}
+
+static struct pmbus_data *pmbus_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	const struct pmbus_driver_info *info = data->info;
+
+	mutex_lock(&data->update_lock);
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		int i;
+
+		for (i = 0; i < info->pages; i++)
+			data->status[PB_STATUS_BASE + i]
+			    = pmbus_read_byte_data(client, i,
+						   PMBUS_STATUS_BYTE);
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT))
+				continue;
+			data->status[PB_STATUS_VOUT_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_VOUT);
+		}
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_IOUT))
+				continue;
+			data->status[PB_STATUS_IOUT_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_IOUT);
+		}
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_TEMP))
+				continue;
+			data->status[PB_STATUS_TEMP_BASE + i]
+			  = pmbus_get_status(client, i,
+					     PMBUS_STATUS_TEMPERATURE);
+		}
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN12))
+				continue;
+			data->status[PB_STATUS_FAN_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_FAN_12);
+		}
+
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN34))
+				continue;
+			data->status[PB_STATUS_FAN34_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_FAN_34);
+		}
+
+		if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
+			data->status[PB_STATUS_INPUT_BASE]
+			  = pmbus_get_status(client, 0, PMBUS_STATUS_INPUT);
+
+		for (i = 0; i < data->num_sensors; i++) {
+			struct pmbus_sensor *sensor = &data->sensors[i];
+
+			if (!data->valid || sensor->update)
+				sensor->data
+				    = pmbus_read_word_data(client, sensor->page,
+							   sensor->reg);
+		}
+		pmbus_clear_faults(client);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/*
+ * Convert linear sensor values to milli- or micro-units
+ * depending on sensor type.
+ */
+static int pmbus_reg2data_linear(struct pmbus_data *data,
+				 struct pmbus_sensor *sensor)
+{
+	s16 exponent;
+	s32 mantissa;
+	long val;
+
+	if (sensor->class == PSC_VOLTAGE_OUT) {	/* LINEAR16 */
+		exponent = data->exponent;
+		mantissa = (u16) sensor->data;
+	} else {				/* LINEAR11 */
+		exponent = (sensor->data >> 11) & 0x001f;
+		mantissa = sensor->data & 0x07ff;
+
+		if (exponent > 0x0f)
+			exponent |= 0xffe0;	/* sign extend exponent */
+		if (mantissa > 0x03ff)
+			mantissa |= 0xfffff800;	/* sign extend mantissa */
+	}
+
+	val = mantissa;
+
+	/* scale result to milli-units for all sensors except fans */
+	if (sensor->class != PSC_FAN)
+		val = val * 1000L;
+
+	/* scale result to micro-units for power sensors */
+	if (sensor->class == PSC_POWER)
+		val = val * 1000L;
+
+	if (exponent >= 0)
+		val <<= exponent;
+	else
+		val >>= -exponent;
+
+	return (int)val;
+}
+
+/*
+ * Convert direct sensor values to milli- or micro-units
+ * depending on sensor type.
+ */
+static int pmbus_reg2data_direct(struct pmbus_data *data,
+				 struct pmbus_sensor *sensor)
+{
+	long val = (s16) sensor->data;
+	long m, b, R;
+
+	m = data->info->m[sensor->class];
+	b = data->info->b[sensor->class];
+	R = data->info->R[sensor->class];
+
+	if (m == 0)
+		return 0;
+
+	/* X = 1/m * (Y * 10^-R - b) */
+	R = -R;
+	/* scale result to milli-units for everything but fans */
+	if (sensor->class != PSC_FAN) {
+		R += 3;
+		b *= 1000;
+	}
+
+	/* scale result to micro-units for power sensors */
+	if (sensor->class == PSC_POWER) {
+		R += 3;
+		b *= 1000;
+	}
+
+	while (R > 0) {
+		val *= 10;
+		R--;
+	}
+	while (R < 0) {
+		val = DIV_ROUND_CLOSEST(val, 10);
+		R++;
+	}
+
+	return (int)((val - b) / m);
+}
+
+static int pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
+{
+	int val;
+
+	if (data->info->direct[sensor->class])
+		val = pmbus_reg2data_direct(data, sensor);
+	else
+		val = pmbus_reg2data_linear(data, sensor);
+
+	return val;
+}
+
+#define MAX_MANTISSA	(1023 * 1000)
+#define MIN_MANTISSA	(511 * 1000)
+
+static u16 pmbus_data2reg_linear(struct pmbus_data *data,
+				 enum pmbus_sensor_classes class, long val)
+{
+	s16 exponent = 0, mantissa;
+	bool negative = false;
+
+	/* simple case */
+	if (val == 0)
+		return 0;
+
+	if (class == PSC_VOLTAGE_OUT) {
+		/* LINEAR16 does not support negative voltages */
+		if (val < 0)
+			return 0;
+
+		/*
+		 * For a static exponents, we don't have a choice
+		 * but to adjust the value to it.
+		 */
+		if (data->exponent < 0)
+			val <<= -data->exponent;
+		else
+			val >>= data->exponent;
+		val = DIV_ROUND_CLOSEST(val, 1000);
+		return val & 0xffff;
+	}
+
+	if (val < 0) {
+		negative = true;
+		val = -val;
+	}
+
+	/* Power is in uW. Convert to mW before converting. */
+	if (class == PSC_POWER)
+		val = DIV_ROUND_CLOSEST(val, 1000L);
+
+	/*
+	 * For simplicity, convert fan data to milli-units
+	 * before calculating the exponent.
+	 */
+	if (class == PSC_FAN)
+		val = val * 1000;
+
+	/* Reduce large mantissa until it fits into 10 bit */
+	while (val >= MAX_MANTISSA && exponent < 15) {
+		exponent++;
+		val >>= 1;
+	}
+	/* Increase small mantissa to improve precision */
+	while (val < MIN_MANTISSA && exponent > -15) {
+		exponent--;
+		val <<= 1;
+	}
+
+	/* Convert mantissa from milli-units to units */
+	mantissa = DIV_ROUND_CLOSEST(val, 1000);
+
+	/* Ensure that resulting number is within range */
+	if (mantissa > 0x3ff)
+		mantissa = 0x3ff;
+
+	/* restore sign */
+	if (negative)
+		mantissa = -mantissa;
+
+	/* Convert to 5 bit exponent, 11 bit mantissa */
+	return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
+}
+
+static u16 pmbus_data2reg_direct(struct pmbus_data *data,
+				 enum pmbus_sensor_classes class, long val)
+{
+	long m, b, R;
+
+	m = data->info->m[class];
+	b = data->info->b[class];
+	R = data->info->R[class];
+
+	/* Power is in uW. Adjust R and b. */
+	if (class == PSC_POWER) {
+		R -= 3;
+		b *= 1000;
+	}
+
+	/* Calculate Y = (m * X + b) * 10^R */
+	if (class != PSC_FAN) {
+		R -= 3;		/* Adjust R and b for data in milli-units */
+		b *= 1000;
+	}
+	val = val * m + b;
+
+	while (R > 0) {
+		val *= 10;
+		R--;
+	}
+	while (R < 0) {
+		val = DIV_ROUND_CLOSEST(val, 10);
+		R++;
+	}
+
+	return val;
+}
+
+static u16 pmbus_data2reg(struct pmbus_data *data,
+			  enum pmbus_sensor_classes class, long val)
+{
+	u16 regval;
+
+	if (data->info->direct[class])
+		regval = pmbus_data2reg_direct(data, class, val);
+	else
+		regval = pmbus_data2reg_linear(data, class, val);
+
+	return regval;
+}
+
+/*
+ * Return boolean calculated from converted data.
+ * <index> defines a status register index and mask, and optionally
+ * two sensor indexes.
+ * The upper half-word references the two sensors,
+ * two sensor indices.
+ * The upper half-word references the two optional sensors,
+ * the lower half word references status register and mask.
+ * The function returns true if (status[reg] & mask) is true and,
+ * if specified, if v1 >= v2.
+ * To determine if an object exceeds upper limits, specify <v, limit>.
+ * To determine if an object exceeds lower limits, specify <limit, v>.
+ *
+ * For booleans created with pmbus_add_boolean_reg(), only the lower 16 bits of
+ * index are set. s1 and s2 (the sensor index values) are zero in this case.
+ * The function returns true if (status[reg] & mask) is true.
+ *
+ * If the boolean was created with pmbus_add_boolean_cmp(), a comparison against
+ * a specified limit has to be performed to determine the boolean result.
+ * In this case, the function returns true if v1 >= v2 (where v1 and v2 are
+ * sensor values referenced by sensor indices s1 and s2).
+ *
+ * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>.
+ * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>.
+ *
+ * If a negative value is stored in any of the referenced registers, this value
+ * reflects an error code which will be returned.
+ */
+static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
+{
+	u8 s1 = (index >> 24) & 0xff;
+	u8 s2 = (index >> 16) & 0xff;
+	u8 reg = (index >> 8) & 0xff;
+	u8 mask = index & 0xff;
+	int status;
+	u8 regval;
+
+	status = data->status[reg];
+	if (status < 0)
+		return status;
+
+	regval = status & mask;
+	if (!s1 && !s2)
+		*val = !!regval;
+	else {
+		int v1, v2;
+		struct pmbus_sensor *sensor1, *sensor2;
+
+		sensor1 = &data->sensors[s1];
+		if (sensor1->data < 0)
+			return sensor1->data;
+		sensor2 = &data->sensors[s2];
+		if (sensor2->data < 0)
+			return sensor2->data;
+
+		v1 = pmbus_reg2data(data, sensor1);
+		v2 = pmbus_reg2data(data, sensor2);
+		*val = !!(regval && v1 >= v2);
+	}
+	return 0;
+}
+
+static ssize_t pmbus_show_boolean(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pmbus_data *data = pmbus_update_device(dev);
+	int val;
+	int err;
+
+	err = pmbus_get_boolean(data, attr->index, &val);
+	if (err)
+		return err;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t pmbus_show_sensor(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pmbus_data *data = pmbus_update_device(dev);
+	struct pmbus_sensor *sensor;
+
+	sensor = &data->sensors[attr->index];
+	if (sensor->data < 0)
+		return sensor->data;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", pmbus_reg2data(data, sensor));
+}
+
+static ssize_t pmbus_set_sensor(struct device *dev,
+				struct device_attribute *devattr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	struct pmbus_sensor *sensor = &data->sensors[attr->index];
+	ssize_t rv = count;
+	long val = 0;
+	int ret;
+	u16 regval;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	regval = pmbus_data2reg(data, sensor->class, val);
+	ret = pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
+	if (ret < 0)
+		rv = ret;
+	else
+		data->sensors[attr->index].data = regval;
+	mutex_unlock(&data->update_lock);
+	return rv;
+}
+
+static ssize_t pmbus_show_label(struct device *dev,
+				struct device_attribute *da, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			data->labels[attr->index].label);
+}
+
+#define PMBUS_ADD_ATTR(data, _name, _idx, _mode, _type, _show, _set)	\
+do {									\
+	struct sensor_device_attribute *a				\
+	    = &data->_type##s[data->num_##_type##s].attribute;		\
+	BUG_ON(data->num_attributes >= data->max_attributes);		\
+	a->dev_attr.attr.name = _name;					\
+	a->dev_attr.attr.mode = _mode;					\
+	a->dev_attr.show = _show;					\
+	a->dev_attr.store = _set;					\
+	a->index = _idx;						\
+	data->attributes[data->num_attributes] = &a->dev_attr.attr;	\
+	data->num_attributes++;						\
+} while (0)
+
+#define PMBUS_ADD_GET_ATTR(data, _name, _type, _idx)			\
+	PMBUS_ADD_ATTR(data, _name, _idx, S_IRUGO, _type,		\
+		       pmbus_show_##_type,  NULL)
+
+#define PMBUS_ADD_SET_ATTR(data, _name, _type, _idx)			\
+	PMBUS_ADD_ATTR(data, _name, _idx, S_IWUSR | S_IRUGO, _type,	\
+		       pmbus_show_##_type, pmbus_set_##_type)
+
+static void pmbus_add_boolean(struct pmbus_data *data,
+			      const char *name, const char *type, int seq,
+			      int idx)
+{
+	struct pmbus_boolean *boolean;
+
+	BUG_ON(data->num_booleans >= data->max_booleans);
+
+	boolean = &data->booleans[data->num_booleans];
+
+	snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s",
+		 name, seq, type);
+	PMBUS_ADD_GET_ATTR(data, boolean->name, boolean, idx);
+	data->num_booleans++;
+}
+
+static void pmbus_add_boolean_reg(struct pmbus_data *data,
+				  const char *name, const char *type,
+				  int seq, int reg, int bit)
+{
+	pmbus_add_boolean(data, name, type, seq, (reg << 8) | bit);
+}
+
+static void pmbus_add_boolean_cmp(struct pmbus_data *data,
+				  const char *name, const char *type,
+				  int seq, int i1, int i2, int reg, int mask)
+{
+	pmbus_add_boolean(data, name, type, seq,
+			  (i1 << 24) | (i2 << 16) | (reg << 8) | mask);
+}
+
+static void pmbus_add_sensor(struct pmbus_data *data,
+			     const char *name, const char *type, int seq,
+			     int page, int reg, enum pmbus_sensor_classes class,
+			     bool update)
+{
+	struct pmbus_sensor *sensor;
+
+	BUG_ON(data->num_sensors >= data->max_sensors);
+
+	sensor = &data->sensors[data->num_sensors];
+	snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s",
+		 name, seq, type);
+	sensor->page = page;
+	sensor->reg = reg;
+	sensor->class = class;
+	sensor->update = update;
+	if (update)
+		PMBUS_ADD_GET_ATTR(data, sensor->name, sensor,
+				   data->num_sensors);
+	else
+		PMBUS_ADD_SET_ATTR(data, sensor->name, sensor,
+				   data->num_sensors);
+	data->num_sensors++;
+}
+
+static void pmbus_add_label(struct pmbus_data *data,
+			    const char *name, int seq,
+			    const char *lstring, int index)
+{
+	struct pmbus_label *label;
+
+	BUG_ON(data->num_labels >= data->max_labels);
+
+	label = &data->labels[data->num_labels];
+	snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq);
+	if (!index)
+		strncpy(label->label, lstring, sizeof(label->label) - 1);
+	else
+		snprintf(label->label, sizeof(label->label), "%s%d", lstring,
+			 index);
+
+	PMBUS_ADD_GET_ATTR(data, label->name, label, data->num_labels);
+	data->num_labels++;
+}
+
+static const int pmbus_temp_registers[] = {
+	PMBUS_READ_TEMPERATURE_1,
+	PMBUS_READ_TEMPERATURE_2,
+	PMBUS_READ_TEMPERATURE_3
+};
+
+static const int pmbus_temp_flags[] = {
+	PMBUS_HAVE_TEMP,
+	PMBUS_HAVE_TEMP2,
+	PMBUS_HAVE_TEMP3
+};
+
+static const int pmbus_fan_registers[] = {
+	PMBUS_READ_FAN_SPEED_1,
+	PMBUS_READ_FAN_SPEED_2,
+	PMBUS_READ_FAN_SPEED_3,
+	PMBUS_READ_FAN_SPEED_4
+};
+
+static const int pmbus_fan_config_registers[] = {
+	PMBUS_FAN_CONFIG_12,
+	PMBUS_FAN_CONFIG_12,
+	PMBUS_FAN_CONFIG_34,
+	PMBUS_FAN_CONFIG_34
+};
+
+static const int pmbus_fan_status_registers[] = {
+	PMBUS_STATUS_FAN_12,
+	PMBUS_STATUS_FAN_12,
+	PMBUS_STATUS_FAN_34,
+	PMBUS_STATUS_FAN_34
+};
+
+static const u32 pmbus_fan_flags[] = {
+	PMBUS_HAVE_FAN12,
+	PMBUS_HAVE_FAN12,
+	PMBUS_HAVE_FAN34,
+	PMBUS_HAVE_FAN34
+};
+
+static const u32 pmbus_fan_status_flags[] = {
+	PMBUS_HAVE_STATUS_FAN12,
+	PMBUS_HAVE_STATUS_FAN12,
+	PMBUS_HAVE_STATUS_FAN34,
+	PMBUS_HAVE_STATUS_FAN34
+};
+
+/*
+ * Determine maximum number of sensors, booleans, and labels.
+ * To keep things simple, only make a rough high estimate.
+ */
+static void pmbus_find_max_attr(struct i2c_client *client,
+				struct pmbus_data *data)
+{
+	const struct pmbus_driver_info *info = data->info;
+	int page, max_sensors, max_booleans, max_labels;
+
+	max_sensors = PMBUS_MAX_INPUT_SENSORS;
+	max_booleans = PMBUS_MAX_INPUT_BOOLEANS;
+	max_labels = PMBUS_MAX_INPUT_LABELS;
+
+	for (page = 0; page < info->pages; page++) {
+		if (info->func[page] & PMBUS_HAVE_VOUT) {
+			max_sensors += PMBUS_VOUT_SENSORS_PER_PAGE;
+			max_booleans += PMBUS_VOUT_BOOLEANS_PER_PAGE;
+			max_labels++;
+		}
+		if (info->func[page] & PMBUS_HAVE_IOUT) {
+			max_sensors += PMBUS_IOUT_SENSORS_PER_PAGE;
+			max_booleans += PMBUS_IOUT_BOOLEANS_PER_PAGE;
+			max_labels++;
+		}
+		if (info->func[page] & PMBUS_HAVE_POUT) {
+			max_sensors += PMBUS_POUT_SENSORS_PER_PAGE;
+			max_booleans += PMBUS_POUT_BOOLEANS_PER_PAGE;
+			max_labels++;
+		}
+		if (info->func[page] & PMBUS_HAVE_FAN12) {
+			max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
+			max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
+		}
+		if (info->func[page] & PMBUS_HAVE_FAN34) {
+			max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
+			max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
+		}
+		if (info->func[page] & PMBUS_HAVE_TEMP) {
+			max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
+			max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
+		}
+		if (info->func[page] & PMBUS_HAVE_TEMP2) {
+			max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
+			max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
+		}
+		if (info->func[page] & PMBUS_HAVE_TEMP3) {
+			max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
+			max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
+		}
+	}
+	data->max_sensors = max_sensors;
+	data->max_booleans = max_booleans;
+	data->max_labels = max_labels;
+	data->max_attributes = max_sensors + max_booleans + max_labels;
+}
+
+/*
+ * Search for attributes. Allocate sensors, booleans, and labels as needed.
+ */
+static void pmbus_find_attributes(struct i2c_client *client,
+				  struct pmbus_data *data)
+{
+	const struct pmbus_driver_info *info = data->info;
+	int page, i0, i1, in_index;
+
+	/*
+	 * Input voltage sensors
+	 */
+	in_index = 1;
+	if (info->func[0] & PMBUS_HAVE_VIN) {
+		bool have_alarm = false;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "in", in_index, "vin", 0);
+		pmbus_add_sensor(data, "in", "input", in_index,
+				 0, PMBUS_READ_VIN, PSC_VOLTAGE_IN, true);
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_UV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "min", in_index,
+					 0, PMBUS_VIN_UV_WARN_LIMIT,
+					 PSC_VOLTAGE_IN, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "min_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_UV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_UV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "lcrit", in_index,
+					 0, PMBUS_VIN_UV_FAULT_LIMIT,
+					 PSC_VOLTAGE_IN, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "lcrit_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_UV_FAULT);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_OV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "max", in_index,
+					 0, PMBUS_VIN_OV_WARN_LIMIT,
+					 PSC_VOLTAGE_IN, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "max_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_OV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_OV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "crit", in_index,
+					 0, PMBUS_VIN_OV_FAULT_LIMIT,
+					 PSC_VOLTAGE_IN, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "crit_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_OV_FAULT);
+				have_alarm = true;
+			}
+		}
+		/*
+		 * Add generic alarm attribute only if there are no individual
+		 * attributes.
+		 */
+		if (!have_alarm)
+			pmbus_add_boolean_reg(data, "in", "alarm",
+					      in_index,
+					      PB_STATUS_BASE,
+					      PB_STATUS_VIN_UV);
+		in_index++;
+	}
+	if (info->func[0] & PMBUS_HAVE_VCAP) {
+		pmbus_add_label(data, "in", in_index, "vcap", 0);
+		pmbus_add_sensor(data, "in", "input", in_index, 0,
+				 PMBUS_READ_VCAP, PSC_VOLTAGE_IN, true);
+		in_index++;
+	}
+
+	/*
+	 * Output voltage sensors
+	 */
+	for (page = 0; page < info->pages; page++) {
+		bool have_alarm = false;
+
+		if (!(info->func[page] & PMBUS_HAVE_VOUT))
+			continue;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "in", in_index, "vout", page + 1);
+		pmbus_add_sensor(data, "in", "input", in_index, page,
+				 PMBUS_READ_VOUT, PSC_VOLTAGE_OUT, true);
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_UV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "min", in_index, page,
+					 PMBUS_VOUT_UV_WARN_LIMIT,
+					 PSC_VOLTAGE_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "min_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_UV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_UV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "lcrit", in_index, page,
+					 PMBUS_VOUT_UV_FAULT_LIMIT,
+					 PSC_VOLTAGE_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "lcrit_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_UV_FAULT);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_OV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "max", in_index, page,
+					 PMBUS_VOUT_OV_WARN_LIMIT,
+					 PSC_VOLTAGE_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "max_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_OV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_OV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "crit", in_index, page,
+					 PMBUS_VOUT_OV_FAULT_LIMIT,
+					 PSC_VOLTAGE_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "crit_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_OV_FAULT);
+				have_alarm = true;
+			}
+		}
+		/*
+		 * Add generic alarm attribute only if there are no individual
+		 * attributes.
+		 */
+		if (!have_alarm)
+			pmbus_add_boolean_reg(data, "in", "alarm",
+					      in_index,
+					      PB_STATUS_BASE + page,
+					      PB_STATUS_VOUT_OV);
+		in_index++;
+	}
+
+	/*
+	 * Current sensors
+	 */
+
+	/*
+	 * Input current sensors
+	 */
+	in_index = 1;
+	if (info->func[0] & PMBUS_HAVE_IIN) {
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "curr", in_index, "iin", 0);
+		pmbus_add_sensor(data, "curr", "input", in_index,
+				 0, PMBUS_READ_IIN, PSC_CURRENT_IN, true);
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_IIN_OC_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "max", in_index,
+					 0, PMBUS_IIN_OC_WARN_LIMIT,
+					 PSC_CURRENT_IN, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "curr", "max_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_IIN_OC_WARNING);
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_IIN_OC_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "crit", in_index,
+					 0, PMBUS_IIN_OC_FAULT_LIMIT,
+					 PSC_CURRENT_IN, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
+				pmbus_add_boolean_reg(data, "curr",
+						      "crit_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_IIN_OC_FAULT);
+		}
+		in_index++;
+	}
+
+	/*
+	 * Output current sensors
+	 */
+	for (page = 0; page < info->pages; page++) {
+		bool have_alarm = false;
+
+		if (!(info->func[page] & PMBUS_HAVE_IOUT))
+			continue;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "curr", in_index, "iout", page + 1);
+		pmbus_add_sensor(data, "curr", "input", in_index, page,
+				 PMBUS_READ_IOUT, PSC_CURRENT_OUT, true);
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_IOUT_OC_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "max", in_index, page,
+					 PMBUS_IOUT_OC_WARN_LIMIT,
+					 PSC_CURRENT_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
+				pmbus_add_boolean_reg(data, "curr", "max_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE +
+						      page, PB_IOUT_OC_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_IOUT_UC_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "lcrit", in_index, page,
+					 PMBUS_IOUT_UC_FAULT_LIMIT,
+					 PSC_CURRENT_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
+				pmbus_add_boolean_reg(data, "curr",
+						      "lcrit_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE +
+						      page, PB_IOUT_UC_FAULT);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_IOUT_OC_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "crit", in_index, page,
+					 PMBUS_IOUT_OC_FAULT_LIMIT,
+					 PSC_CURRENT_OUT, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
+				pmbus_add_boolean_reg(data, "curr",
+						      "crit_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE +
+						      page, PB_IOUT_OC_FAULT);
+				have_alarm = true;
+			}
+		}
+		/*
+		 * Add generic alarm attribute only if there are no individual
+		 * attributes.
+		 */
+		if (!have_alarm)
+			pmbus_add_boolean_reg(data, "curr", "alarm",
+					      in_index,
+					      PB_STATUS_BASE + page,
+					      PB_STATUS_IOUT_OC);
+		in_index++;
+	}
+
+	/*
+	 * Power sensors
+	 */
+	/*
+	 * Input Power sensors
+	 */
+	in_index = 1;
+	if (info->func[0] & PMBUS_HAVE_PIN) {
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "power", in_index, "pin", 0);
+		pmbus_add_sensor(data, "power", "input", in_index,
+				 0, PMBUS_READ_PIN, PSC_POWER, true);
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_PIN_OP_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "max", in_index,
+					 0, PMBUS_PIN_OP_WARN_LIMIT, PSC_POWER,
+					 false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
+				pmbus_add_boolean_reg(data, "power",
+						      "alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_PIN_OP_WARNING);
+		}
+		in_index++;
+	}
+
+	/*
+	 * Output Power sensors
+	 */
+	for (page = 0; page < info->pages; page++) {
+		bool need_alarm = false;
+
+		if (!(info->func[page] & PMBUS_HAVE_POUT))
+			continue;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "power", in_index, "pout", page + 1);
+		pmbus_add_sensor(data, "power", "input", in_index, page,
+				 PMBUS_READ_POUT, PSC_POWER, true);
+		/*
+		 * Per hwmon sysfs API, power_cap is to be used to limit output
+		 * power.
+		 * We have two registers related to maximum output power,
+		 * PMBUS_POUT_MAX and PMBUS_POUT_OP_WARN_LIMIT.
+		 * PMBUS_POUT_MAX matches the powerX_cap attribute definition.
+		 * There is no attribute in the API to match
+		 * PMBUS_POUT_OP_WARN_LIMIT. We use powerX_max for now.
+		 */
+		if (pmbus_check_word_register(client, page, PMBUS_POUT_MAX)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "cap", in_index, page,
+					 PMBUS_POUT_MAX, PSC_POWER, false);
+			need_alarm = true;
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_POUT_OP_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "max", in_index, page,
+					 PMBUS_POUT_OP_WARN_LIMIT, PSC_POWER,
+					 false);
+			need_alarm = true;
+		}
+		if (need_alarm && (info->func[page] & PMBUS_HAVE_STATUS_IOUT))
+			pmbus_add_boolean_reg(data, "power", "alarm",
+					      in_index,
+					      PB_STATUS_IOUT_BASE + page,
+					      PB_POUT_OP_WARNING
+					      | PB_POWER_LIMITING);
+
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_POUT_OP_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "crit", in_index, page,
+					 PMBUS_POUT_OP_FAULT_LIMIT, PSC_POWER,
+					 false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT)
+				pmbus_add_boolean_reg(data, "power",
+						      "crit_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE
+						      + page,
+						      PB_POUT_OP_FAULT);
+		}
+		in_index++;
+	}
+
+	/*
+	 * Temperature sensors
+	 */
+	in_index = 1;
+	for (page = 0; page < info->pages; page++) {
+		int t;
+
+		for (t = 0; t < ARRAY_SIZE(pmbus_temp_registers); t++) {
+			bool have_alarm = false;
+
+			/*
+			 * A PMBus chip may support any combination of
+			 * temperature registers on any page. So we can not
+			 * abort after a failure to detect a register, but have
+			 * to continue checking for all registers on all pages.
+			 */
+			if (!(info->func[page] & pmbus_temp_flags[t]))
+				continue;
+
+			if (!pmbus_check_word_register
+			    (client, page, pmbus_temp_registers[t]))
+				continue;
+
+			i0 = data->num_sensors;
+			pmbus_add_sensor(data, "temp", "input", in_index, page,
+					 pmbus_temp_registers[t],
+					 PSC_TEMPERATURE, true);
+
+			/*
+			 * PMBus provides only one status register for TEMP1-3.
+			 * Thus, we can not use the status register to determine
+			 * which of the three sensors actually caused an alarm.
+			 * Always compare current temperature against the limit
+			 * registers to determine alarm conditions for a
+			 * specific sensor.
+			 *
+			 * Since there is only one set of limit registers for
+			 * up to three temperature sensors, we need to update
+			 * all limit registers after the limit was changed for
+			 * one of the sensors. This ensures that correct limits
+			 * are reported for all temperature sensors.
+			 */
+			if (pmbus_check_word_register
+			    (client, page, PMBUS_UT_WARN_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "min", in_index,
+						 page, PMBUS_UT_WARN_LIMIT,
+						 PSC_TEMPERATURE, true);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"min_alarm", in_index, i1, i0,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_UT_WARNING);
+					have_alarm = true;
+				}
+			}
+			if (pmbus_check_word_register(client, page,
+						      PMBUS_UT_FAULT_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "lcrit",
+						 in_index, page,
+						 PMBUS_UT_FAULT_LIMIT,
+						 PSC_TEMPERATURE, true);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"lcrit_alarm", in_index, i1, i0,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_UT_FAULT);
+					have_alarm = true;
+				}
+			}
+			if (pmbus_check_word_register
+			    (client, page, PMBUS_OT_WARN_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "max", in_index,
+						 page, PMBUS_OT_WARN_LIMIT,
+						 PSC_TEMPERATURE, true);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"max_alarm", in_index, i0, i1,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_OT_WARNING);
+					have_alarm = true;
+				}
+			}
+			if (pmbus_check_word_register(client, page,
+						      PMBUS_OT_FAULT_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "crit", in_index,
+						 page, PMBUS_OT_FAULT_LIMIT,
+						 PSC_TEMPERATURE, true);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"crit_alarm", in_index, i0, i1,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_OT_FAULT);
+					have_alarm = true;
+				}
+			}
+			/*
+			 * Last resort - we were not able to create any alarm
+			 * registers. Report alarm for all sensors using the
+			 * status register temperature alarm bit.
+			 */
+			if (!have_alarm)
+				pmbus_add_boolean_reg(data, "temp", "alarm",
+						      in_index,
+						      PB_STATUS_BASE + page,
+						      PB_STATUS_TEMPERATURE);
+			in_index++;
+		}
+	}
+
+	/*
+	 * Fans
+	 */
+	in_index = 1;
+	for (page = 0; page < info->pages; page++) {
+		int f;
+
+		for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) {
+			int regval;
+
+			if (!(info->func[page] & pmbus_fan_flags[f]))
+				break;
+
+			if (!pmbus_check_word_register(client, page,
+						       pmbus_fan_registers[f])
+			    || !pmbus_check_byte_register(client, page,
+						pmbus_fan_config_registers[f]))
+				break;
+
+			/*
+			 * Skip fan if not installed.
+			 * Each fan configuration register covers multiple fans,
+			 * so we have to do some magic.
+			 */
+			regval = pmbus_read_byte_data(client, page,
+				pmbus_fan_config_registers[f]);
+			if (regval < 0 ||
+			    (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4)))))
+				continue;
+
+			i0 = data->num_sensors;
+			pmbus_add_sensor(data, "fan", "input", in_index, page,
+					 pmbus_fan_registers[f], PSC_FAN, true);
+
+			/*
+			 * Each fan status register covers multiple fans,
+			 * so we have to do some magic.
+			 */
+			if ((info->func[page] & pmbus_fan_status_flags[f]) &&
+			    pmbus_check_byte_register(client,
+					page, pmbus_fan_status_registers[f])) {
+				int base;
+
+				if (f > 1)	/* fan 3, 4 */
+					base = PB_STATUS_FAN34_BASE + page;
+				else
+					base = PB_STATUS_FAN_BASE + page;
+				pmbus_add_boolean_reg(data, "fan", "alarm",
+					in_index, base,
+					PB_FAN_FAN1_WARNING >> (f & 1));
+				pmbus_add_boolean_reg(data, "fan", "fault",
+					in_index, base,
+					PB_FAN_FAN1_FAULT >> (f & 1));
+			}
+			in_index++;
+		}
+	}
+}
+
+/*
+ * Identify chip parameters.
+ * This function is called for all chips.
+ */
+static int pmbus_identify_common(struct i2c_client *client,
+				 struct pmbus_data *data)
+{
+	int vout_mode = -1, exponent;
+
+	if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
+		vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+	if (vout_mode >= 0 && vout_mode != 0xff) {
+		/*
+		 * Not all chips support the VOUT_MODE command,
+		 * so a failure to read it is not an error.
+		 */
+		switch (vout_mode >> 5) {
+		case 0:	/* linear mode      */
+			if (data->info->direct[PSC_VOLTAGE_OUT])
+				return -ENODEV;
+
+			exponent = vout_mode & 0x1f;
+			/* and sign-extend it */
+			if (exponent & 0x10)
+				exponent |= ~0x1f;
+			data->exponent = exponent;
+			break;
+		case 2:	/* direct mode      */
+			if (!data->info->direct[PSC_VOLTAGE_OUT])
+				return -ENODEV;
+			break;
+		default:
+			return -ENODEV;
+		}
+	}
+
+	/* Determine maximum number of sensors, booleans, and labels */
+	pmbus_find_max_attr(client, data);
+	pmbus_clear_fault_page(client, 0);
+	return 0;
+}
+
+int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+		   struct pmbus_driver_info *info)
+{
+	const struct pmbus_platform_data *pdata = client->dev.platform_data;
+	struct pmbus_data *data;
+	int ret;
+
+	if (!info) {
+		dev_err(&client->dev, "Missing chip information");
+		return -ENODEV;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
+				     | I2C_FUNC_SMBUS_BYTE_DATA
+				     | I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&client->dev, "No memory to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/*
+	 * Bail out if status register or PMBus revision register
+	 * does not exist.
+	 */
+	if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0
+	    || i2c_smbus_read_byte_data(client, PMBUS_REVISION) < 0) {
+		dev_err(&client->dev,
+			"Status or revision register not found\n");
+		ret = -ENODEV;
+		goto out_data;
+	}
+
+	if (pdata)
+		data->flags = pdata->flags;
+	data->info = info;
+
+	pmbus_clear_faults(client);
+
+	if (info->identify) {
+		ret = (*info->identify)(client, info);
+		if (ret < 0) {
+			dev_err(&client->dev, "Chip identification failed\n");
+			goto out_data;
+		}
+	}
+
+	if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
+		dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
+			info->pages);
+		ret = -EINVAL;
+		goto out_data;
+	}
+	/*
+	 * Bail out if more than one page was configured, but we can not
+	 * select the highest page. This is an indication that the wrong
+	 * chip type was selected. Better bail out now than keep
+	 * returning errors later on.
+	 */
+	if (info->pages > 1 && pmbus_set_page(client, info->pages - 1) < 0) {
+		dev_err(&client->dev, "Failed to select page %d\n",
+			info->pages - 1);
+		ret = -EINVAL;
+		goto out_data;
+	}
+
+	ret = pmbus_identify_common(client, data);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to identify chip capabilities\n");
+		goto out_data;
+	}
+
+	ret = -ENOMEM;
+	data->sensors = kzalloc(sizeof(struct pmbus_sensor) * data->max_sensors,
+				GFP_KERNEL);
+	if (!data->sensors) {
+		dev_err(&client->dev, "No memory to allocate sensor data\n");
+		goto out_data;
+	}
+
+	data->booleans = kzalloc(sizeof(struct pmbus_boolean)
+				 * data->max_booleans, GFP_KERNEL);
+	if (!data->booleans) {
+		dev_err(&client->dev, "No memory to allocate boolean data\n");
+		goto out_sensors;
+	}
+
+	data->labels = kzalloc(sizeof(struct pmbus_label) * data->max_labels,
+			       GFP_KERNEL);
+	if (!data->labels) {
+		dev_err(&client->dev, "No memory to allocate label data\n");
+		goto out_booleans;
+	}
+
+	data->attributes = kzalloc(sizeof(struct attribute *)
+				   * data->max_attributes, GFP_KERNEL);
+	if (!data->attributes) {
+		dev_err(&client->dev, "No memory to allocate attribute data\n");
+		goto out_labels;
+	}
+
+	pmbus_find_attributes(client, data);
+
+	/*
+	 * If there are no attributes, something is wrong.
+	 * Bail out instead of trying to register nothing.
+	 */
+	if (!data->num_attributes) {
+		dev_err(&client->dev, "No attributes found\n");
+		ret = -ENODEV;
+		goto out_attributes;
+	}
+
+	/* Register sysfs hooks */
+	data->group.attrs = data->attributes;
+	ret = sysfs_create_group(&client->dev.kobj, &data->group);
+	if (ret) {
+		dev_err(&client->dev, "Failed to create sysfs entries\n");
+		goto out_attributes;
+	}
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		dev_err(&client->dev, "Failed to register hwmon device\n");
+		goto out_hwmon_device_register;
+	}
+	return 0;
+
+out_hwmon_device_register:
+	sysfs_remove_group(&client->dev.kobj, &data->group);
+out_attributes:
+	kfree(data->attributes);
+out_labels:
+	kfree(data->labels);
+out_booleans:
+	kfree(data->booleans);
+out_sensors:
+	kfree(data->sensors);
+out_data:
+	kfree(data);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pmbus_do_probe);
+
+int pmbus_do_remove(struct i2c_client *client)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &data->group);
+	kfree(data->attributes);
+	kfree(data->labels);
+	kfree(data->booleans);
+	kfree(data->sensors);
+	kfree(data);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pmbus_do_remove);
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c
new file mode 100644
index 0000000..9a51dcc
--- /dev/null
+++ b/drivers/hwmon/sch5627.c
@@ -0,0 +1,858 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>           *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+
+#define DRVNAME "sch5627"
+#define DEVNAME DRVNAME /* We only support one model */
+
+#define SIO_SCH5627_EM_LD	0x0C	/* Embedded Microcontroller LD */
+#define SIO_UNLOCK_KEY		0x55	/* Key to enable Super-I/O */
+#define SIO_LOCK_KEY		0xAA	/* Key to disable Super-I/O */
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x66	/* Logical device address (2 bytes) */
+
+#define SIO_SCH5627_ID		0xC6	/* Chipset ID */
+
+#define REGION_LENGTH		9
+
+#define SCH5627_HWMON_ID		0xa5
+#define SCH5627_COMPANY_ID		0x5c
+#define SCH5627_PRIMARY_ID		0xa0
+
+#define SCH5627_REG_BUILD_CODE		0x39
+#define SCH5627_REG_BUILD_ID		0x3a
+#define SCH5627_REG_HWMON_ID		0x3c
+#define SCH5627_REG_HWMON_REV		0x3d
+#define SCH5627_REG_COMPANY_ID		0x3e
+#define SCH5627_REG_PRIMARY_ID		0x3f
+#define SCH5627_REG_CTRL		0x40
+
+#define SCH5627_NO_TEMPS		8
+#define SCH5627_NO_FANS			4
+#define SCH5627_NO_IN			5
+
+static const u16 SCH5627_REG_TEMP_MSB[SCH5627_NO_TEMPS] = {
+	0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181 };
+static const u16 SCH5627_REG_TEMP_LSN[SCH5627_NO_TEMPS] = {
+	0xE2, 0xE1, 0xE1, 0xE5, 0xE5, 0xE6, 0x182, 0x182 };
+static const u16 SCH5627_REG_TEMP_HIGH_NIBBLE[SCH5627_NO_TEMPS] = {
+	0, 0, 1, 1, 0, 0, 0, 1 };
+static const u16 SCH5627_REG_TEMP_HIGH[SCH5627_NO_TEMPS] = {
+	0x61, 0x57, 0x59, 0x5B, 0x5D, 0x5F, 0x184, 0x186 };
+static const u16 SCH5627_REG_TEMP_ABS[SCH5627_NO_TEMPS] = {
+	0x9B, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x1A8, 0x1A9 };
+
+static const u16 SCH5627_REG_FAN[SCH5627_NO_FANS] = {
+	0x2C, 0x2E, 0x30, 0x32 };
+static const u16 SCH5627_REG_FAN_MIN[SCH5627_NO_FANS] = {
+	0x62, 0x64, 0x66, 0x68 };
+
+static const u16 SCH5627_REG_IN_MSB[SCH5627_NO_IN] = {
+	0x22, 0x23, 0x24, 0x25, 0x189 };
+static const u16 SCH5627_REG_IN_LSN[SCH5627_NO_IN] = {
+	0xE4, 0xE4, 0xE3, 0xE3, 0x18A };
+static const u16 SCH5627_REG_IN_HIGH_NIBBLE[SCH5627_NO_IN] = {
+	1, 0, 1, 0, 1 };
+static const u16 SCH5627_REG_IN_FACTOR[SCH5627_NO_IN] = {
+	10745, 3660, 9765, 10745, 3660 };
+static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = {
+	"VCC", "VTT", "VBAT", "VTR", "V_IN" };
+
+struct sch5627_data {
+	unsigned short addr;
+	struct device *hwmon_dev;
+	u8 temp_max[SCH5627_NO_TEMPS];
+	u8 temp_crit[SCH5627_NO_TEMPS];
+	u16 fan_min[SCH5627_NO_FANS];
+
+	struct mutex update_lock;
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	u16 temp[SCH5627_NO_TEMPS];
+	u16 fan[SCH5627_NO_FANS];
+	u16 in[SCH5627_NO_IN];
+};
+
+static struct platform_device *sch5627_pdev;
+
+/* Super I/O functions */
+static inline int superio_inb(int base, int reg)
+{
+	outb(reg, base);
+	return inb(base + 1);
+}
+
+static inline int superio_enter(int base)
+{
+	/* Don't step on other drivers' I/O space by accident */
+	if (!request_muxed_region(base, 2, DRVNAME)) {
+		pr_err("I/O address 0x%04x already in use\n", base);
+		return -EBUSY;
+	}
+
+	outb(SIO_UNLOCK_KEY, base);
+
+	return 0;
+}
+
+static inline void superio_select(int base, int ld)
+{
+	outb(SIO_REG_LDSEL, base);
+	outb(ld, base + 1);
+}
+
+static inline void superio_exit(int base)
+{
+	outb(SIO_LOCK_KEY, base);
+	release_region(base, 2);
+}
+
+static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
+{
+	u8 val;
+	int i;
+	/*
+	 * According to SMSC for the commands we use the maximum time for
+	 * the EM to respond is 15 ms, but testing shows in practice it
+	 * responds within 15-32 reads, so we first busy poll, and if
+	 * that fails sleep a bit and try again until we are way past
+	 * the 15 ms maximum response time.
+	 */
+	const int max_busy_polls = 64;
+	const int max_lazy_polls = 32;
+
+	/* (Optional) Write-Clear the EC to Host Mailbox Register */
+	val = inb(data->addr + 1);
+	outb(val, data->addr + 1);
+
+	/* Set Mailbox Address Pointer to first location in Region 1 */
+	outb(0x00, data->addr + 2);
+	outb(0x80, data->addr + 3);
+
+	/* Write Request Packet Header */
+	outb(0x02, data->addr + 4); /* Access Type: VREG read */
+	outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
+	outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
+
+	/* Write Address field */
+	outb(reg & 0xff, data->addr + 6);
+	outb(reg >> 8, data->addr + 7);
+
+	/* Execute the Random Access Command */
+	outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
+
+	/* EM Interface Polling "Algorithm" */
+	for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
+		if (i >= max_busy_polls)
+			msleep(1);
+		/* Read Interrupt source Register */
+		val = inb(data->addr + 8);
+		/* Write Clear the interrupt source bits */
+		if (val)
+			outb(val, data->addr + 8);
+		/* Command Completed ? */
+		if (val & 0x01)
+			break;
+	}
+	if (i == max_busy_polls + max_lazy_polls) {
+		pr_err("Max retries exceeded reading virtual "
+		       "register 0x%04hx (%d)\n", reg, 1);
+		return -EIO;
+	}
+
+	/*
+	 * According to SMSC we may need to retry this, but sofar I've always
+	 * seen this succeed in 1 try.
+	 */
+	for (i = 0; i < max_busy_polls; i++) {
+		/* Read EC-to-Host Register */
+		val = inb(data->addr + 1);
+		/* Command Completed ? */
+		if (val == 0x01)
+			break;
+
+		if (i == 0)
+			pr_warn("EC reports: 0x%02x reading virtual register "
+				"0x%04hx\n", (unsigned int)val, reg);
+	}
+	if (i == max_busy_polls) {
+		pr_err("Max retries exceeded reading virtual "
+		       "register 0x%04hx (%d)\n", reg, 2);
+		return -EIO;
+	}
+
+	/*
+	 * According to the SMSC app note we should now do:
+	 *
+	 * Set Mailbox Address Pointer to first location in Region 1 *
+	 * outb(0x00, data->addr + 2);
+	 * outb(0x80, data->addr + 3);
+	 *
+	 * But if we do that things don't work, so let's not.
+	 */
+
+	/* Read Data from Mailbox */
+	return inb(data->addr + 4);
+}
+
+static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
+{
+	int lsb, msb;
+
+	/* Read LSB first, this will cause the matching MSB to be latched */
+	lsb = sch5627_read_virtual_reg(data, reg);
+	if (lsb < 0)
+		return lsb;
+
+	msb = sch5627_read_virtual_reg(data, reg + 1);
+	if (msb < 0)
+		return msb;
+
+	return lsb | (msb << 8);
+}
+
+static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
+				      u16 lsn_reg, int high_nibble)
+{
+	int msb, lsn;
+
+	/* Read MSB first, this will cause the matching LSN to be latched */
+	msb = sch5627_read_virtual_reg(data, msb_reg);
+	if (msb < 0)
+		return msb;
+
+	lsn = sch5627_read_virtual_reg(data, lsn_reg);
+	if (lsn < 0)
+		return lsn;
+
+	if (high_nibble)
+		return (msb << 4) | (lsn >> 4);
+	else
+		return (msb << 4) | (lsn & 0x0f);
+}
+
+static struct sch5627_data *sch5627_update_device(struct device *dev)
+{
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	struct sch5627_data *ret = data;
+	int i, val;
+
+	mutex_lock(&data->update_lock);
+
+	/* Cache the values for 1 second */
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		for (i = 0; i < SCH5627_NO_TEMPS; i++) {
+			val = sch5627_read_virtual_reg12(data,
+				SCH5627_REG_TEMP_MSB[i],
+				SCH5627_REG_TEMP_LSN[i],
+				SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
+			if (unlikely(val < 0)) {
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->temp[i] = val;
+		}
+
+		for (i = 0; i < SCH5627_NO_FANS; i++) {
+			val = sch5627_read_virtual_reg16(data,
+							 SCH5627_REG_FAN[i]);
+			if (unlikely(val < 0)) {
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->fan[i] = val;
+		}
+
+		for (i = 0; i < SCH5627_NO_IN; i++) {
+			val = sch5627_read_virtual_reg12(data,
+				SCH5627_REG_IN_MSB[i],
+				SCH5627_REG_IN_LSN[i],
+				SCH5627_REG_IN_HIGH_NIBBLE[i]);
+			if (unlikely(val < 0)) {
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->in[i] = val;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static int __devinit sch5627_read_limits(struct sch5627_data *data)
+{
+	int i, val;
+
+	for (i = 0; i < SCH5627_NO_TEMPS; i++) {
+		/*
+		 * Note what SMSC calls ABS, is what lm_sensors calls max
+		 * (aka high), and HIGH is what lm_sensors calls crit.
+		 */
+		val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]);
+		if (val < 0)
+			return val;
+		data->temp_max[i] = val;
+
+		val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]);
+		if (val < 0)
+			return val;
+		data->temp_crit[i] = val;
+	}
+	for (i = 0; i < SCH5627_NO_FANS; i++) {
+		val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]);
+		if (val < 0)
+			return val;
+		data->fan_min[i] = val;
+	}
+
+	return 0;
+}
+
+static int reg_to_temp(u16 reg)
+{
+	return (reg * 625) / 10 - 64000;
+}
+
+static int reg_to_temp_limit(u8 reg)
+{
+	return (reg - 64) * 1000;
+}
+
+static int reg_to_rpm(u16 reg)
+{
+	if (reg == 0)
+		return -EIO;
+	if (reg == 0xffff)
+		return 0;
+
+	return 5400540 / reg;
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+	char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = reg_to_temp(data->temp[attr->index]);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_fault(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0);
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	int val;
+
+	val = reg_to_temp_limit(data->temp_max[attr->index]);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	int val;
+
+	val = reg_to_temp_limit(data->temp_crit[attr->index]);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = reg_to_rpm(data->fan[attr->index]);
+	if (val < 0)
+		return val;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			data->fan[attr->index] == 0xffff);
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	int val = reg_to_rpm(data->fan_min[attr->index]);
+	if (val < 0)
+		return val;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = DIV_ROUND_CLOSEST(
+		data->in[attr->index] * SCH5627_REG_IN_FACTOR[attr->index],
+		10000);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in_label(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			SCH5627_IN_LABELS[attr->index]);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+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(temp6_input, S_IRUGO, show_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3);
+
+static struct attribute *sch5627_attributes[] = {
+	&dev_attr_name.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp5_input.dev_attr.attr,
+	&sensor_dev_attr_temp6_input.dev_attr.attr,
+	&sensor_dev_attr_temp7_input.dev_attr.attr,
+	&sensor_dev_attr_temp8_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.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_temp6_fault.dev_attr.attr,
+	&sensor_dev_attr_temp7_fault.dev_attr.attr,
+	&sensor_dev_attr_temp8_fault.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_temp6_max.dev_attr.attr,
+	&sensor_dev_attr_temp7_max.dev_attr.attr,
+	&sensor_dev_attr_temp8_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit.dev_attr.attr,
+	&sensor_dev_attr_temp5_crit.dev_attr.attr,
+	&sensor_dev_attr_temp6_crit.dev_attr.attr,
+	&sensor_dev_attr_temp7_crit.dev_attr.attr,
+	&sensor_dev_attr_temp8_crit.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
+	&sensor_dev_attr_fan2_fault.dev_attr.attr,
+	&sensor_dev_attr_fan3_fault.dev_attr.attr,
+	&sensor_dev_attr_fan4_fault.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan4_min.dev_attr.attr,
+
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in0_label.dev_attr.attr,
+	&sensor_dev_attr_in1_label.dev_attr.attr,
+	&sensor_dev_attr_in2_label.dev_attr.attr,
+	&sensor_dev_attr_in3_label.dev_attr.attr,
+	/* No in4_label as in4 is a generic input pin */
+
+	NULL
+};
+
+static const struct attribute_group sch5627_group = {
+	.attrs = sch5627_attributes,
+};
+
+static int sch5627_remove(struct platform_device *pdev)
+{
+	struct sch5627_data *data = platform_get_drvdata(pdev);
+
+	if (data->hwmon_dev)
+		hwmon_device_unregister(data->hwmon_dev);
+
+	sysfs_remove_group(&pdev->dev.kobj, &sch5627_group);
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+
+	return 0;
+}
+
+static int __devinit sch5627_probe(struct platform_device *pdev)
+{
+	struct sch5627_data *data;
+	int err, build_code, build_id, hwmon_rev, val;
+
+	data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+	mutex_init(&data->update_lock);
+	platform_set_drvdata(pdev, data);
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (val != SCH5627_HWMON_ID) {
+		pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "hwmon",
+		       val, SCH5627_HWMON_ID);
+		err = -ENODEV;
+		goto error;
+	}
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (val != SCH5627_COMPANY_ID) {
+		pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "company",
+		       val, SCH5627_COMPANY_ID);
+		err = -ENODEV;
+		goto error;
+	}
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (val != SCH5627_PRIMARY_ID) {
+		pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "primary",
+		       val, SCH5627_PRIMARY_ID);
+		err = -ENODEV;
+		goto error;
+	}
+
+	build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE);
+	if (build_code < 0) {
+		err = build_code;
+		goto error;
+	}
+
+	build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID);
+	if (build_id < 0) {
+		err = build_id;
+		goto error;
+	}
+
+	hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV);
+	if (hwmon_rev < 0) {
+		err = hwmon_rev;
+		goto error;
+	}
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (!(val & 0x01)) {
+		pr_err("hardware monitoring not enabled\n");
+		err = -ENODEV;
+		goto error;
+	}
+
+	/*
+	 * Read limits, we do this only once as reading a register on
+	 * the sch5627 is quite expensive (and they don't change).
+	 */
+	err = sch5627_read_limits(data);
+	if (err)
+		goto error;
+
+	pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
+		build_code, build_id, hwmon_rev);
+
+	/* Register sysfs interface files */
+	err = sysfs_create_group(&pdev->dev.kobj, &sch5627_group);
+	if (err)
+		goto error;
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		goto error;
+	}
+
+	return 0;
+
+error:
+	sch5627_remove(pdev);
+	return err;
+}
+
+static int __init sch5627_find(int sioaddr, unsigned short *address)
+{
+	u8 devid;
+	int err = superio_enter(sioaddr);
+	if (err)
+		return err;
+
+	devid = superio_inb(sioaddr, SIO_REG_DEVID);
+	if (devid != SIO_SCH5627_ID) {
+		pr_debug("Unsupported device id: 0x%02x\n",
+			 (unsigned int)devid);
+		err = -ENODEV;
+		goto exit;
+	}
+
+	superio_select(sioaddr, SIO_SCH5627_EM_LD);
+
+	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+		pr_warn("Device not activated\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/*
+	 * Warning the order of the low / high byte is the other way around
+	 * as on most other superio devices!!
+	 */
+	*address = superio_inb(sioaddr, SIO_REG_ADDR) |
+		   superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
+	if (*address == 0) {
+		pr_warn("Base address not set\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
+exit:
+	superio_exit(sioaddr);
+	return err;
+}
+
+static int __init sch5627_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + REGION_LENGTH - 1,
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	sch5627_pdev = platform_device_alloc(DRVNAME, address);
+	if (!sch5627_pdev)
+		return -ENOMEM;
+
+	res.name = sch5627_pdev->name;
+	err = acpi_check_resource_conflict(&res);
+	if (err)
+		goto exit_device_put;
+
+	err = platform_device_add_resources(sch5627_pdev, &res, 1);
+	if (err) {
+		pr_err("Device resource addition failed\n");
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(sch5627_pdev);
+	if (err) {
+		pr_err("Device addition failed\n");
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(sch5627_pdev);
+
+	return err;
+}
+
+static struct platform_driver sch5627_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= sch5627_probe,
+	.remove		= sch5627_remove,
+};
+
+static int __init sch5627_init(void)
+{
+	int err = -ENODEV;
+	unsigned short address;
+
+	if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
+		goto exit;
+
+	err = platform_driver_register(&sch5627_driver);
+	if (err)
+		goto exit;
+
+	err = sch5627_device_add(address);
+	if (err)
+		goto exit_driver;
+
+	return 0;
+
+exit_driver:
+	platform_driver_unregister(&sch5627_driver);
+exit:
+	return err;
+}
+
+static void __exit sch5627_exit(void)
+{
+	platform_device_unregister(sch5627_pdev);
+	platform_driver_unregister(&sch5627_driver);
+}
+
+MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
+MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)");
+MODULE_LICENSE("GPL");
+
+module_init(sch5627_init);
+module_exit(sch5627_exit);
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index a610e78..1a9c32d 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -333,11 +333,11 @@ static inline int sht15_calc_humid(struct sht15_data *data)
 
 	const int c1 = -4;
 	const int c2 = 40500; /* x 10 ^ -6 */
-	const int c3 = -2800; /* x10 ^ -9 */
+	const int c3 = -28; /* x 10 ^ -7 */
 
 	RHlinear = c1*1000
 		+ c2 * data->val_humid/1000
-		+ (data->val_humid * data->val_humid * c3)/1000000;
+		+ (data->val_humid * data->val_humid * c3) / 10000;
 	return (temp - 25000) * (10000 + 80 * data->val_humid)
 		/ 1000000 + RHlinear;
 }
@@ -610,7 +610,7 @@ static int __devexit sht15_remove(struct platform_device *pdev)
 	struct sht15_data *data = platform_get_drvdata(pdev);
 
 	/* Make sure any reads from the device are done and
-	 * prevent new ones beginnning */
+	 * prevent new ones from beginning */
 	mutex_lock(&data->read_lock);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c
index d863e13..1f36c63 100644
--- a/drivers/hwmon/ultra45_env.c
+++ b/drivers/hwmon/ultra45_env.c
@@ -234,8 +234,7 @@ static const struct attribute_group env_group = {
 	.attrs = env_attributes,
 };
 
-static int __devinit env_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit env_probe(struct platform_device *op)
 {
 	struct env *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -299,7 +298,7 @@ static const struct of_device_id env_match[] = {
 };
 MODULE_DEVICE_TABLE(of, env_match);
 
-static struct of_platform_driver env_driver = {
+static struct platform_driver env_driver = {
 	.driver = {
 		.name = "ultra45_env",
 		.owner = THIS_MODULE,
@@ -311,12 +310,12 @@ static struct of_platform_driver env_driver = {
 
 static int __init env_init(void)
 {
-	return of_register_platform_driver(&env_driver);
+	return platform_driver_register(&env_driver);
 }
 
 static void __exit env_exit(void)
 {
-	of_unregister_platform_driver(&env_driver);
+	platform_driver_unregister(&env_driver);
 }
 
 module_init(env_init);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 073eabe..f2b377c 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1,11 +1,12 @@
 /*
     w83627ehf - Driver for the hardware monitoring functionality of
-                the Winbond W83627EHF Super-I/O chip
+		the Winbond W83627EHF Super-I/O chip
     Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2006  Yuan Mu (Winbond),
-                        Rudolf Marek <r.marek@assembler.cz>
-                        David Hubbard <david.c.hubbard@gmail.com>
+			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
@@ -35,11 +36,13 @@
 
     Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
     w83627ehf   10      5       4       3      0x8850 0x88    0x5ca3
-                                               0x8860 0xa1
+					       0x8860 0xa1
     w83627dhg    9      5       4       3      0xa020 0xc1    0x5ca3
     w83627dhg-p  9      5       4       3      0xb070 0xc1    0x5ca3
     w83667hg     9      5       3       3      0xa510 0xc1    0x5ca3
-    w83667hg-b   9      5       3       3      0xb350 0xc1    0x5ca3
+    w83667hg-b   9      5       3       4      0xb350 0xc1    0x5ca3
+    nct6775f     9      4       3       9      0xb470 0xc1    0x5ca3
+    nct6776f     9      5       3       9      0xC330 0xc1    0x5ca3
 */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -58,21 +61,28 @@
 #include <linux/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b };
+enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b, nct6775,
+	nct6776 };
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
-static const char * w83627ehf_device_names[] = {
+static const char * const w83627ehf_device_names[] = {
 	"w83627ehf",
 	"w83627dhg",
 	"w83627dhg",
 	"w83667hg",
 	"w83667hg",
+	"nct6775",
+	"nct6776",
 };
 
 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 "w83627ehf"
 
 /*
@@ -80,7 +90,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
  */
 
 #define W83627EHF_LD_HWM	0x0b
-#define W83667HG_LD_VID 	0x0d
+#define W83667HG_LD_VID		0x0d
 
 #define SIO_REG_LDSEL		0x07	/* Logical device select */
 #define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
@@ -94,8 +104,10 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
 #define SIO_W83627EHG_ID	0x8860
 #define SIO_W83627DHG_ID	0xa020
 #define SIO_W83627DHG_P_ID	0xb070
-#define SIO_W83667HG_ID 	0xa510
+#define SIO_W83667HG_ID		0xa510
 #define SIO_W83667HG_B_ID	0xb350
+#define SIO_NCT6775_ID		0xb470
+#define SIO_NCT6776_ID		0xc330
 #define SIO_ID_MASK		0xFFF0
 
 static inline void
@@ -138,7 +150,7 @@ superio_exit(int ioreg)
  * ISA constants
  */
 
-#define IOREGION_ALIGNMENT	~7
+#define IOREGION_ALIGNMENT	(~7)
 #define IOREGION_OFFSET		5
 #define IOREGION_LENGTH		2
 #define ADDR_REG_OFFSET		0
@@ -164,13 +176,10 @@ static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
 #define W83627EHF_REG_IN(nr)		((nr < 7) ? (0x20 + (nr)) : \
 					 (0x550 + (nr) - 7))
 
-#define W83627EHF_REG_TEMP1		0x27
-#define W83627EHF_REG_TEMP1_HYST	0x3a
-#define W83627EHF_REG_TEMP1_OVER	0x39
-static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
-static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
-static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
-static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
+static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250, 0x7e };
+static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253, 0 };
+static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255, 0 };
+static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 };
 
 /* Fan clock dividers are spread over the following five registers */
 #define W83627EHF_REG_FANDIV1		0x47
@@ -179,6 +188,11 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
 #define W83627EHF_REG_DIODE		0x59
 #define W83627EHF_REG_SMI_OVT		0x4C
 
+/* NCT6775F has its own fan divider registers */
+#define NCT6775_REG_FANDIV1		0x506
+#define NCT6775_REG_FANDIV2		0x507
+#define NCT6775_REG_FAN_DEBOUNCE	0xf0
+
 #define W83627EHF_REG_ALARM1		0x459
 #define W83627EHF_REG_ALARM2		0x45A
 #define W83627EHF_REG_ALARM3		0x45B
@@ -199,22 +213,123 @@ static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 };
 static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
 
 /* FAN Duty Cycle, be used to control */
-static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
-static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
+static const u16 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
+static const u16 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
 static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
 
 /* Advanced Fan control, some values are common for all fans */
-static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
-static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
-static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
+static const u16 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
+static const u16 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
+static const u16 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
 
-static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[]
+static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[]
 						= { 0xff, 0x67, 0xff, 0x69 };
-static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
+static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
 						= { 0xff, 0x68, 0xff, 0x6a };
 
-static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
-static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c };
+static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
+static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[]
+						= { 0x68, 0x6a, 0x6c };
+
+static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 };
+static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 };
+static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 };
+static const u16 NCT6775_REG_FAN_START_OUTPUT[] = { 0x106, 0x206, 0x306 };
+static const u16 NCT6775_REG_FAN_STOP_TIME[] = { 0x107, 0x207, 0x307 };
+static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309 };
+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[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
+static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642};
+
+static const u16 NCT6775_REG_TEMP[]
+	= { 0x27, 0x150, 0x250, 0x73, 0x75, 0x77, 0x62b, 0x62c, 0x62d };
+static const u16 NCT6775_REG_TEMP_CONFIG[]
+	= { 0, 0x152, 0x252, 0, 0, 0, 0x628, 0x629, 0x62A };
+static const u16 NCT6775_REG_TEMP_HYST[]
+	= { 0x3a, 0x153, 0x253, 0, 0, 0, 0x673, 0x678, 0x67D };
+static const u16 NCT6775_REG_TEMP_OVER[]
+	= { 0x39, 0x155, 0x255, 0, 0, 0, 0x672, 0x677, 0x67C };
+static const u16 NCT6775_REG_TEMP_SOURCE[]
+	= { 0x621, 0x622, 0x623, 0x100, 0x200, 0x300, 0x624, 0x625, 0x626 };
+
+static const char *const w83667hg_b_temp_label[] = {
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"AMDTSI",
+	"PECI Agent 1",
+	"PECI Agent 2",
+	"PECI Agent 3",
+	"PECI Agent 4"
+};
+
+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 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"
+};
+
+#define NUM_REG_TEMP	ARRAY_SIZE(NCT6775_REG_TEMP)
+
+static inline int is_word_sized(u16 reg)
+{
+	return ((((reg & 0xff00) == 0x100
+	      || (reg & 0xff00) == 0x200)
+	     && ((reg & 0x00ff) == 0x50
+	      || (reg & 0x00ff) == 0x53
+	      || (reg & 0x00ff) == 0x55))
+	     || (reg & 0xfff0) == 0x630
+	     || reg == 0x640 || reg == 0x642
+	     || ((reg & 0xfff0) == 0x650
+		 && (reg & 0x000f) >= 0x06)
+	     || reg == 0x73 || reg == 0x75 || reg == 0x77
+		);
+}
 
 /*
  * Conversions
@@ -232,12 +347,36 @@ static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
 						(msec + 200) / 400), 1, 255);
 }
 
-static inline unsigned int
-fan_from_reg(u8 reg, unsigned int div)
+static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
 {
 	if (reg == 0 || reg == 255)
 		return 0;
-	return 1350000U / (reg * div);
+	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 inline unsigned int
@@ -247,21 +386,19 @@ div_from_reg(u8 reg)
 }
 
 static inline int
-temp1_from_reg(s8 reg)
+temp_from_reg(u16 reg, s16 regval)
 {
-	return reg * 1000;
+	if (is_word_sized(reg))
+		return LM75_TEMP_FROM_REG(regval);
+	return regval * 1000;
 }
 
-static inline s8
-temp1_to_reg(long temp, int min, int max)
+static inline u16
+temp_to_reg(u16 reg, long temp)
 {
-	if (temp <= min)
-		return min / 1000;
-	if (temp >= max)
-		return max / 1000;
-	if (temp < 0)
-		return (temp - 500) / 1000;
-	return (temp + 500) / 1000;
+	if (is_word_sized(reg))
+		return LM75_TEMP_TO_REG(temp);
+	return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000), 1000);
 }
 
 /* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
@@ -275,7 +412,8 @@ static inline long in_from_reg(u8 reg, u8 nr)
 
 static inline u8 in_to_reg(u32 val, u8 nr)
 {
-	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
+	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0,
+			     255);
 }
 
 /*
@@ -289,38 +427,57 @@ struct w83627ehf_data {
 	struct device *hwmon_dev;
 	struct mutex lock;
 
-	const u8 *REG_FAN_START_OUTPUT;
-	const u8 *REG_FAN_STOP_OUTPUT;
-	const u8 *REG_FAN_MAX_OUTPUT;
-	const u8 *REG_FAN_STEP_OUTPUT;
+	u16 reg_temp[NUM_REG_TEMP];
+	u16 reg_temp_over[NUM_REG_TEMP];
+	u16 reg_temp_hyst[NUM_REG_TEMP];
+	u16 reg_temp_config[NUM_REG_TEMP];
+	u8 temp_src[NUM_REG_TEMP];
+	const char * const *temp_label;
+
+	const u16 *REG_PWM;
+	const u16 *REG_TARGET;
+	const u16 *REG_FAN;
+	const u16 *REG_FAN_MIN;
+	const u16 *REG_FAN_START_OUTPUT;
+	const u16 *REG_FAN_STOP_OUTPUT;
+	const u16 *REG_FAN_STOP_TIME;
+	const u16 *REG_FAN_MAX_OUTPUT;
+	const u16 *REG_FAN_STEP_OUTPUT;
+
+	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;
 	char valid;		/* !=0 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[10];		/* Register value */
 	u8 in_max[10];		/* Register value */
 	u8 in_min[10];		/* Register value */
-	u8 fan[5];
-	u8 fan_min[5];
+	unsigned int rpm[5];
+	u16 fan_min[5];
 	u8 fan_div[5];
 	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_type[3];
-	s8 temp1;
-	s8 temp1_max;
-	s8 temp1_max_hyst;
-	s16 temp[2];
-	s16 temp_max[2];
-	s16 temp_max_hyst[2];
+	s16 temp[9];
+	s16 temp_max[9];
+	s16 temp_max_hyst[9];
 	u32 alarms;
 
 	u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
 	u8 pwm_enable[4]; /* 1->manual
 			     2->thermal cruise mode (also called SmartFan I)
 			     3->fan speed cruise mode
-			     4->variable thermal cruise (also called SmartFan III) */
+			     4->variable thermal cruise (also called
+				SmartFan III)
+			     5->enhanced variable thermal cruise (also called
+				SmartFan IV) */
+	u8 pwm_enable_orig[4];	/* original value of pwm_enable */
 	u8 pwm_num;		/* number of pwm */
 	u8 pwm[4];
 	u8 target_temp[4];
@@ -335,7 +492,7 @@ struct w83627ehf_data {
 	u8 vid;
 	u8 vrm;
 
-	u8 temp3_disable;
+	u16 have_temp;
 	u8 in6_skip;
 };
 
@@ -344,30 +501,19 @@ struct w83627ehf_sio_data {
 	enum kinds kind;
 };
 
-static inline int is_word_sized(u16 reg)
-{
-	return (((reg & 0xff00) == 0x100
-	      || (reg & 0xff00) == 0x200)
-	     && ((reg & 0x00ff) == 0x50
-	      || (reg & 0x00ff) == 0x53
-	      || (reg & 0x00ff) == 0x55));
-}
-
-/* Registers 0x50-0x5f are banked */
+/*
+ * 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 w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg)
 {
-	if ((reg & 0x00f0) == 0x50) {
+	u8 bank = reg >> 8;
+	if (data->bank != bank) {
 		outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
-		outb_p(reg >> 8, data->addr + DATA_REG_OFFSET);
-	}
-}
-
-/* Not strictly necessary, but play it safe for now */
-static inline void w83627ehf_reset_bank(struct w83627ehf_data *data, u16 reg)
-{
-	if (reg & 0xff00) {
-		outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
-		outb_p(0, data->addr + DATA_REG_OFFSET);
+		outb_p(bank, data->addr + DATA_REG_OFFSET);
+		data->bank = bank;
 	}
 }
 
@@ -385,14 +531,13 @@ static u16 w83627ehf_read_value(struct w83627ehf_data *data, u16 reg)
 		       data->addr + ADDR_REG_OFFSET);
 		res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
 	}
-	w83627ehf_reset_bank(data, reg);
 
 	mutex_unlock(&data->lock);
-
 	return res;
 }
 
-static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg, u16 value)
+static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg,
+				 u16 value)
 {
 	int word_sized = is_word_sized(reg);
 
@@ -406,13 +551,40 @@ static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg, u16 value
 		       data->addr + ADDR_REG_OFFSET);
 	}
 	outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
-	w83627ehf_reset_bank(data, reg);
 
 	mutex_unlock(&data->lock);
 	return 0;
 }
 
 /* This function assumes that the caller holds data->update_lock */
+static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr)
+{
+	u8 reg;
+
+	switch (nr) {
+	case 0:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
+		    | (data->fan_div[0] & 0x7);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg);
+		break;
+	case 1:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
+		    | ((data->fan_div[1] << 4) & 0x70);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg);
+	case 2:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
+		    | (data->fan_div[2] & 0x7);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	case 3:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
+		    | ((data->fan_div[3] << 4) & 0x70);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	}
+}
+
+/* This function assumes that the caller holds data->update_lock */
 static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr)
 {
 	u8 reg;
@@ -463,6 +635,32 @@ static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr)
 	}
 }
 
+static void w83627ehf_write_fan_div_common(struct device *dev,
+					   struct w83627ehf_data *data, int nr)
+{
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	if (sio_data->kind == nct6776)
+		; /* no dividers, do nothing */
+	else if (sio_data->kind == nct6775)
+		nct6775_write_fan_div(data, nr);
+	else
+		w83627ehf_write_fan_div(data, nr);
+}
+
+static void nct6775_update_fan_div(struct w83627ehf_data *data)
+{
+	u8 i;
+
+	i = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
+	data->fan_div[0] = i & 0x7;
+	data->fan_div[1] = (i & 0x70) >> 4;
+	i = w83627ehf_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 w83627ehf_update_fan_div(struct w83627ehf_data *data)
 {
 	int i;
@@ -488,10 +686,79 @@ static void w83627ehf_update_fan_div(struct w83627ehf_data *data)
 	}
 }
 
+static void w83627ehf_update_fan_div_common(struct device *dev,
+					    struct w83627ehf_data *data)
+{
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	if (sio_data->kind == nct6776)
+		; /* no dividers, do nothing */
+	else if (sio_data->kind == nct6775)
+		nct6775_update_fan_div(data);
+	else
+		w83627ehf_update_fan_div(data);
+}
+
+static void nct6775_update_pwm(struct w83627ehf_data *data)
+{
+	int i;
+	int pwmcfg, fanmodecfg;
+
+	for (i = 0; i < data->pwm_num; i++) {
+		pwmcfg = w83627ehf_read_value(data,
+					      W83627EHF_REG_PWM_ENABLE[i]);
+		fanmodecfg = w83627ehf_read_value(data,
+						  NCT6775_REG_FAN_MODE[i]);
+		data->pwm_mode[i] =
+		  ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1;
+		data->pwm_enable[i] = ((fanmodecfg >> 4) & 7) + 1;
+		data->tolerance[i] = fanmodecfg & 0x0f;
+		data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]);
+	}
+}
+
+static void w83627ehf_update_pwm(struct w83627ehf_data *data)
+{
+	int i;
+	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
+
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_fan & (1 << i)))
+			continue;
+
+		/* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
+		if (i != 1) {
+			pwmcfg = w83627ehf_read_value(data,
+					W83627EHF_REG_PWM_ENABLE[i]);
+			tolerance = w83627ehf_read_value(data,
+					W83627EHF_REG_TOLERANCE[i]);
+		}
+		data->pwm_mode[i] =
+			((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1;
+		data->pwm_enable[i] = ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
+				       & 3) + 1;
+		data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]);
+
+		data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) & 0x0f;
+	}
+}
+
+static void w83627ehf_update_pwm_common(struct device *dev,
+					struct w83627ehf_data *data)
+{
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776)
+		nct6775_update_pwm(data);
+	else
+		w83627ehf_update_pwm(data);
+}
+
 static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
-	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -499,7 +766,7 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 	if (time_after(jiffies, data->last_updated + HZ + HZ/2)
 	 || !data->valid) {
 		/* Fan clock dividers */
-		w83627ehf_update_fan_div(data);
+		w83627ehf_update_fan_div_common(dev, data);
 
 		/* Measured voltages and limits */
 		for (i = 0; i < data->in_num; i++) {
@@ -513,92 +780,90 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 
 		/* Measured fan speeds and limits */
 		for (i = 0; i < 5; i++) {
+			u16 reg;
+
 			if (!(data->has_fan & (1 << i)))
 				continue;
 
-			data->fan[i] = w83627ehf_read_value(data,
-				       W83627EHF_REG_FAN[i]);
-			data->fan_min[i] = w83627ehf_read_value(data,
-					   W83627EHF_REG_FAN_MIN[i]);
+			reg = w83627ehf_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] = w83627ehf_read_value(data,
+					   data->REG_FAN_MIN[i]);
 
 			/* If we failed to measure the fan speed and clock
 			   divider can be increased, let's try that for next
 			   time */
-			if (data->fan[i] == 0xff
-			 && data->fan_div[i] < 0x07) {
-			 	dev_dbg(dev, "Increasing fan%d "
+			if (data->has_fan_div
+			    && (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",
 					i + 1, div_from_reg(data->fan_div[i]),
 					div_from_reg(data->fan_div[i] + 1));
 				data->fan_div[i]++;
-				w83627ehf_write_fan_div(data, i);
+				w83627ehf_write_fan_div_common(dev, data, i);
 				/* Preserve min limit if possible */
-				if (data->fan_min[i] >= 2
+				if ((data->has_fan_min & (1 << i))
+				 && data->fan_min[i] >= 2
 				 && data->fan_min[i] != 255)
 					w83627ehf_write_value(data,
-						W83627EHF_REG_FAN_MIN[i],
+						data->REG_FAN_MIN[i],
 						(data->fan_min[i] /= 2));
 			}
 		}
 
+		w83627ehf_update_pwm_common(dev, data);
+
 		for (i = 0; i < data->pwm_num; i++) {
 			if (!(data->has_fan & (1 << i)))
 				continue;
 
-			/* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
-			if (i != 1) {
-				pwmcfg = w83627ehf_read_value(data,
-						W83627EHF_REG_PWM_ENABLE[i]);
-				tolerance = w83627ehf_read_value(data,
-						W83627EHF_REG_TOLERANCE[i]);
-			}
-			data->pwm_mode[i] =
-				((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
-				? 0 : 1;
-			data->pwm_enable[i] =
-					((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
-						& 3) + 1;
-			data->pwm[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_PWM[i]);
-			data->fan_start_output[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_FAN_START_OUTPUT[i]);
-			data->fan_stop_output[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_FAN_STOP_OUTPUT[i]);
-			data->fan_stop_time[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_FAN_STOP_TIME[i]);
-
-			if (data->REG_FAN_MAX_OUTPUT[i] != 0xff)
+			data->fan_start_output[i] =
+			  w83627ehf_read_value(data,
+					       data->REG_FAN_START_OUTPUT[i]);
+			data->fan_stop_output[i] =
+			  w83627ehf_read_value(data,
+					       data->REG_FAN_STOP_OUTPUT[i]);
+			data->fan_stop_time[i] =
+			  w83627ehf_read_value(data,
+					       data->REG_FAN_STOP_TIME[i]);
+
+			if (data->REG_FAN_MAX_OUTPUT &&
+			    data->REG_FAN_MAX_OUTPUT[i] != 0xff)
 				data->fan_max_output[i] =
 				  w83627ehf_read_value(data,
-					       data->REG_FAN_MAX_OUTPUT[i]);
+						data->REG_FAN_MAX_OUTPUT[i]);
 
-			if (data->REG_FAN_STEP_OUTPUT[i] != 0xff)
+			if (data->REG_FAN_STEP_OUTPUT &&
+			    data->REG_FAN_STEP_OUTPUT[i] != 0xff)
 				data->fan_step_output[i] =
 				  w83627ehf_read_value(data,
-					       data->REG_FAN_STEP_OUTPUT[i]);
+						data->REG_FAN_STEP_OUTPUT[i]);
 
 			data->target_temp[i] =
 				w83627ehf_read_value(data,
-					W83627EHF_REG_TARGET[i]) &
+					data->REG_TARGET[i]) &
 					(data->pwm_mode[i] == 1 ? 0x7f : 0xff);
-			data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
-									& 0x0f;
 		}
 
 		/* Measured temperatures and limits */
-		data->temp1 = w83627ehf_read_value(data,
-			      W83627EHF_REG_TEMP1);
-		data->temp1_max = w83627ehf_read_value(data,
-				  W83627EHF_REG_TEMP1_OVER);
-		data->temp1_max_hyst = w83627ehf_read_value(data,
-				       W83627EHF_REG_TEMP1_HYST);
-		for (i = 0; i < 2; i++) {
+		for (i = 0; i < NUM_REG_TEMP; i++) {
+			if (!(data->have_temp & (1 << i)))
+				continue;
 			data->temp[i] = w83627ehf_read_value(data,
-					W83627EHF_REG_TEMP[i]);
-			data->temp_max[i] = w83627ehf_read_value(data,
-					    W83627EHF_REG_TEMP_OVER[i]);
-			data->temp_max_hyst[i] = w83627ehf_read_value(data,
-						 W83627EHF_REG_TEMP_HYST[i]);
+						data->reg_temp[i]);
+			if (data->reg_temp_over[i])
+				data->temp_max[i]
+				  = w83627ehf_read_value(data,
+						data->reg_temp_over[i]);
+			if (data->reg_temp_hyst[i])
+				data->temp_max_hyst[i]
+				  = w83627ehf_read_value(data,
+						data->reg_temp_hyst[i]);
 		}
 
 		data->alarms = w83627ehf_read_value(data,
@@ -625,7 +890,8 @@ show_##reg(struct device *dev, struct device_attribute *attr, \
 	   char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
 }
@@ -635,14 +901,18 @@ show_in_reg(in_max)
 
 #define store_in_reg(REG, reg) \
 static ssize_t \
-store_in_##reg (struct device *dev, struct device_attribute *attr, \
-			const char *buf, size_t count) \
+store_in_##reg(struct device *dev, struct device_attribute *attr, \
+	       const char *buf, size_t count) \
 { \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	u32 val = simple_strtoul(buf, NULL, 10); \
- \
+	unsigned long val; \
+	int err; \
+	err = strict_strtoul(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = in_to_reg(val, nr); \
 	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
@@ -654,7 +924,8 @@ store_in_##reg (struct device *dev, struct device_attribute *attr, \
 store_in_reg(MIN, min)
 store_in_reg(MAX, max)
 
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct w83627ehf_data *data = w83627ehf_update_device(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
@@ -689,45 +960,50 @@ static struct sensor_device_attribute sda_in_alarm[] = {
 };
 
 static struct sensor_device_attribute sda_in_min[] = {
-       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
-       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
-       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
-       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
-       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
-       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
-       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
-       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
-       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
-       SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
+	SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+	SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+	SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+	SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
+	SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
+	SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
+	SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
+	SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
+	SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
+	SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
 };
 
 static struct sensor_device_attribute sda_in_max[] = {
-       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
-       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
-       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
-       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
-       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
-       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
-       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
-       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
-       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
-       SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
+	SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+	SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+	SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+	SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
+	SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
+	SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
+	SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
+	SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
+	SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
+	SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
 };
 
-#define show_fan_reg(reg) \
-static ssize_t \
-show_##reg(struct device *dev, struct device_attribute *attr, \
-	   char *buf) \
-{ \
-	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
-	int nr = sensor_attr->index; \
-	return sprintf(buf, "%d\n", \
-		       fan_from_reg(data->reg[nr], \
-				    div_from_reg(data->fan_div[nr]))); \
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%d\n", data->rpm[nr]);
+}
+
+static ssize_t
+show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%d\n",
+		       data->fan_from_reg_min(data->fan_min[nr],
+					      data->fan_div[nr]));
 }
-show_fan_reg(fan);
-show_fan_reg(fan_min);
 
 static ssize_t
 show_fan_div(struct device *dev, struct device_attribute *attr,
@@ -746,11 +1022,32 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	unsigned int val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
 	unsigned int reg;
 	u8 new_div;
 
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
 	mutex_lock(&data->update_lock);
+	if (!data->has_fan_div) {
+		/*
+		 * Only NCT6776F for now, so we know that 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 done;	/* Leave fan divider alone */
+	}
 	if (!val) {
 		/* No min limit, alarm disabled */
 		data->fan_min[nr] = 255;
@@ -761,15 +1058,17 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 		   even with the highest divider (128) */
 		data->fan_min[nr] = 254;
 		new_div = 7; /* 128 == (1 << 7) */
-		dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
-			 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
+		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 %u above maximum %u, set to "
-			 "maximum\n", nr + 1, val, fan_from_reg(1, 1));
+		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
@@ -785,25 +1084,16 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 	/* Write both the fan clock divider (if it changed) and the new
 	   fan min (unconditionally) */
 	if (new_div != data->fan_div[nr]) {
-		/* Preserve the fan speed reading */
-		if (data->fan[nr] != 0xff) {
-			if (new_div > data->fan_div[nr])
-				data->fan[nr] >>= new_div - data->fan_div[nr];
-			else if (data->fan[nr] & 0x80)
-				data->fan[nr] = 0xff;
-			else
-				data->fan[nr] <<= data->fan_div[nr] - new_div;
-		}
-
 		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;
-		w83627ehf_write_fan_div(data, nr);
+		w83627ehf_write_fan_div_common(dev, data, nr);
 		/* Give the chip time to sample a new speed value */
 		data->last_updated = jiffies;
 	}
-	w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[nr],
+done:
+	w83627ehf_write_value(data, data->REG_FAN_MIN[nr],
 			      data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 
@@ -847,70 +1137,54 @@ static struct sensor_device_attribute sda_fan_div[] = {
 	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
 };
 
-#define show_temp1_reg(reg) \
-static ssize_t \
-show_##reg(struct device *dev, struct device_attribute *attr, \
-	   char *buf) \
-{ \
-	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
-}
-show_temp1_reg(temp1);
-show_temp1_reg(temp1_max);
-show_temp1_reg(temp1_max_hyst);
-
-#define store_temp1_reg(REG, reg) \
-static ssize_t \
-store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
-		  const char *buf, size_t count) \
-{ \
-	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock); \
-	data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
-	w83627ehf_write_value(data, W83627EHF_REG_TEMP1_##REG, \
-			      data->temp1_##reg); \
-	mutex_unlock(&data->update_lock); \
-	return count; \
+static ssize_t
+show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
 }
-store_temp1_reg(OVER, max);
-store_temp1_reg(HYST, max_hyst);
 
-#define show_temp_reg(reg) \
+#define show_temp_reg(addr, reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
 	   char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", \
-		       LM75_TEMP_FROM_REG(data->reg[nr])); \
+		       temp_from_reg(data->addr[nr], data->reg[nr])); \
 }
-show_temp_reg(temp);
-show_temp_reg(temp_max);
-show_temp_reg(temp_max_hyst);
+show_temp_reg(reg_temp, temp);
+show_temp_reg(reg_temp_over, temp_max);
+show_temp_reg(reg_temp_hyst, temp_max_hyst);
 
-#define store_temp_reg(REG, reg) \
+#define store_temp_reg(addr, reg) \
 static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 	    const char *buf, size_t count) \
 { \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	long val = simple_strtol(buf, NULL, 10); \
- \
+	int err; \
+	long val; \
+	err = strict_strtol(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
 	mutex_lock(&data->update_lock); \
-	data->reg[nr] = LM75_TEMP_TO_REG(val); \
-	w83627ehf_write_value(data, W83627EHF_REG_TEMP_##REG[nr], \
+	data->reg[nr] = temp_to_reg(data->addr[nr], val); \
+	w83627ehf_write_value(data, data->addr[nr], \
 			      data->reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
-store_temp_reg(OVER, temp_max);
-store_temp_reg(HYST, temp_max_hyst);
+store_temp_reg(reg_temp_over, temp_max);
+store_temp_reg(reg_temp_hyst, temp_max_hyst);
 
 static ssize_t
 show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
@@ -922,27 +1196,69 @@ show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
 }
 
 static struct sensor_device_attribute sda_temp_input[] = {
-	SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
-	SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
-	SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1),
+	SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
+	SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
+	SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
+	SENSOR_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3),
+	SENSOR_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4),
+	SENSOR_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5),
+	SENSOR_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6),
+	SENSOR_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7),
+	SENSOR_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8),
+};
+
+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),
 };
 
 static struct sensor_device_attribute sda_temp_max[] = {
-	SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max,
-		    store_temp1_max, 0),
-	SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
+	SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max,
 		    store_temp_max, 0),
-	SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
+	SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
 		    store_temp_max, 1),
+	SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 2),
+	SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 3),
+	SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 4),
+	SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 5),
+	SENSOR_ATTR(temp7_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 6),
+	SENSOR_ATTR(temp8_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 7),
+	SENSOR_ATTR(temp9_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 8),
 };
 
 static struct sensor_device_attribute sda_temp_max_hyst[] = {
-	SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst,
-		    store_temp1_max_hyst, 0),
-	SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+	SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
 		    store_temp_max_hyst, 0),
-	SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+	SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
 		    store_temp_max_hyst, 1),
+	SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 2),
+	SENSOR_ATTR(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 3),
+	SENSOR_ATTR(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 4),
+	SENSOR_ATTR(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 5),
+	SENSOR_ATTR(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 6),
+	SENSOR_ATTR(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 7),
+	SENSOR_ATTR(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 8),
 };
 
 static struct sensor_device_attribute sda_temp_alarm[] = {
@@ -958,11 +1274,12 @@ static struct sensor_device_attribute sda_temp_type[] = {
 };
 
 #define show_pwm_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
-				char *buf) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+			  char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", data->reg[nr]); \
 }
@@ -978,9 +1295,14 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
 	u16 reg;
 
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
 	if (val > 1)
 		return -EINVAL;
 	mutex_lock(&data->update_lock);
@@ -1001,11 +1323,18 @@ store_pwm(struct device *dev, struct device_attribute *attr,
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
+	unsigned long val;
+	int err;
+
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(val, 0, 255);
 
 	mutex_lock(&data->update_lock);
 	data->pwm[nr] = val;
-	w83627ehf_write_value(data, W83627EHF_REG_PWM[nr], val);
+	w83627ehf_write_value(data, data->REG_PWM[nr], val);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1015,19 +1344,38 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
 	u16 reg;
 
-	if (!val || (val > 4))
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (!val || (val > 4 && val != data->pwm_enable_orig[nr]))
 		return -EINVAL;
+	/* SmartFan III mode is not supported on NCT6776F */
+	if (sio_data->kind == nct6776 && val == 4)
+		return -EINVAL;
+
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
 	data->pwm_enable[nr] = val;
-	reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
-	reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
-	w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		reg = w83627ehf_read_value(data,
+					   NCT6775_REG_FAN_MODE[nr]);
+		reg &= 0x0f;
+		reg |= (val - 1) << 4;
+		w83627ehf_write_value(data,
+				      NCT6775_REG_FAN_MODE[nr], reg);
+	} else {
+		reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
+		reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
+		reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
+		w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1038,9 +1386,10 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 				char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \
+	return sprintf(buf, "%d\n", data->reg[nr] * 1000); \
 }
 
 show_tol_temp(tolerance)
@@ -1053,11 +1402,18 @@ store_target_temp(struct device *dev, struct device_attribute *attr,
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
+	long val;
+	int err;
+
+	err = strict_strtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
 
 	mutex_lock(&data->update_lock);
 	data->target_temp[nr] = val;
-	w83627ehf_write_value(data, W83627EHF_REG_TARGET[nr], val);
+	w83627ehf_write_value(data, data->REG_TARGET[nr], val);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1067,20 +1423,37 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u16 reg;
+	long val;
+	int err;
+
+	err = strict_strtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
 	/* Limit the temp to 0C - 15C */
-	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
 
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
-	data->tolerance[nr] = val;
-	if (nr == 1)
-		reg = (reg & 0x0f) | (val << 4);
-	else
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		/* Limit tolerance further for NCT6776F */
+		if (sio_data->kind == nct6776 && val > 7)
+			val = 7;
+		reg = w83627ehf_read_value(data, NCT6775_REG_FAN_MODE[nr]);
 		reg = (reg & 0xf0) | val;
-	w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg);
+		w83627ehf_write_value(data, NCT6775_REG_FAN_MODE[nr], reg);
+	} else {
+		reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
+		if (nr == 1)
+			reg = (reg & 0x0f) | (val << 4);
+		else
+			reg = (reg & 0xf0) | val;
+		w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg);
+	}
+	data->tolerance[nr] = val;
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1143,18 +1516,25 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 		       char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", data->reg[nr]); \
-}\
+} \
 static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 			    const char *buf, size_t count) \
-{\
+{ \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
+	unsigned long val; \
+	int err; \
+	err = strict_strtoul(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
+	val = SENSORS_LIMIT(val, 1, 255); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
 	w83627ehf_write_value(data, data->REG_##REG[nr], val); \
@@ -1172,10 +1552,12 @@ static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
 				char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", \
-			step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \
+			step_time_from_reg(data->reg[nr], \
+					   data->pwm_mode[nr])); \
 } \
 \
 static ssize_t \
@@ -1183,10 +1565,15 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
 			const char *buf, size_t count) \
 { \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
-					data->pwm_mode[nr]); \
+	unsigned long val; \
+	int err; \
+	err = strict_strtoul(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
+	val = step_time_to_reg(val, data->pwm_mode[nr]); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
 	w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \
@@ -1283,7 +1670,8 @@ static void w83627ehf_device_remove_files(struct device *dev)
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
 		struct sensor_device_attribute *attr =
 		  &sda_sf3_max_step_arrays[i];
-		if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
+		if (data->REG_FAN_STEP_OUTPUT &&
+		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
 			device_remove_file(dev, &attr->dev_attr);
 	}
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
@@ -1309,12 +1697,15 @@ static void w83627ehf_device_remove_files(struct device *dev)
 		device_remove_file(dev, &sda_target_temp[i].dev_attr);
 		device_remove_file(dev, &sda_tolerance[i].dev_attr);
 	}
-	for (i = 0; i < 3; i++) {
-		if ((i == 2) && data->temp3_disable)
+	for (i = 0; i < NUM_REG_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);
+		if (i > 2)
+			continue;
 		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
 		device_remove_file(dev, &sda_temp_type[i].dev_attr);
 	}
@@ -1335,15 +1726,17 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
 		w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
 				      tmp | 0x01);
 
-	/* Enable temp2 and temp3 if needed */
-	for (i = 0; i < 2; i++) {
-		tmp = w83627ehf_read_value(data,
-					   W83627EHF_REG_TEMP_CONFIG[i]);
-		if ((i == 1) && data->temp3_disable)
+	/* Enable temperature sensors if needed */
+	for (i = 0; i < NUM_REG_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		if (!data->reg_temp_config[i])
 			continue;
+		tmp = w83627ehf_read_value(data,
+					   data->reg_temp_config[i]);
 		if (tmp & 0x01)
 			w83627ehf_write_value(data,
-					      W83627EHF_REG_TEMP_CONFIG[i],
+					      data->reg_temp_config[i],
 					      tmp & 0xfe);
 	}
 
@@ -1362,13 +1755,39 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
 	}
 }
 
+static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
+				   int r1, int r2)
+{
+	u16 tmp;
+
+	tmp = data->temp_src[r1];
+	data->temp_src[r1] = data->temp_src[r2];
+	data->temp_src[r2] = tmp;
+
+	tmp = data->reg_temp[r1];
+	data->reg_temp[r1] = data->reg_temp[r2];
+	data->reg_temp[r2] = tmp;
+
+	tmp = data->reg_temp_over[r1];
+	data->reg_temp_over[r1] = data->reg_temp_over[r2];
+	data->reg_temp_over[r2] = tmp;
+
+	tmp = data->reg_temp_hyst[r1];
+	data->reg_temp_hyst[r1] = data->reg_temp_hyst[r2];
+	data->reg_temp_hyst[r2] = tmp;
+
+	tmp = data->reg_temp_config[r1];
+	data->reg_temp_config[r1] = data->reg_temp_config[r2];
+	data->reg_temp_config[r2] = tmp;
+}
+
 static int __devinit w83627ehf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct w83627ehf_data *data;
 	struct resource *res;
-	u8 fan4pin, fan5pin, en_vrm10;
+	u8 fan3pin, fan4pin, fan4min, fan5pin, en_vrm10;
 	int i, err = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1380,7 +1799,8 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 		goto exit;
 	}
 
-	if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
@@ -1393,25 +1813,202 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 
 	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
 	data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
-	/* 667HG has 3 pwms */
+	/* 667HG, NCT6775F, and NCT6776F have 3 pwms */
 	data->pwm_num = (sio_data->kind == w83667hg
-			 || sio_data->kind == w83667hg_b) ? 3 : 4;
+			 || sio_data->kind == w83667hg_b
+			 || sio_data->kind == nct6775
+			 || sio_data->kind == nct6776) ? 3 : 4;
 
+	data->have_temp = 0x07;
 	/* Check temp3 configuration bit for 667HG */
-	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
-		data->temp3_disable = w83627ehf_read_value(data,
-					W83627EHF_REG_TEMP_CONFIG[1]) & 0x01;
-		data->in6_skip = !data->temp3_disable;
+	if (sio_data->kind == w83667hg) {
+		u8 reg;
+
+		reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
+		if (reg & 0x01)
+			data->have_temp &= ~(1 << 2);
+		else
+			data->in6_skip = 1;	/* either temp3 or in6 */
+	}
+
+	/* Deal with temperature register setup first. */
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		int mask = 0;
+
+		/*
+		 * Display temperature sensor output only if it monitors
+		 * a source other than one already reported. Always display
+		 * first three temperature registers, though.
+		 */
+		for (i = 0; i < NUM_REG_TEMP; i++) {
+			u8 src;
+
+			data->reg_temp[i] = NCT6775_REG_TEMP[i];
+			data->reg_temp_over[i] = NCT6775_REG_TEMP_OVER[i];
+			data->reg_temp_hyst[i] = NCT6775_REG_TEMP_HYST[i];
+			data->reg_temp_config[i] = NCT6775_REG_TEMP_CONFIG[i];
+
+			src = w83627ehf_read_value(data,
+						   NCT6775_REG_TEMP_SOURCE[i]);
+			src &= 0x1f;
+			if (src && !(mask & (1 << src))) {
+				data->have_temp |= 1 << i;
+				mask |= 1 << src;
+			}
+
+			data->temp_src[i] = src;
+
+			/*
+			 * Now do some register swapping if index 0..2 don't
+			 * point to SYSTIN(1), CPUIN(2), and AUXIN(3).
+			 * Idea is to have the first three attributes
+			 * report SYSTIN, CPUIN, and AUXIN if possible
+			 * without overriding the basic system configuration.
+			 */
+			if (i > 0 && data->temp_src[0] != 1
+			    && data->temp_src[i] == 1)
+				w82627ehf_swap_tempreg(data, 0, i);
+			if (i > 1 && data->temp_src[1] != 2
+			    && data->temp_src[i] == 2)
+				w82627ehf_swap_tempreg(data, 1, i);
+			if (i > 2 && data->temp_src[2] != 3
+			    && data->temp_src[i] == 3)
+				w82627ehf_swap_tempreg(data, 2, i);
+		}
+		if (sio_data->kind == 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->temp_src[2] == 3) {
+				u8 reg;
+
+				if (data->reg_temp_config[2])
+					reg = w83627ehf_read_value(data,
+						data->reg_temp_config[2]);
+				else
+					reg = 0; /* Assume AUXTIN is used */
+
+				if (reg & 0x01)
+					data->have_temp &= ~(1 << 2);
+				else
+					data->in6_skip = 1;
+			}
+			data->temp_label = nct6776_temp_label;
+		} else {
+			data->temp_label = nct6775_temp_label;
+		}
+	} else if (sio_data->kind == w83667hg_b) {
+		u8 reg;
+
+		/*
+		 * Temperature sources are selected with bank 0, registers 0x49
+		 * and 0x4a.
+		 */
+		for (i = 0; i < ARRAY_SIZE(W83627EHF_REG_TEMP); i++) {
+			data->reg_temp[i] = W83627EHF_REG_TEMP[i];
+			data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
+			data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
+			data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+		}
+		reg = w83627ehf_read_value(data, 0x4a);
+		data->temp_src[0] = reg >> 5;
+		reg = w83627ehf_read_value(data, 0x49);
+		data->temp_src[1] = reg & 0x07;
+		data->temp_src[2] = (reg >> 4) & 0x07;
+
+		/*
+		 * W83667HG-B has another temperature register at 0x7e.
+		 * The temperature source is selected with register 0x7d.
+		 * Support it if the source differs from already reported
+		 * sources.
+		 */
+		reg = w83627ehf_read_value(data, 0x7d);
+		reg &= 0x07;
+		if (reg != data->temp_src[0] && reg != data->temp_src[1]
+		    && reg != data->temp_src[2]) {
+			data->temp_src[3] = reg;
+			data->have_temp |= 1 << 3;
+		}
+
+		/*
+		 * Chip supports either AUXTIN or VIN3. Try to find out which
+		 * one.
+		 */
+		reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
+		if (data->temp_src[2] == 2 && (reg & 0x01))
+			data->have_temp &= ~(1 << 2);
+
+		if ((data->temp_src[2] == 2 && (data->have_temp & (1 << 2)))
+		    || (data->temp_src[3] == 2 && (data->have_temp & (1 << 3))))
+			data->in6_skip = 1;
+
+		data->temp_label = w83667hg_b_temp_label;
+	} else {
+		/* Temperature sources are fixed */
+		for (i = 0; i < 3; i++) {
+			data->reg_temp[i] = W83627EHF_REG_TEMP[i];
+			data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
+			data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
+			data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+		}
 	}
 
-	data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
-	data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
-	if (sio_data->kind == w83667hg_b) {
+	if (sio_data->kind == nct6775) {
+		data->has_fan_div = true;
+		data->fan_from_reg = fan_from_reg16;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->REG_PWM = NCT6775_REG_PWM;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_MAX_OUTPUT = NCT6775_REG_FAN_MAX_OUTPUT;
+		data->REG_FAN_STEP_OUTPUT = NCT6775_REG_FAN_STEP_OUTPUT;
+	} else if (sio_data->kind == nct6776) {
+		data->has_fan_div = false;
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+		data->REG_PWM = NCT6775_REG_PWM;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME;
+	} else if (sio_data->kind == w83667hg_b) {
+		data->has_fan_div = true;
+		data->fan_from_reg = fan_from_reg8;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->REG_PWM = W83627EHF_REG_PWM;
+		data->REG_TARGET = W83627EHF_REG_TARGET;
+		data->REG_FAN = W83627EHF_REG_FAN;
+		data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME;
 		data->REG_FAN_MAX_OUTPUT =
 		  W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B;
 		data->REG_FAN_STEP_OUTPUT =
 		  W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B;
 	} else {
+		data->has_fan_div = true;
+		data->fan_from_reg = fan_from_reg8;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->REG_PWM = W83627EHF_REG_PWM;
+		data->REG_TARGET = W83627EHF_REG_TARGET;
+		data->REG_FAN = W83627EHF_REG_FAN;
+		data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME;
 		data->REG_FAN_MAX_OUTPUT =
 		  W83627EHF_REG_FAN_MAX_OUTPUT_COMMON;
 		data->REG_FAN_STEP_OUTPUT =
@@ -1424,7 +2021,8 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 	data->vrm = vid_which_vrm();
 	superio_enter(sio_data->sioreg);
 	/* Read VID value */
-	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
+	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b ||
+	    sio_data->kind == nct6775 || sio_data->kind == nct6776) {
 		/* W83667HG has different pins for VID input and output, so
 		we can get the VID input values directly at logical device D
 		0xe3. */
@@ -1475,13 +2073,44 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 	}
 
 	/* fan4 and fan5 share some pins with the GPIO and serial flash */
-	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
-		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+	if (sio_data->kind == nct6775) {
+		/* On NCT6775, fan4 shares pins with the fdc interface */
+		fan3pin = 1;
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
+		fan4min = 0;
+		fan5pin = 0;
+	} else if (sio_data->kind == nct6776) {
+		fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+		fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+		fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+		fan4min = fan4pin;
+	} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
+		fan3pin = 1;
 		fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
+		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+		fan4min = fan4pin;
 	} else {
-		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+		fan3pin = 1;
 		fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
+		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+		fan4min = fan4pin;
 	}
+
+	if (fan_debounce &&
+	    (sio_data->kind == nct6775 || sio_data->kind == nct6776)) {
+		u8 tmp;
+
+		superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+		tmp = superio_inb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE);
+		if (sio_data->kind == nct6776)
+			superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE,
+				     0x3e | tmp);
+		else
+			superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE,
+				     0x1e | tmp);
+		pr_info("Enabled fan debounce for chip %s\n", data->name);
+	}
+
 	superio_exit(sio_data->sioreg);
 
 	/* It looks like fan4 and fan5 pins can be alternatively used
@@ -1490,26 +2119,54 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 	   connected fan5 as input unless they are emitting log 1, which
 	   is not the default. */
 
-	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
-	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
-	if ((i & (1 << 2)) && fan4pin)
-		data->has_fan |= (1 << 3);
-	if (!(i & (1 << 1)) && fan5pin)
-		data->has_fan |= (1 << 4);
+	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+
+	data->has_fan |= (fan3pin << 2);
+	data->has_fan_min |= (fan3pin << 2);
+
+	/*
+	 * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1 register
+	 */
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+		data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+	} else {
+		i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
+		if ((i & (1 << 2)) && fan4pin) {
+			data->has_fan |= (1 << 3);
+			data->has_fan_min |= (1 << 3);
+		}
+		if (!(i & (1 << 1)) && fan5pin) {
+			data->has_fan |= (1 << 4);
+			data->has_fan_min |= (1 << 4);
+		}
+	}
 
 	/* Read fan clock dividers immediately */
-	w83627ehf_update_fan_div(data);
+	w83627ehf_update_fan_div_common(dev, data);
+
+	/* Read pwm data to save original values */
+	w83627ehf_update_pwm_common(dev, data);
+	for (i = 0; i < data->pwm_num; i++)
+		data->pwm_enable_orig[i] = data->pwm_enable[i];
+
+	/* Read pwm data to save original values */
+	w83627ehf_update_pwm_common(dev, data);
+	for (i = 0; i < data->pwm_num; i++)
+		data->pwm_enable_orig[i] = data->pwm_enable[i];
 
 	/* Register sysfs hooks */
-  	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
-		if ((err = device_create_file(dev,
-			&sda_sf3_arrays[i].dev_attr)))
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) {
+		err = device_create_file(dev, &sda_sf3_arrays[i].dev_attr);
+		if (err)
 			goto exit_remove;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
 		struct sensor_device_attribute *attr =
 		  &sda_sf3_max_step_arrays[i];
-		if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) {
+		if (data->REG_FAN_STEP_OUTPUT &&
+		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) {
 			err = device_create_file(dev, &attr->dev_attr);
 			if (err)
 				goto exit_remove;
@@ -1518,8 +2175,9 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 	/* if fan4 is enabled create the sf3 files for it */
 	if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
 		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
-			if ((err = device_create_file(dev,
-				&sda_sf3_arrays_fan4[i].dev_attr)))
+			err = device_create_file(dev,
+					&sda_sf3_arrays_fan4[i].dev_attr);
+			if (err)
 				goto exit_remove;
 		}
 
@@ -1541,12 +2199,20 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 			if ((err = device_create_file(dev,
 					&sda_fan_input[i].dev_attr))
 				|| (err = device_create_file(dev,
-					&sda_fan_alarm[i].dev_attr))
-				|| (err = device_create_file(dev,
-					&sda_fan_div[i].dev_attr))
-				|| (err = device_create_file(dev,
-					&sda_fan_min[i].dev_attr)))
+					&sda_fan_alarm[i].dev_attr)))
 				goto exit_remove;
+			if (sio_data->kind != nct6776) {
+				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;
+			}
 			if (i < data->pwm_num &&
 				((err = device_create_file(dev,
 					&sda_pwm[i].dev_attr))
@@ -1562,16 +2228,33 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
 		}
 	}
 
-	for (i = 0; i < 3; i++) {
-		if ((i == 2) && data->temp3_disable)
+	for (i = 0; i < NUM_REG_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_over[i]) {
+			err = device_create_file(dev,
+				&sda_temp_max[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp_hyst[i]) {
+			err = device_create_file(dev,
+				&sda_temp_max_hyst[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (i > 2)
 			continue;
 		if ((err = device_create_file(dev,
-				&sda_temp_input[i].dev_attr))
-			|| (err = device_create_file(dev,
-				&sda_temp_max[i].dev_attr))
-			|| (err = device_create_file(dev,
-				&sda_temp_max_hyst[i].dev_attr))
-			|| (err = device_create_file(dev,
 				&sda_temp_alarm[i].dev_attr))
 			|| (err = device_create_file(dev,
 				&sda_temp_type[i].dev_attr)))
@@ -1632,6 +2315,8 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
 	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
 	static const char __initdata sio_name_W83667HG[] = "W83667HG";
 	static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
+	static const char __initdata sio_name_NCT6775[] = "NCT6775F";
+	static const char __initdata sio_name_NCT6776[] = "NCT6776F";
 
 	u16 val;
 	const char *sio_name;
@@ -1668,6 +2353,14 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
 		sio_data->kind = w83667hg_b;
 		sio_name = sio_name_W83667HG_B;
 		break;
+	case SIO_NCT6775_ID:
+		sio_data->kind = nct6775;
+		sio_name = sio_name_NCT6775;
+		break;
+	case SIO_NCT6776_ID:
+		sio_data->kind = nct6776;
+		sio_name = sio_name_NCT6776;
+		break;
 	default:
 		if (val != 0xffff)
 			pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -1689,7 +2382,8 @@ 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);
 	}
 
@@ -1726,7 +2420,8 @@ static int __init sensors_w83627ehf_init(void)
 	if (err)
 		goto exit;
 
-	if (!(pdev = platform_device_alloc(DRVNAME, address))) {
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
 		err = -ENOMEM;
 		pr_err("Device allocation failed\n");
 		goto exit_unregister;
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
new file mode 100644
index 0000000..eb4af28
--- /dev/null
+++ b/drivers/hwspinlock/Kconfig
@@ -0,0 +1,22 @@
+#
+# Generic HWSPINLOCK framework
+#
+
+config HWSPINLOCK
+	tristate "Generic Hardware Spinlock framework"
+	help
+	  Say y here to support the generic hardware spinlock framework.
+	  You only need to enable this if you have hardware spinlock module
+	  on your system (usually only relevant if your system has remote slave
+	  coprocessors).
+
+	  If unsure, say N.
+
+config HWSPINLOCK_OMAP
+	tristate "OMAP Hardware Spinlock device"
+	depends on HWSPINLOCK && ARCH_OMAP4
+	help
+	  Say y here to support the OMAP Hardware Spinlock device (firstly
+	  introduced in OMAP4).
+
+	  If unsure, say N.
diff --git a/drivers/hwspinlock/Makefile b/drivers/hwspinlock/Makefile
new file mode 100644
index 0000000..5729a3f
--- /dev/null
+++ b/drivers/hwspinlock/Makefile
@@ -0,0 +1,6 @@
+#
+# Generic Hardware Spinlock framework
+#
+
+obj-$(CONFIG_HWSPINLOCK)		+= hwspinlock_core.o
+obj-$(CONFIG_HWSPINLOCK_OMAP)		+= omap_hwspinlock.o
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
new file mode 100644
index 0000000..43a6271
--- /dev/null
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -0,0 +1,548 @@
+/*
+ * Hardware spinlock framework
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#define pr_fmt(fmt)    "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/radix-tree.h>
+#include <linux/hwspinlock.h>
+#include <linux/pm_runtime.h>
+
+#include "hwspinlock_internal.h"
+
+/* radix tree tags */
+#define HWSPINLOCK_UNUSED	(0) /* tags an hwspinlock as unused */
+
+/*
+ * A radix tree is used to maintain the available hwspinlock instances.
+ * The tree associates hwspinlock pointers with their integer key id,
+ * and provides easy-to-use API which makes the hwspinlock core code simple
+ * and easy to read.
+ *
+ * Radix trees are quick on lookups, and reasonably efficient in terms of
+ * storage, especially with high density usages such as this framework
+ * requires (a continuous range of integer keys, beginning with zero, is
+ * used as the ID's of the hwspinlock instances).
+ *
+ * The radix tree API supports tagging items in the tree, which this
+ * framework uses to mark unused hwspinlock instances (see the
+ * HWSPINLOCK_UNUSED tag above). As a result, the process of querying the
+ * tree, looking for an unused hwspinlock instance, is now reduced to a
+ * single radix tree API call.
+ */
+static RADIX_TREE(hwspinlock_tree, GFP_KERNEL);
+
+/*
+ * Synchronization of access to the tree is achieved using this spinlock,
+ * as the radix-tree API requires that users provide all synchronisation.
+ */
+static DEFINE_SPINLOCK(hwspinlock_tree_lock);
+
+/**
+ * __hwspin_trylock() - attempt to lock a specific hwspinlock
+ * @hwlock: an hwspinlock which we want to trylock
+ * @mode: controls whether local interrupts are disabled or not
+ * @flags: a pointer where the caller's interrupt state will be saved at (if
+ *         requested)
+ *
+ * This function attempts to lock an hwspinlock, and will immediately
+ * fail if the hwspinlock is already taken.
+ *
+ * Upon a successful return from this function, preemption (and possibly
+ * interrupts) is disabled, so the caller must not sleep, and is advised to
+ * release the hwspinlock as soon as possible. This is required in order to
+ * minimize remote cores polling on the hardware interconnect.
+ *
+ * The user decides whether local interrupts are disabled or not, and if yes,
+ * whether he wants their previous state to be saved. It is up to the user
+ * to choose the appropriate @mode of operation, exactly the same way users
+ * should decide between spin_trylock, spin_trylock_irq and
+ * spin_trylock_irqsave.
+ *
+ * Returns 0 if we successfully locked the hwspinlock or -EBUSY if
+ * the hwspinlock was already taken.
+ * This function will never sleep.
+ */
+int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
+{
+	int ret;
+
+	BUG_ON(!hwlock);
+	BUG_ON(!flags && mode == HWLOCK_IRQSTATE);
+
+	/*
+	 * This spin_lock{_irq, _irqsave} serves three purposes:
+	 *
+	 * 1. Disable preemption, in order to minimize the period of time
+	 *    in which the hwspinlock is taken. This is important in order
+	 *    to minimize the possible polling on the hardware interconnect
+	 *    by a remote user of this lock.
+	 * 2. Make the hwspinlock SMP-safe (so we can take it from
+	 *    additional contexts on the local host).
+	 * 3. Ensure that in_atomic/might_sleep checks catch potential
+	 *    problems with hwspinlock usage (e.g. scheduler checks like
+	 *    'scheduling while atomic' etc.)
+	 */
+	if (mode == HWLOCK_IRQSTATE)
+		ret = spin_trylock_irqsave(&hwlock->lock, *flags);
+	else if (mode == HWLOCK_IRQ)
+		ret = spin_trylock_irq(&hwlock->lock);
+	else
+		ret = spin_trylock(&hwlock->lock);
+
+	/* is lock already taken by another context on the local cpu ? */
+	if (!ret)
+		return -EBUSY;
+
+	/* try to take the hwspinlock device */
+	ret = hwlock->ops->trylock(hwlock);
+
+	/* if hwlock is already taken, undo spin_trylock_* and exit */
+	if (!ret) {
+		if (mode == HWLOCK_IRQSTATE)
+			spin_unlock_irqrestore(&hwlock->lock, *flags);
+		else if (mode == HWLOCK_IRQ)
+			spin_unlock_irq(&hwlock->lock);
+		else
+			spin_unlock(&hwlock->lock);
+
+		return -EBUSY;
+	}
+
+	/*
+	 * We can be sure the other core's memory operations
+	 * are observable to us only _after_ we successfully take
+	 * the hwspinlock, and we must make sure that subsequent memory
+	 * operations (both reads and writes) will not be reordered before
+	 * we actually took the hwspinlock.
+	 *
+	 * Note: the implicit memory barrier of the spinlock above is too
+	 * early, so we need this additional explicit memory barrier.
+	 */
+	mb();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__hwspin_trylock);
+
+/**
+ * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit
+ * @hwlock: the hwspinlock to be locked
+ * @timeout: timeout value in msecs
+ * @mode: mode which controls whether local interrupts are disabled or not
+ * @flags: a pointer to where the caller's interrupt state will be saved at (if
+ *         requested)
+ *
+ * This function locks the given @hwlock. If the @hwlock
+ * is already taken, the function will busy loop waiting for it to
+ * be released, but give up after @timeout msecs have elapsed.
+ *
+ * Upon a successful return from this function, preemption is disabled
+ * (and possibly local interrupts, too), so the caller must not sleep,
+ * and is advised to release the hwspinlock as soon as possible.
+ * This is required in order to minimize remote cores polling on the
+ * hardware interconnect.
+ *
+ * The user decides whether local interrupts are disabled or not, and if yes,
+ * whether he wants their previous state to be saved. It is up to the user
+ * to choose the appropriate @mode of operation, exactly the same way users
+ * should decide between spin_lock, spin_lock_irq and spin_lock_irqsave.
+ *
+ * Returns 0 when the @hwlock was successfully taken, and an appropriate
+ * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still
+ * busy after @timeout msecs). The function will never sleep.
+ */
+int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to,
+					int mode, unsigned long *flags)
+{
+	int ret;
+	unsigned long expire;
+
+	expire = msecs_to_jiffies(to) + jiffies;
+
+	for (;;) {
+		/* Try to take the hwspinlock */
+		ret = __hwspin_trylock(hwlock, mode, flags);
+		if (ret != -EBUSY)
+			break;
+
+		/*
+		 * The lock is already taken, let's check if the user wants
+		 * us to try again
+		 */
+		if (time_is_before_eq_jiffies(expire))
+			return -ETIMEDOUT;
+
+		/*
+		 * Allow platform-specific relax handlers to prevent
+		 * hogging the interconnect (no sleeping, though)
+		 */
+		if (hwlock->ops->relax)
+			hwlock->ops->relax(hwlock);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__hwspin_lock_timeout);
+
+/**
+ * __hwspin_unlock() - unlock a specific hwspinlock
+ * @hwlock: a previously-acquired hwspinlock which we want to unlock
+ * @mode: controls whether local interrupts needs to be restored or not
+ * @flags: previous caller's interrupt state to restore (if requested)
+ *
+ * This function will unlock a specific hwspinlock, enable preemption and
+ * (possibly) enable interrupts or restore their previous state.
+ * @hwlock must be already locked before calling this function: it is a bug
+ * to call unlock on a @hwlock that is already unlocked.
+ *
+ * The user decides whether local interrupts should be enabled or not, and
+ * if yes, whether he wants their previous state to be restored. It is up
+ * to the user to choose the appropriate @mode of operation, exactly the
+ * same way users decide between spin_unlock, spin_unlock_irq and
+ * spin_unlock_irqrestore.
+ *
+ * The function will never sleep.
+ */
+void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
+{
+	BUG_ON(!hwlock);
+	BUG_ON(!flags && mode == HWLOCK_IRQSTATE);
+
+	/*
+	 * We must make sure that memory operations (both reads and writes),
+	 * done before unlocking the hwspinlock, will not be reordered
+	 * after the lock is released.
+	 *
+	 * That's the purpose of this explicit memory barrier.
+	 *
+	 * Note: the memory barrier induced by the spin_unlock below is too
+	 * late; the other core is going to access memory soon after it will
+	 * take the hwspinlock, and by then we want to be sure our memory
+	 * operations are already observable.
+	 */
+	mb();
+
+	hwlock->ops->unlock(hwlock);
+
+	/* Undo the spin_trylock{_irq, _irqsave} called while locking */
+	if (mode == HWLOCK_IRQSTATE)
+		spin_unlock_irqrestore(&hwlock->lock, *flags);
+	else if (mode == HWLOCK_IRQ)
+		spin_unlock_irq(&hwlock->lock);
+	else
+		spin_unlock(&hwlock->lock);
+}
+EXPORT_SYMBOL_GPL(__hwspin_unlock);
+
+/**
+ * hwspin_lock_register() - register a new hw spinlock
+ * @hwlock: hwspinlock to register.
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to register a new hwspinlock instance.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context.
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_register(struct hwspinlock *hwlock)
+{
+	struct hwspinlock *tmp;
+	int ret;
+
+	if (!hwlock || !hwlock->ops ||
+		!hwlock->ops->trylock || !hwlock->ops->unlock) {
+		pr_err("invalid parameters\n");
+		return -EINVAL;
+	}
+
+	spin_lock_init(&hwlock->lock);
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock);
+	if (ret)
+		goto out;
+
+	/* mark this hwspinlock as available */
+	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+
+	/* self-sanity check which should never fail */
+	WARN_ON(tmp != hwlock);
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_register);
+
+/**
+ * hwspin_lock_unregister() - unregister an hw spinlock
+ * @id: index of the specific hwspinlock to unregister
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to unregister an existing (and unused) hwspinlock.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context.
+ *
+ * Returns the address of hwspinlock @id on success, or NULL on failure
+ */
+struct hwspinlock *hwspin_lock_unregister(unsigned int id)
+{
+	struct hwspinlock *hwlock = NULL;
+	int ret;
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* make sure the hwspinlock is not in use (tag is set) */
+	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
+	if (ret == 0) {
+		pr_err("hwspinlock %d still in use (or not present)\n", id);
+		goto out;
+	}
+
+	hwlock = radix_tree_delete(&hwspinlock_tree, id);
+	if (!hwlock) {
+		pr_err("failed to delete hwspinlock %d\n", id);
+		goto out;
+	}
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return hwlock;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
+
+/**
+ * __hwspin_lock_request() - tag an hwspinlock as used and power it up
+ *
+ * This is an internal function that prepares an hwspinlock instance
+ * before it is given to the user. The function assumes that
+ * hwspinlock_tree_lock is taken.
+ *
+ * Returns 0 or positive to indicate success, and a negative value to
+ * indicate an error (with the appropriate error code)
+ */
+static int __hwspin_lock_request(struct hwspinlock *hwlock)
+{
+	struct hwspinlock *tmp;
+	int ret;
+
+	/* prevent underlying implementation from being removed */
+	if (!try_module_get(hwlock->owner)) {
+		dev_err(hwlock->dev, "%s: can't get owner\n", __func__);
+		return -EINVAL;
+	}
+
+	/* notify PM core that power is now needed */
+	ret = pm_runtime_get_sync(hwlock->dev);
+	if (ret < 0) {
+		dev_err(hwlock->dev, "%s: can't power on device\n", __func__);
+		return ret;
+	}
+
+	/* mark hwspinlock as used, should not fail */
+	tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+
+	/* self-sanity check that should never fail */
+	WARN_ON(tmp != hwlock);
+
+	return ret;
+}
+
+/**
+ * hwspin_lock_get_id() - retrieve id number of a given hwspinlock
+ * @hwlock: a valid hwspinlock instance
+ *
+ * Returns the id number of a given @hwlock, or -EINVAL if @hwlock is invalid.
+ */
+int hwspin_lock_get_id(struct hwspinlock *hwlock)
+{
+	if (!hwlock) {
+		pr_err("invalid hwlock\n");
+		return -EINVAL;
+	}
+
+	return hwlock->id;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
+
+/**
+ * hwspin_lock_request() - request an hwspinlock
+ *
+ * This function should be called by users of the hwspinlock device,
+ * in order to dynamically assign them an unused hwspinlock.
+ * Usually the user of this lock will then have to communicate the lock's id
+ * to the remote core before it can be used for synchronization (to get the
+ * id of a given hwlock, use hwspin_lock_get_id()).
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context (simply because there is no use case for
+ * that yet).
+ *
+ * Returns the address of the assigned hwspinlock, or NULL on error
+ */
+struct hwspinlock *hwspin_lock_request(void)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* look for an unused lock */
+	ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock,
+						0, 1, HWSPINLOCK_UNUSED);
+	if (ret == 0) {
+		pr_warn("a free hwspinlock is not available\n");
+		hwlock = NULL;
+		goto out;
+	}
+
+	/* sanity check that should never fail */
+	WARN_ON(ret > 1);
+
+	/* mark as used and power up */
+	ret = __hwspin_lock_request(hwlock);
+	if (ret < 0)
+		hwlock = NULL;
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return hwlock;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_request);
+
+/**
+ * hwspin_lock_request_specific() - request for a specific hwspinlock
+ * @id: index of the specific hwspinlock that is requested
+ *
+ * This function should be called by users of the hwspinlock module,
+ * in order to assign them a specific hwspinlock.
+ * Usually early board code will be calling this function in order to
+ * reserve specific hwspinlock ids for predefined purposes.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context (simply because there is no use case for
+ * that yet).
+ *
+ * Returns the address of the assigned hwspinlock, or NULL on error
+ */
+struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* make sure this hwspinlock exists */
+	hwlock = radix_tree_lookup(&hwspinlock_tree, id);
+	if (!hwlock) {
+		pr_warn("hwspinlock %u does not exist\n", id);
+		goto out;
+	}
+
+	/* sanity check (this shouldn't happen) */
+	WARN_ON(hwlock->id != id);
+
+	/* make sure this hwspinlock is unused */
+	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
+	if (ret == 0) {
+		pr_warn("hwspinlock %u is already in use\n", id);
+		hwlock = NULL;
+		goto out;
+	}
+
+	/* mark as used and power up */
+	ret = __hwspin_lock_request(hwlock);
+	if (ret < 0)
+		hwlock = NULL;
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return hwlock;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
+
+/**
+ * hwspin_lock_free() - free a specific hwspinlock
+ * @hwlock: the specific hwspinlock to free
+ *
+ * This function mark @hwlock as free again.
+ * Should only be called with an @hwlock that was retrieved from
+ * an earlier call to omap_hwspin_lock_request{_specific}.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context (simply because there is no use case for
+ * that yet).
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_free(struct hwspinlock *hwlock)
+{
+	struct hwspinlock *tmp;
+	int ret;
+
+	if (!hwlock) {
+		pr_err("invalid hwlock\n");
+		return -EINVAL;
+	}
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* make sure the hwspinlock is used */
+	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+	if (ret == 1) {
+		dev_err(hwlock->dev, "%s: hwlock is already free\n", __func__);
+		dump_stack();
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* notify the underlying device that power is not needed */
+	ret = pm_runtime_put(hwlock->dev);
+	if (ret < 0)
+		goto out;
+
+	/* mark this hwspinlock as available */
+	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+
+	/* sanity check (this shouldn't happen) */
+	WARN_ON(tmp != hwlock);
+
+	module_put(hwlock->owner);
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_free);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware spinlock interface");
+MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h
new file mode 100644
index 0000000..69935e6
--- /dev/null
+++ b/drivers/hwspinlock/hwspinlock_internal.h
@@ -0,0 +1,61 @@
+/*
+ * Hardware spinlocks internal header
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#ifndef __HWSPINLOCK_HWSPINLOCK_H
+#define __HWSPINLOCK_HWSPINLOCK_H
+
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+/**
+ * struct hwspinlock_ops - platform-specific hwspinlock handlers
+ *
+ * @trylock: make a single attempt to take the lock. returns 0 on
+ *	     failure and true on success. may _not_ sleep.
+ * @unlock:  release the lock. always succeed. may _not_ sleep.
+ * @relax:   optional, platform-specific relax handler, called by hwspinlock
+ *	     core while spinning on a lock, between two successive
+ *	     invocations of @trylock. may _not_ sleep.
+ */
+struct hwspinlock_ops {
+	int (*trylock)(struct hwspinlock *lock);
+	void (*unlock)(struct hwspinlock *lock);
+	void (*relax)(struct hwspinlock *lock);
+};
+
+/**
+ * struct hwspinlock - this struct represents a single hwspinlock instance
+ *
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @id: a global, unique, system-wide, index of the lock.
+ * @lock: initialized and used by hwspinlock core
+ * @owner: underlying implementation module, used to maintain module ref count
+ *
+ * Note: currently simplicity was opted for, but later we can squeeze some
+ * memory bytes by grouping the dev, ops and owner members in a single
+ * per-platform struct, and have all hwspinlocks point at it.
+ */
+struct hwspinlock {
+	struct device *dev;
+	const struct hwspinlock_ops *ops;
+	int id;
+	spinlock_t lock;
+	struct module *owner;
+};
+
+#endif /* __HWSPINLOCK_HWSPINLOCK_H */
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
new file mode 100644
index 0000000..a8f0273
--- /dev/null
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -0,0 +1,231 @@
+/*
+ * OMAP hardware spinlock driver
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Simon Que <sque@ti.com>
+ *          Hari Kanigeri <h-kanigeri2@ti.com>
+ *          Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+#include <linux/platform_device.h>
+
+#include "hwspinlock_internal.h"
+
+/* Spinlock register offsets */
+#define SYSSTATUS_OFFSET		0x0014
+#define LOCK_BASE_OFFSET		0x0800
+
+#define SPINLOCK_NUMLOCKS_BIT_OFFSET	(24)
+
+/* Possible values of SPINLOCK_LOCK_REG */
+#define SPINLOCK_NOTTAKEN		(0)	/* free */
+#define SPINLOCK_TAKEN			(1)	/* locked */
+
+#define to_omap_hwspinlock(lock)	\
+	container_of(lock, struct omap_hwspinlock, lock)
+
+struct omap_hwspinlock {
+	struct hwspinlock lock;
+	void __iomem *addr;
+};
+
+struct omap_hwspinlock_state {
+	int num_locks;			/* Total number of locks in system */
+	void __iomem *io_base;		/* Mapped base address */
+};
+
+static int omap_hwspinlock_trylock(struct hwspinlock *lock)
+{
+	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+
+	/* attempt to acquire the lock by reading its value */
+	return (SPINLOCK_NOTTAKEN == readl(omap_lock->addr));
+}
+
+static void omap_hwspinlock_unlock(struct hwspinlock *lock)
+{
+	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+
+	/* release the lock by writing 0 to it */
+	writel(SPINLOCK_NOTTAKEN, omap_lock->addr);
+}
+
+/*
+ * relax the OMAP interconnect while spinning on it.
+ *
+ * The specs recommended that the retry delay time will be
+ * just over half of the time that a requester would be
+ * expected to hold the lock.
+ *
+ * The number below is taken from an hardware specs example,
+ * obviously it is somewhat arbitrary.
+ */
+static void omap_hwspinlock_relax(struct hwspinlock *lock)
+{
+	ndelay(50);
+}
+
+static const struct hwspinlock_ops omap_hwspinlock_ops = {
+	.trylock = omap_hwspinlock_trylock,
+	.unlock = omap_hwspinlock_unlock,
+	.relax = omap_hwspinlock_relax,
+};
+
+static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
+{
+	struct omap_hwspinlock *omap_lock;
+	struct omap_hwspinlock_state *state;
+	struct hwspinlock *lock;
+	struct resource *res;
+	void __iomem *io_base;
+	int i, ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	io_base = ioremap(res->start, resource_size(res));
+	if (!io_base) {
+		ret = -ENOMEM;
+		goto free_state;
+	}
+
+	/* Determine number of locks */
+	i = readl(io_base + SYSSTATUS_OFFSET);
+	i >>= SPINLOCK_NUMLOCKS_BIT_OFFSET;
+
+	/* one of the four lsb's must be set, and nothing else */
+	if (hweight_long(i & 0xf) != 1 || i > 8) {
+		ret = -EINVAL;
+		goto iounmap_base;
+	}
+
+	state->num_locks = i * 32;
+	state->io_base = io_base;
+
+	platform_set_drvdata(pdev, state);
+
+	/*
+	 * runtime PM will make sure the clock of this module is
+	 * enabled iff at least one lock is requested
+	 */
+	pm_runtime_enable(&pdev->dev);
+
+	for (i = 0; i < state->num_locks; i++) {
+		omap_lock = kzalloc(sizeof(*omap_lock), GFP_KERNEL);
+		if (!omap_lock) {
+			ret = -ENOMEM;
+			goto free_locks;
+		}
+
+		omap_lock->lock.dev = &pdev->dev;
+		omap_lock->lock.owner = THIS_MODULE;
+		omap_lock->lock.id = i;
+		omap_lock->lock.ops = &omap_hwspinlock_ops;
+		omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
+
+		ret = hwspin_lock_register(&omap_lock->lock);
+		if (ret) {
+			kfree(omap_lock);
+			goto free_locks;
+		}
+	}
+
+	return 0;
+
+free_locks:
+	while (--i >= 0) {
+		lock = hwspin_lock_unregister(i);
+		/* this should't happen, but let's give our best effort */
+		if (!lock) {
+			dev_err(&pdev->dev, "%s: cleanups failed\n", __func__);
+			continue;
+		}
+		omap_lock = to_omap_hwspinlock(lock);
+		kfree(omap_lock);
+	}
+	pm_runtime_disable(&pdev->dev);
+iounmap_base:
+	iounmap(io_base);
+free_state:
+	kfree(state);
+	return ret;
+}
+
+static int omap_hwspinlock_remove(struct platform_device *pdev)
+{
+	struct omap_hwspinlock_state *state = platform_get_drvdata(pdev);
+	struct hwspinlock *lock;
+	struct omap_hwspinlock *omap_lock;
+	int i;
+
+	for (i = 0; i < state->num_locks; i++) {
+		lock = hwspin_lock_unregister(i);
+		/* this shouldn't happen at this point. if it does, at least
+		 * don't continue with the remove */
+		if (!lock) {
+			dev_err(&pdev->dev, "%s: failed on %d\n", __func__, i);
+			return -EBUSY;
+		}
+
+		omap_lock = to_omap_hwspinlock(lock);
+		kfree(omap_lock);
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	iounmap(state->io_base);
+	kfree(state);
+
+	return 0;
+}
+
+static struct platform_driver omap_hwspinlock_driver = {
+	.probe		= omap_hwspinlock_probe,
+	.remove		= omap_hwspinlock_remove,
+	.driver		= {
+		.name	= "omap_hwspinlock",
+	},
+};
+
+static int __init omap_hwspinlock_init(void)
+{
+	return platform_driver_register(&omap_hwspinlock_driver);
+}
+/* board init code might need to reserve hwspinlocks for predefined purposes */
+postcore_initcall(omap_hwspinlock_init);
+
+static void __exit omap_hwspinlock_exit(void)
+{
+	platform_driver_unregister(&omap_hwspinlock_driver);
+}
+module_exit(omap_hwspinlock_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware spinlock driver for OMAP");
+MODULE_AUTHOR("Simon Que <sque@ti.com>");
+MODULE_AUTHOR("Hari Kanigeri <h-kanigeri2@ti.com>");
+MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 23ac61e..beee6b2 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o
 obj-y				+= algos/ busses/ muxes/
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
+CFLAGS_i2c-core.o := -Wno-deprecated-declarations
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 113505a..326652f 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -98,8 +98,9 @@ config I2C_I801
 	    EP80579 (Tolapai)
 	    ICH10
 	    5/3400 Series (PCH)
-	    Cougar Point (PCH)
+	    6 Series (PCH)
 	    Patsburg (PCH)
+	    DH89xxCC (PCH)
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-i801.
@@ -433,7 +434,7 @@ config I2C_IXP2000
 
 config I2C_MPC
 	tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
-	depends on PPC32
+	depends on PPC
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx,
@@ -452,6 +453,16 @@ config I2C_MV64XXX
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mv64xxx.
 
+config I2C_MXS
+	tristate "Freescale i.MX28 I2C interface"
+	depends on SOC_IMX28
+	help
+	  Say Y here if you want to use the I2C bus controller on
+	  the Freescale i.MX28 processors.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mxs.
+
 config I2C_NOMADIK
 	tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
 	depends on PLAT_NOMADIK
@@ -523,17 +534,31 @@ config I2C_PNX
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pnx.
 
+config I2C_PUV3
+	tristate "PKUnity v3 I2C bus support"
+	depends on UNICORE32 && ARCH_PUV3
+	select I2C_ALGOBIT
+	help
+	  This driver supports the I2C IP inside the PKUnity-v3 SoC.
+	  This I2C bus controller is under AMBA/AXI bus.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-puv3.
+
 config I2C_PXA
 	tristate "Intel PXA2XX I2C adapter"
-	depends on ARCH_PXA || ARCH_MMP
+	depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
 	help
 	  If you have devices in the PXA I2C bus, say yes to this option.
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pxa.
 
+config I2C_PXA_PCI
+	def_bool I2C_PXA && X86_32 && PCI && OF
+
 config I2C_PXA_SLAVE
 	bool "Intel PXA2XX I2C Slave comms support"
-	depends on I2C_PXA
+	depends on I2C_PXA && !X86_32
 	help
 	  Support I2C slave mode communications on the PXA I2C bus.  This
 	  is necessary for systems where the PXA may be a target on the
@@ -607,6 +632,13 @@ config I2C_STU300
 	  This driver can also be built as a module. If so, the module
 	  will be called i2c-stu300.
 
+config I2C_TEGRA
+	tristate "NVIDIA Tegra internal I2C controller"
+	depends on ARCH_TEGRA
+	help
+	  If you say yes to this option, support will be included for the
+	  I2C controller embedded in NVIDIA Tegra SOCs
+
 config I2C_VERSATILE
 	tristate "ARM Versatile/Realview I2C bus support"
 	depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
@@ -639,15 +671,28 @@ config I2C_XILINX
 	  will be called xilinx_i2c.
 
 config I2C_EG20T
-        tristate "PCH I2C of Intel EG20T"
-        depends on PCI
-        help
-          This driver is for PCH(Platform controller Hub) I2C of EG20T which
-          is an IOH(Input/Output Hub) for x86 embedded processor.
-          This driver can access PCH I2C bus device.
+	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH"
+	depends on PCI
+	help
+	  This driver is for PCH(Platform controller Hub) I2C of EG20T which
+	  is an IOH(Input/Output Hub) for x86 embedded processor.
+	  This driver can access PCH I2C bus device.
+
+	  This driver also supports the ML7213, a companion chip for the
+	  Atom E6xx series and compatible with the Intel EG20T PCH.
 
 comment "External I2C/SMBus adapter drivers"
 
+config I2C_DIOLAN_U2C
+	tristate "Diolan U2C-12 USB adapter"
+	depends on USB
+	help
+	  If you say yes to this option, support will be included for Diolan
+	  U2C-12, a USB to I2C interface.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-diolan-u2c.
+
 config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on PARPORT
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 9d2d0ec..e6cf294 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
+obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
 obj-$(CONFIG_I2C_NUC900)	+= i2c-nuc900.o
 obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
@@ -51,19 +52,23 @@ obj-$(CONFIG_I2C_PASEMI)	+= i2c-pasemi.o
 obj-$(CONFIG_I2C_PCA_PLATFORM)	+= i2c-pca-platform.o
 obj-$(CONFIG_I2C_PMCMSP)	+= i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
+obj-$(CONFIG_I2C_PUV3)		+= i2c-puv3.o
 obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
+obj-$(CONFIG_I2C_PXA_PCI)	+= i2c-pxa-pci.o
 obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
 obj-$(CONFIG_I2C_S6000)		+= i2c-s6000.o
 obj-$(CONFIG_I2C_SH7760)	+= i2c-sh7760.o
 obj-$(CONFIG_I2C_SH_MOBILE)	+= i2c-sh_mobile.o
 obj-$(CONFIG_I2C_SIMTEC)	+= i2c-simtec.o
 obj-$(CONFIG_I2C_STU300)	+= i2c-stu300.o
+obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
 obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
+obj-$(CONFIG_I2C_DIOLAN_U2C)	+= i2c-diolan-u2c.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_TAOS_EVM)	+= i2c-taos-evm.o
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
index f2de3be..3a20961 100644
--- a/drivers/i2c/busses/i2c-cpm.c
+++ b/drivers/i2c/busses/i2c-cpm.c
@@ -634,8 +634,7 @@ static void cpm_i2c_shutdown(struct cpm_i2c *cpm)
 		cpm_muram_free(cpm->i2c_addr);
 }
 
-static int __devinit cpm_i2c_probe(struct platform_device *ofdev,
-			 const struct of_device_id *match)
+static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
 {
 	int result, len;
 	struct cpm_i2c *cpm;
@@ -718,7 +717,7 @@ static const struct of_device_id cpm_i2c_match[] = {
 
 MODULE_DEVICE_TABLE(of, cpm_i2c_match);
 
-static struct of_platform_driver cpm_i2c_driver = {
+static struct platform_driver cpm_i2c_driver = {
 	.probe		= cpm_i2c_probe,
 	.remove		= __devexit_p(cpm_i2c_remove),
 	.driver = {
@@ -730,12 +729,12 @@ static struct of_platform_driver cpm_i2c_driver = {
 
 static int __init cpm_i2c_init(void)
 {
-	return of_register_platform_driver(&cpm_i2c_driver);
+	return platform_driver_register(&cpm_i2c_driver);
 }
 
 static void __exit cpm_i2c_exit(void)
 {
-	of_unregister_platform_driver(&cpm_i2c_driver);
+	platform_driver_unregister(&cpm_i2c_driver);
 }
 
 module_init(cpm_i2c_init);
diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c
new file mode 100644
index 0000000..7636671
--- /dev/null
+++ b/drivers/i2c/busses/i2c-diolan-u2c.c
@@ -0,0 +1,535 @@
+/*
+ * Driver for the Diolan u2c-12 USB-I2C adapter
+ *
+ * Copyright (c) 2010-2011 Ericsson AB
+ *
+ * Derived from:
+ *  i2c-tiny-usb.c
+ *  Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.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, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#define DRIVER_NAME		"i2c-diolan-u2c"
+
+#define USB_VENDOR_ID_DIOLAN		0x0abf
+#define USB_DEVICE_ID_DIOLAN_U2C	0x3370
+
+#define DIOLAN_OUT_EP		0x02
+#define DIOLAN_IN_EP		0x84
+
+/* commands via USB, must match command ids in the firmware */
+#define CMD_I2C_READ		0x01
+#define CMD_I2C_WRITE		0x02
+#define CMD_I2C_SCAN		0x03	/* Returns list of detected devices */
+#define CMD_I2C_RELEASE_SDA	0x04
+#define CMD_I2C_RELEASE_SCL	0x05
+#define CMD_I2C_DROP_SDA	0x06
+#define CMD_I2C_DROP_SCL	0x07
+#define CMD_I2C_READ_SDA	0x08
+#define CMD_I2C_READ_SCL	0x09
+#define CMD_GET_FW_VERSION	0x0a
+#define CMD_GET_SERIAL		0x0b
+#define CMD_I2C_START		0x0c
+#define CMD_I2C_STOP		0x0d
+#define CMD_I2C_REPEATED_START	0x0e
+#define CMD_I2C_PUT_BYTE	0x0f
+#define CMD_I2C_GET_BYTE	0x10
+#define CMD_I2C_PUT_ACK		0x11
+#define CMD_I2C_GET_ACK		0x12
+#define CMD_I2C_PUT_BYTE_ACK	0x13
+#define CMD_I2C_GET_BYTE_ACK	0x14
+#define CMD_I2C_SET_SPEED	0x1b
+#define CMD_I2C_GET_SPEED	0x1c
+#define CMD_I2C_SET_CLK_SYNC	0x24
+#define CMD_I2C_GET_CLK_SYNC	0x25
+#define CMD_I2C_SET_CLK_SYNC_TO	0x26
+#define CMD_I2C_GET_CLK_SYNC_TO	0x27
+
+#define RESP_OK			0x00
+#define RESP_FAILED		0x01
+#define RESP_BAD_MEMADDR	0x04
+#define RESP_DATA_ERR		0x05
+#define RESP_NOT_IMPLEMENTED	0x06
+#define RESP_NACK		0x07
+#define RESP_TIMEOUT		0x09
+
+#define U2C_I2C_SPEED_FAST	0	/* 400 kHz */
+#define U2C_I2C_SPEED_STD	1	/* 100 kHz */
+#define U2C_I2C_SPEED_2KHZ	242	/* 2 kHz, minimum speed */
+#define U2C_I2C_SPEED(f)	((DIV_ROUND_UP(1000000, (f)) - 10) / 2 + 1)
+
+#define U2C_I2C_FREQ_FAST	400000
+#define U2C_I2C_FREQ_STD	100000
+#define U2C_I2C_FREQ(s)		(1000000 / (2 * (s - 1) + 10))
+
+#define DIOLAN_USB_TIMEOUT	100	/* in ms */
+#define DIOLAN_SYNC_TIMEOUT	20	/* in ms */
+
+#define DIOLAN_OUTBUF_LEN	128
+#define DIOLAN_FLUSH_LEN	(DIOLAN_OUTBUF_LEN - 4)
+#define DIOLAN_INBUF_LEN	256	/* Maximum supported receive length */
+
+/* Structure to hold all of our device specific stuff */
+struct i2c_diolan_u2c {
+	u8 obuffer[DIOLAN_OUTBUF_LEN];	/* output buffer */
+	u8 ibuffer[DIOLAN_INBUF_LEN];	/* input buffer */
+	struct usb_device *usb_dev;	/* the usb device for this device */
+	struct usb_interface *interface;/* the interface for this device */
+	struct i2c_adapter adapter;	/* i2c related things */
+	int olen;			/* Output buffer length */
+	int ocount;			/* Number of enqueued messages */
+};
+
+static uint frequency = U2C_I2C_FREQ_STD;	/* I2C clock frequency in Hz */
+
+module_param(frequency, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz");
+
+/* usb layer */
+
+/* Send command to device, and get response. */
+static int diolan_usb_transfer(struct i2c_diolan_u2c *dev)
+{
+	int ret = 0;
+	int actual;
+	int i;
+
+	if (!dev->olen || !dev->ocount)
+		return -EINVAL;
+
+	ret = usb_bulk_msg(dev->usb_dev,
+			   usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP),
+			   dev->obuffer, dev->olen, &actual,
+			   DIOLAN_USB_TIMEOUT);
+	if (!ret) {
+		for (i = 0; i < dev->ocount; i++) {
+			int tmpret;
+
+			tmpret = usb_bulk_msg(dev->usb_dev,
+					      usb_rcvbulkpipe(dev->usb_dev,
+							      DIOLAN_IN_EP),
+					      dev->ibuffer,
+					      sizeof(dev->ibuffer), &actual,
+					      DIOLAN_USB_TIMEOUT);
+			/*
+			 * Stop command processing if a previous command
+			 * returned an error.
+			 * Note that we still need to retrieve all messages.
+			 */
+			if (ret < 0)
+				continue;
+			ret = tmpret;
+			if (ret == 0 && actual > 0) {
+				switch (dev->ibuffer[actual - 1]) {
+				case RESP_NACK:
+					/*
+					 * Return ENXIO if NACK was received as
+					 * response to the address phase,
+					 * EIO otherwise
+					 */
+					ret = i == 1 ? -ENXIO : -EIO;
+					break;
+				case RESP_TIMEOUT:
+					ret = -ETIMEDOUT;
+					break;
+				case RESP_OK:
+					/* strip off return code */
+					ret = actual - 1;
+					break;
+				default:
+					ret = -EIO;
+					break;
+				}
+			}
+		}
+	}
+	dev->olen = 0;
+	dev->ocount = 0;
+	return ret;
+}
+
+static int diolan_write_cmd(struct i2c_diolan_u2c *dev, bool flush)
+{
+	if (flush || dev->olen >= DIOLAN_FLUSH_LEN)
+		return diolan_usb_transfer(dev);
+	return 0;
+}
+
+/* Send command (no data) */
+static int diolan_usb_cmd(struct i2c_diolan_u2c *dev, u8 command, bool flush)
+{
+	dev->obuffer[dev->olen++] = command;
+	dev->ocount++;
+	return diolan_write_cmd(dev, flush);
+}
+
+/* Send command with one byte of data */
+static int diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data,
+			       bool flush)
+{
+	dev->obuffer[dev->olen++] = command;
+	dev->obuffer[dev->olen++] = data;
+	dev->ocount++;
+	return diolan_write_cmd(dev, flush);
+}
+
+/* Send command with two bytes of data */
+static int diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1,
+				u8 d2, bool flush)
+{
+	dev->obuffer[dev->olen++] = command;
+	dev->obuffer[dev->olen++] = d1;
+	dev->obuffer[dev->olen++] = d2;
+	dev->ocount++;
+	return diolan_write_cmd(dev, flush);
+}
+
+/*
+ * Flush input queue.
+ * If we don't do this at startup and the controller has queued up
+ * messages which were not retrieved, it will stop responding
+ * at some point.
+ */
+static void diolan_flush_input(struct i2c_diolan_u2c *dev)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		int actual = 0;
+		int ret;
+
+		ret = usb_bulk_msg(dev->usb_dev,
+				   usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP),
+				   dev->ibuffer, sizeof(dev->ibuffer), &actual,
+				   DIOLAN_USB_TIMEOUT);
+		if (ret < 0 || actual == 0)
+			break;
+	}
+	if (i == 10)
+		dev_err(&dev->interface->dev, "Failed to flush input buffer\n");
+}
+
+static int diolan_i2c_start(struct i2c_diolan_u2c *dev)
+{
+	return diolan_usb_cmd(dev, CMD_I2C_START, false);
+}
+
+static int diolan_i2c_repeated_start(struct i2c_diolan_u2c *dev)
+{
+	return diolan_usb_cmd(dev, CMD_I2C_REPEATED_START, false);
+}
+
+static int diolan_i2c_stop(struct i2c_diolan_u2c *dev)
+{
+	return diolan_usb_cmd(dev, CMD_I2C_STOP, true);
+}
+
+static int diolan_i2c_get_byte_ack(struct i2c_diolan_u2c *dev, bool ack,
+				   u8 *byte)
+{
+	int ret;
+
+	ret = diolan_usb_cmd_data(dev, CMD_I2C_GET_BYTE_ACK, ack, true);
+	if (ret > 0)
+		*byte = dev->ibuffer[0];
+	else if (ret == 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int diolan_i2c_put_byte_ack(struct i2c_diolan_u2c *dev, u8 byte)
+{
+	return diolan_usb_cmd_data(dev, CMD_I2C_PUT_BYTE_ACK, byte, false);
+}
+
+static int diolan_set_speed(struct i2c_diolan_u2c *dev, u8 speed)
+{
+	return diolan_usb_cmd_data(dev, CMD_I2C_SET_SPEED, speed, true);
+}
+
+/* Enable or disable clock synchronization (stretching) */
+static int diolan_set_clock_synch(struct i2c_diolan_u2c *dev, bool enable)
+{
+	return diolan_usb_cmd_data(dev, CMD_I2C_SET_CLK_SYNC, enable, true);
+}
+
+/* Set clock synchronization timeout in ms */
+static int diolan_set_clock_synch_timeout(struct i2c_diolan_u2c *dev, int ms)
+{
+	int to_val = ms * 10;
+
+	return diolan_usb_cmd_data2(dev, CMD_I2C_SET_CLK_SYNC_TO,
+				    to_val & 0xff, (to_val >> 8) & 0xff, true);
+}
+
+static void diolan_fw_version(struct i2c_diolan_u2c *dev)
+{
+	int ret;
+
+	ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true);
+	if (ret >= 2)
+		dev_info(&dev->interface->dev,
+			 "Diolan U2C firmware version %u.%u\n",
+			 (unsigned int)dev->ibuffer[0],
+			 (unsigned int)dev->ibuffer[1]);
+}
+
+static void diolan_get_serial(struct i2c_diolan_u2c *dev)
+{
+	int ret;
+	u32 serial;
+
+	ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true);
+	if (ret >= 4) {
+		serial = le32_to_cpu(*(u32 *)dev->ibuffer);
+		dev_info(&dev->interface->dev,
+			 "Diolan U2C serial number %u\n", serial);
+	}
+}
+
+static int diolan_init(struct i2c_diolan_u2c *dev)
+{
+	int speed, ret;
+
+	if (frequency >= 200000) {
+		speed = U2C_I2C_SPEED_FAST;
+		frequency = U2C_I2C_FREQ_FAST;
+	} else if (frequency >= 100000 || frequency == 0) {
+		speed = U2C_I2C_SPEED_STD;
+		frequency = U2C_I2C_FREQ_STD;
+	} else {
+		speed = U2C_I2C_SPEED(frequency);
+		if (speed > U2C_I2C_SPEED_2KHZ)
+			speed = U2C_I2C_SPEED_2KHZ;
+		frequency = U2C_I2C_FREQ(speed);
+	}
+
+	dev_info(&dev->interface->dev,
+		 "Diolan U2C at USB bus %03d address %03d speed %d Hz\n",
+		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency);
+
+	diolan_flush_input(dev);
+	diolan_fw_version(dev);
+	diolan_get_serial(dev);
+
+	/* Set I2C speed */
+	ret = diolan_set_speed(dev, speed);
+	if (ret < 0)
+		return ret;
+
+	/* Configure I2C clock synchronization */
+	ret = diolan_set_clock_synch(dev, speed != U2C_I2C_SPEED_FAST);
+	if (ret < 0)
+		return ret;
+
+	if (speed != U2C_I2C_SPEED_FAST)
+		ret = diolan_set_clock_synch_timeout(dev, DIOLAN_SYNC_TIMEOUT);
+
+	return ret;
+}
+
+/* i2c layer */
+
+static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
+			   int num)
+{
+	struct i2c_diolan_u2c *dev = i2c_get_adapdata(adapter);
+	struct i2c_msg *pmsg;
+	int i, j;
+	int ret, sret;
+
+	ret = diolan_i2c_start(dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < num; i++) {
+		pmsg = &msgs[i];
+		if (i) {
+			ret = diolan_i2c_repeated_start(dev);
+			if (ret < 0)
+				goto abort;
+		}
+		if (pmsg->flags & I2C_M_RD) {
+			ret =
+			    diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1);
+			if (ret < 0)
+				goto abort;
+			for (j = 0; j < pmsg->len; j++) {
+				u8 byte;
+				bool ack = j < pmsg->len - 1;
+
+				/*
+				 * Don't send NACK if this is the first byte
+				 * of a SMBUS_BLOCK message.
+				 */
+				if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN))
+					ack = true;
+
+				ret = diolan_i2c_get_byte_ack(dev, ack, &byte);
+				if (ret < 0)
+					goto abort;
+				/*
+				 * Adjust count if first received byte is length
+				 */
+				if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) {
+					if (byte == 0
+					    || byte > I2C_SMBUS_BLOCK_MAX) {
+						ret = -EPROTO;
+						goto abort;
+					}
+					pmsg->len += byte;
+				}
+				pmsg->buf[j] = byte;
+			}
+		} else {
+			ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1);
+			if (ret < 0)
+				goto abort;
+			for (j = 0; j < pmsg->len; j++) {
+				ret = diolan_i2c_put_byte_ack(dev,
+							      pmsg->buf[j]);
+				if (ret < 0)
+					goto abort;
+			}
+		}
+	}
+abort:
+	sret = diolan_i2c_stop(dev);
+	if (sret < 0 && ret >= 0)
+		ret = sret;
+	return ret;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 diolan_usb_func(struct i2c_adapter *a)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
+}
+
+static const struct i2c_algorithm diolan_usb_algorithm = {
+	.master_xfer = diolan_usb_xfer,
+	.functionality = diolan_usb_func,
+};
+
+/* device layer */
+
+static const struct usb_device_id diolan_u2c_table[] = {
+	{ USB_DEVICE(USB_VENDOR_ID_DIOLAN, USB_DEVICE_ID_DIOLAN_U2C) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, diolan_u2c_table);
+
+static void diolan_u2c_free(struct i2c_diolan_u2c *dev)
+{
+	usb_put_dev(dev->usb_dev);
+	kfree(dev);
+}
+
+static int diolan_u2c_probe(struct usb_interface *interface,
+			    const struct usb_device_id *id)
+{
+	struct i2c_diolan_u2c *dev;
+	int ret;
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "no memory for device state\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
+	dev->interface = interface;
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	/* setup i2c adapter description */
+	dev->adapter.owner = THIS_MODULE;
+	dev->adapter.class = I2C_CLASS_HWMON;
+	dev->adapter.algo = &diolan_usb_algorithm;
+	i2c_set_adapdata(&dev->adapter, dev);
+	snprintf(dev->adapter.name, sizeof(dev->adapter.name),
+		 DRIVER_NAME " at bus %03d device %03d",
+		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
+
+	dev->adapter.dev.parent = &dev->interface->dev;
+
+	/* initialize diolan i2c interface */
+	ret = diolan_init(dev);
+	if (ret < 0) {
+		dev_err(&interface->dev, "failed to initialize adapter\n");
+		goto error_free;
+	}
+
+	/* and finally attach to i2c layer */
+	ret = i2c_add_adapter(&dev->adapter);
+	if (ret < 0) {
+		dev_err(&interface->dev, "failed to add I2C adapter\n");
+		goto error_free;
+	}
+
+	dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
+
+	return 0;
+
+error_free:
+	usb_set_intfdata(interface, NULL);
+	diolan_u2c_free(dev);
+error:
+	return ret;
+}
+
+static void diolan_u2c_disconnect(struct usb_interface *interface)
+{
+	struct i2c_diolan_u2c *dev = usb_get_intfdata(interface);
+
+	i2c_del_adapter(&dev->adapter);
+	usb_set_intfdata(interface, NULL);
+	diolan_u2c_free(dev);
+
+	dev_dbg(&interface->dev, "disconnected\n");
+}
+
+static struct usb_driver diolan_u2c_driver = {
+	.name = DRIVER_NAME,
+	.probe = diolan_u2c_probe,
+	.disconnect = diolan_u2c_disconnect,
+	.id_table = diolan_u2c_table,
+};
+
+static int __init diolan_u2c_init(void)
+{
+	/* register this driver with the USB subsystem */
+	return usb_register(&diolan_u2c_driver);
+}
+
+static void __exit diolan_u2c_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&diolan_u2c_driver);
+}
+
+module_init(diolan_u2c_init);
+module_exit(diolan_u2c_exit);
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION(DRIVER_NAME " driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 50ea1f4..878a120 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -132,6 +132,13 @@
 #define pch_pci_dbg(pdev, fmt, arg...)  \
 	dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg)
 
+/*
+Set the number of I2C instance max
+Intel EG20T PCH :		1ch
+OKI SEMICONDUCTOR ML7213 IOH :	2ch
+*/
+#define PCH_I2C_MAX_DEV			2
+
 /**
  * struct i2c_algo_pch_data - for I2C driver functionalities
  * @pch_adapter:		stores the reference to i2c_adapter structure
@@ -156,12 +163,14 @@ struct i2c_algo_pch_data {
  * @pch_data:		stores a list of i2c_algo_pch_data
  * @pch_i2c_suspended:	specifies whether the system is suspended or not
  *			perhaps with more lines and words.
+ * @ch_num:		specifies the number of i2c instance
  *
  * pch_data has as many elements as maximum I2C channels
  */
 struct adapter_info {
-	struct i2c_algo_pch_data pch_data;
+	struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV];
 	bool pch_i2c_suspended;
+	int ch_num;
 };
 
 
@@ -170,8 +179,13 @@ static int pch_clk = 50000;	/* specifies I2C clock speed in KHz */
 static wait_queue_head_t pch_event;
 static DEFINE_MUTEX(pch_mutex);
 
+/* Definition for ML7213 by OKI SEMICONDUCTOR */
+#define PCI_VENDOR_ID_ROHM		0x10DB
+#define PCI_DEVICE_ID_ML7213_I2C	0x802D
+
 static struct pci_device_id __devinitdata pch_pcidev_id[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_I2C)},
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C),   1, },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
 	{0,}
 };
 
@@ -212,8 +226,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
 	/* Initialize I2C registers */
 	iowrite32(0x21, p + PCH_I2CNF);
 
-	pch_setbit(adap->pch_base_address, PCH_I2CCTL,
-			  PCH_I2CCTL_I2CMEN);
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN);
 
 	if (pch_i2c_speed != 400)
 		pch_i2c_speed = 100;
@@ -255,7 +268,7 @@ static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
  * @timeout:	waiting time counter (us).
  */
 static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
-				 s32 timeout)
+				     s32 timeout)
 {
 	void __iomem *p = adap->pch_base_address;
 
@@ -475,8 +488,8 @@ static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap)
  * @last:	specifies whether last message or not.
  * @first:	specifies whether first message or not.
  */
-s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
-		  u32 last, u32 first)
+static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+			     u32 last, u32 first)
 {
 	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
 
@@ -569,10 +582,10 @@ s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 }
 
 /**
- * pch_i2c_cb_ch0() - Interrupt handler Call back function
+ * pch_i2c_cb() - Interrupt handler Call back function
  * @adap:	Pointer to struct i2c_algo_pch_data.
  */
-static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap)
+static void pch_i2c_cb(struct i2c_algo_pch_data *adap)
 {
 	u32 sts;
 	void __iomem *p = adap->pch_base_address;
@@ -600,24 +613,30 @@ static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap)
  */
 static irqreturn_t pch_i2c_handler(int irq, void *pData)
 {
-	s32 reg_val;
-
-	struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData;
-	void __iomem *p = adap_data->pch_base_address;
-	u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE);
-
-	if (mode != NORMAL_MODE) {
-		pch_err(adap_data, "I2C mode is not supported\n");
-		return IRQ_NONE;
+	u32 reg_val;
+	int flag;
+	int i;
+	struct adapter_info *adap_info = pData;
+	void __iomem *p;
+	u32 mode;
+
+	for (i = 0, flag = 0; i < adap_info->ch_num; i++) {
+		p = adap_info->pch_data[i].pch_base_address;
+		mode = ioread32(p + PCH_I2CMOD);
+		mode &= BUFFER_MODE | EEPROM_SR_MODE;
+		if (mode != NORMAL_MODE) {
+			pch_err(adap_info->pch_data,
+				"I2C-%d mode(%d) is not supported\n", mode, i);
+			continue;
+		}
+		reg_val = ioread32(p + PCH_I2CSR);
+		if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) {
+			pch_i2c_cb(&adap_info->pch_data[i]);
+			flag = 1;
+		}
 	}
 
-	reg_val = ioread32(p + PCH_I2CSR);
-	if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT))
-		pch_i2c_cb_ch0(adap_data);
-	else
-		return IRQ_NONE;
-
-	return IRQ_HANDLED;
+	return flag ? IRQ_HANDLED : IRQ_NONE;
 }
 
 /**
@@ -627,7 +646,7 @@ static irqreturn_t pch_i2c_handler(int irq, void *pData)
  * @num:	number of messages.
  */
 static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
-		    struct i2c_msg *msgs, s32 num)
+			struct i2c_msg *msgs, s32 num)
 {
 	struct i2c_msg *pmsg;
 	u32 i = 0;
@@ -710,11 +729,13 @@ static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap)
 }
 
 static int __devinit pch_i2c_probe(struct pci_dev *pdev,
-			       const struct pci_device_id *id)
+				   const struct pci_device_id *id)
 {
 	void __iomem *base_addr;
-	s32 ret;
+	int ret;
+	int i, j;
 	struct adapter_info *adap_info;
+	struct i2c_adapter *pch_adap;
 
 	pch_pci_dbg(pdev, "Entered.\n");
 
@@ -744,44 +765,48 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
 		goto err_pci_iomap;
 	}
 
-	adap_info->pch_i2c_suspended = false;
+	/* Set the number of I2C channel instance */
+	adap_info->ch_num = id->driver_data;
 
-	adap_info->pch_data.p_adapter_info = adap_info;
+	for (i = 0; i < adap_info->ch_num; i++) {
+		pch_adap = &adap_info->pch_data[i].pch_adapter;
+		adap_info->pch_i2c_suspended = false;
 
-	adap_info->pch_data.pch_adapter.owner = THIS_MODULE;
-	adap_info->pch_data.pch_adapter.class = I2C_CLASS_HWMON;
-	strcpy(adap_info->pch_data.pch_adapter.name, KBUILD_MODNAME);
-	adap_info->pch_data.pch_adapter.algo = &pch_algorithm;
-	adap_info->pch_data.pch_adapter.algo_data =
-						&adap_info->pch_data;
+		adap_info->pch_data[i].p_adapter_info = adap_info;
 
-	/* (i * 0x80) + base_addr; */
-	adap_info->pch_data.pch_base_address = base_addr;
+		pch_adap->owner = THIS_MODULE;
+		pch_adap->class = I2C_CLASS_HWMON;
+		strcpy(pch_adap->name, KBUILD_MODNAME);
+		pch_adap->algo = &pch_algorithm;
+		pch_adap->algo_data = &adap_info->pch_data[i];
 
-	adap_info->pch_data.pch_adapter.dev.parent = &pdev->dev;
+		/* base_addr + offset; */
+		adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
 
-	ret = i2c_add_adapter(&(adap_info->pch_data.pch_adapter));
+		pch_adap->dev.parent = &pdev->dev;
 
-	if (ret) {
-		pch_pci_err(pdev, "i2c_add_adapter FAILED\n");
-		goto err_i2c_add_adapter;
-	}
+		ret = i2c_add_adapter(pch_adap);
+		if (ret) {
+			pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
+			goto err_i2c_add_adapter;
+		}
 
-	pch_i2c_init(&adap_info->pch_data);
+		pch_i2c_init(&adap_info->pch_data[i]);
+	}
 	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
-		  KBUILD_MODNAME, &adap_info->pch_data);
+		  KBUILD_MODNAME, adap_info);
 	if (ret) {
 		pch_pci_err(pdev, "request_irq FAILED\n");
-		goto err_request_irq;
+		goto err_i2c_add_adapter;
 	}
 
 	pci_set_drvdata(pdev, adap_info);
 	pch_pci_dbg(pdev, "returns %d.\n", ret);
 	return 0;
 
-err_request_irq:
-	i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
 err_i2c_add_adapter:
+	for (j = 0; j < i; j++)
+		i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
 	pci_iounmap(pdev, base_addr);
 err_pci_iomap:
 	pci_release_regions(pdev);
@@ -794,17 +819,22 @@ err_pci_enable:
 
 static void __devexit pch_i2c_remove(struct pci_dev *pdev)
 {
+	int i;
 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
 
-	pch_i2c_disbl_int(&adap_info->pch_data);
-	free_irq(pdev->irq, &adap_info->pch_data);
-	i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
+	free_irq(pdev->irq, adap_info);
 
-	if (adap_info->pch_data.pch_base_address) {
-		pci_iounmap(pdev, adap_info->pch_data.pch_base_address);
-		adap_info->pch_data.pch_base_address = 0;
+	for (i = 0; i < adap_info->ch_num; i++) {
+		pch_i2c_disbl_int(&adap_info->pch_data[i]);
+		i2c_del_adapter(&adap_info->pch_data[i].pch_adapter);
 	}
 
+	if (adap_info->pch_data[0].pch_base_address)
+		pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
+
+	for (i = 0; i < adap_info->ch_num; i++)
+		adap_info->pch_data[i].pch_base_address = 0;
+
 	pci_set_drvdata(pdev, NULL);
 
 	pci_release_regions(pdev);
@@ -817,17 +847,22 @@ static void __devexit pch_i2c_remove(struct pci_dev *pdev)
 static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	int ret;
+	int i;
 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
-	void __iomem *p = adap_info->pch_data.pch_base_address;
+	void __iomem *p = adap_info->pch_data[0].pch_base_address;
 
 	adap_info->pch_i2c_suspended = true;
 
-	while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) {
-		/* Wait until all channel transfers are completed */
-		msleep(20);
+	for (i = 0; i < adap_info->ch_num; i++) {
+		while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) {
+			/* Wait until all channel transfers are completed */
+			msleep(20);
+		}
 	}
+
 	/* Disable the i2c interrupts */
-	pch_i2c_disbl_int(&adap_info->pch_data);
+	for (i = 0; i < adap_info->ch_num; i++)
+		pch_i2c_disbl_int(&adap_info->pch_data[i]);
 
 	pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x "
 		"invoked function pch_i2c_disbl_int successfully\n",
@@ -850,6 +885,7 @@ static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
 
 static int pch_i2c_resume(struct pci_dev *pdev)
 {
+	int i;
 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
 
 	pci_set_power_state(pdev, PCI_D0);
@@ -862,7 +898,8 @@ static int pch_i2c_resume(struct pci_dev *pdev)
 
 	pci_enable_wake(pdev, PCI_D3hot, 0);
 
-	pch_i2c_init(&adap_info->pch_data);
+	for (i = 0; i < adap_info->ch_num; i++)
+		pch_i2c_init(&adap_info->pch_data[i]);
 
 	adap_info->pch_i2c_suspended = false;
 
@@ -894,7 +931,7 @@ static void __exit pch_pci_exit(void)
 }
 module_exit(pch_pci_exit);
 
-MODULE_DESCRIPTION("PCH I2C PCI Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
 module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 7979aef7e..ed2e0c5 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -44,11 +44,12 @@
   ICH10                 0x3a30     32     hard     yes     yes     yes
   ICH10                 0x3a60     32     hard     yes     yes     yes
   5/3400 Series (PCH)   0x3b30     32     hard     yes     yes     yes
-  Cougar Point (PCH)    0x1c22     32     hard     yes     yes     yes
+  6 Series (PCH)        0x1c22     32     hard     yes     yes     yes
   Patsburg (PCH)        0x1d22     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d70     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d71     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
+  DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
@@ -621,6 +622,7 @@ static const struct pci_device_id i801_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
 	{ 0, }
 };
 
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 6e3c382..e4f88dc 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -691,8 +691,7 @@ static int __devinit iic_request_irq(struct platform_device *ofdev,
 /*
  * Register single IIC interface
  */
-static int __devinit iic_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit iic_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct ibm_iic_private *dev;
@@ -806,7 +805,7 @@ static const struct of_device_id ibm_iic_match[] = {
 	{}
 };
 
-static struct of_platform_driver ibm_iic_driver = {
+static struct platform_driver ibm_iic_driver = {
 	.driver = {
 		.name = "ibm-iic",
 		.owner = THIS_MODULE,
@@ -818,12 +817,12 @@ static struct of_platform_driver ibm_iic_driver = {
 
 static int __init iic_init(void)
 {
-	return of_register_platform_driver(&ibm_iic_driver);
+	return platform_driver_register(&ibm_iic_driver);
 }
 
 static void __exit iic_exit(void)
 {
-	of_unregister_platform_driver(&ibm_iic_driver);
+	platform_driver_unregister(&ibm_iic_driver);
 }
 
 module_init(iic_init);
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index b74e6dc..75b984c 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -560,8 +560,7 @@ static struct i2c_adapter mpc_ops = {
 	.timeout = HZ,
 };
 
-static int __devinit fsl_i2c_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static int __devinit fsl_i2c_probe(struct platform_device *op)
 {
 	struct mpc_i2c *i2c;
 	const u32 *prop;
@@ -569,6 +568,9 @@ static int __devinit fsl_i2c_probe(struct platform_device *op,
 	int result = 0;
 	int plen;
 
+	if (!op->dev.of_match)
+		return -EINVAL;
+
 	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
 	if (!i2c)
 		return -ENOMEM;
@@ -603,8 +605,8 @@ static int __devinit fsl_i2c_probe(struct platform_device *op,
 			clock = *prop;
 	}
 
-	if (match->data) {
-		struct mpc_i2c_data *data = match->data;
+	if (op->dev.of_match->data) {
+		struct mpc_i2c_data *data = op->dev.of_match->data;
 		data->setup(op->dev.of_node, i2c, clock, data->prescaler);
 	} else {
 		/* Backwards compatibility */
@@ -700,7 +702,7 @@ static const struct of_device_id mpc_i2c_of_match[] = {
 MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
 
 /* Structure for a device driver */
-static struct of_platform_driver mpc_i2c_driver = {
+static struct platform_driver mpc_i2c_driver = {
 	.probe		= fsl_i2c_probe,
 	.remove		= __devexit_p(fsl_i2c_remove),
 	.driver = {
@@ -712,18 +714,12 @@ static struct of_platform_driver mpc_i2c_driver = {
 
 static int __init fsl_i2c_init(void)
 {
-	int rv;
-
-	rv = of_register_platform_driver(&mpc_i2c_driver);
-	if (rv)
-		printk(KERN_ERR DRV_NAME
-		       " of_register_platform_driver failed (%i)\n", rv);
-	return rv;
+	return platform_driver_register(&mpc_i2c_driver);
 }
 
 static void __exit fsl_i2c_exit(void)
 {
-	of_unregister_platform_driver(&mpc_i2c_driver);
+	platform_driver_unregister(&mpc_i2c_driver);
 }
 
 module_init(fsl_i2c_init);
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
new file mode 100644
index 0000000..caf96dc
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -0,0 +1,412 @@
+/*
+ * Freescale MXS I2C bus driver
+ *
+ * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ *
+ * based on a (non-working) driver which was:
+ *
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * TODO: add dma-support if platform-support for it is available
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+
+#define DRIVER_NAME "mxs-i2c"
+
+#define MXS_I2C_CTRL0		(0x00)
+#define MXS_I2C_CTRL0_SET	(0x04)
+
+#define MXS_I2C_CTRL0_SFTRST			0x80000000
+#define MXS_I2C_CTRL0_SEND_NAK_ON_LAST		0x02000000
+#define MXS_I2C_CTRL0_RETAIN_CLOCK		0x00200000
+#define MXS_I2C_CTRL0_POST_SEND_STOP		0x00100000
+#define MXS_I2C_CTRL0_PRE_SEND_START		0x00080000
+#define MXS_I2C_CTRL0_MASTER_MODE		0x00020000
+#define MXS_I2C_CTRL0_DIRECTION			0x00010000
+#define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
+
+#define MXS_I2C_CTRL1		(0x40)
+#define MXS_I2C_CTRL1_SET	(0x44)
+#define MXS_I2C_CTRL1_CLR	(0x48)
+
+#define MXS_I2C_CTRL1_BUS_FREE_IRQ		0x80
+#define MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ	0x40
+#define MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ		0x20
+#define MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	0x10
+#define MXS_I2C_CTRL1_EARLY_TERM_IRQ		0x08
+#define MXS_I2C_CTRL1_MASTER_LOSS_IRQ		0x04
+#define MXS_I2C_CTRL1_SLAVE_STOP_IRQ		0x02
+#define MXS_I2C_CTRL1_SLAVE_IRQ			0x01
+
+#define MXS_I2C_IRQ_MASK	(MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | \
+				 MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ | \
+				 MXS_I2C_CTRL1_EARLY_TERM_IRQ | \
+				 MXS_I2C_CTRL1_MASTER_LOSS_IRQ | \
+				 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
+				 MXS_I2C_CTRL1_SLAVE_IRQ)
+
+#define MXS_I2C_QUEUECTRL	(0x60)
+#define MXS_I2C_QUEUECTRL_SET	(0x64)
+#define MXS_I2C_QUEUECTRL_CLR	(0x68)
+
+#define MXS_I2C_QUEUECTRL_QUEUE_RUN		0x20
+#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE	0x04
+
+#define MXS_I2C_QUEUESTAT	(0x70)
+#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000
+
+#define MXS_I2C_QUEUECMD	(0x80)
+
+#define MXS_I2C_QUEUEDATA	(0x90)
+
+#define MXS_I2C_DATA		(0xa0)
+
+
+#define MXS_CMD_I2C_SELECT	(MXS_I2C_CTRL0_RETAIN_CLOCK |	\
+				 MXS_I2C_CTRL0_PRE_SEND_START |	\
+				 MXS_I2C_CTRL0_MASTER_MODE |	\
+				 MXS_I2C_CTRL0_DIRECTION |	\
+				 MXS_I2C_CTRL0_XFER_COUNT(1))
+
+#define MXS_CMD_I2C_WRITE	(MXS_I2C_CTRL0_PRE_SEND_START |	\
+				 MXS_I2C_CTRL0_MASTER_MODE |	\
+				 MXS_I2C_CTRL0_DIRECTION)
+
+#define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
+				 MXS_I2C_CTRL0_MASTER_MODE)
+
+/**
+ * struct mxs_i2c_dev - per device, private MXS-I2C data
+ *
+ * @dev: driver model device node
+ * @regs: IO registers pointer
+ * @cmd_complete: completion object for transaction wait
+ * @cmd_err: error code for last transaction
+ * @adapter: i2c subsystem adapter node
+ */
+struct mxs_i2c_dev {
+	struct device *dev;
+	void __iomem *regs;
+	struct completion cmd_complete;
+	u32 cmd_err;
+	struct i2c_adapter adapter;
+};
+
+/*
+ * TODO: check if calls to here are really needed. If not, we could get rid of
+ * mxs_reset_block and the mach-dependency. Needs an I2C analyzer, probably.
+ */
+static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
+{
+	mxs_reset_block(i2c->regs);
+	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
+	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+			i2c->regs + MXS_I2C_QUEUECTRL_SET);
+}
+
+static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
+					int flags)
+{
+	u32 data;
+
+	writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
+
+	data = (addr << 1) | I2C_SMBUS_READ;
+	writel(data, i2c->regs + MXS_I2C_DATA);
+
+	data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
+	writel(data, i2c->regs + MXS_I2C_QUEUECMD);
+}
+
+static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
+				    u8 addr, u8 *buf, int len, int flags)
+{
+	u32 data;
+	int i, shifts_left;
+
+	data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
+	writel(data, i2c->regs + MXS_I2C_QUEUECMD);
+
+	/*
+	 * We have to copy the slave address (u8) and buffer (arbitrary number
+	 * of u8) into the data register (u32). To achieve that, the u8 are put
+	 * into the MSBs of 'data' which is then shifted for the next u8. When
+	 * apropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
+	 * looks like this:
+	 *
+	 *  3          2          1          0
+	 * 10987654|32109876|54321098|76543210
+	 * --------+--------+--------+--------
+	 * buffer+2|buffer+1|buffer+0|slave_addr
+	 */
+
+	data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
+
+	for (i = 0; i < len; i++) {
+		data >>= 8;
+		data |= buf[i] << 24;
+		if ((i & 3) == 2)
+			writel(data, i2c->regs + MXS_I2C_DATA);
+	}
+
+	/* Write out the remaining bytes if any */
+	shifts_left = 24 - (i & 3) * 8;
+	if (shifts_left)
+		writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
+}
+
+/*
+ * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
+ * rd_threshold to 1). Couldn't get this to work, though.
+ */
+static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
+			& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
+			if (time_after(jiffies, timeout))
+				return -ETIMEDOUT;
+			cond_resched();
+	}
+
+	return 0;
+}
+
+static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
+{
+	u32 data;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if ((i & 3) == 0) {
+			if (mxs_i2c_wait_for_data(i2c))
+				return -ETIMEDOUT;
+			data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
+		}
+		buf[i] = data & 0xff;
+		data >>= 8;
+	}
+
+	return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
+				int stop)
+{
+	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
+	int ret;
+	int flags;
+
+	init_completion(&i2c->cmd_complete);
+
+	dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+		msg->addr, msg->len, msg->flags, stop);
+
+	if (msg->len == 0)
+		return -EINVAL;
+
+	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
+
+	if (msg->flags & I2C_M_RD)
+		mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags);
+	else
+		mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len,
+					flags);
+
+	writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+			i2c->regs + MXS_I2C_QUEUECTRL_SET);
+
+	ret = wait_for_completion_timeout(&i2c->cmd_complete,
+						msecs_to_jiffies(1000));
+	if (ret == 0)
+		goto timeout;
+
+	if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) {
+		ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
+		if (ret)
+			goto timeout;
+	}
+
+	if (i2c->cmd_err == -ENXIO)
+		mxs_i2c_reset(i2c);
+
+	dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
+
+	return i2c->cmd_err;
+
+timeout:
+	dev_dbg(i2c->dev, "Timeout!\n");
+	mxs_i2c_reset(i2c);
+	return -ETIMEDOUT;
+}
+
+static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			int num)
+{
+	int i;
+	int err;
+
+	for (i = 0; i < num; i++) {
+		err = mxs_i2c_xfer_msg(adap, &msgs[i], i == (num - 1));
+		if (err)
+			return err;
+	}
+
+	return num;
+}
+
+static u32 mxs_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
+{
+	struct mxs_i2c_dev *i2c = dev_id;
+	u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
+
+	if (!stat)
+		return IRQ_NONE;
+
+	if (stat & MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ)
+		i2c->cmd_err = -ENXIO;
+	else if (stat & (MXS_I2C_CTRL1_EARLY_TERM_IRQ |
+		    MXS_I2C_CTRL1_MASTER_LOSS_IRQ |
+		    MXS_I2C_CTRL1_SLAVE_STOP_IRQ | MXS_I2C_CTRL1_SLAVE_IRQ))
+		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
+		i2c->cmd_err = -EIO;
+	else
+		i2c->cmd_err = 0;
+
+	complete(&i2c->cmd_complete);
+
+	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
+	return IRQ_HANDLED;
+}
+
+static const struct i2c_algorithm mxs_i2c_algo = {
+	.master_xfer = mxs_i2c_xfer,
+	.functionality = mxs_i2c_func,
+};
+
+static int __devinit mxs_i2c_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mxs_i2c_dev *i2c;
+	struct i2c_adapter *adap;
+	struct resource *res;
+	resource_size_t res_size;
+	int err, irq;
+
+	i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL);
+	if (!i2c)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	res_size = resource_size(res);
+	if (!devm_request_mem_region(dev, res->start, res_size, res->name))
+		return -EBUSY;
+
+	i2c->regs = devm_ioremap_nocache(dev, res->start, res_size);
+	if (!i2c->regs)
+		return -EBUSY;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c);
+	if (err)
+		return err;
+
+	i2c->dev = dev;
+	platform_set_drvdata(pdev, i2c);
+
+	/* Do reset to enforce correct startup after pinmuxing */
+	mxs_i2c_reset(i2c);
+
+	adap = &i2c->adapter;
+	strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
+	adap->owner = THIS_MODULE;
+	adap->algo = &mxs_i2c_algo;
+	adap->dev.parent = dev;
+	adap->nr = pdev->id;
+	i2c_set_adapdata(adap, i2c);
+	err = i2c_add_numbered_adapter(adap);
+	if (err) {
+		dev_err(dev, "Failed to add adapter (%d)\n", err);
+		writel(MXS_I2C_CTRL0_SFTRST,
+				i2c->regs + MXS_I2C_CTRL0_SET);
+		return err;
+	}
+
+	return 0;
+}
+
+static int __devexit 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;
+
+	writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+			i2c->regs + MXS_I2C_QUEUECTRL_CLR);
+	writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver mxs_i2c_driver = {
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   },
+	.remove = __devexit_p(mxs_i2c_remove),
+};
+
+static int __init mxs_i2c_init(void)
+{
+	return platform_driver_probe(&mxs_i2c_driver, mxs_i2c_probe);
+}
+subsys_initcall(mxs_i2c_init);
+
+static void __exit mxs_i2c_exit(void)
+{
+	platform_driver_unregister(&mxs_i2c_driver);
+}
+module_exit(mxs_i2c_exit);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("MXS I2C Bus Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 61653f0..1b46a9d 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -330,9 +330,7 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
 	i2c->adap = ocores_adapter;
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &pdev->dev;
-#ifdef CONFIG_OF
 	i2c->adap.dev.of_node = pdev->dev.of_node;
-#endif
 
 	/* add i2c adapter to i2c tree */
 	ret = i2c_add_adapter(&i2c->adap);
@@ -390,15 +388,11 @@ static int ocores_i2c_resume(struct platform_device *pdev)
 #define ocores_i2c_resume	NULL
 #endif
 
-#ifdef CONFIG_OF
 static struct of_device_id ocores_i2c_match[] = {
-        {
-                .compatible = "opencores,i2c-ocores",
-        },
-        {},
+	{ .compatible = "opencores,i2c-ocores", },
+	{},
 };
 MODULE_DEVICE_TABLE(of, ocores_i2c_match);
-#endif
 
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:ocores-i2c");
@@ -411,9 +405,7 @@ static struct platform_driver ocores_i2c_driver = {
 	.driver  = {
 		.owner = THIS_MODULE,
 		.name = "ocores-i2c",
-#ifdef CONFIG_OF
-                .of_match_table = ocores_i2c_match,
-#endif
+		.of_match_table = ocores_i2c_match,
 	},
 };
 
diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c
new file mode 100644
index 0000000..fac6739
--- /dev/null
+++ b/drivers/i2c/busses/i2c-puv3.c
@@ -0,0 +1,306 @@
+/*
+ * I2C driver for PKUnity-v3 SoC
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can 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/err.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+/*
+ * Poll the i2c status register until the specified bit is set.
+ * Returns 0 if timed out (100 msec).
+ */
+static short poll_status(unsigned long bit)
+{
+	int loop_cntr = 1000;
+
+	if (bit & I2C_STATUS_TFNF) {
+		do {
+			udelay(10);
+		} while (!(readl(I2C_STATUS) & bit) && (--loop_cntr > 0));
+	} else {
+		/* RXRDY handler */
+		do {
+			if (readl(I2C_TAR) == I2C_TAR_EEPROM)
+				msleep(20);
+			else
+				udelay(10);
+		} while (!(readl(I2C_RXFLR) & 0xf) && (--loop_cntr > 0));
+	}
+
+	return (loop_cntr > 0);
+}
+
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+	int i2c_reg = *buf;
+
+	/* Read data */
+	while (length--) {
+		if (!poll_status(I2C_STATUS_TFNF)) {
+			dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		/* send addr */
+		writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
+
+		/* get ready to next write */
+		i2c_reg++;
+
+		/* send read CMD */
+		writel(I2C_DATACMD_READ, I2C_DATACMD);
+
+		/* wait until the Rx FIFO have available */
+		if (!poll_status(I2C_STATUS_RFNE)) {
+			dev_dbg(&adap->dev, "RXRDY timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		/* read the data to buf */
+		*buf = (readl(I2C_DATACMD) & I2C_DATACMD_DAT_MASK);
+		buf++;
+	}
+
+	return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+	int i2c_reg = *buf;
+
+	/* Do nothing but storing the reg_num to a static variable */
+	if (i2c_reg == -1) {
+		printk(KERN_WARNING "Error i2c reg\n");
+		return -ETIMEDOUT;
+	}
+
+	if (length == 1)
+		return 0;
+
+	buf++;
+	length--;
+	while (length--) {
+		/* send addr */
+		writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
+
+		/* send write CMD */
+		writel(*buf | I2C_DATACMD_WRITE, I2C_DATACMD);
+
+		/* wait until the Rx FIFO have available */
+		msleep(20);
+
+		/* read the data to buf */
+		i2c_reg++;
+		buf++;
+	}
+
+	return 0;
+}
+
+/*
+ * Generic i2c master transfer entrypoint.
+ *
+ */
+static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg,
+		int num)
+{
+	int i, ret;
+	unsigned char swap;
+
+	/* Disable i2c */
+	writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
+
+	/* Set the work mode and speed*/
+	writel(I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE, I2C_CON);
+
+	writel(pmsg->addr, I2C_TAR);
+
+	/* Enable i2c */
+	writel(I2C_ENABLE_ENABLE, I2C_ENABLE);
+
+	dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num);
+
+	for (i = 0; i < num; i++) {
+		dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+			pmsg->flags & I2C_M_RD ? "read" : "writ",
+			pmsg->len, pmsg->len > 1 ? "s" : "",
+			pmsg->flags & I2C_M_RD ? "from" : "to",	pmsg->addr);
+
+		if (pmsg->len && pmsg->buf) {	/* sanity check */
+			if (pmsg->flags & I2C_M_RD)
+				ret = xfer_read(adap, pmsg->buf, pmsg->len);
+			else
+				ret = xfer_write(adap, pmsg->buf, pmsg->len);
+
+			if (ret)
+				return ret;
+
+		}
+		dev_dbg(&adap->dev, "transfer complete\n");
+		pmsg++;		/* next message */
+	}
+
+	/* XXX: fixup be16_to_cpu in bq27x00_battery.c */
+	if (pmsg->addr == I2C_TAR_PWIC) {
+		swap = pmsg->buf[0];
+		pmsg->buf[0] = pmsg->buf[1];
+		pmsg->buf[1] = swap;
+	}
+
+	return i;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 puv3_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm puv3_i2c_algorithm = {
+	.master_xfer	= puv3_i2c_xfer,
+	.functionality	= puv3_i2c_func,
+};
+
+/*
+ * Main initialization routine.
+ */
+static int __devinit puv3_i2c_probe(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter;
+	struct resource *mem;
+	int rc;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENODEV;
+
+	if (!request_mem_region(mem->start, resource_size(mem), "puv3_i2c"))
+		return -EBUSY;
+
+	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (adapter == NULL) {
+		dev_err(&pdev->dev, "can't allocate inteface!\n");
+		rc = -ENOMEM;
+		goto fail_nomem;
+	}
+	snprintf(adapter->name, sizeof(adapter->name), "PUV3-I2C at 0x%08x",
+			mem->start);
+	adapter->algo = &puv3_i2c_algorithm;
+	adapter->class = I2C_CLASS_HWMON;
+	adapter->dev.parent = &pdev->dev;
+
+	platform_set_drvdata(pdev, adapter);
+
+	adapter->nr = pdev->id;
+	rc = i2c_add_numbered_adapter(adapter);
+	if (rc) {
+		dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
+				adapter->name);
+		goto fail_add_adapter;
+	}
+
+	dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
+	return 0;
+
+fail_add_adapter:
+	platform_set_drvdata(pdev, NULL);
+	kfree(adapter);
+fail_nomem:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return rc;
+}
+
+static int __devexit 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;
+	}
+
+	put_device(&pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	return rc;
+}
+
+#ifdef CONFIG_PM
+static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state)
+{
+	int poll_count;
+	/* Disable the IIC */
+	writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
+	for (poll_count = 0; poll_count < 50; poll_count++) {
+		if (readl(I2C_ENSTATUS) & I2C_ENSTATUS_ENABLE)
+			udelay(25);
+	}
+
+	return 0;
+}
+
+static int puv3_i2c_resume(struct platform_device *dev)
+{
+	return 0 ;
+}
+#else
+#define puv3_i2c_suspend NULL
+#define puv3_i2c_resume NULL
+#endif
+
+MODULE_ALIAS("platform:puv3_i2c");
+
+static struct platform_driver puv3_i2c_driver = {
+	.probe		= puv3_i2c_probe,
+	.remove		= __devexit_p(puv3_i2c_remove),
+	.suspend	= puv3_i2c_suspend,
+	.resume		= puv3_i2c_resume,
+	.driver		= {
+		.name	= "PKUnity-v3-I2C",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init puv3_i2c_init(void)
+{
+	return platform_driver_register(&puv3_i2c_driver);
+}
+
+static void __exit puv3_i2c_exit(void)
+{
+	platform_driver_unregister(&puv3_i2c_driver);
+}
+
+module_init(puv3_i2c_init);
+module_exit(puv3_i2c_exit);
+
+MODULE_DESCRIPTION("PKUnity v3 I2C driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c
new file mode 100644
index 0000000..6659d26
--- /dev/null
+++ b/drivers/i2c/busses/i2c-pxa-pci.c
@@ -0,0 +1,176 @@
+/*
+ * The CE4100's I2C device is more or less the same one as found on PXA.
+ * It does not support slave mode, the register slightly moved. This PCI
+ * device provides three bars, every contains a single I2C controller.
+ */
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#define CE4100_PCI_I2C_DEVS	3
+
+struct ce4100_devices {
+	struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
+};
+
+static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
+{
+	struct platform_device *pdev;
+	struct i2c_pxa_platform_data pdata;
+	struct resource res[2];
+	struct device_node *child;
+	static int devnum;
+	int ret;
+
+	memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
+	memset(&res, 0, sizeof(res));
+
+	res[0].flags = IORESOURCE_MEM;
+	res[0].start = pci_resource_start(dev, bar);
+	res[0].end = pci_resource_end(dev, bar);
+
+	res[1].flags = IORESOURCE_IRQ;
+	res[1].start = dev->irq;
+	res[1].end = dev->irq;
+
+	for_each_child_of_node(dev->dev.of_node, child) {
+		const void *prop;
+		struct resource r;
+		int ret;
+
+		ret = of_address_to_resource(child, 0, &r);
+		if (ret < 0)
+			continue;
+		if (r.start != res[0].start)
+			continue;
+		if (r.end != res[0].end)
+			continue;
+		if (r.flags != res[0].flags)
+			continue;
+
+		prop = of_get_property(child, "fast-mode", NULL);
+		if (prop)
+			pdata.fast_mode = 1;
+
+		break;
+	}
+
+	if (!child) {
+		dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
+				bar);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	pdev = platform_device_alloc("ce4100-i2c", devnum);
+	if (!pdev) {
+		of_node_put(child);
+		ret = -ENOMEM;
+		goto out;
+	}
+	pdev->dev.parent = &dev->dev;
+	pdev->dev.of_node = child;
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret)
+		goto err;
+
+	ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (ret)
+		goto err;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto err;
+	devnum++;
+	return pdev;
+err:
+	platform_device_put(pdev);
+out:
+	return ERR_PTR(ret);
+}
+
+static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
+		const struct pci_device_id *ent)
+{
+	int ret;
+	int i;
+	struct ce4100_devices *sds;
+
+	ret = pci_enable_device_mem(dev);
+	if (ret)
+		return ret;
+
+	if (!dev->dev.of_node) {
+		dev_err(&dev->dev, "Missing device tree node.\n");
+		return -EINVAL;
+	}
+	sds = kzalloc(sizeof(*sds), GFP_KERNEL);
+	if (!sds)
+		goto err_mem;
+
+	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
+		sds->pdev[i] = add_i2c_device(dev, i);
+		if (IS_ERR(sds->pdev[i])) {
+			while (--i >= 0)
+				platform_device_unregister(sds->pdev[i]);
+			goto err_dev_add;
+		}
+	}
+	pci_set_drvdata(dev, sds);
+	return 0;
+
+err_dev_add:
+	pci_set_drvdata(dev, NULL);
+	kfree(sds);
+err_mem:
+	pci_disable_device(dev);
+	return ret;
+}
+
+static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
+{
+	struct ce4100_devices *sds;
+	unsigned int i;
+
+	sds = pci_get_drvdata(dev);
+	pci_set_drvdata(dev, NULL);
+
+	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
+		platform_device_unregister(sds->pdev[i]);
+
+	pci_disable_device(dev);
+	kfree(sds);
+}
+
+static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
+
+static struct pci_driver ce4100_i2c_driver = {
+	.name           = "ce4100_i2c",
+	.id_table       = ce4100_i2c_devices,
+	.probe          = ce4100_i2c_probe,
+	.remove         = __devexit_p(ce4100_i2c_remove),
+};
+
+static int __init ce4100_i2c_init(void)
+{
+	return pci_register_driver(&ce4100_i2c_driver);
+}
+module_init(ce4100_i2c_init);
+
+static void __exit ce4100_i2c_exit(void)
+{
+	pci_unregister_driver(&ce4100_i2c_driver);
+}
+module_exit(ce4100_i2c_exit);
+
+MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index f4c19a9..f59224a 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -29,38 +29,75 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/i2c-pxa.h>
+#include <linux/of_i2c.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/irq.h>
-#include <plat/i2c.h>
+
+#ifndef CONFIG_HAVE_CLK
+#define clk_get(dev, id)	NULL
+#define clk_put(clk)		do { } while (0)
+#define clk_disable(clk)	do { } while (0)
+#define clk_enable(clk)		do { } while (0)
+#endif
+
+struct pxa_reg_layout {
+	u32 ibmr;
+	u32 idbr;
+	u32 icr;
+	u32 isr;
+	u32 isar;
+};
+
+enum pxa_i2c_types {
+	REGS_PXA2XX,
+	REGS_PXA3XX,
+	REGS_CE4100,
+};
 
 /*
- * I2C register offsets will be shifted 0 or 1 bit left, depending on
- * different SoCs
+ * I2C registers definitions
  */
-#define REG_SHIFT_0	(0 << 0)
-#define REG_SHIFT_1	(1 << 0)
-#define REG_SHIFT(d)	((d) & 0x1)
+static struct pxa_reg_layout pxa_reg_layout[] = {
+	[REGS_PXA2XX] = {
+		.ibmr =	0x00,
+		.idbr =	0x08,
+		.icr =	0x10,
+		.isr =	0x18,
+		.isar =	0x20,
+	},
+	[REGS_PXA3XX] = {
+		.ibmr =	0x00,
+		.idbr =	0x04,
+		.icr =	0x08,
+		.isr =	0x0c,
+		.isar =	0x10,
+	},
+	[REGS_CE4100] = {
+		.ibmr =	0x14,
+		.idbr =	0x0c,
+		.icr =	0x00,
+		.isr =	0x04,
+		/* no isar register */
+	},
+};
 
 static const struct platform_device_id i2c_pxa_id_table[] = {
-	{ "pxa2xx-i2c",		REG_SHIFT_1 },
-	{ "pxa3xx-pwri2c",	REG_SHIFT_0 },
+	{ "pxa2xx-i2c",		REGS_PXA2XX },
+	{ "pxa3xx-pwri2c",	REGS_PXA3XX },
+	{ "ce4100-i2c",		REGS_CE4100 },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
 
 /*
- * I2C registers and bit definitions
+ * I2C bit definitions
  */
-#define IBMR		(0x00)
-#define IDBR		(0x08)
-#define ICR		(0x10)
-#define ISR		(0x18)
-#define ISAR		(0x20)
 
 #define ICR_START	(1 << 0)	   /* start bit */
 #define ICR_STOP	(1 << 1)	   /* stop bit */
@@ -111,7 +148,11 @@ struct pxa_i2c {
 	u32			icrlog[32];
 
 	void __iomem		*reg_base;
-	unsigned int		reg_shift;
+	void __iomem		*reg_ibmr;
+	void __iomem		*reg_idbr;
+	void __iomem		*reg_icr;
+	void __iomem		*reg_isr;
+	void __iomem		*reg_isar;
 
 	unsigned long		iobase;
 	unsigned long		iosize;
@@ -121,11 +162,11 @@ struct pxa_i2c {
 	unsigned int		fast_mode :1;
 };
 
-#define _IBMR(i2c)	((i2c)->reg_base + (0x0 << (i2c)->reg_shift))
-#define _IDBR(i2c)	((i2c)->reg_base + (0x4 << (i2c)->reg_shift))
-#define _ICR(i2c)	((i2c)->reg_base + (0x8 << (i2c)->reg_shift))
-#define _ISR(i2c)	((i2c)->reg_base + (0xc << (i2c)->reg_shift))
-#define _ISAR(i2c)	((i2c)->reg_base + (0x10 << (i2c)->reg_shift))
+#define _IBMR(i2c)	((i2c)->reg_ibmr)
+#define _IDBR(i2c)	((i2c)->reg_idbr)
+#define _ICR(i2c)	((i2c)->reg_icr)
+#define _ISR(i2c)	((i2c)->reg_isr)
+#define _ISAR(i2c)	((i2c)->reg_isar)
 
 /*
  * I2C Slave mode address
@@ -418,7 +459,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c)
 	writel(I2C_ISR_INIT, _ISR(i2c));
 	writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
 
-	writel(i2c->slave_addr, _ISAR(i2c));
+	if (i2c->reg_isar)
+		writel(i2c->slave_addr, _ISAR(i2c));
 
 	/* set control register values */
 	writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
@@ -729,8 +771,10 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
 	 */
 	ret = i2c->msg_idx;
 
-	if (timeout == 0)
+	if (!timeout && i2c->msg_num) {
 		i2c_pxa_scream_blue_murder(i2c, "timeout");
+		ret = I2C_RETRY;
+	}
 
  out:
 	return ret;
@@ -915,11 +959,16 @@ static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr)
 	writel(icr, _ICR(i2c));
 }
 
+#define VALID_INT_SOURCE	(ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \
+				ISR_SAD | ISR_BED)
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 {
 	struct pxa_i2c *i2c = dev_id;
 	u32 isr = readl(_ISR(i2c));
 
+	if (!(isr & VALID_INT_SOURCE))
+		return IRQ_NONE;
+
 	if (i2c_debug > 2 && 0) {
 		dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
 			__func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
@@ -934,7 +983,7 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 	/*
 	 * Always clear all pending IRQs.
 	 */
-	writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c));
+	writel(isr & VALID_INT_SOURCE, _ISR(i2c));
 
 	if (isr & ISR_SAD)
 		i2c_pxa_slave_start(i2c, isr);
@@ -1001,6 +1050,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 	const struct platform_device_id *id = platform_get_device_id(dev);
+	enum pxa_i2c_types i2c_type = id->driver_data;
 	int ret;
 	int irq;
 
@@ -1044,7 +1094,13 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		ret = -EIO;
 		goto eremap;
 	}
-	i2c->reg_shift = REG_SHIFT(id->driver_data);
+
+	i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
+	i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
+	i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
+	i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
+	if (i2c_type != REGS_CE4100)
+		i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
 
 	i2c->iobase = res->start;
 	i2c->iosize = resource_size(res);
@@ -1072,7 +1128,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
 		i2c->adap.algo = &i2c_pxa_pio_algorithm;
 	} else {
 		i2c->adap.algo = &i2c_pxa_algorithm;
-		ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+		ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED,
 				  i2c->adap.name, i2c);
 		if (ret)
 			goto ereqirq;
@@ -1082,12 +1138,19 @@ static int i2c_pxa_probe(struct platform_device *dev)
 
 	i2c->adap.algo_data = i2c;
 	i2c->adap.dev.parent = &dev->dev;
+#ifdef CONFIG_OF
+	i2c->adap.dev.of_node = dev->dev.of_node;
+#endif
 
-	ret = i2c_add_numbered_adapter(&i2c->adap);
+	if (i2c_type == REGS_CE4100)
+		ret = i2c_add_adapter(&i2c->adap);
+	else
+		ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
 		printk(KERN_INFO "I2C: Failed to add bus\n");
 		goto eadapt;
 	}
+	of_i2c_register_devices(&i2c->adap);
 
 	platform_set_drvdata(dev, i2c);
 
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
new file mode 100644
index 0000000..3921f66
--- /dev/null
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -0,0 +1,700 @@
+/*
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c-tegra.h>
+
+#include <asm/unaligned.h>
+
+#include <mach/clk.h>
+
+#define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000))
+#define BYTES_PER_FIFO_WORD 4
+
+#define I2C_CNFG				0x000
+#define I2C_CNFG_PACKET_MODE_EN			(1<<10)
+#define I2C_CNFG_NEW_MASTER_FSM			(1<<11)
+#define I2C_SL_CNFG				0x020
+#define I2C_SL_CNFG_NEWSL			(1<<2)
+#define I2C_SL_ADDR1				0x02c
+#define I2C_TX_FIFO				0x050
+#define I2C_RX_FIFO				0x054
+#define I2C_PACKET_TRANSFER_STATUS		0x058
+#define I2C_FIFO_CONTROL			0x05c
+#define I2C_FIFO_CONTROL_TX_FLUSH		(1<<1)
+#define I2C_FIFO_CONTROL_RX_FLUSH		(1<<0)
+#define I2C_FIFO_CONTROL_TX_TRIG_SHIFT		5
+#define I2C_FIFO_CONTROL_RX_TRIG_SHIFT		2
+#define I2C_FIFO_STATUS				0x060
+#define I2C_FIFO_STATUS_TX_MASK			0xF0
+#define I2C_FIFO_STATUS_TX_SHIFT		4
+#define I2C_FIFO_STATUS_RX_MASK			0x0F
+#define I2C_FIFO_STATUS_RX_SHIFT		0
+#define I2C_INT_MASK				0x064
+#define I2C_INT_STATUS				0x068
+#define I2C_INT_PACKET_XFER_COMPLETE		(1<<7)
+#define I2C_INT_ALL_PACKETS_XFER_COMPLETE	(1<<6)
+#define I2C_INT_TX_FIFO_OVERFLOW		(1<<5)
+#define I2C_INT_RX_FIFO_UNDERFLOW		(1<<4)
+#define I2C_INT_NO_ACK				(1<<3)
+#define I2C_INT_ARBITRATION_LOST		(1<<2)
+#define I2C_INT_TX_FIFO_DATA_REQ		(1<<1)
+#define I2C_INT_RX_FIFO_DATA_REQ		(1<<0)
+#define I2C_CLK_DIVISOR				0x06c
+
+#define DVC_CTRL_REG1				0x000
+#define DVC_CTRL_REG1_INTR_EN			(1<<10)
+#define DVC_CTRL_REG2				0x004
+#define DVC_CTRL_REG3				0x008
+#define DVC_CTRL_REG3_SW_PROG			(1<<26)
+#define DVC_CTRL_REG3_I2C_DONE_INTR_EN		(1<<30)
+#define DVC_STATUS				0x00c
+#define DVC_STATUS_I2C_DONE_INTR		(1<<30)
+
+#define I2C_ERR_NONE				0x00
+#define I2C_ERR_NO_ACK				0x01
+#define I2C_ERR_ARBITRATION_LOST		0x02
+
+#define PACKET_HEADER0_HEADER_SIZE_SHIFT	28
+#define PACKET_HEADER0_PACKET_ID_SHIFT		16
+#define PACKET_HEADER0_CONT_ID_SHIFT		12
+#define PACKET_HEADER0_PROTOCOL_I2C		(1<<4)
+
+#define I2C_HEADER_HIGHSPEED_MODE		(1<<22)
+#define I2C_HEADER_CONT_ON_NAK			(1<<21)
+#define I2C_HEADER_SEND_START_BYTE		(1<<20)
+#define I2C_HEADER_READ				(1<<19)
+#define I2C_HEADER_10BIT_ADDR			(1<<18)
+#define I2C_HEADER_IE_ENABLE			(1<<17)
+#define I2C_HEADER_REPEAT_START			(1<<16)
+#define I2C_HEADER_MASTER_ADDR_SHIFT		12
+#define I2C_HEADER_SLAVE_ADDR_SHIFT		1
+
+/**
+ * struct tegra_i2c_dev	- per device i2c context
+ * @dev: device reference for power management
+ * @adapter: core i2c layer adapter information
+ * @clk: clock reference for i2c controller
+ * @i2c_clk: clock reference for i2c bus
+ * @iomem: memory resource for registers
+ * @base: ioremapped registers cookie
+ * @cont_id: i2c controller id, used for for packet header
+ * @irq: irq number of transfer complete interrupt
+ * @is_dvc: identifies the DVC i2c controller, has a different register layout
+ * @msg_complete: transfer completion notifier
+ * @msg_err: error code for completed message
+ * @msg_buf: pointer to current message data
+ * @msg_buf_remaining: size of unsent data in the message buffer
+ * @msg_read: identifies read transfers
+ * @bus_clk_rate: current i2c bus clock rate
+ * @is_suspended: prevents i2c controller accesses after suspend is called
+ */
+struct tegra_i2c_dev {
+	struct device *dev;
+	struct i2c_adapter adapter;
+	struct clk *clk;
+	struct clk *i2c_clk;
+	struct resource *iomem;
+	void __iomem *base;
+	int cont_id;
+	int irq;
+	int is_dvc;
+	struct completion msg_complete;
+	int msg_err;
+	u8 *msg_buf;
+	size_t msg_buf_remaining;
+	int msg_read;
+	unsigned long bus_clk_rate;
+	bool is_suspended;
+};
+
+static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg)
+{
+	writel(val, i2c_dev->base + reg);
+}
+
+static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
+{
+	return readl(i2c_dev->base + reg);
+}
+
+/*
+ * i2c_writel and i2c_readl will offset the register if necessary to talk
+ * to the I2C block inside the DVC block
+ */
+static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev,
+	unsigned long reg)
+{
+	if (i2c_dev->is_dvc)
+		reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
+	return reg;
+}
+
+static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
+	unsigned long reg)
+{
+	writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+}
+
+static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
+{
+	return readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+}
+
+static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
+	unsigned long reg, int len)
+{
+	writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+}
+
+static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
+	unsigned long reg, int len)
+{
+	readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+}
+
+static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
+{
+	u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK);
+	int_mask &= ~mask;
+	i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
+}
+
+static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
+{
+	u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK);
+	int_mask |= mask;
+	i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
+}
+
+static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
+{
+	unsigned long timeout = jiffies + HZ;
+	u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
+	val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
+	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+
+	while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) &
+		(I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) {
+		if (time_after(jiffies, timeout)) {
+			dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+	}
+	return 0;
+}
+
+static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val;
+	int rx_fifo_avail;
+	u8 *buf = i2c_dev->msg_buf;
+	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	int words_to_transfer;
+
+	val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+	rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
+		I2C_FIFO_STATUS_RX_SHIFT;
+
+	/* Rounds down to not include partial word at the end of buf */
+	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
+	if (words_to_transfer > rx_fifo_avail)
+		words_to_transfer = rx_fifo_avail;
+
+	i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
+
+	buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+	buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+	rx_fifo_avail -= words_to_transfer;
+
+	/*
+	 * If there is a partial word at the end of buf, handle it manually to
+	 * prevent overwriting past the end of buf
+	 */
+	if (rx_fifo_avail > 0 && buf_remaining > 0) {
+		BUG_ON(buf_remaining > 3);
+		val = i2c_readl(i2c_dev, I2C_RX_FIFO);
+		memcpy(buf, &val, buf_remaining);
+		buf_remaining = 0;
+		rx_fifo_avail--;
+	}
+
+	BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0);
+	i2c_dev->msg_buf_remaining = buf_remaining;
+	i2c_dev->msg_buf = buf;
+	return 0;
+}
+
+static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val;
+	int tx_fifo_avail;
+	u8 *buf = i2c_dev->msg_buf;
+	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	int words_to_transfer;
+
+	val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+	tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
+		I2C_FIFO_STATUS_TX_SHIFT;
+
+	/* Rounds down to not include partial word at the end of buf */
+	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
+	if (words_to_transfer > tx_fifo_avail)
+		words_to_transfer = tx_fifo_avail;
+
+	i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+
+	buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+	buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+	tx_fifo_avail -= words_to_transfer;
+
+	/*
+	 * If there is a partial word at the end of buf, handle it manually to
+	 * prevent reading past the end of buf, which could cross a page
+	 * boundary and fault.
+	 */
+	if (tx_fifo_avail > 0 && buf_remaining > 0) {
+		BUG_ON(buf_remaining > 3);
+		memcpy(&val, buf, buf_remaining);
+		i2c_writel(i2c_dev, val, I2C_TX_FIFO);
+		buf_remaining = 0;
+		tx_fifo_avail--;
+	}
+
+	BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0);
+	i2c_dev->msg_buf_remaining = buf_remaining;
+	i2c_dev->msg_buf = buf;
+	return 0;
+}
+
+/*
+ * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller)
+ * block.  This block is identical to the rest of the I2C blocks, except that
+ * it only supports master mode, it has registers moved around, and it needs
+ * some extra init to get it into I2C mode.  The register moves are handled
+ * by i2c_readl and i2c_writel
+ */
+static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val = 0;
+	val = dvc_readl(i2c_dev, DVC_CTRL_REG3);
+	val |= DVC_CTRL_REG3_SW_PROG;
+	val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN;
+	dvc_writel(i2c_dev, val, DVC_CTRL_REG3);
+
+	val = dvc_readl(i2c_dev, DVC_CTRL_REG1);
+	val |= DVC_CTRL_REG1_INTR_EN;
+	dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
+}
+
+static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val;
+	int err = 0;
+
+	clk_enable(i2c_dev->clk);
+
+	tegra_periph_reset_assert(i2c_dev->clk);
+	udelay(2);
+	tegra_periph_reset_deassert(i2c_dev->clk);
+
+	if (i2c_dev->is_dvc)
+		tegra_dvc_init(i2c_dev);
+
+	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN;
+	i2c_writel(i2c_dev, val, I2C_CNFG);
+	i2c_writel(i2c_dev, 0, I2C_INT_MASK);
+	clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8);
+
+	val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+		0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+
+	if (tegra_i2c_flush_fifos(i2c_dev))
+		err = -ETIMEDOUT;
+
+	clk_disable(i2c_dev->clk);
+	return err;
+}
+
+static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
+{
+	u32 status;
+	const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
+	struct tegra_i2c_dev *i2c_dev = dev_id;
+
+	status = i2c_readl(i2c_dev, I2C_INT_STATUS);
+
+	if (status == 0) {
+		dev_warn(i2c_dev->dev, "interrupt with no status\n");
+		return IRQ_NONE;
+	}
+
+	if (unlikely(status & status_err)) {
+		if (status & I2C_INT_NO_ACK)
+			i2c_dev->msg_err |= I2C_ERR_NO_ACK;
+		if (status & I2C_INT_ARBITRATION_LOST)
+			i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
+		complete(&i2c_dev->msg_complete);
+		goto err;
+	}
+
+	if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) {
+		if (i2c_dev->msg_buf_remaining)
+			tegra_i2c_empty_rx_fifo(i2c_dev);
+		else
+			BUG();
+	}
+
+	if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) {
+		if (i2c_dev->msg_buf_remaining)
+			tegra_i2c_fill_tx_fifo(i2c_dev);
+		else
+			tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
+	}
+
+	if ((status & I2C_INT_PACKET_XFER_COMPLETE) &&
+			!i2c_dev->msg_buf_remaining)
+		complete(&i2c_dev->msg_complete);
+
+	i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+	if (i2c_dev->is_dvc)
+		dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
+	return IRQ_HANDLED;
+err:
+	/* An error occured, mask all interrupts */
+	tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST |
+		I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ |
+		I2C_INT_RX_FIFO_DATA_REQ);
+	i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+	return IRQ_HANDLED;
+}
+
+static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
+	struct i2c_msg *msg, int stop)
+{
+	u32 packet_header;
+	u32 int_mask;
+	int ret;
+
+	tegra_i2c_flush_fifos(i2c_dev);
+	i2c_writel(i2c_dev, 0xFF, I2C_INT_STATUS);
+
+	if (msg->len == 0)
+		return -EINVAL;
+
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+	i2c_dev->msg_err = I2C_ERR_NONE;
+	i2c_dev->msg_read = (msg->flags & I2C_M_RD);
+	INIT_COMPLETION(i2c_dev->msg_complete);
+
+	packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) |
+			PACKET_HEADER0_PROTOCOL_I2C |
+			(i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) |
+			(1 << PACKET_HEADER0_PACKET_ID_SHIFT);
+	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	packet_header = msg->len - 1;
+	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	packet_header = msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
+	packet_header |= I2C_HEADER_IE_ENABLE;
+	if (msg->flags & I2C_M_TEN)
+		packet_header |= I2C_HEADER_10BIT_ADDR;
+	if (msg->flags & I2C_M_IGNORE_NAK)
+		packet_header |= I2C_HEADER_CONT_ON_NAK;
+	if (msg->flags & I2C_M_NOSTART)
+		packet_header |= I2C_HEADER_REPEAT_START;
+	if (msg->flags & I2C_M_RD)
+		packet_header |= I2C_HEADER_READ;
+	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	if (!(msg->flags & I2C_M_RD))
+		tegra_i2c_fill_tx_fifo(i2c_dev);
+
+	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
+	if (msg->flags & I2C_M_RD)
+		int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
+	else if (i2c_dev->msg_buf_remaining)
+		int_mask |= I2C_INT_TX_FIFO_DATA_REQ;
+	tegra_i2c_unmask_irq(i2c_dev, int_mask);
+	dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
+		i2c_readl(i2c_dev, I2C_INT_MASK));
+
+	ret = wait_for_completion_timeout(&i2c_dev->msg_complete, TEGRA_I2C_TIMEOUT);
+	tegra_i2c_mask_irq(i2c_dev, int_mask);
+
+	if (WARN_ON(ret == 0)) {
+		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+
+		tegra_i2c_init(i2c_dev);
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(i2c_dev->dev, "transfer complete: %d %d %d\n",
+		ret, completion_done(&i2c_dev->msg_complete), i2c_dev->msg_err);
+
+	if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
+		return 0;
+
+	tegra_i2c_init(i2c_dev);
+	if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
+		if (msg->flags & I2C_M_IGNORE_NAK)
+			return 0;
+		return -EREMOTEIO;
+	}
+
+	return -EIO;
+}
+
+static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+	int num)
+{
+	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	int i;
+	int ret = 0;
+
+	if (i2c_dev->is_suspended)
+		return -EBUSY;
+
+	clk_enable(i2c_dev->clk);
+	for (i = 0; i < num; i++) {
+		int stop = (i == (num - 1)) ? 1  : 0;
+		ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop);
+		if (ret)
+			break;
+	}
+	clk_disable(i2c_dev->clk);
+	return ret ?: i;
+}
+
+static u32 tegra_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm tegra_i2c_algo = {
+	.master_xfer	= tegra_i2c_xfer,
+	.functionality	= tegra_i2c_func,
+};
+
+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 resource *iomem;
+	struct clk *clk;
+	struct clk *i2c_clk;
+	void *base;
+	int irq;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no mem resource\n");
+		return -EINVAL;
+	}
+	iomem = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (!iomem) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	base = ioremap(iomem->start, resource_size(iomem));
+	if (!base) {
+		dev_err(&pdev->dev, "Cannot ioremap I2C region\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no irq resource\n");
+		ret = -EINVAL;
+		goto err_iounmap;
+	}
+	irq = res->start;
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "missing controller clock");
+		ret = PTR_ERR(clk);
+		goto err_release_region;
+	}
+
+	i2c_clk = clk_get(&pdev->dev, "i2c");
+	if (IS_ERR(i2c_clk)) {
+		dev_err(&pdev->dev, "missing bus clock");
+		ret = PTR_ERR(i2c_clk);
+		goto err_clk_put;
+	}
+
+	i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL);
+	if (!i2c_dev) {
+		ret = -ENOMEM;
+		goto err_i2c_clk_put;
+	}
+
+	i2c_dev->base = base;
+	i2c_dev->clk = clk;
+	i2c_dev->i2c_clk = i2c_clk;
+	i2c_dev->iomem = iomem;
+	i2c_dev->adapter.algo = &tegra_i2c_algo;
+	i2c_dev->irq = irq;
+	i2c_dev->cont_id = pdev->id;
+	i2c_dev->dev = &pdev->dev;
+	i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000;
+
+	if (pdev->id == 3)
+		i2c_dev->is_dvc = 1;
+	init_completion(&i2c_dev->msg_complete);
+
+	platform_set_drvdata(pdev, i2c_dev);
+
+	ret = tegra_i2c_init(i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize i2c controller");
+		goto err_free;
+	}
+
+	ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
+		goto err_free;
+	}
+
+	clk_enable(i2c_dev->i2c_clk);
+
+	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
+	i2c_dev->adapter.owner = THIS_MODULE;
+	i2c_dev->adapter.class = I2C_CLASS_HWMON;
+	strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
+		sizeof(i2c_dev->adapter.name));
+	i2c_dev->adapter.algo = &tegra_i2c_algo;
+	i2c_dev->adapter.dev.parent = &pdev->dev;
+	i2c_dev->adapter.nr = pdev->id;
+
+	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+err_free_irq:
+	free_irq(i2c_dev->irq, i2c_dev);
+err_free:
+	kfree(i2c_dev);
+err_i2c_clk_put:
+	clk_put(i2c_clk);
+err_clk_put:
+	clk_put(clk);
+err_release_region:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_iounmap:
+	iounmap(base);
+	return ret;
+}
+
+static int tegra_i2c_remove(struct platform_device *pdev)
+{
+	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+	i2c_del_adapter(&i2c_dev->adapter);
+	free_irq(i2c_dev->irq, i2c_dev);
+	clk_put(i2c_dev->i2c_clk);
+	clk_put(i2c_dev->clk);
+	release_mem_region(i2c_dev->iomem->start,
+		resource_size(i2c_dev->iomem));
+	iounmap(i2c_dev->base);
+	kfree(i2c_dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+	i2c_lock_adapter(&i2c_dev->adapter);
+	i2c_dev->is_suspended = true;
+	i2c_unlock_adapter(&i2c_dev->adapter);
+
+	return 0;
+}
+
+static int tegra_i2c_resume(struct platform_device *pdev)
+{
+	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+	int ret;
+
+	i2c_lock_adapter(&i2c_dev->adapter);
+
+	ret = tegra_i2c_init(i2c_dev);
+
+	if (ret) {
+		i2c_unlock_adapter(&i2c_dev->adapter);
+		return ret;
+	}
+
+	i2c_dev->is_suspended = false;
+
+	i2c_unlock_adapter(&i2c_dev->adapter);
+
+	return 0;
+}
+#endif
+
+static struct platform_driver tegra_i2c_driver = {
+	.probe   = tegra_i2c_probe,
+	.remove  = tegra_i2c_remove,
+#ifdef CONFIG_PM
+	.suspend = tegra_i2c_suspend,
+	.resume  = tegra_i2c_resume,
+#endif
+	.driver  = {
+		.name  = "tegra-i2c",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init tegra_i2c_init_driver(void)
+{
+	return platform_driver_register(&tegra_i2c_driver);
+}
+
+static void __exit tegra_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&tegra_i2c_driver);
+}
+
+subsys_initcall(tegra_i2c_init_driver);
+module_exit(tegra_i2c_exit_driver);
+
+MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver");
+MODULE_AUTHOR("Colin Cross");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/i2c-boardinfo.c b/drivers/i2c/i2c-boardinfo.c
index 7e6a63b..3ca2e01 100644
--- a/drivers/i2c/i2c-boardinfo.c
+++ b/drivers/i2c/i2c-boardinfo.c
@@ -1,5 +1,5 @@
 /*
- * i2c-boardinfo.h - collect pre-declarations of I2C devices
+ * i2c-boardinfo.c - collect pre-declarations of I2C devices
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index f0bd5bc..e5f76a0 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -537,9 +537,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
 	client->dev.parent = &client->adapter->dev;
 	client->dev.bus = &i2c_bus_type;
 	client->dev.type = &i2c_client_type;
-#ifdef CONFIG_OF
 	client->dev.of_node = info->of_node;
-#endif
 
 	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
 		     client->addr);
@@ -799,6 +797,9 @@ static int i2c_do_add_adapter(struct i2c_driver *driver,
 
 	/* Let legacy drivers scan this bus for matching devices */
 	if (driver->attach_adapter) {
+		dev_warn(&adap->dev, "attach_adapter method is deprecated\n");
+		dev_warn(&adap->dev, "Please use another way to instantiate "
+			 "your i2c_client\n");
 		/* We ignore the return code; if it fails, too bad */
 		driver->attach_adapter(adap);
 	}
@@ -983,6 +984,7 @@ static int i2c_do_del_adapter(struct i2c_driver *driver,
 
 	if (!driver->detach_adapter)
 		return 0;
+	dev_warn(&adapter->dev, "detach_adapter method is deprecated\n");
 	res = driver->detach_adapter(adapter);
 	if (res)
 		dev_err(&adapter->dev, "detach_adapter failed (%d) "
@@ -1093,6 +1095,18 @@ EXPORT_SYMBOL(i2c_del_adapter);
 
 /* ------------------------------------------------------------------------- */
 
+int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
+{
+	int res;
+
+	mutex_lock(&core_lock);
+	res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
+	mutex_unlock(&core_lock);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(i2c_for_each_dev);
+
 static int __process_new_driver(struct device *dev, void *data)
 {
 	if (dev->type != &i2c_adapter_type)
@@ -1136,9 +1150,7 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 
 	INIT_LIST_HEAD(&driver->clients);
 	/* Walk the adapters that are already present */
-	mutex_lock(&core_lock);
-	bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
-	mutex_unlock(&core_lock);
+	i2c_for_each_dev(driver, __process_new_driver);
 
 	return 0;
 }
@@ -1158,9 +1170,7 @@ static int __process_removed_driver(struct device *dev, void *data)
  */
 void i2c_del_driver(struct i2c_driver *driver)
 {
-	mutex_lock(&core_lock);
-	bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);
-	mutex_unlock(&core_lock);
+	i2c_for_each_dev(driver, __process_removed_driver);
 
 	driver_unregister(&driver->driver);
 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
@@ -1583,12 +1593,12 @@ i2c_new_probed_device(struct i2c_adapter *adap,
 }
 EXPORT_SYMBOL_GPL(i2c_new_probed_device);
 
-struct i2c_adapter *i2c_get_adapter(int id)
+struct i2c_adapter *i2c_get_adapter(int nr)
 {
 	struct i2c_adapter *adapter;
 
 	mutex_lock(&core_lock);
-	adapter = idr_find(&i2c_adapter_idr, id);
+	adapter = idr_find(&i2c_adapter_idr, nr);
 	if (adapter && !try_module_get(adapter->owner))
 		adapter = NULL;
 
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index cec0f3b..c90ce50 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -28,6 +28,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/device.h>
+#include <linux/notifier.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -37,16 +39,13 @@
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
 
-static struct i2c_driver i2cdev_driver;
-
 /*
  * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
  * slave (i2c_client) with which messages will be exchanged.  It's coupled
  * with a character special file which is accessed by user mode drivers.
  *
  * The list of i2c_dev structures is parallel to the i2c_adapter lists
- * maintained by the driver model, and is updated using notifications
- * delivered to the i2cdev_driver.
+ * maintained by the driver model, and is updated using bus notifications.
  */
 struct i2c_dev {
 	struct list_head list;
@@ -491,7 +490,6 @@ static int i2cdev_open(struct inode *inode, struct file *file)
 		return -ENOMEM;
 	}
 	snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
-	client->driver = &i2cdev_driver;
 
 	client->adapter = adap;
 	file->private_data = client;
@@ -522,19 +520,18 @@ static const struct file_operations i2cdev_fops = {
 
 /* ------------------------------------------------------------------------- */
 
-/*
- * The legacy "i2cdev_driver" is used primarily to get notifications when
- * I2C adapters are added or removed, so that each one gets an i2c_dev
- * and is thus made available to userspace driver code.
- */
-
 static struct class *i2c_dev_class;
 
-static int i2cdev_attach_adapter(struct i2c_adapter *adap)
+static int i2cdev_attach_adapter(struct device *dev, void *dummy)
 {
+	struct i2c_adapter *adap;
 	struct i2c_dev *i2c_dev;
 	int res;
 
+	if (dev->type != &i2c_adapter_type)
+		return 0;
+	adap = to_i2c_adapter(dev);
+
 	i2c_dev = get_free_i2c_dev(adap);
 	if (IS_ERR(i2c_dev))
 		return PTR_ERR(i2c_dev);
@@ -561,10 +558,15 @@ error:
 	return res;
 }
 
-static int i2cdev_detach_adapter(struct i2c_adapter *adap)
+static int i2cdev_detach_adapter(struct device *dev, void *dummy)
 {
+	struct i2c_adapter *adap;
 	struct i2c_dev *i2c_dev;
 
+	if (dev->type != &i2c_adapter_type)
+		return 0;
+	adap = to_i2c_adapter(dev);
+
 	i2c_dev = i2c_dev_get_by_minor(adap->nr);
 	if (!i2c_dev) /* attach_adapter must have failed */
 		return 0;
@@ -577,12 +579,23 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
 	return 0;
 }
 
-static struct i2c_driver i2cdev_driver = {
-	.driver = {
-		.name	= "dev_driver",
-	},
-	.attach_adapter	= i2cdev_attach_adapter,
-	.detach_adapter	= i2cdev_detach_adapter,
+int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+			 void *data)
+{
+	struct device *dev = data;
+
+	switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		return i2cdev_attach_adapter(dev, NULL);
+	case BUS_NOTIFY_DEL_DEVICE:
+		return i2cdev_detach_adapter(dev, NULL);
+	}
+
+	return 0;
+}
+
+static struct notifier_block i2cdev_notifier = {
+	.notifier_call = i2cdev_notifier_call,
 };
 
 /* ------------------------------------------------------------------------- */
@@ -607,10 +620,14 @@ static int __init i2c_dev_init(void)
 		goto out_unreg_chrdev;
 	}
 
-	res = i2c_add_driver(&i2cdev_driver);
+	/* Keep track of adapters which will be added or removed later */
+	res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
 	if (res)
 		goto out_unreg_class;
 
+	/* Bind to already existing adapters right away */
+	i2c_for_each_dev(NULL, i2cdev_attach_adapter);
+
 	return 0;
 
 out_unreg_class:
@@ -624,7 +641,8 @@ out:
 
 static void __exit i2c_dev_exit(void)
 {
-	i2c_del_driver(&i2cdev_driver);
+	bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
+	i2c_for_each_dev(NULL, i2cdev_detach_adapter);
 	class_destroy(i2c_dev_class);
 	unregister_chrdev(I2C_MAJOR, "i2c");
 }
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 81df925..7f879b2 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -2,7 +2,7 @@
 # link order is important here
 #
 
-EXTRA_CFLAGS				+= -Idrivers/ide
+ccflags-y				:= -Idrivers/ide
 
 ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
 	      ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \
diff --git a/drivers/ieee802154/Makefile b/drivers/ieee802154/Makefile
index e0e8e1a..6899913 100644
--- a/drivers/ieee802154/Makefile
+++ b/drivers/ieee802154/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
 
-EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD
+ccflags-y := -DDEBUG -DCONFIG_FFD
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8aba0ba..e0ef5fd 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -183,20 +183,15 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 {
 	__be32 src_ip = src_in->sin_addr.s_addr;
 	__be32 dst_ip = dst_in->sin_addr.s_addr;
-	struct flowi fl;
 	struct rtable *rt;
 	struct neighbour *neigh;
 	int ret;
 
-	memset(&fl, 0, sizeof fl);
-	fl.nl_u.ip4_u.daddr = dst_ip;
-	fl.nl_u.ip4_u.saddr = src_ip;
-	fl.oif = addr->bound_dev_if;
-
-	ret = ip_route_output_key(&init_net, &rt, &fl);
-	if (ret)
+	rt = ip_route_output(&init_net, dst_ip, src_ip, 0, addr->bound_dev_if);
+	if (IS_ERR(rt)) {
+		ret = PTR_ERR(rt);
 		goto out;
-
+	}
 	src_in->sin_family = AF_INET;
 	src_in->sin_addr.s_addr = rt->rt_src;
 
@@ -236,28 +231,28 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
 			 struct sockaddr_in6 *dst_in,
 			 struct rdma_dev_addr *addr)
 {
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct neighbour *neigh;
 	struct dst_entry *dst;
 	int ret;
 
-	memset(&fl, 0, sizeof fl);
-	ipv6_addr_copy(&fl.fl6_dst, &dst_in->sin6_addr);
-	ipv6_addr_copy(&fl.fl6_src, &src_in->sin6_addr);
-	fl.oif = addr->bound_dev_if;
+	memset(&fl6, 0, sizeof fl6);
+	ipv6_addr_copy(&fl6.daddr, &dst_in->sin6_addr);
+	ipv6_addr_copy(&fl6.saddr, &src_in->sin6_addr);
+	fl6.flowi6_oif = addr->bound_dev_if;
 
-	dst = ip6_route_output(&init_net, NULL, &fl);
+	dst = ip6_route_output(&init_net, NULL, &fl6);
 	if ((ret = dst->error))
 		goto put;
 
-	if (ipv6_addr_any(&fl.fl6_src)) {
+	if (ipv6_addr_any(&fl6.saddr)) {
 		ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev,
-					 &fl.fl6_dst, 0, &fl.fl6_src);
+					 &fl6.daddr, 0, &fl6.saddr);
 		if (ret)
 			goto put;
 
 		src_in->sin6_family = AF_INET6;
-		ipv6_addr_copy(&src_in->sin6_addr, &fl.fl6_src);
+		ipv6_addr_copy(&src_in->sin6_addr, &fl6.saddr);
 	}
 
 	if (dst->dev->flags & IFF_LOOPBACK) {
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 64e0903..f804e28 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -1988,6 +1988,10 @@ int ib_send_cm_dreq(struct ib_cm_id *cm_id,
 		goto out;
 	}
 
+	if (cm_id->lap_state == IB_CM_LAP_SENT ||
+	    cm_id->lap_state == IB_CM_MRA_LAP_RCVD)
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
+
 	ret = cm_alloc_msg(cm_id_priv, &msg);
 	if (ret) {
 		cm_enter_timewait(cm_id_priv);
@@ -2129,6 +2133,10 @@ static int cm_dreq_handler(struct cm_work *work)
 		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		break;
 	case IB_CM_ESTABLISHED:
+		if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT ||
+		    cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
+			ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
+		break;
 	case IB_CM_MRA_REP_RCVD:
 		break;
 	case IB_CM_TIMEWAIT:
@@ -2349,9 +2357,18 @@ static int cm_rej_handler(struct cm_work *work)
 		/* fall through */
 	case IB_CM_REP_RCVD:
 	case IB_CM_MRA_REP_SENT:
-	case IB_CM_ESTABLISHED:
 		cm_enter_timewait(cm_id_priv);
 		break;
+	case IB_CM_ESTABLISHED:
+		if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT ||
+		    cm_id_priv->id.lap_state == IB_CM_LAP_SENT) {
+			if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT)
+				ib_cancel_mad(cm_id_priv->av.port->mad_agent,
+					      cm_id_priv->msg);
+			cm_enter_timewait(cm_id_priv);
+			break;
+		}
+		/* fall through */
 	default:
 		spin_unlock_irq(&cm_id_priv->lock);
 		ret = -EINVAL;
@@ -2989,6 +3006,7 @@ static int cm_sidr_req_handler(struct cm_work *work)
 		goto out; /* No match. */
 	}
 	atomic_inc(&cur_cm_id_priv->refcount);
+	atomic_inc(&cm_id_priv->refcount);
 	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 6884da2..5ed9d25 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -308,11 +308,13 @@ static inline void release_mc(struct kref *kref)
 	kfree(mc);
 }
 
-static void cma_detach_from_dev(struct rdma_id_private *id_priv)
+static void cma_release_dev(struct rdma_id_private *id_priv)
 {
+	mutex_lock(&lock);
 	list_del(&id_priv->list);
 	cma_deref_dev(id_priv->cma_dev);
 	id_priv->cma_dev = NULL;
+	mutex_unlock(&lock);
 }
 
 static int cma_set_qkey(struct rdma_id_private *id_priv)
@@ -373,6 +375,7 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
 	enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
 		IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
 
+	mutex_lock(&lock);
 	iboe_addr_get_sgid(dev_addr, &iboe_gid);
 	memcpy(&gid, dev_addr->src_dev_addr +
 	       rdma_addr_gid_offset(dev_addr), sizeof gid);
@@ -398,6 +401,7 @@ out:
 	if (!ret)
 		cma_attach_to_dev(id_priv, cma_dev);
 
+	mutex_unlock(&lock);
 	return ret;
 }
 
@@ -904,9 +908,14 @@ void rdma_destroy_id(struct rdma_cm_id *id)
 	state = cma_exch(id_priv, CMA_DESTROYING);
 	cma_cancel_operation(id_priv, state);
 
-	mutex_lock(&lock);
+	/*
+	 * Wait for any active callback to finish.  New callbacks will find
+	 * the id_priv state set to destroying and abort.
+	 */
+	mutex_lock(&id_priv->handler_mutex);
+	mutex_unlock(&id_priv->handler_mutex);
+
 	if (id_priv->cma_dev) {
-		mutex_unlock(&lock);
 		switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
 		case RDMA_TRANSPORT_IB:
 			if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
@@ -920,10 +929,8 @@ void rdma_destroy_id(struct rdma_cm_id *id)
 			break;
 		}
 		cma_leave_mc_groups(id_priv);
-		mutex_lock(&lock);
-		cma_detach_from_dev(id_priv);
+		cma_release_dev(id_priv);
 	}
-	mutex_unlock(&lock);
 
 	cma_release_port(id_priv);
 	cma_deref_id(id_priv);
@@ -1200,9 +1207,7 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 	}
 
 	mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
-	mutex_lock(&lock);
 	ret = cma_acquire_dev(conn_id);
-	mutex_unlock(&lock);
 	if (ret)
 		goto release_conn_id;
 
@@ -1210,6 +1215,11 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 	cm_id->context = conn_id;
 	cm_id->cm_handler = cma_ib_handler;
 
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (!ret) {
 		/*
@@ -1222,8 +1232,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
 			ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
 		mutex_unlock(&lock);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		goto out;
 	}
+	cma_deref_id(conn_id);
 
 	/* Destroy the CM ID by returning a non-zero value. */
 	conn_id->cm_id.ib = NULL;
@@ -1394,9 +1406,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
 		goto out;
 	}
 
-	mutex_lock(&lock);
 	ret = cma_acquire_dev(conn_id);
-	mutex_unlock(&lock);
 	if (ret) {
 		mutex_unlock(&conn_id->handler_mutex);
 		rdma_destroy_id(new_cm_id);
@@ -1425,17 +1435,25 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
 	event.param.conn.private_data_len = iw_event->private_data_len;
 	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
 	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (ret) {
 		/* User wants to destroy the CM ID */
 		conn_id->cm_id.iw = NULL;
 		cma_exch(conn_id, CMA_DESTROYING);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		rdma_destroy_id(&conn_id->id);
 		goto out;
 	}
 
 	mutex_unlock(&conn_id->handler_mutex);
+	cma_deref_id(conn_id);
 
 out:
 	if (dev)
@@ -1951,20 +1969,11 @@ static void addr_handler(int status, struct sockaddr *src_addr,
 
 	memset(&event, 0, sizeof event);
 	mutex_lock(&id_priv->handler_mutex);
-
-	/*
-	 * Grab mutex to block rdma_destroy_id() from removing the device while
-	 * we're trying to acquire it.
-	 */
-	mutex_lock(&lock);
-	if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) {
-		mutex_unlock(&lock);
+	if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
 		goto out;
-	}
 
 	if (!status && !id_priv->cma_dev)
 		status = cma_acquire_dev(id_priv);
-	mutex_unlock(&lock);
 
 	if (status) {
 		if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
@@ -2265,9 +2274,7 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 		if (ret)
 			goto err1;
 
-		mutex_lock(&lock);
 		ret = cma_acquire_dev(id_priv);
-		mutex_unlock(&lock);
 		if (ret)
 			goto err1;
 	}
@@ -2279,11 +2286,8 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
 
 	return 0;
 err2:
-	if (id_priv->cma_dev) {
-		mutex_lock(&lock);
-		cma_detach_from_dev(id_priv);
-		mutex_unlock(&lock);
-	}
+	if (id_priv->cma_dev)
+		cma_release_dev(id_priv);
 err1:
 	cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
 	return ret;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index d02dcc6..3216bca 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -338,23 +338,11 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
 				 __be16 peer_port, u8 tos)
 {
 	struct rtable *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			 .ip4_u = {
-				   .daddr = peer_ip,
-				   .saddr = local_ip,
-				   .tos = tos}
-			 },
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			  .ports = {
-				    .sport = local_port,
-				    .dport = peer_port}
-			  }
-	};
-
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+
+	rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip,
+				   peer_port, local_port, IPPROTO_TCP,
+				   tos, 0);
+	if (IS_ERR(rt))
 		return NULL;
 	return rt;
 }
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 8b00e6c..9d8dcfa 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -61,9 +61,9 @@ static char *states[] = {
 	NULL,
 };
 
-static int dack_mode;
+static int dack_mode = 1;
 module_param(dack_mode, int, 0644);
-MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=0)");
+MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
 
 int c4iw_max_read_depth = 8;
 module_param(c4iw_max_read_depth, int, 0644);
@@ -315,23 +315,11 @@ static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip,
 				 __be16 peer_port, u8 tos)
 {
 	struct rtable *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			 .ip4_u = {
-				   .daddr = peer_ip,
-				   .saddr = local_ip,
-				   .tos = tos}
-			 },
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			  .ports = {
-				    .sport = local_port,
-				    .dport = peer_port}
-			  }
-	};
-
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+
+	rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip,
+				   peer_port, local_port, IPPROTO_TCP,
+				   tos, 0);
+	if (IS_ERR(rt))
 		return NULL;
 	return rt;
 }
@@ -482,6 +470,7 @@ static int send_connect(struct c4iw_ep *ep)
 	       TX_CHAN(ep->tx_chan) |
 	       SMAC_SEL(ep->smac_idx) |
 	       DSCP(ep->tos) |
+	       ULP_MODE(ULP_MODE_TCPDDP) |
 	       RCV_BUFSIZ(rcv_win>>10);
 	opt2 = RX_CHANNEL(0) |
 	       RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
@@ -1274,6 +1263,7 @@ static void accept_cr(struct c4iw_ep *ep, __be32 peer_ip, struct sk_buff *skb,
 	       TX_CHAN(ep->tx_chan) |
 	       SMAC_SEL(ep->smac_idx) |
 	       DSCP(ep->tos) |
+	       ULP_MODE(ULP_MODE_TCPDDP) |
 	       RCV_BUFSIZ(rcv_win>>10);
 	opt2 = RX_CHANNEL(0) |
 	       RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 54fbc11..e29172c 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -87,17 +87,22 @@ static int dump_qp(int id, void *p, void *data)
 		return 1;
 
 	if (qp->ep)
-		cc = snprintf(qpd->buf + qpd->pos, space, "qp id %u state %u "
+		cc = snprintf(qpd->buf + qpd->pos, space,
+			     "qp sq id %u rq id %u state %u onchip %u "
 			     "ep tid %u state %u %pI4:%u->%pI4:%u\n",
-			     qp->wq.sq.qid, (int)qp->attr.state,
+			     qp->wq.sq.qid, qp->wq.rq.qid, (int)qp->attr.state,
+			     qp->wq.sq.flags & T4_SQ_ONCHIP,
 			     qp->ep->hwtid, (int)qp->ep->com.state,
 			     &qp->ep->com.local_addr.sin_addr.s_addr,
 			     ntohs(qp->ep->com.local_addr.sin_port),
 			     &qp->ep->com.remote_addr.sin_addr.s_addr,
 			     ntohs(qp->ep->com.remote_addr.sin_port));
 	else
-		cc = snprintf(qpd->buf + qpd->pos, space, "qp id %u state %u\n",
-			      qp->wq.sq.qid, (int)qp->attr.state);
+		cc = snprintf(qpd->buf + qpd->pos, space,
+			     "qp sq id %u rq id %u state %u onchip %u\n",
+			      qp->wq.sq.qid, qp->wq.rq.qid,
+			      (int)qp->attr.state,
+			      qp->wq.sq.flags & T4_SQ_ONCHIP);
 	if (cc < space)
 		qpd->pos += cc;
 	return 0;
@@ -368,7 +373,6 @@ static void c4iw_rdev_close(struct c4iw_rdev *rdev)
 static void c4iw_remove(struct c4iw_dev *dev)
 {
 	PDBG("%s c4iw_dev %p\n", __func__,  dev);
-	cancel_delayed_work_sync(&dev->db_drop_task);
 	list_del(&dev->entry);
 	if (dev->registered)
 		c4iw_unregister_device(dev);
@@ -523,8 +527,16 @@ static int c4iw_uld_state_change(void *handle, enum cxgb4_state new_state)
 	case CXGB4_STATE_START_RECOVERY:
 		printk(KERN_INFO MOD "%s: Fatal Error\n",
 		       pci_name(dev->rdev.lldi.pdev));
-		if (dev->registered)
+		dev->rdev.flags |= T4_FATAL_ERROR;
+		if (dev->registered) {
+			struct ib_event event;
+
+			memset(&event, 0, sizeof event);
+			event.event  = IB_EVENT_DEVICE_FATAL;
+			event.device = &dev->ibdev;
+			ib_dispatch_event(&event);
 			c4iw_unregister_device(dev);
+		}
 		break;
 	case CXGB4_STATE_DETACH:
 		printk(KERN_INFO MOD "%s: Detach\n",
diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
index 2fe19ec..9f6166f 100644
--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
+++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
@@ -176,7 +176,6 @@ struct c4iw_dev {
 	struct idr mmidr;
 	spinlock_t lock;
 	struct list_head entry;
-	struct delayed_work db_drop_task;
 	struct dentry *debugfs_root;
 	u8 registered;
 };
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 4f0be25..70a5a3c 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -31,9 +31,9 @@
  */
 #include "iw_cxgb4.h"
 
-static int ocqp_support;
+static int ocqp_support = 1;
 module_param(ocqp_support, int, 0644);
-MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=0)");
+MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)");
 
 static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
 {
diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h
index 7000442..24af12f 100644
--- a/drivers/infiniband/hw/cxgb4/t4.h
+++ b/drivers/infiniband/hw/cxgb4/t4.h
@@ -507,8 +507,14 @@ static inline void t4_swcq_consume(struct t4_cq *cq)
 static inline void t4_hwcq_consume(struct t4_cq *cq)
 {
 	cq->bits_type_ts = cq->queue[cq->cidx].bits_type_ts;
-	if (++cq->cidx_inc == cq->size)
+	if (++cq->cidx_inc == (cq->size >> 4)) {
+		u32 val;
+
+		val = SEINTARM(0) | CIDXINC(cq->cidx_inc) | TIMERREG(7) |
+		      INGRESSQID(cq->cqid);
+		writel(val, cq->gts);
 		cq->cidx_inc = 0;
+	}
 	if (++cq->cidx == cq->size) {
 		cq->cidx = 0;
 		cq->gen ^= 1;
diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
index b8cb2f1..8991677 100644
--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
@@ -557,6 +557,7 @@ static ssize_t store_reset(struct device *dev,
 		dev_info(dev,"Unit %d is disabled, can't reset\n",
 			 dd->ipath_unit);
 		ret = -EINVAL;
+		goto bail;
 	}
 	ret = ipath_reset_device(dd->ipath_unit);
 bail:
diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c
index bab9f74..cfed539 100644
--- a/drivers/infiniband/hw/ipath/ipath_user_pages.c
+++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c
@@ -53,8 +53,8 @@ static void __ipath_release_user_pages(struct page **p, size_t num_pages,
 }
 
 /* call with current->mm->mmap_sem held */
-static int __get_user_pages(unsigned long start_page, size_t num_pages,
-			struct page **p, struct vm_area_struct **vma)
+static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
+				  struct page **p, struct vm_area_struct **vma)
 {
 	unsigned long lock_limit;
 	size_t got;
@@ -165,7 +165,7 @@ int ipath_get_user_pages(unsigned long start_page, size_t num_pages,
 
 	down_write(&current->mm->mmap_sem);
 
-	ret = __get_user_pages(start_page, num_pages, p, NULL);
+	ret = __ipath_get_user_pages(start_page, num_pages, p, NULL);
 
 	up_write(&current->mm->mmap_sem);
 
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 3b4ec32..3d7f366 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -153,7 +153,8 @@ static int nes_inetaddr_event(struct notifier_block *notifier,
 				nesdev, nesdev->netdev[0]->name);
 		netdev = nesdev->netdev[0];
 		nesvnic = netdev_priv(netdev);
-		is_bonded = (netdev->master == event_netdev);
+		is_bonded = netif_is_bond_slave(netdev) &&
+			    (netdev->master == event_netdev);
 		if ((netdev == event_netdev) || is_bonded) {
 			if (nesvnic->rdma_enabled == 0) {
 				nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since"
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 009ec81..ef32915 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1104,21 +1104,19 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
 static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpindex)
 {
 	struct rtable *rt;
-	struct flowi fl;
 	struct neighbour *neigh;
 	int rc = arpindex;
 	struct net_device *netdev;
 	struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
 
-	memset(&fl, 0, sizeof fl);
-	fl.nl_u.ip4_u.daddr = htonl(dst_ip);
-	if (ip_route_output_key(&init_net, &rt, &fl)) {
+	rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
+	if (IS_ERR(rt)) {
 		printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
 				__func__, dst_ip);
 		return rc;
 	}
 
-	if (nesvnic->netdev->master)
+	if (netif_is_bond_slave(netdev))
 		netdev = nesvnic->netdev->master;
 	else
 		netdev = nesvnic->netdev;
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index b01809a..4a2d21e 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -5582,9 +5582,16 @@ static void qsfp_7322_event(struct work_struct *work)
 	 * even on failure to read cable information.  We don't
 	 * get here for QME, so IS_QME check not needed here.
 	 */
-	le2 = (!ret && qd->cache.atten[1] >= qib_long_atten &&
-	       !ppd->dd->cspec->r1 && QSFP_IS_CU(qd->cache.tech)) ?
-		LE2_5m : LE2_DEFAULT;
+	if (!ret && !ppd->dd->cspec->r1) {
+		if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
+			le2 = LE2_QME;
+		else if (qd->cache.atten[1] >= qib_long_atten &&
+			 QSFP_IS_CU(qd->cache.tech))
+			le2 = LE2_5m;
+		else
+			le2 = LE2_DEFAULT;
+	} else
+		le2 = LE2_DEFAULT;
 	ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
 	init_txdds_table(ppd, 0);
 }
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 5ad224e..8fd3df5 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -464,8 +464,9 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
 	memset(smp->data, 0, sizeof(smp->data));
 
 	/* Only return the mkey if the protection field allows it. */
-	if (smp->method == IB_MGMT_METHOD_SET || ibp->mkey == smp->mkey ||
-	    ibp->mkeyprot == 0)
+	if (!(smp->method == IB_MGMT_METHOD_GET &&
+	      ibp->mkey != smp->mkey &&
+	      ibp->mkeyprot == 1))
 		pip->mkey = ibp->mkey;
 	pip->gid_prefix = ibp->gid_prefix;
 	lid = ppd->lid;
@@ -705,7 +706,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
 	lwe = pip->link_width_enabled;
 	if (lwe) {
 		if (lwe == 0xFF)
-			lwe = ppd->link_width_supported;
+			set_link_width_enabled(ppd, ppd->link_width_supported);
 		else if (lwe >= 16 || (lwe & ~ppd->link_width_supported))
 			smp->status |= IB_SMP_INVALID_FIELD;
 		else if (lwe != ppd->link_width_enabled)
@@ -720,7 +721,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
 		 * speeds.
 		 */
 		if (lse == 15)
-			lse = ppd->link_speed_supported;
+			set_link_speed_enabled(ppd,
+					       ppd->link_speed_supported);
 		else if (lse >= 8 || (lse & ~ppd->link_speed_supported))
 			smp->status |= IB_SMP_INVALID_FIELD;
 		else if (lse != ppd->link_speed_enabled)
@@ -849,7 +851,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
 	if (clientrereg)
 		pip->clientrereg_resv_subnetto |= 0x80;
 
-	goto done;
+	goto get_only;
 
 err:
 	smp->status |= IB_SMP_INVALID_FIELD;
diff --git a/drivers/infiniband/hw/qib/qib_qsfp.h b/drivers/infiniband/hw/qib/qib_qsfp.h
index 19b527b..c109bbd 100644
--- a/drivers/infiniband/hw/qib/qib_qsfp.h
+++ b/drivers/infiniband/hw/qib/qib_qsfp.h
@@ -79,6 +79,8 @@
 extern const char *const qib_qsfp_devtech[16];
 /* Active Equalization includes fiber, copper full EQ, and copper near Eq */
 #define QSFP_IS_ACTIVE(tech) ((0xA2FF >> ((tech) >> 4)) & 1)
+/* Active Equalization includes fiber, copper full EQ, and copper far Eq */
+#define QSFP_IS_ACTIVE_FAR(tech) ((0x32FF >> ((tech) >> 4)) & 1)
 /* Attenuation should be valid for copper other than full/near Eq */
 #define QSFP_HAS_ATTEN(tech) ((0x4D00 >> ((tech) >> 4)) & 1)
 /* Length is only valid if technology is "copper" */
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index d7a26c1..7689e49 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -51,8 +51,8 @@ static void __qib_release_user_pages(struct page **p, size_t num_pages,
 /*
  * Call with current->mm->mmap_sem held.
  */
-static int __get_user_pages(unsigned long start_page, size_t num_pages,
-			    struct page **p, struct vm_area_struct **vma)
+static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
+				struct page **p, struct vm_area_struct **vma)
 {
 	unsigned long lock_limit;
 	size_t got;
@@ -136,7 +136,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages,
 
 	down_write(&current->mm->mmap_sem);
 
-	ret = __get_user_pages(start_page, num_pages, p, NULL);
+	ret = __qib_get_user_pages(start_page, num_pages, p, NULL);
 
 	up_write(&current->mm->mmap_sem);
 
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 7b2fc98..8db008d 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -532,6 +532,29 @@ iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *s
 	stats->custom[3].value = conn->fmr_unalign_cnt;
 }
 
+static int iscsi_iser_get_ep_param(struct iscsi_endpoint *ep,
+				   enum iscsi_param param, char *buf)
+{
+	struct iser_conn *ib_conn = ep->dd_data;
+	int len;
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_PORT:
+	case ISCSI_PARAM_CONN_ADDRESS:
+		if (!ib_conn || !ib_conn->cma_id)
+			return -ENOTCONN;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+					&ib_conn->cma_id->route.addr.dst_addr,
+					param, buf);
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return len;
+}
+
 static struct iscsi_endpoint *
 iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
 		      int non_blocking)
@@ -637,6 +660,8 @@ static struct iscsi_transport iscsi_iser_transport = {
 				  ISCSI_MAX_BURST |
 				  ISCSI_PDU_INORDER_EN |
 				  ISCSI_DATASEQ_INORDER_EN |
+				  ISCSI_CONN_PORT |
+				  ISCSI_CONN_ADDRESS |
 				  ISCSI_EXP_STATSN |
 				  ISCSI_PERSISTENT_PORT |
 				  ISCSI_PERSISTENT_ADDRESS |
@@ -659,6 +684,7 @@ static struct iscsi_transport iscsi_iser_transport = {
 	.destroy_conn           = iscsi_iser_conn_destroy,
 	.set_param              = iscsi_iser_set_param,
 	.get_conn_param		= iscsi_conn_get_param,
+	.get_ep_param		= iscsi_iser_get_ep_param,
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn             = iscsi_iser_conn_start,
 	.stop_conn              = iscsi_iser_conn_stop,
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 1903c0f..23e82e4 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -161,16 +161,6 @@ config INPUT_APMPOWER
 	  To compile this driver as a module, choose M here: the
 	  module will be called apm-power.
 
-config XEN_KBDDEV_FRONTEND
-	tristate "Xen virtual keyboard and mouse support"
-	depends on XEN_FBDEV_FRONTEND
-	default y
-	select XEN_XENBUS_FRONTEND
-	help
-	  This driver implements the front-end of the Xen virtual
-	  keyboard and mouse device driver.  It communicates with a back-end
-	  in another domain.
-
 comment "Input Device Drivers"
 
 source "drivers/input/keyboard/Kconfig"
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 09614ce..0c78949 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -24,5 +24,3 @@ obj-$(CONFIG_INPUT_TOUCHSCREEN)	+= touchscreen/
 obj-$(CONFIG_INPUT_MISC)	+= misc/
 
 obj-$(CONFIG_INPUT_APMPOWER)	+= apm-power.o
-
-obj-$(CONFIG_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index c8471a2..7f42d3a 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -321,6 +321,9 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
 	struct input_event event;
 	int retval;
 
+	if (count < input_event_size())
+		return -EINVAL;
+
 	retval = mutex_lock_interruptible(&evdev->mutex);
 	if (retval)
 		return retval;
@@ -330,17 +333,16 @@ static ssize_t evdev_write(struct file *file, const char __user *buffer,
 		goto out;
 	}
 
-	while (retval < count) {
-
+	do {
 		if (input_event_from_user(buffer + retval, &event)) {
 			retval = -EFAULT;
 			goto out;
 		}
+		retval += input_event_size();
 
 		input_inject_event(&evdev->handle,
 				   event.type, event.code, event.value);
-		retval += input_event_size();
-	}
+	} while (retval + input_event_size() <= count);
 
  out:
 	mutex_unlock(&evdev->mutex);
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 0559e30..3037842 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -192,7 +192,7 @@ static struct attribute_group input_polldev_attribute_group = {
 };
 
 /**
- * input_allocate_polled_device - allocated memory polled device
+ * input_allocate_polled_device - allocate memory for polled device
  *
  * The function allocates memory for a polled device and also
  * for an input device associated with this polled device.
@@ -239,7 +239,7 @@ EXPORT_SYMBOL(input_free_polled_device);
  * with input layer. The device should be allocated with call to
  * input_allocate_polled_device(). Callers should also set up poll()
  * method and set up capabilities (id, name, phys, bits) of the
- * corresponing input_dev structure.
+ * corresponding input_dev structure.
  */
 int input_register_polled_device(struct input_polled_dev *dev)
 {
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 11905b6..d6e8bd8 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -791,22 +791,9 @@ int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
 	int retval;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
-
-	if (dev->getkeycode) {
-		/*
-		 * Support for legacy drivers, that don't implement the new
-		 * ioctls
-		 */
-		u32 scancode = ke->index;
-
-		memcpy(ke->scancode, &scancode, sizeof(scancode));
-		ke->len = sizeof(scancode);
-		retval = dev->getkeycode(dev, scancode, &ke->keycode);
-	} else {
-		retval = dev->getkeycode_new(dev, ke);
-	}
-
+	retval = dev->getkeycode(dev, ke);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
+
 	return retval;
 }
 EXPORT_SYMBOL(input_get_keycode);
@@ -831,35 +818,7 @@ int input_set_keycode(struct input_dev *dev,
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 
-	if (dev->setkeycode) {
-		/*
-		 * Support for legacy drivers, that don't implement the new
-		 * ioctls
-		 */
-		unsigned int scancode;
-
-		retval = input_scancode_to_scalar(ke, &scancode);
-		if (retval)
-			goto out;
-
-		/*
-		 * We need to know the old scancode, in order to generate a
-		 * keyup effect, if the set operation happens successfully
-		 */
-		if (!dev->getkeycode) {
-			retval = -EINVAL;
-			goto out;
-		}
-
-		retval = dev->getkeycode(dev, scancode, &old_keycode);
-		if (retval)
-			goto out;
-
-		retval = dev->setkeycode(dev, scancode, ke->keycode);
-	} else {
-		retval = dev->setkeycode_new(dev, ke, &old_keycode);
-	}
-
+	retval = dev->setkeycode(dev, ke, &old_keycode);
 	if (retval)
 		goto out;
 
@@ -1846,11 +1805,11 @@ int input_register_device(struct input_dev *dev)
 		dev->rep[REP_PERIOD] = 33;
 	}
 
-	if (!dev->getkeycode && !dev->getkeycode_new)
-		dev->getkeycode_new = input_default_getkeycode;
+	if (!dev->getkeycode)
+		dev->getkeycode = input_default_getkeycode;
 
-	if (!dev->setkeycode && !dev->setkeycode_new)
-		dev->setkeycode_new = input_default_setkeycode;
+	if (!dev->setkeycode)
+		dev->setkeycode = input_default_setkeycode;
 
 	dev_set_name(&dev->dev, "input%ld",
 		     (unsigned long) atomic_inc_return(&input_no) - 1);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index c7a9202..b16bed0 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -112,6 +112,16 @@ config KEYBOARD_ATKBD_RDI_KEYCODES
 	  right-hand column will be interpreted as the key shown in the
 	  left-hand column.
 
+config KEYBOARD_QT1070
+       tristate "Atmel AT42QT1070 Touch Sensor Chip"
+       depends on I2C
+       help
+         Say Y here if you want to use Atmel AT42QT1070 QTouch
+         Sensor chip as input device.
+
+         To compile this driver as a module, choose M here:
+         the module will be called qt1070
+
 config KEYBOARD_QT2160
 	tristate "Atmel AT42QT2160 Touch Sensor Chip"
 	depends on I2C && EXPERIMENTAL
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 468c627..878e6c2 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_KEYBOARD_OMAP4)		+= omap4-keypad.o
 obj-$(CONFIG_KEYBOARD_OPENCORES)	+= opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)	+= pxa930_rotary.o
+obj-$(CONFIG_KEYBOARD_QT1070)           += qt1070.o
 obj-$(CONFIG_KEYBOARD_QT2160)		+= qt2160.o
 obj-$(CONFIG_KEYBOARD_SAMSUNG)		+= samsung-keypad.o
 obj-$(CONFIG_KEYBOARD_SH_KEYSC)		+= sh_keysc.o
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index f7c2a16..b732870 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/leds.h>
+#include <linux/pm.h>
 #include <linux/i2c/lm8323.h>
 #include <linux/slab.h>
 
@@ -802,8 +803,9 @@ static int __devexit lm8323_remove(struct i2c_client *client)
  * We don't need to explicitly suspend the chip, as it already switches off
  * when there's no activity.
  */
-static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
+static int lm8323_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 	int i;
 
@@ -821,8 +823,9 @@ static int lm8323_suspend(struct i2c_client *client, pm_message_t mesg)
 	return 0;
 }
 
-static int lm8323_resume(struct i2c_client *client)
+static int lm8323_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 	int i;
 
@@ -839,11 +842,10 @@ static int lm8323_resume(struct i2c_client *client)
 
 	return 0;
 }
-#else
-#define lm8323_suspend	NULL
-#define lm8323_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
+
 static const struct i2c_device_id lm8323_id[] = {
 	{ "lm8323", 0 },
 	{ }
@@ -852,11 +854,10 @@ static const struct i2c_device_id lm8323_id[] = {
 static struct i2c_driver lm8323_i2c_driver = {
 	.driver = {
 		.name	= "lm8323",
+		.pm	= &lm8323_pm_ops,
 	},
 	.probe		= lm8323_probe,
 	.remove		= __devexit_p(lm8323_remove),
-	.suspend	= lm8323_suspend,
-	.resume		= lm8323_resume,
 	.id_table	= lm8323_id,
 };
 MODULE_DEVICE_TABLE(i2c, lm8323_id);
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index 9091ff5..5afe35a 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 
@@ -271,8 +272,10 @@ static int __devexit max7359_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int max7359_suspend(struct i2c_client *client, pm_message_t mesg)
+static int max7359_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	max7359_fall_deepsleep(client);
 
 	if (device_may_wakeup(&client->dev))
@@ -281,8 +284,10 @@ static int max7359_suspend(struct i2c_client *client, pm_message_t mesg)
 	return 0;
 }
 
-static int max7359_resume(struct i2c_client *client)
+static int max7359_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	if (device_may_wakeup(&client->dev))
 		disable_irq_wake(client->irq);
 
@@ -291,11 +296,10 @@ static int max7359_resume(struct i2c_client *client)
 
 	return 0;
 }
-#else
-#define max7359_suspend	NULL
-#define max7359_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
+
 static const struct i2c_device_id max7359_ids[] = {
 	{ "max7359", 0 },
 	{ }
@@ -305,11 +309,10 @@ MODULE_DEVICE_TABLE(i2c, max7359_ids);
 static struct i2c_driver max7359_i2c_driver = {
 	.driver = {
 		.name = "max7359",
+		.pm   = &max7359_pm,
 	},
 	.probe		= max7359_probe,
 	.remove		= __devexit_p(max7359_remove),
-	.suspend	= max7359_suspend,
-	.resume		= max7359_resume,
 	.id_table	= max7359_ids,
 };
 
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index 63b849d..af1aab3 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -1,5 +1,5 @@
 /*
- * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller
+ * Touchkey driver for MELFAS MCS5000/5080 controller
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
  * Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 /* MCS5000 Touchkey */
 #define MCS5000_TOUCHKEY_STATUS		0x04
@@ -45,6 +46,8 @@ struct mcs_touchkey_chip {
 };
 
 struct mcs_touchkey_data {
+	void (*poweron)(bool);
+
 	struct i2c_client *client;
 	struct input_dev *input_dev;
 	struct mcs_touchkey_chip chip;
@@ -169,6 +172,11 @@ static int __devinit mcs_touchkey_probe(struct i2c_client *client,
 	if (pdata->cfg_pin)
 		pdata->cfg_pin();
 
+	if (pdata->poweron) {
+		data->poweron = pdata->poweron;
+		data->poweron(true);
+	}
+
 	error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
 			IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
 	if (error) {
@@ -196,12 +204,57 @@ static int __devexit mcs_touchkey_remove(struct i2c_client *client)
 	struct mcs_touchkey_data *data = i2c_get_clientdata(client);
 
 	free_irq(client->irq, data);
+	if (data->poweron)
+		data->poweron(false);
 	input_unregister_device(data->input_dev);
 	kfree(data);
 
 	return 0;
 }
 
+static void mcs_touchkey_shutdown(struct i2c_client *client)
+{
+	struct mcs_touchkey_data *data = i2c_get_clientdata(client);
+
+	if (data->poweron)
+		data->poweron(false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mcs_touchkey_suspend(struct device *dev)
+{
+	struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	/* Disable the work */
+	disable_irq(client->irq);
+
+	/* Finally turn off the power */
+	if (data->poweron)
+		data->poweron(false);
+
+	return 0;
+}
+
+static int mcs_touchkey_resume(struct device *dev)
+{
+	struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	/* Enable the device first */
+	if (data->poweron)
+		data->poweron(true);
+
+	/* Enable irq again */
+	enable_irq(client->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
+			 mcs_touchkey_suspend, mcs_touchkey_resume);
+
 static const struct i2c_device_id mcs_touchkey_id[] = {
 	{ "mcs5000_touchkey", MCS5000_TOUCHKEY },
 	{ "mcs5080_touchkey", MCS5080_TOUCHKEY },
@@ -213,9 +266,11 @@ static struct i2c_driver mcs_touchkey_driver = {
 	.driver = {
 		.name	= "mcs_touchkey",
 		.owner	= THIS_MODULE,
+		.pm	= &mcs_touchkey_pm_ops,
 	},
 	.probe		= mcs_touchkey_probe,
 	.remove		= __devexit_p(mcs_touchkey_remove),
+	.shutdown       = mcs_touchkey_shutdown,
 	.id_table	= mcs_touchkey_id,
 };
 
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index 45bd097..c51a3c4 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -29,6 +29,7 @@
 #include <linux/io.h>
 #include <linux/input.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/omap4-keypad.h>
 
@@ -80,20 +81,6 @@ struct omap4_keypad {
 	unsigned short keymap[];
 };
 
-static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
-{
-	__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
-			keypad_data->base + OMAP4_KBD_CTRL);
-	__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
-			keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
-	__raw_writel(OMAP4_VAL_IRQDISABLE,
-			keypad_data->base + OMAP4_KBD_IRQSTATUS);
-	__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
-			keypad_data->base + OMAP4_KBD_IRQENABLE);
-	__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
-			keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
-}
-
 /* Interrupt handler */
 static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
 {
@@ -144,6 +131,49 @@ static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int omap4_keypad_open(struct input_dev *input)
+{
+	struct omap4_keypad *keypad_data = input_get_drvdata(input);
+
+	pm_runtime_get_sync(input->dev.parent);
+
+	disable_irq(keypad_data->irq);
+
+	__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
+			keypad_data->base + OMAP4_KBD_CTRL);
+	__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
+			keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
+	__raw_writel(OMAP4_VAL_IRQDISABLE,
+			keypad_data->base + OMAP4_KBD_IRQSTATUS);
+	__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+			keypad_data->base + OMAP4_KBD_IRQENABLE);
+	__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
+			keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+
+	enable_irq(keypad_data->irq);
+
+	return 0;
+}
+
+static void omap4_keypad_close(struct input_dev *input)
+{
+	struct omap4_keypad *keypad_data = input_get_drvdata(input);
+
+	disable_irq(keypad_data->irq);
+
+	/* Disable interrupts */
+	__raw_writel(OMAP4_VAL_IRQDISABLE,
+		     keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+	/* clear pending interrupts */
+	__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
+			keypad_data->base + OMAP4_KBD_IRQSTATUS);
+
+	enable_irq(keypad_data->irq);
+
+	pm_runtime_put_sync(input->dev.parent);
+}
+
 static int __devinit omap4_keypad_probe(struct platform_device *pdev)
 {
 	const struct omap4_keypad_platform_data *pdata;
@@ -225,6 +255,9 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0001;
 
+	input_dev->open = omap4_keypad_open;
+	input_dev->close = omap4_keypad_close;
+
 	input_dev->keycode	= keypad_data->keymap;
 	input_dev->keycodesize	= sizeof(keypad_data->keymap[0]);
 	input_dev->keycodemax	= max_keys;
@@ -239,8 +272,6 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
 	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
 			input_dev->keycode, input_dev->keybit);
 
-	omap4_keypad_config(keypad_data);
-
 	error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
 			     IRQF_TRIGGER_RISING,
 			     "omap4-keypad", keypad_data);
@@ -249,17 +280,19 @@ static int __devinit omap4_keypad_probe(struct platform_device *pdev)
 		goto err_free_input;
 	}
 
+	pm_runtime_enable(&pdev->dev);
+
 	error = input_register_device(keypad_data->input);
 	if (error < 0) {
 		dev_err(&pdev->dev, "failed to register input device\n");
-		goto err_free_irq;
+		goto err_pm_disable;
 	}
 
-
 	platform_set_drvdata(pdev, keypad_data);
 	return 0;
 
-err_free_irq:
+err_pm_disable:
+	pm_runtime_disable(&pdev->dev);
 	free_irq(keypad_data->irq, keypad_data);
 err_free_input:
 	input_free_device(input_dev);
@@ -278,6 +311,9 @@ static int __devexit omap4_keypad_remove(struct platform_device *pdev)
 	struct resource *res;
 
 	free_irq(keypad_data->irq, keypad_data);
+
+	pm_runtime_disable(&pdev->dev);
+
 	input_unregister_device(keypad_data->input);
 
 	iounmap(keypad_data->base);
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
new file mode 100644
index 0000000..fba8404
--- /dev/null
+++ b/drivers/input/keyboard/qt1070.c
@@ -0,0 +1,276 @@
+/*
+ *  Atmel AT42QT1070 QTouch Sensor Controller
+ *
+ *  Copyright (C) 2011 Atmel
+ *
+ *  Authors: Bo Shen <voice.shen@atmel.com>
+ *
+ *  Base on AT42QT2160 driver by:
+ *  Raphael Derosso Pereira <raphaelpereira@gmail.com>
+ *  Copyright (C) 2009
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/i2c.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+
+/* Address for each register */
+#define CHIP_ID            0x00
+#define QT1070_CHIP_ID     0x2E
+
+#define FW_VERSION         0x01
+#define QT1070_FW_VERSION  0x15
+
+#define DET_STATUS         0x02
+
+#define KEY_STATUS         0x03
+
+/* Calibrate */
+#define CALIBRATE_CMD      0x38
+#define QT1070_CAL_TIME    200
+
+/* Reset */
+#define RESET              0x39
+#define QT1070_RESET_TIME  255
+
+/* AT42QT1070 support up to 7 keys */
+static const unsigned short qt1070_key2code[] = {
+	KEY_0, KEY_1, KEY_2, KEY_3,
+	KEY_4, KEY_5, KEY_6,
+};
+
+struct qt1070_data {
+	struct i2c_client *client;
+	struct input_dev *input;
+	unsigned int irq;
+	unsigned short keycodes[ARRAY_SIZE(qt1070_key2code)];
+	u8 last_keys;
+};
+
+static int qt1070_read(struct i2c_client *client, u8 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0)
+		dev_err(&client->dev,
+			"can not read register, returned %d\n", ret);
+
+	return ret;
+}
+
+static int qt1070_write(struct i2c_client *client, u8 reg, u8 data)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, reg, data);
+	if (ret < 0)
+		dev_err(&client->dev,
+			"can not write register, returned %d\n", ret);
+
+	return ret;
+}
+
+static bool __devinit qt1070_identify(struct i2c_client *client)
+{
+	int id, ver;
+
+	/* Read Chip ID */
+	id = qt1070_read(client, CHIP_ID);
+	if (id != QT1070_CHIP_ID) {
+		dev_err(&client->dev, "ID %d not supported\n", id);
+		return false;
+	}
+
+	/* Read firmware version */
+	ver = qt1070_read(client, FW_VERSION);
+	if (ver < 0) {
+		dev_err(&client->dev, "could not read the firmware version\n");
+		return false;
+	}
+
+	dev_info(&client->dev, "AT42QT1070 firmware version %x\n", ver);
+
+	return true;
+}
+
+static irqreturn_t qt1070_interrupt(int irq, void *dev_id)
+{
+	struct qt1070_data *data = dev_id;
+	struct i2c_client *client = data->client;
+	struct input_dev *input = data->input;
+	int i;
+	u8 new_keys, keyval, mask = 0x01;
+
+	/* Read the detected status register, thus clearing interrupt */
+	qt1070_read(client, DET_STATUS);
+
+	/* Read which key changed */
+	new_keys = qt1070_read(client, KEY_STATUS);
+
+	for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) {
+		keyval = new_keys & mask;
+		if ((data->last_keys & mask) != keyval)
+			input_report_key(input, data->keycodes[i], keyval);
+		mask <<= 1;
+	}
+	input_sync(input);
+
+	data->last_keys = new_keys;
+	return IRQ_HANDLED;
+}
+
+static int __devinit qt1070_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct qt1070_data *data;
+	struct input_dev *input;
+	int i;
+	int err;
+
+	err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
+	if (!err) {
+		dev_err(&client->dev, "%s adapter not supported\n",
+			dev_driver_string(&client->adapter->dev));
+		return -ENODEV;
+	}
+
+	if (!client->irq) {
+		dev_err(&client->dev, "please assign the irq to this device\n");
+		return -EINVAL;
+	}
+
+	/* Identify the qt1070 chip */
+	if (!qt1070_identify(client))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!data || !input) {
+		dev_err(&client->dev, "insufficient memory\n");
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	data->client = client;
+	data->input = input;
+	data->irq = client->irq;
+
+	input->name = "AT42QT1070 QTouch Sensor";
+	input->dev.parent = &client->dev;
+	input->id.bustype = BUS_I2C;
+
+	/* Add the keycode */
+	input->keycode = data->keycodes;
+	input->keycodesize = sizeof(data->keycodes[0]);
+	input->keycodemax = ARRAY_SIZE(qt1070_key2code);
+
+	__set_bit(EV_KEY, input->evbit);
+
+	for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) {
+		data->keycodes[i] = qt1070_key2code[i];
+		__set_bit(qt1070_key2code[i], input->keybit);
+	}
+
+	/* Calibrate device */
+	qt1070_write(client, CALIBRATE_CMD, 1);
+	msleep(QT1070_CAL_TIME);
+
+	/* Soft reset */
+	qt1070_write(client, RESET, 1);
+	msleep(QT1070_RESET_TIME);
+
+	err = request_threaded_irq(client->irq, NULL, qt1070_interrupt,
+		IRQF_TRIGGER_NONE, client->dev.driver->name, data);
+	if (err) {
+		dev_err(&client->dev, "fail to request irq\n");
+		goto err_free_mem;
+	}
+
+	/* Register the input device */
+	err = input_register_device(data->input);
+	if (err) {
+		dev_err(&client->dev, "Failed to register input device\n");
+		goto err_free_irq;
+	}
+
+	i2c_set_clientdata(client, data);
+
+	/* Read to clear the chang line */
+	qt1070_read(client, DET_STATUS);
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, data);
+err_free_mem:
+	input_free_device(input);
+	kfree(data);
+	return err;
+}
+
+static int __devexit qt1070_remove(struct i2c_client *client)
+{
+	struct qt1070_data *data = i2c_get_clientdata(client);
+
+	/* Release IRQ */
+	free_irq(client->irq, data);
+
+	input_unregister_device(data->input);
+	kfree(data);
+
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static const struct i2c_device_id qt1070_id[] = {
+	{ "qt1070", 0 },
+	{ },
+};
+
+static struct i2c_driver qt1070_driver = {
+	.driver	= {
+		.name	= "qt1070",
+		.owner	= THIS_MODULE,
+	},
+	.id_table	= qt1070_id,
+	.probe		= qt1070_probe,
+	.remove		= __devexit_p(qt1070_remove),
+};
+
+static int __init qt1070_init(void)
+{
+	return i2c_add_driver(&qt1070_driver);
+}
+module_init(qt1070_init);
+
+static void __exit qt1070_exit(void)
+{
+	i2c_del_driver(&qt1070_driver);
+}
+module_exit(qt1070_exit);
+
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
index dbbe761..99122f5 100644
--- a/drivers/input/keyboard/tc3589x-keypad.c
+++ b/drivers/input/keyboard/tc3589x-keypad.c
@@ -402,7 +402,7 @@ static int __devexit tc3589x_keypad_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int tc3589x_keypad_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -439,19 +439,19 @@ static int tc3589x_keypad_resume(struct device *dev)
 
 	return 0;
 }
-
-static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
-			       tc3589x_keypad_suspend, tc3589x_keypad_resume);
 #endif
 
+static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
+			 tc3589x_keypad_suspend, tc3589x_keypad_resume);
+
 static struct platform_driver tc3589x_keypad_driver = {
-	.driver.name  = "tc3589x-keypad",
-	.driver.owner = THIS_MODULE,
-#ifdef CONFIG_PM
-	.driver.pm = &tc3589x_keypad_dev_pm_ops,
-#endif
-	.probe = tc3589x_keypad_probe,
-	.remove = __devexit_p(tc3589x_keypad_remove),
+	.driver	= {
+		.name	= "tc3589x-keypad",
+		.owner	= THIS_MODULE,
+		.pm	= &tc3589x_keypad_dev_pm_ops,
+	},
+	.probe	= tc3589x_keypad_probe,
+	.remove	= __devexit_p(tc3589x_keypad_remove),
 };
 
 static int __init tc3589x_keypad_init(void)
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index 800fbcc..3afea3f 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -297,6 +297,7 @@ static int __devinit tca6416_keypad_probe(struct i2c_client *client,
 	}
 
 	i2c_set_clientdata(client, chip);
+	device_init_wakeup(&client->dev, 1);
 
 	return 0;
 
@@ -326,10 +327,37 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client)
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tca6416_keypad_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(chip->irqnum);
+
+	return 0;
+}
+
+static int tca6416_keypad_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(chip->irqnum);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops,
+			 tca6416_keypad_suspend, tca6416_keypad_resume);
 
 static struct i2c_driver tca6416_keypad_driver = {
 	.driver = {
 		.name	= "tca6416-keypad",
+		.pm	= &tca6416_keypad_dev_pm_ops,
 	},
 	.probe		= tca6416_keypad_probe,
 	.remove		= __devexit_p(tca6416_keypad_remove),
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index b0c6772..f9cf088 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -454,4 +454,17 @@ config INPUT_CMA3000_I2C
 	  To compile this driver as a module, choose M here: the
 	  module will be called cma3000_d0x_i2c.
 
+config INPUT_XEN_KBDDEV_FRONTEND
+	tristate "Xen virtual keyboard and mouse support"
+	depends on XEN_FBDEV_FRONTEND
+	default y
+	select XEN_XENBUS_FRONTEND
+	help
+	  This driver implements the front-end of the Xen virtual
+	  keyboard and mouse device driver.  It communicates with a back-end
+	  in another domain.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called xen-kbdfront.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 9b47971..e3f7984 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -42,5 +42,6 @@ obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
+obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
 
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index 2bef8fa..e21deb1 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -10,23 +10,23 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 #include "ad714x.h"
 
 #ifdef CONFIG_PM
-static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int ad714x_i2c_suspend(struct device *dev)
 {
-	return ad714x_disable(i2c_get_clientdata(client));
+	return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev)));
 }
 
-static int ad714x_i2c_resume(struct i2c_client *client)
+static int ad714x_i2c_resume(struct device *dev)
 {
-	return ad714x_enable(i2c_get_clientdata(client));
+	return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev)));
 }
-#else
-# define ad714x_i2c_suspend NULL
-# define ad714x_i2c_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume);
+
 static int ad714x_i2c_write(struct device *dev, unsigned short reg,
 				unsigned short data)
 {
@@ -114,11 +114,10 @@ MODULE_DEVICE_TABLE(i2c, ad714x_id);
 static struct i2c_driver ad714x_i2c_driver = {
 	.driver = {
 		.name = "ad714x_captouch",
+		.pm   = &ad714x_i2c_pm,
 	},
 	.probe    = ad714x_i2c_probe,
 	.remove   = __devexit_p(ad714x_i2c_remove),
-	.suspend  = ad714x_i2c_suspend,
-	.resume	  = ad714x_i2c_resume,
 	.id_table = ad714x_id,
 };
 
diff --git a/drivers/input/misc/ad714x-spi.c b/drivers/input/misc/ad714x-spi.c
index 7f8dedf..4120dd5 100644
--- a/drivers/input/misc/ad714x-spi.c
+++ b/drivers/input/misc/ad714x-spi.c
@@ -9,6 +9,7 @@
 #include <linux/input.h>	/* BUS_I2C */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include "ad714x.h"
 
@@ -16,20 +17,19 @@
 #define AD714x_SPI_READ            BIT(10)
 
 #ifdef CONFIG_PM
-static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message)
+static int ad714x_spi_suspend(struct device *dev)
 {
-	return ad714x_disable(spi_get_drvdata(spi));
+	return ad714x_disable(spi_get_drvdata(to_spi_device(dev)));
 }
 
-static int ad714x_spi_resume(struct spi_device *spi)
+static int ad714x_spi_resume(struct device *dev)
 {
-	return ad714x_enable(spi_get_drvdata(spi));
+	return ad714x_enable(spi_get_drvdata(to_spi_device(dev)));
 }
-#else
-# define ad714x_spi_suspend NULL
-# define ad714x_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);
+
 static int ad714x_spi_read(struct device *dev, unsigned short reg,
 		unsigned short *data)
 {
@@ -79,11 +79,10 @@ static struct spi_driver ad714x_spi_driver = {
 	.driver = {
 		.name	= "ad714x_captouch",
 		.owner	= THIS_MODULE,
+		.pm	= &ad714x_spi_pm,
 	},
 	.probe		= ad714x_spi_probe,
 	.remove		= __devexit_p(ad714x_spi_remove),
-	.suspend	= ad714x_spi_suspend,
-	.resume		= ad714x_spi_resume,
 };
 
 static __init int ad714x_spi_init(void)
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index 0779724..ccacf2b 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 #include "adxl34x.h"
 
 static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
@@ -105,8 +106,9 @@ static int __devexit adxl34x_i2c_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int adxl34x_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct adxl34x *ac = i2c_get_clientdata(client);
 
 	adxl34x_suspend(ac);
@@ -114,19 +116,20 @@ static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message)
 	return 0;
 }
 
-static int adxl34x_i2c_resume(struct i2c_client *client)
+static int adxl34x_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct adxl34x *ac = i2c_get_clientdata(client);
 
 	adxl34x_resume(ac);
 
 	return 0;
 }
-#else
-# define adxl34x_i2c_suspend NULL
-# define adxl34x_i2c_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
+			 adxl34x_i2c_resume);
+
 static const struct i2c_device_id adxl34x_id[] = {
 	{ "adxl34x", 0 },
 	{ }
@@ -138,11 +141,10 @@ static struct i2c_driver adxl34x_driver = {
 	.driver = {
 		.name = "adxl34x",
 		.owner = THIS_MODULE,
+		.pm = &adxl34x_i2c_pm,
 	},
 	.probe    = adxl34x_i2c_probe,
 	.remove   = __devexit_p(adxl34x_i2c_remove),
-	.suspend  = adxl34x_i2c_suspend,
-	.resume   = adxl34x_i2c_resume,
 	.id_table = adxl34x_id,
 };
 
diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c
index 782de9e..f29de22 100644
--- a/drivers/input/misc/adxl34x-spi.c
+++ b/drivers/input/misc/adxl34x-spi.c
@@ -10,6 +10,7 @@
 #include <linux/input.h>	/* BUS_SPI */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include "adxl34x.h"
 
@@ -57,7 +58,7 @@ static int adxl34x_spi_read_block(struct device *dev,
 	return (status < 0) ? status : 0;
 }
 
-static const struct adxl34x_bus_ops adx134x_spi_bops = {
+static const struct adxl34x_bus_ops adxl34x_spi_bops = {
 	.bustype	= BUS_SPI,
 	.write		= adxl34x_spi_write,
 	.read		= adxl34x_spi_read,
@@ -76,7 +77,7 @@ static int __devinit adxl34x_spi_probe(struct spi_device *spi)
 
 	ac = adxl34x_probe(&spi->dev, spi->irq,
 			   spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY,
-			   &adx134x_spi_bops);
+			   &adxl34x_spi_bops);
 
 	if (IS_ERR(ac))
 		return PTR_ERR(ac);
@@ -94,8 +95,9 @@ static int __devexit adxl34x_spi_remove(struct spi_device *spi)
 }
 
 #ifdef CONFIG_PM
-static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message)
+static int adxl34x_spi_suspend(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
 	adxl34x_suspend(ac);
@@ -103,29 +105,29 @@ static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message)
 	return 0;
 }
 
-static int adxl34x_spi_resume(struct spi_device *spi)
+static int adxl34x_spi_resume(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
 	adxl34x_resume(ac);
 
 	return 0;
 }
-#else
-# define adxl34x_spi_suspend NULL
-# define adxl34x_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
+			 adxl34x_spi_resume);
+
 static struct spi_driver adxl34x_driver = {
 	.driver = {
 		.name = "adxl34x",
 		.bus = &spi_bus_type,
 		.owner = THIS_MODULE,
+		.pm = &adxl34x_spi_pm,
 	},
 	.probe   = adxl34x_spi_probe,
 	.remove  = __devexit_p(adxl34x_spi_remove),
-	.suspend = adxl34x_spi_suspend,
-	.resume  = adxl34x_spi_resume,
 };
 
 static int __init adxl34x_spi_init(void)
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c
index 0b0e9be..9ccdb82 100644
--- a/drivers/input/misc/ati_remote2.c
+++ b/drivers/input/misc/ati_remote2.c
@@ -612,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
 	idev->open = ati_remote2_open;
 	idev->close = ati_remote2_close;
 
-	idev->getkeycode_new = ati_remote2_getkeycode;
-	idev->setkeycode_new = ati_remote2_setkeycode;
+	idev->getkeycode = ati_remote2_getkeycode;
+	idev->setkeycode = ati_remote2_setkeycode;
 
 	idev->name = ar2->name;
 	idev->phys = ar2->phys;
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index 8e130bf..0122f53 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -173,18 +173,16 @@ static int __devinit sparcspkr_probe(struct device *dev)
 	return 0;
 }
 
-static int sparcspkr_shutdown(struct platform_device *dev)
+static void sparcspkr_shutdown(struct platform_device *dev)
 {
 	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
 	struct input_dev *input_dev = state->input_dev;
 
 	/* turn off the speaker */
 	state->event(input_dev, EV_SND, SND_BELL, 0);
-
-	return 0;
 }
 
-static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bbc_beep_probe(struct platform_device *op)
 {
 	struct sparcspkr_state *state;
 	struct bbc_beep_info *info;
@@ -258,7 +256,7 @@ static const struct of_device_id bbc_beep_match[] = {
 	{},
 };
 
-static struct of_platform_driver bbc_beep_driver = {
+static struct platform_driver bbc_beep_driver = {
 	.driver = {
 		.name = "bbcbeep",
 		.owner = THIS_MODULE,
@@ -269,7 +267,7 @@ static struct of_platform_driver bbc_beep_driver = {
 	.shutdown	= sparcspkr_shutdown,
 };
 
-static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit grover_beep_probe(struct platform_device *op)
 {
 	struct sparcspkr_state *state;
 	struct grover_beep_info *info;
@@ -340,7 +338,7 @@ static const struct of_device_id grover_beep_match[] = {
 	{},
 };
 
-static struct of_platform_driver grover_beep_driver = {
+static struct platform_driver grover_beep_driver = {
 	.driver = {
 		.name = "groverbeep",
 		.owner = THIS_MODULE,
@@ -353,12 +351,12 @@ static struct of_platform_driver grover_beep_driver = {
 
 static int __init sparcspkr_init(void)
 {
-	int err = of_register_platform_driver(&bbc_beep_driver);
+	int err = platform_driver_register(&bbc_beep_driver);
 
 	if (!err) {
-		err = of_register_platform_driver(&grover_beep_driver);
+		err = platform_driver_register(&grover_beep_driver);
 		if (err)
-			of_unregister_platform_driver(&bbc_beep_driver);
+			platform_driver_unregister(&bbc_beep_driver);
 	}
 
 	return err;
@@ -366,8 +364,8 @@ static int __init sparcspkr_init(void)
 
 static void __exit sparcspkr_exit(void)
 {
-	of_unregister_platform_driver(&bbc_beep_driver);
-	of_unregister_platform_driver(&grover_beep_driver);
+	platform_driver_unregister(&bbc_beep_driver);
+	platform_driver_unregister(&grover_beep_driver);
 }
 
 module_init(sparcspkr_init);
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 82542a1..364bdf4 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -347,8 +347,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 {
 	struct uinput_user_dev	*user_dev;
 	struct input_dev	*dev;
-	char			*name;
-	int			i, size;
+	int			i;
 	int			retval;
 
 	if (count != sizeof(struct uinput_user_dev))
@@ -362,30 +361,25 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu
 
 	dev = udev->dev;
 
-	user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
-	if (!user_dev)
-		return -ENOMEM;
-
-	if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
-		retval = -EFAULT;
-		goto exit;
-	}
+	user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
+	if (IS_ERR(user_dev))
+		return PTR_ERR(user_dev);
 
 	udev->ff_effects_max = user_dev->ff_effects_max;
 
-	size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
-	if (!size) {
+	/* Ensure name is filled in */
+	if (!user_dev->name[0]) {
 		retval = -EINVAL;
 		goto exit;
 	}
 
 	kfree(dev->name);
-	dev->name = name = kmalloc(size, GFP_KERNEL);
-	if (!name) {
+	dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
+			     GFP_KERNEL);
+	if (!dev->name) {
 		retval = -ENOMEM;
 		goto exit;
 	}
-	strlcpy(name, user_dev->name, size);
 
 	dev->id.bustype	= user_dev->id.bustype;
 	dev->id.vendor	= user_dev->id.vendor;
@@ -622,7 +616,6 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 	struct uinput_ff_upload ff_up;
 	struct uinput_ff_erase  ff_erase;
 	struct uinput_request   *req;
-	int                     length;
 	char			*phys;
 
 	retval = mutex_lock_interruptible(&udev->mutex);
@@ -689,24 +682,15 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
 				retval = -EINVAL;
 				goto out;
 			}
-			length = strnlen_user(p, 1024);
-			if (length <= 0) {
-				retval = -EFAULT;
-				break;
+
+			phys = strndup_user(p, 1024);
+			if (IS_ERR(phys)) {
+				retval = PTR_ERR(phys);
+				goto out;
 			}
+
 			kfree(udev->dev->phys);
-			udev->dev->phys = phys = kmalloc(length, GFP_KERNEL);
-			if (!phys) {
-				retval = -ENOMEM;
-				break;
-			}
-			if (copy_from_user(phys, p, length)) {
-				udev->dev->phys = NULL;
-				kfree(phys);
-				retval = -EFAULT;
-				break;
-			}
-			phys[length - 1] = '\0';
+			udev->dev->phys = phys;
 			break;
 
 		case UI_BEGIN_FF_UPLOAD:
diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c
new file mode 100644
index 0000000..7077f9b
--- /dev/null
+++ b/drivers/input/misc/xen-kbdfront.c
@@ -0,0 +1,385 @@
+/*
+ * Xen para-virtual input device
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/input/mouse/sermouse.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
+#include <xen/events.h>
+#include <xen/page.h>
+#include <xen/grant_table.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/kbdif.h>
+#include <xen/xenbus.h>
+
+struct xenkbd_info {
+	struct input_dev *kbd;
+	struct input_dev *ptr;
+	struct xenkbd_page *page;
+	int gref;
+	int irq;
+	struct xenbus_device *xbdev;
+	char phys[32];
+};
+
+static int xenkbd_remove(struct xenbus_device *);
+static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
+static void xenkbd_disconnect_backend(struct xenkbd_info *);
+
+/*
+ * Note: if you need to send out events, see xenfb_do_update() for how
+ * to do that.
+ */
+
+static irqreturn_t input_handler(int rq, void *dev_id)
+{
+	struct xenkbd_info *info = dev_id;
+	struct xenkbd_page *page = info->page;
+	__u32 cons, prod;
+
+	prod = page->in_prod;
+	if (prod == page->in_cons)
+		return IRQ_HANDLED;
+	rmb();			/* ensure we see ring contents up to prod */
+	for (cons = page->in_cons; cons != prod; cons++) {
+		union xenkbd_in_event *event;
+		struct input_dev *dev;
+		event = &XENKBD_IN_RING_REF(page, cons);
+
+		dev = info->ptr;
+		switch (event->type) {
+		case XENKBD_TYPE_MOTION:
+			input_report_rel(dev, REL_X, event->motion.rel_x);
+			input_report_rel(dev, REL_Y, event->motion.rel_y);
+			if (event->motion.rel_z)
+				input_report_rel(dev, REL_WHEEL,
+						 -event->motion.rel_z);
+			break;
+		case XENKBD_TYPE_KEY:
+			dev = NULL;
+			if (test_bit(event->key.keycode, info->kbd->keybit))
+				dev = info->kbd;
+			if (test_bit(event->key.keycode, info->ptr->keybit))
+				dev = info->ptr;
+			if (dev)
+				input_report_key(dev, event->key.keycode,
+						 event->key.pressed);
+			else
+				pr_warning("unhandled keycode 0x%x\n",
+					   event->key.keycode);
+			break;
+		case XENKBD_TYPE_POS:
+			input_report_abs(dev, ABS_X, event->pos.abs_x);
+			input_report_abs(dev, ABS_Y, event->pos.abs_y);
+			if (event->pos.rel_z)
+				input_report_rel(dev, REL_WHEEL,
+						 -event->pos.rel_z);
+			break;
+		}
+		if (dev)
+			input_sync(dev);
+	}
+	mb();			/* ensure we got ring contents */
+	page->in_cons = cons;
+	notify_remote_via_irq(info->irq);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit xenkbd_probe(struct xenbus_device *dev,
+				  const struct xenbus_device_id *id)
+{
+	int ret, i, abs;
+	struct xenkbd_info *info;
+	struct input_dev *kbd, *ptr;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+		return -ENOMEM;
+	}
+	dev_set_drvdata(&dev->dev, info);
+	info->xbdev = dev;
+	info->irq = -1;
+	info->gref = -1;
+	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
+
+	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+	if (!info->page)
+		goto error_nomem;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
+		abs = 0;
+	if (abs)
+		xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+
+	/* keyboard */
+	kbd = input_allocate_device();
+	if (!kbd)
+		goto error_nomem;
+	kbd->name = "Xen Virtual Keyboard";
+	kbd->phys = info->phys;
+	kbd->id.bustype = BUS_PCI;
+	kbd->id.vendor = 0x5853;
+	kbd->id.product = 0xffff;
+
+	__set_bit(EV_KEY, kbd->evbit);
+	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
+		__set_bit(i, kbd->keybit);
+	for (i = KEY_OK; i < KEY_MAX; i++)
+		__set_bit(i, kbd->keybit);
+
+	ret = input_register_device(kbd);
+	if (ret) {
+		input_free_device(kbd);
+		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
+		goto error;
+	}
+	info->kbd = kbd;
+
+	/* pointing device */
+	ptr = input_allocate_device();
+	if (!ptr)
+		goto error_nomem;
+	ptr->name = "Xen Virtual Pointer";
+	ptr->phys = info->phys;
+	ptr->id.bustype = BUS_PCI;
+	ptr->id.vendor = 0x5853;
+	ptr->id.product = 0xfffe;
+
+	if (abs) {
+		__set_bit(EV_ABS, ptr->evbit);
+		input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+		input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+	} else {
+		input_set_capability(ptr, EV_REL, REL_X);
+		input_set_capability(ptr, EV_REL, REL_Y);
+	}
+	input_set_capability(ptr, EV_REL, REL_WHEEL);
+
+	__set_bit(EV_KEY, ptr->evbit);
+	for (i = BTN_LEFT; i <= BTN_TASK; i++)
+		__set_bit(i, ptr->keybit);
+
+	ret = input_register_device(ptr);
+	if (ret) {
+		input_free_device(ptr);
+		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
+		goto error;
+	}
+	info->ptr = ptr;
+
+	ret = xenkbd_connect_backend(dev, info);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+ error_nomem:
+	ret = -ENOMEM;
+	xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+	xenkbd_remove(dev);
+	return ret;
+}
+
+static int xenkbd_resume(struct xenbus_device *dev)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+	xenkbd_disconnect_backend(info);
+	memset(info->page, 0, PAGE_SIZE);
+	return xenkbd_connect_backend(dev, info);
+}
+
+static int xenkbd_remove(struct xenbus_device *dev)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+	xenkbd_disconnect_backend(info);
+	if (info->kbd)
+		input_unregister_device(info->kbd);
+	if (info->ptr)
+		input_unregister_device(info->ptr);
+	free_page((unsigned long)info->page);
+	kfree(info);
+	return 0;
+}
+
+static int xenkbd_connect_backend(struct xenbus_device *dev,
+				  struct xenkbd_info *info)
+{
+	int ret, evtchn;
+	struct xenbus_transaction xbt;
+
+	ret = gnttab_grant_foreign_access(dev->otherend_id,
+	                                  virt_to_mfn(info->page), 0);
+	if (ret < 0)
+		return ret;
+	info->gref = ret;
+
+	ret = xenbus_alloc_evtchn(dev, &evtchn);
+	if (ret)
+		goto error_grant;
+	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
+					0, dev->devicetype, info);
+	if (ret < 0) {
+		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
+		goto error_evtchan;
+	}
+	info->irq = ret;
+
+ again:
+	ret = xenbus_transaction_start(&xbt);
+	if (ret) {
+		xenbus_dev_fatal(dev, ret, "starting transaction");
+		goto error_irqh;
+	}
+	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+			    virt_to_mfn(info->page));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    evtchn);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_transaction_end(xbt, 0);
+	if (ret) {
+		if (ret == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, ret, "completing transaction");
+		goto error_irqh;
+	}
+
+	xenbus_switch_state(dev, XenbusStateInitialised);
+	return 0;
+
+ error_xenbus:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, ret, "writing xenstore");
+ error_irqh:
+	unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+ error_evtchan:
+	xenbus_free_evtchn(dev, evtchn);
+ error_grant:
+	gnttab_end_foreign_access_ref(info->gref, 0);
+	info->gref = -1;
+	return ret;
+}
+
+static void xenkbd_disconnect_backend(struct xenkbd_info *info)
+{
+	if (info->irq >= 0)
+		unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+	if (info->gref >= 0)
+		gnttab_end_foreign_access_ref(info->gref, 0);
+	info->gref = -1;
+}
+
+static void xenkbd_backend_changed(struct xenbus_device *dev,
+				   enum xenbus_state backend_state)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+	int val;
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateInitWait:
+InitWait:
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateConnected:
+		/*
+		 * Work around xenbus race condition: If backend goes
+		 * through InitWait to Connected fast enough, we can
+		 * get Connected twice here.
+		 */
+		if (dev->state != XenbusStateConnected)
+			goto InitWait; /* no InitWait seen yet, fudge it */
+
+		/* Set input abs params to match backend screen res */
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "width", "%d", &val) > 0)
+			input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
+
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "height", "%d", &val) > 0)
+			input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
+
+		break;
+
+	case XenbusStateClosing:
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static const struct xenbus_device_id xenkbd_ids[] = {
+	{ "vkbd" },
+	{ "" }
+};
+
+static struct xenbus_driver xenkbd_driver = {
+	.name = "vkbd",
+	.owner = THIS_MODULE,
+	.ids = xenkbd_ids,
+	.probe = xenkbd_probe,
+	.remove = xenkbd_remove,
+	.resume = xenkbd_resume,
+	.otherend_changed = xenkbd_backend_changed,
+};
+
+static int __init xenkbd_init(void)
+{
+	if (!xen_pv_domain())
+		return -ENODEV;
+
+	/* Nothing to do if running in dom0. */
+	if (xen_initial_domain())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&xenkbd_driver);
+}
+
+static void __exit xenkbd_cleanup(void)
+{
+	xenbus_unregister_driver(&xenkbd_driver);
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vkbd");
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index ee82851..3aead91 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -63,6 +63,10 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+/* Macbook8 (unibody, March 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI	0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO	0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS	0x0247
 
 #define BCM5974_DEVICE(prod) {					\
 	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\
@@ -96,6 +100,10 @@ static const struct usb_device_id bcm5974_table[] = {
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
+	/* MacbookPro8 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
 	/* Terminating entry */
 	{}
 };
@@ -274,6 +282,18 @@ static const struct bcm5974_config bcm5974_config_table[] = {
 		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
 		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
 	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING5_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4415, 5050 },
+		{ DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
+	},
 	{}
 };
 
@@ -430,10 +450,6 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 		ptest = int2bound(&c->p, raw_p);
 		origin = raw2int(f->origin);
 
-		/* set the integrated button if applicable */
-		if (c->tp_type == TYPE2)
-			ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
-
 		/* while tracking finger still valid, count all fingers */
 		if (ptest > PRESSURE_LOW && origin) {
 			abs_p = ptest;
@@ -452,6 +468,10 @@ static int report_tp_state(struct bcm5974 *dev, int size)
 		}
 	}
 
+	/* set the integrated button if applicable */
+	if (c->tp_type == TYPE2)
+		ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
+
 	if (dev->fingers < nmin)
 		dev->fingers = nmin;
 	if (dev->fingers > nmax)
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index 0ae62f0..f6aa26d 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 #define DRIVER_NAME		"synaptics_i2c"
 /* maximum product id is 15 characters */
@@ -619,8 +620,9 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int synaptics_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
 	cancel_delayed_work_sync(&touch->dwork);
@@ -631,9 +633,10 @@ static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 	return 0;
 }
 
-static int synaptics_i2c_resume(struct i2c_client *client)
+static int synaptics_i2c_resume(struct device *dev)
 {
 	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
 	ret = synaptics_i2c_reset_config(client);
@@ -645,11 +648,11 @@ static int synaptics_i2c_resume(struct i2c_client *client)
 
 	return 0;
 }
-#else
-#define synaptics_i2c_suspend	NULL
-#define synaptics_i2c_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
+			 synaptics_i2c_resume);
+
 static const struct i2c_device_id synaptics_i2c_id_table[] = {
 	{ "synaptics_i2c", 0 },
 	{ },
@@ -660,13 +663,12 @@ static struct i2c_driver synaptics_i2c_driver = {
 	.driver = {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.pm	= &synaptics_i2c_pm,
 	},
 
 	.probe		= synaptics_i2c_probe,
 	.remove		= __devexit_p(synaptics_i2c_remove),
 
-	.suspend	= synaptics_i2c_suspend,
-	.resume		= synaptics_i2c_resume,
 	.id_table	= synaptics_i2c_id_table,
 };
 
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c
index 7998560..d363dc4 100644
--- a/drivers/input/serio/altera_ps2.c
+++ b/drivers/input/serio/altera_ps2.c
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #define DRV_NAME "altera_ps2"
 
@@ -173,6 +174,16 @@ static int __devexit altera_ps2_remove(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id altera_ps2_match[] = {
+	{ .compatible = "ALTR,ps2-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_ps2_match);
+#else /* CONFIG_OF */
+#define altera_ps2_match NULL
+#endif /* CONFIG_OF */
+
 /*
  * Our device driver structure
  */
@@ -182,6 +193,7 @@ static struct platform_driver altera_ps2_driver = {
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = altera_ps2_match,
 	},
 };
 
@@ -189,13 +201,12 @@ static int __init altera_ps2_init(void)
 {
 	return platform_driver_register(&altera_ps2_driver);
 }
+module_init(altera_ps2_init);
 
 static void __exit altera_ps2_exit(void)
 {
 	platform_driver_unregister(&altera_ps2_driver);
 }
-
-module_init(altera_ps2_init);
 module_exit(altera_ps2_exit);
 
 MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
index 92563a6..12abc50 100644
--- a/drivers/input/serio/ambakmi.c
+++ b/drivers/input/serio/ambakmi.c
@@ -107,7 +107,8 @@ static void amba_kmi_close(struct serio *io)
 	clk_disable(kmi->clk);
 }
 
-static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit amba_kmi_probe(struct amba_device *dev,
+	const struct amba_id *id)
 {
 	struct amba_kmi_port *kmi;
 	struct serio *io;
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index c5cc450..395a9af 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -49,7 +49,7 @@ static inline void i8042_write_command(int val)
 #define OBP_PS2MS_NAME1		"kdmouse"
 #define OBP_PS2MS_NAME2		"mouse"
 
-static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit sparc_i8042_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -95,7 +95,7 @@ static const struct of_device_id sparc_i8042_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sparc_i8042_match);
 
-static struct of_platform_driver sparc_i8042_driver = {
+static struct platform_driver sparc_i8042_driver = {
 	.driver = {
 		.name = "i8042",
 		.owner = THIS_MODULE,
@@ -116,7 +116,7 @@ static int __init i8042_platform_init(void)
 		if (!kbd_iobase)
 			return -ENODEV;
 	} else {
-		int err = of_register_platform_driver(&sparc_i8042_driver);
+		int err = platform_driver_register(&sparc_i8042_driver);
 		if (err)
 			return err;
 
@@ -140,7 +140,7 @@ static inline void i8042_platform_exit(void)
 	struct device_node *root = of_find_node_by_path("/");
 
 	if (strcmp(root->name, "SUNW,JavaStation-1"))
-		of_unregister_platform_driver(&sparc_i8042_driver);
+		platform_driver_unregister(&sparc_i8042_driver);
 }
 
 #else /* !CONFIG_PCI */
diff --git a/drivers/input/serio/i8042-unicore32io.h b/drivers/input/serio/i8042-unicore32io.h
new file mode 100644
index 0000000..73f5cc1
--- /dev/null
+++ b/drivers/input/serio/i8042-unicore32io.h
@@ -0,0 +1,73 @@
+/*
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2011 Guan Xuetao
+ *
+ * This program is free software; you can 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 _I8042_UNICORE32_H
+#define _I8042_UNICORE32_H
+
+#include <mach/hardware.h>
+
+/*
+ * Names.
+ */
+#define I8042_KBD_PHYS_DESC "isa0060/serio0"
+#define I8042_AUX_PHYS_DESC "isa0060/serio1"
+#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
+
+/*
+ * IRQs.
+ */
+#define I8042_KBD_IRQ           IRQ_PS2_KBD
+#define I8042_AUX_IRQ           IRQ_PS2_AUX
+
+/*
+ * Register numbers.
+ */
+#define I8042_COMMAND_REG	PS2_COMMAND
+#define I8042_STATUS_REG	PS2_STATUS
+#define I8042_DATA_REG		PS2_DATA
+
+#define I8042_REGION_START	(resource_size_t)(PS2_DATA)
+#define I8042_REGION_SIZE	(resource_size_t)(16)
+
+static inline int i8042_read_data(void)
+{
+	return readb(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+	return readb(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+	writeb(val, I8042_DATA_REG);
+}
+
+static inline void i8042_write_command(int val)
+{
+	writeb(val, I8042_COMMAND_REG);
+}
+
+static inline int i8042_platform_init(void)
+{
+	if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
+		return -EBUSY;
+
+	i8042_reset = 1;
+	return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+	release_mem_region(I8042_REGION_START, I8042_REGION_SIZE);
+}
+
+#endif /* _I8042_UNICORE32_H */
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index ac1d759..3452708 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -26,6 +26,8 @@
 #include "i8042-sparcio.h"
 #elif defined(CONFIG_X86) || defined(CONFIG_IA64)
 #include "i8042-x86ia64io.h"
+#elif defined(CONFIG_UNICORE32)
+#include "i8042-unicore32io.h"
 #else
 #include "i8042-io.h"
 #endif
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c
index bb14449..7540baf 100644
--- a/drivers/input/serio/xilinx_ps2.c
+++ b/drivers/input/serio/xilinx_ps2.c
@@ -232,8 +232,7 @@ static void sxps2_close(struct serio *pserio)
  * It returns 0, if the driver is bound to the PS/2 device, or a negative
  * value if there is an error.
  */
-static int __devinit xps2_of_probe(struct platform_device *ofdev,
-				   const struct of_device_id *match)
+static int __devinit xps2_of_probe(struct platform_device *ofdev)
 {
 	struct resource r_irq; /* Interrupt resources */
 	struct resource r_mem; /* IO mem resources */
@@ -361,7 +360,7 @@ static const struct of_device_id xps2_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, xps2_of_match);
 
-static struct of_platform_driver xps2_of_driver = {
+static struct platform_driver xps2_of_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -373,12 +372,12 @@ static struct of_platform_driver xps2_of_driver = {
 
 static int __init xps2_init(void)
 {
-	return of_register_platform_driver(&xps2_of_driver);
+	return platform_driver_register(&xps2_of_driver);
 }
 
 static void __exit xps2_cleanup(void)
 {
-	of_unregister_platform_driver(&xps2_of_driver);
+	platform_driver_unregister(&xps2_of_driver);
 }
 
 module_init(xps2_init);
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
index 7729e54..337bf51 100644
--- a/drivers/input/sparse-keymap.c
+++ b/drivers/input/sparse-keymap.c
@@ -210,8 +210,8 @@ int sparse_keymap_setup(struct input_dev *dev,
 
 	dev->keycode = map;
 	dev->keycodemax = map_size;
-	dev->getkeycode_new = sparse_keymap_getkeycode;
-	dev->setkeycode_new = sparse_keymap_setkeycode;
+	dev->getkeycode = sparse_keymap_getkeycode;
+	dev->setkeycode = sparse_keymap_setkeycode;
 
 	return 0;
 
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index cf8fb9f..449c0a4 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -193,16 +193,16 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 			case HID_USAGE_X:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						features->device_type = BTN_TOOL_DOUBLETAP;
+						features->device_type = BTN_TOOL_FINGER;
 						if (features->type == TABLETPC2FG) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 						}
 						if (features->type == BAMBOO_PT) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_BBTOUCH;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 							features->x_phy =
 								get_unaligned_le16(&report[i + 5]);
 							features->x_max =
@@ -241,11 +241,11 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 			case HID_USAGE_Y:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						features->device_type = BTN_TOOL_DOUBLETAP;
+						features->device_type = BTN_TOOL_FINGER;
 						if (features->type == TABLETPC2FG) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 							features->y_max =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_phy =
@@ -254,7 +254,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
 						} else if (features->type == BAMBOO_PT) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_BBTOUCH;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 							features->y_phy =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_max =
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 367fa82..5597637 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -675,169 +675,87 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
 	return 1;
 }
 
-
-static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx)
+static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 {
 	struct input_dev *input = wacom->input;
-	int finger = idx + 1;
-	int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff;
-	int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff;
+	unsigned char *data = wacom->data;
+	int contact_with_no_pen_down_count = 0;
+	int i;
 
-	/*
-	 * Work around input core suppressing "duplicate" events since
-	 * we are abusing ABS_X/ABS_Y to transmit multi-finger data.
-	 * This should go away once we switch to true multitouch
-	 * protocol.
-	 */
-	if (wacom->last_finger != finger) {
-		if (x == input_abs_get_val(input, ABS_X))
-			x++;
+	for (i = 0; i < 2; i++) {
+		int p = data[1] & (1 << i);
+		bool touch = p && !wacom->shared->stylus_in_proximity;
+
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+		if (touch) {
+			int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff;
+			int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff;
 
-		if (y == input_abs_get_val(input, ABS_Y))
-			y++;
+			input_report_abs(input, ABS_MT_POSITION_X, x);
+			input_report_abs(input, ABS_MT_POSITION_Y, y);
+			contact_with_no_pen_down_count++;
+		}
 	}
 
-	input_report_abs(input, ABS_X, x);
-	input_report_abs(input, ABS_Y, y);
-	input_report_abs(input, ABS_MISC, wacom->id[0]);
-	input_report_key(input, wacom->tool[finger], 1);
-	if (!idx)
-		input_report_key(input, BTN_TOUCH, 1);
-	input_event(input, EV_MSC, MSC_SERIAL, finger);
-	input_sync(input);
+	/* keep touch state for pen event */
+	wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
 
-	wacom->last_finger = finger;
-}
+	input_mt_report_pointer_emulation(input, true);
 
-static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx)
-{
-	struct input_dev *input = wacom->input;
-	int finger = idx + 1;
-
-	input_report_abs(input, ABS_X, 0);
-	input_report_abs(input, ABS_Y, 0);
-	input_report_abs(input, ABS_MISC, 0);
-	input_report_key(input, wacom->tool[finger], 0);
-	if (!idx)
-		input_report_key(input, BTN_TOUCH, 0);
-	input_event(input, EV_MSC, MSC_SERIAL, finger);
-	input_sync(input);
+	return 1;
 }
 
-static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len)
+static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
 	char *data = wacom->data;
 	struct input_dev *input = wacom->input;
+	bool prox;
+	int x = 0, y = 0;
 
-	wacom->tool[1] = BTN_TOOL_DOUBLETAP;
-	wacom->id[0] = TOUCH_DEVICE_ID;
-	wacom->tool[2] = BTN_TOOL_TRIPLETAP;
-
-	if (len != WACOM_PKGLEN_TPC1FG) {
-
-		switch (data[0]) {
+	if (!wacom->shared->stylus_in_proximity) {
+		if (len == WACOM_PKGLEN_TPC1FG) {
+			prox = data[0] & 0x01;
+			x = get_unaligned_le16(&data[1]);
+			y = get_unaligned_le16(&data[3]);
+		} else { /* with capacity */
+			prox = data[1] & 0x01;
+			x = le16_to_cpup((__le16 *)&data[2]);
+			y = le16_to_cpup((__le16 *)&data[4]);
+		}
+	} else
+		/* force touch out when pen is in prox */
+		prox = 0;
 
-		case WACOM_REPORT_TPC1FG:
-			input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-			input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-			input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
-			input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6]));
-			input_report_abs(input, ABS_MISC, wacom->id[0]);
-			input_report_key(input, wacom->tool[1], 1);
-			input_sync(input);
-			break;
+	if (prox) {
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+	}
+	input_report_key(input, BTN_TOUCH, prox);
 
-		case WACOM_REPORT_TPC2FG:
-			if (data[1] & 0x01)
-				wacom_tpc_finger_in(wacom, data, 0);
-			else if (wacom->id[1] & 0x01)
-				wacom_tpc_touch_out(wacom, 0);
+	/* keep touch state for pen events */
+	wacom->shared->touch_down = prox;
 
-			if (data[1] & 0x02)
-				wacom_tpc_finger_in(wacom, data, 1);
-			else if (wacom->id[1] & 0x02)
-				wacom_tpc_touch_out(wacom, 1);
-			break;
-		}
-	} else {
-		input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
-		input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
-		input_report_key(input, BTN_TOUCH, 1);
-		input_report_abs(input, ABS_MISC, wacom->id[1]);
-		input_report_key(input, wacom->tool[1], 1);
-		input_sync(input);
-	}
+	return 1;
 }
 
-static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
 	struct wacom_features *features = &wacom->features;
 	char *data = wacom->data;
 	struct input_dev *input = wacom->input;
-	int prox = 0, pressure;
-	int retval = 0;
+	int pressure;
+	bool prox = data[1] & 0x20;
 
-	dbg("wacom_tpc_irq: received report #%d", data[0]);
-
-	if (len == WACOM_PKGLEN_TPC1FG ||		 /* single touch */
-	    data[0] == WACOM_REPORT_TPC1FG ||		 /* single touch */
-	    data[0] == WACOM_REPORT_TPC2FG) {		 /* 2FG touch */
-
-		if (wacom->shared->stylus_in_proximity) {
-			if (wacom->id[1] & 0x01)
-				wacom_tpc_touch_out(wacom, 0);
-
-			if (wacom->id[1] & 0x02)
-				wacom_tpc_touch_out(wacom, 1);
-
-			wacom->id[1] = 0;
-			return 0;
-		}
-
-		if (len == WACOM_PKGLEN_TPC1FG) {	/* with touch */
-			prox = data[0] & 0x01;
-		} else {  /* with capacity */
-			if (data[0] == WACOM_REPORT_TPC1FG)
-				/* single touch */
-				prox = data[1] & 0x01;
-			else
-				/* 2FG touch data */
-				prox = data[1] & 0x03;
-		}
-
-		if (prox) {
-			if (!wacom->id[1])
-				wacom->last_finger = 1;
-			wacom_tpc_touch_in(wacom, len);
-		} else {
-			if (data[0] == WACOM_REPORT_TPC2FG) {
-				/* 2FGT out-prox */
-				if (wacom->id[1] & 0x01)
-					wacom_tpc_touch_out(wacom, 0);
+	if (!wacom->shared->stylus_in_proximity) /* first in prox */
+		/* Going into proximity select tool */
+		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
-				if (wacom->id[1] & 0x02)
-					wacom_tpc_touch_out(wacom, 1);
-			} else
-				/* one finger touch */
-				wacom_tpc_touch_out(wacom, 0);
+	/* keep pen state for touch events */
+	wacom->shared->stylus_in_proximity = prox;
 
-			wacom->id[0] = 0;
-		}
-		/* keep prox bit to send proper out-prox event */
-		wacom->id[1] = prox;
-	} else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */
-		prox = data[1] & 0x20;
-
-		if (!wacom->shared->stylus_in_proximity) { /* first in prox */
-			/* Going into proximity select tool */
-			wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-			if (wacom->tool[0] == BTN_TOOL_PEN)
-				wacom->id[0] = STYLUS_DEVICE_ID;
-			else
-				wacom->id[0] = ERASER_DEVICE_ID;
-
-			wacom->shared->stylus_in_proximity = true;
-		}
+	/* send pen events only when touch is up or forced out */
+	if (!wacom->shared->touch_down) {
 		input_report_key(input, BTN_STYLUS, data[1] & 0x02);
 		input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
 		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
@@ -847,15 +765,27 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
 			pressure = features->pressure_max + pressure + 1;
 		input_report_abs(input, ABS_PRESSURE, pressure);
 		input_report_key(input, BTN_TOUCH, data[1] & 0x05);
-		if (!prox) { /* out-prox */
-			wacom->id[0] = 0;
-			wacom->shared->stylus_in_proximity = false;
-		}
 		input_report_key(input, wacom->tool[0], prox);
-		input_report_abs(input, ABS_MISC, wacom->id[0]);
-		retval = 1;
+		return 1;
 	}
-	return retval;
+
+	return 0;
+}
+
+static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+{
+	char *data = wacom->data;
+
+	dbg("wacom_tpc_irq: received report #%d", data[0]);
+
+	if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG)
+		return wacom_tpc_single_touch(wacom, len);
+	else if (data[0] == WACOM_REPORT_TPC2FG)
+		return wacom_tpc_mt_touch(wacom);
+	else if (data[0] == WACOM_REPORT_PENABLED)
+		return wacom_tpc_pen(wacom);
+
+	return 0;
 }
 
 static int wacom_bpt_touch(struct wacom_wac *wacom)
@@ -1078,7 +1008,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 {
 
 	/* touch device found but size is not defined. use default */
-	if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+	if (features->device_type == BTN_TOOL_FINGER && !features->x_max) {
 		features->x_max = 1023;
 		features->y_max = 1023;
 	}
@@ -1090,7 +1020,7 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
 	/* quirks for bamboo touch */
 	if (features->type == BAMBOO_PT &&
-	    features->device_type == BTN_TOOL_TRIPLETAP) {
+	    features->device_type == BTN_TOOL_DOUBLETAP) {
 		features->x_max <<= 5;
 		features->y_max <<= 5;
 		features->x_fuzz <<= 5;
@@ -1226,27 +1156,30 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 		break;
 
 	case TABLETPC2FG:
-		if (features->device_type == BTN_TOOL_TRIPLETAP) {
-			__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
-			input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
+		if (features->device_type == BTN_TOOL_DOUBLETAP) {
+
+			input_mt_init_slots(input_dev, 2);
+			input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
+					0, MT_TOOL_MAX, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+					0, features->x_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+					0, features->y_max, 0, 0);
 		}
 		/* fall through */
 
 	case TABLETPC:
-		if (features->device_type == BTN_TOOL_DOUBLETAP ||
-		    features->device_type == BTN_TOOL_TRIPLETAP) {
+		__clear_bit(ABS_MISC, input_dev->absbit);
+
+		if (features->device_type != BTN_TOOL_PEN) {
 			input_abs_set_res(input_dev, ABS_X,
 				wacom_calculate_touch_res(features->x_max,
 							features->x_phy));
 			input_abs_set_res(input_dev, ABS_Y,
 				wacom_calculate_touch_res(features->y_max,
 							features->y_phy));
-			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-		}
-
-		if (features->device_type != BTN_TOOL_PEN)
 			break;  /* no need to process stylus stuff */
-
+		}
 		/* fall through */
 
 	case PL:
@@ -1264,7 +1197,7 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 	case BAMBOO_PT:
 		__clear_bit(ABS_MISC, input_dev->absbit);
 
-		if (features->device_type == BTN_TOOL_TRIPLETAP) {
+		if (features->device_type == BTN_TOOL_DOUBLETAP) {
 			__set_bit(BTN_LEFT, input_dev->keybit);
 			__set_bit(BTN_FORWARD, input_dev->keybit);
 			__set_bit(BTN_BACK, input_dev->keybit);
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index b1310ec..835f756 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -88,15 +88,15 @@ struct wacom_features {
 
 struct wacom_shared {
 	bool stylus_in_proximity;
+	bool touch_down;
 };
 
 struct wacom_wac {
 	char name[64];
 	unsigned char *data;
-	int tool[3];
-	int id[3];
+	int tool[2];
+	int id[2];
 	__u32 serial[2];
-	int last_finger;
 	struct wacom_features features;
 	struct wacom_shared *shared;
 	struct input_dev *input;
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 61834ae..112ec55 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -86,6 +86,18 @@ config TOUCHSCREEN_AD7879_SPI
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7879-spi.
 
+config TOUCHSCREEN_ATMEL_MXT
+	tristate "Atmel mXT I2C Touchscreen"
+	depends on I2C
+	help
+	  Say Y here if you have Atmel mXT series I2C touchscreen,
+	  such as AT42QT602240/ATMXT224, connected to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel_mxt_ts.
+
 config TOUCHSCREEN_BITSY
 	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
 	depends on SA1100_BITSY
@@ -339,18 +351,6 @@ config TOUCHSCREEN_PENMOUNT
 	  To compile this driver as a module, choose M here: the
 	  module will be called penmount.
 
-config TOUCHSCREEN_QT602240
-	tristate "QT602240 I2C Touchscreen"
-	depends on I2C
-	help
-	  Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen
-	  connected to your system.
-
-	  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called qt602240_ts.
-
 config TOUCHSCREEN_MIGOR
 	tristate "Renesas MIGO-R touchscreen"
 	depends on SH_MIGOR && I2C
@@ -423,6 +423,16 @@ config TOUCHSCREEN_UCB1400
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_ts.
 
+config TOUCHSCREEN_WM831X
+	tristate "Support for WM831x touchscreen controllers"
+	depends on MFD_WM831X
+	help
+	  This enables support for the touchscreen controller on the WM831x
+	  series of PMICs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm831x-ts.
+
 config TOUCHSCREEN_WM97XX
 	tristate "Support for WM97xx AC97 touchscreen controllers"
 	depends on AC97_BUS
@@ -629,6 +639,17 @@ config TOUCHSCREEN_TOUCHIT213
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchit213.
 
+config TOUCHSCREEN_TSC2005
+        tristate "TSC2005 based touchscreens"
+        depends on SPI_MASTER
+        help
+          Say Y here if you have a TSC2005 based touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tsc2005.
+
 config TOUCHSCREEN_TSC2007
 	tristate "TSC2007 based touchscreens"
 	depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 718bcc8..ca94098 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879)	+= ad7879.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)	+= ad7879-i2c.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
@@ -37,7 +38,6 @@ obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
-obj-$(CONFIG_TOUCHSCREEN_QT602240)	+= qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
@@ -45,9 +45,11 @@ obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2005)	+= tsc2005.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)	+= tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)	+= wacom_w8001.o
+obj-$(CONFIG_TOUCHSCREEN_WM831X)	+= wm831x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX)	+= wm97xx-ts.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c
index a1952fc..714d4e0 100644
--- a/drivers/input/touchscreen/ad7877.c
+++ b/drivers/input/touchscreen/ad7877.c
@@ -41,6 +41,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ad7877.h>
@@ -826,39 +827,37 @@ static int __devexit ad7877_remove(struct spi_device *spi)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int ad7877_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ad7877_suspend(struct device *dev)
 {
-	struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+	struct ad7877 *ts = dev_get_drvdata(dev);
 
 	ad7877_disable(ts);
 
 	return 0;
 }
 
-static int ad7877_resume(struct spi_device *spi)
+static int ad7877_resume(struct device *dev)
 {
-	struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+	struct ad7877 *ts = dev_get_drvdata(dev);
 
 	ad7877_enable(ts);
 
 	return 0;
 }
-#else
-#define ad7877_suspend NULL
-#define ad7877_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
+
 static struct spi_driver ad7877_driver = {
 	.driver = {
 		.name	= "ad7877",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &ad7877_pm,
 	},
 	.probe		= ad7877_probe,
 	.remove		= __devexit_p(ad7877_remove),
-	.suspend	= ad7877_suspend,
-	.resume		= ad7877_resume,
 };
 
 static int __init ad7877_init(void)
diff --git a/drivers/input/touchscreen/ad7879-spi.c b/drivers/input/touchscreen/ad7879-spi.c
index 59c6e68..ddf732f 100644
--- a/drivers/input/touchscreen/ad7879-spi.c
+++ b/drivers/input/touchscreen/ad7879-spi.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/input.h>	/* BUS_SPI */
+#include <linux/pm.h>
 #include <linux/spi/spi.h>
 
 #include "ad7879.h"
@@ -20,9 +21,10 @@
 #define AD7879_WRITECMD(reg) (AD7879_CMD(reg))
 #define AD7879_READCMD(reg)  (AD7879_CMD(reg) | AD7879_CMD_READ)
 
-#ifdef CONFIG_PM
-static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ad7879_spi_suspend(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct ad7879 *ts = spi_get_drvdata(spi);
 
 	ad7879_suspend(ts);
@@ -30,19 +32,19 @@ static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message)
 	return 0;
 }
 
-static int ad7879_spi_resume(struct spi_device *spi)
+static int ad7879_spi_resume(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct ad7879 *ts = spi_get_drvdata(spi);
 
 	ad7879_resume(ts);
 
 	return 0;
 }
-#else
-# define ad7879_spi_suspend NULL
-# define ad7879_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume);
+
 /*
  * ad7879_read/write are only used for initial setup and for sysfs controls.
  * The main traffic is done in ad7879_collect().
@@ -173,11 +175,10 @@ static struct spi_driver ad7879_spi_driver = {
 		.name	= "ad7879",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &ad7879_spi_pm,
 	},
 	.probe		= ad7879_spi_probe,
 	.remove		= __devexit_p(ad7879_spi_remove),
-	.suspend	= ad7879_spi_suspend,
-	.resume		= ad7879_spi_resume,
 };
 
 static int __init ad7879_spi_init(void)
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 4bf2316..c24946f 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -26,6 +26,7 @@
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -892,9 +893,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle)
 	return IRQ_HANDLED;
 }
 
-static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ads7846_suspend(struct device *dev)
 {
-	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
 
 	mutex_lock(&ts->lock);
 
@@ -914,9 +916,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
 	return 0;
 }
 
-static int ads7846_resume(struct spi_device *spi)
+static int ads7846_resume(struct device *dev)
 {
-	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
 
 	mutex_lock(&ts->lock);
 
@@ -935,6 +937,9 @@ static int ads7846_resume(struct spi_device *spi)
 
 	return 0;
 }
+#endif
+
+static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
 static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 {
@@ -1408,11 +1413,10 @@ static struct spi_driver ads7846_driver = {
 		.name	= "ads7846",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &ads7846_pm,
 	},
 	.probe		= ads7846_probe,
 	.remove		= __devexit_p(ads7846_remove),
-	.suspend	= ads7846_suspend,
-	.resume		= ads7846_resume,
 };
 
 static int __init ads7846_init(void)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
new file mode 100644
index 0000000..4012436
--- /dev/null
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -0,0 +1,1211 @@
+/*
+ * Atmel maXTouch Touchscreen driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+/* Version */
+#define MXT_VER_20		20
+#define MXT_VER_21		21
+#define MXT_VER_22		22
+
+/* Slave addresses */
+#define MXT_APP_LOW		0x4a
+#define MXT_APP_HIGH		0x4b
+#define MXT_BOOT_LOW		0x24
+#define MXT_BOOT_HIGH		0x25
+
+/* Firmware */
+#define MXT_FW_NAME		"maxtouch.fw"
+
+/* Registers */
+#define MXT_FAMILY_ID		0x00
+#define MXT_VARIANT_ID		0x01
+#define MXT_VERSION		0x02
+#define MXT_BUILD		0x03
+#define MXT_MATRIX_X_SIZE	0x04
+#define MXT_MATRIX_Y_SIZE	0x05
+#define MXT_OBJECT_NUM		0x06
+#define MXT_OBJECT_START	0x07
+
+#define MXT_OBJECT_SIZE		6
+
+/* Object types */
+#define MXT_DEBUG_DIAGNOSTIC	37
+#define MXT_GEN_MESSAGE		5
+#define MXT_GEN_COMMAND		6
+#define MXT_GEN_POWER		7
+#define MXT_GEN_ACQUIRE		8
+#define MXT_TOUCH_MULTI		9
+#define MXT_TOUCH_KEYARRAY	15
+#define MXT_TOUCH_PROXIMITY	23
+#define MXT_PROCI_GRIPFACE	20
+#define MXT_PROCG_NOISE		22
+#define MXT_PROCI_ONETOUCH	24
+#define MXT_PROCI_TWOTOUCH	27
+#define MXT_PROCI_GRIP		40
+#define MXT_PROCI_PALM		41
+#define MXT_SPT_COMMSCONFIG	18
+#define MXT_SPT_GPIOPWM		19
+#define MXT_SPT_SELFTEST	25
+#define MXT_SPT_CTECONFIG	28
+#define MXT_SPT_USERDATA	38
+#define MXT_SPT_DIGITIZER	43
+#define MXT_SPT_MESSAGECOUNT	44
+
+/* MXT_GEN_COMMAND field */
+#define MXT_COMMAND_RESET	0
+#define MXT_COMMAND_BACKUPNV	1
+#define MXT_COMMAND_CALIBRATE	2
+#define MXT_COMMAND_REPORTALL	3
+#define MXT_COMMAND_DIAGNOSTIC	5
+
+/* MXT_GEN_POWER field */
+#define MXT_POWER_IDLEACQINT	0
+#define MXT_POWER_ACTVACQINT	1
+#define MXT_POWER_ACTV2IDLETO	2
+
+/* MXT_GEN_ACQUIRE field */
+#define MXT_ACQUIRE_CHRGTIME	0
+#define MXT_ACQUIRE_TCHDRIFT	2
+#define MXT_ACQUIRE_DRIFTST	3
+#define MXT_ACQUIRE_TCHAUTOCAL	4
+#define MXT_ACQUIRE_SYNC	5
+#define MXT_ACQUIRE_ATCHCALST	6
+#define MXT_ACQUIRE_ATCHCALSTHR	7
+
+/* MXT_TOUCH_MULTI field */
+#define MXT_TOUCH_CTRL		0
+#define MXT_TOUCH_XORIGIN	1
+#define MXT_TOUCH_YORIGIN	2
+#define MXT_TOUCH_XSIZE		3
+#define MXT_TOUCH_YSIZE		4
+#define MXT_TOUCH_BLEN		6
+#define MXT_TOUCH_TCHTHR	7
+#define MXT_TOUCH_TCHDI		8
+#define MXT_TOUCH_ORIENT	9
+#define MXT_TOUCH_MOVHYSTI	11
+#define MXT_TOUCH_MOVHYSTN	12
+#define MXT_TOUCH_NUMTOUCH	14
+#define MXT_TOUCH_MRGHYST	15
+#define MXT_TOUCH_MRGTHR	16
+#define MXT_TOUCH_AMPHYST	17
+#define MXT_TOUCH_XRANGE_LSB	18
+#define MXT_TOUCH_XRANGE_MSB	19
+#define MXT_TOUCH_YRANGE_LSB	20
+#define MXT_TOUCH_YRANGE_MSB	21
+#define MXT_TOUCH_XLOCLIP	22
+#define MXT_TOUCH_XHICLIP	23
+#define MXT_TOUCH_YLOCLIP	24
+#define MXT_TOUCH_YHICLIP	25
+#define MXT_TOUCH_XEDGECTRL	26
+#define MXT_TOUCH_XEDGEDIST	27
+#define MXT_TOUCH_YEDGECTRL	28
+#define MXT_TOUCH_YEDGEDIST	29
+#define MXT_TOUCH_JUMPLIMIT	30
+
+/* MXT_PROCI_GRIPFACE field */
+#define MXT_GRIPFACE_CTRL	0
+#define MXT_GRIPFACE_XLOGRIP	1
+#define MXT_GRIPFACE_XHIGRIP	2
+#define MXT_GRIPFACE_YLOGRIP	3
+#define MXT_GRIPFACE_YHIGRIP	4
+#define MXT_GRIPFACE_MAXTCHS	5
+#define MXT_GRIPFACE_SZTHR1	7
+#define MXT_GRIPFACE_SZTHR2	8
+#define MXT_GRIPFACE_SHPTHR1	9
+#define MXT_GRIPFACE_SHPTHR2	10
+#define MXT_GRIPFACE_SUPEXTTO	11
+
+/* MXT_PROCI_NOISE field */
+#define MXT_NOISE_CTRL		0
+#define MXT_NOISE_OUTFLEN	1
+#define MXT_NOISE_GCAFUL_LSB	3
+#define MXT_NOISE_GCAFUL_MSB	4
+#define MXT_NOISE_GCAFLL_LSB	5
+#define MXT_NOISE_GCAFLL_MSB	6
+#define MXT_NOISE_ACTVGCAFVALID	7
+#define MXT_NOISE_NOISETHR	8
+#define MXT_NOISE_FREQHOPSCALE	10
+#define MXT_NOISE_FREQ0		11
+#define MXT_NOISE_FREQ1		12
+#define MXT_NOISE_FREQ2		13
+#define MXT_NOISE_FREQ3		14
+#define MXT_NOISE_FREQ4		15
+#define MXT_NOISE_IDLEGCAFVALID	16
+
+/* MXT_SPT_COMMSCONFIG */
+#define MXT_COMMS_CTRL		0
+#define MXT_COMMS_CMD		1
+
+/* MXT_SPT_CTECONFIG field */
+#define MXT_CTE_CTRL		0
+#define MXT_CTE_CMD		1
+#define MXT_CTE_MODE		2
+#define MXT_CTE_IDLEGCAFDEPTH	3
+#define MXT_CTE_ACTVGCAFDEPTH	4
+#define MXT_CTE_VOLTAGE		5
+
+#define MXT_VOLTAGE_DEFAULT	2700000
+#define MXT_VOLTAGE_STEP	10000
+
+/* Define for MXT_GEN_COMMAND */
+#define MXT_BOOT_VALUE		0xa5
+#define MXT_BACKUP_VALUE	0x55
+#define MXT_BACKUP_TIME		25	/* msec */
+#define MXT_RESET_TIME		65	/* msec */
+
+#define MXT_FWRESET_TIME	175	/* msec */
+
+/* Command to unlock bootloader */
+#define MXT_UNLOCK_CMD_MSB	0xaa
+#define MXT_UNLOCK_CMD_LSB	0xdc
+
+/* Bootloader mode status */
+#define MXT_WAITING_BOOTLOAD_CMD	0xc0	/* valid 7 6 bit only */
+#define MXT_WAITING_FRAME_DATA	0x80	/* valid 7 6 bit only */
+#define MXT_FRAME_CRC_CHECK	0x02
+#define MXT_FRAME_CRC_FAIL	0x03
+#define MXT_FRAME_CRC_PASS	0x04
+#define MXT_APP_CRC_FAIL	0x40	/* valid 7 8 bit only */
+#define MXT_BOOT_STATUS_MASK	0x3f
+
+/* Touch status */
+#define MXT_SUPPRESS		(1 << 1)
+#define MXT_AMP			(1 << 2)
+#define MXT_VECTOR		(1 << 3)
+#define MXT_MOVE		(1 << 4)
+#define MXT_RELEASE		(1 << 5)
+#define MXT_PRESS		(1 << 6)
+#define MXT_DETECT		(1 << 7)
+
+/* Touchscreen absolute values */
+#define MXT_MAX_XC		0x3ff
+#define MXT_MAX_YC		0x3ff
+#define MXT_MAX_AREA		0xff
+
+#define MXT_MAX_FINGER		10
+
+struct mxt_info {
+	u8 family_id;
+	u8 variant_id;
+	u8 version;
+	u8 build;
+	u8 matrix_xsize;
+	u8 matrix_ysize;
+	u8 object_num;
+};
+
+struct mxt_object {
+	u8 type;
+	u16 start_address;
+	u8 size;
+	u8 instances;
+	u8 num_report_ids;
+
+	/* to map object and message */
+	u8 max_reportid;
+};
+
+struct mxt_message {
+	u8 reportid;
+	u8 message[7];
+	u8 checksum;
+};
+
+struct mxt_finger {
+	int status;
+	int x;
+	int y;
+	int area;
+};
+
+/* Each client has this additional data */
+struct mxt_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	const struct mxt_platform_data *pdata;
+	struct mxt_object *object_table;
+	struct mxt_info info;
+	struct mxt_finger finger[MXT_MAX_FINGER];
+	unsigned int irq;
+};
+
+static bool mxt_object_readable(unsigned int type)
+{
+	switch (type) {
+	case MXT_GEN_MESSAGE:
+	case MXT_GEN_COMMAND:
+	case MXT_GEN_POWER:
+	case MXT_GEN_ACQUIRE:
+	case MXT_TOUCH_MULTI:
+	case MXT_TOUCH_KEYARRAY:
+	case MXT_TOUCH_PROXIMITY:
+	case MXT_PROCI_GRIPFACE:
+	case MXT_PROCG_NOISE:
+	case MXT_PROCI_ONETOUCH:
+	case MXT_PROCI_TWOTOUCH:
+	case MXT_PROCI_GRIP:
+	case MXT_PROCI_PALM:
+	case MXT_SPT_COMMSCONFIG:
+	case MXT_SPT_GPIOPWM:
+	case MXT_SPT_SELFTEST:
+	case MXT_SPT_CTECONFIG:
+	case MXT_SPT_USERDATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool mxt_object_writable(unsigned int type)
+{
+	switch (type) {
+	case MXT_GEN_COMMAND:
+	case MXT_GEN_POWER:
+	case MXT_GEN_ACQUIRE:
+	case MXT_TOUCH_MULTI:
+	case MXT_TOUCH_KEYARRAY:
+	case MXT_TOUCH_PROXIMITY:
+	case MXT_PROCI_GRIPFACE:
+	case MXT_PROCG_NOISE:
+	case MXT_PROCI_ONETOUCH:
+	case MXT_PROCI_TWOTOUCH:
+	case MXT_PROCI_GRIP:
+	case MXT_PROCI_PALM:
+	case MXT_SPT_GPIOPWM:
+	case MXT_SPT_SELFTEST:
+	case MXT_SPT_CTECONFIG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void mxt_dump_message(struct device *dev,
+				  struct mxt_message *message)
+{
+	dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
+	dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
+	dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
+	dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
+	dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
+	dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
+	dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
+	dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
+	dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
+}
+
+static int mxt_check_bootloader(struct i2c_client *client,
+				     unsigned int state)
+{
+	u8 val;
+
+recheck:
+	if (i2c_master_recv(client, &val, 1) != 1) {
+		dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
+		return -EIO;
+	}
+
+	switch (state) {
+	case MXT_WAITING_BOOTLOAD_CMD:
+	case MXT_WAITING_FRAME_DATA:
+		val &= ~MXT_BOOT_STATUS_MASK;
+		break;
+	case MXT_FRAME_CRC_PASS:
+		if (val == MXT_FRAME_CRC_CHECK)
+			goto recheck;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val != state) {
+		dev_err(&client->dev, "Unvalid bootloader mode state\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mxt_unlock_bootloader(struct i2c_client *client)
+{
+	u8 buf[2];
+
+	buf[0] = MXT_UNLOCK_CMD_LSB;
+	buf[1] = MXT_UNLOCK_CMD_MSB;
+
+	if (i2c_master_send(client, buf, 2) != 2) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mxt_fw_write(struct i2c_client *client,
+			     const u8 *data, unsigned int frame_size)
+{
+	if (i2c_master_send(client, data, frame_size) != frame_size) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int __mxt_read_reg(struct i2c_client *client,
+			       u16 reg, u16 len, void *val)
+{
+	struct i2c_msg xfer[2];
+	u8 buf[2];
+
+	buf[0] = reg & 0xff;
+	buf[1] = (reg >> 8) & 0xff;
+
+	/* Write register */
+	xfer[0].addr = client->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 2;
+	xfer[0].buf = buf;
+
+	/* Read data */
+	xfer[1].addr = client->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = len;
+	xfer[1].buf = val;
+
+	if (i2c_transfer(client->adapter, xfer, 2) != 2) {
+		dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+{
+	return __mxt_read_reg(client, reg, 1, val);
+}
+
+static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
+{
+	u8 buf[3];
+
+	buf[0] = reg & 0xff;
+	buf[1] = (reg >> 8) & 0xff;
+	buf[2] = val;
+
+	if (i2c_master_send(client, buf, 3) != 3) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mxt_read_object_table(struct i2c_client *client,
+				      u16 reg, u8 *object_buf)
+{
+	return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
+				   object_buf);
+}
+
+static struct mxt_object *
+mxt_get_object(struct mxt_data *data, u8 type)
+{
+	struct mxt_object *object;
+	int i;
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+		if (object->type == type)
+			return object;
+	}
+
+	dev_err(&data->client->dev, "Invalid object type\n");
+	return NULL;
+}
+
+static int mxt_read_message(struct mxt_data *data,
+				 struct mxt_message *message)
+{
+	struct mxt_object *object;
+	u16 reg;
+
+	object = mxt_get_object(data, MXT_GEN_MESSAGE);
+	if (!object)
+		return -EINVAL;
+
+	reg = object->start_address;
+	return __mxt_read_reg(data->client, reg,
+			sizeof(struct mxt_message), message);
+}
+
+static int mxt_read_object(struct mxt_data *data,
+				u8 type, u8 offset, u8 *val)
+{
+	struct mxt_object *object;
+	u16 reg;
+
+	object = mxt_get_object(data, type);
+	if (!object)
+		return -EINVAL;
+
+	reg = object->start_address;
+	return __mxt_read_reg(data->client, reg + offset, 1, val);
+}
+
+static int mxt_write_object(struct mxt_data *data,
+				 u8 type, u8 offset, u8 val)
+{
+	struct mxt_object *object;
+	u16 reg;
+
+	object = mxt_get_object(data, type);
+	if (!object)
+		return -EINVAL;
+
+	reg = object->start_address;
+	return mxt_write_reg(data->client, reg + offset, val);
+}
+
+static void mxt_input_report(struct mxt_data *data, int single_id)
+{
+	struct mxt_finger *finger = data->finger;
+	struct input_dev *input_dev = data->input_dev;
+	int status = finger[single_id].status;
+	int finger_num = 0;
+	int id;
+
+	for (id = 0; id < MXT_MAX_FINGER; id++) {
+		if (!finger[id].status)
+			continue;
+
+		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+				finger[id].status != MXT_RELEASE ?
+				finger[id].area : 0);
+		input_report_abs(input_dev, ABS_MT_POSITION_X,
+				finger[id].x);
+		input_report_abs(input_dev, ABS_MT_POSITION_Y,
+				finger[id].y);
+		input_mt_sync(input_dev);
+
+		if (finger[id].status == MXT_RELEASE)
+			finger[id].status = 0;
+		else
+			finger_num++;
+	}
+
+	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
+
+	if (status != MXT_RELEASE) {
+		input_report_abs(input_dev, ABS_X, finger[single_id].x);
+		input_report_abs(input_dev, ABS_Y, finger[single_id].y);
+	}
+
+	input_sync(input_dev);
+}
+
+static void mxt_input_touchevent(struct mxt_data *data,
+				      struct mxt_message *message, int id)
+{
+	struct mxt_finger *finger = data->finger;
+	struct device *dev = &data->client->dev;
+	u8 status = message->message[0];
+	int x;
+	int y;
+	int area;
+
+	/* Check the touch is present on the screen */
+	if (!(status & MXT_DETECT)) {
+		if (status & MXT_RELEASE) {
+			dev_dbg(dev, "[%d] released\n", id);
+
+			finger[id].status = MXT_RELEASE;
+			mxt_input_report(data, id);
+		}
+		return;
+	}
+
+	/* Check only AMP detection */
+	if (!(status & (MXT_PRESS | MXT_MOVE)))
+		return;
+
+	x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
+	y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
+	area = message->message[4];
+
+	dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
+		status & MXT_MOVE ? "moved" : "pressed",
+		x, y, area);
+
+	finger[id].status = status & MXT_MOVE ?
+				MXT_MOVE : MXT_PRESS;
+	finger[id].x = x;
+	finger[id].y = y;
+	finger[id].area = area;
+
+	mxt_input_report(data, id);
+}
+
+static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+{
+	struct mxt_data *data = dev_id;
+	struct mxt_message message;
+	struct mxt_object *object;
+	struct device *dev = &data->client->dev;
+	int id;
+	u8 reportid;
+	u8 max_reportid;
+	u8 min_reportid;
+
+	do {
+		if (mxt_read_message(data, &message)) {
+			dev_err(dev, "Failed to read message\n");
+			goto end;
+		}
+
+		reportid = message.reportid;
+
+		/* whether reportid is thing of MXT_TOUCH_MULTI */
+		object = mxt_get_object(data, MXT_TOUCH_MULTI);
+		if (!object)
+			goto end;
+
+		max_reportid = object->max_reportid;
+		min_reportid = max_reportid - object->num_report_ids + 1;
+		id = reportid - min_reportid;
+
+		if (reportid >= min_reportid && reportid <= max_reportid)
+			mxt_input_touchevent(data, &message, id);
+		else
+			mxt_dump_message(dev, &message);
+	} while (reportid != 0xff);
+
+end:
+	return IRQ_HANDLED;
+}
+
+static int mxt_check_reg_init(struct mxt_data *data)
+{
+	const struct mxt_platform_data *pdata = data->pdata;
+	struct mxt_object *object;
+	struct device *dev = &data->client->dev;
+	int index = 0;
+	int i, j, config_offset;
+
+	if (!pdata->config) {
+		dev_dbg(dev, "No cfg data defined, skipping reg init\n");
+		return 0;
+	}
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+
+		if (!mxt_object_writable(object->type))
+			continue;
+
+		for (j = 0; j < object->size + 1; j++) {
+			config_offset = index + j;
+			if (config_offset > pdata->config_length) {
+				dev_err(dev, "Not enough config data!\n");
+				return -EINVAL;
+			}
+			mxt_write_object(data, object->type, j,
+					 pdata->config[config_offset]);
+		}
+		index += object->size + 1;
+	}
+
+	return 0;
+}
+
+static int mxt_make_highchg(struct mxt_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct mxt_message message;
+	int count = 10;
+	int error;
+
+	/* Read dummy message to make high CHG pin */
+	do {
+		error = mxt_read_message(data, &message);
+		if (error)
+			return error;
+	} while (message.reportid != 0xff && --count);
+
+	if (!count) {
+		dev_err(dev, "CHG pin isn't cleared\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static void mxt_handle_pdata(struct mxt_data *data)
+{
+	const struct mxt_platform_data *pdata = data->pdata;
+	u8 voltage;
+
+	/* Set touchscreen lines */
+	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
+			pdata->x_line);
+	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
+			pdata->y_line);
+
+	/* Set touchscreen orient */
+	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
+			pdata->orient);
+
+	/* Set touchscreen burst length */
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_BLEN, pdata->blen);
+
+	/* Set touchscreen threshold */
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_TCHTHR, pdata->threshold);
+
+	/* Set touchscreen resolution */
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
+
+	/* Set touchscreen voltage */
+	if (pdata->voltage) {
+		if (pdata->voltage < MXT_VOLTAGE_DEFAULT) {
+			voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) /
+				MXT_VOLTAGE_STEP;
+			voltage = 0xff - voltage + 1;
+		} else
+			voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
+				MXT_VOLTAGE_STEP;
+
+		mxt_write_object(data, MXT_SPT_CTECONFIG,
+				MXT_CTE_VOLTAGE, voltage);
+	}
+}
+
+static int mxt_get_info(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct mxt_info *info = &data->info;
+	int error;
+	u8 val;
+
+	error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
+	if (error)
+		return error;
+	info->family_id = val;
+
+	error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
+	if (error)
+		return error;
+	info->variant_id = val;
+
+	error = mxt_read_reg(client, MXT_VERSION, &val);
+	if (error)
+		return error;
+	info->version = val;
+
+	error = mxt_read_reg(client, MXT_BUILD, &val);
+	if (error)
+		return error;
+	info->build = val;
+
+	error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
+	if (error)
+		return error;
+	info->object_num = val;
+
+	return 0;
+}
+
+static int mxt_get_object_table(struct mxt_data *data)
+{
+	int error;
+	int i;
+	u16 reg;
+	u8 reportid = 0;
+	u8 buf[MXT_OBJECT_SIZE];
+
+	for (i = 0; i < data->info.object_num; i++) {
+		struct mxt_object *object = data->object_table + i;
+
+		reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
+		error = mxt_read_object_table(data->client, reg, buf);
+		if (error)
+			return error;
+
+		object->type = buf[0];
+		object->start_address = (buf[2] << 8) | buf[1];
+		object->size = buf[3];
+		object->instances = buf[4];
+		object->num_report_ids = buf[5];
+
+		if (object->num_report_ids) {
+			reportid += object->num_report_ids *
+					(object->instances + 1);
+			object->max_reportid = reportid;
+		}
+	}
+
+	return 0;
+}
+
+static int mxt_initialize(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct mxt_info *info = &data->info;
+	int error;
+	u8 val;
+
+	error = mxt_get_info(data);
+	if (error)
+		return error;
+
+	data->object_table = kcalloc(info->object_num,
+				     sizeof(struct mxt_object),
+				     GFP_KERNEL);
+	if (!data->object_table) {
+		dev_err(&client->dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	/* Get object table information */
+	error = mxt_get_object_table(data);
+	if (error)
+		return error;
+
+	/* Check register init values */
+	error = mxt_check_reg_init(data);
+	if (error)
+		return error;
+
+	error = mxt_make_highchg(data);
+	if (error)
+		return error;
+
+	mxt_handle_pdata(data);
+
+	/* Backup to memory */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_BACKUPNV,
+			MXT_BACKUP_VALUE);
+	msleep(MXT_BACKUP_TIME);
+
+	/* Soft reset */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_RESET, 1);
+	msleep(MXT_RESET_TIME);
+
+	/* Update matrix size at info struct */
+	error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
+	if (error)
+		return error;
+	info->matrix_xsize = val;
+
+	error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
+	if (error)
+		return error;
+	info->matrix_ysize = val;
+
+	dev_info(&client->dev,
+			"Family ID: %d Variant ID: %d Version: %d Build: %d\n",
+			info->family_id, info->variant_id, info->version,
+			info->build);
+
+	dev_info(&client->dev,
+			"Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
+			info->matrix_xsize, info->matrix_ysize,
+			info->object_num);
+
+	return 0;
+}
+
+static ssize_t mxt_object_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct mxt_object *object;
+	int count = 0;
+	int i, j;
+	int error;
+	u8 val;
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+
+		count += sprintf(buf + count,
+				"Object Table Element %d(Type %d)\n",
+				i + 1, object->type);
+
+		if (!mxt_object_readable(object->type)) {
+			count += sprintf(buf + count, "\n");
+			continue;
+		}
+
+		for (j = 0; j < object->size + 1; j++) {
+			error = mxt_read_object(data,
+						object->type, j, &val);
+			if (error)
+				return error;
+
+			count += sprintf(buf + count,
+					"  Byte %d: 0x%x (%d)\n", j, val, val);
+		}
+
+		count += sprintf(buf + count, "\n");
+	}
+
+	return count;
+}
+
+static int mxt_load_fw(struct device *dev, const char *fn)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	const struct firmware *fw = NULL;
+	unsigned int frame_size;
+	unsigned int pos = 0;
+	int ret;
+
+	ret = request_firmware(&fw, fn, dev);
+	if (ret) {
+		dev_err(dev, "Unable to open firmware %s\n", fn);
+		return ret;
+	}
+
+	/* Change to the bootloader mode */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+	msleep(MXT_RESET_TIME);
+
+	/* Change to slave address of bootloader */
+	if (client->addr == MXT_APP_LOW)
+		client->addr = MXT_BOOT_LOW;
+	else
+		client->addr = MXT_BOOT_HIGH;
+
+	ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
+	if (ret)
+		goto out;
+
+	/* Unlock bootloader */
+	mxt_unlock_bootloader(client);
+
+	while (pos < fw->size) {
+		ret = mxt_check_bootloader(client,
+						MXT_WAITING_FRAME_DATA);
+		if (ret)
+			goto out;
+
+		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+
+		/* We should add 2 at frame size as the the firmware data is not
+		 * included the CRC bytes.
+		 */
+		frame_size += 2;
+
+		/* Write one frame to device */
+		mxt_fw_write(client, fw->data + pos, frame_size);
+
+		ret = mxt_check_bootloader(client,
+						MXT_FRAME_CRC_PASS);
+		if (ret)
+			goto out;
+
+		pos += frame_size;
+
+		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+	}
+
+out:
+	release_firmware(fw);
+
+	/* Change to slave address of application */
+	if (client->addr == MXT_BOOT_LOW)
+		client->addr = MXT_APP_LOW;
+	else
+		client->addr = MXT_APP_HIGH;
+
+	return ret;
+}
+
+static ssize_t mxt_update_fw_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int error;
+
+	disable_irq(data->irq);
+
+	error = mxt_load_fw(dev, MXT_FW_NAME);
+	if (error) {
+		dev_err(dev, "The firmware update failed(%d)\n", error);
+		count = error;
+	} else {
+		dev_dbg(dev, "The firmware update succeeded\n");
+
+		/* Wait for reset */
+		msleep(MXT_FWRESET_TIME);
+
+		kfree(data->object_table);
+		data->object_table = NULL;
+
+		mxt_initialize(data);
+	}
+
+	enable_irq(data->irq);
+
+	return count;
+}
+
+static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
+static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
+
+static struct attribute *mxt_attrs[] = {
+	&dev_attr_object.attr,
+	&dev_attr_update_fw.attr,
+	NULL
+};
+
+static const struct attribute_group mxt_attr_group = {
+	.attrs = mxt_attrs,
+};
+
+static void mxt_start(struct mxt_data *data)
+{
+	/* Touch enable */
+	mxt_write_object(data,
+			MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
+}
+
+static void mxt_stop(struct mxt_data *data)
+{
+	/* Touch disable */
+	mxt_write_object(data,
+			MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
+}
+
+static int mxt_input_open(struct input_dev *dev)
+{
+	struct mxt_data *data = input_get_drvdata(dev);
+
+	mxt_start(data);
+
+	return 0;
+}
+
+static void mxt_input_close(struct input_dev *dev)
+{
+	struct mxt_data *data = input_get_drvdata(dev);
+
+	mxt_stop(data);
+}
+
+static int __devinit mxt_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	const struct mxt_platform_data *pdata = client->dev.platform_data;
+	struct mxt_data *data;
+	struct input_dev *input_dev;
+	int error;
+
+	if (!pdata)
+		return -EINVAL;
+
+	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!data || !input_dev) {
+		dev_err(&client->dev, "Failed to allocate memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	input_dev->name = "Atmel maXTouch Touchscreen";
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+	input_dev->open = mxt_input_open;
+	input_dev->close = mxt_input_close;
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+
+	/* For single touch */
+	input_set_abs_params(input_dev, ABS_X,
+			     0, MXT_MAX_XC, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			     0, MXT_MAX_YC, 0, 0);
+
+	/* For multi touch */
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+			     0, MXT_MAX_AREA, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+			     0, MXT_MAX_XC, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+			     0, MXT_MAX_YC, 0, 0);
+
+	input_set_drvdata(input_dev, data);
+
+	data->client = client;
+	data->input_dev = input_dev;
+	data->pdata = pdata;
+	data->irq = client->irq;
+
+	i2c_set_clientdata(client, data);
+
+	error = mxt_initialize(data);
+	if (error)
+		goto err_free_object;
+
+	error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+			pdata->irqflags, client->dev.driver->name, data);
+	if (error) {
+		dev_err(&client->dev, "Failed to register interrupt\n");
+		goto err_free_object;
+	}
+
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_irq;
+
+	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+	if (error)
+		goto err_unregister_device;
+
+	return 0;
+
+err_unregister_device:
+	input_unregister_device(input_dev);
+	input_dev = NULL;
+err_free_irq:
+	free_irq(client->irq, data);
+err_free_object:
+	kfree(data->object_table);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(data);
+	return error;
+}
+
+static int __devexit mxt_remove(struct i2c_client *client)
+{
+	struct mxt_data *data = i2c_get_clientdata(client);
+
+	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+	free_irq(data->irq, data);
+	input_unregister_device(data->input_dev);
+	kfree(data->object_table);
+	kfree(data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxt_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mxt_data *data = i2c_get_clientdata(client);
+	struct input_dev *input_dev = data->input_dev;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		mxt_stop(data);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
+static int mxt_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mxt_data *data = i2c_get_clientdata(client);
+	struct input_dev *input_dev = data->input_dev;
+
+	/* Soft reset */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_RESET, 1);
+
+	msleep(MXT_RESET_TIME);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		mxt_start(data);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
+static const struct dev_pm_ops mxt_pm_ops = {
+	.suspend	= mxt_suspend,
+	.resume		= mxt_resume,
+};
+#endif
+
+static const struct i2c_device_id mxt_id[] = {
+	{ "qt602240_ts", 0 },
+	{ "atmel_mxt_ts", 0 },
+	{ "mXT224", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mxt_id);
+
+static struct i2c_driver mxt_driver = {
+	.driver = {
+		.name	= "atmel_mxt_ts",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &mxt_pm_ops,
+#endif
+	},
+	.probe		= mxt_probe,
+	.remove		= __devexit_p(mxt_remove),
+	.id_table	= mxt_id,
+};
+
+static int __init mxt_init(void)
+{
+	return i2c_add_driver(&mxt_driver);
+}
+
+static void __exit mxt_exit(void)
+{
+	i2c_del_driver(&mxt_driver);
+}
+
+module_init(mxt_init);
+module_exit(mxt_exit);
+
+/* Module information */
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/qt602240_ts.c b/drivers/input/touchscreen/qt602240_ts.c
deleted file mode 100644
index 4dcb0e8..0000000
--- a/drivers/input/touchscreen/qt602240_ts.c
+++ /dev/null
@@ -1,1406 +0,0 @@
-/*
- * AT42QT602240/ATMXT224 Touchscreen driver
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <linux/i2c/qt602240_ts.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-/* Version */
-#define QT602240_VER_20			20
-#define QT602240_VER_21			21
-#define QT602240_VER_22			22
-
-/* Slave addresses */
-#define QT602240_APP_LOW		0x4a
-#define QT602240_APP_HIGH		0x4b
-#define QT602240_BOOT_LOW		0x24
-#define QT602240_BOOT_HIGH		0x25
-
-/* Firmware */
-#define QT602240_FW_NAME		"qt602240.fw"
-
-/* Registers */
-#define QT602240_FAMILY_ID		0x00
-#define QT602240_VARIANT_ID		0x01
-#define QT602240_VERSION		0x02
-#define QT602240_BUILD			0x03
-#define QT602240_MATRIX_X_SIZE		0x04
-#define QT602240_MATRIX_Y_SIZE		0x05
-#define QT602240_OBJECT_NUM		0x06
-#define QT602240_OBJECT_START		0x07
-
-#define QT602240_OBJECT_SIZE		6
-
-/* Object types */
-#define QT602240_DEBUG_DIAGNOSTIC	37
-#define QT602240_GEN_MESSAGE		5
-#define QT602240_GEN_COMMAND		6
-#define QT602240_GEN_POWER		7
-#define QT602240_GEN_ACQUIRE		8
-#define QT602240_TOUCH_MULTI		9
-#define QT602240_TOUCH_KEYARRAY		15
-#define QT602240_TOUCH_PROXIMITY	23
-#define QT602240_PROCI_GRIPFACE		20
-#define QT602240_PROCG_NOISE		22
-#define QT602240_PROCI_ONETOUCH		24
-#define QT602240_PROCI_TWOTOUCH		27
-#define QT602240_SPT_COMMSCONFIG	18	/* firmware ver 21 over */
-#define QT602240_SPT_GPIOPWM		19
-#define QT602240_SPT_SELFTEST		25
-#define QT602240_SPT_CTECONFIG		28
-#define QT602240_SPT_USERDATA		38	/* firmware ver 21 over */
-
-/* QT602240_GEN_COMMAND field */
-#define QT602240_COMMAND_RESET		0
-#define QT602240_COMMAND_BACKUPNV	1
-#define QT602240_COMMAND_CALIBRATE	2
-#define QT602240_COMMAND_REPORTALL	3
-#define QT602240_COMMAND_DIAGNOSTIC	5
-
-/* QT602240_GEN_POWER field */
-#define QT602240_POWER_IDLEACQINT	0
-#define QT602240_POWER_ACTVACQINT	1
-#define QT602240_POWER_ACTV2IDLETO	2
-
-/* QT602240_GEN_ACQUIRE field */
-#define QT602240_ACQUIRE_CHRGTIME	0
-#define QT602240_ACQUIRE_TCHDRIFT	2
-#define QT602240_ACQUIRE_DRIFTST	3
-#define QT602240_ACQUIRE_TCHAUTOCAL	4
-#define QT602240_ACQUIRE_SYNC		5
-#define QT602240_ACQUIRE_ATCHCALST	6
-#define QT602240_ACQUIRE_ATCHCALSTHR	7
-
-/* QT602240_TOUCH_MULTI field */
-#define QT602240_TOUCH_CTRL		0
-#define QT602240_TOUCH_XORIGIN		1
-#define QT602240_TOUCH_YORIGIN		2
-#define QT602240_TOUCH_XSIZE		3
-#define QT602240_TOUCH_YSIZE		4
-#define QT602240_TOUCH_BLEN		6
-#define QT602240_TOUCH_TCHTHR		7
-#define QT602240_TOUCH_TCHDI		8
-#define QT602240_TOUCH_ORIENT		9
-#define QT602240_TOUCH_MOVHYSTI		11
-#define QT602240_TOUCH_MOVHYSTN		12
-#define QT602240_TOUCH_NUMTOUCH		14
-#define QT602240_TOUCH_MRGHYST		15
-#define QT602240_TOUCH_MRGTHR		16
-#define QT602240_TOUCH_AMPHYST		17
-#define QT602240_TOUCH_XRANGE_LSB	18
-#define QT602240_TOUCH_XRANGE_MSB	19
-#define QT602240_TOUCH_YRANGE_LSB	20
-#define QT602240_TOUCH_YRANGE_MSB	21
-#define QT602240_TOUCH_XLOCLIP		22
-#define QT602240_TOUCH_XHICLIP		23
-#define QT602240_TOUCH_YLOCLIP		24
-#define QT602240_TOUCH_YHICLIP		25
-#define QT602240_TOUCH_XEDGECTRL	26
-#define QT602240_TOUCH_XEDGEDIST	27
-#define QT602240_TOUCH_YEDGECTRL	28
-#define QT602240_TOUCH_YEDGEDIST	29
-#define QT602240_TOUCH_JUMPLIMIT	30	/* firmware ver 22 over */
-
-/* QT602240_PROCI_GRIPFACE field */
-#define QT602240_GRIPFACE_CTRL		0
-#define QT602240_GRIPFACE_XLOGRIP	1
-#define QT602240_GRIPFACE_XHIGRIP	2
-#define QT602240_GRIPFACE_YLOGRIP	3
-#define QT602240_GRIPFACE_YHIGRIP	4
-#define QT602240_GRIPFACE_MAXTCHS	5
-#define QT602240_GRIPFACE_SZTHR1	7
-#define QT602240_GRIPFACE_SZTHR2	8
-#define QT602240_GRIPFACE_SHPTHR1	9
-#define QT602240_GRIPFACE_SHPTHR2	10
-#define QT602240_GRIPFACE_SUPEXTTO	11
-
-/* QT602240_PROCI_NOISE field */
-#define QT602240_NOISE_CTRL		0
-#define QT602240_NOISE_OUTFLEN		1
-#define QT602240_NOISE_GCAFUL_LSB	3
-#define QT602240_NOISE_GCAFUL_MSB	4
-#define QT602240_NOISE_GCAFLL_LSB	5
-#define QT602240_NOISE_GCAFLL_MSB	6
-#define QT602240_NOISE_ACTVGCAFVALID	7
-#define QT602240_NOISE_NOISETHR		8
-#define QT602240_NOISE_FREQHOPSCALE	10
-#define QT602240_NOISE_FREQ0		11
-#define QT602240_NOISE_FREQ1		12
-#define QT602240_NOISE_FREQ2		13
-#define QT602240_NOISE_FREQ3		14
-#define QT602240_NOISE_FREQ4		15
-#define QT602240_NOISE_IDLEGCAFVALID	16
-
-/* QT602240_SPT_COMMSCONFIG */
-#define QT602240_COMMS_CTRL		0
-#define QT602240_COMMS_CMD		1
-
-/* QT602240_SPT_CTECONFIG field */
-#define QT602240_CTE_CTRL		0
-#define QT602240_CTE_CMD		1
-#define QT602240_CTE_MODE		2
-#define QT602240_CTE_IDLEGCAFDEPTH	3
-#define QT602240_CTE_ACTVGCAFDEPTH	4
-#define QT602240_CTE_VOLTAGE		5	/* firmware ver 21 over */
-
-#define QT602240_VOLTAGE_DEFAULT	2700000
-#define QT602240_VOLTAGE_STEP		10000
-
-/* Define for QT602240_GEN_COMMAND */
-#define QT602240_BOOT_VALUE		0xa5
-#define QT602240_BACKUP_VALUE		0x55
-#define QT602240_BACKUP_TIME		25	/* msec */
-#define QT602240_RESET_TIME		65	/* msec */
-
-#define QT602240_FWRESET_TIME		175	/* msec */
-
-/* Command to unlock bootloader */
-#define QT602240_UNLOCK_CMD_MSB		0xaa
-#define QT602240_UNLOCK_CMD_LSB		0xdc
-
-/* Bootloader mode status */
-#define QT602240_WAITING_BOOTLOAD_CMD	0xc0	/* valid 7 6 bit only */
-#define QT602240_WAITING_FRAME_DATA	0x80	/* valid 7 6 bit only */
-#define QT602240_FRAME_CRC_CHECK	0x02
-#define QT602240_FRAME_CRC_FAIL		0x03
-#define QT602240_FRAME_CRC_PASS		0x04
-#define QT602240_APP_CRC_FAIL		0x40	/* valid 7 8 bit only */
-#define QT602240_BOOT_STATUS_MASK	0x3f
-
-/* Touch status */
-#define QT602240_SUPPRESS		(1 << 1)
-#define QT602240_AMP			(1 << 2)
-#define QT602240_VECTOR			(1 << 3)
-#define QT602240_MOVE			(1 << 4)
-#define QT602240_RELEASE		(1 << 5)
-#define QT602240_PRESS			(1 << 6)
-#define QT602240_DETECT			(1 << 7)
-
-/* Touchscreen absolute values */
-#define QT602240_MAX_XC			0x3ff
-#define QT602240_MAX_YC			0x3ff
-#define QT602240_MAX_AREA		0xff
-
-#define QT602240_MAX_FINGER		10
-
-/* Initial register values recommended from chip vendor */
-static const u8 init_vals_ver_20[] = {
-	/* QT602240_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* QT602240_GEN_ACQUIRE(8) */
-	0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14,
-	/* QT602240_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64,
-	/* QT602240_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00,
-	/* QT602240_PROCI_GRIPFACE(20) */
-	0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04,
-	0x1e, 0x00,
-	/* QT602240_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00,
-	0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8,
-	/* QT602240_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00,
-	/* QT602240_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x00, 0x04, 0x08,
-};
-
-static const u8 init_vals_ver_21[] = {
-	/* QT602240_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* QT602240_GEN_ACQUIRE(8) */
-	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-	/* QT602240_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_GRIPFACE(20) */
-	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-	0x0f, 0x0a,
-	/* QT602240_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-	/* QT602240_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00,
-	/* QT602240_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
-};
-
-static const u8 init_vals_ver_22[] = {
-	/* QT602240_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* QT602240_GEN_ACQUIRE(8) */
-	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-	/* QT602240_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_GRIPFACE(20) */
-	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-	0x0f, 0x0a,
-	/* QT602240_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-	/* QT602240_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
-};
-
-struct qt602240_info {
-	u8 family_id;
-	u8 variant_id;
-	u8 version;
-	u8 build;
-	u8 matrix_xsize;
-	u8 matrix_ysize;
-	u8 object_num;
-};
-
-struct qt602240_object {
-	u8 type;
-	u16 start_address;
-	u8 size;
-	u8 instances;
-	u8 num_report_ids;
-
-	/* to map object and message */
-	u8 max_reportid;
-};
-
-struct qt602240_message {
-	u8 reportid;
-	u8 message[7];
-	u8 checksum;
-};
-
-struct qt602240_finger {
-	int status;
-	int x;
-	int y;
-	int area;
-};
-
-/* Each client has this additional data */
-struct qt602240_data {
-	struct i2c_client *client;
-	struct input_dev *input_dev;
-	const struct qt602240_platform_data *pdata;
-	struct qt602240_object *object_table;
-	struct qt602240_info info;
-	struct qt602240_finger finger[QT602240_MAX_FINGER];
-	unsigned int irq;
-};
-
-static bool qt602240_object_readable(unsigned int type)
-{
-	switch (type) {
-	case QT602240_GEN_MESSAGE:
-	case QT602240_GEN_COMMAND:
-	case QT602240_GEN_POWER:
-	case QT602240_GEN_ACQUIRE:
-	case QT602240_TOUCH_MULTI:
-	case QT602240_TOUCH_KEYARRAY:
-	case QT602240_TOUCH_PROXIMITY:
-	case QT602240_PROCI_GRIPFACE:
-	case QT602240_PROCG_NOISE:
-	case QT602240_PROCI_ONETOUCH:
-	case QT602240_PROCI_TWOTOUCH:
-	case QT602240_SPT_COMMSCONFIG:
-	case QT602240_SPT_GPIOPWM:
-	case QT602240_SPT_SELFTEST:
-	case QT602240_SPT_CTECONFIG:
-	case QT602240_SPT_USERDATA:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static bool qt602240_object_writable(unsigned int type)
-{
-	switch (type) {
-	case QT602240_GEN_COMMAND:
-	case QT602240_GEN_POWER:
-	case QT602240_GEN_ACQUIRE:
-	case QT602240_TOUCH_MULTI:
-	case QT602240_TOUCH_KEYARRAY:
-	case QT602240_TOUCH_PROXIMITY:
-	case QT602240_PROCI_GRIPFACE:
-	case QT602240_PROCG_NOISE:
-	case QT602240_PROCI_ONETOUCH:
-	case QT602240_PROCI_TWOTOUCH:
-	case QT602240_SPT_GPIOPWM:
-	case QT602240_SPT_SELFTEST:
-	case QT602240_SPT_CTECONFIG:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static void qt602240_dump_message(struct device *dev,
-				  struct qt602240_message *message)
-{
-	dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
-	dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
-	dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
-	dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
-	dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
-	dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
-	dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
-	dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
-	dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
-}
-
-static int qt602240_check_bootloader(struct i2c_client *client,
-				     unsigned int state)
-{
-	u8 val;
-
-recheck:
-	if (i2c_master_recv(client, &val, 1) != 1) {
-		dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
-		return -EIO;
-	}
-
-	switch (state) {
-	case QT602240_WAITING_BOOTLOAD_CMD:
-	case QT602240_WAITING_FRAME_DATA:
-		val &= ~QT602240_BOOT_STATUS_MASK;
-		break;
-	case QT602240_FRAME_CRC_PASS:
-		if (val == QT602240_FRAME_CRC_CHECK)
-			goto recheck;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (val != state) {
-		dev_err(&client->dev, "Unvalid bootloader mode state\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int qt602240_unlock_bootloader(struct i2c_client *client)
-{
-	u8 buf[2];
-
-	buf[0] = QT602240_UNLOCK_CMD_LSB;
-	buf[1] = QT602240_UNLOCK_CMD_MSB;
-
-	if (i2c_master_send(client, buf, 2) != 2) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int qt602240_fw_write(struct i2c_client *client,
-			     const u8 *data, unsigned int frame_size)
-{
-	if (i2c_master_send(client, data, frame_size) != frame_size) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int __qt602240_read_reg(struct i2c_client *client,
-			       u16 reg, u16 len, void *val)
-{
-	struct i2c_msg xfer[2];
-	u8 buf[2];
-
-	buf[0] = reg & 0xff;
-	buf[1] = (reg >> 8) & 0xff;
-
-	/* Write register */
-	xfer[0].addr = client->addr;
-	xfer[0].flags = 0;
-	xfer[0].len = 2;
-	xfer[0].buf = buf;
-
-	/* Read data */
-	xfer[1].addr = client->addr;
-	xfer[1].flags = I2C_M_RD;
-	xfer[1].len = len;
-	xfer[1].buf = val;
-
-	if (i2c_transfer(client->adapter, xfer, 2) != 2) {
-		dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int qt602240_read_reg(struct i2c_client *client, u16 reg, u8 *val)
-{
-	return __qt602240_read_reg(client, reg, 1, val);
-}
-
-static int qt602240_write_reg(struct i2c_client *client, u16 reg, u8 val)
-{
-	u8 buf[3];
-
-	buf[0] = reg & 0xff;
-	buf[1] = (reg >> 8) & 0xff;
-	buf[2] = val;
-
-	if (i2c_master_send(client, buf, 3) != 3) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int qt602240_read_object_table(struct i2c_client *client,
-				      u16 reg, u8 *object_buf)
-{
-	return __qt602240_read_reg(client, reg, QT602240_OBJECT_SIZE,
-				   object_buf);
-}
-
-static struct qt602240_object *
-qt602240_get_object(struct qt602240_data *data, u8 type)
-{
-	struct qt602240_object *object;
-	int i;
-
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
-		if (object->type == type)
-			return object;
-	}
-
-	dev_err(&data->client->dev, "Invalid object type\n");
-	return NULL;
-}
-
-static int qt602240_read_message(struct qt602240_data *data,
-				 struct qt602240_message *message)
-{
-	struct qt602240_object *object;
-	u16 reg;
-
-	object = qt602240_get_object(data, QT602240_GEN_MESSAGE);
-	if (!object)
-		return -EINVAL;
-
-	reg = object->start_address;
-	return __qt602240_read_reg(data->client, reg,
-			sizeof(struct qt602240_message), message);
-}
-
-static int qt602240_read_object(struct qt602240_data *data,
-				u8 type, u8 offset, u8 *val)
-{
-	struct qt602240_object *object;
-	u16 reg;
-
-	object = qt602240_get_object(data, type);
-	if (!object)
-		return -EINVAL;
-
-	reg = object->start_address;
-	return __qt602240_read_reg(data->client, reg + offset, 1, val);
-}
-
-static int qt602240_write_object(struct qt602240_data *data,
-				 u8 type, u8 offset, u8 val)
-{
-	struct qt602240_object *object;
-	u16 reg;
-
-	object = qt602240_get_object(data, type);
-	if (!object)
-		return -EINVAL;
-
-	reg = object->start_address;
-	return qt602240_write_reg(data->client, reg + offset, val);
-}
-
-static void qt602240_input_report(struct qt602240_data *data, int single_id)
-{
-	struct qt602240_finger *finger = data->finger;
-	struct input_dev *input_dev = data->input_dev;
-	int status = finger[single_id].status;
-	int finger_num = 0;
-	int id;
-
-	for (id = 0; id < QT602240_MAX_FINGER; id++) {
-		if (!finger[id].status)
-			continue;
-
-		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
-				finger[id].status != QT602240_RELEASE ?
-				finger[id].area : 0);
-		input_report_abs(input_dev, ABS_MT_POSITION_X,
-				finger[id].x);
-		input_report_abs(input_dev, ABS_MT_POSITION_Y,
-				finger[id].y);
-		input_mt_sync(input_dev);
-
-		if (finger[id].status == QT602240_RELEASE)
-			finger[id].status = 0;
-		else
-			finger_num++;
-	}
-
-	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
-
-	if (status != QT602240_RELEASE) {
-		input_report_abs(input_dev, ABS_X, finger[single_id].x);
-		input_report_abs(input_dev, ABS_Y, finger[single_id].y);
-	}
-
-	input_sync(input_dev);
-}
-
-static void qt602240_input_touchevent(struct qt602240_data *data,
-				      struct qt602240_message *message, int id)
-{
-	struct qt602240_finger *finger = data->finger;
-	struct device *dev = &data->client->dev;
-	u8 status = message->message[0];
-	int x;
-	int y;
-	int area;
-
-	/* Check the touch is present on the screen */
-	if (!(status & QT602240_DETECT)) {
-		if (status & QT602240_RELEASE) {
-			dev_dbg(dev, "[%d] released\n", id);
-
-			finger[id].status = QT602240_RELEASE;
-			qt602240_input_report(data, id);
-		}
-		return;
-	}
-
-	/* Check only AMP detection */
-	if (!(status & (QT602240_PRESS | QT602240_MOVE)))
-		return;
-
-	x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
-	y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
-	area = message->message[4];
-
-	dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
-		status & QT602240_MOVE ? "moved" : "pressed",
-		x, y, area);
-
-	finger[id].status = status & QT602240_MOVE ?
-				QT602240_MOVE : QT602240_PRESS;
-	finger[id].x = x;
-	finger[id].y = y;
-	finger[id].area = area;
-
-	qt602240_input_report(data, id);
-}
-
-static irqreturn_t qt602240_interrupt(int irq, void *dev_id)
-{
-	struct qt602240_data *data = dev_id;
-	struct qt602240_message message;
-	struct qt602240_object *object;
-	struct device *dev = &data->client->dev;
-	int id;
-	u8 reportid;
-	u8 max_reportid;
-	u8 min_reportid;
-
-	do {
-		if (qt602240_read_message(data, &message)) {
-			dev_err(dev, "Failed to read message\n");
-			goto end;
-		}
-
-		reportid = message.reportid;
-
-		/* whether reportid is thing of QT602240_TOUCH_MULTI */
-		object = qt602240_get_object(data, QT602240_TOUCH_MULTI);
-		if (!object)
-			goto end;
-
-		max_reportid = object->max_reportid;
-		min_reportid = max_reportid - object->num_report_ids + 1;
-		id = reportid - min_reportid;
-
-		if (reportid >= min_reportid && reportid <= max_reportid)
-			qt602240_input_touchevent(data, &message, id);
-		else
-			qt602240_dump_message(dev, &message);
-	} while (reportid != 0xff);
-
-end:
-	return IRQ_HANDLED;
-}
-
-static int qt602240_check_reg_init(struct qt602240_data *data)
-{
-	struct qt602240_object *object;
-	struct device *dev = &data->client->dev;
-	int index = 0;
-	int i, j;
-	u8 version = data->info.version;
-	u8 *init_vals;
-
-	switch (version) {
-	case QT602240_VER_20:
-		init_vals = (u8 *)init_vals_ver_20;
-		break;
-	case QT602240_VER_21:
-		init_vals = (u8 *)init_vals_ver_21;
-		break;
-	case QT602240_VER_22:
-		init_vals = (u8 *)init_vals_ver_22;
-		break;
-	default:
-		dev_err(dev, "Firmware version %d doesn't support\n", version);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
-
-		if (!qt602240_object_writable(object->type))
-			continue;
-
-		for (j = 0; j < object->size + 1; j++)
-			qt602240_write_object(data, object->type, j,
-					init_vals[index + j]);
-
-		index += object->size + 1;
-	}
-
-	return 0;
-}
-
-static int qt602240_check_matrix_size(struct qt602240_data *data)
-{
-	const struct qt602240_platform_data *pdata = data->pdata;
-	struct device *dev = &data->client->dev;
-	int mode = -1;
-	int error;
-	u8 val;
-
-	dev_dbg(dev, "Number of X lines: %d\n", pdata->x_line);
-	dev_dbg(dev, "Number of Y lines: %d\n", pdata->y_line);
-
-	switch (pdata->x_line) {
-	case 0 ... 15:
-		if (pdata->y_line <= 14)
-			mode = 0;
-		break;
-	case 16:
-		if (pdata->y_line <= 12)
-			mode = 1;
-		if (pdata->y_line == 13 || pdata->y_line == 14)
-			mode = 0;
-		break;
-	case 17:
-		if (pdata->y_line <= 11)
-			mode = 2;
-		if (pdata->y_line == 12 || pdata->y_line == 13)
-			mode = 1;
-		break;
-	case 18:
-		if (pdata->y_line <= 10)
-			mode = 3;
-		if (pdata->y_line == 11 || pdata->y_line == 12)
-			mode = 2;
-		break;
-	case 19:
-		if (pdata->y_line <= 9)
-			mode = 4;
-		if (pdata->y_line == 10 || pdata->y_line == 11)
-			mode = 3;
-		break;
-	case 20:
-		mode = 4;
-	}
-
-	if (mode < 0) {
-		dev_err(dev, "Invalid X/Y lines\n");
-		return -EINVAL;
-	}
-
-	error = qt602240_read_object(data, QT602240_SPT_CTECONFIG,
-				QT602240_CTE_MODE, &val);
-	if (error)
-		return error;
-
-	if (mode == val)
-		return 0;
-
-	/* Change the CTE configuration */
-	qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-			QT602240_CTE_CTRL, 1);
-	qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-			QT602240_CTE_MODE, mode);
-	qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-			QT602240_CTE_CTRL, 0);
-
-	return 0;
-}
-
-static int qt602240_make_highchg(struct qt602240_data *data)
-{
-	struct device *dev = &data->client->dev;
-	int count = 10;
-	int error;
-	u8 val;
-
-	/* Read dummy message to make high CHG pin */
-	do {
-		error = qt602240_read_object(data, QT602240_GEN_MESSAGE, 0, &val);
-		if (error)
-			return error;
-	} while ((val != 0xff) && --count);
-
-	if (!count) {
-		dev_err(dev, "CHG pin isn't cleared\n");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static void qt602240_handle_pdata(struct qt602240_data *data)
-{
-	const struct qt602240_platform_data *pdata = data->pdata;
-	u8 voltage;
-
-	/* Set touchscreen lines */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_XSIZE,
-			pdata->x_line);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_YSIZE,
-			pdata->y_line);
-
-	/* Set touchscreen orient */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_ORIENT,
-			pdata->orient);
-
-	/* Set touchscreen burst length */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_BLEN, pdata->blen);
-
-	/* Set touchscreen threshold */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_TCHTHR, pdata->threshold);
-
-	/* Set touchscreen resolution */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
-
-	/* Set touchscreen voltage */
-	if (data->info.version >= QT602240_VER_21 && pdata->voltage) {
-		if (pdata->voltage < QT602240_VOLTAGE_DEFAULT) {
-			voltage = (QT602240_VOLTAGE_DEFAULT - pdata->voltage) /
-				QT602240_VOLTAGE_STEP;
-			voltage = 0xff - voltage + 1;
-		} else
-			voltage = (pdata->voltage - QT602240_VOLTAGE_DEFAULT) /
-				QT602240_VOLTAGE_STEP;
-
-		qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-				QT602240_CTE_VOLTAGE, voltage);
-	}
-}
-
-static int qt602240_get_info(struct qt602240_data *data)
-{
-	struct i2c_client *client = data->client;
-	struct qt602240_info *info = &data->info;
-	int error;
-	u8 val;
-
-	error = qt602240_read_reg(client, QT602240_FAMILY_ID, &val);
-	if (error)
-		return error;
-	info->family_id = val;
-
-	error = qt602240_read_reg(client, QT602240_VARIANT_ID, &val);
-	if (error)
-		return error;
-	info->variant_id = val;
-
-	error = qt602240_read_reg(client, QT602240_VERSION, &val);
-	if (error)
-		return error;
-	info->version = val;
-
-	error = qt602240_read_reg(client, QT602240_BUILD, &val);
-	if (error)
-		return error;
-	info->build = val;
-
-	error = qt602240_read_reg(client, QT602240_OBJECT_NUM, &val);
-	if (error)
-		return error;
-	info->object_num = val;
-
-	return 0;
-}
-
-static int qt602240_get_object_table(struct qt602240_data *data)
-{
-	int error;
-	int i;
-	u16 reg;
-	u8 reportid = 0;
-	u8 buf[QT602240_OBJECT_SIZE];
-
-	for (i = 0; i < data->info.object_num; i++) {
-		struct qt602240_object *object = data->object_table + i;
-
-		reg = QT602240_OBJECT_START + QT602240_OBJECT_SIZE * i;
-		error = qt602240_read_object_table(data->client, reg, buf);
-		if (error)
-			return error;
-
-		object->type = buf[0];
-		object->start_address = (buf[2] << 8) | buf[1];
-		object->size = buf[3];
-		object->instances = buf[4];
-		object->num_report_ids = buf[5];
-
-		if (object->num_report_ids) {
-			reportid += object->num_report_ids *
-					(object->instances + 1);
-			object->max_reportid = reportid;
-		}
-	}
-
-	return 0;
-}
-
-static int qt602240_initialize(struct qt602240_data *data)
-{
-	struct i2c_client *client = data->client;
-	struct qt602240_info *info = &data->info;
-	int error;
-	u8 val;
-
-	error = qt602240_get_info(data);
-	if (error)
-		return error;
-
-	data->object_table = kcalloc(info->object_num,
-				     sizeof(struct qt602240_object),
-				     GFP_KERNEL);
-	if (!data->object_table) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	/* Get object table information */
-	error = qt602240_get_object_table(data);
-	if (error)
-		return error;
-
-	/* Check register init values */
-	error = qt602240_check_reg_init(data);
-	if (error)
-		return error;
-
-	/* Check X/Y matrix size */
-	error = qt602240_check_matrix_size(data);
-	if (error)
-		return error;
-
-	error = qt602240_make_highchg(data);
-	if (error)
-		return error;
-
-	qt602240_handle_pdata(data);
-
-	/* Backup to memory */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_BACKUPNV,
-			QT602240_BACKUP_VALUE);
-	msleep(QT602240_BACKUP_TIME);
-
-	/* Soft reset */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_RESET, 1);
-	msleep(QT602240_RESET_TIME);
-
-	/* Update matrix size at info struct */
-	error = qt602240_read_reg(client, QT602240_MATRIX_X_SIZE, &val);
-	if (error)
-		return error;
-	info->matrix_xsize = val;
-
-	error = qt602240_read_reg(client, QT602240_MATRIX_Y_SIZE, &val);
-	if (error)
-		return error;
-	info->matrix_ysize = val;
-
-	dev_info(&client->dev,
-			"Family ID: %d Variant ID: %d Version: %d Build: %d\n",
-			info->family_id, info->variant_id, info->version,
-			info->build);
-
-	dev_info(&client->dev,
-			"Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
-			info->matrix_xsize, info->matrix_ysize,
-			info->object_num);
-
-	return 0;
-}
-
-static ssize_t qt602240_object_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct qt602240_data *data = dev_get_drvdata(dev);
-	struct qt602240_object *object;
-	int count = 0;
-	int i, j;
-	int error;
-	u8 val;
-
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
-
-		count += sprintf(buf + count,
-				"Object Table Element %d(Type %d)\n",
-				i + 1, object->type);
-
-		if (!qt602240_object_readable(object->type)) {
-			count += sprintf(buf + count, "\n");
-			continue;
-		}
-
-		for (j = 0; j < object->size + 1; j++) {
-			error = qt602240_read_object(data,
-						object->type, j, &val);
-			if (error)
-				return error;
-
-			count += sprintf(buf + count,
-					"  Byte %d: 0x%x (%d)\n", j, val, val);
-		}
-
-		count += sprintf(buf + count, "\n");
-	}
-
-	return count;
-}
-
-static int qt602240_load_fw(struct device *dev, const char *fn)
-{
-	struct qt602240_data *data = dev_get_drvdata(dev);
-	struct i2c_client *client = data->client;
-	const struct firmware *fw = NULL;
-	unsigned int frame_size;
-	unsigned int pos = 0;
-	int ret;
-
-	ret = request_firmware(&fw, fn, dev);
-	if (ret) {
-		dev_err(dev, "Unable to open firmware %s\n", fn);
-		return ret;
-	}
-
-	/* Change to the bootloader mode */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_RESET, QT602240_BOOT_VALUE);
-	msleep(QT602240_RESET_TIME);
-
-	/* Change to slave address of bootloader */
-	if (client->addr == QT602240_APP_LOW)
-		client->addr = QT602240_BOOT_LOW;
-	else
-		client->addr = QT602240_BOOT_HIGH;
-
-	ret = qt602240_check_bootloader(client, QT602240_WAITING_BOOTLOAD_CMD);
-	if (ret)
-		goto out;
-
-	/* Unlock bootloader */
-	qt602240_unlock_bootloader(client);
-
-	while (pos < fw->size) {
-		ret = qt602240_check_bootloader(client,
-						QT602240_WAITING_FRAME_DATA);
-		if (ret)
-			goto out;
-
-		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
-
-		/* We should add 2 at frame size as the the firmware data is not
-		 * included the CRC bytes.
-		 */
-		frame_size += 2;
-
-		/* Write one frame to device */
-		qt602240_fw_write(client, fw->data + pos, frame_size);
-
-		ret = qt602240_check_bootloader(client,
-						QT602240_FRAME_CRC_PASS);
-		if (ret)
-			goto out;
-
-		pos += frame_size;
-
-		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
-	}
-
-out:
-	release_firmware(fw);
-
-	/* Change to slave address of application */
-	if (client->addr == QT602240_BOOT_LOW)
-		client->addr = QT602240_APP_LOW;
-	else
-		client->addr = QT602240_APP_HIGH;
-
-	return ret;
-}
-
-static ssize_t qt602240_update_fw_store(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	struct qt602240_data *data = dev_get_drvdata(dev);
-	unsigned int version;
-	int error;
-
-	if (sscanf(buf, "%u", &version) != 1) {
-		dev_err(dev, "Invalid values\n");
-		return -EINVAL;
-	}
-
-	if (data->info.version < QT602240_VER_21 || version < QT602240_VER_21) {
-		dev_err(dev, "FW update supported starting with version 21\n");
-		return -EINVAL;
-	}
-
-	disable_irq(data->irq);
-
-	error = qt602240_load_fw(dev, QT602240_FW_NAME);
-	if (error) {
-		dev_err(dev, "The firmware update failed(%d)\n", error);
-		count = error;
-	} else {
-		dev_dbg(dev, "The firmware update succeeded\n");
-
-		/* Wait for reset */
-		msleep(QT602240_FWRESET_TIME);
-
-		kfree(data->object_table);
-		data->object_table = NULL;
-
-		qt602240_initialize(data);
-	}
-
-	enable_irq(data->irq);
-
-	return count;
-}
-
-static DEVICE_ATTR(object, 0444, qt602240_object_show, NULL);
-static DEVICE_ATTR(update_fw, 0664, NULL, qt602240_update_fw_store);
-
-static struct attribute *qt602240_attrs[] = {
-	&dev_attr_object.attr,
-	&dev_attr_update_fw.attr,
-	NULL
-};
-
-static const struct attribute_group qt602240_attr_group = {
-	.attrs = qt602240_attrs,
-};
-
-static void qt602240_start(struct qt602240_data *data)
-{
-	/* Touch enable */
-	qt602240_write_object(data,
-			QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0x83);
-}
-
-static void qt602240_stop(struct qt602240_data *data)
-{
-	/* Touch disable */
-	qt602240_write_object(data,
-			QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0);
-}
-
-static int qt602240_input_open(struct input_dev *dev)
-{
-	struct qt602240_data *data = input_get_drvdata(dev);
-
-	qt602240_start(data);
-
-	return 0;
-}
-
-static void qt602240_input_close(struct input_dev *dev)
-{
-	struct qt602240_data *data = input_get_drvdata(dev);
-
-	qt602240_stop(data);
-}
-
-static int __devinit qt602240_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	struct qt602240_data *data;
-	struct input_dev *input_dev;
-	int error;
-
-	if (!client->dev.platform_data)
-		return -EINVAL;
-
-	data = kzalloc(sizeof(struct qt602240_data), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!data || !input_dev) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
-		error = -ENOMEM;
-		goto err_free_mem;
-	}
-
-	input_dev->name = "AT42QT602240/ATMXT224 Touchscreen";
-	input_dev->id.bustype = BUS_I2C;
-	input_dev->dev.parent = &client->dev;
-	input_dev->open = qt602240_input_open;
-	input_dev->close = qt602240_input_close;
-
-	__set_bit(EV_ABS, input_dev->evbit);
-	__set_bit(EV_KEY, input_dev->evbit);
-	__set_bit(BTN_TOUCH, input_dev->keybit);
-
-	/* For single touch */
-	input_set_abs_params(input_dev, ABS_X,
-			     0, QT602240_MAX_XC, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y,
-			     0, QT602240_MAX_YC, 0, 0);
-
-	/* For multi touch */
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			     0, QT602240_MAX_AREA, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     0, QT602240_MAX_XC, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     0, QT602240_MAX_YC, 0, 0);
-
-	input_set_drvdata(input_dev, data);
-
-	data->client = client;
-	data->input_dev = input_dev;
-	data->pdata = client->dev.platform_data;
-	data->irq = client->irq;
-
-	i2c_set_clientdata(client, data);
-
-	error = qt602240_initialize(data);
-	if (error)
-		goto err_free_object;
-
-	error = request_threaded_irq(client->irq, NULL, qt602240_interrupt,
-			IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
-	if (error) {
-		dev_err(&client->dev, "Failed to register interrupt\n");
-		goto err_free_object;
-	}
-
-	error = input_register_device(input_dev);
-	if (error)
-		goto err_free_irq;
-
-	error = sysfs_create_group(&client->dev.kobj, &qt602240_attr_group);
-	if (error)
-		goto err_unregister_device;
-
-	return 0;
-
-err_unregister_device:
-	input_unregister_device(input_dev);
-	input_dev = NULL;
-err_free_irq:
-	free_irq(client->irq, data);
-err_free_object:
-	kfree(data->object_table);
-err_free_mem:
-	input_free_device(input_dev);
-	kfree(data);
-	return error;
-}
-
-static int __devexit qt602240_remove(struct i2c_client *client)
-{
-	struct qt602240_data *data = i2c_get_clientdata(client);
-
-	sysfs_remove_group(&client->dev.kobj, &qt602240_attr_group);
-	free_irq(data->irq, data);
-	input_unregister_device(data->input_dev);
-	kfree(data->object_table);
-	kfree(data);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int qt602240_suspend(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct qt602240_data *data = i2c_get_clientdata(client);
-	struct input_dev *input_dev = data->input_dev;
-
-	mutex_lock(&input_dev->mutex);
-
-	if (input_dev->users)
-		qt602240_stop(data);
-
-	mutex_unlock(&input_dev->mutex);
-
-	return 0;
-}
-
-static int qt602240_resume(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct qt602240_data *data = i2c_get_clientdata(client);
-	struct input_dev *input_dev = data->input_dev;
-
-	/* Soft reset */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_RESET, 1);
-
-	msleep(QT602240_RESET_TIME);
-
-	mutex_lock(&input_dev->mutex);
-
-	if (input_dev->users)
-		qt602240_start(data);
-
-	mutex_unlock(&input_dev->mutex);
-
-	return 0;
-}
-
-static const struct dev_pm_ops qt602240_pm_ops = {
-	.suspend	= qt602240_suspend,
-	.resume		= qt602240_resume,
-};
-#endif
-
-static const struct i2c_device_id qt602240_id[] = {
-	{ "qt602240_ts", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, qt602240_id);
-
-static struct i2c_driver qt602240_driver = {
-	.driver = {
-		.name	= "qt602240_ts",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &qt602240_pm_ops,
-#endif
-	},
-	.probe		= qt602240_probe,
-	.remove		= __devexit_p(qt602240_remove),
-	.id_table	= qt602240_id,
-};
-
-static int __init qt602240_init(void)
-{
-	return i2c_add_driver(&qt602240_driver);
-}
-
-static void __exit qt602240_exit(void)
-{
-	i2c_del_driver(&qt602240_driver);
-}
-
-module_init(qt602240_init);
-module_exit(qt602240_exit);
-
-/* Module information */
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_DESCRIPTION("AT42QT602240/ATMXT224 Touchscreen driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
index c8c136c..4303149 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -43,7 +43,6 @@ struct tps6507x_ts {
 	struct input_dev	*input_dev;
 	struct device		*dev;
 	char			phys[32];
-	struct workqueue_struct *wq;
 	struct delayed_work	work;
 	unsigned		polling;	/* polling is active */
 	struct ts_event		tc;
@@ -220,8 +219,8 @@ done:
 	poll = 1;
 
 	if (poll) {
-		schd = queue_delayed_work(tsc->wq, &tsc->work,
-					  msecs_to_jiffies(tsc->poll_period));
+		schd = schedule_delayed_work(&tsc->work,
+					msecs_to_jiffies(tsc->poll_period));
 		if (schd)
 			tsc->polling = 1;
 		else {
@@ -303,7 +302,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
 	tsc->input_dev = input_dev;
 
 	INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler);
-	tsc->wq = create_workqueue("TPS6507x Touchscreen");
 
 	if (init_data) {
 		tsc->poll_period = init_data->poll_period;
@@ -325,8 +323,8 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
 	if (error)
 		goto err2;
 
-	schd = queue_delayed_work(tsc->wq, &tsc->work,
-				  msecs_to_jiffies(tsc->poll_period));
+	schd = schedule_delayed_work(&tsc->work,
+				     msecs_to_jiffies(tsc->poll_period));
 
 	if (schd)
 		tsc->polling = 1;
@@ -341,7 +339,6 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
 
 err2:
 	cancel_delayed_work_sync(&tsc->work);
-	destroy_workqueue(tsc->wq);
 	input_free_device(input_dev);
 err1:
 	kfree(tsc);
@@ -357,7 +354,6 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
 	struct input_dev *input_dev = tsc->input_dev;
 
 	cancel_delayed_work_sync(&tsc->work);
-	destroy_workqueue(tsc->wq);
 
 	input_unregister_device(input_dev);
 
diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c
new file mode 100644
index 0000000..8742061
--- /dev/null
+++ b/drivers/input/touchscreen/tsc2005.c
@@ -0,0 +1,756 @@
+/*
+ * TSC2005 touchscreen driver
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ *
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/tsc2005.h>
+
+/*
+ * The touchscreen interface operates as follows:
+ *
+ * 1) Pen is pressed against the touchscreen.
+ * 2) TSC2005 performs AD conversion.
+ * 3) After the conversion is done TSC2005 drives DAV line down.
+ * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
+ * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
+ *    values.
+ * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
+ *    tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
+ * 7) When the penup timer expires, there have not been touch or DAV interrupts
+ *    during the last 40ms which means the pen has been lifted.
+ *
+ * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
+ * after a configurable period (in ms) of activity. If esd_timeout is 0, the
+ * watchdog is disabled.
+ */
+
+/* control byte 1 */
+#define TSC2005_CMD			0x80
+#define TSC2005_CMD_NORMAL		0x00
+#define TSC2005_CMD_STOP		0x01
+#define TSC2005_CMD_12BIT		0x04
+
+/* control byte 0 */
+#define TSC2005_REG_READ		0x0001
+#define TSC2005_REG_PND0		0x0002
+#define TSC2005_REG_X			0x0000
+#define TSC2005_REG_Y			0x0008
+#define TSC2005_REG_Z1			0x0010
+#define TSC2005_REG_Z2			0x0018
+#define TSC2005_REG_TEMP_HIGH		0x0050
+#define TSC2005_REG_CFR0		0x0060
+#define TSC2005_REG_CFR1		0x0068
+#define TSC2005_REG_CFR2		0x0070
+
+/* configuration register 0 */
+#define TSC2005_CFR0_PRECHARGE_276US	0x0040
+#define TSC2005_CFR0_STABTIME_1MS	0x0300
+#define TSC2005_CFR0_CLOCK_1MHZ		0x1000
+#define TSC2005_CFR0_RESOLUTION12	0x2000
+#define TSC2005_CFR0_PENMODE		0x8000
+#define TSC2005_CFR0_INITVALUE		(TSC2005_CFR0_STABTIME_1MS    | \
+					 TSC2005_CFR0_CLOCK_1MHZ      | \
+					 TSC2005_CFR0_RESOLUTION12    | \
+					 TSC2005_CFR0_PRECHARGE_276US | \
+					 TSC2005_CFR0_PENMODE)
+
+/* bits common to both read and write of configuration register 0 */
+#define	TSC2005_CFR0_RW_MASK		0x3fff
+
+/* configuration register 1 */
+#define TSC2005_CFR1_BATCHDELAY_4MS	0x0003
+#define TSC2005_CFR1_INITVALUE		TSC2005_CFR1_BATCHDELAY_4MS
+
+/* configuration register 2 */
+#define TSC2005_CFR2_MAVE_Z		0x0004
+#define TSC2005_CFR2_MAVE_Y		0x0008
+#define TSC2005_CFR2_MAVE_X		0x0010
+#define TSC2005_CFR2_AVG_7		0x0800
+#define TSC2005_CFR2_MEDIUM_15		0x3000
+#define TSC2005_CFR2_INITVALUE		(TSC2005_CFR2_MAVE_X	| \
+					 TSC2005_CFR2_MAVE_Y	| \
+					 TSC2005_CFR2_MAVE_Z	| \
+					 TSC2005_CFR2_MEDIUM_15	| \
+					 TSC2005_CFR2_AVG_7)
+
+#define MAX_12BIT			0xfff
+#define TSC2005_SPI_MAX_SPEED_HZ	10000000
+#define TSC2005_PENUP_TIME_MS		40
+
+struct tsc2005_spi_rd {
+	struct spi_transfer	spi_xfer;
+	u32			spi_tx;
+	u32			spi_rx;
+};
+
+struct tsc2005 {
+	struct spi_device	*spi;
+
+	struct spi_message      spi_read_msg;
+	struct tsc2005_spi_rd	spi_x;
+	struct tsc2005_spi_rd	spi_y;
+	struct tsc2005_spi_rd	spi_z1;
+	struct tsc2005_spi_rd	spi_z2;
+
+	struct input_dev	*idev;
+	char			phys[32];
+
+	struct mutex		mutex;
+
+	/* raw copy of previous x,y,z */
+	int			in_x;
+	int			in_y;
+	int                     in_z1;
+	int			in_z2;
+
+	spinlock_t		lock;
+	struct timer_list	penup_timer;
+
+	unsigned int		esd_timeout;
+	struct delayed_work	esd_work;
+	unsigned long		last_valid_interrupt;
+
+	unsigned int		x_plate_ohm;
+
+	bool			opened;
+	bool			suspended;
+
+	bool			pen_down;
+
+	void			(*set_reset)(bool enable);
+};
+
+static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
+{
+	u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
+	struct spi_transfer xfer = {
+		.tx_buf		= &tx,
+		.len		= 1,
+		.bits_per_word	= 8,
+	};
+	struct spi_message msg;
+	int error;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	error = spi_sync(ts->spi, &msg);
+	if (error) {
+		dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n",
+			__func__, cmd, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value)
+{
+	u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value;
+	struct spi_transfer xfer = {
+		.tx_buf		= &tx,
+		.len		= 4,
+		.bits_per_word	= 24,
+	};
+	struct spi_message msg;
+	int error;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	error = spi_sync(ts->spi, &msg);
+	if (error) {
+		dev_err(&ts->spi->dev,
+			"%s: failed, register: %x, value: %x, error: %d\n",
+			__func__, reg, value, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last)
+{
+	memset(rd, 0, sizeof(*rd));
+
+	rd->spi_tx		   = (reg | TSC2005_REG_READ) << 16;
+	rd->spi_xfer.tx_buf	   = &rd->spi_tx;
+	rd->spi_xfer.rx_buf	   = &rd->spi_rx;
+	rd->spi_xfer.len	   = 4;
+	rd->spi_xfer.bits_per_word = 24;
+	rd->spi_xfer.cs_change	   = !last;
+}
+
+static int tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value)
+{
+	struct tsc2005_spi_rd spi_rd;
+	struct spi_message msg;
+	int error;
+
+	tsc2005_setup_read(&spi_rd, reg, true);
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&spi_rd.spi_xfer, &msg);
+
+	error = spi_sync(ts->spi, &msg);
+	if (error)
+		return error;
+
+	*value = spi_rd.spi_rx;
+	return 0;
+}
+
+static void tsc2005_update_pen_state(struct tsc2005 *ts,
+				     int x, int y, int pressure)
+{
+	if (pressure) {
+		input_report_abs(ts->idev, ABS_X, x);
+		input_report_abs(ts->idev, ABS_Y, y);
+		input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+		if (!ts->pen_down) {
+			input_report_key(ts->idev, BTN_TOUCH, !!pressure);
+			ts->pen_down = true;
+		}
+	} else {
+		input_report_abs(ts->idev, ABS_PRESSURE, 0);
+		if (ts->pen_down) {
+			input_report_key(ts->idev, BTN_TOUCH, 0);
+			ts->pen_down = false;
+		}
+	}
+	input_sync(ts->idev);
+	dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
+		pressure);
+}
+
+static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
+{
+	struct tsc2005 *ts = _ts;
+	unsigned long flags;
+	unsigned int pressure;
+	u32 x, y;
+	u32 z1, z2;
+	int error;
+
+	/* read the coordinates */
+	error = spi_sync(ts->spi, &ts->spi_read_msg);
+	if (unlikely(error))
+		goto out;
+
+	x = ts->spi_x.spi_rx;
+	y = ts->spi_y.spi_rx;
+	z1 = ts->spi_z1.spi_rx;
+	z2 = ts->spi_z2.spi_rx;
+
+	/* validate position */
+	if (unlikely(x > MAX_12BIT || y > MAX_12BIT))
+		goto out;
+
+	/* Skip reading if the pressure components are out of range */
+	if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2))
+		goto out;
+
+       /*
+	* Skip point if this is a pen down with the exact same values as
+	* the value before pen-up - that implies SPI fed us stale data
+	*/
+	if (!ts->pen_down &&
+	    ts->in_x == x && ts->in_y == y &&
+	    ts->in_z1 == z1 && ts->in_z2 == z2) {
+		goto out;
+	}
+
+	/*
+	 * At this point we are happy we have a valid and useful reading.
+	 * Remember it for later comparisons. We may now begin downsampling.
+	 */
+	ts->in_x = x;
+	ts->in_y = y;
+	ts->in_z1 = z1;
+	ts->in_z2 = z2;
+
+	/* Compute touch pressure resistance using equation #1 */
+	pressure = x * (z2 - z1) / z1;
+	pressure = pressure * ts->x_plate_ohm / 4096;
+	if (unlikely(pressure > MAX_12BIT))
+		goto out;
+
+	spin_lock_irqsave(&ts->lock, flags);
+
+	tsc2005_update_pen_state(ts, x, y, pressure);
+	mod_timer(&ts->penup_timer,
+		  jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
+
+	spin_unlock_irqrestore(&ts->lock, flags);
+
+	ts->last_valid_interrupt = jiffies;
+out:
+	return IRQ_HANDLED;
+}
+
+static void tsc2005_penup_timer(unsigned long data)
+{
+	struct tsc2005 *ts = (struct tsc2005 *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ts->lock, flags);
+	tsc2005_update_pen_state(ts, 0, 0, 0);
+	spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void tsc2005_start_scan(struct tsc2005 *ts)
+{
+	tsc2005_write(ts, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
+	tsc2005_write(ts, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
+	tsc2005_write(ts, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
+	tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
+}
+
+static void tsc2005_stop_scan(struct tsc2005 *ts)
+{
+	tsc2005_cmd(ts, TSC2005_CMD_STOP);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc2005_disable(struct tsc2005 *ts)
+{
+	tsc2005_stop_scan(ts);
+
+	disable_irq(ts->spi->irq);
+	del_timer_sync(&ts->penup_timer);
+
+	cancel_delayed_work_sync(&ts->esd_work);
+
+	enable_irq(ts->spi->irq);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc2005_enable(struct tsc2005 *ts)
+{
+	tsc2005_start_scan(ts);
+
+	if (ts->esd_timeout && ts->set_reset) {
+		ts->last_valid_interrupt = jiffies;
+		schedule_delayed_work(&ts->esd_work,
+				round_jiffies(jiffies +
+					msecs_to_jiffies(ts->esd_timeout)));
+	}
+
+}
+
+static ssize_t tsc2005_selftest_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+	u16 temp_high;
+	u16 temp_high_orig;
+	u16 temp_high_test;
+	bool success = true;
+	int error;
+
+	mutex_lock(&ts->mutex);
+
+	/*
+	 * Test TSC2005 communications via temp high register.
+	 */
+	__tsc2005_disable(ts);
+
+	error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
+	if (error) {
+		dev_warn(dev, "selftest failed: read error %d\n", error);
+		success = false;
+		goto out;
+	}
+
+	temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
+
+	error = tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test);
+	if (error) {
+		dev_warn(dev, "selftest failed: write error %d\n", error);
+		success = false;
+		goto out;
+	}
+
+	error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
+	if (error) {
+		dev_warn(dev, "selftest failed: read error %d after write\n",
+			 error);
+		success = false;
+		goto out;
+	}
+
+	if (temp_high != temp_high_test) {
+		dev_warn(dev, "selftest failed: %d != %d\n",
+			 temp_high, temp_high_test);
+		success = false;
+	}
+
+	/* hardware reset */
+	ts->set_reset(false);
+	usleep_range(100, 500); /* only 10us required */
+	ts->set_reset(true);
+
+	if (!success)
+		goto out;
+
+	/* test that the reset really happened */
+	error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
+	if (error) {
+		dev_warn(dev, "selftest failed: read error %d after reset\n",
+			 error);
+		success = false;
+		goto out;
+	}
+
+	if (temp_high != temp_high_orig) {
+		dev_warn(dev, "selftest failed after reset: %d != %d\n",
+			 temp_high, temp_high_orig);
+		success = false;
+	}
+
+out:
+	__tsc2005_enable(ts);
+	mutex_unlock(&ts->mutex);
+
+	return sprintf(buf, "%d\n", success);
+}
+
+static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
+
+static struct attribute *tsc2005_attrs[] = {
+	&dev_attr_selftest.attr,
+	NULL
+};
+
+static mode_t tsc2005_attr_is_visible(struct kobject *kobj,
+				      struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+	mode_t mode = attr->mode;
+
+	if (attr == &dev_attr_selftest.attr) {
+		if (!ts->set_reset)
+			mode = 0;
+	}
+
+	return mode;
+}
+
+static const struct attribute_group tsc2005_attr_group = {
+	.is_visible	= tsc2005_attr_is_visible,
+	.attrs		= tsc2005_attrs,
+};
+
+static void tsc2005_esd_work(struct work_struct *work)
+{
+	struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
+	int error;
+	u16 r;
+
+	mutex_lock(&ts->mutex);
+
+	if (time_is_after_jiffies(ts->last_valid_interrupt +
+				  msecs_to_jiffies(ts->esd_timeout)))
+		goto out;
+
+	/* We should be able to read register without disabling interrupts. */
+	error = tsc2005_read(ts, TSC2005_REG_CFR0, &r);
+	if (!error &&
+	    !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
+		goto out;
+	}
+
+	/*
+	 * If we could not read our known value from configuration register 0
+	 * then we should reset the controller as if from power-up and start
+	 * scanning again.
+	 */
+	dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
+
+	disable_irq(ts->spi->irq);
+	del_timer_sync(&ts->penup_timer);
+
+	tsc2005_update_pen_state(ts, 0, 0, 0);
+
+	ts->set_reset(false);
+	usleep_range(100, 500); /* only 10us required */
+	ts->set_reset(true);
+
+	enable_irq(ts->spi->irq);
+	tsc2005_start_scan(ts);
+
+out:
+	/* re-arm the watchdog */
+	schedule_delayed_work(&ts->esd_work,
+			      round_jiffies(jiffies +
+					msecs_to_jiffies(ts->esd_timeout)));
+	mutex_unlock(&ts->mutex);
+}
+
+static int tsc2005_open(struct input_dev *input)
+{
+	struct tsc2005 *ts = input_get_drvdata(input);
+
+	mutex_lock(&ts->mutex);
+
+	if (!ts->suspended)
+		__tsc2005_enable(ts);
+
+	ts->opened = true;
+
+	mutex_unlock(&ts->mutex);
+
+	return 0;
+}
+
+static void tsc2005_close(struct input_dev *input)
+{
+	struct tsc2005 *ts = input_get_drvdata(input);
+
+	mutex_lock(&ts->mutex);
+
+	if (!ts->suspended)
+		__tsc2005_disable(ts);
+
+	ts->opened = false;
+
+	mutex_unlock(&ts->mutex);
+}
+
+static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
+{
+	tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false);
+	tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false);
+	tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, false);
+	tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, true);
+
+	spi_message_init(&ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_y.spi_xfer, &ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_z1.spi_xfer, &ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
+}
+
+static int __devinit tsc2005_probe(struct spi_device *spi)
+{
+	const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
+	struct tsc2005 *ts;
+	struct input_dev *input_dev;
+	unsigned int max_x, max_y, max_p;
+	unsigned int fudge_x, fudge_y, fudge_p;
+	int error;
+
+	if (!pdata) {
+		dev_dbg(&spi->dev, "no platform data\n");
+		return -ENODEV;
+	}
+
+	fudge_x	= pdata->ts_x_fudge	   ? : 4;
+	fudge_y	= pdata->ts_y_fudge	   ? : 8;
+	fudge_p	= pdata->ts_pressure_fudge ? : 2;
+	max_x	= pdata->ts_x_max	   ? : MAX_12BIT;
+	max_y	= pdata->ts_y_max	   ? : MAX_12BIT;
+	max_p	= pdata->ts_pressure_max   ? : MAX_12BIT;
+
+	if (spi->irq <= 0) {
+		dev_dbg(&spi->dev, "no irq\n");
+		return -ENODEV;
+	}
+
+	spi->mode = SPI_MODE_0;
+	spi->bits_per_word = 8;
+	if (!spi->max_speed_hz)
+		spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ;
+
+	error = spi_setup(spi);
+	if (error)
+		return error;
+
+	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	ts->spi = spi;
+	ts->idev = input_dev;
+
+	ts->x_plate_ohm	= pdata->ts_x_plate_ohm	? : 280;
+	ts->esd_timeout	= pdata->esd_timeout_ms;
+	ts->set_reset	= pdata->set_reset;
+
+	mutex_init(&ts->mutex);
+
+	spin_lock_init(&ts->lock);
+	setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
+
+	INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
+
+	tsc2005_setup_spi_xfer(ts);
+
+	snprintf(ts->phys, sizeof(ts->phys),
+		 "%s/input-ts", dev_name(&spi->dev));
+
+	input_dev->name = "TSC2005 touchscreen";
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = BUS_SPI;
+	input_dev->dev.parent = &spi->dev;
+	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
+
+	input_dev->open = tsc2005_open;
+	input_dev->close = tsc2005_close;
+
+	input_set_drvdata(input_dev, ts);
+
+	/* Ensure the touchscreen is off */
+	tsc2005_stop_scan(ts);
+
+	error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread,
+				     IRQF_TRIGGER_RISING, "tsc2005", ts);
+	if (error) {
+		dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
+		goto err_free_mem;
+	}
+
+	spi_set_drvdata(spi, ts);
+	error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
+	if (error) {
+		dev_err(&spi->dev,
+			"Failed to create sysfs attributes, err: %d\n", error);
+		goto err_clear_drvdata;
+	}
+
+	error = input_register_device(ts->idev);
+	if (error) {
+		dev_err(&spi->dev,
+			"Failed to register input device, err: %d\n", error);
+		goto err_remove_sysfs;
+	}
+
+	set_irq_wake(spi->irq, 1);
+	return 0;
+
+err_remove_sysfs:
+	sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
+err_clear_drvdata:
+	spi_set_drvdata(spi, NULL);
+	free_irq(spi->irq, ts);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(ts);
+	return error;
+}
+
+static int __devexit tsc2005_remove(struct spi_device *spi)
+{
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+
+	sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
+
+	free_irq(ts->spi->irq, ts);
+	input_unregister_device(ts->idev);
+	kfree(ts);
+
+	spi_set_drvdata(spi, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tsc2005_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+
+	mutex_lock(&ts->mutex);
+
+	if (!ts->suspended && ts->opened)
+		__tsc2005_disable(ts);
+
+	ts->suspended = true;
+
+	mutex_unlock(&ts->mutex);
+
+	return 0;
+}
+
+static int tsc2005_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+
+	mutex_lock(&ts->mutex);
+
+	if (ts->suspended && ts->opened)
+		__tsc2005_enable(ts);
+
+	ts->suspended = false;
+
+	mutex_unlock(&ts->mutex);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
+
+static struct spi_driver tsc2005_driver = {
+	.driver	= {
+		.name	= "tsc2005",
+		.owner	= THIS_MODULE,
+		.pm	= &tsc2005_pm_ops,
+	},
+	.probe	= tsc2005_probe,
+	.remove	= __devexit_p(tsc2005_remove),
+};
+
+static int __init tsc2005_init(void)
+{
+	return spi_register_driver(&tsc2005_driver);
+}
+module_init(tsc2005_init);
+
+static void __exit tsc2005_exit(void)
+{
+	spi_unregister_driver(&tsc2005_driver);
+}
+module_exit(tsc2005_exit);
+
+MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c
new file mode 100644
index 0000000..6ae054f
--- /dev/null
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -0,0 +1,368 @@
+/*
+ * Touchscreen driver for WM831x PMICs
+ *
+ * Copyright 2011 Wolfson Microelectronics plc.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License 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/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/*
+ * R16424 (0x4028) - Touch Control 1
+ */
+#define WM831X_TCH_ENA                          0x8000  /* TCH_ENA */
+#define WM831X_TCH_CVT_ENA                      0x4000  /* TCH_CVT_ENA */
+#define WM831X_TCH_SLPENA                       0x1000  /* TCH_SLPENA */
+#define WM831X_TCH_Z_ENA                        0x0400  /* TCH_Z_ENA */
+#define WM831X_TCH_Y_ENA                        0x0200  /* TCH_Y_ENA */
+#define WM831X_TCH_X_ENA                        0x0100  /* TCH_X_ENA */
+#define WM831X_TCH_DELAY_MASK                   0x00E0  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_DELAY_SHIFT                       5  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_DELAY_WIDTH                       3  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_RATE_MASK                    0x001F  /* TCH_RATE - [4:0] */
+#define WM831X_TCH_RATE_SHIFT                        0  /* TCH_RATE - [4:0] */
+#define WM831X_TCH_RATE_WIDTH                        5  /* TCH_RATE - [4:0] */
+
+/*
+ * R16425 (0x4029) - Touch Control 2
+ */
+#define WM831X_TCH_PD_WK                        0x2000  /* TCH_PD_WK */
+#define WM831X_TCH_5WIRE                        0x1000  /* TCH_5WIRE */
+#define WM831X_TCH_PDONLY                       0x0800  /* TCH_PDONLY */
+#define WM831X_TCH_ISEL                         0x0100  /* TCH_ISEL */
+#define WM831X_TCH_RPU_MASK                     0x000F  /* TCH_RPU - [3:0] */
+#define WM831X_TCH_RPU_SHIFT                         0  /* TCH_RPU - [3:0] */
+#define WM831X_TCH_RPU_WIDTH                         4  /* TCH_RPU - [3:0] */
+
+/*
+ * R16426-8 (0x402A-C) - Touch Data X/Y/X
+ */
+#define WM831X_TCH_PD                           0x8000  /* TCH_PD1 */
+#define WM831X_TCH_DATA_MASK                    0x0FFF  /* TCH_DATA - [11:0] */
+#define WM831X_TCH_DATA_SHIFT                        0  /* TCH_DATA - [11:0] */
+#define WM831X_TCH_DATA_WIDTH                       12  /* TCH_DATA - [11:0] */
+
+struct wm831x_ts {
+	struct input_dev *input_dev;
+	struct wm831x *wm831x;
+	unsigned int data_irq;
+	unsigned int pd_irq;
+	bool pressure;
+	bool pen_down;
+};
+
+static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
+{
+	struct wm831x_ts *wm831x_ts = irq_data;
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+	static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE };
+	u16 data[3];
+	int count;
+	int i, ret;
+
+	if (wm831x_ts->pressure)
+		count = 3;
+	else
+		count = 2;
+
+	wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+			WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
+
+	ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count,
+			       data);
+	if (ret != 0) {
+		dev_err(wm831x->dev, "Failed to read touch data: %d\n",
+			ret);
+		return IRQ_NONE;
+	}
+
+	/*
+	 * We get a pen down reading on every reading, report pen up if any
+	 * individual reading does so.
+	 */
+	wm831x_ts->pen_down = true;
+	for (i = 0; i < count; i++) {
+		if (!(data[i] & WM831X_TCH_PD)) {
+			wm831x_ts->pen_down = false;
+			continue;
+		}
+		input_report_abs(wm831x_ts->input_dev, data_types[i],
+				 data[i] & WM831X_TCH_DATA_MASK);
+	}
+
+	if (!wm831x_ts->pen_down) {
+		disable_irq_nosync(wm831x_ts->data_irq);
+
+		/* Don't need data any more */
+		wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+				WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+				WM831X_TCH_Z_ENA, 0);
+
+		/* Flush any final samples that arrived while reading */
+		wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+				WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
+
+		wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data);
+
+		if (wm831x_ts->pressure)
+			input_report_abs(wm831x_ts->input_dev,
+					 ABS_PRESSURE, 0);
+
+		input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
+	}
+
+	input_sync(wm831x_ts->input_dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
+{
+	struct wm831x_ts *wm831x_ts = irq_data;
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+	int ena = 0;
+
+	/* Start collecting data */
+	if (wm831x_ts->pressure)
+		ena |= WM831X_TCH_Z_ENA;
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
+
+	input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
+	input_sync(wm831x_ts->input_dev);
+
+	wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+			WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
+
+	wm831x_ts->pen_down = true;
+	enable_irq(wm831x_ts->data_irq);
+
+	return IRQ_HANDLED;
+}
+
+static int wm831x_ts_input_open(struct input_dev *idev)
+{
+	struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+			WM831X_TCH_Z_ENA, WM831X_TCH_ENA);
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA);
+
+	return 0;
+}
+
+static void wm831x_ts_input_close(struct input_dev *idev)
+{
+	struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+			WM831X_TCH_Z_ENA, 0);
+
+	if (wm831x_ts->pen_down)
+		disable_irq(wm831x_ts->data_irq);
+}
+
+static __devinit int wm831x_ts_probe(struct platform_device *pdev)
+{
+	struct wm831x_ts *wm831x_ts;
+	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+	struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
+	struct wm831x_touch_pdata *pdata = NULL;
+	struct input_dev *input_dev;
+	int error;
+
+	if (core_pdata)
+		pdata = core_pdata->touch;
+
+	wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!wm831x_ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_alloc;
+	}
+
+	wm831x_ts->wm831x = wm831x;
+	wm831x_ts->input_dev = input_dev;
+
+	/*
+	 * If we have a direct IRQ use it, otherwise use the interrupt
+	 * from the WM831x IRQ controller.
+	 */
+	if (pdata && pdata->data_irq)
+		wm831x_ts->data_irq = pdata->data_irq;
+	else
+		wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA");
+
+	if (pdata && pdata->pd_irq)
+		wm831x_ts->pd_irq = pdata->pd_irq;
+	else
+		wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD");
+
+	if (pdata)
+		wm831x_ts->pressure = pdata->pressure;
+	else
+		wm831x_ts->pressure = true;
+
+	/* Five wire touchscreens can't report pressure */
+	if (pdata && pdata->fivewire) {
+		wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+				WM831X_TCH_5WIRE, WM831X_TCH_5WIRE);
+
+		/* Pressure measurements are not possible for five wire mode */
+		WARN_ON(pdata->pressure && pdata->fivewire);
+		wm831x_ts->pressure = false;
+	} else {
+		wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+				WM831X_TCH_5WIRE, 0);
+	}
+
+	if (pdata) {
+		switch (pdata->isel) {
+		default:
+			dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n",
+				pdata->isel);
+			/* Fall through */
+		case 200:
+		case 0:
+			wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+					WM831X_TCH_ISEL, 0);
+			break;
+		case 400:
+			wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+					WM831X_TCH_ISEL, WM831X_TCH_ISEL);
+			break;
+		}
+	}
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+			WM831X_TCH_PDONLY, 0);
+
+	/* Default to 96 samples/sec */
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_RATE_MASK, 6);
+
+	error = request_threaded_irq(wm831x_ts->data_irq,
+				     NULL, wm831x_ts_data_irq,
+				     IRQF_ONESHOT,
+				     "Touchscreen data", wm831x_ts);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
+			wm831x_ts->data_irq, error);
+		goto err_alloc;
+	}
+	disable_irq(wm831x_ts->data_irq);
+
+	error = request_threaded_irq(wm831x_ts->pd_irq,
+				     NULL, wm831x_ts_pen_down_irq,
+				     IRQF_ONESHOT,
+				     "Touchscreen pen down", wm831x_ts);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
+			wm831x_ts->pd_irq, error);
+		goto err_data_irq;
+	}
+
+	/* set up touch configuration */
+	input_dev->name = "WM831x touchscreen";
+	input_dev->phys = "wm831x";
+	input_dev->open = wm831x_ts_input_open;
+	input_dev->close = wm831x_ts_input_close;
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+
+	input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0);
+	if (wm831x_ts->pressure)
+		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0);
+
+	input_set_drvdata(input_dev, wm831x_ts);
+	input_dev->dev.parent = &pdev->dev;
+
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_pd_irq;
+
+	platform_set_drvdata(pdev, wm831x_ts);
+	return 0;
+
+err_pd_irq:
+	free_irq(wm831x_ts->pd_irq, wm831x_ts);
+err_data_irq:
+	free_irq(wm831x_ts->data_irq, wm831x_ts);
+err_alloc:
+	input_free_device(input_dev);
+	kfree(wm831x_ts);
+
+	return error;
+}
+
+static __devexit int wm831x_ts_remove(struct platform_device *pdev)
+{
+	struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
+
+	free_irq(wm831x_ts->pd_irq, wm831x_ts);
+	free_irq(wm831x_ts->data_irq, wm831x_ts);
+	input_unregister_device(wm831x_ts->input_dev);
+	kfree(wm831x_ts);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver wm831x_ts_driver = {
+	.driver = {
+		.name = "wm831x-touch",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm831x_ts_probe,
+	.remove = __devexit_p(wm831x_ts_remove),
+};
+
+static int __init wm831x_ts_init(void)
+{
+	return platform_driver_register(&wm831x_ts_driver);
+}
+module_init(wm831x_ts_init);
+
+static void __exit wm831x_ts_exit(void)
+{
+	platform_driver_unregister(&wm831x_ts_driver);
+}
+module_exit(wm831x_ts_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM831x PMIC touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-touch");
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c
deleted file mode 100644
index 7f85a86..0000000
--- a/drivers/input/xen-kbdfront.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Xen para-virtual input device
- *
- * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
- * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
- *
- *  Based on linux/drivers/input/mouse/sermouse.c
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-/*
- * TODO:
- *
- * Switch to grant tables together with xen-fbfront.c.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-
-#include <asm/xen/hypervisor.h>
-
-#include <xen/xen.h>
-#include <xen/events.h>
-#include <xen/page.h>
-#include <xen/interface/io/fbif.h>
-#include <xen/interface/io/kbdif.h>
-#include <xen/xenbus.h>
-
-struct xenkbd_info {
-	struct input_dev *kbd;
-	struct input_dev *ptr;
-	struct xenkbd_page *page;
-	int irq;
-	struct xenbus_device *xbdev;
-	char phys[32];
-};
-
-static int xenkbd_remove(struct xenbus_device *);
-static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
-static void xenkbd_disconnect_backend(struct xenkbd_info *);
-
-/*
- * Note: if you need to send out events, see xenfb_do_update() for how
- * to do that.
- */
-
-static irqreturn_t input_handler(int rq, void *dev_id)
-{
-	struct xenkbd_info *info = dev_id;
-	struct xenkbd_page *page = info->page;
-	__u32 cons, prod;
-
-	prod = page->in_prod;
-	if (prod == page->in_cons)
-		return IRQ_HANDLED;
-	rmb();			/* ensure we see ring contents up to prod */
-	for (cons = page->in_cons; cons != prod; cons++) {
-		union xenkbd_in_event *event;
-		struct input_dev *dev;
-		event = &XENKBD_IN_RING_REF(page, cons);
-
-		dev = info->ptr;
-		switch (event->type) {
-		case XENKBD_TYPE_MOTION:
-			input_report_rel(dev, REL_X, event->motion.rel_x);
-			input_report_rel(dev, REL_Y, event->motion.rel_y);
-			if (event->motion.rel_z)
-				input_report_rel(dev, REL_WHEEL,
-						 -event->motion.rel_z);
-			break;
-		case XENKBD_TYPE_KEY:
-			dev = NULL;
-			if (test_bit(event->key.keycode, info->kbd->keybit))
-				dev = info->kbd;
-			if (test_bit(event->key.keycode, info->ptr->keybit))
-				dev = info->ptr;
-			if (dev)
-				input_report_key(dev, event->key.keycode,
-						 event->key.pressed);
-			else
-				pr_warning("unhandled keycode 0x%x\n",
-					   event->key.keycode);
-			break;
-		case XENKBD_TYPE_POS:
-			input_report_abs(dev, ABS_X, event->pos.abs_x);
-			input_report_abs(dev, ABS_Y, event->pos.abs_y);
-			if (event->pos.rel_z)
-				input_report_rel(dev, REL_WHEEL,
-						 -event->pos.rel_z);
-			break;
-		}
-		if (dev)
-			input_sync(dev);
-	}
-	mb();			/* ensure we got ring contents */
-	page->in_cons = cons;
-	notify_remote_via_irq(info->irq);
-
-	return IRQ_HANDLED;
-}
-
-static int __devinit xenkbd_probe(struct xenbus_device *dev,
-				  const struct xenbus_device_id *id)
-{
-	int ret, i;
-	struct xenkbd_info *info;
-	struct input_dev *kbd, *ptr;
-
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
-		return -ENOMEM;
-	}
-	dev_set_drvdata(&dev->dev, info);
-	info->xbdev = dev;
-	info->irq = -1;
-	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
-
-	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-	if (!info->page)
-		goto error_nomem;
-
-	/* keyboard */
-	kbd = input_allocate_device();
-	if (!kbd)
-		goto error_nomem;
-	kbd->name = "Xen Virtual Keyboard";
-	kbd->phys = info->phys;
-	kbd->id.bustype = BUS_PCI;
-	kbd->id.vendor = 0x5853;
-	kbd->id.product = 0xffff;
-	kbd->evbit[0] = BIT(EV_KEY);
-	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
-		set_bit(i, kbd->keybit);
-	for (i = KEY_OK; i < KEY_MAX; i++)
-		set_bit(i, kbd->keybit);
-
-	ret = input_register_device(kbd);
-	if (ret) {
-		input_free_device(kbd);
-		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
-		goto error;
-	}
-	info->kbd = kbd;
-
-	/* pointing device */
-	ptr = input_allocate_device();
-	if (!ptr)
-		goto error_nomem;
-	ptr->name = "Xen Virtual Pointer";
-	ptr->phys = info->phys;
-	ptr->id.bustype = BUS_PCI;
-	ptr->id.vendor = 0x5853;
-	ptr->id.product = 0xfffe;
-	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
-	for (i = BTN_LEFT; i <= BTN_TASK; i++)
-		set_bit(i, ptr->keybit);
-	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
-	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
-	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
-
-	ret = input_register_device(ptr);
-	if (ret) {
-		input_free_device(ptr);
-		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
-		goto error;
-	}
-	info->ptr = ptr;
-
-	ret = xenkbd_connect_backend(dev, info);
-	if (ret < 0)
-		goto error;
-
-	return 0;
-
- error_nomem:
-	ret = -ENOMEM;
-	xenbus_dev_fatal(dev, ret, "allocating device memory");
- error:
-	xenkbd_remove(dev);
-	return ret;
-}
-
-static int xenkbd_resume(struct xenbus_device *dev)
-{
-	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-
-	xenkbd_disconnect_backend(info);
-	memset(info->page, 0, PAGE_SIZE);
-	return xenkbd_connect_backend(dev, info);
-}
-
-static int xenkbd_remove(struct xenbus_device *dev)
-{
-	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-
-	xenkbd_disconnect_backend(info);
-	if (info->kbd)
-		input_unregister_device(info->kbd);
-	if (info->ptr)
-		input_unregister_device(info->ptr);
-	free_page((unsigned long)info->page);
-	kfree(info);
-	return 0;
-}
-
-static int xenkbd_connect_backend(struct xenbus_device *dev,
-				  struct xenkbd_info *info)
-{
-	int ret, evtchn;
-	struct xenbus_transaction xbt;
-
-	ret = xenbus_alloc_evtchn(dev, &evtchn);
-	if (ret)
-		return ret;
-	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
-					0, dev->devicetype, info);
-	if (ret < 0) {
-		xenbus_free_evtchn(dev, evtchn);
-		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
-		return ret;
-	}
-	info->irq = ret;
-
- again:
-	ret = xenbus_transaction_start(&xbt);
-	if (ret) {
-		xenbus_dev_fatal(dev, ret, "starting transaction");
-		return ret;
-	}
-	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
-			    virt_to_mfn(info->page));
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
-			    evtchn);
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_transaction_end(xbt, 0);
-	if (ret) {
-		if (ret == -EAGAIN)
-			goto again;
-		xenbus_dev_fatal(dev, ret, "completing transaction");
-		return ret;
-	}
-
-	xenbus_switch_state(dev, XenbusStateInitialised);
-	return 0;
-
- error_xenbus:
-	xenbus_transaction_end(xbt, 1);
-	xenbus_dev_fatal(dev, ret, "writing xenstore");
-	return ret;
-}
-
-static void xenkbd_disconnect_backend(struct xenkbd_info *info)
-{
-	if (info->irq >= 0)
-		unbind_from_irqhandler(info->irq, info);
-	info->irq = -1;
-}
-
-static void xenkbd_backend_changed(struct xenbus_device *dev,
-				   enum xenbus_state backend_state)
-{
-	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-	int ret, val;
-
-	switch (backend_state) {
-	case XenbusStateInitialising:
-	case XenbusStateInitialised:
-	case XenbusStateReconfiguring:
-	case XenbusStateReconfigured:
-	case XenbusStateUnknown:
-	case XenbusStateClosed:
-		break;
-
-	case XenbusStateInitWait:
-InitWait:
-		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				   "feature-abs-pointer", "%d", &val);
-		if (ret < 0)
-			val = 0;
-		if (val) {
-			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
-					    "request-abs-pointer", "1");
-			if (ret)
-				pr_warning("can't request abs-pointer\n");
-		}
-		xenbus_switch_state(dev, XenbusStateConnected);
-		break;
-
-	case XenbusStateConnected:
-		/*
-		 * Work around xenbus race condition: If backend goes
-		 * through InitWait to Connected fast enough, we can
-		 * get Connected twice here.
-		 */
-		if (dev->state != XenbusStateConnected)
-			goto InitWait; /* no InitWait seen yet, fudge it */
-
-		/* Set input abs params to match backend screen res */
-		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				 "width", "%d", &val) > 0)
-			input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
-
-		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				 "height", "%d", &val) > 0)
-			input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
-
-		break;
-
-	case XenbusStateClosing:
-		xenbus_frontend_closed(dev);
-		break;
-	}
-}
-
-static const struct xenbus_device_id xenkbd_ids[] = {
-	{ "vkbd" },
-	{ "" }
-};
-
-static struct xenbus_driver xenkbd_driver = {
-	.name = "vkbd",
-	.owner = THIS_MODULE,
-	.ids = xenkbd_ids,
-	.probe = xenkbd_probe,
-	.remove = xenkbd_remove,
-	.resume = xenkbd_resume,
-	.otherend_changed = xenkbd_backend_changed,
-};
-
-static int __init xenkbd_init(void)
-{
-	if (!xen_pv_domain())
-		return -ENODEV;
-
-	/* Nothing to do if running in dom0. */
-	if (xen_initial_domain())
-		return -ENODEV;
-
-	return xenbus_register_frontend(&xenkbd_driver);
-}
-
-static void __exit xenkbd_cleanup(void)
-{
-	xenbus_unregister_driver(&xenkbd_driver);
-}
-
-module_init(xenkbd_init);
-module_exit(xenkbd_cleanup);
-
-MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("xen:vkbd");
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index f80a7c4..0d70883 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1219,16 +1219,10 @@ static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
 	return mp->outbytes;
 }
 
-static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
+static int capinc_tty_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
-	int error = 0;
-	switch (cmd) {
-	default:
-		error = n_tty_ioctl_helper(tty, file, cmd, arg);
-		break;
-	}
-	return error;
+	return -ENOIOCTLCMD;
 }
 
 static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index bb710d16..59de638 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -115,15 +115,15 @@ static int if_config(struct cardstate *cs, int *arg)
 
 static int  if_open(struct tty_struct *tty, struct file *filp);
 static void if_close(struct tty_struct *tty, struct file *filp);
-static int  if_ioctl(struct tty_struct *tty, struct file *file,
+static int  if_ioctl(struct tty_struct *tty,
 		     unsigned int cmd, unsigned long arg);
 static int  if_write_room(struct tty_struct *tty);
 static int  if_chars_in_buffer(struct tty_struct *tty);
 static void if_throttle(struct tty_struct *tty);
 static void if_unthrottle(struct tty_struct *tty);
 static void if_set_termios(struct tty_struct *tty, struct ktermios *old);
-static int  if_tiocmget(struct tty_struct *tty, struct file *file);
-static int  if_tiocmset(struct tty_struct *tty, struct file *file,
+static int  if_tiocmget(struct tty_struct *tty);
+static int  if_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
 static int  if_write(struct tty_struct *tty,
 		     const unsigned char *buf, int count);
@@ -205,7 +205,7 @@ static void if_close(struct tty_struct *tty, struct file *filp)
 	module_put(cs->driver->owner);
 }
 
-static int if_ioctl(struct tty_struct *tty, struct file *file,
+static int if_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct cardstate *cs;
@@ -280,7 +280,7 @@ static int if_ioctl(struct tty_struct *tty, struct file *file,
 	return retval;
 }
 
-static int if_tiocmget(struct tty_struct *tty, struct file *file)
+static int if_tiocmget(struct tty_struct *tty)
 {
 	struct cardstate *cs;
 	int retval;
@@ -303,7 +303,7 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file)
 	return retval;
 }
 
-static int if_tiocmset(struct tty_struct *tty, struct file *file,
+static int if_tiocmset(struct tty_struct *tty,
 		       unsigned int set, unsigned int clear)
 {
 	struct cardstate *cs;
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 0ef09d0..86a5c4f 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -440,7 +440,7 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
 	if (!set && !clear)
 		return 0;
 	gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
-	return tty->ops->tiocmset(tty, NULL, set, clear);
+	return tty->ops->tiocmset(tty, set, clear);
 }
 
 static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index ab638b08..646368f 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -4,7 +4,7 @@
 
 # Define maximum number of cards
 
-EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+ccflags-y      := -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
 
 obj-$(CONFIG_ISDN_DRV_HISAX)		+= hisax.o
 obj-$(CONFIG_HISAX_SEDLBAUER_CS)	+= sedlbauer_cs.o
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index c463162..3d88f15 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1345,7 +1345,7 @@ isdn_tty_get_lsr_info(modem_info * info, uint __user * value)
 
 
 static int
-isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
+isdn_tty_tiocmget(struct tty_struct *tty)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
 	u_char control, status;
@@ -1372,7 +1372,7 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 static int
-isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
+isdn_tty_tiocmset(struct tty_struct *tty,
 		unsigned int set, unsigned int clear)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
@@ -1413,8 +1413,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
 }
 
 static int
-isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
-	       uint cmd, ulong arg)
+isdn_tty_ioctl(struct tty_struct *tty, uint cmd, ulong arg)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
 	int retval;
diff --git a/drivers/isdn/mISDN/hwchannel.c b/drivers/isdn/mISDN/hwchannel.c
index 199f374..f6e108d 100644
--- a/drivers/isdn/mISDN/hwchannel.c
+++ b/drivers/isdn/mISDN/hwchannel.c
@@ -206,7 +206,7 @@ recv_Bchannel(struct bchannel *bch, unsigned int id)
 	hh->id = id;
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
-			"fushing!\n", bch);
+			"flushing!\n", bch);
 		skb_queue_purge(&bch->rqueue);
 		bch->rcount = 0;
 		return;
@@ -231,7 +231,7 @@ recv_Bchannel_skb(struct bchannel *bch, struct sk_buff *skb)
 {
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
-			"fushing!\n", bch);
+			"flushing!\n", bch);
 		skb_queue_purge(&bch->rqueue);
 		bch->rcount = 0;
 	}
@@ -279,7 +279,7 @@ confirm_Bsend(struct bchannel *bch)
 
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
-			"fushing!\n", bch);
+			"flushing!\n", bch);
 		skb_queue_purge(&bch->rqueue);
 		bch->rcount = 0;
 	}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 6f190f4..9bec869 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -34,6 +34,16 @@ config LEDS_ATMEL_PWM
 	  This option enables support for LEDs driven using outputs
 	  of the dedicated PWM controller found on newer Atmel SOCs.
 
+config LEDS_LM3530
+	tristate "LCD Backlight driver for LM3530"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for the LCD backlight using
+	  LM3530 ambient light sensor chip. This ALS chip can be
+	  controlled manually or using PWM input or using ambient
+	  light automatically.
+
 config LEDS_LOCOMO
 	tristate "LED Support for Locomo device"
 	depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index aae6989..39c80fc 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_88PM860X)		+= leds-88pm860x.o
 obj-$(CONFIG_LEDS_ATMEL_PWM)		+= leds-atmel-pwm.o
 obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
+obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
 obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
 obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 19dc4b6..3ebe382 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -19,7 +19,7 @@
 #include <linux/leds.h>
 #include <linux/leds-bd2802.h>
 #include <linux/slab.h>
-
+#include <linux/pm.h>
 
 #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0))
 
@@ -319,20 +319,6 @@ static void bd2802_turn_off(struct bd2802_led *led, enum led_ids id,
 	bd2802_update_state(led, id, color, BD2802_OFF);
 }
 
-static void bd2802_restore_state(struct bd2802_led *led)
-{
-	int i;
-
-	for (i = 0; i < LED_NUM; i++) {
-		if (led->led[i].r)
-			bd2802_turn_on(led, i, RED, led->led[i].r);
-		if (led->led[i].g)
-			bd2802_turn_on(led, i, GREEN, led->led[i].g);
-		if (led->led[i].b)
-			bd2802_turn_on(led, i, BLUE, led->led[i].b);
-	}
-}
-
 #define BD2802_SET_REGISTER(reg_addr, reg_name)				\
 static ssize_t bd2802_store_reg##reg_addr(struct device *dev,		\
 	struct device_attribute *attr, const char *buf, size_t count)	\
@@ -761,8 +747,25 @@ static int __exit bd2802_remove(struct i2c_client *client)
 	return 0;
 }
 
-static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg)
+#ifdef CONFIG_PM
+
+static void bd2802_restore_state(struct bd2802_led *led)
 {
+	int i;
+
+	for (i = 0; i < LED_NUM; i++) {
+		if (led->led[i].r)
+			bd2802_turn_on(led, i, RED, led->led[i].r);
+		if (led->led[i].g)
+			bd2802_turn_on(led, i, GREEN, led->led[i].g);
+		if (led->led[i].b)
+			bd2802_turn_on(led, i, BLUE, led->led[i].b);
+	}
+}
+
+static int bd2802_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
 	struct bd2802_led *led = i2c_get_clientdata(client);
 
 	gpio_set_value(led->pdata->reset_gpio, 0);
@@ -770,8 +773,9 @@ static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg)
 	return 0;
 }
 
-static int bd2802_resume(struct i2c_client *client)
+static int bd2802_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct bd2802_led *led = i2c_get_clientdata(client);
 
 	if (!bd2802_is_all_off(led) || led->adf_on) {
@@ -782,6 +786,12 @@ static int bd2802_resume(struct i2c_client *client)
 	return 0;
 }
 
+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 },
 	{ }
@@ -791,11 +801,10 @@ MODULE_DEVICE_TABLE(i2c, bd2802_id);
 static struct i2c_driver bd2802_i2c_driver = {
 	.driver	= {
 		.name	= "BD2802",
+		.pm	= BD2802_PM,
 	},
 	.probe		= bd2802_probe,
 	.remove		= __exit_p(bd2802_remove),
-	.suspend	= bd2802_suspend,
-	.resume		= bd2802_resume,
 	.id_table	= bd2802_id,
 };
 
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 4d9fa38..b0480c8 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -14,6 +14,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 
@@ -151,96 +153,34 @@ static void delete_gpio_led(struct gpio_led_data *led)
 	gpio_free(led->gpio);
 }
 
-#ifdef CONFIG_LEDS_GPIO_PLATFORM
-static int __devinit gpio_led_probe(struct platform_device *pdev)
-{
-	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
-	struct gpio_led_data *leds_data;
-	int i, ret = 0;
-
-	if (!pdata)
-		return -EBUSY;
-
-	leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
-				GFP_KERNEL);
-	if (!leds_data)
-		return -ENOMEM;
-
-	for (i = 0; i < pdata->num_leds; i++) {
-		ret = create_gpio_led(&pdata->leds[i], &leds_data[i],
-				      &pdev->dev, pdata->gpio_blink_set);
-		if (ret < 0)
-			goto err;
-	}
-
-	platform_set_drvdata(pdev, leds_data);
-
-	return 0;
-
-err:
-	for (i = i - 1; i >= 0; i--)
-		delete_gpio_led(&leds_data[i]);
-
-	kfree(leds_data);
-
-	return ret;
-}
+struct gpio_leds_priv {
+	int num_leds;
+	struct gpio_led_data leds[];
+};
 
-static int __devexit gpio_led_remove(struct platform_device *pdev)
+static inline int sizeof_gpio_leds_priv(int num_leds)
 {
-	int i;
-	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
-	struct gpio_led_data *leds_data;
-
-	leds_data = platform_get_drvdata(pdev);
-
-	for (i = 0; i < pdata->num_leds; i++)
-		delete_gpio_led(&leds_data[i]);
-
-	kfree(leds_data);
-
-	return 0;
+	return sizeof(struct gpio_leds_priv) +
+		(sizeof(struct gpio_led_data) * num_leds);
 }
 
-static struct platform_driver gpio_led_driver = {
-	.probe		= gpio_led_probe,
-	.remove		= __devexit_p(gpio_led_remove),
-	.driver		= {
-		.name	= "leds-gpio",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS("platform:leds-gpio");
-#endif /* CONFIG_LEDS_GPIO_PLATFORM */
-
 /* Code to create from OpenFirmware platform devices */
 #ifdef CONFIG_LEDS_GPIO_OF
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-
-struct gpio_led_of_platform_data {
-	int num_leds;
-	struct gpio_led_data led_data[];
-};
-
-static int __devinit of_gpio_leds_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
 {
-	struct device_node *np = ofdev->dev.of_node, *child;
-	struct gpio_led_of_platform_data *pdata;
+	struct device_node *np = pdev->dev.of_node, *child;
+	struct gpio_leds_priv *priv;
 	int count = 0, ret;
 
-	/* count LEDs defined by this device, so we know how much to allocate */
+	/* count LEDs in this device, so we know how much to allocate */
 	for_each_child_of_node(np, child)
 		count++;
 	if (!count)
-		return 0; /* or ENODEV? */
+		return NULL;
 
-	pdata = kzalloc(sizeof(*pdata) + sizeof(struct gpio_led_data) * count,
-			GFP_KERNEL);
-	if (!pdata)
-		return -ENOMEM;
+	priv = kzalloc(sizeof_gpio_leds_priv(count), GFP_KERNEL);
+	if (!priv)
+		return NULL;
 
 	for_each_child_of_node(np, child) {
 		struct gpio_led led = {};
@@ -256,92 +196,112 @@ static int __devinit of_gpio_leds_probe(struct platform_device *ofdev,
 		if (state) {
 			if (!strcmp(state, "keep"))
 				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
-			else if(!strcmp(state, "on"))
+			else if (!strcmp(state, "on"))
 				led.default_state = LEDS_GPIO_DEFSTATE_ON;
 			else
 				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
 		}
 
-		ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++],
-				      &ofdev->dev, NULL);
+		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
+				      &pdev->dev, NULL);
 		if (ret < 0) {
 			of_node_put(child);
 			goto err;
 		}
 	}
 
-	dev_set_drvdata(&ofdev->dev, pdata);
-
-	return 0;
+	return priv;
 
 err:
-	for (count = pdata->num_leds - 2; count >= 0; count--)
-		delete_gpio_led(&pdata->led_data[count]);
+	for (count = priv->num_leds - 2; count >= 0; count--)
+		delete_gpio_led(&priv->leds[count]);
+	kfree(priv);
+	return NULL;
+}
 
-	kfree(pdata);
+static const struct of_device_id of_gpio_leds_match[] = {
+	{ .compatible = "gpio-leds", },
+	{},
+};
+#else
+static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
+{
+	return NULL;
+}
+#define of_gpio_leds_match NULL
+#endif
 
-	return ret;
+
+static int __devinit gpio_led_probe(struct platform_device *pdev)
+{
+	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_leds_priv *priv;
+	int i, ret = 0;
+
+	if (pdata && pdata->num_leds) {
+		priv = kzalloc(sizeof_gpio_leds_priv(pdata->num_leds),
+				GFP_KERNEL);
+		if (!priv)
+			return -ENOMEM;
+
+		priv->num_leds = pdata->num_leds;
+		for (i = 0; i < priv->num_leds; i++) {
+			ret = create_gpio_led(&pdata->leds[i],
+					      &priv->leds[i],
+					      &pdev->dev, pdata->gpio_blink_set);
+			if (ret < 0) {
+				/* On failure: unwind the led creations */
+				for (i = i - 1; i >= 0; i--)
+					delete_gpio_led(&priv->leds[i]);
+				kfree(priv);
+				return ret;
+			}
+		}
+	} else {
+		priv = gpio_leds_create_of(pdev);
+		if (!priv)
+			return -ENODEV;
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	return 0;
 }
 
-static int __devexit of_gpio_leds_remove(struct platform_device *ofdev)
+static int __devexit gpio_led_remove(struct platform_device *pdev)
 {
-	struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev);
+	struct gpio_leds_priv *priv = dev_get_drvdata(&pdev->dev);
 	int i;
 
-	for (i = 0; i < pdata->num_leds; i++)
-		delete_gpio_led(&pdata->led_data[i]);
-
-	kfree(pdata);
+	for (i = 0; i < priv->num_leds; i++)
+		delete_gpio_led(&priv->leds[i]);
 
-	dev_set_drvdata(&ofdev->dev, NULL);
+	dev_set_drvdata(&pdev->dev, NULL);
+	kfree(priv);
 
 	return 0;
 }
 
-static const struct of_device_id of_gpio_leds_match[] = {
-	{ .compatible = "gpio-leds", },
-	{},
-};
-
-static struct of_platform_driver of_gpio_leds_driver = {
-	.driver = {
-		.name = "of_gpio_leds",
-		.owner = THIS_MODULE,
+static struct platform_driver gpio_led_driver = {
+	.probe		= gpio_led_probe,
+	.remove		= __devexit_p(gpio_led_remove),
+	.driver		= {
+		.name	= "leds-gpio",
+		.owner	= THIS_MODULE,
 		.of_match_table = of_gpio_leds_match,
 	},
-	.probe = of_gpio_leds_probe,
-	.remove = __devexit_p(of_gpio_leds_remove),
 };
-#endif
+
+MODULE_ALIAS("platform:leds-gpio");
 
 static int __init gpio_led_init(void)
 {
-	int ret = 0;
-
-#ifdef CONFIG_LEDS_GPIO_PLATFORM	
-	ret = platform_driver_register(&gpio_led_driver);
-	if (ret)
-		return ret;
-#endif
-#ifdef CONFIG_LEDS_GPIO_OF
-	ret = of_register_platform_driver(&of_gpio_leds_driver);
-#endif
-#ifdef CONFIG_LEDS_GPIO_PLATFORM	
-	if (ret)
-		platform_driver_unregister(&gpio_led_driver);
-#endif
-
-	return ret;
+	return platform_driver_register(&gpio_led_driver);
 }
 
 static void __exit gpio_led_exit(void)
 {
-#ifdef CONFIG_LEDS_GPIO_PLATFORM
 	platform_driver_unregister(&gpio_led_driver);
-#endif
-#ifdef CONFIG_LEDS_GPIO_OF
-	of_unregister_platform_driver(&of_gpio_leds_driver);
-#endif
 }
 
 module_init(gpio_led_init);
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
new file mode 100644
index 0000000..e7089a1
--- /dev/null
+++ b/drivers/leds/leds-lm3530.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson SA.
+ * Copyright (C) 2009 Motorola, Inc.
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Simple driver for National Semiconductor LM3530 Backlight driver chip
+ *
+ * Author: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>
+ * based on leds-lm3530.c by Dan Murphy <D.Murphy@motorola.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/led-lm3530.h>
+#include <linux/types.h>
+
+#define LM3530_LED_DEV "lcd-backlight"
+#define LM3530_NAME "lm3530-led"
+
+#define LM3530_GEN_CONFIG		0x10
+#define LM3530_ALS_CONFIG		0x20
+#define LM3530_BRT_RAMP_RATE		0x30
+#define LM3530_ALS_ZONE_REG		0x40
+#define LM3530_ALS_IMP_SELECT		0x41
+#define LM3530_BRT_CTRL_REG		0xA0
+#define LM3530_ALS_ZB0_REG		0x60
+#define LM3530_ALS_ZB1_REG		0x61
+#define LM3530_ALS_ZB2_REG		0x62
+#define LM3530_ALS_ZB3_REG		0x63
+#define LM3530_ALS_Z0T_REG		0x70
+#define LM3530_ALS_Z1T_REG		0x71
+#define LM3530_ALS_Z2T_REG		0x72
+#define LM3530_ALS_Z3T_REG		0x73
+#define LM3530_ALS_Z4T_REG		0x74
+#define LM3530_REG_MAX			15
+
+/* General Control Register */
+#define LM3530_EN_I2C_SHIFT		(0)
+#define LM3530_RAMP_LAW_SHIFT		(1)
+#define LM3530_MAX_CURR_SHIFT		(2)
+#define LM3530_EN_PWM_SHIFT		(5)
+#define LM3530_PWM_POL_SHIFT		(6)
+#define LM3530_EN_PWM_SIMPLE_SHIFT	(7)
+
+#define LM3530_ENABLE_I2C		(1 << LM3530_EN_I2C_SHIFT)
+#define LM3530_ENABLE_PWM		(1 << LM3530_EN_PWM_SHIFT)
+#define LM3530_POL_LOW			(1 << LM3530_PWM_POL_SHIFT)
+#define LM3530_ENABLE_PWM_SIMPLE	(1 << LM3530_EN_PWM_SIMPLE_SHIFT)
+
+/* ALS Config Register Options */
+#define LM3530_ALS_AVG_TIME_SHIFT	(0)
+#define LM3530_EN_ALS_SHIFT		(3)
+#define LM3530_ALS_SEL_SHIFT		(5)
+
+#define LM3530_ENABLE_ALS		(3 << LM3530_EN_ALS_SHIFT)
+
+/* Brightness Ramp Rate Register */
+#define LM3530_BRT_RAMP_FALL_SHIFT	(0)
+#define LM3530_BRT_RAMP_RISE_SHIFT	(3)
+
+/* ALS Resistor Select */
+#define LM3530_ALS1_IMP_SHIFT		(0)
+#define LM3530_ALS2_IMP_SHIFT		(4)
+
+/* Zone Boundary Register defaults */
+#define LM3530_DEF_ZB_0			(0x33)
+#define LM3530_DEF_ZB_1			(0x66)
+#define LM3530_DEF_ZB_2			(0x99)
+#define LM3530_DEF_ZB_3			(0xCC)
+
+/* Zone Target Register defaults */
+#define LM3530_DEF_ZT_0			(0x19)
+#define LM3530_DEF_ZT_1			(0x33)
+#define LM3530_DEF_ZT_2			(0x4C)
+#define LM3530_DEF_ZT_3			(0x66)
+#define LM3530_DEF_ZT_4			(0x7F)
+
+struct lm3530_mode_map {
+	const char *mode;
+	enum lm3530_mode mode_val;
+};
+
+static struct lm3530_mode_map mode_map[] = {
+	{ "man", LM3530_BL_MODE_MANUAL },
+	{ "als", LM3530_BL_MODE_ALS },
+	{ "pwm", LM3530_BL_MODE_PWM },
+};
+
+/**
+ * struct lm3530_data
+ * @led_dev: led class device
+ * @client: i2c client
+ * @pdata: LM3530 platform data
+ * @mode: mode of operation - manual, ALS, PWM
+ */
+struct lm3530_data {
+	struct led_classdev led_dev;
+	struct i2c_client *client;
+	struct lm3530_platform_data *pdata;
+	enum lm3530_mode mode;
+};
+
+static const u8 lm3530_reg[LM3530_REG_MAX] = {
+	LM3530_GEN_CONFIG,
+	LM3530_ALS_CONFIG,
+	LM3530_BRT_RAMP_RATE,
+	LM3530_ALS_ZONE_REG,
+	LM3530_ALS_IMP_SELECT,
+	LM3530_BRT_CTRL_REG,
+	LM3530_ALS_ZB0_REG,
+	LM3530_ALS_ZB1_REG,
+	LM3530_ALS_ZB2_REG,
+	LM3530_ALS_ZB3_REG,
+	LM3530_ALS_Z0T_REG,
+	LM3530_ALS_Z1T_REG,
+	LM3530_ALS_Z2T_REG,
+	LM3530_ALS_Z3T_REG,
+	LM3530_ALS_Z4T_REG,
+};
+
+static int lm3530_get_mode_from_str(const char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mode_map); i++)
+		if (sysfs_streq(str, mode_map[i].mode))
+			return mode_map[i].mode_val;
+
+	return -1;
+}
+
+static int lm3530_init_registers(struct lm3530_data *drvdata)
+{
+	int ret = 0;
+	int i;
+	u8 gen_config;
+	u8 als_config = 0;
+	u8 brt_ramp;
+	u8 als_imp_sel = 0;
+	u8 brightness;
+	u8 reg_val[LM3530_REG_MAX];
+	struct lm3530_platform_data *pltfm = drvdata->pdata;
+	struct i2c_client *client = drvdata->client;
+
+	gen_config = (pltfm->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) |
+			((pltfm->max_current & 7) << LM3530_MAX_CURR_SHIFT);
+
+	if (drvdata->mode == LM3530_BL_MODE_MANUAL ||
+	    drvdata->mode == LM3530_BL_MODE_ALS)
+		gen_config |= (LM3530_ENABLE_I2C);
+
+	if (drvdata->mode == LM3530_BL_MODE_ALS) {
+		als_config =
+			(pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
+			(LM3530_ENABLE_ALS) |
+			(pltfm->als_input_mode << LM3530_ALS_SEL_SHIFT);
+
+		als_imp_sel =
+			(pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
+			(pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
+	}
+
+	if (drvdata->mode == LM3530_BL_MODE_PWM)
+		gen_config |= (LM3530_ENABLE_PWM) |
+				(pltfm->pwm_pol_hi << LM3530_PWM_POL_SHIFT) |
+				(LM3530_ENABLE_PWM_SIMPLE);
+
+	brt_ramp = (pltfm->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) |
+			(pltfm->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT);
+
+	brightness = pltfm->brt_val;
+
+	reg_val[0] = gen_config;	/* LM3530_GEN_CONFIG */
+	reg_val[1] = als_config;	/* LM3530_ALS_CONFIG */
+	reg_val[2] = brt_ramp;		/* LM3530_BRT_RAMP_RATE */
+	reg_val[3] = 0x00;		/* LM3530_ALS_ZONE_REG */
+	reg_val[4] = als_imp_sel;	/* LM3530_ALS_IMP_SELECT */
+	reg_val[5] = brightness;	/* LM3530_BRT_CTRL_REG */
+	reg_val[6] = LM3530_DEF_ZB_0;	/* LM3530_ALS_ZB0_REG */
+	reg_val[7] = LM3530_DEF_ZB_1;	/* LM3530_ALS_ZB1_REG */
+	reg_val[8] = LM3530_DEF_ZB_2;	/* LM3530_ALS_ZB2_REG */
+	reg_val[9] = LM3530_DEF_ZB_3;	/* LM3530_ALS_ZB3_REG */
+	reg_val[10] = LM3530_DEF_ZT_0;	/* LM3530_ALS_Z0T_REG */
+	reg_val[11] = LM3530_DEF_ZT_1;	/* LM3530_ALS_Z1T_REG */
+	reg_val[12] = LM3530_DEF_ZT_2;	/* LM3530_ALS_Z2T_REG */
+	reg_val[13] = LM3530_DEF_ZT_3;	/* LM3530_ALS_Z3T_REG */
+	reg_val[14] = LM3530_DEF_ZT_4;	/* LM3530_ALS_Z4T_REG */
+
+	for (i = 0; i < LM3530_REG_MAX; i++) {
+		ret = i2c_smbus_write_byte_data(client,
+				lm3530_reg[i], reg_val[i]);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static void lm3530_brightness_set(struct led_classdev *led_cdev,
+				     enum led_brightness brt_val)
+{
+	int err;
+	struct lm3530_data *drvdata =
+	    container_of(led_cdev, struct lm3530_data, led_dev);
+
+	switch (drvdata->mode) {
+	case LM3530_BL_MODE_MANUAL:
+
+		/* set the brightness in brightness control register*/
+		err = i2c_smbus_write_byte_data(drvdata->client,
+				LM3530_BRT_CTRL_REG, brt_val / 2);
+		if (err)
+			dev_err(&drvdata->client->dev,
+				"Unable to set brightness: %d\n", err);
+		break;
+	case LM3530_BL_MODE_ALS:
+		break;
+	case LM3530_BL_MODE_PWM:
+		break;
+	default:
+		break;
+	}
+}
+
+
+static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
+				   *attr, const char *buf, size_t size)
+{
+	int err;
+	struct i2c_client *client = container_of(
+					dev->parent, struct i2c_client, dev);
+	struct lm3530_data *drvdata = i2c_get_clientdata(client);
+	int mode;
+
+	mode = lm3530_get_mode_from_str(buf);
+	if (mode < 0) {
+		dev_err(dev, "Invalid mode\n");
+		return -EINVAL;
+	}
+
+	if (mode == LM3530_BL_MODE_MANUAL)
+		drvdata->mode = LM3530_BL_MODE_MANUAL;
+	else if (mode == LM3530_BL_MODE_ALS)
+		drvdata->mode = LM3530_BL_MODE_ALS;
+	else if (mode == LM3530_BL_MODE_PWM) {
+		dev_err(dev, "PWM mode not supported\n");
+		return -EINVAL;
+	}
+
+	err = lm3530_init_registers(drvdata);
+	if (err) {
+		dev_err(dev, "Setting %s Mode failed :%d\n", buf, err);
+		return err;
+	}
+
+	return sizeof(drvdata->mode);
+}
+
+static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set);
+
+static int __devinit lm3530_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct lm3530_platform_data *pdata = client->dev.platform_data;
+	struct lm3530_data *drvdata;
+	int err = 0;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "platform data required\n");
+		err = -ENODEV;
+		goto err_out;
+	}
+
+	/* BL mode */
+	if (pdata->mode > LM3530_BL_MODE_PWM) {
+		dev_err(&client->dev, "Illegal Mode request\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "I2C_FUNC_I2C not supported\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	drvdata = kzalloc(sizeof(struct lm3530_data), GFP_KERNEL);
+	if (drvdata == NULL) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	drvdata->mode = pdata->mode;
+	drvdata->client = client;
+	drvdata->pdata = pdata;
+	drvdata->led_dev.name = LM3530_LED_DEV;
+	drvdata->led_dev.brightness_set = lm3530_brightness_set;
+
+	i2c_set_clientdata(client, drvdata);
+
+	err = lm3530_init_registers(drvdata);
+	if (err < 0) {
+		dev_err(&client->dev, "Register Init failed: %d\n", err);
+		err = -ENODEV;
+		goto err_reg_init;
+	}
+
+	err = led_classdev_register((struct device *)
+				      &client->dev, &drvdata->led_dev);
+	if (err < 0) {
+		dev_err(&client->dev, "Register led class failed: %d\n", err);
+		err = -ENODEV;
+		goto err_class_register;
+	}
+
+	err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
+	if (err < 0) {
+		dev_err(&client->dev, "File device creation failed: %d\n", err);
+		err = -ENODEV;
+		goto err_create_file;
+	}
+
+	return 0;
+
+err_create_file:
+	led_classdev_unregister(&drvdata->led_dev);
+err_class_register:
+err_reg_init:
+	kfree(drvdata);
+err_out:
+	return err;
+}
+
+static int __devexit lm3530_remove(struct i2c_client *client)
+{
+	struct lm3530_data *drvdata = i2c_get_clientdata(client);
+
+	device_remove_file(drvdata->led_dev.dev, &dev_attr_mode);
+	led_classdev_unregister(&drvdata->led_dev);
+	kfree(drvdata);
+	return 0;
+}
+
+static const struct i2c_device_id lm3530_id[] = {
+	{LM3530_NAME, 0},
+	{}
+};
+
+static struct i2c_driver lm3530_i2c_driver = {
+	.probe = lm3530_probe,
+	.remove = lm3530_remove,
+	.id_table = lm3530_id,
+	.driver = {
+		.name = LM3530_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init lm3530_init(void)
+{
+	return i2c_add_driver(&lm3530_i2c_driver);
+}
+
+static void __exit lm3530_exit(void)
+{
+	i2c_del_driver(&lm3530_i2c_driver);
+}
+
+module_init(lm3530_init);
+module_exit(lm3530_exit);
+
+MODULE_DESCRIPTION("Back Light driver for LM3530");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>");
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 80a3ae3..c0cff64 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -534,7 +534,7 @@ static ssize_t lp5521_selftest(struct device *dev,
 }
 
 /* led class device attributes */
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
 
 static struct attribute *lp5521_led_attributes[] = {
@@ -548,15 +548,15 @@ static struct attribute_group lp5521_led_attribute_group = {
 };
 
 /* device attributes */
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
 		   show_engine1_mode, store_engine1_mode);
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
 		   show_engine2_mode, store_engine2_mode);
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
 		   show_engine3_mode, store_engine3_mode);
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
 static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
 
 static struct attribute *lp5521_attributes[] = {
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index d0c4068..e19fed2 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -713,7 +713,7 @@ static ssize_t store_current(struct device *dev,
 }
 
 /* led class device attributes */
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
 
 static struct attribute *lp5523_led_attributes[] = {
@@ -727,21 +727,21 @@ static struct attribute_group lp5523_led_attribute_group = {
 };
 
 /* device attributes */
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
 		   show_engine1_mode, store_engine1_mode);
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
 		   show_engine2_mode, store_engine2_mode);
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
 		   show_engine3_mode, store_engine3_mode);
-static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUSR,
 		   show_engine1_leds, store_engine1_leds);
-static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUSR,
 		   show_engine2_leds, store_engine2_leds);
-static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUSR,
 		   show_engine3_leds, store_engine3_leds);
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
 static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL);
 
 static struct attribute *lp5523_attributes[] = {
diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c
index 1739557..7e764b8 100644
--- a/drivers/leds/leds-net5501.c
+++ b/drivers/leds/leds-net5501.c
@@ -19,7 +19,7 @@
 
 #include <asm/geode.h>
 
-static struct gpio_led net5501_leds[] = {
+static const struct gpio_led net5501_leds[] = {
 	{
 		.name = "error",
 		.gpio = 6,
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c
index 39f660b..2637c13 100644
--- a/drivers/macintosh/rack-meter.c
+++ b/drivers/macintosh/rack-meter.c
@@ -283,7 +283,7 @@ static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm)
 	}
 }
 
-static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
+static void rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
 {
 	cancel_delayed_work_sync(&rm->cpu[0].sniffer);
 	cancel_delayed_work_sync(&rm->cpu[1].sniffer);
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index 290cb32..116a49c 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -645,8 +645,7 @@ static void smu_expose_childs(struct work_struct *unused)
 
 static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs);
 
-static int smu_platform_probe(struct platform_device* dev,
-			      const struct of_device_id *match)
+static int smu_platform_probe(struct platform_device* dev)
 {
 	if (!smu)
 		return -ENODEV;
@@ -669,7 +668,7 @@ static const struct of_device_id smu_platform_match[] =
 	{},
 };
 
-static struct of_platform_driver smu_of_platform_driver =
+static struct platform_driver smu_of_platform_driver =
 {
 	.driver = {
 		.name = "smu",
@@ -689,7 +688,7 @@ static int __init smu_init_sysfs(void)
 	 * I'm a bit too far from figuring out how that works with those
 	 * new chipsets, but that will come back and bite us
 	 */
-	of_register_platform_driver(&smu_of_platform_driver);
+	platform_driver_register(&smu_of_platform_driver);
 	return 0;
 }
 
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index f3a29f2..bca2af2 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -2210,7 +2210,7 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
 	}
 }
 
-static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match)
+static int fcu_of_probe(struct platform_device* dev)
 {
 	state = state_detached;
 	of_dev = dev;
@@ -2240,7 +2240,7 @@ static const struct of_device_id fcu_match[] =
 };
 MODULE_DEVICE_TABLE(of, fcu_match);
 
-static struct of_platform_driver fcu_of_platform_driver = 
+static struct platform_driver fcu_of_platform_driver = 
 {
 	.driver = {
 		.name = "temperature",
@@ -2263,12 +2263,12 @@ static int __init therm_pm72_init(void)
 	    !rackmac)
 	    	return -ENODEV;
 
-	return of_register_platform_driver(&fcu_of_platform_driver);
+	return platform_driver_register(&fcu_of_platform_driver);
 }
 
 static void __exit therm_pm72_exit(void)
 {
-	of_unregister_platform_driver(&fcu_of_platform_driver);
+	platform_driver_unregister(&fcu_of_platform_driver);
 }
 
 module_init(therm_pm72_init);
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index c89f396..d37819f 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -443,8 +443,7 @@ static struct i2c_driver g4fan_driver = {
 /*	initialization / cleanup					*/
 /************************************************************************/
 
-static int
-therm_of_probe( struct platform_device *dev, const struct of_device_id *match )
+static int therm_of_probe(struct platform_device *dev)
 {
 	return i2c_add_driver( &g4fan_driver );
 }
@@ -462,7 +461,7 @@ static const struct of_device_id therm_of_match[] = {{
     }, {}
 };
 
-static struct of_platform_driver therm_of_driver = {
+static struct platform_driver therm_of_driver = {
 	.driver = {
 		.name = "temperature",
 		.owner = THIS_MODULE,
@@ -509,14 +508,14 @@ g4fan_init( void )
 		return -ENODEV;
 	}
 
-	of_register_platform_driver( &therm_of_driver );
+	platform_driver_register( &therm_of_driver );
 	return 0;
 }
 
 static void __exit
 g4fan_exit( void )
 {
-	of_unregister_platform_driver( &therm_of_driver );
+	platform_driver_unregister( &therm_of_driver );
 
 	if( x.of_dev )
 		of_device_unregister( x.of_dev );
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
index ade1e65..b1d9117 100644
--- a/drivers/macintosh/via-pmu-backlight.c
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -163,6 +163,7 @@ void __init pmu_backlight_init()
 	snprintf(name, sizeof(name), "pmubl");
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data,
 				       &props);
diff --git a/drivers/md/dm-log-userspace-transfer.c b/drivers/md/dm-log-userspace-transfer.c
index 049eaf1..1f23e04 100644
--- a/drivers/md/dm-log-userspace-transfer.c
+++ b/drivers/md/dm-log-userspace-transfer.c
@@ -134,7 +134,7 @@ static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
 {
 	struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
 
-	if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+	if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
 		return;
 
 	spin_lock(&receiving_list_lock);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index b82d288..4b0b63c 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1283,24 +1283,22 @@ static int do_end_io(struct multipath *m, struct request *clone,
 	if (!error && !clone->errors)
 		return 0;	/* I/O complete */
 
-	if (error == -EOPNOTSUPP)
-		return error;
-
-	if (clone->cmd_flags & REQ_DISCARD)
-		/*
-		 * Pass all discard request failures up.
-		 * FIXME: only fail_path if the discard failed due to a
-		 * transport problem.  This requires precise understanding
-		 * of the underlying failure (e.g. the SCSI sense).
-		 */
+	if (error == -EOPNOTSUPP || error == -EREMOTEIO)
 		return error;
 
 	if (mpio->pgpath)
 		fail_path(mpio->pgpath);
 
 	spin_lock_irqsave(&m->lock, flags);
-	if (!m->nr_valid_paths && !m->queue_if_no_path && !__must_push_back(m))
-		r = -EIO;
+	if (!m->nr_valid_paths) {
+		if (!m->queue_if_no_path) {
+			if (!__must_push_back(m))
+				r = -EIO;
+		} else {
+			if (error == -EBADE)
+				r = error;
+		}
+	}
 	spin_unlock_irqrestore(&m->lock, flags);
 
 	return r;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 818313e..d5ad772 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7361,7 +7361,7 @@ static int __init md_init(void)
 {
 	int ret = -ENOMEM;
 
-	md_wq = alloc_workqueue("md", WQ_RESCUER, 0);
+	md_wq = alloc_workqueue("md", WQ_MEM_RECLAIM, 0);
 	if (!md_wq)
 		goto err_wq;
 
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
index 23005b3..b2b9415 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -8,60 +8,71 @@
 #include "dvb-usb-common.h"
 #include <linux/usb/input.h>
 
+static unsigned int
+legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
+				struct rc_map_table *keymap,
+				unsigned int keymap_size)
+{
+	unsigned int index;
+	unsigned int scancode;
+
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+	} else {
+		if (input_scancode_to_scalar(ke, &scancode))
+			return keymap_size;
+
+		/* See if we can match the raw key code. */
+		for (index = 0; index < keymap_size; index++)
+			if (keymap[index].scancode == scancode)
+				break;
+
+		/* See if there is an unused hole in the map */
+		if (index >= keymap_size) {
+			for (index = 0; index < keymap_size; index++) {
+				if (keymap[index].keycode == KEY_RESERVED ||
+				    keymap[index].keycode == KEY_UNKNOWN) {
+					break;
+				}
+			}
+		}
+	}
+
+	return index;
+}
+
 static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
-				unsigned int scancode, unsigned int *keycode)
+				     struct input_keymap_entry *ke)
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
-
 	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	int i;
+	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
+	unsigned int index;
 
-	/* See if we can match the raw key code. */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].scancode == scancode) {
-			*keycode = keymap[i].keycode;
-			return 0;
-		}
+	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
+	if (index >= keymap_size)
+		return -EINVAL;
 
-	/*
-	 * If is there extra space, returns KEY_RESERVED,
-	 * otherwise, input core won't let legacy_dvb_usb_setkeycode
-	 * to work
-	 */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].keycode == KEY_RESERVED ||
-		    keymap[i].keycode == KEY_UNKNOWN) {
-			*keycode = KEY_RESERVED;
-			return 0;
-		}
+	ke->keycode = keymap[index].keycode;
+	if (ke->keycode == KEY_UNKNOWN)
+		ke->keycode = KEY_RESERVED;
+	ke->len = sizeof(keymap[index].scancode);
+	memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
+	ke->index = index;
 
-	return -EINVAL;
+	return 0;
 }
 
 static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
-				unsigned int scancode, unsigned int keycode)
+				     const struct input_keymap_entry *ke,
+				     unsigned int *old_keycode)
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
-
 	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	int i;
-
-	/* Search if it is replacing an existing keycode */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].scancode == scancode) {
-			keymap[i].keycode = keycode;
-			return 0;
-		}
-
-	/* Search if is there a clean entry. If so, use it */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].keycode == KEY_RESERVED ||
-		    keymap[i].keycode == KEY_UNKNOWN) {
-			keymap[i].scancode = scancode;
-			keymap[i].keycode = keycode;
-			return 0;
-		}
+	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
+	unsigned int index;
 
+	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
 	/*
 	 * FIXME: Currently, it is not possible to increase the size of
 	 * scancode table. For it to happen, one possibility
@@ -69,8 +80,24 @@ static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
 	 * copying data, appending the new key on it, and freeing
 	 * the old one - or maybe just allocating some spare space
 	 */
+	if (index >= keymap_size)
+		return -EINVAL;
+
+	*old_keycode = keymap[index].keycode;
+	keymap->keycode = ke->keycode;
+	__set_bit(ke->keycode, dev->keybit);
+
+	if (*old_keycode != KEY_RESERVED) {
+		__clear_bit(*old_keycode, dev->keybit);
+		for (index = 0; index < keymap_size; index++) {
+			if (keymap[index].keycode == *old_keycode) {
+				__set_bit(*old_keycode, dev->keybit);
+				break;
+			}
+		}
+	}
 
-	return -EINVAL;
+	return 0;
 }
 
 /* Remote-control poll function - called every dib->rc_query_interval ms to see
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 5b4422e..5ac1baf 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -966,8 +966,8 @@ struct rc_dev *rc_allocate_device(void)
 		return NULL;
 	}
 
-	dev->input_dev->getkeycode_new = ir_getkeycode;
-	dev->input_dev->setkeycode_new = ir_setkeycode;
+	dev->input_dev->getkeycode = ir_getkeycode;
+	dev->input_dev->setkeycode = ir_setkeycode;
 	input_set_drvdata(dev->input_dev, dev);
 
 	spin_lock_init(&dev->rc_map.lock);
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c
index e4bba88..031af16 100644
--- a/drivers/media/video/fsl-viu.c
+++ b/drivers/media/video/fsl-viu.c
@@ -1445,8 +1445,7 @@ static struct video_device viu_template = {
 	.current_norm   = V4L2_STD_NTSC_M,
 };
 
-static int __devinit viu_of_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit viu_of_probe(struct platform_device *op)
 {
 	struct viu_dev *viu_dev;
 	struct video_device *vdev;
@@ -1627,7 +1626,7 @@ static struct of_device_id mpc512x_viu_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
 
-static struct of_platform_driver viu_of_platform_driver = {
+static struct platform_driver viu_of_platform_driver = {
 	.probe = viu_of_probe,
 	.remove = __devexit_p(viu_of_remove),
 #ifdef CONFIG_PM
@@ -1643,12 +1642,12 @@ static struct of_platform_driver viu_of_platform_driver = {
 
 static int __init viu_init(void)
 {
-	return of_register_platform_driver(&viu_of_platform_driver);
+	return platform_driver_register(&viu_of_platform_driver);
 }
 
 static void __exit viu_exit(void)
 {
-	of_unregister_platform_driver(&viu_of_platform_driver);
+	platform_driver_unregister(&viu_of_platform_driver);
 }
 
 module_init(viu_init);
diff --git a/drivers/memstick/Makefile b/drivers/memstick/Makefile
index dc160fb..9862359 100644
--- a/drivers/memstick/Makefile
+++ b/drivers/memstick/Makefile
@@ -2,9 +2,7 @@
 # Makefile for the kernel MemoryStick device drivers.
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+subdir-ccflags-$(CONFIG_MEMSTICK_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_MEMSTICK)		+= core/
 obj-$(CONFIG_MEMSTICK)		+= host/
diff --git a/drivers/memstick/core/Makefile b/drivers/memstick/core/Makefile
index 8b2b529..ecd0299 100644
--- a/drivers/memstick/core/Makefile
+++ b/drivers/memstick/core/Makefile
@@ -2,10 +2,6 @@
 # Makefile for the kernel MemoryStick core.
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
-
 obj-$(CONFIG_MEMSTICK)		+= memstick.o
 
 obj-$(CONFIG_MSPRO_BLOCK)	+= mspro_block.o
diff --git a/drivers/memstick/host/Makefile b/drivers/memstick/host/Makefile
index 12530e4..a1815e9 100644
--- a/drivers/memstick/host/Makefile
+++ b/drivers/memstick/host/Makefile
@@ -2,9 +2,5 @@
 # Makefile for MemoryStick host controller drivers
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS			+= -DDEBUG
-endif
-
 obj-$(CONFIG_MEMSTICK_TIFM_MS)		+= tifm_ms.o
 obj-$(CONFIG_MEMSTICK_JMICRON_38X)	+= jmb38x_ms.o
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index 95c9532..d182a24 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -2,7 +2,7 @@
 
 # enable verbose logging
 # CONFIG_FUSION_LOGGING needs to be enabled in Kconfig
-#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE
+#ccflags-y := -DMPT_DEBUG_VERBOSE
 
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 013c7d8..22027e7 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -2593,6 +2593,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
 #define MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE              (0x03)
 #define MPI_SAS_IOUNIT0_RATE_1_5                            (0x08)
 #define MPI_SAS_IOUNIT0_RATE_3_0                            (0x09)
+#define MPI_SAS_IOUNIT0_RATE_6_0                            (0x0A)
 
 /* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
 
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 8faa4fa..fd62228 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -841,6 +841,7 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
 #define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE         (0x03)
 #define MPI_EVENT_SAS_PLS_LR_RATE_1_5                       (0x08)
 #define MPI_EVENT_SAS_PLS_LR_RATE_3_0                       (0x09)
+#define MPI_EVENT_SAS_PLS_LR_RATE_6_0                       (0x0A)
 
 /* SAS Discovery Event data */
 
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 3358c0a..ec8080c 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -7418,7 +7418,12 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
 		case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
 			   "SAS PHY Link Status: Phy=%d:"
-			   " Rate 3.0 Gpbs",PhyNumber);
+			   " Rate 3.0 Gbps", PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_6_0:
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
+			   " Rate 6.0 Gbps", PhyNumber);
 			break;
 		default:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index e8deb8e..878bda0 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -1314,8 +1314,10 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
 	else
 		karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
 
-	if (karg->hdr.port > 1)
+	if (karg->hdr.port > 1) {
+		kfree(karg);
 		return -EINVAL;
+	}
 	port = karg->hdr.port;
 
 	karg->port = port;
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 8aefb18..f5a14af 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1973,7 +1973,6 @@ static struct scsi_host_template mptsas_driver_template = {
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
 	.eh_device_reset_handler	= mptscsih_dev_reset,
-	.eh_bus_reset_handler		= mptscsih_bus_reset,
 	.eh_host_reset_handler		= mptscsih_host_reset,
 	.bios_param			= mptscsih_bios_param,
 	.can_queue			= MPT_SAS_CAN_QUEUE,
@@ -3063,6 +3062,9 @@ static int mptsas_probe_one_phy(struct device *dev,
 	case MPI_SAS_IOUNIT0_RATE_3_0:
 		phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
 		break;
+	case MPI_SAS_IOUNIT0_RATE_6_0:
+		phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS;
+		break;
 	case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
 	case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
 	default:
@@ -3691,7 +3693,8 @@ mptsas_send_link_status_event(struct fw_event_work *fw_event)
 	}
 
 	if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
-	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
+	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0 ||
+	    link_rate == MPI_SAS_IOUNIT0_RATE_6_0) {
 
 		if (!port_info) {
 			if (ioc->old_sas_discovery_protocal) {
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index a0421ef..8a5b2d8 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -84,7 +84,8 @@ int i2o_driver_register(struct i2o_driver *drv)
 	osm_debug("Register driver %s\n", drv->name);
 
 	if (drv->event) {
-		drv->event_queue = create_workqueue(drv->name);
+		drv->event_queue = alloc_workqueue(drv->name,
+						   WQ_MEM_RECLAIM, 1);
 		if (!drv->event_queue) {
 			osm_err("Could not initialize event queue for driver "
 				"%s\n", drv->name);
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 7d3cc57..098de2b 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -1044,8 +1044,7 @@ static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 
 static int cfg_open(struct inode *inode, struct file *file)
 {
-	struct i2o_cfg_info *tmp =
-	    (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info),
+	struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info),
 					   GFP_KERNEL);
 	unsigned long flags;
 
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index fd01836..fdca643 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -81,6 +81,17 @@ config MFD_DM355EVM_MSP
 	  boards.  MSP430 firmware manages resets and power sequencing,
 	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
 
+config MFD_TI_SSP
+	tristate "TI Sequencer Serial Port support"
+	depends on ARCH_DAVINCI_TNETV107X
+	select MFD_CORE
+	---help---
+	  Say Y here if you want support for the Sequencer Serial Port
+	  in a Texas Instruments TNETV107X SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ti-ssp.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
@@ -624,6 +635,15 @@ config MFD_WL1273_CORE
 	  driver connects the radio-wl1273 V4L2 module and the wl1273
 	  audio codec.
 
+config MFD_OMAP_USB_HOST
+	bool "Support OMAP USBHS core driver"
+	depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
+	default y
+	help
+	  This is the core driver for the OAMP EHCI and OHCI drivers.
+	  This MFD driver does the required setup functionalities for
+	  OMAP USB Host drivers.
+
 endif # MFD_SUPPORT
 
 menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index a54e2c7..f0e25ca 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_HTC_I2CPLD)	+= htc-i2cpld.o
 
 obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
+obj-$(CONFIG_MFD_TI_SSP)	+= ti-ssp.o
 
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
 obj-$(CONFIG_MFD_TC3589X)	+= tc3589x.o
@@ -83,3 +84,4 @@ obj-$(CONFIG_MFD_TPS6586X)	+= tps6586x.o
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
+obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
new file mode 100644
index 0000000..cb01209
--- /dev/null
+++ b/drivers/mfd/omap-usb-host.c
@@ -0,0 +1,1061 @@
+/**
+ * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <plat/usb.h>
+
+#define USBHS_DRIVER_NAME	"usbhs-omap"
+#define OMAP_EHCI_DEVICE	"ehci-omap"
+#define OMAP_OHCI_DEVICE	"ohci-omap3"
+
+/* OMAP USBHOST Register addresses  */
+
+/* TLL Register Set */
+#define	OMAP_USBTLL_REVISION				(0x00)
+#define	OMAP_USBTLL_SYSCONFIG				(0x10)
+#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
+#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
+#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
+#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
+#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define	OMAP_USBTLL_SYSSTATUS				(0x14)
+#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
+
+#define	OMAP_USBTLL_IRQSTATUS				(0x18)
+#define	OMAP_USBTLL_IRQENABLE				(0x1C)
+
+#define	OMAP_TLL_SHARED_CONF				(0x30)
+#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
+#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
+#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
+#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
+#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
+
+#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
+#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
+#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
+#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
+#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
+#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
+#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
+#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
+
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0		0x0
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM		0x1
+#define OMAP_TLL_FSLSMODE_3PIN_PHY			0x2
+#define OMAP_TLL_FSLSMODE_4PIN_PHY			0x3
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0		0x4
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM		0x5
+#define OMAP_TLL_FSLSMODE_3PIN_TLL			0x6
+#define OMAP_TLL_FSLSMODE_4PIN_TLL			0x7
+#define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0		0xA
+#define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM		0xB
+
+#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
+#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
+#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
+#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
+
+#define OMAP_TLL_CHANNEL_COUNT				3
+#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
+#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
+#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
+
+/* UHH Register Set */
+#define	OMAP_UHH_REVISION				(0x00)
+#define	OMAP_UHH_SYSCONFIG				(0x10)
+#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
+#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
+#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
+#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
+#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
+#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define	OMAP_UHH_SYSSTATUS				(0x14)
+#define	OMAP_UHH_HOSTCONFIG				(0x40)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
+#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
+#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
+#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
+#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
+#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
+#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
+#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
+#define OMAP4_UHH_HOSTCONFIG_APP_START_CLK		(1 << 31)
+
+/* OMAP4-specific defines */
+#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR		(3 << 2)
+#define OMAP4_UHH_SYSCONFIG_NOIDLE			(1 << 2)
+#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR		(3 << 4)
+#define OMAP4_UHH_SYSCONFIG_NOSTDBY			(1 << 4)
+#define OMAP4_UHH_SYSCONFIG_SOFTRESET			(1 << 0)
+
+#define OMAP4_P1_MODE_CLEAR				(3 << 16)
+#define OMAP4_P1_MODE_TLL				(1 << 16)
+#define OMAP4_P1_MODE_HSIC				(3 << 16)
+#define OMAP4_P2_MODE_CLEAR				(3 << 18)
+#define OMAP4_P2_MODE_TLL				(1 << 18)
+#define OMAP4_P2_MODE_HSIC				(3 << 18)
+
+#define OMAP_REV2_TLL_CHANNEL_COUNT			2
+
+#define	OMAP_UHH_DEBUG_CSR				(0x44)
+
+/* Values of UHH_REVISION - Note: these are not given in the TRM */
+#define OMAP_USBHS_REV1		0x00000010	/* OMAP3 */
+#define OMAP_USBHS_REV2		0x50700100	/* OMAP4 */
+
+#define is_omap_usbhs_rev1(x)	(x->usbhs_rev == OMAP_USBHS_REV1)
+#define is_omap_usbhs_rev2(x)	(x->usbhs_rev == OMAP_USBHS_REV2)
+
+#define is_ehci_phy_mode(x)	(x == OMAP_EHCI_PORT_MODE_PHY)
+#define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
+#define is_ehci_hsic_mode(x)	(x == OMAP_EHCI_PORT_MODE_HSIC)
+
+
+struct usbhs_hcd_omap {
+	struct clk			*usbhost_ick;
+	struct clk			*usbhost_hs_fck;
+	struct clk			*usbhost_fs_fck;
+	struct clk			*xclk60mhsp1_ck;
+	struct clk			*xclk60mhsp2_ck;
+	struct clk			*utmi_p1_fck;
+	struct clk			*usbhost_p1_fck;
+	struct clk			*usbtll_p1_fck;
+	struct clk			*utmi_p2_fck;
+	struct clk			*usbhost_p2_fck;
+	struct clk			*usbtll_p2_fck;
+	struct clk			*init_60m_fclk;
+	struct clk			*usbtll_fck;
+	struct clk			*usbtll_ick;
+
+	void __iomem			*uhh_base;
+	void __iomem			*tll_base;
+
+	struct usbhs_omap_platform_data	platdata;
+
+	u32				usbhs_rev;
+	spinlock_t			lock;
+	int				count;
+};
+/*-------------------------------------------------------------------------*/
+
+const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
+static u64 usbhs_dmamask = ~(u32)0;
+
+/*-------------------------------------------------------------------------*/
+
+static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 usbhs_read(void __iomem *base, u32 reg)
+{
+	return __raw_readl(base + reg);
+}
+
+static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val)
+{
+	__raw_writeb(val, base + reg);
+}
+
+static inline u8 usbhs_readb(void __iomem *base, u8 reg)
+{
+	return __raw_readb(base + reg);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct platform_device *omap_usbhs_alloc_child(const char *name,
+			struct resource	*res, int num_resources, void *pdata,
+			size_t pdata_size, struct device *dev)
+{
+	struct platform_device	*child;
+	int			ret;
+
+	child = platform_device_alloc(name, 0);
+
+	if (!child) {
+		dev_err(dev, "platform_device_alloc %s failed\n", name);
+		goto err_end;
+	}
+
+	ret = platform_device_add_resources(child, res, num_resources);
+	if (ret) {
+		dev_err(dev, "platform_device_add_resources failed\n");
+		goto err_alloc;
+	}
+
+	ret = platform_device_add_data(child, pdata, pdata_size);
+	if (ret) {
+		dev_err(dev, "platform_device_add_data failed\n");
+		goto err_alloc;
+	}
+
+	child->dev.dma_mask		= &usbhs_dmamask;
+	child->dev.coherent_dma_mask	= 0xffffffff;
+	child->dev.parent		= dev;
+
+	ret = platform_device_add(child);
+	if (ret) {
+		dev_err(dev, "platform_device_add failed\n");
+		goto err_alloc;
+	}
+
+	return child;
+
+err_alloc:
+	platform_device_put(child);
+
+err_end:
+	return NULL;
+}
+
+static int omap_usbhs_alloc_children(struct platform_device *pdev)
+{
+	struct device				*dev = &pdev->dev;
+	struct usbhs_hcd_omap			*omap;
+	struct ehci_hcd_omap_platform_data	*ehci_data;
+	struct ohci_hcd_omap_platform_data	*ohci_data;
+	struct platform_device			*ehci;
+	struct platform_device			*ohci;
+	struct resource				*res;
+	struct resource				resources[2];
+	int					ret;
+
+	omap = platform_get_drvdata(pdev);
+	ehci_data = omap->platdata.ehci_data;
+	ohci_data = omap->platdata.ohci_data;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
+	if (!res) {
+		dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
+		ret = -ENODEV;
+		goto err_end;
+	}
+	resources[0] = *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq");
+	if (!res) {
+		dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n");
+		ret = -ENODEV;
+		goto err_end;
+	}
+	resources[1] = *res;
+
+	ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, ehci_data,
+		sizeof(*ehci_data), dev);
+
+	if (!ehci) {
+		dev_err(dev, "omap_usbhs_alloc_child failed\n");
+		goto err_end;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
+	if (!res) {
+		dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n");
+		ret = -ENODEV;
+		goto err_ehci;
+	}
+	resources[0] = *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq");
+	if (!res) {
+		dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n");
+		ret = -ENODEV;
+		goto err_ehci;
+	}
+	resources[1] = *res;
+
+	ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, ohci_data,
+		sizeof(*ohci_data), dev);
+	if (!ohci) {
+		dev_err(dev, "omap_usbhs_alloc_child failed\n");
+		goto err_ehci;
+	}
+
+	return 0;
+
+err_ehci:
+	platform_device_put(ehci);
+
+err_end:
+	return ret;
+}
+
+/**
+ * usbhs_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller.
+ */
+static int __devinit usbhs_omap_probe(struct platform_device *pdev)
+{
+	struct device			*dev =  &pdev->dev;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_hcd_omap		*omap;
+	struct resource			*res;
+	int				ret = 0;
+	int				i;
+
+	if (!pdata) {
+		dev_err(dev, "Missing platfrom data\n");
+		ret = -ENOMEM;
+		goto end_probe;
+	}
+
+	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
+	if (!omap) {
+		dev_err(dev, "Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto end_probe;
+	}
+
+	spin_lock_init(&omap->lock);
+
+	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
+		omap->platdata.port_mode[i] = pdata->port_mode[i];
+
+	omap->platdata.ehci_data = pdata->ehci_data;
+	omap->platdata.ohci_data = pdata->ohci_data;
+
+	omap->usbhost_ick = clk_get(dev, "usbhost_ick");
+	if (IS_ERR(omap->usbhost_ick)) {
+		ret =  PTR_ERR(omap->usbhost_ick);
+		dev_err(dev, "usbhost_ick failed error:%d\n", ret);
+		goto err_end;
+	}
+
+	omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
+	if (IS_ERR(omap->usbhost_hs_fck)) {
+		ret = PTR_ERR(omap->usbhost_hs_fck);
+		dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
+		goto err_usbhost_ick;
+	}
+
+	omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
+	if (IS_ERR(omap->usbhost_fs_fck)) {
+		ret = PTR_ERR(omap->usbhost_fs_fck);
+		dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
+		goto err_usbhost_hs_fck;
+	}
+
+	omap->usbtll_fck = clk_get(dev, "usbtll_fck");
+	if (IS_ERR(omap->usbtll_fck)) {
+		ret = PTR_ERR(omap->usbtll_fck);
+		dev_err(dev, "usbtll_fck failed error:%d\n", ret);
+		goto err_usbhost_fs_fck;
+	}
+
+	omap->usbtll_ick = clk_get(dev, "usbtll_ick");
+	if (IS_ERR(omap->usbtll_ick)) {
+		ret = PTR_ERR(omap->usbtll_ick);
+		dev_err(dev, "usbtll_ick failed error:%d\n", ret);
+		goto err_usbtll_fck;
+	}
+
+	omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
+	if (IS_ERR(omap->utmi_p1_fck)) {
+		ret = PTR_ERR(omap->utmi_p1_fck);
+		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
+		goto err_usbtll_ick;
+	}
+
+	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
+	if (IS_ERR(omap->xclk60mhsp1_ck)) {
+		ret = PTR_ERR(omap->xclk60mhsp1_ck);
+		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
+		goto err_utmi_p1_fck;
+	}
+
+	omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
+	if (IS_ERR(omap->utmi_p2_fck)) {
+		ret = PTR_ERR(omap->utmi_p2_fck);
+		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
+		goto err_xclk60mhsp1_ck;
+	}
+
+	omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
+	if (IS_ERR(omap->xclk60mhsp2_ck)) {
+		ret = PTR_ERR(omap->xclk60mhsp2_ck);
+		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
+		goto err_utmi_p2_fck;
+	}
+
+	omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
+	if (IS_ERR(omap->usbhost_p1_fck)) {
+		ret = PTR_ERR(omap->usbhost_p1_fck);
+		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
+		goto err_xclk60mhsp2_ck;
+	}
+
+	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
+	if (IS_ERR(omap->usbtll_p1_fck)) {
+		ret = PTR_ERR(omap->usbtll_p1_fck);
+		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
+		goto err_usbhost_p1_fck;
+	}
+
+	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
+	if (IS_ERR(omap->usbhost_p2_fck)) {
+		ret = PTR_ERR(omap->usbhost_p2_fck);
+		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
+		goto err_usbtll_p1_fck;
+	}
+
+	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
+	if (IS_ERR(omap->usbtll_p2_fck)) {
+		ret = PTR_ERR(omap->usbtll_p2_fck);
+		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
+		goto err_usbhost_p2_fck;
+	}
+
+	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
+	if (IS_ERR(omap->init_60m_fclk)) {
+		ret = PTR_ERR(omap->init_60m_fclk);
+		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
+		goto err_usbtll_p2_fck;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		ret = -ENODEV;
+		goto err_init_60m_fclk;
+	}
+
+	omap->uhh_base = ioremap(res->start, resource_size(res));
+	if (!omap->uhh_base) {
+		dev_err(dev, "UHH ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_init_60m_fclk;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		ret = -ENODEV;
+		goto err_tll;
+	}
+
+	omap->tll_base = ioremap(res->start, resource_size(res));
+	if (!omap->tll_base) {
+		dev_err(dev, "TLL ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_tll;
+	}
+
+	platform_set_drvdata(pdev, omap);
+
+	ret = omap_usbhs_alloc_children(pdev);
+	if (ret) {
+		dev_err(dev, "omap_usbhs_alloc_children failed\n");
+		goto err_alloc;
+	}
+
+	goto end_probe;
+
+err_alloc:
+	iounmap(omap->tll_base);
+
+err_tll:
+	iounmap(omap->uhh_base);
+
+err_init_60m_fclk:
+	clk_put(omap->init_60m_fclk);
+
+err_usbtll_p2_fck:
+	clk_put(omap->usbtll_p2_fck);
+
+err_usbhost_p2_fck:
+	clk_put(omap->usbhost_p2_fck);
+
+err_usbtll_p1_fck:
+	clk_put(omap->usbtll_p1_fck);
+
+err_usbhost_p1_fck:
+	clk_put(omap->usbhost_p1_fck);
+
+err_xclk60mhsp2_ck:
+	clk_put(omap->xclk60mhsp2_ck);
+
+err_utmi_p2_fck:
+	clk_put(omap->utmi_p2_fck);
+
+err_xclk60mhsp1_ck:
+	clk_put(omap->xclk60mhsp1_ck);
+
+err_utmi_p1_fck:
+	clk_put(omap->utmi_p1_fck);
+
+err_usbtll_ick:
+	clk_put(omap->usbtll_ick);
+
+err_usbtll_fck:
+	clk_put(omap->usbtll_fck);
+
+err_usbhost_fs_fck:
+	clk_put(omap->usbhost_fs_fck);
+
+err_usbhost_hs_fck:
+	clk_put(omap->usbhost_hs_fck);
+
+err_usbhost_ick:
+	clk_put(omap->usbhost_ick);
+
+err_end:
+	kfree(omap);
+
+end_probe:
+	return ret;
+}
+
+/**
+ * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
+ * @pdev: USB Host Controller being removed
+ *
+ * Reverses the effect of usbhs_omap_probe().
+ */
+static int __devexit usbhs_omap_remove(struct platform_device *pdev)
+{
+	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+
+	if (omap->count != 0) {
+		dev_err(&pdev->dev,
+			"Either EHCI or OHCI is still using usbhs core\n");
+		return -EBUSY;
+	}
+
+	iounmap(omap->tll_base);
+	iounmap(omap->uhh_base);
+	clk_put(omap->init_60m_fclk);
+	clk_put(omap->usbtll_p2_fck);
+	clk_put(omap->usbhost_p2_fck);
+	clk_put(omap->usbtll_p1_fck);
+	clk_put(omap->usbhost_p1_fck);
+	clk_put(omap->xclk60mhsp2_ck);
+	clk_put(omap->utmi_p2_fck);
+	clk_put(omap->xclk60mhsp1_ck);
+	clk_put(omap->utmi_p1_fck);
+	clk_put(omap->usbtll_ick);
+	clk_put(omap->usbtll_fck);
+	clk_put(omap->usbhost_fs_fck);
+	clk_put(omap->usbhost_hs_fck);
+	clk_put(omap->usbhost_ick);
+	kfree(omap);
+
+	return 0;
+}
+
+static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
+{
+	switch (pmode) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * convert the port-mode enum to a value we can use in the FSLSMODE
+ * field of USBTLL_CHANNEL_CONF
+ */
+static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
+{
+	switch (mode) {
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_3PIN_PHY;
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_4PIN_PHY;
+
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
+
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_3PIN_TLL;
+
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_4PIN_TLL;
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
+	default:
+		pr_warning("Invalid port mode, using default\n");
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+	}
+}
+
+static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	unsigned			reg;
+	int				i;
+
+	/* Program Common TLL register */
+	reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF);
+	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
+		| OMAP_TLL_SHARED_CONF_USB_DIVRATION);
+	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
+	reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
+
+	usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
+
+	/* Enable channels now */
+	for (i = 0; i < tll_channel_count; i++) {
+		reg = usbhs_read(omap->tll_base,
+				OMAP_TLL_CHANNEL_CONF(i));
+
+		if (is_ohci_port(pdata->port_mode[i])) {
+			reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
+				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
+			reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
+		} else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) {
+
+			/* Disable AutoIdle, BitStuffing and use SDR Mode */
+			reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
+				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
+				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+
+			reg |= (1 << (i + 1));
+		} else
+			continue;
+
+		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
+		usbhs_write(omap->tll_base,
+				OMAP_TLL_CHANNEL_CONF(i), reg);
+
+		usbhs_writeb(omap->tll_base,
+				OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
+	}
+}
+
+static int usbhs_enable(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	unsigned long			flags = 0;
+	int				ret = 0;
+	unsigned long			timeout;
+	unsigned			reg;
+
+	dev_dbg(dev, "starting TI HSUSB Controller\n");
+	if (!pdata) {
+		dev_dbg(dev, "missing platform_data\n");
+		ret =  -ENODEV;
+		goto end_enable;
+	}
+
+	spin_lock_irqsave(&omap->lock, flags);
+	if (omap->count > 0)
+		goto end_count;
+
+	clk_enable(omap->usbhost_ick);
+	clk_enable(omap->usbhost_hs_fck);
+	clk_enable(omap->usbhost_fs_fck);
+	clk_enable(omap->usbtll_fck);
+	clk_enable(omap->usbtll_ick);
+
+	if (pdata->ehci_data->phy_reset) {
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
+			gpio_request(pdata->ehci_data->reset_gpio_port[0],
+						"USB1 PHY reset");
+			gpio_direction_output
+				(pdata->ehci_data->reset_gpio_port[0], 1);
+		}
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) {
+			gpio_request(pdata->ehci_data->reset_gpio_port[1],
+						"USB2 PHY reset");
+			gpio_direction_output
+				(pdata->ehci_data->reset_gpio_port[1], 1);
+		}
+
+		/* Hold the PHY in RESET for enough time till DIR is high */
+		udelay(10);
+	}
+
+	omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
+	dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
+
+	/* perform TLL soft reset, and wait until reset is complete */
+	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
+			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
+
+	/* Wait for TLL reset to complete */
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
+			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			dev_dbg(dev, "operation timed out\n");
+			ret = -EINVAL;
+			goto err_tll;
+		}
+	}
+
+	dev_dbg(dev, "TLL RESET DONE\n");
+
+	/* (1<<3) = no idle mode only for initial debugging */
+	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
+			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
+			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
+			OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
+
+	/* Put UHH in NoIdle/NoStandby mode */
+	reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
+	if (is_omap_usbhs_rev1(omap)) {
+		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
+				| OMAP_UHH_SYSCONFIG_SIDLEMODE
+				| OMAP_UHH_SYSCONFIG_CACTIVITY
+				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
+		reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
+
+
+	} else if (is_omap_usbhs_rev2(omap)) {
+		reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
+		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
+		reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
+		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
+	}
+
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
+
+	reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
+	/* setup ULPI bypass and burst configurations */
+	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
+			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
+			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
+	reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK;
+	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
+
+	if (is_omap_usbhs_rev1(omap)) {
+		if (pdata->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
+		if (pdata->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
+		if (pdata->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
+
+		/* Bypass the TLL module for PHY mode operation */
+		if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
+			dev_dbg(dev, "OMAP3 ES version <= ES2.1\n");
+			if (is_ehci_phy_mode(pdata->port_mode[0]) ||
+				is_ehci_phy_mode(pdata->port_mode[1]) ||
+					is_ehci_phy_mode(pdata->port_mode[2]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+		} else {
+			dev_dbg(dev, "OMAP3 ES version > ES2.1\n");
+			if (is_ehci_phy_mode(pdata->port_mode[0]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
+			if (is_ehci_phy_mode(pdata->port_mode[1]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
+			if (is_ehci_phy_mode(pdata->port_mode[2]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+		}
+	} else if (is_omap_usbhs_rev2(omap)) {
+		/* Clear port mode fields for PHY mode*/
+		reg &= ~OMAP4_P1_MODE_CLEAR;
+		reg &= ~OMAP4_P2_MODE_CLEAR;
+
+		if (is_ehci_phy_mode(pdata->port_mode[0])) {
+			ret = clk_set_parent(omap->utmi_p1_fck,
+						omap->xclk60mhsp1_ck);
+			if (ret != 0) {
+				dev_err(dev, "xclk60mhsp1_ck set parent"
+				"failed error:%d\n", ret);
+				goto err_tll;
+			}
+		} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
+			ret = clk_set_parent(omap->utmi_p1_fck,
+						omap->init_60m_fclk);
+			if (ret != 0) {
+				dev_err(dev, "init_60m_fclk set parent"
+				"failed error:%d\n", ret);
+				goto err_tll;
+			}
+			clk_enable(omap->usbhost_p1_fck);
+			clk_enable(omap->usbtll_p1_fck);
+		}
+
+		if (is_ehci_phy_mode(pdata->port_mode[1])) {
+			ret = clk_set_parent(omap->utmi_p2_fck,
+						omap->xclk60mhsp2_ck);
+			if (ret != 0) {
+				dev_err(dev, "xclk60mhsp1_ck set parent"
+					"failed error:%d\n", ret);
+				goto err_tll;
+			}
+		} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
+			ret = clk_set_parent(omap->utmi_p2_fck,
+						omap->init_60m_fclk);
+			if (ret != 0) {
+				dev_err(dev, "init_60m_fclk set parent"
+				"failed error:%d\n", ret);
+				goto err_tll;
+			}
+			clk_enable(omap->usbhost_p2_fck);
+			clk_enable(omap->usbtll_p2_fck);
+		}
+
+		clk_enable(omap->utmi_p1_fck);
+		clk_enable(omap->utmi_p2_fck);
+
+		if (is_ehci_tll_mode(pdata->port_mode[0]) ||
+			(is_ohci_port(pdata->port_mode[0])))
+			reg |= OMAP4_P1_MODE_TLL;
+		else if (is_ehci_hsic_mode(pdata->port_mode[0]))
+			reg |= OMAP4_P1_MODE_HSIC;
+
+		if (is_ehci_tll_mode(pdata->port_mode[1]) ||
+			(is_ohci_port(pdata->port_mode[1])))
+			reg |= OMAP4_P2_MODE_TLL;
+		else if (is_ehci_hsic_mode(pdata->port_mode[1]))
+			reg |= OMAP4_P2_MODE_HSIC;
+	}
+
+	usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
+	dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
+
+	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
+		is_ehci_tll_mode(pdata->port_mode[1]) ||
+		is_ehci_tll_mode(pdata->port_mode[2]) ||
+		(is_ohci_port(pdata->port_mode[0])) ||
+		(is_ohci_port(pdata->port_mode[1])) ||
+		(is_ohci_port(pdata->port_mode[2]))) {
+
+		/* Enable UTMI mode for required TLL channels */
+		if (is_omap_usbhs_rev2(omap))
+			usbhs_omap_tll_init(dev, OMAP_REV2_TLL_CHANNEL_COUNT);
+		else
+			usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
+	}
+
+	if (pdata->ehci_data->phy_reset) {
+		/* Hold the PHY in RESET for enough time till
+		 * PHY is settled and ready
+		 */
+		udelay(10);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+			gpio_set_value
+				(pdata->ehci_data->reset_gpio_port[0], 0);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+			gpio_set_value
+				(pdata->ehci_data->reset_gpio_port[1], 0);
+	}
+
+end_count:
+	omap->count++;
+	goto end_enable;
+
+err_tll:
+	if (pdata->ehci_data->phy_reset) {
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+	}
+
+	clk_disable(omap->usbtll_ick);
+	clk_disable(omap->usbtll_fck);
+	clk_disable(omap->usbhost_fs_fck);
+	clk_disable(omap->usbhost_hs_fck);
+	clk_disable(omap->usbhost_ick);
+
+end_enable:
+	spin_unlock_irqrestore(&omap->lock, flags);
+	return ret;
+}
+
+static void usbhs_disable(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	unsigned long			flags = 0;
+	unsigned long			timeout;
+
+	dev_dbg(dev, "stopping TI HSUSB Controller\n");
+
+	spin_lock_irqsave(&omap->lock, flags);
+
+	if (omap->count == 0)
+		goto end_disble;
+
+	omap->count--;
+
+	if (omap->count != 0)
+		goto end_disble;
+
+	/* Reset OMAP modules for insmod/rmmod to work */
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
+			is_omap_usbhs_rev2(omap) ?
+			OMAP4_UHH_SYSCONFIG_SOFTRESET :
+			OMAP_UHH_SYSCONFIG_SOFTRESET);
+
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+				& (1 << 0))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+				& (1 << 1))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+				& (1 << 2))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
+
+	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
+				& (1 << 0))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	if (pdata->ehci_data->phy_reset) {
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+	}
+
+	clk_disable(omap->utmi_p2_fck);
+	clk_disable(omap->utmi_p1_fck);
+	clk_disable(omap->usbtll_ick);
+	clk_disable(omap->usbtll_fck);
+	clk_disable(omap->usbhost_fs_fck);
+	clk_disable(omap->usbhost_hs_fck);
+	clk_disable(omap->usbhost_ick);
+
+end_disble:
+	spin_unlock_irqrestore(&omap->lock, flags);
+}
+
+int omap_usbhs_enable(struct device *dev)
+{
+	return  usbhs_enable(dev->parent);
+}
+EXPORT_SYMBOL_GPL(omap_usbhs_enable);
+
+void omap_usbhs_disable(struct device *dev)
+{
+	usbhs_disable(dev->parent);
+}
+EXPORT_SYMBOL_GPL(omap_usbhs_disable);
+
+static struct platform_driver usbhs_omap_driver = {
+	.driver = {
+		.name		= (char *)usbhs_driver_name,
+		.owner		= THIS_MODULE,
+	},
+	.remove		= __exit_p(usbhs_omap_remove),
+};
+
+MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
+MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
+
+static int __init omap_usbhs_drvinit(void)
+{
+	return platform_driver_probe(&usbhs_omap_driver, usbhs_omap_probe);
+}
+
+/*
+ * init before ehci and ohci drivers;
+ * The usbhs core driver should be initialized much before
+ * the omap ehci and ohci probe functions are called.
+ */
+fs_initcall(omap_usbhs_drvinit);
+
+static void __exit omap_usbhs_drvexit(void)
+{
+	platform_driver_unregister(&usbhs_omap_driver);
+}
+module_exit(omap_usbhs_drvexit);
diff --git a/drivers/mfd/ti-ssp.c b/drivers/mfd/ti-ssp.c
new file mode 100644
index 0000000..af9ab0e
--- /dev/null
+++ b/drivers/mfd/ti-ssp.c
@@ -0,0 +1,476 @@
+/*
+ * Sequencer Serial Port (SSP) driver for Texas Instruments' SoCs
+ *
+ * Copyright (C) 2010 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ti_ssp.h>
+
+/* Register Offsets */
+#define REG_REV		0x00
+#define REG_IOSEL_1	0x04
+#define REG_IOSEL_2	0x08
+#define REG_PREDIV	0x0c
+#define REG_INTR_ST	0x10
+#define REG_INTR_EN	0x14
+#define REG_TEST_CTRL	0x18
+
+/* Per port registers */
+#define PORT_CFG_2	0x00
+#define PORT_ADDR	0x04
+#define PORT_DATA	0x08
+#define PORT_CFG_1	0x0c
+#define PORT_STATE	0x10
+
+#define SSP_PORT_CONFIG_MASK	(SSP_EARLY_DIN | SSP_DELAY_DOUT)
+#define SSP_PORT_CLKRATE_MASK	0x0f
+
+#define SSP_SEQRAM_WR_EN	BIT(4)
+#define SSP_SEQRAM_RD_EN	BIT(5)
+#define SSP_START		BIT(15)
+#define SSP_BUSY		BIT(10)
+#define SSP_PORT_ASL		BIT(7)
+#define SSP_PORT_CFO1		BIT(6)
+
+#define SSP_PORT_SEQRAM_SIZE	32
+
+static const int ssp_port_base[]   = {0x040, 0x080};
+static const int ssp_port_seqram[] = {0x100, 0x180};
+
+struct ti_ssp {
+	struct resource		*res;
+	struct device		*dev;
+	void __iomem		*regs;
+	spinlock_t		lock;
+	struct clk		*clk;
+	int			irq;
+	wait_queue_head_t	wqh;
+
+	/*
+	 * Some of the iosel2 register bits always read-back as 0, we need to
+	 * remember these values so that we don't clobber previously set
+	 * values.
+	 */
+	u32			iosel2;
+};
+
+static inline struct ti_ssp *dev_to_ssp(struct device *dev)
+{
+	return dev_get_drvdata(dev->parent);
+}
+
+static inline int dev_to_port(struct device *dev)
+{
+	return to_platform_device(dev)->id;
+}
+
+/* Register Access Helpers, rmw() functions need to run locked */
+static inline u32 ssp_read(struct ti_ssp *ssp, int reg)
+{
+	return __raw_readl(ssp->regs + reg);
+}
+
+static inline void ssp_write(struct ti_ssp *ssp, int reg, u32 val)
+{
+	__raw_writel(val, ssp->regs + reg);
+}
+
+static inline void ssp_rmw(struct ti_ssp *ssp, int reg, u32 mask, u32 bits)
+{
+	ssp_write(ssp, reg, (ssp_read(ssp, reg) & ~mask) | bits);
+}
+
+static inline u32 ssp_port_read(struct ti_ssp *ssp, int port, int reg)
+{
+	return ssp_read(ssp, ssp_port_base[port] + reg);
+}
+
+static inline void ssp_port_write(struct ti_ssp *ssp, int port, int reg,
+				  u32 val)
+{
+	ssp_write(ssp, ssp_port_base[port] + reg, val);
+}
+
+static inline void ssp_port_rmw(struct ti_ssp *ssp, int port, int reg,
+				u32 mask, u32 bits)
+{
+	ssp_rmw(ssp, ssp_port_base[port] + reg, mask, bits);
+}
+
+static inline void ssp_port_clr_bits(struct ti_ssp *ssp, int port, int reg,
+				     u32 bits)
+{
+	ssp_port_rmw(ssp, port, reg, bits, 0);
+}
+
+static inline void ssp_port_set_bits(struct ti_ssp *ssp, int port, int reg,
+				     u32 bits)
+{
+	ssp_port_rmw(ssp, port, reg, 0, bits);
+}
+
+/* Called to setup port clock mode, caller must hold ssp->lock */
+static int __set_mode(struct ti_ssp *ssp, int port, int mode)
+{
+	mode &= SSP_PORT_CONFIG_MASK;
+	ssp_port_rmw(ssp, port, PORT_CFG_1, SSP_PORT_CONFIG_MASK, mode);
+
+	return 0;
+}
+
+int ti_ssp_set_mode(struct device *dev, int mode)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int ret;
+
+	spin_lock(&ssp->lock);
+	ret = __set_mode(ssp, port, mode);
+	spin_unlock(&ssp->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(ti_ssp_set_mode);
+
+/* Called to setup iosel2, caller must hold ssp->lock */
+static void __set_iosel2(struct ti_ssp *ssp, u32 mask, u32 val)
+{
+	ssp->iosel2 = (ssp->iosel2 & ~mask) | val;
+	ssp_write(ssp, REG_IOSEL_2, ssp->iosel2);
+}
+
+/* Called to setup port iosel, caller must hold ssp->lock */
+static void __set_iosel(struct ti_ssp *ssp, int port, u32 iosel)
+{
+	unsigned val, shift = port ? 16 : 0;
+
+	/* IOSEL1 gets the least significant 16 bits */
+	val = ssp_read(ssp, REG_IOSEL_1);
+	val &= 0xffff << (port ? 0 : 16);
+	val |= (iosel & 0xffff) << (port ? 16 : 0);
+	ssp_write(ssp, REG_IOSEL_1, val);
+
+	/* IOSEL2 gets the most significant 16 bits */
+	val = (iosel >> 16) & 0x7;
+	__set_iosel2(ssp, 0x7 << shift, val << shift);
+}
+
+int ti_ssp_set_iosel(struct device *dev, u32 iosel)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+
+	spin_lock(&ssp->lock);
+	__set_iosel(ssp, port, iosel);
+	spin_unlock(&ssp->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ti_ssp_set_iosel);
+
+int ti_ssp_load(struct device *dev, int offs, u32* prog, int len)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int i;
+
+	if (len > SSP_PORT_SEQRAM_SIZE)
+		return -ENOSPC;
+
+	spin_lock(&ssp->lock);
+
+	/* Enable SeqRAM access */
+	ssp_port_set_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
+
+	/* Copy code */
+	for (i = 0; i < len; i++) {
+		__raw_writel(prog[i], ssp->regs + offs + 4*i +
+			     ssp_port_seqram[port]);
+	}
+
+	/* Disable SeqRAM access */
+	ssp_port_clr_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
+
+	spin_unlock(&ssp->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ti_ssp_load);
+
+int ti_ssp_raw_read(struct device *dev)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int shift = port ? 27 : 11;
+
+	return (ssp_read(ssp, REG_IOSEL_2) >> shift) & 0xf;
+}
+EXPORT_SYMBOL(ti_ssp_raw_read);
+
+int ti_ssp_raw_write(struct device *dev, u32 val)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev), shift;
+
+	spin_lock(&ssp->lock);
+
+	shift = port ? 22 : 6;
+	val &= 0xf;
+	__set_iosel2(ssp, 0xf << shift, val << shift);
+
+	spin_unlock(&ssp->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ti_ssp_raw_write);
+
+static inline int __xfer_done(struct ti_ssp *ssp, int port)
+{
+	return !(ssp_port_read(ssp, port, PORT_CFG_1) & SSP_BUSY);
+}
+
+int ti_ssp_run(struct device *dev, u32 pc, u32 input, u32 *output)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int ret;
+
+	if (pc & ~(0x3f))
+		return -EINVAL;
+
+	/* Grab ssp->lock to serialize rmw on ssp registers */
+	spin_lock(&ssp->lock);
+
+	ssp_port_write(ssp, port, PORT_ADDR, input >> 16);
+	ssp_port_write(ssp, port, PORT_DATA, input & 0xffff);
+	ssp_port_rmw(ssp, port, PORT_CFG_1, 0x3f, pc);
+
+	/* grab wait queue head lock to avoid race with the isr */
+	spin_lock_irq(&ssp->wqh.lock);
+
+	/* kick off sequence execution in hardware */
+	ssp_port_set_bits(ssp, port, PORT_CFG_1, SSP_START);
+
+	/* drop ssp lock; no register writes beyond this */
+	spin_unlock(&ssp->lock);
+
+	ret = wait_event_interruptible_locked_irq(ssp->wqh,
+						  __xfer_done(ssp, port));
+	spin_unlock_irq(&ssp->wqh.lock);
+
+	if (ret < 0)
+		return ret;
+
+	if (output) {
+		*output = (ssp_port_read(ssp, port, PORT_ADDR) << 16) |
+			  (ssp_port_read(ssp, port, PORT_DATA) &  0xffff);
+	}
+
+	ret = ssp_port_read(ssp, port, PORT_STATE) & 0x3f; /* stop address */
+
+	return ret;
+}
+EXPORT_SYMBOL(ti_ssp_run);
+
+static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
+{
+	struct ti_ssp *ssp = dev_data;
+
+	spin_lock(&ssp->wqh.lock);
+
+	ssp_write(ssp, REG_INTR_ST, 0x3);
+	wake_up_locked(&ssp->wqh);
+
+	spin_unlock(&ssp->wqh.lock);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit ti_ssp_probe(struct platform_device *pdev)
+{
+	static struct ti_ssp *ssp;
+	const struct ti_ssp_data *pdata = pdev->dev.platform_data;
+	int error = 0, prediv = 0xff, id;
+	unsigned long sysclk;
+	struct device *dev = &pdev->dev;
+	struct mfd_cell cells[2];
+
+	ssp = kzalloc(sizeof(*ssp), GFP_KERNEL);
+	if (!ssp) {
+		dev_err(dev, "cannot allocate device info\n");
+		return -ENOMEM;
+	}
+
+	ssp->dev = dev;
+	dev_set_drvdata(dev, ssp);
+
+	ssp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ssp->res) {
+		error = -ENODEV;
+		dev_err(dev, "cannot determine register area\n");
+		goto error_res;
+	}
+
+	if (!request_mem_region(ssp->res->start, resource_size(ssp->res),
+				pdev->name)) {
+		error = -ENOMEM;
+		dev_err(dev, "cannot claim register memory\n");
+		goto error_res;
+	}
+
+	ssp->regs = ioremap(ssp->res->start, resource_size(ssp->res));
+	if (!ssp->regs) {
+		error = -ENOMEM;
+		dev_err(dev, "cannot map register memory\n");
+		goto error_map;
+	}
+
+	ssp->clk = clk_get(dev, NULL);
+	if (IS_ERR(ssp->clk)) {
+		error = PTR_ERR(ssp->clk);
+		dev_err(dev, "cannot claim device clock\n");
+		goto error_clk;
+	}
+
+	ssp->irq = platform_get_irq(pdev, 0);
+	if (ssp->irq < 0) {
+		error = -ENODEV;
+		dev_err(dev, "unknown irq\n");
+		goto error_irq;
+	}
+
+	error = request_threaded_irq(ssp->irq, NULL, ti_ssp_interrupt, 0,
+				     dev_name(dev), ssp);
+	if (error < 0) {
+		dev_err(dev, "cannot acquire irq\n");
+		goto error_irq;
+	}
+
+	spin_lock_init(&ssp->lock);
+	init_waitqueue_head(&ssp->wqh);
+
+	/* Power on and initialize SSP */
+	error = clk_enable(ssp->clk);
+	if (error) {
+		dev_err(dev, "cannot enable device clock\n");
+		goto error_enable;
+	}
+
+	/* Reset registers to a sensible known state */
+	ssp_write(ssp, REG_IOSEL_1, 0);
+	ssp_write(ssp, REG_IOSEL_2, 0);
+	ssp_write(ssp, REG_INTR_EN, 0x3);
+	ssp_write(ssp, REG_INTR_ST, 0x3);
+	ssp_write(ssp, REG_TEST_CTRL, 0);
+	ssp_port_write(ssp, 0, PORT_CFG_1, SSP_PORT_ASL);
+	ssp_port_write(ssp, 1, PORT_CFG_1, SSP_PORT_ASL);
+	ssp_port_write(ssp, 0, PORT_CFG_2, SSP_PORT_CFO1);
+	ssp_port_write(ssp, 1, PORT_CFG_2, SSP_PORT_CFO1);
+
+	sysclk = clk_get_rate(ssp->clk);
+	if (pdata && pdata->out_clock)
+		prediv = (sysclk / pdata->out_clock) - 1;
+	prediv = clamp(prediv, 0, 0xff);
+	ssp_rmw(ssp, REG_PREDIV, 0xff, prediv);
+
+	memset(cells, 0, sizeof(cells));
+	for (id = 0; id < 2; id++) {
+		const struct ti_ssp_dev_data *data = &pdata->dev_data[id];
+
+		cells[id].id		= id;
+		cells[id].name		= data->dev_name;
+		cells[id].platform_data	= data->pdata;
+		cells[id].data_size	= data->pdata_size;
+	}
+
+	error = mfd_add_devices(dev, 0, cells, 2, NULL, 0);
+	if (error < 0) {
+		dev_err(dev, "cannot add mfd cells\n");
+		goto error_enable;
+	}
+
+	return 0;
+
+error_enable:
+	free_irq(ssp->irq, ssp);
+error_irq:
+	clk_put(ssp->clk);
+error_clk:
+	iounmap(ssp->regs);
+error_map:
+	release_mem_region(ssp->res->start, resource_size(ssp->res));
+error_res:
+	kfree(ssp);
+	return error;
+}
+
+static int __devexit ti_ssp_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ti_ssp *ssp = dev_get_drvdata(dev);
+
+	mfd_remove_devices(dev);
+	clk_disable(ssp->clk);
+	free_irq(ssp->irq, ssp);
+	clk_put(ssp->clk);
+	iounmap(ssp->regs);
+	release_mem_region(ssp->res->start, resource_size(ssp->res));
+	kfree(ssp);
+	dev_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver ti_ssp_driver = {
+	.probe		= ti_ssp_probe,
+	.remove		= __devexit_p(ti_ssp_remove),
+	.driver		= {
+		.name	= "ti-ssp",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init ti_ssp_init(void)
+{
+	return platform_driver_register(&ti_ssp_driver);
+}
+module_init(ti_ssp_init);
+
+static void __exit ti_ssp_exit(void)
+{
+	platform_driver_unregister(&ti_ssp_driver);
+}
+module_exit(ti_ssp_exit);
+
+MODULE_DESCRIPTION("Sequencer Serial Port (SSP) Driver");
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ti-ssp");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index cc8e49d..4e007c6 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -2,6 +2,14 @@
 # Misc strange devices
 #
 
+# This one has to live outside of the MISC_DEVICES conditional,
+# because it may be selected by drivers/platform/x86/hp_accel.
+config SENSORS_LIS3LV02D
+	tristate
+	depends on INPUT
+	select INPUT_POLLDEV
+	default n
+
 menuconfig MISC_DEVICES
 	bool "Misc devices"
 	---help---
@@ -394,6 +402,16 @@ config DS1682
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1682.
 
+config SPEAR13XX_PCIE_GADGET
+	bool "PCIe gadget support for SPEAr13XX platform"
+	depends on ARCH_SPEAR13XX
+	default n
+	help
+	 This option enables gadget support for PCIe controller. If
+	 board file defines any controller as PCIe endpoint then a sysfs
+	 entry will be created for that controller. User can use these
+	 sysfs node to configure PCIe EP as per his requirements.
+
 config TI_DAC7512
 	tristate "Texas Instruments DAC7512"
 	depends on SPI && SYSFS
@@ -441,7 +459,7 @@ config BMP085
 	  module will be called bmp085.
 
 config PCH_PHUB
-	tristate "PCH Packet Hub of Intel Topcliff"
+	tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213"
 	depends on PCI
 	help
 	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -449,6 +467,11 @@ config PCH_PHUB
 	  processor. The Topcliff has MAC address and Option ROM data in SROM.
 	  This driver can access MAC address and Option ROM data in SROM.
 
+	  This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
+	  for IVI(In-Vehicle Infotainment) use.
+	  ML7213 is companion chip for Intel Atom E6xx series.
+	  ML7213 is completely compatible for Intel EG20T PCH.
+
 	  To compile this driver as a module, choose M here: the module will
 	  be called pch_phub.
 
@@ -457,5 +480,6 @@ source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
 source "drivers/misc/iwmc3200top/Kconfig"
 source "drivers/misc/ti-st/Kconfig"
+source "drivers/misc/lis3lv02d/Kconfig"
 
 endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 98009cc..f546860 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -37,8 +37,10 @@ obj-$(CONFIG_IWMC3200TOP)      += iwmc3200top/
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
+obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)	+= spear13xx_pcie_gadget.o
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)	+= arm-charlcd.o
 obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
 obj-y				+= ti-st/
 obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
+obj-y				+= lis3lv02d/
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
index 644d4cd..81db781 100644
--- a/drivers/misc/apds9802als.c
+++ b/drivers/misc/apds9802als.c
@@ -245,9 +245,8 @@ static int apds9802als_probe(struct i2c_client *client,
 	als_set_default_config(client);
 	mutex_init(&data->mutex);
 
+	pm_runtime_set_active(&client->dev);
 	pm_runtime_enable(&client->dev);
-	pm_runtime_get(&client->dev);
-	pm_runtime_put(&client->dev);
 
 	return res;
 als_error1:
@@ -255,12 +254,19 @@ als_error1:
 	return res;
 }
 
-static int apds9802als_remove(struct i2c_client *client)
+static int __devexit apds9802als_remove(struct i2c_client *client)
 {
 	struct als_data *data = i2c_get_clientdata(client);
 
+	pm_runtime_get_sync(&client->dev);
+
 	als_set_power_state(client, false);
 	sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+	pm_runtime_put_noidle(&client->dev);
+
 	kfree(data);
 	return 0;
 }
@@ -275,9 +281,6 @@ static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg)
 static int apds9802als_resume(struct i2c_client *client)
 {
 	als_set_default_config(client);
-
-	pm_runtime_get(&client->dev);
-	pm_runtime_put(&client->dev);
 	return 0;
 }
 
@@ -323,7 +326,7 @@ static struct i2c_driver apds9802als_driver = {
 		.pm = APDS9802ALS_PM_OPS,
 	},
 	.probe = apds9802als_probe,
-	.remove = apds9802als_remove,
+	.remove = __devexit_p(apds9802als_remove),
 	.suspend = apds9802als_suspend,
 	.resume = apds9802als_resume,
 	.id_table = apds9802als_id,
diff --git a/drivers/misc/atmel_tclib.c b/drivers/misc/atmel_tclib.c
index 3891124..a844810 100644
--- a/drivers/misc/atmel_tclib.c
+++ b/drivers/misc/atmel_tclib.c
@@ -75,7 +75,7 @@ out:
 	return tc;
 
 fail_ioremap:
-	release_resource(r);
+	release_mem_region(r->start, ATMEL_TC_IOMEM_SIZE);
 fail:
 	tc = NULL;
 	goto out;
@@ -95,7 +95,7 @@ void atmel_tc_free(struct atmel_tc *tc)
 	spin_lock(&tc_list_lock);
 	if (tc->regs) {
 		iounmap(tc->regs);
-		release_resource(tc->iomem);
+		release_mem_region(tc->iomem->start, ATMEL_TC_IOMEM_SIZE);
 		tc->regs = NULL;
 		tc->iomem = NULL;
 	}
diff --git a/drivers/misc/bh1780gli.c b/drivers/misc/bh1780gli.c
index d5f3a3f..d07cd67 100644
--- a/drivers/misc/bh1780gli.c
+++ b/drivers/misc/bh1780gli.c
@@ -196,10 +196,11 @@ static int __devexit bh1780_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int bh1780_suspend(struct i2c_client *client, pm_message_t mesg)
+static int bh1780_suspend(struct device *dev)
 {
 	struct bh1780_data *ddata;
 	int state, ret;
+	struct i2c_client *client = to_i2c_client(dev);
 
 	ddata = i2c_get_clientdata(client);
 	state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL");
@@ -217,14 +218,14 @@ static int bh1780_suspend(struct i2c_client *client, pm_message_t mesg)
 	return 0;
 }
 
-static int bh1780_resume(struct i2c_client *client)
+static int bh1780_resume(struct device *dev)
 {
 	struct bh1780_data *ddata;
 	int state, ret;
+	struct i2c_client *client = to_i2c_client(dev);
 
 	ddata = i2c_get_clientdata(client);
 	state = ddata->power_state;
-
 	ret = bh1780_write(ddata, BH1780_REG_CONTROL, state,
 				"CONTROL");
 
@@ -233,9 +234,10 @@ static int bh1780_resume(struct i2c_client *client)
 
 	return 0;
 }
+static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume);
+#define BH1780_PMOPS (&bh1780_pm)
 #else
-#define bh1780_suspend NULL
-#define bh1780_resume NULL
+#define BH1780_PMOPS NULL
 #endif /* CONFIG_PM */
 
 static const struct i2c_device_id bh1780_id[] = {
@@ -247,11 +249,10 @@ static struct i2c_driver bh1780_driver = {
 	.probe		= bh1780_probe,
 	.remove		= bh1780_remove,
 	.id_table	= bh1780_id,
-	.suspend	= bh1780_suspend,
-	.resume		= bh1780_resume,
 	.driver = {
-		.name = "bh1780"
-	},
+		.name = "bh1780",
+		.pm	= BH1780_PMOPS,
+},
 };
 
 static int __init bh1780_init(void)
diff --git a/drivers/misc/bmp085.c b/drivers/misc/bmp085.c
index b6e1c9a..ecd276a 100644
--- a/drivers/misc/bmp085.c
+++ b/drivers/misc/bmp085.c
@@ -402,7 +402,7 @@ exit:
 	return status;
 }
 
-static int bmp085_probe(struct i2c_client *client,
+static int __devinit bmp085_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct bmp085_data *data;
@@ -438,7 +438,7 @@ exit:
 	return err;
 }
 
-static int bmp085_remove(struct i2c_client *client)
+static int __devexit bmp085_remove(struct i2c_client *client)
 {
 	sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
 	kfree(i2c_get_clientdata(client));
@@ -458,7 +458,7 @@ static struct i2c_driver bmp085_driver = {
 	},
 	.id_table	= bmp085_id,
 	.probe		= bmp085_probe,
-	.remove		= bmp085_remove,
+	.remove		= __devexit_p(bmp085_remove),
 
 	.detect		= bmp085_detect,
 	.address_list	= normal_i2c
diff --git a/drivers/misc/cb710/Makefile b/drivers/misc/cb710/Makefile
index 7b80cbf..467c8e9 100644
--- a/drivers/misc/cb710/Makefile
+++ b/drivers/misc/cb710/Makefile
@@ -1,6 +1,4 @@
-ifeq ($(CONFIG_CB710_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_CB710_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_CB710_CORE)	+= cb710.o
 
diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c
index 46b3439..16d7179 100644
--- a/drivers/misc/ep93xx_pwm.c
+++ b/drivers/misc/ep93xx_pwm.c
@@ -249,11 +249,11 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev,
 
 static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
 static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
-static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
-static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
-static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
 
 static struct attribute *ep93xx_pwm_attrs[] = {
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c
index 234bfca..ca938fc 100644
--- a/drivers/misc/hmc6352.c
+++ b/drivers/misc/hmc6352.c
@@ -75,7 +75,7 @@ static ssize_t compass_heading_data_show(struct device *dev,
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	unsigned char i2c_data[2];
-	unsigned int ret;
+	int ret;
 
 	mutex_lock(&compass_mutex);
 	ret = compass_command(client, 'A');
@@ -86,7 +86,7 @@ static ssize_t compass_heading_data_show(struct device *dev,
 	msleep(10); /* sending 'A' cmd we need to wait for 7-10 millisecs */
 	ret = i2c_master_recv(client, i2c_data, 2);
 	mutex_unlock(&compass_mutex);
-	if (ret != 1) {
+	if (ret < 0) {
 		dev_warn(dev, "i2c read data cmd failed\n");
 		return ret;
 	}
diff --git a/drivers/misc/iwmc3200top/iwmc3200top.h b/drivers/misc/iwmc3200top/iwmc3200top.h
index 740ff07..620973e 100644
--- a/drivers/misc/iwmc3200top/iwmc3200top.h
+++ b/drivers/misc/iwmc3200top/iwmc3200top.h
@@ -183,9 +183,7 @@ struct iwmct_priv {
 	u32 barker;
 	struct iwmct_dbg dbg;
 
-	/* drivers work queue */
-	struct workqueue_struct *wq;
-	struct workqueue_struct *bus_rescan_wq;
+	/* drivers work items */
 	struct work_struct bus_rescan_worker;
 	struct work_struct isr_worker;
 
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
index c73cef2..727af07 100644
--- a/drivers/misc/iwmc3200top/main.c
+++ b/drivers/misc/iwmc3200top/main.c
@@ -89,7 +89,7 @@ static void op_top_message(struct iwmct_priv *priv, struct top_msg *msg)
 	switch (msg->hdr.opcode) {
 	case OP_OPR_ALIVE:
 		LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n");
-		queue_work(priv->bus_rescan_wq, &priv->bus_rescan_worker);
+		schedule_work(&priv->bus_rescan_worker);
 		break;
 	default:
 		LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n",
@@ -360,7 +360,7 @@ static void iwmct_irq(struct sdio_func *func)
 	/* clear the function's interrupt request bit (write 1 to clear) */
 	sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
 
-	queue_work(priv->wq, &priv->isr_worker);
+	schedule_work(&priv->isr_worker);
 
 	LOG_TRACE(priv, IRQ, "exit iwmct_irq\n");
 
@@ -506,10 +506,6 @@ static int iwmct_probe(struct sdio_func *func,
 	priv->func = func;
 	sdio_set_drvdata(func, priv);
 
-
-	/* create drivers work queue */
-	priv->wq = create_workqueue(DRV_NAME "_wq");
-	priv->bus_rescan_wq = create_workqueue(DRV_NAME "_rescan_wq");
 	INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
 	INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);
 
@@ -604,9 +600,9 @@ static void iwmct_remove(struct sdio_func *func)
 	sdio_release_irq(func);
 	sdio_release_host(func);
 
-	/* Safely destroy osc workqueue */
-	destroy_workqueue(priv->bus_rescan_wq);
-	destroy_workqueue(priv->wq);
+	/* Make sure works are finished */
+	flush_work_sync(&priv->bus_rescan_worker);
+	flush_work_sync(&priv->isr_worker);
 
 	sdio_claim_host(func);
 	sdio_disable_func(func);
diff --git a/drivers/misc/lis3lv02d/Kconfig b/drivers/misc/lis3lv02d/Kconfig
new file mode 100644
index 0000000..8f474e6
--- /dev/null
+++ b/drivers/misc/lis3lv02d/Kconfig
@@ -0,0 +1,37 @@
+#
+# STMicroelectonics LIS3LV02D and similar accelerometers
+#
+
+config SENSORS_LIS3_SPI
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
+	depends on !ACPI && SPI_MASTER && INPUT
+	select SENSORS_LIS3LV02D
+	default n
+	help
+	  This driver provides support for the LIS3LV02Dx accelerometer connected
+	  via SPI. The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the laptop to act as a pinball machine-esque joystick.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for the SPI transport
+	  is called lis3lv02d_spi.
+
+config SENSORS_LIS3_I2C
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
+	depends on I2C && INPUT
+	select SENSORS_LIS3LV02D
+	default n
+	help
+	  This driver provides support for the LIS3LV02Dx accelerometer connected
+	  via I2C. The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the device to act as a pinball machine-esque joystick.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for the I2C transport
+	  is called lis3lv02d_i2c.
diff --git a/drivers/misc/lis3lv02d/Makefile b/drivers/misc/lis3lv02d/Makefile
new file mode 100644
index 0000000..4bf58b1
--- /dev/null
+++ b/drivers/misc/lis3lv02d/Makefile
@@ -0,0 +1,7 @@
+#
+# STMicroelectonics LIS3LV02D and similar accelerometers
+#
+
+obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o
+obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d_spi.o
+obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d_i2c.o
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c
new file mode 100644
index 0000000..b928bc1
--- /dev/null
+++ b/drivers/misc/lis3lv02d/lis3lv02d.c
@@ -0,0 +1,999 @@
+/*
+ *  lis3lv02d.c - ST LIS3LV02DL accelerometer driver
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008 Eric Piel
+ *  Copyright (C) 2008-2009 Pavel Machek
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input-polldev.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
+#include <linux/atomic.h>
+#include "lis3lv02d.h"
+
+#define DRIVER_NAME     "lis3lv02d"
+
+/* joystick device poll interval in milliseconds */
+#define MDPS_POLL_INTERVAL 50
+#define MDPS_POLL_MIN	   0
+#define MDPS_POLL_MAX	   2000
+
+#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
+
+#define SELFTEST_OK	       0
+#define SELFTEST_FAIL	       -1
+#define SELFTEST_IRQ	       -2
+
+#define IRQ_LINE0	       0
+#define IRQ_LINE1	       1
+
+/*
+ * The sensor can also generate interrupts (DRDY) but it's pretty pointless
+ * because they are generated even if the data do not change. So it's better
+ * to keep the interrupt for the free-fall event. The values are updated at
+ * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
+ * some low processor, we poll the sensor only at 20Hz... enough for the
+ * joystick.
+ */
+
+#define LIS3_PWRON_DELAY_WAI_12B	(5000)
+#define LIS3_PWRON_DELAY_WAI_8B		(3000)
+
+/*
+ * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
+ * LIS302D spec says: 18 mG / digit
+ * LIS3_ACCURACY is used to increase accuracy of the intermediate
+ * calculation results.
+ */
+#define LIS3_ACCURACY			1024
+/* Sensitivity values for -2G +2G scale */
+#define LIS3_SENSITIVITY_12B		((LIS3_ACCURACY * 1000) / 1024)
+#define LIS3_SENSITIVITY_8B		(18 * LIS3_ACCURACY)
+
+#define LIS3_DEFAULT_FUZZ_12B		3
+#define LIS3_DEFAULT_FLAT_12B		3
+#define LIS3_DEFAULT_FUZZ_8B		1
+#define LIS3_DEFAULT_FLAT_8B		1
+
+struct lis3lv02d lis3_dev = {
+	.misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
+};
+EXPORT_SYMBOL_GPL(lis3_dev);
+
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+	int ret = param_set_int(val, kp);
+	if (!ret) {
+		int val = *(int *)kp->arg;
+		if (val < 0)
+			val = -val;
+		if (!val || val > 3)
+			return -EINVAL;
+	}
+	return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+	.set = param_set_axis,
+	.get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
+static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
+{
+	s8 lo;
+	if (lis3->read(lis3, reg, &lo) < 0)
+		return 0;
+
+	return lo;
+}
+
+static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
+{
+	u8 lo, hi;
+
+	lis3->read(lis3, reg - 1, &lo);
+	lis3->read(lis3, reg, &hi);
+	/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
+	return (s16)((hi << 8) | lo);
+}
+
+/**
+ * lis3lv02d_get_axis - For the given axis, give the value converted
+ * @axis:      1,2,3 - can also be negative
+ * @hw_values: raw values returned by the hardware
+ *
+ * Returns the converted value.
+ */
+static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
+{
+	if (axis > 0)
+		return hw_values[axis - 1];
+	else
+		return -hw_values[-axis - 1];
+}
+
+/**
+ * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
+ * @lis3: pointer to the device struct
+ * @x:    where to store the X axis value
+ * @y:    where to store the Y axis value
+ * @z:    where to store the Z axis value
+ *
+ * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
+ */
+static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
+{
+	int position[3];
+	int i;
+
+	if (lis3->blkread) {
+		if (lis3_dev.whoami == WAI_12B) {
+			u16 data[3];
+			lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
+			for (i = 0; i < 3; i++)
+				position[i] = (s16)le16_to_cpu(data[i]);
+		} else {
+			u8 data[5];
+			/* Data: x, dummy, y, dummy, z */
+			lis3->blkread(lis3, OUTX, 5, data);
+			for (i = 0; i < 3; i++)
+				position[i] = (s8)data[i * 2];
+		}
+	} else {
+		position[0] = lis3->read_data(lis3, OUTX);
+		position[1] = lis3->read_data(lis3, OUTY);
+		position[2] = lis3->read_data(lis3, OUTZ);
+	}
+
+	for (i = 0; i < 3; i++)
+		position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
+
+	*x = lis3lv02d_get_axis(lis3->ac.x, position);
+	*y = lis3lv02d_get_axis(lis3->ac.y, position);
+	*z = lis3lv02d_get_axis(lis3->ac.z, position);
+}
+
+/* conversion btw sampling rate and the register values */
+static int lis3_12_rates[4] = {40, 160, 640, 2560};
+static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
+
+/* ODR is Output Data Rate */
+static int lis3lv02d_get_odr(void)
+{
+	u8 ctrl;
+	int shift;
+
+	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
+	ctrl &= lis3_dev.odr_mask;
+	shift = ffs(lis3_dev.odr_mask) - 1;
+	return lis3_dev.odrs[(ctrl >> shift)];
+}
+
+static int lis3lv02d_set_odr(int rate)
+{
+	u8 ctrl;
+	int i, len, shift;
+
+	if (!rate)
+		return -EINVAL;
+
+	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
+	ctrl &= ~lis3_dev.odr_mask;
+	len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
+	shift = ffs(lis3_dev.odr_mask) - 1;
+
+	for (i = 0; i < len; i++)
+		if (lis3_dev.odrs[i] == rate) {
+			lis3_dev.write(&lis3_dev, CTRL_REG1,
+					ctrl | (i << shift));
+			return 0;
+		}
+	return -EINVAL;
+}
+
+static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
+{
+	u8 ctlreg, reg;
+	s16 x, y, z;
+	u8 selftest;
+	int ret;
+	u8 ctrl_reg_data;
+	unsigned char irq_cfg;
+
+	mutex_lock(&lis3->mutex);
+
+	irq_cfg = lis3->irq_cfg;
+	if (lis3_dev.whoami == WAI_8B) {
+		lis3->data_ready_count[IRQ_LINE0] = 0;
+		lis3->data_ready_count[IRQ_LINE1] = 0;
+
+		/* Change interrupt cfg to data ready for selftest */
+		atomic_inc(&lis3_dev.wake_thread);
+		lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
+		lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
+		lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
+				~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
+				(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
+	}
+
+	if (lis3_dev.whoami == WAI_3DC) {
+		ctlreg = CTRL_REG4;
+		selftest = CTRL4_ST0;
+	} else {
+		ctlreg = CTRL_REG1;
+		if (lis3_dev.whoami == WAI_12B)
+			selftest = CTRL1_ST;
+		else
+			selftest = CTRL1_STP;
+	}
+
+	lis3->read(lis3, ctlreg, &reg);
+	lis3->write(lis3, ctlreg, (reg | selftest));
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	/* Read directly to avoid axis remap */
+	x = lis3->read_data(lis3, OUTX);
+	y = lis3->read_data(lis3, OUTY);
+	z = lis3->read_data(lis3, OUTZ);
+
+	/* back to normal settings */
+	lis3->write(lis3, ctlreg, reg);
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	results[0] = x - lis3->read_data(lis3, OUTX);
+	results[1] = y - lis3->read_data(lis3, OUTY);
+	results[2] = z - lis3->read_data(lis3, OUTZ);
+
+	ret = 0;
+
+	if (lis3_dev.whoami == WAI_8B) {
+		/* Restore original interrupt configuration */
+		atomic_dec(&lis3_dev.wake_thread);
+		lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
+		lis3->irq_cfg = irq_cfg;
+
+		if ((irq_cfg & LIS3_IRQ1_MASK) &&
+			lis3->data_ready_count[IRQ_LINE0] < 2) {
+			ret = SELFTEST_IRQ;
+			goto fail;
+		}
+
+		if ((irq_cfg & LIS3_IRQ2_MASK) &&
+			lis3->data_ready_count[IRQ_LINE1] < 2) {
+			ret = SELFTEST_IRQ;
+			goto fail;
+		}
+	}
+
+	if (lis3->pdata) {
+		int i;
+		for (i = 0; i < 3; i++) {
+			/* Check against selftest acceptance limits */
+			if ((results[i] < lis3->pdata->st_min_limits[i]) ||
+			    (results[i] > lis3->pdata->st_max_limits[i])) {
+				ret = SELFTEST_FAIL;
+				goto fail;
+			}
+		}
+	}
+
+	/* test passed */
+fail:
+	mutex_unlock(&lis3->mutex);
+	return ret;
+}
+
+/*
+ * Order of registers in the list affects to order of the restore process.
+ * Perhaps it is a good idea to set interrupt enable register as a last one
+ * after all other configurations
+ */
+static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
+			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
+			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
+			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
+			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
+
+static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
+			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
+			       DD_THSE_L, DD_THSE_H,
+			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
+
+static inline void lis3_context_save(struct lis3lv02d *lis3)
+{
+	int i;
+	for (i = 0; i < lis3->regs_size; i++)
+		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
+	lis3->regs_stored = true;
+}
+
+static inline void lis3_context_restore(struct lis3lv02d *lis3)
+{
+	int i;
+	if (lis3->regs_stored)
+		for (i = 0; i < lis3->regs_size; i++)
+			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
+}
+
+void lis3lv02d_poweroff(struct lis3lv02d *lis3)
+{
+	if (lis3->reg_ctrl)
+		lis3_context_save(lis3);
+	/* disable X,Y,Z axis and power down */
+	lis3->write(lis3, CTRL_REG1, 0x00);
+	if (lis3->reg_ctrl)
+		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
+
+void lis3lv02d_poweron(struct lis3lv02d *lis3)
+{
+	u8 reg;
+
+	lis3->init(lis3);
+
+	/*
+	 * Common configuration
+	 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
+	 *      both have been read. So the value read will always be correct.
+	 * Set BOOT bit to refresh factory tuning values.
+	 */
+	lis3->read(lis3, CTRL_REG2, &reg);
+	if (lis3->whoami ==  WAI_12B)
+		reg |= CTRL2_BDU | CTRL2_BOOT;
+	else
+		reg |= CTRL2_BOOT_8B;
+	lis3->write(lis3, CTRL_REG2, reg);
+
+	/* LIS3 power on delay is quite long */
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	if (lis3->reg_ctrl)
+		lis3_context_restore(lis3);
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
+
+
+static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
+{
+	int x, y, z;
+
+	mutex_lock(&lis3_dev.mutex);
+	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+	input_report_abs(pidev->input, ABS_X, x);
+	input_report_abs(pidev->input, ABS_Y, y);
+	input_report_abs(pidev->input, ABS_Z, z);
+	input_sync(pidev->input);
+	mutex_unlock(&lis3_dev.mutex);
+}
+
+static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
+{
+	if (lis3_dev.pm_dev)
+		pm_runtime_get_sync(lis3_dev.pm_dev);
+
+	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
+		atomic_set(&lis3_dev.wake_thread, 1);
+	/*
+	 * Update coordinates for the case where poll interval is 0 and
+	 * the chip in running purely under interrupt control
+	 */
+	lis3lv02d_joystick_poll(pidev);
+}
+
+static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
+{
+	atomic_set(&lis3_dev.wake_thread, 0);
+	if (lis3_dev.pm_dev)
+		pm_runtime_put(lis3_dev.pm_dev);
+}
+
+static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+{
+	if (!test_bit(0, &lis3_dev.misc_opened))
+		goto out;
+
+	/*
+	 * Be careful: on some HP laptops the bios force DD when on battery and
+	 * the lid is closed. This leads to interrupts as soon as a little move
+	 * is done.
+	 */
+	atomic_inc(&lis3_dev.count);
+
+	wake_up_interruptible(&lis3_dev.misc_wait);
+	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+out:
+	if (atomic_read(&lis3_dev.wake_thread))
+		return IRQ_WAKE_THREAD;
+	return IRQ_HANDLED;
+}
+
+static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
+{
+	struct input_dev *dev = lis3->idev->input;
+	u8 click_src;
+
+	mutex_lock(&lis3->mutex);
+	lis3->read(lis3, CLICK_SRC, &click_src);
+
+	if (click_src & CLICK_SINGLE_X) {
+		input_report_key(dev, lis3->mapped_btns[0], 1);
+		input_report_key(dev, lis3->mapped_btns[0], 0);
+	}
+
+	if (click_src & CLICK_SINGLE_Y) {
+		input_report_key(dev, lis3->mapped_btns[1], 1);
+		input_report_key(dev, lis3->mapped_btns[1], 0);
+	}
+
+	if (click_src & CLICK_SINGLE_Z) {
+		input_report_key(dev, lis3->mapped_btns[2], 1);
+		input_report_key(dev, lis3->mapped_btns[2], 0);
+	}
+	input_sync(dev);
+	mutex_unlock(&lis3->mutex);
+}
+
+static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
+{
+	int dummy;
+
+	/* Dummy read to ack interrupt */
+	lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
+	lis3->data_ready_count[index]++;
+}
+
+static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
+{
+	struct lis3lv02d *lis3 = data;
+	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
+
+	if (irq_cfg == LIS3_IRQ1_CLICK)
+		lis302dl_interrupt_handle_click(lis3);
+	else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
+		lis302dl_data_ready(lis3, IRQ_LINE0);
+	else
+		lis3lv02d_joystick_poll(lis3->idev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
+{
+	struct lis3lv02d *lis3 = data;
+	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
+
+	if (irq_cfg == LIS3_IRQ2_CLICK)
+		lis302dl_interrupt_handle_click(lis3);
+	else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
+		lis302dl_data_ready(lis3, IRQ_LINE1);
+	else
+		lis3lv02d_joystick_poll(lis3->idev);
+
+	return IRQ_HANDLED;
+}
+
+static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &lis3_dev.misc_opened))
+		return -EBUSY; /* already open */
+
+	if (lis3_dev.pm_dev)
+		pm_runtime_get_sync(lis3_dev.pm_dev);
+
+	atomic_set(&lis3_dev.count, 0);
+	return 0;
+}
+
+static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
+{
+	fasync_helper(-1, file, 0, &lis3_dev.async_queue);
+	clear_bit(0, &lis3_dev.misc_opened); /* release the device */
+	if (lis3_dev.pm_dev)
+		pm_runtime_put(lis3_dev.pm_dev);
+	return 0;
+}
+
+static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
+				size_t count, loff_t *pos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	u32 data;
+	unsigned char byte_data;
+	ssize_t retval = 1;
+
+	if (count < 1)
+		return -EINVAL;
+
+	add_wait_queue(&lis3_dev.misc_wait, &wait);
+	while (true) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		data = atomic_xchg(&lis3_dev.count, 0);
+		if (data)
+			break;
+
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+
+		schedule();
+	}
+
+	if (data < 255)
+		byte_data = data;
+	else
+		byte_data = 255;
+
+	/* make sure we are not going into copy_to_user() with
+	 * TASK_INTERRUPTIBLE state */
+	set_current_state(TASK_RUNNING);
+	if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
+		retval = -EFAULT;
+
+out:
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&lis3_dev.misc_wait, &wait);
+
+	return retval;
+}
+
+static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &lis3_dev.misc_wait, wait);
+	if (atomic_read(&lis3_dev.count))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
+{
+	return fasync_helper(fd, file, on, &lis3_dev.async_queue);
+}
+
+static const struct file_operations lis3lv02d_misc_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = lis3lv02d_misc_read,
+	.open    = lis3lv02d_misc_open,
+	.release = lis3lv02d_misc_release,
+	.poll    = lis3lv02d_misc_poll,
+	.fasync  = lis3lv02d_misc_fasync,
+};
+
+static struct miscdevice lis3lv02d_misc_device = {
+	.minor   = MISC_DYNAMIC_MINOR,
+	.name    = "freefall",
+	.fops    = &lis3lv02d_misc_fops,
+};
+
+int lis3lv02d_joystick_enable(void)
+{
+	struct input_dev *input_dev;
+	int err;
+	int max_val, fuzz, flat;
+	int btns[] = {BTN_X, BTN_Y, BTN_Z};
+
+	if (lis3_dev.idev)
+		return -EINVAL;
+
+	lis3_dev.idev = input_allocate_polled_device();
+	if (!lis3_dev.idev)
+		return -ENOMEM;
+
+	lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+	lis3_dev.idev->open = lis3lv02d_joystick_open;
+	lis3_dev.idev->close = lis3lv02d_joystick_close;
+	lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
+	lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
+	lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
+	input_dev = lis3_dev.idev->input;
+
+	input_dev->name       = "ST LIS3LV02DL Accelerometer";
+	input_dev->phys       = DRIVER_NAME "/input0";
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor  = 0;
+	input_dev->dev.parent = &lis3_dev.pdev->dev;
+
+	set_bit(EV_ABS, input_dev->evbit);
+	max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
+	if (lis3_dev.whoami == WAI_12B) {
+		fuzz = LIS3_DEFAULT_FUZZ_12B;
+		flat = LIS3_DEFAULT_FLAT_12B;
+	} else {
+		fuzz = LIS3_DEFAULT_FUZZ_8B;
+		flat = LIS3_DEFAULT_FLAT_8B;
+	}
+	fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
+	flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+
+	input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
+	input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
+	input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
+
+	lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
+	lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
+	lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
+
+	err = input_register_polled_device(lis3_dev.idev);
+	if (err) {
+		input_free_polled_device(lis3_dev.idev);
+		lis3_dev.idev = NULL;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
+
+void lis3lv02d_joystick_disable(void)
+{
+	if (lis3_dev.irq)
+		free_irq(lis3_dev.irq, &lis3_dev);
+	if (lis3_dev.pdata && lis3_dev.pdata->irq2)
+		free_irq(lis3_dev.pdata->irq2, &lis3_dev);
+
+	if (!lis3_dev.idev)
+		return;
+
+	if (lis3_dev.irq)
+		misc_deregister(&lis3lv02d_misc_device);
+	input_unregister_polled_device(lis3_dev.idev);
+	input_free_polled_device(lis3_dev.idev);
+	lis3_dev.idev = NULL;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
+
+/* Sysfs stuff */
+static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
+{
+	/*
+	 * SYSFS functions are fast visitors so put-call
+	 * immediately after the get-call. However, keep
+	 * chip running for a while and schedule delayed
+	 * suspend. This way periodic sysfs calls doesn't
+	 * suffer from relatively long power up time.
+	 */
+
+	if (lis3->pm_dev) {
+		pm_runtime_get_sync(lis3->pm_dev);
+		pm_runtime_put_noidle(lis3->pm_dev);
+		pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
+	}
+}
+
+static ssize_t lis3lv02d_selftest_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	s16 values[3];
+
+	static const char ok[] = "OK";
+	static const char fail[] = "FAIL";
+	static const char irq[] = "FAIL_IRQ";
+	const char *res;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	switch (lis3lv02d_selftest(&lis3_dev, values)) {
+	case SELFTEST_FAIL:
+		res = fail;
+		break;
+	case SELFTEST_IRQ:
+		res = irq;
+		break;
+	case SELFTEST_OK:
+	default:
+		res = ok;
+		break;
+	}
+	return sprintf(buf, "%s %d %d %d\n", res,
+		values[0], values[1], values[2]);
+}
+
+static ssize_t lis3lv02d_position_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int x, y, z;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	mutex_lock(&lis3_dev.mutex);
+	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+	mutex_unlock(&lis3_dev.mutex);
+	return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
+}
+
+static ssize_t lis3lv02d_rate_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	return sprintf(buf, "%d\n", lis3lv02d_get_odr());
+}
+
+static ssize_t lis3lv02d_rate_set(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
+{
+	unsigned long rate;
+
+	if (strict_strtoul(buf, 0, &rate))
+		return -EINVAL;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	if (lis3lv02d_set_odr(rate))
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
+static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
+static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
+					    lis3lv02d_rate_set);
+
+static struct attribute *lis3lv02d_attributes[] = {
+	&dev_attr_selftest.attr,
+	&dev_attr_position.attr,
+	&dev_attr_rate.attr,
+	NULL
+};
+
+static struct attribute_group lis3lv02d_attribute_group = {
+	.attrs = lis3lv02d_attributes
+};
+
+
+static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
+{
+	lis3->pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
+	if (IS_ERR(lis3->pdev))
+		return PTR_ERR(lis3->pdev);
+
+	return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
+}
+
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
+{
+	sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
+	platform_device_unregister(lis3->pdev);
+	if (lis3->pm_dev) {
+		/* Barrier after the sysfs remove */
+		pm_runtime_barrier(lis3->pm_dev);
+
+		/* SYSFS may have left chip running. Turn off if necessary */
+		if (!pm_runtime_suspended(lis3->pm_dev))
+			lis3lv02d_poweroff(&lis3_dev);
+
+		pm_runtime_disable(lis3->pm_dev);
+		pm_runtime_set_suspended(lis3->pm_dev);
+	}
+	kfree(lis3->reg_cache);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
+
+static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+				struct lis3lv02d_platform_data *p)
+{
+	int err;
+	int ctrl2 = p->hipass_ctrl;
+
+	if (p->click_flags) {
+		dev->write(dev, CLICK_CFG, p->click_flags);
+		dev->write(dev, CLICK_TIMELIMIT, p->click_time_limit);
+		dev->write(dev, CLICK_LATENCY, p->click_latency);
+		dev->write(dev, CLICK_WINDOW, p->click_window);
+		dev->write(dev, CLICK_THSZ, p->click_thresh_z & 0xf);
+		dev->write(dev, CLICK_THSY_X,
+			(p->click_thresh_x & 0xf) |
+			(p->click_thresh_y << 4));
+
+		if (dev->idev) {
+			struct input_dev *input_dev = lis3_dev.idev->input;
+			input_set_capability(input_dev, EV_KEY, BTN_X);
+			input_set_capability(input_dev, EV_KEY, BTN_Y);
+			input_set_capability(input_dev, EV_KEY, BTN_Z);
+		}
+	}
+
+	if (p->wakeup_flags) {
+		dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
+		dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
+		/* pdata value + 1 to keep this backward compatible*/
+		dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
+		ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
+	}
+
+	if (p->wakeup_flags2) {
+		dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
+		dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
+		/* pdata value + 1 to keep this backward compatible*/
+		dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
+		ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
+	}
+	/* Configure hipass filters */
+	dev->write(dev, CTRL_REG2, ctrl2);
+
+	if (p->irq2) {
+		err = request_threaded_irq(p->irq2,
+					NULL,
+					lis302dl_interrupt_thread2_8b,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+					(p->irq_flags2 & IRQF_TRIGGER_MASK),
+					DRIVER_NAME, &lis3_dev);
+		if (err < 0)
+			pr_err("No second IRQ. Limited functionality\n");
+	}
+}
+
+/*
+ * Initialise the accelerometer and the various subsystems.
+ * Should be rather independent of the bus system.
+ */
+int lis3lv02d_init_device(struct lis3lv02d *dev)
+{
+	int err;
+	irq_handler_t thread_fn;
+	int irq_flags = 0;
+
+	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
+
+	switch (dev->whoami) {
+	case WAI_12B:
+		pr_info("12 bits sensor found\n");
+		dev->read_data = lis3lv02d_read_12;
+		dev->mdps_max_val = 2048;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
+		dev->odrs = lis3_12_rates;
+		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
+		dev->scale = LIS3_SENSITIVITY_12B;
+		dev->regs = lis3_wai12_regs;
+		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
+		break;
+	case WAI_8B:
+		pr_info("8 bits sensor found\n");
+		dev->read_data = lis3lv02d_read_8;
+		dev->mdps_max_val = 128;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		dev->odrs = lis3_8_rates;
+		dev->odr_mask = CTRL1_DR;
+		dev->scale = LIS3_SENSITIVITY_8B;
+		dev->regs = lis3_wai8_regs;
+		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+		break;
+	case WAI_3DC:
+		pr_info("8 bits 3DC sensor found\n");
+		dev->read_data = lis3lv02d_read_8;
+		dev->mdps_max_val = 128;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		dev->odrs = lis3_3dc_rates;
+		dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+		dev->scale = LIS3_SENSITIVITY_8B;
+		break;
+	default:
+		pr_err("unknown sensor type 0x%X\n", dev->whoami);
+		return -EINVAL;
+	}
+
+	dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+				     sizeof(lis3_wai12_regs)), GFP_KERNEL);
+
+	if (dev->reg_cache == NULL) {
+		printk(KERN_ERR DRIVER_NAME "out of memory\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&dev->mutex);
+	atomic_set(&dev->wake_thread, 0);
+
+	lis3lv02d_add_fs(dev);
+	lis3lv02d_poweron(dev);
+
+	if (dev->pm_dev) {
+		pm_runtime_set_active(dev->pm_dev);
+		pm_runtime_enable(dev->pm_dev);
+	}
+
+	if (lis3lv02d_joystick_enable())
+		pr_err("joystick initialization failed\n");
+
+	/* passing in platform specific data is purely optional and only
+	 * used by the SPI transport layer at the moment */
+	if (dev->pdata) {
+		struct lis3lv02d_platform_data *p = dev->pdata;
+
+		if (dev->whoami == WAI_8B)
+			lis3lv02d_8b_configure(dev, p);
+
+		irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
+
+		dev->irq_cfg = p->irq_cfg;
+		if (p->irq_cfg)
+			dev->write(dev, CTRL_REG3, p->irq_cfg);
+
+		if (p->default_rate)
+			lis3lv02d_set_odr(p->default_rate);
+	}
+
+	/* bail if we did not get an IRQ from the bus layer */
+	if (!dev->irq) {
+		pr_debug("No IRQ. Disabling /dev/freefall\n");
+		goto out;
+	}
+
+	/*
+	 * The sensor can generate interrupts for free-fall and direction
+	 * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
+	 * the things simple and _fast_ we activate it only for free-fall, so
+	 * no need to read register (very slow with ACPI). For the same reason,
+	 * we forbid shared interrupts.
+	 *
+	 * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
+	 * io-apic is not configurable (and generates a warning) but I keep it
+	 * in case of support for other hardware.
+	 */
+	if (dev->pdata && dev->whoami == WAI_8B)
+		thread_fn = lis302dl_interrupt_thread1_8b;
+	else
+		thread_fn = NULL;
+
+	err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+				thread_fn,
+				IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+				irq_flags,
+				DRIVER_NAME, &lis3_dev);
+
+	if (err < 0) {
+		pr_err("Cannot get IRQ\n");
+		goto out;
+	}
+
+	if (misc_register(&lis3lv02d_misc_device))
+		pr_err("misc_register failed\n");
+out:
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
+
+MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h
new file mode 100644
index 0000000..a193958
--- /dev/null
+++ b/drivers/misc/lis3lv02d/lis3lv02d.h
@@ -0,0 +1,291 @@
+/*
+ *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008-2009 Eric Piel
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * This driver tries to support the "digital" accelerometer chips from
+ * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
+ * LIS35DE, or LIS202DL. They are very similar in terms of programming, with
+ * almost the same registers. In addition to differing on physical properties,
+ * they differ on the number of axes (2/3), precision (8/12 bits), and special
+ * features (freefall detection, click...). Unfortunately, not all the
+ * differences can be probed via a register.
+ * They can be connected either via IÂ˛C or SPI.
+ */
+
+#include <linux/lis3lv02d.h>
+
+enum lis3_reg {
+	WHO_AM_I	= 0x0F,
+	OFFSET_X	= 0x16,
+	OFFSET_Y	= 0x17,
+	OFFSET_Z	= 0x18,
+	GAIN_X		= 0x19,
+	GAIN_Y		= 0x1A,
+	GAIN_Z		= 0x1B,
+	CTRL_REG1	= 0x20,
+	CTRL_REG2	= 0x21,
+	CTRL_REG3	= 0x22,
+	CTRL_REG4	= 0x23,
+	HP_FILTER_RESET	= 0x23,
+	STATUS_REG	= 0x27,
+	OUTX_L		= 0x28,
+	OUTX_H		= 0x29,
+	OUTX		= 0x29,
+	OUTY_L		= 0x2A,
+	OUTY_H		= 0x2B,
+	OUTY		= 0x2B,
+	OUTZ_L		= 0x2C,
+	OUTZ_H		= 0x2D,
+	OUTZ		= 0x2D,
+};
+
+enum lis302d_reg {
+	FF_WU_CFG_1	= 0x30,
+	FF_WU_SRC_1	= 0x31,
+	FF_WU_THS_1	= 0x32,
+	FF_WU_DURATION_1 = 0x33,
+	FF_WU_CFG_2	= 0x34,
+	FF_WU_SRC_2	= 0x35,
+	FF_WU_THS_2	= 0x36,
+	FF_WU_DURATION_2 = 0x37,
+	CLICK_CFG	= 0x38,
+	CLICK_SRC	= 0x39,
+	CLICK_THSY_X	= 0x3B,
+	CLICK_THSZ	= 0x3C,
+	CLICK_TIMELIMIT	= 0x3D,
+	CLICK_LATENCY	= 0x3E,
+	CLICK_WINDOW	= 0x3F,
+};
+
+enum lis3lv02d_reg {
+	FF_WU_CFG	= 0x30,
+	FF_WU_SRC	= 0x31,
+	FF_WU_ACK	= 0x32,
+	FF_WU_THS_L	= 0x34,
+	FF_WU_THS_H	= 0x35,
+	FF_WU_DURATION	= 0x36,
+	DD_CFG		= 0x38,
+	DD_SRC		= 0x39,
+	DD_ACK		= 0x3A,
+	DD_THSI_L	= 0x3C,
+	DD_THSI_H	= 0x3D,
+	DD_THSE_L	= 0x3E,
+	DD_THSE_H	= 0x3F,
+};
+
+enum lis3_who_am_i {
+	WAI_3DC		= 0x33,	/* 8 bits: LIS3DC, HP3DC */
+	WAI_12B		= 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
+	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
+	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
+};
+
+enum lis3lv02d_ctrl1_12b {
+	CTRL1_Xen	= 0x01,
+	CTRL1_Yen	= 0x02,
+	CTRL1_Zen	= 0x04,
+	CTRL1_ST	= 0x08,
+	CTRL1_DF0	= 0x10,
+	CTRL1_DF1	= 0x20,
+	CTRL1_PD0	= 0x40,
+	CTRL1_PD1	= 0x80,
+};
+
+/* Delta to ctrl1_12b version */
+enum lis3lv02d_ctrl1_8b {
+	CTRL1_STM	= 0x08,
+	CTRL1_STP	= 0x10,
+	CTRL1_FS	= 0x20,
+	CTRL1_PD	= 0x40,
+	CTRL1_DR	= 0x80,
+};
+
+enum lis3lv02d_ctrl1_3dc {
+	CTRL1_ODR0	= 0x10,
+	CTRL1_ODR1	= 0x20,
+	CTRL1_ODR2	= 0x40,
+	CTRL1_ODR3	= 0x80,
+};
+
+enum lis3lv02d_ctrl2 {
+	CTRL2_DAS	= 0x01,
+	CTRL2_SIM	= 0x02,
+	CTRL2_DRDY	= 0x04,
+	CTRL2_IEN	= 0x08,
+	CTRL2_BOOT	= 0x10,
+	CTRL2_BLE	= 0x20,
+	CTRL2_BDU	= 0x40, /* Block Data Update */
+	CTRL2_FS	= 0x80, /* Full Scale selection */
+};
+
+enum lis3lv02d_ctrl4_3dc {
+	CTRL4_SIM	= 0x01,
+	CTRL4_ST0	= 0x02,
+	CTRL4_ST1	= 0x04,
+	CTRL4_FS0	= 0x10,
+	CTRL4_FS1	= 0x20,
+};
+
+enum lis302d_ctrl2 {
+	HP_FF_WU2	= 0x08,
+	HP_FF_WU1	= 0x04,
+	CTRL2_BOOT_8B   = 0x40,
+};
+
+enum lis3lv02d_ctrl3 {
+	CTRL3_CFS0	= 0x01,
+	CTRL3_CFS1	= 0x02,
+	CTRL3_FDS	= 0x10,
+	CTRL3_HPFF	= 0x20,
+	CTRL3_HPDD	= 0x40,
+	CTRL3_ECK	= 0x80,
+};
+
+enum lis3lv02d_status_reg {
+	STATUS_XDA	= 0x01,
+	STATUS_YDA	= 0x02,
+	STATUS_ZDA	= 0x04,
+	STATUS_XYZDA	= 0x08,
+	STATUS_XOR	= 0x10,
+	STATUS_YOR	= 0x20,
+	STATUS_ZOR	= 0x40,
+	STATUS_XYZOR	= 0x80,
+};
+
+enum lis3lv02d_ff_wu_cfg {
+	FF_WU_CFG_XLIE	= 0x01,
+	FF_WU_CFG_XHIE	= 0x02,
+	FF_WU_CFG_YLIE	= 0x04,
+	FF_WU_CFG_YHIE	= 0x08,
+	FF_WU_CFG_ZLIE	= 0x10,
+	FF_WU_CFG_ZHIE	= 0x20,
+	FF_WU_CFG_LIR	= 0x40,
+	FF_WU_CFG_AOI	= 0x80,
+};
+
+enum lis3lv02d_ff_wu_src {
+	FF_WU_SRC_XL	= 0x01,
+	FF_WU_SRC_XH	= 0x02,
+	FF_WU_SRC_YL	= 0x04,
+	FF_WU_SRC_YH	= 0x08,
+	FF_WU_SRC_ZL	= 0x10,
+	FF_WU_SRC_ZH	= 0x20,
+	FF_WU_SRC_IA	= 0x40,
+};
+
+enum lis3lv02d_dd_cfg {
+	DD_CFG_XLIE	= 0x01,
+	DD_CFG_XHIE	= 0x02,
+	DD_CFG_YLIE	= 0x04,
+	DD_CFG_YHIE	= 0x08,
+	DD_CFG_ZLIE	= 0x10,
+	DD_CFG_ZHIE	= 0x20,
+	DD_CFG_LIR	= 0x40,
+	DD_CFG_IEND	= 0x80,
+};
+
+enum lis3lv02d_dd_src {
+	DD_SRC_XL	= 0x01,
+	DD_SRC_XH	= 0x02,
+	DD_SRC_YL	= 0x04,
+	DD_SRC_YH	= 0x08,
+	DD_SRC_ZL	= 0x10,
+	DD_SRC_ZH	= 0x20,
+	DD_SRC_IA	= 0x40,
+};
+
+enum lis3lv02d_click_src_8b {
+	CLICK_SINGLE_X	= 0x01,
+	CLICK_DOUBLE_X	= 0x02,
+	CLICK_SINGLE_Y	= 0x04,
+	CLICK_DOUBLE_Y	= 0x08,
+	CLICK_SINGLE_Z	= 0x10,
+	CLICK_DOUBLE_Z	= 0x20,
+	CLICK_IA	= 0x40,
+};
+
+enum lis3lv02d_reg_state {
+	LIS3_REG_OFF	= 0x00,
+	LIS3_REG_ON	= 0x01,
+};
+
+union axis_conversion {
+	struct {
+		int x, y, z;
+	};
+	int as_array[3];
+
+};
+
+struct lis3lv02d {
+	void			*bus_priv; /* used by the bus layer only */
+	struct device		*pm_dev; /* for pm_runtime purposes */
+	int (*init) (struct lis3lv02d *lis3);
+	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
+	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
+	int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
+	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
+
+	int                     *odrs;     /* Supported output data rates */
+	u8			*regs;	   /* Regs to store / restore */
+	int			regs_size;
+	u8                      *reg_cache;
+	bool			regs_stored;
+	u8                      odr_mask;  /* ODR bit mask */
+	u8			whoami;    /* indicates measurement precision */
+	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
+	int			mdps_max_val;
+	int			pwron_delay;
+	int                     scale; /*
+					* relationship between 1 LBS and mG
+					* (1/1000th of earth gravity)
+					*/
+
+	struct input_polled_dev	*idev;     /* input device */
+	struct platform_device	*pdev;     /* platform device */
+	struct regulator_bulk_data regulators[2];
+	atomic_t		count;     /* interrupt count after last read */
+	union axis_conversion	ac;        /* hw -> logical axis */
+	int			mapped_btns[3];
+
+	u32			irq;       /* IRQ number */
+	struct fasync_struct	*async_queue; /* queue for the misc device */
+	wait_queue_head_t	misc_wait; /* Wait queue for the misc device */
+	unsigned long		misc_opened; /* bit0: whether the device is open */
+	int                     data_ready_count[2];
+	atomic_t		wake_thread;
+	unsigned char           irq_cfg;
+
+	struct lis3lv02d_platform_data *pdata;	/* for passing board config */
+	struct mutex		mutex;     /* Serialize poll and selftest */
+};
+
+int lis3lv02d_init_device(struct lis3lv02d *lis3);
+int lis3lv02d_joystick_enable(void);
+void lis3lv02d_joystick_disable(void);
+void lis3lv02d_poweroff(struct lis3lv02d *lis3);
+void lis3lv02d_poweron(struct lis3lv02d *lis3);
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
+
+extern struct lis3lv02d lis3_dev;
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
new file mode 100644
index 0000000..b20dfb4
--- /dev/null
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -0,0 +1,279 @@
+/*
+ * drivers/hwmon/lis3lv02d_i2c.c
+ *
+ * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
+ * Driver is based on corresponding SPI driver written by Daniel Mack
+ * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "lis3lv02d.h"
+
+#define DRV_NAME	"lis3lv02d_i2c"
+
+static const char reg_vdd[]    = "Vdd";
+static const char reg_vdd_io[] = "Vdd_IO";
+
+static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
+{
+	int ret;
+	if (state == LIS3_REG_OFF) {
+		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
+					lis3->regulators);
+	} else {
+		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
+					lis3->regulators);
+		/* Chip needs time to wakeup. Not mentioned in datasheet */
+		usleep_range(10000, 20000);
+	}
+	return ret;
+}
+
+static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	*v = i2c_smbus_read_byte_data(c, reg);
+	return 0;
+}
+
+static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
+				u8 *v)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	reg |= (1 << 7); /* 7th bit enables address auto incrementation */
+	return i2c_smbus_read_i2c_block_data(c, reg, len, v);
+}
+
+static int lis3_i2c_init(struct lis3lv02d *lis3)
+{
+	u8 reg;
+	int ret;
+
+	if (lis3->reg_ctrl)
+		lis3_reg_ctrl(lis3, LIS3_REG_ON);
+
+	lis3->read(lis3, WHO_AM_I, &reg);
+	if (reg != lis3->whoami)
+		printk(KERN_ERR "lis3: power on failure\n");
+
+	/* power up the device */
+	ret = lis3->read(lis3, CTRL_REG1, &reg);
+	if (ret < 0)
+		return ret;
+
+	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
+	return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+/* Default axis mapping but it can be overwritten by platform data */
+static union axis_conversion lis3lv02d_axis_map =
+	{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
+
+static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int ret = 0;
+	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata) {
+		/* Regulator control is optional */
+		if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
+			lis3_dev.reg_ctrl = lis3_reg_ctrl;
+
+		if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
+			(i2c_check_functionality(client->adapter,
+						I2C_FUNC_SMBUS_I2C_BLOCK)))
+			lis3_dev.blkread  = lis3_i2c_blockread;
+
+		if (pdata->axis_x)
+			lis3lv02d_axis_map.x = pdata->axis_x;
+
+		if (pdata->axis_y)
+			lis3lv02d_axis_map.y = pdata->axis_y;
+
+		if (pdata->axis_z)
+			lis3lv02d_axis_map.z = pdata->axis_z;
+
+		if (pdata->setup_resources)
+			ret = pdata->setup_resources();
+
+		if (ret)
+			goto fail;
+	}
+
+	if (lis3_dev.reg_ctrl) {
+		lis3_dev.regulators[0].supply = reg_vdd;
+		lis3_dev.regulators[1].supply = reg_vdd_io;
+		ret = regulator_bulk_get(&client->dev,
+					ARRAY_SIZE(lis3_dev.regulators),
+					lis3_dev.regulators);
+		if (ret < 0)
+			goto fail;
+	}
+
+	lis3_dev.pdata	  = pdata;
+	lis3_dev.bus_priv = client;
+	lis3_dev.init	  = lis3_i2c_init;
+	lis3_dev.read	  = lis3_i2c_read;
+	lis3_dev.write	  = lis3_i2c_write;
+	lis3_dev.irq	  = client->irq;
+	lis3_dev.ac	  = lis3lv02d_axis_map;
+	lis3_dev.pm_dev	  = &client->dev;
+
+	i2c_set_clientdata(client, &lis3_dev);
+
+	/* Provide power over the init call */
+	if (lis3_dev.reg_ctrl)
+		lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+
+	ret = lis3lv02d_init_device(&lis3_dev);
+
+	if (lis3_dev.reg_ctrl)
+		lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+
+	if (ret == 0)
+		return 0;
+fail:
+	if (pdata && pdata->release_resources)
+		pdata->release_resources();
+	return ret;
+}
+
+static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+{
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata && pdata->release_resources)
+		pdata->release_resources();
+
+	lis3lv02d_joystick_disable();
+	lis3lv02d_remove_fs(&lis3_dev);
+
+	if (lis3_dev.reg_ctrl)
+		regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+				lis3_dev.regulators);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lis3lv02d_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+		lis3lv02d_poweroff(lis3);
+	return 0;
+}
+
+static int lis3lv02d_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	/*
+	 * pm_runtime documentation says that devices should always
+	 * be powered on at resume. Pm_runtime turns them off after system
+	 * wide resume is complete.
+	 */
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
+		pm_runtime_suspended(dev))
+		lis3lv02d_poweron(lis3);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int lis3_i2c_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	lis3lv02d_poweroff(lis3);
+	return 0;
+}
+
+static int lis3_i2c_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	lis3lv02d_poweron(lis3);
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct i2c_device_id lis3lv02d_id[] = {
+	{"lis3lv02d", 0 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
+
+static const struct dev_pm_ops lis3_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
+				lis3lv02d_i2c_resume)
+	SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
+			   lis3_i2c_runtime_resume,
+			   NULL)
+};
+
+static struct i2c_driver lis3lv02d_i2c_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+		.pm     = &lis3_pm_ops,
+	},
+	.probe	= lis3lv02d_i2c_probe,
+	.remove	= __devexit_p(lis3lv02d_i2c_remove),
+	.id_table = lis3lv02d_id,
+};
+
+static int __init lis3lv02d_init(void)
+{
+	return i2c_add_driver(&lis3lv02d_i2c_driver);
+}
+
+static void __exit lis3lv02d_exit(void)
+{
+	i2c_del_driver(&lis3lv02d_i2c_driver);
+}
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("lis3lv02d I2C interface");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init);
+module_exit(lis3lv02d_exit);
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
new file mode 100644
index 0000000..c1f8a8f
--- /dev/null
+++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c
@@ -0,0 +1,145 @@
+/*
+ * lis3lv02d_spi - SPI glue layer for lis3lv02d
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/pm.h>
+
+#include "lis3lv02d.h"
+
+#define DRV_NAME 	"lis3lv02d_spi"
+#define LIS3_SPI_READ	0x80
+
+static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+	struct spi_device *spi = lis3->bus_priv;
+	int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
+	if (ret < 0)
+		return -EINVAL;
+
+	*v = (u8) ret;
+	return 0;
+}
+
+static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
+{
+	u8 tmp[2] = { reg, val };
+	struct spi_device *spi = lis3->bus_priv;
+	return spi_write(spi, tmp, sizeof(tmp));
+}
+
+static int lis3_spi_init(struct lis3lv02d *lis3)
+{
+	u8 reg;
+	int ret;
+
+	/* power up the device */
+	ret = lis3->read(lis3, CTRL_REG1, &reg);
+	if (ret < 0)
+		return ret;
+
+	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
+	return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+static union axis_conversion lis3lv02d_axis_normal =
+	{ .as_array = { 1, 2, 3 } };
+
+static int __devinit lis302dl_spi_probe(struct spi_device *spi)
+{
+	int ret;
+
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	lis3_dev.bus_priv	= spi;
+	lis3_dev.init		= lis3_spi_init;
+	lis3_dev.read		= lis3_spi_read;
+	lis3_dev.write		= lis3_spi_write;
+	lis3_dev.irq		= spi->irq;
+	lis3_dev.ac		= lis3lv02d_axis_normal;
+	lis3_dev.pdata		= spi->dev.platform_data;
+	spi_set_drvdata(spi, &lis3_dev);
+
+	return lis3lv02d_init_device(&lis3_dev);
+}
+
+static int __devexit lis302dl_spi_remove(struct spi_device *spi)
+{
+	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+	lis3lv02d_joystick_disable();
+	lis3lv02d_poweroff(lis3);
+
+	return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lis3lv02d_spi_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+		lis3lv02d_poweroff(&lis3_dev);
+
+	return 0;
+}
+
+static int lis3lv02d_spi_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+		lis3lv02d_poweron(lis3);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
+			 lis3lv02d_spi_resume);
+
+static struct spi_driver lis302dl_spi_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+		.pm	= &lis3lv02d_spi_pm,
+	},
+	.probe	= lis302dl_spi_probe,
+	.remove	= __devexit_p(lis302dl_spi_remove),
+};
+
+static int __init lis302dl_init(void)
+{
+	return spi_register_driver(&lis302dl_spi_driver);
+}
+
+static void __exit lis302dl_exit(void)
+{
+	spi_unregister_driver(&lis302dl_spi_driver);
+}
+
+module_init(lis302dl_init);
+module_exit(lis302dl_exit);
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:" DRV_NAME);
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 744b804..a19cb71 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,13 +27,19 @@
 #include <linux/mutex.h>
 #include <linux/if_ether.h>
 #include <linux/ctype.h>
+#include <linux/dmi.h>
 
 #define PHUB_STATUS 0x00		/* Status Register offset */
 #define PHUB_CONTROL 0x04		/* Control Register offset */
 #define PHUB_TIMEOUT 0x05		/* Time out value for Status Register */
 #define PCH_PHUB_ROM_WRITE_ENABLE 0x01	/* Enabling for writing ROM */
 #define PCH_PHUB_ROM_WRITE_DISABLE 0x00	/* Disabling for writing ROM */
-#define PCH_PHUB_ROM_START_ADDR 0x14	/* ROM data area start address offset */
+#define PCH_PHUB_MAC_START_ADDR 0x20C  /* MAC data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset
+					      (Intel EG20T PCH)*/
+#define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address
+						offset(OKI SEMICONDUCTOR ML7213)
+					      */
 
 /* MAX number of INT_REDUCE_CONTROL registers */
 #define MAX_NUM_INT_REDUCE_CONTROL_REG 128
@@ -41,6 +47,21 @@
 #define PCH_MINOR_NOS 1
 #define CLKCFG_CAN_50MHZ 0x12000000
 #define CLKCFG_CANCLK_MASK 0xFF000000
+#define CLKCFG_UART_MASK			0xFFFFFF
+
+/* CM-iTC */
+#define CLKCFG_UART_48MHZ			(1 << 16)
+#define CLKCFG_BAUDDIV				(2 << 20)
+#define CLKCFG_PLL2VCO				(8 << 9)
+#define CLKCFG_UARTCLKSEL			(1 << 18)
+
+/* Macros for ML7213 */
+#define PCI_VENDOR_ID_ROHM			0x10db
+#define PCI_DEVICE_ID_ROHM_ML7213_PHUB		0x801A
+
+/* Macros for ML7213 */
+#define PCI_VENDOR_ID_ROHM			0x10db
+#define PCI_DEVICE_ID_ROHM_ML7213_PHUB		0x801A
 
 /* SROM ACCESS Macro */
 #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
@@ -298,7 +319,7 @@ static void pch_phub_read_serial_rom_val(struct pch_phub_reg *chip,
 {
 	unsigned int mem_addr;
 
-	mem_addr = PCH_PHUB_ROM_START_ADDR +
+	mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T +
 			pch_phub_mac_offset[offset_address];
 
 	pch_phub_read_serial_rom(chip, mem_addr, data);
@@ -315,7 +336,7 @@ static int pch_phub_write_serial_rom_val(struct pch_phub_reg *chip,
 	int retval;
 	unsigned int mem_addr;
 
-	mem_addr = PCH_PHUB_ROM_START_ADDR +
+	mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T +
 			pch_phub_mac_offset[offset_address];
 
 	retval = pch_phub_write_serial_rom(chip, mem_addr, data);
@@ -594,23 +615,46 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
 		"pch_phub_extrom_base_address variable is %p\n", __func__,
 		chip->pch_phub_extrom_base_address);
 
-	pci_set_drvdata(pdev, chip);
-
-	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
-	if (retval)
-		goto err_sysfs_create;
-
-	retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-	if (retval)
-		goto exit_bin_attr;
-
-	pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
-					CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+	if (id->driver_data == 1) {
+		retval = sysfs_create_file(&pdev->dev.kobj,
+					   &dev_attr_pch_mac.attr);
+		if (retval)
+			goto err_sysfs_create;
 
-	/* set the prefech value */
-	iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
-	/* set the interrupt delay value */
-	iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (retval)
+			goto exit_bin_attr;
+
+		pch_phub_read_modify_write_reg(chip,
+					       (unsigned int)CLKCFG_REG_OFFSET,
+					       CLKCFG_CAN_50MHZ,
+					       CLKCFG_CANCLK_MASK);
+
+		/* quirk for CM-iTC board */
+		if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+			pch_phub_read_modify_write_reg(chip,
+						(unsigned int)CLKCFG_REG_OFFSET,
+						CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |
+						CLKCFG_PLL2VCO | CLKCFG_UARTCLKSEL,
+						CLKCFG_UART_MASK);
+
+		/* set the prefech value */
+		iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+		/* set the interrupt delay value */
+		iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+	} else if (id->driver_data == 2) {
+		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (retval)
+			goto err_sysfs_create;
+		/* set the prefech value
+		 * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a
+		 * Device4(SDIO #0,1,2):f
+		 * Device6(SATA 2):f
+		 * Device8(USB OHCI #0/ USB EHCI #0):a
+		 */
+		iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14);
+	}
+	pci_set_drvdata(pdev, chip);
 
 	return 0;
 exit_bin_attr:
@@ -687,9 +731,11 @@ static int pch_phub_resume(struct pci_dev *pdev)
 #endif /* CONFIG_PM */
 
 static struct pci_device_id pch_phub_pcidev_id[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
-	{0,}
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB),       1,  },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },
+	{ }
 };
+MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
 
 static struct pci_driver pch_phub_driver = {
 	.name = "pch_phub",
diff --git a/drivers/misc/sgi-gru/Makefile b/drivers/misc/sgi-gru/Makefile
index 7c4c306..0003a1d 100644
--- a/drivers/misc/sgi-gru/Makefile
+++ b/drivers/misc/sgi-gru/Makefile
@@ -1,6 +1,4 @@
-ifdef CONFIG_SGI_GRU_DEBUG
-  EXTRA_CFLAGS	+= -DDEBUG
-endif
+ccflags-$(CONFIG_SGI_GRU_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_SGI_GRU) := gru.o
 gru-y := grufile.o grumain.o grufault.o grutlbpurge.o gruprocfs.o grukservices.o gruhandles.o grukdump.o
diff --git a/drivers/misc/spear13xx_pcie_gadget.c b/drivers/misc/spear13xx_pcie_gadget.c
new file mode 100644
index 0000000..ec3b8c9
--- /dev/null
+++ b/drivers/misc/spear13xx_pcie_gadget.c
@@ -0,0 +1,908 @@
+/*
+ * drivers/misc/spear13xx_pcie_gadget.c
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Pratyush Anand<pratyush.anand@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/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pci_regs.h>
+#include <linux/configfs.h>
+#include <mach/pcie.h>
+#include <mach/misc_regs.h>
+
+#define IN0_MEM_SIZE	(200 * 1024 * 1024 - 1)
+/* In current implementation address translation is done using IN0 only.
+ * So IN1 start address and IN0 end address has been kept same
+*/
+#define IN1_MEM_SIZE	(0 * 1024 * 1024 - 1)
+#define IN_IO_SIZE	(20 * 1024 * 1024 - 1)
+#define IN_CFG0_SIZE	(12 * 1024 * 1024 - 1)
+#define IN_CFG1_SIZE	(12 * 1024 * 1024 - 1)
+#define IN_MSG_SIZE	(12 * 1024 * 1024 - 1)
+/* Keep default BAR size as 4K*/
+/* AORAM would be mapped by default*/
+#define INBOUND_ADDR_MASK	(SPEAR13XX_SYSRAM1_SIZE - 1)
+
+#define INT_TYPE_NO_INT	0
+#define INT_TYPE_INTX	1
+#define INT_TYPE_MSI	2
+struct spear_pcie_gadget_config {
+	void __iomem *base;
+	void __iomem *va_app_base;
+	void __iomem *va_dbi_base;
+	char int_type[10];
+	ulong requested_msi;
+	ulong configured_msi;
+	ulong bar0_size;
+	ulong bar0_rw_offset;
+	void __iomem *va_bar0_address;
+};
+
+struct pcie_gadget_target {
+	struct configfs_subsystem subsys;
+	struct spear_pcie_gadget_config config;
+};
+
+struct pcie_gadget_target_attr {
+	struct configfs_attribute	attr;
+	ssize_t		(*show)(struct spear_pcie_gadget_config *config,
+						char *buf);
+	ssize_t		(*store)(struct spear_pcie_gadget_config *config,
+						 const char *buf,
+						 size_t count);
+};
+
+static void enable_dbi_access(struct pcie_app_reg __iomem *app_reg)
+{
+	/* Enable DBI access */
+	writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void disable_dbi_access(struct pcie_app_reg __iomem *app_reg)
+{
+	/* disable DBI access */
+	writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
+		int where, int size, u32 *val)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (ulong)config->va_dbi_base + (where & ~0x3);
+
+	*val = readl(va_address);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
+		int where, int size, u32 val)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (ulong)config->va_dbi_base + (where & ~0x3);
+
+	if (size == 4)
+		writel(val, va_address);
+	else if (size == 2)
+		writew(val, va_address + (where & 2));
+	else if (size == 1)
+		writeb(val, va_address + (where & 3));
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+#define PCI_FIND_CAP_TTL	48
+
+static int pci_find_own_next_cap_ttl(struct spear_pcie_gadget_config *config,
+		u32 pos, int cap, int *ttl)
+{
+	u32 id;
+
+	while ((*ttl)--) {
+		spear_dbi_read_reg(config, pos, 1, &pos);
+		if (pos < 0x40)
+			break;
+		pos &= ~3;
+		spear_dbi_read_reg(config, pos + PCI_CAP_LIST_ID, 1, &id);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pos += PCI_CAP_LIST_NEXT;
+	}
+	return 0;
+}
+
+static int pci_find_own_next_cap(struct spear_pcie_gadget_config *config,
+			u32 pos, int cap)
+{
+	int ttl = PCI_FIND_CAP_TTL;
+
+	return pci_find_own_next_cap_ttl(config, pos, cap, &ttl);
+}
+
+static int pci_find_own_cap_start(struct spear_pcie_gadget_config *config,
+				u8 hdr_type)
+{
+	u32 status;
+
+	spear_dbi_read_reg(config, PCI_STATUS, 2, &status);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+
+	switch (hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+	case PCI_HEADER_TYPE_BRIDGE:
+		return PCI_CAPABILITY_LIST;
+	case PCI_HEADER_TYPE_CARDBUS:
+		return PCI_CB_CAPABILITY_LIST;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+/*
+ * Tell if a device supports a given PCI capability.
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it. Possible values for @cap:
+ *
+ * %PCI_CAP_ID_PM	Power Management
+ * %PCI_CAP_ID_AGP	Accelerated Graphics Port
+ * %PCI_CAP_ID_VPD	Vital Product Data
+ * %PCI_CAP_ID_SLOTID	Slot Identification
+ * %PCI_CAP_ID_MSI	Message Signalled Interrupts
+ * %PCI_CAP_ID_CHSWP	CompactPCI HotSwap
+ * %PCI_CAP_ID_PCIX	PCI-X
+ * %PCI_CAP_ID_EXP	PCI Express
+ */
+static int pci_find_own_capability(struct spear_pcie_gadget_config *config,
+		int cap)
+{
+	u32 pos;
+	u32 hdr_type;
+
+	spear_dbi_read_reg(config, PCI_HEADER_TYPE, 1, &hdr_type);
+
+	pos = pci_find_own_cap_start(config, hdr_type);
+	if (pos)
+		pos = pci_find_own_next_cap(config, pos, cap);
+
+	return pos;
+}
+
+static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
+{
+	return 0;
+}
+
+/*
+ * configfs interfaces show/store functions
+ */
+static ssize_t pcie_gadget_show_link(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
+		return sprintf(buf, "UP");
+	else
+		return sprintf(buf, "DOWN");
+}
+
+static ssize_t pcie_gadget_store_link(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	if (sysfs_streq(buf, "UP"))
+		writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
+			&app_reg->app_ctrl_0);
+	else if (sysfs_streq(buf, "DOWN"))
+		writel(readl(&app_reg->app_ctrl_0)
+				& ~(1 << APP_LTSSM_ENABLE_ID),
+				&app_reg->app_ctrl_0);
+	else
+		return -EINVAL;
+	return count;
+}
+
+static ssize_t pcie_gadget_show_int_type(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	return sprintf(buf, "%s", config->int_type);
+}
+
+static ssize_t pcie_gadget_store_int_type(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	u32 cap, vec, flags;
+	ulong vector;
+
+	if (sysfs_streq(buf, "INTA"))
+		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+
+	else if (sysfs_streq(buf, "MSI")) {
+		vector = config->requested_msi;
+		vec = 0;
+		while (vector > 1) {
+			vector /= 2;
+			vec++;
+		}
+		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
+		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
+		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
+		flags &= ~PCI_MSI_FLAGS_QMASK;
+		flags |= vec << 1;
+		spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
+	} else
+		return -EINVAL;
+
+	strcpy(config->int_type, buf);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_no_of_msi(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	u32 cap, vec, flags;
+	ulong vector;
+
+	if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
+			!= (1 << CFG_MSI_EN_ID))
+		vector = 0;
+	else {
+		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
+		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
+		flags &= ~PCI_MSI_FLAGS_QSIZE;
+		vec = flags >> 4;
+		vector = 1;
+		while (vec--)
+			vector *= 2;
+	}
+	config->configured_msi = vector;
+
+	return sprintf(buf, "%lu", vector);
+}
+
+static ssize_t pcie_gadget_store_no_of_msi(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	if (strict_strtoul(buf, 0, &config->requested_msi))
+		return -EINVAL;
+	if (config->requested_msi > 32)
+		config->requested_msi = 32;
+
+	return count;
+}
+
+static ssize_t pcie_gadget_store_inta(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong en;
+
+	if (strict_strtoul(buf, 0, &en))
+		return -EINVAL;
+
+	if (en)
+		writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
+				&app_reg->app_ctrl_0);
+	else
+		writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
+				&app_reg->app_ctrl_0);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_store_send_msi(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong vector;
+	u32 ven_msi;
+
+	if (strict_strtoul(buf, 0, &vector))
+		return -EINVAL;
+
+	if (!config->configured_msi)
+		return -EINVAL;
+
+	if (vector >= config->configured_msi)
+		return -EINVAL;
+
+	ven_msi = readl(&app_reg->ven_msi_1);
+	ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
+	ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
+	ven_msi &= ~VEN_MSI_TC_MASK;
+	ven_msi |= 0 << VEN_MSI_TC_ID;
+	ven_msi &= ~VEN_MSI_VECTOR_MASK;
+	ven_msi |= vector << VEN_MSI_VECTOR_ID;
+
+	/* generating interrupt for msi vector */
+	ven_msi |= VEN_MSI_REQ_EN;
+	writel(ven_msi, &app_reg->ven_msi_1);
+	udelay(1);
+	ven_msi &= ~VEN_MSI_REQ_EN;
+	writel(ven_msi, &app_reg->ven_msi_1);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_vendor_id(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	u32 id;
+
+	spear_dbi_read_reg(config, PCI_VENDOR_ID, 2, &id);
+
+	return sprintf(buf, "%x", id);
+}
+
+static ssize_t pcie_gadget_store_vendor_id(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong id;
+
+	if (strict_strtoul(buf, 0, &id))
+		return -EINVAL;
+
+	spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_device_id(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	u32 id;
+
+	spear_dbi_read_reg(config, PCI_DEVICE_ID, 2, &id);
+
+	return sprintf(buf, "%x", id);
+}
+
+static ssize_t pcie_gadget_store_device_id(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong id;
+
+	if (strict_strtoul(buf, 0, &id))
+		return -EINVAL;
+
+	spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_size(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	return sprintf(buf, "%lx", config->bar0_size);
+}
+
+static ssize_t pcie_gadget_store_bar0_size(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong size;
+	u32 pos, pos1;
+	u32 no_of_bit = 0;
+
+	if (strict_strtoul(buf, 0, &size))
+		return -EINVAL;
+	/* min bar size is 256 */
+	if (size <= 0x100)
+		size = 0x100;
+	/* max bar size is 1MB*/
+	else if (size >= 0x100000)
+		size = 0x100000;
+	else {
+		pos = 0;
+		pos1 = 0;
+		while (pos < 21) {
+			pos = find_next_bit((ulong *)&size, 21, pos);
+			if (pos != 21)
+				pos1 = pos + 1;
+			pos++;
+			no_of_bit++;
+		}
+		if (no_of_bit == 2)
+			pos1--;
+
+		size = 1 << pos1;
+	}
+	config->bar0_size = size;
+	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_address(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	u32 address = readl(&app_reg->pim0_mem_addr_start);
+
+	return sprintf(buf, "%x", address);
+}
+
+static ssize_t pcie_gadget_store_bar0_address(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong address;
+
+	if (strict_strtoul(buf, 0, &address))
+		return -EINVAL;
+
+	address &= ~(config->bar0_size - 1);
+	if (config->va_bar0_address)
+		iounmap(config->va_bar0_address);
+	config->va_bar0_address = ioremap(address, config->bar0_size);
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	writel(address, &app_reg->pim0_mem_addr_start);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_rw_offset(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	return sprintf(buf, "%lx", config->bar0_rw_offset);
+}
+
+static ssize_t pcie_gadget_store_bar0_rw_offset(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong offset;
+
+	if (strict_strtoul(buf, 0, &offset))
+		return -EINVAL;
+
+	if (offset % 4)
+		return -EINVAL;
+
+	config->bar0_rw_offset = offset;
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_data(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	ulong data;
+
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	data = readl((ulong)config->va_bar0_address + config->bar0_rw_offset);
+
+	return sprintf(buf, "%lx", data);
+}
+
+static ssize_t pcie_gadget_store_bar0_data(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong data;
+
+	if (strict_strtoul(buf, 0, &data))
+		return -EINVAL;
+
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	writel(data, (ulong)config->va_bar0_address + config->bar0_rw_offset);
+
+	return count;
+}
+
+/*
+ * Attribute definitions.
+ */
+
+#define PCIE_GADGET_TARGET_ATTR_RO(_name)				\
+static struct pcie_gadget_target_attr pcie_gadget_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IRUGO, pcie_gadget_show_##_name, NULL)
+
+#define PCIE_GADGET_TARGET_ATTR_WO(_name)				\
+static struct pcie_gadget_target_attr pcie_gadget_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IWUSR, NULL, pcie_gadget_store_##_name)
+
+#define PCIE_GADGET_TARGET_ATTR_RW(_name)				\
+static struct pcie_gadget_target_attr pcie_gadget_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, pcie_gadget_show_##_name, \
+			pcie_gadget_store_##_name)
+PCIE_GADGET_TARGET_ATTR_RW(link);
+PCIE_GADGET_TARGET_ATTR_RW(int_type);
+PCIE_GADGET_TARGET_ATTR_RW(no_of_msi);
+PCIE_GADGET_TARGET_ATTR_WO(inta);
+PCIE_GADGET_TARGET_ATTR_WO(send_msi);
+PCIE_GADGET_TARGET_ATTR_RW(vendor_id);
+PCIE_GADGET_TARGET_ATTR_RW(device_id);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_size);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_address);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_rw_offset);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_data);
+
+static struct configfs_attribute *pcie_gadget_target_attrs[] = {
+	&pcie_gadget_target_link.attr,
+	&pcie_gadget_target_int_type.attr,
+	&pcie_gadget_target_no_of_msi.attr,
+	&pcie_gadget_target_inta.attr,
+	&pcie_gadget_target_send_msi.attr,
+	&pcie_gadget_target_vendor_id.attr,
+	&pcie_gadget_target_device_id.attr,
+	&pcie_gadget_target_bar0_size.attr,
+	&pcie_gadget_target_bar0_address.attr,
+	&pcie_gadget_target_bar0_rw_offset.attr,
+	&pcie_gadget_target_bar0_data.attr,
+	NULL,
+};
+
+static struct pcie_gadget_target *to_target(struct config_item *item)
+{
+	return item ?
+		container_of(to_configfs_subsystem(to_config_group(item)),
+				struct pcie_gadget_target, subsys) : NULL;
+}
+
+/*
+ * Item operations and type for pcie_gadget_target.
+ */
+
+static ssize_t pcie_gadget_target_attr_show(struct config_item *item,
+					   struct configfs_attribute *attr,
+					   char *buf)
+{
+	ssize_t ret = -EINVAL;
+	struct pcie_gadget_target *target = to_target(item);
+	struct pcie_gadget_target_attr *t_attr =
+		container_of(attr, struct pcie_gadget_target_attr, attr);
+
+	if (t_attr->show)
+		ret = t_attr->show(&target->config, buf);
+	return ret;
+}
+
+static ssize_t pcie_gadget_target_attr_store(struct config_item *item,
+					struct configfs_attribute *attr,
+					const char *buf,
+					size_t count)
+{
+	ssize_t ret = -EINVAL;
+	struct pcie_gadget_target *target = to_target(item);
+	struct pcie_gadget_target_attr *t_attr =
+		container_of(attr, struct pcie_gadget_target_attr, attr);
+
+	if (t_attr->store)
+		ret = t_attr->store(&target->config, buf, count);
+	return ret;
+}
+
+static struct configfs_item_operations pcie_gadget_target_item_ops = {
+	.show_attribute		= pcie_gadget_target_attr_show,
+	.store_attribute	= pcie_gadget_target_attr_store,
+};
+
+static struct config_item_type pcie_gadget_target_type = {
+	.ct_attrs		= pcie_gadget_target_attrs,
+	.ct_item_ops		= &pcie_gadget_target_item_ops,
+	.ct_owner		= THIS_MODULE,
+};
+
+static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	/*setup registers for outbound translation */
+
+	writel(config->base, &app_reg->in0_mem_addr_start);
+	writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE,
+			&app_reg->in0_mem_addr_limit);
+	writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE,
+			&app_reg->in1_mem_addr_limit);
+	writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start);
+	writel(app_reg->in_io_addr_start + IN_IO_SIZE,
+			&app_reg->in_io_addr_limit);
+	writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start);
+	writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE,
+			&app_reg->in_cfg0_addr_limit);
+	writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start);
+	writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE,
+			&app_reg->in_cfg1_addr_limit);
+	writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start);
+	writel(app_reg->in_msg_addr_start + IN_MSG_SIZE,
+			&app_reg->in_msg_addr_limit);
+
+	writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start);
+	writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start);
+
+	/*setup registers for inbound translation */
+
+	/* Keep AORAM mapped at BAR0 as default */
+	config->bar0_size = INBOUND_ADDR_MASK + 1;
+	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK);
+	spear_dbi_write_reg(config, PCI_BASE_ADDRESS_0, 4, 0xC);
+	config->va_bar0_address = ioremap(SPEAR13XX_SYSRAM1_BASE,
+			config->bar0_size);
+
+	writel(SPEAR13XX_SYSRAM1_BASE, &app_reg->pim0_mem_addr_start);
+	writel(0, &app_reg->pim1_mem_addr_start);
+	writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit);
+
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_rom_addr_start);
+
+	writel(DEVICE_TYPE_EP | (1 << MISCTRL_EN_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+	/* disable all rx interrupts */
+	writel(0, &app_reg->int_mask);
+
+	/* Select INTA as default*/
+	spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+}
+
+static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
+{
+	struct resource *res0, *res1;
+	unsigned int status = 0;
+	int irq;
+	struct clk *clk;
+	static struct pcie_gadget_target *target;
+	struct spear_pcie_gadget_config *config;
+	struct config_item		*cg_item;
+	struct configfs_subsystem *subsys;
+
+	/* get resource for application registers*/
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res0) {
+		dev_err(&pdev->dev, "no resource defined\n");
+		return -EBUSY;
+	}
+	if (!request_mem_region(res0->start, resource_size(res0),
+				pdev->name)) {
+		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
+		return -EBUSY;
+	}
+	/* get resource for dbi registers*/
+
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res1) {
+		dev_err(&pdev->dev, "no resource defined\n");
+		goto err_rel_res0;
+	}
+	if (!request_mem_region(res1->start, resource_size(res1),
+				pdev->name)) {
+		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
+		goto err_rel_res0;
+	}
+
+	target = kzalloc(sizeof(*target), GFP_KERNEL);
+	if (!target) {
+		dev_err(&pdev->dev, "out of memory\n");
+		status = -ENOMEM;
+		goto err_rel_res;
+	}
+
+	cg_item = &target->subsys.su_group.cg_item;
+	sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id);
+	cg_item->ci_type	= &pcie_gadget_target_type;
+	config = &target->config;
+	config->va_app_base = (void __iomem *)ioremap(res0->start,
+			resource_size(res0));
+	if (!config->va_app_base) {
+		dev_err(&pdev->dev, "ioremap fail\n");
+		status = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	config->base = (void __iomem *)res1->start;
+
+	config->va_dbi_base = (void __iomem *)ioremap(res1->start,
+			resource_size(res1));
+	if (!config->va_dbi_base) {
+		dev_err(&pdev->dev, "ioremap fail\n");
+		status = -ENOMEM;
+		goto err_iounmap_app;
+	}
+
+	dev_set_drvdata(&pdev->dev, target);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no update irq?\n");
+		status = irq;
+		goto err_iounmap;
+	}
+
+	status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name, NULL);
+	if (status) {
+		dev_err(&pdev->dev, "pcie gadget interrupt IRQ%d already \
+				claimed\n", irq);
+		goto err_iounmap;
+	}
+
+	/* Register configfs hooks */
+	subsys = &target->subsys;
+	config_group_init(&subsys->su_group);
+	mutex_init(&subsys->su_mutex);
+	status = configfs_register_subsystem(subsys);
+	if (status)
+		goto err_irq;
+
+	/*
+	 * init basic pcie application registers
+	 * do not enable clock if it is PCIE0.Ideally , all controller should
+	 * have been independent from others with respect to clock. But PCIE1
+	 * and 2 depends on PCIE0.So PCIE0 clk is provided during board init.
+	 */
+	if (pdev->id == 1) {
+		/*
+		 * Ideally CFG Clock should have been also enabled here. But
+		 * it is done currently during board init routne
+		 */
+		clk = clk_get_sys("pcie1", NULL);
+		if (IS_ERR(clk)) {
+			pr_err("%s:couldn't get clk for pcie1\n", __func__);
+			goto err_irq;
+		}
+		if (clk_enable(clk)) {
+			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
+			goto err_irq;
+		}
+	} else if (pdev->id == 2) {
+		/*
+		 * Ideally CFG Clock should have been also enabled here. But
+		 * it is done currently during board init routne
+		 */
+		clk = clk_get_sys("pcie2", NULL);
+		if (IS_ERR(clk)) {
+			pr_err("%s:couldn't get clk for pcie2\n", __func__);
+			goto err_irq;
+		}
+		if (clk_enable(clk)) {
+			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
+			goto err_irq;
+		}
+	}
+	spear13xx_pcie_device_init(config);
+
+	return 0;
+err_irq:
+	free_irq(irq, NULL);
+err_iounmap:
+	iounmap(config->va_dbi_base);
+err_iounmap_app:
+	iounmap(config->va_app_base);
+err_kzalloc:
+	kfree(config);
+err_rel_res:
+	release_mem_region(res1->start, resource_size(res1));
+err_rel_res0:
+	release_mem_region(res0->start, resource_size(res0));
+	return status;
+}
+
+static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev)
+{
+	struct resource *res0, *res1;
+	static struct pcie_gadget_target *target;
+	struct spear_pcie_gadget_config *config;
+	int irq;
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irq = platform_get_irq(pdev, 0);
+	target = dev_get_drvdata(&pdev->dev);
+	config = &target->config;
+
+	free_irq(irq, NULL);
+	iounmap(config->va_dbi_base);
+	iounmap(config->va_app_base);
+	release_mem_region(res1->start, resource_size(res1));
+	release_mem_region(res0->start, resource_size(res0));
+	configfs_unregister_subsystem(&target->subsys);
+	kfree(target);
+
+	return 0;
+}
+
+static void spear_pcie_gadget_shutdown(struct platform_device *pdev)
+{
+}
+
+static struct platform_driver spear_pcie_gadget_driver = {
+	.probe = spear_pcie_gadget_probe,
+	.remove = spear_pcie_gadget_remove,
+	.shutdown = spear_pcie_gadget_shutdown,
+	.driver = {
+		.name = "pcie-gadget-spear",
+		.bus = &platform_bus_type
+	},
+};
+
+static int __init spear_pcie_gadget_init(void)
+{
+	return platform_driver_register(&spear_pcie_gadget_driver);
+}
+module_init(spear_pcie_gadget_init);
+
+static void __exit spear_pcie_gadget_exit(void)
+{
+	platform_driver_unregister(&spear_pcie_gadget_driver);
+}
+module_exit(spear_pcie_gadget_exit);
+
+MODULE_ALIAS("pcie-gadget-spear");
+MODULE_AUTHOR("Pratyush Anand");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
index f9aad06..486117f 100644
--- a/drivers/misc/ti-st/st_core.c
+++ b/drivers/misc/ti-st/st_core.c
@@ -25,10 +25,9 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 
-/* understand BT, FM and GPS for now */
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-#include <net/bluetooth/hci.h>
+#include <linux/seq_file.h>
+#include <linux/skbuff.h>
+
 #include <linux/ti_wilink_st.h>
 
 /* function pointer pointing to either,
@@ -38,21 +37,38 @@
 void (*st_recv) (void*, const unsigned char*, long);
 
 /********************************************************************/
-#if 0
-/* internal misc functions */
-bool is_protocol_list_empty(void)
+static void add_channel_to_table(struct st_data_s *st_gdata,
+		struct st_proto_s *new_proto)
 {
-	unsigned char i = 0;
-	pr_debug(" %s ", __func__);
-	for (i = 0; i < ST_MAX; i++) {
-		if (st_gdata->list[i] != NULL)
-			return ST_NOTEMPTY;
-		/* not empty */
+	pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
+	/* list now has the channel id as index itself */
+	st_gdata->list[new_proto->chnl_id] = new_proto;
+}
+
+static void remove_channel_from_table(struct st_data_s *st_gdata,
+		struct st_proto_s *proto)
+{
+	pr_info("%s: id %d\n", __func__, proto->chnl_id);
+	st_gdata->list[proto->chnl_id] = NULL;
+}
+
+/*
+ * called from KIM during firmware download.
+ *
+ * This is a wrapper function to tty->ops->write_room.
+ * It returns number of free space available in
+ * uart tx buffer.
+ */
+int st_get_uart_wr_room(struct st_data_s *st_gdata)
+{
+	struct tty_struct *tty;
+	if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
+		pr_err("tty unavailable to perform write");
+		return -1;
 	}
-	/* list empty */
-	return ST_EMPTY;
+	tty = st_gdata->tty;
+	return tty->ops->write_room(tty);
 }
-#endif
 
 /* can be called in from
  * -- KIM (during fw download)
@@ -67,7 +83,7 @@ int st_int_write(struct st_data_s *st_gdata,
 	struct tty_struct *tty;
 	if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
 		pr_err("tty unavailable to perform write");
-		return -1;
+		return -EINVAL;
 	}
 	tty = st_gdata->tty;
 #ifdef VERBOSE
@@ -82,15 +98,15 @@ int st_int_write(struct st_data_s *st_gdata,
  * push the skb received to relevant
  * protocol stacks
  */
-void st_send_frame(enum proto_type protoid, struct st_data_s *st_gdata)
+void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
 {
-	pr_info(" %s(prot:%d) ", __func__, protoid);
+	pr_debug(" %s(prot:%d) ", __func__, chnl_id);
 
 	if (unlikely
 	    (st_gdata == NULL || st_gdata->rx_skb == NULL
-	     || st_gdata->list[protoid] == NULL)) {
-		pr_err("protocol %d not registered, no data to send?",
-			   protoid);
+	     || st_gdata->list[chnl_id] == NULL)) {
+		pr_err("chnl_id %d not registered, no data to send?",
+			   chnl_id);
 		kfree_skb(st_gdata->rx_skb);
 		return;
 	}
@@ -99,17 +115,17 @@ void st_send_frame(enum proto_type protoid, struct st_data_s *st_gdata)
 	 * - should be just skb_queue_tail for the
 	 *   protocol stack driver
 	 */
-	if (likely(st_gdata->list[protoid]->recv != NULL)) {
+	if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
 		if (unlikely
-			(st_gdata->list[protoid]->recv
-			(st_gdata->list[protoid]->priv_data, st_gdata->rx_skb)
+			(st_gdata->list[chnl_id]->recv
+			(st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
 			     != 0)) {
-			pr_err(" proto stack %d's ->recv failed", protoid);
+			pr_err(" proto stack %d's ->recv failed", chnl_id);
 			kfree_skb(st_gdata->rx_skb);
 			return;
 		}
 	} else {
-		pr_err(" proto stack %d's ->recv null", protoid);
+		pr_err(" proto stack %d's ->recv null", chnl_id);
 		kfree_skb(st_gdata->rx_skb);
 	}
 	return;
@@ -124,16 +140,22 @@ void st_reg_complete(struct st_data_s *st_gdata, char err)
 {
 	unsigned char i = 0;
 	pr_info(" %s ", __func__);
-	for (i = 0; i < ST_MAX; i++) {
+	for (i = 0; i < ST_MAX_CHANNELS; i++) {
 		if (likely(st_gdata != NULL && st_gdata->list[i] != NULL &&
-			   st_gdata->list[i]->reg_complete_cb != NULL))
+			   st_gdata->list[i]->reg_complete_cb != NULL)) {
 			st_gdata->list[i]->reg_complete_cb
 				(st_gdata->list[i]->priv_data, err);
+			pr_info("protocol %d's cb sent %d\n", i, err);
+			if (err) { /* cleanup registered protocol */
+				st_gdata->protos_registered--;
+				st_gdata->list[i] = NULL;
+			}
+		}
 	}
 }
 
 static inline int st_check_data_len(struct st_data_s *st_gdata,
-	int protoid, int len)
+	unsigned char chnl_id, int len)
 {
 	int room = skb_tailroom(st_gdata->rx_skb);
 
@@ -144,7 +166,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata,
 		 * has zero length payload. So, ask ST CORE to
 		 * forward the packet to protocol driver (BT/FM/GPS)
 		 */
-		st_send_frame(protoid, st_gdata);
+		st_send_frame(chnl_id, st_gdata);
 
 	} else if (len > room) {
 		/* Received packet's payload length is larger.
@@ -157,7 +179,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata,
 		/* Packet header has non-zero payload length and
 		 * we have enough space in created skb. Lets read
 		 * payload data */
-		st_gdata->rx_state = ST_BT_W4_DATA;
+		st_gdata->rx_state = ST_W4_DATA;
 		st_gdata->rx_count = len;
 		return len;
 	}
@@ -167,6 +189,7 @@ static inline int st_check_data_len(struct st_data_s *st_gdata,
 	st_gdata->rx_state = ST_W4_PACKET_TYPE;
 	st_gdata->rx_skb = NULL;
 	st_gdata->rx_count = 0;
+	st_gdata->rx_chnl = 0;
 
 	return 0;
 }
@@ -208,14 +231,12 @@ void st_int_recv(void *disc_data,
 	const unsigned char *data, long count)
 {
 	char *ptr;
-	struct hci_event_hdr *eh;
-	struct hci_acl_hdr *ah;
-	struct hci_sco_hdr *sh;
-	struct fm_event_hdr *fm;
-	struct gps_event_hdr *gps;
-	int len = 0, type = 0, dlen = 0;
-	static enum proto_type protoid = ST_MAX;
+	struct st_proto_s *proto;
+	unsigned short payload_len = 0;
+	int len = 0, type = 0;
+	unsigned char *plen;
 	struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
+	unsigned long flags;
 
 	ptr = (char *)data;
 	/* tty_receive sent null ? */
@@ -224,10 +245,11 @@ void st_int_recv(void *disc_data,
 		return;
 	}
 
-	pr_info("count %ld rx_state %ld"
+	pr_debug("count %ld rx_state %ld"
 		   "rx_count %ld", count, st_gdata->rx_state,
 		   st_gdata->rx_count);
 
+	spin_lock_irqsave(&st_gdata->lock, flags);
 	/* Decode received bytes here */
 	while (count) {
 		if (st_gdata->rx_count) {
@@ -242,64 +264,36 @@ void st_int_recv(void *disc_data,
 
 			/* Check ST RX state machine , where are we? */
 			switch (st_gdata->rx_state) {
-
-				/* Waiting for complete packet ? */
-			case ST_BT_W4_DATA:
+			/* Waiting for complete packet ? */
+			case ST_W4_DATA:
 				pr_debug("Complete pkt received");
-
 				/* Ask ST CORE to forward
 				 * the packet to protocol driver */
-				st_send_frame(protoid, st_gdata);
+				st_send_frame(st_gdata->rx_chnl, st_gdata);
 
 				st_gdata->rx_state = ST_W4_PACKET_TYPE;
 				st_gdata->rx_skb = NULL;
-				protoid = ST_MAX;	/* is this required ? */
 				continue;
-
-				/* Waiting for Bluetooth event header ? */
-			case ST_BT_W4_EVENT_HDR:
-				eh = (struct hci_event_hdr *)st_gdata->rx_skb->
-				    data;
-
-				pr_debug("Event header: evt 0x%2.2x"
-					   "plen %d", eh->evt, eh->plen);
-
-				st_check_data_len(st_gdata, protoid, eh->plen);
-				continue;
-
-				/* Waiting for Bluetooth acl header ? */
-			case ST_BT_W4_ACL_HDR:
-				ah = (struct hci_acl_hdr *)st_gdata->rx_skb->
-				    data;
-				dlen = __le16_to_cpu(ah->dlen);
-
-				pr_info("ACL header: dlen %d", dlen);
-
-				st_check_data_len(st_gdata, protoid, dlen);
-				continue;
-
-				/* Waiting for Bluetooth sco header ? */
-			case ST_BT_W4_SCO_HDR:
-				sh = (struct hci_sco_hdr *)st_gdata->rx_skb->
-				    data;
-
-				pr_info("SCO header: dlen %d", sh->dlen);
-
-				st_check_data_len(st_gdata, protoid, sh->dlen);
-				continue;
-			case ST_FM_W4_EVENT_HDR:
-				fm = (struct fm_event_hdr *)st_gdata->rx_skb->
-				    data;
-				pr_info("FM Header: ");
-				st_check_data_len(st_gdata, ST_FM, fm->plen);
-				continue;
-				/* TODO : Add GPS packet machine logic here */
-			case ST_GPS_W4_EVENT_HDR:
-				/* [0x09 pkt hdr][R/W byte][2 byte len] */
-				gps = (struct gps_event_hdr *)st_gdata->rx_skb->
-				     data;
-				pr_info("GPS Header: ");
-				st_check_data_len(st_gdata, ST_GPS, gps->plen);
+			/* parse the header to know details */
+			case ST_W4_HEADER:
+				proto = st_gdata->list[st_gdata->rx_chnl];
+				plen =
+				&st_gdata->rx_skb->data
+				[proto->offset_len_in_hdr];
+				pr_debug("plen pointing to %x\n", *plen);
+				if (proto->len_size == 1)/* 1 byte len field */
+					payload_len = *(unsigned char *)plen;
+				else if (proto->len_size == 2)
+					payload_len =
+					__le16_to_cpu(*(unsigned short *)plen);
+				else
+					pr_info("%s: invalid length "
+					"for id %d\n",
+					__func__, proto->chnl_id);
+				st_check_data_len(st_gdata, proto->chnl_id,
+						payload_len);
+				pr_debug("off %d, pay len %d\n",
+					proto->offset_len_in_hdr, payload_len);
 				continue;
 			}	/* end of switch rx_state */
 		}
@@ -308,123 +302,56 @@ void st_int_recv(void *disc_data,
 		/* Check first byte of packet and identify module
 		 * owner (BT/FM/GPS) */
 		switch (*ptr) {
-
-			/* Bluetooth event packet? */
-		case HCI_EVENT_PKT:
-			pr_info("Event packet");
-			st_gdata->rx_state = ST_BT_W4_EVENT_HDR;
-			st_gdata->rx_count = HCI_EVENT_HDR_SIZE;
-			type = HCI_EVENT_PKT;
-			protoid = ST_BT;
-			break;
-
-			/* Bluetooth acl packet? */
-		case HCI_ACLDATA_PKT:
-			pr_info("ACL packet");
-			st_gdata->rx_state = ST_BT_W4_ACL_HDR;
-			st_gdata->rx_count = HCI_ACL_HDR_SIZE;
-			type = HCI_ACLDATA_PKT;
-			protoid = ST_BT;
-			break;
-
-			/* Bluetooth sco packet? */
-		case HCI_SCODATA_PKT:
-			pr_info("SCO packet");
-			st_gdata->rx_state = ST_BT_W4_SCO_HDR;
-			st_gdata->rx_count = HCI_SCO_HDR_SIZE;
-			type = HCI_SCODATA_PKT;
-			protoid = ST_BT;
-			break;
-
-			/* Channel 8(FM) packet? */
-		case ST_FM_CH8_PKT:
-			pr_info("FM CH8 packet");
-			type = ST_FM_CH8_PKT;
-			st_gdata->rx_state = ST_FM_W4_EVENT_HDR;
-			st_gdata->rx_count = FM_EVENT_HDR_SIZE;
-			protoid = ST_FM;
-			break;
-
-			/* Channel 9(GPS) packet? */
-		case 0x9:	/*ST_LL_GPS_CH9_PKT */
-			pr_info("GPS CH9 packet");
-			type = 0x9;	/* ST_LL_GPS_CH9_PKT; */
-			protoid = ST_GPS;
-			st_gdata->rx_state = ST_GPS_W4_EVENT_HDR;
-			st_gdata->rx_count = 3;	/* GPS_EVENT_HDR_SIZE -1*/
-			break;
 		case LL_SLEEP_IND:
 		case LL_SLEEP_ACK:
 		case LL_WAKE_UP_IND:
-			pr_info("PM packet");
+			pr_debug("PM packet");
 			/* this takes appropriate action based on
 			 * sleep state received --
 			 */
 			st_ll_sleep_state(st_gdata, *ptr);
+			/* if WAKEUP_IND collides copy from waitq to txq
+			 * and assume chip awake
+			 */
+			spin_unlock_irqrestore(&st_gdata->lock, flags);
+			if (st_ll_getstate(st_gdata) == ST_LL_AWAKE)
+				st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK);
+			spin_lock_irqsave(&st_gdata->lock, flags);
+
 			ptr++;
 			count--;
 			continue;
 		case LL_WAKE_UP_ACK:
-			pr_info("PM packet");
+			pr_debug("PM packet");
+
+			spin_unlock_irqrestore(&st_gdata->lock, flags);
 			/* wake up ack received */
 			st_wakeup_ack(st_gdata, *ptr);
+			spin_lock_irqsave(&st_gdata->lock, flags);
+
 			ptr++;
 			count--;
 			continue;
 			/* Unknow packet? */
 		default:
-			pr_err("Unknown packet type %2.2x", (__u8) *ptr);
-			ptr++;
-			count--;
-			continue;
+			type = *ptr;
+			st_gdata->rx_skb = alloc_skb(
+					st_gdata->list[type]->max_frame_size,
+					GFP_ATOMIC);
+			skb_reserve(st_gdata->rx_skb,
+					st_gdata->list[type]->reserve);
+			/* next 2 required for BT only */
+			st_gdata->rx_skb->cb[0] = type; /*pkt_type*/
+			st_gdata->rx_skb->cb[1] = 0; /*incoming*/
+			st_gdata->rx_chnl = *ptr;
+			st_gdata->rx_state = ST_W4_HEADER;
+			st_gdata->rx_count = st_gdata->list[type]->hdr_len;
+			pr_debug("rx_count %ld\n", st_gdata->rx_count);
 		};
 		ptr++;
 		count--;
-
-		switch (protoid) {
-		case ST_BT:
-			/* Allocate new packet to hold received data */
-			st_gdata->rx_skb =
-			    bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
-			if (!st_gdata->rx_skb) {
-				pr_err("Can't allocate mem for new packet");
-				st_gdata->rx_state = ST_W4_PACKET_TYPE;
-				st_gdata->rx_count = 0;
-				return;
-			}
-			bt_cb(st_gdata->rx_skb)->pkt_type = type;
-			break;
-		case ST_FM:	/* for FM */
-			st_gdata->rx_skb =
-			    alloc_skb(FM_MAX_FRAME_SIZE, GFP_ATOMIC);
-			if (!st_gdata->rx_skb) {
-				pr_err("Can't allocate mem for new packet");
-				st_gdata->rx_state = ST_W4_PACKET_TYPE;
-				st_gdata->rx_count = 0;
-				return;
-			}
-			/* place holder 0x08 */
-			skb_reserve(st_gdata->rx_skb, 1);
-			st_gdata->rx_skb->cb[0] = ST_FM_CH8_PKT;
-			break;
-		case ST_GPS:
-			/* for GPS */
-			st_gdata->rx_skb =
-			    alloc_skb(100 /*GPS_MAX_FRAME_SIZE */ , GFP_ATOMIC);
-			if (!st_gdata->rx_skb) {
-				pr_err("Can't allocate mem for new packet");
-				st_gdata->rx_state = ST_W4_PACKET_TYPE;
-				st_gdata->rx_count = 0;
-				return;
-			}
-			/* place holder 0x09 */
-			skb_reserve(st_gdata->rx_skb, 1);
-			st_gdata->rx_skb->cb[0] = 0x09;	/*ST_GPS_CH9_PKT; */
-			break;
-		case ST_MAX:
-			break;
-		}
 	}
+	spin_unlock_irqrestore(&st_gdata->lock, flags);
 	pr_debug("done %s", __func__);
 	return;
 }
@@ -466,7 +393,7 @@ void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
 
 	switch (st_ll_getstate(st_gdata)) {
 	case ST_LL_AWAKE:
-		pr_info("ST LL is AWAKE, sending normally");
+		pr_debug("ST LL is AWAKE, sending normally");
 		skb_queue_tail(&st_gdata->txq, skb);
 		break;
 	case ST_LL_ASLEEP_TO_AWAKE:
@@ -506,7 +433,7 @@ void st_tx_wakeup(struct st_data_s *st_data)
 	pr_debug("%s", __func__);
 	/* check for sending & set flag sending here */
 	if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
-		pr_info("ST already sending");
+		pr_debug("ST already sending");
 		/* keep sending */
 		set_bit(ST_TX_WAKEUP, &st_data->tx_state);
 		return;
@@ -548,9 +475,9 @@ void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
 {
 	seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
 			st_gdata->protos_registered,
-			st_gdata->list[ST_BT] != NULL ? 'R' : 'U',
-			st_gdata->list[ST_FM] != NULL ? 'R' : 'U',
-			st_gdata->list[ST_GPS] != NULL ? 'R' : 'U');
+			st_gdata->list[0x04] != NULL ? 'R' : 'U',
+			st_gdata->list[0x08] != NULL ? 'R' : 'U',
+			st_gdata->list[0x09] != NULL ? 'R' : 'U');
 }
 
 /********************************************************************/
@@ -565,20 +492,20 @@ long st_register(struct st_proto_s *new_proto)
 	unsigned long flags = 0;
 
 	st_kim_ref(&st_gdata, 0);
-	pr_info("%s(%d) ", __func__, new_proto->type);
+	pr_info("%s(%d) ", __func__, new_proto->chnl_id);
 	if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
 	    || new_proto->reg_complete_cb == NULL) {
 		pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
-		return -1;
+		return -EINVAL;
 	}
 
-	if (new_proto->type < ST_BT || new_proto->type >= ST_MAX) {
-		pr_err("protocol %d not supported", new_proto->type);
+	if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
+		pr_err("chnl_id %d not supported", new_proto->chnl_id);
 		return -EPROTONOSUPPORT;
 	}
 
-	if (st_gdata->list[new_proto->type] != NULL) {
-		pr_err("protocol %d already registered", new_proto->type);
+	if (st_gdata->list[new_proto->chnl_id] != NULL) {
+		pr_err("chnl_id %d already registered", new_proto->chnl_id);
 		return -EALREADY;
 	}
 
@@ -586,11 +513,10 @@ long st_register(struct st_proto_s *new_proto)
 	spin_lock_irqsave(&st_gdata->lock, flags);
 
 	if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) {
-		pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->type);
+		pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id);
 		/* fw download in progress */
-		st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE);
 
-		st_gdata->list[new_proto->type] = new_proto;
+		add_channel_to_table(st_gdata, new_proto);
 		st_gdata->protos_registered++;
 		new_proto->write = st_write;
 
@@ -598,7 +524,7 @@ long st_register(struct st_proto_s *new_proto)
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
 		return -EINPROGRESS;
 	} else if (st_gdata->protos_registered == ST_EMPTY) {
-		pr_info(" protocol list empty :%d ", new_proto->type);
+		pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
 		set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
 		st_recv = st_kim_recv;
 
@@ -616,16 +542,11 @@ long st_register(struct st_proto_s *new_proto)
 			if ((st_gdata->protos_registered != ST_EMPTY) &&
 			    (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
 				pr_err(" KIM failure complete callback ");
-				st_reg_complete(st_gdata, -1);
+				st_reg_complete(st_gdata, err);
 			}
-
-			return -1;
+			return -EINVAL;
 		}
 
-		/* the protocol might require other gpios to be toggled
-		 */
-		st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE);
-
 		clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
 		st_recv = st_int_recv;
 
@@ -642,14 +563,14 @@ long st_register(struct st_proto_s *new_proto)
 		/* check for already registered once more,
 		 * since the above check is old
 		 */
-		if (st_gdata->list[new_proto->type] != NULL) {
+		if (st_gdata->list[new_proto->chnl_id] != NULL) {
 			pr_err(" proto %d already registered ",
-				   new_proto->type);
+				   new_proto->chnl_id);
 			return -EALREADY;
 		}
 
 		spin_lock_irqsave(&st_gdata->lock, flags);
-		st_gdata->list[new_proto->type] = new_proto;
+		add_channel_to_table(st_gdata, new_proto);
 		st_gdata->protos_registered++;
 		new_proto->write = st_write;
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
@@ -657,22 +578,7 @@ long st_register(struct st_proto_s *new_proto)
 	}
 	/* if fw is already downloaded & new stack registers protocol */
 	else {
-		switch (new_proto->type) {
-		case ST_BT:
-			/* do nothing */
-			break;
-		case ST_FM:
-		case ST_GPS:
-			st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE);
-			break;
-		case ST_MAX:
-		default:
-			pr_err("%d protocol not supported",
-				   new_proto->type);
-			spin_unlock_irqrestore(&st_gdata->lock, flags);
-			return -EPROTONOSUPPORT;
-		}
-		st_gdata->list[new_proto->type] = new_proto;
+		add_channel_to_table(st_gdata, new_proto);
 		st_gdata->protos_registered++;
 		new_proto->write = st_write;
 
@@ -680,48 +586,42 @@ long st_register(struct st_proto_s *new_proto)
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
 		return err;
 	}
-	pr_debug("done %s(%d) ", __func__, new_proto->type);
+	pr_debug("done %s(%d) ", __func__, new_proto->chnl_id);
 }
 EXPORT_SYMBOL_GPL(st_register);
 
 /* to unregister a protocol -
  * to be called from protocol stack driver
  */
-long st_unregister(enum proto_type type)
+long st_unregister(struct st_proto_s *proto)
 {
 	long err = 0;
 	unsigned long flags = 0;
 	struct st_data_s	*st_gdata;
 
-	pr_debug("%s: %d ", __func__, type);
+	pr_debug("%s: %d ", __func__, proto->chnl_id);
 
 	st_kim_ref(&st_gdata, 0);
-	if (type < ST_BT || type >= ST_MAX) {
-		pr_err(" protocol %d not supported", type);
+	if (proto->chnl_id >= ST_MAX_CHANNELS) {
+		pr_err(" chnl_id %d not supported", proto->chnl_id);
 		return -EPROTONOSUPPORT;
 	}
 
 	spin_lock_irqsave(&st_gdata->lock, flags);
 
-	if (st_gdata->list[type] == NULL) {
-		pr_err(" protocol %d not registered", type);
+	if (st_gdata->list[proto->chnl_id] == NULL) {
+		pr_err(" chnl_id %d not registered", proto->chnl_id);
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
 		return -EPROTONOSUPPORT;
 	}
 
 	st_gdata->protos_registered--;
-	st_gdata->list[type] = NULL;
-
-	/* kim ignores BT in the below function
-	 * and handles the rest, BT is toggled
-	 * only in kim_start and kim_stop
-	 */
-	st_kim_chip_toggle(type, KIM_GPIO_INACTIVE);
+	remove_channel_from_table(st_gdata, proto);
 	spin_unlock_irqrestore(&st_gdata->lock, flags);
 
 	if ((st_gdata->protos_registered == ST_EMPTY) &&
 	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
-		pr_info(" all protocols unregistered ");
+		pr_info(" all chnl_ids unregistered ");
 
 		/* stop traffic on tty */
 		if (st_gdata->tty) {
@@ -729,7 +629,7 @@ long st_unregister(enum proto_type type)
 			stop_tty(st_gdata->tty);
 		}
 
-		/* all protocols now unregistered */
+		/* all chnl_ids now unregistered */
 		st_kim_stop(st_gdata->kim_data);
 		/* disable ST LL */
 		st_ll_disable(st_gdata);
@@ -744,37 +644,15 @@ long st_unregister(enum proto_type type)
 long st_write(struct sk_buff *skb)
 {
 	struct st_data_s *st_gdata;
-#ifdef DEBUG
-	enum proto_type protoid = ST_MAX;
-#endif
 	long len;
 
 	st_kim_ref(&st_gdata, 0);
 	if (unlikely(skb == NULL || st_gdata == NULL
 		|| st_gdata->tty == NULL)) {
 		pr_err("data/tty unavailable to perform write");
-		return -1;
+		return -EINVAL;
 	}
-#ifdef DEBUG			/* open-up skb to read the 1st byte */
-	switch (skb->data[0]) {
-	case HCI_COMMAND_PKT:
-	case HCI_ACLDATA_PKT:
-	case HCI_SCODATA_PKT:
-		protoid = ST_BT;
-		break;
-	case ST_FM_CH8_PKT:
-		protoid = ST_FM;
-		break;
-	case 0x09:
-		protoid = ST_GPS;
-		break;
-	}
-	if (unlikely(st_gdata->list[protoid] == NULL)) {
-		pr_err(" protocol %d not registered, and writing? ",
-			   protoid);
-		return -1;
-	}
-#endif
+
 	pr_debug("%d to be written", skb->len);
 	len = skb->len;
 
@@ -824,7 +702,7 @@ static int st_tty_open(struct tty_struct *tty)
 
 static void st_tty_close(struct tty_struct *tty)
 {
-	unsigned char i = ST_MAX;
+	unsigned char i = ST_MAX_CHANNELS;
 	unsigned long flags = 0;
 	struct	st_data_s *st_gdata = tty->disc_data;
 
@@ -835,7 +713,7 @@ static void st_tty_close(struct tty_struct *tty)
 	 * un-installed for some reason - what should be done ?
 	 */
 	spin_lock_irqsave(&st_gdata->lock, flags);
-	for (i = ST_BT; i < ST_MAX; i++) {
+	for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
 		if (st_gdata->list[i] != NULL)
 			pr_err("%d not un-registered", i);
 		st_gdata->list[i] = NULL;
@@ -869,7 +747,6 @@ static void st_tty_close(struct tty_struct *tty)
 static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,
 			   char *tty_flags, int count)
 {
-
 #ifdef VERBOSE
 	print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
 		16, 1, data, count, 0);
@@ -960,7 +837,7 @@ int st_core_init(struct st_data_s **core_data)
 		err = tty_unregister_ldisc(N_TI_WL);
 		if (err)
 			pr_err("unable to un-register ldisc");
-		return -1;
+		return err;
 	}
 	*core_data = st_gdata;
 	return 0;
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 73b6c8b..9ee4c78 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -30,50 +30,12 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/sched.h>
-#include <linux/rfkill.h>
-
-/* understand BT events for fw response */
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-#include <net/bluetooth/hci.h>
+#include <linux/tty.h>
 
+#include <linux/skbuff.h>
 #include <linux/ti_wilink_st.h>
 
 
-static int kim_probe(struct platform_device *pdev);
-static int kim_remove(struct platform_device *pdev);
-
-/* KIM platform device driver structure */
-static struct platform_driver kim_platform_driver = {
-	.probe = kim_probe,
-	.remove = kim_remove,
-	/* TODO: ST driver power management during suspend/resume ?
-	 */
-#if 0
-	.suspend = kim_suspend,
-	.resume = kim_resume,
-#endif
-	.driver = {
-		   .name = "kim",
-		   .owner = THIS_MODULE,
-		   },
-};
-
-static int kim_toggle_radio(void*, bool);
-static const struct rfkill_ops kim_rfkill_ops = {
-	.set_block = kim_toggle_radio,
-};
-
-/* strings to be used for rfkill entries and by
- * ST Core to be used for sysfs debug entry
- */
-#define PROTO_ENTRY(type, name)	name
-const unsigned char *protocol_names[] = {
-	PROTO_ENTRY(ST_BT, "Bluetooth"),
-	PROTO_ENTRY(ST_FM, "FM"),
-	PROTO_ENTRY(ST_GPS, "GPS"),
-};
-
 #define MAX_ST_DEVICES	3	/* Imagine 1 on each UART for now */
 static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
 
@@ -134,7 +96,7 @@ static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len)
 		/* Packet header has non-zero payload length and
 		 * we have enough space in created skb. Lets read
 		 * payload data */
-		kim_gdata->rx_state = ST_BT_W4_DATA;
+		kim_gdata->rx_state = ST_W4_DATA;
 		kim_gdata->rx_count = len;
 		return len;
 	}
@@ -158,8 +120,8 @@ void kim_int_recv(struct kim_data_s *kim_gdata,
 	const unsigned char *data, long count)
 {
 	const unsigned char *ptr;
-	struct hci_event_hdr *eh;
 	int len = 0, type = 0;
+	unsigned char *plen;
 
 	pr_debug("%s", __func__);
 	/* Decode received bytes here */
@@ -183,29 +145,27 @@ void kim_int_recv(struct kim_data_s *kim_gdata,
 			/* Check ST RX state machine , where are we? */
 			switch (kim_gdata->rx_state) {
 				/* Waiting for complete packet ? */
-			case ST_BT_W4_DATA:
+			case ST_W4_DATA:
 				pr_debug("Complete pkt received");
 				validate_firmware_response(kim_gdata);
 				kim_gdata->rx_state = ST_W4_PACKET_TYPE;
 				kim_gdata->rx_skb = NULL;
 				continue;
 				/* Waiting for Bluetooth event header ? */
-			case ST_BT_W4_EVENT_HDR:
-				eh = (struct hci_event_hdr *)kim_gdata->
-				    rx_skb->data;
-				pr_debug("Event header: evt 0x%2.2x"
-					   "plen %d", eh->evt, eh->plen);
-				kim_check_data_len(kim_gdata, eh->plen);
+			case ST_W4_HEADER:
+				plen =
+				(unsigned char *)&kim_gdata->rx_skb->data[1];
+				pr_debug("event hdr: plen 0x%02x\n", *plen);
+				kim_check_data_len(kim_gdata, *plen);
 				continue;
 			}	/* end of switch */
 		}		/* end of if rx_state */
 		switch (*ptr) {
 			/* Bluetooth event packet? */
-		case HCI_EVENT_PKT:
-			pr_info("Event packet");
-			kim_gdata->rx_state = ST_BT_W4_EVENT_HDR;
-			kim_gdata->rx_count = HCI_EVENT_HDR_SIZE;
-			type = HCI_EVENT_PKT;
+		case 0x04:
+			kim_gdata->rx_state = ST_W4_HEADER;
+			kim_gdata->rx_count = 2;
+			type = *ptr;
 			break;
 		default:
 			pr_info("unknown packet");
@@ -216,16 +176,18 @@ void kim_int_recv(struct kim_data_s *kim_gdata,
 		ptr++;
 		count--;
 		kim_gdata->rx_skb =
-		    bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
+			alloc_skb(1024+8, GFP_ATOMIC);
 		if (!kim_gdata->rx_skb) {
 			pr_err("can't allocate mem for new packet");
 			kim_gdata->rx_state = ST_W4_PACKET_TYPE;
 			kim_gdata->rx_count = 0;
 			return;
 		}
-		bt_cb(kim_gdata->rx_skb)->pkt_type = type;
+		skb_reserve(kim_gdata->rx_skb, 8);
+		kim_gdata->rx_skb->cb[0] = 4;
+		kim_gdata->rx_skb->cb[1] = 0;
+
 	}
-	pr_info("done %s", __func__);
 	return;
 }
 
@@ -239,13 +201,13 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
 	INIT_COMPLETION(kim_gdata->kim_rcvd);
 	if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) {
 		pr_err("kim: couldn't write 4 bytes");
-		return -1;
+		return -EIO;
 	}
 
 	if (!wait_for_completion_timeout
 	    (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
 		pr_err(" waiting for ver info- timed out ");
-		return -1;
+		return -ETIMEDOUT;
 	}
 
 	version =
@@ -270,6 +232,26 @@ static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
 	return 0;
 }
 
+void skip_change_remote_baud(unsigned char **ptr, long *len)
+{
+	unsigned char *nxt_action, *cur_action;
+	cur_action = *ptr;
+
+	nxt_action = cur_action + sizeof(struct bts_action) +
+		((struct bts_action *) cur_action)->size;
+
+	if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) {
+		pr_err("invalid action after change remote baud command");
+	} else {
+		*ptr = *ptr + sizeof(struct bts_action) +
+			((struct bts_action *)nxt_action)->size;
+		*len = *len - (sizeof(struct bts_action) +
+				((struct bts_action *)nxt_action)->size);
+		/* warn user on not commenting these in firmware */
+		pr_warn("skipping the wait event of change remote baud");
+	}
+}
+
 /**
  * download_firmware -
  *	internal function which parses through the .bts firmware
@@ -282,6 +264,9 @@ static long download_firmware(struct kim_data_s *kim_gdata)
 	unsigned char *ptr = NULL;
 	unsigned char *action_ptr = NULL;
 	unsigned char bts_scr_name[30] = { 0 };	/* 30 char long bts scr name? */
+	int wr_room_space;
+	int cmd_size;
+	unsigned long timeout;
 
 	err = read_local_version(kim_gdata, bts_scr_name);
 	if (err != 0) {
@@ -295,7 +280,7 @@ static long download_firmware(struct kim_data_s *kim_gdata)
 		     (kim_gdata->fw_entry->size == 0))) {
 		pr_err(" request_firmware failed(errno %ld) for %s", err,
 			   bts_scr_name);
-		return -1;
+		return -EINVAL;
 	}
 	ptr = (void *)kim_gdata->fw_entry->data;
 	len = kim_gdata->fw_entry->size;
@@ -318,29 +303,72 @@ static long download_firmware(struct kim_data_s *kim_gdata)
 			     0xFF36)) {
 				/* ignore remote change
 				 * baud rate HCI VS command */
-				pr_err
-				    (" change remote baud"
+				pr_warn("change remote baud"
 				    " rate command in firmware");
+				skip_change_remote_baud(&ptr, &len);
 				break;
 			}
+			/*
+			 * Make sure we have enough free space in uart
+			 * tx buffer to write current firmware command
+			 */
+			cmd_size = ((struct bts_action *)ptr)->size;
+			timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME);
+			do {
+				wr_room_space =
+					st_get_uart_wr_room(kim_gdata->core_data);
+				if (wr_room_space < 0) {
+					pr_err("Unable to get free "
+							"space info from uart tx buffer");
+					release_firmware(kim_gdata->fw_entry);
+					return wr_room_space;
+				}
+				mdelay(1); /* wait 1ms before checking room */
+			} while ((wr_room_space < cmd_size) &&
+					time_before(jiffies, timeout));
+
+			/* Timeout happened ? */
+			if (time_after_eq(jiffies, timeout)) {
+				pr_err("Timeout while waiting for free "
+						"free space in uart tx buffer");
+				release_firmware(kim_gdata->fw_entry);
+				return -ETIMEDOUT;
+			}
 
-			INIT_COMPLETION(kim_gdata->kim_rcvd);
+			/*
+			 * Free space found in uart buffer, call st_int_write
+			 * to send current firmware command to the uart tx
+			 * buffer.
+			 */
 			err = st_int_write(kim_gdata->core_data,
 			((struct bts_action_send *)action_ptr)->data,
 					   ((struct bts_action *)ptr)->size);
 			if (unlikely(err < 0)) {
 				release_firmware(kim_gdata->fw_entry);
-				return -1;
+				return err;
 			}
+			/*
+			 * Check number of bytes written to the uart tx buffer
+			 * and requested command write size
+			 */
+			if (err != cmd_size) {
+				pr_err("Number of bytes written to uart "
+						"tx buffer are not matching with "
+						"requested cmd write size");
+				release_firmware(kim_gdata->fw_entry);
+				return -EIO;
+			}
+			break;
+		case ACTION_WAIT_EVENT:  /* wait */
 			if (!wait_for_completion_timeout
-			    (&kim_gdata->kim_rcvd,
-			     msecs_to_jiffies(CMD_RESP_TIME))) {
-				pr_err
-				    (" response timeout during fw download ");
+					(&kim_gdata->kim_rcvd,
+					 msecs_to_jiffies(CMD_RESP_TIME))) {
+				pr_err("response timeout during fw download ");
 				/* timed out */
 				release_firmware(kim_gdata->fw_entry);
-				return -1;
+				return -ETIMEDOUT;
 			}
+			INIT_COMPLETION(kim_gdata->kim_rcvd);
 			break;
 		case ACTION_DELAY:	/* sleep */
 			pr_info("sleep command in scr");
@@ -362,50 +390,6 @@ static long download_firmware(struct kim_data_s *kim_gdata)
 
 /**********************************************************************/
 /* functions called from ST core */
-/* function to toggle the GPIO
- * needs to know whether the GPIO is active high or active low
- */
-void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state)
-{
-	struct platform_device	*kim_pdev;
-	struct kim_data_s	*kim_gdata;
-	pr_info(" %s ", __func__);
-
-	kim_pdev = st_get_plat_device(0);
-	kim_gdata = dev_get_drvdata(&kim_pdev->dev);
-
-	if (kim_gdata->gpios[type] == -1) {
-		pr_info(" gpio not requested for protocol %s",
-			   protocol_names[type]);
-		return;
-	}
-	switch (type) {
-	case ST_BT:
-		/*Do Nothing */
-		break;
-
-	case ST_FM:
-		if (state == KIM_GPIO_ACTIVE)
-			gpio_set_value(kim_gdata->gpios[ST_FM], GPIO_LOW);
-		else
-			gpio_set_value(kim_gdata->gpios[ST_FM], GPIO_HIGH);
-		break;
-
-	case ST_GPS:
-		if (state == KIM_GPIO_ACTIVE)
-			gpio_set_value(kim_gdata->gpios[ST_GPS], GPIO_HIGH);
-		else
-			gpio_set_value(kim_gdata->gpios[ST_GPS], GPIO_LOW);
-		break;
-
-	case ST_MAX:
-	default:
-		break;
-	}
-
-	return;
-}
-
 /* called from ST Core, when REG_IN_PROGRESS (registration in progress)
  * can be because of
  * 1. response to read local version
@@ -416,7 +400,6 @@ void st_kim_recv(void *disc_data, const unsigned char *data, long count)
 	struct st_data_s	*st_gdata = (struct st_data_s *)disc_data;
 	struct kim_data_s	*kim_gdata = st_gdata->kim_data;
 
-	pr_info(" %s ", __func__);
 	/* copy to local buffer */
 	if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) {
 		/* must be the read_ver_cmd */
@@ -455,35 +438,28 @@ long st_kim_start(void *kim_data)
 	pr_info(" %s", __func__);
 
 	do {
-		/* TODO: this is only because rfkill sub-system
-		 * doesn't send events to user-space if the state
-		 * isn't changed
-		 */
-		rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1);
 		/* Configure BT nShutdown to HIGH state */
-		gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
+		gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
 		mdelay(5);	/* FIXME: a proper toggle */
-		gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_HIGH);
+		gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
 		mdelay(100);
 		/* re-initialize the completion */
 		INIT_COMPLETION(kim_gdata->ldisc_installed);
-#if 0 /* older way of signalling user-space UIM */
-		/* send signal to UIM */
-		err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 0);
-		if (err != 0) {
-			pr_info(" sending SIGUSR2 to uim failed %ld", err);
-			err = -1;
-			continue;
-		}
-#endif
-		/* unblock and send event to UIM via /dev/rfkill */
-		rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 0);
+		/* send notification to UIM */
+		kim_gdata->ldisc_install = 1;
+		pr_info("ldisc_install = 1");
+		sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
+				NULL, "install");
 		/* wait for ldisc to be installed */
 		err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
 				msecs_to_jiffies(LDISC_TIME));
 		if (!err) {	/* timeout */
 			pr_err("line disc installation timed out ");
-			err = -1;
+			kim_gdata->ldisc_install = 0;
+			pr_info("ldisc_install = 0");
+			sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
+					NULL, "install");
+			err = -ETIMEDOUT;
 			continue;
 		} else {
 			/* ldisc installed now */
@@ -491,6 +467,10 @@ long st_kim_start(void *kim_data)
 			err = download_firmware(kim_gdata);
 			if (err != 0) {
 				pr_err("download firmware failed");
+				kim_gdata->ldisc_install = 0;
+				pr_info("ldisc_install = 0");
+				sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
+						NULL, "install");
 				continue;
 			} else {	/* on success don't retry */
 				break;
@@ -510,31 +490,30 @@ long st_kim_stop(void *kim_data)
 	struct kim_data_s	*kim_gdata = (struct kim_data_s *)kim_data;
 
 	INIT_COMPLETION(kim_gdata->ldisc_installed);
-#if 0 /* older way of signalling user-space UIM */
-	/* send signal to UIM */
-	err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 1);
-	if (err != 0) {
-		pr_err("sending SIGUSR2 to uim failed %ld", err);
-		return -1;
-	}
-#endif
-	/* set BT rfkill to be blocked */
-	err = rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1);
+
+	/* Flush any pending characters in the driver and discipline. */
+	tty_ldisc_flush(kim_gdata->core_data->tty);
+	tty_driver_flush_buffer(kim_gdata->core_data->tty);
+
+	/* send uninstall notification to UIM */
+	pr_info("ldisc_install = 0");
+	kim_gdata->ldisc_install = 0;
+	sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
 
 	/* wait for ldisc to be un-installed */
 	err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
 			msecs_to_jiffies(LDISC_TIME));
 	if (!err) {		/* timeout */
 		pr_err(" timed out waiting for ldisc to be un-installed");
-		return -1;
+		return -ETIMEDOUT;
 	}
 
 	/* By default configure BT nShutdown to LOW state */
-	gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
 	mdelay(1);
-	gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_HIGH);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
 	mdelay(1);
-	gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
 	return err;
 }
 
@@ -558,33 +537,59 @@ static int show_list(struct seq_file *s, void *unused)
 	return 0;
 }
 
-/* function called from rfkill subsystem, when someone from
- * user space would write 0/1 on the sysfs entry
- * /sys/class/rfkill/rfkill0,1,3/state
- */
-static int kim_toggle_radio(void *data, bool blocked)
+static ssize_t show_install(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
-	enum proto_type type = *((enum proto_type *)data);
-	pr_debug(" %s: %d ", __func__, type);
-
-	switch (type) {
-	case ST_BT:
-		/* do nothing */
-	break;
-	case ST_FM:
-	case ST_GPS:
-		if (blocked)
-			st_kim_chip_toggle(type, KIM_GPIO_INACTIVE);
-		else
-			st_kim_chip_toggle(type, KIM_GPIO_ACTIVE);
-	break;
-	case ST_MAX:
-		pr_err(" wrong proto type ");
-	break;
-	}
-	return 0;
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", kim_data->ldisc_install);
 }
 
+static ssize_t show_dev_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", kim_data->dev_name);
+}
+
+static ssize_t show_baud_rate(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%ld\n", kim_data->baud_rate);
+}
+
+static ssize_t show_flow_cntrl(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", kim_data->flow_cntrl);
+}
+
+/* structures specific for sysfs entries */
+static struct kobj_attribute ldisc_install =
+__ATTR(install, 0444, (void *)show_install, NULL);
+
+static struct kobj_attribute uart_dev_name =
+__ATTR(dev_name, 0444, (void *)show_dev_name, NULL);
+
+static struct kobj_attribute uart_baud_rate =
+__ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL);
+
+static struct kobj_attribute uart_flow_cntrl =
+__ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL);
+
+static struct attribute *uim_attrs[] = {
+	&ldisc_install.attr,
+	&uart_dev_name.attr,
+	&uart_baud_rate.attr,
+	&uart_flow_cntrl.attr,
+	NULL,
+};
+
+static struct attribute_group uim_attr_grp = {
+	.attrs = uim_attrs,
+};
+
 /**
  * st_kim_ref - reference the core's data
  *	This references the per-ST platform device in the arch/xx/
@@ -637,9 +642,8 @@ struct dentry *kim_debugfs_dir;
 static int kim_probe(struct platform_device *pdev)
 {
 	long status;
-	long proto;
-	long *gpios = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
 
 	if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
 		/* multiple devices could exist */
@@ -659,44 +663,24 @@ static int kim_probe(struct platform_device *pdev)
 	status = st_core_init(&kim_gdata->core_data);
 	if (status != 0) {
 		pr_err(" ST core init failed");
-		return -1;
+		return -EIO;
 	}
 	/* refer to itself */
 	kim_gdata->core_data->kim_data = kim_gdata;
 
-	for (proto = 0; proto < ST_MAX; proto++) {
-		kim_gdata->gpios[proto] = gpios[proto];
-		pr_info(" %ld gpio to be requested", gpios[proto]);
+	/* Claim the chip enable nShutdown gpio from the system */
+	kim_gdata->nshutdown = pdata->nshutdown_gpio;
+	status = gpio_request(kim_gdata->nshutdown, "kim");
+	if (unlikely(status)) {
+		pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
+		return status;
 	}
 
-	for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) {
-		/* Claim the Bluetooth/FM/GPIO
-		 * nShutdown gpio from the system
-		 */
-		status = gpio_request(gpios[proto], "kim");
-		if (unlikely(status)) {
-			pr_err(" gpio %ld request failed ", gpios[proto]);
-			proto -= 1;
-			while (proto >= 0) {
-				if (gpios[proto] != -1)
-					gpio_free(gpios[proto]);
-			}
-			return status;
-		}
-
-		/* Configure nShutdown GPIO as output=0 */
-		status =
-		    gpio_direction_output(gpios[proto], 0);
-		if (unlikely(status)) {
-			pr_err(" unable to configure gpio %ld",
-				   gpios[proto]);
-			proto -= 1;
-			while (proto >= 0) {
-				if (gpios[proto] != -1)
-					gpio_free(gpios[proto]);
-			}
-			return status;
-		}
+	/* Configure nShutdown GPIO as output=0 */
+	status = gpio_direction_output(kim_gdata->nshutdown, 0);
+	if (unlikely(status)) {
+		pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
+		return status;
 	}
 	/* get reference of pdev for request_firmware
 	 */
@@ -704,34 +688,23 @@ static int kim_probe(struct platform_device *pdev)
 	init_completion(&kim_gdata->kim_rcvd);
 	init_completion(&kim_gdata->ldisc_installed);
 
-	for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) {
-		/* TODO: should all types be rfkill_type_bt ? */
-		kim_gdata->rf_protos[proto] = proto;
-		kim_gdata->rfkill[proto] = rfkill_alloc(protocol_names[proto],
-			&pdev->dev, RFKILL_TYPE_BLUETOOTH,
-			&kim_rfkill_ops, &kim_gdata->rf_protos[proto]);
-		if (kim_gdata->rfkill[proto] == NULL) {
-			pr_err("cannot create rfkill entry for gpio %ld",
-				   gpios[proto]);
-			continue;
-		}
-		/* block upon creation */
-		rfkill_init_sw_state(kim_gdata->rfkill[proto], 1);
-		status = rfkill_register(kim_gdata->rfkill[proto]);
-		if (unlikely(status)) {
-			pr_err("rfkill registration failed for gpio %ld",
-				   gpios[proto]);
-			rfkill_unregister(kim_gdata->rfkill[proto]);
-			continue;
-		}
-		pr_info("rfkill entry created for %ld", gpios[proto]);
+	status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
+	if (status) {
+		pr_err("failed to create sysfs entries");
+		return status;
 	}
 
+	/* copying platform data */
+	strncpy(kim_gdata->dev_name, pdata->dev_name, UART_DEV_NAME_LEN);
+	kim_gdata->flow_cntrl = pdata->flow_cntrl;
+	kim_gdata->baud_rate = pdata->baud_rate;
+	pr_info("sysfs entries created\n");
+
 	kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
 	if (IS_ERR(kim_debugfs_dir)) {
 		pr_err(" debugfs entries creation failed ");
 		kim_debugfs_dir = NULL;
-		return -1;
+		return -EIO;
 	}
 
 	debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
@@ -744,25 +717,22 @@ static int kim_probe(struct platform_device *pdev)
 
 static int kim_remove(struct platform_device *pdev)
 {
-	/* free the GPIOs requested
-	 */
-	long *gpios = pdev->dev.platform_data;
-	long proto;
+	/* free the GPIOs requested */
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
 
 	kim_gdata = dev_get_drvdata(&pdev->dev);
 
-	for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) {
-		/* Claim the Bluetooth/FM/GPIO
-		 * nShutdown gpio from the system
-		 */
-		gpio_free(gpios[proto]);
-		rfkill_unregister(kim_gdata->rfkill[proto]);
-		rfkill_destroy(kim_gdata->rfkill[proto]);
-		kim_gdata->rfkill[proto] = NULL;
-	}
-	pr_info("kim: GPIO Freed");
+	/* Free the Bluetooth/FM/GPIO
+	 * nShutdown gpio from the system
+	 */
+	gpio_free(pdata->nshutdown_gpio);
+	pr_info("nshutdown GPIO Freed");
+
 	debugfs_remove_recursive(kim_debugfs_dir);
+	sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
+	pr_info("sysfs entries removed");
+
 	kim_gdata->kim_pdev = NULL;
 	st_core_exit(kim_gdata->core_data);
 
@@ -771,23 +741,46 @@ static int kim_remove(struct platform_device *pdev)
 	return 0;
 }
 
+int kim_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
+
+	if (pdata->suspend)
+		return pdata->suspend(pdev, state);
+
+	return -EOPNOTSUPP;
+}
+
+int kim_resume(struct platform_device *pdev)
+{
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
+
+	if (pdata->resume)
+		return pdata->resume(pdev);
+
+	return -EOPNOTSUPP;
+}
+
 /**********************************************************************/
 /* entry point for ST KIM module, called in from ST Core */
+static struct platform_driver kim_platform_driver = {
+	.probe = kim_probe,
+	.remove = kim_remove,
+	.suspend = kim_suspend,
+	.resume = kim_resume,
+	.driver = {
+		.name = "kim",
+		.owner = THIS_MODULE,
+	},
+};
 
 static int __init st_kim_init(void)
 {
-	long ret = 0;
-	ret = platform_driver_register(&kim_platform_driver);
-	if (ret != 0) {
-		pr_err("platform drv registration failed");
-		return -1;
-	}
-	return 0;
+	return platform_driver_register(&kim_platform_driver);
 }
 
 static void __exit st_kim_deinit(void)
 {
-	/* the following returns void */
 	platform_driver_unregister(&kim_platform_driver);
 }
 
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
index 2bda8de..3f24951 100644
--- a/drivers/misc/ti-st/st_ll.c
+++ b/drivers/misc/ti-st/st_ll.c
@@ -30,7 +30,7 @@ static void send_ll_cmd(struct st_data_s *st_data,
 	unsigned char cmd)
 {
 
-	pr_info("%s: writing %x", __func__, cmd);
+	pr_debug("%s: writing %x", __func__, cmd);
 	st_int_write(st_data, &cmd, 1);
 	return;
 }
@@ -114,23 +114,23 @@ unsigned long st_ll_sleep_state(struct st_data_s *st_data,
 {
 	switch (cmd) {
 	case LL_SLEEP_IND:	/* sleep ind */
-		pr_info("sleep indication recvd");
+		pr_debug("sleep indication recvd");
 		ll_device_want_to_sleep(st_data);
 		break;
 	case LL_SLEEP_ACK:	/* sleep ack */
 		pr_err("sleep ack rcvd: host shouldn't");
 		break;
 	case LL_WAKE_UP_IND:	/* wake ind */
-		pr_info("wake indication recvd");
+		pr_debug("wake indication recvd");
 		ll_device_want_to_wakeup(st_data);
 		break;
 	case LL_WAKE_UP_ACK:	/* wake ack */
-		pr_info("wake ack rcvd");
+		pr_debug("wake ack rcvd");
 		st_data->ll_state = ST_LL_AWAKE;
 		break;
 	default:
 		pr_err(" unknown input/state ");
-		return -1;
+		return -EINVAL;
 	}
 	return 0;
 }
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 2a876c4..3b1f783 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -58,12 +58,11 @@ config SDIO_UART
 
 config MMC_TEST
 	tristate "MMC host test driver"
-	default n
 	help
 	  Development driver that performs a series of reads and writes
 	  to a memory card in order to expose certain well known bugs
 	  in host controllers. The tests are executed by writing to the
-	  "test" file in sysfs under each card. Note that whatever is
+	  "test" file in debugfs under each card. Note that whatever is
 	  on your card will be overwritten by these tests.
 
 	  This driver is only of interest to those developing or
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index bfc8a8a..61d233a 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -621,6 +621,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
 	md->disk->private_data = md;
 	md->disk->queue = md->queue.queue;
 	md->disk->driverfs_dev = &card->dev;
+	set_disk_ro(md->disk, md->read_only);
 
 	/*
 	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 21adc27..5ec8edd 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -88,6 +88,7 @@ struct mmc_test_area {
  * @sectors: amount of sectors to check in one group
  * @ts: time values of transfer
  * @rate: calculated transfer rate
+ * @iops: I/O operations per second (times 100)
  */
 struct mmc_test_transfer_result {
 	struct list_head link;
@@ -95,6 +96,7 @@ struct mmc_test_transfer_result {
 	unsigned int sectors;
 	struct timespec ts;
 	unsigned int rate;
+	unsigned int iops;
 };
 
 /**
@@ -226,9 +228,10 @@ static int mmc_test_wait_busy(struct mmc_test_card *test)
 
 		if (!busy && mmc_test_busy(&cmd)) {
 			busy = 1;
-			printk(KERN_INFO "%s: Warning: Host did not "
-				"wait for busy state to end.\n",
-				mmc_hostname(test->card->host));
+			if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+				printk(KERN_INFO "%s: Warning: Host did not "
+					"wait for busy state to end.\n",
+					mmc_hostname(test->card->host));
 		}
 	} while (mmc_test_busy(&cmd));
 
@@ -494,7 +497,7 @@ static unsigned int mmc_test_rate(uint64_t bytes, struct timespec *ts)
  */
 static void mmc_test_save_transfer_result(struct mmc_test_card *test,
 	unsigned int count, unsigned int sectors, struct timespec ts,
-	unsigned int rate)
+	unsigned int rate, unsigned int iops)
 {
 	struct mmc_test_transfer_result *tr;
 
@@ -509,6 +512,7 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test,
 	tr->sectors = sectors;
 	tr->ts = ts;
 	tr->rate = rate;
+	tr->iops = iops;
 
 	list_add_tail(&tr->link, &test->gr->tr_lst);
 }
@@ -519,20 +523,22 @@ static void mmc_test_save_transfer_result(struct mmc_test_card *test,
 static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
 				struct timespec *ts1, struct timespec *ts2)
 {
-	unsigned int rate, sectors = bytes >> 9;
+	unsigned int rate, iops, sectors = bytes >> 9;
 	struct timespec ts;
 
 	ts = timespec_sub(*ts2, *ts1);
 
 	rate = mmc_test_rate(bytes, &ts);
+	iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
 
 	printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
-			 "seconds (%u kB/s, %u KiB/s)\n",
+			 "seconds (%u kB/s, %u KiB/s, %u.%02u IOPS)\n",
 			 mmc_hostname(test->card->host), sectors, sectors >> 1,
 			 (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec,
-			 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024);
+			 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024,
+			 iops / 100, iops % 100);
 
-	mmc_test_save_transfer_result(test, 1, sectors, ts, rate);
+	mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops);
 }
 
 /*
@@ -542,22 +548,24 @@ static void mmc_test_print_avg_rate(struct mmc_test_card *test, uint64_t bytes,
 				    unsigned int count, struct timespec *ts1,
 				    struct timespec *ts2)
 {
-	unsigned int rate, sectors = bytes >> 9;
+	unsigned int rate, iops, sectors = bytes >> 9;
 	uint64_t tot = bytes * count;
 	struct timespec ts;
 
 	ts = timespec_sub(*ts2, *ts1);
 
 	rate = mmc_test_rate(tot, &ts);
+	iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
 
 	printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
-			 "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n",
+			 "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
+			 "%u.%02u IOPS)\n",
 			 mmc_hostname(test->card->host), count, sectors, count,
 			 sectors >> 1, (sectors & 1 ? ".5" : ""),
 			 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
-			 rate / 1000, rate / 1024);
+			 rate / 1000, rate / 1024, iops / 100, iops % 100);
 
-	mmc_test_save_transfer_result(test, count, sectors, ts, rate);
+	mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
 }
 
 /*
@@ -1425,28 +1433,29 @@ static int mmc_test_area_cleanup(struct mmc_test_card *test)
 }
 
 /*
- * Initialize an area for testing large transfers.  The size of the area is the
- * preferred erase size which is a good size for optimal transfer speed.  Note
- * that is typically 4MiB for modern cards.  The test area is set to the middle
- * of the card because cards may have different charateristics at the front
- * (for FAT file system optimization).  Optionally, the area is erased (if the
- * card supports it) which may improve write performance.  Optionally, the area
- * is filled with data for subsequent read tests.
+ * Initialize an area for testing large transfers.  The test area is set to the
+ * middle of the card because cards may have different charateristics at the
+ * front (for FAT file system optimization).  Optionally, the area is erased
+ * (if the card supports it) which may improve write performance.  Optionally,
+ * the area is filled with data for subsequent read tests.
  */
 static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill)
 {
 	struct mmc_test_area *t = &test->area;
-	unsigned long min_sz = 64 * 1024;
+	unsigned long min_sz = 64 * 1024, sz;
 	int ret;
 
 	ret = mmc_test_set_blksize(test, 512);
 	if (ret)
 		return ret;
 
-	if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9)
-		t->max_sz = TEST_AREA_MAX_SIZE;
-	else
-		t->max_sz = (unsigned long)test->card->pref_erase << 9;
+	/* Make the test area size about 4MiB */
+	sz = (unsigned long)test->card->pref_erase << 9;
+	t->max_sz = sz;
+	while (t->max_sz < 4 * 1024 * 1024)
+		t->max_sz += sz;
+	while (t->max_sz > TEST_AREA_MAX_SIZE && t->max_sz > sz)
+		t->max_sz -= sz;
 
 	t->max_segs = test->card->host->max_segs;
 	t->max_seg_sz = test->card->host->max_seg_size;
@@ -1766,6 +1775,188 @@ static int mmc_test_profile_seq_trim_perf(struct mmc_test_card *test)
 	return 0;
 }
 
+static unsigned int rnd_next = 1;
+
+static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
+{
+	uint64_t r;
+
+	rnd_next = rnd_next * 1103515245 + 12345;
+	r = (rnd_next >> 16) & 0x7fff;
+	return (r * rnd_cnt) >> 15;
+}
+
+static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
+			     unsigned long sz)
+{
+	unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
+	unsigned int ssz;
+	struct timespec ts1, ts2, ts;
+	int ret;
+
+	ssz = sz >> 9;
+
+	rnd_addr = mmc_test_capacity(test->card) / 4;
+	range1 = rnd_addr / test->card->pref_erase;
+	range2 = range1 / ssz;
+
+	getnstimeofday(&ts1);
+	for (cnt = 0; cnt < UINT_MAX; cnt++) {
+		getnstimeofday(&ts2);
+		ts = timespec_sub(ts2, ts1);
+		if (ts.tv_sec >= 10)
+			break;
+		ea = mmc_test_rnd_num(range1);
+		if (ea == last_ea)
+			ea -= 1;
+		last_ea = ea;
+		dev_addr = rnd_addr + test->card->pref_erase * ea +
+			   ssz * mmc_test_rnd_num(range2);
+		ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
+		if (ret)
+			return ret;
+	}
+	if (print)
+		mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+	return 0;
+}
+
+static int mmc_test_random_perf(struct mmc_test_card *test, int write)
+{
+	unsigned int next;
+	unsigned long sz;
+	int ret;
+
+	for (sz = 512; sz < test->area.max_tfr; sz <<= 1) {
+		/*
+		 * When writing, try to get more consistent results by running
+		 * the test twice with exactly the same I/O but outputting the
+		 * results only for the 2nd run.
+		 */
+		if (write) {
+			next = rnd_next;
+			ret = mmc_test_rnd_perf(test, write, 0, sz);
+			if (ret)
+				return ret;
+			rnd_next = next;
+		}
+		ret = mmc_test_rnd_perf(test, write, 1, sz);
+		if (ret)
+			return ret;
+	}
+	sz = test->area.max_tfr;
+	if (write) {
+		next = rnd_next;
+		ret = mmc_test_rnd_perf(test, write, 0, sz);
+		if (ret)
+			return ret;
+		rnd_next = next;
+	}
+	return mmc_test_rnd_perf(test, write, 1, sz);
+}
+
+/*
+ * Random read performance by transfer size.
+ */
+static int mmc_test_random_read_perf(struct mmc_test_card *test)
+{
+	return mmc_test_random_perf(test, 0);
+}
+
+/*
+ * Random write performance by transfer size.
+ */
+static int mmc_test_random_write_perf(struct mmc_test_card *test)
+{
+	return mmc_test_random_perf(test, 1);
+}
+
+static int mmc_test_seq_perf(struct mmc_test_card *test, int write,
+			     unsigned int tot_sz, int max_scatter)
+{
+	unsigned int dev_addr, i, cnt, sz, ssz;
+	struct timespec ts1, ts2, ts;
+	int ret;
+
+	sz = test->area.max_tfr;
+	/*
+	 * In the case of a maximally scattered transfer, the maximum transfer
+	 * size is further limited by using PAGE_SIZE segments.
+	 */
+	if (max_scatter) {
+		struct mmc_test_area *t = &test->area;
+		unsigned long max_tfr;
+
+		if (t->max_seg_sz >= PAGE_SIZE)
+			max_tfr = t->max_segs * PAGE_SIZE;
+		else
+			max_tfr = t->max_segs * t->max_seg_sz;
+		if (sz > max_tfr)
+			sz = max_tfr;
+	}
+
+	ssz = sz >> 9;
+	dev_addr = mmc_test_capacity(test->card) / 4;
+	if (tot_sz > dev_addr << 9)
+		tot_sz = dev_addr << 9;
+	cnt = tot_sz / sz;
+	dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+
+	getnstimeofday(&ts1);
+	for (i = 0; i < cnt; i++) {
+		ret = mmc_test_area_io(test, sz, dev_addr, write,
+				       max_scatter, 0);
+		if (ret)
+			return ret;
+		dev_addr += ssz;
+	}
+	getnstimeofday(&ts2);
+
+	ts = timespec_sub(ts2, ts1);
+	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+
+	return 0;
+}
+
+static int mmc_test_large_seq_perf(struct mmc_test_card *test, int write)
+{
+	int ret, i;
+
+	for (i = 0; i < 10; i++) {
+		ret = mmc_test_seq_perf(test, write, 10 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < 5; i++) {
+		ret = mmc_test_seq_perf(test, write, 100 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < 3; i++) {
+		ret = mmc_test_seq_perf(test, write, 1000 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+/*
+ * Large sequential read performance.
+ */
+static int mmc_test_large_seq_read_perf(struct mmc_test_card *test)
+{
+	return mmc_test_large_seq_perf(test, 0);
+}
+
+/*
+ * Large sequential write performance.
+ */
+static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
+{
+	return mmc_test_large_seq_perf(test, 1);
+}
+
 static const struct mmc_test_case mmc_test_cases[] = {
 	{
 		.name = "Basic write (no data verification)",
@@ -2005,6 +2196,34 @@ static const struct mmc_test_case mmc_test_cases[] = {
 		.cleanup = mmc_test_area_cleanup,
 	},
 
+	{
+		.name = "Random read performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_random_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Random write performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_random_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Large sequential read into scattered pages",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_large_seq_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Large sequential write from scattered pages",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_large_seq_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
 };
 
 static DEFINE_MUTEX(mmc_test_lock);
@@ -2148,11 +2367,11 @@ static int mtf_test_show(struct seq_file *sf, void *data)
 		seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
 
 		list_for_each_entry(tr, &gr->tr_lst, link) {
-			seq_printf(sf, "%u %d %lu.%09lu %u\n",
+			seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n",
 				tr->count, tr->sectors,
 				(unsigned long)tr->ts.tv_sec,
 				(unsigned long)tr->ts.tv_nsec,
-				tr->rate);
+				tr->rate, tr->iops / 100, tr->iops % 100);
 		}
 	}
 
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c
index a071696..c8c9edb 100644
--- a/drivers/mmc/card/sdio_uart.c
+++ b/drivers/mmc/card/sdio_uart.c
@@ -956,7 +956,7 @@ static int sdio_uart_break_ctl(struct tty_struct *tty, int break_state)
 	return 0;
 }
 
-static int sdio_uart_tiocmget(struct tty_struct *tty, struct file *file)
+static int sdio_uart_tiocmget(struct tty_struct *tty)
 {
 	struct sdio_uart_port *port = tty->driver_data;
 	int result;
@@ -970,7 +970,7 @@ static int sdio_uart_tiocmget(struct tty_struct *tty, struct file *file)
 	return result;
 }
 
-static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file,
+static int sdio_uart_tiocmset(struct tty_struct *tty,
 			      unsigned int set, unsigned int clear)
 {
 	struct sdio_uart_port *port = tty->driver_data;
diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 86b4791..6395019 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_MMC)		+= mmc_core.o
 mmc_core-y			:= core.o bus.o host.o \
 				   mmc.o mmc_ops.o sd.o sd_ops.o \
 				   sdio.o sdio_ops.o sdio_bus.o \
-				   sdio_cis.o sdio_io.o sdio_irq.o
+				   sdio_cis.o sdio_io.o sdio_irq.o \
+				   quirks.o
 
 mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 150b5f3..1f453ac 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -167,8 +167,6 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 
 	WARN_ON(!host->claimed);
 
-	led_trigger_event(host->led, LED_FULL);
-
 	mrq->cmd->error = 0;
 	mrq->cmd->mrq = mrq;
 	if (mrq->data) {
@@ -194,6 +192,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
 		}
 	}
 	mmc_host_clk_ungate(host);
+	led_trigger_event(host->led, LED_FULL);
 	host->ops->request(host, mrq);
 }
 
@@ -528,7 +527,14 @@ int mmc_try_claim_host(struct mmc_host *host)
 }
 EXPORT_SYMBOL(mmc_try_claim_host);
 
-static void mmc_do_release_host(struct mmc_host *host)
+/**
+ *	mmc_do_release_host - release a claimed host
+ *	@host: mmc host to release
+ *
+ *	If you successfully claimed a host, this function will
+ *	release it again.
+ */
+void mmc_do_release_host(struct mmc_host *host)
 {
 	unsigned long flags;
 
@@ -543,6 +549,7 @@ static void mmc_do_release_host(struct mmc_host *host)
 		wake_up(&host->wq);
 	}
 }
+EXPORT_SYMBOL(mmc_do_release_host);
 
 void mmc_host_deeper_disable(struct work_struct *work)
 {
@@ -1002,6 +1009,13 @@ static void mmc_power_off(struct mmc_host *host)
 {
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
+
+	/*
+	 * Reset ocr mask to be the highest possible voltage supported for
+	 * this mmc host. This value will be used at next power up.
+	 */
+	host->ocr = 1 << (fls(host->ocr_avail) - 1);
+
 	if (!mmc_host_is_spi(host)) {
 		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
 		host->ios.chip_select = MMC_CS_DONTCARE;
@@ -1495,6 +1509,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
 		mmc_hostname(host), __func__, host->f_init);
 #endif
 	mmc_power_up(host);
+
+	/*
+	 * sdio_reset sends CMD52 to reset card.  Since we do not know
+	 * if the card is being re-initialized, just send it.  CMD52
+	 * should be ignored by SD/eMMC cards.
+	 */
 	sdio_reset(host);
 	mmc_go_idle(host);
 
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index ca1fdde..20b1c08 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -61,6 +61,8 @@ int mmc_attach_mmc(struct mmc_host *host);
 int mmc_attach_sd(struct mmc_host *host);
 int mmc_attach_sdio(struct mmc_host *host);
 
+void mmc_fixup_device(struct mmc_card *card);
+
 /* Module parameters */
 extern int use_spi_crc;
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index b3ac6c5..461e6a1 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -160,10 +160,7 @@ static bool mmc_host_may_gate_card(struct mmc_card *card)
 	 * gate the clock, because there is somebody out there that may still
 	 * be using it.
 	 */
-	if (mmc_card_sdio(card))
-		return false;
-
-	return true;
+	return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING);
 }
 
 /**
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 16006ef..14e95f3 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -302,6 +302,44 @@ static int mmc_read_ext_csd(struct mmc_card *card)
 	}
 
 	if (card->ext_csd.rev >= 4) {
+		/*
+		 * Enhanced area feature support -- check whether the eMMC
+		 * card has the Enhanced area enabled.  If so, export enhanced
+		 * area offset and size to user by adding sysfs interface.
+		 */
+		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+				(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+			u8 hc_erase_grp_sz =
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+			u8 hc_wp_grp_sz =
+				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+			card->ext_csd.enhanced_area_en = 1;
+			/*
+			 * calculate the enhanced data area offset, in bytes
+			 */
+			card->ext_csd.enhanced_area_offset =
+				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
+				(ext_csd[137] << 8) + ext_csd[136];
+			if (mmc_card_blockaddr(card))
+				card->ext_csd.enhanced_area_offset <<= 9;
+			/*
+			 * calculate the enhanced data area size, in kilobytes
+			 */
+			card->ext_csd.enhanced_area_size =
+				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
+				ext_csd[140];
+			card->ext_csd.enhanced_area_size *=
+				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+			card->ext_csd.enhanced_area_size <<= 9;
+		} else {
+			/*
+			 * If the enhanced area is not enabled, disable these
+			 * device attributes.
+			 */
+			card->ext_csd.enhanced_area_offset = -EINVAL;
+			card->ext_csd.enhanced_area_size = -EINVAL;
+		}
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =
@@ -336,6 +374,9 @@ 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(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
+		card->ext_csd.enhanced_area_offset);
+MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
 
 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -349,6 +390,8 @@ static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_enhanced_area_offset.attr,
+	&dev_attr_enhanced_area_size.attr,
 	NULL,
 };
 
@@ -378,6 +421,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	int err, ddr = 0;
 	u32 cid[4];
 	unsigned int max_dtr;
+	u32 rocr;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
@@ -391,7 +435,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 	mmc_go_idle(host);
 
 	/* The extra bit indicates that we support high capacity */
-	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
+	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
 	if (err)
 		goto err;
 
@@ -479,11 +523,51 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		err = mmc_read_ext_csd(card);
 		if (err)
 			goto free_card;
+
+		/* If doing byte addressing, check if required to do sector
+		 * addressing.  Handle the case of <2GB cards needing sector
+		 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
+		 * ocr register has bit 30 set for sector addressing.
+		 */
+		if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
+			mmc_card_set_blockaddr(card);
+
 		/* Erase size depends on CSD and Extended CSD */
 		mmc_set_erase_size(card);
 	}
 
 	/*
+	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
+	 * bit.  This bit will be lost everytime after a reset or power off.
+	 */
+	if (card->ext_csd.enhanced_area_en) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_ERASE_GROUP_DEF, 1);
+
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		if (err) {
+			err = 0;
+			/*
+			 * Just disable enhanced area off & sz
+			 * will try to enable ERASE_GROUP_DEF
+			 * during next time reinit
+			 */
+			card->ext_csd.enhanced_area_offset = -EINVAL;
+			card->ext_csd.enhanced_area_size = -EINVAL;
+		} else {
+			card->ext_csd.erase_group_def = 1;
+			/*
+			 * enable ERASE_GRP_DEF successfully.
+			 * This will affect the erase size, so
+			 * here need to reset erase size
+			 */
+			mmc_set_erase_size(card);
+		}
+	}
+
+	/*
 	 * Activate high speed (if supported)
 	 */
 	if ((card->ext_csd.hs_max_dtr != 0) &&
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
new file mode 100644
index 0000000..11118b74
--- /dev/null
+++ b/drivers/mmc/core/quirks.c
@@ -0,0 +1,84 @@
+/*
+ *  This file contains work-arounds for many known sdio hardware
+ *  bugs.
+ *
+ *  Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com>
+ *  Inspired from pci fixup code:
+ *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mmc/card.h>
+#include <linux/mod_devicetable.h>
+
+/*
+ *  The world is not perfect and supplies us with broken mmc/sdio devices.
+ *  For at least a part of these bugs we need a work-around
+ */
+
+struct mmc_fixup {
+	u16 vendor, device;	/* You can use SDIO_ANY_ID here of course */
+	void (*vendor_fixup)(struct mmc_card *card, int data);
+	int data;
+};
+
+/*
+ * This hook just adds a quirk unconditionnally
+ */
+static void __maybe_unused add_quirk(struct mmc_card *card, int data)
+{
+	card->quirks |= data;
+}
+
+/*
+ * This hook just removes a quirk unconditionnally
+ */
+static void __maybe_unused remove_quirk(struct mmc_card *card, int data)
+{
+	card->quirks &= ~data;
+}
+
+/*
+ * This hook just adds a quirk for all sdio devices
+ */
+static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
+{
+	if (mmc_card_sdio(card))
+		card->quirks |= data;
+}
+
+#ifndef SDIO_VENDOR_ID_TI
+#define SDIO_VENDOR_ID_TI		0x0097
+#endif
+
+#ifndef SDIO_DEVICE_ID_TI_WL1271
+#define SDIO_DEVICE_ID_TI_WL1271	0x4076
+#endif
+
+static const struct mmc_fixup mmc_fixup_methods[] = {
+	/* by default sdio devices are considered CLK_GATING broken */
+	/* good cards will be whitelisted as they are tested */
+	{ SDIO_ANY_ID, SDIO_ANY_ID,
+		add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING },
+	{ SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
+		remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING },
+	{ 0 }
+};
+
+void mmc_fixup_device(struct mmc_card *card)
+{
+	const struct mmc_fixup *f;
+
+	for (f = mmc_fixup_methods; f->vendor_fixup; f++) {
+		if ((f->vendor == card->cis.vendor
+		     || f->vendor == (u16) SDIO_ANY_ID) &&
+		    (f->device == card->cis.device
+		     || f->device == (u16) SDIO_ANY_ID)) {
+			dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
+			f->vendor_fixup(card, f->data);
+		}
+	}
+}
+EXPORT_SYMBOL(mmc_fixup_device);
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index d18c32b..6dac89f 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -21,6 +21,7 @@
 #include "core.h"
 #include "bus.h"
 #include "mmc_ops.h"
+#include "sd.h"
 #include "sd_ops.h"
 
 static const unsigned int tran_exp[] = {
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index ebc62ad..db0f0b4 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -395,6 +395,14 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 		if (err)
 			goto remove;
 
+		/*
+		 * Update oldcard with the new RCA received from the SDIO
+		 * device -- we're doing this so that it's updated in the
+		 * "card" struct when oldcard overwrites that later.
+		 */
+		if (oldcard)
+			oldcard->rca = card->rca;
+
 		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
@@ -458,6 +466,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
 
 		card = oldcard;
 	}
+	mmc_fixup_device(card);
 
 	if (card->type == MMC_TYPE_SD_COMBO) {
 		err = mmc_sd_setup_card(host, card, oldcard != NULL);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index afe8c6f..1a21c64 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -225,7 +225,7 @@ config MMC_OMAP
 
 config MMC_OMAP_HS
 	tristate "TI OMAP High Speed Multimedia Card Interface support"
-	depends on ARCH_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
+	depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
 	help
 	  This selects the TI OMAP High Speed Multimedia card Interface.
 	  If you have an OMAP2430 or OMAP3 board or OMAP4 board with a
@@ -311,7 +311,7 @@ config MMC_MSM
 
 config MMC_MXC
 	tristate "Freescale i.MX2/3 Multimedia Card Interface support"
-	depends on ARCH_MXC
+	depends on MACH_MX21 || MACH_MX27 || ARCH_MX31
 	help
 	  This selects the Freescale i.MX2/3 Multimedia card Interface.
 	  If you have a i.MX platform with a Multimedia Card slot,
@@ -319,6 +319,15 @@ config MMC_MXC
 
 	  If unsure, say N.
 
+config MMC_MXS
+	tristate "Freescale MXS Multimedia Card Interface support"
+	depends on ARCH_MXS && MXS_DMA
+	help
+	  This selects the Freescale SSP MMC controller found on MXS based
+	  platforms like mx23/28.
+
+	  If unsure, say N.
+
 config MMC_TIFM_SD
 	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index e834fb2..30aa686 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_MMC_ARMMMCI)	+= mmci.o
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
 obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
 obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
+obj-$(CONFIG_MMC_MXS)		+= mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(CONFIG_MMC_SDHCI_PXA)	+= sdhci-pxa.o
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index ad2a7a0..80bc9a5 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -578,7 +578,8 @@ static void atmci_dma_cleanup(struct atmel_mci *host)
 	struct mmc_data			*data = host->data;
 
 	if (data)
-		dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+		dma_unmap_sg(host->dma.chan->device->dev,
+			     data->sg, data->sg_len,
 			     ((data->flags & MMC_DATA_WRITE)
 			      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
 }
@@ -588,7 +589,7 @@ static void atmci_stop_dma(struct atmel_mci *host)
 	struct dma_chan *chan = host->data_chan;
 
 	if (chan) {
-	  chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		dmaengine_terminate_all(chan);
 		atmci_dma_cleanup(host);
 	} else {
 		/* Data transfer was stopped by the interrupt handler */
@@ -684,11 +685,11 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
 	else
 		direction = DMA_TO_DEVICE;
 
-	sglen = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, direction);
-	if (sglen != data->sg_len)
-		goto unmap_exit;
+	sglen = dma_map_sg(chan->device->dev, data->sg,
+			   data->sg_len, direction);
+
 	desc = chan->device->device_prep_slave_sg(chan,
-			data->sg, data->sg_len, direction,
+			data->sg, sglen, direction,
 			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc)
 		goto unmap_exit;
@@ -699,7 +700,7 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
 
 	return 0;
 unmap_exit:
-	dma_unmap_sg(&host->pdev->dev, data->sg, sglen, direction);
+	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction);
 	return -ENOMEM;
 }
 
@@ -709,8 +710,8 @@ static void atmci_submit_data(struct atmel_mci *host)
 	struct dma_async_tx_descriptor	*desc = host->dma.data_desc;
 
 	if (chan) {
-		desc->tx_submit(desc);
-		chan->device->device_issue_pending(chan);
+		dmaengine_submit(desc);
+		dma_async_issue_pending(chan);
 	}
 }
 
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index 66b4ce5..ce2a47b 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -205,7 +205,7 @@ static int cb710_wait_while_busy(struct cb710_slot *slot, uint8_t mask)
 			"WAIT12: waited %d loops, mask %02X, entry val %08X, exit val %08X\n",
 			limit, mask, e, x);
 #endif
-	return 0;
+	return err;
 }
 
 static void cb710_mmc_set_transfer_size(struct cb710_slot *slot,
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 2fcc825..5a61406 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -32,6 +32,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/dw_mmc.h>
 #include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
 
 #include "dw_mmc.h"
 
@@ -562,7 +563,8 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
 			     SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
 
 		/* enable clock */
-		mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE);
+		mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE |
+			   SDMMC_CLKEN_LOW_PWR);
 
 		/* inform CIU */
 		mci_send_cmd(slot,
@@ -661,6 +663,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct dw_mci_slot *slot = mmc_priv(mmc);
+	u32 regs;
 
 	/* set default 1 bit mode */
 	slot->ctype = SDMMC_CTYPE_1BIT;
@@ -672,6 +675,16 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	case MMC_BUS_WIDTH_4:
 		slot->ctype = SDMMC_CTYPE_4BIT;
 		break;
+	case MMC_BUS_WIDTH_8:
+		slot->ctype = SDMMC_CTYPE_8BIT;
+		break;
+	}
+
+	/* DDR mode set */
+	if (ios->ddr) {
+		regs = mci_readl(slot->host, UHS_REG);
+		regs |= (0x1 << slot->id) << 16;
+		mci_writel(slot->host, UHS_REG, regs);
 	}
 
 	if (ios->clock) {
@@ -717,7 +730,9 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	struct dw_mci_board *brd = slot->host->pdata;
 
 	/* Use platform get_cd function, else try onboard card detect */
-	if (brd->get_cd)
+	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
+		present = 1;
+	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
@@ -1019,13 +1034,10 @@ 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, old_len, count = 0;
+	unsigned int nbytes = 0, len;
 
 	do {
 		len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift;
-		if (count == 0)
-			old_len = len;
-
 		if (offset + len <= sg->length) {
 			host->pull_data(host, (void *)(buf + offset), len);
 
@@ -1070,7 +1082,6 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
 			tasklet_schedule(&host->tasklet);
 			return;
 		}
-		count++;
 	} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
 	len = SDMMC_GET_FCNT(mci_readl(host, STATUS));
 	host->pio_offset = offset;
@@ -1395,7 +1406,11 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	if (host->pdata->setpower)
 		host->pdata->setpower(id, 0);
 
-	mmc->caps = 0;
+	if (host->pdata->caps)
+		mmc->caps = host->pdata->caps;
+	else
+		mmc->caps = 0;
+
 	if (host->pdata->get_bus_wd)
 		if (host->pdata->get_bus_wd(slot->id) >= 4)
 			mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1426,6 +1441,13 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	}
 #endif /* CONFIG_MMC_DW_IDMAC */
 
+	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+	if (IS_ERR(host->vmmc)) {
+		printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc));
+		host->vmmc = NULL;
+	} else
+		regulator_enable(host->vmmc);
+
 	if (dw_mci_get_cd(mmc))
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 	else
@@ -1441,6 +1463,12 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 	/* Card initially undetected */
 	slot->last_detect_state = 0;
 
+	/*
+	 * Card may have been plugged in prior to boot so we
+	 * need to run the detect tasklet
+	 */
+	tasklet_schedule(&host->card_tasklet);
+
 	return 0;
 }
 
@@ -1619,8 +1647,9 @@ static int dw_mci_probe(struct platform_device *pdev)
 	 */
 	fifo_size = mci_readl(host, FIFOTH);
 	fifo_size = (fifo_size >> 16) & 0x7ff;
-	mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
-				  ((fifo_size/2) << 0)));
+	host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
+			((fifo_size/2) << 0));
+	mci_writel(host, FIFOTH, host->fifoth_val);
 
 	/* disable clock to CIU */
 	mci_writel(host, CLKENA, 0);
@@ -1683,6 +1712,12 @@ err_dmaunmap:
 			  host->sg_cpu, host->sg_dma);
 	iounmap(host->regs);
 
+	if (host->vmmc) {
+		regulator_disable(host->vmmc);
+		regulator_put(host->vmmc);
+	}
+
+
 err_freehost:
 	kfree(host);
 	return ret;
@@ -1714,6 +1749,11 @@ static int __exit dw_mci_remove(struct platform_device *pdev)
 	if (host->use_dma && host->dma_ops->exit)
 		host->dma_ops->exit(host);
 
+	if (host->vmmc) {
+		regulator_disable(host->vmmc);
+		regulator_put(host->vmmc);
+	}
+
 	iounmap(host->regs);
 
 	kfree(host);
@@ -1729,6 +1769,9 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
 	int i, ret;
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
+	if (host->vmmc)
+		regulator_enable(host->vmmc);
+
 	for (i = 0; i < host->num_slots; i++) {
 		struct dw_mci_slot *slot = host->slot[i];
 		if (!slot)
@@ -1744,6 +1787,9 @@ static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg)
 		}
 	}
 
+	if (host->vmmc)
+		regulator_disable(host->vmmc);
+
 	return 0;
 }
 
@@ -1752,6 +1798,23 @@ static int dw_mci_resume(struct platform_device *pdev)
 	int i, ret;
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
+	if (host->dma_ops->init)
+		host->dma_ops->init(host);
+
+	if (!mci_wait_reset(&pdev->dev, host)) {
+		ret = -ENODEV;
+		return ret;
+	}
+
+	/* Restore the old value at FIFOTH register */
+	mci_writel(host, FIFOTH, host->fifoth_val);
+
+	mci_writel(host, RINTSTS, 0xFFFFFFFF);
+	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+		   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
+
 	for (i = 0; i < host->num_slots; i++) {
 		struct dw_mci_slot *slot = host->slot[i];
 		if (!slot)
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 5dd55a7..23c662a 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -43,6 +43,7 @@
 #define SDMMC_USRID		0x068
 #define SDMMC_VERID		0x06c
 #define SDMMC_HCON		0x070
+#define SDMMC_UHS_REG		0x074
 #define SDMMC_BMOD		0x080
 #define SDMMC_PLDMND		0x084
 #define SDMMC_DBADDR		0x088
@@ -51,7 +52,6 @@
 #define SDMMC_DSCADDR		0x094
 #define SDMMC_BUFADDR		0x098
 #define SDMMC_DATA		0x100
-#define SDMMC_DATA_ADR		0x100
 
 /* shift bit field */
 #define _SBF(f, v)		((v) << (f))
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c
index fd877f6..2f7fc0c 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -1516,21 +1516,17 @@ static int __devexit mmc_spi_remove(struct spi_device *spi)
 	return 0;
 }
 
-#if defined(CONFIG_OF)
 static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
 	{ .compatible = "mmc-spi-slot", },
 	{},
 };
-#endif
 
 static struct spi_driver mmc_spi_driver = {
 	.driver = {
 		.name =		"mmc_spi",
 		.bus =		&spi_bus_type,
 		.owner =	THIS_MODULE,
-#if defined(CONFIG_OF)
 		.of_match_table = mmc_spi_of_match_table,
-#endif
 	},
 	.probe =	mmc_spi_probe,
 	.remove =	__devexit_p(mmc_spi_remove),
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 2d6de3e..5bbb87d 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -2,7 +2,7 @@
  *  linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver
  *
  *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
- *  Copyright (C) 2010 ST-Ericsson AB.
+ *  Copyright (C) 2010 ST-Ericsson SA
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -25,8 +25,10 @@
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
 #include <linux/gpio.h>
-#include <linux/amba/mmci.h>
 #include <linux/regulator/consumer.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/amba/mmci.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -142,9 +144,6 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 	host->mrq = NULL;
 	host->cmd = NULL;
 
-	if (mrq->data)
-		mrq->data->bytes_xfered = host->data_xfered;
-
 	/*
 	 * Need to drop the host lock here; mmc_request_done may call
 	 * back into the driver...
@@ -189,6 +188,248 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
 	sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
 }
 
+/*
+ * All the DMA operation mode stuff goes inside this ifdef.
+ * This assumes that you have a generic DMA device interface,
+ * no custom DMA interfaces are supported.
+ */
+#ifdef CONFIG_DMA_ENGINE
+static void __devinit mmci_dma_setup(struct mmci_host *host)
+{
+	struct mmci_platform_data *plat = host->plat;
+	const char *rxname, *txname;
+	dma_cap_mask_t mask;
+
+	if (!plat || !plat->dma_filter) {
+		dev_info(mmc_dev(host->mmc), "no DMA platform data\n");
+		return;
+	}
+
+	/* Try to acquire a generic DMA engine slave channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/*
+	 * If only an RX channel is specified, the driver will
+	 * attempt to use it bidirectionally, however if it is
+	 * is specified but cannot be located, DMA will be disabled.
+	 */
+	if (plat->dma_rx_param) {
+		host->dma_rx_channel = dma_request_channel(mask,
+							   plat->dma_filter,
+							   plat->dma_rx_param);
+		/* E.g if no DMA hardware is present */
+		if (!host->dma_rx_channel)
+			dev_err(mmc_dev(host->mmc), "no RX DMA channel\n");
+	}
+
+	if (plat->dma_tx_param) {
+		host->dma_tx_channel = dma_request_channel(mask,
+							   plat->dma_filter,
+							   plat->dma_tx_param);
+		if (!host->dma_tx_channel)
+			dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n");
+	} else {
+		host->dma_tx_channel = host->dma_rx_channel;
+	}
+
+	if (host->dma_rx_channel)
+		rxname = dma_chan_name(host->dma_rx_channel);
+	else
+		rxname = "none";
+
+	if (host->dma_tx_channel)
+		txname = dma_chan_name(host->dma_tx_channel);
+	else
+		txname = "none";
+
+	dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n",
+		 rxname, txname);
+
+	/*
+	 * Limit the maximum segment size in any SG entry according to
+	 * the parameters of the DMA engine device.
+	 */
+	if (host->dma_tx_channel) {
+		struct device *dev = host->dma_tx_channel->device->dev;
+		unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+		if (max_seg_size < host->mmc->max_seg_size)
+			host->mmc->max_seg_size = max_seg_size;
+	}
+	if (host->dma_rx_channel) {
+		struct device *dev = host->dma_rx_channel->device->dev;
+		unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+		if (max_seg_size < host->mmc->max_seg_size)
+			host->mmc->max_seg_size = max_seg_size;
+	}
+}
+
+/*
+ * This is used in __devinit or __devexit so inline it
+ * so it can be discarded.
+ */
+static inline void mmci_dma_release(struct mmci_host *host)
+{
+	struct mmci_platform_data *plat = host->plat;
+
+	if (host->dma_rx_channel)
+		dma_release_channel(host->dma_rx_channel);
+	if (host->dma_tx_channel && plat->dma_tx_param)
+		dma_release_channel(host->dma_tx_channel);
+	host->dma_rx_channel = host->dma_tx_channel = NULL;
+}
+
+static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
+{
+	struct dma_chan *chan = host->dma_current;
+	enum dma_data_direction dir;
+	u32 status;
+	int i;
+
+	/* Wait up to 1ms for the DMA to complete */
+	for (i = 0; ; i++) {
+		status = readl(host->base + MMCISTATUS);
+		if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100)
+			break;
+		udelay(10);
+	}
+
+	/*
+	 * Check to see whether we still have some data left in the FIFO -
+	 * this catches DMA controllers which are unable to monitor the
+	 * DMALBREQ and DMALSREQ signals while allowing us to DMA to non-
+	 * contiguous buffers.  On TX, we'll get a FIFO underrun error.
+	 */
+	if (status & MCI_RXDATAAVLBLMASK) {
+		dmaengine_terminate_all(chan);
+		if (!data->error)
+			data->error = -EIO;
+	}
+
+	if (data->flags & MMC_DATA_WRITE) {
+		dir = DMA_TO_DEVICE;
+	} else {
+		dir = DMA_FROM_DEVICE;
+	}
+
+	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
+
+	/*
+	 * Use of DMA with scatter-gather is impossible.
+	 * Give up with DMA and switch back to PIO mode.
+	 */
+	if (status & MCI_RXDATAAVLBLMASK) {
+		dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n");
+		mmci_dma_release(host);
+	}
+}
+
+static void mmci_dma_data_error(struct mmci_host *host)
+{
+	dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n");
+	dmaengine_terminate_all(host->dma_current);
+}
+
+static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+	struct variant_data *variant = host->variant;
+	struct dma_slave_config conf = {
+		.src_addr = host->phybase + MMCIFIFO,
+		.dst_addr = host->phybase + MMCIFIFO,
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+		.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+		.src_maxburst = variant->fifohalfsize >> 2, /* # of words */
+		.dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
+	};
+	struct mmc_data *data = host->data;
+	struct dma_chan *chan;
+	struct dma_device *device;
+	struct dma_async_tx_descriptor *desc;
+	int nr_sg;
+
+	host->dma_current = NULL;
+
+	if (data->flags & MMC_DATA_READ) {
+		conf.direction = DMA_FROM_DEVICE;
+		chan = host->dma_rx_channel;
+	} else {
+		conf.direction = DMA_TO_DEVICE;
+		chan = host->dma_tx_channel;
+	}
+
+	/* If there's no DMA channel, fall back to PIO */
+	if (!chan)
+		return -EINVAL;
+
+	/* If less than or equal to the fifo size, don't bother with DMA */
+	if (host->size <= variant->fifosize)
+		return -EINVAL;
+
+	device = chan->device;
+	nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction);
+	if (nr_sg == 0)
+		return -EINVAL;
+
+	dmaengine_slave_config(chan, &conf);
+	desc = device->device_prep_slave_sg(chan, data->sg, nr_sg,
+					    conf.direction, DMA_CTRL_ACK);
+	if (!desc)
+		goto unmap_exit;
+
+	/* Okay, go for it. */
+	host->dma_current = chan;
+
+	dev_vdbg(mmc_dev(host->mmc),
+		 "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
+		 data->sg_len, data->blksz, data->blocks, data->flags);
+	dmaengine_submit(desc);
+	dma_async_issue_pending(chan);
+
+	datactrl |= MCI_DPSM_DMAENABLE;
+
+	/* Trigger the DMA transfer */
+	writel(datactrl, host->base + MMCIDATACTRL);
+
+	/*
+	 * Let the MMCI say when the data is ended and it's time
+	 * to fire next DMA request. When that happens, MMCI will
+	 * call mmci_data_end()
+	 */
+	writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
+	       host->base + MMCIMASK0);
+	return 0;
+
+unmap_exit:
+	dmaengine_terminate_all(chan);
+	dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
+	return -ENOMEM;
+}
+#else
+/* Blank functions if the DMA engine is not available */
+static inline void mmci_dma_setup(struct mmci_host *host)
+{
+}
+
+static inline void mmci_dma_release(struct mmci_host *host)
+{
+}
+
+static inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
+{
+}
+
+static inline void mmci_dma_data_error(struct mmci_host *host)
+{
+}
+
+static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 {
 	struct variant_data *variant = host->variant;
@@ -202,9 +443,7 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 
 	host->data = data;
 	host->size = data->blksz * data->blocks;
-	host->data_xfered = 0;
-
-	mmci_init_sg(host, data);
+	data->bytes_xfered = 0;
 
 	clks = (unsigned long long)data->timeout_ns * host->cclk;
 	do_div(clks, 1000000000UL);
@@ -219,15 +458,29 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 	BUG_ON(1 << blksz_bits != data->blksz);
 
 	datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
-	if (data->flags & MMC_DATA_READ) {
+
+	if (data->flags & MMC_DATA_READ)
 		datactrl |= MCI_DPSM_DIRECTION;
+
+	/*
+	 * Attempt to use DMA operation mode, if this
+	 * should fail, fall back to PIO mode
+	 */
+	if (!mmci_dma_start_data(host, datactrl))
+		return;
+
+	/* IRQ mode, map the SG list for CPU reading/writing */
+	mmci_init_sg(host, data);
+
+	if (data->flags & MMC_DATA_READ) {
 		irqmask = MCI_RXFIFOHALFFULLMASK;
 
 		/*
-		 * If we have less than a FIFOSIZE of bytes to transfer,
-		 * trigger a PIO interrupt as soon as any data is available.
+		 * If we have less than the fifo 'half-full' threshold to
+		 * transfer, trigger a PIO interrupt as soon as any data
+		 * is available.
 		 */
-		if (host->size < variant->fifosize)
+		if (host->size < variant->fifohalfsize)
 			irqmask |= MCI_RXDATAAVLBLMASK;
 	} else {
 		/*
@@ -283,49 +536,51 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
 	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
 		u32 remain, success;
 
-		/* Calculate how far we are into the transfer */
+		/* Terminate the DMA transfer */
+		if (dma_inprogress(host))
+			mmci_dma_data_error(host);
+
+		/*
+		 * Calculate how far we are into the transfer.  Note that
+		 * the data counter gives the number of bytes transferred
+		 * on the MMC bus, not on the host side.  On reads, this
+		 * can be as much as a FIFO-worth of data ahead.  This
+		 * matters for FIFO overruns only.
+		 */
 		remain = readl(host->base + MMCIDATACNT);
 		success = data->blksz * data->blocks - remain;
 
-		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
+		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ, status 0x%08x at 0x%08x\n",
+			status, success);
 		if (status & MCI_DATACRCFAIL) {
 			/* Last block was not successful */
-			host->data_xfered = round_down(success - 1, data->blksz);
+			success -= 1;
 			data->error = -EILSEQ;
 		} else if (status & MCI_DATATIMEOUT) {
-			host->data_xfered = round_down(success, data->blksz);
 			data->error = -ETIMEDOUT;
-		} else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
-			host->data_xfered = round_down(success, data->blksz);
+		} else if (status & MCI_TXUNDERRUN) {
+			data->error = -EIO;
+		} else if (status & MCI_RXOVERRUN) {
+			if (success > host->variant->fifosize)
+				success -= host->variant->fifosize;
+			else
+				success = 0;
 			data->error = -EIO;
 		}
-
-		/*
-		 * We hit an error condition.  Ensure that any data
-		 * partially written to a page is properly coherent.
-		 */
-		if (data->flags & MMC_DATA_READ) {
-			struct sg_mapping_iter *sg_miter = &host->sg_miter;
-			unsigned long flags;
-
-			local_irq_save(flags);
-			if (sg_miter_next(sg_miter)) {
-				flush_dcache_page(sg_miter->page);
-				sg_miter_stop(sg_miter);
-			}
-			local_irq_restore(flags);
-		}
+		data->bytes_xfered = round_down(success, data->blksz);
 	}
 
 	if (status & MCI_DATABLOCKEND)
 		dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
 
 	if (status & MCI_DATAEND || data->error) {
+		if (dma_inprogress(host))
+			mmci_dma_unmap(host, data);
 		mmci_stop_data(host);
 
 		if (!data->error)
 			/* The error clause is handled above, success! */
-			host->data_xfered += data->blksz * data->blocks;
+			data->bytes_xfered = data->blksz * data->blocks;
 
 		if (!data->stop) {
 			mmci_request_end(host, data->mrq);
@@ -498,9 +753,6 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 		if (remain)
 			break;
 
-		if (status & MCI_RXACTIVE)
-			flush_dcache_page(sg_miter->page);
-
 		status = readl(base + MMCISTATUS);
 	} while (1);
 
@@ -509,10 +761,10 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
 	local_irq_restore(flags);
 
 	/*
-	 * If we're nearing the end of the read, switch to
-	 * "any data available" mode.
+	 * If we have less than the fifo 'half-full' threshold to transfer,
+	 * trigger a PIO interrupt as soon as any data is available.
 	 */
-	if (status & MCI_RXACTIVE && host->size < variant->fifosize)
+	if (status & MCI_RXACTIVE && host->size < variant->fifohalfsize)
 		mmci_set_mask1(host, MCI_RXDATAAVLBLMASK);
 
 	/*
@@ -713,7 +965,8 @@ static const struct mmc_host_ops mmci_ops = {
 	.get_cd		= mmci_get_cd,
 };
 
-static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit mmci_probe(struct amba_device *dev,
+	const struct amba_id *id)
 {
 	struct mmci_platform_data *plat = dev->dev.platform_data;
 	struct variant_data *variant = id->data;
@@ -776,6 +1029,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 		dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
 			host->mclk);
 	}
+	host->phybase = dev->res.start;
 	host->base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!host->base) {
 		ret = -ENOMEM;
@@ -903,9 +1157,12 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
 
 	amba_set_drvdata(dev, mmc);
 
-	dev_info(&dev->dev, "%s: PL%03x rev%u at 0x%08llx irq %d,%d\n",
-		mmc_hostname(mmc), amba_part(dev), amba_rev(dev),
-		(unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
+	dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n",
+		 mmc_hostname(mmc), amba_part(dev), amba_manf(dev),
+		 amba_rev(dev), (unsigned long long)dev->res.start,
+		 dev->irq[0], dev->irq[1]);
+
+	mmci_dma_setup(host);
 
 	mmc_add_host(mmc);
 
@@ -952,6 +1209,7 @@ static int __devexit mmci_remove(struct amba_device *dev)
 		writel(0, host->base + MMCICOMMAND);
 		writel(0, host->base + MMCIDATACTRL);
 
+		mmci_dma_release(host);
 		free_irq(dev->irq[0], host);
 		if (!host->singleirq)
 			free_irq(dev->irq[1], host);
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index c1df7b8..ec9a7bc6 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -148,8 +148,10 @@
 
 struct clk;
 struct variant_data;
+struct dma_chan;
 
 struct mmci_host {
+	phys_addr_t		phybase;
 	void __iomem		*base;
 	struct mmc_request	*mrq;
 	struct mmc_command	*cmd;
@@ -161,8 +163,6 @@ struct mmci_host {
 	int			gpio_cd_irq;
 	bool			singleirq;
 
-	unsigned int		data_xfered;
-
 	spinlock_t		lock;
 
 	unsigned int		mclk;
@@ -181,5 +181,16 @@ struct mmci_host {
 	struct sg_mapping_iter	sg_miter;
 	unsigned int		size;
 	struct regulator	*vcc;
+
+#ifdef CONFIG_DMA_ENGINE
+	/* DMA stuff */
+	struct dma_chan		*dma_current;
+	struct dma_chan		*dma_rx_channel;
+	struct dma_chan		*dma_tx_channel;
+
+#define dma_inprogress(host)	((host)->dma_current)
+#else
+#define dma_inprogress(host)	(0)
+#endif
 };
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 153ab97..a4c865a 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/memory.h>
 #include <linux/gfp.h>
+#include <linux/gpio.h>
 
 #include <asm/cacheflush.h>
 #include <asm/div64.h>
@@ -266,14 +267,6 @@ msmsdcc_dma_complete_tlet(unsigned long data)
 	dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
 		     host->dma.dir);
 
-	if (host->curr.user_pages) {
-		struct scatterlist *sg = host->dma.sg;
-		int i;
-
-		for (i = 0; i < host->dma.num_ents; i++)
-			flush_dcache_page(sg_page(sg++));
-	}
-
 	host->dma.sg = NULL;
 	host->dma.busy = 0;
 
@@ -941,6 +934,38 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
+{
+	struct msm_mmc_gpio_data *curr;
+	int i, rc = 0;
+
+	if (!host->plat->gpio_data && host->gpio_config_status == enable)
+		return;
+
+	curr = host->plat->gpio_data;
+	for (i = 0; i < curr->size; i++) {
+		if (enable) {
+			rc = gpio_request(curr->gpio[i].no,
+						curr->gpio[i].name);
+			if (rc) {
+				pr_err("%s: gpio_request(%d, %s) failed %d\n",
+					mmc_hostname(host->mmc),
+					curr->gpio[i].no,
+					curr->gpio[i].name, rc);
+				goto free_gpios;
+			}
+		} else {
+			gpio_free(curr->gpio[i].no);
+		}
+	}
+	host->gpio_config_status = enable;
+	return;
+
+free_gpios:
+	for (; i >= 0; i--)
+		gpio_free(curr->gpio[i].no);
+}
+
 static void
 msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
@@ -953,6 +978,8 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	msmsdcc_enable_clocks(host);
 
+	spin_unlock_irqrestore(&host->lock, flags);
+
 	if (ios->clock) {
 		if (ios->clock != host->clk_rate) {
 			rc = clk_set_rate(host->clk, ios->clock);
@@ -979,9 +1006,11 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
+		msmsdcc_setup_gpio(host, false);
 		break;
 	case MMC_POWER_UP:
 		pwr |= MCI_PWR_UP;
+		msmsdcc_setup_gpio(host, true);
 		break;
 	case MMC_POWER_ON:
 		pwr |= MCI_PWR_ON;
@@ -998,9 +1027,10 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		msmsdcc_writel(host, pwr, MMCIPOWER);
 	}
 #if BUSCLK_PWRSAVE
+	spin_lock_irqsave(&host->lock, flags);
 	msmsdcc_disable_clocks(host, 1);
-#endif
 	spin_unlock_irqrestore(&host->lock, flags);
+#endif
 }
 
 static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 939557a..42d7bbc 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -243,6 +243,7 @@ struct msmsdcc_host {
 	unsigned int		cmd_datactrl;
 	struct mmc_command	*cmd_cmd;
 	u32			cmd_c;
+	bool			gpio_config_status;
 
 	bool prog_scan;
 	bool prog_enable;
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c
index 4428594..cc20e02 100644
--- a/drivers/mmc/host/mxcmmc.c
+++ b/drivers/mmc/host/mxcmmc.c
@@ -32,16 +32,14 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/dmaengine.h>
 
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
 #include <mach/mmc.h>
 
-#ifdef CONFIG_ARCH_MX2
-#include <mach/dma-mx1-mx2.h>
-#define HAS_DMA
-#endif
+#include <mach/dma.h>
 
 #define DRIVER_NAME "mxc-mmc"
 
@@ -118,7 +116,8 @@ struct mxcmci_host {
 	void __iomem		*base;
 	int			irq;
 	int			detect_irq;
-	int			dma;
+	struct dma_chan		*dma;
+	struct dma_async_tx_descriptor *desc;
 	int			do_dma;
 	int			default_irq_mask;
 	int			use_sdio;
@@ -129,7 +128,6 @@ struct mxcmci_host {
 	struct mmc_command	*cmd;
 	struct mmc_data		*data;
 
-	unsigned int		dma_nents;
 	unsigned int		datasize;
 	unsigned int		dma_dir;
 
@@ -144,6 +142,11 @@ struct mxcmci_host {
 	spinlock_t		lock;
 
 	struct regulator	*vcc;
+
+	int			burstlen;
+	int			dmareq;
+	struct dma_slave_config dma_slave_config;
+	struct imx_dma_data	dma_data;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -206,17 +209,16 @@ static void mxcmci_softreset(struct mxcmci_host *host)
 
 	writew(0xff, host->base + MMC_REG_RES_TO);
 }
+static int mxcmci_setup_dma(struct mmc_host *mmc);
 
 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 {
 	unsigned int nob = data->blocks;
 	unsigned int blksz = data->blksz;
 	unsigned int datasize = nob * blksz;
-#ifdef HAS_DMA
 	struct scatterlist *sg;
-	int i;
-	int ret;
-#endif
+	int i, nents;
+
 	if (data->flags & MMC_DATA_STREAM)
 		nob = 0xffff;
 
@@ -227,7 +229,9 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 	writew(blksz, host->base + MMC_REG_BLK_LEN);
 	host->datasize = datasize;
 
-#ifdef HAS_DMA
+	if (!mxcmci_use_dma(host))
+		return 0;
+
 	for_each_sg(data->sg, sg, data->sg_len, i) {
 		if (sg->offset & 3 || sg->length & 3) {
 			host->do_dma = 0;
@@ -235,34 +239,30 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 		}
 	}
 
-	if (data->flags & MMC_DATA_READ) {
+	if (data->flags & MMC_DATA_READ)
 		host->dma_dir = DMA_FROM_DEVICE;
-		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-					     data->sg_len,  host->dma_dir);
-
-		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-				datasize,
-				host->res->start + MMC_REG_BUFFER_ACCESS,
-				DMA_MODE_READ);
-	} else {
+	else
 		host->dma_dir = DMA_TO_DEVICE;
-		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-					     data->sg_len,  host->dma_dir);
 
-		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-				datasize,
-				host->res->start + MMC_REG_BUFFER_ACCESS,
-				DMA_MODE_WRITE);
-	}
+	nents = dma_map_sg(host->dma->device->dev, data->sg,
+				     data->sg_len,  host->dma_dir);
+	if (nents != data->sg_len)
+		return -EINVAL;
+
+	host->desc = host->dma->device->device_prep_slave_sg(host->dma,
+		data->sg, data->sg_len, host->dma_dir,
+		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 
-	if (ret) {
-		dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret);
-		return ret;
+	if (!host->desc) {
+		dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
+				host->dma_dir);
+		host->do_dma = 0;
+		return 0; /* Fall back to PIO */
 	}
 	wmb();
 
-	imx_dma_enable(host->dma);
-#endif /* HAS_DMA */
+	dmaengine_submit(host->desc);
+
 	return 0;
 }
 
@@ -337,13 +337,11 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat)
 	struct mmc_data *data = host->data;
 	int data_error;
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host)) {
-		imx_dma_disable(host->dma);
-		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+		dmaengine_terminate_all(host->dma);
+		dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
 				host->dma_dir);
 	}
-#endif
 
 	if (stat & STATUS_ERR_MASK) {
 		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -545,7 +543,6 @@ static void mxcmci_datawork(struct work_struct *work)
 	}
 }
 
-#ifdef HAS_DMA
 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 {
 	struct mmc_data *data = host->data;
@@ -568,7 +565,6 @@ static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 		mxcmci_finish_request(host, host->req);
 	}
 }
-#endif /* HAS_DMA */
 
 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
 {
@@ -606,12 +602,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
 	sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
 	spin_unlock_irqrestore(&host->lock, flags);
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 	    (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
 		writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
 			host->base + MMC_REG_STATUS);
-#endif
 
 	if (sdio_irq) {
 		writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS);
@@ -621,14 +615,14 @@ static irqreturn_t mxcmci_irq(int irq, void *devid)
 	if (stat & STATUS_END_CMD_RESP)
 		mxcmci_cmd_done(host, stat);
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 		  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
 		mxcmci_data_done(host, stat);
-#endif
+
 	if (host->default_irq_mask &&
 		  (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
 		mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+
 	return IRQ_HANDLED;
 }
 
@@ -642,9 +636,10 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
 
 	host->req = req;
 	host->cmdat &= ~CMD_DAT_CONT_INIT;
-#ifdef HAS_DMA
-	host->do_dma = 1;
-#endif
+
+	if (host->dma)
+		host->do_dma = 1;
+
 	if (req->data) {
 		error = mxcmci_setup_data(host, req->data);
 		if (error) {
@@ -660,6 +655,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req)
 	}
 
 	error = mxcmci_start_cmd(host, req->cmd, cmdat);
+
 out:
 	if (error)
 		mxcmci_finish_request(host, req);
@@ -698,22 +694,46 @@ static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios)
 			prescaler, divider, clk_in, clk_ios);
 }
 
+static int mxcmci_setup_dma(struct mmc_host *mmc)
+{
+	struct mxcmci_host *host = mmc_priv(mmc);
+	struct dma_slave_config *config = &host->dma_slave_config;
+
+	config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
+	config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
+	config->dst_addr_width = 4;
+	config->src_addr_width = 4;
+	config->dst_maxburst = host->burstlen;
+	config->src_maxburst = host->burstlen;
+
+	return dmaengine_slave_config(host->dma, config);
+}
+
 static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mxcmci_host *host = mmc_priv(mmc);
-#ifdef HAS_DMA
-	unsigned int blen;
+	int burstlen, ret;
+
 	/*
 	 * use burstlen of 64 in 4 bit mode (--> reg value  0)
 	 * use burstlen of 16 in 1 bit mode (--> reg value 16)
 	 */
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
-		blen = 0;
+		burstlen = 64;
 	else
-		blen = 16;
+		burstlen = 16;
+
+	if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
+		host->burstlen = burstlen;
+		ret = mxcmci_setup_dma(mmc);
+		if (ret) {
+			dev_err(mmc_dev(host->mmc),
+				"failed to config DMA channel. Falling back to PIO\n");
+			dma_release_channel(host->dma);
+			host->do_dma = 0;
+		}
+	}
 
-	imx_dma_config_burstlen(host->dma, blen);
-#endif
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
 		host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
 	else
@@ -794,6 +814,18 @@ static void mxcmci_init_card(struct mmc_host *host, struct mmc_card *card)
 		host->caps |= MMC_CAP_4_BIT_DATA;
 }
 
+static bool filter(struct dma_chan *chan, void *param)
+{
+	struct mxcmci_host *host = param;
+
+	if (!imx_dma_is_general_purpose(chan))
+		return false;
+
+	chan->private = &host->dma_data;
+
+	return true;
+}
+
 static const struct mmc_host_ops mxcmci_ops = {
 	.request		= mxcmci_request,
 	.set_ios		= mxcmci_set_ios,
@@ -808,6 +840,7 @@ static int mxcmci_probe(struct platform_device *pdev)
 	struct mxcmci_host *host = NULL;
 	struct resource *iores, *r;
 	int ret = 0, irq;
+	dma_cap_mask_t mask;
 
 	printk(KERN_INFO "i.MX SDHC driver\n");
 
@@ -883,29 +916,23 @@ static int mxcmci_probe(struct platform_device *pdev)
 
 	writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
 
-#ifdef HAS_DMA
-	host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
-	if (host->dma < 0) {
-		dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
-		ret = -EBUSY;
-		goto out_clk_put;
-	}
-
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r) {
-		ret = -EINVAL;
-		goto out_free_dma;
+	if (r) {
+		host->dmareq = r->start;
+		host->dma_data.peripheral_type = IMX_DMATYPE_SDHC;
+		host->dma_data.priority = DMA_PRIO_LOW;
+		host->dma_data.dma_request = host->dmareq;
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		host->dma = dma_request_channel(mask, filter, host);
+		if (host->dma)
+			mmc->max_seg_size = dma_get_max_seg_size(
+					host->dma->device->dev);
 	}
 
-	ret = imx_dma_config_channel(host->dma,
-				     IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
-				     IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
-				     r->start, 0);
-	if (ret) {
-		dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n");
-		goto out_free_dma;
-	}
-#endif
+	if (!host->dma)
+		dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
+
 	INIT_WORK(&host->datawork, mxcmci_datawork);
 
 	ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host);
@@ -928,9 +955,8 @@ static int mxcmci_probe(struct platform_device *pdev)
 out_free_irq:
 	free_irq(host->irq, host);
 out_free_dma:
-#ifdef HAS_DMA
-	imx_dma_free(host->dma);
-#endif
+	if (host->dma)
+		dma_release_channel(host->dma);
 out_clk_put:
 	clk_disable(host->clk);
 	clk_put(host->clk);
@@ -960,9 +986,10 @@ static int mxcmci_remove(struct platform_device *pdev)
 
 	free_irq(host->irq, host);
 	iounmap(host->base);
-#ifdef HAS_DMA
-	imx_dma_free(host->dma);
-#endif
+
+	if (host->dma)
+		dma_release_channel(host->dma);
+
 	clk_disable(host->clk);
 	clk_put(host->clk);
 
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
new file mode 100644
index 0000000..99d39a6
--- /dev/null
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -0,0 +1,874 @@
+/*
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have 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/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/mmc.h>
+
+#define DRIVER_NAME	"mxs-mmc"
+
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT			(HZ/2)
+
+#define SSP_VERSION_LATEST	4
+#define ssp_is_old()		(host->version < SSP_VERSION_LATEST)
+
+/* SSP registers */
+#define HW_SSP_CTRL0				0x000
+#define  BM_SSP_CTRL0_RUN			(1 << 29)
+#define  BM_SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define  BM_SSP_CTRL0_IGNORE_CRC		(1 << 26)
+#define  BM_SSP_CTRL0_READ			(1 << 25)
+#define  BM_SSP_CTRL0_DATA_XFER			(1 << 24)
+#define  BP_SSP_CTRL0_BUS_WIDTH			(22)
+#define  BM_SSP_CTRL0_BUS_WIDTH			(0x3 << 22)
+#define  BM_SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
+#define  BM_SSP_CTRL0_LONG_RESP			(1 << 19)
+#define  BM_SSP_CTRL0_GET_RESP			(1 << 17)
+#define  BM_SSP_CTRL0_ENABLE			(1 << 16)
+#define  BP_SSP_CTRL0_XFER_COUNT		(0)
+#define  BM_SSP_CTRL0_XFER_COUNT		(0xffff)
+#define HW_SSP_CMD0				0x010
+#define  BM_SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define  BM_SSP_CMD0_SLOW_CLKING_EN		(1 << 22)
+#define  BM_SSP_CMD0_CONT_CLKING_EN		(1 << 21)
+#define  BM_SSP_CMD0_APPEND_8CYC		(1 << 20)
+#define  BP_SSP_CMD0_BLOCK_SIZE			(16)
+#define  BM_SSP_CMD0_BLOCK_SIZE			(0xf << 16)
+#define  BP_SSP_CMD0_BLOCK_COUNT		(8)
+#define  BM_SSP_CMD0_BLOCK_COUNT		(0xff << 8)
+#define  BP_SSP_CMD0_CMD			(0)
+#define  BM_SSP_CMD0_CMD			(0xff)
+#define HW_SSP_CMD1				0x020
+#define HW_SSP_XFER_SIZE			0x030
+#define HW_SSP_BLOCK_SIZE			0x040
+#define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT		(4)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_COUNT		(0xffffff << 4)
+#define  BP_SSP_BLOCK_SIZE_BLOCK_SIZE		(0)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_SIZE		(0xf)
+#define HW_SSP_TIMING				(ssp_is_old() ? 0x050 : 0x070)
+#define  BP_SSP_TIMING_TIMEOUT			(16)
+#define  BM_SSP_TIMING_TIMEOUT			(0xffff << 16)
+#define  BP_SSP_TIMING_CLOCK_DIVIDE		(8)
+#define  BM_SSP_TIMING_CLOCK_DIVIDE		(0xff << 8)
+#define  BP_SSP_TIMING_CLOCK_RATE		(0)
+#define  BM_SSP_TIMING_CLOCK_RATE		(0xff)
+#define HW_SSP_CTRL1				(ssp_is_old() ? 0x060 : 0x080)
+#define  BM_SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define  BM_SSP_CTRL1_SDIO_IRQ_EN		(1 << 30)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ		(1 << 29)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	(1 << 26)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	(1 << 24)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ		(1 << 23)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN	(1 << 20)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	(1 << 16)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN	(1 << 14)
+#define  BM_SSP_CTRL1_DMA_ENABLE		(1 << 13)
+#define  BM_SSP_CTRL1_POLARITY			(1 << 9)
+#define  BP_SSP_CTRL1_WORD_LENGTH		(4)
+#define  BM_SSP_CTRL1_WORD_LENGTH		(0xf << 4)
+#define  BP_SSP_CTRL1_SSP_MODE			(0)
+#define  BM_SSP_CTRL1_SSP_MODE			(0xf)
+#define HW_SSP_SDRESP0				(ssp_is_old() ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1				(ssp_is_old() ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2				(ssp_is_old() ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3				(ssp_is_old() ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS				(ssp_is_old() ? 0x0c0 : 0x100)
+#define  BM_SSP_STATUS_CARD_DETECT		(1 << 28)
+#define  BM_SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define HW_SSP_VERSION				(cpu_is_mx23() ? 0x110 : 0x130)
+#define  BP_SSP_VERSION_MAJOR			(24)
+
+#define BF_SSP(value, field)	(((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define MXS_MMC_IRQ_BITS	(BM_SSP_CTRL1_SDIO_IRQ		| \
+				 BM_SSP_CTRL1_RESP_ERR_IRQ	| \
+				 BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	| \
+				 BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	| \
+				 BM_SSP_CTRL1_DATA_CRC_IRQ	| \
+				 BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	| \
+				 BM_SSP_CTRL1_RECV_TIMEOUT_IRQ  | \
+				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
+
+#define SSP_PIO_NUM	3
+
+struct mxs_mmc_host {
+	struct mmc_host			*mmc;
+	struct mmc_request		*mrq;
+	struct mmc_command		*cmd;
+	struct mmc_data			*data;
+
+	void __iomem			*base;
+	int				irq;
+	struct resource			*res;
+	struct resource			*dma_res;
+	struct clk			*clk;
+	unsigned int			clk_rate;
+
+	struct dma_chan         	*dmach;
+	struct mxs_dma_data		dma_data;
+	unsigned int			dma_dir;
+	u32				ssp_pio_words[SSP_PIO_NUM];
+
+	unsigned int			version;
+	unsigned char			bus_width;
+	spinlock_t			lock;
+	int				sdio_irq_en;
+};
+
+static int mxs_mmc_get_ro(struct mmc_host *mmc)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_mmc_platform_data *pdata =
+		mmc_dev(host->mmc)->platform_data;
+
+	if (!pdata)
+		return -EFAULT;
+
+	if (!gpio_is_valid(pdata->wp_gpio))
+		return -EINVAL;
+
+	return gpio_get_value(pdata->wp_gpio);
+}
+
+static int mxs_mmc_get_cd(struct mmc_host *mmc)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	return !(readl(host->base + HW_SSP_STATUS) &
+		 BM_SSP_STATUS_CARD_DETECT);
+}
+
+static void mxs_mmc_reset(struct mxs_mmc_host *host)
+{
+	u32 ctrl0, ctrl1;
+
+	mxs_reset_block(host->base);
+
+	ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
+	ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
+		BF_SSP(0x7, CTRL1_WORD_LENGTH) |
+		BM_SSP_CTRL1_DMA_ENABLE |
+		BM_SSP_CTRL1_POLARITY |
+		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
+
+	writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
+	       BF_SSP(2, TIMING_CLOCK_DIVIDE) |
+	       BF_SSP(0, TIMING_CLOCK_RATE),
+	       host->base + HW_SSP_TIMING);
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
+	}
+
+	writel(ctrl0, host->base + HW_SSP_CTRL0);
+	writel(ctrl1, host->base + HW_SSP_CTRL1);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+			      struct mmc_command *cmd);
+
+static void mxs_mmc_request_done(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = host->data;
+	struct mmc_request *mrq = host->mrq;
+
+	if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
+		if (mmc_resp_type(cmd) & MMC_RSP_136) {
+			cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0);
+			cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1);
+			cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2);
+			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3);
+		} else {
+			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0);
+		}
+	}
+
+	if (data) {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+			     data->sg_len, host->dma_dir);
+		/*
+		 * If there was an error on any block, we mark all
+		 * data blocks as being in error.
+		 */
+		if (!data->error)
+			data->bytes_xfered = data->blocks * data->blksz;
+		else
+			data->bytes_xfered = 0;
+
+		host->data = NULL;
+		if (mrq->stop) {
+			mxs_mmc_start_cmd(host, mrq->stop);
+			return;
+		}
+	}
+
+	host->mrq = NULL;
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void mxs_mmc_dma_irq_callback(void *param)
+{
+	struct mxs_mmc_host *host = param;
+
+	mxs_mmc_request_done(host);
+}
+
+static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
+{
+	struct mxs_mmc_host *host = dev_id;
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = host->data;
+	u32 stat;
+
+	spin_lock(&host->lock);
+
+	stat = readl(host->base + HW_SSP_CTRL1);
+	writel(stat & MXS_MMC_IRQ_BITS,
+	       host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+
+	if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
+		mmc_signal_sdio_irq(host->mmc);
+
+	spin_unlock(&host->lock);
+
+	if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
+		cmd->error = -ETIMEDOUT;
+	else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
+		cmd->error = -EIO;
+
+	if (data) {
+		if (stat & (BM_SSP_CTRL1_DATA_TIMEOUT_IRQ |
+			    BM_SSP_CTRL1_RECV_TIMEOUT_IRQ))
+			data->error = -ETIMEDOUT;
+		else if (stat & BM_SSP_CTRL1_DATA_CRC_IRQ)
+			data->error = -EILSEQ;
+		else if (stat & (BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ |
+				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ))
+			data->error = -EIO;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
+	struct mxs_mmc_host *host, unsigned int append)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct mmc_data *data = host->data;
+	struct scatterlist * sgl;
+	unsigned int sg_len;
+
+	if (data) {
+		/* data */
+		dma_map_sg(mmc_dev(host->mmc), data->sg,
+			   data->sg_len, host->dma_dir);
+		sgl = data->sg;
+		sg_len = data->sg_len;
+	} else {
+		/* pio */
+		sgl = (struct scatterlist *) host->ssp_pio_words;
+		sg_len = SSP_PIO_NUM;
+	}
+
+	desc = host->dmach->device->device_prep_slave_sg(host->dmach,
+				sgl, sg_len, host->dma_dir, append);
+	if (desc) {
+		desc->callback = mxs_mmc_dma_irq_callback;
+		desc->callback_param = host;
+	} else {
+		if (data)
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+				     data->sg_len, host->dma_dir);
+	}
+
+	return desc;
+}
+
+static void mxs_mmc_bc(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct dma_async_tx_descriptor *desc;
+	u32 ctrl0, cmd0, cmd1;
+
+	ctrl0 = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC;
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC;
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_ac(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct dma_async_tx_descriptor *desc;
+	u32 ignore_crc, get_resp, long_resp;
+	u32 ctrl0, cmd0, cmd1;
+
+	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+			0 : BM_SSP_CTRL0_IGNORE_CRC;
+	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+			BM_SSP_CTRL0_GET_RESP : 0;
+	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+			BM_SSP_CTRL0_LONG_RESP : 0;
+
+	ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp;
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static unsigned short mxs_ns_to_ssp_ticks(unsigned clock_rate, unsigned ns)
+{
+	const unsigned int ssp_timeout_mul = 4096;
+	/*
+	 * Calculate ticks in ms since ns are large numbers
+	 * and might overflow
+	 */
+	const unsigned int clock_per_ms = clock_rate / 1000;
+	const unsigned int ms = ns / 1000;
+	const unsigned int ticks = ms * clock_per_ms;
+	const unsigned int ssp_ticks = ticks / ssp_timeout_mul;
+
+	WARN_ON(ssp_ticks == 0);
+	return ssp_ticks;
+}
+
+static void mxs_mmc_adtc(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = cmd->data;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl = data->sg, *sg;
+	unsigned int sg_len = data->sg_len;
+	int i;
+
+	unsigned short dma_data_dir, timeout;
+	unsigned int data_size = 0, log2_blksz;
+	unsigned int blocks = data->blocks;
+
+	u32 ignore_crc, get_resp, long_resp, read;
+	u32 ctrl0, cmd0, cmd1, val;
+
+	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+			0 : BM_SSP_CTRL0_IGNORE_CRC;
+	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+			BM_SSP_CTRL0_GET_RESP : 0;
+	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+			BM_SSP_CTRL0_LONG_RESP : 0;
+
+	if (data->flags & MMC_DATA_WRITE) {
+		dma_data_dir = DMA_TO_DEVICE;
+		read = 0;
+	} else {
+		dma_data_dir = DMA_FROM_DEVICE;
+		read = BM_SSP_CTRL0_READ;
+	}
+
+	ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) |
+		ignore_crc | get_resp | long_resp |
+		BM_SSP_CTRL0_DATA_XFER | read |
+		BM_SSP_CTRL0_WAIT_FOR_IRQ |
+		BM_SSP_CTRL0_ENABLE;
+
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+
+	/* get logarithm to base 2 of block size for setting register */
+	log2_blksz = ilog2(data->blksz);
+
+	/*
+	 * take special care of the case that data size from data->sg
+	 * is not equal to blocks x blksz
+	 */
+	for_each_sg(sgl, sg, sg_len, i)
+		data_size += sg->length;
+
+	if (data_size != data->blocks * data->blksz)
+		blocks = 1;
+
+	/* xfer count, block size and count need to be set differently */
+	if (ssp_is_old()) {
+		ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
+		cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
+			BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
+	} else {
+		writel(data_size, host->base + HW_SSP_XFER_SIZE);
+		writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
+		       BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
+		       host->base + HW_SSP_BLOCK_SIZE);
+	}
+
+	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
+	    (cmd->opcode == SD_IO_RW_EXTENDED))
+		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	/* set the timeout count */
+	timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
+	val = readl(host->base + HW_SSP_TIMING);
+	val &= ~(BM_SSP_TIMING_TIMEOUT);
+	val |= BF_SSP(timeout, TIMING_TIMEOUT);
+	writel(val, host->base + HW_SSP_TIMING);
+
+	/* pio */
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	/* append data sg */
+	WARN_ON(host->data != NULL);
+	host->data = data;
+	host->dma_dir = dma_data_dir;
+	desc = mxs_mmc_prep_dma(host, 1);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+			      struct mmc_command *cmd)
+{
+	host->cmd = cmd;
+
+	switch (mmc_cmd_type(cmd)) {
+	case MMC_CMD_BC:
+		mxs_mmc_bc(host);
+		break;
+	case MMC_CMD_BCR:
+		mxs_mmc_ac(host);
+		break;
+	case MMC_CMD_AC:
+		mxs_mmc_ac(host);
+		break;
+	case MMC_CMD_ADTC:
+		mxs_mmc_adtc(host);
+		break;
+	default:
+		dev_warn(mmc_dev(host->mmc),
+			 "%s: unknown MMC command\n", __func__);
+		break;
+	}
+}
+
+static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != NULL);
+	host->mrq = mrq;
+	mxs_mmc_start_cmd(host, mrq->cmd);
+}
+
+static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
+{
+	unsigned int ssp_rate, bit_rate;
+	u32 div1, div2;
+	u32 val;
+
+	ssp_rate = clk_get_rate(host->clk);
+
+	for (div1 = 2; div1 < 254; div1 += 2) {
+		div2 = ssp_rate / rate / div1;
+		if (div2 < 0x100)
+			break;
+	}
+
+	if (div1 >= 254) {
+		dev_err(mmc_dev(host->mmc),
+			"%s: cannot set clock to %d\n", __func__, rate);
+		return;
+	}
+
+	if (div2 == 0)
+		bit_rate = ssp_rate / div1;
+	else
+		bit_rate = ssp_rate / div1 / div2;
+
+	val = readl(host->base + HW_SSP_TIMING);
+	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+	val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE);
+	val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE);
+	writel(val, host->base + HW_SSP_TIMING);
+
+	host->clk_rate = bit_rate;
+
+	dev_dbg(mmc_dev(host->mmc),
+		"%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n",
+		__func__, div1, div2, ssp_rate, bit_rate, rate);
+}
+
+static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	if (ios->bus_width == MMC_BUS_WIDTH_8)
+		host->bus_width = 2;
+	else if (ios->bus_width == MMC_BUS_WIDTH_4)
+		host->bus_width = 1;
+	else
+		host->bus_width = 0;
+
+	if (ios->clock)
+		mxs_mmc_set_clk_rate(host, ios->clock);
+}
+
+static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->sdio_irq_en = enable;
+
+	if (enable) {
+		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+		       host->base + HW_SSP_CTRL0 + MXS_SET_ADDR);
+		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+		       host->base + HW_SSP_CTRL1 + MXS_SET_ADDR);
+
+		if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ)
+			mmc_signal_sdio_irq(host->mmc);
+
+	} else {
+		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+		       host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR);
+		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+		       host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static const struct mmc_host_ops mxs_mmc_ops = {
+	.request = mxs_mmc_request,
+	.get_ro = mxs_mmc_get_ro,
+	.get_cd = mxs_mmc_get_cd,
+	.set_ios = mxs_mmc_set_ios,
+	.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;
+
+	if (!mxs_dma_is_apbh(chan))
+		return false;
+
+	if (chan->chan_id != host->dma_res->start)
+		return false;
+
+	chan->private = &host->dma_data;
+
+	return true;
+}
+
+static int mxs_mmc_probe(struct platform_device *pdev)
+{
+	struct mxs_mmc_host *host;
+	struct mmc_host *mmc;
+	struct resource *iores, *dmares, *r;
+	struct mxs_mmc_platform_data *pdata;
+	int ret = 0, irq_err, irq_dma;
+	dma_cap_mask_t mask;
+
+	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 || !dmares || irq_err < 0 || irq_dma < 0)
+		return -EINVAL;
+
+	r = request_mem_region(iores->start, resource_size(iores), pdev->name);
+	if (!r)
+		return -EBUSY;
+
+	mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out_release_mem;
+	}
+
+	host = mmc_priv(mmc);
+	host->base = ioremap(r->start, resource_size(r));
+	if (!host->base) {
+		ret = -ENOMEM;
+		goto out_mmc_free;
+	}
+
+	/* only major verion does matter */
+	host->version = readl(host->base + HW_SSP_VERSION) >>
+			BP_SSP_VERSION_MAJOR;
+
+	host->mmc = mmc;
+	host->res = r;
+	host->dma_res = dmares;
+	host->irq = irq_err;
+	host->sdio_irq_en = 0;
+
+	host->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto out_iounmap;
+	}
+	clk_enable(host->clk);
+
+	mxs_mmc_reset(host);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	host->dma_data.chan_irq = irq_dma;
+	host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+	if (!host->dmach) {
+		dev_err(mmc_dev(host->mmc),
+			"%s: failed to request dma\n", __func__);
+		goto out_clk_put;
+	}
+
+	/* set mmc core parameters */
+	mmc->ops = &mxs_mmc_ops;
+	mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
+		    MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
+
+	pdata =	mmc_dev(host->mmc)->platform_data;
+	if (pdata) {
+		if (pdata->flags & SLOTF_8_BIT_CAPABLE)
+			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+		if (pdata->flags & SLOTF_4_BIT_CAPABLE)
+			mmc->caps |= MMC_CAP_4_BIT_DATA;
+	}
+
+	mmc->f_min = 400000;
+	mmc->f_max = 288000000;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->max_segs = 52;
+	mmc->max_blk_size = 1 << 0xf;
+	mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff;
+	mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff;
+	mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
+
+	platform_set_drvdata(pdev, mmc);
+
+	ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host);
+	if (ret)
+		goto out_free_dma;
+
+	spin_lock_init(&host->lock);
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto out_free_irq;
+
+	dev_info(mmc_dev(host->mmc), "initialized\n");
+
+	return 0;
+
+out_free_irq:
+	free_irq(host->irq, host);
+out_free_dma:
+	if (host->dmach)
+		dma_release_channel(host->dmach);
+out_clk_put:
+	clk_disable(host->clk);
+	clk_put(host->clk);
+out_iounmap:
+	iounmap(host->base);
+out_mmc_free:
+	mmc_free_host(mmc);
+out_release_mem:
+	release_mem_region(iores->start, resource_size(iores));
+	return ret;
+}
+
+static int mxs_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct resource *res = host->res;
+
+	mmc_remove_host(mmc);
+
+	free_irq(host->irq, host);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (host->dmach)
+		dma_release_channel(host->dmach);
+
+	clk_disable(host->clk);
+	clk_put(host->clk);
+
+	iounmap(host->base);
+
+	mmc_free_host(mmc);
+
+	release_mem_region(res->start, resource_size(res));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxs_mmc_suspend(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	int ret = 0;
+
+	ret = mmc_suspend_host(mmc);
+
+	clk_disable(host->clk);
+
+	return ret;
+}
+
+static int mxs_mmc_resume(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	int ret = 0;
+
+	clk_enable(host->clk);
+
+	ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+
+static const struct dev_pm_ops mxs_mmc_pm_ops = {
+	.suspend	= mxs_mmc_suspend,
+	.resume		= mxs_mmc_resume,
+};
+#endif
+
+static struct platform_driver mxs_mmc_driver = {
+	.probe		= mxs_mmc_probe,
+	.remove		= mxs_mmc_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &mxs_mmc_pm_ops,
+#endif
+	},
+};
+
+static int __init mxs_mmc_init(void)
+{
+	return platform_driver_register(&mxs_mmc_driver);
+}
+
+static void __exit mxs_mmc_exit(void)
+{
+	platform_driver_unregister(&mxs_mmc_driver);
+}
+
+module_init(mxs_mmc_init);
+module_exit(mxs_mmc_exit);
+
+MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index 1247e5d..5530def 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -34,6 +34,7 @@ enum {
 struct of_mmc_spi {
 	int gpios[NUM_GPIOS];
 	bool alow_gpios[NUM_GPIOS];
+	int detect_irq;
 	struct mmc_spi_platform_data pdata;
 };
 
@@ -61,6 +62,22 @@ static int of_mmc_spi_get_ro(struct device *dev)
 	return of_mmc_spi_read_gpio(dev, WP_GPIO);
 }
 
+static int of_mmc_spi_init(struct device *dev,
+			   irqreturn_t (*irqhandler)(int, void *), void *mmc)
+{
+	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+
+	return request_threaded_irq(oms->detect_irq, NULL, irqhandler, 0,
+				    dev_name(dev), mmc);
+}
+
+static void of_mmc_spi_exit(struct device *dev, void *mmc)
+{
+	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+
+	free_irq(oms->detect_irq, mmc);
+}
+
 struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
 {
 	struct device *dev = &spi->dev;
@@ -121,8 +138,13 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
 	if (gpio_is_valid(oms->gpios[WP_GPIO]))
 		oms->pdata.get_ro = of_mmc_spi_get_ro;
 
-	/* We don't support interrupts yet, let's poll. */
-	oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
+	oms->detect_irq = irq_of_parse_and_map(np, 0);
+	if (oms->detect_irq != NO_IRQ) {
+		oms->pdata.init = of_mmc_spi_init;
+		oms->pdata.exit = of_mmc_spi_exit;
+	} else {
+		oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
+	}
 
 	dev->platform_data = &oms->pdata;
 	return dev->platform_data;
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 379d2ff..2e032f0 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1417,7 +1417,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
 	if (res == NULL || irq < 0)
 		return -ENXIO;
 
-	res = request_mem_region(res->start, res->end - res->start + 1,
+	res = request_mem_region(res->start, resource_size(res),
 				 pdev->name);
 	if (res == NULL)
 		return -EBUSY;
@@ -1457,7 +1457,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
 
 	host->irq = irq;
 	host->phys_base = host->mem_res->start;
-	host->virt_base = ioremap(res->start, res->end - res->start + 1);
+	host->virt_base = ioremap(res->start, resource_size(res));
 	if (!host->virt_base)
 		goto err_ioremap;
 
@@ -1514,7 +1514,7 @@ err_free_mmc_host:
 err_ioremap:
 	kfree(host);
 err_free_mem_region:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 078fdf1..259ece0 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -118,7 +118,7 @@
 
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
-#define DRIVER_NAME		"mmci-omap-hs"
+#define DRIVER_NAME		"omap_hsmmc"
 
 /* Timeouts for entering power saving states on inactivity, msec */
 #define OMAP_MMC_DISABLED_TIMEOUT	100
@@ -260,7 +260,7 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on,
 	return ret;
 }
 
-static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
+static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on,
 				   int vdd)
 {
 	struct omap_hsmmc_host *host =
@@ -316,6 +316,12 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
 	return ret;
 }
 
+static int omap_hsmmc_4_set_power(struct device *dev, int slot, int power_on,
+					int vdd)
+{
+	return 0;
+}
+
 static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
 				  int vdd, int cardsleep)
 {
@@ -326,7 +332,7 @@ static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
 	return regulator_set_mode(host->vcc, mode);
 }
 
-static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
+static int omap_hsmmc_235_set_sleep(struct device *dev, int slot, int sleep,
 				   int vdd, int cardsleep)
 {
 	struct omap_hsmmc_host *host =
@@ -365,6 +371,12 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
 		return regulator_enable(host->vcc_aux);
 }
 
+static int omap_hsmmc_4_set_sleep(struct device *dev, int slot, int sleep,
+					int vdd, int cardsleep)
+{
+	return 0;
+}
+
 static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 {
 	struct regulator *reg;
@@ -379,10 +391,14 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 		break;
 	case OMAP_MMC2_DEVID:
 	case OMAP_MMC3_DEVID:
+	case OMAP_MMC5_DEVID:
 		/* Off-chip level shifting, or none */
-		mmc_slot(host).set_power = omap_hsmmc_23_set_power;
-		mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep;
+		mmc_slot(host).set_power = omap_hsmmc_235_set_power;
+		mmc_slot(host).set_sleep = omap_hsmmc_235_set_sleep;
 		break;
+	case OMAP_MMC4_DEVID:
+		mmc_slot(host).set_power = omap_hsmmc_4_set_power;
+		mmc_slot(host).set_sleep = omap_hsmmc_4_set_sleep;
 	default:
 		pr_err("MMC%d configuration not supported!\n", host->id);
 		return -EINVAL;
@@ -1555,7 +1571,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 		break;
 	}
 
-	if (host->id == OMAP_MMC1_DEVID) {
+	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		/* Only MMC1 can interface at 3V without some flavor
 		 * of external transceiver; but they all handle 1.8V.
 		 */
@@ -1647,7 +1663,7 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
 	u32 hctl, capa, value;
 
 	/* Only MMC1 supports 3.0V */
-	if (host->id == OMAP_MMC1_DEVID) {
+	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		hctl = SDVS30;
 		capa = VS30 | VS18;
 	} else {
@@ -2031,8 +2047,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 
 	res->start += pdata->reg_offset;
 	res->end += pdata->reg_offset;
-	res = request_mem_region(res->start, res->end - res->start + 1,
-							pdev->name);
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (res == NULL)
 		return -EBUSY;
 
@@ -2101,14 +2116,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
 	/* we start off in DISABLED state */
 	host->dpm_state = DISABLED;
 
-	if (mmc_host_enable(host->mmc) != 0) {
+	if (clk_enable(host->iclk) != 0) {
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
 	}
 
-	if (clk_enable(host->iclk) != 0) {
-		mmc_host_disable(host->mmc);
+	if (mmc_host_enable(host->mmc) != 0) {
+		clk_disable(host->iclk);
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
@@ -2271,7 +2286,7 @@ err1:
 err_alloc:
 	omap_hsmmc_gpio_free(pdata);
 err:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
@@ -2308,7 +2323,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res)
-		release_mem_region(res->start, res->end - res->start + 1);
+		release_mem_region(res->start, resource_size(res));
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 9b82910..3b52485 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -15,9 +15,11 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdhci-pltfm.h>
 #include <mach/hardware.h>
+#include <mach/esdhc.h>
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
@@ -30,6 +32,39 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i
 	writel(((readl(base) & ~(mask << shift)) | (val << shift)), base);
 }
 
+static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+{
+	/* fake CARD_PRESENT flag on mx25/35 */
+	u32 val = readl(host->ioaddr + reg);
+
+	if (unlikely(reg == SDHCI_PRESENT_STATE)) {
+		struct esdhc_platform_data *boarddata =
+				host->mmc->parent->platform_data;
+
+		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
+				&& gpio_get_value(boarddata->cd_gpio))
+			/* no card, if a valid gpio says so... */
+			val &= SDHCI_CARD_PRESENT;
+		else
+			/* ... in all other cases assume card is present */
+			val |= SDHCI_CARD_PRESENT;
+	}
+
+	return val;
+}
+
+static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
+{
+	if (unlikely(reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE))
+		/*
+		 * these interrupts won't work with a custom card_detect gpio
+		 * (only applied to mx25/35)
+		 */
+		val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+
+	writel(val, host->ioaddr + reg);
+}
+
 static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 {
 	if (unlikely(reg == SDHCI_HOST_VERSION))
@@ -100,10 +135,39 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
 	return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+		return gpio_get_value(boarddata->wp_gpio);
+	else
+		return -ENOSYS;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+	.read_w = esdhc_readw_le,
+	.write_w = esdhc_writew_le,
+	.write_b = esdhc_writeb_le,
+	.set_clock = esdhc_set_clock,
+	.get_max_clock = esdhc_pltfm_get_max_clock,
+	.get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
+static irqreturn_t cd_irq(int irq, void *data)
+{
+	struct sdhci_host *sdhost = (struct sdhci_host *)data;
+
+	tasklet_schedule(&sdhost->card_tasklet);
+	return IRQ_HANDLED;
+};
+
 static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
 	struct clk *clk;
+	int err;
 
 	clk = clk_get(mmc_dev(host->mmc), NULL);
 	if (IS_ERR(clk)) {
@@ -116,32 +180,78 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
 	if (cpu_is_mx35() || cpu_is_mx51())
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	/* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
-	if (cpu_is_mx25() || cpu_is_mx35())
+	if (cpu_is_mx25() || cpu_is_mx35()) {
+		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+		/* write_protect can't be routed to controller, use gpio */
+		sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+	}
+
+	if (boarddata) {
+		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+		if (err) {
+			dev_warn(mmc_dev(host->mmc),
+				"no write-protect pin available!\n");
+			boarddata->wp_gpio = err;
+		}
+
+		err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+		if (err) {
+			dev_warn(mmc_dev(host->mmc),
+				"no card-detect pin available!\n");
+			goto no_card_detect_pin;
+		}
+
+		/* i.MX5x has issues to be researched */
+		if (!cpu_is_mx25() && !cpu_is_mx35())
+			goto not_supported;
+
+		err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				 mmc_hostname(host->mmc), host);
+		if (err) {
+			dev_warn(mmc_dev(host->mmc), "request irq error\n");
+			goto no_card_detect_irq;
+		}
+
+		sdhci_esdhc_ops.write_l = esdhc_writel_le;
+		sdhci_esdhc_ops.read_l = esdhc_readl_le;
+		/* Now we have a working card_detect again */
+		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+	}
+
+	return 0;
 
+ no_card_detect_irq:
+	gpio_free(boarddata->cd_gpio);
+ no_card_detect_pin:
+	boarddata->cd_gpio = err;
+ not_supported:
 	return 0;
 }
 
 static void esdhc_pltfm_exit(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+		gpio_free(boarddata->wp_gpio);
+
+	if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+		gpio_free(boarddata->cd_gpio);
+
+		if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
+			free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+	}
 
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
 }
 
-static struct sdhci_ops sdhci_esdhc_ops = {
-	.read_w = esdhc_readw_le,
-	.write_w = esdhc_writew_le,
-	.write_b = esdhc_writeb_le,
-	.set_clock = esdhc_set_clock,
-	.get_max_clock = esdhc_pltfm_get_max_clock,
-	.get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
 struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
+	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+			| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
 	/* ADMA has issues. Might be fixable */
 	.ops = &sdhci_esdhc_ops,
 	.init = esdhc_pltfm_init,
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index afaf1bc..c55aae8 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -19,7 +19,6 @@
  */
 
 #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
-				SDHCI_QUIRK_BROKEN_CARD_DETECTION | \
 				SDHCI_QUIRK_NO_BUSY_IRQ | \
 				SDHCI_QUIRK_NONSTANDARD_CLOCK | \
 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c
index dd84124..f9b611f 100644
--- a/drivers/mmc/host/sdhci-of-core.c
+++ b/drivers/mmc/host/sdhci-of-core.c
@@ -124,17 +124,20 @@ static bool __devinit sdhci_of_wp_inverted(struct device_node *np)
 #endif
 }
 
-static int __devinit sdhci_of_probe(struct platform_device *ofdev,
-				 const struct of_device_id *match)
+static int __devinit sdhci_of_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
-	struct sdhci_of_data *sdhci_of_data = match->data;
+	struct sdhci_of_data *sdhci_of_data;
 	struct sdhci_host *host;
 	struct sdhci_of_host *of_host;
 	const __be32 *clk;
 	int size;
 	int ret;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+	sdhci_of_data = ofdev->dev.of_match->data;
+
 	if (!of_device_is_available(np))
 		return -ENODEV;
 
@@ -217,7 +220,7 @@ static const struct of_device_id sdhci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sdhci_of_match);
 
-static struct of_platform_driver sdhci_of_driver = {
+static struct platform_driver sdhci_of_driver = {
 	.driver = {
 		.name = "sdhci-of",
 		.owner = THIS_MODULE,
@@ -231,13 +234,13 @@ static struct of_platform_driver sdhci_of_driver = {
 
 static int __init sdhci_of_init(void)
 {
-	return of_register_platform_driver(&sdhci_of_driver);
+	return platform_driver_register(&sdhci_of_driver);
 }
 module_init(sdhci_of_init);
 
 static void __exit sdhci_of_exit(void)
 {
-	of_unregister_platform_driver(&sdhci_of_driver);
+	platform_driver_unregister(&sdhci_of_driver);
 }
 module_exit(sdhci_of_exit);
 
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index fcd0e1f..08161f6 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -73,7 +73,8 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)
 }
 
 struct sdhci_of_data sdhci_esdhc = {
-	.quirks = ESDHC_DEFAULT_QUIRKS,
+	/* card detection could be handled via GPIO */
+	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION,
 	.ops = {
 		.read_l = sdhci_be32bs_readl,
 		.read_w = esdhc_readw,
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 0dc905b..2f8d468 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -547,6 +547,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
 	},
 
 	{
+		.vendor         = PCI_VENDOR_ID_RICOH,
+		.device         = 0xe823,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.driver_data    = (kernel_ulong_t)&sdhci_ricoh_mmc,
+	},
+
+	{
 		.vendor		= PCI_VENDOR_ID_ENE,
 		.device		= PCI_DEVICE_ID_ENE_CB712_SD,
 		.subvendor	= PCI_ANY_ID,
@@ -900,9 +908,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
 {
 	struct sdhci_pci_slot *slot;
 	struct sdhci_host *host;
-
-	resource_size_t addr;
-
 	int ret;
 
 	if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
@@ -949,7 +954,6 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
 		goto free;
 	}
 
-	addr = pci_resource_start(pdev, bar);
 	host->ioaddr = pci_ioremap_bar(pdev, bar);
 	if (!host->ioaddr) {
 		dev_err(&pdev->dev, "failed to remap registers\n");
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index 5309ab9..69e3ee3 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -499,6 +499,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
 	 * SDHCI block, or a missing configuration that needs to be set. */
 	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
 
+	/* This host supports the Auto CMD12 */
+	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+
 	if (pdata->cd_type == S3C_SDHCI_CD_NONE ||
 	    pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
 		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 4823ee9..f7e1f96 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -169,7 +169,7 @@ static int tegra_sdhci_pltfm_init(struct sdhci_host *host,
 		if (rc) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to allocate wp gpio\n");
-			goto out_cd;
+			goto out_irq;
 		}
 		tegra_gpio_enable(plat->wp_gpio);
 		gpio_direction_input(plat->wp_gpio);
@@ -195,6 +195,9 @@ out_wp:
 		gpio_free(plat->wp_gpio);
 	}
 
+out_irq:
+	if (gpio_is_valid(plat->cd_gpio))
+		free_irq(gpio_to_irq(plat->cd_gpio), host);
 out_cd:
 	if (gpio_is_valid(plat->cd_gpio)) {
 		tegra_gpio_disable(plat->cd_gpio);
@@ -225,6 +228,7 @@ static void tegra_sdhci_pltfm_exit(struct sdhci_host *host)
 	}
 
 	if (gpio_is_valid(plat->cd_gpio)) {
+		free_irq(gpio_to_irq(plat->cd_gpio), host);
 		tegra_gpio_disable(plat->cd_gpio);
 		gpio_free(plat->cd_gpio);
 	}
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 12884c2..af97015 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -169,7 +169,7 @@ struct sh_mmcif_host {
 	struct dma_chan		*chan_rx;
 	struct dma_chan		*chan_tx;
 	struct completion	dma_complete;
-	unsigned int            dma_sglen;
+	bool			dma_active;
 };
 
 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
@@ -194,10 +194,12 @@ static void mmcif_dma_complete(void *arg)
 		return;
 
 	if (host->data->flags & MMC_DATA_READ)
-		dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+		dma_unmap_sg(host->chan_rx->device->dev,
+			     host->data->sg, host->data->sg_len,
 			     DMA_FROM_DEVICE);
 	else
-		dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+		dma_unmap_sg(host->chan_tx->device->dev,
+			     host->data->sg, host->data->sg_len,
 			     DMA_TO_DEVICE);
 
 	complete(&host->dma_complete);
@@ -211,9 +213,10 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
 	dma_cookie_t cookie = -EINVAL;
 	int ret;
 
-	ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_FROM_DEVICE);
+	ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+			 DMA_FROM_DEVICE);
 	if (ret > 0) {
-		host->dma_sglen = ret;
+		host->dma_active = true;
 		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
 			DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	}
@@ -221,14 +224,9 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
 	if (desc) {
 		desc->callback = mmcif_dma_complete;
 		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		} else {
-			sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
-			chan->device->device_issue_pending(chan);
-		}
+		cookie = dmaengine_submit(desc);
+		sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
+		dma_async_issue_pending(chan);
 	}
 	dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
 		__func__, host->data->sg_len, ret, cookie);
@@ -238,7 +236,7 @@ static void sh_mmcif_start_dma_rx(struct sh_mmcif_host *host)
 		if (ret >= 0)
 			ret = -EIO;
 		host->chan_rx = NULL;
-		host->dma_sglen = 0;
+		host->dma_active = false;
 		dma_release_channel(chan);
 		/* Free the Tx channel too */
 		chan = host->chan_tx;
@@ -263,9 +261,10 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
 	dma_cookie_t cookie = -EINVAL;
 	int ret;
 
-	ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_TO_DEVICE);
+	ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+			 DMA_TO_DEVICE);
 	if (ret > 0) {
-		host->dma_sglen = ret;
+		host->dma_active = true;
 		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
 			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	}
@@ -273,14 +272,9 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
 	if (desc) {
 		desc->callback = mmcif_dma_complete;
 		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		} else {
-			sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
-			chan->device->device_issue_pending(chan);
-		}
+		cookie = dmaengine_submit(desc);
+		sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
+		dma_async_issue_pending(chan);
 	}
 	dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
 		__func__, host->data->sg_len, ret, cookie);
@@ -290,7 +284,7 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
 		if (ret >= 0)
 			ret = -EIO;
 		host->chan_tx = NULL;
-		host->dma_sglen = 0;
+		host->dma_active = false;
 		dma_release_channel(chan);
 		/* Free the Rx channel too */
 		chan = host->chan_rx;
@@ -317,7 +311,7 @@ static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
 static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
 				 struct sh_mmcif_plat_data *pdata)
 {
-	host->dma_sglen = 0;
+	host->dma_active = false;
 
 	/* We can only either use DMA for both Tx and Rx or not use it at all */
 	if (pdata->dma) {
@@ -364,7 +358,7 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
 		dma_release_channel(chan);
 	}
 
-	host->dma_sglen = 0;
+	host->dma_active = false;
 }
 
 static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
@@ -753,7 +747,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
 	}
 	sh_mmcif_get_response(host, cmd);
 	if (host->data) {
-		if (!host->dma_sglen) {
+		if (!host->dma_active) {
 			ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
 		} else {
 			long time =
@@ -765,7 +759,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
 				ret = time;
 			sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
 					BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
-			host->dma_sglen = 0;
+			host->dma_active = false;
 		}
 		if (ret < 0)
 			mrq->data->bytes_xfered = 0;
@@ -850,15 +844,15 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 	struct sh_mmcif_host *host = mmc_priv(mmc);
 	struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
 
-	if (ios->power_mode == MMC_POWER_OFF) {
+	if (ios->power_mode == MMC_POWER_UP) {
+		if (p->set_pwr)
+			p->set_pwr(host->pd, ios->power_mode);
+	} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
 		/* clock stop */
 		sh_mmcif_clock_control(host, 0);
-		if (p->down_pwr)
+		if (ios->power_mode == MMC_POWER_OFF && p->down_pwr)
 			p->down_pwr(host->pd);
 		return;
-	} else if (ios->power_mode == MMC_POWER_UP) {
-		if (p->set_pwr)
-			p->set_pwr(host->pd, ios->power_mode);
 	}
 
 	if (ios->clock)
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index e3c6ef2..ac52eb6 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -152,7 +152,6 @@ struct tmio_mmc_host {
 	struct tasklet_struct	dma_complete;
 	struct tasklet_struct	dma_issue;
 #ifdef CONFIG_TMIO_MMC_DMA
-	unsigned int            dma_sglen;
 	u8			bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN)));
 	struct scatterlist	bounce_sg;
 #endif
@@ -220,44 +219,48 @@ static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
 	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
 }
 
-static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags)
+static void tmio_mmc_kunmap_atomic(struct scatterlist *sg, unsigned long *flags, void *virt)
 {
-	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+	kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ);
 	local_irq_restore(*flags);
 }
 
 #ifdef CONFIG_MMC_DEBUG
 
-#define STATUS_TO_TEXT(a) \
+#define STATUS_TO_TEXT(a, status, i) \
 	do { \
-		if (status & TMIO_STAT_##a) \
+		if (status & TMIO_STAT_##a) { \
+			if (i++) \
+				printk(" | "); \
 			printk(#a); \
+		} \
 	} while (0)
 
 void pr_debug_status(u32 status)
 {
+	int i = 0;
 	printk(KERN_DEBUG "status: %08x = ", status);
-	STATUS_TO_TEXT(CARD_REMOVE);
-	STATUS_TO_TEXT(CARD_INSERT);
-	STATUS_TO_TEXT(SIGSTATE);
-	STATUS_TO_TEXT(WRPROTECT);
-	STATUS_TO_TEXT(CARD_REMOVE_A);
-	STATUS_TO_TEXT(CARD_INSERT_A);
-	STATUS_TO_TEXT(SIGSTATE_A);
-	STATUS_TO_TEXT(CMD_IDX_ERR);
-	STATUS_TO_TEXT(STOPBIT_ERR);
-	STATUS_TO_TEXT(ILL_FUNC);
-	STATUS_TO_TEXT(CMD_BUSY);
-	STATUS_TO_TEXT(CMDRESPEND);
-	STATUS_TO_TEXT(DATAEND);
-	STATUS_TO_TEXT(CRCFAIL);
-	STATUS_TO_TEXT(DATATIMEOUT);
-	STATUS_TO_TEXT(CMDTIMEOUT);
-	STATUS_TO_TEXT(RXOVERFLOW);
-	STATUS_TO_TEXT(TXUNDERRUN);
-	STATUS_TO_TEXT(RXRDY);
-	STATUS_TO_TEXT(TXRQ);
-	STATUS_TO_TEXT(ILL_ACCESS);
+	STATUS_TO_TEXT(CARD_REMOVE, status, i);
+	STATUS_TO_TEXT(CARD_INSERT, status, i);
+	STATUS_TO_TEXT(SIGSTATE, status, i);
+	STATUS_TO_TEXT(WRPROTECT, status, i);
+	STATUS_TO_TEXT(CARD_REMOVE_A, status, i);
+	STATUS_TO_TEXT(CARD_INSERT_A, status, i);
+	STATUS_TO_TEXT(SIGSTATE_A, status, i);
+	STATUS_TO_TEXT(CMD_IDX_ERR, status, i);
+	STATUS_TO_TEXT(STOPBIT_ERR, status, i);
+	STATUS_TO_TEXT(ILL_FUNC, status, i);
+	STATUS_TO_TEXT(CMD_BUSY, status, i);
+	STATUS_TO_TEXT(CMDRESPEND, status, i);
+	STATUS_TO_TEXT(DATAEND, status, i);
+	STATUS_TO_TEXT(CRCFAIL, status, i);
+	STATUS_TO_TEXT(DATATIMEOUT, status, i);
+	STATUS_TO_TEXT(CMDTIMEOUT, status, i);
+	STATUS_TO_TEXT(RXOVERFLOW, status, i);
+	STATUS_TO_TEXT(TXUNDERRUN, status, i);
+	STATUS_TO_TEXT(RXRDY, status, i);
+	STATUS_TO_TEXT(TXRQ, status, i);
+	STATUS_TO_TEXT(ILL_ACCESS, status, i);
 	printk("\n");
 }
 
@@ -507,7 +510,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
 
 	host->sg_off += count;
 
-	tmio_mmc_kunmap_atomic(sg_virt, &flags);
+	tmio_mmc_kunmap_atomic(host->sg_ptr, &flags, sg_virt);
 
 	if (host->sg_off == host->sg_ptr->length)
 		tmio_mmc_next_sg(host);
@@ -767,7 +770,7 @@ static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
 		unsigned long flags;
 		void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags);
 		memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length);
-		tmio_mmc_kunmap_atomic(sg_vaddr, &flags);
+		tmio_mmc_kunmap_atomic(host->sg_orig, &flags, sg_vaddr);
 	}
 }
 
@@ -825,23 +828,16 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
 		sg = host->sg_ptr;
 	}
 
-	ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE);
-	if (ret > 0) {
-		host->dma_sglen = ret;
+	ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
+	if (ret > 0)
 		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
 			DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	}
 
 	if (desc) {
 		desc->callback = tmio_dma_complete;
 		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		} else {
-			chan->device->device_issue_pending(chan);
-		}
+		cookie = dmaengine_submit(desc);
+		dma_async_issue_pending(chan);
 	}
 	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
 		__func__, host->sg_len, ret, cookie, host->mrq);
@@ -901,26 +897,20 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
 		void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags);
 		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
 		memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length);
-		tmio_mmc_kunmap_atomic(sg_vaddr, &flags);
+		tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr);
 		host->sg_ptr = &host->bounce_sg;
 		sg = host->sg_ptr;
 	}
 
-	ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE);
-	if (ret > 0) {
-		host->dma_sglen = ret;
+	ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
+	if (ret > 0)
 		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
 			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	}
 
 	if (desc) {
 		desc->callback = tmio_dma_complete;
 		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		}
+		cookie = dmaengine_submit(desc);
 	}
 	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
 		__func__, host->sg_len, ret, cookie, host->mrq);
@@ -964,7 +954,7 @@ static void tmio_issue_tasklet_fn(unsigned long priv)
 	struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
 	struct dma_chan *chan = host->chan_tx;
 
-	chan->device->device_issue_pending(chan);
+	dma_async_issue_pending(chan);
 }
 
 static void tmio_tasklet_fn(unsigned long arg)
@@ -978,10 +968,12 @@ static void tmio_tasklet_fn(unsigned long arg)
 		goto out;
 
 	if (host->data->flags & MMC_DATA_READ)
-		dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
+		dma_unmap_sg(host->chan_rx->device->dev,
+			     host->sg_ptr, host->sg_len,
 			     DMA_FROM_DEVICE);
 	else
-		dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
+		dma_unmap_sg(host->chan_tx->device->dev,
+			     host->sg_ptr, host->sg_len,
 			     DMA_TO_DEVICE);
 
 	tmio_mmc_do_data_irq(host);
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index 9ed84dd..8c5b488 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -802,12 +802,9 @@ static const struct mmc_host_ops via_sdc_ops = {
 
 static void via_reset_pcictrl(struct via_crdr_mmc_host *host)
 {
-	void __iomem *addrbase;
 	unsigned long flags;
 	u8 gatt;
 
-	addrbase = host->pcictrl_mmiobase;
-
 	spin_lock_irqsave(&host->lock, flags);
 
 	via_save_pcictrlreg(host);
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 8506578..3db0cb0 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -216,8 +216,7 @@ static void __devinit of_free_probes(const char **probes)
 }
 #endif
 
-static int __devinit of_flash_probe(struct platform_device *dev,
-				    const struct of_device_id *match)
+static int __devinit of_flash_probe(struct platform_device *dev)
 {
 #ifdef CONFIG_MTD_PARTITIONS
 	const char **part_probe_types;
@@ -225,7 +224,7 @@ static int __devinit of_flash_probe(struct platform_device *dev,
 	struct device_node *dp = dev->dev.of_node;
 	struct resource res;
 	struct of_flash *info;
-	const char *probe_type = match->data;
+	const char *probe_type;
 	const __be32 *width;
 	int err;
 	int i;
@@ -235,6 +234,10 @@ static int __devinit of_flash_probe(struct platform_device *dev,
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
 
+	if (!dev->dev.of_match)
+		return -EINVAL;
+	probe_type = dev->dev.of_match->data;
+
 	reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
 
 	/*
@@ -418,7 +421,7 @@ static struct of_device_id of_flash_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_flash_match);
 
-static struct of_platform_driver of_flash_driver = {
+static struct platform_driver of_flash_driver = {
 	.driver = {
 		.name = "of-flash",
 		.owner = THIS_MODULE,
@@ -430,12 +433,12 @@ static struct of_platform_driver of_flash_driver = {
 
 static int __init of_flash_init(void)
 {
-	return of_register_platform_driver(&of_flash_driver);
+	return platform_driver_register(&of_flash_driver);
 }
 
 static void __exit of_flash_exit(void)
 {
-	of_unregister_platform_driver(&of_flash_driver);
+	platform_driver_unregister(&of_flash_driver);
 }
 
 module_init(of_flash_init);
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 3582ba1..3f1cb32 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -108,7 +108,7 @@ int uflash_devinit(struct platform_device *op, struct device_node *dp)
 	return 0;
 }
 
-static int __devinit uflash_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit uflash_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -148,7 +148,7 @@ static const struct of_device_id uflash_match[] = {
 
 MODULE_DEVICE_TABLE(of, uflash_match);
 
-static struct of_platform_driver uflash_driver = {
+static struct platform_driver uflash_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -160,12 +160,12 @@ static struct of_platform_driver uflash_driver = {
 
 static int __init uflash_init(void)
 {
-	return of_register_platform_driver(&uflash_driver);
+	return platform_driver_register(&uflash_driver);
 }
 
 static void __exit uflash_exit(void)
 {
-	of_unregister_platform_driver(&uflash_driver);
+	platform_driver_unregister(&uflash_driver);
 }
 
 module_init(uflash_init);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index c895922..4f6c06f 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -106,23 +106,6 @@ config MTD_NAND_OMAP2
 	help
           Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
 
-config MTD_NAND_OMAP_PREFETCH
-	bool "GPMC prefetch support for NAND Flash device"
-	depends on MTD_NAND_OMAP2
-	default y
-	help
-	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
-	 to improve the performance.
-
-config MTD_NAND_OMAP_PREFETCH_DMA
-	depends on MTD_NAND_OMAP_PREFETCH
-	bool "DMA mode"
-	default n
-	help
-	 The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
-	 or in DMA interrupt mode.
-	 Say y for DMA mode or MPU mode will be used
-
 config MTD_NAND_IDS
 	tristate
 
@@ -476,7 +459,7 @@ config MTD_NAND_MPC5121_NFC
 
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
-	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51
+	depends on IMX_HAVE_PLATFORM_MXC_NAND
 	help
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index efdcca9..073ee02 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -217,8 +217,7 @@ err:
 	return ret;
 }
 
-static int __devinit fun_probe(struct platform_device *ofdev,
-			       const struct of_device_id *ofid)
+static int __devinit fun_probe(struct platform_device *ofdev)
 {
 	struct fsl_upm_nand *fun;
 	struct resource io_res;
@@ -360,7 +359,7 @@ static const struct of_device_id of_fun_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_fun_match);
 
-static struct of_platform_driver of_fun_driver = {
+static struct platform_driver of_fun_driver = {
 	.driver = {
 		.name = "fsl,upm-nand",
 		.owner = THIS_MODULE,
@@ -372,13 +371,13 @@ static struct of_platform_driver of_fun_driver = {
 
 static int __init fun_module_init(void)
 {
-	return of_register_platform_driver(&of_fun_driver);
+	return platform_driver_register(&of_fun_driver);
 }
 module_init(fun_module_init);
 
 static void __exit fun_module_exit(void)
 {
-	of_unregister_platform_driver(&of_fun_driver);
+	platform_driver_unregister(&of_fun_driver);
 }
 module_exit(fun_module_exit);
 
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 469e649..c2f9543 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -650,8 +650,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd)
 		iounmap(prv->csreg);
 }
 
-static int __devinit mpc5121_nfc_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -891,7 +890,7 @@ static struct of_device_id mpc5121_nfc_match[] __devinitdata = {
 	{},
 };
 
-static struct of_platform_driver mpc5121_nfc_driver = {
+static struct platform_driver mpc5121_nfc_driver = {
 	.probe		= mpc5121_nfc_probe,
 	.remove		= __devexit_p(mpc5121_nfc_remove),
 	.driver		= {
@@ -903,14 +902,14 @@ static struct of_platform_driver mpc5121_nfc_driver = {
 
 static int __init mpc5121_nfc_init(void)
 {
-	return of_register_platform_driver(&mpc5121_nfc_driver);
+	return platform_driver_register(&mpc5121_nfc_driver);
 }
 
 module_init(mpc5121_nfc_init);
 
 static void __exit mpc5121_nfc_cleanup(void)
 {
-	of_unregister_platform_driver(&mpc5121_nfc_driver);
+	platform_driver_unregister(&mpc5121_nfc_driver);
 }
 
 module_exit(mpc5121_nfc_cleanup);
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index ef932ba..5ae1d9e 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -722,9 +722,8 @@ static void mxc_do_addr_cycle(struct mtd_info *mtd, int column, int page_addr)
 		/*
 		 * MXC NANDFC can only perform full page+spare or
 		 * spare-only read/write.  When the upper layers
-		 * layers perform a read/write buf operation,
-		 * we will used the saved column address to index into
-		 * the full page.
+		 * perform a read/write buf operation, the saved column
+		  * address is used to index into the full page.
 		 */
 		host->send_addr(host, 0, page_addr == -1);
 		if (mtd->writesize > 512)
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index c9ae0a5..bbe6d45 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -225,8 +225,7 @@ err:
 	return ret;
 }
 
-static int __devinit ndfc_probe(struct platform_device *ofdev,
-				const struct of_device_id *match)
+static int __devinit ndfc_probe(struct platform_device *ofdev)
 {
 	struct ndfc_controller *ndfc = &ndfc_ctrl;
 	const __be32 *reg;
@@ -292,7 +291,7 @@ static const struct of_device_id ndfc_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ndfc_match);
 
-static struct of_platform_driver ndfc_driver = {
+static struct platform_driver ndfc_driver = {
 	.driver = {
 		.name = "ndfc",
 		.owner = THIS_MODULE,
@@ -304,12 +303,12 @@ static struct of_platform_driver ndfc_driver = {
 
 static int __init ndfc_nand_init(void)
 {
-	return of_register_platform_driver(&ndfc_driver);
+	return platform_driver_register(&ndfc_driver);
 }
 
 static void __exit ndfc_nand_exit(void)
 {
-	of_unregister_platform_driver(&ndfc_driver);
+	platform_driver_unregister(&ndfc_driver);
 }
 
 module_init(ndfc_nand_init);
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 28af71c..7b8f1ff 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/mtd/mtd.h>
@@ -24,6 +25,7 @@
 #include <plat/nand.h>
 
 #define	DRIVER_NAME	"omap2-nand"
+#define	OMAP_NAND_TIMEOUT_MS	5000
 
 #define NAND_Ecc_P1e		(1 << 0)
 #define NAND_Ecc_P2e		(1 << 1)
@@ -96,26 +98,19 @@
 static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
-#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
-static int use_prefetch = 1;
-
-/* "modprobe ... use_prefetch=0" etc */
-module_param(use_prefetch, bool, 0);
-MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
-
-#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
-static int use_dma = 1;
+/* oob info generated runtime depending on ecc algorithm and layout selected */
+static struct nand_ecclayout omap_oobinfo;
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks
+ */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr bb_descrip_flashbased = {
+	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+	.offs = 0,
+	.len = 1,
+	.pattern = scan_ff_pattern,
+};
 
-/* "modprobe ... use_dma=0" etc */
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
-#else
-static const int use_dma;
-#endif
-#else
-const int use_prefetch;
-static const int use_dma;
-#endif
 
 struct omap_nand_info {
 	struct nand_hw_control		controller;
@@ -129,6 +124,13 @@ struct omap_nand_info {
 	unsigned long			phys_base;
 	struct completion		comp;
 	int				dma_ch;
+	int				gpmc_irq;
+	enum {
+		OMAP_NAND_IO_READ = 0,	/* read */
+		OMAP_NAND_IO_WRITE,	/* write */
+	} iomode;
+	u_char				*buf;
+	int					buf_len;
 };
 
 /**
@@ -256,7 +258,8 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
 	}
 
 	/* configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -288,9 +291,10 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 {
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
-	uint32_t pref_count = 0, w_count = 0;
+	uint32_t w_count = 0;
 	int i = 0, ret = 0;
 	u16 *p;
+	unsigned long tim, limit;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
@@ -300,7 +304,8 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 	}
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -316,15 +321,17 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
 				iowrite16(*p++, info->nand.IO_ADDR_W);
 		}
 		/* wait for data to flushed-out before reset the prefetch */
-		do {
-			pref_count = gpmc_read_status(GPMC_PREFETCH_COUNT);
-		} while (pref_count);
+		tim = 0;
+		limit = (loops_per_jiffy *
+					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
+		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+			cpu_relax();
+
 		/* disable and stop the PFPW engine */
 		gpmc_prefetch_reset(info->gpmc_cs);
 	}
 }
 
-#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
 /*
  * omap_nand_dma_cb: callback on the completion of dma transfer
  * @lch: logical channel
@@ -348,14 +355,15 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 {
 	struct omap_nand_info *info = container_of(mtd,
 					struct omap_nand_info, mtd);
-	uint32_t prefetch_status = 0;
 	enum dma_data_direction dir = is_write ? DMA_TO_DEVICE :
 							DMA_FROM_DEVICE;
 	dma_addr_t dma_addr;
 	int ret;
+	unsigned long tim, limit;
 
-	/* The fifo depth is 64 bytes. We have a sync at each frame and frame
-	 * length is 64 bytes.
+	/* The fifo depth is 64 bytes max.
+	 * But configure the FIFO-threahold to 32 to get a sync at each frame
+	 * and frame length is 32 bytes.
 	 */
 	int buf_len = len >> 6;
 
@@ -396,9 +404,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
 	}
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs, 0x1, len, is_write);
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
 	if (ret)
-		/* PFPW engine is busy, use cpu copy methode */
+		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
 
 	init_completion(&info->comp);
@@ -407,10 +416,11 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
 
 	/* setup and start DMA using dma_addr */
 	wait_for_completion(&info->comp);
+	tim = 0;
+	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
+	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		cpu_relax();
 
-	do {
-		prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT);
-	} while (prefetch_status);
 	/* disable and stop the PFPW engine */
 	gpmc_prefetch_reset(info->gpmc_cs);
 
@@ -426,14 +436,6 @@ out_copy:
 			: omap_write_buf8(mtd, (u_char *) addr, len);
 	return 0;
 }
-#else
-static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) {}
-static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
-					unsigned int len, int is_write)
-{
-	return 0;
-}
-#endif
 
 /**
  * omap_read_buf_dma_pref - read data from NAND controller into buffer
@@ -466,6 +468,157 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd,
 		omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
 }
 
+/*
+ * omap_nand_irq - GMPC irq handler
+ * @this_irq: gpmc irq number
+ * @dev: omap_nand_info structure pointer is passed here
+ */
+static irqreturn_t omap_nand_irq(int this_irq, void *dev)
+{
+	struct omap_nand_info *info = (struct omap_nand_info *) dev;
+	u32 bytes;
+	u32 irq_stat;
+
+	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
+	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
+		if (irq_stat & 0x2)
+			goto done;
+
+		if (info->buf_len && (info->buf_len < bytes))
+			bytes = info->buf_len;
+		else if (!info->buf_len)
+			bytes = 0;
+		iowrite32_rep(info->nand.IO_ADDR_W,
+						(u32 *)info->buf, bytes >> 2);
+		info->buf = info->buf + bytes;
+		info->buf_len -= bytes;
+
+	} else {
+		ioread32_rep(info->nand.IO_ADDR_R,
+						(u32 *)info->buf, bytes >> 2);
+		info->buf = info->buf + bytes;
+
+		if (irq_stat & 0x2)
+			goto done;
+	}
+	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+
+	return IRQ_HANDLED;
+
+done:
+	complete(&info->comp);
+	/* disable irq */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
+
+	/* clear status */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * omap_read_buf_irq_pref - read data from NAND controller into buffer
+ * @mtd: MTD device structure
+ * @buf: buffer to store date
+ * @len: number of bytes to read
+ */
+static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct omap_nand_info *info = container_of(mtd,
+						struct omap_nand_info, mtd);
+	int ret = 0;
+
+	if (len <= mtd->oobsize) {
+		omap_read_buf_pref(mtd, buf, len);
+		return;
+	}
+
+	info->iomode = OMAP_NAND_IO_READ;
+	info->buf = buf;
+	init_completion(&info->comp);
+
+	/*  configure and start prefetch transfer */
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
+	if (ret)
+		/* PFPW engine is busy, use cpu copy method */
+		goto out_copy;
+
+	info->buf_len = len;
+	/* enable irq */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
+		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	/* waiting for read to complete */
+	wait_for_completion(&info->comp);
+
+	/* disable and stop the PFPW engine */
+	gpmc_prefetch_reset(info->gpmc_cs);
+	return;
+
+out_copy:
+	if (info->nand.options & NAND_BUSWIDTH_16)
+		omap_read_buf16(mtd, buf, len);
+	else
+		omap_read_buf8(mtd, buf, len);
+}
+
+/*
+ * omap_write_buf_irq_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_irq_pref(struct mtd_info *mtd,
+					const u_char *buf, int len)
+{
+	struct omap_nand_info *info = container_of(mtd,
+						struct omap_nand_info, mtd);
+	int ret = 0;
+	unsigned long tim, limit;
+
+	if (len <= mtd->oobsize) {
+		omap_write_buf_pref(mtd, buf, len);
+		return;
+	}
+
+	info->iomode = OMAP_NAND_IO_WRITE;
+	info->buf = (u_char *) buf;
+	init_completion(&info->comp);
+
+	/* configure and start prefetch transfer : size=24 */
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1);
+	if (ret)
+		/* PFPW engine is busy, use cpu copy method */
+		goto out_copy;
+
+	info->buf_len = len;
+	/* enable irq */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
+			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	/* waiting for write to complete */
+	wait_for_completion(&info->comp);
+	/* wait for data to flushed-out before reset the prefetch */
+	tim = 0;
+	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
+	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		cpu_relax();
+
+	/* disable and stop the PFPW engine */
+	gpmc_prefetch_reset(info->gpmc_cs);
+	return;
+
+out_copy:
+	if (info->nand.options & NAND_BUSWIDTH_16)
+		omap_write_buf16(mtd, buf, len);
+	else
+		omap_write_buf8(mtd, buf, len);
+}
+
 /**
  * omap_verify_buf - Verify chip data against buffer
  * @mtd: MTD device structure
@@ -487,8 +640,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
 	return 0;
 }
 
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
-
 /**
  * gen_true_ecc - This function will generate true ECC value
  * @ecc_buf: buffer to store ecc code
@@ -708,8 +859,6 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
 	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
 }
 
-#endif
-
 /**
  * omap_wait - wait until the command is done
  * @mtd: MTD device structure
@@ -779,6 +928,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	struct omap_nand_info		*info;
 	struct omap_nand_platform_data	*pdata;
 	int				err;
+	int				i, offset;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -804,7 +954,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 	info->mtd.name		= dev_name(&pdev->dev);
 	info->mtd.owner		= THIS_MODULE;
 
-	info->nand.options	|= pdata->devsize ? NAND_BUSWIDTH_16 : 0;
+	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
 	/* NAND write protect off */
@@ -842,28 +992,13 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		info->nand.chip_delay = 50;
 	}
 
-	if (use_prefetch) {
-
+	switch (pdata->xfer_type) {
+	case NAND_OMAP_PREFETCH_POLLED:
 		info->nand.read_buf   = omap_read_buf_pref;
 		info->nand.write_buf  = omap_write_buf_pref;
-		if (use_dma) {
-			err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
-				omap_nand_dma_cb, &info->comp, &info->dma_ch);
-			if (err < 0) {
-				info->dma_ch = -1;
-				printk(KERN_WARNING "DMA request failed."
-					" Non-dma data transfer mode\n");
-			} else {
-				omap_set_dma_dest_burst_mode(info->dma_ch,
-						OMAP_DMA_DATA_BURST_16);
-				omap_set_dma_src_burst_mode(info->dma_ch,
-						OMAP_DMA_DATA_BURST_16);
-
-				info->nand.read_buf   = omap_read_buf_dma_pref;
-				info->nand.write_buf  = omap_write_buf_dma_pref;
-			}
-		}
-	} else {
+		break;
+
+	case NAND_OMAP_POLLED:
 		if (info->nand.options & NAND_BUSWIDTH_16) {
 			info->nand.read_buf   = omap_read_buf16;
 			info->nand.write_buf  = omap_write_buf16;
@@ -871,20 +1006,61 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 			info->nand.read_buf   = omap_read_buf8;
 			info->nand.write_buf  = omap_write_buf8;
 		}
+		break;
+
+	case NAND_OMAP_PREFETCH_DMA:
+		err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
+				omap_nand_dma_cb, &info->comp, &info->dma_ch);
+		if (err < 0) {
+			info->dma_ch = -1;
+			dev_err(&pdev->dev, "DMA request failed!\n");
+			goto out_release_mem_region;
+		} else {
+			omap_set_dma_dest_burst_mode(info->dma_ch,
+					OMAP_DMA_DATA_BURST_16);
+			omap_set_dma_src_burst_mode(info->dma_ch,
+					OMAP_DMA_DATA_BURST_16);
+
+			info->nand.read_buf   = omap_read_buf_dma_pref;
+			info->nand.write_buf  = omap_write_buf_dma_pref;
+		}
+		break;
+
+	case NAND_OMAP_PREFETCH_IRQ:
+		err = request_irq(pdata->gpmc_irq,
+				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info);
+		if (err) {
+			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
+							pdata->gpmc_irq, err);
+			goto out_release_mem_region;
+		} else {
+			info->gpmc_irq	     = pdata->gpmc_irq;
+			info->nand.read_buf  = omap_read_buf_irq_pref;
+			info->nand.write_buf = omap_write_buf_irq_pref;
+		}
+		break;
+
+	default:
+		dev_err(&pdev->dev,
+			"xfer_type(%d) not supported!\n", pdata->xfer_type);
+		err = -EINVAL;
+		goto out_release_mem_region;
 	}
-	info->nand.verify_buf = omap_verify_buf;
 
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
-	info->nand.ecc.bytes		= 3;
-	info->nand.ecc.size		= 512;
-	info->nand.ecc.calculate	= omap_calculate_ecc;
-	info->nand.ecc.hwctl		= omap_enable_hwecc;
-	info->nand.ecc.correct		= omap_correct_data;
-	info->nand.ecc.mode		= NAND_ECC_HW;
+	info->nand.verify_buf = omap_verify_buf;
 
-#else
-	info->nand.ecc.mode = NAND_ECC_SOFT;
-#endif
+	/* selsect the ecc type */
+	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
+		info->nand.ecc.mode = NAND_ECC_SOFT;
+	else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
+		(pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
+		info->nand.ecc.bytes            = 3;
+		info->nand.ecc.size             = 512;
+		info->nand.ecc.calculate        = omap_calculate_ecc;
+		info->nand.ecc.hwctl            = omap_enable_hwecc;
+		info->nand.ecc.correct          = omap_correct_data;
+		info->nand.ecc.mode             = NAND_ECC_HW;
+	}
 
 	/* DIP switches on some boards change between 8 and 16 bit
 	 * bus widths for flash.  Try the other width if the first try fails.
@@ -897,6 +1073,26 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		}
 	}
 
+	/* rom code layout */
+	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) {
+
+		if (info->nand.options & NAND_BUSWIDTH_16)
+			offset = 2;
+		else {
+			offset = 1;
+			info->nand.badblock_pattern = &bb_descrip_flashbased;
+		}
+		omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16);
+		for (i = 0; i < omap_oobinfo.eccbytes; i++)
+			omap_oobinfo.eccpos[i] = i+offset;
+
+		omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
+		omap_oobinfo.oobfree->length = info->mtd.oobsize -
+					(offset + omap_oobinfo.eccbytes);
+
+		info->nand.ecc.layout = &omap_oobinfo;
+	}
+
 #ifdef CONFIG_MTD_PARTITIONS
 	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 	if (err > 0)
@@ -926,9 +1122,12 @@ static int omap_nand_remove(struct platform_device *pdev)
 							mtd);
 
 	platform_set_drvdata(pdev, NULL);
-	if (use_dma)
+	if (info->dma_ch != -1)
 		omap_free_dma(info->dma_ch);
 
+	if (info->gpmc_irq)
+		free_irq(info->gpmc_irq, info);
+
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
 	iounmap(info->nand.IO_ADDR_R);
@@ -947,16 +1146,8 @@ static struct platform_driver omap_nand_driver = {
 
 static int __init omap_nand_init(void)
 {
-	printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME);
+	pr_info("%s driver initializing\n", DRIVER_NAME);
 
-	/* This check is required if driver is being
-	 * loaded run time as a module
-	 */
-	if ((1 == use_dma) && (0 == use_prefetch)) {
-		printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 "
-				"without use_prefetch'. Prefetch will not be"
-				" used in either mode (mpu or dma)\n");
-	}
 	return platform_driver_register(&omap_nand_driver);
 }
 
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index bb277a5..59efa82 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -89,8 +89,7 @@ int pasemi_device_ready(struct mtd_info *mtd)
 	return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
 }
 
-static int __devinit pasemi_nand_probe(struct platform_device *ofdev,
-				      const struct of_device_id *match)
+static int __devinit pasemi_nand_probe(struct platform_device *ofdev)
 {
 	struct pci_dev *pdev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -219,7 +218,7 @@ static const struct of_device_id pasemi_nand_match[] =
 
 MODULE_DEVICE_TABLE(of, pasemi_nand_match);
 
-static struct of_platform_driver pasemi_nand_driver =
+static struct platform_driver pasemi_nand_driver =
 {
 	.driver = {
 		.name = (char*)driver_name,
@@ -232,13 +231,13 @@ static struct of_platform_driver pasemi_nand_driver =
 
 static int __init pasemi_nand_init(void)
 {
-	return of_register_platform_driver(&pasemi_nand_driver);
+	return platform_driver_register(&pasemi_nand_driver);
 }
 module_init(pasemi_nand_init);
 
 static void __exit pasemi_nand_exit(void)
 {
-	of_unregister_platform_driver(&pasemi_nand_driver);
+	platform_driver_unregister(&pasemi_nand_driver);
 }
 module_exit(pasemi_nand_exit);
 
diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index a8e403e..a853548 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -162,8 +162,7 @@ static const char *part_probes[] = { "cmdlinepart", NULL };
 /*
  * Probe for the NAND device.
  */
-static int __devinit socrates_nand_probe(struct platform_device *ofdev,
-					 const struct of_device_id *ofid)
+static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 {
 	struct socrates_nand_host *host;
 	struct mtd_info *mtd;
@@ -300,7 +299,7 @@ static const struct of_device_id socrates_nand_match[] =
 
 MODULE_DEVICE_TABLE(of, socrates_nand_match);
 
-static struct of_platform_driver socrates_nand_driver = {
+static struct platform_driver socrates_nand_driver = {
 	.driver = {
 		.name = "socrates_nand",
 		.owner = THIS_MODULE,
@@ -312,12 +311,12 @@ static struct of_platform_driver socrates_nand_driver = {
 
 static int __init socrates_nand_init(void)
 {
-	return of_register_platform_driver(&socrates_nand_driver);
+	return platform_driver_register(&socrates_nand_driver);
 }
 
 static void __exit socrates_nand_exit(void)
 {
-	of_unregister_platform_driver(&socrates_nand_driver);
+	platform_driver_unregister(&socrates_nand_driver);
 }
 
 module_init(socrates_nand_init);
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 4dbd0f5..4f42619 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -32,7 +32,7 @@ config MTD_ONENAND_OMAP2
 
 config MTD_ONENAND_SAMSUNG
         tristate "OneNAND on Samsung SOC controller support"
-        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310
+        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4
         help
           Support for a OneNAND flash device connected to an Samsung SOC.
           S3C64XX/S5PC100 use command mapping method.
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index c849cac..14a49ab 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -63,7 +63,7 @@ struct omap2_onenand {
 	struct completion dma_done;
 	int dma_channel;
 	int freq;
-	int (*setup)(void __iomem *base, int freq);
+	int (*setup)(void __iomem *base, int *freq_ptr);
 	struct regulator *regulator;
 };
 
@@ -148,11 +148,9 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
 			wait_err("controller error", state, ctrl, intr);
 			return -EIO;
 		}
-		if ((intr & intr_flags) != intr_flags) {
-			wait_err("timeout", state, ctrl, intr);
-			return -EIO;
-		}
-		return 0;
+		if ((intr & intr_flags) == intr_flags)
+			return 0;
+		/* Continue in wait for interrupt branch */
 	}
 
 	if (state != FL_READING) {
@@ -581,7 +579,7 @@ static int __adjust_timing(struct device *dev, void *data)
 
 	/* DMA is not in use so this is all that is needed */
 	/* Revisit for OMAP3! */
-	ret = c->setup(c->onenand.base, c->freq);
+	ret = c->setup(c->onenand.base, &c->freq);
 
 	return ret;
 }
@@ -673,7 +671,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	}
 
 	if (pdata->onenand_setup != NULL) {
-		r = pdata->onenand_setup(c->onenand.base, c->freq);
+		r = pdata->onenand_setup(c->onenand.base, &c->freq);
 		if (r < 0) {
 			dev_err(&pdev->dev, "Onenand platform setup failed: "
 				"%d\n", r);
@@ -718,8 +716,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	}
 
 	dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
-		 "base %p\n", c->gpmc_cs, c->phys_base,
-		 c->onenand.base);
+		 "base %p, freq %d MHz\n", c->gpmc_cs, c->phys_base,
+		 c->onenand.base, c->freq);
 
 	c->pdev = pdev;
 	c->mtd.name = dev_name(&pdev->dev);
@@ -754,24 +752,6 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	switch ((c->onenand.version_id >> 4) & 0xf) {
-	case 0:
-		c->freq = 40;
-		break;
-	case 1:
-		c->freq = 54;
-		break;
-	case 2:
-		c->freq = 66;
-		break;
-	case 3:
-		c->freq = 83;
-		break;
-	case 4:
-		c->freq = 104;
-		break;
-	}
-
 #ifdef CONFIG_MTD_PARTITIONS
 	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
 	if (r > 0)
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 3cf193f..6abeb4f 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -52,6 +52,12 @@ config MTD_UBI_GLUEBI
 	   work on top of UBI. Do not enable this unless you use legacy
 	   software.
 
-source "drivers/mtd/ubi/Kconfig.debug"
+config MTD_UBI_DEBUG
+	bool "UBI debugging"
+	depends on SYSFS
+	select DEBUG_FS
+	select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
+	help
+	  This option enables UBI debugging.
 
 endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug
deleted file mode 100644
index fad4adc..0000000
--- a/drivers/mtd/ubi/Kconfig.debug
+++ /dev/null
@@ -1,73 +0,0 @@
-comment "UBI debugging options"
-
-config MTD_UBI_DEBUG
-	bool "UBI debugging"
-	depends on SYSFS
-	select DEBUG_FS
-	select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
-	help
-	  This option enables UBI debugging.
-
-if MTD_UBI_DEBUG
-
-config MTD_UBI_DEBUG_MSG
-	bool "UBI debugging messages"
-	help
-	  This option enables UBI debugging messages.
-
-config MTD_UBI_DEBUG_PARANOID
-	bool "Extra self-checks"
-	help
-	  This option enables extra checks in UBI code. Note this slows UBI down
-	  significantly.
-
-config MTD_UBI_DEBUG_DISABLE_BGT
-	bool "Do not enable the UBI background thread"
-	help
-	  This option switches the background thread off by default. The thread
-	  may be also be enabled/disabled via UBI sysfs.
-
-config MTD_UBI_DEBUG_EMULATE_BITFLIPS
-	bool "Emulate flash bit-flips"
-	help
-	  This option emulates bit-flips with probability 1/50, which in turn
-	  causes scrubbing. Useful for debugging and stressing UBI.
-
-config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
-	bool "Emulate flash write failures"
-	help
-	  This option emulates write failures with probability 1/100. Useful for
-	  debugging and testing how UBI handlines errors.
-
-config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
-	bool "Emulate flash erase failures"
-	help
-	  This option emulates erase failures with probability 1/100. Useful for
-	  debugging and testing how UBI handlines errors.
-
-comment "Additional UBI debugging messages"
-
-config MTD_UBI_DEBUG_MSG_BLD
-	bool "Additional UBI initialization and build messages"
-	help
-	  This option enables detailed UBI initialization and device build
-	  debugging messages.
-
-config MTD_UBI_DEBUG_MSG_EBA
-	bool "Eraseblock association unit messages"
-	help
-	  This option enables debugging messages from the UBI eraseblock
-	  association unit.
-
-config MTD_UBI_DEBUG_MSG_WL
-	bool "Wear-leveling unit messages"
-	help
-	  This option enables debugging messages from the UBI wear-leveling
-	  unit.
-
-config MTD_UBI_DEBUG_MSG_IO
-	bool "Input/output unit messages"
-	help
-	  This option enables debugging messages from the UBI input/output unit.
-
-endif # MTD_UBI_DEBUG
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 5ebe280..65626c1 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -690,11 +690,25 @@ static int io_init(struct ubi_device *ubi)
 	ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size);
 	ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);
 
+	ubi->max_write_size = ubi->mtd->writebufsize;
+	/*
+	 * Maximum write size has to be greater or equivalent to min. I/O
+	 * size, and be multiple of min. I/O size.
+	 */
+	if (ubi->max_write_size < ubi->min_io_size ||
+	    ubi->max_write_size % ubi->min_io_size ||
+	    !is_power_of_2(ubi->max_write_size)) {
+		ubi_err("bad write buffer size %d for %d min. I/O unit",
+			ubi->max_write_size, ubi->min_io_size);
+		return -EINVAL;
+	}
+
 	/* Calculate default aligned sizes of EC and VID headers */
 	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
 	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
 
 	dbg_msg("min_io_size      %d", ubi->min_io_size);
+	dbg_msg("max_write_size   %d", ubi->max_write_size);
 	dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
 	dbg_msg("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);
 	dbg_msg("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);
@@ -711,7 +725,7 @@ static int io_init(struct ubi_device *ubi)
 	}
 
 	/* Similar for the data offset */
-	ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE;
+	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
 	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
 
 	dbg_msg("vid_hdr_offset   %d", ubi->vid_hdr_offset);
@@ -923,6 +937,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	spin_lock_init(&ubi->volumes_lock);
 
 	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
+	dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
+	dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
 
 	err = io_init(ubi);
 	if (err)
@@ -937,13 +953,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	if (!ubi->peb_buf2)
 		goto out_free;
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-	mutex_init(&ubi->dbg_buf_mutex);
-	ubi->dbg_peb_buf = vmalloc(ubi->peb_size);
-	if (!ubi->dbg_peb_buf)
-		goto out_free;
-#endif
-
 	err = attach_by_scanning(ubi);
 	if (err) {
 		dbg_err("failed to attach by scanning, error %d", err);
@@ -991,8 +1000,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
 	 * checks @ubi->thread_enabled. Otherwise we may fail to wake it up.
 	 */
 	spin_lock(&ubi->wl_lock);
-	if (!DBG_DISABLE_BGT)
-		ubi->thread_enabled = 1;
+	ubi->thread_enabled = 1;
 	wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 
@@ -1009,9 +1017,6 @@ out_detach:
 out_free:
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-	vfree(ubi->dbg_peb_buf);
-#endif
 	if (ref)
 		put_device(&ubi->dev);
 	else
@@ -1082,9 +1087,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
 	put_mtd_device(ubi->mtd);
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-	vfree(ubi->dbg_peb_buf);
-#endif
 	ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num);
 	put_device(&ubi->dev);
 	return 0;
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 4876977..d4d07e5 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -27,6 +27,20 @@
 #ifdef CONFIG_MTD_UBI_DEBUG
 
 #include "ubi.h"
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+unsigned int ubi_msg_flags;
+unsigned int ubi_chk_flags;
+unsigned int ubi_tst_flags;
+
+module_param_named(debug_msgs, ubi_msg_flags, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
+
+MODULE_PARM_DESC(debug_msgs, "Debug message type flags");
+MODULE_PARM_DESC(debug_chks, "Debug check flags");
+MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
 
 /**
  * ubi_dbg_dump_ec_hdr - dump an erase counter header.
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 9eca950..0b0c288 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -38,6 +38,11 @@
 	printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
 	       current->pid, __func__, ##__VA_ARGS__)
 
+#define dbg_do_msg(typ, fmt, ...) do {                       \
+	if (ubi_msg_flags & typ)                             \
+		dbg_msg(fmt, ##__VA_ARGS__);                 \
+} while (0)
+
 #define ubi_dbg_dump_stack() dump_stack()
 
 struct ubi_ec_hdr;
@@ -57,62 +62,88 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
 void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
 
+extern unsigned int ubi_msg_flags;
+
+/*
+ * Debugging message type flags (must match msg_type_names in debug.c).
+ *
+ * UBI_MSG_GEN: general messages
+ * UBI_MSG_EBA: journal messages
+ * UBI_MSG_WL: mount messages
+ * UBI_MSG_IO: commit messages
+ * UBI_MSG_BLD: LEB find messages
+ */
+enum {
+	UBI_MSG_GEN  = 0x1,
+	UBI_MSG_EBA  = 0x2,
+	UBI_MSG_WL   = 0x4,
+	UBI_MSG_IO   = 0x8,
+	UBI_MSG_BLD  = 0x10,
+};
+
 #define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  \
 		print_hex_dump(l, ps, pt, r, g, b, len, a)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG
 /* General debugging messages */
-#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_gen(fmt, ...) ({})
-#endif
+#define dbg_gen(fmt, ...) dbg_do_msg(UBI_MSG_GEN, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA
 /* Messages from the eraseblock association sub-system */
-#define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_eba(fmt, ...) ({})
-#endif
+#define dbg_eba(fmt, ...) dbg_do_msg(UBI_MSG_EBA, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL
 /* Messages from the wear-leveling sub-system */
-#define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_wl(fmt, ...) ({})
-#endif
+#define dbg_wl(fmt, ...) dbg_do_msg(UBI_MSG_WL, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO
 /* Messages from the input/output sub-system */
-#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_io(fmt, ...) ({})
-#endif
+#define dbg_io(fmt, ...) dbg_do_msg(UBI_MSG_IO, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD
 /* Initialization and build messages */
-#define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#define UBI_IO_DEBUG 1
-#else
-#define dbg_bld(fmt, ...) ({})
-#define UBI_IO_DEBUG 0
-#endif
+#define dbg_bld(fmt, ...) dbg_do_msg(UBI_MSG_BLD, fmt, ##__VA_ARGS__)
+
+extern unsigned int ubi_chk_flags;
+
+/*
+ * Debugging check flags.
+ *
+ * UBI_CHK_GEN: general checks
+ * UBI_CHK_IO: check writes and erases
+ */
+enum {
+	UBI_CHK_GEN = 0x1,
+	UBI_CHK_IO  = 0x2,
+};
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
 int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
 			int offset, int len);
-#else
-#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
-#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
-#define DBG_DISABLE_BGT 1
-#else
-#define DBG_DISABLE_BGT 0
-#endif
+extern unsigned int ubi_tst_flags;
+
+/*
+ * Special testing flags.
+ *
+ * UBIFS_TST_DISABLE_BGT: disable the background thread
+ * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips
+ * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures
+ * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures
+ */
+enum {
+	UBI_TST_DISABLE_BGT            = 0x1,
+	UBI_TST_EMULATE_BITFLIPS       = 0x2,
+	UBI_TST_EMULATE_WRITE_FAILURES = 0x4,
+	UBI_TST_EMULATE_ERASE_FAILURES = 0x8,
+};
+
+/**
+ * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ *
+ * Returns non-zero if the UBI background thread is disabled for testing
+ * purposes.
+ */
+static inline int ubi_dbg_is_bgt_disabled(void)
+{
+	return ubi_tst_flags & UBI_TST_DISABLE_BGT;
+}
 
-#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
 /**
  * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
  *
@@ -120,13 +151,11 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
  */
 static inline int ubi_dbg_is_bitflip(void)
 {
-	return !(random32() % 200);
+	if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS)
+		return !(random32() % 200);
+	return 0;
 }
-#else
-#define ubi_dbg_is_bitflip() 0
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
 /**
  * ubi_dbg_is_write_failure - if it is time to emulate a write failure.
  *
@@ -135,13 +164,11 @@ static inline int ubi_dbg_is_bitflip(void)
  */
 static inline int ubi_dbg_is_write_failure(void)
 {
-	return !(random32() % 500);
+	if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES)
+		return !(random32() % 500);
+	return 0;
 }
-#else
-#define ubi_dbg_is_write_failure() 0
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
 /**
  * ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
  *
@@ -150,11 +177,10 @@ static inline int ubi_dbg_is_write_failure(void)
  */
 static inline int ubi_dbg_is_erase_failure(void)
 {
+	if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES)
 		return !(random32() % 400);
+	return 0;
 }
-#else
-#define ubi_dbg_is_erase_failure() 0
-#endif
 
 #else
 
@@ -177,8 +203,7 @@ static inline int ubi_dbg_is_erase_failure(void)
 #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({})
 #define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  ({})
 
-#define UBI_IO_DEBUG               0
-#define DBG_DISABLE_BGT            0
+#define ubi_dbg_is_bgt_disabled()  0
 #define ubi_dbg_is_bitflip()       0
 #define ubi_dbg_is_write_failure() 0
 #define ubi_dbg_is_erase_failure() 0
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 811775a..aaa6e1e 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -91,7 +91,7 @@
 #include <linux/slab.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
@@ -146,6 +146,28 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
 	if (err)
 		return err;
 
+	/*
+	 * Deliberately corrupt the buffer to improve robustness. Indeed, if we
+	 * do not do this, the following may happen:
+	 * 1. The buffer contains data from previous operation, e.g., read from
+	 *    another PEB previously. The data looks like expected, e.g., if we
+	 *    just do not read anything and return - the caller would not
+	 *    notice this. E.g., if we are reading a VID header, the buffer may
+	 *    contain a valid VID header from another PEB.
+	 * 2. The driver is buggy and returns us success or -EBADMSG or
+	 *    -EUCLEAN, but it does not actually put any data to the buffer.
+	 *
+	 * This may confuse UBI or upper layers - they may think the buffer
+	 * contains valid data while in fact it is just old data. This is
+	 * especially possible because UBI (and UBIFS) relies on CRC, and
+	 * treats data as correct even in case of ECC errors if the CRC is
+	 * correct.
+	 *
+	 * Try to prevent this situation by changing the first byte of the
+	 * buffer.
+	 */
+	*((uint8_t *)buf) ^= 0xFF;
+
 	addr = (loff_t)pnum * ubi->peb_size + offset;
 retry:
 	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
@@ -166,7 +188,7 @@ retry:
 			return UBI_IO_BITFLIPS;
 		}
 
-		if (read != len && retries++ < UBI_IO_RETRIES) {
+		if (retries++ < UBI_IO_RETRIES) {
 			dbg_io("error %d%s while reading %d bytes from PEB %d:%d,"
 			       " read only %zd bytes, retry",
 			       err, errstr, len, pnum, offset, read);
@@ -480,6 +502,13 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
 	size_t written;
 	loff_t addr;
 	uint32_t data = 0;
+	/*
+	 * Note, we cannot generally define VID header buffers on stack,
+	 * because of the way we deal with these buffers (see the header
+	 * comment in this file). But we know this is a NOR-specific piece of
+	 * code, so we can do this. But yes, this is error-prone and we should
+	 * (pre-)allocate VID header buffer instead.
+	 */
 	struct ubi_vid_hdr vid_hdr;
 
 	/*
@@ -507,11 +536,13 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
 	 * PEB.
 	 */
 	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
-	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) {
+	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR ||
+	    err1 == UBI_IO_FF) {
 		struct ubi_ec_hdr ec_hdr;
 
 		err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
-		if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
+		if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR ||
+		    err1 == UBI_IO_FF)
 			/*
 			 * Both VID and EC headers are corrupted, so we can
 			 * safely erase this PEB and not afraid that it will be
@@ -752,9 +783,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 			if (verbose)
 				ubi_warn("no EC header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
-			else if (UBI_IO_DEBUG)
-				dbg_msg("no EC header found at PEB %d, "
-					"only 0xFF bytes", pnum);
+			dbg_bld("no EC header found at PEB %d, "
+				"only 0xFF bytes", pnum);
 			if (!read_err)
 				return UBI_IO_FF;
 			else
@@ -769,9 +799,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 			ubi_warn("bad magic number at PEB %d: %08x instead of "
 				 "%08x", pnum, magic, UBI_EC_HDR_MAGIC);
 			ubi_dbg_dump_ec_hdr(ec_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad magic number at PEB %d: %08x instead of "
-				"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
+		}
+		dbg_bld("bad magic number at PEB %d: %08x instead of "
+			"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
 		return UBI_IO_BAD_HDR;
 	}
 
@@ -783,9 +813,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
 			ubi_warn("bad EC header CRC at PEB %d, calculated "
 				 "%#08x, read %#08x", pnum, crc, hdr_crc);
 			ubi_dbg_dump_ec_hdr(ec_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad EC header CRC at PEB %d, calculated "
-				"%#08x, read %#08x", pnum, crc, hdr_crc);
+		}
+		dbg_bld("bad EC header CRC at PEB %d, calculated "
+			"%#08x, read %#08x", pnum, crc, hdr_crc);
 
 		if (!read_err)
 			return UBI_IO_BAD_HDR;
@@ -1008,9 +1038,8 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 			if (verbose)
 				ubi_warn("no VID header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
-			else if (UBI_IO_DEBUG)
-				dbg_msg("no VID header found at PEB %d, "
-					"only 0xFF bytes", pnum);
+			dbg_bld("no VID header found at PEB %d, "
+				"only 0xFF bytes", pnum);
 			if (!read_err)
 				return UBI_IO_FF;
 			else
@@ -1021,9 +1050,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 			ubi_warn("bad magic number at PEB %d: %08x instead of "
 				 "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
 			ubi_dbg_dump_vid_hdr(vid_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad magic number at PEB %d: %08x instead of "
-				"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
+		}
+		dbg_bld("bad magic number at PEB %d: %08x instead of "
+			"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
 		return UBI_IO_BAD_HDR;
 	}
 
@@ -1035,9 +1064,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
 			ubi_warn("bad CRC at PEB %d, calculated %#08x, "
 				 "read %#08x", pnum, crc, hdr_crc);
 			ubi_dbg_dump_vid_hdr(vid_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad CRC at PEB %d, calculated %#08x, "
-				"read %#08x", pnum, crc, hdr_crc);
+		}
+		dbg_bld("bad CRC at PEB %d, calculated %#08x, "
+			"read %#08x", pnum, crc, hdr_crc);
 		if (!read_err)
 			return UBI_IO_BAD_HDR;
 		else
@@ -1097,7 +1126,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
 	return err;
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_not_bad - ensure that a physical eraseblock is not bad.
@@ -1111,6 +1140,9 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
 {
 	int err;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	err = ubi_io_is_bad(ubi, pnum);
 	if (!err)
 		return err;
@@ -1135,6 +1167,9 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
 	int err;
 	uint32_t magic;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	magic = be32_to_cpu(ec_hdr->magic);
 	if (magic != UBI_EC_HDR_MAGIC) {
 		ubi_err("bad magic %#08x, must be %#08x",
@@ -1170,6 +1205,9 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
 	uint32_t crc, hdr_crc;
 	struct ubi_ec_hdr *ec_hdr;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
@@ -1211,6 +1249,9 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
 	int err;
 	uint32_t magic;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	magic = be32_to_cpu(vid_hdr->magic);
 	if (magic != UBI_VID_HDR_MAGIC) {
 		ubi_err("bad VID header magic %#08x at PEB %d, must be %#08x",
@@ -1249,6 +1290,9 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
 	struct ubi_vid_hdr *vid_hdr;
 	void *p;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
 		return -ENOMEM;
@@ -1294,15 +1338,26 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
 			int offset, int len)
 {
 	int err, i;
+	size_t read;
+	void *buf1;
+	loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-	mutex_lock(&ubi->dbg_buf_mutex);
-	err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len);
-	if (err)
-		goto out_unlock;
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
+	buf1 = __vmalloc(len, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf1) {
+		ubi_err("cannot allocate memory to check writes");
+		return 0;
+	}
+
+	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1);
+	if (err && err != -EUCLEAN)
+		goto out_free;
 
 	for (i = 0; i < len; i++) {
 		uint8_t c = ((uint8_t *)buf)[i];
-		uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i];
+		uint8_t c1 = ((uint8_t *)buf1)[i];
 		int dump_len;
 
 		if (c == c1)
@@ -1319,17 +1374,17 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
 		ubi_msg("hex dump of the read buffer from %d to %d",
 			i, i + dump_len);
 		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-			       ubi->dbg_peb_buf + i, dump_len, 1);
+			       buf1 + i, dump_len, 1);
 		ubi_dbg_dump_stack();
 		err = -EINVAL;
-		goto out_unlock;
+		goto out_free;
 	}
-	mutex_unlock(&ubi->dbg_buf_mutex);
 
+	vfree(buf1);
 	return 0;
 
-out_unlock:
-	mutex_unlock(&ubi->dbg_buf_mutex);
+out_free:
+	vfree(buf1);
 	return err;
 }
 
@@ -1348,36 +1403,44 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
 {
 	size_t read;
 	int err;
+	void *buf;
 	loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-	mutex_lock(&ubi->dbg_buf_mutex);
-	err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf);
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
+	buf = __vmalloc(len, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubi_err("cannot allocate memory to check for 0xFFs");
+		return 0;
+	}
+
+	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
 	if (err && err != -EUCLEAN) {
 		ubi_err("error %d while reading %d bytes from PEB %d:%d, "
 			"read %zd bytes", err, len, pnum, offset, read);
 		goto error;
 	}
 
-	err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len);
+	err = ubi_check_pattern(buf, 0xFF, len);
 	if (err == 0) {
 		ubi_err("flash region at PEB %d:%d, length %d does not "
 			"contain all 0xFF bytes", pnum, offset, len);
 		goto fail;
 	}
-	mutex_unlock(&ubi->dbg_buf_mutex);
 
+	vfree(buf);
 	return 0;
 
 fail:
 	ubi_err("paranoid check failed for PEB %d", pnum);
 	ubi_msg("hex dump of the %d-%d region", offset, offset + len);
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-		       ubi->dbg_peb_buf, len, 1);
+	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
 	err = -EINVAL;
 error:
 	ubi_dbg_dump_stack();
-	mutex_unlock(&ubi->dbg_buf_mutex);
+	vfree(buf);
 	return err;
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index 69fa4ef0..d39716e 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -40,7 +40,9 @@ void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di)
 {
 	di->ubi_num = ubi->ubi_num;
 	di->leb_size = ubi->leb_size;
+	di->leb_start = ubi->leb_start;
 	di->min_io_size = ubi->min_io_size;
+	di->max_write_size = ubi->max_write_size;
 	di->ro_mode = ubi->ro_mode;
 	di->cdev = ubi->cdev.dev;
 }
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 79ca304..11eb8ef 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -39,32 +39,46 @@
  * eraseblocks are put to the @free list and the physical eraseblock to be
  * erased are put to the @erase list.
  *
+ * About corruptions
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * UBI protects EC and VID headers with CRC-32 checksums, so it can detect
+ * whether the headers are corrupted or not. Sometimes UBI also protects the
+ * data with CRC-32, e.g., when it executes the atomic LEB change operation, or
+ * when it moves the contents of a PEB for wear-leveling purposes.
+ *
  * UBI tries to distinguish between 2 types of corruptions.
- * 1. Corruptions caused by power cuts. These are harmless and expected
- *    corruptions and UBI tries to handle them gracefully, without printing too
- *    many warnings and error messages. The idea is that we do not lose
- *    important data in these case - we may lose only the data which was being
- *    written to the media just before the power cut happened, and the upper
- *    layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
- *    these PEBs to the head of the @erase list and they are scheduled for
- *    erasure.
+ *
+ * 1. Corruptions caused by power cuts. These are expected corruptions and UBI
+ * tries to handle them gracefully, without printing too many warnings and
+ * error messages. The idea is that we do not lose important data in these case
+ * - we may lose only the data which was being written to the media just before
+ * the power cut happened, and the upper layers (e.g., UBIFS) are supposed to
+ * handle such data losses (e.g., by using the FS journal).
+ *
+ * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like
+ * the reason is a power cut, UBI puts this PEB to the @erase list, and all
+ * PEBs in the @erase list are scheduled for erasure later.
  *
  * 2. Unexpected corruptions which are not caused by power cuts. During
- *    scanning, such PEBs are put to the @corr list and UBI preserves them.
- *    Obviously, this lessens the amount of available PEBs, and if at some
- *    point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
- *    informs about such PEBs every time the MTD device is attached.
+ * scanning, such PEBs are put to the @corr list and UBI preserves them.
+ * Obviously, this lessens the amount of available PEBs, and if at some  point
+ * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs
+ * about such PEBs every time the MTD device is attached.
  *
  * However, it is difficult to reliably distinguish between these types of
- * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
- * header is corrupted and the data area does not contain all 0xFFs, and there
- * were not bit-flips or integrity errors while reading the data area. Otherwise
- * UBI assumes (1.). The assumptions are:
- *   o if the data area contains only 0xFFs, there is no data, and it is safe
- *     to just erase this PEB.
- *   o if the data area has bit-flips and data integrity errors (ECC errors on
+ * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2
+ * if the VID header is corrupted and the data area does not contain all 0xFFs,
+ * and there were no bit-flips or integrity errors while reading the data area.
+ * Otherwise UBI assumes corruption type 1. So the decision criteria are as
+ * follows.
+ *   o If the data area contains only 0xFFs, there is no data, and it is safe
+ *     to just erase this PEB - this is corruption type 1.
+ *   o If the data area has bit-flips or data integrity errors (ECC errors on
  *     NAND), it is probably a PEB which was being erased when power cut
- *     happened.
+ *     happened, so this is corruption type 1. However, this is just a guess,
+ *     which might be wrong.
+ *   o Otherwise this it corruption type 2.
  */
 
 #include <linux/err.h>
@@ -74,7 +88,7 @@
 #include <linux/random.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
 #else
 #define paranoid_check_si(ubi, si) 0
@@ -115,7 +129,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
 	} else
 		BUG();
 
-	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 	if (!seb)
 		return -ENOMEM;
 
@@ -144,7 +158,7 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
 
 	dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
 
-	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 	if (!seb)
 		return -ENOMEM;
 
@@ -553,7 +567,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
 	if (err)
 		return err;
 
-	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 	if (!seb)
 		return -ENOMEM;
 
@@ -1152,9 +1166,15 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
 	si->volumes = RB_ROOT;
 
 	err = -ENOMEM;
+	si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
+					      sizeof(struct ubi_scan_leb),
+					      0, 0, NULL);
+	if (!si->scan_leb_slab)
+		goto out_si;
+
 	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
 	if (!ech)
-		goto out_si;
+		goto out_slab;
 
 	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 	if (!vidh)
@@ -1215,6 +1235,8 @@ out_vidh:
 	ubi_free_vid_hdr(ubi, vidh);
 out_ech:
 	kfree(ech);
+out_slab:
+	kmem_cache_destroy(si->scan_leb_slab);
 out_si:
 	ubi_scan_destroy_si(si);
 	return ERR_PTR(err);
@@ -1223,11 +1245,12 @@ out_si:
 /**
  * destroy_sv - free the scanning volume information
  * @sv: scanning volume information
+ * @si: scanning information
  *
  * This function destroys the volume RB-tree (@sv->root) and the scanning
  * volume information.
  */
-static void destroy_sv(struct ubi_scan_volume *sv)
+static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
 {
 	struct ubi_scan_leb *seb;
 	struct rb_node *this = sv->root.rb_node;
@@ -1247,7 +1270,7 @@ static void destroy_sv(struct ubi_scan_volume *sv)
 					this->rb_right = NULL;
 			}
 
-			kfree(seb);
+			kmem_cache_free(si->scan_leb_slab, seb);
 		}
 	}
 	kfree(sv);
@@ -1265,19 +1288,19 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
 
 	list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 	list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 	list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 	list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 
 	/* Destroy the volume RB-tree */
@@ -1298,14 +1321,15 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
 					rb->rb_right = NULL;
 			}
 
-			destroy_sv(sv);
+			destroy_sv(si, sv);
 		}
 	}
 
+	kmem_cache_destroy(si->scan_leb_slab);
 	kfree(si);
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_si - check the scanning information.
@@ -1323,6 +1347,9 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
 	struct ubi_scan_leb *seb, *last_seb;
 	uint8_t *buf;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	/*
 	 * At first, check that scanning information is OK.
 	 */
@@ -1575,4 +1602,4 @@ out:
 	return -EINVAL;
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index a3264f0..d48aef1 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -109,6 +109,7 @@ struct ubi_scan_volume {
  * @mean_ec: mean erase counter value
  * @ec_sum: a temporary variable used when calculating @mean_ec
  * @ec_count: a temporary variable used when calculating @mean_ec
+ * @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
  *
  * This data structure contains the result of scanning and may be used by other
  * UBI sub-systems to build final UBI data structures, further error-recovery
@@ -134,6 +135,7 @@ struct ubi_scan_info {
 	int mean_ec;
 	uint64_t ec_sum;
 	int ec_count;
+	struct kmem_cache *scan_leb_slab;
 };
 
 struct ubi_device;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 0b0149c..f1be8b7 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -40,6 +40,7 @@
 #include <linux/notifier.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
+#include <asm/pgtable.h>
 
 #include "ubi-media.h"
 #include "scan.h"
@@ -381,14 +382,14 @@ struct ubi_wl_entry;
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  *               not
  * @nor_flash: non-zero if working on top of NOR flash
+ * @max_write_size: maximum amount of bytes the underlying flash can write at a
+ *                  time (MTD write buffer size)
  * @mtd: MTD device descriptor
  *
  * @peb_buf1: a buffer of PEB size used for different purposes
  * @peb_buf2: another buffer of PEB size used for different purposes
  * @buf_mutex: protects @peb_buf1 and @peb_buf2
  * @ckvol_mutex: serializes static volume checking when opening
- * @dbg_peb_buf: buffer of PEB size used for debugging
- * @dbg_buf_mutex: protects @dbg_peb_buf
  */
 struct ubi_device {
 	struct cdev cdev;
@@ -464,16 +465,13 @@ struct ubi_device {
 	int vid_hdr_shift;
 	unsigned int bad_allowed:1;
 	unsigned int nor_flash:1;
+	int max_write_size;
 	struct mtd_info *mtd;
 
 	void *peb_buf1;
 	void *peb_buf2;
 	struct mutex buf_mutex;
 	struct mutex ckvol_mutex;
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-	void *dbg_peb_buf;
-	struct mutex dbg_buf_mutex;
-#endif
 };
 
 extern struct kmem_cache *ubi_wl_entry_slab;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index c47620d..b79e0de 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -28,7 +28,7 @@
 #include <linux/slab.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_volumes(struct ubi_device *ubi);
 #else
 #define paranoid_check_volumes(ubi) 0
@@ -711,7 +711,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
 	volume_sysfs_close(vol);
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_volume - check volume information.
@@ -876,6 +876,9 @@ static int paranoid_check_volumes(struct ubi_device *ubi)
 {
 	int i, err = 0;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	for (i = 0; i < ubi->vtbl_slots; i++) {
 		err = paranoid_check_volume(ubi, i);
 		if (err)
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 0b8141f..fd3bf77 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -62,7 +62,7 @@
 #include <asm/div64.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static void paranoid_vtbl_check(const struct ubi_device *ubi);
 #else
 #define paranoid_vtbl_check(ubi)
@@ -868,7 +868,7 @@ out_free:
 	return err;
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_vtbl_check - check volume table.
@@ -876,10 +876,13 @@ out_free:
  */
 static void paranoid_vtbl_check(const struct ubi_device *ubi)
 {
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return;
+
 	if (vtbl_check(ubi, ubi->vtbl)) {
 		ubi_err("paranoid check failed");
 		BUG();
 	}
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 655bbbe..b4cf57d 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -161,7 +161,7 @@ struct ubi_work {
 	int torture;
 };
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
 				     struct rb_root *root);
@@ -613,7 +613,7 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
 	list_add_tail(&wrk->list, &ubi->works);
 	ubi_assert(ubi->works_count >= 0);
 	ubi->works_count += 1;
-	if (ubi->thread_enabled)
+	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled())
 		wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 }
@@ -1364,7 +1364,7 @@ int ubi_thread(void *u)
 
 		spin_lock(&ubi->wl_lock);
 		if (list_empty(&ubi->works) || ubi->ro_mode ||
-			       !ubi->thread_enabled) {
+		    !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock(&ubi->wl_lock);
 			schedule();
@@ -1561,7 +1561,7 @@ void ubi_wl_close(struct ubi_device *ubi)
 	kfree(ubi->lookuptbl);
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_ec - make sure that the erase counter of a PEB is correct.
@@ -1578,6 +1578,9 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
 	long long read_ec;
 	struct ubi_ec_hdr *ec_hdr;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
@@ -1614,6 +1617,9 @@ out_free:
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
 				     struct rb_root *root)
 {
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	if (in_wl_tree(e, root))
 		return 0;
 
@@ -1636,6 +1642,9 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
 	struct ubi_wl_entry *p;
 	int i;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
 		list_for_each_entry(p, &ubi->pq[i], u.list)
 			if (p == e)
@@ -1646,4 +1655,5 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
 	ubi_dbg_dump_stack();
 	return -EINVAL;
 }
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 0382332..dc280bc 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -238,8 +238,8 @@ source "drivers/net/arm/Kconfig"
 config AX88796
 	tristate "ASIX AX88796 NE2000 clone support"
 	depends on ARM || MIPS || SUPERH
-	select CRC32
-	select MII
+	select PHYLIB
+	select MDIO_BITBANG
 	help
 	  AX88796 driver, using platform bus to provide
 	  chip detection and resources
@@ -1498,7 +1498,7 @@ config FORCEDETH
 config CS89x0
 	tristate "CS89x0 support"
 	depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \
-		|| ARCH_IXDP2X01 || MACH_MX31ADS)
+		|| ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards. If you have a
 	  network (Ethernet) card of this type, say Y and read the
@@ -1512,7 +1512,7 @@ config CS89x0
 config CS89x0_NONISA_IRQ
 	def_bool y
 	depends on CS89x0 != n
-	depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS
+	depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
 
 config TC35815
 	tristate "TOSHIBA TC35815 Ethernet support"
@@ -1944,7 +1944,8 @@ config 68360_ENET
 config FEC
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
 	depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
-		MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
+		IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC
+	default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
 	select PHYLIB
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
@@ -2007,6 +2008,15 @@ config BCM63XX_ENET
 	  This driver supports the ethernet MACs in the Broadcom 63xx
 	  MIPS chipset family (BCM63XX).
 
+config FTMAC100
+	tristate "Faraday FTMAC100 10/100 Ethernet support"
+	depends on ARM
+	select MII
+	help
+	  This driver supports the FTMAC100 10/100 Ethernet controller
+	  from Faraday. It is used on Faraday A320, Andes AG101 and some
+	  other ARM/NDS32 SoC's.
+
 source "drivers/net/fs_enet/Kconfig"
 
 source "drivers/net/octeon/Kconfig"
@@ -2098,7 +2108,9 @@ config E1000
 
 config E1000E
 	tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
+	select CRC32
 	depends on PCI && (!SPARC32 || BROKEN)
+	select CRC32
 	---help---
 	  This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
 	  ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -2235,15 +2247,6 @@ config R8169
 	  To compile this driver as a module, choose M here: the module
 	  will be called r8169.  This is recommended.
 
-config R8169_VLAN
-	bool "VLAN support"
-	depends on R8169 && VLAN_8021Q
-	---help---
-	  Say Y here for the r8169 driver to support the functions required
-	  by the kernel 802.1Q code.
-
-	  If in doubt, say Y.
-
 config SB1250_MAC
 	tristate "SB1250 Gigabit Ethernet support"
 	depends on SIBYTE_SB1xxx_SOC
@@ -2594,14 +2597,9 @@ config CHELSIO_T1_1G
 	  Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
 	  are using only 10G cards say 'N' here.
 
-config CHELSIO_T3_DEPENDS
-	tristate
-	depends on PCI && INET
-	default y
-
 config CHELSIO_T3
 	tristate "Chelsio Communications T3 10Gb Ethernet support"
-	depends on CHELSIO_T3_DEPENDS
+	depends on PCI && INET
 	select FW_LOADER
 	select MDIO
 	help
@@ -2619,14 +2617,9 @@ config CHELSIO_T3
 	  To compile this driver as a module, choose M here: the module
 	  will be called cxgb3.
 
-config CHELSIO_T4_DEPENDS
-	tristate
-	depends on PCI && INET
-	default y
-
 config CHELSIO_T4
 	tristate "Chelsio Communications T4 Ethernet support"
-	depends on CHELSIO_T4_DEPENDS
+	depends on PCI
 	select FW_LOADER
 	select MDIO
 	help
@@ -2644,14 +2637,9 @@ config CHELSIO_T4
 	  To compile this driver as a module choose M here; the module
 	  will be called cxgb4.
 
-config CHELSIO_T4VF_DEPENDS
-	tristate
-	depends on PCI && INET
-	default y
-
 config CHELSIO_T4VF
 	tristate "Chelsio Communications T4 Virtual Function Ethernet support"
-	depends on CHELSIO_T4VF_DEPENDS
+	depends on PCI
 	help
 	  This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
 	  adapters with PCI-E SR-IOV Virtual Functions.
@@ -2966,12 +2954,38 @@ config XEN_NETDEV_FRONTEND
 	select XEN_XENBUS_FRONTEND
 	default y
 	help
-	  The network device frontend driver allows the kernel to
-	  access network devices exported exported by a virtual
-	  machine containing a physical network device driver. The
-	  frontend driver is intended for unprivileged guest domains;
-	  if you are compiling a kernel for a Xen guest, you almost
-	  certainly want to enable this.
+	  This driver provides support for Xen paravirtual network
+	  devices exported by a Xen network driver domain (often
+	  domain 0).
+
+	  The corresponding Linux backend driver is enabled by the
+	  CONFIG_XEN_NETDEV_BACKEND option.
+
+	  If you are compiling a kernel for use as Xen guest, you
+	  should say Y here. To compile this driver as a module, chose
+	  M here: the module will be called xen-netfront.
+
+config XEN_NETDEV_BACKEND
+	tristate "Xen backend network device"
+	depends on XEN_BACKEND
+	help
+	  This driver allows the kernel to act as a Xen network driver
+	  domain which exports paravirtual network devices to other
+	  Xen domains. These devices can be accessed by any operating
+	  system that implements a compatible front end.
+
+	  The corresponding Linux frontend driver is enabled by the
+	  CONFIG_XEN_NETDEV_FRONTEND configuration option.
+
+	  The backend driver presents a standard network device
+	  endpoint for each paravirtual network device to the driver
+	  domain network stack. These can then be bridged or routed
+	  etc in order to provide full network connectivity.
+
+	  If you are compiling a kernel to run in a Xen network driver
+	  domain (often this is domain 0) you should say Y here. To
+	  compile this driver as a module, chose M here: the module
+	  will be called xen-netback.
 
 config ISERIES_VETH
 	tristate "iSeries Virtual Ethernet driver support"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b90738d..01b604a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -147,6 +147,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o
 obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_FTMAC100) += ftmac100.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
@@ -171,6 +172,7 @@ obj-$(CONFIG_SLIP) += slip.o
 obj-$(CONFIG_SLHC) += slhc.o
 
 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
diff --git a/drivers/net/appletalk/Kconfig b/drivers/net/appletalk/Kconfig
index 0b376a9..f5a8916 100644
--- a/drivers/net/appletalk/Kconfig
+++ b/drivers/net/appletalk/Kconfig
@@ -3,7 +3,6 @@
 #
 config ATALK
 	tristate "Appletalk protocol support"
-	depends on BKL # waiting to be removed from net/appletalk/ddp.c
 	select LLC
 	---help---
 	  AppleTalk is the protocol that Apple computers can use to communicate
diff --git a/drivers/net/atl1c/atl1c.h b/drivers/net/atl1c/atl1c.h
index 9ab5809..7cb375e 100644
--- a/drivers/net/atl1c/atl1c.h
+++ b/drivers/net/atl1c/atl1c.h
@@ -265,7 +265,7 @@ struct atl1c_recv_ret_status {
 	__le32	word3;
 };
 
-/* RFD desciptor */
+/* RFD descriptor */
 struct atl1c_rx_free_desc {
 	__le64	buffer_addr;
 };
@@ -531,7 +531,7 @@ struct atl1c_rfd_ring {
 	struct atl1c_buffer *buffer_info;
 };
 
-/* receive return desciptor (rrd) ring */
+/* receive return descriptor (rrd) ring */
 struct atl1c_rrd_ring {
 	void *desc;		/* descriptor ring virtual address */
 	dma_addr_t dma;		/* descriptor ring physical address */
diff --git a/drivers/net/atl1c/atl1c_hw.c b/drivers/net/atl1c/atl1c_hw.c
index 1bf6720..23f2ab0 100644
--- a/drivers/net/atl1c/atl1c_hw.c
+++ b/drivers/net/atl1c/atl1c_hw.c
@@ -345,7 +345,7 @@ int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data)
  */
 static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 {
-	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
+	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL;
 	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
 				~GIGA_CR_1000T_SPEED_MASK;
 
@@ -373,7 +373,7 @@ static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 	}
 
 	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
-	    atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
+	    atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0)
 		return -1;
 	return 0;
 }
@@ -517,19 +517,18 @@ int atl1c_phy_init(struct atl1c_hw *hw)
 					"Error Setting up Auto-Negotiation\n");
 			return ret_val;
 		}
-		mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+		mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
 		break;
 	case MEDIA_TYPE_100M_FULL:
-		mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
+		mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX;
 		break;
 	case MEDIA_TYPE_100M_HALF:
-		mii_bmcr_data |= BMCR_SPEED_100;
+		mii_bmcr_data |= BMCR_SPEED100;
 		break;
 	case MEDIA_TYPE_10M_FULL:
-		mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
+		mii_bmcr_data |= BMCR_FULLDPLX;
 		break;
 	case MEDIA_TYPE_10M_HALF:
-		mii_bmcr_data |= BMCR_SPEED_10;
 		break;
 	default:
 		if (netif_msg_link(adapter))
@@ -657,7 +656,7 @@ int atl1c_restart_autoneg(struct atl1c_hw *hw)
 	err = atl1c_phy_setup_adv(hw);
 	if (err)
 		return err;
-	mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+	mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
 
 	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 }
diff --git a/drivers/net/atl1c/atl1c_hw.h b/drivers/net/atl1c/atl1c_hw.h
index 3dd6759..655fc6c 100644
--- a/drivers/net/atl1c/atl1c_hw.h
+++ b/drivers/net/atl1c/atl1c_hw.h
@@ -736,55 +736,16 @@ int atl1c_phy_power_saving(struct atl1c_hw *hw);
 #define REG_DEBUG_DATA0 		0x1900
 #define REG_DEBUG_DATA1 		0x1904
 
-/* PHY Control Register */
-#define MII_BMCR			0x00
-#define BMCR_SPEED_SELECT_MSB		0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define BMCR_COLL_TEST_ENABLE		0x0080  /* Collision test enable */
-#define BMCR_FULL_DUPLEX		0x0100  /* FDX =1, half duplex =0 */
-#define BMCR_RESTART_AUTO_NEG		0x0200  /* Restart auto negotiation */
-#define BMCR_ISOLATE			0x0400  /* Isolate PHY from MII */
-#define BMCR_POWER_DOWN			0x0800  /* Power down */
-#define BMCR_AUTO_NEG_EN		0x1000  /* Auto Neg Enable */
-#define BMCR_SPEED_SELECT_LSB		0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define BMCR_LOOPBACK			0x4000  /* 0 = normal, 1 = loopback */
-#define BMCR_RESET			0x8000  /* 0 = normal, 1 = PHY reset */
-#define BMCR_SPEED_MASK			0x2040
-#define BMCR_SPEED_1000			0x0040
-#define BMCR_SPEED_100			0x2000
-#define BMCR_SPEED_10			0x0000
-
-/* PHY Status Register */
-#define MII_BMSR			0x01
-#define BMMSR_EXTENDED_CAPS		0x0001  /* Extended register capabilities */
-#define BMSR_JABBER_DETECT		0x0002  /* Jabber Detected */
-#define BMSR_LINK_STATUS		0x0004  /* Link Status 1 = link */
-#define BMSR_AUTONEG_CAPS		0x0008  /* Auto Neg Capable */
-#define BMSR_REMOTE_FAULT		0x0010  /* Remote Fault Detect */
-#define BMSR_AUTONEG_COMPLETE		0x0020  /* Auto Neg Complete */
-#define BMSR_PREAMBLE_SUPPRESS		0x0040  /* Preamble may be suppressed */
-#define BMSR_EXTENDED_STATUS		0x0100  /* Ext. status info in Reg 0x0F */
-#define BMSR_100T2_HD_CAPS		0x0200  /* 100T2 Half Duplex Capable */
-#define BMSR_100T2_FD_CAPS		0x0400  /* 100T2 Full Duplex Capable */
-#define BMSR_10T_HD_CAPS		0x0800  /* 10T   Half Duplex Capable */
-#define BMSR_10T_FD_CAPS		0x1000  /* 10T   Full Duplex Capable */
-#define BMSR_100X_HD_CAPS		0x2000  /* 100X  Half Duplex Capable */
-#define BMMII_SR_100X_FD_CAPS		0x4000  /* 100X  Full Duplex Capable */
-#define BMMII_SR_100T4_CAPS		0x8000  /* 100T4 Capable */
-
-#define MII_PHYSID1			0x02
-#define MII_PHYSID2			0x03
 #define L1D_MPW_PHYID1			0xD01C  /* V7 */
 #define L1D_MPW_PHYID2			0xD01D  /* V1-V6 */
 #define L1D_MPW_PHYID3			0xD01E  /* V8 */
 
 
 /* Autoneg Advertisement Register */
-#define MII_ADVERTISE			0x04
-#define ADVERTISE_SPEED_MASK		0x01E0
-#define ADVERTISE_DEFAULT_CAP		0x0DE0
+#define ADVERTISE_DEFAULT_CAP \
+	(ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)
 
 /* 1000BASE-T Control Register */
-#define MII_GIGA_CR			0x09
 #define GIGA_CR_1000T_REPEATER_DTE	0x0400  /* 1=Repeater/switch device port 0=DTE device */
 
 #define GIGA_CR_1000T_MS_VALUE		0x0800  /* 1=Configure PHY as Master 0=Configure PHY as Slave */
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 3824382..7d9d506 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -1102,10 +1102,10 @@ static void atl1c_configure_tx(struct atl1c_adapter *adapter)
 	AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data);
 	max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) &
 			DEVICE_CTRL_MAX_PAYLOAD_MASK;
-	hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+	hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block);
 	max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) &
 			DEVICE_CTRL_MAX_RREQ_SZ_MASK;
-	hw->dmar_block = min(max_pay_load, hw->dmar_block);
+	hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block);
 
 	txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
 			TXQ_NUM_TPD_BURST_SHIFT;
@@ -2718,7 +2718,6 @@ static int __devinit atl1c_probe(struct pci_dev *pdev,
 		goto err_reset;
 	}
 
-	device_init_wakeup(&pdev->dev, 1);
 	/* reset the controller to
 	 * put the device in a known good starting state */
 	err = atl1c_phy_init(&adapter->hw);
diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c
index 6943a6c..1209297 100644
--- a/drivers/net/atl1e/atl1e_ethtool.c
+++ b/drivers/net/atl1e/atl1e_ethtool.c
@@ -95,18 +95,18 @@ static int atl1e_set_settings(struct net_device *netdev,
 		ecmd->advertising = hw->autoneg_advertised |
 				    ADVERTISED_TP | ADVERTISED_Autoneg;
 
-		adv4 = hw->mii_autoneg_adv_reg & ~MII_AR_SPEED_MASK;
+		adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL;
 		adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK;
 		if (hw->autoneg_advertised & ADVERTISE_10_HALF)
-			adv4 |= MII_AR_10T_HD_CAPS;
+			adv4 |= ADVERTISE_10HALF;
 		if (hw->autoneg_advertised & ADVERTISE_10_FULL)
-			adv4 |= MII_AR_10T_FD_CAPS;
+			adv4 |= ADVERTISE_10FULL;
 		if (hw->autoneg_advertised & ADVERTISE_100_HALF)
-			adv4 |= MII_AR_100TX_HD_CAPS;
+			adv4 |= ADVERTISE_100HALF;
 		if (hw->autoneg_advertised & ADVERTISE_100_FULL)
-			adv4 |= MII_AR_100TX_FD_CAPS;
+			adv4 |= ADVERTISE_100FULL;
 		if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
-			adv9 |= MII_AT001_CR_1000T_FD_CAPS;
+			adv9 |= ADVERTISE_1000FULL;
 
 		if (adv4 != hw->mii_autoneg_adv_reg ||
 				adv9 != hw->mii_1000t_ctrl_reg) {
diff --git a/drivers/net/atl1e/atl1e_hw.c b/drivers/net/atl1e/atl1e_hw.c
index 76cc043..923063d 100644
--- a/drivers/net/atl1e/atl1e_hw.c
+++ b/drivers/net/atl1e/atl1e_hw.c
@@ -318,7 +318,7 @@ static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
 	 * the  1000Base-T control Register (Address 9).
 	 */
-	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+	mii_autoneg_adv_reg &= ~ADVERTISE_ALL;
 	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK;
 
 	/*
@@ -327,44 +327,37 @@ static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
 	 */
 	switch (hw->media_type) {
 	case MEDIA_TYPE_AUTO_SENSOR:
-		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS   |
-					MII_AR_10T_FD_CAPS   |
-					MII_AR_100TX_HD_CAPS |
-					MII_AR_100TX_FD_CAPS);
-		hw->autoneg_advertised = ADVERTISE_10_HALF  |
-					 ADVERTISE_10_FULL  |
-					 ADVERTISE_100_HALF |
-					 ADVERTISE_100_FULL;
+		mii_autoneg_adv_reg |= ADVERTISE_ALL;
+		hw->autoneg_advertised = ADVERTISE_ALL;
 		if (hw->nic_type == athr_l1e) {
-			mii_1000t_ctrl_reg |=
-				MII_AT001_CR_1000T_FD_CAPS;
+			mii_1000t_ctrl_reg |= ADVERTISE_1000FULL;
 			hw->autoneg_advertised |= ADVERTISE_1000_FULL;
 		}
 		break;
 
 	case MEDIA_TYPE_100M_FULL:
-		mii_autoneg_adv_reg   |= MII_AR_100TX_FD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_100FULL;
 		hw->autoneg_advertised = ADVERTISE_100_FULL;
 		break;
 
 	case MEDIA_TYPE_100M_HALF:
-		mii_autoneg_adv_reg   |= MII_AR_100TX_HD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_100_HALF;
 		hw->autoneg_advertised = ADVERTISE_100_HALF;
 		break;
 
 	case MEDIA_TYPE_10M_FULL:
-		mii_autoneg_adv_reg   |= MII_AR_10T_FD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_10_FULL;
 		hw->autoneg_advertised = ADVERTISE_10_FULL;
 		break;
 
 	default:
-		mii_autoneg_adv_reg   |= MII_AR_10T_HD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_10_HALF;
 		hw->autoneg_advertised = ADVERTISE_10_HALF;
 		break;
 	}
 
 	/* flow control fixed to enable all */
-	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+	mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP);
 
 	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
 	hw->mii_1000t_ctrl_reg  = mii_1000t_ctrl_reg;
@@ -374,7 +367,7 @@ static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
 		return ret_val;
 
 	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
-		ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+		ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000,
 					   mii_1000t_ctrl_reg);
 		if (ret_val)
 			return ret_val;
@@ -397,7 +390,7 @@ int atl1e_phy_commit(struct atl1e_hw *hw)
 	int ret_val;
 	u16 phy_data;
 
-	phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+	phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART;
 
 	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
 	if (ret_val) {
@@ -645,15 +638,14 @@ int atl1e_restart_autoneg(struct atl1e_hw *hw)
 		return err;
 
 	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
-		err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+		err = atl1e_write_phy_reg(hw, MII_CTRL1000,
 				       hw->mii_1000t_ctrl_reg);
 		if (err)
 			return err;
 	}
 
 	err = atl1e_write_phy_reg(hw, MII_BMCR,
-			MII_CR_RESET | MII_CR_AUTO_NEG_EN |
-			MII_CR_RESTART_AUTO_NEG);
+			BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
 	return err;
 }
 
diff --git a/drivers/net/atl1e/atl1e_hw.h b/drivers/net/atl1e/atl1e_hw.h
index 5ea2f4d..74df16a 100644
--- a/drivers/net/atl1e/atl1e_hw.h
+++ b/drivers/net/atl1e/atl1e_hw.h
@@ -629,127 +629,24 @@ s32 atl1e_restart_autoneg(struct atl1e_hw *hw);
 
 /***************************** MII definition ***************************************/
 /* PHY Common Register */
-#define MII_BMCR                        0x00
-#define MII_BMSR                        0x01
-#define MII_PHYSID1                     0x02
-#define MII_PHYSID2                     0x03
-#define MII_ADVERTISE                   0x04
-#define MII_LPA                         0x05
-#define MII_EXPANSION                   0x06
-#define MII_AT001_CR                    0x09
-#define MII_AT001_SR                    0x0A
-#define MII_AT001_ESR                   0x0F
 #define MII_AT001_PSCR                  0x10
 #define MII_AT001_PSSR                  0x11
 #define MII_INT_CTRL                    0x12
 #define MII_INT_STATUS                  0x13
 #define MII_SMARTSPEED                  0x14
-#define MII_RERRCOUNTER                 0x15
-#define MII_SREVISION                   0x16
-#define MII_RESV1                       0x17
 #define MII_LBRERROR                    0x18
-#define MII_PHYADDR                     0x19
 #define MII_RESV2                       0x1a
-#define MII_TPISTATUS                   0x1b
-#define MII_NCONFIG                     0x1c
 
 #define MII_DBG_ADDR			0x1D
 #define MII_DBG_DATA			0x1E
 
-
-/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB                  0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE                  0x0080  /* Collision test enable */
-#define MII_CR_FULL_DUPLEX                       0x0100  /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG                  0x0200  /* Restart auto negotiation */
-#define MII_CR_ISOLATE                           0x0400  /* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN                        0x0800  /* Power down */
-#define MII_CR_AUTO_NEG_EN                       0x1000  /* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB                  0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK                          0x4000  /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET                             0x8000  /* 0 = normal, 1 = PHY reset */
-#define MII_CR_SPEED_MASK                        0x2040
-#define MII_CR_SPEED_1000                        0x0040
-#define MII_CR_SPEED_100                         0x2000
-#define MII_CR_SPEED_10                          0x0000
-
-
-/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS                     0x0001  /* Extended register capabilities */
-#define MII_SR_JABBER_DETECT                     0x0002  /* Jabber Detected */
-#define MII_SR_LINK_STATUS                       0x0004  /* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS                      0x0008  /* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT                      0x0010  /* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE                  0x0020  /* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS                 0x0040  /* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS                   0x0100  /* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS                     0x0200  /* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS                     0x0400  /* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS                       0x0800  /* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS                       0x1000  /* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS                      0x2000  /* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS                      0x4000  /* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS                        0x8000  /* 100T4 Capable */
-
-/* Link partner ability register. */
-#define MII_LPA_SLCT                             0x001f  /* Same as advertise selector  */
-#define MII_LPA_10HALF                           0x0020  /* Can do 10mbps half-duplex   */
-#define MII_LPA_10FULL                           0x0040  /* Can do 10mbps full-duplex   */
-#define MII_LPA_100HALF                          0x0080  /* Can do 100mbps half-duplex  */
-#define MII_LPA_100FULL                          0x0100  /* Can do 100mbps full-duplex  */
-#define MII_LPA_100BASE4                         0x0200  /* 100BASE-T4  */
-#define MII_LPA_PAUSE                            0x0400  /* PAUSE */
-#define MII_LPA_ASYPAUSE                         0x0800  /* Asymmetrical PAUSE */
-#define MII_LPA_RFAULT                           0x2000  /* Link partner faulted        */
-#define MII_LPA_LPACK                            0x4000  /* Link partner acked us       */
-#define MII_LPA_NPAGE                            0x8000  /* Next page bit               */
-
 /* Autoneg Advertisement Register */
-#define MII_AR_SELECTOR_FIELD                   0x0001  /* indicates IEEE 802.3 CSMA/CD */
-#define MII_AR_10T_HD_CAPS                      0x0020  /* 10T   Half Duplex Capable */
-#define MII_AR_10T_FD_CAPS                      0x0040  /* 10T   Full Duplex Capable */
-#define MII_AR_100TX_HD_CAPS                    0x0080  /* 100TX Half Duplex Capable */
-#define MII_AR_100TX_FD_CAPS                    0x0100  /* 100TX Full Duplex Capable */
-#define MII_AR_100T4_CAPS                       0x0200  /* 100T4 Capable */
-#define MII_AR_PAUSE                            0x0400  /* Pause operation desired */
-#define MII_AR_ASM_DIR                          0x0800  /* Asymmetric Pause Direction bit */
-#define MII_AR_REMOTE_FAULT                     0x2000  /* Remote Fault detected */
-#define MII_AR_NEXT_PAGE                        0x8000  /* Next Page ability supported */
-#define MII_AR_SPEED_MASK                       0x01E0
-#define MII_AR_DEFAULT_CAP_MASK                 0x0DE0
+#define MII_AR_DEFAULT_CAP_MASK                 0
 
 /* 1000BASE-T Control Register */
-#define MII_AT001_CR_1000T_HD_CAPS              0x0100  /* Advertise 1000T HD capability */
-#define MII_AT001_CR_1000T_FD_CAPS              0x0200  /* Advertise 1000T FD capability  */
-#define MII_AT001_CR_1000T_REPEATER_DTE         0x0400  /* 1=Repeater/switch device port */
-/* 0=DTE device */
-#define MII_AT001_CR_1000T_MS_VALUE             0x0800  /* 1=Configure PHY as Master */
-/* 0=Configure PHY as Slave */
-#define MII_AT001_CR_1000T_MS_ENABLE            0x1000  /* 1=Master/Slave manual config value */
-/* 0=Automatic Master/Slave config */
-#define MII_AT001_CR_1000T_TEST_MODE_NORMAL     0x0000  /* Normal Operation */
-#define MII_AT001_CR_1000T_TEST_MODE_1          0x2000  /* Transmit Waveform test */
-#define MII_AT001_CR_1000T_TEST_MODE_2          0x4000  /* Master Transmit Jitter test */
-#define MII_AT001_CR_1000T_TEST_MODE_3          0x6000  /* Slave Transmit Jitter test */
-#define MII_AT001_CR_1000T_TEST_MODE_4          0x8000  /* Transmitter Distortion test */
-#define MII_AT001_CR_1000T_SPEED_MASK           0x0300
-#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK     0x0300
-
-/* 1000BASE-T Status Register */
-#define MII_AT001_SR_1000T_LP_HD_CAPS           0x0400  /* LP is 1000T HD capable */
-#define MII_AT001_SR_1000T_LP_FD_CAPS           0x0800  /* LP is 1000T FD capable */
-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS     0x1000  /* Remote receiver OK */
-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS      0x2000  /* Local receiver OK */
-#define MII_AT001_SR_1000T_MS_CONFIG_RES        0x4000  /* 1=Local TX is Master, 0=Slave */
-#define MII_AT001_SR_1000T_MS_CONFIG_FAULT      0x8000  /* Master/Slave config fault */
-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT   12
-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT    13
-
-/* Extended Status Register */
-#define MII_AT001_ESR_1000T_HD_CAPS             0x1000  /* 1000T HD capable */
-#define MII_AT001_ESR_1000T_FD_CAPS             0x2000  /* 1000T FD capable */
-#define MII_AT001_ESR_1000X_HD_CAPS             0x4000  /* 1000X HD capable */
-#define MII_AT001_ESR_1000X_FD_CAPS             0x8000  /* 1000X FD capable */
+#define MII_AT001_CR_1000T_SPEED_MASK \
+	(ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK	MII_AT001_CR_1000T_SPEED_MASK
 
 /* AT001 PHY Specific Control Register */
 #define MII_AT001_PSCR_JABBER_DISABLE           0x0001  /* 1=Jabber Function disabled */
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index e28f8ba..1ff001a 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -547,8 +547,8 @@ static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_id = pdev->subsystem_device;
+	hw->revision_id  = pdev->revision;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
 	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
@@ -932,11 +932,11 @@ static inline void atl1e_configure_tx(struct atl1e_adapter *adapter)
 	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
 			DEVICE_CTRL_MAX_PAYLOAD_MASK;
 
-	hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+	hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block);
 
 	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
 			DEVICE_CTRL_MAX_RREQ_SZ_MASK;
-	hw->dmar_block = min(max_pay_load, hw->dmar_block);
+	hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block);
 
 	if (hw->nic_type != athr_l2e_revB)
 		AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
@@ -2051,9 +2051,9 @@ static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state)
 		atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
 		atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
 
-		mii_advertise_data = MII_AR_10T_HD_CAPS;
+		mii_advertise_data = ADVERTISE_10HALF;
 
-		if ((atl1e_write_phy_reg(hw, MII_AT001_CR, 0) != 0) ||
+		if ((atl1e_write_phy_reg(hw, MII_CTRL1000, 0) != 0) ||
 		    (atl1e_write_phy_reg(hw,
 			   MII_ADVERTISE, mii_advertise_data) != 0) ||
 		    (atl1e_phy_commit(hw)) != 0) {
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 3b52768..67f40b9 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -950,6 +950,7 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
 	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
 	adapter->wol = 0;
+	device_set_wakeup_enable(&adapter->pdev->dev, false);
 	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
 	adapter->ict = 50000;		/* 100ms */
 	adapter->link_speed = SPEED_0;	/* hardware init */
@@ -2735,15 +2736,15 @@ static int atl1_close(struct net_device *netdev)
 }
 
 #ifdef CONFIG_PM
-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+static int atl1_suspend(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct atl1_adapter *adapter = netdev_priv(netdev);
 	struct atl1_hw *hw = &adapter->hw;
 	u32 ctrl = 0;
 	u32 wufc = adapter->wol;
 	u32 val;
-	int retval;
 	u16 speed;
 	u16 duplex;
 
@@ -2751,17 +2752,15 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
 	if (netif_running(netdev))
 		atl1_down(adapter);
 
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-
 	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
 	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
 	val = ctrl & BMSR_LSTATUS;
 	if (val)
 		wufc &= ~ATLX_WUFC_LNKC;
+	if (!wufc)
+		goto disable_wol;
 
-	if (val && wufc) {
+	if (val) {
 		val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
 		if (val) {
 			if (netif_msg_ifdown(adapter))
@@ -2798,23 +2797,18 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
 		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
 		iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
 		ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
-
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-		goto exit;
-	}
-
-	if (!val && wufc) {
+	} else {
 		ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
 		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
 		ioread32(hw->hw_addr + REG_WOL_CTRL);
 		iowrite32(0, hw->hw_addr + REG_MAC_CTRL);
 		ioread32(hw->hw_addr + REG_MAC_CTRL);
 		hw->phy_configured = false;
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-		goto exit;
 	}
 
-disable_wol:
+	return 0;
+
+ disable_wol:
 	iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
 	ioread32(hw->hw_addr + REG_WOL_CTRL);
 	ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
@@ -2822,37 +2816,17 @@ disable_wol:
 	iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
 	ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
 	hw->phy_configured = false;
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-exit:
-	if (netif_running(netdev))
-		pci_disable_msi(adapter->pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
 	return 0;
 }
 
-static int atl1_resume(struct pci_dev *pdev)
+static int atl1_resume(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u32 err;
 
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		if (netif_msg_ifup(adapter))
-			dev_printk(KERN_DEBUG, &pdev->dev,
-				"error enabling pci device\n");
-		return err;
-	}
-
-	pci_set_master(pdev);
 	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	atl1_reset_hw(&adapter->hw);
 
@@ -2864,16 +2838,25 @@ static int atl1_resume(struct pci_dev *pdev)
 
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(atl1_pm_ops, atl1_suspend, atl1_resume);
+#define ATL1_PM_OPS	(&atl1_pm_ops)
+
 #else
-#define atl1_suspend NULL
-#define atl1_resume NULL
+
+static int atl1_suspend(struct device *dev) { return 0; }
+
+#define ATL1_PM_OPS	NULL
 #endif
 
 static void atl1_shutdown(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PM
-	atl1_suspend(pdev, PMSG_SUSPEND);
-#endif
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	atl1_suspend(&pdev->dev);
+	pci_wake_from_d3(pdev, adapter->wol);
+	pci_set_power_state(pdev, PCI_D3hot);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3117,9 +3100,8 @@ static struct pci_driver atl1_driver = {
 	.id_table = atl1_pci_tbl,
 	.probe = atl1_probe,
 	.remove = __devexit_p(atl1_remove),
-	.suspend = atl1_suspend,
-	.resume = atl1_resume,
-	.shutdown = atl1_shutdown
+	.shutdown = atl1_shutdown,
+	.driver.pm = ATL1_PM_OPS,
 };
 
 /*
@@ -3409,6 +3391,9 @@ static int atl1_set_wol(struct net_device *netdev,
 	adapter->wol = 0;
 	if (wol->wolopts & WAKE_MAGIC)
 		adapter->wol |= ATLX_WUFC_MAG;
+
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
 	return 0;
 }
 
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 4e6f4e9..e637e9f 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -93,8 +93,8 @@ static int __devinit atl2_sw_init(struct atl2_adapter *adapter)
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_id = pdev->subsystem_device;
+	hw->revision_id  = pdev->revision;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
 	adapter->wol = 0;
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 4bebff3..e7cb8c8 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -9,7 +9,7 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
-*/
+ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -17,46 +17,45 @@
 #include <linux/isapnp.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
-#include <linux/mii.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/phy.h>
 #include <linux/eeprom_93cx6.h>
 #include <linux/slab.h>
 
 #include <net/ax88796.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
-
-static int phy_debug = 0;
 
 /* Rename the lib8390.c functions to show that they are in this driver */
-#define __ei_open       ax_ei_open
-#define __ei_close      ax_ei_close
-#define __ei_poll	ax_ei_poll
+#define __ei_open ax_ei_open
+#define __ei_close ax_ei_close
+#define __ei_poll ax_ei_poll
 #define __ei_start_xmit ax_ei_start_xmit
 #define __ei_tx_timeout ax_ei_tx_timeout
-#define __ei_get_stats  ax_ei_get_stats
+#define __ei_get_stats ax_ei_get_stats
 #define __ei_set_multicast_list ax_ei_set_multicast_list
-#define __ei_interrupt  ax_ei_interrupt
+#define __ei_interrupt ax_ei_interrupt
 #define ____alloc_ei_netdev ax__alloc_ei_netdev
-#define __NS8390_init   ax_NS8390_init
+#define __NS8390_init ax_NS8390_init
 
 /* force unsigned long back to 'void __iomem *' */
 #define ax_convert_addr(_a) ((void __force __iomem *)(_a))
 
-#define ei_inb(_a)	readb(ax_convert_addr(_a))
+#define ei_inb(_a) readb(ax_convert_addr(_a))
 #define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
 
-#define ei_inb_p(_a)	ei_inb(_a)
+#define ei_inb_p(_a) ei_inb(_a)
 #define ei_outb_p(_v, _a) ei_outb(_v, _a)
 
 /* define EI_SHIFT() to take into account our register offsets */
-#define EI_SHIFT(x)     (ei_local->reg_offset[(x)])
+#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
 
 /* Ensure we have our RCR base value */
 #define AX88796_PLATFORM
@@ -74,43 +73,46 @@ static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electron
 #define NE_DATAPORT	EI_SHIFT(0x10)
 
 #define NE1SM_START_PG	0x20	/* First page of TX buffer */
-#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
+#define NE1SM_STOP_PG	0x40	/* Last page +1 of RX ring */
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
+#define AX_GPOC_PPDSET	BIT(6)
+
 /* device private data */
 
 struct ax_device {
-	struct timer_list	 mii_timer;
-	spinlock_t		 mii_lock;
-	struct mii_if_info	 mii;
-
-	u32			 msg_enable;
-	void __iomem		*map2;
-	struct platform_device	*dev;
-	struct resource		*mem;
-	struct resource		*mem2;
-	struct ax_plat_data	*plat;
-
-	unsigned char		 running;
-	unsigned char		 resume_open;
-	unsigned int		 irqflags;
-
-	u32			 reg_offsets[0x20];
+	struct mii_bus *mii_bus;
+	struct mdiobb_ctrl bb_ctrl;
+	struct phy_device *phy_dev;
+	void __iomem *addr_memr;
+	u8 reg_memr;
+	int link;
+	int speed;
+	int duplex;
+
+	void __iomem *map2;
+	const struct ax_plat_data *plat;
+
+	unsigned char running;
+	unsigned char resume_open;
+	unsigned int irqflags;
+
+	u32 reg_offsets[0x20];
 };
 
 static inline struct ax_device *to_ax_dev(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	return (struct ax_device *)(ei_local+1);
+	return (struct ax_device *)(ei_local + 1);
 }
 
-/* ax_initial_check
+/*
+ * ax_initial_check
  *
  * do an initial probe for the card to check wether it exists
  * and is functional
  */
-
 static int ax_initial_check(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
@@ -122,10 +124,10 @@ static int ax_initial_check(struct net_device *dev)
 	if (reg0 == 0xFF)
 		return -ENODEV;
 
-	ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+	ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
 	regd = ei_inb(ioaddr + 0x0d);
 	ei_outb(0xff, ioaddr + 0x0d);
-	ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+	ei_outb(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
 	ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
 	if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
 		ei_outb(reg0, ioaddr);
@@ -136,29 +138,28 @@ static int ax_initial_check(struct net_device *dev)
 	return 0;
 }
 
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-
+/*
+ * Hard reset the card. This used to pause for the same period that a
+ * 8390 reset command required, but that shouldn't be necessary.
+ */
 static void ax_reset_8390(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	unsigned long reset_start_time = jiffies;
 	void __iomem *addr = (void __iomem *)dev->base_addr;
 
 	if (ei_debug > 1)
-		dev_dbg(&ax->dev->dev, "resetting the 8390 t=%ld\n", jiffies);
+		netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
 
 	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
 
-	ei_status.txing = 0;
-	ei_status.dmaing = 0;
+	ei_local->txing = 0;
+	ei_local->dmaing = 0;
 
 	/* This check _should_not_ be necessary, omit eventually. */
 	while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
-		if (jiffies - reset_start_time > 2*HZ/100) {
-			dev_warn(&ax->dev->dev, "%s: %s did not complete.\n",
-			       __func__, dev->name);
+		if (jiffies - reset_start_time > 2 * HZ / 100) {
+			netdev_warn(dev, "%s: did not complete.\n", __func__);
 			break;
 		}
 	}
@@ -171,70 +172,72 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 			    int ring_page)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	void __iomem *nic_base = ei_local->mem;
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing) {
-		dev_err(&ax->dev->dev, "%s: DMAing conflict in %s "
+	if (ei_local->dmaing) {
+		netdev_err(dev, "DMAing conflict in %s "
 			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, __func__,
-			ei_status.dmaing, ei_status.irqlock);
+			__func__,
+			ei_local->dmaing, ei_local->irqlock);
 		return;
 	}
 
-	ei_status.dmaing |= 0x01;
-	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_local->dmaing |= 0x01;
+	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
 	ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
 	ei_outb(0, nic_base + EN0_RCNTHI);
 	ei_outb(0, nic_base + EN0_RSARLO);		/* On page boundary */
 	ei_outb(ring_page, nic_base + EN0_RSARHI);
 	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-	if (ei_status.word16)
-		readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	if (ei_local->word16)
+		readsw(nic_base + NE_DATAPORT, hdr,
+		       sizeof(struct e8390_pkt_hdr) >> 1);
 	else
-		readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+		readsb(nic_base + NE_DATAPORT, hdr,
+		       sizeof(struct e8390_pkt_hdr));
 
 	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
+	ei_local->dmaing &= ~0x01;
 
 	le16_to_cpus(&hdr->count);
 }
 
 
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using ei_outb. */
-
+/*
+ * Block input and output, similar to the Crynwr packet driver. If
+ * you are porting to a new ethercard, look at the packet driver
+ * source for hints. The NEx000 doesn't share the on-board packet
+ * memory -- you have to put the packet out through the "remote DMA"
+ * dataport using ei_outb.
+ */
 static void ax_block_input(struct net_device *dev, int count,
 			   struct sk_buff *skb, int ring_offset)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	void __iomem *nic_base = ei_local->mem;
 	char *buf = skb->data;
 
-	if (ei_status.dmaing) {
-		dev_err(&ax->dev->dev,
-			"%s: DMAing conflict in %s "
+	if (ei_local->dmaing) {
+		netdev_err(dev,
+			"DMAing conflict in %s "
 			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, __func__,
-			ei_status.dmaing, ei_status.irqlock);
+			__func__,
+			ei_local->dmaing, ei_local->irqlock);
 		return;
 	}
 
-	ei_status.dmaing |= 0x01;
+	ei_local->dmaing |= 0x01;
 
-	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + NE_CMD);
 	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
 	ei_outb(count >> 8, nic_base + EN0_RCNTHI);
 	ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
 	ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
 	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-	if (ei_status.word16) {
+	if (ei_local->word16) {
 		readsw(nic_base + NE_DATAPORT, buf, count >> 1);
 		if (count & 0x01)
 			buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
@@ -243,34 +246,34 @@ static void ax_block_input(struct net_device *dev, int count,
 		readsb(nic_base + NE_DATAPORT, buf, count);
 	}
 
-	ei_status.dmaing &= ~1;
+	ei_local->dmaing &= ~1;
 }
 
 static void ax_block_output(struct net_device *dev, int count,
 			    const unsigned char *buf, const int start_page)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	void __iomem *nic_base = ei_local->mem;
 	unsigned long dma_start;
 
-	/* Round the count up for word writes.  Do we need to do this?
-	   What effect will an odd byte count have on the 8390?
-	   I should check someday. */
-
-	if (ei_status.word16 && (count & 0x01))
+	/*
+	 * Round the count up for word writes. Do we need to do this?
+	 * What effect will an odd byte count have on the 8390?  I
+	 * should check someday.
+	 */
+	if (ei_local->word16 && (count & 0x01))
 		count++;
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing) {
-		dev_err(&ax->dev->dev, "%s: DMAing conflict in %s."
+	if (ei_local->dmaing) {
+		netdev_err(dev, "DMAing conflict in %s."
 			"[DMAstat:%d][irqlock:%d]\n",
-			dev->name, __func__,
-		       ei_status.dmaing, ei_status.irqlock);
+			__func__,
+		       ei_local->dmaing, ei_local->irqlock);
 		return;
 	}
 
-	ei_status.dmaing |= 0x01;
+	ei_local->dmaing |= 0x01;
 	/* We should already be in page 0, but to be safe... */
 	ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
 
@@ -278,250 +281,170 @@ static void ax_block_output(struct net_device *dev, int count,
 
 	/* Now the normal output. */
 	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
-	ei_outb(count >> 8,   nic_base + EN0_RCNTHI);
+	ei_outb(count >> 8, nic_base + EN0_RCNTHI);
 	ei_outb(0x00, nic_base + EN0_RSARLO);
 	ei_outb(start_page, nic_base + EN0_RSARHI);
 
 	ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-	if (ei_status.word16) {
-		writesw(nic_base + NE_DATAPORT, buf, count>>1);
-	} else {
+	if (ei_local->word16)
+		writesw(nic_base + NE_DATAPORT, buf, count >> 1);
+	else
 		writesb(nic_base + NE_DATAPORT, buf, count);
-	}
 
 	dma_start = jiffies;
 
 	while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
-		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
-			dev_warn(&ax->dev->dev,
-				 "%s: timeout waiting for Tx RDC.\n", dev->name);
+		if (jiffies - dma_start > 2 * HZ / 100) {		/* 20ms */
+			netdev_warn(dev, "timeout waiting for Tx RDC.\n");
 			ax_reset_8390(dev);
-			ax_NS8390_init(dev,1);
+			ax_NS8390_init(dev, 1);
 			break;
 		}
 	}
 
 	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
+	ei_local->dmaing &= ~0x01;
 }
 
 /* definitions for accessing MII/EEPROM interface */
 
 #define AX_MEMR			EI_SHIFT(0x14)
-#define AX_MEMR_MDC		(1<<0)
-#define AX_MEMR_MDIR		(1<<1)
-#define AX_MEMR_MDI		(1<<2)
-#define AX_MEMR_MDO		(1<<3)
-#define AX_MEMR_EECS		(1<<4)
-#define AX_MEMR_EEI		(1<<5)
-#define AX_MEMR_EEO		(1<<6)
-#define AX_MEMR_EECLK		(1<<7)
-
-/* ax_mii_ei_outbits
- *
- * write the specified set of bits to the phy
-*/
-
-static void
-ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
+#define AX_MEMR_MDC		BIT(0)
+#define AX_MEMR_MDIR		BIT(1)
+#define AX_MEMR_MDI		BIT(2)
+#define AX_MEMR_MDO		BIT(3)
+#define AX_MEMR_EECS		BIT(4)
+#define AX_MEMR_EEI		BIT(5)
+#define AX_MEMR_EEO		BIT(6)
+#define AX_MEMR_EECLK		BIT(7)
+
+static void ax_handle_link_change(struct net_device *dev)
 {
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
-	unsigned int memr;
-
-	/* clock low, data to output mode */
-	memr = ei_inb(memr_addr);
-	memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
-	ei_outb(memr, memr_addr);
-
-	for (len--; len >= 0; len--) {
-		if (bits & (1 << len))
-			memr |= AX_MEMR_MDO;
-		else
-			memr &= ~AX_MEMR_MDO;
-
-		ei_outb(memr, memr_addr);
-
-		/* clock high */
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = ax->phy_dev;
+	int status_change = 0;
 
-		ei_outb(memr | AX_MEMR_MDC, memr_addr);
-		udelay(1);
+	if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
+			     (ax->duplex != phy_dev->duplex))) {
 
-		/* clock low */
-		ei_outb(memr, memr_addr);
+		ax->speed = phy_dev->speed;
+		ax->duplex = phy_dev->duplex;
+		status_change = 1;
 	}
 
-	/* leaves the clock line low, mdir input */
-	memr |= AX_MEMR_MDIR;
-	ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
-}
-
-/* ax_phy_ei_inbits
- *
- * read a specified number of bits from the phy
-*/
-
-static unsigned int
-ax_phy_ei_inbits(struct net_device *dev, int no)
-{
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
-	unsigned int memr;
-	unsigned int result = 0;
-
-	/* clock low, data to input mode */
-	memr = ei_inb(memr_addr);
-	memr &= ~AX_MEMR_MDC;
-	memr |= AX_MEMR_MDIR;
-	ei_outb(memr, memr_addr);
-
-	for (no--; no >= 0; no--) {
-		ei_outb(memr | AX_MEMR_MDC, memr_addr);
-
-		udelay(1);
-
-		if (ei_inb(memr_addr) & AX_MEMR_MDI)
-			result |= (1<<no);
+	if (phy_dev->link != ax->link) {
+		if (!phy_dev->link) {
+			ax->speed = 0;
+			ax->duplex = -1;
+		}
+		ax->link = phy_dev->link;
 
-		ei_outb(memr, memr_addr);
+		status_change = 1;
 	}
 
-	return result;
-}
-
-/* ax_phy_issueaddr
- *
- * use the low level bit shifting routines to send the address
- * and command to the specified phy
-*/
-
-static void
-ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
-{
-	if (phy_debug)
-		pr_debug("%s: dev %p, %04x, %04x, %d\n",
-			__func__, dev, phy_addr, reg, opc);
-
-	ax_mii_ei_outbits(dev, 0x3f, 6);	/* pre-amble */
-	ax_mii_ei_outbits(dev, 1, 2);		/* frame-start */
-	ax_mii_ei_outbits(dev, opc, 2);		/* op code */
-	ax_mii_ei_outbits(dev, phy_addr, 5);	/* phy address */
-	ax_mii_ei_outbits(dev, reg, 5);		/* reg address */
+	if (status_change)
+		phy_print_status(phy_dev);
 }
 
-static int
-ax_phy_read(struct net_device *dev, int phy_addr, int reg)
+static int ax_mii_probe(struct net_device *dev)
 {
-	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned long flags;
- 	unsigned int result;
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = NULL;
+	int ret;
 
-      	spin_lock_irqsave(&ei_local->page_lock, flags);
+	/* find the first phy */
+	phy_dev = phy_find_first(ax->mii_bus);
+	if (!phy_dev) {
+		netdev_err(dev, "no PHY found\n");
+		return -ENODEV;
+	}
 
-	ax_phy_issueaddr(dev, phy_addr, reg, 2);
+	ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0,
+				 PHY_INTERFACE_MODE_MII);
+	if (ret) {
+		netdev_err(dev, "Could not attach to PHY\n");
+		return ret;
+	}
 
-	result = ax_phy_ei_inbits(dev, 17);
-	result &= ~(3<<16);
+	/* mask with MAC supported features */
+	phy_dev->supported &= PHY_BASIC_FEATURES;
+	phy_dev->advertising = phy_dev->supported;
 
-      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
+	ax->phy_dev = phy_dev;
 
-	if (phy_debug)
-		pr_debug("%s: %04x.%04x => read %04x\n", __func__,
-			 phy_addr, reg, result);
+	netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+		    phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq);
 
-	return result;
+	return 0;
 }
 
-static void
-ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
+static void ax_phy_switch(struct net_device *dev, int on)
 {
-	struct ei_device *ei = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
-	unsigned long flags;
-
-	dev_dbg(&ax->dev->dev, "%s: %p, %04x, %04x %04x\n",
-		__func__, dev, phy_addr, reg, value);
-
-      	spin_lock_irqsave(&ei->page_lock, flags);
-
-	ax_phy_issueaddr(dev, phy_addr, reg, 1);
-	ax_mii_ei_outbits(dev, 2, 2);		/* send TA */
-	ax_mii_ei_outbits(dev, value, 16);
-
-      	spin_unlock_irqrestore(&ei->page_lock, flags);
-}
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
 
-static void ax_mii_expiry(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct ax_device  *ax = to_ax_dev(dev);
-	unsigned long flags;
+	u8 reg_gpoc =  ax->plat->gpoc_val;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	mii_check_media(&ax->mii, netif_msg_link(ax), 0);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
+	if (!!on)
+		reg_gpoc &= ~AX_GPOC_PPDSET;
+	else
+		reg_gpoc |= AX_GPOC_PPDSET;
 
-	if (ax->running) {
-		ax->mii_timer.expires = jiffies + HZ*2;
-		add_timer(&ax->mii_timer);
-	}
+	ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
 }
 
 static int ax_open(struct net_device *dev)
 {
-	struct ax_device  *ax = to_ax_dev(dev);
-	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
 	int ret;
 
-	dev_dbg(&ax->dev->dev, "%s: open\n", dev->name);
+	netdev_dbg(dev, "open\n");
 
 	ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
 			  dev->name, dev);
 	if (ret)
-		return ret;
-
-	ret = ax_ei_open(dev);
-	if (ret) {
-		free_irq(dev->irq, dev);
-		return ret;
-	}
+		goto failed_request_irq;
 
 	/* turn the phy on (if turned off) */
+	ax_phy_switch(dev, 1);
 
-	ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
-	ax->running = 1;
-
-	/* start the MII timer */
-
-	init_timer(&ax->mii_timer);
+	ret = ax_mii_probe(dev);
+	if (ret)
+		goto failed_mii_probe;
+	phy_start(ax->phy_dev);
 
-	ax->mii_timer.expires  = jiffies+1;
-	ax->mii_timer.data     = (unsigned long) dev;
-	ax->mii_timer.function = ax_mii_expiry;
+	ret = ax_ei_open(dev);
+	if (ret)
+		goto failed_ax_ei_open;
 
-	add_timer(&ax->mii_timer);
+	ax->running = 1;
 
 	return 0;
+
+ failed_ax_ei_open:
+	phy_disconnect(ax->phy_dev);
+ failed_mii_probe:
+	ax_phy_switch(dev, 0);
+	free_irq(dev->irq, dev);
+ failed_request_irq:
+	return ret;
 }
 
 static int ax_close(struct net_device *dev)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	struct ei_device *ei_local = netdev_priv(dev);
 
-	dev_dbg(&ax->dev->dev, "%s: close\n", dev->name);
-
-	/* turn the phy off */
-
-	ei_outb(ax->plat->gpoc_val | (1<<6),
-	       ei_local->mem + EI_SHIFT(0x17));
+	netdev_dbg(dev, "close\n");
 
 	ax->running = 0;
 	wmb();
 
-	del_timer_sync(&ax->mii_timer);
 	ax_ei_close(dev);
 
+	/* turn the phy off */
+	ax_phy_switch(dev, 0);
+	phy_disconnect(ax->phy_dev);
+
 	free_irq(dev->irq, dev);
 	return 0;
 }
@@ -529,17 +452,15 @@ static int ax_close(struct net_device *dev)
 static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	unsigned long flags;
-	int rc;
+	struct phy_device *phy_dev = ax->phy_dev;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
+	if (!phy_dev)
+		return -ENODEV;
 
-	return rc;
+	return phy_mii_ioctl(phy_dev, req, cmd);
 }
 
 /* ethtool ops */
@@ -547,56 +468,40 @@ static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 static void ax_get_drvinfo(struct net_device *dev,
 			   struct ethtool_drvinfo *info)
 {
-	struct ax_device *ax = to_ax_dev(dev);
+	struct platform_device *pdev = to_platform_device(dev->dev.parent);
 
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, ax->dev->name);
+	strcpy(info->bus_info, pdev->name);
 }
 
 static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	unsigned long flags;
+	struct phy_device *phy_dev = ax->phy_dev;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	mii_ethtool_gset(&ax->mii, cmd);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
+	if (!phy_dev)
+		return -ENODEV;
 
-	return 0;
+	return phy_ethtool_gset(phy_dev, cmd);
 }
 
 static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	unsigned long flags;
-	int rc;
+	struct phy_device *phy_dev = ax->phy_dev;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	rc = mii_ethtool_sset(&ax->mii, cmd);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
-
-	return rc;
-}
-
-static int ax_nway_reset(struct net_device *dev)
-{
-	struct ax_device *ax = to_ax_dev(dev);
-	return mii_nway_restart(&ax->mii);
-}
+	if (!phy_dev)
+		return -ENODEV;
 
-static u32 ax_get_link(struct net_device *dev)
-{
-	struct ax_device *ax = to_ax_dev(dev);
-	return mii_link_ok(&ax->mii);
+	return phy_ethtool_sset(phy_dev, cmd);
 }
 
 static const struct ethtool_ops ax_ethtool_ops = {
 	.get_drvinfo		= ax_get_drvinfo,
 	.get_settings		= ax_get_settings,
 	.set_settings		= ax_set_settings,
-	.nway_reset		= ax_nway_reset,
-	.get_link		= ax_get_link,
+	.get_link		= ethtool_op_get_link,
 };
 
 #ifdef CONFIG_AX88796_93CX6
@@ -640,37 +545,131 @@ static const struct net_device_ops ax_netdev_ops = {
 	.ndo_get_stats		= ax_ei_get_stats,
 	.ndo_set_multicast_list = ax_ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ax_ei_poll,
 #endif
 };
 
+static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+	if (level)
+		ax->reg_memr |= AX_MEMR_MDC;
+	else
+		ax->reg_memr &= ~AX_MEMR_MDC;
+
+	ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+	if (output)
+		ax->reg_memr &= ~AX_MEMR_MDIR;
+	else
+		ax->reg_memr |= AX_MEMR_MDIR;
+
+	ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+	if (value)
+		ax->reg_memr |= AX_MEMR_MDO;
+	else
+		ax->reg_memr &= ~AX_MEMR_MDO;
+
+	ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+	int reg_memr = ei_inb(ax->addr_memr);
+
+	return reg_memr & AX_MEMR_MDI ? 1 : 0;
+}
+
+static struct mdiobb_ops bb_ops = {
+	.owner = THIS_MODULE,
+	.set_mdc = ax_bb_mdc,
+	.set_mdio_dir = ax_bb_dir,
+	.set_mdio_data = ax_bb_set_data,
+	.get_mdio_data = ax_bb_get_data,
+};
+
 /* setup code */
 
+static int ax_mii_init(struct net_device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev->dev.parent);
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	int err, i;
+
+	ax->bb_ctrl.ops = &bb_ops;
+	ax->addr_memr = ei_local->mem + AX_MEMR;
+	ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
+	if (!ax->mii_bus) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	ax->mii_bus->name = "ax88796_mii_bus";
+	ax->mii_bus->parent = dev->dev.parent;
+	snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+	ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!ax->mii_bus->irq) {
+		err = -ENOMEM;
+		goto out_free_mdio_bitbang;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		ax->mii_bus->irq[i] = PHY_POLL;
+
+	err = mdiobus_register(ax->mii_bus);
+	if (err)
+		goto out_free_irq;
+
+	return 0;
+
+ out_free_irq:
+	kfree(ax->mii_bus->irq);
+ out_free_mdio_bitbang:
+	free_mdio_bitbang(ax->mii_bus);
+ out:
+	return err;
+}
+
 static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
 {
 	void __iomem *ioaddr = ei_local->mem;
 	struct ax_device *ax = to_ax_dev(dev);
 
-	/* Select page 0*/
-	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);
+	/* Select page 0 */
+	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);
 
 	/* set to byte access */
 	ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
 	ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
 }
 
-/* ax_init_dev
+/*
+ * ax_init_dev
  *
  * initialise the specified device, taking care to note the MAC
  * address it may already have (if configured), ensure
  * the device is ready to be used by lib8390.c and registerd with
  * the network layer.
  */
-
-static int ax_init_dev(struct net_device *dev, int first_init)
+static int ax_init_dev(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
 	struct ax_device *ax = to_ax_dev(dev);
@@ -690,23 +689,23 @@ static int ax_init_dev(struct net_device *dev, int first_init)
 
 	/* read the mac from the card prom if we need it */
 
-	if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {
+	if (ax->plat->flags & AXFLG_HAS_EEPROM) {
 		unsigned char SA_prom[32];
 
-		for(i = 0; i < sizeof(SA_prom); i+=2) {
+		for (i = 0; i < sizeof(SA_prom); i += 2) {
 			SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
-			SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);
+			SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
 		}
 
 		if (ax->plat->wordlength == 2)
 			for (i = 0; i < 16; i++)
 				SA_prom[i] = SA_prom[i+i];
 
-		memcpy(dev->dev_addr,  SA_prom, 6);
+		memcpy(dev->dev_addr, SA_prom, 6);
 	}
 
 #ifdef CONFIG_AX88796_93CX6
-	if (first_init && ax->plat->flags & AXFLG_HAS_93CX6) {
+	if (ax->plat->flags & AXFLG_HAS_93CX6) {
 		unsigned char mac_addr[6];
 		struct eeprom_93cx6 eeprom;
 
@@ -719,7 +718,7 @@ static int ax_init_dev(struct net_device *dev, int first_init)
 				       (__le16 __force *)mac_addr,
 				       sizeof(mac_addr) >> 1);
 
-		memcpy(dev->dev_addr,  mac_addr, 6);
+		memcpy(dev->dev_addr, mac_addr, 6);
 	}
 #endif
 	if (ax->plat->wordlength == 2) {
@@ -732,67 +731,56 @@ static int ax_init_dev(struct net_device *dev, int first_init)
 		stop_page = NE1SM_STOP_PG;
 	}
 
-	/* load the mac-address from the device if this is the
-	 * first time we've initialised */
-
-	if (first_init) {
-		if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
-			ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
-				ei_local->mem + E8390_CMD); /* 0x61 */
-			for (i = 0; i < ETHER_ADDR_LEN; i++)
-				dev->dev_addr[i] =
-					ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
-		}
-
-		if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
-		     ax->plat->mac_addr)
-			memcpy(dev->dev_addr, ax->plat->mac_addr,
-				ETHER_ADDR_LEN);
+	/* load the mac-address from the device */
+	if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
+		ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+			ei_local->mem + E8390_CMD); /* 0x61 */
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
+			dev->dev_addr[i] =
+				ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
 	}
 
+	if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
+	    ax->plat->mac_addr)
+		memcpy(dev->dev_addr, ax->plat->mac_addr,
+		       ETHER_ADDR_LEN);
+
 	ax_reset_8390(dev);
 
-	ei_status.name = "AX88796";
-	ei_status.tx_start_page = start_page;
-	ei_status.stop_page = stop_page;
-	ei_status.word16 = (ax->plat->wordlength == 2);
-	ei_status.rx_start_page = start_page + TX_PAGES;
+	ei_local->name = "AX88796";
+	ei_local->tx_start_page = start_page;
+	ei_local->stop_page = stop_page;
+	ei_local->word16 = (ax->plat->wordlength == 2);
+	ei_local->rx_start_page = start_page + TX_PAGES;
 
 #ifdef PACKETBUF_MEMSIZE
-	 /* Allow the packet buffer size to be overridden by know-it-alls. */
-	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+	/* Allow the packet buffer size to be overridden by know-it-alls. */
+	ei_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
 #endif
 
-	ei_status.reset_8390	= &ax_reset_8390;
-	ei_status.block_input	= &ax_block_input;
-	ei_status.block_output	= &ax_block_output;
-	ei_status.get_8390_hdr	= &ax_get_8390_hdr;
-	ei_status.priv = 0;
-
-	dev->netdev_ops		= &ax_netdev_ops;
-	dev->ethtool_ops	= &ax_ethtool_ops;
-
-	ax->msg_enable		= NETIF_MSG_LINK;
-	ax->mii.phy_id_mask	= 0x1f;
-	ax->mii.reg_num_mask	= 0x1f;
-	ax->mii.phy_id		= 0x10;		/* onboard phy */
-	ax->mii.force_media	= 0;
-	ax->mii.full_duplex	= 0;
-	ax->mii.mdio_read	= ax_phy_read;
-	ax->mii.mdio_write	= ax_phy_write;
-	ax->mii.dev		= dev;
+	ei_local->reset_8390 = &ax_reset_8390;
+	ei_local->block_input = &ax_block_input;
+	ei_local->block_output = &ax_block_output;
+	ei_local->get_8390_hdr = &ax_get_8390_hdr;
+	ei_local->priv = 0;
 
-	ax_NS8390_init(dev, 0);
+	dev->netdev_ops = &ax_netdev_ops;
+	dev->ethtool_ops = &ax_ethtool_ops;
 
-	if (first_init)
-		dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %pM\n",
-			 ei_status.word16 ? 16:8, dev->irq, dev->base_addr,
-			 dev->dev_addr);
+	ret = ax_mii_init(dev);
+	if (ret)
+		goto out_irq;
+
+	ax_NS8390_init(dev, 0);
 
 	ret = register_netdev(dev);
 	if (ret)
 		goto out_irq;
 
+	netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
+		    ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
+		    dev->dev_addr);
+
 	return 0;
 
  out_irq:
@@ -802,24 +790,24 @@ static int ax_init_dev(struct net_device *dev, int first_init)
 	return ret;
 }
 
-static int ax_remove(struct platform_device *_dev)
+static int ax_remove(struct platform_device *pdev)
 {
-	struct net_device *dev = platform_get_drvdata(_dev);
-	struct ax_device  *ax;
-
-	ax = to_ax_dev(dev);
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	struct resource *mem;
 
 	unregister_netdev(dev);
 	free_irq(dev->irq, dev);
 
-	iounmap(ei_status.mem);
-	release_resource(ax->mem);
-	kfree(ax->mem);
+	iounmap(ei_local->mem);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
 
 	if (ax->map2) {
 		iounmap(ax->map2);
-		release_resource(ax->mem2);
-		kfree(ax->mem2);
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		release_mem_region(mem->start, resource_size(mem));
 	}
 
 	free_netdev(dev);
@@ -827,19 +815,20 @@ static int ax_remove(struct platform_device *_dev)
 	return 0;
 }
 
-/* ax_probe
+/*
+ * ax_probe
  *
  * This is the entry point when the platform device system uses to
- * notify us of a new device to attach to. Allocate memory, find
- * the resources and information passed, and map the necessary registers.
-*/
-
+ * notify us of a new device to attach to. Allocate memory, find the
+ * resources and information passed, and map the necessary registers.
+ */
 static int ax_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
-	struct ax_device  *ax;
-	struct resource   *res;
-	size_t size;
+	struct ei_device *ei_local;
+	struct ax_device *ax;
+	struct resource *irq, *mem, *mem2;
+	resource_size_t mem_size, mem2_size = 0;
 	int ret = 0;
 
 	dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
@@ -847,120 +836,107 @@ static int ax_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	/* ok, let's setup our device */
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	ei_local = netdev_priv(dev);
 	ax = to_ax_dev(dev);
 
-	memset(ax, 0, sizeof(struct ax_device));
-
-	spin_lock_init(&ax->mii_lock);
-
-	ax->dev = pdev;
 	ax->plat = pdev->dev.platform_data;
 	platform_set_drvdata(pdev, dev);
 
-	ei_status.rxcr_base  = ax->plat->rcr_val;
+	ei_local->rxcr_base = ax->plat->rcr_val;
 
 	/* find the platform resources */
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res == NULL) {
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
 		dev_err(&pdev->dev, "no IRQ specified\n");
 		ret = -ENXIO;
 		goto exit_mem;
 	}
 
-	dev->irq = res->start;
-	ax->irqflags = res->flags & IRQF_TRIGGER_MASK;
+	dev->irq = irq->start;
+	ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
 		dev_err(&pdev->dev, "no MEM specified\n");
 		ret = -ENXIO;
 		goto exit_mem;
 	}
 
-	size = (res->end - res->start) + 1;
-
-	/* setup the register offsets from either the platform data
-	 * or by using the size of the resource provided */
+	mem_size = resource_size(mem);
 
+	/*
+	 * setup the register offsets from either the platform data or
+	 * by using the size of the resource provided
+	 */
 	if (ax->plat->reg_offsets)
-		ei_status.reg_offset = ax->plat->reg_offsets;
+		ei_local->reg_offset = ax->plat->reg_offsets;
 	else {
-		ei_status.reg_offset = ax->reg_offsets;
+		ei_local->reg_offset = ax->reg_offsets;
 		for (ret = 0; ret < 0x18; ret++)
-			ax->reg_offsets[ret] = (size / 0x18) * ret;
+			ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
 	}
 
-	ax->mem = request_mem_region(res->start, size, pdev->name);
-	if (ax->mem == NULL) {
+	if (!request_mem_region(mem->start, mem_size, pdev->name)) {
 		dev_err(&pdev->dev, "cannot reserve registers\n");
- 		ret = -ENXIO;
+		ret = -ENXIO;
 		goto exit_mem;
 	}
 
-	ei_status.mem = ioremap(res->start, size);
-	dev->base_addr = (unsigned long)ei_status.mem;
+	ei_local->mem = ioremap(mem->start, mem_size);
+	dev->base_addr = (unsigned long)ei_local->mem;
 
-	if (ei_status.mem == NULL) {
-		dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n",
-			(unsigned long long)res->start,
-			(unsigned long long)res->end);
+	if (ei_local->mem == NULL) {
+		dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
 
- 		ret = -ENXIO;
+		ret = -ENXIO;
 		goto exit_req;
 	}
 
 	/* look for reset area */
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (res == NULL) {
+	mem2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mem2) {
 		if (!ax->plat->reg_offsets) {
 			for (ret = 0; ret < 0x20; ret++)
-				ax->reg_offsets[ret] = (size / 0x20) * ret;
+				ax->reg_offsets[ret] = (mem_size / 0x20) * ret;
 		}
-
-		ax->map2 = NULL;
 	} else {
- 		size = (res->end - res->start) + 1;
+		mem2_size = resource_size(mem2);
 
-		ax->mem2 = request_mem_region(res->start, size, pdev->name);
-		if (ax->mem2 == NULL) {
+		if (!request_mem_region(mem2->start, mem2_size, pdev->name)) {
 			dev_err(&pdev->dev, "cannot reserve registers\n");
 			ret = -ENXIO;
 			goto exit_mem1;
 		}
 
-		ax->map2 = ioremap(res->start, size);
-		if (ax->map2 == NULL) {
+		ax->map2 = ioremap(mem2->start, mem2_size);
+		if (!ax->map2) {
 			dev_err(&pdev->dev, "cannot map reset register\n");
 			ret = -ENXIO;
 			goto exit_mem2;
 		}
 
-		ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
+		ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
 	}
 
 	/* got resources, now initialise and register device */
-
-	ret = ax_init_dev(dev, 1);
+	ret = ax_init_dev(dev);
 	if (!ret)
 		return 0;
 
-	if (ax->map2 == NULL)
+	if (!ax->map2)
 		goto exit_mem1;
 
 	iounmap(ax->map2);
 
  exit_mem2:
-	release_resource(ax->mem2);
-	kfree(ax->mem2);
+	release_mem_region(mem2->start, mem2_size);
 
  exit_mem1:
-	iounmap(ei_status.mem);
+	iounmap(ei_local->mem);
 
  exit_req:
-	release_resource(ax->mem);
-	kfree(ax->mem);
+	release_mem_region(mem->start, mem_size);
 
  exit_mem:
 	free_netdev(dev);
@@ -974,7 +950,7 @@ static int ax_probe(struct platform_device *pdev)
 static int ax_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct net_device *ndev = platform_get_drvdata(dev);
-	struct ax_device  *ax = to_ax_dev(ndev);
+	struct ax_device *ax = to_ax_dev(ndev);
 
 	ax->resume_open = ax->running;
 
@@ -987,7 +963,7 @@ static int ax_suspend(struct platform_device *dev, pm_message_t state)
 static int ax_resume(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ax_device  *ax = to_ax_dev(ndev);
+	struct ax_device *ax = to_ax_dev(ndev);
 
 	ax_initial_setup(ndev, netdev_priv(ndev));
 	ax_NS8390_init(ndev, ax->resume_open);
@@ -1001,7 +977,7 @@ static int ax_resume(struct platform_device *pdev)
 
 #else
 #define ax_suspend NULL
-#define ax_resume  NULL
+#define ax_resume NULL
 #endif
 
 static struct platform_driver axdrv = {
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index add0b93..f803c58 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #ifndef BE_H
@@ -33,7 +33,7 @@
 
 #include "be_hw.h"
 
-#define DRV_VER			"2.103.175u"
+#define DRV_VER			"4.0.100u"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
@@ -67,7 +67,7 @@ static inline char *nic_name(struct pci_dev *pdev)
 }
 
 /* Number of bytes of an RX frame that are copied to skb->data */
-#define BE_HDR_LEN 		64
+#define BE_HDR_LEN		((u16) 64)
 #define BE_MAX_JUMBO_FRAME_SIZE	9018
 #define BE_MIN_MTU		256
 
@@ -211,18 +211,40 @@ struct be_rx_stats {
 	u32 rx_fps;		/* Rx frags per second */
 };
 
+struct be_rx_compl_info {
+	u32 rss_hash;
+	u16 vid;
+	u16 pkt_size;
+	u16 rxq_idx;
+	u16 mac_id;
+	u8 vlanf;
+	u8 num_rcvd;
+	u8 err;
+	u8 ipf;
+	u8 tcpf;
+	u8 udpf;
+	u8 ip_csum;
+	u8 l4_csum;
+	u8 ipv6;
+	u8 vtm;
+	u8 pkt_type;
+};
+
 struct be_rx_obj {
 	struct be_adapter *adapter;
 	struct be_queue_info q;
 	struct be_queue_info cq;
+	struct be_rx_compl_info rxcp;
 	struct be_rx_page_info page_info_tbl[RX_Q_LEN];
 	struct be_eq_obj rx_eq;
 	struct be_rx_stats stats;
 	u8 rss_id;
 	bool rx_post_starved;	/* Zero rx frags have been posted to BE */
-	u16 last_frag_index;
-	u16 rsvd;
-	u32 cache_line_barrier[15];
+	u32 cache_line_barrier[16];
+};
+
+struct be_drv_stats {
+	u8 be_on_die_temperature;
 };
 
 struct be_vf_cfg {
@@ -234,6 +256,7 @@ struct be_vf_cfg {
 };
 
 #define BE_INVALID_PMAC_ID		0xffffffff
+
 struct be_adapter {
 	struct pci_dev *pdev;
 	struct net_device *netdev;
@@ -269,6 +292,7 @@ struct be_adapter {
 	u32 big_page_size;	/* Compounded page size shared by rx wrbs */
 
 	u8 msix_vec_next_idx;
+	struct be_drv_stats drv_stats;
 
 	struct vlan_group *vlan_grp;
 	u16 vlans_added;
@@ -281,6 +305,7 @@ struct be_adapter {
 	struct be_dma_mem stats_cmd;
 	/* Work queue used to perform periodic tasks like getting statistics */
 	struct delayed_work work;
+	u16 work_counter;
 
 	/* Ethtool knobs and info */
 	bool rx_csum; 		/* BE card must perform rx-checksumming */
@@ -298,7 +323,7 @@ struct be_adapter {
 	u32 rx_fc;		/* Rx flow control */
 	u32 tx_fc;		/* Tx flow control */
 	bool ue_detected;
-	bool stats_ioctl_sent;
+	bool stats_cmd_sent;
 	int link_speed;
 	u8 port_type;
 	u8 transceiver;
@@ -307,10 +332,13 @@ struct be_adapter {
 	u32 flash_status;
 	struct completion flash_compl;
 
+	bool be3_native;
 	bool sriov_enabled;
 	struct be_vf_cfg vf_cfg[BE_MAX_VF];
 	u8 is_virtfn;
 	u32 sli_family;
+	u8 hba_port_num;
+	u16 pvid;
 };
 
 #define be_physfn(adapter) (!adapter->is_virtfn)
@@ -450,9 +478,8 @@ static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac)
 	mac[5] = (u8)(addr & 0xFF);
 	mac[4] = (u8)((addr >> 8) & 0xFF);
 	mac[3] = (u8)((addr >> 16) & 0xFF);
-	mac[2] = 0xC9;
-	mac[1] = 0x00;
-	mac[0] = 0x00;
+	/* Use the OUI from the current MAC address */
+	memcpy(mac, adapter->netdev->dev_addr, 3);
 }
 
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index a179cc6..5a4a87e 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,21 +8,30 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #include "be.h"
 #include "be_cmds.h"
 
+/* Must be a power of 2 or else MODULO will BUG_ON */
+static int be_get_temp_freq = 32;
+
 static void be_mcc_notify(struct be_adapter *adapter)
 {
 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	u32 val = 0;
 
+	if (adapter->eeh_err) {
+		dev_info(&adapter->pdev->dev,
+			"Error in Card Detected! Cannot issue commands\n");
+		return;
+	}
+
 	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
 	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
 
@@ -75,7 +84,7 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
 			be_dws_le_to_cpu(&resp->hw_stats,
 						sizeof(resp->hw_stats));
 			netdev_stats_update(adapter);
-			adapter->stats_ioctl_sent = false;
+			adapter->stats_cmd_sent = false;
 		}
 	} else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) &&
 		   (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) {
@@ -102,6 +111,7 @@ static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
 {
 	if (evt->valid) {
 		adapter->vlan_prio_bmap = evt->available_priority_bmap;
+		adapter->recommended_prio &= ~VLAN_PRIO_MASK;
 		adapter->recommended_prio =
 			evt->reco_default_priority << VLAN_PRIO_SHIFT;
 	}
@@ -117,6 +127,16 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
 	}
 }
 
+/*Grp5 PVID evt*/
+static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
+		struct be_async_event_grp5_pvid_state *evt)
+{
+	if (evt->enabled)
+		adapter->pvid = evt->tag;
+	else
+		adapter->pvid = 0;
+}
+
 static void be_async_grp5_evt_process(struct be_adapter *adapter,
 		u32 trailer, struct be_mcc_compl *evt)
 {
@@ -134,6 +154,10 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter,
 		be_async_grp5_qos_speed_process(adapter,
 		(struct be_async_event_grp5_qos_link_speed *)evt);
 	break;
+	case ASYNC_EVENT_PVID_STATE:
+		be_async_grp5_pvid_state_process(adapter,
+		(struct be_async_event_grp5_pvid_state *)evt);
+	break;
 	default:
 		dev_warn(&adapter->pdev->dev, "Unknown grp5 event!\n");
 		break;
@@ -216,6 +240,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
 	int i, num, status = 0;
 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
+	if (adapter->eeh_err)
+		return -EIO;
+
 	for (i = 0; i < mcc_timeout; i++) {
 		num = be_process_mcc(adapter, &status);
 		if (num)
@@ -245,6 +272,12 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
 	int msecs = 0;
 	u32 ready;
 
+	if (adapter->eeh_err) {
+		dev_err(&adapter->pdev->dev,
+			"Error detected in card.Cannot issue commands\n");
+		return -EIO;
+	}
+
 	do {
 		ready = ioread32(db);
 		if (ready == 0xffffffff) {
@@ -598,7 +631,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
 
 /* Uses synchronous MCCQ */
 int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
-		u32 if_id, u32 *pmac_id)
+		u32 if_id, u32 *pmac_id, u32 domain)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_pmac_add *req;
@@ -619,6 +652,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req));
 
+	req->hdr.domain = domain;
 	req->if_id = cpu_to_le32(if_id);
 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
 
@@ -634,7 +668,7 @@ err:
 }
 
 /* Uses synchronous MCCQ */
-int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
+int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id, u32 dom)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_pmac_del *req;
@@ -655,6 +689,7 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req));
 
+	req->hdr.domain = dom;
 	req->if_id = cpu_to_le32(if_id);
 	req->pmac_id = cpu_to_le32(pmac_id);
 
@@ -691,7 +726,7 @@ int be_cmd_cq_create(struct be_adapter *adapter,
 
 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
 	if (lancer_chip(adapter)) {
-		req->hdr.version = 1;
+		req->hdr.version = 2;
 		req->page_size = 1; /* 1 for 4K */
 		AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt,
 								coalesce_wm);
@@ -827,6 +862,12 @@ int be_cmd_txq_create(struct be_adapter *adapter,
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE,
 		sizeof(*req));
 
+	if (lancer_chip(adapter)) {
+		req->hdr.version = 1;
+		AMAP_SET_BITS(struct amap_tx_context, if_id, ctxt,
+					adapter->if_handle);
+	}
+
 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
 	req->ulp_num = BE_ULP1_NUM;
 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
@@ -995,7 +1036,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
 }
 
 /* Uses mbox */
-int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
+int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_if_destroy *req;
@@ -1016,6 +1057,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
 
+	req->hdr.domain = domain;
 	req->interface_id = cpu_to_le32(interface_id);
 
 	status = be_mbox_notify_wait(adapter);
@@ -1036,6 +1078,9 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 	struct be_sge *sge;
 	int status = 0;
 
+	if (MODULO(adapter->work_counter, be_get_temp_freq) == 0)
+		be_cmd_get_die_temperature(adapter);
+
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
@@ -1056,7 +1101,7 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
 	sge->len = cpu_to_le32(nonemb_cmd->size);
 
 	be_mcc_notify(adapter);
-	adapter->stats_ioctl_sent = true;
+	adapter->stats_cmd_sent = true;
 
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
@@ -1103,6 +1148,44 @@ err:
 	return status;
 }
 
+/* Uses synchronous mcc */
+int be_cmd_get_die_temperature(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_cntl_addnl_attribs *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req));
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_get_cntl_addnl_attribs *resp =
+						embedded_payload(wrb);
+		adapter->drv_stats.be_on_die_temperature =
+						resp->on_die_temperature;
+	}
+	/* If IOCTL fails once, do not bother issuing it again */
+	else
+		be_get_temp_freq = 0;
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
 /* Uses Mbox */
 int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
 {
@@ -1868,8 +1951,8 @@ int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain)
 			OPCODE_COMMON_SET_QOS, sizeof(*req));
 
 	req->hdr.domain = domain;
-	req->valid_bits = BE_QOS_BITS_NIC;
-	req->max_bps_nic = bps;
+	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
+	req->max_bps_nic = cpu_to_le32(bps);
 
 	status = be_mcc_notify_wait(adapter);
 
@@ -1877,3 +1960,96 @@ err:
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
+
+int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_cntl_attribs *req;
+	struct be_cmd_resp_cntl_attribs *resp;
+	struct be_sge *sge;
+	int status;
+	int payload_len = max(sizeof(*req), sizeof(*resp));
+	struct mgmt_controller_attrib *attribs;
+	struct be_dma_mem attribs_cmd;
+
+	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
+	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
+	attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size,
+						&attribs_cmd.dma);
+	if (!attribs_cmd.va) {
+		dev_err(&adapter->pdev->dev,
+				"Memory allocation failure\n");
+		return -ENOMEM;
+	}
+
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = attribs_cmd.va;
+	sge = nonembedded_sgl(wrb);
+
+	be_wrb_hdr_prepare(wrb, payload_len, false, 1,
+			OPCODE_COMMON_GET_CNTL_ATTRIBUTES);
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			 OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len);
+	sge->pa_hi = cpu_to_le32(upper_32_bits(attribs_cmd.dma));
+	sge->pa_lo = cpu_to_le32(attribs_cmd.dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(attribs_cmd.size);
+
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va +
+					sizeof(struct be_cmd_resp_hdr));
+		adapter->hba_port_num = attribs->hba_attribs.phy_port;
+	}
+
+err:
+	mutex_unlock(&adapter->mbox_lock);
+	pci_free_consistent(adapter->pdev, attribs_cmd.size, attribs_cmd.va,
+					attribs_cmd.dma);
+	return status;
+}
+
+/* Uses mbox */
+int be_cmd_check_native_mode(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_set_func_cap *req;
+	int status;
+
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+		OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, sizeof(*req));
+
+	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
+				CAPABILITY_BE3_NATIVE_ERX_API);
+	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
+
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
+		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
+					CAPABILITY_BE3_NATIVE_ERX_API;
+	}
+err:
+	mutex_unlock(&adapter->mbox_lock);
+	return status;
+}
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 83d15c8..4f254cf 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 /*
@@ -88,6 +88,7 @@ struct be_mcc_compl {
 #define ASYNC_EVENT_CODE_GRP_5		0x5
 #define ASYNC_EVENT_QOS_SPEED		0x1
 #define ASYNC_EVENT_COS_PRIORITY	0x2
+#define ASYNC_EVENT_PVID_STATE		0x3
 struct be_async_event_trailer {
 	u32 code;
 };
@@ -134,6 +135,18 @@ struct be_async_event_grp5_cos_priority {
 	struct be_async_event_trailer trailer;
 } __packed;
 
+/* When the event code of an async trailer is GRP5 and event type is
+ * PVID state, the mcc_compl must be interpreted as follows
+ */
+struct be_async_event_grp5_pvid_state {
+	u8 enabled;
+	u8 rsvd0;
+	u16 tag;
+	u32 event_tag;
+	u32 rsvd1;
+	struct be_async_event_trailer trailer;
+} __packed;
+
 struct be_mcc_mailbox {
 	struct be_mcc_wrb wrb;
 	struct be_mcc_compl compl;
@@ -156,6 +169,7 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_SET_QOS				28
 #define OPCODE_COMMON_MCC_CREATE_EXT			90
 #define OPCODE_COMMON_SEEPROM_READ			30
+#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES               32
 #define OPCODE_COMMON_NTWK_RX_FILTER    		34
 #define OPCODE_COMMON_GET_FW_VERSION			35
 #define OPCODE_COMMON_SET_FLOW_CONTROL			36
@@ -176,6 +190,8 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_BEACON_STATE			70
 #define OPCODE_COMMON_READ_TRANSRECV_DATA		73
 #define OPCODE_COMMON_GET_PHY_DETAILS			102
+#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP		103
+#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES	121
 
 #define OPCODE_ETH_RSS_CONFIG				1
 #define OPCODE_ETH_ACPI_CONFIG				2
@@ -415,7 +431,7 @@ struct be_cmd_resp_mcc_create {
 /* Pseudo amap definition in which each bit of the actual structure is defined
  * as a byte: used to calculate offset/shift/mask of each field */
 struct amap_tx_context {
-	u8 rsvd0[16];		/* dword 0 */
+	u8 if_id[16];		/* dword 0 */
 	u8 tx_ring_size[4];	/* dword 0 */
 	u8 rsvd1[26];		/* dword 0 */
 	u8 pci_func_id[8];	/* dword 1 */
@@ -503,7 +519,8 @@ enum be_if_flags {
 	BE_IF_FLAGS_VLAN = 0x100,
 	BE_IF_FLAGS_MCAST_PROMISCUOUS = 0x200,
 	BE_IF_FLAGS_PASS_L2_ERRORS = 0x400,
-	BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800
+	BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800,
+	BE_IF_FLAGS_MULTICAST = 0x1000
 };
 
 /* An RX interface is an object with one or more MAC addresses and
@@ -619,7 +636,10 @@ struct be_rxf_stats {
 	u32 rx_drops_invalid_ring;	/* dword 145*/
 	u32 forwarded_packets;	/* dword 146*/
 	u32 rx_drops_mtu;	/* dword 147*/
-	u32 rsvd0[15];
+	u32 rsvd0[7];
+	u32 port0_jabber_events;
+	u32 port1_jabber_events;
+	u32 rsvd1[6];
 };
 
 struct be_erx_stats {
@@ -630,11 +650,16 @@ struct be_erx_stats {
 	u32 debug_pmem_pbuf_dealloc;       /* dword 47*/
 };
 
+struct be_pmem_stats {
+	u32 eth_red_drops;
+	u32 rsvd[4];
+};
+
 struct be_hw_stats {
 	struct be_rxf_stats rxf;
 	u32 rsvd[48];
 	struct be_erx_stats erx;
-	u32 rsvd1[6];
+	struct be_pmem_stats pmem;
 };
 
 struct be_cmd_req_get_stats {
@@ -647,6 +672,20 @@ struct be_cmd_resp_get_stats {
 	struct be_hw_stats hw_stats;
 };
 
+struct be_cmd_req_get_cntl_addnl_attribs {
+	struct be_cmd_req_hdr hdr;
+	u8 rsvd[8];
+};
+
+struct be_cmd_resp_get_cntl_addnl_attribs {
+	struct be_cmd_resp_hdr hdr;
+	u16 ipl_file_number;
+	u8 ipl_file_version;
+	u8 rsvd0;
+	u8 on_die_temperature; /* in degrees centigrade*/
+	u8 rsvd1[3];
+};
+
 struct be_cmd_req_vlan_config {
 	struct be_cmd_req_hdr hdr;
 	u8 interface_id;
@@ -994,17 +1033,47 @@ struct be_cmd_resp_set_qos {
 	u32 rsvd;
 };
 
+/*********************** Controller Attributes ***********************/
+struct be_cmd_req_cntl_attribs {
+	struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_resp_cntl_attribs {
+	struct be_cmd_resp_hdr hdr;
+	struct mgmt_controller_attrib attribs;
+};
+
+/*********************** Set driver function ***********************/
+#define CAPABILITY_SW_TIMESTAMPS	2
+#define CAPABILITY_BE3_NATIVE_ERX_API	4
+
+struct be_cmd_req_set_func_cap {
+	struct be_cmd_req_hdr hdr;
+	u32 valid_cap_flags;
+	u32 cap_flags;
+	u8 rsvd[212];
+};
+
+struct be_cmd_resp_set_func_cap {
+	struct be_cmd_resp_hdr hdr;
+	u32 valid_cap_flags;
+	u32 cap_flags;
+	u8 rsvd[212];
+};
+
 extern int be_pci_fnum_get(struct be_adapter *adapter);
 extern int be_cmd_POST(struct be_adapter *adapter);
 extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
 			u8 type, bool permanent, u32 if_handle);
 extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
-			u32 if_id, u32 *pmac_id);
-extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
+			u32 if_id, u32 *pmac_id, u32 domain);
+extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
+			u32 pmac_id, u32 domain);
 extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
 			u32 en_flags, u8 *mac, bool pmac_invalid,
 			u32 *if_handle, u32 *pmac_id, u32 domain);
-extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
+extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle,
+			u32 domain);
 extern int be_cmd_eq_create(struct be_adapter *adapter,
 			struct be_queue_info *eq, int eq_delay);
 extern int be_cmd_cq_create(struct be_adapter *adapter,
@@ -1076,4 +1145,7 @@ extern int be_cmd_get_phy_info(struct be_adapter *adapter,
 		struct be_dma_mem *cmd);
 extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
 extern void be_detect_dump_ue(struct be_adapter *adapter);
+extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
+extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
+extern int be_cmd_check_native_mode(struct be_adapter *adapter);
 
diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c
index b4be027..aac248f 100644
--- a/drivers/net/benet/be_ethtool.c
+++ b/drivers/net/benet/be_ethtool.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #include "be.h"
@@ -26,7 +26,8 @@ struct be_ethtool_stat {
 	int offset;
 };
 
-enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT};
+enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT,
+			PMEMSTAT, DRVSTAT};
 #define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
 					offsetof(_struct, field)
 #define NETSTAT_INFO(field) 	#field, NETSTAT,\
@@ -43,6 +44,11 @@ enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT};
 						field)
 #define ERXSTAT_INFO(field) 	#field, ERXSTAT,\
 					FIELDINFO(struct be_erx_stats, field)
+#define PMEMSTAT_INFO(field) 	#field, PMEMSTAT,\
+					FIELDINFO(struct be_pmem_stats, field)
+#define	DRVSTAT_INFO(field)	#field, DRVSTAT,\
+					FIELDINFO(struct be_drv_stats, \
+						field)
 
 static const struct be_ethtool_stat et_stats[] = {
 	{NETSTAT_INFO(rx_packets)},
@@ -99,7 +105,11 @@ static const struct be_ethtool_stat et_stats[] = {
 	{MISCSTAT_INFO(rx_drops_too_many_frags)},
 	{MISCSTAT_INFO(rx_drops_invalid_ring)},
 	{MISCSTAT_INFO(forwarded_packets)},
-	{MISCSTAT_INFO(rx_drops_mtu)}
+	{MISCSTAT_INFO(rx_drops_mtu)},
+	{MISCSTAT_INFO(port0_jabber_events)},
+	{MISCSTAT_INFO(port1_jabber_events)},
+	{PMEMSTAT_INFO(eth_red_drops)},
+	{DRVSTAT_INFO(be_on_die_temperature)}
 };
 #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
 
@@ -121,7 +131,7 @@ static const char et_self_tests[][ETH_GSTRING_LEN] = {
 	"MAC Loopback test",
 	"PHY Loopback test",
 	"External Loopback test",
-	"DDR DMA test"
+	"DDR DMA test",
 	"Link test"
 };
 
@@ -276,6 +286,12 @@ be_get_ethtool_stats(struct net_device *netdev,
 		case MISCSTAT:
 			p = &hw_stats->rxf;
 			break;
+		case PMEMSTAT:
+			p = &hw_stats->pmem;
+			break;
+		case DRVSTAT:
+			p = &adapter->drv_stats;
+			break;
 		}
 
 		p = (u8 *)p + et_stats[i].offset;
@@ -376,8 +392,9 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 		}
 
 		phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info);
-		phy_cmd.va = pci_alloc_consistent(adapter->pdev, phy_cmd.size,
-					&phy_cmd.dma);
+		phy_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+						phy_cmd.size, &phy_cmd.dma,
+						GFP_KERNEL);
 		if (!phy_cmd.va) {
 			dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
 			return -ENOMEM;
@@ -416,8 +433,8 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 		adapter->port_type = ecmd->port;
 		adapter->transceiver = ecmd->transceiver;
 		adapter->autoneg = ecmd->autoneg;
-		pci_free_consistent(adapter->pdev, phy_cmd.size,
-					phy_cmd.va, phy_cmd.dma);
+		dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va,
+				  phy_cmd.dma);
 	} else {
 		ecmd->speed = adapter->link_speed;
 		ecmd->port = adapter->port_type;
@@ -496,7 +513,7 @@ be_phys_id(struct net_device *netdev, u32 data)
 	int status;
 	u32 cur;
 
-	be_cmd_get_beacon_state(adapter, adapter->port_num, &cur);
+	be_cmd_get_beacon_state(adapter, adapter->hba_port_num, &cur);
 
 	if (cur == BEACON_STATE_ENABLED)
 		return 0;
@@ -504,23 +521,34 @@ be_phys_id(struct net_device *netdev, u32 data)
 	if (data < 2)
 		data = 2;
 
-	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
+	status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 			BEACON_STATE_ENABLED);
 	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(data*HZ);
 
-	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
+	status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 			BEACON_STATE_DISABLED);
 
 	return status;
 }
 
+static bool
+be_is_wol_supported(struct be_adapter *adapter)
+{
+	if (!be_physfn(adapter))
+		return false;
+	else
+		return true;
+}
+
 static void
 be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 
-	wol->supported = WAKE_MAGIC;
+	if (be_is_wol_supported(adapter))
+		wol->supported = WAKE_MAGIC;
+
 	if (adapter->wol)
 		wol->wolopts = WAKE_MAGIC;
 	else
@@ -536,7 +564,7 @@ be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 
-	if (wol->wolopts & WAKE_MAGIC)
+	if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter))
 		adapter->wol = true;
 	else
 		adapter->wol = false;
@@ -554,8 +582,8 @@ be_test_ddr_dma(struct be_adapter *adapter)
 	};
 
 	ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
-	ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size,
-					&ddrdma_cmd.dma);
+	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");
 		return -ENOMEM;
@@ -569,20 +597,20 @@ be_test_ddr_dma(struct be_adapter *adapter)
 	}
 
 err:
-	pci_free_consistent(adapter->pdev, ddrdma_cmd.size,
-			ddrdma_cmd.va, ddrdma_cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,
+			  ddrdma_cmd.dma);
 	return ret;
 }
 
 static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
 				u64 *status)
 {
-	be_cmd_set_loopback(adapter, adapter->port_num,
+	be_cmd_set_loopback(adapter, adapter->hba_port_num,
 				loopback_type, 1);
-	*status = be_cmd_loopback_test(adapter, adapter->port_num,
+	*status = be_cmd_loopback_test(adapter, adapter->hba_port_num,
 				loopback_type, 1500,
 				2, 0xabc);
-	be_cmd_set_loopback(adapter, adapter->port_num,
+	be_cmd_set_loopback(adapter, adapter->hba_port_num,
 				BE_NO_LOOPBACK, 1);
 	return *status;
 }
@@ -621,7 +649,8 @@ be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data)
 				&qos_link_speed) != 0) {
 		test->flags |= ETH_TEST_FL_FAILED;
 		data[4] = -1;
-	} else if (mac_speed) {
+	} else if (!mac_speed) {
+		test->flags |= ETH_TEST_FL_FAILED;
 		data[4] = 1;
 	}
 }
@@ -662,8 +691,8 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
 
 	memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
 	eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
-	eeprom_cmd.va = pci_alloc_consistent(adapter->pdev, eeprom_cmd.size,
-				&eeprom_cmd.dma);
+	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,
@@ -677,8 +706,8 @@ be_read_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
 		resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
 		memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
 	}
-	pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va,
-			eeprom_cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
+			  eeprom_cmd.dma);
 
 	return status;
 }
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h
index 4096d97..d4344a0 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/benet/be_hw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 /********* Mailbox door bell *************/
@@ -44,6 +44,18 @@
 #define POST_STAGE_BE_RESET		0x3 /* Host wants to reset chip */
 #define POST_STAGE_ARMFW_RDY		0xc000	/* FW is done with POST */
 
+
+/* Lancer SLIPORT_CONTROL SLIPORT_STATUS registers */
+#define SLIPORT_STATUS_OFFSET		0x404
+#define SLIPORT_CONTROL_OFFSET		0x408
+
+#define SLIPORT_STATUS_ERR_MASK		0x80000000
+#define SLIPORT_STATUS_RN_MASK		0x01000000
+#define SLIPORT_STATUS_RDY_MASK		0x00800000
+
+
+#define SLI_PORT_CONTROL_IP_MASK	0x08000000
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 	0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
@@ -289,10 +301,10 @@ struct be_eth_rx_d {
 
 /* RX Compl Queue Descriptor */
 
-/* Pseudo amap definition for eth_rx_compl in which each bit of the
- * actual structure is defined as a byte: used to calculate
+/* Pseudo amap definition for BE2 and BE3 legacy mode eth_rx_compl in which
+ * each bit of the actual structure is defined as a byte: used to calculate
  * offset/shift/mask of each field */
-struct amap_eth_rx_compl {
+struct amap_eth_rx_compl_v0 {
 	u8 vlan_tag[16];	/* dword 0 */
 	u8 pktsize[14];		/* dword 0 */
 	u8 port;		/* dword 0 */
@@ -323,10 +335,92 @@ struct amap_eth_rx_compl {
 	u8 rsshash[32];		/* dword 3 */
 } __packed;
 
+/* Pseudo amap definition for BE3 native mode eth_rx_compl in which
+ * each bit of the actual structure is defined as a byte: used to calculate
+ * offset/shift/mask of each field */
+struct amap_eth_rx_compl_v1 {
+	u8 vlan_tag[16];	/* dword 0 */
+	u8 pktsize[14];		/* dword 0 */
+	u8 vtp;			/* dword 0 */
+	u8 ip_opt;		/* dword 0 */
+	u8 err;			/* dword 1 */
+	u8 rsshp;		/* dword 1 */
+	u8 ipf;			/* dword 1 */
+	u8 tcpf;		/* dword 1 */
+	u8 udpf;		/* dword 1 */
+	u8 ipcksm;		/* dword 1 */
+	u8 l4_cksm;		/* dword 1 */
+	u8 ip_version;		/* dword 1 */
+	u8 macdst[7];		/* dword 1 */
+	u8 rsvd0;		/* dword 1 */
+	u8 fragndx[10];		/* dword 1 */
+	u8 ct[2];		/* dword 1 */
+	u8 sw;			/* dword 1 */
+	u8 numfrags[3];		/* dword 1 */
+	u8 rss_flush;		/* dword 2 */
+	u8 cast_enc[2];		/* dword 2 */
+	u8 vtm;			/* dword 2 */
+	u8 rss_bank;		/* dword 2 */
+	u8 port[2];		/* dword 2 */
+	u8 vntagp;		/* dword 2 */
+	u8 header_len[8];	/* dword 2 */
+	u8 header_split[2];	/* dword 2 */
+	u8 rsvd1[13];		/* dword 2 */
+	u8 valid;		/* dword 2 */
+	u8 rsshash[32];		/* dword 3 */
+} __packed;
+
 struct be_eth_rx_compl {
 	u32 dw[4];
 };
 
+struct mgmt_hba_attribs {
+	u8 flashrom_version_string[32];
+	u8 manufacturer_name[32];
+	u32 supported_modes;
+	u32 rsvd0[3];
+	u8 ncsi_ver_string[12];
+	u32 default_extended_timeout;
+	u8 controller_model_number[32];
+	u8 controller_description[64];
+	u8 controller_serial_number[32];
+	u8 ip_version_string[32];
+	u8 firmware_version_string[32];
+	u8 bios_version_string[32];
+	u8 redboot_version_string[32];
+	u8 driver_version_string[32];
+	u8 fw_on_flash_version_string[32];
+	u32 functionalities_supported;
+	u16 max_cdblength;
+	u8 asic_revision;
+	u8 generational_guid[16];
+	u8 hba_port_count;
+	u16 default_link_down_timeout;
+	u8 iscsi_ver_min_max;
+	u8 multifunction_device;
+	u8 cache_valid;
+	u8 hba_status;
+	u8 max_domains_supported;
+	u8 phy_port;
+	u32 firmware_post_status;
+	u32 hba_mtu[8];
+	u32 rsvd1[4];
+};
+
+struct mgmt_controller_attrib {
+	struct mgmt_hba_attribs hba_attribs;
+	u16 pci_vendor_id;
+	u16 pci_device_id;
+	u16 pci_sub_vendor_id;
+	u16 pci_sub_system_id;
+	u8 pci_bus_number;
+	u8 pci_device_number;
+	u8 pci_function_number;
+	u8 interface_type;
+	u64 unique_identifier;
+	u32 rsvd0[5];
+};
+
 struct controller_id {
 	u32 vendor;
 	u32 device;
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 28a32a6..a71163f 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #include "be.h"
@@ -25,9 +25,9 @@ MODULE_DESCRIPTION(DRV_DESC " " DRV_VER);
 MODULE_AUTHOR("ServerEngines Corporation");
 MODULE_LICENSE("GPL");
 
-static unsigned int rx_frag_size = 2048;
+static ushort rx_frag_size = 2048;
 static unsigned int num_vfs;
-module_param(rx_frag_size, uint, S_IRUGO);
+module_param(rx_frag_size, ushort, S_IRUGO);
 module_param(num_vfs, uint, S_IRUGO);
 MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
 MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
@@ -125,8 +125,8 @@ static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q)
 {
 	struct be_dma_mem *mem = &q->dma_mem;
 	if (mem->va)
-		pci_free_consistent(adapter->pdev, mem->size,
-			mem->va, mem->dma);
+		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
+				  mem->dma);
 }
 
 static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
@@ -138,7 +138,8 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
 	q->len = len;
 	q->entry_size = entry_size;
 	mem->size = len * entry_size;
-	mem->va = pci_alloc_consistent(adapter->pdev, mem->size, &mem->dma);
+	mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
+				     GFP_KERNEL);
 	if (!mem->va)
 		return -1;
 	memset(mem->va, 0, mem->size);
@@ -235,12 +236,13 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
 	if (!be_physfn(adapter))
 		goto netdev_addr;
 
-	status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id);
+	status = be_cmd_pmac_del(adapter, adapter->if_handle,
+				adapter->pmac_id, 0);
 	if (status)
 		return status;
 
 	status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-			adapter->if_handle, &adapter->pmac_id);
+				adapter->if_handle, &adapter->pmac_id, 0);
 netdev_addr:
 	if (!status)
 		memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -484,7 +486,7 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
 	AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len);
 }
 
-static void unmap_tx_frag(struct pci_dev *pdev, struct be_eth_wrb *wrb,
+static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
 		bool unmap_single)
 {
 	dma_addr_t dma;
@@ -494,11 +496,10 @@ static void unmap_tx_frag(struct pci_dev *pdev, struct be_eth_wrb *wrb,
 	dma = (u64)wrb->frag_pa_hi << 32 | (u64)wrb->frag_pa_lo;
 	if (wrb->frag_len) {
 		if (unmap_single)
-			pci_unmap_single(pdev, dma, wrb->frag_len,
-				PCI_DMA_TODEVICE);
+			dma_unmap_single(dev, dma, wrb->frag_len,
+					 DMA_TO_DEVICE);
 		else
-			pci_unmap_page(pdev, dma, wrb->frag_len,
-				PCI_DMA_TODEVICE);
+			dma_unmap_page(dev, dma, wrb->frag_len, DMA_TO_DEVICE);
 	}
 }
 
@@ -507,7 +508,7 @@ static int make_tx_wrbs(struct be_adapter *adapter,
 {
 	dma_addr_t busaddr;
 	int i, copied = 0;
-	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = &adapter->pdev->dev;
 	struct sk_buff *first_skb = skb;
 	struct be_queue_info *txq = &adapter->tx_obj.q;
 	struct be_eth_wrb *wrb;
@@ -521,9 +522,8 @@ static int make_tx_wrbs(struct be_adapter *adapter,
 
 	if (skb->len > skb->data_len) {
 		int len = skb_headlen(skb);
-		busaddr = pci_map_single(pdev, skb->data, len,
-					 PCI_DMA_TODEVICE);
-		if (pci_dma_mapping_error(pdev, busaddr))
+		busaddr = dma_map_single(dev, skb->data, len, DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, busaddr))
 			goto dma_err;
 		map_single = true;
 		wrb = queue_head_node(txq);
@@ -536,10 +536,9 @@ static int make_tx_wrbs(struct be_adapter *adapter,
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		struct skb_frag_struct *frag =
 			&skb_shinfo(skb)->frags[i];
-		busaddr = pci_map_page(pdev, frag->page,
-				       frag->page_offset,
-				       frag->size, PCI_DMA_TODEVICE);
-		if (pci_dma_mapping_error(pdev, busaddr))
+		busaddr = dma_map_page(dev, frag->page, frag->page_offset,
+				       frag->size, DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, busaddr))
 			goto dma_err;
 		wrb = queue_head_node(txq);
 		wrb_fill(wrb, busaddr, frag->size);
@@ -563,7 +562,7 @@ dma_err:
 	txq->head = map_head;
 	while (copied) {
 		wrb = queue_head_node(txq);
-		unmap_tx_frag(pdev, wrb, map_single);
+		unmap_tx_frag(dev, wrb, map_single);
 		map_single = false;
 		copied -= wrb->frag_len;
 		queue_head_inc(txq);
@@ -743,11 +742,11 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 	if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
 		status = be_cmd_pmac_del(adapter,
 					adapter->vf_cfg[vf].vf_if_handle,
-					adapter->vf_cfg[vf].vf_pmac_id);
+					adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
 
 	status = be_cmd_pmac_add(adapter, mac,
 				adapter->vf_cfg[vf].vf_if_handle,
-				&adapter->vf_cfg[vf].vf_pmac_id);
+				&adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
 
 	if (status)
 		dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
@@ -822,7 +821,7 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
 		rate = 10000;
 
 	adapter->vf_cfg[vf].vf_tx_rate = rate;
-	status = be_cmd_set_qos(adapter, rate / 10, vf);
+	status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
 
 	if (status)
 		dev_info(&adapter->pdev->dev,
@@ -852,28 +851,26 @@ static void be_rx_rate_update(struct be_rx_obj *rxo)
 }
 
 static void be_rx_stats_update(struct be_rx_obj *rxo,
-		u32 pktsize, u16 numfrags, u8 pkt_type)
+		struct be_rx_compl_info *rxcp)
 {
 	struct be_rx_stats *stats = &rxo->stats;
 
 	stats->rx_compl++;
-	stats->rx_frags += numfrags;
-	stats->rx_bytes += pktsize;
+	stats->rx_frags += rxcp->num_rcvd;
+	stats->rx_bytes += rxcp->pkt_size;
 	stats->rx_pkts++;
-	if (pkt_type == BE_MULTICAST_PACKET)
+	if (rxcp->pkt_type == BE_MULTICAST_PACKET)
 		stats->rx_mcast_pkts++;
+	if (rxcp->err)
+		stats->rxcp_err++;
 }
 
-static inline bool csum_passed(struct be_eth_rx_compl *rxcp)
+static inline bool csum_passed(struct be_rx_compl_info *rxcp)
 {
-	u8 l4_cksm, ipv6, ipcksm;
-
-	l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp);
-	ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp);
-	ipv6 = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp);
-
-	/* Ignore ipcksm for ipv6 pkts */
-	return l4_cksm && (ipcksm || ipv6);
+	/* L4 checksum is not reliable for non TCP/UDP packets.
+	 * Also ignore ipcksm for ipv6 pkts */
+	return (rxcp->tcpf || rxcp->udpf) && rxcp->l4_csum &&
+				(rxcp->ip_csum || rxcp->ipv6);
 }
 
 static struct be_rx_page_info *
@@ -888,8 +885,9 @@ get_rx_page_info(struct be_adapter *adapter,
 	BUG_ON(!rx_page_info->page);
 
 	if (rx_page_info->last_page_user) {
-		pci_unmap_page(adapter->pdev, dma_unmap_addr(rx_page_info, bus),
-			adapter->big_page_size, PCI_DMA_FROMDEVICE);
+		dma_unmap_page(&adapter->pdev->dev,
+			       dma_unmap_addr(rx_page_info, bus),
+			       adapter->big_page_size, DMA_FROM_DEVICE);
 		rx_page_info->last_page_user = false;
 	}
 
@@ -900,26 +898,17 @@ get_rx_page_info(struct be_adapter *adapter,
 /* Throwaway the data in the Rx completion */
 static void be_rx_compl_discard(struct be_adapter *adapter,
 		struct be_rx_obj *rxo,
-		struct be_eth_rx_compl *rxcp)
+		struct be_rx_compl_info *rxcp)
 {
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_rx_page_info *page_info;
-	u16 rxq_idx, i, num_rcvd;
-
-	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
-	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
+	u16 i, num_rcvd = rxcp->num_rcvd;
 
-	 /* Skip out-of-buffer compl(lancer) or flush compl(BE) */
-	if (likely(rxq_idx != rxo->last_frag_index && num_rcvd != 0)) {
-
-		rxo->last_frag_index = rxq_idx;
-
-		for (i = 0; i < num_rcvd; i++) {
-			page_info = get_rx_page_info(adapter, rxo, rxq_idx);
-			put_page(page_info->page);
-			memset(page_info, 0, sizeof(*page_info));
-			index_inc(&rxq_idx, rxq->len);
-		}
+	for (i = 0; i < num_rcvd; i++) {
+		page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+		put_page(page_info->page);
+		memset(page_info, 0, sizeof(*page_info));
+		index_inc(&rxcp->rxq_idx, rxq->len);
 	}
 }
 
@@ -928,30 +917,23 @@ static void be_rx_compl_discard(struct be_adapter *adapter,
  * indicated by rxcp.
  */
 static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
-			struct sk_buff *skb, struct be_eth_rx_compl *rxcp,
-			u16 num_rcvd)
+			struct sk_buff *skb, struct be_rx_compl_info *rxcp)
 {
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_rx_page_info *page_info;
-	u16 rxq_idx, i, j;
-	u32 pktsize, hdr_len, curr_frag_len, size;
+	u16 i, j;
+	u16 hdr_len, curr_frag_len, remaining;
 	u8 *start;
-	u8 pkt_type;
-
-	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
-	pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
-	pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
-
-	page_info = get_rx_page_info(adapter, rxo, rxq_idx);
 
+	page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
 	start = page_address(page_info->page) + page_info->page_offset;
 	prefetch(start);
 
 	/* Copy data in the first descriptor of this completion */
-	curr_frag_len = min(pktsize, rx_frag_size);
+	curr_frag_len = min(rxcp->pkt_size, rx_frag_size);
 
 	/* Copy the header portion into skb_data */
-	hdr_len = min((u32)BE_HDR_LEN, curr_frag_len);
+	hdr_len = min(BE_HDR_LEN, curr_frag_len);
 	memcpy(skb->data, start, hdr_len);
 	skb->len = curr_frag_len;
 	if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */
@@ -970,19 +952,17 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
 	}
 	page_info->page = NULL;
 
-	if (pktsize <= rx_frag_size) {
-		BUG_ON(num_rcvd != 1);
-		goto done;
+	if (rxcp->pkt_size <= rx_frag_size) {
+		BUG_ON(rxcp->num_rcvd != 1);
+		return;
 	}
 
 	/* More frags present for this completion */
-	size = pktsize;
-	for (i = 1, j = 0; i < num_rcvd; i++) {
-		size -= curr_frag_len;
-		index_inc(&rxq_idx, rxq->len);
-		page_info = get_rx_page_info(adapter, rxo, rxq_idx);
-
-		curr_frag_len = min(size, rx_frag_size);
+	index_inc(&rxcp->rxq_idx, rxq->len);
+	remaining = rxcp->pkt_size - curr_frag_len;
+	for (i = 1, j = 0; i < rxcp->num_rcvd; i++) {
+		page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+		curr_frag_len = min(remaining, rx_frag_size);
 
 		/* Coalesce all frags from the same physical page in one slot */
 		if (page_info->page_offset == 0) {
@@ -1001,25 +981,19 @@ static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
 		skb->len += curr_frag_len;
 		skb->data_len += curr_frag_len;
 
+		remaining -= curr_frag_len;
+		index_inc(&rxcp->rxq_idx, rxq->len);
 		page_info->page = NULL;
 	}
 	BUG_ON(j > MAX_SKB_FRAGS);
-
-done:
-	be_rx_stats_update(rxo, pktsize, num_rcvd, pkt_type);
 }
 
 /* Process the RX completion indicated by rxcp when GRO is disabled */
 static void be_rx_compl_process(struct be_adapter *adapter,
 			struct be_rx_obj *rxo,
-			struct be_eth_rx_compl *rxcp)
+			struct be_rx_compl_info *rxcp)
 {
 	struct sk_buff *skb;
-	u32 vlanf, vid;
-	u16 num_rcvd;
-	u8 vtm;
-
-	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 
 	skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN);
 	if (unlikely(!skb)) {
@@ -1029,7 +1003,7 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 		return;
 	}
 
-	skb_fill_rx_data(adapter, rxo, skb, rxcp, num_rcvd);
+	skb_fill_rx_data(adapter, rxo, skb, rxcp);
 
 	if (likely(adapter->rx_csum && csum_passed(rxcp)))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1039,23 +1013,12 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 	skb->truesize = skb->len + sizeof(struct sk_buff);
 	skb->protocol = eth_type_trans(skb, adapter->netdev);
 
-	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
-	vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
-
-	/* vlanf could be wrongly set in some cards.
-	 * ignore if vtm is not set */
-	if ((adapter->function_mode & 0x400) && !vtm)
-		vlanf = 0;
-
-	if (unlikely(vlanf)) {
+	if (unlikely(rxcp->vlanf)) {
 		if (!adapter->vlan_grp || adapter->vlans_added == 0) {
 			kfree_skb(skb);
 			return;
 		}
-		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-		if (!lancer_chip(adapter))
-			vid = swab16(vid);
-		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid);
+		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, rxcp->vid);
 	} else {
 		netif_receive_skb(skb);
 	}
@@ -1064,28 +1027,14 @@ static void be_rx_compl_process(struct be_adapter *adapter,
 /* Process the RX completion indicated by rxcp when GRO is enabled */
 static void be_rx_compl_process_gro(struct be_adapter *adapter,
 		struct be_rx_obj *rxo,
-		struct be_eth_rx_compl *rxcp)
+		struct be_rx_compl_info *rxcp)
 {
 	struct be_rx_page_info *page_info;
 	struct sk_buff *skb = NULL;
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_eq_obj *eq_obj =  &rxo->rx_eq;
-	u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
-	u16 i, rxq_idx = 0, vid, j;
-	u8 vtm;
-	u8 pkt_type;
-
-	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-	pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
-	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
-	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
-	vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
-	pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
-
-	/* vlanf could be wrongly set in some cards.
-	 * ignore if vtm is not set */
-	if ((adapter->function_mode & 0x400) && !vtm)
-		vlanf = 0;
+	u16 remaining, curr_frag_len;
+	u16 i, j;
 
 	skb = napi_get_frags(&eq_obj->napi);
 	if (!skb) {
@@ -1093,9 +1042,9 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
 		return;
 	}
 
-	remaining = pkt_size;
-	for (i = 0, j = -1; i < num_rcvd; i++) {
-		page_info = get_rx_page_info(adapter, rxo, rxq_idx);
+	remaining = rxcp->pkt_size;
+	for (i = 0, j = -1; i < rxcp->num_rcvd; i++) {
+		page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
 
 		curr_frag_len = min(remaining, rx_frag_size);
 
@@ -1113,70 +1062,125 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
 		skb_shinfo(skb)->frags[j].size += curr_frag_len;
 
 		remaining -= curr_frag_len;
-		index_inc(&rxq_idx, rxq->len);
+		index_inc(&rxcp->rxq_idx, rxq->len);
 		memset(page_info, 0, sizeof(*page_info));
 	}
 	BUG_ON(j > MAX_SKB_FRAGS);
 
 	skb_shinfo(skb)->nr_frags = j + 1;
-	skb->len = pkt_size;
-	skb->data_len = pkt_size;
-	skb->truesize += pkt_size;
+	skb->len = rxcp->pkt_size;
+	skb->data_len = rxcp->pkt_size;
+	skb->truesize += rxcp->pkt_size;
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	if (likely(!vlanf)) {
+	if (likely(!rxcp->vlanf))
 		napi_gro_frags(&eq_obj->napi);
-	} else {
-		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-		if (!lancer_chip(adapter))
-			vid = swab16(vid);
+	else
+		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, rxcp->vid);
+}
+
+static void be_parse_rx_compl_v1(struct be_adapter *adapter,
+				struct be_eth_rx_compl *compl,
+				struct be_rx_compl_info *rxcp)
+{
+	rxcp->pkt_size =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, pktsize, compl);
+	rxcp->vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtp, compl);
+	rxcp->err = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, err, compl);
+	rxcp->tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, tcpf, compl);
+	rxcp->udpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, udpf, compl);
+	rxcp->ip_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ipcksm, compl);
+	rxcp->l4_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, l4_cksm, compl);
+	rxcp->ipv6 =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ip_version, compl);
+	rxcp->rxq_idx =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, fragndx, compl);
+	rxcp->num_rcvd =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl);
+	rxcp->pkt_type =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl);
+	rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, compl);
+	rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag, compl);
+}
+
+static void be_parse_rx_compl_v0(struct be_adapter *adapter,
+				struct be_eth_rx_compl *compl,
+				struct be_rx_compl_info *rxcp)
+{
+	rxcp->pkt_size =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, pktsize, compl);
+	rxcp->vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtp, compl);
+	rxcp->err = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, err, compl);
+	rxcp->tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, tcpf, compl);
+	rxcp->udpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, udpf, compl);
+	rxcp->ip_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ipcksm, compl);
+	rxcp->l4_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, l4_cksm, compl);
+	rxcp->ipv6 =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ip_version, compl);
+	rxcp->rxq_idx =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, fragndx, compl);
+	rxcp->num_rcvd =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl);
+	rxcp->pkt_type =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl);
+	rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, compl);
+	rxcp->vid = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag, compl);
+}
+
+static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
+{
+	struct be_eth_rx_compl *compl = queue_tail_node(&rxo->cq);
+	struct be_rx_compl_info *rxcp = &rxo->rxcp;
+	struct be_adapter *adapter = rxo->adapter;
 
-		if (!adapter->vlan_grp || adapter->vlans_added == 0)
-			return;
+	/* For checking the valid bit it is Ok to use either definition as the
+	 * valid bit is at the same position in both v0 and v1 Rx compl */
+	if (compl->dw[offsetof(struct amap_eth_rx_compl_v1, valid) / 32] == 0)
+		return NULL;
 
-		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
-	}
+	rmb();
+	be_dws_le_to_cpu(compl, sizeof(*compl));
 
-	be_rx_stats_update(rxo, pkt_size, num_rcvd, pkt_type);
-}
+	if (adapter->be3_native)
+		be_parse_rx_compl_v1(adapter, compl, rxcp);
+	else
+		be_parse_rx_compl_v0(adapter, compl, rxcp);
 
-static struct be_eth_rx_compl *be_rx_compl_get(struct be_rx_obj *rxo)
-{
-	struct be_eth_rx_compl *rxcp = queue_tail_node(&rxo->cq);
+	/* vlanf could be wrongly set in some cards. ignore if vtm is not set */
+	if ((adapter->function_mode & 0x400) && !rxcp->vtm)
+		rxcp->vlanf = 0;
 
-	if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0)
-		return NULL;
+	if (!lancer_chip(adapter))
+		rxcp->vid = swab16(rxcp->vid);
 
-	rmb();
-	be_dws_le_to_cpu(rxcp, sizeof(*rxcp));
+	if ((adapter->pvid == rxcp->vid) && !adapter->vlan_tag[rxcp->vid])
+		rxcp->vlanf = 0;
+
+	/* As the compl has been parsed, reset it; we wont touch it again */
+	compl->dw[offsetof(struct amap_eth_rx_compl_v1, valid) / 32] = 0;
 
 	queue_tail_inc(&rxo->cq);
 	return rxcp;
 }
 
-/* To reset the valid bit, we need to reset the whole word as
- * when walking the queue the valid entries are little-endian
- * and invalid entries are host endian
- */
-static inline void be_rx_compl_reset(struct be_eth_rx_compl *rxcp)
+static inline struct page *be_alloc_pages(u32 size, gfp_t gfp)
 {
-	rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0;
-}
-
-static inline struct page *be_alloc_pages(u32 size)
-{
-	gfp_t alloc_flags = GFP_ATOMIC;
 	u32 order = get_order(size);
+
 	if (order > 0)
-		alloc_flags |= __GFP_COMP;
-	return  alloc_pages(alloc_flags, order);
+		gfp |= __GFP_COMP;
+	return  alloc_pages(gfp, order);
 }
 
 /*
  * Allocate a page, split it to fragments of size rx_frag_size and post as
  * receive buffers to BE
  */
-static void be_post_rx_frags(struct be_rx_obj *rxo)
+static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
 {
 	struct be_adapter *adapter = rxo->adapter;
 	struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl;
@@ -1190,14 +1194,14 @@ static void be_post_rx_frags(struct be_rx_obj *rxo)
 	page_info = &rxo->page_info_tbl[rxq->head];
 	for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) {
 		if (!pagep) {
-			pagep = be_alloc_pages(adapter->big_page_size);
+			pagep = be_alloc_pages(adapter->big_page_size, gfp);
 			if (unlikely(!pagep)) {
 				rxo->stats.rx_post_fail++;
 				break;
 			}
-			page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0,
-						adapter->big_page_size,
-						PCI_DMA_FROMDEVICE);
+			page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
+						    0, adapter->big_page_size,
+						    DMA_FROM_DEVICE);
 			page_info->page_offset = 0;
 		} else {
 			get_page(pagep);
@@ -1270,8 +1274,8 @@ static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index)
 	do {
 		cur_index = txq->tail;
 		wrb = queue_tail_node(txq);
-		unmap_tx_frag(adapter->pdev, wrb, (unmap_skb_hdr &&
-					skb_headlen(sent_skb)));
+		unmap_tx_frag(&adapter->pdev->dev, wrb,
+			      (unmap_skb_hdr && skb_headlen(sent_skb)));
 		unmap_skb_hdr = false;
 
 		num_wrbs++;
@@ -1339,13 +1343,12 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo)
 	struct be_rx_page_info *page_info;
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_queue_info *rx_cq = &rxo->cq;
-	struct be_eth_rx_compl *rxcp;
+	struct be_rx_compl_info *rxcp;
 	u16 tail;
 
 	/* First cleanup pending rx completions */
 	while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
 		be_rx_compl_discard(adapter, rxo, rxcp);
-		be_rx_compl_reset(rxcp);
 		be_cq_notify(adapter, rx_cq->id, false, 1);
 	}
 
@@ -1573,9 +1576,6 @@ static int be_rx_queues_create(struct be_adapter *adapter)
 	adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
 	for_all_rx_queues(adapter, rxo, i) {
 		rxo->adapter = adapter;
-		/* Init last_frag_index so that the frag index in the first
-		 * completion will never match */
-		rxo->last_frag_index = 0xffff;
 		rxo->rx_eq.max_eqd = BE_MAX_EQD;
 		rxo->rx_eq.enable_aic = true;
 
@@ -1697,15 +1697,9 @@ static irqreturn_t be_msix_tx_mcc(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static inline bool do_gro(struct be_rx_obj *rxo,
-			struct be_eth_rx_compl *rxcp, u8 err)
+static inline bool do_gro(struct be_rx_compl_info *rxcp)
 {
-	int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
-
-	if (err)
-		rxo->stats.rxcp_err++;
-
-	return (tcp_frame && !err) ? true : false;
+	return (rxcp->tcpf && !rxcp->err) ? true : false;
 }
 
 static int be_poll_rx(struct napi_struct *napi, int budget)
@@ -1714,10 +1708,8 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
 	struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq);
 	struct be_adapter *adapter = rxo->adapter;
 	struct be_queue_info *rx_cq = &rxo->cq;
-	struct be_eth_rx_compl *rxcp;
+	struct be_rx_compl_info *rxcp;
 	u32 work_done;
-	u16 frag_index, num_rcvd;
-	u8 err;
 
 	rxo->stats.rx_polls++;
 	for (work_done = 0; work_done < budget; work_done++) {
@@ -1725,29 +1717,19 @@ static int be_poll_rx(struct napi_struct *napi, int budget)
 		if (!rxcp)
 			break;
 
-		err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
-		frag_index = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx,
-								rxcp);
-		num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags,
-								rxcp);
-
-		/* Skip out-of-buffer compl(lancer) or flush compl(BE) */
-		if (likely(frag_index != rxo->last_frag_index &&
-				num_rcvd != 0)) {
-			rxo->last_frag_index = frag_index;
-
-			if (do_gro(rxo, rxcp, err))
+		/* Ignore flush completions */
+		if (rxcp->num_rcvd) {
+			if (do_gro(rxcp))
 				be_rx_compl_process_gro(adapter, rxo, rxcp);
 			else
 				be_rx_compl_process(adapter, rxo, rxcp);
 		}
-
-		be_rx_compl_reset(rxcp);
+		be_rx_stats_update(rxo, rxcp);
 	}
 
 	/* Refill the queue */
 	if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
-		be_post_rx_frags(rxo);
+		be_post_rx_frags(rxo, GFP_ATOMIC);
 
 	/* All consumed */
 	if (work_done < budget) {
@@ -1827,6 +1809,7 @@ void be_detect_dump_ue(struct be_adapter *adapter)
 
 	if (ue_status_lo || ue_status_hi) {
 		adapter->ue_detected = true;
+		adapter->eeh_err = true;
 		dev_err(&adapter->pdev->dev, "UE Detected!!\n");
 	}
 
@@ -1865,10 +1848,14 @@ static void be_worker(struct work_struct *work)
 			struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 			be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
 		}
+
+		if (!adapter->ue_detected && !lancer_chip(adapter))
+			be_detect_dump_ue(adapter);
+
 		goto reschedule;
 	}
 
-	if (!adapter->stats_ioctl_sent)
+	if (!adapter->stats_cmd_sent)
 		be_cmd_get_stats(adapter, &adapter->stats_cmd);
 
 	be_tx_rate_update(adapter);
@@ -1879,7 +1866,7 @@ static void be_worker(struct work_struct *work)
 
 		if (rxo->rx_post_starved) {
 			rxo->rx_post_starved = false;
-			be_post_rx_frags(rxo);
+			be_post_rx_frags(rxo, GFP_KERNEL);
 		}
 	}
 	if (!adapter->ue_detected && !lancer_chip(adapter))
@@ -2083,13 +2070,24 @@ static int be_close(struct net_device *netdev)
 
 	be_async_mcc_disable(adapter);
 
-	netif_stop_queue(netdev);
 	netif_carrier_off(netdev);
 	adapter->link_up = false;
 
 	if (!lancer_chip(adapter))
 		be_intr_set(adapter, false);
 
+	for_all_rx_queues(adapter, rxo, i)
+		napi_disable(&rxo->rx_eq.napi);
+
+	napi_disable(&tx_eq->napi);
+
+	if (lancer_chip(adapter)) {
+		be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0);
+		be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
+		for_all_rx_queues(adapter, rxo, i)
+			 be_cq_notify(adapter, rxo->cq.id, false, 0);
+	}
+
 	if (adapter->msix_enabled) {
 		vec = be_msix_vec_get(adapter, tx_eq);
 		synchronize_irq(vec);
@@ -2103,11 +2101,6 @@ static int be_close(struct net_device *netdev)
 	}
 	be_irq_unregister(adapter);
 
-	for_all_rx_queues(adapter, rxo, i)
-		napi_disable(&rxo->rx_eq.napi);
-
-	napi_disable(&tx_eq->napi);
-
 	/* Wait for all pending tx completions to arrive so that
 	 * all tx skbs are freed.
 	 */
@@ -2127,7 +2120,7 @@ static int be_open(struct net_device *netdev)
 	u16 link_speed;
 
 	for_all_rx_queues(adapter, rxo, i) {
-		be_post_rx_frags(rxo);
+		be_post_rx_frags(rxo, GFP_KERNEL);
 		napi_enable(&rxo->rx_eq.napi);
 	}
 	napi_enable(&tx_eq->napi);
@@ -2179,7 +2172,8 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
 	memset(mac, 0, ETH_ALEN);
 
 	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
-	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+				    GFP_KERNEL);
 	if (cmd.va == NULL)
 		return -1;
 	memset(cmd.va, 0, cmd.size);
@@ -2190,8 +2184,8 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
 		if (status) {
 			dev_err(&adapter->pdev->dev,
 				"Could not enable Wake-on-lan\n");
-			pci_free_consistent(adapter->pdev, cmd.size, cmd.va,
-					cmd.dma);
+			dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
+					  cmd.dma);
 			return status;
 		}
 		status = be_cmd_enable_magic_wol(adapter,
@@ -2204,7 +2198,7 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable)
 		pci_enable_wake(adapter->pdev, PCI_D3cold, 0);
 	}
 
-	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
 	return status;
 }
 
@@ -2225,7 +2219,8 @@ static inline int be_vf_eth_addr_config(struct be_adapter *adapter)
 	for (vf = 0; vf < num_vfs; vf++) {
 		status = be_cmd_pmac_add(adapter, mac,
 					adapter->vf_cfg[vf].vf_if_handle,
-					&adapter->vf_cfg[vf].vf_pmac_id);
+					&adapter->vf_cfg[vf].vf_pmac_id,
+					vf + 1);
 		if (status)
 			dev_err(&adapter->pdev->dev,
 				"Mac address add failed for VF %d\n", vf);
@@ -2245,7 +2240,7 @@ static inline void be_vf_eth_addr_rem(struct be_adapter *adapter)
 		if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
 			be_cmd_pmac_del(adapter,
 					adapter->vf_cfg[vf].vf_if_handle,
-					adapter->vf_cfg[vf].vf_pmac_id);
+					adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
 	}
 }
 
@@ -2256,7 +2251,9 @@ static int be_setup(struct be_adapter *adapter)
 	int status;
 	u8 mac[ETH_ALEN];
 
-	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST;
+	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
+				BE_IF_FLAGS_BROADCAST |
+				BE_IF_FLAGS_MULTICAST;
 
 	if (be_physfn(adapter)) {
 		cap_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS |
@@ -2277,22 +2274,26 @@ static int be_setup(struct be_adapter *adapter)
 		goto do_none;
 
 	if (be_physfn(adapter)) {
-		while (vf < num_vfs) {
-			cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED
-					| BE_IF_FLAGS_BROADCAST;
-			status = be_cmd_if_create(adapter, cap_flags, en_flags,
-					mac, true,
+		if (adapter->sriov_enabled) {
+			while (vf < num_vfs) {
+				cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
+							BE_IF_FLAGS_BROADCAST;
+				status = be_cmd_if_create(adapter, cap_flags,
+					en_flags, mac, true,
 					&adapter->vf_cfg[vf].vf_if_handle,
 					NULL, vf+1);
-			if (status) {
-				dev_err(&adapter->pdev->dev,
-				"Interface Create failed for VF %d\n", vf);
-				goto if_destroy;
+				if (status) {
+					dev_err(&adapter->pdev->dev,
+					"Interface Create failed for VF %d\n",
+					vf);
+					goto if_destroy;
+				}
+				adapter->vf_cfg[vf].vf_pmac_id =
+							BE_INVALID_PMAC_ID;
+				vf++;
 			}
-			adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID;
-			vf++;
 		}
-	} else if (!be_physfn(adapter)) {
+	} else {
 		status = be_cmd_mac_addr_query(adapter, mac,
 			MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
 		if (!status) {
@@ -2313,44 +2314,46 @@ static int be_setup(struct be_adapter *adapter)
 	if (status != 0)
 		goto rx_qs_destroy;
 
-	if (be_physfn(adapter)) {
-		status = be_vf_eth_addr_config(adapter);
-		if (status)
-			goto mcc_q_destroy;
-	}
-
 	adapter->link_speed = -1;
 
 	return 0;
 
-mcc_q_destroy:
-	if (be_physfn(adapter))
-		be_vf_eth_addr_rem(adapter);
 	be_mcc_queues_destroy(adapter);
 rx_qs_destroy:
 	be_rx_queues_destroy(adapter);
 tx_qs_destroy:
 	be_tx_queues_destroy(adapter);
 if_destroy:
-	for (vf = 0; vf < num_vfs; vf++)
-		if (adapter->vf_cfg[vf].vf_if_handle)
-			be_cmd_if_destroy(adapter,
-					adapter->vf_cfg[vf].vf_if_handle);
-	be_cmd_if_destroy(adapter, adapter->if_handle);
+	if (be_physfn(adapter) && adapter->sriov_enabled)
+		for (vf = 0; vf < num_vfs; vf++)
+			if (adapter->vf_cfg[vf].vf_if_handle)
+				be_cmd_if_destroy(adapter,
+					adapter->vf_cfg[vf].vf_if_handle,
+					vf + 1);
+	be_cmd_if_destroy(adapter, adapter->if_handle, 0);
 do_none:
 	return status;
 }
 
 static int be_clear(struct be_adapter *adapter)
 {
-	if (be_physfn(adapter))
+	int vf;
+
+	if (be_physfn(adapter) && adapter->sriov_enabled)
 		be_vf_eth_addr_rem(adapter);
 
 	be_mcc_queues_destroy(adapter);
 	be_rx_queues_destroy(adapter);
 	be_tx_queues_destroy(adapter);
 
-	be_cmd_if_destroy(adapter, adapter->if_handle);
+	if (be_physfn(adapter) && adapter->sriov_enabled)
+		for (vf = 0; vf < num_vfs; vf++)
+			if (adapter->vf_cfg[vf].vf_if_handle)
+				be_cmd_if_destroy(adapter,
+					adapter->vf_cfg[vf].vf_if_handle,
+					vf + 1);
+
+	be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
 	/* tell fw we're done with firing cmds */
 	be_cmd_fw_clean(adapter);
@@ -2453,8 +2456,8 @@ static int be_flash_data(struct be_adapter *adapter,
 			continue;
 		if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
 			(!be_flash_redboot(adapter, fw->data,
-			 pflashcomp[i].offset, pflashcomp[i].size,
-			 filehdr_size)))
+			pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
+			(num_of_images * sizeof(struct image_hdr)))))
 			continue;
 		p = fw->data;
 		p += filehdr_size + pflashcomp[i].offset
@@ -2528,8 +2531,8 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
 	dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
 
 	flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
-	flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size,
-					&flash_cmd.dma);
+	flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
+					  &flash_cmd.dma, GFP_KERNEL);
 	if (!flash_cmd.va) {
 		status = -ENOMEM;
 		dev_err(&adapter->pdev->dev,
@@ -2558,8 +2561,8 @@ int be_load_fw(struct be_adapter *adapter, u8 *func)
 		status = -1;
 	}
 
-	pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va,
-				flash_cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
+			  flash_cmd.dma);
 	if (status) {
 		dev_err(&adapter->pdev->dev, "Firmware load error\n");
 		goto fw_exit;
@@ -2700,13 +2703,13 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
 	be_unmap_pci_bars(adapter);
 
 	if (mem->va)
-		pci_free_consistent(adapter->pdev, mem->size,
-			mem->va, mem->dma);
+		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
+				  mem->dma);
 
 	mem = &adapter->mc_cmd_mem;
 	if (mem->va)
-		pci_free_consistent(adapter->pdev, mem->size,
-			mem->va, mem->dma);
+		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
+				  mem->dma);
 }
 
 static int be_ctrl_init(struct be_adapter *adapter)
@@ -2721,8 +2724,10 @@ static int be_ctrl_init(struct be_adapter *adapter)
 		goto done;
 
 	mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
-	mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev,
-				mbox_mem_alloc->size, &mbox_mem_alloc->dma);
+	mbox_mem_alloc->va = dma_alloc_coherent(&adapter->pdev->dev,
+						mbox_mem_alloc->size,
+						&mbox_mem_alloc->dma,
+						GFP_KERNEL);
 	if (!mbox_mem_alloc->va) {
 		status = -ENOMEM;
 		goto unmap_pci_bars;
@@ -2734,8 +2739,9 @@ static int be_ctrl_init(struct be_adapter *adapter)
 	memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
 
 	mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
-	mc_cmd_mem->va = pci_alloc_consistent(adapter->pdev, mc_cmd_mem->size,
-			&mc_cmd_mem->dma);
+	mc_cmd_mem->va = dma_alloc_coherent(&adapter->pdev->dev,
+					    mc_cmd_mem->size, &mc_cmd_mem->dma,
+					    GFP_KERNEL);
 	if (mc_cmd_mem->va == NULL) {
 		status = -ENOMEM;
 		goto free_mbox;
@@ -2751,8 +2757,8 @@ static int be_ctrl_init(struct be_adapter *adapter)
 	return 0;
 
 free_mbox:
-	pci_free_consistent(adapter->pdev, mbox_mem_alloc->size,
-		mbox_mem_alloc->va, mbox_mem_alloc->dma);
+	dma_free_coherent(&adapter->pdev->dev, mbox_mem_alloc->size,
+			  mbox_mem_alloc->va, mbox_mem_alloc->dma);
 
 unmap_pci_bars:
 	be_unmap_pci_bars(adapter);
@@ -2766,8 +2772,8 @@ static void be_stats_cleanup(struct be_adapter *adapter)
 	struct be_dma_mem *cmd = &adapter->stats_cmd;
 
 	if (cmd->va)
-		pci_free_consistent(adapter->pdev, cmd->size,
-			cmd->va, cmd->dma);
+		dma_free_coherent(&adapter->pdev->dev, cmd->size,
+				  cmd->va, cmd->dma);
 }
 
 static int be_stats_init(struct be_adapter *adapter)
@@ -2775,7 +2781,8 @@ static int be_stats_init(struct be_adapter *adapter)
 	struct be_dma_mem *cmd = &adapter->stats_cmd;
 
 	cmd->size = sizeof(struct be_cmd_req_get_stats);
-	cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma);
+	cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
+				     GFP_KERNEL);
 	if (cmd->va == NULL)
 		return -1;
 	memset(cmd->va, 0, cmd->size);
@@ -2845,6 +2852,11 @@ static int be_get_config(struct be_adapter *adapter)
 	else
 		adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
 
+	status = be_cmd_get_cntl_attributes(adapter);
+	if (status)
+		return status;
+
+	be_cmd_check_native_mode(adapter);
 	return 0;
 }
 
@@ -2886,6 +2898,54 @@ static int be_dev_family_check(struct be_adapter *adapter)
 	return 0;
 }
 
+static int lancer_wait_ready(struct be_adapter *adapter)
+{
+#define SLIPORT_READY_TIMEOUT 500
+	u32 sliport_status;
+	int status = 0, i;
+
+	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
+		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
+			break;
+
+		msleep(20);
+	}
+
+	if (i == SLIPORT_READY_TIMEOUT)
+		status = -1;
+
+	return status;
+}
+
+static int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
+{
+	int status;
+	u32 sliport_status, err, reset_needed;
+	status = lancer_wait_ready(adapter);
+	if (!status) {
+		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+		err = sliport_status & SLIPORT_STATUS_ERR_MASK;
+		reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK;
+		if (err && reset_needed) {
+			iowrite32(SLI_PORT_CONTROL_IP_MASK,
+					adapter->db + SLIPORT_CONTROL_OFFSET);
+
+			/* check adapter has corrected the error */
+			status = lancer_wait_ready(adapter);
+			sliport_status = ioread32(adapter->db +
+							SLIPORT_STATUS_OFFSET);
+			sliport_status &= (SLIPORT_STATUS_ERR_MASK |
+						SLIPORT_STATUS_RN_MASK);
+			if (status || sliport_status)
+				status = -1;
+		} else if (err || reset_needed) {
+			status = -1;
+		}
+	}
+	return status;
+}
+
 static int __devinit be_probe(struct pci_dev *pdev,
 			const struct pci_device_id *pdev_id)
 {
@@ -2918,11 +2978,11 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	adapter->netdev = netdev;
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
-	status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
 	if (!status) {
 		netdev->features |= NETIF_F_HIGHDMA;
 	} else {
-		status = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 		if (status) {
 			dev_err(&pdev->dev, "Could not set PCI DMA Mask\n");
 			goto free_netdev;
@@ -2935,6 +2995,14 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	if (status)
 		goto free_netdev;
 
+	if (lancer_chip(adapter)) {
+		status = lancer_test_and_set_rdy_state(adapter);
+		if (status) {
+			dev_err(&pdev->dev, "Adapter in non recoverable error\n");
+			goto free_netdev;
+		}
+	}
+
 	/* sync up with fw's ready state */
 	if (be_physfn(adapter)) {
 		status = be_cmd_POST(adapter);
@@ -2947,11 +3015,9 @@ static int __devinit be_probe(struct pci_dev *pdev,
 	if (status)
 		goto ctrl_clean;
 
-	if (be_physfn(adapter)) {
-		status = be_cmd_reset_function(adapter);
-		if (status)
-			goto ctrl_clean;
-	}
+	status = be_cmd_reset_function(adapter);
+	if (status)
+		goto ctrl_clean;
 
 	status = be_stats_init(adapter);
 	if (status)
@@ -2975,10 +3041,18 @@ static int __devinit be_probe(struct pci_dev *pdev,
 		goto unsetup;
 	netif_carrier_off(netdev);
 
+	if (be_physfn(adapter) && adapter->sriov_enabled) {
+		status = be_vf_eth_addr_config(adapter);
+		if (status)
+			goto unreg_netdev;
+	}
+
 	dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
 	return 0;
 
+unreg_netdev:
+	unregister_netdev(netdev);
 unsetup:
 	be_clear(adapter);
 msix_disable:
@@ -3005,6 +3079,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
 	struct be_adapter *adapter = pci_get_drvdata(pdev);
 	struct net_device *netdev =  adapter->netdev;
 
+	cancel_delayed_work_sync(&adapter->work);
 	if (adapter->wol)
 		be_setup_wol(adapter, true);
 
@@ -3017,6 +3092,7 @@ static int be_suspend(struct pci_dev *pdev, pm_message_t state)
 	be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc);
 	be_clear(adapter);
 
+	be_msix_disable(adapter);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -3038,6 +3114,7 @@ static int be_resume(struct pci_dev *pdev)
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
 
+	be_msix_enable(adapter);
 	/* tell fw we're ready to fire cmds */
 	status = be_cmd_fw_init(adapter);
 	if (status)
@@ -3053,6 +3130,8 @@ static int be_resume(struct pci_dev *pdev)
 
 	if (adapter->wol)
 		be_setup_wol(adapter, false);
+
+	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
 	return 0;
 }
 
@@ -3064,6 +3143,9 @@ static void be_shutdown(struct pci_dev *pdev)
 	struct be_adapter *adapter = pci_get_drvdata(pdev);
 	struct net_device *netdev =  adapter->netdev;
 
+	if (netif_running(netdev))
+		cancel_delayed_work_sync(&adapter->work);
+
 	netif_device_detach(netdev);
 
 	be_cmd_reset_function(adapter);
diff --git a/drivers/net/bna/bnad.c b/drivers/net/bna/bnad.c
index fad9126..9f356d5 100644
--- a/drivers/net/bna/bnad.c
+++ b/drivers/net/bna/bnad.c
@@ -126,22 +126,22 @@ bnad_free_all_txbufs(struct bnad *bnad,
 		}
 		unmap_array[unmap_cons].skb = NULL;
 
-		pci_unmap_single(bnad->pcidev,
-				 pci_unmap_addr(&unmap_array[unmap_cons],
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
 						dma_addr), skb_headlen(skb),
-						PCI_DMA_TODEVICE);
+						DMA_TO_DEVICE);
 
-		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+		dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
 		if (++unmap_cons >= unmap_q->q_depth)
 			break;
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			pci_unmap_page(bnad->pcidev,
-				       pci_unmap_addr(&unmap_array[unmap_cons],
+			dma_unmap_page(&bnad->pcidev->dev,
+				       dma_unmap_addr(&unmap_array[unmap_cons],
 						      dma_addr),
 				       skb_shinfo(skb)->frags[i].size,
-				       PCI_DMA_TODEVICE);
-			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+				       DMA_TO_DEVICE);
+			dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
 					   0);
 			if (++unmap_cons >= unmap_q->q_depth)
 				break;
@@ -199,23 +199,23 @@ bnad_free_txbufs(struct bnad *bnad,
 		sent_bytes += skb->len;
 		wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
 
-		pci_unmap_single(bnad->pcidev,
-				 pci_unmap_addr(&unmap_array[unmap_cons],
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
 						dma_addr), skb_headlen(skb),
-				 PCI_DMA_TODEVICE);
-		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+				 DMA_TO_DEVICE);
+		dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
 		BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
 
 		prefetch(&unmap_array[unmap_cons + 1]);
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			prefetch(&unmap_array[unmap_cons + 1]);
 
-			pci_unmap_page(bnad->pcidev,
-				       pci_unmap_addr(&unmap_array[unmap_cons],
+			dma_unmap_page(&bnad->pcidev->dev,
+				       dma_unmap_addr(&unmap_array[unmap_cons],
 						      dma_addr),
 				       skb_shinfo(skb)->frags[i].size,
-				       PCI_DMA_TODEVICE);
-			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+				       DMA_TO_DEVICE);
+			dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
 					   0);
 			BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
 		}
@@ -340,19 +340,22 @@ static void
 bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
 {
 	struct bnad_unmap_q *unmap_q;
+	struct bnad_skb_unmap *unmap_array;
 	struct sk_buff *skb;
 	int unmap_cons;
 
 	unmap_q = rcb->unmap_q;
+	unmap_array = unmap_q->unmap_array;
 	for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) {
-		skb = unmap_q->unmap_array[unmap_cons].skb;
+		skb = unmap_array[unmap_cons].skb;
 		if (!skb)
 			continue;
-		unmap_q->unmap_array[unmap_cons].skb = NULL;
-		pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
-					unmap_array[unmap_cons],
-					dma_addr), rcb->rxq->buffer_size,
-					PCI_DMA_FROMDEVICE);
+		unmap_array[unmap_cons].skb = NULL;
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
+						dma_addr),
+				 rcb->rxq->buffer_size,
+				 DMA_FROM_DEVICE);
 		dev_kfree_skb(skb);
 	}
 	bnad_reset_rcb(bnad, rcb);
@@ -391,9 +394,10 @@ bnad_alloc_n_post_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
 		skb->dev = bnad->netdev;
 		skb_reserve(skb, NET_IP_ALIGN);
 		unmap_array[unmap_prod].skb = skb;
-		dma_addr = pci_map_single(bnad->pcidev, skb->data,
-			rcb->rxq->buffer_size, PCI_DMA_FROMDEVICE);
-		pci_unmap_addr_set(&unmap_array[unmap_prod], dma_addr,
+		dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
+					  rcb->rxq->buffer_size,
+					  DMA_FROM_DEVICE);
+		dma_unmap_addr_set(&unmap_array[unmap_prod], dma_addr,
 				   dma_addr);
 		BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
 		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
@@ -434,8 +438,9 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 	struct bna_rcb *rcb = NULL;
 	unsigned int wi_range, packets = 0, wis = 0;
 	struct bnad_unmap_q *unmap_q;
+	struct bnad_skb_unmap *unmap_array;
 	struct sk_buff *skb;
-	u32 flags;
+	u32 flags, unmap_cons;
 	u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
 	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
 
@@ -456,17 +461,17 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget)
 			rcb = ccb->rcb[1];
 
 		unmap_q = rcb->unmap_q;
+		unmap_array = unmap_q->unmap_array;
+		unmap_cons = unmap_q->consumer_index;
 
-		skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
+		skb = unmap_array[unmap_cons].skb;
 		BUG_ON(!(skb));
-		unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
-		pci_unmap_single(bnad->pcidev,
-				 pci_unmap_addr(&unmap_q->
-						unmap_array[unmap_q->
-							    consumer_index],
+		unmap_array[unmap_cons].skb = NULL;
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
 						dma_addr),
-						rcb->rxq->buffer_size,
-						PCI_DMA_FROMDEVICE);
+				 rcb->rxq->buffer_size,
+				 DMA_FROM_DEVICE);
 		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
 
 		/* Should be more efficient ? Performance ? */
@@ -1015,9 +1020,9 @@ bnad_mem_free(struct bnad *bnad,
 			if (mem_info->mem_type == BNA_MEM_T_DMA) {
 				BNA_GET_DMA_ADDR(&(mem_info->mdl[i].dma),
 						dma_pa);
-				pci_free_consistent(bnad->pcidev,
-						mem_info->mdl[i].len,
-						mem_info->mdl[i].kva, dma_pa);
+				dma_free_coherent(&bnad->pcidev->dev,
+						  mem_info->mdl[i].len,
+						  mem_info->mdl[i].kva, dma_pa);
 			} else
 				kfree(mem_info->mdl[i].kva);
 		}
@@ -1047,8 +1052,9 @@ bnad_mem_alloc(struct bnad *bnad,
 		for (i = 0; i < mem_info->num; i++) {
 			mem_info->mdl[i].len = mem_info->len;
 			mem_info->mdl[i].kva =
-				pci_alloc_consistent(bnad->pcidev,
-						mem_info->len, &dma_pa);
+				dma_alloc_coherent(&bnad->pcidev->dev,
+						mem_info->len, &dma_pa,
+						GFP_KERNEL);
 
 			if (mem_info->mdl[i].kva == NULL)
 				goto err_return;
@@ -2600,9 +2606,9 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 	unmap_q->unmap_array[unmap_prod].skb = skb;
 	BUG_ON(!(skb_headlen(skb) <= BFI_TX_MAX_DATA_PER_VECTOR));
 	txqent->vector[vect_id].length = htons(skb_headlen(skb));
-	dma_addr = pci_map_single(bnad->pcidev, skb->data, skb_headlen(skb),
-		PCI_DMA_TODEVICE);
-	pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+	dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
+				  skb_headlen(skb), DMA_TO_DEVICE);
+	dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
 			   dma_addr);
 
 	BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
@@ -2630,11 +2636,9 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 		BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
 		txqent->vector[vect_id].length = htons(size);
-		dma_addr =
-			pci_map_page(bnad->pcidev, frag->page,
-				     frag->page_offset, size,
-				     PCI_DMA_TODEVICE);
-		pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+		dma_addr = dma_map_page(&bnad->pcidev->dev, frag->page,
+					frag->page_offset, size, DMA_TO_DEVICE);
+		dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
 				   dma_addr);
 		BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
 		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
@@ -3022,14 +3026,14 @@ bnad_pci_init(struct bnad *bnad,
 	err = pci_request_regions(pdev, BNAD_NAME);
 	if (err)
 		goto disable_device;
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
-	    !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
+	    !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
 		*using_dac = 1;
 	} else {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 		if (err) {
-			err = pci_set_consistent_dma_mask(pdev,
-						DMA_BIT_MASK(32));
+			err = dma_set_coherent_mask(&pdev->dev,
+						    DMA_BIT_MASK(32));
 			if (err)
 				goto release_regions;
 		}
diff --git a/drivers/net/bna/bnad.h b/drivers/net/bna/bnad.h
index 8b1d515..a89117f 100644
--- a/drivers/net/bna/bnad.h
+++ b/drivers/net/bna/bnad.h
@@ -181,7 +181,7 @@ struct bnad_rx_info {
 /* Unmap queues for Tx / Rx cleanup */
 struct bnad_skb_unmap {
 	struct sk_buff		*skb;
-	DECLARE_PCI_UNMAP_ADDR(dma_addr)
+	DEFINE_DMA_UNMAP_ADDR(dma_addr);
 };
 
 struct bnad_unmap_q {
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 0ba59d5..d1865cc 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -1,6 +1,6 @@
 /* bnx2.c: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004-2010 Broadcom Corporation
+ * Copyright (c) 2004-2011 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -56,11 +56,11 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.0.21"
-#define DRV_MODULE_RELDATE	"Dec 23, 2010"
+#define DRV_MODULE_VERSION	"2.1.6"
+#define DRV_MODULE_RELDATE	"Mar 7, 2011"
 #define FW_MIPS_FILE_06		"bnx2/bnx2-mips-06-6.2.1.fw"
 #define FW_RV2P_FILE_06		"bnx2/bnx2-rv2p-06-6.0.15.fw"
-#define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-6.2.1.fw"
+#define FW_MIPS_FILE_09		"bnx2/bnx2-mips-09-6.2.1a.fw"
 #define FW_RV2P_FILE_09_Ax	"bnx2/bnx2-rv2p-09ax-6.0.17.fw"
 #define FW_RV2P_FILE_09		"bnx2/bnx2-rv2p-09-6.0.17.fw"
 
@@ -435,7 +435,8 @@ bnx2_cnic_stop(struct bnx2 *bp)
 	struct cnic_ctl_info info;
 
 	mutex_lock(&bp->cnic_lock);
-	c_ops = bp->cnic_ops;
+	c_ops = rcu_dereference_protected(bp->cnic_ops,
+					  lockdep_is_held(&bp->cnic_lock));
 	if (c_ops) {
 		info.cmd = CNIC_CTL_STOP_CMD;
 		c_ops->cnic_ctl(bp->cnic_data, &info);
@@ -450,7 +451,8 @@ bnx2_cnic_start(struct bnx2 *bp)
 	struct cnic_ctl_info info;
 
 	mutex_lock(&bp->cnic_lock);
-	c_ops = bp->cnic_ops;
+	c_ops = rcu_dereference_protected(bp->cnic_ops,
+					  lockdep_is_held(&bp->cnic_lock));
 	if (c_ops) {
 		if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
 			struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
@@ -8315,7 +8317,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
 #endif
 };
 
-static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+static void inline vlan_features_add(struct net_device *dev, u32 flags)
 {
 	dev->vlan_features |= flags;
 }
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index f459fb2..6802045 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -1,6 +1,6 @@
 /* bnx2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004-2009 Broadcom Corporation
+ * Copyright (c) 2004-2011 Broadcom Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -6207,6 +6207,8 @@ struct l2_fhdr {
 
 #define BNX2_CP_SCRATCH					0x001a0000
 
+#define BNX2_FW_MAX_ISCSI_CONN				 0x001a0080
+
 
 /*
  *  mcp_reg definition
@@ -6759,7 +6761,7 @@ struct bnx2 {
 	u32		tx_wake_thresh;
 
 #ifdef BCM_CNIC
-	struct cnic_ops		*cnic_ops;
+	struct cnic_ops	__rcu	*cnic_ops;
 	void			*cnic_data;
 #endif
 
diff --git a/drivers/net/bnx2x/bnx2x.h b/drivers/net/bnx2x/bnx2x.h
index 8849699..b7ff87b 100644
--- a/drivers/net/bnx2x/bnx2x.h
+++ b/drivers/net/bnx2x/bnx2x.h
@@ -22,8 +22,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.62.00-6"
-#define DRV_MODULE_RELDATE      "2011/01/30"
+#define DRV_MODULE_VERSION      "1.62.11-0"
+#define DRV_MODULE_RELDATE      "2011/01/31"
 #define BNX2X_BC_VER            0x040200
 
 #define BNX2X_MULTI_QUEUE
@@ -31,7 +31,7 @@
 #define BNX2X_NEW_NAPI
 
 #if defined(CONFIG_DCB)
-#define BCM_DCB
+#define BCM_DCBNL
 #endif
 #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 #define BCM_CNIC 1
@@ -129,6 +129,7 @@ void bnx2x_panic_dump(struct bnx2x *bp);
 #endif
 
 #define bnx2x_mc_addr(ha)      ((ha)->addr)
+#define bnx2x_uc_addr(ha)      ((ha)->addr)
 
 #define U64_LO(x)			(u32)(((u64)(x)) & 0xffffffff)
 #define U64_HI(x)			(u32)(((u64)(x)) >> 32)
@@ -341,6 +342,8 @@ struct bnx2x_fastpath {
 	/* chip independed shortcut into rx_prods_offset memory */
 	u32			ustorm_rx_prods_offset;
 
+	u32			rx_buf_size;
+
 	dma_addr_t		status_blk_mapping;
 
 	struct sw_tx_bd		*tx_buf_ring;
@@ -428,6 +431,10 @@ struct bnx2x_fastpath {
 };
 
 #define bnx2x_fp(bp, nr, var)		(bp->fp[nr].var)
+
+/* Use 2500 as a mini-jumbo MTU for FCoE */
+#define BNX2X_FCOE_MINI_JUMBO_MTU	2500
+
 #ifdef BCM_CNIC
 /* FCoE L2 `fastpath' is right after the eth entries */
 #define FCOE_IDX			BNX2X_NUM_ETH_QUEUES(bp)
@@ -810,6 +817,7 @@ struct bnx2x_slowpath {
 	struct eth_stats_query		fw_stats;
 	struct mac_configuration_cmd	mac_config;
 	struct mac_configuration_cmd	mcast_config;
+	struct mac_configuration_cmd	uc_mac_config;
 	struct client_init_ramrod_data	client_init_data;
 
 	/* used by dmae command executer */
@@ -911,7 +919,6 @@ struct bnx2x {
 	int			tx_ring_size;
 
 	u32			rx_csum;
-	u32			rx_buf_size;
 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
 #define ETH_OVREHEAD		(ETH_HLEN + 8 + 8)
 #define ETH_MIN_PACKET_SIZE		60
@@ -939,7 +946,7 @@ struct bnx2x {
 	struct eth_spe		*spq_prod_bd;
 	struct eth_spe		*spq_last_bd;
 	__le16			*dsb_sp_prod;
-	atomic_t		spq_left; /* serialize spq */
+	atomic_t		cq_spq_left; /* ETH_XXX ramrods credit */
 	/* used to synchronize spq accesses */
 	spinlock_t		spq_lock;
 
@@ -949,6 +956,7 @@ struct bnx2x {
 	u16			eq_prod;
 	u16			eq_cons;
 	__le16			*eq_cons_sb;
+	atomic_t		eq_spq_left; /* COMMON_XXX ramrods credit */
 
 	/* Flags for marking that there is a STAT_QUERY or
 	   SET_MAC ramrod pending */
@@ -976,8 +984,12 @@ struct bnx2x {
 #define MF_FUNC_DIS			0x1000
 #define FCOE_MACS_SET			0x2000
 #define NO_FCOE_FLAG			0x4000
+#define NO_ISCSI_OOO_FLAG		0x8000
+#define NO_ISCSI_FLAG			0x10000
 
 #define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
+#define NO_ISCSI(bp)		((bp)->flags & NO_ISCSI_FLAG)
+#define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
 
 	int			pf_num;	/* absolute PF number */
 	int			pfid;	/* per-path PF number */
@@ -1064,6 +1076,7 @@ struct bnx2x {
 	int			num_queues;
 	int			disable_tpa;
 	int			int_mode;
+	u32			*rx_indir_table;
 
 	struct tstorm_eth_mac_filter_config	mac_filters;
 #define BNX2X_ACCEPT_NONE		0x0000
@@ -1110,7 +1123,7 @@ struct bnx2x {
 #define BNX2X_CNIC_FLAG_MAC_SET		1
 	void			*t2;
 	dma_addr_t		t2_mapping;
-	struct cnic_ops		*cnic_ops;
+	struct cnic_ops	__rcu	*cnic_ops;
 	void			*cnic_data;
 	u32			cnic_tag;
 	struct cnic_eth_dev	cnic_eth_dev;
@@ -1125,13 +1138,12 @@ struct bnx2x {
 	u16			cnic_kwq_pending;
 	u16			cnic_spq_pending;
 	struct mutex		cnic_mutex;
-	u8			iscsi_mac[ETH_ALEN];
 	u8			fip_mac[ETH_ALEN];
 #endif
 
 	int			dmae_ready;
 	/* used to synchronize dmae accesses */
-	struct mutex		dmae_mutex;
+	spinlock_t		dmae_lock;
 
 	/* used to protect the FW mail box */
 	struct mutex		fw_mb_mutex;
@@ -1448,6 +1460,12 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
 void bnx2x_calc_fc_adv(struct bnx2x *bp);
 int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 		  u32 data_hi, u32 data_lo, int common);
+
+/* Clears multicast and unicast list configuration in the chip. */
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp);
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
+void bnx2x_invalidate_uc_list(struct bnx2x *bp);
+
 void bnx2x_update_coalesce(struct bnx2x *bp);
 int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
 
@@ -1787,5 +1805,6 @@ static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
 
 extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
+void bnx2x_push_indir_table(struct bnx2x *bp);
 
 #endif /* bnx2x.h */
diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c
index a71b329..e83ac6d 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/bnx2x/bnx2x_cmn.c
@@ -232,7 +232,7 @@ static void bnx2x_tpa_start(struct bnx2x_fastpath *fp, u16 queue,
 	/* move empty skb from pool to prod and map it */
 	prod_rx_buf->skb = fp->tpa_pool[queue].skb;
 	mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data,
-				 bp->rx_buf_size, DMA_FROM_DEVICE);
+				 fp->rx_buf_size, DMA_FROM_DEVICE);
 	dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
 
 	/* move partial skb from cons to pool (don't unmap yet) */
@@ -367,13 +367,13 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 	struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue];
 	struct sk_buff *skb = rx_buf->skb;
 	/* alloc new skb */
-	struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+	struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 
 	/* Unmap skb in the pool anyway, as we are going to change
 	   pool entry status to BNX2X_TPA_STOP even if new skb allocation
 	   fails. */
 	dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
-			 bp->rx_buf_size, DMA_FROM_DEVICE);
+			 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 	if (likely(new_skb)) {
 		/* fix ip xsum and give it to the stack */
@@ -385,10 +385,10 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
 #ifdef BNX2X_STOP_ON_ERROR
-		if (pad + len > bp->rx_buf_size) {
+		if (pad + len > fp->rx_buf_size) {
 			BNX2X_ERR("skb_put is about to fail...  "
 				  "pad %d  len %d  rx_buf_size %d\n",
-				  pad, len, bp->rx_buf_size);
+				  pad, len, fp->rx_buf_size);
 			bnx2x_panic();
 			return;
 		}
@@ -618,7 +618,7 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
 			if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
 				dma_unmap_single(&bp->pdev->dev,
 					dma_unmap_addr(rx_buf, mapping),
-						 bp->rx_buf_size,
+						 fp->rx_buf_size,
 						 DMA_FROM_DEVICE);
 				skb_reserve(skb, pad);
 				skb_put(skb, len);
@@ -858,19 +858,16 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
 	u16 ring_prod;
 	int i, j;
 
-	bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
-		IP_HEADER_ALIGNMENT_PADDING;
-
-	DP(NETIF_MSG_IFUP,
-	   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size);
-
 	for_each_rx_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
+		DP(NETIF_MSG_IFUP,
+		   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
+
 		if (!fp->disable_tpa) {
 			for (i = 0; i < max_agg_queues; i++) {
 				fp->tpa_pool[i].skb =
-				   netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+				   netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 				if (!fp->tpa_pool[i].skb) {
 					BNX2X_ERR("Failed to allocate TPA "
 						  "skb pool for queue[%d] - "
@@ -978,7 +975,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 
 			dma_unmap_single(&bp->pdev->dev,
 					 dma_unmap_addr(rx_buf, mapping),
-					 bp->rx_buf_size, DMA_FROM_DEVICE);
+					 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 			rx_buf->skb = NULL;
 			dev_kfree_skb(skb);
@@ -1303,6 +1300,31 @@ static inline int bnx2x_set_real_num_queues(struct bnx2x *bp)
 	return rc;
 }
 
+static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_queue(bp, i) {
+		struct bnx2x_fastpath *fp = &bp->fp[i];
+
+		/* Always use a mini-jumbo MTU for the FCoE L2 ring */
+		if (IS_FCOE_IDX(i))
+			/*
+			 * Although there are no IP frames expected to arrive to
+			 * this ring we still want to add an
+			 * IP_HEADER_ALIGNMENT_PADDING to prevent a buffer
+			 * overrun attack.
+			 */
+			fp->rx_buf_size =
+				BNX2X_FCOE_MINI_JUMBO_MTU + ETH_OVREHEAD +
+				BNX2X_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+		else
+			fp->rx_buf_size =
+				bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
+				IP_HEADER_ALIGNMENT_PADDING;
+	}
+}
+
 /* must be called with rtnl_lock */
 int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
@@ -1326,6 +1348,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	/* must be called before memory allocation and HW init */
 	bnx2x_ilt_set_info(bp);
 
+	/* Set the receive queues buffer size */
+	bnx2x_set_rx_buf_size(bp);
+
 	if (bnx2x_alloc_mem(bp))
 		return -ENOMEM;
 
@@ -1481,6 +1506,15 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
 	bnx2x_set_eth_mac(bp, 1);
 
+	/* Clear MC configuration */
+	if (CHIP_IS_E1(bp))
+		bnx2x_invalidate_e1_mc_list(bp);
+	else
+		bnx2x_invalidate_e1h_mc_list(bp);
+
+	/* Clear UC lists configuration */
+	bnx2x_invalidate_uc_list(bp);
+
 	if (bp->pending_max) {
 		bnx2x_update_max_mf_config(bp, bp->pending_max);
 		bp->pending_max = 0;
@@ -1489,25 +1523,23 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 	if (bp->port.pmf)
 		bnx2x_initial_phy_init(bp, load_mode);
 
+	/* Initialize Rx filtering */
+	bnx2x_set_rx_mode(bp->dev);
+
 	/* Start fast path */
 	switch (load_mode) {
 	case LOAD_NORMAL:
 		/* Tx queue should be only reenabled */
 		netif_tx_wake_all_queues(bp->dev);
 		/* Initialize the receive filter. */
-		bnx2x_set_rx_mode(bp->dev);
 		break;
 
 	case LOAD_OPEN:
 		netif_tx_start_all_queues(bp->dev);
 		smp_mb__after_clear_bit();
-		/* Initialize the receive filter. */
-		bnx2x_set_rx_mode(bp->dev);
 		break;
 
 	case LOAD_DIAG:
-		/* Initialize the receive filter. */
-		bnx2x_set_rx_mode(bp->dev);
 		bp->state = BNX2X_STATE_DIAG;
 		break;
 
diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h
index 85ea7f2..ef37b98 100644
--- a/drivers/net/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/bnx2x/bnx2x_cmn.h
@@ -831,11 +831,11 @@ static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
 	struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
 	dma_addr_t mapping;
 
-	skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+	skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 	if (unlikely(skb == NULL))
 		return -ENOMEM;
 
-	mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_size,
+	mapping = dma_map_single(&bp->pdev->dev, skb->data, fp->rx_buf_size,
 				 DMA_FROM_DEVICE);
 	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
 		dev_kfree_skb(skb);
@@ -901,7 +901,7 @@ static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
 		if (fp->tpa_state[i] == BNX2X_TPA_START)
 			dma_unmap_single(&bp->pdev->dev,
 					 dma_unmap_addr(rx_buf, mapping),
-					 bp->rx_buf_size, DMA_FROM_DEVICE);
+					 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 		dev_kfree_skb(skb);
 		rx_buf->skb = NULL;
diff --git a/drivers/net/bnx2x/bnx2x_dcb.c b/drivers/net/bnx2x/bnx2x_dcb.c
index fb60021..9a24d79 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.c
+++ b/drivers/net/bnx2x/bnx2x_dcb.c
@@ -19,6 +19,9 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#ifdef BCM_DCBNL
+#include <linux/dcbnl.h>
+#endif
 
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
@@ -508,13 +511,75 @@ static int bnx2x_dcbx_read_shmem_neg_results(struct bnx2x *bp)
 	return 0;
 }
 
+
+#ifdef BCM_DCBNL
+static inline
+u8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent)
+{
+	u8 pri;
+
+	/* Choose the highest priority */
+	for (pri = MAX_PFC_PRIORITIES - 1; pri > 0; pri--)
+		if (ent->pri_bitmap & (1 << pri))
+			break;
+	return pri;
+}
+
+static inline
+u8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
+{
+	return ((ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) ==
+		DCBX_APP_SF_PORT) ? DCB_APP_IDTYPE_PORTNUM :
+		DCB_APP_IDTYPE_ETHTYPE;
+}
+
+static inline
+void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
+{
+	int i;
+	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
+		bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
+							~DCBX_APP_ENTRY_VALID;
+}
+
+int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
+{
+	int i, err = 0;
+
+	for (i = 0; i < DCBX_MAX_APP_PROTOCOL && err == 0; i++) {
+		struct dcbx_app_priority_entry *ent =
+			&bp->dcbx_local_feat.app.app_pri_tbl[i];
+
+		if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
+			u8 up = bnx2x_dcbx_dcbnl_app_up(ent);
+
+			/* avoid invalid user-priority */
+			if (up) {
+				struct dcb_app app;
+				app.selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
+				app.protocol = ent->app_id;
+				app.priority = delall ? 0 : up;
+				err = dcb_setapp(bp->dev, &app);
+			}
+		}
+	}
+	return err;
+}
+#endif
+
 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
 {
 	switch (state) {
 	case BNX2X_DCBX_STATE_NEG_RECEIVED:
 		{
 			DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
-
+#ifdef BCM_DCBNL
+			/**
+			 * Delete app tlvs from dcbnl before reading new
+			 * negotiation results
+			 */
+			bnx2x_dcbnl_update_applist(bp, true);
+#endif
 			/* Read neg results if dcbx is in the FW */
 			if (bnx2x_dcbx_read_shmem_neg_results(bp))
 				return;
@@ -526,10 +591,24 @@ void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
 						 bp->dcbx_error);
 
 			if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
+#ifdef BCM_DCBNL
+				/**
+				 * Add new app tlvs to dcbnl
+				 */
+				bnx2x_dcbnl_update_applist(bp, false);
+#endif
 				bnx2x_dcbx_stop_hw_tx(bp);
 				return;
 			}
 			/* fall through */
+#ifdef BCM_DCBNL
+			/**
+			 * Invalidate the local app tlvs if they are not added
+			 * to the dcbnl app list to avoid deleting them from
+			 * the list later on
+			 */
+			bnx2x_dcbx_invalidate_local_apps(bp);
+#endif
 		}
 	case BNX2X_DCBX_STATE_TX_PAUSED:
 		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
@@ -1505,8 +1584,7 @@ static void bnx2x_pfc_fw_struct_e2(struct bnx2x *bp)
 	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
 }
 /* DCB netlink */
-#ifdef BCM_DCB
-#include <linux/dcbnl.h>
+#ifdef BCM_DCBNL
 
 #define BNX2X_DCBX_CAPS		(DCB_CAP_DCBX_LLD_MANAGED | \
 				DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
@@ -1816,32 +1894,6 @@ static void bnx2x_dcbnl_set_pfc_state(struct net_device *netdev, u8 state)
 	bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
 }
 
-static bool bnx2x_app_is_equal(struct dcbx_app_priority_entry *app_ent,
-			       u8 idtype, u16 idval)
-{
-	if (!(app_ent->appBitfield & DCBX_APP_ENTRY_VALID))
-		return false;
-
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-		if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
-			DCBX_APP_SF_ETH_TYPE)
-			return false;
-		break;
-	case DCB_APP_IDTYPE_PORTNUM:
-		if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
-			DCBX_APP_SF_PORT)
-			return false;
-		break;
-	default:
-		return false;
-	}
-	if (app_ent->app_id != idval)
-		return false;
-
-	return true;
-}
-
 static void bnx2x_admin_app_set_ent(
 	struct bnx2x_admin_priority_app_table *app_ent,
 	u8 idtype, u16 idval, u8 up)
@@ -1943,30 +1995,6 @@ static u8 bnx2x_dcbnl_set_app_up(struct net_device *netdev, u8 idtype,
 	return bnx2x_set_admin_app_up(bp, idtype, idval, up);
 }
 
-static u8 bnx2x_dcbnl_get_app_up(struct net_device *netdev, u8 idtype,
-				 u16 idval)
-{
-	int i;
-	u8 up = 0;
-
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "app_type %d, app_id 0x%x\n", idtype, idval);
-
-	/* iterate over the app entries looking for idtype and idval */
-	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
-		if (bnx2x_app_is_equal(&bp->dcbx_local_feat.app.app_pri_tbl[i],
-				       idtype, idval))
-			break;
-
-	if (i < DCBX_MAX_APP_PROTOCOL)
-		/* if found return up */
-		up = bp->dcbx_local_feat.app.app_pri_tbl[i].pri_bitmap;
-	else
-		DP(NETIF_MSG_LINK, "app not found\n");
-
-	return up;
-}
-
 static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
 {
 	struct bnx2x *bp = netdev_priv(netdev);
@@ -2107,7 +2135,6 @@ const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
 	.setnumtcs      = bnx2x_dcbnl_set_numtcs,
 	.getpfcstate    = bnx2x_dcbnl_get_pfc_state,
 	.setpfcstate    = bnx2x_dcbnl_set_pfc_state,
-	.getapp         = bnx2x_dcbnl_get_app_up,
 	.setapp         = bnx2x_dcbnl_set_app_up,
 	.getdcbx        = bnx2x_dcbnl_get_dcbx,
 	.setdcbx        = bnx2x_dcbnl_set_dcbx,
@@ -2115,4 +2142,4 @@ const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops = {
 	.setfeatcfg     = bnx2x_dcbnl_set_featcfg,
 };
 
-#endif /* BCM_DCB */
+#endif /* BCM_DCBNL */
diff --git a/drivers/net/bnx2x/bnx2x_dcb.h b/drivers/net/bnx2x/bnx2x_dcb.h
index f650f98..71b8eda 100644
--- a/drivers/net/bnx2x/bnx2x_dcb.h
+++ b/drivers/net/bnx2x/bnx2x_dcb.h
@@ -189,8 +189,9 @@ enum {
 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
 
 /* DCB netlink */
-#ifdef BCM_DCB
+#ifdef BCM_DCBNL
 extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
-#endif /* BCM_DCB */
+int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
+#endif /* BCM_DCBNL */
 
 #endif /* BNX2X_DCB_H */
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c
index 7e92f9d..f505015 100644
--- a/drivers/net/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/bnx2x/bnx2x_ethtool.c
@@ -1617,7 +1617,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
 	/* prepare the loopback packet */
 	pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ?
 		     bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN);
-	skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+	skb = netdev_alloc_skb(bp->dev, fp_rx->rx_buf_size);
 	if (!skb) {
 		rc = -ENOMEM;
 		goto test_loopback_exit;
@@ -2131,6 +2131,59 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
 	return 0;
 }
 
+static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
+			   void *rules __always_unused)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	switch (info->cmd) {
+	case ETHTOOL_GRXRINGS:
+		info->data = BNX2X_NUM_ETH_QUEUES(bp);
+		return 0;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int bnx2x_get_rxfh_indir(struct net_device *dev,
+				struct ethtool_rxfh_indir *indir)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	size_t copy_size =
+		min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
+
+	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+		return -EOPNOTSUPP;
+
+	indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
+	memcpy(indir->ring_index, bp->rx_indir_table,
+	       copy_size * sizeof(bp->rx_indir_table[0]));
+	return 0;
+}
+
+static int bnx2x_set_rxfh_indir(struct net_device *dev,
+				const struct ethtool_rxfh_indir *indir)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	size_t i;
+
+	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+		return -EOPNOTSUPP;
+
+	/* Validate size and indices */
+	if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
+		return -EINVAL;
+	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+		if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp))
+			return -EINVAL;
+
+	memcpy(bp->rx_indir_table, indir->ring_index,
+	       indir->size * sizeof(bp->rx_indir_table[0]));
+	bnx2x_push_indir_table(bp);
+	return 0;
+}
+
 static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_settings		= bnx2x_get_settings,
 	.set_settings		= bnx2x_set_settings,
@@ -2167,6 +2220,9 @@ static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_strings		= bnx2x_get_strings,
 	.phys_id		= bnx2x_phys_id,
 	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
+	.get_rxnfc		= bnx2x_get_rxnfc,
+	.get_rxfh_indir		= bnx2x_get_rxfh_indir,
+	.set_rxfh_indir		= bnx2x_set_rxfh_indir,
 };
 
 void bnx2x_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h
index 548f563..be503cc 100644
--- a/drivers/net/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/bnx2x/bnx2x_hsi.h
@@ -11,20 +11,27 @@
 
 #include "bnx2x_fw_defs.h"
 
+#define FW_ENCODE_32BIT_PATTERN		0x1e1e1e1e
+
 struct license_key {
 	u32 reserved[6];
 
-#if defined(__BIG_ENDIAN)
-	u16 max_iscsi_init_conn;
-	u16 max_iscsi_trgt_conn;
-#elif defined(__LITTLE_ENDIAN)
-	u16 max_iscsi_trgt_conn;
-	u16 max_iscsi_init_conn;
-#endif
+	u32 max_iscsi_conn;
+#define BNX2X_MAX_ISCSI_TRGT_CONN_MASK	0xFFFF
+#define BNX2X_MAX_ISCSI_TRGT_CONN_SHIFT	0
+#define BNX2X_MAX_ISCSI_INIT_CONN_MASK	0xFFFF0000
+#define BNX2X_MAX_ISCSI_INIT_CONN_SHIFT	16
 
-	u32 reserved_a[6];
-};
+	u32 reserved_a;
+
+	u32 max_fcoe_conn;
+#define BNX2X_MAX_FCOE_TRGT_CONN_MASK	0xFFFF
+#define BNX2X_MAX_FCOE_TRGT_CONN_SHIFT	0
+#define BNX2X_MAX_FCOE_INIT_CONN_MASK	0xFFFF0000
+#define BNX2X_MAX_FCOE_INIT_CONN_SHIFT	16
 
+	u32 reserved_b[4];
+};
 
 #define PORT_0				0
 #define PORT_1				1
@@ -237,8 +244,26 @@ struct port_hw_cfg {			    /* port 0: 0x12c  port 1: 0x2bc */
 #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT	      16
 
 
-	u32 Reserved0[16];				    /* 0x158 */
-
+	u32 Reserved0[3];				    /* 0x158 */
+	/*	Controls the TX laser of the SFP+ module */
+	u32 sfp_ctrl;					/* 0x164 */
+#define PORT_HW_CFG_TX_LASER_MASK			      0x000000FF
+#define PORT_HW_CFG_TX_LASER_SHIFT			      0
+#define PORT_HW_CFG_TX_LASER_MDIO			      0x00000000
+#define PORT_HW_CFG_TX_LASER_GPIO0			      0x00000001
+#define PORT_HW_CFG_TX_LASER_GPIO1			      0x00000002
+#define PORT_HW_CFG_TX_LASER_GPIO2			      0x00000003
+#define PORT_HW_CFG_TX_LASER_GPIO3			      0x00000004
+
+    /*	Controls the fault module LED of the SFP+ */
+#define PORT_HW_CFG_FAULT_MODULE_LED_MASK		      0x0000FF00
+#define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT		      8
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0		      0x00000000
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1		      0x00000100
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2		      0x00000200
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3		      0x00000300
+#define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED		      0x00000400
+	u32 Reserved01[12];				    /* 0x158 */
 	/*  for external PHY, or forced mode or during AN */
 	u16 xgxs_config_rx[4];				    /* 0x198 */
 
@@ -246,12 +271,78 @@ struct port_hw_cfg {			    /* port 0: 0x12c  port 1: 0x2bc */
 
 	u32 Reserved1[56];				    /* 0x1A8 */
 	u32 default_cfg;				    /* 0x288 */
+#define PORT_HW_CFG_GPIO0_CONFIG_MASK			      0x00000003
+#define PORT_HW_CFG_GPIO0_CONFIG_SHIFT			      0
+#define PORT_HW_CFG_GPIO0_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO0_CONFIG_LOW			      0x00000001
+#define PORT_HW_CFG_GPIO0_CONFIG_HIGH			      0x00000002
+#define PORT_HW_CFG_GPIO0_CONFIG_INPUT			      0x00000003
+
+#define PORT_HW_CFG_GPIO1_CONFIG_MASK			      0x0000000C
+#define PORT_HW_CFG_GPIO1_CONFIG_SHIFT			      2
+#define PORT_HW_CFG_GPIO1_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO1_CONFIG_LOW			      0x00000004
+#define PORT_HW_CFG_GPIO1_CONFIG_HIGH			      0x00000008
+#define PORT_HW_CFG_GPIO1_CONFIG_INPUT			      0x0000000c
+
+#define PORT_HW_CFG_GPIO2_CONFIG_MASK			      0x00000030
+#define PORT_HW_CFG_GPIO2_CONFIG_SHIFT			      4
+#define PORT_HW_CFG_GPIO2_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO2_CONFIG_LOW			      0x00000010
+#define PORT_HW_CFG_GPIO2_CONFIG_HIGH			      0x00000020
+#define PORT_HW_CFG_GPIO2_CONFIG_INPUT			      0x00000030
+
+#define PORT_HW_CFG_GPIO3_CONFIG_MASK			      0x000000C0
+#define PORT_HW_CFG_GPIO3_CONFIG_SHIFT			      6
+#define PORT_HW_CFG_GPIO3_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO3_CONFIG_LOW			      0x00000040
+#define PORT_HW_CFG_GPIO3_CONFIG_HIGH			      0x00000080
+#define PORT_HW_CFG_GPIO3_CONFIG_INPUT			      0x000000c0
+
+	/*
+	 * When KR link is required to be set to force which is not
+	 * KR-compliant, this parameter determine what is the trigger for it.
+	 * When GPIO is selected, low input will force the speed. Currently
+	 * default speed is 1G. In the future, it may be widen to select the
+	 * forced speed in with another parameter. Note when force-1G is
+	 * enabled, it override option 56: Link Speed option.
+	 */
+#define PORT_HW_CFG_FORCE_KR_ENABLER_MASK		      0x00000F00
+#define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT		      8
+#define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED		      0x00000000
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0		      0x00000100
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0		      0x00000200
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0		      0x00000300
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0		      0x00000400
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1		      0x00000500
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1		      0x00000600
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1		      0x00000700
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1		      0x00000800
+#define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED		      0x00000900
+    /*	Enable to determine with which GPIO to reset the external phy */
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK		      0x000F0000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT		      16
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE		      0x00000000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0		      0x00010000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0		      0x00020000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0		      0x00030000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0		      0x00040000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1		      0x00050000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1		      0x00060000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1		      0x00070000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1		      0x00080000
 	/*  Enable BAM on KR */
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK		      0x00100000
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT		      20
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED		      0x00000000
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED		      0x00100000
 
+	/*  Enable Common Mode Sense */
+#define PORT_HW_CFG_ENABLE_CMS_MASK			      0x00200000
+#define PORT_HW_CFG_ENABLE_CMS_SHIFT			      21
+#define PORT_HW_CFG_ENABLE_CMS_DISABLED			      0x00000000
+#define PORT_HW_CFG_ENABLE_CMS_ENABLED			      0x00200000
+
 	u32 speed_capability_mask2;			    /* 0x28C */
 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK		      0x0000FFFF
 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT		      0
@@ -381,6 +472,7 @@ struct port_hw_cfg {			    /* port 0: 0x12c  port 1: 0x2bc */
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727	    0x00000900
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC   0x00000a00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823	    0x00000b00
+#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833	    0x00000d00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE	    0x0000fd00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN	    0x0000ff00
 
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c
index dd1210f..f2f367d 100644
--- a/drivers/net/bnx2x/bnx2x_link.c
+++ b/drivers/net/bnx2x/bnx2x_link.c
@@ -1,4 +1,4 @@
-/* Copyright 2008-2009 Broadcom Corporation
+/* Copyright 2008-2011 Broadcom Corporation
  *
  * Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -28,12 +28,13 @@
 
 /********************************************************/
 #define ETH_HLEN			14
-#define ETH_OVREHEAD		(ETH_HLEN + 8 + 8)/* 16 for CRC + VLAN + LLC */
+/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
+#define ETH_OVREHEAD			(ETH_HLEN + 8 + 8)
 #define ETH_MIN_PACKET_SIZE		60
 #define ETH_MAX_PACKET_SIZE		1500
 #define ETH_MAX_JUMBO_PACKET_SIZE	9600
 #define MDIO_ACCESS_TIMEOUT		1000
-#define BMAC_CONTROL_RX_ENABLE	2
+#define BMAC_CONTROL_RX_ENABLE		2
 
 /***********************************************************/
 /*			Shortcut definitions		   */
@@ -79,7 +80,7 @@
 
 #define AUTONEG_CL37		SHARED_HW_CFG_AN_ENABLE_CL37
 #define AUTONEG_CL73		SHARED_HW_CFG_AN_ENABLE_CL73
-#define AUTONEG_BAM 		SHARED_HW_CFG_AN_ENABLE_BAM
+#define AUTONEG_BAM		SHARED_HW_CFG_AN_ENABLE_BAM
 #define AUTONEG_PARALLEL \
 				SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
 #define AUTONEG_SGMII_FIBER_AUTODET \
@@ -112,10 +113,10 @@
 #define GP_STATUS_10G_KX4 \
 			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
 
-#define LINK_10THD			LINK_STATUS_SPEED_AND_DUPLEX_10THD
-#define LINK_10TFD			LINK_STATUS_SPEED_AND_DUPLEX_10TFD
+#define LINK_10THD		LINK_STATUS_SPEED_AND_DUPLEX_10THD
+#define LINK_10TFD		LINK_STATUS_SPEED_AND_DUPLEX_10TFD
 #define LINK_100TXHD		LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
-#define LINK_100T4			LINK_STATUS_SPEED_AND_DUPLEX_100T4
+#define LINK_100T4		LINK_STATUS_SPEED_AND_DUPLEX_100T4
 #define LINK_100TXFD		LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
 #define LINK_1000THD		LINK_STATUS_SPEED_AND_DUPLEX_1000THD
 #define LINK_1000TFD		LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
@@ -123,18 +124,18 @@
 #define LINK_2500THD		LINK_STATUS_SPEED_AND_DUPLEX_2500THD
 #define LINK_2500TFD		LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
 #define LINK_2500XFD		LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
-#define LINK_10GTFD			LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
-#define LINK_10GXFD			LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
-#define LINK_12GTFD			LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
-#define LINK_12GXFD			LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
+#define LINK_10GTFD		LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
+#define LINK_10GXFD		LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
+#define LINK_12GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
+#define LINK_12GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
 #define LINK_12_5GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
 #define LINK_12_5GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
-#define LINK_13GTFD			LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
-#define LINK_13GXFD			LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
-#define LINK_15GTFD			LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
-#define LINK_15GXFD			LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
-#define LINK_16GTFD			LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
-#define LINK_16GXFD			LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
+#define LINK_13GTFD		LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
+#define LINK_13GXFD		LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
+#define LINK_15GTFD		LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
+#define LINK_15GXFD		LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
+#define LINK_16GTFD		LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
+#define LINK_16GXFD		LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
 
 #define PHY_XGXS_FLAG			0x1
 #define PHY_SGMII_FLAG			0x2
@@ -142,7 +143,7 @@
 
 /* */
 #define SFP_EEPROM_CON_TYPE_ADDR		0x2
-	#define SFP_EEPROM_CON_TYPE_VAL_LC 		0x7
+	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7
 	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21
 
 
@@ -153,15 +154,15 @@
 
 #define SFP_EEPROM_FC_TX_TECH_ADDR		0x8
 	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
-	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE	 0x8
+	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE  0x8
 
-#define SFP_EEPROM_OPTIONS_ADDR 		0x40
+#define SFP_EEPROM_OPTIONS_ADDR			0x40
 	#define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
-#define SFP_EEPROM_OPTIONS_SIZE 		2
+#define SFP_EEPROM_OPTIONS_SIZE			2
 
-#define EDC_MODE_LINEAR	 			0x0022
-#define EDC_MODE_LIMITING	 			0x0044
-#define EDC_MODE_PASSIVE_DAC 			0x0055
+#define EDC_MODE_LINEAR				0x0022
+#define EDC_MODE_LIMITING				0x0044
+#define EDC_MODE_PASSIVE_DAC			0x0055
 
 
 #define ETS_BW_LIMIT_CREDIT_UPPER_BOUND		(0x5000)
@@ -170,24 +171,18 @@
 /*                     INTERFACE                          */
 /**********************************************************/
 
-#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+#define CL22_WR_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
 	bnx2x_cl45_write(_bp, _phy, \
 		(_phy)->def_md_devad, \
 		(_bank + (_addr & 0xf)), \
 		_val)
 
-#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+#define CL22_RD_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
 	bnx2x_cl45_read(_bp, _phy, \
 		(_phy)->def_md_devad, \
 		(_bank + (_addr & 0xf)), \
 		_val)
 
-static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
-			  u8 devad, u16 reg, u16 *ret_val);
-
-static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-			   u8 devad, u16 reg, u16 val);
-
 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
 {
 	u32 val = REG_RD(bp, reg);
@@ -216,7 +211,7 @@ void bnx2x_ets_disabled(struct link_params *params)
 
 	DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
 
-	/**
+	/*
 	 * mapping between entry  priority to client number (0,1,2 -debug and
 	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
 	 * 3bits client num.
@@ -225,7 +220,7 @@ void bnx2x_ets_disabled(struct link_params *params)
 	 */
 
 	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
-	/**
+	/*
 	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
 	 * as strict.  Bits 0,1,2 - debug and management entries, 3 -
 	 * COS0 entry, 4 - COS1 entry.
@@ -237,12 +232,12 @@ void bnx2x_ets_disabled(struct link_params *params)
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
 	/* defines which entries (clients) are subjected to WFQ arbitration */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
-	/**
-	* For strict priority entries defines the number of consecutive
-	* slots for the highest priority.
-	*/
+	/*
+	 * For strict priority entries defines the number of consecutive
+	 * slots for the highest priority.
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
-	/**
+	/*
 	 * mapping between the CREDIT_WEIGHT registers and actual client
 	 * numbers
 	 */
@@ -255,7 +250,7 @@ void bnx2x_ets_disabled(struct link_params *params)
 	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
 	/* ETS mode disable */
 	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
-	/**
+	/*
 	 * If ETS mode is enabled (there is no strict priority) defines a WFQ
 	 * weight for COS0/COS1.
 	 */
@@ -268,24 +263,24 @@ void bnx2x_ets_disabled(struct link_params *params)
 	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
 }
 
-void bnx2x_ets_bw_limit_common(const struct link_params *params)
+static void bnx2x_ets_bw_limit_common(const struct link_params *params)
 {
 	/* ETS disabled configuration */
 	struct bnx2x *bp = params->bp;
 	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
-	/**
-	* defines which entries (clients) are subjected to WFQ arbitration
-	* COS0 0x8
-	* COS1 0x10
-	*/
+	/*
+	 * defines which entries (clients) are subjected to WFQ arbitration
+	 * COS0 0x8
+	 * COS1 0x10
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
-	/**
-	* mapping between the ARB_CREDIT_WEIGHT registers and actual
-	* client numbers (WEIGHT_0 does not actually have to represent
-	* client 0)
-	*    PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
-	*  cos1-001     cos0-000     dbg1-100     dbg0-011     MCP-010
-	*/
+	/*
+	 * mapping between the ARB_CREDIT_WEIGHT registers and actual
+	 * client numbers (WEIGHT_0 does not actually have to represent
+	 * client 0)
+	 *    PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	 *  cos1-001     cos0-000     dbg1-100     dbg0-011     MCP-010
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
 
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
@@ -298,14 +293,14 @@ void bnx2x_ets_bw_limit_common(const struct link_params *params)
 
 	/* Defines the number of consecutive slots for the strict priority */
 	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
-	/**
-	* Bitmap of 5bits length. Each bit specifies whether the entry behaves
-	* as strict.  Bits 0,1,2 - debug and management entries, 3 - COS0
-	* entry, 4 - COS1 entry.
-	* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
-	* bit4   bit3	  bit2     bit1	   bit0
-	* MCP and debug are strict
-	*/
+	/*
+	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+	 * as strict.  Bits 0,1,2 - debug and management entries, 3 - COS0
+	 * entry, 4 - COS1 entry.
+	 * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
+	 * bit4   bit3	  bit2     bit1	   bit0
+	 * MCP and debug are strict
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
 
 	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
@@ -329,8 +324,7 @@ void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
 	if ((0 == total_bw) ||
 	    (0 == cos0_bw) ||
 	    (0 == cos1_bw)) {
-		DP(NETIF_MSG_LINK,
-		   "bnx2x_ets_bw_limit: Total BW can't be zero\n");
+		DP(NETIF_MSG_LINK, "Total BW can't be zero\n");
 		return;
 	}
 
@@ -355,7 +349,7 @@ u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 	u32 val	= 0;
 
 	DP(NETIF_MSG_LINK, "ETS enabled strict configuration\n");
-	/**
+	/*
 	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
 	 * as strict.  Bits 0,1,2 - debug and management entries,
 	 * 3 - COS0 entry, 4 - COS1 entry.
@@ -364,7 +358,7 @@ u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 	 * MCP and debug are strict
 	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
-	/**
+	/*
 	 * For strict priority entries defines the number of consecutive slots
 	 * for the highest priority.
 	 */
@@ -377,14 +371,14 @@ u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos)
 	/* Defines the number of consecutive slots for the strict priority */
 	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
 
-	/**
-	* mapping between entry  priority to client number (0,1,2 -debug and
-	* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
-	* 3bits client num.
-	*   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
-	* dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
-	* dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
-	*/
+	/*
+	 * mapping between entry  priority to client number (0,1,2 -debug and
+	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
+	 * 3bits client num.
+	 *   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	 * dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
+	 * dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
+	 */
 	val = (0 == strict_cos) ? 0x2318 : 0x22E0;
 	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
 
@@ -471,7 +465,7 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 /*			MAC/PBF section				  */
 /******************************************************************/
 static void bnx2x_emac_init(struct link_params *params,
-			   struct link_vars *vars)
+			    struct link_vars *vars)
 {
 	/* reset and unreset the emac core */
 	struct bnx2x *bp = params->bp;
@@ -481,10 +475,10 @@ static void bnx2x_emac_init(struct link_params *params,
 	u16 timeout;
 
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-		   (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
 	udelay(5);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-		   (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
 
 	/* init emac - use read-modify-write */
 	/* self clear reset */
@@ -515,7 +509,7 @@ static void bnx2x_emac_init(struct link_params *params,
 }
 
 static u8 bnx2x_emac_enable(struct link_params *params,
-			  struct link_vars *vars, u8 lb)
+			    struct link_vars *vars, u8 lb)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -527,55 +521,33 @@ static u8 bnx2x_emac_enable(struct link_params *params,
 	/* enable emac and not bmac */
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
 
-	/* for paladium */
-	if (CHIP_REV_IS_EMUL(bp)) {
-		/* Use lane 1 (of lanes 0-3) */
-		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
-			    port*4, 1);
-	}
-	/* for fpga */
-	else
-
-	if (CHIP_REV_IS_FPGA(bp)) {
-		/* Use lane 1 (of lanes 0-3) */
-		DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
-
-		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
-			    0);
-	} else
 	/* ASIC */
 	if (vars->phy_flags & PHY_XGXS_FLAG) {
 		u32 ser_lane = ((params->lane_config &
-			    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-			    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+				 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
+				PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 
 		DP(NETIF_MSG_LINK, "XGXS\n");
 		/* select the master lanes (out of 0-3) */
-		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
-			   port*4, ser_lane);
+		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, ser_lane);
 		/* select XGXS */
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
-			   port*4, 1);
+		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
 
 	} else { /* SerDes */
 		DP(NETIF_MSG_LINK, "SerDes\n");
 		/* select SerDes */
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
-			   port*4, 0);
+		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0);
 	}
 
 	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
-		    EMAC_RX_MODE_RESET);
+		      EMAC_RX_MODE_RESET);
 	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
-		    EMAC_TX_MODE_RESET);
+		      EMAC_TX_MODE_RESET);
 
 	if (CHIP_REV_IS_SLOW(bp)) {
 		/* config GMII mode */
 		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-		EMAC_WR(bp, EMAC_REG_EMAC_MODE,
-			    (val | EMAC_MODE_PORT_GMII));
+		EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_PORT_GMII));
 	} else { /* ASIC */
 		/* pause enable/disable */
 		bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
@@ -605,14 +577,14 @@ static u8 bnx2x_emac_enable(struct link_params *params,
 	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
 	val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
 
-	/**
-	* Setting this bit causes MAC control frames (except for pause
-	* frames) to be passed on for processing. This setting has no
-	* affect on the operation of the pause frames. This bit effects
-	* all packets regardless of RX Parser packet sorting logic.
-	* Turn the PFC off to make sure we are in Xon state before
-	* enabling it.
-	*/
+	/*
+	 * Setting this bit causes MAC control frames (except for pause
+	 * frames) to be passed on for processing. This setting has no
+	 * affect on the operation of the pause frames. This bit effects
+	 * all packets regardless of RX Parser packet sorting logic.
+	 * Turn the PFC off to make sure we are in Xon state before
+	 * enabling it.
+	 */
 	EMAC_WR(bp, EMAC_REG_RX_PFC_MODE, 0);
 	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
 		DP(NETIF_MSG_LINK, "PFC is enabled\n");
@@ -666,16 +638,7 @@ static u8 bnx2x_emac_enable(struct link_params *params,
 	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
 
-	if (CHIP_REV_IS_EMUL(bp)) {
-		/* take the BigMac out of reset */
-		REG_WR(bp,
-			   GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-			   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
-
-		/* enable access for bmac registers */
-		REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
-	} else
-		REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
+	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
 
 	vars->mac_type = MAC_TYPE_EMAC;
 	return 0;
@@ -731,8 +694,7 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
 		val |= (1<<5);
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL, wb_data, 2);
 	udelay(30);
 
 	/* Tx control */
@@ -768,12 +730,12 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
 
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
 
-	/**
-	* Set Time (based unit is 512 bit time) between automatic
-	* re-sending of PP packets amd enable automatic re-send of
-	* Per-Priroity Packet as long as pp_gen is asserted and
-	* pp_disable is low.
-	*/
+	/*
+	 * Set Time (based unit is 512 bit time) between automatic
+	 * re-sending of PP packets amd enable automatic re-send of
+	 * Per-Priroity Packet as long as pp_gen is asserted and
+	 * pp_disable is low.
+	 */
 	val = 0x8000;
 	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
 		val |= (1<<16); /* enable automatic re-send */
@@ -781,7 +743,7 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
 	wb_data[0] = val;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
-			wb_data, 2);
+		    wb_data, 2);
 
 	/* mac control */
 	val = 0x3; /* Enable RX and TX */
@@ -795,8 +757,7 @@ static void bnx2x_update_pfc_bmac2(struct link_params *params,
 
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 }
 
 static void bnx2x_update_pfc_brb(struct link_params *params,
@@ -825,17 +786,25 @@ static void bnx2x_update_pfc_brb(struct link_params *params,
 			full_xon_th =
 			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
 		}
-	/* The number of free blocks below which the pause signal to class 0
-	   of MAC #n is asserted. n=0,1 */
+	/*
+	 * The number of free blocks below which the pause signal to class 0
+	 * of MAC #n is asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
-	/* The number of free blocks above which the pause signal to class 0
-	   of MAC #n is de-asserted. n=0,1 */
+	/*
+	 * The number of free blocks above which the pause signal to class 0
+	 * of MAC #n is de-asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
-	/* The number of free blocks below which the full signal to class 0
-	   of MAC #n is asserted. n=0,1 */
+	/*
+	 * The number of free blocks below which the full signal to class 0
+	 * of MAC #n is asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
-	/* The number of free blocks above which the full signal to class 0
-	   of MAC #n is de-asserted. n=0,1 */
+	/*
+	 * The number of free blocks above which the full signal to class 0
+	 * of MAC #n is de-asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
 
 	if (set_pfc && pfc_params) {
@@ -859,25 +828,25 @@ static void bnx2x_update_pfc_brb(struct link_params *params,
 			full_xon_th =
 			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
 		}
-		/**
+		/*
 		 * The number of free blocks below which the pause signal to
 		 * class 1 of MAC #n is asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
-		/**
+		/*
 		 * The number of free blocks above which the pause signal to
 		 * class 1 of MAC #n is de-asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
-		/**
+		/*
 		 * The number of free blocks below which the full signal to
 		 * class 1 of MAC #n is asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
-		/**
+		/*
 		 * The number of free blocks above which the full signal to
 		 * class 1 of MAC #n is de-asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
 	}
 }
@@ -896,7 +865,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 		FEATURE_CONFIG_PFC_ENABLED;
 	DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
 
-	/**
+	/*
 	 * When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
 	 * MAC control frames (that are not pause packets)
 	 * will be forwarded to the XCM.
@@ -904,7 +873,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
 	xcm_mask = REG_RD(bp,
 				port ? NIG_REG_LLH1_XCM_MASK :
 				NIG_REG_LLH0_XCM_MASK);
-	/**
+	/*
 	 * nig params will override non PFC params, since it's possible to
 	 * do transition from PFC to SAFC
 	 */
@@ -994,7 +963,7 @@ void bnx2x_update_pfc(struct link_params *params,
 		      struct link_vars *vars,
 		      struct bnx2x_nig_brb_pfc_port_params *pfc_params)
 {
-	/**
+	/*
 	 * The PFC and pause are orthogonal to one another, meaning when
 	 * PFC is enabled, the pause are disabled, and when PFC is
 	 * disabled, pause are set according to the pause result.
@@ -1035,7 +1004,7 @@ void bnx2x_update_pfc(struct link_params *params,
 
 static u8 bnx2x_bmac1_enable(struct link_params *params,
 			     struct link_vars *vars,
-			  u8 is_lb)
+			     u8 is_lb)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1049,9 +1018,8 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
 	/* XGXS control */
 	wb_data[0] = 0x3c;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr +
-		      BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
-		      wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
+		    wb_data, 2);
 
 	/* tx MAC SA */
 	wb_data[0] = ((params->mac_addr[2] << 24) |
@@ -1060,8 +1028,7 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
 			params->mac_addr[5]);
 	wb_data[1] = ((params->mac_addr[0] << 8) |
 			params->mac_addr[1]);
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
-		    wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR, wb_data, 2);
 
 	/* mac control */
 	val = 0x3;
@@ -1071,43 +1038,30 @@ static u8 bnx2x_bmac1_enable(struct link_params *params,
 	}
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
-		    wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
 
 	/* set rx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
 
 	bnx2x_update_pfc_bmac1(params, vars);
 
 	/* set tx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2);
 
 	/* set cnt max size */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
-		    wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 
 	/* configure safc */
 	wb_data[0] = 0x1000200;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
 		    wb_data, 2);
-	/* fix for emulation */
-	if (CHIP_REV_IS_EMUL(bp)) {
-		wb_data[0] = 0xf000;
-		wb_data[1] = 0;
-		REG_WR_DMAE(bp,
-			    bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
-			    wb_data, 2);
-	}
-
 
 	return 0;
 }
@@ -1126,16 +1080,14 @@ static u8 bnx2x_bmac2_enable(struct link_params *params,
 
 	wb_data[0] = 0;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 	udelay(30);
 
 	/* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
 	wb_data[0] = 0x3c;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr +
-			BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
+		    wb_data, 2);
 
 	udelay(30);
 
@@ -1147,7 +1099,7 @@ static u8 bnx2x_bmac2_enable(struct link_params *params,
 	wb_data[1] = ((params->mac_addr[0] << 8) |
 			params->mac_addr[1]);
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR,
-			wb_data, 2);
+		    wb_data, 2);
 
 	udelay(30);
 
@@ -1155,27 +1107,24 @@ static u8 bnx2x_bmac2_enable(struct link_params *params,
 	wb_data[0] = 0x1000200;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
-			wb_data, 2);
+		    wb_data, 2);
 	udelay(30);
 
 	/* set rx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2);
 	udelay(30);
 
 	/* set tx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2);
 	udelay(30);
 	/* set cnt max size */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 	udelay(30);
 	bnx2x_update_pfc_bmac2(params, vars, is_lb);
 
@@ -1191,11 +1140,11 @@ static u8 bnx2x_bmac_enable(struct link_params *params,
 	u32 val;
 	/* reset and unreset the BigMac */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 	msleep(1);
 
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 
 	/* enable access for bmac registers */
 	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
@@ -1230,15 +1179,14 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status)
 	struct bnx2x *bp = params->bp;
 
 	REG_WR(bp, params->shmem_base +
-		   offsetof(struct shmem_region,
-			    port_mb[params->port].link_status),
-			link_status);
+	       offsetof(struct shmem_region,
+			port_mb[params->port].link_status), link_status);
 }
 
 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
 {
 	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
-		NIG_REG_INGRESS_BMAC0_MEM;
+			NIG_REG_INGRESS_BMAC0_MEM;
 	u32 wb_data[2];
 	u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
 
@@ -1250,12 +1198,12 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
 		if (CHIP_IS_E2(bp)) {
 			/* Clear Rx Enable bit in BMAC_CONTROL register */
 			REG_RD_DMAE(bp, bmac_addr +
-					BIGMAC2_REGISTER_BMAC_CONTROL,
-					wb_data, 2);
+				    BIGMAC2_REGISTER_BMAC_CONTROL,
+				    wb_data, 2);
 			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
 			REG_WR_DMAE(bp, bmac_addr +
-					BIGMAC2_REGISTER_BMAC_CONTROL,
-					wb_data, 2);
+				    BIGMAC2_REGISTER_BMAC_CONTROL,
+				    wb_data, 2);
 		} else {
 			/* Clear Rx Enable bit in BMAC_CONTROL register */
 			REG_RD_DMAE(bp, bmac_addr +
@@ -1271,7 +1219,7 @@ static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
 }
 
 static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
-			 u32 line_speed)
+			   u32 line_speed)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1308,7 +1256,7 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
 		/* update threshold */
 		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
 		/* update init credit */
-		init_crd = 778; 	/* (800-18-4) */
+		init_crd = 778;		/* (800-18-4) */
 
 	} else {
 		u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
@@ -1353,6 +1301,23 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
 	return 0;
 }
 
+/*
+ * get_emac_base
+ *
+ * @param cb
+ * @param mdc_mdio_access
+ * @param port
+ *
+ * @return u32
+ *
+ * This function selects the MDC/MDIO access (through emac0 or
+ * emac1) depend on the mdc_mdio_access, port, port swapped. Each
+ * phy has a default access mode, which could also be overridden
+ * by nvram configuration. This parameter, whether this is the
+ * default phy configuration, or the nvram overrun
+ * configuration, is passed here as mdc_mdio_access and selects
+ * the emac_base for the CL45 read/writes operations
+ */
 static u32 bnx2x_get_emac_base(struct bnx2x *bp,
 			       u32 mdc_mdio_access, u8 port)
 {
@@ -1385,13 +1350,16 @@ static u32 bnx2x_get_emac_base(struct bnx2x *bp,
 
 }
 
-u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-		    u8 devad, u16 reg, u16 val)
+/******************************************************************/
+/*			CL45 access functions			  */
+/******************************************************************/
+static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+			   u8 devad, u16 reg, u16 val)
 {
 	u32 tmp, saved_mode;
 	u8 i, rc = 0;
-
-	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	/*
+	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
 	 * (a value of 49==0x31) and make sure that the AUTO poll is off
 	 */
 
@@ -1414,8 +1382,7 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 	for (i = 0; i < 50; i++) {
 		udelay(10);
 
-		tmp = REG_RD(bp, phy->mdio_ctrl +
-				   EMAC_REG_EMAC_MDIO_COMM);
+		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 			udelay(5);
 			break;
@@ -1423,6 +1390,7 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 	}
 	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
 		DP(NETIF_MSG_LINK, "write phy register failed\n");
+		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		rc = -EFAULT;
 	} else {
 		/* data */
@@ -1435,7 +1403,7 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 			udelay(10);
 
 			tmp = REG_RD(bp, phy->mdio_ctrl +
-					 EMAC_REG_EMAC_MDIO_COMM);
+				     EMAC_REG_EMAC_MDIO_COMM);
 			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 				udelay(5);
 				break;
@@ -1443,6 +1411,7 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 		}
 		if (tmp & EMAC_MDIO_COMM_START_BUSY) {
 			DP(NETIF_MSG_LINK, "write phy register failed\n");
+			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 			rc = -EFAULT;
 		}
 	}
@@ -1453,20 +1422,20 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
 	return rc;
 }
 
-u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
-		   u8 devad, u16 reg, u16 *ret_val)
+static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+			  u8 devad, u16 reg, u16 *ret_val)
 {
 	u32 val, saved_mode;
 	u16 i;
 	u8 rc = 0;
-
-	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	/*
+	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
 	 * (a value of 49==0x31) and make sure that the AUTO poll is off
 	 */
 
 	saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
 	val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
-			     EMAC_MDIO_MODE_CLOCK_CNT));
+			      EMAC_MDIO_MODE_CLOCK_CNT));
 	val |= (EMAC_MDIO_MODE_CLAUSE_45 |
 		(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
 	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
@@ -1490,7 +1459,7 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
 	}
 	if (val & EMAC_MDIO_COMM_START_BUSY) {
 		DP(NETIF_MSG_LINK, "read phy register failed\n");
-
+		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		*ret_val = 0;
 		rc = -EFAULT;
 
@@ -1505,7 +1474,7 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
 			udelay(10);
 
 			val = REG_RD(bp, phy->mdio_ctrl +
-					  EMAC_REG_EMAC_MDIO_COMM);
+				     EMAC_REG_EMAC_MDIO_COMM);
 			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
 				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
 				break;
@@ -1513,7 +1482,7 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
 		}
 		if (val & EMAC_MDIO_COMM_START_BUSY) {
 			DP(NETIF_MSG_LINK, "read phy register failed\n");
-
+			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 			*ret_val = 0;
 			rc = -EFAULT;
 		}
@@ -1529,7 +1498,7 @@ u8 bnx2x_phy_read(struct link_params *params, u8 phy_addr,
 		  u8 devad, u16 reg, u16 *ret_val)
 {
 	u8 phy_index;
-	/**
+	/*
 	 * Probe for the phy according to the given phy_addr, and execute
 	 * the read request on it
 	 */
@@ -1547,7 +1516,7 @@ u8 bnx2x_phy_write(struct link_params *params, u8 phy_addr,
 		   u8 devad, u16 reg, u16 val)
 {
 	u8 phy_index;
-	/**
+	/*
 	 * Probe for the phy according to the given phy_addr, and execute
 	 * the write request on it
 	 */
@@ -1576,16 +1545,15 @@ static void bnx2x_set_aer_mmd_xgxs(struct link_params *params,
 		aer_val = 0x3800 + offset - 1;
 	else
 		aer_val = 0x3800 + offset;
-	CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_AER_BLOCK,
-				MDIO_AER_BLOCK_AER_REG, aer_val);
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, aer_val);
 }
 static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
 				     struct bnx2x_phy *phy)
 {
-	CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_AER_BLOCK,
-				MDIO_AER_BLOCK_AER_REG, 0x3800);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, 0x3800);
 }
 
 /******************************************************************/
@@ -1621,9 +1589,8 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
 
 	bnx2x_set_serdes_access(bp, port);
 
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
-		     port*0x10,
-		     DEFAULT_PHY_DEV_ADDR);
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
+	       DEFAULT_PHY_DEV_ADDR);
 }
 
 static void bnx2x_xgxs_deassert(struct link_params *params)
@@ -1641,23 +1608,22 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
 	udelay(500);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
 
-	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
-		     port*0x18, 0);
+	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
 	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-		     params->phy[INT_PHY].def_md_devad);
+	       params->phy[INT_PHY].def_md_devad);
 }
 
 
 void bnx2x_link_status_update(struct link_params *params,
-			    struct link_vars   *vars)
+			      struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 link_10g;
 	u8 port = params->port;
 
 	vars->link_status = REG_RD(bp, params->shmem_base +
-					  offsetof(struct shmem_region,
-					   port_mb[port].link_status));
+				   offsetof(struct shmem_region,
+					    port_mb[port].link_status));
 
 	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
 
@@ -1667,7 +1633,7 @@ void bnx2x_link_status_update(struct link_params *params,
 		vars->phy_link_up = 1;
 		vars->duplex = DUPLEX_FULL;
 		switch (vars->link_status &
-					LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
+			LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
 			case LINK_10THD:
 				vars->duplex = DUPLEX_HALF;
 				/* fall thru */
@@ -1779,20 +1745,20 @@ static void bnx2x_set_master_ln(struct link_params *params,
 {
 	struct bnx2x *bp = params->bp;
 	u16 new_master_ln, ser_lane;
-	ser_lane =  ((params->lane_config &
+	ser_lane = ((params->lane_config &
 		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 
 	/* set the master_ln for AN */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_XGXS_BLOCK2,
-			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
-			      &new_master_ln);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_XGXS_BLOCK2,
+			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
+			  &new_master_ln);
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_XGXS_BLOCK2 ,
-			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
-			      (new_master_ln | ser_lane));
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_XGXS_BLOCK2 ,
+			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
+			  (new_master_ln | ser_lane));
 }
 
 static u8 bnx2x_reset_unicore(struct link_params *params,
@@ -1802,17 +1768,16 @@ static u8 bnx2x_reset_unicore(struct link_params *params,
 	struct bnx2x *bp = params->bp;
 	u16 mii_control;
 	u16 i;
-
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
 
 	/* reset the unicore */
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL,
-			      (mii_control |
-			       MDIO_COMBO_IEEO_MII_CONTROL_RESET));
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL,
+			  (mii_control |
+			   MDIO_COMBO_IEEO_MII_CONTROL_RESET));
 	if (set_serdes)
 		bnx2x_set_serdes_access(bp, params->port);
 
@@ -1821,10 +1786,10 @@ static u8 bnx2x_reset_unicore(struct link_params *params,
 		udelay(5);
 
 		/* the reset erased the previous bank value */
-		CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL,
-			      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  &mii_control);
 
 		if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
 			udelay(5);
@@ -1832,6 +1797,9 @@ static u8 bnx2x_reset_unicore(struct link_params *params,
 		}
 	}
 
+	netdev_err(bp->dev,  "Warning: PHY was not initialized,"
+			      " Port %d\n",
+			 params->port);
 	DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
 	return -EINVAL;
 
@@ -1841,43 +1809,45 @@ static void bnx2x_set_swap_lanes(struct link_params *params,
 				 struct bnx2x_phy *phy)
 {
 	struct bnx2x *bp = params->bp;
-	/* Each two bits represents a lane number:
-	   No swap is 0123 => 0x1b no need to enable the swap */
+	/*
+	 *  Each two bits represents a lane number:
+	 *  No swap is 0123 => 0x1b no need to enable the swap
+	 */
 	u16 ser_lane, rx_lane_swap, tx_lane_swap;
 
 	ser_lane = ((params->lane_config &
-			 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-			PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
+		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 	rx_lane_swap = ((params->lane_config &
-			     PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
-			    PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
+			 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
+			PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
 	tx_lane_swap = ((params->lane_config &
-			     PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
-			    PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
+			 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
+			PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
 
 	if (rx_lane_swap != 0x1b) {
-		CL45_WR_OVER_CL22(bp, phy,
-				    MDIO_REG_BANK_XGXS_BLOCK2,
-				    MDIO_XGXS_BLOCK2_RX_LN_SWAP,
-				    (rx_lane_swap |
-				    MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
-				    MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_RX_LN_SWAP,
+				  (rx_lane_swap |
+				   MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
+				   MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
 	} else {
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_XGXS_BLOCK2,
-				      MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
 	}
 
 	if (tx_lane_swap != 0x1b) {
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_XGXS_BLOCK2,
-				      MDIO_XGXS_BLOCK2_TX_LN_SWAP,
-				      (tx_lane_swap |
-				       MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_TX_LN_SWAP,
+				  (tx_lane_swap |
+				   MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
 	} else {
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_XGXS_BLOCK2,
-				      MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
 	}
 }
 
@@ -1886,66 +1856,66 @@ static void bnx2x_set_parallel_detection(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u16 control2;
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
-			      &control2);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
+			  &control2);
 	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
 		control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
 	else
 		control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
 	DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
 		phy->speed_cap_mask, control2);
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
-			      control2);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
+			  control2);
 
 	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
 	     (phy->speed_cap_mask &
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
 		DP(NETIF_MSG_LINK, "XGXS\n");
 
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_10G_PARALLEL_DETECT,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
+		CL22_WR_OVER_CL45(bp, phy,
+				 MDIO_REG_BANK_10G_PARALLEL_DETECT,
+				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
+				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
 
-		CL45_RD_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_10G_PARALLEL_DETECT,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
-				&control2);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_10G_PARALLEL_DETECT,
+				  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
+				  &control2);
 
 
 		control2 |=
 		    MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
 
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_10G_PARALLEL_DETECT,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
-				control2);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_10G_PARALLEL_DETECT,
+				  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
+				  control2);
 
 		/* Disable parallel detection of HiG */
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_XGXS_BLOCK2,
-				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
-				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
-				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
+				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
+				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
 	}
 }
 
 static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 			      struct link_params *params,
-			    struct link_vars *vars,
-			    u8 enable_cl73)
+			      struct link_vars *vars,
+			      u8 enable_cl73)
 {
 	struct bnx2x *bp = params->bp;
 	u16 reg_val;
 
 	/* CL37 Autoneg */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
 
 	/* CL37 Autoneg Enabled */
 	if (vars->line_speed == SPEED_AUTO_NEG)
@@ -1954,15 +1924,15 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 		reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 			     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
 
 	/* Enable/Disable Autodetection */
 
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
 	reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
 		    MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
 	reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
@@ -1971,14 +1941,14 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 	else
 		reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
 
 	/* Enable TetonII and BAM autoneg */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_BAM_NEXT_PAGE,
-			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_BAM_NEXT_PAGE,
+			  MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
 			  &reg_val);
 	if (vars->line_speed == SPEED_AUTO_NEG) {
 		/* Enable BAM aneg Mode and TetonII aneg Mode */
@@ -1989,20 +1959,20 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 		reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
 			     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
 	}
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_BAM_NEXT_PAGE,
-			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
-			      reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_BAM_NEXT_PAGE,
+			  MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
+			  reg_val);
 
 	if (enable_cl73) {
 		/* Enable Cl73 FSM status bits */
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_CL73_USERB0,
-				    MDIO_CL73_USERB0_CL73_UCTRL,
-				      0xe);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_USERB0,
+				  MDIO_CL73_USERB0_CL73_UCTRL,
+				  0xe);
 
 		/* Enable BAM Station Manager*/
-		CL45_WR_OVER_CL22(bp, phy,
+		CL22_WR_OVER_CL45(bp, phy,
 			MDIO_REG_BANK_CL73_USERB0,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
@@ -2010,10 +1980,10 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
 
 		/* Advertise CL73 link speeds */
-		CL45_RD_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_CL73_IEEEB1,
-					      MDIO_CL73_IEEEB1_AN_ADV2,
-					      &reg_val);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB1,
+				  MDIO_CL73_IEEEB1_AN_ADV2,
+				  &reg_val);
 		if (phy->speed_cap_mask &
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
@@ -2021,10 +1991,10 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
 			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
 
-		CL45_WR_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_CL73_IEEEB1,
-					      MDIO_CL73_IEEEB1_AN_ADV2,
-				      reg_val);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB1,
+				  MDIO_CL73_IEEEB1_AN_ADV2,
+				  reg_val);
 
 		/* CL73 Autoneg Enabled */
 		reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
@@ -2032,37 +2002,39 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 	} else /* CL73 Autoneg Disabled */
 		reg_val = 0;
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB0,
-			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB0,
+			  MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
 }
 
 /* program SerDes, forced speed */
 static void bnx2x_program_serdes(struct bnx2x_phy *phy,
 				 struct link_params *params,
-			       struct link_vars *vars)
+				 struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 reg_val;
 
 	/* program duplex, disable autoneg and sgmii*/
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
 	reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
 		     MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 		     MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
 	if (phy->req_duplex == DUPLEX_FULL)
 		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
-
-	/* program speed
-	   - needed only if the speed is greater than 1G (2.5G or 10G) */
-	CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_SERDES_DIGITAL,
-				      MDIO_SERDES_DIGITAL_MISC1, &reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
+
+	/*
+	 * program speed
+	 *  - needed only if the speed is greater than 1G (2.5G or 10G)
+	 */
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_MISC1, &reg_val);
 	/* clearing the speed value before setting the right speed */
 	DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
 
@@ -2083,9 +2055,9 @@ static void bnx2x_program_serdes(struct bnx2x_phy *phy,
 				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
 	}
 
-	CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_SERDES_DIGITAL,
-				      MDIO_SERDES_DIGITAL_MISC1, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_MISC1, reg_val);
 
 }
 
@@ -2102,13 +2074,13 @@ static void bnx2x_set_brcm_cl37_advertisment(struct bnx2x_phy *phy,
 		val |= MDIO_OVER_1G_UP1_2_5G;
 	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 		val |= MDIO_OVER_1G_UP1_10G;
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_OVER_1G,
-			      MDIO_OVER_1G_UP1, val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_OVER_1G,
+			  MDIO_OVER_1G_UP1, val);
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_OVER_1G,
-			      MDIO_OVER_1G_UP3, 0x400);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_OVER_1G,
+			  MDIO_OVER_1G_UP3, 0x400);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -2116,22 +2088,21 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
-	/* resolve pause mode and advertisement
-	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
+	/*
+	 * Resolve pause mode and advertisement.
+	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec
+	 */
 
 	switch (phy->req_flow_ctrl) {
 	case BNX2X_FLOW_CTRL_AUTO:
-		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
-			*ieee_fc |=
-			     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-		} else {
+		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
+			*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+		else
 			*ieee_fc |=
-		       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		}
+			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
 		break;
 	case BNX2X_FLOW_CTRL_TX:
-		*ieee_fc |=
-		       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
 		break;
 
 	case BNX2X_FLOW_CTRL_RX:
@@ -2149,23 +2120,23 @@ static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
 
 static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
 					     struct link_params *params,
-					   u16 ieee_fc)
+					     u16 ieee_fc)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val;
 	/* for AN, we are always publishing full duplex */
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB1,
-			      MDIO_CL73_IEEEB1_AN_ADV1, &val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB1,
+			  MDIO_CL73_IEEEB1_AN_ADV1, &val);
 	val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
 	val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB1,
-			      MDIO_CL73_IEEEB1_AN_ADV1, val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB1,
+			  MDIO_CL73_IEEEB1_AN_ADV1, val);
 }
 
 static void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
@@ -2179,67 +2150,67 @@ static void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
 	/* Enable and restart BAM/CL37 aneg */
 
 	if (enable_cl73) {
-		CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_CL73_IEEEB0,
-				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				      &mii_control);
-
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_CL73_IEEEB0,
-				MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				(mii_control |
-				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
-				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB0,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+				  &mii_control);
+
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB0,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+				  (mii_control |
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
 	} else {
 
-		CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  &mii_control);
 		DP(NETIF_MSG_LINK,
 			 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
 			 mii_control);
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      (mii_control |
-				       MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
-				       MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  (mii_control |
+				   MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
+				   MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
 	}
 }
 
 static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
 					   struct link_params *params,
-					 struct link_vars *vars)
+					   struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 control1;
 
 	/* in SGMII mode, the unicore is always slave */
 
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
-		      &control1);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
+			  &control1);
 	control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
 	/* set sgmii mode (and not fiber) */
 	control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
 		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
 		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
-			      control1);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
+			  control1);
 
 	/* if forced speed */
 	if (!(vars->line_speed == SPEED_AUTO_NEG)) {
 		/* set speed, disable autoneg */
 		u16 mii_control;
 
-		CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  &mii_control);
 		mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 				 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
 				 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
@@ -2267,10 +2238,10 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
 		if (phy->req_duplex == DUPLEX_FULL)
 			mii_control |=
 				MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      mii_control);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  mii_control);
 
 	} else { /* AN mode */
 		/* enable and restart AN */
@@ -2285,19 +2256,19 @@ static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
 
 static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
 {						/*  LD	    LP	 */
-	switch (pause_result) { 		/* ASYM P ASYM P */
-	case 0xb:       			/*   1  0   1  1 */
+	switch (pause_result) {			/* ASYM P ASYM P */
+	case 0xb:				/*   1  0   1  1 */
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
 		break;
 
-	case 0xe:       			/*   1  1   1  0 */
+	case 0xe:				/*   1  1   1  0 */
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
 		break;
 
-	case 0x5:       			/*   0  1   0  1 */
-	case 0x7:       			/*   0  1   1  1 */
-	case 0xd:       			/*   1  1   0  1 */
-	case 0xf:       			/*   1  1   1  1 */
+	case 0x5:				/*   0  1   0  1 */
+	case 0x7:				/*   0  1   1  1 */
+	case 0xd:				/*   1  1   0  1 */
+	case 0xf:				/*   1  1   1  1 */
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
 		break;
 
@@ -2317,24 +2288,24 @@ static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy,
 	u16 pd_10g, status2_1000x;
 	if (phy->req_line_speed != SPEED_AUTO_NEG)
 		return 0;
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
-			      &status2_1000x);
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
-			      &status2_1000x);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
+			  &status2_1000x);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
+			  &status2_1000x);
 	if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
 		DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n",
 			 params->port);
 		return 1;
 	}
 
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_10G_PARALLEL_DETECT,
-			      MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
-			      &pd_10g);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_10G_PARALLEL_DETECT,
+			  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
+			  &pd_10g);
 
 	if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
 		DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n",
@@ -2373,14 +2344,14 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
 		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
 		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
 
-			CL45_RD_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_CL73_IEEEB1,
-					      MDIO_CL73_IEEEB1_AN_ADV1,
-					      &ld_pause);
-			CL45_RD_OVER_CL22(bp, phy,
-					     MDIO_REG_BANK_CL73_IEEEB1,
-					     MDIO_CL73_IEEEB1_AN_LP_ADV1,
-					     &lp_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+					  MDIO_REG_BANK_CL73_IEEEB1,
+					  MDIO_CL73_IEEEB1_AN_ADV1,
+					  &ld_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+					  MDIO_REG_BANK_CL73_IEEEB1,
+					  MDIO_CL73_IEEEB1_AN_LP_ADV1,
+					  &lp_pause);
 			pause_result = (ld_pause &
 					MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
 					>> 8;
@@ -2390,18 +2361,18 @@ static void bnx2x_flow_ctrl_resolve(struct bnx2x_phy *phy,
 			DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
 				 pause_result);
 		} else {
-			CL45_RD_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_COMBO_IEEE0,
-					      MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
-					      &ld_pause);
-			CL45_RD_OVER_CL22(bp, phy,
-			       MDIO_REG_BANK_COMBO_IEEE0,
-			       MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
-			       &lp_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+					  MDIO_REG_BANK_COMBO_IEEE0,
+					  MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
+					  &ld_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+				MDIO_REG_BANK_COMBO_IEEE0,
+				MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
+				&lp_pause);
 			pause_result = (ld_pause &
 				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
 			pause_result |= (lp_pause &
-				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
+				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
 			DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
 				 pause_result);
 		}
@@ -2417,25 +2388,25 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
 	u16 rx_status, ustat_val, cl37_fsm_recieved;
 	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
 	/* Step 1: Make sure signal is detected */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_RX0,
-			      MDIO_RX0_RX_STATUS,
-			      &rx_status);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_RX0,
+			  MDIO_RX0_RX_STATUS,
+			  &rx_status);
 	if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
 	    (MDIO_RX0_RX_STATUS_SIGDET)) {
 		DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
 			     "rx_status(0x80b0) = 0x%x\n", rx_status);
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_CL73_IEEEB0,
-				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB0,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
 		return;
 	}
 	/* Step 2: Check CL73 state machine */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_USERB0,
-			      MDIO_CL73_USERB0_CL73_USTAT1,
-			      &ustat_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_USERB0,
+			  MDIO_CL73_USERB0_CL73_USTAT1,
+			  &ustat_val);
 	if ((ustat_val &
 	     (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
 	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
@@ -2445,12 +2416,14 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
 			     "ustat_val(0x8371) = 0x%x\n", ustat_val);
 		return;
 	}
-	/* Step 3: Check CL37 Message Pages received to indicate LP
-	supports only CL37 */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_REMOTE_PHY,
-			      MDIO_REMOTE_PHY_MISC_RX_STATUS,
-			      &cl37_fsm_recieved);
+	/*
+	 * Step 3: Check CL37 Message Pages received to indicate LP
+	 * supports only CL37
+	 */
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_REMOTE_PHY,
+			  MDIO_REMOTE_PHY_MISC_RX_STATUS,
+			  &cl37_fsm_recieved);
 	if ((cl37_fsm_recieved &
 	     (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
 	     MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
@@ -2461,14 +2434,18 @@ static void bnx2x_check_fallback_to_cl37(struct bnx2x_phy *phy,
 			 cl37_fsm_recieved);
 		return;
 	}
-	/* The combined cl37/cl73 fsm state information indicating that we are
-	connected to a device which does not support cl73, but does support
-	cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */
+	/*
+	 * The combined cl37/cl73 fsm state information indicating that
+	 * we are connected to a device which does not support cl73, but
+	 * does support cl37 BAM. In this case we disable cl73 and
+	 * restart cl37 auto-neg
+	 */
+
 	/* Disable CL73 */
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB0,
-			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-			      0);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB0,
+			  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+			  0);
 	/* Restart CL37 autoneg */
 	bnx2x_restart_autoneg(phy, params, 0);
 	DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
@@ -2493,14 +2470,14 @@ static u8 bnx2x_link_settings_status(struct bnx2x_phy *phy,
 				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 new_line_speed , gp_status;
+	u16 new_line_speed, gp_status;
 	u8 rc = 0;
 
 	/* Read gp_status */
-	CL45_RD_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_GP_STATUS,
-				MDIO_GP_STATUS_TOP_AN_STATUS1,
-				&gp_status);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_GP_STATUS,
+			  MDIO_GP_STATUS_TOP_AN_STATUS1,
+			  &gp_status);
 
 	if (phy->req_line_speed == SPEED_AUTO_NEG)
 		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
@@ -2637,9 +2614,9 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
 	u16 bank;
 
 	/* read precomp */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_OVER_1G,
-			      MDIO_OVER_1G_LP_UP2, &lp_up2);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_OVER_1G,
+			  MDIO_OVER_1G_LP_UP2, &lp_up2);
 
 	/* bits [10:7] at lp_up2, positioned at [15:12] */
 	lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
@@ -2651,18 +2628,18 @@ static void bnx2x_set_gmii_tx_driver(struct link_params *params)
 
 	for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
 	      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
-		CL45_RD_OVER_CL22(bp, phy,
-				      bank,
-				      MDIO_TX0_TX_DRIVER, &tx_driver);
+		CL22_RD_OVER_CL45(bp, phy,
+				  bank,
+				  MDIO_TX0_TX_DRIVER, &tx_driver);
 
 		/* replace tx_driver bits [15:12] */
 		if (lp_up2 !=
 		    (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
 			tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
 			tx_driver |= lp_up2;
-			CL45_WR_OVER_CL22(bp, phy,
-					      bank,
-					      MDIO_TX0_TX_DRIVER, tx_driver);
+			CL22_WR_OVER_CL45(bp, phy,
+					  bank,
+					  MDIO_TX0_TX_DRIVER, tx_driver);
 		}
 	}
 }
@@ -2676,10 +2653,10 @@ static u8 bnx2x_emac_program(struct link_params *params,
 
 	DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
 	bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
-		     EMAC_REG_EMAC_MODE,
-		     (EMAC_MODE_25G_MODE |
-		     EMAC_MODE_PORT_MII_10M |
-		     EMAC_MODE_HALF_DUPLEX));
+		       EMAC_REG_EMAC_MODE,
+		       (EMAC_MODE_25G_MODE |
+			EMAC_MODE_PORT_MII_10M |
+			EMAC_MODE_HALF_DUPLEX));
 	switch (vars->line_speed) {
 	case SPEED_10:
 		mode |= EMAC_MODE_PORT_MII_10M;
@@ -2707,8 +2684,8 @@ static u8 bnx2x_emac_program(struct link_params *params,
 	if (vars->duplex == DUPLEX_HALF)
 		mode |= EMAC_MODE_HALF_DUPLEX;
 	bnx2x_bits_en(bp,
-		    GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
-		    mode);
+		      GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
+		      mode);
 
 	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
 	return 0;
@@ -2723,7 +2700,7 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
 
 	for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
 	      bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
-			CL45_WR_OVER_CL22(bp, phy,
+			CL22_WR_OVER_CL45(bp, phy,
 					  bank,
 					  MDIO_RX0_RX_EQ_BOOST,
 					  phy->rx_preemphasis[i]);
@@ -2731,7 +2708,7 @@ static void bnx2x_set_preemphasis(struct bnx2x_phy *phy,
 
 	for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
 		      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
-			CL45_WR_OVER_CL22(bp, phy,
+			CL22_WR_OVER_CL45(bp, phy,
 					  bank,
 					  MDIO_TX0_TX_DRIVER,
 					  phy->tx_preemphasis[i]);
@@ -2754,7 +2731,7 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
 		/* forced speed requested? */
 		if (vars->line_speed != SPEED_AUTO_NEG ||
 		    (SINGLE_MEDIA_DIRECT(params) &&
-			  params->loopback_mode == LOOPBACK_EXT)) {
+		     params->loopback_mode == LOOPBACK_EXT)) {
 			DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
 
 			/* disable autoneg */
@@ -2771,7 +2748,7 @@ static void bnx2x_init_internal_phy(struct bnx2x_phy *phy,
 
 			/* program duplex & pause advertisement (for aneg) */
 			bnx2x_set_ieee_aneg_advertisment(phy, params,
-						       vars->ieee_fc);
+							 vars->ieee_fc);
 
 			/* enable autoneg */
 			bnx2x_set_autoneg(phy, params, vars, enable_cl73);
@@ -2842,7 +2819,8 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy,
 }
 
 static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
-				     struct bnx2x_phy *phy)
+				     struct bnx2x_phy *phy,
+				     struct link_params *params)
 {
 	u16 cnt, ctrl;
 	/* Wait for soft reset to get cleared upto 1 sec */
@@ -2853,6 +2831,11 @@ static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
 			break;
 		msleep(1);
 	}
+
+	if (cnt == 1000)
+		netdev_err(bp->dev,  "Warning: PHY was not initialized,"
+				      " Port %d\n",
+			 params->port);
 	DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
 	return cnt;
 }
@@ -2863,9 +2846,7 @@ static void bnx2x_link_int_enable(struct link_params *params)
 	u32 mask;
 	struct bnx2x *bp = params->bp;
 
-	/* setting the status to report on link up
-	   for either XGXS or SerDes */
-
+	/* Setting the status to report on link up for either XGXS or SerDes */
 	if (params->switch_cfg == SWITCH_CFG_10G) {
 		mask = (NIG_MASK_XGXS0_LINK10G |
 			NIG_MASK_XGXS0_LINK_STATUS);
@@ -2908,7 +2889,7 @@ static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
 {
 	u32 latch_status = 0;
 
-	/**
+	/*
 	 * Disable the MI INT ( external phy int ) by writing 1 to the
 	 * status register. Link down indication is high-active-signal,
 	 * so in this case we need to write the status to clear the XOR
@@ -2933,27 +2914,30 @@ static void bnx2x_rearm_latch_signal(struct bnx2x *bp, u8 port,
 
 		/* For all latched-signal=up : Re-Arm Latch signals */
 		REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
-			     (latch_status & 0xfffe) | (latch_status & 1));
+		       (latch_status & 0xfffe) | (latch_status & 1));
 	}
 	/* For all latched-signal=up,Write original_signal to status */
 }
 
 static void bnx2x_link_int_ack(struct link_params *params,
-			     struct link_vars *vars, u8 is_10g)
+			       struct link_vars *vars, u8 is_10g)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
 
-	/* first reset all status
-	 * we assume only one line will be change at a time */
+	/*
+	 * First reset all status we assume only one line will be
+	 * change at a time
+	 */
 	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-		     (NIG_STATUS_XGXS0_LINK10G |
-		      NIG_STATUS_XGXS0_LINK_STATUS |
-		      NIG_STATUS_SERDES0_LINK_STATUS));
+		       (NIG_STATUS_XGXS0_LINK10G |
+			NIG_STATUS_XGXS0_LINK_STATUS |
+			NIG_STATUS_SERDES0_LINK_STATUS));
 	if (vars->phy_link_up) {
 		if (is_10g) {
-			/* Disable the 10G link interrupt
-			 * by writing 1 to the status register
+			/*
+			 * Disable the 10G link interrupt by writing 1 to the
+			 * status register
 			 */
 			DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
 			bnx2x_bits_en(bp,
@@ -2961,9 +2945,9 @@ static void bnx2x_link_int_ack(struct link_params *params,
 				      NIG_STATUS_XGXS0_LINK10G);
 
 		} else if (params->switch_cfg == SWITCH_CFG_10G) {
-			/* Disable the link interrupt
-			 * by writing 1 to the relevant lane
-			 * in the status register
+			/*
+			 * Disable the link interrupt by writing 1 to the
+			 * relevant lane in the status register
 			 */
 			u32 ser_lane = ((params->lane_config &
 				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
@@ -2978,8 +2962,9 @@ static void bnx2x_link_int_ack(struct link_params *params,
 
 		} else { /* SerDes */
 			DP(NETIF_MSG_LINK, "SerDes phy link up\n");
-			/* Disable the link interrupt
-			 * by writing 1 to the status register
+			/*
+			 * Disable the link interrupt by writing 1 to the status
+			 * register
 			 */
 			bnx2x_bits_en(bp,
 				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
@@ -3059,8 +3044,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded,
 	}
 	if ((params->num_phys == MAX_PHYS) &&
 	    (params->phy[EXT_PHY2].ver_addr != 0)) {
-		spirom_ver = REG_RD(bp,
-					  params->phy[EXT_PHY2].ver_addr);
+		spirom_ver = REG_RD(bp, params->phy[EXT_PHY2].ver_addr);
 		if (params->phy[EXT_PHY2].format_fw_ver) {
 			*ver_p = '/';
 			ver_p++;
@@ -3089,29 +3073,27 @@ static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy,
 
 		/* change the uni_phy_addr in the nig */
 		md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
-					  port*0x18));
+				       port*0x18));
 
 		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
 
 		bnx2x_cl45_write(bp, phy,
-			       5,
-			       (MDIO_REG_BANK_AER_BLOCK +
-				(MDIO_AER_BLOCK_AER_REG & 0xf)),
-			       0x2800);
+				 5,
+				 (MDIO_REG_BANK_AER_BLOCK +
+				  (MDIO_AER_BLOCK_AER_REG & 0xf)),
+				 0x2800);
 
 		bnx2x_cl45_write(bp, phy,
-			       5,
-			       (MDIO_REG_BANK_CL73_IEEEB0 +
-				(MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
-			       0x6041);
+				 5,
+				 (MDIO_REG_BANK_CL73_IEEEB0 +
+				  (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
+				 0x6041);
 		msleep(200);
 		/* set aer mmd back */
 		bnx2x_set_aer_mmd_xgxs(params, phy);
 
 		/* and md_devad */
-		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-			    md_devad);
-
+		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, md_devad);
 	} else {
 		u16 mii_ctrl;
 		DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
@@ -3152,26 +3134,26 @@ u8 bnx2x_set_led(struct link_params *params,
 	case LED_MODE_OFF:
 		REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
 		REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
-			   SHARED_HW_CFG_LED_MAC1);
+		       SHARED_HW_CFG_LED_MAC1);
 
 		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
 		EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
 		break;
 
 	case LED_MODE_OPER:
-		/**
+		/*
 		 * For all other phys, OPER mode is same as ON, so in case
 		 * link is down, do nothing
-		 **/
+		 */
 		if (!vars->link_up)
 			break;
 	case LED_MODE_ON:
 		if (params->phy[EXT_PHY1].type ==
 		    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 &&
 		    CHIP_IS_E2(bp) && params->num_phys == 2) {
-			/**
-			* This is a work-around for E2+8727 Configurations
-			*/
+			/*
+			 * This is a work-around for E2+8727 Configurations
+			 */
 			if (mode == LED_MODE_ON ||
 				speed == SPEED_10000){
 				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
@@ -3183,41 +3165,40 @@ u8 bnx2x_set_led(struct link_params *params,
 				return rc;
 			}
 		} else if (SINGLE_MEDIA_DIRECT(params)) {
-			/**
-			* This is a work-around for HW issue found when link
-			* is up in CL73
-			*/
+			/*
+			 * This is a work-around for HW issue found when link
+			 * is up in CL73
+			 */
 			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
 			REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
 		} else {
-			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
-				   hw_led_mode);
+			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
 		}
 
-		REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
-			   port*4, 0);
+		REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
 		/* Set blinking rate to ~15.9Hz */
 		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
-			   LED_BLINK_RATE_VAL);
+		       LED_BLINK_RATE_VAL);
 		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
-			   port*4, 1);
+		       port*4, 1);
 		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
-		EMAC_WR(bp, EMAC_REG_EMAC_LED,
-			    (tmp & (~EMAC_LED_OVERRIDE)));
+		EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE)));
 
 		if (CHIP_IS_E1(bp) &&
 		    ((speed == SPEED_2500) ||
 		     (speed == SPEED_1000) ||
 		     (speed == SPEED_100) ||
 		     (speed == SPEED_10))) {
-			/* On Everest 1 Ax chip versions for speeds less than
-			10G LED scheme is different */
+			/*
+			 * On Everest 1 Ax chip versions for speeds less than
+			 * 10G LED scheme is different
+			 */
 			REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
-				   + port*4, 1);
+			       + port*4, 1);
 			REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
-				   port*4, 0);
+			       port*4, 0);
 			REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
-				   port*4, 1);
+			       port*4, 1);
 		}
 		break;
 
@@ -3231,7 +3212,7 @@ u8 bnx2x_set_led(struct link_params *params,
 
 }
 
-/**
+/*
  * This function comes to reflect the actual link state read DIRECTLY from the
  * HW
  */
@@ -3243,10 +3224,10 @@ u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars,
 	u8 ext_phy_link_up = 0, serdes_phy_type;
 	struct link_vars temp_vars;
 
-	CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY],
-			      MDIO_REG_BANK_GP_STATUS,
-			      MDIO_GP_STATUS_TOP_AN_STATUS1,
-			      &gp_status);
+	CL22_RD_OVER_CL45(bp, &params->phy[INT_PHY],
+			  MDIO_REG_BANK_GP_STATUS,
+			  MDIO_GP_STATUS_TOP_AN_STATUS1,
+			  &gp_status);
 	/* link is up only if both local phy and external phy are up */
 	if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
 		return -ESRCH;
@@ -3290,15 +3271,15 @@ static u8 bnx2x_link_initialize(struct link_params *params,
 	u8 rc = 0;
 	u8 phy_index, non_ext_phy;
 	struct bnx2x *bp = params->bp;
-	/**
-	* In case of external phy existence, the line speed would be the
-	* line speed linked up by the external phy. In case it is direct
-	* only, then the line_speed during initialization will be
-	* equal to the req_line_speed
-	*/
+	/*
+	 * In case of external phy existence, the line speed would be the
+	 * line speed linked up by the external phy. In case it is direct
+	 * only, then the line_speed during initialization will be
+	 * equal to the req_line_speed
+	 */
 	vars->line_speed = params->phy[INT_PHY].req_line_speed;
 
-	/**
+	/*
 	 * Initialize the internal phy in case this is a direct board
 	 * (no external phys), or this board has external phy which requires
 	 * to first.
@@ -3326,17 +3307,16 @@ static u8 bnx2x_link_initialize(struct link_params *params,
 	if (!non_ext_phy)
 		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
 		      phy_index++) {
-			/**
+			/*
 			 * No need to initialize second phy in case of first
 			 * phy only selection. In case of second phy, we do
 			 * need to initialize the first phy, since they are
 			 * connected.
-			 **/
+			 */
 			if (phy_index == EXT_PHY2 &&
 			    (bnx2x_phy_selection(params) ==
 			     PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
-				DP(NETIF_MSG_LINK, "Not initializing"
-						   "second phy\n");
+				DP(NETIF_MSG_LINK, "Ignoring second phy\n");
 				continue;
 			}
 			params->phy[phy_index].config_init(
@@ -3358,9 +3338,8 @@ static void bnx2x_int_link_reset(struct bnx2x_phy *phy,
 				 struct link_params *params)
 {
 	/* reset the SerDes/XGXS */
-	REG_WR(params->bp, GRCBASE_MISC +
-		     MISC_REGISTERS_RESET_REG_3_CLEAR,
-		     (0x1ff << (params->port*16)));
+	REG_WR(params->bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
+	       (0x1ff << (params->port*16)));
 }
 
 static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
@@ -3374,11 +3353,11 @@ static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
 	else
 		gpio_port = params->port;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       gpio_port);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       gpio_port);
 	DP(NETIF_MSG_LINK, "reset external PHY\n");
 }
 
@@ -3409,9 +3388,8 @@ static u8 bnx2x_update_link_down(struct link_params *params,
 
 	/* reset BigMac */
 	bnx2x_bmac_rx_disable(bp, params->port);
-	REG_WR(bp, GRCBASE_MISC +
-		   MISC_REGISTERS_RESET_REG_2_CLEAR,
-		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 	return 0;
 }
 
@@ -3462,7 +3440,7 @@ static u8 bnx2x_update_link_up(struct link_params *params,
 	msleep(20);
 	return rc;
 }
-/**
+/*
  * The bnx2x_link_update function should be called upon link
  * interrupt.
  * Link is considered up as follows:
@@ -3501,12 +3479,11 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
 
 	is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
-				    port*0x18) > 0);
+				port*0x18) > 0);
 	DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
 		 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
 		 is_mi_int,
-		 REG_RD(bp,
-			    NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
+		 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
 
 	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
 	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
@@ -3515,14 +3492,14 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 	/* disable emac */
 	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
-	/**
-	* Step 1:
-	* Check external link change only for external phys, and apply
-	* priority selection between them in case the link on both phys
-	* is up. Note that the instead of the common vars, a temporary
-	* vars argument is used since each phy may have different link/
-	* speed/duplex result
-	*/
+	/*
+	 * Step 1:
+	 * Check external link change only for external phys, and apply
+	 * priority selection between them in case the link on both phys
+	 * is up. Note that the instead of the common vars, a temporary
+	 * vars argument is used since each phy may have different link/
+	 * speed/duplex result
+	 */
 	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
 	      phy_index++) {
 		struct bnx2x_phy *phy = &params->phy[phy_index];
@@ -3547,22 +3524,22 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 			switch (bnx2x_phy_selection(params)) {
 			case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
 			case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
-			/**
+			/*
 			 * In this option, the first PHY makes sure to pass the
 			 * traffic through itself only.
 			 * Its not clear how to reset the link on the second phy
-			 **/
+			 */
 				active_external_phy = EXT_PHY1;
 				break;
 			case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
-			/**
+			/*
 			 * In this option, the first PHY makes sure to pass the
 			 * traffic through the second PHY.
-			 **/
+			 */
 				active_external_phy = EXT_PHY2;
 				break;
 			default:
-			/**
+			/*
 			 * Link indication on both PHYs with the following cases
 			 * is invalid:
 			 * - FIRST_PHY means that second phy wasn't initialized,
@@ -3570,7 +3547,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 			 * - SECOND_PHY means that first phy should not be able
 			 * to link up by itself (using configuration)
 			 * - DEFAULT should be overriden during initialiazation
-			 **/
+			 */
 				DP(NETIF_MSG_LINK, "Invalid link indication"
 					   "mpc=0x%x. DISABLING LINK !!!\n",
 					   params->multi_phy_config);
@@ -3580,18 +3557,18 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 		}
 	}
 	prev_line_speed = vars->line_speed;
-	/**
-	* Step 2:
-	* Read the status of the internal phy. In case of
-	* DIRECT_SINGLE_MEDIA board, this link is the external link,
-	* otherwise this is the link between the 577xx and the first
-	* external phy
-	*/
+	/*
+	 * Step 2:
+	 * Read the status of the internal phy. In case of
+	 * DIRECT_SINGLE_MEDIA board, this link is the external link,
+	 * otherwise this is the link between the 577xx and the first
+	 * external phy
+	 */
 	if (params->phy[INT_PHY].read_status)
 		params->phy[INT_PHY].read_status(
 			&params->phy[INT_PHY],
 			params, vars);
-	/**
+	/*
 	 * The INT_PHY flow control reside in the vars. This include the
 	 * case where the speed or flow control are not set to AUTO.
 	 * Otherwise, the active external phy flow control result is set
@@ -3601,13 +3578,13 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 	 */
 	if (active_external_phy > INT_PHY) {
 		vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
-		/**
+		/*
 		 * Link speed is taken from the XGXS. AN and FC result from
 		 * the external phy.
 		 */
 		vars->link_status |= phy_vars[active_external_phy].link_status;
 
-		/**
+		/*
 		 * if active_external_phy is first PHY and link is up - disable
 		 * disable TX on second external PHY
 		 */
@@ -3643,7 +3620,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 	DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
 		   " ext_phy_line_speed = %d\n", vars->flow_ctrl,
 		   vars->link_status, ext_phy_line_speed);
-	/**
+	/*
 	 * Upon link speed change set the NIG into drain mode. Comes to
 	 * deals with possible FIFO glitch due to clk change when speed
 	 * is decreased without link down indicator
@@ -3658,8 +3635,8 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 				   ext_phy_line_speed);
 			vars->phy_link_up = 0;
 		} else if (prev_line_speed != vars->line_speed) {
-			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
-				     + params->port*4, 0);
+			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
+			       0);
 			msleep(1);
 		}
 	}
@@ -3674,14 +3651,14 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 
 	bnx2x_link_int_ack(params, vars, link_10g);
 
-	/**
-	* In case external phy link is up, and internal link is down
-	* (not initialized yet probably after link initialization, it
-	* needs to be initialized.
-	* Note that after link down-up as result of cable plug, the xgxs
-	* link would probably become up again without the need
-	* initialize it
-	*/
+	/*
+	 * In case external phy link is up, and internal link is down
+	 * (not initialized yet probably after link initialization, it
+	 * needs to be initialized.
+	 * Note that after link down-up as result of cable plug, the xgxs
+	 * link would probably become up again without the need
+	 * initialize it
+	 */
 	if (!(SINGLE_MEDIA_DIRECT(params))) {
 		DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
 			   " init_preceding = %d\n", ext_phy_link_up,
@@ -3701,9 +3678,9 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 						vars);
 		}
 	}
-	/**
-	 *  Link is up only if both local phy and external phy (in case of
-	 *  non-direct board) are up
+	/*
+	 * Link is up only if both local phy and external phy (in case of
+	 * non-direct board) are up
 	 */
 	vars->link_up = (vars->phy_link_up &&
 			 (ext_phy_link_up ||
@@ -3724,10 +3701,10 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
 void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
 {
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 	msleep(1);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
 }
 
 static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
@@ -3747,9 +3724,9 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp,
 	u16 fw_ver1, fw_ver2;
 
 	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+			MDIO_PMA_REG_ROM_VER1, &fw_ver1);
 	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2, &fw_ver2);
+			MDIO_PMA_REG_ROM_VER2, &fw_ver2);
 	bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
 				  phy->ver_addr);
 }
@@ -3770,7 +3747,7 @@ static void bnx2x_ext_phy_set_pause(struct link_params *params,
 	if ((vars->ieee_fc &
 	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
 	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
-		val |=  MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+		val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
 	}
 	if ((vars->ieee_fc &
 	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
@@ -3801,11 +3778,11 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
 	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
 		ret = 1;
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_AN_DEVAD,
-			      MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_ADV_PAUSE, &ld_pause);
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_AN_DEVAD,
-			      MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
 		pause_result = (ld_pause &
 				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
 		pause_result |= (lp_pause &
@@ -3881,31 +3858,31 @@ static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
 	/* Boot port from external ROM  */
 	/* EDC grst */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x0001);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 0x0001);
 
 	/* ucode reboot and rst */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x008c);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 0x008c);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
 
 	/* Reset internal microprocessor */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
 
 	/* Release srst bit */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
 
 	/* Delay 100ms per the PHY specifications */
 	msleep(100);
@@ -3936,8 +3913,8 @@ static u8 bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
 
 	/* Clear ser_boot_ctl bit */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
 	bnx2x_save_bcm_spirom_ver(bp, phy, port);
 
 	DP(NETIF_MSG_LINK,
@@ -3958,8 +3935,8 @@ static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
 
 	/* Read 8073 HW revision*/
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8073_CHIP_REV, &val);
 
 	if (val != 1) {
 		/* No need to workaround in 8073 A1 */
@@ -3967,8 +3944,8 @@ static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy)
 	}
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_ROM_VER2, &val);
 
 	/* SNR should be applied only for version 0x102 */
 	if (val != 0x102)
@@ -3982,8 +3959,8 @@ static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
 	u16 val, cnt, cnt1 ;
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8073_CHIP_REV, &val);
 
 	if (val > 0) {
 		/* No need to workaround in 8073 A1 */
@@ -3991,26 +3968,32 @@ static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy)
 	}
 	/* XAUI workaround in 8073 A0: */
 
-	/* After loading the boot ROM and restarting Autoneg,
-	poll Dev1, Reg $C820: */
+	/*
+	 * After loading the boot ROM and restarting Autoneg, poll
+	 * Dev1, Reg $C820:
+	 */
 
 	for (cnt = 0; cnt < 1000; cnt++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
-			      &val);
-		  /* If bit [14] = 0 or bit [13] = 0, continue on with
-		   system initialization (XAUI work-around not required,
-		    as these bits indicate 2.5G or 1G link up). */
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
+				&val);
+		  /*
+		   * If bit [14] = 0 or bit [13] = 0, continue on with
+		   * system initialization (XAUI work-around not required, as
+		   * these bits indicate 2.5G or 1G link up).
+		   */
 		if (!(val & (1<<14)) || !(val & (1<<13))) {
 			DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
 			return 0;
 		} else if (!(val & (1<<15))) {
-			DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
-			 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
-			  it's MSB (bit 15) goes to 1 (indicating that the
-			  XAUI workaround has completed),
-			  then continue on with system initialization.*/
+			DP(NETIF_MSG_LINK, "bit 15 went off\n");
+			/*
+			 * If bit 15 is 0, then poll Dev1, Reg $C841 until it's
+			 * MSB (bit15) goes to 1 (indicating that the XAUI
+			 * workaround has completed), then continue on with
+			 * system initialization.
+			 */
 			for (cnt1 = 0; cnt1 < 1000; cnt1++) {
 				bnx2x_cl45_read(bp, phy,
 					MDIO_PMA_DEVAD,
@@ -4093,10 +4076,10 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 		gpio_port = params->port;
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
 
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
 
 	/* enable LASI */
 	bnx2x_cl45_write(bp, phy,
@@ -4114,10 +4097,6 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 
 	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
 
-	/**
-	 * If this is forced speed, set to KR or KX (all other are not
-	 * supported)
-	 */
 	/* Swap polarity if required - Must be done only in non-1G mode */
 	if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
 		/* Configure the 8073 to swap _P and _N of the KR lines */
@@ -4160,8 +4139,10 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 			val = (1<<7);
 		} else if (phy->req_line_speed ==  SPEED_2500) {
 			val = (1<<5);
-			/* Note that 2.5G works only
-			when used with 1G advertisment */
+			/*
+			 * Note that 2.5G works only when used with 1G
+			 * advertisment
+			 */
 		} else
 			val = (1<<5);
 	} else {
@@ -4170,8 +4151,7 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 			PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 			val |= (1<<7);
 
-		/* Note that 2.5G works only when
-		used with 1G advertisment */
+		/* Note that 2.5G works only when used with 1G advertisment */
 		if (phy->speed_cap_mask &
 			(PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
 			 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
@@ -4211,9 +4191,11 @@ static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy,
 	/* Add support for CL37 (passive mode) III */
 	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
 
-	/* The SNR will improve about 2db by changing
-	BW and FEE main tap. Rest commands are executed
-	after link is up*/
+	/*
+	 * The SNR will improve about 2db by changing BW and FEE main
+	 * tap. Rest commands are executed after link is up
+	 * Change FFE main cursor to 5 in EDC register
+	 */
 	if (bnx2x_8073_is_snr_needed(bp, phy))
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
@@ -4297,12 +4279,11 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
 
 	link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
 	if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) {
-		/* The SNR will improve about 2dbby
-		changing the BW and FEE main tap.*/
-		/* The 1st write to change FFE main
-		tap is set before restart AN */
-		/* Change PLL Bandwidth in EDC
-		register */
+		/*
+		 * The SNR will improve about 2dbby changing the BW and FEE main
+		 * tap. The 1st write to change FFE main tap is set before
+		 * restart AN. Change PLL Bandwidth in EDC register
+		 */
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
 				 0x26BC);
@@ -4346,10 +4327,10 @@ static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy,
 			bnx2x_cl45_read(bp, phy,
 					MDIO_XS_DEVAD,
 					MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1);
-			/**
-			* Set bit 3 to invert Rx in 1G mode and clear this bit
-			* when it`s in 10G mode.
-			*/
+			/*
+			 * Set bit 3 to invert Rx in 1G mode and clear this bit
+			 * when it`s in 10G mode.
+			 */
 			if (vars->line_speed == SPEED_1000) {
 				DP(NETIF_MSG_LINK, "Swapping 1G polarity for"
 					      "the 8073\n");
@@ -4381,8 +4362,8 @@ static void bnx2x_8073_link_reset(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
 	   gpio_port);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       gpio_port);
 }
 
 /******************************************************************/
@@ -4396,11 +4377,11 @@ static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "init 8705\n");
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
@@ -4451,35 +4432,79 @@ static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy,
 /******************************************************************/
 /*			SFP+ module Section			  */
 /******************************************************************/
-static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
+static u8 bnx2x_get_gpio_port(struct link_params *params)
+{
+	u8 gpio_port;
+	u32 swap_val, swap_override;
+	struct bnx2x *bp = params->bp;
+	if (CHIP_IS_E2(bp))
+		gpio_port = BP_PATH(bp);
+	else
+		gpio_port = params->port;
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+	return gpio_port ^ (swap_val && swap_override);
+}
+static void bnx2x_sfp_set_transmitter(struct link_params *params,
 				      struct bnx2x_phy *phy,
-				      u8 port,
 				      u8 tx_en)
 {
 	u16 val;
+	u8 port = params->port;
+	struct bnx2x *bp = params->bp;
+	u32 tx_en_mode;
 
-	DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
-		 tx_en, port);
 	/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_PHY_IDENTIFIER,
-		      &val);
+	tx_en_mode = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+				     dev_info.port_hw_config[port].sfp_ctrl)) &
+		PORT_HW_CFG_TX_LASER_MASK;
+	DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x "
+			   "mode = %x\n", tx_en, port, tx_en_mode);
+	switch (tx_en_mode) {
+	case PORT_HW_CFG_TX_LASER_MDIO:
 
-	if (tx_en)
-		val &= ~(1<<15);
-	else
-		val |= (1<<15);
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_PHY_IDENTIFIER,
+				&val);
 
-	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       val);
+		if (tx_en)
+			val &= ~(1<<15);
+		else
+			val |= (1<<15);
+
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_PHY_IDENTIFIER,
+				 val);
+	break;
+	case PORT_HW_CFG_TX_LASER_GPIO0:
+	case PORT_HW_CFG_TX_LASER_GPIO1:
+	case PORT_HW_CFG_TX_LASER_GPIO2:
+	case PORT_HW_CFG_TX_LASER_GPIO3:
+	{
+		u16 gpio_pin;
+		u8 gpio_port, gpio_mode;
+		if (tx_en)
+			gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_HIGH;
+		else
+			gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_LOW;
+
+		gpio_pin = tx_en_mode - PORT_HW_CFG_TX_LASER_GPIO0;
+		gpio_port = bnx2x_get_gpio_port(params);
+		bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port);
+		break;
+	}
+	default:
+		DP(NETIF_MSG_LINK, "Invalid TX_LASER_MDIO 0x%x\n", tx_en_mode);
+		break;
+	}
 }
 
 static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 					    struct link_params *params,
-					  u16 addr, u8 byte_cnt, u8 *o_buf)
+					    u16 addr, u8 byte_cnt, u8 *o_buf)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0;
@@ -4492,23 +4517,23 @@ static u8 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 | 0xa000));
 
 	/* Set the read command address */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-		       addr);
+			 addr);
 
 	/* Activate read command */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		       0x2c0f);
+			 0x2c0f);
 
 	/* Wait up to 500us for command complete status */
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
 			break;
@@ -4526,15 +4551,15 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	/* Read the buffer */
 	for (i = 0; i < byte_cnt; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
 		o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
 	}
 
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
 			return 0;
@@ -4545,7 +4570,7 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 
 static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 					    struct link_params *params,
-					  u16 addr, u8 byte_cnt, u8 *o_buf)
+					    u16 addr, u8 byte_cnt, u8 *o_buf)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val, i;
@@ -4558,41 +4583,43 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 
 	/* Need to read from 1.8000 to clear it */
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		      &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+			&val);
 
 	/* Set the read command byte count */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
-		       ((byte_cnt < 2) ? 2 : byte_cnt));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
+			 ((byte_cnt < 2) ? 2 : byte_cnt));
 
 	/* Set the read command address */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-		       addr);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
+			 addr);
 	/* Set the destination address */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       0x8004,
-		       MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
+			 MDIO_PMA_DEVAD,
+			 0x8004,
+			 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
 
 	/* Activate read command */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		       0x8002);
-	/* Wait appropriate time for two-wire command to finish before
-	polling the status register */
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+			 0x8002);
+	/*
+	 * Wait appropriate time for two-wire command to finish before
+	 * polling the status register
+	 */
 	msleep(1);
 
 	/* Wait up to 500us for command complete status */
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
 			break;
@@ -4604,21 +4631,21 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 		DP(NETIF_MSG_LINK,
 			 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
 			 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	/* Read the buffer */
 	for (i = 0; i < byte_cnt; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
 		o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
 	}
 
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
 			return 0;
@@ -4628,22 +4655,22 @@ static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 	return -EINVAL;
 }
 
-static u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				       struct link_params *params, u16 addr,
-				       u8 byte_cnt, u8 *o_buf)
+u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+				struct link_params *params, u16 addr,
+				u8 byte_cnt, u8 *o_buf)
 {
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
 		return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
-						       byte_cnt, o_buf);
+							 byte_cnt, o_buf);
 	else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
 		return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
-						       byte_cnt, o_buf);
+							 byte_cnt, o_buf);
 	return -EINVAL;
 }
 
 static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 			     struct link_params *params,
-				  u16 *edc_mode)
+			     u16 *edc_mode)
 {
 	struct bnx2x *bp = params->bp;
 	u8 val, check_limiting_mode = 0;
@@ -4664,8 +4691,10 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 	{
 		u8 copper_module_type;
 
-		/* Check if its active cable( includes SFP+ module)
-		of passive cable*/
+		/*
+		 * Check if its active cable (includes SFP+ module)
+		 * of passive cable
+		 */
 		if (bnx2x_read_sfp_module_eeprom(phy,
 					       params,
 					       SFP_EEPROM_FC_TX_TECH_ADDR,
@@ -4724,8 +4753,10 @@ static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
 	return 0;
 }
-/* This function read the relevant field from the module ( SFP+ ),
-	and verify it is compliant with this board */
+/*
+ * This function read the relevant field from the module (SFP+), and verify it
+ * is compliant with this board
+ */
 static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
 				  struct link_params *params)
 {
@@ -4774,24 +4805,24 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
 	/* format the warning message */
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
-				       SFP_EEPROM_VENDOR_NAME_ADDR,
-				       SFP_EEPROM_VENDOR_NAME_SIZE,
-				       (u8 *)vendor_name))
+					 SFP_EEPROM_VENDOR_NAME_ADDR,
+					 SFP_EEPROM_VENDOR_NAME_SIZE,
+					 (u8 *)vendor_name))
 		vendor_name[0] = '\0';
 	else
 		vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
-				       SFP_EEPROM_PART_NO_ADDR,
-				       SFP_EEPROM_PART_NO_SIZE,
-				       (u8 *)vendor_pn))
+					 SFP_EEPROM_PART_NO_ADDR,
+					 SFP_EEPROM_PART_NO_SIZE,
+					 (u8 *)vendor_pn))
 		vendor_pn[0] = '\0';
 	else
 		vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
 
-	netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected,"
-			     " Port %d from %s part number %s\n",
-		    params->port, vendor_name, vendor_pn);
+	netdev_err(bp->dev,  "Warning: Unqualified SFP+ module detected,"
+			      " Port %d from %s part number %s\n",
+			 params->port, vendor_name, vendor_pn);
 	phy->flags |= FLAGS_SFP_NOT_APPROVED;
 	return -EINVAL;
 }
@@ -4803,8 +4834,11 @@ static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 	u8 val;
 	struct bnx2x *bp = params->bp;
 	u16 timeout;
-	/* Initialization time after hot-plug may take up to 300ms for some
-	phys type ( e.g. JDSU ) */
+	/*
+	 * Initialization time after hot-plug may take up to 300ms for
+	 * some phys type ( e.g. JDSU )
+	 */
+
 	for (timeout = 0; timeout < 60; timeout++) {
 		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
 		    == 0) {
@@ -4823,16 +4857,14 @@ static void bnx2x_8727_power_module(struct bnx2x *bp,
 	/* Make sure GPIOs are not using for LED mode */
 	u16 val;
 	/*
-	 * In the GPIO register, bit 4 is use to detemine if the GPIOs are
+	 * In the GPIO register, bit 4 is use to determine if the GPIOs are
 	 * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
 	 * output
 	 * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
 	 * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
 	 * where the 1st bit is the over-current(only input), and 2nd bit is
 	 * for power( only output )
-	*/
-
-	/*
+	 *
 	 * In case of NOC feature is disabled and power is up, set GPIO control
 	 *  as input to enable listening of over-current indication
 	 */
@@ -4861,15 +4893,14 @@ static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
 	u16 cur_limiting_mode;
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2,
-		      &cur_limiting_mode);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_ROM_VER2,
+			&cur_limiting_mode);
 	DP(NETIF_MSG_LINK, "Current Limiting mode is 0x%x\n",
 		 cur_limiting_mode);
 
 	if (edc_mode == EDC_MODE_LIMITING) {
-		DP(NETIF_MSG_LINK,
-			 "Setting LIMITING MODE\n");
+		DP(NETIF_MSG_LINK, "Setting LIMITING MODE\n");
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD,
 				 MDIO_PMA_REG_ROM_VER2,
@@ -4878,62 +4909,63 @@ static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp,
 
 		DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
 
-		/* Changing to LRM mode takes quite few seconds.
-		So do it only if current mode is limiting
-		( default is LRM )*/
+		/*
+		 * Changing to LRM mode takes quite few seconds. So do it only
+		 * if current mode is limiting (default is LRM)
+		 */
 		if (cur_limiting_mode != EDC_MODE_LIMITING)
 			return 0;
 
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_LRM_MODE,
-			       0);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_LRM_MODE,
+				 0);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_ROM_VER2,
-			       0x128);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_ROM_VER2,
+				 0x128);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_MISC_CTRL0,
-			       0x4008);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_MISC_CTRL0,
+				 0x4008);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_LRM_MODE,
-			       0xaaaa);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_LRM_MODE,
+				 0xaaaa);
 	}
 	return 0;
 }
 
 static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
 				       struct bnx2x_phy *phy,
-					u16 edc_mode)
+				       u16 edc_mode)
 {
 	u16 phy_identifier;
 	u16 rom_ver2_val;
 	bnx2x_cl45_read(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       &phy_identifier);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_PHY_IDENTIFIER,
+			&phy_identifier);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       (phy_identifier & ~(1<<9)));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_PHY_IDENTIFIER,
+			 (phy_identifier & ~(1<<9)));
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2,
-		      &rom_ver2_val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_ROM_VER2,
+			&rom_ver2_val);
 	/* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_ROM_VER2,
-		       (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_ROM_VER2,
+			 (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       (phy_identifier | (1<<9)));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_PHY_IDENTIFIER,
+			 (phy_identifier | (1<<9)));
 
 	return 0;
 }
@@ -4946,11 +4978,11 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
 
 	switch (action) {
 	case DISABLE_TX:
-		bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+		bnx2x_sfp_set_transmitter(params, phy, 0);
 		break;
 	case ENABLE_TX:
 		if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
-			bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
+			bnx2x_sfp_set_transmitter(params, phy, 1);
 		break;
 	default:
 		DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
@@ -4959,6 +4991,38 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy,
 	}
 }
 
+static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+					   u8 gpio_mode)
+{
+	struct bnx2x *bp = params->bp;
+
+	u32 fault_led_gpio = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].sfp_ctrl)) &
+		PORT_HW_CFG_FAULT_MODULE_LED_MASK;
+	switch (fault_led_gpio) {
+	case PORT_HW_CFG_FAULT_MODULE_LED_DISABLED:
+		return;
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO0:
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO1:
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO2:
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO3:
+	{
+		u8 gpio_port = bnx2x_get_gpio_port(params);
+		u16 gpio_pin = fault_led_gpio -
+			PORT_HW_CFG_FAULT_MODULE_LED_GPIO0;
+		DP(NETIF_MSG_LINK, "Set fault module-detected led "
+				   "pin %x port %x mode %x\n",
+			       gpio_pin, gpio_port, gpio_mode);
+		bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port);
+	}
+	break;
+	default:
+		DP(NETIF_MSG_LINK, "Error: Invalid fault led mode 0x%x\n",
+			       fault_led_gpio);
+	}
+}
+
 static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 				     struct link_params *params)
 {
@@ -4976,15 +5040,14 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 	if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
 		DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
 		return -EINVAL;
-	} else if (bnx2x_verify_sfp_module(phy, params) !=
-		   0) {
+	} else if (bnx2x_verify_sfp_module(phy, params) != 0) {
 		/* check SFP+ module compatibility */
 		DP(NETIF_MSG_LINK, "Module verification failed!!\n");
 		rc = -EINVAL;
 		/* Turn on fault module-detected led */
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				  MISC_REGISTERS_GPIO_HIGH,
-				  params->port);
+		bnx2x_set_sfp_module_fault_led(params,
+					       MISC_REGISTERS_GPIO_HIGH);
+
 		if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
 		    ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
@@ -4995,18 +5058,17 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 		}
 	} else {
 		/* Turn off fault module-detected led */
-		DP(NETIF_MSG_LINK, "Turn off fault module-detected led\n");
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-					  MISC_REGISTERS_GPIO_LOW,
-					  params->port);
+		bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
 	}
 
 	/* power up the SFP module */
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
 		bnx2x_8727_power_module(bp, phy, 1);
 
-	/* Check and set limiting mode / LRM mode on 8726.
-	On 8727 it is done automatically */
+	/*
+	 * Check and set limiting mode / LRM mode on 8726. On 8727 it
+	 * is done automatically
+	 */
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
 		bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
 	else
@@ -5018,9 +5080,9 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 	if (rc == 0 ||
 	    (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
 	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-		bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
+		bnx2x_sfp_set_transmitter(params, phy, 1);
 	else
-		bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+		bnx2x_sfp_set_transmitter(params, phy, 0);
 
 	return rc;
 }
@@ -5033,11 +5095,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 	u8 port = params->port;
 
 	/* Set valid module led off */
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-			  MISC_REGISTERS_GPIO_HIGH,
-			  params->port);
+	bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
 
-	/* Get current gpio val refelecting module plugged in / out*/
+	/* Get current gpio val reflecting module plugged in / out*/
 	gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
 
 	/* Call the handling function in case module is detected */
@@ -5053,18 +5113,20 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
 	} else {
 		u32 val = REG_RD(bp, params->shmem_base +
-				     offsetof(struct shmem_region, dev_info.
-					      port_feature_config[params->port].
-					      config));
+				 offsetof(struct shmem_region, dev_info.
+					  port_feature_config[params->port].
+					  config));
 
 		bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
 				   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
 				   port);
-		/* Module was plugged out. */
-		/* Disable transmit for this module */
+		/*
+		 * Module was plugged out.
+		 * Disable transmit for this module
+		 */
 		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+			bnx2x_sfp_set_transmitter(params, phy, 0);
 	}
 }
 
@@ -5100,9 +5162,9 @@ static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy,
 
 	DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
 			" link_status 0x%x\n", rx_sd, pcs_status, val2);
-	/* link is up if both bit 0 of pmd_rx_sd and
-	 * bit 0 of pcs_status are set, or if the autoneg bit
-	 * 1 is set
+	/*
+	 * link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
+	 * are set, or if the autoneg bit 1 is set
 	 */
 	link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
 	if (link_up) {
@@ -5123,14 +5185,15 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
 				 struct link_params *params,
 				 struct link_vars *vars)
 {
-	u16 cnt, val;
+	u32 tx_en_mode;
+	u16 cnt, val, tmp1;
 	struct bnx2x *bp = params->bp;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	/* Wait until fw is loaded */
 	for (cnt = 0; cnt < 100; cnt++) {
@@ -5197,6 +5260,26 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy,
 				 0x0004);
 	}
 	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
+
+	/*
+	 * If TX Laser is controlled by GPIO_0, do not let PHY go into low
+	 * power mode, if TX Laser is disabled
+	 */
+
+	tx_en_mode = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+				dev_info.port_hw_config[params->port].sfp_ctrl))
+			& PORT_HW_CFG_TX_LASER_MASK;
+
+	if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
+		DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n");
+		bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, &tmp1);
+		tmp1 |= 0x1;
+		bnx2x_cl45_write(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, tmp1);
+	}
+
 	return 0;
 }
 
@@ -5231,26 +5314,26 @@ static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy,
 
 	/* Set soft reset */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
 
 	/* wait for 150ms for microcode load */
 	msleep(150);
 
 	/* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
 
 	msleep(200);
 	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
@@ -5285,23 +5368,18 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
 	u32 val;
 	u32 swap_val, swap_override, aeu_gpio_mask, offset;
 	DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
-	/* Restore normal power mode*/
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
-
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_8726_external_rom_boot(phy, params);
 
-	/* Need to call module detected on initialization since
-	the module detection triggered by actual module
-	insertion might occur before driver is loaded, and when
-	driver is loaded, it reset all registers, including the
-	transmitter */
+	/*
+	 * Need to call module detected on initialization since the module
+	 * detection triggered by actual module insertion might occur before
+	 * driver is loaded, and when driver is loaded, it reset all
+	 * registers, including the transmitter
+	 */
 	bnx2x_sfp_module_detection(phy, params);
 
 	if (phy->req_line_speed == SPEED_1000) {
@@ -5334,8 +5412,10 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
 		bnx2x_cl45_write(bp, phy,
 				MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
-		/* Enable RX-ALARM control to receive
-		interrupt for 1G speed change */
+		/*
+		 * Enable RX-ALARM control to receive interrupt for 1G speed
+		 * change
+		 */
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
 		bnx2x_cl45_write(bp, phy,
@@ -5367,7 +5447,7 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy,
 
 	/* Set GPIO3 to trigger SFP+ module insertion/removal */
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			    MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
+		       MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
 
 	/* The GPIO should be swapped if the swap register is set and active */
 	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
@@ -5458,7 +5538,7 @@ static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
 				struct link_params *params) {
 	u32 swap_val, swap_override;
 	u8 port;
-	/**
+	/*
 	 * The PHY reset is controlled by GPIO 1. Fake the port number
 	 * to cancel the swap done in set_gpio()
 	 */
@@ -5467,20 +5547,21 @@ static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy,
 	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
 	port = (swap_val && swap_override) ^ 1;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 }
 
 static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 				 struct link_params *params,
 				 struct link_vars *vars)
 {
-	u16 tmp1, val, mod_abs;
+	u32 tx_en_mode;
+	u16 tmp1, val, mod_abs, tmp2;
 	u16 rx_alarm_ctrl_val;
 	u16 lasi_ctrl_val;
 	struct bnx2x *bp = params->bp;
 	/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 	rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
 	lasi_ctrl_val = 0x0004;
 
@@ -5493,14 +5574,17 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
 
-	/* Initially configure  MOD_ABS to interrupt when
-	module is presence( bit 8) */
+	/*
+	 * Initially configure MOD_ABS to interrupt when module is
+	 * presence( bit 8)
+	 */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
-	/* Set EDC off by setting OPTXLOS signal input to low
-	(bit 9).
-	When the EDC is off it locks onto a reference clock and
-	avoids becoming 'lost'.*/
+	/*
+	 * Set EDC off by setting OPTXLOS signal input to low (bit 9).
+	 * When the EDC is off it locks onto a reference clock and avoids
+	 * becoming 'lost'
+	 */
 	mod_abs &= ~(1<<8);
 	if (!(phy->flags & FLAGS_NOC))
 		mod_abs &= ~(1<<9);
@@ -5515,7 +5599,7 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 	if (phy->flags & FLAGS_NOC)
 		val |= (3<<5);
 
-	/**
+	/*
 	 * Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
 	 * status which reflect SFP+ module over-current
 	 */
@@ -5542,7 +5626,7 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
 		DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
-		/**
+		/*
 		 * Power down the XAUI until link is up in case of dual-media
 		 * and 1G
 		 */
@@ -5568,7 +5652,7 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
 	} else {
-		/**
+		/*
 		 * Since the 8727 has only single reset pin, need to set the 10G
 		 * registers although it is default
 		 */
@@ -5584,7 +5668,8 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 				 0x0008);
 	}
 
-	/* Set 2-wire transfer rate of SFP+ module EEPROM
+	/*
+	 * Set 2-wire transfer rate of SFP+ module EEPROM
 	 * to 100Khz since some DACs(direct attached cables) do
 	 * not work at 400Khz.
 	 */
@@ -5607,6 +5692,26 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 				 phy->tx_preemphasis[1]);
 	}
 
+	/*
+	 * If TX Laser is controlled by GPIO_0, do not let PHY go into low
+	 * power mode, if TX Laser is disabled
+	 */
+	tx_en_mode = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+				dev_info.port_hw_config[params->port].sfp_ctrl))
+			& PORT_HW_CFG_TX_LASER_MASK;
+
+	if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
+
+		DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n");
+		bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, &tmp2);
+		tmp2 |= 0x1000;
+		tmp2 &= 0xFFEF;
+		bnx2x_cl45_write(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2);
+	}
+
 	return 0;
 }
 
@@ -5620,46 +5725,49 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 				      port_feature_config[params->port].
 				      config));
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
 	if (mod_abs & (1<<8)) {
 
 		/* Module is absent */
 		DP(NETIF_MSG_LINK, "MOD_ABS indication "
 			    "show module is absent\n");
 
-		/* 1. Set mod_abs to detect next module
-		presence event
-		   2. Set EDC off by setting OPTXLOS signal input to low
-			(bit 9).
-			When the EDC is off it locks onto a reference clock and
-			avoids becoming 'lost'.*/
+		/*
+		 * 1. Set mod_abs to detect next module
+		 *    presence event
+		 * 2. Set EDC off by setting OPTXLOS signal input to low
+		 *    (bit 9).
+		 *    When the EDC is off it locks onto a reference clock and
+		 *    avoids becoming 'lost'.
+		 */
 		mod_abs &= ~(1<<8);
 		if (!(phy->flags & FLAGS_NOC))
 			mod_abs &= ~(1<<9);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
 
-		/* Clear RX alarm since it stays up as long as
-		the mod_abs wasn't changed */
+		/*
+		 * Clear RX alarm since it stays up as long as
+		 * the mod_abs wasn't changed
+		 */
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
 
 	} else {
 		/* Module is present */
 		DP(NETIF_MSG_LINK, "MOD_ABS indication "
 			    "show module is present\n");
-		/* First thing, disable transmitter,
-		and if the module is ok, the
-		module_detection will enable it*/
-
-		/* 1. Set mod_abs to detect next module
-		absent event ( bit 8)
-		   2. Restore the default polarity of the OPRXLOS signal and
-		this signal will then correctly indicate the presence or
-		absence of the Rx signal. (bit 9) */
+		/*
+		 * First disable transmitter, and if the module is ok, the
+		 * module_detection will enable it
+		 * 1. Set mod_abs to detect next module absent event ( bit 8)
+		 * 2. Restore the default polarity of the OPRXLOS signal and
+		 * this signal will then correctly indicate the presence or
+		 * absence of the Rx signal. (bit 9)
+		 */
 		mod_abs |= (1<<8);
 		if (!(phy->flags & FLAGS_NOC))
 			mod_abs |= (1<<9);
@@ -5667,10 +5775,12 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 				 MDIO_PMA_DEVAD,
 				 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
 
-		/* Clear RX alarm since it stays up as long as
-		the mod_abs wasn't changed. This is need to be done
-		before calling the module detection, otherwise it will clear
-		the link update alarm */
+		/*
+		 * Clear RX alarm since it stays up as long as the mod_abs
+		 * wasn't changed. This is need to be done before calling the
+		 * module detection, otherwise it will clear* the link update
+		 * alarm
+		 */
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
@@ -5678,7 +5788,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 
 		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+			bnx2x_sfp_set_transmitter(params, phy, 0);
 
 		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
 			bnx2x_sfp_module_detection(phy, params);
@@ -5687,9 +5797,8 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy,
 	}
 
 	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
-		 rx_alarm_status);
-	/* No need to check link status in case of
-	module plugged in/out */
+		   rx_alarm_status);
+	/* No need to check link status in case of module plugged in/out */
 }
 
 static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
@@ -5725,7 +5834,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
 
-	/**
+	/*
 	 * If a module is present and there is need to check
 	 * for over current
 	 */
@@ -5745,12 +5854,8 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 					    " Please remove the SFP+ module and"
 					    " restart the system to clear this"
 					    " error.\n",
-				   params->port);
-
-			/*
-			 * Disable all RX_ALARMs except for
-			 * mod_abs
-			 */
+			 params->port);
+			/* Disable all RX_ALARMs except for mod_abs */
 			bnx2x_cl45_write(bp, phy,
 					 MDIO_PMA_DEVAD,
 					 MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
@@ -5793,11 +5898,15 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 			MDIO_PMA_DEVAD,
 			MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
 
-	/* Bits 0..2 --> speed detected,
-	   bits 13..15--> link is down */
+	/*
+	 * Bits 0..2 --> speed detected,
+	 * Bits 13..15--> link is down
+	 */
 	if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
 		link_up = 1;
 		vars->line_speed = SPEED_10000;
+		DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
+			   params->port);
 	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
 		link_up = 1;
 		vars->line_speed = SPEED_1000;
@@ -5819,7 +5928,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_REG_8727_PCS_GP, &val1);
-		/**
+		/*
 		 * In case of dual-media board and 1G, power up the XAUI side,
 		 * otherwise power it down. For 10G it is done automatically
 		 */
@@ -5839,7 +5948,7 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	/* Disable Transmitter */
-	bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+	bnx2x_sfp_set_transmitter(params, phy, 0);
 	/* Clear LASI */
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
 
@@ -5851,19 +5960,23 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy,
 static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 					   struct link_params *params)
 {
-	u16 val, fw_ver1, fw_ver2, cnt;
+	u16 val, fw_ver1, fw_ver2, cnt, adj;
 	struct bnx2x *bp = params->bp;
 
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = -1;
+
 	/* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
 	/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0014);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, 0x0300);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x0009);
 
 	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
 		if (val & 1)
 			break;
 		udelay(5);
@@ -5877,11 +5990,11 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 
 
 	/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x000A);
 	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
 		if (val & 1)
 			break;
 		udelay(5);
@@ -5894,9 +6007,9 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 	}
 
 	/* lower 16 bits of the register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, &fw_ver1);
 	/* upper 16 bits of register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, &fw_ver2);
 
 	bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
 				  phy->ver_addr);
@@ -5905,49 +6018,53 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
 				struct bnx2x_phy *phy)
 {
-	u16 val;
+	u16 val, adj;
+
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = -1;
 
 	/* PHYC_CTL_LED_CTL */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
+			MDIO_PMA_REG_8481_LINK_SIGNAL + adj, &val);
 	val &= 0xFE00;
 	val |= 0x0092;
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
+			 MDIO_PMA_REG_8481_LINK_SIGNAL + adj, val);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED1_MASK,
+			 MDIO_PMA_REG_8481_LED1_MASK + adj,
 			 0x80);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED2_MASK,
+			 MDIO_PMA_REG_8481_LED2_MASK + adj,
 			 0x18);
 
 	/* Select activity source by Tx and Rx, as suggested by PHY AE */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED3_MASK,
+			 MDIO_PMA_REG_8481_LED3_MASK + adj,
 			 0x0006);
 
 	/* Select the closest activity blink rate to that in 10/100/1000 */
 	bnx2x_cl45_write(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LED3_BLINK,
+			MDIO_PMA_REG_8481_LED3_BLINK + adj,
 			0);
 
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
+			MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, &val);
 	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
+			 MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, val);
 
 	/* 'Interrupt Mask' */
 	bnx2x_cl45_write(bp, phy,
@@ -5961,7 +6078,11 @@ static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u16 autoneg_val, an_1000_val, an_10_100_val;
-
+	/*
+	 * This phy uses the NIG latch mechanism since link indication
+	 * arrives through its LED4 and not via its LASI signal, so we
+	 * get steady signal instead of clear on read
+	 */
 	bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
 		      1 << NIG_LATCH_BC_ENABLE_MI_INT);
 
@@ -6086,11 +6207,11 @@ static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy,
 	struct bnx2x *bp = params->bp;
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
 	return bnx2x_848xx_cmn_config_init(phy, params, vars);
@@ -6102,12 +6223,15 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 {
 	struct bnx2x *bp = params->bp;
 	u8 port, initialize = 1;
-	u16 val;
+	u16 val, adj;
 	u16 temp;
-	u32 actual_phy_selection;
+	u32 actual_phy_selection, cms_enable;
 	u8 rc = 0;
 
 	/* This is just for MDIO_CTL_REG_84823_MEDIA register. */
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = 3;
 
 	msleep(1);
 	if (CHIP_IS_E2(bp))
@@ -6117,11 +6241,12 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
 		       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
 		       port);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 	/* Wait for GPHY to come out of reset */
 	msleep(50);
-	/* BCM84823 requires that XGXS links up first @ 10G for normal
-	behavior */
+	/*
+	 * BCM84823 requires that XGXS links up first @ 10G for normal behavior
+	 */
 	temp = vars->line_speed;
 	vars->line_speed = SPEED_10000;
 	bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
@@ -6131,7 +6256,7 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 	/* Set dual-media configuration according to configuration */
 
 	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_CTL_REG_84823_MEDIA, &val);
+			MDIO_CTL_REG_84823_MEDIA + adj, &val);
 	val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
@@ -6164,7 +6289,7 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
 
 	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			 MDIO_CTL_REG_84823_MEDIA, val);
+			 MDIO_CTL_REG_84823_MEDIA + adj, val);
 	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
 		   params->multi_phy_config, val);
 
@@ -6172,23 +6297,43 @@ static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
 	else
 		bnx2x_save_848xx_spirom_version(phy, params);
+	cms_enable = REG_RD(bp, params->shmem_base +
+			offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].default_cfg)) &
+			PORT_HW_CFG_ENABLE_CMS_MASK;
+
+	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+		MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
+	if (cms_enable)
+		val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
+	else
+		val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+		MDIO_CTL_REG_84823_USER_CTRL_REG, val);
+
+
 	return rc;
 }
 
 static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
-				       struct link_params *params,
-				       struct link_vars *vars)
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 val, val1, val2;
+	u16 val, val1, val2, adj;
 	u8 link_up = 0;
 
+	/* Reg offset adjustment for 84833 */
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = -1;
+
 	/* Check 10G-BaseT link status */
 	/* Check PMD signal ok */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_AN_DEVAD, 0xFFFA, &val1);
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL + adj,
 			&val2);
 	DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
 
@@ -6273,9 +6418,9 @@ static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy,
 				struct link_params *params)
 {
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
 }
 
 static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
@@ -6297,8 +6442,8 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy,
 	else
 		port = params->port;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       port);
 }
 
 static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
@@ -6353,24 +6498,24 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 
 			/* Set LED masks */
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED2_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED5_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x20);
 
 		} else {
 			bnx2x_cl45_write(bp, phy,
@@ -6394,35 +6539,35 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 			val |= 0x2492;
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
-					val);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LINK_SIGNAL,
+					 val);
 
 			/* Set LED masks */
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED2_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x20);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x20);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED5_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x0);
 		} else {
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x20);
 		}
 		break;
 
@@ -6440,9 +6585,9 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 					&val);
 
 			if (!((val &
-			      MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
-			   >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)){
-				DP(NETIF_MSG_LINK, "Seting LINK_SIGNAL\n");
+			       MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
+			  >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) {
+				DP(NETIF_MSG_LINK, "Setting LINK_SIGNAL\n");
 				bnx2x_cl45_write(bp, phy,
 						 MDIO_PMA_DEVAD,
 						 MDIO_PMA_REG_8481_LINK_SIGNAL,
@@ -6451,24 +6596,24 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
 
 			/* Set LED masks */
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x10);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x10);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED2_MASK,
-					0x80);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x80);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x98);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x98);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED5_MASK,
-					0x40);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x40);
 
 		} else {
 			bnx2x_cl45_write(bp, phy,
@@ -6513,10 +6658,10 @@ static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy,
 
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
@@ -6563,9 +6708,7 @@ static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy,
 	DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n",
 		   val2, val1);
 	link_up = ((val1 & 4) == 4);
-	/* if link is up
-	 * print the AN outcome of the SFX7101 PHY
-	 */
+	/* if link is up print the AN outcome of the SFX7101 PHY */
 	if (link_up) {
 		bnx2x_cl45_read(bp, phy,
 				MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
@@ -6599,20 +6742,20 @@ void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy)
 	u16 val, cnt;
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_7101_RESET, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_7101_RESET, &val);
 
 	for (cnt = 0; cnt < 10; cnt++) {
 		msleep(50);
 		/* Writes a self-clearing reset */
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_7101_RESET,
-			       (val | (1<<15)));
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_7101_RESET,
+				 (val | (1<<15)));
 		/* Wait for clear */
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_7101_RESET, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_7101_RESET, &val);
 
 		if ((val & (1<<15)) == 0)
 			break;
@@ -6623,10 +6766,10 @@ static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy,
 				struct link_params *params) {
 	/* Low power mode is controlled by GPIO 2 */
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
 	/* The PHY reset is controlled by GPIO 1 */
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
 }
 
 static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
@@ -6668,9 +6811,9 @@ static struct bnx2x_phy phy_null = {
 	.supported	= 0,
 	.media_type	= ETH_PHY_NOT_PRESENT,
 	.ver_addr	= 0,
-	.req_flow_ctrl  = 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)NULL,
@@ -6705,8 +6848,8 @@ static struct bnx2x_phy phy_serdes = {
 	.media_type	= ETH_PHY_UNSPECIFIED,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_init_serdes,
@@ -6742,8 +6885,8 @@ static struct bnx2x_phy phy_xgxs = {
 	.media_type	= ETH_PHY_UNSPECIFIED,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_init_xgxs,
@@ -6773,8 +6916,8 @@ static struct bnx2x_phy phy_7101 = {
 	.media_type	= ETH_PHY_BASE_T,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_7101_config_init,
@@ -6804,9 +6947,9 @@ static struct bnx2x_phy phy_8073 = {
 			   SUPPORTED_Asym_Pause),
 	.media_type	= ETH_PHY_UNSPECIFIED,
 	.ver_addr	= 0,
-	.req_flow_ctrl  = 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_8073_config_init,
@@ -7015,6 +7158,43 @@ static struct bnx2x_phy phy_84823 = {
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
+static struct bnx2x_phy phy_84833 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
+	.addr		= 0xff,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
+			    FLAGS_REARM_LATCH_SIGNAL,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10baseT_Half |
+			   SUPPORTED_10baseT_Full |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_10000baseT_Full |
+			   SUPPORTED_TP |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_BASE_T,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
+	.req_duplex	= 0,
+	.rsrv		= 0,
+	.config_init	= (config_init_t)bnx2x_848x3_config_init,
+	.read_status	= (read_status_t)bnx2x_848xx_read_status,
+	.link_reset	= (link_reset_t)bnx2x_848x3_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
 /*****************************************************************/
 /*                                                               */
 /* Populate the phy according. Main function: bnx2x_populate_phy   */
@@ -7028,7 +7208,7 @@ static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
 	/* Get the 4 lanes xgxs config rx and tx */
 	u32 rx = 0, tx = 0, i;
 	for (i = 0; i < 2; i++) {
-		/**
+		/*
 		 * INT_PHY and EXT_PHY1 share the same value location in the
 		 * shmem. When num_phys is greater than 1, than this value
 		 * applies only to EXT_PHY1
@@ -7036,19 +7216,19 @@ static void bnx2x_populate_preemphasis(struct bnx2x *bp, u32 shmem_base,
 		if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
 			rx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			   dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
+			  dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
 
 			tx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			   dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
+			  dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
 		} else {
 			rx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			  dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
+			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
 
 			tx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			  dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
+			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
 		}
 
 		phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
@@ -7168,6 +7348,9 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
 		*phy = phy_84823;
 		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+		*phy = phy_84833;
+		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
 		*phy = phy_7101;
 		break;
@@ -7182,21 +7365,21 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
 	phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
 	bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
 
-	/**
-	* The shmem address of the phy version is located on different
-	* structures. In case this structure is too old, do not set
-	* the address
-	*/
+	/*
+	 * The shmem address of the phy version is located on different
+	 * structures. In case this structure is too old, do not set
+	 * the address
+	 */
 	config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
 					dev_info.shared_hw_config.config2));
 	if (phy_index == EXT_PHY1) {
 		phy->ver_addr = shmem_base + offsetof(struct shmem_region,
 				port_mb[port].ext_phy_fw_version);
 
-	/* Check specific mdc mdio settings */
-	if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
-		mdc_mdio_access = config2 &
-		SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
+		/* Check specific mdc mdio settings */
+		if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
+			mdc_mdio_access = config2 &
+			SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
 	} else {
 		u32 size = REG_RD(bp, shmem2_base);
 
@@ -7215,7 +7398,7 @@ static u8 bnx2x_populate_ext_phy(struct bnx2x *bp,
 	}
 	phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
 
-	/**
+	/*
 	 * In case mdc/mdio_access of the external phy is different than the
 	 * mdc/mdio access of the XGXS, a HW lock must be taken in each access
 	 * to prevent one port interfere with another port's CL45 operations.
@@ -7250,18 +7433,20 @@ static void bnx2x_phy_def_cfg(struct link_params *params,
 	/* Populate the default phy configuration for MF mode */
 	if (phy_index == EXT_PHY2) {
 		link_config = REG_RD(bp, params->shmem_base +
-					 offsetof(struct shmem_region, dev_info.
+				     offsetof(struct shmem_region, dev_info.
 			port_feature_config[params->port].link_config2));
 		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
-					offsetof(struct shmem_region, dev_info.
+					     offsetof(struct shmem_region,
+						      dev_info.
 			port_hw_config[params->port].speed_capability_mask2));
 	} else {
 		link_config = REG_RD(bp, params->shmem_base +
-				offsetof(struct shmem_region, dev_info.
+				     offsetof(struct shmem_region, dev_info.
 				port_feature_config[params->port].link_config));
 		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
-				offsetof(struct shmem_region, dev_info.
-			   port_hw_config[params->port].speed_capability_mask));
+					     offsetof(struct shmem_region,
+						      dev_info.
+			port_hw_config[params->port].speed_capability_mask));
 	}
 	DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
 		       " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
@@ -7408,7 +7593,7 @@ static void set_phy_vars(struct link_params *params)
 			else if (phy_index == EXT_PHY2)
 				actual_phy_idx = EXT_PHY1;
 		}
-		params->phy[actual_phy_idx].req_flow_ctrl  =
+		params->phy[actual_phy_idx].req_flow_ctrl =
 			params->req_flow_ctrl[link_cfg_idx];
 
 		params->phy[actual_phy_idx].req_line_speed =
@@ -7461,57 +7646,6 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 	set_phy_vars(params);
 
 	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
-	if (CHIP_REV_IS_FPGA(bp)) {
-
-		vars->link_up = 1;
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
-		/* enable on E1.5 FPGA */
-		if (CHIP_IS_E1H(bp)) {
-			vars->flow_ctrl |=
-					(BNX2X_FLOW_CTRL_TX |
-					 BNX2X_FLOW_CTRL_RX);
-			vars->link_status |=
-					(LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
-					 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
-		}
-
-		bnx2x_emac_enable(params, vars, 0);
-		if (!(CHIP_IS_E2(bp)))
-			bnx2x_pbf_update(params, vars->flow_ctrl,
-					 vars->line_speed);
-		/* disable drain */
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-
-		/* update shared memory */
-		bnx2x_update_mng(params, vars->link_status);
-
-		return 0;
-
-	} else
-	if (CHIP_REV_IS_EMUL(bp)) {
-
-		vars->link_up = 1;
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
-
-		bnx2x_bmac_enable(params, vars, 0);
-
-		bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
-		/* Disable drain */
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
-				    + params->port*4, 0);
-
-		/* update shared memory */
-		bnx2x_update_mng(params, vars->link_status);
-
-		return 0;
-
-	} else
 	if (params->loopback_mode == LOOPBACK_BMAC) {
 
 		vars->link_up = 1;
@@ -7527,8 +7661,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 		/* set bmac loopback */
 		bnx2x_bmac_enable(params, vars, 1);
 
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
-		    params->port*4, 0);
+		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 	} else if (params->loopback_mode == LOOPBACK_EMAC) {
 
@@ -7544,8 +7677,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 		/* 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);
+		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 	} else if ((params->loopback_mode == LOOPBACK_XGXS) ||
 		   (params->loopback_mode == LOOPBACK_EXT_PHY)) {
@@ -7568,8 +7700,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 			bnx2x_emac_program(params, vars);
 			bnx2x_emac_enable(params, vars, 0);
 		} else
-		bnx2x_bmac_enable(params, vars, 0);
-
+			bnx2x_bmac_enable(params, vars, 0);
 		if (params->loopback_mode == LOOPBACK_XGXS) {
 			/* set 10G XGXS loopback */
 			params->phy[INT_PHY].config_loopback(
@@ -7587,9 +7718,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 						params);
 			}
 		}
-
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
-			    params->port*4, 0);
+		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 		bnx2x_set_led(params, vars,
 			      LED_MODE_OPER, vars->line_speed);
@@ -7608,7 +7737,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
 	return 0;
 }
 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
-		  u8 reset_ext_phy)
+		    u8 reset_ext_phy)
 {
 	struct bnx2x *bp = params->bp;
 	u8 phy_index, port = params->port, clear_latch_ind = 0;
@@ -7617,10 +7746,10 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
 	vars->link_status = 0;
 	bnx2x_update_mng(params, vars->link_status);
 	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-		     (NIG_MASK_XGXS0_LINK_STATUS |
-		      NIG_MASK_XGXS0_LINK10G |
-		      NIG_MASK_SERDES0_LINK_STATUS |
-		      NIG_MASK_MI_INT));
+		       (NIG_MASK_XGXS0_LINK_STATUS |
+			NIG_MASK_XGXS0_LINK10G |
+			NIG_MASK_SERDES0_LINK_STATUS |
+			NIG_MASK_MI_INT));
 
 	/* activate nig drain */
 	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
@@ -7719,21 +7848,22 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
 		/* disable attentions */
 		bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
 			       port_of_path*4,
-			     (NIG_MASK_XGXS0_LINK_STATUS |
-			      NIG_MASK_XGXS0_LINK10G |
-			      NIG_MASK_SERDES0_LINK_STATUS |
-			      NIG_MASK_MI_INT));
+			       (NIG_MASK_XGXS0_LINK_STATUS |
+				NIG_MASK_XGXS0_LINK10G |
+				NIG_MASK_SERDES0_LINK_STATUS |
+				NIG_MASK_MI_INT));
 
 		/* Need to take the phy out of low power mode in order
 			to write to access its registers */
 		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				  MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+			       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+			       port);
 
 		/* Reset the phy */
 		bnx2x_cl45_write(bp, &phy[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_CTRL,
-			       1<<15);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_CTRL,
+				 1<<15);
 	}
 
 	/* Add delay of 150ms after reset */
@@ -7762,18 +7892,20 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
 
 		/* Only set bit 10 = 1 (Tx power down) */
 		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_TX_POWER_DOWN, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
 		/* Phase1 of TX_POWER_DOWN reset */
 		bnx2x_cl45_write(bp, phy_blk[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_TX_POWER_DOWN,
-			       (val | 1<<10));
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_TX_POWER_DOWN,
+				 (val | 1<<10));
 	}
 
-	/* Toggle Transmitter: Power down and then up with 600ms
-	   delay between */
+	/*
+	 * Toggle Transmitter: Power down and then up with 600ms delay
+	 * between
+	 */
 	msleep(600);
 
 	/* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
@@ -7781,25 +7913,25 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp,
 		/* Phase2 of POWER_DOWN_RESET */
 		/* Release bit 10 (Release Tx power down) */
 		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_TX_POWER_DOWN, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
 		bnx2x_cl45_write(bp, phy_blk[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
 		msleep(15);
 
 		/* Read modify write the SPI-ROM version select register */
 		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_EDC_FFE_MAIN, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_EDC_FFE_MAIN, &val);
 		bnx2x_cl45_write(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
 
 		/* set GPIO2 back to LOW */
 		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				  MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+			       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 	}
 	return 0;
 }
@@ -7846,32 +7978,90 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp,
 
 		/* Set fault module detected LED on */
 		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				  MISC_REGISTERS_GPIO_HIGH,
-				  port);
+			       MISC_REGISTERS_GPIO_HIGH,
+			       port);
 	}
 
 	return 0;
 }
+static void bnx2x_get_ext_phy_reset_gpio(struct bnx2x *bp, u32 shmem_base,
+					 u8 *io_gpio, u8 *io_port)
+{
+
+	u32 phy_gpio_reset = REG_RD(bp, shmem_base +
+					  offsetof(struct shmem_region,
+				dev_info.port_hw_config[PORT_0].default_cfg));
+	switch (phy_gpio_reset) {
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0:
+		*io_gpio = 0;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0:
+		*io_gpio = 1;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0:
+		*io_gpio = 2;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0:
+		*io_gpio = 3;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1:
+		*io_gpio = 0;
+		*io_port = 1;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1:
+		*io_gpio = 1;
+		*io_port = 1;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1:
+		*io_gpio = 2;
+		*io_port = 1;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1:
+		*io_gpio = 3;
+		*io_port = 1;
+		break;
+	default:
+		/* Don't override the io_gpio and io_port */
+		break;
+	}
+}
 static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
 				     u32 shmem_base_path[],
 				     u32 shmem2_base_path[], u8 phy_index,
 				     u32 chip_id)
 {
-	s8 port;
+	s8 port, reset_gpio;
 	u32 swap_val, swap_override;
 	struct bnx2x_phy phy[PORT_MAX];
 	struct bnx2x_phy *phy_blk[PORT_MAX];
 	s8 port_of_path;
-	swap_val = REG_RD(bp,  NIG_REG_PORT_SWAP);
-	swap_override = REG_RD(bp,  NIG_REG_STRAP_OVERRIDE);
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
 
+	reset_gpio = MISC_REGISTERS_GPIO_1;
 	port = 1;
 
-	bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override));
+	/*
+	 * Retrieve the reset gpio/port which control the reset.
+	 * Default is GPIO1, PORT1
+	 */
+	bnx2x_get_ext_phy_reset_gpio(bp, shmem_base_path[0],
+				     (u8 *)&reset_gpio, (u8 *)&port);
 
 	/* Calculate the port based on port swap */
 	port ^= (swap_val && swap_override);
 
+	/* Initiate PHY reset*/
+	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       port);
+	msleep(1);
+	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+		       port);
+
 	msleep(5);
 
 	/* PART1 - Reset both phys */
@@ -7907,9 +8097,7 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
 
 		/* Reset the phy */
 		bnx2x_cl45_write(bp, &phy[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_CTRL,
-			       1<<15);
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
 	}
 
 	/* Add delay of 150ms after reset */
@@ -7923,7 +8111,7 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
 	}
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		 if (CHIP_IS_E2(bp))
+		if (CHIP_IS_E2(bp))
 			port_of_path = 0;
 		else
 			port_of_path = port;
@@ -7958,8 +8146,10 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 		break;
 
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		/* GPIO1 affects both ports, so there's need to pull
-		it for single port alone */
+		/*
+		 * GPIO1 affects both ports, so there's need to pull
+		 * it for single port alone
+		 */
 		rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
 						shmem2_base_path,
 						phy_index, chip_id);
@@ -7969,11 +8159,15 @@ static u8 bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
 		break;
 	default:
 		DP(NETIF_MSG_LINK,
-			 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
-			 ext_phy_type);
+			   "ext_phy 0x%x common init not required\n",
+			   ext_phy_type);
 		break;
 	}
 
+	if (rc != 0)
+		netdev_err(bp->dev,  "Warning: PHY was not initialized,"
+				      " Port %d\n",
+			 0);
 	return rc;
 }
 
@@ -7986,9 +8180,6 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
 	u32 ext_phy_type, ext_phy_config;
 	DP(NETIF_MSG_LINK, "Begin common phy init\n");
 
-	if (CHIP_REV_IS_EMUL(bp))
-		return 0;
-
 	/* Check if common init was already done */
 	phy_ver = REG_RD(bp, shmem_base_path[0] +
 			 offsetof(struct shmem_region,
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h
index bedab1a..92f36b6 100644
--- a/drivers/net/bnx2x/bnx2x_link.h
+++ b/drivers/net/bnx2x/bnx2x_link.h
@@ -1,4 +1,4 @@
-/* Copyright 2008-2010 Broadcom Corporation
+/* Copyright 2008-2011 Broadcom Corporation
  *
  * Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -33,7 +33,7 @@
 #define BNX2X_FLOW_CTRL_BOTH		PORT_FEATURE_FLOW_CONTROL_BOTH
 #define BNX2X_FLOW_CTRL_NONE		PORT_FEATURE_FLOW_CONTROL_NONE
 
-#define SPEED_AUTO_NEG	    0
+#define SPEED_AUTO_NEG		0
 #define SPEED_12000		12000
 #define SPEED_12500		12500
 #define SPEED_13000		13000
@@ -44,8 +44,8 @@
 #define SFP_EEPROM_VENDOR_NAME_SIZE		16
 #define SFP_EEPROM_VENDOR_OUI_ADDR		0x25
 #define SFP_EEPROM_VENDOR_OUI_SIZE		3
-#define SFP_EEPROM_PART_NO_ADDR 		0x28
-#define SFP_EEPROM_PART_NO_SIZE		16
+#define SFP_EEPROM_PART_NO_ADDR			0x28
+#define SFP_EEPROM_PART_NO_SIZE			16
 #define PWR_FLT_ERR_MSG_LEN			250
 
 #define XGXS_EXT_PHY_TYPE(ext_phy_config) \
@@ -62,7 +62,7 @@
 #define SINGLE_MEDIA(params)		(params->num_phys == 2)
 /* Dual Media board contains two external phy with different media */
 #define DUAL_MEDIA(params)		(params->num_phys == 3)
-#define FW_PARAM_MDIO_CTRL_OFFSET 16
+#define FW_PARAM_MDIO_CTRL_OFFSET		16
 #define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
 	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
 
@@ -201,12 +201,14 @@ struct link_params {
 
 	/* Default / User Configuration */
 	u8 loopback_mode;
-#define LOOPBACK_NONE	0
-#define LOOPBACK_EMAC	1
-#define LOOPBACK_BMAC	2
+#define LOOPBACK_NONE		0
+#define LOOPBACK_EMAC		1
+#define LOOPBACK_BMAC		2
 #define LOOPBACK_XGXS		3
 #define LOOPBACK_EXT_PHY	4
-#define LOOPBACK_EXT 	5
+#define LOOPBACK_EXT		5
+#define LOOPBACK_UMAC		6
+#define LOOPBACK_XMAC		7
 
 	/* Device parameters */
 	u8 mac_addr[6];
@@ -230,10 +232,11 @@ struct link_params {
 	/* Phy register parameter */
 	u32 chip_id;
 
+	/* features */
 	u32 feature_config_flags;
-#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
-#define FEATURE_CONFIG_PFC_ENABLED		(1<<1)
-#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY	(1<<2)
+#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED	(1<<0)
+#define FEATURE_CONFIG_PFC_ENABLED			(1<<1)
+#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY		(1<<2)
 #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
 	/* Will be populated during common init */
 	struct bnx2x_phy phy[MAX_PHYS];
@@ -334,6 +337,11 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
 /* Reset the external of SFX7101 */
 void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
 
+/* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
+u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+				struct link_params *params, u16 addr,
+				u8 byte_cnt, u8 *o_buf);
+
 void bnx2x_hw_reset_phy(struct link_params *params);
 
 /* Checks if HW lock is required for this phy/board type */
@@ -379,7 +387,7 @@ void bnx2x_ets_disabled(struct link_params *params);
 
 /* Used to configure the ETS to BW limited */
 void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
-						const u32 cos1_bw);
+			const u32 cos1_bw);
 
 /* Used to configure the ETS to strict */
 u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index aa03233..32e64cc8 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c
@@ -145,13 +145,6 @@ static struct {
 	{ "Broadcom NetXtreme II BCM57712E XGb" }
 };
 
-#ifndef PCI_DEVICE_ID_NX2_57712
-#define PCI_DEVICE_ID_NX2_57712		0x1662
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57712E
-#define PCI_DEVICE_ID_NX2_57712E	0x1663
-#endif
-
 static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
@@ -586,7 +579,7 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
 	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
 	/* lock the dmae channel */
-	mutex_lock(&bp->dmae_mutex);
+	spin_lock_bh(&bp->dmae_lock);
 
 	/* reset completion */
 	*wb_comp = 0;
@@ -617,7 +610,7 @@ static int bnx2x_issue_dmae_with_comp(struct bnx2x *bp,
 	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
 unlock:
-	mutex_unlock(&bp->dmae_mutex);
+	spin_unlock_bh(&bp->dmae_lock);
 	return rc;
 }
 
@@ -1397,7 +1390,7 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp,
 	}
 
 	smp_mb__before_atomic_inc();
-	atomic_inc(&bp->spq_left);
+	atomic_inc(&bp->cq_spq_left);
 	/* push the change in fp->state and towards the memory */
 	smp_wmb();
 
@@ -2484,8 +2477,14 @@ static void bnx2x_pf_rx_cl_prep(struct bnx2x *bp,
 	rxq_init->sge_map = fp->rx_sge_mapping;
 	rxq_init->rcq_map = fp->rx_comp_mapping;
 	rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
-	rxq_init->mtu = bp->dev->mtu;
-	rxq_init->buf_sz = bp->rx_buf_size;
+
+	/* Always use mini-jumbo MTU for FCoE L2 ring */
+	if (IS_FCOE_FP(fp))
+		rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+	else
+		rxq_init->mtu = bp->dev->mtu;
+
+	rxq_init->buf_sz = fp->rx_buf_size;
 	rxq_init->cl_qzone_id = fp->cl_qzone_id;
 	rxq_init->cl_id = fp->cl_id;
 	rxq_init->spcl_id = fp->cl_id;
@@ -2737,11 +2736,18 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 
 	spin_lock_bh(&bp->spq_lock);
 
-	if (!atomic_read(&bp->spq_left)) {
-		BNX2X_ERR("BUG! SPQ ring full!\n");
-		spin_unlock_bh(&bp->spq_lock);
-		bnx2x_panic();
-		return -EBUSY;
+	if (common) {
+		if (!atomic_read(&bp->eq_spq_left)) {
+			BNX2X_ERR("BUG! EQ ring full!\n");
+			spin_unlock_bh(&bp->spq_lock);
+			bnx2x_panic();
+			return -EBUSY;
+		}
+	} else if (!atomic_read(&bp->cq_spq_left)) {
+			BNX2X_ERR("BUG! SPQ ring full!\n");
+			spin_unlock_bh(&bp->spq_lock);
+			bnx2x_panic();
+			return -EBUSY;
 	}
 
 	spe = bnx2x_sp_get_next(bp);
@@ -2772,20 +2778,26 @@ int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 	spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
 
 	/* stats ramrod has it's own slot on the spq */
-	if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY)
+	if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
 		/* It's ok if the actual decrement is issued towards the memory
 		 * somewhere between the spin_lock and spin_unlock. Thus no
 		 * more explict memory barrier is needed.
 		 */
-		atomic_dec(&bp->spq_left);
+		if (common)
+			atomic_dec(&bp->eq_spq_left);
+		else
+			atomic_dec(&bp->cq_spq_left);
+	}
+
 
 	DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
 	   "SPQE[%x] (%x:%x)  command %d  hw_cid %x  data (%x:%x) "
-	   "type(0x%x) left %x\n",
+	   "type(0x%x) left (ETH, COMMON) (%x,%x)\n",
 	   bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
 	   (u32)(U64_LO(bp->spq_mapping) +
 	   (void *)bp->spq_prod_bd - (void *)bp->spq), command,
-	   HW_CID(bp, cid), data_hi, data_lo, type, atomic_read(&bp->spq_left));
+	   HW_CID(bp, cid), data_hi, data_lo, type,
+	   atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left));
 
 	bnx2x_sp_prod_update(bp);
 	spin_unlock_bh(&bp->spq_lock);
@@ -3697,8 +3709,8 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 	sw_cons = bp->eq_cons;
 	sw_prod = bp->eq_prod;
 
-	DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->spq_left %u\n",
-			hw_cons, sw_cons, atomic_read(&bp->spq_left));
+	DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->cq_spq_left %u\n",
+			hw_cons, sw_cons, atomic_read(&bp->eq_spq_left));
 
 	for (; sw_cons != hw_cons;
 	      sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) {
@@ -3763,13 +3775,15 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
 		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
 			DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
-			bp->set_mac_pending = 0;
+			if (elem->message.data.set_mac_event.echo)
+				bp->set_mac_pending = 0;
 			break;
 
 		case (EVENT_RING_OPCODE_SET_MAC |
 		      BNX2X_STATE_CLOSING_WAIT4_HALT):
 			DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
-			bp->set_mac_pending = 0;
+			if (elem->message.data.set_mac_event.echo)
+				bp->set_mac_pending = 0;
 			break;
 		default:
 			/* unknown event log error and continue */
@@ -3781,7 +3795,7 @@ next_spqe:
 	} /* for */
 
 	smp_mb__before_atomic_inc();
-	atomic_add(spqe_cnt, &bp->spq_left);
+	atomic_add(spqe_cnt, &bp->eq_spq_left);
 
 	bp->eq_cons = sw_cons;
 	bp->eq_prod = sw_prod;
@@ -4208,13 +4222,13 @@ void bnx2x_update_coalesce(struct bnx2x *bp)
 
 	for_each_eth_queue(bp, i)
 		bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
-					 bp->rx_ticks, bp->tx_ticks);
+					 bp->tx_ticks, bp->rx_ticks);
 }
 
 static void bnx2x_init_sp_ring(struct bnx2x *bp)
 {
 	spin_lock_init(&bp->spq_lock);
-	atomic_set(&bp->spq_left, MAX_SPQ_PENDING);
+	atomic_set(&bp->cq_spq_left, MAX_SPQ_PENDING);
 
 	bp->spq_prod_idx = 0;
 	bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
@@ -4239,9 +4253,12 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp)
 	bp->eq_cons = 0;
 	bp->eq_prod = NUM_EQ_DESC;
 	bp->eq_cons_sb = BNX2X_EQ_INDEX;
+	/* we want a warning message before it gets rought... */
+	atomic_set(&bp->eq_spq_left,
+		min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
 }
 
-static void bnx2x_init_ind_table(struct bnx2x *bp)
+void bnx2x_push_indir_table(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
 	int i;
@@ -4249,13 +4266,20 @@ static void bnx2x_init_ind_table(struct bnx2x *bp)
 	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 		return;
 
-	DP(NETIF_MSG_IFUP,
-	   "Initializing indirection table  multi_mode %d\n", bp->multi_mode);
 	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
 		REG_WR8(bp, BAR_TSTRORM_INTMEM +
 			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
-			bp->fp->cl_id + (i % (bp->num_queues -
-				NONE_ETH_CONTEXT_USE)));
+			bp->fp->cl_id + bp->rx_indir_table[i]);
+}
+
+static void bnx2x_init_ind_table(struct bnx2x *bp)
+{
+	int i;
+
+	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+		bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp);
+
+	bnx2x_push_indir_table(bp);
 }
 
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
@@ -5851,7 +5875,7 @@ int bnx2x_init_hw(struct bnx2x *bp, u32 load_code)
 	   BP_ABS_FUNC(bp), load_code);
 
 	bp->dmae_ready = 0;
-	mutex_init(&bp->dmae_mutex);
+	spin_lock_init(&bp->dmae_lock);
 	rc = bnx2x_gunzip_init(bp);
 	if (rc)
 		return rc;
@@ -6003,6 +6027,8 @@ void bnx2x_free_mem(struct bnx2x *bp)
 	BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
 		       BCM_PAGE_SIZE * NUM_EQ_PAGES);
 
+	BNX2X_FREE(bp->rx_indir_table);
+
 #undef BNX2X_PCI_FREE
 #undef BNX2X_KFREE
 }
@@ -6133,6 +6159,9 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
 	/* EQ */
 	BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
 			BCM_PAGE_SIZE * NUM_EQ_PAGES);
+
+	BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) *
+		    TSTORM_INDIRECTION_TABLE_SIZE);
 	return 0;
 
 alloc_mem_err:
@@ -6186,12 +6215,14 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
 	int ramrod_flags = WAIT_RAMROD_COMMON;
 
 	bp->set_mac_pending = 1;
-	smp_wmb();
 
 	config->hdr.length = 1;
 	config->hdr.offset = cam_offset;
 	config->hdr.client_id = 0xff;
-	config->hdr.reserved1 = 0;
+	/* Mark the single MAC configuration ramrod as opposed to a
+	 * UC/MC list configuration).
+	 */
+	config->hdr.echo = 1;
 
 	/* primary MAC */
 	config->config_table[0].msb_mac_addr =
@@ -6223,6 +6254,8 @@ static void bnx2x_set_mac_addr_gen(struct bnx2x *bp, int set, const u8 *mac,
 	   config->config_table[0].middle_mac_addr,
 	   config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
 
+	mb();
+
 	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 		      U64_HI(bnx2x_sp_mapping(bp, mac_config)),
 		      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
@@ -6287,20 +6320,15 @@ static u8 bnx2x_e1h_cam_offset(struct bnx2x *bp, u8 rel_offset)
 	if (CHIP_IS_E1H(bp))
 		return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
 	else if (CHIP_MODE_IS_4_PORT(bp))
-		return BP_FUNC(bp) * 32  + rel_offset;
+		return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
 	else
-		return BP_VN(bp) * 32  + rel_offset;
+		return E2_FUNC_MAX * rel_offset + BP_VN(bp);
 }
 
 /**
  *  LLH CAM line allocations: currently only iSCSI and ETH macs are
  *  relevant. In addition, current implementation is tuned for a
  *  single ETH MAC.
- *
- *  When multiple unicast ETH MACs PF configuration in switch
- *  independent mode is required (NetQ, multiple netdev MACs,
- *  etc.), consider better utilisation of 16 per function MAC
- *  entries in the LLH memory.
  */
 enum {
 	LLH_CAM_ISCSI_ETH_LINE = 0,
@@ -6375,14 +6403,37 @@ void bnx2x_set_eth_mac(struct bnx2x *bp, int set)
 		bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
 	}
 }
-static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
+
+static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
+{
+	return CHIP_REV_IS_SLOW(bp) ?
+		(BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
+		(BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
+}
+
+/* set mc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of a very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
 {
 	int i = 0, old;
 	struct net_device *dev = bp->dev;
+	u8 offset = bnx2x_e1_cam_mc_offset(bp);
 	struct netdev_hw_addr *ha;
 	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
 	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
 
+	if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
+		return -EINVAL;
+
 	netdev_for_each_mc_addr(ha, dev) {
 		/* copy mac */
 		config_cmd->config_table[i].msb_mac_addr =
@@ -6423,32 +6474,47 @@ static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
 		}
 	}
 
+	wmb();
+
 	config_cmd->hdr.length = i;
 	config_cmd->hdr.offset = offset;
 	config_cmd->hdr.client_id = 0xff;
-	config_cmd->hdr.reserved1 = 0;
+	/* Mark that this ramrod doesn't use bp->set_mac_pending for
+	 * synchronization.
+	 */
+	config_cmd->hdr.echo = 0;
 
-	bp->set_mac_pending = 1;
-	smp_wmb();
+	mb();
 
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 		   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
 }
-static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
+
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
 {
 	int i;
 	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
 	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
 	int ramrod_flags = WAIT_RAMROD_COMMON;
+	u8 offset = bnx2x_e1_cam_mc_offset(bp);
 
-	bp->set_mac_pending = 1;
-	smp_wmb();
-
-	for (i = 0; i < config_cmd->hdr.length; i++)
+	for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
 		SET_FLAG(config_cmd->config_table[i].flags,
 			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
 			T_ETH_MAC_COMMAND_INVALIDATE);
 
+	wmb();
+
+	config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	/* We'll wait for a completion this time... */
+	config_cmd->hdr.echo = 1;
+
+	bp->set_mac_pending = 1;
+
+	mb();
+
 	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 		      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
 
@@ -6458,6 +6524,44 @@ static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
 
 }
 
+/* Accept one or more multicasts */
+static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
+{
+	struct net_device *dev = bp->dev;
+	struct netdev_hw_addr *ha;
+	u32 mc_filter[MC_HASH_SIZE];
+	u32 crc, bit, regidx;
+	int i;
+
+	memset(mc_filter, 0, 4 * MC_HASH_SIZE);
+
+	netdev_for_each_mc_addr(ha, dev) {
+		DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
+		   bnx2x_mc_addr(ha));
+
+		crc = crc32c_le(0, bnx2x_mc_addr(ha),
+				ETH_ALEN);
+		bit = (crc >> 24) & 0xff;
+		regidx = bit >> 5;
+		bit &= 0x1f;
+		mc_filter[regidx] |= (1 << bit);
+	}
+
+	for (i = 0; i < MC_HASH_SIZE; i++)
+		REG_WR(bp, MC_HASH_OFFSET(bp, i),
+		       mc_filter[i]);
+
+	return 0;
+}
+
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
+{
+	int i;
+
+	for (i = 0; i < MC_HASH_SIZE; i++)
+		REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+}
+
 #ifdef BCM_CNIC
 /**
  * Set iSCSI MAC(s) at the next enties in the CAM after the ETH
@@ -6476,12 +6580,13 @@ static int bnx2x_set_iscsi_eth_mac_addr(struct bnx2x *bp, int set)
 	u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
 		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
 	u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
+	u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
 
 	/* Send a SET_MAC ramrod */
-	bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec,
+	bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec,
 			       cam_offset, 0);
 
-	bnx2x_set_mac_in_nig(bp, set, bp->iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
+	bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
 
 	return 0;
 }
@@ -7123,20 +7228,15 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode)
 	/* Give HW time to discard old tx messages */
 	msleep(1);
 
-	if (CHIP_IS_E1(bp)) {
-		/* invalidate mc list,
-		 * wait and poll (interrupts are off)
-		 */
-		bnx2x_invlidate_e1_mc_list(bp);
-		bnx2x_set_eth_mac(bp, 0);
-
-	} else {
-		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+	bnx2x_set_eth_mac(bp, 0);
 
-		bnx2x_set_eth_mac(bp, 0);
+	bnx2x_invalidate_uc_list(bp);
 
-		for (i = 0; i < MC_HASH_SIZE; i++)
-			REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+	if (CHIP_IS_E1(bp))
+		bnx2x_invalidate_e1_mc_list(bp);
+	else {
+		bnx2x_invalidate_e1h_mc_list(bp);
+		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
 	}
 
 #ifdef BCM_CNIC
@@ -8405,11 +8505,47 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 							bp->common.shmem2_base);
 }
 
+#ifdef BCM_CNIC
+static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
+{
+	u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
+				drv_lic_key[BP_PORT(bp)].max_iscsi_conn);
+	u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
+				drv_lic_key[BP_PORT(bp)].max_fcoe_conn);
+
+	/* Get the number of maximum allowed iSCSI and FCoE connections */
+	bp->cnic_eth_dev.max_iscsi_conn =
+		(max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >>
+		BNX2X_MAX_ISCSI_INIT_CONN_SHIFT;
+
+	bp->cnic_eth_dev.max_fcoe_conn =
+		(max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
+		BNX2X_MAX_FCOE_INIT_CONN_SHIFT;
+
+	BNX2X_DEV_INFO("max_iscsi_conn 0x%x max_fcoe_conn 0x%x\n",
+		       bp->cnic_eth_dev.max_iscsi_conn,
+		       bp->cnic_eth_dev.max_fcoe_conn);
+
+	/* If mamimum allowed number of connections is zero -
+	 * disable the feature.
+	 */
+	if (!bp->cnic_eth_dev.max_iscsi_conn)
+		bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+
+	if (!bp->cnic_eth_dev.max_fcoe_conn)
+		bp->flags |= NO_FCOE_FLAG;
+}
+#endif
+
 static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 {
 	u32 val, val2;
 	int func = BP_ABS_FUNC(bp);
 	int port = BP_PORT(bp);
+#ifdef BCM_CNIC
+	u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
+	u8 *fip_mac = bp->fip_mac;
+#endif
 
 	if (BP_NOMCP(bp)) {
 		BNX2X_ERROR("warning: random MAC workaround active\n");
@@ -8422,7 +8558,9 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 			bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
 
 #ifdef BCM_CNIC
-		/* iSCSI NPAR MAC */
+		/* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
+		 * FCoE MAC then the appropriate feature should be disabled.
+		 */
 		if (IS_MF_SI(bp)) {
 			u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
 			if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
@@ -8430,8 +8568,39 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 						     iscsi_mac_addr_upper);
 				val = MF_CFG_RD(bp, func_ext_config[func].
 						    iscsi_mac_addr_lower);
-				bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
-			}
+				BNX2X_DEV_INFO("Read iSCSI MAC: "
+					       "0x%x:0x%04x\n", val2, val);
+				bnx2x_set_mac_buf(iscsi_mac, val, val2);
+
+				/* Disable iSCSI OOO if MAC configuration is
+				 * invalid.
+				 */
+				if (!is_valid_ether_addr(iscsi_mac)) {
+					bp->flags |= NO_ISCSI_OOO_FLAG |
+						     NO_ISCSI_FLAG;
+					memset(iscsi_mac, 0, ETH_ALEN);
+				}
+			} else
+				bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+
+			if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
+				val2 = MF_CFG_RD(bp, func_ext_config[func].
+						     fcoe_mac_addr_upper);
+				val = MF_CFG_RD(bp, func_ext_config[func].
+						    fcoe_mac_addr_lower);
+				BNX2X_DEV_INFO("Read FCoE MAC to "
+					       "0x%x:0x%04x\n", val2, val);
+				bnx2x_set_mac_buf(fip_mac, val, val2);
+
+				/* Disable FCoE if MAC configuration is
+				 * invalid.
+				 */
+				if (!is_valid_ether_addr(fip_mac)) {
+					bp->flags |= NO_FCOE_FLAG;
+					memset(bp->fip_mac, 0, ETH_ALEN);
+				}
+			} else
+				bp->flags |= NO_FCOE_FLAG;
 		}
 #endif
 	} else {
@@ -8445,7 +8614,7 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 				    iscsi_mac_upper);
 		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
 				   iscsi_mac_lower);
-		bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
+		bnx2x_set_mac_buf(iscsi_mac, val, val2);
 #endif
 	}
 
@@ -8453,14 +8622,12 @@ static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
 #ifdef BCM_CNIC
-	/* Inform the upper layers about FCoE MAC */
+	/* Set the FCoE MAC in modes other then MF_SI */
 	if (!CHIP_IS_E1x(bp)) {
 		if (IS_MF_SD(bp))
-			memcpy(bp->fip_mac, bp->dev->dev_addr,
-			       sizeof(bp->fip_mac));
-		else
-			memcpy(bp->fip_mac, bp->iscsi_mac,
-			       sizeof(bp->fip_mac));
+			memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
+		else if (!IS_MF(bp))
+			memcpy(fip_mac, iscsi_mac, ETH_ALEN);
 	}
 #endif
 }
@@ -8623,6 +8790,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
 	/* Get MAC addresses */
 	bnx2x_get_mac_hwinfo(bp);
 
+#ifdef BCM_CNIC
+	bnx2x_get_cnic_info(bp);
+#endif
+
 	return rc;
 }
 
@@ -8837,12 +9008,197 @@ static int bnx2x_close(struct net_device *dev)
 	return 0;
 }
 
+#define E1_MAX_UC_LIST	29
+#define E1H_MAX_UC_LIST	30
+#define E2_MAX_UC_LIST	14
+static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+{
+	if (CHIP_IS_E1(bp))
+		return E1_MAX_UC_LIST;
+	else if (CHIP_IS_E1H(bp))
+		return E1H_MAX_UC_LIST;
+	else
+		return E2_MAX_UC_LIST;
+}
+
+
+static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
+{
+	if (CHIP_IS_E1(bp))
+		/* CAM Entries for Port0:
+		 *      0 - prim ETH MAC
+		 *      1 - BCAST MAC
+		 *      2 - iSCSI L2 ring ETH MAC
+		 *      3-31 - UC MACs
+		 *
+		 * Port1 entries are allocated the same way starting from
+		 * entry 32.
+		 */
+		return 3 + 32 * BP_PORT(bp);
+	else if (CHIP_IS_E1H(bp)) {
+		/* CAM Entries:
+		 *      0-7  - prim ETH MAC for each function
+		 *      8-15 - iSCSI L2 ring ETH MAC for each function
+		 *      16 till 255 UC MAC lists for each function
+		 *
+		 * Remark: There is no FCoE support for E1H, thus FCoE related
+		 *         MACs are not considered.
+		 */
+		return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
+			bnx2x_max_uc_list(bp) * BP_FUNC(bp);
+	} else {
+		/* CAM Entries (there is a separate CAM per engine):
+		 *      0-4  - prim ETH MAC for each function
+		 *      4-7 - iSCSI L2 ring ETH MAC for each function
+		 *      8-11 - FIP ucast L2 MAC for each function
+		 *      12-15 - ALL_ENODE_MACS mcast MAC for each function
+		 *      16 till 71 UC MAC lists for each function
+		 */
+		u8 func_idx =
+			(CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
+
+		return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
+			bnx2x_max_uc_list(bp) * func_idx;
+	}
+}
+
+/* set uc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_uc_list(struct bnx2x *bp)
+{
+	int i = 0, old;
+	struct net_device *dev = bp->dev;
+	u8 offset = bnx2x_uc_list_cam_offset(bp);
+	struct netdev_hw_addr *ha;
+	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+
+	if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
+		return -EINVAL;
+
+	netdev_for_each_uc_addr(ha, dev) {
+		/* copy mac */
+		config_cmd->config_table[i].msb_mac_addr =
+			swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
+		config_cmd->config_table[i].middle_mac_addr =
+			swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
+		config_cmd->config_table[i].lsb_mac_addr =
+			swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
+
+		config_cmd->config_table[i].vlan_id = 0;
+		config_cmd->config_table[i].pf_id = BP_FUNC(bp);
+		config_cmd->config_table[i].clients_bit_vector =
+			cpu_to_le32(1 << BP_L_ID(bp));
+
+		SET_FLAG(config_cmd->config_table[i].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_SET);
+
+		DP(NETIF_MSG_IFUP,
+		   "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
+		   config_cmd->config_table[i].msb_mac_addr,
+		   config_cmd->config_table[i].middle_mac_addr,
+		   config_cmd->config_table[i].lsb_mac_addr);
+
+		i++;
+
+		/* Set uc MAC in NIG */
+		bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
+				     LLH_CAM_ETH_LINE + i);
+	}
+	old = config_cmd->hdr.length;
+	if (old > i) {
+		for (; i < old; i++) {
+			if (CAM_IS_INVALID(config_cmd->
+					   config_table[i])) {
+				/* already invalidated */
+				break;
+			}
+			/* invalidate */
+			SET_FLAG(config_cmd->config_table[i].flags,
+				MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+				T_ETH_MAC_COMMAND_INVALIDATE);
+		}
+	}
+
+	wmb();
+
+	config_cmd->hdr.length = i;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	/* Mark that this ramrod doesn't use bp->set_mac_pending for
+	 * synchronization.
+	 */
+	config_cmd->hdr.echo = 0;
+
+	mb();
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+		   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+}
+
+void bnx2x_invalidate_uc_list(struct bnx2x *bp)
+{
+	int i;
+	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+	int ramrod_flags = WAIT_RAMROD_COMMON;
+	u8 offset = bnx2x_uc_list_cam_offset(bp);
+	u8 max_list_size = bnx2x_max_uc_list(bp);
+
+	for (i = 0; i < max_list_size; i++) {
+		SET_FLAG(config_cmd->config_table[i].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_INVALIDATE);
+		bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
+	}
+
+	wmb();
+
+	config_cmd->hdr.length = max_list_size;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	/* We'll wait for a completion this time... */
+	config_cmd->hdr.echo = 1;
+
+	bp->set_mac_pending = 1;
+
+	mb();
+
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+		      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+	/* Wait for a completion */
+	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
+				ramrod_flags);
+
+}
+
+static inline int bnx2x_set_mc_list(struct bnx2x *bp)
+{
+	/* some multicasts */
+	if (CHIP_IS_E1(bp)) {
+		return bnx2x_set_e1_mc_list(bp);
+	} else { /* E1H and newer */
+		return bnx2x_set_e1h_mc_list(bp);
+	}
+}
+
 /* called with netif_tx_lock from dev_mcast.c */
 void bnx2x_set_rx_mode(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	u32 rx_mode = BNX2X_RX_MODE_NORMAL;
-	int port = BP_PORT(bp);
 
 	if (bp->state != BNX2X_STATE_OPEN) {
 		DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
@@ -8853,47 +9209,16 @@ void bnx2x_set_rx_mode(struct net_device *dev)
 
 	if (dev->flags & IFF_PROMISC)
 		rx_mode = BNX2X_RX_MODE_PROMISC;
-	else if ((dev->flags & IFF_ALLMULTI) ||
-		 ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
-		  CHIP_IS_E1(bp)))
+	else if (dev->flags & IFF_ALLMULTI)
 		rx_mode = BNX2X_RX_MODE_ALLMULTI;
-	else { /* some multicasts */
-		if (CHIP_IS_E1(bp)) {
-			/*
-			 * set mc list, do not wait as wait implies sleep
-			 * and set_rx_mode can be invoked from non-sleepable
-			 * context
-			 */
-			u8 offset = (CHIP_REV_IS_SLOW(bp) ?
-				     BNX2X_MAX_EMUL_MULTI*(1 + port) :
-				     BNX2X_MAX_MULTICAST*(1 + port));
-
-			bnx2x_set_e1_mc_list(bp, offset);
-		} else { /* E1H */
-			/* Accept one or more multicasts */
-			struct netdev_hw_addr *ha;
-			u32 mc_filter[MC_HASH_SIZE];
-			u32 crc, bit, regidx;
-			int i;
-
-			memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
-			netdev_for_each_mc_addr(ha, dev) {
-				DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
-				   bnx2x_mc_addr(ha));
-
-				crc = crc32c_le(0, bnx2x_mc_addr(ha),
-						ETH_ALEN);
-				bit = (crc >> 24) & 0xff;
-				regidx = bit >> 5;
-				bit &= 0x1f;
-				mc_filter[regidx] |= (1 << bit);
-			}
+	else {
+		/* some multicasts */
+		if (bnx2x_set_mc_list(bp))
+			rx_mode = BNX2X_RX_MODE_ALLMULTI;
 
-			for (i = 0; i < MC_HASH_SIZE; i++)
-				REG_WR(bp, MC_HASH_OFFSET(bp, i),
-				       mc_filter[i]);
-		}
+		/* some unicasts */
+		if (bnx2x_set_uc_list(bp))
+			rx_mode = BNX2X_RX_MODE_PROMISC;
 	}
 
 	bp->rx_mode = rx_mode;
@@ -8974,7 +9299,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 	.ndo_stop		= bnx2x_close,
 	.ndo_start_xmit		= bnx2x_start_xmit,
 	.ndo_select_queue	= bnx2x_select_queue,
-	.ndo_set_multicast_list	= bnx2x_set_rx_mode,
+	.ndo_set_rx_mode	= bnx2x_set_rx_mode,
 	.ndo_set_mac_address	= bnx2x_change_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= bnx2x_ioctl,
@@ -9120,7 +9445,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
 	dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
 	dev->vlan_features |= NETIF_F_TSO6;
 
-#ifdef BCM_DCB
+#ifdef BCM_DCBNL
 	dev->dcbnl_ops = &bnx2x_dcbnl_ops;
 #endif
 
@@ -9527,6 +9852,11 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
 	}
 #endif
 
+#ifdef BCM_DCBNL
+	/* Delete app tlvs from dcbnl */
+	bnx2x_dcbnl_update_applist(bp, true);
+#endif
+
 	unregister_netdev(dev);
 
 	/* Delete all NAPI objects */
@@ -9800,15 +10130,21 @@ static void bnx2x_cnic_sp_post(struct bnx2x *bp, int count)
 					HW_CID(bp, BNX2X_ISCSI_ETH_CID));
 		}
 
-		/* There may be not more than 8 L2 and COMMON SPEs and not more
-		 * than 8 L5 SPEs in the air.
+		/* There may be not more than 8 L2 and not more than 8 L5 SPEs
+		 * We also check that the number of outstanding
+		 * COMMON ramrods is not more than the EQ and SPQ can
+		 * accommodate.
 		 */
-		if ((type == NONE_CONNECTION_TYPE) ||
-		    (type == ETH_CONNECTION_TYPE)) {
-			if (!atomic_read(&bp->spq_left))
+		if (type == ETH_CONNECTION_TYPE) {
+			if (!atomic_read(&bp->cq_spq_left))
 				break;
 			else
-				atomic_dec(&bp->spq_left);
+				atomic_dec(&bp->cq_spq_left);
+		} else if (type == NONE_CONNECTION_TYPE) {
+			if (!atomic_read(&bp->eq_spq_left))
+				break;
+			else
+				atomic_dec(&bp->eq_spq_left);
 		} else if ((type == ISCSI_CONNECTION_TYPE) ||
 			   (type == FCOE_CONNECTION_TYPE)) {
 			if (bp->cnic_spq_pending >=
@@ -9886,7 +10222,8 @@ static int bnx2x_cnic_ctl_send(struct bnx2x *bp, struct cnic_ctl_info *ctl)
 	int rc = 0;
 
 	mutex_lock(&bp->cnic_mutex);
-	c_ops = bp->cnic_ops;
+	c_ops = rcu_dereference_protected(bp->cnic_ops,
+					  lockdep_is_held(&bp->cnic_mutex));
 	if (c_ops)
 		rc = c_ops->cnic_ctl(bp->cnic_data, ctl);
 	mutex_unlock(&bp->cnic_mutex);
@@ -10000,7 +10337,7 @@ static int bnx2x_drv_ctl(struct net_device *dev, struct drv_ctl_info *ctl)
 		int count = ctl->data.credit.credit_count;
 
 		smp_mb__before_atomic_inc();
-		atomic_add(count, &bp->spq_left);
+		atomic_add(count, &bp->cq_spq_left);
 		smp_mb__after_atomic_inc();
 		break;
 	}
@@ -10096,6 +10433,13 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
 	struct bnx2x *bp = netdev_priv(dev);
 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
+	/* If both iSCSI and FCoE are disabled - return NULL in
+	 * order to indicate CNIC that it should not try to work
+	 * with this device.
+	 */
+	if (NO_ISCSI(bp) && NO_FCOE(bp))
+		return NULL;
+
 	cp->drv_owner = THIS_MODULE;
 	cp->chip_id = CHIP_ID(bp);
 	cp->pdev = bp->pdev;
@@ -10116,6 +10460,15 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
 		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
 	cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
 
+	if (NO_ISCSI_OOO(bp))
+		cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
+
+	if (NO_ISCSI(bp))
+		cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
+
+	if (NO_FCOE(bp))
+		cp->drv_state |= CNIC_DRV_STATE_NO_FCOE;
+
 	DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
 			 "starting cid %d\n",
 	   cp->ctx_blk_size,
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h
index e01330b..1c89f19 100644
--- a/drivers/net/bnx2x/bnx2x_reg.h
+++ b/drivers/net/bnx2x/bnx2x_reg.h
@@ -6083,6 +6083,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_PMA_REG_8727_PCS_OPT_CTRL		0xc808
 #define MDIO_PMA_REG_8727_GPIO_CTRL		0xc80e
 #define MDIO_PMA_REG_8727_PCS_GP		0xc842
+#define MDIO_PMA_REG_8727_OPT_CFG_REG		0xc8e4
 
 #define MDIO_AN_REG_8727_MISC_CTRL		0x8309
 
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile
index 0e2737e..3c5c014 100644
--- a/drivers/net/bonding/Makefile
+++ b/drivers/net/bonding/Makefile
@@ -6,6 +6,9 @@ obj-$(CONFIG_BONDING) += bonding.o
 
 bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o
 
+proc-$(CONFIG_PROC_FS) += bond_procfs.o
+bonding-objs += $(proc-y)
+
 ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
 bonding-objs += $(ipv6-y)
 
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index a5d5d0b..494bf96 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -246,7 +246,7 @@ static inline void __enable_port(struct port *port)
  */
 static inline int __port_is_enabled(struct port *port)
 {
-	return port->slave->state == BOND_STATE_ACTIVE;
+	return bond_is_active_slave(port->slave);
 }
 
 /**
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 5c6fba8..9bc5de3 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -604,7 +604,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
 
 	_lock_rx_hashtbl(bond);
 
-	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_src));
+	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 	if (client_info->assigned) {
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 163e0b0..338bea1 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -59,15 +59,12 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
-#include <linux/netpoll.h>
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/smp.h>
 #include <linux/if_ether.h>
 #include <net/arp.h>
@@ -174,9 +171,6 @@ MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on link
 atomic_t netpoll_block_tx = ATOMIC_INIT(0);
 #endif
 
-static const char * const version =
-	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
-
 int bond_net_id __read_mostly;
 
 static __be32 arp_target[BOND_MAX_ARP_TARGETS];
@@ -246,7 +240,7 @@ static void bond_uninit(struct net_device *bond_dev);
 
 /*---------------------------- General routines -----------------------------*/
 
-static const char *bond_mode_name(int mode)
+const char *bond_mode_name(int mode)
 {
 	static const char *names[] = {
 		[BOND_MODE_ROUNDROBIN] = "load balancing (round-robin)",
@@ -424,15 +418,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
 {
 	skb->dev = slave_dev;
 	skb->priority = 1;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
-		struct netpoll *np = bond->dev->npinfo->netpoll;
-		slave_dev->npinfo = bond->dev->npinfo;
-		slave_dev->priv_flags |= IFF_IN_NETPOLL;
-		netpoll_send_skb_on_dev(np, skb, slave_dev);
-		slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
-	} else
-#endif
+	if (unlikely(netpoll_tx_running(slave_dev)))
+		bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb);
+	else
 		dev_queue_xmit(skb);
 
 	return 0;
@@ -1288,63 +1276,103 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * You must hold read lock on bond->lock before calling this.
- */
-static bool slaves_support_netpoll(struct net_device *bond_dev)
+static inline int slave_enable_netpoll(struct slave *slave)
 {
-	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave;
-	int i = 0;
-	bool ret = true;
+	struct netpoll *np;
+	int err = 0;
 
-	bond_for_each_slave(bond, slave, i) {
-		if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL) ||
-		    !slave->dev->netdev_ops->ndo_poll_controller)
-			ret = false;
+	np = kzalloc(sizeof(*np), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!np)
+		goto out;
+
+	np->dev = slave->dev;
+	err = __netpoll_setup(np);
+	if (err) {
+		kfree(np);
+		goto out;
 	}
-	return i != 0 && ret;
+	slave->np = np;
+out:
+	return err;
+}
+static inline void slave_disable_netpoll(struct slave *slave)
+{
+	struct netpoll *np = slave->np;
+
+	if (!np)
+		return;
+
+	slave->np = NULL;
+	synchronize_rcu_bh();
+	__netpoll_cleanup(np);
+	kfree(np);
+}
+static inline bool slave_dev_support_netpoll(struct net_device *slave_dev)
+{
+	if (slave_dev->priv_flags & IFF_DISABLE_NETPOLL)
+		return false;
+	if (!slave_dev->netdev_ops->ndo_poll_controller)
+		return false;
+	return true;
 }
 
 static void bond_poll_controller(struct net_device *bond_dev)
 {
-	struct bonding *bond = netdev_priv(bond_dev);
+}
+
+static void __bond_netpoll_cleanup(struct bonding *bond)
+{
 	struct slave *slave;
 	int i;
 
-	bond_for_each_slave(bond, slave, i) {
-		if (slave->dev && IS_UP(slave->dev))
-			netpoll_poll_dev(slave->dev);
-	}
+	bond_for_each_slave(bond, slave, i)
+		if (IS_UP(slave->dev))
+			slave_disable_netpoll(slave);
 }
-
 static void bond_netpoll_cleanup(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+
+	read_lock(&bond->lock);
+	__bond_netpoll_cleanup(bond);
+	read_unlock(&bond->lock);
+}
+
+static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
+{
+	struct bonding *bond = netdev_priv(dev);
 	struct slave *slave;
-	const struct net_device_ops *ops;
-	int i;
+	int i, err = 0;
 
 	read_lock(&bond->lock);
-	bond_dev->npinfo = NULL;
 	bond_for_each_slave(bond, slave, i) {
-		if (slave->dev) {
-			ops = slave->dev->netdev_ops;
-			if (ops->ndo_netpoll_cleanup)
-				ops->ndo_netpoll_cleanup(slave->dev);
-			else
-				slave->dev->npinfo = NULL;
+		err = slave_enable_netpoll(slave);
+		if (err) {
+			__bond_netpoll_cleanup(bond);
+			break;
 		}
 	}
 	read_unlock(&bond->lock);
+	return err;
 }
 
-#else
+static struct netpoll_info *bond_netpoll_info(struct bonding *bond)
+{
+	return bond->dev->npinfo;
+}
 
+#else
+static inline int slave_enable_netpoll(struct slave *slave)
+{
+	return 0;
+}
+static inline void slave_disable_netpoll(struct slave *slave)
+{
+}
 static void bond_netpoll_cleanup(struct net_device *bond_dev)
 {
 }
-
 #endif
 
 /*---------------------------------- IOCTL ----------------------------------*/
@@ -1372,8 +1400,8 @@ static int bond_compute_features(struct bonding *bond)
 {
 	struct slave *slave;
 	struct net_device *bond_dev = bond->dev;
-	unsigned long features = bond_dev->features;
-	unsigned long vlan_features = 0;
+	u32 features = bond_dev->features;
+	u32 vlan_features = 0;
 	unsigned short max_hard_header_len = max((u16)ETH_HLEN,
 						bond_dev->hard_header_len);
 	int i;
@@ -1400,8 +1428,8 @@ static int bond_compute_features(struct bonding *bond)
 
 done:
 	features |= (bond_dev->features & BOND_VLAN_FEATURES);
-	bond_dev->features = netdev_fix_features(features, NULL);
-	bond_dev->vlan_features = netdev_fix_features(vlan_features, NULL);
+	bond_dev->features = netdev_fix_features(bond_dev, features);
+	bond_dev->vlan_features = netdev_fix_features(bond_dev, vlan_features);
 	bond_dev->hard_header_len = max_hard_header_len;
 
 	return 0;
@@ -1423,6 +1451,77 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
 	bond->setup_by_slave = 1;
 }
 
+/* On bonding slaves other than the currently active slave, suppress
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
+ */
+static bool bond_should_deliver_exact_match(struct sk_buff *skb,
+					    struct slave *slave,
+					    struct bonding *bond)
+{
+	if (bond_is_slave_inactive(slave)) {
+		if (slave_do_arp_validate(bond, slave) &&
+		    skb->protocol == __cpu_to_be16(ETH_P_ARP))
+			return false;
+
+		if (bond->params.mode == BOND_MODE_ALB &&
+		    skb->pkt_type != PACKET_BROADCAST &&
+		    skb->pkt_type != PACKET_MULTICAST)
+				return false;
+
+		if (bond->params.mode == BOND_MODE_8023AD &&
+		    skb->protocol == __cpu_to_be16(ETH_P_SLOW))
+			return false;
+
+		return true;
+	}
+	return false;
+}
+
+static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct slave *slave;
+	struct net_device *bond_dev;
+	struct bonding *bond;
+
+	slave = bond_slave_get_rcu(skb->dev);
+	bond_dev = ACCESS_ONCE(slave->dev->master);
+	if (unlikely(!bond_dev))
+		return RX_HANDLER_PASS;
+
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (unlikely(!skb))
+		return RX_HANDLER_CONSUMED;
+
+	*pskb = skb;
+
+	bond = netdev_priv(bond_dev);
+
+	if (bond->params.arp_interval)
+		slave->dev->last_rx = jiffies;
+
+	if (bond_should_deliver_exact_match(skb, slave, bond)) {
+		return RX_HANDLER_EXACT;
+	}
+
+	skb->dev = bond_dev;
+
+	if (bond->params.mode == BOND_MODE_ALB &&
+	    bond_dev->priv_flags & IFF_BRIDGE_PORT &&
+	    skb->pkt_type == PACKET_HOST) {
+
+		if (unlikely(skb_cow_head(skb,
+					  skb->data - skb_mac_header(skb)))) {
+			kfree_skb(skb);
+			return RX_HANDLER_CONSUMED;
+		}
+		memcpy(eth_hdr(skb)->h_dest, bond_dev->dev_addr, ETH_ALEN);
+	}
+
+	return RX_HANDLER_ANOTHER;
+}
+
 /* enslave device <slave> to bond device <master> */
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 {
@@ -1594,16 +1693,23 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		}
 	}
 
-	res = netdev_set_master(slave_dev, bond_dev);
+	res = netdev_set_bond_master(slave_dev, bond_dev);
 	if (res) {
-		pr_debug("Error %d calling netdev_set_master\n", res);
+		pr_debug("Error %d calling netdev_set_bond_master\n", res);
 		goto err_restore_mac;
 	}
+	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
+					 new_slave);
+	if (res) {
+		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
+		goto err_unset_master;
+	}
+
 	/* open the slave since the application closed it */
 	res = dev_open(slave_dev);
 	if (res) {
 		pr_debug("Opening slave %s failed\n", slave_dev->name);
-		goto err_unset_master;
+		goto err_unreg_rxhandler;
 	}
 
 	new_slave->dev = slave_dev;
@@ -1757,7 +1863,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		break;
 	case BOND_MODE_TLB:
 	case BOND_MODE_ALB:
-		new_slave->state = BOND_STATE_ACTIVE;
+		bond_set_active_slave(new_slave);
 		bond_set_slave_inactive_flags(new_slave);
 		bond_select_active_slave(bond);
 		break;
@@ -1765,7 +1871,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 		pr_debug("This slave is always active in trunk mode\n");
 
 		/* always active in trunk mode */
-		new_slave->state = BOND_STATE_ACTIVE;
+		bond_set_active_slave(new_slave);
 
 		/* In trunking mode there is little meaning to curr_active_slave
 		 * anyway (it holds no special properties of the bond device),
@@ -1782,17 +1888,19 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 	bond_set_carrier(bond);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	if (slaves_support_netpoll(bond_dev)) {
-		bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
-		if (bond_dev->npinfo)
-			slave_dev->npinfo = bond_dev->npinfo;
-	} else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
-		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
-		pr_info("New slave device %s does not support netpoll\n",
-			slave_dev->name);
-		pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+	slave_dev->npinfo = bond_netpoll_info(bond);
+	if (slave_dev->npinfo) {
+		if (slave_enable_netpoll(new_slave)) {
+			read_unlock(&bond->lock);
+			pr_info("Error, %s: master_dev is using netpoll, "
+				 "but new slave device does not support netpoll.\n",
+				 bond_dev->name);
+			res = -EBUSY;
+			goto err_close;
+		}
 	}
 #endif
+
 	read_unlock(&bond->lock);
 
 	res = bond_create_slave_symlinks(bond_dev, slave_dev);
@@ -1801,7 +1909,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
 		bond_dev->name, slave_dev->name,
-		new_slave->state == BOND_STATE_ACTIVE ? "n active" : " backup",
+		bond_is_active_slave(new_slave) ? "n active" : " backup",
 		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
 
 	/* enslave is successful */
@@ -1811,8 +1919,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 err_close:
 	dev_close(slave_dev);
 
+err_unreg_rxhandler:
+	netdev_rx_handler_unregister(slave_dev);
+	synchronize_net();
+
 err_unset_master:
-	netdev_set_master(slave_dev, NULL);
+	netdev_set_bond_master(slave_dev, NULL);
 
 err_restore_mac:
 	if (!bond->params.fail_over_mac) {
@@ -1895,7 +2007,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	pr_info("%s: releasing %s interface %s\n",
 		bond_dev->name,
-		(slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
+		bond_is_active_slave(slave) ? "active" : "backup",
 		slave_dev->name);
 
 	oldcurrent = bond->curr_active_slave;
@@ -1992,19 +2104,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 		netif_addr_unlock_bh(bond_dev);
 	}
 
-	netdev_set_master(slave_dev, NULL);
+	netdev_rx_handler_unregister(slave_dev);
+	synchronize_net();
+	netdev_set_bond_master(slave_dev, NULL);
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	read_lock_bh(&bond->lock);
-
-	if (slaves_support_netpoll(bond_dev))
-		bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
-	read_unlock_bh(&bond->lock);
-	if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
-		slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
-	else
-		slave_dev->npinfo = NULL;
-#endif
+	slave_disable_netpoll(slave);
 
 	/* close slave before restoring its mac address */
 	dev_close(slave_dev);
@@ -2018,9 +2122,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 
 	dev_set_mtu(slave_dev, slave->original_mtu);
 
-	slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-				   IFF_SLAVE_INACTIVE | IFF_BONDING |
-				   IFF_SLAVE_NEEDARP);
+	slave_dev->priv_flags &= ~IFF_BONDING;
 
 	kfree(slave);
 
@@ -2028,7 +2130,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
 }
 
 /*
-* First release a slave and than destroy the bond if no more slaves are left.
+* First release a slave and then destroy the bond if no more slaves are left.
 * Must be under rtnl_lock when this function is called.
 */
 static int  bond_release_and_destroy(struct net_device *bond_dev,
@@ -2039,6 +2141,7 @@ static int  bond_release_and_destroy(struct net_device *bond_dev,
 
 	ret = bond_release(bond_dev, slave_dev);
 	if ((ret == 0) && (bond->slave_cnt == 0)) {
+		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
 		pr_info("%s: destroying bond %s.\n",
 			bond_dev->name, bond_dev->name);
 		unregister_netdevice(bond_dev);
@@ -2114,7 +2217,11 @@ static int bond_release_all(struct net_device *bond_dev)
 			netif_addr_unlock_bh(bond_dev);
 		}
 
-		netdev_set_master(slave_dev, NULL);
+		netdev_rx_handler_unregister(slave_dev);
+		synchronize_net();
+		netdev_set_bond_master(slave_dev, NULL);
+
+		slave_disable_netpoll(slave);
 
 		/* close slave before restoring its mac address */
 		dev_close(slave_dev);
@@ -2126,9 +2233,6 @@ static int bond_release_all(struct net_device *bond_dev)
 			dev_set_mac_address(slave_dev, &addr);
 		}
 
-		slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-					   IFF_SLAVE_INACTIVE);
-
 		kfree(slave);
 
 		/* re-acquire the lock before getting the next slave */
@@ -2242,7 +2346,7 @@ static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *in
 			res = 0;
 			strcpy(info->slave_name, slave->dev->name);
 			info->link = slave->link;
-			info->state = slave->state;
+			info->state = bond_slave_state(slave);
 			info->link_failure_count = slave->link_failure_count;
 			break;
 		}
@@ -2281,7 +2385,7 @@ static int bond_miimon_inspect(struct bonding *bond)
 					bond->dev->name,
 					(bond->params.mode ==
 					 BOND_MODE_ACTIVEBACKUP) ?
-					((slave->state == BOND_STATE_ACTIVE) ?
+					(bond_is_active_slave(slave) ?
 					 "active " : "backup ") : "",
 					slave->dev->name,
 					bond->params.downdelay * bond->params.miimon);
@@ -2372,13 +2476,13 @@ static void bond_miimon_commit(struct bonding *bond)
 
 			if (bond->params.mode == BOND_MODE_8023AD) {
 				/* prevent it from being the active one */
-				slave->state = BOND_STATE_BACKUP;
+				bond_set_backup_slave(slave);
 			} else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
 				/* make it immediately active */
-				slave->state = BOND_STATE_ACTIVE;
+				bond_set_active_slave(slave);
 			} else if (slave != bond->primary_slave) {
 				/* prevent it from being the active one */
-				slave->state = BOND_STATE_BACKUP;
+				bond_set_backup_slave(slave);
 			}
 
 			bond_update_speed_duplex(slave);
@@ -2571,11 +2675,10 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
 
 static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
-	int i, vlan_id, rv;
+	int i, vlan_id;
 	__be32 *targets = bond->params.arp_targets;
 	struct vlan_entry *vlan;
 	struct net_device *vlan_dev;
-	struct flowi fl;
 	struct rtable *rt;
 
 	for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
@@ -2594,15 +2697,12 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 		 * determine which VLAN interface would be used, so we
 		 * can tag the ARP with the proper VLAN tag.
 		 */
-		memset(&fl, 0, sizeof(fl));
-		fl.fl4_dst = targets[i];
-		fl.fl4_tos = RTO_ONLINK;
-
-		rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl);
-		if (rv) {
+		rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
+				     RTO_ONLINK, 0);
+		if (IS_ERR(rt)) {
 			if (net_ratelimit()) {
 				pr_warning("%s: no route to arp_ip_target %pI4\n",
-					   bond->dev->name, &fl.fl4_dst);
+					   bond->dev->name, &targets[i]);
 			}
 			continue;
 		}
@@ -2638,7 +2738,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 
 		if (net_ratelimit()) {
 			pr_warning("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
-				   bond->dev->name, &fl.fl4_dst,
+				   bond->dev->name, &targets[i],
 				   rt->dst.dev ? rt->dst.dev->name : "NULL");
 		}
 		ip_rt_put(rt);
@@ -2756,7 +2856,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
 	memcpy(&tip, arp_ptr, 4);
 
 	pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
-		 bond->dev->name, slave->dev->name, slave->state,
+		 bond->dev->name, slave->dev->name, bond_slave_state(slave),
 		 bond->params.arp_validate, slave_do_arp_validate(bond, slave),
 		 &sip, &tip);
 
@@ -2768,7 +2868,7 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
 	 * the active, through one switch, the router, then the other
 	 * switch before reaching the backup.
 	 */
-	if (slave->state == BOND_STATE_ACTIVE)
+	if (bond_is_active_slave(slave))
 		bond_validate_arp(bond, slave, sip, tip);
 	else
 		bond_validate_arp(bond, slave, tip, sip);
@@ -2830,7 +2930,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 				slave->dev->last_rx + delta_in_ticks)) {
 
 				slave->link  = BOND_LINK_UP;
-				slave->state = BOND_STATE_ACTIVE;
+				bond_set_active_slave(slave);
 
 				/* primary_slave has no meaning in round-robin
 				 * mode. the window of a slave being up and
@@ -2863,7 +2963,7 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
 				slave->dev->last_rx + 2 * delta_in_ticks)) {
 
 				slave->link  = BOND_LINK_DOWN;
-				slave->state = BOND_STATE_BACKUP;
+				bond_set_backup_slave(slave);
 
 				if (slave->link_failure_count < UINT_MAX)
 					slave->link_failure_count++;
@@ -2957,7 +3057,7 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
 		 * gives each slave a chance to tx/rx traffic
 		 * before being taken out
 		 */
-		if (slave->state == BOND_STATE_BACKUP &&
+		if (!bond_is_active_slave(slave) &&
 		    !bond->current_arp_slave &&
 		    !time_in_range(jiffies,
 			slave_last_rx(bond, slave) - delta_in_ticks,
@@ -2974,7 +3074,7 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
 		 *    the bond has an IP address)
 		 */
 		trans_start = dev_trans_start(slave->dev);
-		if ((slave->state == BOND_STATE_ACTIVE) &&
+		if (bond_is_active_slave(slave) &&
 		    (!time_in_range(jiffies,
 			trans_start - delta_in_ticks,
 			trans_start + 2 * delta_in_ticks) ||
@@ -3182,299 +3282,6 @@ out:
 	read_unlock(&bond->lock);
 }
 
-/*------------------------------ proc/seq_file-------------------------------*/
-
-#ifdef CONFIG_PROC_FS
-
-static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(RCU)
-	__acquires(&bond->lock)
-{
-	struct bonding *bond = seq->private;
-	loff_t off = 0;
-	struct slave *slave;
-	int i;
-
-	/* make sure the bond won't be taken away */
-	rcu_read_lock();
-	read_lock(&bond->lock);
-
-	if (*pos == 0)
-		return SEQ_START_TOKEN;
-
-	bond_for_each_slave(bond, slave, i) {
-		if (++off == *pos)
-			return slave;
-	}
-
-	return NULL;
-}
-
-static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	struct bonding *bond = seq->private;
-	struct slave *slave = v;
-
-	++*pos;
-	if (v == SEQ_START_TOKEN)
-		return bond->first_slave;
-
-	slave = slave->next;
-
-	return (slave == bond->first_slave) ? NULL : slave;
-}
-
-static void bond_info_seq_stop(struct seq_file *seq, void *v)
-	__releases(&bond->lock)
-	__releases(RCU)
-{
-	struct bonding *bond = seq->private;
-
-	read_unlock(&bond->lock);
-	rcu_read_unlock();
-}
-
-static void bond_info_show_master(struct seq_file *seq)
-{
-	struct bonding *bond = seq->private;
-	struct slave *curr;
-	int i;
-
-	read_lock(&bond->curr_slave_lock);
-	curr = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
-	seq_printf(seq, "Bonding Mode: %s",
-		   bond_mode_name(bond->params.mode));
-
-	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
-	    bond->params.fail_over_mac)
-		seq_printf(seq, " (fail_over_mac %s)",
-		   fail_over_mac_tbl[bond->params.fail_over_mac].modename);
-
-	seq_printf(seq, "\n");
-
-	if (bond->params.mode == BOND_MODE_XOR ||
-		bond->params.mode == BOND_MODE_8023AD) {
-		seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
-			xmit_hashtype_tbl[bond->params.xmit_policy].modename,
-			bond->params.xmit_policy);
-	}
-
-	if (USES_PRIMARY(bond->params.mode)) {
-		seq_printf(seq, "Primary Slave: %s",
-			   (bond->primary_slave) ?
-			   bond->primary_slave->dev->name : "None");
-		if (bond->primary_slave)
-			seq_printf(seq, " (primary_reselect %s)",
-		   pri_reselect_tbl[bond->params.primary_reselect].modename);
-
-		seq_printf(seq, "\nCurrently Active Slave: %s\n",
-			   (curr) ? curr->dev->name : "None");
-	}
-
-	seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
-		   "up" : "down");
-	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
-	seq_printf(seq, "Up Delay (ms): %d\n",
-		   bond->params.updelay * bond->params.miimon);
-	seq_printf(seq, "Down Delay (ms): %d\n",
-		   bond->params.downdelay * bond->params.miimon);
-
-
-	/* ARP information */
-	if (bond->params.arp_interval > 0) {
-		int printed = 0;
-		seq_printf(seq, "ARP Polling Interval (ms): %d\n",
-				bond->params.arp_interval);
-
-		seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
-
-		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
-			if (!bond->params.arp_targets[i])
-				break;
-			if (printed)
-				seq_printf(seq, ",");
-			seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
-			printed = 1;
-		}
-		seq_printf(seq, "\n");
-	}
-
-	if (bond->params.mode == BOND_MODE_8023AD) {
-		struct ad_info ad_info;
-
-		seq_puts(seq, "\n802.3ad info\n");
-		seq_printf(seq, "LACP rate: %s\n",
-			   (bond->params.lacp_fast) ? "fast" : "slow");
-		seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
-			   ad_select_tbl[bond->params.ad_select].modename);
-
-		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
-			seq_printf(seq, "bond %s has no active aggregator\n",
-				   bond->dev->name);
-		} else {
-			seq_printf(seq, "Active Aggregator Info:\n");
-
-			seq_printf(seq, "\tAggregator ID: %d\n",
-				   ad_info.aggregator_id);
-			seq_printf(seq, "\tNumber of ports: %d\n",
-				   ad_info.ports);
-			seq_printf(seq, "\tActor Key: %d\n",
-				   ad_info.actor_key);
-			seq_printf(seq, "\tPartner Key: %d\n",
-				   ad_info.partner_key);
-			seq_printf(seq, "\tPartner Mac Address: %pM\n",
-				   ad_info.partner_system);
-		}
-	}
-}
-
-static void bond_info_show_slave(struct seq_file *seq,
-				 const struct slave *slave)
-{
-	struct bonding *bond = seq->private;
-
-	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
-	seq_printf(seq, "MII Status: %s\n",
-		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-	seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
-	seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
-	seq_printf(seq, "Link Failure Count: %u\n",
-		   slave->link_failure_count);
-
-	seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
-
-	if (bond->params.mode == BOND_MODE_8023AD) {
-		const struct aggregator *agg
-			= SLAVE_AD_INFO(slave).port.aggregator;
-
-		if (agg)
-			seq_printf(seq, "Aggregator ID: %d\n",
-				   agg->aggregator_identifier);
-		else
-			seq_puts(seq, "Aggregator ID: N/A\n");
-	}
-	seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
-}
-
-static int bond_info_seq_show(struct seq_file *seq, void *v)
-{
-	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "%s\n", version);
-		bond_info_show_master(seq);
-	} else
-		bond_info_show_slave(seq, v);
-
-	return 0;
-}
-
-static const struct seq_operations bond_info_seq_ops = {
-	.start = bond_info_seq_start,
-	.next  = bond_info_seq_next,
-	.stop  = bond_info_seq_stop,
-	.show  = bond_info_seq_show,
-};
-
-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;
-	}
-
-	return res;
-}
-
-static const struct file_operations bond_info_fops = {
-	.owner   = THIS_MODULE,
-	.open    = bond_info_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-static void bond_create_proc_entry(struct bonding *bond)
-{
-	struct net_device *bond_dev = bond->dev;
-	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
-
-	if (bn->proc_dir) {
-		bond->proc_entry = proc_create_data(bond_dev->name,
-						    S_IRUGO, bn->proc_dir,
-						    &bond_info_fops, bond);
-		if (bond->proc_entry == NULL)
-			pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
-				   DRV_NAME, bond_dev->name);
-		else
-			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
-	}
-}
-
-static void bond_remove_proc_entry(struct bonding *bond)
-{
-	struct net_device *bond_dev = bond->dev;
-	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
-
-	if (bn->proc_dir && bond->proc_entry) {
-		remove_proc_entry(bond->proc_file_name, bn->proc_dir);
-		memset(bond->proc_file_name, 0, IFNAMSIZ);
-		bond->proc_entry = NULL;
-	}
-}
-
-/* Create the bonding directory under /proc/net, if doesn't exist yet.
- * Caller must hold rtnl_lock.
- */
-static void __net_init bond_create_proc_dir(struct bond_net *bn)
-{
-	if (!bn->proc_dir) {
-		bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
-		if (!bn->proc_dir)
-			pr_warning("Warning: cannot create /proc/net/%s\n",
-				   DRV_NAME);
-	}
-}
-
-/* Destroy the bonding directory under /proc/net, if empty.
- * Caller must hold rtnl_lock.
- */
-static void __net_exit bond_destroy_proc_dir(struct bond_net *bn)
-{
-	if (bn->proc_dir) {
-		remove_proc_entry(DRV_NAME, bn->net->proc_net);
-		bn->proc_dir = NULL;
-	}
-}
-
-#else /* !CONFIG_PROC_FS */
-
-static void bond_create_proc_entry(struct bonding *bond)
-{
-}
-
-static void bond_remove_proc_entry(struct bonding *bond)
-{
-}
-
-static inline void bond_create_proc_dir(struct bond_net *bn)
-{
-}
-
-static inline void bond_destroy_proc_dir(struct bond_net *bn)
-{
-}
-
-#endif /* CONFIG_PROC_FS */
-
-
 /*-------------------------- netdev event handling --------------------------*/
 
 /*
@@ -4331,7 +4138,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
-		    (slave->state == BOND_STATE_ACTIVE)) {
+		    bond_is_active_slave(slave)) {
 			res = bond_dev_queue_xmit(bond, skb, slave->dev);
 			break;
 		}
@@ -4408,7 +4215,7 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
-		    (slave->state == BOND_STATE_ACTIVE)) {
+		    bond_is_active_slave(slave)) {
 			res = bond_dev_queue_xmit(bond, skb, slave->dev);
 			break;
 		}
@@ -4449,7 +4256,7 @@ static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
-		    (slave->state == BOND_STATE_ACTIVE)) {
+		    bond_is_active_slave(slave)) {
 			if (tx_dev) {
 				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 				if (!skb2) {
@@ -4537,11 +4344,18 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
 	/*
 	 * This helper function exists to help dev_pick_tx get the correct
-	 * destination queue.  Using a helper function skips the a call to
+	 * destination queue.  Using a helper function skips a call to
 	 * skb_tx_hash and will put the skbs in the queue we expect on their
 	 * way down to the bonding driver.
 	 */
-	return skb->queue_mapping;
+	u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
+
+	if (unlikely(txq >= dev->real_num_tx_queues)) {
+		do
+			txq -= dev->real_num_tx_queues;
+		while (txq >= dev->real_num_tx_queues);
+	}
+	return txq;
 }
 
 static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -4603,11 +4417,9 @@ void bond_set_mode_ops(struct bonding *bond, int mode)
 	case BOND_MODE_BROADCAST:
 		break;
 	case BOND_MODE_8023AD:
-		bond_set_master_3ad_flags(bond);
 		bond_set_xmit_hash_policy(bond);
 		break;
 	case BOND_MODE_ALB:
-		bond_set_master_alb_flags(bond);
 		/* FALLTHRU */
 	case BOND_MODE_TLB:
 		break;
@@ -4654,9 +4466,12 @@ static const struct net_device_ops bond_netdev_ops = {
 	.ndo_vlan_rx_add_vid 	= bond_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= bond_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_netpoll_setup	= bond_netpoll_setup,
 	.ndo_netpoll_cleanup	= bond_netpoll_cleanup,
 	.ndo_poll_controller	= bond_poll_controller,
 #endif
+	.ndo_add_slave		= bond_enslave,
+	.ndo_del_slave		= bond_release,
 };
 
 static void bond_destructor(struct net_device *bond_dev)
@@ -4695,9 +4510,6 @@ static void bond_setup(struct net_device *bond_dev)
 	bond_dev->priv_flags |= IFF_BONDING;
 	bond_dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 
-	if (bond->params.arp_interval)
-		bond_dev->priv_flags |= IFF_MASTER_ARPMON;
-
 	/* At first, we block adding VLANs. That's the only way to
 	 * prevent problems that occur when adding VLANs over an
 	 * empty bond. The block will be removed once non-challenged
@@ -5166,8 +4978,6 @@ static int bond_init(struct net_device *bond_dev)
 
 	bond_set_lockdep_class(bond_dev);
 
-	netif_carrier_off(bond_dev);
-
 	bond_create_proc_entry(bond);
 	list_add_tail(&bond->bond_list, &bn->dev_list);
 
@@ -5237,6 +5047,8 @@ int bond_create(struct net *net, const char *name)
 
 	res = register_netdevice(bond_dev);
 
+	netif_carrier_off(bond_dev);
+
 out:
 	rtnl_unlock();
 	if (res < 0)
@@ -5275,7 +5087,7 @@ static int __init bonding_init(void)
 	int i;
 	int res;
 
-	pr_info("%s", version);
+	pr_info("%s", bond_version);
 
 	res = bond_check_params(&bonding_defaults);
 	if (res)
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
new file mode 100644
index 0000000..c32ff55
--- /dev/null
+++ b/drivers/net/bonding/bond_procfs.c
@@ -0,0 +1,275 @@
+#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include "bonding.h"
+
+
+extern const char *bond_mode_name(int mode);
+
+static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
+	__acquires(RCU)
+	__acquires(&bond->lock)
+{
+	struct bonding *bond = seq->private;
+	loff_t off = 0;
+	struct slave *slave;
+	int i;
+
+	/* make sure the bond won't be taken away */
+	rcu_read_lock();
+	read_lock(&bond->lock);
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (++off == *pos)
+			return slave;
+	}
+
+	return NULL;
+}
+
+static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct bonding *bond = seq->private;
+	struct slave *slave = v;
+
+	++*pos;
+	if (v == SEQ_START_TOKEN)
+		return bond->first_slave;
+
+	slave = slave->next;
+
+	return (slave == bond->first_slave) ? NULL : slave;
+}
+
+static void bond_info_seq_stop(struct seq_file *seq, void *v)
+	__releases(&bond->lock)
+	__releases(RCU)
+{
+	struct bonding *bond = seq->private;
+
+	read_unlock(&bond->lock);
+	rcu_read_unlock();
+}
+
+static void bond_info_show_master(struct seq_file *seq)
+{
+	struct bonding *bond = seq->private;
+	struct slave *curr;
+	int i;
+
+	read_lock(&bond->curr_slave_lock);
+	curr = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	seq_printf(seq, "Bonding Mode: %s",
+		   bond_mode_name(bond->params.mode));
+
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
+	    bond->params.fail_over_mac)
+		seq_printf(seq, " (fail_over_mac %s)",
+		   fail_over_mac_tbl[bond->params.fail_over_mac].modename);
+
+	seq_printf(seq, "\n");
+
+	if (bond->params.mode == BOND_MODE_XOR ||
+		bond->params.mode == BOND_MODE_8023AD) {
+		seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
+			xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+			bond->params.xmit_policy);
+	}
+
+	if (USES_PRIMARY(bond->params.mode)) {
+		seq_printf(seq, "Primary Slave: %s",
+			   (bond->primary_slave) ?
+			   bond->primary_slave->dev->name : "None");
+		if (bond->primary_slave)
+			seq_printf(seq, " (primary_reselect %s)",
+		   pri_reselect_tbl[bond->params.primary_reselect].modename);
+
+		seq_printf(seq, "\nCurrently Active Slave: %s\n",
+			   (curr) ? curr->dev->name : "None");
+	}
+
+	seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
+		   "up" : "down");
+	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
+	seq_printf(seq, "Up Delay (ms): %d\n",
+		   bond->params.updelay * bond->params.miimon);
+	seq_printf(seq, "Down Delay (ms): %d\n",
+		   bond->params.downdelay * bond->params.miimon);
+
+
+	/* ARP information */
+	if (bond->params.arp_interval > 0) {
+		int printed = 0;
+		seq_printf(seq, "ARP Polling Interval (ms): %d\n",
+				bond->params.arp_interval);
+
+		seq_printf(seq, "ARP IP target/s (n.n.n.n form):");
+
+		for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
+			if (!bond->params.arp_targets[i])
+				break;
+			if (printed)
+				seq_printf(seq, ",");
+			seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
+			printed = 1;
+		}
+		seq_printf(seq, "\n");
+	}
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+
+		seq_puts(seq, "\n802.3ad info\n");
+		seq_printf(seq, "LACP rate: %s\n",
+			   (bond->params.lacp_fast) ? "fast" : "slow");
+		seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
+			   ad_select_tbl[bond->params.ad_select].modename);
+
+		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+			seq_printf(seq, "bond %s has no active aggregator\n",
+				   bond->dev->name);
+		} else {
+			seq_printf(seq, "Active Aggregator Info:\n");
+
+			seq_printf(seq, "\tAggregator ID: %d\n",
+				   ad_info.aggregator_id);
+			seq_printf(seq, "\tNumber of ports: %d\n",
+				   ad_info.ports);
+			seq_printf(seq, "\tActor Key: %d\n",
+				   ad_info.actor_key);
+			seq_printf(seq, "\tPartner Key: %d\n",
+				   ad_info.partner_key);
+			seq_printf(seq, "\tPartner Mac Address: %pM\n",
+				   ad_info.partner_system);
+		}
+	}
+}
+
+static void bond_info_show_slave(struct seq_file *seq,
+				 const struct slave *slave)
+{
+	struct bonding *bond = seq->private;
+
+	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
+	seq_printf(seq, "MII Status: %s\n",
+		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
+	seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+	seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+	seq_printf(seq, "Link Failure Count: %u\n",
+		   slave->link_failure_count);
+
+	seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		const struct aggregator *agg
+			= SLAVE_AD_INFO(slave).port.aggregator;
+
+		if (agg)
+			seq_printf(seq, "Aggregator ID: %d\n",
+				   agg->aggregator_identifier);
+		else
+			seq_puts(seq, "Aggregator ID: N/A\n");
+	}
+	seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
+}
+
+static int bond_info_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "%s\n", bond_version);
+		bond_info_show_master(seq);
+	} else
+		bond_info_show_slave(seq, v);
+
+	return 0;
+}
+
+static const struct seq_operations bond_info_seq_ops = {
+	.start = bond_info_seq_start,
+	.next  = bond_info_seq_next,
+	.stop  = bond_info_seq_stop,
+	.show  = bond_info_seq_show,
+};
+
+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;
+	}
+
+	return res;
+}
+
+static const struct file_operations bond_info_fops = {
+	.owner   = THIS_MODULE,
+	.open    = bond_info_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
+void bond_create_proc_entry(struct bonding *bond)
+{
+	struct net_device *bond_dev = bond->dev;
+	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
+
+	if (bn->proc_dir) {
+		bond->proc_entry = proc_create_data(bond_dev->name,
+						    S_IRUGO, bn->proc_dir,
+						    &bond_info_fops, bond);
+		if (bond->proc_entry == NULL)
+			pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
+				   DRV_NAME, bond_dev->name);
+		else
+			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
+	}
+}
+
+void bond_remove_proc_entry(struct bonding *bond)
+{
+	struct net_device *bond_dev = bond->dev;
+	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
+
+	if (bn->proc_dir && bond->proc_entry) {
+		remove_proc_entry(bond->proc_file_name, bn->proc_dir);
+		memset(bond->proc_file_name, 0, IFNAMSIZ);
+		bond->proc_entry = NULL;
+	}
+}
+
+/* Create the bonding directory under /proc/net, if doesn't exist yet.
+ * Caller must hold rtnl_lock.
+ */
+void __net_init bond_create_proc_dir(struct bond_net *bn)
+{
+	if (!bn->proc_dir) {
+		bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
+		if (!bn->proc_dir)
+			pr_warning("Warning: cannot create /proc/net/%s\n",
+				   DRV_NAME);
+	}
+}
+
+/* Destroy the bonding directory under /proc/net, if empty.
+ * Caller must hold rtnl_lock.
+ */
+void __net_exit bond_destroy_proc_dir(struct bond_net *bn)
+{
+	if (bn->proc_dir) {
+		remove_proc_entry(DRV_NAME, bn->net->proc_net);
+		bn->proc_dir = NULL;
+	}
+}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 8fd0174..de87aea 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -118,7 +118,10 @@ static ssize_t bonding_store_bonds(struct class *cls,
 		pr_info("%s is being created...\n", ifname);
 		rv = bond_create(net, ifname);
 		if (rv) {
-			pr_info("Bond creation failed.\n");
+			if (rv == -EEXIST)
+				pr_info("%s already exists.\n", ifname);
+			else
+				pr_info("%s creation failed.\n", ifname);
 			res = rv;
 		}
 	} else if (command[0] == '-') {
@@ -322,11 +325,6 @@ static ssize_t bonding_store_mode(struct device *d,
 		ret = -EINVAL;
 		goto out;
 	}
-	if (bond->params.mode == BOND_MODE_8023AD)
-		bond_unset_master_3ad_flags(bond);
-
-	if (bond->params.mode == BOND_MODE_ALB)
-		bond_unset_master_alb_flags(bond);
 
 	bond->params.mode = new_value;
 	bond_set_mode_ops(bond, bond->params.mode);
@@ -527,8 +525,6 @@ 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.arp_interval)
-		bond->dev->priv_flags |= IFF_MASTER_ARPMON;
 	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);
@@ -1004,7 +1000,6 @@ static ssize_t bonding_store_miimon(struct device *d,
 			pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
 				bond->dev->name);
 			bond->params.arp_interval = 0;
-			bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
 			if (bond->params.arp_validate) {
 				bond_unregister_arp(bond);
 				bond->params.arp_validate =
@@ -1198,7 +1193,7 @@ static ssize_t bonding_store_carrier(struct device *d,
 			bond->dev->name, new_value);
 	}
 out:
-	return count;
+	return ret;
 }
 static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR,
 		   bonding_show_carrier, bonding_store_carrier);
@@ -1587,15 +1582,15 @@ static ssize_t bonding_store_slaves_active(struct device *d,
 	}
 
 	bond_for_each_slave(bond, slave, i) {
-		if (slave->state == BOND_STATE_BACKUP) {
+		if (!bond_is_active_slave(slave)) {
 			if (new_value)
-				slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+				slave->inactive = 0;
 			else
-				slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
+				slave->inactive = 1;
 		}
 	}
 out:
-	return count;
+	return ret;
 }
 static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
 		   bonding_show_slaves_active, bonding_store_slaves_active);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 31fe980..6b26962 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -20,6 +20,7 @@
 #include <linux/if_bonding.h>
 #include <linux/cpumask.h>
 #include <linux/in6.h>
+#include <linux/netpoll.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
@@ -28,6 +29,8 @@
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
+#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
+
 #define BOND_MAX_ARP_TARGETS	16
 
 #define IS_UP(dev)					   \
@@ -52,7 +55,7 @@
 		    (((slave)->dev->flags & IFF_UP)  && \
 		     netif_running((slave)->dev)     && \
 		     ((slave)->link == BOND_LINK_UP) && \
-		     ((slave)->state == BOND_STATE_ACTIVE))
+		     bond_is_active_slave(slave))
 
 
 #define USES_PRIMARY(mode)				\
@@ -132,7 +135,7 @@ static inline void unblock_netpoll_tx(void)
 
 static inline int is_netpoll_tx_blocked(struct net_device *dev)
 {
-	if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
+	if (unlikely(netpoll_tx_running(dev)))
 		return atomic_read(&netpoll_block_tx);
 	return 0;
 }
@@ -189,7 +192,9 @@ struct slave {
 	unsigned long last_arp_rx;
 	s8     link;    /* one of BOND_LINK_XXXX */
 	s8     new_link;
-	s8     state;   /* one of BOND_STATE_XXXX */
+	u8     backup:1,   /* indicates backup slave. Value corresponds with
+			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
+	       inactive:1; /* indicates inactive slave */
 	u32    original_mtu;
 	u32    link_failure_count;
 	u8     perm_hwaddr[ETH_ALEN];
@@ -198,6 +203,9 @@ struct slave {
 	u16    queue_id;
 	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
 	struct tlb_slave_info tlb_info;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	struct netpoll *np;
+#endif
 };
 
 /*
@@ -260,12 +268,16 @@ struct bonding {
 #endif /* CONFIG_DEBUG_FS */
 };
 
+#define bond_slave_get_rcu(dev) \
+	((struct slave *) rcu_dereference(dev->rx_handler_data))
+
 /**
  * Returns NULL if the net_device does not belong to any of the bond's slaves
  *
  * Caller must hold bond lock for read
  */
-static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
+						  struct net_device *slave_dev)
 {
 	struct slave *slave = NULL;
 	int i;
@@ -276,7 +288,7 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n
 		}
 	}
 
-	return 0;
+	return NULL;
 }
 
 static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
@@ -294,6 +306,26 @@ static inline bool bond_is_lb(const struct bonding *bond)
 		bond->params.mode == BOND_MODE_ALB);
 }
 
+static inline void bond_set_active_slave(struct slave *slave)
+{
+	slave->backup = 0;
+}
+
+static inline void bond_set_backup_slave(struct slave *slave)
+{
+	slave->backup = 1;
+}
+
+static inline int bond_slave_state(struct slave *slave)
+{
+	return slave->backup;
+}
+
+static inline bool bond_is_active_slave(struct slave *slave)
+{
+	return !bond_slave_state(slave);
+}
+
 #define BOND_PRI_RESELECT_ALWAYS	0
 #define BOND_PRI_RESELECT_BETTER	1
 #define BOND_PRI_RESELECT_FAILURE	2
@@ -311,7 +343,7 @@ static inline bool bond_is_lb(const struct bonding *bond)
 static inline int slave_do_arp_validate(struct bonding *bond,
 					struct slave *slave)
 {
-	return bond->params.arp_validate & (1 << slave->state);
+	return bond->params.arp_validate & (1 << bond_slave_state(slave));
 }
 
 static inline unsigned long slave_last_rx(struct bonding *bond,
@@ -323,41 +355,40 @@ static inline unsigned long slave_last_rx(struct bonding *bond,
 	return slave->dev->last_rx;
 }
 
-static inline void bond_set_slave_inactive_flags(struct slave *slave)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static inline void bond_netpoll_send_skb(const struct slave *slave,
+					 struct sk_buff *skb)
 {
-	struct bonding *bond = netdev_priv(slave->dev->master);
-	if (!bond_is_lb(bond))
-		slave->state = BOND_STATE_BACKUP;
-	if (!bond->params.all_slaves_active)
-		slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
-	if (slave_do_arp_validate(bond, slave))
-		slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
-}
+	struct netpoll *np = slave->np;
 
-static inline void bond_set_slave_active_flags(struct slave *slave)
-{
-	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
+	if (np)
+		netpoll_send_skb(np, skb);
 }
-
-static inline void bond_set_master_3ad_flags(struct bonding *bond)
+#else
+static inline void bond_netpoll_send_skb(const struct slave *slave,
+					 struct sk_buff *skb)
 {
-	bond->dev->priv_flags |= IFF_MASTER_8023AD;
 }
+#endif
 
-static inline void bond_unset_master_3ad_flags(struct bonding *bond)
+static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
-	bond->dev->priv_flags &= ~IFF_MASTER_8023AD;
+	struct bonding *bond = netdev_priv(slave->dev->master);
+	if (!bond_is_lb(bond))
+		bond_set_backup_slave(slave);
+	if (!bond->params.all_slaves_active)
+		slave->inactive = 1;
 }
 
-static inline void bond_set_master_alb_flags(struct bonding *bond)
+static inline void bond_set_slave_active_flags(struct slave *slave)
 {
-	bond->dev->priv_flags |= IFF_MASTER_ALB;
+	bond_set_active_slave(slave);
+	slave->inactive = 0;
 }
 
-static inline void bond_unset_master_alb_flags(struct bonding *bond)
+static inline bool bond_is_slave_inactive(struct slave *slave)
 {
-	bond->dev->priv_flags &= ~IFF_MASTER_ALB;
+	return slave->inactive;
 }
 
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
@@ -393,6 +424,30 @@ struct bond_net {
 #endif
 };
 
+#ifdef CONFIG_PROC_FS
+void bond_create_proc_entry(struct bonding *bond);
+void bond_remove_proc_entry(struct bonding *bond);
+void bond_create_proc_dir(struct bond_net *bn);
+void bond_destroy_proc_dir(struct bond_net *bn);
+#else
+static inline void bond_create_proc_entry(struct bonding *bond)
+{
+}
+
+static inline void bond_remove_proc_entry(struct bonding *bond)
+{
+}
+
+static inline void bond_create_proc_dir(struct bond_net *bn)
+{
+}
+
+static inline void bond_destroy_proc_dir(struct bond_net *bn)
+{
+}
+#endif
+
+
 /* exported from bond_main.c */
 extern int bond_net_id;
 extern const struct bond_parm_tbl bond_lacp_tbl[];
diff --git a/drivers/net/caif/Makefile b/drivers/net/caif/Makefile
index b38d987..9560b9d 100644
--- a/drivers/net/caif/Makefile
+++ b/drivers/net/caif/Makefile
@@ -1,6 +1,4 @@
-ifeq ($(CONFIG_CAIF_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG
 
 # Serial interface
 obj-$(CONFIG_CAIF_TTY) += caif_serial.o
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 5dec456..1d699e3 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -115,6 +115,8 @@ source "drivers/net/can/mscan/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
 
+source "drivers/net/can/c_can/Kconfig"
+
 source "drivers/net/can/usb/Kconfig"
 
 source "drivers/net/can/softing/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 53c82a7..24ebfe8 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -13,6 +13,7 @@ obj-y				+= softing/
 
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_MSCAN)		+= mscan/
+obj-$(CONFIG_CAN_C_CAN)		+= c_can/
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig
new file mode 100644
index 0000000..ffb9773
--- /dev/null
+++ b/drivers/net/can/c_can/Kconfig
@@ -0,0 +1,15 @@
+menuconfig CAN_C_CAN
+	tristate "Bosch C_CAN devices"
+	depends on CAN_DEV && HAS_IOMEM
+
+if CAN_C_CAN
+
+config CAN_C_CAN_PLATFORM
+	tristate "Generic Platform Bus based C_CAN driver"
+	---help---
+	  This driver adds support for the C_CAN chips connected to
+	  the "platform bus" (Linux abstraction for directly to the
+	  processor attached devices) which can be found on various
+	  boards from ST Microelectronics (http://www.st.com)
+	  like the SPEAr1310 and SPEAr320 evaluation boards.
+endif
diff --git a/drivers/net/can/c_can/Makefile b/drivers/net/can/c_can/Makefile
new file mode 100644
index 0000000..9273f6d
--- /dev/null
+++ b/drivers/net/can/c_can/Makefile
@@ -0,0 +1,8 @@
+#
+#  Makefile for the Bosch C_CAN controller drivers.
+#
+
+obj-$(CONFIG_CAN_C_CAN) += c_can.o
+obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
new file mode 100644
index 0000000..110eda0
--- /dev/null
+++ b/drivers/net/can/c_can/c_can.c
@@ -0,0 +1,1158 @@
+/*
+ * CAN bus driver for Bosch C_CAN controller
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma@st.com>
+ *
+ * Borrowed heavily from the C_CAN driver originally written by:
+ * Copyright (C) 2007
+ * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
+ * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
+ *
+ * TX and RX NAPI implementation has been borrowed from at91 CAN driver
+ * written by:
+ * Copyright
+ * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
+ * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
+ * Bosch C_CAN user manual can be obtained from:
+ * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
+ * users_manual_c_can.pdf
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#include "c_can.h"
+
+/* control register */
+#define CONTROL_TEST		BIT(7)
+#define CONTROL_CCE		BIT(6)
+#define CONTROL_DISABLE_AR	BIT(5)
+#define CONTROL_ENABLE_AR	(0 << 5)
+#define CONTROL_EIE		BIT(3)
+#define CONTROL_SIE		BIT(2)
+#define CONTROL_IE		BIT(1)
+#define CONTROL_INIT		BIT(0)
+
+/* test register */
+#define TEST_RX			BIT(7)
+#define TEST_TX1		BIT(6)
+#define TEST_TX2		BIT(5)
+#define TEST_LBACK		BIT(4)
+#define TEST_SILENT		BIT(3)
+#define TEST_BASIC		BIT(2)
+
+/* status register */
+#define STATUS_BOFF		BIT(7)
+#define STATUS_EWARN		BIT(6)
+#define STATUS_EPASS		BIT(5)
+#define STATUS_RXOK		BIT(4)
+#define STATUS_TXOK		BIT(3)
+
+/* error counter register */
+#define ERR_CNT_TEC_MASK	0xff
+#define ERR_CNT_TEC_SHIFT	0
+#define ERR_CNT_REC_SHIFT	8
+#define ERR_CNT_REC_MASK	(0x7f << ERR_CNT_REC_SHIFT)
+#define ERR_CNT_RP_SHIFT	15
+#define ERR_CNT_RP_MASK		(0x1 << ERR_CNT_RP_SHIFT)
+
+/* bit-timing register */
+#define BTR_BRP_MASK		0x3f
+#define BTR_BRP_SHIFT		0
+#define BTR_SJW_SHIFT		6
+#define BTR_SJW_MASK		(0x3 << BTR_SJW_SHIFT)
+#define BTR_TSEG1_SHIFT		8
+#define BTR_TSEG1_MASK		(0xf << BTR_TSEG1_SHIFT)
+#define BTR_TSEG2_SHIFT		12
+#define BTR_TSEG2_MASK		(0x7 << BTR_TSEG2_SHIFT)
+
+/* brp extension register */
+#define BRP_EXT_BRPE_MASK	0x0f
+#define BRP_EXT_BRPE_SHIFT	0
+
+/* IFx command request */
+#define IF_COMR_BUSY		BIT(15)
+
+/* IFx command mask */
+#define IF_COMM_WR		BIT(7)
+#define IF_COMM_MASK		BIT(6)
+#define IF_COMM_ARB		BIT(5)
+#define IF_COMM_CONTROL		BIT(4)
+#define IF_COMM_CLR_INT_PND	BIT(3)
+#define IF_COMM_TXRQST		BIT(2)
+#define IF_COMM_DATAA		BIT(1)
+#define IF_COMM_DATAB		BIT(0)
+#define IF_COMM_ALL		(IF_COMM_MASK | IF_COMM_ARB | \
+				IF_COMM_CONTROL | IF_COMM_TXRQST | \
+				IF_COMM_DATAA | IF_COMM_DATAB)
+
+/* IFx arbitration */
+#define IF_ARB_MSGVAL		BIT(15)
+#define IF_ARB_MSGXTD		BIT(14)
+#define IF_ARB_TRANSMIT		BIT(13)
+
+/* IFx message control */
+#define IF_MCONT_NEWDAT		BIT(15)
+#define IF_MCONT_MSGLST		BIT(14)
+#define IF_MCONT_CLR_MSGLST	(0 << 14)
+#define IF_MCONT_INTPND		BIT(13)
+#define IF_MCONT_UMASK		BIT(12)
+#define IF_MCONT_TXIE		BIT(11)
+#define IF_MCONT_RXIE		BIT(10)
+#define IF_MCONT_RMTEN		BIT(9)
+#define IF_MCONT_TXRQST		BIT(8)
+#define IF_MCONT_EOB		BIT(7)
+#define IF_MCONT_DLC_MASK	0xf
+
+/*
+ * IFx register masks:
+ * allow easy operation on 16-bit registers when the
+ * argument is 32-bit instead
+ */
+#define IFX_WRITE_LOW_16BIT(x)	((x) & 0xFFFF)
+#define IFX_WRITE_HIGH_16BIT(x)	(((x) & 0xFFFF0000) >> 16)
+
+/* message object split */
+#define C_CAN_NO_OF_OBJECTS	32
+#define C_CAN_MSG_OBJ_RX_NUM	16
+#define C_CAN_MSG_OBJ_TX_NUM	16
+
+#define C_CAN_MSG_OBJ_RX_FIRST	1
+#define C_CAN_MSG_OBJ_RX_LAST	(C_CAN_MSG_OBJ_RX_FIRST + \
+				C_CAN_MSG_OBJ_RX_NUM - 1)
+
+#define C_CAN_MSG_OBJ_TX_FIRST	(C_CAN_MSG_OBJ_RX_LAST + 1)
+#define C_CAN_MSG_OBJ_TX_LAST	(C_CAN_MSG_OBJ_TX_FIRST + \
+				C_CAN_MSG_OBJ_TX_NUM - 1)
+
+#define C_CAN_MSG_OBJ_RX_SPLIT	9
+#define C_CAN_MSG_RX_LOW_LAST	(C_CAN_MSG_OBJ_RX_SPLIT - 1)
+
+#define C_CAN_NEXT_MSG_OBJ_MASK	(C_CAN_MSG_OBJ_TX_NUM - 1)
+#define RECEIVE_OBJECT_BITS	0x0000ffff
+
+/* status interrupt */
+#define STATUS_INTERRUPT	0x8000
+
+/* global interrupt masks */
+#define ENABLE_ALL_INTERRUPTS	1
+#define DISABLE_ALL_INTERRUPTS	0
+
+/* minimum timeout for checking BUSY status */
+#define MIN_TIMEOUT_VALUE	6
+
+/* napi related */
+#define C_CAN_NAPI_WEIGHT	C_CAN_MSG_OBJ_RX_NUM
+
+/* c_can lec values */
+enum c_can_lec_type {
+	LEC_NO_ERROR = 0,
+	LEC_STUFF_ERROR,
+	LEC_FORM_ERROR,
+	LEC_ACK_ERROR,
+	LEC_BIT1_ERROR,
+	LEC_BIT0_ERROR,
+	LEC_CRC_ERROR,
+	LEC_UNUSED,
+};
+
+/*
+ * c_can error types:
+ * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
+ */
+enum c_can_bus_error_types {
+	C_CAN_NO_ERROR = 0,
+	C_CAN_BUS_OFF,
+	C_CAN_ERROR_WARNING,
+	C_CAN_ERROR_PASSIVE,
+};
+
+static struct can_bittiming_const c_can_bittiming_const = {
+	.name = KBUILD_MODNAME,
+	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
+	.tseg1_max = 16,
+	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 1024,	/* 6-bit BRP field + 4-bit BRPE field*/
+	.brp_inc = 1,
+};
+
+static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
+{
+	return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
+			C_CAN_MSG_OBJ_TX_FIRST;
+}
+
+static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv)
+{
+	return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) +
+			C_CAN_MSG_OBJ_TX_FIRST;
+}
+
+static u32 c_can_read_reg32(struct c_can_priv *priv, void *reg)
+{
+	u32 val = priv->read_reg(priv, reg);
+	val |= ((u32) priv->read_reg(priv, reg + 2)) << 16;
+	return val;
+}
+
+static void c_can_enable_all_interrupts(struct c_can_priv *priv,
+						int enable)
+{
+	unsigned int cntrl_save = priv->read_reg(priv,
+						&priv->regs->control);
+
+	if (enable)
+		cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE);
+	else
+		cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE);
+
+	priv->write_reg(priv, &priv->regs->control, cntrl_save);
+}
+
+static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
+{
+	int count = MIN_TIMEOUT_VALUE;
+
+	while (count && priv->read_reg(priv,
+				&priv->regs->ifregs[iface].com_req) &
+				IF_COMR_BUSY) {
+		count--;
+		udelay(1);
+	}
+
+	if (!count)
+		return 1;
+
+	return 0;
+}
+
+static inline void c_can_object_get(struct net_device *dev,
+					int iface, int objno, int mask)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/*
+	 * As per specs, after writting the message object number in the
+	 * IF command request register the transfer b/w interface
+	 * register and message RAM must be complete in 6 CAN-CLK
+	 * period.
+	 */
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_mask,
+			IFX_WRITE_LOW_16BIT(mask));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_req,
+			IFX_WRITE_LOW_16BIT(objno));
+
+	if (c_can_msg_obj_is_busy(priv, iface))
+		netdev_err(dev, "timed out in object get\n");
+}
+
+static inline void c_can_object_put(struct net_device *dev,
+					int iface, int objno, int mask)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/*
+	 * As per specs, after writting the message object number in the
+	 * IF command request register the transfer b/w interface
+	 * register and message RAM must be complete in 6 CAN-CLK
+	 * period.
+	 */
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_mask,
+			(IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask)));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_req,
+			IFX_WRITE_LOW_16BIT(objno));
+
+	if (c_can_msg_obj_is_busy(priv, iface))
+		netdev_err(dev, "timed out in object put\n");
+}
+
+static void c_can_write_msg_object(struct net_device *dev,
+			int iface, struct can_frame *frame, int objno)
+{
+	int i;
+	u16 flags = 0;
+	unsigned int id;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	if (!(frame->can_id & CAN_RTR_FLAG))
+		flags |= IF_ARB_TRANSMIT;
+
+	if (frame->can_id & CAN_EFF_FLAG) {
+		id = frame->can_id & CAN_EFF_MASK;
+		flags |= IF_ARB_MSGXTD;
+	} else
+		id = ((frame->can_id & CAN_SFF_MASK) << 18);
+
+	flags |= IF_ARB_MSGVAL;
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
+				IFX_WRITE_LOW_16BIT(id));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, flags |
+				IFX_WRITE_HIGH_16BIT(id));
+
+	for (i = 0; i < frame->can_dlc; i += 2) {
+		priv->write_reg(priv, &priv->regs->ifregs[iface].data[i / 2],
+				frame->data[i] | (frame->data[i + 1] << 8));
+	}
+
+	/* enable interrupt for this message object */
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB |
+			frame->can_dlc);
+	c_can_object_put(dev, iface, objno, IF_COMM_ALL);
+}
+
+static inline void c_can_mark_rx_msg_obj(struct net_device *dev,
+						int iface, int ctrl_mask,
+						int obj)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			ctrl_mask & ~(IF_MCONT_MSGLST | IF_MCONT_INTPND));
+	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
+
+}
+
+static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
+						int iface,
+						int ctrl_mask)
+{
+	int i;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) {
+		priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+				ctrl_mask & ~(IF_MCONT_MSGLST |
+					IF_MCONT_INTPND | IF_MCONT_NEWDAT));
+		c_can_object_put(dev, iface, i, IF_COMM_CONTROL);
+	}
+}
+
+static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
+						int iface, int ctrl_mask,
+						int obj)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			ctrl_mask & ~(IF_MCONT_MSGLST |
+				IF_MCONT_INTPND | IF_MCONT_NEWDAT));
+	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
+}
+
+static void c_can_handle_lost_msg_obj(struct net_device *dev,
+					int iface, int objno)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	netdev_err(dev, "msg lost in buffer %d\n", objno);
+
+	c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			IF_MCONT_CLR_MSGLST);
+
+	c_can_object_put(dev, 0, objno, IF_COMM_CONTROL);
+
+	/* create an error msg */
+	skb = alloc_can_err_skb(dev, &frame);
+	if (unlikely(!skb))
+		return;
+
+	frame->can_id |= CAN_ERR_CRTL;
+	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+	stats->rx_errors++;
+	stats->rx_over_errors++;
+
+	netif_receive_skb(skb);
+}
+
+static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
+{
+	u16 flags, data;
+	int i;
+	unsigned int val;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	skb = alloc_can_skb(dev, &frame);
+	if (!skb) {
+		stats->rx_dropped++;
+		return -ENOMEM;
+	}
+
+	frame->can_dlc = get_can_dlc(ctrl & 0x0F);
+
+	flags =	priv->read_reg(priv, &priv->regs->ifregs[iface].arb2);
+	val = priv->read_reg(priv, &priv->regs->ifregs[iface].arb1) |
+		(flags << 16);
+
+	if (flags & IF_ARB_MSGXTD)
+		frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		frame->can_id = (val >> 18) & CAN_SFF_MASK;
+
+	if (flags & IF_ARB_TRANSMIT)
+		frame->can_id |= CAN_RTR_FLAG;
+	else {
+		for (i = 0; i < frame->can_dlc; i += 2) {
+			data = priv->read_reg(priv,
+				&priv->regs->ifregs[iface].data[i / 2]);
+			frame->data[i] = data;
+			frame->data[i + 1] = data >> 8;
+		}
+	}
+
+	netif_receive_skb(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += frame->can_dlc;
+
+	return 0;
+}
+
+static void c_can_setup_receive_object(struct net_device *dev, int iface,
+					int objno, unsigned int mask,
+					unsigned int id, unsigned int mcont)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].mask1,
+			IFX_WRITE_LOW_16BIT(mask));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].mask2,
+			IFX_WRITE_HIGH_16BIT(mask));
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
+			IFX_WRITE_LOW_16BIT(id));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2,
+			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, mcont);
+	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
+
+	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
+			c_can_read_reg32(priv, &priv->regs->msgval1));
+}
+
+static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1, 0);
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, 0);
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, 0);
+
+	c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL);
+
+	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
+			c_can_read_reg32(priv, &priv->regs->msgval1));
+}
+
+static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno)
+{
+	int val = c_can_read_reg32(priv, &priv->regs->txrqst1);
+
+	/*
+	 * as transmission request register's bit n-1 corresponds to
+	 * message object n, we need to handle the same properly.
+	 */
+	if (val & (1 << (objno - 1)))
+		return 1;
+
+	return 0;
+}
+
+static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
+					struct net_device *dev)
+{
+	u32 msg_obj_no;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct can_frame *frame = (struct can_frame *)skb->data;
+
+	if (can_dropped_invalid_skb(dev, skb))
+		return NETDEV_TX_OK;
+
+	msg_obj_no = get_tx_next_msg_obj(priv);
+
+	/* prepare message object for transmission */
+	c_can_write_msg_object(dev, 0, frame, msg_obj_no);
+	can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+
+	/*
+	 * we have to stop the queue in case of a wrap around or
+	 * if the next TX message object is still in use
+	 */
+	priv->tx_next++;
+	if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) ||
+			(priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
+		netif_stop_queue(dev);
+
+	return NETDEV_TX_OK;
+}
+
+static int c_can_set_bittiming(struct net_device *dev)
+{
+	unsigned int reg_btr, reg_brpe, ctrl_save;
+	u8 brp, brpe, sjw, tseg1, tseg2;
+	u32 ten_bit_brp;
+	struct c_can_priv *priv = netdev_priv(dev);
+	const struct can_bittiming *bt = &priv->can.bittiming;
+
+	/* c_can provides a 6-bit brp and 4-bit brpe fields */
+	ten_bit_brp = bt->brp - 1;
+	brp = ten_bit_brp & BTR_BRP_MASK;
+	brpe = ten_bit_brp >> 6;
+
+	sjw = bt->sjw - 1;
+	tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
+	tseg2 = bt->phase_seg2 - 1;
+	reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) |
+			(tseg2 << BTR_TSEG2_SHIFT);
+	reg_brpe = brpe & BRP_EXT_BRPE_MASK;
+
+	netdev_info(dev,
+		"setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);
+
+	ctrl_save = priv->read_reg(priv, &priv->regs->control);
+	priv->write_reg(priv, &priv->regs->control,
+			ctrl_save | CONTROL_CCE | CONTROL_INIT);
+	priv->write_reg(priv, &priv->regs->btr, reg_btr);
+	priv->write_reg(priv, &priv->regs->brp_ext, reg_brpe);
+	priv->write_reg(priv, &priv->regs->control, ctrl_save);
+
+	return 0;
+}
+
+/*
+ * Configure C_CAN message objects for Tx and Rx purposes:
+ * C_CAN provides a total of 32 message objects that can be configured
+ * either for Tx or Rx purposes. Here the first 16 message objects are used as
+ * a reception FIFO. The end of reception FIFO is signified by the EoB bit
+ * being SET. The remaining 16 message objects are kept aside for Tx purposes.
+ * See user guide document for further details on configuring message
+ * objects.
+ */
+static void c_can_configure_msg_objects(struct net_device *dev)
+{
+	int i;
+
+	/* first invalidate all message objects */
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++)
+		c_can_inval_msg_object(dev, 0, i);
+
+	/* setup receive message objects */
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
+		c_can_setup_receive_object(dev, 0, i, 0, 0,
+			(IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB);
+
+	c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
+			IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
+}
+
+/*
+ * Configure C_CAN chip:
+ * - enable/disable auto-retransmission
+ * - set operating mode
+ * - configure message objects
+ */
+static void c_can_chip_config(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+		/* disable automatic retransmission */
+		priv->write_reg(priv, &priv->regs->control,
+				CONTROL_DISABLE_AR);
+	else
+		/* enable automatic retransmission */
+		priv->write_reg(priv, &priv->regs->control,
+				CONTROL_ENABLE_AR);
+
+	if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
+					CAN_CTRLMODE_LOOPBACK)) {
+		/* loopback + silent mode : useful for hot self-test */
+		priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
+				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, &priv->regs->test,
+				TEST_LBACK | TEST_SILENT);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+		/* loopback mode : useful for self-test function */
+		priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
+				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, &priv->regs->test, TEST_LBACK);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+		/* silent mode : bus-monitoring mode */
+		priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
+				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, &priv->regs->test, TEST_SILENT);
+	} else
+		/* normal mode*/
+		priv->write_reg(priv, &priv->regs->control,
+				CONTROL_EIE | CONTROL_SIE | CONTROL_IE);
+
+	/* configure message objects */
+	c_can_configure_msg_objects(dev);
+
+	/* set a `lec` value so that we can check for updates later */
+	priv->write_reg(priv, &priv->regs->status, LEC_UNUSED);
+
+	/* set bittiming params */
+	c_can_set_bittiming(dev);
+}
+
+static void c_can_start(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* basic c_can configuration */
+	c_can_chip_config(dev);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	/* reset tx helper pointers */
+	priv->tx_next = priv->tx_echo = 0;
+
+	/* enable status change, error and module interrupts */
+	c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+}
+
+static void c_can_stop(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* disable all interrupts */
+	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+
+	/* set the state as STOPPED */
+	priv->can.state = CAN_STATE_STOPPED;
+}
+
+static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	switch (mode) {
+	case CAN_MODE_START:
+		c_can_start(dev);
+		netif_wake_queue(dev);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int c_can_get_berr_counter(const struct net_device *dev,
+					struct can_berr_counter *bec)
+{
+	unsigned int reg_err_counter;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	reg_err_counter = priv->read_reg(priv, &priv->regs->err_cnt);
+	bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
+				ERR_CNT_REC_SHIFT;
+	bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
+
+	return 0;
+}
+
+/*
+ * theory of operation:
+ *
+ * priv->tx_echo holds the number of the oldest can_frame put for
+ * transmission into the hardware, but not yet ACKed by the CAN tx
+ * complete IRQ.
+ *
+ * We iterate from priv->tx_echo to priv->tx_next and check if the
+ * packet has been transmitted, echo it back to the CAN framework.
+ * If we discover a not yet transmitted package, stop looking for more.
+ */
+static void c_can_do_tx(struct net_device *dev)
+{
+	u32 val;
+	u32 msg_obj_no;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+
+	for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
+		msg_obj_no = get_tx_echo_msg_obj(priv);
+		c_can_inval_msg_object(dev, 0, msg_obj_no);
+		val = c_can_read_reg32(priv, &priv->regs->txrqst1);
+		if (!(val & (1 << msg_obj_no))) {
+			can_get_echo_skb(dev,
+					msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+			stats->tx_bytes += priv->read_reg(priv,
+					&priv->regs->ifregs[0].msg_cntrl)
+					& IF_MCONT_DLC_MASK;
+			stats->tx_packets++;
+		}
+	}
+
+	/* restart queue if wrap-up or if queue stalled on last pkt */
+	if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
+			((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
+		netif_wake_queue(dev);
+}
+
+/*
+ * theory of operation:
+ *
+ * c_can core saves a received CAN message into the first free message
+ * object it finds free (starting with the lowest). Bits NEWDAT and
+ * INTPND are set for this message object indicating that a new message
+ * has arrived. To work-around this issue, we keep two groups of message
+ * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
+ *
+ * To ensure in-order frame reception we use the following
+ * approach while re-activating a message object to receive further
+ * frames:
+ * - if the current message object number is lower than
+ *   C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing
+ *   the INTPND bit.
+ * - if the current message object number is equal to
+ *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower
+ *   receive message objects.
+ * - if the current message object number is greater than
+ *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
+ *   only this message object.
+ */
+static int c_can_do_rx_poll(struct net_device *dev, int quota)
+{
+	u32 num_rx_pkts = 0;
+	unsigned int msg_obj, msg_ctrl_save;
+	struct c_can_priv *priv = netdev_priv(dev);
+	u32 val = c_can_read_reg32(priv, &priv->regs->intpnd1);
+
+	for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST;
+			msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0;
+			val = c_can_read_reg32(priv, &priv->regs->intpnd1),
+			msg_obj++) {
+		/*
+		 * as interrupt pending register's bit n-1 corresponds to
+		 * message object n, we need to handle the same properly.
+		 */
+		if (val & (1 << (msg_obj - 1))) {
+			c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL &
+					~IF_COMM_TXRQST);
+			msg_ctrl_save = priv->read_reg(priv,
+					&priv->regs->ifregs[0].msg_cntrl);
+
+			if (msg_ctrl_save & IF_MCONT_EOB)
+				return num_rx_pkts;
+
+			if (msg_ctrl_save & IF_MCONT_MSGLST) {
+				c_can_handle_lost_msg_obj(dev, 0, msg_obj);
+				num_rx_pkts++;
+				quota--;
+				continue;
+			}
+
+			if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
+				continue;
+
+			/* read the data from the message object */
+			c_can_read_msg_object(dev, 0, msg_ctrl_save);
+
+			if (msg_obj < C_CAN_MSG_RX_LOW_LAST)
+				c_can_mark_rx_msg_obj(dev, 0,
+						msg_ctrl_save, msg_obj);
+			else if (msg_obj > C_CAN_MSG_RX_LOW_LAST)
+				/* activate this msg obj */
+				c_can_activate_rx_msg_obj(dev, 0,
+						msg_ctrl_save, msg_obj);
+			else if (msg_obj == C_CAN_MSG_RX_LOW_LAST)
+				/* activate all lower message objects */
+				c_can_activate_all_lower_rx_msg_obj(dev,
+						0, msg_ctrl_save);
+
+			num_rx_pkts++;
+			quota--;
+		}
+	}
+
+	return num_rx_pkts;
+}
+
+static inline int c_can_has_and_handle_berr(struct c_can_priv *priv)
+{
+	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
+		(priv->current_status & LEC_UNUSED);
+}
+
+static int c_can_handle_state_change(struct net_device *dev,
+				enum c_can_bus_error_types error_type)
+{
+	unsigned int reg_err_counter;
+	unsigned int rx_err_passive;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct can_berr_counter bec;
+
+	/* propogate the error condition to the CAN stack */
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return 0;
+
+	c_can_get_berr_counter(dev, &bec);
+	reg_err_counter = priv->read_reg(priv, &priv->regs->err_cnt);
+	rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
+				ERR_CNT_RP_SHIFT;
+
+	switch (error_type) {
+	case C_CAN_ERROR_WARNING:
+		/* error warning state */
+		priv->can.can_stats.error_warning++;
+		priv->can.state = CAN_STATE_ERROR_WARNING;
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = (bec.txerr > bec.rxerr) ?
+			CAN_ERR_CRTL_TX_WARNING :
+			CAN_ERR_CRTL_RX_WARNING;
+		cf->data[6] = bec.txerr;
+		cf->data[7] = bec.rxerr;
+
+		break;
+	case C_CAN_ERROR_PASSIVE:
+		/* error passive state */
+		priv->can.can_stats.error_passive++;
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+		cf->can_id |= CAN_ERR_CRTL;
+		if (rx_err_passive)
+			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+		if (bec.txerr > 127)
+			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+
+		cf->data[6] = bec.txerr;
+		cf->data[7] = bec.rxerr;
+		break;
+	case C_CAN_BUS_OFF:
+		/* bus-off state */
+		priv->can.state = CAN_STATE_BUS_OFF;
+		cf->can_id |= CAN_ERR_BUSOFF;
+		/*
+		 * disable all interrupts in bus-off mode to ensure that
+		 * the CPU is not hogged down
+		 */
+		c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+		can_bus_off(dev);
+		break;
+	default:
+		break;
+	}
+
+	netif_receive_skb(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 1;
+}
+
+static int c_can_handle_bus_err(struct net_device *dev,
+				enum c_can_lec_type lec_type)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+
+	/*
+	 * early exit if no lec update or no error.
+	 * no lec update means that no CAN bus event has been detected
+	 * since CPU wrote 0x7 value to status reg.
+	 */
+	if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)
+		return 0;
+
+	/* propogate the error condition to the CAN stack */
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return 0;
+
+	/*
+	 * check for 'last error code' which tells us the
+	 * type of the last error to occur on the CAN bus
+	 */
+
+	/* common for all type of bus errors */
+	priv->can.can_stats.bus_error++;
+	stats->rx_errors++;
+	cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+	cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+
+	switch (lec_type) {
+	case LEC_STUFF_ERROR:
+		netdev_dbg(dev, "stuff error\n");
+		cf->data[2] |= CAN_ERR_PROT_STUFF;
+		break;
+	case LEC_FORM_ERROR:
+		netdev_dbg(dev, "form error\n");
+		cf->data[2] |= CAN_ERR_PROT_FORM;
+		break;
+	case LEC_ACK_ERROR:
+		netdev_dbg(dev, "ack error\n");
+		cf->data[2] |= (CAN_ERR_PROT_LOC_ACK |
+				CAN_ERR_PROT_LOC_ACK_DEL);
+		break;
+	case LEC_BIT1_ERROR:
+		netdev_dbg(dev, "bit1 error\n");
+		cf->data[2] |= CAN_ERR_PROT_BIT1;
+		break;
+	case LEC_BIT0_ERROR:
+		netdev_dbg(dev, "bit0 error\n");
+		cf->data[2] |= CAN_ERR_PROT_BIT0;
+		break;
+	case LEC_CRC_ERROR:
+		netdev_dbg(dev, "CRC error\n");
+		cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+				CAN_ERR_PROT_LOC_CRC_DEL);
+		break;
+	default:
+		break;
+	}
+
+	/* set a `lec` value so that we can check for updates later */
+	priv->write_reg(priv, &priv->regs->status, LEC_UNUSED);
+
+	netif_receive_skb(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 1;
+}
+
+static int c_can_poll(struct napi_struct *napi, int quota)
+{
+	u16 irqstatus;
+	int lec_type = 0;
+	int work_done = 0;
+	struct net_device *dev = napi->dev;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+	if (!irqstatus)
+		goto end;
+
+	/* status events have the highest priority */
+	if (irqstatus == STATUS_INTERRUPT) {
+		priv->current_status = priv->read_reg(priv,
+					&priv->regs->status);
+
+		/* handle Tx/Rx events */
+		if (priv->current_status & STATUS_TXOK)
+			priv->write_reg(priv, &priv->regs->status,
+					priv->current_status & ~STATUS_TXOK);
+
+		if (priv->current_status & STATUS_RXOK)
+			priv->write_reg(priv, &priv->regs->status,
+					priv->current_status & ~STATUS_RXOK);
+
+		/* handle state changes */
+		if ((priv->current_status & STATUS_EWARN) &&
+				(!(priv->last_status & STATUS_EWARN))) {
+			netdev_dbg(dev, "entered error warning state\n");
+			work_done += c_can_handle_state_change(dev,
+						C_CAN_ERROR_WARNING);
+		}
+		if ((priv->current_status & STATUS_EPASS) &&
+				(!(priv->last_status & STATUS_EPASS))) {
+			netdev_dbg(dev, "entered error passive state\n");
+			work_done += c_can_handle_state_change(dev,
+						C_CAN_ERROR_PASSIVE);
+		}
+		if ((priv->current_status & STATUS_BOFF) &&
+				(!(priv->last_status & STATUS_BOFF))) {
+			netdev_dbg(dev, "entered bus off state\n");
+			work_done += c_can_handle_state_change(dev,
+						C_CAN_BUS_OFF);
+		}
+
+		/* handle bus recovery events */
+		if ((!(priv->current_status & STATUS_BOFF)) &&
+				(priv->last_status & STATUS_BOFF)) {
+			netdev_dbg(dev, "left bus off state\n");
+			priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		}
+		if ((!(priv->current_status & STATUS_EPASS)) &&
+				(priv->last_status & STATUS_EPASS)) {
+			netdev_dbg(dev, "left error passive state\n");
+			priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		}
+
+		priv->last_status = priv->current_status;
+
+		/* handle lec errors on the bus */
+		lec_type = c_can_has_and_handle_berr(priv);
+		if (lec_type)
+			work_done += c_can_handle_bus_err(dev, lec_type);
+	} else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) &&
+			(irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) {
+		/* handle events corresponding to receive message objects */
+		work_done += c_can_do_rx_poll(dev, (quota - work_done));
+	} else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) &&
+			(irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) {
+		/* handle events corresponding to transmit message objects */
+		c_can_do_tx(dev);
+	}
+
+end:
+	if (work_done < quota) {
+		napi_complete(napi);
+		/* enable all IRQs */
+		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+	}
+
+	return work_done;
+}
+
+static irqreturn_t c_can_isr(int irq, void *dev_id)
+{
+	u16 irqstatus;
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+	if (!irqstatus)
+		return IRQ_NONE;
+
+	/* disable all interrupts and schedule the NAPI */
+	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+	napi_schedule(&priv->napi);
+
+	return IRQ_HANDLED;
+}
+
+static int c_can_open(struct net_device *dev)
+{
+	int err;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* open the can device */
+	err = open_candev(dev);
+	if (err) {
+		netdev_err(dev, "failed to open can device\n");
+		return err;
+	}
+
+	/* register interrupt handler */
+	err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name,
+				dev);
+	if (err < 0) {
+		netdev_err(dev, "failed to request interrupt\n");
+		goto exit_irq_fail;
+	}
+
+	/* start the c_can controller */
+	c_can_start(dev);
+
+	napi_enable(&priv->napi);
+	netif_start_queue(dev);
+
+	return 0;
+
+exit_irq_fail:
+	close_candev(dev);
+	return err;
+}
+
+static int c_can_close(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	napi_disable(&priv->napi);
+	c_can_stop(dev);
+	free_irq(dev->irq, dev);
+	close_candev(dev);
+
+	return 0;
+}
+
+struct net_device *alloc_c_can_dev(void)
+{
+	struct net_device *dev;
+	struct c_can_priv *priv;
+
+	dev = alloc_candev(sizeof(struct c_can_priv), C_CAN_MSG_OBJ_TX_NUM);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+	netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
+
+	priv->dev = dev;
+	priv->can.bittiming_const = &c_can_bittiming_const;
+	priv->can.do_set_mode = c_can_set_mode;
+	priv->can.do_get_berr_counter = c_can_get_berr_counter;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT |
+					CAN_CTRLMODE_LOOPBACK |
+					CAN_CTRLMODE_LISTENONLY |
+					CAN_CTRLMODE_BERR_REPORTING;
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_c_can_dev);
+
+void free_c_can_dev(struct net_device *dev)
+{
+	free_candev(dev);
+}
+EXPORT_SYMBOL_GPL(free_c_can_dev);
+
+static const struct net_device_ops c_can_netdev_ops = {
+	.ndo_open = c_can_open,
+	.ndo_stop = c_can_close,
+	.ndo_start_xmit = c_can_start_xmit,
+};
+
+int register_c_can_dev(struct net_device *dev)
+{
+	dev->flags |= IFF_ECHO;	/* we support local echo */
+	dev->netdev_ops = &c_can_netdev_ops;
+
+	return register_candev(dev);
+}
+EXPORT_SYMBOL_GPL(register_c_can_dev);
+
+void unregister_c_can_dev(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* disable all interrupts */
+	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+
+	unregister_candev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_c_can_dev);
+
+MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CAN bus driver for Bosch C_CAN controller");
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
new file mode 100644
index 0000000..9b7fbef
--- /dev/null
+++ b/drivers/net/can/c_can/c_can.h
@@ -0,0 +1,86 @@
+/*
+ * CAN bus driver for Bosch C_CAN controller
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma@st.com>
+ *
+ * Borrowed heavily from the C_CAN driver originally written by:
+ * Copyright (C) 2007
+ * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
+ * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
+ *
+ * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
+ * Bosch C_CAN user manual can be obtained from:
+ * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
+ * users_manual_c_can.pdf
+ *
+ * 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 C_CAN_H
+#define C_CAN_H
+
+/* c_can IF registers */
+struct c_can_if_regs {
+	u16 com_req;
+	u16 com_mask;
+	u16 mask1;
+	u16 mask2;
+	u16 arb1;
+	u16 arb2;
+	u16 msg_cntrl;
+	u16 data[4];
+	u16 _reserved[13];
+};
+
+/* c_can hardware registers */
+struct c_can_regs {
+	u16 control;
+	u16 status;
+	u16 err_cnt;
+	u16 btr;
+	u16 interrupt;
+	u16 test;
+	u16 brp_ext;
+	u16 _reserved1;
+	struct c_can_if_regs ifregs[2]; /* [0] = IF1 and [1] = IF2 */
+	u16 _reserved2[8];
+	u16 txrqst1;
+	u16 txrqst2;
+	u16 _reserved3[6];
+	u16 newdat1;
+	u16 newdat2;
+	u16 _reserved4[6];
+	u16 intpnd1;
+	u16 intpnd2;
+	u16 _reserved5[6];
+	u16 msgval1;
+	u16 msgval2;
+	u16 _reserved6[6];
+};
+
+/* c_can private data structure */
+struct c_can_priv {
+	struct can_priv can;	/* must be the first member */
+	struct napi_struct napi;
+	struct net_device *dev;
+	int tx_object;
+	int current_status;
+	int last_status;
+	u16 (*read_reg) (struct c_can_priv *priv, void *reg);
+	void (*write_reg) (struct c_can_priv *priv, void *reg, u16 val);
+	struct c_can_regs __iomem *regs;
+	unsigned long irq_flags; /* for request_irq() */
+	unsigned int tx_next;
+	unsigned int tx_echo;
+	void *priv;		/* for board-specific data */
+};
+
+struct net_device *alloc_c_can_dev(void);
+void free_c_can_dev(struct net_device *dev);
+int register_c_can_dev(struct net_device *dev);
+void unregister_c_can_dev(struct net_device *dev);
+
+#endif /* C_CAN_H */
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
new file mode 100644
index 0000000..e629b96
--- /dev/null
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -0,0 +1,215 @@
+/*
+ * Platform CAN bus driver for Bosch C_CAN controller
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma@st.com>
+ *
+ * Borrowed heavily from the C_CAN driver originally written by:
+ * Copyright (C) 2007
+ * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
+ * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
+ *
+ * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
+ * Bosch C_CAN user manual can be obtained from:
+ * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
+ * users_manual_c_can.pdf
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <linux/can/dev.h>
+
+#include "c_can.h"
+
+/*
+ * 16-bit c_can registers can be arranged differently in the memory
+ * architecture of different implementations. For example: 16-bit
+ * registers can be aligned to a 16-bit boundary or 32-bit boundary etc.
+ * Handle the same by providing a common read/write interface.
+ */
+static u16 c_can_plat_read_reg_aligned_to_16bit(struct c_can_priv *priv,
+						void *reg)
+{
+	return readw(reg);
+}
+
+static void c_can_plat_write_reg_aligned_to_16bit(struct c_can_priv *priv,
+						void *reg, u16 val)
+{
+	writew(val, reg);
+}
+
+static u16 c_can_plat_read_reg_aligned_to_32bit(struct c_can_priv *priv,
+						void *reg)
+{
+	return readw(reg + (long)reg - (long)priv->regs);
+}
+
+static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
+						void *reg, u16 val)
+{
+	writew(val, reg + (long)reg - (long)priv->regs);
+}
+
+static int __devinit c_can_plat_probe(struct platform_device *pdev)
+{
+	int ret;
+	void __iomem *addr;
+	struct net_device *dev;
+	struct c_can_priv *priv;
+	struct resource *mem, *irq;
+#ifdef CONFIG_HAVE_CLK
+	struct clk *clk;
+
+	/* get the appropriate clk */
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "no clock defined\n");
+		ret = -ENODEV;
+		goto exit;
+	}
+#endif
+
+	/* get the platform data */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mem || (irq <= 0)) {
+		ret = -ENODEV;
+		goto exit_free_clk;
+	}
+
+	if (!request_mem_region(mem->start, resource_size(mem),
+				KBUILD_MODNAME)) {
+		dev_err(&pdev->dev, "resource unavailable\n");
+		ret = -ENODEV;
+		goto exit_free_clk;
+	}
+
+	addr = ioremap(mem->start, resource_size(mem));
+	if (!addr) {
+		dev_err(&pdev->dev, "failed to map can port\n");
+		ret = -ENOMEM;
+		goto exit_release_mem;
+	}
+
+	/* allocate the c_can device */
+	dev = alloc_c_can_dev();
+	if (!dev) {
+		ret = -ENOMEM;
+		goto exit_iounmap;
+	}
+
+	priv = netdev_priv(dev);
+
+	dev->irq = irq->start;
+	priv->regs = addr;
+#ifdef CONFIG_HAVE_CLK
+	priv->can.clock.freq = clk_get_rate(clk);
+	priv->priv = clk;
+#endif
+
+	switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
+	case IORESOURCE_MEM_32BIT:
+		priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
+		priv->write_reg = c_can_plat_write_reg_aligned_to_32bit;
+		break;
+	case IORESOURCE_MEM_16BIT:
+	default:
+		priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
+		priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+		break;
+	}
+
+	platform_set_drvdata(pdev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	ret = register_c_can_dev(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
+			KBUILD_MODNAME, ret);
+		goto exit_free_device;
+	}
+
+	dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
+		 KBUILD_MODNAME, priv->regs, dev->irq);
+	return 0;
+
+exit_free_device:
+	platform_set_drvdata(pdev, NULL);
+	free_c_can_dev(dev);
+exit_iounmap:
+	iounmap(addr);
+exit_release_mem:
+	release_mem_region(mem->start, resource_size(mem));
+exit_free_clk:
+#ifdef CONFIG_HAVE_CLK
+	clk_put(clk);
+exit:
+#endif
+	dev_err(&pdev->dev, "probe failed\n");
+
+	return ret;
+}
+
+static int __devexit c_can_plat_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct resource *mem;
+
+	unregister_c_can_dev(dev);
+	platform_set_drvdata(pdev, NULL);
+
+	free_c_can_dev(dev);
+	iounmap(priv->regs);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+#ifdef CONFIG_HAVE_CLK
+	clk_put(priv->priv);
+#endif
+
+	return 0;
+}
+
+static struct platform_driver c_can_plat_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = c_can_plat_probe,
+	.remove = __devexit_p(c_can_plat_remove),
+};
+
+static int __init c_can_plat_init(void)
+{
+	return platform_driver_register(&c_can_plat_driver);
+}
+module_init(c_can_plat_init);
+
+static void __exit c_can_plat_exit(void)
+{
+	platform_driver_unregister(&c_can_plat_driver);
+}
+module_exit(c_can_plat_exit);
+
+MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Platform CAN bus driver for Bosch C_CAN controller");
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index 312b9c8..c0a1bc5 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -247,10 +247,9 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
 }
 #endif /* CONFIG_PPC_MPC512x */
 
-static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev,
-				       const struct of_device_id *id)
+static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
 {
-	struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
+	struct mpc5xxx_can_data *data;
 	struct device_node *np = ofdev->dev.of_node;
 	struct net_device *dev;
 	struct mscan_priv *priv;
@@ -259,6 +258,10 @@ static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev,
 	int irq, mscan_clksrc = 0;
 	int err = -ENOMEM;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+	data = (struct mpc5xxx_can_data *)of_dev->dev.of_match->data;
+
 	base = of_iomap(np, 0);
 	if (!base) {
 		dev_err(&ofdev->dev, "couldn't ioremap\n");
@@ -391,7 +394,7 @@ static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
 	{},
 };
 
-static struct of_platform_driver mpc5xxx_can_driver = {
+static struct platform_driver mpc5xxx_can_driver = {
 	.driver = {
 		.name = "mpc5xxx_can",
 		.owner = THIS_MODULE,
@@ -407,13 +410,13 @@ static struct of_platform_driver mpc5xxx_can_driver = {
 
 static int __init mpc5xxx_can_init(void)
 {
-	return of_register_platform_driver(&mpc5xxx_can_driver);
+	return platform_driver_register(&mpc5xxx_can_driver);
 }
 module_init(mpc5xxx_can_init);
 
 static void __exit mpc5xxx_can_exit(void)
 {
-	return of_unregister_platform_driver(&mpc5xxx_can_driver);
+	platform_driver_unregister(&mpc5xxx_can_driver);
 };
 module_exit(mpc5xxx_can_exit);
 
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 09c3e9d..9793df6 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -87,8 +87,7 @@ static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
 	return 0;
 }
 
-static int __devinit sja1000_ofp_probe(struct platform_device *ofdev,
-				       const struct of_device_id *id)
+static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct net_device *dev;
@@ -210,7 +209,7 @@ static struct of_device_id __devinitdata sja1000_ofp_table[] = {
 };
 MODULE_DEVICE_TABLE(of, sja1000_ofp_table);
 
-static struct of_platform_driver sja1000_ofp_driver = {
+static struct platform_driver sja1000_ofp_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = DRV_NAME,
@@ -222,12 +221,12 @@ static struct of_platform_driver sja1000_ofp_driver = {
 
 static int __init sja1000_ofp_init(void)
 {
-	return of_register_platform_driver(&sja1000_ofp_driver);
+	return platform_driver_register(&sja1000_ofp_driver);
 }
 module_init(sja1000_ofp_init);
 
 static void __exit sja1000_ofp_exit(void)
 {
-	return of_unregister_platform_driver(&sja1000_ofp_driver);
+	return platform_driver_unregister(&sja1000_ofp_driver);
 };
 module_exit(sja1000_ofp_exit);
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index 05a5275..dc53c83 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -659,7 +659,7 @@ failed:
 static void unlink_all_urbs(struct esd_usb2 *dev)
 {
 	struct esd_usb2_net_priv *priv;
-	int i;
+	int i, j;
 
 	usb_kill_anchored_urbs(&dev->rx_submitted);
 	for (i = 0; i < dev->net_count; i++) {
@@ -668,8 +668,8 @@ static void unlink_all_urbs(struct esd_usb2 *dev)
 			usb_kill_anchored_urbs(&priv->tx_submitted);
 			atomic_set(&priv->active_tx_jobs, 0);
 
-			for (i = 0; i < MAX_TX_URBS; i++)
-				priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+			for (j = 0; j < MAX_TX_URBS; j++)
+				priv->tx_contexts[j].echo_index = MAX_TX_URBS;
 		}
 	}
 }
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 302be4a..8cca60e 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -65,7 +65,14 @@ static LIST_HEAD(cnic_udev_list);
 static DEFINE_RWLOCK(cnic_dev_lock);
 static DEFINE_MUTEX(cnic_lock);
 
-static struct cnic_ulp_ops *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE];
+static struct cnic_ulp_ops __rcu *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE];
+
+/* helper function, assuming cnic_lock is held */
+static inline struct cnic_ulp_ops *cnic_ulp_tbl_prot(int type)
+{
+	return rcu_dereference_protected(cnic_ulp_tbl[type],
+					 lockdep_is_held(&cnic_lock));
+}
 
 static int cnic_service_bnx2(void *, void *);
 static int cnic_service_bnx2x(void *, void *);
@@ -435,7 +442,7 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
 		return -EINVAL;
 	}
 	mutex_lock(&cnic_lock);
-	if (cnic_ulp_tbl[ulp_type]) {
+	if (cnic_ulp_tbl_prot(ulp_type)) {
 		pr_err("%s: Type %d has already been registered\n",
 		       __func__, ulp_type);
 		mutex_unlock(&cnic_lock);
@@ -478,7 +485,7 @@ int cnic_unregister_driver(int ulp_type)
 		return -EINVAL;
 	}
 	mutex_lock(&cnic_lock);
-	ulp_ops = cnic_ulp_tbl[ulp_type];
+	ulp_ops = cnic_ulp_tbl_prot(ulp_type);
 	if (!ulp_ops) {
 		pr_err("%s: Type %d has not been registered\n",
 		       __func__, ulp_type);
@@ -529,7 +536,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type,
 		return -EINVAL;
 	}
 	mutex_lock(&cnic_lock);
-	if (cnic_ulp_tbl[ulp_type] == NULL) {
+	if (cnic_ulp_tbl_prot(ulp_type) == NULL) {
 		pr_err("%s: Driver with type %d has not been registered\n",
 		       __func__, ulp_type);
 		mutex_unlock(&cnic_lock);
@@ -544,7 +551,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type,
 
 	clear_bit(ULP_F_START, &cp->ulp_flags[ulp_type]);
 	cp->ulp_handle[ulp_type] = ulp_ctx;
-	ulp_ops = cnic_ulp_tbl[ulp_type];
+	ulp_ops = cnic_ulp_tbl_prot(ulp_type);
 	rcu_assign_pointer(cp->ulp_ops[ulp_type], ulp_ops);
 	cnic_hold(dev);
 
@@ -2970,7 +2977,8 @@ static void cnic_ulp_stop(struct cnic_dev *dev)
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cp->ulp_ops[if_type];
+		ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
+						    lockdep_is_held(&cnic_lock));
 		if (!ulp_ops) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -2994,7 +3002,8 @@ static void cnic_ulp_start(struct cnic_dev *dev)
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cp->ulp_ops[if_type];
+		ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
+						    lockdep_is_held(&cnic_lock));
 		if (!ulp_ops || !ulp_ops->cnic_start) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -3058,7 +3067,7 @@ static void cnic_ulp_init(struct cnic_dev *dev)
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cnic_ulp_tbl[i];
+		ulp_ops = cnic_ulp_tbl_prot(i);
 		if (!ulp_ops || !ulp_ops->cnic_init) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -3082,7 +3091,7 @@ static void cnic_ulp_exit(struct cnic_dev *dev)
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cnic_ulp_tbl[i];
+		ulp_ops = cnic_ulp_tbl_prot(i);
 		if (!ulp_ops || !ulp_ops->cnic_exit) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -3398,17 +3407,14 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
 			     struct dst_entry **dst)
 {
 #if defined(CONFIG_INET)
-	struct flowi fl;
-	int err;
 	struct rtable *rt;
 
-	memset(&fl, 0, sizeof(fl));
-	fl.nl_u.ip4_u.daddr = dst_addr->sin_addr.s_addr;
-
-	err = ip_route_output_key(&init_net, &rt, &fl);
-	if (!err)
+	rt = ip_route_output(&init_net, dst_addr->sin_addr.s_addr, 0, 0, 0);
+	if (!IS_ERR(rt)) {
 		*dst = &rt->dst;
-	return err;
+		return 0;
+	}
+	return PTR_ERR(rt);
 #else
 	return -ENETUNREACH;
 #endif
@@ -3418,14 +3424,14 @@ static int cnic_get_v6_route(struct sockaddr_in6 *dst_addr,
 			     struct dst_entry **dst)
 {
 #if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
-	struct flowi fl;
+	struct flowi6 fl6;
 
-	memset(&fl, 0, sizeof(fl));
-	ipv6_addr_copy(&fl.fl6_dst, &dst_addr->sin6_addr);
-	if (ipv6_addr_type(&fl.fl6_dst) & IPV6_ADDR_LINKLOCAL)
-		fl.oif = dst_addr->sin6_scope_id;
+	memset(&fl6, 0, sizeof(fl6));
+	ipv6_addr_copy(&fl6.daddr, &dst_addr->sin6_addr);
+	if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+		fl6.flowi6_oif = dst_addr->sin6_scope_id;
 
-	*dst = ip6_route_output(&init_net, NULL, &fl);
+	*dst = ip6_route_output(&init_net, NULL, &fl6);
 	if (*dst)
 		return 0;
 #endif
@@ -4187,6 +4193,14 @@ static void cnic_enable_bnx2_int(struct cnic_dev *dev)
 		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
 }
 
+static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev)
+{
+	u32 max_conn;
+
+	max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN);
+	dev->max_iscsi_conn = max_conn;
+}
+
 static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -4511,6 +4525,8 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 		return err;
 	}
 
+	cnic_get_bnx2_iscsi_info(dev);
+
 	return 0;
 }
 
@@ -4722,129 +4738,6 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 	cp->rx_cons = *cp->rx_cons_ptr;
 }
 
-static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr,
-				     u32 lower_addr)
-{
-	u32 val;
-	u8 mac[6];
-
-	val = CNIC_RD(dev, upper_addr);
-
-	mac[0] = (u8) (val >> 8);
-	mac[1] = (u8) val;
-
-	val = CNIC_RD(dev, lower_addr);
-
-	mac[2] = (u8) (val >> 24);
-	mac[3] = (u8) (val >> 16);
-	mac[4] = (u8) (val >> 8);
-	mac[5] = (u8) val;
-
-	if (is_valid_ether_addr(mac)) {
-		memcpy(dev->mac_addr, mac, 6);
-		return 0;
-	} else {
-		return -EINVAL;
-	}
-}
-
-static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 base, base2, addr, addr1, val;
-	int port = CNIC_PORT(cp);
-
-	dev->max_iscsi_conn = 0;
-	base = CNIC_RD(dev, MISC_REG_SHARED_MEM_ADDR);
-	if (base == 0)
-		return;
-
-	base2 = CNIC_RD(dev, (CNIC_PATH(cp) ? MISC_REG_GENERIC_CR_1 :
-					      MISC_REG_GENERIC_CR_0));
-	addr = BNX2X_SHMEM_ADDR(base,
-		dev_info.port_hw_config[port].iscsi_mac_upper);
-
-	addr1 = BNX2X_SHMEM_ADDR(base,
-		dev_info.port_hw_config[port].iscsi_mac_lower);
-
-	cnic_read_bnx2x_iscsi_mac(dev, addr, addr1);
-
-	addr = BNX2X_SHMEM_ADDR(base, validity_map[port]);
-	val = CNIC_RD(dev, addr);
-
-	if (!(val & SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT)) {
-		u16 val16;
-
-		addr = BNX2X_SHMEM_ADDR(base,
-				drv_lic_key[port].max_iscsi_init_conn);
-		val16 = CNIC_RD16(dev, addr);
-
-		if (val16)
-			val16 ^= 0x1e1e;
-		dev->max_iscsi_conn = val16;
-	}
-
-	if (BNX2X_CHIP_IS_E2(cp->chip_id))
-		dev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS;
-
-	if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) {
-		int func = CNIC_FUNC(cp);
-		u32 mf_cfg_addr;
-
-		if (BNX2X_SHMEM2_HAS(base2, mf_cfg_addr))
-			mf_cfg_addr = CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base2,
-					      mf_cfg_addr));
-		else
-			mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET;
-
-		if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
-			/* Must determine if the MF is SD vs SI mode */
-			addr = BNX2X_SHMEM_ADDR(base,
-					dev_info.shared_feature_config.config);
-			val = CNIC_RD(dev, addr);
-			if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) ==
-			    SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) {
-				int rc;
-
-				/* MULTI_FUNCTION_SI mode */
-				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-					func_ext_config[func].func_cfg);
-				val = CNIC_RD(dev, addr);
-				if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD))
-					dev->max_iscsi_conn = 0;
-
-				if (!(val & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD))
-					dev->max_fcoe_conn = 0;
-
-				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-					func_ext_config[func].
-					iscsi_mac_addr_upper);
-				addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-					func_ext_config[func].
-					iscsi_mac_addr_lower);
-				rc = cnic_read_bnx2x_iscsi_mac(dev, addr,
-								addr1);
-				if (rc && func > 1)
-					dev->max_iscsi_conn = 0;
-
-				return;
-			}
-		}
-
-		addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-			func_mf_config[func].e1hov_tag);
-
-		val = CNIC_RD(dev, addr);
-		val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
-		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-			dev->max_fcoe_conn = 0;
-			dev->max_iscsi_conn = 0;
-		}
-	}
-	if (!is_valid_ether_addr(dev->mac_addr))
-		dev->max_iscsi_conn = 0;
-}
-
 static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -4926,8 +4819,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 
 	cnic_init_bnx2x_kcq(dev);
 
-	cnic_get_bnx2x_iscsi_info(dev);
-
 	/* Only 1 EQ */
 	CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
@@ -5281,15 +5172,11 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
 
 	dev_hold(dev);
 	pci_dev_get(pdev);
-	if (pdev->device == PCI_DEVICE_ID_NX2_5709 ||
-	    pdev->device == PCI_DEVICE_ID_NX2_5709S) {
-		u8 rev;
-
-		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
-		if (rev < 0x10) {
-			pci_dev_put(pdev);
-			goto cnic_err;
-		}
+	if ((pdev->device == PCI_DEVICE_ID_NX2_5709 ||
+	     pdev->device == PCI_DEVICE_ID_NX2_5709S) &&
+	    (pdev->revision < 0x10)) {
+		pci_dev_put(pdev);
+		goto cnic_err;
 	}
 	pci_dev_put(pdev);
 
@@ -5360,6 +5247,14 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
 	cdev->pcidev = pdev;
 	cp->chip_id = ethdev->chip_id;
 
+	if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI))
+		cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
+	if (BNX2X_CHIP_IS_E2(cp->chip_id) &&
+	    !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
+		cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
+
+	memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6);
+
 	cp->cnic_ops = &cnic_bnx2x_ops;
 	cp->start_hw = cnic_start_bnx2x_hw;
 	cp->stop_hw = cnic_stop_bnx2x_hw;
diff --git a/drivers/net/cnic.h b/drivers/net/cnic.h
index b328f6c..4456260 100644
--- a/drivers/net/cnic.h
+++ b/drivers/net/cnic.h
@@ -220,7 +220,7 @@ struct cnic_local {
 #define ULP_F_INIT	0
 #define ULP_F_START	1
 #define ULP_F_CALL_PENDING	2
-	struct cnic_ulp_ops *ulp_ops[MAX_CNIC_ULP_TYPE];
+	struct cnic_ulp_ops __rcu *ulp_ops[MAX_CNIC_ULP_TYPE];
 
 	unsigned long cnic_local_flags;
 #define	CNIC_LCL_FL_KWQ_INIT		0x0
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h
index 9f44e0f..e01b49e 100644
--- a/drivers/net/cnic_if.h
+++ b/drivers/net/cnic_if.h
@@ -12,8 +12,8 @@
 #ifndef CNIC_IF_H
 #define CNIC_IF_H
 
-#define CNIC_MODULE_VERSION	"2.2.12"
-#define CNIC_MODULE_RELDATE	"Jan 03, 2011"
+#define CNIC_MODULE_VERSION	"2.2.13"
+#define CNIC_MODULE_RELDATE	"Jan 31, 2011"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
@@ -159,6 +159,9 @@ struct cnic_eth_dev {
 	u32		drv_state;
 #define CNIC_DRV_STATE_REGD		0x00000001
 #define CNIC_DRV_STATE_USING_MSIX	0x00000002
+#define CNIC_DRV_STATE_NO_ISCSI_OOO	0x00000004
+#define CNIC_DRV_STATE_NO_ISCSI		0x00000008
+#define CNIC_DRV_STATE_NO_FCOE		0x00000010
 	u32		chip_id;
 	u32		max_kwqe_pending;
 	struct pci_dev	*pdev;
@@ -176,6 +179,7 @@ struct cnic_eth_dev {
 	u32		fcoe_init_cid;
 	u16		iscsi_l2_client_id;
 	u16		iscsi_l2_cid;
+	u8		iscsi_mac[ETH_ALEN];
 
 	int		num_irq;
 	struct cnic_irq	irq_arr[MAX_CNIC_VEC];
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index d325e01..537a4b2 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -95,6 +95,9 @@
   Dmitry Pervushin  : dpervushin@ru.mvista.com
                     : PNX010X platform support
 
+  Domenico Andreoli : cavokz@gmail.com
+                    : QQ2440 platform support
+
 */
 
 /* Always include 'config.h' first in case the user wants to turn on
@@ -176,6 +179,10 @@ static unsigned int cs8900_irq_map[] = {IRQ_IXDP2351_CS8900, 0, 0, 0};
 #elif defined(CONFIG_ARCH_IXDP2X01)
 static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
 static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
+#elif defined(CONFIG_MACH_QQ2440)
+#include <mach/qq2440.h>
+static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 };
+static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 };
 #elif defined(CONFIG_MACH_MX31ADS)
 #include <mach/board-mx31ads.h>
 static unsigned int netcard_portlist[] __used __initdata = {
@@ -521,6 +528,10 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
 #endif
 		lp->force = g_cs89x0_media__force;
 #endif
+
+#if defined(CONFIG_MACH_QQ2440)
+		lp->force |= FORCE_RJ45 | FORCE_FULL;
+#endif
         }
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
@@ -943,10 +954,10 @@ skip_this_frame:
 static void __init reset_chip(struct net_device *dev)
 {
 #if !defined(CONFIG_MACH_MX31ADS)
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
+#if !defined(CS89x0_NONISA_IRQ)
 	struct net_local *lp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
-#endif
+#endif /* CS89x0_NONISA_IRQ */
 	int reset_start_time;
 
 	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
@@ -954,7 +965,7 @@ static void __init reset_chip(struct net_device *dev)
 	/* wait 30 ms */
 	msleep(30);
 
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
+#if !defined(CS89x0_NONISA_IRQ)
 	if (lp->chip_type != CS8900) {
 		/* Hardware problem requires PNP registers to be reconfigured after a reset */
 		writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
@@ -965,7 +976,7 @@ static void __init reset_chip(struct net_device *dev)
 		outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
 		outb((dev->mem_start >> 8) & 0xff,   ioaddr + DATA_PORT + 1);
 	}
-#endif	/* IXDP2x01 */
+#endif /* CS89x0_NONISA_IRQ */
 
 	/* Wait until the chip is reset */
 	reset_start_time = jiffies;
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index ef02aa6..862804f 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -186,9 +186,10 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
 				dev = NULL;
 				if (grp)
 					dev = vlan_group_get_device(grp, vlan);
-			} else
+			} else if (netif_is_bond_slave(dev)) {
 				while (dev->master)
 					dev = dev->master;
+			}
 			return dev;
 		}
 	}
@@ -967,8 +968,6 @@ static int nb_callback(struct notifier_block *self, unsigned long event,
 		cxgb_neigh_update((struct neighbour *)ctx);
 		break;
 	}
-	case (NETEVENT_PMTU_UPDATE):
-		break;
 	case (NETEVENT_REDIRECT):{
 		struct netevent_redirect *nr = ctx;
 		cxgb_redirect(nr->old, nr->new);
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c
index ec35d45..5352c8a 100644
--- a/drivers/net/cxgb4/cxgb4_main.c
+++ b/drivers/net/cxgb4/cxgb4_main.c
@@ -2471,7 +2471,6 @@ static int netevent_cb(struct notifier_block *nb, unsigned long event,
 	case NETEVENT_NEIGH_UPDATE:
 		check_neigh_update(data);
 		break;
-	case NETEVENT_PMTU_UPDATE:
 	case NETEVENT_REDIRECT:
 	default:
 		break;
diff --git a/drivers/net/cxgb4/t4_msg.h b/drivers/net/cxgb4/t4_msg.h
index a550d0c..eb71b82 100644
--- a/drivers/net/cxgb4/t4_msg.h
+++ b/drivers/net/cxgb4/t4_msg.h
@@ -123,6 +123,7 @@ enum {
 	ULP_MODE_NONE          = 0,
 	ULP_MODE_ISCSI         = 2,
 	ULP_MODE_RDMA          = 4,
+	ULP_MODE_TCPDDP	       = 5,
 	ULP_MODE_FCOE          = 6,
 };
 
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 7018bfe..082d6ea 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -1730,7 +1730,7 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
 		emac_read(EMAC_TXCARRIERSENSE);
 	emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask);
 
-	ndev->stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN);
+	ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
 	emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
 
 	return &ndev->stats;
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 461dd6f..3177081 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -1593,10 +1593,15 @@ dm9000_probe(struct platform_device *pdev)
 			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
 	}
 
-	if (!is_valid_ether_addr(ndev->dev_addr))
+	if (!is_valid_ether_addr(ndev->dev_addr)) {
 		dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
 			 "set using ifconfig\n", ndev->name);
 
+		random_ether_addr(ndev->dev_addr);
+		mac_src = "random";
+	}
+
+
 	platform_set_drvdata(pdev, ndev);
 	ret = register_netdev(ndev);
 
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 1314998..c516a74 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -86,6 +86,7 @@
 #define E1000_CTRL_EXT_IAME           0x08000000 /* Interrupt acknowledge Auto-mask */
 #define E1000_CTRL_EXT_INT_TIMER_CLR  0x20000000 /* Clear Interrupt timers after IMS clear */
 #define E1000_CTRL_EXT_PBA_CLR        0x80000000 /* PBA Clear */
+#define E1000_CTRL_EXT_LSECCK         0x00001000
 #define E1000_CTRL_EXT_PHYPDEN        0x00100000
 
 /* Receive Descriptor bit definitions */
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index e610e13..00bf595 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -364,6 +364,7 @@ struct e1000_adapter {
 	/* structs defined in e1000_hw.h */
 	struct e1000_hw hw;
 
+	spinlock_t stats64_lock;
 	struct e1000_hw_stats stats;
 	struct e1000_phy_info phy_info;
 	struct e1000_phy_stats phy_stats;
@@ -494,7 +495,9 @@ extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter);
 extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
-extern void e1000e_update_stats(struct e1000_adapter *adapter);
+extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+                                                    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);
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index fa08b63..07f09e9 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -46,15 +46,15 @@ struct e1000_stats {
 };
 
 #define E1000_STAT(str, m) { \
-			.stat_string = str, \
-			.type = E1000_STATS, \
-			.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
-			.stat_offset = offsetof(struct e1000_adapter, m) }
+		.stat_string = str, \
+		.type = E1000_STATS, \
+		.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
+		.stat_offset = offsetof(struct e1000_adapter, m) }
 #define E1000_NETDEV_STAT(str, m) { \
-			.stat_string = str, \
-			.type = NETDEV_STATS, \
-			.sizeof_stat = sizeof(((struct net_device *)0)->m), \
-			.stat_offset = offsetof(struct net_device, m) }
+		.stat_string = str, \
+		.type = NETDEV_STATS, \
+		.sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \
+		.stat_offset = offsetof(struct rtnl_link_stats64, m) }
 
 static const struct e1000_stats e1000_gstrings_stats[] = {
 	E1000_STAT("rx_packets", stats.gprc),
@@ -65,21 +65,21 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
 	E1000_STAT("tx_broadcast", stats.bptc),
 	E1000_STAT("rx_multicast", stats.mprc),
 	E1000_STAT("tx_multicast", stats.mptc),
-	E1000_NETDEV_STAT("rx_errors", stats.rx_errors),
-	E1000_NETDEV_STAT("tx_errors", stats.tx_errors),
-	E1000_NETDEV_STAT("tx_dropped", stats.tx_dropped),
+	E1000_NETDEV_STAT("rx_errors", rx_errors),
+	E1000_NETDEV_STAT("tx_errors", tx_errors),
+	E1000_NETDEV_STAT("tx_dropped", tx_dropped),
 	E1000_STAT("multicast", stats.mprc),
 	E1000_STAT("collisions", stats.colc),
-	E1000_NETDEV_STAT("rx_length_errors", stats.rx_length_errors),
-	E1000_NETDEV_STAT("rx_over_errors", stats.rx_over_errors),
+	E1000_NETDEV_STAT("rx_length_errors", rx_length_errors),
+	E1000_NETDEV_STAT("rx_over_errors", rx_over_errors),
 	E1000_STAT("rx_crc_errors", stats.crcerrs),
-	E1000_NETDEV_STAT("rx_frame_errors", stats.rx_frame_errors),
+	E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors),
 	E1000_STAT("rx_no_buffer_count", stats.rnbc),
 	E1000_STAT("rx_missed_errors", stats.mpc),
 	E1000_STAT("tx_aborted_errors", stats.ecol),
 	E1000_STAT("tx_carrier_errors", stats.tncrs),
-	E1000_NETDEV_STAT("tx_fifo_errors", stats.tx_fifo_errors),
-	E1000_NETDEV_STAT("tx_heartbeat_errors", stats.tx_heartbeat_errors),
+	E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors),
+	E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors),
 	E1000_STAT("tx_window_errors", stats.latecol),
 	E1000_STAT("tx_abort_late_coll", stats.latecol),
 	E1000_STAT("tx_deferred_ok", stats.dc),
@@ -433,13 +433,11 @@ static void e1000_get_regs(struct net_device *netdev,
 	struct e1000_hw *hw = &adapter->hw;
 	u32 *regs_buff = p;
 	u16 phy_data;
-	u8 revision_id;
 
 	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
 
-	pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
-
-	regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
+	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
+			adapter->pdev->device;
 
 	regs_buff[0]  = er32(CTRL);
 	regs_buff[1]  = er32(STATUS);
@@ -684,20 +682,13 @@ static int e1000_set_ringparam(struct net_device *netdev,
 	rx_old = adapter->rx_ring;
 
 	err = -ENOMEM;
-	tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+	tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL);
 	if (!tx_ring)
 		goto err_alloc_tx;
-	/*
-	 * use a memcpy to save any previously configured
-	 * items like napi structs from having to be
-	 * reinitialized
-	 */
-	memcpy(tx_ring, tx_old, sizeof(struct e1000_ring));
 
-	rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+	rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL);
 	if (!rx_ring)
 		goto err_alloc_rx;
-	memcpy(rx_ring, rx_old, sizeof(struct e1000_ring));
 
 	adapter->tx_ring = tx_ring;
 	adapter->rx_ring = rx_ring;
@@ -1255,7 +1246,6 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_reg = 0;
-	u32 stat_reg = 0;
 	u16 phy_reg = 0;
 	s32 ret_val = 0;
 
@@ -1363,8 +1353,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 		 * Set the ILOS bit on the fiber Nic if half duplex link is
 		 * detected.
 		 */
-		stat_reg = er32(STATUS);
-		if ((stat_reg & E1000_STATUS_FD) == 0)
+		if ((er32(STATUS) & E1000_STATUS_FD) == 0)
 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
 	}
 
@@ -1677,10 +1666,13 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
 	} else {
 		hw->mac.ops.check_for_link(hw);
 		if (hw->mac.autoneg)
-			msleep(4000);
+			/*
+			 * On some Phy/switch combinations, link establishment
+			 * can take a few seconds more than expected.
+			 */
+			msleep(5000);
 
-		if (!(er32(STATUS) &
-		      E1000_STATUS_LU))
+		if (!(er32(STATUS) & E1000_STATUS_LU))
 			*data = 1;
 	}
 	return *data;
@@ -1807,8 +1799,7 @@ static void e1000_get_wol(struct net_device *netdev,
 		return;
 
 	wol->supported = WAKE_UCAST | WAKE_MCAST |
-	                 WAKE_BCAST | WAKE_MAGIC |
-	                 WAKE_PHY | WAKE_ARP;
+	    WAKE_BCAST | WAKE_MAGIC | WAKE_PHY;
 
 	/* apply any specific unsupported masks here */
 	if (adapter->flags & FLAG_NO_WAKE_UCAST) {
@@ -1829,19 +1820,16 @@ static void e1000_get_wol(struct net_device *netdev,
 		wol->wolopts |= WAKE_MAGIC;
 	if (adapter->wol & E1000_WUFC_LNKC)
 		wol->wolopts |= WAKE_PHY;
-	if (adapter->wol & E1000_WUFC_ARP)
-		wol->wolopts |= WAKE_ARP;
 }
 
-static int e1000_set_wol(struct net_device *netdev,
-			 struct ethtool_wolinfo *wol)
+static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
 	if (!(adapter->flags & FLAG_HAS_WOL) ||
 	    !device_can_wakeup(&adapter->pdev->dev) ||
 	    (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
-	                      WAKE_MAGIC | WAKE_PHY | WAKE_ARP)))
+			      WAKE_MAGIC | WAKE_PHY)))
 		return -EOPNOTSUPP;
 
 	/* these settings will always override what we currently have */
@@ -1857,8 +1845,6 @@ static int e1000_set_wol(struct net_device *netdev,
 		adapter->wol |= E1000_WUFC_MAG;
 	if (wol->wolopts & WAKE_PHY)
 		adapter->wol |= E1000_WUFC_LNKC;
-	if (wol->wolopts & WAKE_ARP)
-		adapter->wol |= E1000_WUFC_ARP;
 
 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
@@ -1972,8 +1958,15 @@ static int e1000_set_coalesce(struct net_device *netdev,
 static int e1000_nway_reset(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		e1000e_reinit_locked(adapter);
+
+	if (!netif_running(netdev))
+		return -EAGAIN;
+
+	if (!adapter->hw.mac.autoneg)
+		return -EINVAL;
+
+	e1000e_reinit_locked(adapter);
+
 	return 0;
 }
 
@@ -1982,14 +1975,15 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
 				    u64 *data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct rtnl_link_stats64 net_stats;
 	int i;
 	char *p = NULL;
 
-	e1000e_update_stats(adapter);
+	e1000e_get_stats64(netdev, &net_stats);
 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
 		switch (e1000_gstrings_stats[i].type) {
 		case NETDEV_STATS:
-			p = (char *) netdev +
+			p = (char *) &net_stats +
 					e1000_gstrings_stats[i].stat_offset;
 			break;
 		case E1000_STATS:
@@ -2014,7 +2008,7 @@ static void e1000_get_strings(struct net_device *netdev, u32 stringset,
 
 	switch (stringset) {
 	case ETH_SS_TEST:
-		memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test));
+		memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test));
 		break;
 	case ETH_SS_STATS:
 		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index bc0860a..307e1ec 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -812,9 +812,8 @@ struct e1000_nvm_operations {
 
 struct e1000_mac_info {
 	struct e1000_mac_operations ops;
-
-	u8 addr[6];
-	u8 perm_addr[6];
+	u8 addr[ETH_ALEN];
+	u8 perm_addr[ETH_ALEN];
 
 	enum e1000_mac_type type;
 
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index fb46974..ce1dbfd 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -140,6 +140,11 @@
 #define I82579_LPI_CTRL			PHY_REG(772, 20)
 #define I82579_LPI_CTRL_ENABLE_MASK	0x6000
 
+/* EMI Registers */
+#define I82579_EMI_ADDR         0x10
+#define I82579_EMI_DATA         0x11
+#define I82579_LPI_UPDATE_TIMER 0x4805	/* in 40ns units + 40 ns base value */
+
 /* Strapping Option Register - RO */
 #define E1000_STRAP                     0x0000C
 #define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
@@ -302,9 +307,9 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 	 * the interconnect to PCIe mode.
 	 */
 	fwsm = er32(FWSM);
-	if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+	if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
 		ctrl = er32(CTRL);
-		ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
+		ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
 		ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
 		ew32(CTRL, ctrl);
 		udelay(10);
@@ -331,7 +336,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 		goto out;
 
 	/* Ungate automatic PHY configuration on non-managed 82579 */
-	if ((hw->mac.type == e1000_pch2lan)  &&
+	if ((hw->mac.type == e1000_pch2lan) &&
 	    !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
 		msleep(10);
 		e1000_gate_hw_phy_config_ich8lan(hw, false);
@@ -366,7 +371,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 	case e1000_phy_82579:
 		phy->ops.check_polarity = e1000_check_polarity_82577;
 		phy->ops.force_speed_duplex =
-			e1000_phy_force_speed_duplex_82577;
+		    e1000_phy_force_speed_duplex_82577;
 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
 		phy->ops.get_info = e1000_get_phy_info_82577;
 		phy->ops.commit = e1000e_phy_sw_reset;
@@ -753,7 +758,13 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
 	if (rc)
 		return rc;
 
-	if (adapter->hw.phy.type == e1000_phy_ife) {
+	/*
+	 * Disable Jumbo Frame support on parts with Intel 10/100 PHY or
+	 * on parts with MACsec enabled in NVM (reflected in CTRL_EXT).
+	 */
+	if ((adapter->hw.phy.type == e1000_phy_ife) ||
+	    ((adapter->hw.mac.type >= e1000_pch2lan) &&
+	     (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LSECCK)))) {
 		adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES;
 		adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
 	}
@@ -1723,11 +1734,25 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
 	/* Configure the LCD with the OEM bits in NVM */
 	ret_val = e1000_oem_bits_config_ich8lan(hw, true);
 
-	/* Ungate automatic PHY configuration on non-managed 82579 */
-	if ((hw->mac.type == e1000_pch2lan) &&
-	    !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
-		msleep(10);
-		e1000_gate_hw_phy_config_ich8lan(hw, false);
+	if (hw->mac.type == e1000_pch2lan) {
+		/* Ungate automatic PHY configuration on non-managed 82579 */
+		if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+			msleep(10);
+			e1000_gate_hw_phy_config_ich8lan(hw, false);
+		}
+
+		/* Set EEE LPI Update Timer to 200usec */
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val)
+			goto out;
+		ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
+						       I82579_LPI_UPDATE_TIMER);
+		if (ret_val)
+			goto release;
+		ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA,
+						       0x1387);
+release:
+		hw->phy.ops.release(hw);
 	}
 
 out:
@@ -2104,7 +2129,6 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 {
 	union ich8_hws_flash_status hsfsts;
 	s32 ret_val = -E1000_ERR_NVM;
-	s32 i = 0;
 
 	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
 
@@ -2140,6 +2164,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 		ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
 		ret_val = 0;
 	} else {
+		s32 i = 0;
+
 		/*
 		 * Otherwise poll for sometime so the current
 		 * cycle has a chance to end before giving up.
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index 68aa174..96921de 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -1978,15 +1978,15 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
 {
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	u32 eecd = er32(EECD);
-	u16 timeout = 0;
 	u8 spi_stat_reg;
 
 	if (nvm->type == e1000_nvm_eeprom_spi) {
+		u16 timeout = NVM_MAX_RETRY_SPI;
+
 		/* Clear SK and CS */
 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
 		ew32(EECD, eecd);
 		udelay(1);
-		timeout = NVM_MAX_RETRY_SPI;
 
 		/*
 		 * Read "Status Register" repeatedly until the LSB is cleared.
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 2e50228..a39d4a4 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -54,7 +54,7 @@
 
 #define DRV_EXTRAVERSION "-k2"
 
-#define DRV_VERSION "1.2.20" DRV_EXTRAVERSION
+#define DRV_VERSION "1.3.10" DRV_EXTRAVERSION
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -900,8 +900,6 @@ next_desc:
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1060,8 +1058,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
 	}
 	adapter->total_tx_bytes += total_tx_bytes;
 	adapter->total_tx_packets += total_tx_packets;
-	netdev->stats.tx_bytes += total_tx_bytes;
-	netdev->stats.tx_packets += total_tx_packets;
 	return count < tx_ring->count;
 }
 
@@ -1248,8 +1244,6 @@ next_desc:
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1328,7 +1322,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 				/* an error means any chain goes out the window
 				 * too */
 				if (rx_ring->rx_skb_top)
-					dev_kfree_skb(rx_ring->rx_skb_top);
+					dev_kfree_skb_irq(rx_ring->rx_skb_top);
 				rx_ring->rx_skb_top = NULL;
 				goto next_desc;
 		}
@@ -1401,7 +1395,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter,
 		/* eth type trans needs skb->data to point to something */
 		if (!pskb_may_pull(skb, ETH_HLEN)) {
 			e_err("pskb_may_pull failed.\n");
-			dev_kfree_skb(skb);
+			dev_kfree_skb_irq(skb);
 			goto next_desc;
 		}
 
@@ -1429,8 +1423,6 @@ next_desc:
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1857,7 +1849,9 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
 	int err = 0, vector = 0;
 
 	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name);
+		snprintf(adapter->rx_ring->name,
+			 sizeof(adapter->rx_ring->name) - 1,
+			 "%s-rx-0", netdev->name);
 	else
 		memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
 	err = request_irq(adapter->msix_entries[vector].vector,
@@ -1870,7 +1864,9 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
 	vector++;
 
 	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name);
+		snprintf(adapter->tx_ring->name,
+			 sizeof(adapter->tx_ring->name) - 1,
+			 "%s-tx-0", netdev->name);
 	else
 		memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
 	err = request_irq(adapter->msix_entries[vector].vector,
@@ -2734,7 +2730,6 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl, rfctl;
-	u32 psrctl = 0;
 	u32 pages = 0;
 
 	/* Workaround Si errata on 82579 - configure jumbo frame flow */
@@ -2833,6 +2828,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
 		adapter->rx_ps_pages = 0;
 
 	if (adapter->rx_ps_pages) {
+		u32 psrctl = 0;
+
 		/* Configure extra packet-split registers */
 		rfctl = er32(RFCTL);
 		rfctl |= E1000_RFCTL_EXTEN;
@@ -3034,7 +3031,6 @@ static void e1000_set_multi(struct net_device *netdev)
 	struct netdev_hw_addr *ha;
 	u8  *mta_list;
 	u32 rctl;
-	int i;
 
 	/* Check for Promiscuous and All Multicast modes */
 
@@ -3057,12 +3053,13 @@ static void e1000_set_multi(struct net_device *netdev)
 	ew32(RCTL, rctl);
 
 	if (!netdev_mc_empty(netdev)) {
+		int i = 0;
+
 		mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC);
 		if (!mta_list)
 			return;
 
 		/* prepare 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);
 
@@ -3359,6 +3356,8 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter)
 	e1e_flush();
 }
 
+static void e1000e_update_stats(struct e1000_adapter *adapter);
+
 void e1000e_down(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -3393,6 +3392,11 @@ void e1000e_down(struct e1000_adapter *adapter)
 	del_timer_sync(&adapter->phy_info_timer);
 
 	netif_carrier_off(netdev);
+
+	spin_lock(&adapter->stats64_lock);
+	e1000e_update_stats(adapter);
+	spin_unlock(&adapter->stats64_lock);
+
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 
@@ -3437,6 +3441,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
 	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
+	spin_lock_init(&adapter->stats64_lock);
+
 	e1000e_set_interrupt_capability(adapter);
 
 	if (e1000_alloc_queues(adapter))
@@ -3918,7 +3924,7 @@ release:
  * e1000e_update_stats - Update the board statistics counters
  * @adapter: board private structure
  **/
-void e1000e_update_stats(struct e1000_adapter *adapter)
+static void e1000e_update_stats(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_hw *hw = &adapter->hw;
@@ -4030,10 +4036,11 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_phy_regs *phy = &adapter->phy_regs;
-	int ret_val;
 
 	if ((er32(STATUS) & E1000_STATUS_LU) &&
 	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
+		int ret_val;
+
 		ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
 		ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
 		ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
@@ -4179,7 +4186,6 @@ static void e1000_watchdog_task(struct work_struct *work)
 	struct e1000_ring *tx_ring = adapter->tx_ring;
 	struct e1000_hw *hw = &adapter->hw;
 	u32 link, tctl;
-	int tx_pending = 0;
 
 	if (test_bit(__E1000_DOWN, &adapter->state))
 		return;
@@ -4320,7 +4326,9 @@ static void e1000_watchdog_task(struct work_struct *work)
 	}
 
 link_up:
+	spin_lock(&adapter->stats64_lock);
 	e1000e_update_stats(adapter);
+	spin_unlock(&adapter->stats64_lock);
 
 	mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
 	adapter->tpt_old = adapter->stats.tpt;
@@ -4334,20 +4342,17 @@ link_up:
 
 	e1000e_update_adaptive(&adapter->hw);
 
-	if (!netif_carrier_ok(netdev)) {
-		tx_pending = (e1000_desc_unused(tx_ring) + 1 <
-			       tx_ring->count);
-		if (tx_pending) {
-			/*
-			 * We've lost link, so the controller stops DMA,
-			 * but we've got queued Tx work that's never going
-			 * to get done, so reset controller to flush Tx.
-			 * (Do the reset outside of interrupt context).
-			 */
-			schedule_work(&adapter->reset_task);
-			/* return immediately since reset is imminent */
-			return;
-		}
+	if (!netif_carrier_ok(netdev) &&
+	    (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) {
+		/*
+		 * We've lost link, so the controller stops DMA,
+		 * but we've got queued Tx work that's never going
+		 * to get done, so reset controller to flush Tx.
+		 * (Do the reset outside of interrupt context).
+		 */
+		schedule_work(&adapter->reset_task);
+		/* return immediately since reset is imminent */
+		return;
 	}
 
 	/* Simple mode for Interrupt Throttle Rate (ITR) */
@@ -4411,13 +4416,13 @@ static int e1000_tso(struct e1000_adapter *adapter,
 	u32 cmd_length = 0;
 	u16 ipcse = 0, tucse, mss;
 	u8 ipcss, ipcso, tucss, tucso, hdr_len;
-	int err;
 
 	if (!skb_is_gso(skb))
 		return 0;
 
 	if (skb_header_cloned(skb)) {
-		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+		int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+
 		if (err)
 			return err;
 	}
@@ -4928,16 +4933,55 @@ static void e1000_reset_task(struct work_struct *work)
 }
 
 /**
- * e1000_get_stats - Get System Network Statistics
+ * e1000_get_stats64 - Get System Network Statistics
  * @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
  *
  * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
  **/
-static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+                                             struct rtnl_link_stats64 *stats)
 {
-	/* only return the current stats */
-	return &netdev->stats;
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	memset(stats, 0, sizeof(struct rtnl_link_stats64));
+	spin_lock(&adapter->stats64_lock);
+	e1000e_update_stats(adapter);
+	/* Fill out the OS statistics structure */
+	stats->rx_bytes = adapter->stats.gorc;
+	stats->rx_packets = adapter->stats.gprc;
+	stats->tx_bytes = adapter->stats.gotc;
+	stats->tx_packets = adapter->stats.gptc;
+	stats->multicast = adapter->stats.mprc;
+	stats->collisions = adapter->stats.colc;
+
+	/* Rx Errors */
+
+	/*
+	 * RLEC on some newer hardware can be incorrect so build
+	 * 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;
+	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_aborted_errors = adapter->stats.ecol;
+	stats->tx_window_errors = adapter->stats.latecol;
+	stats->tx_carrier_errors = adapter->stats.tncrs;
+
+	/* Tx Dropped needs to be maintained elsewhere */
+
+	spin_unlock(&adapter->stats64_lock);
+	return stats;
 }
 
 /**
@@ -5338,7 +5382,7 @@ void e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
 	__e1000e_disable_aspm(pdev, state);
 }
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 static bool e1000e_pm_ready(struct e1000_adapter *adapter)
 {
 	return !!adapter->tx_ring->buffer_info;
@@ -5489,7 +5533,7 @@ static int e1000_runtime_resume(struct device *dev)
 	return __e1000_resume(pdev);
 }
 #endif /* CONFIG_PM_RUNTIME */
-#endif /* CONFIG_PM_OPS */
+#endif /* CONFIG_PM */
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
@@ -5507,9 +5551,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data)
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int vector, msix_irq;
 
 	if (adapter->msix_entries) {
+		int vector, msix_irq;
+
 		vector = 0;
 		msix_irq = adapter->msix_entries[vector].vector;
 		disable_irq(msix_irq);
@@ -5706,7 +5751,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
 	.ndo_open		= e1000_open,
 	.ndo_stop		= e1000_close,
 	.ndo_start_xmit		= e1000_xmit_frame,
-	.ndo_get_stats		= e1000_get_stats,
+	.ndo_get_stats64	= e1000e_get_stats64,
 	.ndo_set_multicast_list	= e1000_set_multi,
 	.ndo_set_mac_address	= e1000_set_mac,
 	.ndo_change_mtu		= e1000_change_mtu,
@@ -6196,7 +6241,7 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
 };
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-#ifdef CONFIG_PM_OPS
+#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,
@@ -6210,7 +6255,7 @@ static struct pci_driver e1000_driver = {
 	.id_table = e1000_pci_tbl,
 	.probe    = e1000_probe,
 	.remove   = __devexit_p(e1000_remove),
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 	.driver.pm = &e1000_pm_ops,
 #endif
 	.shutdown = e1000_shutdown,
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 6bea051..6ae31fc 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -2409,9 +2409,7 @@ static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
 s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 {
 	s32 ret_val;
-	u32 page_select = 0;
 	u32 page = offset >> IGP_PAGE_SHIFT;
-	u32 page_shift = 0;
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -2427,6 +2425,8 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+		u32 page_shift, page_select;
+
 		/*
 		 * Page select is register 31 for phy address 1 and 22 for
 		 * phy address 2 and 3. Page select is shifted only for
@@ -2468,9 +2468,7 @@ out:
 s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 {
 	s32 ret_val;
-	u32 page_select = 0;
 	u32 page = offset >> IGP_PAGE_SHIFT;
-	u32 page_shift = 0;
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -2486,6 +2484,8 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+		u32 page_shift, page_select;
+
 		/*
 		 * Page select is register 31 for phy address 1 and 22 for
 		 * phy address 2 and 3. Page select is shifted only for
diff --git a/drivers/net/enic/Makefile b/drivers/net/enic/Makefile
index e7b6c31..2e573be 100644
--- a/drivers/net/enic/Makefile
+++ b/drivers/net/enic/Makefile
@@ -1,5 +1,5 @@
 obj-$(CONFIG_ENIC) := enic.o
 
 enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
-	enic_res.o vnic_dev.o vnic_rq.o vnic_vic.o
+	enic_res.o enic_dev.o vnic_dev.o vnic_rq.o vnic_vic.o
 
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index a937f49..3a3c3c8 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -32,13 +32,13 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"1.4.1.10"
-#define DRV_COPYRIGHT		"Copyright 2008-2010 Cisco Systems, Inc"
+#define DRV_VERSION		"2.1.1.12"
+#define DRV_COPYRIGHT		"Copyright 2008-2011 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
 
-#define ENIC_WQ_MAX		8
-#define ENIC_RQ_MAX		8
+#define ENIC_WQ_MAX		1
+#define ENIC_RQ_MAX		1
 #define ENIC_CQ_MAX		(ENIC_WQ_MAX + ENIC_RQ_MAX)
 #define ENIC_INTR_MAX		(ENIC_CQ_MAX + 2)
 
@@ -49,7 +49,7 @@ struct enic_msix_entry {
 	void *devid;
 };
 
-#define ENIC_SET_APPLIED		(1 << 0)
+#define ENIC_PORT_REQUEST_APPLIED	(1 << 0)
 #define ENIC_SET_REQUEST		(1 << 1)
 #define ENIC_SET_NAME			(1 << 2)
 #define ENIC_SET_INSTANCE		(1 << 3)
@@ -101,7 +101,6 @@ struct enic {
 	/* receive queue cache line section */
 	____cacheline_aligned struct vnic_rq rq[ENIC_RQ_MAX];
 	unsigned int rq_count;
-	int (*rq_alloc_buf)(struct vnic_rq *rq);
 	u64 rq_truncated_pkts;
 	u64 rq_bad_fcs;
 	struct napi_struct napi[ENIC_RQ_MAX];
diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/enic/enic_dev.c
new file mode 100644
index 0000000..37ad3a1
--- /dev/null
+++ b/drivers/net/enic/enic_dev.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2011 Cisco Systems, Inc.  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.
+ *
+ */
+
+#include <linux/pci.h>
+#include <linux/etherdevice.h>
+
+#include "vnic_dev.h"
+#include "vnic_vic.h"
+#include "enic_res.h"
+#include "enic.h"
+#include "enic_dev.h"
+
+int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_fw_info(enic->vdev, fw_info);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_stats_dump(enic->vdev, vstats);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_add_station_addr(struct enic *enic)
+{
+	int err;
+
+	if (!is_valid_ether_addr(enic->netdev->dev_addr))
+		return -EADDRNOTAVAIL;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_del_station_addr(struct enic *enic)
+{
+	int err;
+
+	if (!is_valid_ether_addr(enic->netdev->dev_addr))
+		return -EADDRNOTAVAIL;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_packet_filter(struct enic *enic, int directed, int multicast,
+	int broadcast, int promisc, int allmulti)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_packet_filter(enic->vdev, directed,
+		multicast, broadcast, promisc, allmulti);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_add_addr(struct enic *enic, u8 *addr)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_add_addr(enic->vdev, addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_del_addr(struct enic *enic, u8 *addr)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_del_addr(enic->vdev, addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_notify_unset(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_notify_unset(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_hang_notify(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_hang_notify(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
+		IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_enable(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_enable_wait(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_disable(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_disable(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_vnic_dev_deinit(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_deinit(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_init_prov(enic->vdev,
+		(u8 *)vp, vic_provinfo_size(vp));
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_init_done(struct enic *enic, int *done, int *error)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_init_done(enic->vdev, done, error);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+/* rtnl lock is held */
+void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	spin_lock(&enic->devcmd_lock);
+	enic_add_vlan(enic, vid);
+	spin_unlock(&enic->devcmd_lock);
+}
+
+/* rtnl lock is held */
+void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	spin_lock(&enic->devcmd_lock);
+	enic_del_vlan(enic, vid);
+	spin_unlock(&enic->devcmd_lock);
+}
diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/enic/enic_dev.h
new file mode 100644
index 0000000..495f57f
--- /dev/null
+++ b/drivers/net/enic/enic_dev.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 Cisco Systems, Inc.  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 _ENIC_DEV_H_
+#define _ENIC_DEV_H_
+
+int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info);
+int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats);
+int enic_dev_add_station_addr(struct enic *enic);
+int enic_dev_del_station_addr(struct enic *enic);
+int enic_dev_packet_filter(struct enic *enic, int directed, int multicast,
+	int broadcast, int promisc, int allmulti);
+int enic_dev_add_addr(struct enic *enic, u8 *addr);
+int enic_dev_del_addr(struct enic *enic, u8 *addr);
+void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
+void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+int enic_dev_notify_unset(struct enic *enic);
+int enic_dev_hang_notify(struct enic *enic);
+int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic);
+int enic_dev_enable(struct enic *enic);
+int enic_dev_disable(struct enic *enic);
+int enic_vnic_dev_deinit(struct enic *enic);
+int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp);
+int enic_dev_init_done(struct enic *enic, int *done, int *error);
+
+#endif /* _ENIC_DEV_H_ */
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index a0af48c..8b9cad5 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -44,6 +44,7 @@
 #include "vnic_vic.h"
 #include "enic_res.h"
 #include "enic.h"
+#include "enic_dev.h"
 
 #define ENIC_NOTIFY_TIMER_PERIOD	(2 * HZ)
 #define WQ_ENET_MAX_DESC_LEN		(1 << WQ_ENET_LEN_BITS)
@@ -190,18 +191,6 @@ static int enic_get_settings(struct net_device *netdev,
 	return 0;
 }
 
-static int enic_dev_fw_info(struct enic *enic,
-	struct vnic_devcmd_fw_info **fw_info)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_fw_info(enic->vdev, fw_info);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_get_drvinfo(struct net_device *netdev,
 	struct ethtool_drvinfo *drvinfo)
 {
@@ -246,17 +235,6 @@ static int enic_get_sset_count(struct net_device *netdev, int sset)
 	}
 }
 
-static int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_stats_dump(enic->vdev, vstats);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_get_ethtool_stats(struct net_device *netdev,
 	struct ethtool_stats *stats, u64 *data)
 {
@@ -896,9 +874,10 @@ static struct net_device_stats *enic_get_stats(struct net_device *netdev)
 	return net_stats;
 }
 
-static void enic_reset_multicast_list(struct enic *enic)
+static void enic_reset_addr_lists(struct enic *enic)
 {
 	enic->mc_count = 0;
+	enic->uc_count = 0;
 	enic->flags = 0;
 }
 
@@ -919,32 +898,6 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
 	return 0;
 }
 
-static int enic_dev_add_station_addr(struct enic *enic)
-{
-	int err = 0;
-
-	if (is_valid_ether_addr(enic->netdev->dev_addr)) {
-		spin_lock(&enic->devcmd_lock);
-		err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
-		spin_unlock(&enic->devcmd_lock);
-	}
-
-	return err;
-}
-
-static int enic_dev_del_station_addr(struct enic *enic)
-{
-	int err = 0;
-
-	if (is_valid_ether_addr(enic->netdev->dev_addr)) {
-		spin_lock(&enic->devcmd_lock);
-		err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
-		spin_unlock(&enic->devcmd_lock);
-	}
-
-	return err;
-}
-
 static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p)
 {
 	struct enic *enic = netdev_priv(netdev);
@@ -989,42 +942,7 @@ static int enic_set_mac_address(struct net_device *netdev, void *p)
 	return enic_dev_add_station_addr(enic);
 }
 
-static int enic_dev_packet_filter(struct enic *enic, int directed,
-	int multicast, int broadcast, int promisc, int allmulti)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_packet_filter(enic->vdev, directed,
-		multicast, broadcast, promisc, allmulti);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_add_addr(struct enic *enic, u8 *addr)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_add_addr(enic->vdev, addr);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_del_addr(struct enic *enic, u8 *addr)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_del_addr(enic->vdev, addr);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static void enic_add_multicast_addr_list(struct enic *enic)
+static void enic_update_multicast_addr_list(struct enic *enic)
 {
 	struct net_device *netdev = enic->netdev;
 	struct netdev_hw_addr *ha;
@@ -1079,7 +997,7 @@ static void enic_add_multicast_addr_list(struct enic *enic)
 	enic->mc_count = mc_count;
 }
 
-static void enic_add_unicast_addr_list(struct enic *enic)
+static void enic_update_unicast_addr_list(struct enic *enic)
 {
 	struct net_device *netdev = enic->netdev;
 	struct netdev_hw_addr *ha;
@@ -1156,9 +1074,9 @@ static void enic_set_rx_mode(struct net_device *netdev)
 	}
 
 	if (!promisc) {
-		enic_add_unicast_addr_list(enic);
+		enic_update_unicast_addr_list(enic);
 		if (!allmulti)
-			enic_add_multicast_addr_list(enic);
+			enic_update_multicast_addr_list(enic);
 	}
 }
 
@@ -1170,26 +1088,6 @@ static void enic_vlan_rx_register(struct net_device *netdev,
 	enic->vlan_group = vlan_group;
 }
 
-/* rtnl lock is held */
-static void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	spin_lock(&enic->devcmd_lock);
-	enic_add_vlan(enic, vid);
-	spin_unlock(&enic->devcmd_lock);
-}
-
-/* rtnl lock is held */
-static void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	spin_lock(&enic->devcmd_lock);
-	enic_del_vlan(enic, vid);
-	spin_unlock(&enic->devcmd_lock);
-}
-
 /* netif_tx_lock held, BHs disabled */
 static void enic_tx_timeout(struct net_device *netdev)
 {
@@ -1197,40 +1095,6 @@ static void enic_tx_timeout(struct net_device *netdev)
 	schedule_work(&enic->reset);
 }
 
-static int enic_vnic_dev_deinit(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_deinit(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_init_prov(enic->vdev,
-		(u8 *)vp, vic_provinfo_size(vp));
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_init_done(struct enic *enic, int *done, int *error)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_init_done(enic->vdev, done, error);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 {
 	struct enic *enic = netdev_priv(netdev);
@@ -1262,6 +1126,8 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac)
 	if (err)
 		return err;
 
+	enic_reset_addr_lists(enic);
+
 	switch (enic->pp.request) {
 
 	case PORT_REQUEST_ASSOCIATE:
@@ -1318,18 +1184,20 @@ static int enic_set_port_profile(struct enic *enic, u8 *mac)
 		vic_provinfo_free(vp);
 		if (err)
 			return err;
-
-		enic->pp.set |= ENIC_SET_APPLIED;
 		break;
 
 	case PORT_REQUEST_DISASSOCIATE:
-		enic->pp.set &= ~ENIC_SET_APPLIED;
 		break;
 
 	default:
 		return -EINVAL;
 	}
 
+	/* Set flag to indicate that the port assoc/disassoc
+	 * request has been sent out to fw
+	 */
+	enic->pp.set |= ENIC_PORT_REQUEST_APPLIED;
+
 	return 0;
 }
 
@@ -1379,9 +1247,6 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
 
 		if (is_zero_ether_addr(netdev->dev_addr))
 			random_ether_addr(netdev->dev_addr);
-	} else if (new_pp.request == PORT_REQUEST_DISASSOCIATE) {
-		if (!is_zero_ether_addr(enic->pp.mac_addr))
-			enic_dev_del_addr(enic, enic->pp.mac_addr);
 	}
 
 	memcpy(&enic->pp, &new_pp, sizeof(struct enic_port_profile));
@@ -1390,9 +1255,6 @@ static int enic_set_vf_port(struct net_device *netdev, int vf,
 	if (err)
 		goto set_port_profile_cleanup;
 
-	if (!is_zero_ether_addr(enic->pp.mac_addr))
-		enic_dev_add_addr(enic, enic->pp.mac_addr);
-
 set_port_profile_cleanup:
 	memset(enic->pp.vf_mac, 0, ETH_ALEN);
 
@@ -1411,7 +1273,7 @@ static int enic_get_vf_port(struct net_device *netdev, int vf,
 	int err, error, done;
 	u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
 
-	if (!(enic->pp.set & ENIC_SET_APPLIED))
+	if (!(enic->pp.set & ENIC_PORT_REQUEST_APPLIED))
 		return -ENODATA;
 
 	err = enic_dev_init_done(enic, &done, &error);
@@ -1489,62 +1351,6 @@ static int enic_rq_alloc_buf(struct vnic_rq *rq)
 	return 0;
 }
 
-static int enic_rq_alloc_buf_a1(struct vnic_rq *rq)
-{
-	struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
-
-	if (vnic_rq_posting_soon(rq)) {
-
-		/* SW workaround for A0 HW erratum: if we're just about
-		 * to write posted_index, insert a dummy desc
-		 * of type resvd
-		 */
-
-		rq_enet_desc_enc(desc, 0, RQ_ENET_TYPE_RESV2, 0);
-		vnic_rq_post(rq, 0, 0, 0, 0);
-	} else {
-		return enic_rq_alloc_buf(rq);
-	}
-
-	return 0;
-}
-
-static int enic_dev_hw_version(struct enic *enic,
-	enum vnic_dev_hw_version *hw_ver)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_hw_version(enic->vdev, hw_ver);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_set_rq_alloc_buf(struct enic *enic)
-{
-	enum vnic_dev_hw_version hw_ver;
-	int err;
-
-	err = enic_dev_hw_version(enic, &hw_ver);
-	if (err)
-		return err;
-
-	switch (hw_ver) {
-	case VNIC_DEV_HW_VER_A1:
-		enic->rq_alloc_buf = enic_rq_alloc_buf_a1;
-		break;
-	case VNIC_DEV_HW_VER_A2:
-	case VNIC_DEV_HW_VER_UNKNOWN:
-		enic->rq_alloc_buf = enic_rq_alloc_buf;
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
 static void enic_rq_indicate_buf(struct vnic_rq *rq,
 	struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
 	int skipped, void *opaque)
@@ -1681,7 +1487,7 @@ static int enic_poll(struct napi_struct *napi, int budget)
 			0 /* don't unmask intr */,
 			0 /* don't reset intr timer */);
 
-	err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf);
+	err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
 
 	/* Buffer allocation failed. Stay in polling
 	 * mode so we can try to fill the ring again.
@@ -1731,7 +1537,7 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
 			0 /* don't unmask intr */,
 			0 /* don't reset intr timer */);
 
-	err = vnic_rq_fill(&enic->rq[rq], enic->rq_alloc_buf);
+	err = vnic_rq_fill(&enic->rq[rq], enic_rq_alloc_buf);
 
 	/* Buffer allocation failed. Stay in polling mode
 	 * so we can try to fill the ring again.
@@ -1901,39 +1707,6 @@ static int enic_dev_notify_set(struct enic *enic)
 	return err;
 }
 
-static int enic_dev_notify_unset(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_notify_unset(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_enable(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_enable_wait(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_disable(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_disable(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_notify_timer_start(struct enic *enic)
 {
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
@@ -1967,7 +1740,7 @@ static int enic_open(struct net_device *netdev)
 	}
 
 	for (i = 0; i < enic->rq_count; i++) {
-		vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf);
+		vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf);
 		/* Need at least one buffer on ring to get going */
 		if (vnic_rq_desc_used(&enic->rq[i]) == 0) {
 			netdev_err(netdev, "Unable to alloc receive buffers\n");
@@ -2285,29 +2058,6 @@ static int enic_set_rss_nic_cfg(struct enic *enic)
 		rss_hash_bits, rss_base_cpu, rss_enable);
 }
 
-static int enic_dev_hang_notify(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_hang_notify(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
-		IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_reset(struct work_struct *work)
 {
 	struct enic *enic = container_of(work, struct enic, reset);
@@ -2320,7 +2070,7 @@ static void enic_reset(struct work_struct *work)
 	enic_dev_hang_notify(enic);
 	enic_stop(enic->netdev);
 	enic_dev_hang_reset(enic);
-	enic_reset_multicast_list(enic);
+	enic_reset_addr_lists(enic);
 	enic_init_vnic_resources(enic);
 	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
@@ -2332,7 +2082,7 @@ static void enic_reset(struct work_struct *work)
 static int enic_set_intr_mode(struct enic *enic)
 {
 	unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX);
-	unsigned int m = 1;
+	unsigned int m = min_t(unsigned int, enic->wq_count, ENIC_WQ_MAX);
 	unsigned int i;
 
 	/* Set interrupt mode (INTx, MSI, MSI-X) depending
@@ -2475,9 +2225,7 @@ static const struct net_device_ops enic_netdev_dynamic_ops = {
 	.ndo_tx_timeout		= enic_tx_timeout,
 	.ndo_set_vf_port	= enic_set_vf_port,
 	.ndo_get_vf_port	= enic_get_vf_port,
-#ifdef IFLA_VF_MAX
 	.ndo_set_vf_mac		= enic_set_vf_mac,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= enic_poll_controller,
 #endif
@@ -2556,25 +2304,12 @@ static int enic_dev_init(struct enic *enic)
 
 	enic_init_vnic_resources(enic);
 
-	err = enic_set_rq_alloc_buf(enic);
-	if (err) {
-		dev_err(dev, "Failed to set RQ buffer allocator, aborting\n");
-		goto err_out_free_vnic_resources;
-	}
-
 	err = enic_set_rss_nic_cfg(enic);
 	if (err) {
 		dev_err(dev, "Failed to config nic, aborting\n");
 		goto err_out_free_vnic_resources;
 	}
 
-	err = enic_dev_set_ig_vlan_rewrite_mode(enic);
-	if (err) {
-		dev_err(dev,
-			"Failed to set ingress vlan rewrite mode, aborting.\n");
-		goto err_out_free_vnic_resources;
-	}
-
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	default:
 		netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
@@ -2713,6 +2448,22 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 		goto err_out_vnic_unregister;
 	}
 
+	/* Setup devcmd lock
+	 */
+
+	spin_lock_init(&enic->devcmd_lock);
+
+	/*
+	 * Set ingress vlan rewrite mode before vnic initialization
+	 */
+
+	err = enic_dev_set_ig_vlan_rewrite_mode(enic);
+	if (err) {
+		dev_err(dev,
+			"Failed to set ingress vlan rewrite mode, aborting.\n");
+		goto err_out_dev_close;
+	}
+
 	/* Issue device init to initialize the vnic-to-switch link.
 	 * We'll start with carrier off and wait for link UP
 	 * notification later to turn on carrier.  We don't need
@@ -2736,11 +2487,6 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 		}
 	}
 
-	/* Setup devcmd lock
-	 */
-
-	spin_lock_init(&enic->devcmd_lock);
-
 	err = enic_dev_init(enic);
 	if (err) {
 		dev_err(dev, "Device initialization failed, aborting\n");
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index fb35d8b..c089b36 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -408,10 +408,17 @@ int vnic_dev_fw_info(struct vnic_dev *vdev,
 		if (!vdev->fw_info)
 			return -ENOMEM;
 
+		memset(vdev->fw_info, 0, sizeof(struct vnic_devcmd_fw_info));
+
 		a0 = vdev->fw_info_pa;
+		a1 = sizeof(struct vnic_devcmd_fw_info);
 
 		/* only get fw_info once and cache it */
 		err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
+		if (err == ERR_ECMDUNKNOWN) {
+			err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO_OLD,
+				&a0, &a1, wait);
+		}
 	}
 
 	*fw_info = vdev->fw_info;
@@ -419,25 +426,6 @@ int vnic_dev_fw_info(struct vnic_dev *vdev,
 	return err;
 }
 
-int vnic_dev_hw_version(struct vnic_dev *vdev, enum vnic_dev_hw_version *hw_ver)
-{
-	struct vnic_devcmd_fw_info *fw_info;
-	int err;
-
-	err = vnic_dev_fw_info(vdev, &fw_info);
-	if (err)
-		return err;
-
-	if (strncmp(fw_info->hw_version, "A1", sizeof("A1")) == 0)
-		*hw_ver = VNIC_DEV_HW_VER_A1;
-	else if (strncmp(fw_info->hw_version, "A2", sizeof("A2")) == 0)
-		*hw_ver = VNIC_DEV_HW_VER_A2;
-	else
-		*hw_ver = VNIC_DEV_HW_VER_UNKNOWN;
-
-	return 0;
-}
-
 int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
 	void *value)
 {
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index 05f9a24..e837546 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -44,12 +44,6 @@ static inline void writeq(u64 val, void __iomem *reg)
 #undef pr_fmt
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-enum vnic_dev_hw_version {
-	VNIC_DEV_HW_VER_UNKNOWN,
-	VNIC_DEV_HW_VER_A1,
-	VNIC_DEV_HW_VER_A2,
-};
-
 enum vnic_dev_intr_mode {
 	VNIC_DEV_INTR_MODE_UNKNOWN,
 	VNIC_DEV_INTR_MODE_INTX,
@@ -93,8 +87,6 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
 	u64 *a0, u64 *a1, int wait);
 int vnic_dev_fw_info(struct vnic_dev *vdev,
 	struct vnic_devcmd_fw_info **fw_info);
-int vnic_dev_hw_version(struct vnic_dev *vdev,
-	enum vnic_dev_hw_version *hw_ver);
 int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
 	void *value);
 int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index 9abb3d5..d833a07 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -80,8 +80,34 @@
 enum vnic_devcmd_cmd {
 	CMD_NONE                = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_NONE, 0),
 
-	/* mcpu fw info in mem: (u64)a0=paddr to struct vnic_devcmd_fw_info */
-	CMD_MCPU_FW_INFO        = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1),
+	/*
+	 * mcpu fw info in mem:
+	 * in:
+	 *   (u64)a0=paddr to struct vnic_devcmd_fw_info
+	 * action:
+	 *   Fills in struct vnic_devcmd_fw_info (128 bytes)
+	 * note:
+	 *   An old definition of CMD_MCPU_FW_INFO
+	 */
+	CMD_MCPU_FW_INFO_OLD    = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1),
+
+	/*
+	 * mcpu fw info in mem:
+	 * in:
+	 *   (u64)a0=paddr to struct vnic_devcmd_fw_info
+	 *   (u16)a1=size of the structure
+	 * out:
+	 *	 (u16)a1=0                          for in:a1 = 0,
+	 *	         data size actually written for other values.
+	 * action:
+	 *   Fills in first 128 bytes of vnic_devcmd_fw_info for in:a1 = 0,
+	 *            first in:a1 bytes               for 0 < in:a1 <= 132,
+	 *            132 bytes                       for other values of in:a1.
+	 * note:
+	 *   CMD_MCPU_FW_INFO and CMD_MCPU_FW_INFO_OLD have the same enum 1
+	 *   for source compatibility.
+	 */
+	CMD_MCPU_FW_INFO        = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 1),
 
 	/* dev-specific block member:
 	 *    in: (u16)a0=offset,(u8)a1=size
@@ -291,11 +317,19 @@ enum vnic_devcmd_error {
 	ERR_EMAXRES = 10,
 };
 
+/*
+ * note: hw_version and asic_rev refer to the same thing,
+ *       but have different formats. hw_version is
+ *       a 32-byte string (e.g. "A2") and asic_rev is
+ *       a 16-bit integer (e.g. 0xA2).
+ */
 struct vnic_devcmd_fw_info {
 	char fw_version[32];
 	char fw_build[32];
 	char hw_version[32];
 	char hw_serial_number[32];
+	u16 asic_type;
+	u16 asic_rev;
 };
 
 struct vnic_devcmd_notify {
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h
index 37f08de..2056586 100644
--- a/drivers/net/enic/vnic_rq.h
+++ b/drivers/net/enic/vnic_rq.h
@@ -141,11 +141,6 @@ static inline void vnic_rq_post(struct vnic_rq *rq,
 	}
 }
 
-static inline int vnic_rq_posting_soon(struct vnic_rq *rq)
-{
-	return (rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0;
-}
-
 static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
 {
 	rq->ring.desc_avail += count;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 0cb1cf9..a59cf96 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -111,6 +111,8 @@
  * Sorry, I had to rewrite most of this for 2.5.x -DaveM
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -162,7 +164,7 @@ static void eql_timer(unsigned long param)
 }
 
 static const char version[] __initconst =
-	"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n";
+	"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)";
 
 static const struct net_device_ops eql_netdev_ops = {
 	.ndo_open	= eql_open,
@@ -204,8 +206,8 @@ static int eql_open(struct net_device *dev)
 	equalizer_t *eql = netdev_priv(dev);
 
 	/* XXX We should force this off automatically for the user. */
-	printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
-	       "your slave devices.\n", dev->name);
+	netdev_info(dev,
+		    "remember to turn off Van-Jacobson compression on your slave devices\n");
 
 	BUG_ON(!list_empty(&eql->queue.all_slaves));
 
@@ -591,7 +593,7 @@ static int __init eql_init_module(void)
 {
 	int err;
 
-	printk(version);
+	pr_info("%s\n", version);
 
 	dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup);
 	if (!dev_eql)
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index b79d7e1..db0290f 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -1163,15 +1163,11 @@ static int ethoc_resume(struct platform_device *pdev)
 # define ethoc_resume  NULL
 #endif
 
-#ifdef CONFIG_OF
 static struct of_device_id ethoc_match[] = {
-	{
-		.compatible = "opencores,ethoc",
-	},
+	{ .compatible = "opencores,ethoc", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ethoc_match);
-#endif
 
 static struct platform_driver ethoc_driver = {
 	.probe   = ethoc_probe,
@@ -1181,9 +1177,7 @@ static struct platform_driver ethoc_driver = {
 	.driver  = {
 		.name = "ethoc",
 		.owner = THIS_MODULE,
-#ifdef CONFIG_OF
 		.of_match_table = ethoc_match,
-#endif
 	},
 };
 
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index cd0282d..885d8ba 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -54,7 +54,7 @@
 
 #include "fec.h"
 
-#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+#if defined(CONFIG_ARM)
 #define FEC_ALIGNMENT	0xf
 #else
 #define FEC_ALIGNMENT	0x3
@@ -148,8 +148,7 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
  * account when setting it.
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
-    defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
 #define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
 #else
 #define	OPT_FRAME_SIZE	0
@@ -184,7 +183,7 @@ struct fec_enet_private {
 	struct bufdesc	*rx_bd_base;
 	struct bufdesc	*tx_bd_base;
 	/* The next free ring entry */
-	struct bufdesc	*cur_rx, *cur_tx; 
+	struct bufdesc	*cur_rx, *cur_tx;
 	/* The ring entries to be free()ed */
 	struct bufdesc	*dirty_tx;
 
@@ -192,28 +191,21 @@ struct fec_enet_private {
 	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
 	spinlock_t hw_lock;
 
-	struct  platform_device *pdev;
+	struct	platform_device *pdev;
 
 	int	opened;
 
 	/* Phylib and MDIO interface */
-	struct  mii_bus *mii_bus;
-	struct  phy_device *phy_dev;
-	int     mii_timeout;
-	uint    phy_speed;
+	struct	mii_bus *mii_bus;
+	struct	phy_device *phy_dev;
+	int	mii_timeout;
+	uint	phy_speed;
 	phy_interface_t	phy_interface;
 	int	link;
 	int	full_duplex;
 	struct	completion mdio_done;
 };
 
-static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
-static void fec_enet_tx(struct net_device *dev);
-static void fec_enet_rx(struct net_device *dev);
-static int fec_enet_close(struct net_device *dev);
-static void fec_restart(struct net_device *dev, int duplex);
-static void fec_stop(struct net_device *dev);
-
 /* FEC MII MMFR bits definition */
 #define FEC_MMFR_ST		(1 << 30)
 #define FEC_MMFR_OP_READ	(2 << 28)
@@ -240,9 +232,9 @@ static void *swap_buffer(void *bufaddr, int len)
 }
 
 static netdev_tx_t
-fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
@@ -263,9 +255,9 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (status & BD_ENET_TX_READY) {
 		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since dev->tbusy should be set.
+		 * This should not happen, since ndev->tbusy should be set.
 		 */
-		printk("%s: tx queue full!.\n", dev->name);
+		printk("%s: tx queue full!.\n", ndev->name);
 		spin_unlock_irqrestore(&fep->hw_lock, flags);
 		return NETDEV_TX_BUSY;
 	}
@@ -285,7 +277,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
 		unsigned int index;
 		index = bdp - fep->tx_bd_base;
-		memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
+		memcpy(fep->tx_bounce[index], skb->data, skb->len);
 		bufaddr = fep->tx_bounce[index];
 	}
 
@@ -300,13 +292,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Save skb pointer */
 	fep->tx_skbuff[fep->skb_cur] = skb;
 
-	dev->stats.tx_bytes += skb->len;
+	ndev->stats.tx_bytes += skb->len;
 	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
 
 	/* Push the data cache so the CPM does not get stale memory
 	 * data.
 	 */
-	bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
+	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,
@@ -327,7 +319,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (bdp == fep->dirty_tx) {
 		fep->tx_full = 1;
-		netif_stop_queue(dev);
+		netif_stop_queue(ndev);
 	}
 
 	fep->cur_tx = bdp;
@@ -337,62 +329,170 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	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_timeout(struct net_device *dev)
+fec_restart(struct net_device *ndev, int duplex)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	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;
 
-	dev->stats.tx_errors++;
+	/* Whack a reset.  We should wait for this. */
+	writel(1, fep->hwp + FEC_ECNTRL);
+	udelay(10);
 
-	fec_restart(dev, fep->full_duplex);
-	netif_wake_queue(dev);
-}
+	/*
+	 * 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);
+	}
 
-static irqreturn_t
-fec_enet_interrupt(int irq, void * dev_id)
-{
-	struct	net_device *dev = dev_id;
-	struct fec_enet_private *fep = netdev_priv(dev);
-	uint	int_events;
-	irqreturn_t ret = IRQ_NONE;
+	/* Clear any outstanding interrupt. */
+	writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
-	do {
-		int_events = readl(fep->hwp + FEC_IEVENT);
-		writel(int_events, 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
 
-		if (int_events & FEC_ENET_RXF) {
-			ret = IRQ_HANDLED;
-			fec_enet_rx(dev);
-		}
+	/* Set maximum receive buffer size. */
+	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
-		/* Transmit OK, or non-fatal error. Update the buffer
-		 * descriptors. FEC handles all errors, we just discover
-		 * them as part of the transmit process.
-		 */
-		if (int_events & FEC_ENET_TXF) {
-			ret = IRQ_HANDLED;
-			fec_enet_tx(dev);
+	/* Set receive and transmit descriptor base. */
+	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
+	writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
+			fep->hwp + FEC_X_DES_START);
+
+	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+	fep->cur_rx = fep->rx_bd_base;
+
+	/* Reset SKB transmit buffers. */
+	fep->skb_cur = fep->skb_dirty = 0;
+	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;
 		}
+	}
 
-		if (int_events & FEC_ENET_MII) {
-			ret = IRQ_HANDLED;
-			complete(&fep->mdio_done);
+	/* 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;
+
+		/* MII or RMII */
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+			rcntl |= (1 << 8);
+		else
+			rcntl &= ~(1 << 8);
+
+		/* 10M or 100M */
+		if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
+			rcntl &= ~(1 << 9);
+		else
+			rcntl |= (1 << 9);
+
+	} else {
+#ifdef FEC_MIIGSK_ENR
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
+			/* 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
+			 */
+			writel(1, fep->hwp + FEC_MIIGSK_CFGR);
+
+			/* re-enable the gasket */
+			writel(2, fep->hwp + FEC_MIIGSK_ENR);
 		}
-	} while (int_events);
+#endif
+	}
+	writel(rcntl, fep->hwp + FEC_R_CNTRL);
 
-	return ret;
+	/* And last, enable the transmit and receive processing */
+	writel(2, fep->hwp + FEC_ECNTRL);
+	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+
+	/* 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);
+
+	/* 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);
 }
 
 
 static void
-fec_enet_tx(struct net_device *dev)
+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;
 
-	fep = netdev_priv(dev);
+	fep = netdev_priv(ndev);
 	spin_lock(&fep->hw_lock);
 	bdp = fep->dirty_tx;
 
@@ -400,7 +500,8 @@ fec_enet_tx(struct net_device *dev)
 		if (bdp == fep->cur_tx && fep->tx_full == 0)
 			break;
 
-		dma_unmap_single(&dev->dev, bdp->cbd_bufaddr, FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 
 		skb = fep->tx_skbuff[fep->skb_dirty];
@@ -408,19 +509,19 @@ fec_enet_tx(struct net_device *dev)
 		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
 				   BD_ENET_TX_RL | BD_ENET_TX_UN |
 				   BD_ENET_TX_CSL)) {
-			dev->stats.tx_errors++;
+			ndev->stats.tx_errors++;
 			if (status & BD_ENET_TX_HB)  /* No heartbeat */
-				dev->stats.tx_heartbeat_errors++;
+				ndev->stats.tx_heartbeat_errors++;
 			if (status & BD_ENET_TX_LC)  /* Late collision */
-				dev->stats.tx_window_errors++;
+				ndev->stats.tx_window_errors++;
 			if (status & BD_ENET_TX_RL)  /* Retrans limit */
-				dev->stats.tx_aborted_errors++;
+				ndev->stats.tx_aborted_errors++;
 			if (status & BD_ENET_TX_UN)  /* Underrun */
-				dev->stats.tx_fifo_errors++;
+				ndev->stats.tx_fifo_errors++;
 			if (status & BD_ENET_TX_CSL) /* Carrier lost */
-				dev->stats.tx_carrier_errors++;
+				ndev->stats.tx_carrier_errors++;
 		} else {
-			dev->stats.tx_packets++;
+			ndev->stats.tx_packets++;
 		}
 
 		if (status & BD_ENET_TX_READY)
@@ -430,7 +531,7 @@ fec_enet_tx(struct net_device *dev)
 		 * but we eventually sent the packet OK.
 		 */
 		if (status & BD_ENET_TX_DEF)
-			dev->stats.collisions++;
+			ndev->stats.collisions++;
 
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
@@ -447,8 +548,8 @@ fec_enet_tx(struct net_device *dev)
 		 */
 		if (fep->tx_full) {
 			fep->tx_full = 0;
-			if (netif_queue_stopped(dev))
-				netif_wake_queue(dev);
+			if (netif_queue_stopped(ndev))
+				netif_wake_queue(ndev);
 		}
 	}
 	fep->dirty_tx = bdp;
@@ -462,9 +563,9 @@ fec_enet_tx(struct net_device *dev)
  * effectively tossing the packet.
  */
 static void
-fec_enet_rx(struct net_device *dev)
+fec_enet_rx(struct net_device *ndev)
 {
-	struct	fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
@@ -498,17 +599,17 @@ fec_enet_rx(struct net_device *dev)
 		/* 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)) {
-			dev->stats.rx_errors++;
+			ndev->stats.rx_errors++;
 			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
 				/* Frame too long or too short. */
-				dev->stats.rx_length_errors++;
+				ndev->stats.rx_length_errors++;
 			}
 			if (status & BD_ENET_RX_NO)	/* Frame alignment */
-				dev->stats.rx_frame_errors++;
+				ndev->stats.rx_frame_errors++;
 			if (status & BD_ENET_RX_CR)	/* CRC Error */
-				dev->stats.rx_crc_errors++;
+				ndev->stats.rx_crc_errors++;
 			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-				dev->stats.rx_fifo_errors++;
+				ndev->stats.rx_fifo_errors++;
 		}
 
 		/* Report late collisions as a frame error.
@@ -516,19 +617,19 @@ fec_enet_rx(struct net_device *dev)
 		 * have in the buffer.  So, just drop this frame on the floor.
 		 */
 		if (status & BD_ENET_RX_CL) {
-			dev->stats.rx_errors++;
-			dev->stats.rx_frame_errors++;
+			ndev->stats.rx_errors++;
+			ndev->stats.rx_frame_errors++;
 			goto rx_processing_done;
 		}
 
 		/* Process the incoming frame. */
-		dev->stats.rx_packets++;
+		ndev->stats.rx_packets++;
 		pkt_len = bdp->cbd_datlen;
-		dev->stats.rx_bytes += pkt_len;
+		ndev->stats.rx_bytes += pkt_len;
 		data = (__u8*)__va(bdp->cbd_bufaddr);
 
-	        dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
-        			DMA_FROM_DEVICE);
+		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);
@@ -542,18 +643,18 @@ fec_enet_rx(struct net_device *dev)
 
 		if (unlikely(!skb)) {
 			printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-			dev->stats.rx_dropped++;
+					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, dev);
+			skb->protocol = eth_type_trans(skb, ndev);
 			netif_rx(skb);
 		}
 
-        	bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
-			DMA_FROM_DEVICE);
+		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;
@@ -578,10 +679,47 @@ rx_processing_done:
 	spin_unlock(&fep->hw_lock);
 }
 
+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) {
+			ret = IRQ_HANDLED;
+			fec_enet_rx(ndev);
+		}
+
+		/* Transmit OK, or non-fatal error. Update the buffer
+		 * descriptors. FEC handles all errors, we just discover
+		 * them as part of the transmit process.
+		 */
+		if (int_events & FEC_ENET_TXF) {
+			ret = IRQ_HANDLED;
+			fec_enet_tx(ndev);
+		}
+
+		if (int_events & FEC_ENET_MII) {
+			ret = IRQ_HANDLED;
+			complete(&fep->mdio_done);
+		}
+	} while (int_events);
+
+	return ret;
+}
+
+
+
 /* ------------------------------------------------------------------------- */
-static void __inline__ fec_get_mac(struct net_device *dev)
+static void __inline__ fec_get_mac(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
@@ -617,11 +755,11 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 		iap = &tmpaddr[0];
 	}
 
-	memcpy(dev->dev_addr, iap, ETH_ALEN);
+	memcpy(ndev->dev_addr, iap, ETH_ALEN);
 
 	/* Adjust MAC if using macaddr */
 	if (iap == macaddr)
-		 dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
+		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -629,9 +767,9 @@ static void __inline__ fec_get_mac(struct net_device *dev)
 /*
  * Phy section
  */
-static void fec_enet_adjust_link(struct net_device *dev)
+static void fec_enet_adjust_link(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = fep->phy_dev;
 	unsigned long flags;
 
@@ -648,7 +786,7 @@ static void fec_enet_adjust_link(struct net_device *dev)
 	/* Duplex link change */
 	if (phy_dev->link) {
 		if (fep->full_duplex != phy_dev->duplex) {
-			fec_restart(dev, phy_dev->duplex);
+			fec_restart(ndev, phy_dev->duplex);
 			status_change = 1;
 		}
 	}
@@ -657,9 +795,9 @@ static void fec_enet_adjust_link(struct net_device *dev)
 	if (phy_dev->link != fep->link) {
 		fep->link = phy_dev->link;
 		if (phy_dev->link)
-			fec_restart(dev, phy_dev->duplex);
+			fec_restart(ndev, phy_dev->duplex);
 		else
-			fec_stop(dev);
+			fec_stop(ndev);
 		status_change = 1;
 	}
 
@@ -728,9 +866,9 @@ static int fec_enet_mdio_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static int fec_enet_mii_probe(struct net_device *dev)
+static int fec_enet_mii_probe(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = NULL;
 	char mdio_bus_id[MII_BUS_ID_SIZE];
 	char phy_name[MII_BUS_ID_SIZE + 3];
@@ -755,16 +893,16 @@ static int fec_enet_mii_probe(struct net_device *dev)
 
 	if (phy_id >= PHY_MAX_ADDR) {
 		printk(KERN_INFO "%s: no PHY, assuming direct connection "
-			"to switch\n", dev->name);
+			"to switch\n", ndev->name);
 		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
 		phy_id = 0;
 	}
 
 	snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
-	phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0,
+	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
 		PHY_INTERFACE_MODE_MII);
 	if (IS_ERR(phy_dev)) {
-		printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
 		return PTR_ERR(phy_dev);
 	}
 
@@ -777,7 +915,7 @@ static int fec_enet_mii_probe(struct net_device *dev)
 	fep->full_duplex = 0;
 
 	printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
-		"(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
+		"(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);
 
@@ -787,8 +925,8 @@ static int fec_enet_mii_probe(struct net_device *dev)
 static int fec_enet_mii_init(struct platform_device *pdev)
 {
 	static struct mii_bus *fec0_mii_bus;
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct fec_enet_private *fep = netdev_priv(dev);
+	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;
@@ -846,8 +984,6 @@ static int fec_enet_mii_init(struct platform_device *pdev)
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		fep->mii_bus->irq[i] = PHY_POLL;
 
-	platform_set_drvdata(dev, fep->mii_bus);
-
 	if (mdiobus_register(fep->mii_bus))
 		goto err_out_free_mdio_irq;
 
@@ -874,10 +1010,10 @@ static void fec_enet_mii_remove(struct fec_enet_private *fep)
 	mdiobus_free(fep->mii_bus);
 }
 
-static int fec_enet_get_settings(struct net_device *dev,
+static int fec_enet_get_settings(struct net_device *ndev,
 				  struct ethtool_cmd *cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
 	if (!phydev)
@@ -886,10 +1022,10 @@ static int fec_enet_get_settings(struct net_device *dev,
 	return phy_ethtool_gset(phydev, cmd);
 }
 
-static int fec_enet_set_settings(struct net_device *dev,
+static int fec_enet_set_settings(struct net_device *ndev,
 				 struct ethtool_cmd *cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
 	if (!phydev)
@@ -898,14 +1034,14 @@ static int fec_enet_set_settings(struct net_device *dev,
 	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void fec_enet_get_drvinfo(struct net_device *dev,
+static void fec_enet_get_drvinfo(struct net_device *ndev,
 				 struct ethtool_drvinfo *info)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	strcpy(info->driver, fep->pdev->dev.driver->name);
 	strcpy(info->version, "Revision: 1.0");
-	strcpy(info->bus_info, dev_name(&dev->dev));
+	strcpy(info->bus_info, dev_name(&ndev->dev));
 }
 
 static struct ethtool_ops fec_enet_ethtool_ops = {
@@ -915,12 +1051,12 @@ static struct ethtool_ops fec_enet_ethtool_ops = {
 	.get_link		= ethtool_op_get_link,
 };
 
-static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
-	if (!netif_running(dev))
+	if (!netif_running(ndev))
 		return -EINVAL;
 
 	if (!phydev)
@@ -929,9 +1065,9 @@ static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
-static void fec_enet_free_buffers(struct net_device *dev)
+static void fec_enet_free_buffers(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
 	struct bufdesc	*bdp;
@@ -941,7 +1077,7 @@ static void fec_enet_free_buffers(struct net_device *dev)
 		skb = fep->rx_skbuff[i];
 
 		if (bdp->cbd_bufaddr)
-			dma_unmap_single(&dev->dev, 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);
@@ -953,9 +1089,9 @@ static void fec_enet_free_buffers(struct net_device *dev)
 		kfree(fep->tx_bounce[i]);
 }
 
-static int fec_enet_alloc_buffers(struct net_device *dev)
+static int fec_enet_alloc_buffers(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
 	struct bufdesc	*bdp;
@@ -964,12 +1100,12 @@ static int fec_enet_alloc_buffers(struct net_device *dev)
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
 		if (!skb) {
-			fec_enet_free_buffers(dev);
+			fec_enet_free_buffers(ndev);
 			return -ENOMEM;
 		}
 		fep->rx_skbuff[i] = skb;
 
-		bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+		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;
 		bdp++;
@@ -996,45 +1132,47 @@ static int fec_enet_alloc_buffers(struct net_device *dev)
 }
 
 static int
-fec_enet_open(struct net_device *dev)
+fec_enet_open(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int ret;
 
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
 
-	ret = fec_enet_alloc_buffers(dev);
+	ret = fec_enet_alloc_buffers(ndev);
 	if (ret)
 		return ret;
 
 	/* Probe and connect to PHY when open the interface */
-	ret = fec_enet_mii_probe(dev);
+	ret = fec_enet_mii_probe(ndev);
 	if (ret) {
-		fec_enet_free_buffers(dev);
+		fec_enet_free_buffers(ndev);
 		return ret;
 	}
 	phy_start(fep->phy_dev);
-	netif_start_queue(dev);
+	netif_start_queue(ndev);
 	fep->opened = 1;
 	return 0;
 }
 
 static int
-fec_enet_close(struct net_device *dev)
+fec_enet_close(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	/* Don't know what to do yet. */
 	fep->opened = 0;
-	netif_stop_queue(dev);
-	fec_stop(dev);
+	netif_stop_queue(ndev);
+	fec_stop(ndev);
 
-	if (fep->phy_dev)
+	if (fep->phy_dev) {
+		phy_stop(fep->phy_dev);
 		phy_disconnect(fep->phy_dev);
+	}
 
-        fec_enet_free_buffers(dev);
+	fec_enet_free_buffers(ndev);
 
 	return 0;
 }
@@ -1052,14 +1190,14 @@ fec_enet_close(struct net_device *dev)
 #define HASH_BITS	6		/* #bits in hash */
 #define CRC32_POLY	0xEDB88320
 
-static void set_multicast_list(struct net_device *dev)
+static void set_multicast_list(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct netdev_hw_addr *ha;
 	unsigned int i, bit, data, crc, tmp;
 	unsigned char hash;
 
-	if (dev->flags & IFF_PROMISC) {
+	if (ndev->flags & IFF_PROMISC) {
 		tmp = readl(fep->hwp + FEC_R_CNTRL);
 		tmp |= 0x8;
 		writel(tmp, fep->hwp + FEC_R_CNTRL);
@@ -1070,7 +1208,7 @@ static void set_multicast_list(struct net_device *dev)
 	tmp &= ~0x8;
 	writel(tmp, fep->hwp + FEC_R_CNTRL);
 
-	if (dev->flags & IFF_ALLMULTI) {
+	if (ndev->flags & IFF_ALLMULTI) {
 		/* Catch all multicast addresses, so set the
 		 * filter to all 1's
 		 */
@@ -1085,7 +1223,7 @@ static void set_multicast_list(struct net_device *dev)
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
-	netdev_for_each_mc_addr(ha, dev) {
+	netdev_for_each_mc_addr(ha, ndev) {
 		/* Only support group multicast for now */
 		if (!(ha->addr[0] & 1))
 			continue;
@@ -1093,7 +1231,7 @@ static void set_multicast_list(struct net_device *dev)
 		/* calculate crc32 value of mac address */
 		crc = 0xffffffff;
 
-		for (i = 0; i < dev->addr_len; i++) {
+		for (i = 0; i < ndev->addr_len; i++) {
 			data = ha->addr[i];
 			for (bit = 0; bit < 8; bit++, data >>= 1) {
 				crc = (crc >> 1) ^
@@ -1120,20 +1258,20 @@ static void set_multicast_list(struct net_device *dev)
 
 /* Set a MAC change in hardware. */
 static int
-fec_set_mac_address(struct net_device *dev, void *p)
+fec_set_mac_address(struct net_device *ndev, void *p)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct sockaddr *addr = p;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
 
-	writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
-		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
+	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((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
+	writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24),
 		fep->hwp + FEC_ADDR_HIGH);
 	return 0;
 }
@@ -1147,16 +1285,16 @@ static const struct net_device_ops fec_netdev_ops = {
 	.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,
+	.ndo_do_ioctl		= fec_enet_ioctl,
 };
 
  /*
   * XXX:  We need to clean up on failure exits here.
   *
   */
-static int fec_enet_init(struct net_device *dev)
+static int fec_enet_init(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct bufdesc *cbd_base;
 	struct bufdesc *bdp;
 	int i;
@@ -1171,20 +1309,19 @@ static int fec_enet_init(struct net_device *dev)
 
 	spin_lock_init(&fep->hw_lock);
 
-	fep->hwp = (void __iomem *)dev->base_addr;
-	fep->netdev = dev;
+	fep->netdev = ndev;
 
 	/* Get the Ethernet address */
-	fec_get_mac(dev);
+	fec_get_mac(ndev);
 
 	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
 	fep->tx_bd_base = cbd_base + RX_RING_SIZE;
 
 	/* The FEC Ethernet specific entries in the device structure */
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->netdev_ops = &fec_netdev_ops;
-	dev->ethtool_ops = &fec_enet_ethtool_ops;
+	ndev->watchdog_timeo = TX_TIMEOUT;
+	ndev->netdev_ops = &fec_netdev_ops;
+	ndev->ethtool_ops = &fec_enet_ethtool_ops;
 
 	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
@@ -1213,152 +1350,11 @@ static int fec_enet_init(struct net_device *dev)
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
-	fec_restart(dev, 0);
+	fec_restart(ndev, 0);
 
 	return 0;
 }
 
-/* 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 *dev, int duplex)
-{
-	struct fec_enet_private *fep = netdev_priv(dev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	int i;
-	u32 val, temp_mac[2];
-
-	/* 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, dev->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);
-	writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
-			fep->hwp + FEC_X_DES_START);
-
-	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
-	fep->cur_rx = fep->rx_bd_base;
-
-	/* Reset SKB transmit buffers. */
-	fep->skb_cur = fep->skb_dirty = 0;
-	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) {
-		/* MII enable / FD enable */
-		writel(OPT_FRAME_SIZE | 0x04, fep->hwp + FEC_R_CNTRL);
-		writel(0x04, fep->hwp + FEC_X_CNTRL);
-	} else {
-		/* MII enable / No Rcv on Xmit */
-		writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL);
-		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) {
-		val = readl(fep->hwp + FEC_R_CNTRL);
-
-		/* MII or RMII */
-		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
-			val |= (1 << 8);
-		else
-			val &= ~(1 << 8);
-
-		/* 10M or 100M */
-		if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
-			val &= ~(1 << 9);
-		else
-			val |= (1 << 9);
-
-		writel(val, fep->hwp + FEC_R_CNTRL);
-	} else {
-#ifdef FEC_MIIGSK_ENR
-		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
-			/* 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
-			 */
-			writel(1, fep->hwp + FEC_MIIGSK_CFGR);
-
-			/* re-enable the gasket */
-			writel(2, fep->hwp + FEC_MIIGSK_ENR);
-		}
-#endif
-	}
-
-	/* And last, enable the transmit and receive processing */
-	writel(2, fep->hwp + FEC_ECNTRL);
-	writel(0, fep->hwp + FEC_R_DES_ACTIVE);
-
-	/* Enable interrupts we wish to service */
-	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-}
-
-static void
-fec_stop(struct net_device *dev)
-{
-	struct fec_enet_private *fep = netdev_priv(dev);
-
-	/* 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);
-}
-
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1378,19 +1374,20 @@ fec_probe(struct platform_device *pdev)
 
 	/* Init network device */
 	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
-	if (!ndev)
-		return -ENOMEM;
+	if (!ndev) {
+		ret = -ENOMEM;
+		goto failed_alloc_etherdev;
+	}
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	/* setup board info structure */
 	fep = netdev_priv(ndev);
-	memset(fep, 0, sizeof(*fep));
 
-	ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r));
+	fep->hwp = ioremap(r->start, resource_size(r));
 	fep->pdev = pdev;
 
-	if (!ndev->base_addr) {
+	if (!fep->hwp) {
 		ret = -ENOMEM;
 		goto failed_ioremap;
 	}
@@ -1408,10 +1405,9 @@ fec_probe(struct platform_device *pdev)
 			break;
 		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
 		if (ret) {
-			while (i >= 0) {
+			while (--i >= 0) {
 				irq = platform_get_irq(pdev, i);
 				free_irq(irq, ndev);
-				i--;
 			}
 			goto failed_irq;
 		}
@@ -1454,9 +1450,11 @@ failed_clk:
 			free_irq(irq, ndev);
 	}
 failed_irq:
-	iounmap((void __iomem *)ndev->base_addr);
+	iounmap(fep->hwp);
 failed_ioremap:
 	free_netdev(ndev);
+failed_alloc_etherdev:
+	release_mem_region(r->start, resource_size(r));
 
 	return ret;
 }
@@ -1466,16 +1464,22 @@ fec_drv_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	platform_set_drvdata(pdev, NULL);
+	struct resource *r;
 
 	fec_stop(ndev);
 	fec_enet_mii_remove(fep);
 	clk_disable(fep->clk);
 	clk_put(fep->clk);
-	iounmap((void __iomem *)ndev->base_addr);
+	iounmap(fep->hwp);
 	unregister_netdev(ndev);
 	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;
 }
 
@@ -1484,16 +1488,14 @@ static int
 fec_suspend(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	if (ndev) {
-		fep = netdev_priv(ndev);
-		if (netif_running(ndev)) {
-			fec_stop(ndev);
-			netif_device_detach(ndev);
-		}
-		clk_disable(fep->clk);
+	if (netif_running(ndev)) {
+		fec_stop(ndev);
+		netif_device_detach(ndev);
 	}
+	clk_disable(fep->clk);
+
 	return 0;
 }
 
@@ -1501,16 +1503,14 @@ static int
 fec_resume(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	if (ndev) {
-		fep = netdev_priv(ndev);
-		clk_enable(fep->clk);
-		if (netif_running(ndev)) {
-			fec_restart(ndev, fep->full_duplex);
-			netif_device_attach(ndev);
-		}
+	clk_enable(fep->clk);
+	if (netif_running(ndev)) {
+		fec_restart(ndev, fep->full_duplex);
+		netif_device_attach(ndev);
 	}
+
 	return 0;
 }
 
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index 50c1213..9f81b1a 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -840,8 +840,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
 /* OF Driver                                                                */
 /* ======================================================================== */
 
-static int __devinit
-mpc52xx_fec_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit mpc52xx_fec_probe(struct platform_device *op)
 {
 	int rv;
 	struct net_device *ndev;
@@ -1049,7 +1048,7 @@ static struct of_device_id mpc52xx_fec_match[] = {
 
 MODULE_DEVICE_TABLE(of, mpc52xx_fec_match);
 
-static struct of_platform_driver mpc52xx_fec_driver = {
+static struct platform_driver mpc52xx_fec_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1073,21 +1072,21 @@ mpc52xx_fec_init(void)
 {
 #ifdef CONFIG_FEC_MPC52xx_MDIO
 	int ret;
-	ret = of_register_platform_driver(&mpc52xx_fec_mdio_driver);
+	ret = platform_driver_register(&mpc52xx_fec_mdio_driver);
 	if (ret) {
 		printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n");
 		return ret;
 	}
 #endif
-	return of_register_platform_driver(&mpc52xx_fec_driver);
+	return platform_driver_register(&mpc52xx_fec_driver);
 }
 
 static void __exit
 mpc52xx_fec_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_fec_driver);
+	platform_driver_unregister(&mpc52xx_fec_driver);
 #ifdef CONFIG_FEC_MPC52xx_MDIO
-	of_unregister_platform_driver(&mpc52xx_fec_mdio_driver);
+	platform_driver_unregister(&mpc52xx_fec_mdio_driver);
 #endif
 }
 
diff --git a/drivers/net/fec_mpc52xx.h b/drivers/net/fec_mpc52xx.h
index a227a52..41d2dff 100644
--- a/drivers/net/fec_mpc52xx.h
+++ b/drivers/net/fec_mpc52xx.h
@@ -289,6 +289,6 @@ struct mpc52xx_fec {
 #define FEC_XMIT_FSM_ENABLE_CRC		0x01000000
 
 
-extern struct of_platform_driver mpc52xx_fec_mdio_driver;
+extern struct platform_driver mpc52xx_fec_mdio_driver;
 
 #endif	/* __DRIVERS_NET_MPC52XX_FEC_H__ */
diff --git a/drivers/net/fec_mpc52xx_phy.c b/drivers/net/fec_mpc52xx_phy.c
index 0b4cb6f..360a578 100644
--- a/drivers/net/fec_mpc52xx_phy.c
+++ b/drivers/net/fec_mpc52xx_phy.c
@@ -61,8 +61,7 @@ static int mpc52xx_fec_mdio_write(struct mii_bus *bus, int phy_id, int reg,
 		data | FEC_MII_WRITE_FRAME);
 }
 
-static int mpc52xx_fec_mdio_probe(struct platform_device *of,
-		const struct of_device_id *match)
+static int mpc52xx_fec_mdio_probe(struct platform_device *of)
 {
 	struct device *dev = &of->dev;
 	struct device_node *np = of->dev.of_node;
@@ -145,7 +144,7 @@ static struct of_device_id mpc52xx_fec_mdio_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mpc52xx_fec_mdio_match);
 
-struct of_platform_driver mpc52xx_fec_mdio_driver = {
+struct platform_driver mpc52xx_fec_mdio_driver = {
 	.driver = {
 		.name = "mpc5200b-fec-phy",
 		.owner = THIS_MODULE,
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 9c0b1ba..7b92897 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -5744,7 +5744,7 @@ static void __devexit nv_remove(struct pci_dev *pci_dev)
 	pci_set_drvdata(pci_dev, NULL);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int nv_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
@@ -5795,6 +5795,11 @@ static int nv_resume(struct device *device)
 static SIMPLE_DEV_PM_OPS(nv_pm_ops, nv_suspend, nv_resume);
 #define NV_PM_OPS (&nv_pm_ops)
 
+#else
+#define NV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
 static void nv_shutdown(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -5822,7 +5827,6 @@ static void nv_shutdown(struct pci_dev *pdev)
 	}
 }
 #else
-#define NV_PM_OPS NULL
 #define nv_shutdown NULL
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 7a1f3d0..24cb953 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -998,8 +998,7 @@ static const struct net_device_ops fs_enet_netdev_ops = {
 #endif
 };
 
-static int __devinit fs_enet_probe(struct platform_device *ofdev,
-                                   const struct of_device_id *match)
+static int __devinit fs_enet_probe(struct platform_device *ofdev)
 {
 	struct net_device *ndev;
 	struct fs_enet_private *fep;
@@ -1008,11 +1007,14 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev,
 	const u8 *mac_addr;
 	int privsize, len, ret = -ENODEV;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+
 	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
 	if (!fpi)
 		return -ENOMEM;
 
-	if (!IS_FEC(match)) {
+	if (!IS_FEC(ofdev->dev.of_match)) {
 		data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len);
 		if (!data || len != 4)
 			goto out_free_fpi;
@@ -1047,7 +1049,7 @@ static int __devinit fs_enet_probe(struct platform_device *ofdev,
 	fep->dev = &ofdev->dev;
 	fep->ndev = ndev;
 	fep->fpi = fpi;
-	fep->ops = match->data;
+	fep->ops = ofdev->dev.of_match->data;
 
 	ret = fep->ops->setup_data(ndev);
 	if (ret)
@@ -1156,7 +1158,7 @@ static struct of_device_id fs_enet_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fs_enet_match);
 
-static struct of_platform_driver fs_enet_driver = {
+static struct platform_driver fs_enet_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "fs_enet",
@@ -1168,12 +1170,12 @@ static struct of_platform_driver fs_enet_driver = {
 
 static int __init fs_init(void)
 {
-	return of_register_platform_driver(&fs_enet_driver);
+	return platform_driver_register(&fs_enet_driver);
 }
 
 static void __exit fs_cleanup(void)
 {
-	of_unregister_platform_driver(&fs_enet_driver);
+	platform_driver_unregister(&fs_enet_driver);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/fs_enet/mii-bitbang.c b/drivers/net/fs_enet/mii-bitbang.c
index 3cda2b5..ad29754 100644
--- a/drivers/net/fs_enet/mii-bitbang.c
+++ b/drivers/net/fs_enet/mii-bitbang.c
@@ -150,8 +150,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
 	return 0;
 }
 
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 {
 	struct mii_bus *new_bus;
 	struct bb_info *bitbang;
@@ -223,7 +222,7 @@ static struct of_device_id fs_enet_mdio_bb_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fs_enet_mdio_bb_match);
 
-static struct of_platform_driver fs_enet_bb_mdio_driver = {
+static struct platform_driver fs_enet_bb_mdio_driver = {
 	.driver = {
 		.name = "fsl-bb-mdio",
 		.owner = THIS_MODULE,
@@ -235,12 +234,12 @@ static struct of_platform_driver fs_enet_bb_mdio_driver = {
 
 static int fs_enet_mdio_bb_init(void)
 {
-	return of_register_platform_driver(&fs_enet_bb_mdio_driver);
+	return platform_driver_register(&fs_enet_bb_mdio_driver);
 }
 
 static void fs_enet_mdio_bb_exit(void)
 {
-	of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
+	platform_driver_unregister(&fs_enet_bb_mdio_driver);
 }
 
 module_init(fs_enet_mdio_bb_init);
diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c
index dbb9c48..7e840d3 100644
--- a/drivers/net/fs_enet/mii-fec.c
+++ b/drivers/net/fs_enet/mii-fec.c
@@ -101,15 +101,18 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
 	return 0;
 }
 
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 {
 	struct resource res;
 	struct mii_bus *new_bus;
 	struct fec_info *fec;
-	int (*get_bus_freq)(struct device_node *) = match->data;
+	int (*get_bus_freq)(struct device_node *);
 	int ret = -ENOMEM, clock, speed;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+	get_bus_freq = ofdev->dev.of_match->data;
+
 	new_bus = mdiobus_alloc();
 	if (!new_bus)
 		goto out;
@@ -221,7 +224,7 @@ static struct of_device_id fs_enet_mdio_fec_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fs_enet_mdio_fec_match);
 
-static struct of_platform_driver fs_enet_fec_mdio_driver = {
+static struct platform_driver fs_enet_fec_mdio_driver = {
 	.driver = {
 		.name = "fsl-fec-mdio",
 		.owner = THIS_MODULE,
@@ -233,12 +236,12 @@ static struct of_platform_driver fs_enet_fec_mdio_driver = {
 
 static int fs_enet_mdio_fec_init(void)
 {
-	return of_register_platform_driver(&fs_enet_fec_mdio_driver);
+	return platform_driver_register(&fs_enet_fec_mdio_driver);
 }
 
 static void fs_enet_mdio_fec_exit(void)
 {
-	of_unregister_platform_driver(&fs_enet_fec_mdio_driver);
+	platform_driver_unregister(&fs_enet_fec_mdio_driver);
 }
 
 module_init(fs_enet_mdio_fec_init);
diff --git a/drivers/net/fsl_pq_mdio.c b/drivers/net/fsl_pq_mdio.c
index 8d3a2cc..52f4e8a 100644
--- a/drivers/net/fsl_pq_mdio.c
+++ b/drivers/net/fsl_pq_mdio.c
@@ -265,8 +265,7 @@ static int get_ucc_id_for_range(u64 start, u64 end, u32 *ucc_id)
 #endif
 
 
-static int fsl_pq_mdio_probe(struct platform_device *ofdev,
-		const struct of_device_id *match)
+static int fsl_pq_mdio_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct device_node *tbi;
@@ -471,7 +470,7 @@ static struct of_device_id fsl_pq_mdio_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);
 
-static struct of_platform_driver fsl_pq_mdio_driver = {
+static struct platform_driver fsl_pq_mdio_driver = {
 	.driver = {
 		.name = "fsl-pq_mdio",
 		.owner = THIS_MODULE,
@@ -483,13 +482,13 @@ static struct of_platform_driver fsl_pq_mdio_driver = {
 
 int __init fsl_pq_mdio_init(void)
 {
-	return of_register_platform_driver(&fsl_pq_mdio_driver);
+	return platform_driver_register(&fsl_pq_mdio_driver);
 }
 module_init(fsl_pq_mdio_init);
 
 void fsl_pq_mdio_exit(void)
 {
-	of_unregister_platform_driver(&fsl_pq_mdio_driver);
+	platform_driver_unregister(&fsl_pq_mdio_driver);
 }
 module_exit(fsl_pq_mdio_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
new file mode 100644
index 0000000..a316619
--- /dev/null
+++ b/drivers/net/ftmac100.c
@@ -0,0 +1,1198 @@
+/*
+ * Faraday FTMAC100 10/100 Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#include "ftmac100.h"
+
+#define DRV_NAME	"ftmac100"
+#define DRV_VERSION	"0.2"
+
+#define RX_QUEUE_ENTRIES	128	/* must be power of 2 */
+#define TX_QUEUE_ENTRIES	16	/* must be power of 2 */
+
+#define MAX_PKT_SIZE		1518
+#define RX_BUF_SIZE		2044	/* must be smaller than 0x7ff */
+
+#if MAX_PKT_SIZE > 0x7ff
+#error invalid MAX_PKT_SIZE
+#endif
+
+#if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
+#error invalid RX_BUF_SIZE
+#endif
+
+/******************************************************************************
+ * private data
+ *****************************************************************************/
+struct ftmac100_descs {
+	struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
+	struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
+};
+
+struct ftmac100 {
+	struct resource *res;
+	void __iomem *base;
+	int irq;
+
+	struct ftmac100_descs *descs;
+	dma_addr_t descs_dma_addr;
+
+	unsigned int rx_pointer;
+	unsigned int tx_clean_pointer;
+	unsigned int tx_pointer;
+	unsigned int tx_pending;
+
+	spinlock_t tx_lock;
+
+	struct net_device *netdev;
+	struct device *dev;
+	struct napi_struct napi;
+
+	struct mii_if_info mii;
+};
+
+static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
+				  struct ftmac100_rxdes *rxdes, gfp_t gfp);
+
+/******************************************************************************
+ * internal functions (hardware register access)
+ *****************************************************************************/
+#define INT_MASK_ALL_ENABLED	(FTMAC100_INT_RPKT_FINISH	| \
+				 FTMAC100_INT_NORXBUF		| \
+				 FTMAC100_INT_XPKT_OK		| \
+				 FTMAC100_INT_XPKT_LOST		| \
+				 FTMAC100_INT_RPKT_LOST		| \
+				 FTMAC100_INT_AHB_ERR		| \
+				 FTMAC100_INT_PHYSTS_CHG)
+
+#define INT_MASK_ALL_DISABLED	0
+
+static void ftmac100_enable_all_int(struct ftmac100 *priv)
+{
+	iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
+}
+
+static void ftmac100_disable_all_int(struct ftmac100 *priv)
+{
+	iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
+}
+
+static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
+{
+	iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
+}
+
+static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
+{
+	iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
+}
+
+static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
+{
+	iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
+}
+
+static int ftmac100_reset(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	int i;
+
+	/* NOTE: reset clears all registers */
+	iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
+
+	for (i = 0; i < 5; i++) {
+		unsigned int maccr;
+
+		maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
+		if (!(maccr & FTMAC100_MACCR_SW_RST)) {
+			/*
+			 * FTMAC100_MACCR_SW_RST cleared does not indicate
+			 * that hardware reset completed (what the f*ck).
+			 * We still need to wait for a while.
+			 */
+			usleep_range(500, 1000);
+			return 0;
+		}
+
+		usleep_range(1000, 10000);
+	}
+
+	netdev_err(netdev, "software reset failed\n");
+	return -EIO;
+}
+
+static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
+{
+	unsigned int maddr = mac[0] << 8 | mac[1];
+	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+
+	iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
+	iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
+}
+
+#define MACCR_ENABLE_ALL	(FTMAC100_MACCR_XMT_EN	| \
+				 FTMAC100_MACCR_RCV_EN	| \
+				 FTMAC100_MACCR_XDMA_EN	| \
+				 FTMAC100_MACCR_RDMA_EN	| \
+				 FTMAC100_MACCR_CRC_APD	| \
+				 FTMAC100_MACCR_FULLDUP	| \
+				 FTMAC100_MACCR_RX_RUNT	| \
+				 FTMAC100_MACCR_RX_BROADPKT)
+
+static int ftmac100_start_hw(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+
+	if (ftmac100_reset(priv))
+		return -EIO;
+
+	/* setup ring buffer base registers */
+	ftmac100_set_rx_ring_base(priv,
+				  priv->descs_dma_addr +
+				  offsetof(struct ftmac100_descs, rxdes));
+	ftmac100_set_tx_ring_base(priv,
+				  priv->descs_dma_addr +
+				  offsetof(struct ftmac100_descs, txdes));
+
+	iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
+
+	ftmac100_set_mac(priv, netdev->dev_addr);
+
+	iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
+	return 0;
+}
+
+static void ftmac100_stop_hw(struct ftmac100 *priv)
+{
+	iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
+}
+
+/******************************************************************************
+ * internal functions (receive descriptor)
+ *****************************************************************************/
+static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
+}
+
+static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
+}
+
+static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
+}
+
+static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
+{
+	/* clear status bits */
+	rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
+}
+
+static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
+}
+
+static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
+}
+
+static bool ftmac100_rxdes_frame_too_long(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FTL);
+}
+
+static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
+}
+
+static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
+}
+
+static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
+{
+	return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
+}
+
+static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
+}
+
+static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
+					   unsigned int size)
+{
+	rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
+	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
+}
+
+static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
+{
+	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
+}
+
+static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
+					dma_addr_t addr)
+{
+	rxdes->rxdes2 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
+{
+	return le32_to_cpu(rxdes->rxdes2);
+}
+
+/*
+ * rxdes3 is not used by hardware. We use it to keep track of page.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
+{
+	rxdes->rxdes3 = (unsigned int)page;
+}
+
+static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
+{
+	return (struct page *)rxdes->rxdes3;
+}
+
+/******************************************************************************
+ * internal functions (receive)
+ *****************************************************************************/
+static int ftmac100_next_rx_pointer(int pointer)
+{
+	return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
+}
+
+static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
+{
+	priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
+}
+
+static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
+{
+	return &priv->descs->rxdes[priv->rx_pointer];
+}
+
+static struct ftmac100_rxdes *
+ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
+{
+	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
+
+	while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
+		if (ftmac100_rxdes_first_segment(rxdes))
+			return rxdes;
+
+		ftmac100_rxdes_set_dma_own(rxdes);
+		ftmac100_rx_pointer_advance(priv);
+		rxdes = ftmac100_current_rxdes(priv);
+	}
+
+	return NULL;
+}
+
+static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
+				     struct ftmac100_rxdes *rxdes)
+{
+	struct net_device *netdev = priv->netdev;
+	bool error = false;
+
+	if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx err\n");
+
+		netdev->stats.rx_errors++;
+		error = true;
+	}
+
+	if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx crc err\n");
+
+		netdev->stats.rx_crc_errors++;
+		error = true;
+	}
+
+	if (unlikely(ftmac100_rxdes_frame_too_long(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx frame too long\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	} else if (unlikely(ftmac100_rxdes_runt(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx runt\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	} else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx odd nibble\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	}
+
+	return error;
+}
+
+static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
+	bool done = false;
+
+	if (net_ratelimit())
+		netdev_dbg(netdev, "drop packet %p\n", rxdes);
+
+	do {
+		if (ftmac100_rxdes_last_segment(rxdes))
+			done = true;
+
+		ftmac100_rxdes_set_dma_own(rxdes);
+		ftmac100_rx_pointer_advance(priv);
+		rxdes = ftmac100_current_rxdes(priv);
+	} while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
+
+	netdev->stats.rx_dropped++;
+}
+
+static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_rxdes *rxdes;
+	struct sk_buff *skb;
+	struct page *page;
+	dma_addr_t map;
+	int length;
+
+	rxdes = ftmac100_rx_locate_first_segment(priv);
+	if (!rxdes)
+		return false;
+
+	if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
+		ftmac100_rx_drop_packet(priv);
+		return true;
+	}
+
+	/*
+	 * It is impossible to get multi-segment packets
+	 * because we always provide big enough receive buffers.
+	 */
+	if (unlikely(!ftmac100_rxdes_last_segment(rxdes)))
+		BUG();
+
+	/* start processing */
+	skb = netdev_alloc_skb_ip_align(netdev, 128);
+	if (unlikely(!skb)) {
+		if (net_ratelimit())
+			netdev_err(netdev, "rx skb alloc failed\n");
+
+		ftmac100_rx_drop_packet(priv);
+		return true;
+	}
+
+	if (unlikely(ftmac100_rxdes_multicast(rxdes)))
+		netdev->stats.multicast++;
+
+	map = ftmac100_rxdes_get_dma_addr(rxdes);
+	dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+
+	length = ftmac100_rxdes_frame_length(rxdes);
+	page = ftmac100_rxdes_get_page(rxdes);
+	skb_fill_page_desc(skb, 0, page, 0, length);
+	skb->len += length;
+	skb->data_len += length;
+	skb->truesize += length;
+	__pskb_pull_tail(skb, min(length, 64));
+
+	ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
+
+	ftmac100_rx_pointer_advance(priv);
+
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	netdev->stats.rx_packets++;
+	netdev->stats.rx_bytes += skb->len;
+
+	/* push packet to protocol stack */
+	netif_receive_skb(skb);
+
+	(*processed)++;
+	return true;
+}
+
+/******************************************************************************
+ * internal functions (transmit descriptor)
+ *****************************************************************************/
+static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
+{
+	/* clear all except end of ring bit */
+	txdes->txdes0 = 0;
+	txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
+	txdes->txdes2 = 0;
+	txdes->txdes3 = 0;
+}
+
+static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
+{
+	/*
+	 * Make sure dma own bit will not be set before any other
+	 * descriptor fields.
+	 */
+	wmb();
+	txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
+}
+
+static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
+}
+
+static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
+}
+
+static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
+}
+
+static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
+}
+
+static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
+}
+
+static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
+}
+
+static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
+					   unsigned int len)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
+}
+
+static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
+					dma_addr_t addr)
+{
+	txdes->txdes2 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
+{
+	return le32_to_cpu(txdes->txdes2);
+}
+
+/*
+ * txdes3 is not used by hardware. We use it to keep track of socket buffer.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
+{
+	txdes->txdes3 = (unsigned int)skb;
+}
+
+static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
+{
+	return (struct sk_buff *)txdes->txdes3;
+}
+
+/******************************************************************************
+ * internal functions (transmit)
+ *****************************************************************************/
+static int ftmac100_next_tx_pointer(int pointer)
+{
+	return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+}
+
+static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
+{
+	priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
+}
+
+static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
+{
+	priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
+}
+
+static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
+{
+	return &priv->descs->txdes[priv->tx_pointer];
+}
+
+static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
+{
+	return &priv->descs->txdes[priv->tx_clean_pointer];
+}
+
+static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_txdes *txdes;
+	struct sk_buff *skb;
+	dma_addr_t map;
+
+	if (priv->tx_pending == 0)
+		return false;
+
+	txdes = ftmac100_current_clean_txdes(priv);
+
+	if (ftmac100_txdes_owned_by_dma(txdes))
+		return false;
+
+	skb = ftmac100_txdes_get_skb(txdes);
+	map = ftmac100_txdes_get_dma_addr(txdes);
+
+	if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
+		     ftmac100_txdes_late_collision(txdes))) {
+		/*
+		 * packet transmitted to ethernet lost due to late collision
+		 * or excessive collision
+		 */
+		netdev->stats.tx_aborted_errors++;
+	} else {
+		netdev->stats.tx_packets++;
+		netdev->stats.tx_bytes += skb->len;
+	}
+
+	dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+	dev_kfree_skb(skb);
+
+	ftmac100_txdes_reset(txdes);
+
+	ftmac100_tx_clean_pointer_advance(priv);
+
+	spin_lock(&priv->tx_lock);
+	priv->tx_pending--;
+	spin_unlock(&priv->tx_lock);
+	netif_wake_queue(netdev);
+
+	return true;
+}
+
+static void ftmac100_tx_complete(struct ftmac100 *priv)
+{
+	while (ftmac100_tx_complete_packet(priv))
+		;
+}
+
+static int ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
+			 dma_addr_t map)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_txdes *txdes;
+	unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+
+	txdes = ftmac100_current_txdes(priv);
+	ftmac100_tx_pointer_advance(priv);
+
+	/* setup TX descriptor */
+	ftmac100_txdes_set_skb(txdes, skb);
+	ftmac100_txdes_set_dma_addr(txdes, map);
+
+	ftmac100_txdes_set_first_segment(txdes);
+	ftmac100_txdes_set_last_segment(txdes);
+	ftmac100_txdes_set_txint(txdes);
+	ftmac100_txdes_set_buffer_size(txdes, len);
+
+	spin_lock(&priv->tx_lock);
+	priv->tx_pending++;
+	if (priv->tx_pending == TX_QUEUE_ENTRIES)
+		netif_stop_queue(netdev);
+
+	/* start transmit */
+	ftmac100_txdes_set_dma_own(txdes);
+	spin_unlock(&priv->tx_lock);
+
+	ftmac100_txdma_start_polling(priv);
+	return NETDEV_TX_OK;
+}
+
+/******************************************************************************
+ * internal functions (buffer)
+ *****************************************************************************/
+static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
+				  struct ftmac100_rxdes *rxdes, gfp_t gfp)
+{
+	struct net_device *netdev = priv->netdev;
+	struct page *page;
+	dma_addr_t map;
+
+	page = alloc_page(gfp);
+	if (!page) {
+		if (net_ratelimit())
+			netdev_err(netdev, "failed to allocate rx page\n");
+		return -ENOMEM;
+	}
+
+	map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, map))) {
+		if (net_ratelimit())
+			netdev_err(netdev, "failed to map rx page\n");
+		__free_page(page);
+		return -ENOMEM;
+	}
+
+	ftmac100_rxdes_set_page(rxdes, page);
+	ftmac100_rxdes_set_dma_addr(rxdes, map);
+	ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
+	ftmac100_rxdes_set_dma_own(rxdes);
+	return 0;
+}
+
+static void ftmac100_free_buffers(struct ftmac100 *priv)
+{
+	int i;
+
+	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+		struct page *page = ftmac100_rxdes_get_page(rxdes);
+		dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
+
+		if (!page)
+			continue;
+
+		dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+		__free_page(page);
+	}
+
+	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
+		struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
+		struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
+		dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
+
+		if (!skb)
+			continue;
+
+		dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+		dev_kfree_skb(skb);
+	}
+
+	dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
+			  priv->descs, priv->descs_dma_addr);
+}
+
+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);
+	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]);
+
+	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+
+		if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
+			goto err;
+	}
+
+	/* initialize TX ring */
+	ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
+	return 0;
+
+err:
+	ftmac100_free_buffers(priv);
+	return -ENOMEM;
+}
+
+/******************************************************************************
+ * struct mii_if_info functions
+ *****************************************************************************/
+static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	unsigned int phycr;
+	int i;
+
+	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
+		FTMAC100_PHYCR_REGAD(reg) |
+		FTMAC100_PHYCR_MIIRD;
+
+	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
+
+	for (i = 0; i < 10; i++) {
+		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
+
+		if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
+			return phycr & FTMAC100_PHYCR_MIIRDATA;
+
+		usleep_range(100, 1000);
+	}
+
+	netdev_err(netdev, "mdio read timed out\n");
+	return 0;
+}
+
+static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
+				int data)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	unsigned int phycr;
+	int i;
+
+	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
+		FTMAC100_PHYCR_REGAD(reg) |
+		FTMAC100_PHYCR_MIIWR;
+
+	data = FTMAC100_PHYWDATA_MIIWDATA(data);
+
+	iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
+	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
+
+	for (i = 0; i < 10; i++) {
+		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
+
+		if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
+			return;
+
+		usleep_range(100, 1000);
+	}
+
+	netdev_err(netdev, "mdio write timed out\n");
+}
+
+/******************************************************************************
+ * struct ethtool_ops functions
+ *****************************************************************************/
+static void ftmac100_get_drvinfo(struct net_device *netdev,
+				 struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, dev_name(&netdev->dev));
+}
+
+static int ftmac100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_ethtool_gset(&priv->mii, cmd);
+}
+
+static int ftmac100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_ethtool_sset(&priv->mii, cmd);
+}
+
+static int ftmac100_nway_reset(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_nway_restart(&priv->mii);
+}
+
+static u32 ftmac100_get_link(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_link_ok(&priv->mii);
+}
+
+static const struct ethtool_ops ftmac100_ethtool_ops = {
+	.set_settings		= ftmac100_set_settings,
+	.get_settings		= ftmac100_get_settings,
+	.get_drvinfo		= ftmac100_get_drvinfo,
+	.nway_reset		= ftmac100_nway_reset,
+	.get_link		= ftmac100_get_link,
+};
+
+/******************************************************************************
+ * interrupt handler
+ *****************************************************************************/
+static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
+{
+	struct net_device *netdev = dev_id;
+	struct ftmac100 *priv = netdev_priv(netdev);
+
+	if (likely(netif_running(netdev))) {
+		/* Disable interrupts for polling */
+		ftmac100_disable_all_int(priv);
+		napi_schedule(&priv->napi);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ * struct napi_struct functions
+ *****************************************************************************/
+static int ftmac100_poll(struct napi_struct *napi, int budget)
+{
+	struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
+	struct net_device *netdev = priv->netdev;
+	unsigned int status;
+	bool completed = true;
+	int rx = 0;
+
+	status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
+
+	if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
+		/*
+		 * FTMAC100_INT_RPKT_FINISH:
+		 *	RX DMA has received packets into RX buffer successfully
+		 *
+		 * FTMAC100_INT_NORXBUF:
+		 *	RX buffer unavailable
+		 */
+		bool retry;
+
+		do {
+			retry = ftmac100_rx_packet(priv, &rx);
+		} while (retry && rx < budget);
+
+		if (retry && rx == budget)
+			completed = false;
+	}
+
+	if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
+		/*
+		 * FTMAC100_INT_XPKT_OK:
+		 *	packet transmitted to ethernet successfully
+		 *
+		 * FTMAC100_INT_XPKT_LOST:
+		 *	packet transmitted to ethernet lost due to late
+		 *	collision or excessive collision
+		 */
+		ftmac100_tx_complete(priv);
+	}
+
+	if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
+		      FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
+		if (net_ratelimit())
+			netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
+				    status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
+				    status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
+				    status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
+				    status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
+
+		if (status & FTMAC100_INT_NORXBUF) {
+			/* RX buffer unavailable */
+			netdev->stats.rx_over_errors++;
+		}
+
+		if (status & FTMAC100_INT_RPKT_LOST) {
+			/* received packet lost due to RX FIFO full */
+			netdev->stats.rx_fifo_errors++;
+		}
+
+		if (status & FTMAC100_INT_PHYSTS_CHG) {
+			/* PHY link status change */
+			mii_check_link(&priv->mii);
+		}
+	}
+
+	if (completed) {
+		/* stop polling */
+		napi_complete(napi);
+		ftmac100_enable_all_int(priv);
+	}
+
+	return rx;
+}
+
+/******************************************************************************
+ * struct net_device_ops functions
+ *****************************************************************************/
+static int ftmac100_open(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	int err;
+
+	err = ftmac100_alloc_buffers(priv);
+	if (err) {
+		netdev_err(netdev, "failed to allocate buffers\n");
+		goto err_alloc;
+	}
+
+	err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
+	if (err) {
+		netdev_err(netdev, "failed to request irq %d\n", priv->irq);
+		goto err_irq;
+	}
+
+	priv->rx_pointer = 0;
+	priv->tx_clean_pointer = 0;
+	priv->tx_pointer = 0;
+	priv->tx_pending = 0;
+
+	err = ftmac100_start_hw(priv);
+	if (err)
+		goto err_hw;
+
+	napi_enable(&priv->napi);
+	netif_start_queue(netdev);
+
+	ftmac100_enable_all_int(priv);
+
+	return 0;
+
+err_hw:
+	free_irq(priv->irq, netdev);
+err_irq:
+	ftmac100_free_buffers(priv);
+err_alloc:
+	return err;
+}
+
+static int ftmac100_stop(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+
+	ftmac100_disable_all_int(priv);
+	netif_stop_queue(netdev);
+	napi_disable(&priv->napi);
+	ftmac100_stop_hw(priv);
+	free_irq(priv->irq, netdev);
+	ftmac100_free_buffers(priv);
+
+	return 0;
+}
+
+static int ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	dma_addr_t map;
+
+	if (unlikely(skb->len > MAX_PKT_SIZE)) {
+		if (net_ratelimit())
+			netdev_dbg(netdev, "tx packet too big\n");
+
+		netdev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, map))) {
+		/* drop packet */
+		if (net_ratelimit())
+			netdev_err(netdev, "map socket buffer failed\n");
+
+		netdev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	return ftmac100_xmit(priv, skb, map);
+}
+
+/* optional */
+static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	struct mii_ioctl_data *data = if_mii(ifr);
+
+	return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
+}
+
+static const struct net_device_ops ftmac100_netdev_ops = {
+	.ndo_open		= ftmac100_open,
+	.ndo_stop		= ftmac100_stop,
+	.ndo_start_xmit		= ftmac100_hard_start_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_do_ioctl		= ftmac100_do_ioctl,
+};
+
+/******************************************************************************
+ * struct platform_driver functions
+ *****************************************************************************/
+static int ftmac100_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int irq;
+	struct net_device *netdev;
+	struct ftmac100 *priv;
+	int err;
+
+	if (!pdev)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	/* setup net_device */
+	netdev = alloc_etherdev(sizeof(*priv));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto err_alloc_etherdev;
+	}
+
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
+	netdev->netdev_ops = &ftmac100_netdev_ops;
+
+	platform_set_drvdata(pdev, netdev);
+
+	/* setup private data */
+	priv = netdev_priv(netdev);
+	priv->netdev = netdev;
+	priv->dev = &pdev->dev;
+
+	spin_lock_init(&priv->tx_lock);
+
+	/* initialize NAPI */
+	netif_napi_add(netdev, &priv->napi, ftmac100_poll, 64);
+
+	/* map io memory */
+	priv->res = request_mem_region(res->start, resource_size(res),
+				       dev_name(&pdev->dev));
+	if (!priv->res) {
+		dev_err(&pdev->dev, "Could not reserve memory region\n");
+		err = -ENOMEM;
+		goto err_req_mem;
+	}
+
+	priv->base = ioremap(res->start, resource_size(res));
+	if (!priv->base) {
+		dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+		err = -EIO;
+		goto err_ioremap;
+	}
+
+	priv->irq = irq;
+
+	/* initialize struct mii_if_info */
+	priv->mii.phy_id	= 0;
+	priv->mii.phy_id_mask	= 0x1f;
+	priv->mii.reg_num_mask	= 0x1f;
+	priv->mii.dev		= netdev;
+	priv->mii.mdio_read	= ftmac100_mdio_read;
+	priv->mii.mdio_write	= ftmac100_mdio_write;
+
+	/* register network device */
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register netdev\n");
+		goto err_register_netdev;
+	}
+
+	netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		random_ether_addr(netdev->dev_addr);
+		netdev_info(netdev, "generated random MAC address %pM\n",
+			    netdev->dev_addr);
+	}
+
+	return 0;
+
+err_register_netdev:
+	iounmap(priv->base);
+err_ioremap:
+	release_resource(priv->res);
+err_req_mem:
+	netif_napi_del(&priv->napi);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+err_alloc_etherdev:
+	return err;
+}
+
+static int __exit ftmac100_remove(struct platform_device *pdev)
+{
+	struct net_device *netdev;
+	struct ftmac100 *priv;
+
+	netdev = platform_get_drvdata(pdev);
+	priv = netdev_priv(netdev);
+
+	unregister_netdev(netdev);
+
+	iounmap(priv->base);
+	release_resource(priv->res);
+
+	netif_napi_del(&priv->napi);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+	return 0;
+}
+
+static struct platform_driver ftmac100_driver = {
+	.probe		= ftmac100_probe,
+	.remove		= __exit_p(ftmac100_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+/******************************************************************************
+ * initialization / finalization
+ *****************************************************************************/
+static int __init ftmac100_init(void)
+{
+	pr_info("Loading version " DRV_VERSION " ...\n");
+	return platform_driver_register(&ftmac100_driver);
+}
+
+static void __exit ftmac100_exit(void)
+{
+	platform_driver_unregister(&ftmac100_driver);
+}
+
+module_init(ftmac100_init);
+module_exit(ftmac100_exit);
+
+MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
+MODULE_DESCRIPTION("FTMAC100 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftmac100.h b/drivers/net/ftmac100.h
new file mode 100644
index 0000000..46a0c47
--- /dev/null
+++ b/drivers/net/ftmac100.h
@@ -0,0 +1,180 @@
+/*
+ * Faraday FTMAC100 10/100 Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __FTMAC100_H
+#define __FTMAC100_H
+
+#define	FTMAC100_OFFSET_ISR		0x00
+#define	FTMAC100_OFFSET_IMR		0x04
+#define	FTMAC100_OFFSET_MAC_MADR	0x08
+#define	FTMAC100_OFFSET_MAC_LADR	0x0c
+#define	FTMAC100_OFFSET_MAHT0		0x10
+#define	FTMAC100_OFFSET_MAHT1		0x14
+#define	FTMAC100_OFFSET_TXPD		0x18
+#define	FTMAC100_OFFSET_RXPD		0x1c
+#define	FTMAC100_OFFSET_TXR_BADR	0x20
+#define	FTMAC100_OFFSET_RXR_BADR	0x24
+#define	FTMAC100_OFFSET_ITC		0x28
+#define	FTMAC100_OFFSET_APTC		0x2c
+#define	FTMAC100_OFFSET_DBLAC		0x30
+#define	FTMAC100_OFFSET_MACCR		0x88
+#define	FTMAC100_OFFSET_MACSR		0x8c
+#define	FTMAC100_OFFSET_PHYCR		0x90
+#define	FTMAC100_OFFSET_PHYWDATA	0x94
+#define	FTMAC100_OFFSET_FCR		0x98
+#define	FTMAC100_OFFSET_BPR		0x9c
+#define	FTMAC100_OFFSET_TS		0xc4
+#define	FTMAC100_OFFSET_DMAFIFOS	0xc8
+#define	FTMAC100_OFFSET_TM		0xcc
+#define	FTMAC100_OFFSET_TX_MCOL_SCOL	0xd4
+#define	FTMAC100_OFFSET_RPF_AEP		0xd8
+#define	FTMAC100_OFFSET_XM_PG		0xdc
+#define	FTMAC100_OFFSET_RUNT_TLCC	0xe0
+#define	FTMAC100_OFFSET_CRCER_FTL	0xe4
+#define	FTMAC100_OFFSET_RLC_RCC		0xe8
+#define	FTMAC100_OFFSET_BROC		0xec
+#define	FTMAC100_OFFSET_MULCA		0xf0
+#define	FTMAC100_OFFSET_RP		0xf4
+#define	FTMAC100_OFFSET_XP		0xf8
+
+/*
+ * Interrupt status register & interrupt mask register
+ */
+#define	FTMAC100_INT_RPKT_FINISH	(1 << 0)
+#define	FTMAC100_INT_NORXBUF		(1 << 1)
+#define	FTMAC100_INT_XPKT_FINISH	(1 << 2)
+#define	FTMAC100_INT_NOTXBUF		(1 << 3)
+#define	FTMAC100_INT_XPKT_OK		(1 << 4)
+#define	FTMAC100_INT_XPKT_LOST		(1 << 5)
+#define	FTMAC100_INT_RPKT_SAV		(1 << 6)
+#define	FTMAC100_INT_RPKT_LOST		(1 << 7)
+#define	FTMAC100_INT_AHB_ERR		(1 << 8)
+#define	FTMAC100_INT_PHYSTS_CHG		(1 << 9)
+
+/*
+ * Interrupt timer control register
+ */
+#define FTMAC100_ITC_RXINT_CNT(x)	(((x) & 0xf) << 0)
+#define FTMAC100_ITC_RXINT_THR(x)	(((x) & 0x7) << 4)
+#define FTMAC100_ITC_RXINT_TIME_SEL	(1 << 7)
+#define FTMAC100_ITC_TXINT_CNT(x)	(((x) & 0xf) << 8)
+#define FTMAC100_ITC_TXINT_THR(x)	(((x) & 0x7) << 12)
+#define FTMAC100_ITC_TXINT_TIME_SEL	(1 << 15)
+
+/*
+ * Automatic polling timer control register
+ */
+#define	FTMAC100_APTC_RXPOLL_CNT(x)	(((x) & 0xf) << 0)
+#define	FTMAC100_APTC_RXPOLL_TIME_SEL	(1 << 4)
+#define	FTMAC100_APTC_TXPOLL_CNT(x)	(((x) & 0xf) << 8)
+#define	FTMAC100_APTC_TXPOLL_TIME_SEL	(1 << 12)
+
+/*
+ * DMA burst length and arbitration control register
+ */
+#define FTMAC100_DBLAC_INCR4_EN		(1 << 0)
+#define FTMAC100_DBLAC_INCR8_EN		(1 << 1)
+#define FTMAC100_DBLAC_INCR16_EN	(1 << 2)
+#define FTMAC100_DBLAC_RXFIFO_LTHR(x)	(((x) & 0x7) << 3)
+#define FTMAC100_DBLAC_RXFIFO_HTHR(x)	(((x) & 0x7) << 6)
+#define FTMAC100_DBLAC_RX_THR_EN	(1 << 9)
+
+/*
+ * MAC control register
+ */
+#define	FTMAC100_MACCR_XDMA_EN		(1 << 0)
+#define	FTMAC100_MACCR_RDMA_EN		(1 << 1)
+#define	FTMAC100_MACCR_SW_RST		(1 << 2)
+#define	FTMAC100_MACCR_LOOP_EN		(1 << 3)
+#define	FTMAC100_MACCR_CRC_DIS		(1 << 4)
+#define	FTMAC100_MACCR_XMT_EN		(1 << 5)
+#define	FTMAC100_MACCR_ENRX_IN_HALFTX	(1 << 6)
+#define	FTMAC100_MACCR_RCV_EN		(1 << 8)
+#define	FTMAC100_MACCR_HT_MULTI_EN	(1 << 9)
+#define	FTMAC100_MACCR_RX_RUNT		(1 << 10)
+#define	FTMAC100_MACCR_RX_FTL		(1 << 11)
+#define	FTMAC100_MACCR_RCV_ALL		(1 << 12)
+#define	FTMAC100_MACCR_CRC_APD		(1 << 14)
+#define	FTMAC100_MACCR_FULLDUP		(1 << 15)
+#define	FTMAC100_MACCR_RX_MULTIPKT	(1 << 16)
+#define	FTMAC100_MACCR_RX_BROADPKT	(1 << 17)
+
+/*
+ * PHY control register
+ */
+#define FTMAC100_PHYCR_MIIRDATA		0xffff
+#define FTMAC100_PHYCR_PHYAD(x)		(((x) & 0x1f) << 16)
+#define FTMAC100_PHYCR_REGAD(x)		(((x) & 0x1f) << 21)
+#define FTMAC100_PHYCR_MIIRD		(1 << 26)
+#define FTMAC100_PHYCR_MIIWR		(1 << 27)
+
+/*
+ * PHY write data register
+ */
+#define FTMAC100_PHYWDATA_MIIWDATA(x)	((x) & 0xffff)
+
+/*
+ * Transmit descriptor, aligned to 16 bytes
+ */
+struct ftmac100_txdes {
+	unsigned int	txdes0;
+	unsigned int	txdes1;
+	unsigned int	txdes2;	/* TXBUF_BADR */
+	unsigned int	txdes3;	/* not used by HW */
+} __attribute__ ((aligned(16)));
+
+#define	FTMAC100_TXDES0_TXPKT_LATECOL	(1 << 0)
+#define	FTMAC100_TXDES0_TXPKT_EXSCOL	(1 << 1)
+#define	FTMAC100_TXDES0_TXDMA_OWN	(1 << 31)
+
+#define	FTMAC100_TXDES1_TXBUF_SIZE(x)	((x) & 0x7ff)
+#define	FTMAC100_TXDES1_LTS		(1 << 27)
+#define	FTMAC100_TXDES1_FTS		(1 << 28)
+#define	FTMAC100_TXDES1_TX2FIC		(1 << 29)
+#define	FTMAC100_TXDES1_TXIC		(1 << 30)
+#define	FTMAC100_TXDES1_EDOTR		(1 << 31)
+
+/*
+ * Receive descriptor, aligned to 16 bytes
+ */
+struct ftmac100_rxdes {
+	unsigned int	rxdes0;
+	unsigned int	rxdes1;
+	unsigned int	rxdes2;	/* RXBUF_BADR */
+	unsigned int	rxdes3;	/* not used by HW */
+} __attribute__ ((aligned(16)));
+
+#define	FTMAC100_RXDES0_RFL		0x7ff
+#define	FTMAC100_RXDES0_MULTICAST	(1 << 16)
+#define	FTMAC100_RXDES0_BROADCAST	(1 << 17)
+#define	FTMAC100_RXDES0_RX_ERR		(1 << 18)
+#define	FTMAC100_RXDES0_CRC_ERR		(1 << 19)
+#define	FTMAC100_RXDES0_FTL		(1 << 20)
+#define	FTMAC100_RXDES0_RUNT		(1 << 21)
+#define	FTMAC100_RXDES0_RX_ODD_NB	(1 << 22)
+#define	FTMAC100_RXDES0_LRS		(1 << 28)
+#define	FTMAC100_RXDES0_FRS		(1 << 29)
+#define	FTMAC100_RXDES0_RXDMA_OWN	(1 << 31)
+
+#define	FTMAC100_RXDES1_RXBUF_SIZE(x)	((x) & 0x7ff)
+#define	FTMAC100_RXDES1_EDORR		(1 << 31)
+
+#endif /* __FTMAC100_H */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 5ed8f9f..2a0ad9a 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -123,8 +123,7 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id);
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
-static int gfar_probe(struct platform_device *ofdev,
-		const struct of_device_id *match);
+static int gfar_probe(struct platform_device *ofdev);
 static int gfar_remove(struct platform_device *ofdev);
 static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
@@ -950,6 +949,11 @@ static void gfar_detect_errata(struct gfar_private *priv)
 			(pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
 		priv->errata |= GFAR_ERRATA_A002;
 
+	/* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
+	if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) ||
+			(pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))
+		priv->errata |= GFAR_ERRATA_12;
+
 	if (priv->errata)
 		dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
 			 priv->errata);
@@ -957,8 +961,7 @@ static void gfar_detect_errata(struct gfar_private *priv)
 
 /* Set up the ethernet device structure, private data,
  * and anything else we need before we start */
-static int gfar_probe(struct platform_device *ofdev,
-		const struct of_device_id *match)
+static int gfar_probe(struct platform_device *ofdev)
 {
 	u32 tempval;
 	struct net_device *dev = NULL;
@@ -2156,8 +2159,15 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Set up checksumming */
 	if (CHECKSUM_PARTIAL == skb->ip_summed) {
 		fcb = gfar_add_fcb(skb);
-		lstatus |= BD_LFLAG(TXBD_TOE);
-		gfar_tx_checksum(skb, fcb);
+		/* as specified by errata */
+		if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12)
+			     && ((unsigned long)fcb % 0x20) > 0x18)) {
+			__skb_pull(skb, GMAC_FCB_LEN);
+			skb_checksum_help(skb);
+		} else {
+			lstatus |= BD_LFLAG(TXBD_TOE);
+			gfar_tx_checksum(skb, fcb);
+		}
 	}
 
 	if (vlan_tx_tag_present(skb)) {
@@ -3256,7 +3266,7 @@ static struct of_device_id gfar_match[] =
 MODULE_DEVICE_TABLE(of, gfar_match);
 
 /* Structure for a device driver */
-static struct of_platform_driver gfar_driver = {
+static struct platform_driver gfar_driver = {
 	.driver = {
 		.name = "fsl-gianfar",
 		.owner = THIS_MODULE,
@@ -3269,12 +3279,12 @@ static struct of_platform_driver gfar_driver = {
 
 static int __init gfar_init(void)
 {
-	return of_register_platform_driver(&gfar_driver);
+	return platform_driver_register(&gfar_driver);
 }
 
 static void __exit gfar_exit(void)
 {
-	of_unregister_platform_driver(&gfar_driver);
+	platform_driver_unregister(&gfar_driver);
 }
 
 module_init(gfar_init);
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 54de413..ec5d595 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -1039,6 +1039,7 @@ enum gfar_errata {
 	GFAR_ERRATA_74		= 0x01,
 	GFAR_ERRATA_76		= 0x02,
 	GFAR_ERRATA_A002	= 0x04,
+	GFAR_ERRATA_12		= 0x08, /* a.k.a errata eTSEC49 */
 };
 
 /* Struct stolen almost completely (and shamelessly) from the FCC enet source
diff --git a/drivers/net/greth.c b/drivers/net/greth.c
index fdb0333..396ff7d 100644
--- a/drivers/net/greth.c
+++ b/drivers/net/greth.c
@@ -1411,7 +1411,7 @@ error:
 }
 
 /* Initialize the GRETH MAC */
-static int __devinit greth_of_probe(struct platform_device *ofdev, const struct of_device_id *match)
+static int __devinit greth_of_probe(struct platform_device *ofdev)
 {
 	struct net_device *dev;
 	struct greth_private *greth;
@@ -1646,7 +1646,7 @@ static struct of_device_id greth_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, greth_of_match);
 
-static struct of_platform_driver greth_of_driver = {
+static struct platform_driver greth_of_driver = {
 	.driver = {
 		.name = "grlib-greth",
 		.owner = THIS_MODULE,
@@ -1658,12 +1658,12 @@ static struct of_platform_driver greth_of_driver = {
 
 static int __init greth_init(void)
 {
-	return of_register_platform_driver(&greth_of_driver);
+	return platform_driver_register(&greth_of_driver);
 }
 
 static void __exit greth_cleanup(void)
 {
-	of_unregister_platform_driver(&greth_of_driver);
+	platform_driver_unregister(&greth_of_driver);
 }
 
 module_init(greth_init);
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index ac1d323..8931168 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -400,13 +400,14 @@ static void *bpq_seq_start(struct seq_file *seq, loff_t *pos)
 static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct list_head *p;
+	struct bpqdev *bpqdev = v;
 
 	++*pos;
 
 	if (v == SEQ_START_TOKEN)
-		p = rcu_dereference(bpq_devices.next);
+		p = rcu_dereference(list_next_rcu(&bpq_devices));
 	else
-		p = rcu_dereference(((struct bpqdev *)v)->bpq_list.next);
+		p = rcu_dereference(list_next_rcu(&bpqdev->bpq_list));
 
 	return (p == &bpq_devices) ? NULL 
 		: list_entry(p, struct bpqdev, bpq_list);
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 6d9275c..3bb990b 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2719,8 +2719,7 @@ static const struct net_device_ops emac_gige_netdev_ops = {
 	.ndo_change_mtu		= emac_change_mtu,
 };
 
-static int __devinit emac_probe(struct platform_device *ofdev,
-				const struct of_device_id *match)
+static int __devinit emac_probe(struct platform_device *ofdev)
 {
 	struct net_device *ndev;
 	struct emac_instance *dev;
@@ -2994,7 +2993,7 @@ static struct of_device_id emac_match[] =
 };
 MODULE_DEVICE_TABLE(of, emac_match);
 
-static struct of_platform_driver emac_driver = {
+static struct platform_driver emac_driver = {
 	.driver = {
 		.name = "emac",
 		.owner = THIS_MODULE,
@@ -3069,7 +3068,7 @@ static int __init emac_init(void)
 	rc = tah_init();
 	if (rc)
 		goto err_rgmii;
-	rc = of_register_platform_driver(&emac_driver);
+	rc = platform_driver_register(&emac_driver);
 	if (rc)
 		goto err_tah;
 
@@ -3091,7 +3090,7 @@ static void __exit emac_exit(void)
 {
 	int i;
 
-	of_unregister_platform_driver(&emac_driver);
+	platform_driver_unregister(&emac_driver);
 
 	tah_exit();
 	rgmii_exit();
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index d5717e2..d268f40 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -517,8 +517,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf)
 	return regs + 1;
 }
 
-static int __devinit mal_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit mal_probe(struct platform_device *ofdev)
 {
 	struct mal_instance *mal;
 	int err = 0, i, bd_size;
@@ -789,7 +788,7 @@ static struct of_device_id mal_platform_match[] =
 	{},
 };
 
-static struct of_platform_driver mal_of_driver = {
+static struct platform_driver mal_of_driver = {
 	.driver = {
 		.name = "mcmal",
 		.owner = THIS_MODULE,
@@ -801,10 +800,10 @@ static struct of_platform_driver mal_of_driver = {
 
 int __init mal_init(void)
 {
-	return of_register_platform_driver(&mal_of_driver);
+	return platform_driver_register(&mal_of_driver);
 }
 
 void mal_exit(void)
 {
-	of_unregister_platform_driver(&mal_of_driver);
+	platform_driver_unregister(&mal_of_driver);
 }
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c
index dd61798..4fa53f3 100644
--- a/drivers/net/ibm_newemac/rgmii.c
+++ b/drivers/net/ibm_newemac/rgmii.c
@@ -228,8 +228,7 @@ void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
 }
 
 
-static int __devinit rgmii_probe(struct platform_device *ofdev,
-				 const struct of_device_id *match)
+static int __devinit rgmii_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct rgmii_instance *dev;
@@ -318,7 +317,7 @@ static struct of_device_id rgmii_match[] =
 	{},
 };
 
-static struct of_platform_driver rgmii_driver = {
+static struct platform_driver rgmii_driver = {
 	.driver = {
 		.name = "emac-rgmii",
 		.owner = THIS_MODULE,
@@ -330,10 +329,10 @@ static struct of_platform_driver rgmii_driver = {
 
 int __init rgmii_init(void)
 {
-	return of_register_platform_driver(&rgmii_driver);
+	return platform_driver_register(&rgmii_driver);
 }
 
 void rgmii_exit(void)
 {
-	of_unregister_platform_driver(&rgmii_driver);
+	platform_driver_unregister(&rgmii_driver);
 }
diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c
index 299aa49..8ead6a9 100644
--- a/drivers/net/ibm_newemac/tah.c
+++ b/drivers/net/ibm_newemac/tah.c
@@ -87,8 +87,7 @@ void *tah_dump_regs(struct platform_device *ofdev, void *buf)
 	return regs + 1;
 }
 
-static int __devinit tah_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit tah_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct tah_instance *dev;
@@ -165,7 +164,7 @@ static struct of_device_id tah_match[] =
 	{},
 };
 
-static struct of_platform_driver tah_driver = {
+static struct platform_driver tah_driver = {
 	.driver = {
 		.name = "emac-tah",
 		.owner = THIS_MODULE,
@@ -177,10 +176,10 @@ static struct of_platform_driver tah_driver = {
 
 int __init tah_init(void)
 {
-	return of_register_platform_driver(&tah_driver);
+	return platform_driver_register(&tah_driver);
 }
 
 void tah_exit(void)
 {
-	of_unregister_platform_driver(&tah_driver);
+	platform_driver_unregister(&tah_driver);
 }
diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c
index 34ed6ee..97449e7 100644
--- a/drivers/net/ibm_newemac/zmii.c
+++ b/drivers/net/ibm_newemac/zmii.c
@@ -231,8 +231,7 @@ void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
 	return regs + 1;
 }
 
-static int __devinit zmii_probe(struct platform_device *ofdev,
-				const struct of_device_id *match)
+static int __devinit zmii_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct zmii_instance *dev;
@@ -312,7 +311,7 @@ static struct of_device_id zmii_match[] =
 	{},
 };
 
-static struct of_platform_driver zmii_driver = {
+static struct platform_driver zmii_driver = {
 	.driver = {
 		.name = "emac-zmii",
 		.owner = THIS_MODULE,
@@ -324,10 +323,10 @@ static struct of_platform_driver zmii_driver = {
 
 int __init zmii_init(void)
 {
-	return of_register_platform_driver(&zmii_driver);
+	return platform_driver_register(&zmii_driver);
 }
 
 void zmii_exit(void)
 {
-	of_unregister_platform_driver(&zmii_driver);
+	platform_driver_unregister(&zmii_driver);
 }
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 0a2368f..6b256c2 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -64,7 +64,14 @@ static s32  igb_reset_init_script_82575(struct e1000_hw *);
 static s32  igb_read_mac_addr_82575(struct e1000_hw *);
 static s32  igb_set_pcie_completion_timeout(struct e1000_hw *hw);
 static s32  igb_reset_mdicnfg_82580(struct e1000_hw *hw);
-
+static s32  igb_validate_nvm_checksum_82580(struct e1000_hw *hw);
+static s32  igb_update_nvm_checksum_82580(struct e1000_hw *hw);
+static s32  igb_update_nvm_checksum_with_offset(struct e1000_hw *hw,
+						u16 offset);
+static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+						u16 offset);
+static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw);
+static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw);
 static const u16 e1000_82580_rxpbs_table[] =
 	{ 36, 72, 144, 1, 2, 4, 8, 16,
 	  35, 70, 140 };
@@ -129,6 +136,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 		break;
 	case E1000_DEV_ID_82580_COPPER:
 	case E1000_DEV_ID_82580_FIBER:
+	case E1000_DEV_ID_82580_QUAD_FIBER:
 	case E1000_DEV_ID_82580_SERDES:
 	case E1000_DEV_ID_82580_SGMII:
 	case E1000_DEV_ID_82580_COPPER_DUAL:
@@ -194,7 +202,11 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 	mac->arc_subsystem_valid =
 		(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK)
 			? true : false;
-
+	/* enable EEE on i350 parts */
+	if (mac->type == e1000_i350)
+		dev_spec->eee_disable = false;
+	else
+		dev_spec->eee_disable = true;
 	/* physical interface link setup */
 	mac->ops.setup_physical_interface =
 		(hw->phy.media_type == e1000_media_type_copper)
@@ -232,14 +244,42 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
 	 */
 	size += NVM_WORD_SIZE_BASE_SHIFT;
 
-	/* EEPROM access above 16k is unsupported */
-	if (size > 14)
-		size = 14;
 	nvm->word_size = 1 << size;
+	if (nvm->word_size == (1 << 15))
+		nvm->page_size = 128;
 
-	/* if 82576 then initialize mailbox parameters */
-	if (mac->type == e1000_82576)
+	/* NVM Function Pointers */
+	nvm->ops.acquire = igb_acquire_nvm_82575;
+	if (nvm->word_size < (1 << 15))
+		nvm->ops.read = igb_read_nvm_eerd;
+	else
+		nvm->ops.read = igb_read_nvm_spi;
+
+	nvm->ops.release = igb_release_nvm_82575;
+	switch (hw->mac.type) {
+	case e1000_82580:
+		nvm->ops.validate = igb_validate_nvm_checksum_82580;
+		nvm->ops.update = igb_update_nvm_checksum_82580;
+		break;
+	case e1000_i350:
+		nvm->ops.validate = igb_validate_nvm_checksum_i350;
+		nvm->ops.update = igb_update_nvm_checksum_i350;
+		break;
+	default:
+		nvm->ops.validate = igb_validate_nvm_checksum;
+		nvm->ops.update = igb_update_nvm_checksum;
+	}
+	nvm->ops.write = igb_write_nvm_spi;
+
+	/* if part supports SR-IOV then initialize mailbox parameters */
+	switch (mac->type) {
+	case e1000_82576:
+	case e1000_i350:
 		igb_init_mbx_params_pf(hw);
+		break;
+	default:
+		break;
+	}
 
 	/* setup PHY parameters */
 	if (phy->media_type != e1000_media_type_copper) {
@@ -1747,6 +1787,248 @@ u16 igb_rxpbs_adjust_82580(u32 data)
 	return ret_val;
 }
 
+/**
+ *  igb_validate_nvm_checksum_with_offset - Validate EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+	s32 ret_val = 0;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Read Error\n");
+			goto out;
+		}
+		checksum += nvm_data;
+	}
+
+	if (checksum != (u16) NVM_SUM) {
+		hw_dbg("NVM Checksum Invalid\n");
+		ret_val = -E1000_ERR_NVM;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_update_nvm_checksum_with_offset - Update EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  up to the checksum.  Then calculates the EEPROM checksum and writes the
+ *  value to the EEPROM.
+ **/
+s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+	s32 ret_val;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Read Error while updating checksum.\n");
+			goto out;
+		}
+		checksum += nvm_data;
+	}
+	checksum = (u16) NVM_SUM - checksum;
+	ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+				&checksum);
+	if (ret_val)
+		hw_dbg("NVM Write Error while updating checksum.\n");
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_validate_nvm_checksum_82580 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 eeprom_regions_count = 1;
+	u16 j, nvm_data;
+	u16 nvm_offset;
+
+	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+	if (ret_val) {
+		hw_dbg("NVM Read Error\n");
+		goto out;
+	}
+
+	if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
+		/* if chekcsums compatibility bit is set validate checksums
+		 * for all 4 ports. */
+		eeprom_regions_count = 4;
+	}
+
+	for (j = 0; j < eeprom_regions_count; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_validate_nvm_checksum_with_offset(hw,
+								nvm_offset);
+		if (ret_val != 0)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_update_nvm_checksum_82580 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw)
+{
+	s32 ret_val;
+	u16 j, nvm_data;
+	u16 nvm_offset;
+
+	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+	if (ret_val) {
+		hw_dbg("NVM Read Error while updating checksum"
+			" compatibility bit.\n");
+		goto out;
+	}
+
+	if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) {
+		/* set compatibility bit to validate checksums appropriately */
+		nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
+		ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
+					&nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Write Error while updating checksum"
+				" compatibility bit.\n");
+			goto out;
+		}
+	}
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 j;
+	u16 nvm_offset;
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_validate_nvm_checksum_with_offset(hw,
+								nvm_offset);
+		if (ret_val != 0)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_update_nvm_checksum_i350 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 j;
+	u16 nvm_offset;
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset);
+		if (ret_val != 0)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+/**
+ *  igb_set_eee_i350 - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable/disable EEE based on setting in dev_spec structure.
+ *
+ **/
+s32 igb_set_eee_i350(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u32 ipcnfg, eeer, ctrl_ext;
+
+	ctrl_ext = rd32(E1000_CTRL_EXT);
+	if ((hw->mac.type != e1000_i350) ||
+	    (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK))
+		goto out;
+	ipcnfg = rd32(E1000_IPCNFG);
+	eeer = rd32(E1000_EEER);
+
+	/* enable or disable per user setting */
+	if (!(hw->dev_spec._82575.eee_disable)) {
+		ipcnfg |= (E1000_IPCNFG_EEE_1G_AN |
+			E1000_IPCNFG_EEE_100M_AN);
+		eeer |= (E1000_EEER_TX_LPI_EN |
+			E1000_EEER_RX_LPI_EN |
+			E1000_EEER_LPI_FC);
+
+	} else {
+		ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN |
+			E1000_IPCNFG_EEE_100M_AN);
+		eeer &= ~(E1000_EEER_TX_LPI_EN |
+			E1000_EEER_RX_LPI_EN |
+			E1000_EEER_LPI_FC);
+	}
+	wr32(E1000_IPCNFG, ipcnfg);
+	wr32(E1000_EEER, eeer);
+out:
+
+	return ret_val;
+}
+
 static struct e1000_mac_operations e1000_mac_ops_82575 = {
 	.init_hw              = igb_init_hw_82575,
 	.check_for_link       = igb_check_for_link_82575,
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index 1d01af2..dd6df34 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -251,5 +251,6 @@ void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
 void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
 void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
 u16 igb_rxpbs_adjust_82580(u32 data);
+s32 igb_set_eee_i350(struct e1000_hw *);
 
 #endif
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 6319ed9..6b80d40 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -51,6 +51,7 @@
 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES  0x00C00000
 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX  0x00400000
 #define E1000_CTRL_EXT_LINK_MODE_SGMII   0x00800000
+#define E1000_CTRL_EXT_LINK_MODE_GMII   0x00000000
 #define E1000_CTRL_EXT_EIAME          0x01000000
 #define E1000_CTRL_EXT_IRCA           0x00000001
 /* Interrupt delay cancellation */
@@ -110,6 +111,7 @@
 /* Management Control */
 #define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
 #define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_EN_BMC2OS     0x10000000 /* OSBMC is Enabled or not */
 /* Enable Neighbor Discovery Filtering */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
 #define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
@@ -286,7 +288,34 @@
 #define E1000_TCTL_COLD   0x003ff000    /* collision distance */
 #define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
 
-/* Transmit Arbitration Count */
+/* DMA Coalescing register fields */
+#define E1000_DMACR_DMACWT_MASK         0x00003FFF /* DMA Coalescing
+							* Watchdog Timer */
+#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Receive
+							* Threshold */
+#define E1000_DMACR_DMACTHR_SHIFT       16
+#define E1000_DMACR_DMAC_LX_MASK        0x30000000 /* Lx when no PCIe
+							* transactions */
+#define E1000_DMACR_DMAC_LX_SHIFT       28
+#define E1000_DMACR_DMAC_EN             0x80000000 /* Enable DMA Coalescing */
+
+#define E1000_DMCTXTH_DMCTTHR_MASK      0x00000FFF /* DMA Coalescing Transmit
+							* Threshold */
+
+#define E1000_DMCTLX_TTLX_MASK          0x00000FFF /* Time to LX request */
+
+#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Receive Traffic Rate
+							* Threshold */
+#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rcv packet rate in
+							* current window */
+
+#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rcv Traffic
+							* Current Cnt */
+
+#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rcv Threshold
+							* High val */
+#define E1000_FCRTC_RTH_COAL_SHIFT      4
+#define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision */
 
 /* SerDes Control */
 #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
@@ -565,6 +594,8 @@
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
 #define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
+#define NVM_COMPATIBILITY_REG_3    0x0003
+#define NVM_COMPATIBILITY_BIT_MASK 0x8000
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
@@ -599,6 +630,7 @@
 /* NVM Commands - SPI */
 #define NVM_MAX_RETRY_SPI          5000 /* Max wait of 5ms, for RDY signal */
 #define NVM_WRITE_OPCODE_SPI       0x02 /* NVM write opcode */
+#define NVM_READ_OPCODE_SPI        0x03 /* NVM read opcode */
 #define NVM_A8_OPCODE_SPI          0x08 /* opcode bit-3 = address bit-8 */
 #define NVM_WREN_OPCODE_SPI        0x06 /* NVM set Write Enable latch */
 #define NVM_RDSR_OPCODE_SPI        0x05 /* NVM read Status register */
@@ -757,6 +789,17 @@
 #define E1000_MDIC_ERROR     0x40000000
 #define E1000_MDIC_DEST      0x80000000
 
+/* Thermal Sensor */
+#define E1000_THSTAT_PWR_DOWN       0x00000001 /* Power Down Event */
+#define E1000_THSTAT_LINK_THROTTLE  0x00000002 /* Link Speed Throttle Event */
+
+/* Energy Efficient Ethernet */
+#define E1000_IPCNFG_EEE_1G_AN       0x00000008  /* EEE Enable 1G AN */
+#define E1000_IPCNFG_EEE_100M_AN     0x00000004  /* EEE Enable 100M AN */
+#define E1000_EEER_TX_LPI_EN         0x00010000  /* EEE Tx LPI Enable */
+#define E1000_EEER_RX_LPI_EN         0x00020000  /* EEE Rx LPI Enable */
+#define E1000_EEER_LPI_FC            0x00040000  /* EEE Enable on FC */
+
 /* SerDes Control */
 #define E1000_GEN_CTL_READY             0x80000000
 #define E1000_GEN_CTL_ADDRESS_SHIFT     8
@@ -770,4 +813,11 @@
 #define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision based
                                                       on DMA coal */
 
+/* Tx Rate-Scheduler Config fields */
+#define E1000_RTTBCNRC_RS_ENA		0x80000000
+#define E1000_RTTBCNRC_RF_DEC_MASK	0x00003FFF
+#define E1000_RTTBCNRC_RF_INT_SHIFT	14
+#define E1000_RTTBCNRC_RF_INT_MASK	\
+	(E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT)
+
 #endif
diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
index e2638af..27153e8 100644
--- a/drivers/net/igb/e1000_hw.h
+++ b/drivers/net/igb/e1000_hw.h
@@ -54,6 +54,7 @@ struct e1000_hw;
 #define E1000_DEV_ID_82580_SERDES             0x1510
 #define E1000_DEV_ID_82580_SGMII              0x1511
 #define E1000_DEV_ID_82580_COPPER_DUAL        0x1516
+#define E1000_DEV_ID_82580_QUAD_FIBER         0x1527
 #define E1000_DEV_ID_DH89XXCC_SGMII           0x0438
 #define E1000_DEV_ID_DH89XXCC_SERDES          0x043A
 #define E1000_DEV_ID_DH89XXCC_BACKPLANE       0x043C
@@ -247,6 +248,10 @@ struct e1000_hw_stats {
 	u64 scvpc;
 	u64 hrmpc;
 	u64 doosync;
+	u64 o2bgptc;
+	u64 o2bspc;
+	u64 b2ospc;
+	u64 b2ogprc;
 };
 
 struct e1000_phy_stats {
@@ -331,6 +336,8 @@ struct e1000_nvm_operations {
 	s32  (*read)(struct e1000_hw *, u16, u16, u16 *);
 	void (*release)(struct e1000_hw *);
 	s32  (*write)(struct e1000_hw *, u16, u16, u16 *);
+	s32  (*update)(struct e1000_hw *);
+	s32  (*validate)(struct e1000_hw *);
 };
 
 struct e1000_info {
@@ -417,7 +424,6 @@ struct e1000_phy_info {
 
 struct e1000_nvm_info {
 	struct e1000_nvm_operations ops;
-
 	enum e1000_nvm_type type;
 	enum e1000_nvm_override override;
 
@@ -483,6 +489,7 @@ struct e1000_mbx_info {
 struct e1000_dev_spec_82575 {
 	bool sgmii_active;
 	bool global_device_reset;
+	bool eee_disable;
 };
 
 struct e1000_hw {
diff --git a/drivers/net/igb/e1000_mbx.c b/drivers/net/igb/e1000_mbx.c
index c474cdb..78d48c7 100644
--- a/drivers/net/igb/e1000_mbx.c
+++ b/drivers/net/igb/e1000_mbx.c
@@ -422,26 +422,24 @@ s32 igb_init_mbx_params_pf(struct e1000_hw *hw)
 {
 	struct e1000_mbx_info *mbx = &hw->mbx;
 
-	if (hw->mac.type == e1000_82576) {
-		mbx->timeout = 0;
-		mbx->usec_delay = 0;
-
-		mbx->size = E1000_VFMAILBOX_SIZE;
-
-		mbx->ops.read = igb_read_mbx_pf;
-		mbx->ops.write = igb_write_mbx_pf;
-		mbx->ops.read_posted = igb_read_posted_mbx;
-		mbx->ops.write_posted = igb_write_posted_mbx;
-		mbx->ops.check_for_msg = igb_check_for_msg_pf;
-		mbx->ops.check_for_ack = igb_check_for_ack_pf;
-		mbx->ops.check_for_rst = igb_check_for_rst_pf;
-
-		mbx->stats.msgs_tx = 0;
-		mbx->stats.msgs_rx = 0;
-		mbx->stats.reqs = 0;
-		mbx->stats.acks = 0;
-		mbx->stats.rsts = 0;
-	}
+	mbx->timeout = 0;
+	mbx->usec_delay = 0;
+
+	mbx->size = E1000_VFMAILBOX_SIZE;
+
+	mbx->ops.read = igb_read_mbx_pf;
+	mbx->ops.write = igb_write_mbx_pf;
+	mbx->ops.read_posted = igb_read_posted_mbx;
+	mbx->ops.write_posted = igb_write_posted_mbx;
+	mbx->ops.check_for_msg = igb_check_for_msg_pf;
+	mbx->ops.check_for_ack = igb_check_for_ack_pf;
+	mbx->ops.check_for_rst = igb_check_for_rst_pf;
+
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 0;
 
 	return 0;
 }
diff --git a/drivers/net/igb/e1000_nvm.c b/drivers/net/igb/e1000_nvm.c
index 6b5cc2c..75bf36a 100644
--- a/drivers/net/igb/e1000_nvm.c
+++ b/drivers/net/igb/e1000_nvm.c
@@ -318,6 +318,68 @@ out:
 }
 
 /**
+ *  igb_read_nvm_spi - Read EEPROM's using SPI
+ *  @hw: pointer to the HW structure
+ *  @offset: offset of word in the EEPROM to read
+ *  @words: number of words to read
+ *  @data: word read from the EEPROM
+ *
+ *  Reads a 16 bit word from the EEPROM.
+ **/
+s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+	struct e1000_nvm_info *nvm = &hw->nvm;
+	u32 i = 0;
+	s32 ret_val;
+	u16 word_in;
+	u8 read_opcode = NVM_READ_OPCODE_SPI;
+
+	/*
+	 * A check for invalid values:  offset too large, too many words,
+	 * and not enough words.
+	 */
+	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+	    (words == 0)) {
+		hw_dbg("nvm parameter(s) out of bounds\n");
+		ret_val = -E1000_ERR_NVM;
+		goto out;
+	}
+
+	ret_val = nvm->ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igb_ready_nvm_eeprom(hw);
+	if (ret_val)
+		goto release;
+
+	igb_standby_nvm(hw);
+
+	if ((nvm->address_bits == 8) && (offset >= 128))
+		read_opcode |= NVM_A8_OPCODE_SPI;
+
+	/* Send the READ command (opcode + addr) */
+	igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
+	igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
+
+	/*
+	 * Read the data.  SPI NVMs increment the address with each byte
+	 * read and will roll over if reading beyond the end.  This allows
+	 * us to read the whole NVM from any offset
+	 */
+	for (i = 0; i < words; i++) {
+		word_in = igb_shift_in_eec_bits(hw, 16);
+		data[i] = (word_in >> 8) | (word_in << 8);
+	}
+
+release:
+	nvm->ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
  *  igb_read_nvm_eerd - Reads EEPROM using EERD register
  *  @hw: pointer to the HW structure
  *  @offset: offset of word in the EEPROM to read
@@ -353,7 +415,7 @@ s32 igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 			break;
 
 		data[i] = (rd32(E1000_EERD) >>
-			   E1000_NVM_RW_REG_DATA);
+			E1000_NVM_RW_REG_DATA);
 	}
 
 out:
diff --git a/drivers/net/igb/e1000_nvm.h b/drivers/net/igb/e1000_nvm.h
index 29c956a..7f43564 100644
--- a/drivers/net/igb/e1000_nvm.h
+++ b/drivers/net/igb/e1000_nvm.h
@@ -35,6 +35,7 @@ s32  igb_read_part_num(struct e1000_hw *hw, u32 *part_num);
 s32  igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
                           u32 part_num_size);
 s32  igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+s32  igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_validate_nvm_checksum(struct e1000_hw *hw);
 s32  igb_update_nvm_checksum(struct e1000_hw *hw);
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 8ac83c5..958ca3b 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -106,6 +106,19 @@
 
 #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
 
+/* DMA Coalescing registers */
+#define E1000_DMACR             0x02508 /* Control Register */
+#define E1000_DMCTXTH           0x03550 /* Transmit Threshold */
+#define E1000_DMCTLX            0x02514 /* Time to Lx Request */
+#define E1000_DMCRTRH           0x05DD0 /* Receive Packet Rate Threshold */
+#define E1000_DMCCNT            0x05DD4 /* Current Rx Count */
+#define E1000_FCRTC             0x02170 /* Flow Control Rx high watermark */
+#define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */
+
+/* TX Rate Limit Registers */
+#define E1000_RTTDQSEL	0x3604	/* Tx Desc Plane Queue Select - WO */
+#define E1000_RTTBCNRC	0x36B0	/* Tx BCN Rate-Scheduler Config - WO */
+
 /* Split and Replication RX Control - RW */
 #define E1000_RXPBS    0x02404  /* Rx Packet Buffer Size - RW */
 /*
@@ -324,4 +337,18 @@
 
 /* DMA Coalescing registers */
 #define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */
+
+/* Energy Efficient Ethernet "EEE" register */
+#define E1000_IPCNFG  0x0E38  /* Internal PHY Configuration */
+#define E1000_EEER    0x0E30  /* Energy Efficient Ethernet */
+
+/* Thermal Sensor Register */
+#define E1000_THSTAT    0x08110 /* Thermal Sensor Status */
+
+/* OS2BMC Registers */
+#define E1000_B2OSPC    0x08FE0 /* BMC2OS packets sent by BMC */
+#define E1000_B2OGPRC   0x04158 /* BMC2OS packets received by host */
+#define E1000_O2BGPTC   0x08FE4 /* OS2BMC packets received by BMC */
+#define E1000_O2BSPC    0x0415C /* OS2BMC packets transmitted by host */
+
 #endif
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 92a4ef0..1c687e2 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -77,6 +77,7 @@ struct vf_data_storage {
 	unsigned long last_nack;
 	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
 	u16 pf_qos;
+	u16 tx_rate;
 };
 
 #define IGB_VF_FLAG_CTS            0x00000001 /* VF is clear to send data */
@@ -323,6 +324,7 @@ struct igb_adapter {
 	u16 rx_ring_count;
 	unsigned int vfs_allocated_count;
 	struct vf_data_storage *vf_data;
+	int vf_rate_link_speed;
 	u32 rss_queues;
 	u32 wvbr;
 };
@@ -331,6 +333,12 @@ struct igb_adapter {
 #define IGB_FLAG_DCA_ENABLED       (1 << 1)
 #define IGB_FLAG_QUAD_PORT_A       (1 << 2)
 #define IGB_FLAG_QUEUE_PAIRS       (1 << 3)
+#define IGB_FLAG_DMAC              (1 << 4)
+
+/* DMA Coalescing defines */
+#define IGB_MIN_TXPBSIZE           20408
+#define IGB_TX_BUF_4096            4096
+#define IGB_DMCTLX_DCFLUSH_DIS     0x80000000  /* Disable DMA Coal Flush */
 
 #define IGB_82576_TSYNC_SHIFT 19
 #define IGB_82580_TSYNC_SHIFT 24
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index a70e16b..d976733 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -86,6 +86,10 @@ static const struct igb_stats igb_gstrings_stats[] = {
 	IGB_STAT("tx_smbus", stats.mgptc),
 	IGB_STAT("rx_smbus", stats.mgprc),
 	IGB_STAT("dropped_smbus", stats.mgpdc),
+	IGB_STAT("os2bmc_rx_by_bmc", stats.o2bgptc),
+	IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
+	IGB_STAT("os2bmc_tx_by_host", stats.o2bspc),
+	IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc),
 };
 
 #define IGB_NETDEV_STAT(_net_stat) { \
@@ -603,7 +607,10 @@ static void igb_get_regs(struct net_device *netdev,
 	regs_buff[548] = rd32(E1000_TDFT);
 	regs_buff[549] = rd32(E1000_TDFHS);
 	regs_buff[550] = rd32(E1000_TDFPC);
-
+	regs_buff[551] = adapter->stats.o2bgptc;
+	regs_buff[552] = adapter->stats.b2ospc;
+	regs_buff[553] = adapter->stats.o2bspc;
+	regs_buff[554] = adapter->stats.b2ogprc;
 }
 
 static int igb_get_eeprom_len(struct net_device *netdev)
@@ -714,7 +721,7 @@ static int igb_set_eeprom(struct net_device *netdev,
 	/* Update the checksum over the first part of the EEPROM if needed
 	 * and flush shadow RAM for 82573 controllers */
 	if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG)))
-		igb_update_nvm_checksum(hw);
+		hw->nvm.ops.update(hw);
 
 	kfree(eeprom_buff);
 	return ret_val;
@@ -727,8 +734,9 @@ static void igb_get_drvinfo(struct net_device *netdev,
 	char firmware_version[32];
 	u16 eeprom_data;
 
-	strncpy(drvinfo->driver,  igb_driver_name, 32);
-	strncpy(drvinfo->version, igb_driver_version, 32);
+	strncpy(drvinfo->driver,  igb_driver_name, sizeof(drvinfo->driver) - 1);
+	strncpy(drvinfo->version, igb_driver_version,
+		sizeof(drvinfo->version) - 1);
 
 	/* EEPROM image version # is reported as firmware version # for
 	 * 82575 controllers */
@@ -738,8 +746,10 @@ static void igb_get_drvinfo(struct net_device *netdev,
 		(eeprom_data & 0x0FF0) >> 4,
 		eeprom_data & 0x000F);
 
-	strncpy(drvinfo->fw_version, firmware_version, 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	strncpy(drvinfo->fw_version, firmware_version,
+		sizeof(drvinfo->fw_version) - 1);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info) - 1);
 	drvinfo->n_stats = IGB_STATS_LEN;
 	drvinfo->testinfo_len = IGB_TEST_LEN;
 	drvinfo->regdump_len = igb_get_regs_len(netdev);
@@ -1070,7 +1080,7 @@ static bool reg_pattern_test(struct igb_adapter *adapter, u64 *data,
 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
 	for (pat = 0; pat < ARRAY_SIZE(_test); pat++) {
 		wr32(reg, (_test[pat] & write));
-		val = rd32(reg);
+		val = rd32(reg) & mask;
 		if (val != (_test[pat] & write & mask)) {
 			dev_err(&adapter->pdev->dev, "pattern test reg %04X "
 				"failed: got 0x%08X expected 0x%08X\n",
@@ -1999,6 +2009,12 @@ static int igb_set_coalesce(struct net_device *netdev,
 	if ((adapter->flags & IGB_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs)
 		return -EINVAL;
 
+	/* If ITR is disabled, disable DMAC */
+	if (ec->rx_coalesce_usecs == 0) {
+		if (adapter->flags & IGB_FLAG_DMAC)
+			adapter->flags &= ~IGB_FLAG_DMAC;
+	}
+
 	/* convert to rate of irq's per second */
 	if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3)
 		adapter->rx_itr_setting = ec->rx_coalesce_usecs;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 58c665b..3d850af 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -50,12 +50,17 @@
 #endif
 #include "igb.h"
 
-#define DRV_VERSION "2.1.0-k2"
+#define MAJ 3
+#define MIN 0
+#define BUILD 6
+#define KFIX 2
+#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
+__stringify(BUILD) "-k" __stringify(KFIX)
 char igb_driver_name[] = "igb";
 char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
 				"Intel(R) Gigabit Ethernet Network Driver";
-static const char igb_copyright[] = "Copyright (c) 2007-2009 Intel Corporation.";
+static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation.";
 
 static const struct e1000_info *igb_info_tbl[] = {
 	[board_82575] = &e1000_82575_info,
@@ -68,6 +73,7 @@ static DEFINE_PCI_DEVICE_TABLE(igb_pci_tbl) = {
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
@@ -100,6 +106,7 @@ static void igb_free_all_rx_resources(struct igb_adapter *);
 static void igb_setup_mrqc(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
 static void __devexit igb_remove(struct pci_dev *pdev);
+static void igb_init_hw_timer(struct igb_adapter *adapter);
 static int igb_sw_init(struct igb_adapter *);
 static int igb_open(struct net_device *);
 static int igb_close(struct net_device *);
@@ -149,6 +156,7 @@ static int igb_ndo_set_vf_vlan(struct net_device *netdev,
 static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
 static int igb_ndo_get_vf_config(struct net_device *netdev, int vf,
 				 struct ifla_vf_info *ivi);
+static void igb_check_vf_rate_limit(struct igb_adapter *);
 
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
@@ -1672,7 +1680,58 @@ void igb_reset(struct igb_adapter *adapter)
 
 	if (hw->mac.ops.init_hw(hw))
 		dev_err(&pdev->dev, "Hardware Error\n");
+	if (hw->mac.type > e1000_82580) {
+		if (adapter->flags & IGB_FLAG_DMAC) {
+			u32 reg;
 
+			/*
+			 * DMA Coalescing high water mark needs to be higher
+			 * than * the * Rx threshold.  The Rx threshold is
+			 * currently * pba - 6, so we * should use a high water
+			 * mark of pba * - 4. */
+			hwm = (pba - 4) << 10;
+
+			reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT)
+			       & E1000_DMACR_DMACTHR_MASK);
+
+			/* transition to L0x or L1 if available..*/
+			reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
+
+			/* watchdog timer= +-1000 usec in 32usec intervals */
+			reg |= (1000 >> 5);
+			wr32(E1000_DMACR, reg);
+
+			/* no lower threshold to disable coalescing(smart fifb)
+			 * -UTRESH=0*/
+			wr32(E1000_DMCRTRH, 0);
+
+			/* set hwm to PBA -  2 * max frame size */
+			wr32(E1000_FCRTC, hwm);
+
+			/*
+			 * This sets the time to wait before requesting tran-
+			 * sition to * low power state to number of usecs needed
+			 * to receive 1 512 * byte frame at gigabit line rate
+			 */
+			reg = rd32(E1000_DMCTLX);
+			reg |= IGB_DMCTLX_DCFLUSH_DIS;
+
+			/* Delay 255 usec before entering Lx state. */
+			reg |= 0xFF;
+			wr32(E1000_DMCTLX, reg);
+
+			/* free space in Tx packet buffer to wake from DMAC */
+			wr32(E1000_DMCTXTH,
+			     (IGB_MIN_TXPBSIZE -
+			     (IGB_TX_BUF_4096 + adapter->max_frame_size))
+			     >> 6);
+
+			/* make low power state decision controlled by DMAC */
+			reg = rd32(E1000_PCIEMISC);
+			reg |= E1000_PCIEMISC_LX_DECISION;
+			wr32(E1000_PCIEMISC, reg);
+		} /* end if IGB_FLAG_DMAC set */
+	}
 	if (hw->mac.type == e1000_82580) {
 		u32 reg = rd32(E1000_PCIEMISC);
 		wr32(E1000_PCIEMISC,
@@ -1882,7 +1941,7 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 	hw->mac.ops.reset_hw(hw);
 
 	/* make sure the NVM is good */
-	if (igb_validate_nvm_checksum(hw) < 0) {
+	if (hw->nvm.ops.validate(hw) < 0) {
 		dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
 		err = -EIO;
 		goto err_eeprom;
@@ -1990,6 +2049,9 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 	}
 
 #endif
+	/* do hw tstamp init after resetting */
+	igb_init_hw_timer(adapter);
+
 	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
 	/* print bus type/speed/width info */
 	dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
@@ -2012,7 +2074,13 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 		adapter->msix_entries ? "MSI-X" :
 		(adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy",
 		adapter->num_rx_queues, adapter->num_tx_queues);
-
+	switch (hw->mac.type) {
+	case e1000_i350:
+		igb_set_eee_i350(hw);
+		break;
+	default:
+		break;
+	}
 	return 0;
 
 err_register:
@@ -2149,6 +2217,9 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
 			random_ether_addr(mac_addr);
 			igb_set_vf_mac(adapter, i, mac_addr);
 		}
+		/* DMA Coalescing is not supported in IOV mode. */
+		if (adapter->flags & IGB_FLAG_DMAC)
+			adapter->flags &= ~IGB_FLAG_DMAC;
 	}
 #endif /* CONFIG_PCI_IOV */
 }
@@ -2286,9 +2357,19 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
 
 	spin_lock_init(&adapter->stats64_lock);
 #ifdef CONFIG_PCI_IOV
-	if (hw->mac.type == e1000_82576)
-		adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs;
-
+	switch (hw->mac.type) {
+	case e1000_82576:
+	case e1000_i350:
+		if (max_vfs > 7) {
+			dev_warn(&pdev->dev,
+				 "Maximum of 7 VFs per PF, using max\n");
+			adapter->vfs_allocated_count = 7;
+		} else
+			adapter->vfs_allocated_count = max_vfs;
+		break;
+	default:
+		break;
+	}
 #endif /* CONFIG_PCI_IOV */
 	adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
 
@@ -2307,12 +2388,14 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
 		return -ENOMEM;
 	}
 
-	igb_init_hw_timer(adapter);
 	igb_probe_vfs(adapter);
 
 	/* Explicitly disable IRQ since the NIC can be in any state. */
 	igb_irq_disable(adapter);
 
+	if (hw->mac.type == e1000_i350)
+		adapter->flags &= ~IGB_FLAG_DMAC;
+
 	set_bit(__IGB_DOWN, &adapter->state);
 	return 0;
 }
@@ -3467,7 +3550,7 @@ static void igb_watchdog_task(struct work_struct *work)
                                                    watchdog_task);
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
-	u32 link;
+	u32 link, ctrl_ext, thstat;
 	int i;
 
 	link = igb_has_link(adapter);
@@ -3491,6 +3574,25 @@ static void igb_watchdog_task(struct work_struct *work)
 			       ((ctrl & E1000_CTRL_RFCE) ?  "RX" :
 			       ((ctrl & E1000_CTRL_TFCE) ?  "TX" : "None")));
 
+			/* check for thermal sensor event on i350,
+			 * copper only */
+			if (hw->mac.type == e1000_i350) {
+				thstat = rd32(E1000_THSTAT);
+				ctrl_ext = rd32(E1000_CTRL_EXT);
+				if ((hw->phy.media_type ==
+				     e1000_media_type_copper) && !(ctrl_ext &
+				     E1000_CTRL_EXT_LINK_MODE_SGMII)) {
+					if (thstat &
+					    E1000_THSTAT_LINK_THROTTLE) {
+						printk(KERN_INFO "igb: %s The "
+						       "network adapter link "
+						       "speed was downshifted "
+						       "because it "
+						       "overheated.\n",
+						       netdev->name);
+					}
+				}
+			}
 			/* adjust timeout factor according to speed/duplex */
 			adapter->tx_timeout_factor = 1;
 			switch (adapter->link_speed) {
@@ -3505,6 +3607,7 @@ static void igb_watchdog_task(struct work_struct *work)
 			netif_carrier_on(netdev);
 
 			igb_ping_all_vfs(adapter);
+			igb_check_vf_rate_limit(adapter);
 
 			/* link state has changed, schedule phy info update */
 			if (!test_bit(__IGB_DOWN, &adapter->state))
@@ -3515,6 +3618,22 @@ static void igb_watchdog_task(struct work_struct *work)
 		if (netif_carrier_ok(netdev)) {
 			adapter->link_speed = 0;
 			adapter->link_duplex = 0;
+			/* check for thermal sensor event on i350
+			 * copper only*/
+			if (hw->mac.type == e1000_i350) {
+				thstat = rd32(E1000_THSTAT);
+				ctrl_ext = rd32(E1000_CTRL_EXT);
+				if ((hw->phy.media_type ==
+				     e1000_media_type_copper) && !(ctrl_ext &
+				     E1000_CTRL_EXT_LINK_MODE_SGMII)) {
+					if (thstat & E1000_THSTAT_PWR_DOWN) {
+						printk(KERN_ERR "igb: %s The "
+						"network adapter was stopped "
+						"because it overheated.\n",
+						netdev->name);
+					}
+				}
+			}
 			/* Links status message must follow this format */
 			printk(KERN_INFO "igb: %s NIC Link is Down\n",
 			       netdev->name);
@@ -4547,6 +4666,15 @@ void igb_update_stats(struct igb_adapter *adapter,
 	adapter->stats.mgptc += rd32(E1000_MGTPTC);
 	adapter->stats.mgprc += rd32(E1000_MGTPRC);
 	adapter->stats.mgpdc += rd32(E1000_MGTPDC);
+
+	/* OS2BMC Stats */
+	reg = rd32(E1000_MANC);
+	if (reg & E1000_MANC_EN_BMC2OS) {
+		adapter->stats.o2bgptc += rd32(E1000_O2BGPTC);
+		adapter->stats.o2bspc += rd32(E1000_O2BSPC);
+		adapter->stats.b2ospc += rd32(E1000_B2OSPC);
+		adapter->stats.b2ogprc += rd32(E1000_B2OGPRC);
+	}
 }
 
 static irqreturn_t igb_msix_other(int irq, void *data)
@@ -6593,9 +6721,91 @@ static int igb_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 	return igb_set_vf_mac(adapter, vf, mac);
 }
 
+static int igb_link_mbps(int internal_link_speed)
+{
+	switch (internal_link_speed) {
+	case SPEED_100:
+		return 100;
+	case SPEED_1000:
+		return 1000;
+	default:
+		return 0;
+	}
+}
+
+static void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate,
+				  int link_speed)
+{
+	int rf_dec, rf_int;
+	u32 bcnrc_val;
+
+	if (tx_rate != 0) {
+		/* Calculate the rate factor values to set */
+		rf_int = link_speed / tx_rate;
+		rf_dec = (link_speed - (rf_int * tx_rate));
+		rf_dec = (rf_dec * (1<<E1000_RTTBCNRC_RF_INT_SHIFT)) / tx_rate;
+
+		bcnrc_val = E1000_RTTBCNRC_RS_ENA;
+		bcnrc_val |= ((rf_int<<E1000_RTTBCNRC_RF_INT_SHIFT) &
+		               E1000_RTTBCNRC_RF_INT_MASK);
+		bcnrc_val |= (rf_dec & E1000_RTTBCNRC_RF_DEC_MASK);
+	} else {
+		bcnrc_val = 0;
+	}
+
+	wr32(E1000_RTTDQSEL, vf); /* vf X uses queue X */
+	wr32(E1000_RTTBCNRC, bcnrc_val);
+}
+
+static void igb_check_vf_rate_limit(struct igb_adapter *adapter)
+{
+	int actual_link_speed, i;
+	bool reset_rate = false;
+
+	/* VF TX rate limit was not set or not supported */
+	if ((adapter->vf_rate_link_speed == 0) ||
+	    (adapter->hw.mac.type != e1000_82576))
+		return;
+
+	actual_link_speed = igb_link_mbps(adapter->link_speed);
+	if (actual_link_speed != adapter->vf_rate_link_speed) {
+		reset_rate = true;
+		adapter->vf_rate_link_speed = 0;
+		dev_info(&adapter->pdev->dev,
+		         "Link speed has been changed. VF Transmit "
+		         "rate is disabled\n");
+	}
+
+	for (i = 0; i < adapter->vfs_allocated_count; i++) {
+		if (reset_rate)
+			adapter->vf_data[i].tx_rate = 0;
+
+		igb_set_vf_rate_limit(&adapter->hw, i,
+		                      adapter->vf_data[i].tx_rate,
+		                      actual_link_speed);
+	}
+}
+
 static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
 {
-	return -EOPNOTSUPP;
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	int actual_link_speed;
+
+	if (hw->mac.type != e1000_82576)
+		return -EOPNOTSUPP;
+
+	actual_link_speed = igb_link_mbps(adapter->link_speed);
+	if ((vf >= adapter->vfs_allocated_count) ||
+	    (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) ||
+	    (tx_rate < 0) || (tx_rate > actual_link_speed))
+		return -EINVAL;
+
+	adapter->vf_rate_link_speed = actual_link_speed;
+	adapter->vf_data[vf].tx_rate = (u16)tx_rate;
+	igb_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed);
+
+	return 0;
 }
 
 static int igb_ndo_get_vf_config(struct net_device *netdev,
@@ -6606,7 +6816,7 @@ static int igb_ndo_get_vf_config(struct net_device *netdev,
 		return -EINVAL;
 	ivi->vf = vf;
 	memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN);
-	ivi->tx_rate = 0;
+	ivi->tx_rate = adapter->vf_data[vf].tx_rate;
 	ivi->vlan = adapter->vf_data[vf].pf_vlan;
 	ivi->qos = adapter->vf_data[vf].pf_qos;
 	return 0;
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index ed6e3d9..1d943aa 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -201,13 +201,11 @@ static void igbvf_get_regs(struct net_device *netdev,
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	u32 *regs_buff = p;
-	u8 revision_id;
 
 	memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
 
-	pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
-
-	regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
+	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
+			adapter->pdev->device;
 
 	regs_buff[0] = er32(CTRL);
 	regs_buff[1] = er32(STATUS);
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h
index 990c329..d5dad5d 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/igbvf/igbvf.h
@@ -201,9 +201,6 @@ struct igbvf_adapter {
 	unsigned int restart_queue;
 	u32 txd_cmd;
 
-	bool detect_tx_hung;
-	u8 tx_timeout_factor;
-
 	u32 tx_int_delay;
 	u32 tx_abs_int_delay;
 
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 6352c81..6ccc32f 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -396,35 +396,6 @@ static void igbvf_put_txbuf(struct igbvf_adapter *adapter,
 	buffer_info->time_stamp = 0;
 }
 
-static void igbvf_print_tx_hang(struct igbvf_adapter *adapter)
-{
-	struct igbvf_ring *tx_ring = adapter->tx_ring;
-	unsigned int i = tx_ring->next_to_clean;
-	unsigned int eop = tx_ring->buffer_info[i].next_to_watch;
-	union e1000_adv_tx_desc *eop_desc = IGBVF_TX_DESC_ADV(*tx_ring, eop);
-
-	/* detected Tx unit hang */
-	dev_err(&adapter->pdev->dev,
-	        "Detected Tx Unit Hang:\n"
-	        "  TDH                  <%x>\n"
-	        "  TDT                  <%x>\n"
-	        "  next_to_use          <%x>\n"
-	        "  next_to_clean        <%x>\n"
-	        "buffer_info[next_to_clean]:\n"
-	        "  time_stamp           <%lx>\n"
-	        "  next_to_watch        <%x>\n"
-	        "  jiffies              <%lx>\n"
-	        "  next_to_watch.status <%x>\n",
-	        readl(adapter->hw.hw_addr + tx_ring->head),
-	        readl(adapter->hw.hw_addr + tx_ring->tail),
-	        tx_ring->next_to_use,
-	        tx_ring->next_to_clean,
-	        tx_ring->buffer_info[eop].time_stamp,
-	        eop,
-	        jiffies,
-	        eop_desc->wb.status);
-}
-
 /**
  * igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
  * @adapter: board private structure
@@ -771,7 +742,6 @@ static void igbvf_set_itr(struct igbvf_adapter *adapter)
 static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring)
 {
 	struct igbvf_adapter *adapter = tx_ring->adapter;
-	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct igbvf_buffer *buffer_info;
 	struct sk_buff *skb;
@@ -832,22 +802,6 @@ static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring)
 		}
 	}
 
-	if (adapter->detect_tx_hung) {
-		/* Detect a transmit hang in hardware, this serializes the
-		 * check with the clearing of time_stamp and movement of i */
-		adapter->detect_tx_hung = false;
-		if (tx_ring->buffer_info[i].time_stamp &&
-		    time_after(jiffies, tx_ring->buffer_info[i].time_stamp +
-		               (adapter->tx_timeout_factor * HZ)) &&
-		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
-
-			tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i);
-			/* detected Tx unit hang */
-			igbvf_print_tx_hang(adapter);
-
-			netif_stop_queue(netdev);
-		}
-	}
 	adapter->net_stats.tx_bytes += total_bytes;
 	adapter->net_stats.tx_packets += total_packets;
 	return count < tx_ring->count;
@@ -1863,17 +1817,6 @@ static void igbvf_watchdog_task(struct work_struct *work)
 			                          &adapter->link_duplex);
 			igbvf_print_link_info(adapter);
 
-			/* adjust timeout factor according to speed/duplex */
-			adapter->tx_timeout_factor = 1;
-			switch (adapter->link_speed) {
-			case SPEED_10:
-				adapter->tx_timeout_factor = 16;
-				break;
-			case SPEED_100:
-				/* maybe add some timeout factor ? */
-				break;
-			}
-
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
 		}
@@ -1907,9 +1850,6 @@ static void igbvf_watchdog_task(struct work_struct *work)
 	/* Cause software interrupt to ensure Rx ring is cleaned */
 	ew32(EICS, adapter->rx_ring->eims_value);
 
-	/* Force detection of hung controller every watchdog period */
-	adapter->detect_tx_hung = 1;
-
 	/* Reset the timer */
 	if (!test_bit(__IGBVF_DOWN, &adapter->state))
 		mod_timer(&adapter->watchdog_timer,
@@ -2699,8 +2639,7 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
-
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+	hw->revision_id = pdev->revision;
 
 	err = -EIO;
 	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0),
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index aa93655..a5b0f0e 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -2025,7 +2025,6 @@ static void ipg_init_mii(struct net_device *dev)
 
 	if (phyaddr != 0x1f) {
 		u16 mii_phyctrl, mii_1000cr;
-		u8 revisionid = 0;
 
 		mii_1000cr  = mdio_read(dev, phyaddr, MII_CTRL1000);
 		mii_1000cr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF |
@@ -2035,8 +2034,7 @@ static void ipg_init_mii(struct net_device *dev)
 		mii_phyctrl = mdio_read(dev, phyaddr, MII_BMCR);
 
 		/* Set default phyparam */
-		pci_read_config_byte(sp->pdev, PCI_REVISION_ID, &revisionid);
-		ipg_set_phy_default_param(revisionid, dev, phyaddr);
+		ipg_set_phy_default_param(sp->pdev->revision, dev, phyaddr);
 
 		/* Reset PHY */
 		mii_phyctrl |= BMCR_RESET | BMCR_ANRESTART;
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index ee1dde5..3352b24 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -167,7 +167,7 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
 	 * let's be careful... Jean II
 	 */
 	IRDA_ASSERT(priv->tty->ops->tiocmset != NULL, return -1;);
-	priv->tty->ops->tiocmset(priv->tty, NULL, set, clear);
+	priv->tty->ops->tiocmset(priv->tty, set, clear);
 
 	return 0;
 }
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 521c0c7..8f3df04 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -149,7 +149,7 @@ struct ixgb_desc_ring {
 
 struct ixgb_adapter {
 	struct timer_list watchdog_timer;
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u32 bd_number;
 	u32 rx_buffer_len;
 	u32 part_num;
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index 43994c1..cc53aa1 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -706,6 +706,43 @@ ixgb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
 	}
 }
 
+static int ixgb_set_flags(struct net_device *netdev, u32 data)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	bool need_reset;
+	int rc;
+
+	/*
+	 * Tx VLAN insertion does not work per HW design when Rx stripping is
+	 * disabled.  Disable txvlan when rxvlan is turned off, and enable
+	 * rxvlan when txvlan is turned on.
+	 */
+	if (!(data & ETH_FLAG_RXVLAN) &&
+	    (netdev->features & NETIF_F_HW_VLAN_TX))
+		data &= ~ETH_FLAG_TXVLAN;
+	else if (data & ETH_FLAG_TXVLAN)
+		data |= ETH_FLAG_RXVLAN;
+
+	need_reset = (data & ETH_FLAG_RXVLAN) !=
+		     (netdev->features & NETIF_F_HW_VLAN_RX);
+
+	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
+						ETH_FLAG_TXVLAN);
+	if (rc)
+		return rc;
+
+	if (need_reset) {
+		if (netif_running(netdev)) {
+			ixgb_down(adapter, true);
+			ixgb_up(adapter);
+			ixgb_set_speed_duplex(netdev);
+		} else
+			ixgb_reset(adapter);
+	}
+
+	return 0;
+}
+
 static const struct ethtool_ops ixgb_ethtool_ops = {
 	.get_settings = ixgb_get_settings,
 	.set_settings = ixgb_set_settings,
@@ -732,6 +769,8 @@ static const struct ethtool_ops ixgb_ethtool_ops = {
 	.phys_id = ixgb_phys_id,
 	.get_sset_count = ixgb_get_sset_count,
 	.get_ethtool_stats = ixgb_get_ethtool_stats,
+	.get_flags = ethtool_op_get_flags,
+	.set_flags = ixgb_set_flags,
 };
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 5639ccc..0f681ac 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -100,8 +100,6 @@ static void ixgb_tx_timeout_task(struct work_struct *work);
 
 static void ixgb_vlan_strip_enable(struct ixgb_adapter *adapter);
 static void ixgb_vlan_strip_disable(struct ixgb_adapter *adapter);
-static void ixgb_vlan_rx_register(struct net_device *netdev,
-                                  struct vlan_group *grp);
 static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
 static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
 static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
@@ -336,7 +334,6 @@ static const struct net_device_ops ixgb_netdev_ops = {
 	.ndo_set_mac_address	= ixgb_set_mac,
 	.ndo_change_mtu		= ixgb_change_mtu,
 	.ndo_tx_timeout		= ixgb_tx_timeout,
-	.ndo_vlan_rx_register	= ixgb_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= ixgb_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= ixgb_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1508,7 +1505,7 @@ ixgb_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
                      DESC_NEEDED)))
 		return NETDEV_TX_BUSY;
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= IXGB_TX_FLAGS_VLAN;
 		vlan_id = vlan_tx_tag_get(skb);
 	}
@@ -2049,12 +2046,11 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
 		ixgb_rx_checksum(adapter, rx_desc, skb);
 
 		skb->protocol = eth_type_trans(skb, netdev);
-		if (adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) {
-			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-			                        le16_to_cpu(rx_desc->special));
-		} else {
-			netif_receive_skb(skb);
-		}
+		if (status & IXGB_RX_DESC_STATUS_VP)
+			__vlan_hwaccel_put_tag(skb,
+					       le16_to_cpu(rx_desc->special));
+
+		netif_receive_skb(skb);
 
 rxdesc_done:
 		/* clean up descriptor, might be written over by hw */
@@ -2152,20 +2148,6 @@ map_skb:
 	}
 }
 
-/**
- * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping.
- *
- * @param netdev network interface device structure
- * @param grp indicates to enable or disable tagging/stripping
- **/
-static void
-ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct ixgb_adapter *adapter = netdev_priv(netdev);
-
-	adapter->vlgrp = grp;
-}
-
 static void
 ixgb_vlan_strip_enable(struct ixgb_adapter *adapter)
 {
@@ -2200,6 +2182,7 @@ ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
 	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta |= (1 << (vid & 0x1F));
 	ixgb_write_vfta(&adapter->hw, index, vfta);
+	set_bit(vid, adapter->active_vlans);
 }
 
 static void
@@ -2208,35 +2191,22 @@ ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	u32 vfta, index;
 
-	ixgb_irq_disable(adapter);
-
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
-	/* don't enable interrupts unless we are UP */
-	if (adapter->netdev->flags & IFF_UP)
-		ixgb_irq_enable(adapter);
-
 	/* remove VID from filter table */
 
 	index = (vid >> 5) & 0x7F;
 	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta &= ~(1 << (vid & 0x1F));
 	ixgb_write_vfta(&adapter->hw, index, vfta);
+	clear_bit(vid, adapter->active_vlans);
 }
 
 static void
 ixgb_restore_vlan(struct ixgb_adapter *adapter)
 {
-	ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
-
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			ixgb_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
+	u16 vid;
+
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		ixgb_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index 3b8c924..8d46802 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -118,6 +118,7 @@ struct vf_data_storage {
 	bool pf_set_mac;
 	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
 	u16 pf_qos;
+	u16 tx_rate;
 };
 
 /* wrapper around a pointer to a socket buffer,
@@ -209,6 +210,7 @@ struct ixgbe_ring {
 					 * associated with this ring, which is
 					 * different for DCB and RSS modes
 					 */
+	u8 dcb_tc;
 
 	u16 work_limit;			/* max work per interrupt */
 
@@ -243,7 +245,7 @@ enum ixgbe_ring_f_enum {
 	RING_F_ARRAY_SIZE      /* must be last in enum set */
 };
 
-#define IXGBE_MAX_DCB_INDICES   8
+#define IXGBE_MAX_DCB_INDICES  64
 #define IXGBE_MAX_RSS_INDICES  16
 #define IXGBE_MAX_VMDQ_INDICES 64
 #define IXGBE_MAX_FDIR_INDICES 64
@@ -334,9 +336,14 @@ struct ixgbe_adapter {
 	u16 bd_number;
 	struct work_struct reset_task;
 	struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
+
+	/* DCB parameters */
+	struct ieee_pfc *ixgbe_ieee_pfc;
+	struct ieee_ets *ixgbe_ieee_ets;
 	struct ixgbe_dcb_config dcb_cfg;
 	struct ixgbe_dcb_config temp_dcb_cfg;
 	u8 dcb_set_bitmap;
+	u8 dcbx_cap;
 	enum ixgbe_fc_mode last_lfc_mode;
 
 	/* Interrupt Throttle Rate */
@@ -462,6 +469,7 @@ struct ixgbe_adapter {
 	DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
 	unsigned int num_vfs;
 	struct vf_data_storage *vfinfo;
+	int vf_rate_link_speed;
 };
 
 enum ixbge_state_t {
@@ -521,7 +529,6 @@ extern void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *,
 extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
 extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
 extern int ethtool_ioctl(struct ifreq *ifr);
-extern u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 index);
 extern s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
 extern s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
 extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
@@ -538,6 +545,7 @@ extern void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
 extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
                                struct ixgbe_ring *ring);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
+extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
 #ifdef IXGBE_FCOE
 extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
 extern int ixgbe_fso(struct ixgbe_adapter *adapter,
@@ -549,6 +557,8 @@ extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
                           struct sk_buff *skb);
 extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
                               struct scatterlist *sgl, unsigned int sgc);
+extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+				 struct scatterlist *sgl, unsigned int sgc);
 extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid);
 extern int ixgbe_fcoe_enable(struct net_device *netdev);
 extern int ixgbe_fcoe_disable(struct net_device *netdev);
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index d0f1d9d..845c679 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -158,6 +158,7 @@ static s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
 
 	switch (hw->phy.type) {
 	case ixgbe_phy_tn:
+		phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
 		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
 		phy->ops.get_firmware_version =
 		             &ixgbe_get_phy_firmware_version_tnx;
@@ -280,10 +281,22 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
 {
 	enum ixgbe_media_type media_type;
 
+	/* Detect if there is a copper PHY attached. */
+	switch (hw->phy.type) {
+	case ixgbe_phy_cu_unknown:
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
+		media_type = ixgbe_media_type_copper;
+		goto out;
+	default:
+		break;
+	}
+
 	/* Media type for I82598 is based on device ID */
 	switch (hw->device_id) {
 	case IXGBE_DEV_ID_82598:
 	case IXGBE_DEV_ID_82598_BX:
+		/* Default device ID is mezzanine card KX/KX4 */
 		media_type = ixgbe_media_type_backplane;
 		break;
 	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
@@ -306,7 +319,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
 		media_type = ixgbe_media_type_unknown;
 		break;
 	}
-
+out:
 	return media_type;
 }
 
@@ -354,7 +367,7 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
 
 	/* Negotiate the fc mode to use */
 	ret_val = ixgbe_fc_autoneg(hw);
-	if (ret_val)
+	if (ret_val == IXGBE_ERR_FLOW_CONTROL)
 		goto out;
 
 	/* Disable any previous flow control settings */
@@ -372,10 +385,10 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
 	 * 2: Tx flow control is enabled (we can send pause frames but
 	 *     we do not support receiving pause frames).
 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
-	 * other: Invalid.
 #ifdef CONFIG_DCB
 	 * 4: Priority Flow Control is enabled.
 #endif
+	 * other: Invalid.
 	 */
 	switch (hw->fc.current_mode) {
 	case ixgbe_fc_none:
@@ -432,9 +445,10 @@ static s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
 		reg = (rx_pba_size - hw->fc.low_water) << 6;
 		if (hw->fc.send_xon)
 			reg |= IXGBE_FCRTL_XONE;
+
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
 
-		reg = (rx_pba_size - hw->fc.high_water) << 10;
+		reg = (rx_pba_size - hw->fc.high_water) << 6;
 		reg |= IXGBE_FCRTH_FCEN;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
@@ -627,13 +641,12 @@ out:
 	return 0;
 }
 
-
 /**
  *  ixgbe_setup_mac_link_82598 - Set MAC link speed
  *  @hw: pointer to hardware structure
  *  @speed: new link speed
  *  @autoneg: true if auto-negotiation enabled
- *  @autoneg_wait_to_complete: true if waiting is needed to complete
+ *  @autoneg_wait_to_complete: true when waiting for completion is needed
  *
  *  Set the link speed in the AUTOC register and restarts link.
  **/
@@ -672,7 +685,8 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw,
 		 * ixgbe_hw This will write the AUTOC register based on the new
 		 * stored values
 		 */
-		status = ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
+		status = ixgbe_start_mac_link_82598(hw,
+						    autoneg_wait_to_complete);
 	}
 
 	return status;
@@ -698,7 +712,6 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw,
 	/* Setup the PHY according to input speed */
 	status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
 	                                      autoneg_wait_to_complete);
-
 	/* Set up MAC */
 	ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
 
@@ -770,7 +783,6 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
 		else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
 			goto no_phy_reset;
 
-
 		hw->phy.ops.reset(hw);
 	}
 
@@ -779,12 +791,9 @@ no_phy_reset:
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	status = ixgbe_disable_pcie_master(hw);
-	if (status != 0) {
-		status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
-		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
-	}
+	ixgbe_disable_pcie_master(hw);
 
+mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  This needs to be a SW reset.
 	 * If link reset is used, it might reset the MAC when mng is using it
@@ -805,6 +814,19 @@ no_phy_reset:
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
+	/*
+	 * Double resets are required for recovery from certain error
+	 * conditions.  Between resets, it is necessary to stall to allow time
+	 * for any pending HW events to complete.  We use 1usec since that is
+	 * what is needed for ixgbe_disable_pcie_master().  The second reset
+	 * then clears out any effects of those events.
+	 */
+	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+		udelay(1);
+		goto mac_reset_top;
+	}
+
 	msleep(50);
 
 	gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
@@ -824,15 +846,15 @@ no_phy_reset:
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
 	}
 
+	/* Store the permanent mac address */
+	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
 	/*
 	 * Store MAC address from RAR0, clear receive address registers, and
 	 * clear the multicast table
 	 */
 	hw->mac.ops.init_rx_addrs(hw);
 
-	/* Store the permanent mac address */
-	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
-
 reset_hw_out:
 	if (phy_status)
 		status = phy_status;
@@ -849,6 +871,13 @@ reset_hw_out:
 static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
 {
 	u32 rar_high;
+	u32 rar_entries = hw->mac.num_rar_entries;
+
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
+		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
 
 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
 	rar_high &= ~IXGBE_RAH_VIND_MASK;
@@ -868,14 +897,17 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
 	u32 rar_high;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
-	if (rar < rar_entries) {
-		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
-		if (rar_high & IXGBE_RAH_VIND_MASK) {
-			rar_high &= ~IXGBE_RAH_VIND_MASK;
-			IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
-		}
-	} else {
+
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
+
+	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+	if (rar_high & IXGBE_RAH_VIND_MASK) {
+		rar_high &= ~IXGBE_RAH_VIND_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
 	}
 
 	return 0;
@@ -994,13 +1026,12 @@ static s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
 }
 
 /**
- *  ixgbe_read_i2c_eeprom_82598 - Read 8 bit EEPROM word of an SFP+ module
- *  over I2C interface through an intermediate phy.
+ *  ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface.
  *  @hw: pointer to hardware structure
  *  @byte_offset: EEPROM byte offset to read
  *  @eeprom_data: value read
  *
- *  Performs byte read operation to SFP module's EEPROM over I2C interface.
+ *  Performs 8 byte read operation to SFP module's EEPROM over I2C interface.
  **/
 static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
 				       u8 *eeprom_data)
@@ -1074,10 +1105,12 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
 
 	/* Copper PHY must be checked before AUTOC LMS to determine correct
 	 * physical layer because 10GBase-T PHYs use LMS = KX4/KX */
-	if (hw->phy.type == ixgbe_phy_tn ||
-	    hw->phy.type == ixgbe_phy_cu_unknown) {
-		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
-				     &ext_ability);
+	switch (hw->phy.type) {
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
+	case ixgbe_phy_cu_unknown:
+		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE,
+		MDIO_MMD_PMAPMD, &ext_ability);
 		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
 		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
@@ -1085,6 +1118,8 @@ static u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
 		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
 		goto out;
+	default:
+		break;
 	}
 
 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -1179,13 +1214,14 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
 	.set_vmdq		= &ixgbe_set_vmdq_82598,
 	.clear_vmdq		= &ixgbe_clear_vmdq_82598,
 	.init_rx_addrs		= &ixgbe_init_rx_addrs_generic,
-	.update_uc_addr_list	= &ixgbe_update_uc_addr_list_generic,
 	.update_mc_addr_list	= &ixgbe_update_mc_addr_list_generic,
 	.enable_mc		= &ixgbe_enable_mc_generic,
 	.disable_mc		= &ixgbe_disable_mc_generic,
 	.clear_vfta		= &ixgbe_clear_vfta_82598,
 	.set_vfta		= &ixgbe_set_vfta_82598,
 	.fc_enable		= &ixgbe_fc_enable_82598,
+	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
+	.release_swfw_sync      = &ixgbe_release_swfw_sync,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index a21f581..00aeba3 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -112,7 +112,8 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 			goto setup_sfp_out;
 
 		/* PHY config will finish before releasing the semaphore */
-		ret_val = ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+		                                        IXGBE_GSSR_MAC_CSR_SM);
 		if (ret_val != 0) {
 			ret_val = IXGBE_ERR_SWFW_SYNC;
 			goto setup_sfp_out;
@@ -329,11 +330,14 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
 	enum ixgbe_media_type media_type;
 
 	/* Detect if there is a copper PHY attached. */
-	if (hw->phy.type == ixgbe_phy_cu_unknown ||
-	    hw->phy.type == ixgbe_phy_tn ||
-	    hw->phy.type == ixgbe_phy_aq) {
+	switch (hw->phy.type) {
+	case ixgbe_phy_cu_unknown:
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
 		media_type = ixgbe_media_type_copper;
 		goto out;
+	default:
+		break;
 	}
 
 	switch (hw->device_id) {
@@ -354,6 +358,9 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
 	case IXGBE_DEV_ID_82599_CX4:
 		media_type = ixgbe_media_type_cx4;
 		break;
+	case IXGBE_DEV_ID_82599_T3_LOM:
+		media_type = ixgbe_media_type_copper;
+		break;
 	default:
 		media_type = ixgbe_media_type_unknown;
 		break;
@@ -411,14 +418,14 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
 	return status;
 }
 
- /**
-  *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
-  *  @hw: pointer to hardware structure
-  *
-  *  The base drivers may require better control over SFP+ module
-  *  PHY states.  This includes selectively shutting down the Tx
-  *  laser on the PHY, effectively halting physical link.
-  **/
+/**
+ *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
+ *  @hw: pointer to hardware structure
+ *
+ *  The base drivers may require better control over SFP+ module
+ *  PHY states.  This includes selectively shutting down the Tx
+ *  laser on the PHY, effectively halting physical link.
+ **/
 static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
@@ -463,8 +470,6 @@ static void ixgbe_enable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
  **/
 static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
-	hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");
-
 	if (hw->mac.autotry_restart) {
 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
@@ -487,17 +492,21 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
                                           bool autoneg_wait_to_complete)
 {
 	s32 status = 0;
-	ixgbe_link_speed phy_link_speed;
+	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	u32 speedcnt = 0;
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+	u32 i = 0;
 	bool link_up = false;
 	bool negotiation;
-	int i;
 
 	/* Mask off requested but non-supported speeds */
-	hw->mac.ops.get_link_capabilities(hw, &phy_link_speed, &negotiation);
-	speed &= phy_link_speed;
+	status = hw->mac.ops.get_link_capabilities(hw, &link_speed,
+						   &negotiation);
+	if (status != 0)
+		return status;
+
+	speed &= link_speed;
 
 	/*
 	 * Try each speed one by one, highest priority first.  We do this in
@@ -508,9 +517,12 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 		highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
 
 		/* If we already have link at this speed, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+						false);
+		if (status != 0)
+			return status;
 
-		if ((phy_link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
+		if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
 			goto out;
 
 		/* Set the module link speed */
@@ -522,9 +534,9 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 		msleep(40);
 
 		status = ixgbe_setup_mac_link_82599(hw,
-		                               IXGBE_LINK_SPEED_10GB_FULL,
-		                               autoneg,
-		                               autoneg_wait_to_complete);
+						    IXGBE_LINK_SPEED_10GB_FULL,
+						    autoneg,
+						    autoneg_wait_to_complete);
 		if (status != 0)
 			return status;
 
@@ -536,14 +548,16 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
 		 * attempted.  82599 uses the same timing for 10g SFI.
 		 */
-
 		for (i = 0; i < 5; i++) {
 			/* Wait for the link partner to also set speed */
 			msleep(100);
 
 			/* If we have link, just jump out */
-			hw->mac.ops.check_link(hw, &phy_link_speed,
-			                       &link_up, false);
+			status = hw->mac.ops.check_link(hw, &link_speed,
+							&link_up, false);
+			if (status != 0)
+				return status;
+
 			if (link_up)
 				goto out;
 		}
@@ -555,9 +569,12 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 			highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
 
 		/* If we already have link at this speed, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+						false);
+		if (status != 0)
+			return status;
 
-		if ((phy_link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
+		if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
 			goto out;
 
 		/* Set the module link speed */
@@ -570,9 +587,9 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 		msleep(40);
 
 		status = ixgbe_setup_mac_link_82599(hw,
-		                                      IXGBE_LINK_SPEED_1GB_FULL,
-		                                      autoneg,
-		                                      autoneg_wait_to_complete);
+						    IXGBE_LINK_SPEED_1GB_FULL,
+						    autoneg,
+						    autoneg_wait_to_complete);
 		if (status != 0)
 			return status;
 
@@ -583,7 +600,11 @@ s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,
 		msleep(100);
 
 		/* If we have link, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+						false);
+		if (status != 0)
+			return status;
+
 		if (link_up)
 			goto out;
 	}
@@ -626,13 +647,10 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
 				     bool autoneg_wait_to_complete)
 {
 	s32 status = 0;
-	ixgbe_link_speed link_speed;
+	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	s32 i, j;
 	bool link_up = false;
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-	struct ixgbe_adapter *adapter = hw->back;
-
-	hw_dbg(hw, "ixgbe_setup_mac_link_smartspeed.\n");
 
 	 /* Set autoneg_advertised value based on input link speed */
 	hw->phy.autoneg_advertised = 0;
@@ -658,7 +676,7 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
 	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
 		status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
 						    autoneg_wait_to_complete);
-		if (status)
+		if (status != 0)
 			goto out;
 
 		/*
@@ -671,8 +689,11 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
 			mdelay(100);
 
 			/* If we have link, just jump out */
-			hw->mac.ops.check_link(hw, &link_speed,
-			                       &link_up, false);
+			status = hw->mac.ops.check_link(hw, &link_speed,
+							&link_up, false);
+			if (status != 0)
+				goto out;
+
 			if (link_up)
 				goto out;
 		}
@@ -690,7 +711,7 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
 	hw->phy.smart_speed_active = true;
 	status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
 					    autoneg_wait_to_complete);
-	if (status)
+	if (status != 0)
 		goto out;
 
 	/*
@@ -703,8 +724,11 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
 		mdelay(100);
 
 		/* If we have link, just jump out */
-		hw->mac.ops.check_link(hw, &link_speed,
-		                       &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed,
+						&link_up, false);
+		if (status != 0)
+			goto out;
+
 		if (link_up)
 			goto out;
 	}
@@ -716,7 +740,7 @@ static s32 ixgbe_setup_mac_link_smartspeed(struct ixgbe_hw *hw,
 
 out:
 	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
-		e_info(hw, "Smartspeed has downgraded the link speed from "
+		hw_dbg(hw, "Smartspeed has downgraded the link speed from "
 		       "the maximum advertised\n");
 	return status;
 }
@@ -748,6 +772,9 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 
 	/* Check to see if speed passed in is supported. */
 	hw->mac.ops.get_link_capabilities(hw, &link_capabilities, &autoneg);
+	if (status != 0)
+		goto out;
+
 	speed &= link_capabilities;
 
 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
@@ -761,7 +788,6 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
 	else
 		orig_autoc = autoc;
 
-
 	if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
 	    link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
@@ -878,7 +904,7 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 
 	/* PHY ops must be identified and initialized prior to reset */
 
-	/* Init PHY and function pointers, perform SFP setup */
+	/* Identify PHY and related function pointers */
 	status = hw->phy.ops.init(hw);
 
 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
@@ -890,6 +916,9 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 		hw->phy.sfp_setup_needed = false;
 	}
 
+	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+		goto reset_hw_out;
+
 	/* Reset PHY */
 	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
 		hw->phy.ops.reset(hw);
@@ -898,12 +927,9 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	status = ixgbe_disable_pcie_master(hw);
-	if (status != 0) {
-		status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
-		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
-	}
+	ixgbe_disable_pcie_master(hw);
 
+mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  This needs to be a SW reset.
 	 * If link reset is used, it might reset the MAC when mng is using it
@@ -924,6 +950,19 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
+	/*
+	 * Double resets are required for recovery from certain error
+	 * conditions.  Between resets, it is necessary to stall to allow time
+	 * for any pending HW events to complete.  We use 1usec since that is
+	 * what is needed for ixgbe_disable_pcie_master().  The second reset
+	 * then clears out any effects of those events.
+	 */
+	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+		udelay(1);
+		goto mac_reset_top;
+	}
+
 	msleep(50);
 
 	/*
@@ -951,6 +990,9 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 		}
 	}
 
+	/* Store the permanent mac address */
+	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
 	/*
 	 * Store MAC address from RAR0, clear receive address registers, and
 	 * clear the multicast table.  Also reset num_rar_entries to 128,
@@ -959,9 +1001,6 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
 	hw->mac.num_rar_entries = 128;
 	hw->mac.ops.init_rx_addrs(hw);
 
-	/* Store the permanent mac address */
-	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
-
 	/* Store the permanent SAN mac address */
 	hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
 
@@ -1733,13 +1772,34 @@ static s32 ixgbe_start_hw_82599(struct ixgbe_hw *hw)
  *  @hw: pointer to hardware structure
  *
  *  Determines the physical layer module found on the current adapter.
+ *  If PHY already detected, maintains current PHY type in hw struct,
+ *  otherwise executes the PHY detection routine.
  **/
-static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
+s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
 {
 	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+
+	/* Detect PHY if not unknown - returns success if already detected. */
 	status = ixgbe_identify_phy_generic(hw);
-	if (status != 0)
-		status = ixgbe_identify_sfp_module_generic(hw);
+	if (status != 0) {
+		/* 82599 10GBASE-T requires an external PHY */
+		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
+			goto out;
+		else
+			status = ixgbe_identify_sfp_module_generic(hw);
+	}
+
+	/* Set PHY type none if no PHY detected */
+	if (hw->phy.type == ixgbe_phy_unknown) {
+		hw->phy.type = ixgbe_phy_none;
+		status = 0;
+	}
+
+	/* Return error if SFP module has been detected but is not supported */
+	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+
+out:
 	return status;
 }
 
@@ -1763,11 +1823,12 @@ static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
 
 	hw->phy.ops.identify(hw);
 
-	if (hw->phy.type == ixgbe_phy_tn ||
-	    hw->phy.type == ixgbe_phy_aq ||
-	    hw->phy.type == ixgbe_phy_cu_unknown) {
+	switch (hw->phy.type) {
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
+	case ixgbe_phy_cu_unknown:
 		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
-				     &ext_ability);
+							 &ext_ability);
 		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
 		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
@@ -1775,6 +1836,8 @@ static u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
 		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
 		goto out;
+	default:
+		break;
 	}
 
 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -1886,6 +1949,7 @@ static s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
 		if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
 			break;
 		else
+			/* Use interrupt-safe sleep just in case */
 			udelay(10);
 	}
 
@@ -1995,7 +2059,6 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
 	.set_vmdq               = &ixgbe_set_vmdq_generic,
 	.clear_vmdq             = &ixgbe_clear_vmdq_generic,
 	.init_rx_addrs          = &ixgbe_init_rx_addrs_generic,
-	.update_uc_addr_list    = &ixgbe_update_uc_addr_list_generic,
 	.update_mc_addr_list    = &ixgbe_update_mc_addr_list_generic,
 	.enable_mc              = &ixgbe_enable_mc_generic,
 	.disable_mc             = &ixgbe_disable_mc_generic,
@@ -2006,31 +2069,34 @@ static struct ixgbe_mac_operations mac_ops_82599 = {
 	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
 	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
 	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
+	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
+	.release_swfw_sync      = &ixgbe_release_swfw_sync,
+
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
-	.init_params            = &ixgbe_init_eeprom_params_generic,
-	.read                   = &ixgbe_read_eerd_generic,
-	.write                  = &ixgbe_write_eeprom_generic,
-	.calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
-	.validate_checksum      = &ixgbe_validate_eeprom_checksum_generic,
-	.update_checksum        = &ixgbe_update_eeprom_checksum_generic,
+	.init_params		= &ixgbe_init_eeprom_params_generic,
+	.read			= &ixgbe_read_eerd_generic,
+	.write			= &ixgbe_write_eeprom_generic,
+	.calc_checksum		= &ixgbe_calc_eeprom_checksum_generic,
+	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
+	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
 };
 
 static struct ixgbe_phy_operations phy_ops_82599 = {
-	.identify               = &ixgbe_identify_phy_82599,
-	.identify_sfp           = &ixgbe_identify_sfp_module_generic,
-	.init			            = &ixgbe_init_phy_ops_82599,
-	.reset                  = &ixgbe_reset_phy_generic,
-	.read_reg               = &ixgbe_read_phy_reg_generic,
-	.write_reg              = &ixgbe_write_phy_reg_generic,
-	.setup_link             = &ixgbe_setup_phy_link_generic,
-	.setup_link_speed       = &ixgbe_setup_phy_link_speed_generic,
-	.read_i2c_byte          = &ixgbe_read_i2c_byte_generic,
-	.write_i2c_byte         = &ixgbe_write_i2c_byte_generic,
-	.read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_generic,
-	.write_i2c_eeprom       = &ixgbe_write_i2c_eeprom_generic,
-	.check_overtemp         = &ixgbe_tn_check_overtemp,
+	.identify		= &ixgbe_identify_phy_82599,
+	.identify_sfp		= &ixgbe_identify_sfp_module_generic,
+	.init			= &ixgbe_init_phy_ops_82599,
+	.reset			= &ixgbe_reset_phy_generic,
+	.read_reg		= &ixgbe_read_phy_reg_generic,
+	.write_reg		= &ixgbe_write_phy_reg_generic,
+	.setup_link		= &ixgbe_setup_phy_link_generic,
+	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic,
+	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic,
+	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic,
+	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic,
+	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic,
+	.check_overtemp		= &ixgbe_tn_check_overtemp,
 };
 
 struct ixgbe_info ixgbe_82599_info = {
diff --git a/drivers/net/ixgbe/ixgbe_common.c b/drivers/net/ixgbe/ixgbe_common.c
index ebbda7d..bcd9529 100644
--- a/drivers/net/ixgbe/ixgbe_common.c
+++ b/drivers/net/ixgbe/ixgbe_common.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -46,10 +46,13 @@ static void ixgbe_raise_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
 static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
 static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
 
-static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
-static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
-static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
+static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
+static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
+static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
 static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
 
 /**
@@ -139,17 +142,29 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
 	IXGBE_READ_REG(hw, IXGBE_MRFC);
 	IXGBE_READ_REG(hw, IXGBE_RLEC);
 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
-	IXGBE_READ_REG(hw, IXGBE_LXONRXC);
 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
-	IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+	if (hw->mac.type >= ixgbe_mac_82599EB) {
+		IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+		IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+	} else {
+		IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+		IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+	}
 
 	for (i = 0; i < 8; i++) {
 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
-		IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
-		IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+		if (hw->mac.type >= ixgbe_mac_82599EB) {
+			IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+			IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+		} else {
+			IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+			IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+		}
 	}
-
+	if (hw->mac.type >= ixgbe_mac_82599EB)
+		for (i = 0; i < 8; i++)
+			IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
 	IXGBE_READ_REG(hw, IXGBE_PRC64);
 	IXGBE_READ_REG(hw, IXGBE_PRC127);
 	IXGBE_READ_REG(hw, IXGBE_PRC255);
@@ -187,9 +202,26 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
 	IXGBE_READ_REG(hw, IXGBE_BPTC);
 	for (i = 0; i < 16; i++) {
 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
-		IXGBE_READ_REG(hw, IXGBE_QBRC(i));
 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
-		IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+		if (hw->mac.type >= ixgbe_mac_82599EB) {
+			IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
+			IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
+			IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
+			IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
+			IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+		} else {
+			IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+			IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+		}
+	}
+
+	if (hw->mac.type == ixgbe_mac_X540) {
+		if (hw->phy.id == 0)
+			hw->phy.ops.identify(hw);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_PCRC8ECL, &i);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_PCRC8ECH, &i);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_LDPCECL, &i);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_LDPCECH, &i);
 	}
 
 	return 0;
@@ -454,8 +486,7 @@ s32 ixgbe_stop_adapter_generic(struct ixgbe_hw *hw)
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests
 	 */
-	if (ixgbe_disable_pcie_master(hw) != 0)
-		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
+	ixgbe_disable_pcie_master(hw);
 
 	return 0;
 }
@@ -603,7 +634,6 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
 		ixgbe_shift_out_eeprom_bits(hw, data, 16);
 		ixgbe_standby_eeprom(hw);
 
-		msleep(hw->eeprom.semaphore_delay);
 		/* Done with writing - release the EEPROM */
 		ixgbe_release_eeprom(hw);
 	}
@@ -747,10 +777,10 @@ s32 ixgbe_poll_eerd_eewr_done(struct ixgbe_hw *hw, u32 ee_reg)
 static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
 {
 	s32 status = 0;
-	u32 eec = 0;
+	u32 eec;
 	u32 i;
 
-	if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == 0) {
@@ -773,18 +803,18 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
 			hw_dbg(hw, "Could not acquire EEPROM grant\n");
 
-			ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+			hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 			status = IXGBE_ERR_EEPROM;
 		}
-	}
 
-	/* Setup EEPROM for Read/Write */
-	if (status == 0) {
-		/* Clear CS and SK */
-		eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
-		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
-		IXGBE_WRITE_FLUSH(hw);
-		udelay(1);
+		/* Setup EEPROM for Read/Write */
+		if (status == 0) {
+			/* Clear CS and SK */
+			eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
+			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+			IXGBE_WRITE_FLUSH(hw);
+			udelay(1);
+		}
 	}
 	return status;
 }
@@ -798,13 +828,10 @@ static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
 static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
 {
 	s32 status = IXGBE_ERR_EEPROM;
-	u32 timeout;
+	u32 timeout = 2000;
 	u32 i;
 	u32 swsm;
 
-	/* Set timeout value based on size of EEPROM */
-	timeout = hw->eeprom.word_size + 1;
-
 	/* Get SMBI software semaphore between device drivers first */
 	for (i = 0; i < timeout; i++) {
 		/*
@@ -816,7 +843,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
 			status = 0;
 			break;
 		}
-		msleep(1);
+		udelay(50);
 	}
 
 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
@@ -844,11 +871,14 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
 		 * was not granted because we don't have access to the EEPROM
 		 */
 		if (i >= timeout) {
-			hw_dbg(hw, "Driver can't access the Eeprom - Semaphore "
+			hw_dbg(hw, "SWESMBI Software EEPROM semaphore "
 			       "not granted.\n");
 			ixgbe_release_eeprom_semaphore(hw);
 			status = IXGBE_ERR_EEPROM;
 		}
+	} else {
+		hw_dbg(hw, "Software semaphore SMBI between device drivers "
+		       "not granted.\n");
 	}
 
 	return status;
@@ -1080,11 +1110,14 @@ static void ixgbe_release_eeprom(struct ixgbe_hw *hw)
 	eec &= ~IXGBE_EEC_REQ;
 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
 
-	ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+
+	/* Delay before attempt to obtain semaphore again to allow FW access */
+	msleep(hw->eeprom.semaphore_delay);
 }
 
 /**
- *  ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
+ *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
  **/
 u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
@@ -1190,7 +1223,7 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
 	if (status == 0) {
 		checksum = hw->eeprom.ops.calc_checksum(hw);
 		status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
-		                            checksum);
+					      checksum);
 	} else {
 		hw_dbg(hw, "EEPROM read failed\n");
 	}
@@ -1238,37 +1271,37 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
 	u32 rar_low, rar_high;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
+	/* Make sure we are using a valid rar index range */
+	if (index >= rar_entries) {
+		hw_dbg(hw, "RAR index %d is out of range.\n", index);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
+
 	/* setup VMDq pool selection before this RAR gets enabled */
 	hw->mac.ops.set_vmdq(hw, index, vmdq);
 
-	/* Make sure we are using a valid rar index range */
-	if (index < rar_entries) {
-		/*
-		 * HW expects these in little endian so we reverse the byte
-		 * order from network order (big endian) to little endian
-		 */
-		rar_low = ((u32)addr[0] |
-		           ((u32)addr[1] << 8) |
-		           ((u32)addr[2] << 16) |
-		           ((u32)addr[3] << 24));
-		/*
-		 * Some parts put the VMDq setting in the extra RAH bits,
-		 * so save everything except the lower 16 bits that hold part
-		 * of the address and the address valid bit.
-		 */
-		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
-		rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
+	/*
+	 * HW expects these in little endian so we reverse the byte
+	 * order from network order (big endian) to little endian
+	 */
+	rar_low = ((u32)addr[0] |
+		   ((u32)addr[1] << 8) |
+		   ((u32)addr[2] << 16) |
+		   ((u32)addr[3] << 24));
+	/*
+	 * Some parts put the VMDq setting in the extra RAH bits,
+	 * so save everything except the lower 16 bits that hold part
+	 * of the address and the address valid bit.
+	 */
+	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+	rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
 
-		if (enable_addr != 0)
-			rar_high |= IXGBE_RAH_AV;
+	if (enable_addr != 0)
+		rar_high |= IXGBE_RAH_AV;
 
-		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
-		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-	} else {
-		hw_dbg(hw, "RAR index %d is out of range.\n", index);
-		return IXGBE_ERR_RAR_INDEX;
-	}
+	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
+	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
 
 	return 0;
 }
@@ -1286,58 +1319,26 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
 	u32 rar_entries = hw->mac.num_rar_entries;
 
 	/* Make sure we are using a valid rar index range */
-	if (index < rar_entries) {
-		/*
-		 * Some parts put the VMDq setting in the extra RAH bits,
-		 * so save everything except the lower 16 bits that hold part
-		 * of the address and the address valid bit.
-		 */
-		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
-
-		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-	} else {
+	if (index >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", index);
-		return IXGBE_ERR_RAR_INDEX;
+		return IXGBE_ERR_INVALID_ARGUMENT;
 	}
 
-	/* clear VMDq pool/queue selection for this RAR */
-	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
-
-	return 0;
-}
-
-/**
- *  ixgbe_enable_rar - Enable Rx address register
- *  @hw: pointer to hardware structure
- *  @index: index into the RAR table
- *
- *  Enables the select receive address register.
- **/
-static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index)
-{
-	u32 rar_high;
-
+	/*
+	 * Some parts put the VMDq setting in the extra RAH bits,
+	 * so save everything except the lower 16 bits that hold part
+	 * of the address and the address valid bit.
+	 */
 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-	rar_high |= IXGBE_RAH_AV;
+	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+
+	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-}
 
-/**
- *  ixgbe_disable_rar - Disable Rx address register
- *  @hw: pointer to hardware structure
- *  @index: index into the RAR table
- *
- *  Disables the select receive address register.
- **/
-static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index)
-{
-	u32 rar_high;
+	/* clear VMDq pool/queue selection for this RAR */
+	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
 
-	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-	rar_high &= (~IXGBE_RAH_AV);
-	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+	return 0;
 }
 
 /**
@@ -1386,7 +1387,6 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
 	}
 
 	/* Clear the MTA */
-	hw->addr_ctrl.mc_addr_in_rar_count = 0;
 	hw->addr_ctrl.mta_in_use = 0;
 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
 
@@ -1401,105 +1401,6 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
 }
 
 /**
- *  ixgbe_add_uc_addr - Adds a secondary unicast address.
- *  @hw: pointer to hardware structure
- *  @addr: new address
- *
- *  Adds it to unused receive address register or goes into promiscuous mode.
- **/
-static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
-{
-	u32 rar_entries = hw->mac.num_rar_entries;
-	u32 rar;
-
-	hw_dbg(hw, " UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
-	          addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-
-	/*
-	 * Place this address in the RAR if there is room,
-	 * else put the controller into promiscuous mode
-	 */
-	if (hw->addr_ctrl.rar_used_count < rar_entries) {
-		rar = hw->addr_ctrl.rar_used_count -
-		      hw->addr_ctrl.mc_addr_in_rar_count;
-		hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
-		hw_dbg(hw, "Added a secondary address to RAR[%d]\n", rar);
-		hw->addr_ctrl.rar_used_count++;
-	} else {
-		hw->addr_ctrl.overflow_promisc++;
-	}
-
-	hw_dbg(hw, "ixgbe_add_uc_addr Complete\n");
-}
-
-/**
- *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
- *  @hw: pointer to hardware structure
- *  @netdev: pointer to net device structure
- *
- *  The given list replaces any existing list.  Clears the secondary addrs from
- *  receive address registers.  Uses unused receive address registers for the
- *  first secondary addresses, and falls back to promiscuous mode as needed.
- *
- *  Drivers using secondary unicast addresses must set user_set_promisc when
- *  manually putting the device into promiscuous mode.
- **/
-s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
-				      struct net_device *netdev)
-{
-	u32 i;
-	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
-	u32 uc_addr_in_use;
-	u32 fctrl;
-	struct netdev_hw_addr *ha;
-
-	/*
-	 * Clear accounting of old secondary address list,
-	 * don't count RAR[0]
-	 */
-	uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
-	hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
-	hw->addr_ctrl.overflow_promisc = 0;
-
-	/* Zero out the other receive addresses */
-	hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use + 1);
-	for (i = 0; i < uc_addr_in_use; i++) {
-		IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
-	}
-
-	/* Add the new addresses */
-	netdev_for_each_uc_addr(ha, netdev) {
-		hw_dbg(hw, " Adding the secondary addresses:\n");
-		ixgbe_add_uc_addr(hw, ha->addr, 0);
-	}
-
-	if (hw->addr_ctrl.overflow_promisc) {
-		/* enable promisc if not already in overflow or set by user */
-		if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
-			hw_dbg(hw, " Entering address overflow promisc mode\n");
-			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-			fctrl |= IXGBE_FCTRL_UPE;
-			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
-			hw->addr_ctrl.uc_set_promisc = true;
-		}
-	} else {
-		/* only disable if set by overflow, not by user */
-		if ((old_promisc_setting && hw->addr_ctrl.uc_set_promisc) &&
-		   !(hw->addr_ctrl.user_set_promisc)) {
-			hw_dbg(hw, " Leaving address overflow promisc mode\n");
-			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-			fctrl &= ~IXGBE_FCTRL_UPE;
-			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
-			hw->addr_ctrl.uc_set_promisc = false;
-		}
-	}
-
-	hw_dbg(hw, "ixgbe_update_uc_addr_list_generic Complete\n");
-	return 0;
-}
-
-/**
  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
  *  @hw: pointer to hardware structure
  *  @mc_addr: the multicast address
@@ -1550,7 +1451,6 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
 	u32 vector;
 	u32 vector_bit;
 	u32 vector_reg;
-	u32 mta_reg;
 
 	hw->addr_ctrl.mta_in_use++;
 
@@ -1568,9 +1468,7 @@ static void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
 	 */
 	vector_reg = (vector >> 5) & 0x7F;
 	vector_bit = vector & 0x1F;
-	mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
-	mta_reg |= (1 << vector_bit);
-	IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
+	hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit);
 }
 
 /**
@@ -1596,18 +1494,21 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
 	hw->addr_ctrl.num_mc_addrs = netdev_mc_count(netdev);
 	hw->addr_ctrl.mta_in_use = 0;
 
-	/* Clear the MTA */
+	/* Clear mta_shadow */
 	hw_dbg(hw, " Clearing MTA\n");
-	for (i = 0; i < hw->mac.mcft_size; i++)
-		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
+	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
 
-	/* Add the new addresses */
+	/* Update mta shadow */
 	netdev_for_each_mc_addr(ha, netdev) {
 		hw_dbg(hw, " Adding the multicast addresses:\n");
 		ixgbe_set_mta(hw, ha->addr);
 	}
 
 	/* Enable mta */
+	for (i = 0; i < hw->mac.mcft_size; i++)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i,
+				      hw->mac.mta_shadow[i]);
+
 	if (hw->addr_ctrl.mta_in_use > 0)
 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
 		                IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
@@ -1624,15 +1525,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
  **/
 s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
 {
-	u32 i;
-	u32 rar_entries = hw->mac.num_rar_entries;
 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
 
-	if (a->mc_addr_in_rar_count > 0)
-		for (i = (rar_entries - a->mc_addr_in_rar_count);
-		     i < rar_entries; i++)
-			ixgbe_enable_rar(hw, i);
-
 	if (a->mta_in_use > 0)
 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
 		                hw->mac.mc_filter_type);
@@ -1648,15 +1542,8 @@ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
  **/
 s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
 {
-	u32 i;
-	u32 rar_entries = hw->mac.num_rar_entries;
 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
 
-	if (a->mc_addr_in_rar_count > 0)
-		for (i = (rar_entries - a->mc_addr_in_rar_count);
-		     i < rar_entries; i++)
-			ixgbe_disable_rar(hw, i);
-
 	if (a->mta_in_use > 0)
 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
 
@@ -1685,7 +1572,7 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
 #endif /* CONFIG_DCB */
 	/* Negotiate the fc mode to use */
 	ret_val = ixgbe_fc_autoneg(hw);
-	if (ret_val)
+	if (ret_val == IXGBE_ERR_FLOW_CONTROL)
 		goto out;
 
 	/* Disable any previous flow control settings */
@@ -1703,7 +1590,9 @@ s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
 	 * 2: Tx flow control is enabled (we can send pause frames but
 	 *    we do not support receiving pause frames).
 	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
+#ifdef CONFIG_DCB
 	 * 4: Priority Flow Control is enabled.
+#endif
 	 * other: Invalid.
 	 */
 	switch (hw->fc.current_mode) {
@@ -1791,12 +1680,13 @@ out:
  **/
 s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 {
-	s32 ret_val = 0;
+	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 	ixgbe_link_speed speed;
-	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
-	u32 links2, anlp1_reg, autoc_reg, links;
 	bool link_up;
 
+	if (hw->fc.disable_fc_autoneg)
+		goto out;
+
 	/*
 	 * AN should have completed when the cable was plugged in.
 	 * Look for reasons to bail out.  Bail out if:
@@ -1807,153 +1697,199 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 	 * So use link_up_wait_to_complete=false.
 	 */
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
-
-	if (hw->fc.disable_fc_autoneg || (!link_up)) {
-		hw->fc.fc_was_autonegged = false;
-		hw->fc.current_mode = hw->fc.requested_mode;
+	if (!link_up) {
+		ret_val = IXGBE_ERR_FLOW_CONTROL;
 		goto out;
 	}
 
-	/*
-	 * On backplane, bail out if
-	 * - backplane autoneg was not completed, or if
-	 * - we are 82599 and link partner is not AN enabled
-	 */
-	if (hw->phy.media_type == ixgbe_media_type_backplane) {
-		links = IXGBE_READ_REG(hw, IXGBE_LINKS);
-		if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
-			hw->fc.fc_was_autonegged = false;
-			hw->fc.current_mode = hw->fc.requested_mode;
-			goto out;
-		}
+	switch (hw->phy.media_type) {
+	/* Autoneg flow control on fiber adapters */
+	case ixgbe_media_type_fiber:
+		if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+			ret_val = ixgbe_fc_autoneg_fiber(hw);
+		break;
 
-		if (hw->mac.type == ixgbe_mac_82599EB) {
-			links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
-			if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
-				hw->fc.fc_was_autonegged = false;
-				hw->fc.current_mode = hw->fc.requested_mode;
-				goto out;
-			}
-		}
+	/* Autoneg flow control on backplane adapters */
+	case ixgbe_media_type_backplane:
+		ret_val = ixgbe_fc_autoneg_backplane(hw);
+		break;
+
+	/* Autoneg flow control on copper adapters */
+	case ixgbe_media_type_copper:
+		if (ixgbe_device_supports_autoneg_fc(hw) == 0)
+			ret_val = ixgbe_fc_autoneg_copper(hw);
+		break;
+
+	default:
+		break;
 	}
 
+out:
+	if (ret_val == 0) {
+		hw->fc.fc_was_autonegged = true;
+	} else {
+		hw->fc.fc_was_autonegged = false;
+		hw->fc.current_mode = hw->fc.requested_mode;
+	}
+	return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according on 1 gig fiber.
+ **/
+static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
+{
+	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+	s32 ret_val;
+
 	/*
 	 * On multispeed fiber at 1g, bail out if
 	 * - link is up but AN did not complete, or if
 	 * - link is up and AN completed but timed out
 	 */
-	if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
-		linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-		if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
-		    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
-			hw->fc.fc_was_autonegged = false;
-			hw->fc.current_mode = hw->fc.requested_mode;
-			goto out;
-		}
+
+	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+	if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+	    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+		ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+		goto out;
 	}
 
+	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+
+	ret_val =  ixgbe_negotiate_fc(hw, pcs_anadv_reg,
+			       pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE,
+			       IXGBE_PCS1GANA_ASM_PAUSE,
+			       IXGBE_PCS1GANA_SYM_PAUSE,
+			       IXGBE_PCS1GANA_ASM_PAUSE);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according to IEEE clause 37.
+ **/
+static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
+{
+	u32 links2, anlp1_reg, autoc_reg, links;
+	s32 ret_val;
+
 	/*
-	 * Bail out on
-	 * - copper or CX4 adapters
-	 * - fiber adapters running at 10gig
+	 * On backplane, bail out if
+	 * - backplane autoneg was not completed, or if
+	 * - we are 82599 and link partner is not AN enabled
 	 */
-	if ((hw->phy.media_type == ixgbe_media_type_copper) ||
-	     (hw->phy.media_type == ixgbe_media_type_cx4) ||
-	     ((hw->phy.media_type == ixgbe_media_type_fiber) &&
-	     (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
+	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
+	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
 		hw->fc.fc_was_autonegged = false;
 		hw->fc.current_mode = hw->fc.requested_mode;
+		ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 		goto out;
 	}
 
+	if (hw->mac.type == ixgbe_mac_82599EB) {
+		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
+			hw->fc.fc_was_autonegged = false;
+			hw->fc.current_mode = hw->fc.requested_mode;
+			ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+			goto out;
+		}
+	}
 	/*
-	 * Read the AN advertisement and LP ability registers and resolve
+	 * Read the 10g AN autoc and LP ability registers and resolve
 	 * local flow control settings accordingly
 	 */
-	if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
-	    (hw->phy.media_type != ixgbe_media_type_backplane)) {
-		pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
-		pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
-		if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		    (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
-			/*
-			 * Now we need to check if the user selected Rx ONLY
-			 * of pause frames.  In this case, we had to advertise
-			 * FULL flow control because we could not advertise RX
-			 * ONLY. Hence, we must now check to see if we need to
-			 * turn OFF the TRANSMISSION of PAUSE frames.
-			 */
-			if (hw->fc.requested_mode == ixgbe_fc_full) {
-				hw->fc.current_mode = ixgbe_fc_full;
-				hw_dbg(hw, "Flow Control = FULL.\n");
-			} else {
-				hw->fc.current_mode = ixgbe_fc_rx_pause;
-				hw_dbg(hw, "Flow Control=RX PAUSE only\n");
-			}
-		} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-			   (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_tx_pause;
-			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
-		} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-			   !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_rx_pause;
-			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
-		} else {
-			hw->fc.current_mode = ixgbe_fc_none;
-			hw_dbg(hw, "Flow Control = NONE.\n");
-		}
-	}
+	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
 
-	if (hw->phy.media_type == ixgbe_media_type_backplane) {
+	ret_val = ixgbe_negotiate_fc(hw, autoc_reg,
+		anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
+		IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according to IEEE clause 37.
+ **/
+static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
+{
+	u16 technology_ability_reg = 0;
+	u16 lp_technology_ability_reg = 0;
+
+	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+			     MDIO_MMD_AN,
+			     &technology_ability_reg);
+	hw->phy.ops.read_reg(hw, MDIO_AN_LPA,
+			     MDIO_MMD_AN,
+			     &lp_technology_ability_reg);
+
+	return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg,
+				  (u32)lp_technology_ability_reg,
+				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
+				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
+}
+
+/**
+ *  ixgbe_negotiate_fc - Negotiate flow control
+ *  @hw: pointer to hardware structure
+ *  @adv_reg: flow control advertised settings
+ *  @lp_reg: link partner's flow control settings
+ *  @adv_sym: symmetric pause bit in advertisement
+ *  @adv_asm: asymmetric pause bit in advertisement
+ *  @lp_sym: symmetric pause bit in link partner advertisement
+ *  @lp_asm: asymmetric pause bit in link partner advertisement
+ *
+ *  Find the intersection between advertised settings and link partner's
+ *  advertised settings
+ **/
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+{
+	if ((!(adv_reg)) ||  (!(lp_reg)))
+		return IXGBE_ERR_FC_NOT_NEGOTIATED;
+
+	if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
 		/*
-		 * Read the 10g AN autoc and LP ability registers and resolve
-		 * local flow control settings accordingly
+		 * Now we need to check if the user selected Rx ONLY
+		 * of pause frames.  In this case, we had to advertise
+		 * FULL flow control because we could not advertise RX
+		 * ONLY. Hence, we must now check to see if we need to
+		 * turn OFF the TRANSMISSION of PAUSE frames.
 		 */
-		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
-
-		if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
-		    (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
-			/*
-			 * Now we need to check if the user selected Rx ONLY
-			 * of pause frames.  In this case, we had to advertise
-			 * FULL flow control because we could not advertise RX
-			 * ONLY. Hence, we must now check to see if we need to
-			 * turn OFF the TRANSMISSION of PAUSE frames.
-			 */
-			if (hw->fc.requested_mode == ixgbe_fc_full) {
-				hw->fc.current_mode = ixgbe_fc_full;
-				hw_dbg(hw, "Flow Control = FULL.\n");
-			} else {
-				hw->fc.current_mode = ixgbe_fc_rx_pause;
-				hw_dbg(hw, "Flow Control=RX PAUSE only\n");
-			}
-		} else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
-			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
-			   (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
-			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_tx_pause;
-			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
-		} else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
-			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
-			   !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
-			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_rx_pause;
-			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+		if (hw->fc.requested_mode == ixgbe_fc_full) {
+			hw->fc.current_mode = ixgbe_fc_full;
+			hw_dbg(hw, "Flow Control = FULL.\n");
 		} else {
-			hw->fc.current_mode = ixgbe_fc_none;
-			hw_dbg(hw, "Flow Control = NONE.\n");
+			hw->fc.current_mode = ixgbe_fc_rx_pause;
+			hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
 		}
+	} else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+		   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+		hw->fc.current_mode = ixgbe_fc_tx_pause;
+		hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+	} else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+		   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+		hw->fc.current_mode = ixgbe_fc_rx_pause;
+		hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+	} else {
+		hw->fc.current_mode = ixgbe_fc_none;
+		hw_dbg(hw, "Flow Control = NONE.\n");
 	}
-	/* Record that current_mode is the result of a successful autoneg */
-	hw->fc.fc_was_autonegged = true;
-
-out:
-	return ret_val;
+	return 0;
 }
 
 /**
@@ -1965,7 +1901,8 @@ out:
 static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 {
 	s32 ret_val = 0;
-	u32 reg;
+	u32 reg = 0, reg_bp = 0;
+	u16 reg_cu = 0;
 
 #ifdef CONFIG_DCB
 	if (hw->fc.requested_mode == ixgbe_fc_pfc) {
@@ -1973,7 +1910,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 		goto out;
 	}
 
-#endif
+#endif /* CONFIG_DCB */
 	/* Validate the packetbuf configuration */
 	if (packetbuf_num < 0 || packetbuf_num > 7) {
 		hw_dbg(hw, "Invalid packet buffer number [%d], expected range "
@@ -2011,11 +1948,26 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 		hw->fc.requested_mode = ixgbe_fc_full;
 
 	/*
-	 * Set up the 1G flow control advertisement registers so the HW will be
-	 * able to do fc autoneg once the cable is plugged in.  If we end up
-	 * using 10g instead, this is harmless.
+	 * Set up the 1G and 10G flow control advertisement registers so the
+	 * HW will be able to do fc autoneg once the cable is plugged in.  If
+	 * we link at 10G, the 1G advertisement is harmless and vice versa.
 	 */
-	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+
+	switch (hw->phy.media_type) {
+	case ixgbe_media_type_fiber:
+	case ixgbe_media_type_backplane:
+		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+		reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+		break;
+
+	case ixgbe_media_type_copper:
+		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+					MDIO_MMD_AN, &reg_cu);
+		break;
+
+	default:
+		;
+	}
 
 	/*
 	 * The possible values of fc.requested_mode are:
@@ -2034,6 +1986,11 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 	case ixgbe_fc_none:
 		/* Flow control completely disabled by software override. */
 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane)
+			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+				    IXGBE_AUTOC_ASM_PAUSE);
+		else if (hw->phy.media_type == ixgbe_media_type_copper)
+			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
 		break;
 	case ixgbe_fc_rx_pause:
 		/*
@@ -2045,6 +2002,11 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 		 * disable the adapter's ability to send PAUSE frames.
 		 */
 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane)
+			reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+				   IXGBE_AUTOC_ASM_PAUSE);
+		else if (hw->phy.media_type == ixgbe_media_type_copper)
+			reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
 		break;
 	case ixgbe_fc_tx_pause:
 		/*
@@ -2053,10 +2015,22 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 		 */
 		reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane) {
+			reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
+			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
+		} else if (hw->phy.media_type == ixgbe_media_type_copper) {
+			reg_cu |= (IXGBE_TAF_ASM_PAUSE);
+			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE);
+		}
 		break;
 	case ixgbe_fc_full:
 		/* Flow control (both Rx and Tx) is enabled by SW override. */
 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane)
+			reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+				   IXGBE_AUTOC_ASM_PAUSE);
+		else if (hw->phy.media_type == ixgbe_media_type_copper)
+			reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
 		break;
 #ifdef CONFIG_DCB
 	case ixgbe_fc_pfc:
@@ -2070,80 +2044,37 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 		break;
 	}
 
-	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
-	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
-	/* Disable AN timeout */
-	if (hw->fc.strict_ieee)
-		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+	if (hw->mac.type != ixgbe_mac_X540) {
+		/*
+		 * Enable auto-negotiation between the MAC & PHY;
+		 * the MAC will advertise clause 37 flow control.
+		 */
+		IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
 
-	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
-	hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+		/* Disable AN timeout */
+		if (hw->fc.strict_ieee)
+			reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
 
-	/*
-	 * Set up the 10G flow control advertisement registers so the HW
-	 * can do fc autoneg once the cable is plugged in.  If we end up
-	 * using 1g instead, this is harmless.
-	 */
-	reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+		IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+		hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+	}
 
 	/*
-	 * The possible values of fc.requested_mode are:
-	 * 0: Flow control is completely disabled
-	 * 1: Rx flow control is enabled (we can receive pause frames,
-	 *    but not send pause frames).
-	 * 2: Tx flow control is enabled (we can send pause frames but
-	 *    we do not support receiving pause frames).
-	 * 3: Both Rx and Tx flow control (symmetric) are enabled.
-	 * other: Invalid.
+	 * AUTOC restart handles negotiation of 1G and 10G on backplane
+	 * and copper. There is no need to set the PCS1GCTL register.
+	 *
 	 */
-	switch (hw->fc.requested_mode) {
-	case ixgbe_fc_none:
-		/* Flow control completely disabled by software override. */
-		reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
-		break;
-	case ixgbe_fc_rx_pause:
-		/*
-		 * Rx Flow control is enabled and Tx Flow control is
-		 * disabled by software override. Since there really
-		 * isn't a way to advertise that we are capable of RX
-		 * Pause ONLY, we will advertise that we support both
-		 * symmetric and asymmetric Rx PAUSE.  Later, we will
-		 * disable the adapter's ability to send PAUSE frames.
-		 */
-		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
-		break;
-	case ixgbe_fc_tx_pause:
-		/*
-		 * Tx Flow control is enabled, and Rx Flow control is
-		 * disabled by software override.
-		 */
-		reg |= (IXGBE_AUTOC_ASM_PAUSE);
-		reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
-		break;
-	case ixgbe_fc_full:
-		/* Flow control (both Rx and Tx) is enabled by SW override. */
-		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
-		break;
-#ifdef CONFIG_DCB
-	case ixgbe_fc_pfc:
-		goto out;
-		break;
-#endif /* CONFIG_DCB */
-	default:
-		hw_dbg(hw, "Flow control param set incorrectly\n");
-		ret_val = IXGBE_ERR_CONFIG;
-		goto out;
-		break;
+	if (hw->phy.media_type == ixgbe_media_type_backplane) {
+		reg_bp |= IXGBE_AUTOC_AN_RESTART;
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+		    (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
+		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
+				      MDIO_MMD_AN, reg_cu);
 	}
-	/*
-	 * AUTOC restart handles negotiation of 1G and 10G. There is
-	 * no need to set the PCS1GCTL register.
-	 */
-	reg |= IXGBE_AUTOC_AN_RESTART;
-	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
-	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
 
+	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
 out:
 	return ret_val;
 }
@@ -2159,10 +2090,16 @@ out:
  **/
 s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
+	struct ixgbe_adapter *adapter = hw->back;
 	u32 i;
 	u32 reg_val;
 	u32 number_of_queues;
-	s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+	s32 status = 0;
+	u16 dev_status = 0;
+
+	/* Just jump out if bus mastering is already disabled */
+	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+		goto out;
 
 	/* Disable the receive unit by stopping each queue */
 	number_of_queues = hw->mac.max_rx_queues;
@@ -2179,13 +2116,43 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
 
 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
-		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) {
-			status = 0;
+		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+			goto check_device_status;
+		udelay(100);
+	}
+
+	hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n");
+	status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+
+	/*
+	 * Before proceeding, make sure that the PCIe block does not have
+	 * transactions pending.
+	 */
+check_device_status:
+	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+		pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS,
+							 &dev_status);
+		if (!(dev_status & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
 			break;
-		}
 		udelay(100);
 	}
 
+	if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
+		hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
+	else
+		goto out;
+
+	/*
+	 * Two consecutive resets are required via CTRL.RST per datasheet
+	 * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
+	 * of this need.  The first reset prevents new master requests from
+	 * being issued by our device.  We then must wait 1usec for any
+	 * remaining completions from the PCIe bus to trickle in, and then reset
+	 * again to clear out any effects they may have had on our device.
+	 */
+	 hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+
+out:
 	return status;
 }
 
@@ -2195,7 +2162,7 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
  *  @hw: pointer to hardware structure
  *  @mask: Mask to specify which semaphore to acquire
  *
- *  Acquires the SWFW semaphore thought the GSSR register for the specified
+ *  Acquires the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
@@ -2206,6 +2173,10 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 	s32 timeout = 200;
 
 	while (timeout) {
+		/*
+		 * SW EEPROM semaphore bit is used for access to all
+		 * SW_FW_SYNC/GSSR bits (not just EEPROM)
+		 */
 		if (ixgbe_get_eeprom_semaphore(hw))
 			return IXGBE_ERR_SWFW_SYNC;
 
@@ -2223,7 +2194,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 	}
 
 	if (!timeout) {
-		hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n");
+		hw_dbg(hw, "Driver can't access resource, SW_FW_SYNC timeout.\n");
 		return IXGBE_ERR_SWFW_SYNC;
 	}
 
@@ -2239,7 +2210,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
  *  @hw: pointer to hardware structure
  *  @mask: Mask to specify which semaphore to release
  *
- *  Releases the SWFW semaphore thought the GSSR register for the specified
+ *  Releases the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
 void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
@@ -2427,37 +2398,38 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
 	u32 mpsar_lo, mpsar_hi;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
-	if (rar < rar_entries) {
-		mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
-		mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
+		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
 
-		if (!mpsar_lo && !mpsar_hi)
-			goto done;
+	mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+	mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
 
-		if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
-			if (mpsar_lo) {
-				IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
-				mpsar_lo = 0;
-			}
-			if (mpsar_hi) {
-				IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
-				mpsar_hi = 0;
-			}
-		} else if (vmdq < 32) {
-			mpsar_lo &= ~(1 << vmdq);
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
-		} else {
-			mpsar_hi &= ~(1 << (vmdq - 32));
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
-		}
+	if (!mpsar_lo && !mpsar_hi)
+		goto done;
 
-		/* was that the last pool using this rar? */
-		if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
-			hw->mac.ops.clear_rar(hw, rar);
+	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
+		if (mpsar_lo) {
+			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
+			mpsar_lo = 0;
+		}
+		if (mpsar_hi) {
+			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
+			mpsar_hi = 0;
+		}
+	} else if (vmdq < 32) {
+		mpsar_lo &= ~(1 << vmdq);
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
 	} else {
-		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		mpsar_hi &= ~(1 << (vmdq - 32));
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
 	}
 
+	/* was that the last pool using this rar? */
+	if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
+		hw->mac.ops.clear_rar(hw, rar);
 done:
 	return 0;
 }
@@ -2473,18 +2445,20 @@ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
 	u32 mpsar;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
-	if (rar < rar_entries) {
-		if (vmdq < 32) {
-			mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
-			mpsar |= 1 << vmdq;
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
-		} else {
-			mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
-			mpsar |= 1 << (vmdq - 32);
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
-		}
-	} else {
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
+
+	if (vmdq < 32) {
+		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+		mpsar |= 1 << vmdq;
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
+	} else {
+		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+		mpsar |= 1 << (vmdq - 32);
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
 	}
 	return 0;
 }
@@ -2497,7 +2471,6 @@ s32 ixgbe_init_uta_tables_generic(struct ixgbe_hw *hw)
 {
 	int i;
 
-
 	for (i = 0; i < 128; i++)
 		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
 
@@ -2726,12 +2699,21 @@ s32 ixgbe_clear_vfta_generic(struct ixgbe_hw *hw)
  *  Reads the links register to determine if link is up and the current speed
  **/
 s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
-                               bool *link_up, bool link_up_wait_to_complete)
+				 bool *link_up, bool link_up_wait_to_complete)
 {
-	u32 links_reg;
+	u32 links_reg, links_orig;
 	u32 i;
 
+	/* clear the old state */
+	links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
+	if (links_orig != links_reg) {
+		hw_dbg(hw, "LINKS changed from %08X to %08X\n",
+		       links_orig, links_reg);
+	}
+
 	if (link_up_wait_to_complete) {
 		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
 			if (links_reg & IXGBE_LINKS_UP) {
@@ -2754,10 +2736,13 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
 	    IXGBE_LINKS_SPEED_10G_82599)
 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
 	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
-	         IXGBE_LINKS_SPEED_1G_82599)
+		 IXGBE_LINKS_SPEED_1G_82599)
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
-	else
+	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+		 IXGBE_LINKS_SPEED_100_82599)
 		*speed = IXGBE_LINK_SPEED_100_FULL;
+	else
+		*speed = IXGBE_LINK_SPEED_UNKNOWN;
 
 	/* if link is down, zero out the current_mode */
 	if (*link_up == false) {
@@ -2814,6 +2799,28 @@ wwn_prefix_out:
 }
 
 /**
+ *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ *  control
+ *  @hw: pointer to hardware structure
+ *
+ *  There are several phys that do not support autoneg flow control. This
+ *  function check the device id to see if the associated phy supports
+ *  autoneg flow control.
+ **/
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_X540T:
+		return 0;
+	case IXGBE_DEV_ID_82599_T3_LOM:
+		return 0;
+	default:
+		return IXGBE_ERR_FC_NOT_SUPPORTED;
+	}
+}
+
+/**
  *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
  *  @hw: pointer to hardware structure
  *  @enable: enable or disable switch for anti-spoofing
diff --git a/drivers/net/ixgbe/ixgbe_common.h b/drivers/net/ixgbe/ixgbe_common.h
index 66ed045..508f635 100644
--- a/drivers/net/ixgbe/ixgbe_common.h
+++ b/drivers/net/ixgbe/ixgbe_common.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -29,6 +29,7 @@
 #define _IXGBE_COMMON_H_
 
 #include "ixgbe_type.h"
+#include "ixgbe.h"
 
 u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
 s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
@@ -62,8 +63,6 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index);
 s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw);
 s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
 				      struct net_device *netdev);
-s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
-				      struct net_device *netdev);
 s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
 s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
@@ -110,9 +109,8 @@ void ixgbe_set_vlan_anti_spoofing(struct ixgbe_hw *hw, bool enable, int vf);
 
 #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
 
-extern struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw);
 #define hw_dbg(hw, format, arg...) \
-	netdev_dbg(ixgbe_get_hw_dev(hw), format, ##arg)
+	netdev_dbg(((struct ixgbe_adapter *)(hw->back))->netdev, format, ##arg)
 #define e_dev_info(format, arg...) \
 	dev_info(&adapter->pdev->dev, format, ## arg)
 #define e_dev_warn(format, arg...) \
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
index d16c260..41c529f 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.c
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -34,6 +34,42 @@
 #include "ixgbe_dcb_82599.h"
 
 /**
+ * ixgbe_ieee_credits - This calculates the ieee traffic class
+ * credits from the configured bandwidth percentages. Credits
+ * are the smallest unit programable into the underlying
+ * hardware. The IEEE 802.1Qaz specification do not use bandwidth
+ * groups so this is much simplified from the CEE case.
+ */
+s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame)
+{
+	int min_percent = 100;
+	int min_credit, multiplier;
+	int i;
+
+	min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
+			DCB_CREDIT_QUANTUM;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		if (bw[i] < min_percent && bw[i])
+			min_percent = bw[i];
+	}
+
+	multiplier = (min_credit / min_percent) + 1;
+
+	/* Find out the hw credits for each TC */
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		int val = min(bw[i] * multiplier, MAX_CREDIT_REFILL);
+
+		if (val < min_credit)
+			val = min_credit;
+		refill[i] = val;
+
+		max[i] = bw[i] ? (bw[i] * MAX_CREDIT)/100 : min_credit;
+	}
+	return 0;
+}
+
+/**
  * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
  * @ixgbe_dcb_config: Struct containing DCB settings.
  * @direction: Configuring either Tx or Rx.
@@ -141,6 +177,59 @@ out:
 	return ret_val;
 }
 
+void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
+{
+	int i;
+
+	*pfc_en = 0;
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+		*pfc_en |= (cfg->tc_config[i].dcb_pfc & 0xF) << i;
+}
+
+void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *cfg, int direction,
+			     u16 *refill)
+{
+	struct tc_bw_alloc *p;
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		p = &cfg->tc_config[i].path[direction];
+		refill[i] = p->data_credits_refill;
+	}
+}
+
+void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *cfg, u16 *max)
+{
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+		max[i] = cfg->tc_config[i].desc_credits_max;
+}
+
+void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *cfg, int direction,
+			    u8 *bwgid)
+{
+	struct tc_bw_alloc *p;
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		p = &cfg->tc_config[i].path[direction];
+		bwgid[i] = p->bwg_id;
+	}
+}
+
+void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction,
+			    u8 *ptype)
+{
+	struct tc_bw_alloc *p;
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		p = &cfg->tc_config[i].path[direction];
+		ptype[i] = p->prio_type;
+	}
+}
+
 /**
  * ixgbe_dcb_hw_config - Config and enable DCB
  * @hw: pointer to hardware structure
@@ -152,13 +241,32 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
                         struct ixgbe_dcb_config *dcb_config)
 {
 	s32 ret = 0;
+	u8 pfc_en;
+	u8 ptype[MAX_TRAFFIC_CLASS];
+	u8 bwgid[MAX_TRAFFIC_CLASS];
+	u16 refill[MAX_TRAFFIC_CLASS];
+	u16 max[MAX_TRAFFIC_CLASS];
+	/* CEE does not define a priority to tc mapping so map 1:1 */
+	u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+	/* Unpack CEE standard containers */
+	ixgbe_dcb_unpack_pfc(dcb_config, &pfc_en);
+	ixgbe_dcb_unpack_refill(dcb_config, DCB_TX_CONFIG, refill);
+	ixgbe_dcb_unpack_max(dcb_config, max);
+	ixgbe_dcb_unpack_bwgid(dcb_config, DCB_TX_CONFIG, bwgid);
+	ixgbe_dcb_unpack_prio(dcb_config, DCB_TX_CONFIG, ptype);
+
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config);
+		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->rx_pba_cfg,
+						pfc_en, refill, max, bwgid,
+						ptype);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config);
+		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->rx_pba_cfg,
+						pfc_en, refill, max, bwgid,
+						ptype, prio_tc);
 		break;
 	default:
 		break;
@@ -166,3 +274,49 @@ s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
 	return ret;
 }
 
+/* Helper routines to abstract HW specifics from DCB netlink ops */
+s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en)
+{
+	int ret = -EINVAL;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
+			    u16 *refill, u16 *max, u8 *bwg_id,
+			    u8 *prio_type, u8 *prio_tc)
+{
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max,
+							prio_type);
+		ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
+							     bwg_id, prio_type);
+		ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
+							     bwg_id, prio_type);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max,
+						  bwg_id, prio_type, prio_tc);
+		ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
+						       bwg_id, prio_type);
+		ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id,
+						       prio_type, prio_tc);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
index 1cfe38e..944838f 100644
--- a/drivers/net/ixgbe/ixgbe_dcb.h
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -139,7 +139,6 @@ struct ixgbe_dcb_config {
 	struct tc_configuration tc_config[MAX_TRAFFIC_CLASS];
 	u8     bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
 	bool   pfc_mode_enable;
-	bool   round_robin_enable;
 
 	enum dcb_rx_pba_cfg rx_pba_cfg;
 
@@ -148,12 +147,21 @@ struct ixgbe_dcb_config {
 };
 
 /* DCB driver APIs */
+void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en);
+void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *, int, u16 *);
+void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *, u16 *);
+void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *, int, u8 *);
+void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *, int, u8 *);
 
 /* DCB credits calculation */
+s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame);
 s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *,
 				   struct ixgbe_dcb_config *, int, u8);
 
 /* DCB hw initialization */
+s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, u16 *refill, u16 *max,
+			    u8 *bwg_id, u8 *prio_type, u8 *tc_prio);
+s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en);
 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
 
 /* DCB definitions for credit calculation */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
index 9a5e89c..1bc57e5 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -38,15 +38,14 @@
  *
  * Configure packet buffers for DCB mode.
  */
-static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw,
-						 struct ixgbe_dcb_config *dcb_config)
+static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, u8 rx_pba)
 {
 	s32 ret_val = 0;
 	u32 value = IXGBE_RXPBSIZE_64KB;
 	u8  i = 0;
 
 	/* Setup Rx packet buffer sizes */
-	switch (dcb_config->rx_pba_cfg) {
+	switch (rx_pba) {
 	case pba_80_48:
 		/* Setup the first four at 80KB */
 		value = IXGBE_RXPBSIZE_80KB;
@@ -78,10 +77,11 @@ static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw,
  *
  * Configure Rx Data Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
-                                      struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+					u16 *refill,
+					u16 *max,
+					u8 *prio_type)
 {
-	struct tc_bw_alloc    *p;
 	u32    reg           = 0;
 	u32    credit_refill = 0;
 	u32    credit_max    = 0;
@@ -102,13 +102,12 @@ static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG];
-		credit_refill = p->data_credits_refill;
-		credit_max    = p->data_credits_max;
+		credit_refill = refill[i];
+		credit_max    = max[i];
 
 		reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT);
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RT2CR_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg);
@@ -135,10 +134,12 @@ static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
  *
  * Configure Tx Descriptor Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type)
 {
-	struct tc_bw_alloc *p;
 	u32    reg, max_credits;
 	u8     i;
 
@@ -146,10 +147,8 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
 
 	/* Enable arbiter */
 	reg &= ~IXGBE_DPMCS_ARBDIS;
-	if (!(dcb_config->round_robin_enable)) {
-		/* Enable DFP and Recycle mode */
-		reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
-	}
+	/* Enable DFP and Recycle mode */
+	reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
 	reg |= IXGBE_DPMCS_TSOEF;
 	/* Configure Max TSO packet size 34KB including payload and headers */
 	reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT);
@@ -158,16 +157,15 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		max_credits = dcb_config->tc_config[i].desc_credits_max;
+		max_credits = max[i];
 		reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT;
-		reg |= p->data_credits_refill;
-		reg |= (u32)(p->bwg_id) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
+		reg |= refill[i];
+		reg |= (u32)(bwg_id[i]) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_TDTQ2TCCR_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_TDTQ2TCCR_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg);
@@ -183,10 +181,12 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
  *
  * Configure Tx Data Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type)
 {
-	struct tc_bw_alloc *p;
 	u32 reg;
 	u8 i;
 
@@ -200,15 +200,14 @@ static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		reg = p->data_credits_refill;
-		reg |= (u32)(p->data_credits_max) << IXGBE_TDPT2TCCR_MCL_SHIFT;
-		reg |= (u32)(p->bwg_id) << IXGBE_TDPT2TCCR_BWG_SHIFT;
+		reg = refill[i];
+		reg |= (u32)(max[i]) << IXGBE_TDPT2TCCR_MCL_SHIFT;
+		reg |= (u32)(bwg_id[i]) << IXGBE_TDPT2TCCR_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_TDPT2TCCR_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_TDPT2TCCR_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg);
@@ -229,59 +228,57 @@ static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
  *
  * Configure Priority Flow Control for each traffic class.
  */
-s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw,
-                               struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
 {
 	u32 reg, rx_pba_size;
 	u8  i;
 
-	if (!dcb_config->pfc_mode_enable)
-		goto out;
-
-	/* Enable Transmit Priority Flow Control */
-	reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
-	reg &= ~IXGBE_RMCS_TFCE_802_3X;
-	/* correct the reporting of our flow control status */
-	reg |= IXGBE_RMCS_TFCE_PRIORITY;
-	IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
-
-	/* Enable Receive Priority Flow Control */
-	reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-	reg &= ~IXGBE_FCTRL_RFCE;
-	reg |= IXGBE_FCTRL_RPFCE;
-	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
+	if (pfc_en) {
+		/* Enable Transmit Priority Flow Control */
+		reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
+		reg &= ~IXGBE_RMCS_TFCE_802_3X;
+		/* correct the reporting of our flow control status */
+		reg |= IXGBE_RMCS_TFCE_PRIORITY;
+		IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
+
+		/* Enable Receive Priority Flow Control */
+		reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+		reg &= ~IXGBE_FCTRL_RFCE;
+		reg |= IXGBE_FCTRL_RPFCE;
+		IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
+
+		/* Configure pause time */
+		for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
+			IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
+
+		/* Configure flow control refresh threshold value */
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
+	}
 
 	/*
 	 * Configure flow control thresholds and enable priority flow control
 	 * for each traffic class.
 	 */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		int enabled = pfc_en & (1 << i);
 		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
 		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 		reg = (rx_pba_size - hw->fc.low_water) << 10;
 
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
+		if (enabled == pfc_enabled_tx ||
+		    enabled == pfc_enabled_full)
 			reg |= IXGBE_FCRTL_XONE;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
 
 		reg = (rx_pba_size - hw->fc.high_water) << 10;
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
+		if (enabled == pfc_enabled_tx ||
+		    enabled == pfc_enabled_full)
 			reg |= IXGBE_FCRTH_FCEN;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
 	}
 
-	/* Configure pause time */
-	for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
-		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
-
-	/* Configure flow control refresh threshold value */
-	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
-
-out:
 	return 0;
 }
 
@@ -292,7 +289,7 @@ out:
  * Configure queue statistics registers, all queues belonging to same traffic
  * class uses a single set of queue statistics counters.
  */
-static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
+s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
 {
 	u32 reg = 0;
 	u8  i   = 0;
@@ -325,13 +322,16 @@ static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
  * Configure dcb settings and enable dcb mode.
  */
 s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
-                              struct ixgbe_dcb_config *dcb_config)
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type)
 {
-	ixgbe_dcb_config_packet_buffers_82598(hw, dcb_config);
-	ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
-	ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
-	ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
-	ixgbe_dcb_config_pfc_82598(hw, dcb_config);
+	ixgbe_dcb_config_packet_buffers_82598(hw, rx_pba);
+	ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, prio_type);
+	ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
+					       bwg_id, prio_type);
+	ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
+					       bwg_id, prio_type);
+	ixgbe_dcb_config_pfc_82598(hw, pfc_en);
 	ixgbe_dcb_config_tc_stats_82598(hw);
 
 	return 0;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
index abc03cc..1e9750c 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82598.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -71,9 +71,28 @@
 /* DCB hardware-specific driver APIs */
 
 /* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, u8 pfc_en);
 
 /* DCB hw initialization */
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+					u16 *refill,
+					u16 *max,
+					u8 *prio_type);
+
+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type);
+
+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type);
+
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type);
 
 #endif /* _DCB_82598_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.c b/drivers/net/ixgbe/ixgbe_dcb_82599.c
index 374e1f7..025af8c 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -33,19 +33,18 @@
 /**
  * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @rx_pba: method to distribute packet buffer
  *
  * Configure packet buffers for DCB mode.
  */
-static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
-                                          struct ixgbe_dcb_config *dcb_config)
+static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba)
 {
 	s32 ret_val = 0;
 	u32 value = IXGBE_RXPBSIZE_64KB;
 	u8  i = 0;
 
 	/* Setup Rx packet buffer sizes */
-	switch (dcb_config->rx_pba_cfg) {
+	switch (rx_pba) {
 	case pba_80_48:
 		/* Setup the first four at 80KB */
 		value = IXGBE_RXPBSIZE_80KB;
@@ -75,14 +74,20 @@ static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
 /**
  * ixgbe_dcb_config_rx_arbiter_82599 - Config Rx Data arbiter
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
  *
  * Configure Rx Packet Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
-                                      struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
+				      u16 *refill,
+				      u16 *max,
+				      u8 *bwg_id,
+				      u8 *prio_type,
+				      u8 *prio_tc)
 {
-	struct tc_bw_alloc    *p;
 	u32    reg           = 0;
 	u32    credit_refill = 0;
 	u32    credit_max    = 0;
@@ -98,20 +103,18 @@ static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
 	/* Map all traffic classes to their UP, 1 to 1 */
 	reg = 0;
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
-		reg |= (i << (i * IXGBE_RTRUP2TC_UP_SHIFT));
+		reg |= (prio_tc[i] << (i * IXGBE_RTRUP2TC_UP_SHIFT));
 	IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg);
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG];
-
-		credit_refill = p->data_credits_refill;
-		credit_max    = p->data_credits_max;
+		credit_refill = refill[i];
+		credit_max    = max[i];
 		reg = credit_refill | (credit_max << IXGBE_RTRPT4C_MCL_SHIFT);
 
-		reg |= (u32)(p->bwg_id) << IXGBE_RTRPT4C_BWG_SHIFT;
+		reg |= (u32)(bwg_id[i]) << IXGBE_RTRPT4C_BWG_SHIFT;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RTRPT4C_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RTRPT4C(i), reg);
@@ -130,14 +133,19 @@ static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
 /**
  * ixgbe_dcb_config_tx_desc_arbiter_82599 - Config Tx Desc. arbiter
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
  *
  * Configure Tx Descriptor Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
+					   u16 *refill,
+					   u16 *max,
+					   u8 *bwg_id,
+					   u8 *prio_type)
 {
-	struct tc_bw_alloc *p;
 	u32    reg, max_credits;
 	u8     i;
 
@@ -149,16 +157,15 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		max_credits = dcb_config->tc_config[i].desc_credits_max;
+		max_credits = max[i];
 		reg = max_credits << IXGBE_RTTDT2C_MCL_SHIFT;
-		reg |= p->data_credits_refill;
-		reg |= (u32)(p->bwg_id) << IXGBE_RTTDT2C_BWG_SHIFT;
+		reg |= refill[i];
+		reg |= (u32)(bwg_id[i]) << IXGBE_RTTDT2C_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_RTTDT2C_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RTTDT2C_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RTTDT2C(i), reg);
@@ -177,14 +184,20 @@ static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
 /**
  * ixgbe_dcb_config_tx_data_arbiter_82599 - Config Tx Data arbiter
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
  *
  * Configure Tx Packet Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
+					   u16 *refill,
+					   u16 *max,
+					   u8 *bwg_id,
+					   u8 *prio_type,
+					   u8 *prio_tc)
 {
-	struct tc_bw_alloc *p;
 	u32 reg;
 	u8 i;
 
@@ -200,20 +213,19 @@ static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
 	/* Map all traffic classes to their UP, 1 to 1 */
 	reg = 0;
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
-		reg |= (i << (i * IXGBE_RTTUP2TC_UP_SHIFT));
+		reg |= (prio_tc[i] << (i * IXGBE_RTTUP2TC_UP_SHIFT));
 	IXGBE_WRITE_REG(hw, IXGBE_RTTUP2TC, reg);
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		reg = p->data_credits_refill;
-		reg |= (u32)(p->data_credits_max) << IXGBE_RTTPT2C_MCL_SHIFT;
-		reg |= (u32)(p->bwg_id) << IXGBE_RTTPT2C_BWG_SHIFT;
+		reg = refill[i];
+		reg |= (u32)(max[i]) << IXGBE_RTTPT2C_MCL_SHIFT;
+		reg |= (u32)(bwg_id[i]) << IXGBE_RTTPT2C_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_RTTPT2C_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RTTPT2C_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RTTPT2C(i), reg);
@@ -233,63 +245,59 @@ static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
 /**
  * ixgbe_dcb_config_pfc_82599 - Configure priority flow control
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @pfc_en: enabled pfc bitmask
  *
  * Configure Priority Flow Control (PFC) for each traffic class.
  */
-s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw,
-                               struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en)
 {
 	u32 i, reg, rx_pba_size;
 
-	/* If PFC is disabled globally then fall back to LFC. */
-	if (!dcb_config->pfc_mode_enable) {
-		for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
-			hw->mac.ops.fc_enable(hw, i);
-		goto out;
-	}
-
 	/* Configure PFC Tx thresholds per TC */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		int enabled = pfc_en & (1 << i);
 		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
 		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 
 		reg = (rx_pba_size - hw->fc.low_water) << 10;
 
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx)
+		if (enabled)
 			reg |= IXGBE_FCRTL_XONE;
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
 
 		reg = (rx_pba_size - hw->fc.high_water) << 10;
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx)
+		if (enabled)
 			reg |= IXGBE_FCRTH_FCEN;
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
 	}
 
-	/* Configure pause time (2 TCs per register) */
-	reg = hw->fc.pause_time | (hw->fc.pause_time << 16);
-	for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
-		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
-
-	/* Configure flow control refresh threshold value */
-	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
-
-	/* Enable Transmit PFC */
-	reg = IXGBE_FCCFG_TFCE_PRIORITY;
-	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg);
+	if (pfc_en) {
+		/* Configure pause time (2 TCs per register) */
+		reg = hw->fc.pause_time | (hw->fc.pause_time << 16);
+		for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+			IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
+
+		/* Configure flow control refresh threshold value */
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
+
+
+		reg = IXGBE_FCCFG_TFCE_PRIORITY;
+		IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg);
+		/*
+		 * Enable Receive PFC
+		 * We will always honor XOFF frames we receive when
+		 * we are in PFC mode.
+		 */
+		reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+		reg &= ~IXGBE_MFLCN_RFCE;
+		reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
+		IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
+
+	} else {
+		for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+			hw->mac.ops.fc_enable(hw, i);
+	}
 
-	/*
-	 * Enable Receive PFC
-	 * We will always honor XOFF frames we receive when
-	 * we are in PFC mode.
-	 */
-	reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-	reg &= ~IXGBE_MFLCN_RFCE;
-	reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
-	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
-out:
 	return 0;
 }
 
@@ -349,7 +357,6 @@ static s32 ixgbe_dcb_config_tc_stats_82599(struct ixgbe_hw *hw)
 /**
  * ixgbe_dcb_config_82599 - Configure general DCB parameters
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
  *
  * Configure general DCB parameters.
  */
@@ -406,19 +413,28 @@ static s32 ixgbe_dcb_config_82599(struct ixgbe_hw *hw)
 /**
  * ixgbe_dcb_hw_config_82599 - Configure and enable DCB
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @rx_pba: method to distribute packet buffer
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
+ * @pfc_en: enabled pfc bitmask
  *
  * Configure dcb settings and enable dcb mode.
  */
 s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
-                              struct ixgbe_dcb_config *dcb_config)
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type, u8 *prio_tc)
 {
-	ixgbe_dcb_config_packet_buffers_82599(hw, dcb_config);
+	ixgbe_dcb_config_packet_buffers_82599(hw, rx_pba);
 	ixgbe_dcb_config_82599(hw);
-	ixgbe_dcb_config_rx_arbiter_82599(hw, dcb_config);
-	ixgbe_dcb_config_tx_desc_arbiter_82599(hw, dcb_config);
-	ixgbe_dcb_config_tx_data_arbiter_82599(hw, dcb_config);
-	ixgbe_dcb_config_pfc_82599(hw, dcb_config);
+	ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
+					  prio_type, prio_tc);
+	ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
+					       bwg_id, prio_type);
+	ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
+					       bwg_id, prio_type, prio_tc);
+	ixgbe_dcb_config_pfc_82599(hw, pfc_en);
 	ixgbe_dcb_config_tc_stats_82599(hw);
 
 	return 0;
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82599.h b/drivers/net/ixgbe/ixgbe_dcb_82599.h
index 3841649..148fd8b 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_82599.h
+++ b/drivers/net/ixgbe/ixgbe_dcb_82599.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -102,11 +102,32 @@
 /* DCB hardware-specific driver APIs */
 
 /* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw,
-                               struct ixgbe_dcb_config *dcb_config);
+s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en);
 
 /* DCB hw initialization */
+s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
+					u16 *refill,
+					u16 *max,
+					u8 *bwg_id,
+					u8 *prio_type,
+					u8 *prio_tc);
+
+s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type);
+
+s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type,
+						u8 *prio_tc);
+
 s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
-                              struct ixgbe_dcb_config *config);
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type,
+			      u8 *prio_tc);
 
 #endif /* _DCB_82599_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
index bf566e8..fec4c72 100644
--- a/drivers/net/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -37,7 +37,6 @@
 #define BIT_PG_RX	0x04
 #define BIT_PG_TX	0x08
 #define BIT_APP_UPCHG	0x10
-#define BIT_RESETLINK   0x40
 #define BIT_LINKSPEED   0x80
 
 /* Responses for the DCB_C_SET_ALL command */
@@ -130,7 +129,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 			netdev->netdev_ops->ndo_stop(netdev);
 		ixgbe_clear_interrupt_scheme(adapter);
 
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
 		switch (adapter->hw.mac.type) {
 		case ixgbe_mac_82598EB:
 			adapter->last_lfc_mode = adapter->hw.fc.current_mode;
@@ -146,6 +144,9 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 		}
 
 		adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+		if (!netdev_get_num_tc(netdev))
+			ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
+
 		ixgbe_init_interrupt_scheme(adapter);
 		if (netif_running(netdev))
 			netdev->netdev_ops->ndo_open(netdev);
@@ -160,7 +161,6 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 			adapter->temp_dcb_cfg.pfc_mode_enable = false;
 			adapter->dcb_cfg.pfc_mode_enable = false;
 			adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
-			adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
 			switch (adapter->hw.mac.type) {
 			case ixgbe_mac_82599EB:
 			case ixgbe_mac_X540:
@@ -170,6 +170,8 @@ static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
 				break;
 			}
 
+			ixgbe_setup_tc(netdev, 0);
+
 			ixgbe_init_interrupt_scheme(adapter);
 			if (netif_running(netdev))
 				netdev->netdev_ops->ndo_open(netdev);
@@ -225,10 +227,8 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
 	     adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
-	     adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)) {
+	     adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
 		adapter->dcb_set_bitmap |= BIT_PG_TX;
-		adapter->dcb_set_bitmap |= BIT_RESETLINK;
-	}
 }
 
 static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
@@ -239,10 +239,8 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
 	adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
 
 	if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
-	    adapter->dcb_cfg.bw_percentage[0][bwg_id]) {
+	    adapter->dcb_cfg.bw_percentage[0][bwg_id])
 		adapter->dcb_set_bitmap |= BIT_PG_TX;
-		adapter->dcb_set_bitmap |= BIT_RESETLINK;
-	}
 }
 
 static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
@@ -269,10 +267,8 @@ static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
 	     adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
 	    (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
-	     adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)) {
+	     adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
 		adapter->dcb_set_bitmap |= BIT_PG_RX;
-		adapter->dcb_set_bitmap |= BIT_RESETLINK;
-	}
 }
 
 static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
@@ -283,10 +279,8 @@ static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
 	adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
 
 	if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
-	    adapter->dcb_cfg.bw_percentage[1][bwg_id]) {
+	    adapter->dcb_cfg.bw_percentage[1][bwg_id])
 		adapter->dcb_set_bitmap |= BIT_PG_RX;
-		adapter->dcb_set_bitmap |= BIT_RESETLINK;
-	}
 }
 
 static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
@@ -355,31 +349,28 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	int ret;
 
-	if (!adapter->dcb_set_bitmap)
+	if (!adapter->dcb_set_bitmap ||
+	    !(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
 		return DCB_NO_HW_CHG;
 
 	ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
-				 adapter->ring_feature[RING_F_DCB].indices);
+				 MAX_TRAFFIC_CLASS);
 
 	if (ret)
 		return DCB_NO_HW_CHG;
 
 	/*
-	 * Only take down the adapter if the configuration change
-	 * requires a reset.
+	 * Only take down the adapter if an app change occured. FCoE
+	 * may shuffle tx rings in this case and this can not be done
+	 * without a reset currently.
 	 */
-	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
+	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
 		while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
 			msleep(1);
 
-		if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
-			if (netif_running(netdev))
-				netdev->netdev_ops->ndo_stop(netdev);
-			ixgbe_clear_interrupt_scheme(adapter);
-		} else {
-			if (netif_running(netdev))
-				ixgbe_down(adapter);
-		}
+		if (netif_running(netdev))
+			netdev->netdev_ops->ndo_stop(netdev);
+		ixgbe_clear_interrupt_scheme(adapter);
 	}
 
 	if (adapter->dcb_cfg.pfc_mode_enable) {
@@ -408,29 +399,53 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 		}
 	}
 
-	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
-		if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
-			ixgbe_init_interrupt_scheme(adapter);
-			if (netif_running(netdev))
-				netdev->netdev_ops->ndo_open(netdev);
-		} else {
-			if (netif_running(netdev))
-				ixgbe_up(adapter);
-		}
+	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
+		ixgbe_init_interrupt_scheme(adapter);
+		if (netif_running(netdev))
+			netdev->netdev_ops->ndo_open(netdev);
 		ret = DCB_HW_CHG_RST;
-	} else if (adapter->dcb_set_bitmap & BIT_PFC) {
-		if (adapter->hw.mac.type == ixgbe_mac_82598EB)
-			ixgbe_dcb_config_pfc_82598(&adapter->hw,
-			                           &adapter->dcb_cfg);
-		else if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-			ixgbe_dcb_config_pfc_82599(&adapter->hw,
-			                           &adapter->dcb_cfg);
+	}
+
+	if (adapter->dcb_set_bitmap & BIT_PFC) {
+		u8 pfc_en;
+		ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
+		ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en);
 		ret = DCB_HW_CHG;
 	}
+
+	if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
+		u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
+		u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
+		/* Priority to TC mapping in CEE case default to 1:1 */
+		u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
+		int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+
+#ifdef CONFIG_FCOE
+		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
+#endif
+
+		ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg,
+					       max_frame, DCB_TX_CONFIG);
+		ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg,
+					       max_frame, DCB_RX_CONFIG);
+
+		ixgbe_dcb_unpack_refill(&adapter->dcb_cfg,
+					DCB_TX_CONFIG, refill);
+		ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max);
+		ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg,
+				       DCB_TX_CONFIG, bwg_id);
+		ixgbe_dcb_unpack_prio(&adapter->dcb_cfg,
+				      DCB_TX_CONFIG, prio_type);
+
+		ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
+					bwg_id, prio_type, prio_tc);
+	}
+
 	if (adapter->dcb_cfg.pfc_mode_enable)
 		adapter->hw.fc.current_mode = ixgbe_fc_pfc;
 
-	if (adapter->dcb_set_bitmap & BIT_RESETLINK)
+	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG)
 		clear_bit(__IXGBE_RESETTING, &adapter->state);
 	adapter->dcb_set_bitmap = 0x00;
 	return ret;
@@ -439,40 +454,38 @@ static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
 static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u8 rval = 0;
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		switch (capid) {
-		case DCB_CAP_ATTR_PG:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_PFC:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_UP2TC:
-			*cap = false;
-			break;
-		case DCB_CAP_ATTR_PG_TCS:
-			*cap = 0x80;
-			break;
-		case DCB_CAP_ATTR_PFC_TCS:
-			*cap = 0x80;
-			break;
-		case DCB_CAP_ATTR_GSP:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_BCN:
-			*cap = false;
-			break;
-		default:
-			rval = -EINVAL;
-			break;
-		}
-	} else {
-		rval = -EINVAL;
+	switch (capid) {
+	case DCB_CAP_ATTR_PG:
+		*cap = true;
+		break;
+	case DCB_CAP_ATTR_PFC:
+		*cap = true;
+		break;
+	case DCB_CAP_ATTR_UP2TC:
+		*cap = false;
+		break;
+	case DCB_CAP_ATTR_PG_TCS:
+		*cap = 0x80;
+		break;
+	case DCB_CAP_ATTR_PFC_TCS:
+		*cap = 0x80;
+		break;
+	case DCB_CAP_ATTR_GSP:
+		*cap = true;
+		break;
+	case DCB_CAP_ATTR_BCN:
+		*cap = false;
+		break;
+	case DCB_CAP_ATTR_DCBX:
+		*cap = adapter->dcbx_cap;
+		break;
+	default:
+		*cap = false;
+		break;
 	}
 
-	return rval;
+	return 0;
 }
 
 static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
@@ -533,21 +546,16 @@ static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
  */
 static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
 {
-	u8 rval = 0;
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct dcb_app app = {
+				.selector = idtype,
+				.protocol = id,
+			     };
 
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-#ifdef IXGBE_FCOE
-		if (id == ETH_P_FCOE)
-			rval = ixgbe_fcoe_getapp(netdev_priv(netdev));
-#endif
-		break;
-	case DCB_APP_IDTYPE_PORTNUM:
-		break;
-	default:
-		break;
-	}
-	return rval;
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
+		return 0;
+
+	return dcb_getapp(netdev, &app);
 }
 
 /**
@@ -562,24 +570,45 @@ static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
 static u8 ixgbe_dcbnl_setapp(struct net_device *netdev,
                              u8 idtype, u16 id, u8 up)
 {
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	u8 rval = 1;
+	struct dcb_app app = {
+			      .selector = idtype,
+			      .protocol = id,
+			      .priority = up
+			     };
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
+		return rval;
+
+	rval = dcb_setapp(netdev, &app);
 
 	switch (idtype) {
 	case DCB_APP_IDTYPE_ETHTYPE:
 #ifdef IXGBE_FCOE
 		if (id == ETH_P_FCOE) {
-			u8 tc;
-			struct ixgbe_adapter *adapter;
+			u8 old_tc;
 
-			adapter = netdev_priv(netdev);
-			tc = adapter->fcoe.tc;
+			/* Get current programmed tc */
+			old_tc = adapter->fcoe.tc;
 			rval = ixgbe_fcoe_setapp(adapter, up);
-			if ((!rval) && (tc != adapter->fcoe.tc) &&
-			    (adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
-			    (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
+
+			if (rval ||
+			   !(adapter->flags & IXGBE_FLAG_DCB_ENABLED) ||
+			   !(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
+				break;
+
+			/* The FCoE application priority may be changed multiple
+			 * times in quick sucession with switches that build up
+			 * TLVs. To avoid creating uneeded device resets this
+			 * checks the actual HW configuration and clears
+			 * BIT_APP_UPCHG if a HW configuration change is not
+			 * need
+			 */
+			if (old_tc == adapter->fcoe.tc)
+				adapter->dcb_set_bitmap &= ~BIT_APP_UPCHG;
+			else
 				adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
-				adapter->dcb_set_bitmap |= BIT_RESETLINK;
-			}
 		}
 #endif
 		break;
@@ -591,7 +620,204 @@ static u8 ixgbe_dcbnl_setapp(struct net_device *netdev,
 	return rval;
 }
 
+static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
+				   struct ieee_ets *ets)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets;
+
+	/* No IEEE PFC settings available */
+	if (!my_ets)
+		return -EINVAL;
+
+	ets->ets_cap = MAX_TRAFFIC_CLASS;
+	ets->cbs = my_ets->cbs;
+	memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
+	memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
+	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
+	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
+	return 0;
+}
+
+static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
+				   struct ieee_ets *ets)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	__u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
+	__u8 prio_type[IEEE_8021QAZ_MAX_TCS];
+	int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
+	int i, err;
+	__u64 *p = (__u64 *) ets->prio_tc;
+	/* naively give each TC a bwg to map onto CEE hardware */
+	__u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+
+	if (!adapter->ixgbe_ieee_ets) {
+		adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets),
+						  GFP_KERNEL);
+		if (!adapter->ixgbe_ieee_ets)
+			return -ENOMEM;
+	}
+
+	memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));
+
+	/* Map TSA onto CEE prio type */
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+		switch (ets->tc_tsa[i]) {
+		case IEEE_8021QAZ_TSA_STRICT:
+			prio_type[i] = 2;
+			break;
+		case IEEE_8021QAZ_TSA_ETS:
+			prio_type[i] = 0;
+			break;
+		default:
+			/* Hardware only supports priority strict or
+			 * ETS transmission selection algorithms if
+			 * we receive some other value from dcbnl
+			 * throw an error
+			 */
+			return -EINVAL;
+		}
+	}
+
+	if (*p)
+		ixgbe_dcbnl_set_state(dev, 1);
+	else
+		ixgbe_dcbnl_set_state(dev, 0);
+
+	ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
+	err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
+				      bwg_id, prio_type, ets->prio_tc);
+	return err;
+}
+
+static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
+				   struct ieee_pfc *pfc)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
+	int i;
+
+	/* No IEEE PFC settings available */
+	if (!my_pfc)
+		return -EINVAL;
+
+	pfc->pfc_cap = MAX_TRAFFIC_CLASS;
+	pfc->pfc_en = my_pfc->pfc_en;
+	pfc->mbc = my_pfc->mbc;
+	pfc->delay = my_pfc->delay;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		pfc->requests[i] = adapter->stats.pxoffrxc[i];
+		pfc->indications[i] = adapter->stats.pxofftxc[i];
+	}
+
+	return 0;
+}
+
+static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
+				   struct ieee_pfc *pfc)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	int err;
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+
+	if (!adapter->ixgbe_ieee_pfc) {
+		adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc),
+						  GFP_KERNEL);
+		if (!adapter->ixgbe_ieee_pfc)
+			return -ENOMEM;
+	}
+
+	memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
+	err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en);
+	return err;
+}
+
+static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
+				   struct dcb_app *app)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+#ifdef IXGBE_FCOE
+	if (app->selector == 1 && app->protocol == ETH_P_FCOE) {
+		if (adapter->fcoe.tc == app->priority)
+			goto setapp;
+
+		/* In IEEE mode map up to tc 1:1 */
+		adapter->fcoe.tc = app->priority;
+		adapter->fcoe.up = app->priority;
+
+		/* Force hardware reset required to push FCoE
+		 * setup on {tx|rx}_rings
+		 */
+		adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
+		ixgbe_dcbnl_set_all(dev);
+	}
+
+setapp:
+#endif
+	dcb_setapp(dev, app);
+	return 0;
+}
+
+static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	return adapter->dcbx_cap;
+}
+
+static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ieee_ets ets = {0};
+	struct ieee_pfc pfc = {0};
+
+	/* no support for LLD_MANAGED modes or CEE+IEEE */
+	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
+	    ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
+	    !(mode & DCB_CAP_DCBX_HOST))
+		return 1;
+
+	if (mode == adapter->dcbx_cap)
+		return 0;
+
+	adapter->dcbx_cap = mode;
+
+	/* ETS and PFC defaults */
+	ets.ets_cap = 8;
+	pfc.pfc_cap = 8;
+
+	if (mode & DCB_CAP_DCBX_VER_IEEE) {
+		ixgbe_dcbnl_ieee_setets(dev, &ets);
+		ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
+	} else if (mode & DCB_CAP_DCBX_VER_CEE) {
+		adapter->dcb_set_bitmap |= (BIT_PFC & BIT_PG_TX & BIT_PG_RX);
+		ixgbe_dcbnl_set_all(dev);
+	} else {
+		/* Drop into single TC mode strict priority as this
+		 * indicates CEE and IEEE versions are disabled
+		 */
+		ixgbe_dcbnl_ieee_setets(dev, &ets);
+		ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
+		ixgbe_dcbnl_set_state(dev, 0);
+	}
+
+	return 0;
+}
+
 const struct dcbnl_rtnl_ops dcbnl_ops = {
+	.ieee_getets	= ixgbe_dcbnl_ieee_getets,
+	.ieee_setets	= ixgbe_dcbnl_ieee_setets,
+	.ieee_getpfc	= ixgbe_dcbnl_ieee_getpfc,
+	.ieee_setpfc	= ixgbe_dcbnl_ieee_setpfc,
+	.ieee_setapp	= ixgbe_dcbnl_ieee_setapp,
 	.getstate	= ixgbe_dcbnl_get_state,
 	.setstate	= ixgbe_dcbnl_set_state,
 	.getpermhwaddr	= ixgbe_dcbnl_get_perm_hw_addr,
@@ -613,5 +839,6 @@ const struct dcbnl_rtnl_ops dcbnl_ops = {
 	.setpfcstate	= ixgbe_dcbnl_setpfcstate,
 	.getapp		= ixgbe_dcbnl_getapp,
 	.setapp		= ixgbe_dcbnl_setapp,
+	.getdcbx	= ixgbe_dcbnl_getdcbx,
+	.setdcbx	= ixgbe_dcbnl_setdcbx,
 };
-
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 2002ea8..76380a2 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -152,20 +152,35 @@ static int ixgbe_get_settings(struct net_device *netdev,
 		ecmd->supported |= (SUPPORTED_1000baseT_Full |
 		                    SUPPORTED_Autoneg);
 
+		switch (hw->mac.type) {
+		case ixgbe_mac_X540:
+			ecmd->supported |= SUPPORTED_100baseT_Full;
+			break;
+		default:
+			break;
+		}
+
 		ecmd->advertising = ADVERTISED_Autoneg;
-		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
-			ecmd->advertising |= ADVERTISED_10000baseT_Full;
-		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
-			ecmd->advertising |= ADVERTISED_1000baseT_Full;
-		/*
-		 * It's possible that phy.autoneg_advertised may not be
-		 * set yet.  If so display what the default would be -
-		 * both 1G and 10G supported.
-		 */
-		if (!(ecmd->advertising & (ADVERTISED_1000baseT_Full |
-					   ADVERTISED_10000baseT_Full)))
+		if (hw->phy.autoneg_advertised) {
+			if (hw->phy.autoneg_advertised &
+			    IXGBE_LINK_SPEED_100_FULL)
+				ecmd->advertising |= ADVERTISED_100baseT_Full;
+			if (hw->phy.autoneg_advertised &
+			    IXGBE_LINK_SPEED_10GB_FULL)
+				ecmd->advertising |= ADVERTISED_10000baseT_Full;
+			if (hw->phy.autoneg_advertised &
+			    IXGBE_LINK_SPEED_1GB_FULL)
+				ecmd->advertising |= ADVERTISED_1000baseT_Full;
+		} else {
+			/*
+			 * Default advertised modes in case
+			 * phy.autoneg_advertised isn't set.
+			 */
 			ecmd->advertising |= (ADVERTISED_10000baseT_Full |
 					      ADVERTISED_1000baseT_Full);
+			if (hw->mac.type == ixgbe_mac_X540)
+				ecmd->advertising |= ADVERTISED_100baseT_Full;
+		}
 
 		if (hw->phy.media_type == ixgbe_media_type_copper) {
 			ecmd->supported |= SUPPORTED_TP;
@@ -271,8 +286,19 @@ static int ixgbe_get_settings(struct net_device *netdev,
 
 	hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
 	if (link_up) {
-		ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
-		               SPEED_10000 : SPEED_1000;
+		switch (link_speed) {
+		case IXGBE_LINK_SPEED_10GB_FULL:
+			ecmd->speed = SPEED_10000;
+			break;
+		case IXGBE_LINK_SPEED_1GB_FULL:
+			ecmd->speed = SPEED_1000;
+			break;
+		case IXGBE_LINK_SPEED_100_FULL:
+			ecmd->speed = SPEED_100;
+			break;
+		default:
+			break;
+		}
 		ecmd->duplex = DUPLEX_FULL;
 	} else {
 		ecmd->speed = -1;
@@ -306,6 +332,9 @@ static int ixgbe_set_settings(struct net_device *netdev,
 		if (ecmd->advertising & ADVERTISED_1000baseT_Full)
 			advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
+		if (ecmd->advertising & ADVERTISED_100baseT_Full)
+			advertised |= IXGBE_LINK_SPEED_100_FULL;
+
 		if (old == advertised)
 			return err;
 		/* this sets the link speed and restarts auto-neg */
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c
index c54a882..dba7d77 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ixgbe/ixgbe_fcoe.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -135,22 +135,19 @@ out_ddp_put:
 	return len;
 }
 
+
 /**
- * ixgbe_fcoe_ddp_get - called to set up ddp context
+ * ixgbe_fcoe_ddp_setup - called to set up ddp context
  * @netdev: the corresponding net_device
  * @xid: the exchange id requesting ddp
  * @sgl: the scatter-gather list for this request
  * @sgc: the number of scatter-gather items
  *
- * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
- * and is expected to be called from ULD, e.g., FCP layer of libfc
- * to set up ddp for the corresponding xid of the given sglist for
- * the corresponding I/O.
- *
  * Returns : 1 for success and 0 for no ddp
  */
-int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
-		       struct scatterlist *sgl, unsigned int sgc)
+static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
+				struct scatterlist *sgl, unsigned int sgc,
+				int target_mode)
 {
 	struct ixgbe_adapter *adapter;
 	struct ixgbe_hw *hw;
@@ -164,7 +161,7 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
 	unsigned int lastsize;
 	unsigned int thisoff = 0;
 	unsigned int thislen = 0;
-	u32 fcbuff, fcdmarw, fcfltrw;
+	u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
 	dma_addr_t addr = 0;
 
 	if (!netdev || !sgl)
@@ -275,6 +272,9 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
 	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
 	fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
 	fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
+	/* Set WRCONTX bit to allow DDP for target */
+	if (target_mode)
+		fcbuff |= (IXGBE_FCBUFF_WRCONTX);
 	fcbuff |= (IXGBE_FCBUFF_VALID);
 
 	fcdmarw = xid;
@@ -287,6 +287,16 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
 	/* program DMA context */
 	hw = &adapter->hw;
 	spin_lock_bh(&fcoe->lock);
+
+	/* turn on last frame indication for target mode as FCP_RSPtarget is
+	 * supposed to send FCP_RSP when it is done. */
+	if (target_mode && !test_bit(__IXGBE_FCOE_TARGET, &fcoe->mode)) {
+		set_bit(__IXGBE_FCOE_TARGET, &fcoe->mode);
+		fcrxctl = IXGBE_READ_REG(hw, IXGBE_FCRXCTRL);
+		fcrxctl |= IXGBE_FCRXCTRL_LASTSEQH;
+		IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, fcrxctl);
+	}
+
 	IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_BIT_MASK(32));
 	IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32);
 	IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff);
@@ -295,6 +305,7 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
 	IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0);
 	IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID);
 	IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw);
+
 	spin_unlock_bh(&fcoe->lock);
 
 	return 1;
@@ -309,6 +320,47 @@ out_noddp_unmap:
 }
 
 /**
+ * ixgbe_fcoe_ddp_get - called to set up ddp context in initiator mode
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ */
+int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid,
+		       struct scatterlist *sgl, unsigned int sgc)
+{
+	return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
+}
+
+/**
+ * ixgbe_fcoe_ddp_target - called to set up ddp context in target mode
+ * @netdev: the corresponding net_device
+ * @xid: the exchange id requesting ddp
+ * @sgl: the scatter-gather list for this request
+ * @sgc: the number of scatter-gather items
+ *
+ * This is the implementation of net_device_ops.ndo_fcoe_ddp_target
+ * and is expected to be called from ULD, e.g., FCP layer of libfc
+ * to set up ddp for the corresponding xid of the given sglist for
+ * the corresponding I/O. The DDP in target mode is a write I/O request
+ * from the initiator.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ */
+int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+			    struct scatterlist *sgl, unsigned int sgc)
+{
+	return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
+}
+
+/**
  * ixgbe_fcoe_ddp - check ddp status and mark it done
  * @adapter: ixgbe adapter
  * @rx_desc: advanced rx descriptor
@@ -331,6 +383,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
 	struct ixgbe_fcoe *fcoe;
 	struct ixgbe_fcoe_ddp *ddp;
 	struct fc_frame_header *fh;
+	struct fcoe_crc_eof *crc;
 
 	if (!ixgbe_rx_is_fcoe(rx_desc))
 		goto ddp_out;
@@ -384,7 +437,18 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter,
 		else if (ddp->len)
 			rc = ddp->len;
 	}
-
+	/* In target mode, check the last data frame of the sequence.
+	 * For DDP in target mode, data is already DDPed but the header
+	 * indication of the last data frame ould allow is to tell if we
+	 * got all the data and the ULP can send FCP_RSP back, as this is
+	 * not a full fcoe frame, we fill the trailer here so it won't be
+	 * dropped by the ULP stack.
+	 */
+	if ((fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA) &&
+	    (fctl & FC_FC_END_SEQ)) {
+		crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
+		crc->fcoe_eof = FC_EOF_T;
+	}
 ddp_out:
 	return rc;
 }
@@ -749,21 +813,6 @@ out_disable:
 
 #ifdef CONFIG_IXGBE_DCB
 /**
- * ixgbe_fcoe_getapp - retrieves current user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- *
- * Finds out the corresponding user priority bitmap from the current
- * traffic class that FCoE belongs to. Returns 0 as the invalid user
- * priority bitmap to indicate an error.
- *
- * Returns : 802.1p user priority bitmap for FCoE
- */
-u8 ixgbe_fcoe_getapp(struct ixgbe_adapter *adapter)
-{
-	return 1 << adapter->fcoe.up;
-}
-
-/**
  * ixgbe_fcoe_setapp - sets the user priority bitmap for FCoE
  * @adapter : ixgbe adapter
  * @up : 802.1p user priority bitmap
@@ -840,5 +889,3 @@ int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type)
 	}
 	return rc;
 }
-
-
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h
index 65cc8fb..5a650a4 100644
--- a/drivers/net/ixgbe/ixgbe_fcoe.h
+++ b/drivers/net/ixgbe/ixgbe_fcoe.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -52,6 +52,9 @@
 /* fcerr */
 #define IXGBE_FCERR_BADCRC       0x00100000
 
+/* FCoE DDP for target mode */
+#define __IXGBE_FCOE_TARGET	1
+
 struct ixgbe_fcoe_ddp {
 	int len;
 	u32 err;
@@ -66,6 +69,7 @@ struct ixgbe_fcoe {
 	u8 tc;
 	u8 up;
 #endif
+	unsigned long mode;
 	atomic_t refcnt;
 	spinlock_t lock;
 	struct pci_pool *pool;
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 30f9ccf..f17e4a7 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -54,7 +54,8 @@ static const char ixgbe_driver_string[] =
 
 #define DRV_VERSION "3.2.9-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
-static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
+static const char ixgbe_copyright[] =
+				"Copyright (c) 1999-2011 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
 	[board_82598] = &ixgbe_82598_info,
@@ -648,10 +649,10 @@ void ixgbe_unmap_and_free_tx_resource(struct ixgbe_ring *tx_ring,
  *
  * Returns : a tc index for use in range 0-7, or 0-3
  */
-u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
+static u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
 {
 	int tc = -1;
-	int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+	int dcb_i = netdev_get_num_tc(adapter->netdev);
 
 	/* if DCB is not enabled the queues have no TC */
 	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
@@ -2597,6 +2598,11 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
 
 		i--;
 		for (; i >= 0; i--) {
+			/* free only the irqs that were actually requested */
+			if (!adapter->q_vector[i]->rxr_count &&
+			    !adapter->q_vector[i]->txr_count)
+				continue;
+
 			free_irq(adapter->msix_entries[i].vector,
 				 adapter->q_vector[i]);
 		}
@@ -2886,17 +2892,20 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
 					);
 
 	switch (mask) {
+#ifdef CONFIG_IXGBE_DCB
+	case (IXGBE_FLAG_DCB_ENABLED | IXGBE_FLAG_RSS_ENABLED):
+		mrqc = IXGBE_MRQC_RTRSS8TCEN;
+		break;
+	case (IXGBE_FLAG_DCB_ENABLED):
+		mrqc = IXGBE_MRQC_RT8TCEN;
+		break;
+#endif /* CONFIG_IXGBE_DCB */
 	case (IXGBE_FLAG_RSS_ENABLED):
 		mrqc = IXGBE_MRQC_RSSEN;
 		break;
 	case (IXGBE_FLAG_SRIOV_ENABLED):
 		mrqc = IXGBE_MRQC_VMDQEN;
 		break;
-#ifdef CONFIG_IXGBE_DCB
-	case (IXGBE_FLAG_DCB_ENABLED):
-		mrqc = IXGBE_MRQC_RT8TCEN;
-		break;
-#endif /* CONFIG_IXGBE_DCB */
 	default:
 		break;
 	}
@@ -3077,6 +3086,14 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
 	ixgbe_configure_srrctl(adapter, ring);
 	ixgbe_configure_rscctl(adapter, ring);
 
+	/* If operating in IOV mode set RLPML for X540 */
+	if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
+	    hw->mac.type == ixgbe_mac_X540) {
+		rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
+		rxdctl |= ((ring->netdev->mtu + ETH_HLEN +
+			    ETH_FCS_LEN + VLAN_HLEN) | IXGBE_RXDCTL_RLPML_EN);
+	}
+
 	if (hw->mac.type == ixgbe_mac_82598EB) {
 		/*
 		 * enable cache line friendly hardware writes:
@@ -3641,15 +3658,6 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 	if (hw->mac.type == ixgbe_mac_82598EB)
 		netif_set_gso_max_size(adapter->netdev, 32768);
 
-#ifdef CONFIG_FCOE
-	if (adapter->netdev->features & NETIF_F_FCOE_MTU)
-		max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
-#endif
-
-	ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
-					DCB_TX_CONFIG);
-	ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
-					DCB_RX_CONFIG);
 
 	/* Enable VLAN tag insert/strip */
 	adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
@@ -3657,7 +3665,43 @@ static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
 	hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
 
 	/* reconfigure the hardware */
-	ixgbe_dcb_hw_config(hw, &adapter->dcb_cfg);
+	if (adapter->dcbx_cap & (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE)) {
+#ifdef CONFIG_FCOE
+		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
+#endif
+		ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
+						DCB_TX_CONFIG);
+		ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
+						DCB_RX_CONFIG);
+		ixgbe_dcb_hw_config(hw, &adapter->dcb_cfg);
+	} else {
+		struct net_device *dev = adapter->netdev;
+
+		if (adapter->ixgbe_ieee_ets)
+			dev->dcbnl_ops->ieee_setets(dev,
+						    adapter->ixgbe_ieee_ets);
+		if (adapter->ixgbe_ieee_pfc)
+			dev->dcbnl_ops->ieee_setpfc(dev,
+						    adapter->ixgbe_ieee_pfc);
+	}
+
+	/* Enable RSS Hash per TC */
+	if (hw->mac.type != ixgbe_mac_82598EB) {
+		int i;
+		u32 reg = 0;
+
+		for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+			u8 msb = 0;
+			u8 cnt = adapter->netdev->tc_to_txq[i].count;
+
+			while (cnt >>= 1)
+				msb++;
+
+			reg |= msb << IXGBE_RQTC_SHIFT_TC(i);
+		}
+		IXGBE_WRITE_REG(hw, IXGBE_RQTC, reg);
+	}
 }
 
 #endif
@@ -3761,7 +3805,8 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
 	if (ret)
 		goto link_cfg_out;
 
-	if (hw->mac.ops.get_link_capabilities)
+	autoneg = hw->phy.autoneg_advertised;
+	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
 		ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
 							&negotiation);
 	if (ret)
@@ -3876,7 +3921,7 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
 	 * If we're not hot-pluggable SFP+, we just need to configure link
 	 * and bring it up.
 	 */
-	if (hw->phy.type == ixgbe_phy_unknown)
+	if (hw->phy.type == ixgbe_phy_none)
 		schedule_work(&adapter->sfp_config_module_task);
 
 	/* enable transmits */
@@ -4243,24 +4288,6 @@ static void ixgbe_reset_task(struct work_struct *work)
 	ixgbe_reinit_locked(adapter);
 }
 
-#ifdef CONFIG_IXGBE_DCB
-static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
-{
-	bool ret = false;
-	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB];
-
-	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
-		return ret;
-
-	f->mask = 0x7 << 3;
-	adapter->num_rx_queues = f->indices;
-	adapter->num_tx_queues = f->indices;
-	ret = true;
-
-	return ret;
-}
-#endif
-
 /**
  * ixgbe_set_rss_queues: Allocate queues for RSS
  * @adapter: board private structure to initialize
@@ -4331,19 +4358,26 @@ static inline bool ixgbe_set_fdir_queues(struct ixgbe_adapter *adapter)
  **/
 static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
 {
-	bool ret = false;
 	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE];
 
-	f->indices = min((int)num_online_cpus(), f->indices);
-	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
-		adapter->num_rx_queues = 1;
-		adapter->num_tx_queues = 1;
+	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
+		return false;
+
+	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 #ifdef CONFIG_IXGBE_DCB
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			e_info(probe, "FCoE enabled with DCB\n");
-			ixgbe_set_dcb_queues(adapter);
-		}
+		int tc;
+		struct net_device *dev = adapter->netdev;
+
+		tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
+		f->indices = dev->tc_to_txq[tc].count;
+		f->mask = dev->tc_to_txq[tc].offset;
 #endif
+	} else {
+		f->indices = min((int)num_online_cpus(), f->indices);
+
+		adapter->num_rx_queues = 1;
+		adapter->num_tx_queues = 1;
+
 		if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 			e_info(probe, "FCoE enabled with RSS\n");
 			if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
@@ -4356,14 +4390,45 @@ static inline bool ixgbe_set_fcoe_queues(struct ixgbe_adapter *adapter)
 		f->mask = adapter->num_rx_queues;
 		adapter->num_rx_queues += f->indices;
 		adapter->num_tx_queues += f->indices;
+	}
 
-		ret = true;
+	return true;
+}
+#endif /* IXGBE_FCOE */
+
+#ifdef CONFIG_IXGBE_DCB
+static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter)
+{
+	bool ret = false;
+	struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_DCB];
+	int i, q;
+
+	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return ret;
+
+	f->indices = 0;
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		q = min((int)num_online_cpus(), MAX_TRAFFIC_CLASS);
+		f->indices += q;
 	}
 
+	f->mask = 0x7 << 3;
+	adapter->num_rx_queues = f->indices;
+	adapter->num_tx_queues = f->indices;
+	ret = true;
+
+#ifdef IXGBE_FCOE
+	/* FCoE enabled queues require special configuration done through
+	 * configure_fcoe() and others. Here we map FCoE indices onto the
+	 * DCB queue pairs allowing FCoE to own configuration later.
+	 */
+	ixgbe_set_fcoe_queues(adapter);
+#endif
+
 	return ret;
 }
+#endif
 
-#endif /* IXGBE_FCOE */
 /**
  * ixgbe_set_sriov_queues: Allocate queues for IOV use
  * @adapter: board private structure to initialize
@@ -4399,16 +4464,16 @@ static int ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
 	if (ixgbe_set_sriov_queues(adapter))
 		goto done;
 
-#ifdef IXGBE_FCOE
-	if (ixgbe_set_fcoe_queues(adapter))
-		goto done;
-
-#endif /* IXGBE_FCOE */
 #ifdef CONFIG_IXGBE_DCB
 	if (ixgbe_set_dcb_queues(adapter))
 		goto done;
 
 #endif
+#ifdef IXGBE_FCOE
+	if (ixgbe_set_fcoe_queues(adapter))
+		goto done;
+
+#endif /* IXGBE_FCOE */
 	if (ixgbe_set_fdir_queues(adapter))
 		goto done;
 
@@ -4500,6 +4565,110 @@ static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
 }
 
 #ifdef CONFIG_IXGBE_DCB
+
+/* ixgbe_get_first_reg_idx - Return first register index associated with ring */
+void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
+			     unsigned int *tx, unsigned int *rx)
+{
+	struct net_device *dev = adapter->netdev;
+	struct ixgbe_hw *hw = &adapter->hw;
+	u8 num_tcs = netdev_get_num_tc(dev);
+
+	*tx = 0;
+	*rx = 0;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		*tx = tc << 3;
+		*rx = tc << 2;
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		if (num_tcs == 8) {
+			if (tc < 3) {
+				*tx = tc << 5;
+				*rx = tc << 4;
+			} else if (tc <  5) {
+				*tx = ((tc + 2) << 4);
+				*rx = tc << 4;
+			} else if (tc < num_tcs) {
+				*tx = ((tc + 8) << 3);
+				*rx = tc << 4;
+			}
+		} else if (num_tcs == 4) {
+			*rx =  tc << 5;
+			switch (tc) {
+			case 0:
+				*tx =  0;
+				break;
+			case 1:
+				*tx = 64;
+				break;
+			case 2:
+				*tx = 96;
+				break;
+			case 3:
+				*tx = 112;
+				break;
+			default:
+				break;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+#define IXGBE_MAX_Q_PER_TC	(IXGBE_MAX_DCB_INDICES / MAX_TRAFFIC_CLASS)
+
+/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+int ixgbe_setup_tc(struct net_device *dev, u8 tc)
+{
+	int i;
+	unsigned int q, offset = 0;
+
+	if (!tc) {
+		netdev_reset_tc(dev);
+	} else {
+		struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+		/* Hardware supports up to 8 traffic classes */
+		if (tc > MAX_TRAFFIC_CLASS || netdev_set_num_tc(dev, tc))
+			return -EINVAL;
+
+		/* Partition Tx queues evenly amongst traffic classes */
+		for (i = 0; i < tc; i++) {
+			q = min((int)num_online_cpus(), IXGBE_MAX_Q_PER_TC);
+			netdev_set_prio_tc_map(dev, i, i);
+			netdev_set_tc_queue(dev, i, q, offset);
+			offset += q;
+		}
+
+		/* This enables multiple traffic class support in the hardware
+		 * which defaults to strict priority transmission by default.
+		 * If traffic classes are already enabled perhaps through DCB
+		 * code path then existing configuration will be used.
+		 */
+		if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+		    dev->dcbnl_ops && dev->dcbnl_ops->setdcbx) {
+			struct ieee_ets ets = {
+					.prio_tc = {0, 1, 2, 3, 4, 5, 6, 7},
+					      };
+			u8 mode = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+
+			dev->dcbnl_ops->setdcbx(dev, mode);
+			dev->dcbnl_ops->ieee_setets(dev, &ets);
+		}
+	}
+	return 0;
+}
+
 /**
  * ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB
  * @adapter: board private structure to initialize
@@ -4509,72 +4678,27 @@ static inline bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
  **/
 static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
 {
-	int i;
-	bool ret = false;
-	int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+	struct net_device *dev = adapter->netdev;
+	int i, j, k;
+	u8 num_tcs = netdev_get_num_tc(dev);
 
 	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
 		return false;
 
-	/* the number of queues is assumed to be symmetric */
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82598EB:
-		for (i = 0; i < dcb_i; i++) {
-			adapter->rx_ring[i]->reg_idx = i << 3;
-			adapter->tx_ring[i]->reg_idx = i << 2;
-		}
-		ret = true;
-		break;
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		if (dcb_i == 8) {
-			/*
-			 * Tx TC0 starts at: descriptor queue 0
-			 * Tx TC1 starts at: descriptor queue 32
-			 * Tx TC2 starts at: descriptor queue 64
-			 * Tx TC3 starts at: descriptor queue 80
-			 * Tx TC4 starts at: descriptor queue 96
-			 * Tx TC5 starts at: descriptor queue 104
-			 * Tx TC6 starts at: descriptor queue 112
-			 * Tx TC7 starts at: descriptor queue 120
-			 *
-			 * Rx TC0-TC7 are offset by 16 queues each
-			 */
-			for (i = 0; i < 3; i++) {
-				adapter->tx_ring[i]->reg_idx = i << 5;
-				adapter->rx_ring[i]->reg_idx = i << 4;
-			}
-			for ( ; i < 5; i++) {
-				adapter->tx_ring[i]->reg_idx = ((i + 2) << 4);
-				adapter->rx_ring[i]->reg_idx = i << 4;
-			}
-			for ( ; i < dcb_i; i++) {
-				adapter->tx_ring[i]->reg_idx = ((i + 8) << 3);
-				adapter->rx_ring[i]->reg_idx = i << 4;
-			}
-			ret = true;
-		} else if (dcb_i == 4) {
-			/*
-			 * Tx TC0 starts at: descriptor queue 0
-			 * Tx TC1 starts at: descriptor queue 64
-			 * Tx TC2 starts at: descriptor queue 96
-			 * Tx TC3 starts at: descriptor queue 112
-			 *
-			 * Rx TC0-TC3 are offset by 32 queues each
-			 */
-			adapter->tx_ring[0]->reg_idx = 0;
-			adapter->tx_ring[1]->reg_idx = 64;
-			adapter->tx_ring[2]->reg_idx = 96;
-			adapter->tx_ring[3]->reg_idx = 112;
-			for (i = 0 ; i < dcb_i; i++)
-				adapter->rx_ring[i]->reg_idx = i << 5;
-			ret = true;
+	for (i = 0, k = 0; i < num_tcs; i++) {
+		unsigned int tx_s, rx_s;
+		u16 count = dev->tc_to_txq[i].count;
+
+		ixgbe_get_first_reg_idx(adapter, i, &tx_s, &rx_s);
+		for (j = 0; j < count; j++, k++) {
+			adapter->tx_ring[k]->reg_idx = tx_s + j;
+			adapter->rx_ring[k]->reg_idx = rx_s + j;
+			adapter->tx_ring[k]->dcb_tc = i;
+			adapter->rx_ring[k]->dcb_tc = i;
 		}
-		break;
-	default:
-		break;
 	}
-	return ret;
+
+	return true;
 }
 #endif
 
@@ -4620,33 +4744,6 @@ static inline bool ixgbe_cache_ring_fcoe(struct ixgbe_adapter *adapter)
 	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
 		return false;
 
-#ifdef CONFIG_IXGBE_DCB
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-
-		ixgbe_cache_ring_dcb(adapter);
-		/* find out queues in TC for FCoE */
-		fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1;
-		fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1;
-		/*
-		 * In 82599, the number of Tx queues for each traffic
-		 * class for both 8-TC and 4-TC modes are:
-		 * TCs  : TC0 TC1 TC2 TC3 TC4 TC5 TC6 TC7
-		 * 8 TCs:  32  32  16  16   8   8   8   8
-		 * 4 TCs:  64  64  32  32
-		 * We have max 8 queues for FCoE, where 8 the is
-		 * FCoE redirection table size. If TC for FCoE is
-		 * less than or equal to TC3, we have enough queues
-		 * to add max of 8 queues for FCoE, so we start FCoE
-		 * Tx queue from the next one, i.e., reg_idx + 1.
-		 * If TC for FCoE is above TC3, implying 8 TC mode,
-		 * and we need 8 for FCoE, we have to take all queues
-		 * in that traffic class for FCoE.
-		 */
-		if ((f->indices == IXGBE_FCRETA_SIZE) && (fcoe->tc > 3))
-			fcoe_tx_i--;
-	}
-#endif /* CONFIG_IXGBE_DCB */
 	if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 		if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
 		    (adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE))
@@ -4703,16 +4800,16 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
 	if (ixgbe_cache_ring_sriov(adapter))
 		return;
 
+#ifdef CONFIG_IXGBE_DCB
+	if (ixgbe_cache_ring_dcb(adapter))
+		return;
+#endif
+
 #ifdef IXGBE_FCOE
 	if (ixgbe_cache_ring_fcoe(adapter))
 		return;
-
 #endif /* IXGBE_FCOE */
-#ifdef CONFIG_IXGBE_DCB
-	if (ixgbe_cache_ring_dcb(adapter))
-		return;
 
-#endif
 	if (ixgbe_cache_ring_fdir(adapter))
 		return;
 
@@ -5174,10 +5271,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 	adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
 	adapter->dcb_cfg.rx_pba_cfg = pba_equal;
 	adapter->dcb_cfg.pfc_mode_enable = false;
-	adapter->dcb_cfg.round_robin_enable = false;
 	adapter->dcb_set_bitmap = 0x00;
+	adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
 	ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
-			   adapter->ring_feature[RING_F_DCB].indices);
+			   MAX_TRAFFIC_CLASS);
 
 #endif
 
@@ -5442,8 +5539,14 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
 	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
-		return -EINVAL;
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED &&
+	    hw->mac.type != ixgbe_mac_X540) {
+		if ((new_mtu < 68) || (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
+			return -EINVAL;
+	} else {
+		if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
+			return -EINVAL;
+	}
 
 	e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
 	/* must set new MTU before calling down or up */
@@ -5611,6 +5714,10 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
 	}
 
 	ixgbe_clear_interrupt_scheme(adapter);
+#ifdef CONFIG_DCB
+	kfree(adapter->ixgbe_ieee_pfc);
+	kfree(adapter->ixgbe_ieee_ets);
+#endif
 
 #ifdef CONFIG_PM
 	retval = pci_save_state(pdev);
@@ -6101,12 +6208,16 @@ static void ixgbe_watchdog_task(struct work_struct *work)
 			       (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
 			       "10 Gbps" :
 			       (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
-			       "1 Gbps" : "unknown speed")),
+			       "1 Gbps" :
+			       (link_speed == IXGBE_LINK_SPEED_100_FULL ?
+			       "100 Mbps" :
+			       "unknown speed"))),
 			       ((flow_rx && flow_tx) ? "RX/TX" :
 			       (flow_rx ? "RX" :
 			       (flow_tx ? "TX" : "None"))));
 
 			netif_carrier_on(netdev);
+			ixgbe_check_vf_rate_limit(adapter);
 		} else {
 			/* Force detection of hung controller */
 			for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -6636,18 +6747,12 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 
 	protocol = vlan_get_protocol(skb);
 
-	if ((protocol == htons(ETH_P_FCOE)) ||
-	    (protocol == htons(ETH_P_FIP))) {
-		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
-			txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1);
-			txq += adapter->ring_feature[RING_F_FCOE].mask;
-			return txq;
-#ifdef CONFIG_IXGBE_DCB
-		} else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			txq = adapter->fcoe.up;
-			return txq;
-#endif
-		}
+	if (((protocol == htons(ETH_P_FCOE)) ||
+	    (protocol == htons(ETH_P_FIP))) &&
+	    (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
+		txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1);
+		txq += adapter->ring_feature[RING_F_FCOE].mask;
+		return txq;
 	}
 #endif
 
@@ -6657,15 +6762,6 @@ static u16 ixgbe_select_queue(struct net_device *dev, struct sk_buff *skb)
 		return txq;
 	}
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		if (skb->priority == TC_PRIO_CONTROL)
-			txq = adapter->ring_feature[RING_F_DCB].indices-1;
-		else
-			txq = (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK)
-			       >> 13;
-		return txq;
-	}
-
 	return skb_tx_hash(dev, skb);
 }
 
@@ -6687,13 +6783,13 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 		tx_flags |= vlan_tx_tag_get(skb);
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 			tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
-			tx_flags |= ((skb->queue_mapping & 0x7) << 13);
+			tx_flags |= tx_ring->dcb_tc << 13;
 		}
 		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 	} else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED &&
 		   skb->priority != TC_PRIO_CONTROL) {
-		tx_flags |= ((skb->queue_mapping & 0x7) << 13);
+		tx_flags |= tx_ring->dcb_tc << 13;
 		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 	}
@@ -6702,20 +6798,8 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 	/* for FCoE with DCB, we force the priority to what
 	 * was specified by the switch */
 	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
-	    (protocol == htons(ETH_P_FCOE) ||
-	     protocol == htons(ETH_P_FIP))) {
-#ifdef CONFIG_IXGBE_DCB
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK
-				      << IXGBE_TX_FLAGS_VLAN_SHIFT);
-			tx_flags |= ((adapter->fcoe.up << 13)
-				      << IXGBE_TX_FLAGS_VLAN_SHIFT);
-		}
-#endif
-		/* flag for FCoE offloads */
-		if (protocol == htons(ETH_P_FCOE))
-			tx_flags |= IXGBE_TX_FLAGS_FCOE;
-	}
+	    (protocol == htons(ETH_P_FCOE)))
+		tx_flags |= IXGBE_TX_FLAGS_FCOE;
 #endif
 
 	/* four things can cause us to need a context descriptor */
@@ -6988,11 +7072,15 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 	.ndo_set_vf_tx_rate	= ixgbe_ndo_set_vf_bw,
 	.ndo_get_vf_config	= ixgbe_ndo_get_vf_config,
 	.ndo_get_stats64	= ixgbe_get_stats64,
+#ifdef CONFIG_IXGBE_DCB
+	.ndo_setup_tc		= ixgbe_setup_tc,
+#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ixgbe_netpoll,
 #endif
 #ifdef IXGBE_FCOE
 	.ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get,
+	.ndo_fcoe_ddp_target = ixgbe_fcoe_ddp_target,
 	.ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put,
 	.ndo_fcoe_enable = ixgbe_fcoe_enable,
 	.ndo_fcoe_disable = ixgbe_fcoe_disable,
@@ -7128,8 +7216,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 	else
 		indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES);
 
+#if defined(CONFIG_DCB)
 	indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES);
-#ifdef IXGBE_FCOE
+#elif defined(IXGBE_FCOE)
 	indices += min_t(unsigned int, num_possible_cpus(),
 			 IXGBE_MAX_FCOE_INDICES);
 #endif
@@ -7285,8 +7374,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 		adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED |
 				    IXGBE_FLAG_DCB_ENABLED);
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
 
 #ifdef CONFIG_IXGBE_DCB
 	netdev->dcbnl_ops = &dcbnl_ops;
@@ -7706,16 +7793,6 @@ static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
 
 #endif /* CONFIG_IXGBE_DCA */
 
-/**
- * ixgbe_get_hw_dev return device
- * used by hardware layer to print debugging information
- **/
-struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw)
-{
-	struct ixgbe_adapter *adapter = hw->back;
-	return adapter->netdev;
-}
-
 module_exit(ixgbe_exit_module);
 
 /* ixgbe_main.c */
diff --git a/drivers/net/ixgbe/ixgbe_mbx.c b/drivers/net/ixgbe/ixgbe_mbx.c
index ea82c5a..1ff0eef 100644
--- a/drivers/net/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ixgbe/ixgbe_mbx.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -154,9 +154,6 @@ static s32 ixgbe_poll_for_msg(struct ixgbe_hw *hw, u16 mbx_id)
 		udelay(mbx->usec_delay);
 	}
 
-	/* if we failed, all future posted messages fail until reset */
-	if (!countdown)
-		mbx->timeout = 0;
 out:
 	return countdown ? 0 : IXGBE_ERR_MBX;
 }
@@ -183,9 +180,6 @@ static s32 ixgbe_poll_for_ack(struct ixgbe_hw *hw, u16 mbx_id)
 		udelay(mbx->usec_delay);
 	}
 
-	/* if we failed, all future posted messages fail until reset */
-	if (!countdown)
-		mbx->timeout = 0;
 out:
 	return countdown ? 0 : IXGBE_ERR_MBX;
 }
@@ -437,6 +431,7 @@ out_no_read:
 	return ret_val;
 }
 
+#ifdef CONFIG_PCI_IOV
 /**
  *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
  *  @hw: pointer to the HW structure
@@ -447,24 +442,22 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
-	switch (hw->mac.type) {
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		mbx->timeout = 0;
-		mbx->usec_delay = 0;
+	if (hw->mac.type != ixgbe_mac_82599EB &&
+	    hw->mac.type != ixgbe_mac_X540)
+		return;
 
-		mbx->size = IXGBE_VFMAILBOX_SIZE;
+	mbx->timeout = 0;
+	mbx->usec_delay = 0;
 
-		mbx->stats.msgs_tx = 0;
-		mbx->stats.msgs_rx = 0;
-		mbx->stats.reqs = 0;
-		mbx->stats.acks = 0;
-		mbx->stats.rsts = 0;
-		break;
-	default:
-		break;
-	}
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 0;
+
+	mbx->size = IXGBE_VFMAILBOX_SIZE;
 }
+#endif /* CONFIG_PCI_IOV */
 
 struct ixgbe_mbx_operations mbx_ops_generic = {
 	.read                   = ixgbe_read_mbx_pf,
diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h
index 3df9b15..fe6ea81 100644
--- a/drivers/net/ixgbe/ixgbe_mbx.h
+++ b/drivers/net/ixgbe/ixgbe_mbx.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -86,7 +86,9 @@ s32 ixgbe_write_mbx(struct ixgbe_hw *, u32 *, u16, u16);
 s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16);
 s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16);
 s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16);
+#ifdef CONFIG_PCI_IOV
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
+#endif /* CONFIG_PCI_IOV */
 
 extern struct ixgbe_mbx_operations mbx_ops_generic;
 
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 8f7123e..f72f705 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -57,6 +57,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 {
 	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
 	u32 phy_addr;
+	u16 ext_ability = 0;
 
 	if (hw->phy.type == ixgbe_phy_unknown) {
 		for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
@@ -65,12 +66,29 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
 				ixgbe_get_phy_id(hw);
 				hw->phy.type =
 				        ixgbe_get_phy_type_from_id(hw->phy.id);
+
+				if (hw->phy.type == ixgbe_phy_unknown) {
+					hw->phy.ops.read_reg(hw,
+							     MDIO_PMA_EXTABLE,
+							     MDIO_MMD_PMAPMD,
+							     &ext_ability);
+					if (ext_ability &
+					    (MDIO_PMA_EXTABLE_10GBT |
+					     MDIO_PMA_EXTABLE_1000BT))
+						hw->phy.type =
+							 ixgbe_phy_cu_unknown;
+					else
+						hw->phy.type =
+							 ixgbe_phy_generic;
+				}
+
 				status = 0;
 				break;
 			}
 		}
 		/* clear value if nothing found */
-		hw->phy.mdio.prtad = 0;
+		if (status != 0)
+			hw->phy.mdio.prtad = 0;
 	} else {
 		status = 0;
 	}
@@ -138,17 +156,51 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
  **/
 s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
 {
+	u32 i;
+	u16 ctrl = 0;
+	s32 status = 0;
+
+	if (hw->phy.type == ixgbe_phy_unknown)
+		status = ixgbe_identify_phy_generic(hw);
+
+	if (status != 0 || hw->phy.type == ixgbe_phy_none)
+		goto out;
+
 	/* Don't reset PHY if it's shut down due to overtemp. */
 	if (!hw->phy.reset_if_overtemp &&
 	    (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
-		return 0;
+		goto out;
 
 	/*
 	 * Perform soft PHY reset to the PHY_XS.
 	 * This will cause a soft reset to the PHY
 	 */
-	return hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
-				     MDIO_CTRL1_RESET);
+	hw->phy.ops.write_reg(hw, MDIO_CTRL1,
+			      MDIO_MMD_PHYXS,
+			      MDIO_CTRL1_RESET);
+
+	/*
+	 * Poll for reset bit to self-clear indicating reset is complete.
+	 * Some PHYs could take up to 3 seconds to complete and need about
+	 * 1.7 usec delay after the reset is complete.
+	 */
+	for (i = 0; i < 30; i++) {
+		msleep(100);
+		hw->phy.ops.read_reg(hw, MDIO_CTRL1,
+				     MDIO_MMD_PHYXS, &ctrl);
+		if (!(ctrl & MDIO_CTRL1_RESET)) {
+			udelay(2);
+			break;
+		}
+	}
+
+	if (ctrl & MDIO_CTRL1_RESET) {
+		status = IXGBE_ERR_RESET_FAILED;
+		hw_dbg(hw, "PHY reset polling failed to complete.\n");
+	}
+
+out:
+	return status;
 }
 
 /**
@@ -171,7 +223,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 	else
 		gssr = IXGBE_GSSR_PHY0_SM;
 
-	if (ixgbe_acquire_swfw_sync(hw, gssr) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == 0) {
@@ -243,7 +295,7 @@ s32 ixgbe_read_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 			}
 		}
 
-		ixgbe_release_swfw_sync(hw, gssr);
+		hw->mac.ops.release_swfw_sync(hw, gssr);
 	}
 
 	return status;
@@ -269,7 +321,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 	else
 		gssr = IXGBE_GSSR_PHY0_SM;
 
-	if (ixgbe_acquire_swfw_sync(hw, gssr) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == 0) {
@@ -336,7 +388,7 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
 			}
 		}
 
-		ixgbe_release_swfw_sync(hw, gssr);
+		hw->mac.ops.release_swfw_sync(hw, gssr);
 	}
 
 	return status;
@@ -350,49 +402,89 @@ s32 ixgbe_write_phy_reg_generic(struct ixgbe_hw *hw, u32 reg_addr,
  **/
 s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_NOT_IMPLEMENTED;
+	s32 status = 0;
 	u32 time_out;
 	u32 max_time_out = 10;
-	u16 autoneg_reg;
+	u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+	bool autoneg = false;
+	ixgbe_link_speed speed;
 
-	/*
-	 * Set advertisement settings in PHY based on autoneg_advertised
-	 * settings. If autoneg_advertised = 0, then advertise default values
-	 * tnx devices cannot be "forced" to a autoneg 10G and fail.  But can
-	 * for a 1G.
-	 */
-	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg);
+	ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
+
+	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+		/* Set or unset auto-negotiation 10G advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
 
-	if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
 		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
-	else
-		autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+			autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
+
+		hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+		/* Set or unset auto-negotiation 1G advertisement */
+		hw->phy.ops.read_reg(hw,
+				     IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+			autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
+
+		hw->phy.ops.write_reg(hw,
+				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_100_FULL) {
+		/* Set or unset auto-negotiation 100M advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
 
-	hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);
+		autoneg_reg &= ~ADVERTISE_100FULL;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
+			autoneg_reg |= ADVERTISE_100FULL;
+
+		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
 
 	/* Restart PHY autonegotiation and wait for completion */
-	hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, &autoneg_reg);
+	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
+			     MDIO_MMD_AN, &autoneg_reg);
 
 	autoneg_reg |= MDIO_AN_CTRL1_RESTART;
 
-	hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, autoneg_reg);
+	hw->phy.ops.write_reg(hw, MDIO_CTRL1,
+			      MDIO_MMD_AN, autoneg_reg);
 
 	/* Wait for autonegotiation to finish */
 	for (time_out = 0; time_out < max_time_out; time_out++) {
 		udelay(10);
 		/* Restart PHY autonegotiation and wait for completion */
-		status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN,
-		                              &autoneg_reg);
+		status = hw->phy.ops.read_reg(hw, MDIO_STAT1,
+					      MDIO_MMD_AN,
+					      &autoneg_reg);
 
 		autoneg_reg &= MDIO_AN_STAT1_COMPLETE;
 		if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) {
-			status = 0;
 			break;
 		}
 	}
 
-	if (time_out == max_time_out)
+	if (time_out == max_time_out) {
 		status = IXGBE_ERR_LINK_SETUP;
+		hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out");
+	}
 
 	return status;
 }
@@ -421,6 +513,9 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
+	if (speed & IXGBE_LINK_SPEED_100_FULL)
+		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
+
 	/* Setup link based on the new speed settings */
 	hw->phy.ops.setup_link(hw);
 
@@ -461,6 +556,180 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
 }
 
 /**
+ *  ixgbe_check_phy_link_tnx - Determine link and speed status
+ *  @hw: pointer to hardware structure
+ *
+ *  Reads the VS1 register to determine if link is up and the current speed for
+ *  the PHY.
+ **/
+s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+			     bool *link_up)
+{
+	s32 status = 0;
+	u32 time_out;
+	u32 max_time_out = 10;
+	u16 phy_link = 0;
+	u16 phy_speed = 0;
+	u16 phy_data = 0;
+
+	/* Initialize speed and link to default case */
+	*link_up = false;
+	*speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+	/*
+	 * Check current speed and link status of the PHY register.
+	 * This is a vendor specific register and may have to
+	 * be changed for other copper PHYs.
+	 */
+	for (time_out = 0; time_out < max_time_out; time_out++) {
+		udelay(10);
+		status = hw->phy.ops.read_reg(hw,
+					      MDIO_STAT1,
+					      MDIO_MMD_VEND1,
+					      &phy_data);
+		phy_link = phy_data &
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
+		phy_speed = phy_data &
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
+		if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
+			*link_up = true;
+			if (phy_speed ==
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
+				*speed = IXGBE_LINK_SPEED_1GB_FULL;
+			break;
+		}
+	}
+
+	return status;
+}
+
+/**
+ *	ixgbe_setup_phy_link_tnx - Set and restart autoneg
+ *	@hw: pointer to hardware structure
+ *
+ *	Restart autonegotiation and PHY and waits for completion.
+ **/
+s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
+{
+	s32 status = 0;
+	u32 time_out;
+	u32 max_time_out = 10;
+	u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+	bool autoneg = false;
+	ixgbe_link_speed speed;
+
+	ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
+
+	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+		/* Set or unset auto-negotiation 10G advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+			autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
+
+		hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+		/* Set or unset auto-negotiation 1G advertisement */
+		hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+			autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+
+		hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_100_FULL) {
+		/* Set or unset auto-negotiation 100M advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~ADVERTISE_100FULL;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
+			autoneg_reg |= ADVERTISE_100FULL;
+
+		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	/* Restart PHY autonegotiation and wait for completion */
+	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
+			     MDIO_MMD_AN, &autoneg_reg);
+
+	autoneg_reg |= MDIO_AN_CTRL1_RESTART;
+
+	hw->phy.ops.write_reg(hw, MDIO_CTRL1,
+			      MDIO_MMD_AN, autoneg_reg);
+
+	/* Wait for autonegotiation to finish */
+	for (time_out = 0; time_out < max_time_out; time_out++) {
+		udelay(10);
+		/* Restart PHY autonegotiation and wait for completion */
+		status = hw->phy.ops.read_reg(hw, MDIO_STAT1,
+					      MDIO_MMD_AN,
+					      &autoneg_reg);
+
+		autoneg_reg &= MDIO_AN_STAT1_COMPLETE;
+		if (autoneg_reg == MDIO_AN_STAT1_COMPLETE)
+			break;
+	}
+
+	if (time_out == max_time_out) {
+		status = IXGBE_ERR_LINK_SETUP;
+		hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out");
+	}
+
+	return status;
+}
+
+/**
+ *  ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
+ *  @hw: pointer to hardware structure
+ *  @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
+				       u16 *firmware_version)
+{
+	s32 status = 0;
+
+	status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
+				      MDIO_MMD_VEND1,
+				      firmware_version);
+
+	return status;
+}
+
+/**
+ *  ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
+ *  @hw: pointer to hardware structure
+ *  @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
+					   u16 *firmware_version)
+{
+	s32 status = 0;
+
+	status = hw->phy.ops.read_reg(hw, AQ_FW_REV,
+				      MDIO_MMD_VEND1,
+				      firmware_version);
+
+	return status;
+}
+
+/**
  *  ixgbe_reset_phy_nl - Performs a PHY reset
  *  @hw: pointer to hardware structure
  **/
@@ -556,11 +825,10 @@ out:
 }
 
 /**
- *  ixgbe_identify_sfp_module_generic - Identifies SFP module and assigns
- *                                      the PHY type.
+ *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
  *  @hw: pointer to hardware structure
  *
- *  Searches for and indentifies the SFP module.  Assings appropriate PHY type.
+ *  Searches for and identifies the SFP module and assigns appropriate PHY type.
  **/
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 {
@@ -581,41 +849,62 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 		goto out;
 	}
 
-	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_IDENTIFIER,
 	                                     &identifier);
 
-	if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) {
-		status = IXGBE_ERR_SFP_NOT_PRESENT;
-		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
-		if (hw->phy.type != ixgbe_phy_nl) {
-			hw->phy.id = 0;
-			hw->phy.type = ixgbe_phy_unknown;
-		}
-		goto out;
-	}
+	if (status == IXGBE_ERR_SWFW_SYNC ||
+	    status == IXGBE_ERR_I2C ||
+	    status == IXGBE_ERR_SFP_NOT_PRESENT)
+		goto err_read_i2c_eeprom;
 
-	if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
-		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
-		                            &comp_codes_1g);
-		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
-		                            &comp_codes_10g);
-		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_CABLE_TECHNOLOGY,
-		                            &cable_tech);
-
-		/* ID Module
-		 * =========
-		 * 0    SFP_DA_CU
-		 * 1    SFP_SR
-		 * 2    SFP_LR
-		 * 3    SFP_DA_CORE0 - 82599-specific
-		 * 4    SFP_DA_CORE1 - 82599-specific
-		 * 5    SFP_SR/LR_CORE0 - 82599-specific
-		 * 6    SFP_SR/LR_CORE1 - 82599-specific
-		 * 7    SFP_act_lmt_DA_CORE0 - 82599-specific
-		 * 8    SFP_act_lmt_DA_CORE1 - 82599-specific
-		 * 9    SFP_1g_cu_CORE0 - 82599-specific
-		 * 10   SFP_1g_cu_CORE1 - 82599-specific
-		 */
+	/* LAN ID is needed for sfp_type determination */
+	hw->mac.ops.set_lan_id(hw);
+
+	if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
+		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+	} else {
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+						     IXGBE_SFF_1GBE_COMP_CODES,
+						     &comp_codes_1g);
+
+		if (status == IXGBE_ERR_SWFW_SYNC ||
+		    status == IXGBE_ERR_I2C ||
+		    status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto err_read_i2c_eeprom;
+
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+						     IXGBE_SFF_10GBE_COMP_CODES,
+						     &comp_codes_10g);
+
+		if (status == IXGBE_ERR_SWFW_SYNC ||
+		    status == IXGBE_ERR_I2C ||
+		    status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto err_read_i2c_eeprom;
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+						     IXGBE_SFF_CABLE_TECHNOLOGY,
+						     &cable_tech);
+
+		if (status == IXGBE_ERR_SWFW_SYNC ||
+		    status == IXGBE_ERR_I2C ||
+		    status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto err_read_i2c_eeprom;
+
+		 /* ID Module
+		  * =========
+		  * 0   SFP_DA_CU
+		  * 1   SFP_SR
+		  * 2   SFP_LR
+		  * 3   SFP_DA_CORE0 - 82599-specific
+		  * 4   SFP_DA_CORE1 - 82599-specific
+		  * 5   SFP_SR/LR_CORE0 - 82599-specific
+		  * 6   SFP_SR/LR_CORE1 - 82599-specific
+		  * 7   SFP_act_lmt_DA_CORE0 - 82599-specific
+		  * 8   SFP_act_lmt_DA_CORE1 - 82599-specific
+		  * 9   SFP_1g_cu_CORE0 - 82599-specific
+		  * 10  SFP_1g_cu_CORE1 - 82599-specific
+		  */
 		if (hw->mac.type == ixgbe_mac_82598EB) {
 			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 				hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
@@ -647,31 +936,27 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 						ixgbe_sfp_type_da_act_lmt_core1;
 				} else {
 					hw->phy.sfp_type =
-						ixgbe_sfp_type_unknown;
+							ixgbe_sfp_type_unknown;
 				}
-			} else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+			} else if (comp_codes_10g &
+				   (IXGBE_SFF_10GBASESR_CAPABLE |
+				    IXGBE_SFF_10GBASELR_CAPABLE)) {
 				if (hw->bus.lan_id == 0)
 					hw->phy.sfp_type =
 					              ixgbe_sfp_type_srlr_core0;
 				else
 					hw->phy.sfp_type =
 					              ixgbe_sfp_type_srlr_core1;
-			else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
-				if (hw->bus.lan_id == 0)
-					hw->phy.sfp_type =
-					              ixgbe_sfp_type_srlr_core0;
-				else
-					hw->phy.sfp_type =
-					              ixgbe_sfp_type_srlr_core1;
-			else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
+			} else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
 				if (hw->bus.lan_id == 0)
 					hw->phy.sfp_type =
 						ixgbe_sfp_type_1g_cu_core0;
 				else
 					hw->phy.sfp_type =
 						ixgbe_sfp_type_1g_cu_core1;
-			else
+			} else {
 				hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+			}
 		}
 
 		if (hw->phy.sfp_type != stored_sfp_type)
@@ -688,16 +973,33 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 		/* Determine PHY vendor */
 		if (hw->phy.type != ixgbe_phy_nl) {
 			hw->phy.id = identifier;
-			hw->phy.ops.read_i2c_eeprom(hw,
+			status = hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE0,
 			                            &oui_bytes[0]);
-			hw->phy.ops.read_i2c_eeprom(hw,
+
+			if (status == IXGBE_ERR_SWFW_SYNC ||
+			    status == IXGBE_ERR_I2C ||
+			    status == IXGBE_ERR_SFP_NOT_PRESENT)
+				goto err_read_i2c_eeprom;
+
+			status = hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE1,
 			                            &oui_bytes[1]);
-			hw->phy.ops.read_i2c_eeprom(hw,
+
+			if (status == IXGBE_ERR_SWFW_SYNC ||
+			    status == IXGBE_ERR_I2C ||
+			    status == IXGBE_ERR_SFP_NOT_PRESENT)
+				goto err_read_i2c_eeprom;
+
+			status = hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE2,
 			                            &oui_bytes[2]);
 
+			if (status == IXGBE_ERR_SWFW_SYNC ||
+			    status == IXGBE_ERR_I2C ||
+			    status == IXGBE_ERR_SFP_NOT_PRESENT)
+				goto err_read_i2c_eeprom;
+
 			vendor_oui =
 			  ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
 			   (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
@@ -707,7 +1009,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 			case IXGBE_SFF_VENDOR_OUI_TYCO:
 				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 					hw->phy.type =
-						ixgbe_phy_sfp_passive_tyco;
+						    ixgbe_phy_sfp_passive_tyco;
 				break;
 			case IXGBE_SFF_VENDOR_OUI_FTL:
 				if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
@@ -724,7 +1026,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 			default:
 				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 					hw->phy.type =
-						ixgbe_phy_sfp_passive_unknown;
+						 ixgbe_phy_sfp_passive_unknown;
 				else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
 					hw->phy.type =
 						ixgbe_phy_sfp_active_unknown;
@@ -734,7 +1036,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 			}
 		}
 
-		/* All passive DA cables are supported */
+		/* Allow any DA cable vendor */
 		if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
 		    IXGBE_SFF_DA_ACTIVE_CABLE)) {
 			status = 0;
@@ -756,7 +1058,6 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 			goto out;
 		}
 
-		/* This is guaranteed to be 82599, no need to check for NULL */
 		hw->mac.ops.get_device_caps(hw, &enforce_sfp);
 		if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP) &&
 		    !((hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0) ||
@@ -776,15 +1077,24 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 
 out:
 	return status;
+
+err_read_i2c_eeprom:
+	hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+	if (hw->phy.type != ixgbe_phy_nl) {
+		hw->phy.id = 0;
+		hw->phy.type = ixgbe_phy_unknown;
+	}
+	return IXGBE_ERR_SFP_NOT_PRESENT;
 }
 
 /**
- *  ixgbe_get_sfp_init_sequence_offsets - Checks the MAC's EEPROM to see
- *  if it supports a given SFP+ module type, if so it returns the offsets to the
- *  phy init sequence block.
+ *  ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence
  *  @hw: pointer to hardware structure
  *  @list_offset: offset to the SFP ID list
  *  @data_offset: offset to the SFP data block
+ *
+ *  Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if
+ *  so it returns the offsets to the phy init sequence block.
  **/
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                                         u16 *list_offset,
@@ -899,11 +1209,22 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
                                 u8 dev_addr, u8 *data)
 {
 	s32 status = 0;
-	u32 max_retry = 1;
+	u32 max_retry = 10;
 	u32 retry = 0;
+	u16 swfw_mask = 0;
 	bool nack = 1;
 
+	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+		swfw_mask = IXGBE_GSSR_PHY1_SM;
+	else
+		swfw_mask = IXGBE_GSSR_PHY0_SM;
+
 	do {
+		if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) {
+			status = IXGBE_ERR_SWFW_SYNC;
+			goto read_byte_out;
+		}
+
 		ixgbe_i2c_start(hw);
 
 		/* Device Address and write indication */
@@ -946,6 +1267,8 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
 		break;
 
 fail:
+		ixgbe_release_swfw_sync(hw, swfw_mask);
+		msleep(100);
 		ixgbe_i2c_bus_clear(hw);
 		retry++;
 		if (retry < max_retry)
@@ -955,6 +1278,9 @@ fail:
 
 	} while (retry < max_retry);
 
+	ixgbe_release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
 	return status;
 }
 
@@ -973,6 +1299,17 @@ s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
 	s32 status = 0;
 	u32 max_retry = 1;
 	u32 retry = 0;
+	u16 swfw_mask = 0;
+
+	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+		swfw_mask = IXGBE_GSSR_PHY1_SM;
+	else
+		swfw_mask = IXGBE_GSSR_PHY0_SM;
+
+	if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) {
+		status = IXGBE_ERR_SWFW_SYNC;
+		goto write_byte_out;
+	}
 
 	do {
 		ixgbe_i2c_start(hw);
@@ -1013,6 +1350,9 @@ fail:
 			hw_dbg(hw, "I2C byte write error.\n");
 	} while (retry < max_retry);
 
+	ixgbe_release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
 	return status;
 }
 
@@ -1331,6 +1671,8 @@ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
 	u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
 	u32 i;
 
+	ixgbe_i2c_start(hw);
+
 	ixgbe_set_i2c_data(hw, &i2cctl, 1);
 
 	for (i = 0; i < 9; i++) {
@@ -1345,91 +1687,13 @@ static void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
 		udelay(IXGBE_I2C_T_LOW);
 	}
 
+	ixgbe_i2c_start(hw);
+
 	/* Put the i2c bus back to default state */
 	ixgbe_i2c_stop(hw);
 }
 
 /**
- *  ixgbe_check_phy_link_tnx - Determine link and speed status
- *  @hw: pointer to hardware structure
- *
- *  Reads the VS1 register to determine if link is up and the current speed for
- *  the PHY.
- **/
-s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
-                             bool *link_up)
-{
-	s32 status = 0;
-	u32 time_out;
-	u32 max_time_out = 10;
-	u16 phy_link = 0;
-	u16 phy_speed = 0;
-	u16 phy_data = 0;
-
-	/* Initialize speed and link to default case */
-	*link_up = false;
-	*speed = IXGBE_LINK_SPEED_10GB_FULL;
-
-	/*
-	 * Check current speed and link status of the PHY register.
-	 * This is a vendor specific register and may have to
-	 * be changed for other copper PHYs.
-	 */
-	for (time_out = 0; time_out < max_time_out; time_out++) {
-		udelay(10);
-		status = hw->phy.ops.read_reg(hw,
-		                        IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
-					MDIO_MMD_VEND1,
-		                        &phy_data);
-		phy_link = phy_data &
-		           IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
-		phy_speed = phy_data &
-		            IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
-		if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
-			*link_up = true;
-			if (phy_speed ==
-			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
-				*speed = IXGBE_LINK_SPEED_1GB_FULL;
-			break;
-		}
-	}
-
-	return status;
-}
-
-/**
- *  ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
- *  @hw: pointer to hardware structure
- *  @firmware_version: pointer to the PHY Firmware Version
- **/
-s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
-                                       u16 *firmware_version)
-{
-	s32 status = 0;
-
-	status = hw->phy.ops.read_reg(hw, TNX_FW_REV, MDIO_MMD_VEND1,
-	                              firmware_version);
-
-	return status;
-}
-
-/**
- *  ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
- *  @hw: pointer to hardware structure
- *  @firmware_version: pointer to the PHY Firmware Version
-**/
-s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
-                                           u16 *firmware_version)
-{
-	s32 status = 0;
-
-	status = hw->phy.ops.read_reg(hw, AQ_FW_REV, MDIO_MMD_VEND1,
-	                              firmware_version);
-
-	return status;
-}
-
-/**
  *  ixgbe_tn_check_overtemp - Checks if an overtemp occured.
  *  @hw: pointer to hardware structure
  *
diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h
index e2c6b7e..197bdd1 100644
--- a/drivers/net/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ixgbe/ixgbe_phy.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -58,6 +58,10 @@
 #define IXGBE_I2C_EEPROM_STATUS_FAIL         0x2
 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS  0x3
 
+/* Flow control defines */
+#define IXGBE_TAF_SYM_PAUSE                  0x400
+#define IXGBE_TAF_ASM_PAUSE                  0x800
+
 /* Bit-shift macros */
 #define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT    24
 #define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT    16
@@ -104,6 +108,7 @@ s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
 s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
                              ixgbe_link_speed *speed,
                              bool *link_up);
+s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw);
 s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
                                        u16 *firmware_version);
 s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c
index 187b3a1..6e50d83 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ixgbe/ixgbe_sriov.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -110,6 +110,33 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
 	return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
+void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int new_mtu = msgbuf[1];
+	u32 max_frs;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+
+	/* Only X540 supports jumbo frames in IOV mode */
+	if (adapter->hw.mac.type != ixgbe_mac_X540)
+		return;
+
+	/* MTU < 68 is an error and causes problems on some kernels */
+	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) {
+		e_err(drv, "VF mtu %d out of range\n", new_mtu);
+		return;
+	}
+
+	max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
+		   IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
+	if (max_frs < new_mtu) {
+		max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+		IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
+	}
+
+	e_info(hw, "VF requests change max MTU to %d\n", new_mtu);
+}
+
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
 {
 	u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
@@ -302,7 +329,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 		                                 hash_list, vf);
 		break;
 	case IXGBE_VF_SET_LPE:
-		WARN_ON((msgbuf[0] & 0xFFFF) == IXGBE_VF_SET_LPE);
+		ixgbe_set_vf_lpe(adapter, msgbuf);
 		break;
 	case IXGBE_VF_SET_VLAN:
 		add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
@@ -451,9 +478,90 @@ out:
        return err;
 }
 
+static int ixgbe_link_mbps(int internal_link_speed)
+{
+	switch (internal_link_speed) {
+	case IXGBE_LINK_SPEED_100_FULL:
+		return 100;
+	case IXGBE_LINK_SPEED_1GB_FULL:
+		return 1000;
+	case IXGBE_LINK_SPEED_10GB_FULL:
+		return 10000;
+	default:
+		return 0;
+	}
+}
+
+static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate,
+				    int link_speed)
+{
+	int rf_dec, rf_int;
+	u32 bcnrc_val;
+
+	if (tx_rate != 0) {
+		/* Calculate the rate factor values to set */
+		rf_int = link_speed / tx_rate;
+		rf_dec = (link_speed - (rf_int * tx_rate));
+		rf_dec = (rf_dec * (1<<IXGBE_RTTBCNRC_RF_INT_SHIFT)) / tx_rate;
+
+		bcnrc_val = IXGBE_RTTBCNRC_RS_ENA;
+		bcnrc_val |= ((rf_int<<IXGBE_RTTBCNRC_RF_INT_SHIFT) &
+		               IXGBE_RTTBCNRC_RF_INT_MASK);
+		bcnrc_val |= (rf_dec & IXGBE_RTTBCNRC_RF_DEC_MASK);
+	} else {
+		bcnrc_val = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, 2*vf); /* vf Y uses queue 2*Y */
+	IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val);
+}
+
+void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter)
+{
+	int actual_link_speed, i;
+	bool reset_rate = false;
+
+	/* VF Tx rate limit was not set */
+	if (adapter->vf_rate_link_speed == 0)
+		return;
+
+	actual_link_speed = ixgbe_link_mbps(adapter->link_speed);
+	if (actual_link_speed != adapter->vf_rate_link_speed) {
+		reset_rate = true;
+		adapter->vf_rate_link_speed = 0;
+		dev_info(&adapter->pdev->dev,
+		         "Link speed has been changed. VF Transmit rate "
+		         "is disabled\n");
+	}
+
+	for (i = 0; i < adapter->num_vfs; i++) {
+		if (reset_rate)
+			adapter->vfinfo[i].tx_rate = 0;
+
+		ixgbe_set_vf_rate_limit(&adapter->hw, i,
+					adapter->vfinfo[i].tx_rate,
+					actual_link_speed);
+	}
+}
+
 int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
 {
-	return -EOPNOTSUPP;
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
+	int actual_link_speed;
+
+	actual_link_speed = ixgbe_link_mbps(adapter->link_speed);
+	if ((vf >= adapter->num_vfs) || (!adapter->link_up) ||
+	    (tx_rate > actual_link_speed) || (actual_link_speed != 10000) ||
+	    ((tx_rate != 0) && (tx_rate <= 10)))
+	    /* rate limit cannot be set to 10Mb or less in 10Gb adapters */
+		return -EINVAL;
+
+	adapter->vf_rate_link_speed = actual_link_speed;
+	adapter->vfinfo[vf].tx_rate = (u16)tx_rate;
+	ixgbe_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed);
+
+	return 0;
 }
 
 int ixgbe_ndo_get_vf_config(struct net_device *netdev,
@@ -464,7 +572,7 @@ int ixgbe_ndo_get_vf_config(struct net_device *netdev,
 		return -EINVAL;
 	ivi->vf = vf;
 	memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN);
-	ivi->tx_rate = 0;
+	ivi->tx_rate = adapter->vfinfo[vf].tx_rate;
 	ivi->vlan = adapter->vfinfo[vf].pf_vlan;
 	ivi->qos = adapter->vfinfo[vf].pf_qos;
 	return 0;
diff --git a/drivers/net/ixgbe/ixgbe_sriov.h b/drivers/net/ixgbe/ixgbe_sriov.h
index 49dc14d..3417556 100644
--- a/drivers/net/ixgbe/ixgbe_sriov.h
+++ b/drivers/net/ixgbe/ixgbe_sriov.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -40,6 +40,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan,
 int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
 int ixgbe_ndo_get_vf_config(struct net_device *netdev,
 			    int vf, struct ifla_vf_info *ivi);
+void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
 
 #endif /* _IXGBE_SRIOV_H_ */
 
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index fd3358f..25c1fb7 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -91,7 +91,7 @@
 
 /* General Receive Control */
 #define IXGBE_GRC_MNG  0x00000001 /* Manageability Enable */
-#define IXGBE_GRC_APME 0x00000002 /* Advanced Power Management Enable */
+#define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */
 
 #define IXGBE_VPDDIAG0  0x10204
 #define IXGBE_VPDDIAG1  0x10208
@@ -342,7 +342,7 @@
 /* Wake Up Control */
 #define IXGBE_WUC_PME_EN     0x00000002 /* PME Enable */
 #define IXGBE_WUC_PME_STATUS 0x00000004 /* PME Status */
-#define IXGBE_WUC_ADVD3WUC   0x00000010 /* D3Cold wake up cap. enable*/
+#define IXGBE_WUC_WKEN       0x00000010 /* Enable PE_WAKE_N pin assertion  */
 
 /* Wake Up Filter Control */
 #define IXGBE_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
@@ -533,6 +533,12 @@
 #define IXGBE_RTTDTECC    0x04990
 #define IXGBE_RTTDTECC_NO_BCN   0x00000100
 #define IXGBE_RTTBCNRC    0x04984
+#define IXGBE_RTTBCNRC_RS_ENA	0x80000000
+#define IXGBE_RTTBCNRC_RF_DEC_MASK	0x00003FFF
+#define IXGBE_RTTBCNRC_RF_INT_SHIFT	14
+#define IXGBE_RTTBCNRC_RF_INT_MASK	\
+	(IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
+
 
 /* FCoE registers */
 #define IXGBE_FCPTRL    0x02410 /* FC User Desc. PTR Low */
@@ -659,6 +665,8 @@
 #define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QBRC(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QBTC(_i) (0x06034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBRC_L(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBRC_H(_i) (0x01038 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */
 #define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */
@@ -669,6 +677,11 @@
 #define IXGBE_FCOEDWRC  0x0242C /* Number of FCoE DWords Received */
 #define IXGBE_FCOEPTC   0x08784 /* Number of FCoE Packets Transmitted */
 #define IXGBE_FCOEDWTC  0x08788 /* Number of FCoE DWords Transmitted */
+#define IXGBE_PCRC8ECL  0x0E810
+#define IXGBE_PCRC8ECH  0x0E811
+#define IXGBE_PCRC8ECH_MASK     0x1F
+#define IXGBE_LDPCECL   0x0E820
+#define IXGBE_LDPCECH   0x0E821
 
 /* Management */
 #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */
@@ -1002,6 +1015,13 @@
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA     0xC30B /* PHY_XS SDA/SCL Data Reg */
 #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT     0xC30C /* PHY_XS SDA/SCL Status Reg */
 
+/* MII clause 22/28 definitions */
+#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */
+#define IXGBE_MII_AUTONEG_XNP_TX_REG             0x17   /* 1G XNP Transmit */
+#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX      0x4000 /* full duplex, bit:14*/
+#define IXGBE_MII_1GBASE_T_ADVERTISE             0x8000 /* full duplex, bit:15*/
+#define IXGBE_MII_AUTONEG_REG                    0x0
+
 #define IXGBE_PHY_REVISION_MASK        0xFFFFFFF0
 #define IXGBE_MAX_PHY_ADDR             32
 
@@ -1614,6 +1634,8 @@
 #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN  0x1 /* Alt. WWN base exists */
 
 /* PCI Bus Info */
+#define IXGBE_PCI_DEVICE_STATUS   0xAA
+#define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING   0x0020
 #define IXGBE_PCI_LINK_STATUS     0xB2
 #define IXGBE_PCI_DEVICE_CONTROL2 0xC8
 #define IXGBE_PCI_LINK_WIDTH      0x3F0
@@ -1680,6 +1702,8 @@
 #define IXGBE_RXCTRL_DMBYPS     0x00000002  /* Descriptor Monitor Bypass */
 #define IXGBE_RXDCTL_ENABLE     0x02000000  /* Enable specific Rx Queue */
 #define IXGBE_RXDCTL_VME        0x40000000  /* VLAN mode enable */
+#define IXGBE_RXDCTL_RLPMLMASK  0x00003FFF  /* Only supported on the X540 */
+#define IXGBE_RXDCTL_RLPML_EN   0x00008000
 
 #define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */
 #define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/
@@ -2240,6 +2264,7 @@ enum ixgbe_mac_type {
 
 enum ixgbe_phy_type {
 	ixgbe_phy_unknown = 0,
+	ixgbe_phy_none,
 	ixgbe_phy_tn,
 	ixgbe_phy_aq,
 	ixgbe_phy_cu_unknown,
@@ -2328,32 +2353,31 @@ enum ixgbe_bus_type {
 /* PCI bus speeds */
 enum ixgbe_bus_speed {
 	ixgbe_bus_speed_unknown = 0,
-	ixgbe_bus_speed_33,
-	ixgbe_bus_speed_66,
-	ixgbe_bus_speed_100,
-	ixgbe_bus_speed_120,
-	ixgbe_bus_speed_133,
-	ixgbe_bus_speed_2500,
-	ixgbe_bus_speed_5000,
+	ixgbe_bus_speed_33      = 33,
+	ixgbe_bus_speed_66      = 66,
+	ixgbe_bus_speed_100     = 100,
+	ixgbe_bus_speed_120     = 120,
+	ixgbe_bus_speed_133     = 133,
+	ixgbe_bus_speed_2500    = 2500,
+	ixgbe_bus_speed_5000    = 5000,
 	ixgbe_bus_speed_reserved
 };
 
 /* PCI bus widths */
 enum ixgbe_bus_width {
 	ixgbe_bus_width_unknown = 0,
-	ixgbe_bus_width_pcie_x1,
-	ixgbe_bus_width_pcie_x2,
+	ixgbe_bus_width_pcie_x1 = 1,
+	ixgbe_bus_width_pcie_x2 = 2,
 	ixgbe_bus_width_pcie_x4 = 4,
 	ixgbe_bus_width_pcie_x8 = 8,
-	ixgbe_bus_width_32,
-	ixgbe_bus_width_64,
+	ixgbe_bus_width_32      = 32,
+	ixgbe_bus_width_64      = 64,
 	ixgbe_bus_width_reserved
 };
 
 struct ixgbe_addr_filter_info {
 	u32 num_mc_addrs;
 	u32 rar_used_count;
-	u32 mc_addr_in_rar_count;
 	u32 mta_in_use;
 	u32 overflow_promisc;
 	bool uc_set_promisc;
@@ -2491,6 +2515,8 @@ struct ixgbe_mac_operations {
 	s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8);
 	s32 (*setup_sfp)(struct ixgbe_hw *);
 	s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
+	s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u16);
+	void (*release_swfw_sync)(struct ixgbe_hw *, u16);
 
 	/* Link */
 	void (*disable_tx_laser)(struct ixgbe_hw *);
@@ -2513,7 +2539,6 @@ struct ixgbe_mac_operations {
 	s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32);
 	s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32);
 	s32 (*init_rx_addrs)(struct ixgbe_hw *);
-	s32 (*update_uc_addr_list)(struct ixgbe_hw *, struct net_device *);
 	s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *);
 	s32 (*enable_mc)(struct ixgbe_hw *);
 	s32 (*disable_mc)(struct ixgbe_hw *);
@@ -2554,6 +2579,7 @@ struct ixgbe_eeprom_info {
 	u16                             address_bits;
 };
 
+#define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED	0x01
 struct ixgbe_mac_info {
 	struct ixgbe_mac_operations     ops;
 	enum ixgbe_mac_type             type;
@@ -2564,6 +2590,8 @@ struct ixgbe_mac_info {
 	u16                             wwnn_prefix;
 	/* prefix for World Wide Port Name (WWPN) */
 	u16                             wwpn_prefix;
+#define IXGBE_MAX_MTA			128
+	u32				mta_shadow[IXGBE_MAX_MTA];
 	s32                             mc_filter_type;
 	u32                             mcft_size;
 	u32                             vft_size;
@@ -2576,6 +2604,7 @@ struct ixgbe_mac_info {
 	u32                             orig_autoc2;
 	bool                            orig_link_settings_stored;
 	bool                            autotry_restart;
+	u8                              flags;
 };
 
 struct ixgbe_phy_info {
@@ -2682,7 +2711,9 @@ struct ixgbe_info {
 #define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_ERR_NO_SPACE                      -25
 #define IXGBE_ERR_OVERTEMP                      -26
-#define IXGBE_ERR_RAR_INDEX                     -27
+#define IXGBE_ERR_FC_NOT_NEGOTIATED             -27
+#define IXGBE_ERR_FC_NOT_SUPPORTED              -28
+#define IXGBE_ERR_FLOW_CONTROL                  -29
 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE        -30
 #define IXGBE_ERR_PBA_SECTION                   -31
 #define IXGBE_ERR_INVALID_ARGUMENT              -32
diff --git a/drivers/net/ixgbe/ixgbe_x540.c b/drivers/net/ixgbe/ixgbe_x540.c
index f2518b0..f47e93f 100644
--- a/drivers/net/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ixgbe/ixgbe_x540.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 Intel Corporation.
 
   This program is free software; you can redistribute it and/or modify it
   under the terms and conditions of the GNU General Public License,
@@ -31,7 +31,6 @@
 
 #include "ixgbe.h"
 #include "ixgbe_phy.h"
-//#include "ixgbe_mbx.h"
 
 #define IXGBE_X540_MAX_TX_QUEUES 128
 #define IXGBE_X540_MAX_RX_QUEUES 128
@@ -110,12 +109,9 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	status = ixgbe_disable_pcie_master(hw);
-	if (status != 0) {
-		status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
-		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
-	}
+	ixgbe_disable_pcie_master(hw);
 
+mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
 	 * If link reset is used when link is up, it might reset the PHY when
@@ -148,6 +144,19 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
+	/*
+	 * Double resets are required for recovery from certain error
+	 * conditions.  Between resets, it is necessary to stall to allow time
+	 * for any pending HW events to complete.  We use 1usec since that is
+	 * what is needed for ixgbe_disable_pcie_master().  The second reset
+	 * then clears out any effects of those events.
+	 */
+	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+		udelay(1);
+		goto mac_reset_top;
+	}
+
 	/* Clear PF Reset Done bit so PF/VF Mail Ops can work */
 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
 	ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
@@ -191,7 +200,7 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
 	 * clear the multicast table.  Also reset num_rar_entries to 128,
 	 * since we modify this value when programming the SAN MAC address.
 	 */
-	hw->mac.num_rar_entries = 128;
+	hw->mac.num_rar_entries = IXGBE_X540_MAX_TX_QUEUES;
 	hw->mac.ops.init_rx_addrs(hw);
 
 	/* Store the permanent mac address */
@@ -242,8 +251,11 @@ static u32 ixgbe_get_supported_physical_layer_X540(struct ixgbe_hw *hw)
 }
 
 /**
- * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
- * @hw: pointer to hardware structure
+ *  ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
+ *  @hw: pointer to hardware structure
+ *
+ *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
+ *  ixgbe_hw struct in order to set up EEPROM access.
  **/
 static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
 {
@@ -262,7 +274,7 @@ static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
 		                          IXGBE_EEPROM_WORD_SIZE_SHIFT);
 
 		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
-		        eeprom->type, eeprom->word_size);
+		       eeprom->type, eeprom->word_size);
 	}
 
 	return 0;
@@ -278,7 +290,7 @@ static s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
 {
 	s32 status;
 
-	if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM) == 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0)
 		status = ixgbe_read_eerd_generic(hw, offset, data);
 	else
 		status = IXGBE_ERR_SWFW_SYNC;
@@ -311,7 +323,7 @@ static s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
 	       (data << IXGBE_EEPROM_RW_REG_DATA) |
 	       IXGBE_EEPROM_RW_REG_START;
 
-	if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM) == 0) {
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
 		if (status != 0) {
 			hw_dbg(hw, "Eeprom write EEWR timed out\n");
@@ -676,7 +688,6 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
 	.set_vmdq               = &ixgbe_set_vmdq_generic,
 	.clear_vmdq             = &ixgbe_clear_vmdq_generic,
 	.init_rx_addrs          = &ixgbe_init_rx_addrs_generic,
-	.update_uc_addr_list    = &ixgbe_update_uc_addr_list_generic,
 	.update_mc_addr_list    = &ixgbe_update_mc_addr_list_generic,
 	.enable_mc              = &ixgbe_enable_mc_generic,
 	.disable_mc             = &ixgbe_disable_mc_generic,
@@ -687,6 +698,8 @@ static struct ixgbe_mac_operations mac_ops_X540 = {
 	.setup_sfp              = NULL,
 	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
 	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
+	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync_X540,
+	.release_swfw_sync      = &ixgbe_release_swfw_sync_X540,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
@@ -702,7 +715,7 @@ static struct ixgbe_phy_operations phy_ops_X540 = {
 	.identify               = &ixgbe_identify_phy_generic,
 	.identify_sfp           = &ixgbe_identify_sfp_module_generic,
 	.init			= NULL,
-	.reset                  = &ixgbe_reset_phy_generic,
+	.reset                  = NULL,
 	.read_reg               = &ixgbe_read_phy_reg_generic,
 	.write_reg              = &ixgbe_write_phy_reg_generic,
 	.setup_link             = &ixgbe_setup_phy_link_generic,
diff --git a/drivers/net/ixgbevf/defines.h b/drivers/net/ixgbevf/defines.h
index de643eb..78abb6f 100644
--- a/drivers/net/ixgbevf/defines.h
+++ b/drivers/net/ixgbevf/defines.h
@@ -65,6 +65,8 @@ typedef u32 ixgbe_link_speed;
 #define IXGBE_RXCTRL_DMBYPS     0x00000002  /* Descriptor Monitor Bypass */
 #define IXGBE_RXDCTL_ENABLE     0x02000000  /* Enable specific Rx Queue */
 #define IXGBE_RXDCTL_VME        0x40000000  /* VLAN mode enable */
+#define IXGBE_RXDCTL_RLPMLMASK  0x00003FFF  /* Only supported on the X540 */
+#define IXGBE_RXDCTL_RLPML_EN   0x00008000
 
 /* DCA Control */
 #define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c
index fa29b3c..0563ab2 100644
--- a/drivers/net/ixgbevf/ethtool.c
+++ b/drivers/net/ixgbevf/ethtool.c
@@ -172,7 +172,7 @@ static char *ixgbevf_reg_names[] = {
 	"IXGBE_VFSTATUS",
 	"IXGBE_VFLINKS",
 	"IXGBE_VFRXMEMWRAP",
-	"IXGBE_VFRTIMER",
+	"IXGBE_VFFRTIMER",
 	"IXGBE_VTEICR",
 	"IXGBE_VTEICS",
 	"IXGBE_VTEIMS",
@@ -240,7 +240,7 @@ static void ixgbevf_get_regs(struct net_device *netdev,
 	regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS);
 	regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
 	regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP);
-	regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFRTIMER);
+	regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER);
 
 	/* Interrupt */
 	/* don't read EICR because it can clear interrupt causes, instead
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index a63efcb..b703f60 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -207,7 +207,6 @@ struct ixgbevf_adapter {
 	u64 hw_tso_ctxt;
 	u64 hw_tso6_ctxt;
 	u32 tx_timeout_count;
-	bool detect_tx_hung;
 
 	/* RX */
 	struct ixgbevf_ring *rx_ring;	/* One per active queue */
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 464e6c9..054ab05 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -49,9 +49,9 @@
 
 char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
-	"Intel(R) 82599 Virtual Function";
+	"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
-#define DRV_VERSION "1.0.19-k0"
+#define DRV_VERSION "2.0.0-k2"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
 	"Copyright (c) 2009 - 2010 Intel Corporation.";
@@ -107,7 +107,7 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
 }
 
 /*
- * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors
+ * ixgbevf_set_ivar - set IVAR registers - maps interrupt causes to vectors
  * @adapter: pointer to adapter struct
  * @direction: 0 for Rx, 1 for Tx, -1 for other causes
  * @queue: queue to map the corresponding interrupt to
@@ -162,42 +162,6 @@ static void ixgbevf_unmap_and_free_tx_resource(struct ixgbevf_adapter *adapter,
 	/* tx_buffer_info must be completely set up in the transmit path */
 }
 
-static inline bool ixgbevf_check_tx_hang(struct ixgbevf_adapter *adapter,
-					 struct ixgbevf_ring *tx_ring,
-					 unsigned int eop)
-{
-	struct ixgbe_hw *hw = &adapter->hw;
-	u32 head, tail;
-
-	/* Detect a transmit hang in hardware, this serializes the
-	 * check with the clearing of time_stamp and movement of eop */
-	head = readl(hw->hw_addr + tx_ring->head);
-	tail = readl(hw->hw_addr + tx_ring->tail);
-	adapter->detect_tx_hung = false;
-	if ((head != tail) &&
-	    tx_ring->tx_buffer_info[eop].time_stamp &&
-	    time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ)) {
-		/* detected Tx unit hang */
-		union ixgbe_adv_tx_desc *tx_desc;
-		tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
-		printk(KERN_ERR "Detected Tx Unit Hang\n"
-		       "  Tx Queue             <%d>\n"
-		       "  TDH, TDT             <%x>, <%x>\n"
-		       "  next_to_use          <%x>\n"
-		       "  next_to_clean        <%x>\n"
-		       "tx_buffer_info[next_to_clean]\n"
-		       "  time_stamp           <%lx>\n"
-		       "  jiffies              <%lx>\n",
-		       tx_ring->queue_index,
-		       head, tail,
-		       tx_ring->next_to_use, eop,
-		       tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
-		return true;
-	}
-
-	return false;
-}
-
 #define IXGBE_MAX_TXD_PWR	14
 #define IXGBE_MAX_DATA_PER_TXD	(1 << IXGBE_MAX_TXD_PWR)
 
@@ -293,16 +257,6 @@ static bool ixgbevf_clean_tx_irq(struct ixgbevf_adapter *adapter,
 #endif
 	}
 
-	if (adapter->detect_tx_hung) {
-		if (ixgbevf_check_tx_hang(adapter, tx_ring, i)) {
-			/* schedule immediate reset if we believe we hung */
-			printk(KERN_INFO
-			       "tx hang %d detected, resetting adapter\n",
-			       adapter->tx_timeout_count + 1);
-			ixgbevf_tx_timeout(adapter->netdev);
-		}
-	}
-
 	/* re-arm the interrupt */
 	if ((count >= tx_ring->work_limit) &&
 	    (!test_bit(__IXGBEVF_DOWN, &adapter->state))) {
@@ -334,7 +288,6 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
 	struct ixgbevf_adapter *adapter = q_vector->adapter;
 	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
 	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
-	int ret;
 
 	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
 		if (adapter->vlgrp && is_vlan)
@@ -345,9 +298,9 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
 			napi_gro_receive(&q_vector->napi, skb);
 	} else {
 		if (adapter->vlgrp && is_vlan)
-			ret = vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
+			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
 		else
-			ret = netif_rx(skb);
+			netif_rx(skb);
 	}
 }
 
@@ -1017,7 +970,7 @@ static irqreturn_t ixgbevf_msix_clean_tx(int irq, void *data)
 }
 
 /**
- * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
+ * ixgbevf_msix_clean_rx - single unshared vector rx clean (all queues)
  * @irq: unused
  * @data: pointer to our q_vector struct for this interrupt vector
  **/
@@ -1665,6 +1618,11 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 		j = adapter->rx_ring[i].reg_idx;
 		rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
 		rxdctl |= IXGBE_RXDCTL_ENABLE;
+		if (hw->mac.type == ixgbe_mac_X540_vf) {
+			rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
+			rxdctl |= ((netdev->mtu + ETH_HLEN + ETH_FCS_LEN) |
+				   IXGBE_RXDCTL_RLPML_EN);
+		}
 		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl);
 		ixgbevf_rx_desc_queue_enable(adapter, i);
 	}
@@ -1967,7 +1925,7 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
 }
 
 /*
- * ixgbe_set_num_queues: Allocate queues for device, feature dependant
+ * ixgbevf_set_num_queues: Allocate queues for device, feature dependant
  * @adapter: board private structure to initialize
  *
  * This is the top level queue allocation routine.  The order here is very
@@ -2216,7 +2174,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
 
 	hw->vendor_id = pdev->vendor;
 	hw->device_id = pdev->device;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+	hw->revision_id = pdev->revision;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
 
@@ -2410,9 +2368,6 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
 			       10 : 1);
 			netif_carrier_on(netdev);
 			netif_tx_wake_all_queues(netdev);
-		} else {
-			/* Force detection of hung controller */
-			adapter->detect_tx_hung = true;
 		}
 	} else {
 		adapter->link_up = false;
@@ -2427,9 +2382,6 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
 	ixgbevf_update_stats(adapter);
 
 pf_has_reset:
-	/* Force detection of hung controller every watchdog period */
-	adapter->detect_tx_hung = true;
-
 	/* Reset the timer */
 	if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
 		mod_timer(&adapter->watchdog_timer,
@@ -3217,10 +3169,16 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p)
 static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+	int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
+	u32 msg[2];
+
+	if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+		max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
 
 	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
+	if ((new_mtu < 68) || (max_frame > max_possible_frame))
 		return -EINVAL;
 
 	hw_dbg(&adapter->hw, "changing MTU from %d to %d\n",
@@ -3228,6 +3186,10 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
 	/* must set new MTU before calling down or up */
 	netdev->mtu = new_mtu;
 
+	msg[0] = IXGBE_VF_SET_LPE;
+	msg[1] = max_frame;
+	hw->mbx.ops.write_posted(hw, msg, 2);
+
 	if (netif_running(netdev))
 		ixgbevf_reinit_locked(adapter);
 
@@ -3272,8 +3234,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
 
 static void ixgbevf_assign_netdev_ops(struct net_device *dev)
 {
-	struct ixgbevf_adapter *adapter;
-	adapter = netdev_priv(dev);
 	dev->netdev_ops = &ixgbe_netdev_ops;
 	ixgbevf_set_ethtool_ops(dev);
 	dev->watchdog_timeo = 5 * HZ;
@@ -3519,9 +3479,9 @@ static struct pci_driver ixgbevf_driver = {
 };
 
 /**
- * ixgbe_init_module - Driver Registration Routine
+ * ixgbevf_init_module - Driver Registration Routine
  *
- * ixgbe_init_module is the first routine called when the driver is
+ * ixgbevf_init_module is the first routine called when the driver is
  * loaded. All it does is register with the PCI subsystem.
  **/
 static int __init ixgbevf_init_module(void)
@@ -3539,9 +3499,9 @@ static int __init ixgbevf_init_module(void)
 module_init(ixgbevf_init_module);
 
 /**
- * ixgbe_exit_module - Driver Exit Cleanup Routine
+ * ixgbevf_exit_module - Driver Exit Cleanup Routine
  *
- * ixgbe_exit_module is called just before the driver is removed
+ * ixgbevf_exit_module is called just before the driver is removed
  * from memory.
  **/
 static void __exit ixgbevf_exit_module(void)
@@ -3551,7 +3511,7 @@ static void __exit ixgbevf_exit_module(void)
 
 #ifdef DEBUG
 /**
- * ixgbe_get_hw_dev_name - return device name string
+ * ixgbevf_get_hw_dev_name - return device name string
  * used by hardware layer to print debugging information
  **/
 char *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw)
diff --git a/drivers/net/ixgbevf/regs.h b/drivers/net/ixgbevf/regs.h
index fb80ca1..189200e 100644
--- a/drivers/net/ixgbevf/regs.h
+++ b/drivers/net/ixgbevf/regs.h
@@ -31,7 +31,7 @@
 #define IXGBE_VFCTRL           0x00000
 #define IXGBE_VFSTATUS         0x00008
 #define IXGBE_VFLINKS          0x00010
-#define IXGBE_VFRTIMER         0x00048
+#define IXGBE_VFFRTIMER        0x00048
 #define IXGBE_VFRXMEMWRAP      0x03190
 #define IXGBE_VTEICR           0x00100
 #define IXGBE_VTEICS           0x00104
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index e97ebef..f690474 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -161,6 +161,67 @@ jme_setup_wakeup_frame(struct jme_adapter *jme,
 }
 
 static inline void
+jme_mac_rxclk_off(struct jme_adapter *jme)
+{
+	jme->reg_gpreg1 |= GPREG1_RXCLKOFF;
+	jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1);
+}
+
+static inline void
+jme_mac_rxclk_on(struct jme_adapter *jme)
+{
+	jme->reg_gpreg1 &= ~GPREG1_RXCLKOFF;
+	jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1);
+}
+
+static inline void
+jme_mac_txclk_off(struct jme_adapter *jme)
+{
+	jme->reg_ghc &= ~(GHC_TO_CLK_SRC | GHC_TXMAC_CLK_SRC);
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_mac_txclk_on(struct jme_adapter *jme)
+{
+	u32 speed = jme->reg_ghc & GHC_SPEED;
+	if (speed == GHC_SPEED_1000M)
+		jme->reg_ghc |= GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
+	else
+		jme->reg_ghc |= GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_reset_ghc_speed(struct jme_adapter *jme)
+{
+	jme->reg_ghc &= ~(GHC_SPEED | GHC_DPX);
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_reset_250A2_workaround(struct jme_adapter *jme)
+{
+	jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH |
+			     GPREG1_RSSPATCH);
+	jwrite32(jme, JME_GPREG1, jme->reg_gpreg1);
+}
+
+static inline void
+jme_assert_ghc_reset(struct jme_adapter *jme)
+{
+	jme->reg_ghc |= GHC_SWRST;
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_clear_ghc_reset(struct jme_adapter *jme)
+{
+	jme->reg_ghc &= ~GHC_SWRST;
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
 jme_reset_mac_processor(struct jme_adapter *jme)
 {
 	static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0};
@@ -168,9 +229,24 @@ jme_reset_mac_processor(struct jme_adapter *jme)
 	u32 gpreg0;
 	int i;
 
-	jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST);
-	udelay(2);
-	jwrite32(jme, JME_GHC, jme->reg_ghc);
+	jme_reset_ghc_speed(jme);
+	jme_reset_250A2_workaround(jme);
+
+	jme_mac_rxclk_on(jme);
+	jme_mac_txclk_on(jme);
+	udelay(1);
+	jme_assert_ghc_reset(jme);
+	udelay(1);
+	jme_mac_rxclk_off(jme);
+	jme_mac_txclk_off(jme);
+	udelay(1);
+	jme_clear_ghc_reset(jme);
+	udelay(1);
+	jme_mac_rxclk_on(jme);
+	jme_mac_txclk_on(jme);
+	udelay(1);
+	jme_mac_rxclk_off(jme);
+	jme_mac_txclk_off(jme);
 
 	jwrite32(jme, JME_RXDBA_LO, 0x00000000);
 	jwrite32(jme, JME_RXDBA_HI, 0x00000000);
@@ -190,14 +266,6 @@ jme_reset_mac_processor(struct jme_adapter *jme)
 	else
 		gpreg0 = GPREG0_DEFAULT;
 	jwrite32(jme, JME_GPREG0, gpreg0);
-	jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT);
-}
-
-static inline void
-jme_reset_ghc_speed(struct jme_adapter *jme)
-{
-	jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX);
-	jwrite32(jme, JME_GHC, jme->reg_ghc);
 }
 
 static inline void
@@ -336,13 +404,13 @@ jme_linkstat_from_phy(struct jme_adapter *jme)
 }
 
 static inline void
-jme_set_phyfifoa(struct jme_adapter *jme)
+jme_set_phyfifo_5level(struct jme_adapter *jme)
 {
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004);
 }
 
 static inline void
-jme_set_phyfifob(struct jme_adapter *jme)
+jme_set_phyfifo_8level(struct jme_adapter *jme)
 {
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0000);
 }
@@ -351,7 +419,7 @@ static int
 jme_check_link(struct net_device *netdev, int testonly)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
-	u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1;
+	u32 phylink, cnt = JME_SPDRSV_TIMEOUT, bmcr;
 	char linkmsg[64];
 	int rc = 0;
 
@@ -414,23 +482,21 @@ jme_check_link(struct net_device *netdev, int testonly)
 
 		jme->phylink = phylink;
 
-		ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX |
-				GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE |
-				GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY);
+		/*
+		 * The speed/duplex setting of jme->reg_ghc already cleared
+		 * by jme_reset_mac_processor()
+		 */
 		switch (phylink & PHY_LINK_SPEED_MASK) {
 		case PHY_LINK_SPEED_10M:
-			ghc |= GHC_SPEED_10M |
-				GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+			jme->reg_ghc |= GHC_SPEED_10M;
 			strcat(linkmsg, "10 Mbps, ");
 			break;
 		case PHY_LINK_SPEED_100M:
-			ghc |= GHC_SPEED_100M |
-				GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+			jme->reg_ghc |= GHC_SPEED_100M;
 			strcat(linkmsg, "100 Mbps, ");
 			break;
 		case PHY_LINK_SPEED_1000M:
-			ghc |= GHC_SPEED_1000M |
-				GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
+			jme->reg_ghc |= GHC_SPEED_1000M;
 			strcat(linkmsg, "1000 Mbps, ");
 			break;
 		default:
@@ -439,42 +505,40 @@ jme_check_link(struct net_device *netdev, int testonly)
 
 		if (phylink & PHY_LINK_DUPLEX) {
 			jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT);
-			ghc |= GHC_DPX;
+			jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX);
+			jme->reg_ghc |= GHC_DPX;
 		} else {
 			jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT |
 						TXMCS_BACKOFF |
 						TXMCS_CARRIERSENSE |
 						TXMCS_COLLISION);
-			jwrite32(jme, JME_TXTRHD, TXTRHD_TXPEN |
-				((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
-				TXTRHD_TXREN |
-				((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL));
+			jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX);
 		}
 
-		gpreg1 = GPREG1_DEFAULT;
+		jwrite32(jme, JME_GHC, jme->reg_ghc);
+
 		if (is_buggy250(jme->pdev->device, jme->chiprev)) {
+			jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH |
+					     GPREG1_RSSPATCH);
 			if (!(phylink & PHY_LINK_DUPLEX))
-				gpreg1 |= GPREG1_HALFMODEPATCH;
+				jme->reg_gpreg1 |= GPREG1_HALFMODEPATCH;
 			switch (phylink & PHY_LINK_SPEED_MASK) {
 			case PHY_LINK_SPEED_10M:
-				jme_set_phyfifoa(jme);
-				gpreg1 |= GPREG1_RSSPATCH;
+				jme_set_phyfifo_8level(jme);
+				jme->reg_gpreg1 |= GPREG1_RSSPATCH;
 				break;
 			case PHY_LINK_SPEED_100M:
-				jme_set_phyfifob(jme);
-				gpreg1 |= GPREG1_RSSPATCH;
+				jme_set_phyfifo_5level(jme);
+				jme->reg_gpreg1 |= GPREG1_RSSPATCH;
 				break;
 			case PHY_LINK_SPEED_1000M:
-				jme_set_phyfifoa(jme);
+				jme_set_phyfifo_8level(jme);
 				break;
 			default:
 				break;
 			}
 		}
-
-		jwrite32(jme, JME_GPREG1, gpreg1);
-		jwrite32(jme, JME_GHC, ghc);
-		jme->reg_ghc = ghc;
+		jwrite32(jme, JME_GPREG1, jme->reg_gpreg1);
 
 		strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
 					"Full-Duplex, " :
@@ -613,10 +677,14 @@ jme_enable_tx_engine(struct jme_adapter *jme)
 	 * Enable TX Engine
 	 */
 	wmb();
-	jwrite32(jme, JME_TXCS, jme->reg_txcs |
+	jwrite32f(jme, JME_TXCS, jme->reg_txcs |
 				TXCS_SELECT_QUEUE0 |
 				TXCS_ENABLE);
 
+	/*
+	 * Start clock for TX MAC Processor
+	 */
+	jme_mac_txclk_on(jme);
 }
 
 static inline void
@@ -651,6 +719,11 @@ jme_disable_tx_engine(struct jme_adapter *jme)
 
 	if (!i)
 		pr_err("Disable TX engine timeout\n");
+
+	/*
+	 * Stop clock for TX MAC Processor
+	 */
+	jme_mac_txclk_off(jme);
 }
 
 static void
@@ -825,16 +898,22 @@ jme_enable_rx_engine(struct jme_adapter *jme)
 	/*
 	 * Setup Unicast Filter
 	 */
+	jme_set_unicastaddr(jme->dev);
 	jme_set_multi(jme->dev);
 
 	/*
 	 * Enable RX Engine
 	 */
 	wmb();
-	jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+	jwrite32f(jme, JME_RXCS, jme->reg_rxcs |
 				RXCS_QUEUESEL_Q0 |
 				RXCS_ENABLE |
 				RXCS_QST);
+
+	/*
+	 * Start clock for RX MAC Processor
+	 */
+	jme_mac_rxclk_on(jme);
 }
 
 static inline void
@@ -871,10 +950,40 @@ jme_disable_rx_engine(struct jme_adapter *jme)
 	if (!i)
 		pr_err("Disable RX engine timeout\n");
 
+	/*
+	 * Stop clock for RX MAC Processor
+	 */
+	jme_mac_rxclk_off(jme);
+}
+
+static u16
+jme_udpsum(struct sk_buff *skb)
+{
+	u16 csum = 0xFFFFu;
+
+	if (skb->len < (ETH_HLEN + sizeof(struct iphdr)))
+		return csum;
+	if (skb->protocol != htons(ETH_P_IP))
+		return csum;
+	skb_set_network_header(skb, ETH_HLEN);
+	if ((ip_hdr(skb)->protocol != IPPROTO_UDP) ||
+	    (skb->len < (ETH_HLEN +
+			(ip_hdr(skb)->ihl << 2) +
+			sizeof(struct udphdr)))) {
+		skb_reset_network_header(skb);
+		return csum;
+	}
+	skb_set_transport_header(skb,
+			ETH_HLEN + (ip_hdr(skb)->ihl << 2));
+	csum = udp_hdr(skb)->check;
+	skb_reset_transport_header(skb);
+	skb_reset_network_header(skb);
+
+	return csum;
 }
 
 static int
-jme_rxsum_ok(struct jme_adapter *jme, u16 flags)
+jme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb)
 {
 	if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4)))
 		return false;
@@ -887,7 +996,7 @@ jme_rxsum_ok(struct jme_adapter *jme, u16 flags)
 	}
 
 	if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS))
-			== RXWBFLAG_UDPON)) {
+			== RXWBFLAG_UDPON) && jme_udpsum(skb)) {
 		if (flags & RXWBFLAG_IPV4)
 			netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n");
 		return false;
@@ -935,7 +1044,7 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
 		skb_put(skb, framesize);
 		skb->protocol = eth_type_trans(skb, jme->dev);
 
-		if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags)))
+		if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
 			skb_checksum_none_assert(skb);
@@ -1207,7 +1316,6 @@ jme_link_change_tasklet(unsigned long arg)
 	tasklet_disable(&jme->rxempty_task);
 
 	if (netif_carrier_ok(netdev)) {
-		jme_reset_ghc_speed(jme);
 		jme_disable_rx_engine(jme);
 		jme_disable_tx_engine(jme);
 		jme_reset_mac_processor(jme);
@@ -1577,6 +1685,38 @@ jme_free_irq(struct jme_adapter *jme)
 }
 
 static inline void
+jme_new_phy_on(struct jme_adapter *jme)
+{
+	u32 reg;
+
+	reg = jread32(jme, JME_PHY_PWR);
+	reg &= ~(PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW |
+		 PHY_PWR_DWN2 | PHY_PWR_CLKSEL);
+	jwrite32(jme, JME_PHY_PWR, reg);
+
+	pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, &reg);
+	reg &= ~PE1_GPREG0_PBG;
+	reg |= PE1_GPREG0_ENBG;
+	pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
+}
+
+static inline void
+jme_new_phy_off(struct jme_adapter *jme)
+{
+	u32 reg;
+
+	reg = jread32(jme, JME_PHY_PWR);
+	reg |= PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW |
+	       PHY_PWR_DWN2 | PHY_PWR_CLKSEL;
+	jwrite32(jme, JME_PHY_PWR, reg);
+
+	pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, &reg);
+	reg &= ~PE1_GPREG0_PBG;
+	reg |= PE1_GPREG0_PDD3COLD;
+	pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
+}
+
+static inline void
 jme_phy_on(struct jme_adapter *jme)
 {
 	u32 bmcr;
@@ -1584,6 +1724,22 @@ jme_phy_on(struct jme_adapter *jme)
 	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
 	bmcr &= ~BMCR_PDOWN;
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+
+	if (new_phy_power_ctrl(jme->chip_main_rev))
+		jme_new_phy_on(jme);
+}
+
+static inline void
+jme_phy_off(struct jme_adapter *jme)
+{
+	u32 bmcr;
+
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr |= BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+
+	if (new_phy_power_ctrl(jme->chip_main_rev))
+		jme_new_phy_off(jme);
 }
 
 static int
@@ -1606,12 +1762,11 @@ jme_open(struct net_device *netdev)
 
 	jme_start_irq(jme);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
-		jme_phy_on(jme);
+	jme_phy_on(jme);
+	if (test_bit(JME_FLAG_SSET, &jme->flags))
 		jme_set_settings(netdev, &jme->old_ecmd);
-	} else {
+	else
 		jme_reset_phy_processor(jme);
-	}
 
 	jme_reset_link(jme);
 
@@ -1657,12 +1812,6 @@ jme_wait_link(struct jme_adapter *jme)
 	}
 }
 
-static inline void
-jme_phy_off(struct jme_adapter *jme)
-{
-	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN);
-}
-
 static void
 jme_powersave_phy(struct jme_adapter *jme)
 {
@@ -1696,7 +1845,6 @@ jme_close(struct net_device *netdev)
 	tasklet_disable(&jme->rxclean_task);
 	tasklet_disable(&jme->rxempty_task);
 
-	jme_reset_ghc_speed(jme);
 	jme_disable_rx_engine(jme);
 	jme_disable_tx_engine(jme);
 	jme_reset_mac_processor(jme);
@@ -1993,27 +2141,34 @@ jme_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 	return NETDEV_TX_OK;
 }
 
+static void
+jme_set_unicastaddr(struct net_device *netdev)
+{
+	struct jme_adapter *jme = netdev_priv(netdev);
+	u32 val;
+
+	val = (netdev->dev_addr[3] & 0xff) << 24 |
+	      (netdev->dev_addr[2] & 0xff) << 16 |
+	      (netdev->dev_addr[1] & 0xff) <<  8 |
+	      (netdev->dev_addr[0] & 0xff);
+	jwrite32(jme, JME_RXUMA_LO, val);
+	val = (netdev->dev_addr[5] & 0xff) << 8 |
+	      (netdev->dev_addr[4] & 0xff);
+	jwrite32(jme, JME_RXUMA_HI, val);
+}
+
 static int
 jme_set_macaddr(struct net_device *netdev, void *p)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
 	struct sockaddr *addr = p;
-	u32 val;
 
 	if (netif_running(netdev))
 		return -EBUSY;
 
 	spin_lock_bh(&jme->macaddr_lock);
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-
-	val = (addr->sa_data[3] & 0xff) << 24 |
-	      (addr->sa_data[2] & 0xff) << 16 |
-	      (addr->sa_data[1] & 0xff) <<  8 |
-	      (addr->sa_data[0] & 0xff);
-	jwrite32(jme, JME_RXUMA_LO, val);
-	val = (addr->sa_data[5] & 0xff) << 8 |
-	      (addr->sa_data[4] & 0xff);
-	jwrite32(jme, JME_RXUMA_HI, val);
+	jme_set_unicastaddr(netdev);
 	spin_unlock_bh(&jme->macaddr_lock);
 
 	return 0;
@@ -2731,6 +2886,8 @@ jme_check_hw_ver(struct jme_adapter *jme)
 
 	jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT;
 	jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT;
+	jme->chip_main_rev = jme->chiprev & 0xF;
+	jme->chip_sub_rev = (jme->chiprev >> 4) & 0xF;
 }
 
 static const struct net_device_ops jme_netdev_ops = {
@@ -2880,6 +3037,7 @@ jme_init_one(struct pci_dev *pdev,
 	jme->reg_rxmcs = RXMCS_DEFAULT;
 	jme->reg_txpfc = 0;
 	jme->reg_pmcs = PMCS_MFEN;
+	jme->reg_gpreg1 = GPREG1_DEFAULT;
 	set_bit(JME_FLAG_TXCSUM, &jme->flags);
 	set_bit(JME_FLAG_TSO, &jme->flags);
 
@@ -2936,8 +3094,8 @@ jme_init_one(struct pci_dev *pdev,
 	jme->mii_if.mdio_write = jme_mdio_write;
 
 	jme_clear_pm(jme);
-	jme_set_phyfifoa(jme);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->rev);
+	jme_set_phyfifo_5level(jme);
+	jme->pcirev = pdev->revision;
 	if (!jme->fpgaver)
 		jme_phy_init(jme);
 	jme_phy_off(jme);
@@ -2964,14 +3122,14 @@ jme_init_one(struct pci_dev *pdev,
 		goto err_out_unmap;
 	}
 
-	netif_info(jme, probe, jme->dev, "%s%s ver:%x rev:%x macaddr:%pM\n",
+	netif_info(jme, probe, jme->dev, "%s%s chiprev:%x pcirev:%x macaddr:%pM\n",
 		   (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ?
 		   "JMC250 Gigabit Ethernet" :
 		   (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ?
 		   "JMC260 Fast Ethernet" : "Unknown",
 		   (jme->fpgaver != 0) ? " (FPGA)" : "",
 		   (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev,
-		   jme->rev, netdev->dev_addr);
+		   jme->pcirev, netdev->dev_addr);
 
 	return 0;
 
@@ -3035,7 +3193,6 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
 			jme_polling_mode(jme);
 
 		jme_stop_pcc_timer(jme);
-		jme_reset_ghc_speed(jme);
 		jme_disable_rx_engine(jme);
 		jme_disable_tx_engine(jme);
 		jme_reset_mac_processor(jme);
@@ -3066,12 +3223,11 @@ jme_resume(struct pci_dev *pdev)
 	jme_clear_pm(jme);
 	pci_restore_state(pdev);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
-		jme_phy_on(jme);
+	jme_phy_on(jme);
+	if (test_bit(JME_FLAG_SSET, &jme->flags))
 		jme_set_settings(netdev, &jme->old_ecmd);
-	} else {
+	else
 		jme_reset_phy_processor(jme);
-	}
 
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index eac0926..8bf3045 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -26,7 +26,7 @@
 #define __JME_H_INCLUDED__
 
 #define DRV_NAME	"jme"
-#define DRV_VERSION	"1.0.7"
+#define DRV_VERSION	"1.0.8"
 #define PFX		DRV_NAME ": "
 
 #define PCI_DEVICE_ID_JMICRON_JMC250	0x0250
@@ -103,6 +103,37 @@ enum jme_spi_op_bits {
 #define HALF_US 500	/* 500 ns */
 #define JMESPIIOCTL	SIOCDEVPRIVATE
 
+#define PCI_PRIV_PE1		0xE4
+
+enum pci_priv_pe1_bit_masks {
+	PE1_ASPMSUPRT	= 0x00000003, /*
+				       * RW:
+				       * Aspm_support[1:0]
+				       * (R/W Port of 5C[11:10])
+				       */
+	PE1_MULTIFUN	= 0x00000004, /* RW: Multi_fun_bit */
+	PE1_RDYDMA	= 0x00000008, /* RO: ~link.rdy_for_dma */
+	PE1_ASPMOPTL	= 0x00000030, /* RW: link.rx10s_option[1:0] */
+	PE1_ASPMOPTH	= 0x000000C0, /* RW: 10_req=[3]?HW:[2] */
+	PE1_GPREG0	= 0x0000FF00, /*
+				       * SRW:
+				       * Cfg_gp_reg0
+				       * [7:6] phy_giga BG control
+				       * [5] CREQ_N as CREQ_N1 (CPPE# as CREQ#)
+				       * [4:0] Reserved
+				       */
+	PE1_GPREG0_PBG	= 0x0000C000, /* phy_giga BG control */
+	PE1_GPREG1	= 0x00FF0000, /* RW: Cfg_gp_reg1 */
+	PE1_REVID	= 0xFF000000, /* RO: Rev ID */
+};
+
+enum pci_priv_pe1_values {
+	PE1_GPREG0_ENBG		= 0x00000000, /* en BG */
+	PE1_GPREG0_PDD3COLD	= 0x00004000, /* giga_PD + d3cold */
+	PE1_GPREG0_PDPCIESD	= 0x00008000, /* giga_PD + pcie_shutdown */
+	PE1_GPREG0_PDPCIEIDDQ	= 0x0000C000, /* giga_PD + pcie_iddq */
+};
+
 /*
  * Dynamic(adaptive)/Static PCC values
  */
@@ -403,6 +434,7 @@ struct jme_adapter {
 	u32			reg_rxmcs;
 	u32			reg_ghc;
 	u32			reg_pmcs;
+	u32			reg_gpreg1;
 	u32			phylink;
 	u32			tx_ring_size;
 	u32			tx_ring_mask;
@@ -411,8 +443,10 @@ struct jme_adapter {
 	u32			rx_ring_mask;
 	u8			mrrs;
 	unsigned int		fpgaver;
-	unsigned int		chiprev;
-	u8			rev;
+	u8			chiprev;
+	u8			chip_main_rev;
+	u8			chip_sub_rev;
+	u8			pcirev;
 	u32			msg_enable;
 	struct ethtool_cmd	old_ecmd;
 	unsigned int		old_mtu;
@@ -497,6 +531,7 @@ enum jme_iomap_regs {
 	JME_PMCS	= JME_MAC | 0x60, /* Power Management Control/Stat */
 
 
+	JME_PHY_PWR	= JME_PHY | 0x24, /* New PHY Power Ctrl Register */
 	JME_PHY_CS	= JME_PHY | 0x28, /* PHY Ctrl and Status Register */
 	JME_PHY_LINK	= JME_PHY | 0x30, /* PHY Link Status Register */
 	JME_SMBCSR	= JME_PHY | 0x40, /* SMB Control and Status */
@@ -624,6 +659,14 @@ enum jme_txtrhd_shifts {
 	TXTRHD_TXRL_SHIFT	= 0,
 };
 
+enum jme_txtrhd_values {
+	TXTRHD_FULLDUPLEX	= 0x00000000,
+	TXTRHD_HALFDUPLEX	= TXTRHD_TXPEN |
+				  ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
+				  TXTRHD_TXREN |
+				  ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL),
+};
+
 /*
  * RX Control/Status Bits
  */
@@ -779,6 +822,8 @@ static inline u32 smi_phy_addr(int x)
  */
 enum jme_ghc_bit_mask {
 	GHC_SWRST		= 0x40000000,
+	GHC_TO_CLK_SRC		= 0x00C00000,
+	GHC_TXMAC_CLK_SRC	= 0x00300000,
 	GHC_DPX			= 0x00000040,
 	GHC_SPEED		= 0x00000030,
 	GHC_LINK_POLL		= 0x00000001,
@@ -833,6 +878,21 @@ enum jme_pmcs_bit_masks {
 };
 
 /*
+ * New PHY Power Control Register
+ */
+enum jme_phy_pwr_bit_masks {
+	PHY_PWR_DWN1SEL	= 0x01000000, /* Phy_giga.p_PWR_DOWN1_SEL */
+	PHY_PWR_DWN1SW	= 0x02000000, /* Phy_giga.p_PWR_DOWN1_SW */
+	PHY_PWR_DWN2	= 0x04000000, /* Phy_giga.p_PWR_DOWN2 */
+	PHY_PWR_CLKSEL	= 0x08000000, /*
+				       * XTL_OUT Clock select
+				       * (an internal free-running clock)
+				       * 0: xtl_out = phy_giga.A_XTL25_O
+				       * 1: xtl_out = phy_giga.PD_OSC
+				       */
+};
+
+/*
  * Giga PHY Status Registers
  */
 enum jme_phy_link_bit_mask {
@@ -942,18 +1002,17 @@ enum jme_gpreg0_vals {
 
 /*
  * General Purpose REG-1
- * Note: All theses bits defined here are for
- *       Chip mode revision 0x11 only
  */
-enum jme_gpreg1_masks {
+enum jme_gpreg1_bit_masks {
+	GPREG1_RXCLKOFF		= 0x04000000,
+	GPREG1_PCREQN		= 0x00020000,
+	GPREG1_HALFMODEPATCH	= 0x00000040, /* For Chip revision 0x11 only */
+	GPREG1_RSSPATCH		= 0x00000020, /* For Chip revision 0x11 only */
 	GPREG1_INTRDELAYUNIT	= 0x00000018,
 	GPREG1_INTRDELAYENABLE	= 0x00000007,
 };
 
 enum jme_gpreg1_vals {
-	GPREG1_RSSPATCH		= 0x00000040,
-	GPREG1_HALFMODEPATCH	= 0x00000020,
-
 	GPREG1_INTDLYUNIT_16NS	= 0x00000000,
 	GPREG1_INTDLYUNIT_256NS	= 0x00000008,
 	GPREG1_INTDLYUNIT_1US	= 0x00000010,
@@ -967,7 +1026,7 @@ enum jme_gpreg1_vals {
 	GPREG1_INTDLYEN_6U	= 0x00000006,
 	GPREG1_INTDLYEN_7U	= 0x00000007,
 
-	GPREG1_DEFAULT		= 0x00000000,
+	GPREG1_DEFAULT		= GPREG1_PCREQN,
 };
 
 /*
@@ -1184,16 +1243,22 @@ enum jme_phy_reg17_vals {
 /*
  * Workaround
  */
-static inline int is_buggy250(unsigned short device, unsigned int chiprev)
+static inline int is_buggy250(unsigned short device, u8 chiprev)
 {
 	return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
 }
 
+static inline int new_phy_power_ctrl(u8 chip_main_rev)
+{
+	return chip_main_rev >= 5;
+}
+
 /*
  * Function prototypes
  */
 static int jme_set_settings(struct net_device *netdev,
 				struct ethtool_cmd *ecmd);
+static void jme_set_unicastaddr(struct net_device *netdev);
 static void jme_set_multi(struct net_device *netdev);
 
 #endif
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
index f35554d..b7948cc 100644
--- a/drivers/net/ll_temac_main.c
+++ b/drivers/net/ll_temac_main.c
@@ -952,8 +952,7 @@ static const struct attribute_group temac_attr_group = {
 	.attrs = temac_device_attrs,
 };
 
-static int __devinit
-temac_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit temac_of_probe(struct platform_device *op)
 {
 	struct device_node *np;
 	struct temac_local *lp;
@@ -1123,7 +1122,7 @@ static struct of_device_id temac_of_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, temac_of_match);
 
-static struct of_platform_driver temac_of_driver = {
+static struct platform_driver temac_of_driver = {
 	.probe = temac_of_probe,
 	.remove = __devexit_p(temac_of_remove),
 	.driver = {
@@ -1135,13 +1134,13 @@ static struct of_platform_driver temac_of_driver = {
 
 static int __init temac_init(void)
 {
-	return of_register_platform_driver(&temac_of_driver);
+	return platform_driver_register(&temac_of_driver);
 }
 module_init(temac_init);
 
 static void __exit temac_exit(void)
 {
-	of_unregister_platform_driver(&temac_of_driver);
+	platform_driver_unregister(&temac_of_driver);
 }
 module_exit(temac_exit);
 
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 2d9663a..ea0dc45 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -129,10 +129,6 @@ static u32 always_on(struct net_device *dev)
 
 static const struct ethtool_ops loopback_ethtool_ops = {
 	.get_link		= always_on,
-	.set_tso		= ethtool_op_set_tso,
-	.get_tx_csum		= always_on,
-	.get_sg			= always_on,
-	.get_rx_csum		= always_on,
 };
 
 static int loopback_dev_init(struct net_device *dev)
@@ -169,9 +165,12 @@ static void loopback_setup(struct net_device *dev)
 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
 	dev->flags		= IFF_LOOPBACK;
 	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
+	dev->hw_features	= NETIF_F_ALL_TSO | NETIF_F_UFO;
 	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
-		| NETIF_F_TSO
+		| NETIF_F_ALL_TSO
+		| NETIF_F_UFO
 		| NETIF_F_NO_CSUM
+		| NETIF_F_RXCSUM
 		| NETIF_F_HIGHDMA
 		| NETIF_F_LLTX
 		| NETIF_F_NETNS_LOCAL;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 6ed577b..78e34e9 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -39,8 +39,11 @@ struct macvlan_port {
 	struct list_head	vlans;
 	struct rcu_head		rcu;
 	bool 			passthru;
+	int			count;
 };
 
+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)
@@ -152,9 +155,10 @@ static void macvlan_broadcast(struct sk_buff *skb,
 }
 
 /* called under rcu_read_lock() from netif_receive_skb */
-static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
+static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
 {
 	struct macvlan_port *port;
+	struct sk_buff *skb = *pskb;
 	const struct ethhdr *eth = eth_hdr(skb);
 	const struct macvlan_dev *vlan;
 	const struct macvlan_dev *src;
@@ -184,7 +188,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
 			 */
 			macvlan_broadcast(skb, port, src->dev,
 					  MACVLAN_MODE_VEPA);
-		return skb;
+		return RX_HANDLER_PASS;
 	}
 
 	if (port->passthru)
@@ -192,12 +196,12 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
 	else
 		vlan = macvlan_hash_lookup(port, eth->h_dest);
 	if (vlan == NULL)
-		return skb;
+		return RX_HANDLER_PASS;
 
 	dev = vlan->dev;
 	if (unlikely(!(dev->flags & IFF_UP))) {
 		kfree_skb(skb);
-		return NULL;
+		return RX_HANDLER_CONSUMED;
 	}
 	len = skb->len + ETH_HLEN;
 	skb = skb_share_check(skb, GFP_ATOMIC);
@@ -211,7 +215,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
 
 out:
 	macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0);
-	return NULL;
+	return RX_HANDLER_CONSUMED;
 }
 
 static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -219,9 +223,11 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 	const struct macvlan_dev *vlan = netdev_priv(dev);
 	const struct macvlan_port *port = vlan->port;
 	const struct macvlan_dev *dest;
+	__u8 ip_summed = skb->ip_summed;
 
 	if (vlan->mode == MACVLAN_MODE_BRIDGE) {
 		const struct ethhdr *eth = (void *)skb->data;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		/* send to other bridge ports directly */
 		if (is_multicast_ether_addr(eth->h_dest)) {
@@ -241,6 +247,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
 	}
 
 xmit_world:
+	skb->ip_summed = ip_summed;
 	skb_set_dev(skb, vlan->lowerdev);
 	return dev_queue_xmit(skb);
 }
@@ -453,8 +460,13 @@ static int macvlan_init(struct net_device *dev)
 static void macvlan_uninit(struct net_device *dev)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct macvlan_port *port = vlan->port;
 
 	free_percpu(vlan->pcpu_stats);
+
+	port->count -= 1;
+	if (!port->count)
+		macvlan_port_destroy(port->dev);
 }
 
 static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
@@ -687,12 +699,13 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 		vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
 
 	if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
-		if (!list_empty(&port->vlans))
+		if (port->count)
 			return -EINVAL;
 		port->passthru = true;
 		memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN);
 	}
 
+	port->count += 1;
 	err = register_netdevice(dev);
 	if (err < 0)
 		goto destroy_port;
@@ -703,7 +716,8 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
 	return 0;
 
 destroy_port:
-	if (list_empty(&port->vlans))
+	port->count -= 1;
+	if (!port->count)
 		macvlan_port_destroy(lowerdev);
 
 	return err;
@@ -721,13 +735,9 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
 void macvlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
-	struct macvlan_port *port = vlan->port;
 
 	list_del(&vlan->list);
 	unregister_netdevice_queue(dev, head);
-
-	if (list_empty(&port->vlans))
-		macvlan_port_destroy(port->dev);
 }
 EXPORT_SYMBOL_GPL(macvlan_dellink);
 
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index fc27a99..6696e56 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -39,7 +39,7 @@ struct macvtap_queue {
 	struct socket sock;
 	struct socket_wq wq;
 	int vnet_hdr_sz;
-	struct macvlan_dev *vlan;
+	struct macvlan_dev __rcu *vlan;
 	struct file *file;
 	unsigned int flags;
 };
@@ -141,7 +141,8 @@ static void macvtap_put_queue(struct macvtap_queue *q)
 	struct macvlan_dev *vlan;
 
 	spin_lock(&macvtap_lock);
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_protected(q->vlan,
+					 lockdep_is_held(&macvtap_lock));
 	if (vlan) {
 		int index = get_slot(vlan, q);
 
@@ -219,7 +220,8 @@ static void macvtap_del_queues(struct net_device *dev)
 	/* macvtap_put_queue can free some slots, so go through all slots */
 	spin_lock(&macvtap_lock);
 	for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) {
-		q = rcu_dereference(vlan->taps[i]);
+		q = rcu_dereference_protected(vlan->taps[i],
+					      lockdep_is_held(&macvtap_lock));
 		if (q) {
 			qlist[j++] = q;
 			rcu_assign_pointer(vlan->taps[i], NULL);
@@ -570,7 +572,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
 	}
 
 	rcu_read_lock_bh();
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_bh(q->vlan);
 	if (vlan)
 		macvlan_start_xmit(skb, vlan->dev);
 	else
@@ -584,7 +586,7 @@ err_kfree:
 
 err:
 	rcu_read_lock_bh();
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_bh(q->vlan);
 	if (vlan)
 		vlan->dev->stats.tx_dropped++;
 	rcu_read_unlock_bh();
@@ -632,7 +634,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
 	ret = skb_copy_datagram_const_iovec(skb, 0, iv, vnet_hdr_len, len);
 
 	rcu_read_lock_bh();
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_bh(q->vlan);
 	if (vlan)
 		macvlan_count_rx(vlan, len, ret == 0, 0);
 	rcu_read_unlock_bh();
@@ -728,7 +730,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
 
 	case TUNGETIFF:
 		rcu_read_lock_bh();
-		vlan = rcu_dereference(q->vlan);
+		vlan = rcu_dereference_bh(q->vlan);
 		if (vlan)
 			dev_hold(vlan->dev);
 		rcu_read_unlock_bh();
@@ -737,7 +739,7 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
 			return -ENOLINK;
 
 		ret = 0;
-		if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) ||
+		if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) ||
 		    put_user(q->flags, &ifr->ifr_flags))
 			ret = -EFAULT;
 		dev_put(vlan->dev);
diff --git a/drivers/net/mii.c b/drivers/net/mii.c
index 210b2b1..0a6c6a2 100644
--- a/drivers/net/mii.c
+++ b/drivers/net/mii.c
@@ -354,7 +354,7 @@ unsigned int mii_check_media (struct mii_if_info *mii,
 	if (!new_carrier) {
 		netif_carrier_off(mii->dev);
 		if (ok_to_print)
-			printk(KERN_INFO "%s: link down\n", mii->dev->name);
+			netdev_info(mii->dev, "link down\n");
 		return 0; /* duplex did not change */
 	}
 
@@ -381,12 +381,12 @@ unsigned int mii_check_media (struct mii_if_info *mii,
 		duplex = 1;
 
 	if (ok_to_print)
-		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
-		       mii->dev->name,
-		       lpa2 & (LPA_1000FULL | LPA_1000HALF) ? "1000" :
-		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
-		       duplex ? "full" : "half",
-		       lpa);
+		netdev_info(mii->dev, "link up, %uMbps, %s-duplex, lpa 0x%04X\n",
+			    lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 :
+			    media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
+			    100 : 10,
+			    duplex ? "full" : "half",
+			    lpa);
 
 	if ((init_media) || (mii->full_duplex != duplex)) {
 		mii->full_duplex = duplex;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 02076e1..34425b9 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -35,6 +35,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/in.h>
@@ -627,9 +629,8 @@ err:
 		if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
 			(RX_FIRST_DESC | RX_LAST_DESC)) {
 			if (net_ratelimit())
-				dev_printk(KERN_ERR, &mp->dev->dev,
-					   "received packet spanning "
-					   "multiple descriptors\n");
+				netdev_err(mp->dev,
+					   "received packet spanning multiple descriptors\n");
 		}
 
 		if (cmd_sts & ERROR_SUMMARY)
@@ -868,15 +869,14 @@ static netdev_tx_t mv643xx_eth_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) {
 		txq->tx_dropped++;
-		dev_printk(KERN_DEBUG, &dev->dev,
-			   "failed to linearize skb with tiny "
-			   "unaligned fragment\n");
+		netdev_printk(KERN_DEBUG, dev,
+			      "failed to linearize skb with tiny unaligned fragment\n");
 		return NETDEV_TX_BUSY;
 	}
 
 	if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) {
 		if (net_ratelimit())
-			dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n");
+			netdev_err(dev, "tx queue full?!\n");
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -959,7 +959,7 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force)
 			skb = __skb_dequeue(&txq->tx_skb);
 
 		if (cmd_sts & ERROR_SUMMARY) {
-			dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n");
+			netdev_info(mp->dev, "tx error\n");
 			mp->dev->stats.tx_errors++;
 		}
 
@@ -1122,20 +1122,20 @@ static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
 	int ret;
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
 	writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
 	ret = readl(smi_reg);
 	if (!(ret & SMI_READ_VALID)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus read not valid\n");
+		pr_warn("SMI bus read not valid\n");
 		return -ENODEV;
 	}
 
@@ -1148,7 +1148,7 @@ static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
 	void __iomem *smi_reg = msp->base + SMI_REG;
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
@@ -1156,7 +1156,7 @@ static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
 		(addr << 16) | (val & 0xffff), smi_reg);
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
@@ -1566,9 +1566,8 @@ mv643xx_eth_set_ringparam(struct net_device *dev, struct ethtool_ringparam *er)
 	if (netif_running(dev)) {
 		mv643xx_eth_stop(dev);
 		if (mv643xx_eth_open(dev)) {
-			dev_printk(KERN_ERR, &dev->dev,
-				   "fatal error on re-opening device after "
-				   "ring param change\n");
+			netdev_err(dev,
+				   "fatal error on re-opening device after ring param change\n");
 			return -ENOMEM;
 		}
 	}
@@ -1874,7 +1873,7 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index)
 	}
 
 	if (rxq->rx_desc_area == NULL) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
+		netdev_err(mp->dev,
 			   "can't allocate rx ring (%d bytes)\n", size);
 		goto out;
 	}
@@ -1884,8 +1883,7 @@ static int rxq_init(struct mv643xx_eth_private *mp, int index)
 	rxq->rx_skb = kmalloc(rxq->rx_ring_size * sizeof(*rxq->rx_skb),
 								GFP_KERNEL);
 	if (rxq->rx_skb == NULL) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
-			   "can't allocate rx skb ring\n");
+		netdev_err(mp->dev, "can't allocate rx skb ring\n");
 		goto out_free;
 	}
 
@@ -1944,8 +1942,7 @@ static void rxq_deinit(struct rx_queue *rxq)
 	}
 
 	if (rxq->rx_desc_count) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
-			   "error freeing rx ring -- %d skbs stuck\n",
+		netdev_err(mp->dev, "error freeing rx ring -- %d skbs stuck\n",
 			   rxq->rx_desc_count);
 	}
 
@@ -1987,7 +1984,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index)
 	}
 
 	if (txq->tx_desc_area == NULL) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
+		netdev_err(mp->dev,
 			   "can't allocate tx ring (%d bytes)\n", size);
 		return -ENOMEM;
 	}
@@ -2093,7 +2090,7 @@ static void handle_link_event(struct mv643xx_eth_private *mp)
 		if (netif_carrier_ok(dev)) {
 			int i;
 
-			printk(KERN_INFO "%s: link down\n", dev->name);
+			netdev_info(dev, "link down\n");
 
 			netif_carrier_off(dev);
 
@@ -2124,10 +2121,8 @@ static void handle_link_event(struct mv643xx_eth_private *mp)
 	duplex = (port_status & FULL_DUPLEX) ? 1 : 0;
 	fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0;
 
-	printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
-			 "flow control %sabled\n", dev->name,
-			 speed, duplex ? "full" : "half",
-			 fc ? "en" : "dis");
+	netdev_info(dev, "link up, %d Mb/s, %s duplex, flow control %sabled\n",
+		    speed, duplex ? "full" : "half", fc ? "en" : "dis");
 
 	if (!netif_carrier_ok(dev))
 		netif_carrier_on(dev);
@@ -2337,7 +2332,7 @@ static int mv643xx_eth_open(struct net_device *dev)
 	err = request_irq(dev->irq, mv643xx_eth_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err) {
-		dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
+		netdev_err(dev, "can't assign irq\n");
 		return -EAGAIN;
 	}
 
@@ -2483,9 +2478,8 @@ static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
 	 */
 	mv643xx_eth_stop(dev);
 	if (mv643xx_eth_open(dev)) {
-		dev_printk(KERN_ERR, &dev->dev,
-			   "fatal error on re-opening device after "
-			   "MTU change\n");
+		netdev_err(dev,
+			   "fatal error on re-opening device after MTU change\n");
 	}
 
 	return 0;
@@ -2508,7 +2502,7 @@ static void mv643xx_eth_tx_timeout(struct net_device *dev)
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
 
-	dev_printk(KERN_INFO, &dev->dev, "tx timeout\n");
+	netdev_info(dev, "tx timeout\n");
 
 	schedule_work(&mp->tx_timeout_task);
 }
@@ -2603,8 +2597,8 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 	int ret;
 
 	if (!mv643xx_eth_version_printed++)
-		printk(KERN_NOTICE "MV-643xx 10/100/1000 ethernet "
-			"driver version %s\n", mv643xx_eth_driver_version);
+		pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
+			  mv643xx_eth_driver_version);
 
 	ret = -EINVAL;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2871,14 +2865,12 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 
 	pd = pdev->dev.platform_data;
 	if (pd == NULL) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "no mv643xx_eth_platform_data\n");
+		dev_err(&pdev->dev, "no mv643xx_eth_platform_data\n");
 		return -ENODEV;
 	}
 
 	if (pd->shared == NULL) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "no mv643xx_eth_platform_data->shared\n");
+		dev_err(&pdev->dev, "no mv643xx_eth_platform_data->shared\n");
 		return -ENODEV;
 	}
 
@@ -2957,11 +2949,11 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
 	if (err)
 		goto out;
 
-	dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %pM\n",
-		   mp->port_num, dev->dev_addr);
+	netdev_notice(dev, "port %d with MAC address %pM\n",
+		      mp->port_num, dev->dev_addr);
 
 	if (mp->tx_desc_sram_size > 0)
-		dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n");
+		netdev_notice(dev, "configured with sram\n");
 
 	return 0;
 
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index ea5cfe2..a7f2eed 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -253,7 +253,7 @@ struct myri10ge_priv {
 	unsigned long serial_number;
 	int vendor_specific_offset;
 	int fw_multicast_support;
-	unsigned long features;
+	u32 features;
 	u32 max_tso6;
 	u32 read_dma;
 	u32 write_dma;
@@ -1776,7 +1776,7 @@ static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
 static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
 {
 	struct myri10ge_priv *mgp = netdev_priv(netdev);
-	unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
+	u32 flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
 
 	if (tso_enabled)
 		netdev->features |= flags;
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 4846e13..a761076 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -926,7 +926,7 @@ static const struct net_device_ops myri_ops = {
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-static int __devinit myri_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit myri_sbus_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	static unsigned version_printed;
@@ -1160,7 +1160,7 @@ static const struct of_device_id myri_sbus_match[] = {
 
 MODULE_DEVICE_TABLE(of, myri_sbus_match);
 
-static struct of_platform_driver myri_sbus_driver = {
+static struct platform_driver myri_sbus_driver = {
 	.driver = {
 		.name = "myri",
 		.owner = THIS_MODULE,
@@ -1172,12 +1172,12 @@ static struct of_platform_driver myri_sbus_driver = {
 
 static int __init myri_sbus_init(void)
 {
-	return of_register_platform_driver(&myri_sbus_driver);
+	return platform_driver_register(&myri_sbus_driver);
 }
 
 static void __exit myri_sbus_exit(void)
 {
-	of_unregister_platform_driver(&myri_sbus_driver);
+	platform_driver_unregister(&myri_sbus_driver);
 }
 
 module_init(myri_sbus_init);
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index a113805..d7299f1 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -739,7 +739,8 @@ struct netxen_recv_context {
 #define NX_CDRP_CMD_READ_PEXQ_PARAMETERS	0x0000001c
 #define NX_CDRP_CMD_GET_LIC_CAPABILITIES	0x0000001d
 #define NX_CDRP_CMD_READ_MAX_LRO_PER_BOARD	0x0000001e
-#define NX_CDRP_CMD_MAX				0x0000001f
+#define NX_CDRP_CMD_CONFIG_GBE_PORT		0x0000001f
+#define NX_CDRP_CMD_MAX				0x00000020
 
 #define NX_RCODE_SUCCESS		0
 #define NX_RCODE_NO_HOST_MEM		1
@@ -1054,6 +1055,7 @@ typedef struct {
 #define NX_FW_CAPABILITY_BDG			(1 << 8)
 #define NX_FW_CAPABILITY_FVLANTX		(1 << 9)
 #define NX_FW_CAPABILITY_HW_LRO			(1 << 10)
+#define NX_FW_CAPABILITY_GBE_LINK_CFG		(1 << 11)
 
 /* module types */
 #define LINKEVENT_MODULE_NOT_PRESENT			1
@@ -1349,6 +1351,8 @@ void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup);
 void netxen_pci_camqm_read_2M(struct netxen_adapter *, u64, u64 *);
 void netxen_pci_camqm_write_2M(struct netxen_adapter *, u64, u64);
 
+int nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
+				u32 speed, u32 duplex, u32 autoneg);
 int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
 int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable);
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c
index f7d06cb..f16966a 100644
--- a/drivers/net/netxen/netxen_nic_ctx.c
+++ b/drivers/net/netxen/netxen_nic_ctx.c
@@ -112,6 +112,21 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
 	return 0;
 }
 
+int
+nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
+			u32 speed, u32 duplex, u32 autoneg)
+{
+
+	return netxen_issue_cmd(adapter,
+				adapter->ahw.pci_func,
+				NXHAL_VERSION,
+				speed,
+				duplex,
+				autoneg,
+				NX_CDRP_CMD_CONFIG_GBE_PORT);
+
+}
+
 static int
 nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 {
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index 587498e..653d308 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -214,7 +214,6 @@ skip:
 			check_sfp_module = netif_running(dev) &&
 				adapter->has_link_events;
 		} else {
-			ecmd->autoneg = AUTONEG_ENABLE;
 			ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
 			ecmd->advertising |=
 				(ADVERTISED_TP | ADVERTISED_Autoneg);
@@ -252,53 +251,24 @@ static int
 netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
-	__u32 status;
+	int ret;
 
-	/* read which mode */
-	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
-		/* autonegotiation */
-		if (adapter->phy_write &&
-		    adapter->phy_write(adapter,
-				       NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-				       ecmd->autoneg) != 0)
-			return -EIO;
-		else
-			adapter->link_autoneg = ecmd->autoneg;
+	if (adapter->ahw.port_type != NETXEN_NIC_GBE)
+		return -EOPNOTSUPP;
 
-		if (adapter->phy_read &&
-		    adapter->phy_read(adapter,
-				      NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-				      &status) != 0)
-			return -EIO;
+	if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
+		return -EOPNOTSUPP;
 
-		/* speed */
-		switch (ecmd->speed) {
-		case SPEED_10:
-			netxen_set_phy_speed(status, 0);
-			break;
-		case SPEED_100:
-			netxen_set_phy_speed(status, 1);
-			break;
-		case SPEED_1000:
-			netxen_set_phy_speed(status, 2);
-			break;
-		}
-		/* set duplex mode */
-		if (ecmd->duplex == DUPLEX_HALF)
-			netxen_clear_phy_duplex(status);
-		if (ecmd->duplex == DUPLEX_FULL)
-			netxen_set_phy_duplex(status);
-		if (adapter->phy_write &&
-		    adapter->phy_write(adapter,
-				       NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-				       *((int *)&status)) != 0)
-			return -EIO;
-		else {
-			adapter->link_speed = ecmd->speed;
-			adapter->link_duplex = ecmd->duplex;
-		}
-	} else
+	ret = nx_fw_cmd_set_gbe_port(adapter, ecmd->speed, ecmd->duplex,
+				     ecmd->autoneg);
+	if (ret == NX_RCODE_NOT_SUPPORTED)
 		return -EOPNOTSUPP;
+	else if (ret)
+		return -EIO;
+
+	adapter->link_speed = ecmd->speed;
+	adapter->link_duplex = ecmd->duplex;
+	adapter->link_autoneg = ecmd->autoneg;
 
 	if (!netif_running(dev))
 		return 0;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 33fac32..83348dc 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1032,6 +1032,9 @@ __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev)
 	netif_carrier_off(netdev);
 	netif_tx_disable(netdev);
 
+	if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
+		netxen_linkevent_request(adapter, 0);
+
 	if (adapter->stop_port)
 		adapter->stop_port(adapter);
 
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 9fb59d3..32678b6 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -9501,7 +9501,7 @@ static struct niu_parent * __devinit niu_new_parent(struct niu *np,
 	struct niu_parent *p;
 	int i;
 
-	plat_dev = platform_device_register_simple("niu", niu_parent_index,
+	plat_dev = platform_device_register_simple("niu-board", niu_parent_index,
 						   NULL, 0);
 	if (IS_ERR(plat_dev))
 		return NULL;
@@ -10062,8 +10062,7 @@ static const struct niu_ops niu_phys_ops = {
 	.unmap_single	= niu_phys_unmap_single,
 };
 
-static int __devinit niu_of_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit niu_of_probe(struct platform_device *op)
 {
 	union niu_parent_id parent_id;
 	struct net_device *dev;
@@ -10223,7 +10222,7 @@ static const struct of_device_id niu_match[] = {
 };
 MODULE_DEVICE_TABLE(of, niu_match);
 
-static struct of_platform_driver niu_of_driver = {
+static struct platform_driver niu_of_driver = {
 	.driver = {
 		.name = "niu",
 		.owner = THIS_MODULE,
@@ -10244,14 +10243,14 @@ static int __init niu_init(void)
 	niu_debug = netif_msg_init(debug, NIU_MSG_DEFAULT);
 
 #ifdef CONFIG_SPARC64
-	err = of_register_platform_driver(&niu_of_driver);
+	err = platform_driver_register(&niu_of_driver);
 #endif
 
 	if (!err) {
 		err = pci_register_driver(&niu_pci_driver);
 #ifdef CONFIG_SPARC64
 		if (err)
-			of_unregister_platform_driver(&niu_of_driver);
+			platform_driver_unregister(&niu_of_driver);
 #endif
 	}
 
@@ -10262,7 +10261,7 @@ static void __exit niu_exit(void)
 {
 	pci_unregister_driver(&niu_pci_driver);
 #ifdef CONFIG_SPARC64
-	of_unregister_platform_driver(&niu_of_driver);
+	platform_driver_unregister(&niu_of_driver);
 #endif
 }
 
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
index b99e90a..8c66e22 100644
--- a/drivers/net/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -2446,7 +2446,7 @@ static struct pci_driver pch_gbe_pcidev = {
 	.id_table = pch_gbe_pcidev_id,
 	.probe = pch_gbe_probe,
 	.remove = pch_gbe_remove,
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 	.driver.pm = &pch_gbe_pm_ops,
 #endif
 	.shutdown = pch_gbe_shutdown,
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 35fda5a..392a6c4 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -77,7 +77,6 @@ config NATIONAL_PHY
 	  Currently supports the DP83865 PHY.
 
 config STE10XP
-	depends on PHYLIB
 	tristate "Driver for STMicroelectronics STe10Xp PHYs"
 	---help---
 	  This is the driver for the STe100p and STe101p PHYs.
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index f62c7b7..47c8339a 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -188,8 +188,7 @@ static int __devexit mdio_gpio_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_OF_GPIO
 
-static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev)
 {
 	struct mdio_gpio_platform_data *pdata;
 	struct mii_bus *new_bus;
@@ -240,7 +239,7 @@ static struct of_device_id mdio_ofgpio_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mdio_ofgpio_match);
 
-static struct of_platform_driver mdio_ofgpio_driver = {
+static struct platform_driver mdio_ofgpio_driver = {
 	.driver = {
 		.name = "mdio-gpio",
 		.owner = THIS_MODULE,
@@ -252,12 +251,12 @@ static struct of_platform_driver mdio_ofgpio_driver = {
 
 static inline int __init mdio_ofgpio_init(void)
 {
-	return of_register_platform_driver(&mdio_ofgpio_driver);
+	return platform_driver_register(&mdio_ofgpio_driver);
 }
 
 static inline void __exit mdio_ofgpio_exit(void)
 {
-	of_unregister_platform_driver(&mdio_ofgpio_driver);
+	platform_driver_unregister(&mdio_ofgpio_driver);
 }
 #else
 static inline int __init mdio_ofgpio_init(void) { return 0; }
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 0fd1678..590f902 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -19,13 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/phy.h>
-
-#define	PHY_ID_KSZ9021			0x00221611
-#define	PHY_ID_KS8737			0x00221720
-#define	PHY_ID_KS8041			0x00221510
-#define	PHY_ID_KS8051			0x00221550
-/* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
-#define	PHY_ID_KS8001			0x0022161A
+#include <linux/micrel_phy.h>
 
 /* general Interrupt control/status reg in vendor specific block. */
 #define MII_KSZPHY_INTCS			0x1B
@@ -46,6 +40,7 @@
 #define KSZPHY_CTRL_INT_ACTIVE_HIGH		(1 << 9)
 #define KSZ9021_CTRL_INT_ACTIVE_HIGH		(1 << 14)
 #define KS8737_CTRL_INT_ACTIVE_HIGH		(1 << 14)
+#define KSZ8051_RMII_50MHZ_CLK			(1 << 7)
 
 static int kszphy_ack_interrupt(struct phy_device *phydev)
 {
@@ -106,6 +101,19 @@ static int kszphy_config_init(struct phy_device *phydev)
 	return 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);
+	}
+
+	return 0;
+}
+
 static struct phy_driver ks8737_driver = {
 	.phy_id		= PHY_ID_KS8737,
 	.phy_id_mask	= 0x00fffff0,
@@ -142,7 +150,7 @@ static struct phy_driver ks8051_driver = {
 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
 				| SUPPORTED_Asym_Pause),
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-	.config_init	= kszphy_config_init,
+	.config_init	= ks8051_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index a8445c7..f767033 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -319,7 +319,8 @@ int phy_mii_ioctl(struct phy_device *phydev,
 		/* fall through */
 
 	case SIOCGMIIREG:
-		mii_data->val_out = phy_read(phydev, mii_data->reg_num);
+		mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id,
+						 mii_data->reg_num);
 		break;
 
 	case SIOCSMIIREG:
@@ -350,8 +351,9 @@ int phy_mii_ioctl(struct phy_device *phydev,
 			}
 		}
 
-		phy_write(phydev, mii_data->reg_num, val);
-		
+		mdiobus_write(phydev->bus, mii_data->phy_id,
+			      mii_data->reg_num, val);
+
 		if (mii_data->reg_num == MII_BMCR &&
 		    val & BMCR_RESET &&
 		    phydev->drv->config_init) {
diff --git a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
index 4358330..31e9407 100644
--- a/drivers/net/ppp_deflate.c
+++ b/drivers/net/ppp_deflate.c
@@ -129,7 +129,7 @@ static void *z_comp_alloc(unsigned char *options, int opt_len)
 
 	state->strm.next_in   = NULL;
 	state->w_size         = w_size;
-	state->strm.workspace = vmalloc(zlib_deflate_workspacesize());
+	state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
 	if (state->strm.workspace == NULL)
 		goto out_free;
 
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index c7a6c44..9f6d670 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -592,8 +592,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 			ppp_release(NULL, file);
 			err = 0;
 		} else
-			printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%ld\n",
-			       atomic_long_read(&file->f_count));
+			pr_warn("PPPIOCDETACH file->f_count=%ld\n",
+				atomic_long_read(&file->f_count));
 		mutex_unlock(&ppp_mutex);
 		return err;
 	}
@@ -630,7 +630,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	if (pf->kind != INTERFACE) {
 		/* can't happen */
-		printk(KERN_ERR "PPP: not interface or channel??\n");
+		pr_err("PPP: not interface or channel??\n");
 		return -EINVAL;
 	}
 
@@ -704,7 +704,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		}
 		vj = slhc_init(val2+1, val+1);
 		if (!vj) {
-			printk(KERN_ERR "PPP: no memory (VJ compressor)\n");
+			netdev_err(ppp->dev,
+				   "PPP: no memory (VJ compressor)\n");
 			err = -ENOMEM;
 			break;
 		}
@@ -898,17 +899,17 @@ static int __init ppp_init(void)
 {
 	int err;
 
-	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
+	pr_info("PPP generic driver version " PPP_VERSION "\n");
 
 	err = register_pernet_device(&ppp_net_ops);
 	if (err) {
-		printk(KERN_ERR "failed to register PPP pernet device (%d)\n", err);
+		pr_err("failed to register PPP pernet device (%d)\n", err);
 		goto out;
 	}
 
 	err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
 	if (err) {
-		printk(KERN_ERR "failed to register PPP device (%d)\n", err);
+		pr_err("failed to register PPP device (%d)\n", err);
 		goto out_net;
 	}
 
@@ -1078,7 +1079,7 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
 	new_skb = alloc_skb(new_skb_size, GFP_ATOMIC);
 	if (!new_skb) {
 		if (net_ratelimit())
-			printk(KERN_ERR "PPP: no memory (comp pkt)\n");
+			netdev_err(ppp->dev, "PPP: no memory (comp pkt)\n");
 		return NULL;
 	}
 	if (ppp->dev->hard_header_len > PPP_HDRLEN)
@@ -1108,7 +1109,7 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
 		 * the same number.
 		 */
 		if (net_ratelimit())
-			printk(KERN_ERR "ppp: compressor dropped pkt\n");
+			netdev_err(ppp->dev, "ppp: compressor dropped pkt\n");
 		kfree_skb(skb);
 		kfree_skb(new_skb);
 		new_skb = NULL;
@@ -1138,7 +1139,9 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 		if (ppp->pass_filter &&
 		    sk_run_filter(skb, ppp->pass_filter) == 0) {
 			if (ppp->debug & 1)
-				printk(KERN_DEBUG "PPP: outbound frame not passed\n");
+				netdev_printk(KERN_DEBUG, ppp->dev,
+					      "PPP: outbound frame "
+					      "not passed\n");
 			kfree_skb(skb);
 			return;
 		}
@@ -1164,7 +1167,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 		new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
 				    GFP_ATOMIC);
 		if (!new_skb) {
-			printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n");
+			netdev_err(ppp->dev, "PPP: no memory (VJ comp pkt)\n");
 			goto drop;
 		}
 		skb_reserve(new_skb, ppp->dev->hard_header_len - 2);
@@ -1202,7 +1205,9 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 	    proto != PPP_LCP && proto != PPP_CCP) {
 		if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
 			if (net_ratelimit())
-				printk(KERN_ERR "ppp: compression required but down - pkt dropped.\n");
+				netdev_err(ppp->dev,
+					   "ppp: compression required but "
+					   "down - pkt dropped.\n");
 			goto drop;
 		}
 		skb = pad_compress_skb(ppp, skb);
@@ -1505,7 +1510,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
  noskb:
 	spin_unlock_bh(&pch->downl);
 	if (ppp->debug & 1)
-		printk(KERN_ERR "PPP: no memory (fragment)\n");
+		netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
 	++ppp->dev->stats.tx_errors;
 	++ppp->nxseq;
 	return 1;	/* abandon the frame */
@@ -1686,7 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 			/* copy to a new sk_buff with more tailroom */
 			ns = dev_alloc_skb(skb->len + 128);
 			if (!ns) {
-				printk(KERN_ERR"PPP: no memory (VJ decomp)\n");
+				netdev_err(ppp->dev, "PPP: no memory "
+					   "(VJ decomp)\n");
 				goto err;
 			}
 			skb_reserve(ns, 2);
@@ -1699,7 +1705,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 
 		len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
 		if (len <= 0) {
-			printk(KERN_DEBUG "PPP: VJ decompression error\n");
+			netdev_printk(KERN_DEBUG, ppp->dev,
+				      "PPP: VJ decompression error\n");
 			goto err;
 		}
 		len += 2;
@@ -1721,7 +1728,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 			goto err;
 
 		if (slhc_remember(ppp->vj, skb->data + 2, skb->len - 2) <= 0) {
-			printk(KERN_ERR "PPP: VJ uncompressed error\n");
+			netdev_err(ppp->dev, "PPP: VJ uncompressed error\n");
 			goto err;
 		}
 		proto = PPP_IP;
@@ -1762,8 +1769,9 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 			if (ppp->pass_filter &&
 			    sk_run_filter(skb, ppp->pass_filter) == 0) {
 				if (ppp->debug & 1)
-					printk(KERN_DEBUG "PPP: inbound frame "
-					       "not passed\n");
+					netdev_printk(KERN_DEBUG, ppp->dev,
+						      "PPP: inbound frame "
+						      "not passed\n");
 				kfree_skb(skb);
 				return;
 			}
@@ -1821,7 +1829,8 @@ ppp_decompress_frame(struct ppp *ppp, struct sk_buff *skb)
 
 		ns = dev_alloc_skb(obuff_size);
 		if (!ns) {
-			printk(KERN_ERR "ppp_decompress_frame: no memory\n");
+			netdev_err(ppp->dev, "ppp_decompress_frame: "
+				   "no memory\n");
 			goto err;
 		}
 		/* the decompressor still expects the A/C bytes in the hdr */
@@ -1989,7 +1998,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
 	u32 seq = ppp->nextseq;
 	u32 minseq = ppp->minseq;
 	struct sk_buff_head *list = &ppp->mrq;
-	struct sk_buff *p, *next;
+	struct sk_buff *p, *tmp;
 	struct sk_buff *head, *tail;
 	struct sk_buff *skb = NULL;
 	int lost = 0, len = 0;
@@ -1998,13 +2007,15 @@ ppp_mp_reconstruct(struct ppp *ppp)
 		return NULL;
 	head = list->next;
 	tail = NULL;
-	for (p = head; p != (struct sk_buff *) list; p = next) {
-		next = p->next;
+	skb_queue_walk_safe(list, p, tmp) {
+	again:
 		if (seq_before(PPP_MP_CB(p)->sequence, seq)) {
 			/* this can't happen, anyway ignore the skb */
-			printk(KERN_ERR "ppp_mp_reconstruct bad seq %u < %u\n",
-			       PPP_MP_CB(p)->sequence, seq);
-			head = next;
+			netdev_err(ppp->dev, "ppp_mp_reconstruct bad "
+				   "seq %u < %u\n",
+				   PPP_MP_CB(p)->sequence, seq);
+			__skb_unlink(p, list);
+			kfree_skb(p);
 			continue;
 		}
 		if (PPP_MP_CB(p)->sequence != seq) {
@@ -2016,8 +2027,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
 			lost = 1;
 			seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
 				minseq + 1: PPP_MP_CB(p)->sequence;
-			next = p;
-			continue;
+			goto again;
 		}
 
 		/*
@@ -2042,17 +2052,9 @@ ppp_mp_reconstruct(struct ppp *ppp)
 		    (PPP_MP_CB(head)->BEbits & B)) {
 			if (len > ppp->mrru + 2) {
 				++ppp->dev->stats.rx_length_errors;
-				printk(KERN_DEBUG "PPP: reconstructed packet"
-				       " is too long (%d)\n", len);
-			} else if (p == head) {
-				/* fragment is complete packet - reuse skb */
-				tail = p;
-				skb = skb_get(p);
-				break;
-			} else if ((skb = dev_alloc_skb(len)) == NULL) {
-				++ppp->dev->stats.rx_missed_errors;
-				printk(KERN_DEBUG "PPP: no memory for "
-				       "reconstructed packet");
+				netdev_printk(KERN_DEBUG, ppp->dev,
+					      "PPP: reconstructed packet"
+					      " is too long (%d)\n", len);
 			} else {
 				tail = p;
 				break;
@@ -2065,9 +2067,17 @@ ppp_mp_reconstruct(struct ppp *ppp)
 		 * and we haven't found a complete valid packet yet,
 		 * we can discard up to and including this fragment.
 		 */
-		if (PPP_MP_CB(p)->BEbits & E)
-			head = next;
+		if (PPP_MP_CB(p)->BEbits & E) {
+			struct sk_buff *tmp2;
 
+			skb_queue_reverse_walk_from_safe(list, p, tmp2) {
+				__skb_unlink(p, list);
+				kfree_skb(p);
+			}
+			head = skb_peek(list);
+			if (!head)
+				break;
+		}
 		++seq;
 	}
 
@@ -2077,26 +2087,37 @@ ppp_mp_reconstruct(struct ppp *ppp)
 		   signal a receive error. */
 		if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
 			if (ppp->debug & 1)
-				printk(KERN_DEBUG "  missed pkts %u..%u\n",
-				       ppp->nextseq,
-				       PPP_MP_CB(head)->sequence-1);
+				netdev_printk(KERN_DEBUG, ppp->dev,
+					      "  missed pkts %u..%u\n",
+					      ppp->nextseq,
+					      PPP_MP_CB(head)->sequence-1);
 			++ppp->dev->stats.rx_dropped;
 			ppp_receive_error(ppp);
 		}
 
-		if (head != tail)
-			/* copy to a single skb */
-			for (p = head; p != tail->next; p = p->next)
-				skb_copy_bits(p, 0, skb_put(skb, p->len), p->len);
-		ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
-		head = tail->next;
-	}
+		skb = head;
+		if (head != tail) {
+			struct sk_buff **fragpp = &skb_shinfo(skb)->frag_list;
+			p = skb_queue_next(list, head);
+			__skb_unlink(skb, list);
+			skb_queue_walk_from_safe(list, p, tmp) {
+				__skb_unlink(p, list);
+				*fragpp = p;
+				p->next = NULL;
+				fragpp = &p->next;
+
+				skb->len += p->len;
+				skb->data_len += p->len;
+				skb->truesize += p->len;
+
+				if (p == tail)
+					break;
+			}
+		} else {
+			__skb_unlink(skb, list);
+		}
 
-	/* Discard all the skbuffs that we have copied the data out of
-	   or that we can't use. */
-	while ((p = list->next) != head) {
-		__skb_unlink(p, list);
-		kfree_skb(p);
+		ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
 	}
 
 	return skb;
@@ -2617,8 +2638,8 @@ ppp_create_interface(struct net *net, int unit, int *retp)
 	ret = register_netdev(dev);
 	if (ret != 0) {
 		unit_put(&pn->units_idr, unit);
-		printk(KERN_ERR "PPP: couldn't register device %s (%d)\n",
-		       dev->name, ret);
+		netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n",
+			   dev->name, ret);
 		goto out2;
 	}
 
@@ -2690,9 +2711,9 @@ static void ppp_destroy_interface(struct ppp *ppp)
 
 	if (!ppp->file.dead || ppp->n_channels) {
 		/* "can't happen" */
-		printk(KERN_ERR "ppp: destroying ppp struct %p but dead=%d "
-		       "n_channels=%d !\n", ppp, ppp->file.dead,
-		       ppp->n_channels);
+		netdev_err(ppp->dev, "ppp: destroying ppp struct %p "
+			   "but dead=%d n_channels=%d !\n",
+			   ppp, ppp->file.dead, ppp->n_channels);
 		return;
 	}
 
@@ -2834,8 +2855,7 @@ static void ppp_destroy_channel(struct channel *pch)
 
 	if (!pch->file.dead) {
 		/* "can't happen" */
-		printk(KERN_ERR "ppp: destroying undead channel %p !\n",
-		       pch);
+		pr_err("ppp: destroying undead channel %p !\n", pch);
 		return;
 	}
 	skb_queue_purge(&pch->file.xq);
@@ -2847,7 +2867,7 @@ static void __exit ppp_cleanup(void)
 {
 	/* should never happen */
 	if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
-		printk(KERN_ERR "PPP: removing module but units remain!\n");
+		pr_err("PPP: removing module but units remain!\n");
 	unregister_chrdev(PPP_MAJOR, "ppp");
 	device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
 	class_destroy(ppp_class);
@@ -2865,7 +2885,7 @@ static int __unit_alloc(struct idr *p, void *ptr, int n)
 
 again:
 	if (!idr_pre_get(p, GFP_KERNEL)) {
-		printk(KERN_ERR "PPP: No free memory for idr\n");
+		pr_err("PPP: No free memory for idr\n");
 		return -ENOMEM;
 	}
 
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
index 164cfad..51dfcf8 100644
--- a/drivers/net/pptp.c
+++ b/drivers/net/pptp.c
@@ -175,7 +175,6 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 	struct pptp_opt *opt = &po->proto.pptp;
 	struct pptp_gre_header *hdr;
 	unsigned int header_len = sizeof(*hdr);
-	int err = 0;
 	int islcp;
 	int len;
 	unsigned char *data;
@@ -190,18 +189,14 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
 	if (sk_pppox(po)->sk_state & PPPOX_DEAD)
 		goto tx_error;
 
-	{
-		struct flowi fl = { .oif = 0,
-			.nl_u = {
-				.ip4_u = {
-					.daddr = opt->dst_addr.sin_addr.s_addr,
-					.saddr = opt->src_addr.sin_addr.s_addr,
-					.tos = RT_TOS(0) } },
-			.proto = IPPROTO_GRE };
-		err = ip_route_output_key(&init_net, &rt, &fl);
-		if (err)
-			goto tx_error;
-	}
+	rt = ip_route_output_ports(&init_net, NULL,
+				   opt->dst_addr.sin_addr.s_addr,
+				   opt->src_addr.sin_addr.s_addr,
+				   0, 0, IPPROTO_GRE,
+				   RT_TOS(0), 0);
+	if (IS_ERR(rt))
+		goto tx_error;
+
 	tdev = rt->dst.dev;
 
 	max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
@@ -468,21 +463,17 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
 	po->chan.private = sk;
 	po->chan.ops = &pptp_chan_ops;
 
-	{
-		struct flowi fl = {
-			.nl_u = {
-				.ip4_u = {
-					.daddr = opt->dst_addr.sin_addr.s_addr,
-					.saddr = opt->src_addr.sin_addr.s_addr,
-					.tos = RT_CONN_FLAGS(sk) } },
-			.proto = IPPROTO_GRE };
-		security_sk_classify_flow(sk, &fl);
-		if (ip_route_output_key(&init_net, &rt, &fl)) {
-			error = -EHOSTUNREACH;
-			goto end;
-		}
-		sk_setup_caps(sk, &rt->dst);
+	rt = ip_route_output_ports(&init_net, sk,
+				   opt->dst_addr.sin_addr.s_addr,
+				   opt->src_addr.sin_addr.s_addr,
+				   0, 0,
+				   IPPROTO_GRE, RT_CONN_FLAGS(sk), 0);
+	if (IS_ERR(rt)) {
+		error = -EHOSTUNREACH;
+		goto end;
 	}
+	sk_setup_caps(sk, &rt->dst);
+
 	po->chan.mtu = dst_mtu(&rt->dst);
 	if (!po->chan.mtu)
 		po->chan.mtu = PPP_MTU;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 1a3584e..348b4f1 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -379,7 +379,7 @@ static void fm93c56a_select(struct ql3_adapter *qdev)
 {
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1;
 	ql_write_nvram_reg(qdev, spir, ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
@@ -398,7 +398,7 @@ static void fm93c56a_cmd(struct ql3_adapter *qdev, u32 cmd, u32 eepromAddr)
 	u32 previousBit;
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	/* Clock in a zero, then do the start bit */
 	ql_write_nvram_reg(qdev, spir,
@@ -467,7 +467,7 @@ static void fm93c56a_deselect(struct ql3_adapter *qdev)
 {
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0;
 	ql_write_nvram_reg(qdev, spir, ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
@@ -483,7 +483,7 @@ static void fm93c56a_datain(struct ql3_adapter *qdev, unsigned short *value)
 	u32 dataBit;
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	/* Read the data bits */
 	/* The first bit is a dummy.  Clock right over it. */
@@ -2460,7 +2460,7 @@ map_error:
  * The 3032 supports sglists by using the 3 addr/len pairs (ALP)
  * in the IOCB plus a chain of outbound address lists (OAL) that
  * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th)
- * will used to point to an OAL when more ALP entries are required.
+ * will be used to point to an OAL when more ALP entries are required.
  * The IOCB is always the top of the chain followed by one or more
  * OALs (when necessary).
  */
@@ -3011,7 +3011,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
 	u32 value;
 	struct ql3xxx_port_registers __iomem *port_regs =
 		qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 	struct ql3xxx_host_memory_registers __iomem *hmem_regs =
 		(void __iomem *)port_regs;
 	u32 delay = 10;
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 44e316f..dc44564 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -867,7 +867,6 @@ struct qlcnic_nic_intr_coalesce {
 #define LINKEVENT_LINKSPEED_MBPS	0
 #define LINKEVENT_LINKSPEED_ENCODED	1
 
-#define AUTO_FW_RESET_ENABLED	0x01
 /* firmware response header:
  *	63:58 - message type
  *	57:56 - owner
@@ -1133,14 +1132,10 @@ struct qlcnic_eswitch {
 #define MAX_BW			100	/* % of link speed */
 #define MAX_VLAN_ID		4095
 #define MIN_VLAN_ID		2
-#define MAX_TX_QUEUES		1
-#define MAX_RX_QUEUES		4
 #define DEFAULT_MAC_LEARN	1
 
 #define IS_VALID_VLAN(vlan)	(vlan >= MIN_VLAN_ID && vlan < MAX_VLAN_ID)
 #define IS_VALID_BW(bw)		(bw <= MAX_BW)
-#define IS_VALID_TX_QUEUES(que)	(que > 0 && que <= MAX_TX_QUEUES)
-#define IS_VALID_RX_QUEUES(que)	(que > 0 && que <= MAX_RX_QUEUES)
 
 struct qlcnic_pci_func_cfg {
 	u16	func_type;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 37c04b4..cd88c7e 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -42,7 +42,7 @@ static int use_msi_x = 1;
 module_param(use_msi_x, int, 0444);
 MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
 
-static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
+static int auto_fw_reset = 1;
 module_param(auto_fw_reset, int, 0644);
 MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
 
@@ -2959,8 +2959,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
 		if (adapter->need_fw_reset)
 			goto detach;
 
-		if (adapter->reset_context &&
-		    auto_fw_reset == AUTO_FW_RESET_ENABLED) {
+		if (adapter->reset_context && auto_fw_reset) {
 			qlcnic_reset_hw_context(adapter);
 			adapter->netdev->trans_start = jiffies;
 		}
@@ -2973,7 +2972,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
 
 	qlcnic_dev_request_reset(adapter);
 
-	if ((auto_fw_reset == AUTO_FW_RESET_ENABLED))
+	if (auto_fw_reset)
 		clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
 
 	dev_info(&netdev->dev, "firmware hang detected\n");
@@ -2982,7 +2981,7 @@ detach:
 	adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
 		QLCNIC_DEV_NEED_RESET;
 
-	if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) &&
+	if (auto_fw_reset &&
 		!test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) {
 
 		qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
@@ -3654,10 +3653,8 @@ validate_npar_config(struct qlcnic_adapter *adapter,
 		if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
 			return QL_STATUS_INVALID_PARAM;
 
-		if (!IS_VALID_BW(np_cfg[i].min_bw)
-				|| !IS_VALID_BW(np_cfg[i].max_bw)
-				|| !IS_VALID_RX_QUEUES(np_cfg[i].max_rx_queues)
-				|| !IS_VALID_TX_QUEUES(np_cfg[i].max_tx_queues))
+		if (!IS_VALID_BW(np_cfg[i].min_bw) ||
+		    !IS_VALID_BW(np_cfg[i].max_bw))
 			return QL_STATUS_INVALID_PARAM;
 	}
 	return 0;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 7ffdb80..493b0de 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -37,6 +37,7 @@
 
 #define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
 #define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
+#define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
 
 #ifdef RTL8169_DEBUG
 #define assert(expr) \
@@ -124,6 +125,8 @@ enum mac_version {
 	RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
 	RTL_GIGA_MAC_VER_27 = 0x1b, // 8168DP
 	RTL_GIGA_MAC_VER_28 = 0x1c, // 8168DP
+	RTL_GIGA_MAC_VER_29 = 0x1d, // 8105E
+	RTL_GIGA_MAC_VER_30 = 0x1e, // 8105E
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -161,7 +164,9 @@ static const struct {
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
 	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E
-	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880)  // PCI-E
+	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E
+	_R("RTL8105e",		RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E
+	_R("RTL8105e",		RTL_GIGA_MAC_VER_30, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
@@ -268,9 +273,15 @@ enum rtl8168_8101_registers {
 #define	EPHYAR_REG_MASK			0x1f
 #define	EPHYAR_REG_SHIFT		16
 #define	EPHYAR_DATA_MASK		0xffff
+	DLLPR			= 0xd0,
+#define	PM_SWITCH			(1 << 6)
 	DBG_REG			= 0xd1,
 #define	FIX_NAK_1			(1 << 4)
 #define	FIX_NAK_2			(1 << 3)
+	TWSI			= 0xd2,
+	MCU			= 0xd3,
+#define	EN_NDP				(1 << 3)
+#define	EN_OOB_RESET			(1 << 2)
 	EFUSEAR			= 0xdc,
 #define	EFUSEAR_FLAG			0x80000000
 #define	EFUSEAR_WRITE_CMD		0x80000000
@@ -527,9 +538,6 @@ struct rtl8169_private {
 	u16 napi_event;
 	u16 intr_mask;
 	int phy_1000_ctrl_reg;
-#ifdef CONFIG_R8169_VLAN
-	struct vlan_group *vlgrp;
-#endif
 
 	struct mdio_ops {
 		void (*write)(void __iomem *, int, int);
@@ -541,7 +549,7 @@ struct rtl8169_private {
 		void (*up)(struct rtl8169_private *);
 	} pll_power_ops;
 
-	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
+	int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
 	int (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(struct rtl8169_private *tp);
 	void (*hw_start)(struct net_device *);
@@ -569,6 +577,7 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
 MODULE_FIRMWARE(FIRMWARE_8168D_1);
 MODULE_FIRMWARE(FIRMWARE_8168D_2);
+MODULE_FIRMWARE(FIRMWARE_8105E_1);
 
 static int rtl8169_open(struct net_device *dev);
 static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
@@ -1098,7 +1107,7 @@ static int rtl8169_get_regs_len(struct net_device *dev)
 }
 
 static int rtl8169_set_speed_tbi(struct net_device *dev,
-				 u8 autoneg, u16 speed, u8 duplex)
+				 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1121,17 +1130,30 @@ static int rtl8169_set_speed_tbi(struct net_device *dev,
 }
 
 static int rtl8169_set_speed_xmii(struct net_device *dev,
-				  u8 autoneg, u16 speed, u8 duplex)
+				  u8 autoneg, u16 speed, u8 duplex, u32 adv)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int giga_ctrl, bmcr;
+	int rc = -EINVAL;
+
+	rtl_writephy(tp, 0x1f, 0x0000);
 
 	if (autoneg == AUTONEG_ENABLE) {
 		int auto_nego;
 
 		auto_nego = rtl_readphy(tp, MII_ADVERTISE);
-		auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
-			      ADVERTISE_100HALF | ADVERTISE_100FULL);
+		auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
+				ADVERTISE_100HALF | ADVERTISE_100FULL);
+
+		if (adv & ADVERTISED_10baseT_Half)
+			auto_nego |= ADVERTISE_10HALF;
+		if (adv & ADVERTISED_10baseT_Full)
+			auto_nego |= ADVERTISE_10FULL;
+		if (adv & ADVERTISED_100baseT_Half)
+			auto_nego |= ADVERTISE_100HALF;
+		if (adv & ADVERTISED_100baseT_Full)
+			auto_nego |= ADVERTISE_100FULL;
+
 		auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 
 		giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
@@ -1145,27 +1167,22 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 		    (tp->mac_version != RTL_GIGA_MAC_VER_13) &&
 		    (tp->mac_version != RTL_GIGA_MAC_VER_14) &&
 		    (tp->mac_version != RTL_GIGA_MAC_VER_15) &&
-		    (tp->mac_version != RTL_GIGA_MAC_VER_16)) {
-			giga_ctrl |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
-		} else {
+		    (tp->mac_version != RTL_GIGA_MAC_VER_16) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_29) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_30)) {
+			if (adv & ADVERTISED_1000baseT_Half)
+				giga_ctrl |= ADVERTISE_1000HALF;
+			if (adv & ADVERTISED_1000baseT_Full)
+				giga_ctrl |= ADVERTISE_1000FULL;
+		} else if (adv & (ADVERTISED_1000baseT_Half |
+				  ADVERTISED_1000baseT_Full)) {
 			netif_info(tp, link, dev,
 				   "PHY does not support 1000Mbps\n");
+			goto out;
 		}
 
 		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
 
-		if ((tp->mac_version == RTL_GIGA_MAC_VER_11) ||
-		    (tp->mac_version == RTL_GIGA_MAC_VER_12) ||
-		    (tp->mac_version >= RTL_GIGA_MAC_VER_17)) {
-			/*
-			 * Wake up the PHY.
-			 * Vendor specific (0x1f) and reserved (0x0e) MII
-			 * registers.
-			 */
-			rtl_writephy(tp, 0x1f, 0x0000);
-			rtl_writephy(tp, 0x0e, 0x0000);
-		}
-
 		rtl_writephy(tp, MII_ADVERTISE, auto_nego);
 		rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
 	} else {
@@ -1176,12 +1193,10 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 		else if (speed == SPEED_100)
 			bmcr = BMCR_SPEED100;
 		else
-			return -EINVAL;
+			goto out;
 
 		if (duplex == DUPLEX_FULL)
 			bmcr |= BMCR_FULLDPLX;
-
-		rtl_writephy(tp, 0x1f, 0x0000);
 	}
 
 	tp->phy_1000_ctrl_reg = giga_ctrl;
@@ -1199,16 +1214,18 @@ static int rtl8169_set_speed_xmii(struct net_device *dev,
 		}
 	}
 
-	return 0;
+	rc = 0;
+out:
+	return rc;
 }
 
 static int rtl8169_set_speed(struct net_device *dev,
-			     u8 autoneg, u16 speed, u8 duplex)
+			     u8 autoneg, u16 speed, u8 duplex, u32 advertising)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int ret;
 
-	ret = tp->set_speed(dev, autoneg, speed, duplex);
+	ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
 
 	if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
 		mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
@@ -1223,7 +1240,8 @@ static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	int ret;
 
 	spin_lock_irqsave(&tp->lock, flags);
-	ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
+	ret = rtl8169_set_speed(dev,
+		cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising);
 	spin_unlock_irqrestore(&tp->lock, flags);
 
 	return ret;
@@ -1257,8 +1275,6 @@ static int rtl8169_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
-#ifdef CONFIG_R8169_VLAN
-
 static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
 				      struct sk_buff *skb)
 {
@@ -1266,64 +1282,37 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
 		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
 }
 
-static void rtl8169_vlan_rx_register(struct net_device *dev,
-				     struct vlan_group *grp)
+#define NETIF_F_HW_VLAN_TX_RX	(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX)
+
+static void rtl8169_vlan_mode(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&tp->lock, flags);
-	tp->vlgrp = grp;
-	/*
-	 * Do not disable RxVlan on 8110SCd.
-	 */
-	if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05))
+	if (dev->features & NETIF_F_HW_VLAN_RX)
 		tp->cp_cmd |= RxVlan;
 	else
 		tp->cp_cmd &= ~RxVlan;
 	RTL_W16(CPlusCmd, tp->cp_cmd);
+	/* PCI commit */
 	RTL_R16(CPlusCmd);
 	spin_unlock_irqrestore(&tp->lock, flags);
+
+	dev->vlan_features = dev->features &~ NETIF_F_HW_VLAN_TX_RX;
 }
 
-static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
-			       struct sk_buff *skb, int polling)
+static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
 {
 	u32 opts2 = le32_to_cpu(desc->opts2);
-	struct vlan_group *vlgrp = tp->vlgrp;
-	int ret;
 
-	if (vlgrp && (opts2 & RxVlanTag)) {
-		u16 vtag = swab16(opts2 & 0xffff);
+	if (opts2 & RxVlanTag)
+		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
 
-		if (likely(polling))
-			vlan_gro_receive(&tp->napi, vlgrp, vtag, skb);
-		else
-			__vlan_hwaccel_rx(skb, vlgrp, vtag, polling);
-		ret = 0;
-	} else
-		ret = -1;
 	desc->opts2 = 0;
-	return ret;
 }
 
-#else /* !CONFIG_R8169_VLAN */
-
-static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
-				      struct sk_buff *skb)
-{
-	return 0;
-}
-
-static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
-			       struct sk_buff *skb, int polling)
-{
-	return -1;
-}
-
-#endif
-
 static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -1494,6 +1483,28 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 	}
 }
 
+static int rtl8169_set_flags(struct net_device *dev, u32 data)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned long old_feat = dev->features;
+	int rc;
+
+	if ((tp->mac_version == RTL_GIGA_MAC_VER_05) &&
+	    !(data & ETH_FLAG_RXVLAN)) {
+		netif_info(tp, drv, dev, "8110SCd requires hardware Rx VLAN\n");
+		return -EINVAL;
+	}
+
+	rc = ethtool_op_set_flags(dev, data, ETH_FLAG_TXVLAN | ETH_FLAG_RXVLAN);
+	if (rc)
+		return rc;
+
+	if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX)
+		rtl8169_vlan_mode(dev);
+
+	return 0;
+}
+
 static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
 	.get_regs_len		= rtl8169_get_regs_len,
@@ -1513,6 +1524,8 @@ static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_strings		= rtl8169_get_strings,
 	.get_sset_count		= rtl8169_get_sset_count,
 	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
+	.set_flags		= rtl8169_set_flags,
+	.get_flags		= ethtool_op_get_flags,
 };
 
 static void rtl8169_get_mac_version(struct rtl8169_private *tp,
@@ -1561,6 +1574,9 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 		{ 0x7c800000, 0x30000000,	RTL_GIGA_MAC_VER_11 },
 
 		/* 8101 family. */
+		{ 0x7cf00000, 0x40a00000,	RTL_GIGA_MAC_VER_30 },
+		{ 0x7cf00000, 0x40900000,	RTL_GIGA_MAC_VER_29 },
+		{ 0x7c800000, 0x40800000,	RTL_GIGA_MAC_VER_30 },
 		{ 0x7cf00000, 0x34a00000,	RTL_GIGA_MAC_VER_09 },
 		{ 0x7cf00000, 0x24a00000,	RTL_GIGA_MAC_VER_09 },
 		{ 0x7cf00000, 0x34900000,	RTL_GIGA_MAC_VER_08 },
@@ -2437,6 +2453,33 @@ static void rtl8102e_hw_phy_config(struct rtl8169_private *tp)
 	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
+static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0005 },
+		{ 0x1a, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0004 },
+		{ 0x1c, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x15, 0x7701 },
+		{ 0x1f, 0x0000 }
+	};
+
+	/* Disable ALDPS before ram code */
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x18, 0x0310);
+	msleep(100);
+
+	if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0)
+		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
 static void rtl_hw_phy_config(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -2504,6 +2547,10 @@ static void rtl_hw_phy_config(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_28:
 		rtl8168d_4_hw_phy_config(tp);
 		break;
+	case RTL_GIGA_MAC_VER_29:
+	case RTL_GIGA_MAC_VER_30:
+		rtl8105e_hw_phy_config(tp);
+		break;
 
 	default:
 		break;
@@ -2635,11 +2682,12 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
 
 	rtl8169_phy_reset(dev, tp);
 
-	/*
-	 * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
-	 * only 8101. Don't panic.
-	 */
-	rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
+	rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+		ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+		(tp->mii.supports_gmii ?
+			ADVERTISED_1000baseT_Half |
+			ADVERTISED_1000baseT_Full : 0));
 
 	if (RTL_R8(PHYstatus) & TBI_Enable)
 		netif_info(tp, link, dev, "TBI auto-negotiating\n");
@@ -2795,9 +2843,6 @@ static const struct net_device_ops rtl8169_netdev_ops = {
 	.ndo_set_mac_address	= rtl_set_mac_address,
 	.ndo_do_ioctl		= rtl8169_ioctl,
 	.ndo_set_multicast_list	= rtl_set_rx_mode,
-#ifdef CONFIG_R8169_VLAN
-	.ndo_vlan_rx_register	= rtl8169_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= rtl8169_netpoll,
 #endif
@@ -2952,6 +2997,8 @@ static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
 	case RTL_GIGA_MAC_VER_09:
 	case RTL_GIGA_MAC_VER_10:
 	case RTL_GIGA_MAC_VER_16:
+	case RTL_GIGA_MAC_VER_29:
+	case RTL_GIGA_MAC_VER_30:
 		ops->down	= r810x_pll_power_down;
 		ops->up		= r810x_pll_power_up;
 		break;
@@ -3104,6 +3151,13 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* Identify chip attached to board */
 	rtl8169_get_mac_version(tp, ioaddr);
 
+	/*
+	 * Pretend we are using VLANs; This bypasses a nasty bug where
+	 * Interrupts stop flowing on high load on 8110SCd controllers.
+	 */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+		tp->cp_cmd |= RxVlan;
+
 	rtl_init_mdio_ops(tp);
 	rtl_init_pll_power_ops(tp);
 
@@ -3172,10 +3226,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 	netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
 
-#ifdef CONFIG_R8169_VLAN
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
-	dev->features |= NETIF_F_GRO;
+	dev->features |= NETIF_F_HW_VLAN_TX_RX | NETIF_F_GRO;
 
 	tp->intr_mask = 0xffff;
 	tp->hw_start = cfg->hw_start;
@@ -3293,12 +3344,7 @@ static int rtl8169_open(struct net_device *dev)
 
 	rtl8169_init_phy(dev, tp);
 
-	/*
-	 * Pretend we are using VLANs; This bypasses a nasty bug where
-	 * Interrupts stop flowing on high load on 8110SCd controllers.
-	 */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
-		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+	rtl8169_vlan_mode(dev);
 
 	rtl_pll_power_up(tp);
 
@@ -3915,6 +3961,37 @@ static void rtl_hw_start_8102e_3(void __iomem *ioaddr, struct pci_dev *pdev)
 	rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
 }
 
+static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8105e_1[] = {
+		{ 0x07,	0, 0x4000 },
+		{ 0x19,	0, 0x0200 },
+		{ 0x19,	0, 0x0020 },
+		{ 0x1e,	0, 0x2000 },
+		{ 0x03,	0, 0x0001 },
+		{ 0x19,	0, 0x0100 },
+		{ 0x19,	0, 0x0004 },
+		{ 0x0a,	0, 0x0020 }
+	};
+
+	/* Force LAN exit from ASPM if Rx/Tx are not idel */
+	RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
+
+	/* disable Early Tally Counter */
+	RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
+
+	RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PM_SWITCH);
+
+	rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
+}
+
+static void rtl_hw_start_8105e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	rtl_hw_start_8105e_1(ioaddr, pdev);
+	rtl_ephy_write(ioaddr, 0x1e, rtl_ephy_read(ioaddr, 0x1e) | 0x8000);
+}
+
 static void rtl_hw_start_8101(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -3945,6 +4022,13 @@ static void rtl_hw_start_8101(struct net_device *dev)
 	case RTL_GIGA_MAC_VER_09:
 		rtl_hw_start_8102e_2(ioaddr, pdev);
 		break;
+
+	case RTL_GIGA_MAC_VER_29:
+		rtl_hw_start_8105e_1(ioaddr, pdev);
+		break;
+	case RTL_GIGA_MAC_VER_30:
+		rtl_hw_start_8105e_2(ioaddr, pdev);
+		break;
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -4603,12 +4687,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
 
-			if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
-				if (likely(polling))
-					napi_gro_receive(&tp->napi, skb);
-				else
-					netif_rx(skb);
-			}
+			rtl8169_rx_vlan_tag(desc, skb);
+
+			if (likely(polling))
+				napi_gro_receive(&tp->napi, skb);
+			else
+				netif_rx(skb);
 
 			dev->stats.rx_bytes += pkt_size;
 			dev->stats.rx_packets++;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 39c17ce..2ad6364 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -7556,7 +7556,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
 			 */
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			if (ring_data->lro) {
-				u32 tcp_len;
+				u32 tcp_len = 0;
 				u8 *tcp;
 				int ret = 0;
 
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 002bac7..b8bd936 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2011 Solarflare Communications 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
@@ -21,6 +21,7 @@
 #include <linux/ethtool.h>
 #include <linux/topology.h>
 #include <linux/gfp.h>
+#include <linux/cpu_rmap.h>
 #include "net_driver.h"
 #include "efx.h"
 #include "nic.h"
@@ -307,6 +308,8 @@ static int efx_poll(struct napi_struct *napi, int budget)
 			channel->irq_mod_score = 0;
 		}
 
+		efx_filter_rfs_expire(channel);
+
 		/* There is no race here; although napi_disable() will
 		 * only wait for napi_complete(), this isn't a problem
 		 * since efx_channel_processed() will have no effect if
@@ -673,7 +676,7 @@ static void efx_fini_channels(struct efx_nic *efx)
 
 		efx_for_each_channel_rx_queue(rx_queue, channel)
 			efx_fini_rx_queue(rx_queue);
-		efx_for_each_channel_tx_queue(tx_queue, channel)
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel)
 			efx_fini_tx_queue(tx_queue);
 		efx_fini_eventq(channel);
 	}
@@ -689,7 +692,7 @@ static void efx_remove_channel(struct efx_channel *channel)
 
 	efx_for_each_channel_rx_queue(rx_queue, channel)
 		efx_remove_rx_queue(rx_queue);
-	efx_for_each_channel_tx_queue(tx_queue, channel)
+	efx_for_each_possible_channel_tx_queue(tx_queue, channel)
 		efx_remove_tx_queue(tx_queue);
 	efx_remove_eventq(channel);
 }
@@ -1101,8 +1104,8 @@ static int efx_init_io(struct efx_nic *efx)
 		rc = -EIO;
 		goto fail3;
 	}
-	efx->membase = ioremap_nocache(efx->membase_phys,
-				       efx->type->mem_map_size);
+	efx->membase = ioremap_wc(efx->membase_phys,
+				  efx->type->mem_map_size);
 	if (!efx->membase) {
 		netif_err(efx, probe, efx->net_dev,
 			  "could not map memory BAR at %llx+%x\n",
@@ -1175,10 +1178,32 @@ static int efx_wanted_channels(void)
 	return count;
 }
 
+static int
+efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
+{
+#ifdef CONFIG_RFS_ACCEL
+	int i, rc;
+
+	efx->net_dev->rx_cpu_rmap = alloc_irq_cpu_rmap(efx->n_rx_channels);
+	if (!efx->net_dev->rx_cpu_rmap)
+		return -ENOMEM;
+	for (i = 0; i < efx->n_rx_channels; i++) {
+		rc = irq_cpu_rmap_add(efx->net_dev->rx_cpu_rmap,
+				      xentries[i].vector);
+		if (rc) {
+			free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
+			efx->net_dev->rx_cpu_rmap = NULL;
+			return rc;
+		}
+	}
+#endif
+	return 0;
+}
+
 /* Probe the number and type of interrupts we are able to obtain, and
  * the resulting numbers of channels and RX queues.
  */
-static void efx_probe_interrupts(struct efx_nic *efx)
+static int efx_probe_interrupts(struct efx_nic *efx)
 {
 	int max_channels =
 		min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
@@ -1220,6 +1245,11 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 				efx->n_tx_channels = efx->n_channels;
 				efx->n_rx_channels = efx->n_channels;
 			}
+			rc = efx_init_rx_cpu_rmap(efx, xentries);
+			if (rc) {
+				pci_disable_msix(efx->pci_dev);
+				return rc;
+			}
 			for (i = 0; i < n_channels; i++)
 				efx_get_channel(efx, i)->irq =
 					xentries[i].vector;
@@ -1253,6 +1283,8 @@ static void efx_probe_interrupts(struct efx_nic *efx)
 		efx->n_tx_channels = 1;
 		efx->legacy_irq = efx->pci_dev->irq;
 	}
+
+	return 0;
 }
 
 static void efx_remove_interrupts(struct efx_nic *efx)
@@ -1271,21 +1303,8 @@ static void efx_remove_interrupts(struct efx_nic *efx)
 
 static void efx_set_channels(struct efx_nic *efx)
 {
-	struct efx_channel *channel;
-	struct efx_tx_queue *tx_queue;
-
 	efx->tx_channel_offset =
 		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
-
-	/* Channel pointers were set in efx_init_struct() but we now
-	 * need to clear them for TX queues in any RX-only channels. */
-	efx_for_each_channel(channel, efx) {
-		if (channel->channel - efx->tx_channel_offset >=
-		    efx->n_tx_channels) {
-			efx_for_each_channel_tx_queue(tx_queue, channel)
-				tx_queue->channel = NULL;
-		}
-	}
 }
 
 static int efx_probe_nic(struct efx_nic *efx)
@@ -1302,7 +1321,9 @@ static int efx_probe_nic(struct efx_nic *efx)
 
 	/* Determine the number of channels and queues by trying to hook
 	 * in MSI-X interrupts. */
-	efx_probe_interrupts(efx);
+	rc = efx_probe_interrupts(efx);
+	if (rc)
+		goto fail;
 
 	if (efx->n_channels > 1)
 		get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
@@ -1317,6 +1338,10 @@ static int efx_probe_nic(struct efx_nic *efx)
 	efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
 
 	return 0;
+
+fail:
+	efx->type->remove(efx);
+	return rc;
 }
 
 static void efx_remove_nic(struct efx_nic *efx)
@@ -1531,9 +1556,9 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs,
 	efx->irq_rx_adaptive = rx_adaptive;
 	efx->irq_rx_moderation = rx_ticks;
 	efx_for_each_channel(channel, efx) {
-		if (efx_channel_get_rx_queue(channel))
+		if (efx_channel_has_rx_queue(channel))
 			channel->irq_moderation = rx_ticks;
-		else if (efx_channel_get_tx_queue(channel, 0))
+		else if (efx_channel_has_tx_queues(channel))
 			channel->irq_moderation = tx_ticks;
 	}
 }
@@ -1849,6 +1874,10 @@ static const struct net_device_ops efx_netdev_ops = {
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = efx_netpoll,
 #endif
+	.ndo_setup_tc		= efx_setup_tc,
+#ifdef CONFIG_RFS_ACCEL
+	.ndo_rx_flow_steer	= efx_filter_rfs,
+#endif
 };
 
 static void efx_update_name(struct efx_nic *efx)
@@ -1910,10 +1939,8 @@ static int efx_register_netdev(struct efx_nic *efx)
 
 	efx_for_each_channel(channel, efx) {
 		struct efx_tx_queue *tx_queue;
-		efx_for_each_channel_tx_queue(tx_queue, channel) {
-			tx_queue->core_txq = netdev_get_tx_queue(
-				efx->net_dev, tx_queue->queue / EFX_TXQ_TYPES);
-		}
+		efx_for_each_channel_tx_queue(tx_queue, channel)
+			efx_init_tx_queue_core_txq(tx_queue);
 	}
 
 	/* Always start with carrier off; PHY events will detect the link */
@@ -2288,6 +2315,10 @@ static void efx_fini_struct(struct efx_nic *efx)
  */
 static void efx_pci_remove_main(struct efx_nic *efx)
 {
+#ifdef CONFIG_RFS_ACCEL
+	free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
+	efx->net_dev->rx_cpu_rmap = NULL;
+#endif
 	efx_nic_fini_interrupt(efx);
 	efx_fini_channels(efx);
 	efx_fini_port(efx);
@@ -2401,7 +2432,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
 	int i, rc;
 
 	/* Allocate and initialise a struct net_device and struct efx_nic */
-	net_dev = alloc_etherdev_mq(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES);
+	net_dev = alloc_etherdev_mqs(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES,
+				     EFX_MAX_RX_QUEUES);
 	if (!net_dev)
 		return -ENOMEM;
 	net_dev->features |= (type->offload_features | NETIF_F_SG |
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index d43a7e5..3d83a1f 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -29,6 +29,7 @@
 extern int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
 extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
 extern netdev_tx_t
@@ -36,6 +37,7 @@ efx_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev);
 extern netdev_tx_t
 efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
 
 /* RX */
 extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -74,6 +76,21 @@ extern int efx_filter_remove_filter(struct efx_nic *efx,
 				    struct efx_filter_spec *spec);
 extern void efx_filter_clear_rx(struct efx_nic *efx,
 				enum efx_filter_priority priority);
+#ifdef CONFIG_RFS_ACCEL
+extern int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+			  u16 rxq_index, u32 flow_id);
+extern bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota);
+static inline void efx_filter_rfs_expire(struct efx_channel *channel)
+{
+	if (channel->rfs_filters_added >= 60 &&
+	    __efx_filter_rfs_expire(channel->efx, 100))
+		channel->rfs_filters_added -= 60;
+}
+#define efx_filter_rfs_enabled() 1
+#else
+static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
+#define efx_filter_rfs_enabled() 0
+#endif
 
 /* Channels */
 extern void efx_process_channel_now(struct efx_channel *channel);
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index ca886d9..807178e 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -28,7 +28,8 @@ struct efx_ethtool_stat {
 	enum {
 		EFX_ETHTOOL_STAT_SOURCE_mac_stats,
 		EFX_ETHTOOL_STAT_SOURCE_nic,
-		EFX_ETHTOOL_STAT_SOURCE_channel
+		EFX_ETHTOOL_STAT_SOURCE_channel,
+		EFX_ETHTOOL_STAT_SOURCE_tx_queue
 	} source;
 	unsigned offset;
 	u64(*get_stat) (void *field); /* Reader function */
@@ -86,6 +87,10 @@ static u64 efx_get_atomic_stat(void *field)
 	EFX_ETHTOOL_STAT(field, channel, n_##field,		\
 			 unsigned int, efx_get_uint_stat)
 
+#define EFX_ETHTOOL_UINT_TXQ_STAT(field)			\
+	EFX_ETHTOOL_STAT(tx_##field, tx_queue, field,		\
+			 unsigned int, efx_get_uint_stat)
+
 static struct efx_ethtool_stat efx_ethtool_stats[] = {
 	EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
 	EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
@@ -116,6 +121,10 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
 	EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp),
 	EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error),
 	EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error),
+	EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts),
+	EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers),
+	EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets),
+	EFX_ETHTOOL_UINT_TXQ_STAT(pushes),
 	EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
 	EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
 	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
@@ -237,8 +246,8 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 	strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
 	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
-		siena_print_fwver(efx, info->fw_version,
-				  sizeof(info->fw_version));
+		efx_mcdi_print_fwver(efx, info->fw_version,
+				     sizeof(info->fw_version));
 	strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
@@ -470,6 +479,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
 	struct efx_mac_stats *mac_stats = &efx->mac_stats;
 	struct efx_ethtool_stat *stat;
 	struct efx_channel *channel;
+	struct efx_tx_queue *tx_queue;
 	struct rtnl_link_stats64 temp;
 	int i;
 
@@ -495,6 +505,15 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
 				data[i] += stat->get_stat((void *)channel +
 							  stat->offset);
 			break;
+		case EFX_ETHTOOL_STAT_SOURCE_tx_queue:
+			data[i] = 0;
+			efx_for_each_channel(channel, efx) {
+				efx_for_each_channel_tx_queue(tx_queue, channel)
+					data[i] +=
+						stat->get_stat((void *)tx_queue
+							       + stat->offset);
+			}
+			break;
 		}
 	}
 }
@@ -502,7 +521,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
 static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
 {
 	struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev);
-	unsigned long features;
+	u32 features;
 
 	features = NETIF_F_TSO;
 	if (efx->type->offload_features & NETIF_F_V6_CSUM)
@@ -519,7 +538,7 @@ static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
 static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	unsigned long features = efx->type->offload_features & NETIF_F_ALL_CSUM;
+	u32 features = efx->type->offload_features & NETIF_F_ALL_CSUM;
 
 	if (enable)
 		net_dev->features |= features;
@@ -635,7 +654,7 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev,
 	/* Find lowest IRQ moderation across all used TX queues */
 	coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
 	efx_for_each_channel(channel, efx) {
-		if (!efx_channel_get_tx_queue(channel, 0))
+		if (!efx_channel_has_tx_queues(channel))
 			continue;
 		if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
 			if (channel->channel < efx->n_rx_channels)
@@ -680,8 +699,8 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev,
 
 	/* If the channel is shared only allow RX parameters to be set */
 	efx_for_each_channel(channel, efx) {
-		if (efx_channel_get_rx_queue(channel) &&
-		    efx_channel_get_tx_queue(channel, 0) &&
+		if (efx_channel_has_rx_queue(channel) &&
+		    efx_channel_has_tx_queues(channel) &&
 		    tx_usecs) {
 			netif_err(efx, drv, efx->net_dev, "Channel is shared. "
 				  "Only RX coalescing may be set\n");
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 61ddd2c..734fcfb 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -1478,36 +1478,26 @@ static void falcon_init_rx_cfg(struct efx_nic *efx)
 	/* RX control FIFO thresholds (32 entries) */
 	const unsigned ctrl_xon_thr = 20;
 	const unsigned ctrl_xoff_thr = 25;
-	/* RX data FIFO thresholds (256-byte units; size varies) */
-	int data_xon_thr = efx_nic_rx_xon_thresh >> 8;
-	int data_xoff_thr = efx_nic_rx_xoff_thresh >> 8;
 	efx_oword_t reg;
 
 	efx_reado(efx, &reg, FR_AZ_RX_CFG);
 	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
 		/* Data FIFO size is 5.5K */
-		if (data_xon_thr < 0)
-			data_xon_thr = 512 >> 8;
-		if (data_xoff_thr < 0)
-			data_xoff_thr = 2048 >> 8;
 		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);
-		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, data_xon_thr);
-		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, data_xoff_thr);
+		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);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_TX_TH, ctrl_xoff_thr);
 	} else {
 		/* Data FIFO size is 80K; register fields moved */
-		if (data_xon_thr < 0)
-			data_xon_thr = 27648 >> 8; /* ~3*max MTU */
-		if (data_xoff_thr < 0)
-			data_xoff_thr = 54272 >> 8; /* ~80Kb - 3*max MTU */
 		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_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, data_xon_thr);
-		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, data_xoff_thr);
+		/* 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);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index 2dd16f0..b9cc846 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2009 Solarflare Communications Inc.
+ * Copyright 2007-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index b49e843..2c9ee5d 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c
index d4722c4..95a980f 100644
--- a/drivers/net/sfc/filter.c
+++ b/drivers/net/sfc/filter.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/in.h>
+#include <net/ip.h>
 #include "efx.h"
 #include "filter.h"
 #include "io.h"
@@ -27,6 +28,10 @@
  */
 #define FILTER_CTL_SRCH_MAX 200
 
+/* Don't try very hard to find space for performance hints, as this is
+ * counter-productive. */
+#define FILTER_CTL_SRCH_HINT_MAX 5
+
 enum efx_filter_table_id {
 	EFX_FILTER_TABLE_RX_IP = 0,
 	EFX_FILTER_TABLE_RX_MAC,
@@ -47,6 +52,10 @@ struct efx_filter_table {
 struct efx_filter_state {
 	spinlock_t	lock;
 	struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
+#ifdef CONFIG_RFS_ACCEL
+	u32		*rps_flow_id;
+	unsigned	rps_expire_index;
+#endif
 };
 
 /* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
@@ -325,15 +334,16 @@ static int efx_filter_search(struct efx_filter_table *table,
 			     struct efx_filter_spec *spec, u32 key,
 			     bool for_insert, int *depth_required)
 {
-	unsigned hash, incr, filter_idx, depth;
+	unsigned hash, incr, filter_idx, depth, depth_max;
 	struct efx_filter_spec *cmp;
 
 	hash = efx_filter_hash(key);
 	incr = efx_filter_increment(key);
+	depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ?
+		     FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX);
 
 	for (depth = 1, filter_idx = hash & (table->size - 1);
-	     depth <= FILTER_CTL_SRCH_MAX &&
-		     test_bit(filter_idx, table->used_bitmap);
+	     depth <= depth_max && test_bit(filter_idx, table->used_bitmap);
 	     ++depth) {
 		cmp = &table->spec[filter_idx];
 		if (efx_filter_equal(spec, cmp))
@@ -342,7 +352,7 @@ static int efx_filter_search(struct efx_filter_table *table,
 	}
 	if (!for_insert)
 		return -ENOENT;
-	if (depth > FILTER_CTL_SRCH_MAX)
+	if (depth > depth_max)
 		return -EBUSY;
 found:
 	*depth_required = depth;
@@ -562,6 +572,13 @@ int efx_probe_filters(struct efx_nic *efx)
 	spin_lock_init(&state->lock);
 
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+#ifdef CONFIG_RFS_ACCEL
+		state->rps_flow_id = kcalloc(FR_BZ_RX_FILTER_TBL0_ROWS,
+					     sizeof(*state->rps_flow_id),
+					     GFP_KERNEL);
+		if (!state->rps_flow_id)
+			goto fail;
+#endif
 		table = &state->table[EFX_FILTER_TABLE_RX_IP];
 		table->id = EFX_FILTER_TABLE_RX_IP;
 		table->offset = FR_BZ_RX_FILTER_TBL0;
@@ -607,5 +624,97 @@ void efx_remove_filters(struct efx_nic *efx)
 		kfree(state->table[table_id].used_bitmap);
 		vfree(state->table[table_id].spec);
 	}
+#ifdef CONFIG_RFS_ACCEL
+	kfree(state->rps_flow_id);
+#endif
 	kfree(state);
 }
+
+#ifdef CONFIG_RFS_ACCEL
+
+int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+		   u16 rxq_index, u32 flow_id)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	struct efx_channel *channel;
+	struct efx_filter_state *state = efx->filter_state;
+	struct efx_filter_spec spec;
+	const struct iphdr *ip;
+	const __be16 *ports;
+	int nhoff;
+	int rc;
+
+	nhoff = skb_network_offset(skb);
+
+	if (skb->protocol != htons(ETH_P_IP))
+		return -EPROTONOSUPPORT;
+
+	/* RFS must validate the IP header length before calling us */
+	EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip)));
+	ip = (const struct iphdr *)(skb->data + nhoff);
+	if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+		return -EPROTONOSUPPORT;
+	EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4));
+	ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
+
+	efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index);
+	rc = efx_filter_set_ipv4_full(&spec, ip->protocol,
+				      ip->daddr, ports[1], ip->saddr, ports[0]);
+	if (rc)
+		return rc;
+
+	rc = efx_filter_insert_filter(efx, &spec, true);
+	if (rc < 0)
+		return rc;
+
+	/* Remember this so we can check whether to expire the filter later */
+	state->rps_flow_id[rc] = flow_id;
+	channel = efx_get_channel(efx, skb_get_rx_queue(skb));
+	++channel->rfs_filters_added;
+
+	netif_info(efx, rx_status, efx->net_dev,
+		   "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
+		   (ip->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
+		   &ip->saddr, ntohs(ports[0]), &ip->daddr, ntohs(ports[1]),
+		   rxq_index, flow_id, rc);
+
+	return rc;
+}
+
+bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_IP];
+	unsigned mask = table->size - 1;
+	unsigned index;
+	unsigned stop;
+
+	if (!spin_trylock_bh(&state->lock))
+		return false;
+
+	index = state->rps_expire_index;
+	stop = (index + quota) & mask;
+
+	while (index != stop) {
+		if (test_bit(index, table->used_bitmap) &&
+		    table->spec[index].priority == EFX_FILTER_PRI_HINT &&
+		    rps_may_expire_flow(efx->net_dev,
+					table->spec[index].dmaq_id,
+					state->rps_flow_id[index], index)) {
+			netif_info(efx, rx_status, efx->net_dev,
+				   "expiring filter %d [flow %u]\n",
+				   index, state->rps_flow_id[index]);
+			efx_filter_table_clear_entry(efx, table, index);
+		}
+		index = (index + 1) & mask;
+	}
+
+	state->rps_expire_index = stop;
+	if (table->used == 0)
+		efx_filter_table_reset_search_depth(table);
+
+	spin_unlock_bh(&state->lock);
+	return true;
+}
+
+#endif /* CONFIG_RFS_ACCEL */
diff --git a/drivers/net/sfc/io.h b/drivers/net/sfc/io.h
index 6da4ae2..d9d8c2e 100644
--- a/drivers/net/sfc/io.h
+++ b/drivers/net/sfc/io.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -48,9 +48,9 @@
  *   replacing the low 96 bits with zero does not affect functionality.
  * - If the host writes to the last dword address of such a register
  *   (i.e. the high 32 bits) the underlying register will always be
- *   written.  If the collector does not hold values for the low 96
- *   bits of the register, they will be written as zero.  Writing to
- *   the last qword does not have this effect and must not be done.
+ *   written.  If the collector and the current write together do not
+ *   provide values for all 128 bits of the register, the low 96 bits
+ *   will be written as zero.
  * - If the host writes to the address of any other part of such a
  *   register while the collector already holds values for some other
  *   register, the write is discarded and the collector maintains its
@@ -103,6 +103,7 @@ static inline void efx_writeo(struct efx_nic *efx, efx_oword_t *value,
 	_efx_writed(efx, value->u32[2], reg + 8);
 	_efx_writed(efx, value->u32[3], reg + 12);
 #endif
+	wmb();
 	mmiowb();
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
 }
@@ -125,6 +126,7 @@ static inline void efx_sram_writeq(struct efx_nic *efx, void __iomem *membase,
 	__raw_writel((__force u32)value->u32[0], membase + addr);
 	__raw_writel((__force u32)value->u32[1], membase + addr + 4);
 #endif
+	wmb();
 	mmiowb();
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
 }
@@ -139,6 +141,7 @@ static inline void efx_writed(struct efx_nic *efx, efx_dword_t *value,
 
 	/* No lock required */
 	_efx_writed(efx, value->u32[0], reg);
+	wmb();
 }
 
 /* Read a 128-bit CSR, locking as appropriate. */
@@ -237,12 +240,14 @@ static inline void _efx_writeo_page(struct efx_nic *efx, efx_oword_t *value,
 
 #ifdef EFX_USE_QWORD_IO
 	_efx_writeq(efx, value->u64[0], reg + 0);
+	_efx_writeq(efx, value->u64[1], reg + 8);
 #else
 	_efx_writed(efx, value->u32[0], reg + 0);
 	_efx_writed(efx, value->u32[1], reg + 4);
-#endif
 	_efx_writed(efx, value->u32[2], reg + 8);
 	_efx_writed(efx, value->u32[3], reg + 12);
+#endif
+	wmb();
 }
 #define efx_writeo_page(efx, value, reg, page)				\
 	_efx_writeo_page(efx, value,					\
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c
index b716e82..5e118f0 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/sfc/mcdi.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2008-2009 Solarflare Communications Inc.
+ * Copyright 2008-2011 Solarflare Communications 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
@@ -94,14 +94,15 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
 
 	efx_writed(efx, &hdr, pdu);
 
-	for (i = 0; i < inlen; i += 4)
+	for (i = 0; i < inlen; i += 4) {
 		_efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i);
-
-	/* Ensure the payload is written out before the header */
-	wmb();
+		/* use wmb() within loop to inhibit write combining */
+		wmb();
+	}
 
 	/* ring the doorbell with a distinctive value */
 	_efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
+	wmb();
 }
 
 static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
@@ -602,7 +603,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
  **************************************************************************
  */
 
-int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build)
+void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
 {
 	u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)];
 	size_t outlength;
@@ -616,29 +617,20 @@ int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build)
 	if (rc)
 		goto fail;
 
-	if (outlength == MC_CMD_GET_VERSION_V0_OUT_LEN) {
-		*version = 0;
-		*build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
-		return 0;
-	}
-
 	if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) {
 		rc = -EIO;
 		goto fail;
 	}
 
 	ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
-	*version = (((u64)le16_to_cpu(ver_words[0]) << 48) |
-		    ((u64)le16_to_cpu(ver_words[1]) << 32) |
-		    ((u64)le16_to_cpu(ver_words[2]) << 16) |
-		    le16_to_cpu(ver_words[3]));
-	*build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
-
-	return 0;
+	snprintf(buf, len, "%u.%u.%u.%u",
+		 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
+		 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
+	return;
 
 fail:
 	netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
-	return rc;
+	buf[0] = 0;
 }
 
 int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
diff --git a/drivers/net/sfc/mcdi.h b/drivers/net/sfc/mcdi.h
index c792f1d..aced2a7 100644
--- a/drivers/net/sfc/mcdi.h
+++ b/drivers/net/sfc/mcdi.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2008-2009 Solarflare Communications Inc.
+ * Copyright 2008-2010 Solarflare Communications 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
@@ -93,7 +93,7 @@ extern void efx_mcdi_process_event(struct efx_channel *channel,
 #define MCDI_EVENT_FIELD(_ev, _field)			\
 	EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
 
-extern int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build);
+extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
 extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
 			       bool *was_attached_out);
 extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
diff --git a/drivers/net/sfc/mcdi_mac.c b/drivers/net/sfc/mcdi_mac.c
index f88f4bf..33f7294 100644
--- a/drivers/net/sfc/mcdi_mac.c
+++ b/drivers/net/sfc/mcdi_mac.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2009 Solarflare Communications Inc.
+ * Copyright 2009-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/mcdi_pcol.h b/drivers/net/sfc/mcdi_pcol.h
index 90359e6..b86a15f 100644
--- a/drivers/net/sfc/mcdi_pcol.h
+++ b/drivers/net/sfc/mcdi_pcol.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2009 Solarflare Communications Inc.
+ * Copyright 2009-2011 Solarflare Communications 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
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c
index 0e97eed..ec3f740 100644
--- a/drivers/net/sfc/mcdi_phy.c
+++ b/drivers/net/sfc/mcdi_phy.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2009 Solarflare Communications Inc.
+ * Copyright 2009-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 56b0266..19e68c2 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 Solarflare Communications 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
@@ -51,13 +51,10 @@ int efx_mdio_reset_mmd(struct efx_nic *port, int mmd,
 	return spins ? spins : -ETIMEDOUT;
 }
 
-static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
+static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd)
 {
 	int status;
 
-	if (LOOPBACK_INTERNAL(efx))
-		return 0;
-
 	if (mmd != MDIO_MMD_AN) {
 		/* Read MMD STATUS2 to check it is responding. */
 		status = efx_mdio_read(efx, mmd, MDIO_STAT2);
@@ -68,20 +65,6 @@ static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
 		}
 	}
 
-	/* Read MMD STATUS 1 to check for fault. */
-	status = efx_mdio_read(efx, mmd, MDIO_STAT1);
-	if (status & MDIO_STAT1_FAULT) {
-		if (fault_fatal) {
-			netif_err(efx, hw, efx->net_dev,
-				  "PHY MMD %d reporting fatal"
-				  " fault: status %x\n", mmd, status);
-			return -EIO;
-		} else {
-			netif_dbg(efx, hw, efx->net_dev,
-				  "PHY MMD %d reporting status"
-				  " %x (expected)\n", mmd, status);
-		}
-	}
 	return 0;
 }
 
@@ -130,8 +113,7 @@ int efx_mdio_wait_reset_mmds(struct efx_nic *efx, unsigned int mmd_mask)
 	return rc;
 }
 
-int efx_mdio_check_mmds(struct efx_nic *efx,
-			unsigned int mmd_mask, unsigned int fatal_mask)
+int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask)
 {
 	int mmd = 0, probe_mmd, devs1, devs2;
 	u32 devices;
@@ -161,13 +143,9 @@ int efx_mdio_check_mmds(struct efx_nic *efx,
 
 	/* Check all required MMDs are responding and happy. */
 	while (mmd_mask) {
-		if (mmd_mask & 1) {
-			int fault_fatal = fatal_mask & 1;
-			if (efx_mdio_check_mmd(efx, mmd, fault_fatal))
-				return -EIO;
-		}
+		if ((mmd_mask & 1) && efx_mdio_check_mmd(efx, mmd))
+			return -EIO;
 		mmd_mask = mmd_mask >> 1;
-		fatal_mask = fatal_mask >> 1;
 		mmd++;
 	}
 
@@ -337,7 +315,7 @@ int efx_mdio_test_alive(struct efx_nic *efx)
 			  "no MDIO PHY present with ID %d\n", efx->mdio.prtad);
 		rc = -EINVAL;
 	} else {
-		rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
+		rc = efx_mdio_check_mmds(efx, efx->mdio.mmds);
 	}
 
 	mutex_unlock(&efx->mac_lock);
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 75791d3..df07039 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 Solarflare Communications 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
@@ -68,8 +68,7 @@ extern int efx_mdio_reset_mmd(struct efx_nic *efx, int mmd,
 			      int spins, int spintime);
 
 /* As efx_mdio_check_mmd but for multiple MMDs */
-int efx_mdio_check_mmds(struct efx_nic *efx,
-			unsigned int mmd_mask, unsigned int fatal_mask);
+int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask);
 
 /* Check the link status of specified mmds in bit mask */
 extern bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask);
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c
index d386274..e646bfc 100644
--- a/drivers/net/sfc/mtd.c
+++ b/drivers/net/sfc/mtd.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 28df866..215d5c5 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2011 Solarflare Communications 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
@@ -41,7 +41,7 @@
  *
  **************************************************************************/
 
-#define EFX_DRIVER_VERSION	"3.0"
+#define EFX_DRIVER_VERSION	"3.1"
 
 #ifdef EFX_ENABLE_DEBUG
 #define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@@ -63,10 +63,12 @@
 /* Checksum generation is a per-queue option in hardware, so each
  * queue visible to the networking core is backed by two hardware TX
  * queues. */
-#define EFX_MAX_CORE_TX_QUEUES	EFX_MAX_CHANNELS
-#define EFX_TXQ_TYPE_OFFLOAD	1
-#define EFX_TXQ_TYPES		2
-#define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CORE_TX_QUEUES)
+#define EFX_MAX_TX_TC		2
+#define EFX_MAX_CORE_TX_QUEUES	(EFX_MAX_TX_TC * EFX_MAX_CHANNELS)
+#define EFX_TXQ_TYPE_OFFLOAD	1	/* flag */
+#define EFX_TXQ_TYPE_HIGHPRI	2	/* flag */
+#define EFX_TXQ_TYPES		4
+#define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
 
 /**
  * struct efx_special_buffer - An Efx special buffer
@@ -140,6 +142,7 @@ struct efx_tx_buffer {
  * @buffer: The software buffer ring
  * @txd: The hardware descriptor ring
  * @ptr_mask: The size of the ring minus 1.
+ * @initialised: Has hardware queue been initialised?
  * @flushed: Used when handling queue flushing
  * @read_count: Current read pointer.
  *	This is the number of buffers that have been removed from both rings.
@@ -182,6 +185,7 @@ struct efx_tx_queue {
 	struct efx_tx_buffer *buffer;
 	struct efx_special_buffer txd;
 	unsigned int ptr_mask;
+	bool initialised;
 	enum efx_flush_state flushed;
 
 	/* Members used mainly on the completion path */
@@ -210,15 +214,17 @@ struct efx_tx_queue {
  *	If both this and page are %NULL, the buffer slot is currently free.
  * @page: The associated page buffer, if any.
  *	If both this and skb are %NULL, the buffer slot is currently free.
- * @data: Pointer to ethernet header
  * @len: Buffer length, in bytes.
+ * @is_page: Indicates if @page is valid. If false, @skb is valid.
  */
 struct efx_rx_buffer {
 	dma_addr_t dma_addr;
-	struct sk_buff *skb;
-	struct page *page;
-	char *data;
+	union {
+		struct sk_buff *skb;
+		struct page *page;
+	} u;
 	unsigned int len;
+	bool is_page;
 };
 
 /**
@@ -358,6 +364,9 @@ struct efx_channel {
 
 	unsigned int irq_count;
 	unsigned int irq_mod_score;
+#ifdef CONFIG_RFS_ACCEL
+	unsigned int rfs_filters_added;
+#endif
 
 	int rx_alloc_level;
 	int rx_alloc_push_pages;
@@ -377,7 +386,7 @@ struct efx_channel {
 	bool rx_pkt_csummed;
 
 	struct efx_rx_queue rx_queue;
-	struct efx_tx_queue tx_queue[2];
+	struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
 };
 
 enum efx_led_mode {
@@ -906,7 +915,7 @@ struct efx_nic_type {
 	unsigned int phys_addr_channels;
 	unsigned int tx_dc_base;
 	unsigned int rx_dc_base;
-	unsigned long offload_features;
+	u32 offload_features;
 	u32 reset_world_flags;
 };
 
@@ -938,18 +947,40 @@ efx_get_tx_queue(struct efx_nic *efx, unsigned index, unsigned type)
 	return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
 }
 
+static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
+{
+	return channel->channel - channel->efx->tx_channel_offset <
+		channel->efx->n_tx_channels;
+}
+
 static inline struct efx_tx_queue *
 efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
 {
-	struct efx_tx_queue *tx_queue = channel->tx_queue;
-	EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES);
-	return tx_queue->channel ? tx_queue + type : NULL;
+	EFX_BUG_ON_PARANOID(!efx_channel_has_tx_queues(channel) ||
+			    type >= EFX_TXQ_TYPES);
+	return &channel->tx_queue[type];
+}
+
+static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
+{
+	return !(tx_queue->efx->net_dev->num_tc < 2 &&
+		 tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI);
 }
 
 /* Iterate over all TX queues belonging to a channel */
 #define efx_for_each_channel_tx_queue(_tx_queue, _channel)		\
-	for (_tx_queue = efx_channel_get_tx_queue(channel, 0);		\
-	     _tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
+	if (!efx_channel_has_tx_queues(_channel))			\
+		;							\
+	else								\
+		for (_tx_queue = (_channel)->tx_queue;			\
+		     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES && \
+			     efx_tx_queue_used(_tx_queue);		\
+		     _tx_queue++)
+
+/* Iterate over all possible TX queues belonging to a channel */
+#define efx_for_each_possible_channel_tx_queue(_tx_queue, _channel)	\
+	for (_tx_queue = (_channel)->tx_queue;				\
+	     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES;		\
 	     _tx_queue++)
 
 static inline struct efx_rx_queue *
@@ -959,18 +990,26 @@ efx_get_rx_queue(struct efx_nic *efx, unsigned index)
 	return &efx->channel[index]->rx_queue;
 }
 
+static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
+{
+	return channel->channel < channel->efx->n_rx_channels;
+}
+
 static inline struct efx_rx_queue *
 efx_channel_get_rx_queue(struct efx_channel *channel)
 {
-	return channel->channel < channel->efx->n_rx_channels ?
-		&channel->rx_queue : NULL;
+	EFX_BUG_ON_PARANOID(!efx_channel_has_rx_queue(channel));
+	return &channel->rx_queue;
 }
 
 /* Iterate over all RX queues belonging to a channel */
 #define efx_for_each_channel_rx_queue(_rx_queue, _channel)		\
-	for (_rx_queue = efx_channel_get_rx_queue(channel);		\
-	     _rx_queue;							\
-	     _rx_queue = NULL)
+	if (!efx_channel_has_rx_queue(_channel))			\
+		;							\
+	else								\
+		for (_rx_queue = &(_channel)->rx_queue;			\
+		     _rx_queue;						\
+		     _rx_queue = NULL)
 
 static inline struct efx_channel *
 efx_rx_queue_channel(struct efx_rx_queue *rx_queue)
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c
index da38659..e839661 100644
--- a/drivers/net/sfc/nic.c
+++ b/drivers/net/sfc/nic.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 Solarflare Communications 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
@@ -41,26 +41,6 @@
 #define RX_DC_ENTRIES 64
 #define RX_DC_ENTRIES_ORDER 3
 
-/* RX FIFO XOFF watermark
- *
- * When the amount of the RX FIFO increases used increases past this
- * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A)
- * This also has an effect on RX/TX arbitration
- */
-int efx_nic_rx_xoff_thresh = -1;
-module_param_named(rx_xoff_thresh_bytes, efx_nic_rx_xoff_thresh, int, 0644);
-MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold");
-
-/* RX FIFO XON watermark
- *
- * When the amount of the RX FIFO used decreases below this
- * watermark send XON. Only used if TX flow control is enabled (ethtool -A)
- * This also has an effect on RX/TX arbitration
- */
-int efx_nic_rx_xon_thresh = -1;
-module_param_named(rx_xon_thresh_bytes, efx_nic_rx_xon_thresh, int, 0644);
-MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
-
 /* If EFX_MAX_INT_ERRORS internal errors occur within
  * EFX_INT_ERROR_EXPIRE seconds, we consider the NIC broken and
  * disable it.
@@ -445,8 +425,8 @@ int efx_nic_probe_tx(struct efx_tx_queue *tx_queue)
 
 void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 {
-	efx_oword_t tx_desc_ptr;
 	struct efx_nic *efx = tx_queue->efx;
+	efx_oword_t reg;
 
 	tx_queue->flushed = FLUSH_NONE;
 
@@ -454,7 +434,7 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 	efx_init_special_buffer(efx, &tx_queue->txd);
 
 	/* Push TX descriptor ring to card */
-	EFX_POPULATE_OWORD_10(tx_desc_ptr,
+	EFX_POPULATE_OWORD_10(reg,
 			      FRF_AZ_TX_DESCQ_EN, 1,
 			      FRF_AZ_TX_ISCSI_DDIG_EN, 0,
 			      FRF_AZ_TX_ISCSI_HDIG_EN, 0,
@@ -470,17 +450,15 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
 		int csum = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
-		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
-		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_TCP_CHKSM_DIS,
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_TCP_CHKSM_DIS,
 				    !csum);
 	}
 
-	efx_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+	efx_writeo_table(efx, &reg, efx->type->txd_ptr_tbl_base,
 			 tx_queue->queue);
 
 	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
-		efx_oword_t reg;
-
 		/* Only 128 bits in this register */
 		BUILD_BUG_ON(EFX_MAX_TX_QUEUES > 128);
 
@@ -491,6 +469,16 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 			set_bit_le(tx_queue->queue, (void *)&reg);
 		efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
 	}
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_1(reg,
+				     FRF_BZ_TX_PACE,
+				     (tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+				     FFE_BZ_TX_PACE_OFF :
+				     FFE_BZ_TX_PACE_RESERVED);
+		efx_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL,
+				 tx_queue->queue);
+	}
 }
 
 static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
@@ -1238,8 +1226,10 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 
 	/* Flush all tx queues in parallel */
 	efx_for_each_channel(channel, efx) {
-		efx_for_each_channel_tx_queue(tx_queue, channel)
-			efx_flush_tx_queue(tx_queue);
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->initialised)
+				efx_flush_tx_queue(tx_queue);
+		}
 	}
 
 	/* The hardware supports four concurrent rx flushes, each of which may
@@ -1262,8 +1252,9 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 					++rx_pending;
 				}
 			}
-			efx_for_each_channel_tx_queue(tx_queue, channel) {
-				if (tx_queue->flushed != FLUSH_DONE)
+			efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+				if (tx_queue->initialised &&
+				    tx_queue->flushed != FLUSH_DONE)
 					++tx_pending;
 			}
 		}
@@ -1278,8 +1269,9 @@ int efx_nic_flush_queues(struct efx_nic *efx)
 	/* Mark the queues as all flushed. We're going to return failure
 	 * leading to a reset, or fake up success anyway */
 	efx_for_each_channel(channel, efx) {
-		efx_for_each_channel_tx_queue(tx_queue, channel) {
-			if (tx_queue->flushed != FLUSH_DONE)
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->initialised &&
+			    tx_queue->flushed != FLUSH_DONE)
 				netif_err(efx, hw, efx->net_dev,
 					  "tx queue %d flush command timed out\n",
 					  tx_queue->queue);
@@ -1682,6 +1674,19 @@ void efx_nic_init_common(struct efx_nic *efx)
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
 		EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
 	efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_4(temp,
+				     /* Default values */
+				     FRF_BZ_TX_PACE_SB_NOT_AF, 0x15,
+				     FRF_BZ_TX_PACE_SB_AF, 0xb,
+				     FRF_BZ_TX_PACE_FB_BASE, 0,
+				     /* Allow large pace values in the
+				      * fast bin. */
+				     FRF_BZ_TX_PACE_BIN_TH,
+				     FFE_BZ_TX_PACE_RESERVED);
+		efx_writeo(efx, &temp, FR_BZ_TX_PACE);
+	}
 }
 
 /* Register dump */
diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h
index eb05869..d9de1b6 100644
--- a/drivers/net/sfc/nic.h
+++ b/drivers/net/sfc/nic.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 Solarflare Communications 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
@@ -142,20 +142,14 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
 
 /**
  * struct siena_nic_data - Siena NIC state
- * @fw_version: Management controller firmware version
- * @fw_build: Firmware build number
  * @mcdi: Management-Controller-to-Driver Interface
  * @wol_filter_id: Wake-on-LAN packet filter id
  */
 struct siena_nic_data {
-	u64 fw_version;
-	u32 fw_build;
 	struct efx_mcdi_iface mcdi;
 	int wol_filter_id;
 };
 
-extern void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len);
-
 extern struct efx_nic_type falcon_a1_nic_type;
 extern struct efx_nic_type falcon_b0_nic_type;
 extern struct efx_nic_type siena_a0_nic_type;
@@ -194,7 +188,6 @@ extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
 /* MAC/PHY */
 extern void falcon_drain_tx_fifo(struct efx_nic *efx);
 extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
-extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh;
 
 /* Interrupts and test events */
 extern int efx_nic_init_interrupt(struct efx_nic *efx);
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index 1dab609..b3b7947 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2009 Solarflare Communications Inc.
+ * Copyright 2007-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c
index ea3ae00..55f9092 100644
--- a/drivers/net/sfc/qt202x_phy.c
+++ b/drivers/net/sfc/qt202x_phy.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/regs.h b/drivers/net/sfc/regs.h
index 96430ed..cc2c86b 100644
--- a/drivers/net/sfc/regs.h
+++ b/drivers/net/sfc/regs.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -2907,6 +2907,12 @@
 #define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
 #define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
 
+/* TX_PACE_TBL */
+/* Values >20 are documented as reserved, but will result in a queue going
+ * into the fast bin with a pace value of zero. */
+#define FFE_BZ_TX_PACE_OFF 0
+#define FFE_BZ_TX_PACE_RESERVED 21
+
 /* DRIVER_EV */
 /* Sub-fields of an RX flush completion event */
 #define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 3925fd6..c0fdb59 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2011 Solarflare Communications 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
@@ -89,24 +89,37 @@ static unsigned int rx_refill_limit = 95;
  */
 #define EFX_RXD_HEAD_ROOM 2
 
-static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf)
+/* Offset of ethernet header within page */
+static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
+					     struct efx_rx_buffer *buf)
 {
 	/* Offset is always within one page, so we don't need to consider
 	 * the page order.
 	 */
-	return (__force unsigned long) buf->data & (PAGE_SIZE - 1);
+	return (((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) +
+		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 inline u32 efx_rx_buf_hash(struct efx_rx_buffer *buf)
+static u8 *efx_rx_buf_eh(struct efx_nic *efx, struct efx_rx_buffer *buf)
 {
+	if (buf->is_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);
+}
+
+static inline u32 efx_rx_buf_hash(const u8 *eh)
+{
+	/* The ethernet header is always directly after any hash. */
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || NET_IP_ALIGN % 4 == 0
-	return __le32_to_cpup((const __le32 *)(buf->data - 4));
+	return __le32_to_cpup((const __le32 *)(eh - 4));
 #else
-	const u8 *data = (const u8 *)(buf->data - 4);
+	const u8 *data = eh - 4;
 	return ((u32)data[0]       |
 		(u32)data[1] << 8  |
 		(u32)data[2] << 16 |
@@ -129,6 +142,7 @@ static int efx_init_rx_buffers_skb(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;
 
@@ -136,24 +150,23 @@ static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
 		index = rx_queue->added_count & rx_queue->ptr_mask;
 		rx_buf = efx_rx_buffer(rx_queue, index);
 
-		rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
-		if (unlikely(!rx_buf->skb))
+		rx_buf->u.skb = skb = netdev_alloc_skb(net_dev, skb_len);
+		if (unlikely(!skb))
 			return -ENOMEM;
-		rx_buf->page = NULL;
 
 		/* Adjust the SKB for padding and checksum */
-		skb_reserve(rx_buf->skb, NET_IP_ALIGN);
+		skb_reserve(skb, NET_IP_ALIGN);
 		rx_buf->len = skb_len - NET_IP_ALIGN;
-		rx_buf->data = (char *)rx_buf->skb->data;
-		rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
+		rx_buf->is_page = false;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		rx_buf->dma_addr = pci_map_single(efx->pci_dev,
-						  rx_buf->data, rx_buf->len,
+						  skb->data, rx_buf->len,
 						  PCI_DMA_FROMDEVICE);
 		if (unlikely(pci_dma_mapping_error(efx->pci_dev,
 						   rx_buf->dma_addr))) {
-			dev_kfree_skb_any(rx_buf->skb);
-			rx_buf->skb = NULL;
+			dev_kfree_skb_any(skb);
+			rx_buf->u.skb = NULL;
 			return -EIO;
 		}
 
@@ -211,10 +224,9 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
 		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->skb = NULL;
-		rx_buf->page = page;
-		rx_buf->data = page_addr + EFX_PAGE_IP_ALIGN;
+		rx_buf->u.page = page;
 		rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
+		rx_buf->is_page = true;
 		++rx_queue->added_count;
 		++rx_queue->alloc_page_count;
 		++state->refcnt;
@@ -235,19 +247,17 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
 static void efx_unmap_rx_buffer(struct efx_nic *efx,
 				struct efx_rx_buffer *rx_buf)
 {
-	if (rx_buf->page) {
+	if (rx_buf->is_page && rx_buf->u.page) {
 		struct efx_rx_page_state *state;
 
-		EFX_BUG_ON_PARANOID(rx_buf->skb);
-
-		state = page_address(rx_buf->page);
+		state = page_address(rx_buf->u.page);
 		if (--state->refcnt == 0) {
 			pci_unmap_page(efx->pci_dev,
 				       state->dma_addr,
 				       efx_rx_buf_size(efx),
 				       PCI_DMA_FROMDEVICE);
 		}
-	} else if (likely(rx_buf->skb)) {
+	} else if (!rx_buf->is_page && rx_buf->u.skb) {
 		pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
 				 rx_buf->len, PCI_DMA_FROMDEVICE);
 	}
@@ -256,12 +266,12 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx,
 static void efx_free_rx_buffer(struct efx_nic *efx,
 			       struct efx_rx_buffer *rx_buf)
 {
-	if (rx_buf->page) {
-		__free_pages(rx_buf->page, efx->rx_buffer_order);
-		rx_buf->page = NULL;
-	} else if (likely(rx_buf->skb)) {
-		dev_kfree_skb_any(rx_buf->skb);
-		rx_buf->skb = NULL;
+	if (rx_buf->is_page && rx_buf->u.page) {
+		__free_pages(rx_buf->u.page, efx->rx_buffer_order);
+		rx_buf->u.page = NULL;
+	} else if (!rx_buf->is_page && rx_buf->u.skb) {
+		dev_kfree_skb_any(rx_buf->u.skb);
+		rx_buf->u.skb = NULL;
 	}
 }
 
@@ -277,7 +287,7 @@ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
 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->page);
+	struct efx_rx_page_state *state = page_address(rx_buf->u.page);
 	struct efx_rx_buffer *new_buf;
 	unsigned fill_level, index;
 
@@ -292,16 +302,14 @@ static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
 	}
 
 	++state->refcnt;
-	get_page(rx_buf->page);
+	get_page(rx_buf->u.page);
 
 	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->skb = NULL;
-	new_buf->page = rx_buf->page;
-	new_buf->data = (void *)
-		((__force unsigned long)rx_buf->data ^ (PAGE_SIZE >> 1));
+	new_buf->u.page = rx_buf->u.page;
 	new_buf->len = rx_buf->len;
+	new_buf->is_page = true;
 	++rx_queue->added_count;
 }
 
@@ -315,16 +323,15 @@ static void efx_recycle_rx_buffer(struct efx_channel *channel,
 	struct efx_rx_buffer *new_buf;
 	unsigned index;
 
-	if (rx_buf->page != NULL && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
-	    page_count(rx_buf->page) == 1)
+	if (rx_buf->is_page && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
+	    page_count(rx_buf->u.page) == 1)
 		efx_resurrect_rx_buffer(rx_queue, rx_buf);
 
 	index = rx_queue->added_count & rx_queue->ptr_mask;
 	new_buf = efx_rx_buffer(rx_queue, index);
 
 	memcpy(new_buf, rx_buf, sizeof(*new_buf));
-	rx_buf->page = NULL;
-	rx_buf->skb = NULL;
+	rx_buf->u.page = NULL;
 	++rx_queue->added_count;
 }
 
@@ -428,7 +435,7 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
 		 * data at the end of the skb will be trashed. So
 		 * we have no choice but to leak the fragment.
 		 */
-		*leak_packet = (rx_buf->skb != NULL);
+		*leak_packet = !rx_buf->is_page;
 		efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
 	} else {
 		if (net_ratelimit())
@@ -448,19 +455,18 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
  */
 static void efx_rx_packet_gro(struct efx_channel *channel,
 			      struct efx_rx_buffer *rx_buf,
-			      bool checksummed)
+			      const u8 *eh, bool checksummed)
 {
 	struct napi_struct *napi = &channel->napi_str;
 	gro_result_t gro_result;
 
 	/* Pass the skb/page into the GRO engine */
-	if (rx_buf->page) {
+	if (rx_buf->is_page) {
 		struct efx_nic *efx = channel->efx;
-		struct page *page = rx_buf->page;
+		struct page *page = rx_buf->u.page;
 		struct sk_buff *skb;
 
-		EFX_BUG_ON_PARANOID(rx_buf->skb);
-		rx_buf->page = NULL;
+		rx_buf->u.page = NULL;
 
 		skb = napi_get_frags(napi);
 		if (!skb) {
@@ -469,11 +475,11 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
 		}
 
 		if (efx->net_dev->features & NETIF_F_RXHASH)
-			skb->rxhash = efx_rx_buf_hash(rx_buf);
+			skb->rxhash = efx_rx_buf_hash(eh);
 
 		skb_shinfo(skb)->frags[0].page = page;
 		skb_shinfo(skb)->frags[0].page_offset =
-			efx_rx_buf_offset(rx_buf);
+			efx_rx_buf_offset(efx, rx_buf);
 		skb_shinfo(skb)->frags[0].size = rx_buf->len;
 		skb_shinfo(skb)->nr_frags = 1;
 
@@ -487,11 +493,10 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
 
 		gro_result = napi_gro_frags(napi);
 	} else {
-		struct sk_buff *skb = rx_buf->skb;
+		struct sk_buff *skb = rx_buf->u.skb;
 
-		EFX_BUG_ON_PARANOID(!skb);
 		EFX_BUG_ON_PARANOID(!checksummed);
-		rx_buf->skb = NULL;
+		rx_buf->u.skb = NULL;
 
 		gro_result = napi_gro_receive(napi, skb);
 	}
@@ -513,9 +518,6 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
 	bool leak_packet = false;
 
 	rx_buf = efx_rx_buffer(rx_queue, index);
-	EFX_BUG_ON_PARANOID(!rx_buf->data);
-	EFX_BUG_ON_PARANOID(rx_buf->skb && rx_buf->page);
-	EFX_BUG_ON_PARANOID(!(rx_buf->skb || rx_buf->page));
 
 	/* This allows the refill path to post another buffer.
 	 * EFX_RXD_HEAD_ROOM ensures that the slot we are using
@@ -554,12 +556,12 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
 	/* Prefetch nice and early so data will (hopefully) be in cache by
 	 * the time we look at it.
 	 */
-	prefetch(rx_buf->data);
+	prefetch(efx_rx_buf_eh(efx, rx_buf));
 
 	/* Pipeline receives so that we give time for packet headers to be
 	 * prefetched into cache.
 	 */
-	rx_buf->len = len;
+	rx_buf->len = len - efx->type->rx_buffer_hash_size;
 out:
 	if (channel->rx_pkt)
 		__efx_rx_packet(channel,
@@ -574,45 +576,43 @@ void __efx_rx_packet(struct efx_channel *channel,
 {
 	struct efx_nic *efx = channel->efx;
 	struct sk_buff *skb;
-
-	rx_buf->data += efx->type->rx_buffer_hash_size;
-	rx_buf->len -= efx->type->rx_buffer_hash_size;
+	u8 *eh = efx_rx_buf_eh(efx, 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, rx_buf->data, rx_buf->len);
+		efx_loopback_rx_packet(efx, eh, rx_buf->len);
 		efx_free_rx_buffer(efx, rx_buf);
 		return;
 	}
 
-	if (rx_buf->skb) {
-		prefetch(skb_shinfo(rx_buf->skb));
+	if (!rx_buf->is_page) {
+		skb = rx_buf->u.skb;
 
-		skb_reserve(rx_buf->skb, efx->type->rx_buffer_hash_size);
-		skb_put(rx_buf->skb, rx_buf->len);
+		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)
-			rx_buf->skb->rxhash = efx_rx_buf_hash(rx_buf);
+			skb->rxhash = efx_rx_buf_hash(eh);
 
 		/* Move past the ethernet header. rx_buf->data still points
 		 * at the ethernet header */
-		rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
-						       efx->net_dev);
+		skb->protocol = eth_type_trans(skb, efx->net_dev);
 
-		skb_record_rx_queue(rx_buf->skb, channel->channel);
+		skb_record_rx_queue(skb, channel->channel);
 	}
 
-	if (likely(checksummed || rx_buf->page)) {
-		efx_rx_packet_gro(channel, rx_buf, checksummed);
+	if (likely(checksummed || rx_buf->is_page)) {
+		efx_rx_packet_gro(channel, rx_buf, eh, checksummed);
 		return;
 	}
 
 	/* We now own the SKB */
-	skb = rx_buf->skb;
-	rx_buf->skb = NULL;
-	EFX_BUG_ON_PARANOID(!skb);
+	skb = rx_buf->u.skb;
+	rx_buf->u.skb = NULL;
 
 	/* Set the SKB flags */
 	skb_checksum_none_assert(skb);
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 0ebfb99..a0f49b3 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -644,7 +644,7 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
 			goto out;
 		}
 
-		/* Test both types of TX queue */
+		/* Test all enabled types of TX queue */
 		efx_for_each_channel_tx_queue(tx_queue, channel) {
 			state->offload_csum = (tx_queue->queue &
 					       EFX_TXQ_TYPE_OFFLOAD);
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h
index aed495a..dba5456 100644
--- a/drivers/net/sfc/selftest.h
+++ b/drivers/net/sfc/selftest.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c
index bf84561..e4dd898 100644
--- a/drivers/net/sfc/siena.c
+++ b/drivers/net/sfc/siena.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
@@ -227,13 +227,6 @@ static int siena_probe_nic(struct efx_nic *efx)
 	if (rc)
 		goto fail1;
 
-	rc = efx_mcdi_fwver(efx, &nic_data->fw_version, &nic_data->fw_build);
-	if (rc) {
-		netif_err(efx, probe, efx->net_dev,
-			  "Failed to read MCPU firmware version - rc %d\n", rc);
-		goto fail1; /* MCPU absent? */
-	}
-
 	/* Let the BMC know that the driver is now in charge of link and
 	 * filter settings. We must do this before we reset the NIC */
 	rc = efx_mcdi_drv_attach(efx, true, &already_attached);
@@ -348,11 +341,6 @@ static int siena_init_nic(struct efx_nic *efx)
 	       FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);
 	efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3);
 
-	if (efx_nic_rx_xoff_thresh >= 0 || efx_nic_rx_xon_thresh >= 0)
-		/* No MCDI operation has been defined to set thresholds */
-		netif_err(efx, hw, efx->net_dev,
-			  "ignoring RX flow control thresholds\n");
-
 	/* Enable event logging */
 	rc = efx_mcdi_log_ctrl(efx, true, false, 0);
 	if (rc)
@@ -514,16 +502,6 @@ static void siena_stop_nic_stats(struct efx_nic *efx)
 	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0);
 }
 
-void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len)
-{
-	struct siena_nic_data *nic_data = efx->nic_data;
-	snprintf(buf, len, "%u.%u.%u.%u",
-		 (unsigned int)(nic_data->fw_version >> 48),
-		 (unsigned int)(nic_data->fw_version >> 32 & 0xffff),
-		 (unsigned int)(nic_data->fw_version >> 16 & 0xffff),
-		 (unsigned int)(nic_data->fw_version & 0xffff));
-}
-
 /**************************************************************************
  *
  * Wake on LAN
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h
index 879b7f6..71f2e3e 100644
--- a/drivers/net/sfc/spi.h
+++ b/drivers/net/sfc/spi.h
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005 Fen Systems Ltd.
- * Copyright 2006 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index f102912..efdceb3 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2009 Solarflare Communications Inc.
+ * Copyright 2007-2011 Solarflare Communications 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
@@ -196,7 +196,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
 		if (rc < 0)
 			return rc;
 
-		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
+		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS);
 		if (rc < 0)
 			return rc;
 	}
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c
index 2f5e9da..1398019 100644
--- a/drivers/net/sfc/tx.c
+++ b/drivers/net/sfc/tx.c
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2010 Solarflare Communications 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
@@ -336,17 +336,91 @@ netdev_tx_t efx_hard_start_xmit(struct sk_buff *skb,
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_tx_queue *tx_queue;
+	unsigned index, type;
 
 	if (unlikely(efx->port_inhibited))
 		return NETDEV_TX_BUSY;
 
-	tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb),
-				    skb->ip_summed == CHECKSUM_PARTIAL ?
-				    EFX_TXQ_TYPE_OFFLOAD : 0);
+	index = skb_get_queue_mapping(skb);
+	type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0;
+	if (index >= efx->n_tx_channels) {
+		index -= efx->n_tx_channels;
+		type |= EFX_TXQ_TYPE_HIGHPRI;
+	}
+	tx_queue = efx_get_tx_queue(efx, index, type);
 
 	return efx_enqueue_skb(tx_queue, skb);
 }
 
+void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
+{
+	struct efx_nic *efx = tx_queue->efx;
+
+	/* Must be inverse of queue lookup in efx_hard_start_xmit() */
+	tx_queue->core_txq =
+		netdev_get_tx_queue(efx->net_dev,
+				    tx_queue->queue / EFX_TXQ_TYPES +
+				    ((tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+				     efx->n_tx_channels : 0));
+}
+
+int efx_setup_tc(struct net_device *net_dev, u8 num_tc)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	struct efx_channel *channel;
+	struct efx_tx_queue *tx_queue;
+	unsigned tc;
+	int rc;
+
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0 || num_tc > EFX_MAX_TX_TC)
+		return -EINVAL;
+
+	if (num_tc == net_dev->num_tc)
+		return 0;
+
+	for (tc = 0; tc < num_tc; tc++) {
+		net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
+		net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+	}
+
+	if (num_tc > net_dev->num_tc) {
+		/* Initialise high-priority queues as necessary */
+		efx_for_each_channel(channel, efx) {
+			efx_for_each_possible_channel_tx_queue(tx_queue,
+							       channel) {
+				if (!(tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI))
+					continue;
+				if (!tx_queue->buffer) {
+					rc = efx_probe_tx_queue(tx_queue);
+					if (rc)
+						return rc;
+				}
+				if (!tx_queue->initialised)
+					efx_init_tx_queue(tx_queue);
+				efx_init_tx_queue_core_txq(tx_queue);
+			}
+		}
+	} else {
+		/* Reduce number of classes before number of queues */
+		net_dev->num_tc = num_tc;
+	}
+
+	rc = netif_set_real_num_tx_queues(net_dev,
+					  max_t(int, num_tc, 1) *
+					  efx->n_tx_channels);
+	if (rc)
+		return rc;
+
+	/* Do not destroy high-priority queues when they become
+	 * unused.  We would have to flush them first, and it is
+	 * fairly difficult to flush a subset of TX queues.  Leave
+	 * it to efx_fini_channels().
+	 */
+
+	net_dev->num_tc = num_tc;
+	return 0;
+}
+
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
 {
 	unsigned fill_level;
@@ -430,6 +504,8 @@ void efx_init_tx_queue(struct efx_tx_queue *tx_queue)
 
 	/* Set up TX descriptor ring */
 	efx_nic_init_tx(tx_queue);
+
+	tx_queue->initialised = true;
 }
 
 void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
@@ -452,9 +528,14 @@ void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
 
 void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
 {
+	if (!tx_queue->initialised)
+		return;
+
 	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
 		  "shutting down TX queue %d\n", tx_queue->queue);
 
+	tx_queue->initialised = false;
+
 	/* Flush TX queue, remove descriptor ring */
 	efx_nic_fini_tx(tx_queue);
 
@@ -466,6 +547,9 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
 
 void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
 {
+	if (!tx_queue->buffer)
+		return;
+
 	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
 		  "destroying TX queue %d\n", tx_queue->queue);
 	efx_nic_remove_tx(tx_queue);
diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/sfc/txc43128_phy.c
index 351794a..d9886ad 100644
--- a/drivers/net/sfc/txc43128_phy.c
+++ b/drivers/net/sfc/txc43128_phy.c
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2010 Solarflare Communications Inc.
+ * Copyright 2006-2011 Solarflare Communications 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
@@ -193,7 +193,7 @@ static int txc_reset_phy(struct efx_nic *efx)
 		goto fail;
 
 	/* Check that all the MMDs we expect are present and responding. */
-	rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
+	rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS);
 	if (rc < 0)
 		goto fail;
 
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index e0d6308..e4dd3a7 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 Solarflare Communications 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
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 819c175..e9e7a53 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -32,35 +32,40 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/ethtool.h>
 #include <asm/cacheflush.h>
 
 #include "sh_eth.h"
 
+#define SH_ETH_DEF_MSG_ENABLE \
+		(NETIF_MSG_LINK	| \
+		NETIF_MSG_TIMER	| \
+		NETIF_MSG_RX_ERR| \
+		NETIF_MSG_TX_ERR)
+
 /* There is CPU dependent code */
 #if 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);
-	u32 ioaddr = ndev->base_addr;
 
 	if (mdp->duplex) /* Full */
-		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
 	else		/* Half */
-		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		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);
-	u32 ioaddr = ndev->base_addr;
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		writel(readl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
 		break;
 	case 100:/* 100BASE */
-		writel(readl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
 		break;
 	default:
 		break;
@@ -89,29 +94,28 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
 };
 #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-#define SH_ETH_RESET_DEFAULT	1
+#define SH_ETH_HAS_BOTH_MODULES	1
+#define SH_ETH_HAS_TSU	1
 static void sh_eth_set_duplex(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 
 	if (mdp->duplex) /* Full */
-		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
 	else		/* Half */
-		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		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);
-	u32 ioaddr = ndev->base_addr;
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		writel(0, ioaddr + RTRATE);
+		sh_eth_write(ndev, 0, RTRATE);
 		break;
 	case 100:/* 100BASE */
-		writel(1, ioaddr + RTRATE);
+		sh_eth_write(ndev, 1, RTRATE);
 		break;
 	default:
 		break;
@@ -138,24 +142,154 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 	.no_ade		= 1,
 };
 
+#define SH_GIGA_ETH_BASE	0xfee00000
+#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
+#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
+static void sh_eth_chip_reset_giga(struct net_device *ndev)
+{
+	int i;
+	unsigned long mahr[2], malr[2];
+
+	/* save MAHR and MALR */
+	for (i = 0; i < 2; i++) {
+		malr[i] = readl(GIGA_MALR(i));
+		mahr[i] = readl(GIGA_MAHR(i));
+	}
+
+	/* reset device */
+	writel(ARSTR_ARSTR, SH_GIGA_ETH_BASE + 0x1800);
+	mdelay(1);
+
+	/* restore MAHR and MALR */
+	for (i = 0; i < 2; i++) {
+		writel(malr[i], GIGA_MALR(i));
+		writel(mahr[i], GIGA_MAHR(i));
+	}
+}
+
+static int sh_eth_is_gether(struct sh_eth_private *mdp);
+static void sh_eth_reset(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int cnt = 100;
+
+	if (sh_eth_is_gether(mdp)) {
+		sh_eth_write(ndev, 0x03, EDSR);
+		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
+				EDMR);
+		while (cnt > 0) {
+			if (!(sh_eth_read(ndev, EDMR) & 0x3))
+				break;
+			mdelay(1);
+			cnt--;
+		}
+		if (cnt < 0)
+			printk(KERN_ERR "Device reset fail\n");
+
+		/* Table Init */
+		sh_eth_write(ndev, 0x0, TDLAR);
+		sh_eth_write(ndev, 0x0, TDFAR);
+		sh_eth_write(ndev, 0x0, TDFXR);
+		sh_eth_write(ndev, 0x0, TDFFR);
+		sh_eth_write(ndev, 0x0, RDLAR);
+		sh_eth_write(ndev, 0x0, RDFAR);
+		sh_eth_write(ndev, 0x0, RDFXR);
+		sh_eth_write(ndev, 0x0, RDFFR);
+	} else {
+		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
+				EDMR);
+		mdelay(3);
+		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
+				EDMR);
+	}
+}
+
+static void sh_eth_set_duplex_giga(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_giga(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	switch (mdp->speed) {
+	case 10: /* 10BASE */
+		sh_eth_write(ndev, 0x00000000, GECMR);
+		break;
+	case 100:/* 100BASE */
+		sh_eth_write(ndev, 0x00000010, GECMR);
+		break;
+	case 1000: /* 1000BASE */
+		sh_eth_write(ndev, 0x00000020, GECMR);
+		break;
+	default:
+		break;
+	}
+}
+
+/* SH7757(GETHERC) */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
+	.chip_reset	= sh_eth_chip_reset_giga,
+	.set_duplex	= sh_eth_set_duplex_giga,
+	.set_rate	= sh_eth_set_rate_giga,
+
+	.ecsr_value	= ECSR_ICD | ECSR_MPD,
+	.ecsipr_value	= ECSIPR_LCHNGIP | ECSIPR_ICDIP | ECSIPR_MPDIP,
+	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+
+	.tx_check	= EESR_TC1 | EESR_FTC,
+	.eesr_err_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \
+			  EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \
+			  EESR_ECI,
+	.tx_error_check	= EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \
+			  EESR_TFE,
+	.fdr_value	= 0x0000072f,
+	.rmcr_value	= 0x00000001,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.bculr		= 1,
+	.hw_swap	= 1,
+	.rpadir		= 1,
+	.rpadir_value   = 2 << 16,
+	.no_trimd	= 1,
+	.no_ade		= 1,
+};
+
+static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
+{
+	if (sh_eth_is_gether(mdp))
+		return &sh_eth_my_cpu_data_giga;
+	else
+		return &sh_eth_my_cpu_data;
+}
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 #define SH_ETH_HAS_TSU	1
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
 	/* reset device */
-	writel(ARSTR_ARSTR, ARSTR);
+	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
 	mdelay(1);
 }
 
 static void sh_eth_reset(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
 	int cnt = 100;
 
-	writel(EDSR_ENALL, ioaddr + EDSR);
-	writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	sh_eth_write(ndev, EDSR_ENALL, EDSR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
 	while (cnt > 0) {
-		if (!(readl(ioaddr + EDMR) & 0x3))
+		if (!(sh_eth_read(ndev, EDMR) & 0x3))
 			break;
 		mdelay(1);
 		cnt--;
@@ -164,41 +298,39 @@ static void sh_eth_reset(struct net_device *ndev)
 		printk(KERN_ERR "Device reset fail\n");
 
 	/* Table Init */
-	writel(0x0, ioaddr + TDLAR);
-	writel(0x0, ioaddr + TDFAR);
-	writel(0x0, ioaddr + TDFXR);
-	writel(0x0, ioaddr + TDFFR);
-	writel(0x0, ioaddr + RDLAR);
-	writel(0x0, ioaddr + RDFAR);
-	writel(0x0, ioaddr + RDFXR);
-	writel(0x0, ioaddr + RDFFR);
+	sh_eth_write(ndev, 0x0, TDLAR);
+	sh_eth_write(ndev, 0x0, TDFAR);
+	sh_eth_write(ndev, 0x0, TDFXR);
+	sh_eth_write(ndev, 0x0, TDFFR);
+	sh_eth_write(ndev, 0x0, RDLAR);
+	sh_eth_write(ndev, 0x0, RDFAR);
+	sh_eth_write(ndev, 0x0, RDFXR);
+	sh_eth_write(ndev, 0x0, RDFFR);
 }
 
 static void sh_eth_set_duplex(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 
 	if (mdp->duplex) /* Full */
-		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
 	else		/* Half */
-		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		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);
-	u32 ioaddr = ndev->base_addr;
 
 	switch (mdp->speed) {
 	case 10: /* 10BASE */
-		writel(GECMR_10, ioaddr + GECMR);
+		sh_eth_write(ndev, GECMR_10, GECMR);
 		break;
 	case 100:/* 100BASE */
-		writel(GECMR_100, ioaddr + GECMR);
+		sh_eth_write(ndev, GECMR_100, GECMR);
 		break;
 	case 1000: /* 1000BASE */
-		writel(GECMR_1000, ioaddr + GECMR);
+		sh_eth_write(ndev, GECMR_1000, GECMR);
 		break;
 	default:
 		break;
@@ -229,6 +361,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 	.hw_swap	= 1,
 	.no_trimd	= 1,
 	.no_ade		= 1,
+	.tsu		= 1,
 };
 
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
@@ -246,6 +379,7 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 #define SH_ETH_HAS_TSU	1
 static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
 	.eesipr_value	= DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff,
+	.tsu		= 1,
 };
 #endif
 
@@ -281,11 +415,9 @@ static void sh_eth_set_default_cpu_data(struct sh_eth_cpu_data *cd)
 /* Chip Reset */
 static void sh_eth_reset(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
-
-	writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
 	mdelay(3);
-	writel(readl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
 }
 #endif
 
@@ -334,13 +466,11 @@ static inline __u32 edmac_to_cpu(struct sh_eth_private *mdp, u32 x)
  */
 static void update_mac_address(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
-
-	writel((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
-		  (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]),
-		  ioaddr + MAHR);
-	writel((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]),
-		  ioaddr + MALR);
+	sh_eth_write(ndev,
+		(ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
+		(ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
+	sh_eth_write(ndev,
+		(ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
 }
 
 /*
@@ -353,21 +483,36 @@ static void update_mac_address(struct net_device *ndev)
  */
 static void read_mac_address(struct net_device *ndev, unsigned char *mac)
 {
-	u32 ioaddr = ndev->base_addr;
-
 	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
 		memcpy(ndev->dev_addr, mac, 6);
 	} else {
-		ndev->dev_addr[0] = (readl(ioaddr + MAHR) >> 24);
-		ndev->dev_addr[1] = (readl(ioaddr + MAHR) >> 16) & 0xFF;
-		ndev->dev_addr[2] = (readl(ioaddr + MAHR) >> 8) & 0xFF;
-		ndev->dev_addr[3] = (readl(ioaddr + MAHR) & 0xFF);
-		ndev->dev_addr[4] = (readl(ioaddr + MALR) >> 8) & 0xFF;
-		ndev->dev_addr[5] = (readl(ioaddr + MALR) & 0xFF);
+		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
+		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
+		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
+		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
+		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
+		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
 	}
 }
 
+static int sh_eth_is_gether(struct sh_eth_private *mdp)
+{
+	if (mdp->reg_offset == sh_eth_offset_gigabit)
+		return 1;
+	else
+		return 0;
+}
+
+static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
+{
+	if (sh_eth_is_gether(mdp))
+		return EDTRR_TRNS_GETHER;
+	else
+		return EDTRR_TRNS_ETHER;
+}
+
 struct bb_info {
+	void (*set_gate)(unsigned long addr);
 	struct mdiobb_ctrl ctrl;
 	u32 addr;
 	u32 mmd_msk;/* MMD */
@@ -398,6 +543,10 @@ static int bb_read(u32 addr, u32 msk)
 static void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	if (bit)
 		bb_set(bitbang->addr, bitbang->mmd_msk);
 	else
@@ -409,6 +558,9 @@ static void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
 
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	if (bit)
 		bb_set(bitbang->addr, bitbang->mdo_msk);
 	else
@@ -419,6 +571,10 @@ static void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
 static int sh_get_mdio(struct mdiobb_ctrl *ctrl)
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	return bb_read(bitbang->addr, bitbang->mdi_msk);
 }
 
@@ -427,6 +583,9 @@ static void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
 
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	if (bit)
 		bb_set(bitbang->addr, bitbang->mdc_msk);
 	else
@@ -470,7 +629,6 @@ static void sh_eth_ring_free(struct net_device *ndev)
 /* format skb and descriptor buffer */
 static void sh_eth_ring_format(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
@@ -506,10 +664,9 @@ static void sh_eth_ring_format(struct net_device *ndev)
 		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
 		/* Rx descriptor address set */
 		if (i == 0) {
-			writel(mdp->rx_desc_dma, ioaddr + RDLAR);
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			writel(mdp->rx_desc_dma, ioaddr + RDFAR);
-#endif
+			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
+			if (sh_eth_is_gether(mdp))
+				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
 		}
 	}
 
@@ -528,10 +685,9 @@ static void sh_eth_ring_format(struct net_device *ndev)
 		txdesc->buffer_length = 0;
 		if (i == 0) {
 			/* Tx descriptor address set */
-			writel(mdp->tx_desc_dma, ioaddr + TDLAR);
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			writel(mdp->tx_desc_dma, ioaddr + TDFAR);
-#endif
+			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
+			if (sh_eth_is_gether(mdp))
+				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
 		}
 	}
 
@@ -613,7 +769,6 @@ static int sh_eth_dev_init(struct net_device *ndev)
 {
 	int ret = 0;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	u_int32_t rx_int_var, tx_int_var;
 	u32 val;
 
@@ -623,71 +778,71 @@ static int sh_eth_dev_init(struct net_device *ndev)
 	/* Descriptor format */
 	sh_eth_ring_format(ndev);
 	if (mdp->cd->rpadir)
-		writel(mdp->cd->rpadir_value, ioaddr + RPADIR);
+		sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR);
 
 	/* all sh_eth int mask */
-	writel(0, ioaddr + EESIPR);
+	sh_eth_write(ndev, 0, EESIPR);
 
 #if defined(__LITTLE_ENDIAN__)
 	if (mdp->cd->hw_swap)
-		writel(EDMR_EL, ioaddr + EDMR);
+		sh_eth_write(ndev, EDMR_EL, EDMR);
 	else
 #endif
-		writel(0, ioaddr + EDMR);
+		sh_eth_write(ndev, 0, EDMR);
 
 	/* FIFO size set */
-	writel(mdp->cd->fdr_value, ioaddr + FDR);
-	writel(0, ioaddr + TFTR);
+	sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
+	sh_eth_write(ndev, 0, TFTR);
 
 	/* Frame recv control */
-	writel(mdp->cd->rmcr_value, ioaddr + RMCR);
+	sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
 
 	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
 	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
-	writel(rx_int_var | tx_int_var, ioaddr + TRSCER);
+	sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER);
 
 	if (mdp->cd->bculr)
-		writel(0x800, ioaddr + BCULR);	/* Burst sycle set */
+		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */
 
-	writel(mdp->cd->fcftr_value, ioaddr + FCFTR);
+	sh_eth_write(ndev, mdp->cd->fcftr_value, FCFTR);
 
 	if (!mdp->cd->no_trimd)
-		writel(0, ioaddr + TRIMD);
+		sh_eth_write(ndev, 0, TRIMD);
 
 	/* Recv frame limit set register */
-	writel(RFLR_VALUE, ioaddr + RFLR);
+	sh_eth_write(ndev, RFLR_VALUE, RFLR);
 
-	writel(readl(ioaddr + EESR), ioaddr + EESR);
-	writel(mdp->cd->eesipr_value, ioaddr + EESIPR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
+	sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
 
 	/* PAUSE Prohibition */
-	val = (readl(ioaddr + ECMR) & ECMR_DM) |
+	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
 		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
 
-	writel(val, ioaddr + ECMR);
+	sh_eth_write(ndev, val, ECMR);
 
 	if (mdp->cd->set_rate)
 		mdp->cd->set_rate(ndev);
 
 	/* E-MAC Status Register clear */
-	writel(mdp->cd->ecsr_value, ioaddr + ECSR);
+	sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
 
 	/* E-MAC Interrupt Enable register */
-	writel(mdp->cd->ecsipr_value, ioaddr + ECSIPR);
+	sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
 
 	/* Set MAC address */
 	update_mac_address(ndev);
 
 	/* mask reset */
 	if (mdp->cd->apr)
-		writel(APR_AP, ioaddr + APR);
+		sh_eth_write(ndev, APR_AP, APR);
 	if (mdp->cd->mpr)
-		writel(MPR_MP, ioaddr + MPR);
+		sh_eth_write(ndev, MPR_MP, MPR);
 	if (mdp->cd->tpauser)
-		writel(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
+		sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
 
 	/* Setting the Rx mode will start the Rx process. */
-	writel(EDRRR_R, ioaddr + EDRRR);
+	sh_eth_write(ndev, EDRRR_R, EDRRR);
 
 	netif_start_queue(ndev);
 
@@ -811,24 +966,37 @@ static int sh_eth_rx(struct net_device *ndev)
 
 	/* Restart Rx engine if stopped. */
 	/* If we don't need to check status, don't. -KDU */
-	if (!(readl(ndev->base_addr + EDRRR) & EDRRR_R))
-		writel(EDRRR_R, ndev->base_addr + EDRRR);
+	if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R))
+		sh_eth_write(ndev, EDRRR_R, EDRRR);
 
 	return 0;
 }
 
+static void sh_eth_rcv_snd_disable(struct net_device *ndev)
+{
+	/* disable tx and rx */
+	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) &
+		~(ECMR_RE | ECMR_TE), ECMR);
+}
+
+static void sh_eth_rcv_snd_enable(struct net_device *ndev)
+{
+	/* enable tx and rx */
+	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
+		(ECMR_RE | ECMR_TE), ECMR);
+}
+
 /* error control function */
 static void sh_eth_error(struct net_device *ndev, int intr_status)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	u32 felic_stat;
 	u32 link_stat;
 	u32 mask;
 
 	if (intr_status & EESR_ECI) {
-		felic_stat = readl(ioaddr + ECSR);
-		writel(felic_stat, ioaddr + ECSR);	/* clear int */
+		felic_stat = sh_eth_read(ndev, ECSR);
+		sh_eth_write(ndev, felic_stat, ECSR);	/* clear int */
 		if (felic_stat & ECSR_ICD)
 			mdp->stats.tx_carrier_errors++;
 		if (felic_stat & ECSR_LCHNG) {
@@ -839,26 +1007,23 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 				else
 					link_stat = PHY_ST_LINK;
 			} else {
-				link_stat = (readl(ioaddr + PSR));
+				link_stat = (sh_eth_read(ndev, PSR));
 				if (mdp->ether_link_active_low)
 					link_stat = ~link_stat;
 			}
-			if (!(link_stat & PHY_ST_LINK)) {
-				/* Link Down : disable tx and rx */
-				writel(readl(ioaddr + ECMR) &
-					  ~(ECMR_RE | ECMR_TE), ioaddr + ECMR);
-			} else {
+			if (!(link_stat & PHY_ST_LINK))
+				sh_eth_rcv_snd_disable(ndev);
+			else {
 				/* Link Up */
-				writel(readl(ioaddr + EESIPR) &
-					  ~DMAC_M_ECI, ioaddr + EESIPR);
+				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
+					  ~DMAC_M_ECI, EESIPR);
 				/*clear int */
-				writel(readl(ioaddr + ECSR),
-					  ioaddr + ECSR);
-				writel(readl(ioaddr + EESIPR) |
-					  DMAC_M_ECI, ioaddr + EESIPR);
+				sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
+					  ECSR);
+				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
+					  DMAC_M_ECI, EESIPR);
 				/* enable tx and rx */
-				writel(readl(ioaddr + ECMR) |
-					  (ECMR_RE | ECMR_TE), ioaddr + ECMR);
+				sh_eth_rcv_snd_enable(ndev);
 			}
 		}
 	}
@@ -867,6 +1032,8 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 		/* Write buck end. unused write back interrupt */
 		if (intr_status & EESR_TABT)	/* Transmit Abort int */
 			mdp->stats.tx_aborted_errors++;
+			if (netif_msg_tx_err(mdp))
+				dev_err(&ndev->dev, "Transmit Abort\n");
 	}
 
 	if (intr_status & EESR_RABT) {
@@ -874,28 +1041,47 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 		if (intr_status & EESR_RFRMER) {
 			/* Receive Frame Overflow int */
 			mdp->stats.rx_frame_errors++;
-			dev_err(&ndev->dev, "Receive Frame Overflow\n");
+			if (netif_msg_rx_err(mdp))
+				dev_err(&ndev->dev, "Receive Abort\n");
 		}
 	}
 
-	if (!mdp->cd->no_ade) {
-		if (intr_status & EESR_ADE && intr_status & EESR_TDE &&
-		    intr_status & EESR_TFE)
-			mdp->stats.tx_fifo_errors++;
+	if (intr_status & EESR_TDE) {
+		/* Transmit Descriptor Empty int */
+		mdp->stats.tx_fifo_errors++;
+		if (netif_msg_tx_err(mdp))
+			dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
+	}
+
+	if (intr_status & EESR_TFE) {
+		/* FIFO under flow */
+		mdp->stats.tx_fifo_errors++;
+		if (netif_msg_tx_err(mdp))
+			dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
 	}
 
 	if (intr_status & EESR_RDE) {
 		/* Receive Descriptor Empty int */
 		mdp->stats.rx_over_errors++;
 
-		if (readl(ioaddr + EDRRR) ^ EDRRR_R)
-			writel(EDRRR_R, ioaddr + EDRRR);
-		dev_err(&ndev->dev, "Receive Descriptor Empty\n");
+		if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R)
+			sh_eth_write(ndev, EDRRR_R, EDRRR);
+		if (netif_msg_rx_err(mdp))
+			dev_err(&ndev->dev, "Receive Descriptor Empty\n");
 	}
+
 	if (intr_status & EESR_RFE) {
 		/* Receive FIFO Overflow int */
 		mdp->stats.rx_fifo_errors++;
-		dev_err(&ndev->dev, "Receive FIFO Overflow\n");
+		if (netif_msg_rx_err(mdp))
+			dev_err(&ndev->dev, "Receive FIFO Overflow\n");
+	}
+
+	if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
+		/* Address Error */
+		mdp->stats.tx_fifo_errors++;
+		if (netif_msg_tx_err(mdp))
+			dev_err(&ndev->dev, "Address Error\n");
 	}
 
 	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
@@ -903,7 +1089,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 		mask &= ~EESR_ADE;
 	if (intr_status & mask) {
 		/* Tx error */
-		u32 edtrr = readl(ndev->base_addr + EDTRR);
+		u32 edtrr = sh_eth_read(ndev, EDTRR);
 		/* dmesg */
 		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
 				intr_status, mdp->cur_tx);
@@ -913,9 +1099,9 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
 		sh_eth_txfree(ndev);
 
 		/* SH7712 BUG */
-		if (edtrr ^ EDTRR_TRNS) {
+		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
 			/* tx dma start */
-			writel(EDTRR_TRNS, ndev->base_addr + EDTRR);
+			sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
 		}
 		/* wakeup */
 		netif_wake_queue(ndev);
@@ -928,18 +1114,17 @@ 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 ioaddr, intr_status = 0;
+	u32 intr_status = 0;
 
-	ioaddr = ndev->base_addr;
 	spin_lock(&mdp->lock);
 
 	/* Get interrpt stat */
-	intr_status = readl(ioaddr + EESR);
+	intr_status = sh_eth_read(ndev, EESR);
 	/* Clear interrupt */
 	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
 			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
 			cd->tx_check | cd->eesr_err_check)) {
-		writel(intr_status, ioaddr + EESR);
+		sh_eth_write(ndev, intr_status, EESR);
 		ret = IRQ_HANDLED;
 	} else
 		goto other_irq;
@@ -982,7 +1167,6 @@ static void sh_eth_adjust_link(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct phy_device *phydev = mdp->phydev;
-	u32 ioaddr = ndev->base_addr;
 	int new_state = 0;
 
 	if (phydev->link != PHY_DOWN) {
@@ -1000,8 +1184,8 @@ static void sh_eth_adjust_link(struct net_device *ndev)
 				mdp->cd->set_rate(ndev);
 		}
 		if (mdp->link == PHY_DOWN) {
-			writel((readl(ioaddr + ECMR) & ~ECMR_TXF)
-					| ECMR_DM, ioaddr + ECMR);
+			sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_TXF)
+					| ECMR_DM, ECMR);
 			new_state = 1;
 			mdp->link = phydev->link;
 		}
@@ -1012,7 +1196,7 @@ static void sh_eth_adjust_link(struct net_device *ndev)
 		mdp->duplex = -1;
 	}
 
-	if (new_state)
+	if (new_state && netif_msg_link(mdp))
 		phy_print_status(phydev);
 }
 
@@ -1032,7 +1216,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
 
 	/* Try connect to PHY */
 	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
-				0, PHY_INTERFACE_MODE_MII);
+				0, mdp->phy_interface);
 	if (IS_ERR(phydev)) {
 		dev_err(&ndev->dev, "phy_connect failed\n");
 		return PTR_ERR(phydev);
@@ -1063,6 +1247,131 @@ static int sh_eth_phy_start(struct net_device *ndev)
 	return 0;
 }
 
+static int sh_eth_get_settings(struct net_device *ndev,
+			struct ethtool_cmd *ecmd)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+	ret = phy_ethtool_gset(mdp->phydev, ecmd);
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	return ret;
+}
+
+static int sh_eth_set_settings(struct net_device *ndev,
+		struct ethtool_cmd *ecmd)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+
+	/* disable tx and rx */
+	sh_eth_rcv_snd_disable(ndev);
+
+	ret = phy_ethtool_sset(mdp->phydev, ecmd);
+	if (ret)
+		goto error_exit;
+
+	if (ecmd->duplex == DUPLEX_FULL)
+		mdp->duplex = 1;
+	else
+		mdp->duplex = 0;
+
+	if (mdp->cd->set_duplex)
+		mdp->cd->set_duplex(ndev);
+
+error_exit:
+	mdelay(1);
+
+	/* enable tx and rx */
+	sh_eth_rcv_snd_enable(ndev);
+
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	return ret;
+}
+
+static int sh_eth_nway_reset(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+	ret = phy_start_aneg(mdp->phydev);
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	return ret;
+}
+
+static u32 sh_eth_get_msglevel(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	return mdp->msg_enable;
+}
+
+static void sh_eth_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	mdp->msg_enable = value;
+}
+
+static const char sh_eth_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"rx_current", "tx_current",
+	"rx_dirty", "tx_dirty",
+};
+#define SH_ETH_STATS_LEN  ARRAY_SIZE(sh_eth_gstrings_stats)
+
+static int sh_eth_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return SH_ETH_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void sh_eth_get_ethtool_stats(struct net_device *ndev,
+			struct ethtool_stats *stats, u64 *data)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int i = 0;
+
+	/* device-specific stats */
+	data[i++] = mdp->cur_rx;
+	data[i++] = mdp->cur_tx;
+	data[i++] = mdp->dirty_rx;
+	data[i++] = mdp->dirty_tx;
+}
+
+static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, *sh_eth_gstrings_stats,
+					sizeof(sh_eth_gstrings_stats));
+		break;
+	}
+}
+
+static struct ethtool_ops sh_eth_ethtool_ops = {
+	.get_settings	= sh_eth_get_settings,
+	.set_settings	= sh_eth_set_settings,
+	.nway_reset		= sh_eth_nway_reset,
+	.get_msglevel	= sh_eth_get_msglevel,
+	.set_msglevel	= sh_eth_set_msglevel,
+	.get_link		= ethtool_op_get_link,
+	.get_strings	= sh_eth_get_strings,
+	.get_ethtool_stats  = sh_eth_get_ethtool_stats,
+	.get_sset_count     = sh_eth_get_sset_count,
+};
+
 /* network device open function */
 static int sh_eth_open(struct net_device *ndev)
 {
@@ -1073,8 +1382,8 @@ static int sh_eth_open(struct net_device *ndev)
 
 	ret = request_irq(ndev->irq, sh_eth_interrupt,
 #if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7764) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7757)
+	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7757)
 				IRQF_SHARED,
 #else
 				0,
@@ -1117,15 +1426,14 @@ out_free_irq:
 static void sh_eth_tx_timeout(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	struct sh_eth_rxdesc *rxdesc;
 	int i;
 
 	netif_stop_queue(ndev);
 
-	/* worning message out. */
-	printk(KERN_WARNING "%s: transmit timed out, status %8.8x,"
-	       " resetting...\n", ndev->name, (int)readl(ioaddr + EESR));
+	if (netif_msg_timer(mdp))
+		dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
+	       " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
 
 	/* tx_errors count up */
 	mdp->stats.tx_errors++;
@@ -1167,6 +1475,8 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 	spin_lock_irqsave(&mdp->lock, flags);
 	if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
 		if (!sh_eth_txfree(ndev)) {
+			if (netif_msg_tx_queued(mdp))
+				dev_warn(&ndev->dev, "TxFD exhausted.\n");
 			netif_stop_queue(ndev);
 			spin_unlock_irqrestore(&mdp->lock, flags);
 			return NETDEV_TX_BUSY;
@@ -1196,8 +1506,8 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 
 	mdp->cur_tx++;
 
-	if (!(readl(ndev->base_addr + EDTRR) & EDTRR_TRNS))
-		writel(EDTRR_TRNS, ndev->base_addr + EDTRR);
+	if (!(sh_eth_read(ndev, EDTRR) & sh_eth_get_edtrr_trns(mdp)))
+		sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
 
 	return NETDEV_TX_OK;
 }
@@ -1206,17 +1516,16 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 static int sh_eth_close(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	int ringsize;
 
 	netif_stop_queue(ndev);
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	writel(0x0000, ioaddr + EESIPR);
+	sh_eth_write(ndev, 0x0000, EESIPR);
 
 	/* Stop the chip's Tx and Rx processes. */
-	writel(0, ioaddr + EDTRR);
-	writel(0, ioaddr + EDRRR);
+	sh_eth_write(ndev, 0, EDTRR);
+	sh_eth_write(ndev, 0, EDRRR);
 
 	/* PHY Disconnect */
 	if (mdp->phydev) {
@@ -1247,25 +1556,24 @@ static int sh_eth_close(struct net_device *ndev)
 static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 
 	pm_runtime_get_sync(&mdp->pdev->dev);
 
-	mdp->stats.tx_dropped += readl(ioaddr + TROCR);
-	writel(0, ioaddr + TROCR);	/* (write clear) */
-	mdp->stats.collisions += readl(ioaddr + CDCR);
-	writel(0, ioaddr + CDCR);	/* (write clear) */
-	mdp->stats.tx_carrier_errors += readl(ioaddr + LCCR);
-	writel(0, ioaddr + LCCR);	/* (write clear) */
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	mdp->stats.tx_carrier_errors += readl(ioaddr + CERCR);/* CERCR */
-	writel(0, ioaddr + CERCR);	/* (write clear) */
-	mdp->stats.tx_carrier_errors += readl(ioaddr + CEECR);/* CEECR */
-	writel(0, ioaddr + CEECR);	/* (write clear) */
-#else
-	mdp->stats.tx_carrier_errors += readl(ioaddr + CNDCR);
-	writel(0, ioaddr + CNDCR);	/* (write clear) */
-#endif
+	mdp->stats.tx_dropped += sh_eth_read(ndev, TROCR);
+	sh_eth_write(ndev, 0, TROCR);	/* (write clear) */
+	mdp->stats.collisions += sh_eth_read(ndev, CDCR);
+	sh_eth_write(ndev, 0, CDCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
+	sh_eth_write(ndev, 0, LCCR);	/* (write clear) */
+	if (sh_eth_is_gether(mdp)) {
+		mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
+		sh_eth_write(ndev, 0, CERCR);	/* (write clear) */
+		mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
+		sh_eth_write(ndev, 0, CEECR);	/* (write clear) */
+	} else {
+		mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
+		sh_eth_write(ndev, 0, CNDCR);	/* (write clear) */
+	}
 	pm_runtime_put_sync(&mdp->pdev->dev);
 
 	return &mdp->stats;
@@ -1291,48 +1599,46 @@ static int sh_eth_do_ioctl(struct net_device *ndev, struct ifreq *rq,
 /* Multicast reception directions set */
 static void sh_eth_set_multicast_list(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
-
 	if (ndev->flags & IFF_PROMISC) {
 		/* Set promiscuous. */
-		writel((readl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM,
-			  ioaddr + ECMR);
+		sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_MCT) |
+				ECMR_PRM, ECMR);
 	} else {
 		/* Normal, unicast/broadcast-only mode. */
-		writel((readl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT,
-			  ioaddr + ECMR);
+		sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) |
+				ECMR_MCT, ECMR);
 	}
 }
+#endif /* SH_ETH_HAS_TSU */
 
 /* SuperH's TSU register init function */
-static void sh_eth_tsu_init(u32 ioaddr)
-{
-	writel(0, ioaddr + TSU_FWEN0);	/* Disable forward(0->1) */
-	writel(0, ioaddr + TSU_FWEN1);	/* Disable forward(1->0) */
-	writel(0, ioaddr + TSU_FCM);	/* forward fifo 3k-3k */
-	writel(0xc, ioaddr + TSU_BSYSL0);
-	writel(0xc, ioaddr + TSU_BSYSL1);
-	writel(0, ioaddr + TSU_PRISL0);
-	writel(0, ioaddr + TSU_PRISL1);
-	writel(0, ioaddr + TSU_FWSL0);
-	writel(0, ioaddr + TSU_FWSL1);
-	writel(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC);
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	writel(0, ioaddr + TSU_QTAG0);	/* Disable QTAG(0->1) */
-	writel(0, ioaddr + TSU_QTAG1);	/* Disable QTAG(1->0) */
-#else
-	writel(0, ioaddr + TSU_QTAGM0);	/* Disable QTAG(0->1) */
-	writel(0, ioaddr + TSU_QTAGM1);	/* Disable QTAG(1->0) */
-#endif
-	writel(0, ioaddr + TSU_FWSR);	/* all interrupt status clear */
-	writel(0, ioaddr + TSU_FWINMK);	/* Disable all interrupt */
-	writel(0, ioaddr + TSU_TEN);	/* Disable all CAM entry */
-	writel(0, ioaddr + TSU_POST1);	/* Disable CAM entry [ 0- 7] */
-	writel(0, ioaddr + TSU_POST2);	/* Disable CAM entry [ 8-15] */
-	writel(0, ioaddr + TSU_POST3);	/* Disable CAM entry [16-23] */
-	writel(0, ioaddr + TSU_POST4);	/* Disable CAM entry [24-31] */
+static void sh_eth_tsu_init(struct sh_eth_private *mdp)
+{
+	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
+	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
+	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
+	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL0);
+	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL1);
+	sh_eth_tsu_write(mdp, 0, TSU_PRISL0);
+	sh_eth_tsu_write(mdp, 0, TSU_PRISL1);
+	sh_eth_tsu_write(mdp, 0, TSU_FWSL0);
+	sh_eth_tsu_write(mdp, 0, TSU_FWSL1);
+	sh_eth_tsu_write(mdp, TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, TSU_FWSLC);
+	if (sh_eth_is_gether(mdp)) {
+		sh_eth_tsu_write(mdp, 0, TSU_QTAG0);	/* Disable QTAG(0->1) */
+		sh_eth_tsu_write(mdp, 0, TSU_QTAG1);	/* Disable QTAG(1->0) */
+	} else {
+		sh_eth_tsu_write(mdp, 0, TSU_QTAGM0);	/* Disable QTAG(0->1) */
+		sh_eth_tsu_write(mdp, 0, TSU_QTAGM1);	/* Disable QTAG(1->0) */
+	}
+	sh_eth_tsu_write(mdp, 0, TSU_FWSR);	/* all interrupt status clear */
+	sh_eth_tsu_write(mdp, 0, TSU_FWINMK);	/* Disable all interrupt */
+	sh_eth_tsu_write(mdp, 0, TSU_TEN);	/* Disable all CAM entry */
+	sh_eth_tsu_write(mdp, 0, TSU_POST1);	/* Disable CAM entry [ 0- 7] */
+	sh_eth_tsu_write(mdp, 0, TSU_POST2);	/* Disable CAM entry [ 8-15] */
+	sh_eth_tsu_write(mdp, 0, TSU_POST3);	/* Disable CAM entry [16-23] */
+	sh_eth_tsu_write(mdp, 0, TSU_POST4);	/* Disable CAM entry [24-31] */
 }
-#endif /* SH_ETH_HAS_TSU */
 
 /* MDIO bus release function */
 static int sh_mdio_release(struct net_device *ndev)
@@ -1355,7 +1661,8 @@ static int sh_mdio_release(struct net_device *ndev)
 }
 
 /* MDIO bus init function */
-static int sh_mdio_init(struct net_device *ndev, int id)
+static int sh_mdio_init(struct net_device *ndev, int id,
+			struct sh_eth_plat_data *pd)
 {
 	int ret, i;
 	struct bb_info *bitbang;
@@ -1369,7 +1676,8 @@ static int sh_mdio_init(struct net_device *ndev, int id)
 	}
 
 	/* bitbang init */
-	bitbang->addr = ndev->base_addr + PIR;
+	bitbang->addr = ndev->base_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 */
@@ -1420,6 +1728,28 @@ out:
 	return ret;
 }
 
+static const u16 *sh_eth_get_register_offset(int register_type)
+{
+	const u16 *reg_offset = NULL;
+
+	switch (register_type) {
+	case SH_ETH_REG_GIGABIT:
+		reg_offset = sh_eth_offset_gigabit;
+		break;
+	case SH_ETH_REG_FAST_SH4:
+		reg_offset = sh_eth_offset_fast_sh4;
+		break;
+	case SH_ETH_REG_FAST_SH3_SH2:
+		reg_offset = sh_eth_offset_fast_sh3_sh2;
+		break;
+	default:
+		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
+		break;
+	}
+
+	return reg_offset;
+}
+
 static const struct net_device_ops sh_eth_netdev_ops = {
 	.ndo_open		= sh_eth_open,
 	.ndo_stop		= sh_eth_close,
@@ -1486,19 +1816,28 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
 	/* get PHY ID */
 	mdp->phy_id = pd->phy;
+	mdp->phy_interface = pd->phy_interface;
 	/* EDMAC endian */
 	mdp->edmac_endian = pd->edmac_endian;
 	mdp->no_ether_link = pd->no_ether_link;
 	mdp->ether_link_active_low = pd->ether_link_active_low;
+	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);
 
 	/* set cpu data */
+#if defined(SH_ETH_HAS_BOTH_MODULES)
+	mdp->cd = sh_eth_get_cpu_data(mdp);
+#else
 	mdp->cd = &sh_eth_my_cpu_data;
+#endif
 	sh_eth_set_default_cpu_data(mdp->cd);
 
 	/* set function */
 	ndev->netdev_ops = &sh_eth_netdev_ops;
+	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
 	ndev->watchdog_timeo = TX_TIMEOUT;
 
+	/* debug message level */
+	mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
 	mdp->post_rx = POST_RX >> (devno << 1);
 	mdp->post_fw = POST_FW >> (devno << 1);
 
@@ -1507,13 +1846,23 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 
 	/* First device only init */
 	if (!devno) {
+		if (mdp->cd->tsu) {
+			struct resource *rtsu;
+			rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+			if (!rtsu) {
+				dev_err(&pdev->dev, "Not found TSU resource\n");
+				goto out_release;
+			}
+			mdp->tsu_addr = ioremap(rtsu->start,
+						resource_size(rtsu));
+		}
 		if (mdp->cd->chip_reset)
 			mdp->cd->chip_reset(ndev);
 
-#if defined(SH_ETH_HAS_TSU)
-		/* TSU init (Init only)*/
-		sh_eth_tsu_init(SH_TSU_ADDR);
-#endif
+		if (mdp->cd->tsu) {
+			/* TSU init (Init only)*/
+			sh_eth_tsu_init(mdp);
+		}
 	}
 
 	/* network device register */
@@ -1522,7 +1871,7 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
 		goto out_release;
 
 	/* mdio bus init */
-	ret = sh_mdio_init(ndev, pdev->id);
+	ret = sh_mdio_init(ndev, pdev->id, pd);
 	if (ret)
 		goto out_unregister;
 
@@ -1539,6 +1888,8 @@ out_unregister:
 
 out_release:
 	/* net_dev free */
+	if (mdp->tsu_addr)
+		iounmap(mdp->tsu_addr);
 	if (ndev)
 		free_netdev(ndev);
 
@@ -1549,7 +1900,9 @@ 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);
 
+	iounmap(mdp->tsu_addr);
 	sh_mdio_release(ndev);
 	unregister_netdev(ndev);
 	pm_runtime_disable(&pdev->dev);
diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h
index efa6422..c3048a6 100644
--- a/drivers/net/sh_eth.h
+++ b/drivers/net/sh_eth.h
@@ -2,7 +2,7 @@
  *  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2009 Renesas Solutions Corp.
+ *  Copyright (C) 2008-2011 Renesas Solutions Corp.
  *
  *  This program is free software; you can redistribute it and/or modify it
  *  under the terms and conditions of the GNU General Public License,
@@ -38,278 +38,340 @@
 #define ETHERSMALL		60
 #define PKT_BUF_SZ		1538
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-/* This CPU register maps is very difference by other SH4 CPU */
-
-/* Chip Base Address */
-# define SH_TSU_ADDR	0xFEE01800
-# define ARSTR		SH_TSU_ADDR
-
-/* Chip Registers */
-/* E-DMAC */
-# define EDSR    0x000
-# define EDMR    0x400
-# define EDTRR   0x408
-# define EDRRR   0x410
-# define EESR    0x428
-# define EESIPR  0x430
-# define TDLAR   0x010
-# define TDFAR   0x014
-# define TDFXR   0x018
-# define TDFFR   0x01C
-# define RDLAR   0x030
-# define RDFAR   0x034
-# define RDFXR   0x038
-# define RDFFR   0x03C
-# define TRSCER  0x438
-# define RMFCR   0x440
-# define TFTR    0x448
-# define FDR     0x450
-# define RMCR    0x458
-# define RPADIR  0x460
-# define FCFTR   0x468
-
-/* Ether Register */
-# define ECMR    0x500
-# define ECSR    0x510
-# define ECSIPR  0x518
-# define PIR     0x520
-# define PSR     0x528
-# define PIPR    0x52C
-# define RFLR    0x508
-# define APR     0x554
-# define MPR     0x558
-# define PFTCR	 0x55C
-# define PFRCR	 0x560
-# define TPAUSER 0x564
-# define GECMR   0x5B0
-# define BCULR   0x5B4
-# define MAHR    0x5C0
-# define MALR    0x5C8
-# define TROCR   0x700
-# define CDCR    0x708
-# define LCCR    0x710
-# define CEFCR   0x740
-# define FRECR   0x748
-# define TSFRCR  0x750
-# define TLFRCR  0x758
-# define RFCR    0x760
-# define CERCR   0x768
-# define CEECR   0x770
-# define MAFCR   0x778
-
-/* TSU Absolute Address */
-# define TSU_CTRST       0x004
-# define TSU_FWEN0       0x010
-# define TSU_FWEN1       0x014
-# define TSU_FCM         0x18
-# define TSU_BSYSL0      0x20
-# define TSU_BSYSL1      0x24
-# define TSU_PRISL0      0x28
-# define TSU_PRISL1      0x2C
-# define TSU_FWSL0       0x30
-# define TSU_FWSL1       0x34
-# define TSU_FWSLC       0x38
-# define TSU_QTAG0       0x40
-# define TSU_QTAG1       0x44
-# define TSU_FWSR        0x50
-# define TSU_FWINMK      0x54
-# define TSU_ADQT0       0x48
-# define TSU_ADQT1       0x4C
-# define TSU_VTAG0       0x58
-# define TSU_VTAG1       0x5C
-# define TSU_ADSBSY      0x60
-# define TSU_TEN         0x64
-# define TSU_POST1       0x70
-# define TSU_POST2       0x74
-# define TSU_POST3       0x78
-# define TSU_POST4       0x7C
-# define TSU_ADRH0       0x100
-# define TSU_ADRL0       0x104
-# define TSU_ADRH31      0x1F8
-# define TSU_ADRL31      0x1FC
-
-# define TXNLCR0         0x80
-# define TXALCR0         0x84
-# define RXNLCR0         0x88
-# define RXALCR0         0x8C
-# define FWNLCR0         0x90
-# define FWALCR0         0x94
-# define TXNLCR1         0xA0
-# define TXALCR1         0xA4
-# define RXNLCR1         0xA8
-# define RXALCR1         0xAC
-# define FWNLCR1         0xB0
-# define FWALCR1         0x40
-
-#elif defined(CONFIG_CPU_SH4)	/* #if defined(CONFIG_CPU_SUBTYPE_SH7763) */
-/* EtherC */
-#define ECMR		0x100
-#define RFLR		0x108
-#define ECSR		0x110
-#define ECSIPR		0x118
-#define PIR		0x120
-#define PSR		0x128
-#define RDMLR		0x140
-#define IPGR		0x150
-#define APR		0x154
-#define MPR		0x158
-#define TPAUSER		0x164
-#define RFCF		0x160
-#define TPAUSECR	0x168
-#define BCFRR		0x16c
-#define MAHR		0x1c0
-#define MALR		0x1c8
-#define TROCR		0x1d0
-#define CDCR		0x1d4
-#define LCCR		0x1d8
-#define CNDCR		0x1dc
-#define CEFCR		0x1e4
-#define FRECR		0x1e8
-#define TSFRCR		0x1ec
-#define TLFRCR		0x1f0
-#define RFCR		0x1f4
-#define MAFCR		0x1f8
-#define RTRATE		0x1fc
-
-/* E-DMAC */
-#define EDMR		0x000
-#define EDTRR		0x008
-#define EDRRR		0x010
-#define TDLAR		0x018
-#define RDLAR		0x020
-#define EESR		0x028
-#define EESIPR		0x030
-#define TRSCER		0x038
-#define RMFCR		0x040
-#define TFTR		0x048
-#define FDR		0x050
-#define RMCR		0x058
-#define TFUCR		0x064
-#define RFOCR		0x068
-#define FCFTR		0x070
-#define RPADIR		0x078
-#define TRIMD		0x07c
-#define RBWAR		0x0c8
-#define RDFAR		0x0cc
-#define TBRAR		0x0d4
-#define TDFAR		0x0d8
-#else /* #elif defined(CONFIG_CPU_SH4) */
-/* This section is SH3 or SH2 */
-#ifndef CONFIG_CPU_SUBTYPE_SH7619
-/* Chip base address */
-# define SH_TSU_ADDR  0xA7000804
-# define ARSTR		  0xA7000800
-#endif
-/* Chip Registers */
-/* E-DMAC */
-# define EDMR	0x0000
-# define EDTRR	0x0004
-# define EDRRR	0x0008
-# define TDLAR	0x000C
-# define RDLAR	0x0010
-# define EESR	0x0014
-# define EESIPR	0x0018
-# define TRSCER	0x001C
-# define RMFCR	0x0020
-# define TFTR	0x0024
-# define FDR	0x0028
-# define RMCR	0x002C
-# define EDOCR	0x0030
-# define FCFTR	0x0034
-# define RPADIR	0x0038
-# define TRIMD	0x003C
-# define RBWAR	0x0040
-# define RDFAR	0x0044
-# define TBRAR	0x004C
-# define TDFAR	0x0050
-
-/* Ether Register */
-# define ECMR	0x0160
-# define ECSR	0x0164
-# define ECSIPR	0x0168
-# define PIR	0x016C
-# define MAHR	0x0170
-# define MALR	0x0174
-# define RFLR	0x0178
-# define PSR	0x017C
-# define TROCR	0x0180
-# define CDCR	0x0184
-# define LCCR	0x0188
-# define CNDCR	0x018C
-# define CEFCR	0x0194
-# define FRECR	0x0198
-# define TSFRCR	0x019C
-# define TLFRCR	0x01A0
-# define RFCR	0x01A4
-# define MAFCR	0x01A8
-# define IPGR	0x01B4
-# if defined(CONFIG_CPU_SUBTYPE_SH7710)
-# define APR	0x01B8
-# define MPR 	0x01BC
-# define TPAUSER 0x1C4
-# define BCFR	0x1CC
-# endif /* CONFIG_CPU_SH7710 */
-
-/* TSU */
-# define TSU_CTRST	0x004
-# define TSU_FWEN0	0x010
-# define TSU_FWEN1	0x014
-# define TSU_FCM	0x018
-# define TSU_BSYSL0	0x020
-# define TSU_BSYSL1	0x024
-# define TSU_PRISL0	0x028
-# define TSU_PRISL1	0x02C
-# define TSU_FWSL0	0x030
-# define TSU_FWSL1	0x034
-# define TSU_FWSLC	0x038
-# define TSU_QTAGM0	0x040
-# define TSU_QTAGM1	0x044
-# define TSU_ADQT0 	0x048
-# define TSU_ADQT1	0x04C
-# define TSU_FWSR	0x050
-# define TSU_FWINMK	0x054
-# define TSU_ADSBSY	0x060
-# define TSU_TEN	0x064
-# define TSU_POST1	0x070
-# define TSU_POST2	0x074
-# define TSU_POST3	0x078
-# define TSU_POST4	0x07C
-# define TXNLCR0	0x080
-# define TXALCR0	0x084
-# define RXNLCR0	0x088
-# define RXALCR0	0x08C
-# define FWNLCR0	0x090
-# define FWALCR0	0x094
-# define TXNLCR1	0x0A0
-# define TXALCR1	0x0A4
-# define RXNLCR1	0x0A8
-# define RXALCR1	0x0AC
-# define FWNLCR1	0x0B0
-# define FWALCR1	0x0B4
-
-#define TSU_ADRH0	0x0100
-#define TSU_ADRL0	0x0104
-#define TSU_ADRL31	0x01FC
-
-#endif /* CONFIG_CPU_SUBTYPE_SH7763 */
-
-/* There are avoid compile error... */
-#if !defined(BCULR)
-#define BCULR	0x0fc
-#endif
-#if !defined(TRIMD)
-#define TRIMD	0x0fc
-#endif
-#if !defined(APR)
-#define APR	0x0fc
-#endif
-#if !defined(MPR)
-#define MPR	0x0fc
-#endif
-#if !defined(TPAUSER)
-#define TPAUSER	0x0fc
-#endif
+enum {
+	/* E-DMAC registers */
+	EDSR = 0,
+	EDMR,
+	EDTRR,
+	EDRRR,
+	EESR,
+	EESIPR,
+	TDLAR,
+	TDFAR,
+	TDFXR,
+	TDFFR,
+	RDLAR,
+	RDFAR,
+	RDFXR,
+	RDFFR,
+	TRSCER,
+	RMFCR,
+	TFTR,
+	FDR,
+	RMCR,
+	EDOCR,
+	TFUCR,
+	RFOCR,
+	FCFTR,
+	RPADIR,
+	TRIMD,
+	RBWAR,
+	TBRAR,
+
+	/* Ether registers */
+	ECMR,
+	ECSR,
+	ECSIPR,
+	PIR,
+	PSR,
+	RDMLR,
+	PIPR,
+	RFLR,
+	IPGR,
+	APR,
+	MPR,
+	PFTCR,
+	PFRCR,
+	RFCR,
+	RFCF,
+	TPAUSER,
+	TPAUSECR,
+	BCFR,
+	BCFRR,
+	GECMR,
+	BCULR,
+	MAHR,
+	MALR,
+	TROCR,
+	CDCR,
+	LCCR,
+	CNDCR,
+	CEFCR,
+	FRECR,
+	TSFRCR,
+	TLFRCR,
+	CERCR,
+	CEECR,
+	MAFCR,
+	RTRATE,
+
+	/* TSU Absolute address */
+	ARSTR,
+	TSU_CTRST,
+	TSU_FWEN0,
+	TSU_FWEN1,
+	TSU_FCM,
+	TSU_BSYSL0,
+	TSU_BSYSL1,
+	TSU_PRISL0,
+	TSU_PRISL1,
+	TSU_FWSL0,
+	TSU_FWSL1,
+	TSU_FWSLC,
+	TSU_QTAG0,
+	TSU_QTAG1,
+	TSU_QTAGM0,
+	TSU_QTAGM1,
+	TSU_FWSR,
+	TSU_FWINMK,
+	TSU_ADQT0,
+	TSU_ADQT1,
+	TSU_VTAG0,
+	TSU_VTAG1,
+	TSU_ADSBSY,
+	TSU_TEN,
+	TSU_POST1,
+	TSU_POST2,
+	TSU_POST3,
+	TSU_POST4,
+	TSU_ADRH0,
+	TSU_ADRL0,
+	TSU_ADRH31,
+	TSU_ADRL31,
+
+	TXNLCR0,
+	TXALCR0,
+	RXNLCR0,
+	RXALCR0,
+	FWNLCR0,
+	FWALCR0,
+	TXNLCR1,
+	TXALCR1,
+	RXNLCR1,
+	RXALCR1,
+	FWNLCR1,
+	FWALCR1,
+
+	/* This value must be written at last. */
+	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,
+
+	[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,
+
+	[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)
@@ -338,20 +400,14 @@ enum GECMR_BIT {
 enum DMAC_M_BIT {
 	EDMR_EL = 0x40, /* Litte endian */
 	EDMR_DL1 = 0x20, EDMR_DL0 = 0x10,
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-	EDMR_SRST = 0x03,
-#else /* CONFIG_CPU_SUBTYPE_SH7763 */
-	EDMR_SRST = 0x01,
-#endif
+	EDMR_SRST_GETHER = 0x03,
+	EDMR_SRST_ETHER = 0x01,
 };
 
 /* EDTRR */
 enum DMAC_T_BIT {
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-	EDTRR_TRNS = 0x03,
-#else
-	EDTRR_TRNS = 0x01,
-#endif
+	EDTRR_TRNS_GETHER = 0x03,
+	EDTRR_TRNS_ETHER = 0x01,
 };
 
 /* EDRRR*/
@@ -695,6 +751,7 @@ struct sh_eth_cpu_data {
 	unsigned mpr:1;			/* EtherC have MPR */
 	unsigned tpauser:1;		/* EtherC have TPAUSER */
 	unsigned bculr:1;		/* EtherC have BCULR */
+	unsigned tsu:1;			/* EtherC have TSU */
 	unsigned hw_swap:1;		/* E-DMAC have DE bit in EDMR */
 	unsigned rpadir:1;		/* E-DMAC have RPADIR */
 	unsigned no_trimd:1;		/* E-DMAC DO NOT have TRIMD */
@@ -704,6 +761,8 @@ struct sh_eth_cpu_data {
 struct sh_eth_private {
 	struct platform_device *pdev;
 	struct sh_eth_cpu_data *cd;
+	const u16 *reg_offset;
+	void __iomem *tsu_addr;
 	dma_addr_t rx_desc_dma;
 	dma_addr_t tx_desc_dma;
 	struct sh_eth_rxdesc *rx_ring;
@@ -722,6 +781,7 @@ struct sh_eth_private {
 	struct mii_bus *mii_bus;	/* MDIO bus control */
 	struct phy_device *phydev;	/* PHY device control */
 	enum phy_state link;
+	phy_interface_t phy_interface;
 	int msg_enable;
 	int speed;
 	int duplex;
@@ -746,4 +806,32 @@ static inline void sh_eth_soft_swap(char *src, int len)
 #endif
 }
 
+static inline void sh_eth_write(struct net_device *ndev, unsigned long data,
+				int enum_index)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	writel(data, ndev->base_addr + mdp->reg_offset[enum_index]);
+}
+
+static inline unsigned long sh_eth_read(struct net_device *ndev,
+					int enum_index)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	return readl(ndev->base_addr + mdp->reg_offset[enum_index]);
+}
+
+static inline void sh_eth_tsu_write(struct sh_eth_private *mdp,
+				unsigned long data, int enum_index)
+{
+	writel(data, mdp->tsu_addr + mdp->reg_offset[enum_index]);
+}
+
+static inline unsigned long sh_eth_tsu_read(struct sh_eth_private *mdp,
+					int enum_index)
+{
+	return readl(mdp->tsu_addr + mdp->reg_offset[enum_index]);
+}
+
 #endif	/* #ifndef __SH_ETH_H__ */
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 640e368..84d4167 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -495,7 +495,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
 	sis_priv->mii_info.reg_num_mask = 0x1f;
 
 	/* Get Mac address according to the chip revision */
-	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev));
+	sis_priv->chipset_rev = pci_dev->revision;
 	if(netif_msg_probe(sis_priv))
 		printk(KERN_DEBUG "%s: detected revision %2.2x, "
 				"trying to get MAC address...\n",
@@ -532,7 +532,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
 	/* save our host bridge revision */
 	dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
 	if (dev) {
-		pci_read_config_byte(dev, PCI_CLASS_REVISION, &sis_priv->host_bridge_rev);
+		sis_priv->host_bridge_rev = dev->revision;
 		pci_dev_put(dev);
 	}
 
diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile
index cb23580..b0be023 100644
--- a/drivers/net/skfp/Makefile
+++ b/drivers/net/skfp/Makefile
@@ -17,4 +17,4 @@ skfp-objs :=  skfddi.o    hwmtm.o    fplustm.o  smt.o      cfm.o     \
 #   projects. To keep the source common for all those drivers (and
 #   thus simplify fixes to it), please do not clean it up!
 
-EXTRA_CFLAGS += -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes 
+ccflags-y := -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 7d85a38..2a91868 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4983,7 +4983,7 @@ static int sky2_suspend(struct device *dev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int sky2_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 726df61..43654a3 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -81,6 +81,7 @@ static const char version[] =
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/workqueue.h>
+#include <linux/of.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2394,6 +2395,15 @@ static int smc_drv_resume(struct device *dev)
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id smc91x_match[] = {
+	{ .compatible = "smsc,lan91c94", },
+	{ .compatible = "smsc,lan91c111", },
+	{},
+}
+MODULE_DEVICE_TABLE(of, smc91x_match);
+#endif
+
 static struct dev_pm_ops smc_drv_pm_ops = {
 	.suspend	= smc_drv_suspend,
 	.resume		= smc_drv_resume,
@@ -2406,6 +2416,9 @@ static struct platform_driver smc_driver = {
 		.name	= CARDNAME,
 		.owner	= THIS_MODULE,
 		.pm	= &smc_drv_pm_ops,
+#ifdef CONFIG_OF
+		.of_match_table = smc91x_match,
+#endif
 	},
 };
 
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index ee74791..68d48ab 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -206,68 +206,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 #define RPC_LSA_DEFAULT		RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT		RPC_LED_100_10
 
-#elif   defined(CONFIG_MACH_LPD79520) ||	\
-	defined(CONFIG_MACH_LPD7A400) ||	\
-	defined(CONFIG_MACH_LPD7A404)
-
-/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the
- * way that the CPU handles chip selects and the way that the SMC chip
- * expects the chip select to operate.  Refer to
- * Documentation/arm/Sharp-LH/IOBarrier for details.  The read from
- * IOBARRIER is a byte, in order that we read the least-common
- * denominator.  It would be wasteful to read 32 bits from an 8-bit
- * accessible region.
- *
- * There is no explicit protection against interrupts intervening
- * between the writew and the IOBARRIER.  In SMC ISR there is a
- * preamble that performs an IOBARRIER in the extremely unlikely event
- * that the driver interrupts itself between a writew to the chip an
- * the IOBARRIER that follows *and* the cache is large enough that the
- * first off-chip access while handing the interrupt is to the SMC
- * chip.  Other devices in the same address space as the SMC chip must
- * be aware of the potential for trouble and perform a similar
- * IOBARRIER on entry to their ISR.
- */
-
-#include <mach/constants.h>	/* IOBARRIER_VIRT */
-
-#define SMC_CAN_USE_8BIT	0
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	0
-#define SMC_NOWAIT		0
-#define LPD7X_IOBARRIER		readb (IOBARRIER_VIRT)
-
-#define SMC_inw(a,r)\
-   ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; })
-#define SMC_outw(v,a,r)	  ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; })
-
-#define SMC_insw		LPD7_SMC_insw
-static inline void LPD7_SMC_insw (unsigned char* a, int r,
-				  unsigned char* p, int l)
-{
-	unsigned short* ps = (unsigned short*) p;
-	while (l-- > 0) {
-		*ps++ = readw (a + r);
-		LPD7X_IOBARRIER;
-	}
-}
-
-#define SMC_outsw		LPD7_SMC_outsw
-static inline void LPD7_SMC_outsw (unsigned char* a, int r,
-				   unsigned char* p, int l)
-{
-	unsigned short* ps = (unsigned short*) p;
-	while (l-- > 0) {
-		writew (*ps++, a + r);
-		LPD7X_IOBARRIER;
-	}
-}
-
-#define SMC_INTERRUPT_PREAMBLE	LPD7X_IOBARRIER
-
-#define RPC_LSA_DEFAULT		RPC_LED_TX_RX
-#define RPC_LSB_DEFAULT		RPC_LED_100_10
-
 #elif	defined(CONFIG_ARCH_VERSATILE)
 
 #define SMC_CAN_USE_8BIT	1
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index d70bde9..1566259 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -791,8 +791,8 @@ static int smsc911x_mii_probe(struct net_device *dev)
 		return -ENODEV;
 	}
 
-	SMSC_TRACE(PROBE, "PHY %d: addr %d, phy_id 0x%08X",
-			phy_addr, phydev->addr, phydev->phy_id);
+	SMSC_TRACE(PROBE, "PHY: addr %d, phy_id 0x%08X",
+			phydev->addr, phydev->phy_id);
 
 	ret = phy_connect_direct(dev, phydev,
 			&smsc911x_phy_adjust_link, 0,
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 0a6a5ce..aa47658 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1242,8 +1242,7 @@ fail_and_cleanup:
 /* QEC can be the parent of either QuadEthernet or a BigMAC.  We want
  * the latter.
  */
-static int __devinit bigmac_sbus_probe(struct platform_device *op,
-				       const struct of_device_id *match)
+static int __devinit bigmac_sbus_probe(struct platform_device *op)
 {
 	struct device *parent = op->dev.parent;
 	struct platform_device *qec_op;
@@ -1289,7 +1288,7 @@ static const struct of_device_id bigmac_sbus_match[] = {
 
 MODULE_DEVICE_TABLE(of, bigmac_sbus_match);
 
-static struct of_platform_driver bigmac_sbus_driver = {
+static struct platform_driver bigmac_sbus_driver = {
 	.driver = {
 		.name = "sunbmac",
 		.owner = THIS_MODULE,
@@ -1301,12 +1300,12 @@ static struct of_platform_driver bigmac_sbus_driver = {
 
 static int __init bigmac_init(void)
 {
-	return of_register_platform_driver(&bigmac_sbus_driver);
+	return platform_driver_register(&bigmac_sbus_driver);
 }
 
 static void __exit bigmac_exit(void)
 {
-	of_unregister_platform_driver(&bigmac_sbus_driver);
+	platform_driver_unregister(&bigmac_sbus_driver);
 }
 
 module_init(bigmac_init);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 1c5408f..c1a3448 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -320,28 +320,28 @@ static int gem_txmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s
 
 	if (txmac_stat & MAC_TXSTAT_URUN) {
 		netdev_err(dev, "TX MAC xmit underrun\n");
-		gp->net_stats.tx_fifo_errors++;
+		dev->stats.tx_fifo_errors++;
 	}
 
 	if (txmac_stat & MAC_TXSTAT_MPE) {
 		netdev_err(dev, "TX MAC max packet size error\n");
-		gp->net_stats.tx_errors++;
+		dev->stats.tx_errors++;
 	}
 
 	/* The rest are all cases of one of the 16-bit TX
 	 * counters expiring.
 	 */
 	if (txmac_stat & MAC_TXSTAT_NCE)
-		gp->net_stats.collisions += 0x10000;
+		dev->stats.collisions += 0x10000;
 
 	if (txmac_stat & MAC_TXSTAT_ECE) {
-		gp->net_stats.tx_aborted_errors += 0x10000;
-		gp->net_stats.collisions += 0x10000;
+		dev->stats.tx_aborted_errors += 0x10000;
+		dev->stats.collisions += 0x10000;
 	}
 
 	if (txmac_stat & MAC_TXSTAT_LCE) {
-		gp->net_stats.tx_aborted_errors += 0x10000;
-		gp->net_stats.collisions += 0x10000;
+		dev->stats.tx_aborted_errors += 0x10000;
+		dev->stats.collisions += 0x10000;
 	}
 
 	/* We do not keep track of MAC_TXSTAT_FCE and
@@ -469,20 +469,20 @@ static int gem_rxmac_interrupt(struct net_device *dev, struct gem *gp, u32 gem_s
 		u32 smac = readl(gp->regs + MAC_SMACHINE);
 
 		netdev_err(dev, "RX MAC fifo overflow smac[%08x]\n", smac);
-		gp->net_stats.rx_over_errors++;
-		gp->net_stats.rx_fifo_errors++;
+		dev->stats.rx_over_errors++;
+		dev->stats.rx_fifo_errors++;
 
 		ret = gem_rxmac_reset(gp);
 	}
 
 	if (rxmac_stat & MAC_RXSTAT_ACE)
-		gp->net_stats.rx_frame_errors += 0x10000;
+		dev->stats.rx_frame_errors += 0x10000;
 
 	if (rxmac_stat & MAC_RXSTAT_CCE)
-		gp->net_stats.rx_crc_errors += 0x10000;
+		dev->stats.rx_crc_errors += 0x10000;
 
 	if (rxmac_stat & MAC_RXSTAT_LCE)
-		gp->net_stats.rx_length_errors += 0x10000;
+		dev->stats.rx_length_errors += 0x10000;
 
 	/* We do not track MAC_RXSTAT_FCE and MAC_RXSTAT_VCE
 	 * events.
@@ -594,7 +594,7 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
 		if (netif_msg_rx_err(gp))
 			printk(KERN_DEBUG "%s: no buffer for rx frame\n",
 				gp->dev->name);
-		gp->net_stats.rx_dropped++;
+		dev->stats.rx_dropped++;
 	}
 
 	if (gem_status & GREG_STAT_RXTAGERR) {
@@ -602,7 +602,7 @@ static int gem_abnormal_irq(struct net_device *dev, struct gem *gp, u32 gem_stat
 		if (netif_msg_rx_err(gp))
 			printk(KERN_DEBUG "%s: corrupt rx tag framing\n",
 				gp->dev->name);
-		gp->net_stats.rx_errors++;
+		dev->stats.rx_errors++;
 
 		goto do_reset;
 	}
@@ -684,7 +684,7 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
 				break;
 		}
 		gp->tx_skbs[entry] = NULL;
-		gp->net_stats.tx_bytes += skb->len;
+		dev->stats.tx_bytes += skb->len;
 
 		for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
 			txd = &gp->init_block->txd[entry];
@@ -696,7 +696,7 @@ static __inline__ void gem_tx(struct net_device *dev, struct gem *gp, u32 gem_st
 			entry = NEXT_TX(entry);
 		}
 
-		gp->net_stats.tx_packets++;
+		dev->stats.tx_packets++;
 		dev_kfree_skb_irq(skb);
 	}
 	gp->tx_old = entry;
@@ -738,6 +738,7 @@ static __inline__ void gem_post_rxds(struct gem *gp, int limit)
 
 static int gem_rx(struct gem *gp, int work_to_do)
 {
+	struct net_device *dev = gp->dev;
 	int entry, drops, work_done = 0;
 	u32 done;
 	__sum16 csum;
@@ -782,15 +783,15 @@ static int gem_rx(struct gem *gp, int work_to_do)
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
 		if ((len < ETH_ZLEN) || (status & RXDCTRL_BAD)) {
-			gp->net_stats.rx_errors++;
+			dev->stats.rx_errors++;
 			if (len < ETH_ZLEN)
-				gp->net_stats.rx_length_errors++;
+				dev->stats.rx_length_errors++;
 			if (len & RXDCTRL_BAD)
-				gp->net_stats.rx_crc_errors++;
+				dev->stats.rx_crc_errors++;
 
 			/* We'll just return it to GEM. */
 		drop_it:
-			gp->net_stats.rx_dropped++;
+			dev->stats.rx_dropped++;
 			goto next;
 		}
 
@@ -843,8 +844,8 @@ static int gem_rx(struct gem *gp, int work_to_do)
 
 		netif_receive_skb(skb);
 
-		gp->net_stats.rx_packets++;
-		gp->net_stats.rx_bytes += len;
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += len;
 
 	next:
 		entry = NEXT_RX(entry);
@@ -2472,7 +2473,6 @@ static int gem_resume(struct pci_dev *pdev)
 static struct net_device_stats *gem_get_stats(struct net_device *dev)
 {
 	struct gem *gp = netdev_priv(dev);
-	struct net_device_stats *stats = &gp->net_stats;
 
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
@@ -2481,17 +2481,17 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
 	 * so we shield against this
 	 */
 	if (gp->running) {
-		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
+		dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
 		writel(0, gp->regs + MAC_FCSERR);
 
-		stats->rx_frame_errors += readl(gp->regs + MAC_AERR);
+		dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
 		writel(0, gp->regs + MAC_AERR);
 
-		stats->rx_length_errors += readl(gp->regs + MAC_LERR);
+		dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
 		writel(0, gp->regs + MAC_LERR);
 
-		stats->tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
-		stats->collisions +=
+		dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
+		dev->stats.collisions +=
 			(readl(gp->regs + MAC_ECOLL) +
 			 readl(gp->regs + MAC_LCOLL));
 		writel(0, gp->regs + MAC_ECOLL);
@@ -2501,7 +2501,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
 	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
-	return &gp->net_stats;
+	return &dev->stats;
 }
 
 static int gem_set_mac_address(struct net_device *dev, void *addr)
diff --git a/drivers/net/sungem.h b/drivers/net/sungem.h
index 1990546..d225077 100644
--- a/drivers/net/sungem.h
+++ b/drivers/net/sungem.h
@@ -843,7 +843,7 @@ struct gem_txd {
 
 /* GEM requires that RX descriptors are provided four at a time,
  * aligned.  Also, the RX ring may not wrap around.  This means that
- * there will be at least 4 unused desciptor entries in the middle
+ * there will be at least 4 unused descriptor entries in the middle
  * of the RX ring at all times.
  *
  * Similar to HME, GEM assumes that it can write garbage bytes before
@@ -994,7 +994,6 @@ struct gem {
 	u32			status;
 
 	struct napi_struct	napi;
-	struct net_device_stats net_stats;
 
 	int			tx_fifo_sz;
 	int			rx_fifo_sz;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 55bbb9c..eb4f59f 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -3237,11 +3237,15 @@ static void happy_meal_pci_exit(void)
 #endif
 
 #ifdef CONFIG_SBUS
-static int __devinit hme_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit hme_sbus_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	const char *model = of_get_property(dp, "model", NULL);
-	int is_qfe = (match->data != NULL);
+	int is_qfe;
+
+	if (!op->dev.of_match)
+		return -EINVAL;
+	is_qfe = (op->dev.of_match->data != NULL);
 
 	if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))
 		is_qfe = 1;
@@ -3292,7 +3296,7 @@ static const struct of_device_id hme_sbus_match[] = {
 
 MODULE_DEVICE_TABLE(of, hme_sbus_match);
 
-static struct of_platform_driver hme_sbus_driver = {
+static struct platform_driver hme_sbus_driver = {
 	.driver = {
 		.name = "hme",
 		.owner = THIS_MODULE,
@@ -3306,7 +3310,7 @@ static int __init happy_meal_sbus_init(void)
 {
 	int err;
 
-	err = of_register_platform_driver(&hme_sbus_driver);
+	err = platform_driver_register(&hme_sbus_driver);
 	if (!err)
 		err = quattro_sbus_register_irqs();
 
@@ -3315,7 +3319,7 @@ static int __init happy_meal_sbus_init(void)
 
 static void happy_meal_sbus_exit(void)
 {
-	of_unregister_platform_driver(&hme_sbus_driver);
+	platform_driver_unregister(&hme_sbus_driver);
 	quattro_sbus_free_irqs();
 
 	while (qfe_sbus_list) {
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 767e1e2..32a5c7f 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1495,7 +1495,7 @@ fail:
 	return -ENODEV;
 }
 
-static int __devinit sunlance_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit sunlance_sbus_probe(struct platform_device *op)
 {
 	struct platform_device *parent = to_platform_device(op->dev.parent);
 	struct device_node *parent_dp = parent->dev.of_node;
@@ -1536,7 +1536,7 @@ static const struct of_device_id sunlance_sbus_match[] = {
 
 MODULE_DEVICE_TABLE(of, sunlance_sbus_match);
 
-static struct of_platform_driver sunlance_sbus_driver = {
+static struct platform_driver sunlance_sbus_driver = {
 	.driver = {
 		.name = "sunlance",
 		.owner = THIS_MODULE,
@@ -1550,12 +1550,12 @@ static struct of_platform_driver sunlance_sbus_driver = {
 /* Find all the lance cards on the system and initialize them */
 static int __init sparc_lance_init(void)
 {
-	return of_register_platform_driver(&sunlance_sbus_driver);
+	return platform_driver_register(&sunlance_sbus_driver);
 }
 
 static void __exit sparc_lance_exit(void)
 {
-	of_unregister_platform_driver(&sunlance_sbus_driver);
+	platform_driver_unregister(&sunlance_sbus_driver);
 }
 
 module_init(sparc_lance_init);
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 9536b2f..18ecdc3 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -941,7 +941,7 @@ fail:
 	return res;
 }
 
-static int __devinit qec_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit qec_sbus_probe(struct platform_device *op)
 {
 	return qec_ether_init(op);
 }
@@ -976,7 +976,7 @@ static const struct of_device_id qec_sbus_match[] = {
 
 MODULE_DEVICE_TABLE(of, qec_sbus_match);
 
-static struct of_platform_driver qec_sbus_driver = {
+static struct platform_driver qec_sbus_driver = {
 	.driver = {
 		.name = "qec",
 		.owner = THIS_MODULE,
@@ -988,12 +988,12 @@ static struct of_platform_driver qec_sbus_driver = {
 
 static int __init qec_init(void)
 {
-	return of_register_platform_driver(&qec_sbus_driver);
+	return platform_driver_register(&qec_sbus_driver);
 }
 
 static void __exit qec_exit(void)
 {
-	of_unregister_platform_driver(&qec_sbus_driver);
+	platform_driver_unregister(&qec_sbus_driver);
 
 	while (root_qec_dev) {
 		struct sunqec *next = root_qec_dev->next_module;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 06c0e503..ebec888 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -4,7 +4,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2005-2010 Broadcom Corporation.
+ * Copyright (C) 2005-2011 Broadcom Corporation.
  *
  * Firmware is:
  *	Derived from proprietary unpublished source code,
@@ -64,10 +64,10 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define TG3_MAJ_NUM			3
-#define TG3_MIN_NUM			116
+#define TG3_MIN_NUM			117
 #define DRV_MODULE_VERSION	\
 	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE	"December 3, 2010"
+#define DRV_MODULE_RELDATE	"January 25, 2011"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -1776,9 +1776,29 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
 		tg3_phy_cl45_read(tp, MDIO_MMD_AN,
 				  TG3_CL45_D7_EEERES_STAT, &val);
 
-		if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
-		    val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
+		switch (val) {
+		case TG3_CL45_D7_EEERES_STAT_LP_1000T:
+			switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+			case ASIC_REV_5717:
+			case ASIC_REV_5719:
+			case ASIC_REV_57765:
+				/* Enable SM_DSP clock and tx 6dB coding. */
+				val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+				      MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+				      MII_TG3_AUXCTL_ACTL_TX_6DB;
+				tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+
+				tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
+
+				/* Turn off SM_DSP clock. */
+				val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+				      MII_TG3_AUXCTL_ACTL_TX_6DB;
+				tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+			}
+			/* Fallthrough */
+		case TG3_CL45_D7_EEERES_STAT_LP_100TX:
 			tp->setlpicnt = 2;
+		}
 	}
 
 	if (!tp->setlpicnt) {
@@ -2100,7 +2120,7 @@ out:
 
 static void tg3_frob_aux_power(struct tg3 *tp)
 {
-	struct tg3 *tp_peer = tp;
+	bool need_vaux = false;
 
 	/* The GPIOs do something completely different on 57765. */
 	if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 ||
@@ -2108,23 +2128,32 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 		return;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) &&
+	    tp->pdev_peer != tp->pdev) {
 		struct net_device *dev_peer;
 
 		dev_peer = pci_get_drvdata(tp->pdev_peer);
+
 		/* remove_one() may have been run on the peer. */
-		if (!dev_peer)
-			tp_peer = tp;
-		else
-			tp_peer = netdev_priv(dev_peer);
+		if (dev_peer) {
+			struct tg3 *tp_peer = netdev_priv(dev_peer);
+
+			if (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE)
+				return;
+
+			if ((tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) ||
+			    (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF))
+				need_vaux = true;
+		}
 	}
 
-	if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
-	    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 ||
-	    (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
-	    (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
+	if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) ||
+	    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+		need_vaux = true;
+
+	if (need_vaux) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
@@ -2154,10 +2183,6 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 			u32 no_gpio2;
 			u32 grc_local_ctrl = 0;
 
-			if (tp_peer != tp &&
-			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
-				return;
-
 			/* Workaround to prevent overdrawing Amps. */
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
 			    ASIC_REV_5714) {
@@ -2196,10 +2221,6 @@ static void tg3_frob_aux_power(struct tg3 *tp)
 	} else {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
 		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-			if (tp_peer != tp &&
-			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
-				return;
-
 			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 				    (GRC_LCLCTRL_GPIO_OE1 |
 				     GRC_LCLCTRL_GPIO_OUTPUT1), 100);
@@ -2968,11 +2989,19 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
 		      MII_TG3_AUXCTL_ACTL_TX_6DB;
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
 
-		if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-		     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
-		    !tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
-			tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2,
-					 val | MII_TG3_DSP_CH34TP2_HIBW01);
+		switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+		case ASIC_REV_5717:
+		case ASIC_REV_57765:
+			if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+				tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
+						 MII_TG3_DSP_CH34TP2_HIBW01);
+			/* Fall through */
+		case ASIC_REV_5719:
+			val = MII_TG3_DSP_TAP26_ALNOKO |
+			      MII_TG3_DSP_TAP26_RMRXSTO |
+			      MII_TG3_DSP_TAP26_OPCSINPT;
+			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
+		}
 
 		val = 0;
 		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
@@ -7801,7 +7830,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 		       TG3_CPMU_DBTMR1_LNKIDLE_2047US);
 
 		tw32_f(TG3_CPMU_EEE_DBTMR2,
-		       TG3_CPMU_DBTMR1_APE_TX_2047US |
+		       TG3_CPMU_DBTMR2_APE_TX_2047US |
 		       TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
 	}
 
@@ -8075,8 +8104,9 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	/* Program the jumbo buffer descriptor ring control
 	 * blocks on those devices that have them.
 	 */
-	if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
-	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	    ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))) {
 		/* Setup replenish threshold. */
 		tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8);
 
@@ -8163,10 +8193,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 			      RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
 			      RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
 
-	/* If statement applies to 5705 and 5750 PCI devices only */
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
 		if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 			rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
@@ -8194,8 +8222,12 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	    (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) {
 		val = tr32(TG3_RDMA_RSRVCTRL_REG);
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
-			val &= ~TG3_RDMA_RSRVCTRL_TXMRGN_MASK;
-			val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B;
+			val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK |
+				 TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+				 TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK);
+			val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B |
+			       TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+			       TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K;
 		}
 		tw32(TG3_RDMA_RSRVCTRL_REG,
 		     val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
@@ -8317,7 +8349,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
-	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) {
+	if ((tp->tg3_flags2 & TG3_FLG2_USING_MSIX) &&
+		tp->irq_cnt > 1) {
 		val = tr32(MSGINT_MODE);
 		val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
 		tw32(MSGINT_MODE, val);
@@ -8334,17 +8367,14 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
 	       WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
 	       WDMAC_MODE_LNGREAD_ENAB);
 
-	/* If statement applies to 5705 and 5750 PCI devices only */
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
 		if ((tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) &&
 		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
 		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
 			/* nothing */
 		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
-			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
-			   !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
 			val |= WDMAC_MODE_RX_ACCEL;
 		}
 	}
@@ -9057,7 +9087,8 @@ static void tg3_ints_init(struct tg3 *tp)
 
 	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
 		u32 msi_mode = tr32(MSGINT_MODE);
-		if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+		if ((tp->tg3_flags2 & TG3_FLG2_USING_MSIX) &&
+		    tp->irq_cnt > 1)
 			msi_mode |= MSGINT_MODE_MULTIVEC_EN;
 		tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
 	}
@@ -10452,16 +10483,53 @@ static int tg3_test_nvram(struct tg3 *tp)
 		goto out;
 	}
 
+	err = -EIO;
+
 	/* Bootstrap checksum at offset 0x10 */
 	csum = calc_crc((unsigned char *) buf, 0x10);
-	if (csum != be32_to_cpu(buf[0x10/4]))
+	if (csum != le32_to_cpu(buf[0x10/4]))
 		goto out;
 
 	/* Manufacturing block starts at offset 0x74, checksum at 0xfc */
 	csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
-	if (csum != be32_to_cpu(buf[0xfc/4]))
+	if (csum != le32_to_cpu(buf[0xfc/4]))
 		goto out;
 
+	for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
+		/* The data is in little-endian format in NVRAM.
+		 * Use the big-endian read routines to preserve
+		 * the byte order as it exists in NVRAM.
+		 */
+		if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &buf[i/4]))
+			goto out;
+	}
+
+	i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN,
+			     PCI_VPD_LRDT_RO_DATA);
+	if (i > 0) {
+		j = pci_vpd_lrdt_size(&((u8 *)buf)[i]);
+		if (j < 0)
+			goto out;
+
+		if (i + PCI_VPD_LRDT_TAG_SIZE + j > TG3_NVM_VPD_LEN)
+			goto out;
+
+		i += PCI_VPD_LRDT_TAG_SIZE;
+		j = pci_vpd_find_info_keyword((u8 *)buf, i, j,
+					      PCI_VPD_RO_KEYWORD_CHKSUM);
+		if (j > 0) {
+			u8 csum8 = 0;
+
+			j += PCI_VPD_INFO_FLD_HDR_SIZE;
+
+			for (i = 0; i <= j; i++)
+				csum8 += ((u8 *)buf)[i];
+
+			if (csum8)
+				goto out;
+		}
+	}
+
 	err = 0;
 
 out:
@@ -10833,13 +10901,16 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 	if (loopback_mode == TG3_MAC_LOOPBACK) {
 		/* HW errata - mac loopback fails in some cases on 5780.
 		 * Normal traffic and PHY loopback are not affected by
-		 * errata.
+		 * errata.  Also, the MAC loopback test is deprecated for
+		 * all newer ASIC revisions.
 		 */
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+		    (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT))
 			return 0;
 
-		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-			   MAC_MODE_PORT_INT_LPBACK;
+		mac_mode = tp->mac_mode &
+			   ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+		mac_mode |= MAC_MODE_PORT_INT_LPBACK;
 		if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 			mac_mode |= MAC_MODE_LINK_POLARITY;
 		if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
@@ -10861,7 +10932,8 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 		tg3_writephy(tp, MII_BMCR, val);
 		udelay(40);
 
-		mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+		mac_mode = tp->mac_mode &
+			   ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
 		if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
 			tg3_writephy(tp, MII_TG3_FET_PTEST,
 				     MII_TG3_FET_PTEST_FRC_TX_LINK |
@@ -10889,6 +10961,13 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode)
 				     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
 		}
 		tw32(MAC_MODE, mac_mode);
+
+		/* Wait for link */
+		for (i = 0; i < 100; i++) {
+			if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
+				break;
+			mdelay(1);
+		}
 	} else {
 		return -EINVAL;
 	}
@@ -10995,14 +11074,19 @@ out:
 static int tg3_test_loopback(struct tg3 *tp)
 {
 	int err = 0;
-	u32 cpmuctrl = 0;
+	u32 eee_cap, cpmuctrl = 0;
 
 	if (!netif_running(tp->dev))
 		return TG3_LOOPBACK_FAILED;
 
+	eee_cap = tp->phy_flags & TG3_PHYFLG_EEE_CAP;
+	tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
+
 	err = tg3_reset_hw(tp, 1);
-	if (err)
-		return TG3_LOOPBACK_FAILED;
+	if (err) {
+		err = TG3_LOOPBACK_FAILED;
+		goto done;
+	}
 
 	/* Turn off gphy autopowerdown. */
 	if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
@@ -11022,8 +11106,10 @@ static int tg3_test_loopback(struct tg3 *tp)
 			udelay(10);
 		}
 
-		if (status != CPMU_MUTEX_GNT_DRIVER)
-			return TG3_LOOPBACK_FAILED;
+		if (status != CPMU_MUTEX_GNT_DRIVER) {
+			err = TG3_LOOPBACK_FAILED;
+			goto done;
+		}
 
 		/* Turn off link-based power management. */
 		cpmuctrl = tr32(TG3_CPMU_CTRL);
@@ -11052,6 +11138,9 @@ static int tg3_test_loopback(struct tg3 *tp)
 	if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
 		tg3_phy_toggle_apd(tp, true);
 
+done:
+	tp->phy_flags |= eee_cap;
+
 	return err;
 }
 
@@ -12407,9 +12496,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 			tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN;
 	}
 done:
-	device_init_wakeup(&tp->pdev->dev, tp->tg3_flags & TG3_FLAG_WOL_CAP);
-	device_set_wakeup_enable(&tp->pdev->dev,
+	if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+		device_set_wakeup_enable(&tp->pdev->dev,
 				 tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+	else
+		device_set_wakeup_capable(&tp->pdev->dev, false);
 }
 
 static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
@@ -12461,12 +12552,45 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
 	return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
 }
 
+static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
+{
+	u32 adv = ADVERTISED_Autoneg |
+		  ADVERTISED_Pause;
+
+	if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
+		adv |= ADVERTISED_1000baseT_Half |
+		       ADVERTISED_1000baseT_Full;
+
+	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+		adv |= ADVERTISED_100baseT_Half |
+		       ADVERTISED_100baseT_Full |
+		       ADVERTISED_10baseT_Half |
+		       ADVERTISED_10baseT_Full |
+		       ADVERTISED_TP;
+	else
+		adv |= ADVERTISED_FIBRE;
+
+	tp->link_config.advertising = adv;
+	tp->link_config.speed = SPEED_INVALID;
+	tp->link_config.duplex = DUPLEX_INVALID;
+	tp->link_config.autoneg = AUTONEG_ENABLE;
+	tp->link_config.active_speed = SPEED_INVALID;
+	tp->link_config.active_duplex = DUPLEX_INVALID;
+	tp->link_config.orig_speed = SPEED_INVALID;
+	tp->link_config.orig_duplex = DUPLEX_INVALID;
+	tp->link_config.orig_autoneg = AUTONEG_INVALID;
+}
+
 static int __devinit tg3_phy_probe(struct tg3 *tp)
 {
 	u32 hw_phy_id_1, hw_phy_id_2;
 	u32 hw_phy_id, hw_phy_id_masked;
 	int err;
 
+	/* flow control autonegotiation is default behavior */
+	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+	tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+
 	if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)
 		return tg3_phy_init(tp);
 
@@ -12528,6 +12652,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
 	      tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
 		tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
 
+	tg3_phy_init_link_config(tp);
+
 	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
 	    !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
@@ -12583,17 +12709,6 @@ skip_phy_reset:
 		err = tg3_init_5401phy_dsp(tp);
 	}
 
-	if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
-		tp->link_config.advertising =
-			(ADVERTISED_1000baseT_Half |
-			 ADVERTISED_1000baseT_Full |
-			 ADVERTISED_Autoneg |
-			 ADVERTISED_FIBRE);
-	if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
-		tp->link_config.advertising &=
-			~(ADVERTISED_1000baseT_Half |
-			  ADVERTISED_1000baseT_Full);
-
 	return err;
 }
 
@@ -13020,7 +13135,7 @@ static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp)
 		return 512;
 }
 
-DEFINE_PCI_DEVICE_TABLE(write_reorder_chipsets) = {
+static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) },
@@ -13262,7 +13377,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	}
 
 	/* Determine TSO capabilities */
-	if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		; /* Do nothing. HW bug. */
+	else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
 		tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3;
 	else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
 		 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
@@ -13313,7 +13430,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG;
 	}
 
-	if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
+	if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
 		tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG;
 
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
@@ -13331,42 +13449,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
 		tp->pcie_readrq = 4096;
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
-			u16 word;
-
-			pci_read_config_word(tp->pdev,
-					     tp->pcie_cap + PCI_EXP_LNKSTA,
-					     &word);
-			switch (word & PCI_EXP_LNKSTA_CLS) {
-			case PCI_EXP_LNKSTA_CLS_2_5GB:
-				word &= PCI_EXP_LNKSTA_NLW;
-				word >>= PCI_EXP_LNKSTA_NLW_SHIFT;
-				switch (word) {
-				case 2:
-					tp->pcie_readrq = 2048;
-					break;
-				case 4:
-					tp->pcie_readrq = 1024;
-					break;
-				}
-				break;
-
-			case PCI_EXP_LNKSTA_CLS_5_0GB:
-				word &= PCI_EXP_LNKSTA_NLW;
-				word >>= PCI_EXP_LNKSTA_NLW_SHIFT;
-				switch (word) {
-				case 1:
-					tp->pcie_readrq = 2048;
-					break;
-				case 2:
-					tp->pcie_readrq = 1024;
-					break;
-				case 4:
-					tp->pcie_readrq = 512;
-					break;
-				}
-			}
-		}
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+			tp->pcie_readrq = 2048;
 
 		pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 
@@ -13405,7 +13489,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 	 * every mailbox register write to force the writes to be
 	 * posted to the chip in order.
 	 */
-	if (pci_dev_present(write_reorder_chipsets) &&
+	if (pci_dev_present(tg3_write_reorder_chipsets) &&
 	    !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
 		tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
 
@@ -14161,7 +14245,7 @@ static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dm
 
 #define TEST_BUFFER_SIZE	0x2000
 
-DEFINE_PCI_DEVICE_TABLE(dma_wait_state_chipsets) = {
+static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
 	{ },
 };
@@ -14340,7 +14424,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
 		 * now look for chipsets that are known to expose the
 		 * DMA bug without failing the test.
 		 */
-		if (pci_dev_present(dma_wait_state_chipsets)) {
+		if (pci_dev_present(tg3_dma_wait_state_chipsets)) {
 			tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
 			tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
 		} else {
@@ -14357,23 +14441,6 @@ out_nofree:
 	return ret;
 }
 
-static void __devinit tg3_init_link_config(struct tg3 *tp)
-{
-	tp->link_config.advertising =
-		(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-		 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-		 ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
-		 ADVERTISED_Autoneg | ADVERTISED_MII);
-	tp->link_config.speed = SPEED_INVALID;
-	tp->link_config.duplex = DUPLEX_INVALID;
-	tp->link_config.autoneg = AUTONEG_ENABLE;
-	tp->link_config.active_speed = SPEED_INVALID;
-	tp->link_config.active_duplex = DUPLEX_INVALID;
-	tp->link_config.orig_speed = SPEED_INVALID;
-	tp->link_config.orig_duplex = DUPLEX_INVALID;
-	tp->link_config.orig_autoneg = AUTONEG_INVALID;
-}
-
 static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
 {
 	if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) {
@@ -14677,8 +14744,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		goto err_out_free_dev;
 	}
 
-	tg3_init_link_config(tp);
-
 	tp->rx_pending = TG3_DEF_RX_RING_PENDING;
 	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
 
@@ -14826,10 +14891,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 		goto err_out_apeunmap;
 	}
 
-	/* flow control autonegotiation is default behavior */
-	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
-	tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
-
 	intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
 	rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
 	sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index f528243..73884b6 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -4,7 +4,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2007-2010 Broadcom Corporation.
+ * Copyright (C) 2007-2011 Broadcom Corporation.
  */
 
 #ifndef _T3_H
@@ -141,6 +141,7 @@
 #define  CHIPREV_ID_57780_A1		 0x57780001
 #define  CHIPREV_ID_5717_A0		 0x05717000
 #define  CHIPREV_ID_57765_A0		 0x57785000
+#define  CHIPREV_ID_5719_A0		 0x05719000
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -1105,7 +1106,7 @@
 #define  TG3_CPMU_DBTMR1_PCIEXIT_2047US	 0x07ff0000
 #define  TG3_CPMU_DBTMR1_LNKIDLE_2047US	 0x000070ff
 #define TG3_CPMU_EEE_DBTMR2		0x000036b8
-#define  TG3_CPMU_DBTMR1_APE_TX_2047US	 0x07ff0000
+#define  TG3_CPMU_DBTMR2_APE_TX_2047US	 0x07ff0000
 #define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US	 0x000070ff
 #define TG3_CPMU_EEE_LNKIDL_CTRL	0x000036bc
 #define  TG3_CPMU_EEE_LNKIDL_PCIE_NL0	 0x01000000
@@ -1333,6 +1334,10 @@
 
 #define TG3_RDMA_RSRVCTRL_REG		0x00004900
 #define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX	 0x00000004
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K	 0x00000c00
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK	 0x00000ff0
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K	 0x000c0000
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK	 0x000ff000
 #define TG3_RDMA_RSRVCTRL_TXMRGN_320B	 0x28000000
 #define TG3_RDMA_RSRVCTRL_TXMRGN_MASK	 0xffe00000
 /* 0x4904 --> 0x4910 unused */
@@ -2108,6 +2113,10 @@
 
 #define MII_TG3_DSP_TAP1		0x0001
 #define  MII_TG3_DSP_TAP1_AGCTGT_DFLT	0x0007
+#define MII_TG3_DSP_TAP26		0x001a
+#define  MII_TG3_DSP_TAP26_ALNOKO	0x0001
+#define  MII_TG3_DSP_TAP26_RMRXSTO	0x0002
+#define  MII_TG3_DSP_TAP26_OPCSINPT	0x0004
 #define MII_TG3_DSP_AADJ1CH0		0x001f
 #define MII_TG3_DSP_CH34TP2		0x4022
 #define MII_TG3_DSP_CH34TP2_HIBW01	0x0010
diff --git a/drivers/net/tile/tilepro.c b/drivers/net/tile/tilepro.c
index 7cb301d..0825db6 100644
--- a/drivers/net/tile/tilepro.c
+++ b/drivers/net/tile/tilepro.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ * Copyright 2011 Tilera 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
@@ -44,10 +44,6 @@
 #include <linux/tcp.h>
 
 
-/* There is no singlethread_cpu, so schedule work on the current cpu. */
-#define singlethread_cpu -1
-
-
 /*
  * First, "tile_net_init_module()" initializes all four "devices" which
  * can be used by linux.
@@ -73,15 +69,16 @@
  * return, knowing we will be called again later.  Otherwise, we
  * reenable the ingress interrupt, and call "napi_complete()".
  *
+ * HACK: Since disabling the ingress interrupt is not reliable, we
+ * ignore the interrupt if the global "active" flag is false.
+ *
  *
  * NOTE: The use of "native_driver" ensures that EPP exists, and that
- * "epp_sendv" is legal, and that "LIPP" is being used.
+ * we are using "LIPP" and "LEPP".
  *
  * NOTE: Failing to free completions for an arbitrarily long time
  * (which is defined to be illegal) does in fact cause bizarre
  * problems.  The "egress_timer" helps prevent this from happening.
- *
- * NOTE: The egress code can be interrupted by the interrupt handler.
  */
 
 
@@ -142,6 +139,7 @@
 MODULE_AUTHOR("Tilera");
 MODULE_LICENSE("GPL");
 
+
 /*
  * Queue of incoming packets for a specific cpu and device.
  *
@@ -177,7 +175,7 @@ struct tile_net_cpu {
 	struct tile_netio_queue queue;
 	/* Statistics. */
 	struct tile_net_stats_t stats;
-	/* ISSUE: Is this needed? */
+	/* True iff NAPI is enabled. */
 	bool napi_enabled;
 	/* True if this tile has succcessfully registered with the IPP. */
 	bool registered;
@@ -200,20 +198,20 @@ struct tile_net_cpu {
 struct tile_net_priv {
 	/* Our network device. */
 	struct net_device *dev;
-	/* The actual egress queue. */
-	lepp_queue_t *epp_queue;
-	/* Protects "epp_queue->cmd_tail" and "epp_queue->comp_tail" */
-	spinlock_t cmd_lock;
-	/* Protects "epp_queue->comp_head". */
-	spinlock_t comp_lock;
+	/* Pages making up the egress queue. */
+	struct page *eq_pages;
+	/* Address of the actual egress queue. */
+	lepp_queue_t *eq;
+	/* Protects "eq". */
+	spinlock_t eq_lock;
 	/* The hypervisor handle for this interface. */
 	int hv_devhdl;
 	/* The intr bit mask that IDs this device. */
 	u32 intr_id;
 	/* True iff "tile_net_open_aux()" has succeeded. */
-	int partly_opened;
-	/* True iff "tile_net_open_inner()" has succeeded. */
-	int fully_opened;
+	bool partly_opened;
+	/* True iff the device is "active". */
+	bool active;
 	/* Effective network cpus. */
 	struct cpumask network_cpus_map;
 	/* Number of network cpus. */
@@ -228,6 +226,10 @@ struct tile_net_priv {
 	struct tile_net_cpu *cpu[NR_CPUS];
 };
 
+/* Log2 of the number of small pages needed for the egress queue. */
+#define EQ_ORDER  get_order(sizeof(lepp_queue_t))
+/* Size of the egress queue's pages. */
+#define EQ_SIZE   (1 << (PAGE_SHIFT + EQ_ORDER))
 
 /*
  * The actual devices (xgbe0, xgbe1, gbe0, gbe1).
@@ -284,7 +286,11 @@ static void net_printk(char *fmt, ...)
  */
 static void dump_packet(unsigned char *data, unsigned long length, char *s)
 {
+	int my_cpu = smp_processor_id();
+
 	unsigned long i;
+	char buf[128];
+
 	static unsigned int count;
 
 	pr_info("dump_packet(data %p, length 0x%lx s %s count 0x%x)\n",
@@ -294,10 +300,12 @@ static void dump_packet(unsigned char *data, unsigned long length, char *s)
 
 	for (i = 0; i < length; i++) {
 		if ((i & 0xf) == 0)
-			sprintf(buf, "%8.8lx:", i);
+			sprintf(buf, "[%02d] %8.8lx:", my_cpu, i);
 		sprintf(buf + strlen(buf), " %2.2x", data[i]);
-		if ((i & 0xf) == 0xf || i == length - 1)
-			pr_info("%s\n", buf);
+		if ((i & 0xf) == 0xf || i == length - 1) {
+			strcat(buf, "\n");
+			pr_info("%s", buf);
+		}
 	}
 }
 #endif
@@ -351,60 +359,109 @@ static void tile_net_provide_linux_buffer(struct tile_net_cpu *info,
 
 /*
  * Provide a linux buffer for LIPP.
+ *
+ * Note that the ACTUAL allocation for each buffer is a "struct sk_buff",
+ * plus a chunk of memory that includes not only the requested bytes, but
+ * also NET_SKB_PAD bytes of initial padding, and a "struct skb_shared_info".
+ *
+ * Note that "struct skb_shared_info" is 88 bytes with 64K pages and
+ * 268 bytes with 4K pages (since the frags[] array needs 18 entries).
+ *
+ * Without jumbo packets, the maximum packet size will be 1536 bytes,
+ * and we use 2 bytes (NET_IP_ALIGN) of padding.  ISSUE: If we told
+ * the hardware to clip at 1518 bytes instead of 1536 bytes, then we
+ * could save an entire cache line, but in practice, we don't need it.
+ *
+ * Since CPAs are 38 bits, and we can only encode the high 31 bits in
+ * a "linux_buffer_t", the low 7 bits must be zero, and thus, we must
+ * align the actual "va" mod 128.
+ *
+ * We assume that the underlying "head" will be aligned mod 64.  Note
+ * that in practice, we have seen "head" NOT aligned mod 128 even when
+ * using 2048 byte allocations, which is surprising.
+ *
+ * If "head" WAS always aligned mod 128, we could change LIPP to
+ * assume that the low SIX bits are zero, and the 7th bit is one, that
+ * is, align the actual "va" mod 128 plus 64, which would be "free".
+ *
+ * For now, the actual "head" pointer points at NET_SKB_PAD bytes of
+ * padding, plus 28 or 92 bytes of extra padding, plus the sk_buff
+ * pointer, plus the NET_IP_ALIGN padding, plus 126 or 1536 bytes for
+ * the actual packet, plus 62 bytes of empty padding, plus some
+ * padding and the "struct skb_shared_info".
+ *
+ * With 64K pages, a large buffer thus needs 32+92+4+2+1536+62+88
+ * bytes, or 1816 bytes, which fits comfortably into 2048 bytes.
+ *
+ * With 64K pages, a small buffer thus needs 32+92+4+2+126+88
+ * bytes, or 344 bytes, which means we are wasting 64+ bytes, and
+ * could presumably increase the size of small buffers.
+ *
+ * With 4K pages, a large buffer thus needs 32+92+4+2+1536+62+268
+ * bytes, or 1996 bytes, which fits comfortably into 2048 bytes.
+ *
+ * With 4K pages, a small buffer thus needs 32+92+4+2+126+268
+ * bytes, or 524 bytes, which is annoyingly wasteful.
+ *
+ * Maybe we should increase LIPP_SMALL_PACKET_SIZE to 192?
+ *
+ * ISSUE: Maybe we should increase "NET_SKB_PAD" to 64?
  */
 static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
 					   bool small)
 {
-	/* ISSUE: What should we use here? */
+#if TILE_NET_MTU <= 1536
+	/* Without "jumbo", 2 + 1536 should be sufficient. */
+	unsigned int large_size = NET_IP_ALIGN + 1536;
+#else
+	/* ISSUE: This has not been tested. */
 	unsigned int large_size = NET_IP_ALIGN + TILE_NET_MTU + 100;
+#endif
 
-	/* Round up to ensure to avoid "false sharing" with last cache line. */
-	unsigned int buffer_size =
+	/* Avoid "false sharing" with last cache line. */
+	/* ISSUE: This is already done by "dev_alloc_skb()". */
+	unsigned int len =
 		 (((small ? LIPP_SMALL_PACKET_SIZE : large_size) +
 		   CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE());
 
-	/*
-	 * ISSUE: Since CPAs are 38 bits, and we can only encode the
-	 * high 31 bits in a "linux_buffer_t", the low 7 bits must be
-	 * zero, and thus, we must align the actual "va" mod 128.
-	 */
-	const unsigned long align = 128;
+	unsigned int padding = 128 - NET_SKB_PAD;
+	unsigned int align;
 
 	struct sk_buff *skb;
 	void *va;
 
 	struct sk_buff **skb_ptr;
 
-	/* Note that "dev_alloc_skb()" adds NET_SKB_PAD more bytes, */
-	/* and also "reserves" that many bytes. */
-	/* ISSUE: Can we "share" the NET_SKB_PAD bytes with "skb_ptr"? */
-	int len = sizeof(*skb_ptr) + align + buffer_size;
-
-	while (1) {
-
-		/* Allocate (or fail). */
-		skb = dev_alloc_skb(len);
-		if (skb == NULL)
-			return false;
-
-		/* Make room for a back-pointer to 'skb'. */
-		skb_reserve(skb, sizeof(*skb_ptr));
+	/* Request 96 extra bytes for alignment purposes. */
+	skb = dev_alloc_skb(len + padding);
+	if (skb == NULL)
+		return false;
 
-		/* Make sure we are aligned. */
-		skb_reserve(skb, -(long)skb->data & (align - 1));
+	/* Skip 32 or 96 bytes to align "data" mod 128. */
+	align = -(long)skb->data & (128 - 1);
+	BUG_ON(align > padding);
+	skb_reserve(skb, align);
 
-		/* This address is given to IPP. */
-		va = skb->data;
+	/* This address is given to IPP. */
+	va = skb->data;
 
-		if (small)
-			break;
+	/* Buffers must not span a huge page. */
+	BUG_ON(((((long)va & ~HPAGE_MASK) + len) & HPAGE_MASK) != 0);
 
-		/* ISSUE: This has never been observed! */
-		/* Large buffers must not span a huge page. */
-		if (((((long)va & ~HPAGE_MASK) + 1535) & HPAGE_MASK) == 0)
-			break;
-		pr_err("Leaking unaligned linux buffer at %p.\n", va);
+#ifdef TILE_NET_PARANOIA
+#if CHIP_HAS_CBOX_HOME_MAP()
+	if (hash_default) {
+		HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va);
+		if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
+			panic("Non-HFH ingress buffer! VA=%p Mode=%d PTE=%llx",
+			      va, hv_pte_get_mode(pte), hv_pte_val(pte));
 	}
+#endif
+#endif
+
+	/* Invalidate the packet buffer. */
+	if (!hash_default)
+		__inv_buffer(va, len);
 
 	/* Skip two bytes to satisfy LIPP assumptions. */
 	/* Note that this aligns IP on a 16 byte boundary. */
@@ -415,23 +472,9 @@ static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
 	skb_ptr = va - sizeof(*skb_ptr);
 	*skb_ptr = skb;
 
-	/* Invalidate the packet buffer. */
-	if (!hash_default)
-		__inv_buffer(skb->data, buffer_size);
-
 	/* Make sure "skb_ptr" has been flushed. */
 	__insn_mf();
 
-#ifdef TILE_NET_PARANOIA
-#if CHIP_HAS_CBOX_HOME_MAP()
-	if (hash_default) {
-		HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va);
-		if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
-			panic("Non-coherent ingress buffer!");
-	}
-#endif
-#endif
-
 	/* Provide the new buffer. */
 	tile_net_provide_linux_buffer(info, va, small);
 
@@ -469,48 +512,64 @@ oops:
  * Grab some LEPP completions, and store them in "comps", of size
  * "comps_size", and return the number of completions which were
  * stored, so the caller can free them.
- *
- * If "pending" is not NULL, it will be set to true if there might
- * still be some pending completions caused by this tile, else false.
  */
-static unsigned int tile_net_lepp_grab_comps(struct net_device *dev,
+static unsigned int tile_net_lepp_grab_comps(lepp_queue_t *eq,
 					     struct sk_buff *comps[],
 					     unsigned int comps_size,
-					     bool *pending)
+					     unsigned int min_size)
 {
-	struct tile_net_priv *priv = netdev_priv(dev);
-
-	lepp_queue_t *eq = priv->epp_queue;
-
 	unsigned int n = 0;
 
-	unsigned int comp_head;
-	unsigned int comp_busy;
-	unsigned int comp_tail;
-
-	spin_lock(&priv->comp_lock);
-
-	comp_head = eq->comp_head;
-	comp_busy = eq->comp_busy;
-	comp_tail = eq->comp_tail;
+	unsigned int comp_head = eq->comp_head;
+	unsigned int comp_busy = eq->comp_busy;
 
 	while (comp_head != comp_busy && n < comps_size) {
 		comps[n++] = eq->comps[comp_head];
 		LEPP_QINC(comp_head);
 	}
 
-	if (pending != NULL)
-		*pending = (comp_head != comp_tail);
+	if (n < min_size)
+		return 0;
 
 	eq->comp_head = comp_head;
 
-	spin_unlock(&priv->comp_lock);
-
 	return n;
 }
 
 
 /*
+ * Free some comps, and return true iff there are still some pending.
+ */
+static bool tile_net_lepp_free_comps(struct net_device *dev, bool all)
+{
+	struct tile_net_priv *priv = netdev_priv(dev);
+
+	lepp_queue_t *eq = priv->eq;
+
+	struct sk_buff *olds[64];
+	unsigned int wanted = 64;
+	unsigned int i, n;
+	bool pending;
+
+	spin_lock(&priv->eq_lock);
+
+	if (all)
+		eq->comp_busy = eq->comp_tail;
+
+	n = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+
+	pending = (eq->comp_head != eq->comp_tail);
+
+	spin_unlock(&priv->eq_lock);
+
+	for (i = 0; i < n; i++)
+		kfree_skb(olds[i]);
+
+	return pending;
+}
+
+
+/*
  * Make sure the egress timer is scheduled.
  *
  * Note that we use "schedule if not scheduled" logic instead of the more
@@ -544,21 +603,11 @@ static void tile_net_handle_egress_timer(unsigned long arg)
 	struct tile_net_cpu *info = (struct tile_net_cpu *)arg;
 	struct net_device *dev = info->napi.dev;
 
-	struct sk_buff *olds[32];
-	unsigned int wanted = 32;
-	unsigned int i, nolds = 0;
-	bool pending;
-
 	/* The timer is no longer scheduled. */
 	info->egress_timer_scheduled = false;
 
-	nolds = tile_net_lepp_grab_comps(dev, olds, wanted, &pending);
-
-	for (i = 0; i < nolds; i++)
-		kfree_skb(olds[i]);
-
-	/* Reschedule timer if needed. */
-	if (pending)
+	/* Free comps, and reschedule timer if more are pending. */
+	if (tile_net_lepp_free_comps(dev, false))
 		tile_net_schedule_egress_timer(info);
 }
 
@@ -636,8 +685,39 @@ static bool is_dup_ack(char *s1, char *s2, unsigned int len)
 
 
 
+static void tile_net_discard_aux(struct tile_net_cpu *info, int index)
+{
+	struct tile_netio_queue *queue = &info->queue;
+	netio_queue_impl_t *qsp = queue->__system_part;
+	netio_queue_user_impl_t *qup = &queue->__user_part;
+
+	int index2_aux = index + sizeof(netio_pkt_t);
+	int index2 =
+		((index2_aux ==
+		  qsp->__packet_receive_queue.__last_packet_plus_one) ?
+		 0 : index2_aux);
+
+	netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index);
+
+	/* Extract the "linux_buffer_t". */
+	unsigned int buffer = pkt->__packet.word;
+
+	/* Convert "linux_buffer_t" to "va". */
+	void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+	/* Acquire the associated "skb". */
+	struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+	struct sk_buff *skb = *skb_ptr;
+
+	kfree_skb(skb);
+
+	/* Consume this packet. */
+	qup->__packet_receive_read = index2;
+}
+
+
 /*
- * Like "tile_net_handle_packets()", but just discard packets.
+ * Like "tile_net_poll()", but just discard packets.
  */
 static void tile_net_discard_packets(struct net_device *dev)
 {
@@ -650,32 +730,8 @@ static void tile_net_discard_packets(struct net_device *dev)
 
 	while (qup->__packet_receive_read !=
 	       qsp->__packet_receive_queue.__packet_write) {
-
 		int index = qup->__packet_receive_read;
-
-		int index2_aux = index + sizeof(netio_pkt_t);
-		int index2 =
-			((index2_aux ==
-			  qsp->__packet_receive_queue.__last_packet_plus_one) ?
-			 0 : index2_aux);
-
-		netio_pkt_t *pkt = (netio_pkt_t *)
-			((unsigned long) &qsp[1] + index);
-
-		/* Extract the "linux_buffer_t". */
-		unsigned int buffer = pkt->__packet.word;
-
-		/* Convert "linux_buffer_t" to "va". */
-		void *va = __va((phys_addr_t)(buffer >> 1) << 7);
-
-		/* Acquire the associated "skb". */
-		struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
-		struct sk_buff *skb = *skb_ptr;
-
-		kfree_skb(skb);
-
-		/* Consume this packet. */
-		qup->__packet_receive_read = index2;
+		tile_net_discard_aux(info, index);
 	}
 }
 
@@ -704,7 +760,8 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 
 	netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt);
 
-	/* Extract the packet size. */
+	/* Extract the packet size.  FIXME: Shouldn't the second line */
+	/* get subtracted?  Mostly moot, since it should be "zero". */
 	unsigned long len =
 		(NETIO_PKT_CUSTOM_LENGTH(pkt) +
 		 NET_IP_ALIGN - NETIO_PACKET_PADDING);
@@ -722,15 +779,6 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 	/* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
 	unsigned char *buf = va + NET_IP_ALIGN;
 
-#ifdef IGNORE_DUP_ACKS
-
-	static int other;
-	static int final;
-	static int keep;
-	static int skip;
-
-#endif
-
 	/* Invalidate the packet buffer. */
 	if (!hash_default)
 		__inv_buffer(buf, len);
@@ -745,16 +793,8 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 #ifdef TILE_NET_VERIFY_INGRESS
 	if (!NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt) &&
 	    NETIO_PKT_L4_CSUM_CALCULATED_M(metadata, pkt)) {
-		/*
-		 * FIXME: This complains about UDP packets
-		 * with a "zero" checksum (bug 6624).
-		 */
-#ifdef TILE_NET_PANIC_ON_BAD
-		dump_packet(buf, len, "rx");
-		panic("Bad L4 checksum.");
-#else
+		/* Bug 6624: Includes UDP packets with a "zero" checksum. */
 		pr_warning("Bad L4 checksum on %d byte packet.\n", len);
-#endif
 	}
 	if (!NETIO_PKT_L3_CSUM_CORRECT_M(metadata, pkt) &&
 	    NETIO_PKT_L3_CSUM_CALCULATED_M(metadata, pkt)) {
@@ -769,90 +809,29 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 		}
 		break;
 	case NETIO_PKT_STATUS_BAD:
-#ifdef TILE_NET_PANIC_ON_BAD
-		dump_packet(buf, len, "rx");
-		panic("Unexpected BAD packet.");
-#else
-		pr_warning("Unexpected BAD %d byte packet.\n", len);
-#endif
+		pr_warning("Unexpected BAD %ld byte packet.\n", len);
 	}
 #endif
 
 	filter = 0;
 
+	/* ISSUE: Filter TCP packets with "bad" checksums? */
+
 	if (!(dev->flags & IFF_UP)) {
 		/* Filter packets received before we're up. */
 		filter = 1;
+	} else if (NETIO_PKT_STATUS_M(metadata, pkt) == NETIO_PKT_STATUS_BAD) {
+		/* Filter "truncated" packets. */
+		filter = 1;
 	} else if (!(dev->flags & IFF_PROMISC)) {
-		/*
-		 * FIXME: Implement HW multicast filter.
-		 */
-		if (is_unicast_ether_addr(buf)) {
+		/* FIXME: Implement HW multicast filter. */
+		if (!is_multicast_ether_addr(buf)) {
 			/* Filter packets not for our address. */
 			const u8 *mine = dev->dev_addr;
 			filter = compare_ether_addr(mine, buf);
 		}
 	}
 
-#ifdef IGNORE_DUP_ACKS
-
-	if (len != 66) {
-		/* FIXME: Must check "is_tcp_ack(buf, len)" somehow. */
-
-		other++;
-
-	} else if (index2 ==
-		   qsp->__packet_receive_queue.__packet_write) {
-
-		final++;
-
-	} else {
-
-		netio_pkt_t *pkt2 = (netio_pkt_t *)
-			((unsigned long) &qsp[1] + index2);
-
-		netio_pkt_metadata_t *metadata2 =
-			NETIO_PKT_METADATA(pkt2);
-
-		/* Extract the packet size. */
-		unsigned long len2 =
-			(NETIO_PKT_CUSTOM_LENGTH(pkt2) +
-			 NET_IP_ALIGN - NETIO_PACKET_PADDING);
-
-		if (len2 == 66 &&
-		    NETIO_PKT_FLOW_HASH_M(metadata, pkt) ==
-		    NETIO_PKT_FLOW_HASH_M(metadata2, pkt2)) {
-
-			/* Extract the "linux_buffer_t". */
-			unsigned int buffer2 = pkt2->__packet.word;
-
-			/* Convert "linux_buffer_t" to "va". */
-			void *va2 =
-				__va((phys_addr_t)(buffer2 >> 1) << 7);
-
-			/* Extract the packet data pointer. */
-			/* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
-			unsigned char *buf2 = va2 + NET_IP_ALIGN;
-
-			/* Invalidate the packet buffer. */
-			if (!hash_default)
-				__inv_buffer(buf2, len2);
-
-			if (is_dup_ack(buf, buf2, len)) {
-				skip++;
-				filter = 1;
-			} else {
-				keep++;
-			}
-		}
-	}
-
-	if (net_ratelimit())
-		pr_info("Other %d Final %d Keep %d Skip %d.\n",
-			other, final, keep, skip);
-
-#endif
-
 	if (filter) {
 
 		/* ISSUE: Update "drop" statistics? */
@@ -877,10 +856,7 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 		/* NOTE: This call also sets "skb->dev = dev". */
 		skb->protocol = eth_type_trans(skb, dev);
 
-		/* ISSUE: Discard corrupt packets? */
-		/* ISSUE: Discard packets with bad checksums? */
-
-		/* Avoid recomputing TCP/UDP checksums. */
+		/* Avoid recomputing "good" TCP/UDP checksums. */
 		if (NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
@@ -912,9 +888,14 @@ static bool tile_net_poll_aux(struct tile_net_cpu *info, int index)
 /*
  * Handle some packets for the given device on the current CPU.
  *
- * ISSUE: The "rotting packet" race condition occurs if a packet
- * arrives after the queue appears to be empty, and before the
- * hypervisor interrupt is re-enabled.
+ * If "tile_net_stop()" is called on some other tile while this
+ * function is running, we will return, hopefully before that
+ * other tile asks us to call "napi_disable()".
+ *
+ * The "rotting packet" race condition occurs if a packet arrives
+ * during the extremely narrow window between the queue appearing to
+ * be empty, and the ingress interrupt being re-enabled.  This happens
+ * a LOT under heavy network load.
  */
 static int tile_net_poll(struct napi_struct *napi, int budget)
 {
@@ -928,7 +909,7 @@ static int tile_net_poll(struct napi_struct *napi, int budget)
 
 	unsigned int work = 0;
 
-	while (1) {
+	while (priv->active) {
 		int index = qup->__packet_receive_read;
 		if (index == qsp->__packet_receive_queue.__packet_write)
 			break;
@@ -941,19 +922,24 @@ static int tile_net_poll(struct napi_struct *napi, int budget)
 
 	napi_complete(&info->napi);
 
-	/* Re-enable hypervisor interrupts. */
+	if (!priv->active)
+		goto done;
+
+	/* Re-enable the ingress interrupt. */
 	enable_percpu_irq(priv->intr_id);
 
-	/* HACK: Avoid the "rotting packet" problem. */
+	/* HACK: Avoid the "rotting packet" problem (see above). */
 	if (qup->__packet_receive_read !=
-	    qsp->__packet_receive_queue.__packet_write)
-		napi_schedule(&info->napi);
-
-	/* ISSUE: Handle completions? */
+	    qsp->__packet_receive_queue.__packet_write) {
+		/* ISSUE: Sometimes this returns zero, presumably */
+		/* because an interrupt was handled for this tile. */
+		(void)napi_reschedule(&info->napi);
+	}
 
 done:
 
-	tile_net_provide_needed_buffers(info);
+	if (priv->active)
+		tile_net_provide_needed_buffers(info);
 
 	return work;
 }
@@ -961,6 +947,12 @@ done:
 
 /*
  * Handle an ingress interrupt for the given device on the current cpu.
+ *
+ * ISSUE: Sometimes this gets called after "disable_percpu_irq()" has
+ * been called!  This is probably due to "pending hypervisor downcalls".
+ *
+ * ISSUE: Is there any race condition between the "napi_schedule()" here
+ * and the "napi_complete()" call above?
  */
 static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr)
 {
@@ -969,9 +961,15 @@ static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr)
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	/* Disable hypervisor interrupt. */
+	/* Disable the ingress interrupt. */
 	disable_percpu_irq(priv->intr_id);
 
+	/* Ignore unwanted interrupts. */
+	if (!priv->active)
+		return IRQ_HANDLED;
+
+	/* ISSUE: Sometimes "info->napi_enabled" is false here. */
+
 	napi_schedule(&info->napi);
 
 	return IRQ_HANDLED;
@@ -1005,8 +1003,7 @@ static int tile_net_open_aux(struct net_device *dev)
 	 */
 	{
 		int epp_home = hv_lotar_to_cpu(epp_lotar);
-		struct page *page = virt_to_page(priv->epp_queue);
-		homecache_change_page_home(page, 0, epp_home);
+		homecache_change_page_home(priv->eq_pages, EQ_ORDER, epp_home);
 	}
 
 	/*
@@ -1015,9 +1012,9 @@ static int tile_net_open_aux(struct net_device *dev)
 	{
 		netio_ipp_address_t ea = {
 			.va = 0,
-			.pa = __pa(priv->epp_queue),
+			.pa = __pa(priv->eq),
 			.pte = hv_pte(0),
-			.size = PAGE_SIZE,
+			.size = EQ_SIZE,
 		};
 		ea.pte = hv_pte_set_lotar(ea.pte, epp_lotar);
 		ea.pte = hv_pte_set_mode(ea.pte, HV_PTE_MODE_CACHE_TILE_L3);
@@ -1043,7 +1040,7 @@ static int tile_net_open_aux(struct net_device *dev)
 
 
 /*
- * Register with hypervisor on each CPU.
+ * Register with hypervisor on the current CPU.
  *
  * Strangely, this function does important things even if it "fails",
  * which is especially common if the link is not up yet.  Hopefully
@@ -1092,7 +1089,8 @@ static void tile_net_register(void *dev_ptr)
 	priv->cpu[my_cpu] = info;
 
 	/*
-	 * Register ourselves with the IPP.
+	 * Register ourselves with LIPP.  This does a lot of stuff,
+	 * including invoking the LIPP registration code.
 	 */
 	ret = hv_dev_pwrite(priv->hv_devhdl, 0,
 			    (HV_VirtAddr)&config,
@@ -1101,8 +1099,11 @@ static void tile_net_register(void *dev_ptr)
 	PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n",
 	       ret);
 	if (ret < 0) {
-		printk(KERN_DEBUG "hv_dev_pwrite NETIO_IPP_INPUT_REGISTER_OFF"
-		       " failure %d\n", ret);
+		if (ret != NETIO_LINK_DOWN) {
+			printk(KERN_DEBUG "hv_dev_pwrite "
+			       "NETIO_IPP_INPUT_REGISTER_OFF failure %d\n",
+			       ret);
+		}
 		info->link_down = (ret == NETIO_LINK_DOWN);
 		return;
 	}
@@ -1145,15 +1146,47 @@ static void tile_net_register(void *dev_ptr)
 			   NETIO_IPP_GET_FASTIO_OFF);
 	PDEBUG("hv_dev_pread(NETIO_IPP_GET_FASTIO_OFF) returned %d\n", ret);
 
-	netif_napi_add(dev, &info->napi, tile_net_poll, 64);
-
 	/* Now we are registered. */
 	info->registered = true;
 }
 
 
 /*
- * Unregister with hypervisor on each CPU.
+ * Deregister with hypervisor on the current CPU.
+ *
+ * This simply discards all our credits, so no more packets will be
+ * delivered to this tile.  There may still be packets in our queue.
+ *
+ * Also, disable the ingress interrupt.
+ */
+static void tile_net_deregister(void *dev_ptr)
+{
+	struct net_device *dev = (struct net_device *)dev_ptr;
+	struct tile_net_priv *priv = netdev_priv(dev);
+	int my_cpu = smp_processor_id();
+	struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+	/* Disable the ingress interrupt. */
+	disable_percpu_irq(priv->intr_id);
+
+	/* Do nothing else if not registered. */
+	if (info == NULL || !info->registered)
+		return;
+
+	{
+		struct tile_netio_queue *queue = &info->queue;
+		netio_queue_user_impl_t *qup = &queue->__user_part;
+
+		/* Discard all our credits. */
+		__netio_fastio_return_credits(qup->__fastio_index, -1);
+	}
+}
+
+
+/*
+ * Unregister with hypervisor on the current CPU.
+ *
+ * Also, disable the ingress interrupt.
  */
 static void tile_net_unregister(void *dev_ptr)
 {
@@ -1162,35 +1195,23 @@ static void tile_net_unregister(void *dev_ptr)
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	int ret = 0;
+	int ret;
 	int dummy = 0;
 
-	/* Do nothing if never registered. */
-	if (info == NULL)
-		return;
+	/* Disable the ingress interrupt. */
+	disable_percpu_irq(priv->intr_id);
 
-	/* Do nothing if already unregistered. */
-	if (!info->registered)
+	/* Do nothing else if not registered. */
+	if (info == NULL || !info->registered)
 		return;
 
-	/*
-	 * Unregister ourselves with LIPP.
-	 */
+	/* Unregister ourselves with LIPP/LEPP. */
 	ret = hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
 			    sizeof(dummy), NETIO_IPP_INPUT_UNREGISTER_OFF);
-	PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_UNREGISTER_OFF) returned %d\n",
-	       ret);
-	if (ret < 0) {
-		/* FIXME: Just panic? */
-		pr_err("hv_dev_pwrite NETIO_IPP_INPUT_UNREGISTER_OFF"
-		       " failure %d\n", ret);
-	}
+	if (ret < 0)
+		panic("Failed to unregister with LIPP/LEPP!\n");
 
-	/*
-	 * Discard all packets still in our NetIO queue.  Hopefully,
-	 * once the unregister call is complete, there will be no
-	 * packets still in flight on the IDN.
-	 */
+	/* Discard all packets still in our NetIO queue. */
 	tile_net_discard_packets(dev);
 
 	/* Reset state. */
@@ -1200,11 +1221,6 @@ static void tile_net_unregister(void *dev_ptr)
 	/* Cancel egress timer. */
 	del_timer(&info->egress_timer);
 	info->egress_timer_scheduled = false;
-
-	netif_napi_del(&info->napi);
-
-	/* Now we are unregistered. */
-	info->registered = false;
 }
 
 
@@ -1212,18 +1228,28 @@ static void tile_net_unregister(void *dev_ptr)
  * Helper function for "tile_net_stop()".
  *
  * Also used to handle registration failure in "tile_net_open_inner()",
- * when "fully_opened" is known to be false, and the various extra
- * steps in "tile_net_stop()" are not necessary.  ISSUE: It might be
- * simpler if we could just call "tile_net_stop()" anyway.
+ * when the various extra steps in "tile_net_stop()" are not necessary.
  */
 static void tile_net_stop_aux(struct net_device *dev)
 {
 	struct tile_net_priv *priv = netdev_priv(dev);
+	int i;
 
 	int dummy = 0;
 
-	/* Unregister all tiles, so LIPP will stop delivering packets. */
+	/*
+	 * Unregister all tiles, so LIPP will stop delivering packets.
+	 * Also, delete all the "napi" objects (sequentially, to protect
+	 * "dev->napi_list").
+	 */
 	on_each_cpu(tile_net_unregister, (void *)dev, 1);
+	for_each_online_cpu(i) {
+		struct tile_net_cpu *info = priv->cpu[i];
+		if (info != NULL && info->registered) {
+			netif_napi_del(&info->napi);
+			info->registered = false;
+		}
+	}
 
 	/* Stop LIPP/LEPP. */
 	if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
@@ -1235,18 +1261,15 @@ static void tile_net_stop_aux(struct net_device *dev)
 
 
 /*
- * Disable ingress interrupts for the given device on the current cpu.
+ * Disable NAPI for the given device on the current cpu.
  */
-static void tile_net_disable_intr(void *dev_ptr)
+static void tile_net_stop_disable(void *dev_ptr)
 {
 	struct net_device *dev = (struct net_device *)dev_ptr;
 	struct tile_net_priv *priv = netdev_priv(dev);
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	/* Disable hypervisor interrupt. */
-	disable_percpu_irq(priv->intr_id);
-
 	/* Disable NAPI if needed. */
 	if (info != NULL && info->napi_enabled) {
 		napi_disable(&info->napi);
@@ -1256,21 +1279,24 @@ static void tile_net_disable_intr(void *dev_ptr)
 
 
 /*
- * Enable ingress interrupts for the given device on the current cpu.
+ * Enable NAPI and the ingress interrupt for the given device
+ * on the current cpu.
+ *
+ * ISSUE: Only do this for "network cpus"?
  */
-static void tile_net_enable_intr(void *dev_ptr)
+static void tile_net_open_enable(void *dev_ptr)
 {
 	struct net_device *dev = (struct net_device *)dev_ptr;
 	struct tile_net_priv *priv = netdev_priv(dev);
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	/* Enable hypervisor interrupt. */
-	enable_percpu_irq(priv->intr_id);
-
 	/* Enable NAPI. */
 	napi_enable(&info->napi);
 	info->napi_enabled = true;
+
+	/* Enable the ingress interrupt. */
+	enable_percpu_irq(priv->intr_id);
 }
 
 
@@ -1288,8 +1314,9 @@ static int tile_net_open_inner(struct net_device *dev)
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info;
 	struct tile_netio_queue *queue;
-	unsigned int irq;
+	int result = 0;
 	int i;
+	int dummy = 0;
 
 	/*
 	 * First try to register just on the local CPU, and handle any
@@ -1307,42 +1334,52 @@ static int tile_net_open_inner(struct net_device *dev)
 	/*
 	 * Now register everywhere else.  If any registration fails,
 	 * even for "link down" (which might not be possible), we
-	 * clean up using "tile_net_stop_aux()".
+	 * clean up using "tile_net_stop_aux()".  Also, add all the
+	 * "napi" objects (sequentially, to protect "dev->napi_list").
+	 * ISSUE: Only use "netif_napi_add()" for "network cpus"?
 	 */
 	smp_call_function(tile_net_register, (void *)dev, 1);
 	for_each_online_cpu(i) {
-		if (!priv->cpu[i]->registered) {
-			tile_net_stop_aux(dev);
-			return -EAGAIN;
-		}
+		struct tile_net_cpu *info = priv->cpu[i];
+		if (info->registered)
+			netif_napi_add(dev, &info->napi, tile_net_poll, 64);
+		else
+			result = -EAGAIN;
+	}
+	if (result != 0) {
+		tile_net_stop_aux(dev);
+		return result;
 	}
 
 	queue = &info->queue;
 
-	/*
-	 * Set the device intr bit mask.
-	 * The tile_net_register above sets per tile __intr_id.
-	 */
-	priv->intr_id = queue->__system_part->__intr_id;
-	BUG_ON(!priv->intr_id);
-
-	/*
-	 * Register the device interrupt handler.
-	 * The __ffs() function returns the index into the interrupt handler
-	 * table from the interrupt bit mask which should have one bit
-	 * and one bit only set.
-	 */
-	irq = __ffs(priv->intr_id);
-	tile_irq_activate(irq, TILE_IRQ_PERCPU);
-	BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt,
-			   0, dev->name, (void *)dev) != 0);
+	if (priv->intr_id == 0) {
+		unsigned int irq;
 
-	/* ISSUE: How could "priv->fully_opened" ever be "true" here? */
-
-	if (!priv->fully_opened) {
+		/*
+		 * Acquire the irq allocated by the hypervisor.  Every
+		 * queue gets the same irq.  The "__intr_id" field is
+		 * "1 << irq", so we use "__ffs()" to extract "irq".
+		 */
+		priv->intr_id = queue->__system_part->__intr_id;
+		BUG_ON(priv->intr_id == 0);
+		irq = __ffs(priv->intr_id);
 
-		int dummy = 0;
+		/*
+		 * Register the ingress interrupt handler for this
+		 * device, permanently.
+		 *
+		 * We used to call "free_irq()" in "tile_net_stop()",
+		 * and then re-register the handler here every time,
+		 * but that caused DNP errors in "handle_IRQ_event()"
+		 * because "desc->action" was NULL.  See bug 9143.
+		 */
+		tile_irq_activate(irq, TILE_IRQ_PERCPU);
+		BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt,
+				   0, dev->name, (void *)dev) != 0);
+	}
 
+	{
 		/* Allocate initial buffers. */
 
 		int max_buffers =
@@ -1359,18 +1396,21 @@ static int tile_net_open_inner(struct net_device *dev)
 		if (info->num_needed_small_buffers != 0 ||
 		    info->num_needed_large_buffers != 0)
 			panic("Insufficient memory for buffer stack!");
+	}
 
-		/* Start LIPP/LEPP and activate "ingress" at the shim. */
-		if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
-				  sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0)
-			panic("Failed to activate the LIPP Shim!\n");
+	/* We are about to be active. */
+	priv->active = true;
 
-		priv->fully_opened = 1;
-	}
+	/* Make sure "active" is visible to all tiles. */
+	mb();
 
-	/* On each tile, enable the hypervisor to trigger interrupts. */
-	/* ISSUE: Do this before starting LIPP/LEPP? */
-	on_each_cpu(tile_net_enable_intr, (void *)dev, 1);
+	/* On each tile, enable NAPI and the ingress interrupt. */
+	on_each_cpu(tile_net_open_enable, (void *)dev, 1);
+
+	/* Start LIPP/LEPP and activate "ingress" at the shim. */
+	if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+			  sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0)
+		panic("Failed to activate the LIPP Shim!\n");
 
 	/* Start our transmit queue. */
 	netif_start_queue(dev);
@@ -1396,9 +1436,9 @@ static void tile_net_open_retry(struct work_struct *w)
 	 * ourselves to try again later; otherwise, tell Linux we now have
 	 * a working link.  ISSUE: What if the return value is negative?
 	 */
-	if (tile_net_open_inner(priv->dev))
-		schedule_delayed_work_on(singlethread_cpu, &priv->retry_work,
-					 TILE_NET_RETRY_INTERVAL);
+	if (tile_net_open_inner(priv->dev) != 0)
+		schedule_delayed_work(&priv->retry_work,
+				      TILE_NET_RETRY_INTERVAL);
 	else
 		netif_carrier_on(priv->dev);
 }
@@ -1412,8 +1452,8 @@ static void tile_net_open_retry(struct work_struct *w)
  * The open entry point is called when a network interface is made
  * active by the system (IFF_UP).  At this point all resources needed
  * for transmit and receive operations are allocated, the interrupt
- * handler is registered with the OS, the watchdog timer is started,
- * and the stack is notified that the interface is ready.
+ * handler is registered with the OS (if needed), the watchdog timer
+ * is started, and the stack is notified that the interface is ready.
  *
  * If the actual link is not available yet, then we tell Linux that
  * we have no carrier, and we keep checking until the link comes up.
@@ -1468,6 +1508,10 @@ static int tile_net_open(struct net_device *dev)
 #endif
 
 		priv->partly_opened = 1;
+
+	} else {
+		/* FIXME: Is this possible? */
+		/* printk("Already partly opened.\n"); */
 	}
 
 	/*
@@ -1487,57 +1531,17 @@ static int tile_net_open(struct net_device *dev)
 	 * and then remember to try again later.
 	 */
 	netif_carrier_off(dev);
-	schedule_delayed_work_on(singlethread_cpu, &priv->retry_work,
-				 TILE_NET_RETRY_INTERVAL);
+	schedule_delayed_work(&priv->retry_work, TILE_NET_RETRY_INTERVAL);
 
 	return 0;
 }
 
 
-/*
- * Disables a network interface.
- *
- * Returns 0, this is not allowed to fail.
- *
- * The close entry point is called when an interface is de-activated
- * by the OS.  The hardware is still under the drivers control, but
- * needs to be disabled.  A global MAC reset is issued to stop the
- * hardware, and all transmit and receive resources are freed.
- *
- * ISSUE: Can this can be called while "tile_net_poll()" is running?
- */
-static int tile_net_stop(struct net_device *dev)
+static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv)
 {
-	struct tile_net_priv *priv = netdev_priv(dev);
-
-	bool pending = true;
-
-	PDEBUG("tile_net_stop()\n");
-
-	/* ISSUE: Only needed if not yet fully open. */
-	cancel_delayed_work_sync(&priv->retry_work);
-
-	/* Can't transmit any more. */
-	netif_stop_queue(dev);
-
-	/*
-	 * Disable hypervisor interrupts on each tile.
-	 */
-	on_each_cpu(tile_net_disable_intr, (void *)dev, 1);
-
-	/*
-	 * Unregister the interrupt handler.
-	 * The __ffs() function returns the index into the interrupt handler
-	 * table from the interrupt bit mask which should have one bit
-	 * and one bit only set.
-	 */
-	if (priv->intr_id)
-		free_irq(__ffs(priv->intr_id), dev);
-
-	/*
-	 * Drain all the LIPP buffers.
-	 */
+	int n = 0;
 
+	/* Drain all the LIPP buffers. */
 	while (true) {
 		int buffer;
 
@@ -1560,43 +1564,105 @@ static int tile_net_stop(struct net_device *dev)
 
 			kfree_skb(skb);
 		}
+
+		n++;
 	}
 
-	/* Stop LIPP/LEPP. */
-	tile_net_stop_aux(dev);
+	return n;
+}
 
 
-	priv->fully_opened = 0;
+/*
+ * Disables a network interface.
+ *
+ * Returns 0, this is not allowed to fail.
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ *
+ * ISSUE: How closely does "netif_running(dev)" mirror "priv->active"?
+ *
+ * Before we are called by "__dev_close()", "netif_running()" will
+ * have been cleared, so no NEW calls to "tile_net_poll()" will be
+ * made by "netpoll_poll_dev()".
+ *
+ * Often, this can cause some tiles to still have packets in their
+ * queues, so we must call "tile_net_discard_packets()" later.
+ *
+ * Note that some other tile may still be INSIDE "tile_net_poll()",
+ * and in fact, many will be, if there is heavy network load.
+ *
+ * Calling "on_each_cpu(tile_net_stop_disable, (void *)dev, 1)" when
+ * any tile is still "napi_schedule()"'d will induce a horrible crash
+ * when "msleep()" is called.  This includes tiles which are inside
+ * "tile_net_poll()" which have not yet called "napi_complete()".
+ *
+ * So, we must first try to wait long enough for other tiles to finish
+ * with any current "tile_net_poll()" call, and, hopefully, to clear
+ * the "scheduled" flag.  ISSUE: It is unclear what happens to tiles
+ * which have called "napi_schedule()" but which had not yet tried to
+ * call "tile_net_poll()", or which exhausted their budget inside
+ * "tile_net_poll()" just before this function was called.
+ */
+static int tile_net_stop(struct net_device *dev)
+{
+	struct tile_net_priv *priv = netdev_priv(dev);
+
+	PDEBUG("tile_net_stop()\n");
 
+	/* Start discarding packets. */
+	priv->active = false;
+
+	/* Make sure "active" is visible to all tiles. */
+	mb();
 
 	/*
-	 * XXX: ISSUE: It appears that, in practice anyway, by the
-	 * time we get here, there are no pending completions.
+	 * On each tile, make sure no NEW packets get delivered, and
+	 * disable the ingress interrupt.
+	 *
+	 * Note that the ingress interrupt can fire AFTER this,
+	 * presumably due to packets which were recently delivered,
+	 * but it will have no effect.
 	 */
-	while (pending) {
+	on_each_cpu(tile_net_deregister, (void *)dev, 1);
 
-		struct sk_buff *olds[32];
-		unsigned int wanted = 32;
-		unsigned int i, nolds = 0;
+	/* Optimistically drain LIPP buffers. */
+	(void)tile_net_drain_lipp_buffers(priv);
 
-		nolds = tile_net_lepp_grab_comps(dev, olds,
-						 wanted, &pending);
+	/* ISSUE: Only needed if not yet fully open. */
+	cancel_delayed_work_sync(&priv->retry_work);
 
-		/* ISSUE: We have never actually seen this debug spew. */
-		if (nolds != 0)
-			pr_info("During tile_net_stop(), grabbed %d comps.\n",
-			       nolds);
+	/* Can't transmit any more. */
+	netif_stop_queue(dev);
 
-		for (i = 0; i < nolds; i++)
-			kfree_skb(olds[i]);
-	}
+	/* Disable NAPI on each tile. */
+	on_each_cpu(tile_net_stop_disable, (void *)dev, 1);
+
+	/*
+	 * Drain any remaining LIPP buffers.  NOTE: This "printk()"
+	 * has never been observed, but in theory it could happen.
+	 */
+	if (tile_net_drain_lipp_buffers(priv) != 0)
+		printk("Had to drain some extra LIPP buffers!\n");
 
+	/* Stop LIPP/LEPP. */
+	tile_net_stop_aux(dev);
+
+	/*
+	 * ISSUE: It appears that, in practice anyway, by the time we
+	 * get here, there are no pending completions, but just in case,
+	 * we free (all of) them anyway.
+	 */
+	while (tile_net_lepp_free_comps(dev, true))
+		/* loop */;
 
 	/* Wipe the EPP queue. */
-	memset(priv->epp_queue, 0, sizeof(lepp_queue_t));
+	memset(priv->eq, 0, sizeof(lepp_queue_t));
 
 	/* Evict the EPP queue. */
-	finv_buffer(priv->epp_queue, PAGE_SIZE);
+	finv_buffer(priv->eq, EQ_SIZE);
 
 	return 0;
 }
@@ -1620,7 +1686,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
 	if (b_len != 0) {
 
 		if (!hash_default)
-			finv_buffer_remote(b_data, b_len);
+			finv_buffer_remote(b_data, b_len, 0);
 
 		cpa = __pa(b_data);
 		frags[n].cpa_lo = cpa;
@@ -1643,7 +1709,7 @@ static unsigned int tile_net_tx_frags(lepp_frag_t *frags,
 		if (!hash_default) {
 			void *va = pfn_to_kaddr(pfn) + f->page_offset;
 			BUG_ON(PageHighMem(f->page));
-			finv_buffer_remote(va, f->size);
+			finv_buffer_remote(va, f->size, 0);
 		}
 
 		cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
@@ -1742,17 +1808,15 @@ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
 
 	unsigned long irqflags;
 
-	lepp_queue_t *eq = priv->epp_queue;
+	lepp_queue_t *eq = priv->eq;
 
-	struct sk_buff *olds[4];
-	unsigned int wanted = 4;
+	struct sk_buff *olds[8];
+	unsigned int wanted = 8;
 	unsigned int i, nolds = 0;
 
 	unsigned int cmd_head, cmd_tail, cmd_next;
 	unsigned int comp_tail;
 
-	unsigned int free_slots;
-
 
 	/* Paranoia. */
 	BUG_ON(skb->protocol != htons(ETH_P_IP));
@@ -1780,34 +1844,32 @@ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev)
 
 	/* Enqueue the command. */
 
-	spin_lock_irqsave(&priv->cmd_lock, irqflags);
+	spin_lock_irqsave(&priv->eq_lock, irqflags);
 
 	/*
 	 * Handle completions if needed to make room.
 	 * HACK: Spin until there is sufficient room.
 	 */
-	free_slots = lepp_num_free_comp_slots(eq);
-	if (free_slots < 1) {
-spin:
-		nolds += tile_net_lepp_grab_comps(dev, olds + nolds,
-						  wanted - nolds, NULL);
-		if (lepp_num_free_comp_slots(eq) < 1)
-			goto spin;
+	if (lepp_num_free_comp_slots(eq) == 0) {
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+		if (nolds == 0) {
+busy:
+			spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+			return NETDEV_TX_BUSY;
+		}
 	}
 
 	cmd_head = eq->cmd_head;
 	cmd_tail = eq->cmd_tail;
 
-	/* NOTE: The "gotos" below are untested. */
-
 	/* Prepare to advance, detecting full queue. */
 	cmd_next = cmd_tail + cmd_size;
 	if (cmd_tail < cmd_head && cmd_next >= cmd_head)
-		goto spin;
+		goto busy;
 	if (cmd_next > LEPP_CMD_LIMIT) {
 		cmd_next = 0;
 		if (cmd_next == cmd_head)
-			goto spin;
+			goto busy;
 	}
 
 	/* Copy the command. */
@@ -1823,14 +1885,18 @@ spin:
 	eq->comp_tail = comp_tail;
 
 	/* Flush before allowing LEPP to handle the command. */
+	/* ISSUE: Is this the optimal location for the flush? */
 	__insn_mf();
 
 	eq->cmd_tail = cmd_tail;
 
-	spin_unlock_irqrestore(&priv->cmd_lock, irqflags);
-
+	/* NOTE: Using "4" here is more efficient than "0" or "2", */
+	/* and, strangely, more efficient than pre-checking the number */
+	/* of available completions, and comparing it to 4. */
 	if (nolds == 0)
-		nolds = tile_net_lepp_grab_comps(dev, olds, wanted, NULL);
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4);
+
+	spin_unlock_irqrestore(&priv->eq_lock, irqflags);
 
 	/* Handle completions. */
 	for (i = 0; i < nolds; i++)
@@ -1870,10 +1936,10 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
 	unsigned int num_frags;
 
-	lepp_queue_t *eq = priv->epp_queue;
+	lepp_queue_t *eq = priv->eq;
 
-	struct sk_buff *olds[4];
-	unsigned int wanted = 4;
+	struct sk_buff *olds[8];
+	unsigned int wanted = 8;
 	unsigned int i, nolds = 0;
 
 	unsigned int cmd_size = sizeof(lepp_cmd_t);
@@ -1883,8 +1949,6 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
 	lepp_cmd_t cmds[LEPP_MAX_FRAGS];
 
-	unsigned int free_slots;
-
 
 	/*
 	 * This is paranoia, since we think that if the link doesn't come
@@ -1905,7 +1969,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 	if (hash_default) {
 		HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)data);
 		if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
-			panic("Non-coherent egress buffer!");
+			panic("Non-HFH egress buffer! VA=%p Mode=%d PTE=%llx",
+			      data, hv_pte_get_mode(pte), hv_pte_val(pte));
 	}
 #endif
 #endif
@@ -1958,37 +2023,35 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
 
 	/* Enqueue the commands. */
 
-	spin_lock_irqsave(&priv->cmd_lock, irqflags);
+	spin_lock_irqsave(&priv->eq_lock, irqflags);
 
 	/*
 	 * Handle completions if needed to make room.
 	 * HACK: Spin until there is sufficient room.
 	 */
-	free_slots = lepp_num_free_comp_slots(eq);
-	if (free_slots < 1) {
-spin:
-		nolds += tile_net_lepp_grab_comps(dev, olds + nolds,
-						  wanted - nolds, NULL);
-		if (lepp_num_free_comp_slots(eq) < 1)
-			goto spin;
+	if (lepp_num_free_comp_slots(eq) == 0) {
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+		if (nolds == 0) {
+busy:
+			spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+			return NETDEV_TX_BUSY;
+		}
 	}
 
 	cmd_head = eq->cmd_head;
 	cmd_tail = eq->cmd_tail;
 
-	/* NOTE: The "gotos" below are untested. */
-
 	/* Copy the commands, or fail. */
 	for (i = 0; i < num_frags; i++) {
 
 		/* Prepare to advance, detecting full queue. */
 		cmd_next = cmd_tail + cmd_size;
 		if (cmd_tail < cmd_head && cmd_next >= cmd_head)
-			goto spin;
+			goto busy;
 		if (cmd_next > LEPP_CMD_LIMIT) {
 			cmd_next = 0;
 			if (cmd_next == cmd_head)
-				goto spin;
+				goto busy;
 		}
 
 		/* Copy the command. */
@@ -2005,14 +2068,18 @@ spin:
 	eq->comp_tail = comp_tail;
 
 	/* Flush before allowing LEPP to handle the command. */
+	/* ISSUE: Is this the optimal location for the flush? */
 	__insn_mf();
 
 	eq->cmd_tail = cmd_tail;
 
-	spin_unlock_irqrestore(&priv->cmd_lock, irqflags);
-
+	/* NOTE: Using "4" here is more efficient than "0" or "2", */
+	/* and, strangely, more efficient than pre-checking the number */
+	/* of available completions, and comparing it to 4. */
 	if (nolds == 0)
-		nolds = tile_net_lepp_grab_comps(dev, olds, wanted, NULL);
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4);
+
+	spin_unlock_irqrestore(&priv->eq_lock, irqflags);
 
 	/* Handle completions. */
 	for (i = 0; i < nolds; i++)
@@ -2261,7 +2328,6 @@ static struct net_device *tile_net_dev_init(const char *name)
 	int ret;
 	struct net_device *dev;
 	struct tile_net_priv *priv;
-	struct page *page;
 
 	/*
 	 * Allocate the device structure.  This allocates "priv", calls
@@ -2285,23 +2351,21 @@ static struct net_device *tile_net_dev_init(const char *name)
 
 	INIT_DELAYED_WORK(&priv->retry_work, tile_net_open_retry);
 
-	spin_lock_init(&priv->cmd_lock);
-	spin_lock_init(&priv->comp_lock);
+	spin_lock_init(&priv->eq_lock);
 
-	/* Allocate "epp_queue". */
-	BUG_ON(get_order(sizeof(lepp_queue_t)) != 0);
-	page = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
-	if (!page) {
+	/* Allocate "eq". */
+	priv->eq_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, EQ_ORDER);
+	if (!priv->eq_pages) {
 		free_netdev(dev);
 		return NULL;
 	}
-	priv->epp_queue = page_address(page);
+	priv->eq = page_address(priv->eq_pages);
 
 	/* Register the network device. */
 	ret = register_netdev(dev);
 	if (ret) {
 		pr_err("register_netdev %s failed %d\n", dev->name, ret);
-		free_page((unsigned long)priv->epp_queue);
+		__free_pages(priv->eq_pages, EQ_ORDER);
 		free_netdev(dev);
 		return NULL;
 	}
@@ -2310,7 +2374,7 @@ static struct net_device *tile_net_dev_init(const char *name)
 	ret = tile_net_get_mac(dev);
 	if (ret < 0) {
 		unregister_netdev(dev);
-		free_page((unsigned long)priv->epp_queue);
+		__free_pages(priv->eq_pages, EQ_ORDER);
 		free_netdev(dev);
 		return NULL;
 	}
@@ -2321,6 +2385,9 @@ static struct net_device *tile_net_dev_init(const char *name)
 
 /*
  * Module cleanup.
+ *
+ * FIXME: If compiled as a module, this module cannot be "unloaded",
+ * because the "ingress interrupt handler" is registered permanently.
  */
 static void tile_net_cleanup(void)
 {
@@ -2331,8 +2398,8 @@ static void tile_net_cleanup(void)
 			struct net_device *dev = tile_net_devs[i];
 			struct tile_net_priv *priv = netdev_priv(dev);
 			unregister_netdev(dev);
-			finv_buffer(priv->epp_queue, PAGE_SIZE);
-			free_page((unsigned long)priv->epp_queue);
+			finv_buffer(priv->eq, EQ_SIZE);
+			__free_pages(priv->eq_pages, EQ_ORDER);
 			free_netdev(dev);
 		}
 	}
@@ -2355,7 +2422,12 @@ static int tile_net_init_module(void)
 }
 
 
+module_init(tile_net_init_module);
+module_exit(tile_net_cleanup);
+
+
 #ifndef MODULE
+
 /*
  * The "network_cpus" boot argument specifies the cpus that are dedicated
  * to handle ingress packets.
@@ -2391,8 +2463,5 @@ static int __init network_cpus_setup(char *str)
 	return 0;
 }
 __setup("network_cpus=", network_cpus_setup);
-#endif
-
 
-module_init(tile_net_init_module);
-module_exit(tile_net_cleanup);
+#endif
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index f8e463c..ace6404 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -25,150 +25,9 @@
  *		Microchip Technology, 24C01A/02A/04A Data Sheet
  *			available in PDF format from www.microchip.com
  *
- * Change History
- *
- *	Tigran Aivazian <tigran@sco.com>:	TLan_PciProbe() now uses
- *						new PCI BIOS interface.
- *	Alan Cox	<alan@lxorguk.ukuu.org.uk>:
- *						Fixed the out of memory
- *						handling.
- *
- *	Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
- *
- *	v1.1 Dec 20, 1999    - Removed linux version checking
- *			       Patch from Tigran Aivazian.
- *			     - v1.1 includes Alan's SMP updates.
- *			     - We still have problems on SMP though,
- *			       but I'm looking into that.
- *
- *	v1.2 Jan 02, 2000    - Hopefully fixed the SMP deadlock.
- *			     - Removed dependency of HZ being 100.
- *			     - We now allow higher priority timers to
- *			       overwrite timers like TLAN_TIMER_ACTIVITY
- *			       Patch from John Cagle <john.cagle@compaq.com>.
- *			     - Fixed a few compiler warnings.
- *
- *	v1.3 Feb 04, 2000    - Fixed the remaining HZ issues.
- *			     - Removed call to pci_present().
- *			     - Removed SA_INTERRUPT flag from irq handler.
- *			     - Added __init and __initdata to reduce resisdent
- *			       code size.
- *			     - Driver now uses module_init/module_exit.
- *			     - Rewrote init_module and tlan_probe to
- *			       share a lot more code. We now use tlan_probe
- *			       with builtin and module driver.
- *			     - Driver ported to new net API.
- *			     - tlan.txt has been reworked to reflect current
- *			       driver (almost)
- *			     - Other minor stuff
- *
- *	v1.4 Feb 10, 2000    - Updated with more changes required after Dave's
- *	                       network cleanup in 2.3.43pre7 (Tigran & myself)
- *	                     - Minor stuff.
- *
- *	v1.5 March 22, 2000  - Fixed another timer bug that would hang the driver
- *			       if no cable/link were present.
- *			     - Cosmetic changes.
- *			     - TODO: Port completely to new PCI/DMA API
- *			     	     Auto-Neg fallback.
- *
- * 	v1.6 April 04, 2000  - Fixed driver support for kernel-parameters. Haven't
- * 			       tested it though, as the kernel support is currently
- * 			       broken (2.3.99p4p3).
- * 			     - Updated tlan.txt accordingly.
- * 			     - Adjusted minimum/maximum frame length.
- * 			     - There is now a TLAN website up at
- * 			       http://hp.sourceforge.net/ 
- *
- * 	v1.7 April 07, 2000  - Started to implement custom ioctls. Driver now
- * 			       reports PHY information when used with Donald
- * 			       Beckers userspace MII diagnostics utility.
- *
- * 	v1.8 April 23, 2000  - Fixed support for forced speed/duplex settings.
- * 			     - Added link information to Auto-Neg and forced
- * 			       modes. When NIC operates with auto-neg the driver
- * 			       will report Link speed & duplex modes as well as
- * 			       link partner abilities. When forced link is used,
- * 			       the driver will report status of the established
- * 			       link.
- * 			       Please read tlan.txt for additional information.
- * 			     - Removed call to check_region(), and used
- * 			       return value of request_region() instead.
- *
- *	v1.8a May 28, 2000   - Minor updates.
- *
- *	v1.9 July 25, 2000   - Fixed a few remaining Full-Duplex issues.
- *	                     - Updated with timer fixes from Andrew Morton.
- *	                     - Fixed module race in TLan_Open.
- *	                     - Added routine to monitor PHY status.
- *	                     - Added activity led support for Proliant devices.
- *
- *	v1.10 Aug 30, 2000   - Added support for EISA based tlan controllers
- *			       like the Compaq NetFlex3/E.
- *			     - Rewrote tlan_probe to better handle multiple
- *			       bus probes. Probing and device setup is now
- *			       done through TLan_Probe and TLan_init_one. Actual
- *			       hardware probe is done with kernel API and
- *			       TLan_EisaProbe.
- *			     - Adjusted debug information for probing.
- *			     - Fixed bug that would cause general debug information
- *			       to be printed after driver removal.
- *			     - Added transmit timeout handling.
- *			     - Fixed OOM return values in tlan_probe.
- *			     - Fixed possible mem leak in tlan_exit
- *			       (now tlan_remove_one).
- *			     - Fixed timer bug in TLan_phyMonitor.
- *			     - This driver version is alpha quality, please
- *			       send me any bug issues you may encounter.
- *
- *	v1.11 Aug 31, 2000   - Do not try to register irq 0 if no irq line was
- *			       set for EISA cards.
- *			     - Added support for NetFlex3/E with nibble-rate
- *			       10Base-T PHY. This is untestet as I haven't got
- *			       one of these cards.
- *			     - Fixed timer being added twice.
- *			     - Disabled PhyMonitoring by default as this is
- *			       work in progress. Define MONITOR to enable it.
- *			     - Now we don't display link info with PHYs that
- *			       doesn't support it (level1).
- *			     - Incresed tx_timeout beacuse of auto-neg.
- *			     - Adjusted timers for forced speeds.
- *
- *	v1.12 Oct 12, 2000   - Minor fixes (memleak, init, etc.)
- *
- * 	v1.13 Nov 28, 2000   - Stop flooding console with auto-neg issues
- * 			       when link can't be established.
- *			     - Added the bbuf option as a kernel parameter.
- *			     - Fixed ioaddr probe bug.
- *			     - Fixed stupid deadlock with MII interrupts.
- *			     - Added support for speed/duplex selection with
- *			       multiple nics.
- *			     - Added partly fix for TX Channel lockup with
- *			       TLAN v1.0 silicon. This needs to be investigated
- *			       further.
- *
- * 	v1.14 Dec 16, 2000   - Added support for servicing multiple frames per.
- * 			       interrupt. Thanks goes to
- * 			       Adam Keys <adam@ti.com>
- * 			       Denis Beaudoin <dbeaudoin@ti.com>
- * 			       for providing the patch.
- * 			     - Fixed auto-neg output when using multiple
- * 			       adapters.
- * 			     - Converted to use new taskq interface.
- *
- * 	v1.14a Jan 6, 2001   - Minor adjustments (spinlocks, etc.)
- *
- *	Samuel Chessman <chessman@tux.org> New Maintainer!
- *
- *	v1.15 Apr 4, 2002    - Correct operation when aui=1 to be
- *	                       10T half duplex no loopback
- *	                       Thanks to Gunnar Eikman
- *
- *	Sakari Ailus <sakari.ailus@iki.fi>:
- *
- *	v1.15a Dec 15 2008   - Remove bbuf support, it doesn't work anyway.
- *
- *******************************************************************************/
+ ******************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/init.h>
@@ -185,13 +44,11 @@
 
 #include "tlan.h"
 
-typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
-
 
 /* For removing EISA devices */
-static	struct net_device	*TLan_Eisa_Devices;
+static	struct net_device	*tlan_eisa_devices;
 
-static	int		TLanDevicesInstalled;
+static	int		tlan_devices_installed;
 
 /* Set speed, duplex and aui settings */
 static  int aui[MAX_TLAN_BOARDS];
@@ -202,8 +59,9 @@ module_param_array(aui, int, NULL, 0);
 module_param_array(duplex, int, NULL, 0);
 module_param_array(speed, int, NULL, 0);
 MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");
-MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
-MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");
+MODULE_PARM_DESC(duplex,
+		 "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
+MODULE_PARM_DESC(speed, "ThunderLAN port speed setting(s) (0,10,100)");
 
 MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
 MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
@@ -218,139 +76,144 @@ static  int		debug;
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
 
-static	const char TLanSignature[] = "TLAN";
-static  const char tlan_banner[] = "ThunderLAN driver v1.15a\n";
+static	const char tlan_signature[] = "TLAN";
+static  const char tlan_banner[] = "ThunderLAN driver v1.17\n";
 static  int tlan_have_pci;
 static  int tlan_have_eisa;
 
-static const char *media[] = {
-	"10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ",
-	"100baseTx-FD", "100baseT4", NULL
+static const char * const media[] = {
+	"10BaseT-HD", "10BaseT-FD", "100baseTx-HD",
+	"100BaseTx-FD", "100BaseT4", NULL
 };
 
 static struct board {
-	const char	*deviceLabel;
-	u32	   	flags;
-	u16	   	addrOfs;
+	const char	*device_label;
+	u32		flags;
+	u16		addr_ofs;
 } board_info[] = {
 	{ "Compaq Netelligent 10 T PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
-	{ "Compaq Netelligent 10/100 TX PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
+	{ "Compaq Netelligent 10/100 TX PCI UTP",
+	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
 	{ "Compaq Integrated NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq NetFlex-3/P",
 	  TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
 	{ "Compaq NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq Netelligent Integrated 10/100 TX UTP",
 	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
-	{ "Compaq Netelligent Dual 10/100 TX PCI UTP", TLAN_ADAPTER_NONE, 0x83 },
-	{ "Compaq Netelligent 10/100 TX Embedded UTP", TLAN_ADAPTER_NONE, 0x83 },
+	{ "Compaq Netelligent Dual 10/100 TX PCI UTP",
+	  TLAN_ADAPTER_NONE, 0x83 },
+	{ "Compaq Netelligent 10/100 TX Embedded UTP",
+	  TLAN_ADAPTER_NONE, 0x83 },
 	{ "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 },
-	{ "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xF8 },
-	{ "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xF8 },
+	{ "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xf8 },
+	{ "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xf8 },
 	{ "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
-	{ "Compaq Netelligent 10 T/2 PCI UTP/Coax", TLAN_ADAPTER_NONE, 0x83 },
+	{ "Compaq Netelligent 10 T/2 PCI UTP/coax", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq NetFlex-3/E",
-	  TLAN_ADAPTER_ACTIVITY_LED | 	/* EISA card */
+	  TLAN_ADAPTER_ACTIVITY_LED |	/* EISA card */
 	  TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
-	{ "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
+	{ "Compaq NetFlex-3/E",
+	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
 };
 
 static DEFINE_PCI_DEVICE_TABLE(tlan_pci_tbl) = {
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2325,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_T2,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, tlan_pci_tbl);
 
-static void	TLan_EisaProbe( void );
-static void	TLan_Eisa_Cleanup( void );
-static int      TLan_Init( struct net_device * );
-static int	TLan_Open( struct net_device *dev );
-static netdev_tx_t TLan_StartTx( struct sk_buff *, struct net_device *);
-static irqreturn_t TLan_HandleInterrupt( int, void *);
-static int	TLan_Close( struct net_device *);
-static struct	net_device_stats *TLan_GetStats( struct net_device *);
-static void	TLan_SetMulticastList( struct net_device *);
-static int	TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd);
-static int      TLan_probe1( struct pci_dev *pdev, long ioaddr,
-			     int irq, int rev, const struct pci_device_id *ent);
-static void	TLan_tx_timeout( struct net_device *dev);
-static void	TLan_tx_timeout_work(struct work_struct *work);
-static int 	tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
-
-static u32	TLan_HandleTxEOF( struct net_device *, u16 );
-static u32	TLan_HandleStatOverflow( struct net_device *, u16 );
-static u32	TLan_HandleRxEOF( struct net_device *, u16 );
-static u32	TLan_HandleDummy( struct net_device *, u16 );
-static u32	TLan_HandleTxEOC( struct net_device *, u16 );
-static u32	TLan_HandleStatusCheck( struct net_device *, u16 );
-static u32	TLan_HandleRxEOC( struct net_device *, u16 );
-
-static void	TLan_Timer( unsigned long );
-
-static void	TLan_ResetLists( struct net_device * );
-static void	TLan_FreeLists( struct net_device * );
-static void	TLan_PrintDio( u16 );
-static void	TLan_PrintList( TLanList *, char *, int );
-static void	TLan_ReadAndClearStats( struct net_device *, int );
-static void	TLan_ResetAdapter( struct net_device * );
-static void	TLan_FinishReset( struct net_device * );
-static void	TLan_SetMac( struct net_device *, int areg, char *mac );
-
-static void	TLan_PhyPrint( struct net_device * );
-static void	TLan_PhyDetect( struct net_device * );
-static void	TLan_PhyPowerDown( struct net_device * );
-static void	TLan_PhyPowerUp( struct net_device * );
-static void	TLan_PhyReset( struct net_device * );
-static void	TLan_PhyStartLink( struct net_device * );
-static void	TLan_PhyFinishAutoNeg( struct net_device * );
+static void	tlan_eisa_probe(void);
+static void	tlan_eisa_cleanup(void);
+static int      tlan_init(struct net_device *);
+static int	tlan_open(struct net_device *dev);
+static netdev_tx_t tlan_start_tx(struct sk_buff *, struct net_device *);
+static irqreturn_t tlan_handle_interrupt(int, void *);
+static int	tlan_close(struct net_device *);
+static struct	net_device_stats *tlan_get_stats(struct net_device *);
+static void	tlan_set_multicast_list(struct net_device *);
+static int	tlan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int      tlan_probe1(struct pci_dev *pdev, long ioaddr,
+			    int irq, int rev, const struct pci_device_id *ent);
+static void	tlan_tx_timeout(struct net_device *dev);
+static void	tlan_tx_timeout_work(struct work_struct *work);
+static int	tlan_init_one(struct pci_dev *pdev,
+			      const struct pci_device_id *ent);
+
+static u32	tlan_handle_tx_eof(struct net_device *, u16);
+static u32	tlan_handle_stat_overflow(struct net_device *, u16);
+static u32	tlan_handle_rx_eof(struct net_device *, u16);
+static u32	tlan_handle_dummy(struct net_device *, u16);
+static u32	tlan_handle_tx_eoc(struct net_device *, u16);
+static u32	tlan_handle_status_check(struct net_device *, u16);
+static u32	tlan_handle_rx_eoc(struct net_device *, u16);
+
+static void	tlan_timer(unsigned long);
+
+static void	tlan_reset_lists(struct net_device *);
+static void	tlan_free_lists(struct net_device *);
+static void	tlan_print_dio(u16);
+static void	tlan_print_list(struct tlan_list *, char *, int);
+static void	tlan_read_and_clear_stats(struct net_device *, int);
+static void	tlan_reset_adapter(struct net_device *);
+static void	tlan_finish_reset(struct net_device *);
+static void	tlan_set_mac(struct net_device *, int areg, char *mac);
+
+static void	tlan_phy_print(struct net_device *);
+static void	tlan_phy_detect(struct net_device *);
+static void	tlan_phy_power_down(struct net_device *);
+static void	tlan_phy_power_up(struct net_device *);
+static void	tlan_phy_reset(struct net_device *);
+static void	tlan_phy_start_link(struct net_device *);
+static void	tlan_phy_finish_auto_neg(struct net_device *);
 #ifdef MONITOR
-static void     TLan_PhyMonitor( struct net_device * );
+static void     tlan_phy_monitor(struct net_device *);
 #endif
 
 /*
-static int	TLan_PhyNop( struct net_device * );
-static int	TLan_PhyInternalCheck( struct net_device * );
-static int	TLan_PhyInternalService( struct net_device * );
-static int	TLan_PhyDp83840aCheck( struct net_device * );
+  static int	tlan_phy_nop(struct net_device *);
+  static int	tlan_phy_internal_check(struct net_device *);
+  static int	tlan_phy_internal_service(struct net_device *);
+  static int	tlan_phy_dp83840a_check(struct net_device *);
 */
 
-static bool	TLan_MiiReadReg( struct net_device *, u16, u16, u16 * );
-static void	TLan_MiiSendData( u16, u32, unsigned );
-static void	TLan_MiiSync( u16 );
-static void	TLan_MiiWriteReg( struct net_device *, u16, u16, u16 );
+static bool	tlan_mii_read_reg(struct net_device *, u16, u16, u16 *);
+static void	tlan_mii_send_data(u16, u32, unsigned);
+static void	tlan_mii_sync(u16);
+static void	tlan_mii_write_reg(struct net_device *, u16, u16, u16);
 
-static void	TLan_EeSendStart( u16 );
-static int	TLan_EeSendByte( u16, u8, int );
-static void	TLan_EeReceiveByte( u16, u8 *, int );
-static int	TLan_EeReadByte( struct net_device *, u8, u8 * );
+static void	tlan_ee_send_start(u16);
+static int	tlan_ee_send_byte(u16, u8, int);
+static void	tlan_ee_receive_byte(u16, u8 *, int);
+static int	tlan_ee_read_byte(struct net_device *, u8, u8 *);
 
 
 static inline void
-TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
+tlan_store_skb(struct tlan_list *tag, struct sk_buff *skb)
 {
 	unsigned long addr = (unsigned long)skb;
 	tag->buffer[9].address = addr;
@@ -358,7 +221,7 @@ TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
 }
 
 static inline struct sk_buff *
-TLan_GetSKB( const struct tlan_list_tag *tag)
+tlan_get_skb(const struct tlan_list *tag)
 {
 	unsigned long addr;
 
@@ -367,50 +230,50 @@ TLan_GetSKB( const struct tlan_list_tag *tag)
 	return (struct sk_buff *) addr;
 }
 
-
-static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = {
+static u32
+(*tlan_int_vector[TLAN_INT_NUMBER_OF_INTS])(struct net_device *, u16) = {
 	NULL,
-	TLan_HandleTxEOF,
-	TLan_HandleStatOverflow,
-	TLan_HandleRxEOF,
-	TLan_HandleDummy,
-	TLan_HandleTxEOC,
-	TLan_HandleStatusCheck,
-	TLan_HandleRxEOC
+	tlan_handle_tx_eof,
+	tlan_handle_stat_overflow,
+	tlan_handle_rx_eof,
+	tlan_handle_dummy,
+	tlan_handle_tx_eoc,
+	tlan_handle_status_check,
+	tlan_handle_rx_eoc
 };
 
 static inline void
-TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
+tlan_set_timer(struct net_device *dev, u32 ticks, u32 type)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	unsigned long flags = 0;
 
 	if (!in_irq())
 		spin_lock_irqsave(&priv->lock, flags);
-	if ( priv->timer.function != NULL &&
-		priv->timerType != TLAN_TIMER_ACTIVITY ) {
+	if (priv->timer.function != NULL &&
+	    priv->timer_type != TLAN_TIMER_ACTIVITY) {
 		if (!in_irq())
 			spin_unlock_irqrestore(&priv->lock, flags);
 		return;
 	}
-	priv->timer.function = TLan_Timer;
+	priv->timer.function = tlan_timer;
 	if (!in_irq())
 		spin_unlock_irqrestore(&priv->lock, flags);
 
 	priv->timer.data = (unsigned long) dev;
-	priv->timerSetAt = jiffies;
-	priv->timerType = type;
+	priv->timer_set_at = jiffies;
+	priv->timer_type = type;
 	mod_timer(&priv->timer, jiffies + ticks);
 
-} /* TLan_SetTimer */
+}
 
 
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Primary Functions
+ThunderLAN driver primary functions
 
-	These functions are more or less common to all Linux network drivers.
+these functions are more or less common to all linux network drivers.
 
 ******************************************************************************
 *****************************************************************************/
@@ -419,56 +282,124 @@ TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
 
 
 
-	/***************************************************************
-	 *	tlan_remove_one
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		None
-	 *
-	 *	Goes through the TLanDevices list and frees the device
-	 *	structs and memory associated with each device (lists
-	 *	and buffers).  It also ureserves the IO port regions
-	 *	associated with this device.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_remove_one
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		None
+ *
+ *	Goes through the TLanDevices list and frees the device
+ *	structs and memory associated with each device (lists
+ *	and buffers).  It also ureserves the IO port regions
+ *	associated with this device.
+ *
+ **************************************************************/
 
 
-static void __devexit tlan_remove_one( struct pci_dev *pdev)
+static void __devexit tlan_remove_one(struct pci_dev *pdev)
 {
-	struct net_device *dev = pci_get_drvdata( pdev );
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 
-	unregister_netdev( dev );
+	unregister_netdev(dev);
 
-	if ( priv->dmaStorage ) {
-		pci_free_consistent(priv->pciDev,
-				    priv->dmaSize, priv->dmaStorage,
-				    priv->dmaStorageDMA );
+	if (priv->dma_storage) {
+		pci_free_consistent(priv->pci_dev,
+				    priv->dma_size, priv->dma_storage,
+				    priv->dma_storage_dma);
 	}
 
 #ifdef CONFIG_PCI
 	pci_release_regions(pdev);
 #endif
 
-	free_netdev( dev );
+	free_netdev(dev);
 
-	pci_set_drvdata( pdev, NULL );
+	pci_set_drvdata(pdev, NULL);
 }
 
+static void tlan_start(struct net_device *dev)
+{
+	tlan_reset_lists(dev);
+	/* NOTE: It might not be necessary to read the stats before a
+	   reset if you don't care what the values are.
+	*/
+	tlan_read_and_clear_stats(dev, TLAN_IGNORE);
+	tlan_reset_adapter(dev);
+	netif_wake_queue(dev);
+}
+
+static void tlan_stop(struct net_device *dev)
+{
+	struct tlan_priv *priv = netdev_priv(dev);
+
+	tlan_read_and_clear_stats(dev, TLAN_RECORD);
+	outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
+	/* Reset and power down phy */
+	tlan_reset_adapter(dev);
+	if (priv->timer.function != NULL) {
+		del_timer_sync(&priv->timer);
+		priv->timer.function = NULL;
+	}
+}
+
+#ifdef CONFIG_PM
+
+static int tlan_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (netif_running(dev))
+		tlan_stop(dev);
+
+	netif_device_detach(dev);
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_wake_from_d3(pdev, false);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int tlan_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, 0, 0);
+	netif_device_attach(dev);
+
+	if (netif_running(dev))
+		tlan_start(dev);
+
+	return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define tlan_suspend   NULL
+#define tlan_resume    NULL
+
+#endif /* CONFIG_PM */
+
+
 static struct pci_driver tlan_driver = {
 	.name		= "tlan",
 	.id_table	= tlan_pci_tbl,
 	.probe		= tlan_init_one,
 	.remove		= __devexit_p(tlan_remove_one),
+	.suspend	= tlan_suspend,
+	.resume		= tlan_resume,
 };
 
 static int __init tlan_probe(void)
 {
 	int rc = -ENODEV;
 
-	printk(KERN_INFO "%s", tlan_banner);
+	pr_info("%s", tlan_banner);
 
 	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n");
 
@@ -477,18 +408,18 @@ static int __init tlan_probe(void)
 	rc = pci_register_driver(&tlan_driver);
 
 	if (rc != 0) {
-		printk(KERN_ERR "TLAN: Could not register pci driver.\n");
+		pr_err("Could not register pci driver\n");
 		goto err_out_pci_free;
 	}
 
 	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n");
-	TLan_EisaProbe();
+	tlan_eisa_probe();
 
-	printk(KERN_INFO "TLAN: %d device%s installed, PCI: %d  EISA: %d\n",
-		 TLanDevicesInstalled, TLanDevicesInstalled == 1 ? "" : "s",
-		 tlan_have_pci, tlan_have_eisa);
+	pr_info("%d device%s installed, PCI: %d  EISA: %d\n",
+		tlan_devices_installed, tlan_devices_installed == 1 ? "" : "s",
+		tlan_have_pci, tlan_have_eisa);
 
-	if (TLanDevicesInstalled == 0) {
+	if (tlan_devices_installed == 0) {
 		rc = -ENODEV;
 		goto  err_out_pci_unreg;
 	}
@@ -501,39 +432,39 @@ err_out_pci_free:
 }
 
 
-static int __devinit tlan_init_one( struct pci_dev *pdev,
-				    const struct pci_device_id *ent)
+static int __devinit tlan_init_one(struct pci_dev *pdev,
+				   const struct pci_device_id *ent)
 {
-	return TLan_probe1( pdev, -1, -1, 0, ent);
+	return tlan_probe1(pdev, -1, -1, 0, ent);
 }
 
 
 /*
-	***************************************************************
-	 *	tlan_probe1
-	 *
-	 *	Returns:
-	 *		0 on success, error code on error
-	 *	Parms:
-	 *		none
-	 *
-	 *	The name is lower case to fit in with all the rest of
-	 *	the netcard_probe names.  This function looks for
-	 *	another TLan based adapter, setting it up with the
-	 *	allocated device struct if one is found.
-	 *	tlan_probe has been ported to the new net API and
-	 *	now allocates its own device structure. This function
-	 *	is also used by modules.
-	 *
-	 **************************************************************/
-
-static int __devinit TLan_probe1(struct pci_dev *pdev,
+***************************************************************
+*	tlan_probe1
+*
+*	Returns:
+*		0 on success, error code on error
+*	Parms:
+*		none
+*
+*	The name is lower case to fit in with all the rest of
+*	the netcard_probe names.  This function looks for
+*	another TLan based adapter, setting it up with the
+*	allocated device struct if one is found.
+*	tlan_probe has been ported to the new net API and
+*	now allocates its own device structure. This function
+*	is also used by modules.
+*
+**************************************************************/
+
+static int __devinit tlan_probe1(struct pci_dev *pdev,
 				 long ioaddr, int irq, int rev,
-				 const struct pci_device_id *ent )
+				 const struct pci_device_id *ent)
 {
 
 	struct net_device  *dev;
-	TLanPrivateInfo    *priv;
+	struct tlan_priv  *priv;
 	u16		   device_id;
 	int		   reg, rc = -ENODEV;
 
@@ -543,17 +474,17 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 		if (rc)
 			return rc;
 
-		rc = pci_request_regions(pdev, TLanSignature);
+		rc = pci_request_regions(pdev, tlan_signature);
 		if (rc) {
-			printk(KERN_ERR "TLAN: Could not reserve IO regions\n");
+			pr_err("Could not reserve IO regions\n");
 			goto err_out;
 		}
 	}
 #endif  /*  CONFIG_PCI  */
 
-	dev = alloc_etherdev(sizeof(TLanPrivateInfo));
+	dev = alloc_etherdev(sizeof(struct tlan_priv));
 	if (dev == NULL) {
-		printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
+		pr_err("Could not allocate memory for device\n");
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
@@ -561,38 +492,39 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 
 	priv = netdev_priv(dev);
 
-	priv->pciDev = pdev;
+	priv->pci_dev = pdev;
 	priv->dev = dev;
 
 	/* Is this a PCI device? */
 	if (pdev) {
-		u32 		   pci_io_base = 0;
+		u32		   pci_io_base = 0;
 
 		priv->adapter = &board_info[ent->driver_data];
 
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n");
+			pr_err("No suitable PCI mapping available\n");
 			goto err_out_free_dev;
 		}
 
-		for ( reg= 0; reg <= 5; reg ++ ) {
+		for (reg = 0; reg <= 5; reg++) {
 			if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
 				pci_io_base = pci_resource_start(pdev, reg);
-				TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n",
-						pci_io_base);
+				TLAN_DBG(TLAN_DEBUG_GNRL,
+					 "IO mapping is available at %x.\n",
+					 pci_io_base);
 				break;
 			}
 		}
 		if (!pci_io_base) {
-			printk(KERN_ERR "TLAN: No IO mappings available\n");
+			pr_err("No IO mappings available\n");
 			rc = -EIO;
 			goto err_out_free_dev;
 		}
 
 		dev->base_addr = pci_io_base;
 		dev->irq = pdev->irq;
-		priv->adapterRev = pdev->revision;
+		priv->adapter_rev = pdev->revision;
 		pci_set_master(pdev);
 		pci_set_drvdata(pdev, dev);
 
@@ -602,11 +534,11 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 		device_id = inw(ioaddr + EISA_ID2);
 		priv->is_eisa = 1;
 		if (device_id == 0x20F1) {
-			priv->adapter = &board_info[13]; 	/* NetFlex-3/E */
-			priv->adapterRev = 23;			/* TLAN 2.3 */
+			priv->adapter = &board_info[13]; /* NetFlex-3/E */
+			priv->adapter_rev = 23;		/* TLAN 2.3 */
 		} else {
 			priv->adapter = &board_info[14];
-			priv->adapterRev = 10;			/* TLAN 1.0 */
+			priv->adapter_rev = 10;		/* TLAN 1.0 */
 		}
 		dev->base_addr = ioaddr;
 		dev->irq = irq;
@@ -620,11 +552,11 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 		priv->speed  = ((dev->mem_start & 0x18) == 0x18) ? 0
 			: (dev->mem_start & 0x18) >> 3;
 
-		if (priv->speed == 0x1) {
+		if (priv->speed == 0x1)
 			priv->speed = TLAN_SPEED_10;
-		} else if (priv->speed == 0x2) {
+		else if (priv->speed == 0x2)
 			priv->speed = TLAN_SPEED_100;
-		}
+
 		debug = priv->debug = dev->mem_end;
 	} else {
 		priv->aui    = aui[boards_found];
@@ -635,46 +567,45 @@ static int __devinit TLan_probe1(struct pci_dev *pdev,
 
 	/* This will be used when we get an adapter error from
 	 * within our irq handler */
-	INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work);
+	INIT_WORK(&priv->tlan_tqueue, tlan_tx_timeout_work);
 
 	spin_lock_init(&priv->lock);
 
-	rc = TLan_Init(dev);
+	rc = tlan_init(dev);
 	if (rc) {
-		printk(KERN_ERR "TLAN: Could not set up device.\n");
+		pr_err("Could not set up device\n");
 		goto err_out_free_dev;
 	}
 
 	rc = register_netdev(dev);
 	if (rc) {
-		printk(KERN_ERR "TLAN: Could not register device.\n");
+		pr_err("Could not register device\n");
 		goto err_out_uninit;
 	}
 
 
-	TLanDevicesInstalled++;
+	tlan_devices_installed++;
 	boards_found++;
 
 	/* pdev is NULL if this is an EISA device */
 	if (pdev)
 		tlan_have_pci++;
 	else {
-		priv->nextDevice = TLan_Eisa_Devices;
-		TLan_Eisa_Devices = dev;
+		priv->next_device = tlan_eisa_devices;
+		tlan_eisa_devices = dev;
 		tlan_have_eisa++;
 	}
 
-	printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n",
-			dev->name,
-			(int) dev->irq,
-			(int) dev->base_addr,
-			priv->adapter->deviceLabel,
-			priv->adapterRev);
+	netdev_info(dev, "irq=%2d, io=%04x, %s, Rev. %d\n",
+		    (int)dev->irq,
+		    (int)dev->base_addr,
+		    priv->adapter->device_label,
+		    priv->adapter_rev);
 	return 0;
 
 err_out_uninit:
-	pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage,
-			    priv->dmaStorageDMA );
+	pci_free_consistent(priv->pci_dev, priv->dma_size, priv->dma_storage,
+			    priv->dma_storage_dma);
 err_out_free_dev:
 	free_netdev(dev);
 err_out_regions:
@@ -689,22 +620,23 @@ err_out:
 }
 
 
-static void TLan_Eisa_Cleanup(void)
+static void tlan_eisa_cleanup(void)
 {
 	struct net_device *dev;
-	TLanPrivateInfo *priv;
+	struct tlan_priv *priv;
 
-	while( tlan_have_eisa ) {
-		dev = TLan_Eisa_Devices;
+	while (tlan_have_eisa) {
+		dev = tlan_eisa_devices;
 		priv = netdev_priv(dev);
-		if (priv->dmaStorage) {
-			pci_free_consistent(priv->pciDev, priv->dmaSize,
-					    priv->dmaStorage, priv->dmaStorageDMA );
+		if (priv->dma_storage) {
+			pci_free_consistent(priv->pci_dev, priv->dma_size,
+					    priv->dma_storage,
+					    priv->dma_storage_dma);
 		}
-		release_region( dev->base_addr, 0x10);
-		unregister_netdev( dev );
-		TLan_Eisa_Devices = priv->nextDevice;
-		free_netdev( dev );
+		release_region(dev->base_addr, 0x10);
+		unregister_netdev(dev);
+		tlan_eisa_devices = priv->next_device;
+		free_netdev(dev);
 		tlan_have_eisa--;
 	}
 }
@@ -715,7 +647,7 @@ static void __exit tlan_exit(void)
 	pci_unregister_driver(&tlan_driver);
 
 	if (tlan_have_eisa)
-		TLan_Eisa_Cleanup();
+		tlan_eisa_cleanup();
 
 }
 
@@ -726,24 +658,24 @@ module_exit(tlan_exit);
 
 
 
-	/**************************************************************
-	 * 	TLan_EisaProbe
-	 *
-	 *  	Returns: 0 on success, 1 otherwise
-	 *
-	 *  	Parms:	 None
-	 *
-	 *
-	 *  	This functions probes for EISA devices and calls
-	 *  	TLan_probe1 when one is found.
-	 *
-	 *************************************************************/
+/**************************************************************
+ *	tlan_eisa_probe
+ *
+ *	Returns: 0 on success, 1 otherwise
+ *
+ *	Parms:	 None
+ *
+ *
+ *	This functions probes for EISA devices and calls
+ *	TLan_probe1 when one is found.
+ *
+ *************************************************************/
 
-static void  __init TLan_EisaProbe (void)
+static void  __init tlan_eisa_probe(void)
 {
-	long 	ioaddr;
-	int 	rc = -ENODEV;
-	int 	irq;
+	long	ioaddr;
+	int	rc = -ENODEV;
+	int	irq;
 	u16	device_id;
 
 	if (!EISA_bus) {
@@ -754,15 +686,16 @@ static void  __init TLan_EisaProbe (void)
 	/* Loop through all slots of the EISA bus */
 	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
 
-	TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
-		 (int) ioaddr + 0xC80, inw(ioaddr + EISA_ID));
-	TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
-		 (int) ioaddr + 0xC82, inw(ioaddr + EISA_ID2));
+		TLAN_DBG(TLAN_DEBUG_PROBE, "EISA_ID 0x%4x: 0x%4x\n",
+			 (int) ioaddr + 0xc80, inw(ioaddr + EISA_ID));
+		TLAN_DBG(TLAN_DEBUG_PROBE, "EISA_ID 0x%4x: 0x%4x\n",
+			 (int) ioaddr + 0xc82, inw(ioaddr + EISA_ID2));
 
 
-		TLAN_DBG(TLAN_DEBUG_PROBE, "Probing for EISA adapter at IO: 0x%4x : ",
-				   	(int) ioaddr);
-		if (request_region(ioaddr, 0x10, TLanSignature) == NULL)
+		TLAN_DBG(TLAN_DEBUG_PROBE,
+			 "Probing for EISA adapter at IO: 0x%4x : ",
+			 (int) ioaddr);
+		if (request_region(ioaddr, 0x10, tlan_signature) == NULL)
 			goto out;
 
 		if (inw(ioaddr + EISA_ID) != 0x110E) {
@@ -772,326 +705,324 @@ static void  __init TLan_EisaProbe (void)
 
 		device_id = inw(ioaddr + EISA_ID2);
 		if (device_id !=  0x20F1 && device_id != 0x40F1) {
-			release_region (ioaddr, 0x10);
+			release_region(ioaddr, 0x10);
 			goto out;
 		}
 
-	 	if (inb(ioaddr + EISA_CR) != 0x1) { 	/* Check if adapter is enabled */
-			release_region (ioaddr, 0x10);
+		/* check if adapter is enabled */
+		if (inb(ioaddr + EISA_CR) != 0x1) {
+			release_region(ioaddr, 0x10);
 			goto out2;
 		}
 
 		if (debug == 0x10)
-			printk("Found one\n");
+			pr_info("Found one\n");
 
 
 		/* Get irq from board */
-		switch (inb(ioaddr + 0xCC0)) {
-			case(0x10):
-				irq=5;
-				break;
-			case(0x20):
-				irq=9;
-				break;
-			case(0x40):
-				irq=10;
-				break;
-			case(0x80):
-				irq=11;
-				break;
-			default:
-				goto out;
+		switch (inb(ioaddr + 0xcc0)) {
+		case(0x10):
+			irq = 5;
+			break;
+		case(0x20):
+			irq = 9;
+			break;
+		case(0x40):
+			irq = 10;
+			break;
+		case(0x80):
+			irq = 11;
+			break;
+		default:
+			goto out;
 		}
 
 
 		/* Setup the newly found eisa adapter */
-		rc = TLan_probe1( NULL, ioaddr, irq,
-					12, NULL);
+		rc = tlan_probe1(NULL, ioaddr, irq,
+				 12, NULL);
 		continue;
 
-		out:
-			if (debug == 0x10)
-				printk("None found\n");
-			continue;
+out:
+		if (debug == 0x10)
+			pr_info("None found\n");
+		continue;
 
-		out2:	if (debug == 0x10)
-				printk("Card found but it is not enabled, skipping\n");
-			continue;
+out2:
+		if (debug == 0x10)
+			pr_info("Card found but it is not enabled, skipping\n");
+		continue;
 
 	}
 
-} /* TLan_EisaProbe */
+}
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static void TLan_Poll(struct net_device *dev)
+static void tlan_poll(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	TLan_HandleInterrupt(dev->irq, dev);
+	tlan_handle_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
 
-static const struct net_device_ops TLan_netdev_ops = {
-	.ndo_open 		= TLan_Open,
-	.ndo_stop		= TLan_Close,
-	.ndo_start_xmit		= TLan_StartTx,
-	.ndo_tx_timeout		= TLan_tx_timeout,
-	.ndo_get_stats		= TLan_GetStats,
-	.ndo_set_multicast_list = TLan_SetMulticastList,
-	.ndo_do_ioctl		= TLan_ioctl,
+static const struct net_device_ops tlan_netdev_ops = {
+	.ndo_open		= tlan_open,
+	.ndo_stop		= tlan_close,
+	.ndo_start_xmit		= tlan_start_tx,
+	.ndo_tx_timeout		= tlan_tx_timeout,
+	.ndo_get_stats		= tlan_get_stats,
+	.ndo_set_multicast_list = tlan_set_multicast_list,
+	.ndo_do_ioctl		= tlan_ioctl,
 	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	 = TLan_Poll,
+	.ndo_poll_controller	 = tlan_poll,
 #endif
 };
 
 
 
-	/***************************************************************
-	 *	TLan_Init
-	 *
-	 *	Returns:
-	 *		0 on success, error code otherwise.
-	 *	Parms:
-	 *		dev	The structure of the device to be
-	 *			init'ed.
-	 *
-	 *	This function completes the initialization of the
-	 *	device structure and driver.  It reserves the IO
-	 *	addresses, allocates memory for the lists and bounce
-	 *	buffers, retrieves the MAC address from the eeprom
-	 *	and assignes the device's methods.
-	 *
-	 **************************************************************/
-
-static int TLan_Init( struct net_device *dev )
+/***************************************************************
+ *	tlan_init
+ *
+ *	Returns:
+ *		0 on success, error code otherwise.
+ *	Parms:
+ *		dev	The structure of the device to be
+ *			init'ed.
+ *
+ *	This function completes the initialization of the
+ *	device structure and driver.  It reserves the IO
+ *	addresses, allocates memory for the lists and bounce
+ *	buffers, retrieves the MAC address from the eeprom
+ *	and assignes the device's methods.
+ *
+ **************************************************************/
+
+static int tlan_init(struct net_device *dev)
 {
 	int		dma_size;
-	int 		err;
+	int		err;
 	int		i;
-	TLanPrivateInfo	*priv;
+	struct tlan_priv	*priv;
 
 	priv = netdev_priv(dev);
 
-	dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
-		* ( sizeof(TLanList) );
-	priv->dmaStorage = pci_alloc_consistent(priv->pciDev,
-						dma_size, &priv->dmaStorageDMA);
-	priv->dmaSize = dma_size;
+	dma_size = (TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS)
+		* (sizeof(struct tlan_list));
+	priv->dma_storage = pci_alloc_consistent(priv->pci_dev,
+						 dma_size,
+						 &priv->dma_storage_dma);
+	priv->dma_size = dma_size;
 
-	if ( priv->dmaStorage == NULL ) {
-		printk(KERN_ERR "TLAN:  Could not allocate lists and buffers for %s.\n",
-			dev->name );
+	if (priv->dma_storage == NULL) {
+		pr_err("Could not allocate lists and buffers for %s\n",
+		       dev->name);
 		return -ENOMEM;
 	}
-	memset( priv->dmaStorage, 0, dma_size );
-	priv->rxList = (TLanList *) ALIGN((unsigned long)priv->dmaStorage, 8);
-	priv->rxListDMA = ALIGN(priv->dmaStorageDMA, 8);
-	priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
-	priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS;
+	memset(priv->dma_storage, 0, dma_size);
+	priv->rx_list = (struct tlan_list *)
+		ALIGN((unsigned long)priv->dma_storage, 8);
+	priv->rx_list_dma = ALIGN(priv->dma_storage_dma, 8);
+	priv->tx_list = priv->rx_list + TLAN_NUM_RX_LISTS;
+	priv->tx_list_dma =
+		priv->rx_list_dma + sizeof(struct tlan_list)*TLAN_NUM_RX_LISTS;
 
 	err = 0;
-	for ( i = 0;  i < 6 ; i++ )
-		err |= TLan_EeReadByte( dev,
-					(u8) priv->adapter->addrOfs + i,
-					(u8 *) &dev->dev_addr[i] );
-	if ( err ) {
-		printk(KERN_ERR "TLAN: %s: Error reading MAC from eeprom: %d\n",
-			dev->name,
-			err );
+	for (i = 0;  i < 6 ; i++)
+		err |= tlan_ee_read_byte(dev,
+					 (u8) priv->adapter->addr_ofs + i,
+					 (u8 *) &dev->dev_addr[i]);
+	if (err) {
+		pr_err("%s: Error reading MAC from eeprom: %d\n",
+		       dev->name, err);
 	}
 	dev->addr_len = 6;
 
 	netif_carrier_off(dev);
 
 	/* Device methods */
-	dev->netdev_ops = &TLan_netdev_ops;
+	dev->netdev_ops = &tlan_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	return 0;
 
-} /* TLan_Init */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_Open
-	 *
-	 *	Returns:
-	 *		0 on success, error code otherwise.
-	 *	Parms:
-	 *		dev	Structure of device to be opened.
-	 *
-	 *	This routine puts the driver and TLAN adapter in a
-	 *	state where it is ready to send and receive packets.
-	 *	It allocates the IRQ, resets and brings the adapter
-	 *	out of reset, and allows interrupts.  It also delays
-	 *	the startup for autonegotiation or sends a Rx GO
-	 *	command to the adapter, as appropriate.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_open
+ *
+ *	Returns:
+ *		0 on success, error code otherwise.
+ *	Parms:
+ *		dev	Structure of device to be opened.
+ *
+ *	This routine puts the driver and TLAN adapter in a
+ *	state where it is ready to send and receive packets.
+ *	It allocates the IRQ, resets and brings the adapter
+ *	out of reset, and allows interrupts.  It also delays
+ *	the startup for autonegotiation or sends a Rx GO
+ *	command to the adapter, as appropriate.
+ *
+ **************************************************************/
 
-static int TLan_Open( struct net_device *dev )
+static int tlan_open(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int		err;
 
-	priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
-	err = request_irq( dev->irq, TLan_HandleInterrupt, IRQF_SHARED,
-			   dev->name, dev );
+	priv->tlan_rev = tlan_dio_read8(dev->base_addr, TLAN_DEF_REVISION);
+	err = request_irq(dev->irq, tlan_handle_interrupt, IRQF_SHARED,
+			  dev->name, dev);
 
-	if ( err ) {
-		pr_err("TLAN:  Cannot open %s because IRQ %d is already in use.\n",
-		       dev->name, dev->irq );
+	if (err) {
+		netdev_err(dev, "Cannot open because IRQ %d is already in use\n",
+			   dev->irq);
 		return err;
 	}
 
 	init_timer(&priv->timer);
-	netif_start_queue(dev);
 
-	/* NOTE: It might not be necessary to read the stats before a
-			 reset if you don't care what the values are.
-	*/
-	TLan_ResetLists( dev );
-	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
-	TLan_ResetAdapter( dev );
+	tlan_start(dev);
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened.  TLAN Chip Rev: %x\n",
-		  dev->name, priv->tlanRev );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Opened.  TLAN Chip Rev: %x\n",
+		 dev->name, priv->tlan_rev);
 
 	return 0;
 
-} /* TLan_Open */
+}
 
 
 
-	/**************************************************************
-	 *	TLan_ioctl
-	 *
-	 *	Returns:
-	 *		0 on success, error code otherwise
-	 *	Params:
-	 *		dev	structure of device to receive ioctl.
-	 *
-	 *		rq	ifreq structure to hold userspace data.
-	 *
-	 *		cmd	ioctl command.
-	 *
-	 *
-	 *************************************************************/
+/**************************************************************
+ *	tlan_ioctl
+ *
+ *	Returns:
+ *		0 on success, error code otherwise
+ *	Params:
+ *		dev	structure of device to receive ioctl.
+ *
+ *		rq	ifreq structure to hold userspace data.
+ *
+ *		cmd	ioctl command.
+ *
+ *
+ *************************************************************/
 
-static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int tlan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	struct mii_ioctl_data *data = if_mii(rq);
-	u32 phy   = priv->phy[priv->phyNum];
+	u32 phy   = priv->phy[priv->phy_num];
 
-	if (!priv->phyOnline)
+	if (!priv->phy_online)
 		return -EAGAIN;
 
-	switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-			data->phy_id = phy;
+	switch (cmd) {
+	case SIOCGMIIPHY:		/* get address of MII PHY in use. */
+		data->phy_id = phy;
 
 
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-			TLan_MiiReadReg(dev, data->phy_id & 0x1f,
-					data->reg_num & 0x1f, &data->val_out);
-			return 0;
+	case SIOCGMIIREG:		/* read MII PHY register. */
+		tlan_mii_read_reg(dev, data->phy_id & 0x1f,
+				  data->reg_num & 0x1f, &data->val_out);
+		return 0;
 
 
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-			TLan_MiiWriteReg(dev, data->phy_id & 0x1f,
-					 data->reg_num & 0x1f, data->val_in);
-			return 0;
-		default:
-			return -EOPNOTSUPP;
+	case SIOCSMIIREG:		/* write MII PHY register. */
+		tlan_mii_write_reg(dev, data->phy_id & 0x1f,
+				   data->reg_num & 0x1f, data->val_in);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
 	}
-} /* tlan_ioctl */
+}
 
 
-	/***************************************************************
-	 * 	TLan_tx_timeout
-	 *
-	 * 	Returns: nothing
-	 *
-	 * 	Params:
-	 * 		dev	structure of device which timed out
-	 * 			during transmit.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_tx_timeout
+ *
+ *	Returns: nothing
+ *
+ *	Params:
+ *		dev	structure of device which timed out
+ *			during transmit.
+ *
+ **************************************************************/
 
-static void TLan_tx_timeout(struct net_device *dev)
+static void tlan_tx_timeout(struct net_device *dev)
 {
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);
 
 	/* Ok so we timed out, lets see what we can do about it...*/
-	TLan_FreeLists( dev );
-	TLan_ResetLists( dev );
-	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
-	TLan_ResetAdapter( dev );
+	tlan_free_lists(dev);
+	tlan_reset_lists(dev);
+	tlan_read_and_clear_stats(dev, TLAN_IGNORE);
+	tlan_reset_adapter(dev);
 	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue( dev );
+	netif_wake_queue(dev);
 
 }
 
 
-	/***************************************************************
-	 * 	TLan_tx_timeout_work
-	 *
-	 * 	Returns: nothing
-	 *
-	 * 	Params:
-	 * 		work	work item of device which timed out
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_tx_timeout_work
+ *
+ *	Returns: nothing
+ *
+ *	Params:
+ *		work	work item of device which timed out
+ *
+ **************************************************************/
 
-static void TLan_tx_timeout_work(struct work_struct *work)
+static void tlan_tx_timeout_work(struct work_struct *work)
 {
-	TLanPrivateInfo	*priv =
-		container_of(work, TLanPrivateInfo, tlan_tqueue);
+	struct tlan_priv	*priv =
+		container_of(work, struct tlan_priv, tlan_tqueue);
 
-	TLan_tx_timeout(priv->dev);
+	tlan_tx_timeout(priv->dev);
 }
 
 
 
-	/***************************************************************
-	 *	TLan_StartTx
-	 *
-	 *	Returns:
-	 *		0 on success, non-zero on failure.
-	 *	Parms:
-	 *		skb	A pointer to the sk_buff containing the
-	 *			frame to be sent.
-	 *		dev	The device to send the data on.
-	 *
-	 *	This function adds a frame to the Tx list to be sent
-	 *	ASAP.  First it	verifies that the adapter is ready and
-	 *	there is room in the queue.  Then it sets up the next
-	 *	available list, copies the frame to the	corresponding
-	 *	buffer.  If the adapter Tx channel is idle, it gives
-	 *	the adapter a Tx Go command on the list, otherwise it
-	 *	sets the forward address of the previous list to point
-	 *	to this one.  Then it frees the sk_buff.
-	 *
-	 **************************************************************/
-
-static netdev_tx_t TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
+/***************************************************************
+ *	tlan_start_tx
+ *
+ *	Returns:
+ *		0 on success, non-zero on failure.
+ *	Parms:
+ *		skb	A pointer to the sk_buff containing the
+ *			frame to be sent.
+ *		dev	The device to send the data on.
+ *
+ *	This function adds a frame to the Tx list to be sent
+ *	ASAP.  First it	verifies that the adapter is ready and
+ *	there is room in the queue.  Then it sets up the next
+ *	available list, copies the frame to the	corresponding
+ *	buffer.  If the adapter Tx channel is idle, it gives
+ *	the adapter a Tx Go command on the list, otherwise it
+ *	sets the forward address of the previous list to point
+ *	to this one.  Then it frees the sk_buff.
+ *
+ **************************************************************/
+
+static netdev_tx_t tlan_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	dma_addr_t	tail_list_phys;
-	TLanList	*tail_list;
+	struct tlan_list	*tail_list;
 	unsigned long	flags;
 	unsigned int    txlen;
 
-	if ( ! priv->phyOnline ) {
-		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n",
-			  dev->name );
+	if (!priv->phy_online) {
+		TLAN_DBG(TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n",
+			 dev->name);
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
@@ -1100,218 +1031,214 @@ static netdev_tx_t TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
 		return NETDEV_TX_OK;
 	txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE);
 
-	tail_list = priv->txList + priv->txTail;
-	tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail;
+	tail_list = priv->tx_list + priv->tx_tail;
+	tail_list_phys =
+		priv->tx_list_dma + sizeof(struct tlan_list)*priv->tx_tail;
 
-	if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n",
-			  dev->name, priv->txHead, priv->txTail );
+	if (tail_list->c_stat != TLAN_CSTAT_UNUSED) {
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n",
+			 dev->name, priv->tx_head, priv->tx_tail);
 		netif_stop_queue(dev);
-		priv->txBusyCount++;
+		priv->tx_busy_count++;
 		return NETDEV_TX_BUSY;
 	}
 
 	tail_list->forward = 0;
 
-	tail_list->buffer[0].address = pci_map_single(priv->pciDev,
+	tail_list->buffer[0].address = pci_map_single(priv->pci_dev,
 						      skb->data, txlen,
 						      PCI_DMA_TODEVICE);
-	TLan_StoreSKB(tail_list, skb);
+	tlan_store_skb(tail_list, skb);
 
-	tail_list->frameSize = (u16) txlen;
+	tail_list->frame_size = (u16) txlen;
 	tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen;
 	tail_list->buffer[1].count = 0;
 	tail_list->buffer[1].address = 0;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	tail_list->cStat = TLAN_CSTAT_READY;
-	if ( ! priv->txInProgress ) {
-		priv->txInProgress = 1;
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );
-		outl( tail_list_phys, dev->base_addr + TLAN_CH_PARM );
-		outl( TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD );
+	tail_list->c_stat = TLAN_CSTAT_READY;
+	if (!priv->tx_in_progress) {
+		priv->tx_in_progress = 1;
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  Starting TX on buffer %d\n",
+			 priv->tx_tail);
+		outl(tail_list_phys, dev->base_addr + TLAN_CH_PARM);
+		outl(TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD);
 	} else {
-		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Adding buffer %d to TX channel\n",
-			  priv->txTail );
-		if ( priv->txTail == 0 ) {
-			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  Adding buffer %d to TX channel\n",
+			 priv->tx_tail);
+		if (priv->tx_tail == 0) {
+			(priv->tx_list + (TLAN_NUM_TX_LISTS - 1))->forward
 				= tail_list_phys;
 		} else {
-			( priv->txList + ( priv->txTail - 1 ) )->forward
+			(priv->tx_list + (priv->tx_tail - 1))->forward
 				= tail_list_phys;
 		}
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
+	CIRC_INC(priv->tx_tail, TLAN_NUM_TX_LISTS);
 
 	return NETDEV_TX_OK;
 
-} /* TLan_StartTx */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleInterrupt
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		irq	The line on which the interrupt
-	 *			occurred.
-	 *		dev_id	A pointer to the device assigned to
-	 *			this irq line.
-	 *
-	 *	This function handles an interrupt generated by its
-	 *	assigned TLAN adapter.  The function deactivates
-	 *	interrupts on its adapter, records the type of
-	 *	interrupt, executes the appropriate subhandler, and
-	 *	acknowdges the interrupt to the adapter (thus
-	 *	re-enabling adapter interrupts.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_interrupt
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		irq	The line on which the interrupt
+ *			occurred.
+ *		dev_id	A pointer to the device assigned to
+ *			this irq line.
+ *
+ *	This function handles an interrupt generated by its
+ *	assigned TLAN adapter.  The function deactivates
+ *	interrupts on its adapter, records the type of
+ *	interrupt, executes the appropriate subhandler, and
+ *	acknowdges the interrupt to the adapter (thus
+ *	re-enabling adapter interrupts.
+ *
+ **************************************************************/
 
-static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id)
+static irqreturn_t tlan_handle_interrupt(int irq, void *dev_id)
 {
 	struct net_device	*dev = dev_id;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16		host_int;
 	u16		type;
 
 	spin_lock(&priv->lock);
 
-	host_int = inw( dev->base_addr + TLAN_HOST_INT );
-	type = ( host_int & TLAN_HI_IT_MASK ) >> 2;
-	if ( type ) {
+	host_int = inw(dev->base_addr + TLAN_HOST_INT);
+	type = (host_int & TLAN_HI_IT_MASK) >> 2;
+	if (type) {
 		u32	ack;
 		u32	host_cmd;
 
-		outw( host_int, dev->base_addr + TLAN_HOST_INT );
-		ack = TLanIntVector[type]( dev, host_int );
+		outw(host_int, dev->base_addr + TLAN_HOST_INT);
+		ack = tlan_int_vector[type](dev, host_int);
 
-		if ( ack ) {
-			host_cmd = TLAN_HC_ACK | ack | ( type << 18 );
-			outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
+		if (ack) {
+			host_cmd = TLAN_HC_ACK | ack | (type << 18);
+			outl(host_cmd, dev->base_addr + TLAN_HOST_CMD);
 		}
 	}
 
 	spin_unlock(&priv->lock);
 
 	return IRQ_RETVAL(type);
-} /* TLan_HandleInterrupts */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_Close
-	 *
-	 * 	Returns:
-	 *		An error code.
-	 *	Parms:
-	 *		dev	The device structure of the device to
-	 *			close.
-	 *
-	 *	This function shuts down the adapter.  It records any
-	 *	stats, puts the adapter into reset state, deactivates
-	 *	its time as needed, and	frees the irq it is using.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_close
+ *
+ *	Returns:
+ *		An error code.
+ *	Parms:
+ *		dev	The device structure of the device to
+ *			close.
+ *
+ *	This function shuts down the adapter.  It records any
+ *	stats, puts the adapter into reset state, deactivates
+ *	its time as needed, and	frees the irq it is using.
+ *
+ **************************************************************/
 
-static int TLan_Close(struct net_device *dev)
+static int tlan_close(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 
-	netif_stop_queue(dev);
 	priv->neg_be_verbose = 0;
+	tlan_stop(dev);
 
-	TLan_ReadAndClearStats( dev, TLAN_RECORD );
-	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
-	if ( priv->timer.function != NULL ) {
-		del_timer_sync( &priv->timer );
-		priv->timer.function = NULL;
-	}
-
-	free_irq( dev->irq, dev );
-	TLan_FreeLists( dev );
-	TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );
+	free_irq(dev->irq, dev);
+	tlan_free_lists(dev);
+	TLAN_DBG(TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name);
 
 	return 0;
 
-} /* TLan_Close */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_GetStats
-	 *
-	 *	Returns:
-	 *		A pointer to the device's statistics structure.
-	 *	Parms:
-	 *		dev	The device structure to return the
-	 *			stats for.
-	 *
-	 *	This function updates the devices statistics by reading
-	 *	the TLAN chip's onboard registers.  Then it returns the
-	 *	address of the statistics structure.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_get_stats
+ *
+ *	Returns:
+ *		A pointer to the device's statistics structure.
+ *	Parms:
+ *		dev	The device structure to return the
+ *			stats for.
+ *
+ *	This function updates the devices statistics by reading
+ *	the TLAN chip's onboard registers.  Then it returns the
+ *	address of the statistics structure.
+ *
+ **************************************************************/
 
-static struct net_device_stats *TLan_GetStats( struct net_device *dev )
+static struct net_device_stats *tlan_get_stats(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int i;
 
 	/* Should only read stats if open ? */
-	TLan_ReadAndClearStats( dev, TLAN_RECORD );
+	tlan_read_and_clear_stats(dev, TLAN_RECORD);
 
-	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  %s EOC count = %d\n", dev->name,
-		  priv->rxEocCount );
-	TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s Busy count = %d\n", dev->name,
-		  priv->txBusyCount );
-	if ( debug & TLAN_DEBUG_GNRL ) {
-		TLan_PrintDio( dev->base_addr );
-		TLan_PhyPrint( dev );
+	TLAN_DBG(TLAN_DEBUG_RX, "RECEIVE:  %s EOC count = %d\n", dev->name,
+		 priv->rx_eoc_count);
+	TLAN_DBG(TLAN_DEBUG_TX, "TRANSMIT:  %s Busy count = %d\n", dev->name,
+		 priv->tx_busy_count);
+	if (debug & TLAN_DEBUG_GNRL) {
+		tlan_print_dio(dev->base_addr);
+		tlan_phy_print(dev);
 	}
-	if ( debug & TLAN_DEBUG_LIST ) {
-		for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ )
-			TLan_PrintList( priv->rxList + i, "RX", i );
-		for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ )
-			TLan_PrintList( priv->txList + i, "TX", i );
+	if (debug & TLAN_DEBUG_LIST) {
+		for (i = 0; i < TLAN_NUM_RX_LISTS; i++)
+			tlan_print_list(priv->rx_list + i, "RX", i);
+		for (i = 0; i < TLAN_NUM_TX_LISTS; i++)
+			tlan_print_list(priv->tx_list + i, "TX", i);
 	}
 
 	return &dev->stats;
 
-} /* TLan_GetStats */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_SetMulticastList
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	The device structure to set the
-	 *			multicast list for.
-	 *
-	 *	This function sets the TLAN adaptor to various receive
-	 *	modes.  If the IFF_PROMISC flag is set, promiscuous
-	 *	mode is acitviated.  Otherwise,	promiscuous mode is
-	 *	turned off.  If the IFF_ALLMULTI flag is set, then
-	 *	the hash table is set to receive all group addresses.
-	 *	Otherwise, the first three multicast addresses are
-	 *	stored in AREG_1-3, and the rest are selected via the
-	 *	hash table, as necessary.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_set_multicast_list
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	The device structure to set the
+ *			multicast list for.
+ *
+ *	This function sets the TLAN adaptor to various receive
+ *	modes.  If the IFF_PROMISC flag is set, promiscuous
+ *	mode is acitviated.  Otherwise,	promiscuous mode is
+ *	turned off.  If the IFF_ALLMULTI flag is set, then
+ *	the hash table is set to receive all group addresses.
+ *	Otherwise, the first three multicast addresses are
+ *	stored in AREG_1-3, and the rest are selected via the
+ *	hash table, as necessary.
+ *
+ **************************************************************/
 
-static void TLan_SetMulticastList( struct net_device *dev )
+static void tlan_set_multicast_list(struct net_device *dev)
 {
 	struct netdev_hw_addr *ha;
 	u32			hash1 = 0;
@@ -1320,53 +1247,56 @@ static void TLan_SetMulticastList( struct net_device *dev )
 	u32			offset;
 	u8			tmp;
 
-	if ( dev->flags & IFF_PROMISC ) {
-		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF );
+	if (dev->flags & IFF_PROMISC) {
+		tmp = tlan_dio_read8(dev->base_addr, TLAN_NET_CMD);
+		tlan_dio_write8(dev->base_addr,
+				TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF);
 	} else {
-		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF );
-		if ( dev->flags & IFF_ALLMULTI ) {
-			for ( i = 0; i < 3; i++ )
-				TLan_SetMac( dev, i + 1, NULL );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF );
+		tmp = tlan_dio_read8(dev->base_addr, TLAN_NET_CMD);
+		tlan_dio_write8(dev->base_addr,
+				TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF);
+		if (dev->flags & IFF_ALLMULTI) {
+			for (i = 0; i < 3; i++)
+				tlan_set_mac(dev, i + 1, NULL);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_1,
+					 0xffffffff);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_2,
+					 0xffffffff);
 		} else {
 			i = 0;
 			netdev_for_each_mc_addr(ha, dev) {
-				if ( i < 3 ) {
-					TLan_SetMac( dev, i + 1,
+				if (i < 3) {
+					tlan_set_mac(dev, i + 1,
 						     (char *) &ha->addr);
 				} else {
-					offset = TLan_HashFunc((u8 *)&ha->addr);
-					if ( offset < 32 )
-						hash1 |= ( 1 << offset );
+					offset =
+						tlan_hash_func((u8 *)&ha->addr);
+					if (offset < 32)
+						hash1 |= (1 << offset);
 					else
-						hash2 |= ( 1 << ( offset - 32 ) );
+						hash2 |= (1 << (offset - 32));
 				}
 				i++;
 			}
-			for ( ; i < 3; i++ )
-				TLan_SetMac( dev, i + 1, NULL );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, hash1 );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, hash2 );
+			for ( ; i < 3; i++)
+				tlan_set_mac(dev, i + 1, NULL);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_1, hash1);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_2, hash2);
 		}
 	}
 
-} /* TLan_SetMulticastList */
+}
 
 
 
 /*****************************************************************************
 ******************************************************************************
 
-        ThunderLAN Driver Interrupt Vectors and Table
+ThunderLAN driver interrupt vectors and table
 
-	Please see Chap. 4, "Interrupt Handling" of the "ThunderLAN
-	Programmer's Guide" for more informations on handling interrupts
-	generated by TLAN based adapters.
+please see chap. 4, "Interrupt Handling" of the "ThunderLAN
+Programmer's Guide" for more informations on handling interrupts
+generated by TLAN based adapters.
 
 ******************************************************************************
 *****************************************************************************/
@@ -1374,46 +1304,48 @@ static void TLan_SetMulticastList( struct net_device *dev )
 
 
 
-	/***************************************************************
-	 *	TLan_HandleTxEOF
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles Tx EOF interrupts which are raised
-	 *	by the adapter when it has completed sending the
-	 *	contents of a buffer.  If detemines which list/buffer
-	 *	was completed and resets it.  If the buffer was the last
-	 *	in the channel (EOC), then the function checks to see if
-	 *	another buffer is ready to send, and if so, sends a Tx
-	 *	Go command.  Finally, the driver activates/continues the
-	 *	activity LED.
-	 *
-	 **************************************************************/
-
-static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
+/***************************************************************
+ *	tlan_handle_tx_eof
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles Tx EOF interrupts which are raised
+ *	by the adapter when it has completed sending the
+ *	contents of a buffer.  If detemines which list/buffer
+ *	was completed and resets it.  If the buffer was the last
+ *	in the channel (EOC), then the function checks to see if
+ *	another buffer is ready to send, and if so, sends a Tx
+ *	Go command.  Finally, the driver activates/continues the
+ *	activity LED.
+ *
+ **************************************************************/
+
+static u32 tlan_handle_tx_eof(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int		eoc = 0;
-	TLanList	*head_list;
+	struct tlan_list	*head_list;
 	dma_addr_t	head_list_phys;
 	u32		ack = 0;
-	u16		tmpCStat;
+	u16		tmp_c_stat;
 
-	TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n",
-		  priv->txHead, priv->txTail );
-	head_list = priv->txList + priv->txHead;
+	TLAN_DBG(TLAN_DEBUG_TX,
+		 "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n",
+		 priv->tx_head, priv->tx_tail);
+	head_list = priv->tx_list + priv->tx_head;
 
-	while (((tmpCStat = head_list->cStat ) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
-		struct sk_buff *skb = TLan_GetSKB(head_list);
+	while (((tmp_c_stat = head_list->c_stat) & TLAN_CSTAT_FRM_CMP)
+	       && (ack < 255)) {
+		struct sk_buff *skb = tlan_get_skb(head_list);
 
 		ack++;
-		pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
+		pci_unmap_single(priv->pci_dev, head_list->buffer[0].address,
 				 max(skb->len,
 				     (unsigned int)TLAN_MIN_FRAME_SIZE),
 				 PCI_DMA_TODEVICE);
@@ -1421,304 +1353,313 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
 		head_list->buffer[8].address = 0;
 		head_list->buffer[9].address = 0;
 
-		if ( tmpCStat & TLAN_CSTAT_EOC )
+		if (tmp_c_stat & TLAN_CSTAT_EOC)
 			eoc = 1;
 
-		dev->stats.tx_bytes += head_list->frameSize;
+		dev->stats.tx_bytes += head_list->frame_size;
 
-		head_list->cStat = TLAN_CSTAT_UNUSED;
+		head_list->c_stat = TLAN_CSTAT_UNUSED;
 		netif_start_queue(dev);
-		CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
-		head_list = priv->txList + priv->txHead;
+		CIRC_INC(priv->tx_head, TLAN_NUM_TX_LISTS);
+		head_list = priv->tx_list + priv->tx_head;
 	}
 
 	if (!ack)
-		printk(KERN_INFO "TLAN: Received interrupt for uncompleted TX frame.\n");
-
-	if ( eoc ) {
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n",
-			  priv->txHead, priv->txTail );
-		head_list = priv->txList + priv->txHead;
-		head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
-		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
-			outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
+		netdev_info(dev,
+			    "Received interrupt for uncompleted TX frame\n");
+
+	if (eoc) {
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  handling TX EOC (Head=%d Tail=%d)\n",
+			 priv->tx_head, priv->tx_tail);
+		head_list = priv->tx_list + priv->tx_head;
+		head_list_phys = priv->tx_list_dma
+			+ sizeof(struct tlan_list)*priv->tx_head;
+		if ((head_list->c_stat & TLAN_CSTAT_READY)
+		    == TLAN_CSTAT_READY) {
+			outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 			ack |= TLAN_HC_GO;
 		} else {
-			priv->txInProgress = 0;
+			priv->tx_in_progress = 0;
 		}
 	}
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
-		if ( priv->timer.function == NULL ) {
-			 priv->timer.function = TLan_Timer;
-			 priv->timer.data = (unsigned long) dev;
-			 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
-			 priv->timerSetAt = jiffies;
-			 priv->timerType = TLAN_TIMER_ACTIVITY;
-			 add_timer(&priv->timer);
-		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
-			priv->timerSetAt = jiffies;
+	if (priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED) {
+		tlan_dio_write8(dev->base_addr,
+				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT);
+		if (priv->timer.function == NULL) {
+			priv->timer.function = tlan_timer;
+			priv->timer.data = (unsigned long) dev;
+			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
+			priv->timer_set_at = jiffies;
+			priv->timer_type = TLAN_TIMER_ACTIVITY;
+			add_timer(&priv->timer);
+		} else if (priv->timer_type == TLAN_TIMER_ACTIVITY) {
+			priv->timer_set_at = jiffies;
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleTxEOF */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleStatOverflow
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles the Statistics Overflow interrupt
-	 *	which means that one or more of the TLAN statistics
-	 *	registers has reached 1/2 capacity and needs to be read.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_HandleStatOverflow
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles the Statistics Overflow interrupt
+ *	which means that one or more of the TLAN statistics
+ *	registers has reached 1/2 capacity and needs to be read.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_stat_overflow(struct net_device *dev, u16 host_int)
 {
-	TLan_ReadAndClearStats( dev, TLAN_RECORD );
+	tlan_read_and_clear_stats(dev, TLAN_RECORD);
 
 	return 1;
 
-} /* TLan_HandleStatOverflow */
-
-
-
-
-	/***************************************************************
-	 *	TLan_HandleRxEOF
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles the Rx EOF interrupt which
-	 *	indicates a frame has been received by the adapter from
-	 *	the net and the frame has been transferred to memory.
-	 *	The function determines the bounce buffer the frame has
-	 *	been loaded into, creates a new sk_buff big enough to
-	 *	hold the frame, and sends it to protocol stack.  It
-	 *	then resets the used buffer and appends it to the end
-	 *	of the list.  If the frame was the last in the Rx
-	 *	channel (EOC), the function restarts the receive channel
-	 *	by sending an Rx Go command to the adapter.  Then it
-	 *	activates/continues the activity LED.
-	 *
-	 **************************************************************/
-
-static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
+}
+
+
+
+
+/***************************************************************
+ *	TLan_HandleRxEOF
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles the Rx EOF interrupt which
+ *	indicates a frame has been received by the adapter from
+ *	the net and the frame has been transferred to memory.
+ *	The function determines the bounce buffer the frame has
+ *	been loaded into, creates a new sk_buff big enough to
+ *	hold the frame, and sends it to protocol stack.  It
+ *	then resets the used buffer and appends it to the end
+ *	of the list.  If the frame was the last in the Rx
+ *	channel (EOC), the function restarts the receive channel
+ *	by sending an Rx Go command to the adapter.  Then it
+ *	activates/continues the activity LED.
+ *
+ **************************************************************/
+
+static u32 tlan_handle_rx_eof(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u32		ack = 0;
 	int		eoc = 0;
-	TLanList	*head_list;
+	struct tlan_list	*head_list;
 	struct sk_buff	*skb;
-	TLanList	*tail_list;
-	u16		tmpCStat;
+	struct tlan_list	*tail_list;
+	u16		tmp_c_stat;
 	dma_addr_t	head_list_phys;
 
-	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOF (Head=%d Tail=%d)\n",
-		  priv->rxHead, priv->rxTail );
-	head_list = priv->rxList + priv->rxHead;
-	head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
+	TLAN_DBG(TLAN_DEBUG_RX, "RECEIVE:  handling RX EOF (Head=%d Tail=%d)\n",
+		 priv->rx_head, priv->rx_tail);
+	head_list = priv->rx_list + priv->rx_head;
+	head_list_phys =
+		priv->rx_list_dma + sizeof(struct tlan_list)*priv->rx_head;
 
-	while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
-		dma_addr_t frameDma = head_list->buffer[0].address;
-		u32 frameSize = head_list->frameSize;
+	while (((tmp_c_stat = head_list->c_stat) & TLAN_CSTAT_FRM_CMP)
+	       && (ack < 255)) {
+		dma_addr_t frame_dma = head_list->buffer[0].address;
+		u32 frame_size = head_list->frame_size;
 		struct sk_buff *new_skb;
 
 		ack++;
-		if (tmpCStat & TLAN_CSTAT_EOC)
+		if (tmp_c_stat & TLAN_CSTAT_EOC)
 			eoc = 1;
 
 		new_skb = netdev_alloc_skb_ip_align(dev,
 						    TLAN_MAX_FRAME_SIZE + 5);
-		if ( !new_skb )
+		if (!new_skb)
 			goto drop_and_reuse;
 
-		skb = TLan_GetSKB(head_list);
-		pci_unmap_single(priv->pciDev, frameDma,
+		skb = tlan_get_skb(head_list);
+		pci_unmap_single(priv->pci_dev, frame_dma,
 				 TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
-		skb_put( skb, frameSize );
+		skb_put(skb, frame_size);
 
-		dev->stats.rx_bytes += frameSize;
+		dev->stats.rx_bytes += frame_size;
 
-		skb->protocol = eth_type_trans( skb, dev );
-		netif_rx( skb );
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
 
-		head_list->buffer[0].address = pci_map_single(priv->pciDev,
-							      new_skb->data,
-							      TLAN_MAX_FRAME_SIZE,
-							      PCI_DMA_FROMDEVICE);
+		head_list->buffer[0].address =
+			pci_map_single(priv->pci_dev, new_skb->data,
+				       TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
 
-		TLan_StoreSKB(head_list, new_skb);
+		tlan_store_skb(head_list, new_skb);
 drop_and_reuse:
 		head_list->forward = 0;
-		head_list->cStat = 0;
-		tail_list = priv->rxList + priv->rxTail;
+		head_list->c_stat = 0;
+		tail_list = priv->rx_list + priv->rx_tail;
 		tail_list->forward = head_list_phys;
 
-		CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );
-		CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );
-		head_list = priv->rxList + priv->rxHead;
-		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
+		CIRC_INC(priv->rx_head, TLAN_NUM_RX_LISTS);
+		CIRC_INC(priv->rx_tail, TLAN_NUM_RX_LISTS);
+		head_list = priv->rx_list + priv->rx_head;
+		head_list_phys = priv->rx_list_dma
+			+ sizeof(struct tlan_list)*priv->rx_head;
 	}
 
 	if (!ack)
-		printk(KERN_INFO "TLAN: Received interrupt for uncompleted RX frame.\n");
-
-
-	if ( eoc ) {
-		TLAN_DBG( TLAN_DEBUG_RX,
-			  "RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n",
-			  priv->rxHead, priv->rxTail );
-		head_list = priv->rxList + priv->rxHead;
-		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
-		outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
+		netdev_info(dev,
+			    "Received interrupt for uncompleted RX frame\n");
+
+
+	if (eoc) {
+		TLAN_DBG(TLAN_DEBUG_RX,
+			 "RECEIVE:  handling RX EOC (Head=%d Tail=%d)\n",
+			 priv->rx_head, priv->rx_tail);
+		head_list = priv->rx_list + priv->rx_head;
+		head_list_phys = priv->rx_list_dma
+			+ sizeof(struct tlan_list)*priv->rx_head;
+		outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
-		priv->rxEocCount++;
+		priv->rx_eoc_count++;
 	}
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
-		if ( priv->timer.function == NULL )  {
-			priv->timer.function = TLan_Timer;
+	if (priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED) {
+		tlan_dio_write8(dev->base_addr,
+				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT);
+		if (priv->timer.function == NULL)  {
+			priv->timer.function = tlan_timer;
 			priv->timer.data = (unsigned long) dev;
 			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
-			priv->timerSetAt = jiffies;
-			priv->timerType = TLAN_TIMER_ACTIVITY;
+			priv->timer_set_at = jiffies;
+			priv->timer_type = TLAN_TIMER_ACTIVITY;
 			add_timer(&priv->timer);
-		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
-			priv->timerSetAt = jiffies;
+		} else if (priv->timer_type == TLAN_TIMER_ACTIVITY) {
+			priv->timer_set_at = jiffies;
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleRxEOF */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleDummy
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles the Dummy interrupt, which is
-	 *	raised whenever a test interrupt is generated by setting
-	 *	the Req_Int bit of HOST_CMD to 1.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_dummy
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles the Dummy interrupt, which is
+ *	raised whenever a test interrupt is generated by setting
+ *	the Req_Int bit of HOST_CMD to 1.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleDummy( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_dummy(struct net_device *dev, u16 host_int)
 {
-	printk( "TLAN:  Test interrupt on %s.\n", dev->name );
+	netdev_info(dev, "Test interrupt\n");
 	return 1;
 
-} /* TLan_HandleDummy */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleTxEOC
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This driver is structured to determine EOC occurrences by
-	 *	reading the CSTAT member of the list structure.  Tx EOC
-	 *	interrupts are disabled via the DIO INTDIS register.
-	 *	However, TLAN chips before revision 3.0 didn't have this
-	 *	functionality, so process EOC events if this is the
-	 *	case.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_tx_eoc
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This driver is structured to determine EOC occurrences by
+ *	reading the CSTAT member of the list structure.  Tx EOC
+ *	interrupts are disabled via the DIO INTDIS register.
+ *	However, TLAN chips before revision 3.0 didn't have this
+ *	functionality, so process EOC events if this is the
+ *	case.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_tx_eoc(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
-	TLanList		*head_list;
+	struct tlan_priv	*priv = netdev_priv(dev);
+	struct tlan_list		*head_list;
 	dma_addr_t		head_list_phys;
 	u32			ack = 1;
 
 	host_int = 0;
-	if ( priv->tlanRev < 0x30 ) {
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d) -- IRQ\n",
-			  priv->txHead, priv->txTail );
-		head_list = priv->txList + priv->txHead;
-		head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
-		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
+	if (priv->tlan_rev < 0x30) {
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  handling TX EOC (Head=%d Tail=%d) -- IRQ\n",
+			 priv->tx_head, priv->tx_tail);
+		head_list = priv->tx_list + priv->tx_head;
+		head_list_phys = priv->tx_list_dma
+			+ sizeof(struct tlan_list)*priv->tx_head;
+		if ((head_list->c_stat & TLAN_CSTAT_READY)
+		    == TLAN_CSTAT_READY) {
 			netif_stop_queue(dev);
-			outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
+			outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 			ack |= TLAN_HC_GO;
 		} else {
-			priv->txInProgress = 0;
+			priv->tx_in_progress = 0;
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleTxEOC */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleStatusCheck
-	 *
-	 *	Returns:
-	 *		0 if Adapter check, 1 if Network Status check.
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles Adapter Check/Network Status
-	 *	interrupts generated by the adapter.  It checks the
-	 *	vector in the HOST_INT register to determine if it is
-	 *	an Adapter Check interrupt.  If so, it resets the
-	 *	adapter.  Otherwise it clears the status registers
-	 *	and services the PHY.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_status_check
+ *
+ *	Returns:
+ *		0 if Adapter check, 1 if Network Status check.
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles Adapter Check/Network Status
+ *	interrupts generated by the adapter.  It checks the
+ *	vector in the HOST_INT register to determine if it is
+ *	an Adapter Check interrupt.  If so, it resets the
+ *	adapter.  Otherwise it clears the status registers
+ *	and services the PHY.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_status_check(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u32		ack;
 	u32		error;
 	u8		net_sts;
@@ -1727,92 +1668,94 @@ static u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int )
 	u16		tlphy_sts;
 
 	ack = 1;
-	if ( host_int & TLAN_HI_IV_MASK ) {
-		netif_stop_queue( dev );
-		error = inl( dev->base_addr + TLAN_CH_PARM );
-		printk( "TLAN:  %s: Adaptor Error = 0x%x\n", dev->name, error );
-		TLan_ReadAndClearStats( dev, TLAN_RECORD );
-		outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
+	if (host_int & TLAN_HI_IV_MASK) {
+		netif_stop_queue(dev);
+		error = inl(dev->base_addr + TLAN_CH_PARM);
+		netdev_info(dev, "Adaptor Error = 0x%x\n", error);
+		tlan_read_and_clear_stats(dev, TLAN_RECORD);
+		outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
 
 		schedule_work(&priv->tlan_tqueue);
 
 		netif_wake_queue(dev);
 		ack = 0;
 	} else {
-		TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );
-		phy = priv->phy[priv->phyNum];
-
-		net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );
-		if ( net_sts ) {
-			TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );
-			TLAN_DBG( TLAN_DEBUG_GNRL, "%s:    Net_Sts = %x\n",
-				  dev->name, (unsigned) net_sts );
+		TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name);
+		phy = priv->phy[priv->phy_num];
+
+		net_sts = tlan_dio_read8(dev->base_addr, TLAN_NET_STS);
+		if (net_sts) {
+			tlan_dio_write8(dev->base_addr, TLAN_NET_STS, net_sts);
+			TLAN_DBG(TLAN_DEBUG_GNRL, "%s:    Net_Sts = %x\n",
+				 dev->name, (unsigned) net_sts);
 		}
-		if ( ( net_sts & TLAN_NET_STS_MIRQ ) &&  ( priv->phyNum == 0 ) ) {
-			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts );
-			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
-        		if ( ! ( tlphy_sts & TLAN_TS_POLOK ) &&
-			     ! ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
-                		tlphy_ctl |= TLAN_TC_SWAPOL;
-                		TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
-			} else if ( ( tlphy_sts & TLAN_TS_POLOK ) &&
-				    ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
-                		tlphy_ctl &= ~TLAN_TC_SWAPOL;
-                		TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
-        		}
-
-			if (debug) {
-				TLan_PhyPrint( dev );
+		if ((net_sts & TLAN_NET_STS_MIRQ) &&  (priv->phy_num == 0)) {
+			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_STS, &tlphy_sts);
+			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
+			if (!(tlphy_sts & TLAN_TS_POLOK) &&
+			    !(tlphy_ctl & TLAN_TC_SWAPOL)) {
+				tlphy_ctl |= TLAN_TC_SWAPOL;
+				tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL,
+						   tlphy_ctl);
+			} else if ((tlphy_sts & TLAN_TS_POLOK) &&
+				   (tlphy_ctl & TLAN_TC_SWAPOL)) {
+				tlphy_ctl &= ~TLAN_TC_SWAPOL;
+				tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL,
+						   tlphy_ctl);
 			}
+
+			if (debug)
+				tlan_phy_print(dev);
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleStatusCheck */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleRxEOC
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This driver is structured to determine EOC occurrences by
-	 *	reading the CSTAT member of the list structure.  Rx EOC
-	 *	interrupts are disabled via the DIO INTDIS register.
-	 *	However, TLAN chips before revision 3.0 didn't have this
-	 *	CSTAT member or a INTDIS register, so if this chip is
-	 *	pre-3.0, process EOC interrupts normally.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_rx_eoc
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This driver is structured to determine EOC occurrences by
+ *	reading the CSTAT member of the list structure.  Rx EOC
+ *	interrupts are disabled via the DIO INTDIS register.
+ *	However, TLAN chips before revision 3.0 didn't have this
+ *	CSTAT member or a INTDIS register, so if this chip is
+ *	pre-3.0, process EOC interrupts normally.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_rx_eoc(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	dma_addr_t	head_list_phys;
 	u32		ack = 1;
 
-	if (  priv->tlanRev < 0x30 ) {
-		TLAN_DBG( TLAN_DEBUG_RX,
-			  "RECEIVE:  Handling RX EOC (Head=%d Tail=%d) -- IRQ\n",
-			  priv->rxHead, priv->rxTail );
-		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
-		outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
+	if (priv->tlan_rev < 0x30) {
+		TLAN_DBG(TLAN_DEBUG_RX,
+			 "RECEIVE:  Handling RX EOC (head=%d tail=%d) -- IRQ\n",
+			 priv->rx_head, priv->rx_tail);
+		head_list_phys = priv->rx_list_dma
+			+ sizeof(struct tlan_list)*priv->rx_head;
+		outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
-		priv->rxEocCount++;
+		priv->rx_eoc_count++;
 	}
 
 	return ack;
 
-} /* TLan_HandleRxEOC */
+}
 
 
 
@@ -1820,98 +1763,98 @@ static u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int )
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Timer Function
+ThunderLAN driver timer function
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_Timer
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		data	A value given to add timer when
-	 *			add_timer was called.
-	 *
-	 *	This function handles timed functionality for the
-	 *	TLAN driver.  The two current timer uses are for
-	 *	delaying for autonegotionation and driving the ACT LED.
-	 *	-	Autonegotiation requires being allowed about
-	 *		2 1/2 seconds before attempting to transmit a
-	 *		packet.  It would be a very bad thing to hang
-	 *		the kernel this long, so the driver doesn't
-	 *		allow transmission 'til after this time, for
-	 *		certain PHYs.  It would be much nicer if all
-	 *		PHYs were interrupt-capable like the internal
-	 *		PHY.
-	 *	-	The ACT LED, which shows adapter activity, is
-	 *		driven by the driver, and so must be left on
-	 *		for a short period to power up the LED so it
-	 *		can be seen.  This delay can be changed by
-	 *		changing the TLAN_TIMER_ACT_DELAY in tlan.h,
-	 *		if desired.  100 ms  produces a slightly
-	 *		sluggish response.
-	 *
-	 **************************************************************/
-
-static void TLan_Timer( unsigned long data )
+/***************************************************************
+ *	tlan_timer
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		data	A value given to add timer when
+ *			add_timer was called.
+ *
+ *	This function handles timed functionality for the
+ *	TLAN driver.  The two current timer uses are for
+ *	delaying for autonegotionation and driving the ACT LED.
+ *	-	Autonegotiation requires being allowed about
+ *		2 1/2 seconds before attempting to transmit a
+ *		packet.  It would be a very bad thing to hang
+ *		the kernel this long, so the driver doesn't
+ *		allow transmission 'til after this time, for
+ *		certain PHYs.  It would be much nicer if all
+ *		PHYs were interrupt-capable like the internal
+ *		PHY.
+ *	-	The ACT LED, which shows adapter activity, is
+ *		driven by the driver, and so must be left on
+ *		for a short period to power up the LED so it
+ *		can be seen.  This delay can be changed by
+ *		changing the TLAN_TIMER_ACT_DELAY in tlan.h,
+ *		if desired.  100 ms  produces a slightly
+ *		sluggish response.
+ *
+ **************************************************************/
+
+static void tlan_timer(unsigned long data)
 {
 	struct net_device	*dev = (struct net_device *) data;
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u32		elapsed;
 	unsigned long	flags = 0;
 
 	priv->timer.function = NULL;
 
-	switch ( priv->timerType ) {
+	switch (priv->timer_type) {
 #ifdef MONITOR
-		case TLAN_TIMER_LINK_BEAT:
-			TLan_PhyMonitor( dev );
-			break;
+	case TLAN_TIMER_LINK_BEAT:
+		tlan_phy_monitor(dev);
+		break;
 #endif
-		case TLAN_TIMER_PHY_PDOWN:
-			TLan_PhyPowerDown( dev );
-			break;
-		case TLAN_TIMER_PHY_PUP:
-			TLan_PhyPowerUp( dev );
-			break;
-		case TLAN_TIMER_PHY_RESET:
-			TLan_PhyReset( dev );
-			break;
-		case TLAN_TIMER_PHY_START_LINK:
-			TLan_PhyStartLink( dev );
-			break;
-		case TLAN_TIMER_PHY_FINISH_AN:
-			TLan_PhyFinishAutoNeg( dev );
-			break;
-		case TLAN_TIMER_FINISH_RESET:
-			TLan_FinishReset( dev );
-			break;
-		case TLAN_TIMER_ACTIVITY:
-			spin_lock_irqsave(&priv->lock, flags);
-			if ( priv->timer.function == NULL ) {
-				elapsed = jiffies - priv->timerSetAt;
-				if ( elapsed >= TLAN_TIMER_ACT_DELAY ) {
-					TLan_DioWrite8( dev->base_addr,
-							TLAN_LED_REG, TLAN_LED_LINK );
-				} else  {
-					priv->timer.function = TLan_Timer;
-					priv->timer.expires = priv->timerSetAt
-						+ TLAN_TIMER_ACT_DELAY;
-					spin_unlock_irqrestore(&priv->lock, flags);
-					add_timer( &priv->timer );
-					break;
-				}
+	case TLAN_TIMER_PHY_PDOWN:
+		tlan_phy_power_down(dev);
+		break;
+	case TLAN_TIMER_PHY_PUP:
+		tlan_phy_power_up(dev);
+		break;
+	case TLAN_TIMER_PHY_RESET:
+		tlan_phy_reset(dev);
+		break;
+	case TLAN_TIMER_PHY_START_LINK:
+		tlan_phy_start_link(dev);
+		break;
+	case TLAN_TIMER_PHY_FINISH_AN:
+		tlan_phy_finish_auto_neg(dev);
+		break;
+	case TLAN_TIMER_FINISH_RESET:
+		tlan_finish_reset(dev);
+		break;
+	case TLAN_TIMER_ACTIVITY:
+		spin_lock_irqsave(&priv->lock, flags);
+		if (priv->timer.function == NULL) {
+			elapsed = jiffies - priv->timer_set_at;
+			if (elapsed >= TLAN_TIMER_ACT_DELAY) {
+				tlan_dio_write8(dev->base_addr,
+						TLAN_LED_REG, TLAN_LED_LINK);
+			} else  {
+				priv->timer.function = tlan_timer;
+				priv->timer.expires = priv->timer_set_at
+					+ TLAN_TIMER_ACT_DELAY;
+				spin_unlock_irqrestore(&priv->lock, flags);
+				add_timer(&priv->timer);
+				break;
 			}
-			spin_unlock_irqrestore(&priv->lock, flags);
-			break;
-		default:
-			break;
+		}
+		spin_unlock_irqrestore(&priv->lock, flags);
+		break;
+	default:
+		break;
 	}
 
-} /* TLan_Timer */
+}
 
 
 
@@ -1919,39 +1862,39 @@ static void TLan_Timer( unsigned long data )
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Adapter Related Routines
+ThunderLAN driver adapter related routines
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_ResetLists
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	The device structure with the list
-	 *			stuctures to be reset.
-	 *
-	 *	This routine sets the variables associated with managing
-	 *	the TLAN lists to their initial values.
-	 *
-	 **************************************************************/
-
-static void TLan_ResetLists( struct net_device *dev )
+/***************************************************************
+ *	tlan_reset_lists
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	The device structure with the list
+ *			stuctures to be reset.
+ *
+ *	This routine sets the variables associated with managing
+ *	the TLAN lists to their initial values.
+ *
+ **************************************************************/
+
+static void tlan_reset_lists(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	int		i;
-	TLanList	*list;
+	struct tlan_list	*list;
 	dma_addr_t	list_phys;
 	struct sk_buff	*skb;
 
-	priv->txHead = 0;
-	priv->txTail = 0;
-	for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
-		list = priv->txList + i;
-		list->cStat = TLAN_CSTAT_UNUSED;
+	priv->tx_head = 0;
+	priv->tx_tail = 0;
+	for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
+		list = priv->tx_list + i;
+		list->c_stat = TLAN_CSTAT_UNUSED;
 		list->buffer[0].address = 0;
 		list->buffer[2].count = 0;
 		list->buffer[2].address = 0;
@@ -1959,169 +1902,169 @@ static void TLan_ResetLists( struct net_device *dev )
 		list->buffer[9].address = 0;
 	}
 
-	priv->rxHead = 0;
-	priv->rxTail = TLAN_NUM_RX_LISTS - 1;
-	for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
-		list = priv->rxList + i;
-		list_phys = priv->rxListDMA + sizeof(TLanList) * i;
-		list->cStat = TLAN_CSTAT_READY;
-		list->frameSize = TLAN_MAX_FRAME_SIZE;
+	priv->rx_head = 0;
+	priv->rx_tail = TLAN_NUM_RX_LISTS - 1;
+	for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
+		list = priv->rx_list + i;
+		list_phys = priv->rx_list_dma + sizeof(struct tlan_list)*i;
+		list->c_stat = TLAN_CSTAT_READY;
+		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 ) {
-			pr_err("TLAN: out of memory for received data.\n" );
+		if (!skb) {
+			netdev_err(dev, "Out of memory for received data\n");
 			break;
 		}
 
-		list->buffer[0].address = pci_map_single(priv->pciDev,
+		list->buffer[0].address = pci_map_single(priv->pci_dev,
 							 skb->data,
 							 TLAN_MAX_FRAME_SIZE,
 							 PCI_DMA_FROMDEVICE);
-		TLan_StoreSKB(list, skb);
+		tlan_store_skb(list, skb);
 		list->buffer[1].count = 0;
 		list->buffer[1].address = 0;
-		list->forward = list_phys + sizeof(TLanList);
+		list->forward = list_phys + sizeof(struct tlan_list);
 	}
 
 	/* in case ran out of memory early, clear bits */
 	while (i < TLAN_NUM_RX_LISTS) {
-		TLan_StoreSKB(priv->rxList + i, NULL);
+		tlan_store_skb(priv->rx_list + i, NULL);
 		++i;
 	}
 	list->forward = 0;
 
-} /* TLan_ResetLists */
+}
 
 
-static void TLan_FreeLists( struct net_device *dev )
+static void tlan_free_lists(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	int		i;
-	TLanList	*list;
+	struct tlan_list	*list;
 	struct sk_buff	*skb;
 
-	for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
-		list = priv->txList + i;
-		skb = TLan_GetSKB(list);
-		if ( skb ) {
+	for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
+		list = priv->tx_list + i;
+		skb = tlan_get_skb(list);
+		if (skb) {
 			pci_unmap_single(
-				priv->pciDev,
+				priv->pci_dev,
 				list->buffer[0].address,
 				max(skb->len,
 				    (unsigned int)TLAN_MIN_FRAME_SIZE),
 				PCI_DMA_TODEVICE);
-			dev_kfree_skb_any( skb );
+			dev_kfree_skb_any(skb);
 			list->buffer[8].address = 0;
 			list->buffer[9].address = 0;
 		}
 	}
 
-	for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
-		list = priv->rxList + i;
-		skb = TLan_GetSKB(list);
-		if ( skb ) {
-			pci_unmap_single(priv->pciDev,
+	for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
+		list = priv->rx_list + i;
+		skb = tlan_get_skb(list);
+		if (skb) {
+			pci_unmap_single(priv->pci_dev,
 					 list->buffer[0].address,
 					 TLAN_MAX_FRAME_SIZE,
 					 PCI_DMA_FROMDEVICE);
-			dev_kfree_skb_any( skb );
+			dev_kfree_skb_any(skb);
 			list->buffer[8].address = 0;
 			list->buffer[9].address = 0;
 		}
 	}
-} /* TLan_FreeLists */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_PrintDio
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		io_base		Base IO port of the device of
-	 *				which to print DIO registers.
-	 *
-	 *	This function prints out all the internal (DIO)
-	 *	registers of a TLAN chip.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_print_dio
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		io_base		Base IO port of the device of
+ *				which to print DIO registers.
+ *
+ *	This function prints out all the internal (DIO)
+ *	registers of a TLAN chip.
+ *
+ **************************************************************/
 
-static void TLan_PrintDio( u16 io_base )
+static void tlan_print_dio(u16 io_base)
 {
 	u32 data0, data1;
 	int	i;
 
-	printk( "TLAN:   Contents of internal registers for io base 0x%04hx.\n",
-		io_base );
-	printk( "TLAN:      Off.  +0         +4\n" );
-	for ( i = 0; i < 0x4C; i+= 8 ) {
-		data0 = TLan_DioRead32( io_base, i );
-		data1 = TLan_DioRead32( io_base, i + 0x4 );
-		printk( "TLAN:      0x%02x  0x%08x 0x%08x\n", i, data0, data1 );
+	pr_info("Contents of internal registers for io base 0x%04hx\n",
+		io_base);
+	pr_info("Off.  +0        +4\n");
+	for (i = 0; i < 0x4C; i += 8) {
+		data0 = tlan_dio_read32(io_base, i);
+		data1 = tlan_dio_read32(io_base, i + 0x4);
+		pr_info("0x%02x  0x%08x 0x%08x\n", i, data0, data1);
 	}
 
-} /* TLan_PrintDio */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_PrintList
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		list	A pointer to the TLanList structure to
-	 *			be printed.
-	 *		type	A string to designate type of list,
-	 *			"Rx" or "Tx".
-	 *		num	The index of the list.
-	 *
-	 *	This function prints out the contents of the list
-	 *	pointed to by the list parameter.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_PrintList
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		list	A pointer to the struct tlan_list structure to
+ *			be printed.
+ *		type	A string to designate type of list,
+ *			"Rx" or "Tx".
+ *		num	The index of the list.
+ *
+ *	This function prints out the contents of the list
+ *	pointed to by the list parameter.
+ *
+ **************************************************************/
 
-static void TLan_PrintList( TLanList *list, char *type, int num)
+static void tlan_print_list(struct tlan_list *list, char *type, int num)
 {
 	int i;
 
-	printk( "TLAN:   %s List %d at %p\n", type, num, list );
-	printk( "TLAN:      Forward    = 0x%08x\n",  list->forward );
-	printk( "TLAN:      CSTAT      = 0x%04hx\n", list->cStat );
-	printk( "TLAN:      Frame Size = 0x%04hx\n", list->frameSize );
-	/* for ( i = 0; i < 10; i++ ) { */
-	for ( i = 0; i < 2; i++ ) {
-		printk( "TLAN:      Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
-			i, list->buffer[i].count, list->buffer[i].address );
+	pr_info("%s List %d at %p\n", type, num, list);
+	pr_info("   Forward    = 0x%08x\n",  list->forward);
+	pr_info("   CSTAT      = 0x%04hx\n", list->c_stat);
+	pr_info("   Frame Size = 0x%04hx\n", list->frame_size);
+	/* for (i = 0; i < 10; i++) { */
+	for (i = 0; i < 2; i++) {
+		pr_info("   Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
+			i, list->buffer[i].count, list->buffer[i].address);
 	}
 
-} /* TLan_PrintList */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_ReadAndClearStats
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	Pointer to device structure of adapter
-	 *			to which to read stats.
-	 *		record	Flag indicating whether to add
-	 *
-	 *	This functions reads all the internal status registers
-	 *	of the TLAN chip, which clears them as a side effect.
-	 *	It then either adds the values to the device's status
-	 *	struct, or discards them, depending on whether record
-	 *	is TLAN_RECORD (!=0)  or TLAN_IGNORE (==0).
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_read_and_clear_stats
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	Pointer to device structure of adapter
+ *			to which to read stats.
+ *		record	Flag indicating whether to add
+ *
+ *	This functions reads all the internal status registers
+ *	of the TLAN chip, which clears them as a side effect.
+ *	It then either adds the values to the device's status
+ *	struct, or discards them, depending on whether record
+ *	is TLAN_RECORD (!=0)  or TLAN_IGNORE (==0).
+ *
+ **************************************************************/
 
-static void TLan_ReadAndClearStats( struct net_device *dev, int record )
+static void tlan_read_and_clear_stats(struct net_device *dev, int record)
 {
 	u32		tx_good, tx_under;
 	u32		rx_good, rx_over;
@@ -2129,41 +2072,42 @@ static void TLan_ReadAndClearStats( struct net_device *dev, int record )
 	u32		multi_col, single_col;
 	u32		excess_col, late_col, loss;
 
-	outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	tx_good  = inb( dev->base_addr + TLAN_DIO_DATA );
-	tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
-	tx_under = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
-
-	outw( TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	rx_good  = inb( dev->base_addr + TLAN_DIO_DATA );
-	rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
-	rx_over  = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
-
-	outw( TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR );
-	def_tx  = inb( dev->base_addr + TLAN_DIO_DATA );
-	def_tx += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	crc     = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
-	code    = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
-
-	outw( TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	multi_col   = inb( dev->base_addr + TLAN_DIO_DATA );
-	multi_col  += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	single_col  = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
-	single_col += inb( dev->base_addr + TLAN_DIO_DATA + 3 ) << 8;
-
-	outw( TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	excess_col = inb( dev->base_addr + TLAN_DIO_DATA );
-	late_col   = inb( dev->base_addr + TLAN_DIO_DATA + 1 );
-	loss       = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
-
-	if ( record ) {
+	outw(TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	tx_good  = inb(dev->base_addr + TLAN_DIO_DATA);
+	tx_good += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	tx_good += inb(dev->base_addr + TLAN_DIO_DATA + 2) << 16;
+	tx_under = inb(dev->base_addr + TLAN_DIO_DATA + 3);
+
+	outw(TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	rx_good  = inb(dev->base_addr + TLAN_DIO_DATA);
+	rx_good += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	rx_good += inb(dev->base_addr + TLAN_DIO_DATA + 2) << 16;
+	rx_over  = inb(dev->base_addr + TLAN_DIO_DATA + 3);
+
+	outw(TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR);
+	def_tx  = inb(dev->base_addr + TLAN_DIO_DATA);
+	def_tx += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	crc     = inb(dev->base_addr + TLAN_DIO_DATA + 2);
+	code    = inb(dev->base_addr + TLAN_DIO_DATA + 3);
+
+	outw(TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	multi_col   = inb(dev->base_addr + TLAN_DIO_DATA);
+	multi_col  += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	single_col  = inb(dev->base_addr + TLAN_DIO_DATA + 2);
+	single_col += inb(dev->base_addr + TLAN_DIO_DATA + 3) << 8;
+
+	outw(TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	excess_col = inb(dev->base_addr + TLAN_DIO_DATA);
+	late_col   = inb(dev->base_addr + TLAN_DIO_DATA + 1);
+	loss       = inb(dev->base_addr + TLAN_DIO_DATA + 2);
+
+	if (record) {
 		dev->stats.rx_packets += rx_good;
 		dev->stats.rx_errors  += rx_over + crc + code;
 		dev->stats.tx_packets += tx_good;
 		dev->stats.tx_errors  += tx_under + loss;
-		dev->stats.collisions += multi_col + single_col + excess_col + late_col;
+		dev->stats.collisions += multi_col
+			+ single_col + excess_col + late_col;
 
 		dev->stats.rx_over_errors    += rx_over;
 		dev->stats.rx_crc_errors     += crc;
@@ -2173,39 +2117,39 @@ static void TLan_ReadAndClearStats( struct net_device *dev, int record )
 		dev->stats.tx_carrier_errors += loss;
 	}
 
-} /* TLan_ReadAndClearStats */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_Reset
-	 *
-	 *	Returns:
-	 *		0
-	 *	Parms:
-	 *		dev	Pointer to device structure of adapter
-	 *			to be reset.
-	 *
-	 *	This function resets the adapter and it's physical
-	 *	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN
-	 *	Programmer's Guide" for details.  The routine tries to
-	 *	implement what is detailed there, though adjustments
-	 *	have been made.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_Reset
+ *
+ *	Returns:
+ *		0
+ *	Parms:
+ *		dev	Pointer to device structure of adapter
+ *			to be reset.
+ *
+ *	This function resets the adapter and it's physical
+ *	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN
+ *	Programmer's Guide" for details.  The routine tries to
+ *	implement what is detailed there, though adjustments
+ *	have been made.
+ *
+ **************************************************************/
 
 static void
-TLan_ResetAdapter( struct net_device *dev )
+tlan_reset_adapter(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int		i;
 	u32		addr;
 	u32		data;
 	u8		data8;
 
-	priv->tlanFullDuplex = false;
-	priv->phyOnline=0;
+	priv->tlan_full_duplex = false;
+	priv->phy_online = 0;
 	netif_carrier_off(dev);
 
 /*  1.	Assert reset bit. */
@@ -2216,7 +2160,7 @@ TLan_ResetAdapter( struct net_device *dev )
 
 	udelay(1000);
 
-/*  2.	Turn off interrupts. ( Probably isn't necessary ) */
+/*  2.	Turn off interrupts. (Probably isn't necessary) */
 
 	data = inl(dev->base_addr + TLAN_HOST_CMD);
 	data |= TLAN_HC_INT_OFF;
@@ -2224,207 +2168,204 @@ TLan_ResetAdapter( struct net_device *dev )
 
 /*  3.	Clear AREGs and HASHs. */
 
- 	for ( i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4 ) {
-		TLan_DioWrite32( dev->base_addr, (u16) i, 0 );
-	}
+	for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4)
+		tlan_dio_write32(dev->base_addr, (u16) i, 0);
 
 /*  4.	Setup NetConfig register. */
 
 	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
-	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
+	tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
 
 /*  5.	Load Ld_Tmr and Ld_Thr in HOST_CMD. */
 
- 	outl( TLAN_HC_LD_TMR | 0x3f, dev->base_addr + TLAN_HOST_CMD );
- 	outl( TLAN_HC_LD_THR | 0x9, dev->base_addr + TLAN_HOST_CMD );
+	outl(TLAN_HC_LD_TMR | 0x3f, dev->base_addr + TLAN_HOST_CMD);
+	outl(TLAN_HC_LD_THR | 0x9, dev->base_addr + TLAN_HOST_CMD);
 
 /*  6.	Unreset the MII by setting NMRST (in NetSio) to 1. */
 
-	outw( TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
 	addr = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
-	TLan_SetBit( TLAN_NET_SIO_NMRST, addr );
+	tlan_set_bit(TLAN_NET_SIO_NMRST, addr);
 
 /*  7.	Setup the remaining registers. */
 
-	if ( priv->tlanRev >= 0x30 ) {
+	if (priv->tlan_rev >= 0x30) {
 		data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
-		TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 );
+		tlan_dio_write8(dev->base_addr, TLAN_INT_DIS, data8);
 	}
-	TLan_PhyDetect( dev );
+	tlan_phy_detect(dev);
 	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) {
+	if (priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY) {
 		data |= TLAN_NET_CFG_BIT;
-		if ( priv->aui == 1 ) {
-			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a );
-		} else if ( priv->duplex == TLAN_DUPLEX_FULL ) {
-			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 );
-			priv->tlanFullDuplex = true;
+		if (priv->aui == 1) {
+			tlan_dio_write8(dev->base_addr, TLAN_ACOMMIT, 0x0a);
+		} else if (priv->duplex == TLAN_DUPLEX_FULL) {
+			tlan_dio_write8(dev->base_addr, TLAN_ACOMMIT, 0x00);
+			priv->tlan_full_duplex = true;
 		} else {
-			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 );
+			tlan_dio_write8(dev->base_addr, TLAN_ACOMMIT, 0x08);
 		}
 	}
 
-	if ( priv->phyNum == 0 ) {
+	if (priv->phy_num == 0)
 		data |= TLAN_NET_CFG_PHY_EN;
-	}
-	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
+	tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
-		TLan_FinishReset( dev );
-	} else {
-		TLan_PhyPowerDown( dev );
-	}
+	if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY)
+		tlan_finish_reset(dev);
+	else
+		tlan_phy_power_down(dev);
 
-} /* TLan_ResetAdapter */
+}
 
 
 
 
 static void
-TLan_FinishReset( struct net_device *dev )
+tlan_finish_reset(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u8		data;
 	u32		phy;
 	u8		sio;
 	u16		status;
 	u16		partner;
 	u16		tlphy_ctl;
-	u16 		tlphy_par;
+	u16		tlphy_par;
 	u16		tlphy_id1, tlphy_id2;
-	int 		i;
+	int		i;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
 	data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
-	if ( priv->tlanFullDuplex ) {
+	if (priv->tlan_full_duplex)
 		data |= TLAN_NET_CMD_DUPLEX;
-	}
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data );
+	tlan_dio_write8(dev->base_addr, TLAN_NET_CMD, data);
 	data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
-	if ( priv->phyNum == 0 ) {
+	if (priv->phy_num == 0)
 		data |= TLAN_NET_MASK_MASK7;
-	}
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data );
-	TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, ((1536)+7)&~7 );
-	TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &tlphy_id1 );
-	TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &tlphy_id2 );
+	tlan_dio_write8(dev->base_addr, TLAN_NET_MASK, data);
+	tlan_dio_write16(dev->base_addr, TLAN_MAX_RX, ((1536)+7)&~7);
+	tlan_mii_read_reg(dev, phy, MII_GEN_ID_HI, &tlphy_id1);
+	tlan_mii_read_reg(dev, phy, MII_GEN_ID_LO, &tlphy_id2);
 
-	if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) ||
-	     ( priv->aui ) ) {
+	if ((priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY) ||
+	    (priv->aui)) {
 		status = MII_GS_LINK;
-		printk( "TLAN:  %s: Link forced.\n", dev->name );
+		netdev_info(dev, "Link forced\n");
 	} else {
-		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-		udelay( 1000 );
-		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-		if ( (status & MII_GS_LINK) &&
-		     /* We only support link info on Nat.Sem. PHY's */
-			(tlphy_id1 == NAT_SEM_ID1) &&
-			(tlphy_id2 == NAT_SEM_ID2) ) {
-			TLan_MiiReadReg( dev, phy, MII_AN_LPA, &partner );
-			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_PAR, &tlphy_par );
-
-			printk( "TLAN: %s: Link active with ", dev->name );
-			if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
-			      	 printk( "forced 10%sMbps %s-Duplex\n",
-					 tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
-					 tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
-			} else {
-				printk( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
-					tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
-					tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
-				printk("TLAN: Partner capability: ");
-					for (i = 5; i <= 10; i++)
-						if (partner & (1<<i))
-							printk("%s",media[i-5]);
-				printk("\n");
+		tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+		udelay(1000);
+		tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+		if ((status & MII_GS_LINK) &&
+		    /* We only support link info on Nat.Sem. PHY's */
+		    (tlphy_id1 == NAT_SEM_ID1) &&
+		    (tlphy_id2 == NAT_SEM_ID2)) {
+			tlan_mii_read_reg(dev, phy, MII_AN_LPA, &partner);
+			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR, &tlphy_par);
+
+			netdev_info(dev,
+				    "Link active with %s %uMbps %s-Duplex\n",
+				    !(tlphy_par & TLAN_PHY_AN_EN_STAT)
+				    ? "forced" : "Autonegotiation enabled,",
+				    tlphy_par & TLAN_PHY_SPEED_100
+				    ? 100 : 10,
+				    tlphy_par & TLAN_PHY_DUPLEX_FULL
+				    ? "Full" : "Half");
+
+			if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
+				netdev_info(dev, "Partner capability:");
+				for (i = 5; i < 10; i++)
+					if (partner & (1 << i))
+						pr_cont(" %s", media[i-5]);
+				pr_cont("\n");
 			}
 
-			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
+			tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
+					TLAN_LED_LINK);
 #ifdef MONITOR
 			/* We have link beat..for now anyway */
-	        	priv->link = 1;
-	        	/*Enabling link beat monitoring */
-			TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_LINK_BEAT );
+			priv->link = 1;
+			/*Enabling link beat monitoring */
+			tlan_set_timer(dev, (10*HZ), TLAN_TIMER_LINK_BEAT);
 #endif
 		} else if (status & MII_GS_LINK)  {
-			printk( "TLAN: %s: Link active\n", dev->name );
-			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
+			netdev_info(dev, "Link active\n");
+			tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
+					TLAN_LED_LINK);
 		}
 	}
 
-	if ( priv->phyNum == 0 ) {
-        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
-        	tlphy_ctl |= TLAN_TC_INTEN;
-        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl );
-        	sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
-        	sio |= TLAN_NET_SIO_MINTEN;
-        	TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
-	}
-
-	if ( status & MII_GS_LINK ) {
-		TLan_SetMac( dev, 0, dev->dev_addr );
-		priv->phyOnline = 1;
-		outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
-		if ( debug >= 1 && debug != TLAN_DEBUG_PROBE ) {
-			outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
-		}
-		outl( priv->rxListDMA, dev->base_addr + TLAN_CH_PARM );
-		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
+	if (priv->phy_num == 0) {
+		tlan_mii_read_reg(dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
+		tlphy_ctl |= TLAN_TC_INTEN;
+		tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
+		sio = tlan_dio_read8(dev->base_addr, TLAN_NET_SIO);
+		sio |= TLAN_NET_SIO_MINTEN;
+		tlan_dio_write8(dev->base_addr, TLAN_NET_SIO, sio);
+	}
+
+	if (status & MII_GS_LINK) {
+		tlan_set_mac(dev, 0, dev->dev_addr);
+		priv->phy_online = 1;
+		outb((TLAN_HC_INT_ON >> 8), dev->base_addr + TLAN_HOST_CMD + 1);
+		if (debug >= 1 && debug != TLAN_DEBUG_PROBE)
+			outb((TLAN_HC_REQ_INT >> 8),
+			     dev->base_addr + TLAN_HOST_CMD + 1);
+		outl(priv->rx_list_dma, dev->base_addr + TLAN_CH_PARM);
+		outl(TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD);
 		netif_carrier_on(dev);
 	} else {
-		printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
-			dev->name );
-		TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
+		netdev_info(dev, "Link inactive, will retry in 10 secs...\n");
+		tlan_set_timer(dev, (10*HZ), TLAN_TIMER_FINISH_RESET);
 		return;
 	}
-	TLan_SetMulticastList(dev);
+	tlan_set_multicast_list(dev);
 
-} /* TLan_FinishReset */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_SetMac
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	Pointer to device structure of adapter
-	 *			on which to change the AREG.
-	 *		areg	The AREG to set the address in (0 - 3).
-	 *		mac	A pointer to an array of chars.  Each
-	 *			element stores one byte of the address.
-	 *			IE, it isn't in ascii.
-	 *
-	 *	This function transfers a MAC address to one of the
-	 *	TLAN AREGs (address registers).  The TLAN chip locks
-	 *	the register on writing to offset 0 and unlocks the
-	 *	register after writing to offset 5.  If NULL is passed
-	 *	in mac, then the AREG is filled with 0's.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_set_mac
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	Pointer to device structure of adapter
+ *			on which to change the AREG.
+ *		areg	The AREG to set the address in (0 - 3).
+ *		mac	A pointer to an array of chars.  Each
+ *			element stores one byte of the address.
+ *			IE, it isn't in ascii.
+ *
+ *	This function transfers a MAC address to one of the
+ *	TLAN AREGs (address registers).  The TLAN chip locks
+ *	the register on writing to offset 0 and unlocks the
+ *	register after writing to offset 5.  If NULL is passed
+ *	in mac, then the AREG is filled with 0's.
+ *
+ **************************************************************/
 
-static void TLan_SetMac( struct net_device *dev, int areg, char *mac )
+static void tlan_set_mac(struct net_device *dev, int areg, char *mac)
 {
 	int i;
 
 	areg *= 6;
 
-	if ( mac != NULL ) {
-		for ( i = 0; i < 6; i++ )
-			TLan_DioWrite8( dev->base_addr,
-					TLAN_AREG_0 + areg + i, mac[i] );
+	if (mac != NULL) {
+		for (i = 0; i < 6; i++)
+			tlan_dio_write8(dev->base_addr,
+					TLAN_AREG_0 + areg + i, mac[i]);
 	} else {
-		for ( i = 0; i < 6; i++ )
-			TLan_DioWrite8( dev->base_addr,
-					TLAN_AREG_0 + areg + i, 0 );
+		for (i = 0; i < 6; i++)
+			tlan_dio_write8(dev->base_addr,
+					TLAN_AREG_0 + areg + i, 0);
 	}
 
-} /* TLan_SetMac */
+}
 
 
 
@@ -2432,205 +2373,199 @@ static void TLan_SetMac( struct net_device *dev, int areg, char *mac )
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver PHY Layer Routines
+ThunderLAN driver PHY layer routines
 
 ******************************************************************************
 *****************************************************************************/
 
 
 
-	/*********************************************************************
-	 *	TLan_PhyPrint
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to the device structure of the
-	 *			TLAN device having the PHYs to be detailed.
-	 *
-	 *	This function prints the registers a PHY (aka transceiver).
-	 *
-	 ********************************************************************/
+/*********************************************************************
+ *	tlan_phy_print
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	A pointer to the device structure of the
+ *			TLAN device having the PHYs to be detailed.
+ *
+ *	This function prints the registers a PHY (aka transceiver).
+ *
+ ********************************************************************/
 
-static void TLan_PhyPrint( struct net_device *dev )
+static void tlan_phy_print(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16 i, data0, data1, data2, data3, phy;
 
-	phy = priv->phy[priv->phyNum];
-
-	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
-		printk( "TLAN:   Device %s, Unmanaged PHY.\n", dev->name );
-	} else if ( phy <= TLAN_PHY_MAX_ADDR ) {
-		printk( "TLAN:   Device %s, PHY 0x%02x.\n", dev->name, phy );
-		printk( "TLAN:      Off.  +0     +1     +2     +3\n" );
-                for ( i = 0; i < 0x20; i+= 4 ) {
-			printk( "TLAN:      0x%02x", i );
-			TLan_MiiReadReg( dev, phy, i, &data0 );
-			printk( " 0x%04hx", data0 );
-			TLan_MiiReadReg( dev, phy, i + 1, &data1 );
-			printk( " 0x%04hx", data1 );
-			TLan_MiiReadReg( dev, phy, i + 2, &data2 );
-			printk( " 0x%04hx", data2 );
-			TLan_MiiReadReg( dev, phy, i + 3, &data3 );
-			printk( " 0x%04hx\n", data3 );
+	phy = priv->phy[priv->phy_num];
+
+	if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+		netdev_info(dev, "Unmanaged PHY\n");
+	} else if (phy <= TLAN_PHY_MAX_ADDR) {
+		netdev_info(dev, "PHY 0x%02x\n", phy);
+		pr_info("   Off.  +0     +1     +2     +3\n");
+		for (i = 0; i < 0x20; i += 4) {
+			tlan_mii_read_reg(dev, phy, i, &data0);
+			tlan_mii_read_reg(dev, phy, i + 1, &data1);
+			tlan_mii_read_reg(dev, phy, i + 2, &data2);
+			tlan_mii_read_reg(dev, phy, i + 3, &data3);
+			pr_info("   0x%02x 0x%04hx 0x%04hx 0x%04hx 0x%04hx\n",
+				i, data0, data1, data2, data3);
 		}
 	} else {
-		printk( "TLAN:   Device %s, Invalid PHY.\n", dev->name );
+		netdev_info(dev, "Invalid PHY\n");
 	}
 
-} /* TLan_PhyPrint */
+}
 
 
 
 
-	/*********************************************************************
-	 *	TLan_PhyDetect
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to the device structure of the adapter
-	 *			for which the PHY needs determined.
-	 *
-	 *	So far I've found that adapters which have external PHYs
-	 *	may also use the internal PHY for part of the functionality.
-	 *	(eg, AUI/Thinnet).  This function finds out if this TLAN
-	 *	chip has an internal PHY, and then finds the first external
-	 *	PHY (starting from address 0) if it exists).
-	 *
-	 ********************************************************************/
+/*********************************************************************
+ *	tlan_phy_detect
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	A pointer to the device structure of the adapter
+ *			for which the PHY needs determined.
+ *
+ *	So far I've found that adapters which have external PHYs
+ *	may also use the internal PHY for part of the functionality.
+ *	(eg, AUI/Thinnet).  This function finds out if this TLAN
+ *	chip has an internal PHY, and then finds the first external
+ *	PHY (starting from address 0) if it exists).
+ *
+ ********************************************************************/
 
-static void TLan_PhyDetect( struct net_device *dev )
+static void tlan_phy_detect(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16		control;
 	u16		hi;
 	u16		lo;
 	u32		phy;
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
-		priv->phyNum = 0xFFFF;
+	if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+		priv->phy_num = 0xffff;
 		return;
 	}
 
-	TLan_MiiReadReg( dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi );
+	tlan_mii_read_reg(dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi);
 
-	if ( hi != 0xFFFF ) {
+	if (hi != 0xffff)
 		priv->phy[0] = TLAN_PHY_MAX_ADDR;
-	} else {
+	else
 		priv->phy[0] = TLAN_PHY_NONE;
-	}
 
 	priv->phy[1] = TLAN_PHY_NONE;
-	for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) {
-		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &control );
-		TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );
-		TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );
-		if ( ( control != 0xFFFF ) ||
-		     ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {
-			TLAN_DBG( TLAN_DEBUG_GNRL,
-				  "PHY found at %02x %04x %04x %04x\n",
-				  phy, control, hi, lo );
-			if ( ( priv->phy[1] == TLAN_PHY_NONE ) &&
-			     ( phy != TLAN_PHY_MAX_ADDR ) ) {
+	for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {
+		tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &control);
+		tlan_mii_read_reg(dev, phy, MII_GEN_ID_HI, &hi);
+		tlan_mii_read_reg(dev, phy, MII_GEN_ID_LO, &lo);
+		if ((control != 0xffff) ||
+		    (hi != 0xffff) || (lo != 0xffff)) {
+			TLAN_DBG(TLAN_DEBUG_GNRL,
+				 "PHY found at %02x %04x %04x %04x\n",
+				 phy, control, hi, lo);
+			if ((priv->phy[1] == TLAN_PHY_NONE) &&
+			    (phy != TLAN_PHY_MAX_ADDR)) {
 				priv->phy[1] = phy;
 			}
 		}
 	}
 
-	if ( priv->phy[1] != TLAN_PHY_NONE ) {
-		priv->phyNum = 1;
-	} else if ( priv->phy[0] != TLAN_PHY_NONE ) {
-		priv->phyNum = 0;
-	} else {
-		printk( "TLAN:  Cannot initialize device, no PHY was found!\n" );
-	}
+	if (priv->phy[1] != TLAN_PHY_NONE)
+		priv->phy_num = 1;
+	else if (priv->phy[0] != TLAN_PHY_NONE)
+		priv->phy_num = 0;
+	else
+		netdev_info(dev, "Cannot initialize device, no PHY was found!\n");
 
-} /* TLan_PhyDetect */
+}
 
 
 
 
-static void TLan_PhyPowerDown( struct net_device *dev )
+static void tlan_phy_power_down(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		value;
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name);
 	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
-	TLan_MiiSync( dev->base_addr );
-	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
-	if ( ( priv->phyNum == 0 ) &&
-	     ( priv->phy[1] != TLAN_PHY_NONE ) &&
-	     ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) {
-		TLan_MiiSync( dev->base_addr );
-		TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
+	tlan_mii_sync(dev->base_addr);
+	tlan_mii_write_reg(dev, priv->phy[priv->phy_num], MII_GEN_CTL, value);
+	if ((priv->phy_num == 0) &&
+	    (priv->phy[1] != TLAN_PHY_NONE) &&
+	    (!(priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))) {
+		tlan_mii_sync(dev->base_addr);
+		tlan_mii_write_reg(dev, priv->phy[1], MII_GEN_CTL, value);
 	}
 
 	/* Wait for 50 ms and powerup
 	 * This is abitrary.  It is intended to make sure the
 	 * transceiver settles.
 	 */
-	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP );
+	tlan_set_timer(dev, (HZ/20), TLAN_TIMER_PHY_PUP);
 
-} /* TLan_PhyPowerDown */
+}
 
 
 
 
-static void TLan_PhyPowerUp( struct net_device *dev )
+static void tlan_phy_power_up(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		value;
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name );
-	TLan_MiiSync( dev->base_addr );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name);
+	tlan_mii_sync(dev->base_addr);
 	value = MII_GC_LOOPBK;
-	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
-	TLan_MiiSync(dev->base_addr);
+	tlan_mii_write_reg(dev, priv->phy[priv->phy_num], MII_GEN_CTL, value);
+	tlan_mii_sync(dev->base_addr);
 	/* Wait for 500 ms and reset the
 	 * transceiver.  The TLAN docs say both 50 ms and
 	 * 500 ms, so do the longer, just in case.
 	 */
-	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET );
+	tlan_set_timer(dev, (HZ/20), TLAN_TIMER_PHY_RESET);
 
-} /* TLan_PhyPowerUp */
+}
 
 
 
 
-static void TLan_PhyReset( struct net_device *dev )
+static void tlan_phy_reset(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		phy;
 	u16		value;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name );
-	TLan_MiiSync( dev->base_addr );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name);
+	tlan_mii_sync(dev->base_addr);
 	value = MII_GC_LOOPBK | MII_GC_RESET;
-	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );
-	TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
-	while ( value & MII_GC_RESET ) {
-		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
-	}
+	tlan_mii_write_reg(dev, phy, MII_GEN_CTL, value);
+	tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
+	while (value & MII_GC_RESET)
+		tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
 
 	/* Wait for 500 ms and initialize.
 	 * I don't remember why I wait this long.
 	 * I've changed this to 50ms, as it seems long enough.
 	 */
-	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK );
+	tlan_set_timer(dev, (HZ/20), TLAN_TIMER_PHY_START_LINK);
 
-} /* TLan_PhyReset */
+}
 
 
 
 
-static void TLan_PhyStartLink( struct net_device *dev )
+static void tlan_phy_start_link(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		ability;
 	u16		control;
 	u16		data;
@@ -2638,86 +2573,87 @@ static void TLan_PhyStartLink( struct net_device *dev )
 	u16		status;
 	u16		tctl;
 
-	phy = priv->phy[priv->phyNum];
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name );
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &ability );
+	phy = priv->phy[priv->phy_num];
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name);
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &ability);
 
-	if ( ( status & MII_GS_AUTONEG ) &&
-	     ( ! priv->aui ) ) {
+	if ((status & MII_GS_AUTONEG) &&
+	    (!priv->aui)) {
 		ability = status >> 11;
-		if ( priv->speed  == TLAN_SPEED_10 &&
-		     priv->duplex == TLAN_DUPLEX_HALF) {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0000);
-		} else if ( priv->speed == TLAN_SPEED_10 &&
-			    priv->duplex == TLAN_DUPLEX_FULL) {
-			priv->tlanFullDuplex = true;
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100);
-		} else if ( priv->speed == TLAN_SPEED_100 &&
-			    priv->duplex == TLAN_DUPLEX_HALF) {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000);
-		} else if ( priv->speed == TLAN_SPEED_100 &&
-			    priv->duplex == TLAN_DUPLEX_FULL) {
-			priv->tlanFullDuplex = true;
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100);
+		if (priv->speed  == TLAN_SPEED_10 &&
+		    priv->duplex == TLAN_DUPLEX_HALF) {
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x0000);
+		} else if (priv->speed == TLAN_SPEED_10 &&
+			   priv->duplex == TLAN_DUPLEX_FULL) {
+			priv->tlan_full_duplex = true;
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x0100);
+		} else if (priv->speed == TLAN_SPEED_100 &&
+			   priv->duplex == TLAN_DUPLEX_HALF) {
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x2000);
+		} else if (priv->speed == TLAN_SPEED_100 &&
+			   priv->duplex == TLAN_DUPLEX_FULL) {
+			priv->tlan_full_duplex = true;
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x2100);
 		} else {
 
 			/* Set Auto-Neg advertisement */
-			TLan_MiiWriteReg( dev, phy, MII_AN_ADV, (ability << 5) | 1);
+			tlan_mii_write_reg(dev, phy, MII_AN_ADV,
+					   (ability << 5) | 1);
 			/* Enablee Auto-Neg */
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x1000);
 			/* Restart Auto-Neg */
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x1200);
 			/* Wait for 4 sec for autonegotiation
-		 	* to complete.  The max spec time is less than this
-		 	* but the card need additional time to start AN.
-		 	* .5 sec should be plenty extra.
-		 	*/
-			printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );
-			TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN );
+			 * to complete.  The max spec time is less than this
+			 * but the card need additional time to start AN.
+			 * .5 sec should be plenty extra.
+			 */
+			netdev_info(dev, "Starting autonegotiation\n");
+			tlan_set_timer(dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN);
 			return;
 		}
 
 	}
 
-	if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) {
-		priv->phyNum = 0;
-		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
-		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN );
+	if ((priv->aui) && (priv->phy_num != 0)) {
+		priv->phy_num = 0;
+		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN
+			| TLAN_NET_CFG_PHY_EN;
+		tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, data);
+		tlan_set_timer(dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN);
 		return;
-	}  else if ( priv->phyNum == 0 ) {
+	} else if (priv->phy_num == 0) {
 		control = 0;
-        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
-		if ( priv->aui ) {
-                	tctl |= TLAN_TC_AUISEL;
+		tlan_mii_read_reg(dev, phy, TLAN_TLPHY_CTL, &tctl);
+		if (priv->aui) {
+			tctl |= TLAN_TC_AUISEL;
 		} else {
-                	tctl &= ~TLAN_TC_AUISEL;
-			if ( priv->duplex == TLAN_DUPLEX_FULL ) {
+			tctl &= ~TLAN_TC_AUISEL;
+			if (priv->duplex == TLAN_DUPLEX_FULL) {
 				control |= MII_GC_DUPLEX;
-				priv->tlanFullDuplex = true;
+				priv->tlan_full_duplex = true;
 			}
-			if ( priv->speed == TLAN_SPEED_100 ) {
+			if (priv->speed == TLAN_SPEED_100)
 				control |= MII_GC_SPEEDSEL;
-			}
 		}
-		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
-        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
+		tlan_mii_write_reg(dev, phy, MII_GEN_CTL, control);
+		tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL, tctl);
 	}
 
 	/* Wait for 2 sec to give the transceiver time
 	 * to establish link.
 	 */
-	TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET );
+	tlan_set_timer(dev, (4*HZ), TLAN_TIMER_FINISH_RESET);
 
-} /* TLan_PhyStartLink */
+}
 
 
 
 
-static void TLan_PhyFinishAutoNeg( struct net_device *dev )
+static void tlan_phy_finish_auto_neg(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		an_adv;
 	u16		an_lpa;
 	u16		data;
@@ -2725,115 +2661,118 @@ static void TLan_PhyFinishAutoNeg( struct net_device *dev )
 	u16		phy;
 	u16		status;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-	udelay( 1000 );
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+	udelay(1000);
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
 
-	if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
+	if (!(status & MII_GS_AUTOCMPLT)) {
 		/* Wait for 8 sec to give the process
 		 * more time.  Perhaps we should fail after a while.
 		 */
-		 if (!priv->neg_be_verbose++) {
-			 pr_info("TLAN:  Giving autonegotiation more time.\n");
-		 	 pr_info("TLAN:  Please check that your adapter has\n");
-		 	 pr_info("TLAN:  been properly connected to a HUB or Switch.\n");
-			 pr_info("TLAN:  Trying to establish link in the background...\n");
-		 }
-		TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
+		if (!priv->neg_be_verbose++) {
+			pr_info("Giving autonegotiation more time.\n");
+			pr_info("Please check that your adapter has\n");
+			pr_info("been properly connected to a HUB or Switch.\n");
+			pr_info("Trying to establish link in the background...\n");
+		}
+		tlan_set_timer(dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN);
 		return;
 	}
 
-	printk( "TLAN: %s: Autonegotiation complete.\n", dev->name );
-	TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );
-	TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );
+	netdev_info(dev, "Autonegotiation complete\n");
+	tlan_mii_read_reg(dev, phy, MII_AN_ADV, &an_adv);
+	tlan_mii_read_reg(dev, phy, MII_AN_LPA, &an_lpa);
 	mode = an_adv & an_lpa & 0x03E0;
-	if ( mode & 0x0100 ) {
-		priv->tlanFullDuplex = true;
-	} else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) {
-		priv->tlanFullDuplex = true;
-	}
-
-	if ( ( ! ( mode & 0x0180 ) ) &&
-	     ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) &&
-	     ( priv->phyNum != 0 ) ) {
-		priv->phyNum = 0;
-		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
-		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN );
+	if (mode & 0x0100)
+		priv->tlan_full_duplex = true;
+	else if (!(mode & 0x0080) && (mode & 0x0040))
+		priv->tlan_full_duplex = true;
+
+	if ((!(mode & 0x0180)) &&
+	    (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10) &&
+	    (priv->phy_num != 0)) {
+		priv->phy_num = 0;
+		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN
+			| TLAN_NET_CFG_PHY_EN;
+		tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, data);
+		tlan_set_timer(dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN);
 		return;
 	}
 
-	if ( priv->phyNum == 0 ) {
-		if ( ( priv->duplex == TLAN_DUPLEX_FULL ) ||
-		     ( an_adv & an_lpa & 0x0040 ) ) {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL,
-					  MII_GC_AUTOENB | MII_GC_DUPLEX );
-			pr_info("TLAN:  Starting internal PHY with FULL-DUPLEX\n" );
+	if (priv->phy_num == 0) {
+		if ((priv->duplex == TLAN_DUPLEX_FULL) ||
+		    (an_adv & an_lpa & 0x0040)) {
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL,
+					   MII_GC_AUTOENB | MII_GC_DUPLEX);
+			netdev_info(dev, "Starting internal PHY with FULL-DUPLEX\n");
 		} else {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB );
-			pr_info( "TLAN:  Starting internal PHY with HALF-DUPLEX\n" );
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL,
+					   MII_GC_AUTOENB);
+			netdev_info(dev, "Starting internal PHY with HALF-DUPLEX\n");
 		}
 	}
 
 	/* Wait for 100 ms.  No reason in partiticular.
 	 */
-	TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET );
+	tlan_set_timer(dev, (HZ/10), TLAN_TIMER_FINISH_RESET);
 
-} /* TLan_PhyFinishAutoNeg */
+}
 
 #ifdef MONITOR
 
-        /*********************************************************************
-        *
-        *      TLan_phyMonitor
-        *
-        *      Returns:
-        *              None
-        *
-        *      Params:
-        *              dev             The device structure of this device.
-        *
-        *
-        *      This function monitors PHY condition by reading the status
-        *      register via the MII bus. This can be used to give info
-        *      about link changes (up/down), and possible switch to alternate
-        *      media.
-        *
-        * ******************************************************************/
-
-void TLan_PhyMonitor( struct net_device *dev )
+/*********************************************************************
+ *
+ *     tlan_phy_monitor
+ *
+ *     Returns:
+ *	      None
+ *
+ *     Params:
+ *	      dev	     The device structure of this device.
+ *
+ *
+ *     This function monitors PHY condition by reading the status
+ *     register via the MII bus. This can be used to give info
+ *     about link changes (up/down), and possible switch to alternate
+ *     media.
+ *
+ *******************************************************************/
+
+void tlan_phy_monitor(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16     phy;
 	u16     phy_status;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-        /* Get PHY status register */
-        TLan_MiiReadReg( dev, phy, MII_GEN_STS, &phy_status );
+	/* Get PHY status register */
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &phy_status);
 
-        /* Check if link has been lost */
-        if (!(phy_status & MII_GS_LINK)) {
- 	       if (priv->link) {
-		      priv->link = 0;
-	              printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
-		      netif_carrier_off(dev);
-		      TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
-		      return;
+	/* Check if link has been lost */
+	if (!(phy_status & MII_GS_LINK)) {
+		if (priv->link) {
+			priv->link = 0;
+			printk(KERN_DEBUG "TLAN: %s has lost link\n",
+			       dev->name);
+			netif_carrier_off(dev);
+			tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
+			return;
 		}
 	}
 
-        /* Link restablished? */
-        if ((phy_status & MII_GS_LINK) && !priv->link) {
- 		priv->link = 1;
-        	printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
+	/* Link restablished? */
+	if ((phy_status & MII_GS_LINK) && !priv->link) {
+		priv->link = 1;
+		printk(KERN_DEBUG "TLAN: %s has reestablished link\n",
+		       dev->name);
 		netif_carrier_on(dev);
-        }
+	}
 
 	/* Setup a new monitor */
-	TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
+	tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
 }
 
 #endif /* MONITOR */
@@ -2842,47 +2781,48 @@ void TLan_PhyMonitor( struct net_device *dev )
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver MII Routines
+ThunderLAN driver MII routines
 
-	These routines are based on the information in Chap. 2 of the
-	"ThunderLAN Programmer's Guide", pp. 15-24.
+these routines are based on the information in chap. 2 of the
+"ThunderLAN Programmer's Guide", pp. 15-24.
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_MiiReadReg
-	 *
-	 *	Returns:
-	 *		false	if ack received ok
-	 *		true	if no ack received or other error
-	 *
-	 *	Parms:
-	 *		dev		The device structure containing
-	 *				The io address and interrupt count
-	 *				for this device.
-	 *		phy		The address of the PHY to be queried.
-	 *		reg		The register whose contents are to be
-	 *				retrieved.
-	 *		val		A pointer to a variable to store the
-	 *				retrieved value.
-	 *
-	 *	This function uses the TLAN's MII bus to retrieve the contents
-	 *	of a given register on a PHY.  It sends the appropriate info
-	 *	and then reads the 16-bit register value from the MII bus via
-	 *	the TLAN SIO register.
-	 *
-	 **************************************************************/
-
-static bool TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val )
+/***************************************************************
+ *	tlan_mii_read_reg
+ *
+ *	Returns:
+ *		false	if ack received ok
+ *		true	if no ack received or other error
+ *
+ *	Parms:
+ *		dev		The device structure containing
+ *				The io address and interrupt count
+ *				for this device.
+ *		phy		The address of the PHY to be queried.
+ *		reg		The register whose contents are to be
+ *				retrieved.
+ *		val		A pointer to a variable to store the
+ *				retrieved value.
+ *
+ *	This function uses the TLAN's MII bus to retrieve the contents
+ *	of a given register on a PHY.  It sends the appropriate info
+ *	and then reads the 16-bit register value from the MII bus via
+ *	the TLAN SIO register.
+ *
+ **************************************************************/
+
+static bool
+tlan_mii_read_reg(struct net_device *dev, u16 phy, u16 reg, u16 *val)
 {
 	u8	nack;
 	u16	sio, tmp;
- 	u32	i;
+	u32	i;
 	bool	err;
 	int	minten;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	unsigned long flags = 0;
 
 	err = false;
@@ -2892,48 +2832,48 @@ static bool TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val
 	if (!in_irq())
 		spin_lock_irqsave(&priv->lock, flags);
 
-	TLan_MiiSync(dev->base_addr);
+	tlan_mii_sync(dev->base_addr);
 
-	minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
-	if ( minten )
-		TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
+	minten = tlan_get_bit(TLAN_NET_SIO_MINTEN, sio);
+	if (minten)
+		tlan_clear_bit(TLAN_NET_SIO_MINTEN, sio);
 
-	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Start ( 01b ) */
-	TLan_MiiSendData( dev->base_addr, 0x2, 2 );	/* Read  ( 10b ) */
-	TLan_MiiSendData( dev->base_addr, phy, 5 );	/* Device #      */
-	TLan_MiiSendData( dev->base_addr, reg, 5 );	/* Register #    */
+	tlan_mii_send_data(dev->base_addr, 0x1, 2);	/* start (01b) */
+	tlan_mii_send_data(dev->base_addr, 0x2, 2);	/* read  (10b) */
+	tlan_mii_send_data(dev->base_addr, phy, 5);	/* device #      */
+	tlan_mii_send_data(dev->base_addr, reg, 5);	/* register #    */
 
 
-	TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);		/* Change direction */
+	tlan_clear_bit(TLAN_NET_SIO_MTXEN, sio);	/* change direction */
 
-	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);		/* Clock Idle bit */
-	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
-	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);		/* Wait 300ns */
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);		/* clock idle bit */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);		/* wait 300ns */
 
-	nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio);	/* Check for ACK */
-	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);		/* Finish ACK */
-	if (nack) {					/* No ACK, so fake it */
+	nack = tlan_get_bit(TLAN_NET_SIO_MDATA, sio);	/* check for ACK */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);		/* finish ACK */
+	if (nack) {					/* no ACK, so fake it */
 		for (i = 0; i < 16; i++) {
-			TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
-			TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+			tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+			tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 		}
 		tmp = 0xffff;
 		err = true;
 	} else {					/* ACK, so read data */
 		for (tmp = 0, i = 0x8000; i; i >>= 1) {
-			TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
-			if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
+			tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+			if (tlan_get_bit(TLAN_NET_SIO_MDATA, sio))
 				tmp |= i;
-			TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+			tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 		}
 	}
 
 
-	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);		/* Idle cycle */
-	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);		/* idle cycle */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 
-	if ( minten )
-		TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
+	if (minten)
+		tlan_set_bit(TLAN_NET_SIO_MINTEN, sio);
 
 	*val = tmp;
 
@@ -2942,116 +2882,117 @@ static bool TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val
 
 	return err;
 
-} /* TLan_MiiReadReg */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_MiiSendData
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		base_port	The base IO port of the adapter	in
-	 *				question.
-	 *		dev		The address of the PHY to be queried.
-	 *		data		The value to be placed on the MII bus.
-	 *		num_bits	The number of bits in data that are to
-	 *				be placed on the MII bus.
-	 *
-	 *	This function sends on sequence of bits on the MII
-	 *	configuration bus.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_mii_send_data
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		base_port	The base IO port of the adapter	in
+ *				question.
+ *		dev		The address of the PHY to be queried.
+ *		data		The value to be placed on the MII bus.
+ *		num_bits	The number of bits in data that are to
+ *				be placed on the MII bus.
+ *
+ *	This function sends on sequence of bits on the MII
+ *	configuration bus.
+ *
+ **************************************************************/
 
-static void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits )
+static void tlan_mii_send_data(u16 base_port, u32 data, unsigned num_bits)
 {
 	u16 sio;
 	u32 i;
 
-	if ( num_bits == 0 )
+	if (num_bits == 0)
 		return;
 
-	outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
 	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
-	TLan_SetBit( TLAN_NET_SIO_MTXEN, sio );
+	tlan_set_bit(TLAN_NET_SIO_MTXEN, sio);
 
-	for ( i = ( 0x1 << ( num_bits - 1 ) ); i; i >>= 1 ) {
-		TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
-		(void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
-		if ( data & i )
-			TLan_SetBit( TLAN_NET_SIO_MDATA, sio );
+	for (i = (0x1 << (num_bits - 1)); i; i >>= 1) {
+		tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+		(void) tlan_get_bit(TLAN_NET_SIO_MCLK, sio);
+		if (data & i)
+			tlan_set_bit(TLAN_NET_SIO_MDATA, sio);
 		else
-			TLan_ClearBit( TLAN_NET_SIO_MDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
-		(void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
+			tlan_clear_bit(TLAN_NET_SIO_MDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
+		(void) tlan_get_bit(TLAN_NET_SIO_MCLK, sio);
 	}
 
-} /* TLan_MiiSendData */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_MiiSync
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		base_port	The base IO port of the adapter in
-	 *				question.
-	 *
-	 *	This functions syncs all PHYs in terms of the MII configuration
-	 *	bus.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_MiiSync
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		base_port	The base IO port of the adapter in
+ *				question.
+ *
+ *	This functions syncs all PHYs in terms of the MII configuration
+ *	bus.
+ *
+ **************************************************************/
 
-static void TLan_MiiSync( u16 base_port )
+static void tlan_mii_sync(u16 base_port)
 {
 	int i;
 	u16 sio;
 
-	outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
 	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	TLan_ClearBit( TLAN_NET_SIO_MTXEN, sio );
-	for ( i = 0; i < 32; i++ ) {
-		TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
-		TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
+	tlan_clear_bit(TLAN_NET_SIO_MTXEN, sio);
+	for (i = 0; i < 32; i++) {
+		tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+		tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 	}
 
-} /* TLan_MiiSync */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_MiiWriteReg
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev		The device structure for the device
-	 *				to write to.
-	 *		phy		The address of the PHY to be written to.
-	 *		reg		The register whose contents are to be
-	 *				written.
-	 *		val		The value to be written to the register.
-	 *
-	 *	This function uses the TLAN's MII bus to write the contents of a
-	 *	given register on a PHY.  It sends the appropriate info and then
-	 *	writes the 16-bit register value from the MII configuration bus
-	 *	via the TLAN SIO register.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_mii_write_reg
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev		The device structure for the device
+ *				to write to.
+ *		phy		The address of the PHY to be written to.
+ *		reg		The register whose contents are to be
+ *				written.
+ *		val		The value to be written to the register.
+ *
+ *	This function uses the TLAN's MII bus to write the contents of a
+ *	given register on a PHY.  It sends the appropriate info and then
+ *	writes the 16-bit register value from the MII configuration bus
+ *	via the TLAN SIO register.
+ *
+ **************************************************************/
 
-static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val )
+static void
+tlan_mii_write_reg(struct net_device *dev, u16 phy, u16 reg, u16 val)
 {
 	u16	sio;
 	int	minten;
 	unsigned long flags = 0;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 
 	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
 	sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
@@ -3059,30 +3000,30 @@ static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val
 	if (!in_irq())
 		spin_lock_irqsave(&priv->lock, flags);
 
-	TLan_MiiSync( dev->base_addr );
+	tlan_mii_sync(dev->base_addr);
 
-	minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
-	if ( minten )
-		TLan_ClearBit( TLAN_NET_SIO_MINTEN, sio );
+	minten = tlan_get_bit(TLAN_NET_SIO_MINTEN, sio);
+	if (minten)
+		tlan_clear_bit(TLAN_NET_SIO_MINTEN, sio);
 
-	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Start ( 01b ) */
-	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Write ( 01b ) */
-	TLan_MiiSendData( dev->base_addr, phy, 5 );	/* Device #      */
-	TLan_MiiSendData( dev->base_addr, reg, 5 );	/* Register #    */
+	tlan_mii_send_data(dev->base_addr, 0x1, 2);	/* start (01b) */
+	tlan_mii_send_data(dev->base_addr, 0x1, 2);	/* write (01b) */
+	tlan_mii_send_data(dev->base_addr, phy, 5);	/* device #      */
+	tlan_mii_send_data(dev->base_addr, reg, 5);	/* register #    */
 
-	TLan_MiiSendData( dev->base_addr, 0x2, 2 );	/* Send ACK */
-	TLan_MiiSendData( dev->base_addr, val, 16 );	/* Send Data */
+	tlan_mii_send_data(dev->base_addr, 0x2, 2);	/* send ACK */
+	tlan_mii_send_data(dev->base_addr, val, 16);	/* send data */
 
-	TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );	/* Idle cycle */
-	TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);	/* idle cycle */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 
-	if ( minten )
-		TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
+	if (minten)
+		tlan_set_bit(TLAN_NET_SIO_MINTEN, sio);
 
 	if (!in_irq())
 		spin_unlock_irqrestore(&priv->lock, flags);
 
-} /* TLan_MiiWriteReg */
+}
 
 
 
@@ -3090,229 +3031,226 @@ static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Eeprom routines
+ThunderLAN driver eeprom routines
 
-	The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
-	EEPROM.  These functions are based on information in Microchip's
-	data sheet.  I don't know how well this functions will work with
-	other EEPROMs.
+the Compaq netelligent 10 and 10/100 cards use a microchip 24C02A
+EEPROM.  these functions are based on information in microchip's
+data sheet.  I don't know how well this functions will work with
+other Eeproms.
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_EeSendStart
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *
-	 *	This function sends a start cycle to an EEPROM attached
-	 *	to a TLAN chip.
-	 *
-	 **************************************************************/
-
-static void TLan_EeSendStart( u16 io_base )
+/***************************************************************
+ *	tlan_ee_send_start
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *
+ *	This function sends a start cycle to an EEPROM attached
+ *	to a TLAN chip.
+ *
+ **************************************************************/
+
+static void tlan_ee_send_start(u16 io_base)
 {
 	u16	sio;
 
-	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-	TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
-	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
-	TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-	TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
-
-} /* TLan_EeSendStart */
-
-
-
-
-	/***************************************************************
-	 *	TLan_EeSendByte
-	 *
-	 *	Returns:
-	 *		If the correct ack was received, 0, otherwise 1
-	 *	Parms:	io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *		data		The 8 bits of information to
-	 *				send to the EEPROM.
-	 *		stop		If TLAN_EEPROM_STOP is passed, a
-	 *				stop cycle is sent after the
-	 *				byte is sent after the ack is
-	 *				read.
-	 *
-	 *	This function sends a byte on the serial EEPROM line,
-	 *	driving the clock to send each bit. The function then
-	 *	reverses transmission direction and reads an acknowledge
-	 *	bit.
-	 *
-	 **************************************************************/
-
-static int TLan_EeSendByte( u16 io_base, u8 data, int stop )
+	tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+	tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
+	tlan_set_bit(TLAN_NET_SIO_ETXEN, sio);
+	tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+	tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
+
+}
+
+
+
+
+/***************************************************************
+ *	tlan_ee_send_byte
+ *
+ *	Returns:
+ *		If the correct ack was received, 0, otherwise 1
+ *	Parms:	io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *		data		The 8 bits of information to
+ *				send to the EEPROM.
+ *		stop		If TLAN_EEPROM_STOP is passed, a
+ *				stop cycle is sent after the
+ *				byte is sent after the ack is
+ *				read.
+ *
+ *	This function sends a byte on the serial EEPROM line,
+ *	driving the clock to send each bit. The function then
+ *	reverses transmission direction and reads an acknowledge
+ *	bit.
+ *
+ **************************************************************/
+
+static int tlan_ee_send_byte(u16 io_base, u8 data, int stop)
 {
 	int	err;
 	u8	place;
 	u16	sio;
 
-	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
 
 	/* Assume clock is low, tx is enabled; */
-	for ( place = 0x80; place != 0; place >>= 1 ) {
-		if ( place & data )
-			TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
+	for (place = 0x80; place != 0; place >>= 1) {
+		if (place & data)
+			tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
 		else
-			TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+			tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 	}
-	TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
-	TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-	err = TLan_GetBit( TLAN_NET_SIO_EDATA, sio );
-	TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
-	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
+	tlan_clear_bit(TLAN_NET_SIO_ETXEN, sio);
+	tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+	err = tlan_get_bit(TLAN_NET_SIO_EDATA, sio);
+	tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
+	tlan_set_bit(TLAN_NET_SIO_ETXEN, sio);
 
-	if ( ( ! err ) && stop ) {
+	if ((!err) && stop) {
 		/* STOP, raise data while clock is high */
-		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
+		tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
 	}
 
 	return err;
 
-} /* TLan_EeSendByte */
-
-
-
-
-	/***************************************************************
-	 *	TLan_EeReceiveByte
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *		data		An address to a char to hold the
-	 *				data sent from the EEPROM.
-	 *		stop		If TLAN_EEPROM_STOP is passed, a
-	 *				stop cycle is sent after the
-	 *				byte is received, and no ack is
-	 *				sent.
-	 *
-	 *	This function receives 8 bits of data from the EEPROM
-	 *	over the serial link.  It then sends and ack bit, or no
-	 *	ack and a stop bit.  This function is used to retrieve
-	 *	data after the address of a byte in the EEPROM has been
-	 *	sent.
-	 *
-	 **************************************************************/
-
-static void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
+}
+
+
+
+
+/***************************************************************
+ *	tlan_ee_receive_byte
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *		data		An address to a char to hold the
+ *				data sent from the EEPROM.
+ *		stop		If TLAN_EEPROM_STOP is passed, a
+ *				stop cycle is sent after the
+ *				byte is received, and no ack is
+ *				sent.
+ *
+ *	This function receives 8 bits of data from the EEPROM
+ *	over the serial link.  It then sends and ack bit, or no
+ *	ack and a stop bit.  This function is used to retrieve
+ *	data after the address of a byte in the EEPROM has been
+ *	sent.
+ *
+ **************************************************************/
+
+static void tlan_ee_receive_byte(u16 io_base, u8 *data, int stop)
 {
 	u8  place;
 	u16 sio;
 
-	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
 	*data = 0;
 
 	/* Assume clock is low, tx is enabled; */
-	TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
-	for ( place = 0x80; place; place >>= 1 ) {
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		if ( TLan_GetBit( TLAN_NET_SIO_EDATA, sio ) )
+	tlan_clear_bit(TLAN_NET_SIO_ETXEN, sio);
+	for (place = 0x80; place; place >>= 1) {
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		if (tlan_get_bit(TLAN_NET_SIO_EDATA, sio))
 			*data |= place;
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 	}
 
-	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
-	if ( ! stop ) {
-		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );	/* Ack = 0 */
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+	tlan_set_bit(TLAN_NET_SIO_ETXEN, sio);
+	if (!stop) {
+		tlan_clear_bit(TLAN_NET_SIO_EDATA, sio); /* ack = 0 */
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 	} else {
-		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );		/* No ack = 1 (?) */
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+		tlan_set_bit(TLAN_NET_SIO_EDATA, sio);	/* no ack = 1 (?) */
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 		/* STOP, raise data while clock is high */
-		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
-	}
-
-} /* TLan_EeReceiveByte */
-
-
-
-
-	/***************************************************************
-	 *	TLan_EeReadByte
-	 *
-	 *	Returns:
-	 *		No error = 0, else, the stage at which the error
-	 *		occurred.
-	 *	Parms:
-	 *		io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *		ee_addr		The address of the byte in the
-	 *				EEPROM whose contents are to be
-	 *				retrieved.
-	 *		data		An address to a char to hold the
-	 *				data obtained from the EEPROM.
-	 *
-	 *	This function reads a byte of information from an byte
-	 *	cell in the EEPROM.
-	 *
-	 **************************************************************/
-
-static int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data )
+		tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
+	}
+
+}
+
+
+
+
+/***************************************************************
+ *	tlan_ee_read_byte
+ *
+ *	Returns:
+ *		No error = 0, else, the stage at which the error
+ *		occurred.
+ *	Parms:
+ *		io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *		ee_addr		The address of the byte in the
+ *				EEPROM whose contents are to be
+ *				retrieved.
+ *		data		An address to a char to hold the
+ *				data obtained from the EEPROM.
+ *
+ *	This function reads a byte of information from an byte
+ *	cell in the EEPROM.
+ *
+ **************************************************************/
+
+static int tlan_ee_read_byte(struct net_device *dev, u8 ee_addr, u8 *data)
 {
 	int err;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	unsigned long flags = 0;
-	int ret=0;
+	int ret = 0;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	TLan_EeSendStart( dev->base_addr );
-	err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
-	if (err)
-	{
-		ret=1;
+	tlan_ee_send_start(dev->base_addr);
+	err = tlan_ee_send_byte(dev->base_addr, 0xa0, TLAN_EEPROM_ACK);
+	if (err) {
+		ret = 1;
 		goto fail;
 	}
-	err = TLan_EeSendByte( dev->base_addr, ee_addr, TLAN_EEPROM_ACK );
-	if (err)
-	{
-		ret=2;
+	err = tlan_ee_send_byte(dev->base_addr, ee_addr, TLAN_EEPROM_ACK);
+	if (err) {
+		ret = 2;
 		goto fail;
 	}
-	TLan_EeSendStart( dev->base_addr );
-	err = TLan_EeSendByte( dev->base_addr, 0xA1, TLAN_EEPROM_ACK );
-	if (err)
-	{
-		ret=3;
+	tlan_ee_send_start(dev->base_addr);
+	err = tlan_ee_send_byte(dev->base_addr, 0xa1, TLAN_EEPROM_ACK);
+	if (err) {
+		ret = 3;
 		goto fail;
 	}
-	TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
+	tlan_ee_receive_byte(dev->base_addr, data, TLAN_EEPROM_STOP);
 fail:
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return ret;
 
-} /* TLan_EeReadByte */
+}
 
 
 
diff --git a/drivers/net/tlan.h b/drivers/net/tlan.h
index 3315ced..5fc98a8 100644
--- a/drivers/net/tlan.h
+++ b/drivers/net/tlan.h
@@ -20,8 +20,8 @@
  ********************************************************************/
 
 
-#include <asm/io.h>
-#include <asm/types.h>
+#include <linux/io.h>
+#include <linux/types.h>
 #include <linux/netdevice.h>
 
 
@@ -40,8 +40,11 @@
 #define TLAN_IGNORE		0
 #define TLAN_RECORD		1
 
-#define TLAN_DBG(lvl, format, args...)	\
-	do { if (debug&lvl) printk(KERN_DEBUG "TLAN: " format, ##args ); } while(0)
+#define TLAN_DBG(lvl, format, args...)					\
+	do {								\
+		if (debug&lvl)						\
+			printk(KERN_DEBUG "TLAN: " format, ##args);	\
+	} while (0)
 
 #define TLAN_DEBUG_GNRL		0x0001
 #define TLAN_DEBUG_TX		0x0002
@@ -50,7 +53,8 @@
 #define TLAN_DEBUG_PROBE	0x0010
 
 #define TX_TIMEOUT		(10*HZ)	 /* We need time for auto-neg */
-#define MAX_TLAN_BOARDS		8	 /* Max number of boards installed at a time */
+#define MAX_TLAN_BOARDS		8	 /* Max number of boards installed
+					    at a time */
 
 
 	/*****************************************************************
@@ -70,13 +74,13 @@
 #define PCI_DEVICE_ID_OLICOM_OC2326			0x0014
 #endif
 
-typedef struct tlan_adapter_entry {
-	u16	vendorId;
-	u16	deviceId;
-	char	*deviceLabel;
+struct tlan_adapter_entry {
+	u16	vendor_id;
+	u16	device_id;
+	char	*device_label;
 	u32	flags;
-	u16	addrOfs;
-} TLanAdapterEntry;
+	u16	addr_ofs;
+};
 
 #define TLAN_ADAPTER_NONE		0x00000000
 #define TLAN_ADAPTER_UNMANAGED_PHY	0x00000001
@@ -129,18 +133,18 @@ typedef struct tlan_adapter_entry {
 #define TLAN_CSTAT_DP_PR	0x0100
 
 
-typedef struct tlan_buffer_ref_tag {
+struct tlan_buffer {
 	u32	count;
 	u32	address;
-} TLanBufferRef;
+};
 
 
-typedef struct tlan_list_tag {
+struct tlan_list {
 	u32		forward;
-	u16		cStat;
-	u16		frameSize;
-	TLanBufferRef	buffer[TLAN_BUFFERS_PER_LIST];
-} TLanList;
+	u16		c_stat;
+	u16		frame_size;
+	struct tlan_buffer buffer[TLAN_BUFFERS_PER_LIST];
+};
 
 
 typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
@@ -164,49 +168,49 @@ typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
 	 *
 	 ****************************************************************/
 
-typedef struct tlan_private_tag {
-	struct net_device       *nextDevice;
-	struct pci_dev		*pciDev;
+struct tlan_priv {
+	struct net_device       *next_device;
+	struct pci_dev		*pci_dev;
 	struct net_device       *dev;
-	void			*dmaStorage;
-	dma_addr_t		dmaStorageDMA;
-	unsigned int		dmaSize;
-	u8			*padBuffer;
-	TLanList                *rxList;
-	dma_addr_t		rxListDMA;
-	u8			*rxBuffer;
-	dma_addr_t		rxBufferDMA;
-	u32                     rxHead;
-	u32                     rxTail;
-	u32			rxEocCount;
-	TLanList                *txList;
-	dma_addr_t		txListDMA;
-	u8			*txBuffer;
-	dma_addr_t		txBufferDMA;
-	u32                     txHead;
-	u32                     txInProgress;
-	u32                     txTail;
-	u32			txBusyCount;
-	u32                     phyOnline;
-	u32			timerSetAt;
-	u32			timerType;
+	void			*dma_storage;
+	dma_addr_t		dma_storage_dma;
+	unsigned int		dma_size;
+	u8			*pad_buffer;
+	struct tlan_list	*rx_list;
+	dma_addr_t		rx_list_dma;
+	u8			*rx_buffer;
+	dma_addr_t		rx_buffer_dma;
+	u32			rx_head;
+	u32			rx_tail;
+	u32			rx_eoc_count;
+	struct tlan_list	*tx_list;
+	dma_addr_t		tx_list_dma;
+	u8			*tx_buffer;
+	dma_addr_t		tx_buffer_dma;
+	u32			tx_head;
+	u32			tx_in_progress;
+	u32			tx_tail;
+	u32			tx_busy_count;
+	u32			phy_online;
+	u32			timer_set_at;
+	u32			timer_type;
 	struct timer_list	timer;
 	struct board		*adapter;
-	u32			adapterRev;
+	u32			adapter_rev;
 	u32			aui;
 	u32			debug;
 	u32			duplex;
 	u32			phy[2];
-	u32			phyNum;
+	u32			phy_num;
 	u32			speed;
-	u8			tlanRev;
-	u8			tlanFullDuplex;
+	u8			tlan_rev;
+	u8			tlan_full_duplex;
 	spinlock_t		lock;
 	u8			link;
 	u8			is_eisa;
 	struct work_struct			tlan_tqueue;
 	u8			neg_be_verbose;
-} TLanPrivateInfo;
+};
 
 
 
@@ -247,7 +251,7 @@ typedef struct tlan_private_tag {
 	 ****************************************************************/
 
 #define TLAN_HOST_CMD			0x00
-#define 	TLAN_HC_GO		0x80000000
+#define	TLAN_HC_GO		0x80000000
 #define		TLAN_HC_STOP		0x40000000
 #define		TLAN_HC_ACK		0x20000000
 #define		TLAN_HC_CS_MASK		0x1FE00000
@@ -283,7 +287,7 @@ typedef struct tlan_private_tag {
 #define		TLAN_NET_CMD_TRFRAM	0x02
 #define		TLAN_NET_CMD_TXPACE	0x01
 #define TLAN_NET_SIO			0x01
-#define 	TLAN_NET_SIO_MINTEN	0x80
+#define	TLAN_NET_SIO_MINTEN	0x80
 #define		TLAN_NET_SIO_ECLOK	0x40
 #define		TLAN_NET_SIO_ETXEN	0x20
 #define		TLAN_NET_SIO_EDATA	0x10
@@ -304,7 +308,7 @@ typedef struct tlan_private_tag {
 #define		TLAN_NET_MASK_MASK4	0x10
 #define		TLAN_NET_MASK_RSRVD	0x0F
 #define TLAN_NET_CONFIG			0x04
-#define 	TLAN_NET_CFG_RCLK	0x8000
+#define	TLAN_NET_CFG_RCLK	0x8000
 #define		TLAN_NET_CFG_TCLK	0x4000
 #define		TLAN_NET_CFG_BIT	0x2000
 #define		TLAN_NET_CFG_RXCRC	0x1000
@@ -372,7 +376,7 @@ typedef struct tlan_private_tag {
 /* Generic MII/PHY Registers */
 
 #define MII_GEN_CTL			0x00
-#define 	MII_GC_RESET		0x8000
+#define	MII_GC_RESET		0x8000
 #define		MII_GC_LOOPBK		0x4000
 #define		MII_GC_SPEEDSEL		0x2000
 #define		MII_GC_AUTOENB		0x1000
@@ -397,9 +401,9 @@ typedef struct tlan_private_tag {
 #define		MII_GS_EXTCAP		0x0001
 #define MII_GEN_ID_HI			0x02
 #define MII_GEN_ID_LO			0x03
-#define 	MII_GIL_OUI		0xFC00
-#define 	MII_GIL_MODEL		0x03F0
-#define 	MII_GIL_REVISION	0x000F
+#define	MII_GIL_OUI		0xFC00
+#define	MII_GIL_MODEL		0x03F0
+#define	MII_GIL_REVISION	0x000F
 #define MII_AN_ADV			0x04
 #define MII_AN_LPA			0x05
 #define MII_AN_EXP			0x06
@@ -408,7 +412,7 @@ typedef struct tlan_private_tag {
 
 #define TLAN_TLPHY_ID			0x10
 #define TLAN_TLPHY_CTL			0x11
-#define 	TLAN_TC_IGLINK		0x8000
+#define	TLAN_TC_IGLINK		0x8000
 #define		TLAN_TC_SWAPOL		0x4000
 #define		TLAN_TC_AUISEL		0x2000
 #define		TLAN_TC_SQEEN		0x1000
@@ -435,41 +439,41 @@ typedef struct tlan_private_tag {
 #define LEVEL1_ID1			0x7810
 #define LEVEL1_ID2			0x0000
 
-#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0
+#define CIRC_INC(a, b) if (++a >= b) a = 0
 
 /* Routines to access internal registers. */
 
-static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
+static inline u8 tlan_dio_read8(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	return inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3));
 
-} /* TLan_DioRead8 */
+}
 
 
 
 
-static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
+static inline u16 tlan_dio_read16(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	return inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2));
 
-} /* TLan_DioRead16 */
+}
 
 
 
 
-static inline u32 TLan_DioRead32(u16 base_addr, u16 internal_addr)
+static inline u32 tlan_dio_read32(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	return inl(base_addr + TLAN_DIO_DATA);
 
-} /* TLan_DioRead32 */
+}
 
 
 
 
-static inline void TLan_DioWrite8(u16 base_addr, u16 internal_addr, u8 data)
+static inline void tlan_dio_write8(u16 base_addr, u16 internal_addr, u8 data)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	outb(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x3));
@@ -479,7 +483,7 @@ static inline void TLan_DioWrite8(u16 base_addr, u16 internal_addr, u8 data)
 
 
 
-static inline void TLan_DioWrite16(u16 base_addr, u16 internal_addr, u16 data)
+static inline void tlan_dio_write16(u16 base_addr, u16 internal_addr, u16 data)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	outw(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
@@ -489,16 +493,16 @@ static inline void TLan_DioWrite16(u16 base_addr, u16 internal_addr, u16 data)
 
 
 
-static inline void TLan_DioWrite32(u16 base_addr, u16 internal_addr, u32 data)
+static inline void tlan_dio_write32(u16 base_addr, u16 internal_addr, u32 data)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	outl(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
 
 }
 
-#define TLan_ClearBit( bit, port )	outb_p(inb_p(port) & ~bit, port)
-#define TLan_GetBit( bit, port )	((int) (inb_p(port) & bit))
-#define TLan_SetBit( bit, port )	outb_p(inb_p(port) | bit, port)
+#define tlan_clear_bit(bit, port)	outb_p(inb_p(port) & ~bit, port)
+#define tlan_get_bit(bit, port)	((int) (inb_p(port) & bit))
+#define tlan_set_bit(bit, port)	outb_p(inb_p(port) | bit, port)
 
 /*
  * given 6 bytes, view them as 8 6-bit numbers and return the XOR of those
@@ -506,37 +510,37 @@ static inline void TLan_DioWrite32(u16 base_addr, u16 internal_addr, u32 data)
  *
  * The original code was:
  *
- * u32	xor( u32 a, u32 b ) {	return ( ( a && ! b ) || ( ! a && b ) ); }
+ * u32	xor(u32 a, u32 b) {	return ((a && !b ) || (! a && b )); }
  *
- * #define XOR8( a, b, c, d, e, f, g, h )	\
- * 	xor( a, xor( b, xor( c, xor( d, xor( e, xor( f, xor( g, h ) ) ) ) ) ) )
- * #define DA( a, bit )		( ( (u8) a[bit/8] ) & ( (u8) ( 1 << bit%8 ) ) )
+ * #define XOR8(a, b, c, d, e, f, g, h)	\
+ *	xor(a, xor(b, xor(c, xor(d, xor(e, xor(f, xor(g, h)) ) ) ) ) )
+ * #define DA(a, bit)		(( (u8) a[bit/8] ) & ( (u8) (1 << bit%8)) )
  *
- * 	hash  = XOR8( DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24),
- * 	              DA(a,30), DA(a,36), DA(a,42) );
- * 	hash |= XOR8( DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25),
- * 		      DA(a,31), DA(a,37), DA(a,43) ) << 1;
- * 	hash |= XOR8( DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26),
- * 		      DA(a,32), DA(a,38), DA(a,44) ) << 2;
- * 	hash |= XOR8( DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27),
- * 		      DA(a,33), DA(a,39), DA(a,45) ) << 3;
- * 	hash |= XOR8( DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28),
- * 	              DA(a,34), DA(a,40), DA(a,46) ) << 4;
- * 	hash |= XOR8( DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29),
- * 	              DA(a,35), DA(a,41), DA(a,47) ) << 5;
+ *	hash  = XOR8(DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24),
+ *		      DA(a,30), DA(a,36), DA(a,42));
+ *	hash |= XOR8(DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25),
+ *		      DA(a,31), DA(a,37), DA(a,43)) << 1;
+ *	hash |= XOR8(DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26),
+ *		      DA(a,32), DA(a,38), DA(a,44)) << 2;
+ *	hash |= XOR8(DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27),
+ *		      DA(a,33), DA(a,39), DA(a,45)) << 3;
+ *	hash |= XOR8(DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28),
+ *		      DA(a,34), DA(a,40), DA(a,46)) << 4;
+ *	hash |= XOR8(DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29),
+ *		      DA(a,35), DA(a,41), DA(a,47)) << 5;
  *
  */
-static inline u32 TLan_HashFunc( const u8 *a )
+static inline u32 tlan_hash_func(const u8 *a)
 {
-        u8     hash;
+	u8     hash;
 
-        hash = (a[0]^a[3]);             /* & 077 */
-        hash ^= ((a[0]^a[3])>>6);       /* & 003 */
-        hash ^= ((a[1]^a[4])<<2);       /* & 074 */
-        hash ^= ((a[1]^a[4])>>4);       /* & 017 */
-        hash ^= ((a[2]^a[5])<<4);       /* & 060 */
-        hash ^= ((a[2]^a[5])>>2);       /* & 077 */
+	hash = (a[0]^a[3]);		/* & 077 */
+	hash ^= ((a[0]^a[3])>>6);	/* & 003 */
+	hash ^= ((a[1]^a[4])<<2);	/* & 074 */
+	hash ^= ((a[1]^a[4])>>4);	/* & 017 */
+	hash ^= ((a[2]^a[5])<<4);	/* & 060 */
+	hash ^= ((a[2]^a[5])>>2);	/* & 077 */
 
-        return hash & 077;
+	return hash & 077;
 }
 #endif
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b100bd5..f5e9ac0 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -34,6 +34,8 @@
  *    Modifications for 2.3.99-pre5 kernel.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME	"tun"
 #define DRV_VERSION	"1.6"
 #define DRV_DESCRIPTION	"Universal TUN/TAP device driver"
@@ -76,11 +78,27 @@
 #ifdef TUN_DEBUG
 static int debug;
 
-#define DBG  if(tun->debug)printk
-#define DBG1 if(debug==2)printk
+#define tun_debug(level, tun, fmt, args...)			\
+do {								\
+	if (tun->debug)						\
+		netdev_printk(level, tun->dev, fmt, ##args);	\
+} while (0)
+#define DBG1(level, fmt, args...)				\
+do {								\
+	if (debug == 2)						\
+		printk(level fmt, ##args);			\
+} while (0)
 #else
-#define DBG( a... )
-#define DBG1( a... )
+#define tun_debug(level, tun, fmt, args...)			\
+do {								\
+	if (0)							\
+		netdev_printk(level, tun->dev, fmt, ##args);	\
+} while (0)
+#define DBG1(level, fmt, args...)				\
+do {								\
+	if (0)							\
+		printk(level fmt, ##args);			\
+} while (0)
 #endif
 
 #define FLT_EXACT_COUNT 8
@@ -205,7 +223,7 @@ static void tun_put(struct tun_struct *tun)
 		tun_detach(tfile->tun);
 }
 
-/* TAP filterting */
+/* TAP filtering */
 static void addr_hash_set(u32 *mask, const u8 *addr)
 {
 	int n = ether_crc(ETH_ALEN, addr) >> 26;
@@ -360,7 +378,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
 
-	DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len);
+	tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
 
 	/* Drop packet if interface is not attached */
 	if (!tun->tfile)
@@ -499,7 +517,7 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 
 	sk = tun->socket.sk;
 
-	DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
 
 	poll_wait(file, &tun->wq.wait, wait);
 
@@ -690,7 +708,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 	if (!tun)
 		return -EBADFD;
 
-	DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count);
+	tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count);
 
 	result = tun_get_user(tun, iv, iov_length(iv, count),
 			      file->f_flags & O_NONBLOCK);
@@ -739,7 +757,7 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
 			else if (sinfo->gso_type & SKB_GSO_UDP)
 				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
 			else {
-				printk(KERN_ERR "tun: unexpected GSO type: "
+				pr_err("unexpected GSO type: "
 				       "0x%x, gso_size %d, hdr_len %d\n",
 				       sinfo->gso_type, gso.gso_size,
 				       gso.hdr_len);
@@ -786,7 +804,7 @@ static ssize_t tun_do_read(struct tun_struct *tun,
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 
-	DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_chr_read\n");
 
 	add_wait_queue(&tun->wq.wait, &wait);
 	while (len) {
@@ -1083,7 +1101,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
-			printk(KERN_ERR "Failed to create tun sysfs files\n");
+			pr_err("Failed to create tun sysfs files\n");
 
 		sk->sk_destruct = tun_sock_destruct;
 
@@ -1092,7 +1110,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 			goto failed;
 	}
 
-	DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
 	if (ifr->ifr_flags & IFF_NO_PI)
 		tun->flags |= TUN_NO_PI;
@@ -1129,7 +1147,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 static int tun_get_iff(struct net *net, struct tun_struct *tun,
 		       struct ifreq *ifr)
 {
-	DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_get_iff\n");
 
 	strcpy(ifr->ifr_name, tun->dev->name);
 
@@ -1142,7 +1160,7 @@ static int tun_get_iff(struct net *net, struct tun_struct *tun,
  * privs required. */
 static int set_offload(struct net_device *dev, unsigned long arg)
 {
-	unsigned int old_features, features;
+	u32 old_features, features;
 
 	old_features = dev->features;
 	/* Unset features, set them as we chew on the arg. */
@@ -1229,7 +1247,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 	if (!tun)
 		goto unlock;
 
-	DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
+	tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d\n", cmd);
 
 	ret = 0;
 	switch (cmd) {
@@ -1249,8 +1267,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		else
 			tun->flags &= ~TUN_NOCHECKSUM;
 
-		DBG(KERN_INFO "%s: checksum %s\n",
-		    tun->dev->name, arg ? "disabled" : "enabled");
+		tun_debug(KERN_INFO, tun, "checksum %s\n",
+			  arg ? "disabled" : "enabled");
 		break;
 
 	case TUNSETPERSIST:
@@ -1260,33 +1278,34 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		else
 			tun->flags &= ~TUN_PERSIST;
 
-		DBG(KERN_INFO "%s: persist %s\n",
-		    tun->dev->name, arg ? "enabled" : "disabled");
+		tun_debug(KERN_INFO, tun, "persist %s\n",
+			  arg ? "enabled" : "disabled");
 		break;
 
 	case TUNSETOWNER:
 		/* Set owner of the device */
 		tun->owner = (uid_t) arg;
 
-		DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
+		tun_debug(KERN_INFO, tun, "owner set to %d\n", tun->owner);
 		break;
 
 	case TUNSETGROUP:
 		/* Set group of the device */
 		tun->group= (gid_t) arg;
 
-		DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+		tun_debug(KERN_INFO, tun, "group set to %d\n", tun->group);
 		break;
 
 	case TUNSETLINK:
 		/* Only allow setting the type when the interface is down */
 		if (tun->dev->flags & IFF_UP) {
-			DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
-				tun->dev->name);
+			tun_debug(KERN_INFO, tun,
+				  "Linktype set failed because interface is up\n");
 			ret = -EBUSY;
 		} else {
 			tun->dev->type = (int) arg;
-			DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
+			tun_debug(KERN_INFO, tun, "linktype set to %d\n",
+				  tun->dev->type);
 			ret = 0;
 		}
 		break;
@@ -1318,8 +1337,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 
 	case SIOCSIFHWADDR:
 		/* Set hw address */
-		DBG(KERN_DEBUG "%s: set hw address: %pM\n",
-			tun->dev->name, ifr.ifr_hwaddr.sa_data);
+		tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n",
+			  ifr.ifr_hwaddr.sa_data);
 
 		ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
 		break;
@@ -1433,7 +1452,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
 	if (!tun)
 		return -EBADFD;
 
-	DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on);
+	tun_debug(KERN_INFO, tun, "tun_chr_fasync %d\n", on);
 
 	if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
 		goto out;
@@ -1455,7 +1474,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 {
 	struct tun_file *tfile;
 
-	DBG1(KERN_INFO "tunX: tun_chr_open\n");
+	DBG1(KERN_INFO, "tunX: tun_chr_open\n");
 
 	tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
 	if (!tfile)
@@ -1476,7 +1495,7 @@ static int tun_chr_close(struct inode *inode, struct file *file)
 	if (tun) {
 		struct net_device *dev = tun->dev;
 
-		DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
+		tun_debug(KERN_INFO, tun, "tun_chr_close\n");
 
 		__tun_detach(tun);
 
@@ -1607,18 +1626,18 @@ static int __init tun_init(void)
 {
 	int ret = 0;
 
-	printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
-	printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
+	pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+	pr_info("%s\n", DRV_COPYRIGHT);
 
 	ret = rtnl_link_register(&tun_link_ops);
 	if (ret) {
-		printk(KERN_ERR "tun: Can't register link_ops\n");
+		pr_err("Can't register link_ops\n");
 		goto err_linkops;
 	}
 
 	ret = misc_register(&tun_miscdev);
 	if (ret) {
-		printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
+		pr_err("Can't register misc device %d\n", TUN_MINOR);
 		goto err_misc;
 	}
 	return  0;
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index a3c46f6..7fa5ec2 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -123,12 +123,11 @@ static const int multicast_filter_limit = 32;
 #include <linux/in6.h>
 #include <linux/dma-mapping.h>
 #include <linux/firmware.h>
-#include <generated/utsrelease.h>
 
 #include "typhoon.h"
 
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
-MODULE_VERSION(UTS_RELEASE);
+MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(FIRMWARE_NAME);
 MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index 715e7b4..ef04105 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3740,7 +3740,7 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
 #endif
 };
 
-static int ucc_geth_probe(struct platform_device* ofdev, const struct of_device_id *match)
+static int ucc_geth_probe(struct platform_device* ofdev)
 {
 	struct device *device = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -3986,7 +3986,7 @@ static struct of_device_id ucc_geth_match[] = {
 
 MODULE_DEVICE_TABLE(of, ucc_geth_match);
 
-static struct of_platform_driver ucc_geth_driver = {
+static struct platform_driver ucc_geth_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -4008,14 +4008,14 @@ static int __init ucc_geth_init(void)
 		memcpy(&(ugeth_info[i]), &ugeth_primary_info,
 		       sizeof(ugeth_primary_info));
 
-	ret = of_register_platform_driver(&ucc_geth_driver);
+	ret = platform_driver_register(&ucc_geth_driver);
 
 	return ret;
 }
 
 static void __exit ucc_geth_exit(void)
 {
-	of_unregister_platform_driver(&ucc_geth_driver);
+	platform_driver_unregister(&ucc_geth_driver);
 }
 
 module_init(ucc_geth_init);
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 109751b..f967913 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -328,13 +328,13 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	static const char ifname[] = "usbpn%d";
 	const struct usb_cdc_union_desc *union_header = NULL;
-	const struct usb_cdc_header_desc *phonet_header = NULL;
 	const struct usb_host_interface *data_desc;
 	struct usb_interface *data_intf;
 	struct usb_device *usbdev = interface_to_usbdev(intf);
 	struct net_device *dev;
 	struct usbpn_dev *pnd;
 	u8 *data;
+	int phonet = 0;
 	int len, err;
 
 	data = intf->altsetting->extra;
@@ -355,10 +355,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
 					(struct usb_cdc_union_desc *)data;
 				break;
 			case 0xAB:
-				if (phonet_header || dlen < 5)
-					break;
-				phonet_header =
-					(struct usb_cdc_header_desc *)data;
+				phonet = 1;
 				break;
 			}
 		}
@@ -366,7 +363,7 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
 		len -= dlen;
 	}
 
-	if (!union_header || !phonet_header)
+	if (!union_header || !phonet)
 		return -EINVAL;
 
 	data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
@@ -392,7 +389,6 @@ int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
 	pnd = netdev_priv(dev);
 	SET_NETDEV_DEV(dev, &intf->dev);
-	netif_stop_queue(dev);
 
 	pnd->dev = dev;
 	pnd->usb = usb_get_dev(usbdev);
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 6d83812..387ca43 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -324,7 +324,7 @@ struct hso_device {
 /* Prototypes                                                                */
 /*****************************************************************************/
 /* Serial driver functions */
-static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
+static int hso_serial_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear);
 static void ctrl_callback(struct urb *urb);
 static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
@@ -1335,7 +1335,7 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp)
 
 	/* done */
 	if (result)
-		hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0);
+		hso_serial_tiocmset(tty, TIOCM_RTS | TIOCM_DTR, 0);
 err_out:
 	mutex_unlock(&serial->parent->mutex);
 	return result;
@@ -1656,7 +1656,7 @@ static int hso_get_count(struct tty_struct *tty,
 }
 
 
-static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file)
+static int hso_serial_tiocmget(struct tty_struct *tty)
 {
 	int retval;
 	struct hso_serial *serial = get_serial_by_tty(tty);
@@ -1687,7 +1687,7 @@ static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file)
 	return retval;
 }
 
-static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
+static int hso_serial_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear)
 {
 	int val = 0;
@@ -1730,7 +1730,7 @@ static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
 			       USB_CTRL_SET_TIMEOUT);
 }
 
-static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
+static int hso_serial_ioctl(struct tty_struct *tty,
 			    unsigned int cmd, unsigned long arg)
 {
 	struct hso_serial *serial =  get_serial_by_tty(tty);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index cc83fa7..2de9b90 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -171,7 +171,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (skb->ip_summed == CHECKSUM_NONE)
 		skb->ip_summed = rcv_priv->ip_summed;
 
-	length = skb->len + ETH_HLEN;
+	length = skb->len;
 	if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
 		goto rx_drop;
 
@@ -403,17 +403,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 	if (tb[IFLA_ADDRESS] == NULL)
 		random_ether_addr(dev->dev_addr);
 
-	if (tb[IFLA_IFNAME])
-		nla_strlcpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);
-	else
-		snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d");
-
-	if (strchr(dev->name, '%')) {
-		err = dev_alloc_name(dev, dev->name);
-		if (err < 0)
-			goto err_alloc_name;
-	}
-
 	err = register_netdevice(dev);
 	if (err < 0)
 		goto err_register_dev;
@@ -433,7 +422,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 
 err_register_dev:
 	/* nothing to do */
-err_alloc_name:
 err_configure_peer:
 	unregister_netdevice(peer);
 	return err;
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 09cac70..0d6fec6 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -2923,6 +2923,7 @@ static u16 wol_calc_crc(int size, u8 *pattern, u8 *mask_pattern)
 static int velocity_set_wol(struct velocity_info *vptr)
 {
 	struct mac_regs __iomem *regs = vptr->mac_regs;
+	enum speed_opt spd_dpx = vptr->options.spd_dpx;
 	static u8 buf[256];
 	int i;
 
@@ -2968,6 +2969,12 @@ static int velocity_set_wol(struct velocity_info *vptr)
 
 	writew(0x0FFF, &regs->WOLSRClr);
 
+	if (spd_dpx == SPD_DPX_1000_FULL)
+		goto mac_done;
+
+	if (spd_dpx != SPD_DPX_AUTO)
+		goto advertise_done;
+
 	if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
 		if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
 			MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
@@ -2978,6 +2985,7 @@ static int velocity_set_wol(struct velocity_info *vptr)
 	if (vptr->mii_status & VELOCITY_SPEED_1000)
 		MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
 
+advertise_done:
 	BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
 
 	{
@@ -2987,6 +2995,7 @@ static int velocity_set_wol(struct velocity_info *vptr)
 		writeb(GCR, &regs->CHIPGCR);
 	}
 
+mac_done:
 	BYTE_REG_BITS_OFF(ISR_PWEI, &regs->ISR);
 	/* Turn on SWPTAG just before entering power mode */
 	BYTE_REG_BITS_ON(STICKHW_SWPTAG, &regs->STICKHW);
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index aa2e69b..d722753 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -361,7 +361,7 @@ enum  velocity_owner {
 #define MAC_REG_CHIPGSR     0x9C
 #define MAC_REG_TESTCFG     0x9D
 #define MAC_REG_DEBUG       0x9E
-#define MAC_REG_CHIPGCR     0x9F
+#define MAC_REG_CHIPGCR     0x9F	/* Chip Operation and Diagnostic Control */
 #define MAC_REG_WOLCR0_SET  0xA0
 #define MAC_REG_WOLCR1_SET  0xA1
 #define MAC_REG_PWCFG_SET   0xA2
@@ -848,10 +848,10 @@ enum  velocity_owner {
  *	Bits in CHIPGCR register
  */
 
-#define CHIPGCR_FCGMII      0x80	/* enable GMII mode */
-#define CHIPGCR_FCFDX       0x40
+#define CHIPGCR_FCGMII      0x80	/* force GMII (else MII only) */
+#define CHIPGCR_FCFDX       0x40	/* force full duplex */
 #define CHIPGCR_FCRESV      0x20
-#define CHIPGCR_FCMODE      0x10
+#define CHIPGCR_FCMODE      0x10	/* enable MAC forced mode */
 #define CHIPGCR_LPSOPT      0x08
 #define CHIPGCR_TM1US       0x04
 #define CHIPGCR_TM0US       0x02
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c
index 228d4f7..e74e4b4 100644
--- a/drivers/net/vxge/vxge-config.c
+++ b/drivers/net/vxge/vxge-config.c
@@ -387,8 +387,8 @@ vxge_hw_vpath_eprom_img_ver_get(struct __vxge_hw_device *hldev,
 		data1 = steer_ctrl = 0;
 
 		status = vxge_hw_vpath_fw_api(vpath,
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
 			VXGE_HW_FW_API_GET_EPROM_REV,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
 			0, &data0, &data1, &steer_ctrl);
 		if (status != VXGE_HW_OK)
 			break;
@@ -2868,6 +2868,8 @@ __vxge_hw_ring_create(struct __vxge_hw_vpath_handle *vp,
 	ring->rxd_init = attr->rxd_init;
 	ring->rxd_term = attr->rxd_term;
 	ring->buffer_mode = config->buffer_mode;
+	ring->tim_rti_cfg1_saved = vp->vpath->tim_rti_cfg1_saved;
+	ring->tim_rti_cfg3_saved = vp->vpath->tim_rti_cfg3_saved;
 	ring->rxds_limit = config->rxds_limit;
 
 	ring->rxd_size = vxge_hw_ring_rxd_size_get(config->buffer_mode);
@@ -3511,6 +3513,8 @@ __vxge_hw_fifo_create(struct __vxge_hw_vpath_handle *vp,
 
 	/* apply "interrupts per txdl" attribute */
 	fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_UTILZ;
+	fifo->tim_tti_cfg1_saved = vpath->tim_tti_cfg1_saved;
+	fifo->tim_tti_cfg3_saved = vpath->tim_tti_cfg3_saved;
 
 	if (fifo->config->intr)
 		fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_PER_LIST;
@@ -4377,6 +4381,8 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
 		}
 
 		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+		vpath->tim_tti_cfg1_saved = val64;
+
 		val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
 
 		if (config->tti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
@@ -4433,6 +4439,7 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
 		}
 
 		writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
+		vpath->tim_tti_cfg3_saved = val64;
 	}
 
 	if (config->ring.enable == VXGE_HW_RING_ENABLE) {
@@ -4481,6 +4488,8 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
 		}
 
 		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
+		vpath->tim_rti_cfg1_saved = val64;
+
 		val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
 
 		if (config->rti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
@@ -4537,6 +4546,7 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
 		}
 
 		writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
+		vpath->tim_rti_cfg3_saved = val64;
 	}
 
 	val64 = 0;
@@ -4555,26 +4565,6 @@ __vxge_hw_vpath_tim_configure(struct __vxge_hw_device *hldev, u32 vp_id)
 	return status;
 }
 
-void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
-{
-	struct __vxge_hw_virtualpath *vpath;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
-	struct vxge_hw_vp_config *config;
-	u64 val64;
-
-	vpath = &hldev->virtual_paths[vp_id];
-	vp_reg = vpath->vp_reg;
-	config = vpath->vp_config;
-
-	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE &&
-	    config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
-		config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
-		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
-		val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
-		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
-	}
-}
-
 /*
  * __vxge_hw_vpath_initialize
  * This routine is the final phase of init which initializes the
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h
index e249e28..3c53aa7 100644
--- a/drivers/net/vxge/vxge-config.h
+++ b/drivers/net/vxge/vxge-config.h
@@ -682,6 +682,10 @@ struct __vxge_hw_virtualpath {
 	u32				vsport_number;
 	u32				max_kdfc_db;
 	u32				max_nofl_db;
+	u64				tim_tti_cfg1_saved;
+	u64				tim_tti_cfg3_saved;
+	u64				tim_rti_cfg1_saved;
+	u64				tim_rti_cfg3_saved;
 
 	struct __vxge_hw_ring *____cacheline_aligned ringh;
 	struct __vxge_hw_fifo *____cacheline_aligned fifoh;
@@ -921,6 +925,9 @@ struct __vxge_hw_ring {
 	u32					doorbell_cnt;
 	u32					total_db_cnt;
 	u64					rxds_limit;
+	u32					rtimer;
+	u64					tim_rti_cfg1_saved;
+	u64					tim_rti_cfg3_saved;
 
 	enum vxge_hw_status (*callback)(
 			struct __vxge_hw_ring *ringh,
@@ -1000,6 +1007,9 @@ struct __vxge_hw_fifo {
 	u32					per_txdl_space;
 	u32					vp_id;
 	u32					tx_intr_num;
+	u32					rtimer;
+	u64					tim_tti_cfg1_saved;
+	u64					tim_tti_cfg3_saved;
 
 	enum vxge_hw_status (*callback)(
 			struct __vxge_hw_fifo *fifo_handle,
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index c81a651..395423a 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -371,9 +371,6 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
 	struct vxge_hw_ring_rxd_info ext_info;
 	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d",
 		ring->ndev->name, __func__, __LINE__);
-	ring->pkts_processed = 0;
-
-	vxge_hw_ring_replenish(ringh);
 
 	do {
 		prefetch((char *)dtr + L1_CACHE_BYTES);
@@ -1588,6 +1585,36 @@ static int vxge_reset_vpath(struct vxgedev *vdev, int vp_id)
 	return ret;
 }
 
+/* Configure CI */
+static void vxge_config_ci_for_tti_rti(struct vxgedev *vdev)
+{
+	int i = 0;
+
+	/* Enable CI for RTI */
+	if (vdev->config.intr_type == MSI_X) {
+		for (i = 0; i < vdev->no_of_vpath; i++) {
+			struct __vxge_hw_ring *hw_ring;
+
+			hw_ring = vdev->vpaths[i].ring.handle;
+			vxge_hw_vpath_dynamic_rti_ci_set(hw_ring);
+		}
+	}
+
+	/* Enable CI for TTI */
+	for (i = 0; i < vdev->no_of_vpath; i++) {
+		struct __vxge_hw_fifo *hw_fifo = vdev->vpaths[i].fifo.handle;
+		vxge_hw_vpath_tti_ci_set(hw_fifo);
+		/*
+		 * For Inta (with or without napi), Set CI ON for only one
+		 * vpath. (Have only one free running timer).
+		 */
+		if ((vdev->config.intr_type == INTA) && (i == 0))
+			break;
+	}
+
+	return;
+}
+
 static int do_vxge_reset(struct vxgedev *vdev, int event)
 {
 	enum vxge_hw_status status;
@@ -1753,6 +1780,9 @@ static int do_vxge_reset(struct vxgedev *vdev, int event)
 		netif_tx_wake_all_queues(vdev->ndev);
 	}
 
+	/* configure CI */
+	vxge_config_ci_for_tti_rti(vdev);
+
 out:
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s:%d  Exiting...", __func__, __LINE__);
@@ -1793,22 +1823,29 @@ static void vxge_reset(struct work_struct *work)
  */
 static int vxge_poll_msix(struct napi_struct *napi, int budget)
 {
-	struct vxge_ring *ring =
-		container_of(napi, struct vxge_ring, napi);
+	struct vxge_ring *ring = container_of(napi, struct vxge_ring, napi);
+	int pkts_processed;
 	int budget_org = budget;
-	ring->budget = budget;
 
+	ring->budget = budget;
+	ring->pkts_processed = 0;
 	vxge_hw_vpath_poll_rx(ring->handle);
+	pkts_processed = ring->pkts_processed;
 
 	if (ring->pkts_processed < budget_org) {
 		napi_complete(napi);
+
 		/* Re enable the Rx interrupts for the vpath */
 		vxge_hw_channel_msix_unmask(
 				(struct __vxge_hw_channel *)ring->handle,
 				ring->rx_vector_no);
+		mmiowb();
 	}
 
-	return ring->pkts_processed;
+	/* We are copying and returning the local variable, in case if after
+	 * clearing the msix interrupt above, if the interrupt fires right
+	 * away which can preempt this NAPI thread */
+	return pkts_processed;
 }
 
 static int vxge_poll_inta(struct napi_struct *napi, int budget)
@@ -1824,6 +1861,7 @@ static int vxge_poll_inta(struct napi_struct *napi, int budget)
 	for (i = 0; i < vdev->no_of_vpath; i++) {
 		ring = &vdev->vpaths[i].ring;
 		ring->budget = budget;
+		ring->pkts_processed = 0;
 		vxge_hw_vpath_poll_rx(ring->handle);
 		pkts_processed += ring->pkts_processed;
 		budget -= ring->pkts_processed;
@@ -2054,6 +2092,7 @@ static int vxge_open_vpaths(struct vxgedev *vdev)
 					netdev_get_tx_queue(vdev->ndev, 0);
 			vpath->fifo.indicate_max_pkts =
 				vdev->config.fifo_indicate_max_pkts;
+			vpath->fifo.tx_vector_no = 0;
 			vpath->ring.rx_vector_no = 0;
 			vpath->ring.rx_csum = vdev->rx_csum;
 			vpath->ring.rx_hwts = vdev->rx_hwts;
@@ -2079,6 +2118,61 @@ static int vxge_open_vpaths(struct vxgedev *vdev)
 	return VXGE_HW_OK;
 }
 
+/**
+ *  adaptive_coalesce_tx_interrupts - Changes the interrupt coalescing
+ *  if the interrupts are not within a range
+ *  @fifo: pointer to transmit fifo structure
+ *  Description: The function changes boundary timer and restriction timer
+ *  value depends on the traffic
+ *  Return Value: None
+ */
+static void adaptive_coalesce_tx_interrupts(struct vxge_fifo *fifo)
+{
+	fifo->interrupt_count++;
+	if (jiffies > fifo->jiffies + HZ / 100) {
+		struct __vxge_hw_fifo *hw_fifo = fifo->handle;
+
+		fifo->jiffies = jiffies;
+		if (fifo->interrupt_count > VXGE_T1A_MAX_TX_INTERRUPT_COUNT &&
+		    hw_fifo->rtimer != VXGE_TTI_RTIMER_ADAPT_VAL) {
+			hw_fifo->rtimer = VXGE_TTI_RTIMER_ADAPT_VAL;
+			vxge_hw_vpath_dynamic_tti_rtimer_set(hw_fifo);
+		} else if (hw_fifo->rtimer != 0) {
+			hw_fifo->rtimer = 0;
+			vxge_hw_vpath_dynamic_tti_rtimer_set(hw_fifo);
+		}
+		fifo->interrupt_count = 0;
+	}
+}
+
+/**
+ *  adaptive_coalesce_rx_interrupts - Changes the interrupt coalescing
+ *  if the interrupts are not within a range
+ *  @ring: pointer to receive ring structure
+ *  Description: The function increases of decreases the packet counts within
+ *  the ranges of traffic utilization, if the interrupts due to this ring are
+ *  not within a fixed range.
+ *  Return Value: Nothing
+ */
+static void adaptive_coalesce_rx_interrupts(struct vxge_ring *ring)
+{
+	ring->interrupt_count++;
+	if (jiffies > ring->jiffies + HZ / 100) {
+		struct __vxge_hw_ring *hw_ring = ring->handle;
+
+		ring->jiffies = jiffies;
+		if (ring->interrupt_count > VXGE_T1A_MAX_INTERRUPT_COUNT &&
+		    hw_ring->rtimer != VXGE_RTI_RTIMER_ADAPT_VAL) {
+			hw_ring->rtimer = VXGE_RTI_RTIMER_ADAPT_VAL;
+			vxge_hw_vpath_dynamic_rti_rtimer_set(hw_ring);
+		} else if (hw_ring->rtimer != 0) {
+			hw_ring->rtimer = 0;
+			vxge_hw_vpath_dynamic_rti_rtimer_set(hw_ring);
+		}
+		ring->interrupt_count = 0;
+	}
+}
+
 /*
  *  vxge_isr_napi
  *  @irq: the irq of the device.
@@ -2139,24 +2233,39 @@ static irqreturn_t vxge_isr_napi(int irq, void *dev_id)
 
 #ifdef CONFIG_PCI_MSI
 
-static irqreturn_t
-vxge_tx_msix_handle(int irq, void *dev_id)
+static irqreturn_t vxge_tx_msix_handle(int irq, void *dev_id)
 {
 	struct vxge_fifo *fifo = (struct vxge_fifo *)dev_id;
 
+	adaptive_coalesce_tx_interrupts(fifo);
+
+	vxge_hw_channel_msix_mask((struct __vxge_hw_channel *)fifo->handle,
+				  fifo->tx_vector_no);
+
+	vxge_hw_channel_msix_clear((struct __vxge_hw_channel *)fifo->handle,
+				   fifo->tx_vector_no);
+
 	VXGE_COMPLETE_VPATH_TX(fifo);
 
+	vxge_hw_channel_msix_unmask((struct __vxge_hw_channel *)fifo->handle,
+				    fifo->tx_vector_no);
+
+	mmiowb();
+
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-vxge_rx_msix_napi_handle(int irq, void *dev_id)
+static irqreturn_t vxge_rx_msix_napi_handle(int irq, void *dev_id)
 {
 	struct vxge_ring *ring = (struct vxge_ring *)dev_id;
 
-	/* MSIX_IDX for Rx is 1 */
+	adaptive_coalesce_rx_interrupts(ring);
+
 	vxge_hw_channel_msix_mask((struct __vxge_hw_channel *)ring->handle,
-					ring->rx_vector_no);
+				  ring->rx_vector_no);
+
+	vxge_hw_channel_msix_clear((struct __vxge_hw_channel *)ring->handle,
+				   ring->rx_vector_no);
 
 	napi_schedule(&ring->napi);
 	return IRQ_HANDLED;
@@ -2173,14 +2282,20 @@ vxge_alarm_msix_handle(int irq, void *dev_id)
 		VXGE_HW_VPATH_MSIX_ACTIVE) + VXGE_ALARM_MSIX_ID;
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
+		/* Reduce the chance of loosing alarm interrupts by masking
+		 * the vector. A pending bit will be set if an alarm is
+		 * generated and on unmask the interrupt will be fired.
+		 */
 		vxge_hw_vpath_msix_mask(vdev->vpaths[i].handle, msix_id);
+		vxge_hw_vpath_msix_clear(vdev->vpaths[i].handle, msix_id);
+		mmiowb();
 
 		status = vxge_hw_vpath_alarm_process(vdev->vpaths[i].handle,
 			vdev->exec_mode);
 		if (status == VXGE_HW_OK) {
-
 			vxge_hw_vpath_msix_unmask(vdev->vpaths[i].handle,
-					msix_id);
+						  msix_id);
+			mmiowb();
 			continue;
 		}
 		vxge_debug_intr(VXGE_ERR,
@@ -2299,6 +2414,9 @@ static int vxge_enable_msix(struct vxgedev *vdev)
 			vpath->ring.rx_vector_no = (vpath->device_id *
 						VXGE_HW_VPATH_MSIX_ACTIVE) + 1;
 
+			vpath->fifo.tx_vector_no = (vpath->device_id *
+						VXGE_HW_VPATH_MSIX_ACTIVE);
+
 			vxge_hw_vpath_msix_set(vpath->handle, tim_msix_id,
 					       VXGE_ALARM_MSIX_ID);
 		}
@@ -2474,8 +2592,9 @@ INTA_MODE:
 			"%s:vxge:INTA", vdev->ndev->name);
 		vxge_hw_device_set_intr_type(vdev->devh,
 			VXGE_HW_INTR_MODE_IRQLINE);
-		vxge_hw_vpath_tti_ci_set(vdev->devh,
-			vdev->vpaths[0].device_id);
+
+		vxge_hw_vpath_tti_ci_set(vdev->vpaths[0].fifo.handle);
+
 		ret = request_irq((int) vdev->pdev->irq,
 			vxge_isr_napi,
 			IRQF_SHARED, vdev->desc[0], vdev);
@@ -2745,6 +2864,10 @@ static int vxge_open(struct net_device *dev)
 	}
 
 	netif_tx_start_all_queues(vdev->ndev);
+
+	/* configure CI */
+	vxge_config_ci_for_tti_rti(vdev);
+
 	goto out0;
 
 out2:
@@ -3264,19 +3387,6 @@ static const struct net_device_ops vxge_netdev_ops = {
 #endif
 };
 
-static int __devinit vxge_device_revision(struct vxgedev *vdev)
-{
-	int ret;
-	u8 revision;
-
-	ret = pci_read_config_byte(vdev->pdev, PCI_REVISION_ID, &revision);
-	if (ret)
-		return -EIO;
-
-	vdev->titan1 = (revision == VXGE_HW_TITAN1_PCI_REVISION);
-	return 0;
-}
-
 static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 					  struct vxge_config *config,
 					  int high_dma, int no_of_vpath,
@@ -3316,10 +3426,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 	memcpy(&vdev->config, config, sizeof(struct vxge_config));
 	vdev->rx_csum = 1;	/* Enable Rx CSUM by default. */
 	vdev->rx_hwts = 0;
-
-	ret = vxge_device_revision(vdev);
-	if (ret < 0)
-		goto _out1;
+	vdev->titan1 = (vdev->pdev->revision == VXGE_HW_TITAN1_PCI_REVISION);
 
 	SET_NETDEV_DEV(ndev, &vdev->pdev->dev);
 
@@ -3348,7 +3455,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 		vxge_debug_init(VXGE_ERR,
 			"%s: vpath memory allocation failed",
 			vdev->ndev->name);
-		ret = -ENODEV;
+		ret = -ENOMEM;
 		goto _out1;
 	}
 
@@ -3369,11 +3476,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 	if (vdev->config.gro_enable)
 		ndev->features |= NETIF_F_GRO;
 
-	if (register_netdev(ndev)) {
+	ret = register_netdev(ndev);
+	if (ret) {
 		vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
 			"%s: %s : device registration failed!",
 			ndev->name, __func__);
-		ret = -ENODEV;
 		goto _out2;
 	}
 
@@ -3444,6 +3551,11 @@ static void vxge_device_unregister(struct __vxge_hw_device *hldev)
 	/* in 2.6 will call stop() if device is up */
 	unregister_netdev(dev);
 
+	kfree(vdev->vpaths);
+
+	/* we are safe to free it now */
+	free_netdev(dev);
+
 	vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered",
 			buf);
 	vxge_debug_entryexit(vdev->level_trace,	"%s: %s:%d  Exiting...", buf,
@@ -3799,7 +3911,7 @@ static void __devinit vxge_device_config_init(
 		break;
 
 	case MSI_X:
-		device_config->intr_mode = VXGE_HW_INTR_MODE_MSIX;
+		device_config->intr_mode = VXGE_HW_INTR_MODE_MSIX_ONE_SHOT;
 		break;
 	}
 
@@ -4335,10 +4447,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 		goto _exit1;
 	}
 
-	if (pci_request_region(pdev, 0, VXGE_DRIVER_NAME)) {
+	ret = pci_request_region(pdev, 0, VXGE_DRIVER_NAME);
+	if (ret) {
 		vxge_debug_init(VXGE_ERR,
 			"%s : request regions failed", __func__);
-		ret = -ENODEV;
 		goto _exit1;
 	}
 
@@ -4446,7 +4558,7 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 			if (!img[i].is_valid)
 				break;
 			vxge_debug_init(VXGE_TRACE, "%s: EPROM %d, version "
-					"%d.%d.%d.%d\n", VXGE_DRIVER_NAME, i,
+					"%d.%d.%d.%d", VXGE_DRIVER_NAME, i,
 					VXGE_EPROM_IMG_MAJOR(img[i].version),
 					VXGE_EPROM_IMG_MINOR(img[i].version),
 					VXGE_EPROM_IMG_FIX(img[i].version),
@@ -4643,8 +4755,9 @@ _exit6:
 _exit5:
 	vxge_device_unregister(hldev);
 _exit4:
-	pci_disable_sriov(pdev);
+	pci_set_drvdata(pdev, NULL);
 	vxge_hw_device_terminate(hldev);
+	pci_disable_sriov(pdev);
 _exit3:
 	iounmap(attr.bar0);
 _exit2:
@@ -4655,7 +4768,7 @@ _exit0:
 	kfree(ll_config);
 	kfree(device_config);
 	driver_config->config_dev_cnt--;
-	pci_set_drvdata(pdev, NULL);
+	driver_config->total_dev_cnt--;
 	return ret;
 }
 
@@ -4668,45 +4781,34 @@ _exit0:
 static void __devexit vxge_remove(struct pci_dev *pdev)
 {
 	struct __vxge_hw_device *hldev;
-	struct vxgedev *vdev = NULL;
-	struct net_device *dev;
-	int i = 0;
+	struct vxgedev *vdev;
+	int i;
 
 	hldev = pci_get_drvdata(pdev);
-
 	if (hldev == NULL)
 		return;
 
-	dev = hldev->ndev;
-	vdev = netdev_priv(dev);
+	vdev = netdev_priv(hldev->ndev);
 
 	vxge_debug_entryexit(vdev->level_trace,	"%s:%d", __func__, __LINE__);
-
 	vxge_debug_init(vdev->level_trace, "%s : removing PCI device...",
 			__func__);
-	vxge_device_unregister(hldev);
 
-	for (i = 0; i < vdev->no_of_vpath; i++) {
+	for (i = 0; i < vdev->no_of_vpath; i++)
 		vxge_free_mac_add_list(&vdev->vpaths[i]);
-		vdev->vpaths[i].mcast_addr_cnt = 0;
-		vdev->vpaths[i].mac_addr_cnt = 0;
-	}
-
-	kfree(vdev->vpaths);
 
+	vxge_device_unregister(hldev);
+	pci_set_drvdata(pdev, NULL);
+	/* Do not call pci_disable_sriov here, as it will break child devices */
+	vxge_hw_device_terminate(hldev);
 	iounmap(vdev->bar0);
-
-	/* we are safe to free it now */
-	free_netdev(dev);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	driver_config->config_dev_cnt--;
+	driver_config->total_dev_cnt--;
 
 	vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered",
 			__func__, __LINE__);
-
-	vxge_hw_device_terminate(hldev);
-
-	pci_disable_device(pdev);
-	pci_release_region(pdev, 0);
-	pci_set_drvdata(pdev, NULL);
 	vxge_debug_entryexit(vdev->level_trace,	"%s:%d  Exiting...", __func__,
 			     __LINE__);
 }
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h
index 5746fed..40474f0 100644
--- a/drivers/net/vxge/vxge-main.h
+++ b/drivers/net/vxge/vxge-main.h
@@ -59,11 +59,13 @@
 #define VXGE_TTI_LTIMER_VAL	1000
 #define VXGE_T1A_TTI_LTIMER_VAL	80
 #define VXGE_TTI_RTIMER_VAL	0
+#define VXGE_TTI_RTIMER_ADAPT_VAL	10
 #define VXGE_T1A_TTI_RTIMER_VAL	400
 #define VXGE_RTI_BTIMER_VAL	250
 #define VXGE_RTI_LTIMER_VAL	100
 #define VXGE_RTI_RTIMER_VAL	0
-#define VXGE_FIFO_INDICATE_MAX_PKTS VXGE_DEF_FIFO_LENGTH
+#define VXGE_RTI_RTIMER_ADAPT_VAL	15
+#define VXGE_FIFO_INDICATE_MAX_PKTS	VXGE_DEF_FIFO_LENGTH
 #define VXGE_ISR_POLLING_CNT 	8
 #define VXGE_MAX_CONFIG_DEV	0xFF
 #define VXGE_EXEC_MODE_DISABLE	0
@@ -107,6 +109,14 @@
 #define RTI_T1A_RX_UFC_C	50
 #define RTI_T1A_RX_UFC_D	60
 
+/*
+ * The interrupt rate is maintained at 3k per second with the moderation
+ * parameters for most traffic but not all. This is the maximum interrupt
+ * count allowed per function with INTA or per vector in the case of
+ * MSI-X in a 10 millisecond time period. Enabled only for Titan 1A.
+ */
+#define VXGE_T1A_MAX_INTERRUPT_COUNT	100
+#define VXGE_T1A_MAX_TX_INTERRUPT_COUNT	200
 
 /* Milli secs timer period */
 #define VXGE_TIMER_DELAY		10000
@@ -247,6 +257,11 @@ struct vxge_fifo {
 	int tx_steering_type;
 	int indicate_max_pkts;
 
+	/* Adaptive interrupt moderation parameters used in T1A */
+	unsigned long interrupt_count;
+	unsigned long jiffies;
+
+	u32 tx_vector_no;
 	/* Tx stats */
 	struct vxge_fifo_stats stats;
 } ____cacheline_aligned;
@@ -271,6 +286,10 @@ struct vxge_ring {
 	 */
 	int driver_id;
 
+	/* Adaptive interrupt moderation parameters used in T1A */
+	unsigned long interrupt_count;
+	unsigned long jiffies;
+
 	/* copy of the flag indicating whether rx_csum is to be used */
 	u32 rx_csum:1,
 	    rx_hwts:1;
@@ -286,7 +305,7 @@ struct vxge_ring {
 
 	int vlan_tag_strip;
 	struct vlan_group *vlgrp;
-	int rx_vector_no;
+	u32 rx_vector_no;
 	enum vxge_hw_status last_status;
 
 	/* Rx stats */
diff --git a/drivers/net/vxge/vxge-traffic.c b/drivers/net/vxge/vxge-traffic.c
index 4c10d6c..8674f33 100644
--- a/drivers/net/vxge/vxge-traffic.c
+++ b/drivers/net/vxge/vxge-traffic.c
@@ -218,6 +218,68 @@ exit:
 	return status;
 }
 
+void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_fifo *fifo)
+{
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	struct vxge_hw_vp_config *config;
+	u64 val64;
+
+	if (fifo->config->enable != VXGE_HW_FIFO_ENABLE)
+		return;
+
+	vp_reg = fifo->vp_reg;
+	config = container_of(fifo->config, struct vxge_hw_vp_config, fifo);
+
+	if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
+		config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
+		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+		val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
+		fifo->tim_tti_cfg1_saved = val64;
+		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+	}
+}
+
+void vxge_hw_vpath_dynamic_rti_ci_set(struct __vxge_hw_ring *ring)
+{
+	u64 val64 = ring->tim_rti_cfg1_saved;
+
+	val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
+	ring->tim_rti_cfg1_saved = val64;
+	writeq(val64, &ring->vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
+}
+
+void vxge_hw_vpath_dynamic_tti_rtimer_set(struct __vxge_hw_fifo *fifo)
+{
+	u64 val64 = fifo->tim_tti_cfg3_saved;
+	u64 timer = (fifo->rtimer * 1000) / 272;
+
+	val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(0x3ffffff);
+	if (timer)
+		val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(timer) |
+			VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(5);
+
+	writeq(val64, &fifo->vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
+	/* tti_cfg3_saved is not updated again because it is
+	 * initialized at one place only - init time.
+	 */
+}
+
+void vxge_hw_vpath_dynamic_rti_rtimer_set(struct __vxge_hw_ring *ring)
+{
+	u64 val64 = ring->tim_rti_cfg3_saved;
+	u64 timer = (ring->rtimer * 1000) / 272;
+
+	val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(0x3ffffff);
+	if (timer)
+		val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(timer) |
+			VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(4);
+
+	writeq(val64, &ring->vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
+	/* rti_cfg3_saved is not updated again because it is
+	 * initialized at one place only - init time.
+	 */
+}
+
 /**
  * vxge_hw_channel_msix_mask - Mask MSIX Vector.
  * @channeh: Channel for rx or tx handle
@@ -254,6 +316,23 @@ vxge_hw_channel_msix_unmask(struct __vxge_hw_channel *channel, int msix_id)
 }
 
 /**
+ * vxge_hw_channel_msix_clear - Unmask the MSIX Vector.
+ * @channel: Channel for rx or tx handle
+ * @msix_id:  MSI ID
+ *
+ * The function unmasks the msix interrupt for the given msix_id
+ * if configured in MSIX oneshot mode
+ *
+ * Returns: 0
+ */
+void vxge_hw_channel_msix_clear(struct __vxge_hw_channel *channel, int msix_id)
+{
+	__vxge_hw_pio_mem_write32_upper(
+		(u32) vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
+		&channel->common_reg->clr_msix_one_shot_vec[msix_id % 4]);
+}
+
+/**
  * vxge_hw_device_set_intr_type - Updates the configuration
  *		with new interrupt type.
  * @hldev: HW device handle.
@@ -2191,19 +2270,14 @@ vxge_hw_vpath_msix_set(struct __vxge_hw_vpath_handle *vp, int *tim_msix_id,
 	if (vpath->hldev->config.intr_mode ==
 					VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
 		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
+				VXGE_HW_ONE_SHOT_VECT0_EN_ONE_SHOT_VECT0_EN,
+				0, 32), &vp_reg->one_shot_vect0_en);
+		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
 				VXGE_HW_ONE_SHOT_VECT1_EN_ONE_SHOT_VECT1_EN,
 				0, 32), &vp_reg->one_shot_vect1_en);
-	}
-
-	if (vpath->hldev->config.intr_mode ==
-		VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
 		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
 				VXGE_HW_ONE_SHOT_VECT2_EN_ONE_SHOT_VECT2_EN,
 				0, 32), &vp_reg->one_shot_vect2_en);
-
-		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
-				VXGE_HW_ONE_SHOT_VECT3_EN_ONE_SHOT_VECT3_EN,
-				0, 32), &vp_reg->one_shot_vect3_en);
 	}
 }
 
@@ -2229,6 +2303,32 @@ vxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vp, int msix_id)
 }
 
 /**
+ * vxge_hw_vpath_msix_clear - Clear MSIX Vector.
+ * @vp: Virtual Path handle.
+ * @msix_id:  MSI ID
+ *
+ * The function clears the msix interrupt for the given msix_id
+ *
+ * Returns: 0,
+ * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
+ * status.
+ * See also:
+ */
+void vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id)
+{
+	struct __vxge_hw_device *hldev = vp->vpath->hldev;
+
+	if ((hldev->config.intr_mode == VXGE_HW_INTR_MODE_MSIX_ONE_SHOT))
+		__vxge_hw_pio_mem_write32_upper(
+			(u32) vxge_bVALn(vxge_mBIT((msix_id >> 2)), 0, 32),
+			&hldev->common_reg->clr_msix_one_shot_vec[msix_id % 4]);
+	else
+		__vxge_hw_pio_mem_write32_upper(
+			(u32) vxge_bVALn(vxge_mBIT((msix_id >> 2)), 0, 32),
+			&hldev->common_reg->clear_msix_mask_vect[msix_id % 4]);
+}
+
+/**
  * vxge_hw_vpath_msix_unmask - Unmask the MSIX Vector.
  * @vp: Virtual Path handle.
  * @msix_id:  MSI ID
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h
index d48486d..9d9dfda 100644
--- a/drivers/net/vxge/vxge-traffic.h
+++ b/drivers/net/vxge/vxge-traffic.h
@@ -2142,6 +2142,10 @@ void vxge_hw_device_clear_tx_rx(
  *  Virtual Paths
  */
 
+void vxge_hw_vpath_dynamic_rti_rtimer_set(struct __vxge_hw_ring *ring);
+
+void vxge_hw_vpath_dynamic_tti_rtimer_set(struct __vxge_hw_fifo *fifo);
+
 u32 vxge_hw_vpath_id(
 	struct __vxge_hw_vpath_handle *vpath_handle);
 
@@ -2245,6 +2249,8 @@ void
 vxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vpath_handle,
 			int msix_id);
 
+void vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id);
+
 void vxge_hw_device_flush_io(struct __vxge_hw_device *devh);
 
 void
@@ -2270,6 +2276,9 @@ void
 vxge_hw_channel_msix_unmask(struct __vxge_hw_channel *channelh, int msix_id);
 
 void
+vxge_hw_channel_msix_clear(struct __vxge_hw_channel *channelh, int msix_id);
+
+void
 vxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel,
 				 void **dtrh);
 
@@ -2282,7 +2291,8 @@ vxge_hw_channel_dtr_free(struct __vxge_hw_channel *channel, void *dtrh);
 int
 vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel);
 
-void
-vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id);
+void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_fifo *fifo);
+
+void vxge_hw_vpath_dynamic_rti_ci_set(struct __vxge_hw_ring *ring);
 
 #endif
diff --git a/drivers/net/vxge/vxge-version.h b/drivers/net/vxge/vxge-version.h
index ad2f99b..581e215 100644
--- a/drivers/net/vxge/vxge-version.h
+++ b/drivers/net/vxge/vxge-version.h
@@ -16,8 +16,8 @@
 
 #define VXGE_VERSION_MAJOR	"2"
 #define VXGE_VERSION_MINOR	"5"
-#define VXGE_VERSION_FIX	"1"
-#define VXGE_VERSION_BUILD	"22082"
+#define VXGE_VERSION_FIX	"2"
+#define VXGE_VERSION_BUILD	"22259"
 #define VXGE_VERSION_FOR	"k"
 
 #define VXGE_FW_VER(maj, min, bld) (((maj) << 16) + ((min) << 8) + (bld))
diff --git a/drivers/net/wan/lmc/Makefile b/drivers/net/wan/lmc/Makefile
index dabdcfe..609710d 100644
--- a/drivers/net/wan/lmc/Makefile
+++ b/drivers/net/wan/lmc/Makefile
@@ -14,4 +14,4 @@ lmc-objs := lmc_debug.o lmc_media.o lmc_main.o lmc_proto.o
 # -DDEBUG \
 # -DLMC_PACKET_LOG
 
-EXTRA_CFLAGS += -I. $(DBGDEF)
+ccflags-y := -I. $(DBGDEF)
diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c
index 515d9b8..1c65d1c 100644
--- a/drivers/net/wan/pc300_tty.c
+++ b/drivers/net/wan/pc300_tty.c
@@ -131,9 +131,8 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
 static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
 static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
 
-static int pc300_tiocmset(struct tty_struct *, struct file *,
-			  unsigned int, unsigned int);
-static int pc300_tiocmget(struct tty_struct *, struct file *);
+static int pc300_tiocmset(struct tty_struct *, unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *);
 
 /* functions called by PC300 driver */
 void cpc_tty_init(pc300dev_t *dev);
@@ -543,7 +542,7 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
 	return 0;
 } 
 
-static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+static int pc300_tiocmset(struct tty_struct *tty,
 			  unsigned int set, unsigned int clear)
 {
 	st_cpc_tty_area    *cpc_tty; 
@@ -570,7 +569,7 @@ static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
 	return 0;
 }
 
-static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+static int pc300_tiocmget(struct tty_struct *tty)
 {
 	unsigned int result;
 	unsigned char status;
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index b4338f3..7aeb113 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -274,6 +274,7 @@ source "drivers/net/wireless/b43legacy/Kconfig"
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/ipw2x00/Kconfig"
 source "drivers/net/wireless/iwlwifi/Kconfig"
+source "drivers/net/wireless/iwlegacy/Kconfig"
 source "drivers/net/wireless/iwmc3200wifi/Kconfig"
 source "drivers/net/wireless/libertas/Kconfig"
 source "drivers/net/wireless/orinoco/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 9760561..ddd3fb6 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -24,7 +24,7 @@ obj-$(CONFIG_B43LEGACY)		+= b43legacy/
 obj-$(CONFIG_ZD1211RW)		+= zd1211rw/
 obj-$(CONFIG_RTL8180)		+= rtl818x/
 obj-$(CONFIG_RTL8187)		+= rtl818x/
-obj-$(CONFIG_RTL8192CE)		+= rtlwifi/
+obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
@@ -41,7 +41,8 @@ obj-$(CONFIG_ADM8211)	+= adm8211.o
 
 obj-$(CONFIG_MWL8K)	+= mwl8k.o
 
-obj-$(CONFIG_IWLWIFI)	+= iwlwifi/
+obj-$(CONFIG_IWLAGN)	+= iwlwifi/
+obj-$(CONFIG_IWLWIFI_LEGACY)	+= iwlegacy/
 obj-$(CONFIG_RT2X00)	+= rt2x00/
 
 obj-$(CONFIG_P54_COMMON)	+= p54/
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index f9aa1bc..afe2cbc 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -1658,7 +1658,7 @@ static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
 }
 
 /* Put adm8211_tx_hdr on skb and transmit */
-static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct adm8211_tx_hdr *txhdr;
 	size_t payload_len, hdrlen;
@@ -1707,8 +1707,6 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 	txhdr->retry_limit = info->control.rates[0].count;
 
 	adm8211_tx_raw(dev, skb, plcp_signal, hdrlen);
-
-	return NETDEV_TX_OK;
 }
 
 static int adm8211_alloc_rings(struct ieee80211_hw *dev)
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 1476314..2986014 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -1728,7 +1728,7 @@ static void at76_mac80211_tx_callback(struct urb *urb)
 	ieee80211_wake_queues(priv->hw);
 }
 
-static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct at76_priv *priv = hw->priv;
 	struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
@@ -1741,7 +1741,8 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (priv->tx_urb->status == -EINPROGRESS) {
 		wiphy_err(priv->hw->wiphy,
 			  "%s called while tx urb is pending\n", __func__);
-		return NETDEV_TX_BUSY;
+		dev_kfree_skb_any(skb);
+		return;
 	}
 
 	/* The following code lines are important when the device is going to
@@ -1755,7 +1756,8 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		if (compare_ether_addr(priv->bssid, mgmt->bssid)) {
 			memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
 			ieee80211_queue_work(hw, &priv->work_join_bssid);
-			return NETDEV_TX_BUSY;
+			dev_kfree_skb_any(skb);
+			return;
 		}
 	}
 
@@ -1795,8 +1797,6 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 				  priv->tx_urb,
 				  priv->tx_urb->hcpriv, priv->tx_urb->complete);
 	}
-
-	return 0;
 }
 
 static int at76_mac80211_start(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/at76c50x-usb.h b/drivers/net/wireless/at76c50x-usb.h
index 4a37447..f14a654 100644
--- a/drivers/net/wireless/at76c50x-usb.h
+++ b/drivers/net/wireless/at76c50x-usb.h
@@ -290,7 +290,7 @@ struct mib_mac_mgmt {
 	u8 res;
 	u8 multi_domain_capability_implemented;
 	u8 multi_domain_capability_enabled;
-	u8 country_string[3];
+	u8 country_string[IEEE80211_COUNTRY_STRING_LEN];
 	u8 reserved[3];
 } __packed;
 
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig
index d7a4799..7b9672b 100644
--- a/drivers/net/wireless/ath/ar9170/Kconfig
+++ b/drivers/net/wireless/ath/ar9170/Kconfig
@@ -1,8 +1,10 @@
 config AR9170_USB
-	tristate "Atheros AR9170 802.11n USB support"
+	tristate "Atheros AR9170 802.11n USB support (OBSOLETE)"
 	depends on USB && MAC80211
 	select FW_LOADER
 	help
+	  This driver is going to get replaced by carl9170.
+
 	  This is a driver for the Atheros "otus" 802.11n USB devices.
 
 	  These devices require additional firmware (2 files).
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
index 4f845f8..371e4ce 100644
--- a/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -224,7 +224,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
 int ar9170_nag_limiter(struct ar9170 *ar);
 
 /* MAC */
-int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 int ar9170_init_mac(struct ar9170 *ar);
 int ar9170_set_qos(struct ar9170 *ar);
 int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast);
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 32bf79e..b761fec 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -1475,7 +1475,7 @@ static void ar9170_tx(struct ar9170 *ar)
 				     msecs_to_jiffies(AR9170_JANITOR_DELAY));
 }
 
-int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ar9170 *ar = hw->priv;
 	struct ieee80211_tx_info *info;
@@ -1493,11 +1493,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	skb_queue_tail(&ar->tx_pending[queue], skb);
 
 	ar9170_tx(ar);
-	return NETDEV_TX_OK;
+	return;
 
 err_free:
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 static int ar9170_op_add_interface(struct ieee80211_hw *hw,
@@ -1945,7 +1944,8 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
 static int ar9170_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index e43210c..a6c6a46 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -108,12 +108,14 @@ enum ath_cipher {
  * struct ath_ops - Register read/write operations
  *
  * @read: Register read
+ * @multi_read: Multiple register read
  * @write: Register write
  * @enable_write_buffer: Enable multiple register writes
  * @write_flush: flush buffered register writes and disable buffering
  */
 struct ath_ops {
 	unsigned int (*read)(void *, u32 reg_offset);
+	void (*multi_read)(void *, u32 *addr, u32 *val, u16 count);
 	void (*write)(void *, u32 val, u32 reg_offset);
 	void (*enable_write_buffer)(void *);
 	void (*write_flush) (void *);
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index e079331..e18a9aa 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -40,6 +40,17 @@ config ATH5K_DEBUG
 
 	  modprobe ath5k debug=0x00000400
 
+config ATH5K_TRACER
+	bool "Atheros 5xxx tracer"
+	depends on ATH5K
+	depends on EVENT_TRACING
+	---help---
+	  Say Y here to enable tracepoints for the ath5k driver
+	  using the kernel tracing infrastructure.  Select this
+	  option if you are interested in debugging the driver.
+
+	  If unsure, say N.
+
 config ATH5K_AHB
 	bool "Atheros 5xxx AHB bus support"
 	depends on (ATHEROS_AR231X && !PCI)
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index 707cde1..82324e9 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -31,7 +31,8 @@ static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
 	*csz = L1_CACHE_BYTES >> 2;
 }
 
-bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+static bool
+ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 {
 	struct ath5k_softc *sc = common->priv;
 	struct platform_device *pdev = to_platform_device(sc->dev);
@@ -46,10 +47,10 @@ bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 
 	eeprom += off;
 	if (eeprom > eeprom_end)
-		return -EINVAL;
+		return false;
 
 	*data = *eeprom;
-	return 0;
+	return true;
 }
 
 int ath5k_hw_read_srev(struct ath5k_hw *ah)
@@ -92,7 +93,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
 		goto err_out;
 	}
 
-	mem = ioremap_nocache(res->start, res->end - res->start + 1);
+	mem = ioremap_nocache(res->start, resource_size(res));
 	if (mem == NULL) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENOMEM;
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 407e39c..8a06dbd 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -210,14 +210,9 @@
 /* Initial values */
 #define	AR5K_INIT_CYCRSSI_THR1			2
 
-/* Tx retry limits */
-#define AR5K_INIT_SH_RETRY			10
-#define AR5K_INIT_LG_RETRY			AR5K_INIT_SH_RETRY
-/* For station mode */
-#define AR5K_INIT_SSH_RETRY			32
-#define AR5K_INIT_SLG_RETRY			AR5K_INIT_SSH_RETRY
-#define AR5K_INIT_TX_RETRY			10
-
+/* Tx retry limit defaults from standard */
+#define AR5K_INIT_RETRY_SHORT			7
+#define AR5K_INIT_RETRY_LONG			4
 
 /* Slot time */
 #define AR5K_INIT_SLOT_TIME_TURBO		6
@@ -518,7 +513,7 @@ enum ath5k_tx_queue_id {
 	AR5K_TX_QUEUE_ID_NOQCU_DATA	= 0,
 	AR5K_TX_QUEUE_ID_NOQCU_BEACON	= 1,
 	AR5K_TX_QUEUE_ID_DATA_MIN	= 0, /*IEEE80211_TX_QUEUE_DATA0*/
-	AR5K_TX_QUEUE_ID_DATA_MAX	= 4, /*IEEE80211_TX_QUEUE_DATA4*/
+	AR5K_TX_QUEUE_ID_DATA_MAX	= 3, /*IEEE80211_TX_QUEUE_DATA3*/
 	AR5K_TX_QUEUE_ID_DATA_SVP	= 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
 	AR5K_TX_QUEUE_ID_CAB		= 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
 	AR5K_TX_QUEUE_ID_BEACON		= 7, /*IEEE80211_TX_QUEUE_BEACON*/
@@ -1057,7 +1052,9 @@ struct ath5k_hw {
 #define ah_modes		ah_capabilities.cap_mode
 #define ah_ee_version		ah_capabilities.cap_eeprom.ee_version
 
-	u32			ah_limit_tx_retries;
+	u8			ah_retry_long;
+	u8			ah_retry_short;
+
 	u8			ah_coverage_class;
 	bool			ah_ack_bitrate_high;
 	u8			ah_bwmode;
@@ -1067,7 +1064,6 @@ struct ath5k_hw {
 	u8			ah_ant_mode;
 	u8			ah_tx_ant;
 	u8			ah_def_ant;
-	bool			ah_software_retry;
 
 	struct ath5k_capabilities ah_capabilities;
 
@@ -1162,6 +1158,26 @@ void ath5k_hw_deinit(struct ath5k_hw *ah);
 int ath5k_sysfs_register(struct ath5k_softc *sc);
 void ath5k_sysfs_unregister(struct ath5k_softc *sc);
 
+/* base.c */
+struct ath5k_buf;
+struct ath5k_txq;
+
+void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+bool ath_any_vif_assoc(struct ath5k_softc *sc);
+void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+		    struct ath5k_txq *txq);
+int ath5k_init_hw(struct ath5k_softc *sc);
+int ath5k_stop_hw(struct ath5k_softc *sc);
+void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+					struct ieee80211_vif *vif);
+int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void ath5k_beacon_config(struct ath5k_softc *sc);
+void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
 /*Chip id helper functions */
 const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
 int ath5k_hw_read_srev(struct ath5k_hw *ah);
@@ -1250,6 +1266,8 @@ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
 int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
 			    enum ath5k_tx_queue queue_type,
 			    struct ath5k_txq_info *queue_info);
+void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
+				  unsigned int queue);
 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
 void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
 int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index cdac5cf..bc82405 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -118,8 +118,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 	ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
 	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
 	ah->ah_imr = 0;
-	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
-	ah->ah_software_retry = false;
+	ah->ah_retry_short = AR5K_INIT_RETRY_SHORT;
+	ah->ah_retry_long = AR5K_INIT_RETRY_LONG;
 	ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
 	ah->ah_noise_floor = -95;	/* until first NF calibration is run */
 	sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
@@ -220,7 +220,8 @@ int ath5k_hw_init(struct ath5k_softc *sc)
 			ah->ah_radio = AR5K_RF5112;
 			ah->ah_single_chip = false;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
-		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) ||
+			ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
 			ah->ah_radio = AR5K_RF2316;
 			ah->ah_single_chip = true;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 09ae4ef..4d7f21e 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -61,6 +61,9 @@
 #include "debug.h"
 #include "ani.h"
 
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
 int ath5k_modparam_nohwcrypt;
 module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -242,73 +245,68 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re
 \********************/
 
 /*
- * Convert IEEE channel number to MHz frequency.
- */
-static inline short
-ath5k_ieee2mhz(short chan)
-{
-	if (chan <= 14 || chan >= 27)
-		return ieee80211chan2mhz(chan);
-	else
-		return 2212 + chan * 20;
-}
-
-/*
  * Returns true for the channel numbers used without all_channels modparam.
  */
-static bool ath5k_is_standard_channel(short chan)
+static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
 {
-	return ((chan <= 14) ||
-		/* UNII 1,2 */
-		((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
+	if (band == IEEE80211_BAND_2GHZ && chan <= 14)
+		return true;
+
+	return	/* UNII 1,2 */
+		(((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
 		/* midband */
 		((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
 		/* UNII-3 */
-		((chan & 3) == 1 && chan >= 149 && chan <= 165));
+		((chan & 3) == 1 && chan >= 149 && chan <= 165) ||
+		/* 802.11j 5.030-5.080 GHz (20MHz) */
+		(chan == 8 || chan == 12 || chan == 16) ||
+		/* 802.11j 4.9GHz (20MHz) */
+		(chan == 184 || chan == 188 || chan == 192 || chan == 196));
 }
 
 static unsigned int
-ath5k_copy_channels(struct ath5k_hw *ah,
-		struct ieee80211_channel *channels,
-		unsigned int mode,
-		unsigned int max)
+ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
+		unsigned int mode, unsigned int max)
 {
-	unsigned int i, count, size, chfreq, freq, ch;
-
-	if (!test_bit(mode, ah->ah_modes))
-		return 0;
+	unsigned int count, size, chfreq, freq, ch;
+	enum ieee80211_band band;
 
 	switch (mode) {
 	case AR5K_MODE_11A:
 		/* 1..220, but 2GHz frequencies are filtered by check_channel */
-		size = 220 ;
+		size = 220;
 		chfreq = CHANNEL_5GHZ;
+		band = IEEE80211_BAND_5GHZ;
 		break;
 	case AR5K_MODE_11B:
 	case AR5K_MODE_11G:
 		size = 26;
 		chfreq = CHANNEL_2GHZ;
+		band = IEEE80211_BAND_2GHZ;
 		break;
 	default:
 		ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
 		return 0;
 	}
 
-	for (i = 0, count = 0; i < size && max > 0; i++) {
-		ch = i + 1 ;
-		freq = ath5k_ieee2mhz(ch);
+	count = 0;
+	for (ch = 1; ch <= size && count < max; ch++) {
+		freq = ieee80211_channel_to_frequency(ch, band);
+
+		if (freq == 0) /* mapping failed - not a standard channel */
+			continue;
 
 		/* Check if channel is supported by the chipset */
 		if (!ath5k_channel_ok(ah, freq, chfreq))
 			continue;
 
-		if (!modparam_all_channels && !ath5k_is_standard_channel(ch))
+		if (!modparam_all_channels &&
+		    !ath5k_is_standard_channel(ch, band))
 			continue;
 
 		/* Write channel info and increment counter */
 		channels[count].center_freq = freq;
-		channels[count].band = (chfreq == CHANNEL_2GHZ) ?
-			IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+		channels[count].band = band;
 		switch (mode) {
 		case AR5K_MODE_11A:
 		case AR5K_MODE_11G:
@@ -319,7 +317,6 @@ ath5k_copy_channels(struct ath5k_hw *ah,
 		}
 
 		count++;
-		max--;
 	}
 
 	return count;
@@ -364,7 +361,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
 		sband->n_bitrates = 12;
 
 		sband->channels = sc->channels;
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11G, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
@@ -390,7 +387,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
 		}
 
 		sband->channels = sc->channels;
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11B, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
@@ -410,7 +407,7 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
 		sband->n_bitrates = 8;
 
 		sband->channels = &sc->channels[count_c];
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11A, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
@@ -445,31 +442,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
 	return ath5k_reset(sc, chan, true);
 }
 
-static void
-ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
-{
-	sc->curmode = mode;
-
-	if (mode == AR5K_MODE_11A) {
-		sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ];
-	} else {
-		sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ];
-	}
-}
-
-struct ath_vif_iter_data {
-	const u8	*hw_macaddr;
-	u8		mask[ETH_ALEN];
-	u8		active_mac[ETH_ALEN]; /* first active MAC */
-	bool		need_set_hw_addr;
-	bool		found_active;
-	bool		any_assoc;
-	enum nl80211_iftype opmode;
-};
-
-static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 {
-	struct ath_vif_iter_data *iter_data = data;
+	struct ath5k_vif_iter_data *iter_data = data;
 	int i;
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
 
@@ -499,9 +474,12 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 	 */
 	if (avf->opmode == NL80211_IFTYPE_AP)
 		iter_data->opmode = NL80211_IFTYPE_AP;
-	else
+	else {
+		if (avf->opmode == NL80211_IFTYPE_STATION)
+			iter_data->n_stas++;
 		if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED)
 			iter_data->opmode = avf->opmode;
+	}
 }
 
 void
@@ -509,7 +487,8 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
 				   struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath5k_hw_common(sc->ah);
-	struct ath_vif_iter_data iter_data;
+	struct ath5k_vif_iter_data iter_data;
+	u32 rfilt;
 
 	/*
 	 * Use the hardware MAC address as reference, the hardware uses it
@@ -520,12 +499,13 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
 	iter_data.found_active = false;
 	iter_data.need_set_hw_addr = true;
 	iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED;
+	iter_data.n_stas = 0;
 
 	if (vif)
-		ath_vif_iter(&iter_data, vif->addr, vif);
+		ath5k_vif_iter(&iter_data, vif->addr, vif);
 
 	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
 						   &iter_data);
 	memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
 
@@ -543,20 +523,19 @@ ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
 
 	if (ath5k_hw_hasbssidmask(sc->ah))
 		ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
-}
 
-void
-ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
-{
-	struct ath5k_hw *ah = sc->ah;
-	u32 rfilt;
+	/* Set up RX Filter */
+	if (iter_data.n_stas > 1) {
+		/* If you have multiple STA interfaces connected to
+		 * different APs, ARPs are not received (most of the time?)
+		 * Enabling PROMISC appears to fix that probem.
+		 */
+		sc->filter_flags |= AR5K_RX_FILTER_PROM;
+	}
 
-	/* configure rx filter */
 	rfilt = sc->filter_flags;
-	ath5k_hw_set_rx_filter(ah, rfilt);
+	ath5k_hw_set_rx_filter(sc->ah, rfilt);
 	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
-
-	ath5k_update_bssid_mask_and_opmode(sc, vif);
 }
 
 static inline int
@@ -569,7 +548,7 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix)
 			"hw_rix out of bounds: %x\n", hw_rix))
 		return 0;
 
-	rix = sc->rate_idx[sc->curband->band][hw_rix];
+	rix = sc->rate_idx[sc->curchan->band][hw_rix];
 	if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
 		rix = 0;
 
@@ -964,6 +943,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
 		spin_lock_init(&txq->lock);
 		txq->setup = true;
 		txq->txq_len = 0;
+		txq->txq_max = ATH5K_TXQ_LEN_MAX;
 		txq->txq_poll_mark = false;
 		txq->txq_stuck = 0;
 	}
@@ -1132,7 +1112,7 @@ ath5k_rx_start(struct ath5k_softc *sc)
 	spin_unlock_bh(&sc->rxbuflock);
 
 	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
-	ath5k_mode_setup(sc, NULL);		/* set filters, etc. */
+	ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */
 	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
 
 	return 0;
@@ -1376,10 +1356,10 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
 	 * right now, so it's not too bad...
 	 */
 	rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp);
-	rxs->flag |= RX_FLAG_TSFT;
+	rxs->flag |= RX_FLAG_MACTIME_MPDU;
 
 	rxs->freq = sc->curchan->center_freq;
-	rxs->band = sc->curband->band;
+	rxs->band = sc->curchan->band;
 
 	rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi;
 
@@ -1394,10 +1374,10 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb,
 	rxs->flag |= ath5k_rx_decrypted(sc, skb, rs);
 
 	if (rxs->rate_idx >= 0 && rs->rs_rate ==
-	    sc->curband->bitrates[rxs->rate_idx].hw_value_short)
+	    sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
 		rxs->flag |= RX_FLAG_SHORTPRE;
 
-	ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
+	trace_ath5k_rx(sc, skb);
 
 	ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi);
 
@@ -1533,7 +1513,7 @@ unlock:
 * TX Handling *
 \*************/
 
-int
+void
 ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 	       struct ath5k_txq *txq)
 {
@@ -1542,7 +1522,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 	unsigned long flags;
 	int padsize;
 
-	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);
+	trace_ath5k_tx(sc, skb, txq);
 
 	/*
 	 * The hardware expects the header padded to 4 byte boundaries.
@@ -1555,7 +1535,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 		goto drop_packet;
 	}
 
-	if (txq->txq_len >= ATH5K_TXQ_LEN_MAX)
+	if (txq->txq_len >= txq->txq_max)
 		ieee80211_stop_queue(hw, txq->qnum);
 
 	spin_lock_irqsave(&sc->txbuflock, flags);
@@ -1582,16 +1562,15 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 		spin_unlock_irqrestore(&sc->txbuflock, flags);
 		goto drop_packet;
 	}
-	return NETDEV_TX_OK;
+	return;
 
 drop_packet:
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 static void
 ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
-			 struct ath5k_tx_status *ts)
+			 struct ath5k_txq *txq, struct ath5k_tx_status *ts)
 {
 	struct ieee80211_tx_info *info;
 	int i;
@@ -1643,6 +1622,7 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
 	else
 		sc->stats.antenna_tx[0]++; /* invalid */
 
+	trace_ath5k_tx_complete(sc, skb, txq, ts);
 	ieee80211_tx_status(sc->hw, skb);
 }
 
@@ -1679,7 +1659,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
 
 			dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
 					DMA_TO_DEVICE);
-			ath5k_tx_frame_completed(sc, skb, &ts);
+			ath5k_tx_frame_completed(sc, skb, txq, &ts);
 		}
 
 		/*
@@ -1821,8 +1801,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 		goto out;
 	}
 
-	ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
-
 	ath5k_txbuf_free_skb(sc, avf->bbuf);
 	avf->bbuf->skb = skb;
 	ret = ath5k_beacon_setup(sc, avf->bbuf);
@@ -1917,6 +1895,8 @@ ath5k_beacon_send(struct ath5k_softc *sc)
 			sc->opmode == NL80211_IFTYPE_MESH_POINT)
 		ath5k_beacon_update(sc->hw, vif);
 
+	trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]);
+
 	ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
 	ath5k_hw_start_tx_dma(ah, sc->bhalq);
 	ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
@@ -2417,7 +2397,8 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
 	/* set up multi-rate retry capabilities */
 	if (sc->ah->ah_version == AR5K_AR5212) {
 		hw->max_rates = 4;
-		hw->max_rate_tries = 11;
+		hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT,
+					 AR5K_INIT_RETRY_LONG);
 	}
 
 	hw->vif_data_size = sizeof(struct ath5k_vif);
@@ -2554,7 +2535,6 @@ ath5k_init_hw(struct ath5k_softc *sc)
 	 * and then setup of the interrupt mask.
 	 */
 	sc->curchan = sc->hw->conf.channel;
-	sc->curband = &sc->sbands[sc->curchan->band];
 	sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
 		AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
 		AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
@@ -2681,10 +2661,8 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
 	 * so we should also free any remaining
 	 * tx buffers */
 	ath5k_drain_tx_buffs(sc);
-	if (chan) {
+	if (chan)
 		sc->curchan = chan;
-		sc->curband = &sc->sbands[chan->band];
-	}
 	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
 								skip_pcu);
 	if (ret) {
@@ -2782,12 +2760,6 @@ ath5k_init(struct ieee80211_hw *hw)
 		goto err;
 	}
 
-	/* NB: setup here so ath5k_rate_update is happy */
-	if (test_bit(AR5K_MODE_11A, ah->ah_modes))
-		ath5k_setcurmode(sc, AR5K_MODE_11A);
-	else
-		ath5k_setcurmode(sc, AR5K_MODE_11B);
-
 	/*
 	 * Allocate tx+rx descriptors and populate the lists.
 	 */
@@ -2946,13 +2918,13 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
 bool
 ath_any_vif_assoc(struct ath5k_softc *sc)
 {
-	struct ath_vif_iter_data iter_data;
+	struct ath5k_vif_iter_data iter_data;
 	iter_data.hw_macaddr = NULL;
 	iter_data.any_assoc = false;
 	iter_data.need_set_hw_addr = false;
 	iter_data.found_active = true;
 
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
 						   &iter_data);
 	return iter_data.any_assoc;
 }
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 6d51147..978f1f4 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -86,6 +86,7 @@ struct ath5k_txq {
 	spinlock_t		lock;	/* lock on q and link */
 	bool			setup;
 	int			txq_len; /* number of queued buffers */
+	int			txq_max; /* max allowed num of queued buffers */
 	bool			txq_poll_mark;
 	unsigned int		txq_stuck;	/* informational counter */
 };
@@ -183,8 +184,6 @@ struct ath5k_softc {
 	enum nl80211_iftype	opmode;
 	struct ath5k_hw		*ah;		/* Atheros HW */
 
-	struct ieee80211_supported_band		*curband;
-
 #ifdef CONFIG_ATH5K_DEBUG
 	struct ath5k_dbg_info	debug;		/* debug info */
 #endif /* CONFIG_ATH5K_DEBUG */
@@ -202,7 +201,6 @@ struct ath5k_softc {
 #define ATH_STAT_STARTED	4		/* opened & irqs enabled */
 
 	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
-	unsigned int		curmode;	/* current phy mode */
 	struct ieee80211_channel *curchan;	/* current h/w channel */
 
 	u16			nvifs;
@@ -262,6 +260,19 @@ struct ath5k_softc {
 	struct survey_info	survey;		/* collected survey info */
 };
 
+struct ath5k_vif_iter_data {
+	const u8	*hw_macaddr;
+	u8		mask[ETH_ALEN];
+	u8		active_mac[ETH_ALEN]; /* first active MAC */
+	bool		need_set_hw_addr;
+	bool		found_active;
+	bool		any_assoc;
+	enum nl80211_iftype opmode;
+	int n_stas;
+};
+void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
+
+
 #define ath5k_hw_hasbssidmask(_ah) \
 	(ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
 #define ath5k_hw_hasveol(_ah) \
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index 31cad80..f77e8a7 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -32,23 +32,24 @@
  */
 int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 {
+	struct ath5k_capabilities *caps = &ah->ah_capabilities;
 	u16 ee_header;
 
 	/* Capabilities stored in the EEPROM */
-	ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+	ee_header = caps->cap_eeprom.ee_header;
 
 	if (ah->ah_version == AR5K_AR5210) {
 		/*
 		 * Set radio capabilities
 		 * (The AR5110 only supports the middle 5GHz band)
 		 */
-		ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
-		ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
-		ah->ah_capabilities.cap_range.range_2ghz_min = 0;
-		ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+		caps->cap_range.range_5ghz_min = 5120;
+		caps->cap_range.range_5ghz_max = 5430;
+		caps->cap_range.range_2ghz_min = 0;
+		caps->cap_range.range_2ghz_max = 0;
 
 		/* Set supported modes */
-		__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
+		__set_bit(AR5K_MODE_11A, caps->cap_mode);
 	} else {
 		/*
 		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
@@ -56,9 +57,8 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 		 * XXX current ieee80211 implementation because the IEEE
 		 * XXX channel mapping does not support negative channel
 		 * XXX numbers (2312MHz is channel -19). Of course, this
-		 * XXX doesn't matter because these channels are out of range
-		 * XXX but some regulation domains like MKK (Japan) will
-		 * XXX support frequencies somewhere around 4.8GHz.
+		 * XXX doesn't matter because these channels are out of the
+		 * XXX legal range.
 		 */
 
 		/*
@@ -66,13 +66,14 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 		 */
 
 		if (AR5K_EEPROM_HDR_11A(ee_header)) {
-			/* 4920 */
-			ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
-			ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+			if (ath_is_49ghz_allowed(caps->cap_eeprom.ee_regdomain))
+				caps->cap_range.range_5ghz_min = 4920;
+			else
+				caps->cap_range.range_5ghz_min = 5005;
+			caps->cap_range.range_5ghz_max = 6100;
 
 			/* Set supported modes */
-			__set_bit(AR5K_MODE_11A,
-					ah->ah_capabilities.cap_mode);
+			__set_bit(AR5K_MODE_11A, caps->cap_mode);
 		}
 
 		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
@@ -81,32 +82,29 @@ int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 		    (AR5K_EEPROM_HDR_11G(ee_header) &&
 		     ah->ah_version != AR5K_AR5211)) {
 			/* 2312 */
-			ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
-			ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+			caps->cap_range.range_2ghz_min = 2412;
+			caps->cap_range.range_2ghz_max = 2732;
 
 			if (AR5K_EEPROM_HDR_11B(ee_header))
-				__set_bit(AR5K_MODE_11B,
-						ah->ah_capabilities.cap_mode);
+				__set_bit(AR5K_MODE_11B, caps->cap_mode);
 
 			if (AR5K_EEPROM_HDR_11G(ee_header) &&
 			    ah->ah_version != AR5K_AR5211)
-				__set_bit(AR5K_MODE_11G,
-						ah->ah_capabilities.cap_mode);
+				__set_bit(AR5K_MODE_11G, caps->cap_mode);
 		}
 	}
 
 	/* Set number of supported TX queues */
 	if (ah->ah_version == AR5K_AR5210)
-		ah->ah_capabilities.cap_queues.q_tx_num =
-			AR5K_NUM_TX_QUEUES_NOQCU;
+		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
 	else
-		ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
+		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
 
 	/* newer hardware has PHY error counters */
 	if (ah->ah_mac_srev >= AR5K_SREV_AR5213A)
-		ah->ah_capabilities.cap_has_phyerr_counters = true;
+		caps->cap_has_phyerr_counters = true;
 	else
-		ah->ah_capabilities.cap_has_phyerr_counters = false;
+		caps->cap_has_phyerr_counters = false;
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index d2f84d7..0230f30 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -308,8 +308,6 @@ static const struct {
 	{ ATH5K_DEBUG_CALIBRATE, "calib",	"periodic calibration" },
 	{ ATH5K_DEBUG_TXPOWER,	"txpower",	"transmit power setting" },
 	{ ATH5K_DEBUG_LED,	"led",		"LED management" },
-	{ ATH5K_DEBUG_DUMP_RX,	"dumprx",	"print received skb content" },
-	{ ATH5K_DEBUG_DUMP_TX,	"dumptx",	"print transmit skb content" },
 	{ ATH5K_DEBUG_DUMPBANDS, "dumpbands",	"dump bands" },
 	{ ATH5K_DEBUG_DMA,	"dma",		"dma start/stop" },
 	{ ATH5K_DEBUG_ANI,	"ani",		"adaptive noise immunity" },
@@ -1036,24 +1034,6 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
 }
 
 void
-ath5k_debug_dump_skb(struct ath5k_softc *sc,
-			struct sk_buff *skb, const char *prefix, int tx)
-{
-	char buf[16];
-
-	if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
-		     (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
-		return;
-
-	snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
-
-	print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
-		min(200U, skb->len));
-
-	printk(KERN_DEBUG "\n");
-}
-
-void
 ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf)
 {
 	struct ath5k_desc *ds = bf->desc;
diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h
index 3e34428..b0355ae 100644
--- a/drivers/net/wireless/ath/ath5k/debug.h
+++ b/drivers/net/wireless/ath/ath5k/debug.h
@@ -116,8 +116,6 @@ enum ath5k_debug_level {
 	ATH5K_DEBUG_CALIBRATE	= 0x00000020,
 	ATH5K_DEBUG_TXPOWER	= 0x00000040,
 	ATH5K_DEBUG_LED		= 0x00000080,
-	ATH5K_DEBUG_DUMP_RX	= 0x00000100,
-	ATH5K_DEBUG_DUMP_TX	= 0x00000200,
 	ATH5K_DEBUG_DUMPBANDS	= 0x00000400,
 	ATH5K_DEBUG_DMA		= 0x00000800,
 	ATH5K_DEBUG_ANI		= 0x00002000,
@@ -152,10 +150,6 @@ void
 ath5k_debug_dump_bands(struct ath5k_softc *sc);
 
 void
-ath5k_debug_dump_skb(struct ath5k_softc *sc,
-			struct sk_buff *skb, const char *prefix, int tx);
-
-void
 ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf);
 
 #else /* no debugging */
@@ -182,10 +176,6 @@ static inline void
 ath5k_debug_dump_bands(struct ath5k_softc *sc) {}
 
 static inline void
-ath5k_debug_dump_skb(struct ath5k_softc *sc,
-			struct sk_buff *skb, const char *prefix, int tx) {}
-
-static inline void
 ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {}
 
 #endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 80e6256..b6561f7 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -72,7 +72,6 @@ static int
 ath5k_eeprom_init_header(struct ath5k_hw *ah)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	int ret;
 	u16 val;
 	u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
 
@@ -192,7 +191,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	u32 o = *offset;
 	u16 val;
-	int ret, i = 0;
+	int i = 0;
 
 	AR5K_EEPROM_READ(o++, val);
 	ee->ee_switch_settling[mode]	= (val >> 8) & 0x7f;
@@ -252,7 +251,6 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	u32 o = *offset;
 	u16 val;
-	int ret;
 
 	ee->ee_n_piers[mode] = 0;
 	AR5K_EEPROM_READ(o++, val);
@@ -515,7 +513,6 @@ ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
 	int o = *offset;
 	int i = 0;
 	u8 freq1, freq2;
-	int ret;
 	u16 val;
 
 	ee->ee_n_piers[mode] = 0;
@@ -551,7 +548,7 @@ ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
-	int i, ret;
+	int i;
 	u16 val;
 	u8 mask;
 
@@ -970,7 +967,6 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
 	u32 offset;
 	u8 i, c;
 	u16 val;
-	int ret;
 	u8 pd_gains = 0;
 
 	/* Count how many curves we have and
@@ -1228,7 +1224,7 @@ ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
 	struct ath5k_chan_pcal_info *chinfo;
 	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
 	u32 offset;
-	int idx, i, ret;
+	int idx, i;
 	u16 val;
 	u8 pd_gains = 0;
 
@@ -1419,7 +1415,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
 	u8 *rate_target_pwr_num;
 	u32 offset;
 	u16 val;
-	int ret, i;
+	int i;
 
 	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
 	rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
@@ -1593,7 +1589,7 @@ ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
 	struct ath5k_edge_power *rep;
 	unsigned int fmask, pmask;
 	unsigned int ctl_mode;
-	int ret, i, j;
+	int i, j;
 	u32 offset;
 	u16 val;
 
@@ -1733,16 +1729,12 @@ int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
 	u8 mac_d[ETH_ALEN] = {};
 	u32 total, offset;
 	u16 data;
-	int octet, ret;
+	int octet;
 
-	ret = ath5k_hw_nvram_read(ah, 0x20, &data);
-	if (ret)
-		return ret;
+	AR5K_EEPROM_READ(0x20, data);
 
 	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
-		ret = ath5k_hw_nvram_read(ah, offset, &data);
-		if (ret)
-			return ret;
+		AR5K_EEPROM_READ(offset, data);
 
 		total += data;
 		mac_d[octet + 1] = data & 0xff;
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 7c09e15..6511c27 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -241,9 +241,8 @@ enum ath5k_eeprom_freq_bands{
 #define	AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz	6250
 
 #define AR5K_EEPROM_READ(_o, _v) do {			\
-	ret = ath5k_hw_nvram_read(ah, (_o), &(_v));	\
-	if (ret)					\
-		return ret;				\
+	if (!ath5k_hw_nvram_read(ah, (_o), &(_v)))	\
+		return -EIO;				\
 } while (0)
 
 #define AR5K_EEPROM_READ_HDR(_o, _v)					\
@@ -269,29 +268,6 @@ enum ath5k_ctl_mode {
 	AR5K_CTL_MODE_M = 15,
 };
 
-/* Default CTL ids for the 3 main reg domains.
- * Atheros only uses these by default but vendors
- * can have up to 32 different CTLs for different
- * scenarios. Note that theese values are ORed with
- * the mode id (above) so we can have up to 24 CTL
- * datasets out of these 3 main regdomains. That leaves
- * 8 ids that can be used by vendors and since 0x20 is
- * missing from HAL sources i guess this is the set of
- * custom CTLs vendors can use. */
-#define	AR5K_CTL_FCC	0x10
-#define	AR5K_CTL_CUSTOM	0x20
-#define	AR5K_CTL_ETSI	0x30
-#define	AR5K_CTL_MKK	0x40
-
-/* Indicates a CTL with only mode set and
- * no reg domain mapping, such CTLs are used
- * for world roaming domains or simply when
- * a reg domain is not set */
-#define	AR5K_CTL_NO_REGDOMAIN	0xf0
-
-/* Indicates an empty (invalid) CTL */
-#define AR5K_CTL_NO_CTL		0xff
-
 /* Per channel calibration data, used for power table setup */
 struct ath5k_chan_pcal_info_rf5111 {
 	/* Power levels in half dbm units
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index d76d68c..9be29b7 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -48,28 +48,11 @@
 
 extern int ath5k_modparam_nohwcrypt;
 
-/* functions used from base.c */
-void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
-int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
-		   struct ath5k_txq *txq);
-int ath5k_init_hw(struct ath5k_softc *sc);
-int ath5k_stop_hw(struct ath5k_softc *sc);
-void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
-					struct ieee80211_vif *vif);
-int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_config(struct ath5k_softc *sc);
-void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-
 /********************\
 * Mac80211 functions *
 \********************/
 
-static int
+static void
 ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ath5k_softc *sc = hw->priv;
@@ -77,10 +60,10 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 	if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
 		dev_kfree_skb_any(skb);
-		return 0;
+		return;
 	}
 
-	return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
+	ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
 }
 
 
@@ -175,8 +158,7 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
 	memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
 
-	ath5k_mode_setup(sc, vif);
-
+	ath5k_update_bssid_mask_and_opmode(sc, vif);
 	ret = 0;
 end:
 	mutex_unlock(&sc->lock);
@@ -226,6 +208,7 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
 	struct ath5k_hw *ah = sc->ah;
 	struct ieee80211_conf *conf = &hw->conf;
 	int ret = 0;
+	int i;
 
 	mutex_lock(&sc->lock);
 
@@ -243,6 +226,14 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
 		ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
 	}
 
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+		ah->ah_retry_long = conf->long_frame_max_tx_count;
+		ah->ah_retry_short = conf->short_frame_max_tx_count;
+
+		for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++)
+			ath5k_hw_set_tx_retry_limits(ah, i);
+	}
+
 	/* TODO:
 	 * 1) Move this on config_interface and handle each case
 	 * separately eg. when we have only one STA vif, use
@@ -389,6 +380,7 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_hw *ah = sc->ah;
 	u32 mfilt[2], rfilt;
+	struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */
 
 	mutex_lock(&sc->lock);
 
@@ -462,6 +454,21 @@ ath5k_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 		break;
 	}
 
+	iter_data.hw_macaddr = NULL;
+	iter_data.n_stas = 0;
+	iter_data.need_set_hw_addr = false;
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+						   &iter_data);
+
+	/* Set up RX Filter */
+	if (iter_data.n_stas > 1) {
+		/* If you have multiple STA interfaces connected to
+		 * different APs, ARPs are not received (most of the time?)
+		 * Enabling PROMISC appears to fix that probem.
+		 */
+		rfilt |= AR5K_RX_FILTER_PROM;
+	}
+
 	/* Set filters */
 	ath5k_hw_set_rx_filter(ah, rfilt);
 
@@ -733,6 +740,47 @@ ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 }
 
 
+static void ath5k_get_ringparam(struct ieee80211_hw *hw,
+				u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	*tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
+
+	*tx_max = ATH5K_TXQ_LEN_MAX;
+	*rx = *rx_max = ATH_RXBUF;
+}
+
+
+static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
+{
+	struct ath5k_softc *sc = hw->priv;
+	u16 qnum;
+
+	/* only support setting tx ring size for now */
+	if (rx != ATH_RXBUF)
+		return -EINVAL;
+
+	/* restrict tx ring size min/max */
+	if (!tx || tx > ATH5K_TXQ_LEN_MAX)
+		return -EINVAL;
+
+	for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) {
+		if (!sc->txqs[qnum].setup)
+			continue;
+		if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
+		    sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
+			continue;
+
+		sc->txqs[qnum].txq_max = tx;
+		if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max)
+			ieee80211_stop_queue(hw, sc->txqs[qnum].qnum);
+	}
+
+	return 0;
+}
+
+
 const struct ieee80211_ops ath5k_hw_ops = {
 	.tx			= ath5k_tx,
 	.start			= ath5k_start,
@@ -771,4 +819,6 @@ const struct ieee80211_ops ath5k_hw_ops = {
 	/* .napi_poll		= not implemented */
 	.set_antenna		= ath5k_set_antenna,
 	.get_antenna		= ath5k_get_antenna,
+	.set_ringparam		= ath5k_set_ringparam,
+	.get_ringparam		= ath5k_get_ringparam,
 };
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index 7f8c5b0..66598a0 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -69,7 +69,8 @@ static void ath5k_pci_read_cachesize(struct ath_common *common, int *csz)
 /*
  * Read from eeprom
  */
-bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+static bool
+ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
 {
 	struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
 	u32 status, timeout;
@@ -90,15 +91,15 @@ bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
 		status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
 		if (status & AR5K_EEPROM_STAT_RDDONE) {
 			if (status & AR5K_EEPROM_STAT_RDERR)
-				return -EIO;
+				return false;
 			*data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
 					0xffff);
-			return 0;
+			return true;
 		}
 		udelay(15);
 	}
 
-	return -ETIMEDOUT;
+	return false;
 }
 
 int ath5k_hw_read_srev(struct ath5k_hw *ah)
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 2c9c9e7..3343fb9 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -228,24 +228,9 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
 /*
  * Set tx retry limits on DCU
  */
-static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
-					unsigned int queue)
+void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
+				  unsigned int queue)
 {
-	u32 retry_lg, retry_sh;
-
-	/*
-	 * Calculate and set retry limits
-	 */
-	if (ah->ah_software_retry) {
-		/* XXX Need to test this */
-		retry_lg = ah->ah_limit_tx_retries;
-		retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
-			AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
-	} else {
-		retry_lg = AR5K_INIT_LG_RETRY;
-		retry_sh = AR5K_INIT_SH_RETRY;
-	}
-
 	/* Single data queue on AR5210 */
 	if (ah->ah_version == AR5K_AR5210) {
 		struct ath5k_txq_info *tq = &ah->ah_txq[queue];
@@ -255,25 +240,26 @@ static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
 
 		ath5k_hw_reg_write(ah,
 			(tq->tqi_cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
-			| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
-				AR5K_NODCU_RETRY_LMT_SLG_RETRY)
-			| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
-				AR5K_NODCU_RETRY_LMT_SSH_RETRY)
-			| AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
-			| AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
+			| AR5K_REG_SM(ah->ah_retry_long,
+				      AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+			| AR5K_REG_SM(ah->ah_retry_short,
+				      AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+			| AR5K_REG_SM(ah->ah_retry_long,
+				      AR5K_NODCU_RETRY_LMT_LG_RETRY)
+			| AR5K_REG_SM(ah->ah_retry_short,
+				      AR5K_NODCU_RETRY_LMT_SH_RETRY),
 			AR5K_NODCU_RETRY_LMT);
 	/* DCU on AR5211+ */
 	} else {
 		ath5k_hw_reg_write(ah,
-			AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
-				AR5K_DCU_RETRY_LMT_SLG_RETRY) |
-			AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
-				AR5K_DCU_RETRY_LMT_SSH_RETRY) |
-			AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
-			AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
+			AR5K_REG_SM(ah->ah_retry_long,
+				    AR5K_DCU_RETRY_LMT_RTS)
+			| AR5K_REG_SM(ah->ah_retry_long,
+				      AR5K_DCU_RETRY_LMT_STA_RTS)
+			| AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
+				      AR5K_DCU_RETRY_LMT_STA_DATA),
 			AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
 	}
-	return;
 }
 
 /**
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h
index fd14b91..e1c9abd 100644
--- a/drivers/net/wireless/ath/ath5k/reg.h
+++ b/drivers/net/wireless/ath/ath5k/reg.h
@@ -686,16 +686,15 @@
 
 /*
  * DCU retry limit registers
+ * all these fields don't allow zero values
  */
 #define AR5K_DCU_RETRY_LMT_BASE		0x1080			/* Register Address -Queue0 DCU_RETRY_LMT */
-#define AR5K_DCU_RETRY_LMT_SH_RETRY	0x0000000f	/* Short retry limit mask */
-#define AR5K_DCU_RETRY_LMT_SH_RETRY_S	0
-#define AR5K_DCU_RETRY_LMT_LG_RETRY	0x000000f0	/* Long retry limit mask */
-#define AR5K_DCU_RETRY_LMT_LG_RETRY_S	4
-#define AR5K_DCU_RETRY_LMT_SSH_RETRY	0x00003f00	/* Station short retry limit mask (?) */
-#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S	8
-#define AR5K_DCU_RETRY_LMT_SLG_RETRY	0x000fc000	/* Station long retry limit mask (?) */
-#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S	14
+#define AR5K_DCU_RETRY_LMT_RTS		0x0000000f	/* RTS failure limit. Transmission fails if no CTS is received for this number of times */
+#define AR5K_DCU_RETRY_LMT_RTS_S	0
+#define AR5K_DCU_RETRY_LMT_STA_RTS	0x00003f00	/* STA RTS failure limit. If exceeded CW reset */
+#define AR5K_DCU_RETRY_LMT_STA_RTS_S	8
+#define AR5K_DCU_RETRY_LMT_STA_DATA	0x000fc000	/* STA data failure limit. If exceeded CW reset. */
+#define AR5K_DCU_RETRY_LMT_STA_DATA_S	14
 #define	AR5K_QUEUE_DFS_RETRY_LIMIT(_q)	AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
 
 /*
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
new file mode 100644
index 0000000..2de68ad
--- /dev/null
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -0,0 +1,107 @@
+#if !defined(__TRACE_ATH5K_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_ATH5K_H
+
+#include <linux/tracepoint.h>
+#include "base.h"
+
+#ifndef CONFIG_ATH5K_TRACER
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+struct sk_buff;
+
+#define PRIV_ENTRY  __field(struct ath5k_softc *, priv)
+#define PRIV_ASSIGN __entry->priv = priv
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ath5k
+
+TRACE_EVENT(ath5k_rx,
+	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb),
+	TP_ARGS(priv, skb),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(unsigned long, skbaddr)
+		__dynamic_array(u8, frame, skb->len)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->skbaddr = (unsigned long) skb;
+		memcpy(__get_dynamic_array(frame), skb->data, skb->len);
+	),
+	TP_printk(
+		"[%p] RX skb=%lx", __entry->priv, __entry->skbaddr
+	)
+);
+
+TRACE_EVENT(ath5k_tx,
+	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+		 struct ath5k_txq *q),
+
+	TP_ARGS(priv, skb, q),
+
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(unsigned long, skbaddr)
+		__field(u8, qnum)
+		__dynamic_array(u8, frame, skb->len)
+	),
+
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->skbaddr = (unsigned long) skb;
+		__entry->qnum = (u8) q->qnum;
+		memcpy(__get_dynamic_array(frame), skb->data, skb->len);
+	),
+
+	TP_printk(
+		"[%p] TX skb=%lx q=%d", __entry->priv, __entry->skbaddr,
+		__entry->qnum
+	)
+);
+
+TRACE_EVENT(ath5k_tx_complete,
+	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+		 struct ath5k_txq *q, struct ath5k_tx_status *ts),
+
+	TP_ARGS(priv, skb, q, ts),
+
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(unsigned long, skbaddr)
+		__field(u8, qnum)
+		__field(u8, ts_status)
+		__field(s8, ts_rssi)
+		__field(u8, ts_antenna)
+	),
+
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->skbaddr = (unsigned long) skb;
+		__entry->qnum = (u8) q->qnum;
+		__entry->ts_status = ts->ts_status;
+		__entry->ts_rssi =  ts->ts_rssi;
+		__entry->ts_antenna = ts->ts_antenna;
+	),
+
+	TP_printk(
+		"[%p] TX end skb=%lx q=%d stat=%x rssi=%d ant=%x",
+		__entry->priv, __entry->skbaddr, __entry->qnum,
+		__entry->ts_status, __entry->ts_rssi, __entry->ts_antenna
+	)
+);
+
+#endif /* __TRACE_ATH5K_H */
+
+#ifdef CONFIG_ATH5K_TRACER
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+#include <trace/define_trace.h>
+
+#endif
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index aca0162..4d66ca8 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -4,7 +4,6 @@ ath9k-y +=	beacon.o \
 		main.o \
 		recv.o \
 		xmit.o \
-		virtual.o \
 
 ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_PCI) += pci.o
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 25a6e44..9cb0efa 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -54,7 +54,6 @@ static struct ath_bus_ops ath_ahb_bus_ops  = {
 static int ath_ahb_probe(struct platform_device *pdev)
 {
 	void __iomem *mem;
-	struct ath_wiphy *aphy;
 	struct ath_softc *sc;
 	struct ieee80211_hw *hw;
 	struct resource *res;
@@ -76,7 +75,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
 		goto err_out;
 	}
 
-	mem = ioremap_nocache(res->start, res->end - res->start + 1);
+	mem = ioremap_nocache(res->start, resource_size(res));
 	if (mem == NULL) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENOMEM;
@@ -92,8 +91,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
 
 	irq = res->start;
 
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
-				sizeof(struct ath_softc), &ath9k_ops);
+	hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
 	if (hw == NULL) {
 		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
 		ret = -ENOMEM;
@@ -103,11 +101,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	platform_set_drvdata(pdev, hw);
 
-	aphy = hw->priv;
-	sc = (struct ath_softc *) (aphy + 1);
-	aphy->sc = sc;
-	aphy->hw = hw;
-	sc->pri_wiphy = aphy;
+	sc = hw->priv;
 	sc->hw = hw;
 	sc->dev = &pdev->dev;
 	sc->mem = mem;
@@ -151,8 +145,7 @@ static int ath_ahb_remove(struct platform_device *pdev)
 	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
 
 	if (hw) {
-		struct ath_wiphy *aphy = hw->priv;
-		struct ath_softc *sc = aphy->sc;
+		struct ath_softc *sc = hw->priv;
 		void __iomem *mem = sc->mem;
 
 		ath9k_deinit_device(sc);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 5e300bd..76388c6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -805,7 +805,10 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
+	if (AR_SREV_9271(ah)) {
+		if (!ar9285_hw_cl_cal(ah, chan))
+			return false;
+	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
 		if (!ar9285_hw_clc(ah, chan))
 			return false;
 	} else {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 4819747..4a92718 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3673,7 +3673,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
 				return;
 
 			reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
-				      (7 << 14) | (6 << 17) | (1 << 20) |
+				      (2 << 14) | (6 << 17) | (1 << 20) |
 				      (3 << 24) | (1 << 28);
 
 			REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
@@ -3959,19 +3959,19 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 {
 #define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
 	/* make sure forced gain is not set */
-	REG_WRITE(ah, 0xa458, 0);
+	REG_WRITE(ah, AR_PHY_TX_FORCED_GAIN, 0);
 
 	/* Write the OFDM power per rate set */
 
 	/* 6 (LSB), 9, 12, 18 (MSB) */
-	REG_WRITE(ah, 0xa3c0,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(0),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
 
 	/* 24 (LSB), 36, 48, 54 (MSB) */
-	REG_WRITE(ah, 0xa3c4,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(1),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
@@ -3980,14 +3980,14 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	/* Write the CCK power per rate set */
 
 	/* 1L (LSB), reserved, 2L, 2S (MSB) */
-	REG_WRITE(ah, 0xa3c8,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(2),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
 		  /* POW_SM(txPowerTimes2,  8) | this is reserved for AR9003 */
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
 
 	/* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
-	REG_WRITE(ah, 0xa3cc,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(3),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
@@ -3997,7 +3997,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	/* Write the HT20 power per rate set */
 
 	/* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
-	REG_WRITE(ah, 0xa3d0,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(4),
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
@@ -4005,7 +4005,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	    );
 
 	/* 6 (LSB), 7, 12, 13 (MSB) */
-	REG_WRITE(ah, 0xa3d4,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(5),
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
@@ -4013,7 +4013,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	    );
 
 	/* 14 (LSB), 15, 20, 21 */
-	REG_WRITE(ah, 0xa3e4,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(9),
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
@@ -4023,7 +4023,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	/* Mixed HT20 and HT40 rates */
 
 	/* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
-	REG_WRITE(ah, 0xa3e8,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(10),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
@@ -4035,7 +4035,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	 * correct PAR difference between HT40 and HT20/LEGACY
 	 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
 	 */
-	REG_WRITE(ah, 0xa3d8,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(6),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
@@ -4043,7 +4043,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	    );
 
 	/* 6 (LSB), 7, 12, 13 (MSB) */
-	REG_WRITE(ah, 0xa3dc,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(7),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
@@ -4051,7 +4051,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
 	    );
 
 	/* 14 (LSB), 15, 20, 21 */
-	REG_WRITE(ah, 0xa3ec,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(11),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 06fb2c8..7f5de6e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -28,7 +28,67 @@
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-	if (AR_SREV_9485(ah)) {
+	if (AR_SREV_9485_11(ah)) {
+		/* mac */
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+				ar9485_1_1_mac_core,
+				ARRAY_SIZE(ar9485_1_1_mac_core), 2);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+				ar9485_1_1_mac_postamble,
+				ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
+
+		/* bb */
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
+				ARRAY_SIZE(ar9485_1_1), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				ar9485_1_1_baseband_core,
+				ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				ar9485_1_1_baseband_postamble,
+				ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
+
+		/* radio */
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+				ar9485_1_1_radio_core,
+				ARRAY_SIZE(ar9485_1_1_radio_core), 2);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+				ar9485_1_1_radio_postamble,
+				ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
+
+		/* soc */
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+				ar9485_1_1_soc_preamble,
+				ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
+
+		/* rx/tx gain */
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9485_common_rx_gain_1_1,
+				ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9485_modes_lowest_ob_db_tx_gain_1_1,
+				ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+				5);
+
+		/* Load PCIE SERDES settings from INI */
+
+		/* Awake Setting */
+
+		INIT_INI_ARRAY(&ah->iniPcieSerdes,
+				ar9485_1_1_pcie_phy_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+				2);
+
+		/* Sleep Setting */
+
+		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+				ar9485_1_1_pcie_phy_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+				2);
+	} else if (AR_SREV_9485(ah)) {
 		/* mac */
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -85,8 +145,8 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 		/* Sleep Setting */
 
 		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-				ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1,
-				ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1),
+				ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1),
 				2);
 	} else {
 		/* mac */
@@ -163,7 +223,12 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 	switch (ar9003_hw_get_tx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485_modes_lowest_ob_db_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_lowest_ob_db_tx_gain_1_0,
 				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
@@ -175,10 +240,15 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 				       5);
 		break;
 	case 1:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_high_ob_db_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_high_ob_db_tx_gain_1_0,
-				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_0),
 				       5);
 		else
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
@@ -187,10 +257,15 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 				       5);
 		break;
 	case 2:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_low_ob_db_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_low_ob_db_tx_gain_1_0,
-				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_0),
 				       5);
 		else
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
@@ -199,7 +274,12 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
 				       5);
 		break;
 	case 3:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_high_power_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_high_power_tx_gain_1_0,
 				       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0),
@@ -218,7 +298,12 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
 	switch (ar9003_hw_get_rx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9485_common_rx_gain_1_1,
+				       ARRAY_SIZE(ar9485_common_rx_gain_1_1),
+				       2);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesRxGain,
 				       ar9485Common_rx_gain_1_0,
 				       ARRAY_SIZE(ar9485Common_rx_gain_1_0),
@@ -230,7 +315,12 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
 				       2);
 		break;
 	case 1:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9485Common_wo_xlna_rx_gain_1_1,
+				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+				       2);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesRxGain,
 				       ar9485Common_wo_xlna_rx_gain_1_0,
 				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0),
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 4ceddbb..038a0cb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -615,7 +615,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 		 */
 		if (rxsp->status11 & AR_CRCErr)
 			rxs->rs_status |= ATH9K_RXERR_CRC;
-		if (rxsp->status11 & AR_PHYErr) {
+		else if (rxsp->status11 & AR_PHYErr) {
 			phyerr = MS(rxsp->status11, AR_PHYErrCode);
 			/*
 			 * If we reach a point here where AR_PostDelimCRCErr is
@@ -638,11 +638,11 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
 				rxs->rs_phyerr = phyerr;
 			}
 
-		}
-		if (rxsp->status11 & AR_DecryptCRCErr)
+		} else if (rxsp->status11 & AR_DecryptCRCErr)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
-		if (rxsp->status11 & AR_MichaelErr)
+		else if (rxsp->status11 & AR_MichaelErr)
 			rxs->rs_status |= ATH9K_RXERR_MIC;
+
 		if (rxsp->status11 & AR_KeyMiss)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 8d60f4f..eb250d6 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1020,28 +1020,29 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
 static void ar9003_hw_do_getnf(struct ath_hw *ah,
 			      int16_t nfarray[NUM_NF_READINGS])
 {
-	int16_t nf;
-
-	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend32(nf, 8);
-
-	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend32(nf, 8);
+#define AR_PHY_CH_MINCCA_PWR	0x1FF00000
+#define AR_PHY_CH_MINCCA_PWR_S	20
+#define AR_PHY_CH_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_CH_EXT_MINCCA_PWR_S 16
 
-	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
-	nfarray[2] = sign_extend32(nf, 8);
-
-	if (!IS_CHAN_HT40(ah->curchan))
-		return;
+	int16_t nf;
+	int i;
 
-	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
-	nfarray[3] = sign_extend32(nf, 8);
+	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+		if (ah->rxchainmask & BIT(i)) {
+			nf = MS(REG_READ(ah, ah->nf_regs[i]),
+					 AR_PHY_CH_MINCCA_PWR);
+			nfarray[i] = sign_extend32(nf, 8);
 
-	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
-	nfarray[4] = sign_extend32(nf, 8);
+			if (IS_CHAN_HT40(ah->curchan)) {
+				u8 ext_idx = AR9300_MAX_CHAINS + i;
 
-	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
-	nfarray[5] = sign_extend32(nf, 8);
+				nf = MS(REG_READ(ah, ah->nf_regs[ext_idx]),
+						 AR_PHY_CH_EXT_MINCCA_PWR);
+				nfarray[ext_idx] = sign_extend32(nf, 8);
+			}
+		}
+	}
 }
 
 static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index 59bab6b..8bdda2c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -486,6 +486,8 @@
 #define AR_PHY_HEAVYCLIP_40      (AR_SM_BASE + 0x1ac)
 #define AR_PHY_ILLEGAL_TXRATE    (AR_SM_BASE + 0x1b0)
 
+#define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2))
+
 #define AR_PHY_PWRTX_MAX         (AR_SM_BASE + 0x1f0)
 #define AR_PHY_POWER_TX_SUB      (AR_SM_BASE + 0x1f4)
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index 70de3d8..71cc0a3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -667,6 +667,7 @@ static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = {
 
 static const u32 ar9485_1_0_soc_preamble[][2] = {
 	/*   Addr     allmodes */
+	{0x00004090, 0x00aa10aa},
 	{0x000040a4, 0x00a0c9c9},
 	{0x00007048, 0x00000004},
 };
@@ -940,4 +941,1146 @@ static const u32 ar9485_1_0_mac_core[][2] = {
 	{0x000083cc, 0x00000200},
 	{0x000083d0, 0x000301ff},
 };
+
+static const u32 ar9485_1_1_mac_core[][2] = {
+	/*  Addr       allmodes */
+	{0x00000008, 0x00000000},
+	{0x00000030, 0x00020085},
+	{0x00000034, 0x00000005},
+	{0x00000040, 0x00000000},
+	{0x00000044, 0x00000000},
+	{0x00000048, 0x00000008},
+	{0x0000004c, 0x00000010},
+	{0x00000050, 0x00000000},
+	{0x00001040, 0x002ffc0f},
+	{0x00001044, 0x002ffc0f},
+	{0x00001048, 0x002ffc0f},
+	{0x0000104c, 0x002ffc0f},
+	{0x00001050, 0x002ffc0f},
+	{0x00001054, 0x002ffc0f},
+	{0x00001058, 0x002ffc0f},
+	{0x0000105c, 0x002ffc0f},
+	{0x00001060, 0x002ffc0f},
+	{0x00001064, 0x002ffc0f},
+	{0x000010f0, 0x00000100},
+	{0x00001270, 0x00000000},
+	{0x000012b0, 0x00000000},
+	{0x000012f0, 0x00000000},
+	{0x0000143c, 0x00000000},
+	{0x0000147c, 0x00000000},
+	{0x00008000, 0x00000000},
+	{0x00008004, 0x00000000},
+	{0x00008008, 0x00000000},
+	{0x0000800c, 0x00000000},
+	{0x00008018, 0x00000000},
+	{0x00008020, 0x00000000},
+	{0x00008038, 0x00000000},
+	{0x0000803c, 0x00000000},
+	{0x00008040, 0x00000000},
+	{0x00008044, 0x00000000},
+	{0x00008048, 0x00000000},
+	{0x0000804c, 0xffffffff},
+	{0x00008054, 0x00000000},
+	{0x00008058, 0x00000000},
+	{0x0000805c, 0x000fc78f},
+	{0x00008060, 0x0000000f},
+	{0x00008064, 0x00000000},
+	{0x00008070, 0x00000310},
+	{0x00008074, 0x00000020},
+	{0x00008078, 0x00000000},
+	{0x0000809c, 0x0000000f},
+	{0x000080a0, 0x00000000},
+	{0x000080a4, 0x02ff0000},
+	{0x000080a8, 0x0e070605},
+	{0x000080ac, 0x0000000d},
+	{0x000080b0, 0x00000000},
+	{0x000080b4, 0x00000000},
+	{0x000080b8, 0x00000000},
+	{0x000080bc, 0x00000000},
+	{0x000080c0, 0x2a800000},
+	{0x000080c4, 0x06900168},
+	{0x000080c8, 0x13881c22},
+	{0x000080cc, 0x01f40000},
+	{0x000080d0, 0x00252500},
+	{0x000080d4, 0x00a00000},
+	{0x000080d8, 0x00400000},
+	{0x000080dc, 0x00000000},
+	{0x000080e0, 0xffffffff},
+	{0x000080e4, 0x0000ffff},
+	{0x000080e8, 0x3f3f3f3f},
+	{0x000080ec, 0x00000000},
+	{0x000080f0, 0x00000000},
+	{0x000080f4, 0x00000000},
+	{0x000080fc, 0x00020000},
+	{0x00008100, 0x00000000},
+	{0x00008108, 0x00000052},
+	{0x0000810c, 0x00000000},
+	{0x00008110, 0x00000000},
+	{0x00008114, 0x000007ff},
+	{0x00008118, 0x000000aa},
+	{0x0000811c, 0x00003210},
+	{0x00008124, 0x00000000},
+	{0x00008128, 0x00000000},
+	{0x0000812c, 0x00000000},
+	{0x00008130, 0x00000000},
+	{0x00008134, 0x00000000},
+	{0x00008138, 0x00000000},
+	{0x0000813c, 0x0000ffff},
+	{0x00008144, 0xffffffff},
+	{0x00008168, 0x00000000},
+	{0x0000816c, 0x00000000},
+	{0x00008170, 0x18486200},
+	{0x00008174, 0x33332210},
+	{0x00008178, 0x00000000},
+	{0x0000817c, 0x00020000},
+	{0x000081c0, 0x00000000},
+	{0x000081c4, 0x33332210},
+	{0x000081d4, 0x00000000},
+	{0x000081ec, 0x00000000},
+	{0x000081f0, 0x00000000},
+	{0x000081f4, 0x00000000},
+	{0x000081f8, 0x00000000},
+	{0x000081fc, 0x00000000},
+	{0x00008240, 0x00100000},
+	{0x00008244, 0x0010f400},
+	{0x00008248, 0x00000800},
+	{0x0000824c, 0x0001e800},
+	{0x00008250, 0x00000000},
+	{0x00008254, 0x00000000},
+	{0x00008258, 0x00000000},
+	{0x0000825c, 0x40000000},
+	{0x00008260, 0x00080922},
+	{0x00008264, 0x9ca00010},
+	{0x00008268, 0xffffffff},
+	{0x0000826c, 0x0000ffff},
+	{0x00008270, 0x00000000},
+	{0x00008274, 0x40000000},
+	{0x00008278, 0x003e4180},
+	{0x0000827c, 0x00000004},
+	{0x00008284, 0x0000002c},
+	{0x00008288, 0x0000002c},
+	{0x0000828c, 0x000000ff},
+	{0x00008294, 0x00000000},
+	{0x00008298, 0x00000000},
+	{0x0000829c, 0x00000000},
+	{0x00008300, 0x00000140},
+	{0x00008314, 0x00000000},
+	{0x0000831c, 0x0000010d},
+	{0x00008328, 0x00000000},
+	{0x0000832c, 0x00000007},
+	{0x00008330, 0x00000302},
+	{0x00008334, 0x00000700},
+	{0x00008338, 0x00ff0000},
+	{0x0000833c, 0x02400000},
+	{0x00008340, 0x000107ff},
+	{0x00008344, 0xa248105b},
+	{0x00008348, 0x008f0000},
+	{0x0000835c, 0x00000000},
+	{0x00008360, 0xffffffff},
+	{0x00008364, 0xffffffff},
+	{0x00008368, 0x00000000},
+	{0x00008370, 0x00000000},
+	{0x00008374, 0x000000ff},
+	{0x00008378, 0x00000000},
+	{0x0000837c, 0x00000000},
+	{0x00008380, 0xffffffff},
+	{0x00008384, 0xffffffff},
+	{0x00008390, 0xffffffff},
+	{0x00008394, 0xffffffff},
+	{0x00008398, 0x00000000},
+	{0x0000839c, 0x00000000},
+	{0x000083a0, 0x00000000},
+	{0x000083a4, 0x0000fa14},
+	{0x000083a8, 0x000f0c00},
+	{0x000083ac, 0x33332210},
+	{0x000083b0, 0x33332210},
+	{0x000083b4, 0x33332210},
+	{0x000083b8, 0x33332210},
+	{0x000083bc, 0x00000000},
+	{0x000083c0, 0x00000000},
+	{0x000083c4, 0x00000000},
+	{0x000083c8, 0x00000000},
+	{0x000083cc, 0x00000200},
+	{0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9485_1_1_baseband_core[][2] = {
+	/* Addr       allmodes */
+	{0x00009800, 0xafe68e30},
+	{0x00009804, 0xfd14e000},
+	{0x00009808, 0x9c0a8f6b},
+	{0x0000980c, 0x04800000},
+	{0x00009814, 0x9280c00a},
+	{0x00009818, 0x00000000},
+	{0x0000981c, 0x00020028},
+	{0x00009834, 0x5f3ca3de},
+	{0x00009838, 0x0108ecff},
+	{0x0000983c, 0x14750600},
+	{0x00009880, 0x201fff00},
+	{0x00009884, 0x00001042},
+	{0x000098a4, 0x00200400},
+	{0x000098b0, 0x52440bbe},
+	{0x000098d0, 0x004b6a8e},
+	{0x000098d4, 0x00000820},
+	{0x000098dc, 0x00000000},
+	{0x000098f0, 0x00000000},
+	{0x000098f4, 0x00000000},
+	{0x00009c04, 0x00000000},
+	{0x00009c08, 0x03200000},
+	{0x00009c0c, 0x00000000},
+	{0x00009c10, 0x00000000},
+	{0x00009c14, 0x00046384},
+	{0x00009c18, 0x05b6b440},
+	{0x00009c1c, 0x00b6b440},
+	{0x00009d00, 0xc080a333},
+	{0x00009d04, 0x40206c10},
+	{0x00009d08, 0x009c4060},
+	{0x00009d0c, 0x1883800a},
+	{0x00009d10, 0x01834061},
+	{0x00009d14, 0x00c00400},
+	{0x00009d18, 0x00000000},
+	{0x00009d1c, 0x00000000},
+	{0x00009e08, 0x0038233c},
+	{0x00009e24, 0x9927b515},
+	{0x00009e28, 0x12ef0200},
+	{0x00009e30, 0x06336f77},
+	{0x00009e34, 0x6af6532f},
+	{0x00009e38, 0x0cc80c00},
+	{0x00009e40, 0x0d261820},
+	{0x00009e4c, 0x00001004},
+	{0x00009e50, 0x00ff03f1},
+	{0x00009fc0, 0x80be4788},
+	{0x00009fc4, 0x0001efb5},
+	{0x00009fcc, 0x40000014},
+	{0x0000a20c, 0x00000000},
+	{0x0000a210, 0x00000000},
+	{0x0000a220, 0x00000000},
+	{0x0000a224, 0x00000000},
+	{0x0000a228, 0x10002310},
+	{0x0000a23c, 0x00000000},
+	{0x0000a244, 0x0c000000},
+	{0x0000a2a0, 0x00000001},
+	{0x0000a2c0, 0x00000001},
+	{0x0000a2c8, 0x00000000},
+	{0x0000a2cc, 0x18c43433},
+	{0x0000a2d4, 0x00000000},
+	{0x0000a2dc, 0x00000000},
+	{0x0000a2e0, 0x00000000},
+	{0x0000a2e4, 0x00000000},
+	{0x0000a2e8, 0x00000000},
+	{0x0000a2ec, 0x00000000},
+	{0x0000a2f0, 0x00000000},
+	{0x0000a2f4, 0x00000000},
+	{0x0000a2f8, 0x00000000},
+	{0x0000a344, 0x00000000},
+	{0x0000a34c, 0x00000000},
+	{0x0000a350, 0x0000a000},
+	{0x0000a364, 0x00000000},
+	{0x0000a370, 0x00000000},
+	{0x0000a390, 0x00000001},
+	{0x0000a394, 0x00000444},
+	{0x0000a398, 0x001f0e0f},
+	{0x0000a39c, 0x0075393f},
+	{0x0000a3a0, 0xb79f6427},
+	{0x0000a3a4, 0x000000ff},
+	{0x0000a3a8, 0x3b3b3b3b},
+	{0x0000a3ac, 0x2f2f2f2f},
+	{0x0000a3c0, 0x20202020},
+	{0x0000a3c4, 0x22222220},
+	{0x0000a3c8, 0x20200020},
+	{0x0000a3cc, 0x20202020},
+	{0x0000a3d0, 0x20202020},
+	{0x0000a3d4, 0x20202020},
+	{0x0000a3d8, 0x20202020},
+	{0x0000a3dc, 0x20202020},
+	{0x0000a3e0, 0x20202020},
+	{0x0000a3e4, 0x20202020},
+	{0x0000a3e8, 0x20202020},
+	{0x0000a3ec, 0x20202020},
+	{0x0000a3f0, 0x00000000},
+	{0x0000a3f4, 0x00000006},
+	{0x0000a3f8, 0x0cdbd380},
+	{0x0000a3fc, 0x000f0f01},
+	{0x0000a400, 0x8fa91f01},
+	{0x0000a404, 0x00000000},
+	{0x0000a408, 0x0e79e5c6},
+	{0x0000a40c, 0x00820820},
+	{0x0000a414, 0x1ce739cf},
+	{0x0000a418, 0x2d0019ce},
+	{0x0000a41c, 0x1ce739ce},
+	{0x0000a420, 0x000001ce},
+	{0x0000a424, 0x1ce739ce},
+	{0x0000a428, 0x000001ce},
+	{0x0000a42c, 0x1ce739ce},
+	{0x0000a430, 0x1ce739ce},
+	{0x0000a434, 0x00000000},
+	{0x0000a438, 0x00001801},
+	{0x0000a43c, 0x00000000},
+	{0x0000a440, 0x00000000},
+	{0x0000a444, 0x00000000},
+	{0x0000a448, 0x04000000},
+	{0x0000a44c, 0x00000001},
+	{0x0000a450, 0x00010000},
+	{0x0000a5c4, 0xbfad9d74},
+	{0x0000a5c8, 0x0048060a},
+	{0x0000a5cc, 0x00000637},
+	{0x0000a760, 0x03020100},
+	{0x0000a764, 0x09080504},
+	{0x0000a768, 0x0d0c0b0a},
+	{0x0000a76c, 0x13121110},
+	{0x0000a770, 0x31301514},
+	{0x0000a774, 0x35343332},
+	{0x0000a778, 0x00000036},
+	{0x0000a780, 0x00000838},
+	{0x0000a7c0, 0x00000000},
+	{0x0000a7c4, 0xfffffffc},
+	{0x0000a7c8, 0x00000000},
+	{0x0000a7cc, 0x00000000},
+	{0x0000a7d0, 0x00000000},
+	{0x0000a7d4, 0x00000004},
+	{0x0000a7dc, 0x00000000},
+};
+
+static const u32 ar9485Common_1_1[][2] = {
+	/*  Addr      allmodes */
+	{0x00007010, 0x00000022},
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000004c2},
+};
+
+static const u32 ar9485_1_1_baseband_postamble[][5] = {
+	/* Addr       5G_HT20        5G_HT40       2G_HT40       2G_HT20 */
+	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
+	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+	{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
+	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+	{0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
+	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+	{0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+	{0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
+	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+	{0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20  */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1_radio_postamble[][2] = {
+	/* Addr        allmodes */
+	{0x0001609c, 0x0b283f31},
+	{0x000160ac, 0x24611800},
+	{0x000160b0, 0x03284f3e},
+	{0x0001610c, 0x00170000},
+	{0x00016140, 0x10804008},
+};
+
+static const u32 ar9485_1_1_mac_postamble[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9485_1_1_radio_core[][2] = {
+	/* Addr        allmodes */
+	{0x00016000, 0x36db6db6},
+	{0x00016004, 0x6db6db40},
+	{0x00016008, 0x73800000},
+	{0x0001600c, 0x00000000},
+	{0x00016040, 0x7f80fff8},
+	{0x0001604c, 0x000f0278},
+	{0x00016050, 0x4db6db8c},
+	{0x00016054, 0x6db60000},
+	{0x00016080, 0x00080000},
+	{0x00016084, 0x0e48048c},
+	{0x00016088, 0x14214514},
+	{0x0001608c, 0x119f081e},
+	{0x00016090, 0x24926490},
+	{0x00016098, 0xd28b3330},
+	{0x000160a0, 0xc2108ffe},
+	{0x000160a4, 0x812fc370},
+	{0x000160a8, 0x423c8000},
+	{0x000160b4, 0x92480040},
+	{0x000160c0, 0x006db6db},
+	{0x000160c4, 0x0186db60},
+	{0x000160c8, 0x6db6db6c},
+	{0x000160cc, 0x6de6fbe0},
+	{0x000160d0, 0xf7dfcf3c},
+	{0x00016100, 0x04cb0001},
+	{0x00016104, 0xfff80015},
+	{0x00016108, 0x00080010},
+	{0x00016144, 0x01884080},
+	{0x00016148, 0x00008040},
+	{0x00016240, 0x08400000},
+	{0x00016244, 0x1bf90f00},
+	{0x00016248, 0x00000000},
+	{0x0001624c, 0x00000000},
+	{0x00016280, 0x01000015},
+	{0x00016284, 0x00d30000},
+	{0x00016288, 0x00318000},
+	{0x0001628c, 0x50000000},
+	{0x00016290, 0x4b96210f},
+	{0x00016380, 0x00000000},
+	{0x00016384, 0x00000000},
+	{0x00016388, 0x00800700},
+	{0x0001638c, 0x00800700},
+	{0x00016390, 0x00800700},
+	{0x00016394, 0x00000000},
+	{0x00016398, 0x00000000},
+	{0x0001639c, 0x00000000},
+	{0x000163a0, 0x00000001},
+	{0x000163a4, 0x00000001},
+	{0x000163a8, 0x00000000},
+	{0x000163ac, 0x00000000},
+	{0x000163b0, 0x00000000},
+	{0x000163b4, 0x00000000},
+	{0x000163b8, 0x00000000},
+	{0x000163bc, 0x00000000},
+	{0x000163c0, 0x000000a0},
+	{0x000163c4, 0x000c0000},
+	{0x000163c8, 0x14021402},
+	{0x000163cc, 0x00001402},
+	{0x000163d0, 0x00000000},
+	{0x000163d4, 0x00000000},
+	{0x00016c40, 0x13188278},
+	{0x00016c44, 0x12000000},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
+	/* Addr        allmodes */
+	{0x00018c00, 0x10052e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1[][2] = {
+	/* Addr        allmodes */
+	{0x0000a580, 0x00000000},
+	{0x0000a584, 0x00000000},
+	{0x0000a588, 0x00000000},
+	{0x0000a58c, 0x00000000},
+	{0x0000a590, 0x00000000},
+	{0x0000a594, 0x00000000},
+	{0x0000a598, 0x00000000},
+	{0x0000a59c, 0x00000000},
+	{0x0000a5a0, 0x00000000},
+	{0x0000a5a4, 0x00000000},
+	{0x0000a5a8, 0x00000000},
+	{0x0000a5ac, 0x00000000},
+	{0x0000a5b0, 0x00000000},
+	{0x0000a5b4, 0x00000000},
+	{0x0000a5b8, 0x00000000},
+	{0x0000a5bc, 0x00000000},
+};
+
+static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
+	{0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a},
+	{0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a},
+	{0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a},
+	{0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
+	/* Addr        allmodes */
+	{0x00018c00, 0x10013e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_soc_preamble[][2] = {
+	/* Addr        allmodes */
+	{0x00004014, 0xba280400},
+	{0x00004090, 0x00aa10aa},
+	{0x000040a4, 0x00a0c9c9},
+	{0x00007010, 0x00000022},
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000004c2},
+	{0x00007048, 0x00000002},
+};
+
+static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
+	/* Addr        allmodes */
+	{0x0000a398, 0x00000000},
+	{0x0000a39c, 0x6f7f0301},
+	{0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20  */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
+	/* Addr        5G_HT2        5G_HT40  */
+	{0x00009e00, 0x03721821, 0x03721821},
+	{0x0000a230, 0x0000400b, 0x00004016},
+	{0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
+	/* Addr        allmodes  */
+	{0x00018c00, 0x10012e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_common_rx_gain_1_1[][2] = {
+	/* Addr        allmodes */
+	{0x0000a000, 0x00010000},
+	{0x0000a004, 0x00030002},
+	{0x0000a008, 0x00050004},
+	{0x0000a00c, 0x00810080},
+	{0x0000a010, 0x01800082},
+	{0x0000a014, 0x01820181},
+	{0x0000a018, 0x01840183},
+	{0x0000a01c, 0x01880185},
+	{0x0000a020, 0x018a0189},
+	{0x0000a024, 0x02850284},
+	{0x0000a028, 0x02890288},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x21212128},
+	{0x0000a098, 0x171c1c1c},
+	{0x0000a09c, 0x02020212},
+	{0x0000a0a0, 0x00000202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x001f0000},
+	{0x0000a0c4, 0x111f1100},
+	{0x0000a0c8, 0x111d111e},
+	{0x0000a0cc, 0x111b111c},
+	{0x0000a0d0, 0x22032204},
+	{0x0000a0d4, 0x22012202},
+	{0x0000a0d8, 0x221f2200},
+	{0x0000a0dc, 0x221d221e},
+	{0x0000a0e0, 0x33013302},
+	{0x0000a0e4, 0x331f3300},
+	{0x0000a0e8, 0x4402331e},
+	{0x0000a0ec, 0x44004401},
+	{0x0000a0f0, 0x441e441f},
+	{0x0000a0f4, 0x55015502},
+	{0x0000a0f8, 0x551f5500},
+	{0x0000a0fc, 0x6602551e},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
+	/* Addr        allmodes */
+	{0x00018c00, 0x10053e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
+	/* Addr        allmodes */
+	{0x0000a000, 0x00060005},
+	{0x0000a004, 0x00810080},
+	{0x0000a008, 0x00830082},
+	{0x0000a00c, 0x00850084},
+	{0x0000a010, 0x01820181},
+	{0x0000a014, 0x01840183},
+	{0x0000a018, 0x01880185},
+	{0x0000a01c, 0x018a0189},
+	{0x0000a020, 0x02850284},
+	{0x0000a024, 0x02890288},
+	{0x0000a028, 0x028b028a},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x24242428},
+	{0x0000a098, 0x171e1e1e},
+	{0x0000a09c, 0x02020b0b},
+	{0x0000a0a0, 0x02020202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x22072208},
+	{0x0000a0c4, 0x22052206},
+	{0x0000a0c8, 0x22032204},
+	{0x0000a0cc, 0x22012202},
+	{0x0000a0d0, 0x221f2200},
+	{0x0000a0d4, 0x221d221e},
+	{0x0000a0d8, 0x33023303},
+	{0x0000a0dc, 0x33003301},
+	{0x0000a0e0, 0x331e331f},
+	{0x0000a0e4, 0x4402331d},
+	{0x0000a0e8, 0x44004401},
+	{0x0000a0ec, 0x441e441f},
+	{0x0000a0f0, 0x55025503},
+	{0x0000a0f4, 0x55005501},
+	{0x0000a0f8, 0x551e551f},
+	{0x0000a0fc, 0x6602551d},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
 #endif
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 1a7fa6e..099bd41 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -92,9 +92,9 @@ struct ath_config {
  * @BUF_XRETRY: To denote excessive retries of the buffer
  */
 enum buffer_type {
-	BUF_AMPDU		= BIT(2),
-	BUF_AGGR		= BIT(3),
-	BUF_XRETRY		= BIT(5),
+	BUF_AMPDU		= BIT(0),
+	BUF_AGGR		= BIT(1),
+	BUF_XRETRY		= BIT(2),
 };
 
 #define bf_isampdu(bf)		(bf->bf_state.bf_type & BUF_AMPDU)
@@ -134,7 +134,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
 	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
 	 WME_AC_VO)
 
-#define ADDBA_EXCHANGE_ATTEMPTS    10
 #define ATH_AGGR_DELIM_SZ          4
 #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
 /* number of delimiters for encryption padding */
@@ -181,7 +180,8 @@ enum ATH_AGGR_STATUS {
 
 #define ATH_TXFIFO_DEPTH 8
 struct ath_txq {
-	u32 axq_qnum;
+	int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
+	u32 axq_qnum; /* ath9k hardware queue number */
 	u32 *axq_link;
 	struct list_head axq_q;
 	spinlock_t axq_lock;
@@ -231,7 +231,6 @@ struct ath_buf {
 	bool bf_stale;
 	u16 bf_flags;
 	struct ath_buf_state bf_state;
-	struct ath_wiphy *aphy;
 };
 
 struct ath_atx_tid {
@@ -252,7 +251,10 @@ struct ath_atx_tid {
 };
 
 struct ath_node {
-	struct ath_common *common;
+#ifdef CONFIG_ATH9K_DEBUGFS
+	struct list_head list; /* for sc->nodes */
+	struct ieee80211_sta *sta; /* station struct we're part of */
+#endif
 	struct ath_atx_tid tid[WME_NUM_TID];
 	struct ath_atx_ac ac[WME_NUM_AC];
 	u16 maxampdu;
@@ -275,6 +277,11 @@ struct ath_tx_control {
 #define ATH_TX_XRETRY       0x02
 #define ATH_TX_BAR          0x04
 
+/**
+ * @txq_map:  Index is mac80211 queue number.  This is
+ *  not necessarily the same as the hardware queue number
+ *  (axq_qnum).
+ */
 struct ath_tx {
 	u16 seq_no;
 	u32 txqsetup;
@@ -301,6 +308,8 @@ struct ath_rx {
 	struct ath_descdma rxdma;
 	struct ath_buf *rx_bufptr;
 	struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+
+	struct sk_buff *frag;
 };
 
 int ath_startrecv(struct ath_softc *sc);
@@ -337,10 +346,10 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
 
 struct ath_vif {
 	int av_bslot;
+	bool is_bslot_active;
 	__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
 	enum nl80211_iftype av_opmode;
 	struct ath_buf *av_bcbuf;
-	struct ath_tx_control av_btxctl;
 	u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */
 };
 
@@ -360,7 +369,7 @@ struct ath_vif {
 #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
 
 struct ath_beacon_config {
-	u16 beacon_interval;
+	int beacon_interval;
 	u16 listen_interval;
 	u16 dtim_period;
 	u16 bmiss_timeout;
@@ -379,7 +388,6 @@ struct ath_beacon {
 	u32 ast_be_xmit;
 	u64 bc_tstamp;
 	struct ieee80211_vif *bslot[ATH_BCBUF];
-	struct ath_wiphy *bslot_aphy[ATH_BCBUF];
 	int slottime;
 	int slotupdate;
 	struct ath9k_tx_queue_info beacon_qi;
@@ -390,9 +398,10 @@ struct ath_beacon {
 
 void ath_beacon_tasklet(unsigned long data);
 void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
-int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
+int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
 int ath_beaconq_config(struct ath_softc *sc);
+void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
 
 /*******/
 /* ANI */
@@ -439,26 +448,21 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
 
 #define ATH_LED_PIN_DEF 		1
 #define ATH_LED_PIN_9287		8
-#define ATH_LED_ON_DURATION_IDLE	350	/* in msecs */
-#define ATH_LED_OFF_DURATION_IDLE	250	/* in msecs */
-
-enum ath_led_type {
-	ATH_LED_RADIO,
-	ATH_LED_ASSOC,
-	ATH_LED_TX,
-	ATH_LED_RX
-};
-
-struct ath_led {
-	struct ath_softc *sc;
-	struct led_classdev led_cdev;
-	enum ath_led_type led_type;
-	char name[32];
-	bool registered;
-};
+#define ATH_LED_PIN_9485		6
 
+#ifdef CONFIG_MAC80211_LEDS
 void ath_init_leds(struct ath_softc *sc);
 void ath_deinit_leds(struct ath_softc *sc);
+#else
+static inline void ath_init_leds(struct ath_softc *sc)
+{
+}
+
+static inline void ath_deinit_leds(struct ath_softc *sc)
+{
+}
+#endif
+
 
 /* Antenna diversity/combining */
 #define ATH_ANT_RX_CURRENT_SHIFT 4
@@ -527,7 +531,6 @@ struct ath_ant_comb {
 #define ATH_CABQ_READY_TIME     80      /* % of beacon interval */
 #define ATH_MAX_SW_RETRIES      10
 #define ATH_CHAN_MAX            255
-#define IEEE80211_WEP_NKID      4       /* number of key ids */
 
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
 #define ATH_RATE_DUMMY_MARKER   0
@@ -555,27 +558,28 @@ struct ath_ant_comb {
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
 
-struct ath_wiphy;
 struct ath_rate_table;
 
+struct ath9k_vif_iter_data {
+	const u8 *hw_macaddr; /* phy's hardware address, set
+			       * before starting iteration for
+			       * valid bssid mask.
+			       */
+	u8 mask[ETH_ALEN]; /* bssid mask */
+	int naps;      /* number of AP vifs */
+	int nmeshes;   /* number of mesh vifs */
+	int nstations; /* number of station vifs */
+	int nwds;      /* number of nwd vifs */
+	int nadhocs;   /* number of adhoc vifs */
+	int nothers;   /* number of vifs not specified above. */
+};
+
 struct ath_softc {
 	struct ieee80211_hw *hw;
 	struct device *dev;
 
-	spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
-	struct ath_wiphy *pri_wiphy;
-	struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
-				       * have NULL entries */
-	int num_sec_wiphy; /* number of sec_wiphy pointers in the array */
 	int chan_idx;
 	int chan_is_ht;
-	struct ath_wiphy *next_wiphy;
-	struct work_struct chan_work;
-	int wiphy_select_failures;
-	unsigned long wiphy_select_first_fail;
-	struct delayed_work wiphy_work;
-	unsigned long wiphy_scheduler_int;
-	int wiphy_scheduler_index;
 	struct survey_info *cur_survey;
 	struct survey_info survey[ATH9K_NUM_CHANNELS];
 
@@ -592,14 +596,16 @@ struct ath_softc {
 	struct work_struct hw_check_work;
 	struct completion paprd_complete;
 
+	unsigned int hw_busy_count;
+
 	u32 intrstatus;
 	u32 sc_flags; /* SC_OP_* */
 	u16 ps_flags; /* PS_* */
 	u16 curtxpow;
-	u8 nbcnvifs;
-	u16 nvifs;
 	bool ps_enabled;
 	bool ps_idle;
+	short nbcnvifs;
+	short nvifs;
 	unsigned long ps_usecount;
 
 	struct ath_config config;
@@ -608,23 +614,24 @@ struct ath_softc {
 	struct ath_beacon beacon;
 	struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
 
-	struct ath_led radio_led;
-	struct ath_led assoc_led;
-	struct ath_led tx_led;
-	struct ath_led rx_led;
-	struct delayed_work ath_led_blink_work;
-	int led_on_duration;
-	int led_off_duration;
-	int led_on_cnt;
-	int led_off_cnt;
+#ifdef CONFIG_MAC80211_LEDS
+	bool led_registered;
+	char led_name[32];
+	struct led_classdev led_cdev;
+#endif
 
-	int beacon_interval;
+	struct ath9k_hw_cal_data caldata;
+	int last_rssi;
 
 #ifdef CONFIG_ATH9K_DEBUGFS
 	struct ath9k_debug debug;
+	spinlock_t nodes_lock;
+	struct list_head nodes; /* basically, stations */
+	unsigned int tx_complete_poll_work_seen;
 #endif
 	struct ath_beacon_config cur_beacon_conf;
 	struct delayed_work tx_complete_work;
+	struct delayed_work hw_pll_work;
 	struct ath_btcoex btcoex;
 
 	struct ath_descdma txsdma;
@@ -632,23 +639,6 @@ struct ath_softc {
 	struct ath_ant_comb ant_comb;
 };
 
-struct ath_wiphy {
-	struct ath_softc *sc; /* shared for all virtual wiphys */
-	struct ieee80211_hw *hw;
-	struct ath9k_hw_cal_data caldata;
-	enum ath_wiphy_state {
-		ATH_WIPHY_INACTIVE,
-		ATH_WIPHY_ACTIVE,
-		ATH_WIPHY_PAUSING,
-		ATH_WIPHY_PAUSED,
-		ATH_WIPHY_SCAN,
-	} state;
-	bool idle;
-	int chan_idx;
-	int chan_is_ht;
-	int last_rssi;
-};
-
 void ath9k_tasklet(unsigned long data);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
 int ath_cabq_update(struct ath_softc *);
@@ -669,14 +659,13 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 		    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
-void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
-			   struct ath9k_channel *ichan);
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan);
 
 void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
 void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
 bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
+bool ath9k_uses_beacons(int type);
 
 #ifdef CONFIG_PCI
 int ath_pci_init(void);
@@ -700,26 +689,12 @@ void ath9k_ps_restore(struct ath_softc *sc);
 u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
 
 void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-int ath9k_wiphy_add(struct ath_softc *sc);
-int ath9k_wiphy_del(struct ath_wiphy *aphy);
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype);
-int ath9k_wiphy_pause(struct ath_wiphy *aphy);
-int ath9k_wiphy_unpause(struct ath_wiphy *aphy);
-int ath9k_wiphy_select(struct ath_wiphy *aphy);
-void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int);
-void ath9k_wiphy_chan_work(struct work_struct *work);
-bool ath9k_wiphy_started(struct ath_softc *sc);
-void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
-				  struct ath_wiphy *selected);
-bool ath9k_wiphy_scanning(struct ath_softc *sc);
-void ath9k_wiphy_work(struct work_struct *work);
-bool ath9k_all_wiphys_idle(struct ath_softc *sc);
-void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
-
-void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
-bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
 
 void ath_start_rfkill_poll(struct ath_softc *sc);
 extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ath9k_vif_iter_data *iter_data);
+
 
 #endif /* ATH9K_H */
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 385ba03..6d2a545f 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -112,8 +112,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
 
 static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_tx_control txctl;
 
@@ -132,8 +131,7 @@ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
 static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 					   struct ieee80211_vif *vif)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_buf *bf;
 	struct ath_vif *avp;
@@ -142,13 +140,10 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 	struct ieee80211_tx_info *info;
 	int cabq_depth;
 
-	if (aphy->state != ATH_WIPHY_ACTIVE)
-		return NULL;
-
 	avp = (void *)vif->drv_priv;
 	cabq = sc->beacon.cabq;
 
-	if (avp->av_bcbuf == NULL)
+	if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active)
 		return NULL;
 
 	/* Release the old beacon first */
@@ -225,13 +220,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 	return bf;
 }
 
-int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
+int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
 {
-	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_vif *avp;
 	struct ath_buf *bf;
 	struct sk_buff *skb;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	__le64 tstamp;
 
 	avp = (void *)vif->drv_priv;
@@ -244,9 +239,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 						 struct ath_buf, list);
 		list_del(&avp->av_bcbuf->list);
 
-		if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
-		    sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
-		    sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+		if (ath9k_uses_beacons(vif->type)) {
 			int slot;
 			/*
 			 * Assign the vif to a beacon xmit slot. As
@@ -256,6 +249,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 			for (slot = 0; slot < ATH_BCBUF; slot++)
 				if (sc->beacon.bslot[slot] == NULL) {
 					avp->av_bslot = slot;
+					avp->is_bslot_active = false;
 
 					/* NB: keep looking for a double slot */
 					if (slot == 0 || !sc->beacon.bslot[slot-1])
@@ -263,7 +257,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 				}
 			BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
 			sc->beacon.bslot[avp->av_bslot] = vif;
-			sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
 			sc->nbcnvifs++;
 		}
 	}
@@ -281,10 +274,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 
 	/* NB: the beacon data buffer must be 32-bit aligned. */
 	skb = ieee80211_beacon_get(sc->hw, vif);
-	if (skb == NULL) {
-		ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n");
+	if (skb == NULL)
 		return -ENOMEM;
-	}
 
 	tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
 	sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
@@ -293,7 +284,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 		u64 tsfadjust;
 		int intval;
 
-		intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+		intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 
 		/*
 		 * Calculate the TSF offset for this beacon slot, i.e., the
@@ -325,6 +316,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 		ath_err(common, "dma_mapping_error on beacon alloc\n");
 		return -ENOMEM;
 	}
+	avp->is_bslot_active = true;
 
 	return 0;
 }
@@ -336,7 +328,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
 
 		if (avp->av_bslot != -1) {
 			sc->beacon.bslot[avp->av_bslot] = NULL;
-			sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
 			sc->nbcnvifs--;
 		}
 
@@ -358,11 +349,11 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
 void ath_beacon_tasklet(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *)data;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_buf *bf = NULL;
 	struct ieee80211_vif *vif;
-	struct ath_wiphy *aphy;
 	int slot;
 	u32 bfaddr, bc = 0, tsftu;
 	u64 tsf;
@@ -382,6 +373,7 @@ void ath_beacon_tasklet(unsigned long data)
 			ath_dbg(common, ATH_DBG_BSTUCK,
 				"missed %u consecutive beacons\n",
 				sc->beacon.bmisscnt);
+			ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
 			ath9k_hw_bstuck_nfcal(ah);
 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
 			ath_dbg(common, ATH_DBG_BSTUCK,
@@ -406,7 +398,7 @@ void ath_beacon_tasklet(unsigned long data)
 	 * on the tsf to safeguard against missing an swba.
 	 */
 
-	intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+	intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 
 	tsf = ath9k_hw_gettsf64(ah);
 	tsftu = TSF_TO_TU(tsf>>32, tsf);
@@ -420,7 +412,6 @@ void ath_beacon_tasklet(unsigned long data)
 	 */
 	slot = ATH_BCBUF - slot - 1;
 	vif = sc->beacon.bslot[slot];
-	aphy = sc->beacon.bslot_aphy[slot];
 
 	ath_dbg(common, ATH_DBG_BEACON,
 		"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
@@ -428,7 +419,7 @@ void ath_beacon_tasklet(unsigned long data)
 
 	bfaddr = 0;
 	if (vif) {
-		bf = ath_beacon_generate(aphy->hw, vif);
+		bf = ath_beacon_generate(sc->hw, vif);
 		if (bf != NULL) {
 			bfaddr = bf->bf_daddr;
 			bc = 1;
@@ -460,16 +451,6 @@ void ath_beacon_tasklet(unsigned long data)
 		sc->beacon.updateslot = OK;
 	}
 	if (bfaddr != 0) {
-		/*
-		 * Stop any current dma and put the new frame(s) on the queue.
-		 * This should never fail since we check above that no frames
-		 * are still pending on the queue.
-		 */
-		if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
-			ath_err(common, "beacon queue %u did not stop?\n",
-				sc->beacon.beaconq);
-		}
-
 		/* NB: cabq traffic should already be queued and primed */
 		ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
 		ath9k_hw_txstart(ah, sc->beacon.beaconq);
@@ -720,10 +701,10 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
 		iftype = sc->sc_ah->opmode;
 	}
 
-		cur_conf->listen_interval = 1;
-		cur_conf->dtim_count = 1;
-		cur_conf->bmiss_timeout =
-			ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+	cur_conf->listen_interval = 1;
+	cur_conf->dtim_count = 1;
+	cur_conf->bmiss_timeout =
+		ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
 
 	/*
 	 * It looks like mac80211 may end up using beacon interval of zero in
@@ -735,8 +716,9 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
 		cur_conf->beacon_interval = 100;
 
 	/*
-	 * Some times we dont parse dtim period from mac80211, in that case
-	 * use a default value
+	 * We don't parse dtim period from mac80211 during the driver
+	 * initialization as it breaks association with hidden-ssid
+	 * AP and it causes latency in roaming
 	 */
 	if (cur_conf->dtim_period == 0)
 		cur_conf->dtim_period = 1;
@@ -760,3 +742,36 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
 
 	sc->sc_flags |= SC_OP_BEACONS;
 }
+
+void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_vif *avp;
+	int slot;
+	bool found = false;
+
+	ath9k_ps_wakeup(sc);
+	if (status) {
+		for (slot = 0; slot < ATH_BCBUF; slot++) {
+			if (sc->beacon.bslot[slot]) {
+				avp = (void *)sc->beacon.bslot[slot]->drv_priv;
+				if (avp->is_bslot_active) {
+					found = true;
+					break;
+				}
+			}
+		}
+		if (found) {
+			/* Re-enable beaconing */
+			ah->imask |= ATH9K_INT_SWBA;
+			ath9k_hw_set_interrupts(ah, ah->imask);
+		}
+	} else {
+		/* Disable SWBA interrupt */
+		ah->imask &= ~ATH9K_INT_SWBA;
+		ath9k_hw_set_interrupts(ah, ah->imask);
+		tasklet_kill(&sc->bcon_tasklet);
+		ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+	}
+	ath9k_ps_restore(sc);
+}
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index b68a1ac..8649581 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -262,7 +262,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 	 * since 250us often results in NF load timeout and causes deaf
 	 * condition during stress testing 12/12/2009
 	 */
-	for (j = 0; j < 1000; j++) {
+	for (j = 0; j < 10000; j++) {
 		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
 		     AR_PHY_AGC_CONTROL_NF) == 0)
 			break;
@@ -278,7 +278,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 	 * here, the baseband nf cal will just be capped by our present
 	 * noisefloor until the next calibration timer.
 	 */
-	if (j == 1000) {
+	if (j == 10000) {
 		ath_dbg(common, ATH_DBG_ANY,
 			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
 			REG_READ(ah, AR_PHY_AGC_CONTROL));
@@ -382,9 +382,8 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
 	s16 default_nf;
 	int i, j;
 
-	if (!ah->caldata)
-		return;
-
+	ah->caldata->channel = chan->channel;
+	ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
 	h = ah->caldata->nfCalHist;
 	default_nf = ath9k_hw_get_default_nf(ah, chan);
 	for (i = 0; i < NUM_NF_READINGS; i++) {
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index df1998d..615e682 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -189,6 +189,17 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
 }
 EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp);
 
+void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+			    u16 new_txpow, u16 *txpower)
+{
+	if (cur_txpow != new_txpow) {
+		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
+		/* read back in case value is clamped */
+		*txpower = ath9k_hw_regulatory(ah)->power_limit;
+	}
+}
+EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+
 static int __init ath9k_cmn_init(void)
 {
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index a126bdd..b2f7b5f 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -23,8 +23,6 @@
 
 /* Common header for Atheros 802.11n base driver cores */
 
-#define IEEE80211_WEP_NKID 4
-
 #define WME_NUM_TID             16
 #define WME_BA_BMP_SIZE         64
 #define WME_MAX_BA              WME_BA_BMP_SIZE
@@ -70,3 +68,5 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 int ath9k_cmn_count_streams(unsigned int chainmask, int max);
 void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
 				  enum ath_stomp_type stomp_type);
+void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+			    u16 new_txpow, u16 *txpower);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 3586c43..8df5a92 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -15,6 +15,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <asm/unaligned.h>
 
 #include "ath9k.h"
@@ -30,6 +31,19 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
+				      size_t count, loff_t *ppos)
+{
+	u8 *buf = file->private_data;
+	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
+}
+
+static int ath9k_debugfs_release_buf(struct inode *inode, struct file *file)
+{
+	vfree(file->private_data);
+	return 0;
+}
+
 #ifdef CONFIG_ATH_DEBUG
 
 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
@@ -381,41 +395,40 @@ static const struct file_operations fops_interrupt = {
 	.llseek = default_llseek,
 };
 
-static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
+static const char *channel_type_str(enum nl80211_channel_type t)
 {
-	switch (state) {
-	case ATH_WIPHY_INACTIVE:
-		return "INACTIVE";
-	case ATH_WIPHY_ACTIVE:
-		return "ACTIVE";
-	case ATH_WIPHY_PAUSING:
-		return "PAUSING";
-	case ATH_WIPHY_PAUSED:
-		return "PAUSED";
-	case ATH_WIPHY_SCAN:
-		return "SCAN";
+	switch (t) {
+	case NL80211_CHAN_NO_HT:
+		return "no ht";
+	case NL80211_CHAN_HT20:
+		return "ht20";
+	case NL80211_CHAN_HT40MINUS:
+		return "ht40-";
+	case NL80211_CHAN_HT40PLUS:
+		return "ht40+";
+	default:
+		return "???";
 	}
-	return "?";
 }
 
 static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
 			       size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
-	struct ath_wiphy *aphy = sc->pri_wiphy;
-	struct ieee80211_channel *chan = aphy->hw->conf.channel;
+	struct ieee80211_channel *chan = sc->hw->conf.channel;
+	struct ieee80211_conf *conf = &(sc->hw->conf);
 	char buf[512];
 	unsigned int len = 0;
-	int i;
 	u8 addr[ETH_ALEN];
 	u32 tmp;
 
 	len += snprintf(buf + len, sizeof(buf) - len,
-			"primary: %s (%s chan=%d ht=%d)\n",
-			wiphy_name(sc->pri_wiphy->hw->wiphy),
-			ath_wiphy_state_str(sc->pri_wiphy->state),
+			"%s (chan=%d  center-freq: %d MHz  channel-type: %d (%s))\n",
+			wiphy_name(sc->hw->wiphy),
 			ieee80211_frequency_to_channel(chan->center_freq),
-			aphy->chan_is_ht);
+			chan->center_freq,
+			conf->channel_type,
+			channel_type_str(conf->channel_type));
 
 	put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
 	put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
@@ -457,156 +470,82 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
 	else
 		len += snprintf(buf + len, sizeof(buf) - len, "\n");
 
-	/* Put variable-length stuff down here, and check for overflows. */
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i];
-		if (aphy_tmp == NULL)
-			continue;
-		chan = aphy_tmp->hw->conf.channel;
-		len += snprintf(buf + len, sizeof(buf) - len,
-			"secondary: %s (%s chan=%d ht=%d)\n",
-			wiphy_name(aphy_tmp->hw->wiphy),
-			ath_wiphy_state_str(aphy_tmp->state),
-			ieee80211_frequency_to_channel(chan->center_freq),
-						       aphy_tmp->chan_is_ht);
-	}
 	if (len > sizeof(buf))
 		len = sizeof(buf);
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
 }
 
-static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name)
-{
-	int i;
-	if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0)
-		return sc->pri_wiphy;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0)
-			return aphy;
-	}
-	return NULL;
-}
-
-static int del_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_del(aphy);
-}
-
-static int pause_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_pause(aphy);
-}
-
-static int unpause_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_unpause(aphy);
-}
-
-static int select_wiphy(struct ath_softc *sc, const char *name)
-{
-	struct ath_wiphy *aphy = get_wiphy(sc, name);
-	if (!aphy)
-		return -ENOENT;
-	return ath9k_wiphy_select(aphy);
-}
-
-static int schedule_wiphy(struct ath_softc *sc, const char *msec)
-{
-	ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0));
-	return 0;
-}
-
-static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf,
-				size_t count, loff_t *ppos)
-{
-	struct ath_softc *sc = file->private_data;
-	char buf[50];
-	size_t len;
-
-	len = min(count, sizeof(buf) - 1);
-	if (copy_from_user(buf, user_buf, len))
-		return -EFAULT;
-	buf[len] = '\0';
-	if (len > 0 && buf[len - 1] == '\n')
-		buf[len - 1] = '\0';
-
-	if (strncmp(buf, "add", 3) == 0) {
-		int res = ath9k_wiphy_add(sc);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "del=", 4) == 0) {
-		int res = del_wiphy(sc, buf + 4);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "pause=", 6) == 0) {
-		int res = pause_wiphy(sc, buf + 6);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "unpause=", 8) == 0) {
-		int res = unpause_wiphy(sc, buf + 8);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "select=", 7) == 0) {
-		int res = select_wiphy(sc, buf + 7);
-		if (res < 0)
-			return res;
-	} else if (strncmp(buf, "schedule=", 9) == 0) {
-		int res = schedule_wiphy(sc, buf + 9);
-		if (res < 0)
-			return res;
-	} else
-		return -EOPNOTSUPP;
-
-	return count;
-}
-
 static const struct file_operations fops_wiphy = {
 	.read = read_file_wiphy,
-	.write = write_file_wiphy,
 	.open = ath9k_debugfs_open,
 	.owner = THIS_MODULE,
 	.llseek = default_llseek,
 };
 
+#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
 #define PR(str, elem)							\
 	do {								\
 		len += snprintf(buf + len, size - len,			\
 				"%s%13u%11u%10u%10u\n", str,		\
-		sc->debug.stats.txstats[WME_AC_BE].elem, \
-		sc->debug.stats.txstats[WME_AC_BK].elem, \
-		sc->debug.stats.txstats[WME_AC_VI].elem, \
-		sc->debug.stats.txstats[WME_AC_VO].elem); \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
+		if (len >= size)			  \
+			goto done;			  \
+} while(0)
+
+#define PRX(str, elem)							\
+do {									\
+	len += snprintf(buf + len, size - len,				\
+			"%s%13u%11u%10u%10u\n", str,			\
+			(unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem),	\
+			(unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem),	\
+			(unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem),	\
+			(unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem));	\
+	if (len >= size)						\
+		goto done;						\
 } while(0)
 
+#define PRQLE(str, elem)						\
+do {									\
+	len += snprintf(buf + len, size - len,				\
+			"%s%13i%11i%10i%10i\n", str,			\
+			list_empty(&sc->tx.txq_map[WME_AC_BE]->elem),	\
+			list_empty(&sc->tx.txq_map[WME_AC_BK]->elem),	\
+			list_empty(&sc->tx.txq_map[WME_AC_VI]->elem),	\
+			list_empty(&sc->tx.txq_map[WME_AC_VO]->elem));	\
+	if (len >= size)						\
+		goto done;						\
+} while (0)
+
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
 	struct ath_softc *sc = file->private_data;
 	char *buf;
-	unsigned int len = 0, size = 2048;
+	unsigned int len = 0, size = 8000;
+	int i;
 	ssize_t retval = 0;
+	char tmp[32];
 
 	buf = kzalloc(size, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
 
-	len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
+	len += sprintf(buf, "Num-Tx-Queues: %i  tx-queues-setup: 0x%x"
+		       " poll-work-seen: %u\n"
+		       "%30s %10s%10s%10s\n\n",
+		       ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
+		       sc->tx_complete_poll_work_seen,
+		       "BE", "BK", "VI", "VO");
 
 	PR("MPDUs Queued:    ", queued);
 	PR("MPDUs Completed: ", completed);
 	PR("Aggregates:      ", a_aggr);
-	PR("AMPDUs Queued:   ", a_queued);
+	PR("AMPDUs Queued HW:", a_queued_hw);
+	PR("AMPDUs Queued SW:", a_queued_sw);
 	PR("AMPDUs Completed:", a_completed);
 	PR("AMPDUs Retried:  ", a_retries);
 	PR("AMPDUs XRetried: ", a_xretries);
@@ -618,6 +557,223 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 	PR("DELIM Underrun:  ", delim_underrun);
 	PR("TX-Pkts-All:     ", tx_pkts_all);
 	PR("TX-Bytes-All:    ", tx_bytes_all);
+	PR("hw-put-tx-buf:   ", puttxbuf);
+	PR("hw-tx-start:     ", txstart);
+	PR("hw-tx-proc-desc: ", txprocdesc);
+	len += snprintf(buf + len, size - len,
+			"%s%11p%11p%10p%10p\n", "txq-memory-address:",
+			sc->tx.txq_map[WME_AC_BE],
+			sc->tx.txq_map[WME_AC_BK],
+			sc->tx.txq_map[WME_AC_VI],
+			sc->tx.txq_map[WME_AC_VO]);
+	if (len >= size)
+		goto done;
+
+	PRX("axq-qnum:        ", axq_qnum);
+	PRX("axq-depth:       ", axq_depth);
+	PRX("axq-ampdu_depth: ", axq_ampdu_depth);
+	PRX("axq-stopped      ", stopped);
+	PRX("tx-in-progress   ", axq_tx_inprogress);
+	PRX("pending-frames   ", pending_frames);
+	PRX("txq_headidx:     ", txq_headidx);
+	PRX("txq_tailidx:     ", txq_headidx);
+
+	PRQLE("axq_q empty:       ", axq_q);
+	PRQLE("axq_acq empty:     ", axq_acq);
+	PRQLE("txq_fifo_pending:  ", txq_fifo_pending);
+	for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
+		snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
+		PRQLE(tmp, txq_fifo[i]);
+	}
+
+	/* Print out more detailed queue-info */
+	for (i = 0; i <= WME_AC_BK; i++) {
+		struct ath_txq *txq = &(sc->tx.txq[i]);
+		struct ath_atx_ac *ac;
+		struct ath_atx_tid *tid;
+		if (len >= size)
+			goto done;
+		spin_lock_bh(&txq->axq_lock);
+		if (!list_empty(&txq->axq_acq)) {
+			ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
+					      list);
+			len += snprintf(buf + len, size - len,
+					"txq[%i] first-ac: %p sched: %i\n",
+					i, ac, ac->sched);
+			if (list_empty(&ac->tid_q) || (len >= size))
+				goto done_for;
+			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+					       list);
+			len += snprintf(buf + len, size - len,
+					" first-tid: %p sched: %i paused: %i\n",
+					tid, tid->sched, tid->paused);
+		}
+	done_for:
+		spin_unlock_bh(&txq->axq_lock);
+	}
+
+done:
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static ssize_t read_file_stations(struct file *file, char __user *user_buf,
+				  size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	char *buf;
+	unsigned int len = 0, size = 64000;
+	struct ath_node *an = NULL;
+	ssize_t retval = 0;
+	int q;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += snprintf(buf + len, size - len,
+			"Stations:\n"
+			" tid: addr sched paused buf_q-empty an ac\n"
+			" ac: addr sched tid_q-empty txq\n");
+
+	spin_lock(&sc->nodes_lock);
+	list_for_each_entry(an, &sc->nodes, list) {
+		len += snprintf(buf + len, size - len,
+				"%pM\n", an->sta->addr);
+		if (len >= size)
+			goto done;
+
+		for (q = 0; q < WME_NUM_TID; q++) {
+			struct ath_atx_tid *tid = &(an->tid[q]);
+			len += snprintf(buf + len, size - len,
+					" tid: %p %s %s %i %p %p\n",
+					tid, tid->sched ? "sched" : "idle",
+					tid->paused ? "paused" : "running",
+					list_empty(&tid->buf_q),
+					tid->an, tid->ac);
+			if (len >= size)
+				goto done;
+		}
+
+		for (q = 0; q < WME_NUM_AC; q++) {
+			struct ath_atx_ac *ac = &(an->ac[q]);
+			len += snprintf(buf + len, size - len,
+					" ac: %p %s %i %p\n",
+					ac, ac->sched ? "sched" : "idle",
+					list_empty(&ac->tid_q), ac->txq);
+			if (len >= size)
+				goto done;
+		}
+	}
+
+done:
+	spin_unlock(&sc->nodes_lock);
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_hw *ah = sc->sc_ah;
+	struct ieee80211_hw *hw = sc->hw;
+	char *buf;
+	unsigned int len = 0, size = 8000;
+	ssize_t retval = 0;
+	const char *tmp;
+	unsigned int reg;
+	struct ath9k_vif_iter_data iter_data;
+
+	ath9k_calculate_iter_data(hw, NULL, &iter_data);
+	
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	switch (sc->sc_ah->opmode) {
+	case  NL80211_IFTYPE_ADHOC:
+		tmp = "ADHOC";
+		break;
+	case  NL80211_IFTYPE_MESH_POINT:
+		tmp = "MESH";
+		break;
+	case  NL80211_IFTYPE_AP:
+		tmp = "AP";
+		break;
+	case  NL80211_IFTYPE_STATION:
+		tmp = "STATION";
+		break;
+	default:
+		tmp = "???";
+		break;
+	}
+
+	len += snprintf(buf + len, size - len,
+			"curbssid: %pM\n"
+			"OP-Mode: %s(%i)\n"
+			"Beacon-Timer-Register: 0x%x\n",
+			common->curbssid,
+			tmp, (int)(sc->sc_ah->opmode),
+			REG_READ(ah, AR_BEACON_PERIOD));
+
+	reg = REG_READ(ah, AR_TIMER_MODE);
+	len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (",
+			reg);
+	if (reg & AR_TBTT_TIMER_EN)
+		len += snprintf(buf + len, size - len, "TBTT ");
+	if (reg & AR_DBA_TIMER_EN)
+		len += snprintf(buf + len, size - len, "DBA ");
+	if (reg & AR_SWBA_TIMER_EN)
+		len += snprintf(buf + len, size - len, "SWBA ");
+	if (reg & AR_HCF_TIMER_EN)
+		len += snprintf(buf + len, size - len, "HCF ");
+	if (reg & AR_TIM_TIMER_EN)
+		len += snprintf(buf + len, size - len, "TIM ");
+	if (reg & AR_DTIM_TIMER_EN)
+		len += snprintf(buf + len, size - len, "DTIM ");
+	len += snprintf(buf + len, size - len, ")\n");
+
+	reg = sc->sc_ah->imask;
+	len += snprintf(buf + len, size - len, "imask: 0x%x (", reg);
+	if (reg & ATH9K_INT_SWBA)
+		len += snprintf(buf + len, size - len, "SWBA ");
+	if (reg & ATH9K_INT_BMISS)
+		len += snprintf(buf + len, size - len, "BMISS ");
+	if (reg & ATH9K_INT_CST)
+		len += snprintf(buf + len, size - len, "CST ");
+	if (reg & ATH9K_INT_RX)
+		len += snprintf(buf + len, size - len, "RX ");
+	if (reg & ATH9K_INT_RXHP)
+		len += snprintf(buf + len, size - len, "RXHP ");
+	if (reg & ATH9K_INT_RXLP)
+		len += snprintf(buf + len, size - len, "RXLP ");
+	if (reg & ATH9K_INT_BB_WATCHDOG)
+		len += snprintf(buf + len, size - len, "BB_WATCHDOG ");
+	/* there are other IRQs if one wanted to add them. */
+	len += snprintf(buf + len, size - len, ")\n");
+
+	len += snprintf(buf + len, size - len,
+			"VIF Counts: AP: %i STA: %i MESH: %i WDS: %i"
+			" ADHOC: %i OTHER: %i nvifs: %hi beacon-vifs: %hi\n",
+			iter_data.naps, iter_data.nstations, iter_data.nmeshes,
+			iter_data.nwds, iter_data.nadhocs, iter_data.nothers,
+			sc->nvifs, sc->nbcnvifs);
+
+	len += snprintf(buf + len, size - len,
+			"Calculated-BSSID-Mask: %pM\n",
+			iter_data.mask);
 
 	if (len > size)
 		len = size;
@@ -629,9 +785,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 }
 
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-		       struct ath_tx_status *ts)
+		       struct ath_tx_status *ts, struct ath_txq *txq)
 {
-	int qnum = skb_get_queue_mapping(bf->bf_mpdu);
+	int qnum = txq->axq_qnum;
 
 	TX_STAT_INC(qnum, tx_pkts_all);
 	sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
@@ -666,6 +822,20 @@ static const struct file_operations fops_xmit = {
 	.llseek = default_llseek,
 };
 
+static const struct file_operations fops_stations = {
+	.read = read_file_stations,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations fops_misc = {
+	.read = read_file_misc,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
@@ -871,6 +1041,42 @@ static const struct file_operations fops_regval = {
 	.llseek = default_llseek,
 };
 
+#define REGDUMP_LINE_SIZE	20
+
+static int open_file_regdump(struct inode *inode, struct file *file)
+{
+	struct ath_softc *sc = inode->i_private;
+	unsigned int len = 0;
+	u8 *buf;
+	int i;
+	unsigned long num_regs, regdump_len, max_reg_offset;
+
+	max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500;
+	num_regs = max_reg_offset / 4 + 1;
+	regdump_len = num_regs * REGDUMP_LINE_SIZE + 1;
+	buf = vmalloc(regdump_len);
+	if (!buf)
+		return -ENOMEM;
+
+	ath9k_ps_wakeup(sc);
+	for (i = 0; i < num_regs; i++)
+		len += scnprintf(buf + len, regdump_len - len,
+			"0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2));
+	ath9k_ps_restore(sc);
+
+	file->private_data = buf;
+
+	return 0;
+}
+
+static const struct file_operations fops_regdump = {
+	.open = open_file_regdump,
+	.read = ath9k_debugfs_read_buf,
+	.release = ath9k_debugfs_release_buf,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,/* read accesses f_pos */
+};
+
 int ath9k_init_debug(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -903,6 +1109,14 @@ int ath9k_init_debug(struct ath_hw *ah)
 			sc, &fops_xmit))
 		goto err;
 
+	if (!debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy,
+			sc, &fops_stations))
+		goto err;
+
+	if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy,
+			sc, &fops_misc))
+		goto err;
+
 	if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy,
 			sc, &fops_recv))
 		goto err;
@@ -927,6 +1141,10 @@ int ath9k_init_debug(struct ath_hw *ah)
 			sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
 		goto err;
 
+	if (!debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy,
+			sc, &fops_regdump))
+		goto err;
+
 	sc->debug.regidx = 0;
 	return 0;
 err:
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 1e5078b..59338de 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -89,7 +89,8 @@ struct ath_interrupt_stats {
  * @queued: Total MPDUs (non-aggr) queued
  * @completed: Total MPDUs (non-aggr) completed
  * @a_aggr: Total no. of aggregates queued
- * @a_queued: Total AMPDUs queued
+ * @a_queued_hw: Total AMPDUs queued to hardware
+ * @a_queued_sw: Total AMPDUs queued to software queues
  * @a_completed: Total AMPDUs completed
  * @a_retries: No. of AMPDUs retried (SW)
  * @a_xretries: No. of AMPDUs dropped due to xretries
@@ -102,6 +103,9 @@ struct ath_interrupt_stats {
  * @desc_cfg_err: Descriptor configuration errors
  * @data_urn: TX data underrun errors
  * @delim_urn: TX delimiter underrun errors
+ * @puttxbuf: Number of times hardware was given txbuf to write.
+ * @txstart:  Number of times hardware was told to start tx.
+ * @txprocdesc:  Number of times tx descriptor was processed
  */
 struct ath_tx_stats {
 	u32 tx_pkts_all;
@@ -109,7 +113,8 @@ struct ath_tx_stats {
 	u32 queued;
 	u32 completed;
 	u32 a_aggr;
-	u32 a_queued;
+	u32 a_queued_hw;
+	u32 a_queued_sw;
 	u32 a_completed;
 	u32 a_retries;
 	u32 a_xretries;
@@ -119,6 +124,9 @@ struct ath_tx_stats {
 	u32 desc_cfg_err;
 	u32 data_underrun;
 	u32 delim_underrun;
+	u32 puttxbuf;
+	u32 txstart;
+	u32 txprocdesc;
 };
 
 /**
@@ -167,7 +175,7 @@ int ath9k_init_debug(struct ath_hw *ah);
 
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-		       struct ath_tx_status *ts);
+		       struct ath_tx_status *ts, struct ath_txq *txq);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 
 #else
@@ -184,7 +192,8 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     struct ath_buf *bf,
-				     struct ath_tx_status *ts)
+				     struct ath_tx_status *ts,
+				     struct ath_txq *txq)
 {
 }
 
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index d051631..8c18bed 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -89,6 +89,38 @@ bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
 	return false;
 }
 
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+				  int eep_start_loc, int size)
+{
+	int i = 0, j, addr;
+	u32 addrdata[8];
+	u32 data[8];
+
+	for (addr = 0; addr < size; addr++) {
+		addrdata[i] = AR5416_EEPROM_OFFSET +
+			((addr + eep_start_loc) << AR5416_EEPROM_S);
+		i++;
+		if (i == 8) {
+			REG_READ_MULTI(ah, addrdata, data, i);
+
+			for (j = 0; j < i; j++) {
+				*eep_data = data[j];
+				eep_data++;
+			}
+			i = 0;
+		}
+	}
+
+	if (i != 0) {
+		REG_READ_MULTI(ah, addrdata, data, i);
+
+		for (j = 0; j < i; j++) {
+			*eep_data = data[j];
+			eep_data++;
+		}
+	}
+}
+
 bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
 {
 	return common->bus_ops->eeprom_read(common, off, data);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 58e2ddc..bd82447 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -665,6 +665,8 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
 bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
 				    u16 *indexL, u16 *indexR);
 bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+				  int eep_start_loc, int size);
 void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
 			     u8 *pVpdList, u16 numIntercepts,
 			     u8 *pRetVpdList);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index fbdff7e..bc77a30 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -27,19 +27,13 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
 	return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
 }
 
-static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
-{
 #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+
+static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
-	int addr, eep_start_loc = 0;
-
-	eep_start_loc = 64;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		ath_dbg(common, ATH_DBG_EEPROM,
-			"Reading from EEPROM, not flash\n");
-	}
+	int addr, eep_start_loc = 64;
 
 	for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
@@ -51,9 +45,34 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
 	}
 
 	return true;
-#undef SIZE_EEPROM_4K
 }
 
+static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
+{
+	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+
+	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
+
+	return true;
+}
+
+static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	if (common->bus_ops->ath_bus_type == ATH_USB)
+		return __ath9k_hw_usb_4k_fill_eeprom(ah);
+	else
+		return __ath9k_hw_4k_fill_eeprom(ah);
+}
+
+#undef SIZE_EEPROM_4K
+
 static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
 {
 #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 9b6bc8a..8cd8333 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -17,7 +17,7 @@
 #include "hw.h"
 #include "ar9002_phy.h"
 
-#define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16))
+#define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
 
 static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
 {
@@ -29,25 +29,15 @@ static int ath9k_hw_ar9287_get_eeprom_rev(struct ath_hw *ah)
 	return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
 }
 
-static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
 {
 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 *eep_data;
-	int addr, eep_start_loc;
+	int addr, eep_start_loc = AR9287_EEP_START_LOC;
 	eep_data = (u16 *)eep;
 
-	if (common->bus_ops->ath_bus_type == ATH_USB)
-		eep_start_loc = AR9287_HTC_EEP_START_LOC;
-	else
-		eep_start_loc = AR9287_EEP_START_LOC;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		ath_dbg(common, ATH_DBG_EEPROM,
-			"Reading from EEPROM, not flash\n");
-	}
-
-	for (addr = 0; addr < NUM_EEP_WORDS; addr++) {
+	for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
 					 eep_data)) {
 			ath_dbg(common, ATH_DBG_EEPROM,
@@ -60,6 +50,31 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
 	return true;
 }
 
+static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+	u16 *eep_data = (u16 *)&ah->eeprom.map9287;
+
+	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+				     AR9287_HTC_EEP_START_LOC,
+				     SIZE_EEPROM_AR9287);
+	return true;
+}
+
+static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	if (common->bus_ops->ath_bus_type == ATH_USB)
+		return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
+	else
+		return __ath9k_hw_ar9287_fill_eeprom(ah);
+}
+
 static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
 {
 	u32 sum = 0, el, integer;
@@ -86,7 +101,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
 				need_swap = true;
 				eepdata = (u16 *)(&ah->eeprom);
 
-				for (addr = 0; addr < NUM_EEP_WORDS; addr++) {
+				for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
 					temp = swab16(*eepdata);
 					*eepdata = temp;
 					eepdata++;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 749a936..fccd87d 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -86,9 +86,10 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
 	return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
 }
 
-static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
-{
 #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+
+static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 *eep_data = (u16 *)&ah->eeprom.def;
 	int addr, ar5416_eep_start_loc = 0x100;
@@ -103,9 +104,34 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
 		eep_data++;
 	}
 	return true;
-#undef SIZE_EEPROM_DEF
 }
 
+static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
+{
+	u16 *eep_data = (u16 *)&ah->eeprom.def;
+
+	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+				     0x100, SIZE_EEPROM_DEF);
+	return true;
+}
+
+static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	if (common->bus_ops->ath_bus_type == ATH_USB)
+		return __ath9k_hw_usb_def_fill_eeprom(ah);
+	else
+		return __ath9k_hw_def_fill_eeprom(ah);
+}
+
+#undef SIZE_EEPROM_DEF
+
 static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
 {
 	struct ar5416_eeprom_def *eep =
@@ -221,9 +247,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
 	}
 
 	/* Enable fixup for AR_AN_TOP2 if necessary */
-	if (AR_SREV_9280_20_OR_LATER(ah) &&
-	    (eep->baseEepHeader.version & 0xff) > 0x0a &&
-	    eep->baseEepHeader.pwdclkind == 0)
+	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
+	    ((eep->baseEepHeader.version & 0xff) > 0x0a) &&
+	    (eep->baseEepHeader.pwdclkind == 0))
 		ah->need_an_top2_fixup = 1;
 
 	if ((common->bus_ops->ath_bus_type == ATH_USB) &&
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 1337640..0fb8f8a 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -20,121 +20,31 @@
 /*	 LED functions		*/
 /********************************/
 
-static void ath_led_blink_work(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc,
-					    ath_led_blink_work.work);
-
-	if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
-		return;
-
-	if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
-	    (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
-		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
-	else
-		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
-				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
-
-	ieee80211_queue_delayed_work(sc->hw,
-				     &sc->ath_led_blink_work,
-				     (sc->sc_flags & SC_OP_LED_ON) ?
-					msecs_to_jiffies(sc->led_off_duration) :
-					msecs_to_jiffies(sc->led_on_duration));
-
-	sc->led_on_duration = sc->led_on_cnt ?
-			max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
-			ATH_LED_ON_DURATION_IDLE;
-	sc->led_off_duration = sc->led_off_cnt ?
-			max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
-			ATH_LED_OFF_DURATION_IDLE;
-	sc->led_on_cnt = sc->led_off_cnt = 0;
-	if (sc->sc_flags & SC_OP_LED_ON)
-		sc->sc_flags &= ~SC_OP_LED_ON;
-	else
-		sc->sc_flags |= SC_OP_LED_ON;
-}
-
+#ifdef CONFIG_MAC80211_LEDS
 static void ath_led_brightness(struct led_classdev *led_cdev,
 			       enum led_brightness brightness)
 {
-	struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
-	struct ath_softc *sc = led->sc;
-
-	switch (brightness) {
-	case LED_OFF:
-		if (led->led_type == ATH_LED_ASSOC ||
-		    led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
-				(led->led_type == ATH_LED_RADIO));
-			sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
-			if (led->led_type == ATH_LED_RADIO)
-				sc->sc_flags &= ~SC_OP_LED_ON;
-		} else {
-			sc->led_off_cnt++;
-		}
-		break;
-	case LED_FULL:
-		if (led->led_type == ATH_LED_ASSOC) {
-			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
-			if (led_blink)
-				ieee80211_queue_delayed_work(sc->hw,
-						     &sc->ath_led_blink_work, 0);
-		} else if (led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
-			sc->sc_flags |= SC_OP_LED_ON;
-		} else {
-			sc->led_on_cnt++;
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
-			    char *trigger)
-{
-	int ret;
-
-	led->sc = sc;
-	led->led_cdev.name = led->name;
-	led->led_cdev.default_trigger = trigger;
-	led->led_cdev.brightness_set = ath_led_brightness;
-
-	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
-	if (ret)
-		ath_err(ath9k_hw_common(sc->sc_ah),
-			"Failed to register led:%s", led->name);
-	else
-		led->registered = 1;
-	return ret;
-}
-
-static void ath_unregister_led(struct ath_led *led)
-{
-	if (led->registered) {
-		led_classdev_unregister(&led->led_cdev);
-		led->registered = 0;
-	}
+	struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
 }
 
 void ath_deinit_leds(struct ath_softc *sc)
 {
-	ath_unregister_led(&sc->assoc_led);
-	sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
-	ath_unregister_led(&sc->tx_led);
-	ath_unregister_led(&sc->rx_led);
-	ath_unregister_led(&sc->radio_led);
-	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+	if (!sc->led_registered)
+		return;
+
+	ath_led_brightness(&sc->led_cdev, LED_OFF);
+	led_classdev_unregister(&sc->led_cdev);
 }
 
 void ath_init_leds(struct ath_softc *sc)
 {
-	char *trigger;
 	int ret;
 
 	if (AR_SREV_9287(sc->sc_ah))
 		sc->sc_ah->led_pin = ATH_LED_PIN_9287;
+	else if (AR_SREV_9485(sc->sc_ah))
+		sc->sc_ah->led_pin = ATH_LED_PIN_9485;
 	else
 		sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
 
@@ -144,48 +54,22 @@ void ath_init_leds(struct ath_softc *sc)
 	/* LED off, active low */
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
-	if (led_blink)
-		INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
-
-	trigger = ieee80211_get_radio_led_name(sc->hw);
-	snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
-		"ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->radio_led, trigger);
-	sc->radio_led.led_type = ATH_LED_RADIO;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_assoc_led_name(sc->hw);
-	snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
-		"ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->assoc_led, trigger);
-	sc->assoc_led.led_type = ATH_LED_ASSOC;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_tx_led_name(sc->hw);
-	snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
-		"ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->tx_led, trigger);
-	sc->tx_led.led_type = ATH_LED_TX;
-	if (ret)
-		goto fail;
-
-	trigger = ieee80211_get_rx_led_name(sc->hw);
-	snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
-		"ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
-	ret = ath_register_led(sc, &sc->rx_led, trigger);
-	sc->rx_led.led_type = ATH_LED_RX;
-	if (ret)
-		goto fail;
-
-	return;
-
-fail:
-	if (led_blink)
-		cancel_delayed_work_sync(&sc->ath_led_blink_work);
-	ath_deinit_leds(sc);
+	if (!led_blink)
+		sc->led_cdev.default_trigger =
+			ieee80211_get_radio_led_name(sc->hw);
+
+	snprintf(sc->led_name, sizeof(sc->led_name),
+		"ath9k-%s", wiphy_name(sc->hw->wiphy));
+	sc->led_cdev.name = sc->led_name;
+	sc->led_cdev.brightness_set = ath_led_brightness;
+
+	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+	if (ret < 0)
+		return;
+
+	sc->led_registered = true;
 }
+#endif
 
 /*******************/
 /*	Rfkill	   */
@@ -201,8 +85,7 @@ static bool ath_is_rfkill_set(struct ath_softc *sc)
 
 void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	bool blocked = !!ath_is_rfkill_set(sc);
 
 	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 07b1633..f1b8af6 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -52,6 +52,9 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
 	{ USB_DEVICE(0x083A, 0xA704),
 	  .driver_info = AR9280_USB },  /* SMC Networks */
 
+	{ USB_DEVICE(0x0cf3, 0x20ff),
+	  .driver_info = STORAGE_DEVICE },
+
 	{ },
 };
 
@@ -914,13 +917,11 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info)
 	if (ret) {
 		dev_err(&hif_dev->udev->dev,
 			"ath9k_htc: Unable to allocate URBs\n");
-		goto err_urb;
+		goto err_fw_download;
 	}
 
 	return 0;
 
-err_urb:
-	ath9k_hif_usb_dealloc_urbs(hif_dev);
 err_fw_download:
 	release_firmware(hif_dev->firmware);
 err_fw_req:
@@ -935,6 +936,61 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
 		release_firmware(hif_dev->firmware);
 }
 
+/*
+ * An exact copy of the function from zd1211rw.
+ */
+static int send_eject_command(struct usb_interface *interface)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *iface_desc = &interface->altsetting[0];
+	struct usb_endpoint_descriptor *endpoint;
+	unsigned char *cmd;
+	u8 bulk_out_ep;
+	int r;
+
+	/* Find bulk out endpoint */
+	for (r = 1; r >= 0; r--) {
+		endpoint = &iface_desc->endpoint[r].desc;
+		if (usb_endpoint_dir_out(endpoint) &&
+		    usb_endpoint_xfer_bulk(endpoint)) {
+			bulk_out_ep = endpoint->bEndpointAddress;
+			break;
+		}
+	}
+	if (r == -1) {
+		dev_err(&udev->dev,
+			"ath9k_htc: Could not find bulk out endpoint\n");
+		return -ENODEV;
+	}
+
+	cmd = kzalloc(31, GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENODEV;
+
+	/* USB bulk command block */
+	cmd[0] = 0x55;	/* bulk command signature */
+	cmd[1] = 0x53;	/* bulk command signature */
+	cmd[2] = 0x42;	/* bulk command signature */
+	cmd[3] = 0x43;	/* bulk command signature */
+	cmd[14] = 6;	/* command length */
+
+	cmd[15] = 0x1b;	/* SCSI command: START STOP UNIT */
+	cmd[19] = 0x2;	/* eject disc */
+
+	dev_info(&udev->dev, "Ejecting storage device...\n");
+	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
+		cmd, 31, NULL, 2000);
+	kfree(cmd);
+	if (r)
+		return r;
+
+	/* At this point, the device disconnects and reconnects with the real
+	 * ID numbers. */
+
+	usb_set_intfdata(interface, NULL);
+	return 0;
+}
+
 static int ath9k_hif_usb_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 {
@@ -942,6 +998,9 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
 	struct hif_device_usb *hif_dev;
 	int ret = 0;
 
+	if (id->driver_info == STORAGE_DEVICE)
+		return send_eject_command(interface);
+
 	hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
 	if (!hif_dev) {
 		ret = -ENOMEM;
@@ -1028,12 +1087,13 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
 	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
 	bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
 
-	if (hif_dev) {
-		ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
-		ath9k_htc_hw_free(hif_dev->htc_handle);
-		ath9k_hif_usb_dev_deinit(hif_dev);
-		usb_set_intfdata(interface, NULL);
-	}
+	if (!hif_dev)
+		return;
+
+	ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
+	ath9k_htc_hw_free(hif_dev->htc_handle);
+	ath9k_hif_usb_dev_deinit(hif_dev);
+	usb_set_intfdata(interface, NULL);
 
 	if (!unplugged && (hif_dev->flags & HIF_USB_START))
 		ath9k_hif_usb_reboot(udev);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 780ac5e..753a245 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -32,6 +32,7 @@
 #include "wmi.h"
 
 #define ATH_STA_SHORT_CALINTERVAL 1000    /* 1 second */
+#define ATH_AP_SHORT_CALINTERVAL  100     /* 100 ms */
 #define ATH_ANI_POLLINTERVAL      100     /* 100 ms */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
@@ -204,8 +205,50 @@ struct ath9k_htc_target_stats {
 	__be32 ht_tx_xretries;
 } __packed;
 
+#define ATH9K_HTC_MAX_VIF 2
+#define ATH9K_HTC_MAX_BCN_VIF 2
+
+#define INC_VIF(_priv, _type) do {		\
+		switch (_type) {		\
+		case NL80211_IFTYPE_STATION:	\
+			_priv->num_sta_vif++;	\
+			break;			\
+		case NL80211_IFTYPE_ADHOC:	\
+			_priv->num_ibss_vif++;	\
+			break;			\
+		case NL80211_IFTYPE_AP:		\
+			_priv->num_ap_vif++;	\
+			break;			\
+		default:			\
+			break;			\
+		}				\
+	} while (0)
+
+#define DEC_VIF(_priv, _type) do {		\
+		switch (_type) {		\
+		case NL80211_IFTYPE_STATION:	\
+			_priv->num_sta_vif--;	\
+			break;			\
+		case NL80211_IFTYPE_ADHOC:	\
+			_priv->num_ibss_vif--;	\
+			break;			\
+		case NL80211_IFTYPE_AP:		\
+			_priv->num_ap_vif--;	\
+			break;			\
+		default:			\
+			break;			\
+		}				\
+	} while (0)
+
 struct ath9k_htc_vif {
 	u8 index;
+	u16 seq_no;
+	bool beacon_configured;
+};
+
+struct ath9k_vif_iter_data {
+	const u8 *hw_macaddr;
+	u8 mask[ETH_ALEN];
 };
 
 #define ATH9K_HTC_MAX_STA 8
@@ -310,10 +353,8 @@ struct ath_led {
 
 struct htc_beacon_config {
 	u16 beacon_interval;
-	u16 listen_interval;
 	u16 dtim_period;
 	u16 bmiss_timeout;
-	u8 dtim_count;
 };
 
 struct ath_btcoex {
@@ -333,13 +374,12 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv);
 #define OP_SCANNING		   BIT(1)
 #define OP_LED_ASSOCIATED	   BIT(2)
 #define OP_LED_ON		   BIT(3)
-#define OP_PREAMBLE_SHORT	   BIT(4)
-#define OP_PROTECT_ENABLE	   BIT(5)
-#define OP_ASSOCIATED		   BIT(6)
-#define OP_ENABLE_BEACON	   BIT(7)
-#define OP_LED_DEINIT		   BIT(8)
-#define OP_BT_PRIORITY_DETECTED    BIT(9)
-#define OP_BT_SCAN                 BIT(10)
+#define OP_ENABLE_BEACON	   BIT(4)
+#define OP_LED_DEINIT		   BIT(5)
+#define OP_BT_PRIORITY_DETECTED    BIT(6)
+#define OP_BT_SCAN                 BIT(7)
+#define OP_ANI_RUNNING             BIT(8)
+#define OP_TSF_RESET               BIT(9)
 
 struct ath9k_htc_priv {
 	struct device *dev;
@@ -358,15 +398,24 @@ struct ath9k_htc_priv {
 	enum htc_endpoint_id data_vi_ep;
 	enum htc_endpoint_id data_vo_ep;
 
+	u8 vif_slot;
+	u8 mon_vif_idx;
+	u8 sta_slot;
+	u8 vif_sta_pos[ATH9K_HTC_MAX_VIF];
+	u8 num_ibss_vif;
+	u8 num_sta_vif;
+	u8 num_ap_vif;
+
 	u16 op_flags;
 	u16 curtxpow;
 	u16 txpowlimit;
 	u16 nvifs;
 	u16 nstations;
-	u16 seq_no;
 	u32 bmiss_cnt;
+	bool rearm_ani;
+	bool reconfig_beacon;
 
-	struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS];
+	struct ath9k_hw_cal_data caldata;
 
 	spinlock_t beacon_lock;
 
@@ -382,7 +431,7 @@ struct ath9k_htc_priv {
 	struct ath9k_htc_rx rx;
 	struct tasklet_struct tx_tasklet;
 	struct sk_buff_head tx_queue;
-	struct delayed_work ath9k_ani_work;
+	struct delayed_work ani_work;
 	struct work_struct ps_work;
 	struct work_struct fatal_work;
 
@@ -424,6 +473,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv);
 void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif);
+void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv);
 void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
 
 void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
@@ -436,8 +486,9 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
 int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv);
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
-void ath9k_ani_work(struct work_struct *work);;
-void ath_start_ani(struct ath9k_htc_priv *priv);
+void ath9k_htc_ani_work(struct work_struct *work);
+void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
+void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
 
 int ath9k_tx_init(struct ath9k_htc_priv *priv);
 void ath9k_tx_tasklet(unsigned long data);
@@ -460,7 +511,6 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv);
 void ath9k_ps_work(struct work_struct *work);
 bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
 			enum ath9k_power_mode mode);
-void ath_update_txpow(struct ath9k_htc_priv *priv);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
 void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
index 87cc65a..8d1d879 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
@@ -123,8 +123,9 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
 	/* TSF out of range threshold fixed at 1 second */
 	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-	ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-	ath_dbg(common, ATH_DBG_BEACON,
+	ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
+		intval, tsf, tsftu);
+	ath_dbg(common, ATH_DBG_CONFIG,
 		"bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
 		bs.bs_bmissthreshold, bs.bs_sleepduration,
 		bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
@@ -138,25 +139,81 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
 	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
 }
 
+static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
+				       struct htc_beacon_config *bss_conf)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	enum ath9k_int imask = 0;
+	u32 nexttbtt, intval, tsftu;
+	__be32 htc_imask = 0;
+	int ret;
+	u8 cmd_rsp;
+	u64 tsf;
+
+	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval /= ATH9K_HTC_MAX_BCN_VIF;
+	nexttbtt = intval;
+
+	if (priv->op_flags & OP_TSF_RESET) {
+		intval |= ATH9K_BEACON_RESET_TSF;
+		priv->op_flags &= ~OP_TSF_RESET;
+	} else {
+		/*
+		 * Pull nexttbtt forward to reflect the current TSF.
+		 */
+		tsf = ath9k_hw_gettsf64(priv->ah);
+		tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
+		do {
+			nexttbtt += intval;
+		} while (nexttbtt < tsftu);
+	}
+
+	intval |= ATH9K_BEACON_ENA;
+
+	if (priv->op_flags & OP_ENABLE_BEACON)
+		imask |= ATH9K_INT_SWBA;
+
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n",
+		bss_conf->beacon_interval, nexttbtt, imask);
+
+	WMI_CMD(WMI_DISABLE_INTR_CMDID);
+	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
+	priv->bmiss_cnt = 0;
+	htc_imask = cpu_to_be32(imask);
+	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
+}
+
 static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
 					  struct htc_beacon_config *bss_conf)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	enum ath9k_int imask = 0;
-	u32 nexttbtt, intval;
+	u32 nexttbtt, intval, tsftu;
 	__be32 htc_imask = 0;
 	int ret;
 	u8 cmd_rsp;
+	u64 tsf;
 
 	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
 	nexttbtt = intval;
+
+	/*
+	 * Pull nexttbtt forward to reflect the current TSF.
+	 */
+	tsf = ath9k_hw_gettsf64(priv->ah);
+	tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
+	do {
+		nexttbtt += intval;
+	} while (nexttbtt < tsftu);
+
 	intval |= ATH9K_BEACON_ENA;
 	if (priv->op_flags & OP_ENABLE_BEACON)
 		imask |= ATH9K_INT_SWBA;
 
-	ath_dbg(common, ATH_DBG_BEACON,
-		"IBSS Beacon config, intval: %d, imask: 0x%x\n",
-		bss_conf->beacon_interval, imask);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n",
+		bss_conf->beacon_interval, nexttbtt, imask);
 
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
@@ -207,9 +264,9 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending)
 	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 		struct ieee80211_hdr *hdr =
 			(struct ieee80211_hdr *) beacon->data;
-		priv->seq_no += 0x10;
+		avp->seq_no += 0x10;
 		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		hdr->seq_ctrl |= cpu_to_le16(priv->seq_no);
+		hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
 	}
 
 	tx_ctl.type = ATH9K_HTC_NORMAL;
@@ -253,30 +310,123 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv)
 	}
 }
 
+static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	bool *beacon_configured = (bool *)data;
+	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
+
+	if (vif->type == NL80211_IFTYPE_STATION &&
+	    avp->beacon_configured)
+		*beacon_configured = true;
+}
+
+static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
+					  struct ieee80211_vif *vif)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	bool beacon_configured;
+
+	/*
+	 * Changing the beacon interval when multiple AP interfaces
+	 * are configured will affect beacon transmission of all
+	 * of them.
+	 */
+	if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+	    (priv->num_ap_vif > 1) &&
+	    (vif->type == NL80211_IFTYPE_AP) &&
+	    (cur_conf->beacon_interval != bss_conf->beacon_int)) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Changing beacon interval of multiple AP interfaces !\n");
+		return false;
+	}
+
+	/*
+	 * If the HW is operating in AP mode, any new station interfaces that
+	 * are added cannot change the beacon parameters.
+	 */
+	if (priv->num_ap_vif &&
+	    (vif->type != NL80211_IFTYPE_AP)) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"HW in AP mode, cannot set STA beacon parameters\n");
+		return false;
+	}
+
+	/*
+	 * The beacon parameters are configured only for the first
+	 * station interface.
+	 */
+	if ((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
+	    (priv->num_sta_vif > 1) &&
+	    (vif->type == NL80211_IFTYPE_STATION)) {
+		beacon_configured = false;
+		ieee80211_iterate_active_interfaces_atomic(priv->hw,
+							   ath9k_htc_beacon_iter,
+							   &beacon_configured);
+
+		if (beacon_configured) {
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Beacon already configured for a station interface\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
+
+	if (!ath9k_htc_check_beacon_config(priv, vif))
+		return;
 
 	cur_conf->beacon_interval = bss_conf->beacon_int;
 	if (cur_conf->beacon_interval == 0)
 		cur_conf->beacon_interval = 100;
 
 	cur_conf->dtim_period = bss_conf->dtim_period;
-	cur_conf->listen_interval = 1;
-	cur_conf->dtim_count = 1;
 	cur_conf->bmiss_timeout =
 		ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
 		ath9k_htc_beacon_config_sta(priv, cur_conf);
+		avp->beacon_configured = true;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ath9k_htc_beacon_config_adhoc(priv, cur_conf);
+		break;
+	case NL80211_IFTYPE_AP:
+		ath9k_htc_beacon_config_ap(priv, cur_conf);
+		break;
+	default:
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Unsupported beaconing mode\n");
+		return;
+	}
+}
+
+void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
+
+	switch (priv->ah->opmode) {
+	case NL80211_IFTYPE_STATION:
+		ath9k_htc_beacon_config_sta(priv, cur_conf);
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		ath9k_htc_beacon_config_adhoc(priv, cur_conf);
 		break;
+	case NL80211_IFTYPE_AP:
+		ath9k_htc_beacon_config_ap(priv, cur_conf);
+		break;
 	default:
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Unsupported beaconing mode\n");
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
index fe70f67..7e630a8 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
@@ -389,7 +389,8 @@ void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
 			ret, ah->curchan->channel);
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	/* Start RX */
 	WMI_CMD(WMI_START_RECV_CMDID);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 0352f09..fc67c93 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -294,6 +294,34 @@ static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
 	return be32_to_cpu(val);
 }
 
+static void ath9k_multi_regread(void *hw_priv, u32 *addr,
+				u32 *val, u16 count)
+{
+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+	__be32 tmpaddr[8];
+	__be32 tmpval[8];
+	int i, ret;
+
+       for (i = 0; i < count; i++) {
+	       tmpaddr[i] = cpu_to_be32(addr[i]);
+       }
+
+       ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
+			   (u8 *)tmpaddr , sizeof(u32) * count,
+			   (u8 *)tmpval, sizeof(u32) * count,
+			   100);
+	if (unlikely(ret)) {
+		ath_dbg(common, ATH_DBG_WMI,
+			"Multiple REGISTER READ FAILED (count: %d)\n", count);
+	}
+
+       for (i = 0; i < count; i++) {
+	       val[i] = be32_to_cpu(tmpval[i]);
+       }
+}
+
 static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
 {
 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -404,6 +432,7 @@ static void ath9k_regwrite_flush(void *hw_priv)
 
 static const struct ath_ops ath9k_common_ops = {
 	.read = ath9k_regread,
+	.multi_read = ath9k_multi_regread,
 	.write = ath9k_regwrite,
 	.enable_write_buffer = ath9k_enable_regwrite_buffer,
 	.write_flush = ath9k_regwrite_flush,
@@ -650,7 +679,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
 		     (unsigned long)priv);
 	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
 		     (unsigned long)priv);
-	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
+	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
 
@@ -758,6 +787,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
 	struct ath_hw *ah;
 	int error = 0;
 	struct ath_regulatory *reg;
+	char hw_name[64];
 
 	/* Bring up device */
 	error = ath9k_init_priv(priv, devid, product, drv_info);
@@ -798,6 +828,22 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,
 			goto err_world;
 	}
 
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
+		"BE:%d, BK:%d, VI:%d, VO:%d\n",
+		priv->wmi_cmd_ep,
+		priv->beacon_ep,
+		priv->cab_ep,
+		priv->uapsd_ep,
+		priv->mgmt_ep,
+		priv->data_be_ep,
+		priv->data_bk_ep,
+		priv->data_vi_ep,
+		priv->data_vo_ep);
+
+	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
+	wiphy_info(hw->wiphy, "%s\n", hw_name);
+
 	ath9k_init_leds(priv);
 	ath9k_start_rfkill_poll(priv);
 
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 6bb5995..db8c0c0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -24,17 +24,6 @@ static struct dentry *ath9k_debugfs_root;
 /* Utilities */
 /*************/
 
-void ath_update_txpow(struct ath9k_htc_priv *priv)
-{
-	struct ath_hw *ah = priv->ah;
-
-	if (priv->curtxpow != priv->txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
-		/* read back in case value is clamped */
-		priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
-	}
-}
-
 /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */
 static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
 					      struct ath9k_channel *ichan)
@@ -116,12 +105,88 @@ void ath9k_ps_work(struct work_struct *work)
 	ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
 }
 
+static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_htc_priv *priv = data;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+	if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon)
+		priv->reconfig_beacon = true;
+
+	if (bss_conf->assoc) {
+		priv->rearm_ani = true;
+		priv->reconfig_beacon = true;
+	}
+}
+
+static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
+{
+	priv->rearm_ani = false;
+	priv->reconfig_beacon = false;
+
+	ieee80211_iterate_active_interfaces_atomic(priv->hw,
+						   ath9k_htc_vif_iter, priv);
+	if (priv->rearm_ani)
+		ath9k_htc_start_ani(priv);
+
+	if (priv->reconfig_beacon) {
+		ath9k_htc_ps_wakeup(priv);
+		ath9k_htc_beacon_reconfig(priv);
+		ath9k_htc_ps_restore(priv);
+	}
+}
+
+static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_vif_iter_data *iter_data = data;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+}
+
+static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+				     struct ieee80211_vif *vif)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath9k_vif_iter_data iter_data;
+
+	/*
+	 * Use the hardware MAC address as reference, the hardware uses it
+	 * together with the BSSID mask when matching addresses.
+	 */
+	iter_data.hw_macaddr = common->macaddr;
+	memset(&iter_data.mask, 0xff, ETH_ALEN);
+
+	if (vif)
+		ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
+
+	/* Get list of all active MAC addresses */
+	ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
+						   &iter_data);
+
+	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+	ath_hw_setbssidmask(common);
+}
+
+static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv)
+{
+	if (priv->num_ibss_vif)
+		priv->ah->opmode = NL80211_IFTYPE_ADHOC;
+	else if (priv->num_ap_vif)
+		priv->ah->opmode = NL80211_IFTYPE_AP;
+	else
+		priv->ah->opmode = NL80211_IFTYPE_STATION;
+
+	ath9k_hw_setopmode(priv->ah);
+}
+
 void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 {
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_channel *channel = priv->hw->conf.channel;
-	struct ath9k_hw_cal_data *caldata;
+	struct ath9k_hw_cal_data *caldata = NULL;
 	enum htc_phymode mode;
 	__be16 htc_mode;
 	u8 cmd_rsp;
@@ -130,16 +195,14 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
 
-	if (priv->op_flags & OP_ASSOCIATED)
-		cancel_delayed_work_sync(&priv->ath9k_ani_work);
-
+	ath9k_htc_stop_ani(priv);
 	ieee80211_stop_queues(priv->hw);
 	htc_stop(priv->htc);
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
 	WMI_CMD(WMI_STOP_RECV_CMDID);
 
-	caldata = &priv->caldata[channel->hw_value];
+	caldata = &priv->caldata;
 	ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
 	if (ret) {
 		ath_err(common,
@@ -147,7 +210,8 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 			channel->center_freq, ret);
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	WMI_CMD(WMI_START_RECV_CMDID);
 	ath9k_host_rx_init(priv);
@@ -158,12 +222,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 
 	WMI_CMD(WMI_ENABLE_INTR_CMDID);
 	htc_start(priv->htc);
-
-	if (priv->op_flags & OP_ASSOCIATED) {
-		ath9k_htc_beacon_config(priv, priv->vif);
-		ath_start_ani(priv);
-	}
-
+	ath9k_htc_vif_reconfig(priv);
 	ieee80211_wake_queues(priv->hw);
 
 	ath9k_htc_ps_restore(priv);
@@ -179,7 +238,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 	struct ieee80211_conf *conf = &common->hw->conf;
 	bool fastcc;
 	struct ieee80211_channel *channel = hw->conf.channel;
-	struct ath9k_hw_cal_data *caldata;
+	struct ath9k_hw_cal_data *caldata = NULL;
 	enum htc_phymode mode;
 	__be16 htc_mode;
 	u8 cmd_rsp;
@@ -202,7 +261,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 		channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
 		fastcc);
 
-	caldata = &priv->caldata[channel->hw_value];
+	if (!fastcc)
+		caldata = &priv->caldata;
 	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 	if (ret) {
 		ath_err(common,
@@ -211,7 +271,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 		goto err;
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	WMI_CMD(WMI_START_RECV_CMDID);
 	if (ret)
@@ -230,11 +291,23 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 		goto err;
 
 	htc_start(priv->htc);
+
+	if (!(priv->op_flags & OP_SCANNING) &&
+	    !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+		ath9k_htc_vif_reconfig(priv);
+
 err:
 	ath9k_htc_ps_restore(priv);
 	return ret;
 }
 
+/*
+ * Monitor mode handling is a tad complicated because the firmware requires
+ * an interface to be created exclusively, while mac80211 doesn't associate
+ * an interface with the mode.
+ *
+ * So, for now, only one monitor interface can be configured.
+ */
 static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -244,9 +317,10 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
 
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
-	hvif.index = 0; /* Should do for now */
+	hvif.index = priv->mon_vif_idx;
 	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
 	priv->nvifs--;
+	priv->vif_slot &= ~(1 << priv->mon_vif_idx);
 }
 
 static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
@@ -254,70 +328,87 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct ath9k_htc_target_vif hvif;
 	struct ath9k_htc_target_sta tsta;
-	int ret = 0;
+	int ret = 0, sta_idx;
 	u8 cmd_rsp;
 
-	if (priv->nvifs > 0)
-		return -ENOBUFS;
+	if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) ||
+	    (priv->nstations >= ATH9K_HTC_MAX_STA)) {
+		ret = -ENOBUFS;
+		goto err_vif;
+	}
 
-	if (priv->nstations >= ATH9K_HTC_MAX_STA)
-		return -ENOBUFS;
+	sta_idx = ffz(priv->sta_slot);
+	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) {
+		ret = -ENOBUFS;
+		goto err_vif;
+	}
 
 	/*
 	 * Add an interface.
 	 */
-
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
 
 	hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
-	priv->ah->opmode = NL80211_IFTYPE_MONITOR;
-	hvif.index = priv->nvifs;
+	hvif.index = ffz(priv->vif_slot);
 
 	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
 	if (ret)
-		return ret;
+		goto err_vif;
+
+	/*
+	 * Assign the monitor interface index as a special case here.
+	 * This is needed when the interface is brought down.
+	 */
+	priv->mon_vif_idx = hvif.index;
+	priv->vif_slot |= (1 << hvif.index);
+
+	/*
+	 * Set the hardware mode to monitor only if there are no
+	 * other interfaces.
+	 */
+	if (!priv->nvifs)
+		priv->ah->opmode = NL80211_IFTYPE_MONITOR;
 
 	priv->nvifs++;
 
 	/*
 	 * Associate a station with the interface for packet injection.
 	 */
-
 	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
 
 	memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);
 
 	tsta.is_vif_sta = 1;
-	tsta.sta_index = priv->nstations;
+	tsta.sta_index = sta_idx;
 	tsta.vif_index = hvif.index;
 	tsta.maxampdu = 0xffff;
 
 	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
 	if (ret) {
 		ath_err(common, "Unable to add station entry for monitor mode\n");
-		goto err_vif;
+		goto err_sta;
 	}
 
+	priv->sta_slot |= (1 << sta_idx);
 	priv->nstations++;
-
-	/*
-	 * Set chainmask etc. on the target.
-	 */
-	ret = ath9k_htc_update_cap_target(priv);
-	if (ret)
-		ath_dbg(common, ATH_DBG_CONFIG,
-			"Failed to update capability in target\n");
-
+	priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx;
 	priv->ah->is_monitoring = true;
 
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attached a monitor interface at idx: %d, sta idx: %d\n",
+		priv->mon_vif_idx, sta_idx);
+
 	return 0;
 
-err_vif:
+err_sta:
 	/*
 	 * Remove the interface from the target.
 	 */
 	__ath9k_htc_remove_monitor_interface(priv);
+err_vif:
+	ath_dbg(common, ATH_DBG_FATAL, "Unable to attach a monitor interface\n");
+
 	return ret;
 }
 
@@ -329,7 +420,7 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
 
 	__ath9k_htc_remove_monitor_interface(priv);
 
-	sta_idx = 0; /* Only single interface, for now */
+	sta_idx = priv->vif_sta_pos[priv->mon_vif_idx];
 
 	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
 	if (ret) {
@@ -337,9 +428,14 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
 		return ret;
 	}
 
+	priv->sta_slot &= ~(1 << sta_idx);
 	priv->nstations--;
 	priv->ah->is_monitoring = false;
 
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Removed a monitor interface at idx: %d, sta idx: %d\n",
+		priv->mon_vif_idx, sta_idx);
+
 	return 0;
 }
 
@@ -351,12 +447,16 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
 	struct ath9k_htc_target_sta tsta;
 	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
 	struct ath9k_htc_sta *ista;
-	int ret;
+	int ret, sta_idx;
 	u8 cmd_rsp;
 
 	if (priv->nstations >= ATH9K_HTC_MAX_STA)
 		return -ENOBUFS;
 
+	sta_idx = ffz(priv->sta_slot);
+	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA))
+		return -ENOBUFS;
+
 	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
 
 	if (sta) {
@@ -366,13 +466,13 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
 		tsta.associd = common->curaid;
 		tsta.is_vif_sta = 0;
 		tsta.valid = true;
-		ista->index = priv->nstations;
+		ista->index = sta_idx;
 	} else {
 		memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
 		tsta.is_vif_sta = 1;
 	}
 
-	tsta.sta_index = priv->nstations;
+	tsta.sta_index = sta_idx;
 	tsta.vif_index = avp->index;
 	tsta.maxampdu = 0xffff;
 	if (sta && sta->ht_cap.ht_supported)
@@ -387,12 +487,21 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
 		return ret;
 	}
 
-	if (sta)
+	if (sta) {
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Added a station entry for: %pM (idx: %d)\n",
 			sta->addr, tsta.sta_index);
+	} else {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Added a station entry for VIF %d (idx: %d)\n",
+			avp->index, tsta.sta_index);
+	}
 
+	priv->sta_slot |= (1 << sta_idx);
 	priv->nstations++;
+	if (!sta)
+		priv->vif_sta_pos[avp->index] = sta_idx;
+
 	return 0;
 }
 
@@ -401,6 +510,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
 				    struct ieee80211_sta *sta)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
 	struct ath9k_htc_sta *ista;
 	int ret;
 	u8 cmd_rsp, sta_idx;
@@ -409,7 +519,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
 		ista = (struct ath9k_htc_sta *) sta->drv_priv;
 		sta_idx = ista->index;
 	} else {
-		sta_idx = 0;
+		sta_idx = priv->vif_sta_pos[avp->index];
 	}
 
 	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
@@ -421,12 +531,19 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv,
 		return ret;
 	}
 
-	if (sta)
+	if (sta) {
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Removed a station entry for: %pM (idx: %d)\n",
 			sta->addr, sta_idx);
+	} else {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Removed a station entry for VIF %d (idx: %d)\n",
+			avp->index, sta_idx);
+	}
 
+	priv->sta_slot &= ~(1 << sta_idx);
 	priv->nstations--;
+
 	return 0;
 }
 
@@ -808,7 +925,7 @@ void ath9k_htc_debug_remove_root(void)
 /* ANI */
 /*******/
 
-void ath_start_ani(struct ath9k_htc_priv *priv)
+void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -817,15 +934,22 @@ void ath_start_ani(struct ath9k_htc_priv *priv)
 	common->ani.shortcal_timer = timestamp;
 	common->ani.checkani_timer = timestamp;
 
-	ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work,
+	priv->op_flags |= OP_ANI_RUNNING;
+
+	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
 				     msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
 }
 
-void ath9k_ani_work(struct work_struct *work)
+void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
+{
+	cancel_delayed_work_sync(&priv->ani_work);
+	priv->op_flags &= ~OP_ANI_RUNNING;
+}
+
+void ath9k_htc_ani_work(struct work_struct *work)
 {
 	struct ath9k_htc_priv *priv =
-		container_of(work, struct ath9k_htc_priv,
-			     ath9k_ani_work.work);
+		container_of(work, struct ath9k_htc_priv, ani_work.work);
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	bool longcal = false;
@@ -834,7 +958,8 @@ void ath9k_ani_work(struct work_struct *work)
 	unsigned int timestamp = jiffies_to_msecs(jiffies);
 	u32 cal_interval, short_cal_interval;
 
-	short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
+	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
+		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
 
 	/* Only calibrate if awake */
 	if (ah->power_mode != ATH9K_PM_AWAKE)
@@ -903,7 +1028,7 @@ set_timer:
 	if (!common->ani.caldone)
 		cal_interval = min(cal_interval, (u32)short_cal_interval);
 
-	ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work,
+	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
 				     msecs_to_jiffies(cal_interval));
 }
 
@@ -911,7 +1036,7 @@ set_timer:
 /* mac80211 Callbacks */
 /**********************/
 
-static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr;
 	struct ath9k_htc_priv *priv = hw->priv;
@@ -924,7 +1049,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	padsize = padpos & 3;
 	if (padsize && skb->len > padpos) {
 		if (skb_headroom(skb) < padsize)
-			return -1;
+			goto fail_tx;
 		skb_push(skb, padsize);
 		memmove(skb->data, skb->data + padsize, padpos);
 	}
@@ -945,11 +1070,10 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		goto fail_tx;
 	}
 
-	return 0;
+	return;
 
 fail_tx:
 	dev_kfree_skb_any(skb);
-	return 0;
 }
 
 static int ath9k_htc_start(struct ieee80211_hw *hw)
@@ -987,7 +1111,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 		return ret;
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	mode = ath9k_htc_get_curmode(priv, init_channel);
 	htc_mode = cpu_to_be16(mode);
@@ -997,6 +1122,11 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 
 	ath9k_host_rx_init(priv);
 
+	ret = ath9k_htc_update_cap_target(priv);
+	if (ret)
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Failed to update capability in target\n");
+
 	priv->op_flags &= ~OP_INVALID;
 	htc_start(priv->htc);
 
@@ -1051,25 +1181,21 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	cancel_work_sync(&priv->fatal_work);
 	cancel_work_sync(&priv->ps_work);
 	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+	ath9k_htc_stop_ani(priv);
 	ath9k_led_stop_brightness(priv);
 
 	mutex_lock(&priv->mutex);
 
-	/* Remove monitor interface here */
-	if (ah->opmode == NL80211_IFTYPE_MONITOR) {
-		if (ath9k_htc_remove_monitor_interface(priv))
-			ath_err(common, "Unable to remove monitor interface\n");
-		else
-			ath_dbg(common, ATH_DBG_CONFIG,
-				"Monitor interface removed\n");
-	}
-
 	if (ah->btcoex_hw.enabled) {
 		ath9k_hw_btcoex_disable(ah);
 		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
 			ath_htc_cancel_btcoex_work(priv);
 	}
 
+	/* Remove a monitor interface if it's present. */
+	if (priv->ah->is_monitoring)
+		ath9k_htc_remove_monitor_interface(priv);
+
 	ath9k_hw_phy_disable(ah);
 	ath9k_hw_disable(ah);
 	ath9k_htc_ps_restore(priv);
@@ -1093,10 +1219,24 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 
 	mutex_lock(&priv->mutex);
 
-	/* Only one interface for now */
-	if (priv->nvifs > 0) {
-		ret = -ENOBUFS;
-		goto out;
+	if (priv->nvifs >= ATH9K_HTC_MAX_VIF) {
+		mutex_unlock(&priv->mutex);
+		return -ENOBUFS;
+	}
+
+	if (priv->num_ibss_vif ||
+	    (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+		ath_err(common, "IBSS coexistence with other modes is not allowed\n");
+		mutex_unlock(&priv->mutex);
+		return -ENOBUFS;
+	}
+
+	if (((vif->type == NL80211_IFTYPE_AP) ||
+	     (vif->type == NL80211_IFTYPE_ADHOC)) &&
+	    ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) {
+		ath_err(common, "Max. number of beaconing interfaces reached\n");
+		mutex_unlock(&priv->mutex);
+		return -ENOBUFS;
 	}
 
 	ath9k_htc_ps_wakeup(priv);
@@ -1110,6 +1250,9 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 	case NL80211_IFTYPE_ADHOC:
 		hvif.opmode = cpu_to_be32(HTC_M_IBSS);
 		break;
+	case NL80211_IFTYPE_AP:
+		hvif.opmode = cpu_to_be32(HTC_M_HOSTAP);
+		break;
 	default:
 		ath_err(common,
 			"Interface type %d not yet supported\n", vif->type);
@@ -1117,34 +1260,39 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 		goto out;
 	}
 
-	ath_dbg(common, ATH_DBG_CONFIG,
-		"Attach a VIF of type: %d\n", vif->type);
-
-	priv->ah->opmode = vif->type;
-
 	/* Index starts from zero on the target */
-	avp->index = hvif.index = priv->nvifs;
+	avp->index = hvif.index = ffz(priv->vif_slot);
 	hvif.rtsthreshold = cpu_to_be16(2304);
 	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
 	if (ret)
 		goto out;
 
-	priv->nvifs++;
-
 	/*
 	 * We need a node in target to tx mgmt frames
 	 * before association.
 	 */
 	ret = ath9k_htc_add_station(priv, vif, NULL);
-	if (ret)
+	if (ret) {
+		WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
 		goto out;
+	}
 
-	ret = ath9k_htc_update_cap_target(priv);
-	if (ret)
-		ath_dbg(common, ATH_DBG_CONFIG,
-			"Failed to update capability in target\n");
+	ath9k_htc_set_bssid_mask(priv, vif);
 
+	priv->vif_slot |= (1 << avp->index);
+	priv->nvifs++;
 	priv->vif = vif;
+
+	INC_VIF(priv, vif->type);
+	ath9k_htc_set_opmode(priv);
+
+	if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+	    !(priv->op_flags & OP_ANI_RUNNING))
+		ath9k_htc_start_ani(priv);
+
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
+
 out:
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
@@ -1162,8 +1310,6 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 	int ret = 0;
 	u8 cmd_rsp;
 
-	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
-
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
 
@@ -1172,10 +1318,27 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
 	hvif.index = avp->index;
 	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
 	priv->nvifs--;
+	priv->vif_slot &= ~(1 << avp->index);
 
 	ath9k_htc_remove_station(priv, vif, NULL);
 	priv->vif = NULL;
 
+	DEC_VIF(priv, vif->type);
+	ath9k_htc_set_opmode(priv);
+
+	/*
+	 * Stop ANI only if there are no associated station interfaces.
+	 */
+	if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
+		priv->rearm_ani = false;
+		ieee80211_iterate_active_interfaces_atomic(priv->hw,
+						   ath9k_htc_vif_iter, priv);
+		if (!priv->rearm_ani)
+			ath9k_htc_stop_ani(priv);
+	}
+
+	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface at idx: %d\n", avp->index);
+
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
@@ -1211,13 +1374,11 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 	 * IEEE80211_CONF_CHANGE_CHANNEL is handled.
 	 */
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
-		if (conf->flags & IEEE80211_CONF_MONITOR) {
-			if (ath9k_htc_add_monitor_interface(priv))
-				ath_err(common, "Failed to set monitor mode\n");
-			else
-				ath_dbg(common, ATH_DBG_CONFIG,
-					"HW opmode set to Monitor mode\n");
-		}
+		if ((conf->flags & IEEE80211_CONF_MONITOR) &&
+		    !priv->ah->is_monitoring)
+			ath9k_htc_add_monitor_interface(priv);
+		else if (priv->ah->is_monitoring)
+			ath9k_htc_remove_monitor_interface(priv);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -1252,7 +1413,8 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 		priv->txpowlimit = 2 * conf->power_level;
-		ath_update_txpow(priv);
+		ath9k_cmn_update_txpow(priv->ah, priv->curtxpow,
+				       priv->txpowlimit, &priv->curtxpow);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
@@ -1439,66 +1601,81 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
+	bool set_assoc;
 
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
 
+	/*
+	 * Set the HW AID/BSSID only for the first station interface
+	 * or in IBSS mode.
+	 */
+	set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) ||
+		       ((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
+			(priv->num_sta_vif == 1)));
+
+
 	if (changed & BSS_CHANGED_ASSOC) {
-		common->curaid = bss_conf->assoc ?
-				 bss_conf->aid : 0;
-		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
-			bss_conf->assoc);
-
-		if (bss_conf->assoc) {
-			priv->op_flags |= OP_ASSOCIATED;
-			ath_start_ani(priv);
-		} else {
-			priv->op_flags &= ~OP_ASSOCIATED;
-			cancel_delayed_work_sync(&priv->ath9k_ani_work);
+		if (set_assoc) {
+			ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+				bss_conf->assoc);
+
+			common->curaid = bss_conf->assoc ?
+				bss_conf->aid : 0;
+
+			if (bss_conf->assoc)
+				ath9k_htc_start_ani(priv);
+			else
+				ath9k_htc_stop_ani(priv);
 		}
 	}
 
 	if (changed & BSS_CHANGED_BSSID) {
-		/* Set BSSID */
-		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-		ath9k_hw_write_associd(ah);
+		if (set_assoc) {
+			memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+			ath9k_hw_write_associd(ah);
 
-		ath_dbg(common, ATH_DBG_CONFIG,
-			"BSSID: %pM aid: 0x%x\n",
-			common->curbssid, common->curaid);
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"BSSID: %pM aid: 0x%x\n",
+				common->curbssid, common->curaid);
+		}
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_INT) ||
-	    (changed & BSS_CHANGED_BEACON) ||
-	    ((changed & BSS_CHANGED_BEACON_ENABLED) &&
-	    bss_conf->enable_beacon)) {
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Beacon enabled for BSS: %pM\n", bss_conf->bssid);
 		priv->op_flags |= OP_ENABLE_BEACON;
 		ath9k_htc_beacon_config(priv, vif);
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
-	    !bss_conf->enable_beacon) {
-		priv->op_flags &= ~OP_ENABLE_BEACON;
-		ath9k_htc_beacon_config(priv, vif);
-	}
-
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
-			bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			priv->op_flags |= OP_PREAMBLE_SHORT;
-		else
-			priv->op_flags &= ~OP_PREAMBLE_SHORT;
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) {
+		/*
+		 * Disable SWBA interrupt only if there are no
+		 * AP/IBSS interfaces.
+		 */
+		if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) {
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Beacon disabled for BSS: %pM\n",
+				bss_conf->bssid);
+			priv->op_flags &= ~OP_ENABLE_BEACON;
+			ath9k_htc_beacon_config(priv, vif);
+		}
 	}
 
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
-			bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot &&
-		    hw->conf.channel->band != IEEE80211_BAND_5GHZ)
-			priv->op_flags |= OP_PROTECT_ENABLE;
-		else
-			priv->op_flags &= ~OP_PROTECT_ENABLE;
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		/*
+		 * Reset the HW TSF for the first AP interface.
+		 */
+		if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+		    (priv->nvifs == 1) &&
+		    (priv->num_ap_vif == 1) &&
+		    (vif->type == NL80211_IFTYPE_AP)) {
+			priv->op_flags |= OP_TSF_RESET;
+		}
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Beacon interval changed for BSS: %pM\n",
+			bss_conf->bssid);
+		ath9k_htc_beacon_config(priv, vif);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1557,12 +1734,14 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
 				  struct ieee80211_vif *vif,
 				  enum ieee80211_ampdu_mlme_action action,
 				  struct ieee80211_sta *sta,
-				  u16 tid, u16 *ssn)
+				  u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_sta *ista;
 	int ret = 0;
 
+	mutex_lock(&priv->mutex);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		break;
@@ -1587,6 +1766,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
 		ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
 	}
 
+	mutex_unlock(&priv->mutex);
+
 	return ret;
 }
 
@@ -1599,8 +1780,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
 	priv->op_flags |= OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
 	cancel_work_sync(&priv->ps_work);
-	if (priv->op_flags & OP_ASSOCIATED)
-		cancel_delayed_work_sync(&priv->ath9k_ani_work);
+	ath9k_htc_stop_ani(priv);
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1609,14 +1789,11 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
 	struct ath9k_htc_priv *priv = hw->priv;
 
 	mutex_lock(&priv->mutex);
-	ath9k_htc_ps_wakeup(priv);
 	spin_lock_bh(&priv->beacon_lock);
 	priv->op_flags &= ~OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
-	if (priv->op_flags & OP_ASSOCIATED) {
-		ath9k_htc_beacon_config(priv, priv->vif);
-		ath_start_ani(priv);
-	}
+	ath9k_htc_ps_wakeup(priv);
+	ath9k_htc_vif_reconfig(priv);
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 7a5ffca..4a4f27b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -84,7 +84,9 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = tx_info->control.sta;
+	struct ieee80211_vif *vif = tx_info->control.vif;
 	struct ath9k_htc_sta *ista;
+	struct ath9k_htc_vif *avp;
 	struct ath9k_htc_tx_ctl tx_ctl;
 	enum htc_endpoint_id epid;
 	u16 qnum;
@@ -95,18 +97,31 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
 	hdr = (struct ieee80211_hdr *) skb->data;
 	fc = hdr->frame_control;
 
-	if (tx_info->control.vif &&
-			(struct ath9k_htc_vif *) tx_info->control.vif->drv_priv)
-		vif_idx = ((struct ath9k_htc_vif *)
-				tx_info->control.vif->drv_priv)->index;
-	else
-		vif_idx = priv->nvifs;
+	/*
+	 * Find out on which interface this packet has to be
+	 * sent out.
+	 */
+	if (vif) {
+		avp = (struct ath9k_htc_vif *) vif->drv_priv;
+		vif_idx = avp->index;
+	} else {
+		if (!priv->ah->is_monitoring) {
+			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
+				"VIF is null, but no monitor interface !\n");
+			return -EINVAL;
+		}
 
+		vif_idx = priv->mon_vif_idx;
+	}
+
+	/*
+	 * Find out which station this packet is destined for.
+	 */
 	if (sta) {
 		ista = (struct ath9k_htc_sta *) sta->drv_priv;
 		sta_idx = ista->index;
 	} else {
-		sta_idx = 0;
+		sta_idx = priv->vif_sta_pos[vif_idx];
 	}
 
 	memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
@@ -141,7 +156,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb)
 
 		/* CTS-to-self */
 		if (!(flags & ATH9K_HTC_TX_RTSCTS) &&
-		    (priv->op_flags & OP_PROTECT_ENABLE))
+		    (vif && vif->bss_conf.use_cts_prot))
 			flags |= ATH9K_HTC_TX_CTSONLY;
 
 		tx_hdr.flags = cpu_to_be32(flags);
@@ -217,6 +232,7 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv,
 void ath9k_tx_tasklet(unsigned long data)
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
+	struct ieee80211_vif *vif;
 	struct ieee80211_sta *sta;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *tx_info;
@@ -228,12 +244,16 @@ void ath9k_tx_tasklet(unsigned long data)
 		hdr = (struct ieee80211_hdr *) skb->data;
 		fc = hdr->frame_control;
 		tx_info = IEEE80211_SKB_CB(skb);
+		vif = tx_info->control.vif;
 
 		memset(&tx_info->status, 0, sizeof(tx_info->status));
 
+		if (!vif)
+			goto send_mac80211;
+
 		rcu_read_lock();
 
-		sta = ieee80211_find_sta(priv->vif, hdr->addr1);
+		sta = ieee80211_find_sta(vif, hdr->addr1);
 		if (!sta) {
 			rcu_read_unlock();
 			ieee80211_tx_status(priv->hw, skb);
@@ -263,6 +283,7 @@ void ath9k_tx_tasklet(unsigned long data)
 
 		rcu_read_unlock();
 
+	send_mac80211:
 		/* Send status to mac80211 */
 		ieee80211_tx_status(priv->hw, skb);
 	}
@@ -386,7 +407,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
 	 */
 	if (((ah->opmode != NL80211_IFTYPE_AP) &&
 	     (priv->rxfilter & FIF_PROMISC_IN_BSS)) ||
-	    (ah->opmode == NL80211_IFTYPE_MONITOR))
+	    ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
 	if (priv->rxfilter & FIF_CONTROL)
@@ -398,8 +419,13 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
 	else
 		rfilt |= ATH9K_RX_FILTER_BEACON;
 
-	if (conf_is_ht(&priv->hw->conf))
+	if (conf_is_ht(&priv->hw->conf)) {
 		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
+		rfilt |= ATH9K_RX_FILTER_UNCOMP_BA_BAR;
+	}
+
+	if (priv->rxfilter & FIF_PSPOLL)
+		rfilt |= ATH9K_RX_FILTER_PSPOLL;
 
 	return rfilt;
 
@@ -412,20 +438,12 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
 static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv)
 {
 	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-
 	u32 rfilt, mfilt[2];
 
 	/* configure rx filter */
 	rfilt = ath9k_htc_calcrxfilter(priv);
 	ath9k_hw_setrxfilter(ah, rfilt);
 
-	/* configure bssid mask */
-	ath_hw_setbssidmask(common);
-
-	/* configure operational mode */
-	ath9k_hw_setopmode(ah);
-
 	/* calculate and install multicast filter */
 	mfilt[0] = mfilt[1] = ~0;
 	ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
@@ -576,31 +594,29 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 	ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
 			   rxbuf->rxstatus.rs_flags);
 
-	if (priv->op_flags & OP_ASSOCIATED) {
-		if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
-		    !rxbuf->rxstatus.rs_moreaggr)
-			ATH_RSSI_LPF(priv->rx.last_rssi,
-				     rxbuf->rxstatus.rs_rssi);
+	if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
+	    !rxbuf->rxstatus.rs_moreaggr)
+		ATH_RSSI_LPF(priv->rx.last_rssi,
+			     rxbuf->rxstatus.rs_rssi);
 
-		last_rssi = priv->rx.last_rssi;
+	last_rssi = priv->rx.last_rssi;
 
-		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-			rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
-							     ATH_RSSI_EP_MULTIPLIER);
+	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+		rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
+						     ATH_RSSI_EP_MULTIPLIER);
 
-		if (rxbuf->rxstatus.rs_rssi < 0)
-			rxbuf->rxstatus.rs_rssi = 0;
+	if (rxbuf->rxstatus.rs_rssi < 0)
+		rxbuf->rxstatus.rs_rssi = 0;
 
-		if (ieee80211_is_beacon(fc))
-			priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
-	}
+	if (ieee80211_is_beacon(fc))
+		priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
 
 	rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
 	rx_status->band = hw->conf.channel->band;
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->signal =  rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
 	rx_status->antenna = rxbuf->rxstatus.rs_antenna;
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	return true;
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 9f01e50..338b075 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -495,6 +495,17 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	if (ah->hw_version.devid == AR5416_AR9100_DEVID)
 		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
 
+	ath9k_hw_read_revisions(ah);
+
+	/*
+	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
+	 * We need to do this to avoid RMW of this register. We cannot
+	 * read the reg when chip is asleep.
+	 */
+	ah->WARegVal = REG_READ(ah, AR_WA);
+	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+			 AR_WA_ASPM_TIMER_BASED_DISABLE);
+
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
 		ath_err(common, "Couldn't reset chip\n");
 		return -EIO;
@@ -563,14 +574,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 
 	ath9k_hw_init_mode_regs(ah);
 
-	/*
-	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
-	 * We need to do this to avoid RMW of this register. We cannot
-	 * read the reg when chip is asleep.
-	 */
-	ah->WARegVal = REG_READ(ah, AR_WA);
-	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
-			 AR_WA_ASPM_TIMER_BASED_DISABLE);
 
 	if (ah->is_pciexpress)
 		ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -668,14 +671,51 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
 	REGWRITE_BUFFER_FLUSH(ah);
 }
 
+unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
+{
+		REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK)));
+		udelay(100);
+		REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK));
+
+		while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+			udelay(100);
+
+		return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
+}
+EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
+
+#define DPLL2_KD_VAL            0x3D
+#define DPLL2_KI_VAL            0x06
+#define DPLL3_PHASE_SHIFT_VAL   0x1
+
 static void ath9k_hw_init_pll(struct ath_hw *ah,
 			      struct ath9k_channel *chan)
 {
 	u32 pll;
 
-	if (AR_SREV_9485(ah))
+	if (AR_SREV_9485(ah)) {
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
+		REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01);
+
+		REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
+
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+		udelay(1000);
+
 		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
 
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+			      AR_CH0_DPLL2_KD, DPLL2_KD_VAL);
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+			      AR_CH0_DPLL2_KI, DPLL2_KI_VAL);
+
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
+		udelay(1000);
+	}
+
 	pll = ath9k_hw_compute_pll_control(ah, chan);
 
 	REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
@@ -1060,7 +1100,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 		REG_WRITE(ah, AR_RC, AR_RC_AHB);
 
 	REG_WRITE(ah, AR_RTC_RESET, 0);
-	udelay(2);
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
@@ -1082,8 +1121,6 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 		return false;
 	}
 
-	ath9k_hw_read_revisions(ah);
-
 	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
 }
 
@@ -1348,8 +1385,6 @@ 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);
 
-	ath9k_hw_set_operating_mode(ah, ah->opmode);
-
 	ENABLE_REGWRITE_BUFFER(ah);
 
 	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
@@ -1367,6 +1402,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
+	ath9k_hw_set_operating_mode(ah, ah->opmode);
+
 	r = ath9k_hw_rf_set_freq(ah, chan);
 	if (r)
 		return r;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index ea9fde6..6650fd4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -70,6 +70,9 @@
 #define REG_READ(_ah, _reg) \
 	ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
 
+#define REG_READ_MULTI(_ah, _addr, _val, _cnt)		\
+	ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt))
+
 #define ENABLE_REGWRITE_BUFFER(_ah)					\
 	do {								\
 		if (ath9k_hw_common(_ah)->ops->enable_write_buffer)	\
@@ -92,9 +95,9 @@
 #define REG_READ_FIELD(_a, _r, _f) \
 	(((REG_READ(_a, _r) & _f) >> _f##_S))
 #define REG_SET_BIT(_a, _r, _f) \
-	REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
+	REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
 #define REG_CLR_BIT(_a, _r, _f) \
-	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
+	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
 
 #define DO_DELAY(x) do {			\
 		if ((++(x) % 64) == 0)          \
@@ -926,6 +929,7 @@ void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
 void ath9k_hw_reset_tsf(struct ath_hw *ah);
 void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
 void ath9k_hw_init_global_settings(struct ath_hw *ah);
+unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
 void ath9k_hw_set11nmac2040(struct ath_hw *ah);
 void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
 void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index a033d01..79aec98 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -140,6 +140,21 @@ static struct ieee80211_rate ath9k_legacy_rates[] = {
 	RATE(540, 0x0c, 0),
 };
 
+#ifdef CONFIG_MAC80211_LEDS
+static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
+	{ .throughput = 0 * 1024, .blink_time = 334 },
+	{ .throughput = 1 * 1024, .blink_time = 260 },
+	{ .throughput = 5 * 1024, .blink_time = 220 },
+	{ .throughput = 10 * 1024, .blink_time = 190 },
+	{ .throughput = 20 * 1024, .blink_time = 170 },
+	{ .throughput = 50 * 1024, .blink_time = 150 },
+	{ .throughput = 70 * 1024, .blink_time = 130 },
+	{ .throughput = 100 * 1024, .blink_time = 110 },
+	{ .throughput = 200 * 1024, .blink_time = 80 },
+	{ .throughput = 300 * 1024, .blink_time = 50 },
+};
+#endif
+
 static void ath9k_deinit_softc(struct ath_softc *sc);
 
 /*
@@ -250,8 +265,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
 			      struct regulatory_request *request)
 {
 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
 
 	return ath_reg_notifier_apply(wiphy, request, reg);
@@ -438,9 +452,10 @@ static int ath9k_init_queues(struct ath_softc *sc)
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 	ath_cabq_update(sc);
 
-	for (i = 0; i < WME_NUM_AC; i++)
+	for (i = 0; i < WME_NUM_AC; i++) {
 		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
-
+		sc->tx.txq_map[i]->mac80211_qnum = i;
+	}
 	return 0;
 }
 
@@ -512,10 +527,8 @@ static void ath9k_init_misc(struct ath_softc *sc)
 
 	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
 
-	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
+	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
 		sc->beacon.bslot[i] = NULL;
-		sc->beacon.bslot_aphy[i] = NULL;
-	}
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
 		sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
@@ -533,6 +546,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 	if (!ah)
 		return -ENOMEM;
 
+	ah->hw = sc->hw;
 	ah->hw_version.devid = devid;
 	ah->hw_version.subsysid = subsysid;
 	sc->sc_ah = ah;
@@ -550,10 +564,13 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 	common->btcoex_enabled = ath9k_btcoex_enable == 1;
 	spin_lock_init(&common->cc_lock);
 
-	spin_lock_init(&sc->wiphy_lock);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
 	mutex_init(&sc->mutex);
+#ifdef CONFIG_ATH9K_DEBUGFS
+	spin_lock_init(&sc->nodes_lock);
+	INIT_LIST_HEAD(&sc->nodes);
+#endif
 	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
 	tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
 		     (unsigned long)sc);
@@ -695,7 +712,6 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 		    const struct ath_bus_ops *bus_ops)
 {
 	struct ieee80211_hw *hw = sc->hw;
-	struct ath_wiphy *aphy = hw->priv;
 	struct ath_common *common;
 	struct ath_hw *ah;
 	int error = 0;
@@ -730,6 +746,13 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 
 	ath9k_init_txpower_limits(sc);
 
+#ifdef CONFIG_MAC80211_LEDS
+	/* must be initialized before ieee80211_register_hw */
+	sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+		ARRAY_SIZE(ath9k_tpt_blink));
+#endif
+
 	/* Register with mac80211 */
 	error = ieee80211_register_hw(hw);
 	if (error)
@@ -750,10 +773,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 
 	INIT_WORK(&sc->hw_check_work, ath_hw_check);
 	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
-	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
-	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
-	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
-	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+	sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
 
 	ath_init_leds(sc);
 	ath_start_rfkill_poll(sc);
@@ -805,7 +825,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
 void ath9k_deinit_device(struct ath_softc *sc)
 {
 	struct ieee80211_hw *hw = sc->hw;
-	int i = 0;
 
 	ath9k_ps_wakeup(sc);
 
@@ -814,20 +833,10 @@ void ath9k_deinit_device(struct ath_softc *sc)
 
 	ath9k_ps_restore(sc);
 
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
-			continue;
-		sc->sec_wiphy[i] = NULL;
-		ieee80211_unregister_hw(aphy->hw);
-		ieee80211_free_hw(aphy->hw);
-	}
-
 	ieee80211_unregister_hw(hw);
 	ath_rx_cleanup(sc);
 	ath_tx_cleanup(sc);
 	ath9k_deinit_softc(sc);
-	kfree(sc->sec_wiphy);
 }
 
 void ath_descdma_cleanup(struct ath_softc *sc,
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 2915b11..562257a 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -143,84 +143,59 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
 }
 EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
 
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
 {
-#define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
-#define ATH9K_TIME_QUANTUM		100     /* usec */
-	struct ath_common *common = ath9k_hw_common(ah);
-	struct ath9k_hw_capabilities *pCap = &ah->caps;
-	struct ath9k_tx_queue_info *qi;
-	u32 tsfLow, j, wait;
-	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+	int i, q;
 
-	if (q >= pCap->total_queues) {
-		ath_dbg(common, ATH_DBG_QUEUE,
-			"Stopping TX DMA, invalid queue: %u\n", q);
-		return false;
-	}
+	REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
 
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_dbg(common, ATH_DBG_QUEUE,
-			"Stopping TX DMA, inactive queue: %u\n", q);
-		return false;
-	}
+	REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+	REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
 
-	REG_WRITE(ah, AR_Q_TXD, 1 << q);
+	for (q = 0; q < AR_NUM_QCU; q++) {
+		for (i = 0; i < 1000; i++) {
+			if (i)
+				udelay(5);
 
-	for (wait = wait_time; wait != 0; wait--) {
-		if (ath9k_hw_numtxpending(ah, q) == 0)
-			break;
-		udelay(ATH9K_TIME_QUANTUM);
+			if (!ath9k_hw_numtxpending(ah, q))
+				break;
+		}
 	}
 
-	if (ath9k_hw_numtxpending(ah, q)) {
-		ath_dbg(common, ATH_DBG_QUEUE,
-			"%s: Num of pending TX Frames %d on Q %d\n",
-			__func__, ath9k_hw_numtxpending(ah, q), q);
-
-		for (j = 0; j < 2; j++) {
-			tsfLow = REG_READ(ah, AR_TSF_L32);
-			REG_WRITE(ah, AR_QUIET2,
-				  SM(10, AR_QUIET2_QUIET_DUR));
-			REG_WRITE(ah, AR_QUIET_PERIOD, 100);
-			REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
-			REG_SET_BIT(ah, AR_TIMER_MODE,
-				       AR_QUIET_TIMER_EN);
-
-			if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
-				break;
+	REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+	REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+	REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
 
-			ath_dbg(common, ATH_DBG_QUEUE,
-				"TSF has moved while trying to set quiet time TSF: 0x%08x\n",
-				tsfLow);
-		}
+	REG_WRITE(ah, AR_Q_TXD, 0);
+}
+EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
 
-		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
+{
+#define ATH9K_TX_STOP_DMA_TIMEOUT	1000    /* usec */
+#define ATH9K_TIME_QUANTUM		100     /* usec */
+	int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+	int wait;
 
-		udelay(200);
-		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+	REG_WRITE(ah, AR_Q_TXD, 1 << q);
 
-		wait = wait_time;
-		while (ath9k_hw_numtxpending(ah, q)) {
-			if ((--wait) == 0) {
-				ath_err(common,
-					"Failed to stop TX DMA in 100 msec after killing last frame\n");
-				break;
-			}
+	for (wait = wait_time; wait != 0; wait--) {
+		if (wait != wait_time)
 			udelay(ATH9K_TIME_QUANTUM);
-		}
 
-		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+		if (ath9k_hw_numtxpending(ah, q) == 0)
+			break;
 	}
 
 	REG_WRITE(ah, AR_Q_TXD, 0);
+
 	return wait != 0;
 
 #undef ATH9K_TX_STOP_DMA_TIMEOUT
 #undef ATH9K_TIME_QUANTUM
 }
-EXPORT_SYMBOL(ath9k_hw_stoptxdma);
+EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
 
 void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
 {
@@ -690,17 +665,23 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
 		rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
 
 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+		/*
+		 * Treat these errors as mutually exclusive to avoid spurious
+		 * extra error reports from the hardware. If a CRC error is
+		 * reported, then decryption and MIC errors are irrelevant,
+		 * the frame is going to be dropped either way
+		 */
 		if (ads.ds_rxstatus8 & AR_CRCErr)
 			rs->rs_status |= ATH9K_RXERR_CRC;
-		if (ads.ds_rxstatus8 & AR_PHYErr) {
+		else if (ads.ds_rxstatus8 & AR_PHYErr) {
 			rs->rs_status |= ATH9K_RXERR_PHY;
 			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
 			rs->rs_phyerr = phyerr;
-		}
-		if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
-		if (ads.ds_rxstatus8 & AR_MichaelErr)
+		else if (ads.ds_rxstatus8 & AR_MichaelErr)
 			rs->rs_status |= ATH9K_RXERR_MIC;
+
 		if (ads.ds_rxstatus8 & AR_KeyMiss)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 7512f97..b2b2ff8 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -639,6 +639,8 @@ enum ath9k_rx_filter {
 	ATH9K_RX_FILTER_PHYERR = 0x00000100,
 	ATH9K_RX_FILTER_MYBEACON = 0x00000200,
 	ATH9K_RX_FILTER_COMP_BAR = 0x00000400,
+	ATH9K_RX_FILTER_COMP_BA = 0x00000800,
+	ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000,
 	ATH9K_RX_FILTER_PSPOLL = 0x00004000,
 	ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
 	ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
@@ -674,7 +676,8 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
 void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
 u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
 void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
 bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
 			    const struct ath9k_tx_queue_info *qinfo);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a09d15f..115f162 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -15,20 +15,10 @@
  */
 
 #include <linux/nl80211.h>
+#include <linux/delay.h>
 #include "ath9k.h"
 #include "btcoex.h"
 
-static void ath_update_txpow(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-
-	if (sc->curtxpow != sc->config.txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
-		/* read back in case value is clamped */
-		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
-	}
-}
-
 static u8 parse_mpdudensity(u8 mpdudensity)
 {
 	/*
@@ -64,17 +54,19 @@ static u8 parse_mpdudensity(u8 mpdudensity)
 	}
 }
 
-static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
-						struct ieee80211_hw *hw)
+static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
 {
-	struct ieee80211_channel *curchan = hw->conf.channel;
-	struct ath9k_channel *channel;
-	u8 chan_idx;
+	bool pending = false;
+
+	spin_lock_bh(&txq->axq_lock);
 
-	chan_idx = curchan->hw_value;
-	channel = &sc->sc_ah->channels[chan_idx];
-	ath9k_update_ichannel(sc, hw, channel);
-	return channel;
+	if (txq->axq_depth || !list_empty(&txq->axq_acq))
+		pending = true;
+	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+		pending = !list_empty(&txq->txq_fifo_pending);
+
+	spin_unlock_bh(&txq->axq_lock);
+	return pending;
 }
 
 bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
@@ -177,7 +169,12 @@ static void ath_update_survey_nf(struct ath_softc *sc, int channel)
 	}
 }
 
-static void ath_update_survey_stats(struct ath_softc *sc)
+/*
+ * Updates the survey statistics and returns the busy time since last
+ * update in %, if the measurement duration was long enough for the
+ * result to be useful, -1 otherwise.
+ */
+static int ath_update_survey_stats(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -185,9 +182,10 @@ static void ath_update_survey_stats(struct ath_softc *sc)
 	struct survey_info *survey = &sc->survey[pos];
 	struct ath_cycle_counters *cc = &common->cc_survey;
 	unsigned int div = common->clockrate * 1000;
+	int ret = 0;
 
 	if (!ah->curchan)
-		return;
+		return -1;
 
 	if (ah->power_mode == ATH9K_PM_AWAKE)
 		ath_hw_cycle_counters_update(common);
@@ -202,9 +200,18 @@ static void ath_update_survey_stats(struct ath_softc *sc)
 		survey->channel_time_rx += cc->rx_frame / div;
 		survey->channel_time_tx += cc->tx_frame / div;
 	}
+
+	if (cc->cycles < div)
+		return -1;
+
+	if (cc->cycles > 0)
+		ret = cc->rx_busy * 100 / cc->cycles;
+
 	memset(cc, 0, sizeof(*cc));
 
 	ath_update_survey_nf(sc, pos);
+
+	return ret;
 }
 
 /*
@@ -215,7 +222,6 @@ static void ath_update_survey_stats(struct ath_softc *sc)
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan)
 {
-	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &common->hw->conf;
@@ -227,10 +233,13 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 	if (sc->sc_flags & SC_OP_INVALID)
 		return -EIO;
 
+	sc->hw_busy_count = 0;
+
 	del_timer_sync(&common->ani.timer);
 	cancel_work_sync(&sc->paprd_work);
 	cancel_work_sync(&sc->hw_check_work);
 	cancel_delayed_work_sync(&sc->tx_complete_work);
+	cancel_delayed_work_sync(&sc->hw_pll_work);
 
 	ath9k_ps_wakeup(sc);
 
@@ -251,6 +260,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 	if (!ath_stoprecv(sc))
 		stopped = false;
 
+	if (!ath9k_hw_check_alive(ah))
+		stopped = false;
+
 	/* XXX: do not flush receive queue here. We don't want
 	 * to flush data frames already in queue because of
 	 * changing channel. */
@@ -259,7 +271,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		fastcc = false;
 
 	if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
-		caldata = &aphy->caldata;
+		caldata = &sc->caldata;
 
 	ath_dbg(common, ATH_DBG_CONFIG,
 		"(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
@@ -281,17 +293,21 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		goto ps_restore;
 	}
 
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->config.txpowlimit, &sc->curtxpow);
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
 	if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
 		if (sc->sc_flags & SC_OP_BEACONS)
 			ath_beacon_config(sc, NULL);
 		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
 		ath_start_ani(common);
 	}
 
  ps_restore:
+	ieee80211_wake_queues(hw);
+
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
 	ath9k_ps_restore(sc);
@@ -549,6 +565,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
 	struct ath_hw *ah = sc->sc_ah;
 	an = (struct ath_node *)sta->drv_priv;
 
+#ifdef CONFIG_ATH9K_DEBUGFS
+	spin_lock(&sc->nodes_lock);
+	list_add(&an->list, &sc->nodes);
+	spin_unlock(&sc->nodes_lock);
+	an->sta = sta;
+#endif
 	if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
 		sc->sc_flags |= SC_OP_ENABLE_APM;
 
@@ -564,6 +586,13 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
 {
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 
+#ifdef CONFIG_ATH9K_DEBUGFS
+	spin_lock(&sc->nodes_lock);
+	list_del(&an->list);
+	spin_unlock(&sc->nodes_lock);
+	an->sta = NULL;
+#endif
+
 	if (sc->sc_flags & SC_OP_TXAGGR)
 		ath_tx_node_cleanup(sc, an);
 }
@@ -571,17 +600,25 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
 void ath_hw_check(struct work_struct *work)
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
-	int i;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	unsigned long flags;
+	int busy;
 
 	ath9k_ps_wakeup(sc);
+	if (ath9k_hw_check_alive(sc->sc_ah))
+		goto out;
 
-	for (i = 0; i < 3; i++) {
-		if (ath9k_hw_check_alive(sc->sc_ah))
-			goto out;
+	spin_lock_irqsave(&common->cc_lock, flags);
+	busy = ath_update_survey_stats(sc);
+	spin_unlock_irqrestore(&common->cc_lock, flags);
 
-		msleep(1);
-	}
-	ath_reset(sc, true);
+	ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
+		"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+	if (busy >= 99) {
+		if (++sc->hw_busy_count >= 3)
+			ath_reset(sc, true);
+	} else if (busy >= 0)
+		sc->hw_busy_count = 0;
 
 out:
 	ath9k_ps_restore(sc);
@@ -604,7 +641,15 @@ void ath9k_tasklet(unsigned long data)
 	ath9k_ps_wakeup(sc);
 	spin_lock(&sc->sc_pcu_lock);
 
-	if (!ath9k_hw_check_alive(ah))
+	/*
+	 * Only run the baseband hang check if beacons stop working in AP or
+	 * IBSS mode, because it has a high false positive rate. For station
+	 * mode it should not be necessary, since the upper layers will detect
+	 * this through a beacon miss automatically and the following channel
+	 * change will trigger a hardware reset anyway
+	 */
+	if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 &&
+	    !ath9k_hw_check_alive(ah))
 		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
@@ -783,54 +828,11 @@ chip_reset:
 #undef SCHED_INTR
 }
 
-static u32 ath_get_extchanmode(struct ath_softc *sc,
-			       struct ieee80211_channel *chan,
-			       enum nl80211_channel_type channel_type)
-{
-	u32 chanmode = 0;
-
-	switch (chan->band) {
-	case IEEE80211_BAND_2GHZ:
-		switch(channel_type) {
-		case NL80211_CHAN_NO_HT:
-		case NL80211_CHAN_HT20:
-			chanmode = CHANNEL_G_HT20;
-			break;
-		case NL80211_CHAN_HT40PLUS:
-			chanmode = CHANNEL_G_HT40PLUS;
-			break;
-		case NL80211_CHAN_HT40MINUS:
-			chanmode = CHANNEL_G_HT40MINUS;
-			break;
-		}
-		break;
-	case IEEE80211_BAND_5GHZ:
-		switch(channel_type) {
-		case NL80211_CHAN_NO_HT:
-		case NL80211_CHAN_HT20:
-			chanmode = CHANNEL_A_HT20;
-			break;
-		case NL80211_CHAN_HT40PLUS:
-			chanmode = CHANNEL_A_HT40PLUS;
-			break;
-		case NL80211_CHAN_HT40MINUS:
-			chanmode = CHANNEL_A_HT40MINUS;
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-	return chanmode;
-}
-
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
 				 struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf)
 {
-	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 
@@ -854,7 +856,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 		ath_beacon_config(sc, vif);
 
 		/* Reset rssi stats */
-		aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+		sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
 		sc->sc_flags |= SC_OP_ANI_RUN;
@@ -881,7 +883,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	ath9k_hw_configpcipowersave(ah, 0, 0);
 
 	if (!ah->curchan)
-		ah->curchan = ath_get_curchannel(sc, sc->hw);
+		ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
 
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
@@ -890,7 +892,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 			channel->center_freq, r);
 	}
 
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->config.txpowlimit, &sc->curtxpow);
 	if (ath_startrecv(sc) != 0) {
 		ath_err(common, "Unable to restart recv logic\n");
 		goto out;
@@ -907,6 +910,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 
 	ieee80211_wake_queues(hw);
+	ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
+
 out:
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
@@ -920,6 +925,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	int r;
 
 	ath9k_ps_wakeup(sc);
+	cancel_delayed_work_sync(&sc->hw_pll_work);
+
 	spin_lock_bh(&sc->sc_pcu_lock);
 
 	ieee80211_stop_queues(hw);
@@ -942,7 +949,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	ath_flushrecv(sc);		/* flush recv queue */
 
 	if (!ah->curchan)
-		ah->curchan = ath_get_curchannel(sc, hw);
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
 
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
@@ -966,6 +973,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	struct ieee80211_hw *hw = sc->hw;
 	int r;
 
+	sc->hw_busy_count = 0;
+
 	/* Stop ANI */
 	del_timer_sync(&common->ani.timer);
 
@@ -993,7 +1002,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	 * that changes the channel so update any state that
 	 * might change as a result.
 	 */
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->config.txpowlimit, &sc->curtxpow);
 
 	if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
 		ath_beacon_config(sc, NULL);	/* restart beacons */
@@ -1021,38 +1031,13 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	return r;
 }
 
-/* XXX: Remove me once we don't depend on ath9k_channel for all
- * this redundant data */
-void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
-			   struct ath9k_channel *ichan)
-{
-	struct ieee80211_channel *chan = hw->conf.channel;
-	struct ieee80211_conf *conf = &hw->conf;
-
-	ichan->channel = chan->center_freq;
-	ichan->chan = chan;
-
-	if (chan->band == IEEE80211_BAND_2GHZ) {
-		ichan->chanmode = CHANNEL_G;
-		ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G;
-	} else {
-		ichan->chanmode = CHANNEL_A;
-		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
-	}
-
-	if (conf_is_ht(conf))
-		ichan->chanmode = ath_get_extchanmode(sc, chan,
-					    conf->channel_type);
-}
-
 /**********************/
 /* mac80211 callbacks */
 /**********************/
 
 static int ath9k_start(struct ieee80211_hw *hw)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_channel *curchan = hw->conf.channel;
@@ -1065,32 +1050,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
 	mutex_lock(&sc->mutex);
 
-	if (ath9k_wiphy_started(sc)) {
-		if (sc->chan_idx == curchan->hw_value) {
-			/*
-			 * Already on the operational channel, the new wiphy
-			 * can be marked active.
-			 */
-			aphy->state = ATH_WIPHY_ACTIVE;
-			ieee80211_wake_queues(hw);
-		} else {
-			/*
-			 * Another wiphy is on another channel, start the new
-			 * wiphy in paused state.
-			 */
-			aphy->state = ATH_WIPHY_PAUSED;
-			ieee80211_stop_queues(hw);
-		}
-		mutex_unlock(&sc->mutex);
-		return 0;
-	}
-	aphy->state = ATH_WIPHY_ACTIVE;
-
 	/* setup initial channel */
-
 	sc->chan_idx = curchan->hw_value;
 
-	init_channel = ath_get_curchannel(sc, hw);
+	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
 	/* Reset SERDES registers */
 	ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -1116,7 +1079,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
 	 * This is needed only to setup initial state
 	 * but it's best done after a reset.
 	 */
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			sc->config.txpowlimit, &sc->curtxpow);
 
 	/*
 	 * Setup the hardware after reset:
@@ -1182,22 +1146,13 @@ mutex_unlock:
 	return r;
 }
 
-static int ath9k_tx(struct ieee80211_hw *hw,
-		    struct sk_buff *skb)
+static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_tx_control txctl;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 
-	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
-		ath_dbg(common, ATH_DBG_XMIT,
-			"ath9k: %s: TX in unexpected wiphy state %d\n",
-			wiphy_name(hw->wiphy), aphy->state);
-		goto exit;
-	}
-
 	if (sc->ps_enabled) {
 		/*
 		 * mac80211 does not set PM field for normal data frames, so we
@@ -1248,52 +1203,30 @@ static int ath9k_tx(struct ieee80211_hw *hw,
 		goto exit;
 	}
 
-	return 0;
+	return;
 exit:
 	dev_kfree_skb_any(skb);
-	return 0;
 }
 
 static void ath9k_stop(struct ieee80211_hw *hw)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int i;
 
 	mutex_lock(&sc->mutex);
 
-	aphy->state = ATH_WIPHY_INACTIVE;
-
-	if (led_blink)
-		cancel_delayed_work_sync(&sc->ath_led_blink_work);
-
 	cancel_delayed_work_sync(&sc->tx_complete_work);
+	cancel_delayed_work_sync(&sc->hw_pll_work);
 	cancel_work_sync(&sc->paprd_work);
 	cancel_work_sync(&sc->hw_check_work);
 
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i])
-			break;
-	}
-
-	if (i == sc->num_sec_wiphy) {
-		cancel_delayed_work_sync(&sc->wiphy_work);
-		cancel_work_sync(&sc->chan_work);
-	}
-
 	if (sc->sc_flags & SC_OP_INVALID) {
 		ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
 		mutex_unlock(&sc->mutex);
 		return;
 	}
 
-	if (ath9k_wiphy_started(sc)) {
-		mutex_unlock(&sc->mutex);
-		return; /* another wiphy still in use */
-	}
-
 	/* Ensure HW is awake when we try to shut it down. */
 	ath9k_ps_wakeup(sc);
 
@@ -1319,6 +1252,11 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 	} else
 		sc->rx.rxlink = NULL;
 
+	if (sc->rx.frag) {
+		dev_kfree_skb_any(sc->rx.frag);
+		sc->rx.frag = NULL;
+	}
+
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(ah);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
@@ -1334,7 +1272,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 	ath9k_ps_restore(sc);
 
 	sc->ps_idle = true;
-	ath9k_set_wiphy_idle(aphy, true);
 	ath_radio_disable(sc, hw);
 
 	sc->sc_flags |= SC_OP_INVALID;
@@ -1344,112 +1281,225 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 	ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
 }
 
-static int ath9k_add_interface(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif)
+bool ath9k_uses_beacons(int type)
+{
+	switch (type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void ath9k_reclaim_beacon(struct ath_softc *sc,
+				 struct ieee80211_vif *vif)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
-	enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
-	int ret = 0;
 
-	mutex_lock(&sc->mutex);
+	ath9k_set_beaconing_status(sc, false);
+	ath_beacon_return(sc, avp);
+	ath9k_set_beaconing_status(sc, true);
+	sc->sc_flags &= ~SC_OP_BEACONS;
+}
+
+static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_vif_iter_data *iter_data = data;
+	int i;
+
+	if (iter_data->hw_macaddr)
+		for (i = 0; i < ETH_ALEN; i++)
+			iter_data->mask[i] &=
+				~(iter_data->hw_macaddr[i] ^ mac[i]);
 
 	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		ic_opmode = NL80211_IFTYPE_STATION;
+	case NL80211_IFTYPE_AP:
+		iter_data->naps++;
 		break;
-	case NL80211_IFTYPE_WDS:
-		ic_opmode = NL80211_IFTYPE_WDS;
+	case NL80211_IFTYPE_STATION:
+		iter_data->nstations++;
 		break;
 	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_AP:
+		iter_data->nadhocs++;
+		break;
 	case NL80211_IFTYPE_MESH_POINT:
-		if (sc->nbcnvifs >= ATH_BCBUF) {
-			ret = -ENOBUFS;
-			goto out;
-		}
-		ic_opmode = vif->type;
+		iter_data->nmeshes++;
+		break;
+	case NL80211_IFTYPE_WDS:
+		iter_data->nwds++;
 		break;
 	default:
-		ath_err(common, "Interface type %d not yet supported\n",
-			vif->type);
-		ret = -EOPNOTSUPP;
-		goto out;
+		iter_data->nothers++;
+		break;
 	}
+}
 
-	ath_dbg(common, ATH_DBG_CONFIG,
-		"Attach a VIF of type: %d\n", ic_opmode);
+/* Called with sc->mutex held. */
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ath9k_vif_iter_data *iter_data)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 
-	/* Set the VIF opmode */
-	avp->av_opmode = ic_opmode;
-	avp->av_bslot = -1;
+	/*
+	 * Use the hardware MAC address as reference, the hardware uses it
+	 * together with the BSSID mask when matching addresses.
+	 */
+	memset(iter_data, 0, sizeof(*iter_data));
+	iter_data->hw_macaddr = common->macaddr;
+	memset(&iter_data->mask, 0xff, ETH_ALEN);
 
-	sc->nvifs++;
+	if (vif)
+		ath9k_vif_iter(iter_data, vif->addr, vif);
+
+	/* Get list of all active MAC addresses */
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
+						   iter_data);
+}
 
-	ath9k_set_bssid_mask(hw, vif);
+/* Called with sc->mutex held. */
+static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath9k_vif_iter_data iter_data;
 
-	if (sc->nvifs > 1)
-		goto out; /* skip global settings for secondary vif */
+	ath9k_calculate_iter_data(hw, vif, &iter_data);
+
+	ath9k_ps_wakeup(sc);
+	/* Set BSSID mask. */
+	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+	ath_hw_setbssidmask(common);
 
-	if (ic_opmode == NL80211_IFTYPE_AP) {
+	/* Set op-mode & TSF */
+	if (iter_data.naps > 0) {
 		ath9k_hw_set_tsfadjust(ah, 1);
 		sc->sc_flags |= SC_OP_TSF_RESET;
-	}
+		ah->opmode = NL80211_IFTYPE_AP;
+	} else {
+		ath9k_hw_set_tsfadjust(ah, 0);
+		sc->sc_flags &= ~SC_OP_TSF_RESET;
 
-	/* Set the device opmode */
-	ah->opmode = ic_opmode;
+		if (iter_data.nwds + iter_data.nmeshes)
+			ah->opmode = NL80211_IFTYPE_AP;
+		else if (iter_data.nadhocs)
+			ah->opmode = NL80211_IFTYPE_ADHOC;
+		else
+			ah->opmode = NL80211_IFTYPE_STATION;
+	}
 
 	/*
 	 * Enable MIB interrupts when there are hardware phy counters.
-	 * Note we only do this (at the moment) for station mode.
 	 */
-	if ((vif->type == NL80211_IFTYPE_STATION) ||
-	    (vif->type == NL80211_IFTYPE_ADHOC) ||
-	    (vif->type == NL80211_IFTYPE_MESH_POINT)) {
+	if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
 		if (ah->config.enable_ani)
 			ah->imask |= ATH9K_INT_MIB;
 		ah->imask |= ATH9K_INT_TSFOOR;
+	} else {
+		ah->imask &= ~ATH9K_INT_MIB;
+		ah->imask &= ~ATH9K_INT_TSFOOR;
 	}
 
 	ath9k_hw_set_interrupts(ah, ah->imask);
+	ath9k_ps_restore(sc);
 
-	if (vif->type == NL80211_IFTYPE_AP    ||
-	    vif->type == NL80211_IFTYPE_ADHOC) {
+	/* Set up ANI */
+	if ((iter_data.naps + iter_data.nadhocs) > 0) {
 		sc->sc_flags |= SC_OP_ANI_RUN;
 		ath_start_ani(common);
+	} else {
+		sc->sc_flags &= ~SC_OP_ANI_RUN;
+		del_timer_sync(&common->ani.timer);
 	}
+}
 
-out:
-	mutex_unlock(&sc->mutex);
-	return ret;
+/* Called with sc->mutex held, vif counts set up properly. */
+static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = hw->priv;
+
+	ath9k_calculate_summary_state(hw, vif);
+
+	if (ath9k_uses_beacons(vif->type)) {
+		int error;
+		/* This may fail because upper levels do not have beacons
+		 * properly configured yet.  That's OK, we assume it
+		 * will be properly configured and then we will be notified
+		 * in the info_changed method and set up beacons properly
+		 * there.
+		 */
+		ath9k_set_beaconing_status(sc, false);
+		error = ath_beacon_alloc(sc, vif);
+		if (!error)
+			ath_beacon_config(sc, vif);
+		ath9k_set_beaconing_status(sc, true);
+	}
 }
 
-static void ath9k_reclaim_beacon(struct ath_softc *sc,
-				 struct ieee80211_vif *vif)
+
+static int ath9k_add_interface(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif)
 {
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
+	int ret = 0;
 
-	/* Disable SWBA interrupt */
-	sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
-	ath9k_ps_wakeup(sc);
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
-	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-	tasklet_kill(&sc->bcon_tasklet);
-	ath9k_ps_restore(sc);
+	mutex_lock(&sc->mutex);
 
-	ath_beacon_return(sc, avp);
-	sc->sc_flags &= ~SC_OP_BEACONS;
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_MESH_POINT:
+		break;
+	default:
+		ath_err(common, "Interface type %d not yet supported\n",
+			vif->type);
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
 
-	if (sc->nbcnvifs > 0) {
-		/* Re-enable beaconing */
-		sc->sc_ah->imask |= ATH9K_INT_SWBA;
-		ath9k_ps_wakeup(sc);
-		ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
-		ath9k_ps_restore(sc);
+	if (ath9k_uses_beacons(vif->type)) {
+		if (sc->nbcnvifs >= ATH_BCBUF) {
+			ath_err(common, "Not enough beacon buffers when adding"
+				" new interface of type: %i\n",
+				vif->type);
+			ret = -ENOBUFS;
+			goto out;
+		}
 	}
+
+	if ((vif->type == NL80211_IFTYPE_ADHOC) &&
+	    sc->nvifs > 0) {
+		ath_err(common, "Cannot create ADHOC interface when other"
+			" interfaces already exist.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attach a VIF of type: %d\n", vif->type);
+
+	/* Set the VIF opmode */
+	avp->av_opmode = vif->type;
+	avp->av_bslot = -1;
+
+	sc->nvifs++;
+
+	ath9k_do_vif_add_setup(hw, vif);
+out:
+	mutex_unlock(&sc->mutex);
+	return ret;
 }
 
 static int ath9k_change_interface(struct ieee80211_hw *hw,
@@ -1457,40 +1507,40 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
 				  enum nl80211_iftype new_type,
 				  bool p2p)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int ret = 0;
 
 	ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
 	mutex_lock(&sc->mutex);
 
-	switch (new_type) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_ADHOC:
+	/* See if new interface type is valid. */
+	if ((new_type == NL80211_IFTYPE_ADHOC) &&
+	    (sc->nvifs > 1)) {
+		ath_err(common, "When using ADHOC, it must be the only"
+			" interface.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ath9k_uses_beacons(new_type) &&
+	    !ath9k_uses_beacons(vif->type)) {
 		if (sc->nbcnvifs >= ATH_BCBUF) {
 			ath_err(common, "No beacon slot available\n");
 			ret = -ENOBUFS;
 			goto out;
 		}
-		break;
-	case NL80211_IFTYPE_STATION:
-		/* Stop ANI */
-		sc->sc_flags &= ~SC_OP_ANI_RUN;
-		del_timer_sync(&common->ani.timer);
-		if ((vif->type == NL80211_IFTYPE_AP) ||
-		    (vif->type == NL80211_IFTYPE_ADHOC))
-			ath9k_reclaim_beacon(sc, vif);
-		break;
-	default:
-		ath_err(common, "Interface type %d not yet supported\n",
-				vif->type);
-		ret = -ENOTSUPP;
-		goto out;
 	}
+
+	/* Clean up old vif stuff */
+	if (ath9k_uses_beacons(vif->type))
+		ath9k_reclaim_beacon(sc, vif);
+
+	/* Add new settings */
 	vif->type = new_type;
 	vif->p2p = p2p;
 
+	ath9k_do_vif_add_setup(hw, vif);
 out:
 	mutex_unlock(&sc->mutex);
 	return ret;
@@ -1499,25 +1549,20 @@ out:
 static void ath9k_remove_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
 	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
 	mutex_lock(&sc->mutex);
 
-	/* Stop ANI */
-	sc->sc_flags &= ~SC_OP_ANI_RUN;
-	del_timer_sync(&common->ani.timer);
+	sc->nvifs--;
 
 	/* Reclaim beacon resources */
-	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
-	    (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
+	if (ath9k_uses_beacons(vif->type))
 		ath9k_reclaim_beacon(sc, vif);
 
-	sc->nvifs--;
+	ath9k_calculate_summary_state(hw, NULL);
 
 	mutex_unlock(&sc->mutex);
 }
@@ -1558,12 +1603,11 @@ static void ath9k_disable_ps(struct ath_softc *sc)
 
 static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &hw->conf;
-	bool disable_radio;
+	bool disable_radio = false;
 
 	mutex_lock(&sc->mutex);
 
@@ -1574,29 +1618,13 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 	 * the end.
 	 */
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
-		bool enable_radio;
-		bool all_wiphys_idle;
-		bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
-
-		spin_lock_bh(&sc->wiphy_lock);
-		all_wiphys_idle =  ath9k_all_wiphys_idle(sc);
-		ath9k_set_wiphy_idle(aphy, idle);
-
-		enable_radio = (!idle && all_wiphys_idle);
-
-		/*
-		 * After we unlock here its possible another wiphy
-		 * can be re-renabled so to account for that we will
-		 * only disable the radio toward the end of this routine
-		 * if by then all wiphys are still idle.
-		 */
-		spin_unlock_bh(&sc->wiphy_lock);
-
-		if (enable_radio) {
-			sc->ps_idle = false;
+		sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+		if (!sc->ps_idle) {
 			ath_radio_enable(sc, hw);
 			ath_dbg(common, ATH_DBG_CONFIG,
 				"not-idle: enabling radio\n");
+		} else {
+			disable_radio = true;
 		}
 	}
 
@@ -1637,29 +1665,17 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 		if (ah->curchan)
 			old_pos = ah->curchan - &ah->channels[0];
 
-		aphy->chan_idx = pos;
-		aphy->chan_is_ht = conf_is_ht(conf);
 		if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
 			sc->sc_flags |= SC_OP_OFFCHANNEL;
 		else
 			sc->sc_flags &= ~SC_OP_OFFCHANNEL;
 
-		if (aphy->state == ATH_WIPHY_SCAN ||
-		    aphy->state == ATH_WIPHY_ACTIVE)
-			ath9k_wiphy_pause_all_forced(sc, aphy);
-		else {
-			/*
-			 * Do not change operational channel based on a paused
-			 * wiphy changes.
-			 */
-			goto skip_chan_change;
-		}
-
-		ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
-			curchan->center_freq);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Set channel: %d MHz type: %d\n",
+			curchan->center_freq, conf->channel_type);
 
-		/* XXX: remove me eventualy */
-		ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
+		ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+					  curchan, conf->channel_type);
 
 		/* update survey stats for the old channel before switching */
 		spin_lock_irqsave(&common->cc_lock, flags);
@@ -1701,21 +1717,18 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 			ath_update_survey_nf(sc, old_pos);
 	}
 
-skip_chan_change:
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Set power: %d\n", conf->power_level);
 		sc->config.txpowlimit = 2 * conf->power_level;
 		ath9k_ps_wakeup(sc);
-		ath_update_txpow(sc);
+		ath9k_cmn_update_txpow(ah, sc->curtxpow,
+				       sc->config.txpowlimit, &sc->curtxpow);
 		ath9k_ps_restore(sc);
 	}
 
-	spin_lock_bh(&sc->wiphy_lock);
-	disable_radio = ath9k_all_wiphys_idle(sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-
 	if (disable_radio) {
 		ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
-		sc->ps_idle = true;
 		ath_radio_disable(sc, hw);
 	}
 
@@ -1740,8 +1753,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
 				   unsigned int *total_flags,
 				   u64 multicast)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	u32 rfilt;
 
 	changed_flags &= SUPPORTED_FILTERS;
@@ -1761,8 +1773,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
 			 struct ieee80211_vif *vif,
 			 struct ieee80211_sta *sta)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	ath_node_attach(sc, sta);
 
@@ -1773,8 +1784,7 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    struct ieee80211_sta *sta)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	ath_node_detach(sc, sta);
 
@@ -1784,8 +1794,7 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw,
 static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 			 const struct ieee80211_tx_queue_params *params)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_txq *txq;
 	struct ath9k_tx_queue_info qi;
@@ -1829,8 +1838,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 			 struct ieee80211_sta *sta,
 			 struct ieee80211_key_conf *key)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int ret = 0;
 
@@ -1874,8 +1882,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 				   struct ieee80211_bss_conf *bss_conf,
 				   u32 changed)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
@@ -1904,10 +1912,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 	/* Enable transmission of beacons (AP, IBSS, MESH) */
 	if ((changed & BSS_CHANGED_BEACON) ||
 	    ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
-		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-		error = ath_beacon_alloc(aphy, vif);
+		ath9k_set_beaconing_status(sc, false);
+		error = ath_beacon_alloc(sc, vif);
 		if (!error)
 			ath_beacon_config(sc, vif);
+		ath9k_set_beaconing_status(sc, true);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1930,21 +1939,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	/* Disable transmission of beacons */
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
-		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
+	    !bss_conf->enable_beacon) {
+		ath9k_set_beaconing_status(sc, false);
+		avp->is_bslot_active = false;
+		ath9k_set_beaconing_status(sc, true);
+	}
 
 	if (changed & BSS_CHANGED_BEACON_INT) {
-		sc->beacon_interval = bss_conf->beacon_int;
+		cur_conf->beacon_interval = bss_conf->beacon_int;
 		/*
 		 * In case of AP mode, the HW TSF has to be reset
 		 * when the beacon interval changes.
 		 */
 		if (vif->type == NL80211_IFTYPE_AP) {
 			sc->sc_flags |= SC_OP_TSF_RESET;
-			ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-			error = ath_beacon_alloc(aphy, vif);
+			ath9k_set_beaconing_status(sc, false);
+			error = ath_beacon_alloc(sc, vif);
 			if (!error)
 				ath_beacon_config(sc, vif);
+			ath9k_set_beaconing_status(sc, true);
 		} else {
 			ath_beacon_config(sc, vif);
 		}
@@ -1980,9 +1994,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 
 static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
 {
+	struct ath_softc *sc = hw->priv;
 	u64 tsf;
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
 
 	mutex_lock(&sc->mutex);
 	ath9k_ps_wakeup(sc);
@@ -1995,8 +2008,7 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
 
 static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	mutex_lock(&sc->mutex);
 	ath9k_ps_wakeup(sc);
@@ -2007,8 +2019,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 
 static void ath9k_reset_tsf(struct ieee80211_hw *hw)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	mutex_lock(&sc->mutex);
 
@@ -2023,10 +2034,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      enum ieee80211_ampdu_mlme_action action,
 			      struct ieee80211_sta *sta,
-			      u16 tid, u16 *ssn)
+			      u16 tid, u16 *ssn, u8 buf_size)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	int ret = 0;
 
 	local_bh_disable();
@@ -2071,8 +2081,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
 			     struct survey_info *survey)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_channel *chan;
@@ -2106,53 +2115,55 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
 	return 0;
 }
 
-static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
+static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
 
 	mutex_lock(&sc->mutex);
-	if (ath9k_wiphy_scanning(sc)) {
-		/*
-		 * There is a race here in mac80211 but fixing it requires
-		 * we revisit how we handle the scan complete callback.
-		 * After mac80211 fixes we will not have configured hardware
-		 * to the home channel nor would we have configured the RX
-		 * filter yet.
-		 */
-		mutex_unlock(&sc->mutex);
-		return;
-	}
-
-	aphy->state = ATH_WIPHY_SCAN;
-	ath9k_wiphy_pause_all_forced(sc, aphy);
+	ah->coverage_class = coverage_class;
+	ath9k_hw_init_global_settings(ah);
 	mutex_unlock(&sc->mutex);
 }
 
-/*
- * XXX: this requires a revisit after the driver
- * scan_complete gets moved to another place/removed in mac80211.
- */
-static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
+static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
+	int timeout = 200; /* ms */
+	int i, j;
 
+	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
-	aphy->state = ATH_WIPHY_ACTIVE;
-	mutex_unlock(&sc->mutex);
-}
 
-static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
+	cancel_delayed_work_sync(&sc->tx_complete_work);
 
-	mutex_lock(&sc->mutex);
-	ah->coverage_class = coverage_class;
-	ath9k_hw_init_global_settings(ah);
+	if (drop)
+		timeout = 1;
+
+	for (j = 0; j < timeout; j++) {
+		int npend = 0;
+
+		if (j)
+			usleep_range(1000, 2000);
+
+		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+			if (!ATH_TXQ_SETUP(sc, i))
+				continue;
+
+			npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+		}
+
+		if (!npend)
+		    goto out;
+	}
+
+	if (!ath_drain_all_txq(sc, false))
+		ath_reset(sc, false);
+
+out:
+	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
 	mutex_unlock(&sc->mutex);
+	ath9k_ps_restore(sc);
 }
 
 struct ieee80211_ops ath9k_ops = {
@@ -2174,8 +2185,7 @@ struct ieee80211_ops ath9k_ops = {
 	.reset_tsf 	    = ath9k_reset_tsf,
 	.ampdu_action       = ath9k_ampdu_action,
 	.get_survey	    = ath9k_get_survey,
-	.sw_scan_start      = ath9k_sw_scan_start,
-	.sw_scan_complete   = ath9k_sw_scan_complete,
 	.rfkill_poll        = ath9k_rfkill_poll_state,
 	.set_coverage_class = ath9k_set_coverage_class,
+	.flush		    = ath9k_flush,
 };
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 78ef1f1..e83128c 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -126,7 +126,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	void __iomem *mem;
-	struct ath_wiphy *aphy;
 	struct ath_softc *sc;
 	struct ieee80211_hw *hw;
 	u8 csz;
@@ -198,8 +197,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 		goto err_iomap;
 	}
 
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
-				sizeof(struct ath_softc), &ath9k_ops);
+	hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
 	if (!hw) {
 		dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
 		ret = -ENOMEM;
@@ -209,11 +207,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	pci_set_drvdata(pdev, hw);
 
-	aphy = hw->priv;
-	sc = (struct ath_softc *) (aphy + 1);
-	aphy->sc = sc;
-	aphy->hw = hw;
-	sc->pri_wiphy = aphy;
+	sc = hw->priv;
 	sc->hw = hw;
 	sc->dev = &pdev->dev;
 	sc->mem = mem;
@@ -260,8 +254,7 @@ err_dma:
 static void ath_pci_remove(struct pci_dev *pdev)
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	void __iomem *mem = sc->mem;
 
 	if (!is_ath9k_unloaded)
@@ -281,8 +274,7 @@ static int ath_pci_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
@@ -293,8 +285,7 @@ static int ath_pci_resume(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	u32 val;
 
 	/*
@@ -320,7 +311,6 @@ static int ath_pci_resume(struct device *device)
 	ath9k_ps_restore(sc);
 
 	sc->ps_idle = true;
-	ath9k_set_wiphy_idle(aphy, true);
 	ath_radio_disable(sc, hw);
 
 	return 0;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index e451478..960d717 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1560,8 +1560,7 @@ static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta,
 
 static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	return aphy->sc;
+	return hw->priv;
 }
 
 static void ath_rate_free(void *priv)
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index b2497b8..a9c3f46 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -34,27 +34,6 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
 	       (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
 }
 
-static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
-					     struct ieee80211_hdr *hdr)
-{
-	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
-	int i;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (aphy == NULL)
-			continue;
-		if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr)
-		    == 0) {
-			hw = aphy->hw;
-			break;
-		}
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-	return hw;
-}
-
 /*
  * Setup and link descriptors.
  *
@@ -230,11 +209,6 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
 	int error = 0, i;
 	u32 size;
 
-
-	common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN +
-				     ah->caps.rx_status_len,
-				     min(common->cachelsz, (u16)64));
-
 	ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
 				    ah->caps.rx_status_len);
 
@@ -321,12 +295,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	spin_lock_init(&sc->rx.rxbuflock);
 
+	common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
+			     sc->sc_ah->caps.rx_status_len;
+
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 		return ath_rx_edma_init(sc, nbufs);
 	} else {
-		common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
-				min(common->cachelsz, (u16)64));
-
 		ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
 			common->cachelsz, common->rx_bufsize);
 
@@ -439,9 +413,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 	 * mode interface or when in monitor mode. AP mode does not need this
 	 * since it receives all in-BSS frames anyway.
 	 */
-	if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
-	     (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
-	    (sc->sc_ah->is_monitoring))
+	if (sc->sc_ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
 	if (sc->rx.rxfilter & FIF_CONTROL)
@@ -463,8 +435,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
 	if (conf_is_ht(&sc->hw->conf))
 		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
 
-	if (sc->sec_wiphy || (sc->nvifs > 1) ||
-	    (sc->rx.rxfilter & FIF_OTHER_BSS)) {
+	if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
 		/* The following may also be needed for other older chips */
 		if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
 			rfilt |= ATH9K_RX_FILTER_PROM;
@@ -588,8 +559,14 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
 		return;
 
 	mgmt = (struct ieee80211_mgmt *)skb->data;
-	if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0)
+	if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) {
+		/* TODO:  This doesn't work well if you have stations
+		 * associated to two different APs because curbssid
+		 * is just the last AP that any of the stations associated
+		 * with.
+		 */
 		return; /* not from our current AP */
+	}
 
 	sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
 
@@ -662,37 +639,6 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
 	}
 }
 
-static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
-				    struct ath_softc *sc, struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr;
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-
-	/* Send the frame to mac80211 */
-	if (is_multicast_ether_addr(hdr->addr1)) {
-		int i;
-		/*
-		 * Deliver broadcast/multicast frames to all suitable
-		 * virtual wiphys.
-		 */
-		/* TODO: filter based on channel configuration */
-		for (i = 0; i < sc->num_sec_wiphy; i++) {
-			struct ath_wiphy *aphy = sc->sec_wiphy[i];
-			struct sk_buff *nskb;
-			if (aphy == NULL)
-				continue;
-			nskb = skb_copy(skb, GFP_ATOMIC);
-			if (!nskb)
-				continue;
-			ieee80211_rx(aphy->hw, nskb);
-		}
-		ieee80211_rx(sc->hw, skb);
-	} else
-		/* Deliver unicast frames based on receiver address */
-		ieee80211_rx(hw, skb);
-}
-
 static bool ath_edma_get_buffers(struct ath_softc *sc,
 				 enum ath9k_rx_qtype qtype)
 {
@@ -862,15 +808,9 @@ static bool ath9k_rx_accept(struct ath_common *common,
 	if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
 		return false;
 
-	/*
-	 * rs_more indicates chained descriptors which can be used
-	 * to link buffers together for a sort of scatter-gather
-	 * operation.
-	 * reject the frame, we don't support scatter-gather yet and
-	 * the frame is probably corrupt anyway
-	 */
+	/* Only use error bits from the last fragment */
 	if (rx_stats->rs_more)
-		return false;
+		return true;
 
 	/*
 	 * The rx_stats->rs_status will not be set until the end of the
@@ -974,7 +914,7 @@ static void ath9k_process_rssi(struct ath_common *common,
 			       struct ieee80211_hdr *hdr,
 			       struct ath_rx_status *rx_stats)
 {
-	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = common->ah;
 	int last_rssi;
 	__le16 fc;
@@ -984,13 +924,19 @@ static void ath9k_process_rssi(struct ath_common *common,
 
 	fc = hdr->frame_control;
 	if (!ieee80211_is_beacon(fc) ||
-	    compare_ether_addr(hdr->addr3, common->curbssid))
+	    compare_ether_addr(hdr->addr3, common->curbssid)) {
+		/* TODO:  This doesn't work well if you have stations
+		 * associated to two different APs because curbssid
+		 * is just the last AP that any of the stations associated
+		 * with.
+		 */
 		return;
+	}
 
 	if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
-		ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
+		ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
 
-	last_rssi = aphy->last_rssi;
+	last_rssi = sc->last_rssi;
 	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
 		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
 					      ATH_RSSI_EP_MULTIPLIER);
@@ -1022,6 +968,10 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
 	if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
 		return -EINVAL;
 
+	/* Only use status info from the last fragment */
+	if (rx_stats->rs_more)
+		return 0;
+
 	ath9k_process_rssi(common, hw, hdr, rx_stats);
 
 	if (ath9k_process_rate(common, hw, rx_stats, rx_status))
@@ -1031,7 +981,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
 	rx_status->antenna = rx_stats->rs_antenna;
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	return 0;
 }
@@ -1623,7 +1573,7 @@ div_comb_done:
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 {
 	struct ath_buf *bf;
-	struct sk_buff *skb = NULL, *requeue_skb;
+	struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
 	struct ieee80211_rx_status *rxs;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -1632,7 +1582,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 	 * virtual wiphy so to account for that we iterate over the active
 	 * wiphys and find the appropriate wiphy and therefore hw.
 	 */
-	struct ieee80211_hw *hw = NULL;
+	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_hdr *hdr;
 	int retval;
 	bool decrypt_error = false;
@@ -1674,10 +1624,17 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		if (!skb)
 			continue;
 
-		hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
-		rxs =  IEEE80211_SKB_RXCB(skb);
+		/*
+		 * Take frame header from the first fragment and RX status from
+		 * the last one.
+		 */
+		if (sc->rx.frag)
+			hdr_skb = sc->rx.frag;
+		else
+			hdr_skb = skb;
 
-		hw = ath_get_virt_hw(sc, hdr);
+		hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
+		rxs = IEEE80211_SKB_RXCB(hdr_skb);
 
 		ath_debug_stat_rx(sc, &rs);
 
@@ -1686,12 +1643,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		 * chain it back at the queue without processing it.
 		 */
 		if (flush)
-			goto requeue;
+			goto requeue_drop_frag;
 
 		retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
 						 rxs, &decrypt_error);
 		if (retval)
-			goto requeue;
+			goto requeue_drop_frag;
 
 		rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
 		if (rs.rs_tstamp > tsf_lower &&
@@ -1711,7 +1668,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		 * skb and put it at the tail of the sc->rx.rxbuf list for
 		 * processing. */
 		if (!requeue_skb)
-			goto requeue;
+			goto requeue_drop_frag;
 
 		/* Unmap the frame */
 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
@@ -1722,8 +1679,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		if (ah->caps.rx_status_len)
 			skb_pull(skb, ah->caps.rx_status_len);
 
-		ath9k_rx_skb_postprocess(common, skb, &rs,
-					 rxs, decrypt_error);
+		if (!rs.rs_more)
+			ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
+						 rxs, decrypt_error);
 
 		/* We will now give hardware our shiny new allocated skb */
 		bf->bf_mpdu = requeue_skb;
@@ -1736,10 +1694,42 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 			bf->bf_mpdu = NULL;
 			bf->bf_buf_addr = 0;
 			ath_err(common, "dma_mapping_error() on RX\n");
-			ath_rx_send_to_mac80211(hw, sc, skb);
+			ieee80211_rx(hw, skb);
 			break;
 		}
 
+		if (rs.rs_more) {
+			/*
+			 * rs_more indicates chained descriptors which can be
+			 * used to link buffers together for a sort of
+			 * scatter-gather operation.
+			 */
+			if (sc->rx.frag) {
+				/* too many fragments - cannot handle frame */
+				dev_kfree_skb_any(sc->rx.frag);
+				dev_kfree_skb_any(skb);
+				skb = NULL;
+			}
+			sc->rx.frag = skb;
+			goto requeue;
+		}
+
+		if (sc->rx.frag) {
+			int space = skb->len - skb_tailroom(hdr_skb);
+
+			sc->rx.frag = NULL;
+
+			if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
+				dev_kfree_skb(skb);
+				goto requeue_drop_frag;
+			}
+
+			skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
+						  skb->len);
+			dev_kfree_skb_any(skb);
+			skb = hdr_skb;
+		}
+
 		/*
 		 * change the default rx antenna if rx diversity chooses the
 		 * other antenna 3 times in a row.
@@ -1763,8 +1753,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 		if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
 			ath_ant_comb_scan(sc, &rs);
 
-		ath_rx_send_to_mac80211(hw, sc, skb);
+		ieee80211_rx(hw, skb);
 
+requeue_drop_frag:
+		if (sc->rx.frag) {
+			dev_kfree_skb_any(sc->rx.frag);
+			sc->rx.frag = NULL;
+		}
 requeue:
 		if (edma) {
 			list_add_tail(&bf->list, &sc->rx.rxbuf);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 4df5659..8fa8acf 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -789,6 +789,7 @@
 #define AR_SREV_REVISION_9300_20	2 /* 2.0 and 2.1 */
 #define AR_SREV_VERSION_9485		0x240
 #define AR_SREV_REVISION_9485_10	0
+#define AR_SREV_REVISION_9485_11        1
 
 #define AR_SREV_5416(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -866,6 +867,9 @@
 #define AR_SREV_9485_10(_ah) \
 	(AR_SREV_9485(_ah) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10))
+#define AR_SREV_9485_11(_ah) \
+	(AR_SREV_9485(_ah) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11))
 
 #define AR_SREV_9285E_20(_ah) \
     (AR_SREV_9285_12_OR_LATER(_ah) && \
@@ -874,6 +878,7 @@
 enum ath_usb_dev {
 	AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
 	AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
+	STORAGE_DEVICE = 3,
 };
 
 #define AR_DEVID_7010(_ah) \
@@ -1083,6 +1088,17 @@ enum {
 #define AR_ENT_OTP		  0x40d8
 #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
 #define AR_ENT_OTP_MPSD		0x00800000
+#define AR_CH0_BB_DPLL2          0x16184
+#define AR_CH0_BB_DPLL3          0x16188
+#define AR_CH0_DDR_DPLL2         0x16244
+#define AR_CH0_DDR_DPLL3         0x16248
+#define AR_CH0_DPLL2_KD              0x03F80000
+#define AR_CH0_DPLL2_KD_S            19
+#define AR_CH0_DPLL2_KI              0x3C000000
+#define AR_CH0_DPLL2_KI_S            26
+#define AR_CH0_DPLL3_PHASE_SHIFT     0x3F800000
+#define AR_CH0_DPLL3_PHASE_SHIFT_S   23
+#define AR_PHY_CCA_NOM_VAL_2GHZ      -118
 
 #define AR_RTC_9300_PLL_DIV          0x000003ff
 #define AR_RTC_9300_PLL_DIV_S        0
@@ -1129,6 +1145,12 @@ enum {
 #define AR_RTC_PLL_CLKSEL       0x00000300
 #define AR_RTC_PLL_CLKSEL_S     8
 
+#define PLL3 0x16188
+#define PLL3_DO_MEAS_MASK 0x40000000
+#define PLL4 0x1618c
+#define PLL4_MEAS_DONE    0x8
+#define SQSUM_DVC_MASK 0x007ffff8
+
 #define AR_RTC_RESET \
 	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
 #define AR_RTC_RESET_EN		(0x00000001)
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
deleted file mode 100644
index 2dc7095..0000000
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/slab.h>
-
-#include "ath9k.h"
-
-struct ath9k_vif_iter_data {
-	const u8 *hw_macaddr;
-	u8 mask[ETH_ALEN];
-};
-
-static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath9k_vif_iter_data *iter_data = data;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
-}
-
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath9k_vif_iter_data iter_data;
-	int i;
-
-	/*
-	 * Use the hardware MAC address as reference, the hardware uses it
-	 * together with the BSSID mask when matching addresses.
-	 */
-	iter_data.hw_macaddr = common->macaddr;
-	memset(&iter_data.mask, 0xff, ETH_ALEN);
-
-	if (vif)
-		ath9k_vif_iter(&iter_data, vif->addr, vif);
-
-	/* Get list of all active MAC addresses */
-	spin_lock_bh(&sc->wiphy_lock);
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
-						   &iter_data);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] == NULL)
-			continue;
-		ieee80211_iterate_active_interfaces_atomic(
-			sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
-	ath_hw_setbssidmask(common);
-}
-
-int ath9k_wiphy_add(struct ath_softc *sc)
-{
-	int i, error;
-	struct ath_wiphy *aphy;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ieee80211_hw *hw;
-	u8 addr[ETH_ALEN];
-
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops);
-	if (hw == NULL)
-		return -ENOMEM;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] == NULL)
-			break;
-	}
-
-	if (i == sc->num_sec_wiphy) {
-		/* No empty slot available; increase array length */
-		struct ath_wiphy **n;
-		n = krealloc(sc->sec_wiphy,
-			     (sc->num_sec_wiphy + 1) *
-			     sizeof(struct ath_wiphy *),
-			     GFP_ATOMIC);
-		if (n == NULL) {
-			spin_unlock_bh(&sc->wiphy_lock);
-			ieee80211_free_hw(hw);
-			return -ENOMEM;
-		}
-		n[i] = NULL;
-		sc->sec_wiphy = n;
-		sc->num_sec_wiphy++;
-	}
-
-	SET_IEEE80211_DEV(hw, sc->dev);
-
-	aphy = hw->priv;
-	aphy->sc = sc;
-	aphy->hw = hw;
-	sc->sec_wiphy[i] = aphy;
-	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	memcpy(addr, common->macaddr, ETH_ALEN);
-	addr[0] |= 0x02; /* Locally managed address */
-	/*
-	 * XOR virtual wiphy index into the least significant bits to generate
-	 * a different MAC address for each virtual wiphy.
-	 */
-	addr[5] ^= i & 0xff;
-	addr[4] ^= (i & 0xff00) >> 8;
-	addr[3] ^= (i & 0xff0000) >> 16;
-
-	SET_IEEE80211_PERM_ADDR(hw, addr);
-
-	ath9k_set_hw_capab(sc, hw);
-
-	error = ieee80211_register_hw(hw);
-
-	if (error == 0) {
-		/* Make sure wiphy scheduler is started (if enabled) */
-		ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int);
-	}
-
-	return error;
-}
-
-int ath9k_wiphy_del(struct ath_wiphy *aphy)
-{
-	struct ath_softc *sc = aphy->sc;
-	int i;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (aphy == sc->sec_wiphy[i]) {
-			sc->sec_wiphy[i] = NULL;
-			spin_unlock_bh(&sc->wiphy_lock);
-			ieee80211_unregister_hw(aphy->hw);
-			ieee80211_free_hw(aphy->hw);
-			return 0;
-		}
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-	return -ENOENT;
-}
-
-static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
-			       struct ieee80211_vif *vif, const u8 *bssid,
-			       int ps)
-{
-	struct ath_softc *sc = aphy->sc;
-	struct ath_tx_control txctl;
-	struct sk_buff *skb;
-	struct ieee80211_hdr *hdr;
-	__le16 fc;
-	struct ieee80211_tx_info *info;
-
-	skb = dev_alloc_skb(24);
-	if (skb == NULL)
-		return -ENOMEM;
-	hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
-	memset(hdr, 0, 24);
-	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
-			 IEEE80211_FCTL_TODS);
-	if (ps)
-		fc |= cpu_to_le16(IEEE80211_FCTL_PM);
-	hdr->frame_control = fc;
-	memcpy(hdr->addr1, bssid, ETH_ALEN);
-	memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN);
-	memcpy(hdr->addr3, bssid, ETH_ALEN);
-
-	info = IEEE80211_SKB_CB(skb);
-	memset(info, 0, sizeof(*info));
-	info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS;
-	info->control.vif = vif;
-	info->control.rates[0].idx = 0;
-	info->control.rates[0].count = 4;
-	info->control.rates[1].idx = -1;
-
-	memset(&txctl, 0, sizeof(struct ath_tx_control));
-	txctl.txq = sc->tx.txq_map[WME_AC_VO];
-	txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
-
-	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
-		goto exit;
-
-	return 0;
-exit:
-	dev_kfree_skb_any(skb);
-	return -1;
-}
-
-static bool __ath9k_wiphy_pausing(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING)
-		return true;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING)
-			return true;
-	}
-	return false;
-}
-
-static bool ath9k_wiphy_pausing(struct ath_softc *sc)
-{
-	bool ret;
-	spin_lock_bh(&sc->wiphy_lock);
-	ret = __ath9k_wiphy_pausing(sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-	return ret;
-}
-
-static bool __ath9k_wiphy_scanning(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state == ATH_WIPHY_SCAN)
-		return true;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN)
-			return true;
-	}
-	return false;
-}
-
-bool ath9k_wiphy_scanning(struct ath_softc *sc)
-{
-	bool ret;
-	spin_lock_bh(&sc->wiphy_lock);
-	ret = __ath9k_wiphy_scanning(sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-	return ret;
-}
-
-static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy);
-
-/* caller must hold wiphy_lock */
-static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy)
-{
-	if (aphy == NULL)
-		return;
-	if (aphy->chan_idx != aphy->sc->chan_idx)
-		return; /* wiphy not on the selected channel */
-	__ath9k_wiphy_unpause(aphy);
-}
-
-static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
-{
-	int i;
-	spin_lock_bh(&sc->wiphy_lock);
-	__ath9k_wiphy_unpause_ch(sc->pri_wiphy);
-	for (i = 0; i < sc->num_sec_wiphy; i++)
-		__ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]);
-	spin_unlock_bh(&sc->wiphy_lock);
-}
-
-void ath9k_wiphy_chan_work(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath_wiphy *aphy = sc->next_wiphy;
-
-	if (aphy == NULL)
-		return;
-
-	/*
-	 * All pending interfaces paused; ready to change
-	 * channels.
-	 */
-
-	/* Change channels */
-	mutex_lock(&sc->mutex);
-	/* XXX: remove me eventually */
-	ath9k_update_ichannel(sc, aphy->hw,
-			      &sc->sc_ah->channels[sc->chan_idx]);
-
-	/* sync hw configuration for hw code */
-	common->hw = aphy->hw;
-
-	if (ath_set_channel(sc, aphy->hw,
-			    &sc->sc_ah->channels[sc->chan_idx]) < 0) {
-		printk(KERN_DEBUG "ath9k: Failed to set channel for new "
-		       "virtual wiphy\n");
-		mutex_unlock(&sc->mutex);
-		return;
-	}
-	mutex_unlock(&sc->mutex);
-
-	ath9k_wiphy_unpause_channel(sc);
-}
-
-/*
- * ath9k version of ieee80211_tx_status() for TX frames that are generated
- * internally in the driver.
- */
-void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, int ftype)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
-	if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) {
-		if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) {
-			printk(KERN_DEBUG "ath9k: %s: no ACK for pause "
-			       "frame\n", wiphy_name(hw->wiphy));
-			/*
-			 * The AP did not reply; ignore this to allow us to
-			 * continue.
-			 */
-		}
-		aphy->state = ATH_WIPHY_PAUSED;
-		if (!ath9k_wiphy_pausing(aphy->sc)) {
-			/*
-			 * Drop from tasklet to work to allow mutex for channel
-			 * change.
-			 */
-			ieee80211_queue_work(aphy->sc->hw,
-				   &aphy->sc->chan_work);
-		}
-	}
-
-	dev_kfree_skb(skb);
-}
-
-static void ath9k_mark_paused(struct ath_wiphy *aphy)
-{
-	struct ath_softc *sc = aphy->sc;
-	aphy->state = ATH_WIPHY_PAUSED;
-	if (!__ath9k_wiphy_pausing(sc))
-		ieee80211_queue_work(sc->hw, &sc->chan_work);
-}
-
-static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = data;
-	struct ath_vif *avp = (void *) vif->drv_priv;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		if (!vif->bss_conf.assoc) {
-			ath9k_mark_paused(aphy);
-			break;
-		}
-		/* TODO: could avoid this if already in PS mode */
-		if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) {
-			printk(KERN_DEBUG "%s: failed to send PS nullfunc\n",
-			       __func__);
-			ath9k_mark_paused(aphy);
-		}
-		break;
-	case NL80211_IFTYPE_AP:
-		/* Beacon transmission is paused by aphy->state change */
-		ath9k_mark_paused(aphy);
-		break;
-	default:
-		break;
-	}
-}
-
-/* caller must hold wiphy_lock */
-static int __ath9k_wiphy_pause(struct ath_wiphy *aphy)
-{
-	ieee80211_stop_queues(aphy->hw);
-	aphy->state = ATH_WIPHY_PAUSING;
-	/*
-	 * TODO: handle PAUSING->PAUSED for the case where there are multiple
-	 * active vifs (now we do it on the first vif getting ready; should be
-	 * on the last)
-	 */
-	ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter,
-						   aphy);
-	return 0;
-}
-
-int ath9k_wiphy_pause(struct ath_wiphy *aphy)
-{
-	int ret;
-	spin_lock_bh(&aphy->sc->wiphy_lock);
-	ret = __ath9k_wiphy_pause(aphy);
-	spin_unlock_bh(&aphy->sc->wiphy_lock);
-	return ret;
-}
-
-static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = data;
-	struct ath_vif *avp = (void *) vif->drv_priv;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		if (!vif->bss_conf.assoc)
-			break;
-		ath9k_send_nullfunc(aphy, vif, avp->bssid, 0);
-		break;
-	case NL80211_IFTYPE_AP:
-		/* Beacon transmission is re-enabled by aphy->state change */
-		break;
-	default:
-		break;
-	}
-}
-
-/* caller must hold wiphy_lock */
-static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy)
-{
-	ieee80211_iterate_active_interfaces_atomic(aphy->hw,
-						   ath9k_unpause_iter, aphy);
-	aphy->state = ATH_WIPHY_ACTIVE;
-	ieee80211_wake_queues(aphy->hw);
-	return 0;
-}
-
-int ath9k_wiphy_unpause(struct ath_wiphy *aphy)
-{
-	int ret;
-	spin_lock_bh(&aphy->sc->wiphy_lock);
-	ret = __ath9k_wiphy_unpause(aphy);
-	spin_unlock_bh(&aphy->sc->wiphy_lock);
-	return ret;
-}
-
-static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE)
-		sc->pri_wiphy->state = ATH_WIPHY_PAUSED;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE)
-			sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED;
-	}
-}
-
-/* caller must hold wiphy_lock */
-static void __ath9k_wiphy_pause_all(struct ath_softc *sc)
-{
-	int i;
-	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
-		__ath9k_wiphy_pause(sc->pri_wiphy);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
-			__ath9k_wiphy_pause(sc->sec_wiphy[i]);
-	}
-}
-
-int ath9k_wiphy_select(struct ath_wiphy *aphy)
-{
-	struct ath_softc *sc = aphy->sc;
-	bool now;
-
-	spin_lock_bh(&sc->wiphy_lock);
-	if (__ath9k_wiphy_scanning(sc)) {
-		/*
-		 * For now, we are using mac80211 sw scan and it expects to
-		 * have full control over channel changes, so avoid wiphy
-		 * scheduling during a scan. This could be optimized if the
-		 * scanning control were moved into the driver.
-		 */
-		spin_unlock_bh(&sc->wiphy_lock);
-		return -EBUSY;
-	}
-	if (__ath9k_wiphy_pausing(sc)) {
-		if (sc->wiphy_select_failures == 0)
-			sc->wiphy_select_first_fail = jiffies;
-		sc->wiphy_select_failures++;
-		if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2))
-		{
-			printk(KERN_DEBUG "ath9k: Previous wiphy select timed "
-			       "out; disable/enable hw to recover\n");
-			__ath9k_wiphy_mark_all_paused(sc);
-			/*
-			 * TODO: this workaround to fix hardware is unlikely to
-			 * be specific to virtual wiphy changes. It can happen
-			 * on normal channel change, too, and as such, this
-			 * should really be made more generic. For example,
-			 * tricker radio disable/enable on GTT interrupt burst
-			 * (say, 10 GTT interrupts received without any TX
-			 * frame being completed)
-			 */
-			spin_unlock_bh(&sc->wiphy_lock);
-			ath_radio_disable(sc, aphy->hw);
-			ath_radio_enable(sc, aphy->hw);
-			/* Only the primary wiphy hw is used for queuing work */
-			ieee80211_queue_work(aphy->sc->hw,
-				   &aphy->sc->chan_work);
-			return -EBUSY; /* previous select still in progress */
-		}
-		spin_unlock_bh(&sc->wiphy_lock);
-		return -EBUSY; /* previous select still in progress */
-	}
-	sc->wiphy_select_failures = 0;
-
-	/* Store the new channel */
-	sc->chan_idx = aphy->chan_idx;
-	sc->chan_is_ht = aphy->chan_is_ht;
-	sc->next_wiphy = aphy;
-
-	__ath9k_wiphy_pause_all(sc);
-	now = !__ath9k_wiphy_pausing(aphy->sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	if (now) {
-		/* Ready to request channel change immediately */
-		ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work);
-	}
-
-	/*
-	 * wiphys will be unpaused in ath9k_tx_status() once channel has been
-	 * changed if any wiphy needs time to become paused.
-	 */
-
-	return 0;
-}
-
-bool ath9k_wiphy_started(struct ath_softc *sc)
-{
-	int i;
-	spin_lock_bh(&sc->wiphy_lock);
-	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
-		spin_unlock_bh(&sc->wiphy_lock);
-		return true;
-	}
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) {
-			spin_unlock_bh(&sc->wiphy_lock);
-			return true;
-		}
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-	return false;
-}
-
-static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy,
-				   struct ath_wiphy *selected)
-{
-	if (selected->state == ATH_WIPHY_SCAN) {
-		if (aphy == selected)
-			return;
-		/*
-		 * Pause all other wiphys for the duration of the scan even if
-		 * they are on the current channel now.
-		 */
-	} else if (aphy->chan_idx == selected->chan_idx)
-		return;
-	aphy->state = ATH_WIPHY_PAUSED;
-	ieee80211_stop_queues(aphy->hw);
-}
-
-void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
-				  struct ath_wiphy *selected)
-{
-	int i;
-	spin_lock_bh(&sc->wiphy_lock);
-	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE)
-		ath9k_wiphy_pause_chan(sc->pri_wiphy, selected);
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i] &&
-		    sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE)
-			ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected);
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-}
-
-void ath9k_wiphy_work(struct work_struct *work)
-{
-	struct ath_softc *sc = container_of(work, struct ath_softc,
-					    wiphy_work.work);
-	struct ath_wiphy *aphy = NULL;
-	bool first = true;
-
-	spin_lock_bh(&sc->wiphy_lock);
-
-	if (sc->wiphy_scheduler_int == 0) {
-		/* wiphy scheduler is disabled */
-		spin_unlock_bh(&sc->wiphy_lock);
-		return;
-	}
-
-try_again:
-	sc->wiphy_scheduler_index++;
-	while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) {
-		aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1];
-		if (aphy && aphy->state != ATH_WIPHY_INACTIVE)
-			break;
-
-		sc->wiphy_scheduler_index++;
-		aphy = NULL;
-	}
-	if (aphy == NULL) {
-		sc->wiphy_scheduler_index = 0;
-		if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) {
-			if (first) {
-				first = false;
-				goto try_again;
-			}
-			/* No wiphy is ready to be scheduled */
-		} else
-			aphy = sc->pri_wiphy;
-	}
-
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	if (aphy &&
-	    aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN &&
-	    ath9k_wiphy_select(aphy)) {
-		printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy "
-		       "change\n");
-	}
-
-	ieee80211_queue_delayed_work(sc->hw,
-				     &sc->wiphy_work,
-				     sc->wiphy_scheduler_int);
-}
-
-void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
-{
-	cancel_delayed_work_sync(&sc->wiphy_work);
-	sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int);
-	if (sc->wiphy_scheduler_int)
-		ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work,
-					     sc->wiphy_scheduler_int);
-}
-
-/* caller must hold wiphy_lock */
-bool ath9k_all_wiphys_idle(struct ath_softc *sc)
-{
-	unsigned int i;
-	if (!sc->pri_wiphy->idle)
-		return false;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (!aphy)
-			continue;
-		if (!aphy->idle)
-			return false;
-	}
-	return true;
-}
-
-/* caller must hold wiphy_lock */
-void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
-{
-	struct ath_softc *sc = aphy->sc;
-
-	aphy->idle = idle;
-	ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
-		"Marking %s as %sidle\n",
-		wiphy_name(aphy->hw->wiphy), idle ? "" : "not-");
-}
-/* Only bother starting a queue on an active virtual wiphy */
-bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
-{
-	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
-	unsigned int i;
-	bool txq_started = false;
-
-	spin_lock_bh(&sc->wiphy_lock);
-
-	/* Start the primary wiphy */
-	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
-		ieee80211_wake_queue(hw, skb_queue);
-		txq_started = true;
-		goto unlock;
-	}
-
-	/* Now start the secondary wiphy queues */
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (!aphy)
-			continue;
-		if (aphy->state != ATH_WIPHY_ACTIVE)
-			continue;
-
-		hw = aphy->hw;
-		ieee80211_wake_queue(hw, skb_queue);
-		txq_started = true;
-		break;
-	}
-
-unlock:
-	spin_unlock_bh(&sc->wiphy_lock);
-	return txq_started;
-}
-
-/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
-void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue)
-{
-	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
-	unsigned int i;
-
-	spin_lock_bh(&sc->wiphy_lock);
-
-	/* Stop the primary wiphy */
-	ieee80211_stop_queue(hw, skb_queue);
-
-	/* Now stop the secondary wiphy queues */
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (!aphy)
-			continue;
-		hw = aphy->hw;
-		ieee80211_stop_queue(hw, skb_queue);
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-}
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index dc862f5..d3d2490 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -123,12 +123,8 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv)
 void ath9k_swba_tasklet(unsigned long data)
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
-	struct ath_common *common = ath9k_hw_common(priv->ah);
-
-	ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n");
 
 	ath9k_htc_swba(priv, priv->wmi->beacon_pending);
-
 }
 
 void ath9k_fatal_work(struct work_struct *work)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 07b7804..ef22096 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -19,7 +19,6 @@
 
 #define BITS_PER_BYTE           8
 #define OFDM_PLCP_BITS          22
-#define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)
 #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
 #define L_STF                   8
 #define L_LTF                   8
@@ -32,7 +31,6 @@
 #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
 #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
 
-#define OFDM_SIFS_TIME    	    16
 
 static u16 bits_per_symbol[][2] = {
 	/* 20MHz 40MHz */
@@ -57,8 +55,9 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 			     struct list_head *head);
 static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len);
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
-			     int nframes, int nbad, int txok, bool update_rc);
+static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+			     struct ath_tx_status *ts, int nframes, int nbad,
+			     int txok, bool update_rc);
 static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
 			      int seqno);
 
@@ -167,9 +166,9 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 		fi = get_frame_info(bf->bf_mpdu);
 		if (fi->retries) {
 			ath_tx_update_baw(sc, tid, fi->seqno);
-			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
 		} else {
-			ath_tx_send_normal(sc, txq, tid, &bf_head);
+			ath_tx_send_normal(sc, txq, NULL, &bf_head);
 		}
 		spin_lock_bh(&txq->axq_lock);
 	}
@@ -297,7 +296,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
 
 	ATH_TXBUF_RESET(tbf);
 
-	tbf->aphy = bf->aphy;
 	tbf->bf_mpdu = bf->bf_mpdu;
 	tbf->bf_buf_addr = bf->bf_buf_addr;
 	memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
@@ -345,7 +343,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	struct ath_node *an = NULL;
 	struct sk_buff *skb;
 	struct ieee80211_sta *sta;
-	struct ieee80211_hw *hw;
+	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *tx_info;
 	struct ath_atx_tid *tid = NULL;
@@ -364,7 +362,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	hdr = (struct ieee80211_hdr *)skb->data;
 
 	tx_info = IEEE80211_SKB_CB(skb);
-	hw = bf->aphy->hw;
 
 	memcpy(rates, tx_info->control.rates, sizeof(rates));
 
@@ -383,7 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			    !bf->bf_stale || bf_next != NULL)
 				list_move_tail(&bf->list, &bf_head);
 
-			ath_tx_rc_status(bf, ts, 1, 1, 0, false);
+			ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
 				0, 0);
 
@@ -429,7 +426,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
 	ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
 	while (bf) {
-		txfail = txpending = 0;
+		txfail = txpending = sendbar = 0;
 		bf_next = bf->bf_next;
 
 		skb = bf->bf_mpdu;
@@ -489,10 +486,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
 			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
 				memcpy(tx_info->control.rates, rates, sizeof(rates));
-				ath_tx_rc_status(bf, ts, nframes, nbad, txok, true);
+				ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
 				rc_update = false;
 			} else {
-				ath_tx_rc_status(bf, ts, nframes, nbad, txok, false);
+				ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
 			}
 
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
@@ -516,7 +513,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
 						bf->bf_state.bf_type |=
 							BUF_XRETRY;
-						ath_tx_rc_status(bf, ts, nframes,
+						ath_tx_rc_status(sc, bf, ts, nframes,
 								nbad, 0, false);
 						ath_tx_complete_buf(sc, bf, txq,
 								    &bf_head,
@@ -566,8 +563,11 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 
 	rcu_read_unlock();
 
-	if (needreset)
+	if (needreset) {
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		ath_reset(sc, false);
+		spin_lock_bh(&sc->sc_pcu_lock);
+	}
 }
 
 static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -856,7 +856,10 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
 
 	txtid->state |= AGGR_ADDBA_PROGRESS;
 	txtid->paused = true;
-	*ssn = txtid->seq_start;
+	*ssn = txtid->seq_start = txtid->seq_next;
+
+	memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
+	txtid->baw_head = txtid->baw_tail = 0;
 
 	return 0;
 }
@@ -942,7 +945,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 		[WME_AC_VI] = ATH_TXQ_AC_VI,
 		[WME_AC_VO] = ATH_TXQ_AC_VO,
 	};
-	int qnum, i;
+	int axq_qnum, i;
 
 	memset(&qi, 0, sizeof(qi));
 	qi.tqi_subtype = subtype_txq_to_hwq[subtype];
@@ -976,24 +979,25 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 			qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
 					TXQ_FLAG_TXDESCINT_ENABLE;
 	}
-	qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
-	if (qnum == -1) {
+	axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
+	if (axq_qnum == -1) {
 		/*
 		 * NB: don't print a message, this happens
 		 * normally on parts with too few tx queues
 		 */
 		return NULL;
 	}
-	if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
+	if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
 		ath_err(common, "qnum %u out of range, max %zu!\n",
-			qnum, ARRAY_SIZE(sc->tx.txq));
-		ath9k_hw_releasetxqueue(ah, qnum);
+			axq_qnum, ARRAY_SIZE(sc->tx.txq));
+		ath9k_hw_releasetxqueue(ah, axq_qnum);
 		return NULL;
 	}
-	if (!ATH_TXQ_SETUP(sc, qnum)) {
-		struct ath_txq *txq = &sc->tx.txq[qnum];
+	if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
+		struct ath_txq *txq = &sc->tx.txq[axq_qnum];
 
-		txq->axq_qnum = qnum;
+		txq->axq_qnum = axq_qnum;
+		txq->mac80211_qnum = -1;
 		txq->axq_link = NULL;
 		INIT_LIST_HEAD(&txq->axq_q);
 		INIT_LIST_HEAD(&txq->axq_acq);
@@ -1001,14 +1005,14 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 		txq->axq_depth = 0;
 		txq->axq_ampdu_depth = 0;
 		txq->axq_tx_inprogress = false;
-		sc->tx.txqsetup |= 1<<qnum;
+		sc->tx.txqsetup |= 1<<axq_qnum;
 
 		txq->txq_headidx = txq->txq_tailidx = 0;
 		for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
 			INIT_LIST_HEAD(&txq->txq_fifo[i]);
 		INIT_LIST_HEAD(&txq->txq_fifo_pending);
 	}
-	return &sc->tx.txq[qnum];
+	return &sc->tx.txq[axq_qnum];
 }
 
 int ath_txq_update(struct ath_softc *sc, int qnum,
@@ -1051,6 +1055,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
 int ath_cabq_update(struct ath_softc *sc)
 {
 	struct ath9k_tx_queue_info qi;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	int qnum = sc->beacon.cabq->axq_qnum;
 
 	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
@@ -1062,7 +1067,7 @@ int ath_cabq_update(struct ath_softc *sc)
 	else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
 		sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
 
-	qi.tqi_readyTime = (sc->beacon_interval *
+	qi.tqi_readyTime = (cur_conf->beacon_interval *
 			    sc->config.cabqReadytime) / 100;
 	ath_txq_update(sc, qnum, &qi);
 
@@ -1189,24 +1194,31 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 	if (sc->sc_flags & SC_OP_INVALID)
 		return true;
 
-	/* Stop beacon queue */
-	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+	ath9k_hw_abort_tx_dma(ah);
 
-	/* Stop data queues */
+	/* Check if any queue remains active */
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i)) {
-			txq = &sc->tx.txq[i];
-			ath9k_hw_stoptxdma(ah, txq->axq_qnum);
-			npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
-		}
+		if (!ATH_TXQ_SETUP(sc, i))
+			continue;
+
+		npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
 	}
 
 	if (npend)
 		ath_err(common, "Failed to stop TX DMA!\n");
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
+		if (!ATH_TXQ_SETUP(sc, i))
+			continue;
+
+		/*
+		 * The caller will resume queues with ieee80211_wake_queues.
+		 * Mark the queue as not stopped to prevent ath_tx_complete
+		 * from waking the queue too early.
+		 */
+		txq = &sc->tx.txq[i];
+		txq->stopped = false;
+		ath_draintxq(sc, txq, retry_tx);
 	}
 
 	return !npend;
@@ -1218,46 +1230,59 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
 	sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
 }
 
+/* For each axq_acq entry, for each tid, try to schedule packets
+ * for transmit until ampdu_depth has reached min Q depth.
+ */
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 {
-	struct ath_atx_ac *ac;
-	struct ath_atx_tid *tid;
+	struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+	struct ath_atx_tid *tid, *last_tid;
 
-	if (list_empty(&txq->axq_acq))
+	if (list_empty(&txq->axq_acq) ||
+	    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
 		return;
 
 	ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
-	list_del(&ac->list);
-	ac->sched = false;
+	last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
 
-	do {
-		if (list_empty(&ac->tid_q))
-			return;
+	list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+		last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
+		list_del(&ac->list);
+		ac->sched = false;
 
-		tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
-		list_del(&tid->list);
-		tid->sched = false;
+		while (!list_empty(&ac->tid_q)) {
+			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+					       list);
+			list_del(&tid->list);
+			tid->sched = false;
 
-		if (tid->paused)
-			continue;
+			if (tid->paused)
+				continue;
 
-		ath_tx_sched_aggr(sc, txq, tid);
+			ath_tx_sched_aggr(sc, txq, tid);
 
-		/*
-		 * add tid to round-robin queue if more frames
-		 * are pending for the tid
-		 */
-		if (!list_empty(&tid->buf_q))
-			ath_tx_queue_tid(txq, tid);
+			/*
+			 * add tid to round-robin queue if more frames
+			 * are pending for the tid
+			 */
+			if (!list_empty(&tid->buf_q))
+				ath_tx_queue_tid(txq, tid);
 
-		break;
-	} while (!list_empty(&ac->tid_q));
+			if (tid == last_tid ||
+			    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+				break;
+		}
 
-	if (!list_empty(&ac->tid_q)) {
-		if (!ac->sched) {
-			ac->sched = true;
-			list_add_tail(&ac->list, &txq->axq_acq);
+		if (!list_empty(&ac->tid_q)) {
+			if (!ac->sched) {
+				ac->sched = true;
+				list_add_tail(&ac->list, &txq->axq_acq);
+			}
 		}
+
+		if (ac == last_ac ||
+		    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+			return;
 	}
 }
 
@@ -1301,6 +1326,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 		INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
 		list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
 		INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
+		TX_STAT_INC(txq->axq_qnum, puttxbuf);
 		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
 		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
 			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
@@ -1308,6 +1334,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 		list_splice_tail_init(head, &txq->axq_q);
 
 		if (txq->axq_link == NULL) {
+			TX_STAT_INC(txq->axq_qnum, puttxbuf);
 			ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
 			ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
 				txq->axq_qnum, ito64(bf->bf_daddr),
@@ -1321,6 +1348,7 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
 		}
 		ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
 				       &txq->axq_link);
+		TX_STAT_INC(txq->axq_qnum, txstart);
 		ath9k_hw_txstart(ah, txq->axq_qnum);
 	}
 	txq->axq_depth++;
@@ -1335,7 +1363,6 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
 	struct list_head bf_head;
 
 	bf->bf_state.bf_type |= BUF_AMPDU;
-	TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
 
 	/*
 	 * Do not queue to h/w when any of the following conditions is true:
@@ -1351,6 +1378,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
 		 * Add this frame to software queue for scheduling later
 		 * for aggregation.
 		 */
+		TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
 		list_add_tail(&bf->list, &tid->buf_q);
 		ath_tx_queue_tid(txctl->txq, tid);
 		return;
@@ -1364,6 +1392,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
 		ath_tx_addto_baw(sc, tid, fi->seqno);
 
 	/* Queue to h/w without aggregation */
+	TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
 	bf->bf_lastbf = bf;
 	ath_buf_set_rate(sc, bf, fi->framelen);
 	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
@@ -1416,8 +1445,7 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
 static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
 			     int framelen)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = tx_info->control.sta;
 	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
@@ -1635,8 +1663,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
 					   struct ath_txq *txq,
 					   struct sk_buff *skb)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_frame_info *fi = get_frame_info(skb);
@@ -1652,7 +1679,6 @@ static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw,
 
 	ATH_TXBUF_RESET(bf);
 
-	bf->aphy = aphy;
 	bf->bf_flags = setup_tx_flags(skb);
 	bf->bf_mpdu = skb;
 
@@ -1741,8 +1767,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = info->control.sta;
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_txq *txq = txctl->txq;
 	struct ath_buf *bf;
 	int padpos, padsize;
@@ -1794,7 +1819,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 	spin_lock_bh(&txq->axq_lock);
 	if (txq == sc->tx.txq_map[q] &&
 	    ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
-		ath_mac80211_stop_queue(sc, q);
+		ieee80211_stop_queue(sc->hw, q);
 		txq->stopped = 1;
 	}
 	spin_unlock_bh(&txq->axq_lock);
@@ -1809,8 +1834,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 /*****************/
 
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-			    struct ath_wiphy *aphy, int tx_flags, int ftype,
-			    struct ath_txq *txq)
+			    int tx_flags, int ftype, struct ath_txq *txq)
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1820,9 +1844,6 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
 	ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
 
-	if (aphy)
-		hw = aphy->hw;
-
 	if (tx_flags & ATH_TX_BAR)
 		tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 
@@ -1852,19 +1873,20 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 					PS_WAIT_FOR_TX_ACK));
 	}
 
-	if (unlikely(ftype))
-		ath9k_tx_status(hw, skb, ftype);
-	else {
-		q = skb_get_queue_mapping(skb);
-		if (txq == sc->tx.txq_map[q]) {
-			spin_lock_bh(&txq->axq_lock);
-			if (WARN_ON(--txq->pending_frames < 0))
-				txq->pending_frames = 0;
-			spin_unlock_bh(&txq->axq_lock);
-		}
+	q = skb_get_queue_mapping(skb);
+	if (txq == sc->tx.txq_map[q]) {
+		spin_lock_bh(&txq->axq_lock);
+		if (WARN_ON(--txq->pending_frames < 0))
+			txq->pending_frames = 0;
 
-		ieee80211_tx_status(hw, skb);
+		if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
+			ieee80211_wake_queue(sc->hw, q);
+			txq->stopped = 0;
+		}
+		spin_unlock_bh(&txq->axq_lock);
 	}
+
+	ieee80211_tx_status(hw, skb);
 }
 
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
@@ -1896,8 +1918,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 		else
 			complete(&sc->paprd_complete);
 	} else {
-		ath_debug_stat_tx(sc, bf, ts);
-		ath_tx_complete(sc, skb, bf->aphy, tx_flags,
+		ath_debug_stat_tx(sc, bf, ts, txq);
+		ath_tx_complete(sc, skb, tx_flags,
 				bf->bf_state.bfs_ftype, txq);
 	}
 	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
@@ -1913,14 +1935,14 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 	spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
 }
 
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
-			     int nframes, int nbad, int txok, bool update_rc)
+static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+			     struct ath_tx_status *ts, int nframes, int nbad,
+			     int txok, bool update_rc)
 {
 	struct sk_buff *skb = bf->bf_mpdu;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-	struct ieee80211_hw *hw = bf->aphy->hw;
-	struct ath_softc *sc = bf->aphy->sc;
+	struct ieee80211_hw *hw = sc->hw;
 	struct ath_hw *ah = sc->sc_ah;
 	u8 i, tx_rateindex;
 
@@ -1971,19 +1993,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 }
 
-static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
-{
-	struct ath_txq *txq;
-
-	txq = sc->tx.txq_map[qnum];
-	spin_lock_bh(&txq->axq_lock);
-	if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
-		if (ath_mac80211_start_queue(sc, qnum))
-			txq->stopped = 0;
-	}
-	spin_unlock_bh(&txq->axq_lock);
-}
-
 static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 {
 	struct ath_hw *ah = sc->sc_ah;
@@ -1994,7 +2003,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 	struct ath_tx_status ts;
 	int txok;
 	int status;
-	int qnum;
 
 	ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
 		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
@@ -2004,6 +2012,8 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 		spin_lock_bh(&txq->axq_lock);
 		if (list_empty(&txq->axq_q)) {
 			txq->axq_link = NULL;
+			if (sc->sc_flags & SC_OP_TXAGGR)
+				ath_txq_schedule(sc, txq);
 			spin_unlock_bh(&txq->axq_lock);
 			break;
 		}
@@ -2038,6 +2048,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 			spin_unlock_bh(&txq->axq_lock);
 			break;
 		}
+		TX_STAT_INC(txq->axq_qnum, txprocdesc);
 
 		/*
 		 * Remove ath_buf's of the same transmit unit from txq,
@@ -2058,6 +2069,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 
 		if (bf_is_ampdu_not_probing(bf))
 			txq->axq_ampdu_depth--;
+
 		spin_unlock_bh(&txq->axq_lock);
 
 		if (bf_held)
@@ -2070,27 +2082,45 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 			 */
 			if (ts.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true);
+			ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
 		}
 
-		qnum = skb_get_queue_mapping(bf->bf_mpdu);
-
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
 					     true);
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
 
-		if (txq == sc->tx.txq_map[qnum])
-			ath_wake_mac80211_queue(sc, qnum);
-
 		spin_lock_bh(&txq->axq_lock);
+
 		if (sc->sc_flags & SC_OP_TXAGGR)
 			ath_txq_schedule(sc, txq);
 		spin_unlock_bh(&txq->axq_lock);
 	}
 }
 
+static void ath_hw_pll_work(struct work_struct *work)
+{
+	struct ath_softc *sc = container_of(work, struct ath_softc,
+					    hw_pll_work.work);
+	static int count;
+
+	if (AR_SREV_9485(sc->sc_ah)) {
+		if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) {
+			count++;
+
+			if (count == 3) {
+				/* Rx is hung for more than 500ms. Reset it */
+				ath_reset(sc, true);
+				count = 0;
+			}
+		} else
+			count = 0;
+
+		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+	}
+}
+
 static void ath_tx_complete_poll_work(struct work_struct *work)
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc,
@@ -2098,6 +2128,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
 	struct ath_txq *txq;
 	int i;
 	bool needreset = false;
+#ifdef CONFIG_ATH9K_DEBUGFS
+	sc->tx_complete_poll_work_seen++;
+#endif
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
 		if (ATH_TXQ_SETUP(sc, i)) {
@@ -2111,6 +2144,33 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
 				} else {
 					txq->axq_tx_inprogress = true;
 				}
+			} else {
+				/* If the queue has pending buffers, then it
+				 * should be doing tx work (and have axq_depth).
+				 * Shouldn't get to this state I think..but
+				 * we do.
+				 */
+				if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
+				    (txq->pending_frames > 0 ||
+				     !list_empty(&txq->axq_acq) ||
+				     txq->stopped)) {
+					ath_err(ath9k_hw_common(sc->sc_ah),
+						"txq: %p axq_qnum: %u,"
+						" mac80211_qnum: %i"
+						" axq_link: %p"
+						" pending frames: %i"
+						" axq_acq empty: %i"
+						" stopped: %i"
+						" axq_depth: 0  Attempting to"
+						" restart tx logic.\n",
+						txq, txq->axq_qnum,
+						txq->mac80211_qnum,
+						txq->axq_link,
+						txq->pending_frames,
+						list_empty(&txq->axq_acq),
+						txq->stopped);
+					ath_txq_schedule(sc, txq);
+				}
 			}
 			spin_unlock_bh(&txq->axq_lock);
 		}
@@ -2150,7 +2210,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 	struct list_head bf_head;
 	int status;
 	int txok;
-	int qnum;
 
 	for (;;) {
 		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
@@ -2193,11 +2252,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 		if (!bf_isampdu(bf)) {
 			if (txs.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true);
+			ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
 		}
 
-		qnum = skb_get_queue_mapping(bf->bf_mpdu);
-
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
 					     txok, true);
@@ -2205,19 +2262,19 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 			ath_tx_complete_buf(sc, bf, txq, &bf_head,
 					    &txs, txok, 0);
 
-		if (txq == sc->tx.txq_map[qnum])
-			ath_wake_mac80211_queue(sc, qnum);
-
 		spin_lock_bh(&txq->axq_lock);
+
 		if (!list_empty(&txq->txq_fifo_pending)) {
 			INIT_LIST_HEAD(&bf_head);
 			bf = list_first_entry(&txq->txq_fifo_pending,
-				struct ath_buf, list);
-			list_cut_position(&bf_head, &txq->txq_fifo_pending,
-				&bf->bf_lastbf->list);
+					      struct ath_buf, list);
+			list_cut_position(&bf_head,
+					  &txq->txq_fifo_pending,
+					  &bf->bf_lastbf->list);
 			ath_tx_txqaddbuf(sc, txq, &bf_head);
 		} else if (sc->sc_flags & SC_OP_TXAGGR)
 			ath_txq_schedule(sc, txq);
+
 		spin_unlock_bh(&txq->axq_lock);
 	}
 }
@@ -2285,6 +2342,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
 	}
 
 	INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
+	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 		error = ath_tx_edma_init(sc);
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index d07ff7f..c6a5fae 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -283,6 +283,7 @@ struct ar9170 {
 		unsigned int mem_blocks;
 		unsigned int mem_block_size;
 		unsigned int rx_size;
+		unsigned int tx_seq_table;
 	} fw;
 
 	/* reset / stuck frames/queue detection */
@@ -533,7 +534,7 @@ void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len);
 void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
 
 /* TX */
-int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 void carl9170_tx_janitor(struct work_struct *work);
 void carl9170_tx_process_status(struct ar9170 *ar,
 				const struct carl9170_rsp *cmd);
diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c
index 546b4e4..9517ede 100644
--- a/drivers/net/wireless/ath/carl9170/fw.c
+++ b/drivers/net/wireless/ath/carl9170/fw.c
@@ -150,6 +150,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 	const struct carl9170fw_otus_desc *otus_desc;
 	const struct carl9170fw_chk_desc *chk_desc;
 	const struct carl9170fw_last_desc *last_desc;
+	const struct carl9170fw_txsq_desc *txsq_desc;
 
 	last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
 		sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
@@ -264,6 +265,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 			FIF_PROMISC_IN_BSS;
 	}
 
+	if (SUPP(CARL9170FW_WOL))
+		device_set_wakeup_enable(&ar->udev->dev, true);
+
 	ar->fw.vif_num = otus_desc->vif_num;
 	ar->fw.cmd_bufs = otus_desc->cmd_bufs;
 	ar->fw.address = le32_to_cpu(otus_desc->fw_address);
@@ -296,6 +300,17 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
 		}
 	}
 
+	txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC,
+		sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER);
+
+	if (txsq_desc) {
+		ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
+		if (!valid_cpu_addr(ar->fw.tx_seq_table))
+			return -EINVAL;
+	} else {
+		ar->fw.tx_seq_table = 0;
+	}
+
 #undef SUPPORTED
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h
index 3680dfc7..30449d2 100644
--- a/drivers/net/wireless/ath/carl9170/fwcmd.h
+++ b/drivers/net/wireless/ath/carl9170/fwcmd.h
@@ -167,6 +167,7 @@ struct carl9170_rx_filter_cmd {
 #define CARL9170_RX_FILTER_CTL_BACKR	0x20
 #define CARL9170_RX_FILTER_MGMT		0x40
 #define CARL9170_RX_FILTER_DATA		0x80
+#define CARL9170_RX_FILTER_EVERYTHING	(~0)
 
 struct carl9170_bcn_ctrl_cmd {
 	__le32		vif_id;
diff --git a/drivers/net/wireless/ath/carl9170/fwdesc.h b/drivers/net/wireless/ath/carl9170/fwdesc.h
index 71f3821..9210668 100644
--- a/drivers/net/wireless/ath/carl9170/fwdesc.h
+++ b/drivers/net/wireless/ath/carl9170/fwdesc.h
@@ -69,6 +69,9 @@ enum carl9170fw_feature_list {
 	/* Firmware RX filter | CARL9170_CMD_RX_FILTER */
 	CARL9170FW_RX_FILTER,
 
+	/* Wake up on WLAN */
+	CARL9170FW_WOL,
+
 	/* KEEP LAST */
 	__CARL9170FW_FEATURE_NUM
 };
@@ -78,6 +81,7 @@ enum carl9170fw_feature_list {
 #define FIX_MAGIC	"FIX\0"
 #define DBG_MAGIC	"DBG\0"
 #define CHK_MAGIC	"CHK\0"
+#define TXSQ_MAGIC	"TXSQ"
 #define LAST_MAGIC	"LAST"
 
 #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
@@ -88,8 +92,10 @@ enum carl9170fw_feature_list {
 #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1)
 #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10)
 
+#define CARL9170FW_MAGIC_SIZE			4
+
 struct carl9170fw_desc_head {
-	u8	magic[4];
+	u8	magic[CARL9170FW_MAGIC_SIZE];
 	__le16 length;
 	u8 min_ver;
 	u8 cur_ver;
@@ -170,6 +176,16 @@ struct carl9170fw_chk_desc {
 #define CARL9170FW_CHK_DESC_SIZE			\
 	(sizeof(struct carl9170fw_chk_desc))
 
+#define CARL9170FW_TXSQ_DESC_MIN_VER			1
+#define CARL9170FW_TXSQ_DESC_CUR_VER			1
+struct carl9170fw_txsq_desc {
+	struct carl9170fw_desc_head head;
+
+	__le32 seq_table_addr;
+} __packed;
+#define CARL9170FW_TXSQ_DESC_SIZE			\
+	(sizeof(struct carl9170fw_txsq_desc))
+
 #define CARL9170FW_LAST_DESC_MIN_VER			1
 #define CARL9170FW_LAST_DESC_CUR_VER			2
 struct carl9170fw_last_desc {
@@ -189,8 +205,8 @@ struct carl9170fw_last_desc {
 	}
 
 static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head,
-					 u8 magic[4], __le16 length,
-					 u8 min_ver, u8 cur_ver)
+					 u8 magic[CARL9170FW_MAGIC_SIZE],
+					 __le16 length, u8 min_ver, u8 cur_ver)
 {
 	head->magic[0] = magic[0];
 	head->magic[1] = magic[1];
@@ -204,7 +220,7 @@ static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head,
 
 #define carl9170fw_for_each_hdr(desc, fw_desc)				\
 	for (desc = fw_desc;						\
-	     memcmp(desc->magic, LAST_MAGIC, 4) &&			\
+	     memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) &&	\
 	     le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE &&	\
 	     le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH;	\
 	     desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length)))
@@ -218,8 +234,8 @@ static inline bool carl9170fw_supports(__le32 list, u8 feature)
 }
 
 static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head,
-				       const u8 descid[4], u16 min_len,
-				       u8 compatible_revision)
+				       const u8 descid[CARL9170FW_MAGIC_SIZE],
+				       u16 min_len, u8 compatible_revision)
 {
 	if (descid[0] == head->magic[0] && descid[1] == head->magic[1] &&
 	    descid[2] == head->magic[2] && descid[3] == head->magic[3] &&
diff --git a/drivers/net/wireless/ath/carl9170/hw.h b/drivers/net/wireless/ath/carl9170/hw.h
index e85df6e..4e30762 100644
--- a/drivers/net/wireless/ath/carl9170/hw.h
+++ b/drivers/net/wireless/ath/carl9170/hw.h
@@ -463,6 +463,8 @@
 
 #define	AR9170_PWR_REG_CHIP_REVISION		(AR9170_PWR_REG_BASE + 0x010)
 #define AR9170_PWR_REG_PLL_ADDAC		(AR9170_PWR_REG_BASE + 0x014)
+#define		AR9170_PWR_PLL_ADDAC_DIV_S		2
+#define		AR9170_PWR_PLL_ADDAC_DIV		0xffc
 #define	AR9170_PWR_REG_WATCH_DOG_MAGIC		(AR9170_PWR_REG_BASE + 0x020)
 
 /* Faraday USB Controller */
@@ -471,6 +473,9 @@
 #define	AR9170_USB_REG_MAIN_CTRL		(AR9170_USB_REG_BASE + 0x000)
 #define		AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP	BIT(0)
 #define		AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT	BIT(2)
+#define		AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND	BIT(3)
+#define		AR9170_USB_MAIN_CTRL_RESET		BIT(4)
+#define		AR9170_USB_MAIN_CTRL_CHIP_ENABLE	BIT(5)
 #define		AR9170_USB_MAIN_CTRL_HIGHSPEED		BIT(6)
 
 #define	AR9170_USB_REG_DEVICE_ADDRESS		(AR9170_USB_REG_BASE + 0x001)
@@ -499,6 +504,13 @@
 #define	AR9170_USB_REG_INTR_GROUP		(AR9170_USB_REG_BASE + 0x020)
 
 #define	AR9170_USB_REG_INTR_SOURCE_0		(AR9170_USB_REG_BASE + 0x021)
+#define		AR9170_USB_INTR_SRC0_SETUP		BIT(0)
+#define		AR9170_USB_INTR_SRC0_IN			BIT(1)
+#define		AR9170_USB_INTR_SRC0_OUT		BIT(2)
+#define		AR9170_USB_INTR_SRC0_FAIL		BIT(3) /* ??? */
+#define		AR9170_USB_INTR_SRC0_END		BIT(4) /* ??? */
+#define		AR9170_USB_INTR_SRC0_ABORT		BIT(7)
+
 #define	AR9170_USB_REG_INTR_SOURCE_1		(AR9170_USB_REG_BASE + 0x022)
 #define	AR9170_USB_REG_INTR_SOURCE_2		(AR9170_USB_REG_BASE + 0x023)
 #define	AR9170_USB_REG_INTR_SOURCE_3		(AR9170_USB_REG_BASE + 0x024)
@@ -506,6 +518,15 @@
 #define	AR9170_USB_REG_INTR_SOURCE_5		(AR9170_USB_REG_BASE + 0x026)
 #define	AR9170_USB_REG_INTR_SOURCE_6		(AR9170_USB_REG_BASE + 0x027)
 #define	AR9170_USB_REG_INTR_SOURCE_7		(AR9170_USB_REG_BASE + 0x028)
+#define		AR9170_USB_INTR_SRC7_USB_RESET		BIT(1)
+#define		AR9170_USB_INTR_SRC7_USB_SUSPEND	BIT(2)
+#define		AR9170_USB_INTR_SRC7_USB_RESUME		BIT(3)
+#define		AR9170_USB_INTR_SRC7_ISO_SEQ_ERR	BIT(4)
+#define		AR9170_USB_INTR_SRC7_ISO_SEQ_ABORT	BIT(5)
+#define		AR9170_USB_INTR_SRC7_TX0BYTE		BIT(6)
+#define		AR9170_USB_INTR_SRC7_RX0BYTE		BIT(7)
+
+#define	AR9170_USB_REG_IDLE_COUNT		(AR9170_USB_REG_BASE + 0x02f)
 
 #define	AR9170_USB_REG_EP_MAP			(AR9170_USB_REG_BASE + 0x030)
 #define	AR9170_USB_REG_EP1_MAP			(AR9170_USB_REG_BASE + 0x030)
@@ -581,6 +602,10 @@
 
 #define	AR9170_USB_REG_MAX_AGG_UPLOAD		(AR9170_USB_REG_BASE + 0x110)
 #define	AR9170_USB_REG_UPLOAD_TIME_CTL		(AR9170_USB_REG_BASE + 0x114)
+
+#define AR9170_USB_REG_WAKE_UP			(AR9170_USB_REG_BASE + 0x120)
+#define		AR9170_USB_WAKE_UP_WAKE			BIT(0)
+
 #define	AR9170_USB_REG_CBUS_CTRL		(AR9170_USB_REG_BASE + 0x1f0)
 #define		AR9170_USB_CBUS_CTRL_BUFFER_END		(BIT(1))
 
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 870df8c..ede3d7e 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -662,6 +662,13 @@ init:
 			goto unlock;
 	}
 
+	if (ar->fw.tx_seq_table) {
+		err = carl9170_write_reg(ar, ar->fw.tx_seq_table + vif_id * 4,
+					 0);
+		if (err)
+			goto unlock;
+	}
+
 unlock:
 	if (err && (vif_id >= 0)) {
 		vif_priv->active = false;
@@ -1279,7 +1286,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
 				    struct ieee80211_vif *vif,
 				    enum ieee80211_ampdu_mlme_action action,
 				    struct ieee80211_sta *sta,
-				    u16 tid, u16 *ssn)
+				    u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ar9170 *ar = hw->priv;
 	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 6cc58e0..0ef70b6 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -862,6 +862,9 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
 	if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM))
 		txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
 
+	if (unlikely(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+		txc->s.misc |= CARL9170_TX_SUPER_MISC_ASSIGN_SEQ;
+
 	if (unlikely(ieee80211_is_probe_resp(hdr->frame_control)))
 		txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;
 
@@ -1336,7 +1339,7 @@ err_unlock_rcu:
 	return false;
 }
 
-int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ar9170 *ar = hw->priv;
 	struct ieee80211_tx_info *info;
@@ -1370,12 +1373,11 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	}
 
 	carl9170_tx(ar);
-	return NETDEV_TX_OK;
+	return;
 
 err_free:
 	ar->tx_dropped++;
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 void carl9170_tx_scheduler(struct ar9170 *ar)
diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h
index ee0f84f..15095c0 100644
--- a/drivers/net/wireless/ath/carl9170/version.h
+++ b/drivers/net/wireless/ath/carl9170/version.h
@@ -1,7 +1,7 @@
 #ifndef __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
-#define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 10
-#define CARL9170FW_VERSION_DAY 29
-#define CARL9170FW_VERSION_GIT "1.9.0"
+#define CARL9170FW_VERSION_YEAR 11
+#define CARL9170FW_VERSION_MONTH 1
+#define CARL9170FW_VERSION_DAY 22
+#define CARL9170FW_VERSION_GIT "1.9.2"
 #endif /* __CARL9170_SHARED_VERSION_H */
diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h
index 24d63b5..9e1324b 100644
--- a/drivers/net/wireless/ath/carl9170/wlan.h
+++ b/drivers/net/wireless/ath/carl9170/wlan.h
@@ -251,7 +251,7 @@ struct carl9170_tx_superdesc {
 	u8 ampdu_commit_factor:1;
 	u8 ampdu_unused_bit:1;
 	u8 queue:2;
-	u8 reserved:1;
+	u8 assign_seq:1;
 	u8 vif_id:3;
 	u8 fill_in_tsf:1;
 	u8 cab:1;
@@ -299,6 +299,7 @@ struct _ar9170_tx_hwdesc {
 
 #define CARL9170_TX_SUPER_MISC_QUEUE			0x3
 #define CARL9170_TX_SUPER_MISC_QUEUE_S			0
+#define CARL9170_TX_SUPER_MISC_ASSIGN_SEQ		0x4
 #define	CARL9170_TX_SUPER_MISC_VIF_ID			0x38
 #define	CARL9170_TX_SUPER_MISC_VIF_ID_S			3
 #define	CARL9170_TX_SUPER_MISC_FILL_IN_TSF		0x40
@@ -413,6 +414,23 @@ enum ar9170_txq {
 	__AR9170_NUM_TXQ,
 };
 
+/*
+ * This is an workaround for several undocumented bugs.
+ * Don't mess with the QoS/AC <-> HW Queue map, if you don't
+ * know what you are doing.
+ *
+ * Known problems [hardware]:
+ *  * The MAC does not aggregate frames on anything other
+ *    than the first HW queue.
+ *  * when an AMPDU is placed [in the first hw queue] and
+ *    additional frames are already queued on a different
+ *    hw queue, the MAC will ALWAYS freeze.
+ *
+ * In a nutshell: The hardware can either do QoS or
+ * Aggregation but not both at the same time. As a
+ * result, this makes the device pretty much useless
+ * for any serious 802.11n setup.
+ */
 static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
 
 #define	AR9170_TXQ_DEPTH			32
diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c
index 5d465e5..37b8e11 100644
--- a/drivers/net/wireless/ath/key.c
+++ b/drivers/net/wireless/ath/key.c
@@ -58,8 +58,11 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
 		REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
 		REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
 		REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
-		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)
+		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
 			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+		}
 
 	}
 
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 2b14775..f828f29 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -158,6 +158,13 @@ ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
 	}
 }
 
+bool ath_is_49ghz_allowed(u16 regdomain)
+{
+	/* possibly more */
+	return regdomain == MKK9_MKKC;
+}
+EXPORT_SYMBOL(ath_is_49ghz_allowed);
+
 /* Frequency is one where radar detection is required */
 static bool ath_is_radar_freq(u16 center_freq)
 {
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index 345dd97..172f63f 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -250,6 +250,7 @@ enum CountryCode {
 };
 
 bool ath_is_world_regd(struct ath_regulatory *reg);
+bool ath_is_49ghz_allowed(u16 redomain);
 int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
 		  int (*reg_notifier)(struct wiphy *wiphy,
 		  struct regulatory_request *request));
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 47033f6..480595f 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -92,7 +92,7 @@ config B43_PHY_N
 	---help---
 	  Support for the N-PHY.
 
-	  This enables support for devices with N-PHY revision up to 2.
+	  This enables support for devices with N-PHY.
 
 	  Say N if you expect high stability and performance. Saying Y will not
 	  affect other devices support and may provide support for basic needs.
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 22bc9f1..57eb5b6 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3203,7 +3203,7 @@ static void b43_tx_work(struct work_struct *work)
 	mutex_unlock(&wl->mutex);
 }
 
-static int b43_op_tx(struct ieee80211_hw *hw,
+static void b43_op_tx(struct ieee80211_hw *hw,
 		     struct sk_buff *skb)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -3211,14 +3211,12 @@ static int b43_op_tx(struct ieee80211_hw *hw,
 	if (unlikely(skb->len < 2 + 2 + 6)) {
 		/* Too short, this can't be a valid frame. */
 		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
 	skb_queue_tail(&wl->tx_queue, skb);
 	ieee80211_queue_work(wl->hw, &wl->tx_work);
-
-	return NETDEV_TX_OK;
 }
 
 static void b43_qos_params_upload(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index ab81ed8..8a00f9a 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -430,9 +430,9 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
 	bool workaround = false;
 
 	if (sprom->revision < 4)
-		workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM ||
-				binfo->type != 0x46D ||
-				binfo->rev < 0x41);
+		workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM &&
+				binfo->type == 0x46D &&
+				binfo->rev >= 0x41);
 	else
 		workaround =
 			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
@@ -1168,23 +1168,98 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
 static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+
+	/* PHY rev 0, 1, 2 */
 	u8 i, j;
 	u8 code;
 	u16 tmp;
+	u8 rfseq_events[3] = { 6, 8, 7 };
+	u8 rfseq_delays[3] = { 10, 30, 1 };
 
-	/* TODO: for PHY >= 3
-	s8 *lna1_gain, *lna2_gain;
-	u8 *gain_db, *gain_bits;
-	u16 *rfseq_init;
+	/* PHY rev >= 3 */
+	bool ghz5;
+	bool ext_lna;
+	u16 rssi_gain;
+	struct nphy_gain_ctl_workaround_entry *e;
 	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
 	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
-	*/
-
-	u8 rfseq_events[3] = { 6, 8, 7 };
-	u8 rfseq_delays[3] = { 10, 30, 1 };
 
 	if (dev->phy.rev >= 3) {
-		/* TODO */
+		/* Prepare values */
+		ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
+			& B43_NPHY_BANDCTL_5GHZ;
+		ext_lna = sprom->boardflags_lo & B43_BFL_EXTLNA;
+		e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
+		if (ghz5 && dev->phy.rev >= 5)
+			rssi_gain = 0x90;
+		else
+			rssi_gain = 0x50;
+
+		b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
+
+		/* Set Clip 2 detect */
+		b43_phy_set(dev, B43_NPHY_C1_CGAINI,
+				B43_NPHY_C1_CGAINI_CL2DETECT);
+		b43_phy_set(dev, B43_NPHY_C2_CGAINI,
+				B43_NPHY_C2_CGAINI_CL2DETECT);
+
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
+				rssi_gain);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
+				rssi_gain);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
+
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
+		b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
+		b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
+		b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
+
+		b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
+		b43_phy_write(dev, 0x2A7, e->init_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
+					e->rfseq_init);
+		b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
+
+		/* TODO: check defines. Do not match variables names */
+		b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
+		b43_phy_write(dev, 0x2A9, e->cliphi_gain);
+		b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
+		b43_phy_write(dev, 0x2AB, e->clipmd_gain);
+		b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
+		b43_phy_write(dev, 0x2AD, e->cliplo_gain);
+
+		b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
+		b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
+		b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
+		b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
+		b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
+		b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+				~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
+		b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+				~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
+		b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
 	} else {
 		/* Set Clip 2 detect */
 		b43_phy_set(dev, B43_NPHY_C1_CGAINI,
@@ -1281,17 +1356,17 @@ static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 						B43_NPHY_TABLE_DATALO, tmp);
 				}
 			}
+		}
 
-			b43_nphy_set_rf_sequence(dev, 5,
-					rfseq_events, rfseq_delays, 3);
-			b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
-				~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
-				0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
+		b43_nphy_set_rf_sequence(dev, 5,
+				rfseq_events, rfseq_delays, 3);
+		b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
+			~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
+			0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
 
-			if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-				b43_phy_maskset(dev, B43_PHY_N(0xC5D),
-						0xFF80, 4);
-		}
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+			b43_phy_maskset(dev, B43_PHY_N(0xC5D),
+					0xFF80, 4);
 	}
 }
 
@@ -1308,6 +1383,9 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
 	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
 	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
 
+	u16 tmp16;
+	u32 tmp32;
+
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
 		b43_nphy_classifier(dev, 1, 0);
 	else
@@ -1320,7 +1398,82 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
 		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
 
 	if (dev->phy.rev >= 3) {
+		tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+		tmp32 &= 0xffffff;
+		b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+
+		b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+		b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
+		b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+		b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
+		b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
+		b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+		b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
+		b43_phy_write(dev, 0x2AE, 0x000C);
+
 		/* TODO */
+
+		tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
+			0x2 : 0x9C40;
+		b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+
+		b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+
+		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
+		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
+
+		b43_nphy_gain_ctrl_workarounds(dev);
+
+		b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
+		b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
+
+		/* TODO */
+
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+
+		/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
+
+		if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR &&
+		    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
+		    (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR &&
+		    b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
+			tmp32 = 0x00088888;
+		else
+			tmp32 = 0x88888888;
+		b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
+		b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
+		b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
+
+		if (dev->phy.rev == 4 &&
+		    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+			b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
+					0x70);
+			b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
+					0x70);
+		}
+
+		b43_phy_write(dev, 0x224, 0x039C);
+		b43_phy_write(dev, 0x225, 0x0357);
+		b43_phy_write(dev, 0x226, 0x0317);
+		b43_phy_write(dev, 0x227, 0x02D7);
+		b43_phy_write(dev, 0x228, 0x039C);
+		b43_phy_write(dev, 0x229, 0x0357);
+		b43_phy_write(dev, 0x22A, 0x0317);
+		b43_phy_write(dev, 0x22B, 0x02D7);
+		b43_phy_write(dev, 0x22C, 0x039C);
+		b43_phy_write(dev, 0x22D, 0x0357);
+		b43_phy_write(dev, 0x22E, 0x0317);
+		b43_phy_write(dev, 0x22F, 0x02D7);
 	} else {
 		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
 		    nphy->band5g_pwrgain) {
@@ -2128,7 +2281,7 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
 		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
 		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
 		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
-	} else if (dev->phy.rev == 2) {
+	} else {
 		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
 		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
 		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
@@ -2179,7 +2332,7 @@ static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
 		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
-	} else if (dev->phy.rev == 2) {
+	} else {
 		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
 		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
 		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
@@ -3878,10 +4031,14 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
 	}
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
 {
-	b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
-		      on ? 0 : 0x7FFF);
+	u16 val = on ? 0 : 0x7FFF;
+
+	if (dev->phy.rev >= 3)
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
+	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
 }
 
 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index dc8ef09..2de483b 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -1097,6 +1097,1080 @@ static const u32 b43_ntab_tmap[] = {
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 };
 
+/* static tables, PHY revision >= 3 */
+static const u32 b43_ntab_framestruct_r3[] = {
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x09804506, 0x00100030, 0x09804507, 0x00100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a0c, 0x00100004, 0x01000a0d, 0x00100024,
+	0x0980450e, 0x00100034, 0x0980450f, 0x00100034,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a04, 0x00100000, 0x11008a05, 0x00100020,
+	0x1980c506, 0x00100030, 0x21810506, 0x00100030,
+	0x21810506, 0x00100030, 0x01800504, 0x00100030,
+	0x11808505, 0x00100030, 0x29814507, 0x01100030,
+	0x00000a04, 0x00100000, 0x11008a05, 0x00100020,
+	0x21810506, 0x00100030, 0x21810506, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x1980c50e, 0x00100038, 0x2181050e, 0x00100038,
+	0x2181050e, 0x00100038, 0x0180050c, 0x00100038,
+	0x1180850d, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x2181050e, 0x00100038, 0x2181050e, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x1980c506, 0x00100030, 0x1980c506, 0x00100030,
+	0x11808504, 0x00100030, 0x3981ca05, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x10008a04, 0x00100000, 0x3981ca05, 0x00100030,
+	0x1980c506, 0x00100030, 0x29814507, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a0c, 0x00100008, 0x01000a0d, 0x00100028,
+	0x1980c50e, 0x00100038, 0x1980c50e, 0x00100038,
+	0x1180850c, 0x00100038, 0x3981ca0d, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x10008a0c, 0x00100008, 0x3981ca0d, 0x00100038,
+	0x1980c50e, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x02001405, 0x00100040,
+	0x0b004a06, 0x01900060, 0x13008a06, 0x01900060,
+	0x13008a06, 0x01900060, 0x43020a04, 0x00100060,
+	0x1b00ca05, 0x00100060, 0x23010a07, 0x01500060,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x13008a06, 0x01900060, 0x13008a06, 0x01900060,
+	0x23010a07, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x0200140d, 0x00100050,
+	0x0b004a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x13008a0e, 0x01900070, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x23010a0f, 0x01500070,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x13008a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x0b004a06, 0x01900060, 0x0b004a06, 0x01900060,
+	0x5b02ca04, 0x00100060, 0x3b01d405, 0x00100060,
+	0x23010a07, 0x01500060, 0x00000000, 0x00000000,
+	0x5802d404, 0x00100000, 0x3b01d405, 0x00100060,
+	0x0b004a06, 0x01900060, 0x23010a07, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x5002940c, 0x00100010, 0x3201940d, 0x00100050,
+	0x0b004a0e, 0x01900070, 0x0b004a0e, 0x01900070,
+	0x5b02ca0c, 0x00100070, 0x3b01d40d, 0x00100070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x5802d40c, 0x00100010, 0x3b01d40d, 0x00100070,
+	0x0b004a0e, 0x01900070, 0x23010a0f, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x000f4800, 0x62031405, 0x00100040,
+	0x53028a06, 0x01900060, 0x53028a07, 0x01900060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x000f4808, 0x6203140d, 0x00100048,
+	0x53028a0e, 0x01900068, 0x53028a0f, 0x01900068,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100004, 0x11008a0d, 0x00100024,
+	0x1980c50e, 0x00100034, 0x2181050e, 0x00100034,
+	0x2181050e, 0x00100034, 0x0180050c, 0x00100038,
+	0x1180850d, 0x00100038, 0x1181850d, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x2181050e, 0x00100038, 0x2181050e, 0x00100038,
+	0x1181850d, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x0180c506, 0x00100030, 0x0180c506, 0x00100030,
+	0x2180c50c, 0x00100030, 0x49820a0d, 0x0016a130,
+	0x41824a0d, 0x0016a130, 0x2981450f, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x2000ca0c, 0x00100000, 0x49820a0d, 0x0016a130,
+	0x1980c50e, 0x00100030, 0x41824a0d, 0x0016a130,
+	0x2981450f, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100008, 0x0200140d, 0x00100048,
+	0x0b004a0e, 0x01900068, 0x13008a0e, 0x01900068,
+	0x13008a0e, 0x01900068, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x1b014a0d, 0x00100070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x13008a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x1b014a0d, 0x00100070, 0x23010a0f, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x03004a06, 0x01900060, 0x03004a06, 0x01900060,
+	0x6b030a0c, 0x00100060, 0x4b02140d, 0x0016a160,
+	0x4302540d, 0x0016a160, 0x23010a0f, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x6b03140c, 0x00100060, 0x4b02140d, 0x0016a160,
+	0x0b004a0e, 0x01900060, 0x4302540d, 0x0016a160,
+	0x23010a0f, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x53028a06, 0x01900060, 0x5b02ca06, 0x01900060,
+	0x5b02ca06, 0x01900060, 0x43020a04, 0x00100060,
+	0x1b00ca05, 0x00100060, 0x53028a07, 0x0190c060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x53028a0e, 0x01900070, 0x5b02ca0e, 0x01900070,
+	0x5b02ca0e, 0x01900070, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x53028a0f, 0x0190c070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x5b02ca06, 0x01900060, 0x5b02ca06, 0x01900060,
+	0x53028a07, 0x0190c060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x5b02ca0e, 0x01900070, 0x5b02ca0e, 0x01900070,
+	0x53028a0f, 0x0190c070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_ntab_pilot_r3[] = {
+	0xff08, 0xff08, 0xff08, 0xff08, 0xff08, 0xff08,
+	0xff08, 0xff08, 0x80d5, 0x80d5, 0x80d5, 0x80d5,
+	0x80d5, 0x80d5, 0x80d5, 0x80d5, 0xff0a, 0xff82,
+	0xffa0, 0xff28, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xff82, 0xffa0, 0xff28, 0xff0a, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xf83f, 0xfa1f, 0xfa97, 0xfab5,
+	0xf2bd, 0xf0bf, 0xffff, 0xffff, 0xf017, 0xf815,
+	0xf215, 0xf095, 0xf035, 0xf01d, 0xffff, 0xffff,
+	0xff08, 0xff02, 0xff80, 0xff20, 0xff08, 0xff02,
+	0xff80, 0xff20, 0xf01f, 0xf817, 0xfa15, 0xf295,
+	0xf0b5, 0xf03d, 0xffff, 0xffff, 0xf82a, 0xfa0a,
+	0xfa82, 0xfaa0, 0xf2a8, 0xf0aa, 0xffff, 0xffff,
+	0xf002, 0xf800, 0xf200, 0xf080, 0xf020, 0xf008,
+	0xffff, 0xffff, 0xf00a, 0xf802, 0xfa00, 0xf280,
+	0xf0a0, 0xf028, 0xffff, 0xffff,
+};
+
+static const u32 b43_ntab_tmap_r3[] = {
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00011111,
+	0x11110000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00088aaa,
+	0xaaaa0000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xaaa8aaa0, 0x8aaa8aaa, 0xaa8a8a8a, 0x000aaa88,
+	0x8aaa0000, 0xaaa8a888, 0x8aa88a8a, 0x8a88a888,
+	0x08080a00, 0x0a08080a, 0x080a0a08, 0x00080808,
+	0x080a0000, 0x080a0808, 0x080a0808, 0x0a0a0a08,
+	0xa0a0a0a0, 0x80a0a080, 0x8080a0a0, 0x00008080,
+	0x80a00000, 0x80a080a0, 0xa080a0a0, 0x8080a0a0,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x99999000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x22000000, 0x2222b222, 0x22222222, 0x222222b2,
+	0xb2222220, 0x22222222, 0x22d22222, 0x00000222,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x33000000, 0x3333b333, 0x33333333, 0x333333b3,
+	0xb3333330, 0x33333333, 0x33d33333, 0x00000333,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x99b99b00, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb99, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x22222200, 0x2222f222, 0x22222222, 0x222222f2,
+	0x22222222, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x11111111,
+	0xf1111111, 0x11111111, 0x11f11111, 0x01111111,
+	0xbb9bb900, 0xb9b9bb99, 0xb99bbbbb, 0xbbbb9b9b,
+	0xb9bb99bb, 0xb99999b9, 0xb9b9b99b, 0x00000bbb,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88aa, 0xa88888a8, 0xa8a8a88a, 0x0a888aaa,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00000aaa,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0xbbbbbb00, 0x999bbbbb, 0x9bb99b9b, 0xb9b9b9bb,
+	0xb9b99bbb, 0xb9b9b9bb, 0xb9bb9b99, 0x00000999,
+	0x8a000000, 0xaa88a888, 0xa88888aa, 0xa88a8a88,
+	0xa88aa88a, 0x88a8aaaa, 0xa8aa8aaa, 0x0888a88a,
+	0x0b0b0b00, 0x090b0b0b, 0x0b090b0b, 0x0909090b,
+	0x09090b0b, 0x09090b0b, 0x09090b09, 0x00000909,
+	0x0a000000, 0x0a080808, 0x080a080a, 0x080a0a08,
+	0x080a080a, 0x0808080a, 0x0a0a0a08, 0x0808080a,
+	0xb0b0b000, 0x9090b0b0, 0x90b09090, 0xb0b0b090,
+	0xb0b090b0, 0x90b0b0b0, 0xb0b09090, 0x00000090,
+	0x80000000, 0xa080a080, 0xa08080a0, 0xa0808080,
+	0xa080a080, 0x80a0a0a0, 0xa0a080a0, 0x00a0a0a0,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x33000000, 0x3333f333, 0x33333333, 0x333333f3,
+	0xf3333330, 0x33333333, 0x33f33333, 0x00000333,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x99000000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88888000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x88a88a00, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_intlevel_r3[] = {
+	0x00802070, 0x0671188d, 0x0a60192c, 0x0a300e46,
+	0x00c1188d, 0x080024d2, 0x00000070,
+};
+
+static const u32 b43_ntab_tdtrn_r3[] = {
+	0x061c061c, 0x0050ee68, 0xf592fe36, 0xfe5212f6,
+	0x00000c38, 0xfe5212f6, 0xf592fe36, 0x0050ee68,
+	0x061c061c, 0xee680050, 0xfe36f592, 0x12f6fe52,
+	0x0c380000, 0x12f6fe52, 0xfe36f592, 0xee680050,
+	0x061c061c, 0x0050ee68, 0xf592fe36, 0xfe5212f6,
+	0x00000c38, 0xfe5212f6, 0xf592fe36, 0x0050ee68,
+	0x061c061c, 0xee680050, 0xfe36f592, 0x12f6fe52,
+	0x0c380000, 0x12f6fe52, 0xfe36f592, 0xee680050,
+	0x05e305e3, 0x004def0c, 0xf5f3fe47, 0xfe611246,
+	0x00000bc7, 0xfe611246, 0xf5f3fe47, 0x004def0c,
+	0x05e305e3, 0xef0c004d, 0xfe47f5f3, 0x1246fe61,
+	0x0bc70000, 0x1246fe61, 0xfe47f5f3, 0xef0c004d,
+	0x05e305e3, 0x004def0c, 0xf5f3fe47, 0xfe611246,
+	0x00000bc7, 0xfe611246, 0xf5f3fe47, 0x004def0c,
+	0x05e305e3, 0xef0c004d, 0xfe47f5f3, 0x1246fe61,
+	0x0bc70000, 0x1246fe61, 0xfe47f5f3, 0xef0c004d,
+	0xfa58fa58, 0xf895043b, 0xff4c09c0, 0xfbc6ffa8,
+	0xfb84f384, 0x0798f6f9, 0x05760122, 0x058409f6,
+	0x0b500000, 0x05b7f542, 0x08860432, 0x06ddfee7,
+	0xfb84f384, 0xf9d90664, 0xf7e8025c, 0x00fff7bd,
+	0x05a805a8, 0xf7bd00ff, 0x025cf7e8, 0x0664f9d9,
+	0xf384fb84, 0xfee706dd, 0x04320886, 0xf54205b7,
+	0x00000b50, 0x09f60584, 0x01220576, 0xf6f90798,
+	0xf384fb84, 0xffa8fbc6, 0x09c0ff4c, 0x043bf895,
+	0x02d402d4, 0x07de0270, 0xfc96079c, 0xf90afe94,
+	0xfe00ff2c, 0x02d4065d, 0x092a0096, 0x0014fbb8,
+	0xfd2cfd2c, 0x076afb3c, 0x0096f752, 0xf991fd87,
+	0xfb2c0200, 0xfeb8f960, 0x08e0fc96, 0x049802a8,
+	0xfd2cfd2c, 0x02a80498, 0xfc9608e0, 0xf960feb8,
+	0x0200fb2c, 0xfd87f991, 0xf7520096, 0xfb3c076a,
+	0xfd2cfd2c, 0xfbb80014, 0x0096092a, 0x065d02d4,
+	0xff2cfe00, 0xfe94f90a, 0x079cfc96, 0x027007de,
+	0x02d402d4, 0x027007de, 0x079cfc96, 0xfe94f90a,
+	0xff2cfe00, 0x065d02d4, 0x0096092a, 0xfbb80014,
+	0xfd2cfd2c, 0xfb3c076a, 0xf7520096, 0xfd87f991,
+	0x0200fb2c, 0xf960feb8, 0xfc9608e0, 0x02a80498,
+	0xfd2cfd2c, 0x049802a8, 0x08e0fc96, 0xfeb8f960,
+	0xfb2c0200, 0xf991fd87, 0x0096f752, 0x076afb3c,
+	0xfd2cfd2c, 0x0014fbb8, 0x092a0096, 0x02d4065d,
+	0xfe00ff2c, 0xf90afe94, 0xfc96079c, 0x07de0270,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x062a0000, 0xfefa0759, 0x08b80908, 0xf396fc2d,
+	0xf9d6045c, 0xfc4ef608, 0xf748f596, 0x07b207bf,
+	0x062a062a, 0xf84ef841, 0xf748f596, 0x03b209f8,
+	0xf9d6045c, 0x0c6a03d3, 0x08b80908, 0x0106f8a7,
+	0x062a0000, 0xfefaf8a7, 0x08b8f6f8, 0xf39603d3,
+	0xf9d6fba4, 0xfc4e09f8, 0xf7480a6a, 0x07b2f841,
+	0x062af9d6, 0xf84e07bf, 0xf7480a6a, 0x03b2f608,
+	0xf9d6fba4, 0x0c6afc2d, 0x08b8f6f8, 0x01060759,
+	0x062a0000, 0xfefa0759, 0x08b80908, 0xf396fc2d,
+	0xf9d6045c, 0xfc4ef608, 0xf748f596, 0x07b207bf,
+	0x062a062a, 0xf84ef841, 0xf748f596, 0x03b209f8,
+	0xf9d6045c, 0x0c6a03d3, 0x08b80908, 0x0106f8a7,
+	0x062a0000, 0xfefaf8a7, 0x08b8f6f8, 0xf39603d3,
+	0xf9d6fba4, 0xfc4e09f8, 0xf7480a6a, 0x07b2f841,
+	0x062af9d6, 0xf84e07bf, 0xf7480a6a, 0x03b2f608,
+	0xf9d6fba4, 0x0c6afc2d, 0x08b8f6f8, 0x01060759,
+	0x061c061c, 0xff30009d, 0xffb21141, 0xfd87fb54,
+	0xf65dfe59, 0x02eef99e, 0x0166f03c, 0xfff809b6,
+	0x000008a4, 0x000af42b, 0x00eff577, 0xfa840bf2,
+	0xfc02ff51, 0x08260f67, 0xfff0036f, 0x0842f9c3,
+	0x00000000, 0x063df7be, 0xfc910010, 0xf099f7da,
+	0x00af03fe, 0xf40e057c, 0x0a89ff11, 0x0bd5fff6,
+	0xf75c0000, 0xf64a0008, 0x0fc4fe9a, 0x0662fd12,
+	0x01a709a3, 0x04ac0279, 0xeebf004e, 0xff6300d0,
+	0xf9e4f9e4, 0x00d0ff63, 0x004eeebf, 0x027904ac,
+	0x09a301a7, 0xfd120662, 0xfe9a0fc4, 0x0008f64a,
+	0x0000f75c, 0xfff60bd5, 0xff110a89, 0x057cf40e,
+	0x03fe00af, 0xf7daf099, 0x0010fc91, 0xf7be063d,
+	0x00000000, 0xf9c30842, 0x036ffff0, 0x0f670826,
+	0xff51fc02, 0x0bf2fa84, 0xf57700ef, 0xf42b000a,
+	0x08a40000, 0x09b6fff8, 0xf03c0166, 0xf99e02ee,
+	0xfe59f65d, 0xfb54fd87, 0x1141ffb2, 0x009dff30,
+	0x05e30000, 0xff060705, 0x085408a0, 0xf425fc59,
+	0xfa1d042a, 0xfc78f67a, 0xf7acf60e, 0x075a0766,
+	0x05e305e3, 0xf8a6f89a, 0xf7acf60e, 0x03880986,
+	0xfa1d042a, 0x0bdb03a7, 0x085408a0, 0x00faf8fb,
+	0x05e30000, 0xff06f8fb, 0x0854f760, 0xf42503a7,
+	0xfa1dfbd6, 0xfc780986, 0xf7ac09f2, 0x075af89a,
+	0x05e3fa1d, 0xf8a60766, 0xf7ac09f2, 0x0388f67a,
+	0xfa1dfbd6, 0x0bdbfc59, 0x0854f760, 0x00fa0705,
+	0x05e30000, 0xff060705, 0x085408a0, 0xf425fc59,
+	0xfa1d042a, 0xfc78f67a, 0xf7acf60e, 0x075a0766,
+	0x05e305e3, 0xf8a6f89a, 0xf7acf60e, 0x03880986,
+	0xfa1d042a, 0x0bdb03a7, 0x085408a0, 0x00faf8fb,
+	0x05e30000, 0xff06f8fb, 0x0854f760, 0xf42503a7,
+	0xfa1dfbd6, 0xfc780986, 0xf7ac09f2, 0x075af89a,
+	0x05e3fa1d, 0xf8a60766, 0xf7ac09f2, 0x0388f67a,
+	0xfa1dfbd6, 0x0bdbfc59, 0x0854f760, 0x00fa0705,
+	0xfa58fa58, 0xf8f0fe00, 0x0448073d, 0xfdc9fe46,
+	0xf9910258, 0x089d0407, 0xfd5cf71a, 0x02affde0,
+	0x083e0496, 0xff5a0740, 0xff7afd97, 0x00fe01f1,
+	0x0009082e, 0xfa94ff75, 0xfecdf8ea, 0xffb0f693,
+	0xfd2cfa58, 0x0433ff16, 0xfba405dd, 0xfa610341,
+	0x06a606cb, 0x0039fd2d, 0x0677fa97, 0x01fa05e0,
+	0xf896003e, 0x075a068b, 0x012cfc3e, 0xfa23f98d,
+	0xfc7cfd43, 0xff90fc0d, 0x01c10982, 0x00c601d6,
+	0xfd2cfd2c, 0x01d600c6, 0x098201c1, 0xfc0dff90,
+	0xfd43fc7c, 0xf98dfa23, 0xfc3e012c, 0x068b075a,
+	0x003ef896, 0x05e001fa, 0xfa970677, 0xfd2d0039,
+	0x06cb06a6, 0x0341fa61, 0x05ddfba4, 0xff160433,
+	0xfa58fd2c, 0xf693ffb0, 0xf8eafecd, 0xff75fa94,
+	0x082e0009, 0x01f100fe, 0xfd97ff7a, 0x0740ff5a,
+	0x0496083e, 0xfde002af, 0xf71afd5c, 0x0407089d,
+	0x0258f991, 0xfe46fdc9, 0x073d0448, 0xfe00f8f0,
+	0xfd2cfd2c, 0xfce00500, 0xfc09fddc, 0xfe680157,
+	0x04c70571, 0xfc3aff21, 0xfcd70228, 0x056d0277,
+	0x0200fe00, 0x0022f927, 0xfe3c032b, 0xfc44ff3c,
+	0x03e9fbdb, 0x04570313, 0x04c9ff5c, 0x000d03b8,
+	0xfa580000, 0xfbe900d2, 0xf9d0fe0b, 0x0125fdf9,
+	0x042501bf, 0x0328fa2b, 0xffa902f0, 0xfa250157,
+	0x0200fe00, 0x03740438, 0xff0405fd, 0x030cfe52,
+	0x0037fb39, 0xff6904c5, 0x04f8fd23, 0xfd31fc1b,
+	0xfd2cfd2c, 0xfc1bfd31, 0xfd2304f8, 0x04c5ff69,
+	0xfb390037, 0xfe52030c, 0x05fdff04, 0x04380374,
+	0xfe000200, 0x0157fa25, 0x02f0ffa9, 0xfa2b0328,
+	0x01bf0425, 0xfdf90125, 0xfe0bf9d0, 0x00d2fbe9,
+	0x0000fa58, 0x03b8000d, 0xff5c04c9, 0x03130457,
+	0xfbdb03e9, 0xff3cfc44, 0x032bfe3c, 0xf9270022,
+	0xfe000200, 0x0277056d, 0x0228fcd7, 0xff21fc3a,
+	0x057104c7, 0x0157fe68, 0xfddcfc09, 0x0500fce0,
+	0xfd2cfd2c, 0x0500fce0, 0xfddcfc09, 0x0157fe68,
+	0x057104c7, 0xff21fc3a, 0x0228fcd7, 0x0277056d,
+	0xfe000200, 0xf9270022, 0x032bfe3c, 0xff3cfc44,
+	0xfbdb03e9, 0x03130457, 0xff5c04c9, 0x03b8000d,
+	0x0000fa58, 0x00d2fbe9, 0xfe0bf9d0, 0xfdf90125,
+	0x01bf0425, 0xfa2b0328, 0x02f0ffa9, 0x0157fa25,
+	0xfe000200, 0x04380374, 0x05fdff04, 0xfe52030c,
+	0xfb390037, 0x04c5ff69, 0xfd2304f8, 0xfc1bfd31,
+	0xfd2cfd2c, 0xfd31fc1b, 0x04f8fd23, 0xff6904c5,
+	0x0037fb39, 0x030cfe52, 0xff0405fd, 0x03740438,
+	0x0200fe00, 0xfa250157, 0xffa902f0, 0x0328fa2b,
+	0x042501bf, 0x0125fdf9, 0xf9d0fe0b, 0xfbe900d2,
+	0xfa580000, 0x000d03b8, 0x04c9ff5c, 0x04570313,
+	0x03e9fbdb, 0xfc44ff3c, 0xfe3c032b, 0x0022f927,
+	0x0200fe00, 0x056d0277, 0xfcd70228, 0xfc3aff21,
+	0x04c70571, 0xfe680157, 0xfc09fddc, 0xfce00500,
+	0x05a80000, 0xff1006be, 0x0800084a, 0xf49cfc7e,
+	0xfa580400, 0xfc9cf6da, 0xf800f672, 0x0710071c,
+	0x05a805a8, 0xf8f0f8e4, 0xf800f672, 0x03640926,
+	0xfa580400, 0x0b640382, 0x0800084a, 0x00f0f942,
+	0x05a80000, 0xff10f942, 0x0800f7b6, 0xf49c0382,
+	0xfa58fc00, 0xfc9c0926, 0xf800098e, 0x0710f8e4,
+	0x05a8fa58, 0xf8f0071c, 0xf800098e, 0x0364f6da,
+	0xfa58fc00, 0x0b64fc7e, 0x0800f7b6, 0x00f006be,
+	0x05a80000, 0xff1006be, 0x0800084a, 0xf49cfc7e,
+	0xfa580400, 0xfc9cf6da, 0xf800f672, 0x0710071c,
+	0x05a805a8, 0xf8f0f8e4, 0xf800f672, 0x03640926,
+	0xfa580400, 0x0b640382, 0x0800084a, 0x00f0f942,
+	0x05a80000, 0xff10f942, 0x0800f7b6, 0xf49c0382,
+	0xfa58fc00, 0xfc9c0926, 0xf800098e, 0x0710f8e4,
+	0x05a8fa58, 0xf8f0071c, 0xf800098e, 0x0364f6da,
+	0xfa58fc00, 0x0b64fc7e, 0x0800f7b6, 0x00f006be,
+};
+
+static const u32 b43_ntab_noisevar0_r3[] = {
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+};
+
+static const u32 b43_ntab_noisevar1_r3[] = {
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+};
+
+static const u16 b43_ntab_mcs_r3[] = {
+	0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
+	0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
+	0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
+	0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
+	0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
+	0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
+	0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
+	0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
+	0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
+	0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
+	0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
+	0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
+	0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
+	0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
+	0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
+	0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
+	0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007,
+};
+
+static const u32 b43_ntab_tdi20a0_r3[] = {
+	0x00091226, 0x000a1429, 0x000b56ad, 0x000c58b0,
+	0x000d5ab3, 0x000e9cb6, 0x000f9eba, 0x0000c13d,
+	0x00020301, 0x00030504, 0x00040708, 0x0005090b,
+	0x00064b8e, 0x00095291, 0x000a5494, 0x000b9718,
+	0x000c9927, 0x000d9b2a, 0x000edd2e, 0x000fdf31,
+	0x000101b4, 0x000243b7, 0x000345bb, 0x000447be,
+	0x00058982, 0x00068c05, 0x00099309, 0x000a950c,
+	0x000bd78f, 0x000cd992, 0x000ddb96, 0x000f1d99,
+	0x00005fa8, 0x0001422c, 0x0002842f, 0x00038632,
+	0x00048835, 0x0005ca38, 0x0006ccbc, 0x0009d3bf,
+	0x000b1603, 0x000c1806, 0x000d1a0a, 0x000e1c0d,
+	0x000f5e10, 0x00008093, 0x00018297, 0x0002c49a,
+	0x0003c680, 0x0004c880, 0x00060b00, 0x00070d00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi20a1_r3[] = {
+	0x00014b26, 0x00028d29, 0x000393ad, 0x00049630,
+	0x0005d833, 0x0006da36, 0x00099c3a, 0x000a9e3d,
+	0x000bc081, 0x000cc284, 0x000dc488, 0x000f068b,
+	0x0000488e, 0x00018b91, 0x0002d214, 0x0003d418,
+	0x0004d6a7, 0x000618aa, 0x00071aae, 0x0009dcb1,
+	0x000b1eb4, 0x000c0137, 0x000d033b, 0x000e053e,
+	0x000f4702, 0x00008905, 0x00020c09, 0x0003128c,
+	0x0004148f, 0x00051712, 0x00065916, 0x00091b19,
+	0x000a1d28, 0x000b5f2c, 0x000c41af, 0x000d43b2,
+	0x000e85b5, 0x000f87b8, 0x0000c9bc, 0x00024cbf,
+	0x00035303, 0x00045506, 0x0005978a, 0x0006998d,
+	0x00095b90, 0x000a5d93, 0x000b9f97, 0x000c821a,
+	0x000d8400, 0x000ec600, 0x000fc800, 0x00010a00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a0_r3[] = {
+	0x0011a346, 0x00136ccf, 0x0014f5d9, 0x001641e2,
+	0x0017cb6b, 0x00195475, 0x001b2383, 0x001cad0c,
+	0x001e7616, 0x0000821f, 0x00020ba8, 0x0003d4b2,
+	0x00056447, 0x00072dd0, 0x0008b6da, 0x000a02e3,
+	0x000b8c6c, 0x000d15f6, 0x0011e484, 0x0013ae0d,
+	0x00153717, 0x00168320, 0x00180ca9, 0x00199633,
+	0x001b6548, 0x001ceed1, 0x001eb7db, 0x0000c3e4,
+	0x00024d6d, 0x000416f7, 0x0005a585, 0x00076f0f,
+	0x0008f818, 0x000a4421, 0x000bcdab, 0x000d9734,
+	0x00122649, 0x0013efd2, 0x001578dc, 0x0016c4e5,
+	0x00184e6e, 0x001a17f8, 0x001ba686, 0x001d3010,
+	0x001ef999, 0x00010522, 0x00028eac, 0x00045835,
+	0x0005e74a, 0x0007b0d3, 0x00093a5d, 0x000a85e6,
+	0x000c0f6f, 0x000dd8f9, 0x00126787, 0x00143111,
+	0x0015ba9a, 0x00170623, 0x00188fad, 0x001a5936,
+	0x001be84b, 0x001db1d4, 0x001f3b5e, 0x000146e7,
+	0x00031070, 0x000499fa, 0x00062888, 0x0007f212,
+	0x00097b9b, 0x000ac7a4, 0x000c50ae, 0x000e1a37,
+	0x0012a94c, 0x001472d5, 0x0015fc5f, 0x00174868,
+	0x0018d171, 0x001a9afb, 0x001c2989, 0x001df313,
+	0x001f7c9c, 0x000188a5, 0x000351af, 0x0004db38,
+	0x0006aa4d, 0x000833d7, 0x0009bd60, 0x000b0969,
+	0x000c9273, 0x000e5bfc, 0x00132a8a, 0x0014b414,
+	0x00163d9d, 0x001789a6, 0x001912b0, 0x001adc39,
+	0x001c6bce, 0x001e34d8, 0x001fbe61, 0x0001ca6a,
+	0x00039374, 0x00051cfd, 0x0006ec0b, 0x00087515,
+	0x0009fe9e, 0x000b4aa7, 0x000cd3b1, 0x000e9d3a,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a1_r3[] = {
+	0x001edb36, 0x000129ca, 0x0002b353, 0x00047cdd,
+	0x0005c8e6, 0x000791ef, 0x00091bf9, 0x000aaa07,
+	0x000c3391, 0x000dfd1a, 0x00120923, 0x0013d22d,
+	0x00155c37, 0x0016eacb, 0x00187454, 0x001a3dde,
+	0x001b89e7, 0x001d12f0, 0x001f1cfa, 0x00016b88,
+	0x00033492, 0x0004be1b, 0x00060a24, 0x0007d32e,
+	0x00095d38, 0x000aec4c, 0x000c7555, 0x000e3edf,
+	0x00124ae8, 0x001413f1, 0x0015a37b, 0x00172c89,
+	0x0018b593, 0x001a419c, 0x001bcb25, 0x001d942f,
+	0x001f63b9, 0x0001ad4d, 0x00037657, 0x0004c260,
+	0x00068be9, 0x000814f3, 0x0009a47c, 0x000b2d8a,
+	0x000cb694, 0x000e429d, 0x00128c26, 0x001455b0,
+	0x0015e4ba, 0x00176e4e, 0x0018f758, 0x001a8361,
+	0x001c0cea, 0x001dd674, 0x001fa57d, 0x0001ee8b,
+	0x0003b795, 0x0005039e, 0x0006cd27, 0x000856b1,
+	0x0009e5c6, 0x000b6f4f, 0x000cf859, 0x000e8462,
+	0x00130deb, 0x00149775, 0x00162603, 0x0017af8c,
+	0x00193896, 0x001ac49f, 0x001c4e28, 0x001e17b2,
+	0x0000a6c7, 0x00023050, 0x0003f9da, 0x00054563,
+	0x00070eec, 0x00089876, 0x000a2704, 0x000bb08d,
+	0x000d3a17, 0x001185a0, 0x00134f29, 0x0014d8b3,
+	0x001667c8, 0x0017f151, 0x00197adb, 0x001b0664,
+	0x001c8fed, 0x001e5977, 0x0000e805, 0x0002718f,
+	0x00043b18, 0x000586a1, 0x0007502b, 0x0008d9b4,
+	0x000a68c9, 0x000bf252, 0x000dbbdc, 0x0011c7e5,
+	0x001390ee, 0x00151a78, 0x0016a906, 0x00183290,
+	0x0019bc19, 0x001b4822, 0x001cd12c, 0x001e9ab5,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_pilotlt_r3[] = {
+	0x76540213, 0x62407351, 0x76543210, 0x76540213,
+	0x76540213, 0x76430521,
+};
+
+static const u32 b43_ntab_channelest_r3[] = {
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+};
+
+static const u8 b43_ntab_framelookup_r3[] = {
+	0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16,
+	0x0a, 0x0c, 0x1c, 0x1c, 0x0b, 0x0d, 0x1e, 0x1e,
+	0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1a, 0x1a,
+	0x0e, 0x10, 0x20, 0x28, 0x0f, 0x11, 0x22, 0x2a,
+};
+
+static const u8 b43_ntab_estimatepowerlt0_r3[] = {
+	0x55, 0x54, 0x54, 0x53, 0x52, 0x52, 0x51, 0x51,
+	0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4c, 0x4c,
+	0x4b, 0x4a, 0x49, 0x49, 0x48, 0x47, 0x46, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x33, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b,
+	0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a,
+	0x18, 0x15, 0x12, 0x0e, 0x0b, 0x07, 0x02, 0xfd,
+};
+
+static const u8 b43_ntab_estimatepowerlt1_r3[] = {
+	0x55, 0x54, 0x54, 0x53, 0x52, 0x52, 0x51, 0x51,
+	0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4c, 0x4c,
+	0x4b, 0x4a, 0x49, 0x49, 0x48, 0x47, 0x46, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x33, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b,
+	0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a,
+	0x18, 0x15, 0x12, 0x0e, 0x0b, 0x07, 0x02, 0xfd,
+};
+
+static const u8 b43_ntab_adjustpower0_r3[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 b43_ntab_adjustpower1_r3[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u32 b43_ntab_gainctl0_r3[] = {
+	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_ntab_gainctl1_r3[] = {
+	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_ntab_iqlt0_r3[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_iqlt1_r3[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_ntab_loftlt0_r3[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_ntab_loftlt1_r3[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+/* TX gain tables */
 const u32 b43_ntab_tx_gain_rev0_1_2[] = {
 	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
 	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
@@ -1635,6 +2709,79 @@ const struct nphy_rf_control_override_rev3 tbl_rf_control_override_rev3[] = {
 	{ 0x00C0,  6, 0xE7, 0xF9, 0xEC, 0xFB }  /* field == 0x4000 (fls 15) */
 };
 
+struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][3] = {
+	{ /* 2GHz */
+		{ /* PHY rev 3 */
+			{ 7, 11, 16, 23 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x627E,
+			{ 0x613F, 0x613F, 0x613F, 0x613F },
+			0x107E, 0x0066, 0x0074,
+			0x18, 0x18, 0x18,
+			0x020D, 0x5,
+		},
+		{ /* PHY rev 4 */
+			{ 8, 12, 17, 25 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x527E,
+			{ 0x513F, 0x513F, 0x513F, 0x513F },
+			0x007E, 0x0066, 0x0074,
+			0x18, 0x18, 0x18,
+			0x01A1, 0x5,
+		},
+		{ /* PHY rev 5+ */
+			{ 9, 13, 18, 26 },
+			{ -3, 7, 11, 16 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x427E, /* invalid for external LNA! */
+			{ 0x413F, 0x413F, 0x413F, 0x413F }, /* invalid for external LNA! */
+			0x1076, 0x0066, 0x106A,
+			0xC, 0xC, 0xC,
+			0x01D0, 0x5,
+		},
+	},
+	{ /* 5GHz */
+		{ /* PHY rev 3 */
+			{ 7, 11, 17, 23 },
+			{ -6, 2, 6, 10 },
+			{ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
+			{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
+			0x52DE,
+			{ 0x516F, 0x516F, 0x516F, 0x516F },
+			0x00DE, 0x00CA, 0x00CC,
+			0x1E, 0x1E, 0x1E,
+			0x01A1, 25,
+		},
+		{ /* PHY rev 4 */
+			{ 8, 12, 18, 23 },
+			{ -5, 2, 6, 10 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x629E,
+			{ 0x614F, 0x614F, 0x614F, 0x614F },
+			0x029E, 0x1084, 0x0086,
+			0x24, 0x24, 0x24,
+			0x0107, 25,
+		},
+		{ /* PHY rev 5+ */
+			{ 6, 10, 16, 21 },
+			{ -7, 0, 4, 8 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x729E,
+			{ 0x714F, 0x714F, 0x714F, 0x714F },
+			0x029E, 0x2084, 0x2086,
+			0x24, 0x24, 0x24,
+			0x00A9, 25,
+		},
+	},
+};
+
 static inline void assert_ntab_array_sizes(void)
 {
 #undef check
@@ -1813,7 +2960,6 @@ void b43_ntab_write_bulk(struct b43_wldev *dev, u32 offset,
 #define ntab_upload(dev, offset, data) do { \
 		b43_ntab_write_bulk(dev, offset, offset##_SIZE, data);	\
 	} while (0)
-
 void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
 {
 	/* Static tables */
@@ -1847,11 +2993,70 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
 	ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
 }
 
+#define ntab_upload_r3(dev, offset, data) do { \
+		b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+	} while (0)
 void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
 {
 	/* Static tables */
-	/* TODO */
+	ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+	ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+	ntab_upload_r3(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
+	ntab_upload_r3(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+	ntab_upload_r3(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
+	ntab_upload_r3(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
+	ntab_upload_r3(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+	ntab_upload_r3(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+	ntab_upload_r3(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+	ntab_upload_r3(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_ESTPLT_R3,
+		       b43_ntab_estimatepowerlt0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_ESTPLT_R3,
+		       b43_ntab_estimatepowerlt1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
 
 	/* Volatile tables */
 	/* TODO */
 }
+
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+	struct b43_wldev *dev, bool ghz5, bool ext_lna)
+{
+	struct nphy_gain_ctl_workaround_entry *e;
+	u8 phy_idx;
+
+	B43_WARN_ON(dev->phy.rev < 3);
+	if (dev->phy.rev >= 5)
+		phy_idx = 2;
+	else if (dev->phy.rev == 4)
+		phy_idx = 1;
+	else
+		phy_idx = 0;
+
+	e = &nphy_gain_ctl_workaround[ghz5][phy_idx];
+
+	/* Only one entry differs for external LNA, so instead making whole
+	 * table 2 times bigger, hack is here
+	 */
+	if (!ghz5 && dev->phy.rev >= 5 && ext_lna) {
+		e->rfseq_init[0] &= 0x0FFF;
+		e->rfseq_init[1] &= 0x0FFF;
+		e->rfseq_init[2] &= 0x0FFF;
+		e->rfseq_init[3] &= 0x0FFF;
+		e->init_gain &= 0x0FFF;
+	}
+
+	return e;
+}
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
index 4ec593b..1856936 100644
--- a/drivers/net/wireless/b43/tables_nphy.h
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -35,6 +35,31 @@ struct nphy_rf_control_override_rev3 {
 	u8 val_addr1;
 };
 
+struct nphy_gain_ctl_workaround_entry {
+	s8 lna1_gain[4];
+	s8 lna2_gain[4];
+	u8 gain_db[10];
+	u8 gain_bits[10];
+
+	u16 init_gain;
+	u16 rfseq_init[4];
+
+	u16 cliphi_gain;
+	u16 clipmd_gain;
+	u16 cliplo_gain;
+
+	u16 crsmin;
+	u16 crsminl;
+	u16 crsminu;
+
+	u16 nbclip;
+	u16 wlclip;
+};
+
+/* Get entry with workaround values for gain ctl. Does not return NULL. */
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+	struct b43_wldev *dev, bool ghz5, bool ext_lna);
+
 /* Get the NPHY Channel Switch Table entry for a channel.
  * Returns NULL on failure to find an entry. */
 const struct b43_nphy_channeltab_entry_rev2 *
@@ -109,6 +134,33 @@ b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
 #define B43_NTAB_C1_LOFEEDTH		B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
 #define B43_NTAB_C1_LOFEEDTH_SIZE	128
 
+/* Static N-PHY tables, PHY revision >= 3 */
+#define B43_NTAB_FRAMESTRUCT_R3		B43_NTAB32(10, 000) /* frame struct  */
+#define B43_NTAB_PILOT_R3		B43_NTAB16(11, 000) /* pilot  */
+#define B43_NTAB_TMAP_R3		B43_NTAB32(12, 000) /* TM AP  */
+#define B43_NTAB_INTLEVEL_R3		B43_NTAB32(13, 000) /* INT LV  */
+#define B43_NTAB_TDTRN_R3		B43_NTAB32(14, 000) /* TD TRN  */
+#define B43_NTAB_NOISEVAR0_R3		B43_NTAB32(16, 000) /* noise variance 0  */
+#define B43_NTAB_NOISEVAR1_R3		B43_NTAB32(16, 128) /* noise variance 1  */
+#define B43_NTAB_MCS_R3			B43_NTAB16(18, 000) /* MCS  */
+#define B43_NTAB_TDI20A0_R3		B43_NTAB32(19, 128) /* TDI 20/0  */
+#define B43_NTAB_TDI20A1_R3		B43_NTAB32(19, 256) /* TDI 20/1  */
+#define B43_NTAB_TDI40A0_R3		B43_NTAB32(19, 640) /* TDI 40/0  */
+#define B43_NTAB_TDI40A1_R3		B43_NTAB32(19, 768) /* TDI 40/1  */
+#define B43_NTAB_PILOTLT_R3		B43_NTAB32(20, 000) /* PLT lookup  */
+#define B43_NTAB_CHANEST_R3		B43_NTAB32(22, 000) /* channel estimate  */
+#define B43_NTAB_FRAMELT_R3		B43_NTAB8 (24, 000) /* frame lookup  */
+#define B43_NTAB_C0_ESTPLT_R3		B43_NTAB8 (26, 000) /* estimated power lookup 0  */
+#define B43_NTAB_C1_ESTPLT_R3		B43_NTAB8 (27, 000) /* estimated power lookup 1  */
+#define B43_NTAB_C0_ADJPLT_R3		B43_NTAB8 (26, 064) /* adjusted power lookup 0  */
+#define B43_NTAB_C1_ADJPLT_R3		B43_NTAB8 (27, 064) /* adjusted power lookup 1  */
+#define B43_NTAB_C0_GAINCTL_R3		B43_NTAB32(26, 192) /* gain control lookup 0  */
+#define B43_NTAB_C1_GAINCTL_R3		B43_NTAB32(27, 192) /* gain control lookup 1  */
+#define B43_NTAB_C0_IQLT_R3		B43_NTAB32(26, 320) /* I/Q lookup 0  */
+#define B43_NTAB_C1_IQLT_R3		B43_NTAB32(27, 320) /* I/Q lookup 1  */
+#define B43_NTAB_C0_LOFEEDTH_R3		B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0  */
+#define B43_NTAB_C1_LOFEEDTH_R3		B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
+
 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE	18
 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE	18
 #define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE	18
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index e6b0528..e5be381 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -32,6 +32,36 @@
 #include "dma.h"
 #include "pio.h"
 
+static const struct b43_tx_legacy_rate_phy_ctl_entry b43_tx_legacy_rate_phy_ctl[] = {
+	{ B43_CCK_RATE_1MB,	0x0,			0x0 },
+	{ B43_CCK_RATE_2MB,	0x0,			0x1 },
+	{ B43_CCK_RATE_5MB,	0x0,			0x2 },
+	{ B43_CCK_RATE_11MB,	0x0,			0x3 },
+	{ B43_OFDM_RATE_6MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_BPSK },
+	{ B43_OFDM_RATE_9MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_BPSK },
+	{ B43_OFDM_RATE_12MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QPSK },
+	{ B43_OFDM_RATE_18MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QPSK },
+	{ B43_OFDM_RATE_24MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QAM16 },
+	{ B43_OFDM_RATE_36MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM16 },
+	{ B43_OFDM_RATE_48MB,	B43_TXH_PHY1_CRATE_2_3,	B43_TXH_PHY1_MODUL_QAM64 },
+	{ B43_OFDM_RATE_54MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM64 },
+};
+
+static const struct b43_tx_legacy_rate_phy_ctl_entry *
+b43_tx_legacy_rate_phy_ctl_ent(u8 bitrate)
+{
+	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) {
+		e = &(b43_tx_legacy_rate_phy_ctl[i]);
+		if (e->bitrate == bitrate)
+			return e;
+	}
+
+	B43_WARN_ON(1);
+	return NULL;
+}
 
 /* Extract the bitrate index out of a CCK PLCP header. */
 static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
@@ -145,6 +175,34 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
 	}
 }
 
+static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
+{
+	const struct b43_phy *phy = &dev->phy;
+	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
+	u16 control = 0;
+	u16 bw;
+
+	if (phy->type == B43_PHYTYPE_LP)
+		bw = B43_TXH_PHY1_BW_20;
+	else /* FIXME */
+		bw = B43_TXH_PHY1_BW_20;
+
+	if (0) { /* FIXME: MIMO */
+	} else if (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
+		control = bw;
+	} else {
+		control = bw;
+		e = b43_tx_legacy_rate_phy_ctl_ent(bitrate);
+		if (e) {
+			control |= e->coding_rate;
+			control |= e->modulation;
+		}
+		control |= B43_TXH_PHY1_MODE_SISO;
+	}
+
+	return control;
+}
+
 static u8 b43_calc_fallback_rate(u8 bitrate)
 {
 	switch (bitrate) {
@@ -437,6 +495,14 @@ int b43_generate_txhdr(struct b43_wldev *dev,
 			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
 		else
 			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
+
+		if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
+		    phy->type == B43_PHYTYPE_N) {
+			txhdr->phy_ctl1_rts = cpu_to_le16(
+				b43_generate_tx_phy_ctl1(dev, rts_rate));
+			txhdr->phy_ctl1_rts_fb = cpu_to_le16(
+				b43_generate_tx_phy_ctl1(dev, rts_rate_fb));
+		}
 	}
 
 	/* Magic cookie */
@@ -445,6 +511,13 @@ int b43_generate_txhdr(struct b43_wldev *dev,
 	else
 		txhdr->new_format.cookie = cpu_to_le16(cookie);
 
+	if (phy->type == B43_PHYTYPE_N) {
+		txhdr->phy_ctl1 =
+			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
+		txhdr->phy_ctl1_fb =
+			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb));
+	}
+
 	/* Apply the bitfields */
 	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
 	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
@@ -652,7 +725,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 		status.mactime += mactime;
 		if (low_mactime_now <= mactime)
 			status.mactime -= 0x10000;
-		status.flag |= RX_FLAG_TSFT;
+		status.flag |= RX_FLAG_MACTIME_MPDU;
 	}
 
 	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index d4cf9b3..42debb5 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -73,6 +73,12 @@ struct b43_txhdr {
 	} __packed;
 } __packed;
 
+struct b43_tx_legacy_rate_phy_ctl_entry {
+	u8 bitrate;
+	u16 coding_rate;
+	u16 modulation;
+};
+
 /* MAC TX control */
 #define B43_TXH_MAC_USEFBR		0x10000000 /* Use fallback rate for this AMPDU */
 #define B43_TXH_MAC_KEYIDX		0x0FF00000 /* Security key index */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1f11e16..c7fd73e 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -2442,8 +2442,8 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
 	return err;
 }
 
-static int b43legacy_op_tx(struct ieee80211_hw *hw,
-			   struct sk_buff *skb)
+static void b43legacy_op_tx(struct ieee80211_hw *hw,
+			    struct sk_buff *skb)
 {
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev = wl->current_dev;
@@ -2466,7 +2466,6 @@ out:
 		/* Drop the packet. */
 		dev_kfree_skb_any(skb);
 	}
-	return NETDEV_TX_OK;
 }
 
 static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 7d177d9..3a95541 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -572,7 +572,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
 		status.mactime += mactime;
 		if (low_mactime_now <= mactime)
 			status.mactime -= 0x10000;
-		status.flag |= RX_FLAG_TSFT;
+		status.flag |= RX_FLAG_MACTIME_MPDU;
 	}
 
 	chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h
index 30acd39..2c8f71f 100644
--- a/drivers/net/wireless/hostap/hostap_config.h
+++ b/drivers/net/wireless/hostap/hostap_config.h
@@ -30,9 +30,9 @@
 
 /* Following defines can be used to remove unneeded parts of the driver, e.g.,
  * to limit the size of the kernel module. Definitions can be added here in
- * hostap_config.h or they can be added to make command with EXTRA_CFLAGS,
+ * hostap_config.h or they can be added to make command with ccflags-y,
  * e.g.,
- * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
+ * 'make pccard ccflags-y="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
  */
 
 /* Do not include debug messages into the driver */
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 61915f3..4b97f91 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -706,11 +706,10 @@ static void schedule_reset(struct ipw2100_priv *priv)
 		netif_stop_queue(priv->net_dev);
 		priv->status |= STATUS_RESET_PENDING;
 		if (priv->reset_backoff)
-			queue_delayed_work(priv->workqueue, &priv->reset_work,
-					   priv->reset_backoff * HZ);
+			schedule_delayed_work(&priv->reset_work,
+					      priv->reset_backoff * HZ);
 		else
-			queue_delayed_work(priv->workqueue, &priv->reset_work,
-					   0);
+			schedule_delayed_work(&priv->reset_work, 0);
 
 		if (priv->reset_backoff < MAX_RESET_BACKOFF)
 			priv->reset_backoff++;
@@ -1397,7 +1396,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
 }
 
 /*
- * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it
+ * Send the CARD_DISABLE_PHY_OFF command to the card to disable it
  *
  * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent.
  *
@@ -1474,7 +1473,7 @@ static int ipw2100_enable_adapter(struct ipw2100_priv *priv)
 
 	if (priv->stop_hang_check) {
 		priv->stop_hang_check = 0;
-		queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+		schedule_delayed_work(&priv->hang_check, HZ / 2);
 	}
 
       fail_up:
@@ -1808,8 +1807,8 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
 
 		if (priv->stop_rf_kill) {
 			priv->stop_rf_kill = 0;
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(HZ));
 		}
 
 		deferred = 1;
@@ -2086,7 +2085,7 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
 	priv->status |= STATUS_ASSOCIATING;
 	priv->connect_start = get_seconds();
 
-	queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10);
+	schedule_delayed_work(&priv->wx_event_work, HZ / 10);
 }
 
 static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
@@ -2166,9 +2165,9 @@ static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
 		return;
 
 	if (priv->status & STATUS_SECURITY_UPDATED)
-		queue_delayed_work(priv->workqueue, &priv->security_work, 0);
+		schedule_delayed_work(&priv->security_work, 0);
 
-	queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0);
+	schedule_delayed_work(&priv->wx_event_work, 0);
 }
 
 static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
@@ -2183,8 +2182,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
 	/* Make sure the RF Kill check timer is running */
 	priv->stop_rf_kill = 0;
 	cancel_delayed_work(&priv->rf_kill);
-	queue_delayed_work(priv->workqueue, &priv->rf_kill,
-			   round_jiffies_relative(HZ));
+	schedule_delayed_work(&priv->rf_kill, round_jiffies_relative(HZ));
 }
 
 static void send_scan_event(void *data)
@@ -2219,13 +2217,12 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status)
 	/* Only userspace-requested scan completion events go out immediately */
 	if (!priv->user_requested_scan) {
 		if (!delayed_work_pending(&priv->scan_event_later))
-			queue_delayed_work(priv->workqueue,
-					&priv->scan_event_later,
-					round_jiffies_relative(msecs_to_jiffies(4000)));
+			schedule_delayed_work(&priv->scan_event_later,
+					      round_jiffies_relative(msecs_to_jiffies(4000)));
 	} else {
 		priv->user_requested_scan = 0;
 		cancel_delayed_work(&priv->scan_event_later);
-		queue_work(priv->workqueue, &priv->scan_event_now);
+		schedule_work(&priv->scan_event_now);
 	}
 }
 
@@ -4329,8 +4326,8 @@ static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio)
 			/* Make sure the RF_KILL check timer is running */
 			priv->stop_rf_kill = 0;
 			cancel_delayed_work(&priv->rf_kill);
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(HZ));
 		} else
 			schedule_reset(priv);
 	}
@@ -4461,20 +4458,17 @@ static void bd_queue_initialize(struct ipw2100_priv *priv,
 	IPW_DEBUG_INFO("exit\n");
 }
 
-static void ipw2100_kill_workqueue(struct ipw2100_priv *priv)
+static void ipw2100_kill_works(struct ipw2100_priv *priv)
 {
-	if (priv->workqueue) {
-		priv->stop_rf_kill = 1;
-		priv->stop_hang_check = 1;
-		cancel_delayed_work(&priv->reset_work);
-		cancel_delayed_work(&priv->security_work);
-		cancel_delayed_work(&priv->wx_event_work);
-		cancel_delayed_work(&priv->hang_check);
-		cancel_delayed_work(&priv->rf_kill);
-		cancel_delayed_work(&priv->scan_event_later);
-		destroy_workqueue(priv->workqueue);
-		priv->workqueue = NULL;
-	}
+	priv->stop_rf_kill = 1;
+	priv->stop_hang_check = 1;
+	cancel_delayed_work_sync(&priv->reset_work);
+	cancel_delayed_work_sync(&priv->security_work);
+	cancel_delayed_work_sync(&priv->wx_event_work);
+	cancel_delayed_work_sync(&priv->hang_check);
+	cancel_delayed_work_sync(&priv->rf_kill);
+	cancel_work_sync(&priv->scan_event_now);
+	cancel_delayed_work_sync(&priv->scan_event_later);
 }
 
 static int ipw2100_tx_allocate(struct ipw2100_priv *priv)
@@ -6046,7 +6040,7 @@ static void ipw2100_hang_check(struct work_struct *work)
 	priv->last_rtc = rtc;
 
 	if (!priv->stop_hang_check)
-		queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+		schedule_delayed_work(&priv->hang_check, HZ / 2);
 
 	spin_unlock_irqrestore(&priv->low_lock, flags);
 }
@@ -6062,8 +6056,8 @@ static void ipw2100_rf_kill(struct work_struct *work)
 	if (rf_kill_active(priv)) {
 		IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
 		if (!priv->stop_rf_kill)
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(HZ));
 		goto exit_unlock;
 	}
 
@@ -6209,8 +6203,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev,
 	INIT_LIST_HEAD(&priv->fw_pend_list);
 	INIT_STAT(&priv->fw_pend_stat);
 
-	priv->workqueue = create_workqueue(DRV_NAME);
-
 	INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter);
 	INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work);
 	INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work);
@@ -6410,7 +6402,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
 		if (dev->irq)
 			free_irq(dev->irq, priv);
 
-		ipw2100_kill_workqueue(priv);
+		ipw2100_kill_works(priv);
 
 		/* These are safe to call even if they weren't allocated */
 		ipw2100_queues_free(priv);
@@ -6460,9 +6452,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
 		 * first, then close() will crash. */
 		unregister_netdev(dev);
 
-		/* ipw2100_down will ensure that there is no more pending work
-		 * in the workqueue's, so we can safely remove them now. */
-		ipw2100_kill_workqueue(priv);
+		ipw2100_kill_works(priv);
 
 		ipw2100_queues_free(priv);
 
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h
index 838002b..99cba96 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.h
+++ b/drivers/net/wireless/ipw2x00/ipw2100.h
@@ -580,7 +580,6 @@ struct ipw2100_priv {
 
 	struct tasklet_struct irq_tasklet;
 
-	struct workqueue_struct *workqueue;
 	struct delayed_work reset_work;
 	struct delayed_work security_work;
 	struct delayed_work wx_event_work;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index ae438ed..160881f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -894,9 +894,8 @@ static void ipw_led_link_on(struct ipw_priv *priv)
 
 		/* If we aren't associated, schedule turning the LED off */
 		if (!(priv->status & STATUS_ASSOCIATED))
-			queue_delayed_work(priv->workqueue,
-					   &priv->led_link_off,
-					   LD_TIME_LINK_ON);
+			schedule_delayed_work(&priv->led_link_off,
+					      LD_TIME_LINK_ON);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -939,8 +938,8 @@ static void ipw_led_link_off(struct ipw_priv *priv)
 		 * turning the LED on (blink while unassociated) */
 		if (!(priv->status & STATUS_RF_KILL_MASK) &&
 		    !(priv->status & STATUS_ASSOCIATED))
-			queue_delayed_work(priv->workqueue, &priv->led_link_on,
-					   LD_TIME_LINK_OFF);
+			schedule_delayed_work(&priv->led_link_on,
+					      LD_TIME_LINK_OFF);
 
 	}
 
@@ -980,13 +979,11 @@ static void __ipw_led_activity_on(struct ipw_priv *priv)
 		priv->status |= STATUS_LED_ACT_ON;
 
 		cancel_delayed_work(&priv->led_act_off);
-		queue_delayed_work(priv->workqueue, &priv->led_act_off,
-				   LD_TIME_ACT_ON);
+		schedule_delayed_work(&priv->led_act_off, LD_TIME_ACT_ON);
 	} else {
 		/* Reschedule LED off for full time period */
 		cancel_delayed_work(&priv->led_act_off);
-		queue_delayed_work(priv->workqueue, &priv->led_act_off,
-				   LD_TIME_ACT_ON);
+		schedule_delayed_work(&priv->led_act_off, LD_TIME_ACT_ON);
 	}
 }
 
@@ -1795,13 +1792,11 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
 	if (disable_radio) {
 		priv->status |= STATUS_RF_KILL_SW;
 
-		if (priv->workqueue) {
-			cancel_delayed_work(&priv->request_scan);
-			cancel_delayed_work(&priv->request_direct_scan);
-			cancel_delayed_work(&priv->request_passive_scan);
-			cancel_delayed_work(&priv->scan_event);
-		}
-		queue_work(priv->workqueue, &priv->down);
+		cancel_delayed_work(&priv->request_scan);
+		cancel_delayed_work(&priv->request_direct_scan);
+		cancel_delayed_work(&priv->request_passive_scan);
+		cancel_delayed_work(&priv->scan_event);
+		schedule_work(&priv->down);
 	} else {
 		priv->status &= ~STATUS_RF_KILL_SW;
 		if (rf_kill_active(priv)) {
@@ -1809,10 +1804,10 @@ static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio)
 					  "disabled by HW switch\n");
 			/* Make sure the RF_KILL check timer is running */
 			cancel_delayed_work(&priv->rf_kill);
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(2 * HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(2 * HZ));
 		} else
-			queue_work(priv->workqueue, &priv->up);
+			schedule_work(&priv->up);
 	}
 
 	return 1;
@@ -2063,7 +2058,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
 		cancel_delayed_work(&priv->request_passive_scan);
 		cancel_delayed_work(&priv->scan_event);
 		schedule_work(&priv->link_down);
-		queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+		schedule_delayed_work(&priv->rf_kill, 2 * HZ);
 		handled |= IPW_INTA_BIT_RF_KILL_DONE;
 	}
 
@@ -2103,7 +2098,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
 		priv->status &= ~STATUS_HCMD_ACTIVE;
 		wake_up_interruptible(&priv->wait_command_queue);
 
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 		handled |= IPW_INTA_BIT_FATAL_ERROR;
 	}
 
@@ -2323,11 +2318,6 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
 	return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
 }
 
-/*
- * NOTE: This must be executed from our workqueue as it results in udelay
- * being called which may corrupt the keyboard if executed on default
- * workqueue
- */
 static void ipw_adapter_restart(void *adapter)
 {
 	struct ipw_priv *priv = adapter;
@@ -2368,13 +2358,13 @@ static void ipw_scan_check(void *data)
 		IPW_DEBUG_SCAN("Scan completion watchdog resetting "
 			       "adapter after (%dms).\n",
 			       jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 	} else if (priv->status & STATUS_SCANNING) {
 		IPW_DEBUG_SCAN("Scan completion watchdog aborting scan "
 			       "after (%dms).\n",
 			       jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
 		ipw_abort_scan(priv);
-		queue_delayed_work(priv->workqueue, &priv->scan_check, HZ);
+		schedule_delayed_work(&priv->scan_check, HZ);
 	}
 }
 
@@ -3943,7 +3933,7 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
 
 	if (priv->status & STATUS_ASSOCIATING) {
 		IPW_DEBUG_ASSOC("Disassociating while associating.\n");
-		queue_work(priv->workqueue, &priv->disassociate);
+		schedule_work(&priv->disassociate);
 		return;
 	}
 
@@ -4360,8 +4350,7 @@ static void ipw_gather_stats(struct ipw_priv *priv)
 
 	priv->quality = quality;
 
-	queue_delayed_work(priv->workqueue, &priv->gather_stats,
-			   IPW_STATS_INTERVAL);
+	schedule_delayed_work(&priv->gather_stats, IPW_STATS_INTERVAL);
 }
 
 static void ipw_bg_gather_stats(struct work_struct *work)
@@ -4396,10 +4385,10 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
 			IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
 				  IPW_DL_STATE,
 				  "Aborting scan with missed beacon.\n");
-			queue_work(priv->workqueue, &priv->abort_scan);
+			schedule_work(&priv->abort_scan);
 		}
 
-		queue_work(priv->workqueue, &priv->disassociate);
+		schedule_work(&priv->disassociate);
 		return;
 	}
 
@@ -4425,8 +4414,7 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
 		if (!(priv->status & STATUS_ROAMING)) {
 			priv->status |= STATUS_ROAMING;
 			if (!(priv->status & STATUS_SCANNING))
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 		}
 		return;
 	}
@@ -4439,7 +4427,7 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
 		 * channels..) */
 		IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | IPW_DL_STATE,
 			  "Aborting scan with missed beacon.\n");
-		queue_work(priv->workqueue, &priv->abort_scan);
+		schedule_work(&priv->abort_scan);
 	}
 
 	IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count);
@@ -4462,8 +4450,8 @@ static void handle_scan_event(struct ipw_priv *priv)
 	/* Only userspace-requested scan completion events go out immediately */
 	if (!priv->user_requested_scan) {
 		if (!delayed_work_pending(&priv->scan_event))
-			queue_delayed_work(priv->workqueue, &priv->scan_event,
-					 round_jiffies_relative(msecs_to_jiffies(4000)));
+			schedule_delayed_work(&priv->scan_event,
+					      round_jiffies_relative(msecs_to_jiffies(4000)));
 	} else {
 		union iwreq_data wrqu;
 
@@ -4516,20 +4504,17 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 
 						IPW_DEBUG_ASSOC
 						    ("queueing adhoc check\n");
-						queue_delayed_work(priv->
-								   workqueue,
-								   &priv->
-								   adhoc_check,
-								   le16_to_cpu(priv->
-								   assoc_request.
-								   beacon_interval));
+						schedule_delayed_work(
+							&priv->adhoc_check,
+							le16_to_cpu(priv->
+							assoc_request.
+							beacon_interval));
 						break;
 					}
 
 					priv->status &= ~STATUS_ASSOCIATING;
 					priv->status |= STATUS_ASSOCIATED;
-					queue_work(priv->workqueue,
-						   &priv->system_config);
+					schedule_work(&priv->system_config);
 
 #ifdef CONFIG_IPW2200_QOS
 #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
@@ -4792,43 +4777,37 @@ static void ipw_rx_notification(struct ipw_priv *priv,
 #ifdef CONFIG_IPW2200_MONITOR
 			if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
 				priv->status |= STATUS_SCAN_FORCED;
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 				break;
 			}
 			priv->status &= ~STATUS_SCAN_FORCED;
 #endif				/* CONFIG_IPW2200_MONITOR */
 
 			/* Do queued direct scans first */
-			if (priv->status & STATUS_DIRECT_SCAN_PENDING) {
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_direct_scan, 0);
-			}
+			if (priv->status & STATUS_DIRECT_SCAN_PENDING)
+				schedule_delayed_work(&priv->request_direct_scan, 0);
 
 			if (!(priv->status & (STATUS_ASSOCIATED |
 					      STATUS_ASSOCIATING |
 					      STATUS_ROAMING |
 					      STATUS_DISASSOCIATING)))
-				queue_work(priv->workqueue, &priv->associate);
+				schedule_work(&priv->associate);
 			else if (priv->status & STATUS_ROAMING) {
 				if (x->status == SCAN_COMPLETED_STATUS_COMPLETE)
 					/* If a scan completed and we are in roam mode, then
 					 * the scan that completed was the one requested as a
 					 * result of entering roam... so, schedule the
 					 * roam work */
-					queue_work(priv->workqueue,
-						   &priv->roam);
+					schedule_work(&priv->roam);
 				else
 					/* Don't schedule if we aborted the scan */
 					priv->status &= ~STATUS_ROAMING;
 			} else if (priv->status & STATUS_SCAN_PENDING)
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 			else if (priv->config & CFG_BACKGROUND_SCAN
 				 && priv->status & STATUS_ASSOCIATED)
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan,
-						   round_jiffies_relative(HZ));
+				schedule_delayed_work(&priv->request_scan,
+						      round_jiffies_relative(HZ));
 
 			/* Send an empty event to user space.
 			 * We don't send the received data on the event because
@@ -5192,7 +5171,7 @@ static void ipw_rx_queue_restock(struct ipw_priv *priv)
 	/* If the pre-allocated buffer pool is dropping low, schedule to
 	 * refill it */
 	if (rxq->free_count <= RX_LOW_WATERMARK)
-		queue_work(priv->workqueue, &priv->rx_replenish);
+		schedule_work(&priv->rx_replenish);
 
 	/* If we've added more space for the firmware to place data, tell it */
 	if (write != rxq->write)
@@ -6133,8 +6112,8 @@ static void ipw_adhoc_check(void *data)
 		return;
 	}
 
-	queue_delayed_work(priv->workqueue, &priv->adhoc_check,
-			   le16_to_cpu(priv->assoc_request.beacon_interval));
+	schedule_delayed_work(&priv->adhoc_check,
+			      le16_to_cpu(priv->assoc_request.beacon_interval));
 }
 
 static void ipw_bg_adhoc_check(struct work_struct *work)
@@ -6523,8 +6502,7 @@ send_request:
 	} else
 		priv->status &= ~STATUS_SCAN_PENDING;
 
-	queue_delayed_work(priv->workqueue, &priv->scan_check,
-			   IPW_SCAN_CHECK_WATCHDOG);
+	schedule_delayed_work(&priv->scan_check, IPW_SCAN_CHECK_WATCHDOG);
 done:
 	mutex_unlock(&priv->mutex);
 	return err;
@@ -6994,8 +6972,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv,
 				    !memcmp(network->ssid,
 					    priv->assoc_network->ssid,
 					    network->ssid_len)) {
-					queue_work(priv->workqueue,
-						   &priv->merge_networks);
+					schedule_work(&priv->merge_networks);
 				}
 	}
 
@@ -7663,7 +7640,7 @@ static int ipw_associate(void *data)
 	if (priv->status & STATUS_DISASSOCIATING) {
 		IPW_DEBUG_ASSOC("Not attempting association (in "
 				"disassociating)\n ");
-		queue_work(priv->workqueue, &priv->associate);
+		schedule_work(&priv->associate);
 		return 0;
 	}
 
@@ -7731,12 +7708,10 @@ static int ipw_associate(void *data)
 
 		if (!(priv->status & STATUS_SCANNING)) {
 			if (!(priv->config & CFG_SPEED_SCAN))
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan,
-						   SCAN_INTERVAL);
+				schedule_delayed_work(&priv->request_scan,
+						      SCAN_INTERVAL);
 			else
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 		}
 
 		return 0;
@@ -8899,7 +8874,7 @@ static int ipw_wx_set_mode(struct net_device *dev,
 
 	priv->ieee->iw_mode = wrqu->mode;
 
-	queue_work(priv->workqueue, &priv->adapter_restart);
+	schedule_work(&priv->adapter_restart);
 	mutex_unlock(&priv->mutex);
 	return err;
 }
@@ -9598,7 +9573,7 @@ static int ipw_wx_set_scan(struct net_device *dev,
 
 	IPW_DEBUG_WX("Start scan\n");
 
-	queue_delayed_work(priv->workqueue, work, 0);
+	schedule_delayed_work(work, 0);
 
 	return 0;
 }
@@ -9937,7 +9912,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
 #else
 			priv->net_dev->type = ARPHRD_IEEE80211;
 #endif
-			queue_work(priv->workqueue, &priv->adapter_restart);
+			schedule_work(&priv->adapter_restart);
 		}
 
 		ipw_set_channel(priv, parms[1]);
@@ -9947,7 +9922,7 @@ static int ipw_wx_set_monitor(struct net_device *dev,
 			return 0;
 		}
 		priv->net_dev->type = ARPHRD_ETHER;
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 	}
 	mutex_unlock(&priv->mutex);
 	return 0;
@@ -9961,7 +9936,7 @@ static int ipw_wx_reset(struct net_device *dev,
 {
 	struct ipw_priv *priv = libipw_priv(dev);
 	IPW_DEBUG_WX("RESET\n");
-	queue_work(priv->workqueue, &priv->adapter_restart);
+	schedule_work(&priv->adapter_restart);
 	return 0;
 }
 
@@ -10551,7 +10526,7 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
 	memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
 	printk(KERN_INFO "%s: Setting MAC to %pM\n",
 	       priv->net_dev->name, priv->mac_addr);
-	queue_work(priv->workqueue, &priv->adapter_restart);
+	schedule_work(&priv->adapter_restart);
 	mutex_unlock(&priv->mutex);
 	return 0;
 }
@@ -10684,9 +10659,7 @@ static void ipw_rf_kill(void *adapter)
 
 	if (rf_kill_active(priv)) {
 		IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
-		if (priv->workqueue)
-			queue_delayed_work(priv->workqueue,
-					   &priv->rf_kill, 2 * HZ);
+		schedule_delayed_work(&priv->rf_kill, 2 * HZ);
 		goto exit_unlock;
 	}
 
@@ -10697,7 +10670,7 @@ static void ipw_rf_kill(void *adapter)
 				  "device\n");
 
 		/* we can not do an adapter restart while inside an irq lock */
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 	} else
 		IPW_DEBUG_RF_KILL("HW RF Kill deactivated.  SW RF Kill still "
 				  "enabled\n");
@@ -10735,7 +10708,7 @@ static void ipw_link_up(struct ipw_priv *priv)
 	notify_wx_assoc_event(priv);
 
 	if (priv->config & CFG_BACKGROUND_SCAN)
-		queue_delayed_work(priv->workqueue, &priv->request_scan, HZ);
+		schedule_delayed_work(&priv->request_scan, HZ);
 }
 
 static void ipw_bg_link_up(struct work_struct *work)
@@ -10764,7 +10737,7 @@ static void ipw_link_down(struct ipw_priv *priv)
 
 	if (!(priv->status & STATUS_EXIT_PENDING)) {
 		/* Queue up another scan... */
-		queue_delayed_work(priv->workqueue, &priv->request_scan, 0);
+		schedule_delayed_work(&priv->request_scan, 0);
 	} else
 		cancel_delayed_work(&priv->scan_event);
 }
@@ -10782,7 +10755,6 @@ static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv)
 {
 	int ret = 0;
 
-	priv->workqueue = create_workqueue(DRV_NAME);
 	init_waitqueue_head(&priv->wait_command_queue);
 	init_waitqueue_head(&priv->wait_state);
 
@@ -11339,8 +11311,7 @@ static int ipw_up(struct ipw_priv *priv)
 			IPW_WARNING("Radio Frequency Kill Switch is On:\n"
 				    "Kill switch must be turned off for "
 				    "wireless networking to work.\n");
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   2 * HZ);
+			schedule_delayed_work(&priv->rf_kill, 2 * HZ);
 			return 0;
 		}
 
@@ -11350,8 +11321,7 @@ static int ipw_up(struct ipw_priv *priv)
 
 			/* If configure to try and auto-associate, kick
 			 * off a scan. */
-			queue_delayed_work(priv->workqueue,
-					   &priv->request_scan, 0);
+			schedule_delayed_work(&priv->request_scan, 0);
 
 			return 0;
 		}
@@ -11817,7 +11787,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
 	err = request_irq(pdev->irq, ipw_isr, IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 		IPW_ERROR("Error allocating IRQ %d\n", pdev->irq);
-		goto out_destroy_workqueue;
+		goto out_iounmap;
 	}
 
 	SET_NETDEV_DEV(net_dev, &pdev->dev);
@@ -11885,9 +11855,6 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
 	sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
       out_release_irq:
 	free_irq(pdev->irq, priv);
-      out_destroy_workqueue:
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
       out_iounmap:
 	iounmap(priv->hw_base);
       out_pci_release_regions:
@@ -11930,18 +11897,31 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
 		kfree(priv->cmdlog);
 		priv->cmdlog = NULL;
 	}
-	/* ipw_down will ensure that there is no more pending work
-	 * in the workqueue's, so we can safely remove them now. */
-	cancel_delayed_work(&priv->adhoc_check);
-	cancel_delayed_work(&priv->gather_stats);
-	cancel_delayed_work(&priv->request_scan);
-	cancel_delayed_work(&priv->request_direct_scan);
-	cancel_delayed_work(&priv->request_passive_scan);
-	cancel_delayed_work(&priv->scan_event);
-	cancel_delayed_work(&priv->rf_kill);
-	cancel_delayed_work(&priv->scan_check);
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
+
+	/* make sure all works are inactive */
+	cancel_delayed_work_sync(&priv->adhoc_check);
+	cancel_work_sync(&priv->associate);
+	cancel_work_sync(&priv->disassociate);
+	cancel_work_sync(&priv->system_config);
+	cancel_work_sync(&priv->rx_replenish);
+	cancel_work_sync(&priv->adapter_restart);
+	cancel_delayed_work_sync(&priv->rf_kill);
+	cancel_work_sync(&priv->up);
+	cancel_work_sync(&priv->down);
+	cancel_delayed_work_sync(&priv->request_scan);
+	cancel_delayed_work_sync(&priv->request_direct_scan);
+	cancel_delayed_work_sync(&priv->request_passive_scan);
+	cancel_delayed_work_sync(&priv->scan_event);
+	cancel_delayed_work_sync(&priv->gather_stats);
+	cancel_work_sync(&priv->abort_scan);
+	cancel_work_sync(&priv->roam);
+	cancel_delayed_work_sync(&priv->scan_check);
+	cancel_work_sync(&priv->link_up);
+	cancel_work_sync(&priv->link_down);
+	cancel_delayed_work_sync(&priv->led_link_on);
+	cancel_delayed_work_sync(&priv->led_link_off);
+	cancel_delayed_work_sync(&priv->led_act_off);
+	cancel_work_sync(&priv->merge_networks);
 
 	/* Free MAC hash list for ADHOC */
 	for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) {
@@ -12029,7 +12009,7 @@ static int ipw_pci_resume(struct pci_dev *pdev)
 	priv->suspend_time = get_seconds() - priv->suspend_at;
 
 	/* Bring the device back up */
-	queue_work(priv->workqueue, &priv->up);
+	schedule_work(&priv->up);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index d7d049c..91795b5 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -961,7 +961,7 @@ struct ipw_country_channel_info {
 struct ipw_country_info {
 	u8 id;
 	u8 length;
-	u8 country_str[3];
+	u8 country_str[IEEE80211_COUNTRY_STRING_LEN];
 	struct ipw_country_channel_info groups[7];
 } __packed;
 
@@ -1299,8 +1299,6 @@ struct ipw_priv {
 	u8 direct_scan_ssid[IW_ESSID_MAX_SIZE];
 	u8 direct_scan_ssid_len;
 
-	struct workqueue_struct *workqueue;
-
 	struct delayed_work adhoc_check;
 	struct work_struct associate;
 	struct work_struct disassociate;
diff --git a/drivers/net/wireless/iwlegacy/Kconfig b/drivers/net/wireless/iwlegacy/Kconfig
new file mode 100644
index 0000000..2a45dd4
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/Kconfig
@@ -0,0 +1,116 @@
+config IWLWIFI_LEGACY
+	tristate "Intel Wireless Wifi legacy devices"
+	depends on PCI && MAC80211
+	select FW_LOADER
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_TRIGGERS
+	select MAC80211_LEDS
+
+menu "Debugging Options"
+	depends on IWLWIFI_LEGACY
+
+config IWLWIFI_LEGACY_DEBUG
+	bool "Enable full debugging output in 4965 and 3945 drivers"
+	depends on IWLWIFI_LEGACY
+	---help---
+	  This option will enable debug tracing output for the iwlwifilegacy
+	  drivers.
+
+	  This will result in the kernel module being ~100k larger.  You can
+	  control which debug output is sent to the kernel log by setting the
+	  value in
+
+		/sys/class/net/wlan0/device/debug_level
+
+	  This entry will only exist if this option is enabled.
+
+	  To set a value, simply echo an 8-byte hex value to the same file:
+
+		  % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
+
+	  You can find the list of debug mask values in:
+		  drivers/net/wireless/iwlwifilegacy/iwl-debug.h
+
+	  If this is your first time using this driver, you should say Y here
+	  as the debug information can assist others in helping you resolve
+	  any problems you may encounter.
+
+config IWLWIFI_LEGACY_DEBUGFS
+        bool "4965 and 3945 debugfs support"
+        depends on IWLWIFI_LEGACY && MAC80211_DEBUGFS
+        ---help---
+	  Enable creation of debugfs files for the iwlwifilegacy drivers. This
+	  is a low-impact option that allows getting insight into the
+	  driver's state at runtime.
+
+config IWLWIFI_LEGACY_DEVICE_TRACING
+	bool "iwlwifilegacy legacy device access tracing"
+	depends on IWLWIFI_LEGACY
+	depends on EVENT_TRACING
+	help
+	  Say Y here to trace all commands, including TX frames and IO
+	  accesses, sent to the device. If you say yes, iwlwifilegacy will
+	  register with the ftrace framework for event tracing and dump
+	  all this information to the ringbuffer, you may need to
+	  increase the ringbuffer size. See the ftrace documentation
+	  for more information.
+
+	  When tracing is not enabled, this option still has some
+	  (though rather small) overhead.
+
+	  If unsure, say Y so we can help you better when problems
+	  occur.
+endmenu
+
+config IWL4965
+	tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
+	depends on IWLWIFI_LEGACY
+	---help---
+	  This option enables support for
+
+	  Select to build the driver supporting the:
+
+	  Intel Wireless WiFi Link 4965AGN
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  In order to use this driver, you will need a microcode (uCode)
+	  image for it. You can obtain the microcode from:
+
+	          <http://intellinuxwireless.org/>.
+
+	  The microcode is typically installed in /lib/firmware. You can
+	  look in the hotplug script /etc/hotplug/firmware.agent to
+	  determine which directory FIRMWARE_DIR is set to when the script
+	  runs.
+
+	  If you want to compile the driver as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+	  module will be called iwl4965.
+
+config IWL3945
+	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
+	depends on IWLWIFI_LEGACY
+	---help---
+	  Select to build the driver supporting the:
+
+	  Intel PRO/Wireless 3945ABG/BG Network Connection
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  In order to use this driver, you will need a microcode (uCode)
+	  image for it. You can obtain the microcode from:
+
+	          <http://intellinuxwireless.org/>.
+
+	  The microcode is typically installed in /lib/firmware. You can
+	  look in the hotplug script /etc/hotplug/firmware.agent to
+	  determine which directory FIRMWARE_DIR is set to when the script
+	  runs.
+
+	  If you want to compile the driver as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+	  module will be called iwl3945.
diff --git a/drivers/net/wireless/iwlegacy/Makefile b/drivers/net/wireless/iwlegacy/Makefile
new file mode 100644
index 0000000..d56aeb3
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/Makefile
@@ -0,0 +1,25 @@
+obj-$(CONFIG_IWLWIFI_LEGACY)	+= iwl-legacy.o
+iwl-legacy-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
+iwl-legacy-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
+iwl-legacy-objs 		+= iwl-scan.o iwl-led.o
+iwl-legacy-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-debugfs.o
+iwl-legacy-$(CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING) += iwl-devtrace.o
+
+iwl-legacy-objs += $(iwl-legacy-m)
+
+CFLAGS_iwl-devtrace.o := -I$(src)
+
+# 4965
+obj-$(CONFIG_IWL4965)	+= iwl4965.o
+iwl4965-objs		:= iwl-4965.o iwl4965-base.o iwl-4965-rs.o iwl-4965-led.o
+iwl4965-objs		+= iwl-4965-ucode.o iwl-4965-tx.o
+iwl4965-objs		+= iwl-4965-lib.o iwl-4965-rx.o iwl-4965-calib.o
+iwl4965-objs		+= iwl-4965-sta.o iwl-4965-eeprom.o
+iwl4965-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-4965-debugfs.o
+
+# 3945
+obj-$(CONFIG_IWL3945)	+= iwl3945.o
+iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
+iwl3945-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-3945-debugfs.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c
new file mode 100644
index 0000000..cfabb38
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c
@@ -0,0 +1,523 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "iwl-3945-debugfs.h"
+
+
+static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
+{
+	int p = 0;
+
+	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
+		       le32_to_cpu(priv->_3945.statistics.flag));
+	if (le32_to_cpu(priv->_3945.statistics.flag) &
+			UCODE_STATISTICS_CLEAR_MSK)
+		p += scnprintf(buf + p, bufsz - p,
+			       "\tStatistics have been cleared\n");
+	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
+		       (le32_to_cpu(priv->_3945.statistics.flag) &
+			UCODE_STATISTICS_FREQUENCY_MSK)
+			? "2.4 GHz" : "5.2 GHz");
+	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
+		       (le32_to_cpu(priv->_3945.statistics.flag) &
+			UCODE_STATISTICS_NARROW_BAND_MSK)
+			? "enabled" : "disabled");
+	return p;
+}
+
+ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
+				    char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
+		    sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
+	ssize_t ret;
+	struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm,
+					*max_ofdm;
+	struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+	struct iwl39_statistics_rx_non_phy *general, *accum_general;
+	struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	ofdm = &priv->_3945.statistics.rx.ofdm;
+	cck = &priv->_3945.statistics.rx.cck;
+	general = &priv->_3945.statistics.rx.general;
+	accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_3945.accum_statistics.rx.cck;
+	accum_general = &priv->_3945.accum_statistics.rx.general;
+	delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_3945.delta_statistics.rx.cck;
+	delta_general = &priv->_3945.delta_statistics.rx.general;
+	max_ofdm = &priv->_3945.max_delta.rx.ofdm;
+	max_cck = &priv->_3945.max_delta.rx.cck;
+	max_general = &priv->_3945.max_delta.rx.general;
+
+	pos += iwl3945_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - OFDM:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
+			 accum_ofdm->ina_cnt,
+			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_cnt:",
+			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
+			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:",
+			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
+			 le32_to_cpu(ofdm->overrun_err),
+			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
+			 max_ofdm->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "early_overrun_err:",
+			 le32_to_cpu(ofdm->early_overrun_err),
+			 accum_ofdm->early_overrun_err,
+			 delta_ofdm->early_overrun_err,
+			 max_ofdm->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_good:", le32_to_cpu(ofdm->crc32_good),
+			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
+			 max_ofdm->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
+			 le32_to_cpu(ofdm->false_alarm_cnt),
+			 accum_ofdm->false_alarm_cnt,
+			 delta_ofdm->false_alarm_cnt,
+			 max_ofdm->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_sync_err_cnt:",
+			 le32_to_cpu(ofdm->fina_sync_err_cnt),
+			 accum_ofdm->fina_sync_err_cnt,
+			 delta_ofdm->fina_sync_err_cnt,
+			 max_ofdm->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sfd_timeout:",
+			 le32_to_cpu(ofdm->sfd_timeout),
+			 accum_ofdm->sfd_timeout,
+			 delta_ofdm->sfd_timeout,
+			 max_ofdm->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_timeout:",
+			 le32_to_cpu(ofdm->fina_timeout),
+			 accum_ofdm->fina_timeout,
+			 delta_ofdm->fina_timeout,
+			 max_ofdm->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "unresponded_rts:",
+			 le32_to_cpu(ofdm->unresponded_rts),
+			 accum_ofdm->unresponded_rts,
+			 delta_ofdm->unresponded_rts,
+			 max_ofdm->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+			 accum_ofdm->rxe_frame_limit_overrun,
+			 delta_ofdm->rxe_frame_limit_overrun,
+			 max_ofdm->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_ack_cnt:",
+			 le32_to_cpu(ofdm->sent_ack_cnt),
+			 accum_ofdm->sent_ack_cnt,
+			 delta_ofdm->sent_ack_cnt,
+			 max_ofdm->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_cts_cnt:",
+			 le32_to_cpu(ofdm->sent_cts_cnt),
+			 accum_ofdm->sent_cts_cnt,
+			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - CCK:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ina_cnt:",
+			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+			 delta_cck->ina_cnt, max_cck->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_cnt:",
+			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+			 delta_cck->fina_cnt, max_cck->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "plcp_err:",
+			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+			 delta_cck->plcp_err, max_cck->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_err:",
+			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+			 delta_cck->crc32_err, max_cck->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "overrun_err:",
+			 le32_to_cpu(cck->overrun_err),
+			 accum_cck->overrun_err,
+			 delta_cck->overrun_err, max_cck->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "early_overrun_err:",
+			 le32_to_cpu(cck->early_overrun_err),
+			 accum_cck->early_overrun_err,
+			 delta_cck->early_overrun_err,
+			 max_cck->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_good:",
+			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+			 delta_cck->crc32_good,
+			 max_cck->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "false_alarm_cnt:",
+			 le32_to_cpu(cck->false_alarm_cnt),
+			 accum_cck->false_alarm_cnt,
+			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_sync_err_cnt:",
+			 le32_to_cpu(cck->fina_sync_err_cnt),
+			 accum_cck->fina_sync_err_cnt,
+			 delta_cck->fina_sync_err_cnt,
+			 max_cck->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sfd_timeout:",
+			 le32_to_cpu(cck->sfd_timeout),
+			 accum_cck->sfd_timeout,
+			 delta_cck->sfd_timeout, max_cck->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_timeout:",
+			 le32_to_cpu(cck->fina_timeout),
+			 accum_cck->fina_timeout,
+			 delta_cck->fina_timeout, max_cck->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "unresponded_rts:",
+			 le32_to_cpu(cck->unresponded_rts),
+			 accum_cck->unresponded_rts,
+			 delta_cck->unresponded_rts,
+			 max_cck->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(cck->rxe_frame_limit_overrun),
+			 accum_cck->rxe_frame_limit_overrun,
+			 delta_cck->rxe_frame_limit_overrun,
+			 max_cck->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_ack_cnt:",
+			 le32_to_cpu(cck->sent_ack_cnt),
+			 accum_cck->sent_ack_cnt,
+			 delta_cck->sent_ack_cnt,
+			 max_cck->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_cts_cnt:",
+			 le32_to_cpu(cck->sent_cts_cnt),
+			 accum_cck->sent_cts_cnt,
+			 delta_cck->sent_cts_cnt,
+			 max_cck->sent_cts_cnt);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - GENERAL:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bogus_cts:",
+			 le32_to_cpu(general->bogus_cts),
+			 accum_general->bogus_cts,
+			 delta_general->bogus_cts, max_general->bogus_cts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bogus_ack:",
+			 le32_to_cpu(general->bogus_ack),
+			 accum_general->bogus_ack,
+			 delta_general->bogus_ack, max_general->bogus_ack);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "non_bssid_frames:",
+			 le32_to_cpu(general->non_bssid_frames),
+			 accum_general->non_bssid_frames,
+			 delta_general->non_bssid_frames,
+			 max_general->non_bssid_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "filtered_frames:",
+			 le32_to_cpu(general->filtered_frames),
+			 accum_general->filtered_frames,
+			 delta_general->filtered_frames,
+			 max_general->filtered_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "non_channel_beacons:",
+			 le32_to_cpu(general->non_channel_beacons),
+			 accum_general->non_channel_beacons,
+			 delta_general->non_channel_beacons,
+			 max_general->non_channel_beacons);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
+				    char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
+	ssize_t ret;
+	struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	tx = &priv->_3945.statistics.tx;
+	accum_tx = &priv->_3945.accum_statistics.tx;
+	delta_tx = &priv->_3945.delta_statistics.tx;
+	max_tx = &priv->_3945.max_delta.tx;
+	pos += iwl3945_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Tx:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "preamble:",
+			 le32_to_cpu(tx->preamble_cnt),
+			 accum_tx->preamble_cnt,
+			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rx_detected_cnt:",
+			 le32_to_cpu(tx->rx_detected_cnt),
+			 accum_tx->rx_detected_cnt,
+			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bt_prio_defer_cnt:",
+			 le32_to_cpu(tx->bt_prio_defer_cnt),
+			 accum_tx->bt_prio_defer_cnt,
+			 delta_tx->bt_prio_defer_cnt,
+			 max_tx->bt_prio_defer_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bt_prio_kill_cnt:",
+			 le32_to_cpu(tx->bt_prio_kill_cnt),
+			 accum_tx->bt_prio_kill_cnt,
+			 delta_tx->bt_prio_kill_cnt,
+			 max_tx->bt_prio_kill_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "few_bytes_cnt:",
+			 le32_to_cpu(tx->few_bytes_cnt),
+			 accum_tx->few_bytes_cnt,
+			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "cts_timeout:",
+			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+			 delta_tx->cts_timeout, max_tx->cts_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ack_timeout:",
+			 le32_to_cpu(tx->ack_timeout),
+			 accum_tx->ack_timeout,
+			 delta_tx->ack_timeout, max_tx->ack_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "expected_ack_cnt:",
+			 le32_to_cpu(tx->expected_ack_cnt),
+			 accum_tx->expected_ack_cnt,
+			 delta_tx->expected_ack_cnt,
+			 max_tx->expected_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "actual_ack_cnt:",
+			 le32_to_cpu(tx->actual_ack_cnt),
+			 accum_tx->actual_ack_cnt,
+			 delta_tx->actual_ack_cnt,
+			 max_tx->actual_ack_cnt);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
+	ssize_t ret;
+	struct iwl39_statistics_general *general, *accum_general;
+	struct iwl39_statistics_general *delta_general, *max_general;
+	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+	struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	general = &priv->_3945.statistics.general;
+	dbg = &priv->_3945.statistics.general.dbg;
+	div = &priv->_3945.statistics.general.div;
+	accum_general = &priv->_3945.accum_statistics.general;
+	delta_general = &priv->_3945.delta_statistics.general;
+	max_general = &priv->_3945.max_delta.general;
+	accum_dbg = &priv->_3945.accum_statistics.general.dbg;
+	delta_dbg = &priv->_3945.delta_statistics.general.dbg;
+	max_dbg = &priv->_3945.max_delta.general.dbg;
+	accum_div = &priv->_3945.accum_statistics.general.div;
+	delta_div = &priv->_3945.delta_statistics.general.div;
+	max_div = &priv->_3945.max_delta.general.div;
+	pos += iwl3945_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_General:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "burst_check:",
+			 le32_to_cpu(dbg->burst_check),
+			 accum_dbg->burst_check,
+			 delta_dbg->burst_check, max_dbg->burst_check);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "burst_count:",
+			 le32_to_cpu(dbg->burst_count),
+			 accum_dbg->burst_count,
+			 delta_dbg->burst_count, max_dbg->burst_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sleep_time:",
+			 le32_to_cpu(general->sleep_time),
+			 accum_general->sleep_time,
+			 delta_general->sleep_time, max_general->sleep_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "slots_out:",
+			 le32_to_cpu(general->slots_out),
+			 accum_general->slots_out,
+			 delta_general->slots_out, max_general->slots_out);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "slots_idle:",
+			 le32_to_cpu(general->slots_idle),
+			 accum_general->slots_idle,
+			 delta_general->slots_idle, max_general->slots_idle);
+	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
+			 le32_to_cpu(general->ttl_timestamp));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "tx_on_a:",
+			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+			 delta_div->tx_on_a, max_div->tx_on_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "tx_on_b:",
+			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+			 delta_div->tx_on_b, max_div->tx_on_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "exec_time:",
+			 le32_to_cpu(div->exec_time), accum_div->exec_time,
+			 delta_div->exec_time, max_div->exec_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "probe_time:",
+			 le32_to_cpu(div->probe_time), accum_div->probe_time,
+			 delta_div->probe_time, max_div->probe_time);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h b/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h
new file mode 100644
index 0000000..8fef4b3
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos);
+ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos);
+ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+					 char __user *user_buf, size_t count,
+					 loff_t *ppos);
+#else
+static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos)
+{
+	return 0;
+}
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-fh.h b/drivers/net/wireless/iwlegacy/iwl-3945-fh.h
new file mode 100644
index 0000000..836c991
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-fh.h
@@ -0,0 +1,187 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_3945_fh_h__
+#define __iwl_3945_fh_h__
+
+/************************************/
+/* iwl3945 Flow Handler Definitions */
+/************************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH39_MEM_LOWER_BOUND                   (0x0800)
+#define FH39_MEM_UPPER_BOUND                   (0x1000)
+
+#define FH39_CBCC_TABLE		(FH39_MEM_LOWER_BOUND + 0x140)
+#define FH39_TFDB_TABLE		(FH39_MEM_LOWER_BOUND + 0x180)
+#define FH39_RCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x400)
+#define FH39_RSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x4c0)
+#define FH39_TCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x500)
+#define FH39_TSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x680)
+
+/* TFDB (Transmit Frame Buffer Descriptor) */
+#define FH39_TFDB(_ch, buf)			(FH39_TFDB_TABLE + \
+						 ((_ch) * 2 + (buf)) * 0x28)
+#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)	(FH39_TFDB_TABLE + 0x50 * (_ch))
+
+/* CBCC channel is [0,2] */
+#define FH39_CBCC(_ch)		(FH39_CBCC_TABLE + (_ch) * 0x8)
+#define FH39_CBCC_CTRL(_ch)	(FH39_CBCC(_ch) + 0x00)
+#define FH39_CBCC_BASE(_ch)	(FH39_CBCC(_ch) + 0x04)
+
+/* RCSR channel is [0,2] */
+#define FH39_RCSR(_ch)			(FH39_RCSR_TABLE + (_ch) * 0x40)
+#define FH39_RCSR_CONFIG(_ch)		(FH39_RCSR(_ch) + 0x00)
+#define FH39_RCSR_RBD_BASE(_ch)		(FH39_RCSR(_ch) + 0x04)
+#define FH39_RCSR_WPTR(_ch)		(FH39_RCSR(_ch) + 0x20)
+#define FH39_RCSR_RPTR_ADDR(_ch)	(FH39_RCSR(_ch) + 0x24)
+
+#define FH39_RSCSR_CHNL0_WPTR		(FH39_RCSR_WPTR(0))
+
+/* RSSR */
+#define FH39_RSSR_CTRL			(FH39_RSSR_TABLE + 0x000)
+#define FH39_RSSR_STATUS		(FH39_RSSR_TABLE + 0x004)
+
+/* TCSR */
+#define FH39_TCSR(_ch)			(FH39_TCSR_TABLE + (_ch) * 0x20)
+#define FH39_TCSR_CONFIG(_ch)		(FH39_TCSR(_ch) + 0x00)
+#define FH39_TCSR_CREDIT(_ch)		(FH39_TCSR(_ch) + 0x04)
+#define FH39_TCSR_BUFF_STTS(_ch)	(FH39_TCSR(_ch) + 0x08)
+
+/* TSSR */
+#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TABLE + 0x000)
+#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TABLE + 0x008)
+#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TABLE + 0x010)
+
+
+/* DBM */
+
+#define FH39_SRVC_CHNL                            (6)
+
+#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
+#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
+
+#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128		(0x01000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST		(0x00001000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH			(0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER		(0x00000001)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL	(0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL	(0x00000008)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD		(0x00200000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT		(0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE		(0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE		(0x80000000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID		(0x00004000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR		(0x00000001)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON	(0xFF000000)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON	(0x00FF0000)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B	(0x00000400)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON		(0x00000100)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON		(0x00000080)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH	(0x00000020)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH		(0x00000005)
+
+#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)	(BIT(_ch) << 24)
+#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)	(BIT(_ch) << 16)
+
+#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
+	(FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
+	 FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
+
+#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE			(0x01000000)
+
+struct iwl3945_tfd_tb {
+	__le32 addr;
+	__le32 len;
+} __packed;
+
+struct iwl3945_tfd {
+	__le32 control_flags;
+	struct iwl3945_tfd_tb tbs[4];
+	u8 __pad[28];
+} __packed;
+
+
+#endif /* __iwl_3945_fh_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-hw.h b/drivers/net/wireless/iwlegacy/iwl-3945-hw.h
new file mode 100644
index 0000000..779d3cb
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-hw.h
@@ -0,0 +1,293 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
+ * Please use iwl-commands.h for uCode API definitions.
+ * Please use iwl-3945.h for driver implementation definitions.
+ */
+
+#ifndef __iwl_3945_hw__
+#define __iwl_3945_hw__
+
+#include "iwl-eeprom.h"
+
+/* RSSI to dBm */
+#define IWL39_RSSI_OFFSET	95
+
+#define IWL_DEFAULT_TX_POWER	0x0F
+
+/*
+ * EEPROM related constants, enums, and structures.
+ */
+#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
+
+/*
+ * Mapping of a Tx power level, at factory calibration temperature,
+ *   to a radio/DSP gain table index.
+ * One for each of 5 "sample" power levels in each band.
+ * v_det is measured at the factory, using the 3945's built-in power amplifier
+ *   (PA) output voltage detector.  This same detector is used during Tx of
+ *   long packets in normal operation to provide feedback as to proper output
+ *   level.
+ * Data copied from EEPROM.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct iwl3945_eeprom_txpower_sample {
+	u8 gain_index;		/* index into power (gain) setup table ... */
+	s8 power;		/* ... for this pwr level for this chnl group */
+	u16 v_det;		/* PA output voltage */
+} __packed;
+
+/*
+ * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
+ * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
+ * Tx power setup code interpolates between the 5 "sample" power levels
+ *    to determine the nominal setup for a requested power level.
+ * Data copied from EEPROM.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct iwl3945_eeprom_txpower_group {
+	struct iwl3945_eeprom_txpower_sample samples[5];  /* 5 power levels */
+	s32 a, b, c, d, e;	/* coefficients for voltage->power
+				 * formula (signed) */
+	s32 Fa, Fb, Fc, Fd, Fe;	/* these modify coeffs based on
+				 * frequency (signed) */
+	s8 saturation_power;	/* highest power possible by h/w in this
+				 * band */
+	u8 group_channel;	/* "representative" channel # in this band */
+	s16 temperature;	/* h/w temperature at factory calib this band
+				 * (signed) */
+} __packed;
+
+/*
+ * Temperature-based Tx-power compensation data, not band-specific.
+ * These coefficients are use to modify a/b/c/d/e coeffs based on
+ *   difference between current temperature and factory calib temperature.
+ * Data copied from EEPROM.
+ */
+struct iwl3945_eeprom_temperature_corr {
+	u32 Ta;
+	u32 Tb;
+	u32 Tc;
+	u32 Td;
+	u32 Te;
+} __packed;
+
+/*
+ * EEPROM map
+ */
+struct iwl3945_eeprom {
+	u8 reserved0[16];
+	u16 device_id;	/* abs.ofs: 16 */
+	u8 reserved1[2];
+	u16 pmc;		/* abs.ofs: 20 */
+	u8 reserved2[20];
+	u8 mac_address[6];	/* abs.ofs: 42 */
+	u8 reserved3[58];
+	u16 board_revision;	/* abs.ofs: 106 */
+	u8 reserved4[11];
+	u8 board_pba_number[9];	/* abs.ofs: 119 */
+	u8 reserved5[8];
+	u16 version;		/* abs.ofs: 136 */
+	u8 sku_cap;		/* abs.ofs: 138 */
+	u8 leds_mode;		/* abs.ofs: 139 */
+	u16 oem_mode;
+	u16 wowlan_mode;	/* abs.ofs: 142 */
+	u16 leds_time_interval;	/* abs.ofs: 144 */
+	u8 leds_off_time;	/* abs.ofs: 146 */
+	u8 leds_on_time;	/* abs.ofs: 147 */
+	u8 almgor_m_version;	/* abs.ofs: 148 */
+	u8 antenna_switch_type;	/* abs.ofs: 149 */
+	u8 reserved6[42];
+	u8 sku_id[4];		/* abs.ofs: 192 */
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by 3945 has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+	u16 band_1_count;	/* abs.ofs: 196 */
+	struct iwl_eeprom_channel band_1_channels[14];  /* abs.ofs: 198 */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+	u16 band_2_count;	/* abs.ofs: 226 */
+	struct iwl_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+	u16 band_3_count;	/* abs.ofs: 254 */
+	struct iwl_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+	u16 band_4_count;	/* abs.ofs: 280 */
+	struct iwl_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+	u16 band_5_count;	/* abs.ofs: 304 */
+	struct iwl_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
+
+	u8 reserved9[194];
+
+/*
+ * 3945 Txpower calibration data.
+ */
+#define IWL_NUM_TX_CALIB_GROUPS 5
+	struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
+/* abs.ofs: 512 */
+	struct iwl3945_eeprom_temperature_corr corrections;  /* abs.ofs: 832 */
+	u8 reserved16[172];	/* fill out to full 1024 byte block */
+} __packed;
+
+#define IWL3945_EEPROM_IMG_SIZE 1024
+
+/* End of EEPROM */
+
+#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)	/* bit 6    */
+#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)	/* bit 7    */
+
+/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
+#define IWL39_NUM_QUEUES        5
+#define IWL39_CMD_QUEUE_NUM	4
+
+#define IWL_DEFAULT_TX_RETRY  15
+
+/*********************************************/
+
+#define RFD_SIZE                              4
+#define NUM_TFD_CHUNKS                        4
+
+#define RX_QUEUE_SIZE                         256
+#define RX_QUEUE_MASK                         255
+#define RX_QUEUE_SIZE_LOG                     8
+
+#define U32_PAD(n)		((4-(n))&0x3)
+
+#define TFD_CTL_COUNT_SET(n)       (n << 24)
+#define TFD_CTL_COUNT_GET(ctl)     ((ctl >> 24) & 7)
+#define TFD_CTL_PAD_SET(n)         (n << 28)
+#define TFD_CTL_PAD_GET(ctl)       (ctl >> 28)
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+#define IWL39_RTC_INST_LOWER_BOUND		(0x000000)
+#define IWL39_RTC_INST_UPPER_BOUND		(0x014000)
+
+#define IWL39_RTC_DATA_LOWER_BOUND		(0x800000)
+#define IWL39_RTC_DATA_UPPER_BOUND		(0x808000)
+
+#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
+				IWL39_RTC_INST_LOWER_BOUND)
+#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
+				IWL39_RTC_DATA_LOWER_BOUND)
+
+#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
+#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
+
+static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
+{
+	return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
+	       (addr < IWL39_RTC_DATA_UPPER_BOUND);
+}
+
+/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
+ * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
+struct iwl3945_shared {
+	__le32 tx_base_ptr[8];
+} __packed;
+
+static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
+{
+	return le16_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
+{
+	return le16_to_cpu(rate_n_flags);
+}
+
+static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
+{
+	return cpu_to_le16((u16)rate|flags);
+}
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.c b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
new file mode 100644
index 0000000..abd9235
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-commands.h"
+#include "iwl-3945.h"
+#include "iwl-core.h"
+#include "iwl-dev.h"
+#include "iwl-3945-led.h"
+
+
+/* Send led command */
+static int iwl3945_send_led_cmd(struct iwl_priv *priv,
+				struct iwl_led_cmd *led_cmd)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_LEDS_CMD,
+		.len = sizeof(struct iwl_led_cmd),
+		.data = led_cmd,
+		.flags = CMD_ASYNC,
+		.callback = NULL,
+	};
+
+	return iwl_legacy_send_cmd(priv, &cmd);
+}
+
+const struct iwl_led_ops iwl3945_led_ops = {
+	.cmd = iwl3945_send_led_cmd,
+};
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.h b/drivers/net/wireless/iwlegacy/iwl-3945-led.h
new file mode 100644
index 0000000..9671627
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-led.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_3945_led_h__
+#define __iwl_3945_led_h__
+
+extern const struct iwl_led_ops iwl3945_led_ops;
+
+#endif /* __iwl_3945_led_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
new file mode 100644
index 0000000..977bd24
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
@@ -0,0 +1,994 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "iwl-commands.h"
+#include "iwl-3945.h"
+#include "iwl-sta.h"
+
+#define RS_NAME "iwl-3945-rs"
+
+static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
+	7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
+};
+
+static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
+	7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
+};
+
+static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
+	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
+};
+
+static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
+	7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+struct iwl3945_tpt_entry {
+	s8 min_rssi;
+	u8 index;
+};
+
+static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
+	{-60, IWL_RATE_54M_INDEX},
+	{-64, IWL_RATE_48M_INDEX},
+	{-72, IWL_RATE_36M_INDEX},
+	{-80, IWL_RATE_24M_INDEX},
+	{-84, IWL_RATE_18M_INDEX},
+	{-85, IWL_RATE_12M_INDEX},
+	{-87, IWL_RATE_9M_INDEX},
+	{-89, IWL_RATE_6M_INDEX}
+};
+
+static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
+	{-60, IWL_RATE_54M_INDEX},
+	{-64, IWL_RATE_48M_INDEX},
+	{-68, IWL_RATE_36M_INDEX},
+	{-80, IWL_RATE_24M_INDEX},
+	{-84, IWL_RATE_18M_INDEX},
+	{-85, IWL_RATE_12M_INDEX},
+	{-86, IWL_RATE_11M_INDEX},
+	{-88, IWL_RATE_5M_INDEX},
+	{-90, IWL_RATE_2M_INDEX},
+	{-92, IWL_RATE_1M_INDEX}
+};
+
+#define IWL_RATE_MAX_WINDOW          62
+#define IWL_RATE_FLUSH		(3*HZ)
+#define IWL_RATE_WIN_FLUSH       (HZ/2)
+#define IWL39_RATE_HIGH_TH          11520
+#define IWL_SUCCESS_UP_TH	   8960
+#define IWL_SUCCESS_DOWN_TH	  10880
+#define IWL_RATE_MIN_FAILURE_TH       6
+#define IWL_RATE_MIN_SUCCESS_TH       8
+#define IWL_RATE_DECREASE_TH       1920
+#define IWL_RATE_RETRY_TH	     15
+
+static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
+{
+	u32 index = 0;
+	u32 table_size = 0;
+	struct iwl3945_tpt_entry *tpt_table = NULL;
+
+	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
+		rssi = IWL_MIN_RSSI_VAL;
+
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
+		tpt_table = iwl3945_tpt_table_g;
+		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
+		break;
+
+	case IEEE80211_BAND_5GHZ:
+		tpt_table = iwl3945_tpt_table_a;
+		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
+		break;
+
+	default:
+		BUG();
+		break;
+	}
+
+	while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
+		index++;
+
+	index = min(index, (table_size - 1));
+
+	return tpt_table[index].index;
+}
+
+static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
+{
+	window->data = 0;
+	window->success_counter = 0;
+	window->success_ratio = -1;
+	window->counter = 0;
+	window->average_tpt = IWL_INVALID_VALUE;
+	window->stamp = 0;
+}
+
+/**
+ * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
+ *
+ * Returns the number of windows that have gathered data but were
+ * not flushed.  If there were any that were not flushed, then
+ * reschedule the rate flushing routine.
+ */
+static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
+{
+	int unflushed = 0;
+	int i;
+	unsigned long flags;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+
+	/*
+	 * For each rate, if we have collected data on that rate
+	 * and it has been more than IWL_RATE_WIN_FLUSH
+	 * since we flushed, clear out the gathered statistics
+	 */
+	for (i = 0; i < IWL_RATE_COUNT_3945; i++) {
+		if (!rs_sta->win[i].counter)
+			continue;
+
+		spin_lock_irqsave(&rs_sta->lock, flags);
+		if (time_after(jiffies, rs_sta->win[i].stamp +
+			       IWL_RATE_WIN_FLUSH)) {
+			IWL_DEBUG_RATE(priv, "flushing %d samples of rate "
+				       "index %d\n",
+				       rs_sta->win[i].counter, i);
+			iwl3945_clear_window(&rs_sta->win[i]);
+		} else
+			unflushed++;
+		spin_unlock_irqrestore(&rs_sta->lock, flags);
+	}
+
+	return unflushed;
+}
+
+#define IWL_RATE_FLUSH_MAX              5000	/* msec */
+#define IWL_RATE_FLUSH_MIN              50	/* msec */
+#define IWL_AVERAGE_PACKETS             1500
+
+static void iwl3945_bg_rate_scale_flush(unsigned long data)
+{
+	struct iwl3945_rs_sta *rs_sta = (void *)data;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+	int unflushed = 0;
+	unsigned long flags;
+	u32 packet_count, duration, pps;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	/* Number of packets Rx'd since last time this timer ran */
+	packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
+
+	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
+
+	if (unflushed) {
+		duration =
+		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
+
+		IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n",
+			       packet_count, duration);
+
+		/* Determine packets per second */
+		if (duration)
+			pps = (packet_count * 1000) / duration;
+		else
+			pps = 0;
+
+		if (pps) {
+			duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
+			if (duration < IWL_RATE_FLUSH_MIN)
+				duration = IWL_RATE_FLUSH_MIN;
+			else if (duration > IWL_RATE_FLUSH_MAX)
+				duration = IWL_RATE_FLUSH_MAX;
+		} else
+			duration = IWL_RATE_FLUSH_MAX;
+
+		rs_sta->flush_time = msecs_to_jiffies(duration);
+
+		IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n",
+			       duration, packet_count);
+
+		mod_timer(&rs_sta->rate_scale_flush, jiffies +
+			  rs_sta->flush_time);
+
+		rs_sta->last_partial_flush = jiffies;
+	} else {
+		rs_sta->flush_time = IWL_RATE_FLUSH;
+		rs_sta->flush_pending = 0;
+	}
+	/* If there weren't any unflushed entries, we don't schedule the timer
+	 * to run again */
+
+	rs_sta->last_flush = jiffies;
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	IWL_DEBUG_RATE(priv, "leave\n");
+}
+
+/**
+ * iwl3945_collect_tx_data - Update the success/failure sliding window
+ *
+ * We keep a sliding window of the last 64 packets transmitted
+ * at this rate.  window->data contains the bitmask of successful
+ * packets.
+ */
+static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
+				struct iwl3945_rate_scale_data *window,
+				int success, int retries, int index)
+{
+	unsigned long flags;
+	s32 fail_count;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+
+	if (!retries) {
+		IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n");
+		return;
+	}
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	/*
+	 * Keep track of only the latest 62 tx frame attempts in this rate's
+	 * history window; anything older isn't really relevant any more.
+	 * If we have filled up the sliding window, drop the oldest attempt;
+	 * if the oldest attempt (highest bit in bitmap) shows "success",
+	 * subtract "1" from the success counter (this is the main reason
+	 * we keep these bitmaps!).
+	 * */
+	while (retries > 0) {
+		if (window->counter >= IWL_RATE_MAX_WINDOW) {
+
+			/* remove earliest */
+			window->counter = IWL_RATE_MAX_WINDOW - 1;
+
+			if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) {
+				window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1));
+				window->success_counter--;
+			}
+		}
+
+		/* Increment frames-attempted counter */
+		window->counter++;
+
+		/* Shift bitmap by one frame (throw away oldest history),
+		 * OR in "1", and increment "success" if this
+		 * frame was successful. */
+		window->data <<= 1;
+		if (success > 0) {
+			window->success_counter++;
+			window->data |= 0x1;
+			success--;
+		}
+
+		retries--;
+	}
+
+	/* Calculate current success ratio, avoid divide-by-0! */
+	if (window->counter > 0)
+		window->success_ratio = 128 * (100 * window->success_counter)
+					/ window->counter;
+	else
+		window->success_ratio = IWL_INVALID_VALUE;
+
+	fail_count = window->counter - window->success_counter;
+
+	/* Calculate average throughput, if we have enough history. */
+	if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
+	    (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
+		window->average_tpt = ((window->success_ratio *
+				rs_sta->expected_tpt[index] + 64) / 128);
+	else
+		window->average_tpt = IWL_INVALID_VALUE;
+
+	/* Tag this window as having been updated */
+	window->stamp = jiffies;
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+}
+
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
+{
+	struct ieee80211_hw *hw = priv->hw;
+	struct ieee80211_conf *conf = &priv->hw->conf;
+	struct iwl3945_sta_priv *psta;
+	struct iwl3945_rs_sta *rs_sta;
+	struct ieee80211_supported_band *sband;
+	int i;
+
+	IWL_DEBUG_INFO(priv, "enter\n");
+	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
+		goto out;
+
+	psta = (struct iwl3945_sta_priv *) sta->drv_priv;
+	rs_sta = &psta->rs_sta;
+	sband = hw->wiphy->bands[conf->channel->band];
+
+	rs_sta->priv = priv;
+
+	rs_sta->start_rate = IWL_RATE_INVALID;
+
+	/* default to just 802.11b */
+	rs_sta->expected_tpt = iwl3945_expected_tpt_b;
+
+	rs_sta->last_partial_flush = jiffies;
+	rs_sta->last_flush = jiffies;
+	rs_sta->flush_time = IWL_RATE_FLUSH;
+	rs_sta->last_tx_packets = 0;
+
+	rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
+	rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;
+
+	for (i = 0; i < IWL_RATE_COUNT_3945; i++)
+		iwl3945_clear_window(&rs_sta->win[i]);
+
+	/* TODO: what is a good starting rate for STA? About middle? Maybe not
+	 * the lowest or the highest rate.. Could consider using RSSI from
+	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
+	 * after assoc.. */
+
+	for (i = sband->n_bitrates - 1; i >= 0; i--) {
+		if (sta->supp_rates[sband->band] & (1 << i)) {
+			rs_sta->last_txrate_idx = i;
+			break;
+		}
+	}
+
+	priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
+	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
+	if (sband->band == IEEE80211_BAND_5GHZ) {
+		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+		priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
+						IWL_FIRST_OFDM_RATE;
+	}
+
+out:
+	priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+
+	IWL_DEBUG_INFO(priv, "leave\n");
+}
+
+static void *iwl3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+	return hw->priv;
+}
+
+/* rate scale requires free function to be implemented */
+static void iwl3945_rs_free(void *priv)
+{
+	return;
+}
+
+static void *iwl3945_rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
+{
+	struct iwl3945_rs_sta *rs_sta;
+	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
+	struct iwl_priv *priv __maybe_unused = iwl_priv;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	rs_sta = &psta->rs_sta;
+
+	spin_lock_init(&rs_sta->lock);
+	init_timer(&rs_sta->rate_scale_flush);
+
+	IWL_DEBUG_RATE(priv, "leave\n");
+
+	return rs_sta;
+}
+
+static void iwl3945_rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
+			void *priv_sta)
+{
+	struct iwl3945_rs_sta *rs_sta = priv_sta;
+
+	/*
+	 * Be careful not to use any members of iwl3945_rs_sta (like trying
+	 * to use iwl_priv to print out debugging) since it may not be fully
+	 * initialized at this point.
+	 */
+	del_timer_sync(&rs_sta->rate_scale_flush);
+}
+
+
+/**
+ * iwl3945_rs_tx_status - Update rate control values based on Tx results
+ *
+ * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
+ * the hardware for each rate.
+ */
+static void iwl3945_rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
+			 struct ieee80211_sta *sta, void *priv_sta,
+			 struct sk_buff *skb)
+{
+	s8 retries = 0, current_count;
+	int scale_rate_index, first_index, last_index;
+	unsigned long flags;
+	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+	struct iwl3945_rs_sta *rs_sta = priv_sta;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	retries = info->status.rates[0].count;
+	/* Sanity Check for retries */
+	if (retries > IWL_RATE_RETRY_TH)
+		retries = IWL_RATE_RETRY_TH;
+
+	first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
+	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
+		IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index);
+		return;
+	}
+
+	if (!priv_sta) {
+		IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
+		return;
+	}
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (!rs_sta->priv) {
+		IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
+		return;
+	}
+
+
+	rs_sta->tx_packets++;
+
+	scale_rate_index = first_index;
+	last_index = first_index;
+
+	/*
+	 * Update the window for each rate.  We determine which rates
+	 * were Tx'd based on the total number of retries vs. the number
+	 * of retries configured for each rate -- currently set to the
+	 * priv value 'retry_rate' vs. rate specific
+	 *
+	 * On exit from this while loop last_index indicates the rate
+	 * at which the frame was finally transmitted (or failed if no
+	 * ACK)
+	 */
+	while (retries > 1) {
+		if ((retries - 1) < priv->retry_rate) {
+			current_count = (retries - 1);
+			last_index = scale_rate_index;
+		} else {
+			current_count = priv->retry_rate;
+			last_index = iwl3945_rs_next_rate(priv,
+							 scale_rate_index);
+		}
+
+		/* Update this rate accounting for as many retries
+		 * as was used for it (per current_count) */
+		iwl3945_collect_tx_data(rs_sta,
+				    &rs_sta->win[scale_rate_index],
+				    0, current_count, scale_rate_index);
+		IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n",
+			       scale_rate_index, current_count);
+
+		retries -= current_count;
+
+		scale_rate_index = last_index;
+	}
+
+
+	/* Update the last index window with success/failure based on ACK */
+	IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n",
+		       last_index,
+		       (info->flags & IEEE80211_TX_STAT_ACK) ?
+		       "success" : "failure");
+	iwl3945_collect_tx_data(rs_sta,
+			    &rs_sta->win[last_index],
+			    info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
+
+	/* We updated the rate scale window -- if its been more than
+	 * flush_time since the last run, schedule the flush
+	 * again */
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	if (!rs_sta->flush_pending &&
+	    time_after(jiffies, rs_sta->last_flush +
+		       rs_sta->flush_time)) {
+
+		rs_sta->last_partial_flush = jiffies;
+		rs_sta->flush_pending = 1;
+		mod_timer(&rs_sta->rate_scale_flush,
+			  jiffies + rs_sta->flush_time);
+	}
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	IWL_DEBUG_RATE(priv, "leave\n");
+}
+
+static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
+				 u8 index, u16 rate_mask, enum ieee80211_band band)
+{
+	u8 high = IWL_RATE_INVALID;
+	u8 low = IWL_RATE_INVALID;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+
+	/* 802.11A walks to the next literal adjacent rate in
+	 * the rate table */
+	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
+		int i;
+		u32 mask;
+
+		/* Find the previous rate that is in the rate mask */
+		i = index - 1;
+		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
+			if (rate_mask & mask) {
+				low = i;
+				break;
+			}
+		}
+
+		/* Find the next rate that is in the rate mask */
+		i = index + 1;
+		for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
+		     i++, mask <<= 1) {
+			if (rate_mask & mask) {
+				high = i;
+				break;
+			}
+		}
+
+		return (high << 8) | low;
+	}
+
+	low = index;
+	while (low != IWL_RATE_INVALID) {
+		if (rs_sta->tgg)
+			low = iwl3945_rates[low].prev_rs_tgg;
+		else
+			low = iwl3945_rates[low].prev_rs;
+		if (low == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << low))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
+	}
+
+	high = index;
+	while (high != IWL_RATE_INVALID) {
+		if (rs_sta->tgg)
+			high = iwl3945_rates[high].next_rs_tgg;
+		else
+			high = iwl3945_rates[high].next_rs;
+		if (high == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << high))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
+	}
+
+	return (high << 8) | low;
+}
+
+/**
+ * iwl3945_rs_get_rate - find the rate for the requested packet
+ *
+ * Returns the ieee80211_rate structure allocated by the driver.
+ *
+ * The rate control algorithm has no internal mapping between hw_mode's
+ * rate ordering and the rate ordering used by the rate control algorithm.
+ *
+ * The rate control algorithm uses a single table of rates that goes across
+ * the entire A/B/G spectrum vs. being limited to just one particular
+ * hw_mode.
+ *
+ * As such, we can't convert the index obtained below into the hw_mode's
+ * rate table and must reference the driver allocated rate table
+ *
+ */
+static void iwl3945_rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
+			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
+{
+	struct ieee80211_supported_band *sband = txrc->sband;
+	struct sk_buff *skb = txrc->skb;
+	u8 low = IWL_RATE_INVALID;
+	u8 high = IWL_RATE_INVALID;
+	u16 high_low;
+	int index;
+	struct iwl3945_rs_sta *rs_sta = priv_sta;
+	struct iwl3945_rate_scale_data *window = NULL;
+	int current_tpt = IWL_INVALID_VALUE;
+	int low_tpt = IWL_INVALID_VALUE;
+	int high_tpt = IWL_INVALID_VALUE;
+	u32 fail_count;
+	s8 scale_action = 0;
+	unsigned long flags;
+	u16 rate_mask;
+	s8 max_rate_idx = -1;
+	struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (rs_sta && !rs_sta->priv) {
+		IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
+		priv_sta = NULL;
+	}
+
+	if (rate_control_send_low(sta, priv_sta, txrc))
+		return;
+
+	rate_mask = sta->supp_rates[sband->band];
+
+	/* get user max rate if set */
+	max_rate_idx = txrc->max_rate_idx;
+	if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
+		max_rate_idx += IWL_FIRST_OFDM_RATE;
+	if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
+		max_rate_idx = -1;
+
+	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
+
+	if (sband->band == IEEE80211_BAND_5GHZ)
+		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	/* for recent assoc, choose best rate regarding
+	 * to rssi value
+	 */
+	if (rs_sta->start_rate != IWL_RATE_INVALID) {
+		if (rs_sta->start_rate < index &&
+		   (rate_mask & (1 << rs_sta->start_rate)))
+			index = rs_sta->start_rate;
+		rs_sta->start_rate = IWL_RATE_INVALID;
+	}
+
+	/* force user max rate if set by user */
+	if ((max_rate_idx != -1) && (max_rate_idx < index)) {
+		if (rate_mask & (1 << max_rate_idx))
+			index = max_rate_idx;
+	}
+
+	window = &(rs_sta->win[index]);
+
+	fail_count = window->counter - window->success_counter;
+
+	if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
+	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
+		spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+		IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: "
+			       "counter: %d, success_counter: %d, "
+			       "expected_tpt is %sNULL\n",
+			       index,
+			       window->counter,
+			       window->success_counter,
+			       rs_sta->expected_tpt ? "not " : "");
+
+	   /* Can't calculate this yet; not enough history */
+		window->average_tpt = IWL_INVALID_VALUE;
+		goto out;
+
+	}
+
+	current_tpt = window->average_tpt;
+
+	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
+					     sband->band);
+	low = high_low & 0xff;
+	high = (high_low >> 8) & 0xff;
+
+	/* If user set max rate, dont allow higher than user constrain */
+	if ((max_rate_idx != -1) && (max_rate_idx < high))
+		high = IWL_RATE_INVALID;
+
+	/* Collect Measured throughputs of adjacent rates */
+	if (low != IWL_RATE_INVALID)
+		low_tpt = rs_sta->win[low].average_tpt;
+
+	if (high != IWL_RATE_INVALID)
+		high_tpt = rs_sta->win[high].average_tpt;
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	scale_action = 0;
+
+	/* Low success ratio , need to drop the rate */
+	if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
+		IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n");
+		scale_action = -1;
+	/* No throughput measured yet for adjacent rates,
+	 * try increase */
+	} else if ((low_tpt == IWL_INVALID_VALUE) &&
+		   (high_tpt == IWL_INVALID_VALUE)) {
+
+		if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH)
+			scale_action = 1;
+		else if (low != IWL_RATE_INVALID)
+			scale_action = 0;
+
+	/* Both adjacent throughputs are measured, but neither one has
+	 * better throughput; we're using the best rate, don't change
+	 * it! */
+	} else if ((low_tpt != IWL_INVALID_VALUE) &&
+		 (high_tpt != IWL_INVALID_VALUE) &&
+		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
+
+		IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < "
+			       "current_tpt [%d]\n",
+			       low_tpt, high_tpt, current_tpt);
+		scale_action = 0;
+
+	/* At least one of the rates has better throughput */
+	} else {
+		if (high_tpt != IWL_INVALID_VALUE) {
+
+			/* High rate has better throughput, Increase
+			 * rate */
+			if (high_tpt > current_tpt &&
+				window->success_ratio >= IWL_RATE_INCREASE_TH)
+				scale_action = 1;
+			else {
+				IWL_DEBUG_RATE(priv,
+				    "decrease rate because of high tpt\n");
+				scale_action = 0;
+			}
+		} else if (low_tpt != IWL_INVALID_VALUE) {
+			if (low_tpt > current_tpt) {
+				IWL_DEBUG_RATE(priv,
+				    "decrease rate because of low tpt\n");
+				scale_action = -1;
+			} else if (window->success_ratio >= IWL_RATE_INCREASE_TH) {
+				/* Lower rate has better
+				 * throughput,decrease rate */
+				scale_action = 1;
+			}
+		}
+	}
+
+	/* Sanity check; asked for decrease, but success rate or throughput
+	 * has been good at old rate.  Don't change it. */
+	if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
+		    ((window->success_ratio > IWL_RATE_HIGH_TH) ||
+		     (current_tpt > (100 * rs_sta->expected_tpt[low]))))
+		scale_action = 0;
+
+	switch (scale_action) {
+	case -1:
+
+		/* Decrese rate */
+		if (low != IWL_RATE_INVALID)
+			index = low;
+		break;
+
+	case 1:
+		/* Increase rate */
+		if (high != IWL_RATE_INVALID)
+			index = high;
+
+		break;
+
+	case 0:
+	default:
+		/* No change */
+		break;
+	}
+
+	IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n",
+		       index, scale_action, low, high);
+
+ out:
+
+	rs_sta->last_txrate_idx = index;
+	if (sband->band == IEEE80211_BAND_5GHZ)
+		info->control.rates[0].idx = rs_sta->last_txrate_idx -
+				IWL_FIRST_OFDM_RATE;
+	else
+		info->control.rates[0].idx = rs_sta->last_txrate_idx;
+
+	IWL_DEBUG_RATE(priv, "leave: %d\n", index);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
+						  char __user *user_buf,
+						  size_t count, loff_t *ppos)
+{
+	char *buff;
+	int desc = 0;
+	int j;
+	ssize_t ret;
+	struct iwl3945_rs_sta *lq_sta = file->private_data;
+
+	buff = kmalloc(1024, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
+			"rate=0x%X flush time %d\n",
+			lq_sta->tx_packets,
+			lq_sta->last_txrate_idx,
+			lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
+	for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
+		desc += sprintf(buff+desc,
+				"counter=%d success=%d %%=%d\n",
+				lq_sta->win[j].counter,
+				lq_sta->win[j].success_counter,
+				lq_sta->win[j].success_ratio);
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	kfree(buff);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+	.read = iwl3945_sta_dbgfs_stats_table_read,
+	.open = iwl3945_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static void iwl3945_add_debugfs(void *priv, void *priv_sta,
+				struct dentry *dir)
+{
+	struct iwl3945_rs_sta *lq_sta = priv_sta;
+
+	lq_sta->rs_sta_dbgfs_stats_table_file =
+		debugfs_create_file("rate_stats_table", 0600, dir,
+		lq_sta, &rs_sta_dbgfs_stats_table_ops);
+
+}
+
+static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
+{
+	struct iwl3945_rs_sta *lq_sta = priv_sta;
+	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+}
+#endif
+
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void iwl3945_rs_rate_init_stub(void *priv_r,
+				struct ieee80211_supported_band *sband,
+			      struct ieee80211_sta *sta, void *priv_sta)
+{
+}
+
+static struct rate_control_ops rs_ops = {
+	.module = NULL,
+	.name = RS_NAME,
+	.tx_status = iwl3945_rs_tx_status,
+	.get_rate = iwl3945_rs_get_rate,
+	.rate_init = iwl3945_rs_rate_init_stub,
+	.alloc = iwl3945_rs_alloc,
+	.free = iwl3945_rs_free,
+	.alloc_sta = iwl3945_rs_alloc_sta,
+	.free_sta = iwl3945_rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+	.add_sta_debugfs = iwl3945_add_debugfs,
+	.remove_sta_debugfs = iwl3945_remove_debugfs,
+#endif
+
+};
+void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+{
+	struct iwl_priv *priv = hw->priv;
+	s32 rssi = 0;
+	unsigned long flags;
+	struct iwl3945_rs_sta *rs_sta;
+	struct ieee80211_sta *sta;
+	struct iwl3945_sta_priv *psta;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	rcu_read_lock();
+
+	sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
+				 priv->stations[sta_id].sta.sta.addr);
+	if (!sta) {
+		IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
+		rcu_read_unlock();
+		return;
+	}
+
+	psta = (void *) sta->drv_priv;
+	rs_sta = &psta->rs_sta;
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	rs_sta->tgg = 0;
+	switch (priv->band) {
+	case IEEE80211_BAND_2GHZ:
+		/* TODO: this always does G, not a regression */
+		if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+						RXON_FLG_TGG_PROTECT_MSK) {
+			rs_sta->tgg = 1;
+			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
+		} else
+			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
+		break;
+
+	case IEEE80211_BAND_5GHZ:
+		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
+		break;
+	case IEEE80211_NUM_BANDS:
+		BUG();
+		break;
+	}
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	rssi = priv->_3945.last_rx_rssi;
+	if (rssi == 0)
+		rssi = IWL_MIN_RSSI_VAL;
+
+	IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi);
+
+	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
+
+	IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: "
+		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
+		       iwl3945_rates[rs_sta->start_rate].plcp);
+	rcu_read_unlock();
+}
+
+int iwl3945_rate_control_register(void)
+{
+	return ieee80211_rate_control_register(&rs_ops);
+}
+
+void iwl3945_rate_control_unregister(void)
+{
+	ieee80211_rate_control_unregister(&rs_ops);
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
new file mode 100644
index 0000000..d096dc2
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -0,0 +1,2742 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+#include <net/mac80211.h>
+
+#include "iwl-fh.h"
+#include "iwl-3945-fh.h"
+#include "iwl-commands.h"
+#include "iwl-sta.h"
+#include "iwl-3945.h"
+#include "iwl-eeprom.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-led.h"
+#include "iwl-3945-led.h"
+#include "iwl-3945-debugfs.h"
+
+#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
+	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
+				    IWL_RATE_##r##M_IEEE,   \
+				    IWL_RATE_##ip##M_INDEX, \
+				    IWL_RATE_##in##M_INDEX, \
+				    IWL_RATE_##rp##M_INDEX, \
+				    IWL_RATE_##rn##M_INDEX, \
+				    IWL_RATE_##pp##M_INDEX, \
+				    IWL_RATE_##np##M_INDEX, \
+				    IWL_RATE_##r##M_INDEX_TABLE, \
+				    IWL_RATE_##ip##M_INDEX_TABLE }
+
+/*
+ * Parameter order:
+ *   rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to IWL_RATE_INVALID
+ *
+ */
+const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
+	IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),    /*  1mbps */
+	IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),          /*  2mbps */
+	IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
+	IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),      /* 11mbps */
+	IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
+	IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),       /*  9mbps */
+	IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
+	IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
+	IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
+	IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
+	IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
+	IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
+};
+
+static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
+{
+	u8 rate = iwl3945_rates[rate_index].prev_ieee;
+
+	if (rate == IWL_RATE_INVALID)
+		rate = rate_index;
+	return rate;
+}
+
+/* 1 = enable the iwl3945_disable_events() function */
+#define IWL_EVT_DISABLE (0)
+#define IWL_EVT_DISABLE_SIZE (1532/32)
+
+/**
+ * iwl3945_disable_events - Disable selected events in uCode event log
+ *
+ * Disable an event by writing "1"s into "disable"
+ *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
+ *   Default values of 0 enable uCode events to be logged.
+ * Use for only special debugging.  This function is just a placeholder as-is,
+ *   you'll need to provide the special bits! ...
+ *   ... and set IWL_EVT_DISABLE to 1. */
+void iwl3945_disable_events(struct iwl_priv *priv)
+{
+	int i;
+	u32 base;		/* SRAM address of event log header */
+	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
+	u32 array_size;		/* # of u32 entries in array */
+	static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
+		0x00000000,	/*   31 -    0  Event id numbers */
+		0x00000000,	/*   63 -   32 */
+		0x00000000,	/*   95 -   64 */
+		0x00000000,	/*  127 -   96 */
+		0x00000000,	/*  159 -  128 */
+		0x00000000,	/*  191 -  160 */
+		0x00000000,	/*  223 -  192 */
+		0x00000000,	/*  255 -  224 */
+		0x00000000,	/*  287 -  256 */
+		0x00000000,	/*  319 -  288 */
+		0x00000000,	/*  351 -  320 */
+		0x00000000,	/*  383 -  352 */
+		0x00000000,	/*  415 -  384 */
+		0x00000000,	/*  447 -  416 */
+		0x00000000,	/*  479 -  448 */
+		0x00000000,	/*  511 -  480 */
+		0x00000000,	/*  543 -  512 */
+		0x00000000,	/*  575 -  544 */
+		0x00000000,	/*  607 -  576 */
+		0x00000000,	/*  639 -  608 */
+		0x00000000,	/*  671 -  640 */
+		0x00000000,	/*  703 -  672 */
+		0x00000000,	/*  735 -  704 */
+		0x00000000,	/*  767 -  736 */
+		0x00000000,	/*  799 -  768 */
+		0x00000000,	/*  831 -  800 */
+		0x00000000,	/*  863 -  832 */
+		0x00000000,	/*  895 -  864 */
+		0x00000000,	/*  927 -  896 */
+		0x00000000,	/*  959 -  928 */
+		0x00000000,	/*  991 -  960 */
+		0x00000000,	/* 1023 -  992 */
+		0x00000000,	/* 1055 - 1024 */
+		0x00000000,	/* 1087 - 1056 */
+		0x00000000,	/* 1119 - 1088 */
+		0x00000000,	/* 1151 - 1120 */
+		0x00000000,	/* 1183 - 1152 */
+		0x00000000,	/* 1215 - 1184 */
+		0x00000000,	/* 1247 - 1216 */
+		0x00000000,	/* 1279 - 1248 */
+		0x00000000,	/* 1311 - 1280 */
+		0x00000000,	/* 1343 - 1312 */
+		0x00000000,	/* 1375 - 1344 */
+		0x00000000,	/* 1407 - 1376 */
+		0x00000000,	/* 1439 - 1408 */
+		0x00000000,	/* 1471 - 1440 */
+		0x00000000,	/* 1503 - 1472 */
+	};
+
+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+		return;
+	}
+
+	disable_ptr = iwl_legacy_read_targ_mem(priv, base + (4 * sizeof(u32)));
+	array_size = iwl_legacy_read_targ_mem(priv, base + (5 * sizeof(u32)));
+
+	if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
+		IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n",
+			       disable_ptr);
+		for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
+			iwl_legacy_write_targ_mem(priv,
+					   disable_ptr + (i * sizeof(u32)),
+					   evt_disable[i]);
+
+	} else {
+		IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n");
+		IWL_DEBUG_INFO(priv, "  by writing \"1\"s into disable bitmap\n");
+		IWL_DEBUG_INFO(priv, "  in SRAM at 0x%x, size %d u32s\n",
+			       disable_ptr, array_size);
+	}
+
+}
+
+static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
+{
+	int idx;
+
+	for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++)
+		if (iwl3945_rates[idx].plcp == plcp)
+			return idx;
+	return -1;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
+
+static const char *iwl3945_get_tx_fail_reason(u32 status)
+{
+	switch (status & TX_STATUS_MSK) {
+	case TX_3945_STATUS_SUCCESS:
+		return "SUCCESS";
+		TX_STATUS_ENTRY(SHORT_LIMIT);
+		TX_STATUS_ENTRY(LONG_LIMIT);
+		TX_STATUS_ENTRY(FIFO_UNDERRUN);
+		TX_STATUS_ENTRY(MGMNT_ABORT);
+		TX_STATUS_ENTRY(NEXT_FRAG);
+		TX_STATUS_ENTRY(LIFE_EXPIRE);
+		TX_STATUS_ENTRY(DEST_PS);
+		TX_STATUS_ENTRY(ABORTED);
+		TX_STATUS_ENTRY(BT_RETRY);
+		TX_STATUS_ENTRY(STA_INVALID);
+		TX_STATUS_ENTRY(FRAG_DROPPED);
+		TX_STATUS_ENTRY(TID_DISABLE);
+		TX_STATUS_ENTRY(FRAME_FLUSHED);
+		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
+		TX_STATUS_ENTRY(TX_LOCKED);
+		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
+	}
+
+	return "UNKNOWN";
+}
+#else
+static inline const char *iwl3945_get_tx_fail_reason(u32 status)
+{
+	return "";
+}
+#endif
+
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
+{
+	int next_rate = iwl3945_get_prev_ieee_rate(rate);
+
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
+		if (rate == IWL_RATE_12M_INDEX)
+			next_rate = IWL_RATE_9M_INDEX;
+		else if (rate == IWL_RATE_6M_INDEX)
+			next_rate = IWL_RATE_6M_INDEX;
+		break;
+	case IEEE80211_BAND_2GHZ:
+		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+		    iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+			if (rate == IWL_RATE_11M_INDEX)
+				next_rate = IWL_RATE_5M_INDEX;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return next_rate;
+}
+
+
+/**
+ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
+				     int txq_id, int index)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_tx_info *tx_info;
+
+	BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
+
+	for (index = iwl_legacy_queue_inc_wrap(index, q->n_bd);
+		q->read_ptr != index;
+		q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		tx_info = &txq->txb[txq->q.read_ptr];
+		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
+		tx_info->skb = NULL;
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+	}
+
+	if (iwl_legacy_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+			(txq_id != IWL39_CMD_QUEUE_NUM) &&
+			priv->mac80211_registered)
+		iwl_legacy_wake_queue(priv, txq);
+}
+
+/**
+ * iwl3945_rx_reply_tx - Handle Tx response
+ */
+static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct ieee80211_tx_info *info;
+	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	u32  status = le32_to_cpu(tx_resp->status);
+	int rate_idx;
+	int fail;
+
+	if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
+			  "is out of range [0-%d] %d %d\n", txq_id,
+			  index, txq->q.n_bd, txq->q.write_ptr,
+			  txq->q.read_ptr);
+		return;
+	}
+
+	txq->time_stamp = jiffies;
+	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+	ieee80211_tx_info_clear_status(info);
+
+	/* Fill the MRR chain with some info about on-chip retransmissions */
+	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
+	if (info->band == IEEE80211_BAND_5GHZ)
+		rate_idx -= IWL_FIRST_OFDM_RATE;
+
+	fail = tx_resp->failure_frame;
+
+	info->status.rates[0].idx = rate_idx;
+	info->status.rates[0].count = fail + 1; /* add final attempt */
+
+	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
+	info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
+				IEEE80211_TX_STAT_ACK : 0;
+
+	IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
+			txq_id, iwl3945_get_tx_fail_reason(status), status,
+			tx_resp->rate, tx_resp->failure_frame);
+
+	IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
+	iwl3945_tx_queue_reclaim(priv, txq_id, index);
+
+	if (status & TX_ABORT_REQUIRED_MSK)
+		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
+}
+
+
+
+/*****************************************************************************
+ *
+ * Intel PRO/Wireless 3945ABG/BG Network Connection
+ *
+ *  RX handler implementations
+ *
+ *****************************************************************************/
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
+					    __le32 *stats)
+{
+	int i;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+
+	prev_stats = (__le32 *)&priv->_3945.statistics;
+	accum_stats = (u32 *)&priv->_3945.accum_statistics;
+	delta = (u32 *)&priv->_3945.delta_statistics;
+	max_delta = (u32 *)&priv->_3945.max_delta;
+
+	for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
+		}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	priv->_3945.accum_statistics.general.temperature =
+		priv->_3945.statistics.general.temperature;
+	priv->_3945.accum_statistics.general.ttl_timestamp =
+		priv->_3945.statistics.general.ttl_timestamp;
+}
+#endif
+
+void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+		struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
+		     (int)sizeof(struct iwl3945_notif_statistics),
+		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
+#endif
+	iwl_legacy_recover_from_statistics(priv, pkt);
+
+	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
+}
+
+void iwl3945_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	__le32 *flag = (__le32 *)&pkt->u.raw;
+
+	if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+		memset(&priv->_3945.accum_statistics, 0,
+			sizeof(struct iwl3945_notif_statistics));
+		memset(&priv->_3945.delta_statistics, 0,
+			sizeof(struct iwl3945_notif_statistics));
+		memset(&priv->_3945.max_delta, 0,
+			sizeof(struct iwl3945_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl3945_hw_rx_statistics(priv, rxb);
+}
+
+
+/******************************************************************************
+ *
+ * Misc. internal state and helper functions
+ *
+ ******************************************************************************/
+
+/* This is necessary only for a number of statistics, see the caller. */
+static int iwl3945_is_network_packet(struct iwl_priv *priv,
+		struct ieee80211_hdr *header)
+{
+	/* Filter incoming packets to determine if they are targeted toward
+	 * this network, discarding packets coming from ourselves */
+	switch (priv->iw_mode) {
+	case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source    | BSSID */
+		/* packets to our IBSS update information */
+		return !compare_ether_addr(header->addr3, priv->bssid);
+	case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
+		/* packets to our IBSS update information */
+		return !compare_ether_addr(header->addr2, priv->bssid);
+	default:
+		return 1;
+	}
+}
+
+static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
+				   struct iwl_rx_mem_buffer *rxb,
+				   struct ieee80211_rx_status *stats)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
+	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+	u16 len = le16_to_cpu(rx_hdr->len);
+	struct sk_buff *skb;
+	__le16 fc = hdr->frame_control;
+
+	/* We received data from the HW, so stop the watchdog */
+	if (unlikely(len + IWL39_RX_FRAME_SIZE >
+		     PAGE_SIZE << priv->hw_params.rx_page_order)) {
+		IWL_DEBUG_DROP(priv, "Corruption detected!\n");
+		return;
+	}
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!priv->is_open)) {
+		IWL_DEBUG_DROP_LIMIT(priv,
+			"Dropping packet while interface is not open.\n");
+		return;
+	}
+
+	skb = dev_alloc_skb(128);
+	if (!skb) {
+		IWL_ERR(priv, "dev_alloc_skb failed\n");
+		return;
+	}
+
+	if (!iwl3945_mod_params.sw_crypto)
+		iwl_legacy_set_decrypted_flag(priv,
+				       (struct ieee80211_hdr *)rxb_addr(rxb),
+				       le32_to_cpu(rx_end->status), stats);
+
+	skb_add_rx_frag(skb, 0, rxb->page,
+			(void *)rx_hdr->payload - (void *)pkt, len);
+
+	iwl_legacy_update_stats(priv, false, fc, len);
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+	ieee80211_rx(priv->hw, skb);
+	priv->alloc_rxb_page--;
+	rxb->page = NULL;
+}
+
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
+static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct ieee80211_hdr *header;
+	struct ieee80211_rx_status rx_status;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+	u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
+	u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
+	u8 network_packet;
+
+	rx_status.flag = 0;
+	rx_status.mactime = le64_to_cpu(rx_end->timestamp);
+	rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	rx_status.freq =
+		ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
+					       rx_status.band);
+
+	rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
+	if (rx_status.band == IEEE80211_BAND_5GHZ)
+		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
+
+	rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
+					RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+
+	/* set the preamble flag if appropriate */
+	if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+		rx_status.flag |= RX_FLAG_SHORTPRE;
+
+	if ((unlikely(rx_stats->phy_count > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				rx_stats->phy_count);
+		return;
+	}
+
+	if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR)
+	    || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
+		return;
+	}
+
+
+
+	/* Convert 3945's rssi indicator to dBm */
+	rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
+
+	IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
+			rx_status.signal, rx_stats_sig_avg,
+			rx_stats_noise_diff);
+
+	header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
+
+	network_packet = iwl3945_is_network_packet(priv, header);
+
+	IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
+			      network_packet ? '*' : ' ',
+			      le16_to_cpu(rx_hdr->channel),
+			      rx_status.signal, rx_status.signal,
+			      rx_status.rate_idx);
+
+	iwl_legacy_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len),
+						header);
+
+	if (network_packet) {
+		priv->_3945.last_beacon_time =
+			le32_to_cpu(rx_end->beacon_timestamp);
+		priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
+		priv->_3945.last_rx_rssi = rx_status.signal;
+	}
+
+	iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
+}
+
+int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				     struct iwl_tx_queue *txq,
+				     dma_addr_t addr, u16 len, u8 reset, u8 pad)
+{
+	int count;
+	struct iwl_queue *q;
+	struct iwl3945_tfd *tfd, *tfd_tmp;
+
+	q = &txq->q;
+	tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
+	tfd = &tfd_tmp[q->write_ptr];
+
+	if (reset)
+		memset(tfd, 0, sizeof(*tfd));
+
+	count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
+
+	if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
+		IWL_ERR(priv, "Error can not send more than %d chunks\n",
+			  NUM_TFD_CHUNKS);
+		return -EINVAL;
+	}
+
+	tfd->tbs[count].addr = cpu_to_le32(addr);
+	tfd->tbs[count].len = cpu_to_le32(len);
+
+	count++;
+
+	tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) |
+					 TFD_CTL_PAD_SET(pad));
+
+	return 0;
+}
+
+/**
+ * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr]
+ *
+ * Does NOT advance any indexes
+ */
+void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
+	int index = txq->q.read_ptr;
+	struct iwl3945_tfd *tfd = &tfd_tmp[index];
+	struct pci_dev *dev = priv->pci_dev;
+	int i;
+	int counter;
+
+	/* sanity check */
+	counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
+	if (counter > NUM_TFD_CHUNKS) {
+		IWL_ERR(priv, "Too many chunks: %i\n", counter);
+		/* @todo issue fatal error, it is quite serious situation */
+		return;
+	}
+
+	/* Unmap tx_cmd */
+	if (counter)
+		pci_unmap_single(dev,
+				dma_unmap_addr(&txq->meta[index], mapping),
+				dma_unmap_len(&txq->meta[index], len),
+				PCI_DMA_TODEVICE);
+
+	/* unmap chunks if any */
+
+	for (i = 1; i < counter; i++)
+		pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
+			 le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
+
+	/* free SKB */
+	if (txq->txb) {
+		struct sk_buff *skb;
+
+		skb = txq->txb[txq->q.read_ptr].skb;
+
+		/* can be called from irqs-disabled context */
+		if (skb) {
+			dev_kfree_skb_any(skb);
+			txq->txb[txq->q.read_ptr].skb = NULL;
+		}
+	}
+}
+
+/**
+ * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
+ *
+*/
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+				  struct iwl_device_cmd *cmd,
+				  struct ieee80211_tx_info *info,
+				  struct ieee80211_hdr *hdr,
+				  int sta_id, int tx_id)
+{
+	u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
+	u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945);
+	u16 rate_mask;
+	int rate;
+	u8 rts_retry_limit;
+	u8 data_retry_limit;
+	__le32 tx_flags;
+	__le16 fc = hdr->frame_control;
+	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+
+	rate = iwl3945_rates[rate_index].plcp;
+	tx_flags = tx_cmd->tx_flags;
+
+	/* We need to figure out how to get the sta->supp_rates while
+	 * in this running context */
+	rate_mask = IWL_RATES_MASK_3945;
+
+	/* Set retry limit on DATA packets and Probe Responses*/
+	if (ieee80211_is_probe_resp(fc))
+		data_retry_limit = 3;
+	else
+		data_retry_limit = IWL_DEFAULT_TX_RETRY;
+	tx_cmd->data_retry_limit = data_retry_limit;
+
+	if (tx_id >= IWL39_CMD_QUEUE_NUM)
+		rts_retry_limit = 3;
+	else
+		rts_retry_limit = 7;
+
+	if (data_retry_limit < rts_retry_limit)
+		rts_retry_limit = data_retry_limit;
+	tx_cmd->rts_retry_limit = rts_retry_limit;
+
+	tx_cmd->rate = rate;
+	tx_cmd->tx_flags = tx_flags;
+
+	/* OFDM */
+	tx_cmd->supp_rates[0] =
+	   ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
+
+	/* CCK */
+	tx_cmd->supp_rates[1] = (rate_mask & 0xF);
+
+	IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
+		       "cck/ofdm mask: 0x%x/0x%x\n", sta_id,
+		       tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags),
+		       tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
+}
+
+static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
+{
+	unsigned long flags_spin;
+	struct iwl_station_entry *station;
+
+	if (sta_id == IWL_INVALID_STATION)
+		return IWL_INVALID_STATION;
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	station = &priv->stations[sta_id];
+
+	station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
+	station->sta.rate_n_flags = cpu_to_le16(tx_rate);
+	station->sta.mode = STA_CONTROL_MODIFY_MSK;
+	iwl_legacy_send_add_sta(priv, &station->sta, CMD_ASYNC);
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
+			sta_id, tx_rate);
+	return sta_id;
+}
+
+static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do
+
+		if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
+			iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+					~APMG_PS_CTRL_MSK_PWR_SRC);
+
+			iwl_poll_bit(priv, CSR_GPIO_IN,
+				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
+				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
+		}
+ */
+
+	iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			~APMG_PS_CTRL_MSK_PWR_SRC);
+
+	iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
+		     CSR_GPIO_IN_BIT_AUX_POWER, 5000);	/* uS */
+}
+
+static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	iwl_legacy_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
+	iwl_legacy_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0),
+					rxq->rb_stts_dma);
+	iwl_legacy_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
+	iwl_legacy_write_direct32(priv, FH39_RCSR_CONFIG(0),
+		FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
+		FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
+		FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
+		FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
+		(RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
+		FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
+		(1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
+		FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
+
+	/* fake read to flush all prev I/O */
+	iwl_legacy_read_direct32(priv, FH39_RSSR_CTRL);
+
+	return 0;
+}
+
+static int iwl3945_tx_reset(struct iwl_priv *priv)
+{
+
+	/* bypass mode */
+	iwl_legacy_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
+
+	/* RA 0 is active */
+	iwl_legacy_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
+
+	/* all 6 fifo are active */
+	iwl_legacy_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
+
+	iwl_legacy_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
+	iwl_legacy_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
+	iwl_legacy_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
+	iwl_legacy_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
+
+	iwl_legacy_write_direct32(priv, FH39_TSSR_CBB_BASE,
+			     priv->_3945.shared_phys);
+
+	iwl_legacy_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
+
+
+	return 0;
+}
+
+/**
+ * iwl3945_txq_ctx_reset - Reset TX queue context
+ *
+ * Destroys all DMA structures and initialize them again
+ */
+static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
+{
+	int rc;
+	int txq_id, slots_num;
+
+	iwl3945_hw_txq_ctx_free(priv);
+
+	/* allocate tx queue structure */
+	rc = iwl_legacy_alloc_txq_mem(priv);
+	if (rc)
+		return rc;
+
+	/* Tx CMD queue */
+	rc = iwl3945_tx_reset(priv);
+	if (rc)
+		goto error;
+
+	/* Tx queue(s) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
+				TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		rc = iwl_legacy_tx_queue_init(priv, &priv->txq[txq_id],
+						slots_num, txq_id);
+		if (rc) {
+			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return rc;
+
+ error:
+	iwl3945_hw_txq_ctx_free(priv);
+	return rc;
+}
+
+
+/*
+ * Start up 3945's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via iwl_legacy_apm_stop())
+ * NOTE:  This does not load uCode nor start the embedded processor
+ */
+static int iwl3945_apm_init(struct iwl_priv *priv)
+{
+	int ret = iwl_legacy_apm_init(priv);
+
+	/* Clear APMG (NIC's internal power management) interrupts */
+	iwl_legacy_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
+	iwl_legacy_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
+
+	/* Reset radio chip */
+	iwl_legacy_set_bits_prph(priv, APMG_PS_CTRL_REG,
+				APMG_PS_CTRL_VAL_RESET_REQ);
+	udelay(5);
+	iwl_legacy_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+				APMG_PS_CTRL_VAL_RESET_REQ);
+
+	return ret;
+}
+
+static void iwl3945_nic_config(struct iwl_priv *priv)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	unsigned long flags;
+	u8 rev_id = priv->pci_dev->revision;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Determine HW type */
+	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
+
+	if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
+		IWL_DEBUG_INFO(priv, "RTP type\n");
+	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
+		IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
+	} else {
+		IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n");
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
+	}
+
+	if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
+		IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n");
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
+	} else
+		IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n");
+
+	if ((eeprom->board_revision & 0xF0) == 0xD0) {
+		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
+			       eeprom->board_revision);
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+	} else {
+		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
+			       eeprom->board_revision);
+		iwl_legacy_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+			      CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+	}
+
+	if (eeprom->almgor_m_version <= 1) {
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
+		IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n",
+			       eeprom->almgor_m_version);
+	} else {
+		IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n",
+			       eeprom->almgor_m_version);
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
+		IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n");
+
+	if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
+		IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n");
+}
+
+int iwl3945_hw_nic_init(struct iwl_priv *priv)
+{
+	int rc;
+	unsigned long flags;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->cfg->ops->lib->apm_ops.init(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl3945_set_pwr_vmain(priv);
+
+	priv->cfg->ops->lib->apm_ops.config(priv);
+
+	/* Allocate the RX queue, or reset if it is already allocated */
+	if (!rxq->bd) {
+		rc = iwl_legacy_rx_queue_alloc(priv);
+		if (rc) {
+			IWL_ERR(priv, "Unable to initialize Rx queue\n");
+			return -ENOMEM;
+		}
+	} else
+		iwl3945_rx_queue_reset(priv, rxq);
+
+	iwl3945_rx_replenish(priv);
+
+	iwl3945_rx_init(priv, rxq);
+
+
+	/* Look at using this instead:
+	rxq->need_update = 1;
+	iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+	*/
+
+	iwl_legacy_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
+
+	rc = iwl3945_txq_ctx_reset(priv);
+	if (rc)
+		return rc;
+
+	set_bit(STATUS_INIT, &priv->status);
+
+	return 0;
+}
+
+/**
+ * iwl3945_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* Tx queues */
+	if (priv->txq)
+		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
+		     txq_id++)
+			if (txq_id == IWL39_CMD_QUEUE_NUM)
+				iwl_legacy_cmd_queue_free(priv);
+			else
+				iwl_legacy_tx_queue_free(priv, txq_id);
+
+	/* free tx queue structure */
+	iwl_legacy_txq_mem(priv);
+}
+
+void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* stop SCD */
+	iwl_legacy_write_prph(priv, ALM_SCD_MODE_REG, 0);
+	iwl_legacy_write_prph(priv, ALM_SCD_TXFACT_REG, 0);
+
+	/* reset TFD queues */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		iwl_legacy_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
+		iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
+				FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
+				1000);
+	}
+
+	iwl3945_hw_txq_ctx_free(priv);
+}
+
+/**
+ * iwl3945_hw_reg_adjust_power_by_temp
+ * return index delta into power gain settings table
+*/
+static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
+{
+	return (new_reading - old_reading) * (-11) / 100;
+}
+
+/**
+ * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range
+ */
+static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
+{
+	return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
+}
+
+int iwl3945_hw_get_temperature(struct iwl_priv *priv)
+{
+	return iwl_read32(priv, CSR_UCODE_DRV_GP2);
+}
+
+/**
+ * iwl3945_hw_reg_txpower_get_temperature
+ * get the current temperature by reading from NIC
+*/
+static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	int temperature;
+
+	temperature = iwl3945_hw_get_temperature(priv);
+
+	/* driver's okay range is -260 to +25.
+	 *   human readable okay range is 0 to +285 */
+	IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT);
+
+	/* handle insane temp reading */
+	if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
+		IWL_ERR(priv, "Error bad temperature value  %d\n", temperature);
+
+		/* if really really hot(?),
+		 *   substitute the 3rd band/group's temp measured at factory */
+		if (priv->last_temperature > 100)
+			temperature = eeprom->groups[2].temperature;
+		else /* else use most recent "sane" value from driver */
+			temperature = priv->last_temperature;
+	}
+
+	return temperature;	/* raw, not "human readable" */
+}
+
+/* Adjust Txpower only if temperature variance is greater than threshold.
+ *
+ * Both are lower than older versions' 9 degrees */
+#define IWL_TEMPERATURE_LIMIT_TIMER   6
+
+/**
+ * iwl3945_is_temp_calib_needed - determines if new calibration is needed
+ *
+ * records new temperature in tx_mgr->temperature.
+ * replaces tx_mgr->last_temperature *only* if calib needed
+ *    (assumes caller will actually do the calibration!). */
+static int iwl3945_is_temp_calib_needed(struct iwl_priv *priv)
+{
+	int temp_diff;
+
+	priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
+	temp_diff = priv->temperature - priv->last_temperature;
+
+	/* get absolute value */
+	if (temp_diff < 0) {
+		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff);
+		temp_diff = -temp_diff;
+	} else if (temp_diff == 0)
+		IWL_DEBUG_POWER(priv, "Same temp,\n");
+	else
+		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff);
+
+	/* if we don't need calibration, *don't* update last_temperature */
+	if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) {
+		IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n");
+		return 0;
+	}
+
+	IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n");
+
+	/* assume that caller will actually do calib ...
+	 *   update the "last temperature" value */
+	priv->last_temperature = priv->temperature;
+	return 1;
+}
+
+#define IWL_MAX_GAIN_ENTRIES 78
+#define IWL_CCK_FROM_OFDM_POWER_DIFF  -5
+#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10)
+
+/* radio and DSP power table, each step is 1/2 dB.
+ * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
+static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
+	{
+	 {251, 127},		/* 2.4 GHz, highest power */
+	 {251, 127},
+	 {251, 127},
+	 {251, 127},
+	 {251, 125},
+	 {251, 110},
+	 {251, 105},
+	 {251, 98},
+	 {187, 125},
+	 {187, 115},
+	 {187, 108},
+	 {187, 99},
+	 {243, 119},
+	 {243, 111},
+	 {243, 105},
+	 {243, 97},
+	 {243, 92},
+	 {211, 106},
+	 {211, 100},
+	 {179, 120},
+	 {179, 113},
+	 {179, 107},
+	 {147, 125},
+	 {147, 119},
+	 {147, 112},
+	 {147, 106},
+	 {147, 101},
+	 {147, 97},
+	 {147, 91},
+	 {115, 107},
+	 {235, 121},
+	 {235, 115},
+	 {235, 109},
+	 {203, 127},
+	 {203, 121},
+	 {203, 115},
+	 {203, 108},
+	 {203, 102},
+	 {203, 96},
+	 {203, 92},
+	 {171, 110},
+	 {171, 104},
+	 {171, 98},
+	 {139, 116},
+	 {227, 125},
+	 {227, 119},
+	 {227, 113},
+	 {227, 107},
+	 {227, 101},
+	 {227, 96},
+	 {195, 113},
+	 {195, 106},
+	 {195, 102},
+	 {195, 95},
+	 {163, 113},
+	 {163, 106},
+	 {163, 102},
+	 {163, 95},
+	 {131, 113},
+	 {131, 106},
+	 {131, 102},
+	 {131, 95},
+	 {99, 113},
+	 {99, 106},
+	 {99, 102},
+	 {99, 95},
+	 {67, 113},
+	 {67, 106},
+	 {67, 102},
+	 {67, 95},
+	 {35, 113},
+	 {35, 106},
+	 {35, 102},
+	 {35, 95},
+	 {3, 113},
+	 {3, 106},
+	 {3, 102},
+	 {3, 95} },		/* 2.4 GHz, lowest power */
+	{
+	 {251, 127},		/* 5.x GHz, highest power */
+	 {251, 120},
+	 {251, 114},
+	 {219, 119},
+	 {219, 101},
+	 {187, 113},
+	 {187, 102},
+	 {155, 114},
+	 {155, 103},
+	 {123, 117},
+	 {123, 107},
+	 {123, 99},
+	 {123, 92},
+	 {91, 108},
+	 {59, 125},
+	 {59, 118},
+	 {59, 109},
+	 {59, 102},
+	 {59, 96},
+	 {59, 90},
+	 {27, 104},
+	 {27, 98},
+	 {27, 92},
+	 {115, 118},
+	 {115, 111},
+	 {115, 104},
+	 {83, 126},
+	 {83, 121},
+	 {83, 113},
+	 {83, 105},
+	 {83, 99},
+	 {51, 118},
+	 {51, 111},
+	 {51, 104},
+	 {51, 98},
+	 {19, 116},
+	 {19, 109},
+	 {19, 102},
+	 {19, 98},
+	 {19, 93},
+	 {171, 113},
+	 {171, 107},
+	 {171, 99},
+	 {139, 120},
+	 {139, 113},
+	 {139, 107},
+	 {139, 99},
+	 {107, 120},
+	 {107, 113},
+	 {107, 107},
+	 {107, 99},
+	 {75, 120},
+	 {75, 113},
+	 {75, 107},
+	 {75, 99},
+	 {43, 120},
+	 {43, 113},
+	 {43, 107},
+	 {43, 99},
+	 {11, 120},
+	 {11, 113},
+	 {11, 107},
+	 {11, 99},
+	 {131, 107},
+	 {131, 99},
+	 {99, 120},
+	 {99, 113},
+	 {99, 107},
+	 {99, 99},
+	 {67, 120},
+	 {67, 113},
+	 {67, 107},
+	 {67, 99},
+	 {35, 120},
+	 {35, 113},
+	 {35, 107},
+	 {35, 99},
+	 {3, 120} }		/* 5.x GHz, lowest power */
+};
+
+static inline u8 iwl3945_hw_reg_fix_power_index(int index)
+{
+	if (index < 0)
+		return 0;
+	if (index >= IWL_MAX_GAIN_ENTRIES)
+		return IWL_MAX_GAIN_ENTRIES - 1;
+	return (u8) index;
+}
+
+/* Kick off thermal recalibration check every 60 seconds */
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
+ *
+ * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
+ * or 6 Mbit (OFDM) rates.
+ */
+static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
+			       s32 rate_index, const s8 *clip_pwrs,
+			       struct iwl_channel_info *ch_info,
+			       int band_index)
+{
+	struct iwl3945_scan_power_info *scan_power_info;
+	s8 power;
+	u8 power_index;
+
+	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index];
+
+	/* use this channel group's 6Mbit clipping/saturation pwr,
+	 *   but cap at regulatory scan power restriction (set during init
+	 *   based on eeprom channel data) for this channel.  */
+	power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
+
+	power = min(power, priv->tx_power_user_lmt);
+	scan_power_info->requested_power = power;
+
+	/* find difference between new scan *power* and current "normal"
+	 *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
+	 *   current "normal" temperature-compensated Tx power *index* for
+	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
+	 *   *index*. */
+	power_index = ch_info->power_info[rate_index].power_table_index
+	    - (power - ch_info->power_info
+	       [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
+
+	/* store reference index that we use when adjusting *all* scan
+	 *   powers.  So we can accommodate user (all channel) or spectrum
+	 *   management (single channel) power changes "between" temperature
+	 *   feedback compensation procedures.
+	 * don't force fit this reference index into gain table; it may be a
+	 *   negative number.  This will help avoid errors when we're at
+	 *   the lower bounds (highest gains, for warmest temperatures)
+	 *   of the table. */
+
+	/* don't exceed table bounds for "real" setting */
+	power_index = iwl3945_hw_reg_fix_power_index(power_index);
+
+	scan_power_info->power_table_index = power_index;
+	scan_power_info->tpc.tx_gain =
+	    power_gain_table[band_index][power_index].tx_gain;
+	scan_power_info->tpc.dsp_atten =
+	    power_gain_table[band_index][power_index].dsp_atten;
+}
+
+/**
+ * iwl3945_send_tx_power - fill in Tx Power command with gain settings
+ *
+ * Configures power settings for all rates for the current channel,
+ * using values from channel info struct, and send to NIC
+ */
+static int iwl3945_send_tx_power(struct iwl_priv *priv)
+{
+	int rate_idx, i;
+	const struct iwl_channel_info *ch_info = NULL;
+	struct iwl3945_txpowertable_cmd txpower = {
+		.channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
+	};
+	u16 chan;
+
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
+	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
+
+	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band, chan);
+	if (!ch_info) {
+		IWL_ERR(priv,
+			"Failed to get channel info for channel %d [%d]\n",
+			chan, priv->band);
+		return -EINVAL;
+	}
+
+	if (!iwl_legacy_is_channel_valid(ch_info)) {
+		IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on "
+				"non-Tx channel.\n");
+		return 0;
+	}
+
+	/* fill cmd with power settings for all rates for current channel */
+	/* Fill OFDM rate */
+	for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
+	     rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) {
+
+		txpower.power[i].tpc = ch_info->power_info[i].tpc;
+		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
+
+		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+				le16_to_cpu(txpower.channel),
+				txpower.band,
+				txpower.power[i].tpc.tx_gain,
+				txpower.power[i].tpc.dsp_atten,
+				txpower.power[i].rate);
+	}
+	/* Fill CCK rates */
+	for (rate_idx = IWL_FIRST_CCK_RATE;
+	     rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
+		txpower.power[i].tpc = ch_info->power_info[i].tpc;
+		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
+
+		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+				le16_to_cpu(txpower.channel),
+				txpower.band,
+				txpower.power[i].tpc.tx_gain,
+				txpower.power[i].tpc.dsp_atten,
+				txpower.power[i].rate);
+	}
+
+	return iwl_legacy_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
+				sizeof(struct iwl3945_txpowertable_cmd),
+				&txpower);
+
+}
+
+/**
+ * iwl3945_hw_reg_set_new_power - Configures power tables at new levels
+ * @ch_info: Channel to update.  Uses power_info.requested_power.
+ *
+ * Replace requested_power and base_power_index ch_info fields for
+ * one channel.
+ *
+ * Called if user or spectrum management changes power preferences.
+ * Takes into account h/w and modulation limitations (clip power).
+ *
+ * This does *not* send anything to NIC, just sets up ch_info for one channel.
+ *
+ * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
+ *	 properly fill out the scan powers, and actual h/w gain settings,
+ *	 and send changes to NIC
+ */
+static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
+			     struct iwl_channel_info *ch_info)
+{
+	struct iwl3945_channel_power_info *power_info;
+	int power_changed = 0;
+	int i;
+	const s8 *clip_pwrs;
+	int power;
+
+	/* Get this chnlgrp's rate-to-max/clip-powers table */
+	clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
+
+	/* Get this channel's rate-to-current-power settings table */
+	power_info = ch_info->power_info;
+
+	/* update OFDM Txpower settings */
+	for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
+	     i++, ++power_info) {
+		int delta_idx;
+
+		/* limit new power to be no more than h/w capability */
+		power = min(ch_info->curr_txpow, clip_pwrs[i]);
+		if (power == power_info->requested_power)
+			continue;
+
+		/* find difference between old and new requested powers,
+		 *    update base (non-temp-compensated) power index */
+		delta_idx = (power - power_info->requested_power) * 2;
+		power_info->base_power_index -= delta_idx;
+
+		/* save new requested power value */
+		power_info->requested_power = power;
+
+		power_changed = 1;
+	}
+
+	/* update CCK Txpower settings, based on OFDM 12M setting ...
+	 *    ... all CCK power settings for a given channel are the *same*. */
+	if (power_changed) {
+		power =
+		    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
+		    requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
+
+		/* do all CCK rates' iwl3945_channel_power_info structures */
+		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
+			power_info->requested_power = power;
+			power_info->base_power_index =
+			    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
+			    base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
+			++power_info;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
+ *
+ * NOTE: Returned power limit may be less (but not more) than requested,
+ *	 based strictly on regulatory (eeprom and spectrum mgt) limitations
+ *	 (no consideration for h/w clipping limitations).
+ */
+static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
+{
+	s8 max_power;
+
+#if 0
+	/* if we're using TGd limits, use lower of TGd or EEPROM */
+	if (ch_info->tgd_data.max_power != 0)
+		max_power = min(ch_info->tgd_data.max_power,
+				ch_info->eeprom.max_power_avg);
+
+	/* else just use EEPROM limits */
+	else
+#endif
+		max_power = ch_info->eeprom.max_power_avg;
+
+	return min(max_power, ch_info->max_power_avg);
+}
+
+/**
+ * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature
+ *
+ * Compensate txpower settings of *all* channels for temperature.
+ * This only accounts for the difference between current temperature
+ *   and the factory calibration temperatures, and bases the new settings
+ *   on the channel's base_power_index.
+ *
+ * If RxOn is "associated", this sends the new Txpower to NIC!
+ */
+static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
+{
+	struct iwl_channel_info *ch_info = NULL;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	int delta_index;
+	const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
+	u8 a_band;
+	u8 rate_index;
+	u8 scan_tbl_index;
+	u8 i;
+	int ref_temp;
+	int temperature = priv->temperature;
+
+	if (priv->disable_tx_power_cal ||
+	    test_bit(STATUS_SCANNING, &priv->status)) {
+		/* do not perform tx power calibration */
+		return 0;
+	}
+	/* set up new Tx power info for each and every channel, 2.4 and 5.x */
+	for (i = 0; i < priv->channel_count; i++) {
+		ch_info = &priv->channel_info[i];
+		a_band = iwl_legacy_is_channel_a_band(ch_info);
+
+		/* Get this chnlgrp's factory calibration temperature */
+		ref_temp = (s16)eeprom->groups[ch_info->group_index].
+		    temperature;
+
+		/* get power index adjustment based on current and factory
+		 * temps */
+		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
+							      ref_temp);
+
+		/* set tx power value for all rates, OFDM and CCK */
+		for (rate_index = 0; rate_index < IWL_RATE_COUNT_3945;
+		     rate_index++) {
+			int power_idx =
+			    ch_info->power_info[rate_index].base_power_index;
+
+			/* temperature compensate */
+			power_idx += delta_index;
+
+			/* stay within table range */
+			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
+			ch_info->power_info[rate_index].
+			    power_table_index = (u8) power_idx;
+			ch_info->power_info[rate_index].tpc =
+			    power_gain_table[a_band][power_idx];
+		}
+
+		/* Get this chnlgrp's rate-to-max/clip-powers table */
+		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
+
+		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
+		for (scan_tbl_index = 0;
+		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
+			s32 actual_index = (scan_tbl_index == 0) ?
+			    IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
+			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
+					   actual_index, clip_pwrs,
+					   ch_info, a_band);
+		}
+	}
+
+	/* send Txpower command for current channel to ucode */
+	return priv->cfg->ops->lib->send_tx_power(priv);
+}
+
+int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+{
+	struct iwl_channel_info *ch_info;
+	s8 max_power;
+	u8 a_band;
+	u8 i;
+
+	if (priv->tx_power_user_lmt == power) {
+		IWL_DEBUG_POWER(priv, "Requested Tx power same as current "
+				"limit: %ddBm.\n", power);
+		return 0;
+	}
+
+	IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power);
+	priv->tx_power_user_lmt = power;
+
+	/* set up new Tx powers for each and every channel, 2.4 and 5.x */
+
+	for (i = 0; i < priv->channel_count; i++) {
+		ch_info = &priv->channel_info[i];
+		a_band = iwl_legacy_is_channel_a_band(ch_info);
+
+		/* find minimum power of all user and regulatory constraints
+		 *    (does not consider h/w clipping limitations) */
+		max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info);
+		max_power = min(power, max_power);
+		if (max_power != ch_info->curr_txpow) {
+			ch_info->curr_txpow = max_power;
+
+			/* this considers the h/w clipping limitations */
+			iwl3945_hw_reg_set_new_power(priv, ch_info);
+		}
+	}
+
+	/* update txpower settings for all channels,
+	 *   send to NIC if associated. */
+	iwl3945_is_temp_calib_needed(priv);
+	iwl3945_hw_reg_comp_txpower_temp(priv);
+
+	return 0;
+}
+
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
+{
+	int rc = 0;
+	struct iwl_rx_packet *pkt;
+	struct iwl3945_rxon_assoc_cmd rxon_assoc;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_RXON_ASSOC,
+		.len = sizeof(rxon_assoc),
+		.flags = CMD_WANT_SKB,
+		.data = &rxon_assoc,
+	};
+	const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
+	const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
+
+	if ((rxon1->flags == rxon2->flags) &&
+	    (rxon1->filter_flags == rxon2->filter_flags) &&
+	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
+		return 0;
+	}
+
+	rxon_assoc.flags = ctx->staging.flags;
+	rxon_assoc.filter_flags = ctx->staging.filter_flags;
+	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
+	rxon_assoc.reserved = 0;
+
+	rc = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (rc)
+		return rc;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
+		rc = -EIO;
+	}
+
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return rc;
+}
+
+/**
+ * iwl3945_commit_rxon - commit staging_rxon to hardware
+ *
+ * The RXON command in staging_rxon is committed to the hardware and
+ * the active_rxon structure is updated with the new data.  This
+ * function correctly transitions out of the RXON_ASSOC_MSK state if
+ * a HW tune is required based on the RXON structure changes.
+ */
+int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
+	struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
+	int rc = 0;
+	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EINVAL;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -1;
+
+	/* always get timestamp with Rx frame */
+	staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
+
+	/* select antenna */
+	staging_rxon->flags &=
+	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
+	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
+
+	rc = iwl_legacy_check_rxon_cmd(priv, ctx);
+	if (rc) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		return -EINVAL;
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_legacy_full_rxon_required(priv,
+			&priv->contexts[IWL_RXON_CTX_BSS])) {
+		rc = iwl_legacy_send_rxon_assoc(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+		if (rc) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC "
+				  "configuration (%d).\n", rc);
+			return rc;
+		}
+
+		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+		return 0;
+	}
+
+	/* If we are currently associated and the new config requires
+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
+	 * we must clear the associated from the active configuration
+	 * before we apply the new config */
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		/*
+		 * reserved4 and 5 could have been filled by the iwlcore code.
+		 * Let's clear them before pushing to the 3945.
+		 */
+		active_rxon->reserved4 = 0;
+		active_rxon->reserved5 = 0;
+		rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RXON,
+				      sizeof(struct iwl3945_rxon_cmd),
+				      &priv->contexts[IWL_RXON_CTX_BSS].active);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (rc) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
+				  "configuration (%d).\n", rc);
+			return rc;
+		}
+		iwl_legacy_clear_ucode_stations(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+		iwl_legacy_restore_stations(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+	}
+
+	IWL_DEBUG_INFO(priv, "Sending RXON\n"
+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
+		       "* channel = %d\n"
+		       "* bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(staging_rxon->channel),
+		       staging_rxon->bssid_addr);
+
+	/*
+	 * reserved4 and 5 could have been filled by the iwlcore code.
+	 * Let's clear them before pushing to the 3945.
+	 */
+	staging_rxon->reserved4 = 0;
+	staging_rxon->reserved5 = 0;
+
+	iwl_legacy_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
+
+	/* Apply the new configuration */
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RXON,
+			      sizeof(struct iwl3945_rxon_cmd),
+			      staging_rxon);
+	if (rc) {
+		IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
+		return rc;
+	}
+
+	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+	if (!new_assoc) {
+		iwl_legacy_clear_ucode_stations(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+		iwl_legacy_restore_stations(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
+	}
+
+	/* If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames */
+	rc = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
+	if (rc) {
+		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
+		return rc;
+	}
+
+	/* Init the hardware's rate fallback order based on the band */
+	rc = iwl3945_init_hw_rate_table(priv);
+	if (rc) {
+		IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * iwl3945_reg_txpower_periodic -  called when time to check our temperature.
+ *
+ * -- reset periodic timer
+ * -- see if temp has changed enough to warrant re-calibration ... if so:
+ *     -- correct coeffs for temp (can reset temp timer)
+ *     -- save this temp as "last",
+ *     -- send new set of gain settings to NIC
+ * NOTE:  This should continue working, even when we're not associated,
+ *   so we can keep our internal table of scan powers current. */
+void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
+{
+	/* This will kick in the "brute force"
+	 * iwl3945_hw_reg_comp_txpower_temp() below */
+	if (!iwl3945_is_temp_calib_needed(priv))
+		goto reschedule;
+
+	/* Set up a new set of temp-adjusted TxPowers, send to NIC.
+	 * This is based *only* on current temperature,
+	 * ignoring any previous power measurements */
+	iwl3945_hw_reg_comp_txpower_temp(priv);
+
+ reschedule:
+	queue_delayed_work(priv->workqueue,
+			   &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
+}
+
+static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+					     _3945.thermal_periodic.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_reg_txpower_periodic(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/**
+ * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
+ * 				   for the channel.
+ *
+ * This function is used when initializing channel-info structs.
+ *
+ * NOTE: These channel groups do *NOT* match the bands above!
+ *	 These channel groups are based on factory-tested channels;
+ *	 on A-band, EEPROM's "group frequency" entries represent the top
+ *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0.
+ */
+static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
+				       const struct iwl_channel_info *ch_info)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
+	u8 group;
+	u16 group_index = 0;	/* based on factory calib frequencies */
+	u8 grp_channel;
+
+	/* Find the group index for the channel ... don't use index 1(?) */
+	if (iwl_legacy_is_channel_a_band(ch_info)) {
+		for (group = 1; group < 5; group++) {
+			grp_channel = ch_grp[group].group_channel;
+			if (ch_info->channel <= grp_channel) {
+				group_index = group;
+				break;
+			}
+		}
+		/* group 4 has a few channels *above* its factory cal freq */
+		if (group == 5)
+			group_index = 4;
+	} else
+		group_index = 0;	/* 2.4 GHz, group 0 */
+
+	IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel,
+			group_index);
+	return group_index;
+}
+
+/**
+ * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index
+ *
+ * Interpolate to get nominal (i.e. at factory calibration temperature) index
+ *   into radio/DSP gain settings table for requested power.
+ */
+static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv,
+				       s8 requested_power,
+				       s32 setting_index, s32 *new_index)
+{
+	const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	s32 index0, index1;
+	s32 power = 2 * requested_power;
+	s32 i;
+	const struct iwl3945_eeprom_txpower_sample *samples;
+	s32 gains0, gains1;
+	s32 res;
+	s32 denominator;
+
+	chnl_grp = &eeprom->groups[setting_index];
+	samples = chnl_grp->samples;
+	for (i = 0; i < 5; i++) {
+		if (power == samples[i].power) {
+			*new_index = samples[i].gain_index;
+			return 0;
+		}
+	}
+
+	if (power > samples[1].power) {
+		index0 = 0;
+		index1 = 1;
+	} else if (power > samples[2].power) {
+		index0 = 1;
+		index1 = 2;
+	} else if (power > samples[3].power) {
+		index0 = 2;
+		index1 = 3;
+	} else {
+		index0 = 3;
+		index1 = 4;
+	}
+
+	denominator = (s32) samples[index1].power - (s32) samples[index0].power;
+	if (denominator == 0)
+		return -EINVAL;
+	gains0 = (s32) samples[index0].gain_index * (1 << 19);
+	gains1 = (s32) samples[index1].gain_index * (1 << 19);
+	res = gains0 + (gains1 - gains0) *
+	    ((s32) power - (s32) samples[index0].power) / denominator +
+	    (1 << 18);
+	*new_index = res >> 19;
+	return 0;
+}
+
+static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
+{
+	u32 i;
+	s32 rate_index;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	const struct iwl3945_eeprom_txpower_group *group;
+
+	IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n");
+
+	for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {
+		s8 *clip_pwrs;	/* table of power levels for each rate */
+		s8 satur_pwr;	/* saturation power for each chnl group */
+		group = &eeprom->groups[i];
+
+		/* sanity check on factory saturation power value */
+		if (group->saturation_power < 40) {
+			IWL_WARN(priv, "Error: saturation power is %d, "
+				    "less than minimum expected 40\n",
+				    group->saturation_power);
+			return;
+		}
+
+		/*
+		 * Derive requested power levels for each rate, based on
+		 *   hardware capabilities (saturation power for band).
+		 * Basic value is 3dB down from saturation, with further
+		 *   power reductions for highest 3 data rates.  These
+		 *   backoffs provide headroom for high rate modulation
+		 *   power peaks, without too much distortion (clipping).
+		 */
+		/* we'll fill in this array with h/w max power levels */
+		clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
+
+		/* divide factory saturation power by 2 to find -3dB level */
+		satur_pwr = (s8) (group->saturation_power >> 1);
+
+		/* fill in channel group's nominal powers for each rate */
+		for (rate_index = 0;
+		     rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) {
+			switch (rate_index) {
+			case IWL_RATE_36M_INDEX_TABLE:
+				if (i == 0)	/* B/G */
+					*clip_pwrs = satur_pwr;
+				else	/* A */
+					*clip_pwrs = satur_pwr - 5;
+				break;
+			case IWL_RATE_48M_INDEX_TABLE:
+				if (i == 0)
+					*clip_pwrs = satur_pwr - 7;
+				else
+					*clip_pwrs = satur_pwr - 10;
+				break;
+			case IWL_RATE_54M_INDEX_TABLE:
+				if (i == 0)
+					*clip_pwrs = satur_pwr - 9;
+				else
+					*clip_pwrs = satur_pwr - 12;
+				break;
+			default:
+				*clip_pwrs = satur_pwr;
+				break;
+			}
+		}
+	}
+}
+
+/**
+ * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
+ *
+ * Second pass (during init) to set up priv->channel_info
+ *
+ * Set up Tx-power settings in our channel info database for each VALID
+ * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
+ * and current temperature.
+ *
+ * Since this is based on current temperature (at init time), these values may
+ * not be valid for very long, but it gives us a starting/default point,
+ * and allows us to active (i.e. using Tx) scan.
+ *
+ * This does *not* write values to NIC, just sets up our internal table.
+ */
+int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+{
+	struct iwl_channel_info *ch_info = NULL;
+	struct iwl3945_channel_power_info *pwr_info;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	int delta_index;
+	u8 rate_index;
+	u8 scan_tbl_index;
+	const s8 *clip_pwrs;	/* array of power levels for each rate */
+	u8 gain, dsp_atten;
+	s8 power;
+	u8 pwr_index, base_pwr_index, a_band;
+	u8 i;
+	int temperature;
+
+	/* save temperature reference,
+	 *   so we can determine next time to calibrate */
+	temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
+	priv->last_temperature = temperature;
+
+	iwl3945_hw_reg_init_channel_groups(priv);
+
+	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
+	for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
+	     i++, ch_info++) {
+		a_band = iwl_legacy_is_channel_a_band(ch_info);
+		if (!iwl_legacy_is_channel_valid(ch_info))
+			continue;
+
+		/* find this channel's channel group (*not* "band") index */
+		ch_info->group_index =
+			iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
+
+		/* Get this chnlgrp's rate->max/clip-powers table */
+		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
+
+		/* calculate power index *adjustment* value according to
+		 *  diff between current temperature and factory temperature */
+		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
+				eeprom->groups[ch_info->group_index].
+				temperature);
+
+		IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n",
+				ch_info->channel, delta_index, temperature +
+				IWL_TEMP_CONVERT);
+
+		/* set tx power value for all OFDM rates */
+		for (rate_index = 0; rate_index < IWL_OFDM_RATES;
+		     rate_index++) {
+			s32 uninitialized_var(power_idx);
+			int rc;
+
+			/* use channel group's clip-power table,
+			 *   but don't exceed channel's max power */
+			s8 pwr = min(ch_info->max_power_avg,
+				     clip_pwrs[rate_index]);
+
+			pwr_info = &ch_info->power_info[rate_index];
+
+			/* get base (i.e. at factory-measured temperature)
+			 *    power table index for this rate's power */
+			rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr,
+							 ch_info->group_index,
+							 &power_idx);
+			if (rc) {
+				IWL_ERR(priv, "Invalid power index\n");
+				return rc;
+			}
+			pwr_info->base_power_index = (u8) power_idx;
+
+			/* temperature compensate */
+			power_idx += delta_index;
+
+			/* stay within range of gain table */
+			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
+
+			/* fill 1 OFDM rate's iwl3945_channel_power_info struct */
+			pwr_info->requested_power = pwr;
+			pwr_info->power_table_index = (u8) power_idx;
+			pwr_info->tpc.tx_gain =
+			    power_gain_table[a_band][power_idx].tx_gain;
+			pwr_info->tpc.dsp_atten =
+			    power_gain_table[a_band][power_idx].dsp_atten;
+		}
+
+		/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
+		pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
+		power = pwr_info->requested_power +
+			IWL_CCK_FROM_OFDM_POWER_DIFF;
+		pwr_index = pwr_info->power_table_index +
+			IWL_CCK_FROM_OFDM_INDEX_DIFF;
+		base_pwr_index = pwr_info->base_power_index +
+			IWL_CCK_FROM_OFDM_INDEX_DIFF;
+
+		/* stay within table range */
+		pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index);
+		gain = power_gain_table[a_band][pwr_index].tx_gain;
+		dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;
+
+		/* fill each CCK rate's iwl3945_channel_power_info structure
+		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
+		 * NOTE:  CCK rates start at end of OFDM rates! */
+		for (rate_index = 0;
+		     rate_index < IWL_CCK_RATES; rate_index++) {
+			pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
+			pwr_info->requested_power = power;
+			pwr_info->power_table_index = pwr_index;
+			pwr_info->base_power_index = base_pwr_index;
+			pwr_info->tpc.tx_gain = gain;
+			pwr_info->tpc.dsp_atten = dsp_atten;
+		}
+
+		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
+		for (scan_tbl_index = 0;
+		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
+			s32 actual_index = (scan_tbl_index == 0) ?
+				IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
+			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
+				actual_index, clip_pwrs, ch_info, a_band);
+		}
+	}
+
+	return 0;
+}
+
+int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
+{
+	int rc;
+
+	iwl_legacy_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
+	rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
+			FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+	if (rc < 0)
+		IWL_ERR(priv, "Can't stop Rx DMA.\n");
+
+	return 0;
+}
+
+int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	int txq_id = txq->q.id;
+
+	struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
+
+	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
+
+	iwl_legacy_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
+	iwl_legacy_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
+
+	iwl_legacy_write_direct32(priv, FH39_TCSR_CONFIG(txq_id),
+		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
+		FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
+		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
+		FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
+		FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
+
+	/* fake read to flush all prev. writes */
+	iwl_read32(priv, FH39_TSSR_CBB_BASE);
+
+	return 0;
+}
+
+/*
+ * HCMD utils
+ */
+static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
+{
+	switch (cmd_id) {
+	case REPLY_RXON:
+		return sizeof(struct iwl3945_rxon_cmd);
+	case POWER_TABLE_CMD:
+		return sizeof(struct iwl3945_powertable_cmd);
+	default:
+		return len;
+	}
+}
+
+
+static u16 iwl3945_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
+								u8 *data)
+{
+	struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data;
+	addsta->mode = cmd->mode;
+	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
+	memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
+	addsta->station_flags = cmd->station_flags;
+	addsta->station_flags_msk = cmd->station_flags_msk;
+	addsta->tid_disable_tx = cpu_to_le16(0);
+	addsta->rate_n_flags = cmd->rate_n_flags;
+	addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
+	addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
+	addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+
+	return (u16)sizeof(struct iwl3945_addsta_cmd);
+}
+
+static int iwl3945_add_bssid_station(struct iwl_priv *priv,
+				     const u8 *addr, u8 *sta_id_r)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	int ret;
+	u8 sta_id;
+	unsigned long flags;
+
+	if (sta_id_r)
+		*sta_id_r = IWL_INVALID_STATION;
+
+	ret = iwl_legacy_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM\n", addr);
+		return ret;
+	}
+
+	if (sta_id_r)
+		*sta_id_r = sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].used |= IWL_STA_LOCAL;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
+				       struct ieee80211_vif *vif, bool add)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	int ret;
+
+	if (add) {
+		ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
+						&vif_priv->ibss_bssid_sta_id);
+		if (ret)
+			return ret;
+
+		iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
+				 (priv->band == IEEE80211_BAND_5GHZ) ?
+				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
+		iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
+
+		return 0;
+	}
+
+	return iwl_legacy_remove_station(priv, vif_priv->ibss_bssid_sta_id,
+				  vif->bss_conf.bssid);
+}
+
+/**
+ * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
+ */
+int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
+{
+	int rc, i, index, prev_index;
+	struct iwl3945_rate_scaling_cmd rate_cmd = {
+		.reserved = {0, 0, 0},
+	};
+	struct iwl3945_rate_scaling_info *table = rate_cmd.table;
+
+	for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) {
+		index = iwl3945_rates[i].table_rs_index;
+
+		table[index].rate_n_flags =
+			iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
+		table[index].try_cnt = priv->retry_rate;
+		prev_index = iwl3945_get_prev_ieee_rate(i);
+		table[index].next_rate_index =
+				iwl3945_rates[prev_index].table_rs_index;
+	}
+
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
+		IWL_DEBUG_RATE(priv, "Select A mode rate scale\n");
+		/* If one of the following CCK rates is used,
+		 * have it fall back to the 6M OFDM rate */
+		for (i = IWL_RATE_1M_INDEX_TABLE;
+			i <= IWL_RATE_11M_INDEX_TABLE; i++)
+			table[i].next_rate_index =
+			  iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+
+		/* Don't fall back to CCK rates */
+		table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
+						IWL_RATE_9M_INDEX_TABLE;
+
+		/* Don't drop out of OFDM rates */
+		table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
+		    iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+		break;
+
+	case IEEE80211_BAND_2GHZ:
+		IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n");
+		/* If an OFDM rate is used, have it fall back to the
+		 * 1M CCK rates */
+
+		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+		    iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+
+			index = IWL_FIRST_CCK_RATE;
+			for (i = IWL_RATE_6M_INDEX_TABLE;
+			     i <= IWL_RATE_54M_INDEX_TABLE; i++)
+				table[i].next_rate_index =
+					iwl3945_rates[index].table_rs_index;
+
+			index = IWL_RATE_11M_INDEX_TABLE;
+			/* CCK shouldn't fall back to OFDM... */
+			table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
+		}
+		break;
+
+	default:
+		WARN_ON(1);
+		break;
+	}
+
+	/* Update the rate scaling for control frame Tx */
+	rate_cmd.table_id = 0;
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+			      &rate_cmd);
+	if (rc)
+		return rc;
+
+	/* Update the rate scaling for data frame Tx */
+	rate_cmd.table_id = 1;
+	return iwl_legacy_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+				&rate_cmd);
+}
+
+/* Called when initializing driver */
+int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
+{
+	memset((void *)&priv->hw_params, 0,
+	       sizeof(struct iwl_hw_params));
+
+	priv->_3945.shared_virt =
+		dma_alloc_coherent(&priv->pci_dev->dev,
+				   sizeof(struct iwl3945_shared),
+				   &priv->_3945.shared_phys, GFP_KERNEL);
+	if (!priv->_3945.shared_virt) {
+		IWL_ERR(priv, "failed to allocate pci memory\n");
+		return -ENOMEM;
+	}
+
+	/* Assign number of Usable TX queues */
+	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
+
+	priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
+	priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
+	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+	priv->hw_params.max_stations = IWL3945_STATION_COUNT;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
+
+	priv->sta_key_max_num = STA_KEY_MAX_NUM;
+
+	priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
+	priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
+	priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;
+
+	return 0;
+}
+
+unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
+			  struct iwl3945_frame *frame, u8 rate)
+{
+	struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
+	unsigned int frame_size;
+
+	tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
+	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+	tx_beacon_cmd->tx.sta_id =
+		priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
+	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	frame_size = iwl3945_fill_beacon_frame(priv,
+				tx_beacon_cmd->frame,
+				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+
+	BUG_ON(frame_size > MAX_MPDU_SIZE);
+	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
+
+	tx_beacon_cmd->tx.rate = rate;
+	tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
+				      TX_CMD_FLG_TSF_MSK);
+
+	/* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
+	tx_beacon_cmd->tx.supp_rates[0] =
+		(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+
+	tx_beacon_cmd->tx.supp_rates[1] =
+		(IWL_CCK_BASIC_RATES_MASK & 0xF);
+
+	return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
+}
+
+void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
+{
+	priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
+	priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
+}
+
+void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
+{
+	INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
+			  iwl3945_bg_reg_txpower_periodic);
+}
+
+void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
+{
+	cancel_delayed_work(&priv->_3945.thermal_periodic);
+}
+
+/* check contents of special bootstrap uCode SRAM */
+static int iwl3945_verify_bsm(struct iwl_priv *priv)
+ {
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	u32 reg;
+	u32 val;
+
+	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
+
+	/* verify BSM SRAM contents */
+	val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
+	for (reg = BSM_SRAM_LOWER_BOUND;
+	     reg < BSM_SRAM_LOWER_BOUND + len;
+	     reg += sizeof(u32), image++) {
+		val = iwl_legacy_read_prph(priv, reg);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "BSM uCode verification failed at "
+				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+				  BSM_SRAM_LOWER_BOUND,
+				  reg - BSM_SRAM_LOWER_BOUND, len,
+				  val, le32_to_cpu(*image));
+			return -EIO;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
+
+	return 0;
+}
+
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+ ******************************************************************************/
+
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+	_iwl_legacy_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+	return 0;
+}
+
+
+static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+	return;
+}
+
+ /**
+  * iwl3945_load_bsm - Load bootstrap instructions
+  *
+  * BSM operation:
+  *
+  * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+  * in special SRAM that does not power down during RFKILL.  When powering back
+  * up after power-saving sleeps (or during initial uCode load), the BSM loads
+  * the bootstrap program into the on-board processor, and starts it.
+  *
+  * The bootstrap program loads (via DMA) instructions and data for a new
+  * program from host DRAM locations indicated by the host driver in the
+  * BSM_DRAM_* registers.  Once the new program is loaded, it starts
+  * automatically.
+  *
+  * When initializing the NIC, the host driver points the BSM to the
+  * "initialize" uCode image.  This uCode sets up some internal data, then
+  * notifies host via "initialize alive" that it is complete.
+  *
+  * The host then replaces the BSM_DRAM_* pointer values to point to the
+  * normal runtime uCode instructions and a backup uCode data cache buffer
+  * (filled initially with starting data values for the on-board processor),
+  * then triggers the "initialize" uCode to load and launch the runtime uCode,
+  * which begins normal operation.
+  *
+  * When doing a power-save shutdown, runtime uCode saves data SRAM into
+  * the backup data cache in DRAM before SRAM is powered down.
+  *
+  * When powering back up, the BSM loads the bootstrap program.  This reloads
+  * the runtime uCode instructions and the backup data cache into SRAM,
+  * and re-launches the runtime uCode from where it left off.
+  */
+static int iwl3945_load_bsm(struct iwl_priv *priv)
+{
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+	u32 inst_len;
+	u32 data_len;
+	int rc;
+	int i;
+	u32 done;
+	u32 reg_offset;
+
+	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
+
+	/* make sure bootstrap program is no larger than BSM's SRAM size */
+	if (len > IWL39_MAX_BSM_SIZE)
+		return -EINVAL;
+
+	/* Tell bootstrap uCode where to find the "Initialize" uCode
+	*   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
+	* NOTE:  iwl3945_initialize_alive_start() will replace these values,
+	*        after the "initialize" uCode has run, to point to
+	*        runtime/protocol instructions and backup data cache. */
+	pinst = priv->ucode_init.p_addr;
+	pdata = priv->ucode_init_data.p_addr;
+	inst_len = priv->ucode_init.len;
+	data_len = priv->ucode_init_data.len;
+
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+
+	/* Fill BSM memory with bootstrap instructions */
+	for (reg_offset = BSM_SRAM_LOWER_BOUND;
+	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
+	     reg_offset += sizeof(u32), image++)
+		_iwl_legacy_write_prph(priv, reg_offset,
+					  le32_to_cpu(*image));
+
+	rc = iwl3945_verify_bsm(priv);
+	if (rc)
+		return rc;
+
+	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+	iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+	iwl_legacy_write_prph(priv, BSM_WR_MEM_DST_REG,
+				 IWL39_RTC_INST_LOWER_BOUND);
+	iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+	/* Load bootstrap code into instruction SRAM now,
+	 *   to prepare to load "initialize" uCode */
+	iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG,
+		BSM_WR_CTRL_REG_BIT_START);
+
+	/* Wait for load of bootstrap uCode to finish */
+	for (i = 0; i < 100; i++) {
+		done = iwl_legacy_read_prph(priv, BSM_WR_CTRL_REG);
+		if (!(done & BSM_WR_CTRL_REG_BIT_START))
+			break;
+		udelay(10);
+	}
+	if (i < 100)
+		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
+	else {
+		IWL_ERR(priv, "BSM write did not complete!\n");
+		return -EIO;
+	}
+
+	/* Enable future boot loads whenever power management unit triggers it
+	 *   (e.g. when powering back up after power-save shutdown) */
+	iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG,
+		BSM_WR_CTRL_REG_BIT_START_EN);
+
+	return 0;
+}
+
+static struct iwl_hcmd_ops iwl3945_hcmd = {
+	.rxon_assoc = iwl3945_send_rxon_assoc,
+	.commit_rxon = iwl3945_commit_rxon,
+};
+
+static struct iwl_lib_ops iwl3945_lib = {
+	.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
+	.txq_free_tfd = iwl3945_hw_txq_free_tfd,
+	.txq_init = iwl3945_hw_tx_queue_init,
+	.load_ucode = iwl3945_load_bsm,
+	.dump_nic_event_log = iwl3945_dump_nic_event_log,
+	.dump_nic_error_log = iwl3945_dump_nic_error_log,
+	.apm_ops = {
+		.init = iwl3945_apm_init,
+		.config = iwl3945_nic_config,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REGULATORY_BAND_1_CHANNELS,
+			EEPROM_REGULATORY_BAND_2_CHANNELS,
+			EEPROM_REGULATORY_BAND_3_CHANNELS,
+			EEPROM_REGULATORY_BAND_4_CHANNELS,
+			EEPROM_REGULATORY_BAND_5_CHANNELS,
+			EEPROM_REGULATORY_BAND_NO_HT40,
+			EEPROM_REGULATORY_BAND_NO_HT40,
+		},
+		.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
+		.release_semaphore = iwl3945_eeprom_release_semaphore,
+	},
+	.send_tx_power	= iwl3945_send_tx_power,
+	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
+
+	.debugfs_ops = {
+		.rx_stats_read = iwl3945_ucode_rx_stats_read,
+		.tx_stats_read = iwl3945_ucode_tx_stats_read,
+		.general_stats_read = iwl3945_ucode_general_stats_read,
+	},
+};
+
+static const struct iwl_legacy_ops iwl3945_legacy_ops = {
+	.post_associate = iwl3945_post_associate,
+	.config_ap = iwl3945_config_ap,
+	.manage_ibss_station = iwl3945_manage_ibss_station,
+};
+
+static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
+	.get_hcmd_size = iwl3945_get_hcmd_size,
+	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
+	.request_scan = iwl3945_request_scan,
+	.post_scan = iwl3945_post_scan,
+};
+
+static const struct iwl_ops iwl3945_ops = {
+	.lib = &iwl3945_lib,
+	.hcmd = &iwl3945_hcmd,
+	.utils = &iwl3945_hcmd_utils,
+	.led = &iwl3945_led_ops,
+	.legacy = &iwl3945_legacy_ops,
+	.ieee80211_ops = &iwl3945_hw_ops,
+};
+
+static struct iwl_base_params iwl3945_base_params = {
+	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
+	.num_of_queues = IWL39_NUM_QUEUES,
+	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
+	.set_l0s = false,
+	.use_bsm = true,
+	.led_compensation = 64,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.max_event_log_size = 512,
+};
+
+static struct iwl_cfg iwl3945_bg_cfg = {
+	.name = "3945BG",
+	.fw_name_pre = IWL3945_FW_PRE,
+	.ucode_api_max = IWL3945_UCODE_API_MAX,
+	.ucode_api_min = IWL3945_UCODE_API_MIN,
+	.sku = IWL_SKU_G,
+	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+	.ops = &iwl3945_ops,
+	.mod_params = &iwl3945_mod_params,
+	.base_params = &iwl3945_base_params,
+	.led_mode = IWL_LED_BLINK,
+};
+
+static struct iwl_cfg iwl3945_abg_cfg = {
+	.name = "3945ABG",
+	.fw_name_pre = IWL3945_FW_PRE,
+	.ucode_api_max = IWL3945_UCODE_API_MAX,
+	.ucode_api_min = IWL3945_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G,
+	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+	.ops = &iwl3945_ops,
+	.mod_params = &iwl3945_mod_params,
+	.base_params = &iwl3945_base_params,
+	.led_mode = IWL_LED_BLINK,
+};
+
+DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
+	{IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
+	{IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.h b/drivers/net/wireless/iwlegacy/iwl-3945.h
new file mode 100644
index 0000000..b118b59
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.h
@@ -0,0 +1,308 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-3945.h) for driver implementation definitions.
+ * Please use iwl-3945-commands.h for uCode API definitions.
+ * Please use iwl-3945-hw.h for hardware-related definitions.
+ */
+
+#ifndef __iwl_3945_h__
+#define __iwl_3945_h__
+
+#include <linux/pci.h> /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <net/ieee80211_radiotap.h>
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+extern const struct pci_device_id iwl3945_hw_card_ids[];
+
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-fh.h"
+#include "iwl-3945-hw.h"
+#include "iwl-debug.h"
+#include "iwl-power.h"
+#include "iwl-dev.h"
+#include "iwl-led.h"
+
+/* Highest firmware API version supported */
+#define IWL3945_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IWL3945_UCODE_API_MIN 1
+
+#define IWL3945_FW_PRE	"iwlwifi-3945-"
+#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
+#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
+
+/* Default noise level to report when noise measurement is not available.
+ *   This may be because we're:
+ *   1)  Not associated (4965, no beacon statistics being sent to driver)
+ *   2)  Scanning (noise measurement does not apply to associated channel)
+ *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Also, -127 works better than 0 when averaging frames with/without
+ *   noise info (e.g. averaging might be done in app); measured dBm values are
+ *   always negative ... using a negative value as the default keeps all
+ *   averages within an s8's (used in some apps) range of negative values. */
+#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/* Module parameters accessible from iwl-*.c */
+extern struct iwl_mod_params iwl3945_mod_params;
+
+struct iwl3945_rate_scale_data {
+	u64 data;
+	s32 success_counter;
+	s32 success_ratio;
+	s32 counter;
+	s32 average_tpt;
+	unsigned long stamp;
+};
+
+struct iwl3945_rs_sta {
+	spinlock_t lock;
+	struct iwl_priv *priv;
+	s32 *expected_tpt;
+	unsigned long last_partial_flush;
+	unsigned long last_flush;
+	u32 flush_time;
+	u32 last_tx_packets;
+	u32 tx_packets;
+	u8 tgg;
+	u8 flush_pending;
+	u8 start_rate;
+	struct timer_list rate_scale_flush;
+	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *rs_sta_dbgfs_stats_table_file;
+#endif
+
+	/* used to be in sta_info */
+	int last_txrate_idx;
+};
+
+
+/*
+ * The common struct MUST be first because it is shared between
+ * 3945 and 4965!
+ */
+struct iwl3945_sta_priv {
+	struct iwl_station_priv_common common;
+	struct iwl3945_rs_sta rs_sta;
+};
+
+enum iwl3945_antenna {
+	IWL_ANTENNA_DIVERSITY,
+	IWL_ANTENNA_MAIN,
+	IWL_ANTENNA_AUX
+};
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ *   a value of 0 means RTS on all data/management packets
+ *   a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ *   than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD     2347U
+#define MIN_RTS_THRESHOLD         0U
+#define MAX_RTS_THRESHOLD         2347U
+#define MAX_MSDU_SIZE		  2304U
+#define MAX_MPDU_SIZE		  2346U
+#define DEFAULT_BEACON_INTERVAL   100U
+#define	DEFAULT_SHORT_RETRY_LIMIT 7U
+#define	DEFAULT_LONG_RETRY_LIMIT  4U
+
+#define IWL_TX_FIFO_AC0	0
+#define IWL_TX_FIFO_AC1	1
+#define IWL_TX_FIFO_AC2	2
+#define IWL_TX_FIFO_AC3	3
+#define IWL_TX_FIFO_HCCA_1	5
+#define IWL_TX_FIFO_HCCA_2	6
+#define IWL_TX_FIFO_NONE	7
+
+#define IEEE80211_DATA_LEN              2304
+#define IEEE80211_4ADDR_LEN             30
+#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct iwl3945_frame {
+	union {
+		struct ieee80211_hdr frame;
+		struct iwl3945_tx_beacon_cmd beacon;
+		u8 raw[IEEE80211_FRAME_LEN];
+		u8 cmd[360];
+	} u;
+	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
+
+#define IWL_SUPPORTED_RATES_IE_LEN         8
+
+#define SCAN_INTERVAL 100
+
+#define MAX_TID_COUNT        9
+
+#define IWL_INVALID_RATE     0xFF
+#define IWL_INVALID_VALUE    -1
+
+#define STA_PS_STATUS_WAKE             0
+#define STA_PS_STATUS_SLEEP            1
+
+struct iwl3945_ibss_seq {
+	u8 mac[ETH_ALEN];
+	u16 seq_num;
+	u16 frag_num;
+	unsigned long packet_time;
+	struct list_head list;
+};
+
+#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
+		       x->u.rx_frame.stats.payload + \
+		       x->u.rx_frame.stats.phy_count))
+#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
+		       IWL_RX_HDR(x)->payload + \
+		       le16_to_cpu(IWL_RX_HDR(x)->len)))
+#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
+#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
+
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl3945-base.c which are forward declared here
+ * for use by iwl-*.c
+ *
+ *****************************************************************************/
+extern int iwl3945_calc_db_from_ratio(int sig_ratio);
+extern void iwl3945_rx_replenish(void *data);
+extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
+					struct ieee80211_hdr *hdr, int left);
+extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
+				       char **buf, bool display);
+extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-[34]*.c which are forward declared here
+ * for use by iwl3945-base.c
+ *
+ * NOTE:  The implementation of these functions are hardware specific
+ * which is why they are in the hardware specific files (vs. iwl-base.c)
+ *
+ * Naming convention --
+ * iwl3945_         <-- Its part of iwlwifi (should be changed to iwl3945_)
+ * iwl3945_hw_      <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
+ * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * iwl3945_bg_      <-- Called from work queue context
+ * iwl3945_mac_     <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
+extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
+extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
+extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
+extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
+extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
+extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
+extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+					    struct iwl_tx_queue *txq,
+					    dma_addr_t addr, u16 len,
+					    u8 reset, u8 pad);
+extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
+				    struct iwl_tx_queue *txq);
+extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
+extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
+				struct iwl_tx_queue *txq);
+extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
+				 struct iwl3945_frame *frame, u8 rate);
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+				  struct iwl_device_cmd *cmd,
+				  struct ieee80211_tx_info *info,
+				  struct ieee80211_hdr *hdr,
+				  int sta_id, int tx_id);
+extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
+extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
+extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+				 struct iwl_rx_mem_buffer *rxb);
+void iwl3945_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb);
+extern void iwl3945_disable_events(struct iwl_priv *priv);
+extern int iwl4965_get_temperature(const struct iwl_priv *priv);
+extern void iwl3945_post_associate(struct iwl_priv *priv);
+extern void iwl3945_config_ap(struct iwl_priv *priv);
+
+extern int iwl3945_commit_rxon(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+
+/**
+ * iwl3945_hw_find_station - Find station id for a given BSSID
+ * @bssid: MAC address of station ID to find
+ *
+ * NOTE:  This should not be hardware specific but the code has
+ * not yet been merged into a single common layer for managing the
+ * station tables.
+ */
+extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
+
+extern struct ieee80211_ops iwl3945_hw_ops;
+
+/*
+ * Forward declare iwl-3945.c functions for iwl3945-base.c
+ */
+extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
+extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
+extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
+extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
+
+extern const struct iwl_channel_info *iwl3945_get_channel_info(
+	const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
+
+extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
+
+/* scanning */
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+void iwl3945_post_scan(struct iwl_priv *priv);
+
+/* rates */
+extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
+
+/* Requires full declaration of iwl_priv before including */
+#include "iwl-io.h"
+
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-calib.c b/drivers/net/wireless/iwlegacy/iwl-4965-calib.c
new file mode 100644
index 0000000..81d6a25
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-calib.c
@@ -0,0 +1,967 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-4965-calib.h"
+
+/*****************************************************************************
+ * INIT calibrations framework
+ *****************************************************************************/
+
+struct statistics_general_data {
+	u32 beacon_silence_rssi_a;
+	u32 beacon_silence_rssi_b;
+	u32 beacon_silence_rssi_c;
+	u32 beacon_energy_a;
+	u32 beacon_energy_b;
+	u32 beacon_energy_c;
+};
+
+void iwl4965_calib_free_results(struct iwl_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < IWL_CALIB_MAX; i++) {
+		kfree(priv->calib_results[i].buf);
+		priv->calib_results[i].buf = NULL;
+		priv->calib_results[i].buf_len = 0;
+	}
+}
+
+/*****************************************************************************
+ * RUNTIME calibrations framework
+ *****************************************************************************/
+
+/* "false alarms" are signals that our DSP tries to lock onto,
+ *   but then determines that they are either noise, or transmissions
+ *   from a distant wireless network (also "noise", really) that get
+ *   "stepped on" by stronger transmissions within our own network.
+ * This algorithm attempts to set a sensitivity level that is high
+ *   enough to receive all of our own network traffic, but not so
+ *   high that our DSP gets too busy trying to lock onto non-network
+ *   activity/noise. */
+static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
+				   u32 norm_fa,
+				   u32 rx_enable_time,
+				   struct statistics_general_data *rx_info)
+{
+	u32 max_nrg_cck = 0;
+	int i = 0;
+	u8 max_silence_rssi = 0;
+	u32 silence_ref = 0;
+	u8 silence_rssi_a = 0;
+	u8 silence_rssi_b = 0;
+	u8 silence_rssi_c = 0;
+	u32 val;
+
+	/* "false_alarms" values below are cross-multiplications to assess the
+	 *   numbers of false alarms within the measured period of actual Rx
+	 *   (Rx is off when we're txing), vs the min/max expected false alarms
+	 *   (some should be expected if rx is sensitive enough) in a
+	 *   hypothetical listening period of 200 time units (TU), 204.8 msec:
+	 *
+	 * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
+	 *
+	 * */
+	u32 false_alarms = norm_fa * 200 * 1024;
+	u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
+	u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	data = &(priv->sensitivity_data);
+
+	data->nrg_auto_corr_silence_diff = 0;
+
+	/* Find max silence rssi among all 3 receivers.
+	 * This is background noise, which may include transmissions from other
+	 *    networks, measured during silence before our network's beacon */
+	silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
+			    ALL_BAND_FILTER) >> 8);
+	silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
+			    ALL_BAND_FILTER) >> 8);
+	silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
+			    ALL_BAND_FILTER) >> 8);
+
+	val = max(silence_rssi_b, silence_rssi_c);
+	max_silence_rssi = max(silence_rssi_a, (u8) val);
+
+	/* Store silence rssi in 20-beacon history table */
+	data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
+	data->nrg_silence_idx++;
+	if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
+		data->nrg_silence_idx = 0;
+
+	/* Find max silence rssi across 20 beacon history */
+	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
+		val = data->nrg_silence_rssi[i];
+		silence_ref = max(silence_ref, val);
+	}
+	IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n",
+			silence_rssi_a, silence_rssi_b, silence_rssi_c,
+			silence_ref);
+
+	/* Find max rx energy (min value!) among all 3 receivers,
+	 *   measured during beacon frame.
+	 * Save it in 10-beacon history table. */
+	i = data->nrg_energy_idx;
+	val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
+	data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
+
+	data->nrg_energy_idx++;
+	if (data->nrg_energy_idx >= 10)
+		data->nrg_energy_idx = 0;
+
+	/* Find min rx energy (max value) across 10 beacon history.
+	 * This is the minimum signal level that we want to receive well.
+	 * Add backoff (margin so we don't miss slightly lower energy frames).
+	 * This establishes an upper bound (min value) for energy threshold. */
+	max_nrg_cck = data->nrg_value[0];
+	for (i = 1; i < 10; i++)
+		max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
+	max_nrg_cck += 6;
+
+	IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
+			rx_info->beacon_energy_a, rx_info->beacon_energy_b,
+			rx_info->beacon_energy_c, max_nrg_cck - 6);
+
+	/* Count number of consecutive beacons with fewer-than-desired
+	 *   false alarms. */
+	if (false_alarms < min_false_alarms)
+		data->num_in_cck_no_fa++;
+	else
+		data->num_in_cck_no_fa = 0;
+	IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n",
+			data->num_in_cck_no_fa);
+
+	/* If we got too many false alarms this time, reduce sensitivity */
+	if ((false_alarms > max_false_alarms) &&
+		(data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
+		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n",
+		     false_alarms, max_false_alarms);
+		IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n");
+		data->nrg_curr_state = IWL_FA_TOO_MANY;
+		/* Store for "fewer than desired" on later beacon */
+		data->nrg_silence_ref = silence_ref;
+
+		/* increase energy threshold (reduce nrg value)
+		 *   to decrease sensitivity */
+		data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
+	/* Else if we got fewer than desired, increase sensitivity */
+	} else if (false_alarms < min_false_alarms) {
+		data->nrg_curr_state = IWL_FA_TOO_FEW;
+
+		/* Compare silence level with silence level for most recent
+		 *   healthy number or too many false alarms */
+		data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
+						   (s32)silence_ref;
+
+		IWL_DEBUG_CALIB(priv,
+			 "norm FA %u < min FA %u, silence diff %d\n",
+			 false_alarms, min_false_alarms,
+			 data->nrg_auto_corr_silence_diff);
+
+		/* Increase value to increase sensitivity, but only if:
+		 * 1a) previous beacon did *not* have *too many* false alarms
+		 * 1b) AND there's a significant difference in Rx levels
+		 *      from a previous beacon with too many, or healthy # FAs
+		 * OR 2) We've seen a lot of beacons (100) with too few
+		 *       false alarms */
+		if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
+			((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
+			(data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+
+			IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n");
+			/* Increase nrg value to increase sensitivity */
+			val = data->nrg_th_cck + NRG_STEP_CCK;
+			data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
+		} else {
+			IWL_DEBUG_CALIB(priv,
+					 "... but not changing sensitivity\n");
+		}
+
+	/* Else we got a healthy number of false alarms, keep status quo */
+	} else {
+		IWL_DEBUG_CALIB(priv, " FA in safe zone\n");
+		data->nrg_curr_state = IWL_FA_GOOD_RANGE;
+
+		/* Store for use in "fewer than desired" with later beacon */
+		data->nrg_silence_ref = silence_ref;
+
+		/* If previous beacon had too many false alarms,
+		 *   give it some extra margin by reducing sensitivity again
+		 *   (but don't go below measured energy of desired Rx) */
+		if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
+			IWL_DEBUG_CALIB(priv, "... increasing margin\n");
+			if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
+				data->nrg_th_cck -= NRG_MARGIN;
+			else
+				data->nrg_th_cck = max_nrg_cck;
+		}
+	}
+
+	/* Make sure the energy threshold does not go above the measured
+	 * energy of the desired Rx signals (reduced by backoff margin),
+	 * or else we might start missing Rx frames.
+	 * Lower value is higher energy, so we use max()!
+	 */
+	data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
+	IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck);
+
+	data->nrg_prev_state = data->nrg_curr_state;
+
+	/* Auto-correlation CCK algorithm */
+	if (false_alarms > min_false_alarms) {
+
+		/* increase auto_corr values to decrease sensitivity
+		 * so the DSP won't be disturbed by the noise
+		 */
+		if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
+			data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
+		else {
+			val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
+			data->auto_corr_cck =
+				min((u32)ranges->auto_corr_max_cck, val);
+		}
+		val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck_mrc =
+			min((u32)ranges->auto_corr_max_cck_mrc, val);
+	} else if ((false_alarms < min_false_alarms) &&
+	   ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
+	   (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+
+		/* Decrease auto_corr values to increase sensitivity */
+		val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck =
+			max((u32)ranges->auto_corr_min_cck, val);
+		val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck_mrc =
+			max((u32)ranges->auto_corr_min_cck_mrc, val);
+	}
+
+	return 0;
+}
+
+
+static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
+				       u32 norm_fa,
+				       u32 rx_enable_time)
+{
+	u32 val;
+	u32 false_alarms = norm_fa * 200 * 1024;
+	u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
+	u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	data = &(priv->sensitivity_data);
+
+	/* If we got too many false alarms this time, reduce sensitivity */
+	if (false_alarms > max_false_alarms) {
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n",
+			     false_alarms, max_false_alarms);
+
+		val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm =
+			min((u32)ranges->auto_corr_max_ofdm, val);
+
+		val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc =
+			min((u32)ranges->auto_corr_max_ofdm_mrc, val);
+
+		val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_x1 =
+			min((u32)ranges->auto_corr_max_ofdm_x1, val);
+
+		val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc_x1 =
+			min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val);
+	}
+
+	/* Else if we got fewer than desired, increase sensitivity */
+	else if (false_alarms < min_false_alarms) {
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n",
+			     false_alarms, min_false_alarms);
+
+		val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm =
+			max((u32)ranges->auto_corr_min_ofdm, val);
+
+		val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc =
+			max((u32)ranges->auto_corr_min_ofdm_mrc, val);
+
+		val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_x1 =
+			max((u32)ranges->auto_corr_min_ofdm_x1, val);
+
+		val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc_x1 =
+			max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val);
+	} else {
+		IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n",
+			 min_false_alarms, false_alarms, max_false_alarms);
+	}
+	return 0;
+}
+
+static void iwl4965_prepare_legacy_sensitivity_tbl(struct iwl_priv *priv,
+				struct iwl_sensitivity_data *data,
+				__le16 *tbl)
+{
+	tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm);
+	tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
+	tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_x1);
+	tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
+
+	tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_cck);
+	tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_cck_mrc);
+
+	tbl[HD_MIN_ENERGY_CCK_DET_INDEX] =
+				cpu_to_le16((u16)data->nrg_th_cck);
+	tbl[HD_MIN_ENERGY_OFDM_DET_INDEX] =
+				cpu_to_le16((u16)data->nrg_th_ofdm);
+
+	tbl[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
+				cpu_to_le16(data->barker_corr_th_min);
+	tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16(data->barker_corr_th_min_mrc);
+	tbl[HD_OFDM_ENERGY_TH_IN_INDEX] =
+				cpu_to_le16(data->nrg_th_cca);
+
+	IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
+			data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
+			data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
+			data->nrg_th_ofdm);
+
+	IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n",
+			data->auto_corr_cck, data->auto_corr_cck_mrc,
+			data->nrg_th_cck);
+}
+
+/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
+static int iwl4965_sensitivity_write(struct iwl_priv *priv)
+{
+	struct iwl_sensitivity_cmd cmd;
+	struct iwl_sensitivity_data *data = NULL;
+	struct iwl_host_cmd cmd_out = {
+		.id = SENSITIVITY_CMD,
+		.len = sizeof(struct iwl_sensitivity_cmd),
+		.flags = CMD_ASYNC,
+		.data = &cmd,
+	};
+
+	data = &(priv->sensitivity_data);
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	iwl4965_prepare_legacy_sensitivity_tbl(priv, data, &cmd.table[0]);
+
+	/* Update uCode's "work" table, and copy it to DSP */
+	cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
+
+	/* Don't send command to uCode if nothing has changed */
+	if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
+		    sizeof(u16)*HD_TABLE_SIZE)) {
+		IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n");
+		return 0;
+	}
+
+	/* Copy table for comparison next time */
+	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
+	       sizeof(u16)*HD_TABLE_SIZE);
+
+	return iwl_legacy_send_cmd(priv, &cmd_out);
+}
+
+void iwl4965_init_sensitivity(struct iwl_priv *priv)
+{
+	int ret = 0;
+	int i;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	if (priv->disable_sens_cal)
+		return;
+
+	IWL_DEBUG_CALIB(priv, "Start iwl4965_init_sensitivity\n");
+
+	/* Clear driver's sensitivity algo data */
+	data = &(priv->sensitivity_data);
+
+	if (ranges == NULL)
+		return;
+
+	memset(data, 0, sizeof(struct iwl_sensitivity_data));
+
+	data->num_in_cck_no_fa = 0;
+	data->nrg_curr_state = IWL_FA_TOO_MANY;
+	data->nrg_prev_state = IWL_FA_TOO_MANY;
+	data->nrg_silence_ref = 0;
+	data->nrg_silence_idx = 0;
+	data->nrg_energy_idx = 0;
+
+	for (i = 0; i < 10; i++)
+		data->nrg_value[i] = 0;
+
+	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
+		data->nrg_silence_rssi[i] = 0;
+
+	data->auto_corr_ofdm =  ranges->auto_corr_min_ofdm;
+	data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
+	data->auto_corr_ofdm_x1  = ranges->auto_corr_min_ofdm_x1;
+	data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
+	data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
+	data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
+	data->nrg_th_cck = ranges->nrg_th_cck;
+	data->nrg_th_ofdm = ranges->nrg_th_ofdm;
+	data->barker_corr_th_min = ranges->barker_corr_th_min;
+	data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc;
+	data->nrg_th_cca = ranges->nrg_th_cca;
+
+	data->last_bad_plcp_cnt_ofdm = 0;
+	data->last_fa_cnt_ofdm = 0;
+	data->last_bad_plcp_cnt_cck = 0;
+	data->last_fa_cnt_cck = 0;
+
+	ret |= iwl4965_sensitivity_write(priv);
+	IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
+}
+
+void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp)
+{
+	u32 rx_enable_time;
+	u32 fa_cck;
+	u32 fa_ofdm;
+	u32 bad_plcp_cck;
+	u32 bad_plcp_ofdm;
+	u32 norm_fa_ofdm;
+	u32 norm_fa_cck;
+	struct iwl_sensitivity_data *data = NULL;
+	struct statistics_rx_non_phy *rx_info;
+	struct statistics_rx_phy *ofdm, *cck;
+	unsigned long flags;
+	struct statistics_general_data statis;
+
+	if (priv->disable_sens_cal)
+		return;
+
+	data = &(priv->sensitivity_data);
+
+	if (!iwl_legacy_is_any_associated(priv)) {
+		IWL_DEBUG_CALIB(priv, "<< - not associated\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general);
+	ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm);
+	cck = &(((struct iwl_notif_statistics *)resp)->rx.cck);
+
+	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
+		IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	/* Extract Statistics: */
+	rx_enable_time = le32_to_cpu(rx_info->channel_load);
+	fa_cck = le32_to_cpu(cck->false_alarm_cnt);
+	fa_ofdm = le32_to_cpu(ofdm->false_alarm_cnt);
+	bad_plcp_cck = le32_to_cpu(cck->plcp_err);
+	bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err);
+
+	statis.beacon_silence_rssi_a =
+			le32_to_cpu(rx_info->beacon_silence_rssi_a);
+	statis.beacon_silence_rssi_b =
+			le32_to_cpu(rx_info->beacon_silence_rssi_b);
+	statis.beacon_silence_rssi_c =
+			le32_to_cpu(rx_info->beacon_silence_rssi_c);
+	statis.beacon_energy_a =
+			le32_to_cpu(rx_info->beacon_energy_a);
+	statis.beacon_energy_b =
+			le32_to_cpu(rx_info->beacon_energy_b);
+	statis.beacon_energy_c =
+			le32_to_cpu(rx_info->beacon_energy_c);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
+
+	if (!rx_enable_time) {
+		IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n");
+		return;
+	}
+
+	/* These statistics increase monotonically, and do not reset
+	 *   at each beacon.  Calculate difference from last value, or just
+	 *   use the new statistics value if it has reset or wrapped around. */
+	if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
+		data->last_bad_plcp_cnt_cck = bad_plcp_cck;
+	else {
+		bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
+		data->last_bad_plcp_cnt_cck += bad_plcp_cck;
+	}
+
+	if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
+		data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
+	else {
+		bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
+		data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
+	}
+
+	if (data->last_fa_cnt_ofdm > fa_ofdm)
+		data->last_fa_cnt_ofdm = fa_ofdm;
+	else {
+		fa_ofdm -= data->last_fa_cnt_ofdm;
+		data->last_fa_cnt_ofdm += fa_ofdm;
+	}
+
+	if (data->last_fa_cnt_cck > fa_cck)
+		data->last_fa_cnt_cck = fa_cck;
+	else {
+		fa_cck -= data->last_fa_cnt_cck;
+		data->last_fa_cnt_cck += fa_cck;
+	}
+
+	/* Total aborted signal locks */
+	norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
+	norm_fa_cck = fa_cck + bad_plcp_cck;
+
+	IWL_DEBUG_CALIB(priv,
+			 "cck: fa %u badp %u  ofdm: fa %u badp %u\n", fa_cck,
+			bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
+
+	iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
+	iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
+
+	iwl4965_sensitivity_write(priv);
+}
+
+static inline u8 iwl4965_find_first_chain(u8 mask)
+{
+	if (mask & ANT_A)
+		return CHAIN_A;
+	if (mask & ANT_B)
+		return CHAIN_B;
+	return CHAIN_C;
+}
+
+/**
+ * Run disconnected antenna algorithm to find out which antennas are
+ * disconnected.
+ */
+static void
+iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
+				     struct iwl_chain_noise_data *data)
+{
+	u32 active_chains = 0;
+	u32 max_average_sig;
+	u16 max_average_sig_antenna_i;
+	u8 num_tx_chains;
+	u8 first_chain;
+	u16 i = 0;
+
+	average_sig[0] = data->chain_signal_a /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[1] = data->chain_signal_b /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[2] = data->chain_signal_c /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+
+	if (average_sig[0] >= average_sig[1]) {
+		max_average_sig = average_sig[0];
+		max_average_sig_antenna_i = 0;
+		active_chains = (1 << max_average_sig_antenna_i);
+	} else {
+		max_average_sig = average_sig[1];
+		max_average_sig_antenna_i = 1;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	if (average_sig[2] >= max_average_sig) {
+		max_average_sig = average_sig[2];
+		max_average_sig_antenna_i = 2;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
+		     average_sig[0], average_sig[1], average_sig[2]);
+	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
+		     max_average_sig, max_average_sig_antenna_i);
+
+	/* Compare signal strengths for all 3 receivers. */
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (i != max_average_sig_antenna_i) {
+			s32 rssi_delta = (max_average_sig - average_sig[i]);
+
+			/* If signal is very weak, compared with
+			 * strongest, mark it as disconnected. */
+			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
+				data->disconn_array[i] = 1;
+			else
+				active_chains |= (1 << i);
+			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
+			     "disconn_array[i] = %d\n",
+			     i, rssi_delta, data->disconn_array[i]);
+		}
+	}
+
+	/*
+	 * The above algorithm sometimes fails when the ucode
+	 * reports 0 for all chains. It's not clear why that
+	 * happens to start with, but it is then causing trouble
+	 * because this can make us enable more chains than the
+	 * hardware really has.
+	 *
+	 * To be safe, simply mask out any chains that we know
+	 * are not on the device.
+	 */
+	active_chains &= priv->hw_params.valid_rx_ant;
+
+	num_tx_chains = 0;
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		/* loops on all the bits of
+		 * priv->hw_setting.valid_tx_ant */
+		u8 ant_msk = (1 << i);
+		if (!(priv->hw_params.valid_tx_ant & ant_msk))
+			continue;
+
+		num_tx_chains++;
+		if (data->disconn_array[i] == 0)
+			/* there is a Tx antenna connected */
+			break;
+		if (num_tx_chains == priv->hw_params.tx_chains_num &&
+		    data->disconn_array[i]) {
+			/*
+			 * If all chains are disconnected
+			 * connect the first valid tx chain
+			 */
+			first_chain =
+			iwl4965_find_first_chain(priv->cfg->valid_tx_ant);
+			data->disconn_array[first_chain] = 0;
+			active_chains |= BIT(first_chain);
+			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \
+					W/A - declare %d as connected\n",
+					first_chain);
+			break;
+		}
+	}
+
+	if (active_chains != priv->hw_params.valid_rx_ant &&
+	    active_chains != priv->chain_noise_data.active_chains)
+		IWL_DEBUG_CALIB(priv,
+				"Detected that not all antennas are connected! "
+				"Connected: %#x, valid: %#x.\n",
+				active_chains, priv->hw_params.valid_rx_ant);
+
+	/* Save for use within RXON, TX, SCAN commands, etc. */
+	data->active_chains = active_chains;
+	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
+			active_chains);
+}
+
+static void iwl4965_gain_computation(struct iwl_priv *priv,
+		u32 *average_noise,
+		u16 min_average_noise_antenna_i,
+		u32 min_average_noise,
+		u8 default_chain)
+{
+	int i, ret;
+	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+
+	data->delta_gain_code[min_average_noise_antenna_i] = 0;
+
+	for (i = default_chain; i < NUM_RX_CHAINS; i++) {
+		s32 delta_g = 0;
+
+		if (!(data->disconn_array[i]) &&
+		    (data->delta_gain_code[i] ==
+			     CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
+			delta_g = average_noise[i] - min_average_noise;
+			data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
+			data->delta_gain_code[i] =
+				min(data->delta_gain_code[i],
+				(u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+
+			data->delta_gain_code[i] =
+				(data->delta_gain_code[i] | (1 << 2));
+		} else {
+			data->delta_gain_code[i] = 0;
+		}
+	}
+	IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n",
+		     data->delta_gain_code[0],
+		     data->delta_gain_code[1],
+		     data->delta_gain_code[2]);
+
+	/* Differential gain gets sent to uCode only once */
+	if (!data->radio_write) {
+		struct iwl_calib_diff_gain_cmd cmd;
+		data->radio_write = 1;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
+		cmd.diff_gain_a = data->delta_gain_code[0];
+		cmd.diff_gain_b = data->delta_gain_code[1];
+		cmd.diff_gain_c = data->delta_gain_code[2];
+		ret = iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+				      sizeof(cmd), &cmd);
+		if (ret)
+			IWL_DEBUG_CALIB(priv, "fail sending cmd "
+				     "REPLY_PHY_CALIBRATION_CMD\n");
+
+		/* TODO we might want recalculate
+		 * rx_chain in rxon cmd */
+
+		/* Mark so we run this algo only once! */
+		data->state = IWL_CHAIN_NOISE_CALIBRATED;
+	}
+}
+
+
+
+/*
+ * Accumulate 16 beacons of signal and noise statistics for each of
+ *   3 receivers/antennas/rx-chains, then figure out:
+ * 1)  Which antennas are connected.
+ * 2)  Differential rx gain settings to balance the 3 receivers.
+ */
+void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
+{
+	struct iwl_chain_noise_data *data = NULL;
+
+	u32 chain_noise_a;
+	u32 chain_noise_b;
+	u32 chain_noise_c;
+	u32 chain_sig_a;
+	u32 chain_sig_b;
+	u32 chain_sig_c;
+	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
+	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
+	u16 i = 0;
+	u16 rxon_chnum = INITIALIZATION_VALUE;
+	u16 stat_chnum = INITIALIZATION_VALUE;
+	u8 rxon_band24;
+	u8 stat_band24;
+	unsigned long flags;
+	struct statistics_rx_non_phy *rx_info;
+
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (priv->disable_chain_noise_cal)
+		return;
+
+	data = &(priv->chain_noise_data);
+
+	/*
+	 * Accumulate just the first "chain_noise_num_beacons" after
+	 * the first association, then we're done forever.
+	 */
+	if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
+		if (data->state == IWL_CHAIN_NOISE_ALIVE)
+			IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rx_info = &(((struct iwl_notif_statistics *)stat_resp)->
+		      rx.general);
+
+	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
+		IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
+	rxon_chnum = le16_to_cpu(ctx->staging.channel);
+
+	stat_band24 = !!(((struct iwl_notif_statistics *)
+			 stat_resp)->flag &
+			 STATISTICS_REPLY_FLG_BAND_24G_MSK);
+	stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *)
+				 stat_resp)->flag) >> 16;
+
+	/* Make sure we accumulate data for just the associated channel
+	 *   (even if scanning). */
+	if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
+		IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
+				rxon_chnum, rxon_band24);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	/*
+	 *  Accumulate beacon statistics values across
+	 * "chain_noise_num_beacons"
+	 */
+	chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
+				IN_BAND_FILTER;
+	chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
+				IN_BAND_FILTER;
+	chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
+				IN_BAND_FILTER;
+
+	chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
+	chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
+	chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	data->beacon_count++;
+
+	data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
+	data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
+	data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
+
+	data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
+	data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
+	data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
+
+	IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n",
+			rxon_chnum, rxon_band24, data->beacon_count);
+	IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n",
+			chain_sig_a, chain_sig_b, chain_sig_c);
+	IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
+			chain_noise_a, chain_noise_b, chain_noise_c);
+
+	/* If this is the "chain_noise_num_beacons", determine:
+	 * 1)  Disconnected antennas (using signal strengths)
+	 * 2)  Differential gain (using silence noise) to balance receivers */
+	if (data->beacon_count !=
+		priv->cfg->base_params->chain_noise_num_beacons)
+		return;
+
+	/* Analyze signal for disconnected antenna */
+	iwl4965_find_disconn_antenna(priv, average_sig, data);
+
+	/* Analyze noise for rx balance */
+	average_noise[0] = data->chain_noise_a /
+			   priv->cfg->base_params->chain_noise_num_beacons;
+	average_noise[1] = data->chain_noise_b /
+			   priv->cfg->base_params->chain_noise_num_beacons;
+	average_noise[2] = data->chain_noise_c /
+			   priv->cfg->base_params->chain_noise_num_beacons;
+
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (!(data->disconn_array[i]) &&
+		   (average_noise[i] <= min_average_noise)) {
+			/* This means that chain i is active and has
+			 * lower noise values so far: */
+			min_average_noise = average_noise[i];
+			min_average_noise_antenna_i = i;
+		}
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n",
+			average_noise[0], average_noise[1],
+			average_noise[2]);
+
+	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
+			min_average_noise, min_average_noise_antenna_i);
+
+	iwl4965_gain_computation(priv, average_noise,
+			min_average_noise_antenna_i, min_average_noise,
+			iwl4965_find_first_chain(priv->cfg->valid_rx_ant));
+
+	/* Some power changes may have been made during the calibration.
+	 * Update and commit the RXON
+	 */
+	if (priv->cfg->ops->lib->update_chain_flags)
+		priv->cfg->ops->lib->update_chain_flags(priv);
+
+	data->state = IWL_CHAIN_NOISE_DONE;
+	iwl_legacy_power_update_mode(priv, false);
+}
+
+void iwl4965_reset_run_time_calib(struct iwl_priv *priv)
+{
+	int i;
+	memset(&(priv->sensitivity_data), 0,
+	       sizeof(struct iwl_sensitivity_data));
+	memset(&(priv->chain_noise_data), 0,
+	       sizeof(struct iwl_chain_noise_data));
+	for (i = 0; i < NUM_RX_CHAINS; i++)
+		priv->chain_noise_data.delta_gain_code[i] =
+				CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+
+	/* Ask for statistics now, the uCode will send notification
+	 * periodically after association */
+	iwl_legacy_send_statistics_request(priv, CMD_ASYNC, true);
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-calib.h b/drivers/net/wireless/iwlegacy/iwl-4965-calib.h
new file mode 100644
index 0000000..f46c80e
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-calib.h
@@ -0,0 +1,75 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#ifndef __iwl_4965_calib_h__
+#define __iwl_4965_calib_h__
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-commands.h"
+
+void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
+void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp);
+void iwl4965_init_sensitivity(struct iwl_priv *priv);
+void iwl4965_reset_run_time_calib(struct iwl_priv *priv);
+void iwl4965_calib_free_results(struct iwl_priv *priv);
+
+#endif /* __iwl_4965_calib_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c
new file mode 100644
index 0000000..1c93665
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c
@@ -0,0 +1,774 @@
+/******************************************************************************
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of version 2 of the GNU General Public License as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+* USA
+*
+* The full GNU General Public License is included in this distribution
+* in the file called LICENSE.GPL.
+*
+* Contact Information:
+*  Intel Linux Wireless <ilw@linux.intel.com>
+* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*****************************************************************************/
+#include "iwl-4965.h"
+#include "iwl-4965-debugfs.h"
+
+static const char *fmt_value = "  %-30s %10u\n";
+static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
+static const char *fmt_header =
+	"%-32s    current  cumulative       delta         max\n";
+
+static int iwl4965_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
+{
+	int p = 0;
+	u32 flag;
+
+	flag = le32_to_cpu(priv->_4965.statistics.flag);
+
+	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
+	if (flag & UCODE_STATISTICS_CLEAR_MSK)
+		p += scnprintf(buf + p, bufsz - p,
+		"\tStatistics have been cleared\n");
+	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
+		(flag & UCODE_STATISTICS_FREQUENCY_MSK)
+		? "2.4 GHz" : "5.2 GHz");
+	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
+		(flag & UCODE_STATISTICS_NARROW_BAND_MSK)
+		 ? "enabled" : "disabled");
+
+	return p;
+}
+
+ssize_t iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct statistics_rx_phy) * 40 +
+		    sizeof(struct statistics_rx_non_phy) * 40 +
+		    sizeof(struct statistics_rx_ht_phy) * 40 + 400;
+	ssize_t ret;
+	struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
+	struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+	struct statistics_rx_non_phy *general, *accum_general;
+	struct statistics_rx_non_phy *delta_general, *max_general;
+	struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * the statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	ofdm = &priv->_4965.statistics.rx.ofdm;
+	cck = &priv->_4965.statistics.rx.cck;
+	general = &priv->_4965.statistics.rx.general;
+	ht = &priv->_4965.statistics.rx.ofdm_ht;
+	accum_ofdm = &priv->_4965.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_4965.accum_statistics.rx.cck;
+	accum_general = &priv->_4965.accum_statistics.rx.general;
+	accum_ht = &priv->_4965.accum_statistics.rx.ofdm_ht;
+	delta_ofdm = &priv->_4965.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_4965.delta_statistics.rx.cck;
+	delta_general = &priv->_4965.delta_statistics.rx.general;
+	delta_ht = &priv->_4965.delta_statistics.rx.ofdm_ht;
+	max_ofdm = &priv->_4965.max_delta.rx.ofdm;
+	max_cck = &priv->_4965.max_delta.rx.cck;
+	max_general = &priv->_4965.max_delta.rx.general;
+	max_ht = &priv->_4965.max_delta.rx.ofdm_ht;
+
+	pos += iwl4965_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - OFDM:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ina_cnt:",
+			 le32_to_cpu(ofdm->ina_cnt),
+			 accum_ofdm->ina_cnt,
+			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_cnt:",
+			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "plcp_err:",
+			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_err:",
+			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "overrun_err:",
+			 le32_to_cpu(ofdm->overrun_err),
+			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
+			 max_ofdm->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "early_overrun_err:",
+			 le32_to_cpu(ofdm->early_overrun_err),
+			 accum_ofdm->early_overrun_err,
+			 delta_ofdm->early_overrun_err,
+			 max_ofdm->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_good:",
+			 le32_to_cpu(ofdm->crc32_good),
+			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
+			 max_ofdm->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "false_alarm_cnt:",
+			 le32_to_cpu(ofdm->false_alarm_cnt),
+			 accum_ofdm->false_alarm_cnt,
+			 delta_ofdm->false_alarm_cnt,
+			 max_ofdm->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_sync_err_cnt:",
+			 le32_to_cpu(ofdm->fina_sync_err_cnt),
+			 accum_ofdm->fina_sync_err_cnt,
+			 delta_ofdm->fina_sync_err_cnt,
+			 max_ofdm->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sfd_timeout:",
+			 le32_to_cpu(ofdm->sfd_timeout),
+			 accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
+			 max_ofdm->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_timeout:",
+			 le32_to_cpu(ofdm->fina_timeout),
+			 accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
+			 max_ofdm->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "unresponded_rts:",
+			 le32_to_cpu(ofdm->unresponded_rts),
+			 accum_ofdm->unresponded_rts,
+			 delta_ofdm->unresponded_rts,
+			 max_ofdm->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+			 accum_ofdm->rxe_frame_limit_overrun,
+			 delta_ofdm->rxe_frame_limit_overrun,
+			 max_ofdm->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ack_cnt:",
+			 le32_to_cpu(ofdm->sent_ack_cnt),
+			 accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
+			 max_ofdm->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_cts_cnt:",
+			 le32_to_cpu(ofdm->sent_cts_cnt),
+			 accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
+			 max_ofdm->sent_cts_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ba_rsp_cnt:",
+			 le32_to_cpu(ofdm->sent_ba_rsp_cnt),
+			 accum_ofdm->sent_ba_rsp_cnt,
+			 delta_ofdm->sent_ba_rsp_cnt,
+			 max_ofdm->sent_ba_rsp_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dsp_self_kill:",
+			 le32_to_cpu(ofdm->dsp_self_kill),
+			 accum_ofdm->dsp_self_kill,
+			 delta_ofdm->dsp_self_kill,
+			 max_ofdm->dsp_self_kill);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "mh_format_err:",
+			 le32_to_cpu(ofdm->mh_format_err),
+			 accum_ofdm->mh_format_err,
+			 delta_ofdm->mh_format_err,
+			 max_ofdm->mh_format_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "re_acq_main_rssi_sum:",
+			 le32_to_cpu(ofdm->re_acq_main_rssi_sum),
+			 accum_ofdm->re_acq_main_rssi_sum,
+			 delta_ofdm->re_acq_main_rssi_sum,
+			 max_ofdm->re_acq_main_rssi_sum);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - CCK:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ina_cnt:",
+			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+			 delta_cck->ina_cnt, max_cck->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_cnt:",
+			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+			 delta_cck->fina_cnt, max_cck->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "plcp_err:",
+			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+			 delta_cck->plcp_err, max_cck->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_err:",
+			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+			 delta_cck->crc32_err, max_cck->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "overrun_err:",
+			 le32_to_cpu(cck->overrun_err),
+			 accum_cck->overrun_err, delta_cck->overrun_err,
+			 max_cck->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "early_overrun_err:",
+			 le32_to_cpu(cck->early_overrun_err),
+			 accum_cck->early_overrun_err,
+			 delta_cck->early_overrun_err,
+			 max_cck->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_good:",
+			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+			 delta_cck->crc32_good, max_cck->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "false_alarm_cnt:",
+			 le32_to_cpu(cck->false_alarm_cnt),
+			 accum_cck->false_alarm_cnt,
+			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_sync_err_cnt:",
+			 le32_to_cpu(cck->fina_sync_err_cnt),
+			 accum_cck->fina_sync_err_cnt,
+			 delta_cck->fina_sync_err_cnt,
+			 max_cck->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sfd_timeout:",
+			 le32_to_cpu(cck->sfd_timeout),
+			 accum_cck->sfd_timeout, delta_cck->sfd_timeout,
+			 max_cck->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_timeout:",
+			 le32_to_cpu(cck->fina_timeout),
+			 accum_cck->fina_timeout, delta_cck->fina_timeout,
+			 max_cck->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "unresponded_rts:",
+			 le32_to_cpu(cck->unresponded_rts),
+			 accum_cck->unresponded_rts, delta_cck->unresponded_rts,
+			 max_cck->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(cck->rxe_frame_limit_overrun),
+			 accum_cck->rxe_frame_limit_overrun,
+			 delta_cck->rxe_frame_limit_overrun,
+			 max_cck->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ack_cnt:",
+			 le32_to_cpu(cck->sent_ack_cnt),
+			 accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
+			 max_cck->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_cts_cnt:",
+			 le32_to_cpu(cck->sent_cts_cnt),
+			 accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
+			 max_cck->sent_cts_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ba_rsp_cnt:",
+			 le32_to_cpu(cck->sent_ba_rsp_cnt),
+			 accum_cck->sent_ba_rsp_cnt,
+			 delta_cck->sent_ba_rsp_cnt,
+			 max_cck->sent_ba_rsp_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dsp_self_kill:",
+			 le32_to_cpu(cck->dsp_self_kill),
+			 accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
+			 max_cck->dsp_self_kill);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "mh_format_err:",
+			 le32_to_cpu(cck->mh_format_err),
+			 accum_cck->mh_format_err, delta_cck->mh_format_err,
+			 max_cck->mh_format_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "re_acq_main_rssi_sum:",
+			 le32_to_cpu(cck->re_acq_main_rssi_sum),
+			 accum_cck->re_acq_main_rssi_sum,
+			 delta_cck->re_acq_main_rssi_sum,
+			 max_cck->re_acq_main_rssi_sum);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - GENERAL:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bogus_cts:",
+			 le32_to_cpu(general->bogus_cts),
+			 accum_general->bogus_cts, delta_general->bogus_cts,
+			 max_general->bogus_cts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bogus_ack:",
+			 le32_to_cpu(general->bogus_ack),
+			 accum_general->bogus_ack, delta_general->bogus_ack,
+			 max_general->bogus_ack);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "non_bssid_frames:",
+			 le32_to_cpu(general->non_bssid_frames),
+			 accum_general->non_bssid_frames,
+			 delta_general->non_bssid_frames,
+			 max_general->non_bssid_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "filtered_frames:",
+			 le32_to_cpu(general->filtered_frames),
+			 accum_general->filtered_frames,
+			 delta_general->filtered_frames,
+			 max_general->filtered_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "non_channel_beacons:",
+			 le32_to_cpu(general->non_channel_beacons),
+			 accum_general->non_channel_beacons,
+			 delta_general->non_channel_beacons,
+			 max_general->non_channel_beacons);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "channel_beacons:",
+			 le32_to_cpu(general->channel_beacons),
+			 accum_general->channel_beacons,
+			 delta_general->channel_beacons,
+			 max_general->channel_beacons);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "num_missed_bcon:",
+			 le32_to_cpu(general->num_missed_bcon),
+			 accum_general->num_missed_bcon,
+			 delta_general->num_missed_bcon,
+			 max_general->num_missed_bcon);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "adc_rx_saturation_time:",
+			 le32_to_cpu(general->adc_rx_saturation_time),
+			 accum_general->adc_rx_saturation_time,
+			 delta_general->adc_rx_saturation_time,
+			 max_general->adc_rx_saturation_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ina_detect_search_tm:",
+			 le32_to_cpu(general->ina_detection_search_time),
+			 accum_general->ina_detection_search_time,
+			 delta_general->ina_detection_search_time,
+			 max_general->ina_detection_search_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_silence_rssi_a:",
+			 le32_to_cpu(general->beacon_silence_rssi_a),
+			 accum_general->beacon_silence_rssi_a,
+			 delta_general->beacon_silence_rssi_a,
+			 max_general->beacon_silence_rssi_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_silence_rssi_b:",
+			 le32_to_cpu(general->beacon_silence_rssi_b),
+			 accum_general->beacon_silence_rssi_b,
+			 delta_general->beacon_silence_rssi_b,
+			 max_general->beacon_silence_rssi_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_silence_rssi_c:",
+			 le32_to_cpu(general->beacon_silence_rssi_c),
+			 accum_general->beacon_silence_rssi_c,
+			 delta_general->beacon_silence_rssi_c,
+			 max_general->beacon_silence_rssi_c);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "interference_data_flag:",
+			 le32_to_cpu(general->interference_data_flag),
+			 accum_general->interference_data_flag,
+			 delta_general->interference_data_flag,
+			 max_general->interference_data_flag);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "channel_load:",
+			 le32_to_cpu(general->channel_load),
+			 accum_general->channel_load,
+			 delta_general->channel_load,
+			 max_general->channel_load);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dsp_false_alarms:",
+			 le32_to_cpu(general->dsp_false_alarms),
+			 accum_general->dsp_false_alarms,
+			 delta_general->dsp_false_alarms,
+			 max_general->dsp_false_alarms);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_rssi_a:",
+			 le32_to_cpu(general->beacon_rssi_a),
+			 accum_general->beacon_rssi_a,
+			 delta_general->beacon_rssi_a,
+			 max_general->beacon_rssi_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_rssi_b:",
+			 le32_to_cpu(general->beacon_rssi_b),
+			 accum_general->beacon_rssi_b,
+			 delta_general->beacon_rssi_b,
+			 max_general->beacon_rssi_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_rssi_c:",
+			 le32_to_cpu(general->beacon_rssi_c),
+			 accum_general->beacon_rssi_c,
+			 delta_general->beacon_rssi_c,
+			 max_general->beacon_rssi_c);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_energy_a:",
+			 le32_to_cpu(general->beacon_energy_a),
+			 accum_general->beacon_energy_a,
+			 delta_general->beacon_energy_a,
+			 max_general->beacon_energy_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_energy_b:",
+			 le32_to_cpu(general->beacon_energy_b),
+			 accum_general->beacon_energy_b,
+			 delta_general->beacon_energy_b,
+			 max_general->beacon_energy_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_energy_c:",
+			 le32_to_cpu(general->beacon_energy_c),
+			 accum_general->beacon_energy_c,
+			 delta_general->beacon_energy_c,
+			 max_general->beacon_energy_c);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - OFDM_HT:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "plcp_err:",
+			 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
+			 delta_ht->plcp_err, max_ht->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "overrun_err:",
+			 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
+			 delta_ht->overrun_err, max_ht->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "early_overrun_err:",
+			 le32_to_cpu(ht->early_overrun_err),
+			 accum_ht->early_overrun_err,
+			 delta_ht->early_overrun_err,
+			 max_ht->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_good:",
+			 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
+			 delta_ht->crc32_good, max_ht->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_err:",
+			 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
+			 delta_ht->crc32_err, max_ht->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "mh_format_err:",
+			 le32_to_cpu(ht->mh_format_err),
+			 accum_ht->mh_format_err,
+			 delta_ht->mh_format_err, max_ht->mh_format_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg_crc32_good:",
+			 le32_to_cpu(ht->agg_crc32_good),
+			 accum_ht->agg_crc32_good,
+			 delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg_mpdu_cnt:",
+			 le32_to_cpu(ht->agg_mpdu_cnt),
+			 accum_ht->agg_mpdu_cnt,
+			 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg_cnt:",
+			 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
+			 delta_ht->agg_cnt, max_ht->agg_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "unsupport_mcs:",
+			 le32_to_cpu(ht->unsupport_mcs),
+			 accum_ht->unsupport_mcs,
+			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl4965_ucode_tx_stats_read(struct file *file,
+				char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
+	ssize_t ret;
+	struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	  * the last statistics notification from uCode
+	  * might not reflect the current uCode activity
+	  */
+	tx = &priv->_4965.statistics.tx;
+	accum_tx = &priv->_4965.accum_statistics.tx;
+	delta_tx = &priv->_4965.delta_statistics.tx;
+	max_tx = &priv->_4965.max_delta.tx;
+
+	pos += iwl4965_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Tx:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "preamble:",
+			 le32_to_cpu(tx->preamble_cnt),
+			 accum_tx->preamble_cnt,
+			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rx_detected_cnt:",
+			 le32_to_cpu(tx->rx_detected_cnt),
+			 accum_tx->rx_detected_cnt,
+			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bt_prio_defer_cnt:",
+			 le32_to_cpu(tx->bt_prio_defer_cnt),
+			 accum_tx->bt_prio_defer_cnt,
+			 delta_tx->bt_prio_defer_cnt,
+			 max_tx->bt_prio_defer_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bt_prio_kill_cnt:",
+			 le32_to_cpu(tx->bt_prio_kill_cnt),
+			 accum_tx->bt_prio_kill_cnt,
+			 delta_tx->bt_prio_kill_cnt,
+			 max_tx->bt_prio_kill_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "few_bytes_cnt:",
+			 le32_to_cpu(tx->few_bytes_cnt),
+			 accum_tx->few_bytes_cnt,
+			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "cts_timeout:",
+			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+			 delta_tx->cts_timeout, max_tx->cts_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ack_timeout:",
+			 le32_to_cpu(tx->ack_timeout),
+			 accum_tx->ack_timeout,
+			 delta_tx->ack_timeout, max_tx->ack_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "expected_ack_cnt:",
+			 le32_to_cpu(tx->expected_ack_cnt),
+			 accum_tx->expected_ack_cnt,
+			 delta_tx->expected_ack_cnt,
+			 max_tx->expected_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "actual_ack_cnt:",
+			 le32_to_cpu(tx->actual_ack_cnt),
+			 accum_tx->actual_ack_cnt,
+			 delta_tx->actual_ack_cnt,
+			 max_tx->actual_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dump_msdu_cnt:",
+			 le32_to_cpu(tx->dump_msdu_cnt),
+			 accum_tx->dump_msdu_cnt,
+			 delta_tx->dump_msdu_cnt,
+			 max_tx->dump_msdu_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "abort_nxt_frame_mismatch:",
+			 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
+			 accum_tx->burst_abort_next_frame_mismatch_cnt,
+			 delta_tx->burst_abort_next_frame_mismatch_cnt,
+			 max_tx->burst_abort_next_frame_mismatch_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "abort_missing_nxt_frame:",
+			 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
+			 accum_tx->burst_abort_missing_next_frame_cnt,
+			 delta_tx->burst_abort_missing_next_frame_cnt,
+			 max_tx->burst_abort_missing_next_frame_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "cts_timeout_collision:",
+			 le32_to_cpu(tx->cts_timeout_collision),
+			 accum_tx->cts_timeout_collision,
+			 delta_tx->cts_timeout_collision,
+			 max_tx->cts_timeout_collision);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ack_ba_timeout_collision:",
+			 le32_to_cpu(tx->ack_or_ba_timeout_collision),
+			 accum_tx->ack_or_ba_timeout_collision,
+			 delta_tx->ack_or_ba_timeout_collision,
+			 max_tx->ack_or_ba_timeout_collision);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg ba_timeout:",
+			 le32_to_cpu(tx->agg.ba_timeout),
+			 accum_tx->agg.ba_timeout,
+			 delta_tx->agg.ba_timeout,
+			 max_tx->agg.ba_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg ba_resched_frames:",
+			 le32_to_cpu(tx->agg.ba_reschedule_frames),
+			 accum_tx->agg.ba_reschedule_frames,
+			 delta_tx->agg.ba_reschedule_frames,
+			 max_tx->agg.ba_reschedule_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_agg_frame:",
+			 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
+			 accum_tx->agg.scd_query_agg_frame_cnt,
+			 delta_tx->agg.scd_query_agg_frame_cnt,
+			 max_tx->agg.scd_query_agg_frame_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_no_agg:",
+			 le32_to_cpu(tx->agg.scd_query_no_agg),
+			 accum_tx->agg.scd_query_no_agg,
+			 delta_tx->agg.scd_query_no_agg,
+			 max_tx->agg.scd_query_no_agg);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_agg:",
+			 le32_to_cpu(tx->agg.scd_query_agg),
+			 accum_tx->agg.scd_query_agg,
+			 delta_tx->agg.scd_query_agg,
+			 max_tx->agg.scd_query_agg);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_mismatch:",
+			 le32_to_cpu(tx->agg.scd_query_mismatch),
+			 accum_tx->agg.scd_query_mismatch,
+			 delta_tx->agg.scd_query_mismatch,
+			 max_tx->agg.scd_query_mismatch);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg frame_not_ready:",
+			 le32_to_cpu(tx->agg.frame_not_ready),
+			 accum_tx->agg.frame_not_ready,
+			 delta_tx->agg.frame_not_ready,
+			 max_tx->agg.frame_not_ready);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg underrun:",
+			 le32_to_cpu(tx->agg.underrun),
+			 accum_tx->agg.underrun,
+			 delta_tx->agg.underrun, max_tx->agg.underrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg bt_prio_kill:",
+			 le32_to_cpu(tx->agg.bt_prio_kill),
+			 accum_tx->agg.bt_prio_kill,
+			 delta_tx->agg.bt_prio_kill,
+			 max_tx->agg.bt_prio_kill);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg rx_ba_rsp_cnt:",
+			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
+			 accum_tx->agg.rx_ba_rsp_cnt,
+			 delta_tx->agg.rx_ba_rsp_cnt,
+			 max_tx->agg.rx_ba_rsp_cnt);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t
+iwl4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
+				     size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct statistics_general) * 10 + 300;
+	ssize_t ret;
+	struct statistics_general_common *general, *accum_general;
+	struct statistics_general_common *delta_general, *max_general;
+	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+	struct statistics_div *div, *accum_div, *delta_div, *max_div;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	  * the last statistics notification from uCode
+	  * might not reflect the current uCode activity
+	  */
+	general = &priv->_4965.statistics.general.common;
+	dbg = &priv->_4965.statistics.general.common.dbg;
+	div = &priv->_4965.statistics.general.common.div;
+	accum_general = &priv->_4965.accum_statistics.general.common;
+	accum_dbg = &priv->_4965.accum_statistics.general.common.dbg;
+	accum_div = &priv->_4965.accum_statistics.general.common.div;
+	delta_general = &priv->_4965.delta_statistics.general.common;
+	max_general = &priv->_4965.max_delta.general.common;
+	delta_dbg = &priv->_4965.delta_statistics.general.common.dbg;
+	max_dbg = &priv->_4965.max_delta.general.common.dbg;
+	delta_div = &priv->_4965.delta_statistics.general.common.div;
+	max_div = &priv->_4965.max_delta.general.common.div;
+
+	pos += iwl4965_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_General:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_value, "temperature:",
+			 le32_to_cpu(general->temperature));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_value, "ttl_timestamp:",
+			 le32_to_cpu(general->ttl_timestamp));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "burst_check:",
+			 le32_to_cpu(dbg->burst_check),
+			 accum_dbg->burst_check,
+			 delta_dbg->burst_check, max_dbg->burst_check);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "burst_count:",
+			 le32_to_cpu(dbg->burst_count),
+			 accum_dbg->burst_count,
+			 delta_dbg->burst_count, max_dbg->burst_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "wait_for_silence_timeout_count:",
+			 le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
+			 accum_dbg->wait_for_silence_timeout_cnt,
+			 delta_dbg->wait_for_silence_timeout_cnt,
+			 max_dbg->wait_for_silence_timeout_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sleep_time:",
+			 le32_to_cpu(general->sleep_time),
+			 accum_general->sleep_time,
+			 delta_general->sleep_time, max_general->sleep_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "slots_out:",
+			 le32_to_cpu(general->slots_out),
+			 accum_general->slots_out,
+			 delta_general->slots_out, max_general->slots_out);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "slots_idle:",
+			 le32_to_cpu(general->slots_idle),
+			 accum_general->slots_idle,
+			 delta_general->slots_idle, max_general->slots_idle);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "tx_on_a:",
+			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+			 delta_div->tx_on_a, max_div->tx_on_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "tx_on_b:",
+			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+			 delta_div->tx_on_b, max_div->tx_on_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "exec_time:",
+			 le32_to_cpu(div->exec_time), accum_div->exec_time,
+			 delta_div->exec_time, max_div->exec_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "probe_time:",
+			 le32_to_cpu(div->probe_time), accum_div->probe_time,
+			 delta_div->probe_time, max_div->probe_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rx_enable_counter:",
+			 le32_to_cpu(general->rx_enable_counter),
+			 accum_general->rx_enable_counter,
+			 delta_general->rx_enable_counter,
+			 max_general->rx_enable_counter);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "num_of_sos_states:",
+			 le32_to_cpu(general->num_of_sos_states),
+			 accum_general->num_of_sos_states,
+			 delta_general->num_of_sos_states,
+			 max_general->num_of_sos_states);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h b/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h
new file mode 100644
index 0000000..6c8e353
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+ssize_t iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos);
+ssize_t iwl4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos);
+ssize_t iwl4965_ucode_general_stats_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos);
+#else
+static ssize_t
+iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t
+iwl4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t
+iwl4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
+					    size_t count, loff_t *ppos)
+{
+	return 0;
+}
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c
new file mode 100644
index 0000000..cb9baab
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c
@@ -0,0 +1,154 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-4965.h"
+#include "iwl-io.h"
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+/*
+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
+ * when accessing the EEPROM; each access is a series of pulses to/from the
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+int iwl4965_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+	u16 count;
+	int ret;
+
+	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+		/* Request semaphore */
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+		/* See if we got it */
+		ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+				EEPROM_SEM_TIMEOUT);
+		if (ret >= 0) {
+			IWL_DEBUG_IO(priv,
+				"Acquired semaphore after %d tries.\n",
+				count+1);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+void iwl4965_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+	iwl_legacy_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
+int iwl4965_eeprom_check_version(struct iwl_priv *priv)
+{
+	u16 eeprom_ver;
+	u16 calib_ver;
+
+	eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
+	calib_ver = iwl_legacy_eeprom_query16(priv,
+			EEPROM_4965_CALIB_VERSION_OFFSET);
+
+	if (eeprom_ver < priv->cfg->eeprom_ver ||
+	    calib_ver < priv->cfg->eeprom_calib_ver)
+		goto err;
+
+	IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+		 eeprom_ver, calib_ver);
+
+	return 0;
+err:
+	IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
+		  "CALIB=0x%x < 0x%x\n",
+		  eeprom_ver, priv->cfg->eeprom_ver,
+		  calib_ver,  priv->cfg->eeprom_calib_ver);
+	return -EINVAL;
+
+}
+
+void iwl4965_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+	const u8 *addr = iwl_legacy_eeprom_query_addr(priv,
+					EEPROM_MAC_ADDRESS);
+	memcpy(mac, addr, ETH_ALEN);
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-hw.h b/drivers/net/wireless/iwlegacy/iwl-4965-hw.h
new file mode 100644
index 0000000..08b189c
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-hw.h
@@ -0,0 +1,814 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
+ * Use iwl-commands.h for uCode API definitions.
+ * Use iwl-dev.h for driver implementation definitions.
+ */
+
+#ifndef __iwl_4965_hw_h__
+#define __iwl_4965_hw_h__
+
+#include "iwl-fh.h"
+
+/* EEPROM */
+#define IWL4965_EEPROM_IMG_SIZE			1024
+
+/*
+ * uCode queue management definitions ...
+ * The first queue used for block-ack aggregation is #7 (4965 only).
+ * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
+ */
+#define IWL49_FIRST_AMPDU_QUEUE	7
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+#define IWL49_RTC_INST_LOWER_BOUND		(0x000000)
+#define IWL49_RTC_INST_UPPER_BOUND		(0x018000)
+
+#define IWL49_RTC_DATA_LOWER_BOUND		(0x800000)
+#define IWL49_RTC_DATA_UPPER_BOUND		(0x80A000)
+
+#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - \
+				IWL49_RTC_INST_LOWER_BOUND)
+#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - \
+				IWL49_RTC_DATA_LOWER_BOUND)
+
+#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
+#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
+
+static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
+{
+	return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
+	       (addr < IWL49_RTC_DATA_UPPER_BOUND);
+}
+
+/********************* START TEMPERATURE *************************************/
+
+/**
+ * 4965 temperature calculation.
+ *
+ * The driver must calculate the device temperature before calculating
+ * a txpower setting (amplifier gain is temperature dependent).  The
+ * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
+ * values used for the life of the driver, and one of which (R4) is the
+ * real-time temperature indicator.
+ *
+ * uCode provides all 4 values to the driver via the "initialize alive"
+ * notification (see struct iwl4965_init_alive_resp).  After the runtime uCode
+ * image loads, uCode updates the R4 value via statistics notifications
+ * (see STATISTICS_NOTIFICATION), which occur after each received beacon
+ * when associated, or can be requested via REPLY_STATISTICS_CMD.
+ *
+ * NOTE:  uCode provides the R4 value as a 23-bit signed value.  Driver
+ *        must sign-extend to 32 bits before applying formula below.
+ *
+ * Formula:
+ *
+ * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
+ *
+ * NOTE:  The basic formula is 259 * (R4-R2) / (R3-R1).  The 97/100 is
+ * an additional correction, which should be centered around 0 degrees
+ * Celsius (273 degrees Kelvin).  The 8 (3 percent of 273) compensates for
+ * centering the 97/100 correction around 0 degrees K.
+ *
+ * Add 273 to Kelvin value to find degrees Celsius, for comparing current
+ * temperature with factory-measured temperatures when calculating txpower
+ * settings.
+ */
+#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
+#define TEMPERATURE_CALIB_A_VAL 259
+
+/* Limit range of calculated temperature to be between these Kelvin values */
+#define IWL_TX_POWER_TEMPERATURE_MIN  (263)
+#define IWL_TX_POWER_TEMPERATURE_MAX  (410)
+
+#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
+	(((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
+	 ((t) > IWL_TX_POWER_TEMPERATURE_MAX))
+
+/********************* END TEMPERATURE ***************************************/
+
+/********************* START TXPOWER *****************************************/
+
+/**
+ * 4965 txpower calculations rely on information from three sources:
+ *
+ *     1) EEPROM
+ *     2) "initialize" alive notification
+ *     3) statistics notifications
+ *
+ * EEPROM data consists of:
+ *
+ * 1)  Regulatory information (max txpower and channel usage flags) is provided
+ *     separately for each channel that can possibly supported by 4965.
+ *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
+ *     (legacy) channels.
+ *
+ *     See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
+ *     for locations in EEPROM.
+ *
+ * 2)  Factory txpower calibration information is provided separately for
+ *     sub-bands of contiguous channels.  2.4GHz has just one sub-band,
+ *     but 5 GHz has several sub-bands.
+ *
+ *     In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
+ *
+ *     See struct iwl4965_eeprom_calib_info (and the tree of structures
+ *     contained within it) for format, and struct iwl4965_eeprom for
+ *     locations in EEPROM.
+ *
+ * "Initialization alive" notification (see struct iwl4965_init_alive_resp)
+ * consists of:
+ *
+ * 1)  Temperature calculation parameters.
+ *
+ * 2)  Power supply voltage measurement.
+ *
+ * 3)  Tx gain compensation to balance 2 transmitters for MIMO use.
+ *
+ * Statistics notifications deliver:
+ *
+ * 1)  Current values for temperature param R4.
+ */
+
+/**
+ * To calculate a txpower setting for a given desired target txpower, channel,
+ * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
+ * support MIMO and transmit diversity), driver must do the following:
+ *
+ * 1)  Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
+ *     Do not exceed regulatory limit; reduce target txpower if necessary.
+ *
+ *     If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
+ *     2 transmitters will be used simultaneously; driver must reduce the
+ *     regulatory limit by 3 dB (half-power) for each transmitter, so the
+ *     combined total output of the 2 transmitters is within regulatory limits.
+ *
+ *
+ * 2)  Compare target txpower vs. (EEPROM) saturation txpower *reduced by
+ *     backoff for this bit rate*.  Do not exceed (saturation - backoff[rate]);
+ *     reduce target txpower if necessary.
+ *
+ *     Backoff values below are in 1/2 dB units (equivalent to steps in
+ *     txpower gain tables):
+ *
+ *     OFDM 6 - 36 MBit:  10 steps (5 dB)
+ *     OFDM 48 MBit:      15 steps (7.5 dB)
+ *     OFDM 54 MBit:      17 steps (8.5 dB)
+ *     OFDM 60 MBit:      20 steps (10 dB)
+ *     CCK all rates:     10 steps (5 dB)
+ *
+ *     Backoff values apply to saturation txpower on a per-transmitter basis;
+ *     when using MIMO (2 transmitters), each transmitter uses the same
+ *     saturation level provided in EEPROM, and the same backoff values;
+ *     no reduction (such as with regulatory txpower limits) is required.
+ *
+ *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
+ *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
+ *     factory measurement for ht40 channels.
+ *
+ *     The result of this step is the final target txpower.  The rest of
+ *     the steps figure out the proper settings for the device to achieve
+ *     that target txpower.
+ *
+ *
+ * 3)  Determine (EEPROM) calibration sub band for the target channel, by
+ *     comparing against first and last channels in each sub band
+ *     (see struct iwl4965_eeprom_calib_subband_info).
+ *
+ *
+ * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
+ *     referencing the 2 factory-measured (sample) channels within the sub band.
+ *
+ *     Interpolation is based on difference between target channel's frequency
+ *     and the sample channels' frequencies.  Since channel numbers are based
+ *     on frequency (5 MHz between each channel number), this is equivalent
+ *     to interpolating based on channel number differences.
+ *
+ *     Note that the sample channels may or may not be the channels at the
+ *     edges of the sub band.  The target channel may be "outside" of the
+ *     span of the sampled channels.
+ *
+ *     Driver may choose the pair (for 2 Tx chains) of measurements (see
+ *     struct iwl4965_eeprom_calib_ch_info) for which the actual measured
+ *     txpower comes closest to the desired txpower.  Usually, though,
+ *     the middle set of measurements is closest to the regulatory limits,
+ *     and is therefore a good choice for all txpower calculations (this
+ *     assumes that high accuracy is needed for maximizing legal txpower,
+ *     while lower txpower configurations do not need as much accuracy).
+ *
+ *     Driver should interpolate both members of the chosen measurement pair,
+ *     i.e. for both Tx chains (radio transmitters), unless the driver knows
+ *     that only one of the chains will be used (e.g. only one tx antenna
+ *     connected, but this should be unusual).  The rate scaling algorithm
+ *     switches antennas to find best performance, so both Tx chains will
+ *     be used (although only one at a time) even for non-MIMO transmissions.
+ *
+ *     Driver should interpolate factory values for temperature, gain table
+ *     index, and actual power.  The power amplifier detector values are
+ *     not used by the driver.
+ *
+ *     Sanity check:  If the target channel happens to be one of the sample
+ *     channels, the results should agree with the sample channel's
+ *     measurements!
+ *
+ *
+ * 5)  Find difference between desired txpower and (interpolated)
+ *     factory-measured txpower.  Using (interpolated) factory gain table index
+ *     (shown elsewhere) as a starting point, adjust this index lower to
+ *     increase txpower, or higher to decrease txpower, until the target
+ *     txpower is reached.  Each step in the gain table is 1/2 dB.
+ *
+ *     For example, if factory measured txpower is 16 dBm, and target txpower
+ *     is 13 dBm, add 6 steps to the factory gain index to reduce txpower
+ *     by 3 dB.
+ *
+ *
+ * 6)  Find difference between current device temperature and (interpolated)
+ *     factory-measured temperature for sub-band.  Factory values are in
+ *     degrees Celsius.  To calculate current temperature, see comments for
+ *     "4965 temperature calculation".
+ *
+ *     If current temperature is higher than factory temperature, driver must
+ *     increase gain (lower gain table index), and vice verse.
+ *
+ *     Temperature affects gain differently for different channels:
+ *
+ *     2.4 GHz all channels:  3.5 degrees per half-dB step
+ *     5 GHz channels 34-43:  4.5 degrees per half-dB step
+ *     5 GHz channels >= 44:  4.0 degrees per half-dB step
+ *
+ *     NOTE:  Temperature can increase rapidly when transmitting, especially
+ *            with heavy traffic at high txpowers.  Driver should update
+ *            temperature calculations often under these conditions to
+ *            maintain strong txpower in the face of rising temperature.
+ *
+ *
+ * 7)  Find difference between current power supply voltage indicator
+ *     (from "initialize alive") and factory-measured power supply voltage
+ *     indicator (EEPROM).
+ *
+ *     If the current voltage is higher (indicator is lower) than factory
+ *     voltage, gain should be reduced (gain table index increased) by:
+ *
+ *     (eeprom - current) / 7
+ *
+ *     If the current voltage is lower (indicator is higher) than factory
+ *     voltage, gain should be increased (gain table index decreased) by:
+ *
+ *     2 * (current - eeprom) / 7
+ *
+ *     If number of index steps in either direction turns out to be > 2,
+ *     something is wrong ... just use 0.
+ *
+ *     NOTE:  Voltage compensation is independent of band/channel.
+ *
+ *     NOTE:  "Initialize" uCode measures current voltage, which is assumed
+ *            to be constant after this initial measurement.  Voltage
+ *            compensation for txpower (number of steps in gain table)
+ *            may be calculated once and used until the next uCode bootload.
+ *
+ *
+ * 8)  If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
+ *     adjust txpower for each transmitter chain, so txpower is balanced
+ *     between the two chains.  There are 5 pairs of tx_atten[group][chain]
+ *     values in "initialize alive", one pair for each of 5 channel ranges:
+ *
+ *     Group 0:  5 GHz channel 34-43
+ *     Group 1:  5 GHz channel 44-70
+ *     Group 2:  5 GHz channel 71-124
+ *     Group 3:  5 GHz channel 125-200
+ *     Group 4:  2.4 GHz all channels
+ *
+ *     Add the tx_atten[group][chain] value to the index for the target chain.
+ *     The values are signed, but are in pairs of 0 and a non-negative number,
+ *     so as to reduce gain (if necessary) of the "hotter" channel.  This
+ *     avoids any need to double-check for regulatory compliance after
+ *     this step.
+ *
+ *
+ * 9)  If setting up for a CCK rate, lower the gain by adding a CCK compensation
+ *     value to the index:
+ *
+ *     Hardware rev B:  9 steps (4.5 dB)
+ *     Hardware rev C:  5 steps (2.5 dB)
+ *
+ *     Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ *     bits [3:2], 1 = B, 2 = C.
+ *
+ *     NOTE:  This compensation is in addition to any saturation backoff that
+ *            might have been applied in an earlier step.
+ *
+ *
+ * 10) Select the gain table, based on band (2.4 vs 5 GHz).
+ *
+ *     Limit the adjusted index to stay within the table!
+ *
+ *
+ * 11) Read gain table entries for DSP and radio gain, place into appropriate
+ *     location(s) in command (struct iwl4965_txpowertable_cmd).
+ */
+
+/**
+ * When MIMO is used (2 transmitters operating simultaneously), driver should
+ * limit each transmitter to deliver a max of 3 dB below the regulatory limit
+ * for the device.  That is, use half power for each transmitter, so total
+ * txpower is within regulatory limits.
+ *
+ * The value "6" represents number of steps in gain table to reduce power 3 dB.
+ * Each step is 1/2 dB.
+ */
+#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
+
+/**
+ * CCK gain compensation.
+ *
+ * When calculating txpowers for CCK, after making sure that the target power
+ * is within regulatory and saturation limits, driver must additionally
+ * back off gain by adding these values to the gain table index.
+ *
+ * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ * bits [3:2], 1 = B, 2 = C.
+ */
+#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
+#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
+
+/*
+ * 4965 power supply voltage compensation for txpower
+ */
+#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V   (7)
+
+/**
+ * Gain tables.
+ *
+ * The following tables contain pair of values for setting txpower, i.e.
+ * gain settings for the output of the device's digital signal processor (DSP),
+ * and for the analog gain structure of the transmitter.
+ *
+ * Each entry in the gain tables represents a step of 1/2 dB.  Note that these
+ * are *relative* steps, not indications of absolute output power.  Output
+ * power varies with temperature, voltage, and channel frequency, and also
+ * requires consideration of average power (to satisfy regulatory constraints),
+ * and peak power (to avoid distortion of the output signal).
+ *
+ * Each entry contains two values:
+ * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
+ *     linear value that multiplies the output of the digital signal processor,
+ *     before being sent to the analog radio.
+ * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
+ *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * EEPROM contains factory calibration data for txpower.  This maps actual
+ * measured txpower levels to gain settings in the "well known" tables
+ * below ("well-known" means here that both factory calibration *and* the
+ * driver work with the same table).
+ *
+ * There are separate tables for 2.4 GHz and 5 GHz bands.  The 5 GHz table
+ * has an extension (into negative indexes), in case the driver needs to
+ * boost power setting for high device temperatures (higher than would be
+ * present during factory calibration).  A 5 Ghz EEPROM index of "40"
+ * corresponds to the 49th entry in the table used by the driver.
+ */
+#define MIN_TX_GAIN_INDEX		(0)  /* highest gain, lowest idx, 2.4 */
+#define MIN_TX_GAIN_INDEX_52GHZ_EXT	(-9) /* highest gain, lowest idx, 5 */
+
+/**
+ * 2.4 GHz gain table
+ *
+ * Index    Dsp gain   Radio gain
+ *   0        110         0x3f      (highest gain)
+ *   1        104         0x3f
+ *   2         98         0x3f
+ *   3        110         0x3e
+ *   4        104         0x3e
+ *   5         98         0x3e
+ *   6        110         0x3d
+ *   7        104         0x3d
+ *   8         98         0x3d
+ *   9        110         0x3c
+ *  10        104         0x3c
+ *  11         98         0x3c
+ *  12        110         0x3b
+ *  13        104         0x3b
+ *  14         98         0x3b
+ *  15        110         0x3a
+ *  16        104         0x3a
+ *  17         98         0x3a
+ *  18        110         0x39
+ *  19        104         0x39
+ *  20         98         0x39
+ *  21        110         0x38
+ *  22        104         0x38
+ *  23         98         0x38
+ *  24        110         0x37
+ *  25        104         0x37
+ *  26         98         0x37
+ *  27        110         0x36
+ *  28        104         0x36
+ *  29         98         0x36
+ *  30        110         0x35
+ *  31        104         0x35
+ *  32         98         0x35
+ *  33        110         0x34
+ *  34        104         0x34
+ *  35         98         0x34
+ *  36        110         0x33
+ *  37        104         0x33
+ *  38         98         0x33
+ *  39        110         0x32
+ *  40        104         0x32
+ *  41         98         0x32
+ *  42        110         0x31
+ *  43        104         0x31
+ *  44         98         0x31
+ *  45        110         0x30
+ *  46        104         0x30
+ *  47         98         0x30
+ *  48        110          0x6
+ *  49        104          0x6
+ *  50         98          0x6
+ *  51        110          0x5
+ *  52        104          0x5
+ *  53         98          0x5
+ *  54        110          0x4
+ *  55        104          0x4
+ *  56         98          0x4
+ *  57        110          0x3
+ *  58        104          0x3
+ *  59         98          0x3
+ *  60        110          0x2
+ *  61        104          0x2
+ *  62         98          0x2
+ *  63        110          0x1
+ *  64        104          0x1
+ *  65         98          0x1
+ *  66        110          0x0
+ *  67        104          0x0
+ *  68         98          0x0
+ *  69         97            0
+ *  70         96            0
+ *  71         95            0
+ *  72         94            0
+ *  73         93            0
+ *  74         92            0
+ *  75         91            0
+ *  76         90            0
+ *  77         89            0
+ *  78         88            0
+ *  79         87            0
+ *  80         86            0
+ *  81         85            0
+ *  82         84            0
+ *  83         83            0
+ *  84         82            0
+ *  85         81            0
+ *  86         80            0
+ *  87         79            0
+ *  88         78            0
+ *  89         77            0
+ *  90         76            0
+ *  91         75            0
+ *  92         74            0
+ *  93         73            0
+ *  94         72            0
+ *  95         71            0
+ *  96         70            0
+ *  97         69            0
+ *  98         68            0
+ */
+
+/**
+ * 5 GHz gain table
+ *
+ * Index    Dsp gain   Radio gain
+ *  -9 	      123         0x3F      (highest gain)
+ *  -8 	      117         0x3F
+ *  -7        110         0x3F
+ *  -6        104         0x3F
+ *  -5         98         0x3F
+ *  -4        110         0x3E
+ *  -3        104         0x3E
+ *  -2         98         0x3E
+ *  -1        110         0x3D
+ *   0        104         0x3D
+ *   1         98         0x3D
+ *   2        110         0x3C
+ *   3        104         0x3C
+ *   4         98         0x3C
+ *   5        110         0x3B
+ *   6        104         0x3B
+ *   7         98         0x3B
+ *   8        110         0x3A
+ *   9        104         0x3A
+ *  10         98         0x3A
+ *  11        110         0x39
+ *  12        104         0x39
+ *  13         98         0x39
+ *  14        110         0x38
+ *  15        104         0x38
+ *  16         98         0x38
+ *  17        110         0x37
+ *  18        104         0x37
+ *  19         98         0x37
+ *  20        110         0x36
+ *  21        104         0x36
+ *  22         98         0x36
+ *  23        110         0x35
+ *  24        104         0x35
+ *  25         98         0x35
+ *  26        110         0x34
+ *  27        104         0x34
+ *  28         98         0x34
+ *  29        110         0x33
+ *  30        104         0x33
+ *  31         98         0x33
+ *  32        110         0x32
+ *  33        104         0x32
+ *  34         98         0x32
+ *  35        110         0x31
+ *  36        104         0x31
+ *  37         98         0x31
+ *  38        110         0x30
+ *  39        104         0x30
+ *  40         98         0x30
+ *  41        110         0x25
+ *  42        104         0x25
+ *  43         98         0x25
+ *  44        110         0x24
+ *  45        104         0x24
+ *  46         98         0x24
+ *  47        110         0x23
+ *  48        104         0x23
+ *  49         98         0x23
+ *  50        110         0x22
+ *  51        104         0x18
+ *  52         98         0x18
+ *  53        110         0x17
+ *  54        104         0x17
+ *  55         98         0x17
+ *  56        110         0x16
+ *  57        104         0x16
+ *  58         98         0x16
+ *  59        110         0x15
+ *  60        104         0x15
+ *  61         98         0x15
+ *  62        110         0x14
+ *  63        104         0x14
+ *  64         98         0x14
+ *  65        110         0x13
+ *  66        104         0x13
+ *  67         98         0x13
+ *  68        110         0x12
+ *  69        104         0x08
+ *  70         98         0x08
+ *  71        110         0x07
+ *  72        104         0x07
+ *  73         98         0x07
+ *  74        110         0x06
+ *  75        104         0x06
+ *  76         98         0x06
+ *  77        110         0x05
+ *  78        104         0x05
+ *  79         98         0x05
+ *  80        110         0x04
+ *  81        104         0x04
+ *  82         98         0x04
+ *  83        110         0x03
+ *  84        104         0x03
+ *  85         98         0x03
+ *  86        110         0x02
+ *  87        104         0x02
+ *  88         98         0x02
+ *  89        110         0x01
+ *  90        104         0x01
+ *  91         98         0x01
+ *  92        110         0x00
+ *  93        104         0x00
+ *  94         98         0x00
+ *  95         93         0x00
+ *  96         88         0x00
+ *  97         83         0x00
+ *  98         78         0x00
+ */
+
+
+/**
+ * Sanity checks and default values for EEPROM regulatory levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Regulatory limits refer to the maximum average txpower allowed by
+ * regulatory agencies in the geographies in which the device is meant
+ * to be operated.  These limits are SKU-specific (i.e. geography-specific),
+ * and channel-specific; each channel has an individual regulatory limit
+ * listed in the EEPROM.
+ *
+ * Units are in half-dBm (i.e. "34" means 17 dBm).
+ */
+#define IWL_TX_POWER_DEFAULT_REGULATORY_24   (34)
+#define IWL_TX_POWER_DEFAULT_REGULATORY_52   (34)
+#define IWL_TX_POWER_REGULATORY_MIN          (0)
+#define IWL_TX_POWER_REGULATORY_MAX          (34)
+
+/**
+ * Sanity checks and default values for EEPROM saturation levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Saturation is the highest level that the output power amplifier can produce
+ * without significant clipping distortion.  This is a "peak" power level.
+ * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
+ * require differing amounts of backoff, relative to their average power output,
+ * in order to avoid clipping distortion.
+ *
+ * Driver must make sure that it is violating neither the saturation limit,
+ * nor the regulatory limit, when calculating Tx power settings for various
+ * rates.
+ *
+ * Units are in half-dBm (i.e. "38" means 19 dBm).
+ */
+#define IWL_TX_POWER_DEFAULT_SATURATION_24   (38)
+#define IWL_TX_POWER_DEFAULT_SATURATION_52   (38)
+#define IWL_TX_POWER_SATURATION_MIN          (20)
+#define IWL_TX_POWER_SATURATION_MAX          (50)
+
+/**
+ * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
+ * and thermal Txpower calibration.
+ *
+ * When calculating txpower, driver must compensate for current device
+ * temperature; higher temperature requires higher gain.  Driver must calculate
+ * current temperature (see "4965 temperature calculation"), then compare vs.
+ * factory calibration temperature in EEPROM; if current temperature is higher
+ * than factory temperature, driver must *increase* gain by proportions shown
+ * in table below.  If current temperature is lower than factory, driver must
+ * *decrease* gain.
+ *
+ * Different frequency ranges require different compensation, as shown below.
+ */
+/* Group 0, 5.2 GHz ch 34-43:  4.5 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
+#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
+
+/* Group 1, 5.3 GHz ch 44-70:  4.0 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
+#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
+
+/* Group 2, 5.5 GHz ch 71-124:  4.0 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
+#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
+
+/* Group 3, 5.7 GHz ch 125-200:  4.0 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
+#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
+
+/* Group 4, 2.4 GHz all channels:  3.5 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
+#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
+
+enum {
+	CALIB_CH_GROUP_1 = 0,
+	CALIB_CH_GROUP_2 = 1,
+	CALIB_CH_GROUP_3 = 2,
+	CALIB_CH_GROUP_4 = 3,
+	CALIB_CH_GROUP_5 = 4,
+	CALIB_CH_GROUP_MAX
+};
+
+/********************* END TXPOWER *****************************************/
+
+
+/**
+ * Tx/Rx Queues
+ *
+ * Most communication between driver and 4965 is via queues of data buffers.
+ * For example, all commands that the driver issues to device's embedded
+ * controller (uCode) are via the command queue (one of the Tx queues).  All
+ * uCode command responses/replies/notifications, including Rx frames, are
+ * conveyed from uCode to driver via the Rx queue.
+ *
+ * Most support for these queues, including handshake support, resides in
+ * structures in host DRAM, shared between the driver and the device.  When
+ * allocating this memory, the driver must make sure that data written by
+ * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
+ * cache memory), so DRAM and cache are consistent, and the device can
+ * immediately see changes made by the driver.
+ *
+ * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
+ * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
+ * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
+ */
+#define IWL49_NUM_FIFOS 	7
+#define IWL49_CMD_FIFO_NUM	4
+#define IWL49_NUM_QUEUES	16
+#define IWL49_NUM_AMPDU_QUEUES	8
+
+
+/**
+ * struct iwl4965_schedq_bc_tbl
+ *
+ * Byte Count table
+ *
+ * Each Tx queue uses a byte-count table containing 320 entries:
+ * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
+ * duplicate the first 64 entries (to avoid wrap-around within a Tx window;
+ * max Tx window is 64 TFDs).
+ *
+ * When driver sets up a new TFD, it must also enter the total byte count
+ * of the frame to be transmitted into the corresponding entry in the byte
+ * count table for the chosen Tx queue.  If the TFD index is 0-63, the driver
+ * must duplicate the byte count entry in corresponding index 256-319.
+ *
+ * padding puts each byte count table on a 1024-byte boundary;
+ * 4965 assumes tables are separated by 1024 bytes.
+ */
+struct iwl4965_scd_bc_tbl {
+	__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
+	u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
+} __packed;
+
+
+#define IWL4965_RTC_INST_LOWER_BOUND		(0x000000)
+
+/* RSSI to dBm */
+#define IWL4965_RSSI_OFFSET	44
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT	0x041
+
+/* PCI register values */
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02
+
+#define IWL4965_DEFAULT_TX_RETRY  15
+
+/* Limit range of txpower output target to be between these values */
+#define IWL4965_TX_POWER_TARGET_POWER_MIN	(0)	/* 0 dBm: 1 milliwatt */
+
+/* EEPROM */
+#define IWL4965_FIRST_AMPDU_QUEUE	10
+
+
+#endif /* !__iwl_4965_hw_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.c b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
new file mode 100644
index 0000000..26d324e
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-4965-led.h"
+
+/* Send led command */
+static int
+iwl4965_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_LEDS_CMD,
+		.len = sizeof(struct iwl_led_cmd),
+		.data = led_cmd,
+		.flags = CMD_ASYNC,
+		.callback = NULL,
+	};
+	u32 reg;
+
+	reg = iwl_read32(priv, CSR_LED_REG);
+	if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
+		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
+
+	return iwl_legacy_send_cmd(priv, &cmd);
+}
+
+/* Set led register off */
+void iwl4965_led_enable(struct iwl_priv *priv)
+{
+	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
+}
+
+const struct iwl_led_ops iwl4965_led_ops = {
+	.cmd = iwl4965_send_led_cmd,
+};
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.h b/drivers/net/wireless/iwlegacy/iwl-4965-led.h
new file mode 100644
index 0000000..5ed3615
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-led.h
@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_4965_led_h__
+#define __iwl_4965_led_h__
+
+extern const struct iwl_led_ops iwl4965_led_ops;
+void iwl4965_led_enable(struct iwl_priv *priv);
+
+#endif /* __iwl_4965_led_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
new file mode 100644
index 0000000..5a8a3cc
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
@@ -0,0 +1,1260 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+#include "iwl-sta.h"
+
+void iwl4965_check_abort_status(struct iwl_priv *priv,
+			    u8 frame_count, u32 status)
+{
+	if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
+		IWL_ERR(priv, "Tx flush command to flush out all frames\n");
+		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+			queue_work(priv->workqueue, &priv->tx_flush);
+	}
+}
+
+/*
+ * EEPROM
+ */
+struct iwl_mod_params iwl4965_mod_params = {
+	.amsdu_size_8K = 1,
+	.restart_fw = 1,
+	/* the rest are 0 by default */
+};
+
+void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	unsigned long flags;
+	int i;
+	spin_lock_irqsave(&rxq->lock, flags);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+		/* In the reset function, these buffers may have been allocated
+		 * to an SKB, so we need to unmap and free potential storage */
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+	}
+
+	for (i = 0; i < RX_QUEUE_SIZE; i++)
+		rxq->queue[i] = NULL;
+
+	/* Set us so that we have processed and used all buffers, but have
+	 * not restocked the Rx queue with fresh buffers */
+	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
+	rxq->free_count = 0;
+	spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	u32 rb_size;
+	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+	u32 rb_timeout = 0;
+
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+	else
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+	/* Stop Rx DMA */
+	iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+	/* Reset driver's Rx queue write index */
+	iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+	/* Tell device where to find RBD circular buffer in DRAM */
+	iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+			   (u32)(rxq->bd_dma >> 8));
+
+	/* Tell device where in DRAM to update its Rx status */
+	iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+			   rxq->rb_stts_dma >> 4);
+
+	/* Enable Rx DMA
+	 * Direct rx interrupts to hosts
+	 * Rx buffer size 4 or 8k
+	 * RB timeout 0x10
+	 * 256 RBDs
+	 */
+	iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+			   FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
+			   rb_size|
+			   (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+	/* Set interrupt coalescing timer to default (2048 usecs) */
+	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+
+	return 0;
+}
+
+static void iwl4965_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+		if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+			iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+					       ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+	iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			       ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
+int iwl4965_hw_nic_init(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	int ret;
+
+	/* nic_init */
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->cfg->ops->lib->apm_ops.init(priv);
+
+	/* Set interrupt coalescing calibration timer to default (512 usecs) */
+	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl4965_set_pwr_vmain(priv);
+
+	priv->cfg->ops->lib->apm_ops.config(priv);
+
+	/* Allocate the RX queue, or reset if it is already allocated */
+	if (!rxq->bd) {
+		ret = iwl_legacy_rx_queue_alloc(priv);
+		if (ret) {
+			IWL_ERR(priv, "Unable to initialize Rx queue\n");
+			return -ENOMEM;
+		}
+	} else
+		iwl4965_rx_queue_reset(priv, rxq);
+
+	iwl4965_rx_replenish(priv);
+
+	iwl4965_rx_init(priv, rxq);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rxq->need_update = 1;
+	iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Allocate or reset and init all Tx and Command queues */
+	if (!priv->txq) {
+		ret = iwl4965_txq_ctx_alloc(priv);
+		if (ret)
+			return ret;
+	} else
+		iwl4965_txq_ctx_reset(priv);
+
+	set_bit(STATUS_INIT, &priv->status);
+
+	return 0;
+}
+
+/**
+ * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
+					  dma_addr_t dma_addr)
+{
+	return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/**
+ * iwl4965_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+void iwl4965_rx_queue_restock(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	while ((iwl_legacy_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+		/* The overwritten rxb must be a used one */
+		rxb = rxq->queue[rxq->write];
+		BUG_ON(rxb && rxb->page);
+
+		/* Get next free Rx buffer, remove from free list */
+		element = rxq->rx_free.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		/* Point to Rx buffer via next RBD in circular buffer */
+		rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv,
+							      rxb->page_dma);
+		rxq->queue[rxq->write] = rxb;
+		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+		rxq->free_count--;
+	}
+	spin_unlock_irqrestore(&rxq->lock, flags);
+	/* If the pre-allocated buffer pool is dropping low, schedule to
+	 * refill it */
+	if (rxq->free_count <= RX_LOW_WATERMARK)
+		queue_work(priv->workqueue, &priv->rx_replenish);
+
+
+	/* If we've added more space for the firmware to place data, tell it.
+	 * Increment device's write pointer in multiples of 8. */
+	if (rxq->write_actual != (rxq->write & ~0x7)) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		rxq->need_update = 1;
+		spin_unlock_irqrestore(&rxq->lock, flags);
+		iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+	}
+}
+
+/**
+ * iwl4965_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void iwl4965_rx_allocate(struct iwl_priv *priv, gfp_t priority)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	struct page *page;
+	unsigned long flags;
+	gfp_t gfp_mask = priority;
+
+	while (1) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			return;
+		}
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			gfp_mask |= __GFP_NOWARN;
+
+		if (priv->hw_params.rx_page_order > 0)
+			gfp_mask |= __GFP_COMP;
+
+		/* Alloc a new receive buffer */
+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
+		if (!page) {
+			if (net_ratelimit())
+				IWL_DEBUG_INFO(priv, "alloc_pages failed, "
+					       "order: %d\n",
+					       priv->hw_params.rx_page_order);
+
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv,
+					"Failed to alloc_pages with %s. "
+					"Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?
+						 "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
+			/* We don't reschedule replenish work here -- we will
+			 * call the restock method and if it still needs
+			 * more buffers it will schedule replenish */
+			return;
+		}
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			__free_pages(page, priv->hw_params.rx_page_order);
+			return;
+		}
+		element = rxq->rx_used.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		BUG_ON(rxb->page);
+		rxb->page = page;
+		/* Get physical address of the RB */
+		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+		/* dma address must be no more than 36 bits */
+		BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+		/* and also 256 byte aligned! */
+		BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		list_add_tail(&rxb->list, &rxq->rx_free);
+		rxq->free_count++;
+		priv->alloc_rxb_page++;
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+	}
+}
+
+void iwl4965_rx_replenish(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	iwl4965_rx_allocate(priv, GFP_KERNEL);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl4965_rx_queue_restock(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+void iwl4965_rx_replenish_now(struct iwl_priv *priv)
+{
+	iwl4965_rx_allocate(priv, GFP_ATOMIC);
+
+	iwl4965_rx_queue_restock(priv);
+}
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	int i;
+	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+	}
+
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->bd_dma);
+	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+			  rxq->rb_stts, rxq->rb_stts_dma);
+	rxq->bd = NULL;
+	rxq->rb_stts  = NULL;
+}
+
+int iwl4965_rxq_stop(struct iwl_priv *priv)
+{
+
+	/* stop Rx DMA */
+	iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+	iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+			    FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+
+	return 0;
+}
+
+int iwl4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
+{
+	int idx = 0;
+	int band_offset = 0;
+
+	/* HT rate format: mac80211 wants an MCS number, which is just LSB */
+	if (rate_n_flags & RATE_MCS_HT_MSK) {
+		idx = (rate_n_flags & 0xff);
+		return idx;
+	/* Legacy rate format, search for match in table */
+	} else {
+		if (band == IEEE80211_BAND_5GHZ)
+			band_offset = IWL_FIRST_OFDM_RATE;
+		for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
+			if (iwlegacy_rates[idx].plcp == (rate_n_flags & 0xFF))
+				return idx - band_offset;
+	}
+
+	return -1;
+}
+
+static int iwl4965_calc_rssi(struct iwl_priv *priv,
+			     struct iwl_rx_phy_res *rx_resp)
+{
+	/* data from PHY/DSP regarding signal strength, etc.,
+	 *   contents are always there, not configurable by host.  */
+	struct iwl4965_rx_non_cfg_phy *ncphy =
+	    (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+	u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK)
+			>> IWL49_AGC_DB_POS;
+
+	u32 valid_antennae =
+	    (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK)
+			>> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
+	u8 max_rssi = 0;
+	u32 i;
+
+	/* Find max rssi among 3 possible receivers.
+	 * These values are measured by the digital signal processor (DSP).
+	 * They should stay fairly constant even as the signal strength varies,
+	 *   if the radio's automatic gain control (AGC) is working right.
+	 * AGC value (see below) will provide the "interesting" info. */
+	for (i = 0; i < 3; i++)
+		if (valid_antennae & (1 << i))
+			max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
+
+	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+		ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
+		max_rssi, agc);
+
+	/* dBm = max_rssi dB - agc dB - constant.
+	 * Higher AGC (higher radio gain) means lower signal. */
+	return max_rssi - agc - IWL4965_RSSI_OFFSET;
+}
+
+
+static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
+{
+	u32 decrypt_out = 0;
+
+	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
+					RX_RES_STATUS_STATION_FOUND)
+		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
+				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
+
+	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
+
+	/* packet was not encrypted */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_NONE)
+		return decrypt_out;
+
+	/* packet was encrypted with unknown alg */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_ERR)
+		return decrypt_out;
+
+	/* decryption was not done in HW */
+	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
+					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
+		return decrypt_out;
+
+	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
+
+	case RX_RES_STATUS_SEC_TYPE_CCMP:
+		/* alg is CCM: check MIC only */
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
+			/* Bad MIC */
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+
+		break;
+
+	case RX_RES_STATUS_SEC_TYPE_TKIP:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
+			/* Bad TTAK */
+			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
+			break;
+		}
+		/* fall through if TTAK OK */
+	default:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+		break;
+	}
+
+	IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
+					decrypt_in, decrypt_out);
+
+	return decrypt_out;
+}
+
+static void iwl4965_pass_packet_to_mac80211(struct iwl_priv *priv,
+					struct ieee80211_hdr *hdr,
+					u16 len,
+					u32 ampdu_status,
+					struct iwl_rx_mem_buffer *rxb,
+					struct ieee80211_rx_status *stats)
+{
+	struct sk_buff *skb;
+	__le16 fc = hdr->frame_control;
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!priv->is_open)) {
+		IWL_DEBUG_DROP_LIMIT(priv,
+		    "Dropping packet while interface is not open.\n");
+		return;
+	}
+
+	/* In case of HW accelerated crypto and bad decryption, drop */
+	if (!priv->cfg->mod_params->sw_crypto &&
+	    iwl_legacy_set_decrypted_flag(priv, hdr, ampdu_status, stats))
+		return;
+
+	skb = dev_alloc_skb(128);
+	if (!skb) {
+		IWL_ERR(priv, "dev_alloc_skb failed\n");
+		return;
+	}
+
+	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+
+	iwl_legacy_update_stats(priv, false, fc, len);
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+	ieee80211_rx(priv->hw, skb);
+	priv->alloc_rxb_page--;
+	rxb->page = NULL;
+}
+
+/* Called for REPLY_RX (legacy ABG frames), or
+ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct ieee80211_hdr *header;
+	struct ieee80211_rx_status rx_status;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_rx_phy_res *phy_res;
+	__le32 rx_pkt_status;
+	struct iwl_rx_mpdu_res_start *amsdu;
+	u32 len;
+	u32 ampdu_status;
+	u32 rate_n_flags;
+
+	/**
+	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
+	 *	REPLY_RX: physical layer info is in this buffer
+	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
+	 *		command and cached in priv->last_phy_res
+	 *
+	 * Here we set up local variables depending on which command is
+	 * received.
+	 */
+	if (pkt->hdr.cmd == REPLY_RX) {
+		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+				+ phy_res->cfg_phy_cnt);
+
+		len = le16_to_cpu(phy_res->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+				phy_res->cfg_phy_cnt + len);
+		ampdu_status = le32_to_cpu(rx_pkt_status);
+	} else {
+		if (!priv->_4965.last_phy_res_valid) {
+			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
+			return;
+		}
+		phy_res = &priv->_4965.last_phy_res;
+		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+		len = le16_to_cpu(amsdu->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+		ampdu_status = iwl4965_translate_rx_status(priv,
+				le32_to_cpu(rx_pkt_status));
+	}
+
+	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				phy_res->cfg_phy_cnt);
+		return;
+	}
+
+	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
+				le32_to_cpu(rx_pkt_status));
+		return;
+	}
+
+	/* This will be used in several places later */
+	rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
+
+	/* rx_status carries information about the packet to mac80211 */
+	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
+	rx_status.freq =
+		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+							rx_status.band);
+	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	rx_status.rate_idx =
+		iwl4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
+	rx_status.flag = 0;
+
+	/* TSF isn't reliable. In order to allow smooth user experience,
+	 * this W/A doesn't propagate it to the mac80211 */
+	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+
+	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
+
+	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
+	rx_status.signal = iwl4965_calc_rssi(priv, phy_res);
+
+	iwl_legacy_dbg_log_rx_data_frame(priv, len, header);
+	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
+		rx_status.signal, (unsigned long long)rx_status.mactime);
+
+	/*
+	 * "antenna number"
+	 *
+	 * It seems that the antenna field in the phy flags value
+	 * is actually a bit field. This is undefined by radiotap,
+	 * it wants an actual antenna number but I always get "7"
+	 * for most legacy frames I receive indicating that the
+	 * same frame was received on all three RX chains.
+	 *
+	 * I think this field should be removed in favor of a
+	 * new 802.11n radiotap field "RX chains" that is defined
+	 * as a bitmask.
+	 */
+	rx_status.antenna =
+		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
+
+	/* set the preamble flag if appropriate */
+	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+		rx_status.flag |= RX_FLAG_SHORTPRE;
+
+	/* Set up the HT phy flags */
+	if (rate_n_flags & RATE_MCS_HT_MSK)
+		rx_status.flag |= RX_FLAG_HT;
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
+		rx_status.flag |= RX_FLAG_40MHZ;
+	if (rate_n_flags & RATE_MCS_SGI_MSK)
+		rx_status.flag |= RX_FLAG_SHORT_GI;
+
+	iwl4965_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+				    rxb, &rx_status);
+}
+
+/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+			    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	priv->_4965.last_phy_res_valid = true;
+	memcpy(&priv->_4965.last_phy_res, pkt->u.raw,
+	       sizeof(struct iwl_rx_phy_res));
+}
+
+static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv,
+					   struct ieee80211_vif *vif,
+					   enum ieee80211_band band,
+					   struct iwl_scan_channel *scan_ch)
+{
+	const struct ieee80211_supported_band *sband;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added = 0;
+	u16 channel = 0;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband) {
+		IWL_ERR(priv, "invalid band\n");
+		return added;
+	}
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	channel = iwl_legacy_get_single_channel_number(priv, band);
+	if (channel) {
+		scan_ch->channel = cpu_to_le16(channel);
+		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+		added++;
+	} else
+		IWL_ERR(priv, "no valid channel found\n");
+	return added;
+}
+
+static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
+				     struct ieee80211_vif *vif,
+				     enum ieee80211_band band,
+				     u8 is_active, u8 n_probes,
+				     struct iwl_scan_channel *scan_ch)
+{
+	struct ieee80211_channel *chan;
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added, i;
+	u16 channel;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband)
+		return 0;
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, n_probes);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+		chan = priv->scan_request->channels[i];
+
+		if (chan->band != band)
+			continue;
+
+		channel = chan->hw_value;
+		scan_ch->channel = cpu_to_le16(channel);
+
+		ch_info = iwl_legacy_get_channel_info(priv, band, channel);
+		if (!iwl_legacy_is_channel_valid(ch_info)) {
+			IWL_DEBUG_SCAN(priv,
+				 "Channel %d is INVALID for this band.\n",
+					channel);
+			continue;
+		}
+
+		if (!is_active || iwl_legacy_is_channel_passive(ch_info) ||
+		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		else
+			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+
+		if (n_probes)
+			scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+
+		/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+		 * power level:
+		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+		 */
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+		IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
+			       channel, le32_to_cpu(scan_ch->type),
+			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+				"ACTIVE" : "PASSIVE",
+			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+			       active_dwell : passive_dwell);
+
+		scan_ch++;
+		added++;
+	}
+
+	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+	return added;
+}
+
+int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_CMD,
+		.len = sizeof(struct iwl_scan_cmd),
+		.flags = CMD_SIZE_HUGE,
+	};
+	struct iwl_scan_cmd *scan;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	u32 rate_flags = 0;
+	u16 cmd_len;
+	u16 rx_chain = 0;
+	enum ieee80211_band band;
+	u8 n_probes = 0;
+	u8 rx_ant = priv->hw_params.valid_rx_ant;
+	u8 rate;
+	bool is_active = false;
+	int  chan_mod;
+	u8 active_chains;
+	u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (vif)
+		ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
+			IWL_DEBUG_SCAN(priv,
+				       "fail to allocate memory for scan\n");
+			return -ENOMEM;
+		}
+	}
+	scan = priv->scan_cmd;
+	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+	if (iwl_legacy_is_any_associated(priv)) {
+		u16 interval = 0;
+		u32 extra;
+		u32 suspend_time = 100;
+		u32 scan_suspend_time = 100;
+
+		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+		if (priv->is_internal_short_scan)
+			interval = 0;
+		else
+			interval = vif->bss_conf.beacon_int;
+
+		scan->suspend_time = 0;
+		scan->max_out_time = cpu_to_le32(200 * 1024);
+		if (!interval)
+			interval = suspend_time;
+
+		extra = (suspend_time / interval) << 22;
+		scan_suspend_time = (extra |
+		    ((suspend_time % interval) * 1024));
+		scan->suspend_time = cpu_to_le32(scan_suspend_time);
+		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+			       scan_suspend_time, interval);
+	}
+
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+	} else if (priv->scan_request->n_ssids) {
+		int i, p = 0;
+		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+		for (i = 0; i < priv->scan_request->n_ssids; i++) {
+			/* always does wildcard anyway */
+			if (!priv->scan_request->ssids[i].ssid_len)
+				continue;
+			scan->direct_scan[p].id = WLAN_EID_SSID;
+			scan->direct_scan[p].len =
+				priv->scan_request->ssids[i].ssid_len;
+			memcpy(scan->direct_scan[p].ssid,
+			       priv->scan_request->ssids[i].ssid,
+			       priv->scan_request->ssids[i].ssid_len);
+			n_probes++;
+			p++;
+		}
+		is_active = true;
+	} else
+		IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
+
+	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+	scan->tx_cmd.sta_id = ctx->bcast_sta_id;
+	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
+		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+		chan_mod = le32_to_cpu(
+			priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+						RXON_FLG_CHANNEL_MODE_MSK)
+				       >> RXON_FLG_CHANNEL_MODE_POS;
+		if (chan_mod == CHANNEL_MODE_PURE_40) {
+			rate = IWL_RATE_6M_PLCP;
+		} else {
+			rate = IWL_RATE_1M_PLCP;
+			rate_flags = RATE_MCS_CCK_MSK;
+		}
+		break;
+	case IEEE80211_BAND_5GHZ:
+		rate = IWL_RATE_6M_PLCP;
+		break;
+	default:
+		IWL_WARN(priv, "Invalid scan band\n");
+		return -EIO;
+	}
+
+	/*
+	 * If active scanning is requested but a certain channel is
+	 * marked passive, we can do active scanning if we detect
+	 * transmissions.
+	 *
+	 * There is an issue with some firmware versions that triggers
+	 * a sysassert on a "good CRC threshold" of zero (== disabled),
+	 * on a radar channel even though this means that we should NOT
+	 * send probes.
+	 *
+	 * The "good CRC threshold" is the number of frames that we
+	 * need to receive during our dwell time on a channel before
+	 * sending out probes -- setting this to a huge value will
+	 * mean we never reach it, but at the same time work around
+	 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+	 * here instead of IWL_GOOD_CRC_TH_DISABLED.
+	 */
+	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+					IWL_GOOD_CRC_TH_NEVER;
+
+	band = priv->scan_band;
+
+	if (priv->cfg->scan_rx_antennas[band])
+		rx_ant = priv->cfg->scan_rx_antennas[band];
+
+	if (priv->cfg->scan_tx_antennas[band])
+		scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
+
+	priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv,
+						priv->scan_tx_ant[band],
+						    scan_tx_antennas);
+	rate_flags |= iwl4965_ant_idx_to_flags(priv->scan_tx_ant[band]);
+	scan->tx_cmd.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate, rate_flags);
+
+	/* In power save mode use one chain, otherwise use all chains */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		/* rx_ant has been set to all valid chains previously */
+		active_chains = rx_ant &
+				((u8)(priv->chain_noise_data.active_chains));
+		if (!active_chains)
+			active_chains = rx_ant;
+
+		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
+				priv->chain_noise_data.active_chains);
+
+		rx_ant = iwl4965_first_antenna(active_chains);
+	}
+
+	/* MIMO is not used here, but value is required */
+	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
+	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
+	scan->rx_chain = cpu_to_le16(rx_chain);
+	if (!priv->is_internal_short_scan) {
+		cmd_len = iwl_legacy_fill_probe_req(priv,
+					(struct ieee80211_mgmt *)scan->data,
+					vif->addr,
+					priv->scan_request->ie,
+					priv->scan_request->ie_len,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+	} else {
+		/* use bcast addr, will not be transmitted but must be valid */
+		cmd_len = iwl_legacy_fill_probe_req(priv,
+					(struct ieee80211_mgmt *)scan->data,
+					iwlegacy_bcast_addr, NULL, 0,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+
+	}
+	scan->tx_cmd.len = cpu_to_le16(cmd_len);
+
+	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
+			       RXON_FILTER_BCON_AWARE_MSK);
+
+	if (priv->is_internal_short_scan) {
+		scan->channel_count =
+			iwl4965_get_single_channel_for_scan(priv, vif, band,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	} else {
+		scan->channel_count =
+			iwl4965_get_channels_for_scan(priv, vif, band,
+				is_active, n_probes,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	}
+	if (scan->channel_count == 0) {
+		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+		return -EIO;
+	}
+
+	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+	    scan->channel_count * sizeof(struct iwl_scan_channel);
+	cmd.data = scan;
+	scan->len = cpu_to_le16(cmd.len);
+
+	set_bit(STATUS_SCAN_HW, &priv->status);
+
+	ret = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (ret)
+		clear_bit(STATUS_SCAN_HW, &priv->status);
+
+	return ret;
+}
+
+int iwl4965_manage_ibss_station(struct iwl_priv *priv,
+			       struct ieee80211_vif *vif, bool add)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+	if (add)
+		return iwl4965_add_bssid_station(priv, vif_priv->ctx,
+						vif->bss_conf.bssid,
+						&vif_priv->ibss_bssid_sta_id);
+	return iwl_legacy_remove_station(priv, vif_priv->ibss_bssid_sta_id,
+				  vif->bss_conf.bssid);
+}
+
+void iwl4965_free_tfds_in_queue(struct iwl_priv *priv,
+			    int sta_id, int tid, int freed)
+{
+	lockdep_assert_held(&priv->sta_lock);
+
+	if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
+		priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+	else {
+		IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
+			priv->stations[sta_id].tid[tid].tfds_in_queue,
+			freed);
+		priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
+	}
+}
+
+#define IWL_TX_QUEUE_MSK	0xfffff
+
+static bool iwl4965_is_single_rx_stream(struct iwl_priv *priv)
+{
+	return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
+	       priv->current_ht_config.single_chain_sufficient;
+}
+
+#define IWL_NUM_RX_CHAINS_MULTIPLE	3
+#define IWL_NUM_RX_CHAINS_SINGLE	2
+#define IWL_NUM_IDLE_CHAINS_DUAL	2
+#define IWL_NUM_IDLE_CHAINS_SINGLE	1
+
+/*
+ * Determine how many receiver/antenna chains to use.
+ *
+ * More provides better reception via diversity.  Fewer saves power
+ * at the expense of throughput, but only when not in powersave to
+ * start with.
+ *
+ * MIMO (dual stream) requires at least 2, but works better with 3.
+ * This does not determine *which* chains to use, just how many.
+ */
+static int iwl4965_get_active_rx_chain_count(struct iwl_priv *priv)
+{
+	/* # of Rx chains to use when expecting MIMO. */
+	if (iwl4965_is_single_rx_stream(priv))
+		return IWL_NUM_RX_CHAINS_SINGLE;
+	else
+		return IWL_NUM_RX_CHAINS_MULTIPLE;
+}
+
+/*
+ * When we are in power saving mode, unless device support spatial
+ * multiplexing power save, use the active count for rx chain count.
+ */
+static int
+iwl4965_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
+{
+	/* # Rx chains when idling, depending on SMPS mode */
+	switch (priv->current_ht_config.smps) {
+	case IEEE80211_SMPS_STATIC:
+	case IEEE80211_SMPS_DYNAMIC:
+		return IWL_NUM_IDLE_CHAINS_SINGLE;
+	case IEEE80211_SMPS_OFF:
+		return active_cnt;
+	default:
+		WARN(1, "invalid SMPS mode %d",
+		     priv->current_ht_config.smps);
+		return active_cnt;
+	}
+}
+
+/* up to 4 chains */
+static u8 iwl4965_count_chain_bitmap(u32 chain_bitmap)
+{
+	u8 res;
+	res = (chain_bitmap & BIT(0)) >> 0;
+	res += (chain_bitmap & BIT(1)) >> 1;
+	res += (chain_bitmap & BIT(2)) >> 2;
+	res += (chain_bitmap & BIT(3)) >> 3;
+	return res;
+}
+
+/**
+ * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
+ *
+ * Selects how many and which Rx receivers/antennas/chains to use.
+ * This should not be used for scan command ... it puts data in wrong place.
+ */
+void iwl4965_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	bool is_single = iwl4965_is_single_rx_stream(priv);
+	bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+	u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
+	u32 active_chains;
+	u16 rx_chain;
+
+	/* Tell uCode which antennas are actually connected.
+	 * Before first association, we assume all antennas are connected.
+	 * Just after first association, iwl4965_chain_noise_calibration()
+	 *    checks which antennas actually *are* connected. */
+	if (priv->chain_noise_data.active_chains)
+		active_chains = priv->chain_noise_data.active_chains;
+	else
+		active_chains = priv->hw_params.valid_rx_ant;
+
+	rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
+
+	/* How many receivers should we use? */
+	active_rx_cnt = iwl4965_get_active_rx_chain_count(priv);
+	idle_rx_cnt = iwl4965_get_idle_rx_chain_count(priv, active_rx_cnt);
+
+
+	/* correct rx chain count according hw settings
+	 * and chain noise calibration
+	 */
+	valid_rx_cnt = iwl4965_count_chain_bitmap(active_chains);
+	if (valid_rx_cnt < active_rx_cnt)
+		active_rx_cnt = valid_rx_cnt;
+
+	if (valid_rx_cnt < idle_rx_cnt)
+		idle_rx_cnt = valid_rx_cnt;
+
+	rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+	rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
+
+	ctx->staging.rx_chain = cpu_to_le16(rx_chain);
+
+	if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
+		ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
+	else
+		ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
+
+	IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
+			ctx->staging.rx_chain,
+			active_rx_cnt, idle_rx_cnt);
+
+	WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
+		active_rx_cnt < idle_rx_cnt);
+}
+
+u8 iwl4965_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
+{
+	int i;
+	u8 ind = ant;
+
+	for (i = 0; i < RATE_ANT_NUM - 1; i++) {
+		ind = (ind + 1) < RATE_ANT_NUM ?  ind + 1 : 0;
+		if (valid & BIT(ind))
+			return ind;
+	}
+	return ant;
+}
+
+static const char *iwl4965_get_fh_string(int cmd)
+{
+	switch (cmd) {
+	IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
+	IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
+	IWL_CMD(FH_RSCSR_CHNL0_WPTR);
+	IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
+	IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
+	IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
+	IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+	IWL_CMD(FH_TSSR_TX_STATUS_REG);
+	IWL_CMD(FH_TSSR_TX_ERROR_REG);
+	default:
+		return "UNKNOWN";
+	}
+}
+
+int iwl4965_dump_fh(struct iwl_priv *priv, char **buf, bool display)
+{
+	int i;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	int pos = 0;
+	size_t bufsz = 0;
+#endif
+	static const u32 fh_tbl[] = {
+		FH_RSCSR_CHNL0_STTS_WPTR_REG,
+		FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+		FH_RSCSR_CHNL0_WPTR,
+		FH_MEM_RCSR_CHNL0_CONFIG_REG,
+		FH_MEM_RSSR_SHARED_CTRL_REG,
+		FH_MEM_RSSR_RX_STATUS_REG,
+		FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+		FH_TSSR_TX_STATUS_REG,
+		FH_TSSR_TX_ERROR_REG
+	};
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (display) {
+		bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+		pos += scnprintf(*buf + pos, bufsz - pos,
+				"FH register values:\n");
+		for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+			pos += scnprintf(*buf + pos, bufsz - pos,
+				"  %34s: 0X%08x\n",
+				iwl4965_get_fh_string(fh_tbl[i]),
+				iwl_legacy_read_direct32(priv, fh_tbl[i]));
+		}
+		return pos;
+	}
+#endif
+	IWL_ERR(priv, "FH register values:\n");
+	for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++) {
+		IWL_ERR(priv, "  %34s: 0X%08x\n",
+			iwl4965_get_fh_string(fh_tbl[i]),
+			iwl_legacy_read_direct32(priv, fh_tbl[i]));
+	}
+	return 0;
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
new file mode 100644
index 0000000..31ac672
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -0,0 +1,2870 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "iwl-dev.h"
+#include "iwl-sta.h"
+#include "iwl-core.h"
+#include "iwl-4965.h"
+
+#define IWL4965_RS_NAME "iwl-4965-rs"
+
+#define NUM_TRY_BEFORE_ANT_TOGGLE 1
+#define IWL_NUMBER_TRY      1
+#define IWL_HT_NUMBER_TRY   3
+
+#define IWL_RATE_MAX_WINDOW		62	/* # tx in history window */
+#define IWL_RATE_MIN_FAILURE_TH		6	/* min failures to calc tpt */
+#define IWL_RATE_MIN_SUCCESS_TH		8	/* min successes to calc tpt */
+
+/* max allowed rate miss before sync LQ cmd */
+#define IWL_MISSED_RATE_MAX		15
+/* max time to accum history 2 seconds */
+#define IWL_RATE_SCALE_FLUSH_INTVL   (3*HZ)
+
+static u8 rs_ht_to_legacy[] = {
+	IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
+	IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
+	IWL_RATE_6M_INDEX,
+	IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX,
+	IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX,
+	IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX,
+	IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX
+};
+
+static const u8 ant_toggle_lookup[] = {
+	/*ANT_NONE -> */ ANT_NONE,
+	/*ANT_A    -> */ ANT_B,
+	/*ANT_B    -> */ ANT_C,
+	/*ANT_AB   -> */ ANT_BC,
+	/*ANT_C    -> */ ANT_A,
+	/*ANT_AC   -> */ ANT_AB,
+	/*ANT_BC   -> */ ANT_AC,
+	/*ANT_ABC  -> */ ANT_ABC,
+};
+
+#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)    \
+	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,      \
+				    IWL_RATE_SISO_##s##M_PLCP, \
+				    IWL_RATE_MIMO2_##s##M_PLCP,\
+				    IWL_RATE_##r##M_IEEE,      \
+				    IWL_RATE_##ip##M_INDEX,    \
+				    IWL_RATE_##in##M_INDEX,    \
+				    IWL_RATE_##rp##M_INDEX,    \
+				    IWL_RATE_##rn##M_INDEX,    \
+				    IWL_RATE_##pp##M_INDEX,    \
+				    IWL_RATE_##np##M_INDEX }
+
+/*
+ * Parameter order:
+ *   rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to IWL_RATE_INVALID
+ *
+ */
+const struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT] = {
+	IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2),    /*  1mbps */
+	IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5),          /*  2mbps */
+	IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
+	IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18),      /* 11mbps */
+	IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
+	IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11),       /*  9mbps */
+	IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
+	IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
+	IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
+	IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
+	IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
+	IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
+	IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
+};
+
+static int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
+{
+	int idx = 0;
+
+	/* HT rate format */
+	if (rate_n_flags & RATE_MCS_HT_MSK) {
+		idx = (rate_n_flags & 0xff);
+
+		if (idx >= IWL_RATE_MIMO2_6M_PLCP)
+			idx = idx - IWL_RATE_MIMO2_6M_PLCP;
+
+		idx += IWL_FIRST_OFDM_RATE;
+		/* skip 9M not supported in ht*/
+		if (idx >= IWL_RATE_9M_INDEX)
+			idx += 1;
+		if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
+			return idx;
+
+	/* legacy rate format, search for match in table */
+	} else {
+		for (idx = 0; idx < ARRAY_SIZE(iwlegacy_rates); idx++)
+			if (iwlegacy_rates[idx].plcp == (rate_n_flags & 0xFF))
+				return idx;
+	}
+
+	return -1;
+}
+
+static void iwl4965_rs_rate_scale_perform(struct iwl_priv *priv,
+				   struct sk_buff *skb,
+				   struct ieee80211_sta *sta,
+				   struct iwl_lq_sta *lq_sta);
+static void iwl4965_rs_fill_link_cmd(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
+static void iwl4965_rs_stay_in_table(struct iwl_lq_sta *lq_sta,
+					bool force_search);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
+			     u32 *rate_n_flags, int index);
+#else
+static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
+			     u32 *rate_n_flags, int index)
+{}
+#endif
+
+/**
+ * The following tables contain the expected throughput metrics for all rates
+ *
+ *	1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
+ *
+ * where invalid entries are zeros.
+ *
+ * CCK rates are only valid in legacy table and will only be used in G
+ * (2.4 GHz) band.
+ */
+
+static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
+	7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
+};
+
+static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0, 42, 0,  76, 102, 124, 158, 183, 193, 202}, /* Norm */
+	{0, 0, 0, 0, 46, 0,  82, 110, 132, 167, 192, 202, 210}, /* SGI */
+	{0, 0, 0, 0, 48, 0,  93, 135, 176, 251, 319, 351, 381}, /* AGG */
+	{0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
+};
+
+static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
+	{0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
+	{0, 0, 0, 0,  96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
+	{0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
+};
+
+static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
+	{0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
+	{0, 0, 0, 0,  92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
+	{0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
+};
+
+static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
+	{0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
+	{0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
+	{0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
+};
+
+/* mbps, mcs */
+static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+	{  "1", "BPSK DSSS"},
+	{  "2", "QPSK DSSS"},
+	{"5.5", "BPSK CCK"},
+	{ "11", "QPSK CCK"},
+	{  "6", "BPSK 1/2"},
+	{  "9", "BPSK 1/2"},
+	{ "12", "QPSK 1/2"},
+	{ "18", "QPSK 3/4"},
+	{ "24", "16QAM 1/2"},
+	{ "36", "16QAM 3/4"},
+	{ "48", "64QAM 2/3"},
+	{ "54", "64QAM 3/4"},
+	{ "60", "64QAM 5/6"},
+};
+
+#define MCS_INDEX_PER_STREAM	(8)
+
+static inline u8 iwl4965_rs_extract_rate(u32 rate_n_flags)
+{
+	return (u8)(rate_n_flags & 0xFF);
+}
+
+static void
+iwl4965_rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
+{
+	window->data = 0;
+	window->success_counter = 0;
+	window->success_ratio = IWL_INVALID_VALUE;
+	window->counter = 0;
+	window->average_tpt = IWL_INVALID_VALUE;
+	window->stamp = 0;
+}
+
+static inline u8 iwl4965_rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
+{
+	return (ant_type & valid_antenna) == ant_type;
+}
+
+/*
+ *	removes the old data from the statistics. All data that is older than
+ *	TID_MAX_TIME_DIFF, will be deleted.
+ */
+static void
+iwl4965_rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time)
+{
+	/* The oldest age we want to keep */
+	u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
+
+	while (tl->queue_count &&
+	       (tl->time_stamp < oldest_time)) {
+		tl->total -= tl->packet_count[tl->head];
+		tl->packet_count[tl->head] = 0;
+		tl->time_stamp += TID_QUEUE_CELL_SPACING;
+		tl->queue_count--;
+		tl->head++;
+		if (tl->head >= TID_QUEUE_MAX_SIZE)
+			tl->head = 0;
+	}
+}
+
+/*
+ *	increment traffic load value for tid and also remove
+ *	any old values if passed the certain time period
+ */
+static u8 iwl4965_rs_tl_add_packet(struct iwl_lq_sta *lq_data,
+			   struct ieee80211_hdr *hdr)
+{
+	u32 curr_time = jiffies_to_msecs(jiffies);
+	u32 time_diff;
+	s32 index;
+	struct iwl_traffic_load *tl = NULL;
+	u8 tid;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & 0xf;
+	} else
+		return MAX_TID_COUNT;
+
+	if (unlikely(tid >= TID_MAX_LOAD_COUNT))
+		return MAX_TID_COUNT;
+
+	tl = &lq_data->load[tid];
+
+	curr_time -= curr_time % TID_ROUND_VALUE;
+
+	/* Happens only for the first packet. Initialize the data */
+	if (!(tl->queue_count)) {
+		tl->total = 1;
+		tl->time_stamp = curr_time;
+		tl->queue_count = 1;
+		tl->head = 0;
+		tl->packet_count[0] = 1;
+		return MAX_TID_COUNT;
+	}
+
+	time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
+	index = time_diff / TID_QUEUE_CELL_SPACING;
+
+	/* The history is too long: remove data that is older than */
+	/* TID_MAX_TIME_DIFF */
+	if (index >= TID_QUEUE_MAX_SIZE)
+		iwl4965_rs_tl_rm_old_stats(tl, curr_time);
+
+	index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
+	tl->packet_count[index] = tl->packet_count[index] + 1;
+	tl->total = tl->total + 1;
+
+	if ((index + 1) > tl->queue_count)
+		tl->queue_count = index + 1;
+
+	return tid;
+}
+
+/*
+	get the traffic load value for tid
+*/
+static u32 iwl4965_rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
+{
+	u32 curr_time = jiffies_to_msecs(jiffies);
+	u32 time_diff;
+	s32 index;
+	struct iwl_traffic_load *tl = NULL;
+
+	if (tid >= TID_MAX_LOAD_COUNT)
+		return 0;
+
+	tl = &(lq_data->load[tid]);
+
+	curr_time -= curr_time % TID_ROUND_VALUE;
+
+	if (!(tl->queue_count))
+		return 0;
+
+	time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
+	index = time_diff / TID_QUEUE_CELL_SPACING;
+
+	/* The history is too long: remove data that is older than */
+	/* TID_MAX_TIME_DIFF */
+	if (index >= TID_QUEUE_MAX_SIZE)
+		iwl4965_rs_tl_rm_old_stats(tl, curr_time);
+
+	return tl->total;
+}
+
+static int iwl4965_rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
+				      struct iwl_lq_sta *lq_data, u8 tid,
+				      struct ieee80211_sta *sta)
+{
+	int ret = -EAGAIN;
+	u32 load;
+
+	load = iwl4965_rs_tl_get_load(lq_data, tid);
+
+	if (load > IWL_AGG_LOAD_THRESHOLD) {
+		IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
+				sta->addr, tid);
+		ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
+		if (ret == -EAGAIN) {
+			/*
+			 * driver and mac80211 is out of sync
+			 * this might be cause by reloading firmware
+			 * stop the tx ba session here
+			 */
+			IWL_ERR(priv, "Fail start Tx agg on tid: %d\n",
+				tid);
+			ieee80211_stop_tx_ba_session(sta, tid);
+		}
+	} else {
+		IWL_ERR(priv, "Aggregation not enabled for tid %d "
+			"because load = %u\n", tid, load);
+	}
+	return ret;
+}
+
+static void iwl4965_rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
+			      struct iwl_lq_sta *lq_data,
+			      struct ieee80211_sta *sta)
+{
+	if (tid < TID_MAX_LOAD_COUNT)
+		iwl4965_rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
+	else
+		IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
+			tid, TID_MAX_LOAD_COUNT);
+}
+
+static inline int iwl4965_get_iwl4965_num_of_ant_from_rate(u32 rate_n_flags)
+{
+	return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) +
+	       !!(rate_n_flags & RATE_MCS_ANT_B_MSK) +
+	       !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
+}
+
+/*
+ * Static function to get the expected throughput from an iwl_scale_tbl_info
+ * that wraps a NULL pointer check
+ */
+static s32
+iwl4965_get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
+{
+	if (tbl->expected_tpt)
+		return tbl->expected_tpt[rs_index];
+	return 0;
+}
+
+/**
+ * iwl4965_rs_collect_tx_data - Update the success/failure sliding window
+ *
+ * We keep a sliding window of the last 62 packets transmitted
+ * at this rate.  window->data contains the bitmask of successful
+ * packets.
+ */
+static int iwl4965_rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
+			      int scale_index, int attempts, int successes)
+{
+	struct iwl_rate_scale_data *window = NULL;
+	static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
+	s32 fail_count, tpt;
+
+	if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
+		return -EINVAL;
+
+	/* Select window for current tx bit rate */
+	window = &(tbl->win[scale_index]);
+
+	/* Get expected throughput */
+	tpt = iwl4965_get_expected_tpt(tbl, scale_index);
+
+	/*
+	 * Keep track of only the latest 62 tx frame attempts in this rate's
+	 * history window; anything older isn't really relevant any more.
+	 * If we have filled up the sliding window, drop the oldest attempt;
+	 * if the oldest attempt (highest bit in bitmap) shows "success",
+	 * subtract "1" from the success counter (this is the main reason
+	 * we keep these bitmaps!).
+	 */
+	while (attempts > 0) {
+		if (window->counter >= IWL_RATE_MAX_WINDOW) {
+
+			/* remove earliest */
+			window->counter = IWL_RATE_MAX_WINDOW - 1;
+
+			if (window->data & mask) {
+				window->data &= ~mask;
+				window->success_counter--;
+			}
+		}
+
+		/* Increment frames-attempted counter */
+		window->counter++;
+
+		/* Shift bitmap by one frame to throw away oldest history */
+		window->data <<= 1;
+
+		/* Mark the most recent #successes attempts as successful */
+		if (successes > 0) {
+			window->success_counter++;
+			window->data |= 0x1;
+			successes--;
+		}
+
+		attempts--;
+	}
+
+	/* Calculate current success ratio, avoid divide-by-0! */
+	if (window->counter > 0)
+		window->success_ratio = 128 * (100 * window->success_counter)
+					/ window->counter;
+	else
+		window->success_ratio = IWL_INVALID_VALUE;
+
+	fail_count = window->counter - window->success_counter;
+
+	/* Calculate average throughput, if we have enough history. */
+	if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
+	    (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
+		window->average_tpt = (window->success_ratio * tpt + 64) / 128;
+	else
+		window->average_tpt = IWL_INVALID_VALUE;
+
+	/* Tag this window as having been updated */
+	window->stamp = jiffies;
+
+	return 0;
+}
+
+/*
+ * Fill uCode API rate_n_flags field, based on "search" or "active" table.
+ */
+static u32 iwl4965_rate_n_flags_from_tbl(struct iwl_priv *priv,
+				 struct iwl_scale_tbl_info *tbl,
+				 int index, u8 use_green)
+{
+	u32 rate_n_flags = 0;
+
+	if (is_legacy(tbl->lq_type)) {
+		rate_n_flags = iwlegacy_rates[index].plcp;
+		if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
+			rate_n_flags |= RATE_MCS_CCK_MSK;
+
+	} else if (is_Ht(tbl->lq_type)) {
+		if (index > IWL_LAST_OFDM_RATE) {
+			IWL_ERR(priv, "Invalid HT rate index %d\n", index);
+			index = IWL_LAST_OFDM_RATE;
+		}
+		rate_n_flags = RATE_MCS_HT_MSK;
+
+		if (is_siso(tbl->lq_type))
+			rate_n_flags |=	iwlegacy_rates[index].plcp_siso;
+		else
+			rate_n_flags |=	iwlegacy_rates[index].plcp_mimo2;
+	} else {
+		IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type);
+	}
+
+	rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
+						     RATE_MCS_ANT_ABC_MSK);
+
+	if (is_Ht(tbl->lq_type)) {
+		if (tbl->is_ht40) {
+			if (tbl->is_dup)
+				rate_n_flags |= RATE_MCS_DUP_MSK;
+			else
+				rate_n_flags |= RATE_MCS_HT40_MSK;
+		}
+		if (tbl->is_SGI)
+			rate_n_flags |= RATE_MCS_SGI_MSK;
+
+		if (use_green) {
+			rate_n_flags |= RATE_MCS_GF_MSK;
+			if (is_siso(tbl->lq_type) && tbl->is_SGI) {
+				rate_n_flags &= ~RATE_MCS_SGI_MSK;
+				IWL_ERR(priv, "GF was set with SGI:SISO\n");
+			}
+		}
+	}
+	return rate_n_flags;
+}
+
+/*
+ * Interpret uCode API's rate_n_flags format,
+ * fill "search" or "active" tx mode table.
+ */
+static int iwl4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
+				    enum ieee80211_band band,
+				    struct iwl_scale_tbl_info *tbl,
+				    int *rate_idx)
+{
+	u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK);
+	u8 iwl4965_num_of_ant = iwl4965_get_iwl4965_num_of_ant_from_rate(rate_n_flags);
+	u8 mcs;
+
+	memset(tbl, 0, sizeof(struct iwl_scale_tbl_info));
+	*rate_idx = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
+
+	if (*rate_idx  == IWL_RATE_INVALID) {
+		*rate_idx = -1;
+		return -EINVAL;
+	}
+	tbl->is_SGI = 0;	/* default legacy setup */
+	tbl->is_ht40 = 0;
+	tbl->is_dup = 0;
+	tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
+	tbl->lq_type = LQ_NONE;
+	tbl->max_search = IWL_MAX_SEARCH;
+
+	/* legacy rate format */
+	if (!(rate_n_flags & RATE_MCS_HT_MSK)) {
+		if (iwl4965_num_of_ant == 1) {
+			if (band == IEEE80211_BAND_5GHZ)
+				tbl->lq_type = LQ_A;
+			else
+				tbl->lq_type = LQ_G;
+		}
+	/* HT rate format */
+	} else {
+		if (rate_n_flags & RATE_MCS_SGI_MSK)
+			tbl->is_SGI = 1;
+
+		if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
+		    (rate_n_flags & RATE_MCS_DUP_MSK))
+			tbl->is_ht40 = 1;
+
+		if (rate_n_flags & RATE_MCS_DUP_MSK)
+			tbl->is_dup = 1;
+
+		mcs = iwl4965_rs_extract_rate(rate_n_flags);
+
+		/* SISO */
+		if (mcs <= IWL_RATE_SISO_60M_PLCP) {
+			if (iwl4965_num_of_ant == 1)
+				tbl->lq_type = LQ_SISO; /*else NONE*/
+		/* MIMO2 */
+		} else {
+			if (iwl4965_num_of_ant == 2)
+				tbl->lq_type = LQ_MIMO2;
+		}
+	}
+	return 0;
+}
+
+/* switch to another antenna/antennas and return 1 */
+/* if no other valid antenna found, return 0 */
+static int iwl4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
+			     struct iwl_scale_tbl_info *tbl)
+{
+	u8 new_ant_type;
+
+	if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
+		return 0;
+
+	if (!iwl4965_rs_is_valid_ant(valid_ant, tbl->ant_type))
+		return 0;
+
+	new_ant_type = ant_toggle_lookup[tbl->ant_type];
+
+	while ((new_ant_type != tbl->ant_type) &&
+	       !iwl4965_rs_is_valid_ant(valid_ant, new_ant_type))
+		new_ant_type = ant_toggle_lookup[new_ant_type];
+
+	if (new_ant_type == tbl->ant_type)
+		return 0;
+
+	tbl->ant_type = new_ant_type;
+	*rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
+	*rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
+	return 1;
+}
+
+/**
+ * Green-field mode is valid if the station supports it and
+ * there are no non-GF stations present in the BSS.
+ */
+static bool iwl4965_rs_use_green(struct ieee80211_sta *sta)
+{
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
+		!(ctx->ht.non_gf_sta_present);
+}
+
+/**
+ * iwl4965_rs_get_supported_rates - get the available rates
+ *
+ * if management frame or broadcast frame only return
+ * basic available rates.
+ *
+ */
+static u16 iwl4965_rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
+				  struct ieee80211_hdr *hdr,
+				  enum iwl_table_type rate_type)
+{
+	if (is_legacy(rate_type)) {
+		return lq_sta->active_legacy_rate;
+	} else {
+		if (is_siso(rate_type))
+			return lq_sta->active_siso_rate;
+		else
+			return lq_sta->active_mimo2_rate;
+	}
+}
+
+static u16
+iwl4965_rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,
+				int rate_type)
+{
+	u8 high = IWL_RATE_INVALID;
+	u8 low = IWL_RATE_INVALID;
+
+	/* 802.11A or ht walks to the next literal adjacent rate in
+	 * the rate table */
+	if (is_a_band(rate_type) || !is_legacy(rate_type)) {
+		int i;
+		u32 mask;
+
+		/* Find the previous rate that is in the rate mask */
+		i = index - 1;
+		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
+			if (rate_mask & mask) {
+				low = i;
+				break;
+			}
+		}
+
+		/* Find the next rate that is in the rate mask */
+		i = index + 1;
+		for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) {
+			if (rate_mask & mask) {
+				high = i;
+				break;
+			}
+		}
+
+		return (high << 8) | low;
+	}
+
+	low = index;
+	while (low != IWL_RATE_INVALID) {
+		low = iwlegacy_rates[low].prev_rs;
+		if (low == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << low))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
+	}
+
+	high = index;
+	while (high != IWL_RATE_INVALID) {
+		high = iwlegacy_rates[high].next_rs;
+		if (high == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << high))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
+	}
+
+	return (high << 8) | low;
+}
+
+static u32 iwl4965_rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
+			     struct iwl_scale_tbl_info *tbl,
+			     u8 scale_index, u8 ht_possible)
+{
+	s32 low;
+	u16 rate_mask;
+	u16 high_low;
+	u8 switch_to_legacy = 0;
+	u8 is_green = lq_sta->is_green;
+	struct iwl_priv *priv = lq_sta->drv;
+
+	/* check if we need to switch from HT to legacy rates.
+	 * assumption is that mandatory rates (1Mbps or 6Mbps)
+	 * are always supported (spec demand) */
+	if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
+		switch_to_legacy = 1;
+		scale_index = rs_ht_to_legacy[scale_index];
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+			tbl->lq_type = LQ_A;
+		else
+			tbl->lq_type = LQ_G;
+
+		if (iwl4965_num_of_ant(tbl->ant_type) > 1)
+			tbl->ant_type =
+				iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+
+		tbl->is_ht40 = 0;
+		tbl->is_SGI = 0;
+		tbl->max_search = IWL_MAX_SEARCH;
+	}
+
+	rate_mask = iwl4965_rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
+
+	/* Mask with station rate restriction */
+	if (is_legacy(tbl->lq_type)) {
+		/* supp_rates has no CCK bits in A mode */
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+			rate_mask  = (u16)(rate_mask &
+			   (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+		else
+			rate_mask = (u16)(rate_mask & lq_sta->supp_rates);
+	}
+
+	/* If we switched from HT to legacy, check current rate */
+	if (switch_to_legacy && (rate_mask & (1 << scale_index))) {
+		low = scale_index;
+		goto out;
+	}
+
+	high_low = iwl4965_rs_get_adjacent_rate(lq_sta->drv,
+					scale_index, rate_mask,
+					tbl->lq_type);
+	low = high_low & 0xff;
+
+	if (low == IWL_RATE_INVALID)
+		low = scale_index;
+
+out:
+	return iwl4965_rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
+}
+
+/*
+ * Simple function to compare two rate scale table types
+ */
+static bool iwl4965_table_type_matches(struct iwl_scale_tbl_info *a,
+			       struct iwl_scale_tbl_info *b)
+{
+	return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
+		(a->is_SGI == b->is_SGI);
+}
+
+/*
+ * mac80211 sends us Tx status
+ */
+static void
+iwl4965_rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
+			 struct ieee80211_sta *sta, void *priv_sta,
+			 struct sk_buff *skb)
+{
+	int legacy_success;
+	int retries;
+	int rs_index, mac_index, i;
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	struct iwl_link_quality_cmd *table;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	enum mac80211_rate_control_flags mac_flags;
+	u32 tx_rate;
+	struct iwl_scale_tbl_info tbl_type;
+	struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	IWL_DEBUG_RATE_LIMIT(priv,
+		"get frame ack response, update rate scale window\n");
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (!lq_sta) {
+		IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n");
+		return;
+	} else if (!lq_sta->drv) {
+		IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
+		return;
+	}
+
+	if (!ieee80211_is_data(hdr->frame_control) ||
+	    info->flags & IEEE80211_TX_CTL_NO_ACK)
+		return;
+
+	/* This packet was aggregated but doesn't carry status info */
+	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
+		return;
+
+	/*
+	 * Ignore this Tx frame response if its initial rate doesn't match
+	 * that of latest Link Quality command.  There may be stragglers
+	 * from a previous Link Quality command, but we're no longer interested
+	 * in those; they're either from the "active" mode while we're trying
+	 * to check "search" mode, or a prior "search" mode after we've moved
+	 * to a new "search" mode (which might become the new "active" mode).
+	 */
+	table = &lq_sta->lq;
+	tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
+	iwl4965_rs_get_tbl_info_from_mcs(tx_rate,
+			 priv->band, &tbl_type, &rs_index);
+	if (priv->band == IEEE80211_BAND_5GHZ)
+		rs_index -= IWL_FIRST_OFDM_RATE;
+	mac_flags = info->status.rates[0].flags;
+	mac_index = info->status.rates[0].idx;
+	/* For HT packets, map MCS to PLCP */
+	if (mac_flags & IEEE80211_TX_RC_MCS) {
+		mac_index &= RATE_MCS_CODE_MSK;	/* Remove # of streams */
+		if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
+			mac_index++;
+		/*
+		 * mac80211 HT index is always zero-indexed; we need to move
+		 * HT OFDM rates after CCK rates in 2.4 GHz band
+		 */
+		if (priv->band == IEEE80211_BAND_2GHZ)
+			mac_index += IWL_FIRST_OFDM_RATE;
+	}
+	/* Here we actually compare this rate to the latest LQ command */
+	if ((mac_index < 0) ||
+	    (tbl_type.is_SGI !=
+			!!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
+	    (tbl_type.is_ht40 !=
+			!!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
+	    (tbl_type.is_dup !=
+			!!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) ||
+	    (tbl_type.ant_type != info->antenna_sel_tx) ||
+	    (!!(tx_rate & RATE_MCS_HT_MSK) !=
+			!!(mac_flags & IEEE80211_TX_RC_MCS)) ||
+	    (!!(tx_rate & RATE_MCS_GF_MSK) !=
+			!!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
+	    (rs_index != mac_index)) {
+		IWL_DEBUG_RATE(priv,
+		"initial rate %d does not match %d (0x%x)\n",
+			 mac_index, rs_index, tx_rate);
+		/*
+		 * Since rates mis-match, the last LQ command may have failed.
+		 * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
+		 * ... driver.
+		 */
+		lq_sta->missed_rate_counter++;
+		if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
+			lq_sta->missed_rate_counter = 0;
+			iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq,
+							CMD_ASYNC, false);
+		}
+		/* Regardless, ignore this status info for outdated rate */
+		return;
+	} else
+		/* Rate did match, so reset the missed_rate_counter */
+		lq_sta->missed_rate_counter = 0;
+
+	/* Figure out if rate scale algorithm is in active or search table */
+	if (iwl4965_table_type_matches(&tbl_type,
+				&(lq_sta->lq_info[lq_sta->active_tbl]))) {
+		curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+		other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+	} else if (iwl4965_table_type_matches(&tbl_type,
+				&lq_sta->lq_info[1 - lq_sta->active_tbl])) {
+		curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+		other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	} else {
+		IWL_DEBUG_RATE(priv,
+			"Neither active nor search matches tx rate\n");
+		tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+		IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n",
+			tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
+		tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+		IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n",
+			tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
+		IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n",
+			tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI);
+		/*
+		 * no matching table found, let's by-pass the data collection
+		 * and continue to perform rate scale to find the rate table
+		 */
+		iwl4965_rs_stay_in_table(lq_sta, true);
+		goto done;
+	}
+
+	/*
+	 * Updating the frame history depends on whether packets were
+	 * aggregated.
+	 *
+	 * For aggregation, all packets were transmitted at the same rate, the
+	 * first index into rate scale table.
+	 */
+	if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+		tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
+		iwl4965_rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
+				&rs_index);
+		iwl4965_rs_collect_tx_data(curr_tbl, rs_index,
+				   info->status.ampdu_len,
+				   info->status.ampdu_ack_len);
+
+		/* Update success/fail counts if not searching for new mode */
+		if (lq_sta->stay_in_tbl) {
+			lq_sta->total_success += info->status.ampdu_ack_len;
+			lq_sta->total_failed += (info->status.ampdu_len -
+					info->status.ampdu_ack_len);
+		}
+	} else {
+	/*
+	 * For legacy, update frame history with for each Tx retry.
+	 */
+		retries = info->status.rates[0].count - 1;
+		/* HW doesn't send more than 15 retries */
+		retries = min(retries, 15);
+
+		/* The last transmission may have been successful */
+		legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+		/* Collect data for each rate used during failed TX attempts */
+		for (i = 0; i <= retries; ++i) {
+			tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags);
+			iwl4965_rs_get_tbl_info_from_mcs(tx_rate, priv->band,
+					&tbl_type, &rs_index);
+			/*
+			 * Only collect stats if retried rate is in the same RS
+			 * table as active/search.
+			 */
+			if (iwl4965_table_type_matches(&tbl_type, curr_tbl))
+				tmp_tbl = curr_tbl;
+			else if (iwl4965_table_type_matches(&tbl_type,
+								 other_tbl))
+				tmp_tbl = other_tbl;
+			else
+				continue;
+			iwl4965_rs_collect_tx_data(tmp_tbl, rs_index, 1,
+					   i < retries ? 0 : legacy_success);
+		}
+
+		/* Update success/fail counts if not searching for new mode */
+		if (lq_sta->stay_in_tbl) {
+			lq_sta->total_success += legacy_success;
+			lq_sta->total_failed += retries + (1 - legacy_success);
+		}
+	}
+	/* The last TX rate is cached in lq_sta; it's set in if/else above */
+	lq_sta->last_rate_n_flags = tx_rate;
+done:
+	/* See if there's a better rate or modulation mode to try. */
+	if (sta && sta->supp_rates[sband->band])
+		iwl4965_rs_rate_scale_perform(priv, skb, sta, lq_sta);
+}
+
+/*
+ * Begin a period of staying with a selected modulation mode.
+ * Set "stay_in_tbl" flag to prevent any mode switches.
+ * Set frame tx success limits according to legacy vs. high-throughput,
+ * and reset overall (spanning all rates) tx success history statistics.
+ * These control how long we stay using same modulation mode before
+ * searching for a new mode.
+ */
+static void iwl4965_rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
+				 struct iwl_lq_sta *lq_sta)
+{
+	IWL_DEBUG_RATE(priv, "we are staying in the same table\n");
+	lq_sta->stay_in_tbl = 1;	/* only place this gets set */
+	if (is_legacy) {
+		lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT;
+		lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;
+		lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT;
+	} else {
+		lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT;
+		lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT;
+		lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT;
+	}
+	lq_sta->table_count = 0;
+	lq_sta->total_failed = 0;
+	lq_sta->total_success = 0;
+	lq_sta->flush_timer = jiffies;
+	lq_sta->action_counter = 0;
+}
+
+/*
+ * Find correct throughput table for given mode of modulation
+ */
+static void iwl4965_rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
+				      struct iwl_scale_tbl_info *tbl)
+{
+	/* Used to choose among HT tables */
+	s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
+
+	/* Check for invalid LQ type */
+	if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
+		tbl->expected_tpt = expected_tpt_legacy;
+		return;
+	}
+
+	/* Legacy rates have only one table */
+	if (is_legacy(tbl->lq_type)) {
+		tbl->expected_tpt = expected_tpt_legacy;
+		return;
+	}
+
+	/* Choose among many HT tables depending on number of streams
+	 * (SISO/MIMO2), channel width (20/40), SGI, and aggregation
+	 * status */
+	if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
+		ht_tbl_pointer = expected_tpt_siso20MHz;
+	else if (is_siso(tbl->lq_type))
+		ht_tbl_pointer = expected_tpt_siso40MHz;
+	else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
+		ht_tbl_pointer = expected_tpt_mimo2_20MHz;
+	else /* if (is_mimo2(tbl->lq_type)) <-- must be true */
+		ht_tbl_pointer = expected_tpt_mimo2_40MHz;
+
+	if (!tbl->is_SGI && !lq_sta->is_agg)		/* Normal */
+		tbl->expected_tpt = ht_tbl_pointer[0];
+	else if (tbl->is_SGI && !lq_sta->is_agg)	/* SGI */
+		tbl->expected_tpt = ht_tbl_pointer[1];
+	else if (!tbl->is_SGI && lq_sta->is_agg)	/* AGG */
+		tbl->expected_tpt = ht_tbl_pointer[2];
+	else						/* AGG+SGI */
+		tbl->expected_tpt = ht_tbl_pointer[3];
+}
+
+/*
+ * Find starting rate for new "search" high-throughput mode of modulation.
+ * Goal is to find lowest expected rate (under perfect conditions) that is
+ * above the current measured throughput of "active" mode, to give new mode
+ * a fair chance to prove itself without too many challenges.
+ *
+ * This gets called when transitioning to more aggressive modulation
+ * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
+ * (i.e. MIMO to SISO).  When moving to MIMO, bit rate will typically need
+ * to decrease to match "active" throughput.  When moving from MIMO to SISO,
+ * bit rate will typically need to increase, but not if performance was bad.
+ */
+static s32 iwl4965_rs_get_best_rate(struct iwl_priv *priv,
+			    struct iwl_lq_sta *lq_sta,
+			    struct iwl_scale_tbl_info *tbl,	/* "search" */
+			    u16 rate_mask, s8 index)
+{
+	/* "active" values */
+	struct iwl_scale_tbl_info *active_tbl =
+	    &(lq_sta->lq_info[lq_sta->active_tbl]);
+	s32 active_sr = active_tbl->win[index].success_ratio;
+	s32 active_tpt = active_tbl->expected_tpt[index];
+
+	/* expected "search" throughput */
+	s32 *tpt_tbl = tbl->expected_tpt;
+
+	s32 new_rate, high, low, start_hi;
+	u16 high_low;
+	s8 rate = index;
+
+	new_rate = high = low = start_hi = IWL_RATE_INVALID;
+
+	for (; ;) {
+		high_low = iwl4965_rs_get_adjacent_rate(priv, rate, rate_mask,
+						tbl->lq_type);
+
+		low = high_low & 0xff;
+		high = (high_low >> 8) & 0xff;
+
+		/*
+		 * Lower the "search" bit rate, to give new "search" mode
+		 * approximately the same throughput as "active" if:
+		 *
+		 * 1) "Active" mode has been working modestly well (but not
+		 *    great), and expected "search" throughput (under perfect
+		 *    conditions) at candidate rate is above the actual
+		 *    measured "active" throughput (but less than expected
+		 *    "active" throughput under perfect conditions).
+		 * OR
+		 * 2) "Active" mode has been working perfectly or very well
+		 *    and expected "search" throughput (under perfect
+		 *    conditions) at candidate rate is above expected
+		 *    "active" throughput (under perfect conditions).
+		 */
+		if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
+		     ((active_sr > IWL_RATE_DECREASE_TH) &&
+		      (active_sr <= IWL_RATE_HIGH_TH) &&
+		      (tpt_tbl[rate] <= active_tpt))) ||
+		    ((active_sr >= IWL_RATE_SCALE_SWITCH) &&
+		     (tpt_tbl[rate] > active_tpt))) {
+
+			/* (2nd or later pass)
+			 * If we've already tried to raise the rate, and are
+			 * now trying to lower it, use the higher rate. */
+			if (start_hi != IWL_RATE_INVALID) {
+				new_rate = start_hi;
+				break;
+			}
+
+			new_rate = rate;
+
+			/* Loop again with lower rate */
+			if (low != IWL_RATE_INVALID)
+				rate = low;
+
+			/* Lower rate not available, use the original */
+			else
+				break;
+
+		/* Else try to raise the "search" rate to match "active" */
+		} else {
+			/* (2nd or later pass)
+			 * If we've already tried to lower the rate, and are
+			 * now trying to raise it, use the lower rate. */
+			if (new_rate != IWL_RATE_INVALID)
+				break;
+
+			/* Loop again with higher rate */
+			else if (high != IWL_RATE_INVALID) {
+				start_hi = high;
+				rate = high;
+
+			/* Higher rate not available, use the original */
+			} else {
+				new_rate = rate;
+				break;
+			}
+		}
+	}
+
+	return new_rate;
+}
+
+/*
+ * Set up search table for MIMO2
+ */
+static int iwl4965_rs_switch_to_mimo2(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta,
+			     struct ieee80211_conf *conf,
+			     struct ieee80211_sta *sta,
+			     struct iwl_scale_tbl_info *tbl, int index)
+{
+	u16 rate_mask;
+	s32 rate;
+	s8 is_green = lq_sta->is_green;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+		return -1;
+
+	if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
+						== WLAN_HT_CAP_SM_PS_STATIC)
+		return -1;
+
+	/* Need both Tx chains/antennas to support MIMO */
+	if (priv->hw_params.tx_chains_num < 2)
+		return -1;
+
+	IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n");
+
+	tbl->lq_type = LQ_MIMO2;
+	tbl->is_dup = lq_sta->is_dup;
+	tbl->action = 0;
+	tbl->max_search = IWL_MAX_SEARCH;
+	rate_mask = lq_sta->active_mimo2_rate;
+
+	if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+		tbl->is_ht40 = 1;
+	else
+		tbl->is_ht40 = 0;
+
+	iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
+
+	rate = iwl4965_rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
+
+	IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n",
+				rate, rate_mask);
+	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
+		IWL_DEBUG_RATE(priv,
+				"Can't switch with index %d rate mask %x\n",
+						rate, rate_mask);
+		return -1;
+	}
+	tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv,
+						 tbl, rate, is_green);
+
+	IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
+		     tbl->current_rate, is_green);
+	return 0;
+}
+
+/*
+ * Set up search table for SISO
+ */
+static int iwl4965_rs_switch_to_siso(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta,
+			     struct ieee80211_conf *conf,
+			     struct ieee80211_sta *sta,
+			     struct iwl_scale_tbl_info *tbl, int index)
+{
+	u16 rate_mask;
+	u8 is_green = lq_sta->is_green;
+	s32 rate;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+		return -1;
+
+	IWL_DEBUG_RATE(priv, "LQ: try to switch to SISO\n");
+
+	tbl->is_dup = lq_sta->is_dup;
+	tbl->lq_type = LQ_SISO;
+	tbl->action = 0;
+	tbl->max_search = IWL_MAX_SEARCH;
+	rate_mask = lq_sta->active_siso_rate;
+
+	if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+		tbl->is_ht40 = 1;
+	else
+		tbl->is_ht40 = 0;
+
+	if (is_green)
+		tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/
+
+	iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
+	rate = iwl4965_rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
+
+	IWL_DEBUG_RATE(priv, "LQ: get best rate %d mask %X\n", rate, rate_mask);
+	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
+		IWL_DEBUG_RATE(priv,
+			"can not switch with index %d rate mask %x\n",
+			     rate, rate_mask);
+		return -1;
+	}
+	tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv,
+						tbl, rate, is_green);
+	IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
+		     tbl->current_rate, is_green);
+	return 0;
+}
+
+/*
+ * Try to switch to new modulation mode from legacy
+ */
+static int iwl4965_rs_move_legacy_other(struct iwl_priv *priv,
+				struct iwl_lq_sta *lq_sta,
+				struct ieee80211_conf *conf,
+				struct ieee80211_sta *sta,
+				int index)
+{
+	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	struct iwl_scale_tbl_info *search_tbl =
+				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_action;
+	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	int ret = 0;
+	u8 update_search_tbl_counter = 0;
+
+	tbl->action = IWL_LEGACY_SWITCH_SISO;
+
+	start_action = tbl->action;
+	for (; ;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_LEGACY_SWITCH_ANTENNA1:
+		case IWL_LEGACY_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n");
+
+			if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
+							tx_chains_num <= 1) ||
+			    (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
+							tx_chains_num <= 2))
+				break;
+
+			/* Don't change antenna if success has been great */
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			/* Set up search table to try other antenna */
+			memcpy(search_tbl, tbl, sz);
+
+			if (iwl4965_rs_toggle_antenna(valid_tx_ant,
+				&search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
+				iwl4965_rs_set_expected_tpt_table(lq_sta,
+								search_tbl);
+				goto out;
+			}
+			break;
+		case IWL_LEGACY_SWITCH_SISO:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy switch to SISO\n");
+
+			/* Set up search table to try SISO */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			ret = iwl4965_rs_switch_to_siso(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret) {
+				lq_sta->action_counter = 0;
+				goto out;
+			}
+
+			break;
+		case IWL_LEGACY_SWITCH_MIMO2_AB:
+		case IWL_LEGACY_SWITCH_MIMO2_AC:
+		case IWL_LEGACY_SWITCH_MIMO2_BC:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO2\n");
+
+			/* Set up search table to try MIMO */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+
+			if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB)
+				search_tbl->ant_type = ANT_AB;
+			else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC)
+				search_tbl->ant_type = ANT_AC;
+			else
+				search_tbl->ant_type = ANT_BC;
+
+			if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
+						search_tbl->ant_type))
+				break;
+
+			ret = iwl4965_rs_switch_to_mimo2(priv, lq_sta,
+						conf, sta,
+						 search_tbl, index);
+			if (!ret) {
+				lq_sta->action_counter = 0;
+				goto out;
+			}
+			break;
+		}
+		tbl->action++;
+		if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+			tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+
+		if (tbl->action == start_action)
+			break;
+
+	}
+	search_tbl->lq_type = LQ_NONE;
+	return 0;
+
+out:
+	lq_sta->search_better_tbl = 1;
+	tbl->action++;
+	if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+		tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+	return 0;
+
+}
+
+/*
+ * Try to switch to new modulation mode from SISO
+ */
+static int iwl4965_rs_move_siso_to_other(struct iwl_priv *priv,
+				 struct iwl_lq_sta *lq_sta,
+				 struct ieee80211_conf *conf,
+				 struct ieee80211_sta *sta, int index)
+{
+	u8 is_green = lq_sta->is_green;
+	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	struct iwl_scale_tbl_info *search_tbl =
+				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_action;
+	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	u8 update_search_tbl_counter = 0;
+	int ret;
+
+	start_action = tbl->action;
+
+	for (;;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_SISO_SWITCH_ANTENNA1:
+		case IWL_SISO_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n");
+			if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
+						tx_chains_num <= 1) ||
+			    (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
+						tx_chains_num <= 2))
+				break;
+
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			memcpy(search_tbl, tbl, sz);
+			if (iwl4965_rs_toggle_antenna(valid_tx_ant,
+				       &search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
+				goto out;
+			}
+			break;
+		case IWL_SISO_SWITCH_MIMO2_AB:
+		case IWL_SISO_SWITCH_MIMO2_AC:
+		case IWL_SISO_SWITCH_MIMO2_BC:
+			IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO2\n");
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+
+			if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB)
+				search_tbl->ant_type = ANT_AB;
+			else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC)
+				search_tbl->ant_type = ANT_AC;
+			else
+				search_tbl->ant_type = ANT_BC;
+
+			if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
+						 search_tbl->ant_type))
+				break;
+
+			ret = iwl4965_rs_switch_to_mimo2(priv, lq_sta,
+						conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+			break;
+		case IWL_SISO_SWITCH_GI:
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
+				break;
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
+				break;
+
+			IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n");
+
+			memcpy(search_tbl, tbl, sz);
+			if (is_green) {
+				if (!tbl->is_SGI)
+					break;
+				else
+					IWL_ERR(priv,
+						"SGI was set in GF+SISO\n");
+			}
+			search_tbl->is_SGI = !tbl->is_SGI;
+			iwl4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
+			if (tbl->is_SGI) {
+				s32 tpt = lq_sta->last_tpt / 100;
+				if (tpt >= search_tbl->expected_tpt[index])
+					break;
+			}
+			search_tbl->current_rate =
+				iwl4965_rate_n_flags_from_tbl(priv, search_tbl,
+						      index, is_green);
+			update_search_tbl_counter = 1;
+			goto out;
+		}
+		tbl->action++;
+		if (tbl->action > IWL_SISO_SWITCH_GI)
+			tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+
+		if (tbl->action == start_action)
+			break;
+	}
+	search_tbl->lq_type = LQ_NONE;
+	return 0;
+
+ out:
+	lq_sta->search_better_tbl = 1;
+	tbl->action++;
+	if (tbl->action > IWL_SISO_SWITCH_GI)
+		tbl->action = IWL_SISO_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+
+	return 0;
+}
+
+/*
+ * Try to switch to new modulation mode from MIMO2
+ */
+static int iwl4965_rs_move_mimo2_to_other(struct iwl_priv *priv,
+				 struct iwl_lq_sta *lq_sta,
+				 struct ieee80211_conf *conf,
+				 struct ieee80211_sta *sta, int index)
+{
+	s8 is_green = lq_sta->is_green;
+	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	struct iwl_scale_tbl_info *search_tbl =
+				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_action;
+	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	u8 update_search_tbl_counter = 0;
+	int ret;
+
+	start_action = tbl->action;
+	for (;;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_MIMO2_SWITCH_ANTENNA1:
+		case IWL_MIMO2_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n");
+
+			if (tx_chains_num <= 2)
+				break;
+
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			memcpy(search_tbl, tbl, sz);
+			if (iwl4965_rs_toggle_antenna(valid_tx_ant,
+				       &search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
+				goto out;
+			}
+			break;
+		case IWL_MIMO2_SWITCH_SISO_A:
+		case IWL_MIMO2_SWITCH_SISO_B:
+		case IWL_MIMO2_SWITCH_SISO_C:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to SISO\n");
+
+			/* Set up new search table for SISO */
+			memcpy(search_tbl, tbl, sz);
+
+			if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
+				search_tbl->ant_type = ANT_A;
+			else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
+				search_tbl->ant_type = ANT_B;
+			else
+				search_tbl->ant_type = ANT_C;
+
+			if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
+						search_tbl->ant_type))
+				break;
+
+			ret = iwl4965_rs_switch_to_siso(priv, lq_sta,
+						conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
+
+		case IWL_MIMO2_SWITCH_GI:
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
+				break;
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
+				break;
+
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
+
+			/* Set up new search table for MIMO2 */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = !tbl->is_SGI;
+			iwl4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
+			/*
+			 * If active table already uses the fastest possible
+			 * modulation (dual stream with short guard interval),
+			 * and it's working well, there's no need to look
+			 * for a better type of modulation!
+			 */
+			if (tbl->is_SGI) {
+				s32 tpt = lq_sta->last_tpt / 100;
+				if (tpt >= search_tbl->expected_tpt[index])
+					break;
+			}
+			search_tbl->current_rate =
+				iwl4965_rate_n_flags_from_tbl(priv, search_tbl,
+						      index, is_green);
+			update_search_tbl_counter = 1;
+			goto out;
+
+		}
+		tbl->action++;
+		if (tbl->action > IWL_MIMO2_SWITCH_GI)
+			tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
+
+		if (tbl->action == start_action)
+			break;
+	}
+	search_tbl->lq_type = LQ_NONE;
+	return 0;
+ out:
+	lq_sta->search_better_tbl = 1;
+	tbl->action++;
+	if (tbl->action > IWL_MIMO2_SWITCH_GI)
+		tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+
+	return 0;
+
+}
+
+/*
+ * Check whether we should continue using same modulation mode, or
+ * begin search for a new mode, based on:
+ * 1) # tx successes or failures while using this mode
+ * 2) # times calling this function
+ * 3) elapsed time in this mode (not used, for now)
+ */
+static void
+iwl4965_rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
+{
+	struct iwl_scale_tbl_info *tbl;
+	int i;
+	int active_tbl;
+	int flush_interval_passed = 0;
+	struct iwl_priv *priv;
+
+	priv = lq_sta->drv;
+	active_tbl = lq_sta->active_tbl;
+
+	tbl = &(lq_sta->lq_info[active_tbl]);
+
+	/* If we've been disallowing search, see if we should now allow it */
+	if (lq_sta->stay_in_tbl) {
+
+		/* Elapsed time using current modulation mode */
+		if (lq_sta->flush_timer)
+			flush_interval_passed =
+			time_after(jiffies,
+					(unsigned long)(lq_sta->flush_timer +
+					IWL_RATE_SCALE_FLUSH_INTVL));
+
+		/*
+		 * Check if we should allow search for new modulation mode.
+		 * If many frames have failed or succeeded, or we've used
+		 * this same modulation for a long time, allow search, and
+		 * reset history stats that keep track of whether we should
+		 * allow a new search.  Also (below) reset all bitmaps and
+		 * stats in active history.
+		 */
+		if (force_search ||
+		    (lq_sta->total_failed > lq_sta->max_failure_limit) ||
+		    (lq_sta->total_success > lq_sta->max_success_limit) ||
+		    ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer)
+		     && (flush_interval_passed))) {
+			IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n:",
+				     lq_sta->total_failed,
+				     lq_sta->total_success,
+				     flush_interval_passed);
+
+			/* Allow search for new mode */
+			lq_sta->stay_in_tbl = 0;	/* only place reset */
+			lq_sta->total_failed = 0;
+			lq_sta->total_success = 0;
+			lq_sta->flush_timer = 0;
+
+		/*
+		 * Else if we've used this modulation mode enough repetitions
+		 * (regardless of elapsed time or success/failure), reset
+		 * history bitmaps and rate-specific stats for all rates in
+		 * active table.
+		 */
+		} else {
+			lq_sta->table_count++;
+			if (lq_sta->table_count >=
+			    lq_sta->table_count_limit) {
+				lq_sta->table_count = 0;
+
+				IWL_DEBUG_RATE(priv,
+					"LQ: stay in table clear win\n");
+				for (i = 0; i < IWL_RATE_COUNT; i++)
+					iwl4965_rs_rate_scale_clear_window(
+						&(tbl->win[i]));
+			}
+		}
+
+		/* If transitioning to allow "search", reset all history
+		 * bitmaps and stats in active table (this will become the new
+		 * "search" table). */
+		if (!lq_sta->stay_in_tbl) {
+			for (i = 0; i < IWL_RATE_COUNT; i++)
+				iwl4965_rs_rate_scale_clear_window(
+							&(tbl->win[i]));
+		}
+	}
+}
+
+/*
+ * setup rate table in uCode
+ * return rate_n_flags as used in the table
+ */
+static u32 iwl4965_rs_update_rate_tbl(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+				struct iwl_lq_sta *lq_sta,
+				struct iwl_scale_tbl_info *tbl,
+				int index, u8 is_green)
+{
+	u32 rate;
+
+	/* Update uCode's rate table. */
+	rate = iwl4965_rate_n_flags_from_tbl(priv, tbl, index, is_green);
+	iwl4965_rs_fill_link_cmd(priv, lq_sta, rate);
+	iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
+
+	return rate;
+}
+
+/*
+ * Do rate scaling and search for new modulation mode.
+ */
+static void iwl4965_rs_rate_scale_perform(struct iwl_priv *priv,
+				  struct sk_buff *skb,
+				  struct ieee80211_sta *sta,
+				  struct iwl_lq_sta *lq_sta)
+{
+	struct ieee80211_hw *hw = priv->hw;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	int low = IWL_RATE_INVALID;
+	int high = IWL_RATE_INVALID;
+	int index;
+	int i;
+	struct iwl_rate_scale_data *window = NULL;
+	int current_tpt = IWL_INVALID_VALUE;
+	int low_tpt = IWL_INVALID_VALUE;
+	int high_tpt = IWL_INVALID_VALUE;
+	u32 fail_count;
+	s8 scale_action = 0;
+	u16 rate_mask;
+	u8 update_lq = 0;
+	struct iwl_scale_tbl_info *tbl, *tbl1;
+	u16 rate_scale_index_msk = 0;
+	u32 rate;
+	u8 is_green = 0;
+	u8 active_tbl = 0;
+	u8 done_search = 0;
+	u16 high_low;
+	s32 sr;
+	u8 tid = MAX_TID_COUNT;
+	struct iwl_tid_data *tid_data;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
+
+	/* Send management frames and NO_ACK data using lowest rate. */
+	/* TODO: this could probably be improved.. */
+	if (!ieee80211_is_data(hdr->frame_control) ||
+	    info->flags & IEEE80211_TX_CTL_NO_ACK)
+		return;
+
+	if (!sta || !lq_sta)
+		return;
+
+	lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
+
+	tid = iwl4965_rs_tl_add_packet(lq_sta, hdr);
+	if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) {
+		tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid];
+		if (tid_data->agg.state == IWL_AGG_OFF)
+			lq_sta->is_agg = 0;
+		else
+			lq_sta->is_agg = 1;
+	} else
+		lq_sta->is_agg = 0;
+
+	/*
+	 * Select rate-scale / modulation-mode table to work with in
+	 * the rest of this function:  "search" if searching for better
+	 * modulation mode, or "active" if doing rate scaling within a mode.
+	 */
+	if (!lq_sta->search_better_tbl)
+		active_tbl = lq_sta->active_tbl;
+	else
+		active_tbl = 1 - lq_sta->active_tbl;
+
+	tbl = &(lq_sta->lq_info[active_tbl]);
+	if (is_legacy(tbl->lq_type))
+		lq_sta->is_green = 0;
+	else
+		lq_sta->is_green = iwl4965_rs_use_green(sta);
+	is_green = lq_sta->is_green;
+
+	/* current tx rate */
+	index = lq_sta->last_txrate_idx;
+
+	IWL_DEBUG_RATE(priv, "Rate scale index %d for type %d\n", index,
+		       tbl->lq_type);
+
+	/* rates available for this association, and for modulation mode */
+	rate_mask = iwl4965_rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
+
+	IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask);
+
+	/* mask with station rate restriction */
+	if (is_legacy(tbl->lq_type)) {
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+			/* supp_rates has no CCK bits in A mode */
+			rate_scale_index_msk = (u16) (rate_mask &
+				(lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+		else
+			rate_scale_index_msk = (u16) (rate_mask &
+						      lq_sta->supp_rates);
+
+	} else
+		rate_scale_index_msk = rate_mask;
+
+	if (!rate_scale_index_msk)
+		rate_scale_index_msk = rate_mask;
+
+	if (!((1 << index) & rate_scale_index_msk)) {
+		IWL_ERR(priv, "Current Rate is not valid\n");
+		if (lq_sta->search_better_tbl) {
+			/* revert to active table if search table is not valid*/
+			tbl->lq_type = LQ_NONE;
+			lq_sta->search_better_tbl = 0;
+			tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+			/* get "active" rate info */
+			index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
+			rate = iwl4965_rs_update_rate_tbl(priv, ctx, lq_sta,
+						  tbl, index, is_green);
+		}
+		return;
+	}
+
+	/* Get expected throughput table and history window for current rate */
+	if (!tbl->expected_tpt) {
+		IWL_ERR(priv, "tbl->expected_tpt is NULL\n");
+		return;
+	}
+
+	/* force user max rate if set by user */
+	if ((lq_sta->max_rate_idx != -1) &&
+	    (lq_sta->max_rate_idx < index)) {
+		index = lq_sta->max_rate_idx;
+		update_lq = 1;
+		window = &(tbl->win[index]);
+		goto lq_update;
+	}
+
+	window = &(tbl->win[index]);
+
+	/*
+	 * If there is not enough history to calculate actual average
+	 * throughput, keep analyzing results of more tx frames, without
+	 * changing rate or mode (bypass most of the rest of this function).
+	 * Set up new rate table in uCode only if old rate is not supported
+	 * in current association (use new rate found above).
+	 */
+	fail_count = window->counter - window->success_counter;
+	if ((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
+			(window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) {
+		IWL_DEBUG_RATE(priv, "LQ: still below TH. succ=%d total=%d "
+			       "for index %d\n",
+			       window->success_counter, window->counter, index);
+
+		/* Can't calculate this yet; not enough history */
+		window->average_tpt = IWL_INVALID_VALUE;
+
+		/* Should we stay with this modulation mode,
+		 * or search for a new one? */
+		iwl4965_rs_stay_in_table(lq_sta, false);
+
+		goto out;
+	}
+	/* Else we have enough samples; calculate estimate of
+	 * actual average throughput */
+	if (window->average_tpt != ((window->success_ratio *
+			tbl->expected_tpt[index] + 64) / 128)) {
+		IWL_ERR(priv,
+			 "expected_tpt should have been calculated by now\n");
+		window->average_tpt = ((window->success_ratio *
+					tbl->expected_tpt[index] + 64) / 128);
+	}
+
+	/* If we are searching for better modulation mode, check success. */
+	if (lq_sta->search_better_tbl) {
+		/* If good success, continue using the "search" mode;
+		 * no need to send new link quality command, since we're
+		 * continuing to use the setup that we've been trying. */
+		if (window->average_tpt > lq_sta->last_tpt) {
+
+			IWL_DEBUG_RATE(priv, "LQ: SWITCHING TO NEW TABLE "
+					"suc=%d cur-tpt=%d old-tpt=%d\n",
+					window->success_ratio,
+					window->average_tpt,
+					lq_sta->last_tpt);
+
+			if (!is_legacy(tbl->lq_type))
+				lq_sta->enable_counter = 1;
+
+			/* Swap tables; "search" becomes "active" */
+			lq_sta->active_tbl = active_tbl;
+			current_tpt = window->average_tpt;
+
+		/* Else poor success; go back to mode in "active" table */
+		} else {
+
+			IWL_DEBUG_RATE(priv, "LQ: GOING BACK TO THE OLD TABLE "
+					"suc=%d cur-tpt=%d old-tpt=%d\n",
+					window->success_ratio,
+					window->average_tpt,
+					lq_sta->last_tpt);
+
+			/* Nullify "search" table */
+			tbl->lq_type = LQ_NONE;
+
+			/* Revert to "active" table */
+			active_tbl = lq_sta->active_tbl;
+			tbl = &(lq_sta->lq_info[active_tbl]);
+
+			/* Revert to "active" rate and throughput info */
+			index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
+			current_tpt = lq_sta->last_tpt;
+
+			/* Need to set up a new rate table in uCode */
+			update_lq = 1;
+		}
+
+		/* Either way, we've made a decision; modulation mode
+		 * search is done, allow rate adjustment next time. */
+		lq_sta->search_better_tbl = 0;
+		done_search = 1;	/* Don't switch modes below! */
+		goto lq_update;
+	}
+
+	/* (Else) not in search of better modulation mode, try for better
+	 * starting rate, while staying in this mode. */
+	high_low = iwl4965_rs_get_adjacent_rate(priv, index,
+					rate_scale_index_msk,
+					tbl->lq_type);
+	low = high_low & 0xff;
+	high = (high_low >> 8) & 0xff;
+
+	/* If user set max rate, dont allow higher than user constrain */
+	if ((lq_sta->max_rate_idx != -1) &&
+	    (lq_sta->max_rate_idx < high))
+		high = IWL_RATE_INVALID;
+
+	sr = window->success_ratio;
+
+	/* Collect measured throughputs for current and adjacent rates */
+	current_tpt = window->average_tpt;
+	if (low != IWL_RATE_INVALID)
+		low_tpt = tbl->win[low].average_tpt;
+	if (high != IWL_RATE_INVALID)
+		high_tpt = tbl->win[high].average_tpt;
+
+	scale_action = 0;
+
+	/* Too many failures, decrease rate */
+	if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) {
+		IWL_DEBUG_RATE(priv,
+			"decrease rate because of low success_ratio\n");
+		scale_action = -1;
+
+	/* No throughput measured yet for adjacent rates; try increase. */
+	} else if ((low_tpt == IWL_INVALID_VALUE) &&
+		   (high_tpt == IWL_INVALID_VALUE)) {
+
+		if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH)
+			scale_action = 1;
+		else if (low != IWL_RATE_INVALID)
+			scale_action = 0;
+	}
+
+	/* Both adjacent throughputs are measured, but neither one has better
+	 * throughput; we're using the best rate, don't change it! */
+	else if ((low_tpt != IWL_INVALID_VALUE) &&
+		 (high_tpt != IWL_INVALID_VALUE) &&
+		 (low_tpt < current_tpt) &&
+		 (high_tpt < current_tpt))
+		scale_action = 0;
+
+	/* At least one adjacent rate's throughput is measured,
+	 * and may have better performance. */
+	else {
+		/* Higher adjacent rate's throughput is measured */
+		if (high_tpt != IWL_INVALID_VALUE) {
+			/* Higher rate has better throughput */
+			if (high_tpt > current_tpt &&
+					sr >= IWL_RATE_INCREASE_TH) {
+				scale_action = 1;
+			} else {
+				scale_action = 0;
+			}
+
+		/* Lower adjacent rate's throughput is measured */
+		} else if (low_tpt != IWL_INVALID_VALUE) {
+			/* Lower rate has better throughput */
+			if (low_tpt > current_tpt) {
+				IWL_DEBUG_RATE(priv,
+				    "decrease rate because of low tpt\n");
+				scale_action = -1;
+			} else if (sr >= IWL_RATE_INCREASE_TH) {
+				scale_action = 1;
+			}
+		}
+	}
+
+	/* Sanity check; asked for decrease, but success rate or throughput
+	 * has been good at old rate.  Don't change it. */
+	if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
+		    ((sr > IWL_RATE_HIGH_TH) ||
+		     (current_tpt > (100 * tbl->expected_tpt[low]))))
+		scale_action = 0;
+
+	switch (scale_action) {
+	case -1:
+		/* Decrease starting rate, update uCode's rate table */
+		if (low != IWL_RATE_INVALID) {
+			update_lq = 1;
+			index = low;
+		}
+
+		break;
+	case 1:
+		/* Increase starting rate, update uCode's rate table */
+		if (high != IWL_RATE_INVALID) {
+			update_lq = 1;
+			index = high;
+		}
+
+		break;
+	case 0:
+		/* No change */
+	default:
+		break;
+	}
+
+	IWL_DEBUG_RATE(priv, "choose rate scale index %d action %d low %d "
+		    "high %d type %d\n",
+		     index, scale_action, low, high, tbl->lq_type);
+
+lq_update:
+	/* Replace uCode's rate table for the destination station. */
+	if (update_lq)
+		rate = iwl4965_rs_update_rate_tbl(priv, ctx, lq_sta,
+					  tbl, index, is_green);
+
+	/* Should we stay with this modulation mode,
+	 * or search for a new one? */
+	 iwl4965_rs_stay_in_table(lq_sta, false);
+
+	/*
+	 * Search for new modulation mode if we're:
+	 * 1)  Not changing rates right now
+	 * 2)  Not just finishing up a search
+	 * 3)  Allowing a new search
+	 */
+	if (!update_lq && !done_search &&
+		!lq_sta->stay_in_tbl && window->counter) {
+		/* Save current throughput to compare with "search" throughput*/
+		lq_sta->last_tpt = current_tpt;
+
+		/* Select a new "search" modulation mode to try.
+		 * If one is found, set up the new "search" table. */
+		if (is_legacy(tbl->lq_type))
+			iwl4965_rs_move_legacy_other(priv, lq_sta,
+							conf, sta, index);
+		else if (is_siso(tbl->lq_type))
+			iwl4965_rs_move_siso_to_other(priv, lq_sta,
+							conf, sta, index);
+		else /* (is_mimo2(tbl->lq_type)) */
+			iwl4965_rs_move_mimo2_to_other(priv, lq_sta,
+							conf, sta, index);
+
+		/* If new "search" mode was selected, set up in uCode table */
+		if (lq_sta->search_better_tbl) {
+			/* Access the "search" table, clear its history. */
+			tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+			for (i = 0; i < IWL_RATE_COUNT; i++)
+				iwl4965_rs_rate_scale_clear_window(
+							&(tbl->win[i]));
+
+			/* Use new "search" start rate */
+			index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
+
+			IWL_DEBUG_RATE(priv,
+				"Switch current  mcs: %X index: %d\n",
+				     tbl->current_rate, index);
+			iwl4965_rs_fill_link_cmd(priv, lq_sta,
+						tbl->current_rate);
+			iwl_legacy_send_lq_cmd(priv, ctx,
+						&lq_sta->lq, CMD_ASYNC, false);
+		} else
+			done_search = 1;
+	}
+
+	if (done_search && !lq_sta->stay_in_tbl) {
+		/* If the "active" (non-search) mode was legacy,
+		 * and we've tried switching antennas,
+		 * but we haven't been able to try HT modes (not available),
+		 * stay with best antenna legacy modulation for a while
+		 * before next round of mode comparisons. */
+		tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
+		if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) &&
+		    lq_sta->action_counter > tbl1->max_search) {
+			IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n");
+			iwl4965_rs_set_stay_in_table(priv, 1, lq_sta);
+		}
+
+		/* If we're in an HT mode, and all 3 mode switch actions
+		 * have been tried and compared, stay in this best modulation
+		 * mode for a while before next round of mode comparisons. */
+		if (lq_sta->enable_counter &&
+		    (lq_sta->action_counter >= tbl1->max_search)) {
+			if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
+			    (lq_sta->tx_agg_tid_en & (1 << tid)) &&
+			    (tid != MAX_TID_COUNT)) {
+				tid_data =
+				   &priv->stations[lq_sta->lq.sta_id].tid[tid];
+				if (tid_data->agg.state == IWL_AGG_OFF) {
+					IWL_DEBUG_RATE(priv,
+						       "try to aggregate tid %d\n",
+						       tid);
+					iwl4965_rs_tl_turn_on_agg(priv, tid,
+							  lq_sta, sta);
+				}
+			}
+			iwl4965_rs_set_stay_in_table(priv, 0, lq_sta);
+		}
+	}
+
+out:
+	tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv, tbl,
+							index, is_green);
+	i = index;
+	lq_sta->last_txrate_idx = i;
+}
+
+/**
+ * iwl4965_rs_initialize_lq - Initialize a station's hardware rate table
+ *
+ * The uCode's station table contains a table of fallback rates
+ * for automatic fallback during transmission.
+ *
+ * NOTE: This sets up a default set of values.  These will be replaced later
+ *       if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
+ *       rc80211_simple.
+ *
+ * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
+ *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
+ *       which requires station table entry to exist).
+ */
+static void iwl4965_rs_initialize_lq(struct iwl_priv *priv,
+			     struct ieee80211_conf *conf,
+			     struct ieee80211_sta *sta,
+			     struct iwl_lq_sta *lq_sta)
+{
+	struct iwl_scale_tbl_info *tbl;
+	int rate_idx;
+	int i;
+	u32 rate;
+	u8 use_green = iwl4965_rs_use_green(sta);
+	u8 active_tbl = 0;
+	u8 valid_tx_ant;
+	struct iwl_station_priv *sta_priv;
+	struct iwl_rxon_context *ctx;
+
+	if (!sta || !lq_sta)
+		return;
+
+	sta_priv = (void *)sta->drv_priv;
+	ctx = sta_priv->common.ctx;
+
+	i = lq_sta->last_txrate_idx;
+
+	valid_tx_ant = priv->hw_params.valid_tx_ant;
+
+	if (!lq_sta->search_better_tbl)
+		active_tbl = lq_sta->active_tbl;
+	else
+		active_tbl = 1 - lq_sta->active_tbl;
+
+	tbl = &(lq_sta->lq_info[active_tbl]);
+
+	if ((i < 0) || (i >= IWL_RATE_COUNT))
+		i = 0;
+
+	rate = iwlegacy_rates[i].plcp;
+	tbl->ant_type = iwl4965_first_antenna(valid_tx_ant);
+	rate |= tbl->ant_type << RATE_MCS_ANT_POS;
+
+	if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE)
+		rate |= RATE_MCS_CCK_MSK;
+
+	iwl4965_rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
+	if (!iwl4965_rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
+		iwl4965_rs_toggle_antenna(valid_tx_ant, &rate, tbl);
+
+	rate = iwl4965_rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green);
+	tbl->current_rate = rate;
+	iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
+	iwl4965_rs_fill_link_cmd(NULL, lq_sta, rate);
+	priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
+	iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
+}
+
+static void
+iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
+			struct ieee80211_tx_rate_control *txrc)
+{
+
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_supported_band *sband = txrc->sband;
+	struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	int rate_idx;
+
+	IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n");
+
+	/* Get max rate if user set max rate */
+	if (lq_sta) {
+		lq_sta->max_rate_idx = txrc->max_rate_idx;
+		if ((sband->band == IEEE80211_BAND_5GHZ) &&
+		    (lq_sta->max_rate_idx != -1))
+			lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
+		if ((lq_sta->max_rate_idx < 0) ||
+		    (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
+			lq_sta->max_rate_idx = -1;
+	}
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (lq_sta && !lq_sta->drv) {
+		IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
+		priv_sta = NULL;
+	}
+
+	/* Send management frames and NO_ACK data using lowest rate. */
+	if (rate_control_send_low(sta, priv_sta, txrc))
+		return;
+
+	rate_idx  = lq_sta->last_txrate_idx;
+
+	if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
+		rate_idx -= IWL_FIRST_OFDM_RATE;
+		/* 6M and 9M shared same MCS index */
+		rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
+		if (iwl4965_rs_extract_rate(lq_sta->last_rate_n_flags) >=
+			 IWL_RATE_MIMO2_6M_PLCP)
+			rate_idx = rate_idx + MCS_INDEX_PER_STREAM;
+		info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
+			info->control.rates[0].flags |=
+					IEEE80211_TX_RC_SHORT_GI;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
+			info->control.rates[0].flags |=
+					IEEE80211_TX_RC_DUP_DATA;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK)
+			info->control.rates[0].flags |=
+					IEEE80211_TX_RC_40_MHZ_WIDTH;
+		if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
+			info->control.rates[0].flags |=
+					IEEE80211_TX_RC_GREEN_FIELD;
+	} else {
+		/* Check for invalid rates */
+		if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) ||
+				((sband->band == IEEE80211_BAND_5GHZ) &&
+				 (rate_idx < IWL_FIRST_OFDM_RATE)))
+			rate_idx = rate_lowest_index(sband, sta);
+		/* On valid 5 GHz rate, adjust index */
+		else if (sband->band == IEEE80211_BAND_5GHZ)
+			rate_idx -= IWL_FIRST_OFDM_RATE;
+		info->control.rates[0].flags = 0;
+	}
+	info->control.rates[0].idx = rate_idx;
+
+}
+
+static void *iwl4965_rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
+			  gfp_t gfp)
+{
+	struct iwl_lq_sta *lq_sta;
+	struct iwl_station_priv *sta_priv =
+				(struct iwl_station_priv *) sta->drv_priv;
+	struct iwl_priv *priv;
+
+	priv = (struct iwl_priv *)priv_rate;
+	IWL_DEBUG_RATE(priv, "create station rate scale window\n");
+
+	lq_sta = &sta_priv->lq_sta;
+
+	return lq_sta;
+}
+
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void
+iwl4965_rs_rate_init(struct iwl_priv *priv,
+			struct ieee80211_sta *sta,
+			u8 sta_id)
+{
+	int i, j;
+	struct ieee80211_hw *hw = priv->hw;
+	struct ieee80211_conf *conf = &priv->hw->conf;
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+	struct iwl_station_priv *sta_priv;
+	struct iwl_lq_sta *lq_sta;
+	struct ieee80211_supported_band *sband;
+
+	sta_priv = (struct iwl_station_priv *) sta->drv_priv;
+	lq_sta = &sta_priv->lq_sta;
+	sband = hw->wiphy->bands[conf->channel->band];
+
+
+	lq_sta->lq.sta_id = sta_id;
+
+	for (j = 0; j < LQ_SIZE; j++)
+		for (i = 0; i < IWL_RATE_COUNT; i++)
+			iwl4965_rs_rate_scale_clear_window(
+					&lq_sta->lq_info[j].win[i]);
+
+	lq_sta->flush_timer = 0;
+	lq_sta->supp_rates = sta->supp_rates[sband->band];
+	for (j = 0; j < LQ_SIZE; j++)
+		for (i = 0; i < IWL_RATE_COUNT; i++)
+			iwl4965_rs_rate_scale_clear_window(
+					&lq_sta->lq_info[j].win[i]);
+
+	IWL_DEBUG_RATE(priv, "LQ:"
+			"*** rate scale station global init for station %d ***\n",
+		       sta_id);
+	/* TODO: what is a good starting rate for STA? About middle? Maybe not
+	 * the lowest or the highest rate.. Could consider using RSSI from
+	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
+	 * after assoc.. */
+
+	lq_sta->is_dup = 0;
+	lq_sta->max_rate_idx = -1;
+	lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
+	lq_sta->is_green = iwl4965_rs_use_green(sta);
+	lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
+	lq_sta->band = priv->band;
+	/*
+	 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
+	 * supp_rates[] does not; shift to convert format, force 9 MBits off.
+	 */
+	lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
+	lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
+	lq_sta->active_siso_rate &= ~((u16)0x2);
+	lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
+
+	/* Same here */
+	lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
+	lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
+	lq_sta->active_mimo2_rate &= ~((u16)0x2);
+	lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
+
+	/* These values will be overridden later */
+	lq_sta->lq.general_params.single_stream_ant_msk =
+		iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+	lq_sta->lq.general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+	if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
+		lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
+	} else if (iwl4965_num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+		lq_sta->lq.general_params.dual_stream_ant_msk =
+			priv->hw_params.valid_tx_ant;
+	}
+
+	/* as default allow aggregation for all tids */
+	lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
+	lq_sta->drv = priv;
+
+	/* Set last_txrate_idx to lowest rate */
+	lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
+	if (sband->band == IEEE80211_BAND_5GHZ)
+		lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+	lq_sta->is_agg = 0;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	lq_sta->dbg_fixed_rate = 0;
+#endif
+
+	iwl4965_rs_initialize_lq(priv, conf, sta, lq_sta);
+}
+
+static void iwl4965_rs_fill_link_cmd(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta, u32 new_rate)
+{
+	struct iwl_scale_tbl_info tbl_type;
+	int index = 0;
+	int rate_idx;
+	int repeat_rate = 0;
+	u8 ant_toggle_cnt = 0;
+	u8 use_ht_possible = 1;
+	u8 valid_tx_ant = 0;
+	struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
+
+	/* Override starting rate (index 0) if needed for debug purposes */
+	iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+	/* Interpret new_rate (rate_n_flags) */
+	iwl4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
+				  &tbl_type, &rate_idx);
+
+	/* How many times should we repeat the initial rate? */
+	if (is_legacy(tbl_type.lq_type)) {
+		ant_toggle_cnt = 1;
+		repeat_rate = IWL_NUMBER_TRY;
+	} else {
+		repeat_rate = IWL_HT_NUMBER_TRY;
+	}
+
+	lq_cmd->general_params.mimo_delimiter =
+			is_mimo(tbl_type.lq_type) ? 1 : 0;
+
+	/* Fill 1st table entry (index 0) */
+	lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
+
+	if (iwl4965_num_of_ant(tbl_type.ant_type) == 1) {
+		lq_cmd->general_params.single_stream_ant_msk =
+						tbl_type.ant_type;
+	} else if (iwl4965_num_of_ant(tbl_type.ant_type) == 2) {
+		lq_cmd->general_params.dual_stream_ant_msk =
+						tbl_type.ant_type;
+	} /* otherwise we don't modify the existing value */
+
+	index++;
+	repeat_rate--;
+	if (priv)
+		valid_tx_ant = priv->hw_params.valid_tx_ant;
+
+	/* Fill rest of rate table */
+	while (index < LINK_QUAL_MAX_RETRY_NUM) {
+		/* Repeat initial/next rate.
+		 * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
+		 * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
+		while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
+			if (is_legacy(tbl_type.lq_type)) {
+				if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+					ant_toggle_cnt++;
+				else if (priv &&
+					 iwl4965_rs_toggle_antenna(valid_tx_ant,
+							&new_rate, &tbl_type))
+					ant_toggle_cnt = 1;
+			}
+
+			/* Override next rate if needed for debug purposes */
+			iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+			/* Fill next table entry */
+			lq_cmd->rs_table[index].rate_n_flags =
+					cpu_to_le32(new_rate);
+			repeat_rate--;
+			index++;
+		}
+
+		iwl4965_rs_get_tbl_info_from_mcs(new_rate,
+						lq_sta->band, &tbl_type,
+						&rate_idx);
+
+		/* Indicate to uCode which entries might be MIMO.
+		 * If initial rate was MIMO, this will finally end up
+		 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
+		if (is_mimo(tbl_type.lq_type))
+			lq_cmd->general_params.mimo_delimiter = index;
+
+		/* Get next rate */
+		new_rate = iwl4965_rs_get_lower_rate(lq_sta,
+					&tbl_type, rate_idx,
+					     use_ht_possible);
+
+		/* How many times should we repeat the next rate? */
+		if (is_legacy(tbl_type.lq_type)) {
+			if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+				ant_toggle_cnt++;
+			else if (priv &&
+				 iwl4965_rs_toggle_antenna(valid_tx_ant,
+						   &new_rate, &tbl_type))
+				ant_toggle_cnt = 1;
+
+			repeat_rate = IWL_NUMBER_TRY;
+		} else {
+			repeat_rate = IWL_HT_NUMBER_TRY;
+		}
+
+		/* Don't allow HT rates after next pass.
+		 * iwl4965_rs_get_lower_rate() will change type to LQ_A or LQ_G. */
+		use_ht_possible = 0;
+
+		/* Override next rate if needed for debug purposes */
+		iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+		/* Fill next table entry */
+		lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
+
+		index++;
+		repeat_rate--;
+	}
+
+	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+	lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+
+	lq_cmd->agg_params.agg_time_limit =
+		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+}
+
+static void
+*iwl4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+	return hw->priv;
+}
+/* rate scale requires free function to be implemented */
+static void iwl4965_rs_free(void *priv_rate)
+{
+	return;
+}
+
+static void iwl4965_rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
+			void *priv_sta)
+{
+	struct iwl_priv *priv __maybe_unused = priv_r;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+	IWL_DEBUG_RATE(priv, "leave\n");
+}
+
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int iwl4965_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
+			     u32 *rate_n_flags, int index)
+{
+	struct iwl_priv *priv;
+	u8 valid_tx_ant;
+	u8 ant_sel_tx;
+
+	priv = lq_sta->drv;
+	valid_tx_ant = priv->hw_params.valid_tx_ant;
+	if (lq_sta->dbg_fixed_rate) {
+		ant_sel_tx =
+		  ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
+		  >> RATE_MCS_ANT_POS);
+		if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) {
+			*rate_n_flags = lq_sta->dbg_fixed_rate;
+			IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
+		} else {
+			lq_sta->dbg_fixed_rate = 0;
+			IWL_ERR(priv,
+			    "Invalid antenna selection 0x%X, Valid is 0x%X\n",
+			    ant_sel_tx, valid_tx_ant);
+			IWL_DEBUG_RATE(priv, "Fixed rate OFF\n");
+		}
+	} else {
+		IWL_DEBUG_RATE(priv, "Fixed rate OFF\n");
+	}
+}
+
+static ssize_t iwl4965_rs_sta_dbgfs_scale_table_write(struct file *file,
+			const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	struct iwl_priv *priv;
+	char buf[64];
+	int buf_size;
+	u32 parsed_rate;
+	struct iwl_station_priv *sta_priv =
+		container_of(lq_sta, struct iwl_station_priv, lq_sta);
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	priv = lq_sta->drv;
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+
+	if (sscanf(buf, "%x", &parsed_rate) == 1)
+		lq_sta->dbg_fixed_rate = parsed_rate;
+	else
+		lq_sta->dbg_fixed_rate = 0;
+
+	lq_sta->active_legacy_rate = 0x0FFF;	/* 1 - 54 MBits, includes CCK */
+	lq_sta->active_siso_rate   = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
+	lq_sta->active_mimo2_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
+
+	IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
+		lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
+
+	if (lq_sta->dbg_fixed_rate) {
+		iwl4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
+		iwl_legacy_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
+				false);
+	}
+
+	return count;
+}
+
+static ssize_t iwl4965_rs_sta_dbgfs_scale_table_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char *buff;
+	int desc = 0;
+	int i = 0;
+	int index = 0;
+	ssize_t ret;
+
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	struct iwl_priv *priv;
+	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+
+	priv = lq_sta->drv;
+	buff = kmalloc(1024, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
+	desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
+			lq_sta->total_failed, lq_sta->total_success,
+			lq_sta->active_legacy_rate);
+	desc += sprintf(buff+desc, "fixed rate 0x%X\n",
+			lq_sta->dbg_fixed_rate);
+	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
+	    (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
+	    (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
+	    (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : "");
+	desc += sprintf(buff+desc, "lq type %s\n",
+	   (is_legacy(tbl->lq_type)) ? "legacy" : "HT");
+	if (is_Ht(tbl->lq_type)) {
+		desc += sprintf(buff+desc, " %s",
+		   (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
+		   desc += sprintf(buff+desc, " %s",
+		   (tbl->is_ht40) ? "40MHz" : "20MHz");
+		   desc += sprintf(buff+desc, " %s %s %s\n",
+			(tbl->is_SGI) ? "SGI" : "",
+		   (lq_sta->is_green) ? "GF enabled" : "",
+		   (lq_sta->is_agg) ? "AGG on" : "");
+	}
+	desc += sprintf(buff+desc, "last tx rate=0x%X\n",
+		lq_sta->last_rate_n_flags);
+	desc += sprintf(buff+desc, "general:"
+		"flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
+		lq_sta->lq.general_params.flags,
+		lq_sta->lq.general_params.mimo_delimiter,
+		lq_sta->lq.general_params.single_stream_ant_msk,
+		lq_sta->lq.general_params.dual_stream_ant_msk);
+
+	desc += sprintf(buff+desc, "agg:"
+			"time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n",
+			le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit),
+			lq_sta->lq.agg_params.agg_dis_start_th,
+			lq_sta->lq.agg_params.agg_frame_cnt_limit);
+
+	desc += sprintf(buff+desc,
+			"Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n",
+			lq_sta->lq.general_params.start_rate_index[0],
+			lq_sta->lq.general_params.start_rate_index[1],
+			lq_sta->lq.general_params.start_rate_index[2],
+			lq_sta->lq.general_params.start_rate_index[3]);
+
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+		index = iwl4965_hwrate_to_plcp_idx(
+			le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+		if (is_legacy(tbl->lq_type)) {
+			desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
+			i,
+			le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
+			iwl_rate_mcs[index].mbps);
+		} else {
+			desc += sprintf(buff+desc,
+			" rate[%d] 0x%X %smbps (%s)\n",
+			i,
+			le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
+			iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs);
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	kfree(buff);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
+	.write = iwl4965_rs_sta_dbgfs_scale_table_write,
+	.read = iwl4965_rs_sta_dbgfs_scale_table_read,
+	.open = iwl4965_open_file_generic,
+	.llseek = default_llseek,
+};
+static ssize_t iwl4965_rs_sta_dbgfs_stats_table_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char *buff;
+	int desc = 0;
+	int i, j;
+	ssize_t ret;
+
+	struct iwl_lq_sta *lq_sta = file->private_data;
+
+	buff = kmalloc(1024, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	for (i = 0; i < LQ_SIZE; i++) {
+		desc += sprintf(buff+desc,
+				"%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n"
+				"rate=0x%X\n",
+				lq_sta->active_tbl == i ? "*" : "x",
+				lq_sta->lq_info[i].lq_type,
+				lq_sta->lq_info[i].is_SGI,
+				lq_sta->lq_info[i].is_ht40,
+				lq_sta->lq_info[i].is_dup,
+				lq_sta->is_green,
+				lq_sta->lq_info[i].current_rate);
+		for (j = 0; j < IWL_RATE_COUNT; j++) {
+			desc += sprintf(buff+desc,
+				"counter=%d success=%d %%=%d\n",
+				lq_sta->lq_info[i].win[j].counter,
+				lq_sta->lq_info[i].win[j].success_counter,
+				lq_sta->lq_info[i].win[j].success_ratio);
+		}
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	kfree(buff);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+	.read = iwl4965_rs_sta_dbgfs_stats_table_read,
+	.open = iwl4965_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static ssize_t iwl4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char buff[120];
+	int desc = 0;
+	ssize_t ret;
+
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	struct iwl_priv *priv;
+	struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl];
+
+	priv = lq_sta->drv;
+
+	if (is_Ht(tbl->lq_type))
+		desc += sprintf(buff+desc,
+				"Bit Rate= %d Mb/s\n",
+				tbl->expected_tpt[lq_sta->last_txrate_idx]);
+	else
+		desc += sprintf(buff+desc,
+				"Bit Rate= %d Mb/s\n",
+				iwlegacy_rates[lq_sta->last_txrate_idx].ieee >> 1);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
+	.read = iwl4965_rs_sta_dbgfs_rate_scale_data_read,
+	.open = iwl4965_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static void iwl4965_rs_add_debugfs(void *priv, void *priv_sta,
+					struct dentry *dir)
+{
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	lq_sta->rs_sta_dbgfs_scale_table_file =
+		debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
+				lq_sta, &rs_sta_dbgfs_scale_table_ops);
+	lq_sta->rs_sta_dbgfs_stats_table_file =
+		debugfs_create_file("rate_stats_table", S_IRUSR, dir,
+			lq_sta, &rs_sta_dbgfs_stats_table_ops);
+	lq_sta->rs_sta_dbgfs_rate_scale_data_file =
+		debugfs_create_file("rate_scale_data", S_IRUSR, dir,
+			lq_sta, &rs_sta_dbgfs_rate_scale_data_ops);
+	lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file =
+		debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir,
+		&lq_sta->tx_agg_tid_en);
+
+}
+
+static void iwl4965_rs_remove_debugfs(void *priv, void *priv_sta)
+{
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
+	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+	debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file);
+	debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file);
+}
+#endif
+
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void
+iwl4965_rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
+			 struct ieee80211_sta *sta, void *priv_sta)
+{
+}
+static struct rate_control_ops rs_4965_ops = {
+	.module = NULL,
+	.name = IWL4965_RS_NAME,
+	.tx_status = iwl4965_rs_tx_status,
+	.get_rate = iwl4965_rs_get_rate,
+	.rate_init = iwl4965_rs_rate_init_stub,
+	.alloc = iwl4965_rs_alloc,
+	.free = iwl4965_rs_free,
+	.alloc_sta = iwl4965_rs_alloc_sta,
+	.free_sta = iwl4965_rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+	.add_sta_debugfs = iwl4965_rs_add_debugfs,
+	.remove_sta_debugfs = iwl4965_rs_remove_debugfs,
+#endif
+};
+
+int iwl4965_rate_control_register(void)
+{
+	pr_err("Registering 4965 rate control operations\n");
+	return ieee80211_rate_control_register(&rs_4965_ops);
+}
+
+void iwl4965_rate_control_unregister(void)
+{
+	ieee80211_rate_control_unregister(&rs_4965_ops);
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rx.c b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
new file mode 100644
index 0000000..b9fa2f6
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-4965-calib.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+
+void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_missed_beacon_notif *missed_beacon;
+
+	missed_beacon = &pkt->u.missed_beacon;
+	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+	    priv->missed_beacon_threshold) {
+		IWL_DEBUG_CALIB(priv,
+		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+		    le32_to_cpu(missed_beacon->total_missed_becons),
+		    le32_to_cpu(missed_beacon->num_recvd_beacons),
+		    le32_to_cpu(missed_beacon->num_expected_beacons));
+		if (!test_bit(STATUS_SCANNING, &priv->status))
+			iwl4965_init_sensitivity(priv);
+	}
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
+{
+	struct statistics_rx_non_phy *rx_info;
+	int num_active_rx = 0;
+	int total_silence = 0;
+	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
+	int last_rx_noise;
+
+	rx_info = &(priv->_4965.statistics.rx.general);
+	bcn_silence_a =
+		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+	bcn_silence_b =
+		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+	bcn_silence_c =
+		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+
+	if (bcn_silence_a) {
+		total_silence += bcn_silence_a;
+		num_active_rx++;
+	}
+	if (bcn_silence_b) {
+		total_silence += bcn_silence_b;
+		num_active_rx++;
+	}
+	if (bcn_silence_c) {
+		total_silence += bcn_silence_c;
+		num_active_rx++;
+	}
+
+	/* Average among active antennas */
+	if (num_active_rx)
+		last_rx_noise = (total_silence / num_active_rx) - 107;
+	else
+		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
+			bcn_silence_a, bcn_silence_b, bcn_silence_c,
+			last_rx_noise);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+/*
+ *  based on the assumption of all statistics counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
+					__le32 *stats)
+{
+	int i, size;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+	struct statistics_general_common *general, *accum_general;
+	struct statistics_tx *tx, *accum_tx;
+
+	prev_stats = (__le32 *)&priv->_4965.statistics;
+	accum_stats = (u32 *)&priv->_4965.accum_statistics;
+	size = sizeof(struct iwl_notif_statistics);
+	general = &priv->_4965.statistics.general.common;
+	accum_general = &priv->_4965.accum_statistics.general.common;
+	tx = &priv->_4965.statistics.tx;
+	accum_tx = &priv->_4965.accum_statistics.tx;
+	delta = (u32 *)&priv->_4965.delta_statistics;
+	max_delta = (u32 *)&priv->_4965.max_delta;
+
+	for (i = sizeof(__le32); i < size;
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
+		}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	accum_general->temperature = general->temperature;
+	accum_general->ttl_timestamp = general->ttl_timestamp;
+}
+#endif
+
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * iwl4965_good_plcp_health - checks for plcp error.
+ *
+ * When the plcp error is exceeding the thresholds, reset the radio
+ * to improve the throughput.
+ */
+bool iwl4965_good_plcp_health(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt)
+{
+	bool rc = true;
+	int combined_plcp_delta;
+	unsigned int plcp_msec;
+	unsigned long plcp_received_jiffies;
+
+	if (priv->cfg->base_params->plcp_delta_threshold ==
+	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
+		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
+		return rc;
+	}
+
+	/*
+	 * check for plcp_err and trigger radio reset if it exceeds
+	 * the plcp error threshold plcp_delta.
+	 */
+	plcp_received_jiffies = jiffies;
+	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
+					(long) priv->plcp_jiffies);
+	priv->plcp_jiffies = plcp_received_jiffies;
+	/*
+	 * check to make sure plcp_msec is not 0 to prevent division
+	 * by zero.
+	 */
+	if (plcp_msec) {
+		struct statistics_rx_phy *ofdm;
+		struct statistics_rx_ht_phy *ofdm_ht;
+
+		ofdm = &pkt->u.stats.rx.ofdm;
+		ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
+		combined_plcp_delta =
+		    (le32_to_cpu(ofdm->plcp_err) -
+		    le32_to_cpu(priv->_4965.statistics.
+				rx.ofdm.plcp_err)) +
+		    (le32_to_cpu(ofdm_ht->plcp_err) -
+		    le32_to_cpu(priv->_4965.statistics.
+				rx.ofdm_ht.plcp_err));
+
+		if ((combined_plcp_delta > 0) &&
+		    ((combined_plcp_delta * 100) / plcp_msec) >
+			priv->cfg->base_params->plcp_delta_threshold) {
+			/*
+			 * if plcp_err exceed the threshold,
+			 * the following data is printed in csv format:
+			 *    Text: plcp_err exceeded %d,
+			 *    Received ofdm.plcp_err,
+			 *    Current ofdm.plcp_err,
+			 *    Received ofdm_ht.plcp_err,
+			 *    Current ofdm_ht.plcp_err,
+			 *    combined_plcp_delta,
+			 *    plcp_msec
+			 */
+			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
+				"%u, %u, %u, %u, %d, %u mSecs\n",
+				priv->cfg->base_params->plcp_delta_threshold,
+				le32_to_cpu(ofdm->plcp_err),
+				le32_to_cpu(ofdm->plcp_err),
+				le32_to_cpu(ofdm_ht->plcp_err),
+				le32_to_cpu(ofdm_ht->plcp_err),
+				combined_plcp_delta, plcp_msec);
+
+			rc = false;
+		}
+	}
+	return rc;
+}
+
+void iwl4965_rx_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	int change;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	IWL_DEBUG_RX(priv,
+		     "Statistics notification received (%d vs %d).\n",
+		     (int)sizeof(struct iwl_notif_statistics),
+		     le32_to_cpu(pkt->len_n_flags) &
+		     FH_RSCSR_FRAME_SIZE_MSK);
+
+	change = ((priv->_4965.statistics.general.common.temperature !=
+		   pkt->u.stats.general.common.temperature) ||
+		   ((priv->_4965.statistics.flag &
+		   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+		   (pkt->u.stats.flag &
+		   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+#endif
+
+	iwl_legacy_recover_from_statistics(priv, pkt);
+
+	memcpy(&priv->_4965.statistics, &pkt->u.stats,
+		sizeof(priv->_4965.statistics));
+
+	set_bit(STATUS_STATISTICS, &priv->status);
+
+	/* Reschedule the statistics timer to occur in
+	 * REG_RECALIB_PERIOD seconds to ensure we get a
+	 * thermal update even if the uCode doesn't give
+	 * us one */
+	mod_timer(&priv->statistics_periodic, jiffies +
+		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
+
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+		iwl4965_rx_calc_noise(priv);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
+	}
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
+}
+
+void iwl4965_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+		memset(&priv->_4965.accum_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_4965.delta_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_4965.max_delta, 0,
+			sizeof(struct iwl_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl4965_rx_statistics(priv, rxb);
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-sta.c b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
new file mode 100644
index 0000000..a262c23
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
@@ -0,0 +1,721 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-4965.h"
+
+static struct iwl_link_quality_cmd *
+iwl4965_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
+{
+	int i, r;
+	struct iwl_link_quality_cmd *link_cmd;
+	u32 rate_flags = 0;
+	__le32 rate_n_flags;
+
+	link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
+	if (!link_cmd) {
+		IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
+		return NULL;
+	}
+	/* Set up the rate scaling to start at selected rate, fall back
+	 * all the way down to 1M in IEEE order, and then spin on 1M */
+	if (priv->band == IEEE80211_BAND_5GHZ)
+		r = IWL_RATE_6M_INDEX;
+	else
+		r = IWL_RATE_1M_INDEX;
+
+	if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
+		rate_flags |= RATE_MCS_CCK_MSK;
+
+	rate_flags |= iwl4965_first_antenna(priv->hw_params.valid_tx_ant) <<
+				RATE_MCS_ANT_POS;
+	rate_n_flags = iwl4965_hw_set_rate_n_flags(iwlegacy_rates[r].plcp,
+						   rate_flags);
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+		link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
+
+	link_cmd->general_params.single_stream_ant_msk =
+				iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+
+	link_cmd->general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+	if (!link_cmd->general_params.dual_stream_ant_msk) {
+		link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
+	} else if (iwl4965_num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+		link_cmd->general_params.dual_stream_ant_msk =
+			priv->hw_params.valid_tx_ant;
+	}
+
+	link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
+	link_cmd->agg_params.agg_time_limit =
+		cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
+
+	link_cmd->sta_id = sta_id;
+
+	return link_cmd;
+}
+
+/*
+ * iwl4965_add_bssid_station - Add the special IBSS BSSID station
+ *
+ * Function sleeps.
+ */
+int
+iwl4965_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			     const u8 *addr, u8 *sta_id_r)
+{
+	int ret;
+	u8 sta_id;
+	struct iwl_link_quality_cmd *link_cmd;
+	unsigned long flags;
+
+	if (sta_id_r)
+		*sta_id_r = IWL_INVALID_STATION;
+
+	ret = iwl_legacy_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM\n", addr);
+		return ret;
+	}
+
+	if (sta_id_r)
+		*sta_id_r = sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].used |= IWL_STA_LOCAL;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	/* Set up default rate scaling table in device's station table */
+	link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv,
+			"Unable to initialize rate scaling for station %pM.\n",
+			addr);
+		return -ENOMEM;
+	}
+
+	ret = iwl_legacy_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
+	if (ret)
+		IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+static int iwl4965_static_wepkey_cmd(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx,
+				      bool send_if_empty)
+{
+	int i, not_empty = 0;
+	u8 buff[sizeof(struct iwl_wep_cmd) +
+		sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
+	struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
+	size_t cmd_size  = sizeof(struct iwl_wep_cmd);
+	struct iwl_host_cmd cmd = {
+		.id = ctx->wep_key_cmd,
+		.data = wep_cmd,
+		.flags = CMD_SYNC,
+	};
+
+	might_sleep();
+
+	memset(wep_cmd, 0, cmd_size +
+			(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
+
+	for (i = 0; i < WEP_KEYS_MAX ; i++) {
+		wep_cmd->key[i].key_index = i;
+		if (ctx->wep_keys[i].key_size) {
+			wep_cmd->key[i].key_offset = i;
+			not_empty = 1;
+		} else {
+			wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
+		}
+
+		wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
+		memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
+				ctx->wep_keys[i].key_size);
+	}
+
+	wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
+	wep_cmd->num_keys = WEP_KEYS_MAX;
+
+	cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
+
+	cmd.len = cmd_size;
+
+	if (not_empty || send_if_empty)
+		return iwl_legacy_send_cmd(priv, &cmd);
+	else
+		return 0;
+}
+
+int iwl4965_restore_default_wep_keys(struct iwl_priv *priv,
+				 struct iwl_rxon_context *ctx)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	return iwl4965_static_wepkey_cmd(priv, ctx, false);
+}
+
+int iwl4965_remove_default_wep_key(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx,
+			       struct ieee80211_key_conf *keyconf)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
+		      keyconf->keyidx);
+
+	memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_WEP(priv,
+		"Not sending REPLY_WEPKEY command due to RFKILL.\n");
+		/* but keys in device are clear anyway so return success */
+		return 0;
+	}
+	ret = iwl4965_static_wepkey_cmd(priv, ctx, 1);
+	IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
+		      keyconf->keyidx, ret);
+
+	return ret;
+}
+
+int iwl4965_set_default_wep_key(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_key_conf *keyconf)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (keyconf->keylen != WEP_KEY_LEN_128 &&
+	    keyconf->keylen != WEP_KEY_LEN_64) {
+		IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
+		return -EINVAL;
+	}
+
+	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+	keyconf->hw_key_idx = HW_KEY_DEFAULT;
+	priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
+
+	ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
+	memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
+							keyconf->keylen);
+
+	ret = iwl4965_static_wepkey_cmd(priv, ctx, false);
+	IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
+		keyconf->keylen, keyconf->keyidx, ret);
+
+	return ret;
+}
+
+static int iwl4965_set_wep_dynamic_key_info(struct iwl_priv *priv,
+					struct iwl_rxon_context *ctx,
+					struct ieee80211_key_conf *keyconf,
+					u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+
+	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (keyconf->keylen == WEP_KEY_LEN_128)
+		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+	priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
+
+	memcpy(priv->stations[sta_id].keyinfo.key,
+				keyconf->key, keyconf->keylen);
+
+	memcpy(&priv->stations[sta_id].sta.key.key[3],
+				keyconf->key, keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+			sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+					 struct iwl_rxon_context *ctx,
+					 struct ieee80211_key_conf *keyconf,
+					 u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+	       keyconf->keylen);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+	       keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+			 sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+					 struct iwl_rxon_context *ctx,
+					 struct ieee80211_key_conf *keyconf,
+					 u8 sta_id)
+{
+	unsigned long flags;
+	int ret = 0;
+	__le16 key_flags = 0;
+
+	key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = 16;
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+
+
+	/* This copy is acutally not needed: we get the key with each TX */
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
+}
+
+void iwl4965_update_tkip_key(struct iwl_priv *priv,
+			 struct iwl_rxon_context *ctx,
+			 struct ieee80211_key_conf *keyconf,
+			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
+{
+	u8 sta_id;
+	unsigned long flags;
+	int i;
+
+	if (iwl_legacy_scan_cancel(priv)) {
+		/* cancel scan failed, just live w/ bad key and rely
+		   briefly on SW decryption */
+		return;
+	}
+
+	sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
+
+	for (i = 0; i < 5; i++)
+		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
+			cpu_to_le16(phase1key[i]);
+
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	iwl_legacy_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+
+int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx,
+			   struct ieee80211_key_conf *keyconf,
+			   u8 sta_id)
+{
+	unsigned long flags;
+	u16 key_flags;
+	u8 keyidx;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	ctx->key_mapping_keys--;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
+	keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
+
+	IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
+		      keyconf->keyidx, sta_id);
+
+	if (keyconf->keyidx != keyidx) {
+		/* We need to remove a key with index different that the one
+		 * in the uCode. This means that the key we need to remove has
+		 * been replaced by another one with different index.
+		 * Don't do anything and return ok
+		 */
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+
+	if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+		IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
+			    keyconf->keyidx, key_flags);
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+
+	if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
+		&priv->ucode_key_table))
+		IWL_ERR(priv, "index %d not used in uCode key table.\n",
+			priv->stations[sta_id].sta.key.key_offset);
+	memset(&priv->stations[sta_id].keyinfo, 0,
+					sizeof(struct iwl_hw_key));
+	memset(&priv->stations[sta_id].sta.key, 0,
+					sizeof(struct iwl4965_keyinfo));
+	priv->stations[sta_id].sta.key.key_flags =
+			STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
+	priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_WEP(priv,
+		 "Not sending REPLY_ADD_STA command because RFKILL enabled.\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+			sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl4965_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	ctx->key_mapping_keys++;
+	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		ret = iwl4965_set_ccmp_dynamic_key_info(priv, ctx,
+							keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		ret = iwl4965_set_tkip_dynamic_key_info(priv, ctx,
+							keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		ret = iwl4965_set_wep_dynamic_key_info(priv, ctx,
+							keyconf, sta_id);
+		break;
+	default:
+		IWL_ERR(priv,
+			"Unknown alg: %s cipher = %x\n", __func__,
+			keyconf->cipher);
+		ret = -EINVAL;
+	}
+
+	IWL_DEBUG_WEP(priv,
+		"Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
+		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
+		      sta_id, ret);
+
+	return ret;
+}
+
+/**
+ * iwl4965_alloc_bcast_station - add broadcast station into driver's station table.
+ *
+ * This adds the broadcast station into the driver's station table
+ * and marks it driver active, so that it will be restored to the
+ * device at the next best time.
+ */
+int iwl4965_alloc_bcast_station(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx)
+{
+	struct iwl_link_quality_cmd *link_cmd;
+	unsigned long flags;
+	u8 sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	sta_id = iwl_legacy_prep_station(priv, ctx, iwlegacy_bcast_addr,
+								false, NULL);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Unable to prepare broadcast station\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+		return -EINVAL;
+	}
+
+	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+	priv->stations[sta_id].used |= IWL_STA_BCAST;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv,
+			"Unable to initialize rate scaling for bcast station.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+/**
+ * iwl4965_update_bcast_station - update broadcast station's LQ command
+ *
+ * Only used by iwl4965. Placed here to have all bcast station management
+ * code together.
+ */
+static int iwl4965_update_bcast_station(struct iwl_priv *priv,
+				    struct iwl_rxon_context *ctx)
+{
+	unsigned long flags;
+	struct iwl_link_quality_cmd *link_cmd;
+	u8 sta_id = ctx->bcast_sta_id;
+
+	link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv,
+		"Unable to initialize rate scaling for bcast station.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	if (priv->stations[sta_id].lq)
+		kfree(priv->stations[sta_id].lq);
+	else
+		IWL_DEBUG_INFO(priv,
+		"Bcast station rate scaling has not been initialized yet.\n");
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+int iwl4965_update_bcast_stations(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+	int ret = 0;
+
+	for_each_context(priv, ctx) {
+		ret = iwl4965_update_bcast_station(priv, ctx);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * iwl4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
+ */
+int iwl4965_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
+{
+	unsigned long flags;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/* Remove "disable" flag, to enable Tx for this TID */
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
+	priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+					sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl4965_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			 int tid, u16 ssn)
+{
+	unsigned long flags;
+	int sta_id;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	sta_id = iwl_legacy_sta_id(sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return -ENXIO;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.station_flags_msk = 0;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
+	priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
+	priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+					sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl4965_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			int tid)
+{
+	unsigned long flags;
+	int sta_id;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	sta_id = iwl_legacy_sta_id(sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
+		return -ENXIO;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.station_flags_msk = 0;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
+	priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+				sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+void
+iwl4965_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
+	priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+	priv->stations[sta_id].sta.sta.modify_mask =
+					STA_MODIFY_SLEEP_TX_COUNT_MSK;
+	priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	iwl_legacy_send_add_sta(priv,
+				&priv->stations[sta_id].sta, CMD_ASYNC);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-tx.c b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
new file mode 100644
index 0000000..5c40502
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
@@ -0,0 +1,1369 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ *	VO	0
+ *	VI	1
+ *	BE	2
+ *	BK	3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific modules like
+ * iwl-4965.c), the AC->hw queue mapping is the identity
+ * mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+	IEEE80211_AC_BE,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BE,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VO,
+	IEEE80211_AC_VO
+};
+
+static inline int iwl4965_get_ac_from_tid(u16 tid)
+{
+	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+		return tid_to_ac[tid];
+
+	/* no support for TIDs 8-15 yet */
+	return -EINVAL;
+}
+
+static inline int
+iwl4965_get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
+{
+	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+		return ctx->ac_to_fifo[tid_to_ac[tid]];
+
+	/* no support for TIDs 8-15 yet */
+	return -EINVAL;
+}
+
+/*
+ * handle build REPLY_TX command notification.
+ */
+static void iwl4965_tx_cmd_build_basic(struct iwl_priv *priv,
+					struct sk_buff *skb,
+					struct iwl_tx_cmd *tx_cmd,
+					struct ieee80211_tx_info *info,
+					struct ieee80211_hdr *hdr,
+					u8 std_id)
+{
+	__le16 fc = hdr->frame_control;
+	__le32 tx_flags = tx_cmd->tx_flags;
+
+	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+		tx_flags |= TX_CMD_FLG_ACK_MSK;
+		if (ieee80211_is_mgmt(fc))
+			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+		if (ieee80211_is_probe_resp(fc) &&
+		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
+			tx_flags |= TX_CMD_FLG_TSF_MSK;
+	} else {
+		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	if (ieee80211_is_back_req(fc))
+		tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+
+	tx_cmd->sta_id = std_id;
+	if (ieee80211_has_morefrags(fc))
+		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tx_cmd->tid_tspec = qc[0] & 0xf;
+		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+	} else {
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	iwl_legacy_tx_cmd_protection(priv, info, fc, &tx_flags);
+
+	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+	if (ieee80211_is_mgmt(fc)) {
+		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+		else
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+	} else {
+		tx_cmd->timeout.pm_frame_timeout = 0;
+	}
+
+	tx_cmd->driver_txop = 0;
+	tx_cmd->tx_flags = tx_flags;
+	tx_cmd->next_frame_len = 0;
+}
+
+#define RTS_DFAULT_RETRY_LIMIT		60
+
+static void iwl4965_tx_cmd_build_rate(struct iwl_priv *priv,
+			      struct iwl_tx_cmd *tx_cmd,
+			      struct ieee80211_tx_info *info,
+			      __le16 fc)
+{
+	u32 rate_flags;
+	int rate_idx;
+	u8 rts_retry_limit;
+	u8 data_retry_limit;
+	u8 rate_plcp;
+
+	/* Set retry limit on DATA packets and Probe Responses*/
+	if (ieee80211_is_probe_resp(fc))
+		data_retry_limit = 3;
+	else
+		data_retry_limit = IWL4965_DEFAULT_TX_RETRY;
+	tx_cmd->data_retry_limit = data_retry_limit;
+
+	/* Set retry limit on RTS packets */
+	rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
+	if (data_retry_limit < rts_retry_limit)
+		rts_retry_limit = data_retry_limit;
+	tx_cmd->rts_retry_limit = rts_retry_limit;
+
+	/* DATA packets will use the uCode station table for rate/antenna
+	 * selection */
+	if (ieee80211_is_data(fc)) {
+		tx_cmd->initial_rate_index = 0;
+		tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+		return;
+	}
+
+	/**
+	 * If the current TX rate stored in mac80211 has the MCS bit set, it's
+	 * not really a TX rate.  Thus, we use the lowest supported rate for
+	 * this band.  Also use the lowest supported rate if the stored rate
+	 * index is invalid.
+	 */
+	rate_idx = info->control.rates[0].idx;
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
+			(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
+		rate_idx = rate_lowest_index(&priv->bands[info->band],
+				info->control.sta);
+	/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
+	if (info->band == IEEE80211_BAND_5GHZ)
+		rate_idx += IWL_FIRST_OFDM_RATE;
+	/* Get PLCP rate for tx_cmd->rate_n_flags */
+	rate_plcp = iwlegacy_rates[rate_idx].plcp;
+	/* Zero out flags for this packet */
+	rate_flags = 0;
+
+	/* Set CCK flag as needed */
+	if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
+		rate_flags |= RATE_MCS_CCK_MSK;
+
+	/* Set up antennas */
+	priv->mgmt_tx_ant = iwl4965_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+				      priv->hw_params.valid_tx_ant);
+
+	rate_flags |= iwl4965_ant_idx_to_flags(priv->mgmt_tx_ant);
+
+	/* Set the rate in the TX cmd */
+	tx_cmd->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
+}
+
+static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
+				      struct ieee80211_tx_info *info,
+				      struct iwl_tx_cmd *tx_cmd,
+				      struct sk_buff *skb_frag,
+				      int sta_id)
+{
+	struct ieee80211_key_conf *keyconf = info->control.hw_key;
+
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+		memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
+		if (info->flags & IEEE80211_TX_CTL_AMPDU)
+			tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
+		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
+		break;
+
+	case WLAN_CIPHER_SUITE_TKIP:
+		tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+		ieee80211_get_tkip_key(keyconf, skb_frag,
+			IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+		IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
+		break;
+
+	case WLAN_CIPHER_SUITE_WEP104:
+		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+		/* fall through */
+	case WLAN_CIPHER_SUITE_WEP40:
+		tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
+			(keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+
+		memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
+
+		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
+			     "with key %d\n", keyconf->keyidx);
+		break;
+
+	default:
+		IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher);
+		break;
+	}
+}
+
+/*
+ * start REPLY_TX command process
+ */
+int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_sta *sta = info->control.sta;
+	struct iwl_station_priv *sta_priv = NULL;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	struct iwl_tx_cmd *tx_cmd;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	int txq_id;
+	dma_addr_t phys_addr;
+	dma_addr_t txcmd_phys;
+	dma_addr_t scratch_phys;
+	u16 len, firstlen, secondlen;
+	u16 seq_number = 0;
+	__le16 fc;
+	u8 hdr_len;
+	u8 sta_id;
+	u8 wait_write_ptr = 0;
+	u8 tid = 0;
+	u8 *qc = NULL;
+	unsigned long flags;
+	bool is_agg = false;
+
+	if (info->control.vif)
+		ctx = iwl_legacy_rxon_ctx_from_vif(info->control.vif);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
+		goto drop_unlock;
+	}
+
+	fc = hdr->frame_control;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (ieee80211_is_auth(fc))
+		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
+	else if (ieee80211_is_assoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
+	else if (ieee80211_is_reassoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
+#endif
+
+	hdr_len = ieee80211_hdrlen(fc);
+
+	/* Find index into station table for destination station */
+	sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+			       hdr->addr1);
+		goto drop_unlock;
+	}
+
+	IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
+
+	if (sta)
+		sta_priv = (void *)sta->drv_priv;
+
+	if (sta_priv && sta_priv->asleep &&
+	    (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+		/*
+		 * This sends an asynchronous command to the device,
+		 * but we can rely on it being processed before the
+		 * next frame is processed -- and the next frame to
+		 * this station is the one that will consume this
+		 * counter.
+		 * For now set the counter to just 1 since we do not
+		 * support uAPSD yet.
+		 */
+		iwl4965_sta_modify_sleep_tx_count(priv, sta_id, 1);
+	}
+
+	/*
+	 * Send this frame after DTIM -- there's a special queue
+	 * reserved for this for contexts that support AP mode.
+	 */
+	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+		txq_id = ctx->mcast_queue;
+		/*
+		 * The microcode will clear the more data
+		 * bit in the last frame it transmits.
+		 */
+		hdr->frame_control |=
+			cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+	} else
+		txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
+
+	/* irqs already disabled/saved above when locking priv->lock */
+	spin_lock(&priv->sta_lock);
+
+	if (ieee80211_is_data_qos(fc)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
+			spin_unlock(&priv->sta_lock);
+			goto drop_unlock;
+		}
+		seq_number = priv->stations[sta_id].tid[tid].seq_number;
+		seq_number &= IEEE80211_SCTL_SEQ;
+		hdr->seq_ctrl = hdr->seq_ctrl &
+				cpu_to_le16(IEEE80211_SCTL_FRAG);
+		hdr->seq_ctrl |= cpu_to_le16(seq_number);
+		seq_number += 0x10;
+		/* aggregation is on for this <sta,tid> */
+		if (info->flags & IEEE80211_TX_CTL_AMPDU &&
+		    priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
+			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+			is_agg = true;
+		}
+	}
+
+	txq = &priv->txq[txq_id];
+	q = &txq->q;
+
+	if (unlikely(iwl_legacy_queue_space(q) < q->high_mark)) {
+		spin_unlock(&priv->sta_lock);
+		goto drop_unlock;
+	}
+
+	if (ieee80211_is_data_qos(fc)) {
+		priv->stations[sta_id].tid[tid].tfds_in_queue++;
+		if (!ieee80211_has_morefrags(fc))
+			priv->stations[sta_id].tid[tid].seq_number = seq_number;
+	}
+
+	spin_unlock(&priv->sta_lock);
+
+	/* Set up driver data for this TFD */
+	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
+	txq->txb[q->write_ptr].skb = skb;
+	txq->txb[q->write_ptr].ctx = ctx;
+
+	/* Set up first empty entry in queue's array of Tx/cmd buffers */
+	out_cmd = txq->cmd[q->write_ptr];
+	out_meta = &txq->meta[q->write_ptr];
+	tx_cmd = &out_cmd->cmd.tx;
+	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+	memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
+
+	/*
+	 * Set up the Tx-command (not MAC!) header.
+	 * Store the chosen Tx queue and TFD index within the sequence field;
+	 * after Tx, uCode's Tx response will return this value so driver can
+	 * locate the frame within the tx queue and do post-tx processing.
+	 */
+	out_cmd->hdr.cmd = REPLY_TX;
+	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+				INDEX_TO_SEQ(q->write_ptr)));
+
+	/* Copy MAC header from skb into command buffer */
+	memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+
+	/* Total # bytes to be transmitted */
+	len = (u16)skb->len;
+	tx_cmd->len = cpu_to_le16(len);
+
+	if (info->control.hw_key)
+		iwl4965_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
+
+	/* TODO need this for burst mode later on */
+	iwl4965_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
+	iwl_legacy_dbg_log_tx_data_frame(priv, len, hdr);
+
+	iwl4965_tx_cmd_build_rate(priv, tx_cmd, info, fc);
+
+	iwl_legacy_update_stats(priv, true, fc, len);
+	/*
+	 * Use the first empty entry in this queue's command buffer array
+	 * to contain the Tx command and MAC header concatenated together
+	 * (payload data will be in another buffer).
+	 * Size of this varies, due to varying MAC header length.
+	 * If end is not dword aligned, we'll have 2 extra bytes at the end
+	 * of the MAC header (device reads on dword boundaries).
+	 * We'll tell device about this padding later.
+	 */
+	len = sizeof(struct iwl_tx_cmd) +
+		sizeof(struct iwl_cmd_header) + hdr_len;
+	firstlen = (len + 3) & ~3;
+
+	/* Tell NIC about any 2-byte padding after MAC header */
+	if (firstlen != len)
+		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+	/* Physical address of this Tx command's header (not MAC header!),
+	 * within command buffer array. */
+	txcmd_phys = pci_map_single(priv->pci_dev,
+				    &out_cmd->hdr, firstlen,
+				    PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+	dma_unmap_len_set(out_meta, len, firstlen);
+	/* Add buffer containing Tx command and MAC(!) header to TFD's
+	 * first entry */
+	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+						   txcmd_phys, firstlen, 1, 0);
+
+	if (!ieee80211_has_morefrags(hdr->frame_control)) {
+		txq->need_update = 1;
+	} else {
+		wait_write_ptr = 1;
+		txq->need_update = 0;
+	}
+
+	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+	 * if any (802.11 null frames have no payload). */
+	secondlen = skb->len - hdr_len;
+	if (secondlen > 0) {
+		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
+					   secondlen, PCI_DMA_TODEVICE);
+		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+							   phys_addr, secondlen,
+							   0, 0);
+	}
+
+	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+				offsetof(struct iwl_tx_cmd, scratch);
+
+	/* take back ownership of DMA buffer to enable update */
+	pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
+				    firstlen, PCI_DMA_BIDIRECTIONAL);
+	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+	tx_cmd->dram_msb_ptr = iwl_legacy_get_dma_hi_addr(scratch_phys);
+
+	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
+		     le16_to_cpu(out_cmd->hdr.sequence));
+	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
+
+	/* Set up entry for this TFD in Tx byte-count array */
+	if (info->flags & IEEE80211_TX_CTL_AMPDU)
+		priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq,
+						     le16_to_cpu(tx_cmd->len));
+
+	pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
+				       firstlen, PCI_DMA_BIDIRECTIONAL);
+
+	trace_iwlwifi_legacy_dev_tx(priv,
+			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
+			     sizeof(struct iwl_tfd),
+			     &out_cmd->hdr, firstlen,
+			     skb->data + hdr_len, secondlen);
+
+	/* Tell device the write index *just past* this latest filled TFD */
+	q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_legacy_txq_update_write_ptr(priv, txq);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/*
+	 * At this point the frame is "transmitted" successfully
+	 * and we will get a TX status notification eventually,
+	 * regardless of the value of ret. "ret" only indicates
+	 * whether or not we should update the write pointer.
+	 */
+
+	/*
+	 * Avoid atomic ops if it isn't an associated client.
+	 * Also, if this is a packet for aggregation, don't
+	 * increase the counter because the ucode will stop
+	 * aggregation queues when their respective station
+	 * goes to sleep.
+	 */
+	if (sta_priv && sta_priv->client && !is_agg)
+		atomic_inc(&sta_priv->pending_frames);
+
+	if ((iwl_legacy_queue_space(q) < q->high_mark) &&
+			priv->mac80211_registered) {
+		if (wait_write_ptr) {
+			spin_lock_irqsave(&priv->lock, flags);
+			txq->need_update = 1;
+			iwl_legacy_txq_update_write_ptr(priv, txq);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		} else {
+			iwl_legacy_stop_queue(priv, txq);
+		}
+	}
+
+	return 0;
+
+drop_unlock:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return -1;
+}
+
+static inline int iwl4965_alloc_dma_ptr(struct iwl_priv *priv,
+				    struct iwl_dma_ptr *ptr, size_t size)
+{
+	ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
+				       GFP_KERNEL);
+	if (!ptr->addr)
+		return -ENOMEM;
+	ptr->size = size;
+	return 0;
+}
+
+static inline void iwl4965_free_dma_ptr(struct iwl_priv *priv,
+				    struct iwl_dma_ptr *ptr)
+{
+	if (unlikely(!ptr->addr))
+		return;
+
+	dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
+	memset(ptr, 0, sizeof(*ptr));
+}
+
+/**
+ * iwl4965_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* Tx queues */
+	if (priv->txq) {
+		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+			if (txq_id == priv->cmd_queue)
+				iwl_legacy_cmd_queue_free(priv);
+			else
+				iwl_legacy_tx_queue_free(priv, txq_id);
+	}
+	iwl4965_free_dma_ptr(priv, &priv->kw);
+
+	iwl4965_free_dma_ptr(priv, &priv->scd_bc_tbls);
+
+	/* free tx queue structure */
+	iwl_legacy_txq_mem(priv);
+}
+
+/**
+ * iwl4965_txq_ctx_alloc - allocate TX queue context
+ * Allocate all Tx DMA structures and initialize them
+ *
+ * @param priv
+ * @return error code
+ */
+int iwl4965_txq_ctx_alloc(struct iwl_priv *priv)
+{
+	int ret;
+	int txq_id, slots_num;
+	unsigned long flags;
+
+	/* Free all tx/cmd queues and keep-warm buffer */
+	iwl4965_hw_txq_ctx_free(priv);
+
+	ret = iwl4965_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
+				priv->hw_params.scd_bc_tbls_size);
+	if (ret) {
+		IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
+		goto error_bc_tbls;
+	}
+	/* Alloc keep-warm buffer */
+	ret = iwl4965_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
+	if (ret) {
+		IWL_ERR(priv, "Keep Warm allocation failed\n");
+		goto error_kw;
+	}
+
+	/* allocate tx queue structure */
+	ret = iwl_legacy_alloc_txq_mem(priv);
+	if (ret)
+		goto error;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Turn off all Tx DMA fifos */
+	iwl4965_txq_set_sched(priv, 0);
+
+	/* Tell NIC where to find the "keep warm" buffer */
+	iwl_legacy_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = (txq_id == priv->cmd_queue) ?
+					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		ret = iwl_legacy_tx_queue_init(priv,
+					&priv->txq[txq_id], slots_num,
+				       txq_id);
+		if (ret) {
+			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return ret;
+
+ error:
+	iwl4965_hw_txq_ctx_free(priv);
+	iwl4965_free_dma_ptr(priv, &priv->kw);
+ error_kw:
+	iwl4965_free_dma_ptr(priv, &priv->scd_bc_tbls);
+ error_bc_tbls:
+	return ret;
+}
+
+void iwl4965_txq_ctx_reset(struct iwl_priv *priv)
+{
+	int txq_id, slots_num;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Turn off all Tx DMA fifos */
+	iwl4965_txq_set_sched(priv, 0);
+
+	/* Tell NIC where to find the "keep warm" buffer */
+	iwl_legacy_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Alloc and init all Tx queues, including the command queue (#4) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = txq_id == priv->cmd_queue ?
+			    TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		iwl_legacy_tx_queue_reset(priv, &priv->txq[txq_id],
+						slots_num, txq_id);
+	}
+}
+
+/**
+ * iwl4965_txq_ctx_stop - Stop all Tx DMA channels
+ */
+void iwl4965_txq_ctx_stop(struct iwl_priv *priv)
+{
+	int ch, txq_id;
+	unsigned long flags;
+
+	/* Turn off all Tx DMA fifos */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	iwl4965_txq_set_sched(priv, 0);
+
+	/* Stop each Tx DMA channel, and wait for it to be idle */
+	for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
+		iwl_legacy_write_direct32(priv,
+				FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+		if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
+				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+				    1000))
+			IWL_ERR(priv, "Failing on timeout while stopping"
+			    " DMA channel %d [0x%08x]", ch,
+			    iwl_legacy_read_direct32(priv,
+					FH_TSSR_TX_STATUS_REG));
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!priv->txq)
+		return;
+
+	/* Unmap DMA from host system and free skb's */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		if (txq_id == priv->cmd_queue)
+			iwl_legacy_cmd_queue_unmap(priv);
+		else
+			iwl_legacy_tx_queue_unmap(priv, txq_id);
+}
+
+/*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
+ */
+static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
+			return txq_id;
+	return -1;
+}
+
+/**
+ * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
+ */
+static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
+					    u16 txq_id)
+{
+	/* Simply stop the queue, but don't change any configuration;
+	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+	iwl_legacy_write_prph(priv,
+		IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
+		(0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+		(1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
+}
+
+/**
+ * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
+ */
+static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+					u16 txq_id)
+{
+	u32 tbl_dw_addr;
+	u32 tbl_dw;
+	u16 scd_q2ratid;
+
+	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
+
+	tbl_dw_addr = priv->scd_base_addr +
+			IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
+
+	tbl_dw = iwl_legacy_read_targ_mem(priv, tbl_dw_addr);
+
+	if (txq_id & 0x1)
+		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+	else
+		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+
+	iwl_legacy_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
+
+	return 0;
+}
+
+/**
+ * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
+ *
+ * NOTE:  txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE,
+ *        i.e. it must be one of the higher queues used for aggregation
+ */
+static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
+				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
+{
+	unsigned long flags;
+	u16 ra_tid;
+	int ret;
+
+	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
+	    (IWL49_FIRST_AMPDU_QUEUE +
+		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+		IWL_WARN(priv,
+			"queue number out of range: %d, must be %d to %d\n",
+			txq_id, IWL49_FIRST_AMPDU_QUEUE,
+			IWL49_FIRST_AMPDU_QUEUE +
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
+		return -EINVAL;
+	}
+
+	ra_tid = BUILD_RAxTID(sta_id, tid);
+
+	/* Modify device's station table to Tx this TID */
+	ret = iwl4965_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Stop this Tx queue before configuring it */
+	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+
+	/* Map receiver-address / traffic-ID to this queue */
+	iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+
+	/* Set this queue as a chain-building queue */
+	iwl_legacy_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+	/* Place first TFD at index corresponding to start sequence number.
+	 * Assumes that ssn_idx is valid (!= 0xFFF) */
+	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+	/* Set up Tx window size and frame limit for this queue */
+	iwl_legacy_write_targ_mem(priv,
+		priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
+		(SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+		IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+	iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
+		IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
+		(SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
+		& IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+	iwl_legacy_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+
+	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
+	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+
+int iwl4965_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+{
+	int sta_id;
+	int tx_fifo;
+	int txq_id;
+	int ret;
+	unsigned long flags;
+	struct iwl_tid_data *tid_data;
+
+	tx_fifo = iwl4965_get_fifo_from_tid(iwl_legacy_rxon_ctx_from_vif(vif), tid);
+	if (unlikely(tx_fifo < 0))
+		return tx_fifo;
+
+	IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
+			__func__, sta->addr, tid);
+
+	sta_id = iwl_legacy_sta_id(sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Start AGG on invalid station\n");
+		return -ENXIO;
+	}
+	if (unlikely(tid >= MAX_TID_COUNT))
+		return -EINVAL;
+
+	if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) {
+		IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n");
+		return -ENXIO;
+	}
+
+	txq_id = iwl4965_txq_ctx_activate_free(priv);
+	if (txq_id == -1) {
+		IWL_ERR(priv, "No free aggregation queue available\n");
+		return -ENXIO;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	tid_data = &priv->stations[sta_id].tid[tid];
+	*ssn = SEQ_TO_SN(tid_data->seq_number);
+	tid_data->agg.txq_id = txq_id;
+	iwl_legacy_set_swq_id(&priv->txq[txq_id],
+				iwl4965_get_ac_from_tid(tid), txq_id);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	ret = iwl4965_txq_agg_enable(priv, txq_id, tx_fifo,
+						  sta_id, tid, *ssn);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	tid_data = &priv->stations[sta_id].tid[tid];
+	if (tid_data->tfds_in_queue == 0) {
+		IWL_DEBUG_HT(priv, "HW queue is empty\n");
+		tid_data->agg.state = IWL_AGG_ON;
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+	} else {
+		IWL_DEBUG_HT(priv,
+			"HW queue is NOT empty: %d packets in HW queue\n",
+			     tid_data->tfds_in_queue);
+		tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	return ret;
+}
+
+/**
+ * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE
+ * priv->lock must be held by the caller
+ */
+static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+				   u16 ssn_idx, u8 tx_fifo)
+{
+	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
+	    (IWL49_FIRST_AMPDU_QUEUE +
+		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+		IWL_WARN(priv,
+			"queue number out of range: %d, must be %d to %d\n",
+			txq_id, IWL49_FIRST_AMPDU_QUEUE,
+			IWL49_FIRST_AMPDU_QUEUE +
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
+		return -EINVAL;
+	}
+
+	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+
+	iwl_legacy_clear_bits_prph(priv,
+			IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+	/* supposes that ssn_idx is valid (!= 0xFFF) */
+	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+	iwl_legacy_clear_bits_prph(priv,
+			 IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+	iwl_txq_ctx_deactivate(priv, txq_id);
+	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
+
+	return 0;
+}
+
+int iwl4965_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta, u16 tid)
+{
+	int tx_fifo_id, txq_id, sta_id, ssn;
+	struct iwl_tid_data *tid_data;
+	int write_ptr, read_ptr;
+	unsigned long flags;
+
+	tx_fifo_id = iwl4965_get_fifo_from_tid(iwl_legacy_rxon_ctx_from_vif(vif), tid);
+	if (unlikely(tx_fifo_id < 0))
+		return tx_fifo_id;
+
+	sta_id = iwl_legacy_sta_id(sta);
+
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
+		return -ENXIO;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	tid_data = &priv->stations[sta_id].tid[tid];
+	ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
+	txq_id = tid_data->agg.txq_id;
+
+	switch (priv->stations[sta_id].tid[tid].agg.state) {
+	case IWL_EMPTYING_HW_QUEUE_ADDBA:
+		/*
+		 * This can happen if the peer stops aggregation
+		 * again before we've had a chance to drain the
+		 * queue we selected previously, i.e. before the
+		 * session was really started completely.
+		 */
+		IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
+		goto turn_off;
+	case IWL_AGG_ON:
+		break;
+	default:
+		IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
+	}
+
+	write_ptr = priv->txq[txq_id].q.write_ptr;
+	read_ptr = priv->txq[txq_id].q.read_ptr;
+
+	/* The queue is not empty */
+	if (write_ptr != read_ptr) {
+		IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
+		priv->stations[sta_id].tid[tid].agg.state =
+				IWL_EMPTYING_HW_QUEUE_DELBA;
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+
+	IWL_DEBUG_HT(priv, "HW queue is empty\n");
+ turn_off:
+	priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
+
+	/* do not restore/save irqs */
+	spin_unlock(&priv->sta_lock);
+	spin_lock(&priv->lock);
+
+	/*
+	 * the only reason this call can fail is queue number out of range,
+	 * which can happen if uCode is reloaded and all the station
+	 * information are lost. if it is outside the range, there is no need
+	 * to deactivate the uCode queue, just return "success" to allow
+	 *  mac80211 to clean up it own data.
+	 */
+	iwl4965_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+
+	return 0;
+}
+
+int iwl4965_txq_check_empty(struct iwl_priv *priv,
+			   int sta_id, u8 tid, int txq_id)
+{
+	struct iwl_queue *q = &priv->txq[txq_id].q;
+	u8 *addr = priv->stations[sta_id].sta.sta.addr;
+	struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
+	struct iwl_rxon_context *ctx;
+
+	ctx = &priv->contexts[priv->stations[sta_id].ctxid];
+
+	lockdep_assert_held(&priv->sta_lock);
+
+	switch (priv->stations[sta_id].tid[tid].agg.state) {
+	case IWL_EMPTYING_HW_QUEUE_DELBA:
+		/* We are reclaiming the last packet of the */
+		/* 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);
+			int tx_fifo = iwl4965_get_fifo_from_tid(ctx, tid);
+			IWL_DEBUG_HT(priv,
+				"HW queue empty: continue DELBA flow\n");
+			iwl4965_txq_agg_disable(priv, txq_id, ssn, tx_fifo);
+			tid_data->agg.state = IWL_AGG_OFF;
+			ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
+		}
+		break;
+	case IWL_EMPTYING_HW_QUEUE_ADDBA:
+		/* We are reclaiming the last packet of the queue */
+		if (tid_data->tfds_in_queue == 0) {
+			IWL_DEBUG_HT(priv,
+				"HW queue empty: continue ADDBA flow\n");
+			tid_data->agg.state = IWL_AGG_ON;
+			ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void iwl4965_non_agg_tx_status(struct iwl_priv *priv,
+				     struct iwl_rxon_context *ctx,
+				     const u8 *addr1)
+{
+	struct ieee80211_sta *sta;
+	struct iwl_station_priv *sta_priv;
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(ctx->vif, addr1);
+	if (sta) {
+		sta_priv = (void *)sta->drv_priv;
+		/* avoid atomic ops if this isn't a client */
+		if (sta_priv->client &&
+		    atomic_dec_return(&sta_priv->pending_frames) == 0)
+			ieee80211_sta_block_awake(priv->hw, sta, false);
+	}
+	rcu_read_unlock();
+}
+
+static void
+iwl4965_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info,
+			     bool is_agg)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
+
+	if (!is_agg)
+		iwl4965_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1);
+
+	ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
+}
+
+int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_tx_info *tx_info;
+	int nfreed = 0;
+	struct ieee80211_hdr *hdr;
+
+	if ((index >= q->n_bd) || (iwl_legacy_queue_used(q, index) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
+			  "is out of range [0-%d] %d %d.\n", txq_id,
+			  index, q->n_bd, q->write_ptr, q->read_ptr);
+		return 0;
+	}
+
+	for (index = iwl_legacy_queue_inc_wrap(index, q->n_bd);
+	     q->read_ptr != index;
+	     q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		tx_info = &txq->txb[txq->q.read_ptr];
+		iwl4965_tx_status(priv, tx_info,
+				 txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
+
+		hdr = (struct ieee80211_hdr *)tx_info->skb->data;
+		if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+			nfreed++;
+		tx_info->skb = NULL;
+
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+	}
+	return nfreed;
+}
+
+/**
+ * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
+ *
+ * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+ * ACK vs. not.  This gets sent to mac80211, then to rate scaling algo.
+ */
+static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+				 struct iwl_ht_agg *agg,
+				 struct iwl_compressed_ba_resp *ba_resp)
+
+{
+	int i, sh, ack;
+	u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
+	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+	int successes = 0;
+	struct ieee80211_tx_info *info;
+	u64 bitmap, sent_bitmap;
+
+	if (unlikely(!agg->wait_for_ba))  {
+		if (unlikely(ba_resp->bitmap))
+			IWL_ERR(priv, "Received BA when not expected\n");
+		return -EINVAL;
+	}
+
+	/* Mark that the expected block-ack response arrived */
+	agg->wait_for_ba = 0;
+	IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx,
+							ba_resp->seq_ctl);
+
+	/* Calculate shift to align block-ack bits with our Tx window bits */
+	sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
+	if (sh < 0) /* tbw something is wrong with indices */
+		sh += 0x100;
+
+	if (agg->frame_count > (64 - sh)) {
+		IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
+		return -1;
+	}
+
+	/* don't use 64-bit values for now */
+	bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+
+	/* check for success or failure according to the
+	 * transmitted bitmap and block-ack bitmap */
+	sent_bitmap = bitmap & agg->bitmap;
+
+	/* For each frame attempted in aggregation,
+	 * update driver's record of tx frame's status. */
+	i = 0;
+	while (sent_bitmap) {
+		ack = sent_bitmap & 1ULL;
+		successes += ack;
+		IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
+			ack ? "ACK" : "NACK", i,
+			(agg->start_idx + i) & 0xff,
+			agg->start_idx + i);
+		sent_bitmap >>= 1;
+		++i;
+	}
+
+	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
+				   (unsigned long long)bitmap);
+
+	info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
+	memset(&info->status, 0, sizeof(info->status));
+	info->flags |= IEEE80211_TX_STAT_ACK;
+	info->flags |= IEEE80211_TX_STAT_AMPDU;
+	info->status.ampdu_ack_len = successes;
+	info->status.ampdu_len = agg->frame_count;
+	iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+
+	return 0;
+}
+
+/**
+ * translate ucode response to mac80211 tx status control values
+ */
+void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
+				  struct ieee80211_tx_info *info)
+{
+	struct ieee80211_tx_rate *r = &info->control.rates[0];
+
+	info->antenna_sel_tx =
+		((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
+	if (rate_n_flags & RATE_MCS_HT_MSK)
+		r->flags |= IEEE80211_TX_RC_MCS;
+	if (rate_n_flags & RATE_MCS_GF_MSK)
+		r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
+		r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+	if (rate_n_flags & RATE_MCS_DUP_MSK)
+		r->flags |= IEEE80211_TX_RC_DUP_DATA;
+	if (rate_n_flags & RATE_MCS_SGI_MSK)
+		r->flags |= IEEE80211_TX_RC_SHORT_GI;
+	r->idx = iwl4965_hwrate_to_mac80211_idx(rate_n_flags, info->band);
+}
+
+/**
+ * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
+ *
+ * Handles block-acknowledge notification from device, which reports success
+ * of frames sent via aggregation.
+ */
+void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
+					   struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+	struct iwl_tx_queue *txq = NULL;
+	struct iwl_ht_agg *agg;
+	int index;
+	int sta_id;
+	int tid;
+	unsigned long flags;
+
+	/* "flow" corresponds to Tx queue */
+	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+
+	/* "ssn" is start of block-ack Tx window, corresponds to index
+	 * (in Tx queue's circular buffer) of first TFD/frame in window */
+	u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
+
+	if (scd_flow >= priv->hw_params.max_txq_num) {
+		IWL_ERR(priv,
+			"BUG_ON scd_flow is bigger than number of queues\n");
+		return;
+	}
+
+	txq = &priv->txq[scd_flow];
+	sta_id = ba_resp->sta_id;
+	tid = ba_resp->tid;
+	agg = &priv->stations[sta_id].tid[tid].agg;
+	if (unlikely(agg->txq_id != scd_flow)) {
+		/*
+		 * FIXME: this is a uCode bug which need to be addressed,
+		 * log the information and return for now!
+		 * since it is possible happen very often and in order
+		 * not to fill the syslog, don't enable the logging by default
+		 */
+		IWL_DEBUG_TX_REPLY(priv,
+			"BA scd_flow %d does not match txq_id %d\n",
+			scd_flow, agg->txq_id);
+		return;
+	}
+
+	/* Find index just before block-ack window */
+	index = iwl_legacy_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
+			   "sta_id = %d\n",
+			   agg->wait_for_ba,
+			   (u8 *) &ba_resp->sta_addr_lo32,
+			   ba_resp->sta_id);
+	IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx,"
+			"scd_flow = "
+			   "%d, scd_ssn = %d\n",
+			   ba_resp->tid,
+			   ba_resp->seq_ctl,
+			   (unsigned long long)le64_to_cpu(ba_resp->bitmap),
+			   ba_resp->scd_flow,
+			   ba_resp->scd_ssn);
+	IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n",
+			   agg->start_idx,
+			   (unsigned long long)agg->bitmap);
+
+	/* Update driver's record of ACK vs. not for each frame in window */
+	iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
+
+	/* Release all TFDs before the SSN, i.e. all TFDs in front of
+	 * block-ack window (we assume that they've been successfully
+	 * transmitted ... if not, it's too late anyway). */
+	if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
+		/* calculate mac80211 ampdu sw queue to wake */
+		int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
+		iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
+
+		if ((iwl_legacy_queue_space(&txq->q) > txq->q.low_mark) &&
+		    priv->mac80211_registered &&
+		    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+			iwl_legacy_wake_queue(priv, txq);
+
+		iwl4965_txq_check_empty(priv, sta_id, tid, scd_flow);
+	}
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+const char *iwl4965_get_tx_fail_reason(u32 status)
+{
+#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
+#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
+
+	switch (status & TX_STATUS_MSK) {
+	case TX_STATUS_SUCCESS:
+		return "SUCCESS";
+	TX_STATUS_POSTPONE(DELAY);
+	TX_STATUS_POSTPONE(FEW_BYTES);
+	TX_STATUS_POSTPONE(QUIET_PERIOD);
+	TX_STATUS_POSTPONE(CALC_TTAK);
+	TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
+	TX_STATUS_FAIL(SHORT_LIMIT);
+	TX_STATUS_FAIL(LONG_LIMIT);
+	TX_STATUS_FAIL(FIFO_UNDERRUN);
+	TX_STATUS_FAIL(DRAIN_FLOW);
+	TX_STATUS_FAIL(RFKILL_FLUSH);
+	TX_STATUS_FAIL(LIFE_EXPIRE);
+	TX_STATUS_FAIL(DEST_PS);
+	TX_STATUS_FAIL(HOST_ABORTED);
+	TX_STATUS_FAIL(BT_RETRY);
+	TX_STATUS_FAIL(STA_INVALID);
+	TX_STATUS_FAIL(FRAG_DROPPED);
+	TX_STATUS_FAIL(TID_DISABLE);
+	TX_STATUS_FAIL(FIFO_FLUSHED);
+	TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
+	TX_STATUS_FAIL(PASSIVE_NO_RX);
+	TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
+	}
+
+	return "UNKNOWN";
+
+#undef TX_STATUS_FAIL
+#undef TX_STATUS_POSTPONE
+}
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c b/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c
new file mode 100644
index 0000000..001d148
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c
@@ -0,0 +1,166 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+#include "iwl-4965-calib.h"
+
+#define IWL_AC_UNSET -1
+
+/**
+ * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
+ *   using sample data 100 bytes apart.  If these sample points are good,
+ *   it's a pretty good bet that everything between them is good, too.
+ */
+static int
+iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+{
+	u32 val;
+	int ret = 0;
+	u32 errcnt = 0;
+	u32 i;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
+		/* read data comes through single port, auto-incr addr */
+		/* NOTE: Use the debugless read so we don't flood kernel log
+		 * if IWL_DL_IO is set */
+		iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			i + IWL4965_RTC_INST_LOWER_BOUND);
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+			ret = -EIO;
+			errcnt++;
+			if (errcnt >= 3)
+				break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
+ *     looking at all data.
+ */
+static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
+				 u32 len)
+{
+	u32 val;
+	u32 save_len = len;
+	int ret = 0;
+	u32 errcnt;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			   IWL4965_RTC_INST_LOWER_BOUND);
+
+	errcnt = 0;
+	for (; len > 0; len -= sizeof(u32), image++) {
+		/* read data comes through single port, auto-incr addr */
+		/* NOTE: Use the debugless read so we don't flood kernel log
+		 * if IWL_DL_IO is set */
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "uCode INST section is invalid at "
+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+				  save_len - len, val, le32_to_cpu(*image));
+			ret = -EIO;
+			errcnt++;
+			if (errcnt >= 20)
+				break;
+		}
+	}
+
+	if (!errcnt)
+		IWL_DEBUG_INFO(priv,
+		    "ucode image in INSTRUCTION memory is good\n");
+
+	return ret;
+}
+
+/**
+ * iwl4965_verify_ucode - determine which instruction image is in SRAM,
+ *    and verify its contents
+ */
+int iwl4965_verify_ucode(struct iwl_priv *priv)
+{
+	__le32 *image;
+	u32 len;
+	int ret;
+
+	/* Try bootstrap */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	ret = iwl4965_verify_inst_sparse(priv, image, len);
+	if (!ret) {
+		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try initialize */
+	image = (__le32 *)priv->ucode_init.v_addr;
+	len = priv->ucode_init.len;
+	ret = iwl4965_verify_inst_sparse(priv, image, len);
+	if (!ret) {
+		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try runtime/protocol */
+	image = (__le32 *)priv->ucode_code.v_addr;
+	len = priv->ucode_code.len;
+	ret = iwl4965_verify_inst_sparse(priv, image, len);
+	if (!ret) {
+		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+
+	/* Since nothing seems to match, show first several data entries in
+	 * instruction SRAM, so maybe visual inspection will give a clue.
+	 * Selection of bootstrap image (vs. other images) is arbitrary. */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	ret = iwl4965_verify_inst_full(priv, image, len);
+
+	return ret;
+}
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
new file mode 100644
index 0000000..f5433c7
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -0,0 +1,2188 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-calib.h"
+#include "iwl-sta.h"
+#include "iwl-4965-led.h"
+#include "iwl-4965.h"
+#include "iwl-4965-debugfs.h"
+
+static int iwl4965_send_tx_power(struct iwl_priv *priv);
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
+
+/* Highest firmware API version supported */
+#define IWL4965_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IWL4965_UCODE_API_MIN 2
+
+#define IWL4965_FW_PRE "iwlwifi-4965-"
+#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
+#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
+
+/* check contents of special bootstrap uCode SRAM */
+static int iwl4965_verify_bsm(struct iwl_priv *priv)
+{
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	u32 reg;
+	u32 val;
+
+	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
+
+	/* verify BSM SRAM contents */
+	val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
+	for (reg = BSM_SRAM_LOWER_BOUND;
+	     reg < BSM_SRAM_LOWER_BOUND + len;
+	     reg += sizeof(u32), image++) {
+		val = iwl_legacy_read_prph(priv, reg);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "BSM uCode verification failed at "
+				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+				  BSM_SRAM_LOWER_BOUND,
+				  reg - BSM_SRAM_LOWER_BOUND, len,
+				  val, le32_to_cpu(*image));
+			return -EIO;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
+
+	return 0;
+}
+
+/**
+ * iwl4965_load_bsm - Load bootstrap instructions
+ *
+ * BSM operation:
+ *
+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+ * in special SRAM that does not power down during RFKILL.  When powering back
+ * up after power-saving sleeps (or during initial uCode load), the BSM loads
+ * the bootstrap program into the on-board processor, and starts it.
+ *
+ * The bootstrap program loads (via DMA) instructions and data for a new
+ * program from host DRAM locations indicated by the host driver in the
+ * BSM_DRAM_* registers.  Once the new program is loaded, it starts
+ * automatically.
+ *
+ * When initializing the NIC, the host driver points the BSM to the
+ * "initialize" uCode image.  This uCode sets up some internal data, then
+ * notifies host via "initialize alive" that it is complete.
+ *
+ * The host then replaces the BSM_DRAM_* pointer values to point to the
+ * normal runtime uCode instructions and a backup uCode data cache buffer
+ * (filled initially with starting data values for the on-board processor),
+ * then triggers the "initialize" uCode to load and launch the runtime uCode,
+ * which begins normal operation.
+ *
+ * When doing a power-save shutdown, runtime uCode saves data SRAM into
+ * the backup data cache in DRAM before SRAM is powered down.
+ *
+ * When powering back up, the BSM loads the bootstrap program.  This reloads
+ * the runtime uCode instructions and the backup data cache into SRAM,
+ * and re-launches the runtime uCode from where it left off.
+ */
+static int iwl4965_load_bsm(struct iwl_priv *priv)
+{
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+	u32 inst_len;
+	u32 data_len;
+	int i;
+	u32 done;
+	u32 reg_offset;
+	int ret;
+
+	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
+
+	priv->ucode_type = UCODE_RT;
+
+	/* make sure bootstrap program is no larger than BSM's SRAM size */
+	if (len > IWL49_MAX_BSM_SIZE)
+		return -EINVAL;
+
+	/* Tell bootstrap uCode where to find the "Initialize" uCode
+	 *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+	 * NOTE:  iwl_init_alive_start() will replace these values,
+	 *        after the "initialize" uCode has run, to point to
+	 *        runtime/protocol instructions and backup data cache.
+	 */
+	pinst = priv->ucode_init.p_addr >> 4;
+	pdata = priv->ucode_init_data.p_addr >> 4;
+	inst_len = priv->ucode_init.len;
+	data_len = priv->ucode_init_data.len;
+
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+
+	/* Fill BSM memory with bootstrap instructions */
+	for (reg_offset = BSM_SRAM_LOWER_BOUND;
+	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
+	     reg_offset += sizeof(u32), image++)
+		_iwl_legacy_write_prph(priv, reg_offset, le32_to_cpu(*image));
+
+	ret = iwl4965_verify_bsm(priv);
+	if (ret)
+		return ret;
+
+	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+	iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+	iwl_legacy_write_prph(priv,
+			BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
+	iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+	/* Load bootstrap code into instruction SRAM now,
+	 *   to prepare to load "initialize" uCode */
+	iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
+
+	/* Wait for load of bootstrap uCode to finish */
+	for (i = 0; i < 100; i++) {
+		done = iwl_legacy_read_prph(priv, BSM_WR_CTRL_REG);
+		if (!(done & BSM_WR_CTRL_REG_BIT_START))
+			break;
+		udelay(10);
+	}
+	if (i < 100)
+		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
+	else {
+		IWL_ERR(priv, "BSM write did not complete!\n");
+		return -EIO;
+	}
+
+	/* Enable future boot loads whenever power management unit triggers it
+	 *   (e.g. when powering back up after power-save shutdown) */
+	iwl_legacy_write_prph(priv,
+			BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
+
+
+	return 0;
+}
+
+/**
+ * iwl4965_set_ucode_ptrs - Set uCode address location
+ *
+ * Tell initialization uCode where to find runtime uCode.
+ *
+ * BSM registers initially contain pointers to initialization uCode.
+ * We need to replace them to load runtime uCode inst and data,
+ * and to save runtime data when powering down.
+ */
+static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
+{
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+	int ret = 0;
+
+	/* bits 35:4 for 4965 */
+	pinst = priv->ucode_code.p_addr >> 4;
+	pdata = priv->ucode_data_backup.p_addr >> 4;
+
+	/* Tell bootstrap uCode where to find image to load */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+				 priv->ucode_data.len);
+
+	/* Inst byte count must be last to set up, bit 31 signals uCode
+	 *   that all new ptr/size info is in place */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
+
+	return ret;
+}
+
+/**
+ * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
+ *
+ * Called after REPLY_ALIVE notification received from "initialize" uCode.
+ *
+ * The 4965 "initialize" ALIVE reply contains calibration data for:
+ *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
+ *   (3945 does not contain this data).
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+*/
+static void iwl4965_init_alive_start(struct iwl_priv *priv)
+{
+	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "initialize" alive if code weren't properly loaded.  */
+	if (iwl4965_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
+		goto restart;
+	}
+
+	/* Calculate temperature */
+	priv->temperature = iwl4965_hw_get_temperature(priv);
+
+	/* Send pointers to protocol/runtime uCode image ... init code will
+	 * load and launch runtime uCode, which will send us another "Alive"
+	 * notification. */
+	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+	if (iwl4965_set_ucode_ptrs(priv)) {
+		/* Runtime instruction load won't happen;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
+		goto restart;
+	}
+	return;
+
+restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+static bool iw4965_is_ht40_channel(__le32 rxon_flags)
+{
+	int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
+				    >> RXON_FLG_CHANNEL_MODE_POS;
+	return ((chan_mod == CHANNEL_MODE_PURE_40) ||
+		  (chan_mod == CHANNEL_MODE_MIXED));
+}
+
+static void iwl4965_nic_config(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	u16 radio_cfg;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	radio_cfg = iwl_legacy_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+	/* write radio config values to register */
+	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+
+	/* set CSR_HW_CONFIG_REG for uCode use */
+	iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+
+	priv->calib_info = (struct iwl_eeprom_calib_info *)
+		iwl_legacy_eeprom_query_addr(priv,
+				EEPROM_4965_CALIB_TXPOWER_OFFSET);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
+ * Called after every association, but this runs only once!
+ *  ... once chain noise is calibrated the first time, it's good forever.  */
+static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
+{
+	struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
+
+	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
+	    iwl_legacy_is_any_associated(priv)) {
+		struct iwl_calib_diff_gain_cmd cmd;
+
+		/* clear data for chain noise calibration algorithm */
+		data->chain_noise_a = 0;
+		data->chain_noise_b = 0;
+		data->chain_noise_c = 0;
+		data->chain_signal_a = 0;
+		data->chain_signal_b = 0;
+		data->chain_signal_c = 0;
+		data->beacon_count = 0;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
+		cmd.diff_gain_a = 0;
+		cmd.diff_gain_b = 0;
+		cmd.diff_gain_c = 0;
+		if (iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+				 sizeof(cmd), &cmd))
+			IWL_ERR(priv,
+				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
+		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
+	}
+}
+
+static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
+	.min_nrg_cck = 97,
+	.max_nrg_cck = 0, /* not used, set to 0 */
+
+	.auto_corr_min_ofdm = 85,
+	.auto_corr_min_ofdm_mrc = 170,
+	.auto_corr_min_ofdm_x1 = 105,
+	.auto_corr_min_ofdm_mrc_x1 = 220,
+
+	.auto_corr_max_ofdm = 120,
+	.auto_corr_max_ofdm_mrc = 210,
+	.auto_corr_max_ofdm_x1 = 140,
+	.auto_corr_max_ofdm_mrc_x1 = 270,
+
+	.auto_corr_min_cck = 125,
+	.auto_corr_max_cck = 200,
+	.auto_corr_min_cck_mrc = 200,
+	.auto_corr_max_cck_mrc = 400,
+
+	.nrg_th_cck = 100,
+	.nrg_th_ofdm = 100,
+
+	.barker_corr_th_min = 190,
+	.barker_corr_th_min_mrc = 390,
+	.nrg_th_cca = 62,
+};
+
+static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
+{
+	/* want Kelvin */
+	priv->hw_params.ct_kill_threshold =
+		CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
+}
+
+/**
+ * iwl4965_hw_set_hw_params
+ *
+ * Called when initializing driver
+ */
+static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
+{
+	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
+	    priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
+		priv->cfg->base_params->num_of_queues =
+			priv->cfg->mod_params->num_of_queues;
+
+	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
+	priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
+	priv->hw_params.scd_bc_tbls_size =
+			priv->cfg->base_params->num_of_queues *
+			sizeof(struct iwl4965_scd_bc_tbl);
+	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
+	priv->hw_params.max_stations = IWL4965_STATION_COUNT;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
+	priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
+	priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
+	priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
+	priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
+
+	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
+	priv->hw_params.tx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_tx_ant);
+	priv->hw_params.rx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_rx_ant);
+	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
+	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+
+	iwl4965_set_ct_threshold(priv);
+
+	priv->hw_params.sens = &iwl4965_sensitivity;
+	priv->hw_params.beacon_time_tsf_bits = IWL4965_EXT_BEACON_TIME_POS;
+
+	return 0;
+}
+
+static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
+{
+	s32 sign = 1;
+
+	if (num < 0) {
+		sign = -sign;
+		num = -num;
+	}
+	if (denom < 0) {
+		sign = -sign;
+		denom = -denom;
+	}
+	*res = 1;
+	*res = ((num * 2 + denom) / (denom * 2)) * sign;
+
+	return 1;
+}
+
+/**
+ * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
+ *
+ * Determines power supply voltage compensation for txpower calculations.
+ * Returns number of 1/2-dB steps to subtract from gain table index,
+ * to compensate for difference between power supply voltage during
+ * factory measurements, vs. current power supply voltage.
+ *
+ * Voltage indication is higher for lower voltage.
+ * Lower voltage requires more gain (lower gain table index).
+ */
+static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
+					    s32 current_voltage)
+{
+	s32 comp = 0;
+
+	if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) ||
+	    (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage))
+		return 0;
+
+	iwl4965_math_div_round(current_voltage - eeprom_voltage,
+			       TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp);
+
+	if (current_voltage > eeprom_voltage)
+		comp *= 2;
+	if ((comp < -2) || (comp > 2))
+		comp = 0;
+
+	return comp;
+}
+
+static s32 iwl4965_get_tx_atten_grp(u16 channel)
+{
+	if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR5_LCH)
+		return CALIB_CH_GROUP_5;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR1_LCH)
+		return CALIB_CH_GROUP_1;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR2_LCH)
+		return CALIB_CH_GROUP_2;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR3_LCH)
+		return CALIB_CH_GROUP_3;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
+		return CALIB_CH_GROUP_4;
+
+	return -1;
+}
+
+static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
+{
+	s32 b = -1;
+
+	for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
+		if (priv->calib_info->band_info[b].ch_from == 0)
+			continue;
+
+		if ((channel >= priv->calib_info->band_info[b].ch_from)
+		    && (channel <= priv->calib_info->band_info[b].ch_to))
+			break;
+	}
+
+	return b;
+}
+
+static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+{
+	s32 val;
+
+	if (x2 == x1)
+		return y1;
+	else {
+		iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
+		return val + y2;
+	}
+}
+
+/**
+ * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
+ *
+ * Interpolates factory measurements from the two sample channels within a
+ * sub-band, to apply to channel of interest.  Interpolation is proportional to
+ * differences in channel frequencies, which is proportional to differences
+ * in channel number.
+ */
+static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
+				    struct iwl_eeprom_calib_ch_info *chan_info)
+{
+	s32 s = -1;
+	u32 c;
+	u32 m;
+	const struct iwl_eeprom_calib_measure *m1;
+	const struct iwl_eeprom_calib_measure *m2;
+	struct iwl_eeprom_calib_measure *omeas;
+	u32 ch_i1;
+	u32 ch_i2;
+
+	s = iwl4965_get_sub_band(priv, channel);
+	if (s >= EEPROM_TX_POWER_BANDS) {
+		IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
+		return -1;
+	}
+
+	ch_i1 = priv->calib_info->band_info[s].ch1.ch_num;
+	ch_i2 = priv->calib_info->band_info[s].ch2.ch_num;
+	chan_info->ch_num = (u8) channel;
+
+	IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n",
+			  channel, s, ch_i1, ch_i2);
+
+	for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
+		for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
+			m1 = &(priv->calib_info->band_info[s].ch1.
+			       measurements[c][m]);
+			m2 = &(priv->calib_info->band_info[s].ch2.
+			       measurements[c][m]);
+			omeas = &(chan_info->measurements[c][m]);
+
+			omeas->actual_pow =
+			    (u8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->actual_pow,
+							   ch_i2,
+							   m2->actual_pow);
+			omeas->gain_idx =
+			    (u8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->gain_idx, ch_i2,
+							   m2->gain_idx);
+			omeas->temperature =
+			    (u8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->temperature,
+							   ch_i2,
+							   m2->temperature);
+			omeas->pa_det =
+			    (s8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->pa_det, ch_i2,
+							   m2->pa_det);
+
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m,
+				m1->actual_pow, m2->actual_pow, omeas->actual_pow);
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m,
+				m1->gain_idx, m2->gain_idx, omeas->gain_idx);
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m,
+				m1->pa_det, m2->pa_det, omeas->pa_det);
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d  T1=%d  T2=%d  T=%d\n", c, m,
+				m1->temperature, m2->temperature,
+				omeas->temperature);
+		}
+	}
+
+	return 0;
+}
+
+/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
+ * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
+static s32 back_off_table[] = {
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 20 MHz */
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 20 MHz */
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 40 MHz */
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 40 MHz */
+	10			/* CCK */
+};
+
+/* Thermal compensation values for txpower for various frequency ranges ...
+ *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
+static struct iwl4965_txpower_comp_entry {
+	s32 degrees_per_05db_a;
+	s32 degrees_per_05db_a_denom;
+} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
+	{9, 2},			/* group 0 5.2, ch  34-43 */
+	{4, 1},			/* group 1 5.2, ch  44-70 */
+	{4, 1},			/* group 2 5.2, ch  71-124 */
+	{4, 1},			/* group 3 5.2, ch 125-200 */
+	{3, 1}			/* group 4 2.4, ch   all */
+};
+
+static s32 get_min_power_index(s32 rate_power_index, u32 band)
+{
+	if (!band) {
+		if ((rate_power_index & 7) <= 4)
+			return MIN_TX_GAIN_INDEX_52GHZ_EXT;
+	}
+	return MIN_TX_GAIN_INDEX;
+}
+
+struct gain_entry {
+	u8 dsp;
+	u8 radio;
+};
+
+static const struct gain_entry gain_table[2][108] = {
+	/* 5.2GHz power gain index table */
+	{
+	 {123, 0x3F},		/* highest txpower */
+	 {117, 0x3F},
+	 {110, 0x3F},
+	 {104, 0x3F},
+	 {98, 0x3F},
+	 {110, 0x3E},
+	 {104, 0x3E},
+	 {98, 0x3E},
+	 {110, 0x3D},
+	 {104, 0x3D},
+	 {98, 0x3D},
+	 {110, 0x3C},
+	 {104, 0x3C},
+	 {98, 0x3C},
+	 {110, 0x3B},
+	 {104, 0x3B},
+	 {98, 0x3B},
+	 {110, 0x3A},
+	 {104, 0x3A},
+	 {98, 0x3A},
+	 {110, 0x39},
+	 {104, 0x39},
+	 {98, 0x39},
+	 {110, 0x38},
+	 {104, 0x38},
+	 {98, 0x38},
+	 {110, 0x37},
+	 {104, 0x37},
+	 {98, 0x37},
+	 {110, 0x36},
+	 {104, 0x36},
+	 {98, 0x36},
+	 {110, 0x35},
+	 {104, 0x35},
+	 {98, 0x35},
+	 {110, 0x34},
+	 {104, 0x34},
+	 {98, 0x34},
+	 {110, 0x33},
+	 {104, 0x33},
+	 {98, 0x33},
+	 {110, 0x32},
+	 {104, 0x32},
+	 {98, 0x32},
+	 {110, 0x31},
+	 {104, 0x31},
+	 {98, 0x31},
+	 {110, 0x30},
+	 {104, 0x30},
+	 {98, 0x30},
+	 {110, 0x25},
+	 {104, 0x25},
+	 {98, 0x25},
+	 {110, 0x24},
+	 {104, 0x24},
+	 {98, 0x24},
+	 {110, 0x23},
+	 {104, 0x23},
+	 {98, 0x23},
+	 {110, 0x22},
+	 {104, 0x18},
+	 {98, 0x18},
+	 {110, 0x17},
+	 {104, 0x17},
+	 {98, 0x17},
+	 {110, 0x16},
+	 {104, 0x16},
+	 {98, 0x16},
+	 {110, 0x15},
+	 {104, 0x15},
+	 {98, 0x15},
+	 {110, 0x14},
+	 {104, 0x14},
+	 {98, 0x14},
+	 {110, 0x13},
+	 {104, 0x13},
+	 {98, 0x13},
+	 {110, 0x12},
+	 {104, 0x08},
+	 {98, 0x08},
+	 {110, 0x07},
+	 {104, 0x07},
+	 {98, 0x07},
+	 {110, 0x06},
+	 {104, 0x06},
+	 {98, 0x06},
+	 {110, 0x05},
+	 {104, 0x05},
+	 {98, 0x05},
+	 {110, 0x04},
+	 {104, 0x04},
+	 {98, 0x04},
+	 {110, 0x03},
+	 {104, 0x03},
+	 {98, 0x03},
+	 {110, 0x02},
+	 {104, 0x02},
+	 {98, 0x02},
+	 {110, 0x01},
+	 {104, 0x01},
+	 {98, 0x01},
+	 {110, 0x00},
+	 {104, 0x00},
+	 {98, 0x00},
+	 {93, 0x00},
+	 {88, 0x00},
+	 {83, 0x00},
+	 {78, 0x00},
+	 },
+	/* 2.4GHz power gain index table */
+	{
+	 {110, 0x3f},		/* highest txpower */
+	 {104, 0x3f},
+	 {98, 0x3f},
+	 {110, 0x3e},
+	 {104, 0x3e},
+	 {98, 0x3e},
+	 {110, 0x3d},
+	 {104, 0x3d},
+	 {98, 0x3d},
+	 {110, 0x3c},
+	 {104, 0x3c},
+	 {98, 0x3c},
+	 {110, 0x3b},
+	 {104, 0x3b},
+	 {98, 0x3b},
+	 {110, 0x3a},
+	 {104, 0x3a},
+	 {98, 0x3a},
+	 {110, 0x39},
+	 {104, 0x39},
+	 {98, 0x39},
+	 {110, 0x38},
+	 {104, 0x38},
+	 {98, 0x38},
+	 {110, 0x37},
+	 {104, 0x37},
+	 {98, 0x37},
+	 {110, 0x36},
+	 {104, 0x36},
+	 {98, 0x36},
+	 {110, 0x35},
+	 {104, 0x35},
+	 {98, 0x35},
+	 {110, 0x34},
+	 {104, 0x34},
+	 {98, 0x34},
+	 {110, 0x33},
+	 {104, 0x33},
+	 {98, 0x33},
+	 {110, 0x32},
+	 {104, 0x32},
+	 {98, 0x32},
+	 {110, 0x31},
+	 {104, 0x31},
+	 {98, 0x31},
+	 {110, 0x30},
+	 {104, 0x30},
+	 {98, 0x30},
+	 {110, 0x6},
+	 {104, 0x6},
+	 {98, 0x6},
+	 {110, 0x5},
+	 {104, 0x5},
+	 {98, 0x5},
+	 {110, 0x4},
+	 {104, 0x4},
+	 {98, 0x4},
+	 {110, 0x3},
+	 {104, 0x3},
+	 {98, 0x3},
+	 {110, 0x2},
+	 {104, 0x2},
+	 {98, 0x2},
+	 {110, 0x1},
+	 {104, 0x1},
+	 {98, 0x1},
+	 {110, 0x0},
+	 {104, 0x0},
+	 {98, 0x0},
+	 {97, 0},
+	 {96, 0},
+	 {95, 0},
+	 {94, 0},
+	 {93, 0},
+	 {92, 0},
+	 {91, 0},
+	 {90, 0},
+	 {89, 0},
+	 {88, 0},
+	 {87, 0},
+	 {86, 0},
+	 {85, 0},
+	 {84, 0},
+	 {83, 0},
+	 {82, 0},
+	 {81, 0},
+	 {80, 0},
+	 {79, 0},
+	 {78, 0},
+	 {77, 0},
+	 {76, 0},
+	 {75, 0},
+	 {74, 0},
+	 {73, 0},
+	 {72, 0},
+	 {71, 0},
+	 {70, 0},
+	 {69, 0},
+	 {68, 0},
+	 {67, 0},
+	 {66, 0},
+	 {65, 0},
+	 {64, 0},
+	 {63, 0},
+	 {62, 0},
+	 {61, 0},
+	 {60, 0},
+	 {59, 0},
+	 }
+};
+
+static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
+				    u8 is_ht40, u8 ctrl_chan_high,
+				    struct iwl4965_tx_power_db *tx_power_tbl)
+{
+	u8 saturation_power;
+	s32 target_power;
+	s32 user_target_power;
+	s32 power_limit;
+	s32 current_temp;
+	s32 reg_limit;
+	s32 current_regulatory;
+	s32 txatten_grp = CALIB_CH_GROUP_MAX;
+	int i;
+	int c;
+	const struct iwl_channel_info *ch_info = NULL;
+	struct iwl_eeprom_calib_ch_info ch_eeprom_info;
+	const struct iwl_eeprom_calib_measure *measurement;
+	s16 voltage;
+	s32 init_voltage;
+	s32 voltage_compensation;
+	s32 degrees_per_05db_num;
+	s32 degrees_per_05db_denom;
+	s32 factory_temp;
+	s32 temperature_comp[2];
+	s32 factory_gain_index[2];
+	s32 factory_actual_pwr[2];
+	s32 power_index;
+
+	/* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
+	 *   are used for indexing into txpower table) */
+	user_target_power = 2 * priv->tx_power_user_lmt;
+
+	/* Get current (RXON) channel, band, width */
+	IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
+			  is_ht40);
+
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band, channel);
+
+	if (!iwl_legacy_is_channel_valid(ch_info))
+		return -EINVAL;
+
+	/* get txatten group, used to select 1) thermal txpower adjustment
+	 *   and 2) mimo txpower balance between Tx chains. */
+	txatten_grp = iwl4965_get_tx_atten_grp(channel);
+	if (txatten_grp < 0) {
+		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
+			  channel);
+		return -EINVAL;
+	}
+
+	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
+			  channel, txatten_grp);
+
+	if (is_ht40) {
+		if (ctrl_chan_high)
+			channel -= 2;
+		else
+			channel += 2;
+	}
+
+	/* hardware txpower limits ...
+	 * saturation (clipping distortion) txpowers are in half-dBm */
+	if (band)
+		saturation_power = priv->calib_info->saturation_power24;
+	else
+		saturation_power = priv->calib_info->saturation_power52;
+
+	if (saturation_power < IWL_TX_POWER_SATURATION_MIN ||
+	    saturation_power > IWL_TX_POWER_SATURATION_MAX) {
+		if (band)
+			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24;
+		else
+			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52;
+	}
+
+	/* regulatory txpower limits ... reg_limit values are in half-dBm,
+	 *   max_power_avg values are in dBm, convert * 2 */
+	if (is_ht40)
+		reg_limit = ch_info->ht40_max_power_avg * 2;
+	else
+		reg_limit = ch_info->max_power_avg * 2;
+
+	if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) ||
+	    (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) {
+		if (band)
+			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24;
+		else
+			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52;
+	}
+
+	/* Interpolate txpower calibration values for this channel,
+	 *   based on factory calibration tests on spaced channels. */
+	iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
+
+	/* calculate tx gain adjustment based on power supply voltage */
+	voltage = le16_to_cpu(priv->calib_info->voltage);
+	init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
+	voltage_compensation =
+	    iwl4965_get_voltage_compensation(voltage, init_voltage);
+
+	IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n",
+			  init_voltage,
+			  voltage, voltage_compensation);
+
+	/* get current temperature (Celsius) */
+	current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN);
+	current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX);
+	current_temp = KELVIN_TO_CELSIUS(current_temp);
+
+	/* select thermal txpower adjustment params, based on channel group
+	 *   (same frequency group used for mimo txatten adjustment) */
+	degrees_per_05db_num =
+	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
+	degrees_per_05db_denom =
+	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
+
+	/* get per-chain txpower values from factory measurements */
+	for (c = 0; c < 2; c++) {
+		measurement = &ch_eeprom_info.measurements[c][1];
+
+		/* txgain adjustment (in half-dB steps) based on difference
+		 *   between factory and current temperature */
+		factory_temp = measurement->temperature;
+		iwl4965_math_div_round((current_temp - factory_temp) *
+				       degrees_per_05db_denom,
+				       degrees_per_05db_num,
+				       &temperature_comp[c]);
+
+		factory_gain_index[c] = measurement->gain_idx;
+		factory_actual_pwr[c] = measurement->actual_pow;
+
+		IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c);
+		IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, "
+				  "curr tmp %d, comp %d steps\n",
+				  factory_temp, current_temp,
+				  temperature_comp[c]);
+
+		IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n",
+				  factory_gain_index[c],
+				  factory_actual_pwr[c]);
+	}
+
+	/* for each of 33 bit-rates (including 1 for CCK) */
+	for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
+		u8 is_mimo_rate;
+		union iwl4965_tx_power_dual_stream tx_power;
+
+		/* for mimo, reduce each chain's txpower by half
+		 * (3dB, 6 steps), so total output power is regulatory
+		 * compliant. */
+		if (i & 0x8) {
+			current_regulatory = reg_limit -
+			    IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
+			is_mimo_rate = 1;
+		} else {
+			current_regulatory = reg_limit;
+			is_mimo_rate = 0;
+		}
+
+		/* find txpower limit, either hardware or regulatory */
+		power_limit = saturation_power - back_off_table[i];
+		if (power_limit > current_regulatory)
+			power_limit = current_regulatory;
+
+		/* reduce user's txpower request if necessary
+		 * for this rate on this channel */
+		target_power = user_target_power;
+		if (target_power > power_limit)
+			target_power = power_limit;
+
+		IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n",
+				  i, saturation_power - back_off_table[i],
+				  current_regulatory, user_target_power,
+				  target_power);
+
+		/* for each of 2 Tx chains (radio transmitters) */
+		for (c = 0; c < 2; c++) {
+			s32 atten_value;
+
+			if (is_mimo_rate)
+				atten_value =
+				    (s32)le32_to_cpu(priv->card_alive_init.
+				    tx_atten[txatten_grp][c]);
+			else
+				atten_value = 0;
+
+			/* calculate index; higher index means lower txpower */
+			power_index = (u8) (factory_gain_index[c] -
+					    (target_power -
+					     factory_actual_pwr[c]) -
+					    temperature_comp[c] -
+					    voltage_compensation +
+					    atten_value);
+
+/*			IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n",
+						power_index); */
+
+			if (power_index < get_min_power_index(i, band))
+				power_index = get_min_power_index(i, band);
+
+			/* adjust 5 GHz index to support negative indexes */
+			if (!band)
+				power_index += 9;
+
+			/* CCK, rate 32, reduce txpower for CCK */
+			if (i == POWER_TABLE_CCK_ENTRY)
+				power_index +=
+				    IWL_TX_POWER_CCK_COMPENSATION_C_STEP;
+
+			/* stay within the table! */
+			if (power_index > 107) {
+				IWL_WARN(priv, "txpower index %d > 107\n",
+					    power_index);
+				power_index = 107;
+			}
+			if (power_index < 0) {
+				IWL_WARN(priv, "txpower index %d < 0\n",
+					    power_index);
+				power_index = 0;
+			}
+
+			/* fill txpower command for this rate/chain */
+			tx_power.s.radio_tx_gain[c] =
+				gain_table[band][power_index].radio;
+			tx_power.s.dsp_predis_atten[c] =
+				gain_table[band][power_index].dsp;
+
+			IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d "
+					  "gain 0x%02x dsp %d\n",
+					  c, atten_value, power_index,
+					tx_power.s.radio_tx_gain[c],
+					tx_power.s.dsp_predis_atten[c]);
+		} /* for each chain */
+
+		tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
+
+	} /* for each rate */
+
+	return 0;
+}
+
+/**
+ * iwl4965_send_tx_power - Configure the TXPOWER level user limit
+ *
+ * Uses the active RXON for channel, band, and characteristics (ht40, high)
+ * The power limit is taken from priv->tx_power_user_lmt.
+ */
+static int iwl4965_send_tx_power(struct iwl_priv *priv)
+{
+	struct iwl4965_txpowertable_cmd cmd = { 0 };
+	int ret;
+	u8 band = 0;
+	bool is_ht40 = false;
+	u8 ctrl_chan_high = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
+	band = priv->band == IEEE80211_BAND_2GHZ;
+
+	is_ht40 = iw4965_is_ht40_channel(ctx->active.flags);
+
+	if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+		ctrl_chan_high = 1;
+
+	cmd.band = band;
+	cmd.channel = ctx->active.channel;
+
+	ret = iwl4965_fill_txpower_tbl(priv, band,
+				le16_to_cpu(ctx->active.channel),
+				is_ht40, ctrl_chan_high, &cmd.tx_power);
+	if (ret)
+		goto out;
+
+	ret = iwl_legacy_send_cmd_pdu(priv,
+			 REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
+
+out:
+	return ret;
+}
+
+static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
+{
+	int ret = 0;
+	struct iwl4965_rxon_assoc_cmd rxon_assoc;
+	const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
+	const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
+
+	if ((rxon1->flags == rxon2->flags) &&
+	    (rxon1->filter_flags == rxon2->filter_flags) &&
+	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+	    (rxon1->ofdm_ht_single_stream_basic_rates ==
+	     rxon2->ofdm_ht_single_stream_basic_rates) &&
+	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
+	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
+	    (rxon1->rx_chain == rxon2->rx_chain) &&
+	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
+		return 0;
+	}
+
+	rxon_assoc.flags = ctx->staging.flags;
+	rxon_assoc.filter_flags = ctx->staging.filter_flags;
+	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
+	rxon_assoc.reserved = 0;
+	rxon_assoc.ofdm_ht_single_stream_basic_rates =
+	    ctx->staging.ofdm_ht_single_stream_basic_rates;
+	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
+	    ctx->staging.ofdm_ht_dual_stream_basic_rates;
+	rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
+
+	ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
+				     sizeof(rxon_assoc), &rxon_assoc, NULL);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl_legacy_rxon_cmd *active_rxon = (void *)&ctx->active;
+	int ret;
+	bool new_assoc =
+		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EBUSY;
+
+	if (!ctx->is_active)
+		return 0;
+
+	/* always get timestamp with Rx frame */
+	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+	ret = iwl_legacy_check_rxon_cmd(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * receive commit_rxon request
+	 * abort any previous channel switch if still in process
+	 */
+	if (priv->switch_rxon.switch_in_progress &&
+	    (priv->switch_rxon.channel != ctx->staging.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		iwl_legacy_chswitch_done(priv, false);
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_legacy_full_rxon_required(priv, ctx)) {
+		ret = iwl_legacy_send_rxon_assoc(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
+			return ret;
+		}
+
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_legacy_print_rx_config_cmd(priv, ctx);
+		return 0;
+	}
+
+	/* If we are currently associated and the new config requires
+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
+	 * we must clear the associated from the active configuration
+	 * before we apply the new config */
+	if (iwl_legacy_is_associated_ctx(ctx) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
+				       sizeof(struct iwl_legacy_rxon_cmd),
+				       active_rxon);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (ret) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
+			return ret;
+		}
+		iwl_legacy_clear_ucode_stations(priv, ctx);
+		iwl_legacy_restore_stations(priv, ctx);
+		ret = iwl4965_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "Sending RXON\n"
+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
+		       "* channel = %d\n"
+		       "* bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
+
+	iwl_legacy_set_rxon_hwcrypto(priv, ctx,
+				!priv->cfg->mod_params->sw_crypto);
+
+	/* Apply the new configuration
+	 * RXON unassoc clears the station table in uCode so restoration of
+	 * stations is needed after it (the RXON command) completes
+	 */
+	if (!new_assoc) {
+		ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_legacy_clear_ucode_stations(priv, ctx);
+		iwl_legacy_restore_stations(priv, ctx);
+		ret = iwl4965_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+	if (new_assoc) {
+		priv->start_calib = 0;
+		/* Apply the new configuration
+		 * RXON assoc doesn't clear the station table in uCode,
+		 */
+		ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+	}
+	iwl_legacy_print_rx_config_cmd(priv, ctx);
+
+	iwl4965_init_sensitivity(priv);
+
+	/* If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames */
+	ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
+	if (ret) {
+		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
+				     struct ieee80211_channel_switch *ch_switch)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	int rc;
+	u8 band = 0;
+	bool is_ht40 = false;
+	u8 ctrl_chan_high = 0;
+	struct iwl4965_channel_switch_cmd cmd;
+	const struct iwl_channel_info *ch_info;
+	u32 switch_time_in_usec, ucode_switch_time;
+	u16 ch;
+	u32 tsf_low;
+	u8 switch_count;
+	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+	struct ieee80211_vif *vif = ctx->vif;
+	band = priv->band == IEEE80211_BAND_2GHZ;
+
+	is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags);
+
+	if (is_ht40 &&
+	    (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+		ctrl_chan_high = 1;
+
+	cmd.band = band;
+	cmd.expect_beacon = 0;
+	ch = ch_switch->channel->hw_value;
+	cmd.channel = cpu_to_le16(ch);
+	cmd.rxon_flags = ctx->staging.flags;
+	cmd.rxon_filter_flags = ctx->staging.filter_flags;
+	switch_count = ch_switch->count;
+	tsf_low = ch_switch->timestamp & 0x0ffffffff;
+	/*
+	 * calculate the ucode channel switch time
+	 * adding TSF as one of the factor for when to switch
+	 */
+	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
+		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
+		    beacon_interval)) {
+			switch_count -= (priv->ucode_beacon_time -
+				tsf_low) / beacon_interval;
+		} else
+			switch_count = 0;
+	}
+	if (switch_count <= 1)
+		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+	else {
+		switch_time_in_usec =
+			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+		ucode_switch_time = iwl_legacy_usecs_to_beacons(priv,
+							 switch_time_in_usec,
+							 beacon_interval);
+		cmd.switch_time = iwl_legacy_add_beacon_time(priv,
+						      priv->ucode_beacon_time,
+						      ucode_switch_time,
+						      beacon_interval);
+	}
+	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
+		      cmd.switch_time);
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band, ch);
+	if (ch_info)
+		cmd.expect_beacon = iwl_legacy_is_channel_radar(ch_info);
+	else {
+		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
+			ctx->active.channel, ch);
+		return -EFAULT;
+	}
+
+	rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
+				      ctrl_chan_high, &cmd.tx_power);
+	if (rc) {
+		IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
+		return rc;
+	}
+
+	priv->switch_rxon.channel = cmd.channel;
+	priv->switch_rxon.switch_in_progress = true;
+
+	return iwl_legacy_send_cmd_pdu(priv,
+			 REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+}
+
+/**
+ * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+					    struct iwl_tx_queue *txq,
+					    u16 byte_cnt)
+{
+	struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+	int txq_id = txq->q.id;
+	int write_ptr = txq->q.write_ptr;
+	int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	__le16 bc_ent;
+
+	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
+
+	bc_ent = cpu_to_le16(len & 0xFFF);
+	/* Set up byte count within first 256 entries */
+	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+
+	/* If within first 64 entries, duplicate at end */
+	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		scd_bc_tbl[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
+}
+
+/**
+ * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
+ * @statistics: Provides the temperature reading from the uCode
+ *
+ * A return of <0 indicates bogus data in the statistics
+ */
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
+{
+	s32 temperature;
+	s32 vt;
+	s32 R1, R2, R3;
+	u32 R4;
+
+	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
+	    (priv->_4965.statistics.flag &
+			STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
+		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
+		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
+		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
+		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]);
+	} else {
+		IWL_DEBUG_TEMP(priv, "Running temperature calibration\n");
+		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]);
+		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]);
+		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]);
+		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]);
+	}
+
+	/*
+	 * Temperature is only 23 bits, so sign extend out to 32.
+	 *
+	 * NOTE If we haven't received a statistics notification yet
+	 * with an updated temperature, use R4 provided to us in the
+	 * "initialize" ALIVE response.
+	 */
+	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
+		vt = sign_extend32(R4, 23);
+	else
+		vt = sign_extend32(le32_to_cpu(priv->_4965.statistics.
+				 general.common.temperature), 23);
+
+	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
+
+	if (R3 == R1) {
+		IWL_ERR(priv, "Calibration conflict R1 == R3\n");
+		return -1;
+	}
+
+	/* Calculate temperature in degrees Kelvin, adjust by 97%.
+	 * Add offset to center the adjustment around 0 degrees Centigrade. */
+	temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
+	temperature /= (R3 - R1);
+	temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
+
+	IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n",
+			temperature, KELVIN_TO_CELSIUS(temperature));
+
+	return temperature;
+}
+
+/* Adjust Txpower only if temperature variance is greater than threshold. */
+#define IWL_TEMPERATURE_THRESHOLD   3
+
+/**
+ * iwl4965_is_temp_calib_needed - determines if new calibration is needed
+ *
+ * If the temperature changed has changed sufficiently, then a recalibration
+ * is needed.
+ *
+ * Assumes caller will replace priv->last_temperature once calibration
+ * executed.
+ */
+static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
+{
+	int temp_diff;
+
+	if (!test_bit(STATUS_STATISTICS, &priv->status)) {
+		IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n");
+		return 0;
+	}
+
+	temp_diff = priv->temperature - priv->last_temperature;
+
+	/* get absolute value */
+	if (temp_diff < 0) {
+		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
+		temp_diff = -temp_diff;
+	} else if (temp_diff == 0)
+		IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
+	else
+		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
+
+	if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
+		IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
+		return 0;
+	}
+
+	IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
+
+	return 1;
+}
+
+static void iwl4965_temperature_calib(struct iwl_priv *priv)
+{
+	s32 temp;
+
+	temp = iwl4965_hw_get_temperature(priv);
+	if (temp < 0)
+		return;
+
+	if (priv->temperature != temp) {
+		if (priv->temperature)
+			IWL_DEBUG_TEMP(priv, "Temperature changed "
+				       "from %dC to %dC\n",
+				       KELVIN_TO_CELSIUS(priv->temperature),
+				       KELVIN_TO_CELSIUS(temp));
+		else
+			IWL_DEBUG_TEMP(priv, "Temperature "
+				       "initialized to %dC\n",
+				       KELVIN_TO_CELSIUS(temp));
+	}
+
+	priv->temperature = temp;
+	set_bit(STATUS_TEMPERATURE, &priv->status);
+
+	if (!priv->disable_tx_power_cal &&
+	     unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	     iwl4965_is_temp_calib_needed(priv))
+		queue_work(priv->workqueue, &priv->txpower_work);
+}
+
+static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
+{
+	switch (cmd_id) {
+	case REPLY_RXON:
+		return (u16) sizeof(struct iwl4965_rxon_cmd);
+	default:
+		return len;
+	}
+}
+
+static u16 iwl4965_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
+								u8 *data)
+{
+	struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data;
+	addsta->mode = cmd->mode;
+	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
+	memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
+	addsta->station_flags = cmd->station_flags;
+	addsta->station_flags_msk = cmd->station_flags_msk;
+	addsta->tid_disable_tx = cmd->tid_disable_tx;
+	addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
+	addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
+	addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
+	addsta->sleep_tx_count = cmd->sleep_tx_count;
+	addsta->reserved1 = cpu_to_le16(0);
+	addsta->reserved2 = cpu_to_le16(0);
+
+	return (u16)sizeof(struct iwl4965_addsta_cmd);
+}
+
+static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
+{
+	return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
+}
+
+/**
+ * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
+ */
+static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
+				      struct iwl_ht_agg *agg,
+				      struct iwl4965_tx_resp *tx_resp,
+				      int txq_id, u16 start_idx)
+{
+	u16 status;
+	struct agg_tx_status *frame_status = tx_resp->u.agg_status;
+	struct ieee80211_tx_info *info = NULL;
+	struct ieee80211_hdr *hdr = NULL;
+	u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+	int i, sh, idx;
+	u16 seq;
+	if (agg->wait_for_ba)
+		IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
+
+	agg->frame_count = tx_resp->frame_count;
+	agg->start_idx = start_idx;
+	agg->rate_n_flags = rate_n_flags;
+	agg->bitmap = 0;
+
+	/* num frames attempted by Tx command */
+	if (agg->frame_count == 1) {
+		/* Only one frame was attempted; no block-ack will arrive */
+		status = le16_to_cpu(frame_status[0].status);
+		idx = start_idx;
+
+		IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
+				   agg->frame_count, agg->start_idx, idx);
+
+		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
+		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+		info->flags |= iwl4965_tx_status_to_mac80211(status);
+		iwl4965_hwrate_to_tx_control(priv, rate_n_flags, info);
+
+		IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
+				    status & 0xff, tx_resp->failure_frame);
+		IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
+
+		agg->wait_for_ba = 0;
+	} else {
+		/* Two or more frames were attempted; expect block-ack */
+		u64 bitmap = 0;
+		int start = agg->start_idx;
+
+		/* Construct bit-map of pending frames within Tx window */
+		for (i = 0; i < agg->frame_count; i++) {
+			u16 sc;
+			status = le16_to_cpu(frame_status[i].status);
+			seq  = le16_to_cpu(frame_status[i].sequence);
+			idx = SEQ_TO_INDEX(seq);
+			txq_id = SEQ_TO_QUEUE(seq);
+
+			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
+				      AGG_TX_STATE_ABORT_MSK))
+				continue;
+
+			IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
+					   agg->frame_count, txq_id, idx);
+
+			hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, idx);
+			if (!hdr) {
+				IWL_ERR(priv,
+					"BUG_ON idx doesn't point to valid skb"
+					" idx=%d, txq_id=%d\n", idx, txq_id);
+				return -1;
+			}
+
+			sc = le16_to_cpu(hdr->seq_ctrl);
+			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+				IWL_ERR(priv,
+					"BUG_ON idx doesn't match seq control"
+					" idx=%d, seq_idx=%d, seq=%d\n",
+					idx, SEQ_TO_SN(sc), hdr->seq_ctrl);
+				return -1;
+			}
+
+			IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
+					   i, idx, SEQ_TO_SN(sc));
+
+			sh = idx - start;
+			if (sh > 64) {
+				sh = (start - idx) + 0xff;
+				bitmap = bitmap << sh;
+				sh = 0;
+				start = idx;
+			} else if (sh < -64)
+				sh  = 0xff - (start - idx);
+			else if (sh < 0) {
+				sh = start - idx;
+				start = idx;
+				bitmap = bitmap << sh;
+				sh = 0;
+			}
+			bitmap |= 1ULL << sh;
+			IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
+					   start, (unsigned long long)bitmap);
+		}
+
+		agg->bitmap = bitmap;
+		agg->start_idx = start;
+		IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
+				   agg->frame_count, agg->start_idx,
+				   (unsigned long long)agg->bitmap);
+
+		if (bitmap)
+			agg->wait_for_ba = 1;
+	}
+	return 0;
+}
+
+static u8 iwl4965_find_station(struct iwl_priv *priv, const u8 *addr)
+{
+	int i;
+	int start = 0;
+	int ret = IWL_INVALID_STATION;
+	unsigned long flags;
+
+	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC))
+		start = IWL_STA_ID;
+
+	if (is_broadcast_ether_addr(addr))
+		return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	for (i = start; i < priv->hw_params.max_stations; i++)
+		if (priv->stations[i].used &&
+		    (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+					 addr))) {
+			ret = i;
+			goto out;
+		}
+
+	IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
+			      addr, priv->num_stations);
+
+ out:
+	/*
+	 * It may be possible that more commands interacting with stations
+	 * arrive before we completed processing the adding of
+	 * station
+	 */
+	if (ret != IWL_INVALID_STATION &&
+	    (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
+	     ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
+	      (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
+		IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
+			ret);
+		ret = IWL_INVALID_STATION;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	return ret;
+}
+
+static int iwl4965_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+{
+	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
+		return IWL_AP_ID;
+	} else {
+		u8 *da = ieee80211_get_DA(hdr);
+		return iwl4965_find_station(priv, da);
+	}
+}
+
+/**
+ * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
+ */
+static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_tx_info *info;
+	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	u32  status = le32_to_cpu(tx_resp->u.status);
+	int uninitialized_var(tid);
+	int sta_id;
+	int freed;
+	u8 *qc = NULL;
+	unsigned long flags;
+
+	if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
+			  "is out of range [0-%d] %d %d\n", txq_id,
+			  index, txq->q.n_bd, txq->q.write_ptr,
+			  txq->q.read_ptr);
+		return;
+	}
+
+	txq->time_stamp = jiffies;
+	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+	memset(&info->status, 0, sizeof(info->status));
+
+	hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, index);
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & 0xf;
+	}
+
+	sta_id = iwl4965_get_ra_sta_id(priv, hdr);
+	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
+		IWL_ERR(priv, "Station not known\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	if (txq->sched_retry) {
+		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
+		struct iwl_ht_agg *agg = NULL;
+		WARN_ON(!qc);
+
+		agg = &priv->stations[sta_id].tid[tid].agg;
+
+		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
+
+		/* check if BAR is needed */
+		if ((tx_resp->frame_count == 1) && !iwl4965_is_tx_success(status))
+			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+
+		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
+			index = iwl_legacy_queue_dec_wrap(scd_ssn & 0xff,
+								txq->q.n_bd);
+			IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
+					   "%d index %d\n", scd_ssn , index);
+			freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+			if (qc)
+				iwl4965_free_tfds_in_queue(priv, sta_id,
+						       tid, freed);
+
+			if (priv->mac80211_registered &&
+			    (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark)
+				 && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+				iwl_legacy_wake_queue(priv, txq);
+		}
+	} else {
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
+		info->flags |= iwl4965_tx_status_to_mac80211(status);
+		iwl4965_hwrate_to_tx_control(priv,
+					le32_to_cpu(tx_resp->rate_n_flags),
+					info);
+
+		IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) "
+				   "rate_n_flags 0x%x retries %d\n",
+				   txq_id,
+				   iwl4965_get_tx_fail_reason(status), status,
+				   le32_to_cpu(tx_resp->rate_n_flags),
+				   tx_resp->failure_frame);
+
+		freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+		if (qc && likely(sta_id != IWL_INVALID_STATION))
+			iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
+		else if (sta_id == IWL_INVALID_STATION)
+			IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
+
+		if (priv->mac80211_registered &&
+		    (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark))
+			iwl_legacy_wake_queue(priv, txq);
+	}
+	if (qc && likely(sta_id != IWL_INVALID_STATION))
+		iwl4965_txq_check_empty(priv, sta_id, tid, txq_id);
+
+	iwl4965_check_abort_status(priv, tx_resp->frame_count, status);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
+static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw;
+	u8 rate __maybe_unused =
+		iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+	IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
+		"tsf:0x%.8x%.8x rate:%d\n",
+		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+}
+
+/* Set up 4965-specific Rx frame reply handlers */
+static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
+{
+	/* Legacy Rx frames */
+	priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
+	/* Tx response */
+	priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+}
+
+static struct iwl_hcmd_ops iwl4965_hcmd = {
+	.rxon_assoc = iwl4965_send_rxon_assoc,
+	.commit_rxon = iwl4965_commit_rxon,
+	.set_rxon_chain = iwl4965_set_rxon_chain,
+};
+
+static void iwl4965_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+		iwl_legacy_commit_rxon(priv, ctx);
+}
+
+static void iwl4965_post_associate(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	struct ieee80211_conf *conf = NULL;
+	int ret = 0;
+
+	if (!vif || !priv->is_open)
+		return;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
+
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	ret = iwl_legacy_send_rxon_timing(priv, ctx);
+	if (ret)
+		IWL_WARN(priv, "RXON timing - "
+			    "Attempting to continue.\n");
+
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+	iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+
+	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
+			vif->bss_conf.aid, vif->bss_conf.beacon_int);
+
+	if (vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+		if (vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+	}
+
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
+			vif->bss_conf.aid, ctx->active.bssid_addr);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwl4965_send_beacon_cmd(priv);
+		break;
+	default:
+		IWL_ERR(priv, "%s Should not be called in %d mode\n",
+			  __func__, vif->type);
+		break;
+	}
+
+	/* the chain noise calibration will enabled PM upon completion
+	 * If chain noise has already been run, then we need to enable
+	 * power management here */
+	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
+		iwl_legacy_power_update_mode(priv, false);
+
+	/* Enable Rx differential gain and sensitivity calibrations */
+	iwl4965_chain_noise_reset(priv);
+	priv->start_calib = 1;
+}
+
+static void iwl4965_config_ap(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	int ret = 0;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* The following should be done only at AP bring up */
+	if (!iwl_legacy_is_associated_ctx(ctx)) {
+
+		/* RXON - unassoc (to set timing command) */
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwl_legacy_commit_rxon(priv, ctx);
+
+		/* RXON Timing */
+		ret = iwl_legacy_send_rxon_timing(priv, ctx);
+		if (ret)
+			IWL_WARN(priv, "RXON timing failed - "
+					"Attempting to continue.\n");
+
+		/* AP has all antennas */
+		priv->chain_noise_data.active_chains =
+			priv->hw_params.valid_rx_ant;
+		iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+		ctx->staging.assoc_id = 0;
+
+		if (vif->bss_conf.use_short_preamble)
+			ctx->staging.flags |=
+				RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &=
+				~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+			if (vif->bss_conf.use_short_slot)
+				ctx->staging.flags |=
+					RXON_FLG_SHORT_SLOT_MSK;
+			else
+				ctx->staging.flags &=
+					~RXON_FLG_SHORT_SLOT_MSK;
+		}
+		/* need to send beacon cmd before committing assoc RXON! */
+		iwl4965_send_beacon_cmd(priv);
+		/* restore RXON assoc */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwl_legacy_commit_rxon(priv, ctx);
+	}
+	iwl4965_send_beacon_cmd(priv);
+}
+
+static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
+	.get_hcmd_size = iwl4965_get_hcmd_size,
+	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
+	.request_scan = iwl4965_request_scan,
+	.post_scan = iwl4965_post_scan,
+};
+
+static struct iwl_lib_ops iwl4965_lib = {
+	.set_hw_params = iwl4965_hw_set_hw_params,
+	.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
+	.txq_attach_buf_to_tfd = iwl4965_hw_txq_attach_buf_to_tfd,
+	.txq_free_tfd = iwl4965_hw_txq_free_tfd,
+	.txq_init = iwl4965_hw_tx_queue_init,
+	.rx_handler_setup = iwl4965_rx_handler_setup,
+	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
+	.init_alive_start = iwl4965_init_alive_start,
+	.load_ucode = iwl4965_load_bsm,
+	.dump_nic_event_log = iwl4965_dump_nic_event_log,
+	.dump_nic_error_log = iwl4965_dump_nic_error_log,
+	.dump_fh = iwl4965_dump_fh,
+	.set_channel_switch = iwl4965_hw_channel_switch,
+	.apm_ops = {
+		.init = iwl_legacy_apm_init,
+		.config = iwl4965_nic_config,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REGULATORY_BAND_1_CHANNELS,
+			EEPROM_REGULATORY_BAND_2_CHANNELS,
+			EEPROM_REGULATORY_BAND_3_CHANNELS,
+			EEPROM_REGULATORY_BAND_4_CHANNELS,
+			EEPROM_REGULATORY_BAND_5_CHANNELS,
+			EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
+			EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
+		},
+		.acquire_semaphore = iwl4965_eeprom_acquire_semaphore,
+		.release_semaphore = iwl4965_eeprom_release_semaphore,
+	},
+	.send_tx_power	= iwl4965_send_tx_power,
+	.update_chain_flags = iwl4965_update_chain_flags,
+	.temp_ops = {
+		.temperature = iwl4965_temperature_calib,
+	},
+	.debugfs_ops = {
+		.rx_stats_read = iwl4965_ucode_rx_stats_read,
+		.tx_stats_read = iwl4965_ucode_tx_stats_read,
+		.general_stats_read = iwl4965_ucode_general_stats_read,
+	},
+	.check_plcp_health = iwl4965_good_plcp_health,
+};
+
+static const struct iwl_legacy_ops iwl4965_legacy_ops = {
+	.post_associate = iwl4965_post_associate,
+	.config_ap = iwl4965_config_ap,
+	.manage_ibss_station = iwl4965_manage_ibss_station,
+	.update_bcast_stations = iwl4965_update_bcast_stations,
+};
+
+struct ieee80211_ops iwl4965_hw_ops = {
+	.tx = iwl4965_mac_tx,
+	.start = iwl4965_mac_start,
+	.stop = iwl4965_mac_stop,
+	.add_interface = iwl_legacy_mac_add_interface,
+	.remove_interface = iwl_legacy_mac_remove_interface,
+	.change_interface = iwl_legacy_mac_change_interface,
+	.config = iwl_legacy_mac_config,
+	.configure_filter = iwl4965_configure_filter,
+	.set_key = iwl4965_mac_set_key,
+	.update_tkip_key = iwl4965_mac_update_tkip_key,
+	.conf_tx = iwl_legacy_mac_conf_tx,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
+	.ampdu_action = iwl4965_mac_ampdu_action,
+	.hw_scan = iwl_legacy_mac_hw_scan,
+	.sta_add = iwl4965_mac_sta_add,
+	.sta_remove = iwl_legacy_mac_sta_remove,
+	.channel_switch = iwl4965_mac_channel_switch,
+	.tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
+};
+
+static const struct iwl_ops iwl4965_ops = {
+	.lib = &iwl4965_lib,
+	.hcmd = &iwl4965_hcmd,
+	.utils = &iwl4965_hcmd_utils,
+	.led = &iwl4965_led_ops,
+	.legacy = &iwl4965_legacy_ops,
+	.ieee80211_ops = &iwl4965_hw_ops,
+};
+
+static struct iwl_base_params iwl4965_base_params = {
+	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
+	.num_of_queues = IWL49_NUM_QUEUES,
+	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = true,
+	.led_compensation = 61,
+	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.temperature_kelvin = true,
+	.max_event_log_size = 512,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+};
+
+struct iwl_cfg iwl4965_cfg = {
+	.name = "Intel(R) Wireless WiFi Link 4965AGN",
+	.fw_name_pre = IWL4965_FW_PRE,
+	.ucode_api_max = IWL4965_UCODE_API_MAX,
+	.ucode_api_min = IWL4965_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_AB,
+	.valid_rx_ant = ANT_ABC,
+	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
+	.ops = &iwl4965_ops,
+	.mod_params = &iwl4965_mod_params,
+	.base_params = &iwl4965_base_params,
+	.led_mode = IWL_LED_BLINK,
+	/*
+	 * Force use of chains B and C for scan RX on 5 GHz band
+	 * because the device has off-channel reception on chain A.
+	 */
+	.scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
+};
+
+/* Module firmware */
+MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.h b/drivers/net/wireless/iwlegacy/iwl-4965.h
new file mode 100644
index 0000000..01f8163
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.h
@@ -0,0 +1,282 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_4965_h__
+#define __iwl_4965_h__
+
+#include "iwl-dev.h"
+
+/* configuration for the _4965 devices */
+extern struct iwl_cfg iwl4965_cfg;
+
+extern struct iwl_mod_params iwl4965_mod_params;
+
+extern struct ieee80211_ops iwl4965_hw_ops;
+
+/* tx queue */
+void iwl4965_free_tfds_in_queue(struct iwl_priv *priv,
+			    int sta_id, int tid, int freed);
+
+/* RXON */
+void iwl4965_set_rxon_chain(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx);
+
+/* uCode */
+int iwl4965_verify_ucode(struct iwl_priv *priv);
+
+/* lib */
+void iwl4965_check_abort_status(struct iwl_priv *priv,
+			    u8 frame_count, u32 status);
+
+void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl4965_hw_nic_init(struct iwl_priv *priv);
+int iwl4965_dump_fh(struct iwl_priv *priv, char **buf, bool display);
+
+/* rx */
+void iwl4965_rx_queue_restock(struct iwl_priv *priv);
+void iwl4965_rx_replenish(struct iwl_priv *priv);
+void iwl4965_rx_replenish_now(struct iwl_priv *priv);
+void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl4965_rxq_stop(struct iwl_priv *priv);
+int iwl4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
+void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+		     struct iwl_rx_mem_buffer *rxb);
+void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+			 struct iwl_rx_mem_buffer *rxb);
+void iwl4965_rx_handle(struct iwl_priv *priv);
+
+/* tx */
+void iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				 struct iwl_tx_queue *txq,
+				 dma_addr_t addr, u16 len, u8 reset, u8 pad);
+int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
+			 struct iwl_tx_queue *txq);
+void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
+			      struct ieee80211_tx_info *info);
+int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
+int iwl4965_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+int iwl4965_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta, u16 tid);
+int iwl4965_txq_check_empty(struct iwl_priv *priv,
+			   int sta_id, u8 tid, int txq_id);
+void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
+void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
+int iwl4965_txq_ctx_alloc(struct iwl_priv *priv);
+void iwl4965_txq_ctx_reset(struct iwl_priv *priv);
+void iwl4965_txq_ctx_stop(struct iwl_priv *priv);
+void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask);
+
+/*
+ * Acquire priv->lock before calling this function !
+ */
+void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index);
+/**
+ * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
+ * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
+ * @scd_retry: (1) Indicates queue will be used in aggregation mode
+ *
+ * NOTE:  Acquire priv->lock before calling this function !
+ */
+void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					int tx_fifo_id, int scd_retry);
+
+static inline u32 iwl4965_tx_status_to_mac80211(u32 status)
+{
+	status &= TX_STATUS_MSK;
+
+	switch (status) {
+	case TX_STATUS_SUCCESS:
+	case TX_STATUS_DIRECT_DONE:
+		return IEEE80211_TX_STAT_ACK;
+	case TX_STATUS_FAIL_DEST_PS:
+		return IEEE80211_TX_STAT_TX_FILTERED;
+	default:
+		return 0;
+	}
+}
+
+static inline bool iwl4965_is_tx_success(u32 status)
+{
+	status &= TX_STATUS_MSK;
+	return (status == TX_STATUS_SUCCESS) ||
+	       (status == TX_STATUS_DIRECT_DONE);
+}
+
+u8 iwl4965_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
+
+/* rx */
+void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+bool iwl4965_good_plcp_health(struct iwl_priv *priv,
+			  struct iwl_rx_packet *pkt);
+void iwl4965_rx_statistics(struct iwl_priv *priv,
+		       struct iwl_rx_mem_buffer *rxb);
+void iwl4965_reply_statistics(struct iwl_priv *priv,
+			  struct iwl_rx_mem_buffer *rxb);
+
+/* scan */
+int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+
+/* station mgmt */
+int iwl4965_manage_ibss_station(struct iwl_priv *priv,
+			       struct ieee80211_vif *vif, bool add);
+
+/* hcmd */
+int iwl4965_send_beacon_cmd(struct iwl_priv *priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+const char *iwl4965_get_tx_fail_reason(u32 status);
+#else
+static inline const char *
+iwl4965_get_tx_fail_reason(u32 status) { return ""; }
+#endif
+
+/* station management */
+int iwl4965_alloc_bcast_station(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+int iwl4965_add_bssid_station(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx,
+			     const u8 *addr, u8 *sta_id_r);
+int iwl4965_remove_default_wep_key(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx,
+			       struct ieee80211_key_conf *key);
+int iwl4965_set_default_wep_key(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_key_conf *key);
+int iwl4965_restore_default_wep_keys(struct iwl_priv *priv,
+				 struct iwl_rxon_context *ctx);
+int iwl4965_set_dynamic_key(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *key, u8 sta_id);
+int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *key, u8 sta_id);
+void iwl4965_update_tkip_key(struct iwl_priv *priv,
+			 struct iwl_rxon_context *ctx,
+			 struct ieee80211_key_conf *keyconf,
+			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
+int iwl4965_sta_tx_modify_enable_tid(struct iwl_priv *priv,
+			int sta_id, int tid);
+int iwl4965_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			 int tid, u16 ssn);
+int iwl4965_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			int tid);
+void iwl4965_sta_modify_sleep_tx_count(struct iwl_priv *priv,
+			int sta_id, int cnt);
+int iwl4965_update_bcast_stations(struct iwl_priv *priv);
+
+/* rate */
+static inline u32 iwl4965_ant_idx_to_flags(u8 ant_idx)
+{
+	return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
+static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags)
+{
+	return le32_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u32 flags)
+{
+	return cpu_to_le32(flags|(u32)rate);
+}
+
+/* eeprom */
+void iwl4965_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
+int iwl4965_eeprom_acquire_semaphore(struct iwl_priv *priv);
+void iwl4965_eeprom_release_semaphore(struct iwl_priv *priv);
+int  iwl4965_eeprom_check_version(struct iwl_priv *priv);
+
+/* mac80211 handlers (for 4965) */
+void iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+int iwl4965_mac_start(struct ieee80211_hw *hw);
+void iwl4965_mac_stop(struct ieee80211_hw *hw);
+void iwl4965_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast);
+int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key);
+void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key);
+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
+int iwl4965_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta);
+void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch);
+
+#endif /* __iwl_4965_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-commands.h b/drivers/net/wireless/iwlegacy/iwl-commands.h
new file mode 100644
index 0000000..17a1d50
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-commands.h
@@ -0,0 +1,3405 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-commands.h) only for uCode API definitions.
+ * Please use iwl-xxxx-hw.h for hardware-related definitions.
+ * Please use iwl-dev.h for driver implementation definitions.
+ */
+
+#ifndef __iwl_legacy_commands_h__
+#define __iwl_legacy_commands_h__
+
+struct iwl_priv;
+
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver)	(((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver)	(((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver)	(((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver)	((ver) & 0x000000FF)
+
+
+/* Tx rates */
+#define IWL_CCK_RATES	4
+#define IWL_OFDM_RATES	8
+#define IWL_MAX_RATES	(IWL_CCK_RATES + IWL_OFDM_RATES)
+
+enum {
+	REPLY_ALIVE = 0x1,
+	REPLY_ERROR = 0x2,
+
+	/* RXON and QOS commands */
+	REPLY_RXON = 0x10,
+	REPLY_RXON_ASSOC = 0x11,
+	REPLY_QOS_PARAM = 0x13,
+	REPLY_RXON_TIMING = 0x14,
+
+	/* Multi-Station support */
+	REPLY_ADD_STA = 0x18,
+	REPLY_REMOVE_STA = 0x19,
+
+	/* Security */
+	REPLY_WEPKEY = 0x20,
+
+	/* RX, TX, LEDs */
+	REPLY_3945_RX = 0x1b,           /* 3945 only */
+	REPLY_TX = 0x1c,
+	REPLY_RATE_SCALE = 0x47,	/* 3945 only */
+	REPLY_LEDS_CMD = 0x48,
+	REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */
+
+	/* 802.11h related */
+	REPLY_CHANNEL_SWITCH = 0x72,
+	CHANNEL_SWITCH_NOTIFICATION = 0x73,
+	REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
+	SPECTRUM_MEASURE_NOTIFICATION = 0x75,
+
+	/* Power Management */
+	POWER_TABLE_CMD = 0x77,
+	PM_SLEEP_NOTIFICATION = 0x7A,
+	PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
+
+	/* Scan commands and notifications */
+	REPLY_SCAN_CMD = 0x80,
+	REPLY_SCAN_ABORT_CMD = 0x81,
+	SCAN_START_NOTIFICATION = 0x82,
+	SCAN_RESULTS_NOTIFICATION = 0x83,
+	SCAN_COMPLETE_NOTIFICATION = 0x84,
+
+	/* IBSS/AP commands */
+	BEACON_NOTIFICATION = 0x90,
+	REPLY_TX_BEACON = 0x91,
+
+	/* Miscellaneous commands */
+	REPLY_TX_PWR_TABLE_CMD = 0x97,
+
+	/* Bluetooth device coexistence config command */
+	REPLY_BT_CONFIG = 0x9b,
+
+	/* Statistics */
+	REPLY_STATISTICS_CMD = 0x9c,
+	STATISTICS_NOTIFICATION = 0x9d,
+
+	/* RF-KILL commands and notifications */
+	CARD_STATE_NOTIFICATION = 0xa1,
+
+	/* Missed beacons notification */
+	MISSED_BEACONS_NOTIFICATION = 0xa2,
+
+	REPLY_CT_KILL_CONFIG_CMD = 0xa4,
+	SENSITIVITY_CMD = 0xa8,
+	REPLY_PHY_CALIBRATION_CMD = 0xb0,
+	REPLY_RX_PHY_CMD = 0xc0,
+	REPLY_RX_MPDU_CMD = 0xc1,
+	REPLY_RX = 0xc3,
+	REPLY_COMPRESSED_BA = 0xc5,
+
+	REPLY_MAX = 0xff
+};
+
+/******************************************************************************
+ * (0)
+ * Commonly used structures and definitions:
+ * Command header, rate_n_flags, txpower
+ *
+ *****************************************************************************/
+
+/* iwl_cmd_header flags value */
+#define IWL_CMD_FAILED_MSK 0x40
+
+#define SEQ_TO_QUEUE(s)	(((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q)	(((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s)	((s) & 0xff)
+#define INDEX_TO_SEQ(i)	((i) & 0xff)
+#define SEQ_HUGE_FRAME	cpu_to_le16(0x4000)
+#define SEQ_RX_FRAME	cpu_to_le16(0x8000)
+
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
+	u8 flags;	/* 0:5 reserved, 6 abort, 7 internal */
+	/*
+	 * The driver sets up the sequence number to values of its choosing.
+	 * uCode does not use this value, but passes it back to the driver
+	 * when sending the response to each driver-originated command, so
+	 * the driver can match the response to the command.  Since the values
+	 * don't get used by uCode, the driver may set up an arbitrary format.
+	 *
+	 * There is one exception:  uCode sets bit 15 when it originates
+	 * the response/notification, i.e. when the response/notification
+	 * is not a direct response to a command sent by the driver.  For
+	 * example, uCode issues REPLY_3945_RX when it sends a received frame
+	 * to the driver; it is not a direct response to any driver command.
+	 *
+	 * The Linux driver uses the following format:
+	 *
+	 *  0:7		tfd index - position within TX queue
+	 *  8:12	TX queue id
+	 *  13		reserved
+	 *  14		huge - driver sets this to indicate command is in the
+	 *  		'huge' storage at the end of the command buffers
+	 *  15		unsolicited RX or uCode-originated notification
+	*/
+	__le16 sequence;
+
+	/* command or response/notification data follows immediately */
+	u8 data[0];
+} __packed;
+
+
+/**
+ * struct iwl3945_tx_power
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Each entry contains two values:
+ * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
+ *     linear value that multiplies the output of the digital signal processor,
+ *     before being sent to the analog radio.
+ * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
+ *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * Driver obtains values from struct iwl3945_tx_power power_gain_table[][].
+ */
+struct iwl3945_tx_power {
+	u8 tx_gain;		/* gain for analog radio */
+	u8 dsp_atten;		/* gain for DSP */
+} __packed;
+
+/**
+ * struct iwl3945_power_per_rate
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl3945_power_per_rate {
+	u8 rate;		/* plcp */
+	struct iwl3945_tx_power tpc;
+	u8 reserved;
+} __packed;
+
+/**
+ * iwl4965 rate_n_flags bit fields
+ *
+ * rate_n_flags format is used in following iwl4965 commands:
+ *  REPLY_RX (response only)
+ *  REPLY_RX_MPDU (response only)
+ *  REPLY_TX (both command and response)
+ *  REPLY_TX_LINK_QUALITY_CMD
+ *
+ * High-throughput (HT) rate format for bits 7:0 (bit 8 must be "1"):
+ *  2-0:  0)   6 Mbps
+ *        1)  12 Mbps
+ *        2)  18 Mbps
+ *        3)  24 Mbps
+ *        4)  36 Mbps
+ *        5)  48 Mbps
+ *        6)  54 Mbps
+ *        7)  60 Mbps
+ *
+ *  4-3:  0)  Single stream (SISO)
+ *        1)  Dual stream (MIMO)
+ *        2)  Triple stream (MIMO)
+ *
+ *    5:  Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
+ *
+ * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"):
+ *  3-0:  0xD)   6 Mbps
+ *        0xF)   9 Mbps
+ *        0x5)  12 Mbps
+ *        0x7)  18 Mbps
+ *        0x9)  24 Mbps
+ *        0xB)  36 Mbps
+ *        0x1)  48 Mbps
+ *        0x3)  54 Mbps
+ *
+ * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"):
+ *  6-0:   10)  1 Mbps
+ *         20)  2 Mbps
+ *         55)  5.5 Mbps
+ *        110)  11 Mbps
+ */
+#define RATE_MCS_CODE_MSK 0x7
+#define RATE_MCS_SPATIAL_POS 3
+#define RATE_MCS_SPATIAL_MSK 0x18
+#define RATE_MCS_HT_DUP_POS 5
+#define RATE_MCS_HT_DUP_MSK 0x20
+
+/* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */
+#define RATE_MCS_FLAGS_POS 8
+#define RATE_MCS_HT_POS 8
+#define RATE_MCS_HT_MSK 0x100
+
+/* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be "0" for this bit to be valid */
+#define RATE_MCS_CCK_POS 9
+#define RATE_MCS_CCK_MSK 0x200
+
+/* Bit 10: (1) Use Green Field preamble */
+#define RATE_MCS_GF_POS 10
+#define RATE_MCS_GF_MSK 0x400
+
+/* Bit 11: (1) Use 40Mhz HT40 chnl width, (0) use 20 MHz legacy chnl width */
+#define RATE_MCS_HT40_POS 11
+#define RATE_MCS_HT40_MSK 0x800
+
+/* Bit 12: (1) Duplicate data on both 20MHz chnls. HT40 (bit 11) must be set. */
+#define RATE_MCS_DUP_POS 12
+#define RATE_MCS_DUP_MSK 0x1000
+
+/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
+#define RATE_MCS_SGI_POS 13
+#define RATE_MCS_SGI_MSK 0x2000
+
+/**
+ * rate_n_flags Tx antenna masks
+ * 4965 has 2 transmitters
+ * bit14:16
+ */
+#define RATE_MCS_ANT_POS	14
+#define RATE_MCS_ANT_A_MSK	0x04000
+#define RATE_MCS_ANT_B_MSK	0x08000
+#define RATE_MCS_ANT_C_MSK	0x10000
+#define RATE_MCS_ANT_AB_MSK	(RATE_MCS_ANT_A_MSK | RATE_MCS_ANT_B_MSK)
+#define RATE_MCS_ANT_ABC_MSK	(RATE_MCS_ANT_AB_MSK | RATE_MCS_ANT_C_MSK)
+#define RATE_ANT_NUM 3
+
+#define POWER_TABLE_NUM_ENTRIES			33
+#define POWER_TABLE_NUM_HT_OFDM_ENTRIES		32
+#define POWER_TABLE_CCK_ENTRY			32
+
+#define IWL_PWR_NUM_HT_OFDM_ENTRIES		24
+#define IWL_PWR_CCK_ENTRIES			2
+
+/**
+ * union iwl4965_tx_power_dual_stream
+ *
+ * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Use __le32 version (struct tx_power_dual_stream) when building command.
+ *
+ * Driver provides radio gain and DSP attenuation settings to device in pairs,
+ * one value for each transmitter chain.  The first value is for transmitter A,
+ * second for transmitter B.
+ *
+ * For SISO bit rates, both values in a pair should be identical.
+ * For MIMO rates, one value may be different from the other,
+ * in order to balance the Tx output between the two transmitters.
+ *
+ * See more details in doc for TXPOWER in iwl-4965-hw.h.
+ */
+union iwl4965_tx_power_dual_stream {
+	struct {
+		u8 radio_tx_gain[2];
+		u8 dsp_predis_atten[2];
+	} s;
+	u32 dw;
+};
+
+/**
+ * struct tx_power_dual_stream
+ *
+ * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Same format as iwl_tx_power_dual_stream, but __le32
+ */
+struct tx_power_dual_stream {
+	__le32 dw;
+} __packed;
+
+/**
+ * struct iwl4965_tx_power_db
+ *
+ * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl4965_tx_power_db {
+	struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
+} __packed;
+
+/******************************************************************************
+ * (0a)
+ * Alive and Error Commands & Responses:
+ *
+ *****************************************************************************/
+
+#define UCODE_VALID_OK	cpu_to_le32(0x1)
+#define INITIALIZE_SUBTYPE    (9)
+
+/*
+ * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "initialize alive" notification once the initialization
+ * uCode image has completed its work, and is ready to load the runtime image.
+ * This is the *first* "alive" notification that the driver will receive after
+ * rebooting uCode; the "initialize" alive is indicated by subtype field == 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * For 4965, this notification contains important calibration data for
+ * calculating txpower settings:
+ *
+ * 1)  Power supply voltage indication.  The voltage sensor outputs higher
+ *     values for lower voltage, and vice verse.
+ *
+ * 2)  Temperature measurement parameters, for each of two channel widths
+ *     (20 MHz and 40 MHz) supported by the radios.  Temperature sensing
+ *     is done via one of the receiver chains, and channel width influences
+ *     the results.
+ *
+ * 3)  Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation,
+ *     for each of 5 frequency ranges.
+ */
+struct iwl_init_alive_resp {
+	u8 ucode_minor;
+	u8 ucode_major;
+	__le16 reserved1;
+	u8 sw_rev[8];
+	u8 ver_type;
+	u8 ver_subtype;		/* "9" for initialize alive */
+	__le16 reserved2;
+	__le32 log_event_table_ptr;
+	__le32 error_event_table_ptr;
+	__le32 timestamp;
+	__le32 is_valid;
+
+	/* calibration values from "initialize" uCode */
+	__le32 voltage;		/* signed, higher value is lower voltage */
+	__le32 therm_r1[2];	/* signed, 1st for normal, 2nd for HT40 */
+	__le32 therm_r2[2];	/* signed */
+	__le32 therm_r3[2];	/* signed */
+	__le32 therm_r4[2];	/* signed */
+	__le32 tx_atten[5][2];	/* signed MIMO gain comp, 5 freq groups,
+				 * 2 Tx chains */
+} __packed;
+
+
+/**
+ * REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "alive" notification once the runtime image is ready
+ * to receive commands from the driver.  This is the *second* "alive"
+ * notification that the driver will receive after rebooting uCode;
+ * this "alive" is indicated by subtype field != 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * This response includes two pointers to structures within the device's
+ * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging:
+ *
+ * 1)  log_event_table_ptr indicates base of the event log.  This traces
+ *     a 256-entry history of uCode execution within a circular buffer.
+ *     Its header format is:
+ *
+ *	__le32 log_size;     log capacity (in number of entries)
+ *	__le32 type;         (1) timestamp with each entry, (0) no timestamp
+ *	__le32 wraps;        # times uCode has wrapped to top of circular buffer
+ *      __le32 write_index;  next circular buffer entry that uCode would fill
+ *
+ *     The header is followed by the circular buffer of log entries.  Entries
+ *     with timestamps have the following format:
+ *
+ *	__le32 event_id;     range 0 - 1500
+ *	__le32 timestamp;    low 32 bits of TSF (of network, if associated)
+ *	__le32 data;         event_id-specific data value
+ *
+ *     Entries without timestamps contain only event_id and data.
+ *
+ *
+ * 2)  error_event_table_ptr indicates base of the error log.  This contains
+ *     information about any uCode error that occurs.  For 4965, the format
+ *     of the error log is:
+ *
+ *	__le32 valid;        (nonzero) valid, (0) log is empty
+ *	__le32 error_id;     type of error
+ *	__le32 pc;           program counter
+ *	__le32 blink1;       branch link
+ *	__le32 blink2;       branch link
+ *	__le32 ilink1;       interrupt link
+ *	__le32 ilink2;       interrupt link
+ *	__le32 data1;        error-specific data
+ *	__le32 data2;        error-specific data
+ *	__le32 line;         source code line of error
+ *	__le32 bcon_time;    beacon timer
+ *	__le32 tsf_low;      network timestamp function timer
+ *	__le32 tsf_hi;       network timestamp function timer
+ *	__le32 gp1;          GP1 timer register
+ *	__le32 gp2;          GP2 timer register
+ *	__le32 gp3;          GP3 timer register
+ *	__le32 ucode_ver;    uCode version
+ *	__le32 hw_ver;       HW Silicon version
+ *	__le32 brd_ver;      HW board version
+ *	__le32 log_pc;       log program counter
+ *	__le32 frame_ptr;    frame pointer
+ *	__le32 stack_ptr;    stack pointer
+ *	__le32 hcmd;         last host command
+ *	__le32 isr0;         isr status register LMPM_NIC_ISR0: rxtx_flag
+ *	__le32 isr1;         isr status register LMPM_NIC_ISR1: host_flag
+ *	__le32 isr2;         isr status register LMPM_NIC_ISR2: enc_flag
+ *	__le32 isr3;         isr status register LMPM_NIC_ISR3: time_flag
+ *	__le32 isr4;         isr status register LMPM_NIC_ISR4: wico interrupt
+ *	__le32 isr_pref;     isr status register LMPM_NIC_PREF_STAT
+ *	__le32 wait_event;   wait event() caller address
+ *	__le32 l2p_control;  L2pControlField
+ *	__le32 l2p_duration; L2pDurationField
+ *	__le32 l2p_mhvalid;  L2pMhValidBits
+ *	__le32 l2p_addr_match; L2pAddrMatchStat
+ *	__le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL)
+ *	__le32 u_timestamp;  indicate when the date and time of the compilation
+ *	__le32 reserved;
+ *
+ * The Linux driver can print both logs to the system log when a uCode error
+ * occurs.
+ */
+struct iwl_alive_resp {
+	u8 ucode_minor;
+	u8 ucode_major;
+	__le16 reserved1;
+	u8 sw_rev[8];
+	u8 ver_type;
+	u8 ver_subtype;			/* not "9" for runtime alive */
+	__le16 reserved2;
+	__le32 log_event_table_ptr;	/* SRAM address for event log */
+	__le32 error_event_table_ptr;	/* SRAM address for error log */
+	__le32 timestamp;
+	__le32 is_valid;
+} __packed;
+
+/*
+ * REPLY_ERROR = 0x2 (response only, not a command)
+ */
+struct iwl_error_resp {
+	__le32 error_type;
+	u8 cmd_id;
+	u8 reserved1;
+	__le16 bad_cmd_seq_num;
+	__le32 error_info;
+	__le64 timestamp;
+} __packed;
+
+/******************************************************************************
+ * (1)
+ * RXON Commands & Responses:
+ *
+ *****************************************************************************/
+
+/*
+ * Rx config defines & structure
+ */
+/* rx_config device types  */
+enum {
+	RXON_DEV_TYPE_AP = 1,
+	RXON_DEV_TYPE_ESS = 3,
+	RXON_DEV_TYPE_IBSS = 4,
+	RXON_DEV_TYPE_SNIFFER = 6,
+};
+
+
+#define RXON_RX_CHAIN_DRIVER_FORCE_MSK		cpu_to_le16(0x1 << 0)
+#define RXON_RX_CHAIN_DRIVER_FORCE_POS		(0)
+#define RXON_RX_CHAIN_VALID_MSK			cpu_to_le16(0x7 << 1)
+#define RXON_RX_CHAIN_VALID_POS			(1)
+#define RXON_RX_CHAIN_FORCE_SEL_MSK		cpu_to_le16(0x7 << 4)
+#define RXON_RX_CHAIN_FORCE_SEL_POS		(4)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK	cpu_to_le16(0x7 << 7)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS	(7)
+#define RXON_RX_CHAIN_CNT_MSK			cpu_to_le16(0x3 << 10)
+#define RXON_RX_CHAIN_CNT_POS			(10)
+#define RXON_RX_CHAIN_MIMO_CNT_MSK		cpu_to_le16(0x3 << 12)
+#define RXON_RX_CHAIN_MIMO_CNT_POS		(12)
+#define RXON_RX_CHAIN_MIMO_FORCE_MSK		cpu_to_le16(0x1 << 14)
+#define RXON_RX_CHAIN_MIMO_FORCE_POS		(14)
+
+/* rx_config flags */
+/* band & modulation selection */
+#define RXON_FLG_BAND_24G_MSK           cpu_to_le32(1 << 0)
+#define RXON_FLG_CCK_MSK                cpu_to_le32(1 << 1)
+/* auto detection enable */
+#define RXON_FLG_AUTO_DETECT_MSK        cpu_to_le32(1 << 2)
+/* TGg protection when tx */
+#define RXON_FLG_TGG_PROTECT_MSK        cpu_to_le32(1 << 3)
+/* cck short slot & preamble */
+#define RXON_FLG_SHORT_SLOT_MSK          cpu_to_le32(1 << 4)
+#define RXON_FLG_SHORT_PREAMBLE_MSK     cpu_to_le32(1 << 5)
+/* antenna selection */
+#define RXON_FLG_DIS_DIV_MSK            cpu_to_le32(1 << 7)
+#define RXON_FLG_ANT_SEL_MSK            cpu_to_le32(0x0f00)
+#define RXON_FLG_ANT_A_MSK              cpu_to_le32(1 << 8)
+#define RXON_FLG_ANT_B_MSK              cpu_to_le32(1 << 9)
+/* radar detection enable */
+#define RXON_FLG_RADAR_DETECT_MSK       cpu_to_le32(1 << 12)
+#define RXON_FLG_TGJ_NARROW_BAND_MSK    cpu_to_le32(1 << 13)
+/* rx response to host with 8-byte TSF
+* (according to ON_AIR deassertion) */
+#define RXON_FLG_TSF2HOST_MSK           cpu_to_le32(1 << 15)
+
+
+/* HT flags */
+#define RXON_FLG_CTRL_CHANNEL_LOC_POS		(22)
+#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK	cpu_to_le32(0x1 << 22)
+
+#define RXON_FLG_HT_OPERATING_MODE_POS		(23)
+
+#define RXON_FLG_HT_PROT_MSK			cpu_to_le32(0x1 << 23)
+#define RXON_FLG_HT40_PROT_MSK			cpu_to_le32(0x2 << 23)
+
+#define RXON_FLG_CHANNEL_MODE_POS		(25)
+#define RXON_FLG_CHANNEL_MODE_MSK		cpu_to_le32(0x3 << 25)
+
+/* channel mode */
+enum {
+	CHANNEL_MODE_LEGACY = 0,
+	CHANNEL_MODE_PURE_40 = 1,
+	CHANNEL_MODE_MIXED = 2,
+	CHANNEL_MODE_RESERVED = 3,
+};
+#define RXON_FLG_CHANNEL_MODE_LEGACY			\
+	cpu_to_le32(CHANNEL_MODE_LEGACY << RXON_FLG_CHANNEL_MODE_POS)
+#define RXON_FLG_CHANNEL_MODE_PURE_40			\
+	cpu_to_le32(CHANNEL_MODE_PURE_40 << RXON_FLG_CHANNEL_MODE_POS)
+#define RXON_FLG_CHANNEL_MODE_MIXED			\
+	cpu_to_le32(CHANNEL_MODE_MIXED << RXON_FLG_CHANNEL_MODE_POS)
+
+/* CTS to self (if spec allows) flag */
+#define RXON_FLG_SELF_CTS_EN			cpu_to_le32(0x1<<30)
+
+/* rx_config filter flags */
+/* accept all data frames */
+#define RXON_FILTER_PROMISC_MSK         cpu_to_le32(1 << 0)
+/* pass control & management to host */
+#define RXON_FILTER_CTL2HOST_MSK        cpu_to_le32(1 << 1)
+/* accept multi-cast */
+#define RXON_FILTER_ACCEPT_GRP_MSK      cpu_to_le32(1 << 2)
+/* don't decrypt uni-cast frames */
+#define RXON_FILTER_DIS_DECRYPT_MSK     cpu_to_le32(1 << 3)
+/* don't decrypt multi-cast frames */
+#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4)
+/* STA is associated */
+#define RXON_FILTER_ASSOC_MSK           cpu_to_le32(1 << 5)
+/* transfer to host non bssid beacons in associated state */
+#define RXON_FILTER_BCON_AWARE_MSK      cpu_to_le32(1 << 6)
+
+/**
+ * REPLY_RXON = 0x10 (command, has simple generic response)
+ *
+ * RXON tunes the radio tuner to a service channel, and sets up a number
+ * of parameters that are used primarily for Rx, but also for Tx operations.
+ *
+ * NOTE:  When tuning to a new channel, driver must set the
+ *        RXON_FILTER_ASSOC_MSK to 0.  This will clear station-dependent
+ *        info within the device, including the station tables, tx retry
+ *        rate tables, and txpower tables.  Driver must build a new station
+ *        table and txpower table before transmitting anything on the RXON
+ *        channel.
+ *
+ * NOTE:  All RXONs wipe clean the internal txpower table.  Driver must
+ *        issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
+ *        regardless of whether RXON_FILTER_ASSOC_MSK is set.
+ */
+
+struct iwl3945_rxon_cmd {
+	u8 node_addr[6];
+	__le16 reserved1;
+	u8 bssid_addr[6];
+	__le16 reserved2;
+	u8 wlap_bssid_addr[6];
+	__le16 reserved3;
+	u8 dev_type;
+	u8 air_propagation;
+	__le16 reserved4;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 assoc_id;
+	__le32 flags;
+	__le32 filter_flags;
+	__le16 channel;
+	__le16 reserved5;
+} __packed;
+
+struct iwl4965_rxon_cmd {
+	u8 node_addr[6];
+	__le16 reserved1;
+	u8 bssid_addr[6];
+	__le16 reserved2;
+	u8 wlap_bssid_addr[6];
+	__le16 reserved3;
+	u8 dev_type;
+	u8 air_propagation;
+	__le16 rx_chain;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 assoc_id;
+	__le32 flags;
+	__le32 filter_flags;
+	__le16 channel;
+	u8 ofdm_ht_single_stream_basic_rates;
+	u8 ofdm_ht_dual_stream_basic_rates;
+} __packed;
+
+/* Create a common rxon cmd which will be typecast into the 3945 or 4965
+ * specific rxon cmd, depending on where it is called from.
+ */
+struct iwl_legacy_rxon_cmd {
+	u8 node_addr[6];
+	__le16 reserved1;
+	u8 bssid_addr[6];
+	__le16 reserved2;
+	u8 wlap_bssid_addr[6];
+	__le16 reserved3;
+	u8 dev_type;
+	u8 air_propagation;
+	__le16 rx_chain;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 assoc_id;
+	__le32 flags;
+	__le32 filter_flags;
+	__le16 channel;
+	u8 ofdm_ht_single_stream_basic_rates;
+	u8 ofdm_ht_dual_stream_basic_rates;
+	u8 reserved4;
+	u8 reserved5;
+} __packed;
+
+
+/*
+ * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
+ */
+struct iwl3945_rxon_assoc_cmd {
+	__le32 flags;
+	__le32 filter_flags;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 reserved;
+} __packed;
+
+struct iwl4965_rxon_assoc_cmd {
+	__le32 flags;
+	__le32 filter_flags;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	u8 ofdm_ht_single_stream_basic_rates;
+	u8 ofdm_ht_dual_stream_basic_rates;
+	__le16 rx_chain_select_flags;
+	__le16 reserved;
+} __packed;
+
+#define IWL_CONN_MAX_LISTEN_INTERVAL	10
+#define IWL_MAX_UCODE_BEACON_INTERVAL	4 /* 4096 */
+#define IWL39_MAX_UCODE_BEACON_INTERVAL	1 /* 1024 */
+
+/*
+ * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
+ */
+struct iwl_rxon_time_cmd {
+	__le64 timestamp;
+	__le16 beacon_interval;
+	__le16 atim_window;
+	__le32 beacon_init_val;
+	__le16 listen_interval;
+	u8 dtim_period;
+	u8 delta_cp_bss_tbtts;
+} __packed;
+
+/*
+ * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
+ */
+struct iwl3945_channel_switch_cmd {
+	u8 band;
+	u8 expect_beacon;
+	__le16 channel;
+	__le32 rxon_flags;
+	__le32 rxon_filter_flags;
+	__le32 switch_time;
+	struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+} __packed;
+
+struct iwl4965_channel_switch_cmd {
+	u8 band;
+	u8 expect_beacon;
+	__le16 channel;
+	__le32 rxon_flags;
+	__le32 rxon_filter_flags;
+	__le32 switch_time;
+	struct iwl4965_tx_power_db tx_power;
+} __packed;
+
+/*
+ * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
+ */
+struct iwl_csa_notification {
+	__le16 band;
+	__le16 channel;
+	__le32 status;		/* 0 - OK, 1 - fail */
+} __packed;
+
+/******************************************************************************
+ * (2)
+ * Quality-of-Service (QOS) Commands & Responses:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
+ * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
+ *
+ * @cw_min: Contention window, start value in numbers of slots.
+ *          Should be a power-of-2, minus 1.  Device's default is 0x0f.
+ * @cw_max: Contention window, max value in numbers of slots.
+ *          Should be a power-of-2, minus 1.  Device's default is 0x3f.
+ * @aifsn:  Number of slots in Arbitration Interframe Space (before
+ *          performing random backoff timing prior to Tx).  Device default 1.
+ * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.
+ *
+ * Device will automatically increase contention window by (2*CW) + 1 for each
+ * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
+ * value, to cap the CW value.
+ */
+struct iwl_ac_qos {
+	__le16 cw_min;
+	__le16 cw_max;
+	u8 aifsn;
+	u8 reserved1;
+	__le16 edca_txop;
+} __packed;
+
+/* QoS flags defines */
+#define QOS_PARAM_FLG_UPDATE_EDCA_MSK	cpu_to_le32(0x01)
+#define QOS_PARAM_FLG_TGN_MSK		cpu_to_le32(0x02)
+#define QOS_PARAM_FLG_TXOP_TYPE_MSK	cpu_to_le32(0x10)
+
+/* Number of Access Categories (AC) (EDCA), queues 0..3 */
+#define AC_NUM                4
+
+/*
+ * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
+ *
+ * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
+ * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
+ */
+struct iwl_qosparam_cmd {
+	__le32 qos_flags;
+	struct iwl_ac_qos ac[AC_NUM];
+} __packed;
+
+/******************************************************************************
+ * (3)
+ * Add/Modify Stations Commands & Responses:
+ *
+ *****************************************************************************/
+/*
+ * Multi station support
+ */
+
+/* Special, dedicated locations within device's station table */
+#define	IWL_AP_ID		0
+#define	IWL_STA_ID		2
+#define	IWL3945_BROADCAST_ID	24
+#define IWL3945_STATION_COUNT	25
+#define IWL4965_BROADCAST_ID	31
+#define	IWL4965_STATION_COUNT	32
+
+#define	IWL_STATION_COUNT	32 	/* MAX(3945,4965)*/
+#define	IWL_INVALID_STATION	255
+
+#define STA_FLG_TX_RATE_MSK		cpu_to_le32(1 << 2)
+#define STA_FLG_PWR_SAVE_MSK		cpu_to_le32(1 << 8)
+#define STA_FLG_RTS_MIMO_PROT_MSK	cpu_to_le32(1 << 17)
+#define STA_FLG_AGG_MPDU_8US_MSK	cpu_to_le32(1 << 18)
+#define STA_FLG_MAX_AGG_SIZE_POS	(19)
+#define STA_FLG_MAX_AGG_SIZE_MSK	cpu_to_le32(3 << 19)
+#define STA_FLG_HT40_EN_MSK		cpu_to_le32(1 << 21)
+#define STA_FLG_MIMO_DIS_MSK		cpu_to_le32(1 << 22)
+#define STA_FLG_AGG_MPDU_DENSITY_POS	(23)
+#define STA_FLG_AGG_MPDU_DENSITY_MSK	cpu_to_le32(7 << 23)
+
+/* Use in mode field.  1: modify existing entry, 0: add new station entry */
+#define STA_CONTROL_MODIFY_MSK		0x01
+
+/* key flags __le16*/
+#define STA_KEY_FLG_ENCRYPT_MSK	cpu_to_le16(0x0007)
+#define STA_KEY_FLG_NO_ENC	cpu_to_le16(0x0000)
+#define STA_KEY_FLG_WEP		cpu_to_le16(0x0001)
+#define STA_KEY_FLG_CCMP	cpu_to_le16(0x0002)
+#define STA_KEY_FLG_TKIP	cpu_to_le16(0x0003)
+
+#define STA_KEY_FLG_KEYID_POS	8
+#define STA_KEY_FLG_INVALID	cpu_to_le16(0x0800)
+/* wep key is either from global key (0) or from station info array (1) */
+#define STA_KEY_FLG_MAP_KEY_MSK	cpu_to_le16(0x0008)
+
+/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
+#define STA_KEY_FLG_KEY_SIZE_MSK	cpu_to_le16(0x1000)
+#define STA_KEY_MULTICAST_MSK		cpu_to_le16(0x4000)
+#define STA_KEY_MAX_NUM		8
+
+/* Flags indicate whether to modify vs. don't change various station params */
+#define	STA_MODIFY_KEY_MASK		0x01
+#define	STA_MODIFY_TID_DISABLE_TX	0x02
+#define	STA_MODIFY_TX_RATE_MSK		0x04
+#define STA_MODIFY_ADDBA_TID_MSK	0x08
+#define STA_MODIFY_DELBA_TID_MSK	0x10
+#define STA_MODIFY_SLEEP_TX_COUNT_MSK	0x20
+
+/* Receiver address (actually, Rx station's index into station table),
+ * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
+#define BUILD_RAxTID(sta_id, tid)	(((sta_id) << 4) + (tid))
+
+struct iwl4965_keyinfo {
+	__le16 key_flags;
+	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
+	u8 reserved1;
+	__le16 tkip_rx_ttak[5];	/* 10-byte unicast TKIP TTAK */
+	u8 key_offset;
+	u8 reserved2;
+	u8 key[16];		/* 16-byte unicast decryption key */
+} __packed;
+
+/**
+ * struct sta_id_modify
+ * @addr[ETH_ALEN]: station's MAC address
+ * @sta_id: index of station in uCode's station table
+ * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
+ *
+ * Driver selects unused table index when adding new station,
+ * or the index to a pre-existing station entry when modifying that station.
+ * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
+ *
+ * modify_mask flags select which parameters to modify vs. leave alone.
+ */
+struct sta_id_modify {
+	u8 addr[ETH_ALEN];
+	__le16 reserved1;
+	u8 sta_id;
+	u8 modify_mask;
+	__le16 reserved2;
+} __packed;
+
+/*
+ * REPLY_ADD_STA = 0x18 (command)
+ *
+ * The device contains an internal table of per-station information,
+ * with info on security keys, aggregation parameters, and Tx rates for
+ * initial Tx attempt and any retries (4965 devices uses
+ * REPLY_TX_LINK_QUALITY_CMD,
+ * 3945 uses REPLY_RATE_SCALE to set up rate tables).
+ *
+ * REPLY_ADD_STA sets up the table entry for one station, either creating
+ * a new entry, or modifying a pre-existing one.
+ *
+ * NOTE:  RXON command (without "associated" bit set) wipes the station table
+ *        clean.  Moving into RF_KILL state does this also.  Driver must set up
+ *        new station table before transmitting anything on the RXON channel
+ *        (except active scans or active measurements; those commands carry
+ *        their own txpower/rate setup data).
+ *
+ *        When getting started on a new channel, driver must set up the
+ *        IWL_BROADCAST_ID entry (last entry in the table).  For a client
+ *        station in a BSS, once an AP is selected, driver sets up the AP STA
+ *        in the IWL_AP_ID entry (1st entry in the table).  BROADCAST and AP
+ *        are all that are needed for a BSS client station.  If the device is
+ *        used as AP, or in an IBSS network, driver must set up station table
+ *        entries for all STAs in network, starting with index IWL_STA_ID.
+ */
+
+struct iwl3945_addsta_cmd {
+	u8 mode;		/* 1: modify existing, 0: add new station */
+	u8 reserved[3];
+	struct sta_id_modify sta;
+	struct iwl4965_keyinfo key;
+	__le32 station_flags;		/* STA_FLG_* */
+	__le32 station_flags_msk;	/* STA_FLG_* */
+
+	/* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+	 * corresponding to bit (e.g. bit 5 controls TID 5).
+	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+	__le16 tid_disable_tx;
+
+	__le16 rate_n_flags;
+
+	/* TID for which to add block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	u8 add_immediate_ba_tid;
+
+	/* TID for which to remove block-ack support.
+	 * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+	u8 remove_immediate_ba_tid;
+
+	/* Starting Sequence Number for added block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	__le16 add_immediate_ba_ssn;
+} __packed;
+
+struct iwl4965_addsta_cmd {
+	u8 mode;		/* 1: modify existing, 0: add new station */
+	u8 reserved[3];
+	struct sta_id_modify sta;
+	struct iwl4965_keyinfo key;
+	__le32 station_flags;		/* STA_FLG_* */
+	__le32 station_flags_msk;	/* STA_FLG_* */
+
+	/* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+	 * corresponding to bit (e.g. bit 5 controls TID 5).
+	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+	__le16 tid_disable_tx;
+
+	__le16	reserved1;
+
+	/* TID for which to add block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	u8 add_immediate_ba_tid;
+
+	/* TID for which to remove block-ack support.
+	 * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+	u8 remove_immediate_ba_tid;
+
+	/* Starting Sequence Number for added block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	__le16 add_immediate_ba_ssn;
+
+	/*
+	 * Number of packets OK to transmit to station even though
+	 * it is asleep -- used to synchronise PS-poll and u-APSD
+	 * responses while ucode keeps track of STA sleep state.
+	 */
+	__le16 sleep_tx_count;
+
+	__le16 reserved2;
+} __packed;
+
+/* Wrapper struct for 3945 and 4965 addsta_cmd structures */
+struct iwl_legacy_addsta_cmd {
+	u8 mode;		/* 1: modify existing, 0: add new station */
+	u8 reserved[3];
+	struct sta_id_modify sta;
+	struct iwl4965_keyinfo key;
+	__le32 station_flags;		/* STA_FLG_* */
+	__le32 station_flags_msk;	/* STA_FLG_* */
+
+	/* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+	 * corresponding to bit (e.g. bit 5 controls TID 5).
+	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+	__le16 tid_disable_tx;
+
+	__le16	rate_n_flags;		/* 3945 only */
+
+	/* TID for which to add block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	u8 add_immediate_ba_tid;
+
+	/* TID for which to remove block-ack support.
+	 * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+	u8 remove_immediate_ba_tid;
+
+	/* Starting Sequence Number for added block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	__le16 add_immediate_ba_ssn;
+
+	/*
+	 * Number of packets OK to transmit to station even though
+	 * it is asleep -- used to synchronise PS-poll and u-APSD
+	 * responses while ucode keeps track of STA sleep state.
+	 */
+	__le16 sleep_tx_count;
+
+	__le16 reserved2;
+} __packed;
+
+
+#define ADD_STA_SUCCESS_MSK		0x1
+#define ADD_STA_NO_ROOM_IN_TABLE	0x2
+#define ADD_STA_NO_BLOCK_ACK_RESOURCE	0x4
+#define ADD_STA_MODIFY_NON_EXIST_STA	0x8
+/*
+ * REPLY_ADD_STA = 0x18 (response)
+ */
+struct iwl_add_sta_resp {
+	u8 status;	/* ADD_STA_* */
+} __packed;
+
+#define REM_STA_SUCCESS_MSK              0x1
+/*
+ *  REPLY_REM_STA = 0x19 (response)
+ */
+struct iwl_rem_sta_resp {
+	u8 status;
+} __packed;
+
+/*
+ *  REPLY_REM_STA = 0x19 (command)
+ */
+struct iwl_rem_sta_cmd {
+	u8 num_sta;     /* number of removed stations */
+	u8 reserved[3];
+	u8 addr[ETH_ALEN]; /* MAC addr of the first station */
+	u8 reserved2[2];
+} __packed;
+
+#define IWL_TX_FIFO_BK_MSK		cpu_to_le32(BIT(0))
+#define IWL_TX_FIFO_BE_MSK		cpu_to_le32(BIT(1))
+#define IWL_TX_FIFO_VI_MSK		cpu_to_le32(BIT(2))
+#define IWL_TX_FIFO_VO_MSK		cpu_to_le32(BIT(3))
+#define IWL_AGG_TX_QUEUE_MSK		cpu_to_le32(0xffc00)
+
+#define IWL_DROP_SINGLE		0
+#define IWL_DROP_SELECTED	1
+#define IWL_DROP_ALL		2
+
+/*
+ * REPLY_WEP_KEY = 0x20
+ */
+struct iwl_wep_key {
+	u8 key_index;
+	u8 key_offset;
+	u8 reserved1[2];
+	u8 key_size;
+	u8 reserved2[3];
+	u8 key[16];
+} __packed;
+
+struct iwl_wep_cmd {
+	u8 num_keys;
+	u8 global_key_type;
+	u8 flags;
+	u8 reserved;
+	struct iwl_wep_key key[0];
+} __packed;
+
+#define WEP_KEY_WEP_TYPE 1
+#define WEP_KEYS_MAX 4
+#define WEP_INVALID_OFFSET 0xff
+#define WEP_KEY_LEN_64 5
+#define WEP_KEY_LEN_128 13
+
+/******************************************************************************
+ * (4)
+ * Rx Responses:
+ *
+ *****************************************************************************/
+
+#define RX_RES_STATUS_NO_CRC32_ERROR	cpu_to_le32(1 << 0)
+#define RX_RES_STATUS_NO_RXE_OVERFLOW	cpu_to_le32(1 << 1)
+
+#define RX_RES_PHY_FLAGS_BAND_24_MSK	cpu_to_le16(1 << 0)
+#define RX_RES_PHY_FLAGS_MOD_CCK_MSK		cpu_to_le16(1 << 1)
+#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	cpu_to_le16(1 << 2)
+#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK	cpu_to_le16(1 << 3)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK		0xf0
+#define RX_RES_PHY_FLAGS_ANTENNA_POS		4
+
+#define RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
+#define RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
+#define RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
+#define RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
+#define RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
+#define	RX_RES_STATUS_SEC_TYPE_ERR	(0x7 << 8)
+
+#define RX_RES_STATUS_STATION_FOUND	(1<<6)
+#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH	(1<<7)
+
+#define RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
+#define RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
+#define RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
+#define RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
+#define RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
+
+#define RX_MPDU_RES_STATUS_ICV_OK	(0x20)
+#define RX_MPDU_RES_STATUS_MIC_OK	(0x40)
+#define RX_MPDU_RES_STATUS_TTAK_OK	(1 << 7)
+#define RX_MPDU_RES_STATUS_DEC_DONE_MSK	(0x800)
+
+
+struct iwl3945_rx_frame_stats {
+	u8 phy_count;
+	u8 id;
+	u8 rssi;
+	u8 agc;
+	__le16 sig_avg;
+	__le16 noise_diff;
+	u8 payload[0];
+} __packed;
+
+struct iwl3945_rx_frame_hdr {
+	__le16 channel;
+	__le16 phy_flags;
+	u8 reserved1;
+	u8 rate;
+	__le16 len;
+	u8 payload[0];
+} __packed;
+
+struct iwl3945_rx_frame_end {
+	__le32 status;
+	__le64 timestamp;
+	__le32 beacon_timestamp;
+} __packed;
+
+/*
+ * REPLY_3945_RX = 0x1b (response only, not a command)
+ *
+ * NOTE:  DO NOT dereference from casts to this structure
+ * It is provided only for calculating minimum data set size.
+ * The actual offsets of the hdr and end are dynamic based on
+ * stats.phy_count
+ */
+struct iwl3945_rx_frame {
+	struct iwl3945_rx_frame_stats stats;
+	struct iwl3945_rx_frame_hdr hdr;
+	struct iwl3945_rx_frame_end end;
+} __packed;
+
+#define IWL39_RX_FRAME_SIZE	(4 + sizeof(struct iwl3945_rx_frame))
+
+/* Fixed (non-configurable) rx data from phy */
+
+#define IWL49_RX_RES_PHY_CNT 14
+#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET	(4)
+#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK	(0x70)
+#define IWL49_AGC_DB_MASK			(0x3f80)	/* MASK(7,13) */
+#define IWL49_AGC_DB_POS			(7)
+struct iwl4965_rx_non_cfg_phy {
+	__le16 ant_selection;	/* ant A bit 4, ant B bit 5, ant C bit 6 */
+	__le16 agc_info;	/* agc code 0:6, agc dB 7:13, reserved 14:15 */
+	u8 rssi_info[6];	/* we use even entries, 0/2/4 for A/B/C rssi */
+	u8 pad[0];
+} __packed;
+
+
+/*
+ * REPLY_RX = 0xc3 (response only, not a command)
+ * Used only for legacy (non 11n) frames.
+ */
+struct iwl_rx_phy_res {
+	u8 non_cfg_phy_cnt;     /* non configurable DSP phy data byte count */
+	u8 cfg_phy_cnt;		/* configurable DSP phy data byte count */
+	u8 stat_id;		/* configurable DSP phy data set ID */
+	u8 reserved1;
+	__le64 timestamp;	/* TSF at on air rise */
+	__le32 beacon_time_stamp; /* beacon at on-air rise */
+	__le16 phy_flags;	/* general phy flags: band, modulation, ... */
+	__le16 channel;		/* channel number */
+	u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */
+	__le32 rate_n_flags;	/* RATE_MCS_* */
+	__le16 byte_count;	/* frame's byte-count */
+	__le16 frame_time;	/* frame's time on the air */
+} __packed;
+
+struct iwl_rx_mpdu_res_start {
+	__le16 byte_count;
+	__le16 reserved;
+} __packed;
+
+
+/******************************************************************************
+ * (5)
+ * Tx Commands & Responses:
+ *
+ * Driver must place each REPLY_TX command into one of the prioritized Tx
+ * queues in host DRAM, shared between driver and device (see comments for
+ * SCD registers and Tx/Rx Queues).  When the device's Tx scheduler and uCode
+ * are preparing to transmit, the device pulls the Tx command over the PCI
+ * bus via one of the device's Tx DMA channels, to fill an internal FIFO
+ * from which data will be transmitted.
+ *
+ * uCode handles all timing and protocol related to control frames
+ * (RTS/CTS/ACK), based on flags in the Tx command.  uCode and Tx scheduler
+ * handle reception of block-acks; uCode updates the host driver via
+ * REPLY_COMPRESSED_BA.
+ *
+ * uCode handles retrying Tx when an ACK is expected but not received.
+ * This includes trying lower data rates than the one requested in the Tx
+ * command, as set up by the REPLY_RATE_SCALE (for 3945) or
+ * REPLY_TX_LINK_QUALITY_CMD (4965).
+ *
+ * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
+ * This command must be executed after every RXON command, before Tx can occur.
+ *****************************************************************************/
+
+/* REPLY_TX Tx flags field */
+
+/*
+ * 1: Use Request-To-Send protocol before this frame.
+ * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
+ */
+#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
+
+/*
+ * 1: Transmit Clear-To-Send to self before this frame.
+ * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
+ * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
+ */
+#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
+
+/* 1: Expect ACK from receiving station
+ * 0: Don't expect ACK (MAC header's duration field s/b 0)
+ * Set this for unicast frames, but not broadcast/multicast. */
+#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
+
+/* For 4965 devices:
+ * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
+ *    Tx command's initial_rate_index indicates first rate to try;
+ *    uCode walks through table for additional Tx attempts.
+ * 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
+ *    This rate will be used for all Tx attempts; it will not be scaled. */
+#define TX_CMD_FLG_STA_RATE_MSK cpu_to_le32(1 << 4)
+
+/* 1: Expect immediate block-ack.
+ * Set when Txing a block-ack request frame.  Also set TX_CMD_FLG_ACK_MSK. */
+#define TX_CMD_FLG_IMM_BA_RSP_MASK  cpu_to_le32(1 << 6)
+
+/*
+ * 1: Frame requires full Tx-Op protection.
+ * Set this if either RTS or CTS Tx Flag gets set.
+ */
+#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
+
+/* Tx antenna selection field; used only for 3945, reserved (0) for 4965 devices.
+ * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
+#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
+#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
+#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
+
+/* 1: uCode overrides sequence control field in MAC header.
+ * 0: Driver provides sequence control field in MAC header.
+ * Set this for management frames, non-QOS data frames, non-unicast frames,
+ * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
+#define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13)
+
+/* 1: This frame is non-last MPDU; more fragments are coming.
+ * 0: Last fragment, or not using fragmentation. */
+#define TX_CMD_FLG_MORE_FRAG_MSK cpu_to_le32(1 << 14)
+
+/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
+ * 0: No TSF required in outgoing frame.
+ * Set this for transmitting beacons and probe responses. */
+#define TX_CMD_FLG_TSF_MSK cpu_to_le32(1 << 16)
+
+/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
+ *    alignment of frame's payload data field.
+ * 0: No pad
+ * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
+ * field (but not both).  Driver must align frame data (i.e. data following
+ * MAC header) to DWORD boundary. */
+#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(1 << 20)
+
+/* accelerate aggregation support
+ * 0 - no CCMP encryption; 1 - CCMP encryption */
+#define TX_CMD_FLG_AGG_CCMP_MSK cpu_to_le32(1 << 22)
+
+/* HCCA-AP - disable duration overwriting. */
+#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25)
+
+
+/*
+ * TX command security control
+ */
+#define TX_CMD_SEC_WEP		0x01
+#define TX_CMD_SEC_CCM		0x02
+#define TX_CMD_SEC_TKIP		0x03
+#define TX_CMD_SEC_MSK		0x03
+#define TX_CMD_SEC_SHIFT	6
+#define TX_CMD_SEC_KEY128	0x08
+
+/*
+ * security overhead sizes
+ */
+#define WEP_IV_LEN 4
+#define WEP_ICV_LEN 4
+#define CCMP_MIC_LEN 8
+#define TKIP_ICV_LEN 4
+
+/*
+ * REPLY_TX = 0x1c (command)
+ */
+
+struct iwl3945_tx_cmd {
+	/*
+	 * MPDU byte count:
+	 * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+	 * + 8 byte IV for CCM or TKIP (not used for WEP)
+	 * + Data payload
+	 * + 8-byte MIC (not used for CCM/WEP)
+	 * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
+	 *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+	 * Range: 14-2342 bytes.
+	 */
+	__le16 len;
+
+	/*
+	 * MPDU or MSDU byte count for next frame.
+	 * Used for fragmentation and bursting, but not 11n aggregation.
+	 * Same as "len", but for next frame.  Set to 0 if not applicable.
+	 */
+	__le16 next_frame_len;
+
+	__le32 tx_flags;	/* TX_CMD_FLG_* */
+
+	u8 rate;
+
+	/* Index of recipient station in uCode's station table */
+	u8 sta_id;
+	u8 tid_tspec;
+	u8 sec_ctl;
+	u8 key[16];
+	union {
+		u8 byte[8];
+		__le16 word[4];
+		__le32 dw[2];
+	} tkip_mic;
+	__le32 next_frame_info;
+	union {
+		__le32 life_time;
+		__le32 attempt;
+	} stop_time;
+	u8 supp_rates[2];
+	u8 rts_retry_limit;	/*byte 50 */
+	u8 data_retry_limit;	/*byte 51 */
+	union {
+		__le16 pm_frame_timeout;
+		__le16 attempt_duration;
+	} timeout;
+
+	/*
+	 * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+	 * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+	 */
+	__le16 driver_txop;
+
+	/*
+	 * MAC header goes here, followed by 2 bytes padding if MAC header
+	 * length is 26 or 30 bytes, followed by payload data
+	 */
+	u8 payload[0];
+	struct ieee80211_hdr hdr[0];
+} __packed;
+
+/*
+ * REPLY_TX = 0x1c (response)
+ */
+struct iwl3945_tx_resp {
+	u8 failure_rts;
+	u8 failure_frame;
+	u8 bt_kill_count;
+	u8 rate;
+	__le32 wireless_media_time;
+	__le32 status;		/* TX status */
+} __packed;
+
+
+/*
+ * 4965 uCode updates these Tx attempt count values in host DRAM.
+ * Used for managing Tx retries when expecting block-acks.
+ * Driver should set these fields to 0.
+ */
+struct iwl_dram_scratch {
+	u8 try_cnt;		/* Tx attempts */
+	u8 bt_kill_cnt;		/* Tx attempts blocked by Bluetooth device */
+	__le16 reserved;
+} __packed;
+
+struct iwl_tx_cmd {
+	/*
+	 * MPDU byte count:
+	 * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+	 * + 8 byte IV for CCM or TKIP (not used for WEP)
+	 * + Data payload
+	 * + 8-byte MIC (not used for CCM/WEP)
+	 * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
+	 *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+	 * Range: 14-2342 bytes.
+	 */
+	__le16 len;
+
+	/*
+	 * MPDU or MSDU byte count for next frame.
+	 * Used for fragmentation and bursting, but not 11n aggregation.
+	 * Same as "len", but for next frame.  Set to 0 if not applicable.
+	 */
+	__le16 next_frame_len;
+
+	__le32 tx_flags;	/* TX_CMD_FLG_* */
+
+	/* uCode may modify this field of the Tx command (in host DRAM!).
+	 * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
+	struct iwl_dram_scratch scratch;
+
+	/* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
+	__le32 rate_n_flags;	/* RATE_MCS_* */
+
+	/* Index of destination station in uCode's station table */
+	u8 sta_id;
+
+	/* Type of security encryption:  CCM or TKIP */
+	u8 sec_ctl;		/* TX_CMD_SEC_* */
+
+	/*
+	 * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial
+	 * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set.  Normally "0" for
+	 * data frames, this field may be used to selectively reduce initial
+	 * rate (via non-0 value) for special frames (e.g. management), while
+	 * still supporting rate scaling for all frames.
+	 */
+	u8 initial_rate_index;
+	u8 reserved;
+	u8 key[16];
+	__le16 next_frame_flags;
+	__le16 reserved2;
+	union {
+		__le32 life_time;
+		__le32 attempt;
+	} stop_time;
+
+	/* Host DRAM physical address pointer to "scratch" in this command.
+	 * Must be dword aligned.  "0" in dram_lsb_ptr disables usage. */
+	__le32 dram_lsb_ptr;
+	u8 dram_msb_ptr;
+
+	u8 rts_retry_limit;	/*byte 50 */
+	u8 data_retry_limit;	/*byte 51 */
+	u8 tid_tspec;
+	union {
+		__le16 pm_frame_timeout;
+		__le16 attempt_duration;
+	} timeout;
+
+	/*
+	 * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+	 * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+	 */
+	__le16 driver_txop;
+
+	/*
+	 * MAC header goes here, followed by 2 bytes padding if MAC header
+	 * length is 26 or 30 bytes, followed by payload data
+	 */
+	u8 payload[0];
+	struct ieee80211_hdr hdr[0];
+} __packed;
+
+/* TX command response is sent after *3945* transmission attempts.
+ *
+ * NOTES:
+ *
+ * TX_STATUS_FAIL_NEXT_FRAG
+ *
+ * If the fragment flag in the MAC header for the frame being transmitted
+ * is set and there is insufficient time to transmit the next frame, the
+ * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'.
+ *
+ * TX_STATUS_FIFO_UNDERRUN
+ *
+ * Indicates the host did not provide bytes to the FIFO fast enough while
+ * a TX was in progress.
+ *
+ * TX_STATUS_FAIL_MGMNT_ABORT
+ *
+ * This status is only possible if the ABORT ON MGMT RX parameter was
+ * set to true with the TX command.
+ *
+ * If the MSB of the status parameter is set then an abort sequence is
+ * required.  This sequence consists of the host activating the TX Abort
+ * control line, and then waiting for the TX Abort command response.  This
+ * indicates that a the device is no longer in a transmit state, and that the
+ * command FIFO has been cleared.  The host must then deactivate the TX Abort
+ * control line.  Receiving is still allowed in this case.
+ */
+enum {
+	TX_3945_STATUS_SUCCESS = 0x01,
+	TX_3945_STATUS_DIRECT_DONE = 0x02,
+	TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82,
+	TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83,
+	TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
+	TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85,
+	TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86,
+	TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87,
+	TX_3945_STATUS_FAIL_DEST_PS = 0x88,
+	TX_3945_STATUS_FAIL_ABORTED = 0x89,
+	TX_3945_STATUS_FAIL_BT_RETRY = 0x8a,
+	TX_3945_STATUS_FAIL_STA_INVALID = 0x8b,
+	TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c,
+	TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d,
+	TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e,
+	TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
+	TX_3945_STATUS_FAIL_TX_LOCKED = 0x90,
+	TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
+};
+
+/*
+ * TX command response is sent after *4965* transmission attempts.
+ *
+ * both postpone and abort status are expected behavior from uCode. there is
+ * no special operation required from driver; except for RFKILL_FLUSH,
+ * which required tx flush host command to flush all the tx frames in queues
+ */
+enum {
+	TX_STATUS_SUCCESS = 0x01,
+	TX_STATUS_DIRECT_DONE = 0x02,
+	/* postpone TX */
+	TX_STATUS_POSTPONE_DELAY = 0x40,
+	TX_STATUS_POSTPONE_FEW_BYTES = 0x41,
+	TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43,
+	TX_STATUS_POSTPONE_CALC_TTAK = 0x44,
+	/* abort TX */
+	TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81,
+	TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
+	TX_STATUS_FAIL_LONG_LIMIT = 0x83,
+	TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
+	TX_STATUS_FAIL_DRAIN_FLOW = 0x85,
+	TX_STATUS_FAIL_RFKILL_FLUSH = 0x86,
+	TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
+	TX_STATUS_FAIL_DEST_PS = 0x88,
+	TX_STATUS_FAIL_HOST_ABORTED = 0x89,
+	TX_STATUS_FAIL_BT_RETRY = 0x8a,
+	TX_STATUS_FAIL_STA_INVALID = 0x8b,
+	TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
+	TX_STATUS_FAIL_TID_DISABLE = 0x8d,
+	TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e,
+	TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
+	TX_STATUS_FAIL_PASSIVE_NO_RX = 0x90,
+	TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
+};
+
+#define	TX_PACKET_MODE_REGULAR		0x0000
+#define	TX_PACKET_MODE_BURST_SEQ	0x0100
+#define	TX_PACKET_MODE_BURST_FIRST	0x0200
+
+enum {
+	TX_POWER_PA_NOT_ACTIVE = 0x0,
+};
+
+enum {
+	TX_STATUS_MSK = 0x000000ff,		/* bits 0:7 */
+	TX_STATUS_DELAY_MSK = 0x00000040,
+	TX_STATUS_ABORT_MSK = 0x00000080,
+	TX_PACKET_MODE_MSK = 0x0000ff00,	/* bits 8:15 */
+	TX_FIFO_NUMBER_MSK = 0x00070000,	/* bits 16:18 */
+	TX_RESERVED = 0x00780000,		/* bits 19:22 */
+	TX_POWER_PA_DETECT_MSK = 0x7f800000,	/* bits 23:30 */
+	TX_ABORT_REQUIRED_MSK = 0x80000000,	/* bits 31:31 */
+};
+
+/* *******************************
+ * TX aggregation status
+ ******************************* */
+
+enum {
+	AGG_TX_STATE_TRANSMITTED = 0x00,
+	AGG_TX_STATE_UNDERRUN_MSK = 0x01,
+	AGG_TX_STATE_FEW_BYTES_MSK = 0x04,
+	AGG_TX_STATE_ABORT_MSK = 0x08,
+	AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10,
+	AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20,
+	AGG_TX_STATE_SCD_QUERY_MSK = 0x80,
+	AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100,
+	AGG_TX_STATE_RESPONSE_MSK = 0x1ff,
+	AGG_TX_STATE_DUMP_TX_MSK = 0x200,
+	AGG_TX_STATE_DELAY_TX_MSK = 0x400
+};
+
+#define AGG_TX_STATUS_MSK	0x00000fff	/* bits 0:11 */
+#define AGG_TX_TRY_MSK		0x0000f000	/* bits 12:15 */
+
+#define AGG_TX_STATE_LAST_SENT_MSK  (AGG_TX_STATE_LAST_SENT_TTL_MSK | \
+				     AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK)
+
+/* # tx attempts for first frame in aggregation */
+#define AGG_TX_STATE_TRY_CNT_POS 12
+#define AGG_TX_STATE_TRY_CNT_MSK 0xf000
+
+/* Command ID and sequence number of Tx command for this frame */
+#define AGG_TX_STATE_SEQ_NUM_POS 16
+#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
+
+/*
+ * REPLY_TX = 0x1c (response)
+ *
+ * This response may be in one of two slightly different formats, indicated
+ * by the frame_count field:
+ *
+ * 1)  No aggregation (frame_count == 1).  This reports Tx results for
+ *     a single frame.  Multiple attempts, at various bit rates, may have
+ *     been made for this frame.
+ *
+ * 2)  Aggregation (frame_count > 1).  This reports Tx results for
+ *     2 or more frames that used block-acknowledge.  All frames were
+ *     transmitted at same rate.  Rate scaling may have been used if first
+ *     frame in this new agg block failed in previous agg block(s).
+ *
+ *     Note that, for aggregation, ACK (block-ack) status is not delivered here;
+ *     block-ack has not been received by the time the 4965 device records
+ *     this status.
+ *     This status relates to reasons the tx might have been blocked or aborted
+ *     within the sending station (this 4965 device), rather than whether it was
+ *     received successfully by the destination station.
+ */
+struct agg_tx_status {
+	__le16 status;
+	__le16 sequence;
+} __packed;
+
+struct iwl4965_tx_resp {
+	u8 frame_count;		/* 1 no aggregation, >1 aggregation */
+	u8 bt_kill_count;	/* # blocked by bluetooth (unused for agg) */
+	u8 failure_rts;		/* # failures due to unsuccessful RTS */
+	u8 failure_frame;	/* # failures due to no ACK (unused for agg) */
+
+	/* For non-agg:  Rate at which frame was successful.
+	 * For agg:  Rate at which all frames were transmitted. */
+	__le32 rate_n_flags;	/* RATE_MCS_*  */
+
+	/* For non-agg:  RTS + CTS + frame tx attempts time + ACK.
+	 * For agg:  RTS + CTS + aggregation tx time + block-ack time. */
+	__le16 wireless_media_time;	/* uSecs */
+
+	__le16 reserved;
+	__le32 pa_power1;	/* RF power amplifier measurement (not used) */
+	__le32 pa_power2;
+
+	/*
+	 * For non-agg:  frame status TX_STATUS_*
+	 * For agg:  status of 1st frame, AGG_TX_STATE_*; other frame status
+	 *           fields follow this one, up to frame_count.
+	 *           Bit fields:
+	 *           11- 0:  AGG_TX_STATE_* status code
+	 *           15-12:  Retry count for 1st frame in aggregation (retries
+	 *                   occur if tx failed for this frame when it was a
+	 *                   member of a previous aggregation block).  If rate
+	 *                   scaling is used, retry count indicates the rate
+	 *                   table entry used for all frames in the new agg.
+	 *           31-16:  Sequence # for this frame's Tx cmd (not SSN!)
+	 */
+	union {
+		__le32 status;
+		struct agg_tx_status agg_status[0]; /* for each agg frame */
+	} u;
+} __packed;
+
+/*
+ * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+ *
+ * Reports Block-Acknowledge from recipient station
+ */
+struct iwl_compressed_ba_resp {
+	__le32 sta_addr_lo32;
+	__le16 sta_addr_hi16;
+	__le16 reserved;
+
+	/* Index of recipient (BA-sending) station in uCode's station table */
+	u8 sta_id;
+	u8 tid;
+	__le16 seq_ctl;
+	__le64 bitmap;
+	__le16 scd_flow;
+	__le16 scd_ssn;
+} __packed;
+
+/*
+ * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
+ *
+ * See details under "TXPOWER" in iwl-4965-hw.h.
+ */
+
+struct iwl3945_txpowertable_cmd {
+	u8 band;		/* 0: 5 GHz, 1: 2.4 GHz */
+	u8 reserved;
+	__le16 channel;
+	struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+} __packed;
+
+struct iwl4965_txpowertable_cmd {
+	u8 band;		/* 0: 5 GHz, 1: 2.4 GHz */
+	u8 reserved;
+	__le16 channel;
+	struct iwl4965_tx_power_db tx_power;
+} __packed;
+
+
+/**
+ * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response
+ *
+ * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
+ *
+ * NOTE: The table of rates passed to the uCode via the
+ * RATE_SCALE command sets up the corresponding order of
+ * rates used for all related commands, including rate
+ * masks, etc.
+ *
+ * For example, if you set 9MB (PLCP 0x0f) as the first
+ * rate in the rate table, the bit mask for that rate
+ * when passed through ofdm_basic_rates on the REPLY_RXON
+ * command would be bit 0 (1 << 0)
+ */
+struct iwl3945_rate_scaling_info {
+	__le16 rate_n_flags;
+	u8 try_cnt;
+	u8 next_rate_index;
+} __packed;
+
+struct iwl3945_rate_scaling_cmd {
+	u8 table_id;
+	u8 reserved[3];
+	struct iwl3945_rate_scaling_info table[IWL_MAX_RATES];
+} __packed;
+
+
+/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
+#define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK	(1 << 0)
+
+/* # of EDCA prioritized tx fifos */
+#define  LINK_QUAL_AC_NUM AC_NUM
+
+/* # entries in rate scale table to support Tx retries */
+#define  LINK_QUAL_MAX_RETRY_NUM 16
+
+/* Tx antenna selection values */
+#define  LINK_QUAL_ANT_A_MSK (1 << 0)
+#define  LINK_QUAL_ANT_B_MSK (1 << 1)
+#define  LINK_QUAL_ANT_MSK   (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
+
+
+/**
+ * struct iwl_link_qual_general_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl_link_qual_general_params {
+	u8 flags;
+
+	/* No entries at or above this (driver chosen) index contain MIMO */
+	u8 mimo_delimiter;
+
+	/* Best single antenna to use for single stream (legacy, SISO). */
+	u8 single_stream_ant_msk;	/* LINK_QUAL_ANT_* */
+
+	/* Best antennas to use for MIMO (unused for 4965, assumes both). */
+	u8 dual_stream_ant_msk;		/* LINK_QUAL_ANT_* */
+
+	/*
+	 * If driver needs to use different initial rates for different
+	 * EDCA QOS access categories (as implemented by tx fifos 0-3),
+	 * this table will set that up, by indicating the indexes in the
+	 * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start.
+	 * Otherwise, driver should set all entries to 0.
+	 *
+	 * Entry usage:
+	 * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice
+	 * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3.
+	 */
+	u8 start_rate_index[LINK_QUAL_AC_NUM];
+} __packed;
+
+#define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000) /* 4 milliseconds */
+#define LINK_QUAL_AGG_TIME_LIMIT_MAX	(8000)
+#define LINK_QUAL_AGG_TIME_LIMIT_MIN	(100)
+
+#define LINK_QUAL_AGG_DISABLE_START_DEF	(3)
+#define LINK_QUAL_AGG_DISABLE_START_MAX	(255)
+#define LINK_QUAL_AGG_DISABLE_START_MIN	(0)
+
+#define LINK_QUAL_AGG_FRAME_LIMIT_DEF	(31)
+#define LINK_QUAL_AGG_FRAME_LIMIT_MAX	(63)
+#define LINK_QUAL_AGG_FRAME_LIMIT_MIN	(0)
+
+/**
+ * struct iwl_link_qual_agg_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl_link_qual_agg_params {
+
+	/*
+	 *Maximum number of uSec in aggregation.
+	 * default set to 4000 (4 milliseconds) if not configured in .cfg
+	 */
+	__le16 agg_time_limit;
+
+	/*
+	 * Number of Tx retries allowed for a frame, before that frame will
+	 * no longer be considered for the start of an aggregation sequence
+	 * (scheduler will then try to tx it as single frame).
+	 * Driver should set this to 3.
+	 */
+	u8 agg_dis_start_th;
+
+	/*
+	 * Maximum number of frames in aggregation.
+	 * 0 = no limit (default).  1 = no aggregation.
+	 * Other values = max # frames in aggregation.
+	 */
+	u8 agg_frame_cnt_limit;
+
+	__le32 reserved;
+} __packed;
+
+/*
+ * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
+ *
+ * For 4965 devices only; 3945 uses REPLY_RATE_SCALE.
+ *
+ * Each station in the 4965 device's internal station table has its own table
+ * of 16
+ * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when
+ * an ACK is not received.  This command replaces the entire table for
+ * one station.
+ *
+ * NOTE:  Station must already be in 4965 device's station table.
+ *	  Use REPLY_ADD_STA.
+ *
+ * The rate scaling procedures described below work well.  Of course, other
+ * procedures are possible, and may work better for particular environments.
+ *
+ *
+ * FILLING THE RATE TABLE
+ *
+ * Given a particular initial rate and mode, as determined by the rate
+ * scaling algorithm described below, the Linux driver uses the following
+ * formula to fill the rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table in the
+ * Link Quality command:
+ *
+ *
+ * 1)  If using High-throughput (HT) (SISO or MIMO) initial rate:
+ *     a) Use this same initial rate for first 3 entries.
+ *     b) Find next lower available rate using same mode (SISO or MIMO),
+ *        use for next 3 entries.  If no lower rate available, switch to
+ *        legacy mode (no HT40 channel, no MIMO, no short guard interval).
+ *     c) If using MIMO, set command's mimo_delimiter to number of entries
+ *        using MIMO (3 or 6).
+ *     d) After trying 2 HT rates, switch to legacy mode (no HT40 channel,
+ *        no MIMO, no short guard interval), at the next lower bit rate
+ *        (e.g. if second HT bit rate was 54, try 48 legacy), and follow
+ *        legacy procedure for remaining table entries.
+ *
+ * 2)  If using legacy initial rate:
+ *     a) Use the initial rate for only one entry.
+ *     b) For each following entry, reduce the rate to next lower available
+ *        rate, until reaching the lowest available rate.
+ *     c) When reducing rate, also switch antenna selection.
+ *     d) Once lowest available rate is reached, repeat this rate until
+ *        rate table is filled (16 entries), switching antenna each entry.
+ *
+ *
+ * ACCUMULATING HISTORY
+ *
+ * The rate scaling algorithm for 4965 devices, as implemented in Linux driver,
+ * uses two sets of frame Tx success history:  One for the current/active
+ * modulation mode, and one for a speculative/search mode that is being
+ * attempted. If the speculative mode turns out to be more effective (i.e.
+ * actual transfer rate is better), then the driver continues to use the
+ * speculative mode as the new current active mode.
+ *
+ * Each history set contains, separately for each possible rate, data for a
+ * sliding window of the 62 most recent tx attempts at that rate.  The data
+ * includes a shifting bitmap of success(1)/failure(0), and sums of successful
+ * and attempted frames, from which the driver can additionally calculate a
+ * success ratio (success / attempted) and number of failures
+ * (attempted - success), and control the size of the window (attempted).
+ * The driver uses the bit map to remove successes from the success sum, as
+ * the oldest tx attempts fall out of the window.
+ *
+ * When the 4965 device makes multiple tx attempts for a given frame, each
+ * attempt might be at a different rate, and have different modulation
+ * characteristics (e.g. antenna, fat channel, short guard interval), as set
+ * up in the rate scaling table in the Link Quality command.  The driver must
+ * determine which rate table entry was used for each tx attempt, to determine
+ * which rate-specific history to update, and record only those attempts that
+ * match the modulation characteristics of the history set.
+ *
+ * When using block-ack (aggregation), all frames are transmitted at the same
+ * rate, since there is no per-attempt acknowledgment from the destination
+ * station.  The Tx response struct iwl_tx_resp indicates the Tx rate in
+ * rate_n_flags field.  After receiving a block-ack, the driver can update
+ * history for the entire block all at once.
+ *
+ *
+ * FINDING BEST STARTING RATE:
+ *
+ * When working with a selected initial modulation mode (see below), the
+ * driver attempts to find a best initial rate.  The initial rate is the
+ * first entry in the Link Quality command's rate table.
+ *
+ * 1)  Calculate actual throughput (success ratio * expected throughput, see
+ *     table below) for current initial rate.  Do this only if enough frames
+ *     have been attempted to make the value meaningful:  at least 6 failed
+ *     tx attempts, or at least 8 successes.  If not enough, don't try rate
+ *     scaling yet.
+ *
+ * 2)  Find available rates adjacent to current initial rate.  Available means:
+ *     a)  supported by hardware &&
+ *     b)  supported by association &&
+ *     c)  within any constraints selected by user
+ *
+ * 3)  Gather measured throughputs for adjacent rates.  These might not have
+ *     enough history to calculate a throughput.  That's okay, we might try
+ *     using one of them anyway!
+ *
+ * 4)  Try decreasing rate if, for current rate:
+ *     a)  success ratio is < 15% ||
+ *     b)  lower adjacent rate has better measured throughput ||
+ *     c)  higher adjacent rate has worse throughput, and lower is unmeasured
+ *
+ *     As a sanity check, if decrease was determined above, leave rate
+ *     unchanged if:
+ *     a)  lower rate unavailable
+ *     b)  success ratio at current rate > 85% (very good)
+ *     c)  current measured throughput is better than expected throughput
+ *         of lower rate (under perfect 100% tx conditions, see table below)
+ *
+ * 5)  Try increasing rate if, for current rate:
+ *     a)  success ratio is < 15% ||
+ *     b)  both adjacent rates' throughputs are unmeasured (try it!) ||
+ *     b)  higher adjacent rate has better measured throughput ||
+ *     c)  lower adjacent rate has worse throughput, and higher is unmeasured
+ *
+ *     As a sanity check, if increase was determined above, leave rate
+ *     unchanged if:
+ *     a)  success ratio at current rate < 70%.  This is not particularly
+ *         good performance; higher rate is sure to have poorer success.
+ *
+ * 6)  Re-evaluate the rate after each tx frame.  If working with block-
+ *     acknowledge, history and statistics may be calculated for the entire
+ *     block (including prior history that fits within the history windows),
+ *     before re-evaluation.
+ *
+ * FINDING BEST STARTING MODULATION MODE:
+ *
+ * After working with a modulation mode for a "while" (and doing rate scaling),
+ * the driver searches for a new initial mode in an attempt to improve
+ * throughput.  The "while" is measured by numbers of attempted frames:
+ *
+ * For legacy mode, search for new mode after:
+ *   480 successful frames, or 160 failed frames
+ * For high-throughput modes (SISO or MIMO), search for new mode after:
+ *   4500 successful frames, or 400 failed frames
+ *
+ * Mode switch possibilities are (3 for each mode):
+ *
+ * For legacy:
+ *   Change antenna, try SISO (if HT association), try MIMO (if HT association)
+ * For SISO:
+ *   Change antenna, try MIMO, try shortened guard interval (SGI)
+ * For MIMO:
+ *   Try SISO antenna A, SISO antenna B, try shortened guard interval (SGI)
+ *
+ * When trying a new mode, use the same bit rate as the old/current mode when
+ * trying antenna switches and shortened guard interval.  When switching to
+ * SISO from MIMO or legacy, or to MIMO from SISO or legacy, use a rate
+ * for which the expected throughput (under perfect conditions) is about the
+ * same or slightly better than the actual measured throughput delivered by
+ * the old/current mode.
+ *
+ * Actual throughput can be estimated by multiplying the expected throughput
+ * by the success ratio (successful / attempted tx frames).  Frame size is
+ * not considered in this calculation; it assumes that frame size will average
+ * out to be fairly consistent over several samples.  The following are
+ * metric values for expected throughput assuming 100% success ratio.
+ * Only G band has support for CCK rates:
+ *
+ *           RATE:  1    2    5   11    6   9   12   18   24   36   48   54   60
+ *
+ *              G:  7   13   35   58   40  57   72   98  121  154  177  186  186
+ *              A:  0    0    0    0   40  57   72   98  121  154  177  186  186
+ *     SISO 20MHz:  0    0    0    0   42  42   76  102  124  159  183  193  202
+ * SGI SISO 20MHz:  0    0    0    0   46  46   82  110  132  168  192  202  211
+ *     MIMO 20MHz:  0    0    0    0   74  74  123  155  179  214  236  244  251
+ * SGI MIMO 20MHz:  0    0    0    0   81  81  131  164  188  222  243  251  257
+ *     SISO 40MHz:  0    0    0    0   77  77  127  160  184  220  242  250  257
+ * SGI SISO 40MHz:  0    0    0    0   83  83  135  169  193  229  250  257  264
+ *     MIMO 40MHz:  0    0    0    0  123 123  182  214  235  264  279  285  289
+ * SGI MIMO 40MHz:  0    0    0    0  131 131  191  222  242  270  284  289  293
+ *
+ * After the new mode has been tried for a short while (minimum of 6 failed
+ * frames or 8 successful frames), compare success ratio and actual throughput
+ * estimate of the new mode with the old.  If either is better with the new
+ * mode, continue to use the new mode.
+ *
+ * Continue comparing modes until all 3 possibilities have been tried.
+ * If moving from legacy to HT, try all 3 possibilities from the new HT
+ * mode.  After trying all 3, a best mode is found.  Continue to use this mode
+ * for the longer "while" described above (e.g. 480 successful frames for
+ * legacy), and then repeat the search process.
+ *
+ */
+struct iwl_link_quality_cmd {
+
+	/* Index of destination/recipient station in uCode's station table */
+	u8 sta_id;
+	u8 reserved1;
+	__le16 control;		/* not used */
+	struct iwl_link_qual_general_params general_params;
+	struct iwl_link_qual_agg_params agg_params;
+
+	/*
+	 * Rate info; when using rate-scaling, Tx command's initial_rate_index
+	 * specifies 1st Tx rate attempted, via index into this table.
+	 * 4965 devices works its way through table when retrying Tx.
+	 */
+	struct {
+		__le32 rate_n_flags;	/* RATE_MCS_*, IWL_RATE_* */
+	} rs_table[LINK_QUAL_MAX_RETRY_NUM];
+	__le32 reserved2;
+} __packed;
+
+/*
+ * BT configuration enable flags:
+ *   bit 0 - 1: BT channel announcement enabled
+ *           0: disable
+ *   bit 1 - 1: priority of BT device enabled
+ *           0: disable
+ */
+#define BT_COEX_DISABLE (0x0)
+#define BT_ENABLE_CHANNEL_ANNOUNCE BIT(0)
+#define BT_ENABLE_PRIORITY	   BIT(1)
+
+#define BT_COEX_ENABLE  (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY)
+
+#define BT_LEAD_TIME_DEF (0x1E)
+
+#define BT_MAX_KILL_DEF (0x5)
+
+/*
+ * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
+ *
+ * 3945 and 4965 devices support hardware handshake with Bluetooth device on
+ * same platform.  Bluetooth device alerts wireless device when it will Tx;
+ * wireless device can delay or kill its own Tx to accommodate.
+ */
+struct iwl_bt_cmd {
+	u8 flags;
+	u8 lead_time;
+	u8 max_kill;
+	u8 reserved;
+	__le32 kill_ack_mask;
+	__le32 kill_cts_mask;
+} __packed;
+
+
+/******************************************************************************
+ * (6)
+ * Spectrum Management (802.11h) Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/*
+ * Spectrum Management
+ */
+#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK         | \
+				 RXON_FILTER_CTL2HOST_MSK        | \
+				 RXON_FILTER_ACCEPT_GRP_MSK      | \
+				 RXON_FILTER_DIS_DECRYPT_MSK     | \
+				 RXON_FILTER_DIS_GRP_DECRYPT_MSK | \
+				 RXON_FILTER_ASSOC_MSK           | \
+				 RXON_FILTER_BCON_AWARE_MSK)
+
+struct iwl_measure_channel {
+	__le32 duration;	/* measurement duration in extended beacon
+				 * format */
+	u8 channel;		/* channel to measure */
+	u8 type;		/* see enum iwl_measure_type */
+	__le16 reserved;
+} __packed;
+
+/*
+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
+ */
+struct iwl_spectrum_cmd {
+	__le16 len;		/* number of bytes starting from token */
+	u8 token;		/* token id */
+	u8 id;			/* measurement id -- 0 or 1 */
+	u8 origin;		/* 0 = TGh, 1 = other, 2 = TGk */
+	u8 periodic;		/* 1 = periodic */
+	__le16 path_loss_timeout;
+	__le32 start_time;	/* start time in extended beacon format */
+	__le32 reserved2;
+	__le32 flags;		/* rxon flags */
+	__le32 filter_flags;	/* rxon filter flags */
+	__le16 channel_count;	/* minimum 1, maximum 10 */
+	__le16 reserved3;
+	struct iwl_measure_channel channels[10];
+} __packed;
+
+/*
+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
+ */
+struct iwl_spectrum_resp {
+	u8 token;
+	u8 id;			/* id of the prior command replaced, or 0xff */
+	__le16 status;		/* 0 - command will be handled
+				 * 1 - cannot handle (conflicts with another
+				 *     measurement) */
+} __packed;
+
+enum iwl_measurement_state {
+	IWL_MEASUREMENT_START = 0,
+	IWL_MEASUREMENT_STOP = 1,
+};
+
+enum iwl_measurement_status {
+	IWL_MEASUREMENT_OK = 0,
+	IWL_MEASUREMENT_CONCURRENT = 1,
+	IWL_MEASUREMENT_CSA_CONFLICT = 2,
+	IWL_MEASUREMENT_TGH_CONFLICT = 3,
+	/* 4-5 reserved */
+	IWL_MEASUREMENT_STOPPED = 6,
+	IWL_MEASUREMENT_TIMEOUT = 7,
+	IWL_MEASUREMENT_PERIODIC_FAILED = 8,
+};
+
+#define NUM_ELEMENTS_IN_HISTOGRAM 8
+
+struct iwl_measurement_histogram {
+	__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 0.8usec counts */
+	__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 1usec counts */
+} __packed;
+
+/* clear channel availability counters */
+struct iwl_measurement_cca_counters {
+	__le32 ofdm;
+	__le32 cck;
+} __packed;
+
+enum iwl_measure_type {
+	IWL_MEASURE_BASIC = (1 << 0),
+	IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
+	IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
+	IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
+	IWL_MEASURE_FRAME = (1 << 4),
+	/* bits 5:6 are reserved */
+	IWL_MEASURE_IDLE = (1 << 7),
+};
+
+/*
+ * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
+ */
+struct iwl_spectrum_notification {
+	u8 id;			/* measurement id -- 0 or 1 */
+	u8 token;
+	u8 channel_index;	/* index in measurement channel list */
+	u8 state;		/* 0 - start, 1 - stop */
+	__le32 start_time;	/* lower 32-bits of TSF */
+	u8 band;		/* 0 - 5.2GHz, 1 - 2.4GHz */
+	u8 channel;
+	u8 type;		/* see enum iwl_measurement_type */
+	u8 reserved1;
+	/* NOTE:  cca_ofdm, cca_cck, basic_type, and histogram are only only
+	 * valid if applicable for measurement type requested. */
+	__le32 cca_ofdm;	/* cca fraction time in 40Mhz clock periods */
+	__le32 cca_cck;		/* cca fraction time in 44Mhz clock periods */
+	__le32 cca_time;	/* channel load time in usecs */
+	u8 basic_type;		/* 0 - bss, 1 - ofdm preamble, 2 -
+				 * unidentified */
+	u8 reserved2[3];
+	struct iwl_measurement_histogram histogram;
+	__le32 stop_time;	/* lower 32-bits of TSF */
+	__le32 status;		/* see iwl_measurement_status */
+} __packed;
+
+/******************************************************************************
+ * (7)
+ * Power Management Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl_powertable_cmd - Power Table Command
+ * @flags: See below:
+ *
+ * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
+ *
+ * PM allow:
+ *   bit 0 - '0' Driver not allow power management
+ *           '1' Driver allow PM (use rest of parameters)
+ *
+ * uCode send sleep notifications:
+ *   bit 1 - '0' Don't send sleep notification
+ *           '1' send sleep notification (SEND_PM_NOTIFICATION)
+ *
+ * Sleep over DTIM
+ *   bit 2 - '0' PM have to walk up every DTIM
+ *           '1' PM could sleep over DTIM till listen Interval.
+ *
+ * PCI power managed
+ *   bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
+ *           '1' !(PCI_CFG_LINK_CTRL & 0x1)
+ *
+ * Fast PD
+ *   bit 4 - '1' Put radio to sleep when receiving frame for others
+ *
+ * Force sleep Modes
+ *   bit 31/30- '00' use both mac/xtal sleeps
+ *              '01' force Mac sleep
+ *              '10' force xtal sleep
+ *              '11' Illegal set
+ *
+ * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
+ * ucode assume sleep over DTIM is allowed and we don't need to wake up
+ * for every DTIM.
+ */
+#define IWL_POWER_VEC_SIZE 5
+
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	cpu_to_le16(BIT(0))
+#define IWL_POWER_POWER_SAVE_ENA_MSK		cpu_to_le16(BIT(0))
+#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK	cpu_to_le16(BIT(1))
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK		cpu_to_le16(BIT(2))
+#define IWL_POWER_PCI_PM_MSK			cpu_to_le16(BIT(3))
+#define IWL_POWER_FAST_PD			cpu_to_le16(BIT(4))
+#define IWL_POWER_BEACON_FILTERING		cpu_to_le16(BIT(5))
+#define IWL_POWER_SHADOW_REG_ENA		cpu_to_le16(BIT(6))
+#define IWL_POWER_CT_KILL_SET			cpu_to_le16(BIT(7))
+
+struct iwl3945_powertable_cmd {
+	__le16 flags;
+	u8 reserved[2];
+	__le32 rx_data_timeout;
+	__le32 tx_data_timeout;
+	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
+} __packed;
+
+struct iwl_powertable_cmd {
+	__le16 flags;
+	u8 keep_alive_seconds;		/* 3945 reserved */
+	u8 debug_flags;			/* 3945 reserved */
+	__le32 rx_data_timeout;
+	__le32 tx_data_timeout;
+	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
+	__le32 keep_alive_beacons;
+} __packed;
+
+/*
+ * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
+ * all devices identical.
+ */
+struct iwl_sleep_notification {
+	u8 pm_sleep_mode;
+	u8 pm_wakeup_src;
+	__le16 reserved;
+	__le32 sleep_time;
+	__le32 tsf_low;
+	__le32 bcon_timer;
+} __packed;
+
+/* Sleep states.  all devices identical. */
+enum {
+	IWL_PM_NO_SLEEP = 0,
+	IWL_PM_SLP_MAC = 1,
+	IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
+	IWL_PM_SLP_FULL_MAC_CARD_STATE = 3,
+	IWL_PM_SLP_PHY = 4,
+	IWL_PM_SLP_REPENT = 5,
+	IWL_PM_WAKEUP_BY_TIMER = 6,
+	IWL_PM_WAKEUP_BY_DRIVER = 7,
+	IWL_PM_WAKEUP_BY_RFKILL = 8,
+	/* 3 reserved */
+	IWL_PM_NUM_OF_MODES = 12,
+};
+
+/*
+ * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
+ */
+struct iwl_card_state_notif {
+	__le32 flags;
+} __packed;
+
+#define HW_CARD_DISABLED   0x01
+#define SW_CARD_DISABLED   0x02
+#define CT_CARD_DISABLED   0x04
+#define RXON_CARD_DISABLED 0x10
+
+struct iwl_ct_kill_config {
+	__le32   reserved;
+	__le32   critical_temperature_M;
+	__le32   critical_temperature_R;
+}  __packed;
+
+/******************************************************************************
+ * (8)
+ * Scan Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+#define SCAN_CHANNEL_TYPE_PASSIVE cpu_to_le32(0)
+#define SCAN_CHANNEL_TYPE_ACTIVE  cpu_to_le32(1)
+
+/**
+ * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
+ *
+ * One for each channel in the scan list.
+ * Each channel can independently select:
+ * 1)  SSID for directed active scans
+ * 2)  Txpower setting (for rate specified within Tx command)
+ * 3)  How long to stay on-channel (behavior may be modified by quiet_time,
+ *     quiet_plcp_th, good_CRC_th)
+ *
+ * To avoid uCode errors, make sure the following are true (see comments
+ * under struct iwl_scan_cmd about max_out_time and quiet_time):
+ * 1)  If using passive_dwell (i.e. passive_dwell != 0):
+ *     active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
+ * 2)  quiet_time <= active_dwell
+ * 3)  If restricting off-channel time (i.e. max_out_time !=0):
+ *     passive_dwell < max_out_time
+ *     active_dwell < max_out_time
+ */
+struct iwl3945_scan_channel {
+	/*
+	 * type is defined as:
+	 * 0:0 1 = active, 0 = passive
+	 * 1:4 SSID direct bit map; if a bit is set, then corresponding
+	 *     SSID IE is transmitted in probe request.
+	 * 5:7 reserved
+	 */
+	u8 type;
+	u8 channel;	/* band is selected by iwl3945_scan_cmd "flags" field */
+	struct iwl3945_tx_power tpc;
+	__le16 active_dwell;	/* in 1024-uSec TU (time units), typ 5-50 */
+	__le16 passive_dwell;	/* in 1024-uSec TU (time units), typ 20-500 */
+} __packed;
+
+/* set number of direct probes u8 type */
+#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1))))
+
+struct iwl_scan_channel {
+	/*
+	 * type is defined as:
+	 * 0:0 1 = active, 0 = passive
+	 * 1:20 SSID direct bit map; if a bit is set, then corresponding
+	 *     SSID IE is transmitted in probe request.
+	 * 21:31 reserved
+	 */
+	__le32 type;
+	__le16 channel;	/* band is selected by iwl_scan_cmd "flags" field */
+	u8 tx_gain;		/* gain for analog radio */
+	u8 dsp_atten;		/* gain for DSP */
+	__le16 active_dwell;	/* in 1024-uSec TU (time units), typ 5-50 */
+	__le16 passive_dwell;	/* in 1024-uSec TU (time units), typ 20-500 */
+} __packed;
+
+/* set number of direct probes __le32 type */
+#define IWL_SCAN_PROBE_MASK(n)	cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+
+/**
+ * struct iwl_ssid_ie - directed scan network information element
+ *
+ * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
+ * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
+ * each channel may select different ssids from among the 20 (4) entries.
+ * SSID IEs get transmitted in reverse order of entry.
+ */
+struct iwl_ssid_ie {
+	u8 id;
+	u8 len;
+	u8 ssid[32];
+} __packed;
+
+#define PROBE_OPTION_MAX_3945		4
+#define PROBE_OPTION_MAX		20
+#define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF)
+#define IWL_GOOD_CRC_TH_DISABLED	0
+#define IWL_GOOD_CRC_TH_DEFAULT		cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH_NEVER		cpu_to_le16(0xffff)
+#define IWL_MAX_SCAN_SIZE 1024
+#define IWL_MAX_CMD_SIZE 4096
+
+/*
+ * REPLY_SCAN_CMD = 0x80 (command)
+ *
+ * The hardware scan command is very powerful; the driver can set it up to
+ * maintain (relatively) normal network traffic while doing a scan in the
+ * background.  The max_out_time and suspend_time control the ratio of how
+ * long the device stays on an associated network channel ("service channel")
+ * vs. how long it's away from the service channel, i.e. tuned to other channels
+ * for scanning.
+ *
+ * max_out_time is the max time off-channel (in usec), and suspend_time
+ * is how long (in "extended beacon" format) that the scan is "suspended"
+ * after returning to the service channel.  That is, suspend_time is the
+ * time that we stay on the service channel, doing normal work, between
+ * scan segments.  The driver may set these parameters differently to support
+ * scanning when associated vs. not associated, and light vs. heavy traffic
+ * loads when associated.
+ *
+ * After receiving this command, the device's scan engine does the following;
+ *
+ * 1)  Sends SCAN_START notification to driver
+ * 2)  Checks to see if it has time to do scan for one channel
+ * 3)  Sends NULL packet, with power-save (PS) bit set to 1,
+ *     to tell AP that we're going off-channel
+ * 4)  Tunes to first channel in scan list, does active or passive scan
+ * 5)  Sends SCAN_RESULT notification to driver
+ * 6)  Checks to see if it has time to do scan on *next* channel in list
+ * 7)  Repeats 4-6 until it no longer has time to scan the next channel
+ *     before max_out_time expires
+ * 8)  Returns to service channel
+ * 9)  Sends NULL packet with PS=0 to tell AP that we're back
+ * 10) Stays on service channel until suspend_time expires
+ * 11) Repeats entire process 2-10 until list is complete
+ * 12) Sends SCAN_COMPLETE notification
+ *
+ * For fast, efficient scans, the scan command also has support for staying on
+ * a channel for just a short time, if doing active scanning and getting no
+ * responses to the transmitted probe request.  This time is controlled by
+ * quiet_time, and the number of received packets below which a channel is
+ * considered "quiet" is controlled by quiet_plcp_threshold.
+ *
+ * For active scanning on channels that have regulatory restrictions against
+ * blindly transmitting, the scan can listen before transmitting, to make sure
+ * that there is already legitimate activity on the channel.  If enough
+ * packets are cleanly received on the channel (controlled by good_CRC_th,
+ * typical value 1), the scan engine starts transmitting probe requests.
+ *
+ * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
+ *
+ * To avoid uCode errors, see timing restrictions described under
+ * struct iwl_scan_channel.
+ */
+
+struct iwl3945_scan_cmd {
+	__le16 len;
+	u8 reserved0;
+	u8 channel_count;	/* # channels in channel list */
+	__le16 quiet_time;	/* dwell only this # millisecs on quiet channel
+				 * (only for active scan) */
+	__le16 quiet_plcp_th;	/* quiet chnl is < this # pkts (typ. 1) */
+	__le16 good_CRC_th;	/* passive -> active promotion threshold */
+	__le16 reserved1;
+	__le32 max_out_time;	/* max usec to be away from associated (service)
+				 * channel */
+	__le32 suspend_time;	/* pause scan this long (in "extended beacon
+				 * format") when returning to service channel:
+				 * 3945; 31:24 # beacons, 19:0 additional usec,
+				 * 4965; 31:22 # beacons, 21:0 additional usec.
+				 */
+	__le32 flags;		/* RXON_FLG_* */
+	__le32 filter_flags;	/* RXON_FILTER_* */
+
+	/* For active scans (set to all-0s for passive scans).
+	 * Does not include payload.  Must specify Tx rate; no rate scaling. */
+	struct iwl3945_tx_cmd tx_cmd;
+
+	/* For directed active scans (set to all-0s otherwise) */
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
+
+	/*
+	 * Probe request frame, followed by channel list.
+	 *
+	 * Size of probe request frame is specified by byte count in tx_cmd.
+	 * Channel list follows immediately after probe request frame.
+	 * Number of channels in list is specified by channel_count.
+	 * Each channel in list is of type:
+	 *
+	 * struct iwl3945_scan_channel channels[0];
+	 *
+	 * NOTE:  Only one band of channels can be scanned per pass.  You
+	 * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+	 * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+	 * before requesting another scan.
+	 */
+	u8 data[0];
+} __packed;
+
+struct iwl_scan_cmd {
+	__le16 len;
+	u8 reserved0;
+	u8 channel_count;	/* # channels in channel list */
+	__le16 quiet_time;	/* dwell only this # millisecs on quiet channel
+				 * (only for active scan) */
+	__le16 quiet_plcp_th;	/* quiet chnl is < this # pkts (typ. 1) */
+	__le16 good_CRC_th;	/* passive -> active promotion threshold */
+	__le16 rx_chain;	/* RXON_RX_CHAIN_* */
+	__le32 max_out_time;	/* max usec to be away from associated (service)
+				 * channel */
+	__le32 suspend_time;	/* pause scan this long (in "extended beacon
+				 * format") when returning to service chnl:
+				 * 3945; 31:24 # beacons, 19:0 additional usec,
+				 * 4965; 31:22 # beacons, 21:0 additional usec.
+				 */
+	__le32 flags;		/* RXON_FLG_* */
+	__le32 filter_flags;	/* RXON_FILTER_* */
+
+	/* For active scans (set to all-0s for passive scans).
+	 * Does not include payload.  Must specify Tx rate; no rate scaling. */
+	struct iwl_tx_cmd tx_cmd;
+
+	/* For directed active scans (set to all-0s otherwise) */
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
+
+	/*
+	 * Probe request frame, followed by channel list.
+	 *
+	 * Size of probe request frame is specified by byte count in tx_cmd.
+	 * Channel list follows immediately after probe request frame.
+	 * Number of channels in list is specified by channel_count.
+	 * Each channel in list is of type:
+	 *
+	 * struct iwl_scan_channel channels[0];
+	 *
+	 * NOTE:  Only one band of channels can be scanned per pass.  You
+	 * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+	 * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+	 * before requesting another scan.
+	 */
+	u8 data[0];
+} __packed;
+
+/* Can abort will notify by complete notification with abort status. */
+#define CAN_ABORT_STATUS	cpu_to_le32(0x1)
+/* complete notification statuses */
+#define ABORT_STATUS            0x2
+
+/*
+ * REPLY_SCAN_CMD = 0x80 (response)
+ */
+struct iwl_scanreq_notification {
+	__le32 status;		/* 1: okay, 2: cannot fulfill request */
+} __packed;
+
+/*
+ * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
+ */
+struct iwl_scanstart_notification {
+	__le32 tsf_low;
+	__le32 tsf_high;
+	__le32 beacon_timer;
+	u8 channel;
+	u8 band;
+	u8 reserved[2];
+	__le32 status;
+} __packed;
+
+#define  SCAN_OWNER_STATUS 0x1;
+#define  MEASURE_OWNER_STATUS 0x2;
+
+#define IWL_PROBE_STATUS_OK		0
+#define IWL_PROBE_STATUS_TX_FAILED	BIT(0)
+/* error statuses combined with TX_FAILED */
+#define IWL_PROBE_STATUS_FAIL_TTL	BIT(1)
+#define IWL_PROBE_STATUS_FAIL_BT	BIT(2)
+
+#define NUMBER_OF_STATISTICS 1	/* first __le32 is good CRC */
+/*
+ * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
+ */
+struct iwl_scanresults_notification {
+	u8 channel;
+	u8 band;
+	u8 probe_status;
+	u8 num_probe_not_sent; /* not enough time to send */
+	__le32 tsf_low;
+	__le32 tsf_high;
+	__le32 statistics[NUMBER_OF_STATISTICS];
+} __packed;
+
+/*
+ * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
+ */
+struct iwl_scancomplete_notification {
+	u8 scanned_channels;
+	u8 status;
+	u8 last_channel;
+	__le32 tsf_low;
+	__le32 tsf_high;
+} __packed;
+
+
+/******************************************************************************
+ * (9)
+ * IBSS/AP Commands and Notifications:
+ *
+ *****************************************************************************/
+
+enum iwl_ibss_manager {
+	IWL_NOT_IBSS_MANAGER = 0,
+	IWL_IBSS_MANAGER = 1,
+};
+
+/*
+ * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
+ */
+
+struct iwl3945_beacon_notif {
+	struct iwl3945_tx_resp beacon_notify_hdr;
+	__le32 low_tsf;
+	__le32 high_tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
+struct iwl4965_beacon_notif {
+	struct iwl4965_tx_resp beacon_notify_hdr;
+	__le32 low_tsf;
+	__le32 high_tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
+/*
+ * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
+ */
+
+struct iwl3945_tx_beacon_cmd {
+	struct iwl3945_tx_cmd tx;
+	__le16 tim_idx;
+	u8 tim_size;
+	u8 reserved1;
+	struct ieee80211_hdr frame[0];	/* beacon frame */
+} __packed;
+
+struct iwl_tx_beacon_cmd {
+	struct iwl_tx_cmd tx;
+	__le16 tim_idx;
+	u8 tim_size;
+	u8 reserved1;
+	struct ieee80211_hdr frame[0];	/* beacon frame */
+} __packed;
+
+/******************************************************************************
+ * (10)
+ * Statistics Commands and Notifications:
+ *
+ *****************************************************************************/
+
+#define IWL_TEMP_CONVERT 260
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+/* Used for passing to driver number of successes and failures per rate */
+struct rate_histogram {
+	union {
+		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} success;
+	union {
+		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} failed;
+} __packed;
+
+/* statistics command response */
+
+struct iwl39_statistics_rx_phy {
+	__le32 ina_cnt;
+	__le32 fina_cnt;
+	__le32 plcp_err;
+	__le32 crc32_err;
+	__le32 overrun_err;
+	__le32 early_overrun_err;
+	__le32 crc32_good;
+	__le32 false_alarm_cnt;
+	__le32 fina_sync_err_cnt;
+	__le32 sfd_timeout;
+	__le32 fina_timeout;
+	__le32 unresponded_rts;
+	__le32 rxe_frame_limit_overrun;
+	__le32 sent_ack_cnt;
+	__le32 sent_cts_cnt;
+} __packed;
+
+struct iwl39_statistics_rx_non_phy {
+	__le32 bogus_cts;	/* CTS received when not expecting CTS */
+	__le32 bogus_ack;	/* ACK received when not expecting ACK */
+	__le32 non_bssid_frames;	/* number of frames with BSSID that
+					 * doesn't belong to the STA BSSID */
+	__le32 filtered_frames;	/* count frames that were dumped in the
+				 * filtering process */
+	__le32 non_channel_beacons;	/* beacons with our bss id but not on
+					 * our serving channel */
+} __packed;
+
+struct iwl39_statistics_rx {
+	struct iwl39_statistics_rx_phy ofdm;
+	struct iwl39_statistics_rx_phy cck;
+	struct iwl39_statistics_rx_non_phy general;
+} __packed;
+
+struct iwl39_statistics_tx {
+	__le32 preamble_cnt;
+	__le32 rx_detected_cnt;
+	__le32 bt_prio_defer_cnt;
+	__le32 bt_prio_kill_cnt;
+	__le32 few_bytes_cnt;
+	__le32 cts_timeout;
+	__le32 ack_timeout;
+	__le32 expected_ack_cnt;
+	__le32 actual_ack_cnt;
+} __packed;
+
+struct statistics_dbg {
+	__le32 burst_check;
+	__le32 burst_count;
+	__le32 wait_for_silence_timeout_cnt;
+	__le32 reserved[3];
+} __packed;
+
+struct iwl39_statistics_div {
+	__le32 tx_on_a;
+	__le32 tx_on_b;
+	__le32 exec_time;
+	__le32 probe_time;
+} __packed;
+
+struct iwl39_statistics_general {
+	__le32 temperature;
+	struct statistics_dbg dbg;
+	__le32 sleep_time;
+	__le32 slots_out;
+	__le32 slots_idle;
+	__le32 ttl_timestamp;
+	struct iwl39_statistics_div div;
+} __packed;
+
+struct statistics_rx_phy {
+	__le32 ina_cnt;
+	__le32 fina_cnt;
+	__le32 plcp_err;
+	__le32 crc32_err;
+	__le32 overrun_err;
+	__le32 early_overrun_err;
+	__le32 crc32_good;
+	__le32 false_alarm_cnt;
+	__le32 fina_sync_err_cnt;
+	__le32 sfd_timeout;
+	__le32 fina_timeout;
+	__le32 unresponded_rts;
+	__le32 rxe_frame_limit_overrun;
+	__le32 sent_ack_cnt;
+	__le32 sent_cts_cnt;
+	__le32 sent_ba_rsp_cnt;
+	__le32 dsp_self_kill;
+	__le32 mh_format_err;
+	__le32 re_acq_main_rssi_sum;
+	__le32 reserved3;
+} __packed;
+
+struct statistics_rx_ht_phy {
+	__le32 plcp_err;
+	__le32 overrun_err;
+	__le32 early_overrun_err;
+	__le32 crc32_good;
+	__le32 crc32_err;
+	__le32 mh_format_err;
+	__le32 agg_crc32_good;
+	__le32 agg_mpdu_cnt;
+	__le32 agg_cnt;
+	__le32 unsupport_mcs;
+} __packed;
+
+#define INTERFERENCE_DATA_AVAILABLE      cpu_to_le32(1)
+
+struct statistics_rx_non_phy {
+	__le32 bogus_cts;	/* CTS received when not expecting CTS */
+	__le32 bogus_ack;	/* ACK received when not expecting ACK */
+	__le32 non_bssid_frames;	/* number of frames with BSSID that
+					 * doesn't belong to the STA BSSID */
+	__le32 filtered_frames;	/* count frames that were dumped in the
+				 * filtering process */
+	__le32 non_channel_beacons;	/* beacons with our bss id but not on
+					 * our serving channel */
+	__le32 channel_beacons;	/* beacons with our bss id and in our
+				 * serving channel */
+	__le32 num_missed_bcon;	/* number of missed beacons */
+	__le32 adc_rx_saturation_time;	/* count in 0.8us units the time the
+					 * ADC was in saturation */
+	__le32 ina_detection_search_time;/* total time (in 0.8us) searched
+					  * for INA */
+	__le32 beacon_silence_rssi_a;	/* RSSI silence after beacon frame */
+	__le32 beacon_silence_rssi_b;	/* RSSI silence after beacon frame */
+	__le32 beacon_silence_rssi_c;	/* RSSI silence after beacon frame */
+	__le32 interference_data_flag;	/* flag for interference data
+					 * availability. 1 when data is
+					 * available. */
+	__le32 channel_load;		/* counts RX Enable time in uSec */
+	__le32 dsp_false_alarms;	/* DSP false alarm (both OFDM
+					 * and CCK) counter */
+	__le32 beacon_rssi_a;
+	__le32 beacon_rssi_b;
+	__le32 beacon_rssi_c;
+	__le32 beacon_energy_a;
+	__le32 beacon_energy_b;
+	__le32 beacon_energy_c;
+} __packed;
+
+struct statistics_rx {
+	struct statistics_rx_phy ofdm;
+	struct statistics_rx_phy cck;
+	struct statistics_rx_non_phy general;
+	struct statistics_rx_ht_phy ofdm_ht;
+} __packed;
+
+/**
+ * struct statistics_tx_power - current tx power
+ *
+ * @ant_a: current tx power on chain a in 1/2 dB step
+ * @ant_b: current tx power on chain b in 1/2 dB step
+ * @ant_c: current tx power on chain c in 1/2 dB step
+ */
+struct statistics_tx_power {
+	u8 ant_a;
+	u8 ant_b;
+	u8 ant_c;
+	u8 reserved;
+} __packed;
+
+struct statistics_tx_non_phy_agg {
+	__le32 ba_timeout;
+	__le32 ba_reschedule_frames;
+	__le32 scd_query_agg_frame_cnt;
+	__le32 scd_query_no_agg;
+	__le32 scd_query_agg;
+	__le32 scd_query_mismatch;
+	__le32 frame_not_ready;
+	__le32 underrun;
+	__le32 bt_prio_kill;
+	__le32 rx_ba_rsp_cnt;
+} __packed;
+
+struct statistics_tx {
+	__le32 preamble_cnt;
+	__le32 rx_detected_cnt;
+	__le32 bt_prio_defer_cnt;
+	__le32 bt_prio_kill_cnt;
+	__le32 few_bytes_cnt;
+	__le32 cts_timeout;
+	__le32 ack_timeout;
+	__le32 expected_ack_cnt;
+	__le32 actual_ack_cnt;
+	__le32 dump_msdu_cnt;
+	__le32 burst_abort_next_frame_mismatch_cnt;
+	__le32 burst_abort_missing_next_frame_cnt;
+	__le32 cts_timeout_collision;
+	__le32 ack_or_ba_timeout_collision;
+	struct statistics_tx_non_phy_agg agg;
+
+	__le32 reserved1;
+} __packed;
+
+
+struct statistics_div {
+	__le32 tx_on_a;
+	__le32 tx_on_b;
+	__le32 exec_time;
+	__le32 probe_time;
+	__le32 reserved1;
+	__le32 reserved2;
+} __packed;
+
+struct statistics_general_common {
+	__le32 temperature;   /* radio temperature */
+	struct statistics_dbg dbg;
+	__le32 sleep_time;
+	__le32 slots_out;
+	__le32 slots_idle;
+	__le32 ttl_timestamp;
+	struct statistics_div div;
+	__le32 rx_enable_counter;
+	/*
+	 * num_of_sos_states:
+	 *  count the number of times we have to re-tune
+	 *  in order to get out of bad PHY status
+	 */
+	__le32 num_of_sos_states;
+} __packed;
+
+struct statistics_general {
+	struct statistics_general_common common;
+	__le32 reserved2;
+	__le32 reserved3;
+} __packed;
+
+#define UCODE_STATISTICS_CLEAR_MSK		(0x1 << 0)
+#define UCODE_STATISTICS_FREQUENCY_MSK		(0x1 << 1)
+#define UCODE_STATISTICS_NARROW_BAND_MSK	(0x1 << 2)
+
+/*
+ * REPLY_STATISTICS_CMD = 0x9c,
+ * all devices identical.
+ *
+ * This command triggers an immediate response containing uCode statistics.
+ * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
+ *
+ * If the CLEAR_STATS configuration flag is set, uCode will clear its
+ * internal copy of the statistics (counters) after issuing the response.
+ * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below).
+ *
+ * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
+ * STATISTICS_NOTIFICATIONs after received beacons (see below).  This flag
+ * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
+ */
+#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1)	/* see above */
+#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */
+struct iwl_statistics_cmd {
+	__le32 configuration_flags;	/* IWL_STATS_CONF_* */
+} __packed;
+
+/*
+ * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
+ *
+ * By default, uCode issues this notification after receiving a beacon
+ * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the
+ * REPLY_STATISTICS_CMD 0x9c, above.
+ *
+ * Statistics counters continue to increment beacon after beacon, but are
+ * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
+ * 0x9c with CLEAR_STATS bit set (see above).
+ *
+ * uCode also issues this notification during scans.  uCode clears statistics
+ * appropriately so that each notification contains statistics for only the
+ * one channel that has just been scanned.
+ */
+#define STATISTICS_REPLY_FLG_BAND_24G_MSK         cpu_to_le32(0x2)
+#define STATISTICS_REPLY_FLG_HT40_MODE_MSK        cpu_to_le32(0x8)
+
+struct iwl3945_notif_statistics {
+	__le32 flag;
+	struct iwl39_statistics_rx rx;
+	struct iwl39_statistics_tx tx;
+	struct iwl39_statistics_general general;
+} __packed;
+
+struct iwl_notif_statistics {
+	__le32 flag;
+	struct statistics_rx rx;
+	struct statistics_tx tx;
+	struct statistics_general general;
+} __packed;
+
+/*
+ * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
+ *
+ * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed
+ * in regardless of how many missed beacons, which mean when driver receive the
+ * notification, inside the command, it can find all the beacons information
+ * which include number of total missed beacons, number of consecutive missed
+ * beacons, number of beacons received and number of beacons expected to
+ * receive.
+ *
+ * If uCode detected consecutive_missed_beacons > 5, it will reset the radio
+ * in order to bring the radio/PHY back to working state; which has no relation
+ * to when driver will perform sensitivity calibration.
+ *
+ * Driver should set it own missed_beacon_threshold to decide when to perform
+ * sensitivity calibration based on number of consecutive missed beacons in
+ * order to improve overall performance, especially in noisy environment.
+ *
+ */
+
+#define IWL_MISSED_BEACON_THRESHOLD_MIN	(1)
+#define IWL_MISSED_BEACON_THRESHOLD_DEF	(5)
+#define IWL_MISSED_BEACON_THRESHOLD_MAX	IWL_MISSED_BEACON_THRESHOLD_DEF
+
+struct iwl_missed_beacon_notif {
+	__le32 consecutive_missed_beacons;
+	__le32 total_missed_becons;
+	__le32 num_expected_beacons;
+	__le32 num_recvd_beacons;
+} __packed;
+
+
+/******************************************************************************
+ * (11)
+ * Rx Calibration Commands:
+ *
+ * With the uCode used for open source drivers, most Tx calibration (except
+ * for Tx Power) and most Rx calibration is done by uCode during the
+ * "initialize" phase of uCode boot.  Driver must calibrate only:
+ *
+ * 1)  Tx power (depends on temperature), described elsewhere
+ * 2)  Receiver gain balance (optimize MIMO, and detect disconnected antennas)
+ * 3)  Receiver sensitivity (to optimize signal detection)
+ *
+ *****************************************************************************/
+
+/**
+ * SENSITIVITY_CMD = 0xa8 (command, has simple generic response)
+ *
+ * This command sets up the Rx signal detector for a sensitivity level that
+ * is high enough to lock onto all signals within the associated network,
+ * but low enough to ignore signals that are below a certain threshold, so as
+ * not to have too many "false alarms".  False alarms are signals that the
+ * Rx DSP tries to lock onto, but then discards after determining that they
+ * are noise.
+ *
+ * The optimum number of false alarms is between 5 and 50 per 200 TUs
+ * (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e.
+ * time listening, not transmitting).  Driver must adjust sensitivity so that
+ * the ratio of actual false alarms to actual Rx time falls within this range.
+ *
+ * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each
+ * received beacon.  These provide information to the driver to analyze the
+ * sensitivity.  Don't analyze statistics that come in from scanning, or any
+ * other non-associated-network source.  Pertinent statistics include:
+ *
+ * From "general" statistics (struct statistics_rx_non_phy):
+ *
+ * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level)
+ *   Measure of energy of desired signal.  Used for establishing a level
+ *   below which the device does not detect signals.
+ *
+ * (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB)
+ *   Measure of background noise in silent period after beacon.
+ *
+ * channel_load
+ *   uSecs of actual Rx time during beacon period (varies according to
+ *   how much time was spent transmitting).
+ *
+ * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately:
+ *
+ * false_alarm_cnt
+ *   Signal locks abandoned early (before phy-level header).
+ *
+ * plcp_err
+ *   Signal locks abandoned late (during phy-level header).
+ *
+ * NOTE:  Both false_alarm_cnt and plcp_err increment monotonically from
+ *        beacon to beacon, i.e. each value is an accumulation of all errors
+ *        before and including the latest beacon.  Values will wrap around to 0
+ *        after counting up to 2^32 - 1.  Driver must differentiate vs.
+ *        previous beacon's values to determine # false alarms in the current
+ *        beacon period.
+ *
+ * Total number of false alarms = false_alarms + plcp_errs
+ *
+ * For OFDM, adjust the following table entries in struct iwl_sensitivity_cmd
+ * (notice that the start points for OFDM are at or close to settings for
+ * maximum sensitivity):
+ *
+ *                                             START  /  MIN  /  MAX
+ *   HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX          90   /   85  /  120
+ *   HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX     170   /  170  /  210
+ *   HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX         105   /  105  /  140
+ *   HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX     220   /  220  /  270
+ *
+ *   If actual rate of OFDM false alarms (+ plcp_errors) is too high
+ *   (greater than 50 for each 204.8 msecs listening), reduce sensitivity
+ *   by *adding* 1 to all 4 of the table entries above, up to the max for
+ *   each entry.  Conversely, if false alarm rate is too low (less than 5
+ *   for each 204.8 msecs listening), *subtract* 1 from each entry to
+ *   increase sensitivity.
+ *
+ * For CCK sensitivity, keep track of the following:
+ *
+ *   1).  20-beacon history of maximum background noise, indicated by
+ *        (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the
+ *        3 receivers.  For any given beacon, the "silence reference" is
+ *        the maximum of last 60 samples (20 beacons * 3 receivers).
+ *
+ *   2).  10-beacon history of strongest signal level, as indicated
+ *        by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers,
+ *        i.e. the strength of the signal through the best receiver at the
+ *        moment.  These measurements are "upside down", with lower values
+ *        for stronger signals, so max energy will be *minimum* value.
+ *
+ *        Then for any given beacon, the driver must determine the *weakest*
+ *        of the strongest signals; this is the minimum level that needs to be
+ *        successfully detected, when using the best receiver at the moment.
+ *        "Max cck energy" is the maximum (higher value means lower energy!)
+ *        of the last 10 minima.  Once this is determined, driver must add
+ *        a little margin by adding "6" to it.
+ *
+ *   3).  Number of consecutive beacon periods with too few false alarms.
+ *        Reset this to 0 at the first beacon period that falls within the
+ *        "good" range (5 to 50 false alarms per 204.8 milliseconds rx).
+ *
+ * Then, adjust the following CCK table entries in struct iwl_sensitivity_cmd
+ * (notice that the start points for CCK are at maximum sensitivity):
+ *
+ *                                             START  /  MIN  /  MAX
+ *   HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX         125   /  125  /  200
+ *   HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX     200   /  200  /  400
+ *   HD_MIN_ENERGY_CCK_DET_INDEX                100   /    0  /  100
+ *
+ *   If actual rate of CCK false alarms (+ plcp_errors) is too high
+ *   (greater than 50 for each 204.8 msecs listening), method for reducing
+ *   sensitivity is:
+ *
+ *   1)  *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ *       up to max 400.
+ *
+ *   2)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160,
+ *       sensitivity has been reduced a significant amount; bring it up to
+ *       a moderate 161.  Otherwise, *add* 3, up to max 200.
+ *
+ *   3)  a)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160,
+ *       sensitivity has been reduced only a moderate or small amount;
+ *       *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX,
+ *       down to min 0.  Otherwise (if gain has been significantly reduced),
+ *       don't change the HD_MIN_ENERGY_CCK_DET_INDEX value.
+ *
+ *       b)  Save a snapshot of the "silence reference".
+ *
+ *   If actual rate of CCK false alarms (+ plcp_errors) is too low
+ *   (less than 5 for each 204.8 msecs listening), method for increasing
+ *   sensitivity is used only if:
+ *
+ *   1a)  Previous beacon did not have too many false alarms
+ *   1b)  AND difference between previous "silence reference" and current
+ *        "silence reference" (prev - current) is 2 or more,
+ *   OR 2)  100 or more consecutive beacon periods have had rate of
+ *          less than 5 false alarms per 204.8 milliseconds rx time.
+ *
+ *   Method for increasing sensitivity:
+ *
+ *   1)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX,
+ *       down to min 125.
+ *
+ *   2)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ *       down to min 200.
+ *
+ *   3)  *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100.
+ *
+ *   If actual rate of CCK false alarms (+ plcp_errors) is within good range
+ *   (between 5 and 50 for each 204.8 msecs listening):
+ *
+ *   1)  Save a snapshot of the silence reference.
+ *
+ *   2)  If previous beacon had too many CCK false alarms (+ plcp_errors),
+ *       give some extra margin to energy threshold by *subtracting* 8
+ *       from value in HD_MIN_ENERGY_CCK_DET_INDEX.
+ *
+ *   For all cases (too few, too many, good range), make sure that the CCK
+ *   detection threshold (energy) is below the energy level for robust
+ *   detection over the past 10 beacon periods, the "Max cck energy".
+ *   Lower values mean higher energy; this means making sure that the value
+ *   in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy".
+ *
+ */
+
+/*
+ * Table entries in SENSITIVITY_CMD (struct iwl_sensitivity_cmd)
+ */
+#define HD_TABLE_SIZE  (11)	/* number of entries */
+#define HD_MIN_ENERGY_CCK_DET_INDEX                 (0)	/* table indexes */
+#define HD_MIN_ENERGY_OFDM_DET_INDEX                (1)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX          (2)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX      (3)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX      (4)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX          (5)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX      (6)
+#define HD_BARKER_CORR_TH_ADD_MIN_INDEX             (7)
+#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX         (8)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX          (9)
+#define HD_OFDM_ENERGY_TH_IN_INDEX                  (10)
+
+/* Control field in struct iwl_sensitivity_cmd */
+#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE	cpu_to_le16(0)
+#define SENSITIVITY_CMD_CONTROL_WORK_TABLE	cpu_to_le16(1)
+
+/**
+ * struct iwl_sensitivity_cmd
+ * @control:  (1) updates working table, (0) updates default table
+ * @table:  energy threshold values, use HD_* as index into table
+ *
+ * Always use "1" in "control" to update uCode's working table and DSP.
+ */
+struct iwl_sensitivity_cmd {
+	__le16 control;			/* always use "1" */
+	__le16 table[HD_TABLE_SIZE];	/* use HD_* as index */
+} __packed;
+
+
+/**
+ * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
+ *
+ * This command sets the relative gains of 4965 device's 3 radio receiver chains.
+ *
+ * After the first association, driver should accumulate signal and noise
+ * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20
+ * beacons from the associated network (don't collect statistics that come
+ * in from scanning, or any other non-network source).
+ *
+ * DISCONNECTED ANTENNA:
+ *
+ * Driver should determine which antennas are actually connected, by comparing
+ * average beacon signal levels for the 3 Rx chains.  Accumulate (add) the
+ * following values over 20 beacons, one accumulator for each of the chains
+ * a/b/c, from struct statistics_rx_non_phy:
+ *
+ * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB)
+ *
+ * Find the strongest signal from among a/b/c.  Compare the other two to the
+ * strongest.  If any signal is more than 15 dB (times 20, unless you
+ * divide the accumulated values by 20) below the strongest, the driver
+ * considers that antenna to be disconnected, and should not try to use that
+ * antenna/chain for Rx or Tx.  If both A and B seem to be disconnected,
+ * driver should declare the stronger one as connected, and attempt to use it
+ * (A and B are the only 2 Tx chains!).
+ *
+ *
+ * RX BALANCE:
+ *
+ * Driver should balance the 3 receivers (but just the ones that are connected
+ * to antennas, see above) for gain, by comparing the average signal levels
+ * detected during the silence after each beacon (background noise).
+ * Accumulate (add) the following values over 20 beacons, one accumulator for
+ * each of the chains a/b/c, from struct statistics_rx_non_phy:
+ *
+ * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB)
+ *
+ * Find the weakest background noise level from among a/b/c.  This Rx chain
+ * will be the reference, with 0 gain adjustment.  Attenuate other channels by
+ * finding noise difference:
+ *
+ * (accum_noise[i] - accum_noise[reference]) / 30
+ *
+ * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB.
+ * For use in diff_gain_[abc] fields of struct iwl_calibration_cmd, the
+ * driver should limit the difference results to a range of 0-3 (0-4.5 dB),
+ * and set bit 2 to indicate "reduce gain".  The value for the reference
+ * (weakest) chain should be "0".
+ *
+ * diff_gain_[abc] bit fields:
+ *   2: (1) reduce gain, (0) increase gain
+ * 1-0: amount of gain, units of 1.5 dB
+ */
+
+/* Phy calibration command for series */
+/* The default calibrate table size if not specified by firmware */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
+enum {
+	IWL_PHY_CALIBRATE_DIFF_GAIN_CMD		= 7,
+	IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE	= 19,
+};
+
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE		(253)
+
+struct iwl_calib_hdr {
+	u8 op_code;
+	u8 first_group;
+	u8 groups_num;
+	u8 data_valid;
+} __packed;
+
+/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
+struct iwl_calib_diff_gain_cmd {
+	struct iwl_calib_hdr hdr;
+	s8 diff_gain_a;		/* see above */
+	s8 diff_gain_b;
+	s8 diff_gain_c;
+	u8 reserved1;
+} __packed;
+
+/******************************************************************************
+ * (12)
+ * Miscellaneous Commands:
+ *
+ *****************************************************************************/
+
+/*
+ * LEDs Command & Response
+ * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
+ *
+ * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
+ * this command turns it on or off, or sets up a periodic blinking cycle.
+ */
+struct iwl_led_cmd {
+	__le32 interval;	/* "interval" in uSec */
+	u8 id;			/* 1: Activity, 2: Link, 3: Tech */
+	u8 off;			/* # intervals off while blinking;
+				 * "0", with >0 "on" value, turns LED on */
+	u8 on;			/* # intervals on while blinking;
+				 * "0", regardless of "off", turns LED off */
+	u8 reserved;
+} __packed;
+
+
+/******************************************************************************
+ * (13)
+ * Union of all expected notifications/responses:
+ *
+ *****************************************************************************/
+
+struct iwl_rx_packet {
+	/*
+	 * The first 4 bytes of the RX frame header contain both the RX frame
+	 * size and some flags.
+	 * Bit fields:
+	 * 31:    flag flush RB request
+	 * 30:    flag ignore TC (terminal counter) request
+	 * 29:    flag fast IRQ request
+	 * 28-14: Reserved
+	 * 13-00: RX frame size
+	 */
+	__le32 len_n_flags;
+	struct iwl_cmd_header hdr;
+	union {
+		struct iwl3945_rx_frame rx_frame;
+		struct iwl3945_tx_resp tx_resp;
+		struct iwl3945_beacon_notif beacon_status;
+
+		struct iwl_alive_resp alive_frame;
+		struct iwl_spectrum_notification spectrum_notif;
+		struct iwl_csa_notification csa_notif;
+		struct iwl_error_resp err_resp;
+		struct iwl_card_state_notif card_state_notif;
+		struct iwl_add_sta_resp add_sta;
+		struct iwl_rem_sta_resp rem_sta;
+		struct iwl_sleep_notification sleep_notif;
+		struct iwl_spectrum_resp spectrum;
+		struct iwl_notif_statistics stats;
+		struct iwl_compressed_ba_resp compressed_ba;
+		struct iwl_missed_beacon_notif missed_beacon;
+		__le32 status;
+		u8 raw[0];
+	} u;
+} __packed;
+
+#endif				/* __iwl_legacy_commands_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
new file mode 100644
index 0000000..d418b64
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-core.c
@@ -0,0 +1,2674 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-power.h"
+#include "iwl-sta.h"
+#include "iwl-helpers.h"
+
+
+MODULE_DESCRIPTION("iwl-legacy: common functions for 3945 and 4965");
+MODULE_VERSION(IWLWIFI_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ *   Able to scan and finding all the available AP
+ *   Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+static bool bt_coex_active = true;
+module_param(bt_coex_active, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
+
+u32 iwlegacy_debug_level;
+EXPORT_SYMBOL(iwlegacy_debug_level);
+
+const u8 iwlegacy_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+EXPORT_SYMBOL(iwlegacy_bcast_addr);
+
+
+/* This function both allocates and initializes hw and priv. */
+struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg)
+{
+	struct iwl_priv *priv;
+	/* mac80211 allocates memory for this device instance, including
+	 *   space for this driver's private structure */
+	struct ieee80211_hw *hw;
+
+	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
+				cfg->ops->ieee80211_ops);
+	if (hw == NULL) {
+		pr_err("%s: Can not allocate network device\n",
+		       cfg->name);
+		goto out;
+	}
+
+	priv = hw->priv;
+	priv->hw = hw;
+
+out:
+	return hw;
+}
+EXPORT_SYMBOL(iwl_legacy_alloc_all);
+
+#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
+#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
+static void iwl_legacy_init_ht_hw_capab(const struct iwl_priv *priv,
+			      struct ieee80211_sta_ht_cap *ht_info,
+			      enum ieee80211_band band)
+{
+	u16 max_bit_rate = 0;
+	u8 rx_chains_num = priv->hw_params.rx_chains_num;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+
+	ht_info->cap = 0;
+	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+
+	ht_info->ht_supported = true;
+
+	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+	max_bit_rate = MAX_BIT_RATE_20_MHZ;
+	if (priv->hw_params.ht40_channel & BIT(band)) {
+		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+		ht_info->mcs.rx_mask[4] = 0x01;
+		max_bit_rate = MAX_BIT_RATE_40_MHZ;
+	}
+
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+
+	ht_info->mcs.rx_mask[0] = 0xFF;
+	if (rx_chains_num >= 2)
+		ht_info->mcs.rx_mask[1] = 0xFF;
+	if (rx_chains_num >= 3)
+		ht_info->mcs.rx_mask[2] = 0xFF;
+
+	/* Highest supported Rx data rate */
+	max_bit_rate *= rx_chains_num;
+	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
+	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
+
+	/* Tx MCS capabilities */
+	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+	if (tx_chains_num != rx_chains_num) {
+		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+		ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
+				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+	}
+}
+
+/**
+ * iwl_legacy_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ */
+int iwl_legacy_init_geos(struct iwl_priv *priv)
+{
+	struct iwl_channel_info *ch;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *channels;
+	struct ieee80211_channel *geo_ch;
+	struct ieee80211_rate *rates;
+	int i = 0;
+
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
+	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
+		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+		return 0;
+	}
+
+	channels = kzalloc(sizeof(struct ieee80211_channel) *
+			   priv->channel_count, GFP_KERNEL);
+	if (!channels)
+		return -ENOMEM;
+
+	rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
+			GFP_KERNEL);
+	if (!rates) {
+		kfree(channels);
+		return -ENOMEM;
+	}
+
+	/* 5.2GHz channels start after the 2.4GHz channels */
+	sband = &priv->bands[IEEE80211_BAND_5GHZ];
+	sband->channels = &channels[ARRAY_SIZE(iwlegacy_eeprom_band_1)];
+	/* just OFDM */
+	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
+	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
+
+	if (priv->cfg->sku & IWL_SKU_N)
+		iwl_legacy_init_ht_hw_capab(priv, &sband->ht_cap,
+					 IEEE80211_BAND_5GHZ);
+
+	sband = &priv->bands[IEEE80211_BAND_2GHZ];
+	sband->channels = channels;
+	/* OFDM & CCK */
+	sband->bitrates = rates;
+	sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
+
+	if (priv->cfg->sku & IWL_SKU_N)
+		iwl_legacy_init_ht_hw_capab(priv, &sband->ht_cap,
+					 IEEE80211_BAND_2GHZ);
+
+	priv->ieee_channels = channels;
+	priv->ieee_rates = rates;
+
+	for (i = 0;  i < priv->channel_count; i++) {
+		ch = &priv->channel_info[i];
+
+		if (!iwl_legacy_is_channel_valid(ch))
+			continue;
+
+		if (iwl_legacy_is_channel_a_band(ch))
+			sband =  &priv->bands[IEEE80211_BAND_5GHZ];
+		else
+			sband =  &priv->bands[IEEE80211_BAND_2GHZ];
+
+		geo_ch = &sband->channels[sband->n_channels++];
+
+		geo_ch->center_freq =
+			ieee80211_channel_to_frequency(ch->channel, ch->band);
+		geo_ch->max_power = ch->max_power_avg;
+		geo_ch->max_antenna_gain = 0xff;
+		geo_ch->hw_value = ch->channel;
+
+		if (iwl_legacy_is_channel_valid(ch)) {
+			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
+				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+
+			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
+				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+			if (ch->flags & EEPROM_CHANNEL_RADAR)
+				geo_ch->flags |= IEEE80211_CHAN_RADAR;
+
+			geo_ch->flags |= ch->ht40_extension_channel;
+
+			if (ch->max_power_avg > priv->tx_power_device_lmt)
+				priv->tx_power_device_lmt = ch->max_power_avg;
+		} else {
+			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+		}
+
+		IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
+				ch->channel, geo_ch->center_freq,
+				iwl_legacy_is_channel_a_band(ch) ?  "5.2" : "2.4",
+				geo_ch->flags & IEEE80211_CHAN_DISABLED ?
+				"restricted" : "valid",
+				 geo_ch->flags);
+	}
+
+	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
+	     priv->cfg->sku & IWL_SKU_A) {
+		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
+			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
+			   priv->pci_dev->device,
+			   priv->pci_dev->subsystem_device);
+		priv->cfg->sku &= ~IWL_SKU_A;
+	}
+
+	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+		   priv->bands[IEEE80211_BAND_2GHZ].n_channels,
+		   priv->bands[IEEE80211_BAND_5GHZ].n_channels);
+
+	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_init_geos);
+
+/*
+ * iwl_legacy_free_geos - undo allocations in iwl_legacy_init_geos
+ */
+void iwl_legacy_free_geos(struct iwl_priv *priv)
+{
+	kfree(priv->ieee_channels);
+	kfree(priv->ieee_rates);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+EXPORT_SYMBOL(iwl_legacy_free_geos);
+
+static bool iwl_legacy_is_channel_extension(struct iwl_priv *priv,
+				     enum ieee80211_band band,
+				     u16 channel, u8 extension_chan_offset)
+{
+	const struct iwl_channel_info *ch_info;
+
+	ch_info = iwl_legacy_get_channel_info(priv, band, channel);
+	if (!iwl_legacy_is_channel_valid(ch_info))
+		return false;
+
+	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+		return !(ch_info->ht40_extension_channel &
+					IEEE80211_CHAN_NO_HT40PLUS);
+	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+		return !(ch_info->ht40_extension_channel &
+					IEEE80211_CHAN_NO_HT40MINUS);
+
+	return false;
+}
+
+bool iwl_legacy_is_ht40_tx_allowed(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_sta_ht_cap *ht_cap)
+{
+	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
+		return false;
+
+	/*
+	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+	 * the bit will not set if it is pure 40MHz case
+	 */
+	if (ht_cap && !ht_cap->ht_supported)
+		return false;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	if (priv->disable_ht40)
+		return false;
+#endif
+
+	return iwl_legacy_is_channel_extension(priv, priv->band,
+			le16_to_cpu(ctx->staging.channel),
+			ctx->ht.extension_chan_offset);
+}
+EXPORT_SYMBOL(iwl_legacy_is_ht40_tx_allowed);
+
+static u16 iwl_legacy_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
+{
+	u16 new_val;
+	u16 beacon_factor;
+
+	/*
+	 * If mac80211 hasn't given us a beacon interval, program
+	 * the default into the device.
+	 */
+	if (!beacon_val)
+		return DEFAULT_BEACON_INTERVAL;
+
+	/*
+	 * If the beacon interval we obtained from the peer
+	 * is too large, we'll have to wake up more often
+	 * (and in IBSS case, we'll beacon too much)
+	 *
+	 * For example, if max_beacon_val is 4096, and the
+	 * requested beacon interval is 7000, we'll have to
+	 * use 3500 to be able to wake up on the beacons.
+	 *
+	 * This could badly influence beacon detection stats.
+	 */
+
+	beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
+	new_val = beacon_val / beacon_factor;
+
+	if (!new_val)
+		new_val = max_beacon_val;
+
+	return new_val;
+}
+
+int
+iwl_legacy_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	u64 tsf;
+	s32 interval_tm, rem;
+	struct ieee80211_conf *conf = NULL;
+	u16 beacon_int;
+	struct ieee80211_vif *vif = ctx->vif;
+
+	conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
+
+	lockdep_assert_held(&priv->mutex);
+
+	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
+
+	ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
+	ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
+
+	beacon_int = vif ? vif->bss_conf.beacon_int : 0;
+
+	/*
+	 * TODO: For IBSS we need to get atim_window from mac80211,
+	 *	 for now just always use 0
+	 */
+	ctx->timing.atim_window = 0;
+
+	beacon_int = iwl_legacy_adjust_beacon_interval(beacon_int,
+			priv->hw_params.max_beacon_itrvl * TIME_UNIT);
+	ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
+
+	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
+	interval_tm = beacon_int * TIME_UNIT;
+	rem = do_div(tsf, interval_tm);
+	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+	ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
+
+	IWL_DEBUG_ASSOC(priv,
+			"beacon interval %d beacon timer %d beacon tim %d\n",
+			le16_to_cpu(ctx->timing.beacon_interval),
+			le32_to_cpu(ctx->timing.beacon_init_val),
+			le16_to_cpu(ctx->timing.atim_window));
+
+	return iwl_legacy_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
+				sizeof(ctx->timing), &ctx->timing);
+}
+EXPORT_SYMBOL(iwl_legacy_send_rxon_timing);
+
+void
+iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx,
+				int hw_decrypt)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+
+	if (hw_decrypt)
+		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
+	else
+		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+
+}
+EXPORT_SYMBOL(iwl_legacy_set_rxon_hwcrypto);
+
+/* validate RXON structure is valid */
+int
+iwl_legacy_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+	bool error = false;
+
+	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
+		if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
+			IWL_WARN(priv, "check 2.4G: wrong narrow\n");
+			error = true;
+		}
+		if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
+			IWL_WARN(priv, "check 2.4G: wrong radar\n");
+			error = true;
+		}
+	} else {
+		if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
+			IWL_WARN(priv, "check 5.2G: not short slot!\n");
+			error = true;
+		}
+		if (rxon->flags & RXON_FLG_CCK_MSK) {
+			IWL_WARN(priv, "check 5.2G: CCK!\n");
+			error = true;
+		}
+	}
+	if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
+		IWL_WARN(priv, "mac/bssid mcast!\n");
+		error = true;
+	}
+
+	/* make sure basic rates 6Mbps and 1Mbps are supported */
+	if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
+	    (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
+		IWL_WARN(priv, "neither 1 nor 6 are basic\n");
+		error = true;
+	}
+
+	if (le16_to_cpu(rxon->assoc_id) > 2007) {
+		IWL_WARN(priv, "aid > 2007\n");
+		error = true;
+	}
+
+	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
+			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
+		IWL_WARN(priv, "CCK and short slot\n");
+		error = true;
+	}
+
+	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
+			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
+		IWL_WARN(priv, "CCK and auto detect");
+		error = true;
+	}
+
+	if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
+			    RXON_FLG_TGG_PROTECT_MSK)) ==
+			    RXON_FLG_TGG_PROTECT_MSK) {
+		IWL_WARN(priv, "TGg but no auto-detect\n");
+		error = true;
+	}
+
+	if (error)
+		IWL_WARN(priv, "Tuning to channel %d\n",
+			    le16_to_cpu(rxon->channel));
+
+	if (error) {
+		IWL_ERR(priv, "Invalid RXON\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_check_rxon_cmd);
+
+/**
+ * iwl_legacy_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * @priv: staging_rxon is compared to active_rxon
+ *
+ * If the RXON structure is changing enough to require a new tune,
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
+ */
+int iwl_legacy_full_rxon_required(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx)
+{
+	const struct iwl_legacy_rxon_cmd *staging = &ctx->staging;
+	const struct iwl_legacy_rxon_cmd *active = &ctx->active;
+
+#define CHK(cond)							\
+	if ((cond)) {							\
+		IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n");	\
+		return 1;						\
+	}
+
+#define CHK_NEQ(c1, c2)						\
+	if ((c1) != (c2)) {					\
+		IWL_DEBUG_INFO(priv, "need full RXON - "	\
+			       #c1 " != " #c2 " - %d != %d\n",	\
+			       (c1), (c2));			\
+		return 1;					\
+	}
+
+	/* These items are only settable from the full RXON command */
+	CHK(!iwl_legacy_is_associated_ctx(ctx));
+	CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr));
+	CHK(compare_ether_addr(staging->node_addr, active->node_addr));
+	CHK(compare_ether_addr(staging->wlap_bssid_addr,
+				active->wlap_bssid_addr));
+	CHK_NEQ(staging->dev_type, active->dev_type);
+	CHK_NEQ(staging->channel, active->channel);
+	CHK_NEQ(staging->air_propagation, active->air_propagation);
+	CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates,
+		active->ofdm_ht_single_stream_basic_rates);
+	CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates,
+		active->ofdm_ht_dual_stream_basic_rates);
+	CHK_NEQ(staging->assoc_id, active->assoc_id);
+
+	/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
+	 * be updated with the RXON_ASSOC command -- however only some
+	 * flag transitions are allowed using RXON_ASSOC */
+
+	/* Check if we are not switching bands */
+	CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
+		active->flags & RXON_FLG_BAND_24G_MSK);
+
+	/* Check if we are switching association toggle */
+	CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
+		active->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+#undef CHK
+#undef CHK_NEQ
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_full_rxon_required);
+
+u8 iwl_legacy_get_lowest_plcp(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx)
+{
+	/*
+	 * Assign the lowest rate -- should really get this from
+	 * the beacon skb from mac80211.
+	 */
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
+		return IWL_RATE_1M_PLCP;
+	else
+		return IWL_RATE_6M_PLCP;
+}
+EXPORT_SYMBOL(iwl_legacy_get_lowest_plcp);
+
+static void _iwl_legacy_set_rxon_ht(struct iwl_priv *priv,
+			     struct iwl_ht_config *ht_conf,
+			     struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+
+	if (!ctx->ht.enabled) {
+		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+			RXON_FLG_HT40_PROT_MSK |
+			RXON_FLG_HT_PROT_MSK);
+		return;
+	}
+
+	rxon->flags |= cpu_to_le32(ctx->ht.protection <<
+					RXON_FLG_HT_OPERATING_MODE_POS);
+
+	/* Set up channel bandwidth:
+	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
+	/* clear the HT channel mode before set the mode */
+	rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+			 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+	if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, NULL)) {
+		/* pure ht40 */
+		if (ctx->ht.protection ==
+				IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
+			rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
+			/* Note: control channel is opposite of extension channel */
+			switch (ctx->ht.extension_chan_offset) {
+			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+				rxon->flags &=
+					~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+				break;
+			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+				rxon->flags |=
+					RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+				break;
+			}
+		} else {
+			/* Note: control channel is opposite of extension channel */
+			switch (ctx->ht.extension_chan_offset) {
+			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+				rxon->flags &=
+					~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
+				rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+				break;
+			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+				rxon->flags |=
+					RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
+				rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
+				break;
+			case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+			default:
+				/* channel location only valid if in Mixed mode */
+				IWL_ERR(priv,
+					"invalid extension channel offset\n");
+				break;
+			}
+		}
+	} else {
+		rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
+	}
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
+			"extension channel offset 0x%x\n",
+			le32_to_cpu(rxon->flags), ctx->ht.protection,
+			ctx->ht.extension_chan_offset);
+}
+
+void iwl_legacy_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
+{
+	struct iwl_rxon_context *ctx;
+
+	for_each_context(priv, ctx)
+		_iwl_legacy_set_rxon_ht(priv, ht_conf, ctx);
+}
+EXPORT_SYMBOL(iwl_legacy_set_rxon_ht);
+
+/* Return valid, unused, channel for a passive scan to reset the RF */
+u8 iwl_legacy_get_single_channel_number(struct iwl_priv *priv,
+				 enum ieee80211_band band)
+{
+	const struct iwl_channel_info *ch_info;
+	int i;
+	u8 channel = 0;
+	u8 min, max;
+	struct iwl_rxon_context *ctx;
+
+	if (band == IEEE80211_BAND_5GHZ) {
+		min = 14;
+		max = priv->channel_count;
+	} else {
+		min = 0;
+		max = 14;
+	}
+
+	for (i = min; i < max; i++) {
+		bool busy = false;
+
+		for_each_context(priv, ctx) {
+			busy = priv->channel_info[i].channel ==
+				le16_to_cpu(ctx->staging.channel);
+			if (busy)
+				break;
+		}
+
+		if (busy)
+			continue;
+
+		channel = priv->channel_info[i].channel;
+		ch_info = iwl_legacy_get_channel_info(priv, band, channel);
+		if (iwl_legacy_is_channel_valid(ch_info))
+			break;
+	}
+
+	return channel;
+}
+EXPORT_SYMBOL(iwl_legacy_get_single_channel_number);
+
+/**
+ * iwl_legacy_set_rxon_channel - Set the band and channel values in staging RXON
+ * @ch: requested channel as a pointer to struct ieee80211_channel
+
+ * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
+ * in the staging RXON flag structure based on the ch->band
+ */
+int
+iwl_legacy_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+			 struct iwl_rxon_context *ctx)
+{
+	enum ieee80211_band band = ch->band;
+	u16 channel = ch->hw_value;
+
+	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
+	    (priv->band == band))
+		return 0;
+
+	ctx->staging.channel = cpu_to_le16(channel);
+	if (band == IEEE80211_BAND_5GHZ)
+		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
+	else
+		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+
+	priv->band = band;
+
+	IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_set_rxon_channel);
+
+void iwl_legacy_set_flags_for_band(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    enum ieee80211_band band,
+			    struct ieee80211_vif *vif)
+{
+	if (band == IEEE80211_BAND_5GHZ) {
+		ctx->staging.flags &=
+		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+		      | RXON_FLG_CCK_MSK);
+		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+	} else {
+		/* Copied from iwl_post_associate() */
+		if (vif && vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+		ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
+		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_set_flags_for_band);
+
+/*
+ * initialize rxon structure with default values from eeprom
+ */
+void iwl_legacy_connection_init_rx_config(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
+{
+	const struct iwl_channel_info *ch_info;
+
+	memset(&ctx->staging, 0, sizeof(ctx->staging));
+
+	if (!ctx->vif) {
+		ctx->staging.dev_type = ctx->unused_devtype;
+	} else
+	switch (ctx->vif->type) {
+
+	case NL80211_IFTYPE_STATION:
+		ctx->staging.dev_type = ctx->station_devtype;
+		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+		break;
+
+	case NL80211_IFTYPE_ADHOC:
+		ctx->staging.dev_type = ctx->ibss_devtype;
+		ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
+						  RXON_FILTER_ACCEPT_GRP_MSK;
+		break;
+
+	default:
+		IWL_ERR(priv, "Unsupported interface type %d\n",
+			ctx->vif->type);
+		break;
+	}
+
+#if 0
+	/* TODO:  Figure out when short_preamble would be set and cache from
+	 * that */
+	if (!hw_to_local(priv->hw)->short_preamble)
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+#endif
+
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band,
+				       le16_to_cpu(ctx->active.channel));
+
+	if (!ch_info)
+		ch_info = &priv->channel_info[0];
+
+	ctx->staging.channel = cpu_to_le16(ch_info->channel);
+	priv->band = ch_info->band;
+
+	iwl_legacy_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
+
+	ctx->staging.ofdm_basic_rates =
+	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+	ctx->staging.cck_basic_rates =
+	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+	/* clear both MIX and PURE40 mode flag */
+	ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
+					RXON_FLG_CHANNEL_MODE_PURE_40);
+	if (ctx->vif)
+		memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
+
+	ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
+	ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
+}
+EXPORT_SYMBOL(iwl_legacy_connection_init_rx_config);
+
+void iwl_legacy_set_rate(struct iwl_priv *priv)
+{
+	const struct ieee80211_supported_band *hw = NULL;
+	struct ieee80211_rate *rate;
+	struct iwl_rxon_context *ctx;
+	int i;
+
+	hw = iwl_get_hw_mode(priv, priv->band);
+	if (!hw) {
+		IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
+		return;
+	}
+
+	priv->active_rate = 0;
+
+	for (i = 0; i < hw->n_bitrates; i++) {
+		rate = &(hw->bitrates[i]);
+		if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
+			priv->active_rate |= (1 << rate->hw_value);
+	}
+
+	IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
+
+	for_each_context(priv, ctx) {
+		ctx->staging.cck_basic_rates =
+		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+		ctx->staging.ofdm_basic_rates =
+		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_set_rate);
+
+void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (priv->switch_rxon.switch_in_progress) {
+		ieee80211_chswitch_done(ctx->vif, is_success);
+		mutex_lock(&priv->mutex);
+		priv->switch_rxon.switch_in_progress = false;
+		mutex_unlock(&priv->mutex);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_chswitch_done);
+
+void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_legacy_rxon_cmd *rxon = (void *)&ctx->active;
+
+	if (priv->switch_rxon.switch_in_progress) {
+		if (!le32_to_cpu(csa->status) &&
+		    (csa->channel == priv->switch_rxon.channel)) {
+			rxon->channel = csa->channel;
+			ctx->staging.channel = csa->channel;
+			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_legacy_chswitch_done(priv, true);
+		} else {
+			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_legacy_chswitch_done(priv, false);
+		}
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_rx_csa);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+
+	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+	IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n",
+				le16_to_cpu(rxon->channel));
+	IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
+	IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
+				le32_to_cpu(rxon->filter_flags));
+	IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
+	IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
+			rxon->ofdm_basic_rates);
+	IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n",
+				rxon->cck_basic_rates);
+	IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr);
+	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
+	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n",
+				le16_to_cpu(rxon->assoc_id));
+}
+EXPORT_SYMBOL(iwl_legacy_print_rx_config_cmd);
+#endif
+/**
+ * iwl_legacy_irq_handle_error - called for HW or SW error interrupt from card
+ */
+void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
+{
+	/* Set the FW error flag -- cleared on iwl_down */
+	set_bit(STATUS_FW_ERROR, &priv->status);
+
+	/* Cancel currently queued command. */
+	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+
+	IWL_ERR(priv, "Loaded firmware version: %s\n",
+		priv->hw->wiphy->fw_version);
+
+	priv->cfg->ops->lib->dump_nic_error_log(priv);
+	if (priv->cfg->ops->lib->dump_fh)
+		priv->cfg->ops->lib->dump_fh(priv, NULL, false);
+	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
+		iwl_legacy_print_rx_config_cmd(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
+#endif
+
+	wake_up_interruptible(&priv->wait_command_queue);
+
+	/* Keep the restart process from trying to send host
+	 * commands by clearing the INIT status bit */
+	clear_bit(STATUS_READY, &priv->status);
+
+	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
+			  "Restarting adapter due to uCode error.\n");
+
+		if (priv->cfg->mod_params->restart_fw)
+			queue_work(priv->workqueue, &priv->restart);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_irq_handle_error);
+
+static int iwl_legacy_apm_stop_master(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	/* stop device's busmaster DMA activity */
+	iwl_legacy_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+
+	ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
+			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+	if (ret)
+		IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
+
+	IWL_DEBUG_INFO(priv, "stop master\n");
+
+	return ret;
+}
+
+void iwl_legacy_apm_stop(struct iwl_priv *priv)
+{
+	IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
+
+	/* Stop device's DMA activity */
+	iwl_legacy_apm_stop_master(priv);
+
+	/* Reset the entire device */
+	iwl_legacy_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+	udelay(10);
+
+	/*
+	 * Clear "initialization complete" bit to move adapter from
+	 * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
+	 */
+	iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+}
+EXPORT_SYMBOL(iwl_legacy_apm_stop);
+
+
+/*
+ * Start up NIC's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via iwl_legacy_apm_stop())
+ * NOTE:  This does not load uCode nor start the embedded processor
+ */
+int iwl_legacy_apm_init(struct iwl_priv *priv)
+{
+	int ret = 0;
+	u16 lctl;
+
+	IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
+
+	/*
+	 * Use "set_bit" below rather than "write", to preserve any hardware
+	 * bits already set by default after reset.
+	 */
+
+	/* Disable L0S exit timer (platform NMI Work/Around) */
+	iwl_legacy_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+			  CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+	/*
+	 * Disable L0s without affecting L1;
+	 *  don't wait for ICH L0s (ICH bug W/A)
+	 */
+	iwl_legacy_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+			  CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
+
+	/* Set FH wait threshold to maximum (HW error during stress W/A) */
+	iwl_legacy_set_bit(priv, CSR_DBG_HPET_MEM_REG,
+					CSR_DBG_HPET_MEM_REG_VAL);
+
+	/*
+	 * Enable HAP INTA (interrupt from management bus) to
+	 * wake device's PCI Express link L1a -> L0s
+	 * NOTE:  This is no-op for 3945 (non-existant bit)
+	 */
+	iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
+
+	/*
+	 * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
+	 * Check if BIOS (or OS) enabled L1-ASPM on this device.
+	 * If so (likely), disable L0S, so device moves directly L0->L1;
+	 *    costs negligible amount of power savings.
+	 * If not (unlikely), enable L0S, so there is at least some
+	 *    power savings, even without L1.
+	 */
+	if (priv->cfg->base_params->set_l0s) {
+		lctl = iwl_legacy_pcie_link_ctl(priv);
+		if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+					PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+			/* L1-ASPM enabled; disable(!) L0S  */
+			iwl_legacy_set_bit(priv, CSR_GIO_REG,
+					CSR_GIO_REG_VAL_L0S_ENABLED);
+			IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
+		} else {
+			/* L1-ASPM disabled; enable(!) L0S */
+			iwl_legacy_clear_bit(priv, CSR_GIO_REG,
+					CSR_GIO_REG_VAL_L0S_ENABLED);
+			IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
+		}
+	}
+
+	/* Configure analog phase-lock-loop before activating to D0A */
+	if (priv->cfg->base_params->pll_cfg_val)
+		iwl_legacy_set_bit(priv, CSR_ANA_PLL_CFG,
+			    priv->cfg->base_params->pll_cfg_val);
+
+	/*
+	 * Set "initialization complete" bit to move adapter from
+	 * D0U* --> D0A* (powered-up active) state.
+	 */
+	iwl_legacy_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+	/*
+	 * Wait for clock stabilization; once stabilized, access to
+	 * device-internal resources is supported, e.g. iwl_legacy_write_prph()
+	 * and accesses to uCode SRAM.
+	 */
+	ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+			CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+			CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+	if (ret < 0) {
+		IWL_DEBUG_INFO(priv, "Failed to init the card\n");
+		goto out;
+	}
+
+	/*
+	 * Enable DMA and BSM (if used) clocks, wait for them to stabilize.
+	 * BSM (Boostrap State Machine) is only in 3945 and 4965.
+	 *
+	 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
+	 * do not disable clocks.  This preserves any hardware bits already
+	 * set by default in "CLK_CTRL_REG" after reset.
+	 */
+	if (priv->cfg->base_params->use_bsm)
+		iwl_legacy_write_prph(priv, APMG_CLK_EN_REG,
+			APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
+	else
+		iwl_legacy_write_prph(priv, APMG_CLK_EN_REG,
+			APMG_CLK_VAL_DMA_CLK_RQT);
+	udelay(20);
+
+	/* Disable L1-Active */
+	iwl_legacy_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_apm_init);
+
+
+int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
+{
+	int ret;
+	s8 prev_tx_power;
+	bool defer;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (priv->tx_power_user_lmt == tx_power && !force)
+		return 0;
+
+	if (!priv->cfg->ops->lib->send_tx_power)
+		return -EOPNOTSUPP;
+
+	if (tx_power < IWL4965_TX_POWER_TARGET_POWER_MIN) {
+		IWL_WARN(priv,
+			 "Requested user TXPOWER %d below lower limit %d.\n",
+			 tx_power,
+			 IWL4965_TX_POWER_TARGET_POWER_MIN);
+		return -EINVAL;
+	}
+
+	if (tx_power > priv->tx_power_device_lmt) {
+		IWL_WARN(priv,
+			"Requested user TXPOWER %d above upper limit %d.\n",
+			 tx_power, priv->tx_power_device_lmt);
+		return -EINVAL;
+	}
+
+	if (!iwl_legacy_is_ready_rf(priv))
+		return -EIO;
+
+	/* scan complete and commit_rxon use tx_power_next value,
+	 * it always need to be updated for newest request */
+	priv->tx_power_next = tx_power;
+
+	/* do not set tx power when scanning or channel changing */
+	defer = test_bit(STATUS_SCANNING, &priv->status) ||
+		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+	if (defer && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
+		return 0;
+	}
+
+	prev_tx_power = priv->tx_power_user_lmt;
+	priv->tx_power_user_lmt = tx_power;
+
+	ret = priv->cfg->ops->lib->send_tx_power(priv);
+
+	/* if fail to set tx_power, restore the orig. tx power */
+	if (ret) {
+		priv->tx_power_user_lmt = prev_tx_power;
+		priv->tx_power_next = prev_tx_power;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_set_tx_power);
+
+void iwl_legacy_send_bt_config(struct iwl_priv *priv)
+{
+	struct iwl_bt_cmd bt_cmd = {
+		.lead_time = BT_LEAD_TIME_DEF,
+		.max_kill = BT_MAX_KILL_DEF,
+		.kill_ack_mask = 0,
+		.kill_cts_mask = 0,
+	};
+
+	if (!bt_coex_active)
+		bt_cmd.flags = BT_COEX_DISABLE;
+	else
+		bt_cmd.flags = BT_COEX_ENABLE;
+
+	IWL_DEBUG_INFO(priv, "BT coex %s\n",
+		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
+
+	if (iwl_legacy_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+			     sizeof(struct iwl_bt_cmd), &bt_cmd))
+		IWL_ERR(priv, "failed to send BT Coex Config\n");
+}
+EXPORT_SYMBOL(iwl_legacy_send_bt_config);
+
+int iwl_legacy_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
+{
+	struct iwl_statistics_cmd statistics_cmd = {
+		.configuration_flags =
+			clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
+	};
+
+	if (flags & CMD_ASYNC)
+		return iwl_legacy_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
+					sizeof(struct iwl_statistics_cmd),
+					&statistics_cmd, NULL);
+	else
+		return iwl_legacy_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+					sizeof(struct iwl_statistics_cmd),
+					&statistics_cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_statistics_request);
+
+void iwl_legacy_rx_pm_sleep_notif(struct iwl_priv *priv,
+			   struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
+		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
+#endif
+}
+EXPORT_SYMBOL(iwl_legacy_rx_pm_sleep_notif);
+
+void iwl_legacy_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
+			"notification for %s:\n", len,
+			iwl_legacy_get_cmd_string(pkt->hdr.cmd));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+}
+EXPORT_SYMBOL(iwl_legacy_rx_pm_debug_statistics_notif);
+
+void iwl_legacy_rx_reply_error(struct iwl_priv *priv,
+			struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
+		"seq 0x%04X ser 0x%08X\n",
+		le32_to_cpu(pkt->u.err_resp.error_type),
+		iwl_legacy_get_cmd_string(pkt->u.err_resp.cmd_id),
+		pkt->u.err_resp.cmd_id,
+		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
+		le32_to_cpu(pkt->u.err_resp.error_info));
+}
+EXPORT_SYMBOL(iwl_legacy_rx_reply_error);
+
+void iwl_legacy_clear_isr_stats(struct iwl_priv *priv)
+{
+	memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
+}
+
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			   const struct ieee80211_tx_queue_params *params)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx;
+	unsigned long flags;
+	int q;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return -EIO;
+	}
+
+	if (queue >= AC_NUM) {
+		IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue);
+		return 0;
+	}
+
+	q = AC_NUM - 1 - queue;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	for_each_context(priv, ctx) {
+		ctx->qos_data.def_qos_parm.ac[q].cw_min =
+			cpu_to_le16(params->cw_min);
+		ctx->qos_data.def_qos_parm.ac[q].cw_max =
+			cpu_to_le16(params->cw_max);
+		ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+		ctx->qos_data.def_qos_parm.ac[q].edca_txop =
+				cpu_to_le16((params->txop * 32));
+
+		ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_conf_tx);
+
+int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	return priv->ibss_manager == IWL_IBSS_MANAGER;
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_mac_tx_last_beacon);
+
+static int
+iwl_legacy_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	iwl_legacy_connection_init_rx_config(priv, ctx);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	return iwl_legacy_commit_rxon(priv, ctx);
+}
+
+static int iwl_legacy_setup_interface(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx)
+{
+	struct ieee80211_vif *vif = ctx->vif;
+	int err;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/*
+	 * This variable will be correct only when there's just
+	 * a single context, but all code using it is for hardware
+	 * that supports only one context.
+	 */
+	priv->iw_mode = vif->type;
+
+	ctx->is_active = true;
+
+	err = iwl_legacy_set_mode(priv, ctx);
+	if (err) {
+		if (!ctx->always_active)
+			ctx->is_active = false;
+		return err;
+	}
+
+	return 0;
+}
+
+int
+iwl_legacy_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	struct iwl_rxon_context *tmp, *ctx = NULL;
+	int err;
+
+	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
+			   vif->type, vif->addr);
+
+	mutex_lock(&priv->mutex);
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_WARN(priv, "Try to add interface when device not ready\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	for_each_context(priv, tmp) {
+		u32 possible_modes =
+			tmp->interface_modes | tmp->exclusive_interface_modes;
+
+		if (tmp->vif) {
+			/* check if this busy context is exclusive */
+			if (tmp->exclusive_interface_modes &
+						BIT(tmp->vif->type)) {
+				err = -EINVAL;
+				goto out;
+			}
+			continue;
+		}
+
+		if (!(possible_modes & BIT(vif->type)))
+			continue;
+
+		/* have maybe usable context w/o interface */
+		ctx = tmp;
+		break;
+	}
+
+	if (!ctx) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	vif_priv->ctx = ctx;
+	ctx->vif = vif;
+
+	err = iwl_legacy_setup_interface(priv, ctx);
+	if (!err)
+		goto out;
+
+	ctx->vif = NULL;
+	priv->iw_mode = NL80211_IFTYPE_STATION;
+ out:
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return err;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_add_interface);
+
+static void iwl_legacy_teardown_interface(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   bool mode_change)
+{
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (priv->scan_vif == vif) {
+		iwl_legacy_scan_cancel_timeout(priv, 200);
+		iwl_legacy_force_scan_end(priv);
+	}
+
+	if (!mode_change) {
+		iwl_legacy_set_mode(priv, ctx);
+		if (!ctx->always_active)
+			ctx->is_active = false;
+	}
+}
+
+void iwl_legacy_mac_remove_interface(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	mutex_lock(&priv->mutex);
+
+	WARN_ON(ctx->vif != vif);
+	ctx->vif = NULL;
+
+	iwl_legacy_teardown_interface(priv, vif, false);
+
+	memset(priv->bssid, 0, ETH_ALEN);
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+}
+EXPORT_SYMBOL(iwl_legacy_mac_remove_interface);
+
+int iwl_legacy_alloc_txq_mem(struct iwl_priv *priv)
+{
+	if (!priv->txq)
+		priv->txq = kzalloc(
+			sizeof(struct iwl_tx_queue) *
+				priv->cfg->base_params->num_of_queues,
+			GFP_KERNEL);
+	if (!priv->txq) {
+		IWL_ERR(priv, "Not enough memory for txq\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_alloc_txq_mem);
+
+void iwl_legacy_txq_mem(struct iwl_priv *priv)
+{
+	kfree(priv->txq);
+	priv->txq = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_txq_mem);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+
+#define IWL_TRAFFIC_DUMP_SIZE	(IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
+
+void iwl_legacy_reset_traffic_log(struct iwl_priv *priv)
+{
+	priv->tx_traffic_idx = 0;
+	priv->rx_traffic_idx = 0;
+	if (priv->tx_traffic)
+		memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+	if (priv->rx_traffic)
+		memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+}
+
+int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv)
+{
+	u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
+
+	if (iwlegacy_debug_level & IWL_DL_TX) {
+		if (!priv->tx_traffic) {
+			priv->tx_traffic =
+				kzalloc(traffic_size, GFP_KERNEL);
+			if (!priv->tx_traffic)
+				return -ENOMEM;
+		}
+	}
+	if (iwlegacy_debug_level & IWL_DL_RX) {
+		if (!priv->rx_traffic) {
+			priv->rx_traffic =
+				kzalloc(traffic_size, GFP_KERNEL);
+			if (!priv->rx_traffic)
+				return -ENOMEM;
+		}
+	}
+	iwl_legacy_reset_traffic_log(priv);
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_alloc_traffic_mem);
+
+void iwl_legacy_free_traffic_mem(struct iwl_priv *priv)
+{
+	kfree(priv->tx_traffic);
+	priv->tx_traffic = NULL;
+
+	kfree(priv->rx_traffic);
+	priv->rx_traffic = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_free_traffic_mem);
+
+void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+	__le16 fc;
+	u16 len;
+
+	if (likely(!(iwlegacy_debug_level & IWL_DL_TX)))
+		return;
+
+	if (!priv->tx_traffic)
+		return;
+
+	fc = header->frame_control;
+	if (ieee80211_is_data(fc)) {
+		len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+		       ? IWL_TRAFFIC_ENTRY_SIZE : length;
+		memcpy((priv->tx_traffic +
+		       (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+		       header, len);
+		priv->tx_traffic_idx =
+			(priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_dbg_log_tx_data_frame);
+
+void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+	__le16 fc;
+	u16 len;
+
+	if (likely(!(iwlegacy_debug_level & IWL_DL_RX)))
+		return;
+
+	if (!priv->rx_traffic)
+		return;
+
+	fc = header->frame_control;
+	if (ieee80211_is_data(fc)) {
+		len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+		       ? IWL_TRAFFIC_ENTRY_SIZE : length;
+		memcpy((priv->rx_traffic +
+		       (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+		       header, len);
+		priv->rx_traffic_idx =
+			(priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_dbg_log_rx_data_frame);
+
+const char *iwl_legacy_get_mgmt_string(int cmd)
+{
+	switch (cmd) {
+		IWL_CMD(MANAGEMENT_ASSOC_REQ);
+		IWL_CMD(MANAGEMENT_ASSOC_RESP);
+		IWL_CMD(MANAGEMENT_REASSOC_REQ);
+		IWL_CMD(MANAGEMENT_REASSOC_RESP);
+		IWL_CMD(MANAGEMENT_PROBE_REQ);
+		IWL_CMD(MANAGEMENT_PROBE_RESP);
+		IWL_CMD(MANAGEMENT_BEACON);
+		IWL_CMD(MANAGEMENT_ATIM);
+		IWL_CMD(MANAGEMENT_DISASSOC);
+		IWL_CMD(MANAGEMENT_AUTH);
+		IWL_CMD(MANAGEMENT_DEAUTH);
+		IWL_CMD(MANAGEMENT_ACTION);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+const char *iwl_legacy_get_ctrl_string(int cmd)
+{
+	switch (cmd) {
+		IWL_CMD(CONTROL_BACK_REQ);
+		IWL_CMD(CONTROL_BACK);
+		IWL_CMD(CONTROL_PSPOLL);
+		IWL_CMD(CONTROL_RTS);
+		IWL_CMD(CONTROL_CTS);
+		IWL_CMD(CONTROL_ACK);
+		IWL_CMD(CONTROL_CFEND);
+		IWL_CMD(CONTROL_CFENDACK);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+void iwl_legacy_clear_traffic_stats(struct iwl_priv *priv)
+{
+	memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
+	memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
+}
+
+/*
+ * if CONFIG_IWLWIFI_LEGACY_DEBUGFS defined,
+ * iwl_legacy_update_stats function will
+ * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass
+ * Use debugFs to display the rx/rx_statistics
+ * if CONFIG_IWLWIFI_LEGACY_DEBUGFS not being defined, then no MGMT and CTRL
+ * information will be recorded, but DATA pkt still will be recorded
+ * for the reason of iwl_led.c need to control the led blinking based on
+ * number of tx and rx data.
+ *
+ */
+void
+iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
+{
+	struct traffic_stats	*stats;
+
+	if (is_tx)
+		stats = &priv->tx_stats;
+	else
+		stats = &priv->rx_stats;
+
+	if (ieee80211_is_mgmt(fc)) {
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_BEACON):
+			stats->mgmt[MANAGEMENT_BEACON]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ATIM):
+			stats->mgmt[MANAGEMENT_ATIM]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+			stats->mgmt[MANAGEMENT_DISASSOC]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+			stats->mgmt[MANAGEMENT_AUTH]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+			stats->mgmt[MANAGEMENT_DEAUTH]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ACTION):
+			stats->mgmt[MANAGEMENT_ACTION]++;
+			break;
+		}
+	} else if (ieee80211_is_ctl(fc)) {
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
+			stats->ctrl[CONTROL_BACK_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_BACK):
+			stats->ctrl[CONTROL_BACK]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
+			stats->ctrl[CONTROL_PSPOLL]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_RTS):
+			stats->ctrl[CONTROL_RTS]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CTS):
+			stats->ctrl[CONTROL_CTS]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ACK):
+			stats->ctrl[CONTROL_ACK]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CFEND):
+			stats->ctrl[CONTROL_CFEND]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
+			stats->ctrl[CONTROL_CFENDACK]++;
+			break;
+		}
+	} else {
+		/* data */
+		stats->data_cnt++;
+		stats->data_bytes += len;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_update_stats);
+#endif
+
+static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!iwl_legacy_is_any_associated(priv)) {
+		IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
+		return;
+	}
+	/*
+	 * There is no easy and better way to force reset the radio,
+	 * the only known method is switching channel which will force to
+	 * reset and tune the radio.
+	 * Use internal short scan (single channel) operation to should
+	 * achieve this objective.
+	 * Driver should reset the radio when number of consecutive missed
+	 * beacon, or any other uCode error condition detected.
+	 */
+	IWL_DEBUG_INFO(priv, "perform radio reset.\n");
+	iwl_legacy_internal_short_hw_scan(priv);
+}
+
+
+int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+{
+	struct iwl_force_reset *force_reset;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EINVAL;
+
+	if (mode >= IWL_MAX_FORCE_RESET) {
+		IWL_DEBUG_INFO(priv, "invalid reset request.\n");
+		return -EINVAL;
+	}
+	force_reset = &priv->force_reset[mode];
+	force_reset->reset_request_count++;
+	if (!external) {
+		if (force_reset->last_force_reset_jiffies &&
+		    time_after(force_reset->last_force_reset_jiffies +
+		    force_reset->reset_duration, jiffies)) {
+			IWL_DEBUG_INFO(priv, "force reset rejected\n");
+			force_reset->reset_reject_count++;
+			return -EAGAIN;
+		}
+	}
+	force_reset->reset_success_count++;
+	force_reset->last_force_reset_jiffies = jiffies;
+	IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
+	switch (mode) {
+	case IWL_RF_RESET:
+		_iwl_legacy_force_rf_reset(priv);
+		break;
+	case IWL_FW_RESET:
+		/*
+		 * if the request is from external(ex: debugfs),
+		 * then always perform the request in regardless the module
+		 * parameter setting
+		 * if the request is from internal (uCode error or driver
+		 * detect failure), then fw_restart module parameter
+		 * need to be check before performing firmware reload
+		 */
+		if (!external && !priv->cfg->mod_params->restart_fw) {
+			IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+				       "module parameter setting\n");
+			break;
+		}
+		IWL_ERR(priv, "On demand firmware reload\n");
+		/* Set the FW error flag -- cleared on iwl_down */
+		set_bit(STATUS_FW_ERROR, &priv->status);
+		wake_up_interruptible(&priv->wait_command_queue);
+		/*
+		 * Keep the restart process from trying to send host
+		 * commands by clearing the INIT status bit
+		 */
+		clear_bit(STATUS_READY, &priv->status);
+		queue_work(priv->workqueue, &priv->restart);
+		break;
+	}
+	return 0;
+}
+
+int
+iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			enum nl80211_iftype newtype, bool newp2p)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+	struct iwl_rxon_context *tmp;
+	u32 interface_modes;
+	int err;
+
+	newtype = ieee80211_iftype_p2p(newtype, newp2p);
+
+	mutex_lock(&priv->mutex);
+
+	interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
+
+	if (!(interface_modes & BIT(newtype))) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (ctx->exclusive_interface_modes & BIT(newtype)) {
+		for_each_context(priv, tmp) {
+			if (ctx == tmp)
+				continue;
+
+			if (!tmp->vif)
+				continue;
+
+			/*
+			 * The current mode switch would be exclusive, but
+			 * another context is active ... refuse the switch.
+			 */
+			err = -EBUSY;
+			goto out;
+		}
+	}
+
+	/* success */
+	iwl_legacy_teardown_interface(priv, vif, true);
+	vif->type = newtype;
+	err = iwl_legacy_setup_interface(priv, ctx);
+	WARN_ON(err);
+	/*
+	 * We've switched internally, but submitting to the
+	 * device may have failed for some reason. Mask this
+	 * error, because otherwise mac80211 will not switch
+	 * (and set the interface type back) and we'll be
+	 * out of sync with it.
+	 */
+	err = 0;
+
+ out:
+	mutex_unlock(&priv->mutex);
+	return err;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_change_interface);
+
+/*
+ * On every watchdog tick we check (latest) time stamp. If it does not
+ * change during timeout period and queue is not empty we reset firmware.
+ */
+static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
+{
+	struct iwl_tx_queue *txq = &priv->txq[cnt];
+	struct iwl_queue *q = &txq->q;
+	unsigned long timeout;
+	int ret;
+
+	if (q->read_ptr == q->write_ptr) {
+		txq->time_stamp = jiffies;
+		return 0;
+	}
+
+	timeout = txq->time_stamp +
+		  msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
+
+	if (time_after(jiffies, timeout)) {
+		IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
+				q->id, priv->cfg->base_params->wd_timeout);
+		ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+		return (ret == -EAGAIN) ? 0 : 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Making watchdog tick be a quarter of timeout assure we will
+ * discover the queue hung between timeout and 1.25*timeout
+ */
+#define IWL_WD_TICK(timeout) ((timeout) / 4)
+
+/*
+ * Watchdog timer callback, we check each tx queue for stuck, if if hung
+ * we reset the firmware. If everything is fine just rearm the timer.
+ */
+void iwl_legacy_bg_watchdog(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+	int cnt;
+	unsigned long timeout;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	timeout = priv->cfg->base_params->wd_timeout;
+	if (timeout == 0)
+		return;
+
+	/* monitor and check for stuck cmd queue */
+	if (iwl_legacy_check_stuck_queue(priv, priv->cmd_queue))
+		return;
+
+	/* monitor and check for other stuck queues */
+	if (iwl_legacy_is_any_associated(priv)) {
+		for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+			/* skip as we already checked the command queue */
+			if (cnt == priv->cmd_queue)
+				continue;
+			if (iwl_legacy_check_stuck_queue(priv, cnt))
+				return;
+		}
+	}
+
+	mod_timer(&priv->watchdog, jiffies +
+		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
+}
+EXPORT_SYMBOL(iwl_legacy_bg_watchdog);
+
+void iwl_legacy_setup_watchdog(struct iwl_priv *priv)
+{
+	unsigned int timeout = priv->cfg->base_params->wd_timeout;
+
+	if (timeout)
+		mod_timer(&priv->watchdog,
+			  jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
+	else
+		del_timer(&priv->watchdog);
+}
+EXPORT_SYMBOL(iwl_legacy_setup_watchdog);
+
+/*
+ * extended beacon time format
+ * time in usec will be changed into a 32-bit value in extended:internal format
+ * the extended part is the beacon counts
+ * the internal part is the time in usec within one beacon interval
+ */
+u32
+iwl_legacy_usecs_to_beacons(struct iwl_priv *priv,
+					u32 usec, u32 beacon_interval)
+{
+	u32 quot;
+	u32 rem;
+	u32 interval = beacon_interval * TIME_UNIT;
+
+	if (!interval || !usec)
+		return 0;
+
+	quot = (usec / interval) &
+		(iwl_legacy_beacon_time_mask_high(priv,
+		priv->hw_params.beacon_time_tsf_bits) >>
+		priv->hw_params.beacon_time_tsf_bits);
+	rem = (usec % interval) & iwl_legacy_beacon_time_mask_low(priv,
+				   priv->hw_params.beacon_time_tsf_bits);
+
+	return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
+}
+EXPORT_SYMBOL(iwl_legacy_usecs_to_beacons);
+
+/* base is usually what we get from ucode with each received frame,
+ * the same as HW timer counter counting down
+ */
+__le32 iwl_legacy_add_beacon_time(struct iwl_priv *priv, u32 base,
+			   u32 addon, u32 beacon_interval)
+{
+	u32 base_low = base & iwl_legacy_beacon_time_mask_low(priv,
+					priv->hw_params.beacon_time_tsf_bits);
+	u32 addon_low = addon & iwl_legacy_beacon_time_mask_low(priv,
+					priv->hw_params.beacon_time_tsf_bits);
+	u32 interval = beacon_interval * TIME_UNIT;
+	u32 res = (base & iwl_legacy_beacon_time_mask_high(priv,
+				priv->hw_params.beacon_time_tsf_bits)) +
+				(addon & iwl_legacy_beacon_time_mask_high(priv,
+				priv->hw_params.beacon_time_tsf_bits));
+
+	if (base_low > addon_low)
+		res += base_low - addon_low;
+	else if (base_low < addon_low) {
+		res += interval + base_low - addon_low;
+		res += (1 << priv->hw_params.beacon_time_tsf_bits);
+	} else
+		res += (1 << priv->hw_params.beacon_time_tsf_bits);
+
+	return cpu_to_le32(res);
+}
+EXPORT_SYMBOL(iwl_legacy_add_beacon_time);
+
+#ifdef CONFIG_PM
+
+int iwl_legacy_pci_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+	/*
+	 * This function is called when system goes into suspend state
+	 * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
+	 * first but since iwl_mac_stop() has no knowledge of who the caller is,
+	 * it will not call apm_ops.stop() to stop the DMA operation.
+	 * Calling apm_ops.stop here to make sure we stop the DMA.
+	 */
+	iwl_legacy_apm_stop(priv);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_pci_suspend);
+
+int iwl_legacy_pci_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	bool hw_rfkill = false;
+
+	/*
+	 * We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+	iwl_legacy_enable_interrupts(priv);
+
+	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+		hw_rfkill = true;
+
+	if (hw_rfkill)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_pci_resume);
+
+const struct dev_pm_ops iwl_legacy_pm_ops = {
+	.suspend = iwl_legacy_pci_suspend,
+	.resume = iwl_legacy_pci_resume,
+	.freeze = iwl_legacy_pci_suspend,
+	.thaw = iwl_legacy_pci_resume,
+	.poweroff = iwl_legacy_pci_suspend,
+	.restore = iwl_legacy_pci_resume,
+};
+EXPORT_SYMBOL(iwl_legacy_pm_ops);
+
+#endif /* CONFIG_PM */
+
+static void
+iwl_legacy_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+	if (ctx->qos_data.qos_active)
+		ctx->qos_data.def_qos_parm.qos_flags |=
+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+	if (ctx->ht.enabled)
+		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
+
+	iwl_legacy_send_cmd_pdu_async(priv, ctx->qos_cmd,
+			       sizeof(struct iwl_qosparam_cmd),
+			       &ctx->qos_data.def_qos_parm, NULL);
+}
+
+/**
+ * iwl_legacy_mac_config - mac80211 config callback
+ */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct iwl_priv *priv = hw->priv;
+	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = conf->channel;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct iwl_rxon_context *ctx;
+	unsigned long flags = 0;
+	int ret = 0;
+	u16 ch;
+	int scan_active = 0;
+	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
+					channel->hw_value, changed);
+
+	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
+			test_bit(STATUS_SCANNING, &priv->status))) {
+		scan_active = 1;
+		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
+		       IEEE80211_CONF_CHANGE_CHANNEL)) {
+		/* mac80211 uses static for non-HT which is what we want */
+		priv->current_ht_config.smps = conf->smps_mode;
+
+		/*
+		 * Recalculate chain counts.
+		 *
+		 * If monitor mode is enabled then mac80211 will
+		 * set up the SM PS mode to OFF if an HT channel is
+		 * configured.
+		 */
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	/* during scanning mac80211 will delay channel setting until
+	 * scan finish with changed = 0
+	 */
+	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+		if (scan_active)
+			goto set_ch_out;
+
+		ch = channel->hw_value;
+		ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+		if (!iwl_legacy_is_channel_valid(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		for_each_context(priv, ctx) {
+			/* Configure HT40 channels */
+			if (ctx->ht.enabled != conf_is_ht(conf)) {
+				ctx->ht.enabled = conf_is_ht(conf);
+				ht_changed[ctx->ctxid] = true;
+			}
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			/*
+			 * Default to no protection. Protection mode will
+			 * later be set from BSS config in iwl_ht_conf
+			 */
+			ctx->ht.protection =
+					IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+			/* if we are switching from ht to 2.4 clear flags
+			 * from any ht related info since 2.4 does not
+			 * support ht */
+			if ((le16_to_cpu(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
+
+			iwl_legacy_set_rxon_channel(priv, channel, ctx);
+			iwl_legacy_set_rxon_ht(priv, ht_conf);
+
+			iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		if (priv->cfg->ops->legacy->update_bcast_stations)
+			ret =
+			priv->cfg->ops->legacy->update_bcast_stations(priv);
+
+ set_ch_out:
+		/* The list of supported rates and rate mask can be different
+		 * for each band; since the band may have changed, reset
+		 * the rate mask to what mac80211 lists */
+		iwl_legacy_set_rate(priv);
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_PS |
+			IEEE80211_CONF_CHANGE_IDLE)) {
+		ret = iwl_legacy_power_update_mode(priv, false);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
+			priv->tx_power_user_lmt, conf->power_level);
+
+		iwl_legacy_set_tx_power(priv, conf->power_level, false);
+	}
+
+	if (!iwl_legacy_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (scan_active)
+		goto out;
+
+	for_each_context(priv, ctx) {
+		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
+			iwl_legacy_commit_rxon(priv, ctx);
+		else
+			IWL_DEBUG_INFO(priv,
+				"Not re-sending same RXON configuration.\n");
+		if (ht_changed[ctx->ctxid])
+			iwl_legacy_update_qos(priv, ctx);
+	}
+
+out:
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_config);
+
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	/* IBSS can only be the IWL_RXON_CTX_BSS context */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	spin_lock_irqsave(&priv->lock, flags);
+	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* new association get rid of ibss beacon skb */
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = NULL;
+
+	priv->timestamp = 0;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_legacy_scan_cancel_timeout(priv, 100);
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	/* we are restarting association process
+	 * clear RXON_FILTER_ASSOC_MSK bit
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	iwl_legacy_set_rate(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
+
+static void iwl_legacy_ht_conf(struct iwl_priv *priv,
+			struct ieee80211_vif *vif)
+{
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct ieee80211_sta *sta;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	IWL_DEBUG_ASSOC(priv, "enter:\n");
+
+	if (!ctx->ht.enabled)
+		return;
+
+	ctx->ht.protection =
+		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+	ctx->ht.non_gf_sta_present =
+		!!(bss_conf->ht_operation_mode &
+				IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+	ht_conf->single_chain_sufficient = false;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (sta) {
+			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+			int maxstreams;
+
+			maxstreams = (ht_cap->mcs.tx_params &
+			      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+				>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			if ((ht_cap->mcs.rx_mask[1] == 0) &&
+			    (ht_cap->mcs.rx_mask[2] == 0))
+				ht_conf->single_chain_sufficient = true;
+			if (maxstreams <= 1)
+				ht_conf->single_chain_sufficient = true;
+		} else {
+			/*
+			 * If at all, this can only happen through a race
+			 * when the AP disconnects us while we're still
+			 * setting up the connection, in that case mac80211
+			 * will soon tell us about that.
+			 */
+			ht_conf->single_chain_sufficient = true;
+		}
+		rcu_read_unlock();
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ht_conf->single_chain_sufficient = true;
+		break;
+	default:
+		break;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "leave\n");
+}
+
+static inline void iwl_legacy_set_no_assoc(struct iwl_priv *priv,
+				    struct ieee80211_vif *vif)
+{
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	/*
+	 * inform the ucode that there is no longer an
+	 * association and that no more packets should be
+	 * sent
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ctx->staging.assoc_id = 0;
+	iwl_legacy_commit_rxon(priv, ctx);
+}
+
+static void iwl_legacy_beacon_update(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	__le64 timestamp;
+	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+
+	if (!skb)
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "update beacon but no beacon context!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = skb;
+
+	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+	priv->timestamp = le64_to_cpu(timestamp);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return;
+	}
+
+	priv->cfg->ops->legacy->post_associate(priv);
+}
+
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+	int ret;
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
+
+	if (!iwl_legacy_is_alive(priv))
+		return;
+
+	mutex_lock(&priv->mutex);
+
+	if (changes & BSS_CHANGED_QOS) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwl_legacy_update_qos(priv, ctx);
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		/*
+		 * the add_interface code must make sure we only ever
+		 * have a single interface that could be beaconing at
+		 * any time.
+		 */
+		if (vif->bss_conf.enable_beacon)
+			priv->beacon_ctx = ctx;
+		else
+			priv->beacon_ctx = NULL;
+	}
+
+	if (changes & BSS_CHANGED_BSSID) {
+		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
+
+		/*
+		 * If there is currently a HW scan going on in the
+		 * background then we need to cancel it else the RXON
+		 * below/in post_associate will fail.
+		 */
+		if (iwl_legacy_scan_cancel_timeout(priv, 100)) {
+			IWL_WARN(priv,
+				"Aborted scan still in progress after 100ms\n");
+			IWL_DEBUG_MAC80211(priv,
+				"leaving - scan abort failed.\n");
+			mutex_unlock(&priv->mutex);
+			return;
+		}
+
+		/* mac80211 only sets assoc when in STATION mode */
+		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+
+			/* currently needed in a few places */
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+		} else {
+			ctx->staging.filter_flags &=
+				~RXON_FILTER_ASSOC_MSK;
+		}
+
+	}
+
+	/*
+	 * This needs to be after setting the BSSID in case
+	 * mac80211 decides to do both changes at once because
+	 * it will invoke post_associate.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
+		iwl_legacy_beacon_update(hw, vif);
+
+	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
+				   bss_conf->use_short_preamble);
+		if (bss_conf->use_short_preamble)
+			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+	}
+
+	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+		IWL_DEBUG_MAC80211(priv,
+			"ERP_CTS %d\n", bss_conf->use_cts_prot);
+		if (bss_conf->use_cts_prot &&
+			(priv->band != IEEE80211_BAND_5GHZ))
+			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+		if (bss_conf->use_cts_prot)
+			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+	}
+
+	if (changes & BSS_CHANGED_BASIC_RATES) {
+		/* XXX use this information
+		 *
+		 * To do that, remove code from iwl_legacy_set_rate() and put something
+		 * like this here:
+		 *
+		if (A-band)
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates;
+		else
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates >> 4;
+			ctx->staging.cck_basic_rates =
+				bss_conf->basic_rates & 0xF;
+		 */
+	}
+
+	if (changes & BSS_CHANGED_HT) {
+		iwl_legacy_ht_conf(priv, vif);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
+		if (bss_conf->assoc) {
+			priv->timestamp = bss_conf->timestamp;
+
+			if (!iwl_legacy_is_rfkill(priv))
+				priv->cfg->ops->legacy->post_associate(priv);
+		} else
+			iwl_legacy_set_no_assoc(priv, vif);
+	}
+
+	if (changes && iwl_legacy_is_associated_ctx(ctx) && bss_conf->aid) {
+		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
+				   changes);
+		ret = iwl_legacy_send_rxon_assoc(priv, ctx);
+		if (!ret) {
+			/* Sync active_rxon with latest change. */
+			memcpy((void *)&ctx->active,
+				&ctx->staging,
+				sizeof(struct iwl_legacy_rxon_cmd));
+		}
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		if (vif->bss_conf.enable_beacon) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+			priv->cfg->ops->legacy->config_ap(priv);
+		} else
+			iwl_legacy_set_no_assoc(priv, vif);
+	}
+
+	if (changes & BSS_CHANGED_IBSS) {
+		ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
+							bss_conf->ibss_joined);
+		if (ret)
+			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
+				bss_conf->ibss_joined ? "add" : "remove",
+				bss_conf->bssid);
+	}
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
+
+irqreturn_t iwl_legacy_isr(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	u32 inta_fh;
+	unsigned long flags;
+	if (!priv)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 *    back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here. */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(priv, CSR_INT);
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta && !inta_fh) {
+		IWL_DEBUG_ISR(priv,
+			"Ignore interrupt, inta == 0, inta_fh == 0\n");
+		goto none;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		goto unplugged;
+	}
+
+	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+		      inta, inta_mask, inta_fh);
+
+	inta &= ~CSR_INT_BIT_SCD;
+
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
+
+unplugged:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+
+none:
+	/* re-enable interrupts here since we don't have anything to service. */
+	/* only Re-enable if diabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_legacy_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_NONE;
+}
+EXPORT_SYMBOL(iwl_legacy_isr);
+
+/*
+ *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
+ *  function.
+ */
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+			       struct ieee80211_tx_info *info,
+			       __le16 fc, __le32 *tx_flags)
+{
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+		*tx_flags |= TX_CMD_FLG_RTS_MSK;
+		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+		if (!ieee80211_is_mgmt(fc))
+			return;
+
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+			*tx_flags |= TX_CMD_FLG_CTS_MSK;
+			break;
+		}
+	} else if (info->control.rates[0].flags &
+		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
+		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+		*tx_flags |= TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
new file mode 100644
index 0000000..f03b463
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-core.h
@@ -0,0 +1,646 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_core_h__
+#define __iwl_legacy_core_h__
+
+/************************
+ * forward declarations *
+ ************************/
+struct iwl_host_cmd;
+struct iwl_cmd;
+
+
+#define IWLWIFI_VERSION "in-tree:"
+#define DRV_COPYRIGHT	"Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR     "<ilw@linux.intel.com>"
+
+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
+	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
+	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+	.driver_data = (kernel_ulong_t)&(cfg)
+
+#define TIME_UNIT		1024
+
+#define IWL_SKU_G       0x1
+#define IWL_SKU_A       0x2
+#define IWL_SKU_N       0x8
+
+#define IWL_CMD(x) case x: return #x
+
+struct iwl_hcmd_ops {
+	int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+	int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+	void (*set_rxon_chain)(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+};
+
+struct iwl_hcmd_utils_ops {
+	u16 (*get_hcmd_size)(u8 cmd_id, u16 len);
+	u16 (*build_addsta_hcmd)(const struct iwl_legacy_addsta_cmd *cmd,
+								u8 *data);
+	int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
+	void (*post_scan)(struct iwl_priv *priv);
+};
+
+struct iwl_apm_ops {
+	int (*init)(struct iwl_priv *priv);
+	void (*config)(struct iwl_priv *priv);
+};
+
+struct iwl_debugfs_ops {
+	ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
+				 size_t count, loff_t *ppos);
+	ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf,
+				 size_t count, loff_t *ppos);
+	ssize_t (*general_stats_read)(struct file *file, char __user *user_buf,
+				      size_t count, loff_t *ppos);
+};
+
+struct iwl_temp_ops {
+	void (*temperature)(struct iwl_priv *priv);
+};
+
+struct iwl_lib_ops {
+	/* set hw dependent parameters */
+	int (*set_hw_params)(struct iwl_priv *priv);
+	/* Handling TX */
+	void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					u16 byte_cnt);
+	int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
+				     struct iwl_tx_queue *txq,
+				     dma_addr_t addr,
+				     u16 len, u8 reset, u8 pad);
+	void (*txq_free_tfd)(struct iwl_priv *priv,
+			     struct iwl_tx_queue *txq);
+	int (*txq_init)(struct iwl_priv *priv,
+			struct iwl_tx_queue *txq);
+	/* setup Rx handler */
+	void (*rx_handler_setup)(struct iwl_priv *priv);
+	/* alive notification after init uCode load */
+	void (*init_alive_start)(struct iwl_priv *priv);
+	/* check validity of rtc data address */
+	int (*is_valid_rtc_data_addr)(u32 addr);
+	/* 1st ucode load */
+	int (*load_ucode)(struct iwl_priv *priv);
+	int (*dump_nic_event_log)(struct iwl_priv *priv,
+				  bool full_log, char **buf, bool display);
+	void (*dump_nic_error_log)(struct iwl_priv *priv);
+	int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
+	int (*set_channel_switch)(struct iwl_priv *priv,
+				  struct ieee80211_channel_switch *ch_switch);
+	/* power management */
+	struct iwl_apm_ops apm_ops;
+
+	/* power */
+	int (*send_tx_power) (struct iwl_priv *priv);
+	void (*update_chain_flags)(struct iwl_priv *priv);
+
+	/* eeprom operations (as defined in iwl-eeprom.h) */
+	struct iwl_eeprom_ops eeprom_ops;
+
+	/* temperature */
+	struct iwl_temp_ops temp_ops;
+	/* check for plcp health */
+	bool (*check_plcp_health)(struct iwl_priv *priv,
+					struct iwl_rx_packet *pkt);
+
+	struct iwl_debugfs_ops debugfs_ops;
+
+};
+
+struct iwl_led_ops {
+	int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
+};
+
+struct iwl_legacy_ops {
+	void (*post_associate)(struct iwl_priv *priv);
+	void (*config_ap)(struct iwl_priv *priv);
+	/* station management */
+	int (*update_bcast_stations)(struct iwl_priv *priv);
+	int (*manage_ibss_station)(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif, bool add);
+};
+
+struct iwl_ops {
+	const struct iwl_lib_ops *lib;
+	const struct iwl_hcmd_ops *hcmd;
+	const struct iwl_hcmd_utils_ops *utils;
+	const struct iwl_led_ops *led;
+	const struct iwl_nic_ops *nic;
+	const struct iwl_legacy_ops *legacy;
+	const struct ieee80211_ops *ieee80211_ops;
+};
+
+struct iwl_mod_params {
+	int sw_crypto;		/* def: 0 = using hardware encryption */
+	int disable_hw_scan;	/* def: 0 = use h/w scan */
+	int num_of_queues;	/* def: HW dependent */
+	int disable_11n;	/* def: 0 = 11n capabilities enabled */
+	int amsdu_size_8K;	/* def: 1 = enable 8K amsdu size */
+	int antenna;  		/* def: 0 = both antennas (use diversity) */
+	int restart_fw;		/* def: 1 = restart firmware */
+};
+
+/*
+ * @led_compensation: compensate on the led on/off time per HW according
+ *	to the deviation to achieve the desired led frequency.
+ *	The detail algorithm is described in iwl-led.c
+ * @chain_noise_num_beacons: number of beacons used to compute chain noise
+ * @plcp_delta_threshold: plcp error rate threshold used to trigger
+ *	radio tuning when there is a high receiving plcp error rate
+ * @wd_timeout: TX queues watchdog timeout
+ * @temperature_kelvin: temperature report by uCode in kelvin
+ * @max_event_log_size: size of event log buffer size for ucode event logging
+ * @ucode_tracing: support ucode continuous tracing
+ * @sensitivity_calib_by_driver: driver has the capability to perform
+ *	sensitivity calibration operation
+ * @chain_noise_calib_by_driver: driver has the capability to perform
+ *	chain noise calibration operation
+ */
+struct iwl_base_params {
+	int eeprom_size;
+	int num_of_queues;	/* def: HW dependent */
+	int num_of_ampdu_queues;/* def: HW dependent */
+	/* for iwl_legacy_apm_init() */
+	u32 pll_cfg_val;
+	bool set_l0s;
+	bool use_bsm;
+
+	u16 led_compensation;
+	int chain_noise_num_beacons;
+	u8 plcp_delta_threshold;
+	unsigned int wd_timeout;
+	bool temperature_kelvin;
+	u32 max_event_log_size;
+	const bool ucode_tracing;
+	const bool sensitivity_calib_by_driver;
+	const bool chain_noise_calib_by_driver;
+};
+
+/**
+ * struct iwl_cfg
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ *	(.ucode) will be added to filename before loading from disk. The
+ *	filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @scan_antennas: available antenna for scan operation
+ * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
+ *
+ * We enable the driver to be backward compatible wrt API version. The
+ * driver specifies which APIs it supports (with @ucode_api_max being the
+ * highest and @ucode_api_min the lowest). Firmware will only be loaded if
+ * it has a supported API version. The firmware's API version will be
+ * stored in @iwl_priv, enabling the driver to make runtime changes based
+ * on firmware version used.
+ *
+ * For example,
+ * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+ *	Driver interacts with Firmware API version >= 2.
+ * } else {
+ *	Driver interacts with Firmware API version 1.
+ * }
+ *
+ * The ideal usage of this infrastructure is to treat a new ucode API
+ * release as a new hardware revision. That is, through utilizing the
+ * iwl_hcmd_utils_ops etc. we accommodate different command structures
+ * and flows between hardware versions as well as their API
+ * versions.
+ *
+ */
+struct iwl_cfg {
+	/* params specific to an individual device within a device family */
+	const char *name;
+	const char *fw_name_pre;
+	const unsigned int ucode_api_max;
+	const unsigned int ucode_api_min;
+	u8   valid_tx_ant;
+	u8   valid_rx_ant;
+	unsigned int sku;
+	u16  eeprom_ver;
+	u16  eeprom_calib_ver;
+	const struct iwl_ops *ops;
+	/* module based parameters which can be set from modprobe cmd */
+	const struct iwl_mod_params *mod_params;
+	/* params not likely to change within a device family */
+	struct iwl_base_params *base_params;
+	/* params likely to change within a device family */
+	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
+	u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
+	enum iwl_led_mode led_mode;
+};
+
+/***************************
+ *   L i b                 *
+ ***************************/
+
+struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg);
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+		    const struct ieee80211_tx_queue_params *params);
+int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw);
+void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			int hw_decrypt);
+int iwl_legacy_check_rxon_cmd(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx);
+int iwl_legacy_full_rxon_required(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx);
+int iwl_legacy_set_rxon_channel(struct iwl_priv *priv,
+			struct ieee80211_channel *ch,
+			struct iwl_rxon_context *ctx);
+void iwl_legacy_set_flags_for_band(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    enum ieee80211_band band,
+			    struct ieee80211_vif *vif);
+u8 iwl_legacy_get_single_channel_number(struct iwl_priv *priv,
+				  enum ieee80211_band band);
+void iwl_legacy_set_rxon_ht(struct iwl_priv *priv,
+			struct iwl_ht_config *ht_conf);
+bool iwl_legacy_is_ht40_tx_allowed(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_sta_ht_cap *ht_cap);
+void iwl_legacy_connection_init_rx_config(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx);
+void iwl_legacy_set_rate(struct iwl_priv *priv);
+int iwl_legacy_set_decrypted_flag(struct iwl_priv *priv,
+			   struct ieee80211_hdr *hdr,
+			   u32 decrypt_res,
+			   struct ieee80211_rx_status *stats);
+void iwl_legacy_irq_handle_error(struct iwl_priv *priv);
+int iwl_legacy_mac_add_interface(struct ieee80211_hw *hw,
+			  struct ieee80211_vif *vif);
+void iwl_legacy_mac_remove_interface(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif);
+int iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     enum nl80211_iftype newtype, bool newp2p);
+int iwl_legacy_alloc_txq_mem(struct iwl_priv *priv);
+void iwl_legacy_txq_mem(struct iwl_priv *priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv);
+void iwl_legacy_free_traffic_mem(struct iwl_priv *priv);
+void iwl_legacy_reset_traffic_log(struct iwl_priv *priv);
+void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
+				u16 length, struct ieee80211_hdr *header);
+void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
+				u16 length, struct ieee80211_hdr *header);
+const char *iwl_legacy_get_mgmt_string(int cmd);
+const char *iwl_legacy_get_ctrl_string(int cmd);
+void iwl_legacy_clear_traffic_stats(struct iwl_priv *priv);
+void iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
+		      u16 len);
+#else
+static inline int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv)
+{
+	return 0;
+}
+static inline void iwl_legacy_free_traffic_mem(struct iwl_priv *priv)
+{
+}
+static inline void iwl_legacy_reset_traffic_log(struct iwl_priv *priv)
+{
+}
+static inline void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx,
+				    __le16 fc, u16 len)
+{
+}
+#endif
+/*****************************************************
+ * RX handlers.
+ * **************************************************/
+void iwl_legacy_rx_pm_sleep_notif(struct iwl_priv *priv,
+			   struct iwl_rx_mem_buffer *rxb);
+void iwl_legacy_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb);
+void iwl_legacy_rx_reply_error(struct iwl_priv *priv,
+			struct iwl_rx_mem_buffer *rxb);
+
+/*****************************************************
+* RX
+******************************************************/
+void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv);
+void iwl_legacy_cmd_queue_free(struct iwl_priv *priv);
+int iwl_legacy_rx_queue_alloc(struct iwl_priv *priv);
+void iwl_legacy_rx_queue_update_write_ptr(struct iwl_priv *priv,
+				  struct iwl_rx_queue *q);
+int iwl_legacy_rx_queue_space(const struct iwl_rx_queue *q);
+void iwl_legacy_tx_cmd_complete(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+/* Handlers */
+void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
+					  struct iwl_rx_mem_buffer *rxb);
+void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt);
+void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success);
+void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+
+/* TX helpers */
+
+/*****************************************************
+* TX
+******************************************************/
+void iwl_legacy_txq_update_write_ptr(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq);
+int iwl_legacy_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+		      int slots_num, u32 txq_id);
+void iwl_legacy_tx_queue_reset(struct iwl_priv *priv,
+			struct iwl_tx_queue *txq,
+			int slots_num, u32 txq_id);
+void iwl_legacy_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
+void iwl_legacy_tx_queue_free(struct iwl_priv *priv, int txq_id);
+void iwl_legacy_setup_watchdog(struct iwl_priv *priv);
+/*****************************************************
+ * TX power
+ ****************************************************/
+int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
+
+/*******************************************************************************
+ * Rate
+ ******************************************************************************/
+
+u8 iwl_legacy_get_lowest_plcp(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx);
+
+/*******************************************************************************
+ * Scanning
+ ******************************************************************************/
+void iwl_legacy_init_scan_params(struct iwl_priv *priv);
+int iwl_legacy_scan_cancel(struct iwl_priv *priv);
+int iwl_legacy_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
+void iwl_legacy_force_scan_end(struct iwl_priv *priv);
+int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    struct cfg80211_scan_request *req);
+void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
+int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
+			struct ieee80211_mgmt *frame,
+		       const u8 *ta, const u8 *ie, int ie_len, int left);
+void iwl_legacy_setup_rx_scan_handlers(struct iwl_priv *priv);
+u16 iwl_legacy_get_active_dwell_time(struct iwl_priv *priv,
+			      enum ieee80211_band band,
+			      u8 n_probes);
+u16 iwl_legacy_get_passive_dwell_time(struct iwl_priv *priv,
+			       enum ieee80211_band band,
+			       struct ieee80211_vif *vif);
+void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv);
+void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv);
+
+/* For faster active scanning, scan will move to the next channel if fewer than
+ * PLCP_QUIET_THRESH packets are heard on this channel within
+ * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
+ * time if it's a quiet channel (nothing responded to our probe, and there's
+ * no other traffic).
+ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
+#define IWL_ACTIVE_QUIET_TIME       cpu_to_le16(10)  /* msec */
+#define IWL_PLCP_QUIET_THRESH       cpu_to_le16(1)  /* packets */
+
+#define IWL_SCAN_CHECK_WATCHDOG		(HZ * 7)
+
+/*****************************************************
+ *   S e n d i n g     H o s t     C o m m a n d s   *
+ *****************************************************/
+
+const char *iwl_legacy_get_cmd_string(u8 cmd);
+int __must_check iwl_legacy_send_cmd_sync(struct iwl_priv *priv,
+				   struct iwl_host_cmd *cmd);
+int iwl_legacy_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+int __must_check iwl_legacy_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+				  u16 len, const void *data);
+int iwl_legacy_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
+			   const void *data,
+			   void (*callback)(struct iwl_priv *priv,
+					    struct iwl_device_cmd *cmd,
+					    struct iwl_rx_packet *pkt));
+
+int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+
+
+/*****************************************************
+ * PCI						     *
+ *****************************************************/
+
+static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)
+{
+	int pos;
+	u16 pci_lnk_ctl;
+	pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
+	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+	return pci_lnk_ctl;
+}
+
+void iwl_legacy_bg_watchdog(unsigned long data);
+u32 iwl_legacy_usecs_to_beacons(struct iwl_priv *priv,
+					u32 usec, u32 beacon_interval);
+__le32 iwl_legacy_add_beacon_time(struct iwl_priv *priv, u32 base,
+			   u32 addon, u32 beacon_interval);
+
+#ifdef CONFIG_PM
+int iwl_legacy_pci_suspend(struct device *device);
+int iwl_legacy_pci_resume(struct device *device);
+extern const struct dev_pm_ops iwl_legacy_pm_ops;
+
+#define IWL_LEGACY_PM_OPS	(&iwl_legacy_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define IWL_LEGACY_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
+
+/*****************************************************
+*  Error Handling Debugging
+******************************************************/
+void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
+int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
+			   bool full_log, char **buf, bool display);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx);
+#else
+static inline void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
+					   struct iwl_rxon_context *ctx)
+{
+}
+#endif
+
+void iwl_legacy_clear_isr_stats(struct iwl_priv *priv);
+
+/*****************************************************
+*  GEOS
+******************************************************/
+int iwl_legacy_init_geos(struct iwl_priv *priv);
+void iwl_legacy_free_geos(struct iwl_priv *priv);
+
+/*************** DRIVER STATUS FUNCTIONS   *****/
+
+#define STATUS_HCMD_ACTIVE	0	/* host command in progress */
+/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
+#define STATUS_INT_ENABLED	2
+#define STATUS_RF_KILL_HW	3
+#define STATUS_CT_KILL		4
+#define STATUS_INIT		5
+#define STATUS_ALIVE		6
+#define STATUS_READY		7
+#define STATUS_TEMPERATURE	8
+#define STATUS_GEO_CONFIGURED	9
+#define STATUS_EXIT_PENDING	10
+#define STATUS_STATISTICS	12
+#define STATUS_SCANNING		13
+#define STATUS_SCAN_ABORTING	14
+#define STATUS_SCAN_HW		15
+#define STATUS_POWER_PMI	16
+#define STATUS_FW_ERROR		17
+
+
+static inline int iwl_legacy_is_ready(struct iwl_priv *priv)
+{
+	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+	 * set but EXIT_PENDING is not */
+	return test_bit(STATUS_READY, &priv->status) &&
+	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
+	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
+}
+
+static inline int iwl_legacy_is_alive(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_ALIVE, &priv->status);
+}
+
+static inline int iwl_legacy_is_init(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_INIT, &priv->status);
+}
+
+static inline int iwl_legacy_is_rfkill_hw(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
+static inline int iwl_legacy_is_rfkill(struct iwl_priv *priv)
+{
+	return iwl_legacy_is_rfkill_hw(priv);
+}
+
+static inline int iwl_legacy_is_ctkill(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_CT_KILL, &priv->status);
+}
+
+static inline int iwl_legacy_is_ready_rf(struct iwl_priv *priv)
+{
+
+	if (iwl_legacy_is_rfkill(priv))
+		return 0;
+
+	return iwl_legacy_is_ready(priv);
+}
+
+extern void iwl_legacy_send_bt_config(struct iwl_priv *priv);
+extern int iwl_legacy_send_statistics_request(struct iwl_priv *priv,
+				       u8 flags, bool clear);
+void iwl_legacy_apm_stop(struct iwl_priv *priv);
+int iwl_legacy_apm_init(struct iwl_priv *priv);
+
+int iwl_legacy_send_rxon_timing(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx);
+static inline int iwl_legacy_send_rxon_assoc(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx)
+{
+	return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx);
+}
+static inline int iwl_legacy_commit_rxon(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx)
+{
+	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
+}
+static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
+			struct iwl_priv *priv, enum ieee80211_band band)
+{
+	return priv->hw->wiphy->bands[band];
+}
+
+/* mac80211 handlers */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes);
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+				struct ieee80211_tx_info *info,
+				__le16 fc, __le32 *tx_flags);
+
+irqreturn_t iwl_legacy_isr(int irq, void *data);
+
+#endif /* __iwl_legacy_core_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-csr.h b/drivers/net/wireless/iwlegacy/iwl-csr.h
new file mode 100644
index 0000000..668a961
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-csr.h
@@ -0,0 +1,422 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_legacy_csr_h__
+#define __iwl_legacy_csr_h__
+/*
+ * CSR (control and status registers)
+ *
+ * CSR registers are mapped directly into PCI bus space, and are accessible
+ * whenever platform supplies power to device, even when device is in
+ * low power states due to driver-invoked device resets
+ * (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
+ *
+ * Use iwl_write32() and iwl_read32() family to access these registers;
+ * these provide simple PCI bus access, without waking up the MAC.
+ * Do not use iwl_legacy_write_direct32() family for these registers;
+ * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
+ * The MAC (uCode processor, etc.) does not need to be powered up for accessing
+ * the CSR registers.
+ *
+ * NOTE:  Device does need to be awake in order to read this memory
+ *        via CSR_EEPROM register
+ */
+#define CSR_BASE    (0x000)
+
+#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
+#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
+#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
+#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
+#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
+#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
+#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+#define CSR_GP_CNTRL            (CSR_BASE+0x024)
+
+/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
+#define CSR_INT_PERIODIC_REG	(CSR_BASE+0x005)
+
+/*
+ * Hardware revision info
+ * Bit fields:
+ * 31-8:  Reserved
+ *  7-4:  Type of device:  see CSR_HW_REV_TYPE_xxx definitions
+ *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D
+ *  1-0:  "Dash" (-) value, as in A-1, etc.
+ *
+ * NOTE:  Revision step affects calculation of CCK txpower for 4965.
+ * NOTE:  See also CSR_HW_REV_WA_REG (work-around for bug in 4965).
+ */
+#define CSR_HW_REV              (CSR_BASE+0x028)
+
+/*
+ * EEPROM memory reads
+ *
+ * NOTE:  Device must be awake, initialized via apm_ops.init(),
+ *        in order to read.
+ */
+#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
+#define CSR_EEPROM_GP           (CSR_BASE+0x030)
+
+#define CSR_GIO_REG		(CSR_BASE+0x03C)
+#define CSR_GP_UCODE_REG	(CSR_BASE+0x048)
+#define CSR_GP_DRIVER_REG	(CSR_BASE+0x050)
+
+/*
+ * UCODE-DRIVER GP (general purpose) mailbox registers.
+ * SET/CLR registers set/clear bit(s) if "1" is written.
+ */
+#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
+#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
+#define CSR_UCODE_DRV_GP1_CLR   (CSR_BASE+0x05c)
+#define CSR_UCODE_DRV_GP2       (CSR_BASE+0x060)
+
+#define CSR_LED_REG             (CSR_BASE+0x094)
+#define CSR_DRAM_INT_TBL_REG	(CSR_BASE+0x0A0)
+
+/* GIO Chicken Bits (PCI Express bus link power management) */
+#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
+
+/* Analog phase-lock-loop configuration  */
+#define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
+
+/*
+ * CSR Hardware Revision Workaround Register.  Indicates hardware rev;
+ * "step" determines CCK backoff for txpower calculation.  Used for 4965 only.
+ * See also CSR_HW_REV register.
+ * Bit fields:
+ *  3-2:  0 = A, 1 = B, 2 = C, 3 = D step
+ *  1-0:  "Dash" (-) value, as in C-1, etc.
+ */
+#define CSR_HW_REV_WA_REG		(CSR_BASE+0x22C)
+
+#define CSR_DBG_HPET_MEM_REG		(CSR_BASE+0x240)
+#define CSR_DBG_LINK_PWR_MGMT_REG	(CSR_BASE+0x250)
+
+/* Bits for CSR_HW_IF_CONFIG_REG */
+#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R	(0x00000010)
+#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER	(0x00000C00)
+#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI 	(0x00000100)
+#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200)
+
+#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB         (0x00000100)
+#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM         (0x00000200)
+#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC            (0x00000400)
+#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE         (0x00000800)
+#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A    (0x00000000)
+#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B    (0x00001000)
+
+#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A	(0x00080000)
+#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM	(0x00200000)
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY	(0x00400000) /* PCI_OWN_SEM */
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
+#define CSR_HW_IF_CONFIG_REG_PREPARE		  (0x08000000) /* WAKE_ME */
+
+#define CSR_INT_PERIODIC_DIS			(0x00) /* disable periodic int*/
+#define CSR_INT_PERIODIC_ENA			(0xFF) /* 255*32 usec ~ 8 msec*/
+
+/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+ * acknowledged (reset) by host writing "1" to flagged bits. */
+#define CSR_INT_BIT_FH_RX        (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+#define CSR_INT_BIT_HW_ERR       (1 << 29) /* DMA hardware error FH_INT[31] */
+#define CSR_INT_BIT_RX_PERIODIC	 (1 << 28) /* Rx periodic */
+#define CSR_INT_BIT_FH_TX        (1 << 27) /* Tx DMA FH_INT[1:0] */
+#define CSR_INT_BIT_SCD          (1 << 26) /* TXQ pointer advanced */
+#define CSR_INT_BIT_SW_ERR       (1 << 25) /* uCode error */
+#define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
+#define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
+#define CSR_INT_BIT_SW_RX        (1 << 3)  /* Rx, command responses, 3945 */
+#define CSR_INT_BIT_WAKEUP       (1 << 1)  /* NIC controller waking up (pwr mgmt) */
+#define CSR_INT_BIT_ALIVE        (1 << 0)  /* uCode interrupts once it initializes */
+
+#define CSR_INI_SET_MASK	(CSR_INT_BIT_FH_RX   | \
+				 CSR_INT_BIT_HW_ERR  | \
+				 CSR_INT_BIT_FH_TX   | \
+				 CSR_INT_BIT_SW_ERR  | \
+				 CSR_INT_BIT_RF_KILL | \
+				 CSR_INT_BIT_SW_RX   | \
+				 CSR_INT_BIT_WAKEUP  | \
+				 CSR_INT_BIT_ALIVE)
+
+/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+#define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
+#define CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */
+#define CSR39_FH_INT_BIT_RX_CHNL2  (1 << 18) /* Rx channel 2 (3945 only) */
+#define CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */
+#define CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */
+#define CSR39_FH_INT_BIT_TX_CHNL6  (1 << 6)  /* Tx channel 6 (3945 only) */
+#define CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */
+#define CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */
+
+#define CSR39_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
+				 CSR39_FH_INT_BIT_RX_CHNL2 | \
+				 CSR_FH_INT_BIT_RX_CHNL1 | \
+				 CSR_FH_INT_BIT_RX_CHNL0)
+
+
+#define CSR39_FH_INT_TX_MASK	(CSR39_FH_INT_BIT_TX_CHNL6 | \
+				 CSR_FH_INT_BIT_TX_CHNL1 | \
+				 CSR_FH_INT_BIT_TX_CHNL0)
+
+#define CSR49_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
+				 CSR_FH_INT_BIT_RX_CHNL1 | \
+				 CSR_FH_INT_BIT_RX_CHNL0)
+
+#define CSR49_FH_INT_TX_MASK	(CSR_FH_INT_BIT_TX_CHNL1 | \
+				 CSR_FH_INT_BIT_TX_CHNL0)
+
+/* GPIO */
+#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
+#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
+#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC               (0x00000200)
+
+/* RESET */
+#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
+#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
+#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
+#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
+#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
+#define CSR_RESET_LINK_PWR_MGMT_DISABLED             (0x80000000)
+
+/*
+ * GP (general purpose) CONTROL REGISTER
+ * Bit fields:
+ *    27:  HW_RF_KILL_SW
+ *         Indicates state of (platform's) hardware RF-Kill switch
+ * 26-24:  POWER_SAVE_TYPE
+ *         Indicates current power-saving mode:
+ *         000 -- No power saving
+ *         001 -- MAC power-down
+ *         010 -- PHY (radio) power-down
+ *         011 -- Error
+ *   9-6:  SYS_CONFIG
+ *         Indicates current system configuration, reflecting pins on chip
+ *         as forced high/low by device circuit board.
+ *     4:  GOING_TO_SLEEP
+ *         Indicates MAC is entering a power-saving sleep power-down.
+ *         Not a good time to access device-internal resources.
+ *     3:  MAC_ACCESS_REQ
+ *         Host sets this to request and maintain MAC wakeup, to allow host
+ *         access to device-internal resources.  Host must wait for
+ *         MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR
+ *         device registers.
+ *     2:  INIT_DONE
+ *         Host sets this to put device into fully operational D0 power mode.
+ *         Host resets this after SW_RESET to put device into low power mode.
+ *     0:  MAC_CLOCK_READY
+ *         Indicates MAC (ucode processor, etc.) is powered up and can run.
+ *         Internal resources are accessible.
+ *         NOTE:  This does not indicate that the processor is actually running.
+ *         NOTE:  This does not indicate that 4965 or 3945 has completed
+ *                init or post-power-down restore of internal SRAM memory.
+ *                Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that
+ *                SRAM is restored and uCode is in normal operation mode.
+ *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
+ *                do not need to save/restore it.
+ *         NOTE:  After device reset, this bit remains "0" until host sets
+ *                INIT_DONE
+ */
+#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
+#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
+
+#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)
+
+#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
+#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
+
+
+/* EEPROM REG */
+#define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
+#define CSR_EEPROM_REG_BIT_CMD		(0x00000002)
+#define CSR_EEPROM_REG_MSK_ADDR		(0x0000FFFC)
+#define CSR_EEPROM_REG_MSK_DATA		(0xFFFF0000)
+
+/* EEPROM GP */
+#define CSR_EEPROM_GP_VALID_MSK		(0x00000007) /* signature */
+#define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
+#define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K		(0x00000002)
+#define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K		(0x00000004)
+
+/* GP REG */
+#define CSR_GP_REG_POWER_SAVE_STATUS_MSK            (0x03000000) /* bit 24/25 */
+#define CSR_GP_REG_NO_POWER_SAVE            (0x00000000)
+#define CSR_GP_REG_MAC_POWER_SAVE           (0x01000000)
+#define CSR_GP_REG_PHY_POWER_SAVE           (0x02000000)
+#define CSR_GP_REG_POWER_SAVE_ERROR         (0x03000000)
+
+
+/* CSR GIO */
+#define CSR_GIO_REG_VAL_L0S_ENABLED	(0x00000002)
+
+/*
+ * UCODE-DRIVER GP (general purpose) mailbox register 1
+ * Host driver and uCode write and/or read this register to communicate with
+ * each other.
+ * Bit fields:
+ *     4:  UCODE_DISABLE
+ *         Host sets this to request permanent halt of uCode, same as
+ *         sending CARD_STATE command with "halt" bit set.
+ *     3:  CT_KILL_EXIT
+ *         Host sets this to request exit from CT_KILL state, i.e. host thinks
+ *         device temperature is low enough to continue normal operation.
+ *     2:  CMD_BLOCKED
+ *         Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)
+ *         to release uCode to clear all Tx and command queues, enter
+ *         unassociated mode, and power down.
+ *         NOTE:  Some devices also use HBUS_TARG_MBX_C register for this bit.
+ *     1:  SW_BIT_RFKILL
+ *         Host sets this when issuing CARD_STATE command to request
+ *         device sleep.
+ *     0:  MAC_SLEEP
+ *         uCode sets this when preparing a power-saving power-down.
+ *         uCode resets this when power-up is complete and SRAM is sane.
+ *         NOTE:  3945/4965 saves internal SRAM data to host when powering down,
+ *                and must restore this data after powering back up.
+ *                MAC_SLEEP is the best indication that restore is complete.
+ *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
+ *                do not need to save/restore it.
+ */
+#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
+#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
+#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
+#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
+
+/* GIO Chicken Bits (PCI Express bus link power management) */
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
+
+/* LED */
+#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
+#define CSR_LED_REG_TRUN_ON (0x78)
+#define CSR_LED_REG_TRUN_OFF (0x38)
+
+/* ANA_PLL */
+#define CSR39_ANA_PLL_CFG_VAL        (0x01000000)
+
+/* HPET MEM debug */
+#define CSR_DBG_HPET_MEM_REG_VAL	(0xFFFF0000)
+
+/* DRAM INT TABLE */
+#define CSR_DRAM_INT_TBL_ENABLE		(1 << 31)
+#define CSR_DRAM_INIT_TBL_WRAP_CHECK	(1 << 27)
+
+/*
+ * HBUS (Host-side Bus)
+ *
+ * HBUS registers are mapped directly into PCI bus space, but are used
+ * to indirectly access device's internal memory or registers that
+ * may be powered-down.
+ *
+ * Use iwl_legacy_write_direct32()/iwl_legacy_read_direct32() family
+ * for these registers;
+ * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
+ * to make sure the MAC (uCode processor, etc.) is powered up for accessing
+ * internal resources.
+ *
+ * Do not use iwl_write32()/iwl_read32() family to access these registers;
+ * these provide only simple PCI bus access, without waking up the MAC.
+ */
+#define HBUS_BASE	(0x400)
+
+/*
+ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+ * structures, error log, event log, verifying uCode load).
+ * First write to address register, then read from or write to data register
+ * to complete the job.  Once the address register is set up, accesses to
+ * data registers auto-increment the address by one dword.
+ * Bit usage for address registers (read or write):
+ *  0-31:  memory address within device
+ */
+#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
+#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
+#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
+#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
+
+/* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */
+#define HBUS_TARG_MBX_C         (HBUS_BASE+0x030)
+#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
+
+/*
+ * Registers for accessing device's internal peripheral registers
+ * (e.g. SCD, BSM, etc.).  First write to address register,
+ * then read from or write to data register to complete the job.
+ * Bit usage for address registers (read or write):
+ *  0-15:  register address (offset) within device
+ * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)
+ */
+#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
+#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
+#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
+#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
+
+/*
+ * Per-Tx-queue write pointer (index, really!)
+ * Indicates index to next TFD that driver will fill (1 past latest filled).
+ * Bit usage:
+ *  0-7:  queue write index
+ * 11-8:  queue selector
+ */
+#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
+
+#endif /* !__iwl_legacy_csr_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-debug.h b/drivers/net/wireless/iwlegacy/iwl-debug.h
new file mode 100644
index 0000000..ae13112
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-debug.h
@@ -0,0 +1,198 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_debug_h__
+#define __iwl_legacy_debug_h__
+
+struct iwl_priv;
+extern u32 iwlegacy_debug_level;
+
+#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
+#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
+#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
+#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+
+#define iwl_print_hex_error(priv, p, len)				 \
+do {									\
+	print_hex_dump(KERN_ERR, "iwl data: ",				\
+		       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);		\
+} while (0)
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define IWL_DEBUG(__priv, level, fmt, args...)				\
+do {									\
+	if (iwl_legacy_get_debug_level(__priv) & (level))			\
+		dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),		\
+			 "%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
+			__func__ , ## args);				\
+} while (0)
+
+#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)			\
+do {									\
+	if ((iwl_legacy_get_debug_level(__priv) & (level)) && net_ratelimit())	\
+		dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),		\
+			"%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
+			 __func__ , ## args);				\
+} while (0)
+
+#define iwl_print_hex_dump(priv, level, p, len) 			\
+do {									\
+	if (iwl_legacy_get_debug_level(priv) & level)				\
+		print_hex_dump(KERN_DEBUG, "iwl data: ",		\
+			       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);	\
+} while (0)
+
+#else
+#define IWL_DEBUG(__priv, level, fmt, args...)
+#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
+static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+				      const void *p, u32 len)
+{}
+#endif				/* CONFIG_IWLWIFI_LEGACY_DEBUG */
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name);
+void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv);
+#else
+static inline int
+iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
+{
+	return 0;
+}
+static inline void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
+{
+}
+#endif				/* CONFIG_IWLWIFI_LEGACY_DEBUGFS */
+
+/*
+ * To use the debug system:
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of
+ *
+ * #define IWL_DL_xxxx VALUE
+ *
+ * where xxxx should be the name of the classification (for example, WEP).
+ *
+ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
+ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * The active debug levels can be accessed via files
+ *
+ * 	/sys/module/iwl4965/parameters/debug{50}
+ *	/sys/module/iwl3945/parameters/debug
+ * 	/sys/class/net/wlan0/device/debug_level
+ *
+ * when CONFIG_IWLWIFI_LEGACY_DEBUG=y.
+ */
+
+/* 0x0000000F - 0x00000001 */
+#define IWL_DL_INFO		(1 << 0)
+#define IWL_DL_MAC80211		(1 << 1)
+#define IWL_DL_HCMD		(1 << 2)
+#define IWL_DL_STATE		(1 << 3)
+/* 0x000000F0 - 0x00000010 */
+#define IWL_DL_MACDUMP		(1 << 4)
+#define IWL_DL_HCMD_DUMP	(1 << 5)
+#define IWL_DL_EEPROM		(1 << 6)
+#define IWL_DL_RADIO		(1 << 7)
+/* 0x00000F00 - 0x00000100 */
+#define IWL_DL_POWER		(1 << 8)
+#define IWL_DL_TEMP		(1 << 9)
+#define IWL_DL_NOTIF		(1 << 10)
+#define IWL_DL_SCAN		(1 << 11)
+/* 0x0000F000 - 0x00001000 */
+#define IWL_DL_ASSOC		(1 << 12)
+#define IWL_DL_DROP		(1 << 13)
+#define IWL_DL_TXPOWER		(1 << 14)
+#define IWL_DL_AP		(1 << 15)
+/* 0x000F0000 - 0x00010000 */
+#define IWL_DL_FW		(1 << 16)
+#define IWL_DL_RF_KILL		(1 << 17)
+#define IWL_DL_FW_ERRORS	(1 << 18)
+#define IWL_DL_LED		(1 << 19)
+/* 0x00F00000 - 0x00100000 */
+#define IWL_DL_RATE		(1 << 20)
+#define IWL_DL_CALIB		(1 << 21)
+#define IWL_DL_WEP		(1 << 22)
+#define IWL_DL_TX		(1 << 23)
+/* 0x0F000000 - 0x01000000 */
+#define IWL_DL_RX		(1 << 24)
+#define IWL_DL_ISR		(1 << 25)
+#define IWL_DL_HT		(1 << 26)
+#define IWL_DL_IO		(1 << 27)
+/* 0xF0000000 - 0x10000000 */
+#define IWL_DL_11H		(1 << 28)
+#define IWL_DL_STATS		(1 << 29)
+#define IWL_DL_TX_REPLY		(1 << 30)
+#define IWL_DL_QOS		(1 << 31)
+
+#define IWL_DEBUG_INFO(p, f, a...)	IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_MAC80211(p, f, a...)	IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
+#define IWL_DEBUG_MACDUMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a)
+#define IWL_DEBUG_TEMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
+#define IWL_DEBUG_SCAN(p, f, a...)	IWL_DEBUG(p, IWL_DL_SCAN, f, ## a)
+#define IWL_DEBUG_RX(p, f, a...)	IWL_DEBUG(p, IWL_DL_RX, f, ## a)
+#define IWL_DEBUG_TX(p, f, a...)	IWL_DEBUG(p, IWL_DL_TX, f, ## a)
+#define IWL_DEBUG_ISR(p, f, a...)	IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
+#define IWL_DEBUG_LED(p, f, a...)	IWL_DEBUG(p, IWL_DL_LED, f, ## a)
+#define IWL_DEBUG_WEP(p, f, a...)	IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
+#define IWL_DEBUG_HC(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
+#define IWL_DEBUG_HC_DUMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a)
+#define IWL_DEBUG_EEPROM(p, f, a...)	IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
+#define IWL_DEBUG_CALIB(p, f, a...)	IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
+#define IWL_DEBUG_FW(p, f, a...)	IWL_DEBUG(p, IWL_DL_FW, f, ## a)
+#define IWL_DEBUG_RF_KILL(p, f, a...)	IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
+#define IWL_DEBUG_DROP(p, f, a...)	IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_DROP_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_AP(p, f, a...)	IWL_DEBUG(p, IWL_DL_AP, f, ## a)
+#define IWL_DEBUG_TXPOWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_IO(p, f, a...)	IWL_DEBUG(p, IWL_DL_IO, f, ## a)
+#define IWL_DEBUG_RATE(p, f, a...)	IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_RATE_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_NOTIF(p, f, a...)	IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
+#define IWL_DEBUG_ASSOC(p, f, a...)	\
+		IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_HT(p, f, a...)	IWL_DEBUG(p, IWL_DL_HT, f, ## a)
+#define IWL_DEBUG_STATS(p, f, a...)	IWL_DEBUG(p, IWL_DL_STATS, f, ## a)
+#define IWL_DEBUG_STATS_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a)
+#define IWL_DEBUG_TX_REPLY(p, f, a...)	IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \
+		IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_QOS(p, f, a...)	IWL_DEBUG(p, IWL_DL_QOS, f, ## a)
+#define IWL_DEBUG_RADIO(p, f, a...)	IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
+#define IWL_DEBUG_POWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
+#define IWL_DEBUG_11H(p, f, a...)	IWL_DEBUG(p, IWL_DL_11H, f, ## a)
+
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-debugfs.c b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
new file mode 100644
index 0000000..2d32438
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-debugfs.c
@@ -0,0 +1,1467 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#include <linux/ieee80211.h>
+#include <net/mac80211.h>
+
+
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* create and remove of files */
+#define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
+	if (!debugfs_create_file(#name, mode, parent, priv,		\
+			 &iwl_legacy_dbgfs_##name##_ops))		\
+		goto err;						\
+} while (0)
+
+#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\
+	struct dentry *__tmp;						\
+	__tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,		\
+				    parent, ptr);			\
+	if (IS_ERR(__tmp) || !__tmp)					\
+		goto err;						\
+} while (0)
+
+#define DEBUGFS_ADD_X32(name, parent, ptr) do {				\
+	struct dentry *__tmp;						\
+	__tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,		\
+				   parent, ptr);			\
+	if (IS_ERR(__tmp) || !__tmp)					\
+		goto err;						\
+} while (0)
+
+/* file operation */
+#define DEBUGFS_READ_FUNC(name)                                         \
+static ssize_t iwl_legacy_dbgfs_##name##_read(struct file *file,               \
+					char __user *user_buf,          \
+					size_t count, loff_t *ppos);
+
+#define DEBUGFS_WRITE_FUNC(name)                                        \
+static ssize_t iwl_legacy_dbgfs_##name##_write(struct file *file,              \
+					const char __user *user_buf,    \
+					size_t count, loff_t *ppos);
+
+
+static int
+iwl_legacy_dbgfs_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define DEBUGFS_READ_FILE_OPS(name) 				\
+	DEBUGFS_READ_FUNC(name);                                        \
+static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {	\
+	.read = iwl_legacy_dbgfs_##name##_read,				\
+	.open = iwl_legacy_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
+};
+
+#define DEBUGFS_WRITE_FILE_OPS(name) 				\
+	DEBUGFS_WRITE_FUNC(name);                                       \
+static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {	\
+	.write = iwl_legacy_dbgfs_##name##_write,			\
+	.open = iwl_legacy_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
+};
+
+#define DEBUGFS_READ_WRITE_FILE_OPS(name)                           \
+	DEBUGFS_READ_FUNC(name);                                        \
+	DEBUGFS_WRITE_FUNC(name);                                       \
+static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {	\
+	.write = iwl_legacy_dbgfs_##name##_write,			\
+	.read = iwl_legacy_dbgfs_##name##_read,				\
+	.open = iwl_legacy_dbgfs_open_file_generic,			\
+	.llseek = generic_file_llseek,					\
+};
+
+static ssize_t iwl_legacy_dbgfs_tx_statistics_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+
+	int cnt;
+	ssize_t ret;
+	const size_t bufsz = 100 +
+		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_mgmt_string(cnt),
+				 priv->tx_stats.mgmt[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
+	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_ctrl_string(cnt),
+				 priv->tx_stats.ctrl[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+			 priv->tx_stats.data_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+			 priv->tx_stats.data_bytes);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t
+iwl_legacy_dbgfs_clear_traffic_statistics_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	u32 clear_flag;
+	char buf[8];
+	int buf_size;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%x", &clear_flag) != 1)
+		return -EFAULT;
+	iwl_legacy_clear_traffic_stats(priv);
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_rx_statistics_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+	int cnt;
+	ssize_t ret;
+	const size_t bufsz = 100 +
+		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_mgmt_string(cnt),
+				 priv->rx_stats.mgmt[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
+	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_ctrl_string(cnt),
+				 priv->rx_stats.ctrl[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+			 priv->rx_stats.data_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+			 priv->rx_stats.data_bytes);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+#define BYTE1_MASK 0x000000ff;
+#define BYTE2_MASK 0x0000ffff;
+#define BYTE3_MASK 0x00ffffff;
+static ssize_t iwl_legacy_dbgfs_sram_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	u32 val;
+	char *buf;
+	ssize_t ret;
+	int i;
+	int pos = 0;
+	struct iwl_priv *priv = file->private_data;
+	size_t bufsz;
+
+	/* default is to dump the entire data segment */
+	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
+		priv->dbgfs_sram_offset = 0x800000;
+		if (priv->ucode_type == UCODE_INIT)
+			priv->dbgfs_sram_len = priv->ucode_init_data.len;
+		else
+			priv->dbgfs_sram_len = priv->ucode_data.len;
+	}
+	bufsz =  30 + priv->dbgfs_sram_len * sizeof(char) * 10;
+	buf = kmalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
+			priv->dbgfs_sram_len);
+	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
+			priv->dbgfs_sram_offset);
+	for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
+		val = iwl_legacy_read_targ_mem(priv, priv->dbgfs_sram_offset + \
+					priv->dbgfs_sram_len - i);
+		if (i < 4) {
+			switch (i) {
+			case 1:
+				val &= BYTE1_MASK;
+				break;
+			case 2:
+				val &= BYTE2_MASK;
+				break;
+			case 3:
+				val &= BYTE3_MASK;
+				break;
+			}
+		}
+		if (!(i % 16))
+			pos += scnprintf(buf + pos, bufsz - pos, "\n");
+		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_sram_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[64];
+	int buf_size;
+	u32 offset, len;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+
+	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
+		priv->dbgfs_sram_offset = offset;
+		priv->dbgfs_sram_len = len;
+	} else {
+		priv->dbgfs_sram_offset = 0;
+		priv->dbgfs_sram_len = 0;
+	}
+
+	return count;
+}
+
+static ssize_t
+iwl_legacy_dbgfs_stations_read(struct file *file, char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_station_entry *station;
+	int max_sta = priv->hw_params.max_stations;
+	char *buf;
+	int i, j, pos = 0;
+	ssize_t ret;
+	/* Add 30 for initial string */
+	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
+
+	buf = kmalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
+			priv->num_stations);
+
+	for (i = 0; i < max_sta; i++) {
+		station = &priv->stations[i];
+		if (!station->used)
+			continue;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "station %d - addr: %pM, flags: %#x\n",
+				 i, station->sta.sta.addr,
+				 station->sta.station_flags_msk);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"TID\tseq_num\ttxq_id\tframes\ttfds\t");
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"start_idx\tbitmap\t\t\trate_n_flags\n");
+
+		for (j = 0; j < MAX_TID_COUNT; j++) {
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
+				j, station->tid[j].seq_number,
+				station->tid[j].agg.txq_id,
+				station->tid[j].agg.frame_count,
+				station->tid[j].tfds_in_queue,
+				station->tid[j].agg.start_idx,
+				station->tid[j].agg.bitmap,
+				station->tid[j].agg.rate_n_flags);
+
+			if (station->tid[j].agg.wait_for_ba)
+				pos += scnprintf(buf + pos, bufsz - pos,
+						 " - waitforba");
+			pos += scnprintf(buf + pos, bufsz - pos, "\n");
+		}
+
+		pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
+				       char __user *user_buf,
+				       size_t count,
+				       loff_t *ppos)
+{
+	ssize_t ret;
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0, ofs = 0, buf_size = 0;
+	const u8 *ptr;
+	char *buf;
+	u16 eeprom_ver;
+	size_t eeprom_len = priv->cfg->base_params->eeprom_size;
+	buf_size = 4 * eeprom_len + 256;
+
+	if (eeprom_len % 16) {
+		IWL_ERR(priv, "NVM size is not multiple of 16.\n");
+		return -ENODATA;
+	}
+
+	ptr = priv->eeprom;
+	if (!ptr) {
+		IWL_ERR(priv, "Invalid EEPROM memory\n");
+		return -ENOMEM;
+	}
+
+	/* 4 characters for byte 0xYY */
+	buf = kzalloc(buf_size, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+	eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
+	pos += scnprintf(buf + pos, buf_size - pos, "EEPROM "
+			"version: 0x%x\n", eeprom_ver);
+	for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
+		pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
+		hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
+				   buf_size - pos, 0);
+		pos += strlen(buf + pos);
+		if (buf_size - pos > 0)
+			buf[pos++] = '\n';
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+	ssize_t ret = -ENOMEM;
+
+	ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
+					priv, true, &buf, true);
+	if (buf) {
+		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+		kfree(buf);
+	}
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	u32 event_log_flag;
+	char buf[8];
+	int buf_size;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &event_log_flag) != 1)
+		return -EFAULT;
+	if (event_log_flag == 1)
+		priv->cfg->ops->lib->dump_nic_event_log(priv, true,
+							NULL, false);
+
+	return count;
+}
+
+
+
+static ssize_t
+iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	struct ieee80211_channel *channels = NULL;
+	const struct ieee80211_supported_band *supp_band = NULL;
+	int pos = 0, i, bufsz = PAGE_SIZE;
+	char *buf;
+	ssize_t ret;
+
+	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
+	if (supp_band) {
+		channels = supp_band->channels;
+
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Displaying %d channels in 2.4GHz band 802.11bg):\n",
+				supp_band->n_channels);
+
+		for (i = 0; i < supp_band->n_channels; i++)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%d: %ddBm: BSS%s%s, %s.\n",
+				channels[i].hw_value,
+				channels[i].max_power,
+				channels[i].flags & IEEE80211_CHAN_RADAR ?
+				" (IEEE 802.11h required)" : "",
+				((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+				|| (channels[i].flags &
+				IEEE80211_CHAN_RADAR)) ? "" :
+				", IBSS",
+				channels[i].flags &
+				IEEE80211_CHAN_PASSIVE_SCAN ?
+				"passive only" : "active/passive");
+	}
+	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
+	if (supp_band) {
+		channels = supp_band->channels;
+
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Displaying %d channels in 5.2GHz band (802.11a)\n",
+				supp_band->n_channels);
+
+		for (i = 0; i < supp_band->n_channels; i++)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%d: %ddBm: BSS%s%s, %s.\n",
+				channels[i].hw_value,
+				channels[i].max_power,
+				channels[i].flags & IEEE80211_CHAN_RADAR ?
+				" (IEEE 802.11h required)" : "",
+				((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+				|| (channels[i].flags &
+				IEEE80211_CHAN_RADAR)) ? "" :
+				", IBSS",
+				channels[i].flags &
+				IEEE80211_CHAN_PASSIVE_SCAN ?
+				"passive only" : "active/passive");
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_status_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char buf[512];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
+		test_bit(STATUS_HCMD_ACTIVE, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
+		test_bit(STATUS_INT_ENABLED, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
+		test_bit(STATUS_CT_KILL, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
+		test_bit(STATUS_INIT, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
+		test_bit(STATUS_ALIVE, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
+		test_bit(STATUS_READY, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
+		test_bit(STATUS_TEMPERATURE, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
+		test_bit(STATUS_GEO_CONFIGURED, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
+		test_bit(STATUS_EXIT_PENDING, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
+		test_bit(STATUS_STATISTICS, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
+		test_bit(STATUS_SCANNING, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
+		test_bit(STATUS_SCAN_ABORTING, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
+		test_bit(STATUS_SCAN_HW, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
+		test_bit(STATUS_POWER_PMI, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
+		test_bit(STATUS_FW_ERROR, &priv->status));
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_interrupt_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	int cnt = 0;
+	char *buf;
+	int bufsz = 24 * 64; /* 24 items * 64 char per item */
+	ssize_t ret;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"Interrupt Statistics Report:\n");
+
+	pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n",
+		priv->isr_stats.hw);
+	pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n",
+		priv->isr_stats.sw);
+	if (priv->isr_stats.sw || priv->isr_stats.hw) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+			"\tLast Restarting Code:  0x%X\n",
+			priv->isr_stats.err_code);
+	}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n",
+		priv->isr_stats.sch);
+	pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n",
+		priv->isr_stats.alive);
+#endif
+	pos += scnprintf(buf + pos, bufsz - pos,
+		"HW RF KILL switch toggled:\t %u\n",
+		priv->isr_stats.rfkill);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n",
+		priv->isr_stats.ctkill);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n",
+		priv->isr_stats.wakeup);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+		"Rx command responses:\t\t %u\n",
+		priv->isr_stats.rx);
+	for (cnt = 0; cnt < REPLY_MAX; cnt++) {
+		if (priv->isr_stats.rx_handlers[cnt] > 0)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"\tRx handler[%36s]:\t\t %u\n",
+				iwl_legacy_get_cmd_string(cnt),
+				priv->isr_stats.rx_handlers[cnt]);
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n",
+		priv->isr_stats.tx);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n",
+		priv->isr_stats.unhandled);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_interrupt_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	u32 reset_flag;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%x", &reset_flag) != 1)
+		return -EFAULT;
+	if (reset_flag == 0)
+		iwl_legacy_clear_isr_stats(priv);
+
+	return count;
+}
+
+static ssize_t
+iwl_legacy_dbgfs_qos_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_rxon_context *ctx;
+	int pos = 0, i;
+	char buf[256 * NUM_IWL_RXON_CTX];
+	const size_t bufsz = sizeof(buf);
+
+	for_each_context(priv, ctx) {
+		pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
+				 ctx->ctxid);
+		for (i = 0; i < AC_NUM; i++) {
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"\tcw_min\tcw_max\taifsn\ttxop\n");
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"AC[%d]\t%u\t%u\t%u\t%u\n", i,
+				ctx->qos_data.def_qos_parm.ac[i].cw_min,
+				ctx->qos_data.def_qos_parm.ac[i].cw_max,
+				ctx->qos_data.def_qos_parm.ac[i].aifsn,
+				ctx->qos_data.def_qos_parm.ac[i].edca_txop);
+		}
+		pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	}
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_disable_ht40_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int ht40;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &ht40) != 1)
+		return -EFAULT;
+	if (!iwl_legacy_is_any_associated(priv))
+		priv->disable_ht40 = ht40 ? true : false;
+	else {
+		IWL_ERR(priv, "Sta associated with AP - "
+			"Change to 40MHz channel support is not allowed\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[100];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"11n 40MHz Mode: %s\n",
+			priv->disable_ht40 ? "Disabled" : "Enabled");
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(sram);
+DEBUGFS_READ_WRITE_FILE_OPS(log_event);
+DEBUGFS_READ_FILE_OPS(nvm);
+DEBUGFS_READ_FILE_OPS(stations);
+DEBUGFS_READ_FILE_OPS(channels);
+DEBUGFS_READ_FILE_OPS(status);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(qos);
+DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
+
+static ssize_t iwl_legacy_dbgfs_traffic_log_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0, ofs = 0;
+	int cnt = 0, entry;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	char *buf;
+	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
+		(priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
+	const u8 *ptr;
+	ssize_t ret;
+
+	if (!priv->txq) {
+		IWL_ERR(priv, "txq not ready\n");
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate buffer\n");
+		return -ENOMEM;
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
+	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+		txq = &priv->txq[cnt];
+		q = &txq->q;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"q[%d]: read_ptr: %u, write_ptr: %u\n",
+				cnt, q->read_ptr, q->write_ptr);
+	}
+	if (priv->tx_traffic && (iwlegacy_debug_level & IWL_DL_TX)) {
+		ptr = priv->tx_traffic;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx);
+		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+			     entry++,  ofs += 16) {
+				pos += scnprintf(buf + pos, bufsz - pos,
+						"0x%.4x ", ofs);
+				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+						   buf + pos, bufsz - pos, 0);
+				pos += strlen(buf + pos);
+				if (bufsz - pos > 0)
+					buf[pos++] = '\n';
+			}
+		}
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"read: %u, write: %u\n",
+			 rxq->read, rxq->write);
+
+	if (priv->rx_traffic && (iwlegacy_debug_level & IWL_DL_RX)) {
+		ptr = priv->rx_traffic;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx);
+		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+			     entry++,  ofs += 16) {
+				pos += scnprintf(buf + pos, bufsz - pos,
+						"0x%.4x ", ofs);
+				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+						   buf + pos, bufsz - pos, 0);
+				pos += strlen(buf + pos);
+				if (bufsz - pos > 0)
+					buf[pos++] = '\n';
+			}
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_traffic_log_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int traffic_log;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &traffic_log) != 1)
+		return -EFAULT;
+	if (traffic_log == 0)
+		iwl_legacy_reset_traffic_log(priv);
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_tx_queue_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	char *buf;
+	int pos = 0;
+	int cnt;
+	int ret;
+	const size_t bufsz = sizeof(char) * 64 *
+				priv->cfg->base_params->num_of_queues;
+
+	if (!priv->txq) {
+		IWL_ERR(priv, "txq not ready\n");
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+		txq = &priv->txq[cnt];
+		q = &txq->q;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"hwq %.2d: read=%u write=%u stop=%d"
+				" swq_id=%#.2x (ac %d/hwq %d)\n",
+				cnt, q->read_ptr, q->write_ptr,
+				!!test_bit(cnt, priv->queue_stopped),
+				txq->swq_id, txq->swq_id & 3,
+				(txq->swq_id >> 2) & 0x1f);
+		if (cnt >= 4)
+			continue;
+		/* for the ACs, display the stop count too */
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"        stop-count: %d\n",
+				atomic_read(&priv->queue_stop_count[cnt]));
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_rx_queue_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	char buf[256];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
+						rxq->read);
+	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
+						rxq->write);
+	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+						rxq->free_count);
+	if (rxq->rb_stts) {
+		pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
+	} else {
+		pos += scnprintf(buf + pos, bufsz - pos,
+					"closed_rb_num: Not Allocated\n");
+	}
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_rx_stats_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
+			user_buf, count, ppos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_tx_stats_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
+			user_buf, count, ppos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_general_stats_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
+			user_buf, count, ppos);
+}
+
+static ssize_t iwl_legacy_dbgfs_sensitivity_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	int cnt = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
+	ssize_t ret;
+	struct iwl_sensitivity_data *data;
+
+	data = &priv->sensitivity_data;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
+			data->auto_corr_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"auto_corr_ofdm_mrc:\t\t %u\n",
+			data->auto_corr_ofdm_mrc);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
+			data->auto_corr_ofdm_x1);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"auto_corr_ofdm_mrc_x1:\t\t %u\n",
+			data->auto_corr_ofdm_mrc_x1);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
+			data->auto_corr_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
+			data->auto_corr_cck_mrc);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"last_bad_plcp_cnt_ofdm:\t\t %u\n",
+			data->last_bad_plcp_cnt_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
+			data->last_fa_cnt_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"last_bad_plcp_cnt_cck:\t\t %u\n",
+			data->last_bad_plcp_cnt_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
+			data->last_fa_cnt_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
+			data->nrg_curr_state);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
+			data->nrg_prev_state);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
+	for (cnt = 0; cnt < 10; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->nrg_value[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
+	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->nrg_silence_rssi[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
+			data->nrg_silence_ref);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
+			data->nrg_energy_idx);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
+			data->nrg_silence_idx);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
+			data->nrg_th_cck);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"nrg_auto_corr_silence_diff:\t %u\n",
+			data->nrg_auto_corr_silence_diff);
+	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
+			data->num_in_cck_no_fa);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
+			data->nrg_th_ofdm);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+
+static ssize_t iwl_legacy_dbgfs_chain_noise_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	int cnt = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
+	ssize_t ret;
+	struct iwl_chain_noise_data *data;
+
+	data = &priv->chain_noise_data;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
+			data->active_chains);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
+			data->chain_noise_a);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
+			data->chain_noise_b);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
+			data->chain_noise_c);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
+			data->chain_signal_a);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
+			data->chain_signal_b);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
+			data->chain_signal_c);
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
+			data->beacon_count);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
+	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->disconn_array[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
+	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->delta_gain_code[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
+			data->radio_write);
+	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
+			data->state);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_power_save_status_read(struct file *file,
+						    char __user *user_buf,
+						    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[60];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+	u32 pwrsave_status;
+
+	pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
+			CSR_GP_REG_POWER_SAVE_STATUS_MSK;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
+	pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
+		(pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
+		(pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
+		(pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
+		"error");
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int clear;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &clear) != 1)
+		return -EFAULT;
+
+	/* make request to uCode to retrieve statistics information */
+	mutex_lock(&priv->mutex);
+	iwl_legacy_send_statistics_request(priv, CMD_SYNC, true);
+	mutex_unlock(&priv->mutex);
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char buf[128];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
+			priv->event_log.ucode_trace ? "On" : "Off");
+	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
+			priv->event_log.non_wraps_count);
+	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
+			priv->event_log.wraps_once_count);
+	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
+			priv->event_log.wraps_more_count);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int trace;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &trace) != 1)
+		return -EFAULT;
+
+	if (trace) {
+		priv->event_log.ucode_trace = true;
+		/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
+		mod_timer(&priv->ucode_trace,
+			jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
+	} else {
+		priv->event_log.ucode_trace = false;
+		del_timer_sync(&priv->ucode_trace);
+	}
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int len = 0;
+	char buf[20];
+
+	len = sprintf(buf, "0x%04X\n",
+		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_legacy_dbgfs_rxon_filter_flags_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int len = 0;
+	char buf[20];
+
+	len = sprintf(buf, "0x%04X\n",
+	le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_legacy_dbgfs_fh_reg_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+	ssize_t ret = -EFAULT;
+
+	if (priv->cfg->ops->lib->dump_fh) {
+		ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
+		if (buf) {
+			ret = simple_read_from_buffer(user_buf,
+						      count, ppos, buf, pos);
+			kfree(buf);
+		}
+	}
+
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_missed_beacon_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char buf[12];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
+			priv->missed_beacon_threshold);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
+					 const char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int missed;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &missed) != 1)
+		return -EINVAL;
+
+	if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
+	    missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
+		priv->missed_beacon_threshold =
+			IWL_MISSED_BEACON_THRESHOLD_DEF;
+	else
+		priv->missed_beacon_threshold = missed;
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char buf[12];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
+			priv->cfg->base_params->plcp_delta_threshold);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int plcp;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &plcp) != 1)
+		return -EINVAL;
+	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
+		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
+		priv->cfg->base_params->plcp_delta_threshold =
+			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
+	else
+		priv->cfg->base_params->plcp_delta_threshold = plcp;
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int i, pos = 0;
+	char buf[300];
+	const size_t bufsz = sizeof(buf);
+	struct iwl_force_reset *force_reset;
+
+	for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
+		force_reset = &priv->force_reset[i];
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Force reset method %d\n", i);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\tnumber of reset request: %d\n",
+				force_reset->reset_request_count);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\tnumber of reset request success: %d\n",
+				force_reset->reset_success_count);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\tnumber of reset request reject: %d\n",
+				force_reset->reset_reject_count);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\treset duration: %lu\n",
+				force_reset->reset_duration);
+	}
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int reset, ret;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &reset) != 1)
+		return -EINVAL;
+	switch (reset) {
+	case IWL_RF_RESET:
+	case IWL_FW_RESET:
+		ret = iwl_legacy_force_reset(priv, reset, true);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return ret ? ret : count;
+}
+
+static ssize_t iwl_legacy_dbgfs_wd_timeout_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char buf[8];
+	int buf_size;
+	int timeout;
+
+	memset(buf, 0, sizeof(buf));
+	buf_size = min(count, sizeof(buf) -  1);
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	if (sscanf(buf, "%d", &timeout) != 1)
+		return -EINVAL;
+	if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
+		timeout = IWL_DEF_WD_TIMEOUT;
+
+	priv->cfg->base_params->wd_timeout = timeout;
+	iwl_legacy_setup_watchdog(priv);
+	return count;
+}
+
+DEBUGFS_READ_FILE_OPS(rx_statistics);
+DEBUGFS_READ_FILE_OPS(tx_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_general_stats);
+DEBUGFS_READ_FILE_OPS(sensitivity);
+DEBUGFS_READ_FILE_OPS(chain_noise);
+DEBUGFS_READ_FILE_OPS(power_save_status);
+DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
+DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
+DEBUGFS_READ_FILE_OPS(fh_reg);
+DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
+DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
+DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
+DEBUGFS_READ_FILE_OPS(rxon_flags);
+DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
+DEBUGFS_WRITE_FILE_OPS(wd_timeout);
+
+/*
+ * Create the debugfs files and directories
+ *
+ */
+int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
+{
+	struct dentry *phyd = priv->hw->wiphy->debugfsdir;
+	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
+
+	dir_drv = debugfs_create_dir(name, phyd);
+	if (!dir_drv)
+		return -ENOMEM;
+
+	priv->debugfs_dir = dir_drv;
+
+	dir_data = debugfs_create_dir("data", dir_drv);
+	if (!dir_data)
+		goto err;
+	dir_rf = debugfs_create_dir("rf", dir_drv);
+	if (!dir_rf)
+		goto err;
+	dir_debug = debugfs_create_dir("debug", dir_drv);
+	if (!dir_debug)
+		goto err;
+
+	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
+
+	if (priv->cfg->base_params->sensitivity_calib_by_driver)
+		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
+	if (priv->cfg->base_params->chain_noise_calib_by_driver)
+		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
+	if (priv->cfg->base_params->ucode_tracing)
+		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
+	if (priv->cfg->base_params->sensitivity_calib_by_driver)
+		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
+				 &priv->disable_sens_cal);
+	if (priv->cfg->base_params->chain_noise_calib_by_driver)
+		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
+				 &priv->disable_chain_noise_cal);
+	DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
+				&priv->disable_tx_power_cal);
+	return 0;
+
+err:
+	IWL_ERR(priv, "Can't create the debugfs directory\n");
+	iwl_legacy_dbgfs_unregister(priv);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(iwl_legacy_dbgfs_register);
+
+/**
+ * Remove the debugfs files and directories
+ *
+ */
+void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
+{
+	if (!priv->debugfs_dir)
+		return;
+
+	debugfs_remove_recursive(priv->debugfs_dir);
+	priv->debugfs_dir = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_dbgfs_unregister);
diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
new file mode 100644
index 0000000..9ee849d
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
@@ -0,0 +1,1426 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-dev.h) for driver implementation definitions.
+ * Please use iwl-commands.h for uCode API definitions.
+ * Please use iwl-4965-hw.h for hardware-related definitions.
+ */
+
+#ifndef __iwl_legacy_dev_h__
+#define __iwl_legacy_dev_h__
+
+#include <linux/pci.h> /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/wait.h>
+#include <net/ieee80211_radiotap.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-fh.h"
+#include "iwl-debug.h"
+#include "iwl-4965-hw.h"
+#include "iwl-3945-hw.h"
+#include "iwl-led.h"
+#include "iwl-power.h"
+#include "iwl-legacy-rs.h"
+
+struct iwl_tx_queue;
+
+/* CT-KILL constants */
+#define CT_KILL_THRESHOLD_LEGACY   110 /* in Celsius */
+
+/* Default noise level to report when noise measurement is not available.
+ *   This may be because we're:
+ *   1)  Not associated (4965, no beacon statistics being sent to driver)
+ *   2)  Scanning (noise measurement does not apply to associated channel)
+ *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Also, -127 works better than 0 when averaging frames with/without
+ *   noise info (e.g. averaging might be done in app); measured dBm values are
+ *   always negative ... using a negative value as the default keeps all
+ *   averages within an s8's (used in some apps) range of negative values. */
+#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ *   a value of 0 means RTS on all data/management packets
+ *   a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ *   than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD     2347U
+#define MIN_RTS_THRESHOLD         0U
+#define MAX_RTS_THRESHOLD         2347U
+#define MAX_MSDU_SIZE		  2304U
+#define MAX_MPDU_SIZE		  2346U
+#define DEFAULT_BEACON_INTERVAL   100U
+#define	DEFAULT_SHORT_RETRY_LIMIT 7U
+#define	DEFAULT_LONG_RETRY_LIMIT  4U
+
+struct iwl_rx_mem_buffer {
+	dma_addr_t page_dma;
+	struct page *page;
+	struct list_head list;
+};
+
+#define rxb_addr(r) page_address(r->page)
+
+/* defined below */
+struct iwl_device_cmd;
+
+struct iwl_cmd_meta {
+	/* only for SYNC commands, iff the reply skb is wanted */
+	struct iwl_host_cmd *source;
+	/*
+	 * only for ASYNC commands
+	 * (which is somewhat stupid -- look at iwl-sta.c for instance
+	 * which duplicates a bunch of code because the callback isn't
+	 * invoked for SYNC commands, if it were and its result passed
+	 * through it would be simpler...)
+	 */
+	void (*callback)(struct iwl_priv *priv,
+			 struct iwl_device_cmd *cmd,
+			 struct iwl_rx_packet *pkt);
+
+	/* The CMD_SIZE_HUGE flag bit indicates that the command
+	 * structure is stored at the end of the shared queue memory. */
+	u32 flags;
+
+	DEFINE_DMA_UNMAP_ADDR(mapping);
+	DEFINE_DMA_UNMAP_LEN(len);
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct iwl_queue {
+	int n_bd;              /* number of BDs in this queue */
+	int write_ptr;       /* 1-st empty entry (index) host_w*/
+	int read_ptr;         /* last used entry (index) host_r*/
+	/* use for monitoring and recovering the stuck queue */
+	dma_addr_t dma_addr;   /* physical addr for BD's */
+	int n_window;	       /* safe queue window */
+	u32 id;
+	int low_mark;	       /* low watermark, resume queue if free
+				* space more than this */
+	int high_mark;         /* high watermark, stop queue if free
+				* space less than this */
+} __packed;
+
+/* One for each TFD */
+struct iwl_tx_info {
+	struct sk_buff *skb;
+	struct iwl_rxon_context *ctx;
+};
+
+/**
+ * struct iwl_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @time_stamp: time (in jiffies) of last read_ptr change
+ * @need_update: indicates need to update read/write index
+ * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+struct iwl_tx_queue {
+	struct iwl_queue q;
+	void *tfds;
+	struct iwl_device_cmd **cmd;
+	struct iwl_cmd_meta *meta;
+	struct iwl_tx_info *txb;
+	unsigned long time_stamp;
+	u8 need_update;
+	u8 sched_retry;
+	u8 active;
+	u8 swq_id;
+};
+
+#define IWL_NUM_SCAN_RATES         (2)
+
+struct iwl4965_channel_tgd_info {
+	u8 type;
+	s8 max_power;
+};
+
+struct iwl4965_channel_tgh_info {
+	s64 last_radar_time;
+};
+
+#define IWL4965_MAX_RATE (33)
+
+struct iwl3945_clip_group {
+	/* maximum power level to prevent clipping for each rate, derived by
+	 *   us from this band's saturation power in EEPROM */
+	const s8 clip_powers[IWL_MAX_RATES];
+};
+
+/* current Tx power values to use, one for each rate for each channel.
+ * requested power is limited by:
+ * -- regulatory EEPROM limits for this channel
+ * -- hardware capabilities (clip-powers)
+ * -- spectrum management
+ * -- user preference (e.g. iwconfig)
+ * when requested power is set, base power index must also be set. */
+struct iwl3945_channel_power_info {
+	struct iwl3945_tx_power tpc;	/* actual radio and DSP gain settings */
+	s8 power_table_index;	/* actual (compenst'd) index into gain table */
+	s8 base_power_index;	/* gain index for power at factory temp. */
+	s8 requested_power;	/* power (dBm) requested for this chnl/rate */
+};
+
+/* current scan Tx power values to use, one for each scan rate for each
+ * channel. */
+struct iwl3945_scan_power_info {
+	struct iwl3945_tx_power tpc;	/* actual radio and DSP gain settings */
+	s8 power_table_index;	/* actual (compenst'd) index into gain table */
+	s8 requested_power;	/* scan pwr (dBm) requested for chnl/rate */
+};
+
+/*
+ * One for each channel, holds all channel setup data
+ * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
+ *     with one another!
+ */
+struct iwl_channel_info {
+	struct iwl4965_channel_tgd_info tgd;
+	struct iwl4965_channel_tgh_info tgh;
+	struct iwl_eeprom_channel eeprom;	/* EEPROM regulatory limit */
+	struct iwl_eeprom_channel ht40_eeprom;	/* EEPROM regulatory limit for
+						 * HT40 channel */
+
+	u8 channel;	  /* channel number */
+	u8 flags;	  /* flags copied from EEPROM */
+	s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
+	s8 curr_txpow;	  /* (dBm) regulatory/spectrum/user (not h/w) limit */
+	s8 min_power;	  /* always 0 */
+	s8 scan_power;	  /* (dBm) regul. eeprom, direct scans, any rate */
+
+	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
+	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
+	enum ieee80211_band band;
+
+	/* HT40 channel info */
+	s8 ht40_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */
+	u8 ht40_flags;		/* flags copied from EEPROM */
+	u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
+
+	/* Radio/DSP gain settings for each "normal" data Tx rate.
+	 * These include, in addition to RF and DSP gain, a few fields for
+	 *   remembering/modifying gain settings (indexes). */
+	struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE];
+
+	/* Radio/DSP gain settings for each scan rate, for directed scans. */
+	struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
+};
+
+#define IWL_TX_FIFO_BK		0	/* shared */
+#define IWL_TX_FIFO_BE		1
+#define IWL_TX_FIFO_VI		2	/* shared */
+#define IWL_TX_FIFO_VO		3
+#define IWL_TX_FIFO_UNUSED	-1
+
+/* Minimum number of queues. MAX_NUM is defined in hw specific files.
+ * Set the minimum to accommodate the 4 standard TX queues, 1 command
+ * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
+#define IWL_MIN_NUM_QUEUES	10
+
+#define IWL_DEFAULT_CMD_QUEUE_NUM	4
+
+#define IEEE80211_DATA_LEN              2304
+#define IEEE80211_4ADDR_LEN             30
+#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct iwl_frame {
+	union {
+		struct ieee80211_hdr frame;
+		struct iwl_tx_beacon_cmd beacon;
+		u8 raw[IEEE80211_FRAME_LEN];
+		u8 cmd[360];
+	} u;
+	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,
+	CMD_NO_SKB = 0,
+	CMD_SIZE_HUGE = (1 << 0),
+	CMD_ASYNC = (1 << 1),
+	CMD_WANT_SKB = (1 << 2),
+};
+
+#define DEF_CMD_PAYLOAD_SIZE 320
+
+/**
+ * struct iwl_device_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for a scan command
+ * (which is relatively huge; space is allocated separately).
+ */
+struct iwl_device_cmd {
+	struct iwl_cmd_header hdr;	/* uCode API */
+	union {
+		u32 flags;
+		u8 val8;
+		u16 val16;
+		u32 val32;
+		struct iwl_tx_cmd tx;
+		u8 payload[DEF_CMD_PAYLOAD_SIZE];
+	} __packed cmd;
+} __packed;
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+
+
+struct iwl_host_cmd {
+	const void *data;
+	unsigned long reply_page;
+	void (*callback)(struct iwl_priv *priv,
+			 struct iwl_device_cmd *cmd,
+			 struct iwl_rx_packet *pkt);
+	u32 flags;
+	u16 len;
+	u8 id;
+};
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+/**
+ * struct iwl_rx_queue - Rx queue
+ * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
+ * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
+ * @read: Shared index to newest available Rx buffer
+ * @write: Shared index to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write index
+ * @rb_stts: driver's pointer to receive buffer status
+ * @rb_stts_dma: bus address of receive buffer status
+ *
+ * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
+ */
+struct iwl_rx_queue {
+	__le32 *bd;
+	dma_addr_t bd_dma;
+	struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+	struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+	u32 read;
+	u32 write;
+	u32 free_count;
+	u32 write_actual;
+	struct list_head rx_free;
+	struct list_head rx_used;
+	int need_update;
+	struct iwl_rb_status *rb_stts;
+	dma_addr_t rb_stts_dma;
+	spinlock_t lock;
+};
+
+#define IWL_SUPPORTED_RATES_IE_LEN         8
+
+#define MAX_TID_COUNT        9
+
+#define IWL_INVALID_RATE     0xFF
+#define IWL_INVALID_VALUE    -1
+
+/**
+ * struct iwl_ht_agg -- aggregation status while waiting for block-ack
+ * @txq_id: Tx queue used for Tx attempt
+ * @frame_count: # frames attempted by Tx command
+ * @wait_for_ba: Expect block-ack before next Tx reply
+ * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window
+ * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window
+ * @bitmap1: High order, one bit for each frame pending ACK in Tx window
+ * @rate_n_flags: Rate at which Tx was attempted
+ *
+ * If REPLY_TX indicates that aggregation was attempted, driver must wait
+ * for block ack (REPLY_COMPRESSED_BA).  This struct stores tx reply info
+ * until block ack arrives.
+ */
+struct iwl_ht_agg {
+	u16 txq_id;
+	u16 frame_count;
+	u16 wait_for_ba;
+	u16 start_idx;
+	u64 bitmap;
+	u32 rate_n_flags;
+#define IWL_AGG_OFF 0
+#define IWL_AGG_ON 1
+#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
+#define IWL_EMPTYING_HW_QUEUE_DELBA 3
+	u8 state;
+};
+
+
+struct iwl_tid_data {
+	u16 seq_number; /* 4965 only */
+	u16 tfds_in_queue;
+	struct iwl_ht_agg agg;
+};
+
+struct iwl_hw_key {
+	u32 cipher;
+	int keylen;
+	u8 keyidx;
+	u8 key[32];
+};
+
+union iwl_ht_rate_supp {
+	u16 rates;
+	struct {
+		u8 siso_rate;
+		u8 mimo_rate;
+	};
+};
+
+#define CFG_HT_RX_AMPDU_FACTOR_8K   (0x0)
+#define CFG_HT_RX_AMPDU_FACTOR_16K  (0x1)
+#define CFG_HT_RX_AMPDU_FACTOR_32K  (0x2)
+#define CFG_HT_RX_AMPDU_FACTOR_64K  (0x3)
+#define CFG_HT_RX_AMPDU_FACTOR_DEF  CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MAX  CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MIN  CFG_HT_RX_AMPDU_FACTOR_8K
+
+/*
+ * Maximal MPDU density for TX aggregation
+ * 4 - 2us density
+ * 5 - 4us density
+ * 6 - 8us density
+ * 7 - 16us density
+ */
+#define CFG_HT_MPDU_DENSITY_2USEC   (0x4)
+#define CFG_HT_MPDU_DENSITY_4USEC   (0x5)
+#define CFG_HT_MPDU_DENSITY_8USEC   (0x6)
+#define CFG_HT_MPDU_DENSITY_16USEC  (0x7)
+#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
+#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
+#define CFG_HT_MPDU_DENSITY_MIN     (0x1)
+
+struct iwl_ht_config {
+	bool single_chain_sufficient;
+	enum ieee80211_smps_mode smps; /* current smps mode */
+};
+
+/* QoS structures */
+struct iwl_qos_info {
+	int qos_active;
+	struct iwl_qosparam_cmd def_qos_parm;
+};
+
+/*
+ * Structure should be accessed with sta_lock held. When station addition
+ * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only
+ * the commands (iwl_legacy_addsta_cmd and iwl_link_quality_cmd) without
+ * sta_lock held.
+ */
+struct iwl_station_entry {
+	struct iwl_legacy_addsta_cmd sta;
+	struct iwl_tid_data tid[MAX_TID_COUNT];
+	u8 used, ctxid;
+	struct iwl_hw_key keyinfo;
+	struct iwl_link_quality_cmd *lq;
+};
+
+struct iwl_station_priv_common {
+	struct iwl_rxon_context *ctx;
+	u8 sta_id;
+};
+
+/*
+ * iwl_station_priv: Driver's private station information
+ *
+ * When mac80211 creates a station it reserves some space (hw->sta_data_size)
+ * in the structure for use by driver. This structure is places in that
+ * space.
+ *
+ * The common struct MUST be first because it is shared between
+ * 3945 and 4965!
+ */
+struct iwl_station_priv {
+	struct iwl_station_priv_common common;
+	struct iwl_lq_sta lq_sta;
+	atomic_t pending_frames;
+	bool client;
+	bool asleep;
+};
+
+/**
+ * struct iwl_vif_priv - driver's private per-interface information
+ *
+ * When mac80211 allocates a virtual interface, it can allocate
+ * space for us to put data into.
+ */
+struct iwl_vif_priv {
+	struct iwl_rxon_context *ctx;
+	u8 ibss_bssid_sta_id;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+	void *v_addr;		/* access by driver */
+	dma_addr_t p_addr;	/* access by card's busmaster DMA */
+	u32 len;		/* bytes */
+};
+
+/* uCode file layout */
+struct iwl_ucode_header {
+	__le32 ver;	/* major/minor/API/serial */
+	struct {
+		__le32 inst_size;	/* bytes of runtime code */
+		__le32 data_size;	/* bytes of runtime data */
+		__le32 init_size;	/* bytes of init code */
+		__le32 init_data_size;	/* bytes of init data */
+		__le32 boot_size;	/* bytes of bootstrap code */
+		u8 data[0];		/* in same order as sizes */
+	} v1;
+};
+
+struct iwl4965_ibss_seq {
+	u8 mac[ETH_ALEN];
+	u16 seq_num;
+	u16 frag_num;
+	unsigned long packet_time;
+	struct list_head list;
+};
+
+struct iwl_sensitivity_ranges {
+	u16 min_nrg_cck;
+	u16 max_nrg_cck;
+
+	u16 nrg_th_cck;
+	u16 nrg_th_ofdm;
+
+	u16 auto_corr_min_ofdm;
+	u16 auto_corr_min_ofdm_mrc;
+	u16 auto_corr_min_ofdm_x1;
+	u16 auto_corr_min_ofdm_mrc_x1;
+
+	u16 auto_corr_max_ofdm;
+	u16 auto_corr_max_ofdm_mrc;
+	u16 auto_corr_max_ofdm_x1;
+	u16 auto_corr_max_ofdm_mrc_x1;
+
+	u16 auto_corr_max_cck;
+	u16 auto_corr_max_cck_mrc;
+	u16 auto_corr_min_cck;
+	u16 auto_corr_min_cck_mrc;
+
+	u16 barker_corr_th_min;
+	u16 barker_corr_th_min_mrc;
+	u16 nrg_th_cca;
+};
+
+
+#define KELVIN_TO_CELSIUS(x) ((x)-273)
+#define CELSIUS_TO_KELVIN(x) ((x)+273)
+
+
+/**
+ * struct iwl_hw_params
+ * @max_txq_num: Max # Tx queues supported
+ * @dma_chnl_num: Number of Tx DMA/FIFO channels
+ * @scd_bc_tbls_size: size of scheduler byte count tables
+ * @tfd_size: TFD size
+ * @tx/rx_chains_num: Number of TX/RX chains
+ * @valid_tx/rx_ant: usable antennas
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @max_rxq_log: Log-base-2 of max_rxq_size
+ * @rx_page_order: Rx buffer page order
+ * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
+ * @max_stations:
+ * @ht40_channel: is 40MHz width possible in band 2.4
+ * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
+ * @sw_crypto: 0 for hw, 1 for sw
+ * @max_xxx_size: for ucode uses
+ * @ct_kill_threshold: temperature threshold
+ * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
+ * @struct iwl_sensitivity_ranges: range of sensitivity values
+ */
+struct iwl_hw_params {
+	u8 max_txq_num;
+	u8 dma_chnl_num;
+	u16 scd_bc_tbls_size;
+	u32 tfd_size;
+	u8  tx_chains_num;
+	u8  rx_chains_num;
+	u8  valid_tx_ant;
+	u8  valid_rx_ant;
+	u16 max_rxq_size;
+	u16 max_rxq_log;
+	u32 rx_page_order;
+	u32 rx_wrt_ptr_reg;
+	u8  max_stations;
+	u8  ht40_channel;
+	u8  max_beacon_itrvl;	/* in 1024 ms */
+	u32 max_inst_size;
+	u32 max_data_size;
+	u32 max_bsm_size;
+	u32 ct_kill_threshold; /* value in hw-dependent units */
+	u16 beacon_time_tsf_bits;
+	const struct iwl_sensitivity_ranges *sens;
+};
+
+
+/******************************************************************************
+ *
+ * Functions implemented in core module which are forward declared here
+ * for use by iwl-[4-5].c
+ *
+ * NOTE:  The implementation of these functions are not hardware specific
+ * which is why they are in the core module files.
+ *
+ * Naming convention --
+ * iwl_         <-- Is part of iwlwifi
+ * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * iwl4965_bg_      <-- Called from work queue context
+ * iwl4965_mac_     <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
+extern const u8 iwlegacy_bcast_addr[ETH_ALEN];
+extern int iwl_legacy_queue_space(const struct iwl_queue *q);
+static inline int iwl_legacy_queue_used(const struct iwl_queue *q, int i)
+{
+	return q->write_ptr >= q->read_ptr ?
+		(i >= q->read_ptr && i < q->write_ptr) :
+		!(i < q->read_ptr && i >= q->write_ptr);
+}
+
+
+static inline u8 iwl_legacy_get_cmd_index(struct iwl_queue *q, u32 index,
+								int is_huge)
+{
+	/*
+	 * This is for init calibration result and scan command which
+	 * required buffer > TFD_MAX_PAYLOAD_SIZE,
+	 * the big buffer at end of command array
+	 */
+	if (is_huge)
+		return q->n_window;	/* must be power of 2 */
+
+	/* Otherwise, use normal size buffers */
+	return index & (q->n_window - 1);
+}
+
+
+struct iwl_dma_ptr {
+	dma_addr_t dma;
+	void *addr;
+	size_t size;
+};
+
+#define IWL_OPERATION_MODE_AUTO     0
+#define IWL_OPERATION_MODE_HT_ONLY  1
+#define IWL_OPERATION_MODE_MIXED    2
+#define IWL_OPERATION_MODE_20MHZ    3
+
+#define IWL_TX_CRC_SIZE 4
+#define IWL_TX_DELIMITER_SIZE 4
+
+#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
+
+/* Sensitivity and chain noise calibration */
+#define INITIALIZATION_VALUE		0xFFFF
+#define IWL4965_CAL_NUM_BEACONS		20
+#define IWL_CAL_NUM_BEACONS		16
+#define MAXIMUM_ALLOWED_PATHLOSS	15
+
+#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3
+
+#define MAX_FA_OFDM  50
+#define MIN_FA_OFDM  5
+#define MAX_FA_CCK   50
+#define MIN_FA_CCK   5
+
+#define AUTO_CORR_STEP_OFDM       1
+
+#define AUTO_CORR_STEP_CCK     3
+#define AUTO_CORR_MAX_TH_CCK   160
+
+#define NRG_DIFF               2
+#define NRG_STEP_CCK           2
+#define NRG_MARGIN             8
+#define MAX_NUMBER_CCK_NO_FA 100
+
+#define AUTO_CORR_CCK_MIN_VAL_DEF    (125)
+
+#define CHAIN_A             0
+#define CHAIN_B             1
+#define CHAIN_C             2
+#define CHAIN_NOISE_DELTA_GAIN_INIT_VAL 4
+#define ALL_BAND_FILTER			0xFF00
+#define IN_BAND_FILTER			0xFF
+#define MIN_AVERAGE_NOISE_MAX_VALUE	0xFFFFFFFF
+
+#define NRG_NUM_PREV_STAT_L     20
+#define NUM_RX_CHAINS           3
+
+enum iwl4965_false_alarm_state {
+	IWL_FA_TOO_MANY = 0,
+	IWL_FA_TOO_FEW = 1,
+	IWL_FA_GOOD_RANGE = 2,
+};
+
+enum iwl4965_chain_noise_state {
+	IWL_CHAIN_NOISE_ALIVE = 0,  /* must be 0 */
+	IWL_CHAIN_NOISE_ACCUMULATE,
+	IWL_CHAIN_NOISE_CALIBRATED,
+	IWL_CHAIN_NOISE_DONE,
+};
+
+enum iwl4965_calib_enabled_state {
+	IWL_CALIB_DISABLED = 0,  /* must be 0 */
+	IWL_CALIB_ENABLED = 1,
+};
+
+/*
+ * enum iwl_calib
+ * defines the order in which results of initial calibrations
+ * should be sent to the runtime uCode
+ */
+enum iwl_calib {
+	IWL_CALIB_MAX,
+};
+
+/* Opaque calibration results */
+struct iwl_calib_result {
+	void *buf;
+	size_t buf_len;
+};
+
+enum ucode_type {
+	UCODE_NONE = 0,
+	UCODE_INIT,
+	UCODE_RT
+};
+
+/* Sensitivity calib data */
+struct iwl_sensitivity_data {
+	u32 auto_corr_ofdm;
+	u32 auto_corr_ofdm_mrc;
+	u32 auto_corr_ofdm_x1;
+	u32 auto_corr_ofdm_mrc_x1;
+	u32 auto_corr_cck;
+	u32 auto_corr_cck_mrc;
+
+	u32 last_bad_plcp_cnt_ofdm;
+	u32 last_fa_cnt_ofdm;
+	u32 last_bad_plcp_cnt_cck;
+	u32 last_fa_cnt_cck;
+
+	u32 nrg_curr_state;
+	u32 nrg_prev_state;
+	u32 nrg_value[10];
+	u8  nrg_silence_rssi[NRG_NUM_PREV_STAT_L];
+	u32 nrg_silence_ref;
+	u32 nrg_energy_idx;
+	u32 nrg_silence_idx;
+	u32 nrg_th_cck;
+	s32 nrg_auto_corr_silence_diff;
+	u32 num_in_cck_no_fa;
+	u32 nrg_th_ofdm;
+
+	u16 barker_corr_th_min;
+	u16 barker_corr_th_min_mrc;
+	u16 nrg_th_cca;
+};
+
+/* Chain noise (differential Rx gain) calib data */
+struct iwl_chain_noise_data {
+	u32 active_chains;
+	u32 chain_noise_a;
+	u32 chain_noise_b;
+	u32 chain_noise_c;
+	u32 chain_signal_a;
+	u32 chain_signal_b;
+	u32 chain_signal_c;
+	u16 beacon_count;
+	u8 disconn_array[NUM_RX_CHAINS];
+	u8 delta_gain_code[NUM_RX_CHAINS];
+	u8 radio_write;
+	u8 state;
+};
+
+#define	EEPROM_SEM_TIMEOUT 10		/* milliseconds */
+#define EEPROM_SEM_RETRY_LIMIT 1000	/* number of attempts (not time) */
+
+#define IWL_TRAFFIC_ENTRIES	(256)
+#define IWL_TRAFFIC_ENTRY_SIZE  (64)
+
+enum {
+	MEASUREMENT_READY = (1 << 0),
+	MEASUREMENT_ACTIVE = (1 << 1),
+};
+
+/* interrupt statistics */
+struct isr_statistics {
+	u32 hw;
+	u32 sw;
+	u32 err_code;
+	u32 sch;
+	u32 alive;
+	u32 rfkill;
+	u32 ctkill;
+	u32 wakeup;
+	u32 rx;
+	u32 rx_handlers[REPLY_MAX];
+	u32 tx;
+	u32 unhandled;
+};
+
+/* management statistics */
+enum iwl_mgmt_stats {
+	MANAGEMENT_ASSOC_REQ = 0,
+	MANAGEMENT_ASSOC_RESP,
+	MANAGEMENT_REASSOC_REQ,
+	MANAGEMENT_REASSOC_RESP,
+	MANAGEMENT_PROBE_REQ,
+	MANAGEMENT_PROBE_RESP,
+	MANAGEMENT_BEACON,
+	MANAGEMENT_ATIM,
+	MANAGEMENT_DISASSOC,
+	MANAGEMENT_AUTH,
+	MANAGEMENT_DEAUTH,
+	MANAGEMENT_ACTION,
+	MANAGEMENT_MAX,
+};
+/* control statistics */
+enum iwl_ctrl_stats {
+	CONTROL_BACK_REQ =  0,
+	CONTROL_BACK,
+	CONTROL_PSPOLL,
+	CONTROL_RTS,
+	CONTROL_CTS,
+	CONTROL_ACK,
+	CONTROL_CFEND,
+	CONTROL_CFENDACK,
+	CONTROL_MAX,
+};
+
+struct traffic_stats {
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	u32 mgmt[MANAGEMENT_MAX];
+	u32 ctrl[CONTROL_MAX];
+	u32 data_cnt;
+	u64 data_bytes;
+#endif
+};
+
+/*
+ * iwl_switch_rxon: "channel switch" structure
+ *
+ * @ switch_in_progress: channel switch in progress
+ * @ channel: new channel
+ */
+struct iwl_switch_rxon {
+	bool switch_in_progress;
+	__le16 channel;
+};
+
+/*
+ * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
+ * to perform continuous uCode event logging operation if enabled
+ */
+#define UCODE_TRACE_PERIOD (100)
+
+/*
+ * iwl_event_log: current uCode event log position
+ *
+ * @ucode_trace: enable/disable ucode continuous trace timer
+ * @num_wraps: how many times the event buffer wraps
+ * @next_entry:  the entry just before the next one that uCode would fill
+ * @non_wraps_count: counter for no wrap detected when dump ucode events
+ * @wraps_once_count: counter for wrap once detected when dump ucode events
+ * @wraps_more_count: counter for wrap more than once detected
+ *		      when dump ucode events
+ */
+struct iwl_event_log {
+	bool ucode_trace;
+	u32 num_wraps;
+	u32 next_entry;
+	int non_wraps_count;
+	int wraps_once_count;
+	int wraps_more_count;
+};
+
+/*
+ * host interrupt timeout value
+ * used with setting interrupt coalescing timer
+ * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
+ *
+ * default interrupt coalescing timer is 64 x 32 = 2048 usecs
+ * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
+ */
+#define IWL_HOST_INT_TIMEOUT_MAX	(0xFF)
+#define IWL_HOST_INT_TIMEOUT_DEF	(0x40)
+#define IWL_HOST_INT_TIMEOUT_MIN	(0x0)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MAX	(0xFF)
+#define IWL_HOST_INT_CALIB_TIMEOUT_DEF	(0x10)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MIN	(0x0)
+
+/*
+ * This is the threshold value of plcp error rate per 100mSecs.  It is
+ * used to set and check for the validity of plcp_delta.
+ */
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN	(1)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF	(50)
+#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF	(100)
+#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF	(200)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX	(255)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	(0)
+
+#define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
+#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
+
+/* TX queue watchdog timeouts in mSecs */
+#define IWL_DEF_WD_TIMEOUT	(2000)
+#define IWL_LONG_WD_TIMEOUT	(10000)
+#define IWL_MAX_WD_TIMEOUT	(120000)
+
+enum iwl_reset {
+	IWL_RF_RESET = 0,
+	IWL_FW_RESET,
+	IWL_MAX_FORCE_RESET,
+};
+
+struct iwl_force_reset {
+	int reset_request_count;
+	int reset_success_count;
+	int reset_reject_count;
+	unsigned long reset_duration;
+	unsigned long last_force_reset_jiffies;
+};
+
+/* extend beacon time format bit shifting  */
+/*
+ * for _3945 devices
+ * bits 31:24 - extended
+ * bits 23:0  - interval
+ */
+#define IWL3945_EXT_BEACON_TIME_POS	24
+/*
+ * for _4965 devices
+ * bits 31:22 - extended
+ * bits 21:0  - interval
+ */
+#define IWL4965_EXT_BEACON_TIME_POS	22
+
+enum iwl_rxon_context_id {
+	IWL_RXON_CTX_BSS,
+
+	NUM_IWL_RXON_CTX
+};
+
+struct iwl_rxon_context {
+	struct ieee80211_vif *vif;
+
+	const u8 *ac_to_fifo;
+	const u8 *ac_to_queue;
+	u8 mcast_queue;
+
+	/*
+	 * We could use the vif to indicate active, but we
+	 * also need it to be active during disabling when
+	 * we already removed the vif for type setting.
+	 */
+	bool always_active, is_active;
+
+	bool ht_need_multiple_chains;
+
+	enum iwl_rxon_context_id ctxid;
+
+	u32 interface_modes, exclusive_interface_modes;
+	u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype;
+
+	/*
+	 * We declare this const so it can only be
+	 * changed via explicit cast within the
+	 * routines that actually update the physical
+	 * hardware.
+	 */
+	const struct iwl_legacy_rxon_cmd active;
+	struct iwl_legacy_rxon_cmd staging;
+
+	struct iwl_rxon_time_cmd timing;
+
+	struct iwl_qos_info qos_data;
+
+	u8 bcast_sta_id, ap_sta_id;
+
+	u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
+	u8 qos_cmd;
+	u8 wep_key_cmd;
+
+	struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
+	u8 key_mapping_keys;
+
+	__le32 station_flags;
+
+	struct {
+		bool non_gf_sta_present;
+		u8 protection;
+		bool enabled, is_40mhz;
+		u8 extension_chan_offset;
+	} ht;
+};
+
+struct iwl_priv {
+
+	/* ieee device used by generic ieee processing code */
+	struct ieee80211_hw *hw;
+	struct ieee80211_channel *ieee_channels;
+	struct ieee80211_rate *ieee_rates;
+	struct iwl_cfg *cfg;
+
+	/* temporary frame storage list */
+	struct list_head free_frames;
+	int frames_count;
+
+	enum ieee80211_band band;
+	int alloc_rxb_page;
+
+	void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
+				       struct iwl_rx_mem_buffer *rxb);
+
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+	/* spectrum measurement report caching */
+	struct iwl_spectrum_notification measure_report;
+	u8 measurement_status;
+
+	/* ucode beacon time */
+	u32 ucode_beacon_time;
+	int missed_beacon_threshold;
+
+	/* track IBSS manager (last beacon) status */
+	u32 ibss_manager;
+
+	/* storing the jiffies when the plcp error rate is received */
+	unsigned long plcp_jiffies;
+
+	/* force reset */
+	struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+
+	/* we allocate array of iwl_channel_info for NIC's valid channels.
+	 *    Access via channel # using indirect index array */
+	struct iwl_channel_info *channel_info;	/* channel info array */
+	u8 channel_count;	/* # of channels */
+
+	/* thermal calibration */
+	s32 temperature;	/* degrees Kelvin */
+	s32 last_temperature;
+
+	/* init calibration results */
+	struct iwl_calib_result calib_results[IWL_CALIB_MAX];
+
+	/* Scan related variables */
+	unsigned long scan_start;
+	unsigned long scan_start_tsf;
+	void *scan_cmd;
+	enum ieee80211_band scan_band;
+	struct cfg80211_scan_request *scan_request;
+	struct ieee80211_vif *scan_vif;
+	bool is_internal_short_scan;
+	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
+	u8 mgmt_tx_ant;
+
+	/* spinlock */
+	spinlock_t lock;	/* protect general shared data */
+	spinlock_t hcmd_lock;	/* protect hcmd */
+	spinlock_t reg_lock;	/* protect hw register access */
+	struct mutex mutex;
+	struct mutex sync_cmd_mutex; /* enable serialization of sync commands */
+
+	/* basic pci-network driver stuff */
+	struct pci_dev *pci_dev;
+
+	/* pci hardware address support */
+	void __iomem *hw_base;
+	u32  hw_rev;
+	u32  hw_wa_rev;
+	u8   rev_id;
+
+	/* microcode/device supports multiple contexts */
+	u8 valid_contexts;
+
+	/* command queue number */
+	u8 cmd_queue;
+
+	/* max number of station keys */
+	u8 sta_key_max_num;
+
+	/* EEPROM MAC addresses */
+	struct mac_address addresses[1];
+
+	/* uCode images, save to reload in case of failure */
+	int fw_index;			/* firmware we're trying to load */
+	u32 ucode_ver;			/* version of ucode, copy of
+					   iwl_ucode.ver */
+	struct fw_desc ucode_code;	/* runtime inst */
+	struct fw_desc ucode_data;	/* runtime data original */
+	struct fw_desc ucode_data_backup;	/* runtime data save/restore */
+	struct fw_desc ucode_init;	/* initialization inst */
+	struct fw_desc ucode_init_data;	/* initialization data */
+	struct fw_desc ucode_boot;	/* bootstrap inst */
+	enum ucode_type ucode_type;
+	u8 ucode_write_complete;	/* the image write is complete */
+	char firmware_name[25];
+
+	struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
+
+	struct iwl_switch_rxon switch_rxon;
+
+	/* 1st responses from initialize and runtime uCode images.
+	 * _4965's initialize alive response contains some calibration data. */
+	struct iwl_init_alive_resp card_alive_init;
+	struct iwl_alive_resp card_alive;
+
+	u16 active_rate;
+
+	u8 start_calib;
+	struct iwl_sensitivity_data sensitivity_data;
+	struct iwl_chain_noise_data chain_noise_data;
+	__le16 sensitivity_tbl[HD_TABLE_SIZE];
+
+	struct iwl_ht_config current_ht_config;
+
+	/* Rate scaling data */
+	u8 retry_rate;
+
+	wait_queue_head_t wait_command_queue;
+
+	int activity_timer_active;
+
+	/* Rx and Tx DMA processing queues */
+	struct iwl_rx_queue rxq;
+	struct iwl_tx_queue *txq;
+	unsigned long txq_ctx_active_msk;
+	struct iwl_dma_ptr  kw;	/* keep warm address */
+	struct iwl_dma_ptr  scd_bc_tbls;
+
+	u32 scd_base_addr;	/* scheduler sram base address */
+
+	unsigned long status;
+
+	/* counts mgmt, ctl, and data packets */
+	struct traffic_stats tx_stats;
+	struct traffic_stats rx_stats;
+
+	/* counts interrupts */
+	struct isr_statistics isr_stats;
+
+	struct iwl_power_mgr power_data;
+
+	/* context information */
+	u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
+
+	/* station table variables */
+
+	/* Note: if lock and sta_lock are needed, lock must be acquired first */
+	spinlock_t sta_lock;
+	int num_stations;
+	struct iwl_station_entry stations[IWL_STATION_COUNT];
+	unsigned long ucode_key_table;
+
+	/* queue refcounts */
+#define IWL_MAX_HW_QUEUES	32
+	unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
+	/* for each AC */
+	atomic_t queue_stop_count[4];
+
+	/* Indication if ieee80211_ops->open has been called */
+	u8 is_open;
+
+	u8 mac80211_registered;
+
+	/* eeprom -- this is in the card's little endian byte order */
+	u8 *eeprom;
+	struct iwl_eeprom_calib_info *calib_info;
+
+	enum nl80211_iftype iw_mode;
+
+	/* Last Rx'd beacon timestamp */
+	u64 timestamp;
+
+	union {
+#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
+		struct {
+			void *shared_virt;
+			dma_addr_t shared_phys;
+
+			struct delayed_work thermal_periodic;
+			struct delayed_work rfkill_poll;
+
+			struct iwl3945_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+			struct iwl3945_notif_statistics accum_statistics;
+			struct iwl3945_notif_statistics delta_statistics;
+			struct iwl3945_notif_statistics max_delta;
+#endif
+
+			u32 sta_supp_rates;
+			int last_rx_rssi;	/* From Rx packet statistics */
+
+			/* Rx'd packet timing information */
+			u32 last_beacon_time;
+			u64 last_tsf;
+
+			/*
+			 * each calibration channel group in the
+			 * EEPROM has a derived clip setting for
+			 * each rate.
+			 */
+			const struct iwl3945_clip_group clip_groups[5];
+
+		} _3945;
+#endif
+#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
+		struct {
+			/*
+			 * reporting the number of tids has AGG on. 0 means
+			 * no AGGREGATION
+			 */
+			u8 agg_tids_count;
+
+			struct iwl_rx_phy_res last_phy_res;
+			bool last_phy_res_valid;
+
+			struct completion firmware_loading_complete;
+
+			/*
+			 * chain noise reset and gain commands are the
+			 * two extra calibration commands follows the standard
+			 * phy calibration commands
+			 */
+			u8 phy_calib_chain_noise_reset_cmd;
+			u8 phy_calib_chain_noise_gain_cmd;
+
+			struct iwl_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+			struct iwl_notif_statistics accum_statistics;
+			struct iwl_notif_statistics delta_statistics;
+			struct iwl_notif_statistics max_delta;
+#endif
+
+		} _4965;
+#endif
+	};
+
+	struct iwl_hw_params hw_params;
+
+	u32 inta_mask;
+
+	struct workqueue_struct *workqueue;
+
+	struct work_struct restart;
+	struct work_struct scan_completed;
+	struct work_struct rx_replenish;
+	struct work_struct abort_scan;
+
+	struct iwl_rxon_context *beacon_ctx;
+	struct sk_buff *beacon_skb;
+
+	struct work_struct start_internal_scan;
+	struct work_struct tx_flush;
+
+	struct tasklet_struct irq_tasklet;
+
+	struct delayed_work init_alive_start;
+	struct delayed_work alive_start;
+	struct delayed_work scan_check;
+
+	/* TX Power */
+	s8 tx_power_user_lmt;
+	s8 tx_power_device_lmt;
+	s8 tx_power_next;
+
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	/* debugging info */
+	u32 debug_level; /* per device debugging will override global
+			    iwlegacy_debug_level if set */
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	/* debugfs */
+	u16 tx_traffic_idx;
+	u16 rx_traffic_idx;
+	u8 *tx_traffic;
+	u8 *rx_traffic;
+	struct dentry *debugfs_dir;
+	u32 dbgfs_sram_offset, dbgfs_sram_len;
+	bool disable_ht40;
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUGFS */
+
+	struct work_struct txpower_work;
+	u32 disable_sens_cal;
+	u32 disable_chain_noise_cal;
+	u32 disable_tx_power_cal;
+	struct work_struct run_time_calib_work;
+	struct timer_list statistics_periodic;
+	struct timer_list ucode_trace;
+	struct timer_list watchdog;
+	bool hw_ready;
+
+	struct iwl_event_log event_log;
+
+	struct led_classdev led;
+	unsigned long blink_on, blink_off;
+	bool led_registered;
+}; /*iwl_priv */
+
+static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
+{
+	set_bit(txq_id, &priv->txq_ctx_active_msk);
+}
+
+static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
+{
+	clear_bit(txq_id, &priv->txq_ctx_active_msk);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+/*
+ * iwl_legacy_get_debug_level: Return active debug level for device
+ *
+ * Using sysfs it is possible to set per device debug level. This debug
+ * level will be used if set, otherwise the global debug level which can be
+ * set via module parameter is used.
+ */
+static inline u32 iwl_legacy_get_debug_level(struct iwl_priv *priv)
+{
+	if (priv->debug_level)
+		return priv->debug_level;
+	else
+		return iwlegacy_debug_level;
+}
+#else
+static inline u32 iwl_legacy_get_debug_level(struct iwl_priv *priv)
+{
+	return iwlegacy_debug_level;
+}
+#endif
+
+
+static inline struct ieee80211_hdr *
+iwl_legacy_tx_queue_get_hdr(struct iwl_priv *priv,
+						 int txq_id, int idx)
+{
+	if (priv->txq[txq_id].txb[idx].skb)
+		return (struct ieee80211_hdr *)priv->txq[txq_id].
+				txb[idx].skb->data;
+	return NULL;
+}
+
+static inline struct iwl_rxon_context *
+iwl_legacy_rxon_ctx_from_vif(struct ieee80211_vif *vif)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+	return vif_priv->ctx;
+}
+
+#define for_each_context(priv, ctx)				\
+	for (ctx = &priv->contexts[IWL_RXON_CTX_BSS];		\
+	     ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++)	\
+		if (priv->valid_contexts & BIT(ctx->ctxid))
+
+static inline int iwl_legacy_is_associated(struct iwl_priv *priv,
+				    enum iwl_rxon_context_id ctxid)
+{
+	return (priv->contexts[ctxid].active.filter_flags &
+			RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int iwl_legacy_is_any_associated(struct iwl_priv *priv)
+{
+	return iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS);
+}
+
+static inline int iwl_legacy_is_associated_ctx(struct iwl_rxon_context *ctx)
+{
+	return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int iwl_legacy_is_channel_valid(const struct iwl_channel_info *ch_info)
+{
+	if (ch_info == NULL)
+		return 0;
+	return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+}
+
+static inline int iwl_legacy_is_channel_radar(const struct iwl_channel_info *ch_info)
+{
+	return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+}
+
+static inline u8 iwl_legacy_is_channel_a_band(const struct iwl_channel_info *ch_info)
+{
+	return ch_info->band == IEEE80211_BAND_5GHZ;
+}
+
+static inline int
+iwl_legacy_is_channel_passive(const struct iwl_channel_info *ch)
+{
+	return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+}
+
+static inline void
+__iwl_legacy_free_pages(struct iwl_priv *priv, struct page *page)
+{
+	__free_pages(page, priv->hw_params.rx_page_order);
+	priv->alloc_rxb_page--;
+}
+
+static inline void iwl_legacy_free_pages(struct iwl_priv *priv, unsigned long page)
+{
+	free_pages(page, priv->hw_params.rx_page_order);
+	priv->alloc_rxb_page--;
+}
+#endif				/* __iwl_legacy_dev_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.c b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
new file mode 100644
index 0000000..080b852
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.c
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * 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>
+
+/* sparse doesn't like tracepoint macros */
+#ifndef __CHECKER__
+#include "iwl-dev.h"
+
+#define CREATE_TRACE_POINTS
+#include "iwl-devtrace.h"
+
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite8);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-devtrace.h b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
new file mode 100644
index 0000000..9612aa0
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-devtrace.h
@@ -0,0 +1,270 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_LEGACY_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_LEGACY_DEVICE_TRACE
+
+#include <linux/tracepoint.h>
+
+#if !defined(CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING) || defined(__CHECKER__)
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+
+#define PRIV_ENTRY	__field(struct iwl_priv *, priv)
+#define PRIV_ASSIGN	(__entry->priv = priv)
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_legacy_io
+
+TRACE_EVENT(iwlwifi_legacy_dev_ioread32,
+	TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
+	TP_ARGS(priv, offs, val),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, offs)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%p] read io[%#x] = %#x", __entry->priv,
+					__entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_iowrite8,
+	TP_PROTO(struct iwl_priv *priv, u32 offs, u8 val),
+	TP_ARGS(priv, offs, val),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, offs)
+		__field(u8, val)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%p] write io[%#x] = %#x)", __entry->priv,
+					__entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
+	TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
+	TP_ARGS(priv, offs, val),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, offs)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%p] write io[%#x] = %#x)", __entry->priv,
+					__entry->offs, __entry->val)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_legacy_ucode
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
+	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
+	TP_ARGS(priv, time, data, ev),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(u32, time)
+		__field(u32, data)
+		__field(u32, ev)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->time = time;
+		__entry->data = data;
+		__entry->ev = ev;
+	),
+	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
+		  __entry->priv, __entry->time, __entry->data, __entry->ev)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
+	TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
+	TP_ARGS(priv, wraps, n_entry, p_entry),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(u32, wraps)
+		__field(u32, n_entry)
+		__field(u32, p_entry)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->wraps = wraps;
+		__entry->n_entry = n_entry;
+		__entry->p_entry = p_entry;
+	),
+	TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
+		  __entry->priv, __entry->wraps, __entry->n_entry,
+		  __entry->p_entry)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi
+
+TRACE_EVENT(iwlwifi_legacy_dev_hcmd,
+	TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags),
+	TP_ARGS(priv, hcmd, len, flags),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__dynamic_array(u8, hcmd, len)
+		__field(u32, flags)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		memcpy(__get_dynamic_array(hcmd), hcmd, len);
+		__entry->flags = flags;
+	),
+	TP_printk("[%p] hcmd %#.2x (%ssync)",
+		  __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0],
+		  __entry->flags & CMD_ASYNC ? "a" : "")
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_rx,
+	TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len),
+	TP_ARGS(priv, rxbuf, len),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__dynamic_array(u8, rxbuf, len)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
+	),
+	TP_printk("[%p] RX cmd %#.2x",
+		  __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_tx,
+	TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen,
+		 void *buf0, size_t buf0_len,
+		 void *buf1, size_t buf1_len),
+	TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(size_t, framelen)
+		__dynamic_array(u8, tfd, tfdlen)
+
+		/*
+		 * Do not insert between or below these items,
+		 * we want to keep the frame together (except
+		 * for the possible padding).
+		 */
+		__dynamic_array(u8, buf0, buf0_len)
+		__dynamic_array(u8, buf1, buf1_len)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->framelen = buf0_len + buf1_len;
+		memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
+		memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
+		memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+	),
+	TP_printk("[%p] TX %.2x (%zu bytes)",
+		  __entry->priv,
+		  ((u8 *)__get_dynamic_array(buf0))[0],
+		  __entry->framelen)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
+	TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time,
+		 u32 data1, u32 data2, u32 line, u32 blink1,
+		 u32 blink2, u32 ilink1, u32 ilink2),
+	TP_ARGS(priv, desc, time, data1, data2, line,
+		blink1, blink2, ilink1, ilink2),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, desc)
+		__field(u32, time)
+		__field(u32, data1)
+		__field(u32, data2)
+		__field(u32, line)
+		__field(u32, blink1)
+		__field(u32, blink2)
+		__field(u32, ilink1)
+		__field(u32, ilink2)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->desc = desc;
+		__entry->time = time;
+		__entry->data1 = data1;
+		__entry->data2 = data2;
+		__entry->line = line;
+		__entry->blink1 = blink1;
+		__entry->blink2 = blink2;
+		__entry->ilink1 = ilink1;
+		__entry->ilink2 = ilink2;
+	),
+	TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
+		  "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X",
+		  __entry->priv, __entry->desc, __entry->time, __entry->data1,
+		  __entry->data2, __entry->line, __entry->blink1,
+		  __entry->blink2, __entry->ilink1, __entry->ilink2)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
+	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
+	TP_ARGS(priv, time, data, ev),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(u32, time)
+		__field(u32, data)
+		__field(u32, ev)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->time = time;
+		__entry->data = data;
+		__entry->ev = ev;
+	),
+	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
+		  __entry->priv, __entry->time, __entry->data, __entry->ev)
+);
+#endif /* __IWLWIFI_DEVICE_TRACE */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace
+#include <trace/define_trace.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.c b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
new file mode 100644
index 0000000..04c5648
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.c
@@ -0,0 +1,561 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-eeprom.h"
+#include "iwl-io.h"
+
+/************************** EEPROM BANDS ****************************
+ *
+ * The iwlegacy_eeprom_band definitions below provide the mapping from the
+ * EEPROM contents to the specific channel number supported for each
+ * band.
+ *
+ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
+ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
+ * The specific geography and calibration information for that channel
+ * is contained in the eeprom map itself.
+ *
+ * During init, we copy the eeprom information and channel map
+ * information into priv->channel_info_24/52 and priv->channel_map_24/52
+ *
+ * channel_map_24/52 provides the index in the channel_info array for a
+ * given channel.  We have to have two separate maps as there is channel
+ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
+ * band_2
+ *
+ * A value of 0xff stored in the channel_map indicates that the channel
+ * is not supported by the hardware at all.
+ *
+ * A value of 0xfe in the channel_map indicates that the channel is not
+ * valid for Tx with the current hardware.  This means that
+ * while the system can tune and receive on a given channel, it may not
+ * be able to associate or transmit any frames on that
+ * channel.  There is no corresponding channel information for that
+ * entry.
+ *
+ *********************************************************************/
+
+/* 2.4 GHz */
+const u8 iwlegacy_eeprom_band_1[14] = {
+	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+};
+
+/* 5.2 GHz bands */
+static const u8 iwlegacy_eeprom_band_2[] = {	/* 4915-5080MHz */
+	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
+};
+
+static const u8 iwlegacy_eeprom_band_3[] = {	/* 5170-5320MHz */
+	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+};
+
+static const u8 iwlegacy_eeprom_band_4[] = {	/* 5500-5700MHz */
+	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+};
+
+static const u8 iwlegacy_eeprom_band_5[] = {	/* 5725-5825MHz */
+	145, 149, 153, 157, 161, 165
+};
+
+static const u8 iwlegacy_eeprom_band_6[] = {       /* 2.4 ht40 channel */
+	1, 2, 3, 4, 5, 6, 7
+};
+
+static const u8 iwlegacy_eeprom_band_7[] = {       /* 5.2 ht40 channel */
+	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
+};
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+static int iwl_legacy_eeprom_verify_signature(struct iwl_priv *priv)
+{
+	u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
+	int ret = 0;
+
+	IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
+	switch (gp) {
+	case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
+	case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
+		break;
+	default:
+		IWL_ERR(priv, "bad EEPROM signature,"
+			"EEPROM_GP=0x%08x\n", gp);
+		ret = -ENOENT;
+		break;
+	}
+	return ret;
+}
+
+const u8
+*iwl_legacy_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
+{
+	BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
+	return &priv->eeprom[offset];
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_query_addr);
+
+u16 iwl_legacy_eeprom_query16(const struct iwl_priv *priv, size_t offset)
+{
+	if (!priv->eeprom)
+		return 0;
+	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_query16);
+
+/**
+ * iwl_legacy_eeprom_init - read EEPROM contents
+ *
+ * Load the EEPROM contents from adapter into priv->eeprom
+ *
+ * NOTE:  This routine uses the non-debug IO access functions.
+ */
+int iwl_legacy_eeprom_init(struct iwl_priv *priv)
+{
+	__le16 *e;
+	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
+	int sz;
+	int ret;
+	u16 addr;
+
+	/* allocate eeprom */
+	sz = priv->cfg->base_params->eeprom_size;
+	IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
+	priv->eeprom = kzalloc(sz, GFP_KERNEL);
+	if (!priv->eeprom) {
+		ret = -ENOMEM;
+		goto alloc_err;
+	}
+	e = (__le16 *)priv->eeprom;
+
+	priv->cfg->ops->lib->apm_ops.init(priv);
+
+	ret = iwl_legacy_eeprom_verify_signature(priv);
+	if (ret < 0) {
+		IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
+		ret = -ENOENT;
+		goto err;
+	}
+
+	/* Make sure driver (instead of uCode) is allowed to read EEPROM */
+	ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
+	if (ret < 0) {
+		IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n");
+		ret = -ENOENT;
+		goto err;
+	}
+
+	/* eeprom is an array of 16bit values */
+	for (addr = 0; addr < sz; addr += sizeof(u16)) {
+		u32 r;
+
+		_iwl_legacy_write32(priv, CSR_EEPROM_REG,
+			     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+
+		ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
+					  CSR_EEPROM_REG_READ_VALID_MSK,
+					  CSR_EEPROM_REG_READ_VALID_MSK,
+					  IWL_EEPROM_ACCESS_TIMEOUT);
+		if (ret < 0) {
+			IWL_ERR(priv, "Time out reading EEPROM[%d]\n",
+							addr);
+			goto done;
+		}
+		r = _iwl_legacy_read_direct32(priv, CSR_EEPROM_REG);
+		e[addr / 2] = cpu_to_le16(r >> 16);
+	}
+
+	IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
+		       "EEPROM",
+		       iwl_legacy_eeprom_query16(priv, EEPROM_VERSION));
+
+	ret = 0;
+done:
+	priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
+
+err:
+	if (ret)
+		iwl_legacy_eeprom_free(priv);
+	/* Reset chip to save power until we load uCode during "up". */
+	iwl_legacy_apm_stop(priv);
+alloc_err:
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_init);
+
+void iwl_legacy_eeprom_free(struct iwl_priv *priv)
+{
+	kfree(priv->eeprom);
+	priv->eeprom = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_free);
+
+static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
+			int eep_band, int *eeprom_ch_count,
+			const struct iwl_eeprom_channel **eeprom_ch_info,
+			const u8 **eeprom_ch_index)
+{
+	u32 offset = priv->cfg->ops->lib->
+			eeprom_ops.regulatory_bands[eep_band - 1];
+	switch (eep_band) {
+	case 1:		/* 2.4GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_1);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_1;
+		break;
+	case 2:		/* 4.9GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_2);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_2;
+		break;
+	case 3:		/* 5.2GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_3);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_3;
+		break;
+	case 4:		/* 5.5GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_4);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_4;
+		break;
+	case 5:		/* 5.7GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_5);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_5;
+		break;
+	case 6:		/* 2.4GHz ht40 channels */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_6);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_6;
+		break;
+	case 7:		/* 5 GHz ht40 channels */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_7);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_7;
+		break;
+	default:
+		BUG();
+		return;
+	}
+}
+
+#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
+			    ? # x " " : "")
+/**
+ * iwl_legacy_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
+ *
+ * Does not set up a command, or touch hardware.
+ */
+static int iwl_legacy_mod_ht40_chan_info(struct iwl_priv *priv,
+			      enum ieee80211_band band, u16 channel,
+			      const struct iwl_eeprom_channel *eeprom_ch,
+			      u8 clear_ht40_extension_channel)
+{
+	struct iwl_channel_info *ch_info;
+
+	ch_info = (struct iwl_channel_info *)
+			iwl_legacy_get_channel_info(priv, band, channel);
+
+	if (!iwl_legacy_is_channel_valid(ch_info))
+		return -1;
+
+	IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
+			" Ad-Hoc %ssupported\n",
+			ch_info->channel,
+			iwl_legacy_is_channel_a_band(ch_info) ?
+			"5.2" : "2.4",
+			CHECK_AND_PRINT(IBSS),
+			CHECK_AND_PRINT(ACTIVE),
+			CHECK_AND_PRINT(RADAR),
+			CHECK_AND_PRINT(WIDE),
+			CHECK_AND_PRINT(DFS),
+			eeprom_ch->flags,
+			eeprom_ch->max_power_avg,
+			((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
+			 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
+			"" : "not ");
+
+	ch_info->ht40_eeprom = *eeprom_ch;
+	ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
+	ch_info->ht40_flags = eeprom_ch->flags;
+	if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
+		ch_info->ht40_extension_channel &=
+					~clear_ht40_extension_channel;
+
+	return 0;
+}
+
+#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
+			    ? # x " " : "")
+
+/**
+ * iwl_legacy_init_channel_map - Set up driver's info for all possible channels
+ */
+int iwl_legacy_init_channel_map(struct iwl_priv *priv)
+{
+	int eeprom_ch_count = 0;
+	const u8 *eeprom_ch_index = NULL;
+	const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
+	int band, ch;
+	struct iwl_channel_info *ch_info;
+
+	if (priv->channel_count) {
+		IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n");
+		return 0;
+	}
+
+	IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n");
+
+	priv->channel_count =
+	    ARRAY_SIZE(iwlegacy_eeprom_band_1) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_2) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_3) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_4) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_5);
+
+	IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n",
+			priv->channel_count);
+
+	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
+				     priv->channel_count, GFP_KERNEL);
+	if (!priv->channel_info) {
+		IWL_ERR(priv, "Could not allocate channel_info\n");
+		priv->channel_count = 0;
+		return -ENOMEM;
+	}
+
+	ch_info = priv->channel_info;
+
+	/* Loop through the 5 EEPROM bands adding them in order to the
+	 * channel map we maintain (that contains additional information than
+	 * what just in the EEPROM) */
+	for (band = 1; band <= 5; band++) {
+
+		iwl_legacy_init_band_reference(priv, band, &eeprom_ch_count,
+					&eeprom_ch_info, &eeprom_ch_index);
+
+		/* Loop through each band adding each of the channels */
+		for (ch = 0; ch < eeprom_ch_count; ch++) {
+			ch_info->channel = eeprom_ch_index[ch];
+			ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
+			    IEEE80211_BAND_5GHZ;
+
+			/* permanently store EEPROM's channel regulatory flags
+			 *   and max power in channel info database. */
+			ch_info->eeprom = eeprom_ch_info[ch];
+
+			/* Copy the run-time flags so they are there even on
+			 * invalid channels */
+			ch_info->flags = eeprom_ch_info[ch].flags;
+			/* First write that ht40 is not enabled, and then enable
+			 * one by one */
+			ch_info->ht40_extension_channel =
+					IEEE80211_CHAN_NO_HT40;
+
+			if (!(iwl_legacy_is_channel_valid(ch_info))) {
+				IWL_DEBUG_EEPROM(priv,
+					       "Ch. %d Flags %x [%sGHz] - "
+					       "No traffic\n",
+					       ch_info->channel,
+					       ch_info->flags,
+					       iwl_legacy_is_channel_a_band(ch_info) ?
+					       "5.2" : "2.4");
+				ch_info++;
+				continue;
+			}
+
+			/* Initialize regulatory-based run-time data */
+			ch_info->max_power_avg = ch_info->curr_txpow =
+			    eeprom_ch_info[ch].max_power_avg;
+			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
+			ch_info->min_power = 0;
+
+			IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] "
+				       "%s%s%s%s%s%s(0x%02x %ddBm):"
+				       " Ad-Hoc %ssupported\n",
+				       ch_info->channel,
+				       iwl_legacy_is_channel_a_band(ch_info) ?
+				       "5.2" : "2.4",
+				       CHECK_AND_PRINT_I(VALID),
+				       CHECK_AND_PRINT_I(IBSS),
+				       CHECK_AND_PRINT_I(ACTIVE),
+				       CHECK_AND_PRINT_I(RADAR),
+				       CHECK_AND_PRINT_I(WIDE),
+				       CHECK_AND_PRINT_I(DFS),
+				       eeprom_ch_info[ch].flags,
+				       eeprom_ch_info[ch].max_power_avg,
+				       ((eeprom_ch_info[ch].
+					 flags & EEPROM_CHANNEL_IBSS)
+					&& !(eeprom_ch_info[ch].
+					     flags & EEPROM_CHANNEL_RADAR))
+				       ? "" : "not ");
+
+			/* Set the tx_power_user_lmt to the highest power
+			 * supported by any channel */
+			if (eeprom_ch_info[ch].max_power_avg >
+						priv->tx_power_user_lmt)
+				priv->tx_power_user_lmt =
+				    eeprom_ch_info[ch].max_power_avg;
+
+			ch_info++;
+		}
+	}
+
+	/* Check if we do have HT40 channels */
+	if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
+	    EEPROM_REGULATORY_BAND_NO_HT40 &&
+	    priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
+	    EEPROM_REGULATORY_BAND_NO_HT40)
+		return 0;
+
+	/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
+	for (band = 6; band <= 7; band++) {
+		enum ieee80211_band ieeeband;
+
+		iwl_legacy_init_band_reference(priv, band, &eeprom_ch_count,
+					&eeprom_ch_info, &eeprom_ch_index);
+
+		/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
+		ieeeband =
+			(band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+
+		/* Loop through each band adding each of the channels */
+		for (ch = 0; ch < eeprom_ch_count; ch++) {
+			/* Set up driver's info for lower half */
+			iwl_legacy_mod_ht40_chan_info(priv, ieeeband,
+						eeprom_ch_index[ch],
+						&eeprom_ch_info[ch],
+						IEEE80211_CHAN_NO_HT40PLUS);
+
+			/* Set up driver's info for upper half */
+			iwl_legacy_mod_ht40_chan_info(priv, ieeeband,
+						eeprom_ch_index[ch] + 4,
+						&eeprom_ch_info[ch],
+						IEEE80211_CHAN_NO_HT40MINUS);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_init_channel_map);
+
+/*
+ * iwl_legacy_free_channel_map - undo allocations in iwl_legacy_init_channel_map
+ */
+void iwl_legacy_free_channel_map(struct iwl_priv *priv)
+{
+	kfree(priv->channel_info);
+	priv->channel_count = 0;
+}
+EXPORT_SYMBOL(iwl_legacy_free_channel_map);
+
+/**
+ * iwl_legacy_get_channel_info - Find driver's private channel info
+ *
+ * Based on band and channel number.
+ */
+const struct
+iwl_channel_info *iwl_legacy_get_channel_info(const struct iwl_priv *priv,
+					enum ieee80211_band band, u16 channel)
+{
+	int i;
+
+	switch (band) {
+	case IEEE80211_BAND_5GHZ:
+		for (i = 14; i < priv->channel_count; i++) {
+			if (priv->channel_info[i].channel == channel)
+				return &priv->channel_info[i];
+		}
+		break;
+	case IEEE80211_BAND_2GHZ:
+		if (channel >= 1 && channel <= 14)
+			return &priv->channel_info[channel - 1];
+		break;
+	default:
+		BUG();
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_get_channel_info);
diff --git a/drivers/net/wireless/iwlegacy/iwl-eeprom.h b/drivers/net/wireless/iwlegacy/iwl-eeprom.h
new file mode 100644
index 0000000..c59c810
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-eeprom.h
@@ -0,0 +1,344 @@
+/******************************************************************************
+ *
+ * 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) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_eeprom_h__
+#define __iwl_legacy_eeprom_h__
+
+#include <net/mac80211.h>
+
+struct iwl_priv;
+
+/*
+ * EEPROM access time values:
+ *
+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
+ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+ */
+#define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */
+
+#define IWL_EEPROM_SEM_TIMEOUT		10   /* microseconds */
+#define IWL_EEPROM_SEM_RETRY_LIMIT	1000 /* number of attempts (not time) */
+
+
+/*
+ * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
+ *
+ * IBSS and/or AP operation is allowed *only* on those channels with
+ * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
+ * RADAR detection is not supported by the 4965 driver, but is a
+ * requirement for establishing a new network for legal operation on channels
+ * requiring RADAR detection or restricting ACTIVE scanning.
+ *
+ * NOTE:  "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
+ *        It only indicates that 20 MHz channel use is supported; HT40 channel
+ *        usage is indicated by a separate set of regulatory flags for each
+ *        HT40 channel pair.
+ *
+ * NOTE:  Using a channel inappropriately will result in a uCode error!
+ */
+#define IWL_NUM_TX_CALIB_GROUPS 5
+enum {
+	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */
+	EEPROM_CHANNEL_IBSS = (1 << 1),		/* usable as an IBSS channel */
+	/* Bit 2 Reserved */
+	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */
+	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */
+	EEPROM_CHANNEL_WIDE = (1 << 5),		/* 20 MHz channel okay */
+	/* Bit 6 Reserved (was Narrow Channel) */
+	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */
+};
+
+/* SKU Capabilities */
+/* 3945 only */
+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
+
+/* *regulatory* channel data format in eeprom, one for each channel.
+ * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
+struct iwl_eeprom_channel {
+	u8 flags;		/* EEPROM_CHANNEL_* flags copied from EEPROM */
+	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
+} __packed;
+
+/* 3945 Specific */
+#define EEPROM_3945_EEPROM_VERSION	(0x2f)
+
+/* 4965 has two radio transmitters (and 3 radio receivers) */
+#define EEPROM_TX_POWER_TX_CHAINS      (2)
+
+/* 4965 has room for up to 8 sets of txpower calibration data */
+#define EEPROM_TX_POWER_BANDS          (8)
+
+/* 4965 factory calibration measures txpower gain settings for
+ * each of 3 target output levels */
+#define EEPROM_TX_POWER_MEASUREMENTS   (3)
+
+/* 4965 Specific */
+/* 4965 driver does not work with txpower calibration version < 5 */
+#define EEPROM_4965_TX_POWER_VERSION    (5)
+#define EEPROM_4965_EEPROM_VERSION	(0x2f)
+#define EEPROM_4965_CALIB_VERSION_OFFSET       (2*0xB6) /* 2 bytes */
+#define EEPROM_4965_CALIB_TXPOWER_OFFSET       (2*0xE8) /* 48  bytes */
+#define EEPROM_4965_BOARD_REVISION             (2*0x4F) /* 2 bytes */
+#define EEPROM_4965_BOARD_PBA                  (2*0x56+1) /* 9 bytes */
+
+/* 2.4 GHz */
+extern const u8 iwlegacy_eeprom_band_1[14];
+
+/*
+ * factory calibration data for one txpower level, on one channel,
+ * measured on one of the 2 tx chains (radio transmitter and associated
+ * antenna).  EEPROM contains:
+ *
+ * 1)  Temperature (degrees Celsius) of device when measurement was made.
+ *
+ * 2)  Gain table index used to achieve the target measurement power.
+ *     This refers to the "well-known" gain tables (see iwl-4965-hw.h).
+ *
+ * 3)  Actual measured output power, in half-dBm ("34" = 17 dBm).
+ *
+ * 4)  RF power amplifier detector level measurement (not used).
+ */
+struct iwl_eeprom_calib_measure {
+	u8 temperature;		/* Device temperature (Celsius) */
+	u8 gain_idx;		/* Index into gain table */
+	u8 actual_pow;		/* Measured RF output power, half-dBm */
+	s8 pa_det;		/* Power amp detector level (not used) */
+} __packed;
+
+
+/*
+ * measurement set for one channel.  EEPROM contains:
+ *
+ * 1)  Channel number measured
+ *
+ * 2)  Measurements for each of 3 power levels for each of 2 radio transmitters
+ *     (a.k.a. "tx chains") (6 measurements altogether)
+ */
+struct iwl_eeprom_calib_ch_info {
+	u8 ch_num;
+	struct iwl_eeprom_calib_measure
+		measurements[EEPROM_TX_POWER_TX_CHAINS]
+			[EEPROM_TX_POWER_MEASUREMENTS];
+} __packed;
+
+/*
+ * txpower subband info.
+ *
+ * For each frequency subband, EEPROM contains the following:
+ *
+ * 1)  First and last channels within range of the subband.  "0" values
+ *     indicate that this sample set is not being used.
+ *
+ * 2)  Sample measurement sets for 2 channels close to the range endpoints.
+ */
+struct iwl_eeprom_calib_subband_info {
+	u8 ch_from;	/* channel number of lowest channel in subband */
+	u8 ch_to;	/* channel number of highest channel in subband */
+	struct iwl_eeprom_calib_ch_info ch1;
+	struct iwl_eeprom_calib_ch_info ch2;
+} __packed;
+
+
+/*
+ * txpower calibration info.  EEPROM contains:
+ *
+ * 1)  Factory-measured saturation power levels (maximum levels at which
+ *     tx power amplifier can output a signal without too much distortion).
+ *     There is one level for 2.4 GHz band and one for 5 GHz band.  These
+ *     values apply to all channels within each of the bands.
+ *
+ * 2)  Factory-measured power supply voltage level.  This is assumed to be
+ *     constant (i.e. same value applies to all channels/bands) while the
+ *     factory measurements are being made.
+ *
+ * 3)  Up to 8 sets of factory-measured txpower calibration values.
+ *     These are for different frequency ranges, since txpower gain
+ *     characteristics of the analog radio circuitry vary with frequency.
+ *
+ *     Not all sets need to be filled with data;
+ *     struct iwl_eeprom_calib_subband_info contains range of channels
+ *     (0 if unused) for each set of data.
+ */
+struct iwl_eeprom_calib_info {
+	u8 saturation_power24;	/* half-dBm (e.g. "34" = 17 dBm) */
+	u8 saturation_power52;	/* half-dBm */
+	__le16 voltage;		/* signed */
+	struct iwl_eeprom_calib_subband_info
+		band_info[EEPROM_TX_POWER_BANDS];
+} __packed;
+
+
+/* General */
+#define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
+#define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
+#define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
+#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
+#define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
+#define EEPROM_SKU_CAP                      (2*0x45)	/* 2  bytes */
+#define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
+#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
+#define EEPROM_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */
+#define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */
+
+/* The following masks are to be applied on EEPROM_RADIO_CONFIG */
+#define EEPROM_RF_CFG_TYPE_MSK(x)   (x & 0x3)         /* bits 0-1   */
+#define EEPROM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3) /* bits 2-3   */
+#define EEPROM_RF_CFG_DASH_MSK(x)   ((x >> 4)  & 0x3) /* bits 4-5   */
+#define EEPROM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3) /* bits 6-7   */
+#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF) /* bits 8-11  */
+#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
+
+#define EEPROM_3945_RF_CFG_TYPE_MAX  0x0
+#define EEPROM_4965_RF_CFG_TYPE_MAX  0x1
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by iwl has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
+ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+#define EEPROM_REGULATORY_SKU_ID            (2*0x60)    /* 4  bytes */
+#define EEPROM_REGULATORY_BAND_1            (2*0x62)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)	/* 28 bytes */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+#define EEPROM_REGULATORY_BAND_2            (2*0x71)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)	/* 26 bytes */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+#define EEPROM_REGULATORY_BAND_3            (2*0x7F)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)	/* 24 bytes */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+#define EEPROM_REGULATORY_BAND_4            (2*0x8C)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)	/* 22 bytes */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+#define EEPROM_REGULATORY_BAND_5            (2*0x98)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
+
+/*
+ * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+ *
+ * The channel listed is the center of the lower 20 MHz half of the channel.
+ * The overall center frequency is actually 2 channels (10 MHz) above that,
+ * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
+ * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
+ * and the overall HT40 channel width centers on channel 3.
+ *
+ * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
+ *        control channel to which to tune.  RXON also specifies whether the
+ *        control channel is the upper or lower half of a HT40 channel.
+ *
+ * NOTE:  4965 does not support HT40 channels on 2.4 GHz.
+ */
+#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0)	/* 14 bytes */
+
+/*
+ * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
+ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
+ */
+#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8)	/* 22 bytes */
+
+#define EEPROM_REGULATORY_BAND_NO_HT40			(0)
+
+struct iwl_eeprom_ops {
+	const u32 regulatory_bands[7];
+	int (*acquire_semaphore) (struct iwl_priv *priv);
+	void (*release_semaphore) (struct iwl_priv *priv);
+};
+
+
+int iwl_legacy_eeprom_init(struct iwl_priv *priv);
+void iwl_legacy_eeprom_free(struct iwl_priv *priv);
+const u8 *iwl_legacy_eeprom_query_addr(const struct iwl_priv *priv,
+					size_t offset);
+u16 iwl_legacy_eeprom_query16(const struct iwl_priv *priv, size_t offset);
+int iwl_legacy_init_channel_map(struct iwl_priv *priv);
+void iwl_legacy_free_channel_map(struct iwl_priv *priv);
+const struct iwl_channel_info *iwl_legacy_get_channel_info(
+		const struct iwl_priv *priv,
+		enum ieee80211_band band, u16 channel);
+
+#endif  /* __iwl_legacy_eeprom_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-fh.h b/drivers/net/wireless/iwlegacy/iwl-fh.h
new file mode 100644
index 0000000..4e20c7e
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-fh.h
@@ -0,0 +1,513 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_legacy_fh_h__
+#define __iwl_legacy_fh_h__
+
+/****************************/
+/* Flow Handler Definitions */
+/****************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH_MEM_LOWER_BOUND                   (0x1000)
+#define FH_MEM_UPPER_BOUND                   (0x2000)
+
+/**
+ * Keep-Warm (KW) buffer base address.
+ *
+ * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the
+ * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
+ * DRAM access when 4965 is Txing or Rxing.  The dummy accesses prevent host
+ * from going into a power-savings mode that would cause higher DRAM latency,
+ * and possible data over/under-runs, before all Tx/Rx is complete.
+ *
+ * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
+ * of the buffer, which must be 4K aligned.  Once this is set up, the 4965
+ * automatically invokes keep-warm accesses when normal accesses might not
+ * be sufficient to maintain fast DRAM response.
+ *
+ * Bit fields:
+ *  31-0:  Keep-warm buffer physical base address [35:4], must be 4K aligned
+ */
+#define FH_KW_MEM_ADDR_REG		     (FH_MEM_LOWER_BOUND + 0x97C)
+
+
+/**
+ * TFD Circular Buffers Base (CBBC) addresses
+ *
+ * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident
+ * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
+ * (see struct iwl_tfd_frame).  These 16 pointer registers are offset by 0x04
+ * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte
+ * aligned (address bits 0-7 must be 0).
+ *
+ * Bit fields in each pointer register:
+ *  27-0: TFD CB physical base address [35:8], must be 256-byte aligned
+ */
+#define FH_MEM_CBBC_LOWER_BOUND          (FH_MEM_LOWER_BOUND + 0x9D0)
+#define FH_MEM_CBBC_UPPER_BOUND          (FH_MEM_LOWER_BOUND + 0xA10)
+
+/* Find TFD CB base pointer for given queue (range 0-15). */
+#define FH_MEM_CBBC_QUEUE(x)  (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
+
+
+/**
+ * Rx SRAM Control and Status Registers (RSCSR)
+ *
+ * These registers provide handshake between driver and 4965 for the Rx queue
+ * (this queue handles *all* command responses, notifications, Rx data, etc.
+ * sent from 4965 uCode to host driver).  Unlike Tx, there is only one Rx
+ * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can
+ * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
+ * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
+ * mapping between RBDs and RBs.
+ *
+ * Driver must allocate host DRAM memory for the following, and set the
+ * physical address of each into 4965 registers:
+ *
+ * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
+ *     entries (although any power of 2, up to 4096, is selectable by driver).
+ *     Each entry (1 dword) points to a receive buffer (RB) of consistent size
+ *     (typically 4K, although 8K or 16K are also selectable by driver).
+ *     Driver sets up RB size and number of RBDs in the CB via Rx config
+ *     register FH_MEM_RCSR_CHNL0_CONFIG_REG.
+ *
+ *     Bit fields within one RBD:
+ *     27-0:  Receive Buffer physical address bits [35:8], 256-byte aligned
+ *
+ *     Driver sets physical address [35:8] of base of RBD circular buffer
+ *     into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
+ *
+ * 2)  Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers
+ *     (RBs) have been filled, via a "write pointer", actually the index of
+ *     the RB's corresponding RBD within the circular buffer.  Driver sets
+ *     physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
+ *
+ *     Bit fields in lower dword of Rx status buffer (upper dword not used
+ *     by driver; see struct iwl4965_shared, val0):
+ *     31-12:  Not used by driver
+ *     11- 0:  Index of last filled Rx buffer descriptor
+ *             (4965 writes, driver reads this value)
+ *
+ * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must
+ * enter pointers to these RBs into contiguous RBD circular buffer entries,
+ * and update the 4965's "write" index register,
+ * FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
+ *
+ * This "write" index corresponds to the *next* RBD that the driver will make
+ * available, i.e. one RBD past the tail of the ready-to-fill RBDs within
+ * the circular buffer.  This value should initially be 0 (before preparing any
+ * RBs), should be 8 after preparing the first 8 RBs (for example), and must
+ * wrap back to 0 at the end of the circular buffer (but don't wrap before
+ * "read" index has advanced past 1!  See below).
+ * NOTE:  4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
+ *
+ * As the 4965 fills RBs (referenced from contiguous RBDs within the circular
+ * buffer), it updates the Rx status buffer in host DRAM, 2) described above,
+ * to tell the driver the index of the latest filled RBD.  The driver must
+ * read this "read" index from DRAM after receiving an Rx interrupt from 4965.
+ *
+ * The driver must also internally keep track of a third index, which is the
+ * next RBD to process.  When receiving an Rx interrupt, driver should process
+ * all filled but unprocessed RBs up to, but not including, the RB
+ * corresponding to the "read" index.  For example, if "read" index becomes "1",
+ * driver may process the RB pointed to by RBD 0.  Depending on volume of
+ * traffic, there may be many RBs to process.
+ *
+ * If read index == write index, 4965 thinks there is no room to put new data.
+ * Due to this, the maximum number of filled RBs is 255, instead of 256.  To
+ * be safe, make sure that there is a gap of at least 2 RBDs between "write"
+ * and "read" indexes; that is, make sure that there are no more than 254
+ * buffers waiting to be filled.
+ */
+#define FH_MEM_RSCSR_LOWER_BOUND	(FH_MEM_LOWER_BOUND + 0xBC0)
+#define FH_MEM_RSCSR_UPPER_BOUND	(FH_MEM_LOWER_BOUND + 0xC00)
+#define FH_MEM_RSCSR_CHNL0		(FH_MEM_RSCSR_LOWER_BOUND)
+
+/**
+ * Physical base address of 8-byte Rx Status buffer.
+ * Bit fields:
+ *  31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
+ */
+#define FH_RSCSR_CHNL0_STTS_WPTR_REG	(FH_MEM_RSCSR_CHNL0)
+
+/**
+ * Physical base address of Rx Buffer Descriptor Circular Buffer.
+ * Bit fields:
+ *  27-0:  RBD CD physical base address [35:8], must be 256-byte aligned.
+ */
+#define FH_RSCSR_CHNL0_RBDCB_BASE_REG	(FH_MEM_RSCSR_CHNL0 + 0x004)
+
+/**
+ * Rx write pointer (index, really!).
+ * Bit fields:
+ *  11-0:  Index of driver's most recent prepared-to-be-filled RBD, + 1.
+ *         NOTE:  For 256-entry circular buffer, use only bits [7:0].
+ */
+#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG	(FH_MEM_RSCSR_CHNL0 + 0x008)
+#define FH_RSCSR_CHNL0_WPTR        (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
+
+
+/**
+ * Rx Config/Status Registers (RCSR)
+ * Rx Config Reg for channel 0 (only channel used)
+ *
+ * Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for
+ * normal operation (see bit fields).
+ *
+ * Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
+ * Driver should poll FH_MEM_RSSR_RX_STATUS_REG	for
+ * FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
+ *
+ * Bit fields:
+ * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ *        '10' operate normally
+ * 29-24: reserved
+ * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
+ *        min "5" for 32 RBDs, max "12" for 4096 RBDs.
+ * 19-18: reserved
+ * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
+ *        '10' 12K, '11' 16K.
+ * 15-14: reserved
+ * 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
+ * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
+ *        typical value 0x10 (about 1/2 msec)
+ *  3- 0: reserved
+ */
+#define FH_MEM_RCSR_LOWER_BOUND      (FH_MEM_LOWER_BOUND + 0xC00)
+#define FH_MEM_RCSR_UPPER_BOUND      (FH_MEM_LOWER_BOUND + 0xCC0)
+#define FH_MEM_RCSR_CHNL0            (FH_MEM_RCSR_LOWER_BOUND)
+
+#define FH_MEM_RCSR_CHNL0_CONFIG_REG	(FH_MEM_RCSR_CHNL0)
+
+#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK   (0x00001000) /* bits 12 */
+#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */
+#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK   (0x00030000) /* bits 16-17 */
+#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */
+#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/
+
+#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS	(20)
+#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS	(4)
+#define RX_RB_TIMEOUT	(0x10)
+
+#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)
+#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)
+#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        (0x80000000)
+
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K    (0x00010000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K   (0x00020000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K   (0x00030000)
+
+#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY              (0x00000004)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL    (0x00000000)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL  (0x00001000)
+
+#define FH_RSCSR_FRAME_SIZE_MSK	(0x00003FFF)	/* bits 0-13 */
+
+/**
+ * Rx Shared Status Registers (RSSR)
+ *
+ * After stopping Rx DMA channel (writing 0 to
+ * FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll
+ * FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
+ *
+ * Bit fields:
+ *  24:  1 = Channel 0 is idle
+ *
+ * FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV
+ * contain default values that should not be altered by the driver.
+ */
+#define FH_MEM_RSSR_LOWER_BOUND           (FH_MEM_LOWER_BOUND + 0xC40)
+#define FH_MEM_RSSR_UPPER_BOUND           (FH_MEM_LOWER_BOUND + 0xD00)
+
+#define FH_MEM_RSSR_SHARED_CTRL_REG       (FH_MEM_RSSR_LOWER_BOUND)
+#define FH_MEM_RSSR_RX_STATUS_REG	(FH_MEM_RSSR_LOWER_BOUND + 0x004)
+#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\
+					(FH_MEM_RSSR_LOWER_BOUND + 0x008)
+
+#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE	(0x01000000)
+
+#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT	28
+
+/* TFDB  Area - TFDs buffer table */
+#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK      (0xFFFFFFFF)
+#define FH_TFDIB_LOWER_BOUND       (FH_MEM_LOWER_BOUND + 0x900)
+#define FH_TFDIB_UPPER_BOUND       (FH_MEM_LOWER_BOUND + 0x958)
+#define FH_TFDIB_CTRL0_REG(_chnl)  (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
+#define FH_TFDIB_CTRL1_REG(_chnl)  (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
+
+/**
+ * Transmit DMA Channel Control/Status Registers (TCSR)
+ *
+ * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels
+ * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
+ * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
+ *
+ * To use a Tx DMA channel, driver must initialize its
+ * FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
+ *
+ * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
+ *
+ * All other bits should be 0.
+ *
+ * Bit fields:
+ * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ *        '10' operate normally
+ * 29- 4: Reserved, set to "0"
+ *     3: Enable internal DMA requests (1, normal operation), disable (0)
+ *  2- 0: Reserved, set to "0"
+ */
+#define FH_TCSR_LOWER_BOUND  (FH_MEM_LOWER_BOUND + 0xD00)
+#define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)
+
+/* Find Control/Status reg for given Tx DMA/FIFO channel */
+#define FH49_TCSR_CHNL_NUM                            (7)
+#define FH50_TCSR_CHNL_NUM                            (8)
+
+/* TCSR: tx_config register values */
+#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
+#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV		(0x00000001)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE	(0x00000008)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD	(0x00100000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD	(0x00200000)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD	(0x00400000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD	(0x00800000)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF	(0x40000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE	(0x80000000)
+
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY	(0x00000000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT	(0x00002000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID	(0x00000003)
+
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM		(20)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX		(12)
+
+/**
+ * Tx Shared Status Registers (TSSR)
+ *
+ * After stopping Tx DMA channel (writing 0 to
+ * FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
+ * FH_TSSR_TX_STATUS_REG until selected Tx channel is idle
+ * (channel's buffers empty | no pending requests).
+ *
+ * Bit fields:
+ * 31-24:  1 = Channel buffers empty (channel 7:0)
+ * 23-16:  1 = No pending requests (channel 7:0)
+ */
+#define FH_TSSR_LOWER_BOUND		(FH_MEM_LOWER_BOUND + 0xEA0)
+#define FH_TSSR_UPPER_BOUND		(FH_MEM_LOWER_BOUND + 0xEC0)
+
+#define FH_TSSR_TX_STATUS_REG		(FH_TSSR_LOWER_BOUND + 0x010)
+
+/**
+ * Bit fields for TSSR(Tx Shared Status & Control) error status register:
+ * 31:  Indicates an address error when accessed to internal memory
+ *	uCode/driver must write "1" in order to clear this flag
+ * 30:  Indicates that Host did not send the expected number of dwords to FH
+ *	uCode/driver must write "1" in order to clear this flag
+ * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
+ *	command was received from the scheduler while the TRB was already full
+ *	with previous command
+ *	uCode/driver must write "1" in order to clear this flag
+ * 7-0: Each status bit indicates a channel's TxCredit error. When an error
+ *	bit is set, it indicates that the FH has received a full indication
+ *	from the RTC TxFIFO and the current value of the TxCredit counter was
+ *	not equal to zero. This mean that the credit mechanism was not
+ *	synchronized to the TxFIFO status
+ *	uCode/driver must write "1" in order to clear this flag
+ */
+#define FH_TSSR_TX_ERROR_REG		(FH_TSSR_LOWER_BOUND + 0x018)
+
+#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
+
+/* Tx service channels */
+#define FH_SRVC_CHNL		(9)
+#define FH_SRVC_LOWER_BOUND	(FH_MEM_LOWER_BOUND + 0x9C8)
+#define FH_SRVC_UPPER_BOUND	(FH_MEM_LOWER_BOUND + 0x9D0)
+#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
+		(FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
+
+#define FH_TX_CHICKEN_BITS_REG	(FH_MEM_LOWER_BOUND + 0xE98)
+/* Instruct FH to increment the retry count of a packet when
+ * it is brought from the memory to TX-FIFO
+ */
+#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN	(0x00000002)
+
+#define RX_QUEUE_SIZE                         256
+#define RX_QUEUE_MASK                         255
+#define RX_QUEUE_SIZE_LOG                     8
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+/* Size of one Rx buffer in host DRAM */
+#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */
+#define IWL_RX_BUF_SIZE_4K (4 * 1024)
+#define IWL_RX_BUF_SIZE_8K (8 * 1024)
+
+/**
+ * struct iwl_rb_status - reseve buffer status
+ * 	host memory mapped FH registers
+ * @closed_rb_num [0:11] - Indicates the index of the RB which was closed
+ * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
+ * @finished_rb_num [0:11] - Indicates the index of the current RB
+ * 	in which the last frame was written to
+ * @finished_fr_num [0:11] - Indicates the index of the RX Frame
+ * 	which was transfered
+ */
+struct iwl_rb_status {
+	__le16 closed_rb_num;
+	__le16 closed_fr_num;
+	__le16 finished_rb_num;
+	__le16 finished_fr_nam;
+	__le32 __unused; /* 3945 only */
+} __packed;
+
+
+#define TFD_QUEUE_SIZE_MAX      (256)
+#define TFD_QUEUE_SIZE_BC_DUP	(64)
+#define TFD_QUEUE_BC_SIZE	(TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
+#define IWL_TX_DMA_MASK        DMA_BIT_MASK(36)
+#define IWL_NUM_OF_TBS		20
+
+static inline u8 iwl_legacy_get_dma_hi_addr(dma_addr_t addr)
+{
+	return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
+}
+/**
+ * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
+ *
+ * This structure contains dma address and length of transmission address
+ *
+ * @lo: low [31:0] portion of the dma address of TX buffer
+ * 	every even is unaligned on 16 bit boundary
+ * @hi_n_len 0-3 [35:32] portion of dma
+ *	     4-15 length of the tx buffer
+ */
+struct iwl_tfd_tb {
+	__le32 lo;
+	__le16 hi_n_len;
+} __packed;
+
+/**
+ * struct iwl_tfd
+ *
+ * Transmit Frame Descriptor (TFD)
+ *
+ * @ __reserved1[3] reserved
+ * @ num_tbs 0-4 number of active tbs
+ *	     5   reserved
+ * 	     6-7 padding (not used)
+ * @ tbs[20]	transmit frame buffer descriptors
+ * @ __pad 	padding
+ *
+ * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
+ * Both driver and device share these circular buffers, each of which must be
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
+ *
+ * Driver must indicate the physical address of the base of each
+ * circular buffer via the FH_MEM_CBBC_QUEUE registers.
+ *
+ * Each TFD contains pointer/size information for up to 20 data buffers
+ * in host DRAM.  These buffers collectively contain the (one) frame described
+ * by the TFD.  Each buffer must be a single contiguous block of memory within
+ * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
+ * of (4K - 4).  The concatenates all of a TFD's buffers into a single
+ * Tx frame, up to 8 KBytes in size.
+ *
+ * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ */
+struct iwl_tfd {
+	u8 __reserved1[3];
+	u8 num_tbs;
+	struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
+	__le32 __pad;
+} __packed;
+
+/* Keep Warm Size */
+#define IWL_KW_SIZE 0x1000	/* 4k */
+
+#endif /* !__iwl_legacy_fh_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-hcmd.c b/drivers/net/wireless/iwlegacy/iwl-hcmd.c
new file mode 100644
index 0000000..9d721cb
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-hcmd.c
@@ -0,0 +1,271 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-eeprom.h"
+#include "iwl-core.h"
+
+
+const char *iwl_legacy_get_cmd_string(u8 cmd)
+{
+	switch (cmd) {
+		IWL_CMD(REPLY_ALIVE);
+		IWL_CMD(REPLY_ERROR);
+		IWL_CMD(REPLY_RXON);
+		IWL_CMD(REPLY_RXON_ASSOC);
+		IWL_CMD(REPLY_QOS_PARAM);
+		IWL_CMD(REPLY_RXON_TIMING);
+		IWL_CMD(REPLY_ADD_STA);
+		IWL_CMD(REPLY_REMOVE_STA);
+		IWL_CMD(REPLY_WEPKEY);
+		IWL_CMD(REPLY_3945_RX);
+		IWL_CMD(REPLY_TX);
+		IWL_CMD(REPLY_RATE_SCALE);
+		IWL_CMD(REPLY_LEDS_CMD);
+		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+		IWL_CMD(REPLY_CHANNEL_SWITCH);
+		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+		IWL_CMD(POWER_TABLE_CMD);
+		IWL_CMD(PM_SLEEP_NOTIFICATION);
+		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+		IWL_CMD(REPLY_SCAN_CMD);
+		IWL_CMD(REPLY_SCAN_ABORT_CMD);
+		IWL_CMD(SCAN_START_NOTIFICATION);
+		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+		IWL_CMD(BEACON_NOTIFICATION);
+		IWL_CMD(REPLY_TX_BEACON);
+		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+		IWL_CMD(REPLY_BT_CONFIG);
+		IWL_CMD(REPLY_STATISTICS_CMD);
+		IWL_CMD(STATISTICS_NOTIFICATION);
+		IWL_CMD(CARD_STATE_NOTIFICATION);
+		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+		IWL_CMD(SENSITIVITY_CMD);
+		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+		IWL_CMD(REPLY_RX_PHY_CMD);
+		IWL_CMD(REPLY_RX_MPDU_CMD);
+		IWL_CMD(REPLY_RX);
+		IWL_CMD(REPLY_COMPRESSED_BA);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_get_cmd_string);
+
+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+
+static void iwl_legacy_generic_cmd_callback(struct iwl_priv *priv,
+				     struct iwl_device_cmd *cmd,
+				     struct iwl_rx_packet *pkt)
+{
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
+		iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	switch (cmd->hdr.cmd) {
+	case REPLY_TX_LINK_QUALITY_CMD:
+	case SENSITIVITY_CMD:
+		IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
+		iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+		break;
+	default:
+		IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
+		iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+	}
+#endif
+}
+
+static int
+iwl_legacy_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	int ret;
+
+	BUG_ON(!(cmd->flags & CMD_ASYNC));
+
+	/* An asynchronous command can not expect an SKB to be set. */
+	BUG_ON(cmd->flags & CMD_WANT_SKB);
+
+	/* Assign a generic callback if one is not provided */
+	if (!cmd->callback)
+		cmd->callback = iwl_legacy_generic_cmd_callback;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EBUSY;
+
+	ret = iwl_legacy_enqueue_hcmd(priv, cmd);
+	if (ret < 0) {
+		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+			  iwl_legacy_get_cmd_string(cmd->id), ret);
+		return ret;
+	}
+	return 0;
+}
+
+int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	int cmd_idx;
+	int ret;
+
+	BUG_ON(cmd->flags & CMD_ASYNC);
+
+	 /* A synchronous command can not have a callback set. */
+	BUG_ON(cmd->callback);
+
+	IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
+			iwl_legacy_get_cmd_string(cmd->id));
+	mutex_lock(&priv->sync_cmd_mutex);
+
+	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+	IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
+			iwl_legacy_get_cmd_string(cmd->id));
+
+	cmd_idx = iwl_legacy_enqueue_hcmd(priv, cmd);
+	if (cmd_idx < 0) {
+		ret = cmd_idx;
+		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+			  iwl_legacy_get_cmd_string(cmd->id), ret);
+		goto out;
+	}
+
+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+			HOST_COMPLETE_TIMEOUT);
+	if (!ret) {
+		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+			IWL_ERR(priv,
+				"Error sending %s: time out after %dms.\n",
+				iwl_legacy_get_cmd_string(cmd->id),
+				jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+
+			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+			IWL_DEBUG_INFO(priv,
+				"Clearing HCMD_ACTIVE for command %s\n",
+				       iwl_legacy_get_cmd_string(cmd->id));
+			ret = -ETIMEDOUT;
+			goto cancel;
+		}
+	}
+
+	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+		IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
+			       iwl_legacy_get_cmd_string(cmd->id));
+		ret = -ECANCELED;
+		goto fail;
+	}
+	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+		IWL_ERR(priv, "Command %s failed: FW Error\n",
+			       iwl_legacy_get_cmd_string(cmd->id));
+		ret = -EIO;
+		goto fail;
+	}
+	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+		IWL_ERR(priv, "Error: Response NULL in '%s'\n",
+			  iwl_legacy_get_cmd_string(cmd->id));
+		ret = -EIO;
+		goto cancel;
+	}
+
+	ret = 0;
+	goto out;
+
+cancel:
+	if (cmd->flags & CMD_WANT_SKB) {
+		/*
+		 * Cancel the CMD_WANT_SKB flag for the cmd in the
+		 * TX cmd queue. Otherwise in case the cmd comes
+		 * in later, it will possibly set an invalid
+		 * address (cmd->meta.source).
+		 */
+		priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
+							~CMD_WANT_SKB;
+	}
+fail:
+	if (cmd->reply_page) {
+		iwl_legacy_free_pages(priv, cmd->reply_page);
+		cmd->reply_page = 0;
+	}
+out:
+	mutex_unlock(&priv->sync_cmd_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd_sync);
+
+int iwl_legacy_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	if (cmd->flags & CMD_ASYNC)
+		return iwl_legacy_send_cmd_async(priv, cmd);
+
+	return iwl_legacy_send_cmd_sync(priv, cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd);
+
+int
+iwl_legacy_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
+{
+	struct iwl_host_cmd cmd = {
+		.id = id,
+		.len = len,
+		.data = data,
+	};
+
+	return iwl_legacy_send_cmd_sync(priv, &cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd_pdu);
+
+int iwl_legacy_send_cmd_pdu_async(struct iwl_priv *priv,
+			   u8 id, u16 len, const void *data,
+			   void (*callback)(struct iwl_priv *priv,
+					    struct iwl_device_cmd *cmd,
+					    struct iwl_rx_packet *pkt))
+{
+	struct iwl_host_cmd cmd = {
+		.id = id,
+		.len = len,
+		.data = data,
+	};
+
+	cmd.flags |= CMD_ASYNC;
+	cmd.callback = callback;
+
+	return iwl_legacy_send_cmd_async(priv, &cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd_pdu_async);
diff --git a/drivers/net/wireless/iwlegacy/iwl-helpers.h b/drivers/net/wireless/iwlegacy/iwl-helpers.h
new file mode 100644
index 0000000..02132e7
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-helpers.h
@@ -0,0 +1,181 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_helpers_h__
+#define __iwl_legacy_helpers_h__
+
+#include <linux/ctype.h>
+#include <net/mac80211.h>
+
+#include "iwl-io.h"
+
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+
+static inline struct ieee80211_conf *iwl_legacy_ieee80211_get_hw_conf(
+	struct ieee80211_hw *hw)
+{
+	return &hw->conf;
+}
+
+/**
+ * iwl_legacy_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_legacy_queue_inc_wrap(int index, int n_bd)
+{
+	return ++index & (n_bd - 1);
+}
+
+/**
+ * iwl_legacy_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_legacy_queue_dec_wrap(int index, int n_bd)
+{
+	return --index & (n_bd - 1);
+}
+
+/* TODO: Move fw_desc functions to iwl-pci.ko */
+static inline void iwl_legacy_free_fw_desc(struct pci_dev *pci_dev,
+				    struct fw_desc *desc)
+{
+	if (desc->v_addr)
+		dma_free_coherent(&pci_dev->dev, desc->len,
+				  desc->v_addr, desc->p_addr);
+	desc->v_addr = NULL;
+	desc->len = 0;
+}
+
+static inline int iwl_legacy_alloc_fw_desc(struct pci_dev *pci_dev,
+				    struct fw_desc *desc)
+{
+	if (!desc->len) {
+		desc->v_addr = NULL;
+		return -EINVAL;
+	}
+
+	desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
+					  &desc->p_addr, GFP_KERNEL);
+	return (desc->v_addr != NULL) ? 0 : -ENOMEM;
+}
+
+/*
+ * we have 8 bits used like this:
+ *
+ * 7 6 5 4 3 2 1 0
+ * | | | | | | | |
+ * | | | | | | +-+-------- AC queue (0-3)
+ * | | | | | |
+ * | +-+-+-+-+------------ HW queue ID
+ * |
+ * +---------------------- unused
+ */
+static inline void
+iwl_legacy_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
+{
+	BUG_ON(ac > 3);   /* only have 2 bits */
+	BUG_ON(hwq > 31); /* only use 5 bits */
+
+	txq->swq_id = (hwq << 2) | ac;
+}
+
+static inline void iwl_legacy_wake_queue(struct iwl_priv *priv,
+				  struct iwl_tx_queue *txq)
+{
+	u8 queue = txq->swq_id;
+	u8 ac = queue & 3;
+	u8 hwq = (queue >> 2) & 0x1f;
+
+	if (test_and_clear_bit(hwq, priv->queue_stopped))
+		if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
+			ieee80211_wake_queue(priv->hw, ac);
+}
+
+static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
+				  struct iwl_tx_queue *txq)
+{
+	u8 queue = txq->swq_id;
+	u8 ac = queue & 3;
+	u8 hwq = (queue >> 2) & 0x1f;
+
+	if (!test_and_set_bit(hwq, priv->queue_stopped))
+		if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
+			ieee80211_stop_queue(priv->hw, ac);
+}
+
+#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+
+static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
+{
+	clear_bit(STATUS_INT_ENABLED, &priv->status);
+
+	/* disable interrupts from uCode/NIC to host */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* acknowledge/clear/reset any interrupts still pending
+	 * from uCode or flow handler (Rx/Tx DMA) */
+	iwl_write32(priv, CSR_INT, 0xffffffff);
+	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+	IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
+}
+
+static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv)
+{
+	IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
+	set_bit(STATUS_INT_ENABLED, &priv->status);
+	iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
+}
+
+/**
+ * iwl_legacy_beacon_time_mask_low - mask of lower 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_legacy_beacon_time_mask_low(struct iwl_priv *priv,
+					   u16 tsf_bits)
+{
+	return (1 << tsf_bits) - 1;
+}
+
+/**
+ * iwl_legacy_beacon_time_mask_high - mask of higher 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_legacy_beacon_time_mask_high(struct iwl_priv *priv,
+					    u16 tsf_bits)
+{
+	return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
+}
+
+#endif				/* __iwl_legacy_helpers_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-io.h b/drivers/net/wireless/iwlegacy/iwl-io.h
new file mode 100644
index 0000000..5cc5d34
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-io.h
@@ -0,0 +1,545 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_io_h__
+#define __iwl_legacy_io_h__
+
+#include <linux/io.h>
+
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-devtrace.h"
+
+/*
+ * IO, register, and NIC memory access functions
+ *
+ * NOTE on naming convention and macro usage for these
+ *
+ * A single _ prefix before a an access function means that no state
+ * check or debug information is printed when that function is called.
+ *
+ * A double __ prefix before an access function means that state is checked
+ * and the current line number and caller function name are printed in addition
+ * to any other debug output.
+ *
+ * The non-prefixed name is the #define that maps the caller into a
+ * #define that provides the caller's name and __LINE__ to the double
+ * prefix version.
+ *
+ * If you wish to call the function without any debug or state checking,
+ * you should use the single _ prefix version (as is used by dependent IO
+ * routines, for example _iwl_legacy_read_direct32 calls the non-check version of
+ * _iwl_legacy_read32.)
+ *
+ * These declarations are *extremely* useful in quickly isolating code deltas
+ * which result in misconfiguration of the hardware I/O.  In combination with
+ * git-bisect and the IO debug level you can quickly determine the specific
+ * commit which breaks the IO sequence to the hardware.
+ *
+ */
+
+static inline void _iwl_legacy_write8(struct iwl_priv *priv, u32 ofs, u8 val)
+{
+	trace_iwlwifi_legacy_dev_iowrite8(priv, ofs, val);
+	iowrite8(val, priv->hw_base + ofs);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void
+__iwl_legacy_write8(const char *f, u32 l, struct iwl_priv *priv,
+				 u32 ofs, u8 val)
+{
+	IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l);
+	_iwl_legacy_write8(priv, ofs, val);
+}
+#define iwl_write8(priv, ofs, val) \
+	__iwl_legacy_write8(__FILE__, __LINE__, priv, ofs, val)
+#else
+#define iwl_write8(priv, ofs, val) _iwl_legacy_write8(priv, ofs, val)
+#endif
+
+
+static inline void _iwl_legacy_write32(struct iwl_priv *priv, u32 ofs, u32 val)
+{
+	trace_iwlwifi_legacy_dev_iowrite32(priv, ofs, val);
+	iowrite32(val, priv->hw_base + ofs);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void
+__iwl_legacy_write32(const char *f, u32 l, struct iwl_priv *priv,
+				 u32 ofs, u32 val)
+{
+	IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+	_iwl_legacy_write32(priv, ofs, val);
+}
+#define iwl_write32(priv, ofs, val) \
+	__iwl_legacy_write32(__FILE__, __LINE__, priv, ofs, val)
+#else
+#define iwl_write32(priv, ofs, val) _iwl_legacy_write32(priv, ofs, val)
+#endif
+
+static inline u32 _iwl_legacy_read32(struct iwl_priv *priv, u32 ofs)
+{
+	u32 val = ioread32(priv->hw_base + ofs);
+	trace_iwlwifi_legacy_dev_ioread32(priv, ofs, val);
+	return val;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline u32
+__iwl_legacy_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
+{
+	IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+	return _iwl_legacy_read32(priv, ofs);
+}
+#define iwl_read32(priv, ofs) __iwl_legacy_read32(__FILE__, __LINE__, priv, ofs)
+#else
+#define iwl_read32(p, o) _iwl_legacy_read32(p, o)
+#endif
+
+#define IWL_POLL_INTERVAL 10	/* microseconds */
+static inline int
+_iwl_legacy_poll_bit(struct iwl_priv *priv, u32 addr,
+				u32 bits, u32 mask, int timeout)
+{
+	int t = 0;
+
+	do {
+		if ((_iwl_legacy_read32(priv, addr) & mask) == (bits & mask))
+			return t;
+		udelay(IWL_POLL_INTERVAL);
+		t += IWL_POLL_INTERVAL;
+	} while (t < timeout);
+
+	return -ETIMEDOUT;
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline int __iwl_legacy_poll_bit(const char *f, u32 l,
+				 struct iwl_priv *priv, u32 addr,
+				 u32 bits, u32 mask, int timeout)
+{
+	int ret = _iwl_legacy_poll_bit(priv, addr, bits, mask, timeout);
+	IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
+		     addr, bits, mask,
+		     unlikely(ret  == -ETIMEDOUT) ? "timeout" : "", f, l);
+	return ret;
+}
+#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
+	__iwl_legacy_poll_bit(__FILE__, __LINE__, priv, addr, \
+	bits, mask, timeout)
+#else
+#define iwl_poll_bit(p, a, b, m, t) _iwl_legacy_poll_bit(p, a, b, m, t)
+#endif
+
+static inline void _iwl_legacy_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	_iwl_legacy_write32(priv, reg, _iwl_legacy_read32(priv, reg) | mask);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void __iwl_legacy_set_bit(const char *f, u32 l,
+				 struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	u32 val = _iwl_legacy_read32(priv, reg) | mask;
+	IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg,
+							mask, val);
+	_iwl_legacy_write32(priv, reg, val);
+}
+static inline void iwl_legacy_set_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	__iwl_legacy_set_bit(__FILE__, __LINE__, p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#else
+static inline void iwl_legacy_set_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	_iwl_legacy_set_bit(p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#endif
+
+static inline void
+_iwl_legacy_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	_iwl_legacy_write32(priv, reg, _iwl_legacy_read32(priv, reg) & ~mask);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void
+__iwl_legacy_clear_bit(const char *f, u32 l,
+				   struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	u32 val = _iwl_legacy_read32(priv, reg) & ~mask;
+	IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+	_iwl_legacy_write32(priv, reg, val);
+}
+static inline void iwl_legacy_clear_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	__iwl_legacy_clear_bit(__FILE__, __LINE__, p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#else
+static inline void iwl_legacy_clear_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	_iwl_legacy_clear_bit(p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#endif
+
+static inline int _iwl_legacy_grab_nic_access(struct iwl_priv *priv)
+{
+	int ret;
+	u32 val;
+
+	/* this bit wakes up the NIC */
+	_iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+	/*
+	 * These bits say the device is running, and should keep running for
+	 * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
+	 * but they do not indicate that embedded SRAM is restored yet;
+	 * 3945 and 4965 have volatile SRAM, and must save/restore contents
+	 * to/from host DRAM when sleeping/waking for power-saving.
+	 * Each direction takes approximately 1/4 millisecond; with this
+	 * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
+	 * series of register accesses are expected (e.g. reading Event Log),
+	 * to keep device from sleeping.
+	 *
+	 * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
+	 * SRAM is okay/restored.  We don't check that here because this call
+	 * is just for hardware register access; but GP1 MAC_SLEEP check is a
+	 * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
+	 *
+	 */
+	ret = _iwl_legacy_poll_bit(priv, CSR_GP_CNTRL,
+			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+			    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
+	if (ret < 0) {
+		val = _iwl_legacy_read32(priv, CSR_GP_CNTRL);
+		IWL_ERR(priv,
+			"MAC is in deep sleep!.  CSR_GP_CNTRL = 0x%08X\n", val);
+		_iwl_legacy_write32(priv, CSR_RESET,
+				CSR_RESET_REG_FLAG_FORCE_NMI);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline int __iwl_legacy_grab_nic_access(const char *f, u32 l,
+					       struct iwl_priv *priv)
+{
+	IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l);
+	return _iwl_legacy_grab_nic_access(priv);
+}
+#define iwl_grab_nic_access(priv) \
+	__iwl_legacy_grab_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl_grab_nic_access(priv) \
+	_iwl_legacy_grab_nic_access(priv)
+#endif
+
+static inline void _iwl_legacy_release_nic_access(struct iwl_priv *priv)
+{
+	_iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
+			CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void __iwl_legacy_release_nic_access(const char *f, u32 l,
+					    struct iwl_priv *priv)
+{
+
+	IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l);
+	_iwl_legacy_release_nic_access(priv);
+}
+#define iwl_release_nic_access(priv) \
+	__iwl_legacy_release_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl_release_nic_access(priv) \
+	_iwl_legacy_release_nic_access(priv)
+#endif
+
+static inline u32 _iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
+{
+	return _iwl_legacy_read32(priv, reg);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline u32 __iwl_legacy_read_direct32(const char *f, u32 l,
+					struct iwl_priv *priv, u32 reg)
+{
+	u32 value = _iwl_legacy_read_direct32(priv, reg);
+	IWL_DEBUG_IO(priv,
+			"read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value,
+		     f, l);
+	return value;
+}
+static inline u32 iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
+{
+	u32 value;
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	value = __iwl_legacy_read_direct32(__FILE__, __LINE__, priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+}
+
+#else
+static inline u32 iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
+{
+	u32 value;
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	value = _iwl_legacy_read_direct32(priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+
+}
+#endif
+
+static inline void _iwl_legacy_write_direct32(struct iwl_priv *priv,
+					 u32 reg, u32 value)
+{
+	_iwl_legacy_write32(priv, reg, value);
+}
+static inline void
+iwl_legacy_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_direct32(priv, reg, value);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline void iwl_legacy_write_reg_buf(struct iwl_priv *priv,
+					       u32 reg, u32 len, u32 *values)
+{
+	u32 count = sizeof(u32);
+
+	if ((priv != NULL) && (values != NULL)) {
+		for (; 0 < len; len -= count, reg += count, values++)
+			iwl_legacy_write_direct32(priv, reg, *values);
+	}
+}
+
+static inline int _iwl_legacy_poll_direct_bit(struct iwl_priv *priv, u32 addr,
+				       u32 mask, int timeout)
+{
+	int t = 0;
+
+	do {
+		if ((iwl_legacy_read_direct32(priv, addr) & mask) == mask)
+			return t;
+		udelay(IWL_POLL_INTERVAL);
+		t += IWL_POLL_INTERVAL;
+	} while (t < timeout);
+
+	return -ETIMEDOUT;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline int __iwl_legacy_poll_direct_bit(const char *f, u32 l,
+					    struct iwl_priv *priv,
+					    u32 addr, u32 mask, int timeout)
+{
+	int ret  = _iwl_legacy_poll_direct_bit(priv, addr, mask, timeout);
+
+	if (unlikely(ret == -ETIMEDOUT))
+		IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - "
+			     "timedout - %s %d\n", addr, mask, f, l);
+	else
+		IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
+			     "- %s %d\n", addr, mask, ret, f, l);
+	return ret;
+}
+#define iwl_poll_direct_bit(priv, addr, mask, timeout) \
+__iwl_legacy_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
+#else
+#define iwl_poll_direct_bit _iwl_legacy_poll_direct_bit
+#endif
+
+static inline u32 _iwl_legacy_read_prph(struct iwl_priv *priv, u32 reg)
+{
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+	rmb();
+	return _iwl_legacy_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
+}
+static inline u32 iwl_legacy_read_prph(struct iwl_priv *priv, u32 reg)
+{
+	unsigned long reg_flags;
+	u32 val;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	val = _iwl_legacy_read_prph(priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return val;
+}
+
+static inline void _iwl_legacy_write_prph(struct iwl_priv *priv,
+					     u32 addr, u32 val)
+{
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
+			      ((addr & 0x0000FFFF) | (3 << 24)));
+	wmb();
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
+}
+
+static inline void
+iwl_legacy_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_prph(priv, addr, val);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+#define _iwl_legacy_set_bits_prph(priv, reg, mask) \
+_iwl_legacy_write_prph(priv, reg, (_iwl_legacy_read_prph(priv, reg) | mask))
+
+static inline void
+iwl_legacy_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	_iwl_legacy_set_bits_prph(priv, reg, mask);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+#define _iwl_legacy_set_bits_mask_prph(priv, reg, bits, mask) \
+_iwl_legacy_write_prph(priv, reg,				\
+		 ((_iwl_legacy_read_prph(priv, reg) & mask) | bits))
+
+static inline void iwl_legacy_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
+				u32 bits, u32 mask)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	_iwl_legacy_set_bits_mask_prph(priv, reg, bits, mask);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline void iwl_legacy_clear_bits_prph(struct iwl_priv
+						 *priv, u32 reg, u32 mask)
+{
+	unsigned long reg_flags;
+	u32 val;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	val = _iwl_legacy_read_prph(priv, reg);
+	_iwl_legacy_write_prph(priv, reg, (val & ~mask));
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline u32 iwl_legacy_read_targ_mem(struct iwl_priv *priv, u32 addr)
+{
+	unsigned long reg_flags;
+	u32 value;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+	rmb();
+	value = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+}
+
+static inline void
+iwl_legacy_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+		wmb();
+		_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline void
+iwl_legacy_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
+					  u32 len, u32 *values)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+		wmb();
+		for (; 0 < len; len -= sizeof(u32), values++)
+			_iwl_legacy_write_direct32(priv,
+					HBUS_TARG_MEM_WDAT, *values);
+
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.c b/drivers/net/wireless/iwlegacy/iwl-led.c
new file mode 100644
index 0000000..15eb8b7
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-led.c
@@ -0,0 +1,188 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* default: IWL_LED_BLINK(0) using blinking index table */
+static int led_mode;
+module_param(led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+		"1=On(RF On)/Off(RF Off), 2=blinking");
+
+static const struct ieee80211_tpt_blink iwl_blink[] = {
+	{ .throughput = 0 * 1024 - 1, .blink_time = 334 },
+	{ .throughput = 1 * 1024 - 1, .blink_time = 260 },
+	{ .throughput = 5 * 1024 - 1, .blink_time = 220 },
+	{ .throughput = 10 * 1024 - 1, .blink_time = 190 },
+	{ .throughput = 20 * 1024 - 1, .blink_time = 170 },
+	{ .throughput = 50 * 1024 - 1, .blink_time = 150 },
+	{ .throughput = 70 * 1024 - 1, .blink_time = 130 },
+	{ .throughput = 100 * 1024 - 1, .blink_time = 110 },
+	{ .throughput = 200 * 1024 - 1, .blink_time = 80 },
+	{ .throughput = 300 * 1024 - 1, .blink_time = 50 },
+};
+
+/*
+ * Adjust led blink rate to compensate on a MAC Clock difference on every HW
+ * Led blink rate analysis showed an average deviation of 0% on 3945,
+ * 5% on 4965 HW.
+ * Need to compensate on the led on/off time per HW according to the deviation
+ * to achieve the desired led frequency
+ * The calculation is: (100-averageDeviation)/100 * blinkTime
+ * For code efficiency the calculation will be:
+ *     compensation = (100 - averageDeviation) * 64 / 100
+ *     NewBlinkTime = (compensation * BlinkTime) / 64
+ */
+static inline u8 iwl_legacy_blink_compensation(struct iwl_priv *priv,
+				    u8 time, u16 compensation)
+{
+	if (!compensation) {
+		IWL_ERR(priv, "undefined blink compensation: "
+			"use pre-defined blinking time\n");
+		return time;
+	}
+
+	return (u8)((time * compensation) >> 6);
+}
+
+/* Set led pattern command */
+static int iwl_legacy_led_cmd(struct iwl_priv *priv,
+		       unsigned long on,
+		       unsigned long off)
+{
+	struct iwl_led_cmd led_cmd = {
+		.id = IWL_LED_LINK,
+		.interval = IWL_DEF_LED_INTRVL
+	};
+	int ret;
+
+	if (!test_bit(STATUS_READY, &priv->status))
+		return -EBUSY;
+
+	if (priv->blink_on == on && priv->blink_off == off)
+		return 0;
+
+	IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
+			priv->cfg->base_params->led_compensation);
+	led_cmd.on = iwl_legacy_blink_compensation(priv, on,
+				priv->cfg->base_params->led_compensation);
+	led_cmd.off = iwl_legacy_blink_compensation(priv, off,
+				priv->cfg->base_params->led_compensation);
+
+	ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
+	if (!ret) {
+		priv->blink_on = on;
+		priv->blink_off = off;
+	}
+	return ret;
+}
+
+static void iwl_legacy_led_brightness_set(struct led_classdev *led_cdev,
+				   enum led_brightness brightness)
+{
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
+	unsigned long on = 0;
+
+	if (brightness > 0)
+		on = IWL_LED_SOLID;
+
+	iwl_legacy_led_cmd(priv, on, 0);
+}
+
+static int iwl_legacy_led_blink_set(struct led_classdev *led_cdev,
+			     unsigned long *delay_on,
+			     unsigned long *delay_off)
+{
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
+
+	return iwl_legacy_led_cmd(priv, *delay_on, *delay_off);
+}
+
+void iwl_legacy_leds_init(struct iwl_priv *priv)
+{
+	int mode = led_mode;
+	int ret;
+
+	if (mode == IWL_LED_DEFAULT)
+		mode = priv->cfg->led_mode;
+
+	priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
+				   wiphy_name(priv->hw->wiphy));
+	priv->led.brightness_set = iwl_legacy_led_brightness_set;
+	priv->led.blink_set = iwl_legacy_led_blink_set;
+	priv->led.max_brightness = 1;
+
+	switch (mode) {
+	case IWL_LED_DEFAULT:
+		WARN_ON(1);
+		break;
+	case IWL_LED_BLINK:
+		priv->led.default_trigger =
+			ieee80211_create_tpt_led_trigger(priv->hw,
+					IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
+					iwl_blink, ARRAY_SIZE(iwl_blink));
+		break;
+	case IWL_LED_RF_STATE:
+		priv->led.default_trigger =
+			ieee80211_get_radio_led_name(priv->hw);
+		break;
+	}
+
+	ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+	if (ret) {
+		kfree(priv->led.name);
+		return;
+	}
+
+	priv->led_registered = true;
+}
+EXPORT_SYMBOL(iwl_legacy_leds_init);
+
+void iwl_legacy_leds_exit(struct iwl_priv *priv)
+{
+	if (!priv->led_registered)
+		return;
+
+	led_classdev_unregister(&priv->led);
+	kfree(priv->led.name);
+}
+EXPORT_SYMBOL(iwl_legacy_leds_exit);
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.h b/drivers/net/wireless/iwlegacy/iwl-led.h
new file mode 100644
index 0000000..f0791f7
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-led.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_leds_h__
+#define __iwl_legacy_leds_h__
+
+
+struct iwl_priv;
+
+#define IWL_LED_SOLID 11
+#define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
+
+#define IWL_LED_ACTIVITY       (0<<1)
+#define IWL_LED_LINK           (1<<1)
+
+/*
+ * LED mode
+ *    IWL_LED_DEFAULT:  use device default
+ *    IWL_LED_RF_STATE: turn LED on/off based on RF state
+ *			LED ON  = RF ON
+ *			LED OFF = RF OFF
+ *    IWL_LED_BLINK:    adjust led blink rate based on blink table
+ */
+enum iwl_led_mode {
+	IWL_LED_DEFAULT,
+	IWL_LED_RF_STATE,
+	IWL_LED_BLINK,
+};
+
+void iwl_legacy_leds_init(struct iwl_priv *priv);
+void iwl_legacy_leds_exit(struct iwl_priv *priv);
+
+#endif /* __iwl_legacy_leds_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h b/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h
new file mode 100644
index 0000000..38647e4
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h
@@ -0,0 +1,456 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_rs_h__
+#define __iwl_legacy_rs_h__
+
+struct iwl_rate_info {
+	u8 plcp;	/* uCode API:  IWL_RATE_6M_PLCP, etc. */
+	u8 plcp_siso;	/* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */
+	u8 plcp_mimo2;	/* uCode API:  IWL_RATE_MIMO2_6M_PLCP, etc. */
+	u8 ieee;	/* MAC header:  IWL_RATE_6M_IEEE, etc. */
+	u8 prev_ieee;    /* previous rate in IEEE speeds */
+	u8 next_ieee;    /* next rate in IEEE speeds */
+	u8 prev_rs;      /* previous rate used in rs algo */
+	u8 next_rs;      /* next rate used in rs algo */
+	u8 prev_rs_tgg;  /* previous rate used in TGG rs algo */
+	u8 next_rs_tgg;  /* next rate used in TGG rs algo */
+};
+
+struct iwl3945_rate_info {
+	u8 plcp;		/* uCode API:  IWL_RATE_6M_PLCP, etc. */
+	u8 ieee;		/* MAC header:  IWL_RATE_6M_IEEE, etc. */
+	u8 prev_ieee;		/* previous rate in IEEE speeds */
+	u8 next_ieee;		/* next rate in IEEE speeds */
+	u8 prev_rs;		/* previous rate used in rs algo */
+	u8 next_rs;		/* next rate used in rs algo */
+	u8 prev_rs_tgg;		/* previous rate used in TGG rs algo */
+	u8 next_rs_tgg;		/* next rate used in TGG rs algo */
+	u8 table_rs_index;	/* index in rate scale table cmd */
+	u8 prev_table_rs;	/* prev in rate table cmd */
+};
+
+
+/*
+ * These serve as indexes into
+ * struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT];
+ */
+enum {
+	IWL_RATE_1M_INDEX = 0,
+	IWL_RATE_2M_INDEX,
+	IWL_RATE_5M_INDEX,
+	IWL_RATE_11M_INDEX,
+	IWL_RATE_6M_INDEX,
+	IWL_RATE_9M_INDEX,
+	IWL_RATE_12M_INDEX,
+	IWL_RATE_18M_INDEX,
+	IWL_RATE_24M_INDEX,
+	IWL_RATE_36M_INDEX,
+	IWL_RATE_48M_INDEX,
+	IWL_RATE_54M_INDEX,
+	IWL_RATE_60M_INDEX,
+	IWL_RATE_COUNT,
+	IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1,	/* Excluding 60M */
+	IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1,
+	IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
+	IWL_RATE_INVALID = IWL_RATE_COUNT,
+};
+
+enum {
+	IWL_RATE_6M_INDEX_TABLE = 0,
+	IWL_RATE_9M_INDEX_TABLE,
+	IWL_RATE_12M_INDEX_TABLE,
+	IWL_RATE_18M_INDEX_TABLE,
+	IWL_RATE_24M_INDEX_TABLE,
+	IWL_RATE_36M_INDEX_TABLE,
+	IWL_RATE_48M_INDEX_TABLE,
+	IWL_RATE_54M_INDEX_TABLE,
+	IWL_RATE_1M_INDEX_TABLE,
+	IWL_RATE_2M_INDEX_TABLE,
+	IWL_RATE_5M_INDEX_TABLE,
+	IWL_RATE_11M_INDEX_TABLE,
+	IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1,
+};
+
+enum {
+	IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
+	IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
+	IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
+	IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
+	IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
+};
+
+/* #define vs. enum to keep from defaulting to 'large integer' */
+#define	IWL_RATE_6M_MASK   (1 << IWL_RATE_6M_INDEX)
+#define	IWL_RATE_9M_MASK   (1 << IWL_RATE_9M_INDEX)
+#define	IWL_RATE_12M_MASK  (1 << IWL_RATE_12M_INDEX)
+#define	IWL_RATE_18M_MASK  (1 << IWL_RATE_18M_INDEX)
+#define	IWL_RATE_24M_MASK  (1 << IWL_RATE_24M_INDEX)
+#define	IWL_RATE_36M_MASK  (1 << IWL_RATE_36M_INDEX)
+#define	IWL_RATE_48M_MASK  (1 << IWL_RATE_48M_INDEX)
+#define	IWL_RATE_54M_MASK  (1 << IWL_RATE_54M_INDEX)
+#define IWL_RATE_60M_MASK  (1 << IWL_RATE_60M_INDEX)
+#define	IWL_RATE_1M_MASK   (1 << IWL_RATE_1M_INDEX)
+#define	IWL_RATE_2M_MASK   (1 << IWL_RATE_2M_INDEX)
+#define	IWL_RATE_5M_MASK   (1 << IWL_RATE_5M_INDEX)
+#define	IWL_RATE_11M_MASK  (1 << IWL_RATE_11M_INDEX)
+
+/* uCode API values for legacy bit rates, both OFDM and CCK */
+enum {
+	IWL_RATE_6M_PLCP  = 13,
+	IWL_RATE_9M_PLCP  = 15,
+	IWL_RATE_12M_PLCP = 5,
+	IWL_RATE_18M_PLCP = 7,
+	IWL_RATE_24M_PLCP = 9,
+	IWL_RATE_36M_PLCP = 11,
+	IWL_RATE_48M_PLCP = 1,
+	IWL_RATE_54M_PLCP = 3,
+	IWL_RATE_60M_PLCP = 3,/*FIXME:RS:should be removed*/
+	IWL_RATE_1M_PLCP  = 10,
+	IWL_RATE_2M_PLCP  = 20,
+	IWL_RATE_5M_PLCP  = 55,
+	IWL_RATE_11M_PLCP = 110,
+	/*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/
+};
+
+/* uCode API values for OFDM high-throughput (HT) bit rates */
+enum {
+	IWL_RATE_SISO_6M_PLCP = 0,
+	IWL_RATE_SISO_12M_PLCP = 1,
+	IWL_RATE_SISO_18M_PLCP = 2,
+	IWL_RATE_SISO_24M_PLCP = 3,
+	IWL_RATE_SISO_36M_PLCP = 4,
+	IWL_RATE_SISO_48M_PLCP = 5,
+	IWL_RATE_SISO_54M_PLCP = 6,
+	IWL_RATE_SISO_60M_PLCP = 7,
+	IWL_RATE_MIMO2_6M_PLCP  = 0x8,
+	IWL_RATE_MIMO2_12M_PLCP = 0x9,
+	IWL_RATE_MIMO2_18M_PLCP = 0xa,
+	IWL_RATE_MIMO2_24M_PLCP = 0xb,
+	IWL_RATE_MIMO2_36M_PLCP = 0xc,
+	IWL_RATE_MIMO2_48M_PLCP = 0xd,
+	IWL_RATE_MIMO2_54M_PLCP = 0xe,
+	IWL_RATE_MIMO2_60M_PLCP = 0xf,
+	IWL_RATE_SISO_INVM_PLCP,
+	IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
+};
+
+/* MAC header values for bit rates */
+enum {
+	IWL_RATE_6M_IEEE  = 12,
+	IWL_RATE_9M_IEEE  = 18,
+	IWL_RATE_12M_IEEE = 24,
+	IWL_RATE_18M_IEEE = 36,
+	IWL_RATE_24M_IEEE = 48,
+	IWL_RATE_36M_IEEE = 72,
+	IWL_RATE_48M_IEEE = 96,
+	IWL_RATE_54M_IEEE = 108,
+	IWL_RATE_60M_IEEE = 120,
+	IWL_RATE_1M_IEEE  = 2,
+	IWL_RATE_2M_IEEE  = 4,
+	IWL_RATE_5M_IEEE  = 11,
+	IWL_RATE_11M_IEEE = 22,
+};
+
+#define IWL_CCK_BASIC_RATES_MASK    \
+	(IWL_RATE_1M_MASK          | \
+	IWL_RATE_2M_MASK)
+
+#define IWL_CCK_RATES_MASK          \
+	(IWL_CCK_BASIC_RATES_MASK  | \
+	IWL_RATE_5M_MASK          | \
+	IWL_RATE_11M_MASK)
+
+#define IWL_OFDM_BASIC_RATES_MASK   \
+	(IWL_RATE_6M_MASK         | \
+	IWL_RATE_12M_MASK         | \
+	IWL_RATE_24M_MASK)
+
+#define IWL_OFDM_RATES_MASK         \
+	(IWL_OFDM_BASIC_RATES_MASK | \
+	IWL_RATE_9M_MASK          | \
+	IWL_RATE_18M_MASK         | \
+	IWL_RATE_36M_MASK         | \
+	IWL_RATE_48M_MASK         | \
+	IWL_RATE_54M_MASK)
+
+#define IWL_BASIC_RATES_MASK         \
+	(IWL_OFDM_BASIC_RATES_MASK | \
+	 IWL_CCK_BASIC_RATES_MASK)
+
+#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
+#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1)
+
+#define IWL_INVALID_VALUE    -1
+
+#define IWL_MIN_RSSI_VAL                 -100
+#define IWL_MAX_RSSI_VAL                    0
+
+/* These values specify how many Tx frame attempts before
+ * searching for a new modulation mode */
+#define IWL_LEGACY_FAILURE_LIMIT	160
+#define IWL_LEGACY_SUCCESS_LIMIT	480
+#define IWL_LEGACY_TABLE_COUNT		160
+
+#define IWL_NONE_LEGACY_FAILURE_LIMIT	400
+#define IWL_NONE_LEGACY_SUCCESS_LIMIT	4500
+#define IWL_NONE_LEGACY_TABLE_COUNT	1500
+
+/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */
+#define IWL_RS_GOOD_RATIO		12800	/* 100% */
+#define IWL_RATE_SCALE_SWITCH		10880	/*  85% */
+#define IWL_RATE_HIGH_TH		10880	/*  85% */
+#define IWL_RATE_INCREASE_TH		6400	/*  50% */
+#define IWL_RATE_DECREASE_TH		1920	/*  15% */
+
+/* possible actions when in legacy mode */
+#define IWL_LEGACY_SWITCH_ANTENNA1      0
+#define IWL_LEGACY_SWITCH_ANTENNA2      1
+#define IWL_LEGACY_SWITCH_SISO          2
+#define IWL_LEGACY_SWITCH_MIMO2_AB      3
+#define IWL_LEGACY_SWITCH_MIMO2_AC      4
+#define IWL_LEGACY_SWITCH_MIMO2_BC      5
+
+/* possible actions when in siso mode */
+#define IWL_SISO_SWITCH_ANTENNA1        0
+#define IWL_SISO_SWITCH_ANTENNA2        1
+#define IWL_SISO_SWITCH_MIMO2_AB        2
+#define IWL_SISO_SWITCH_MIMO2_AC        3
+#define IWL_SISO_SWITCH_MIMO2_BC        4
+#define IWL_SISO_SWITCH_GI              5
+
+/* possible actions when in mimo mode */
+#define IWL_MIMO2_SWITCH_ANTENNA1       0
+#define IWL_MIMO2_SWITCH_ANTENNA2       1
+#define IWL_MIMO2_SWITCH_SISO_A         2
+#define IWL_MIMO2_SWITCH_SISO_B         3
+#define IWL_MIMO2_SWITCH_SISO_C         4
+#define IWL_MIMO2_SWITCH_GI             5
+
+#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI
+
+#define IWL_ACTION_LIMIT		3	/* # possible actions */
+
+#define LQ_SIZE		2	/* 2 mode tables:  "Active" and "Search" */
+
+/* load per tid defines for A-MPDU activation */
+#define IWL_AGG_TPT_THREHOLD	0
+#define IWL_AGG_LOAD_THRESHOLD	10
+#define IWL_AGG_ALL_TID		0xff
+#define TID_QUEUE_CELL_SPACING	50	/*mS */
+#define TID_QUEUE_MAX_SIZE	20
+#define TID_ROUND_VALUE		5	/* mS */
+#define TID_MAX_LOAD_COUNT	8
+
+#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
+#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
+
+extern const struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT];
+
+enum iwl_table_type {
+	LQ_NONE,
+	LQ_G,		/* legacy types */
+	LQ_A,
+	LQ_SISO,	/* high-throughput types */
+	LQ_MIMO2,
+	LQ_MAX,
+};
+
+#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
+#define is_siso(tbl) ((tbl) == LQ_SISO)
+#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
+#define is_mimo(tbl) (is_mimo2(tbl))
+#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
+#define is_a_band(tbl) ((tbl) == LQ_A)
+#define is_g_and(tbl) ((tbl) == LQ_G)
+
+#define	ANT_NONE	0x0
+#define	ANT_A		BIT(0)
+#define	ANT_B		BIT(1)
+#define	ANT_AB		(ANT_A | ANT_B)
+#define ANT_C		BIT(2)
+#define	ANT_AC		(ANT_A | ANT_C)
+#define ANT_BC		(ANT_B | ANT_C)
+#define ANT_ABC		(ANT_AB | ANT_C)
+
+#define IWL_MAX_MCS_DISPLAY_SIZE	12
+
+struct iwl_rate_mcs_info {
+	char	mbps[IWL_MAX_MCS_DISPLAY_SIZE];
+	char	mcs[IWL_MAX_MCS_DISPLAY_SIZE];
+};
+
+/**
+ * struct iwl_rate_scale_data -- tx success history for one rate
+ */
+struct iwl_rate_scale_data {
+	u64 data;		/* bitmap of successful frames */
+	s32 success_counter;	/* number of frames successful */
+	s32 success_ratio;	/* per-cent * 128  */
+	s32 counter;		/* number of frames attempted */
+	s32 average_tpt;	/* success ratio * expected throughput */
+	unsigned long stamp;
+};
+
+/**
+ * struct iwl_scale_tbl_info -- tx params and success history for all rates
+ *
+ * There are two of these in struct iwl_lq_sta,
+ * one for "active", and one for "search".
+ */
+struct iwl_scale_tbl_info {
+	enum iwl_table_type lq_type;
+	u8 ant_type;
+	u8 is_SGI;	/* 1 = short guard interval */
+	u8 is_ht40;	/* 1 = 40 MHz channel width */
+	u8 is_dup;	/* 1 = duplicated data streams */
+	u8 action;	/* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
+	u8 max_search;	/* maximun number of tables we can search */
+	s32 *expected_tpt;	/* throughput metrics; expected_tpt_G, etc. */
+	u32 current_rate;  /* rate_n_flags, uCode API format */
+	struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
+};
+
+struct iwl_traffic_load {
+	unsigned long time_stamp;	/* age of the oldest statistics */
+	u32 packet_count[TID_QUEUE_MAX_SIZE];   /* packet count in this time
+						 * slice */
+	u32 total;			/* total num of packets during the
+					 * last TID_MAX_TIME_DIFF */
+	u8 queue_count;			/* number of queues that has
+					 * been used since the last cleanup */
+	u8 head;			/* start of the circular buffer */
+};
+
+/**
+ * struct iwl_lq_sta -- driver's rate scaling private structure
+ *
+ * Pointer to this gets passed back and forth between driver and mac80211.
+ */
+struct iwl_lq_sta {
+	u8 active_tbl;		/* index of active table, range 0-1 */
+	u8 enable_counter;	/* indicates HT mode */
+	u8 stay_in_tbl;		/* 1: disallow, 0: allow search for new mode */
+	u8 search_better_tbl;	/* 1: currently trying alternate mode */
+	s32 last_tpt;
+
+	/* The following determine when to search for a new mode */
+	u32 table_count_limit;
+	u32 max_failure_limit;	/* # failed frames before new search */
+	u32 max_success_limit;	/* # successful frames before new search */
+	u32 table_count;
+	u32 total_failed;	/* total failed frames, any/all rates */
+	u32 total_success;	/* total successful frames, any/all rates */
+	u64 flush_timer;	/* time staying in mode before new search */
+
+	u8 action_counter;	/* # mode-switch actions tried */
+	u8 is_green;
+	u8 is_dup;
+	enum ieee80211_band band;
+
+	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
+	u32 supp_rates;
+	u16 active_legacy_rate;
+	u16 active_siso_rate;
+	u16 active_mimo2_rate;
+	s8 max_rate_idx;     /* Max rate set by user */
+	u8 missed_rate_counter;
+
+	struct iwl_link_quality_cmd lq;
+	struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
+	struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
+	u8 tx_agg_tid_en;
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *rs_sta_dbgfs_scale_table_file;
+	struct dentry *rs_sta_dbgfs_stats_table_file;
+	struct dentry *rs_sta_dbgfs_rate_scale_data_file;
+	struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
+	u32 dbg_fixed_rate;
+#endif
+	struct iwl_priv *drv;
+
+	/* used to be in sta_info */
+	int last_txrate_idx;
+	/* last tx rate_n_flags */
+	u32 last_rate_n_flags;
+	/* packets destined for this STA are aggregated */
+	u8 is_agg;
+};
+
+static inline u8 iwl4965_num_of_ant(u8 mask)
+{
+	return  !!((mask) & ANT_A) +
+		!!((mask) & ANT_B) +
+		!!((mask) & ANT_C);
+}
+
+static inline u8 iwl4965_first_antenna(u8 mask)
+{
+	if (mask & ANT_A)
+		return ANT_A;
+	if (mask & ANT_B)
+		return ANT_B;
+	return ANT_C;
+}
+
+
+/**
+ * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
+ *
+ * The specific throughput table used is based on the type of network
+ * the associated with, including A, B, G, and G w/ TGG protection
+ */
+extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+
+/* Initialize station's rate scaling information after adding station */
+extern void iwl4965_rs_rate_init(struct iwl_priv *priv,
+			     struct ieee80211_sta *sta, u8 sta_id);
+extern void iwl3945_rs_rate_init(struct iwl_priv *priv,
+				 struct ieee80211_sta *sta, u8 sta_id);
+
+/**
+ * iwl_rate_control_register - Register the rate control algorithm callbacks
+ *
+ * Since the rate control algorithm is hardware specific, there is no need
+ * or reason to place it as a stand alone module.  The driver can call
+ * iwl_rate_control_register in order to register the rate control callbacks
+ * with the mac80211 subsystem.  This should be performed prior to calling
+ * ieee80211_register_hw
+ *
+ */
+extern int iwl4965_rate_control_register(void);
+extern int iwl3945_rate_control_register(void);
+
+/**
+ * iwl_rate_control_unregister - Unregister the rate control callbacks
+ *
+ * This should be called after calling ieee80211_unregister_hw, but before
+ * the driver is unloaded.
+ */
+extern void iwl4965_rate_control_unregister(void);
+extern void iwl3945_rate_control_unregister(void);
+
+#endif /* __iwl_legacy_rs__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-power.c b/drivers/net/wireless/iwlegacy/iwl-power.c
new file mode 100644
index 0000000..903ef0d
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-power.c
@@ -0,0 +1,165 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-commands.h"
+#include "iwl-debug.h"
+#include "iwl-power.h"
+
+/*
+ * Setting power level allows the card to go to sleep when not busy.
+ *
+ * We calculate a sleep command based on the required latency, which
+ * we get from mac80211. In order to handle thermal throttling, we can
+ * also use pre-defined power levels.
+ */
+
+/*
+ * This defines the old power levels. They are still used by default
+ * (level 1) and for thermal throttle (levels 3 through 5)
+ */
+
+struct iwl_power_vec_entry {
+	struct iwl_powertable_cmd cmd;
+	u8 no_dtim;	/* number of skip dtim */
+};
+
+static void iwl_legacy_power_sleep_cam_cmd(struct iwl_priv *priv,
+				    struct iwl_powertable_cmd *cmd)
+{
+	memset(cmd, 0, sizeof(*cmd));
+
+	if (priv->power_data.pci_pm)
+		cmd->flags |= IWL_POWER_PCI_PM_MSK;
+
+	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
+}
+
+static int
+iwl_legacy_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
+{
+	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
+	IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
+	IWL_DEBUG_POWER(priv, "Tx timeout = %u\n",
+					le32_to_cpu(cmd->tx_data_timeout));
+	IWL_DEBUG_POWER(priv, "Rx timeout = %u\n",
+					le32_to_cpu(cmd->rx_data_timeout));
+	IWL_DEBUG_POWER(priv,
+			"Sleep interval vector = { %d , %d , %d , %d , %d }\n",
+			le32_to_cpu(cmd->sleep_interval[0]),
+			le32_to_cpu(cmd->sleep_interval[1]),
+			le32_to_cpu(cmd->sleep_interval[2]),
+			le32_to_cpu(cmd->sleep_interval[3]),
+			le32_to_cpu(cmd->sleep_interval[4]));
+
+	return iwl_legacy_send_cmd_pdu(priv, POWER_TABLE_CMD,
+				sizeof(struct iwl_powertable_cmd), cmd);
+}
+
+int
+iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force)
+{
+	int ret;
+	bool update_chains;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/* Don't update the RX chain when chain noise calibration is running */
+	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
+			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
+
+	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
+		return 0;
+
+	if (!iwl_legacy_is_ready_rf(priv))
+		return -EIO;
+
+	/* scan complete use sleep_power_next, need to be updated */
+	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
+		return 0;
+	}
+
+	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
+		set_bit(STATUS_POWER_PMI, &priv->status);
+
+	ret = iwl_legacy_set_power(priv, cmd);
+	if (!ret) {
+		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
+			clear_bit(STATUS_POWER_PMI, &priv->status);
+
+		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
+			priv->cfg->ops->lib->update_chain_flags(priv);
+		else if (priv->cfg->ops->lib->update_chain_flags)
+			IWL_DEBUG_POWER(priv,
+					"Cannot update the power, chain noise "
+					"calibration running: %d\n",
+					priv->chain_noise_data.state);
+
+		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
+	} else
+		IWL_ERR(priv, "set power fail, ret = %d", ret);
+
+	return ret;
+}
+
+int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force)
+{
+	struct iwl_powertable_cmd cmd;
+
+	iwl_legacy_power_sleep_cam_cmd(priv, &cmd);
+	return iwl_legacy_power_set_mode(priv, &cmd, force);
+}
+EXPORT_SYMBOL(iwl_legacy_power_update_mode);
+
+/* initialize to default */
+void iwl_legacy_power_initialize(struct iwl_priv *priv)
+{
+	u16 lctl = iwl_legacy_pcie_link_ctl(priv);
+
+	priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+
+	priv->power_data.debug_sleep_level_override = -1;
+
+	memset(&priv->power_data.sleep_cmd, 0,
+		sizeof(priv->power_data.sleep_cmd));
+}
+EXPORT_SYMBOL(iwl_legacy_power_initialize);
diff --git a/drivers/net/wireless/iwlegacy/iwl-power.h b/drivers/net/wireless/iwlegacy/iwl-power.h
new file mode 100644
index 0000000..d30b36a
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-power.h
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#ifndef __iwl_legacy_power_setting_h__
+#define __iwl_legacy_power_setting_h__
+
+#include "iwl-commands.h"
+
+enum iwl_power_level {
+	IWL_POWER_INDEX_1,
+	IWL_POWER_INDEX_2,
+	IWL_POWER_INDEX_3,
+	IWL_POWER_INDEX_4,
+	IWL_POWER_INDEX_5,
+	IWL_POWER_NUM
+};
+
+struct iwl_power_mgr {
+	struct iwl_powertable_cmd sleep_cmd;
+	struct iwl_powertable_cmd sleep_cmd_next;
+	int debug_sleep_level_override;
+	bool pci_pm;
+};
+
+int
+iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force);
+int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force);
+void iwl_legacy_power_initialize(struct iwl_priv *priv);
+
+#endif  /* __iwl_legacy_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-prph.h b/drivers/net/wireless/iwlegacy/iwl-prph.h
new file mode 100644
index 0000000..30a4930
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-prph.h
@@ -0,0 +1,523 @@
+/******************************************************************************
+ *
+ * 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) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef	__iwl_legacy_prph_h__
+#define __iwl_legacy_prph_h__
+
+/*
+ * Registers in this file are internal, not PCI bus memory mapped.
+ * Driver accesses these via HBUS_TARG_PRPH_* registers.
+ */
+#define PRPH_BASE	(0x00000)
+#define PRPH_END	(0xFFFFF)
+
+/* APMG (power management) constants */
+#define APMG_BASE			(PRPH_BASE + 0x3000)
+#define APMG_CLK_CTRL_REG		(APMG_BASE + 0x0000)
+#define APMG_CLK_EN_REG			(APMG_BASE + 0x0004)
+#define APMG_CLK_DIS_REG		(APMG_BASE + 0x0008)
+#define APMG_PS_CTRL_REG		(APMG_BASE + 0x000c)
+#define APMG_PCIDEV_STT_REG		(APMG_BASE + 0x0010)
+#define APMG_RFKILL_REG			(APMG_BASE + 0x0014)
+#define APMG_RTC_INT_STT_REG		(APMG_BASE + 0x001c)
+#define APMG_RTC_INT_MSK_REG		(APMG_BASE + 0x0020)
+#define APMG_DIGITAL_SVR_REG		(APMG_BASE + 0x0058)
+#define APMG_ANALOG_SVR_REG		(APMG_BASE + 0x006C)
+
+#define APMS_CLK_VAL_MRB_FUNC_MODE	(0x00000001)
+#define APMG_CLK_VAL_DMA_CLK_RQT	(0x00000200)
+#define APMG_CLK_VAL_BSM_CLK_RQT	(0x00000800)
+
+#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS	(0x00400000)
+#define APMG_PS_CTRL_VAL_RESET_REQ		(0x04000000)
+#define APMG_PS_CTRL_MSK_PWR_SRC		(0x03000000)
+#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN		(0x00000000)
+#define APMG_PS_CTRL_VAL_PWR_SRC_MAX		(0x01000000) /* 3945 only */
+#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX		(0x02000000)
+#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK	(0x000001E0) /* bit 8:5 */
+#define APMG_SVR_DIGITAL_VOLTAGE_1_32		(0x00000060)
+
+#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS		(0x00000800)
+
+/**
+ * BSM (Bootstrap State Machine)
+ *
+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+ * in special SRAM that does not power down when the embedded control
+ * processor is sleeping (e.g. for periodic power-saving shutdowns of radio).
+ *
+ * When powering back up after sleeps (or during initial uCode load), the BSM
+ * internally loads the short bootstrap program from the special SRAM into the
+ * embedded processor's instruction SRAM, and starts the processor so it runs
+ * the bootstrap program.
+ *
+ * This bootstrap program loads (via PCI busmaster DMA) instructions and data
+ * images for a uCode program from host DRAM locations.  The host driver
+ * indicates DRAM locations and sizes for instruction and data images via the
+ * four BSM_DRAM_* registers.  Once the bootstrap program loads the new program,
+ * the new program starts automatically.
+ *
+ * The uCode used for open-source drivers includes two programs:
+ *
+ * 1)  Initialization -- performs hardware calibration and sets up some
+ *     internal data, then notifies host via "initialize alive" notification
+ *     (struct iwl_init_alive_resp) that it has completed all of its work.
+ *     After signal from host, it then loads and starts the runtime program.
+ *     The initialization program must be used when initially setting up the
+ *     NIC after loading the driver.
+ *
+ * 2)  Runtime/Protocol -- performs all normal runtime operations.  This
+ *     notifies host via "alive" notification (struct iwl_alive_resp) that it
+ *     is ready to be used.
+ *
+ * When initializing the NIC, the host driver does the following procedure:
+ *
+ * 1)  Load bootstrap program (instructions only, no data image for bootstrap)
+ *     into bootstrap memory.  Use dword writes starting at BSM_SRAM_LOWER_BOUND
+ *
+ * 2)  Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction
+ *     images in host DRAM.
+ *
+ * 3)  Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked:
+ *     BSM_WR_MEM_SRC_REG = 0
+ *     BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND
+ *     BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image
+ *
+ * 4)  Load bootstrap into instruction SRAM:
+ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START
+ *
+ * 5)  Wait for load completion:
+ *     Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0
+ *
+ * 6)  Enable future boot loads whenever NIC's power management triggers it:
+ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN
+ *
+ * 7)  Start the NIC by removing all reset bits:
+ *     CSR_RESET = 0
+ *
+ *     The bootstrap uCode (already in instruction SRAM) loads initialization
+ *     uCode.  Initialization uCode performs data initialization, sends
+ *     "initialize alive" notification to host, and waits for a signal from
+ *     host to load runtime code.
+ *
+ * 4)  Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
+ *     images in host DRAM.  The last register loaded must be the instruction
+ *     byte count register ("1" in MSbit tells initialization uCode to load
+ *     the runtime uCode):
+ *     BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD
+ *
+ * 5)  Wait for "alive" notification, then issue normal runtime commands.
+ *
+ * Data caching during power-downs:
+ *
+ * Just before the embedded controller powers down (e.g for automatic
+ * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA)
+ * a current snapshot of the embedded processor's data SRAM into host DRAM.
+ * This caches the data while the embedded processor's memory is powered down.
+ * Location and size are controlled by BSM_DRAM_DATA_* registers.
+ *
+ * NOTE:  Instruction SRAM does not need to be saved, since that doesn't
+ *        change during operation; the original image (from uCode distribution
+ *        file) can be used for reload.
+ *
+ * When powering back up, the BSM loads the bootstrap program.  Bootstrap looks
+ * at the BSM_DRAM_* registers, which now point to the runtime instruction
+ * image and the cached (modified) runtime data (*not* the initialization
+ * uCode).  Bootstrap reloads these runtime images into SRAM, and restarts the
+ * uCode from where it left off before the power-down.
+ *
+ * NOTE:  Initialization uCode does *not* run as part of the save/restore
+ *        procedure.
+ *
+ * This save/restore method is mostly for autonomous power management during
+ * normal operation (result of POWER_TABLE_CMD).  Platform suspend/resume and
+ * RFKILL should use complete restarts (with total re-initialization) of uCode,
+ * allowing total shutdown (including BSM memory).
+ *
+ * Note that, during normal operation, the host DRAM that held the initial
+ * startup data for the runtime code is now being used as a backup data cache
+ * for modified data!  If you need to completely re-initialize the NIC, make
+ * sure that you use the runtime data image from the uCode distribution file,
+ * not the modified/saved runtime data.  You may want to store a separate
+ * "clean" runtime data image in DRAM to avoid disk reads of distribution file.
+ */
+
+/* BSM bit fields */
+#define BSM_WR_CTRL_REG_BIT_START     (0x80000000) /* start boot load now */
+#define BSM_WR_CTRL_REG_BIT_START_EN  (0x40000000) /* enable boot after pwrup*/
+#define BSM_DRAM_INST_LOAD            (0x80000000) /* start program load now */
+
+/* BSM addresses */
+#define BSM_BASE                     (PRPH_BASE + 0x3400)
+#define BSM_END                      (PRPH_BASE + 0x3800)
+
+#define BSM_WR_CTRL_REG              (BSM_BASE + 0x000) /* ctl and status */
+#define BSM_WR_MEM_SRC_REG           (BSM_BASE + 0x004) /* source in BSM mem */
+#define BSM_WR_MEM_DST_REG           (BSM_BASE + 0x008) /* dest in SRAM mem */
+#define BSM_WR_DWCOUNT_REG           (BSM_BASE + 0x00C) /* bytes */
+#define BSM_WR_STATUS_REG            (BSM_BASE + 0x010) /* bit 0:  1 == done */
+
+/*
+ * Pointers and size regs for bootstrap load and data SRAM save/restore.
+ * NOTE:  3945 pointers use bits 31:0 of DRAM address.
+ *        4965 pointers use bits 35:4 of DRAM address.
+ */
+#define BSM_DRAM_INST_PTR_REG        (BSM_BASE + 0x090)
+#define BSM_DRAM_INST_BYTECOUNT_REG  (BSM_BASE + 0x094)
+#define BSM_DRAM_DATA_PTR_REG        (BSM_BASE + 0x098)
+#define BSM_DRAM_DATA_BYTECOUNT_REG  (BSM_BASE + 0x09C)
+
+/*
+ * BSM special memory, stays powered on during power-save sleeps.
+ * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1)
+ */
+#define BSM_SRAM_LOWER_BOUND         (PRPH_BASE + 0x3800)
+#define BSM_SRAM_SIZE			(1024) /* bytes */
+
+
+/* 3945 Tx scheduler registers */
+#define ALM_SCD_BASE                        (PRPH_BASE + 0x2E00)
+#define ALM_SCD_MODE_REG                    (ALM_SCD_BASE + 0x000)
+#define ALM_SCD_ARASTAT_REG                 (ALM_SCD_BASE + 0x004)
+#define ALM_SCD_TXFACT_REG                  (ALM_SCD_BASE + 0x010)
+#define ALM_SCD_TXF4MF_REG                  (ALM_SCD_BASE + 0x014)
+#define ALM_SCD_TXF5MF_REG                  (ALM_SCD_BASE + 0x020)
+#define ALM_SCD_SBYP_MODE_1_REG             (ALM_SCD_BASE + 0x02C)
+#define ALM_SCD_SBYP_MODE_2_REG             (ALM_SCD_BASE + 0x030)
+
+/**
+ * Tx Scheduler
+ *
+ * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
+ * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
+ * host DRAM.  It steers each frame's Tx command (which contains the frame
+ * data) into one of up to 7 prioritized Tx DMA FIFO channels within the
+ * device.  A queue maps to only one (selectable by driver) Tx DMA channel,
+ * but one DMA channel may take input from several queues.
+ *
+ * Tx DMA FIFOs have dedicated purposes.  For 4965, they are used as follows
+ * (cf. default_queue_to_tx_fifo in iwl-4965.c):
+ *
+ * 0 -- EDCA BK (background) frames, lowest priority
+ * 1 -- EDCA BE (best effort) frames, normal priority
+ * 2 -- EDCA VI (video) frames, higher priority
+ * 3 -- EDCA VO (voice) and management frames, highest priority
+ * 4 -- Commands (e.g. RXON, etc.)
+ * 5 -- unused (HCCA)
+ * 6 -- unused (HCCA)
+ * 7 -- not used by driver (device-internal only)
+ *
+ *
+ * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
+ * In addition, driver can map the remaining queues to Tx DMA/FIFO
+ * channels 0-3 to support 11n aggregation via EDCA DMA channels.
+ *
+ * The driver sets up each queue to work in one of two modes:
+ *
+ * 1)  Scheduler-Ack, in which the scheduler automatically supports a
+ *     block-ack (BA) window of up to 64 TFDs.  In this mode, each queue
+ *     contains TFDs for a unique combination of Recipient Address (RA)
+ *     and Traffic Identifier (TID), that is, traffic of a given
+ *     Quality-Of-Service (QOS) priority, destined for a single station.
+ *
+ *     In scheduler-ack mode, the scheduler keeps track of the Tx status of
+ *     each frame within the BA window, including whether it's been transmitted,
+ *     and whether it's been acknowledged by the receiving station.  The device
+ *     automatically processes block-acks received from the receiving STA,
+ *     and reschedules un-acked frames to be retransmitted (successful
+ *     Tx completion may end up being out-of-order).
+ *
+ *     The driver must maintain the queue's Byte Count table in host DRAM
+ *     (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode.
+ *     This mode does not support fragmentation.
+ *
+ * 2)  FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
+ *     The device may automatically retry Tx, but will retry only one frame
+ *     at a time, until receiving ACK from receiving station, or reaching
+ *     retry limit and giving up.
+ *
+ *     The command queue (#4/#9) must use this mode!
+ *     This mode does not require use of the Byte Count table in host DRAM.
+ *
+ * Driver controls scheduler operation via 3 means:
+ * 1)  Scheduler registers
+ * 2)  Shared scheduler data base in internal 4956 SRAM
+ * 3)  Shared data in host DRAM
+ *
+ * Initialization:
+ *
+ * When loading, driver should allocate memory for:
+ * 1)  16 TFD circular buffers, each with space for (typically) 256 TFDs.
+ * 2)  16 Byte Count circular buffers in 16 KBytes contiguous memory
+ *     (1024 bytes for each queue).
+ *
+ * After receiving "Alive" response from uCode, driver must initialize
+ * the scheduler (especially for queue #4/#9, the command queue, otherwise
+ * the driver can't issue commands!):
+ */
+
+/**
+ * Max Tx window size is the max number of contiguous TFDs that the scheduler
+ * can keep track of at one time when creating block-ack chains of frames.
+ * Note that "64" matches the number of ack bits in a block-ack packet.
+ * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize
+ * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values.
+ */
+#define SCD_WIN_SIZE				64
+#define SCD_FRAME_LIMIT				64
+
+/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */
+#define IWL49_SCD_START_OFFSET		0xa02c00
+
+/*
+ * 4965 tells driver SRAM address for internal scheduler structs via this reg.
+ * Value is valid only after "Alive" response from uCode.
+ */
+#define IWL49_SCD_SRAM_BASE_ADDR           (IWL49_SCD_START_OFFSET + 0x0)
+
+/*
+ * Driver may need to update queue-empty bits after changing queue's
+ * write and read pointers (indexes) during (re-)initialization (i.e. when
+ * scheduler is not tracking what's happening).
+ * Bit fields:
+ * 31-16:  Write mask -- 1: update empty bit, 0: don't change empty bit
+ * 15-00:  Empty state, one for each queue -- 1: empty, 0: non-empty
+ * NOTE:  This register is not used by Linux driver.
+ */
+#define IWL49_SCD_EMPTY_BITS               (IWL49_SCD_START_OFFSET + 0x4)
+
+/*
+ * Physical base address of array of byte count (BC) circular buffers (CBs).
+ * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode.
+ * This register points to BC CB for queue 0, must be on 1024-byte boundary.
+ * Others are spaced by 1024 bytes.
+ * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad.
+ * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff).
+ * Bit fields:
+ * 25-00:  Byte Count CB physical address [35:10], must be 1024-byte aligned.
+ */
+#define IWL49_SCD_DRAM_BASE_ADDR           (IWL49_SCD_START_OFFSET + 0x10)
+
+/*
+ * Enables any/all Tx DMA/FIFO channels.
+ * Scheduler generates requests for only the active channels.
+ * Set this to 0xff to enable all 8 channels (normal usage).
+ * Bit fields:
+ *  7- 0:  Enable (1), disable (0), one bit for each channel 0-7
+ */
+#define IWL49_SCD_TXFACT                   (IWL49_SCD_START_OFFSET + 0x1c)
+/*
+ * Queue (x) Write Pointers (indexes, really!), one for each Tx queue.
+ * Initialized and updated by driver as new TFDs are added to queue.
+ * NOTE:  If using Block Ack, index must correspond to frame's
+ *        Start Sequence Number; index = (SSN & 0xff)
+ * NOTE:  Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses?
+ */
+#define IWL49_SCD_QUEUE_WRPTR(x)  (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4)
+
+/*
+ * Queue (x) Read Pointers (indexes, really!), one for each Tx queue.
+ * For FIFO mode, index indicates next frame to transmit.
+ * For Scheduler-ACK mode, index indicates first frame in Tx window.
+ * Initialized by driver, updated by scheduler.
+ */
+#define IWL49_SCD_QUEUE_RDPTR(x)  (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4)
+
+/*
+ * Select which queues work in chain mode (1) vs. not (0).
+ * Use chain mode to build chains of aggregated frames.
+ * Bit fields:
+ * 31-16:  Reserved
+ * 15-00:  Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time
+ * NOTE:  If driver sets up queue for chain mode, it should be also set up
+ *        Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x).
+ */
+#define IWL49_SCD_QUEUECHAIN_SEL  (IWL49_SCD_START_OFFSET + 0xd0)
+
+/*
+ * Select which queues interrupt driver when scheduler increments
+ * a queue's read pointer (index).
+ * Bit fields:
+ * 31-16:  Reserved
+ * 15-00:  Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled
+ * NOTE:  This functionality is apparently a no-op; driver relies on interrupts
+ *        from Rx queue to read Tx command responses and update Tx queues.
+ */
+#define IWL49_SCD_INTERRUPT_MASK  (IWL49_SCD_START_OFFSET + 0xe4)
+
+/*
+ * Queue search status registers.  One for each queue.
+ * Sets up queue mode and assigns queue to Tx DMA channel.
+ * Bit fields:
+ * 19-10: Write mask/enable bits for bits 0-9
+ *     9: Driver should init to "0"
+ *     8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0).
+ *        Driver should init to "1" for aggregation mode, or "0" otherwise.
+ *   7-6: Driver should init to "0"
+ *     5: Window Size Left; indicates whether scheduler can request
+ *        another TFD, based on window size, etc.  Driver should init
+ *        this bit to "1" for aggregation mode, or "0" for non-agg.
+ *   4-1: Tx FIFO to use (range 0-7).
+ *     0: Queue is active (1), not active (0).
+ * Other bits should be written as "0"
+ *
+ * NOTE:  If enabling Scheduler-ACK mode, chain mode should also be enabled
+ *        via SCD_QUEUECHAIN_SEL.
+ */
+#define IWL49_SCD_QUEUE_STATUS_BITS(x)\
+	(IWL49_SCD_START_OFFSET + 0x104 + (x) * 4)
+
+/* Bit field positions */
+#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE	(0)
+#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF	(1)
+#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL	(5)
+#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK	(8)
+
+/* Write masks */
+#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN	(10)
+#define IWL49_SCD_QUEUE_STTS_REG_MSK		(0x0007FC00)
+
+/**
+ * 4965 internal SRAM structures for scheduler, shared with driver ...
+ *
+ * Driver should clear and initialize the following areas after receiving
+ * "Alive" response from 4965 uCode, i.e. after initial
+ * uCode load, or after a uCode load done for error recovery:
+ *
+ * SCD_CONTEXT_DATA_OFFSET (size 128 bytes)
+ * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes)
+ * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes)
+ *
+ * Driver accesses SRAM via HBUS_TARG_MEM_* registers.
+ * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR.
+ * All OFFSET values must be added to this base address.
+ */
+
+/*
+ * Queue context.  One 8-byte entry for each of 16 queues.
+ *
+ * Driver should clear this entire area (size 0x80) to 0 after receiving
+ * "Alive" notification from uCode.  Additionally, driver should init
+ * each queue's entry as follows:
+ *
+ * LS Dword bit fields:
+ *  0-06:  Max Tx window size for Scheduler-ACK.  Driver should init to 64.
+ *
+ * MS Dword bit fields:
+ * 16-22:  Frame limit.  Driver should init to 10 (0xa).
+ *
+ * Driver should init all other bits to 0.
+ *
+ * Init must be done after driver receives "Alive" response from 4965 uCode,
+ * and when setting up queue for aggregation.
+ */
+#define IWL49_SCD_CONTEXT_DATA_OFFSET			0x380
+#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \
+			(IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
+
+#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS		(0)
+#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK		(0x0000007F)
+#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16)
+#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000)
+
+/*
+ * Tx Status Bitmap
+ *
+ * Driver should clear this entire area (size 0x100) to 0 after receiving
+ * "Alive" notification from uCode.  Area is used only by device itself;
+ * no other support (besides clearing) is required from driver.
+ */
+#define IWL49_SCD_TX_STTS_BITMAP_OFFSET		0x400
+
+/*
+ * RAxTID to queue translation mapping.
+ *
+ * When queue is in Scheduler-ACK mode, frames placed in a that queue must be
+ * for only one combination of receiver address (RA) and traffic ID (TID), i.e.
+ * one QOS priority level destined for one station (for this wireless link,
+ * not final destination).  The SCD_TRANSLATE_TABLE area provides 16 16-bit
+ * mappings, one for each of the 16 queues.  If queue is not in Scheduler-ACK
+ * mode, the device ignores the mapping value.
+ *
+ * Bit fields, for each 16-bit map:
+ * 15-9:  Reserved, set to 0
+ *  8-4:  Index into device's station table for recipient station
+ *  3-0:  Traffic ID (tid), range 0-15
+ *
+ * Driver should clear this entire area (size 32 bytes) to 0 after receiving
+ * "Alive" notification from uCode.  To update a 16-bit map value, driver
+ * must read a dword-aligned value from device SRAM, replace the 16-bit map
+ * value of interest, and write the dword value back into device SRAM.
+ */
+#define IWL49_SCD_TRANSLATE_TBL_OFFSET		0x500
+
+/* Find translation table dword to read/write for given queue */
+#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
+	((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
+
+#define IWL_SCD_TXFIFO_POS_TID			(0)
+#define IWL_SCD_TXFIFO_POS_RA			(4)
+#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK	(0x01FF)
+
+/*********************** END TX SCHEDULER *************************************/
+
+#endif				/* __iwl_legacy_prph_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-rx.c b/drivers/net/wireless/iwlegacy/iwl-rx.c
new file mode 100644
index 0000000..654cf23
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-rx.c
@@ -0,0 +1,302 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+#include <asm/unaligned.h>
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC.  These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC.  The driver and NIC manage the Rx buffers by means
+ * of indexes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt.  The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ INDEX is updated (updating the
+ *   'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl_legacy_rx_queue_alloc()   Allocates rx_free
+ * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            iwl_rx_queue_restock
+ * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE index.  If insufficient rx_free buffers
+ *                            are available, schedules iwl_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ *                            READ INDEX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls iwl_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl_legacy_rx_queue_space - Return number of free slots available in queue.
+ */
+int iwl_legacy_rx_queue_space(const struct iwl_rx_queue *q)
+{
+	int s = q->read - q->write;
+	if (s <= 0)
+		s += RX_QUEUE_SIZE;
+	/* keep some buffer to not confuse full and empty queue */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+EXPORT_SYMBOL(iwl_legacy_rx_queue_space);
+
+/**
+ * iwl_legacy_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+void
+iwl_legacy_rx_queue_update_write_ptr(struct iwl_priv *priv,
+					struct iwl_rx_queue *q)
+{
+	unsigned long flags;
+	u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
+	u32 reg;
+
+	spin_lock_irqsave(&q->lock, flags);
+
+	if (q->need_update == 0)
+		goto exit_unlock;
+
+	/* If power-saving is in use, make sure device is awake */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+			IWL_DEBUG_INFO(priv,
+				"Rx queue requesting wakeup,"
+				" GP1 = 0x%x\n", reg);
+			iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+			goto exit_unlock;
+		}
+
+		q->write_actual = (q->write & ~0x7);
+		iwl_legacy_write_direct32(priv, rx_wrt_ptr_reg,
+				q->write_actual);
+
+	/* Else device is assumed to be awake */
+	} else {
+		/* Device expects a multiple of 8 */
+		q->write_actual = (q->write & ~0x7);
+		iwl_legacy_write_direct32(priv, rx_wrt_ptr_reg,
+			q->write_actual);
+	}
+
+	q->need_update = 0;
+
+ exit_unlock:
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(iwl_legacy_rx_queue_update_write_ptr);
+
+int iwl_legacy_rx_queue_alloc(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	spin_lock_init(&rxq->lock);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+
+	/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
+	rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
+				     GFP_KERNEL);
+	if (!rxq->bd)
+		goto err_bd;
+
+	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
+					  &rxq->rb_stts_dma, GFP_KERNEL);
+	if (!rxq->rb_stts)
+		goto err_rb;
+
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
+	/* Set us so that we have processed and used all buffers, but have
+	 * not restocked the Rx queue with fresh buffers */
+	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
+	rxq->free_count = 0;
+	rxq->need_update = 0;
+	return 0;
+
+err_rb:
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->bd_dma);
+err_bd:
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(iwl_legacy_rx_queue_alloc);
+
+
+void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
+					  struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+
+	if (!report->state) {
+		IWL_DEBUG_11H(priv,
+			"Spectrum Measure Notification: Start\n");
+		return;
+	}
+
+	memcpy(&priv->measure_report, report, sizeof(*report));
+	priv->measurement_status |= MEASUREMENT_READY;
+}
+EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
+
+void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+	if (iwl_legacy_is_any_associated(priv)) {
+		if (priv->cfg->ops->lib->check_plcp_health) {
+			if (!priv->cfg->ops->lib->check_plcp_health(
+			    priv, pkt)) {
+				/*
+				 * high plcp error detected
+				 * reset Radio
+				 */
+				iwl_legacy_force_reset(priv,
+							IWL_RF_RESET, false);
+			}
+		}
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
+
+/*
+ * returns non-zero if packet should be dropped
+ */
+int iwl_legacy_set_decrypted_flag(struct iwl_priv *priv,
+			   struct ieee80211_hdr *hdr,
+			   u32 decrypt_res,
+			   struct ieee80211_rx_status *stats)
+{
+	u16 fc = le16_to_cpu(hdr->frame_control);
+
+	/*
+	 * All contexts have the same setting here due to it being
+	 * a module parameter, so OK to check any context.
+	 */
+	if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags &
+						RXON_FILTER_DIS_DECRYPT_MSK)
+		return 0;
+
+	if (!(fc & IEEE80211_FCTL_PROTECTED))
+		return 0;
+
+	IWL_DEBUG_RX(priv, "decrypt_res:0x%x\n", decrypt_res);
+	switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
+	case RX_RES_STATUS_SEC_TYPE_TKIP:
+		/* The uCode has got a bad phase 1 Key, pushes the packet.
+		 * Decryption will be done in SW. */
+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+		    RX_RES_STATUS_BAD_KEY_TTAK)
+			break;
+
+	case RX_RES_STATUS_SEC_TYPE_WEP:
+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+		    RX_RES_STATUS_BAD_ICV_MIC) {
+			/* bad ICV, the packet is destroyed since the
+			 * decryption is inplace, drop it */
+			IWL_DEBUG_RX(priv, "Packet destroyed\n");
+			return -1;
+		}
+	case RX_RES_STATUS_SEC_TYPE_CCMP:
+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+		    RX_RES_STATUS_DECRYPT_OK) {
+			IWL_DEBUG_RX(priv, "hw decrypt successfully!!!\n");
+			stats->flag |= RX_FLAG_DECRYPTED;
+		}
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_set_decrypted_flag);
diff --git a/drivers/net/wireless/iwlegacy/iwl-scan.c b/drivers/net/wireless/iwlegacy/iwl-scan.c
new file mode 100644
index 0000000..60f597f
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-scan.c
@@ -0,0 +1,625 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
+ * sending probe req.  This should be set long enough to hear probe responses
+ * from more than one AP.  */
+#define IWL_ACTIVE_DWELL_TIME_24    (30)       /* all times in msec */
+#define IWL_ACTIVE_DWELL_TIME_52    (20)
+
+#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
+#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
+
+/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
+ * Must be set longer than active dwell time.
+ * For the most reliable scan, set > AP beacon interval (typically 100msec). */
+#define IWL_PASSIVE_DWELL_TIME_24   (20)       /* all times in msec */
+#define IWL_PASSIVE_DWELL_TIME_52   (10)
+#define IWL_PASSIVE_DWELL_BASE      (100)
+#define IWL_CHANNEL_TUNE_TIME       5
+
+static int iwl_legacy_send_scan_abort(struct iwl_priv *priv)
+{
+	int ret;
+	struct iwl_rx_packet *pkt;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_ABORT_CMD,
+		.flags = CMD_WANT_SKB,
+	};
+
+	/* Exit instantly with error when device is not ready
+	 * to receive scan abort command or it does not perform
+	 * hardware scan currently */
+	if (!test_bit(STATUS_READY, &priv->status) ||
+	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
+	    !test_bit(STATUS_SCAN_HW, &priv->status) ||
+	    test_bit(STATUS_FW_ERROR, &priv->status) ||
+	    test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EIO;
+
+	ret = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (ret)
+		return ret;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->u.status != CAN_ABORT_STATUS) {
+		/* The scan abort will return 1 for success or
+		 * 2 for "failure".  A failure condition can be
+		 * due to simply not being in an active scan which
+		 * can occur if we send the scan abort before we
+		 * the microcode has notified us that a scan is
+		 * completed. */
+		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
+		ret = -EIO;
+	}
+
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+	return ret;
+}
+
+static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
+{
+	/* check if scan was requested from mac80211 */
+	if (priv->scan_request) {
+		IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
+		ieee80211_scan_completed(priv->hw, aborted);
+	}
+
+	priv->is_internal_short_scan = false;
+	priv->scan_vif = NULL;
+	priv->scan_request = NULL;
+}
+
+void iwl_legacy_force_scan_end(struct iwl_priv *priv)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
+		return;
+	}
+
+	IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
+	clear_bit(STATUS_SCANNING, &priv->status);
+	clear_bit(STATUS_SCAN_HW, &priv->status);
+	clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+	iwl_legacy_complete_scan(priv, true);
+}
+
+static void iwl_legacy_do_scan_abort(struct iwl_priv *priv)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
+		return;
+	}
+
+	if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
+		return;
+	}
+
+	ret = iwl_legacy_send_scan_abort(priv);
+	if (ret) {
+		IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
+		iwl_legacy_force_scan_end(priv);
+	} else
+		IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n");
+}
+
+/**
+ * iwl_scan_cancel - Cancel any currently executing HW scan
+ */
+int iwl_legacy_scan_cancel(struct iwl_priv *priv)
+{
+	IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
+	queue_work(priv->workqueue, &priv->abort_scan);
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_scan_cancel);
+
+/**
+ * iwl_legacy_scan_cancel_timeout - Cancel any currently executing HW scan
+ * @ms: amount of time to wait (in milliseconds) for scan to abort
+ *
+ */
+int iwl_legacy_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(ms);
+
+	lockdep_assert_held(&priv->mutex);
+
+	IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
+
+	iwl_legacy_do_scan_abort(priv);
+
+	while (time_before_eq(jiffies, timeout)) {
+		if (!test_bit(STATUS_SCAN_HW, &priv->status))
+			break;
+		msleep(20);
+	}
+
+	return test_bit(STATUS_SCAN_HW, &priv->status);
+}
+EXPORT_SYMBOL(iwl_legacy_scan_cancel_timeout);
+
+/* Service response to REPLY_SCAN_CMD (0x80) */
+static void iwl_legacy_rx_reply_scan(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scanreq_notification *notif =
+	    (struct iwl_scanreq_notification *)pkt->u.raw;
+
+	IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
+#endif
+}
+
+/* Service SCAN_START_NOTIFICATION (0x82) */
+static void iwl_legacy_rx_scan_start_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scanstart_notification *notif =
+	    (struct iwl_scanstart_notification *)pkt->u.raw;
+	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
+	IWL_DEBUG_SCAN(priv, "Scan start: "
+		       "%d [802.11%s] "
+		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
+		       notif->channel,
+		       notif->band ? "bg" : "a",
+		       le32_to_cpu(notif->tsf_high),
+		       le32_to_cpu(notif->tsf_low),
+		       notif->status, notif->beacon_timer);
+}
+
+/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
+static void iwl_legacy_rx_scan_results_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scanresults_notification *notif =
+	    (struct iwl_scanresults_notification *)pkt->u.raw;
+
+	IWL_DEBUG_SCAN(priv, "Scan ch.res: "
+		       "%d [802.11%s] "
+		       "(TSF: 0x%08X:%08X) - %d "
+		       "elapsed=%lu usec\n",
+		       notif->channel,
+		       notif->band ? "bg" : "a",
+		       le32_to_cpu(notif->tsf_high),
+		       le32_to_cpu(notif->tsf_low),
+		       le32_to_cpu(notif->statistics[0]),
+		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
+#endif
+}
+
+/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
+static void iwl_legacy_rx_scan_complete_notif(struct iwl_priv *priv,
+				       struct iwl_rx_mem_buffer *rxb)
+{
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+#endif
+
+	IWL_DEBUG_SCAN(priv,
+			"Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
+		       scan_notif->scanned_channels,
+		       scan_notif->tsf_low,
+		       scan_notif->tsf_high, scan_notif->status);
+
+	/* The HW is no longer scanning */
+	clear_bit(STATUS_SCAN_HW, &priv->status);
+
+	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
+		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
+		       jiffies_to_msecs(jiffies - priv->scan_start));
+
+	queue_work(priv->workqueue, &priv->scan_completed);
+}
+
+void iwl_legacy_setup_rx_scan_handlers(struct iwl_priv *priv)
+{
+	/* scan handlers */
+	priv->rx_handlers[REPLY_SCAN_CMD] = iwl_legacy_rx_reply_scan;
+	priv->rx_handlers[SCAN_START_NOTIFICATION] =
+					iwl_legacy_rx_scan_start_notif;
+	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
+					iwl_legacy_rx_scan_results_notif;
+	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
+					iwl_legacy_rx_scan_complete_notif;
+}
+EXPORT_SYMBOL(iwl_legacy_setup_rx_scan_handlers);
+
+inline u16 iwl_legacy_get_active_dwell_time(struct iwl_priv *priv,
+				     enum ieee80211_band band,
+				     u8 n_probes)
+{
+	if (band == IEEE80211_BAND_5GHZ)
+		return IWL_ACTIVE_DWELL_TIME_52 +
+			IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
+	else
+		return IWL_ACTIVE_DWELL_TIME_24 +
+			IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
+}
+EXPORT_SYMBOL(iwl_legacy_get_active_dwell_time);
+
+u16 iwl_legacy_get_passive_dwell_time(struct iwl_priv *priv,
+			       enum ieee80211_band band,
+			       struct ieee80211_vif *vif)
+{
+	struct iwl_rxon_context *ctx;
+	u16 passive = (band == IEEE80211_BAND_2GHZ) ?
+	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
+	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+
+	if (iwl_legacy_is_any_associated(priv)) {
+		/*
+		 * If we're associated, we clamp the maximum passive
+		 * dwell time to be 98% of the smallest beacon interval
+		 * (minus 2 * channel tune time)
+		 */
+		for_each_context(priv, ctx) {
+			u16 value;
+
+			if (!iwl_legacy_is_associated_ctx(ctx))
+				continue;
+			value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
+			if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
+				value = IWL_PASSIVE_DWELL_BASE;
+			value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+			passive = min(value, passive);
+		}
+	}
+
+	return passive;
+}
+EXPORT_SYMBOL(iwl_legacy_get_passive_dwell_time);
+
+void iwl_legacy_init_scan_params(struct iwl_priv *priv)
+{
+	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
+	if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
+		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
+	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
+		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
+}
+EXPORT_SYMBOL(iwl_legacy_init_scan_params);
+
+static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
+					  struct ieee80211_vif *vif,
+					  bool internal,
+					  enum ieee80211_band band)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+		return -EOPNOTSUPP;
+
+	cancel_delayed_work(&priv->scan_check);
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_WARN(priv, "Request scan called when driver not ready.\n");
+		return -EIO;
+	}
+
+	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+		IWL_DEBUG_SCAN(priv,
+			"Multiple concurrent scan requests in parallel.\n");
+		return -EBUSY;
+	}
+
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
+		return -EBUSY;
+	}
+
+	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
+			internal ? "internal short " : "");
+
+	set_bit(STATUS_SCANNING, &priv->status);
+	priv->is_internal_short_scan = internal;
+	priv->scan_start = jiffies;
+	priv->scan_band = band;
+
+	ret = priv->cfg->ops->utils->request_scan(priv, vif);
+	if (ret) {
+		clear_bit(STATUS_SCANNING, &priv->status);
+		priv->is_internal_short_scan = false;
+		return ret;
+	}
+
+	queue_delayed_work(priv->workqueue, &priv->scan_check,
+			   IWL_SCAN_CHECK_WATCHDOG);
+
+	return 0;
+}
+
+int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    struct cfg80211_scan_request *req)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (req->n_channels == 0)
+		return -EINVAL;
+
+	mutex_lock(&priv->mutex);
+
+	if (test_bit(STATUS_SCANNING, &priv->status) &&
+	    !priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+		ret = -EAGAIN;
+		goto out_unlock;
+	}
+
+	/* mac80211 will only ask for one band at a time */
+	priv->scan_request = req;
+	priv->scan_vif = vif;
+
+	/*
+	 * If an internal scan is in progress, just set
+	 * up the scan_request as per above.
+	 */
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
+		ret = 0;
+	} else
+		ret = iwl_legacy_scan_initiate(priv, vif, false,
+					req->channels[0]->band);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+out_unlock:
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
+
+/*
+ * internal short scan, this function should only been called while associated.
+ * It will reset and tune the radio to prevent possible RF related problem
+ */
+void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
+{
+	queue_work(priv->workqueue, &priv->start_internal_scan);
+}
+
+static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+		container_of(work, struct iwl_priv, start_internal_scan);
+
+	IWL_DEBUG_SCAN(priv, "Start internal scan\n");
+
+	mutex_lock(&priv->mutex);
+
+	if (priv->is_internal_short_scan == true) {
+		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
+		goto unlock;
+	}
+
+	if (test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+		goto unlock;
+	}
+
+	if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
+		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
+ unlock:
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl_legacy_bg_scan_check(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, scan_check.work);
+
+	IWL_DEBUG_SCAN(priv, "Scan check work\n");
+
+	/* Since we are here firmware does not finish scan and
+	 * most likely is in bad shape, so we don't bother to
+	 * send abort command, just force scan complete to mac80211 */
+	mutex_lock(&priv->mutex);
+	iwl_legacy_force_scan_end(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/**
+ * iwl_legacy_fill_probe_req - fill in all required fields and IE for probe request
+ */
+
+u16
+iwl_legacy_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
+		       const u8 *ta, const u8 *ies, int ie_len, int left)
+{
+	int len = 0;
+	u8 *pos = NULL;
+
+	/* Make sure there is enough space for the probe request,
+	 * two mandatory IEs and the data */
+	left -= 24;
+	if (left < 0)
+		return 0;
+
+	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+	memcpy(frame->da, iwlegacy_bcast_addr, ETH_ALEN);
+	memcpy(frame->sa, ta, ETH_ALEN);
+	memcpy(frame->bssid, iwlegacy_bcast_addr, ETH_ALEN);
+	frame->seq_ctrl = 0;
+
+	len += 24;
+
+	/* ...next IE... */
+	pos = &frame->u.probe_req.variable[0];
+
+	/* fill in our indirect SSID IE */
+	left -= 2;
+	if (left < 0)
+		return 0;
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = 0;
+
+	len += 2;
+
+	if (WARN_ON(left < ie_len))
+		return len;
+
+	if (ies && ie_len) {
+		memcpy(pos, ies, ie_len);
+		len += ie_len;
+	}
+
+	return (u16)len;
+}
+EXPORT_SYMBOL(iwl_legacy_fill_probe_req);
+
+static void iwl_legacy_bg_abort_scan(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
+
+	IWL_DEBUG_SCAN(priv, "Abort scan work\n");
+
+	/* We keep scan_check work queued in case when firmware will not
+	 * report back scan completed notification */
+	mutex_lock(&priv->mutex);
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl_legacy_bg_scan_completed(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+	    container_of(work, struct iwl_priv, scan_completed);
+	bool aborted;
+
+	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
+		       priv->is_internal_short_scan ? "internal short " : "");
+
+	cancel_delayed_work(&priv->scan_check);
+
+	mutex_lock(&priv->mutex);
+
+	aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+	if (aborted)
+		IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
+
+	if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
+		goto out_settings;
+	}
+
+	if (priv->is_internal_short_scan && !aborted) {
+		int err;
+
+		/* Check if mac80211 requested scan during our internal scan */
+		if (priv->scan_request == NULL)
+			goto out_complete;
+
+		/* If so request a new scan */
+		err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false,
+					priv->scan_request->channels[0]->band);
+		if (err) {
+			IWL_DEBUG_SCAN(priv,
+				"failed to initiate pending scan: %d\n", err);
+			aborted = true;
+			goto out_complete;
+		}
+
+		goto out;
+	}
+
+out_complete:
+	iwl_legacy_complete_scan(priv, aborted);
+
+out_settings:
+	/* Can we still talk to firmware ? */
+	if (!iwl_legacy_is_ready_rf(priv))
+		goto out;
+
+	/*
+	 * We do not commit power settings while scan is pending,
+	 * do it now if the settings changed.
+	 */
+	iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
+								false);
+	iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
+
+	priv->cfg->ops->utils->post_scan(priv);
+
+out:
+	mutex_unlock(&priv->mutex);
+}
+
+void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
+{
+	INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
+	INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
+	INIT_WORK(&priv->start_internal_scan,
+				iwl_legacy_bg_start_internal_scan);
+	INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
+}
+EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
+
+void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
+{
+	cancel_work_sync(&priv->start_internal_scan);
+	cancel_work_sync(&priv->abort_scan);
+	cancel_work_sync(&priv->scan_completed);
+
+	if (cancel_delayed_work_sync(&priv->scan_check)) {
+		mutex_lock(&priv->mutex);
+		iwl_legacy_force_scan_end(priv);
+		mutex_unlock(&priv->mutex);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_cancel_scan_deferred_work);
diff --git a/drivers/net/wireless/iwlegacy/iwl-spectrum.h b/drivers/net/wireless/iwlegacy/iwl-spectrum.h
new file mode 100644
index 0000000..9f70a47
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-spectrum.h
@@ -0,0 +1,92 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_spectrum_h__
+#define __iwl_legacy_spectrum_h__
+enum {				/* ieee80211_basic_report.map */
+	IEEE80211_BASIC_MAP_BSS = (1 << 0),
+	IEEE80211_BASIC_MAP_OFDM = (1 << 1),
+	IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
+	IEEE80211_BASIC_MAP_RADAR = (1 << 3),
+	IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
+	/* Bits 5-7 are reserved */
+
+};
+struct ieee80211_basic_report {
+	u8 channel;
+	__le64 start_time;
+	__le16 duration;
+	u8 map;
+} __packed;
+
+enum {				/* ieee80211_measurement_request.mode */
+	/* Bit 0 is reserved */
+	IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
+	IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
+	IEEE80211_MEASUREMENT_REPORT = (1 << 3),
+	/* Bits 4-7 are reserved */
+};
+
+enum {
+	IEEE80211_REPORT_BASIC = 0,	/* required */
+	IEEE80211_REPORT_CCA = 1,	/* optional */
+	IEEE80211_REPORT_RPI = 2,	/* optional */
+	/* 3-255 reserved */
+};
+
+struct ieee80211_measurement_params {
+	u8 channel;
+	__le64 start_time;
+	__le16 duration;
+} __packed;
+
+struct ieee80211_info_element {
+	u8 id;
+	u8 len;
+	u8 data[0];
+} __packed;
+
+struct ieee80211_measurement_request {
+	struct ieee80211_info_element ie;
+	u8 token;
+	u8 mode;
+	u8 type;
+	struct ieee80211_measurement_params params[0];
+} __packed;
+
+struct ieee80211_measurement_report {
+	struct ieee80211_info_element ie;
+	u8 token;
+	u8 mode;
+	u8 type;
+	union {
+		struct ieee80211_basic_report basic[0];
+	} u;
+} __packed;
+
+#endif
diff --git a/drivers/net/wireless/iwlegacy/iwl-sta.c b/drivers/net/wireless/iwlegacy/iwl-sta.c
new file mode 100644
index 0000000..47c9da3
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-sta.c
@@ -0,0 +1,816 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/lockdep.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+
+/* priv->sta_lock must be held */
+static void iwl_legacy_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+{
+
+	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+		IWL_ERR(priv,
+			"ACTIVATE a non DRIVER active station id %u addr %pM\n",
+			sta_id, priv->stations[sta_id].sta.sta.addr);
+
+	if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
+		IWL_DEBUG_ASSOC(priv,
+			"STA id %u addr %pM already present"
+			" in uCode (according to driver)\n",
+			sta_id, priv->stations[sta_id].sta.sta.addr);
+	} else {
+		priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+		IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
+				sta_id, priv->stations[sta_id].sta.sta.addr);
+	}
+}
+
+static int iwl_legacy_process_add_sta_resp(struct iwl_priv *priv,
+				    struct iwl_legacy_addsta_cmd *addsta,
+				    struct iwl_rx_packet *pkt,
+				    bool sync)
+{
+	u8 sta_id = addsta->sta.sta_id;
+	unsigned long flags;
+	int ret = -EIO;
+
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
+			pkt->hdr.flags);
+		return ret;
+	}
+
+	IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
+		       sta_id);
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	switch (pkt->u.add_sta.status) {
+	case ADD_STA_SUCCESS_MSK:
+		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
+		iwl_legacy_sta_ucode_activate(priv, sta_id);
+		ret = 0;
+		break;
+	case ADD_STA_NO_ROOM_IN_TABLE:
+		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
+			sta_id);
+		break;
+	case ADD_STA_NO_BLOCK_ACK_RESOURCE:
+		IWL_ERR(priv,
+			"Adding station %d failed, no block ack resource.\n",
+			sta_id);
+		break;
+	case ADD_STA_MODIFY_NON_EXIST_STA:
+		IWL_ERR(priv, "Attempting to modify non-existing station %d\n",
+			sta_id);
+		break;
+	default:
+		IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
+				pkt->u.add_sta.status);
+		break;
+	}
+
+	IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
+		       priv->stations[sta_id].sta.mode ==
+		       STA_CONTROL_MODIFY_MSK ?  "Modified" : "Added",
+		       sta_id, priv->stations[sta_id].sta.sta.addr);
+
+	/*
+	 * XXX: The MAC address in the command buffer is often changed from
+	 * the original sent to the device. That is, the MAC address
+	 * written to the command buffer often is not the same MAC adress
+	 * read from the command buffer when the command returns. This
+	 * issue has not yet been resolved and this debugging is left to
+	 * observe the problem.
+	 */
+	IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
+		       priv->stations[sta_id].sta.mode ==
+		       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
+		       addsta->sta.addr);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
+}
+
+static void iwl_legacy_add_sta_callback(struct iwl_priv *priv,
+				 struct iwl_device_cmd *cmd,
+				 struct iwl_rx_packet *pkt)
+{
+	struct iwl_legacy_addsta_cmd *addsta =
+		(struct iwl_legacy_addsta_cmd *)cmd->cmd.payload;
+
+	iwl_legacy_process_add_sta_resp(priv, addsta, pkt, false);
+
+}
+
+int iwl_legacy_send_add_sta(struct iwl_priv *priv,
+		     struct iwl_legacy_addsta_cmd *sta, u8 flags)
+{
+	struct iwl_rx_packet *pkt = NULL;
+	int ret = 0;
+	u8 data[sizeof(*sta)];
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_ADD_STA,
+		.flags = flags,
+		.data = data,
+	};
+	u8 sta_id __maybe_unused = sta->sta.sta_id;
+
+	IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
+		       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
+
+	if (flags & CMD_ASYNC)
+		cmd.callback = iwl_legacy_add_sta_callback;
+	else {
+		cmd.flags |= CMD_WANT_SKB;
+		might_sleep();
+	}
+
+	cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
+	ret = iwl_legacy_send_cmd(priv, &cmd);
+
+	if (ret || (flags & CMD_ASYNC))
+		return ret;
+
+	if (ret == 0) {
+		pkt = (struct iwl_rx_packet *)cmd.reply_page;
+		ret = iwl_legacy_process_add_sta_resp(priv, sta, pkt, true);
+	}
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_send_add_sta);
+
+static void iwl_legacy_set_ht_add_station(struct iwl_priv *priv, u8 index,
+				   struct ieee80211_sta *sta,
+				   struct iwl_rxon_context *ctx)
+{
+	struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
+	__le32 sta_flags;
+	u8 mimo_ps_mode;
+
+	if (!sta || !sta_ht_inf->ht_supported)
+		goto done;
+
+	mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
+	IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
+			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
+			"static" :
+			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
+			"dynamic" : "disabled");
+
+	sta_flags = priv->stations[index].sta.station_flags;
+
+	sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
+
+	switch (mimo_ps_mode) {
+	case WLAN_HT_CAP_SM_PS_STATIC:
+		sta_flags |= STA_FLG_MIMO_DIS_MSK;
+		break;
+	case WLAN_HT_CAP_SM_PS_DYNAMIC:
+		sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+		break;
+	case WLAN_HT_CAP_SM_PS_DISABLED:
+		break;
+	default:
+		IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
+		break;
+	}
+
+	sta_flags |= cpu_to_le32(
+	      (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+
+	sta_flags |= cpu_to_le32(
+	      (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+
+	if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+		sta_flags |= STA_FLG_HT40_EN_MSK;
+	else
+		sta_flags &= ~STA_FLG_HT40_EN_MSK;
+
+	priv->stations[index].sta.station_flags = sta_flags;
+ done:
+	return;
+}
+
+/**
+ * iwl_legacy_prep_station - Prepare station information for addition
+ *
+ * should be called with sta_lock held
+ */
+u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		    const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
+{
+	struct iwl_station_entry *station;
+	int i;
+	u8 sta_id = IWL_INVALID_STATION;
+	u16 rate;
+
+	if (is_ap)
+		sta_id = ctx->ap_sta_id;
+	else if (is_broadcast_ether_addr(addr))
+		sta_id = ctx->bcast_sta_id;
+	else
+		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
+			if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+						addr)) {
+				sta_id = i;
+				break;
+			}
+
+			if (!priv->stations[i].used &&
+			    sta_id == IWL_INVALID_STATION)
+				sta_id = i;
+		}
+
+	/*
+	 * These two conditions have the same outcome, but keep them
+	 * separate
+	 */
+	if (unlikely(sta_id == IWL_INVALID_STATION))
+		return sta_id;
+
+	/*
+	 * uCode is not able to deal with multiple requests to add a
+	 * station. Keep track if one is in progress so that we do not send
+	 * another.
+	 */
+	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
+		IWL_DEBUG_INFO(priv,
+				"STA %d already in process of being added.\n",
+				sta_id);
+		return sta_id;
+	}
+
+	if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) &&
+	    !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
+		IWL_DEBUG_ASSOC(priv,
+				"STA %d (%pM) already added, not adding again.\n",
+				sta_id, addr);
+		return sta_id;
+	}
+
+	station = &priv->stations[sta_id];
+	station->used = IWL_STA_DRIVER_ACTIVE;
+	IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n",
+			sta_id, addr);
+	priv->num_stations++;
+
+	/* Set up the REPLY_ADD_STA command to send to device */
+	memset(&station->sta, 0, sizeof(struct iwl_legacy_addsta_cmd));
+	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
+	station->sta.mode = 0;
+	station->sta.sta.sta_id = sta_id;
+	station->sta.station_flags = ctx->station_flags;
+	station->ctxid = ctx->ctxid;
+
+	if (sta) {
+		struct iwl_station_priv_common *sta_priv;
+
+		sta_priv = (void *)sta->drv_priv;
+		sta_priv->ctx = ctx;
+	}
+
+	/*
+	 * OK to call unconditionally, since local stations (IBSS BSSID
+	 * STA and broadcast STA) pass in a NULL sta, and mac80211
+	 * doesn't allow HT IBSS.
+	 */
+	iwl_legacy_set_ht_add_station(priv, sta_id, sta, ctx);
+
+	/* 3945 only */
+	rate = (priv->band == IEEE80211_BAND_5GHZ) ?
+		IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP;
+	/* Turn on both antennas for the station... */
+	station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK);
+
+	return sta_id;
+
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_prep_station);
+
+#define STA_WAIT_TIMEOUT (HZ/2)
+
+/**
+ * iwl_legacy_add_station_common -
+ */
+int
+iwl_legacy_add_station_common(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			   const u8 *addr, bool is_ap,
+			   struct ieee80211_sta *sta, u8 *sta_id_r)
+{
+	unsigned long flags_spin;
+	int ret = 0;
+	u8 sta_id;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	*sta_id_r = 0;
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	sta_id = iwl_legacy_prep_station(priv, ctx, addr, is_ap, sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
+			addr);
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EINVAL;
+	}
+
+	/*
+	 * uCode is not able to deal with multiple requests to add a
+	 * station. Keep track if one is in progress so that we do not send
+	 * another.
+	 */
+	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
+		IWL_DEBUG_INFO(priv,
+			"STA %d already in process of being added.\n",
+		       sta_id);
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EEXIST;
+	}
+
+	if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+		IWL_DEBUG_ASSOC(priv,
+			"STA %d (%pM) already added, not adding again.\n",
+			sta_id, addr);
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EEXIST;
+	}
+
+	priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+				sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	/* Add station to device's station table */
+	ret = iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+	if (ret) {
+		spin_lock_irqsave(&priv->sta_lock, flags_spin);
+		IWL_ERR(priv, "Adding station %pM failed.\n",
+			priv->stations[sta_id].sta.sta.addr);
+		priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+		priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+	}
+	*sta_id_r = sta_id;
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_add_station_common);
+
+/**
+ * iwl_legacy_sta_ucode_deactivate - deactivate ucode status for a station
+ *
+ * priv->sta_lock must be held
+ */
+static void iwl_legacy_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
+{
+	/* Ucode must be active and driver must be non active */
+	if ((priv->stations[sta_id].used &
+	     (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
+						IWL_STA_UCODE_ACTIVE)
+		IWL_ERR(priv, "removed non active STA %u\n", sta_id);
+
+	priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+
+	memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
+	IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id);
+}
+
+static int iwl_legacy_send_remove_station(struct iwl_priv *priv,
+				   const u8 *addr, int sta_id,
+				   bool temporary)
+{
+	struct iwl_rx_packet *pkt;
+	int ret;
+
+	unsigned long flags_spin;
+	struct iwl_rem_sta_cmd rm_sta_cmd;
+
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_REMOVE_STA,
+		.len = sizeof(struct iwl_rem_sta_cmd),
+		.flags = CMD_SYNC,
+		.data = &rm_sta_cmd,
+	};
+
+	memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
+	rm_sta_cmd.num_sta = 1;
+	memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
+
+	cmd.flags |= CMD_WANT_SKB;
+
+	ret = iwl_legacy_send_cmd(priv, &cmd);
+
+	if (ret)
+		return ret;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+			  pkt->hdr.flags);
+		ret = -EIO;
+	}
+
+	if (!ret) {
+		switch (pkt->u.rem_sta.status) {
+		case REM_STA_SUCCESS_MSK:
+			if (!temporary) {
+				spin_lock_irqsave(&priv->sta_lock, flags_spin);
+				iwl_legacy_sta_ucode_deactivate(priv, sta_id);
+				spin_unlock_irqrestore(&priv->sta_lock,
+								flags_spin);
+			}
+			IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
+			break;
+		default:
+			ret = -EIO;
+			IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
+			break;
+		}
+	}
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return ret;
+}
+
+/**
+ * iwl_legacy_remove_station - Remove driver's knowledge of station.
+ */
+int iwl_legacy_remove_station(struct iwl_priv *priv, const u8 sta_id,
+		       const u8 *addr)
+{
+	unsigned long flags;
+
+	if (!iwl_legacy_is_ready(priv)) {
+		IWL_DEBUG_INFO(priv,
+			"Unable to remove station %pM, device not ready.\n",
+			addr);
+		/*
+		 * It is typical for stations to be removed when we are
+		 * going down. Return success since device will be down
+		 * soon anyway
+		 */
+		return 0;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d  %pM\n",
+			sta_id, addr);
+
+	if (WARN_ON(sta_id == IWL_INVALID_STATION))
+		return -EINVAL;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
+				addr);
+		goto out_err;
+	}
+
+	if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+		IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
+				addr);
+		goto out_err;
+	}
+
+	if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
+		kfree(priv->stations[sta_id].lq);
+		priv->stations[sta_id].lq = NULL;
+	}
+
+	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+	priv->num_stations--;
+
+	BUG_ON(priv->num_stations < 0);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_remove_station(priv, addr, sta_id, false);
+out_err:
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_remove_station);
+
+/**
+ * iwl_legacy_clear_ucode_stations - clear ucode station table bits
+ *
+ * This function clears all the bits in the driver indicating
+ * which stations are active in the ucode. Call when something
+ * other than explicit station management would cause this in
+ * the ucode, e.g. unassociated RXON.
+ */
+void iwl_legacy_clear_ucode_stations(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx)
+{
+	int i;
+	unsigned long flags_spin;
+	bool cleared = false;
+
+	IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if (ctx && ctx->ctxid != priv->stations[i].ctxid)
+			continue;
+
+		if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
+			IWL_DEBUG_INFO(priv,
+				"Clearing ucode active for station %d\n", i);
+			priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+			cleared = true;
+		}
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	if (!cleared)
+		IWL_DEBUG_INFO(priv,
+			"No active stations found to be cleared\n");
+}
+EXPORT_SYMBOL(iwl_legacy_clear_ucode_stations);
+
+/**
+ * iwl_legacy_restore_stations() - Restore driver known stations to device
+ *
+ * All stations considered active by driver, but not present in ucode, is
+ * restored.
+ *
+ * Function sleeps.
+ */
+void
+iwl_legacy_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_addsta_cmd sta_cmd;
+	struct iwl_link_quality_cmd lq;
+	unsigned long flags_spin;
+	int i;
+	bool found = false;
+	int ret;
+	bool send_lq;
+
+	if (!iwl_legacy_is_ready(priv)) {
+		IWL_DEBUG_INFO(priv,
+			"Not ready yet, not restoring any stations.\n");
+		return;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if (ctx->ctxid != priv->stations[i].ctxid)
+			continue;
+		if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
+			    !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
+			IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
+					priv->stations[i].sta.sta.addr);
+			priv->stations[i].sta.mode = 0;
+			priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
+			found = true;
+		}
+	}
+
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
+			memcpy(&sta_cmd, &priv->stations[i].sta,
+			       sizeof(struct iwl_legacy_addsta_cmd));
+			send_lq = false;
+			if (priv->stations[i].lq) {
+				memcpy(&lq, priv->stations[i].lq,
+				       sizeof(struct iwl_link_quality_cmd));
+				send_lq = true;
+			}
+			spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+			ret = iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+			if (ret) {
+				spin_lock_irqsave(&priv->sta_lock, flags_spin);
+				IWL_ERR(priv, "Adding station %pM failed.\n",
+					priv->stations[i].sta.sta.addr);
+				priv->stations[i].used &=
+						~IWL_STA_DRIVER_ACTIVE;
+				priv->stations[i].used &=
+						~IWL_STA_UCODE_INPROGRESS;
+				spin_unlock_irqrestore(&priv->sta_lock,
+								flags_spin);
+			}
+			/*
+			 * Rate scaling has already been initialized, send
+			 * current LQ command
+			 */
+			if (send_lq)
+				iwl_legacy_send_lq_cmd(priv, ctx, &lq,
+								CMD_SYNC, true);
+			spin_lock_irqsave(&priv->sta_lock, flags_spin);
+			priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
+		}
+	}
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+	if (!found)
+		IWL_DEBUG_INFO(priv, "Restoring all known stations"
+				" .... no stations to be restored.\n");
+	else
+		IWL_DEBUG_INFO(priv, "Restoring all known stations"
+				" .... complete.\n");
+}
+EXPORT_SYMBOL(iwl_legacy_restore_stations);
+
+int iwl_legacy_get_free_ucode_key_index(struct iwl_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < priv->sta_key_max_num; i++)
+		if (!test_and_set_bit(i, &priv->ucode_key_table))
+			return i;
+
+	return WEP_INVALID_OFFSET;
+}
+EXPORT_SYMBOL(iwl_legacy_get_free_ucode_key_index);
+
+void iwl_legacy_dealloc_bcast_stations(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if (!(priv->stations[i].used & IWL_STA_BCAST))
+			continue;
+
+		priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+		priv->num_stations--;
+		BUG_ON(priv->num_stations < 0);
+		kfree(priv->stations[i].lq);
+		priv->stations[i].lq = NULL;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_dealloc_bcast_stations);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
+			   struct iwl_link_quality_cmd *lq)
+{
+	int i;
+	IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id);
+	IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n",
+		       lq->general_params.single_stream_ant_msk,
+		       lq->general_params.dual_stream_ant_msk);
+
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+		IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n",
+			       i, lq->rs_table[i].rate_n_flags);
+}
+#else
+static inline void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
+				   struct iwl_link_quality_cmd *lq)
+{
+}
+#endif
+
+/**
+ * iwl_legacy_is_lq_table_valid() - Test one aspect of LQ cmd for validity
+ *
+ * It sometimes happens when a HT rate has been in use and we
+ * loose connectivity with AP then mac80211 will first tell us that the
+ * current channel is not HT anymore before removing the station. In such a
+ * scenario the RXON flags will be updated to indicate we are not
+ * communicating HT anymore, but the LQ command may still contain HT rates.
+ * Test for this to prevent driver from sending LQ command between the time
+ * RXON flags are updated and when LQ command is updated.
+ */
+static bool iwl_legacy_is_lq_table_valid(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_link_quality_cmd *lq)
+{
+	int i;
+
+	if (ctx->ht.enabled)
+		return true;
+
+	IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
+		       ctx->active.channel);
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+		if (le32_to_cpu(lq->rs_table[i].rate_n_flags) &
+						RATE_MCS_HT_MSK) {
+			IWL_DEBUG_INFO(priv,
+				       "index %d of LQ expects HT channel\n",
+				       i);
+			return false;
+		}
+	}
+	return true;
+}
+
+/**
+ * iwl_legacy_send_lq_cmd() - Send link quality command
+ * @init: This command is sent as part of station initialization right
+ *        after station has been added.
+ *
+ * The link quality command is sent as the last step of station creation.
+ * This is the special case in which init is set and we call a callback in
+ * this case to clear the state indicating that station creation is in
+ * progress.
+ */
+int iwl_legacy_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		    struct iwl_link_quality_cmd *lq, u8 flags, bool init)
+{
+	int ret = 0;
+	unsigned long flags_spin;
+
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_TX_LINK_QUALITY_CMD,
+		.len = sizeof(struct iwl_link_quality_cmd),
+		.flags = flags,
+		.data = lq,
+	};
+
+	if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
+		return -EINVAL;
+
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EINVAL;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	iwl_legacy_dump_lq_cmd(priv, lq);
+	BUG_ON(init && (cmd.flags & CMD_ASYNC));
+
+	if (iwl_legacy_is_lq_table_valid(priv, ctx, lq))
+		ret = iwl_legacy_send_cmd(priv, &cmd);
+	else
+		ret = -EINVAL;
+
+	if (cmd.flags & CMD_ASYNC)
+		return ret;
+
+	if (init) {
+		IWL_DEBUG_INFO(priv, "init LQ command complete,"
+				" clearing sta addition status for sta %d\n",
+			       lq->sta_id);
+		spin_lock_irqsave(&priv->sta_lock, flags_spin);
+		priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_send_lq_cmd);
+
+int iwl_legacy_mac_sta_remove(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
+	int ret;
+
+	IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
+			sta->addr);
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+			sta->addr);
+	ret = iwl_legacy_remove_station(priv, sta_common->sta_id, sta->addr);
+	if (ret)
+		IWL_ERR(priv, "Error removing station %pM\n",
+			sta->addr);
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_sta_remove);
diff --git a/drivers/net/wireless/iwlegacy/iwl-sta.h b/drivers/net/wireless/iwlegacy/iwl-sta.h
new file mode 100644
index 0000000..67bd75f
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-sta.h
@@ -0,0 +1,148 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#ifndef __iwl_legacy_sta_h__
+#define __iwl_legacy_sta_h__
+
+#include "iwl-dev.h"
+
+#define HW_KEY_DYNAMIC 0
+#define HW_KEY_DEFAULT 1
+
+#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
+#define IWL_STA_UCODE_ACTIVE  BIT(1) /* ucode entry is active */
+#define IWL_STA_UCODE_INPROGRESS  BIT(2) /* ucode entry is in process of
+					    being activated */
+#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211;
+				(this is for the IBSS BSSID stations) */
+#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
+
+
+void iwl_legacy_restore_stations(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx);
+void iwl_legacy_clear_ucode_stations(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx);
+void iwl_legacy_dealloc_bcast_stations(struct iwl_priv *priv);
+int iwl_legacy_get_free_ucode_key_index(struct iwl_priv *priv);
+int iwl_legacy_send_add_sta(struct iwl_priv *priv,
+			struct iwl_legacy_addsta_cmd *sta, u8 flags);
+int iwl_legacy_add_station_common(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			const u8 *addr, bool is_ap,
+			struct ieee80211_sta *sta, u8 *sta_id_r);
+int iwl_legacy_remove_station(struct iwl_priv *priv,
+			const u8 sta_id,
+			const u8 *addr);
+int iwl_legacy_mac_sta_remove(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			struct ieee80211_sta *sta);
+
+u8 iwl_legacy_prep_station(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			const u8 *addr, bool is_ap,
+			struct ieee80211_sta *sta);
+
+int iwl_legacy_send_lq_cmd(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct iwl_link_quality_cmd *lq,
+			u8 flags, bool init);
+
+/**
+ * iwl_legacy_clear_driver_stations - clear knowledge of all stations from driver
+ * @priv: iwl priv struct
+ *
+ * This is called during iwl_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static inline void iwl_legacy_clear_driver_stations(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	struct iwl_rxon_context *ctx;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	memset(priv->stations, 0, sizeof(priv->stations));
+	priv->num_stations = 0;
+
+	priv->ucode_key_table = 0;
+
+	for_each_context(priv, ctx) {
+		/*
+		 * Remove all key information that is not stored as part
+		 * of station information since mac80211 may not have had
+		 * a chance to remove all the keys. When device is
+		 * reconfigured by mac80211 after an error all keys will
+		 * be reconfigured.
+		 */
+		memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+		ctx->key_mapping_keys = 0;
+	}
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
+static inline int iwl_legacy_sta_id(struct ieee80211_sta *sta)
+{
+	if (WARN_ON(!sta))
+		return IWL_INVALID_STATION;
+
+	return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
+}
+
+/**
+ * iwl_legacy_sta_id_or_broadcast - return sta_id or broadcast sta
+ * @priv: iwl priv
+ * @context: the current context
+ * @sta: mac80211 station
+ *
+ * In certain circumstances mac80211 passes a station pointer
+ * that may be %NULL, for example during TX or key setup. In
+ * that case, we need to use the broadcast station, so this
+ * inline wraps that pattern.
+ */
+static inline int iwl_legacy_sta_id_or_broadcast(struct iwl_priv *priv,
+					  struct iwl_rxon_context *context,
+					  struct ieee80211_sta *sta)
+{
+	int sta_id;
+
+	if (!sta)
+		return context->bcast_sta_id;
+
+	sta_id = iwl_legacy_sta_id(sta);
+
+	/*
+	 * mac80211 should not be passing a partially
+	 * initialised station!
+	 */
+	WARN_ON(sta_id == IWL_INVALID_STATION);
+
+	return sta_id;
+}
+#endif /* __iwl_legacy_sta_h__ */
diff --git a/drivers/net/wireless/iwlegacy/iwl-tx.c b/drivers/net/wireless/iwlegacy/iwl-tx.c
new file mode 100644
index 0000000..a227773
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl-tx.c
@@ -0,0 +1,660 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+/**
+ * iwl_legacy_txq_update_write_ptr - Send new write index to hardware
+ */
+void
+iwl_legacy_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	u32 reg = 0;
+	int txq_id = txq->q.id;
+
+	if (txq->need_update == 0)
+		return;
+
+	/* if we're trying to save power */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		/* wake up nic if it's powered down ...
+		 * uCode will wake up, and interrupt us again, so next
+		 * time we'll skip this part. */
+		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+			IWL_DEBUG_INFO(priv,
+					"Tx queue %d requesting wakeup,"
+					" GP1 = 0x%x\n", txq_id, reg);
+			iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+			return;
+		}
+
+		iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR,
+				txq->q.write_ptr | (txq_id << 8));
+
+		/*
+		 * else not in power-save mode,
+		 * uCode will never sleep when we're
+		 * trying to tx (during RFKILL, we're not trying to tx).
+		 */
+	} else
+		iwl_write32(priv, HBUS_TARG_WRPTR,
+			    txq->q.write_ptr | (txq_id << 8));
+	txq->need_update = 0;
+}
+EXPORT_SYMBOL(iwl_legacy_txq_update_write_ptr);
+
+/**
+ * iwl_legacy_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+void iwl_legacy_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+
+	if (q->n_bd == 0)
+		return;
+
+	while (q->write_ptr != q->read_ptr) {
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+		q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_unmap);
+
+/**
+ * iwl_legacy_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void iwl_legacy_tx_queue_free(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	iwl_legacy_tx_queue_unmap(priv, txq_id);
+
+	/* De-alloc array of command/tx buffers */
+	for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
+		kfree(txq->cmd[i]);
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd)
+		dma_free_coherent(dev, priv->hw_params.tfd_size *
+				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+
+	/* De-alloc array of per-TFD driver data */
+	kfree(txq->txb);
+	txq->txb = NULL;
+
+	/* deallocate arrays */
+	kfree(txq->cmd);
+	kfree(txq->meta);
+	txq->cmd = NULL;
+	txq->meta = NULL;
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_free);
+
+/**
+ * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
+ */
+void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct iwl_queue *q = &txq->q;
+	bool huge = false;
+	int i;
+
+	if (q->n_bd == 0)
+		return;
+
+	while (q->read_ptr != q->write_ptr) {
+		/* we have no way to tell if it is a huge cmd ATM */
+		i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0);
+
+		if (txq->meta[i].flags & CMD_SIZE_HUGE)
+			huge = true;
+		else
+			pci_unmap_single(priv->pci_dev,
+					 dma_unmap_addr(&txq->meta[i], mapping),
+					 dma_unmap_len(&txq->meta[i], len),
+					 PCI_DMA_BIDIRECTIONAL);
+
+		q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+
+	if (huge) {
+		i = q->n_window;
+		pci_unmap_single(priv->pci_dev,
+				 dma_unmap_addr(&txq->meta[i], mapping),
+				 dma_unmap_len(&txq->meta[i], len),
+				 PCI_DMA_BIDIRECTIONAL);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap);
+
+/**
+ * iwl_legacy_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void iwl_legacy_cmd_queue_free(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	iwl_legacy_cmd_queue_unmap(priv);
+
+	/* De-alloc array of command/tx buffers */
+	for (i = 0; i <= TFD_CMD_SLOTS; i++)
+		kfree(txq->cmd[i]);
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd)
+		dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
+				  txq->tfds, txq->q.dma_addr);
+
+	/* deallocate arrays */
+	kfree(txq->cmd);
+	kfree(txq->meta);
+	txq->cmd = NULL;
+	txq->meta = NULL;
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
+EXPORT_SYMBOL(iwl_legacy_cmd_queue_free);
+
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ * See more detailed info in iwl-4965-hw.h.
+ ***************************************************/
+
+int iwl_legacy_queue_space(const struct iwl_queue *q)
+{
+	int s = q->read_ptr - q->write_ptr;
+
+	if (q->read_ptr > q->write_ptr)
+		s -= q->n_bd;
+
+	if (s <= 0)
+		s += q->n_window;
+	/* keep some reserve to not confuse empty and full situations */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+EXPORT_SYMBOL(iwl_legacy_queue_space);
+
+
+/**
+ * iwl_legacy_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+static int iwl_legacy_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+			  int count, int slots_num, u32 id)
+{
+	q->n_bd = count;
+	q->n_window = slots_num;
+	q->id = id;
+
+	/* count must be power-of-two size, otherwise iwl_legacy_queue_inc_wrap
+	 * and iwl_legacy_queue_dec_wrap are broken. */
+	BUG_ON(!is_power_of_2(count));
+
+	/* slots_num must be power-of-two size, otherwise
+	 * iwl_legacy_get_cmd_index is broken. */
+	BUG_ON(!is_power_of_2(slots_num));
+
+	q->low_mark = q->n_window / 4;
+	if (q->low_mark < 4)
+		q->low_mark = 4;
+
+	q->high_mark = q->n_window / 8;
+	if (q->high_mark < 2)
+		q->high_mark = 2;
+
+	q->write_ptr = q->read_ptr = 0;
+
+	return 0;
+}
+
+/**
+ * iwl_legacy_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+static int iwl_legacy_tx_queue_alloc(struct iwl_priv *priv,
+			      struct iwl_tx_queue *txq, u32 id)
+{
+	struct device *dev = &priv->pci_dev->dev;
+	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
+
+	/* Driver private data, only for Tx (not command) queues,
+	 * not shared with device. */
+	if (id != priv->cmd_queue) {
+		txq->txb = kzalloc(sizeof(txq->txb[0]) *
+				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
+		if (!txq->txb) {
+			IWL_ERR(priv, "kmalloc for auxiliary BD "
+				  "structures failed\n");
+			goto error;
+		}
+	} else {
+		txq->txb = NULL;
+	}
+
+	/* Circular buffer of transmit frame descriptors (TFDs),
+	 * shared with device */
+	txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
+				       GFP_KERNEL);
+	if (!txq->tfds) {
+		IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
+		goto error;
+	}
+	txq->q.id = id;
+
+	return 0;
+
+ error:
+	kfree(txq->txb);
+	txq->txb = NULL;
+
+	return -ENOMEM;
+}
+
+/**
+ * iwl_legacy_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+int iwl_legacy_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+		      int slots_num, u32 txq_id)
+{
+	int i, len;
+	int ret;
+	int actual_slots = slots_num;
+
+	/*
+	 * Alloc buffer array for commands (Tx or other types of commands).
+	 * For the command queue (#4/#9), allocate command space + one big
+	 * command for scan, since scan command is very huge; the system will
+	 * not have two scans at the same time, so only one is needed.
+	 * For normal Tx queues (all other queues), no super-size command
+	 * space is needed.
+	 */
+	if (txq_id == priv->cmd_queue)
+		actual_slots++;
+
+	txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
+			    GFP_KERNEL);
+	txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
+			   GFP_KERNEL);
+
+	if (!txq->meta || !txq->cmd)
+		goto out_free_arrays;
+
+	len = sizeof(struct iwl_device_cmd);
+	for (i = 0; i < actual_slots; i++) {
+		/* only happens for cmd queue */
+		if (i == slots_num)
+			len = IWL_MAX_CMD_SIZE;
+
+		txq->cmd[i] = kmalloc(len, GFP_KERNEL);
+		if (!txq->cmd[i])
+			goto err;
+	}
+
+	/* Alloc driver data array and TFD circular buffer */
+	ret = iwl_legacy_tx_queue_alloc(priv, txq, txq_id);
+	if (ret)
+		goto err;
+
+	txq->need_update = 0;
+
+	/*
+	 * For the default queues 0-3, set up the swq_id
+	 * already -- all others need to get one later
+	 * (if they need one at all).
+	 */
+	if (txq_id < 4)
+		iwl_legacy_set_swq_id(txq, txq_id, txq_id);
+
+	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+	 * iwl_legacy_queue_inc_wrap and iwl_legacy_queue_dec_wrap are broken. */
+	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+	/* Initialize queue's high/low-water marks, and head/tail indexes */
+	iwl_legacy_queue_init(priv, &txq->q,
+				TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+	/* Tell device where to find queue */
+	priv->cfg->ops->lib->txq_init(priv, txq);
+
+	return 0;
+err:
+	for (i = 0; i < actual_slots; i++)
+		kfree(txq->cmd[i]);
+out_free_arrays:
+	kfree(txq->meta);
+	kfree(txq->cmd);
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_init);
+
+void iwl_legacy_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+			int slots_num, u32 txq_id)
+{
+	int actual_slots = slots_num;
+
+	if (txq_id == priv->cmd_queue)
+		actual_slots++;
+
+	memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
+
+	txq->need_update = 0;
+
+	/* Initialize queue's high/low-water marks, and head/tail indexes */
+	iwl_legacy_queue_init(priv, &txq->q,
+				TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+	/* Tell device where to find queue */
+	priv->cfg->ops->lib->txq_init(priv, txq);
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_reset);
+
+/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
+
+/**
+ * iwl_legacy_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+ * @cmd: a point to the ucode command structure
+ *
+ * The function returns < 0 values to indicate the operation is
+ * failed. On success, it turns the index (> 0) of command in the
+ * command queue.
+ */
+int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	dma_addr_t phys_addr;
+	unsigned long flags;
+	int len;
+	u32 idx;
+	u16 fix_size;
+
+	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
+	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+
+	/* If any of the command structures end up being larger than
+	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
+	 * we will need to increase the size of the TFD entries
+	 * Also, check to see if command buffer should not exceed the size
+	 * of device_cmd and max_cmd_size. */
+	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
+	       !(cmd->flags & CMD_SIZE_HUGE));
+	BUG_ON(fix_size > IWL_MAX_CMD_SIZE);
+
+	if (iwl_legacy_is_rfkill(priv) || iwl_legacy_is_ctkill(priv)) {
+		IWL_WARN(priv, "Not sending command - %s KILL\n",
+			 iwl_legacy_is_rfkill(priv) ? "RF" : "CT");
+		return -EIO;
+	}
+
+	if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
+		IWL_ERR(priv, "No space in command queue\n");
+		IWL_ERR(priv, "Restarting adapter due to queue full\n");
+		queue_work(priv->workqueue, &priv->restart);
+		return -ENOSPC;
+	}
+
+	spin_lock_irqsave(&priv->hcmd_lock, flags);
+
+	/* If this is a huge cmd, mark the huge flag also on the meta.flags
+	 * of the _original_ cmd. This is used for DMA mapping clean up.
+	 */
+	if (cmd->flags & CMD_SIZE_HUGE) {
+		idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0);
+		txq->meta[idx].flags = CMD_SIZE_HUGE;
+	}
+
+	idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
+	out_cmd = txq->cmd[idx];
+	out_meta = &txq->meta[idx];
+
+	memset(out_meta, 0, sizeof(*out_meta));	/* re-initialize to NULL */
+	out_meta->flags = cmd->flags;
+	if (cmd->flags & CMD_WANT_SKB)
+		out_meta->source = cmd;
+	if (cmd->flags & CMD_ASYNC)
+		out_meta->callback = cmd->callback;
+
+	out_cmd->hdr.cmd = cmd->id;
+	memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
+
+	/* At this point, the out_cmd now has all of the incoming cmd
+	 * information */
+
+	out_cmd->hdr.flags = 0;
+	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
+			INDEX_TO_SEQ(q->write_ptr));
+	if (cmd->flags & CMD_SIZE_HUGE)
+		out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
+	len = sizeof(struct iwl_device_cmd);
+	if (idx == TFD_CMD_SLOTS)
+		len = IWL_MAX_CMD_SIZE;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	switch (out_cmd->hdr.cmd) {
+	case REPLY_TX_LINK_QUALITY_CMD:
+	case SENSITIVITY_CMD:
+		IWL_DEBUG_HC_DUMP(priv,
+				"Sending command %s (#%x), seq: 0x%04X, "
+				"%d bytes at %d[%d]:%d\n",
+				iwl_legacy_get_cmd_string(out_cmd->hdr.cmd),
+				out_cmd->hdr.cmd,
+				le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+				q->write_ptr, idx, priv->cmd_queue);
+		break;
+	default:
+		IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
+				"%d bytes at %d[%d]:%d\n",
+				iwl_legacy_get_cmd_string(out_cmd->hdr.cmd),
+				out_cmd->hdr.cmd,
+				le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+				q->write_ptr, idx, priv->cmd_queue);
+	}
+#endif
+	txq->need_update = 1;
+
+	if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl)
+		/* Set up entry in queue's byte count circular buffer */
+		priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
+
+	phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+				   fix_size, PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_addr_set(out_meta, mapping, phys_addr);
+	dma_unmap_len_set(out_meta, len, fix_size);
+
+	trace_iwlwifi_legacy_dev_hcmd(priv, &out_cmd->hdr,
+						fix_size, cmd->flags);
+
+	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+						   phys_addr, fix_size, 1,
+						   U32_PAD(cmd->len));
+
+	/* Increment and update queue's write index */
+	q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_legacy_txq_update_write_ptr(priv, txq);
+
+	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+	return idx;
+}
+
+/**
+ * iwl_legacy_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms.  If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl_legacy_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
+				   int idx, int cmd_idx)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	int nfreed = 0;
+
+	if ((idx >= q->n_bd) || (iwl_legacy_queue_used(q, idx) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
+			  "is out of range [0-%d] %d %d.\n", txq_id,
+			  idx, q->n_bd, q->write_ptr, q->read_ptr);
+		return;
+	}
+
+	for (idx = iwl_legacy_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+	     q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		if (nfreed++ > 0) {
+			IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
+					q->write_ptr, q->read_ptr);
+			queue_work(priv->workqueue, &priv->restart);
+		}
+
+	}
+}
+
+/**
+ * iwl_legacy_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * @rxb: Rx buffer to reclaim
+ *
+ * If an Rx buffer has an async callback associated with it the callback
+ * will be executed.  The attached skb (if present) will only be freed
+ * if the callback returns 1
+ */
+void
+iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	int cmd_index;
+	bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
+	struct iwl_device_cmd *cmd;
+	struct iwl_cmd_meta *meta;
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+
+	/* If a Tx command is being handled and it isn't in the actual
+	 * command queue then there a command routing bug has been introduced
+	 * in the queue management code. */
+	if (WARN(txq_id != priv->cmd_queue,
+		 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
+		  txq_id, priv->cmd_queue, sequence,
+		  priv->txq[priv->cmd_queue].q.read_ptr,
+		  priv->txq[priv->cmd_queue].q.write_ptr)) {
+		iwl_print_hex_error(priv, pkt, 32);
+		return;
+	}
+
+	/* If this is a huge cmd, clear the huge flag on the meta.flags
+	 * of the _original_ cmd. So that iwl_legacy_cmd_queue_free won't unmap
+	 * the DMA buffer for the scan (huge) command.
+	 */
+	if (huge) {
+		cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, 0);
+		txq->meta[cmd_index].flags = 0;
+	}
+	cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge);
+	cmd = txq->cmd[cmd_index];
+	meta = &txq->meta[cmd_index];
+
+	pci_unmap_single(priv->pci_dev,
+			 dma_unmap_addr(meta, mapping),
+			 dma_unmap_len(meta, len),
+			 PCI_DMA_BIDIRECTIONAL);
+
+	/* Input error checking is done when commands are added to queue. */
+	if (meta->flags & CMD_WANT_SKB) {
+		meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+		rxb->page = NULL;
+	} else if (meta->callback)
+		meta->callback(priv, cmd, pkt);
+
+	iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
+
+	if (!(meta->flags & CMD_ASYNC)) {
+		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+		IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
+			       iwl_legacy_get_cmd_string(cmd->hdr.cmd));
+		wake_up_interruptible(&priv->wait_command_queue);
+	}
+	meta->flags = 0;
+}
+EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete);
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
new file mode 100644
index 0000000..ab87e1b
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -0,0 +1,4293 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/ieee80211_radiotap.h>
+#include <net/mac80211.h>
+
+#include <asm/div64.h>
+
+#define DRV_NAME	"iwl3945"
+
+#include "iwl-fh.h"
+#include "iwl-3945-fh.h"
+#include "iwl-commands.h"
+#include "iwl-sta.h"
+#include "iwl-3945.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-dev.h"
+#include "iwl-spectrum.h"
+
+/*
+ * module name, copyright, version, etc.
+ */
+
+#define DRV_DESCRIPTION	\
+"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+/*
+ * add "s" to indicate spectrum measurement included.
+ * we add it here to be consistent with previous releases in which
+ * this was configurable.
+ */
+#define DRV_VERSION  IWLWIFI_VERSION VD "s"
+#define DRV_COPYRIGHT	"Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR     "<ilw@linux.intel.com>"
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+
+ /* module parameters */
+struct iwl_mod_params iwl3945_mod_params = {
+	.sw_crypto = 1,
+	.restart_fw = 1,
+	/* the rest are 0 by default */
+};
+
+/**
+ * iwl3945_get_antenna_flags - Get antenna flags for RXON command
+ * @priv: eeprom and antenna fields are used to determine antenna flags
+ *
+ * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
+ * iwl3945_mod_params.antenna specifies the antenna diversity mode:
+ *
+ * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
+ * IWL_ANTENNA_MAIN      - Force MAIN antenna
+ * IWL_ANTENNA_AUX       - Force AUX antenna
+ */
+__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+
+	switch (iwl3945_mod_params.antenna) {
+	case IWL_ANTENNA_DIVERSITY:
+		return 0;
+
+	case IWL_ANTENNA_MAIN:
+		if (eeprom->antenna_switch_type)
+			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+
+	case IWL_ANTENNA_AUX:
+		if (eeprom->antenna_switch_type)
+			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+	}
+
+	/* bad antenna selector value */
+	IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
+		iwl3945_mod_params.antenna);
+
+	return 0;		/* "diversity" is default if error */
+}
+
+static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+				   struct ieee80211_key_conf *keyconf,
+				   u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	int ret;
+
+	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+
+	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	keyconf->hw_key_idx = keyconf->keyidx;
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+	       keyconf->keylen);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+	       keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	* in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
+
+	ret = iwl_legacy_send_add_sta(priv,
+				&priv->stations[sta_id].sta, CMD_ASYNC);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
+}
+
+static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+				  struct ieee80211_key_conf *keyconf,
+				  u8 sta_id)
+{
+	return -EOPNOTSUPP;
+}
+
+static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
+				  struct ieee80211_key_conf *keyconf,
+				  u8 sta_id)
+{
+	return -EOPNOTSUPP;
+}
+
+static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
+{
+	unsigned long flags;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
+	memset(&priv->stations[sta_id].sta.key, 0,
+		sizeof(struct iwl4965_keyinfo));
+	priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
+			struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+	int ret = 0;
+
+	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
+		break;
+	default:
+		IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
+			keyconf->cipher);
+		ret = -EINVAL;
+	}
+
+	IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
+		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
+		      sta_id, ret);
+
+	return ret;
+}
+
+static int iwl3945_remove_static_key(struct iwl_priv *priv)
+{
+	int ret = -EOPNOTSUPP;
+
+	return ret;
+}
+
+static int iwl3945_set_static_key(struct iwl_priv *priv,
+				struct ieee80211_key_conf *key)
+{
+	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	    key->cipher == WLAN_CIPHER_SUITE_WEP104)
+		return -EOPNOTSUPP;
+
+	IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
+	return -EINVAL;
+}
+
+static void iwl3945_clear_free_frames(struct iwl_priv *priv)
+{
+	struct list_head *element;
+
+	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
+		       priv->frames_count);
+
+	while (!list_empty(&priv->free_frames)) {
+		element = priv->free_frames.next;
+		list_del(element);
+		kfree(list_entry(element, struct iwl3945_frame, list));
+		priv->frames_count--;
+	}
+
+	if (priv->frames_count) {
+		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
+			    priv->frames_count);
+		priv->frames_count = 0;
+	}
+}
+
+static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
+{
+	struct iwl3945_frame *frame;
+	struct list_head *element;
+	if (list_empty(&priv->free_frames)) {
+		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
+		if (!frame) {
+			IWL_ERR(priv, "Could not allocate frame!\n");
+			return NULL;
+		}
+
+		priv->frames_count++;
+		return frame;
+	}
+
+	element = priv->free_frames.next;
+	list_del(element);
+	return list_entry(element, struct iwl3945_frame, list);
+}
+
+static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
+{
+	memset(frame, 0, sizeof(*frame));
+	list_add(&frame->list, &priv->free_frames);
+}
+
+unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
+				struct ieee80211_hdr *hdr,
+				int left)
+{
+
+	if (!iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
+		return 0;
+
+	if (priv->beacon_skb->len > left)
+		return 0;
+
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
+
+	return priv->beacon_skb->len;
+}
+
+static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
+{
+	struct iwl3945_frame *frame;
+	unsigned int frame_size;
+	int rc;
+	u8 rate;
+
+	frame = iwl3945_get_free_frame(priv);
+
+	if (!frame) {
+		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
+			  "command.\n");
+		return -ENOMEM;
+	}
+
+	rate = iwl_legacy_get_lowest_plcp(priv,
+				&priv->contexts[IWL_RXON_CTX_BSS]);
+
+	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
+
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+			      &frame->u.cmd[0]);
+
+	iwl3945_free_frame(priv, frame);
+
+	return rc;
+}
+
+static void iwl3945_unset_hw_params(struct iwl_priv *priv)
+{
+	if (priv->_3945.shared_virt)
+		dma_free_coherent(&priv->pci_dev->dev,
+				  sizeof(struct iwl3945_shared),
+				  priv->_3945.shared_virt,
+				  priv->_3945.shared_phys);
+}
+
+static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
+				      struct ieee80211_tx_info *info,
+				      struct iwl_device_cmd *cmd,
+				      struct sk_buff *skb_frag,
+				      int sta_id)
+{
+	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
+
+	tx_cmd->sec_ctl = 0;
+
+	switch (keyinfo->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+		memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
+		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
+		break;
+
+	case WLAN_CIPHER_SUITE_TKIP:
+		break;
+
+	case WLAN_CIPHER_SUITE_WEP104:
+		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+		/* fall through */
+	case WLAN_CIPHER_SUITE_WEP40:
+		tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
+		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
+
+		memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
+
+		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
+			     "with key %d\n", info->control.hw_key->hw_key_idx);
+		break;
+
+	default:
+		IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
+		break;
+	}
+}
+
+/*
+ * handle build REPLY_TX command notification.
+ */
+static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
+				  struct iwl_device_cmd *cmd,
+				  struct ieee80211_tx_info *info,
+				  struct ieee80211_hdr *hdr, u8 std_id)
+{
+	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+	__le32 tx_flags = tx_cmd->tx_flags;
+	__le16 fc = hdr->frame_control;
+
+	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+		tx_flags |= TX_CMD_FLG_ACK_MSK;
+		if (ieee80211_is_mgmt(fc))
+			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+		if (ieee80211_is_probe_resp(fc) &&
+		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
+			tx_flags |= TX_CMD_FLG_TSF_MSK;
+	} else {
+		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	tx_cmd->sta_id = std_id;
+	if (ieee80211_has_morefrags(fc))
+		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tx_cmd->tid_tspec = qc[0] & 0xf;
+		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+	} else {
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	iwl_legacy_tx_cmd_protection(priv, info, fc, &tx_flags);
+
+	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+	if (ieee80211_is_mgmt(fc)) {
+		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+		else
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+	} else {
+		tx_cmd->timeout.pm_frame_timeout = 0;
+	}
+
+	tx_cmd->driver_txop = 0;
+	tx_cmd->tx_flags = tx_flags;
+	tx_cmd->next_frame_len = 0;
+}
+
+/*
+ * start REPLY_TX command process
+ */
+static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct iwl3945_tx_cmd *tx_cmd;
+	struct iwl_tx_queue *txq = NULL;
+	struct iwl_queue *q = NULL;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	dma_addr_t phys_addr;
+	dma_addr_t txcmd_phys;
+	int txq_id = skb_get_queue_mapping(skb);
+	u16 len, idx, hdr_len;
+	u8 id;
+	u8 unicast;
+	u8 sta_id;
+	u8 tid = 0;
+	__le16 fc;
+	u8 wait_write_ptr = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
+		goto drop_unlock;
+	}
+
+	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
+		IWL_ERR(priv, "ERROR: No TX rate available.\n");
+		goto drop_unlock;
+	}
+
+	unicast = !is_multicast_ether_addr(hdr->addr1);
+	id = 0;
+
+	fc = hdr->frame_control;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (ieee80211_is_auth(fc))
+		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
+	else if (ieee80211_is_assoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
+	else if (ieee80211_is_reassoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	hdr_len = ieee80211_hdrlen(fc);
+
+	/* Find index into station table for destination station */
+	sta_id = iwl_legacy_sta_id_or_broadcast(
+			priv, &priv->contexts[IWL_RXON_CTX_BSS],
+			info->control.sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+			       hdr->addr1);
+		goto drop;
+	}
+
+	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
+
+	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		if (unlikely(tid >= MAX_TID_COUNT))
+			goto drop;
+	}
+
+	/* Descriptor for chosen Tx queue */
+	txq = &priv->txq[txq_id];
+	q = &txq->q;
+
+	if ((iwl_legacy_queue_space(q) < q->high_mark))
+		goto drop;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0);
+
+	/* Set up driver data for this TFD */
+	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
+	txq->txb[q->write_ptr].skb = skb;
+	txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	/* Init first empty entry in queue's array of Tx/cmd buffers */
+	out_cmd = txq->cmd[idx];
+	out_meta = &txq->meta[idx];
+	tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
+	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+	memset(tx_cmd, 0, sizeof(*tx_cmd));
+
+	/*
+	 * Set up the Tx-command (not MAC!) header.
+	 * Store the chosen Tx queue and TFD index within the sequence field;
+	 * after Tx, uCode's Tx response will return this value so driver can
+	 * locate the frame within the tx queue and do post-tx processing.
+	 */
+	out_cmd->hdr.cmd = REPLY_TX;
+	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+				INDEX_TO_SEQ(q->write_ptr)));
+
+	/* Copy MAC header from skb into command buffer */
+	memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+
+	if (info->control.hw_key)
+		iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
+
+	/* TODO need this for burst mode later on */
+	iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
+
+	/* set is_hcca to 0; it probably will never be implemented */
+	iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
+
+	/* Total # bytes to be transmitted */
+	len = (u16)skb->len;
+	tx_cmd->len = cpu_to_le16(len);
+
+	iwl_legacy_dbg_log_tx_data_frame(priv, len, hdr);
+	iwl_legacy_update_stats(priv, true, fc, len);
+	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+
+	if (!ieee80211_has_morefrags(hdr->frame_control)) {
+		txq->need_update = 1;
+	} else {
+		wait_write_ptr = 1;
+		txq->need_update = 0;
+	}
+
+	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
+		     le16_to_cpu(out_cmd->hdr.sequence));
+	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+	iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
+			   ieee80211_hdrlen(fc));
+
+	/*
+	 * Use the first empty entry in this queue's command buffer array
+	 * to contain the Tx command and MAC header concatenated together
+	 * (payload data will be in another buffer).
+	 * Size of this varies, due to varying MAC header length.
+	 * If end is not dword aligned, we'll have 2 extra bytes at the end
+	 * of the MAC header (device reads on dword boundaries).
+	 * We'll tell device about this padding later.
+	 */
+	len = sizeof(struct iwl3945_tx_cmd) +
+			sizeof(struct iwl_cmd_header) + hdr_len;
+	len = (len + 3) & ~3;
+
+	/* Physical address of this Tx command's header (not MAC header!),
+	 * within command buffer array. */
+	txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+				    len, PCI_DMA_TODEVICE);
+	/* we do not map meta data ... so we can safely access address to
+	 * provide to unmap command*/
+	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+	dma_unmap_len_set(out_meta, len, len);
+
+	/* Add buffer containing Tx command and MAC(!) header to TFD's
+	 * first entry */
+	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+						   txcmd_phys, len, 1, 0);
+
+
+	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+	 * if any (802.11 null frames have no payload). */
+	len = skb->len - hdr_len;
+	if (len) {
+		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
+					   len, PCI_DMA_TODEVICE);
+		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+							   phys_addr, len,
+							   0, U32_PAD(len));
+	}
+
+
+	/* Tell device the write index *just past* this latest filled TFD */
+	q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_legacy_txq_update_write_ptr(priv, txq);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if ((iwl_legacy_queue_space(q) < q->high_mark)
+	    && priv->mac80211_registered) {
+		if (wait_write_ptr) {
+			spin_lock_irqsave(&priv->lock, flags);
+			txq->need_update = 1;
+			iwl_legacy_txq_update_write_ptr(priv, txq);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
+
+		iwl_legacy_stop_queue(priv, txq);
+	}
+
+	return 0;
+
+drop_unlock:
+	spin_unlock_irqrestore(&priv->lock, flags);
+drop:
+	return -1;
+}
+
+static int iwl3945_get_measurement(struct iwl_priv *priv,
+			       struct ieee80211_measurement_params *params,
+			       u8 type)
+{
+	struct iwl_spectrum_cmd spectrum;
+	struct iwl_rx_packet *pkt;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
+		.data = (void *)&spectrum,
+		.flags = CMD_WANT_SKB,
+	};
+	u32 add_time = le64_to_cpu(params->start_time);
+	int rc;
+	int spectrum_resp_status;
+	int duration = le16_to_cpu(params->duration);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))
+		add_time = iwl_legacy_usecs_to_beacons(priv,
+			le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
+			le16_to_cpu(ctx->timing.beacon_interval));
+
+	memset(&spectrum, 0, sizeof(spectrum));
+
+	spectrum.channel_count = cpu_to_le16(1);
+	spectrum.flags =
+	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
+	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
+	cmd.len = sizeof(spectrum);
+	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))
+		spectrum.start_time =
+			iwl_legacy_add_beacon_time(priv,
+				priv->_3945.last_beacon_time, add_time,
+				le16_to_cpu(ctx->timing.beacon_interval));
+	else
+		spectrum.start_time = 0;
+
+	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
+	spectrum.channels[0].channel = params->channel;
+	spectrum.channels[0].type = type;
+	if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
+		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
+		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
+
+	rc = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (rc)
+		return rc;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
+		rc = -EIO;
+	}
+
+	spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
+	switch (spectrum_resp_status) {
+	case 0:		/* Command will be handled */
+		if (pkt->u.spectrum.id != 0xff) {
+			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
+						pkt->u.spectrum.id);
+			priv->measurement_status &= ~MEASUREMENT_READY;
+		}
+		priv->measurement_status |= MEASUREMENT_ACTIVE;
+		rc = 0;
+		break;
+
+	case 1:		/* Command will not be handled */
+		rc = -EAGAIN;
+		break;
+	}
+
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return rc;
+}
+
+static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
+			       struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_alive_resp *palive;
+	struct delayed_work *pwork;
+
+	palive = &pkt->u.alive_frame;
+
+	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+		       "0x%01X 0x%01X\n",
+		       palive->is_valid, palive->ver_type,
+		       palive->ver_subtype);
+
+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
+		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->init_alive_start;
+	} else {
+		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->alive_start;
+		iwl3945_disable_events(priv);
+	}
+
+	/* We delay the ALIVE response by 5ms to
+	 * give the HW RF Kill time to activate... */
+	if (palive->is_valid == UCODE_VALID_OK)
+		queue_delayed_work(priv->workqueue, pwork,
+				   msecs_to_jiffies(5));
+	else
+		IWL_WARN(priv, "uCode did not respond OK.\n");
+}
+
+static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
+				 struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+#endif
+
+	IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
+}
+
+static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	u8 rate = beacon->beacon_notify_hdr.rate;
+
+	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
+		"tsf %d %d rate %d\n",
+		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+#endif
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+	unsigned long status = priv->status;
+
+	IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
+
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	if (flags & HW_CARD_DISABLED)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+
+	iwl_legacy_scan_cancel(priv);
+
+	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+				test_bit(STATUS_RF_KILL_HW, &priv->status));
+	else
+		wake_up_interruptible(&priv->wait_command_queue);
+}
+
+/**
+ * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
+ *
+ * Setup the RX handlers for each of the reply types sent from the uCode
+ * to the host.
+ *
+ * This function chains into the hardware specific files for them to setup
+ * any hardware specific handlers as well.
+ */
+static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
+{
+	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
+	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
+	priv->rx_handlers[REPLY_ERROR] = iwl_legacy_rx_reply_error;
+	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_legacy_rx_csa;
+	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+			iwl_legacy_rx_spectrum_measure_notif;
+	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_legacy_rx_pm_sleep_notif;
+	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
+	    iwl_legacy_rx_pm_debug_statistics_notif;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
+
+	/*
+	 * The same handler is used for both the REPLY to a discrete
+	 * statistics request from the host as well as for the periodic
+	 * statistics notifications (after received beacons) from the uCode.
+	 */
+	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
+	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
+
+	iwl_legacy_setup_rx_scan_handlers(priv);
+	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
+
+	/* Set up hardware specific Rx handlers */
+	iwl3945_hw_rx_handler_setup(priv);
+}
+
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * The host allocates 32 DMA target addresses and passes the host address
+ * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
+ * 0 to 31
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt.  The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ INDEX is updated (updating the
+ *   'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            iwl3945_rx_queue_restock
+ * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE index.  If insufficient rx_free buffers
+ *                            are available, schedules iwl3945_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ *                            READ INDEX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls iwl3945_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
+					  dma_addr_t dma_addr)
+{
+	return cpu_to_le32((u32)dma_addr);
+}
+
+/**
+ * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	unsigned long flags;
+	int write;
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	write = rxq->write & ~0x7;
+	while ((iwl_legacy_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+		/* Get next free Rx buffer, remove from free list */
+		element = rxq->rx_free.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		/* Point to Rx buffer via next RBD in circular buffer */
+		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
+		rxq->queue[rxq->write] = rxb;
+		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+		rxq->free_count--;
+	}
+	spin_unlock_irqrestore(&rxq->lock, flags);
+	/* If the pre-allocated buffer pool is dropping low, schedule to
+	 * refill it */
+	if (rxq->free_count <= RX_LOW_WATERMARK)
+		queue_work(priv->workqueue, &priv->rx_replenish);
+
+
+	/* If we've added more space for the firmware to place data, tell it.
+	 * Increment device's write pointer in multiples of 8. */
+	if ((rxq->write_actual != (rxq->write & ~0x7))
+	    || (abs(rxq->write - rxq->read) > 7)) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		rxq->need_update = 1;
+		spin_unlock_irqrestore(&rxq->lock, flags);
+		iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+	}
+}
+
+/**
+ * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl3945_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	struct page *page;
+	unsigned long flags;
+	gfp_t gfp_mask = priority;
+
+	while (1) {
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			return;
+		}
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			gfp_mask |= __GFP_NOWARN;
+
+		if (priv->hw_params.rx_page_order > 0)
+			gfp_mask |= __GFP_COMP;
+
+		/* Alloc a new receive buffer */
+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
+		if (!page) {
+			if (net_ratelimit())
+				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
+			/* We don't reschedule replenish work here -- we will
+			 * call the restock method and if it still needs
+			 * more buffers it will schedule replenish */
+			break;
+		}
+
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			__free_pages(page, priv->hw_params.rx_page_order);
+			return;
+		}
+		element = rxq->rx_used.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		rxb->page = page;
+		/* Get physical address of RB/SKB */
+		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		list_add_tail(&rxb->list, &rxq->rx_free);
+		rxq->free_count++;
+		priv->alloc_rxb_page++;
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+	}
+}
+
+void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	unsigned long flags;
+	int i;
+	spin_lock_irqsave(&rxq->lock, flags);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+		/* In the reset function, these buffers may have been allocated
+		 * to an SKB, so we need to unmap and free potential storage */
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+	}
+
+	/* Set us so that we have processed and used all buffers, but have
+	 * not restocked the Rx queue with fresh buffers */
+	rxq->read = rxq->write = 0;
+	rxq->write_actual = 0;
+	rxq->free_count = 0;
+	spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+void iwl3945_rx_replenish(void *data)
+{
+	struct iwl_priv *priv = data;
+	unsigned long flags;
+
+	iwl3945_rx_allocate(priv, GFP_KERNEL);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl3945_rx_queue_restock(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void iwl3945_rx_replenish_now(struct iwl_priv *priv)
+{
+	iwl3945_rx_allocate(priv, GFP_ATOMIC);
+
+	iwl3945_rx_queue_restock(priv);
+}
+
+
+/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
+ * This free routine walks the list of POOL entries and if SKB is set to
+ * non NULL it is unmapped and freed
+ */
+static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	int i;
+	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+	}
+
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->bd_dma);
+	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+			  rxq->rb_stts, rxq->rb_stts_dma);
+	rxq->bd = NULL;
+	rxq->rb_stts  = NULL;
+}
+
+
+/* Convert linear signal-to-noise ratio into dB */
+static u8 ratio2dB[100] = {
+/*	 0   1   2   3   4   5   6   7   8   9 */
+	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
+	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
+	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
+	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
+	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
+	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
+	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
+	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
+	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
+	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
+};
+
+/* Calculates a relative dB value from a ratio of linear
+ *   (i.e. not dB) signal levels.
+ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
+int iwl3945_calc_db_from_ratio(int sig_ratio)
+{
+	/* 1000:1 or higher just report as 60 dB */
+	if (sig_ratio >= 1000)
+		return 60;
+
+	/* 100:1 or higher, divide by 10 and use table,
+	 *   add 20 dB to make up for divide by 10 */
+	if (sig_ratio >= 100)
+		return 20 + (int)ratio2dB[sig_ratio/10];
+
+	/* We shouldn't see this */
+	if (sig_ratio < 1)
+		return 0;
+
+	/* Use table for ratios 1:1 - 99:1 */
+	return (int)ratio2dB[sig_ratio];
+}
+
+/**
+ * iwl3945_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the priv->rx_handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+static void iwl3945_rx_handle(struct iwl_priv *priv)
+{
+	struct iwl_rx_mem_buffer *rxb;
+	struct iwl_rx_packet *pkt;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	u32 r, i;
+	int reclaim;
+	unsigned long flags;
+	u8 fill_rx = 0;
+	u32 count = 8;
+	int total_empty = 0;
+
+	/* uCode's read index (stored in shared DRAM) indicates the last Rx
+	 * buffer that the driver may process (last buffer filled by ucode). */
+	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
+	i = rxq->read;
+
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - rxq->write_actual;
+	if (total_empty < 0)
+		total_empty += RX_QUEUE_SIZE;
+
+	if (total_empty > (RX_QUEUE_SIZE / 2))
+		fill_rx = 1;
+	/* Rx interrupt, but nothing sent from uCode */
+	if (i == r)
+		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
+
+	while (i != r) {
+		int len;
+
+		rxb = rxq->queue[i];
+
+		/* If an RXB doesn't have a Rx queue slot associated with it,
+		 * then a bug has been introduced in the queue refilling
+		 * routines -- catch it here */
+		BUG_ON(rxb == NULL);
+
+		rxq->queue[i] = NULL;
+
+		pci_unmap_page(priv->pci_dev, rxb->page_dma,
+			       PAGE_SIZE << priv->hw_params.rx_page_order,
+			       PCI_DMA_FROMDEVICE);
+		pkt = rxb_addr(rxb);
+
+		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+		len += sizeof(u32); /* account for status word */
+		trace_iwlwifi_legacy_dev_rx(priv, pkt, len);
+
+		/* Reclaim a command buffer only if this packet is a response
+		 *   to a (driver-originated) command.
+		 * If the packet (e.g. Rx frame) originated from uCode,
+		 *   there is no command buffer to reclaim.
+		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+		 *   but apparently a few don't get set; catch them here. */
+		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+			(pkt->hdr.cmd != REPLY_TX);
+
+		/* Based on type of command response or notification,
+		 *   handle those that need handling via function in
+		 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
+		if (priv->rx_handlers[pkt->hdr.cmd]) {
+			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
+			iwl_legacy_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+		} else {
+			/* No handling needed */
+			IWL_DEBUG_RX(priv,
+				"r %d i %d No handler needed for %s, 0x%02x\n",
+				r, i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+		}
+
+		/*
+		 * XXX: After here, we should always check rxb->page
+		 * against NULL before touching it or its virtual
+		 * memory (pkt). Because some rx_handler might have
+		 * already taken or freed the pages.
+		 */
+
+		if (reclaim) {
+			/* Invoke any callbacks, transfer the buffer to caller,
+			 * and fire off the (possibly) blocking iwl_legacy_send_cmd()
+			 * as we reclaim the driver command queue */
+			if (rxb->page)
+				iwl_legacy_tx_cmd_complete(priv, rxb);
+			else
+				IWL_WARN(priv, "Claim null rxb?\n");
+		}
+
+		/* Reuse the page if possible. For notification packets and
+		 * SKBs that fail to Rx correctly, add them back into the
+		 * rx_free list for reuse later. */
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (rxb->page != NULL) {
+			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+				0, PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			list_add_tail(&rxb->list, &rxq->rx_free);
+			rxq->free_count++;
+		} else
+			list_add_tail(&rxb->list, &rxq->rx_used);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		i = (i + 1) & RX_QUEUE_MASK;
+		/* If there are a lot of unused frames,
+		 * restock the Rx queue so ucode won't assert. */
+		if (fill_rx) {
+			count++;
+			if (count >= 8) {
+				rxq->read = i;
+				iwl3945_rx_replenish_now(priv);
+				count = 0;
+			}
+		}
+	}
+
+	/* Backtrack one entry */
+	rxq->read = i;
+	if (fill_rx)
+		iwl3945_rx_replenish_now(priv);
+	else
+		iwl3945_rx_queue_restock(priv);
+}
+
+/* call this function to flush any scheduled tasklet */
+static inline void iwl3945_synchronize_irq(struct iwl_priv *priv)
+{
+	/* wait to make sure we flush pending tasklet*/
+	synchronize_irq(priv->pci_dev->irq);
+	tasklet_kill(&priv->irq_tasklet);
+}
+
+static const char *iwl3945_desc_lookup(int i)
+{
+	switch (i) {
+	case 1:
+		return "FAIL";
+	case 2:
+		return "BAD_PARAM";
+	case 3:
+		return "BAD_CHECKSUM";
+	case 4:
+		return "NMI_INTERRUPT";
+	case 5:
+		return "SYSASSERT";
+	case 6:
+		return "FATAL_ERROR";
+	}
+
+	return "UNKNOWN";
+}
+
+#define ERROR_START_OFFSET  (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+{
+	u32 i;
+	u32 desc, time, count, base, data1;
+	u32 blink1, blink2, ilink1, ilink2;
+
+	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+		return;
+	}
+
+
+	count = iwl_legacy_read_targ_mem(priv, base);
+
+	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+			priv->status, count);
+	}
+
+	IWL_ERR(priv, "Desc       Time       asrtPC  blink2 "
+		  "ilink1  nmiPC   Line\n");
+	for (i = ERROR_START_OFFSET;
+	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
+	     i += ERROR_ELEM_SIZE) {
+		desc = iwl_legacy_read_targ_mem(priv, base + i);
+		time =
+		    iwl_legacy_read_targ_mem(priv, base + i + 1 * sizeof(u32));
+		blink1 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 2 * sizeof(u32));
+		blink2 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 3 * sizeof(u32));
+		ilink1 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 4 * sizeof(u32));
+		ilink2 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 5 * sizeof(u32));
+		data1 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 6 * sizeof(u32));
+
+		IWL_ERR(priv,
+			"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+			iwl3945_desc_lookup(desc), desc, time, blink1, blink2,
+			ilink1, ilink2, data1);
+		trace_iwlwifi_legacy_dev_ucode_error(priv, desc, time, data1, 0,
+					0, blink1, blink2, ilink1, ilink2);
+	}
+}
+
+#define EVENT_START_OFFSET  (6 * sizeof(u32))
+
+/**
+ * iwl3945_print_event_log - Dump error event log to syslog
+ *
+ */
+static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
+				  u32 num_events, u32 mode,
+				  int pos, char **buf, size_t bufsz)
+{
+	u32 i;
+	u32 base;       /* SRAM byte address of event log header */
+	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
+	u32 ptr;        /* SRAM byte address of log data */
+	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
+
+	if (num_events == 0)
+		return pos;
+
+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+	if (mode == 0)
+		event_size = 2 * sizeof(u32);
+	else
+		event_size = 3 * sizeof(u32);
+
+	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
+	/* "time" is actually "data" for mode 0 (no timestamp).
+	 * place event id # at far right for easier visual parsing. */
+	for (i = 0; i < num_events; i++) {
+		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (mode == 0) {
+			/* data, ev */
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"0x%08x:%04u\n",
+						time, ev);
+			} else {
+				IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
+				trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
+							      time, ev);
+			}
+		} else {
+			data = _iwl_legacy_read_direct32(priv,
+							HBUS_TARG_MEM_RDAT);
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"%010u:0x%08x:%04u\n",
+						 time, data, ev);
+			} else {
+				IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
+					time, data, ev);
+				trace_iwlwifi_legacy_dev_ucode_event(priv, time,
+							      data, ev);
+			}
+		}
+	}
+
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return pos;
+}
+
+/**
+ * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
+ */
+static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+				      u32 num_wraps, u32 next_entry,
+				      u32 size, u32 mode,
+				      int pos, char **buf, size_t bufsz)
+{
+	/*
+	 * display the newest DEFAULT_LOG_ENTRIES entries
+	 * i.e the entries just before the next ont that uCode would fill.
+	 */
+	if (num_wraps) {
+		if (next_entry < size) {
+			pos = iwl3945_print_event_log(priv,
+					     capacity - (size - next_entry),
+					     size - next_entry, mode,
+					     pos, buf, bufsz);
+			pos = iwl3945_print_event_log(priv, 0,
+						      next_entry, mode,
+						      pos, buf, bufsz);
+		} else
+			pos = iwl3945_print_event_log(priv, next_entry - size,
+						      size, mode,
+						      pos, buf, bufsz);
+	} else {
+		if (next_entry < size)
+			pos = iwl3945_print_event_log(priv, 0,
+						      next_entry, mode,
+						      pos, buf, bufsz);
+		else
+			pos = iwl3945_print_event_log(priv, next_entry - size,
+						      size, mode,
+						      pos, buf, bufsz);
+	}
+	return pos;
+}
+
+#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
+
+int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
+			    char **buf, bool display)
+{
+	u32 base;       /* SRAM byte address of event log header */
+	u32 capacity;   /* event log capacity in # entries */
+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+	u32 num_wraps;  /* # times uCode wrapped to top of log */
+	u32 next_entry; /* index of next entry to be written by uCode */
+	u32 size;       /* # entries that we'll print */
+	int pos = 0;
+	size_t bufsz = 0;
+
+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+		return  -EINVAL;
+	}
+
+	/* event log header */
+	capacity = iwl_legacy_read_targ_mem(priv, base);
+	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
+	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
+	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+	if (capacity > priv->cfg->base_params->max_event_log_size) {
+		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
+			capacity, priv->cfg->base_params->max_event_log_size);
+		capacity = priv->cfg->base_params->max_event_log_size;
+	}
+
+	if (next_entry > priv->cfg->base_params->max_event_log_size) {
+		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
+			next_entry, priv->cfg->base_params->max_event_log_size);
+		next_entry = priv->cfg->base_params->max_event_log_size;
+	}
+
+	size = num_wraps ? capacity : next_entry;
+
+	/* bail out if nothing in log */
+	if (size == 0) {
+		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+		return pos;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
+		size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
+			? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
+#else
+	size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
+		? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
+#endif
+
+	IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
+		  size);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (display) {
+		if (full_log)
+			bufsz = capacity * 48;
+		else
+			bufsz = size * 48;
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+	}
+	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
+		/* if uCode has wrapped back to top of log,
+		 * start at the oldest entry,
+		 * i.e the next one that uCode would fill.
+		 */
+		if (num_wraps)
+			pos = iwl3945_print_event_log(priv, next_entry,
+						capacity - next_entry, mode,
+						pos, buf, bufsz);
+
+		/* (then/else) start at top of log */
+		pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
+					      pos, buf, bufsz);
+	} else
+		pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+						    next_entry, size, mode,
+						    pos, buf, bufsz);
+#else
+	pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+					    next_entry, size, mode,
+					    pos, buf, bufsz);
+#endif
+	return pos;
+}
+
+static void iwl3945_irq_tasklet(struct iwl_priv *priv)
+{
+	u32 inta, handled = 0;
+	u32 inta_fh;
+	unsigned long flags;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	u32 inta_mask;
+#endif
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Ack/clear/reset pending uCode interrupts.
+	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
+	inta = iwl_read32(priv, CSR_INT);
+	iwl_write32(priv, CSR_INT, inta);
+
+	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
+	 * Any new interrupts that happen after this, either while we're
+	 * in this tasklet, or later, will show up in next ISR/tasklet. */
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & IWL_DL_ISR) {
+		/* just for debug */
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+			      inta, inta_mask, inta_fh);
+	}
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
+	 * atomic, make sure that inta covers all the interrupts that
+	 * we've discovered, even if FH interrupt came in just after
+	 * reading CSR_INT. */
+	if (inta_fh & CSR39_FH_INT_RX_MASK)
+		inta |= CSR_INT_BIT_FH_RX;
+	if (inta_fh & CSR39_FH_INT_TX_MASK)
+		inta |= CSR_INT_BIT_FH_TX;
+
+	/* Now service all interrupt bits discovered above. */
+	if (inta & CSR_INT_BIT_HW_ERR) {
+		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
+
+		/* Tell the device to stop sending interrupts */
+		iwl_legacy_disable_interrupts(priv);
+
+		priv->isr_stats.hw++;
+		iwl_legacy_irq_handle_error(priv);
+
+		handled |= CSR_INT_BIT_HW_ERR;
+
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
+		/* NIC fires this, but we don't use it, redundant with WAKEUP */
+		if (inta & CSR_INT_BIT_SCD) {
+			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
+				      "the frame/frames.\n");
+			priv->isr_stats.sch++;
+		}
+
+		/* Alive notification via Rx interrupt will do the real work */
+		if (inta & CSR_INT_BIT_ALIVE) {
+			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+			priv->isr_stats.alive++;
+		}
+	}
+#endif
+	/* Safely ignore these bits for debug checks below */
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+	/* Error detected by uCode */
+	if (inta & CSR_INT_BIT_SW_ERR) {
+		IWL_ERR(priv, "Microcode SW error detected. "
+			"Restarting 0x%X.\n", inta);
+		priv->isr_stats.sw++;
+		iwl_legacy_irq_handle_error(priv);
+		handled |= CSR_INT_BIT_SW_ERR;
+	}
+
+	/* uCode wakes up after power-down sleep */
+	if (inta & CSR_INT_BIT_WAKEUP) {
+		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
+		iwl_legacy_rx_queue_update_write_ptr(priv, &priv->rxq);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[0]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[1]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[2]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[3]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[4]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[5]);
+
+		priv->isr_stats.wakeup++;
+		handled |= CSR_INT_BIT_WAKEUP;
+	}
+
+	/* All uCode command responses, including Tx command responses,
+	 * Rx "responses" (frame-received notification), and other
+	 * notifications from uCode come through here*/
+	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+		iwl3945_rx_handle(priv);
+		priv->isr_stats.rx++;
+		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+	}
+
+	if (inta & CSR_INT_BIT_FH_TX) {
+		IWL_DEBUG_ISR(priv, "Tx interrupt\n");
+		priv->isr_stats.tx++;
+
+		iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
+		iwl_legacy_write_direct32(priv, FH39_TCSR_CREDIT
+					(FH39_SRVC_CHNL), 0x0);
+		handled |= CSR_INT_BIT_FH_TX;
+	}
+
+	if (inta & ~handled) {
+		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+		priv->isr_stats.unhandled++;
+	}
+
+	if (inta & ~priv->inta_mask) {
+		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
+			 inta & ~priv->inta_mask);
+		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
+	}
+
+	/* Re-enable all interrupts */
+	/* only Re-enable if disabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_legacy_enable_interrupts(priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
+		inta = iwl_read32(priv, CSR_INT);
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+		IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+	}
+#endif
+}
+
+static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
+					       struct ieee80211_vif *vif,
+					       enum ieee80211_band band,
+					       struct iwl3945_scan_channel *scan_ch)
+{
+	const struct ieee80211_supported_band *sband;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added = 0;
+	u8 channel = 0;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband) {
+		IWL_ERR(priv, "invalid band\n");
+		return added;
+	}
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+
+	channel = iwl_legacy_get_single_channel_number(priv, band);
+
+	if (channel) {
+		scan_ch->channel = channel;
+		scan_ch->type = 0;	/* passive */
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* Set txpower levels to defaults */
+		scan_ch->tpc.dsp_atten = 110;
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+		added++;
+	} else
+		IWL_ERR(priv, "no valid channel found\n");
+	return added;
+}
+
+static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
+					 enum ieee80211_band band,
+				     u8 is_active, u8 n_probes,
+				     struct iwl3945_scan_channel *scan_ch,
+				     struct ieee80211_vif *vif)
+{
+	struct ieee80211_channel *chan;
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added, i;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband)
+		return 0;
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, n_probes);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+		chan = priv->scan_request->channels[i];
+
+		if (chan->band != band)
+			continue;
+
+		scan_ch->channel = chan->hw_value;
+
+		ch_info = iwl_legacy_get_channel_info(priv, band,
+							scan_ch->channel);
+		if (!iwl_legacy_is_channel_valid(ch_info)) {
+			IWL_DEBUG_SCAN(priv,
+				"Channel %d is INVALID for this band.\n",
+			       scan_ch->channel);
+			continue;
+		}
+
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* If passive , set up for auto-switch
+		 *  and use long active_dwell time.
+		 */
+		if (!is_active || iwl_legacy_is_channel_passive(ch_info) ||
+		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+			scan_ch->type = 0;	/* passive */
+			if (IWL_UCODE_API(priv->ucode_ver) == 1)
+				scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
+		} else {
+			scan_ch->type = 1;	/* active */
+		}
+
+		/* Set direct probe bits. These may be used both for active
+		 * scan channels (probes gets sent right away),
+		 * or for passive channels (probes get se sent only after
+		 * hearing clear Rx packet).*/
+		if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+			if (n_probes)
+				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
+		} else {
+			/* uCode v1 does not allow setting direct probe bits on
+			 * passive channel. */
+			if ((scan_ch->type & 1) && n_probes)
+				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
+		}
+
+		/* Set txpower levels to defaults */
+		scan_ch->tpc.dsp_atten = 110;
+		/* scan_pwr_info->tpc.dsp_atten; */
+
+		/*scan_pwr_info->tpc.tx_gain; */
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else {
+			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+			 * power level:
+			 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
+			 */
+		}
+
+		IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n",
+			       scan_ch->channel,
+			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
+			       (scan_ch->type & 1) ?
+			       active_dwell : passive_dwell);
+
+		scan_ch++;
+		added++;
+	}
+
+	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+	return added;
+}
+
+static void iwl3945_init_hw_rates(struct iwl_priv *priv,
+			      struct ieee80211_rate *rates)
+{
+	int i;
+
+	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
+		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
+		rates[i].hw_value = i; /* Rate scaling will work on indexes */
+		rates[i].hw_value_short = i;
+		rates[i].flags = 0;
+		if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+			/*
+			 * If CCK != 1M then set short preamble rate flag.
+			 */
+			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
+				0 : IEEE80211_RATE_SHORT_PREAMBLE;
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ * uCode download functions
+ *
+ ******************************************************************************/
+
+static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv)
+{
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
+}
+
+/**
+ * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
+ *     looking at all data.
+ */
+static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len)
+{
+	u32 val;
+	u32 save_len = len;
+	int rc = 0;
+	u32 errcnt;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			       IWL39_RTC_INST_LOWER_BOUND);
+
+	errcnt = 0;
+	for (; len > 0; len -= sizeof(u32), image++) {
+		/* read data comes through single port, auto-incr addr */
+		/* NOTE: Use the debugless read so we don't flood kernel log
+		 * if IWL_DL_IO is set */
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "uCode INST section is invalid at "
+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+				  save_len - len, val, le32_to_cpu(*image));
+			rc = -EIO;
+			errcnt++;
+			if (errcnt >= 20)
+				break;
+		}
+	}
+
+
+	if (!errcnt)
+		IWL_DEBUG_INFO(priv,
+			"ucode image in INSTRUCTION memory is good\n");
+
+	return rc;
+}
+
+
+/**
+ * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
+ *   using sample data 100 bytes apart.  If these sample points are good,
+ *   it's a pretty good bet that everything between them is good, too.
+ */
+static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+{
+	u32 val;
+	int rc = 0;
+	u32 errcnt = 0;
+	u32 i;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
+		/* read data comes through single port, auto-incr addr */
+		/* NOTE: Use the debugless read so we don't flood kernel log
+		 * if IWL_DL_IO is set */
+		iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			i + IWL39_RTC_INST_LOWER_BOUND);
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+#if 0 /* Enable this if you want to see details */
+			IWL_ERR(priv, "uCode INST section is invalid at "
+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+				  i, val, *image);
+#endif
+			rc = -EIO;
+			errcnt++;
+			if (errcnt >= 3)
+				break;
+		}
+	}
+
+	return rc;
+}
+
+
+/**
+ * iwl3945_verify_ucode - determine which instruction image is in SRAM,
+ *    and verify its contents
+ */
+static int iwl3945_verify_ucode(struct iwl_priv *priv)
+{
+	__le32 *image;
+	u32 len;
+	int rc = 0;
+
+	/* Try bootstrap */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	rc = iwl3945_verify_inst_sparse(priv, image, len);
+	if (rc == 0) {
+		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try initialize */
+	image = (__le32 *)priv->ucode_init.v_addr;
+	len = priv->ucode_init.len;
+	rc = iwl3945_verify_inst_sparse(priv, image, len);
+	if (rc == 0) {
+		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try runtime/protocol */
+	image = (__le32 *)priv->ucode_code.v_addr;
+	len = priv->ucode_code.len;
+	rc = iwl3945_verify_inst_sparse(priv, image, len);
+	if (rc == 0) {
+		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+
+	/* Since nothing seems to match, show first several data entries in
+	 * instruction SRAM, so maybe visual inspection will give a clue.
+	 * Selection of bootstrap image (vs. other images) is arbitrary. */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	rc = iwl3945_verify_inst_full(priv, image, len);
+
+	return rc;
+}
+
+static void iwl3945_nic_start(struct iwl_priv *priv)
+{
+	/* Remove all resets to allow NIC to operate */
+	iwl_write32(priv, CSR_RESET, 0);
+}
+
+#define IWL3945_UCODE_GET(item)						\
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
+{									\
+	return le32_to_cpu(ucode->v1.item);				\
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+	return 24;
+}
+
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
+{
+	return (u8 *) ucode->v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
+/**
+ * iwl3945_read_ucode - Read uCode images from disk file.
+ *
+ * Copy into buffers for card to fetch via bus-mastering
+ */
+static int iwl3945_read_ucode(struct iwl_priv *priv)
+{
+	const struct iwl_ucode_header *ucode;
+	int ret = -EINVAL, index;
+	const struct firmware *ucode_raw;
+	/* firmware file name contains uCode/driver compatibility version */
+	const char *name_pre = priv->cfg->fw_name_pre;
+	const unsigned int api_max = priv->cfg->ucode_api_max;
+	const unsigned int api_min = priv->cfg->ucode_api_min;
+	char buf[25];
+	u8 *src;
+	size_t len;
+	u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
+
+	/* Ask kernel firmware_class module to get the boot firmware off disk.
+	 * request_firmware() is synchronous, file is in memory on return. */
+	for (index = api_max; index >= api_min; index--) {
+		sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
+		ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
+		if (ret < 0) {
+			IWL_ERR(priv, "%s firmware file req failed: %d\n",
+				  buf, ret);
+			if (ret == -ENOENT)
+				continue;
+			else
+				goto error;
+		} else {
+			if (index < api_max)
+				IWL_ERR(priv, "Loaded firmware %s, "
+					"which is deprecated. "
+					" Please use API v%u instead.\n",
+					  buf, api_max);
+			IWL_DEBUG_INFO(priv, "Got firmware '%s' file "
+				       "(%zd bytes) from disk\n",
+				       buf, ucode_raw->size);
+			break;
+		}
+	}
+
+	if (ret < 0)
+		goto error;
+
+	/* Make sure that we got at least our header! */
+	if (ucode_raw->size <  iwl3945_ucode_get_header_size(1)) {
+		IWL_ERR(priv, "File size way too small!\n");
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	/* Data from ucode file:  header followed by uCode images */
+	ucode = (struct iwl_ucode_header *)ucode_raw->data;
+
+	priv->ucode_ver = le32_to_cpu(ucode->ver);
+	api_ver = IWL_UCODE_API(priv->ucode_ver);
+	inst_size = iwl3945_ucode_get_inst_size(ucode);
+	data_size = iwl3945_ucode_get_data_size(ucode);
+	init_size = iwl3945_ucode_get_init_size(ucode);
+	init_data_size = iwl3945_ucode_get_init_data_size(ucode);
+	boot_size = iwl3945_ucode_get_boot_size(ucode);
+	src = iwl3945_ucode_get_data(ucode);
+
+	/* api_ver should match the api version forming part of the
+	 * firmware filename ... but we don't check for that and only rely
+	 * on the API version read from firmware header from here on forward */
+
+	if (api_ver < api_min || api_ver > api_max) {
+		IWL_ERR(priv, "Driver unable to support your firmware API. "
+			  "Driver supports v%u, firmware is v%u.\n",
+			  api_max, api_ver);
+		priv->ucode_ver = 0;
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (api_ver != api_max)
+		IWL_ERR(priv, "Firmware has old API version. Expected %u, "
+			  "got %u. New firmware can be obtained "
+			  "from http://www.intellinuxwireless.org.\n",
+			  api_max, api_ver);
+
+	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
+		IWL_UCODE_MAJOR(priv->ucode_ver),
+		IWL_UCODE_MINOR(priv->ucode_ver),
+		IWL_UCODE_API(priv->ucode_ver),
+		IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	snprintf(priv->hw->wiphy->fw_version,
+		 sizeof(priv->hw->wiphy->fw_version),
+		 "%u.%u.%u.%u",
+		 IWL_UCODE_MAJOR(priv->ucode_ver),
+		 IWL_UCODE_MINOR(priv->ucode_ver),
+		 IWL_UCODE_API(priv->ucode_ver),
+		 IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
+		       priv->ucode_ver);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
+		       inst_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
+		       data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
+		       init_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
+		       init_data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
+		       boot_size);
+
+
+	/* Verify size of file vs. image size info in file's header */
+	if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
+		inst_size + data_size + init_size +
+		init_data_size + boot_size) {
+
+		IWL_DEBUG_INFO(priv,
+			"uCode file size %zd does not match expected size\n",
+			ucode_raw->size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	/* Verify that uCode images will fit in card's SRAM */
+	if (inst_size > IWL39_MAX_INST_SIZE) {
+		IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
+			       inst_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	if (data_size > IWL39_MAX_DATA_SIZE) {
+		IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
+			       data_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (init_size > IWL39_MAX_INST_SIZE) {
+		IWL_DEBUG_INFO(priv,
+				"uCode init instr len %d too large to fit in\n",
+				init_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (init_data_size > IWL39_MAX_DATA_SIZE) {
+		IWL_DEBUG_INFO(priv,
+				"uCode init data len %d too large to fit in\n",
+				init_data_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (boot_size > IWL39_MAX_BSM_SIZE) {
+		IWL_DEBUG_INFO(priv,
+				"uCode boot instr len %d too large to fit in\n",
+				boot_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	/* Allocate ucode buffers for card's bus-master loading ... */
+
+	/* Runtime instructions and 2 copies of data:
+	 * 1) unmodified from disk
+	 * 2) backup cache for save/restore during power-downs */
+	priv->ucode_code.len = inst_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
+
+	priv->ucode_data.len = data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
+
+	priv->ucode_data_backup.len = data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+
+	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+	    !priv->ucode_data_backup.v_addr)
+		goto err_pci_alloc;
+
+	/* Initialization instructions and data */
+	if (init_size && init_data_size) {
+		priv->ucode_init.len = init_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+		priv->ucode_init_data.len = init_data_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+
+		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Bootstrap (instructions only, no data) */
+	if (boot_size) {
+		priv->ucode_boot.len = boot_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
+
+		if (!priv->ucode_boot.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Copy images into buffers for card's bus-master reads ... */
+
+	/* Runtime instructions (first block of data in file) */
+	len = inst_size;
+	IWL_DEBUG_INFO(priv,
+		"Copying (but not loading) uCode instr len %zd\n", len);
+	memcpy(priv->ucode_code.v_addr, src, len);
+	src += len;
+
+	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
+		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
+
+	/* Runtime data (2nd block)
+	 * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
+	len = data_size;
+	IWL_DEBUG_INFO(priv,
+		"Copying (but not loading) uCode data len %zd\n", len);
+	memcpy(priv->ucode_data.v_addr, src, len);
+	memcpy(priv->ucode_data_backup.v_addr, src, len);
+	src += len;
+
+	/* Initialization instructions (3rd block) */
+	if (init_size) {
+		len = init_size;
+		IWL_DEBUG_INFO(priv,
+			"Copying (but not loading) init instr len %zd\n", len);
+		memcpy(priv->ucode_init.v_addr, src, len);
+		src += len;
+	}
+
+	/* Initialization data (4th block) */
+	if (init_data_size) {
+		len = init_data_size;
+		IWL_DEBUG_INFO(priv,
+			"Copying (but not loading) init data len %zd\n", len);
+		memcpy(priv->ucode_init_data.v_addr, src, len);
+		src += len;
+	}
+
+	/* Bootstrap instructions (5th block) */
+	len = boot_size;
+	IWL_DEBUG_INFO(priv,
+		"Copying (but not loading) boot instr len %zd\n", len);
+	memcpy(priv->ucode_boot.v_addr, src, len);
+
+	/* We have our copies now, allow OS release its copies */
+	release_firmware(ucode_raw);
+	return 0;
+
+ err_pci_alloc:
+	IWL_ERR(priv, "failed to allocate pci memory\n");
+	ret = -ENOMEM;
+	iwl3945_dealloc_ucode_pci(priv);
+
+ err_release:
+	release_firmware(ucode_raw);
+
+ error:
+	return ret;
+}
+
+
+/**
+ * iwl3945_set_ucode_ptrs - Set uCode address location
+ *
+ * Tell initialization uCode where to find runtime uCode.
+ *
+ * BSM registers initially contain pointers to initialization uCode.
+ * We need to replace them to load runtime uCode inst and data,
+ * and to save runtime data when powering down.
+ */
+static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
+{
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+
+	/* bits 31:0 for 3945 */
+	pinst = priv->ucode_code.p_addr;
+	pdata = priv->ucode_data_backup.p_addr;
+
+	/* Tell bootstrap uCode where to find image to load */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+				 priv->ucode_data.len);
+
+	/* Inst byte count must be last to set up, bit 31 signals uCode
+	 *   that all new ptr/size info is in place */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+
+	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
+
+	return 0;
+}
+
+/**
+ * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
+ *
+ * Called after REPLY_ALIVE notification received from "initialize" uCode.
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+ */
+static void iwl3945_init_alive_start(struct iwl_priv *priv)
+{
+	/* Check alive response for "valid" sign from uCode */
+	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
+		/* We had an error bringing up the hardware, so take it
+		 * all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
+		goto restart;
+	}
+
+	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "initialize" alive if code weren't properly loaded.  */
+	if (iwl3945_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
+		goto restart;
+	}
+
+	/* Send pointers to protocol/runtime uCode image ... init code will
+	 * load and launch runtime uCode, which will send us another "Alive"
+	 * notification. */
+	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+	if (iwl3945_set_ucode_ptrs(priv)) {
+		/* Runtime instruction load won't happen;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
+		goto restart;
+	}
+	return;
+
+ restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+/**
+ * iwl3945_alive_start - called after REPLY_ALIVE notification received
+ *                   from protocol/runtime uCode (initialization uCode's
+ *                   Alive gets handled by iwl3945_init_alive_start()).
+ */
+static void iwl3945_alive_start(struct iwl_priv *priv)
+{
+	int thermal_spin = 0;
+	u32 rfkill;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+
+	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
+		/* We had an error bringing up the hardware, so take it
+		 * all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Alive failed.\n");
+		goto restart;
+	}
+
+	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "runtime" alive if code weren't properly loaded.  */
+	if (iwl3945_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
+		goto restart;
+	}
+
+	rfkill = iwl_legacy_read_prph(priv, APMG_RFKILL_REG);
+	IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
+
+	if (rfkill & 0x1) {
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+		/* if RFKILL is not on, then wait for thermal
+		 * sensor in adapter to kick in */
+		while (iwl3945_hw_get_temperature(priv) == 0) {
+			thermal_spin++;
+			udelay(10);
+		}
+
+		if (thermal_spin)
+			IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n",
+				       thermal_spin * 10);
+	} else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	/* After the ALIVE response, we can send commands to 3945 uCode */
+	set_bit(STATUS_ALIVE, &priv->status);
+
+	/* Enable watchdog to monitor the driver tx queues */
+	iwl_legacy_setup_watchdog(priv);
+
+	if (iwl_legacy_is_rfkill(priv))
+		return;
+
+	ieee80211_wake_queues(priv->hw);
+
+	priv->active_rate = IWL_RATES_MASK_3945;
+
+	iwl_legacy_power_update_mode(priv, true);
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+		struct iwl3945_rxon_cmd *active_rxon =
+				(struct iwl3945_rxon_cmd *)(&ctx->active);
+
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	} else {
+		/* Initialize our rx_config data */
+		iwl_legacy_connection_init_rx_config(priv, ctx);
+	}
+
+	/* Configure Bluetooth device coexistence support */
+	iwl_legacy_send_bt_config(priv);
+
+	set_bit(STATUS_READY, &priv->status);
+
+	/* Configure the adapter for unassociated operation */
+	iwl3945_commit_rxon(priv, ctx);
+
+	iwl3945_reg_txpower_periodic(priv);
+
+	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
+	wake_up_interruptible(&priv->wait_command_queue);
+
+	return;
+
+ restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
+
+static void __iwl3945_down(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	int exit_pending;
+
+	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+	 * to prevent rearm timer */
+	del_timer_sync(&priv->watchdog);
+
+	/* Station information will now be cleared in device */
+	iwl_legacy_clear_ucode_stations(priv, NULL);
+	iwl_legacy_dealloc_bcast_stations(priv);
+	iwl_legacy_clear_driver_stations(priv);
+
+	/* Unblock any waiting calls */
+	wake_up_interruptible_all(&priv->wait_command_queue);
+
+	/* Wipe out the EXIT_PENDING status bit if we are not actually
+	 * exiting the module */
+	if (!exit_pending)
+		clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* stop and reset the on-board processor */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/* tell the device to stop sending interrupts */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	iwl3945_synchronize_irq(priv);
+
+	if (priv->mac80211_registered)
+		ieee80211_stop_queues(priv->hw);
+
+	/* If we have not previously called iwl3945_init() then
+	 * clear all bits but the RF Kill bits and return */
+	if (!iwl_legacy_is_init(priv)) {
+		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+					STATUS_RF_KILL_HW |
+			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+					STATUS_GEO_CONFIGURED |
+				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+					STATUS_EXIT_PENDING;
+		goto exit;
+	}
+
+	/* ...otherwise clear out all the status bits but the RF Kill
+	 * bit and continue taking the NIC down. */
+	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+				STATUS_RF_KILL_HW |
+			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+				STATUS_GEO_CONFIGURED |
+			test_bit(STATUS_FW_ERROR, &priv->status) <<
+				STATUS_FW_ERROR |
+			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+				STATUS_EXIT_PENDING;
+
+	iwl3945_hw_txq_ctx_stop(priv);
+	iwl3945_hw_rxq_stop(priv);
+
+	/* Power-down device's busmaster DMA clocks */
+	iwl_legacy_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+	udelay(5);
+
+	/* Stop the device, and put it in low power state */
+	iwl_legacy_apm_stop(priv);
+
+ exit:
+	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
+
+	/* clear out any free frames */
+	iwl3945_clear_free_frames(priv);
+}
+
+static void iwl3945_down(struct iwl_priv *priv)
+{
+	mutex_lock(&priv->mutex);
+	__iwl3945_down(priv);
+	mutex_unlock(&priv->mutex);
+
+	iwl3945_cancel_deferred_work(priv);
+}
+
+#define MAX_HW_RESTARTS 5
+
+static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	unsigned long flags;
+	u8 sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	sta_id = iwl_legacy_prep_station(priv, ctx,
+					iwlegacy_bcast_addr, false, NULL);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Unable to prepare broadcast station\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+		return -EINVAL;
+	}
+
+	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+	priv->stations[sta_id].used |= IWL_STA_BCAST;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+static int __iwl3945_up(struct iwl_priv *priv)
+{
+	int rc, i;
+
+	rc = iwl3945_alloc_bcast_station(priv);
+	if (rc)
+		return rc;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
+		return -EIO;
+	}
+
+	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+		IWL_ERR(priv, "ucode not available for device bring up\n");
+		return -EIO;
+	}
+
+	/* If platform's RF_KILL switch is NOT set to KILL */
+	if (iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+	else {
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+		return -ENODEV;
+	}
+
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+	rc = iwl3945_hw_nic_init(priv);
+	if (rc) {
+		IWL_ERR(priv, "Unable to int nic\n");
+		return rc;
+	}
+
+	/* make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	/* clear (again), then enable host interrupts */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_legacy_enable_interrupts(priv);
+
+	/* really make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+	/* Copy original ucode data image from disk into backup cache.
+	 * This will be used to initialize the on-board processor's
+	 * data SRAM for a clean start when the runtime program first loads. */
+	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
+	       priv->ucode_data.len);
+
+	/* We return success when we resume from suspend and rf_kill is on. */
+	if (test_bit(STATUS_RF_KILL_HW, &priv->status))
+		return 0;
+
+	for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+		/* load bootstrap state machine,
+		 * load bootstrap program into processor's memory,
+		 * prepare to load the "initialize" uCode */
+		rc = priv->cfg->ops->lib->load_ucode(priv);
+
+		if (rc) {
+			IWL_ERR(priv,
+				"Unable to set up bootstrap uCode: %d\n", rc);
+			continue;
+		}
+
+		/* start card; "initialize" will load runtime ucode */
+		iwl3945_nic_start(priv);
+
+		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
+
+		return 0;
+	}
+
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+	__iwl3945_down(priv);
+	clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* tried to restart and config the device for as long as our
+	 * patience could withstand */
+	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
+	return -EIO;
+}
+
+
+/*****************************************************************************
+ *
+ * Workqueue callbacks
+ *
+ *****************************************************************************/
+
+static void iwl3945_bg_init_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, init_alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_init_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl3945_bg_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/*
+ * 3945 cannot interrupt driver when hardware rf kill switch toggles;
+ * driver must poll CSR_GP_CNTRL_REG register for change.  This register
+ * *is* readable even when device has been SW_RESET into low power mode
+ * (e.g. during RF KILL).
+ */
+static void iwl3945_rfkill_poll(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
+	bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
+	bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
+			& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+
+	if (new_rfkill != old_rfkill) {
+		if (new_rfkill)
+			set_bit(STATUS_RF_KILL_HW, &priv->status);
+		else
+			clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill);
+
+		IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
+				new_rfkill ? "disable radio" : "enable radio");
+	}
+
+	/* Keep this running, even if radio now enabled.  This will be
+	 * cancelled in mac_start() if system decides to start again */
+	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
+			   round_jiffies_relative(2 * HZ));
+
+}
+
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_CMD,
+		.len = sizeof(struct iwl3945_scan_cmd),
+		.flags = CMD_SIZE_HUGE,
+	};
+	struct iwl3945_scan_cmd *scan;
+	u8 n_probes = 0;
+	enum ieee80211_band band;
+	bool is_active = false;
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
+			IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
+			return -ENOMEM;
+		}
+	}
+	scan = priv->scan_cmd;
+	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+		u16 interval = 0;
+		u32 extra;
+		u32 suspend_time = 100;
+		u32 scan_suspend_time = 100;
+
+		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+
+		if (priv->is_internal_short_scan)
+			interval = 0;
+		else
+			interval = vif->bss_conf.beacon_int;
+
+		scan->suspend_time = 0;
+		scan->max_out_time = cpu_to_le32(200 * 1024);
+		if (!interval)
+			interval = suspend_time;
+		/*
+		 * suspend time format:
+		 *  0-19: beacon interval in usec (time before exec.)
+		 * 20-23: 0
+		 * 24-31: number of beacons (suspend between channels)
+		 */
+
+		extra = (suspend_time / interval) << 24;
+		scan_suspend_time = 0xFF0FFFFF &
+		    (extra | ((suspend_time % interval) * 1024));
+
+		scan->suspend_time = cpu_to_le32(scan_suspend_time);
+		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+			       scan_suspend_time, interval);
+	}
+
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+	} else if (priv->scan_request->n_ssids) {
+		int i, p = 0;
+		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+		for (i = 0; i < priv->scan_request->n_ssids; i++) {
+			/* always does wildcard anyway */
+			if (!priv->scan_request->ssids[i].ssid_len)
+				continue;
+			scan->direct_scan[p].id = WLAN_EID_SSID;
+			scan->direct_scan[p].len =
+				priv->scan_request->ssids[i].ssid_len;
+			memcpy(scan->direct_scan[p].ssid,
+			       priv->scan_request->ssids[i].ssid,
+			       priv->scan_request->ssids[i].ssid_len);
+			n_probes++;
+			p++;
+		}
+		is_active = true;
+	} else
+		IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
+
+	/* We don't build a direct scan probe request; the uCode will do
+	 * that based on the direct_mask added to each channel entry */
+	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+	scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
+	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	/* flags + rate selection */
+
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
+		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
+		band = IEEE80211_BAND_2GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
+		band = IEEE80211_BAND_5GHZ;
+		break;
+	default:
+		IWL_WARN(priv, "Invalid scan band\n");
+		return -EIO;
+	}
+
+	/*
+	 * If active scaning is requested but a certain channel
+	 * is marked passive, we can do active scanning if we
+	 * detect transmissions.
+	 */
+	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+					IWL_GOOD_CRC_TH_DISABLED;
+
+	if (!priv->is_internal_short_scan) {
+		scan->tx_cmd.len = cpu_to_le16(
+			iwl_legacy_fill_probe_req(priv,
+				(struct ieee80211_mgmt *)scan->data,
+				vif->addr,
+				priv->scan_request->ie,
+				priv->scan_request->ie_len,
+				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+	} else {
+		/* use bcast addr, will not be transmitted but must be valid */
+		scan->tx_cmd.len = cpu_to_le16(
+			iwl_legacy_fill_probe_req(priv,
+				(struct ieee80211_mgmt *)scan->data,
+				iwlegacy_bcast_addr, NULL, 0,
+				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+	}
+	/* select Rx antennas */
+	scan->flags |= iwl3945_get_antenna_flags(priv);
+
+	if (priv->is_internal_short_scan) {
+		scan->channel_count =
+			iwl3945_get_single_channel_for_scan(priv, vif, band,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	} else {
+		scan->channel_count =
+			iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+	}
+
+	if (scan->channel_count == 0) {
+		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+		return -EIO;
+	}
+
+	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+	    scan->channel_count * sizeof(struct iwl3945_scan_channel);
+	cmd.data = scan;
+	scan->len = cpu_to_le16(cmd.len);
+
+	set_bit(STATUS_SCAN_HW, &priv->status);
+	ret = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (ret)
+		clear_bit(STATUS_SCAN_HW, &priv->status);
+	return ret;
+}
+
+void iwl3945_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+		iwl3945_commit_rxon(priv, ctx);
+}
+
+static void iwl3945_bg_restart(struct work_struct *data)
+{
+	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		struct iwl_rxon_context *ctx;
+		mutex_lock(&priv->mutex);
+		for_each_context(priv, ctx)
+			ctx->vif = NULL;
+		priv->is_open = 0;
+		mutex_unlock(&priv->mutex);
+		iwl3945_down(priv);
+		ieee80211_restart_hw(priv->hw);
+	} else {
+		iwl3945_down(priv);
+
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			return;
+
+		mutex_lock(&priv->mutex);
+		__iwl3945_up(priv);
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+static void iwl3945_bg_rx_replenish(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, rx_replenish);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_rx_replenish(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+void iwl3945_post_associate(struct iwl_priv *priv)
+{
+	int rc = 0;
+	struct ieee80211_conf *conf = NULL;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (!ctx->vif || !priv->is_open)
+		return;
+
+	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
+			ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
+
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl3945_commit_rxon(priv, ctx);
+
+	rc = iwl_legacy_send_rxon_timing(priv, ctx);
+	if (rc)
+		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+			    "Attempting to continue.\n");
+
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+	ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
+
+	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
+			ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
+
+	if (ctx->vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+		if (ctx->vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+	}
+
+	iwl3945_commit_rxon(priv, ctx);
+
+	switch (ctx->vif->type) {
+	case NL80211_IFTYPE_STATION:
+		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwl3945_send_beacon_cmd(priv);
+		break;
+	default:
+		IWL_ERR(priv, "%s Should not be called in %d mode\n",
+			__func__, ctx->vif->type);
+		break;
+	}
+}
+
+/*****************************************************************************
+ *
+ * mac80211 entry point functions
+ *
+ *****************************************************************************/
+
+#define UCODE_READY_TIMEOUT	(2 * HZ)
+
+static int iwl3945_mac_start(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	/* we should be verifying the device is ready to be opened */
+	mutex_lock(&priv->mutex);
+
+	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
+	 * ucode filename and max sizes are card-specific. */
+
+	if (!priv->ucode_code.len) {
+		ret = iwl3945_read_ucode(priv);
+		if (ret) {
+			IWL_ERR(priv, "Could not read microcode: %d\n", ret);
+			mutex_unlock(&priv->mutex);
+			goto out_release_irq;
+		}
+	}
+
+	ret = __iwl3945_up(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	if (ret)
+		goto out_release_irq;
+
+	IWL_DEBUG_INFO(priv, "Start UP work.\n");
+
+	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
+	 * mac80211 will not be run successfully. */
+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+			test_bit(STATUS_READY, &priv->status),
+			UCODE_READY_TIMEOUT);
+	if (!ret) {
+		if (!test_bit(STATUS_READY, &priv->status)) {
+			IWL_ERR(priv,
+				"Wait for START_ALIVE timeout after %dms.\n",
+				jiffies_to_msecs(UCODE_READY_TIMEOUT));
+			ret = -ETIMEDOUT;
+			goto out_release_irq;
+		}
+	}
+
+	/* ucode is running and will send rfkill notifications,
+	 * no need to poll the killswitch state anymore */
+	cancel_delayed_work(&priv->_3945.rfkill_poll);
+
+	priv->is_open = 1;
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+
+out_release_irq:
+	priv->is_open = 0;
+	IWL_DEBUG_MAC80211(priv, "leave - failed\n");
+	return ret;
+}
+
+static void iwl3945_mac_stop(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!priv->is_open) {
+		IWL_DEBUG_MAC80211(priv, "leave - skip\n");
+		return;
+	}
+
+	priv->is_open = 0;
+
+	iwl3945_down(priv);
+
+	flush_workqueue(priv->workqueue);
+
+	/* start polling the killswitch state again */
+	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
+			   round_jiffies_relative(2 * HZ));
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+static void iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+	if (iwl3945_tx_skb(priv, skb))
+		dev_kfree_skb_any(skb);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+void iwl3945_config_ap(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	int rc = 0;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* The following should be done only at AP bring up */
+	if (!(iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))) {
+
+		/* RXON - unassoc (to set timing command) */
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwl3945_commit_rxon(priv, ctx);
+
+		/* RXON Timing */
+		rc = iwl_legacy_send_rxon_timing(priv, ctx);
+		if (rc)
+			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+					"Attempting to continue.\n");
+
+		ctx->staging.assoc_id = 0;
+
+		if (vif->bss_conf.use_short_preamble)
+			ctx->staging.flags |=
+				RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &=
+				~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+			if (vif->bss_conf.use_short_slot)
+				ctx->staging.flags |=
+					RXON_FLG_SHORT_SLOT_MSK;
+			else
+				ctx->staging.flags &=
+					~RXON_FLG_SHORT_SLOT_MSK;
+		}
+		/* restore RXON assoc */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwl3945_commit_rxon(priv, ctx);
+	}
+	iwl3945_send_beacon_cmd(priv);
+}
+
+static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+			       struct ieee80211_vif *vif,
+			       struct ieee80211_sta *sta,
+			       struct ieee80211_key_conf *key)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret = 0;
+	u8 sta_id = IWL_INVALID_STATION;
+	u8 static_key;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (iwl3945_mod_params.sw_crypto) {
+		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
+		return -EOPNOTSUPP;
+	}
+
+	/*
+	 * To support IBSS RSN, don't program group keys in IBSS, the
+	 * hardware will then not attempt to decrypt the frames.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
+	static_key = !iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS);
+
+	if (!static_key) {
+		sta_id = iwl_legacy_sta_id_or_broadcast(
+				priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
+		if (sta_id == IWL_INVALID_STATION)
+			return -EINVAL;
+	}
+
+	mutex_lock(&priv->mutex);
+	iwl_legacy_scan_cancel_timeout(priv, 100);
+
+	switch (cmd) {
+	case SET_KEY:
+		if (static_key)
+			ret = iwl3945_set_static_key(priv, key);
+		else
+			ret = iwl3945_set_dynamic_key(priv, key, sta_id);
+		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
+		break;
+	case DISABLE_KEY:
+		if (static_key)
+			ret = iwl3945_remove_static_key(priv);
+		else
+			ret = iwl3945_clear_sta_key_info(priv, sta_id);
+		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+	return ret;
+}
+
+static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
+	int ret;
+	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
+	u8 sta_id;
+
+	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
+			sta->addr);
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+			sta->addr);
+	sta_priv->common.sta_id = IWL_INVALID_STATION;
+
+
+	ret = iwl_legacy_add_station_common(priv,
+				&priv->contexts[IWL_RXON_CTX_BSS],
+				     sta->addr, is_ap, sta, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
+			sta->addr, ret);
+		/* Should we return success if return code is EEXIST ? */
+		mutex_unlock(&priv->mutex);
+		return ret;
+	}
+
+	sta_priv->common.sta_id = sta_id;
+
+	/* Initialize rate scaling */
+	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
+		       sta->addr);
+	iwl3945_rs_rate_init(priv, sta, sta_id);
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+
+static void iwl3945_configure_filter(struct ieee80211_hw *hw,
+				     unsigned int changed_flags,
+				     unsigned int *total_flags,
+				     u64 multicast)
+{
+	struct iwl_priv *priv = hw->priv;
+	__le32 filter_or = 0, filter_nand = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+#define CHK(test, flag)	do { \
+	if (*total_flags & (test))		\
+		filter_or |= (flag);		\
+	else					\
+		filter_nand |= (flag);		\
+	} while (0)
+
+	IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+			changed_flags, *total_flags);
+
+	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+	mutex_lock(&priv->mutex);
+
+	ctx->staging.filter_flags &= ~filter_nand;
+	ctx->staging.filter_flags |= filter_or;
+
+	/*
+	 * Not committing directly because hardware can perform a scan,
+	 * but even if hw is ready, committing here breaks for some reason,
+	 * we'll eventually commit the filter flags change anyway.
+	 */
+
+	mutex_unlock(&priv->mutex);
+
+	/*
+	 * Receiving all multicast frames is always enabled by the
+	 * default flags setup in iwl_legacy_connection_init_rx_config()
+	 * since we currently do not support programming multicast
+	 * filters into the device.
+	 */
+	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t iwl3945_show_debug_level(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%08X\n", iwl_legacy_get_debug_level(priv));
+}
+static ssize_t iwl3945_store_debug_level(struct device *d,
+				struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 0, &val);
+	if (ret)
+		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
+	else {
+		priv->debug_level = val;
+		if (iwl_legacy_alloc_traffic_mem(priv))
+			IWL_ERR(priv,
+				"Not enough memory to generate traffic log\n");
+	}
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+			iwl3945_show_debug_level, iwl3945_store_debug_level);
+
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
+
+static ssize_t iwl3945_show_temperature(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, iwl3945_show_temperature, NULL);
+
+static ssize_t iwl3945_show_tx_power(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t iwl3945_store_tx_power(struct device *d,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	char *p = (char *)buf;
+	u32 val;
+
+	val = simple_strtoul(p, &p, 10);
+	if (p == buf)
+		IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
+	else
+		iwl3945_hw_reg_set_txpower(priv, val);
+
+	return count;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, iwl3945_show_tx_power, iwl3945_store_tx_power);
+
+static ssize_t iwl3945_show_flags(struct device *d,
+			  struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	return sprintf(buf, "0x%04X\n", ctx->active.flags);
+}
+
+static ssize_t iwl3945_store_flags(struct device *d,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	u32 flags = simple_strtoul(buf, NULL, 0);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	mutex_lock(&priv->mutex);
+	if (le32_to_cpu(ctx->staging.flags) != flags) {
+		/* Cancel any currently running scans... */
+		if (iwl_legacy_scan_cancel_timeout(priv, 100))
+			IWL_WARN(priv, "Could not cancel scan.\n");
+		else {
+			IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
+				       flags);
+			ctx->staging.flags = cpu_to_le32(flags);
+			iwl3945_commit_rxon(priv, ctx);
+		}
+	}
+	mutex_unlock(&priv->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, iwl3945_show_flags, iwl3945_store_flags);
+
+static ssize_t iwl3945_show_filter_flags(struct device *d,
+				 struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	return sprintf(buf, "0x%04X\n",
+		le32_to_cpu(ctx->active.filter_flags));
+}
+
+static ssize_t iwl3945_store_filter_flags(struct device *d,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	u32 filter_flags = simple_strtoul(buf, NULL, 0);
+
+	mutex_lock(&priv->mutex);
+	if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
+		/* Cancel any currently running scans... */
+		if (iwl_legacy_scan_cancel_timeout(priv, 100))
+			IWL_WARN(priv, "Could not cancel scan.\n");
+		else {
+			IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
+				       "0x%04X\n", filter_flags);
+			ctx->staging.filter_flags =
+				cpu_to_le32(filter_flags);
+			iwl3945_commit_rxon(priv, ctx);
+		}
+	}
+	mutex_unlock(&priv->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, iwl3945_show_filter_flags,
+		   iwl3945_store_filter_flags);
+
+static ssize_t iwl3945_show_measurement(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_spectrum_notification measure_report;
+	u32 size = sizeof(measure_report), len = 0, ofs = 0;
+	u8 *data = (u8 *)&measure_report;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!(priv->measurement_status & MEASUREMENT_READY)) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return 0;
+	}
+	memcpy(&measure_report, &priv->measure_report, size);
+	priv->measurement_status = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	while (size && (PAGE_SIZE - len)) {
+		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
+				   PAGE_SIZE - len, 1);
+		len = strlen(buf);
+		if (PAGE_SIZE - len)
+			buf[len++] = '\n';
+
+		ofs += 16;
+		size -= min(size, 16U);
+	}
+
+	return len;
+}
+
+static ssize_t iwl3945_store_measurement(struct device *d,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_measurement_params params = {
+		.channel = le16_to_cpu(ctx->active.channel),
+		.start_time = cpu_to_le64(priv->_3945.last_tsf),
+		.duration = cpu_to_le16(1),
+	};
+	u8 type = IWL_MEASURE_BASIC;
+	u8 buffer[32];
+	u8 channel;
+
+	if (count) {
+		char *p = buffer;
+		strncpy(buffer, buf, min(sizeof(buffer), count));
+		channel = simple_strtoul(p, NULL, 0);
+		if (channel)
+			params.channel = channel;
+
+		p = buffer;
+		while (*p && *p != ' ')
+			p++;
+		if (*p)
+			type = simple_strtoul(p + 1, NULL, 0);
+	}
+
+	IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on "
+		       "channel %d (for '%s')\n", type, params.channel, buf);
+	iwl3945_get_measurement(priv, &params, type);
+
+	return count;
+}
+
+static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
+		   iwl3945_show_measurement, iwl3945_store_measurement);
+
+static ssize_t iwl3945_store_retry_rate(struct device *d,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	priv->retry_rate = simple_strtoul(buf, NULL, 0);
+	if (priv->retry_rate <= 0)
+		priv->retry_rate = 1;
+
+	return count;
+}
+
+static ssize_t iwl3945_show_retry_rate(struct device *d,
+			       struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "%d", priv->retry_rate);
+}
+
+static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, iwl3945_show_retry_rate,
+		   iwl3945_store_retry_rate);
+
+
+static ssize_t iwl3945_show_channels(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	/* all this shit doesn't belong into sysfs anyway */
+	return 0;
+}
+
+static DEVICE_ATTR(channels, S_IRUSR, iwl3945_show_channels, NULL);
+
+static ssize_t iwl3945_show_antenna(struct device *d,
+			    struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
+}
+
+static ssize_t iwl3945_store_antenna(struct device *d,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d);
+	int ant;
+
+	if (count == 0)
+		return 0;
+
+	if (sscanf(buf, "%1i", &ant) != 1) {
+		IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n");
+		return count;
+	}
+
+	if ((ant >= 0) && (ant <= 2)) {
+		IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant);
+		iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
+	} else
+		IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant);
+
+
+	return count;
+}
+
+static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, iwl3945_show_antenna, iwl3945_store_antenna);
+
+static ssize_t iwl3945_show_status(struct device *d,
+			   struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+	return sprintf(buf, "0x%08x\n", (int)priv->status);
+}
+
+static DEVICE_ATTR(status, S_IRUGO, iwl3945_show_status, NULL);
+
+static ssize_t iwl3945_dump_error_log(struct device *d,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	char *p = (char *)buf;
+
+	if (p[0] == '1')
+		iwl3945_dump_nic_error_log(priv);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, iwl3945_dump_error_log);
+
+/*****************************************************************************
+ *
+ * driver setup and tear down
+ *
+ *****************************************************************************/
+
+static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
+{
+	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
+
+	init_waitqueue_head(&priv->wait_command_queue);
+
+	INIT_WORK(&priv->restart, iwl3945_bg_restart);
+	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
+	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
+	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
+	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
+
+	iwl_legacy_setup_scan_deferred_work(priv);
+
+	iwl3945_hw_setup_deferred_work(priv);
+
+	init_timer(&priv->watchdog);
+	priv->watchdog.data = (unsigned long)priv;
+	priv->watchdog.function = iwl_legacy_bg_watchdog;
+
+	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+		     iwl3945_irq_tasklet, (unsigned long)priv);
+}
+
+static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
+{
+	iwl3945_hw_cancel_deferred_work(priv);
+
+	cancel_delayed_work_sync(&priv->init_alive_start);
+	cancel_delayed_work(&priv->alive_start);
+
+	iwl_legacy_cancel_scan_deferred_work(priv);
+}
+
+static struct attribute *iwl3945_sysfs_entries[] = {
+	&dev_attr_antenna.attr,
+	&dev_attr_channels.attr,
+	&dev_attr_dump_errors.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_filter_flags.attr,
+	&dev_attr_measurement.attr,
+	&dev_attr_retry_rate.attr,
+	&dev_attr_status.attr,
+	&dev_attr_temperature.attr,
+	&dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	&dev_attr_debug_level.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group iwl3945_attribute_group = {
+	.name = NULL,		/* put in device directory */
+	.attrs = iwl3945_sysfs_entries,
+};
+
+struct ieee80211_ops iwl3945_hw_ops = {
+	.tx = iwl3945_mac_tx,
+	.start = iwl3945_mac_start,
+	.stop = iwl3945_mac_stop,
+	.add_interface = iwl_legacy_mac_add_interface,
+	.remove_interface = iwl_legacy_mac_remove_interface,
+	.change_interface = iwl_legacy_mac_change_interface,
+	.config = iwl_legacy_mac_config,
+	.configure_filter = iwl3945_configure_filter,
+	.set_key = iwl3945_mac_set_key,
+	.conf_tx = iwl_legacy_mac_conf_tx,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
+	.hw_scan = iwl_legacy_mac_hw_scan,
+	.sta_add = iwl3945_mac_sta_add,
+	.sta_remove = iwl_legacy_mac_sta_remove,
+	.tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
+};
+
+static int iwl3945_init_drv(struct iwl_priv *priv)
+{
+	int ret;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+
+	priv->retry_rate = 1;
+	priv->beacon_skb = NULL;
+
+	spin_lock_init(&priv->sta_lock);
+	spin_lock_init(&priv->hcmd_lock);
+
+	INIT_LIST_HEAD(&priv->free_frames);
+
+	mutex_init(&priv->mutex);
+	mutex_init(&priv->sync_cmd_mutex);
+
+	priv->ieee_channels = NULL;
+	priv->ieee_rates = NULL;
+	priv->band = IEEE80211_BAND_2GHZ;
+
+	priv->iw_mode = NL80211_IFTYPE_STATION;
+	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+
+	/* initialize force reset */
+	priv->force_reset[IWL_RF_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_RF_RESET;
+	priv->force_reset[IWL_FW_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+
+	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
+	priv->tx_power_next = IWL_DEFAULT_TX_POWER;
+
+	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
+		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
+			 eeprom->version);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = iwl_legacy_init_channel_map(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
+		goto err;
+	}
+
+	/* Set up txpower settings in driver for all channels */
+	if (iwl3945_txpower_set_from_eeprom(priv)) {
+		ret = -EIO;
+		goto err_free_channel_map;
+	}
+
+	ret = iwl_legacy_init_geos(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
+		goto err_free_channel_map;
+	}
+	iwl3945_init_hw_rates(priv, priv->ieee_rates);
+
+	return 0;
+
+err_free_channel_map:
+	iwl_legacy_free_channel_map(priv);
+err:
+	return ret;
+}
+
+#define IWL3945_MAX_PROBE_REQUEST	200
+
+static int iwl3945_setup_mac(struct iwl_priv *priv)
+{
+	int ret;
+	struct ieee80211_hw *hw = priv->hw;
+
+	hw->rate_control_algorithm = "iwl-3945-rs";
+	hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+	hw->vif_data_size = sizeof(struct iwl_vif_priv);
+
+	/* Tell mac80211 our characteristics */
+	hw->flags = IEEE80211_HW_SIGNAL_DBM |
+		    IEEE80211_HW_SPECTRUM_MGMT;
+
+	hw->wiphy->interface_modes =
+		priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
+
+	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
+			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
+			    WIPHY_FLAG_IBSS_RSN;
+
+	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
+	/* we create the 802.11 header and a zero-length SSID element */
+	hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
+
+	/* Default value; 4 EDCA QOS priorities */
+	hw->queues = 4;
+
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&priv->bands[IEEE80211_BAND_2GHZ];
+
+	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&priv->bands[IEEE80211_BAND_5GHZ];
+
+	iwl_legacy_leds_init(priv);
+
+	ret = ieee80211_register_hw(priv->hw);
+	if (ret) {
+		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
+		return ret;
+	}
+	priv->mac80211_registered = 1;
+
+	return 0;
+}
+
+static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err = 0, i;
+	struct iwl_priv *priv;
+	struct ieee80211_hw *hw;
+	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	struct iwl3945_eeprom *eeprom;
+	unsigned long flags;
+
+	/***********************
+	 * 1. Allocating HW data
+	 * ********************/
+
+	/* mac80211 allocates memory for this device instance, including
+	 *   space for this driver's private structure */
+	hw = iwl_legacy_alloc_all(cfg);
+	if (hw == NULL) {
+		pr_err("Can not allocate network device\n");
+		err = -ENOMEM;
+		goto out;
+	}
+	priv = hw->priv;
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
+
+	/* 3945 has only one valid context */
+	priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+	for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+		priv->contexts[i].ctxid = i;
+
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+	priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+	priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC);
+	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
+	/*
+	 * Disabling hardware scan means that mac80211 will perform scans
+	 * "the hard way", rather than using device's scan.
+	 */
+	if (iwl3945_mod_params.disable_hw_scan) {
+		dev_printk(KERN_DEBUG, &(pdev->dev),
+			"sw scan support is deprecated\n");
+		iwl3945_hw_ops.hw_scan = NULL;
+	}
+
+	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
+	priv->cfg = cfg;
+	priv->pci_dev = pdev;
+	priv->inta_mask = CSR_INI_SET_MASK;
+
+	if (iwl_legacy_alloc_traffic_mem(priv))
+		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
+
+	/***************************
+	 * 2. Initializing PCI bus
+	 * *************************/
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				PCIE_LINK_STATE_CLKPM);
+
+	if (pci_enable_device(pdev)) {
+		err = -ENODEV;
+		goto out_ieee80211_free_hw;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		IWL_WARN(priv, "No suitable DMA available.\n");
+		goto out_pci_disable_device;
+	}
+
+	pci_set_drvdata(pdev, priv);
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err)
+		goto out_pci_disable_device;
+
+	/***********************
+	 * 3. Read REV Register
+	 * ********************/
+	priv->hw_base = pci_iomap(pdev, 0, 0);
+	if (!priv->hw_base) {
+		err = -ENODEV;
+		goto out_pci_release_regions;
+	}
+
+	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
+			(unsigned long long) pci_resource_len(pdev, 0));
+	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
+
+	/* We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state */
+	pci_write_config_byte(pdev, 0x41, 0x00);
+
+	/* these spin locks will be used in apm_ops.init and EEPROM access
+	 * we should init now
+	 */
+	spin_lock_init(&priv->reg_lock);
+	spin_lock_init(&priv->lock);
+
+	/*
+	 * stop and reset the on-board processor just in case it is in a
+	 * strange state ... like being left stranded by a primary kernel
+	 * and this is now the kdump kernel trying to start up
+	 */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/***********************
+	 * 4. Read EEPROM
+	 * ********************/
+
+	/* Read the EEPROM */
+	err = iwl_legacy_eeprom_init(priv);
+	if (err) {
+		IWL_ERR(priv, "Unable to init EEPROM\n");
+		goto out_iounmap;
+	}
+	/* MAC Address location in EEPROM same for 3945/4965 */
+	eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
+	SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
+
+	/***********************
+	 * 5. Setup HW Constants
+	 * ********************/
+	/* Device-specific setup */
+	if (iwl3945_hw_set_hw_params(priv)) {
+		IWL_ERR(priv, "failed to set hw settings\n");
+		goto out_eeprom_free;
+	}
+
+	/***********************
+	 * 6. Setup priv
+	 * ********************/
+
+	err = iwl3945_init_drv(priv);
+	if (err) {
+		IWL_ERR(priv, "initializing driver failed\n");
+		goto out_unset_hw_params;
+	}
+
+	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
+		priv->cfg->name);
+
+	/***********************
+	 * 7. Setup Services
+	 * ********************/
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	pci_enable_msi(priv->pci_dev);
+
+	err = request_irq(priv->pci_dev->irq, iwl_legacy_isr,
+			  IRQF_SHARED, DRV_NAME, priv);
+	if (err) {
+		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
+		goto out_disable_msi;
+	}
+
+	err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+	if (err) {
+		IWL_ERR(priv, "failed to create sysfs device attributes\n");
+		goto out_release_irq;
+	}
+
+	iwl_legacy_set_rxon_channel(priv,
+			     &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
+			     &priv->contexts[IWL_RXON_CTX_BSS]);
+	iwl3945_setup_deferred_work(priv);
+	iwl3945_setup_rx_handlers(priv);
+	iwl_legacy_power_initialize(priv);
+
+	/*********************************
+	 * 8. Setup and Register mac80211
+	 * *******************************/
+
+	iwl_legacy_enable_interrupts(priv);
+
+	err = iwl3945_setup_mac(priv);
+	if (err)
+		goto  out_remove_sysfs;
+
+	err = iwl_legacy_dbgfs_register(priv, DRV_NAME);
+	if (err)
+		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+
+	/* Start monitoring the killswitch */
+	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
+			   2 * HZ);
+
+	return 0;
+
+ out_remove_sysfs:
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ out_release_irq:
+	free_irq(priv->pci_dev->irq, priv);
+ out_disable_msi:
+	pci_disable_msi(priv->pci_dev);
+	iwl_legacy_free_geos(priv);
+	iwl_legacy_free_channel_map(priv);
+ out_unset_hw_params:
+	iwl3945_unset_hw_params(priv);
+ out_eeprom_free:
+	iwl_legacy_eeprom_free(priv);
+ out_iounmap:
+	pci_iounmap(pdev, priv->hw_base);
+ out_pci_release_regions:
+	pci_release_regions(pdev);
+ out_pci_disable_device:
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
+ out_ieee80211_free_hw:
+	iwl_legacy_free_traffic_mem(priv);
+	ieee80211_free_hw(priv->hw);
+ out:
+	return err;
+}
+
+static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+{
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	if (!priv)
+		return;
+
+	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
+
+	iwl_legacy_dbgfs_unregister(priv);
+
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	iwl_legacy_leds_exit(priv);
+
+	if (priv->mac80211_registered) {
+		ieee80211_unregister_hw(priv->hw);
+		priv->mac80211_registered = 0;
+	} else {
+		iwl3945_down(priv);
+	}
+
+	/*
+	 * Make sure device is reset to low power before unloading driver.
+	 * This may be redundant with iwl_down(), but there are paths to
+	 * run iwl_down() without calling apm_ops.stop(), and there are
+	 * paths to avoid running iwl_down() at all before leaving driver.
+	 * This (inexpensive) call *makes sure* device is reset.
+	 */
+	iwl_legacy_apm_stop(priv);
+
+	/* make sure we flush any pending irq or
+	 * tasklet for the driver
+	 */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl3945_synchronize_irq(priv);
+
+	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+
+	cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
+
+	iwl3945_dealloc_ucode_pci(priv);
+
+	if (priv->rxq.bd)
+		iwl3945_rx_queue_free(priv, &priv->rxq);
+	iwl3945_hw_txq_ctx_free(priv);
+
+	iwl3945_unset_hw_params(priv);
+
+	/*netif_stop_queue(dev); */
+	flush_workqueue(priv->workqueue);
+
+	/* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
+	 * priv->workqueue... so we can't take down the workqueue
+	 * until now... */
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	iwl_legacy_free_traffic_mem(priv);
+
+	free_irq(pdev->irq, priv);
+	pci_disable_msi(pdev);
+
+	pci_iounmap(pdev, priv->hw_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+
+	iwl_legacy_free_channel_map(priv);
+	iwl_legacy_free_geos(priv);
+	kfree(priv->scan_cmd);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	ieee80211_free_hw(priv->hw);
+}
+
+
+/*****************************************************************************
+ *
+ * driver and module entry point
+ *
+ *****************************************************************************/
+
+static struct pci_driver iwl3945_driver = {
+	.name = DRV_NAME,
+	.id_table = iwl3945_hw_card_ids,
+	.probe = iwl3945_pci_probe,
+	.remove = __devexit_p(iwl3945_pci_remove),
+	.driver.pm = IWL_LEGACY_PM_OPS,
+};
+
+static int __init iwl3945_init(void)
+{
+
+	int ret;
+	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	pr_info(DRV_COPYRIGHT "\n");
+
+	ret = iwl3945_rate_control_register();
+	if (ret) {
+		pr_err("Unable to register rate control algorithm: %d\n", ret);
+		return ret;
+	}
+
+	ret = pci_register_driver(&iwl3945_driver);
+	if (ret) {
+		pr_err("Unable to initialize PCI module\n");
+		goto error_register;
+	}
+
+	return ret;
+
+error_register:
+	iwl3945_rate_control_unregister();
+	return ret;
+}
+
+static void __exit iwl3945_exit(void)
+{
+	pci_unregister_driver(&iwl3945_driver);
+	iwl3945_rate_control_unregister();
+}
+
+MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
+
+module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO);
+MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
+module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO);
+MODULE_PARM_DESC(swcrypto,
+		"using software crypto (default 1 [software])");
+module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
+		int, S_IRUGO);
+MODULE_PARM_DESC(disable_hw_scan,
+		"disable hardware scanning (default 0) (deprecated)");
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+module_param_named(fw_restart, iwl3945_mod_params.restart_fw, int, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
+
+module_exit(iwl3945_exit);
+module_init(iwl3945_init);
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
new file mode 100644
index 0000000..91b3d8b
--- /dev/null
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -0,0 +1,3632 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/mac80211.h>
+
+#include <asm/div64.h>
+
+#define DRV_NAME        "iwl4965"
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-sta.h"
+#include "iwl-4965-calib.h"
+#include "iwl-4965.h"
+#include "iwl-4965-led.h"
+
+
+/******************************************************************************
+ *
+ * module boiler plate
+ *
+ ******************************************************************************/
+
+/*
+ * module name, copyright, version, etc.
+ */
+#define DRV_DESCRIPTION	"Intel(R) Wireless WiFi 4965 driver for Linux"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+#define DRV_VERSION     IWLWIFI_VERSION VD
+
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("iwl4965");
+
+void iwl4965_update_chain_flags(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain) {
+		for_each_context(priv, ctx) {
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+			if (ctx->active.rx_chain != ctx->staging.rx_chain)
+				iwl_legacy_commit_rxon(priv, ctx);
+		}
+	}
+}
+
+static void iwl4965_clear_free_frames(struct iwl_priv *priv)
+{
+	struct list_head *element;
+
+	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
+		       priv->frames_count);
+
+	while (!list_empty(&priv->free_frames)) {
+		element = priv->free_frames.next;
+		list_del(element);
+		kfree(list_entry(element, struct iwl_frame, list));
+		priv->frames_count--;
+	}
+
+	if (priv->frames_count) {
+		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
+			    priv->frames_count);
+		priv->frames_count = 0;
+	}
+}
+
+static struct iwl_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
+{
+	struct iwl_frame *frame;
+	struct list_head *element;
+	if (list_empty(&priv->free_frames)) {
+		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
+		if (!frame) {
+			IWL_ERR(priv, "Could not allocate frame!\n");
+			return NULL;
+		}
+
+		priv->frames_count++;
+		return frame;
+	}
+
+	element = priv->free_frames.next;
+	list_del(element);
+	return list_entry(element, struct iwl_frame, list);
+}
+
+static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
+{
+	memset(frame, 0, sizeof(*frame));
+	list_add(&frame->list, &priv->free_frames);
+}
+
+static u32 iwl4965_fill_beacon_frame(struct iwl_priv *priv,
+				 struct ieee80211_hdr *hdr,
+				 int left)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_skb)
+		return 0;
+
+	if (priv->beacon_skb->len > left)
+		return 0;
+
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
+
+	return priv->beacon_skb->len;
+}
+
+/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
+static void iwl4965_set_beacon_tim(struct iwl_priv *priv,
+			       struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+			       u8 *beacon, u32 frame_size)
+{
+	u16 tim_idx;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
+
+	/*
+	 * The index is relative to frame start but we start looking at the
+	 * variable-length part of the beacon.
+	 */
+	tim_idx = mgmt->u.beacon.variable - beacon;
+
+	/* Parse variable-length elements of beacon to find WLAN_EID_TIM */
+	while ((tim_idx < (frame_size - 2)) &&
+			(beacon[tim_idx] != WLAN_EID_TIM))
+		tim_idx += beacon[tim_idx+1] + 2;
+
+	/* If TIM field was found, set variables */
+	if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
+		tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
+		tx_beacon_cmd->tim_size = beacon[tim_idx+1];
+	} else
+		IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
+}
+
+static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+				       struct iwl_frame *frame)
+{
+	struct iwl_tx_beacon_cmd *tx_beacon_cmd;
+	u32 frame_size;
+	u32 rate_flags;
+	u32 rate;
+	/*
+	 * We have to set up the TX command, the TX Beacon command, and the
+	 * beacon contents.
+	 */
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
+		return 0;
+	}
+
+	/* Initialize memory */
+	tx_beacon_cmd = &frame->u.beacon;
+	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+	/* Set up TX beacon contents */
+	frame_size = iwl4965_fill_beacon_frame(priv, tx_beacon_cmd->frame,
+				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+	if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
+		return 0;
+	if (!frame_size)
+		return 0;
+
+	/* Set up TX command fields */
+	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
+	tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
+	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+	tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
+		TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
+
+	/* Set up TX beacon command fields */
+	iwl4965_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
+			   frame_size);
+
+	/* Set up packet rate and flags */
+	rate = iwl_legacy_get_lowest_plcp(priv, priv->beacon_ctx);
+	priv->mgmt_tx_ant = iwl4965_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+					      priv->hw_params.valid_tx_ant);
+	rate_flags = iwl4965_ant_idx_to_flags(priv->mgmt_tx_ant);
+	if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+		rate_flags |= RATE_MCS_CCK_MSK;
+	tx_beacon_cmd->tx.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate,
+			rate_flags);
+
+	return sizeof(*tx_beacon_cmd) + frame_size;
+}
+
+int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
+{
+	struct iwl_frame *frame;
+	unsigned int frame_size;
+	int rc;
+
+	frame = iwl4965_get_free_frame(priv);
+	if (!frame) {
+		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
+			  "command.\n");
+		return -ENOMEM;
+	}
+
+	frame_size = iwl4965_hw_get_beacon_cmd(priv, frame);
+	if (!frame_size) {
+		IWL_ERR(priv, "Error configuring the beacon command\n");
+		iwl4965_free_frame(priv, frame);
+		return -EINVAL;
+	}
+
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+			      &frame->u.cmd[0]);
+
+	iwl4965_free_frame(priv, frame);
+
+	return rc;
+}
+
+static inline dma_addr_t iwl4965_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	dma_addr_t addr = get_unaligned_le32(&tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		addr |=
+		((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+	return addr;
+}
+
+static inline u16 iwl4965_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl4965_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+				  dma_addr_t addr, u16 len)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+	u16 hi_n_len = len << 4;
+
+	put_unaligned_le32(addr, &tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+	tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+	tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl4965_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+	return tfd->num_tbs & 0x1f;
+}
+
+/**
+ * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @priv - driver private data
+ * @txq - tx queue
+ *
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+void iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
+	struct iwl_tfd *tfd;
+	struct pci_dev *dev = priv->pci_dev;
+	int index = txq->q.read_ptr;
+	int i;
+	int num_tbs;
+
+	tfd = &tfd_tmp[index];
+
+	/* Sanity check on number of chunks */
+	num_tbs = iwl4965_tfd_get_num_tbs(tfd);
+
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
+		/* @todo issue fatal error, it is quite serious situation */
+		return;
+	}
+
+	/* Unmap tx_cmd */
+	if (num_tbs)
+		pci_unmap_single(dev,
+				dma_unmap_addr(&txq->meta[index], mapping),
+				dma_unmap_len(&txq->meta[index], len),
+				PCI_DMA_BIDIRECTIONAL);
+
+	/* Unmap chunks, if any. */
+	for (i = 1; i < num_tbs; i++)
+		pci_unmap_single(dev, iwl4965_tfd_tb_get_addr(tfd, i),
+				iwl4965_tfd_tb_get_len(tfd, i),
+				PCI_DMA_TODEVICE);
+
+	/* free SKB */
+	if (txq->txb) {
+		struct sk_buff *skb;
+
+		skb = txq->txb[txq->q.read_ptr].skb;
+
+		/* can be called from irqs-disabled context */
+		if (skb) {
+			dev_kfree_skb_any(skb);
+			txq->txb[txq->q.read_ptr].skb = NULL;
+		}
+	}
+}
+
+int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				 struct iwl_tx_queue *txq,
+				 dma_addr_t addr, u16 len,
+				 u8 reset, u8 pad)
+{
+	struct iwl_queue *q;
+	struct iwl_tfd *tfd, *tfd_tmp;
+	u32 num_tbs;
+
+	q = &txq->q;
+	tfd_tmp = (struct iwl_tfd *)txq->tfds;
+	tfd = &tfd_tmp[q->write_ptr];
+
+	if (reset)
+		memset(tfd, 0, sizeof(*tfd));
+
+	num_tbs = iwl4965_tfd_get_num_tbs(tfd);
+
+	/* Each TFD can point to a maximum 20 Tx buffers */
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERR(priv, "Error can not send more than %d chunks\n",
+			  IWL_NUM_OF_TBS);
+		return -EINVAL;
+	}
+
+	BUG_ON(addr & ~DMA_BIT_MASK(36));
+	if (unlikely(addr & ~IWL_TX_DMA_MASK))
+		IWL_ERR(priv, "Unaligned address = %llx\n",
+			  (unsigned long long)addr);
+
+	iwl4965_tfd_set_tb(tfd, num_tbs, addr, len);
+
+	return 0;
+}
+
+/*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
+			 struct iwl_tx_queue *txq)
+{
+	int txq_id = txq->q.id;
+
+	/* Circular buffer (TFD queue in DRAM) physical base address */
+	iwl_legacy_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+			     txq->q.dma_addr >> 8);
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * Generic RX handler implementations
+ *
+ ******************************************************************************/
+static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_alive_resp *palive;
+	struct delayed_work *pwork;
+
+	palive = &pkt->u.alive_frame;
+
+	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+		       "0x%01X 0x%01X\n",
+		       palive->is_valid, palive->ver_type,
+		       palive->ver_subtype);
+
+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
+		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		memcpy(&priv->card_alive_init,
+		       &pkt->u.alive_frame,
+		       sizeof(struct iwl_init_alive_resp));
+		pwork = &priv->init_alive_start;
+	} else {
+		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->alive_start;
+	}
+
+	/* We delay the ALIVE response by 5ms to
+	 * give the HW RF Kill time to activate... */
+	if (palive->is_valid == UCODE_VALID_OK)
+		queue_delayed_work(priv->workqueue, pwork,
+				   msecs_to_jiffies(5));
+	else
+		IWL_WARN(priv, "uCode did not respond OK.\n");
+}
+
+/**
+ * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
+ *
+ * This callback is provided in order to send a statistics request.
+ *
+ * This timer function is continually reset to execute within
+ * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
+ * was received.  We need to ensure we receive the statistics in order
+ * to update the temperature used for calibrating the TXPOWER.
+ */
+static void iwl4965_bg_statistics_periodic(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* dont send host command if rf-kill is on */
+	if (!iwl_legacy_is_ready_rf(priv))
+		return;
+
+	iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
+}
+
+
+static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
+					u32 start_idx, u32 num_events,
+					u32 mode)
+{
+	u32 i;
+	u32 ptr;        /* SRAM byte address of log data */
+	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
+
+	if (mode == 0)
+		ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
+	else
+		ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
+
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (iwl_grab_nic_access(priv)) {
+		spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+		return;
+	}
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
+	/*
+	 * "time" is actually "data" for mode 0 (no timestamp).
+	 * place event id # at far right for easier visual parsing.
+	 */
+	for (i = 0; i < num_events; i++) {
+		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (mode == 0) {
+			trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
+							0, time, ev);
+		} else {
+			data = _iwl_legacy_read_direct32(priv,
+						HBUS_TARG_MEM_RDAT);
+			trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
+						time, data, ev);
+		}
+	}
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
+{
+	u32 capacity;   /* event log capacity in # entries */
+	u32 base;       /* SRAM byte address of event log header */
+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+	u32 num_wraps;  /* # times uCode wrapped to top of log */
+	u32 next_entry; /* index of next entry to be written by uCode */
+
+	if (priv->ucode_type == UCODE_INIT)
+		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+	else
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+		capacity = iwl_legacy_read_targ_mem(priv, base);
+		num_wraps = iwl_legacy_read_targ_mem(priv,
+						base + (2 * sizeof(u32)));
+		mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
+		next_entry = iwl_legacy_read_targ_mem(priv,
+						base + (3 * sizeof(u32)));
+	} else
+		return;
+
+	if (num_wraps == priv->event_log.num_wraps) {
+		iwl4965_print_cont_event_trace(priv,
+				       base, priv->event_log.next_entry,
+				       next_entry - priv->event_log.next_entry,
+				       mode);
+		priv->event_log.non_wraps_count++;
+	} else {
+		if ((num_wraps - priv->event_log.num_wraps) > 1)
+			priv->event_log.wraps_more_count++;
+		else
+			priv->event_log.wraps_once_count++;
+		trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
+				num_wraps - priv->event_log.num_wraps,
+				next_entry, priv->event_log.next_entry);
+		if (next_entry < priv->event_log.next_entry) {
+			iwl4965_print_cont_event_trace(priv, base,
+			       priv->event_log.next_entry,
+			       capacity - priv->event_log.next_entry,
+			       mode);
+
+			iwl4965_print_cont_event_trace(priv, base, 0,
+				next_entry, mode);
+		} else {
+			iwl4965_print_cont_event_trace(priv, base,
+			       next_entry, capacity - next_entry,
+			       mode);
+
+			iwl4965_print_cont_event_trace(priv, base, 0,
+				next_entry, mode);
+		}
+	}
+	priv->event_log.num_wraps = num_wraps;
+	priv->event_log.next_entry = next_entry;
+}
+
+/**
+ * iwl4965_bg_ucode_trace - Timer callback to log ucode event
+ *
+ * The timer is continually set to execute every
+ * UCODE_TRACE_PERIOD milliseconds after the last timer expired
+ * this function is to perform continuous uCode event logging operation
+ * if enabled
+ */
+static void iwl4965_bg_ucode_trace(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (priv->event_log.ucode_trace) {
+		iwl4965_continuous_event_trace(priv);
+		/* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
+		mod_timer(&priv->ucode_trace,
+			 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
+	}
+}
+
+static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl4965_beacon_notif *beacon =
+		(struct iwl4965_beacon_notif *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
+		"tsf %d %d rate %d\n",
+		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+#endif
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+}
+
+static void iwl4965_perform_ct_kill_task(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	IWL_DEBUG_POWER(priv, "Stop all queues\n");
+
+	if (priv->mac80211_registered)
+		ieee80211_stop_queues(priv->hw);
+
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+			CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+	iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+	spin_lock_irqsave(&priv->reg_lock, flags);
+	if (!iwl_grab_nic_access(priv))
+		iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+	unsigned long status = priv->status;
+
+	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & CT_CARD_DISABLED) ?
+			  "Reached" : "Not reached");
+
+	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
+		     CT_CARD_DISABLED)) {
+
+		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+		iwl_legacy_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+
+		if (!(flags & RXON_CARD_DISABLED)) {
+			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+			iwl_legacy_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+		}
+	}
+
+	if (flags & CT_CARD_DISABLED)
+		iwl4965_perform_ct_kill_task(priv);
+
+	if (flags & HW_CARD_DISABLED)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	if (!(flags & RXON_CARD_DISABLED))
+		iwl_legacy_scan_cancel(priv);
+
+	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
+	else
+		wake_up_interruptible(&priv->wait_command_queue);
+}
+
+/**
+ * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
+ *
+ * Setup the RX handlers for each of the reply types sent from the uCode
+ * to the host.
+ *
+ * This function chains into the hardware specific files for them to setup
+ * any hardware specific handlers as well.
+ */
+static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+{
+	priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
+	priv->rx_handlers[REPLY_ERROR] = iwl_legacy_rx_reply_error;
+	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_legacy_rx_csa;
+	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+			iwl_legacy_rx_spectrum_measure_notif;
+	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_legacy_rx_pm_sleep_notif;
+	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
+	    iwl_legacy_rx_pm_debug_statistics_notif;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+
+	/*
+	 * The same handler is used for both the REPLY to a discrete
+	 * statistics request from the host as well as for the periodic
+	 * statistics notifications (after received beacons) from the uCode.
+	 */
+	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_reply_statistics;
+	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_rx_statistics;
+
+	iwl_legacy_setup_rx_scan_handlers(priv);
+
+	/* status change handler */
+	priv->rx_handlers[CARD_STATE_NOTIFICATION] =
+					iwl4965_rx_card_state_notif;
+
+	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
+	    iwl4965_rx_missed_beacon_notif;
+	/* Rx handlers */
+	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
+	priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
+	/* block ack */
+	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
+	/* Set up hardware specific Rx handlers */
+	priv->cfg->ops->lib->rx_handler_setup(priv);
+}
+
+/**
+ * iwl4965_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the priv->rx_handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+void iwl4965_rx_handle(struct iwl_priv *priv)
+{
+	struct iwl_rx_mem_buffer *rxb;
+	struct iwl_rx_packet *pkt;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	u32 r, i;
+	int reclaim;
+	unsigned long flags;
+	u8 fill_rx = 0;
+	u32 count = 8;
+	int total_empty;
+
+	/* uCode's read index (stored in shared DRAM) indicates the last Rx
+	 * buffer that the driver may process (last buffer filled by ucode). */
+	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
+	i = rxq->read;
+
+	/* Rx interrupt, but nothing sent from uCode */
+	if (i == r)
+		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
+
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - rxq->write_actual;
+	if (total_empty < 0)
+		total_empty += RX_QUEUE_SIZE;
+
+	if (total_empty > (RX_QUEUE_SIZE / 2))
+		fill_rx = 1;
+
+	while (i != r) {
+		int len;
+
+		rxb = rxq->queue[i];
+
+		/* If an RXB doesn't have a Rx queue slot associated with it,
+		 * then a bug has been introduced in the queue refilling
+		 * routines -- catch it here */
+		BUG_ON(rxb == NULL);
+
+		rxq->queue[i] = NULL;
+
+		pci_unmap_page(priv->pci_dev, rxb->page_dma,
+			       PAGE_SIZE << priv->hw_params.rx_page_order,
+			       PCI_DMA_FROMDEVICE);
+		pkt = rxb_addr(rxb);
+
+		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+		len += sizeof(u32); /* account for status word */
+		trace_iwlwifi_legacy_dev_rx(priv, pkt, len);
+
+		/* Reclaim a command buffer only if this packet is a response
+		 *   to a (driver-originated) command.
+		 * If the packet (e.g. Rx frame) originated from uCode,
+		 *   there is no command buffer to reclaim.
+		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+		 *   but apparently a few don't get set; catch them here. */
+		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+			(pkt->hdr.cmd != REPLY_RX) &&
+			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
+			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+			(pkt->hdr.cmd != REPLY_TX);
+
+		/* Based on type of command response or notification,
+		 *   handle those that need handling via function in
+		 *   rx_handlers table.  See iwl4965_setup_rx_handlers() */
+		if (priv->rx_handlers[pkt->hdr.cmd]) {
+			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
+				i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+		} else {
+			/* No handling needed */
+			IWL_DEBUG_RX(priv,
+				"r %d i %d No handler needed for %s, 0x%02x\n",
+				r, i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+		}
+
+		/*
+		 * XXX: After here, we should always check rxb->page
+		 * against NULL before touching it or its virtual
+		 * memory (pkt). Because some rx_handler might have
+		 * already taken or freed the pages.
+		 */
+
+		if (reclaim) {
+			/* Invoke any callbacks, transfer the buffer to caller,
+			 * and fire off the (possibly) blocking iwl_legacy_send_cmd()
+			 * as we reclaim the driver command queue */
+			if (rxb->page)
+				iwl_legacy_tx_cmd_complete(priv, rxb);
+			else
+				IWL_WARN(priv, "Claim null rxb?\n");
+		}
+
+		/* Reuse the page if possible. For notification packets and
+		 * SKBs that fail to Rx correctly, add them back into the
+		 * rx_free list for reuse later. */
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (rxb->page != NULL) {
+			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+				0, PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			list_add_tail(&rxb->list, &rxq->rx_free);
+			rxq->free_count++;
+		} else
+			list_add_tail(&rxb->list, &rxq->rx_used);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		i = (i + 1) & RX_QUEUE_MASK;
+		/* If there are a lot of unused frames,
+		 * restock the Rx queue so ucode wont assert. */
+		if (fill_rx) {
+			count++;
+			if (count >= 8) {
+				rxq->read = i;
+				iwl4965_rx_replenish_now(priv);
+				count = 0;
+			}
+		}
+	}
+
+	/* Backtrack one entry */
+	rxq->read = i;
+	if (fill_rx)
+		iwl4965_rx_replenish_now(priv);
+	else
+		iwl4965_rx_queue_restock(priv);
+}
+
+/* call this function to flush any scheduled tasklet */
+static inline void iwl4965_synchronize_irq(struct iwl_priv *priv)
+{
+	/* wait to make sure we flush pending tasklet*/
+	synchronize_irq(priv->pci_dev->irq);
+	tasklet_kill(&priv->irq_tasklet);
+}
+
+static void iwl4965_irq_tasklet(struct iwl_priv *priv)
+{
+	u32 inta, handled = 0;
+	u32 inta_fh;
+	unsigned long flags;
+	u32 i;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	u32 inta_mask;
+#endif
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Ack/clear/reset pending uCode interrupts.
+	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
+	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
+	inta = iwl_read32(priv, CSR_INT);
+	iwl_write32(priv, CSR_INT, inta);
+
+	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
+	 * Any new interrupts that happen after this, either while we're
+	 * in this tasklet, or later, will show up in next ISR/tasklet. */
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & IWL_DL_ISR) {
+		/* just for debug */
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+			      inta, inta_mask, inta_fh);
+	}
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
+	 * atomic, make sure that inta covers all the interrupts that
+	 * we've discovered, even if FH interrupt came in just after
+	 * reading CSR_INT. */
+	if (inta_fh & CSR49_FH_INT_RX_MASK)
+		inta |= CSR_INT_BIT_FH_RX;
+	if (inta_fh & CSR49_FH_INT_TX_MASK)
+		inta |= CSR_INT_BIT_FH_TX;
+
+	/* Now service all interrupt bits discovered above. */
+	if (inta & CSR_INT_BIT_HW_ERR) {
+		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
+
+		/* Tell the device to stop sending interrupts */
+		iwl_legacy_disable_interrupts(priv);
+
+		priv->isr_stats.hw++;
+		iwl_legacy_irq_handle_error(priv);
+
+		handled |= CSR_INT_BIT_HW_ERR;
+
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
+		/* NIC fires this, but we don't use it, redundant with WAKEUP */
+		if (inta & CSR_INT_BIT_SCD) {
+			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
+				      "the frame/frames.\n");
+			priv->isr_stats.sch++;
+		}
+
+		/* Alive notification via Rx interrupt will do the real work */
+		if (inta & CSR_INT_BIT_ALIVE) {
+			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
+			priv->isr_stats.alive++;
+		}
+	}
+#endif
+	/* Safely ignore these bits for debug checks below */
+	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
+
+	/* HW RF KILL switch toggled */
+	if (inta & CSR_INT_BIT_RF_KILL) {
+		int hw_rf_kill = 0;
+		if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+			hw_rf_kill = 1;
+
+		IWL_WARN(priv, "RF_KILL bit toggled to %s.\n",
+				hw_rf_kill ? "disable radio" : "enable radio");
+
+		priv->isr_stats.rfkill++;
+
+		/* driver only loads ucode once setting the interface up.
+		 * the driver allows loading the ucode even if the radio
+		 * is killed. Hence update the killswitch state here. The
+		 * rfkill handler will care about restarting if needed.
+		 */
+		if (!test_bit(STATUS_ALIVE, &priv->status)) {
+			if (hw_rf_kill)
+				set_bit(STATUS_RF_KILL_HW, &priv->status);
+			else
+				clear_bit(STATUS_RF_KILL_HW, &priv->status);
+			wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill);
+		}
+
+		handled |= CSR_INT_BIT_RF_KILL;
+	}
+
+	/* Chip got too hot and stopped itself */
+	if (inta & CSR_INT_BIT_CT_KILL) {
+		IWL_ERR(priv, "Microcode CT kill error detected.\n");
+		priv->isr_stats.ctkill++;
+		handled |= CSR_INT_BIT_CT_KILL;
+	}
+
+	/* Error detected by uCode */
+	if (inta & CSR_INT_BIT_SW_ERR) {
+		IWL_ERR(priv, "Microcode SW error detected. "
+			" Restarting 0x%X.\n", inta);
+		priv->isr_stats.sw++;
+		iwl_legacy_irq_handle_error(priv);
+		handled |= CSR_INT_BIT_SW_ERR;
+	}
+
+	/*
+	 * uCode wakes up after power-down sleep.
+	 * Tell device about any new tx or host commands enqueued,
+	 * and about any Rx buffers made available while asleep.
+	 */
+	if (inta & CSR_INT_BIT_WAKEUP) {
+		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
+		iwl_legacy_rx_queue_update_write_ptr(priv, &priv->rxq);
+		for (i = 0; i < priv->hw_params.max_txq_num; i++)
+			iwl_legacy_txq_update_write_ptr(priv, &priv->txq[i]);
+		priv->isr_stats.wakeup++;
+		handled |= CSR_INT_BIT_WAKEUP;
+	}
+
+	/* All uCode command responses, including Tx command responses,
+	 * Rx "responses" (frame-received notification), and other
+	 * notifications from uCode come through here*/
+	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
+		iwl4965_rx_handle(priv);
+		priv->isr_stats.rx++;
+		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+	}
+
+	/* This "Tx" DMA channel is used only for loading uCode */
+	if (inta & CSR_INT_BIT_FH_TX) {
+		IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
+		priv->isr_stats.tx++;
+		handled |= CSR_INT_BIT_FH_TX;
+		/* Wake up uCode load routine, now that load is complete */
+		priv->ucode_write_complete = 1;
+		wake_up_interruptible(&priv->wait_command_queue);
+	}
+
+	if (inta & ~handled) {
+		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
+		priv->isr_stats.unhandled++;
+	}
+
+	if (inta & ~(priv->inta_mask)) {
+		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
+			 inta & ~priv->inta_mask);
+		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
+	}
+
+	/* Re-enable all interrupts */
+	/* only Re-enable if diabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_legacy_enable_interrupts(priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
+		inta = iwl_read32(priv, CSR_INT);
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+		IWL_DEBUG_ISR(priv,
+			"End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+	}
+#endif
+}
+
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t iwl4965_show_debug_level(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%08X\n", iwl_legacy_get_debug_level(priv));
+}
+static ssize_t iwl4965_store_debug_level(struct device *d,
+				struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 0, &val);
+	if (ret)
+		IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
+	else {
+		priv->debug_level = val;
+		if (iwl_legacy_alloc_traffic_mem(priv))
+			IWL_ERR(priv,
+				"Not enough memory to generate traffic log\n");
+	}
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+			iwl4965_show_debug_level, iwl4965_store_debug_level);
+
+
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
+
+
+static ssize_t iwl4965_show_temperature(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", priv->temperature);
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, iwl4965_show_temperature, NULL);
+
+static ssize_t iwl4965_show_tx_power(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_ready_rf(priv))
+		return sprintf(buf, "off\n");
+	else
+		return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t iwl4965_store_tx_power(struct device *d,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 10, &val);
+	if (ret)
+		IWL_INFO(priv, "%s is not in decimal form.\n", buf);
+	else {
+		ret = iwl_legacy_set_tx_power(priv, val, false);
+		if (ret)
+			IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+				ret);
+		else
+			ret = count;
+	}
+	return ret;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO,
+			iwl4965_show_tx_power, iwl4965_store_tx_power);
+
+static struct attribute *iwl_sysfs_entries[] = {
+	&dev_attr_temperature.attr,
+	&dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	&dev_attr_debug_level.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group iwl_attribute_group = {
+	.name = NULL,		/* put in device directory */
+	.attrs = iwl_sysfs_entries,
+};
+
+/******************************************************************************
+ *
+ * uCode download functions
+ *
+ ******************************************************************************/
+
+static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
+{
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
+}
+
+static void iwl4965_nic_start(struct iwl_priv *priv)
+{
+	/* Remove all resets to allow NIC to operate */
+	iwl_write32(priv, CSR_RESET, 0);
+}
+
+static void iwl4965_ucode_callback(const struct firmware *ucode_raw,
+					void *context);
+static int iwl4965_mac_setup_register(struct iwl_priv *priv,
+						u32 max_probe_length);
+
+static int __must_check iwl4965_request_firmware(struct iwl_priv *priv, bool first)
+{
+	const char *name_pre = priv->cfg->fw_name_pre;
+	char tag[8];
+
+	if (first) {
+		priv->fw_index = priv->cfg->ucode_api_max;
+		sprintf(tag, "%d", priv->fw_index);
+	} else {
+		priv->fw_index--;
+		sprintf(tag, "%d", priv->fw_index);
+	}
+
+	if (priv->fw_index < priv->cfg->ucode_api_min) {
+		IWL_ERR(priv, "no suitable firmware found!\n");
+		return -ENOENT;
+	}
+
+	sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
+
+	IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
+		       priv->firmware_name);
+
+	return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
+				       &priv->pci_dev->dev, GFP_KERNEL, priv,
+				       iwl4965_ucode_callback);
+}
+
+struct iwl4965_firmware_pieces {
+	const void *inst, *data, *init, *init_data, *boot;
+	size_t inst_size, data_size, init_size, init_data_size, boot_size;
+};
+
+static int iwl4965_load_firmware(struct iwl_priv *priv,
+				       const struct firmware *ucode_raw,
+				       struct iwl4965_firmware_pieces *pieces)
+{
+	struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
+	u32 api_ver, hdr_size;
+	const u8 *src;
+
+	priv->ucode_ver = le32_to_cpu(ucode->ver);
+	api_ver = IWL_UCODE_API(priv->ucode_ver);
+
+	switch (api_ver) {
+	default:
+	case 0:
+	case 1:
+	case 2:
+		hdr_size = 24;
+		if (ucode_raw->size < hdr_size) {
+			IWL_ERR(priv, "File size too small!\n");
+			return -EINVAL;
+		}
+		pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
+		pieces->data_size = le32_to_cpu(ucode->v1.data_size);
+		pieces->init_size = le32_to_cpu(ucode->v1.init_size);
+		pieces->init_data_size =
+				le32_to_cpu(ucode->v1.init_data_size);
+		pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
+		src = ucode->v1.data;
+		break;
+	}
+
+	/* Verify size of file vs. image size info in file's header */
+	if (ucode_raw->size != hdr_size + pieces->inst_size +
+				pieces->data_size + pieces->init_size +
+				pieces->init_data_size + pieces->boot_size) {
+
+		IWL_ERR(priv,
+			"uCode file size %d does not match expected size\n",
+			(int)ucode_raw->size);
+		return -EINVAL;
+	}
+
+	pieces->inst = src;
+	src += pieces->inst_size;
+	pieces->data = src;
+	src += pieces->data_size;
+	pieces->init = src;
+	src += pieces->init_size;
+	pieces->init_data = src;
+	src += pieces->init_data_size;
+	pieces->boot = src;
+	src += pieces->boot_size;
+
+	return 0;
+}
+
+/**
+ * iwl4965_ucode_callback - callback when firmware was loaded
+ *
+ * If loaded successfully, copies the firmware into buffers
+ * for the card to fetch (via DMA).
+ */
+static void
+iwl4965_ucode_callback(const struct firmware *ucode_raw, void *context)
+{
+	struct iwl_priv *priv = context;
+	struct iwl_ucode_header *ucode;
+	int err;
+	struct iwl4965_firmware_pieces pieces;
+	const unsigned int api_max = priv->cfg->ucode_api_max;
+	const unsigned int api_min = priv->cfg->ucode_api_min;
+	u32 api_ver;
+
+	u32 max_probe_length = 200;
+	u32 standard_phy_calibration_size =
+			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+	memset(&pieces, 0, sizeof(pieces));
+
+	if (!ucode_raw) {
+		if (priv->fw_index <= priv->cfg->ucode_api_max)
+			IWL_ERR(priv,
+				"request for firmware file '%s' failed.\n",
+				priv->firmware_name);
+		goto try_again;
+	}
+
+	IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
+		       priv->firmware_name, ucode_raw->size);
+
+	/* Make sure that we got at least the API version number */
+	if (ucode_raw->size < 4) {
+		IWL_ERR(priv, "File size way too small!\n");
+		goto try_again;
+	}
+
+	/* Data from ucode file:  header followed by uCode images */
+	ucode = (struct iwl_ucode_header *)ucode_raw->data;
+
+	err = iwl4965_load_firmware(priv, ucode_raw, &pieces);
+
+	if (err)
+		goto try_again;
+
+	api_ver = IWL_UCODE_API(priv->ucode_ver);
+
+	/*
+	 * api_ver should match the api version forming part of the
+	 * firmware filename ... but we don't check for that and only rely
+	 * on the API version read from firmware header from here on forward
+	 */
+	if (api_ver < api_min || api_ver > api_max) {
+		IWL_ERR(priv,
+			"Driver unable to support your firmware API. "
+			"Driver supports v%u, firmware is v%u.\n",
+			api_max, api_ver);
+		goto try_again;
+	}
+
+	if (api_ver != api_max)
+		IWL_ERR(priv,
+			"Firmware has old API version. Expected v%u, "
+			"got v%u. New firmware can be obtained "
+			"from http://www.intellinuxwireless.org.\n",
+			api_max, api_ver);
+
+	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
+		 IWL_UCODE_MAJOR(priv->ucode_ver),
+		 IWL_UCODE_MINOR(priv->ucode_ver),
+		 IWL_UCODE_API(priv->ucode_ver),
+		 IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	snprintf(priv->hw->wiphy->fw_version,
+		 sizeof(priv->hw->wiphy->fw_version),
+		 "%u.%u.%u.%u",
+		 IWL_UCODE_MAJOR(priv->ucode_ver),
+		 IWL_UCODE_MINOR(priv->ucode_ver),
+		 IWL_UCODE_API(priv->ucode_ver),
+		 IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	/*
+	 * For any of the failures below (before allocating pci memory)
+	 * we will try to load a version with a smaller API -- maybe the
+	 * user just got a corrupted version of the latest API.
+	 */
+
+	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
+		       priv->ucode_ver);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
+		       pieces.inst_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
+		       pieces.data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
+		       pieces.init_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
+		       pieces.init_data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n",
+		       pieces.boot_size);
+
+	/* Verify that uCode images will fit in card's SRAM */
+	if (pieces.inst_size > priv->hw_params.max_inst_size) {
+		IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
+			pieces.inst_size);
+		goto try_again;
+	}
+
+	if (pieces.data_size > priv->hw_params.max_data_size) {
+		IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
+			pieces.data_size);
+		goto try_again;
+	}
+
+	if (pieces.init_size > priv->hw_params.max_inst_size) {
+		IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
+			pieces.init_size);
+		goto try_again;
+	}
+
+	if (pieces.init_data_size > priv->hw_params.max_data_size) {
+		IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
+			pieces.init_data_size);
+		goto try_again;
+	}
+
+	if (pieces.boot_size > priv->hw_params.max_bsm_size) {
+		IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n",
+			pieces.boot_size);
+		goto try_again;
+	}
+
+	/* Allocate ucode buffers for card's bus-master loading ... */
+
+	/* Runtime instructions and 2 copies of data:
+	 * 1) unmodified from disk
+	 * 2) backup cache for save/restore during power-downs */
+	priv->ucode_code.len = pieces.inst_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
+
+	priv->ucode_data.len = pieces.data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
+
+	priv->ucode_data_backup.len = pieces.data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+
+	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+	    !priv->ucode_data_backup.v_addr)
+		goto err_pci_alloc;
+
+	/* Initialization instructions and data */
+	if (pieces.init_size && pieces.init_data_size) {
+		priv->ucode_init.len = pieces.init_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+		priv->ucode_init_data.len = pieces.init_data_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+
+		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Bootstrap (instructions only, no data) */
+	if (pieces.boot_size) {
+		priv->ucode_boot.len = pieces.boot_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
+
+		if (!priv->ucode_boot.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Now that we can no longer fail, copy information */
+
+	priv->sta_key_max_num = STA_KEY_MAX_NUM;
+
+	/* Copy images into buffers for card's bus-master reads ... */
+
+	/* Runtime instructions (first block of data in file) */
+	IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n",
+			pieces.inst_size);
+	memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size);
+
+	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
+		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
+
+	/*
+	 * Runtime data
+	 * NOTE:  Copy into backup buffer will be done in iwl_up()
+	 */
+	IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n",
+			pieces.data_size);
+	memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size);
+	memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
+
+	/* Initialization instructions */
+	if (pieces.init_size) {
+		IWL_DEBUG_INFO(priv,
+				"Copying (but not loading) init instr len %Zd\n",
+				pieces.init_size);
+		memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size);
+	}
+
+	/* Initialization data */
+	if (pieces.init_data_size) {
+		IWL_DEBUG_INFO(priv,
+				"Copying (but not loading) init data len %Zd\n",
+			       pieces.init_data_size);
+		memcpy(priv->ucode_init_data.v_addr, pieces.init_data,
+		       pieces.init_data_size);
+	}
+
+	/* Bootstrap instructions */
+	IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n",
+			pieces.boot_size);
+	memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
+
+	/*
+	 * figure out the offset of chain noise reset and gain commands
+	 * base on the size of standard phy calibration commands table size
+	 */
+	priv->_4965.phy_calib_chain_noise_reset_cmd =
+		standard_phy_calibration_size;
+	priv->_4965.phy_calib_chain_noise_gain_cmd =
+		standard_phy_calibration_size + 1;
+
+	/**************************************************
+	 * This is still part of probe() in a sense...
+	 *
+	 * 9. Setup and register with mac80211 and debugfs
+	 **************************************************/
+	err = iwl4965_mac_setup_register(priv, max_probe_length);
+	if (err)
+		goto out_unbind;
+
+	err = iwl_legacy_dbgfs_register(priv, DRV_NAME);
+	if (err)
+		IWL_ERR(priv,
+		"failed to create debugfs files. Ignoring error: %d\n", err);
+
+	err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+					&iwl_attribute_group);
+	if (err) {
+		IWL_ERR(priv, "failed to create sysfs device attributes\n");
+		goto out_unbind;
+	}
+
+	/* We have our copies now, allow OS release its copies */
+	release_firmware(ucode_raw);
+	complete(&priv->_4965.firmware_loading_complete);
+	return;
+
+ try_again:
+	/* try next, if any */
+	if (iwl4965_request_firmware(priv, false))
+		goto out_unbind;
+	release_firmware(ucode_raw);
+	return;
+
+ err_pci_alloc:
+	IWL_ERR(priv, "failed to allocate pci memory\n");
+	iwl4965_dealloc_ucode_pci(priv);
+ out_unbind:
+	complete(&priv->_4965.firmware_loading_complete);
+	device_release_driver(&priv->pci_dev->dev);
+	release_firmware(ucode_raw);
+}
+
+static const char * const desc_lookup_text[] = {
+	"OK",
+	"FAIL",
+	"BAD_PARAM",
+	"BAD_CHECKSUM",
+	"NMI_INTERRUPT_WDG",
+	"SYSASSERT",
+	"FATAL_ERROR",
+	"BAD_COMMAND",
+	"HW_ERROR_TUNE_LOCK",
+	"HW_ERROR_TEMPERATURE",
+	"ILLEGAL_CHAN_FREQ",
+	"VCC_NOT_STABLE",
+	"FH_ERROR",
+	"NMI_INTERRUPT_HOST",
+	"NMI_INTERRUPT_ACTION_PT",
+	"NMI_INTERRUPT_UNKNOWN",
+	"UCODE_VERSION_MISMATCH",
+	"HW_ERROR_ABS_LOCK",
+	"HW_ERROR_CAL_LOCK_FAIL",
+	"NMI_INTERRUPT_INST_ACTION_PT",
+	"NMI_INTERRUPT_DATA_ACTION_PT",
+	"NMI_TRM_HW_ER",
+	"NMI_INTERRUPT_TRM",
+	"NMI_INTERRUPT_BREAK_POINT"
+	"DEBUG_0",
+	"DEBUG_1",
+	"DEBUG_2",
+	"DEBUG_3",
+};
+
+static struct { char *name; u8 num; } advanced_lookup[] = {
+	{ "NMI_INTERRUPT_WDG", 0x34 },
+	{ "SYSASSERT", 0x35 },
+	{ "UCODE_VERSION_MISMATCH", 0x37 },
+	{ "BAD_COMMAND", 0x38 },
+	{ "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
+	{ "FATAL_ERROR", 0x3D },
+	{ "NMI_TRM_HW_ERR", 0x46 },
+	{ "NMI_INTERRUPT_TRM", 0x4C },
+	{ "NMI_INTERRUPT_BREAK_POINT", 0x54 },
+	{ "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
+	{ "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
+	{ "NMI_INTERRUPT_HOST", 0x66 },
+	{ "NMI_INTERRUPT_ACTION_PT", 0x7C },
+	{ "NMI_INTERRUPT_UNKNOWN", 0x84 },
+	{ "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
+	{ "ADVANCED_SYSASSERT", 0 },
+};
+
+static const char *iwl4965_desc_lookup(u32 num)
+{
+	int i;
+	int max = ARRAY_SIZE(desc_lookup_text);
+
+	if (num < max)
+		return desc_lookup_text[num];
+
+	max = ARRAY_SIZE(advanced_lookup) - 1;
+	for (i = 0; i < max; i++) {
+		if (advanced_lookup[i].num == num)
+			break;
+	}
+	return advanced_lookup[i].name;
+}
+
+#define ERROR_START_OFFSET  (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+
+void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
+{
+	u32 data2, line;
+	u32 desc, time, count, base, data1;
+	u32 blink1, blink2, ilink1, ilink2;
+	u32 pc, hcmd;
+
+	if (priv->ucode_type == UCODE_INIT) {
+		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+	} else {
+		base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+	}
+
+	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv,
+			"Not valid error log pointer 0x%08X for %s uCode\n",
+			base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
+		return;
+	}
+
+	count = iwl_legacy_read_targ_mem(priv, base);
+
+	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+			priv->status, count);
+	}
+
+	desc = iwl_legacy_read_targ_mem(priv, base + 1 * sizeof(u32));
+	priv->isr_stats.err_code = desc;
+	pc = iwl_legacy_read_targ_mem(priv, base + 2 * sizeof(u32));
+	blink1 = iwl_legacy_read_targ_mem(priv, base + 3 * sizeof(u32));
+	blink2 = iwl_legacy_read_targ_mem(priv, base + 4 * sizeof(u32));
+	ilink1 = iwl_legacy_read_targ_mem(priv, base + 5 * sizeof(u32));
+	ilink2 = iwl_legacy_read_targ_mem(priv, base + 6 * sizeof(u32));
+	data1 = iwl_legacy_read_targ_mem(priv, base + 7 * sizeof(u32));
+	data2 = iwl_legacy_read_targ_mem(priv, base + 8 * sizeof(u32));
+	line = iwl_legacy_read_targ_mem(priv, base + 9 * sizeof(u32));
+	time = iwl_legacy_read_targ_mem(priv, base + 11 * sizeof(u32));
+	hcmd = iwl_legacy_read_targ_mem(priv, base + 22 * sizeof(u32));
+
+	trace_iwlwifi_legacy_dev_ucode_error(priv, desc,
+					time, data1, data2, line,
+				      blink1, blink2, ilink1, ilink2);
+
+	IWL_ERR(priv, "Desc                                  Time       "
+		"data1      data2      line\n");
+	IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
+		iwl4965_desc_lookup(desc), desc, time, data1, data2, line);
+	IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
+	IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
+		pc, blink1, blink2, ilink1, ilink2, hcmd);
+}
+
+#define EVENT_START_OFFSET  (4 * sizeof(u32))
+
+/**
+ * iwl4965_print_event_log - Dump error event log to syslog
+ *
+ */
+static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
+			       u32 num_events, u32 mode,
+			       int pos, char **buf, size_t bufsz)
+{
+	u32 i;
+	u32 base;       /* SRAM byte address of event log header */
+	u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+	u32 ptr;        /* SRAM byte address of log data */
+	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
+
+	if (num_events == 0)
+		return pos;
+
+	if (priv->ucode_type == UCODE_INIT) {
+		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+	} else {
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	}
+
+	if (mode == 0)
+		event_size = 2 * sizeof(u32);
+	else
+		event_size = 3 * sizeof(u32);
+
+	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
+	/* "time" is actually "data" for mode 0 (no timestamp).
+	* place event id # at far right for easier visual parsing. */
+	for (i = 0; i < num_events; i++) {
+		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (mode == 0) {
+			/* data, ev */
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"EVT_LOG:0x%08x:%04u\n",
+						time, ev);
+			} else {
+				trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
+					time, ev);
+				IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
+					time, ev);
+			}
+		} else {
+			data = _iwl_legacy_read_direct32(priv,
+						HBUS_TARG_MEM_RDAT);
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"EVT_LOGT:%010u:0x%08x:%04u\n",
+						 time, data, ev);
+			} else {
+				IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+					time, data, ev);
+				trace_iwlwifi_legacy_dev_ucode_event(priv, time,
+					data, ev);
+			}
+		}
+	}
+
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return pos;
+}
+
+/**
+ * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
+ */
+static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+				    u32 num_wraps, u32 next_entry,
+				    u32 size, u32 mode,
+				    int pos, char **buf, size_t bufsz)
+{
+	/*
+	 * display the newest DEFAULT_LOG_ENTRIES entries
+	 * i.e the entries just before the next ont that uCode would fill.
+	 */
+	if (num_wraps) {
+		if (next_entry < size) {
+			pos = iwl4965_print_event_log(priv,
+						capacity - (size - next_entry),
+						size - next_entry, mode,
+						pos, buf, bufsz);
+			pos = iwl4965_print_event_log(priv, 0,
+						  next_entry, mode,
+						  pos, buf, bufsz);
+		} else
+			pos = iwl4965_print_event_log(priv, next_entry - size,
+						  size, mode, pos, buf, bufsz);
+	} else {
+		if (next_entry < size) {
+			pos = iwl4965_print_event_log(priv, 0, next_entry,
+						  mode, pos, buf, bufsz);
+		} else {
+			pos = iwl4965_print_event_log(priv, next_entry - size,
+						  size, mode, pos, buf, bufsz);
+		}
+	}
+	return pos;
+}
+
+#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
+
+int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
+			    char **buf, bool display)
+{
+	u32 base;       /* SRAM byte address of event log header */
+	u32 capacity;   /* event log capacity in # entries */
+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+	u32 num_wraps;  /* # times uCode wrapped to top of log */
+	u32 next_entry; /* index of next entry to be written by uCode */
+	u32 size;       /* # entries that we'll print */
+	int pos = 0;
+	size_t bufsz = 0;
+
+	if (priv->ucode_type == UCODE_INIT) {
+		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+	} else {
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	}
+
+	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv,
+			"Invalid event log pointer 0x%08X for %s uCode\n",
+			base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
+		return -EINVAL;
+	}
+
+	/* event log header */
+	capacity = iwl_legacy_read_targ_mem(priv, base);
+	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
+	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
+	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+	size = num_wraps ? capacity : next_entry;
+
+	/* bail out if nothing in log */
+	if (size == 0) {
+		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+		return pos;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
+		size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+			? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#else
+	size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+		? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#endif
+	IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
+		size);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (display) {
+		if (full_log)
+			bufsz = capacity * 48;
+		else
+			bufsz = size * 48;
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+	}
+	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
+		/*
+		 * if uCode has wrapped back to top of log,
+		 * start at the oldest entry,
+		 * i.e the next one that uCode would fill.
+		 */
+		if (num_wraps)
+			pos = iwl4965_print_event_log(priv, next_entry,
+						capacity - next_entry, mode,
+						pos, buf, bufsz);
+		/* (then/else) start at top of log */
+		pos = iwl4965_print_event_log(priv, 0,
+					  next_entry, mode, pos, buf, bufsz);
+	} else
+		pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
+						next_entry, size, mode,
+						pos, buf, bufsz);
+#else
+	pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
+					next_entry, size, mode,
+					pos, buf, bufsz);
+#endif
+	return pos;
+}
+
+static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
+{
+	struct iwl_ct_kill_config cmd;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	cmd.critical_temperature_R =
+		cpu_to_le32(priv->hw_params.ct_kill_threshold);
+
+	ret = iwl_legacy_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+			       sizeof(cmd), &cmd);
+	if (ret)
+		IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+	else
+		IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+				"succeeded, "
+				"critical temperature is %d\n",
+				priv->hw_params.ct_kill_threshold);
+}
+
+static const s8 default_queue_to_tx_fifo[] = {
+	IWL_TX_FIFO_VO,
+	IWL_TX_FIFO_VI,
+	IWL_TX_FIFO_BE,
+	IWL_TX_FIFO_BK,
+	IWL49_CMD_FIFO_NUM,
+	IWL_TX_FIFO_UNUSED,
+	IWL_TX_FIFO_UNUSED,
+};
+
+static int iwl4965_alive_notify(struct iwl_priv *priv)
+{
+	u32 a;
+	unsigned long flags;
+	int i, chan;
+	u32 reg_val;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Clear 4965's internal Tx Scheduler data base */
+	priv->scd_base_addr = iwl_legacy_read_prph(priv,
+					IWL49_SCD_SRAM_BASE_ADDR);
+	a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET;
+	for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
+		iwl_legacy_write_targ_mem(priv, a, 0);
+	for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
+		iwl_legacy_write_targ_mem(priv, a, 0);
+	for (; a < priv->scd_base_addr +
+	       IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
+		iwl_legacy_write_targ_mem(priv, a, 0);
+
+	/* Tel 4965 where to find Tx byte count tables */
+	iwl_legacy_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
+			priv->scd_bc_tbls.dma >> 10);
+
+	/* Enable DMA channel */
+	for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
+		iwl_legacy_write_direct32(priv,
+				FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+	/* Update FH chicken bits */
+	reg_val = iwl_legacy_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
+	iwl_legacy_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
+			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+	/* Disable chain mode for all queues */
+	iwl_legacy_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
+
+	/* Initialize each Tx queue (including the command queue) */
+	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
+
+		/* TFD circular buffer read/write indexes */
+		iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
+		iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+
+		/* Max Tx Window size for Scheduler-ACK mode */
+		iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
+				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i),
+				(SCD_WIN_SIZE <<
+				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+		/* Frame limit */
+		iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
+				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
+				sizeof(u32),
+				(SCD_FRAME_LIMIT <<
+				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+	}
+	iwl_legacy_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
+				 (1 << priv->hw_params.max_txq_num) - 1);
+
+	/* Activate all Tx DMA/FIFO channels */
+	iwl4965_txq_set_sched(priv, IWL_MASK(0, 6));
+
+	iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
+
+	/* make sure all queue are not stopped */
+	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+	for (i = 0; i < 4; i++)
+		atomic_set(&priv->queue_stop_count[i], 0);
+
+	/* reset to 0 to enable all the queue first */
+	priv->txq_ctx_active_msk = 0;
+	/* Map each Tx/cmd queue to its corresponding fifo */
+	BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
+
+	for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
+		int ac = default_queue_to_tx_fifo[i];
+
+		iwl_txq_ctx_activate(priv, i);
+
+		if (ac == IWL_TX_FIFO_UNUSED)
+			continue;
+
+		iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+/**
+ * iwl4965_alive_start - called after REPLY_ALIVE notification received
+ *                   from protocol/runtime uCode (initialization uCode's
+ *                   Alive gets handled by iwl_init_alive_start()).
+ */
+static void iwl4965_alive_start(struct iwl_priv *priv)
+{
+	int ret = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+
+	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
+		/* We had an error bringing up the hardware, so take it
+		 * all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Alive failed.\n");
+		goto restart;
+	}
+
+	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "runtime" alive if code weren't properly loaded.  */
+	if (iwl4965_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
+		goto restart;
+	}
+
+	ret = iwl4965_alive_notify(priv);
+	if (ret) {
+		IWL_WARN(priv,
+			"Could not complete ALIVE transition [ntf]: %d\n", ret);
+		goto restart;
+	}
+
+
+	/* After the ALIVE response, we can send host commands to the uCode */
+	set_bit(STATUS_ALIVE, &priv->status);
+
+	/* Enable watchdog to monitor the driver tx queues */
+	iwl_legacy_setup_watchdog(priv);
+
+	if (iwl_legacy_is_rfkill(priv))
+		return;
+
+	ieee80211_wake_queues(priv->hw);
+
+	priv->active_rate = IWL_RATES_MASK;
+
+	if (iwl_legacy_is_associated_ctx(ctx)) {
+		struct iwl_legacy_rxon_cmd *active_rxon =
+				(struct iwl_legacy_rxon_cmd *)&ctx->active;
+		/* apply any changes in staging */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	} else {
+		struct iwl_rxon_context *tmp;
+		/* Initialize our rx_config data */
+		for_each_context(priv, tmp)
+			iwl_legacy_connection_init_rx_config(priv, tmp);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	/* Configure bluetooth coexistence if enabled */
+	iwl_legacy_send_bt_config(priv);
+
+	iwl4965_reset_run_time_calib(priv);
+
+	set_bit(STATUS_READY, &priv->status);
+
+	/* Configure the adapter for unassociated operation */
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	/* At this point, the NIC is initialized and operational */
+	iwl4965_rf_kill_ct_config(priv);
+
+	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
+	wake_up_interruptible(&priv->wait_command_queue);
+
+	iwl_legacy_power_update_mode(priv, true);
+	IWL_DEBUG_INFO(priv, "Updated power mode\n");
+
+	return;
+
+ restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
+
+static void __iwl4965_down(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+	 * to prevent rearm timer */
+	del_timer_sync(&priv->watchdog);
+
+	iwl_legacy_clear_ucode_stations(priv, NULL);
+	iwl_legacy_dealloc_bcast_stations(priv);
+	iwl_legacy_clear_driver_stations(priv);
+
+	/* Unblock any waiting calls */
+	wake_up_interruptible_all(&priv->wait_command_queue);
+
+	/* Wipe out the EXIT_PENDING status bit if we are not actually
+	 * exiting the module */
+	if (!exit_pending)
+		clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* stop and reset the on-board processor */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/* tell the device to stop sending interrupts */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	iwl4965_synchronize_irq(priv);
+
+	if (priv->mac80211_registered)
+		ieee80211_stop_queues(priv->hw);
+
+	/* If we have not previously called iwl_init() then
+	 * clear all bits but the RF Kill bit and return */
+	if (!iwl_legacy_is_init(priv)) {
+		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+					STATUS_RF_KILL_HW |
+			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+					STATUS_GEO_CONFIGURED |
+			       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+					STATUS_EXIT_PENDING;
+		goto exit;
+	}
+
+	/* ...otherwise clear out all the status bits but the RF Kill
+	 * bit and continue taking the NIC down. */
+	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+				STATUS_RF_KILL_HW |
+			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+				STATUS_GEO_CONFIGURED |
+			test_bit(STATUS_FW_ERROR, &priv->status) <<
+				STATUS_FW_ERROR |
+		       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+				STATUS_EXIT_PENDING;
+
+	iwl4965_txq_ctx_stop(priv);
+	iwl4965_rxq_stop(priv);
+
+	/* Power-down device's busmaster DMA clocks */
+	iwl_legacy_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+	udelay(5);
+
+	/* Make sure (redundant) we've released our request to stay awake */
+	iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+	/* Stop the device, and put it in low power state */
+	iwl_legacy_apm_stop(priv);
+
+ exit:
+	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+
+	dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
+
+	/* clear out any free frames */
+	iwl4965_clear_free_frames(priv);
+}
+
+static void iwl4965_down(struct iwl_priv *priv)
+{
+	mutex_lock(&priv->mutex);
+	__iwl4965_down(priv);
+	mutex_unlock(&priv->mutex);
+
+	iwl4965_cancel_deferred_work(priv);
+}
+
+#define HW_READY_TIMEOUT (50)
+
+static int iwl4965_set_hw_ready(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
+
+	/* See if we got it */
+	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+				CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
+				HW_READY_TIMEOUT);
+	if (ret != -ETIMEDOUT)
+		priv->hw_ready = true;
+	else
+		priv->hw_ready = false;
+
+	IWL_DEBUG_INFO(priv, "hardware %s\n",
+		      (priv->hw_ready == 1) ? "ready" : "not ready");
+	return ret;
+}
+
+static int iwl4965_prepare_card_hw(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	IWL_DEBUG_INFO(priv, "iwl4965_prepare_card_hw enter\n");
+
+	ret = iwl4965_set_hw_ready(priv);
+	if (priv->hw_ready)
+		return ret;
+
+	/* If HW is not ready, prepare the conditions to check again */
+	iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			CSR_HW_IF_CONFIG_REG_PREPARE);
+
+	ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+			~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
+			CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
+
+	/* HW should be ready by now, check again. */
+	if (ret != -ETIMEDOUT)
+		iwl4965_set_hw_ready(priv);
+
+	return ret;
+}
+
+#define MAX_HW_RESTARTS 5
+
+static int __iwl4965_up(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+	int i;
+	int ret;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
+		return -EIO;
+	}
+
+	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+		IWL_ERR(priv, "ucode not available for device bringup\n");
+		return -EIO;
+	}
+
+	for_each_context(priv, ctx) {
+		ret = iwl4965_alloc_bcast_station(priv, ctx);
+		if (ret) {
+			iwl_legacy_dealloc_bcast_stations(priv);
+			return ret;
+		}
+	}
+
+	iwl4965_prepare_card_hw(priv);
+
+	if (!priv->hw_ready) {
+		IWL_WARN(priv, "Exit HW not ready\n");
+		return -EIO;
+	}
+
+	/* If platform's RF_KILL switch is NOT set to KILL */
+	if (iwl_read32(priv,
+		CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	if (iwl_legacy_is_rfkill(priv)) {
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+
+		iwl_legacy_enable_interrupts(priv);
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+		return 0;
+	}
+
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+	/* must be initialised before iwl_hw_nic_init */
+	priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+
+	ret = iwl4965_hw_nic_init(priv);
+	if (ret) {
+		IWL_ERR(priv, "Unable to init nic\n");
+		return ret;
+	}
+
+	/* make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	/* clear (again), then enable host interrupts */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_legacy_enable_interrupts(priv);
+
+	/* really make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+	/* Copy original ucode data image from disk into backup cache.
+	 * This will be used to initialize the on-board processor's
+	 * data SRAM for a clean start when the runtime program first loads. */
+	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
+	       priv->ucode_data.len);
+
+	for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+		/* load bootstrap state machine,
+		 * load bootstrap program into processor's memory,
+		 * prepare to load the "initialize" uCode */
+		ret = priv->cfg->ops->lib->load_ucode(priv);
+
+		if (ret) {
+			IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
+				ret);
+			continue;
+		}
+
+		/* start card; "initialize" will load runtime ucode */
+		iwl4965_nic_start(priv);
+
+		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
+
+		return 0;
+	}
+
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+	__iwl4965_down(priv);
+	clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* tried to restart and config the device for as long as our
+	 * patience could withstand */
+	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
+	return -EIO;
+}
+
+
+/*****************************************************************************
+ *
+ * Workqueue callbacks
+ *
+ *****************************************************************************/
+
+static void iwl4965_bg_init_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, init_alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	priv->cfg->ops->lib->init_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_bg_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl4965_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_bg_run_time_calib_work(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+			run_time_calib_work);
+
+	mutex_lock(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status)) {
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	if (priv->start_calib) {
+		iwl4965_chain_noise_calibration(priv,
+				(void *)&priv->_4965.statistics);
+		iwl4965_sensitivity_calibration(priv,
+				(void *)&priv->_4965.statistics);
+	}
+
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_bg_restart(struct work_struct *data)
+{
+	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		struct iwl_rxon_context *ctx;
+
+		mutex_lock(&priv->mutex);
+		for_each_context(priv, ctx)
+			ctx->vif = NULL;
+		priv->is_open = 0;
+
+		__iwl4965_down(priv);
+
+		mutex_unlock(&priv->mutex);
+		iwl4965_cancel_deferred_work(priv);
+		ieee80211_restart_hw(priv->hw);
+	} else {
+		iwl4965_down(priv);
+
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			return;
+
+		mutex_lock(&priv->mutex);
+		__iwl4965_up(priv);
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+static void iwl4965_bg_rx_replenish(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, rx_replenish);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl4965_rx_replenish(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/*****************************************************************************
+ *
+ * mac80211 entry point functions
+ *
+ *****************************************************************************/
+
+#define UCODE_READY_TIMEOUT	(4 * HZ)
+
+/*
+ * Not a mac80211 entry point function, but it fits in with all the
+ * other mac80211 functions grouped here.
+ */
+static int iwl4965_mac_setup_register(struct iwl_priv *priv,
+				  u32 max_probe_length)
+{
+	int ret;
+	struct ieee80211_hw *hw = priv->hw;
+	struct iwl_rxon_context *ctx;
+
+	hw->rate_control_algorithm = "iwl-4965-rs";
+
+	/* Tell mac80211 our characteristics */
+	hw->flags = IEEE80211_HW_SIGNAL_DBM |
+		    IEEE80211_HW_AMPDU_AGGREGATION |
+		    IEEE80211_HW_NEED_DTIM_PERIOD |
+		    IEEE80211_HW_SPECTRUM_MGMT |
+		    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+
+	if (priv->cfg->sku & IWL_SKU_N)
+		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
+			     IEEE80211_HW_SUPPORTS_STATIC_SMPS;
+
+	hw->sta_data_size = sizeof(struct iwl_station_priv);
+	hw->vif_data_size = sizeof(struct iwl_vif_priv);
+
+	for_each_context(priv, ctx) {
+		hw->wiphy->interface_modes |= ctx->interface_modes;
+		hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
+	}
+
+	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
+			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
+
+	/*
+	 * For now, disable PS by default because it affects
+	 * RX performance significantly.
+	 */
+	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
+	/* we create the 802.11 header and a zero-length SSID element */
+	hw->wiphy->max_scan_ie_len = max_probe_length - 24 - 2;
+
+	/* Default value; 4 EDCA QOS priorities */
+	hw->queues = 4;
+
+	hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
+
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&priv->bands[IEEE80211_BAND_2GHZ];
+	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&priv->bands[IEEE80211_BAND_5GHZ];
+
+	iwl_legacy_leds_init(priv);
+
+	ret = ieee80211_register_hw(priv->hw);
+	if (ret) {
+		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
+		return ret;
+	}
+	priv->mac80211_registered = 1;
+
+	return 0;
+}
+
+
+int iwl4965_mac_start(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	/* we should be verifying the device is ready to be opened */
+	mutex_lock(&priv->mutex);
+	ret = __iwl4965_up(priv);
+	mutex_unlock(&priv->mutex);
+
+	if (ret)
+		return ret;
+
+	if (iwl_legacy_is_rfkill(priv))
+		goto out;
+
+	IWL_DEBUG_INFO(priv, "Start UP work done.\n");
+
+	/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
+	 * mac80211 will not be run successfully. */
+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+			test_bit(STATUS_READY, &priv->status),
+			UCODE_READY_TIMEOUT);
+	if (!ret) {
+		if (!test_bit(STATUS_READY, &priv->status)) {
+			IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
+				jiffies_to_msecs(UCODE_READY_TIMEOUT));
+			return -ETIMEDOUT;
+		}
+	}
+
+	iwl4965_led_enable(priv);
+
+out:
+	priv->is_open = 1;
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+}
+
+void iwl4965_mac_stop(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!priv->is_open)
+		return;
+
+	priv->is_open = 0;
+
+	iwl4965_down(priv);
+
+	flush_workqueue(priv->workqueue);
+
+	/* enable interrupts again in order to receive rfkill changes */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_legacy_enable_interrupts(priv);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+void iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MACDUMP(priv, "enter\n");
+
+	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+	if (iwl4965_tx_skb(priv, skb))
+		dev_kfree_skb_any(skb);
+
+	IWL_DEBUG_MACDUMP(priv, "leave\n");
+}
+
+void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	iwl4965_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
+			    iv32, phase1key);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	struct iwl_rxon_context *ctx = vif_priv->ctx;
+	int ret;
+	u8 sta_id;
+	bool is_default_wep_key = false;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (priv->cfg->mod_params->sw_crypto) {
+		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
+		return -EOPNOTSUPP;
+	}
+
+	sta_id = iwl_legacy_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return -EINVAL;
+
+	mutex_lock(&priv->mutex);
+	iwl_legacy_scan_cancel_timeout(priv, 100);
+
+	/*
+	 * If we are getting WEP group key and we didn't receive any key mapping
+	 * so far, we are in legacy wep mode (group key only), otherwise we are
+	 * in 1X mode.
+	 * In legacy wep mode, we use another host command to the uCode.
+	 */
+	if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+	    !sta) {
+		if (cmd == SET_KEY)
+			is_default_wep_key = !ctx->key_mapping_keys;
+		else
+			is_default_wep_key =
+					(key->hw_key_idx == HW_KEY_DEFAULT);
+	}
+
+	switch (cmd) {
+	case SET_KEY:
+		if (is_default_wep_key)
+			ret = iwl4965_set_default_wep_key(priv,
+							vif_priv->ctx, key);
+		else
+			ret = iwl4965_set_dynamic_key(priv, vif_priv->ctx,
+						  key, sta_id);
+
+		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
+		break;
+	case DISABLE_KEY:
+		if (is_default_wep_key)
+			ret = iwl4965_remove_default_wep_key(priv, ctx, key);
+		else
+			ret = iwl4965_remove_dynamic_key(priv, ctx,
+							key, sta_id);
+
+		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+	return ret;
+}
+
+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret = -EINVAL;
+
+	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
+		     sta->addr, tid);
+
+	if (!(priv->cfg->sku & IWL_SKU_N))
+		return -EACCES;
+
+	mutex_lock(&priv->mutex);
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		IWL_DEBUG_HT(priv, "start Rx\n");
+		ret = iwl4965_sta_rx_agg_start(priv, sta, tid, *ssn);
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		IWL_DEBUG_HT(priv, "stop Rx\n");
+		ret = iwl4965_sta_rx_agg_stop(priv, sta, tid);
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			ret = 0;
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		IWL_DEBUG_HT(priv, "start Tx\n");
+		ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
+		if (ret == 0) {
+			priv->_4965.agg_tids_count++;
+			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
+				     priv->_4965.agg_tids_count);
+		}
+		break;
+	case IEEE80211_AMPDU_TX_STOP:
+		IWL_DEBUG_HT(priv, "stop Tx\n");
+		ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
+		if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
+			priv->_4965.agg_tids_count--;
+			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
+				     priv->_4965.agg_tids_count);
+		}
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			ret = 0;
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		ret = 0;
+		break;
+	}
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+
+int iwl4965_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
+	int ret;
+	u8 sta_id;
+
+	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
+			sta->addr);
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+			sta->addr);
+	sta_priv->common.sta_id = IWL_INVALID_STATION;
+
+	atomic_set(&sta_priv->pending_frames, 0);
+
+	ret = iwl_legacy_add_station_common(priv, vif_priv->ctx, sta->addr,
+				     is_ap, sta, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
+			sta->addr, ret);
+		/* Should we return success if return code is EEXIST ? */
+		mutex_unlock(&priv->mutex);
+		return ret;
+	}
+
+	sta_priv->common.sta_id = sta_id;
+
+	/* Initialize rate scaling */
+	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
+		       sta->addr);
+	iwl4965_rs_rate_init(priv, sta, sta_id);
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+
+void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch)
+{
+	struct iwl_priv *priv = hw->priv;
+	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = ch_switch->channel;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	u16 ch;
+	unsigned long flags = 0;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (iwl_legacy_is_rfkill(priv))
+		goto out_exit;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status))
+		goto out_exit;
+
+	if (!iwl_legacy_is_associated_ctx(ctx))
+		goto out_exit;
+
+	/* channel switch in progress */
+	if (priv->switch_rxon.switch_in_progress == true)
+		goto out_exit;
+
+	mutex_lock(&priv->mutex);
+	if (priv->cfg->ops->lib->set_channel_switch) {
+
+		ch = channel->hw_value;
+		if (le16_to_cpu(ctx->active.channel) != ch) {
+			ch_info = iwl_legacy_get_channel_info(priv,
+						       channel->band,
+						       ch);
+			if (!iwl_legacy_is_channel_valid(ch_info)) {
+				IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+				goto out;
+			}
+			spin_lock_irqsave(&priv->lock, flags);
+
+			priv->current_ht_config.smps = conf->smps_mode;
+
+			/* Configure HT40 channels */
+			ctx->ht.enabled = conf_is_ht(conf);
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			if ((le16_to_cpu(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
+
+			iwl_legacy_set_rxon_channel(priv, channel, ctx);
+			iwl_legacy_set_rxon_ht(priv, ht_conf);
+			iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+			spin_unlock_irqrestore(&priv->lock, flags);
+
+			iwl_legacy_set_rate(priv);
+			/*
+			 * at this point, staging_rxon has the
+			 * configuration for channel switch
+			 */
+			if (priv->cfg->ops->lib->set_channel_switch(priv,
+								    ch_switch))
+				priv->switch_rxon.switch_in_progress = false;
+		}
+	}
+out:
+	mutex_unlock(&priv->mutex);
+out_exit:
+	if (!priv->switch_rxon.switch_in_progress)
+		ieee80211_chswitch_done(ctx->vif, false);
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+void iwl4965_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast)
+{
+	struct iwl_priv *priv = hw->priv;
+	__le32 filter_or = 0, filter_nand = 0;
+	struct iwl_rxon_context *ctx;
+
+#define CHK(test, flag)	do { \
+	if (*total_flags & (test))		\
+		filter_or |= (flag);		\
+	else					\
+		filter_nand |= (flag);		\
+	} while (0)
+
+	IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+			changed_flags, *total_flags);
+
+	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+	/* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
+	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
+	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+	mutex_lock(&priv->mutex);
+
+	for_each_context(priv, ctx) {
+		ctx->staging.filter_flags &= ~filter_nand;
+		ctx->staging.filter_flags |= filter_or;
+
+		/*
+		 * Not committing directly because hardware can perform a scan,
+		 * but we'll eventually commit the filter flags change anyway.
+		 */
+	}
+
+	mutex_unlock(&priv->mutex);
+
+	/*
+	 * Receiving all multicast frames is always enabled by the
+	 * default flags setup in iwl_legacy_connection_init_rx_config()
+	 * since we currently do not support programming multicast
+	 * filters into the device.
+	 */
+	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+/*****************************************************************************
+ *
+ * driver setup and teardown
+ *
+ *****************************************************************************/
+
+static void iwl4965_bg_txpower_work(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+			txpower_work);
+
+	/* If a scan happened to start before we got here
+	 * then just return; the statistics notification will
+	 * kick off another scheduled work to compensate for
+	 * any temperature delta we missed here. */
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+
+	/* Regardless of if we are associated, we must reconfigure the
+	 * TX power since frames can be sent on non-radar channels while
+	 * not associated */
+	priv->cfg->ops->lib->send_tx_power(priv);
+
+	/* Update last_temperature to keep is_calib_needed from running
+	 * when it isn't needed... */
+	priv->last_temperature = priv->temperature;
+
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
+{
+	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
+
+	init_waitqueue_head(&priv->wait_command_queue);
+
+	INIT_WORK(&priv->restart, iwl4965_bg_restart);
+	INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
+	INIT_WORK(&priv->run_time_calib_work, iwl4965_bg_run_time_calib_work);
+	INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
+	INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
+
+	iwl_legacy_setup_scan_deferred_work(priv);
+
+	INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
+
+	init_timer(&priv->statistics_periodic);
+	priv->statistics_periodic.data = (unsigned long)priv;
+	priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
+
+	init_timer(&priv->ucode_trace);
+	priv->ucode_trace.data = (unsigned long)priv;
+	priv->ucode_trace.function = iwl4965_bg_ucode_trace;
+
+	init_timer(&priv->watchdog);
+	priv->watchdog.data = (unsigned long)priv;
+	priv->watchdog.function = iwl_legacy_bg_watchdog;
+
+	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+		iwl4965_irq_tasklet, (unsigned long)priv);
+}
+
+static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
+{
+	cancel_work_sync(&priv->txpower_work);
+	cancel_delayed_work_sync(&priv->init_alive_start);
+	cancel_delayed_work(&priv->alive_start);
+	cancel_work_sync(&priv->run_time_calib_work);
+
+	iwl_legacy_cancel_scan_deferred_work(priv);
+
+	del_timer_sync(&priv->statistics_periodic);
+	del_timer_sync(&priv->ucode_trace);
+}
+
+static void iwl4965_init_hw_rates(struct iwl_priv *priv,
+			      struct ieee80211_rate *rates)
+{
+	int i;
+
+	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
+		rates[i].bitrate = iwlegacy_rates[i].ieee * 5;
+		rates[i].hw_value = i; /* Rate scaling will work on indexes */
+		rates[i].hw_value_short = i;
+		rates[i].flags = 0;
+		if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
+			/*
+			 * If CCK != 1M then set short preamble rate flag.
+			 */
+			rates[i].flags |=
+				(iwlegacy_rates[i].plcp == IWL_RATE_1M_PLCP) ?
+					0 : IEEE80211_RATE_SHORT_PREAMBLE;
+		}
+	}
+}
+/*
+ * Acquire priv->lock before calling this function !
+ */
+void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
+{
+	iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR,
+			     (index & 0xff) | (txq_id << 8));
+	iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
+}
+
+void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					int tx_fifo_id, int scd_retry)
+{
+	int txq_id = txq->q.id;
+
+	/* Find out whether to activate Tx queue */
+	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
+
+	/* Set up and activate */
+	iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
+			 (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+			 (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) |
+			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) |
+			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
+			 IWL49_SCD_QUEUE_STTS_REG_MSK);
+
+	txq->sched_retry = scd_retry;
+
+	IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
+		       active ? "Activate" : "Deactivate",
+		       scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
+}
+
+
+static int iwl4965_init_drv(struct iwl_priv *priv)
+{
+	int ret;
+
+	spin_lock_init(&priv->sta_lock);
+	spin_lock_init(&priv->hcmd_lock);
+
+	INIT_LIST_HEAD(&priv->free_frames);
+
+	mutex_init(&priv->mutex);
+	mutex_init(&priv->sync_cmd_mutex);
+
+	priv->ieee_channels = NULL;
+	priv->ieee_rates = NULL;
+	priv->band = IEEE80211_BAND_2GHZ;
+
+	priv->iw_mode = NL80211_IFTYPE_STATION;
+	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
+	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+	priv->_4965.agg_tids_count = 0;
+
+	/* initialize force reset */
+	priv->force_reset[IWL_RF_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_RF_RESET;
+	priv->force_reset[IWL_FW_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+	/* Choose which receivers/antennas to use */
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
+
+	iwl_legacy_init_scan_params(priv);
+
+	/* Set the tx_power_user_lmt to the lowest power level
+	 * this value will get overwritten by channel max power avg
+	 * from eeprom */
+	priv->tx_power_user_lmt = IWL4965_TX_POWER_TARGET_POWER_MIN;
+	priv->tx_power_next = IWL4965_TX_POWER_TARGET_POWER_MIN;
+
+	ret = iwl_legacy_init_channel_map(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = iwl_legacy_init_geos(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
+		goto err_free_channel_map;
+	}
+	iwl4965_init_hw_rates(priv, priv->ieee_rates);
+
+	return 0;
+
+err_free_channel_map:
+	iwl_legacy_free_channel_map(priv);
+err:
+	return ret;
+}
+
+static void iwl4965_uninit_drv(struct iwl_priv *priv)
+{
+	iwl4965_calib_free_results(priv);
+	iwl_legacy_free_geos(priv);
+	iwl_legacy_free_channel_map(priv);
+	kfree(priv->scan_cmd);
+}
+
+static void iwl4965_hw_detect(struct iwl_priv *priv)
+{
+	priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);
+	priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG);
+	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
+}
+
+static int iwl4965_set_hw_params(struct iwl_priv *priv)
+{
+	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
+	else
+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
+
+	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+
+	if (priv->cfg->mod_params->disable_11n)
+		priv->cfg->sku &= ~IWL_SKU_N;
+
+	/* Device-specific setup */
+	return priv->cfg->ops->lib->set_hw_params(priv);
+}
+
+static const u8 iwl4965_bss_ac_to_fifo[] = {
+	IWL_TX_FIFO_VO,
+	IWL_TX_FIFO_VI,
+	IWL_TX_FIFO_BE,
+	IWL_TX_FIFO_BK,
+};
+
+static const u8 iwl4965_bss_ac_to_queue[] = {
+	0, 1, 2, 3,
+};
+
+static int
+iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err = 0, i;
+	struct iwl_priv *priv;
+	struct ieee80211_hw *hw;
+	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	unsigned long flags;
+	u16 pci_cmd;
+
+	/************************
+	 * 1. Allocating HW data
+	 ************************/
+
+	hw = iwl_legacy_alloc_all(cfg);
+	if (!hw) {
+		err = -ENOMEM;
+		goto out;
+	}
+	priv = hw->priv;
+	/* At this point both hw and priv are allocated. */
+
+	/*
+	 * The default context is always valid,
+	 * more may be discovered when firmware
+	 * is loaded.
+	 */
+	priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+	for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+		priv->contexts[i].ctxid = i;
+
+	priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
+	priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+	priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+	priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+	priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwl4965_bss_ac_to_fifo;
+	priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwl4965_bss_ac_to_queue;
+	priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
+		BIT(NL80211_IFTYPE_ADHOC);
+	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+		BIT(NL80211_IFTYPE_STATION);
+	priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
+	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1);
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
+	priv->cfg = cfg;
+	priv->pci_dev = pdev;
+	priv->inta_mask = CSR_INI_SET_MASK;
+
+	if (iwl_legacy_alloc_traffic_mem(priv))
+		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
+
+	/**************************
+	 * 2. Initializing PCI bus
+	 **************************/
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				PCIE_LINK_STATE_CLKPM);
+
+	if (pci_enable_device(pdev)) {
+		err = -ENODEV;
+		goto out_ieee80211_free_hw;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (err) {
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (!err)
+			err = pci_set_consistent_dma_mask(pdev,
+							DMA_BIT_MASK(32));
+		/* both attempts failed: */
+		if (err) {
+			IWL_WARN(priv, "No suitable DMA available.\n");
+			goto out_pci_disable_device;
+		}
+	}
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err)
+		goto out_pci_disable_device;
+
+	pci_set_drvdata(pdev, priv);
+
+
+	/***********************
+	 * 3. Read REV register
+	 ***********************/
+	priv->hw_base = pci_iomap(pdev, 0, 0);
+	if (!priv->hw_base) {
+		err = -ENODEV;
+		goto out_pci_release_regions;
+	}
+
+	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
+		(unsigned long long) pci_resource_len(pdev, 0));
+	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
+
+	/* these spin locks will be used in apm_ops.init and EEPROM access
+	 * we should init now
+	 */
+	spin_lock_init(&priv->reg_lock);
+	spin_lock_init(&priv->lock);
+
+	/*
+	 * stop and reset the on-board processor just in case it is in a
+	 * strange state ... like being left stranded by a primary kernel
+	 * and this is now the kdump kernel trying to start up
+	 */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	iwl4965_hw_detect(priv);
+	IWL_INFO(priv, "Detected %s, REV=0x%X\n",
+		priv->cfg->name, priv->hw_rev);
+
+	/* We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+	iwl4965_prepare_card_hw(priv);
+	if (!priv->hw_ready) {
+		IWL_WARN(priv, "Failed, HW not ready\n");
+		goto out_iounmap;
+	}
+
+	/*****************
+	 * 4. Read EEPROM
+	 *****************/
+	/* Read the EEPROM */
+	err = iwl_legacy_eeprom_init(priv);
+	if (err) {
+		IWL_ERR(priv, "Unable to init EEPROM\n");
+		goto out_iounmap;
+	}
+	err = iwl4965_eeprom_check_version(priv);
+	if (err)
+		goto out_free_eeprom;
+
+	if (err)
+		goto out_free_eeprom;
+
+	/* extract MAC Address */
+	iwl4965_eeprom_get_mac(priv, priv->addresses[0].addr);
+	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
+	priv->hw->wiphy->addresses = priv->addresses;
+	priv->hw->wiphy->n_addresses = 1;
+
+	/************************
+	 * 5. Setup HW constants
+	 ************************/
+	if (iwl4965_set_hw_params(priv)) {
+		IWL_ERR(priv, "failed to set hw parameters\n");
+		goto out_free_eeprom;
+	}
+
+	/*******************
+	 * 6. Setup priv
+	 *******************/
+
+	err = iwl4965_init_drv(priv);
+	if (err)
+		goto out_free_eeprom;
+	/* At this point both hw and priv are initialized. */
+
+	/********************
+	 * 7. Setup services
+	 ********************/
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	pci_enable_msi(priv->pci_dev);
+
+	err = request_irq(priv->pci_dev->irq, iwl_legacy_isr,
+			  IRQF_SHARED, DRV_NAME, priv);
+	if (err) {
+		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
+		goto out_disable_msi;
+	}
+
+	iwl4965_setup_deferred_work(priv);
+	iwl4965_setup_rx_handlers(priv);
+
+	/*********************************************
+	 * 8. Enable interrupts and read RFKILL state
+	 *********************************************/
+
+	/* enable interrupts if needed: hw bug w/a */
+	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
+	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
+	}
+
+	iwl_legacy_enable_interrupts(priv);
+
+	/* If platform's RF_KILL switch is NOT set to KILL */
+	if (iwl_read32(priv, CSR_GP_CNTRL) &
+		CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
+
+	iwl_legacy_power_initialize(priv);
+
+	init_completion(&priv->_4965.firmware_loading_complete);
+
+	err = iwl4965_request_firmware(priv, true);
+	if (err)
+		goto out_destroy_workqueue;
+
+	return 0;
+
+ out_destroy_workqueue:
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	free_irq(priv->pci_dev->irq, priv);
+ out_disable_msi:
+	pci_disable_msi(priv->pci_dev);
+	iwl4965_uninit_drv(priv);
+ out_free_eeprom:
+	iwl_legacy_eeprom_free(priv);
+ out_iounmap:
+	pci_iounmap(pdev, priv->hw_base);
+ out_pci_release_regions:
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+ out_pci_disable_device:
+	pci_disable_device(pdev);
+ out_ieee80211_free_hw:
+	iwl_legacy_free_traffic_mem(priv);
+	ieee80211_free_hw(priv->hw);
+ out:
+	return err;
+}
+
+static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+{
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	if (!priv)
+		return;
+
+	wait_for_completion(&priv->_4965.firmware_loading_complete);
+
+	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
+
+	iwl_legacy_dbgfs_unregister(priv);
+	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+
+	/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
+	 * to be called and iwl4965_down since we are removing the device
+	 * we need to set STATUS_EXIT_PENDING bit.
+	 */
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	iwl_legacy_leds_exit(priv);
+
+	if (priv->mac80211_registered) {
+		ieee80211_unregister_hw(priv->hw);
+		priv->mac80211_registered = 0;
+	} else {
+		iwl4965_down(priv);
+	}
+
+	/*
+	 * Make sure device is reset to low power before unloading driver.
+	 * This may be redundant with iwl4965_down(), but there are paths to
+	 * run iwl4965_down() without calling apm_ops.stop(), and there are
+	 * paths to avoid running iwl4965_down() at all before leaving driver.
+	 * This (inexpensive) call *makes sure* device is reset.
+	 */
+	iwl_legacy_apm_stop(priv);
+
+	/* make sure we flush any pending irq or
+	 * tasklet for the driver
+	 */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl4965_synchronize_irq(priv);
+
+	iwl4965_dealloc_ucode_pci(priv);
+
+	if (priv->rxq.bd)
+		iwl4965_rx_queue_free(priv, &priv->rxq);
+	iwl4965_hw_txq_ctx_free(priv);
+
+	iwl_legacy_eeprom_free(priv);
+
+
+	/*netif_stop_queue(dev); */
+	flush_workqueue(priv->workqueue);
+
+	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
+	 * priv->workqueue... so we can't take down the workqueue
+	 * until now... */
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	iwl_legacy_free_traffic_mem(priv);
+
+	free_irq(priv->pci_dev->irq, priv);
+	pci_disable_msi(priv->pci_dev);
+	pci_iounmap(pdev, priv->hw_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+
+	iwl4965_uninit_drv(priv);
+
+	dev_kfree_skb(priv->beacon_skb);
+
+	ieee80211_free_hw(priv->hw);
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ * must be called under priv->lock and mac access
+ */
+void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
+{
+	iwl_legacy_write_prph(priv, IWL49_SCD_TXFACT, mask);
+}
+
+/*****************************************************************************
+ *
+ * driver and module entry point
+ *
+ *****************************************************************************/
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(iwl4965_hw_card_ids) = {
+#if defined(CONFIG_IWL4965_MODULE) || defined(CONFIG_IWL4965)
+	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_cfg)},
+	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_cfg)},
+#endif /* CONFIG_IWL4965 */
+
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
+
+static struct pci_driver iwl4965_driver = {
+	.name = DRV_NAME,
+	.id_table = iwl4965_hw_card_ids,
+	.probe = iwl4965_pci_probe,
+	.remove = __devexit_p(iwl4965_pci_remove),
+	.driver.pm = IWL_LEGACY_PM_OPS,
+};
+
+static int __init iwl4965_init(void)
+{
+
+	int ret;
+	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	pr_info(DRV_COPYRIGHT "\n");
+
+	ret = iwl4965_rate_control_register();
+	if (ret) {
+		pr_err("Unable to register rate control algorithm: %d\n", ret);
+		return ret;
+	}
+
+	ret = pci_register_driver(&iwl4965_driver);
+	if (ret) {
+		pr_err("Unable to initialize PCI module\n");
+		goto error_register;
+	}
+
+	return ret;
+
+error_register:
+	iwl4965_rate_control_unregister();
+	return ret;
+}
+
+static void __exit iwl4965_exit(void)
+{
+	pci_unregister_driver(&iwl4965_driver);
+	iwl4965_rate_control_unregister();
+}
+
+module_exit(iwl4965_exit);
+module_init(iwl4965_init);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+
+module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO);
+MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
+module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO);
+MODULE_PARM_DESC(queues_num, "number of hw queues.");
+module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO);
+MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
+module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K,
+		   int, S_IRUGO);
+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+module_param_named(fw_restart, iwl4965_mod_params.restart_fw, int, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ed42457..17d555f 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,14 +1,52 @@
-config IWLWIFI
-	tristate "Intel Wireless Wifi"
+config IWLAGN
+	tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) "
 	depends on PCI && MAC80211
 	select FW_LOADER
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_TRIGGERS
+	select MAC80211_LEDS
+	---help---
+	  Select to build the driver supporting the:
+
+	  Intel Wireless WiFi Link Next-Gen AGN
+
+	  This option enables support for use with the following hardware:
+		Intel Wireless WiFi Link 6250AGN Adapter
+		Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
+		Intel WiFi Link 1000BGN
+		Intel Wireless WiFi 5150AGN
+		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+		Intel 6005 Series Wi-Fi Adapters
+		Intel 6030 Series Wi-Fi Adapters
+		Intel Wireless WiFi Link 6150BGN 2 Adapter
+		Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
+		Intel 2000 Series Wi-Fi Adapters
+
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  In order to use this driver, you will need a microcode (uCode)
+	  image for it. You can obtain the microcode from:
+
+	          <http://intellinuxwireless.org/>.
+
+	  The microcode is typically installed in /lib/firmware. You can
+	  look in the hotplug script /etc/hotplug/firmware.agent to
+	  determine which directory FIRMWARE_DIR is set to when the script
+	  runs.
+
+	  If you want to compile the driver as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+	  module will be called iwlagn.
 
 menu "Debugging Options"
-	depends on IWLWIFI
+	depends on IWLAGN
 
 config IWLWIFI_DEBUG
-	bool "Enable full debugging output in iwlagn and iwl3945 drivers"
-	depends on IWLWIFI
+	bool "Enable full debugging output in the iwlagn driver"
+	depends on IWLAGN
 	---help---
 	  This option will enable debug tracing output for the iwlwifi drivers
 
@@ -33,7 +71,7 @@ config IWLWIFI_DEBUG
 
 config IWLWIFI_DEBUGFS
         bool "iwlagn debugfs support"
-        depends on IWLWIFI && MAC80211_DEBUGFS
+        depends on IWLAGN && MAC80211_DEBUGFS
         ---help---
 	  Enable creation of debugfs files for the iwlwifi drivers. This
 	  is a low-impact option that allows getting insight into the
@@ -41,13 +79,13 @@ config IWLWIFI_DEBUGFS
 
 config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
         bool "Experimental uCode support"
-        depends on IWLWIFI && IWLWIFI_DEBUG
+        depends on IWLAGN && IWLWIFI_DEBUG
         ---help---
 	  Enable use of experimental ucode for testing and debugging.
 
 config IWLWIFI_DEVICE_TRACING
 	bool "iwlwifi device access tracing"
-	depends on IWLWIFI
+	depends on IWLAGN
 	depends on EVENT_TRACING
 	help
 	  Say Y here to trace all commands, including TX frames and IO
@@ -64,73 +102,19 @@ config IWLWIFI_DEVICE_TRACING
 	  occur.
 endmenu
 
-config IWLAGN
-	tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
-	depends on IWLWIFI
-	---help---
-	  Select to build the driver supporting the:
-
-	  Intel Wireless WiFi Link Next-Gen AGN
-
-	  This driver uses the kernel's mac80211 subsystem.
-
-	  In order to use this driver, you will need a microcode (uCode)
-	  image for it. You can obtain the microcode from:
-
-	          <http://intellinuxwireless.org/>.
-
-	  The microcode is typically installed in /lib/firmware. You can
-	  look in the hotplug script /etc/hotplug/firmware.agent to
-	  determine which directory FIRMWARE_DIR is set to when the script
-	  runs.
-
-	  If you want to compile the driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
-	  module will be called iwlagn.
-
-
-config IWL4965
-	bool "Intel Wireless WiFi 4965AGN"
-	depends on IWLAGN
-	---help---
-	  This option enables support for Intel Wireless WiFi Link 4965AGN
-
-config IWL5000
-	bool "Intel Wireless-N/Advanced-N/Ultimate-N WiFi Link"
+config IWL_P2P
+	bool "iwlwifi experimental P2P support"
 	depends on IWLAGN
-	---help---
-	  This option enables support for use with the following hardware:
-		Intel Wireless WiFi Link 6250AGN Adapter
-		Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
-		Intel WiFi Link 1000BGN
-		Intel Wireless WiFi 5150AGN
-		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
-		Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B)
-		Intel WIreless WiFi Link 6050BGN Gen 2 Adapter
-		Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
-
-config IWL3945
-	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
-	depends on IWLWIFI
-	---help---
-	  Select to build the driver supporting the:
-
-	  Intel PRO/Wireless 3945ABG/BG Network Connection
-
-	  This driver uses the kernel's mac80211 subsystem.
-
-	  In order to use this driver, you will need a microcode (uCode)
-	  image for it. You can obtain the microcode from:
+	help
+	  This option enables experimental P2P support for some devices
+	  based on microcode support. Since P2P support is still under
+	  development, this option may even enable it for some devices
+	  now that turn out to not support it in the future due to
+	  microcode restrictions.
 
-	          <http://intellinuxwireless.org/>.
+	  To determine if your microcode supports the experimental P2P
+	  offered by this option, check if the driver advertises AP
+	  support when it is loaded.
 
-	  The microcode is typically installed in /lib/firmware. You can
-	  look in the hotplug script /etc/hotplug/firmware.agent to
-	  determine which directory FIRMWARE_DIR is set to when the script
-	  runs.
+	  Say Y only if you want to experiment with P2P.
 
-	  If you want to compile the driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
-	  module will be called iwl3945.
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 93380f9..9d6ee83 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -1,35 +1,23 @@
-obj-$(CONFIG_IWLWIFI)	+= iwlcore.o
-iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
-iwlcore-objs 		+= iwl-scan.o iwl-led.o
-iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
-iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
-iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
-iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
-
-# If 3945 is selected only, iwl-legacy.o will be added
-# to iwlcore-m above, but it needs to be built in.
-iwlcore-objs += $(iwlcore-m)
-
-CFLAGS_iwl-devtrace.o := -I$(src)
-
 # AGN
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-tx.o
-iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
+iwlagn-objs		+= iwl-agn-lib.o iwl-agn-calib.o
 iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
-iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
-iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
-iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
-iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
-iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
-iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
+iwlagn-objs 		+= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
+iwlagn-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
+iwlagn-objs 		+= iwl-scan.o iwl-led.o
+iwlagn-objs             += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
+iwlagn-objs             += iwl-5000.o
+iwlagn-objs             += iwl-6000.o
+iwlagn-objs             += iwl-1000.o
+iwlagn-objs             += iwl-2000.o
+
+iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
+iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
+iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
 
-# 3945
-obj-$(CONFIG_IWL3945)	+= iwl3945.o
-iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
-iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o
+CFLAGS_iwl-devtrace.o := -I$(src)
 
 ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index ba78bc8..27c5007 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -49,7 +49,7 @@
 #include "iwl-agn-debugfs.h"
 
 /* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 3
+#define IWL1000_UCODE_API_MAX 5
 #define IWL100_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
@@ -232,8 +232,6 @@ static struct iwl_lib_ops iwl1000_lib = {
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
new file mode 100644
index 0000000..d7b6126
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -0,0 +1,560 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008 - 2010 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-sta.h"
+#include "iwl-agn.h"
+#include "iwl-helpers.h"
+#include "iwl-agn-hw.h"
+#include "iwl-6000-hw.h"
+#include "iwl-agn-led.h"
+#include "iwl-agn-debugfs.h"
+
+/* Highest firmware API version supported */
+#define IWL2030_UCODE_API_MAX 5
+#define IWL2000_UCODE_API_MAX 5
+#define IWL200_UCODE_API_MAX 5
+
+/* Lowest firmware API version supported */
+#define IWL2030_UCODE_API_MIN 5
+#define IWL2000_UCODE_API_MIN 5
+#define IWL200_UCODE_API_MIN 5
+
+#define IWL2030_FW_PRE "iwlwifi-2030-"
+#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE #api ".ucode"
+#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api)
+
+#define IWL2000_FW_PRE "iwlwifi-2000-"
+#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE #api ".ucode"
+#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api)
+
+#define IWL200_FW_PRE "iwlwifi-200-"
+#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE #api ".ucode"
+#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api)
+
+static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
+{
+	/* want Celsius */
+	priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
+	priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+}
+
+/* NIC configuration for 2000 series */
+static void iwl2000_nic_config(struct iwl_priv *priv)
+{
+	u16 radio_cfg;
+
+	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+	/* write radio config values to register */
+	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+			EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+			EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+
+	/* set CSR_HW_CONFIG_REG for uCode use */
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+
+	if (priv->cfg->iq_invert)
+		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
+
+}
+
+static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
+	.min_nrg_cck = 97,
+	.max_nrg_cck = 0, /* not used, set to 0 */
+	.auto_corr_min_ofdm = 80,
+	.auto_corr_min_ofdm_mrc = 128,
+	.auto_corr_min_ofdm_x1 = 105,
+	.auto_corr_min_ofdm_mrc_x1 = 192,
+
+	.auto_corr_max_ofdm = 145,
+	.auto_corr_max_ofdm_mrc = 232,
+	.auto_corr_max_ofdm_x1 = 110,
+	.auto_corr_max_ofdm_mrc_x1 = 232,
+
+	.auto_corr_min_cck = 125,
+	.auto_corr_max_cck = 175,
+	.auto_corr_min_cck_mrc = 160,
+	.auto_corr_max_cck_mrc = 310,
+	.nrg_th_cck = 97,
+	.nrg_th_ofdm = 100,
+
+	.barker_corr_th_min = 190,
+	.barker_corr_th_min_mrc = 390,
+	.nrg_th_cca = 62,
+};
+
+static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
+{
+	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
+	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
+		priv->cfg->base_params->num_of_queues =
+			priv->cfg->mod_params->num_of_queues;
+
+	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
+	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
+	priv->hw_params.scd_bc_tbls_size =
+		priv->cfg->base_params->num_of_queues *
+		sizeof(struct iwlagn_scd_bc_tbl);
+	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
+	priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
+
+	priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
+	priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
+
+	priv->hw_params.max_bsm_size = 0;
+	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
+					BIT(IEEE80211_BAND_5GHZ);
+	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
+	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+	if (priv->cfg->rx_with_siso_diversity)
+		priv->hw_params.rx_chains_num = 1;
+	else
+		priv->hw_params.rx_chains_num =
+			num_of_ant(priv->cfg->valid_rx_ant);
+	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
+	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+
+	iwl2000_set_ct_threshold(priv);
+
+	/* Set initial sensitivity parameters */
+	/* Set initial calibration set */
+	priv->hw_params.sens = &iwl2000_sensitivity;
+	priv->hw_params.calib_init_cfg =
+		BIT(IWL_CALIB_XTAL)             |
+		BIT(IWL_CALIB_LO)               |
+		BIT(IWL_CALIB_TX_IQ)            |
+		BIT(IWL_CALIB_BASE_BAND);
+	if (priv->cfg->need_dc_calib)
+		priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+	if (priv->cfg->need_temp_offset_calib)
+		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
+
+	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
+
+	return 0;
+}
+
+static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
+                                    struct ieee80211_channel_switch *ch_switch)
+{
+	/*
+	 * MULTI-FIXME
+	 * See iwl_mac_channel_switch.
+	 */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl6000_channel_switch_cmd cmd;
+	const struct iwl_channel_info *ch_info;
+	u32 switch_time_in_usec, ucode_switch_time;
+	u16 ch;
+	u32 tsf_low;
+	u8 switch_count;
+	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+	struct ieee80211_vif *vif = ctx->vif;
+	struct iwl_host_cmd hcmd = {
+		.id = REPLY_CHANNEL_SWITCH,
+		.len = sizeof(cmd),
+		.flags = CMD_SYNC,
+		.data = &cmd,
+	};
+
+	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+	ch = ch_switch->channel->hw_value;
+	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
+		ctx->active.channel, ch);
+	cmd.channel = cpu_to_le16(ch);
+	cmd.rxon_flags = ctx->staging.flags;
+	cmd.rxon_filter_flags = ctx->staging.filter_flags;
+	switch_count = ch_switch->count;
+	tsf_low = ch_switch->timestamp & 0x0ffffffff;
+	/*
+	 * calculate the ucode channel switch time
+	 * adding TSF as one of the factor for when to switch
+	 */
+	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
+		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
+		    beacon_interval)) {
+			switch_count -= (priv->ucode_beacon_time -
+				tsf_low) / beacon_interval;
+		} else
+			switch_count = 0;
+	}
+	if (switch_count <= 1)
+		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+	else {
+		switch_time_in_usec =
+			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+		ucode_switch_time = iwl_usecs_to_beacons(priv,
+						switch_time_in_usec,
+						beacon_interval);
+		cmd.switch_time = iwl_add_beacon_time(priv,
+						priv->ucode_beacon_time,
+						ucode_switch_time,
+						beacon_interval);
+	}
+	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
+		      cmd.switch_time);
+	ch_info = iwl_get_channel_info(priv, priv->band, ch);
+	if (ch_info)
+		cmd.expect_beacon = is_channel_radar(ch_info);
+	else {
+		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
+			ctx->active.channel, ch);
+		return -EFAULT;
+	}
+	priv->switch_rxon.channel = cmd.channel;
+	priv->switch_rxon.switch_in_progress = true;
+
+	return iwl_send_cmd_sync(priv, &hcmd);
+}
+
+static struct iwl_lib_ops iwl2000_lib = {
+	.set_hw_params = iwl2000_hw_set_hw_params,
+	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
+	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
+	.txq_set_sched = iwlagn_txq_set_sched,
+	.txq_agg_enable = iwlagn_txq_agg_enable,
+	.txq_agg_disable = iwlagn_txq_agg_disable,
+	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
+	.txq_free_tfd = iwl_hw_txq_free_tfd,
+	.txq_init = iwl_hw_tx_queue_init,
+	.rx_handler_setup = iwlagn_rx_handler_setup,
+	.setup_deferred_work = iwlagn_bt_setup_deferred_work,
+	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
+	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
+	.load_ucode = iwlagn_load_ucode,
+	.dump_nic_event_log = iwl_dump_nic_event_log,
+	.dump_nic_error_log = iwl_dump_nic_error_log,
+	.dump_csr = iwl_dump_csr,
+	.dump_fh = iwl_dump_fh,
+	.init_alive_start = iwlagn_init_alive_start,
+	.alive_notify = iwlagn_alive_notify,
+	.send_tx_power = iwlagn_send_tx_power,
+	.update_chain_flags = iwl_update_chain_flags,
+	.set_channel_switch = iwl2030_hw_channel_switch,
+	.apm_ops = {
+		.init = iwl_apm_init,
+		.config = iwl2000_nic_config,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REG_BAND_1_CHANNELS,
+			EEPROM_REG_BAND_2_CHANNELS,
+			EEPROM_REG_BAND_3_CHANNELS,
+			EEPROM_REG_BAND_4_CHANNELS,
+			EEPROM_REG_BAND_5_CHANNELS,
+			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_REG_BAND_52_HT40_CHANNELS
+		},
+		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+		.release_semaphore = iwlcore_eeprom_release_semaphore,
+		.calib_version  = iwlagn_eeprom_calib_version,
+		.query_addr = iwlagn_eeprom_query_addr,
+		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+	},
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
+	.temp_ops = {
+		.temperature = iwlagn_temperature,
+	},
+	.debugfs_ops = {
+		.rx_stats_read = iwl_ucode_rx_stats_read,
+		.tx_stats_read = iwl_ucode_tx_stats_read,
+		.general_stats_read = iwl_ucode_general_stats_read,
+		.bt_stats_read = iwl_ucode_bt_stats_read,
+		.reply_tx_error = iwl_reply_tx_error_read,
+	},
+	.txfifo_flush = iwlagn_txfifo_flush,
+	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.tt_ops = {
+		.lower_power_detection = iwl_tt_is_low_power_state,
+		.tt_power_mode = iwl_tt_current_power_mode,
+		.ct_kill_check = iwl_check_for_ct_kill,
+	}
+};
+
+static const struct iwl_ops iwl2000_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static const struct iwl_ops iwl2030_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_bt_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static const struct iwl_ops iwl200_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static const struct iwl_ops iwl230_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_bt_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static struct iwl_base_params iwl2000_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
+	.shadow_ram_support = true,
+	.led_compensation = 51,
+	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+	.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,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
+};
+
+
+static struct iwl_base_params iwl2030_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
+	.shadow_ram_support = true,
+	.led_compensation = 57,
+	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+	.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,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
+};
+
+static struct iwl_ht_params iwl2000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+static struct iwl_bt_params iwl2030_bt_params = {
+	.bt_statistics = true,
+	/* 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,
+	.bt_session_2 = true,
+};
+
+#define IWL_DEVICE_2000						\
+	.fw_name_pre = IWL2000_FW_PRE,				\
+	.ucode_api_max = IWL2000_UCODE_API_MAX,			\
+	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl2000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2000_base_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.iq_invert = true					\
+
+struct iwl_cfg iwl2000_2bgn_cfg = {
+	.name = "2000 Series 2x2 BGN",
+	IWL_DEVICE_2000,
+	.ht_params = &iwl2000_ht_params,
+};
+
+struct iwl_cfg iwl2000_2bg_cfg = {
+	.name = "2000 Series 2x2 BG",
+	IWL_DEVICE_2000,
+};
+
+#define IWL_DEVICE_2030						\
+	.fw_name_pre = IWL2030_FW_PRE,				\
+	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
+	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl2030_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.iq_invert = true					\
+
+struct iwl_cfg iwl2030_2bgn_cfg = {
+	.name = "2000 Series 2x2 BGN/BT",
+	IWL_DEVICE_2030,
+	.ht_params = &iwl2000_ht_params,
+};
+
+struct iwl_cfg iwl2030_2bg_cfg = {
+	.name = "2000 Series 2x2 BG/BT",
+	IWL_DEVICE_2030,
+};
+
+#define IWL_DEVICE_6035						\
+	.fw_name_pre = IWL2030_FW_PRE,				\
+	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
+	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_6035_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6035_TX_POWER_VERSION,	\
+	.ops = &iwl2030_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true						\
+
+struct iwl_cfg iwl6035_2agn_cfg = {
+	.name = "2000 Series 2x2 AGN/BT",
+	IWL_DEVICE_6035,
+	.ht_params = &iwl2000_ht_params,
+};
+
+struct iwl_cfg iwl6035_2abg_cfg = {
+	.name = "2000 Series 2x2 ABG/BT",
+	IWL_DEVICE_6035,
+};
+
+struct iwl_cfg iwl6035_2bg_cfg = {
+	.name = "2000 Series 2x2 BG/BT",
+	IWL_DEVICE_6035,
+};
+
+#define IWL_DEVICE_200						\
+	.fw_name_pre = IWL200_FW_PRE,				\
+	.ucode_api_max = IWL200_UCODE_API_MAX,			\
+	.ucode_api_min = IWL200_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl200_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2000_base_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.rx_with_siso_diversity = true				\
+
+struct iwl_cfg iwl200_bg_cfg = {
+	.name = "200 Series 1x1 BG",
+	IWL_DEVICE_200,
+};
+
+struct iwl_cfg iwl200_bgn_cfg = {
+	.name = "200 Series 1x1 BGN",
+	IWL_DEVICE_200,
+	.ht_params = &iwl2000_ht_params,
+};
+
+#define IWL_DEVICE_230						\
+	.fw_name_pre = IWL200_FW_PRE,				\
+	.ucode_api_max = IWL200_UCODE_API_MAX,			\
+	.ucode_api_min = IWL200_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl230_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.rx_with_siso_diversity = true				\
+
+struct iwl_cfg iwl230_bg_cfg = {
+	.name = "200 Series 1x1 BG/BT",
+	IWL_DEVICE_230,
+};
+
+struct iwl_cfg iwl230_bgn_cfg = {
+	.name = "200 Series 1x1 BGN/BT",
+	IWL_DEVICE_230,
+	.ht_params = &iwl2000_ht_params,
+};
+
+MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL200_MODULE_FIRMWARE(IWL200_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
deleted file mode 100644
index ef0835b..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-3945-debugfs.h"
-
-
-static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
-{
-	int p = 0;
-
-	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
-		       le32_to_cpu(priv->_3945.statistics.flag));
-	if (le32_to_cpu(priv->_3945.statistics.flag) &
-			UCODE_STATISTICS_CLEAR_MSK)
-		p += scnprintf(buf + p, bufsz - p,
-			       "\tStatistics have been cleared\n");
-	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
-		       (le32_to_cpu(priv->_3945.statistics.flag) &
-			UCODE_STATISTICS_FREQUENCY_MSK)
-			? "2.4 GHz" : "5.2 GHz");
-	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
-		       (le32_to_cpu(priv->_3945.statistics.flag) &
-			UCODE_STATISTICS_NARROW_BAND_MSK)
-			? "enabled" : "disabled");
-	return p;
-}
-
-ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
-				    char __user *user_buf,
-				    size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char *buf;
-	int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
-		    sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
-	ssize_t ret;
-	struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
-	struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
-	struct iwl39_statistics_rx_non_phy *general, *accum_general;
-	struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf) {
-		IWL_ERR(priv, "Can not allocate Buffer\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The statistic information display here is based on
-	 * the last statistics notification from uCode
-	 * might not reflect the current uCode activity
-	 */
-	ofdm = &priv->_3945.statistics.rx.ofdm;
-	cck = &priv->_3945.statistics.rx.cck;
-	general = &priv->_3945.statistics.rx.general;
-	accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
-	accum_cck = &priv->_3945.accum_statistics.rx.cck;
-	accum_general = &priv->_3945.accum_statistics.rx.general;
-	delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
-	delta_cck = &priv->_3945.delta_statistics.rx.cck;
-	delta_general = &priv->_3945.delta_statistics.rx.general;
-	max_ofdm = &priv->_3945.max_delta.rx.ofdm;
-	max_cck = &priv->_3945.max_delta.rx.cck;
-	max_general = &priv->_3945.max_delta.rx.general;
-
-	pos += iwl3945_statistics_flag(priv, buf, bufsz);
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - OFDM:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
-			 accum_ofdm->ina_cnt,
-			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_cnt:",
-			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
-			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
-			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
-			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:",
-			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
-			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
-			 le32_to_cpu(ofdm->overrun_err),
-			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
-			 max_ofdm->overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
-			 le32_to_cpu(ofdm->early_overrun_err),
-			 accum_ofdm->early_overrun_err,
-			 delta_ofdm->early_overrun_err,
-			 max_ofdm->early_overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:", le32_to_cpu(ofdm->crc32_good),
-			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
-			 max_ofdm->crc32_good);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
-			 le32_to_cpu(ofdm->false_alarm_cnt),
-			 accum_ofdm->false_alarm_cnt,
-			 delta_ofdm->false_alarm_cnt,
-			 max_ofdm->false_alarm_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_sync_err_cnt:",
-			 le32_to_cpu(ofdm->fina_sync_err_cnt),
-			 accum_ofdm->fina_sync_err_cnt,
-			 delta_ofdm->fina_sync_err_cnt,
-			 max_ofdm->fina_sync_err_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sfd_timeout:",
-			 le32_to_cpu(ofdm->sfd_timeout),
-			 accum_ofdm->sfd_timeout,
-			 delta_ofdm->sfd_timeout,
-			 max_ofdm->sfd_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_timeout:",
-			 le32_to_cpu(ofdm->fina_timeout),
-			 accum_ofdm->fina_timeout,
-			 delta_ofdm->fina_timeout,
-			 max_ofdm->fina_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unresponded_rts:",
-			 le32_to_cpu(ofdm->unresponded_rts),
-			 accum_ofdm->unresponded_rts,
-			 delta_ofdm->unresponded_rts,
-			 max_ofdm->unresponded_rts);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rxe_frame_lmt_ovrun:",
-			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
-			 accum_ofdm->rxe_frame_limit_overrun,
-			 delta_ofdm->rxe_frame_limit_overrun,
-			 max_ofdm->rxe_frame_limit_overrun);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_ack_cnt:",
-			 le32_to_cpu(ofdm->sent_ack_cnt),
-			 accum_ofdm->sent_ack_cnt,
-			 delta_ofdm->sent_ack_cnt,
-			 max_ofdm->sent_ack_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_cts_cnt:",
-			 le32_to_cpu(ofdm->sent_cts_cnt),
-			 accum_ofdm->sent_cts_cnt,
-			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
-
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - CCK:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ina_cnt:",
-			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
-			 delta_cck->ina_cnt, max_cck->ina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_cnt:",
-			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
-			 delta_cck->fina_cnt, max_cck->fina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "plcp_err:",
-			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
-			 delta_cck->plcp_err, max_cck->plcp_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_err:",
-			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
-			 delta_cck->crc32_err, max_cck->crc32_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "overrun_err:",
-			 le32_to_cpu(cck->overrun_err),
-			 accum_cck->overrun_err,
-			 delta_cck->overrun_err, max_cck->overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
-			 le32_to_cpu(cck->early_overrun_err),
-			 accum_cck->early_overrun_err,
-			 delta_cck->early_overrun_err,
-			 max_cck->early_overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:",
-			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
-			 delta_cck->crc32_good,
-			 max_cck->crc32_good);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "false_alarm_cnt:",
-			 le32_to_cpu(cck->false_alarm_cnt),
-			 accum_cck->false_alarm_cnt,
-			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_sync_err_cnt:",
-			 le32_to_cpu(cck->fina_sync_err_cnt),
-			 accum_cck->fina_sync_err_cnt,
-			 delta_cck->fina_sync_err_cnt,
-			 max_cck->fina_sync_err_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sfd_timeout:",
-			 le32_to_cpu(cck->sfd_timeout),
-			 accum_cck->sfd_timeout,
-			 delta_cck->sfd_timeout, max_cck->sfd_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_timeout:",
-			 le32_to_cpu(cck->fina_timeout),
-			 accum_cck->fina_timeout,
-			 delta_cck->fina_timeout, max_cck->fina_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unresponded_rts:",
-			 le32_to_cpu(cck->unresponded_rts),
-			 accum_cck->unresponded_rts,
-			 delta_cck->unresponded_rts,
-			 max_cck->unresponded_rts);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rxe_frame_lmt_ovrun:",
-			 le32_to_cpu(cck->rxe_frame_limit_overrun),
-			 accum_cck->rxe_frame_limit_overrun,
-			 delta_cck->rxe_frame_limit_overrun,
-			 max_cck->rxe_frame_limit_overrun);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_ack_cnt:",
-			 le32_to_cpu(cck->sent_ack_cnt),
-			 accum_cck->sent_ack_cnt,
-			 delta_cck->sent_ack_cnt,
-			 max_cck->sent_ack_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_cts_cnt:",
-			 le32_to_cpu(cck->sent_cts_cnt),
-			 accum_cck->sent_cts_cnt,
-			 delta_cck->sent_cts_cnt,
-			 max_cck->sent_cts_cnt);
-
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - GENERAL:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bogus_cts:",
-			 le32_to_cpu(general->bogus_cts),
-			 accum_general->bogus_cts,
-			 delta_general->bogus_cts, max_general->bogus_cts);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bogus_ack:",
-			 le32_to_cpu(general->bogus_ack),
-			 accum_general->bogus_ack,
-			 delta_general->bogus_ack, max_general->bogus_ack);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "non_bssid_frames:",
-			 le32_to_cpu(general->non_bssid_frames),
-			 accum_general->non_bssid_frames,
-			 delta_general->non_bssid_frames,
-			 max_general->non_bssid_frames);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "filtered_frames:",
-			 le32_to_cpu(general->filtered_frames),
-			 accum_general->filtered_frames,
-			 delta_general->filtered_frames,
-			 max_general->filtered_frames);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "non_channel_beacons:",
-			 le32_to_cpu(general->non_channel_beacons),
-			 accum_general->non_channel_beacons,
-			 delta_general->non_channel_beacons,
-			 max_general->non_channel_beacons);
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-	kfree(buf);
-	return ret;
-}
-
-ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
-				    char __user *user_buf,
-				    size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char *buf;
-	int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
-	ssize_t ret;
-	struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf) {
-		IWL_ERR(priv, "Can not allocate Buffer\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The statistic information display here is based on
-	 * the last statistics notification from uCode
-	 * might not reflect the current uCode activity
-	 */
-	tx = &priv->_3945.statistics.tx;
-	accum_tx = &priv->_3945.accum_statistics.tx;
-	delta_tx = &priv->_3945.delta_statistics.tx;
-	max_tx = &priv->_3945.max_delta.tx;
-	pos += iwl3945_statistics_flag(priv, buf, bufsz);
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Tx:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "preamble:",
-			 le32_to_cpu(tx->preamble_cnt),
-			 accum_tx->preamble_cnt,
-			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rx_detected_cnt:",
-			 le32_to_cpu(tx->rx_detected_cnt),
-			 accum_tx->rx_detected_cnt,
-			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bt_prio_defer_cnt:",
-			 le32_to_cpu(tx->bt_prio_defer_cnt),
-			 accum_tx->bt_prio_defer_cnt,
-			 delta_tx->bt_prio_defer_cnt,
-			 max_tx->bt_prio_defer_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bt_prio_kill_cnt:",
-			 le32_to_cpu(tx->bt_prio_kill_cnt),
-			 accum_tx->bt_prio_kill_cnt,
-			 delta_tx->bt_prio_kill_cnt,
-			 max_tx->bt_prio_kill_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "few_bytes_cnt:",
-			 le32_to_cpu(tx->few_bytes_cnt),
-			 accum_tx->few_bytes_cnt,
-			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "cts_timeout:",
-			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
-			 delta_tx->cts_timeout, max_tx->cts_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ack_timeout:",
-			 le32_to_cpu(tx->ack_timeout),
-			 accum_tx->ack_timeout,
-			 delta_tx->ack_timeout, max_tx->ack_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "expected_ack_cnt:",
-			 le32_to_cpu(tx->expected_ack_cnt),
-			 accum_tx->expected_ack_cnt,
-			 delta_tx->expected_ack_cnt,
-			 max_tx->expected_ack_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "actual_ack_cnt:",
-			 le32_to_cpu(tx->actual_ack_cnt),
-			 accum_tx->actual_ack_cnt,
-			 delta_tx->actual_ack_cnt,
-			 max_tx->actual_ack_cnt);
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-	kfree(buf);
-	return ret;
-}
-
-ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-					 char __user *user_buf,
-					 size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char *buf;
-	int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
-	ssize_t ret;
-	struct iwl39_statistics_general *general, *accum_general;
-	struct iwl39_statistics_general *delta_general, *max_general;
-	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
-	struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf) {
-		IWL_ERR(priv, "Can not allocate Buffer\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The statistic information display here is based on
-	 * the last statistics notification from uCode
-	 * might not reflect the current uCode activity
-	 */
-	general = &priv->_3945.statistics.general;
-	dbg = &priv->_3945.statistics.general.dbg;
-	div = &priv->_3945.statistics.general.div;
-	accum_general = &priv->_3945.accum_statistics.general;
-	delta_general = &priv->_3945.delta_statistics.general;
-	max_general = &priv->_3945.max_delta.general;
-	accum_dbg = &priv->_3945.accum_statistics.general.dbg;
-	delta_dbg = &priv->_3945.delta_statistics.general.dbg;
-	max_dbg = &priv->_3945.max_delta.general.dbg;
-	accum_div = &priv->_3945.accum_statistics.general.div;
-	delta_div = &priv->_3945.delta_statistics.general.div;
-	max_div = &priv->_3945.max_delta.general.div;
-	pos += iwl3945_statistics_flag(priv, buf, bufsz);
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_General:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "burst_check:",
-			 le32_to_cpu(dbg->burst_check),
-			 accum_dbg->burst_check,
-			 delta_dbg->burst_check, max_dbg->burst_check);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "burst_count:",
-			 le32_to_cpu(dbg->burst_count),
-			 accum_dbg->burst_count,
-			 delta_dbg->burst_count, max_dbg->burst_count);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sleep_time:",
-			 le32_to_cpu(general->sleep_time),
-			 accum_general->sleep_time,
-			 delta_general->sleep_time, max_general->sleep_time);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "slots_out:",
-			 le32_to_cpu(general->slots_out),
-			 accum_general->slots_out,
-			 delta_general->slots_out, max_general->slots_out);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "slots_idle:",
-			 le32_to_cpu(general->slots_idle),
-			 accum_general->slots_idle,
-			 delta_general->slots_idle, max_general->slots_idle);
-	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
-			 le32_to_cpu(general->ttl_timestamp));
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "tx_on_a:",
-			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
-			 delta_div->tx_on_a, max_div->tx_on_a);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "tx_on_b:",
-			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
-			 delta_div->tx_on_b, max_div->tx_on_b);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "exec_time:",
-			 le32_to_cpu(div->exec_time), accum_div->exec_time,
-			 delta_div->exec_time, max_div->exec_time);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "probe_time:",
-			 le32_to_cpu(div->probe_time), accum_div->probe_time,
-			 delta_div->probe_time, max_div->probe_time);
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-	kfree(buf);
-	return ret;
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
deleted file mode 100644
index 70809c5..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos);
-ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos);
-ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-					 char __user *user_buf, size_t count,
-					 loff_t *ppos);
-#else
-static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
-					   char __user *user_buf, size_t count,
-					   loff_t *ppos)
-{
-	return 0;
-}
-static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
-					   char __user *user_buf, size_t count,
-					   loff_t *ppos)
-{
-	return 0;
-}
-static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-						char __user *user_buf,
-						size_t count, loff_t *ppos)
-{
-	return 0;
-}
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
deleted file mode 100644
index 2c9ed2b..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
+++ /dev/null
@@ -1,188 +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) 2005 - 2010 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 - 2010 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_3945_fh_h__
-#define __iwl_3945_fh_h__
-
-/************************************/
-/* iwl3945 Flow Handler Definitions */
-/************************************/
-
-/**
- * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
- * Addresses are offsets from device's PCI hardware base address.
- */
-#define FH39_MEM_LOWER_BOUND                   (0x0800)
-#define FH39_MEM_UPPER_BOUND                   (0x1000)
-
-#define FH39_CBCC_TABLE		(FH39_MEM_LOWER_BOUND + 0x140)
-#define FH39_TFDB_TABLE		(FH39_MEM_LOWER_BOUND + 0x180)
-#define FH39_RCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x400)
-#define FH39_RSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x4c0)
-#define FH39_TCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x500)
-#define FH39_TSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x680)
-
-/* TFDB (Transmit Frame Buffer Descriptor) */
-#define FH39_TFDB(_ch, buf)			(FH39_TFDB_TABLE + \
-						 ((_ch) * 2 + (buf)) * 0x28)
-#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)	(FH39_TFDB_TABLE + 0x50 * (_ch))
-
-/* CBCC channel is [0,2] */
-#define FH39_CBCC(_ch)		(FH39_CBCC_TABLE + (_ch) * 0x8)
-#define FH39_CBCC_CTRL(_ch)	(FH39_CBCC(_ch) + 0x00)
-#define FH39_CBCC_BASE(_ch)	(FH39_CBCC(_ch) + 0x04)
-
-/* RCSR channel is [0,2] */
-#define FH39_RCSR(_ch)			(FH39_RCSR_TABLE + (_ch) * 0x40)
-#define FH39_RCSR_CONFIG(_ch)		(FH39_RCSR(_ch) + 0x00)
-#define FH39_RCSR_RBD_BASE(_ch)		(FH39_RCSR(_ch) + 0x04)
-#define FH39_RCSR_WPTR(_ch)		(FH39_RCSR(_ch) + 0x20)
-#define FH39_RCSR_RPTR_ADDR(_ch)	(FH39_RCSR(_ch) + 0x24)
-
-#define FH39_RSCSR_CHNL0_WPTR		(FH39_RCSR_WPTR(0))
-
-/* RSSR */
-#define FH39_RSSR_CTRL			(FH39_RSSR_TABLE + 0x000)
-#define FH39_RSSR_STATUS		(FH39_RSSR_TABLE + 0x004)
-
-/* TCSR */
-#define FH39_TCSR(_ch)			(FH39_TCSR_TABLE + (_ch) * 0x20)
-#define FH39_TCSR_CONFIG(_ch)		(FH39_TCSR(_ch) + 0x00)
-#define FH39_TCSR_CREDIT(_ch)		(FH39_TCSR(_ch) + 0x04)
-#define FH39_TCSR_BUFF_STTS(_ch)	(FH39_TCSR(_ch) + 0x08)
-
-/* TSSR */
-#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TABLE + 0x000)
-#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TABLE + 0x008)
-#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TABLE + 0x010)
-
-
-/* DBM */
-
-#define FH39_SRVC_CHNL                            (6)
-
-#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
-#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
-
-#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128		(0x01000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST		(0x00001000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH			(0x00000000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER		(0x00000001)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL	(0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL	(0x00000008)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD		(0x00200000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT		(0x00000000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE		(0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE		(0x80000000)
-
-#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID		(0x00004000)
-
-#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR		(0x00000001)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON	(0xFF000000)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON	(0x00FF0000)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B	(0x00000400)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON		(0x00000100)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON		(0x00000080)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH	(0x00000020)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH		(0x00000005)
-
-#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)	(BIT(_ch) << 24)
-#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)	(BIT(_ch) << 16)
-
-#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
-	(FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
-	 FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
-
-#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE			(0x01000000)
-
-struct iwl3945_tfd_tb {
-	__le32 addr;
-	__le32 len;
-} __packed;
-
-struct iwl3945_tfd {
-	__le32 control_flags;
-	struct iwl3945_tfd_tb tbs[4];
-	u8 __pad[28];
-} __packed;
-
-
-#endif /* __iwl_3945_fh_h__ */
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
deleted file mode 100644
index 65b5834..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ /dev/null
@@ -1,294 +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) 2005 - 2010 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 - 2010 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.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
- * Please use iwl-commands.h for uCode API definitions.
- * Please use iwl-3945.h for driver implementation definitions.
- */
-
-#ifndef __iwl_3945_hw__
-#define __iwl_3945_hw__
-
-#include "iwl-eeprom.h"
-
-/* RSSI to dBm */
-#define IWL39_RSSI_OFFSET	95
-
-#define IWL_DEFAULT_TX_POWER	0x0F
-
-/*
- * EEPROM related constants, enums, and structures.
- */
-#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
-
-/*
- * Mapping of a Tx power level, at factory calibration temperature,
- *   to a radio/DSP gain table index.
- * One for each of 5 "sample" power levels in each band.
- * v_det is measured at the factory, using the 3945's built-in power amplifier
- *   (PA) output voltage detector.  This same detector is used during Tx of
- *   long packets in normal operation to provide feedback as to proper output
- *   level.
- * Data copied from EEPROM.
- * DO NOT ALTER THIS STRUCTURE!!!
- */
-struct iwl3945_eeprom_txpower_sample {
-	u8 gain_index;		/* index into power (gain) setup table ... */
-	s8 power;		/* ... for this pwr level for this chnl group */
-	u16 v_det;		/* PA output voltage */
-} __packed;
-
-/*
- * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
- * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
- * Tx power setup code interpolates between the 5 "sample" power levels
- *    to determine the nominal setup for a requested power level.
- * Data copied from EEPROM.
- * DO NOT ALTER THIS STRUCTURE!!!
- */
-struct iwl3945_eeprom_txpower_group {
-	struct iwl3945_eeprom_txpower_sample samples[5];  /* 5 power levels */
-	s32 a, b, c, d, e;	/* coefficients for voltage->power
-				 * formula (signed) */
-	s32 Fa, Fb, Fc, Fd, Fe;	/* these modify coeffs based on
-				 * frequency (signed) */
-	s8 saturation_power;	/* highest power possible by h/w in this
-				 * band */
-	u8 group_channel;	/* "representative" channel # in this band */
-	s16 temperature;	/* h/w temperature at factory calib this band
-				 * (signed) */
-} __packed;
-
-/*
- * Temperature-based Tx-power compensation data, not band-specific.
- * These coefficients are use to modify a/b/c/d/e coeffs based on
- *   difference between current temperature and factory calib temperature.
- * Data copied from EEPROM.
- */
-struct iwl3945_eeprom_temperature_corr {
-	u32 Ta;
-	u32 Tb;
-	u32 Tc;
-	u32 Td;
-	u32 Te;
-} __packed;
-
-/*
- * EEPROM map
- */
-struct iwl3945_eeprom {
-	u8 reserved0[16];
-	u16 device_id;	/* abs.ofs: 16 */
-	u8 reserved1[2];
-	u16 pmc;		/* abs.ofs: 20 */
-	u8 reserved2[20];
-	u8 mac_address[6];	/* abs.ofs: 42 */
-	u8 reserved3[58];
-	u16 board_revision;	/* abs.ofs: 106 */
-	u8 reserved4[11];
-	u8 board_pba_number[9];	/* abs.ofs: 119 */
-	u8 reserved5[8];
-	u16 version;		/* abs.ofs: 136 */
-	u8 sku_cap;		/* abs.ofs: 138 */
-	u8 leds_mode;		/* abs.ofs: 139 */
-	u16 oem_mode;
-	u16 wowlan_mode;	/* abs.ofs: 142 */
-	u16 leds_time_interval;	/* abs.ofs: 144 */
-	u8 leds_off_time;	/* abs.ofs: 146 */
-	u8 leds_on_time;	/* abs.ofs: 147 */
-	u8 almgor_m_version;	/* abs.ofs: 148 */
-	u8 antenna_switch_type;	/* abs.ofs: 149 */
-	u8 reserved6[42];
-	u8 sku_id[4];		/* abs.ofs: 192 */
-
-/*
- * Per-channel regulatory data.
- *
- * Each channel that *might* be supported by 3945 or 4965 has a fixed location
- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
- * txpower (MSB).
- *
- * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
- * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
- *
- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
- */
-	u16 band_1_count;	/* abs.ofs: 196 */
-	struct iwl_eeprom_channel band_1_channels[14];  /* abs.ofs: 198 */
-
-/*
- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
- * 5.0 GHz channels 7, 8, 11, 12, 16
- * (4915-5080MHz) (none of these is ever supported)
- */
-	u16 band_2_count;	/* abs.ofs: 226 */
-	struct iwl_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
-
-/*
- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
- * (5170-5320MHz)
- */
-	u16 band_3_count;	/* abs.ofs: 254 */
-	struct iwl_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
-
-/*
- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
- * (5500-5700MHz)
- */
-	u16 band_4_count;	/* abs.ofs: 280 */
-	struct iwl_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
-
-/*
- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
- * (5725-5825MHz)
- */
-	u16 band_5_count;	/* abs.ofs: 304 */
-	struct iwl_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
-
-	u8 reserved9[194];
-
-/*
- * 3945 Txpower calibration data.
- */
-#define IWL_NUM_TX_CALIB_GROUPS 5
-	struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
-/* abs.ofs: 512 */
-	struct iwl3945_eeprom_temperature_corr corrections;  /* abs.ofs: 832 */
-	u8 reserved16[172];	/* fill out to full 1024 byte block */
-} __packed;
-
-#define IWL3945_EEPROM_IMG_SIZE 1024
-
-/* End of EEPROM */
-
-#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)	/* bit 6    */
-#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)	/* bit 7    */
-
-/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
-#define IWL39_NUM_QUEUES        5
-#define IWL39_CMD_QUEUE_NUM	4
-
-#define IWL_DEFAULT_TX_RETRY  15
-
-/*********************************************/
-
-#define RFD_SIZE                              4
-#define NUM_TFD_CHUNKS                        4
-
-#define RX_QUEUE_SIZE                         256
-#define RX_QUEUE_MASK                         255
-#define RX_QUEUE_SIZE_LOG                     8
-
-#define U32_PAD(n)		((4-(n))&0x3)
-
-#define TFD_CTL_COUNT_SET(n)       (n << 24)
-#define TFD_CTL_COUNT_GET(ctl)     ((ctl >> 24) & 7)
-#define TFD_CTL_PAD_SET(n)         (n << 28)
-#define TFD_CTL_PAD_GET(ctl)       (ctl >> 28)
-
-/* Sizes and addresses for instruction and data memory (SRAM) in
- * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define IWL39_RTC_INST_LOWER_BOUND		(0x000000)
-#define IWL39_RTC_INST_UPPER_BOUND		(0x014000)
-
-#define IWL39_RTC_DATA_LOWER_BOUND		(0x800000)
-#define IWL39_RTC_DATA_UPPER_BOUND		(0x808000)
-
-#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
-				IWL39_RTC_INST_LOWER_BOUND)
-#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
-				IWL39_RTC_DATA_LOWER_BOUND)
-
-#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
-#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
-
-/* Size of uCode instruction memory in bootstrap state machine */
-#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
-
-static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
-{
-	return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
-	       (addr < IWL39_RTC_DATA_UPPER_BOUND);
-}
-
-/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
- * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
-struct iwl3945_shared {
-	__le32 tx_base_ptr[8];
-} __packed;
-
-static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
-{
-	return le16_to_cpu(rate_n_flags) & 0xFF;
-}
-
-static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
-{
-	return le16_to_cpu(rate_n_flags);
-}
-
-static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
-{
-	return cpu_to_le16((u16)rate|flags);
-}
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
deleted file mode 100644
index abe2b73..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-commands.h"
-#include "iwl-3945.h"
-#include "iwl-core.h"
-#include "iwl-dev.h"
-#include "iwl-3945-led.h"
-
-
-/* Send led command */
-static int iwl3945_send_led_cmd(struct iwl_priv *priv,
-				struct iwl_led_cmd *led_cmd)
-{
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_LEDS_CMD,
-		.len = sizeof(struct iwl_led_cmd),
-		.data = led_cmd,
-		.flags = CMD_ASYNC,
-		.callback = NULL,
-	};
-
-	return iwl_send_cmd(priv, &cmd);
-}
-
-/* Set led on command */
-static int iwl3945_led_on(struct iwl_priv *priv)
-{
-	struct iwl_led_cmd led_cmd = {
-		.id = IWL_LED_LINK,
-		.on = IWL_LED_SOLID,
-		.off = 0,
-		.interval = IWL_DEF_LED_INTRVL
-	};
-	return iwl3945_send_led_cmd(priv, &led_cmd);
-}
-
-/* Set led off command */
-static int iwl3945_led_off(struct iwl_priv *priv)
-{
-	struct iwl_led_cmd led_cmd = {
-		.id = IWL_LED_LINK,
-		.on = 0,
-		.off = 0,
-		.interval = IWL_DEF_LED_INTRVL
-	};
-	IWL_DEBUG_LED(priv, "led off\n");
-	return iwl3945_send_led_cmd(priv, &led_cmd);
-}
-
-const struct iwl_led_ops iwl3945_led_ops = {
-	.cmd = iwl3945_send_led_cmd,
-	.on = iwl3945_led_on,
-	.off = iwl3945_led_off,
-};
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
deleted file mode 100644
index ce990ad..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 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
- *
- *****************************************************************************/
-
-#ifndef __iwl_3945_led_h__
-#define __iwl_3945_led_h__
-
-extern const struct iwl_led_ops iwl3945_led_ops;
-
-#endif /* __iwl_3945_led_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
deleted file mode 100644
index 1f3e7e3..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ /dev/null
@@ -1,995 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2005 - 2010 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/kernel.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-
-#include <linux/workqueue.h>
-
-#include "iwl-commands.h"
-#include "iwl-3945.h"
-#include "iwl-sta.h"
-
-#define RS_NAME "iwl-3945-rs"
-
-static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
-	7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
-};
-
-static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
-	7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
-};
-
-static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
-	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
-};
-
-static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
-	7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-struct iwl3945_tpt_entry {
-	s8 min_rssi;
-	u8 index;
-};
-
-static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
-	{-60, IWL_RATE_54M_INDEX},
-	{-64, IWL_RATE_48M_INDEX},
-	{-72, IWL_RATE_36M_INDEX},
-	{-80, IWL_RATE_24M_INDEX},
-	{-84, IWL_RATE_18M_INDEX},
-	{-85, IWL_RATE_12M_INDEX},
-	{-87, IWL_RATE_9M_INDEX},
-	{-89, IWL_RATE_6M_INDEX}
-};
-
-static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
-	{-60, IWL_RATE_54M_INDEX},
-	{-64, IWL_RATE_48M_INDEX},
-	{-68, IWL_RATE_36M_INDEX},
-	{-80, IWL_RATE_24M_INDEX},
-	{-84, IWL_RATE_18M_INDEX},
-	{-85, IWL_RATE_12M_INDEX},
-	{-86, IWL_RATE_11M_INDEX},
-	{-88, IWL_RATE_5M_INDEX},
-	{-90, IWL_RATE_2M_INDEX},
-	{-92, IWL_RATE_1M_INDEX}
-};
-
-#define IWL_RATE_MAX_WINDOW          62
-#define IWL_RATE_FLUSH       	 (3*HZ)
-#define IWL_RATE_WIN_FLUSH       (HZ/2)
-#define IWL39_RATE_HIGH_TH          11520
-#define IWL_SUCCESS_UP_TH	   8960
-#define IWL_SUCCESS_DOWN_TH	  10880
-#define IWL_RATE_MIN_FAILURE_TH       6
-#define IWL_RATE_MIN_SUCCESS_TH       8
-#define IWL_RATE_DECREASE_TH       1920
-#define IWL_RATE_RETRY_TH	     15
-
-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
-{
-	u32 index = 0;
-	u32 table_size = 0;
-	struct iwl3945_tpt_entry *tpt_table = NULL;
-
-	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
-		rssi = IWL_MIN_RSSI_VAL;
-
-	switch (band) {
-	case IEEE80211_BAND_2GHZ:
-		tpt_table = iwl3945_tpt_table_g;
-		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
-		break;
-
-	case IEEE80211_BAND_5GHZ:
-		tpt_table = iwl3945_tpt_table_a;
-		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
-		break;
-
-	default:
-		BUG();
-		break;
-	}
-
-	while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
-		index++;
-
-	index = min(index, (table_size - 1));
-
-	return tpt_table[index].index;
-}
-
-static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
-{
-	window->data = 0;
-	window->success_counter = 0;
-	window->success_ratio = -1;
-	window->counter = 0;
-	window->average_tpt = IWL_INVALID_VALUE;
-	window->stamp = 0;
-}
-
-/**
- * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
- *
- * Returns the number of windows that have gathered data but were
- * not flushed.  If there were any that were not flushed, then
- * reschedule the rate flushing routine.
- */
-static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
-{
-	int unflushed = 0;
-	int i;
-	unsigned long flags;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-	/*
-	 * For each rate, if we have collected data on that rate
-	 * and it has been more than IWL_RATE_WIN_FLUSH
-	 * since we flushed, clear out the gathered statistics
-	 */
-	for (i = 0; i < IWL_RATE_COUNT_3945; i++) {
-		if (!rs_sta->win[i].counter)
-			continue;
-
-		spin_lock_irqsave(&rs_sta->lock, flags);
-		if (time_after(jiffies, rs_sta->win[i].stamp +
-			       IWL_RATE_WIN_FLUSH)) {
-			IWL_DEBUG_RATE(priv, "flushing %d samples of rate "
-				       "index %d\n",
-				       rs_sta->win[i].counter, i);
-			iwl3945_clear_window(&rs_sta->win[i]);
-		} else
-			unflushed++;
-		spin_unlock_irqrestore(&rs_sta->lock, flags);
-	}
-
-	return unflushed;
-}
-
-#define IWL_RATE_FLUSH_MAX              5000	/* msec */
-#define IWL_RATE_FLUSH_MIN              50	/* msec */
-#define IWL_AVERAGE_PACKETS             1500
-
-static void iwl3945_bg_rate_scale_flush(unsigned long data)
-{
-	struct iwl3945_rs_sta *rs_sta = (void *)data;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-	int unflushed = 0;
-	unsigned long flags;
-	u32 packet_count, duration, pps;
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	/* Number of packets Rx'd since last time this timer ran */
-	packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
-
-	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
-
-	if (unflushed) {
-		duration =
-		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
-
-		IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n",
-			       packet_count, duration);
-
-		/* Determine packets per second */
-		if (duration)
-			pps = (packet_count * 1000) / duration;
-		else
-			pps = 0;
-
-		if (pps) {
-			duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
-			if (duration < IWL_RATE_FLUSH_MIN)
-				duration = IWL_RATE_FLUSH_MIN;
-			else if (duration > IWL_RATE_FLUSH_MAX)
-				duration = IWL_RATE_FLUSH_MAX;
-		} else
-			duration = IWL_RATE_FLUSH_MAX;
-
-		rs_sta->flush_time = msecs_to_jiffies(duration);
-
-		IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n",
-			       duration, packet_count);
-
-		mod_timer(&rs_sta->rate_scale_flush, jiffies +
-			  rs_sta->flush_time);
-
-		rs_sta->last_partial_flush = jiffies;
-	} else {
-		rs_sta->flush_time = IWL_RATE_FLUSH;
-		rs_sta->flush_pending = 0;
-	}
-	/* If there weren't any unflushed entries, we don't schedule the timer
-	 * to run again */
-
-	rs_sta->last_flush = jiffies;
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-/**
- * iwl3945_collect_tx_data - Update the success/failure sliding window
- *
- * We keep a sliding window of the last 64 packets transmitted
- * at this rate.  window->data contains the bitmask of successful
- * packets.
- */
-static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
-				struct iwl3945_rate_scale_data *window,
-				int success, int retries, int index)
-{
-	unsigned long flags;
-	s32 fail_count;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-	if (!retries) {
-		IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n");
-		return;
-	}
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	/*
-	 * Keep track of only the latest 62 tx frame attempts in this rate's
-	 * history window; anything older isn't really relevant any more.
-	 * If we have filled up the sliding window, drop the oldest attempt;
-	 * if the oldest attempt (highest bit in bitmap) shows "success",
-	 * subtract "1" from the success counter (this is the main reason
-	 * we keep these bitmaps!).
-	 * */
-	while (retries > 0) {
-		if (window->counter >= IWL_RATE_MAX_WINDOW) {
-
-			/* remove earliest */
-			window->counter = IWL_RATE_MAX_WINDOW - 1;
-
-			if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) {
-				window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1));
-				window->success_counter--;
-			}
-		}
-
-		/* Increment frames-attempted counter */
-		window->counter++;
-
-		/* Shift bitmap by one frame (throw away oldest history),
-		 * OR in "1", and increment "success" if this
-		 * frame was successful. */
-		window->data <<= 1;
-		if (success > 0) {
-			window->success_counter++;
-			window->data |= 0x1;
-			success--;
-		}
-
-		retries--;
-	}
-
-	/* Calculate current success ratio, avoid divide-by-0! */
-	if (window->counter > 0)
-		window->success_ratio = 128 * (100 * window->success_counter)
-					/ window->counter;
-	else
-		window->success_ratio = IWL_INVALID_VALUE;
-
-	fail_count = window->counter - window->success_counter;
-
-	/* Calculate average throughput, if we have enough history. */
-	if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
-	    (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
-		window->average_tpt = ((window->success_ratio *
-				rs_sta->expected_tpt[index] + 64) / 128);
-	else
-		window->average_tpt = IWL_INVALID_VALUE;
-
-	/* Tag this window as having been updated */
-	window->stamp = jiffies;
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-}
-
-/*
- * Called after adding a new station to initialize rate scaling
- */
-void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
-{
-	struct ieee80211_hw *hw = priv->hw;
-	struct ieee80211_conf *conf = &priv->hw->conf;
-	struct iwl3945_sta_priv *psta;
-	struct iwl3945_rs_sta *rs_sta;
-	struct ieee80211_supported_band *sband;
-	int i;
-
-	IWL_DEBUG_INFO(priv, "enter\n");
-	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
-		goto out;
-
-	psta = (struct iwl3945_sta_priv *) sta->drv_priv;
-	rs_sta = &psta->rs_sta;
-	sband = hw->wiphy->bands[conf->channel->band];
-
-	rs_sta->priv = priv;
-
-	rs_sta->start_rate = IWL_RATE_INVALID;
-
-	/* default to just 802.11b */
-	rs_sta->expected_tpt = iwl3945_expected_tpt_b;
-
-	rs_sta->last_partial_flush = jiffies;
-	rs_sta->last_flush = jiffies;
-	rs_sta->flush_time = IWL_RATE_FLUSH;
-	rs_sta->last_tx_packets = 0;
-
-	rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
-	rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;
-
-	for (i = 0; i < IWL_RATE_COUNT_3945; i++)
-		iwl3945_clear_window(&rs_sta->win[i]);
-
-	/* TODO: what is a good starting rate for STA? About middle? Maybe not
-	 * the lowest or the highest rate.. Could consider using RSSI from
-	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
-	 * after assoc.. */
-
-	for (i = sband->n_bitrates - 1; i >= 0; i--) {
-		if (sta->supp_rates[sband->band] & (1 << i)) {
-			rs_sta->last_txrate_idx = i;
-			break;
-		}
-	}
-
-	priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
-	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
-	if (sband->band == IEEE80211_BAND_5GHZ) {
-		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-		priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
-						IWL_FIRST_OFDM_RATE;
-	}
-
-out:
-	priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-
-	IWL_DEBUG_INFO(priv, "leave\n");
-}
-
-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
-	return hw->priv;
-}
-
-/* rate scale requires free function to be implemented */
-static void rs_free(void *priv)
-{
-	return;
-}
-
-static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
-{
-	struct iwl3945_rs_sta *rs_sta;
-	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
-	struct iwl_priv *priv __maybe_unused = iwl_priv;
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	rs_sta = &psta->rs_sta;
-
-	spin_lock_init(&rs_sta->lock);
-	init_timer(&rs_sta->rate_scale_flush);
-
-	IWL_DEBUG_RATE(priv, "leave\n");
-
-	return rs_sta;
-}
-
-static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
-			void *priv_sta)
-{
-	struct iwl3945_rs_sta *rs_sta = priv_sta;
-
-	/*
-	 * Be careful not to use any members of iwl3945_rs_sta (like trying
-	 * to use iwl_priv to print out debugging) since it may not be fully
-	 * initialized at this point.
-	 */
-	del_timer_sync(&rs_sta->rate_scale_flush);
-}
-
-
-/**
- * rs_tx_status - Update rate control values based on Tx results
- *
- * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
- * the hardware for each rate.
- */
-static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
-			 struct ieee80211_sta *sta, void *priv_sta,
-			 struct sk_buff *skb)
-{
-	s8 retries = 0, current_count;
-	int scale_rate_index, first_index, last_index;
-	unsigned long flags;
-	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
-	struct iwl3945_rs_sta *rs_sta = priv_sta;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	retries = info->status.rates[0].count;
-	/* Sanity Check for retries */
-	if (retries > IWL_RATE_RETRY_TH)
-		retries = IWL_RATE_RETRY_TH;
-
-	first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
-	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
-		IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index);
-		return;
-	}
-
-	if (!priv_sta) {
-		IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
-		return;
-	}
-
-	/* Treat uninitialized rate scaling data same as non-existing. */
-	if (!rs_sta->priv) {
-		IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
-		return;
-	}
-
-
-	rs_sta->tx_packets++;
-
-	scale_rate_index = first_index;
-	last_index = first_index;
-
-	/*
-	 * Update the window for each rate.  We determine which rates
-	 * were Tx'd based on the total number of retries vs. the number
-	 * of retries configured for each rate -- currently set to the
-	 * priv value 'retry_rate' vs. rate specific
-	 *
-	 * On exit from this while loop last_index indicates the rate
-	 * at which the frame was finally transmitted (or failed if no
-	 * ACK)
-	 */
-	while (retries > 1) {
-		if ((retries - 1) < priv->retry_rate) {
-			current_count = (retries - 1);
-			last_index = scale_rate_index;
-		} else {
-			current_count = priv->retry_rate;
-			last_index = iwl3945_rs_next_rate(priv,
-							 scale_rate_index);
-		}
-
-		/* Update this rate accounting for as many retries
-		 * as was used for it (per current_count) */
-		iwl3945_collect_tx_data(rs_sta,
-				    &rs_sta->win[scale_rate_index],
-				    0, current_count, scale_rate_index);
-		IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n",
-			       scale_rate_index, current_count);
-
-		retries -= current_count;
-
-		scale_rate_index = last_index;
-	}
-
-
-	/* Update the last index window with success/failure based on ACK */
-	IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n",
-		       last_index,
-		       (info->flags & IEEE80211_TX_STAT_ACK) ?
-		       "success" : "failure");
-	iwl3945_collect_tx_data(rs_sta,
-			    &rs_sta->win[last_index],
-			    info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
-
-	/* We updated the rate scale window -- if its been more than
-	 * flush_time since the last run, schedule the flush
-	 * again */
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	if (!rs_sta->flush_pending &&
-	    time_after(jiffies, rs_sta->last_flush +
-		       rs_sta->flush_time)) {
-
-		rs_sta->last_partial_flush = jiffies;
-		rs_sta->flush_pending = 1;
-		mod_timer(&rs_sta->rate_scale_flush,
-			  jiffies + rs_sta->flush_time);
-	}
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
-				 u8 index, u16 rate_mask, enum ieee80211_band band)
-{
-	u8 high = IWL_RATE_INVALID;
-	u8 low = IWL_RATE_INVALID;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-	/* 802.11A walks to the next literal adjacent rate in
-	 * the rate table */
-	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
-		int i;
-		u32 mask;
-
-		/* Find the previous rate that is in the rate mask */
-		i = index - 1;
-		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
-			if (rate_mask & mask) {
-				low = i;
-				break;
-			}
-		}
-
-		/* Find the next rate that is in the rate mask */
-		i = index + 1;
-		for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
-		     i++, mask <<= 1) {
-			if (rate_mask & mask) {
-				high = i;
-				break;
-			}
-		}
-
-		return (high << 8) | low;
-	}
-
-	low = index;
-	while (low != IWL_RATE_INVALID) {
-		if (rs_sta->tgg)
-			low = iwl3945_rates[low].prev_rs_tgg;
-		else
-			low = iwl3945_rates[low].prev_rs;
-		if (low == IWL_RATE_INVALID)
-			break;
-		if (rate_mask & (1 << low))
-			break;
-		IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
-	}
-
-	high = index;
-	while (high != IWL_RATE_INVALID) {
-		if (rs_sta->tgg)
-			high = iwl3945_rates[high].next_rs_tgg;
-		else
-			high = iwl3945_rates[high].next_rs;
-		if (high == IWL_RATE_INVALID)
-			break;
-		if (rate_mask & (1 << high))
-			break;
-		IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
-	}
-
-	return (high << 8) | low;
-}
-
-/**
- * rs_get_rate - find the rate for the requested packet
- *
- * Returns the ieee80211_rate structure allocated by the driver.
- *
- * The rate control algorithm has no internal mapping between hw_mode's
- * rate ordering and the rate ordering used by the rate control algorithm.
- *
- * The rate control algorithm uses a single table of rates that goes across
- * the entire A/B/G spectrum vs. being limited to just one particular
- * hw_mode.
- *
- * As such, we can't convert the index obtained below into the hw_mode's
- * rate table and must reference the driver allocated rate table
- *
- */
-static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
-			void *priv_sta,	struct ieee80211_tx_rate_control *txrc)
-{
-	struct ieee80211_supported_band *sband = txrc->sband;
-	struct sk_buff *skb = txrc->skb;
-	u8 low = IWL_RATE_INVALID;
-	u8 high = IWL_RATE_INVALID;
-	u16 high_low;
-	int index;
-	struct iwl3945_rs_sta *rs_sta = priv_sta;
-	struct iwl3945_rate_scale_data *window = NULL;
-	int current_tpt = IWL_INVALID_VALUE;
-	int low_tpt = IWL_INVALID_VALUE;
-	int high_tpt = IWL_INVALID_VALUE;
-	u32 fail_count;
-	s8 scale_action = 0;
-	unsigned long flags;
-	u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0;
-	s8 max_rate_idx = -1;
-	struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	/* Treat uninitialized rate scaling data same as non-existing. */
-	if (rs_sta && !rs_sta->priv) {
-		IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
-		priv_sta = NULL;
-	}
-
-	if (rate_control_send_low(sta, priv_sta, txrc))
-		return;
-
-	rate_mask = sta->supp_rates[sband->band];
-
-	/* get user max rate if set */
-	max_rate_idx = txrc->max_rate_idx;
-	if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
-		max_rate_idx += IWL_FIRST_OFDM_RATE;
-	if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
-		max_rate_idx = -1;
-
-	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
-
-	if (sband->band == IEEE80211_BAND_5GHZ)
-		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	/* for recent assoc, choose best rate regarding
-	 * to rssi value
-	 */
-	if (rs_sta->start_rate != IWL_RATE_INVALID) {
-		if (rs_sta->start_rate < index &&
-		   (rate_mask & (1 << rs_sta->start_rate)))
-			index = rs_sta->start_rate;
-		rs_sta->start_rate = IWL_RATE_INVALID;
-	}
-
-	/* force user max rate if set by user */
-	if ((max_rate_idx != -1) && (max_rate_idx < index)) {
-		if (rate_mask & (1 << max_rate_idx))
-			index = max_rate_idx;
-	}
-
-	window = &(rs_sta->win[index]);
-
-	fail_count = window->counter - window->success_counter;
-
-	if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
-	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
-		spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-		IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: "
-			       "counter: %d, success_counter: %d, "
-			       "expected_tpt is %sNULL\n",
-			       index,
-			       window->counter,
-			       window->success_counter,
-			       rs_sta->expected_tpt ? "not " : "");
-
-	   /* Can't calculate this yet; not enough history */
-		window->average_tpt = IWL_INVALID_VALUE;
-		goto out;
-
-	}
-
-	current_tpt = window->average_tpt;
-
-	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
-					     sband->band);
-	low = high_low & 0xff;
-	high = (high_low >> 8) & 0xff;
-
-	/* If user set max rate, dont allow higher than user constrain */
-	if ((max_rate_idx != -1) && (max_rate_idx < high))
-		high = IWL_RATE_INVALID;
-
-	/* Collect Measured throughputs of adjacent rates */
-	if (low != IWL_RATE_INVALID)
-		low_tpt = rs_sta->win[low].average_tpt;
-
-	if (high != IWL_RATE_INVALID)
-		high_tpt = rs_sta->win[high].average_tpt;
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	scale_action = 0;
-
-	/* Low success ratio , need to drop the rate */
-	if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
-		IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n");
-		scale_action = -1;
-	/* No throughput measured yet for adjacent rates,
-	 * try increase */
-	} else if ((low_tpt == IWL_INVALID_VALUE) &&
-		   (high_tpt == IWL_INVALID_VALUE)) {
-
-		if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH)
-			scale_action = 1;
-		else if (low != IWL_RATE_INVALID)
-			scale_action = 0;
-
-	/* Both adjacent throughputs are measured, but neither one has
-	 * better throughput; we're using the best rate, don't change
-	 * it! */
-	} else if ((low_tpt != IWL_INVALID_VALUE) &&
-		 (high_tpt != IWL_INVALID_VALUE) &&
-		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
-
-		IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < "
-			       "current_tpt [%d]\n",
-			       low_tpt, high_tpt, current_tpt);
-		scale_action = 0;
-
-	/* At least one of the rates has better throughput */
-	} else {
-		if (high_tpt != IWL_INVALID_VALUE) {
-
-			/* High rate has better throughput, Increase
-			 * rate */
-			if (high_tpt > current_tpt &&
-				window->success_ratio >= IWL_RATE_INCREASE_TH)
-				scale_action = 1;
-			else {
-				IWL_DEBUG_RATE(priv,
-				    "decrease rate because of high tpt\n");
-				scale_action = 0;
-			}
-		} else if (low_tpt != IWL_INVALID_VALUE) {
-			if (low_tpt > current_tpt) {
-				IWL_DEBUG_RATE(priv,
-				    "decrease rate because of low tpt\n");
-				scale_action = -1;
-			} else if (window->success_ratio >= IWL_RATE_INCREASE_TH) {
-				/* Lower rate has better
-				 * throughput,decrease rate */
-				scale_action = 1;
-			}
-		}
-	}
-
-	/* Sanity check; asked for decrease, but success rate or throughput
-	 * has been good at old rate.  Don't change it. */
-	if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
-		    ((window->success_ratio > IWL_RATE_HIGH_TH) ||
-		     (current_tpt > (100 * rs_sta->expected_tpt[low]))))
-		scale_action = 0;
-
-	switch (scale_action) {
-	case -1:
-
-		/* Decrese rate */
-		if (low != IWL_RATE_INVALID)
-			index = low;
-		break;
-
-	case 1:
-		/* Increase rate */
-		if (high != IWL_RATE_INVALID)
-			index = high;
-
-		break;
-
-	case 0:
-	default:
-		/* No change */
-		break;
-	}
-
-	IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n",
-		       index, scale_action, low, high);
-
- out:
-
-	rs_sta->last_txrate_idx = index;
-	if (sband->band == IEEE80211_BAND_5GHZ)
-		info->control.rates[0].idx = rs_sta->last_txrate_idx -
-				IWL_FIRST_OFDM_RATE;
-	else
-		info->control.rates[0].idx = rs_sta->last_txrate_idx;
-
-	IWL_DEBUG_RATE(priv, "leave: %d\n", index);
-}
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
-						  char __user *user_buf,
-						  size_t count, loff_t *ppos)
-{
-	char *buff;
-	int desc = 0;
-	int j;
-	ssize_t ret;
-	struct iwl3945_rs_sta *lq_sta = file->private_data;
-
-	buff = kmalloc(1024, GFP_KERNEL);
-	if (!buff)
-		return -ENOMEM;
-
-	desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
-			"rate=0x%X flush time %d\n",
-			lq_sta->tx_packets,
-			lq_sta->last_txrate_idx,
-			lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
-	for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
-		desc += sprintf(buff+desc,
-				"counter=%d success=%d %%=%d\n",
-				lq_sta->win[j].counter,
-				lq_sta->win[j].success_counter,
-				lq_sta->win[j].success_ratio);
-	}
-	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
-	kfree(buff);
-	return ret;
-}
-
-static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
-	.read = iwl3945_sta_dbgfs_stats_table_read,
-	.open = iwl3945_open_file_generic,
-	.llseek = default_llseek,
-};
-
-static void iwl3945_add_debugfs(void *priv, void *priv_sta,
-				struct dentry *dir)
-{
-	struct iwl3945_rs_sta *lq_sta = priv_sta;
-
-	lq_sta->rs_sta_dbgfs_stats_table_file =
-		debugfs_create_file("rate_stats_table", 0600, dir,
-		lq_sta, &rs_sta_dbgfs_stats_table_ops);
-
-}
-
-static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
-{
-	struct iwl3945_rs_sta *lq_sta = priv_sta;
-	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
-}
-#endif
-
-/*
- * Initialization of rate scaling information is done by driver after
- * the station is added. Since mac80211 calls this function before a
- * station is added we ignore it.
- */
-static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
-			      struct ieee80211_sta *sta, void *priv_sta)
-{
-}
-
-static struct rate_control_ops rs_ops = {
-	.module = NULL,
-	.name = RS_NAME,
-	.tx_status = rs_tx_status,
-	.get_rate = rs_get_rate,
-	.rate_init = rs_rate_init_stub,
-	.alloc = rs_alloc,
-	.free = rs_free,
-	.alloc_sta = rs_alloc_sta,
-	.free_sta = rs_free_sta,
-#ifdef CONFIG_MAC80211_DEBUGFS
-	.add_sta_debugfs = iwl3945_add_debugfs,
-	.remove_sta_debugfs = iwl3945_remove_debugfs,
-#endif
-
-};
-void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
-{
-	struct iwl_priv *priv = hw->priv;
-	s32 rssi = 0;
-	unsigned long flags;
-	struct iwl3945_rs_sta *rs_sta;
-	struct ieee80211_sta *sta;
-	struct iwl3945_sta_priv *psta;
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	rcu_read_lock();
-
-	sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
-				 priv->stations[sta_id].sta.sta.addr);
-	if (!sta) {
-		IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
-		rcu_read_unlock();
-		return;
-	}
-
-	psta = (void *) sta->drv_priv;
-	rs_sta = &psta->rs_sta;
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	rs_sta->tgg = 0;
-	switch (priv->band) {
-	case IEEE80211_BAND_2GHZ:
-		/* TODO: this always does G, not a regression */
-		if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
-						RXON_FLG_TGG_PROTECT_MSK) {
-			rs_sta->tgg = 1;
-			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
-		} else
-			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
-		break;
-
-	case IEEE80211_BAND_5GHZ:
-		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
-		break;
-	case IEEE80211_NUM_BANDS:
-		BUG();
-		break;
-	}
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	rssi = priv->_3945.last_rx_rssi;
-	if (rssi == 0)
-		rssi = IWL_MIN_RSSI_VAL;
-
-	IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi);
-
-	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
-
-	IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: "
-		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
-		       iwl3945_rates[rs_sta->start_rate].plcp);
-	rcu_read_unlock();
-}
-
-int iwl3945_rate_control_register(void)
-{
-	return ieee80211_rate_control_register(&rs_ops);
-}
-
-void iwl3945_rate_control_unregister(void)
-{
-	ieee80211_rate_control_unregister(&rs_ops);
-}
-
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
deleted file mode 100644
index 39b6f16..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ /dev/null
@@ -1,2753 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-#include <net/mac80211.h>
-
-#include "iwl-fh.h"
-#include "iwl-3945-fh.h"
-#include "iwl-commands.h"
-#include "iwl-sta.h"
-#include "iwl-3945.h"
-#include "iwl-eeprom.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-led.h"
-#include "iwl-3945-led.h"
-#include "iwl-3945-debugfs.h"
-#include "iwl-legacy.h"
-
-#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
-	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
-				    IWL_RATE_##r##M_IEEE,   \
-				    IWL_RATE_##ip##M_INDEX, \
-				    IWL_RATE_##in##M_INDEX, \
-				    IWL_RATE_##rp##M_INDEX, \
-				    IWL_RATE_##rn##M_INDEX, \
-				    IWL_RATE_##pp##M_INDEX, \
-				    IWL_RATE_##np##M_INDEX, \
-				    IWL_RATE_##r##M_INDEX_TABLE, \
-				    IWL_RATE_##ip##M_INDEX_TABLE }
-
-/*
- * Parameter order:
- *   rate, prev rate, next rate, prev tgg rate, next tgg rate
- *
- * If there isn't a valid next or previous rate then INV is used which
- * maps to IWL_RATE_INVALID
- *
- */
-const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
-	IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),    /*  1mbps */
-	IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),          /*  2mbps */
-	IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
-	IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),      /* 11mbps */
-	IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
-	IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),       /*  9mbps */
-	IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
-	IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
-	IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
-	IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
-	IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
-	IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
-};
-
-static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
-{
-	u8 rate = iwl3945_rates[rate_index].prev_ieee;
-
-	if (rate == IWL_RATE_INVALID)
-		rate = rate_index;
-	return rate;
-}
-
-/* 1 = enable the iwl3945_disable_events() function */
-#define IWL_EVT_DISABLE (0)
-#define IWL_EVT_DISABLE_SIZE (1532/32)
-
-/**
- * iwl3945_disable_events - Disable selected events in uCode event log
- *
- * Disable an event by writing "1"s into "disable"
- *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
- *   Default values of 0 enable uCode events to be logged.
- * Use for only special debugging.  This function is just a placeholder as-is,
- *   you'll need to provide the special bits! ...
- *   ... and set IWL_EVT_DISABLE to 1. */
-void iwl3945_disable_events(struct iwl_priv *priv)
-{
-	int i;
-	u32 base;		/* SRAM address of event log header */
-	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
-	u32 array_size;		/* # of u32 entries in array */
-	static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
-		0x00000000,	/*   31 -    0  Event id numbers */
-		0x00000000,	/*   63 -   32 */
-		0x00000000,	/*   95 -   64 */
-		0x00000000,	/*  127 -   96 */
-		0x00000000,	/*  159 -  128 */
-		0x00000000,	/*  191 -  160 */
-		0x00000000,	/*  223 -  192 */
-		0x00000000,	/*  255 -  224 */
-		0x00000000,	/*  287 -  256 */
-		0x00000000,	/*  319 -  288 */
-		0x00000000,	/*  351 -  320 */
-		0x00000000,	/*  383 -  352 */
-		0x00000000,	/*  415 -  384 */
-		0x00000000,	/*  447 -  416 */
-		0x00000000,	/*  479 -  448 */
-		0x00000000,	/*  511 -  480 */
-		0x00000000,	/*  543 -  512 */
-		0x00000000,	/*  575 -  544 */
-		0x00000000,	/*  607 -  576 */
-		0x00000000,	/*  639 -  608 */
-		0x00000000,	/*  671 -  640 */
-		0x00000000,	/*  703 -  672 */
-		0x00000000,	/*  735 -  704 */
-		0x00000000,	/*  767 -  736 */
-		0x00000000,	/*  799 -  768 */
-		0x00000000,	/*  831 -  800 */
-		0x00000000,	/*  863 -  832 */
-		0x00000000,	/*  895 -  864 */
-		0x00000000,	/*  927 -  896 */
-		0x00000000,	/*  959 -  928 */
-		0x00000000,	/*  991 -  960 */
-		0x00000000,	/* 1023 -  992 */
-		0x00000000,	/* 1055 - 1024 */
-		0x00000000,	/* 1087 - 1056 */
-		0x00000000,	/* 1119 - 1088 */
-		0x00000000,	/* 1151 - 1120 */
-		0x00000000,	/* 1183 - 1152 */
-		0x00000000,	/* 1215 - 1184 */
-		0x00000000,	/* 1247 - 1216 */
-		0x00000000,	/* 1279 - 1248 */
-		0x00000000,	/* 1311 - 1280 */
-		0x00000000,	/* 1343 - 1312 */
-		0x00000000,	/* 1375 - 1344 */
-		0x00000000,	/* 1407 - 1376 */
-		0x00000000,	/* 1439 - 1408 */
-		0x00000000,	/* 1471 - 1440 */
-		0x00000000,	/* 1503 - 1472 */
-	};
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-		return;
-	}
-
-	disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32)));
-	array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32)));
-
-	if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
-		IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n",
-			       disable_ptr);
-		for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
-			iwl_write_targ_mem(priv,
-					   disable_ptr + (i * sizeof(u32)),
-					   evt_disable[i]);
-
-	} else {
-		IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n");
-		IWL_DEBUG_INFO(priv, "  by writing \"1\"s into disable bitmap\n");
-		IWL_DEBUG_INFO(priv, "  in SRAM at 0x%x, size %d u32s\n",
-			       disable_ptr, array_size);
-	}
-
-}
-
-static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
-{
-	int idx;
-
-	for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++)
-		if (iwl3945_rates[idx].plcp == plcp)
-			return idx;
-	return -1;
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
-
-static const char *iwl3945_get_tx_fail_reason(u32 status)
-{
-	switch (status & TX_STATUS_MSK) {
-	case TX_3945_STATUS_SUCCESS:
-		return "SUCCESS";
-		TX_STATUS_ENTRY(SHORT_LIMIT);
-		TX_STATUS_ENTRY(LONG_LIMIT);
-		TX_STATUS_ENTRY(FIFO_UNDERRUN);
-		TX_STATUS_ENTRY(MGMNT_ABORT);
-		TX_STATUS_ENTRY(NEXT_FRAG);
-		TX_STATUS_ENTRY(LIFE_EXPIRE);
-		TX_STATUS_ENTRY(DEST_PS);
-		TX_STATUS_ENTRY(ABORTED);
-		TX_STATUS_ENTRY(BT_RETRY);
-		TX_STATUS_ENTRY(STA_INVALID);
-		TX_STATUS_ENTRY(FRAG_DROPPED);
-		TX_STATUS_ENTRY(TID_DISABLE);
-		TX_STATUS_ENTRY(FRAME_FLUSHED);
-		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-		TX_STATUS_ENTRY(TX_LOCKED);
-		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
-	}
-
-	return "UNKNOWN";
-}
-#else
-static inline const char *iwl3945_get_tx_fail_reason(u32 status)
-{
-	return "";
-}
-#endif
-
-/*
- * get ieee prev rate from rate scale table.
- * for A and B mode we need to overright prev
- * value
- */
-int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
-{
-	int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
-	switch (priv->band) {
-	case IEEE80211_BAND_5GHZ:
-		if (rate == IWL_RATE_12M_INDEX)
-			next_rate = IWL_RATE_9M_INDEX;
-		else if (rate == IWL_RATE_6M_INDEX)
-			next_rate = IWL_RATE_6M_INDEX;
-		break;
-	case IEEE80211_BAND_2GHZ:
-		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-		    iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-			if (rate == IWL_RATE_11M_INDEX)
-				next_rate = IWL_RATE_5M_INDEX;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return next_rate;
-}
-
-
-/**
- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms. If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
-				     int txq_id, int index)
-{
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-	struct iwl_tx_info *tx_info;
-
-	BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
-
-	for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-		tx_info = &txq->txb[txq->q.read_ptr];
-		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
-		tx_info->skb = NULL;
-		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-	}
-
-	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-			(txq_id != IWL39_CMD_QUEUE_NUM) &&
-			priv->mac80211_registered)
-		iwl_wake_queue(priv, txq);
-}
-
-/**
- * iwl3945_rx_reply_tx - Handle Tx response
- */
-static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-	int txq_id = SEQ_TO_QUEUE(sequence);
-	int index = SEQ_TO_INDEX(sequence);
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct ieee80211_tx_info *info;
-	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-	u32  status = le32_to_cpu(tx_resp->status);
-	int rate_idx;
-	int fail;
-
-	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
-			  "is out of range [0-%d] %d %d\n", txq_id,
-			  index, txq->q.n_bd, txq->q.write_ptr,
-			  txq->q.read_ptr);
-		return;
-	}
-
-	txq->time_stamp = jiffies;
-	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
-	ieee80211_tx_info_clear_status(info);
-
-	/* Fill the MRR chain with some info about on-chip retransmissions */
-	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
-	if (info->band == IEEE80211_BAND_5GHZ)
-		rate_idx -= IWL_FIRST_OFDM_RATE;
-
-	fail = tx_resp->failure_frame;
-
-	info->status.rates[0].idx = rate_idx;
-	info->status.rates[0].count = fail + 1; /* add final attempt */
-
-	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
-	info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
-				IEEE80211_TX_STAT_ACK : 0;
-
-	IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
-			txq_id, iwl3945_get_tx_fail_reason(status), status,
-			tx_resp->rate, tx_resp->failure_frame);
-
-	IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
-	iwl3945_tx_queue_reclaim(priv, txq_id, index);
-
-	if (status & TX_ABORT_REQUIRED_MSK)
-		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
-}
-
-
-
-/*****************************************************************************
- *
- * Intel PRO/Wireless 3945ABG/BG Network Connection
- *
- *  RX handler implementations
- *
- *****************************************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/*
- *  based on the assumption of all statistics counter are in DWORD
- *  FIXME: This function is for debugging, do not deal with
- *  the case of counters roll-over.
- */
-static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
-					    __le32 *stats)
-{
-	int i;
-	__le32 *prev_stats;
-	u32 *accum_stats;
-	u32 *delta, *max_delta;
-
-	prev_stats = (__le32 *)&priv->_3945.statistics;
-	accum_stats = (u32 *)&priv->_3945.accum_statistics;
-	delta = (u32 *)&priv->_3945.delta_statistics;
-	max_delta = (u32 *)&priv->_3945.max_delta;
-
-	for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
-	     i += sizeof(__le32), stats++, prev_stats++, delta++,
-	     max_delta++, accum_stats++) {
-		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-			*delta = (le32_to_cpu(*stats) -
-				le32_to_cpu(*prev_stats));
-			*accum_stats += *delta;
-			if (*delta > *max_delta)
-				*max_delta = *delta;
-		}
-	}
-
-	/* reset accumulative statistics for "no-counter" type statistics */
-	priv->_3945.accum_statistics.general.temperature =
-		priv->_3945.statistics.general.temperature;
-	priv->_3945.accum_statistics.general.ttl_timestamp =
-		priv->_3945.statistics.general.ttl_timestamp;
-}
-#endif
-
-void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
-		struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-		     (int)sizeof(struct iwl3945_notif_statistics),
-		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
-#endif
-	iwl_recover_from_statistics(priv, pkt);
-
-	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
-}
-
-void iwl3945_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	__le32 *flag = (__le32 *)&pkt->u.raw;
-
-	if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->_3945.accum_statistics, 0,
-			sizeof(struct iwl3945_notif_statistics));
-		memset(&priv->_3945.delta_statistics, 0,
-			sizeof(struct iwl3945_notif_statistics));
-		memset(&priv->_3945.max_delta, 0,
-			sizeof(struct iwl3945_notif_statistics));
-#endif
-		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-	}
-	iwl3945_hw_rx_statistics(priv, rxb);
-}
-
-
-/******************************************************************************
- *
- * Misc. internal state and helper functions
- *
- ******************************************************************************/
-
-/* This is necessary only for a number of statistics, see the caller. */
-static int iwl3945_is_network_packet(struct iwl_priv *priv,
-		struct ieee80211_hdr *header)
-{
-	/* Filter incoming packets to determine if they are targeted toward
-	 * this network, discarding packets coming from ourselves */
-	switch (priv->iw_mode) {
-	case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source    | BSSID */
-		/* packets to our IBSS update information */
-		return !compare_ether_addr(header->addr3, priv->bssid);
-	case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
-		/* packets to our IBSS update information */
-		return !compare_ether_addr(header->addr2, priv->bssid);
-	default:
-		return 1;
-	}
-}
-
-static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
-				   struct iwl_rx_mem_buffer *rxb,
-				   struct ieee80211_rx_status *stats)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-	u16 len = le16_to_cpu(rx_hdr->len);
-	struct sk_buff *skb;
-	__le16 fc = hdr->frame_control;
-
-	/* We received data from the HW, so stop the watchdog */
-	if (unlikely(len + IWL39_RX_FRAME_SIZE >
-		     PAGE_SIZE << priv->hw_params.rx_page_order)) {
-		IWL_DEBUG_DROP(priv, "Corruption detected!\n");
-		return;
-	}
-
-	/* We only process data packets if the interface is open */
-	if (unlikely(!priv->is_open)) {
-		IWL_DEBUG_DROP_LIMIT(priv,
-			"Dropping packet while interface is not open.\n");
-		return;
-	}
-
-	skb = dev_alloc_skb(128);
-	if (!skb) {
-		IWL_ERR(priv, "dev_alloc_skb failed\n");
-		return;
-	}
-
-	if (!iwl3945_mod_params.sw_crypto)
-		iwl_set_decrypted_flag(priv,
-				       (struct ieee80211_hdr *)rxb_addr(rxb),
-				       le32_to_cpu(rx_end->status), stats);
-
-	skb_add_rx_frag(skb, 0, rxb->page,
-			(void *)rx_hdr->payload - (void *)pkt, len);
-
-	iwl_update_stats(priv, false, fc, len);
-	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
-	ieee80211_rx(priv->hw, skb);
-	priv->alloc_rxb_page--;
-	rxb->page = NULL;
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
-static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-	u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
-	u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
-	u8 network_packet;
-
-	rx_status.flag = 0;
-	rx_status.mactime = le64_to_cpu(rx_end->timestamp);
-	rx_status.freq =
-		ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel));
-	rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-
-	rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
-	if (rx_status.band == IEEE80211_BAND_5GHZ)
-		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
-
-	rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
-					RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-
-	/* set the preamble flag if appropriate */
-	if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-		rx_status.flag |= RX_FLAG_SHORTPRE;
-
-	if ((unlikely(rx_stats->phy_count > 20))) {
-		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-				rx_stats->phy_count);
-		return;
-	}
-
-	if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR)
-	    || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
-		return;
-	}
-
-
-
-	/* Convert 3945's rssi indicator to dBm */
-	rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
-
-	IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
-			rx_status.signal, rx_stats_sig_avg,
-			rx_stats_noise_diff);
-
-	header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-
-	network_packet = iwl3945_is_network_packet(priv, header);
-
-	IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
-			      network_packet ? '*' : ' ',
-			      le16_to_cpu(rx_hdr->channel),
-			      rx_status.signal, rx_status.signal,
-			      rx_status.rate_idx);
-
-	iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
-
-	if (network_packet) {
-		priv->_3945.last_beacon_time =
-			le32_to_cpu(rx_end->beacon_timestamp);
-		priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
-		priv->_3945.last_rx_rssi = rx_status.signal;
-	}
-
-	iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
-}
-
-int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-				     struct iwl_tx_queue *txq,
-				     dma_addr_t addr, u16 len, u8 reset, u8 pad)
-{
-	int count;
-	struct iwl_queue *q;
-	struct iwl3945_tfd *tfd, *tfd_tmp;
-
-	q = &txq->q;
-	tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
-	tfd = &tfd_tmp[q->write_ptr];
-
-	if (reset)
-		memset(tfd, 0, sizeof(*tfd));
-
-	count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-
-	if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
-		IWL_ERR(priv, "Error can not send more than %d chunks\n",
-			  NUM_TFD_CHUNKS);
-		return -EINVAL;
-	}
-
-	tfd->tbs[count].addr = cpu_to_le32(addr);
-	tfd->tbs[count].len = cpu_to_le32(len);
-
-	count++;
-
-	tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) |
-					 TFD_CTL_PAD_SET(pad));
-
-	return 0;
-}
-
-/**
- * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr]
- *
- * Does NOT advance any indexes
- */
-void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
-	int index = txq->q.read_ptr;
-	struct iwl3945_tfd *tfd = &tfd_tmp[index];
-	struct pci_dev *dev = priv->pci_dev;
-	int i;
-	int counter;
-
-	/* sanity check */
-	counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-	if (counter > NUM_TFD_CHUNKS) {
-		IWL_ERR(priv, "Too many chunks: %i\n", counter);
-		/* @todo issue fatal error, it is quite serious situation */
-		return;
-	}
-
-	/* Unmap tx_cmd */
-	if (counter)
-		pci_unmap_single(dev,
-				dma_unmap_addr(&txq->meta[index], mapping),
-				dma_unmap_len(&txq->meta[index], len),
-				PCI_DMA_TODEVICE);
-
-	/* unmap chunks if any */
-
-	for (i = 1; i < counter; i++)
-		pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
-			 le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
-
-	/* free SKB */
-	if (txq->txb) {
-		struct sk_buff *skb;
-
-		skb = txq->txb[txq->q.read_ptr].skb;
-
-		/* can be called from irqs-disabled context */
-		if (skb) {
-			dev_kfree_skb_any(skb);
-			txq->txb[txq->q.read_ptr].skb = NULL;
-		}
-	}
-}
-
-/**
- * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
- *
-*/
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-				  struct iwl_device_cmd *cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr,
-				  int sta_id, int tx_id)
-{
-	u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
-	u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945);
-	u16 rate_mask;
-	int rate;
-	u8 rts_retry_limit;
-	u8 data_retry_limit;
-	__le32 tx_flags;
-	__le16 fc = hdr->frame_control;
-	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-
-	rate = iwl3945_rates[rate_index].plcp;
-	tx_flags = tx_cmd->tx_flags;
-
-	/* We need to figure out how to get the sta->supp_rates while
-	 * in this running context */
-	rate_mask = IWL_RATES_MASK;
-
-
-	/* Set retry limit on DATA packets and Probe Responses*/
-	if (ieee80211_is_probe_resp(fc))
-		data_retry_limit = 3;
-	else
-		data_retry_limit = IWL_DEFAULT_TX_RETRY;
-	tx_cmd->data_retry_limit = data_retry_limit;
-
-	if (tx_id >= IWL39_CMD_QUEUE_NUM)
-		rts_retry_limit = 3;
-	else
-		rts_retry_limit = 7;
-
-	if (data_retry_limit < rts_retry_limit)
-		rts_retry_limit = data_retry_limit;
-	tx_cmd->rts_retry_limit = rts_retry_limit;
-
-	tx_cmd->rate = rate;
-	tx_cmd->tx_flags = tx_flags;
-
-	/* OFDM */
-	tx_cmd->supp_rates[0] =
-	   ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
-
-	/* CCK */
-	tx_cmd->supp_rates[1] = (rate_mask & 0xF);
-
-	IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
-		       "cck/ofdm mask: 0x%x/0x%x\n", sta_id,
-		       tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags),
-		       tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
-}
-
-static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
-{
-	unsigned long flags_spin;
-	struct iwl_station_entry *station;
-
-	if (sta_id == IWL_INVALID_STATION)
-		return IWL_INVALID_STATION;
-
-	spin_lock_irqsave(&priv->sta_lock, flags_spin);
-	station = &priv->stations[sta_id];
-
-	station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
-	station->sta.rate_n_flags = cpu_to_le16(tx_rate);
-	station->sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &station->sta, CMD_ASYNC);
-	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
-	IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
-			sta_id, tx_rate);
-	return sta_id;
-}
-
-static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
-{
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do
-
-		if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
-			iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
-					~APMG_PS_CTRL_MSK_PWR_SRC);
-
-			iwl_poll_bit(priv, CSR_GPIO_IN,
-				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
-				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
-		}
- */
-
-	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-			~APMG_PS_CTRL_MSK_PWR_SRC);
-
-	iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
-		     CSR_GPIO_IN_BIT_AUX_POWER, 5000);	/* uS */
-}
-
-static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
-	iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
-	iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
-	iwl_write_direct32(priv, FH39_RCSR_CONFIG(0),
-		FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
-		FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
-		FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
-		FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
-		(RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
-		FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
-		(1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
-		FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
-
-	/* fake read to flush all prev I/O */
-	iwl_read_direct32(priv, FH39_RSSR_CTRL);
-
-	return 0;
-}
-
-static int iwl3945_tx_reset(struct iwl_priv *priv)
-{
-
-	/* bypass mode */
-	iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
-
-	/* RA 0 is active */
-	iwl_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
-
-	/* all 6 fifo are active */
-	iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
-
-	iwl_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
-	iwl_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
-	iwl_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
-	iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
-
-	iwl_write_direct32(priv, FH39_TSSR_CBB_BASE,
-			     priv->_3945.shared_phys);
-
-	iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
-
-
-	return 0;
-}
-
-/**
- * iwl3945_txq_ctx_reset - Reset TX queue context
- *
- * Destroys all DMA structures and initialize them again
- */
-static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
-{
-	int rc;
-	int txq_id, slots_num;
-
-	iwl3945_hw_txq_ctx_free(priv);
-
-	/* allocate tx queue structure */
-	rc = iwl_alloc_txq_mem(priv);
-	if (rc)
-		return rc;
-
-	/* Tx CMD queue */
-	rc = iwl3945_tx_reset(priv);
-	if (rc)
-		goto error;
-
-	/* Tx queue(s) */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
-				TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-		rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-				       txq_id);
-		if (rc) {
-			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-			goto error;
-		}
-	}
-
-	return rc;
-
- error:
-	iwl3945_hw_txq_ctx_free(priv);
-	return rc;
-}
-
-
-/*
- * Start up 3945's basic functionality after it has been reset
- * (e.g. after platform boot, or shutdown via iwl_apm_stop())
- * NOTE:  This does not load uCode nor start the embedded processor
- */
-static int iwl3945_apm_init(struct iwl_priv *priv)
-{
-	int ret = iwl_apm_init(priv);
-
-	/* Clear APMG (NIC's internal power management) interrupts */
-	iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
-	iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
-
-	/* Reset radio chip */
-	iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
-	udelay(5);
-	iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
-
-	return ret;
-}
-
-static void iwl3945_nic_config(struct iwl_priv *priv)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	unsigned long flags;
-	u8 rev_id = 0;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Determine HW type */
-	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-
-	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
-
-	if (rev_id & PCI_CFG_REV_ID_BIT_RTP)
-		IWL_DEBUG_INFO(priv, "RTP type\n");
-	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
-		IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
-	} else {
-		IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n");
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
-	}
-
-	if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
-		IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n");
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
-	} else
-		IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n");
-
-	if ((eeprom->board_revision & 0xF0) == 0xD0) {
-		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
-			       eeprom->board_revision);
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-	} else {
-		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
-			       eeprom->board_revision);
-		iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-			      CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-	}
-
-	if (eeprom->almgor_m_version <= 1) {
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
-		IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n",
-			       eeprom->almgor_m_version);
-	} else {
-		IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n",
-			       eeprom->almgor_m_version);
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
-		IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n");
-
-	if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
-		IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n");
-}
-
-int iwl3945_hw_nic_init(struct iwl_priv *priv)
-{
-	int rc;
-	unsigned long flags;
-	struct iwl_rx_queue *rxq = &priv->rxq;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->cfg->ops->lib->apm_ops.init(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl3945_set_pwr_vmain(priv);
-
-	priv->cfg->ops->lib->apm_ops.config(priv);
-
-	/* Allocate the RX queue, or reset if it is already allocated */
-	if (!rxq->bd) {
-		rc = iwl_rx_queue_alloc(priv);
-		if (rc) {
-			IWL_ERR(priv, "Unable to initialize Rx queue\n");
-			return -ENOMEM;
-		}
-	} else
-		iwl3945_rx_queue_reset(priv, rxq);
-
-	iwl3945_rx_replenish(priv);
-
-	iwl3945_rx_init(priv, rxq);
-
-
-	/* Look at using this instead:
-	rxq->need_update = 1;
-	iwl_rx_queue_update_write_ptr(priv, rxq);
-	*/
-
-	iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
-
-	rc = iwl3945_txq_ctx_reset(priv);
-	if (rc)
-		return rc;
-
-	set_bit(STATUS_INIT, &priv->status);
-
-	return 0;
-}
-
-/**
- * iwl3945_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
-{
-	int txq_id;
-
-	/* Tx queues */
-	if (priv->txq)
-		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
-		     txq_id++)
-			if (txq_id == IWL39_CMD_QUEUE_NUM)
-				iwl_cmd_queue_free(priv);
-			else
-				iwl_tx_queue_free(priv, txq_id);
-
-	/* free tx queue structure */
-	iwl_free_txq_mem(priv);
-}
-
-void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
-{
-	int txq_id;
-
-	/* stop SCD */
-	iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
-	iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0);
-
-	/* reset TFD queues */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
-		iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
-				FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
-				1000);
-	}
-
-	iwl3945_hw_txq_ctx_free(priv);
-}
-
-/**
- * iwl3945_hw_reg_adjust_power_by_temp
- * return index delta into power gain settings table
-*/
-static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
-{
-	return (new_reading - old_reading) * (-11) / 100;
-}
-
-/**
- * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range
- */
-static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
-{
-	return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
-}
-
-int iwl3945_hw_get_temperature(struct iwl_priv *priv)
-{
-	return iwl_read32(priv, CSR_UCODE_DRV_GP2);
-}
-
-/**
- * iwl3945_hw_reg_txpower_get_temperature
- * get the current temperature by reading from NIC
-*/
-static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	int temperature;
-
-	temperature = iwl3945_hw_get_temperature(priv);
-
-	/* driver's okay range is -260 to +25.
-	 *   human readable okay range is 0 to +285 */
-	IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT);
-
-	/* handle insane temp reading */
-	if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
-		IWL_ERR(priv, "Error bad temperature value  %d\n", temperature);
-
-		/* if really really hot(?),
-		 *   substitute the 3rd band/group's temp measured at factory */
-		if (priv->last_temperature > 100)
-			temperature = eeprom->groups[2].temperature;
-		else /* else use most recent "sane" value from driver */
-			temperature = priv->last_temperature;
-	}
-
-	return temperature;	/* raw, not "human readable" */
-}
-
-/* Adjust Txpower only if temperature variance is greater than threshold.
- *
- * Both are lower than older versions' 9 degrees */
-#define IWL_TEMPERATURE_LIMIT_TIMER   6
-
-/**
- * is_temp_calib_needed - determines if new calibration is needed
- *
- * records new temperature in tx_mgr->temperature.
- * replaces tx_mgr->last_temperature *only* if calib needed
- *    (assumes caller will actually do the calibration!). */
-static int is_temp_calib_needed(struct iwl_priv *priv)
-{
-	int temp_diff;
-
-	priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
-	temp_diff = priv->temperature - priv->last_temperature;
-
-	/* get absolute value */
-	if (temp_diff < 0) {
-		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff);
-		temp_diff = -temp_diff;
-	} else if (temp_diff == 0)
-		IWL_DEBUG_POWER(priv, "Same temp,\n");
-	else
-		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff);
-
-	/* if we don't need calibration, *don't* update last_temperature */
-	if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) {
-		IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n");
-		return 0;
-	}
-
-	IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n");
-
-	/* assume that caller will actually do calib ...
-	 *   update the "last temperature" value */
-	priv->last_temperature = priv->temperature;
-	return 1;
-}
-
-#define IWL_MAX_GAIN_ENTRIES 78
-#define IWL_CCK_FROM_OFDM_POWER_DIFF  -5
-#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10)
-
-/* radio and DSP power table, each step is 1/2 dB.
- * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
-static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
-	{
-	 {251, 127},		/* 2.4 GHz, highest power */
-	 {251, 127},
-	 {251, 127},
-	 {251, 127},
-	 {251, 125},
-	 {251, 110},
-	 {251, 105},
-	 {251, 98},
-	 {187, 125},
-	 {187, 115},
-	 {187, 108},
-	 {187, 99},
-	 {243, 119},
-	 {243, 111},
-	 {243, 105},
-	 {243, 97},
-	 {243, 92},
-	 {211, 106},
-	 {211, 100},
-	 {179, 120},
-	 {179, 113},
-	 {179, 107},
-	 {147, 125},
-	 {147, 119},
-	 {147, 112},
-	 {147, 106},
-	 {147, 101},
-	 {147, 97},
-	 {147, 91},
-	 {115, 107},
-	 {235, 121},
-	 {235, 115},
-	 {235, 109},
-	 {203, 127},
-	 {203, 121},
-	 {203, 115},
-	 {203, 108},
-	 {203, 102},
-	 {203, 96},
-	 {203, 92},
-	 {171, 110},
-	 {171, 104},
-	 {171, 98},
-	 {139, 116},
-	 {227, 125},
-	 {227, 119},
-	 {227, 113},
-	 {227, 107},
-	 {227, 101},
-	 {227, 96},
-	 {195, 113},
-	 {195, 106},
-	 {195, 102},
-	 {195, 95},
-	 {163, 113},
-	 {163, 106},
-	 {163, 102},
-	 {163, 95},
-	 {131, 113},
-	 {131, 106},
-	 {131, 102},
-	 {131, 95},
-	 {99, 113},
-	 {99, 106},
-	 {99, 102},
-	 {99, 95},
-	 {67, 113},
-	 {67, 106},
-	 {67, 102},
-	 {67, 95},
-	 {35, 113},
-	 {35, 106},
-	 {35, 102},
-	 {35, 95},
-	 {3, 113},
-	 {3, 106},
-	 {3, 102},
-	 {3, 95} },		/* 2.4 GHz, lowest power */
-	{
-	 {251, 127},		/* 5.x GHz, highest power */
-	 {251, 120},
-	 {251, 114},
-	 {219, 119},
-	 {219, 101},
-	 {187, 113},
-	 {187, 102},
-	 {155, 114},
-	 {155, 103},
-	 {123, 117},
-	 {123, 107},
-	 {123, 99},
-	 {123, 92},
-	 {91, 108},
-	 {59, 125},
-	 {59, 118},
-	 {59, 109},
-	 {59, 102},
-	 {59, 96},
-	 {59, 90},
-	 {27, 104},
-	 {27, 98},
-	 {27, 92},
-	 {115, 118},
-	 {115, 111},
-	 {115, 104},
-	 {83, 126},
-	 {83, 121},
-	 {83, 113},
-	 {83, 105},
-	 {83, 99},
-	 {51, 118},
-	 {51, 111},
-	 {51, 104},
-	 {51, 98},
-	 {19, 116},
-	 {19, 109},
-	 {19, 102},
-	 {19, 98},
-	 {19, 93},
-	 {171, 113},
-	 {171, 107},
-	 {171, 99},
-	 {139, 120},
-	 {139, 113},
-	 {139, 107},
-	 {139, 99},
-	 {107, 120},
-	 {107, 113},
-	 {107, 107},
-	 {107, 99},
-	 {75, 120},
-	 {75, 113},
-	 {75, 107},
-	 {75, 99},
-	 {43, 120},
-	 {43, 113},
-	 {43, 107},
-	 {43, 99},
-	 {11, 120},
-	 {11, 113},
-	 {11, 107},
-	 {11, 99},
-	 {131, 107},
-	 {131, 99},
-	 {99, 120},
-	 {99, 113},
-	 {99, 107},
-	 {99, 99},
-	 {67, 120},
-	 {67, 113},
-	 {67, 107},
-	 {67, 99},
-	 {35, 120},
-	 {35, 113},
-	 {35, 107},
-	 {35, 99},
-	 {3, 120} }		/* 5.x GHz, lowest power */
-};
-
-static inline u8 iwl3945_hw_reg_fix_power_index(int index)
-{
-	if (index < 0)
-		return 0;
-	if (index >= IWL_MAX_GAIN_ENTRIES)
-		return IWL_MAX_GAIN_ENTRIES - 1;
-	return (u8) index;
-}
-
-/* Kick off thermal recalibration check every 60 seconds */
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
- *
- * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
- * or 6 Mbit (OFDM) rates.
- */
-static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
-			       s32 rate_index, const s8 *clip_pwrs,
-			       struct iwl_channel_info *ch_info,
-			       int band_index)
-{
-	struct iwl3945_scan_power_info *scan_power_info;
-	s8 power;
-	u8 power_index;
-
-	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index];
-
-	/* use this channel group's 6Mbit clipping/saturation pwr,
-	 *   but cap at regulatory scan power restriction (set during init
-	 *   based on eeprom channel data) for this channel.  */
-	power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
-
-	/* further limit to user's max power preference.
-	 * FIXME:  Other spectrum management power limitations do not
-	 *   seem to apply?? */
-	power = min(power, priv->tx_power_user_lmt);
-	scan_power_info->requested_power = power;
-
-	/* find difference between new scan *power* and current "normal"
-	 *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
-	 *   current "normal" temperature-compensated Tx power *index* for
-	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
-	 *   *index*. */
-	power_index = ch_info->power_info[rate_index].power_table_index
-	    - (power - ch_info->power_info
-	       [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
-
-	/* store reference index that we use when adjusting *all* scan
-	 *   powers.  So we can accommodate user (all channel) or spectrum
-	 *   management (single channel) power changes "between" temperature
-	 *   feedback compensation procedures.
-	 * don't force fit this reference index into gain table; it may be a
-	 *   negative number.  This will help avoid errors when we're at
-	 *   the lower bounds (highest gains, for warmest temperatures)
-	 *   of the table. */
-
-	/* don't exceed table bounds for "real" setting */
-	power_index = iwl3945_hw_reg_fix_power_index(power_index);
-
-	scan_power_info->power_table_index = power_index;
-	scan_power_info->tpc.tx_gain =
-	    power_gain_table[band_index][power_index].tx_gain;
-	scan_power_info->tpc.dsp_atten =
-	    power_gain_table[band_index][power_index].dsp_atten;
-}
-
-/**
- * iwl3945_send_tx_power - fill in Tx Power command with gain settings
- *
- * Configures power settings for all rates for the current channel,
- * using values from channel info struct, and send to NIC
- */
-static int iwl3945_send_tx_power(struct iwl_priv *priv)
-{
-	int rate_idx, i;
-	const struct iwl_channel_info *ch_info = NULL;
-	struct iwl3945_txpowertable_cmd txpower = {
-		.channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
-	};
-	u16 chan;
-
-	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
-		      "TX Power requested while scanning!\n"))
-		return -EAGAIN;
-
-	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
-
-	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
-	ch_info = iwl_get_channel_info(priv, priv->band, chan);
-	if (!ch_info) {
-		IWL_ERR(priv,
-			"Failed to get channel info for channel %d [%d]\n",
-			chan, priv->band);
-		return -EINVAL;
-	}
-
-	if (!is_channel_valid(ch_info)) {
-		IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on "
-				"non-Tx channel.\n");
-		return 0;
-	}
-
-	/* fill cmd with power settings for all rates for current channel */
-	/* Fill OFDM rate */
-	for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
-	     rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) {
-
-		txpower.power[i].tpc = ch_info->power_info[i].tpc;
-		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
-
-		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
-				le16_to_cpu(txpower.channel),
-				txpower.band,
-				txpower.power[i].tpc.tx_gain,
-				txpower.power[i].tpc.dsp_atten,
-				txpower.power[i].rate);
-	}
-	/* Fill CCK rates */
-	for (rate_idx = IWL_FIRST_CCK_RATE;
-	     rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
-		txpower.power[i].tpc = ch_info->power_info[i].tpc;
-		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
-
-		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
-				le16_to_cpu(txpower.channel),
-				txpower.band,
-				txpower.power[i].tpc.tx_gain,
-				txpower.power[i].tpc.dsp_atten,
-				txpower.power[i].rate);
-	}
-
-	return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
-				sizeof(struct iwl3945_txpowertable_cmd),
-				&txpower);
-
-}
-
-/**
- * iwl3945_hw_reg_set_new_power - Configures power tables at new levels
- * @ch_info: Channel to update.  Uses power_info.requested_power.
- *
- * Replace requested_power and base_power_index ch_info fields for
- * one channel.
- *
- * Called if user or spectrum management changes power preferences.
- * Takes into account h/w and modulation limitations (clip power).
- *
- * This does *not* send anything to NIC, just sets up ch_info for one channel.
- *
- * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
- *	 properly fill out the scan powers, and actual h/w gain settings,
- *	 and send changes to NIC
- */
-static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
-			     struct iwl_channel_info *ch_info)
-{
-	struct iwl3945_channel_power_info *power_info;
-	int power_changed = 0;
-	int i;
-	const s8 *clip_pwrs;
-	int power;
-
-	/* Get this chnlgrp's rate-to-max/clip-powers table */
-	clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-	/* Get this channel's rate-to-current-power settings table */
-	power_info = ch_info->power_info;
-
-	/* update OFDM Txpower settings */
-	for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
-	     i++, ++power_info) {
-		int delta_idx;
-
-		/* limit new power to be no more than h/w capability */
-		power = min(ch_info->curr_txpow, clip_pwrs[i]);
-		if (power == power_info->requested_power)
-			continue;
-
-		/* find difference between old and new requested powers,
-		 *    update base (non-temp-compensated) power index */
-		delta_idx = (power - power_info->requested_power) * 2;
-		power_info->base_power_index -= delta_idx;
-
-		/* save new requested power value */
-		power_info->requested_power = power;
-
-		power_changed = 1;
-	}
-
-	/* update CCK Txpower settings, based on OFDM 12M setting ...
-	 *    ... all CCK power settings for a given channel are the *same*. */
-	if (power_changed) {
-		power =
-		    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
-		    requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
-
-		/* do all CCK rates' iwl3945_channel_power_info structures */
-		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
-			power_info->requested_power = power;
-			power_info->base_power_index =
-			    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
-			    base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
-			++power_info;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
- *
- * NOTE: Returned power limit may be less (but not more) than requested,
- *	 based strictly on regulatory (eeprom and spectrum mgt) limitations
- *	 (no consideration for h/w clipping limitations).
- */
-static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
-{
-	s8 max_power;
-
-#if 0
-	/* if we're using TGd limits, use lower of TGd or EEPROM */
-	if (ch_info->tgd_data.max_power != 0)
-		max_power = min(ch_info->tgd_data.max_power,
-				ch_info->eeprom.max_power_avg);
-
-	/* else just use EEPROM limits */
-	else
-#endif
-		max_power = ch_info->eeprom.max_power_avg;
-
-	return min(max_power, ch_info->max_power_avg);
-}
-
-/**
- * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature
- *
- * Compensate txpower settings of *all* channels for temperature.
- * This only accounts for the difference between current temperature
- *   and the factory calibration temperatures, and bases the new settings
- *   on the channel's base_power_index.
- *
- * If RxOn is "associated", this sends the new Txpower to NIC!
- */
-static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
-{
-	struct iwl_channel_info *ch_info = NULL;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	int delta_index;
-	const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
-	u8 a_band;
-	u8 rate_index;
-	u8 scan_tbl_index;
-	u8 i;
-	int ref_temp;
-	int temperature = priv->temperature;
-
-	if (priv->disable_tx_power_cal ||
-	    test_bit(STATUS_SCANNING, &priv->status)) {
-		/* do not perform tx power calibration */
-		return 0;
-	}
-	/* set up new Tx power info for each and every channel, 2.4 and 5.x */
-	for (i = 0; i < priv->channel_count; i++) {
-		ch_info = &priv->channel_info[i];
-		a_band = is_channel_a_band(ch_info);
-
-		/* Get this chnlgrp's factory calibration temperature */
-		ref_temp = (s16)eeprom->groups[ch_info->group_index].
-		    temperature;
-
-		/* get power index adjustment based on current and factory
-		 * temps */
-		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-							      ref_temp);
-
-		/* set tx power value for all rates, OFDM and CCK */
-		for (rate_index = 0; rate_index < IWL_RATE_COUNT;
-		     rate_index++) {
-			int power_idx =
-			    ch_info->power_info[rate_index].base_power_index;
-
-			/* temperature compensate */
-			power_idx += delta_index;
-
-			/* stay within table range */
-			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
-			ch_info->power_info[rate_index].
-			    power_table_index = (u8) power_idx;
-			ch_info->power_info[rate_index].tpc =
-			    power_gain_table[a_band][power_idx];
-		}
-
-		/* Get this chnlgrp's rate-to-max/clip-powers table */
-		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
-		for (scan_tbl_index = 0;
-		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
-			s32 actual_index = (scan_tbl_index == 0) ?
-			    IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
-			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
-					   actual_index, clip_pwrs,
-					   ch_info, a_band);
-		}
-	}
-
-	/* send Txpower command for current channel to ucode */
-	return priv->cfg->ops->lib->send_tx_power(priv);
-}
-
-int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
-{
-	struct iwl_channel_info *ch_info;
-	s8 max_power;
-	u8 a_band;
-	u8 i;
-
-	if (priv->tx_power_user_lmt == power) {
-		IWL_DEBUG_POWER(priv, "Requested Tx power same as current "
-				"limit: %ddBm.\n", power);
-		return 0;
-	}
-
-	IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power);
-	priv->tx_power_user_lmt = power;
-
-	/* set up new Tx powers for each and every channel, 2.4 and 5.x */
-
-	for (i = 0; i < priv->channel_count; i++) {
-		ch_info = &priv->channel_info[i];
-		a_band = is_channel_a_band(ch_info);
-
-		/* find minimum power of all user and regulatory constraints
-		 *    (does not consider h/w clipping limitations) */
-		max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info);
-		max_power = min(power, max_power);
-		if (max_power != ch_info->curr_txpow) {
-			ch_info->curr_txpow = max_power;
-
-			/* this considers the h/w clipping limitations */
-			iwl3945_hw_reg_set_new_power(priv, ch_info);
-		}
-	}
-
-	/* update txpower settings for all channels,
-	 *   send to NIC if associated. */
-	is_temp_calib_needed(priv);
-	iwl3945_hw_reg_comp_txpower_temp(priv);
-
-	return 0;
-}
-
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
-				   struct iwl_rxon_context *ctx)
-{
-	int rc = 0;
-	struct iwl_rx_packet *pkt;
-	struct iwl3945_rxon_assoc_cmd rxon_assoc;
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_RXON_ASSOC,
-		.len = sizeof(rxon_assoc),
-		.flags = CMD_WANT_SKB,
-		.data = &rxon_assoc,
-	};
-	const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
-	const struct iwl_rxon_cmd *rxon2 = &ctx->active;
-
-	if ((rxon1->flags == rxon2->flags) &&
-	    (rxon1->filter_flags == rxon2->filter_flags) &&
-	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
-		return 0;
-	}
-
-	rxon_assoc.flags = ctx->staging.flags;
-	rxon_assoc.filter_flags = ctx->staging.filter_flags;
-	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
-	rxon_assoc.reserved = 0;
-
-	rc = iwl_send_cmd_sync(priv, &cmd);
-	if (rc)
-		return rc;
-
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
-		rc = -EIO;
-	}
-
-	iwl_free_pages(priv, cmd.reply_page);
-
-	return rc;
-}
-
-/**
- * iwl3945_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed to the hardware and
- * the active_rxon structure is updated with the new data.  This
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
-int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
-	struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
-	int rc = 0;
-	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return -EINVAL;
-
-	if (!iwl_is_alive(priv))
-		return -1;
-
-	/* always get timestamp with Rx frame */
-	staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
-
-	/* select antenna */
-	staging_rxon->flags &=
-	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
-	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
-
-	rc = iwl_check_rxon_cmd(priv, ctx);
-	if (rc) {
-		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-		return -EINVAL;
-	}
-
-	/* If we don't need to send a full RXON, we can use
-	 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
-	 * and other flags for the current radio configuration. */
-	if (!iwl_full_rxon_required(priv, &priv->contexts[IWL_RXON_CTX_BSS])) {
-		rc = iwl_send_rxon_assoc(priv,
-					 &priv->contexts[IWL_RXON_CTX_BSS]);
-		if (rc) {
-			IWL_ERR(priv, "Error setting RXON_ASSOC "
-				  "configuration (%d).\n", rc);
-			return rc;
-		}
-
-		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-		return 0;
-	}
-
-	/* If we are currently associated and the new config requires
-	 * an RXON_ASSOC and the new config wants the associated mask enabled,
-	 * we must clear the associated from the active configuration
-	 * before we apply the new config */
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && new_assoc) {
-		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-		/*
-		 * reserved4 and 5 could have been filled by the iwlcore code.
-		 * Let's clear them before pushing to the 3945.
-		 */
-		active_rxon->reserved4 = 0;
-		active_rxon->reserved5 = 0;
-		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-				      sizeof(struct iwl3945_rxon_cmd),
-				      &priv->contexts[IWL_RXON_CTX_BSS].active);
-
-		/* If the mask clearing failed then we set
-		 * active_rxon back to what it was previously */
-		if (rc) {
-			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-			IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
-				  "configuration (%d).\n", rc);
-			return rc;
-		}
-		iwl_clear_ucode_stations(priv,
-					 &priv->contexts[IWL_RXON_CTX_BSS]);
-		iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
-	}
-
-	IWL_DEBUG_INFO(priv, "Sending RXON\n"
-		       "* with%s RXON_FILTER_ASSOC_MSK\n"
-		       "* channel = %d\n"
-		       "* bssid = %pM\n",
-		       (new_assoc ? "" : "out"),
-		       le16_to_cpu(staging_rxon->channel),
-		       staging_rxon->bssid_addr);
-
-	/*
-	 * reserved4 and 5 could have been filled by the iwlcore code.
-	 * Let's clear them before pushing to the 3945.
-	 */
-	staging_rxon->reserved4 = 0;
-	staging_rxon->reserved5 = 0;
-
-	iwl_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
-
-	/* Apply the new configuration */
-	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
-			      sizeof(struct iwl3945_rxon_cmd),
-			      staging_rxon);
-	if (rc) {
-		IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
-		return rc;
-	}
-
-	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
-
-	if (!new_assoc) {
-		iwl_clear_ucode_stations(priv,
-					 &priv->contexts[IWL_RXON_CTX_BSS]);
-		iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
-	}
-
-	/* If we issue a new RXON command which required a tune then we must
-	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	rc = priv->cfg->ops->lib->send_tx_power(priv);
-	if (rc) {
-		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
-		return rc;
-	}
-
-	/* Init the hardware's rate fallback order based on the band */
-	rc = iwl3945_init_hw_rate_table(priv);
-	if (rc) {
-		IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/**
- * iwl3945_reg_txpower_periodic -  called when time to check our temperature.
- *
- * -- reset periodic timer
- * -- see if temp has changed enough to warrant re-calibration ... if so:
- *     -- correct coeffs for temp (can reset temp timer)
- *     -- save this temp as "last",
- *     -- send new set of gain settings to NIC
- * NOTE:  This should continue working, even when we're not associated,
- *   so we can keep our internal table of scan powers current. */
-void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
-{
-	/* This will kick in the "brute force"
-	 * iwl3945_hw_reg_comp_txpower_temp() below */
-	if (!is_temp_calib_needed(priv))
-		goto reschedule;
-
-	/* Set up a new set of temp-adjusted TxPowers, send to NIC.
-	 * This is based *only* on current temperature,
-	 * ignoring any previous power measurements */
-	iwl3945_hw_reg_comp_txpower_temp(priv);
-
- reschedule:
-	queue_delayed_work(priv->workqueue,
-			   &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
-}
-
-static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-					     _3945.thermal_periodic.work);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_reg_txpower_periodic(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-/**
- * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
- * 				   for the channel.
- *
- * This function is used when initializing channel-info structs.
- *
- * NOTE: These channel groups do *NOT* match the bands above!
- *	 These channel groups are based on factory-tested channels;
- *	 on A-band, EEPROM's "group frequency" entries represent the top
- *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0.
- */
-static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
-				       const struct iwl_channel_info *ch_info)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
-	u8 group;
-	u16 group_index = 0;	/* based on factory calib frequencies */
-	u8 grp_channel;
-
-	/* Find the group index for the channel ... don't use index 1(?) */
-	if (is_channel_a_band(ch_info)) {
-		for (group = 1; group < 5; group++) {
-			grp_channel = ch_grp[group].group_channel;
-			if (ch_info->channel <= grp_channel) {
-				group_index = group;
-				break;
-			}
-		}
-		/* group 4 has a few channels *above* its factory cal freq */
-		if (group == 5)
-			group_index = 4;
-	} else
-		group_index = 0;	/* 2.4 GHz, group 0 */
-
-	IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel,
-			group_index);
-	return group_index;
-}
-
-/**
- * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index
- *
- * Interpolate to get nominal (i.e. at factory calibration temperature) index
- *   into radio/DSP gain settings table for requested power.
- */
-static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv,
-				       s8 requested_power,
-				       s32 setting_index, s32 *new_index)
-{
-	const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	s32 index0, index1;
-	s32 power = 2 * requested_power;
-	s32 i;
-	const struct iwl3945_eeprom_txpower_sample *samples;
-	s32 gains0, gains1;
-	s32 res;
-	s32 denominator;
-
-	chnl_grp = &eeprom->groups[setting_index];
-	samples = chnl_grp->samples;
-	for (i = 0; i < 5; i++) {
-		if (power == samples[i].power) {
-			*new_index = samples[i].gain_index;
-			return 0;
-		}
-	}
-
-	if (power > samples[1].power) {
-		index0 = 0;
-		index1 = 1;
-	} else if (power > samples[2].power) {
-		index0 = 1;
-		index1 = 2;
-	} else if (power > samples[3].power) {
-		index0 = 2;
-		index1 = 3;
-	} else {
-		index0 = 3;
-		index1 = 4;
-	}
-
-	denominator = (s32) samples[index1].power - (s32) samples[index0].power;
-	if (denominator == 0)
-		return -EINVAL;
-	gains0 = (s32) samples[index0].gain_index * (1 << 19);
-	gains1 = (s32) samples[index1].gain_index * (1 << 19);
-	res = gains0 + (gains1 - gains0) *
-	    ((s32) power - (s32) samples[index0].power) / denominator +
-	    (1 << 18);
-	*new_index = res >> 19;
-	return 0;
-}
-
-static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
-{
-	u32 i;
-	s32 rate_index;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	const struct iwl3945_eeprom_txpower_group *group;
-
-	IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n");
-
-	for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {
-		s8 *clip_pwrs;	/* table of power levels for each rate */
-		s8 satur_pwr;	/* saturation power for each chnl group */
-		group = &eeprom->groups[i];
-
-		/* sanity check on factory saturation power value */
-		if (group->saturation_power < 40) {
-			IWL_WARN(priv, "Error: saturation power is %d, "
-				    "less than minimum expected 40\n",
-				    group->saturation_power);
-			return;
-		}
-
-		/*
-		 * Derive requested power levels for each rate, based on
-		 *   hardware capabilities (saturation power for band).
-		 * Basic value is 3dB down from saturation, with further
-		 *   power reductions for highest 3 data rates.  These
-		 *   backoffs provide headroom for high rate modulation
-		 *   power peaks, without too much distortion (clipping).
-		 */
-		/* we'll fill in this array with h/w max power levels */
-		clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
-
-		/* divide factory saturation power by 2 to find -3dB level */
-		satur_pwr = (s8) (group->saturation_power >> 1);
-
-		/* fill in channel group's nominal powers for each rate */
-		for (rate_index = 0;
-		     rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) {
-			switch (rate_index) {
-			case IWL_RATE_36M_INDEX_TABLE:
-				if (i == 0)	/* B/G */
-					*clip_pwrs = satur_pwr;
-				else	/* A */
-					*clip_pwrs = satur_pwr - 5;
-				break;
-			case IWL_RATE_48M_INDEX_TABLE:
-				if (i == 0)
-					*clip_pwrs = satur_pwr - 7;
-				else
-					*clip_pwrs = satur_pwr - 10;
-				break;
-			case IWL_RATE_54M_INDEX_TABLE:
-				if (i == 0)
-					*clip_pwrs = satur_pwr - 9;
-				else
-					*clip_pwrs = satur_pwr - 12;
-				break;
-			default:
-				*clip_pwrs = satur_pwr;
-				break;
-			}
-		}
-	}
-}
-
-/**
- * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
- *
- * Second pass (during init) to set up priv->channel_info
- *
- * Set up Tx-power settings in our channel info database for each VALID
- * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
- * and current temperature.
- *
- * Since this is based on current temperature (at init time), these values may
- * not be valid for very long, but it gives us a starting/default point,
- * and allows us to active (i.e. using Tx) scan.
- *
- * This does *not* write values to NIC, just sets up our internal table.
- */
-int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
-{
-	struct iwl_channel_info *ch_info = NULL;
-	struct iwl3945_channel_power_info *pwr_info;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	int delta_index;
-	u8 rate_index;
-	u8 scan_tbl_index;
-	const s8 *clip_pwrs;	/* array of power levels for each rate */
-	u8 gain, dsp_atten;
-	s8 power;
-	u8 pwr_index, base_pwr_index, a_band;
-	u8 i;
-	int temperature;
-
-	/* save temperature reference,
-	 *   so we can determine next time to calibrate */
-	temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
-	priv->last_temperature = temperature;
-
-	iwl3945_hw_reg_init_channel_groups(priv);
-
-	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
-	for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
-	     i++, ch_info++) {
-		a_band = is_channel_a_band(ch_info);
-		if (!is_channel_valid(ch_info))
-			continue;
-
-		/* find this channel's channel group (*not* "band") index */
-		ch_info->group_index =
-			iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
-
-		/* Get this chnlgrp's rate->max/clip-powers table */
-		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-		/* calculate power index *adjustment* value according to
-		 *  diff between current temperature and factory temperature */
-		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-				eeprom->groups[ch_info->group_index].
-				temperature);
-
-		IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n",
-				ch_info->channel, delta_index, temperature +
-				IWL_TEMP_CONVERT);
-
-		/* set tx power value for all OFDM rates */
-		for (rate_index = 0; rate_index < IWL_OFDM_RATES;
-		     rate_index++) {
-			s32 uninitialized_var(power_idx);
-			int rc;
-
-			/* use channel group's clip-power table,
-			 *   but don't exceed channel's max power */
-			s8 pwr = min(ch_info->max_power_avg,
-				     clip_pwrs[rate_index]);
-
-			pwr_info = &ch_info->power_info[rate_index];
-
-			/* get base (i.e. at factory-measured temperature)
-			 *    power table index for this rate's power */
-			rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr,
-							 ch_info->group_index,
-							 &power_idx);
-			if (rc) {
-				IWL_ERR(priv, "Invalid power index\n");
-				return rc;
-			}
-			pwr_info->base_power_index = (u8) power_idx;
-
-			/* temperature compensate */
-			power_idx += delta_index;
-
-			/* stay within range of gain table */
-			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
-
-			/* fill 1 OFDM rate's iwl3945_channel_power_info struct */
-			pwr_info->requested_power = pwr;
-			pwr_info->power_table_index = (u8) power_idx;
-			pwr_info->tpc.tx_gain =
-			    power_gain_table[a_band][power_idx].tx_gain;
-			pwr_info->tpc.dsp_atten =
-			    power_gain_table[a_band][power_idx].dsp_atten;
-		}
-
-		/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
-		pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
-		power = pwr_info->requested_power +
-			IWL_CCK_FROM_OFDM_POWER_DIFF;
-		pwr_index = pwr_info->power_table_index +
-			IWL_CCK_FROM_OFDM_INDEX_DIFF;
-		base_pwr_index = pwr_info->base_power_index +
-			IWL_CCK_FROM_OFDM_INDEX_DIFF;
-
-		/* stay within table range */
-		pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index);
-		gain = power_gain_table[a_band][pwr_index].tx_gain;
-		dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;
-
-		/* fill each CCK rate's iwl3945_channel_power_info structure
-		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
-		 * NOTE:  CCK rates start at end of OFDM rates! */
-		for (rate_index = 0;
-		     rate_index < IWL_CCK_RATES; rate_index++) {
-			pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
-			pwr_info->requested_power = power;
-			pwr_info->power_table_index = pwr_index;
-			pwr_info->base_power_index = base_pwr_index;
-			pwr_info->tpc.tx_gain = gain;
-			pwr_info->tpc.dsp_atten = dsp_atten;
-		}
-
-		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
-		for (scan_tbl_index = 0;
-		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
-			s32 actual_index = (scan_tbl_index == 0) ?
-				IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
-			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
-				actual_index, clip_pwrs, ch_info, a_band);
-		}
-	}
-
-	return 0;
-}
-
-int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
-{
-	int rc;
-
-	iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
-	rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
-			FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-	if (rc < 0)
-		IWL_ERR(priv, "Can't stop Rx DMA.\n");
-
-	return 0;
-}
-
-int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	int txq_id = txq->q.id;
-
-	struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
-
-	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
-
-	iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
-	iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
-
-	iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id),
-		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
-		FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
-		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
-		FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
-		FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
-
-	/* fake read to flush all prev. writes */
-	iwl_read32(priv, FH39_TSSR_CBB_BASE);
-
-	return 0;
-}
-
-/*
- * HCMD utils
- */
-static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
-{
-	switch (cmd_id) {
-	case REPLY_RXON:
-		return sizeof(struct iwl3945_rxon_cmd);
-	case POWER_TABLE_CMD:
-		return sizeof(struct iwl3945_powertable_cmd);
-	default:
-		return len;
-	}
-}
-
-
-static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
-	struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data;
-	addsta->mode = cmd->mode;
-	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
-	memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
-	addsta->station_flags = cmd->station_flags;
-	addsta->station_flags_msk = cmd->station_flags_msk;
-	addsta->tid_disable_tx = cpu_to_le16(0);
-	addsta->rate_n_flags = cmd->rate_n_flags;
-	addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
-	addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
-	addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
-
-	return (u16)sizeof(struct iwl3945_addsta_cmd);
-}
-
-static int iwl3945_add_bssid_station(struct iwl_priv *priv,
-				     const u8 *addr, u8 *sta_id_r)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	int ret;
-	u8 sta_id;
-	unsigned long flags;
-
-	if (sta_id_r)
-		*sta_id_r = IWL_INVALID_STATION;
-
-	ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
-	if (ret) {
-		IWL_ERR(priv, "Unable to add station %pM\n", addr);
-		return ret;
-	}
-
-	if (sta_id_r)
-		*sta_id_r = sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations[sta_id].used |= IWL_STA_LOCAL;
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return 0;
-}
-static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
-				       struct ieee80211_vif *vif, bool add)
-{
-	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-	int ret;
-
-	if (add) {
-		ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
-						&vif_priv->ibss_bssid_sta_id);
-		if (ret)
-			return ret;
-
-		iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
-				 (priv->band == IEEE80211_BAND_5GHZ) ?
-				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
-		iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
-
-		return 0;
-	}
-
-	return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
-				  vif->bss_conf.bssid);
-}
-
-/**
- * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
- */
-int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
-{
-	int rc, i, index, prev_index;
-	struct iwl3945_rate_scaling_cmd rate_cmd = {
-		.reserved = {0, 0, 0},
-	};
-	struct iwl3945_rate_scaling_info *table = rate_cmd.table;
-
-	for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) {
-		index = iwl3945_rates[i].table_rs_index;
-
-		table[index].rate_n_flags =
-			iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
-		table[index].try_cnt = priv->retry_rate;
-		prev_index = iwl3945_get_prev_ieee_rate(i);
-		table[index].next_rate_index =
-				iwl3945_rates[prev_index].table_rs_index;
-	}
-
-	switch (priv->band) {
-	case IEEE80211_BAND_5GHZ:
-		IWL_DEBUG_RATE(priv, "Select A mode rate scale\n");
-		/* If one of the following CCK rates is used,
-		 * have it fall back to the 6M OFDM rate */
-		for (i = IWL_RATE_1M_INDEX_TABLE;
-			i <= IWL_RATE_11M_INDEX_TABLE; i++)
-			table[i].next_rate_index =
-			  iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
-
-		/* Don't fall back to CCK rates */
-		table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
-						IWL_RATE_9M_INDEX_TABLE;
-
-		/* Don't drop out of OFDM rates */
-		table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
-		    iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
-		break;
-
-	case IEEE80211_BAND_2GHZ:
-		IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n");
-		/* If an OFDM rate is used, have it fall back to the
-		 * 1M CCK rates */
-
-		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-		    iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-
-			index = IWL_FIRST_CCK_RATE;
-			for (i = IWL_RATE_6M_INDEX_TABLE;
-			     i <= IWL_RATE_54M_INDEX_TABLE; i++)
-				table[i].next_rate_index =
-					iwl3945_rates[index].table_rs_index;
-
-			index = IWL_RATE_11M_INDEX_TABLE;
-			/* CCK shouldn't fall back to OFDM... */
-			table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
-		}
-		break;
-
-	default:
-		WARN_ON(1);
-		break;
-	}
-
-	/* Update the rate scaling for control frame Tx */
-	rate_cmd.table_id = 0;
-	rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
-			      &rate_cmd);
-	if (rc)
-		return rc;
-
-	/* Update the rate scaling for data frame Tx */
-	rate_cmd.table_id = 1;
-	return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
-				&rate_cmd);
-}
-
-/* Called when initializing driver */
-int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
-{
-	memset((void *)&priv->hw_params, 0,
-	       sizeof(struct iwl_hw_params));
-
-	priv->_3945.shared_virt =
-		dma_alloc_coherent(&priv->pci_dev->dev,
-				   sizeof(struct iwl3945_shared),
-				   &priv->_3945.shared_phys, GFP_KERNEL);
-	if (!priv->_3945.shared_virt) {
-		IWL_ERR(priv, "failed to allocate pci memory\n");
-		return -ENOMEM;
-	}
-
-	/* Assign number of Usable TX queues */
-	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-
-	priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
-	priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
-	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
-	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-	priv->hw_params.max_stations = IWL3945_STATION_COUNT;
-	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
-
-	priv->sta_key_max_num = STA_KEY_MAX_NUM;
-
-	priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
-	priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
-	priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;
-
-	return 0;
-}
-
-unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
-			  struct iwl3945_frame *frame, u8 rate)
-{
-	struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
-	unsigned int frame_size;
-
-	tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
-	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
-
-	tx_beacon_cmd->tx.sta_id =
-		priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-	frame_size = iwl3945_fill_beacon_frame(priv,
-				tx_beacon_cmd->frame,
-				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
-
-	BUG_ON(frame_size > MAX_MPDU_SIZE);
-	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
-
-	tx_beacon_cmd->tx.rate = rate;
-	tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
-				      TX_CMD_FLG_TSF_MSK);
-
-	/* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
-	tx_beacon_cmd->tx.supp_rates[0] =
-		(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-
-	tx_beacon_cmd->tx.supp_rates[1] =
-		(IWL_CCK_BASIC_RATES_MASK & 0xF);
-
-	return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
-}
-
-void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
-{
-	priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
-	priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
-}
-
-void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
-{
-	INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
-			  iwl3945_bg_reg_txpower_periodic);
-}
-
-void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
-{
-	cancel_delayed_work(&priv->_3945.thermal_periodic);
-}
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl3945_verify_bsm(struct iwl_priv *priv)
- {
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	u32 reg;
-	u32 val;
-
-	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
-
-	/* verify BSM SRAM contents */
-	val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
-	for (reg = BSM_SRAM_LOWER_BOUND;
-	     reg < BSM_SRAM_LOWER_BOUND + len;
-	     reg += sizeof(u32), image++) {
-		val = iwl_read_prph(priv, reg);
-		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(priv, "BSM uCode verification failed at "
-				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-				  BSM_SRAM_LOWER_BOUND,
-				  reg - BSM_SRAM_LOWER_BOUND, len,
-				  val, le32_to_cpu(*image));
-			return -EIO;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
-
-	return 0;
-}
-
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
- ******************************************************************************/
-
-/*
- * Clear the OWNER_MSK, to establish driver (instead of uCode running on
- * embedded controller) as EEPROM reader; each read is a series of pulses
- * to/from the EEPROM chip, not a single event, so even reads could conflict
- * if they weren't arbitrated by some ownership mechanism.  Here, the driver
- * simply claims ownership, which should be safe when this function is called
- * (i.e. before loading uCode!).
- */
-static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
-	_iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
-	return 0;
-}
-
-
-static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv)
-{
-	return;
-}
-
- /**
-  * iwl3945_load_bsm - Load bootstrap instructions
-  *
-  * BSM operation:
-  *
-  * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
-  * in special SRAM that does not power down during RFKILL.  When powering back
-  * up after power-saving sleeps (or during initial uCode load), the BSM loads
-  * the bootstrap program into the on-board processor, and starts it.
-  *
-  * The bootstrap program loads (via DMA) instructions and data for a new
-  * program from host DRAM locations indicated by the host driver in the
-  * BSM_DRAM_* registers.  Once the new program is loaded, it starts
-  * automatically.
-  *
-  * When initializing the NIC, the host driver points the BSM to the
-  * "initialize" uCode image.  This uCode sets up some internal data, then
-  * notifies host via "initialize alive" that it is complete.
-  *
-  * The host then replaces the BSM_DRAM_* pointer values to point to the
-  * normal runtime uCode instructions and a backup uCode data cache buffer
-  * (filled initially with starting data values for the on-board processor),
-  * then triggers the "initialize" uCode to load and launch the runtime uCode,
-  * which begins normal operation.
-  *
-  * When doing a power-save shutdown, runtime uCode saves data SRAM into
-  * the backup data cache in DRAM before SRAM is powered down.
-  *
-  * When powering back up, the BSM loads the bootstrap program.  This reloads
-  * the runtime uCode instructions and the backup data cache into SRAM,
-  * and re-launches the runtime uCode from where it left off.
-  */
-static int iwl3945_load_bsm(struct iwl_priv *priv)
-{
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-	u32 inst_len;
-	u32 data_len;
-	int rc;
-	int i;
-	u32 done;
-	u32 reg_offset;
-
-	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
-
-	/* make sure bootstrap program is no larger than BSM's SRAM size */
-	if (len > IWL39_MAX_BSM_SIZE)
-		return -EINVAL;
-
-	/* Tell bootstrap uCode where to find the "Initialize" uCode
-	*   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
-	* NOTE:  iwl3945_initialize_alive_start() will replace these values,
-	*        after the "initialize" uCode has run, to point to
-	*        runtime/protocol instructions and backup data cache. */
-	pinst = priv->ucode_init.p_addr;
-	pdata = priv->ucode_init_data.p_addr;
-	inst_len = priv->ucode_init.len;
-	data_len = priv->ucode_init_data.len;
-
-	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-
-	/* Fill BSM memory with bootstrap instructions */
-	for (reg_offset = BSM_SRAM_LOWER_BOUND;
-	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
-	     reg_offset += sizeof(u32), image++)
-		_iwl_write_prph(priv, reg_offset,
-					  le32_to_cpu(*image));
-
-	rc = iwl3945_verify_bsm(priv);
-	if (rc)
-		return rc;
-
-	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-	iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-	iwl_write_prph(priv, BSM_WR_MEM_DST_REG,
-				 IWL39_RTC_INST_LOWER_BOUND);
-	iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-	/* Load bootstrap code into instruction SRAM now,
-	 *   to prepare to load "initialize" uCode */
-	iwl_write_prph(priv, BSM_WR_CTRL_REG,
-		BSM_WR_CTRL_REG_BIT_START);
-
-	/* Wait for load of bootstrap uCode to finish */
-	for (i = 0; i < 100; i++) {
-		done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
-		if (!(done & BSM_WR_CTRL_REG_BIT_START))
-			break;
-		udelay(10);
-	}
-	if (i < 100)
-		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
-	else {
-		IWL_ERR(priv, "BSM write did not complete!\n");
-		return -EIO;
-	}
-
-	/* Enable future boot loads whenever power management unit triggers it
-	 *   (e.g. when powering back up after power-save shutdown) */
-	iwl_write_prph(priv, BSM_WR_CTRL_REG,
-		BSM_WR_CTRL_REG_BIT_START_EN);
-
-	return 0;
-}
-
-static struct iwl_hcmd_ops iwl3945_hcmd = {
-	.rxon_assoc = iwl3945_send_rxon_assoc,
-	.commit_rxon = iwl3945_commit_rxon,
-	.send_bt_config = iwl_send_bt_config,
-};
-
-static struct iwl_lib_ops iwl3945_lib = {
-	.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
-	.txq_free_tfd = iwl3945_hw_txq_free_tfd,
-	.txq_init = iwl3945_hw_tx_queue_init,
-	.load_ucode = iwl3945_load_bsm,
-	.dump_nic_event_log = iwl3945_dump_nic_event_log,
-	.dump_nic_error_log = iwl3945_dump_nic_error_log,
-	.apm_ops = {
-		.init = iwl3945_apm_init,
-		.config = iwl3945_nic_config,
-	},
-	.eeprom_ops = {
-		.regulatory_bands = {
-			EEPROM_REGULATORY_BAND_1_CHANNELS,
-			EEPROM_REGULATORY_BAND_2_CHANNELS,
-			EEPROM_REGULATORY_BAND_3_CHANNELS,
-			EEPROM_REGULATORY_BAND_4_CHANNELS,
-			EEPROM_REGULATORY_BAND_5_CHANNELS,
-			EEPROM_REGULATORY_BAND_NO_HT40,
-			EEPROM_REGULATORY_BAND_NO_HT40,
-		},
-		.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
-		.release_semaphore = iwl3945_eeprom_release_semaphore,
-		.query_addr = iwlcore_eeprom_query_addr,
-	},
-	.send_tx_power	= iwl3945_send_tx_power,
-	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
-	.isr_ops = {
-		.isr = iwl_isr_legacy,
-	},
-
-	.debugfs_ops = {
-		.rx_stats_read = iwl3945_ucode_rx_stats_read,
-		.tx_stats_read = iwl3945_ucode_tx_stats_read,
-		.general_stats_read = iwl3945_ucode_general_stats_read,
-	},
-};
-
-static const struct iwl_legacy_ops iwl3945_legacy_ops = {
-	.post_associate = iwl3945_post_associate,
-	.config_ap = iwl3945_config_ap,
-	.manage_ibss_station = iwl3945_manage_ibss_station,
-};
-
-static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
-	.get_hcmd_size = iwl3945_get_hcmd_size,
-	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
-	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
-	.request_scan = iwl3945_request_scan,
-	.post_scan = iwl3945_post_scan,
-};
-
-static const struct iwl_ops iwl3945_ops = {
-	.lib = &iwl3945_lib,
-	.hcmd = &iwl3945_hcmd,
-	.utils = &iwl3945_hcmd_utils,
-	.led = &iwl3945_led_ops,
-	.legacy = &iwl3945_legacy_ops,
-	.ieee80211_ops = &iwl3945_hw_ops,
-};
-
-static struct iwl_base_params iwl3945_base_params = {
-	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
-	.num_of_queues = IWL39_NUM_QUEUES,
-	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
-	.set_l0s = false,
-	.use_bsm = true,
-	.use_isr_legacy = true,
-	.led_compensation = 64,
-	.broken_powersave = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.tx_power_by_driver = true,
-};
-
-static struct iwl_cfg iwl3945_bg_cfg = {
-	.name = "3945BG",
-	.fw_name_pre = IWL3945_FW_PRE,
-	.ucode_api_max = IWL3945_UCODE_API_MAX,
-	.ucode_api_min = IWL3945_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-	.ops = &iwl3945_ops,
-	.mod_params = &iwl3945_mod_params,
-	.base_params = &iwl3945_base_params,
-	.led_mode = IWL_LED_BLINK,
-};
-
-static struct iwl_cfg iwl3945_abg_cfg = {
-	.name = "3945ABG",
-	.fw_name_pre = IWL3945_FW_PRE,
-	.ucode_api_max = IWL3945_UCODE_API_MAX,
-	.ucode_api_min = IWL3945_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-	.ops = &iwl3945_ops,
-	.mod_params = &iwl3945_mod_params,
-	.base_params = &iwl3945_base_params,
-	.led_mode = IWL_LED_BLINK,
-};
-
-DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
-	{IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
-	{IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
deleted file mode 100644
index 3eef1eb..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 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
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945.h) for driver implementation definitions.
- * Please use iwl-3945-commands.h for uCode API definitions.
- * Please use iwl-3945-hw.h for hardware-related definitions.
- */
-
-#ifndef __iwl_3945_h__
-#define __iwl_3945_h__
-
-#include <linux/pci.h> /* for struct pci_device_id */
-#include <linux/kernel.h>
-#include <net/ieee80211_radiotap.h>
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-extern const struct pci_device_id iwl3945_hw_card_ids[];
-
-#include "iwl-csr.h"
-#include "iwl-prph.h"
-#include "iwl-fh.h"
-#include "iwl-3945-hw.h"
-#include "iwl-debug.h"
-#include "iwl-power.h"
-#include "iwl-dev.h"
-#include "iwl-led.h"
-
-/* Highest firmware API version supported */
-#define IWL3945_UCODE_API_MAX 2
-
-/* Lowest firmware API version supported */
-#define IWL3945_UCODE_API_MIN 1
-
-#define IWL3945_FW_PRE	"iwlwifi-3945-"
-#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
-#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
-
-/* Default noise level to report when noise measurement is not available.
- *   This may be because we're:
- *   1)  Not associated (4965, no beacon statistics being sent to driver)
- *   2)  Scanning (noise measurement does not apply to associated channel)
- *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
- * Use default noise value of -127 ... this is below the range of measurable
- *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
- *   Also, -127 works better than 0 when averaging frames with/without
- *   noise info (e.g. averaging might be done in app); measured dBm values are
- *   always negative ... using a negative value as the default keeps all
- *   averages within an s8's (used in some apps) range of negative values. */
-#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
-
-/* Module parameters accessible from iwl-*.c */
-extern struct iwl_mod_params iwl3945_mod_params;
-
-struct iwl3945_rate_scale_data {
-	u64 data;
-	s32 success_counter;
-	s32 success_ratio;
-	s32 counter;
-	s32 average_tpt;
-	unsigned long stamp;
-};
-
-struct iwl3945_rs_sta {
-	spinlock_t lock;
-	struct iwl_priv *priv;
-	s32 *expected_tpt;
-	unsigned long last_partial_flush;
-	unsigned long last_flush;
-	u32 flush_time;
-	u32 last_tx_packets;
-	u32 tx_packets;
-	u8 tgg;
-	u8 flush_pending;
-	u8 start_rate;
-	struct timer_list rate_scale_flush;
-	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
-#ifdef CONFIG_MAC80211_DEBUGFS
-	struct dentry *rs_sta_dbgfs_stats_table_file;
-#endif
-
-	/* used to be in sta_info */
-	int last_txrate_idx;
-};
-
-
-/*
- * The common struct MUST be first because it is shared between
- * 3945 and agn!
- */
-struct iwl3945_sta_priv {
-	struct iwl_station_priv_common common;
-	struct iwl3945_rs_sta rs_sta;
-};
-
-enum iwl3945_antenna {
-	IWL_ANTENNA_DIVERSITY,
-	IWL_ANTENNA_MAIN,
-	IWL_ANTENNA_AUX
-};
-
-/*
- * RTS threshold here is total size [2347] minus 4 FCS bytes
- * Per spec:
- *   a value of 0 means RTS on all data/management packets
- *   a value > max MSDU size means no RTS
- * else RTS for data/management frames where MPDU is larger
- *   than RTS value.
- */
-#define DEFAULT_RTS_THRESHOLD     2347U
-#define MIN_RTS_THRESHOLD         0U
-#define MAX_RTS_THRESHOLD         2347U
-#define MAX_MSDU_SIZE		  2304U
-#define MAX_MPDU_SIZE		  2346U
-#define DEFAULT_BEACON_INTERVAL   100U
-#define	DEFAULT_SHORT_RETRY_LIMIT 7U
-#define	DEFAULT_LONG_RETRY_LIMIT  4U
-
-#define IWL_TX_FIFO_AC0	0
-#define IWL_TX_FIFO_AC1	1
-#define IWL_TX_FIFO_AC2	2
-#define IWL_TX_FIFO_AC3	3
-#define IWL_TX_FIFO_HCCA_1	5
-#define IWL_TX_FIFO_HCCA_2	6
-#define IWL_TX_FIFO_NONE	7
-
-#define IEEE80211_DATA_LEN              2304
-#define IEEE80211_4ADDR_LEN             30
-#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
-#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct iwl3945_frame {
-	union {
-		struct ieee80211_hdr frame;
-		struct iwl3945_tx_beacon_cmd beacon;
-		u8 raw[IEEE80211_FRAME_LEN];
-		u8 cmd[360];
-	} u;
-	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
-
-#define IWL_SUPPORTED_RATES_IE_LEN         8
-
-#define SCAN_INTERVAL 100
-
-#define MAX_TID_COUNT        9
-
-#define IWL_INVALID_RATE     0xFF
-#define IWL_INVALID_VALUE    -1
-
-#define STA_PS_STATUS_WAKE             0
-#define STA_PS_STATUS_SLEEP            1
-
-struct iwl3945_ibss_seq {
-	u8 mac[ETH_ALEN];
-	u16 seq_num;
-	u16 frag_num;
-	unsigned long packet_time;
-	struct list_head list;
-};
-
-#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
-		       x->u.rx_frame.stats.payload + \
-		       x->u.rx_frame.stats.phy_count))
-#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
-		       IWL_RX_HDR(x)->payload + \
-		       le16_to_cpu(IWL_RX_HDR(x)->len)))
-#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
-#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
-
-
-/******************************************************************************
- *
- * Functions implemented in iwl-base.c which are forward declared here
- * for use by iwl-*.c
- *
- *****************************************************************************/
-extern int iwl3945_calc_db_from_ratio(int sig_ratio);
-extern void iwl3945_rx_replenish(void *data);
-extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
-					struct ieee80211_hdr *hdr,int left);
-extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-				       char **buf, bool display);
-extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
-
-/******************************************************************************
- *
- * Functions implemented in iwl-[34]*.c which are forward declared here
- * for use by iwl-base.c
- *
- * NOTE:  The implementation of these functions are hardware specific
- * which is why they are in the hardware specific files (vs. iwl-base.c)
- *
- * Naming convention --
- * iwl3945_         <-- Its part of iwlwifi (should be changed to iwl3945_)
- * iwl3945_hw_      <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
- * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
- * iwl3945_bg_      <-- Called from work queue context
- * iwl3945_mac_     <-- mac80211 callback
- *
- ****************************************************************************/
-extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
-extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
-extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
-extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
-extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
-extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
-extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
-extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-					    struct iwl_tx_queue *txq,
-					    dma_addr_t addr, u16 len,
-					    u8 reset, u8 pad);
-extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
-				    struct iwl_tx_queue *txq);
-extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
-extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
-				struct iwl_tx_queue *txq);
-extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
-				 struct iwl3945_frame *frame, u8 rate);
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-				  struct iwl_device_cmd *cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr,
-				  int sta_id, int tx_id);
-extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
-extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
-extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
-				 struct iwl_rx_mem_buffer *rxb);
-void iwl3945_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb);
-extern void iwl3945_disable_events(struct iwl_priv *priv);
-extern int iwl4965_get_temperature(const struct iwl_priv *priv);
-extern void iwl3945_post_associate(struct iwl_priv *priv);
-extern void iwl3945_config_ap(struct iwl_priv *priv);
-
-extern int iwl3945_commit_rxon(struct iwl_priv *priv,
-			       struct iwl_rxon_context *ctx);
-
-/**
- * iwl3945_hw_find_station - Find station id for a given BSSID
- * @bssid: MAC address of station ID to find
- *
- * NOTE:  This should not be hardware specific but the code has
- * not yet been merged into a single common layer for managing the
- * station tables.
- */
-extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
-
-extern struct ieee80211_ops iwl3945_hw_ops;
-
-/*
- * Forward declare iwl-3945.c functions for iwl-base.c
- */
-extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
-extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
-extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
-extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
-
-extern const struct iwl_channel_info *iwl3945_get_channel_info(
-	const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
-
-extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
-
-/* scanning */
-int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl3945_post_scan(struct iwl_priv *priv);
-
-/* rates */
-extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
-
-/* Requires full declaration of iwl_priv before including */
-#include "iwl-io.h"
-
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
deleted file mode 100644
index 9166794..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ /dev/null
@@ -1,792 +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) 2005 - 2010 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 - 2010 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.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
- * Use iwl-commands.h for uCode API definitions.
- * Use iwl-dev.h for driver implementation definitions.
- */
-
-#ifndef __iwl_4965_hw_h__
-#define __iwl_4965_hw_h__
-
-#include "iwl-fh.h"
-
-/* EEPROM */
-#define IWL4965_EEPROM_IMG_SIZE			1024
-
-/*
- * uCode queue management definitions ...
- * The first queue used for block-ack aggregation is #7 (4965 only).
- * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
- */
-#define IWL49_FIRST_AMPDU_QUEUE	7
-
-/* Sizes and addresses for instruction and data memory (SRAM) in
- * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define IWL49_RTC_INST_LOWER_BOUND		(0x000000)
-#define IWL49_RTC_INST_UPPER_BOUND		(0x018000)
-
-#define IWL49_RTC_DATA_LOWER_BOUND		(0x800000)
-#define IWL49_RTC_DATA_UPPER_BOUND		(0x80A000)
-
-#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - \
-				IWL49_RTC_INST_LOWER_BOUND)
-#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - \
-				IWL49_RTC_DATA_LOWER_BOUND)
-
-#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
-#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
-
-/* Size of uCode instruction memory in bootstrap state machine */
-#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
-
-static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
-{
-	return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
-	       (addr < IWL49_RTC_DATA_UPPER_BOUND);
-}
-
-/********************* START TEMPERATURE *************************************/
-
-/**
- * 4965 temperature calculation.
- *
- * The driver must calculate the device temperature before calculating
- * a txpower setting (amplifier gain is temperature dependent).  The
- * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
- * values used for the life of the driver, and one of which (R4) is the
- * real-time temperature indicator.
- *
- * uCode provides all 4 values to the driver via the "initialize alive"
- * notification (see struct iwl4965_init_alive_resp).  After the runtime uCode
- * image loads, uCode updates the R4 value via statistics notifications
- * (see STATISTICS_NOTIFICATION), which occur after each received beacon
- * when associated, or can be requested via REPLY_STATISTICS_CMD.
- *
- * NOTE:  uCode provides the R4 value as a 23-bit signed value.  Driver
- *        must sign-extend to 32 bits before applying formula below.
- *
- * Formula:
- *
- * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
- *
- * NOTE:  The basic formula is 259 * (R4-R2) / (R3-R1).  The 97/100 is
- * an additional correction, which should be centered around 0 degrees
- * Celsius (273 degrees Kelvin).  The 8 (3 percent of 273) compensates for
- * centering the 97/100 correction around 0 degrees K.
- *
- * Add 273 to Kelvin value to find degrees Celsius, for comparing current
- * temperature with factory-measured temperatures when calculating txpower
- * settings.
- */
-#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
-#define TEMPERATURE_CALIB_A_VAL 259
-
-/* Limit range of calculated temperature to be between these Kelvin values */
-#define IWL_TX_POWER_TEMPERATURE_MIN  (263)
-#define IWL_TX_POWER_TEMPERATURE_MAX  (410)
-
-#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
-	(((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
-	 ((t) > IWL_TX_POWER_TEMPERATURE_MAX))
-
-/********************* END TEMPERATURE ***************************************/
-
-/********************* START TXPOWER *****************************************/
-
-/**
- * 4965 txpower calculations rely on information from three sources:
- *
- *     1) EEPROM
- *     2) "initialize" alive notification
- *     3) statistics notifications
- *
- * EEPROM data consists of:
- *
- * 1)  Regulatory information (max txpower and channel usage flags) is provided
- *     separately for each channel that can possibly supported by 4965.
- *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
- *     (legacy) channels.
- *
- *     See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
- *     for locations in EEPROM.
- *
- * 2)  Factory txpower calibration information is provided separately for
- *     sub-bands of contiguous channels.  2.4GHz has just one sub-band,
- *     but 5 GHz has several sub-bands.
- *
- *     In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
- *
- *     See struct iwl4965_eeprom_calib_info (and the tree of structures
- *     contained within it) for format, and struct iwl4965_eeprom for
- *     locations in EEPROM.
- *
- * "Initialization alive" notification (see struct iwl4965_init_alive_resp)
- * consists of:
- *
- * 1)  Temperature calculation parameters.
- *
- * 2)  Power supply voltage measurement.
- *
- * 3)  Tx gain compensation to balance 2 transmitters for MIMO use.
- *
- * Statistics notifications deliver:
- *
- * 1)  Current values for temperature param R4.
- */
-
-/**
- * To calculate a txpower setting for a given desired target txpower, channel,
- * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
- * support MIMO and transmit diversity), driver must do the following:
- *
- * 1)  Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
- *     Do not exceed regulatory limit; reduce target txpower if necessary.
- *
- *     If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
- *     2 transmitters will be used simultaneously; driver must reduce the
- *     regulatory limit by 3 dB (half-power) for each transmitter, so the
- *     combined total output of the 2 transmitters is within regulatory limits.
- *
- *
- * 2)  Compare target txpower vs. (EEPROM) saturation txpower *reduced by
- *     backoff for this bit rate*.  Do not exceed (saturation - backoff[rate]);
- *     reduce target txpower if necessary.
- *
- *     Backoff values below are in 1/2 dB units (equivalent to steps in
- *     txpower gain tables):
- *
- *     OFDM 6 - 36 MBit:  10 steps (5 dB)
- *     OFDM 48 MBit:      15 steps (7.5 dB)
- *     OFDM 54 MBit:      17 steps (8.5 dB)
- *     OFDM 60 MBit:      20 steps (10 dB)
- *     CCK all rates:     10 steps (5 dB)
- *
- *     Backoff values apply to saturation txpower on a per-transmitter basis;
- *     when using MIMO (2 transmitters), each transmitter uses the same
- *     saturation level provided in EEPROM, and the same backoff values;
- *     no reduction (such as with regulatory txpower limits) is required.
- *
- *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
- *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
- *     factory measurement for ht40 channels.
- *
- *     The result of this step is the final target txpower.  The rest of
- *     the steps figure out the proper settings for the device to achieve
- *     that target txpower.
- *
- *
- * 3)  Determine (EEPROM) calibration sub band for the target channel, by
- *     comparing against first and last channels in each sub band
- *     (see struct iwl4965_eeprom_calib_subband_info).
- *
- *
- * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
- *     referencing the 2 factory-measured (sample) channels within the sub band.
- *
- *     Interpolation is based on difference between target channel's frequency
- *     and the sample channels' frequencies.  Since channel numbers are based
- *     on frequency (5 MHz between each channel number), this is equivalent
- *     to interpolating based on channel number differences.
- *
- *     Note that the sample channels may or may not be the channels at the
- *     edges of the sub band.  The target channel may be "outside" of the
- *     span of the sampled channels.
- *
- *     Driver may choose the pair (for 2 Tx chains) of measurements (see
- *     struct iwl4965_eeprom_calib_ch_info) for which the actual measured
- *     txpower comes closest to the desired txpower.  Usually, though,
- *     the middle set of measurements is closest to the regulatory limits,
- *     and is therefore a good choice for all txpower calculations (this
- *     assumes that high accuracy is needed for maximizing legal txpower,
- *     while lower txpower configurations do not need as much accuracy).
- *
- *     Driver should interpolate both members of the chosen measurement pair,
- *     i.e. for both Tx chains (radio transmitters), unless the driver knows
- *     that only one of the chains will be used (e.g. only one tx antenna
- *     connected, but this should be unusual).  The rate scaling algorithm
- *     switches antennas to find best performance, so both Tx chains will
- *     be used (although only one at a time) even for non-MIMO transmissions.
- *
- *     Driver should interpolate factory values for temperature, gain table
- *     index, and actual power.  The power amplifier detector values are
- *     not used by the driver.
- *
- *     Sanity check:  If the target channel happens to be one of the sample
- *     channels, the results should agree with the sample channel's
- *     measurements!
- *
- *
- * 5)  Find difference between desired txpower and (interpolated)
- *     factory-measured txpower.  Using (interpolated) factory gain table index
- *     (shown elsewhere) as a starting point, adjust this index lower to
- *     increase txpower, or higher to decrease txpower, until the target
- *     txpower is reached.  Each step in the gain table is 1/2 dB.
- *
- *     For example, if factory measured txpower is 16 dBm, and target txpower
- *     is 13 dBm, add 6 steps to the factory gain index to reduce txpower
- *     by 3 dB.
- *
- *
- * 6)  Find difference between current device temperature and (interpolated)
- *     factory-measured temperature for sub-band.  Factory values are in
- *     degrees Celsius.  To calculate current temperature, see comments for
- *     "4965 temperature calculation".
- *
- *     If current temperature is higher than factory temperature, driver must
- *     increase gain (lower gain table index), and vice verse.
- *
- *     Temperature affects gain differently for different channels:
- *
- *     2.4 GHz all channels:  3.5 degrees per half-dB step
- *     5 GHz channels 34-43:  4.5 degrees per half-dB step
- *     5 GHz channels >= 44:  4.0 degrees per half-dB step
- *
- *     NOTE:  Temperature can increase rapidly when transmitting, especially
- *            with heavy traffic at high txpowers.  Driver should update
- *            temperature calculations often under these conditions to
- *            maintain strong txpower in the face of rising temperature.
- *
- *
- * 7)  Find difference between current power supply voltage indicator
- *     (from "initialize alive") and factory-measured power supply voltage
- *     indicator (EEPROM).
- *
- *     If the current voltage is higher (indicator is lower) than factory
- *     voltage, gain should be reduced (gain table index increased) by:
- *
- *     (eeprom - current) / 7
- *
- *     If the current voltage is lower (indicator is higher) than factory
- *     voltage, gain should be increased (gain table index decreased) by:
- *
- *     2 * (current - eeprom) / 7
- *
- *     If number of index steps in either direction turns out to be > 2,
- *     something is wrong ... just use 0.
- *
- *     NOTE:  Voltage compensation is independent of band/channel.
- *
- *     NOTE:  "Initialize" uCode measures current voltage, which is assumed
- *            to be constant after this initial measurement.  Voltage
- *            compensation for txpower (number of steps in gain table)
- *            may be calculated once and used until the next uCode bootload.
- *
- *
- * 8)  If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
- *     adjust txpower for each transmitter chain, so txpower is balanced
- *     between the two chains.  There are 5 pairs of tx_atten[group][chain]
- *     values in "initialize alive", one pair for each of 5 channel ranges:
- *
- *     Group 0:  5 GHz channel 34-43
- *     Group 1:  5 GHz channel 44-70
- *     Group 2:  5 GHz channel 71-124
- *     Group 3:  5 GHz channel 125-200
- *     Group 4:  2.4 GHz all channels
- *
- *     Add the tx_atten[group][chain] value to the index for the target chain.
- *     The values are signed, but are in pairs of 0 and a non-negative number,
- *     so as to reduce gain (if necessary) of the "hotter" channel.  This
- *     avoids any need to double-check for regulatory compliance after
- *     this step.
- *
- *
- * 9)  If setting up for a CCK rate, lower the gain by adding a CCK compensation
- *     value to the index:
- *
- *     Hardware rev B:  9 steps (4.5 dB)
- *     Hardware rev C:  5 steps (2.5 dB)
- *
- *     Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
- *     bits [3:2], 1 = B, 2 = C.
- *
- *     NOTE:  This compensation is in addition to any saturation backoff that
- *            might have been applied in an earlier step.
- *
- *
- * 10) Select the gain table, based on band (2.4 vs 5 GHz).
- *
- *     Limit the adjusted index to stay within the table!
- *
- *
- * 11) Read gain table entries for DSP and radio gain, place into appropriate
- *     location(s) in command (struct iwl4965_txpowertable_cmd).
- */
-
-/**
- * When MIMO is used (2 transmitters operating simultaneously), driver should
- * limit each transmitter to deliver a max of 3 dB below the regulatory limit
- * for the device.  That is, use half power for each transmitter, so total
- * txpower is within regulatory limits.
- *
- * The value "6" represents number of steps in gain table to reduce power 3 dB.
- * Each step is 1/2 dB.
- */
-#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
-
-/**
- * CCK gain compensation.
- *
- * When calculating txpowers for CCK, after making sure that the target power
- * is within regulatory and saturation limits, driver must additionally
- * back off gain by adding these values to the gain table index.
- *
- * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
- * bits [3:2], 1 = B, 2 = C.
- */
-#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
-#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
-
-/*
- * 4965 power supply voltage compensation for txpower
- */
-#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V   (7)
-
-/**
- * Gain tables.
- *
- * The following tables contain pair of values for setting txpower, i.e.
- * gain settings for the output of the device's digital signal processor (DSP),
- * and for the analog gain structure of the transmitter.
- *
- * Each entry in the gain tables represents a step of 1/2 dB.  Note that these
- * are *relative* steps, not indications of absolute output power.  Output
- * power varies with temperature, voltage, and channel frequency, and also
- * requires consideration of average power (to satisfy regulatory constraints),
- * and peak power (to avoid distortion of the output signal).
- *
- * Each entry contains two values:
- * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
- *     linear value that multiplies the output of the digital signal processor,
- *     before being sent to the analog radio.
- * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
- *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
- *
- * EEPROM contains factory calibration data for txpower.  This maps actual
- * measured txpower levels to gain settings in the "well known" tables
- * below ("well-known" means here that both factory calibration *and* the
- * driver work with the same table).
- *
- * There are separate tables for 2.4 GHz and 5 GHz bands.  The 5 GHz table
- * has an extension (into negative indexes), in case the driver needs to
- * boost power setting for high device temperatures (higher than would be
- * present during factory calibration).  A 5 Ghz EEPROM index of "40"
- * corresponds to the 49th entry in the table used by the driver.
- */
-#define MIN_TX_GAIN_INDEX		(0)  /* highest gain, lowest idx, 2.4 */
-#define MIN_TX_GAIN_INDEX_52GHZ_EXT	(-9) /* highest gain, lowest idx, 5 */
-
-/**
- * 2.4 GHz gain table
- *
- * Index    Dsp gain   Radio gain
- *   0        110         0x3f      (highest gain)
- *   1        104         0x3f
- *   2         98         0x3f
- *   3        110         0x3e
- *   4        104         0x3e
- *   5         98         0x3e
- *   6        110         0x3d
- *   7        104         0x3d
- *   8         98         0x3d
- *   9        110         0x3c
- *  10        104         0x3c
- *  11         98         0x3c
- *  12        110         0x3b
- *  13        104         0x3b
- *  14         98         0x3b
- *  15        110         0x3a
- *  16        104         0x3a
- *  17         98         0x3a
- *  18        110         0x39
- *  19        104         0x39
- *  20         98         0x39
- *  21        110         0x38
- *  22        104         0x38
- *  23         98         0x38
- *  24        110         0x37
- *  25        104         0x37
- *  26         98         0x37
- *  27        110         0x36
- *  28        104         0x36
- *  29         98         0x36
- *  30        110         0x35
- *  31        104         0x35
- *  32         98         0x35
- *  33        110         0x34
- *  34        104         0x34
- *  35         98         0x34
- *  36        110         0x33
- *  37        104         0x33
- *  38         98         0x33
- *  39        110         0x32
- *  40        104         0x32
- *  41         98         0x32
- *  42        110         0x31
- *  43        104         0x31
- *  44         98         0x31
- *  45        110         0x30
- *  46        104         0x30
- *  47         98         0x30
- *  48        110          0x6
- *  49        104          0x6
- *  50         98          0x6
- *  51        110          0x5
- *  52        104          0x5
- *  53         98          0x5
- *  54        110          0x4
- *  55        104          0x4
- *  56         98          0x4
- *  57        110          0x3
- *  58        104          0x3
- *  59         98          0x3
- *  60        110          0x2
- *  61        104          0x2
- *  62         98          0x2
- *  63        110          0x1
- *  64        104          0x1
- *  65         98          0x1
- *  66        110          0x0
- *  67        104          0x0
- *  68         98          0x0
- *  69         97            0
- *  70         96            0
- *  71         95            0
- *  72         94            0
- *  73         93            0
- *  74         92            0
- *  75         91            0
- *  76         90            0
- *  77         89            0
- *  78         88            0
- *  79         87            0
- *  80         86            0
- *  81         85            0
- *  82         84            0
- *  83         83            0
- *  84         82            0
- *  85         81            0
- *  86         80            0
- *  87         79            0
- *  88         78            0
- *  89         77            0
- *  90         76            0
- *  91         75            0
- *  92         74            0
- *  93         73            0
- *  94         72            0
- *  95         71            0
- *  96         70            0
- *  97         69            0
- *  98         68            0
- */
-
-/**
- * 5 GHz gain table
- *
- * Index    Dsp gain   Radio gain
- *  -9 	      123         0x3F      (highest gain)
- *  -8 	      117         0x3F
- *  -7        110         0x3F
- *  -6        104         0x3F
- *  -5         98         0x3F
- *  -4        110         0x3E
- *  -3        104         0x3E
- *  -2         98         0x3E
- *  -1        110         0x3D
- *   0        104         0x3D
- *   1         98         0x3D
- *   2        110         0x3C
- *   3        104         0x3C
- *   4         98         0x3C
- *   5        110         0x3B
- *   6        104         0x3B
- *   7         98         0x3B
- *   8        110         0x3A
- *   9        104         0x3A
- *  10         98         0x3A
- *  11        110         0x39
- *  12        104         0x39
- *  13         98         0x39
- *  14        110         0x38
- *  15        104         0x38
- *  16         98         0x38
- *  17        110         0x37
- *  18        104         0x37
- *  19         98         0x37
- *  20        110         0x36
- *  21        104         0x36
- *  22         98         0x36
- *  23        110         0x35
- *  24        104         0x35
- *  25         98         0x35
- *  26        110         0x34
- *  27        104         0x34
- *  28         98         0x34
- *  29        110         0x33
- *  30        104         0x33
- *  31         98         0x33
- *  32        110         0x32
- *  33        104         0x32
- *  34         98         0x32
- *  35        110         0x31
- *  36        104         0x31
- *  37         98         0x31
- *  38        110         0x30
- *  39        104         0x30
- *  40         98         0x30
- *  41        110         0x25
- *  42        104         0x25
- *  43         98         0x25
- *  44        110         0x24
- *  45        104         0x24
- *  46         98         0x24
- *  47        110         0x23
- *  48        104         0x23
- *  49         98         0x23
- *  50        110         0x22
- *  51        104         0x18
- *  52         98         0x18
- *  53        110         0x17
- *  54        104         0x17
- *  55         98         0x17
- *  56        110         0x16
- *  57        104         0x16
- *  58         98         0x16
- *  59        110         0x15
- *  60        104         0x15
- *  61         98         0x15
- *  62        110         0x14
- *  63        104         0x14
- *  64         98         0x14
- *  65        110         0x13
- *  66        104         0x13
- *  67         98         0x13
- *  68        110         0x12
- *  69        104         0x08
- *  70         98         0x08
- *  71        110         0x07
- *  72        104         0x07
- *  73         98         0x07
- *  74        110         0x06
- *  75        104         0x06
- *  76         98         0x06
- *  77        110         0x05
- *  78        104         0x05
- *  79         98         0x05
- *  80        110         0x04
- *  81        104         0x04
- *  82         98         0x04
- *  83        110         0x03
- *  84        104         0x03
- *  85         98         0x03
- *  86        110         0x02
- *  87        104         0x02
- *  88         98         0x02
- *  89        110         0x01
- *  90        104         0x01
- *  91         98         0x01
- *  92        110         0x00
- *  93        104         0x00
- *  94         98         0x00
- *  95         93         0x00
- *  96         88         0x00
- *  97         83         0x00
- *  98         78         0x00
- */
-
-
-/**
- * Sanity checks and default values for EEPROM regulatory levels.
- * If EEPROM values fall outside MIN/MAX range, use default values.
- *
- * Regulatory limits refer to the maximum average txpower allowed by
- * regulatory agencies in the geographies in which the device is meant
- * to be operated.  These limits are SKU-specific (i.e. geography-specific),
- * and channel-specific; each channel has an individual regulatory limit
- * listed in the EEPROM.
- *
- * Units are in half-dBm (i.e. "34" means 17 dBm).
- */
-#define IWL_TX_POWER_DEFAULT_REGULATORY_24   (34)
-#define IWL_TX_POWER_DEFAULT_REGULATORY_52   (34)
-#define IWL_TX_POWER_REGULATORY_MIN          (0)
-#define IWL_TX_POWER_REGULATORY_MAX          (34)
-
-/**
- * Sanity checks and default values for EEPROM saturation levels.
- * If EEPROM values fall outside MIN/MAX range, use default values.
- *
- * Saturation is the highest level that the output power amplifier can produce
- * without significant clipping distortion.  This is a "peak" power level.
- * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
- * require differing amounts of backoff, relative to their average power output,
- * in order to avoid clipping distortion.
- *
- * Driver must make sure that it is violating neither the saturation limit,
- * nor the regulatory limit, when calculating Tx power settings for various
- * rates.
- *
- * Units are in half-dBm (i.e. "38" means 19 dBm).
- */
-#define IWL_TX_POWER_DEFAULT_SATURATION_24   (38)
-#define IWL_TX_POWER_DEFAULT_SATURATION_52   (38)
-#define IWL_TX_POWER_SATURATION_MIN          (20)
-#define IWL_TX_POWER_SATURATION_MAX          (50)
-
-/**
- * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
- * and thermal Txpower calibration.
- *
- * When calculating txpower, driver must compensate for current device
- * temperature; higher temperature requires higher gain.  Driver must calculate
- * current temperature (see "4965 temperature calculation"), then compare vs.
- * factory calibration temperature in EEPROM; if current temperature is higher
- * than factory temperature, driver must *increase* gain by proportions shown
- * in table below.  If current temperature is lower than factory, driver must
- * *decrease* gain.
- *
- * Different frequency ranges require different compensation, as shown below.
- */
-/* Group 0, 5.2 GHz ch 34-43:  4.5 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
-#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
-
-/* Group 1, 5.3 GHz ch 44-70:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
-#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
-
-/* Group 2, 5.5 GHz ch 71-124:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
-#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
-
-/* Group 3, 5.7 GHz ch 125-200:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
-#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
-
-/* Group 4, 2.4 GHz all channels:  3.5 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
-#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
-
-enum {
-	CALIB_CH_GROUP_1 = 0,
-	CALIB_CH_GROUP_2 = 1,
-	CALIB_CH_GROUP_3 = 2,
-	CALIB_CH_GROUP_4 = 3,
-	CALIB_CH_GROUP_5 = 4,
-	CALIB_CH_GROUP_MAX
-};
-
-/********************* END TXPOWER *****************************************/
-
-
-/**
- * Tx/Rx Queues
- *
- * Most communication between driver and 4965 is via queues of data buffers.
- * For example, all commands that the driver issues to device's embedded
- * controller (uCode) are via the command queue (one of the Tx queues).  All
- * uCode command responses/replies/notifications, including Rx frames, are
- * conveyed from uCode to driver via the Rx queue.
- *
- * Most support for these queues, including handshake support, resides in
- * structures in host DRAM, shared between the driver and the device.  When
- * allocating this memory, the driver must make sure that data written by
- * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
- * cache memory), so DRAM and cache are consistent, and the device can
- * immediately see changes made by the driver.
- *
- * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
- * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
- * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
- */
-#define IWL49_NUM_FIFOS 	7
-#define IWL49_CMD_FIFO_NUM	4
-#define IWL49_NUM_QUEUES	16
-#define IWL49_NUM_AMPDU_QUEUES	8
-
-
-/**
- * struct iwl4965_schedq_bc_tbl
- *
- * Byte Count table
- *
- * Each Tx queue uses a byte-count table containing 320 entries:
- * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
- * duplicate the first 64 entries (to avoid wrap-around within a Tx window;
- * max Tx window is 64 TFDs).
- *
- * When driver sets up a new TFD, it must also enter the total byte count
- * of the frame to be transmitted into the corresponding entry in the byte
- * count table for the chosen Tx queue.  If the TFD index is 0-63, the driver
- * must duplicate the byte count entry in corresponding index 256-319.
- *
- * padding puts each byte count table on a 1024-byte boundary;
- * 4965 assumes tables are separated by 1024 bytes.
- */
-struct iwl4965_scd_bc_tbl {
-	__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
-	u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
-} __packed;
-
-#endif /* !__iwl_4965_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
deleted file mode 100644
index 91a9f52..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ /dev/null
@@ -1,2645 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 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/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-agn-calib.h"
-#include "iwl-sta.h"
-#include "iwl-agn-led.h"
-#include "iwl-agn.h"
-#include "iwl-agn-debugfs.h"
-#include "iwl-legacy.h"
-
-static int iwl4965_send_tx_power(struct iwl_priv *priv);
-static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
-
-/* Highest firmware API version supported */
-#define IWL4965_UCODE_API_MAX 2
-
-/* Lowest firmware API version supported */
-#define IWL4965_UCODE_API_MIN 2
-
-#define IWL4965_FW_PRE "iwlwifi-4965-"
-#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
-#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl4965_verify_bsm(struct iwl_priv *priv)
-{
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	u32 reg;
-	u32 val;
-
-	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
-
-	/* verify BSM SRAM contents */
-	val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
-	for (reg = BSM_SRAM_LOWER_BOUND;
-	     reg < BSM_SRAM_LOWER_BOUND + len;
-	     reg += sizeof(u32), image++) {
-		val = iwl_read_prph(priv, reg);
-		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(priv, "BSM uCode verification failed at "
-				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-				  BSM_SRAM_LOWER_BOUND,
-				  reg - BSM_SRAM_LOWER_BOUND, len,
-				  val, le32_to_cpu(*image));
-			return -EIO;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
-
-	return 0;
-}
-
-/**
- * iwl4965_load_bsm - Load bootstrap instructions
- *
- * BSM operation:
- *
- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
- * in special SRAM that does not power down during RFKILL.  When powering back
- * up after power-saving sleeps (or during initial uCode load), the BSM loads
- * the bootstrap program into the on-board processor, and starts it.
- *
- * The bootstrap program loads (via DMA) instructions and data for a new
- * program from host DRAM locations indicated by the host driver in the
- * BSM_DRAM_* registers.  Once the new program is loaded, it starts
- * automatically.
- *
- * When initializing the NIC, the host driver points the BSM to the
- * "initialize" uCode image.  This uCode sets up some internal data, then
- * notifies host via "initialize alive" that it is complete.
- *
- * The host then replaces the BSM_DRAM_* pointer values to point to the
- * normal runtime uCode instructions and a backup uCode data cache buffer
- * (filled initially with starting data values for the on-board processor),
- * then triggers the "initialize" uCode to load and launch the runtime uCode,
- * which begins normal operation.
- *
- * When doing a power-save shutdown, runtime uCode saves data SRAM into
- * the backup data cache in DRAM before SRAM is powered down.
- *
- * When powering back up, the BSM loads the bootstrap program.  This reloads
- * the runtime uCode instructions and the backup data cache into SRAM,
- * and re-launches the runtime uCode from where it left off.
- */
-static int iwl4965_load_bsm(struct iwl_priv *priv)
-{
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-	u32 inst_len;
-	u32 data_len;
-	int i;
-	u32 done;
-	u32 reg_offset;
-	int ret;
-
-	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
-
-	priv->ucode_type = UCODE_RT;
-
-	/* make sure bootstrap program is no larger than BSM's SRAM size */
-	if (len > IWL49_MAX_BSM_SIZE)
-		return -EINVAL;
-
-	/* Tell bootstrap uCode where to find the "Initialize" uCode
-	 *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
-	 * NOTE:  iwl_init_alive_start() will replace these values,
-	 *        after the "initialize" uCode has run, to point to
-	 *        runtime/protocol instructions and backup data cache.
-	 */
-	pinst = priv->ucode_init.p_addr >> 4;
-	pdata = priv->ucode_init_data.p_addr >> 4;
-	inst_len = priv->ucode_init.len;
-	data_len = priv->ucode_init_data.len;
-
-	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-
-	/* Fill BSM memory with bootstrap instructions */
-	for (reg_offset = BSM_SRAM_LOWER_BOUND;
-	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
-	     reg_offset += sizeof(u32), image++)
-		_iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
-
-	ret = iwl4965_verify_bsm(priv);
-	if (ret)
-		return ret;
-
-	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
-	iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
-	iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
-	iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-	/* Load bootstrap code into instruction SRAM now,
-	 *   to prepare to load "initialize" uCode */
-	iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
-
-	/* Wait for load of bootstrap uCode to finish */
-	for (i = 0; i < 100; i++) {
-		done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
-		if (!(done & BSM_WR_CTRL_REG_BIT_START))
-			break;
-		udelay(10);
-	}
-	if (i < 100)
-		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
-	else {
-		IWL_ERR(priv, "BSM write did not complete!\n");
-		return -EIO;
-	}
-
-	/* Enable future boot loads whenever power management unit triggers it
-	 *   (e.g. when powering back up after power-save shutdown) */
-	iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
-
-
-	return 0;
-}
-
-/**
- * iwl4965_set_ucode_ptrs - Set uCode address location
- *
- * Tell initialization uCode where to find runtime uCode.
- *
- * BSM registers initially contain pointers to initialization uCode.
- * We need to replace them to load runtime uCode inst and data,
- * and to save runtime data when powering down.
- */
-static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
-{
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-	int ret = 0;
-
-	/* bits 35:4 for 4965 */
-	pinst = priv->ucode_code.p_addr >> 4;
-	pdata = priv->ucode_data_backup.p_addr >> 4;
-
-	/* Tell bootstrap uCode where to find image to load */
-	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-				 priv->ucode_data.len);
-
-	/* Inst byte count must be last to set up, bit 31 signals uCode
-	 *   that all new ptr/size info is in place */
-	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
-				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
-
-	return ret;
-}
-
-/**
- * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
- *
- * The 4965 "initialize" ALIVE reply contains calibration data for:
- *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
- *   (3945 does not contain this data).
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
-*/
-static void iwl4965_init_alive_start(struct iwl_priv *priv)
-{
-	/* Check alive response for "valid" sign from uCode */
-	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
-		goto restart;
-	}
-
-	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
-	 * This is a paranoid check, because we would not have gotten the
-	 * "initialize" alive if code weren't properly loaded.  */
-	if (iwl_verify_ucode(priv)) {
-		/* Runtime instruction load was bad;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
-		goto restart;
-	}
-
-	/* Calculate temperature */
-	priv->temperature = iwl4965_hw_get_temperature(priv);
-
-	/* Send pointers to protocol/runtime uCode image ... init code will
-	 * load and launch runtime uCode, which will send us another "Alive"
-	 * notification. */
-	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-	if (iwl4965_set_ucode_ptrs(priv)) {
-		/* Runtime instruction load won't happen;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
-		goto restart;
-	}
-	return;
-
-restart:
-	queue_work(priv->workqueue, &priv->restart);
-}
-
-static bool is_ht40_channel(__le32 rxon_flags)
-{
-	int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
-				    >> RXON_FLG_CHANNEL_MODE_POS;
-	return ((chan_mod == CHANNEL_MODE_PURE_40) ||
-		  (chan_mod == CHANNEL_MODE_MIXED));
-}
-
-/*
- * EEPROM handlers
- */
-static u16 iwl4965_eeprom_calib_version(struct iwl_priv *priv)
-{
-	return iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET);
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->lock and mac access
- */
-static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
-{
-	iwl_write_prph(priv, IWL49_SCD_TXFACT, mask);
-}
-
-static void iwl4965_nic_config(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	u16 radio_cfg;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-	/* write radio config values to register */
-	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-	/* set CSR_HW_CONFIG_REG for uCode use */
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
-
-	priv->calib_info = (struct iwl_eeprom_calib_info *)
-		iwl_eeprom_query_addr(priv, EEPROM_4965_CALIB_TXPOWER_OFFSET);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
- * Called after every association, but this runs only once!
- *  ... once chain noise is calibrated the first time, it's good forever.  */
-static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
-{
-	struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
-
-	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
-	    iwl_is_any_associated(priv)) {
-		struct iwl_calib_diff_gain_cmd cmd;
-
-		/* clear data for chain noise calibration algorithm */
-		data->chain_noise_a = 0;
-		data->chain_noise_b = 0;
-		data->chain_noise_c = 0;
-		data->chain_signal_a = 0;
-		data->chain_signal_b = 0;
-		data->chain_signal_c = 0;
-		data->beacon_count = 0;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
-		cmd.diff_gain_a = 0;
-		cmd.diff_gain_b = 0;
-		cmd.diff_gain_c = 0;
-		if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-				 sizeof(cmd), &cmd))
-			IWL_ERR(priv,
-				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
-		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
-		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
-	}
-}
-
-static void iwl4965_gain_computation(struct iwl_priv *priv,
-		u32 *average_noise,
-		u16 min_average_noise_antenna_i,
-		u32 min_average_noise,
-		u8 default_chain)
-{
-	int i, ret;
-	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
-
-	data->delta_gain_code[min_average_noise_antenna_i] = 0;
-
-	for (i = default_chain; i < NUM_RX_CHAINS; i++) {
-		s32 delta_g = 0;
-
-		if (!(data->disconn_array[i]) &&
-		    (data->delta_gain_code[i] ==
-			     CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
-			delta_g = average_noise[i] - min_average_noise;
-			data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
-			data->delta_gain_code[i] =
-				min(data->delta_gain_code[i],
-				(u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
-
-			data->delta_gain_code[i] =
-				(data->delta_gain_code[i] | (1 << 2));
-		} else {
-			data->delta_gain_code[i] = 0;
-		}
-	}
-	IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n",
-		     data->delta_gain_code[0],
-		     data->delta_gain_code[1],
-		     data->delta_gain_code[2]);
-
-	/* Differential gain gets sent to uCode only once */
-	if (!data->radio_write) {
-		struct iwl_calib_diff_gain_cmd cmd;
-		data->radio_write = 1;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
-		cmd.diff_gain_a = data->delta_gain_code[0];
-		cmd.diff_gain_b = data->delta_gain_code[1];
-		cmd.diff_gain_c = data->delta_gain_code[2];
-		ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-				      sizeof(cmd), &cmd);
-		if (ret)
-			IWL_DEBUG_CALIB(priv, "fail sending cmd "
-				     "REPLY_PHY_CALIBRATION_CMD\n");
-
-		/* TODO we might want recalculate
-		 * rx_chain in rxon cmd */
-
-		/* Mark so we run this algo only once! */
-		data->state = IWL_CHAIN_NOISE_CALIBRATED;
-	}
-}
-
-static void iwl4965_bg_txpower_work(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-			txpower_work);
-
-	/* If a scan happened to start before we got here
-	 * then just return; the statistics notification will
-	 * kick off another scheduled work to compensate for
-	 * any temperature delta we missed here. */
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-	    test_bit(STATUS_SCANNING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	/* Regardless of if we are associated, we must reconfigure the
-	 * TX power since frames can be sent on non-radar channels while
-	 * not associated */
-	iwl4965_send_tx_power(priv);
-
-	/* Update last_temperature to keep is_calib_needed from running
-	 * when it isn't needed... */
-	priv->last_temperature = priv->temperature;
-
-	mutex_unlock(&priv->mutex);
-}
-
-/*
- * Acquire priv->lock before calling this function !
- */
-static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
-{
-	iwl_write_direct32(priv, HBUS_TARG_WRPTR,
-			     (index & 0xff) | (txq_id << 8));
-	iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
-}
-
-/**
- * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
- * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
- * @scd_retry: (1) Indicates queue will be used in aggregation mode
- *
- * NOTE:  Acquire priv->lock before calling this function !
- */
-static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
-					struct iwl_tx_queue *txq,
-					int tx_fifo_id, int scd_retry)
-{
-	int txq_id = txq->q.id;
-
-	/* Find out whether to activate Tx queue */
-	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
-
-	/* Set up and activate */
-	iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-			 (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
-			 (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) |
-			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) |
-			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
-			 IWL49_SCD_QUEUE_STTS_REG_MSK);
-
-	txq->sched_retry = scd_retry;
-
-	IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
-		       active ? "Activate" : "Deactivate",
-		       scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
-}
-
-static const s8 default_queue_to_tx_fifo[] = {
-	IWL_TX_FIFO_VO,
-	IWL_TX_FIFO_VI,
-	IWL_TX_FIFO_BE,
-	IWL_TX_FIFO_BK,
-	IWL49_CMD_FIFO_NUM,
-	IWL_TX_FIFO_UNUSED,
-	IWL_TX_FIFO_UNUSED,
-};
-
-static int iwl4965_alive_notify(struct iwl_priv *priv)
-{
-	u32 a;
-	unsigned long flags;
-	int i, chan;
-	u32 reg_val;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Clear 4965's internal Tx Scheduler data base */
-	priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR);
-	a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET;
-	for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-	for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-	for (; a < priv->scd_base_addr +
-	       IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-
-	/* Tel 4965 where to find Tx byte count tables */
-	iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
-			priv->scd_bc_tbls.dma >> 10);
-
-	/* Enable DMA channel */
-	for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
-		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
-				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
-	/* Update FH chicken bits */
-	reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
-	iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
-			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
-	/* Disable chain mode for all queues */
-	iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
-
-	/* Initialize each Tx queue (including the command queue) */
-	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
-
-		/* TFD circular buffer read/write indexes */
-		iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
-		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
-
-		/* Max Tx Window size for Scheduler-ACK mode */
-		iwl_write_targ_mem(priv, priv->scd_base_addr +
-				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i),
-				(SCD_WIN_SIZE <<
-				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
-				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-		/* Frame limit */
-		iwl_write_targ_mem(priv, priv->scd_base_addr +
-				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
-				sizeof(u32),
-				(SCD_FRAME_LIMIT <<
-				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-	}
-	iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
-				 (1 << priv->hw_params.max_txq_num) - 1);
-
-	/* Activate all Tx DMA/FIFO channels */
-	priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
-
-	iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
-
-	/* make sure all queue are not stopped */
-	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
-	for (i = 0; i < 4; i++)
-		atomic_set(&priv->queue_stop_count[i], 0);
-
-	/* reset to 0 to enable all the queue first */
-	priv->txq_ctx_active_msk = 0;
-	/* Map each Tx/cmd queue to its corresponding fifo */
-	BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
-
-	for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
-		int ac = default_queue_to_tx_fifo[i];
-
-		iwl_txq_ctx_activate(priv, i);
-
-		if (ac == IWL_TX_FIFO_UNUSED)
-			continue;
-
-		iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
-	.min_nrg_cck = 97,
-	.max_nrg_cck = 0, /* not used, set to 0 */
-
-	.auto_corr_min_ofdm = 85,
-	.auto_corr_min_ofdm_mrc = 170,
-	.auto_corr_min_ofdm_x1 = 105,
-	.auto_corr_min_ofdm_mrc_x1 = 220,
-
-	.auto_corr_max_ofdm = 120,
-	.auto_corr_max_ofdm_mrc = 210,
-	.auto_corr_max_ofdm_x1 = 140,
-	.auto_corr_max_ofdm_mrc_x1 = 270,
-
-	.auto_corr_min_cck = 125,
-	.auto_corr_max_cck = 200,
-	.auto_corr_min_cck_mrc = 200,
-	.auto_corr_max_cck_mrc = 400,
-
-	.nrg_th_cck = 100,
-	.nrg_th_ofdm = 100,
-
-	.barker_corr_th_min = 190,
-	.barker_corr_th_min_mrc = 390,
-	.nrg_th_cca = 62,
-};
-
-static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
-{
-	/* want Kelvin */
-	priv->hw_params.ct_kill_threshold =
-		CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
-}
-
-/**
- * iwl4965_hw_set_hw_params
- *
- * Called when initializing driver
- */
-static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
-{
-	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
-		priv->cfg->base_params->num_of_queues =
-			priv->cfg->mod_params->num_of_queues;
-
-	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
-	priv->hw_params.scd_bc_tbls_size =
-			priv->cfg->base_params->num_of_queues *
-			sizeof(struct iwl4965_scd_bc_tbl);
-	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
-	priv->hw_params.max_stations = IWL4965_STATION_COUNT;
-	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
-	priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
-	priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
-	priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
-	priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
-
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
-
-	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
-	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
-	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
-
-	iwl4965_set_ct_threshold(priv);
-
-	priv->hw_params.sens = &iwl4965_sensitivity;
-	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
-	return 0;
-}
-
-static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
-{
-	s32 sign = 1;
-
-	if (num < 0) {
-		sign = -sign;
-		num = -num;
-	}
-	if (denom < 0) {
-		sign = -sign;
-		denom = -denom;
-	}
-	*res = 1;
-	*res = ((num * 2 + denom) / (denom * 2)) * sign;
-
-	return 1;
-}
-
-/**
- * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
- *
- * Determines power supply voltage compensation for txpower calculations.
- * Returns number of 1/2-dB steps to subtract from gain table index,
- * to compensate for difference between power supply voltage during
- * factory measurements, vs. current power supply voltage.
- *
- * Voltage indication is higher for lower voltage.
- * Lower voltage requires more gain (lower gain table index).
- */
-static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
-					    s32 current_voltage)
-{
-	s32 comp = 0;
-
-	if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) ||
-	    (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage))
-		return 0;
-
-	iwl4965_math_div_round(current_voltage - eeprom_voltage,
-			       TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp);
-
-	if (current_voltage > eeprom_voltage)
-		comp *= 2;
-	if ((comp < -2) || (comp > 2))
-		comp = 0;
-
-	return comp;
-}
-
-static s32 iwl4965_get_tx_atten_grp(u16 channel)
-{
-	if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR5_LCH)
-		return CALIB_CH_GROUP_5;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR1_LCH)
-		return CALIB_CH_GROUP_1;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR2_LCH)
-		return CALIB_CH_GROUP_2;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR3_LCH)
-		return CALIB_CH_GROUP_3;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
-		return CALIB_CH_GROUP_4;
-
-	return -1;
-}
-
-static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
-{
-	s32 b = -1;
-
-	for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
-		if (priv->calib_info->band_info[b].ch_from == 0)
-			continue;
-
-		if ((channel >= priv->calib_info->band_info[b].ch_from)
-		    && (channel <= priv->calib_info->band_info[b].ch_to))
-			break;
-	}
-
-	return b;
-}
-
-static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
-{
-	s32 val;
-
-	if (x2 == x1)
-		return y1;
-	else {
-		iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
-		return val + y2;
-	}
-}
-
-/**
- * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
- *
- * Interpolates factory measurements from the two sample channels within a
- * sub-band, to apply to channel of interest.  Interpolation is proportional to
- * differences in channel frequencies, which is proportional to differences
- * in channel number.
- */
-static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
-				    struct iwl_eeprom_calib_ch_info *chan_info)
-{
-	s32 s = -1;
-	u32 c;
-	u32 m;
-	const struct iwl_eeprom_calib_measure *m1;
-	const struct iwl_eeprom_calib_measure *m2;
-	struct iwl_eeprom_calib_measure *omeas;
-	u32 ch_i1;
-	u32 ch_i2;
-
-	s = iwl4965_get_sub_band(priv, channel);
-	if (s >= EEPROM_TX_POWER_BANDS) {
-		IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
-		return -1;
-	}
-
-	ch_i1 = priv->calib_info->band_info[s].ch1.ch_num;
-	ch_i2 = priv->calib_info->band_info[s].ch2.ch_num;
-	chan_info->ch_num = (u8) channel;
-
-	IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n",
-			  channel, s, ch_i1, ch_i2);
-
-	for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
-		for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
-			m1 = &(priv->calib_info->band_info[s].ch1.
-			       measurements[c][m]);
-			m2 = &(priv->calib_info->band_info[s].ch2.
-			       measurements[c][m]);
-			omeas = &(chan_info->measurements[c][m]);
-
-			omeas->actual_pow =
-			    (u8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->actual_pow,
-							   ch_i2,
-							   m2->actual_pow);
-			omeas->gain_idx =
-			    (u8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->gain_idx, ch_i2,
-							   m2->gain_idx);
-			omeas->temperature =
-			    (u8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->temperature,
-							   ch_i2,
-							   m2->temperature);
-			omeas->pa_det =
-			    (s8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->pa_det, ch_i2,
-							   m2->pa_det);
-
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m,
-				m1->actual_pow, m2->actual_pow, omeas->actual_pow);
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m,
-				m1->gain_idx, m2->gain_idx, omeas->gain_idx);
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m,
-				m1->pa_det, m2->pa_det, omeas->pa_det);
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d  T1=%d  T2=%d  T=%d\n", c, m,
-				m1->temperature, m2->temperature,
-				omeas->temperature);
-		}
-	}
-
-	return 0;
-}
-
-/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
- * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
-static s32 back_off_table[] = {
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 20 MHz */
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 20 MHz */
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 40 MHz */
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 40 MHz */
-	10			/* CCK */
-};
-
-/* Thermal compensation values for txpower for various frequency ranges ...
- *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
-static struct iwl4965_txpower_comp_entry {
-	s32 degrees_per_05db_a;
-	s32 degrees_per_05db_a_denom;
-} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
-	{9, 2},			/* group 0 5.2, ch  34-43 */
-	{4, 1},			/* group 1 5.2, ch  44-70 */
-	{4, 1},			/* group 2 5.2, ch  71-124 */
-	{4, 1},			/* group 3 5.2, ch 125-200 */
-	{3, 1}			/* group 4 2.4, ch   all */
-};
-
-static s32 get_min_power_index(s32 rate_power_index, u32 band)
-{
-	if (!band) {
-		if ((rate_power_index & 7) <= 4)
-			return MIN_TX_GAIN_INDEX_52GHZ_EXT;
-	}
-	return MIN_TX_GAIN_INDEX;
-}
-
-struct gain_entry {
-	u8 dsp;
-	u8 radio;
-};
-
-static const struct gain_entry gain_table[2][108] = {
-	/* 5.2GHz power gain index table */
-	{
-	 {123, 0x3F},		/* highest txpower */
-	 {117, 0x3F},
-	 {110, 0x3F},
-	 {104, 0x3F},
-	 {98, 0x3F},
-	 {110, 0x3E},
-	 {104, 0x3E},
-	 {98, 0x3E},
-	 {110, 0x3D},
-	 {104, 0x3D},
-	 {98, 0x3D},
-	 {110, 0x3C},
-	 {104, 0x3C},
-	 {98, 0x3C},
-	 {110, 0x3B},
-	 {104, 0x3B},
-	 {98, 0x3B},
-	 {110, 0x3A},
-	 {104, 0x3A},
-	 {98, 0x3A},
-	 {110, 0x39},
-	 {104, 0x39},
-	 {98, 0x39},
-	 {110, 0x38},
-	 {104, 0x38},
-	 {98, 0x38},
-	 {110, 0x37},
-	 {104, 0x37},
-	 {98, 0x37},
-	 {110, 0x36},
-	 {104, 0x36},
-	 {98, 0x36},
-	 {110, 0x35},
-	 {104, 0x35},
-	 {98, 0x35},
-	 {110, 0x34},
-	 {104, 0x34},
-	 {98, 0x34},
-	 {110, 0x33},
-	 {104, 0x33},
-	 {98, 0x33},
-	 {110, 0x32},
-	 {104, 0x32},
-	 {98, 0x32},
-	 {110, 0x31},
-	 {104, 0x31},
-	 {98, 0x31},
-	 {110, 0x30},
-	 {104, 0x30},
-	 {98, 0x30},
-	 {110, 0x25},
-	 {104, 0x25},
-	 {98, 0x25},
-	 {110, 0x24},
-	 {104, 0x24},
-	 {98, 0x24},
-	 {110, 0x23},
-	 {104, 0x23},
-	 {98, 0x23},
-	 {110, 0x22},
-	 {104, 0x18},
-	 {98, 0x18},
-	 {110, 0x17},
-	 {104, 0x17},
-	 {98, 0x17},
-	 {110, 0x16},
-	 {104, 0x16},
-	 {98, 0x16},
-	 {110, 0x15},
-	 {104, 0x15},
-	 {98, 0x15},
-	 {110, 0x14},
-	 {104, 0x14},
-	 {98, 0x14},
-	 {110, 0x13},
-	 {104, 0x13},
-	 {98, 0x13},
-	 {110, 0x12},
-	 {104, 0x08},
-	 {98, 0x08},
-	 {110, 0x07},
-	 {104, 0x07},
-	 {98, 0x07},
-	 {110, 0x06},
-	 {104, 0x06},
-	 {98, 0x06},
-	 {110, 0x05},
-	 {104, 0x05},
-	 {98, 0x05},
-	 {110, 0x04},
-	 {104, 0x04},
-	 {98, 0x04},
-	 {110, 0x03},
-	 {104, 0x03},
-	 {98, 0x03},
-	 {110, 0x02},
-	 {104, 0x02},
-	 {98, 0x02},
-	 {110, 0x01},
-	 {104, 0x01},
-	 {98, 0x01},
-	 {110, 0x00},
-	 {104, 0x00},
-	 {98, 0x00},
-	 {93, 0x00},
-	 {88, 0x00},
-	 {83, 0x00},
-	 {78, 0x00},
-	 },
-	/* 2.4GHz power gain index table */
-	{
-	 {110, 0x3f},		/* highest txpower */
-	 {104, 0x3f},
-	 {98, 0x3f},
-	 {110, 0x3e},
-	 {104, 0x3e},
-	 {98, 0x3e},
-	 {110, 0x3d},
-	 {104, 0x3d},
-	 {98, 0x3d},
-	 {110, 0x3c},
-	 {104, 0x3c},
-	 {98, 0x3c},
-	 {110, 0x3b},
-	 {104, 0x3b},
-	 {98, 0x3b},
-	 {110, 0x3a},
-	 {104, 0x3a},
-	 {98, 0x3a},
-	 {110, 0x39},
-	 {104, 0x39},
-	 {98, 0x39},
-	 {110, 0x38},
-	 {104, 0x38},
-	 {98, 0x38},
-	 {110, 0x37},
-	 {104, 0x37},
-	 {98, 0x37},
-	 {110, 0x36},
-	 {104, 0x36},
-	 {98, 0x36},
-	 {110, 0x35},
-	 {104, 0x35},
-	 {98, 0x35},
-	 {110, 0x34},
-	 {104, 0x34},
-	 {98, 0x34},
-	 {110, 0x33},
-	 {104, 0x33},
-	 {98, 0x33},
-	 {110, 0x32},
-	 {104, 0x32},
-	 {98, 0x32},
-	 {110, 0x31},
-	 {104, 0x31},
-	 {98, 0x31},
-	 {110, 0x30},
-	 {104, 0x30},
-	 {98, 0x30},
-	 {110, 0x6},
-	 {104, 0x6},
-	 {98, 0x6},
-	 {110, 0x5},
-	 {104, 0x5},
-	 {98, 0x5},
-	 {110, 0x4},
-	 {104, 0x4},
-	 {98, 0x4},
-	 {110, 0x3},
-	 {104, 0x3},
-	 {98, 0x3},
-	 {110, 0x2},
-	 {104, 0x2},
-	 {98, 0x2},
-	 {110, 0x1},
-	 {104, 0x1},
-	 {98, 0x1},
-	 {110, 0x0},
-	 {104, 0x0},
-	 {98, 0x0},
-	 {97, 0},
-	 {96, 0},
-	 {95, 0},
-	 {94, 0},
-	 {93, 0},
-	 {92, 0},
-	 {91, 0},
-	 {90, 0},
-	 {89, 0},
-	 {88, 0},
-	 {87, 0},
-	 {86, 0},
-	 {85, 0},
-	 {84, 0},
-	 {83, 0},
-	 {82, 0},
-	 {81, 0},
-	 {80, 0},
-	 {79, 0},
-	 {78, 0},
-	 {77, 0},
-	 {76, 0},
-	 {75, 0},
-	 {74, 0},
-	 {73, 0},
-	 {72, 0},
-	 {71, 0},
-	 {70, 0},
-	 {69, 0},
-	 {68, 0},
-	 {67, 0},
-	 {66, 0},
-	 {65, 0},
-	 {64, 0},
-	 {63, 0},
-	 {62, 0},
-	 {61, 0},
-	 {60, 0},
-	 {59, 0},
-	 }
-};
-
-static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
-				    u8 is_ht40, u8 ctrl_chan_high,
-				    struct iwl4965_tx_power_db *tx_power_tbl)
-{
-	u8 saturation_power;
-	s32 target_power;
-	s32 user_target_power;
-	s32 power_limit;
-	s32 current_temp;
-	s32 reg_limit;
-	s32 current_regulatory;
-	s32 txatten_grp = CALIB_CH_GROUP_MAX;
-	int i;
-	int c;
-	const struct iwl_channel_info *ch_info = NULL;
-	struct iwl_eeprom_calib_ch_info ch_eeprom_info;
-	const struct iwl_eeprom_calib_measure *measurement;
-	s16 voltage;
-	s32 init_voltage;
-	s32 voltage_compensation;
-	s32 degrees_per_05db_num;
-	s32 degrees_per_05db_denom;
-	s32 factory_temp;
-	s32 temperature_comp[2];
-	s32 factory_gain_index[2];
-	s32 factory_actual_pwr[2];
-	s32 power_index;
-
-	/* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
-	 *   are used for indexing into txpower table) */
-	user_target_power = 2 * priv->tx_power_user_lmt;
-
-	/* Get current (RXON) channel, band, width */
-	IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
-			  is_ht40);
-
-	ch_info = iwl_get_channel_info(priv, priv->band, channel);
-
-	if (!is_channel_valid(ch_info))
-		return -EINVAL;
-
-	/* get txatten group, used to select 1) thermal txpower adjustment
-	 *   and 2) mimo txpower balance between Tx chains. */
-	txatten_grp = iwl4965_get_tx_atten_grp(channel);
-	if (txatten_grp < 0) {
-		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
-			  channel);
-		return -EINVAL;
-	}
-
-	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
-			  channel, txatten_grp);
-
-	if (is_ht40) {
-		if (ctrl_chan_high)
-			channel -= 2;
-		else
-			channel += 2;
-	}
-
-	/* hardware txpower limits ...
-	 * saturation (clipping distortion) txpowers are in half-dBm */
-	if (band)
-		saturation_power = priv->calib_info->saturation_power24;
-	else
-		saturation_power = priv->calib_info->saturation_power52;
-
-	if (saturation_power < IWL_TX_POWER_SATURATION_MIN ||
-	    saturation_power > IWL_TX_POWER_SATURATION_MAX) {
-		if (band)
-			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24;
-		else
-			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52;
-	}
-
-	/* regulatory txpower limits ... reg_limit values are in half-dBm,
-	 *   max_power_avg values are in dBm, convert * 2 */
-	if (is_ht40)
-		reg_limit = ch_info->ht40_max_power_avg * 2;
-	else
-		reg_limit = ch_info->max_power_avg * 2;
-
-	if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) ||
-	    (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) {
-		if (band)
-			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24;
-		else
-			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52;
-	}
-
-	/* Interpolate txpower calibration values for this channel,
-	 *   based on factory calibration tests on spaced channels. */
-	iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
-
-	/* calculate tx gain adjustment based on power supply voltage */
-	voltage = le16_to_cpu(priv->calib_info->voltage);
-	init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
-	voltage_compensation =
-	    iwl4965_get_voltage_compensation(voltage, init_voltage);
-
-	IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n",
-			  init_voltage,
-			  voltage, voltage_compensation);
-
-	/* get current temperature (Celsius) */
-	current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN);
-	current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX);
-	current_temp = KELVIN_TO_CELSIUS(current_temp);
-
-	/* select thermal txpower adjustment params, based on channel group
-	 *   (same frequency group used for mimo txatten adjustment) */
-	degrees_per_05db_num =
-	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
-	degrees_per_05db_denom =
-	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
-
-	/* get per-chain txpower values from factory measurements */
-	for (c = 0; c < 2; c++) {
-		measurement = &ch_eeprom_info.measurements[c][1];
-
-		/* txgain adjustment (in half-dB steps) based on difference
-		 *   between factory and current temperature */
-		factory_temp = measurement->temperature;
-		iwl4965_math_div_round((current_temp - factory_temp) *
-				       degrees_per_05db_denom,
-				       degrees_per_05db_num,
-				       &temperature_comp[c]);
-
-		factory_gain_index[c] = measurement->gain_idx;
-		factory_actual_pwr[c] = measurement->actual_pow;
-
-		IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c);
-		IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, "
-				  "curr tmp %d, comp %d steps\n",
-				  factory_temp, current_temp,
-				  temperature_comp[c]);
-
-		IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n",
-				  factory_gain_index[c],
-				  factory_actual_pwr[c]);
-	}
-
-	/* for each of 33 bit-rates (including 1 for CCK) */
-	for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
-		u8 is_mimo_rate;
-		union iwl4965_tx_power_dual_stream tx_power;
-
-		/* for mimo, reduce each chain's txpower by half
-		 * (3dB, 6 steps), so total output power is regulatory
-		 * compliant. */
-		if (i & 0x8) {
-			current_regulatory = reg_limit -
-			    IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
-			is_mimo_rate = 1;
-		} else {
-			current_regulatory = reg_limit;
-			is_mimo_rate = 0;
-		}
-
-		/* find txpower limit, either hardware or regulatory */
-		power_limit = saturation_power - back_off_table[i];
-		if (power_limit > current_regulatory)
-			power_limit = current_regulatory;
-
-		/* reduce user's txpower request if necessary
-		 * for this rate on this channel */
-		target_power = user_target_power;
-		if (target_power > power_limit)
-			target_power = power_limit;
-
-		IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n",
-				  i, saturation_power - back_off_table[i],
-				  current_regulatory, user_target_power,
-				  target_power);
-
-		/* for each of 2 Tx chains (radio transmitters) */
-		for (c = 0; c < 2; c++) {
-			s32 atten_value;
-
-			if (is_mimo_rate)
-				atten_value =
-				    (s32)le32_to_cpu(priv->card_alive_init.
-				    tx_atten[txatten_grp][c]);
-			else
-				atten_value = 0;
-
-			/* calculate index; higher index means lower txpower */
-			power_index = (u8) (factory_gain_index[c] -
-					    (target_power -
-					     factory_actual_pwr[c]) -
-					    temperature_comp[c] -
-					    voltage_compensation +
-					    atten_value);
-
-/*			IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n",
-						power_index); */
-
-			if (power_index < get_min_power_index(i, band))
-				power_index = get_min_power_index(i, band);
-
-			/* adjust 5 GHz index to support negative indexes */
-			if (!band)
-				power_index += 9;
-
-			/* CCK, rate 32, reduce txpower for CCK */
-			if (i == POWER_TABLE_CCK_ENTRY)
-				power_index +=
-				    IWL_TX_POWER_CCK_COMPENSATION_C_STEP;
-
-			/* stay within the table! */
-			if (power_index > 107) {
-				IWL_WARN(priv, "txpower index %d > 107\n",
-					    power_index);
-				power_index = 107;
-			}
-			if (power_index < 0) {
-				IWL_WARN(priv, "txpower index %d < 0\n",
-					    power_index);
-				power_index = 0;
-			}
-
-			/* fill txpower command for this rate/chain */
-			tx_power.s.radio_tx_gain[c] =
-				gain_table[band][power_index].radio;
-			tx_power.s.dsp_predis_atten[c] =
-				gain_table[band][power_index].dsp;
-
-			IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d "
-					  "gain 0x%02x dsp %d\n",
-					  c, atten_value, power_index,
-					tx_power.s.radio_tx_gain[c],
-					tx_power.s.dsp_predis_atten[c]);
-		} /* for each chain */
-
-		tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
-
-	} /* for each rate */
-
-	return 0;
-}
-
-/**
- * iwl4965_send_tx_power - Configure the TXPOWER level user limit
- *
- * Uses the active RXON for channel, band, and characteristics (ht40, high)
- * The power limit is taken from priv->tx_power_user_lmt.
- */
-static int iwl4965_send_tx_power(struct iwl_priv *priv)
-{
-	struct iwl4965_txpowertable_cmd cmd = { 0 };
-	int ret;
-	u8 band = 0;
-	bool is_ht40 = false;
-	u8 ctrl_chan_high = 0;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
-		      "TX Power requested while scanning!\n"))
-		return -EAGAIN;
-
-	band = priv->band == IEEE80211_BAND_2GHZ;
-
-	is_ht40 = is_ht40_channel(ctx->active.flags);
-
-	if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
-		ctrl_chan_high = 1;
-
-	cmd.band = band;
-	cmd.channel = ctx->active.channel;
-
-	ret = iwl4965_fill_txpower_tbl(priv, band,
-				le16_to_cpu(ctx->active.channel),
-				is_ht40, ctrl_chan_high, &cmd.tx_power);
-	if (ret)
-		goto out;
-
-	ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
-
-out:
-	return ret;
-}
-
-static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
-				   struct iwl_rxon_context *ctx)
-{
-	int ret = 0;
-	struct iwl4965_rxon_assoc_cmd rxon_assoc;
-	const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
-	const struct iwl_rxon_cmd *rxon2 = &ctx->active;
-
-	if ((rxon1->flags == rxon2->flags) &&
-	    (rxon1->filter_flags == rxon2->filter_flags) &&
-	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-	    (rxon1->ofdm_ht_single_stream_basic_rates ==
-	     rxon2->ofdm_ht_single_stream_basic_rates) &&
-	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
-	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
-	    (rxon1->rx_chain == rxon2->rx_chain) &&
-	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
-		return 0;
-	}
-
-	rxon_assoc.flags = ctx->staging.flags;
-	rxon_assoc.filter_flags = ctx->staging.filter_flags;
-	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
-	rxon_assoc.reserved = 0;
-	rxon_assoc.ofdm_ht_single_stream_basic_rates =
-	    ctx->staging.ofdm_ht_single_stream_basic_rates;
-	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-	    ctx->staging.ofdm_ht_dual_stream_basic_rates;
-	rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
-
-	ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
-				     sizeof(rxon_assoc), &rxon_assoc, NULL);
-	if (ret)
-		return ret;
-
-	return ret;
-}
-
-static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
-	int ret;
-	bool new_assoc =
-		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (!iwl_is_alive(priv))
-		return -EBUSY;
-
-	if (!ctx->is_active)
-		return 0;
-
-	/* always get timestamp with Rx frame */
-	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
-
-	ret = iwl_check_rxon_cmd(priv, ctx);
-	if (ret) {
-		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * receive commit_rxon request
-	 * abort any previous channel switch if still in process
-	 */
-	if (priv->switch_rxon.switch_in_progress &&
-	    (priv->switch_rxon.channel != ctx->staging.channel)) {
-		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-		      le16_to_cpu(priv->switch_rxon.channel));
-		iwl_chswitch_done(priv, false);
-	}
-
-	/* If we don't need to send a full RXON, we can use
-	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
-	 * and other flags for the current radio configuration. */
-	if (!iwl_full_rxon_required(priv, ctx)) {
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
-			return ret;
-		}
-
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_print_rx_config_cmd(priv, ctx);
-		return 0;
-	}
-
-	/* If we are currently associated and the new config requires
-	 * an RXON_ASSOC and the new config wants the associated mask enabled,
-	 * we must clear the associated from the active configuration
-	 * before we apply the new config */
-	if (iwl_is_associated_ctx(ctx) && new_assoc) {
-		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-				       sizeof(struct iwl_rxon_cmd),
-				       active_rxon);
-
-		/* If the mask clearing failed then we set
-		 * active_rxon back to what it was previously */
-		if (ret) {
-			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
-			return ret;
-		}
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "Sending RXON\n"
-		       "* with%s RXON_FILTER_ASSOC_MSK\n"
-		       "* channel = %d\n"
-		       "* bssid = %pM\n",
-		       (new_assoc ? "" : "out"),
-		       le16_to_cpu(ctx->staging.channel),
-		       ctx->staging.bssid_addr);
-
-	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
-
-	/* Apply the new configuration
-	 * RXON unassoc clears the station table in uCode so restoration of
-	 * stations is needed after it (the RXON command) completes
-	 */
-	if (!new_assoc) {
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-	if (new_assoc) {
-		priv->start_calib = 0;
-		/* Apply the new configuration
-		 * RXON assoc doesn't clear the station table in uCode,
-		 */
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-	}
-	iwl_print_rx_config_cmd(priv, ctx);
-
-	iwl_init_sensitivity(priv);
-
-	/* If we issue a new RXON command which required a tune then we must
-	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-	if (ret) {
-		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
-				     struct ieee80211_channel_switch *ch_switch)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	int rc;
-	u8 band = 0;
-	bool is_ht40 = false;
-	u8 ctrl_chan_high = 0;
-	struct iwl4965_channel_switch_cmd cmd;
-	const struct iwl_channel_info *ch_info;
-	u32 switch_time_in_usec, ucode_switch_time;
-	u16 ch;
-	u32 tsf_low;
-	u8 switch_count;
-	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
-	struct ieee80211_vif *vif = ctx->vif;
-	band = priv->band == IEEE80211_BAND_2GHZ;
-
-	is_ht40 = is_ht40_channel(ctx->staging.flags);
-
-	if (is_ht40 &&
-	    (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
-		ctrl_chan_high = 1;
-
-	cmd.band = band;
-	cmd.expect_beacon = 0;
-	ch = ch_switch->channel->hw_value;
-	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = ctx->staging.flags;
-	cmd.rxon_filter_flags = ctx->staging.filter_flags;
-	switch_count = ch_switch->count;
-	tsf_low = ch_switch->timestamp & 0x0ffffffff;
-	/*
-	 * calculate the ucode channel switch time
-	 * adding TSF as one of the factor for when to switch
-	 */
-	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
-		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
-		    beacon_interval)) {
-			switch_count -= (priv->ucode_beacon_time -
-				tsf_low) / beacon_interval;
-		} else
-			switch_count = 0;
-	}
-	if (switch_count <= 1)
-		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
-	else {
-		switch_time_in_usec =
-			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
-		ucode_switch_time = iwl_usecs_to_beacons(priv,
-							 switch_time_in_usec,
-							 beacon_interval);
-		cmd.switch_time = iwl_add_beacon_time(priv,
-						      priv->ucode_beacon_time,
-						      ucode_switch_time,
-						      beacon_interval);
-	}
-	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-		      cmd.switch_time);
-	ch_info = iwl_get_channel_info(priv, priv->band, ch);
-	if (ch_info)
-		cmd.expect_beacon = is_channel_radar(ch_info);
-	else {
-		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-			ctx->active.channel, ch);
-		return -EFAULT;
-	}
-
-	rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
-				      ctrl_chan_high, &cmd.tx_power);
-	if (rc) {
-		IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
-		return rc;
-	}
-
-	priv->switch_rxon.channel = cmd.channel;
-	priv->switch_rxon.switch_in_progress = true;
-
-	return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
-}
-
-/**
- * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
-static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
-					    struct iwl_tx_queue *txq,
-					    u16 byte_cnt)
-{
-	struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
-	int txq_id = txq->q.id;
-	int write_ptr = txq->q.write_ptr;
-	int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
-	__le16 bc_ent;
-
-	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
-
-	bc_ent = cpu_to_le16(len & 0xFFF);
-	/* Set up byte count within first 256 entries */
-	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
-
-	/* If within first 64 entries, duplicate at end */
-	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-		scd_bc_tbl[txq_id].
-			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
-}
-
-/**
- * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
- * @statistics: Provides the temperature reading from the uCode
- *
- * A return of <0 indicates bogus data in the statistics
- */
-static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
-{
-	s32 temperature;
-	s32 vt;
-	s32 R1, R2, R3;
-	u32 R4;
-
-	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-	    (priv->_agn.statistics.flag &
-			STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
-		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
-		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
-		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
-		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
-		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]);
-	} else {
-		IWL_DEBUG_TEMP(priv, "Running temperature calibration\n");
-		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]);
-		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]);
-		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]);
-		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]);
-	}
-
-	/*
-	 * Temperature is only 23 bits, so sign extend out to 32.
-	 *
-	 * NOTE If we haven't received a statistics notification yet
-	 * with an updated temperature, use R4 provided to us in the
-	 * "initialize" ALIVE response.
-	 */
-	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
-		vt = sign_extend32(R4, 23);
-	else
-		vt = sign_extend32(le32_to_cpu(priv->_agn.statistics.
-				 general.common.temperature), 23);
-
-	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
-
-	if (R3 == R1) {
-		IWL_ERR(priv, "Calibration conflict R1 == R3\n");
-		return -1;
-	}
-
-	/* Calculate temperature in degrees Kelvin, adjust by 97%.
-	 * Add offset to center the adjustment around 0 degrees Centigrade. */
-	temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
-	temperature /= (R3 - R1);
-	temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
-
-	IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n",
-			temperature, KELVIN_TO_CELSIUS(temperature));
-
-	return temperature;
-}
-
-/* Adjust Txpower only if temperature variance is greater than threshold. */
-#define IWL_TEMPERATURE_THRESHOLD   3
-
-/**
- * iwl4965_is_temp_calib_needed - determines if new calibration is needed
- *
- * If the temperature changed has changed sufficiently, then a recalibration
- * is needed.
- *
- * Assumes caller will replace priv->last_temperature once calibration
- * executed.
- */
-static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
-{
-	int temp_diff;
-
-	if (!test_bit(STATUS_STATISTICS, &priv->status)) {
-		IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n");
-		return 0;
-	}
-
-	temp_diff = priv->temperature - priv->last_temperature;
-
-	/* get absolute value */
-	if (temp_diff < 0) {
-		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
-		temp_diff = -temp_diff;
-	} else if (temp_diff == 0)
-		IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
-	else
-		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
-
-	if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
-		IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
-		return 0;
-	}
-
-	IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
-
-	return 1;
-}
-
-static void iwl4965_temperature_calib(struct iwl_priv *priv)
-{
-	s32 temp;
-
-	temp = iwl4965_hw_get_temperature(priv);
-	if (temp < 0)
-		return;
-
-	if (priv->temperature != temp) {
-		if (priv->temperature)
-			IWL_DEBUG_TEMP(priv, "Temperature changed "
-				       "from %dC to %dC\n",
-				       KELVIN_TO_CELSIUS(priv->temperature),
-				       KELVIN_TO_CELSIUS(temp));
-		else
-			IWL_DEBUG_TEMP(priv, "Temperature "
-				       "initialized to %dC\n",
-				       KELVIN_TO_CELSIUS(temp));
-	}
-
-	priv->temperature = temp;
-	iwl_tt_handler(priv);
-	set_bit(STATUS_TEMPERATURE, &priv->status);
-
-	if (!priv->disable_tx_power_cal &&
-	     unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-	     iwl4965_is_temp_calib_needed(priv))
-		queue_work(priv->workqueue, &priv->txpower_work);
-}
-
-/**
- * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
- */
-static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
-					    u16 txq_id)
-{
-	/* Simply stop the queue, but don't change any configuration;
-	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-	iwl_write_prph(priv,
-		IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-		(0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-		(1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
-/**
- * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE
- * priv->lock must be held by the caller
- */
-static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
-				   u16 ssn_idx, u8 tx_fifo)
-{
-	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWL49_FIRST_AMPDU_QUEUE +
-		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-		IWL_WARN(priv,
-			"queue number out of range: %d, must be %d to %d\n",
-			txq_id, IWL49_FIRST_AMPDU_QUEUE,
-			IWL49_FIRST_AMPDU_QUEUE +
-			priv->cfg->base_params->num_of_ampdu_queues - 1);
-		return -EINVAL;
-	}
-
-	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-
-	iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-	/* supposes that ssn_idx is valid (!= 0xFFF) */
-	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-	iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-	iwl_txq_ctx_deactivate(priv, txq_id);
-	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
-
-	return 0;
-}
-
-/**
- * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
- */
-static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
-					u16 txq_id)
-{
-	u32 tbl_dw_addr;
-	u32 tbl_dw;
-	u16 scd_q2ratid;
-
-	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
-
-	tbl_dw_addr = priv->scd_base_addr +
-			IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
-
-	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
-
-	if (txq_id & 0x1)
-		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
-	else
-		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
-
-	iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
-
-	return 0;
-}
-
-
-/**
- * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
- *
- * NOTE:  txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE,
- *        i.e. it must be one of the higher queues used for aggregation
- */
-static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
-				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
-{
-	unsigned long flags;
-	u16 ra_tid;
-	int ret;
-
-	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWL49_FIRST_AMPDU_QUEUE +
-		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-		IWL_WARN(priv,
-			"queue number out of range: %d, must be %d to %d\n",
-			txq_id, IWL49_FIRST_AMPDU_QUEUE,
-			IWL49_FIRST_AMPDU_QUEUE +
-			priv->cfg->base_params->num_of_ampdu_queues - 1);
-		return -EINVAL;
-	}
-
-	ra_tid = BUILD_RAxTID(sta_id, tid);
-
-	/* Modify device's station table to Tx this TID */
-	ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
-	if (ret)
-		return ret;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Stop this Tx queue before configuring it */
-	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-
-	/* Map receiver-address / traffic-ID to this queue */
-	iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
-
-	/* Set this queue as a chain-building queue */
-	iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
-	/* Place first TFD at index corresponding to start sequence number.
-	 * Assumes that ssn_idx is valid (!= 0xFFF) */
-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-	/* Set up Tx window size and frame limit for this queue */
-	iwl_write_targ_mem(priv,
-		priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
-		(SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
-		IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-	iwl_write_targ_mem(priv, priv->scd_base_addr +
-		IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
-		(SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
-		& IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-	iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-
-	/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
-	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-
-static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
-{
-	switch (cmd_id) {
-	case REPLY_RXON:
-		return (u16) sizeof(struct iwl4965_rxon_cmd);
-	default:
-		return len;
-	}
-}
-
-static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
-	struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data;
-	addsta->mode = cmd->mode;
-	memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify));
-	memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo));
-	addsta->station_flags = cmd->station_flags;
-	addsta->station_flags_msk = cmd->station_flags_msk;
-	addsta->tid_disable_tx = cmd->tid_disable_tx;
-	addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid;
-	addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid;
-	addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn;
-	addsta->sleep_tx_count = cmd->sleep_tx_count;
-	addsta->reserved1 = cpu_to_le16(0);
-	addsta->reserved2 = cpu_to_le16(0);
-
-	return (u16)sizeof(struct iwl4965_addsta_cmd);
-}
-
-static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
-{
-	return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
-}
-
-/**
- * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
- */
-static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
-				      struct iwl_ht_agg *agg,
-				      struct iwl4965_tx_resp *tx_resp,
-				      int txq_id, u16 start_idx)
-{
-	u16 status;
-	struct agg_tx_status *frame_status = tx_resp->u.agg_status;
-	struct ieee80211_tx_info *info = NULL;
-	struct ieee80211_hdr *hdr = NULL;
-	u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-	int i, sh, idx;
-	u16 seq;
-	if (agg->wait_for_ba)
-		IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
-
-	agg->frame_count = tx_resp->frame_count;
-	agg->start_idx = start_idx;
-	agg->rate_n_flags = rate_n_flags;
-	agg->bitmap = 0;
-
-	/* num frames attempted by Tx command */
-	if (agg->frame_count == 1) {
-		/* Only one frame was attempted; no block-ack will arrive */
-		status = le16_to_cpu(frame_status[0].status);
-		idx = start_idx;
-
-		/* FIXME: code repetition */
-		IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
-				   agg->frame_count, agg->start_idx, idx);
-
-		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
-		info->status.rates[0].count = tx_resp->failure_frame + 1;
-		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-		info->flags |= iwl_tx_status_to_mac80211(status);
-		iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info);
-		/* FIXME: code repetition end */
-
-		IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
-				    status & 0xff, tx_resp->failure_frame);
-		IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
-
-		agg->wait_for_ba = 0;
-	} else {
-		/* Two or more frames were attempted; expect block-ack */
-		u64 bitmap = 0;
-		int start = agg->start_idx;
-
-		/* Construct bit-map of pending frames within Tx window */
-		for (i = 0; i < agg->frame_count; i++) {
-			u16 sc;
-			status = le16_to_cpu(frame_status[i].status);
-			seq  = le16_to_cpu(frame_status[i].sequence);
-			idx = SEQ_TO_INDEX(seq);
-			txq_id = SEQ_TO_QUEUE(seq);
-
-			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
-				      AGG_TX_STATE_ABORT_MSK))
-				continue;
-
-			IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
-					   agg->frame_count, txq_id, idx);
-
-			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
-			if (!hdr) {
-				IWL_ERR(priv,
-					"BUG_ON idx doesn't point to valid skb"
-					" idx=%d, txq_id=%d\n", idx, txq_id);
-				return -1;
-			}
-
-			sc = le16_to_cpu(hdr->seq_ctrl);
-			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-				IWL_ERR(priv,
-					"BUG_ON idx doesn't match seq control"
-					" idx=%d, seq_idx=%d, seq=%d\n",
-					idx, SEQ_TO_SN(sc), hdr->seq_ctrl);
-				return -1;
-			}
-
-			IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
-					   i, idx, SEQ_TO_SN(sc));
-
-			sh = idx - start;
-			if (sh > 64) {
-				sh = (start - idx) + 0xff;
-				bitmap = bitmap << sh;
-				sh = 0;
-				start = idx;
-			} else if (sh < -64)
-				sh  = 0xff - (start - idx);
-			else if (sh < 0) {
-				sh = start - idx;
-				start = idx;
-				bitmap = bitmap << sh;
-				sh = 0;
-			}
-			bitmap |= 1ULL << sh;
-			IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
-					   start, (unsigned long long)bitmap);
-		}
-
-		agg->bitmap = bitmap;
-		agg->start_idx = start;
-		IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
-				   agg->frame_count, agg->start_idx,
-				   (unsigned long long)agg->bitmap);
-
-		if (bitmap)
-			agg->wait_for_ba = 1;
-	}
-	return 0;
-}
-
-static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
-{
-	int i;
-	int start = 0;
-	int ret = IWL_INVALID_STATION;
-	unsigned long flags;
-
-	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
-	    (priv->iw_mode == NL80211_IFTYPE_AP))
-		start = IWL_STA_ID;
-
-	if (is_broadcast_ether_addr(addr))
-		return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	for (i = start; i < priv->hw_params.max_stations; i++)
-		if (priv->stations[i].used &&
-		    (!compare_ether_addr(priv->stations[i].sta.sta.addr,
-					 addr))) {
-			ret = i;
-			goto out;
-		}
-
-	IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
-			      addr, priv->num_stations);
-
- out:
-	/*
-	 * It may be possible that more commands interacting with stations
-	 * arrive before we completed processing the adding of
-	 * station
-	 */
-	if (ret != IWL_INVALID_STATION &&
-	    (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
-	     ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
-	      (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
-		IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
-			ret);
-		ret = IWL_INVALID_STATION;
-	}
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-	return ret;
-}
-
-static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
-{
-	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
-		return IWL_AP_ID;
-	} else {
-		u8 *da = ieee80211_get_DA(hdr);
-		return iwl_find_station(priv, da);
-	}
-}
-
-/**
- * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
- */
-static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-	int txq_id = SEQ_TO_QUEUE(sequence);
-	int index = SEQ_TO_INDEX(sequence);
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct ieee80211_hdr *hdr;
-	struct ieee80211_tx_info *info;
-	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-	u32  status = le32_to_cpu(tx_resp->u.status);
-	int uninitialized_var(tid);
-	int sta_id;
-	int freed;
-	u8 *qc = NULL;
-	unsigned long flags;
-
-	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
-			  "is out of range [0-%d] %d %d\n", txq_id,
-			  index, txq->q.n_bd, txq->q.write_ptr,
-			  txq->q.read_ptr);
-		return;
-	}
-
-	txq->time_stamp = jiffies;
-	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
-	memset(&info->status, 0, sizeof(info->status));
-
-	hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
-	if (ieee80211_is_data_qos(hdr->frame_control)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		tid = qc[0] & 0xf;
-	}
-
-	sta_id = iwl_get_ra_sta_id(priv, hdr);
-	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
-		IWL_ERR(priv, "Station not known\n");
-		return;
-	}
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	if (txq->sched_retry) {
-		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
-		struct iwl_ht_agg *agg = NULL;
-		WARN_ON(!qc);
-
-		agg = &priv->stations[sta_id].tid[tid].agg;
-
-		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
-
-		/* check if BAR is needed */
-		if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
-			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-
-		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
-			IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
-					   "%d index %d\n", scd_ssn , index);
-			freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
-			if (qc)
-				iwl_free_tfds_in_queue(priv, sta_id,
-						       tid, freed);
-
-			if (priv->mac80211_registered &&
-			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
-			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
-				iwl_wake_queue(priv, txq);
-		}
-	} else {
-		info->status.rates[0].count = tx_resp->failure_frame + 1;
-		info->flags |= iwl_tx_status_to_mac80211(status);
-		iwlagn_hwrate_to_tx_control(priv,
-					le32_to_cpu(tx_resp->rate_n_flags),
-					info);
-
-		IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) "
-				   "rate_n_flags 0x%x retries %d\n",
-				   txq_id,
-				   iwl_get_tx_fail_reason(status), status,
-				   le32_to_cpu(tx_resp->rate_n_flags),
-				   tx_resp->failure_frame);
-
-		freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
-		if (qc && likely(sta_id != IWL_INVALID_STATION))
-			iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-		else if (sta_id == IWL_INVALID_STATION)
-			IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
-
-		if (priv->mac80211_registered &&
-		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
-			iwl_wake_queue(priv, txq);
-	}
-	if (qc && likely(sta_id != IWL_INVALID_STATION))
-		iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
-
-	iwl_check_abort_status(priv, tx_resp->frame_count, status);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-static int iwl4965_calc_rssi(struct iwl_priv *priv,
-			     struct iwl_rx_phy_res *rx_resp)
-{
-	/* data from PHY/DSP regarding signal strength, etc.,
-	 *   contents are always there, not configurable by host.  */
-	struct iwl4965_rx_non_cfg_phy *ncphy =
-	    (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
-	u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK)
-			>> IWL49_AGC_DB_POS;
-
-	u32 valid_antennae =
-	    (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK)
-			>> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
-	u8 max_rssi = 0;
-	u32 i;
-
-	/* Find max rssi among 3 possible receivers.
-	 * These values are measured by the digital signal processor (DSP).
-	 * They should stay fairly constant even as the signal strength varies,
-	 *   if the radio's automatic gain control (AGC) is working right.
-	 * AGC value (see below) will provide the "interesting" info. */
-	for (i = 0; i < 3; i++)
-		if (valid_antennae & (1 << i))
-			max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
-
-	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
-		ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
-		max_rssi, agc);
-
-	/* dBm = max_rssi dB - agc dB - constant.
-	 * Higher AGC (higher radio gain) means lower signal. */
-	return max_rssi - agc - IWLAGN_RSSI_OFFSET;
-}
-
-
-/* Set up 4965-specific Rx frame reply handlers */
-static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
-{
-	/* Legacy Rx frames */
-	priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx;
-	/* Tx response */
-	priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
-}
-
-static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
-{
-	INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
-}
-
-static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
-{
-	cancel_work_sync(&priv->txpower_work);
-}
-
-static struct iwl_hcmd_ops iwl4965_hcmd = {
-	.rxon_assoc = iwl4965_send_rxon_assoc,
-	.commit_rxon = iwl4965_commit_rxon,
-	.set_rxon_chain = iwlagn_set_rxon_chain,
-	.send_bt_config = iwl_send_bt_config,
-};
-
-static void iwl4965_post_scan(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-		iwlcore_commit_rxon(priv, ctx);
-}
-
-static void iwl4965_post_associate(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_vif *vif = ctx->vif;
-	struct ieee80211_conf *conf = NULL;
-	int ret = 0;
-
-	if (!vif || !priv->is_open)
-		return;
-
-	if (vif->type == NL80211_IFTYPE_AP) {
-		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
-		return;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
-
-	ret = iwl_send_rxon_timing(priv, ctx);
-	if (ret)
-		IWL_WARN(priv, "RXON timing - "
-			    "Attempting to continue.\n");
-
-	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-	iwl_set_rxon_ht(priv, &priv->current_ht_config);
-
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
-
-	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			vif->bss_conf.aid, vif->bss_conf.beacon_int);
-
-	if (vif->bss_conf.use_short_preamble)
-		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-	else
-		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (vif->bss_conf.use_short_slot)
-			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-	}
-
-	iwlcore_commit_rxon(priv, ctx);
-
-	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, ctx->active.bssid_addr);
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		iwlagn_send_beacon_cmd(priv);
-		break;
-	default:
-		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			  __func__, vif->type);
-		break;
-	}
-
-	/* the chain noise calibration will enabled PM upon completion
-	 * If chain noise has already been run, then we need to enable
-	 * power management here */
-	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
-		iwl_power_update_mode(priv, false);
-
-	/* Enable Rx differential gain and sensitivity calibrations */
-	iwl_chain_noise_reset(priv);
-	priv->start_calib = 1;
-}
-
-static void iwl4965_config_ap(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_vif *vif = ctx->vif;
-	int ret = 0;
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* The following should be done only at AP bring up */
-	if (!iwl_is_associated_ctx(ctx)) {
-
-		/* RXON - unassoc (to set timing command) */
-		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-
-		/* RXON Timing */
-		ret = iwl_send_rxon_timing(priv, ctx);
-		if (ret)
-			IWL_WARN(priv, "RXON timing failed - "
-					"Attempting to continue.\n");
-
-		/* AP has all antennas */
-		priv->chain_noise_data.active_chains =
-			priv->hw_params.valid_rx_ant;
-		iwl_set_rxon_ht(priv, &priv->current_ht_config);
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-		ctx->staging.assoc_id = 0;
-
-		if (vif->bss_conf.use_short_preamble)
-			ctx->staging.flags |=
-				RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-			if (vif->bss_conf.use_short_slot)
-				ctx->staging.flags |=
-					RXON_FLG_SHORT_SLOT_MSK;
-			else
-				ctx->staging.flags &=
-					~RXON_FLG_SHORT_SLOT_MSK;
-		}
-		/* need to send beacon cmd before committing assoc RXON! */
-		iwlagn_send_beacon_cmd(priv);
-		/* restore RXON assoc */
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-	}
-	iwlagn_send_beacon_cmd(priv);
-
-	/* FIXME - we need to add code here to detect a totally new
-	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-	 * clear sta table, add BCAST sta... */
-}
-
-static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
-	.get_hcmd_size = iwl4965_get_hcmd_size,
-	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
-	.chain_noise_reset = iwl4965_chain_noise_reset,
-	.gain_computation = iwl4965_gain_computation,
-	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
-	.calc_rssi = iwl4965_calc_rssi,
-	.request_scan = iwlagn_request_scan,
-	.post_scan = iwl4965_post_scan,
-};
-
-static struct iwl_lib_ops iwl4965_lib = {
-	.set_hw_params = iwl4965_hw_set_hw_params,
-	.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
-	.txq_set_sched = iwl4965_txq_set_sched,
-	.txq_agg_enable = iwl4965_txq_agg_enable,
-	.txq_agg_disable = iwl4965_txq_agg_disable,
-	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-	.txq_free_tfd = iwl_hw_txq_free_tfd,
-	.txq_init = iwl_hw_tx_queue_init,
-	.rx_handler_setup = iwl4965_rx_handler_setup,
-	.setup_deferred_work = iwl4965_setup_deferred_work,
-	.cancel_deferred_work = iwl4965_cancel_deferred_work,
-	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
-	.alive_notify = iwl4965_alive_notify,
-	.init_alive_start = iwl4965_init_alive_start,
-	.load_ucode = iwl4965_load_bsm,
-	.dump_nic_event_log = iwl_dump_nic_event_log,
-	.dump_nic_error_log = iwl_dump_nic_error_log,
-	.dump_fh = iwl_dump_fh,
-	.set_channel_switch = iwl4965_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl4965_nic_config,
-	},
-	.eeprom_ops = {
-		.regulatory_bands = {
-			EEPROM_REGULATORY_BAND_1_CHANNELS,
-			EEPROM_REGULATORY_BAND_2_CHANNELS,
-			EEPROM_REGULATORY_BAND_3_CHANNELS,
-			EEPROM_REGULATORY_BAND_4_CHANNELS,
-			EEPROM_REGULATORY_BAND_5_CHANNELS,
-			EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
-			EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
-		},
-		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
-		.release_semaphore = iwlcore_eeprom_release_semaphore,
-		.calib_version = iwl4965_eeprom_calib_version,
-		.query_addr = iwlcore_eeprom_query_addr,
-	},
-	.send_tx_power	= iwl4965_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
-	.isr_ops = {
-		.isr = iwl_isr_legacy,
-	},
-	.temp_ops = {
-		.temperature = iwl4965_temperature_calib,
-	},
-	.debugfs_ops = {
-		.rx_stats_read = iwl_ucode_rx_stats_read,
-		.tx_stats_read = iwl_ucode_tx_stats_read,
-		.general_stats_read = iwl_ucode_general_stats_read,
-		.bt_stats_read = iwl_ucode_bt_stats_read,
-		.reply_tx_error = iwl_reply_tx_error_read,
-	},
-	.check_plcp_health = iwl_good_plcp_health,
-};
-
-static const struct iwl_legacy_ops iwl4965_legacy_ops = {
-	.post_associate = iwl4965_post_associate,
-	.config_ap = iwl4965_config_ap,
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
-};
-
-struct ieee80211_ops iwl4965_hw_ops = {
-	.tx = iwlagn_mac_tx,
-	.start = iwlagn_mac_start,
-	.stop = iwlagn_mac_stop,
-	.add_interface = iwl_mac_add_interface,
-	.remove_interface = iwl_mac_remove_interface,
-	.change_interface = iwl_mac_change_interface,
-	.config = iwl_legacy_mac_config,
-	.configure_filter = iwlagn_configure_filter,
-	.set_key = iwlagn_mac_set_key,
-	.update_tkip_key = iwlagn_mac_update_tkip_key,
-	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_legacy_mac_reset_tsf,
-	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
-	.ampdu_action = iwlagn_mac_ampdu_action,
-	.hw_scan = iwl_mac_hw_scan,
-	.sta_add = iwlagn_mac_sta_add,
-	.sta_remove = iwl_mac_sta_remove,
-	.channel_switch = iwlagn_mac_channel_switch,
-	.flush = iwlagn_mac_flush,
-	.tx_last_beacon = iwl_mac_tx_last_beacon,
-};
-
-static const struct iwl_ops iwl4965_ops = {
-	.lib = &iwl4965_lib,
-	.hcmd = &iwl4965_hcmd,
-	.utils = &iwl4965_hcmd_utils,
-	.led = &iwlagn_led_ops,
-	.legacy = &iwl4965_legacy_ops,
-	.ieee80211_ops = &iwl4965_hw_ops,
-};
-
-static struct iwl_base_params iwl4965_base_params = {
-	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
-	.num_of_queues = IWL49_NUM_QUEUES,
-	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = true,
-	.use_isr_legacy = true,
-	.broken_powersave = true,
-	.led_compensation = 61,
-	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.temperature_kelvin = true,
-	.max_event_log_size = 512,
-	.tx_power_by_driver = true,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
-	.no_agg_framecnt_info = true,
-};
-
-struct iwl_cfg iwl4965_agn_cfg = {
-	.name = "Intel(R) Wireless WiFi Link 4965AGN",
-	.fw_name_pre = IWL4965_FW_PRE,
-	.ucode_api_max = IWL4965_UCODE_API_MAX,
-	.ucode_api_min = IWL4965_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_ABC,
-	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
-	.ops = &iwl4965_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl4965_base_params,
-	.led_mode = IWL_LED_BLINK,
-	/*
-	 * Force use of chains B and C for scan RX on 5 GHz band
-	 * because the device has off-channel reception on chain A.
-	 */
-	.scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
-};
-
-/* Module firmware */
-MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
-
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 537fb8c..3ea31b6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -402,8 +402,6 @@ static struct iwl_lib_ops iwl5000_lib = {
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -471,8 +469,6 @@ static struct iwl_lib_ops iwl5150_lib = {
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index ef36aff..a745b01 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -67,13 +67,13 @@
 #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
 #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
 
-#define IWL6000G2A_FW_PRE "iwlwifi-6000g2a-"
-#define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode"
-#define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api)
+#define IWL6005_FW_PRE "iwlwifi-6000g2a-"
+#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE #api ".ucode"
+#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api)
 
-#define IWL6000G2B_FW_PRE "iwlwifi-6000g2b-"
-#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
-#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
+#define IWL6030_FW_PRE "iwlwifi-6000g2b-"
+#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE #api ".ucode"
+#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api)
 
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
@@ -90,7 +90,7 @@ static void iwl6050_additional_nic_config(struct iwl_priv *priv)
 				CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
 }
 
-static void iwl6050g2_additional_nic_config(struct iwl_priv *priv)
+static void iwl6150_additional_nic_config(struct iwl_priv *priv)
 {
 	/* Indicate calibration version to uCode. */
 	if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
@@ -343,8 +343,6 @@ static struct iwl_lib_ops iwl6000_lib = {
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -354,7 +352,7 @@ static struct iwl_lib_ops iwl6000_lib = {
 	}
 };
 
-static struct iwl_lib_ops iwl6000g2b_lib = {
+static struct iwl_lib_ops iwl6030_lib = {
 	.set_hw_params = iwl6000_hw_set_hw_params,
 	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
 	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
@@ -415,8 +413,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -430,8 +426,8 @@ static struct iwl_nic_ops iwl6050_nic_ops = {
 	.additional_nic_config = &iwl6050_additional_nic_config,
 };
 
-static struct iwl_nic_ops iwl6050g2_nic_ops = {
-	.additional_nic_config = &iwl6050g2_additional_nic_config,
+static struct iwl_nic_ops iwl6150_nic_ops = {
+	.additional_nic_config = &iwl6150_additional_nic_config,
 };
 
 static const struct iwl_ops iwl6000_ops = {
@@ -451,17 +447,17 @@ static const struct iwl_ops iwl6050_ops = {
 	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
-static const struct iwl_ops iwl6050g2_ops = {
+static const struct iwl_ops iwl6150_ops = {
 	.lib = &iwl6000_lib,
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
-	.nic = &iwl6050g2_nic_ops,
+	.nic = &iwl6150_nic_ops,
 	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
-static const struct iwl_ops iwl6000g2b_ops = {
-	.lib = &iwl6000g2b_lib,
+static const struct iwl_ops iwl6030_ops = {
+	.lib = &iwl6030_lib,
 	.hcmd = &iwlagn_bt_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
@@ -479,7 +475,6 @@ static struct iwl_base_params iwl6000_base_params = {
 	.shadow_ram_support = true,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -503,7 +498,6 @@ static struct iwl_base_params iwl6050_base_params = {
 	.shadow_ram_support = true,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -526,7 +520,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
 	.shadow_ram_support = true,
 	.led_compensation = 57,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -555,11 +548,11 @@ static struct iwl_bt_params iwl6000_bt_params = {
 };
 
 #define IWL_DEVICE_6005						\
-	.fw_name_pre = IWL6000G2A_FW_PRE,			\
+	.fw_name_pre = IWL6005_FW_PRE,			\
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,		\
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,	\
+	.eeprom_ver = EEPROM_6005_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
 	.ops = &iwl6000_ops,					\
 	.mod_params = &iwlagn_mod_params,			\
 	.base_params = &iwl6000_g2_base_params,			\
@@ -584,12 +577,12 @@ struct iwl_cfg iwl6005_2bg_cfg = {
 };
 
 #define IWL_DEVICE_6030						\
-	.fw_name_pre = IWL6000G2B_FW_PRE,			\
+	.fw_name_pre = IWL6030_FW_PRE,			\
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,		\
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,	\
-	.ops = &iwl6000g2b_ops,					\
+	.eeprom_ver = EEPROM_6030_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
+	.ops = &iwl6030_ops,					\
 	.mod_params = &iwlagn_mod_params,			\
 	.base_params = &iwl6000_g2_base_params,			\
 	.bt_params = &iwl6000_bt_params,			\
@@ -708,9 +701,9 @@ struct iwl_cfg iwl6150_bgn_cfg = {
 	.fw_name_pre = IWL6050_FW_PRE,
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
-	.eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
-	.ops = &iwl6050g2_ops,
+	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,
+	.ops = &iwl6150_ops,
 	.mod_params = &iwlagn_mod_params,
 	.base_params = &iwl6050_base_params,
 	.ht_params = &iwl6000_ht_params,
@@ -736,5 +729,5 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index d16bb5e..9006293 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -631,8 +631,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp)
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
 			      rx.general.common);
 		ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm);
@@ -897,8 +896,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
 			      rx.general.common);
 	} else {
@@ -913,8 +911,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
 
 	rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
 	rxon_chnum = le16_to_cpu(ctx->staging.channel);
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		stat_band24 = !!(((struct iwl_bt_notif_statistics *)
 				 stat_resp)->flag &
 				 STATISTICS_REPLY_FLG_BAND_24G_MSK);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
index a6dbd89..b500aaa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
@@ -39,8 +39,7 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
 	int p = 0;
 	u32 flag;
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics)
+	if (iwl_bt_statistics(priv))
 		flag = le32_to_cpu(priv->_agn.statistics_bt.flag);
 	else
 		flag = le32_to_cpu(priv->_agn.statistics.flag);
@@ -89,8 +88,7 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		ofdm = &priv->_agn.statistics_bt.rx.ofdm;
 		cck = &priv->_agn.statistics_bt.rx.cck;
 		general = &priv->_agn.statistics_bt.rx.general.common;
@@ -536,8 +534,7 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		tx = &priv->_agn.statistics_bt.tx;
 		accum_tx = &priv->_agn.accum_statistics_bt.tx;
 		delta_tx = &priv->_agn.delta_statistics_bt.tx;
@@ -737,8 +734,7 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		general = &priv->_agn.statistics_bt.general.common;
 		dbg = &priv->_agn.statistics_bt.general.common.dbg;
 		div = &priv->_agn.statistics_bt.general.common.div;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
index 366340f..41543ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
@@ -305,7 +305,11 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv)
 	cmd.slots[0].type = 0; /* BSS */
 	cmd.slots[1].type = 1; /* PAN */
 
-	if (ctx_bss->vif && ctx_pan->vif) {
+	if (priv->_agn.hw_roc_channel) {
+		/* both contexts must be used for this to happen */
+		slot1 = priv->_agn.hw_roc_duration;
+		slot0 = IWL_MIN_SLOT_TIME;
+	} else if (ctx_bss->vif && ctx_pan->vif) {
 		int bcnint = ctx_pan->vif->bss_conf.beacon_int;
 		int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
 
@@ -330,12 +334,12 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv)
 		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
 		    (!ctx_bss->vif->bss_conf.idle &&
 		     !ctx_bss->vif->bss_conf.assoc)) {
-			slot0 = dtim * bcnint * 3 - 20;
-			slot1 = 20;
+			slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
+			slot1 = IWL_MIN_SLOT_TIME;
 		} else if (!ctx_pan->vif->bss_conf.idle &&
 			   !ctx_pan->vif->bss_conf.assoc) {
-			slot1 = bcnint * 3 - 20;
-			slot0 = 20;
+			slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME;
+			slot0 = IWL_MIN_SLOT_TIME;
 		}
 	} else if (ctx_pan->vif) {
 		slot0 = 0;
@@ -344,8 +348,8 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv)
 		slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
 
 		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-			slot0 = slot1 * 3 - 20;
-			slot1 = 20;
+			slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
+			slot1 = IWL_MIN_SLOT_TIME;
 		}
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.c b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
index 1a24946..c1190d9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.c
@@ -63,23 +63,11 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
 }
 
 /* Set led register off */
-static int iwl_led_on_reg(struct iwl_priv *priv)
+void iwlagn_led_enable(struct iwl_priv *priv)
 {
-	IWL_DEBUG_LED(priv, "led on\n");
 	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
-	return 0;
-}
-
-/* Set led register off */
-static int iwl_led_off_reg(struct iwl_priv *priv)
-{
-	IWL_DEBUG_LED(priv, "LED Reg off\n");
-	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
-	return 0;
 }
 
 const struct iwl_led_ops iwlagn_led_ops = {
 	.cmd = iwl_send_led_cmd,
-	.on = iwl_led_on_reg,
-	.off = iwl_led_off_reg,
 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-led.h b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
index a594e4f..96f323d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-led.h
@@ -28,5 +28,6 @@
 #define __iwl_agn_led_h__
 
 extern const struct iwl_led_ops iwlagn_led_ops;
+void iwlagn_led_enable(struct iwl_priv *priv);
 
 #endif /* __iwl_agn_led_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 3dee87e..2003c1d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -473,6 +473,11 @@ void iwlagn_rx_handler_setup(struct iwl_priv *priv)
 	priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
 					iwlagn_rx_calib_complete;
 	priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
+
+	/* set up notification wait support */
+	spin_lock_init(&priv->_agn.notif_wait_lock);
+	INIT_LIST_HEAD(&priv->_agn.notif_waits);
+	init_waitqueue_head(&priv->_agn.notif_waitq);
 }
 
 void iwlagn_setup_deferred_work(struct iwl_priv *priv)
@@ -528,9 +533,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 
 void iwlagn_temperature(struct iwl_priv *priv)
 {
-	/* store temperature from statistics (in Celsius) */
-	priv->temperature =
-		le32_to_cpu(priv->_agn.statistics.general.common.temperature);
+	/* store temperature from correct statistics (in Celsius) */
+	priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ?
+		priv->_agn.statistics_bt.general.common.temperature :
+		priv->_agn.statistics.general.common.temperature);
 	iwl_tt_handler(priv);
 }
 
@@ -604,6 +610,7 @@ const u8 *iwlagn_eeprom_query_addr(const struct iwl_priv *priv,
 struct iwl_mod_params iwlagn_mod_params = {
 	.amsdu_size_8K = 1,
 	.restart_fw = 1,
+	.plcp_check = true,
 	/* the rest are 0 by default */
 };
 
@@ -988,240 +995,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
 	return -1;
 }
 
-/* Calc max signal level (dBm) among 3 possible receivers */
-static inline int iwlagn_calc_rssi(struct iwl_priv *priv,
-				struct iwl_rx_phy_res *rx_resp)
-{
-	return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
-}
-
-static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
-{
-	u32 decrypt_out = 0;
-
-	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
-					RX_RES_STATUS_STATION_FOUND)
-		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
-				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
-
-	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
-
-	/* packet was not encrypted */
-	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-					RX_RES_STATUS_SEC_TYPE_NONE)
-		return decrypt_out;
-
-	/* packet was encrypted with unknown alg */
-	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-					RX_RES_STATUS_SEC_TYPE_ERR)
-		return decrypt_out;
-
-	/* decryption was not done in HW */
-	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
-					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
-		return decrypt_out;
-
-	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
-
-	case RX_RES_STATUS_SEC_TYPE_CCMP:
-		/* alg is CCM: check MIC only */
-		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
-			/* Bad MIC */
-			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-		else
-			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-
-		break;
-
-	case RX_RES_STATUS_SEC_TYPE_TKIP:
-		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
-			/* Bad TTAK */
-			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
-			break;
-		}
-		/* fall through if TTAK OK */
-	default:
-		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
-			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-		else
-			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-		break;
-	}
-
-	IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
-					decrypt_in, decrypt_out);
-
-	return decrypt_out;
-}
-
-static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
-					struct ieee80211_hdr *hdr,
-					u16 len,
-					u32 ampdu_status,
-					struct iwl_rx_mem_buffer *rxb,
-					struct ieee80211_rx_status *stats)
-{
-	struct sk_buff *skb;
-	__le16 fc = hdr->frame_control;
-
-	/* We only process data packets if the interface is open */
-	if (unlikely(!priv->is_open)) {
-		IWL_DEBUG_DROP_LIMIT(priv,
-		    "Dropping packet while interface is not open.\n");
-		return;
-	}
-
-	/* In case of HW accelerated crypto and bad decryption, drop */
-	if (!priv->cfg->mod_params->sw_crypto &&
-	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
-		return;
-
-	skb = dev_alloc_skb(128);
-	if (!skb) {
-		IWL_ERR(priv, "dev_alloc_skb failed\n");
-		return;
-	}
-
-	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
-
-	iwl_update_stats(priv, false, fc, len);
-	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
-	ieee80211_rx(priv->hw, skb);
-	priv->alloc_rxb_page--;
-	rxb->page = NULL;
-}
-
-/* Called for REPLY_RX (legacy ABG frames), or
- * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-void iwlagn_rx_reply_rx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_rx_phy_res *phy_res;
-	__le32 rx_pkt_status;
-	struct iwl_rx_mpdu_res_start *amsdu;
-	u32 len;
-	u32 ampdu_status;
-	u32 rate_n_flags;
-
-	/**
-	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
-	 *	REPLY_RX: physical layer info is in this buffer
-	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
-	 *		command and cached in priv->last_phy_res
-	 *
-	 * Here we set up local variables depending on which command is
-	 * received.
-	 */
-	if (pkt->hdr.cmd == REPLY_RX) {
-		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
-		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
-				+ phy_res->cfg_phy_cnt);
-
-		len = le16_to_cpu(phy_res->byte_count);
-		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
-				phy_res->cfg_phy_cnt + len);
-		ampdu_status = le32_to_cpu(rx_pkt_status);
-	} else {
-		if (!priv->_agn.last_phy_res_valid) {
-			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
-			return;
-		}
-		phy_res = &priv->_agn.last_phy_res;
-		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
-		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
-		len = le16_to_cpu(amsdu->byte_count);
-		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
-		ampdu_status = iwlagn_translate_rx_status(priv,
-				le32_to_cpu(rx_pkt_status));
-	}
-
-	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
-		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-				phy_res->cfg_phy_cnt);
-		return;
-	}
-
-	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
-	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
-				le32_to_cpu(rx_pkt_status));
-		return;
-	}
-
-	/* This will be used in several places later */
-	rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
-
-	/* rx_status carries information about the packet to mac80211 */
-	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
-	rx_status.freq =
-		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
-	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-	rx_status.rate_idx =
-		iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
-	rx_status.flag = 0;
-
-	/* TSF isn't reliable. In order to allow smooth user experience,
-	 * this W/A doesn't propagate it to the mac80211 */
-	/*rx_status.flag |= RX_FLAG_TSFT;*/
-
-	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
-
-	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
-	rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
-
-	iwl_dbg_log_rx_data_frame(priv, len, header);
-	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
-		rx_status.signal, (unsigned long long)rx_status.mactime);
-
-	/*
-	 * "antenna number"
-	 *
-	 * It seems that the antenna field in the phy flags value
-	 * is actually a bit field. This is undefined by radiotap,
-	 * it wants an actual antenna number but I always get "7"
-	 * for most legacy frames I receive indicating that the
-	 * same frame was received on all three RX chains.
-	 *
-	 * I think this field should be removed in favor of a
-	 * new 802.11n radiotap field "RX chains" that is defined
-	 * as a bitmask.
-	 */
-	rx_status.antenna =
-		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
-		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
-
-	/* set the preamble flag if appropriate */
-	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-		rx_status.flag |= RX_FLAG_SHORTPRE;
-
-	/* Set up the HT phy flags */
-	if (rate_n_flags & RATE_MCS_HT_MSK)
-		rx_status.flag |= RX_FLAG_HT;
-	if (rate_n_flags & RATE_MCS_HT40_MSK)
-		rx_status.flag |= RX_FLAG_40MHZ;
-	if (rate_n_flags & RATE_MCS_SGI_MSK)
-		rx_status.flag |= RX_FLAG_SHORT_GI;
-
-	iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status,
-				    rxb, &rx_status);
-}
-
-/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
-			    struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	priv->_agn.last_phy_res_valid = true;
-	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
-	       sizeof(struct iwl_rx_phy_res));
-}
-
 static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
 					   struct ieee80211_vif *vif,
 					   enum ieee80211_band band,
@@ -1342,6 +1115,18 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
 	return added;
 }
 
+static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
+{
+	struct sk_buff *skb = priv->_agn.offchan_tx_skb;
+
+	if (skb->len < maxlen)
+		maxlen = skb->len;
+
+	memcpy(data, skb->data, maxlen);
+
+	return maxlen;
+}
+
 int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
 	struct iwl_host_cmd cmd = {
@@ -1384,20 +1169,25 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
-	if (iwl_is_any_associated(priv)) {
+	if (priv->scan_type != IWL_SCAN_OFFCH_TX &&
+	    iwl_is_any_associated(priv)) {
 		u16 interval = 0;
 		u32 extra;
 		u32 suspend_time = 100;
 		u32 scan_suspend_time = 100;
-		unsigned long flags;
 
 		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-		spin_lock_irqsave(&priv->lock, flags);
-		if (priv->is_internal_short_scan)
+		switch (priv->scan_type) {
+		case IWL_SCAN_OFFCH_TX:
+			WARN_ON(1);
+			break;
+		case IWL_SCAN_RADIO_RESET:
 			interval = 0;
-		else
+			break;
+		case IWL_SCAN_NORMAL:
 			interval = vif->bss_conf.beacon_int;
-		spin_unlock_irqrestore(&priv->lock, flags);
+			break;
+		}
 
 		scan->suspend_time = 0;
 		scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -1410,29 +1200,41 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		scan->suspend_time = cpu_to_le32(scan_suspend_time);
 		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
 			       scan_suspend_time, interval);
+	} else if (priv->scan_type == IWL_SCAN_OFFCH_TX) {
+		scan->suspend_time = 0;
+		scan->max_out_time =
+			cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout);
 	}
 
-	if (priv->is_internal_short_scan) {
+	switch (priv->scan_type) {
+	case IWL_SCAN_RADIO_RESET:
 		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else if (priv->scan_request->n_ssids) {
-		int i, p = 0;
-		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
-		for (i = 0; i < priv->scan_request->n_ssids; i++) {
-			/* always does wildcard anyway */
-			if (!priv->scan_request->ssids[i].ssid_len)
-				continue;
-			scan->direct_scan[p].id = WLAN_EID_SSID;
-			scan->direct_scan[p].len =
-				priv->scan_request->ssids[i].ssid_len;
-			memcpy(scan->direct_scan[p].ssid,
-			       priv->scan_request->ssids[i].ssid,
-			       priv->scan_request->ssids[i].ssid_len);
-			n_probes++;
-			p++;
-		}
-		is_active = true;
-	} else
-		IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
+		break;
+	case IWL_SCAN_NORMAL:
+		if (priv->scan_request->n_ssids) {
+			int i, p = 0;
+			IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
+			for (i = 0; i < priv->scan_request->n_ssids; i++) {
+				/* always does wildcard anyway */
+				if (!priv->scan_request->ssids[i].ssid_len)
+					continue;
+				scan->direct_scan[p].id = WLAN_EID_SSID;
+				scan->direct_scan[p].len =
+					priv->scan_request->ssids[i].ssid_len;
+				memcpy(scan->direct_scan[p].ssid,
+				       priv->scan_request->ssids[i].ssid,
+				       priv->scan_request->ssids[i].ssid_len);
+				n_probes++;
+				p++;
+			}
+			is_active = true;
+		} else
+			IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
+		break;
+	case IWL_SCAN_OFFCH_TX:
+		IWL_DEBUG_SCAN(priv, "Start offchannel TX scan.\n");
+		break;
+	}
 
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
 	scan->tx_cmd.sta_id = ctx->bcast_sta_id;
@@ -1530,38 +1332,77 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
 	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
 	scan->rx_chain = cpu_to_le16(rx_chain);
-	if (!priv->is_internal_short_scan) {
+	switch (priv->scan_type) {
+	case IWL_SCAN_NORMAL:
 		cmd_len = iwl_fill_probe_req(priv,
 					(struct ieee80211_mgmt *)scan->data,
 					vif->addr,
 					priv->scan_request->ie,
 					priv->scan_request->ie_len,
 					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-	} else {
+		break;
+	case IWL_SCAN_RADIO_RESET:
 		/* use bcast addr, will not be transmitted but must be valid */
 		cmd_len = iwl_fill_probe_req(priv,
 					(struct ieee80211_mgmt *)scan->data,
 					iwl_bcast_addr, NULL, 0,
 					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
+		break;
+	case IWL_SCAN_OFFCH_TX:
+		cmd_len = iwl_fill_offch_tx(priv, scan->data,
+					    IWL_MAX_SCAN_SIZE
+					     - sizeof(*scan)
+					     - sizeof(struct iwl_scan_channel));
+		scan->scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX;
+		break;
+	default:
+		BUG();
 	}
 	scan->tx_cmd.len = cpu_to_le16(cmd_len);
 
 	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
 			       RXON_FILTER_BCON_AWARE_MSK);
 
-	if (priv->is_internal_short_scan) {
+	switch (priv->scan_type) {
+	case IWL_SCAN_RADIO_RESET:
 		scan->channel_count =
 			iwl_get_single_channel_for_scan(priv, vif, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
+				(void *)&scan->data[cmd_len]);
+		break;
+	case IWL_SCAN_NORMAL:
 		scan->channel_count =
 			iwl_get_channels_for_scan(priv, vif, band,
 				is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
+				(void *)&scan->data[cmd_len]);
+		break;
+	case IWL_SCAN_OFFCH_TX: {
+		struct iwl_scan_channel *scan_ch;
+
+		scan->channel_count = 1;
+
+		scan_ch = (void *)&scan->data[cmd_len];
+		scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+		scan_ch->channel =
+			cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value);
+		scan_ch->active_dwell =
+			cpu_to_le16(priv->_agn.offchan_tx_timeout);
+		scan_ch->passive_dwell = 0;
+
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+
+		/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+		 * power level:
+		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+		 */
+		if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+		}
+		break;
 	}
+
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
 		return -EIO;
@@ -1801,26 +1642,39 @@ static const __le32 iwlagn_concurrent_lookup[12] = {
 
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 {
-	struct iwlagn_bt_cmd bt_cmd = {
+	struct iwl_basic_bt_cmd basic = {
 		.max_kill = IWLAGN_BT_MAX_KILL_DEFAULT,
 		.bt3_timer_t7_value = IWLAGN_BT3_T7_DEFAULT,
 		.bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT,
 		.bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT,
 	};
+	struct iwl6000_bt_cmd bt_cmd_6000;
+	struct iwl2000_bt_cmd bt_cmd_2000;
+	int ret;
 
 	BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
-			sizeof(bt_cmd.bt3_lookup_table));
-
-	if (priv->cfg->bt_params)
-		bt_cmd.prio_boost = priv->cfg->bt_params->bt_prio_boost;
-	else
-		bt_cmd.prio_boost = 0;
-	bt_cmd.kill_ack_mask = priv->kill_ack_mask;
-	bt_cmd.kill_cts_mask = priv->kill_cts_mask;
+			sizeof(basic.bt3_lookup_table));
+
+	if (priv->cfg->bt_params) {
+		if (priv->cfg->bt_params->bt_session_2) {
+			bt_cmd_2000.prio_boost = cpu_to_le32(
+				priv->cfg->bt_params->bt_prio_boost);
+			bt_cmd_2000.tx_prio_boost = 0;
+			bt_cmd_2000.rx_prio_boost = 0;
+		} else {
+			bt_cmd_6000.prio_boost =
+				priv->cfg->bt_params->bt_prio_boost;
+			bt_cmd_6000.tx_prio_boost = 0;
+			bt_cmd_6000.rx_prio_boost = 0;
+		}
+	} else {
+		IWL_ERR(priv, "failed to construct BT Coex Config\n");
+		return;
+	}
 
-	bt_cmd.valid = priv->bt_valid;
-	bt_cmd.tx_prio_boost = 0;
-	bt_cmd.rx_prio_boost = 0;
+	basic.kill_ack_mask = priv->kill_ack_mask;
+	basic.kill_cts_mask = priv->kill_cts_mask;
+	basic.valid = priv->bt_valid;
 
 	/*
 	 * Configure BT coex mode to "no coexistence" when the
@@ -1829,49 +1683,45 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 	 * IBSS mode (no proper uCode support for coex then).
 	 */
 	if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
-		bt_cmd.flags = 0;
+		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
 	} else {
-		bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
+		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
 					IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
 		if (priv->cfg->bt_params &&
 		    priv->cfg->bt_params->bt_sco_disable)
-			bt_cmd.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+			basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
 
 		if (priv->bt_ch_announce)
-			bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
-		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags);
+			basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
+		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags);
 	}
-	priv->bt_enable_flag = bt_cmd.flags;
+	priv->bt_enable_flag = basic.flags;
 	if (priv->bt_full_concurrent)
-		memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
+		memcpy(basic.bt3_lookup_table, iwlagn_concurrent_lookup,
 			sizeof(iwlagn_concurrent_lookup));
 	else
-		memcpy(bt_cmd.bt3_lookup_table, iwlagn_def_3w_lookup,
+		memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
 			sizeof(iwlagn_def_3w_lookup));
 
 	IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
-		       bt_cmd.flags ? "active" : "disabled",
+		       basic.flags ? "active" : "disabled",
 		       priv->bt_full_concurrent ?
 		       "full concurrency" : "3-wire");
 
-	if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd))
+	if (priv->cfg->bt_params->bt_session_2) {
+		memcpy(&bt_cmd_2000.basic, &basic,
+			sizeof(basic));
+		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+			sizeof(bt_cmd_2000), &bt_cmd_2000);
+	} else {
+		memcpy(&bt_cmd_6000.basic, &basic,
+			sizeof(basic));
+		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+			sizeof(bt_cmd_6000), &bt_cmd_6000);
+	}
+	if (ret)
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 
-	/*
-	 * When we are doing a restart, need to also reconfigure BT
-	 * SCO to the device. If not doing a restart, bt_sco_active
-	 * will always be false, so there's no need to have an extra
-	 * variable to check for it.
-	 */
-	if (priv->bt_sco_active) {
-		struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
-
-		if (priv->bt_sco_active)
-			sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
-		if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO,
-				     sizeof(sco_cmd), &sco_cmd))
-			IWL_ERR(priv, "failed to send BT SCO command\n");
-	}
 }
 
 static void iwlagn_bt_traffic_change_work(struct work_struct *work)
@@ -1881,6 +1731,11 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 	struct iwl_rxon_context *ctx;
 	int smps_request = -1;
 
+	if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
+		/* bt coex disabled */
+		return;
+	}
+
 	/*
 	 * Note: bt_traffic_load can be overridden by scan complete and
 	 * coex profile notifications. Ignore that since only bad consequence
@@ -1991,12 +1846,14 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
 		(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
 			BT_UART_MSG_FRAME6DISCOVERABLE_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = "
-			"0x%X, Connectable = 0x%X",
+	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = "
+			"0x%X, Inquiry = 0x%X, Connectable = 0x%X",
 		(BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
 			BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
-		(BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK & uart_msg->frame7) >>
-			BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS,
+		(BT_UART_MSG_FRAME7PAGE_MSK & uart_msg->frame7) >>
+			BT_UART_MSG_FRAME7PAGE_POS,
+		(BT_UART_MSG_FRAME7INQUIRY_MSK & uart_msg->frame7) >>
+			BT_UART_MSG_FRAME7INQUIRY_POS,
 		(BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >>
 			BT_UART_MSG_FRAME7CONNECTABLE_POS);
 }
@@ -2032,9 +1889,13 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 	unsigned long flags;
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
-	struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
 	struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
 
+	if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
+		/* bt coex disabled */
+		return;
+	}
+
 	IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
 	IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
 	IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load);
@@ -2063,15 +1924,6 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
 			queue_work(priv->workqueue,
 				   &priv->bt_traffic_change_work);
 		}
-		if (priv->bt_sco_active !=
-		    (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) {
-			priv->bt_sco_active = uart_msg->frame3 &
-				BT_UART_MSG_FRAME3SCOESCO_MSK;
-			if (priv->bt_sco_active)
-				sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
-			iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO,
-				       sizeof(sco_cmd), &sco_cmd, NULL);
-		}
 	}
 
 	iwlagn_set_kill_msk(priv, uart_msg);
@@ -2389,3 +2241,44 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
 	}
 	return 0;
 }
+
+/* notification wait support */
+void iwlagn_init_notification_wait(struct iwl_priv *priv,
+				   struct iwl_notification_wait *wait_entry,
+				   void (*fn)(struct iwl_priv *priv,
+					      struct iwl_rx_packet *pkt),
+				   u8 cmd)
+{
+	wait_entry->fn = fn;
+	wait_entry->cmd = cmd;
+	wait_entry->triggered = false;
+
+	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	list_add(&wait_entry->list, &priv->_agn.notif_waits);
+	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
+
+signed long iwlagn_wait_notification(struct iwl_priv *priv,
+				     struct iwl_notification_wait *wait_entry,
+				     unsigned long timeout)
+{
+	int ret;
+
+	ret = wait_event_timeout(priv->_agn.notif_waitq,
+				 &wait_entry->triggered,
+				 timeout);
+
+	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	list_del(&wait_entry->list);
+	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+
+	return ret;
+}
+
+void iwlagn_remove_notification(struct iwl_priv *priv,
+				struct iwl_notification_wait *wait_entry)
+{
+	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	list_del(&wait_entry->list);
+	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 75fcd30..d03b473 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -179,31 +179,31 @@ static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
 };
 
 static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
-	{0, 0, 0, 0, 42, 0,  76, 102, 124, 158, 183, 193, 202}, /* Norm */
-	{0, 0, 0, 0, 46, 0,  82, 110, 132, 167, 192, 202, 210}, /* SGI */
-	{0, 0, 0, 0, 48, 0,  93, 135, 176, 251, 319, 351, 381}, /* AGG */
-	{0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
+	{0, 0, 0, 0, 42, 0,  76, 102, 124, 159, 183, 193, 202}, /* Norm */
+	{0, 0, 0, 0, 46, 0,  82, 110, 132, 168, 192, 202, 210}, /* SGI */
+	{0, 0, 0, 0, 47, 0,  91, 133, 171, 242, 305, 334, 362}, /* AGG */
+	{0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */
 };
 
 static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
 	{0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
-	{0, 0, 0, 0,  96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
-	{0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
+	{0, 0, 0, 0,  94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */
+	{0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */
 };
 
 static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
-	{0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
-	{0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
-	{0, 0, 0, 0,  92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
-	{0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
+	{0, 0, 0, 0,  74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */
+	{0, 0, 0, 0,  81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */
+	{0, 0, 0, 0,  89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */
+	{0, 0, 0, 0,  97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/
 };
 
 static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
 	{0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
-	{0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
-	{0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
+	{0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */
+	{0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */
 };
 
 static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
@@ -2890,6 +2890,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
 	u8 ant_toggle_cnt = 0;
 	u8 use_ht_possible = 1;
 	u8 valid_tx_ant = 0;
+	struct iwl_station_priv *sta_priv =
+		container_of(lq_sta, struct iwl_station_priv, lq_sta);
 	struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
 
 	/* Override starting rate (index 0) if needed for debug purposes */
@@ -3008,7 +3010,8 @@ static void rs_fill_link_cmd(struct iwl_priv *priv,
 		repeat_rate--;
 	}
 
-	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+	lq_cmd->agg_params.agg_frame_cnt_limit =
+		sta_priv->max_agg_bufsize ?: LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 	lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
 
 	lq_cmd->agg_params.agg_time_limit =
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index 75e50d3..184828c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -213,6 +213,7 @@ enum {
 	 IWL_CCK_BASIC_RATES_MASK)
 
 #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
+#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1)
 
 #define IWL_INVALID_VALUE    -1
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
deleted file mode 100644
index bbd40b7..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-agn-calib.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-agn-hw.h"
-#include "iwl-agn.h"
-
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_missed_beacon_notif *missed_beacon;
-
-	missed_beacon = &pkt->u.missed_beacon;
-	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
-	    priv->missed_beacon_threshold) {
-		IWL_DEBUG_CALIB(priv,
-		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
-		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
-		    le32_to_cpu(missed_beacon->total_missed_becons),
-		    le32_to_cpu(missed_beacon->num_recvd_beacons),
-		    le32_to_cpu(missed_beacon->num_expected_beacons));
-		if (!test_bit(STATUS_SCANNING, &priv->status))
-			iwl_init_sensitivity(priv);
-	}
-}
-
-/* Calculate noise level, based on measurements during network silence just
- *   before arriving beacon.  This measurement can be done only if we know
- *   exactly when to expect beacons, therefore only when we're associated. */
-static void iwl_rx_calc_noise(struct iwl_priv *priv)
-{
-	struct statistics_rx_non_phy *rx_info;
-	int num_active_rx = 0;
-	int total_silence = 0;
-	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
-	int last_rx_noise;
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics)
-		rx_info = &(priv->_agn.statistics_bt.rx.general.common);
-	else
-		rx_info = &(priv->_agn.statistics.rx.general);
-	bcn_silence_a =
-		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
-	bcn_silence_b =
-		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
-	bcn_silence_c =
-		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
-
-	if (bcn_silence_a) {
-		total_silence += bcn_silence_a;
-		num_active_rx++;
-	}
-	if (bcn_silence_b) {
-		total_silence += bcn_silence_b;
-		num_active_rx++;
-	}
-	if (bcn_silence_c) {
-		total_silence += bcn_silence_c;
-		num_active_rx++;
-	}
-
-	/* Average among active antennas */
-	if (num_active_rx)
-		last_rx_noise = (total_silence / num_active_rx) - 107;
-	else
-		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
-	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
-			bcn_silence_a, bcn_silence_b, bcn_silence_c,
-			last_rx_noise);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/*
- *  based on the assumption of all statistics counter are in DWORD
- *  FIXME: This function is for debugging, do not deal with
- *  the case of counters roll-over.
- */
-static void iwl_accumulative_statistics(struct iwl_priv *priv,
-					__le32 *stats)
-{
-	int i, size;
-	__le32 *prev_stats;
-	u32 *accum_stats;
-	u32 *delta, *max_delta;
-	struct statistics_general_common *general, *accum_general;
-	struct statistics_tx *tx, *accum_tx;
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
-		prev_stats = (__le32 *)&priv->_agn.statistics_bt;
-		accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
-		size = sizeof(struct iwl_bt_notif_statistics);
-		general = &priv->_agn.statistics_bt.general.common;
-		accum_general = &priv->_agn.accum_statistics_bt.general.common;
-		tx = &priv->_agn.statistics_bt.tx;
-		accum_tx = &priv->_agn.accum_statistics_bt.tx;
-		delta = (u32 *)&priv->_agn.delta_statistics_bt;
-		max_delta = (u32 *)&priv->_agn.max_delta_bt;
-	} else {
-		prev_stats = (__le32 *)&priv->_agn.statistics;
-		accum_stats = (u32 *)&priv->_agn.accum_statistics;
-		size = sizeof(struct iwl_notif_statistics);
-		general = &priv->_agn.statistics.general.common;
-		accum_general = &priv->_agn.accum_statistics.general.common;
-		tx = &priv->_agn.statistics.tx;
-		accum_tx = &priv->_agn.accum_statistics.tx;
-		delta = (u32 *)&priv->_agn.delta_statistics;
-		max_delta = (u32 *)&priv->_agn.max_delta;
-	}
-	for (i = sizeof(__le32); i < size;
-	     i += sizeof(__le32), stats++, prev_stats++, delta++,
-	     max_delta++, accum_stats++) {
-		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-			*delta = (le32_to_cpu(*stats) -
-				le32_to_cpu(*prev_stats));
-			*accum_stats += *delta;
-			if (*delta > *max_delta)
-				*max_delta = *delta;
-		}
-	}
-
-	/* reset accumulative statistics for "no-counter" type statistics */
-	accum_general->temperature = general->temperature;
-	accum_general->temperature_m = general->temperature_m;
-	accum_general->ttl_timestamp = general->ttl_timestamp;
-	accum_tx->tx_power.ant_a = tx->tx_power.ant_a;
-	accum_tx->tx_power.ant_b = tx->tx_power.ant_b;
-	accum_tx->tx_power.ant_c = tx->tx_power.ant_c;
-}
-#endif
-
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int combined_plcp_delta;
-	unsigned int plcp_msec;
-	unsigned long plcp_received_jiffies;
-
-	if (priv->cfg->base_params->plcp_delta_threshold ==
-	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
-		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
-		return rc;
-	}
-
-	/*
-	 * check for plcp_err and trigger radio reset if it exceeds
-	 * the plcp error threshold plcp_delta.
-	 */
-	plcp_received_jiffies = jiffies;
-	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-					(long) priv->plcp_jiffies);
-	priv->plcp_jiffies = plcp_received_jiffies;
-	/*
-	 * check to make sure plcp_msec is not 0 to prevent division
-	 * by zero.
-	 */
-	if (plcp_msec) {
-		struct statistics_rx_phy *ofdm;
-		struct statistics_rx_ht_phy *ofdm_ht;
-
-		if (priv->cfg->bt_params &&
-		    priv->cfg->bt_params->bt_statistics) {
-			ofdm = &pkt->u.stats_bt.rx.ofdm;
-			ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht;
-			combined_plcp_delta =
-			   (le32_to_cpu(ofdm->plcp_err) -
-			   le32_to_cpu(priv->_agn.statistics_bt.
-				       rx.ofdm.plcp_err)) +
-			   (le32_to_cpu(ofdm_ht->plcp_err) -
-			   le32_to_cpu(priv->_agn.statistics_bt.
-				       rx.ofdm_ht.plcp_err));
-		} else {
-			ofdm = &pkt->u.stats.rx.ofdm;
-			ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
-			combined_plcp_delta =
-			    (le32_to_cpu(ofdm->plcp_err) -
-			    le32_to_cpu(priv->_agn.statistics.
-					rx.ofdm.plcp_err)) +
-			    (le32_to_cpu(ofdm_ht->plcp_err) -
-			    le32_to_cpu(priv->_agn.statistics.
-					rx.ofdm_ht.plcp_err));
-		}
-
-		if ((combined_plcp_delta > 0) &&
-		    ((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->base_params->plcp_delta_threshold) {
-			/*
-			 * if plcp_err exceed the threshold,
-			 * the following data is printed in csv format:
-			 *    Text: plcp_err exceeded %d,
-			 *    Received ofdm.plcp_err,
-			 *    Current ofdm.plcp_err,
-			 *    Received ofdm_ht.plcp_err,
-			 *    Current ofdm_ht.plcp_err,
-			 *    combined_plcp_delta,
-			 *    plcp_msec
-			 */
-			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				"%u, %u, %u, %u, %d, %u mSecs\n",
-				priv->cfg->base_params->plcp_delta_threshold,
-				le32_to_cpu(ofdm->plcp_err),
-				le32_to_cpu(ofdm->plcp_err),
-				le32_to_cpu(ofdm_ht->plcp_err),
-				le32_to_cpu(ofdm_ht->plcp_err),
-				combined_plcp_delta, plcp_msec);
-
-			rc = false;
-		}
-	}
-	return rc;
-}
-
-void iwl_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	int change;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
-		IWL_DEBUG_RX(priv,
-			     "Statistics notification received (%d vs %d).\n",
-			     (int)sizeof(struct iwl_bt_notif_statistics),
-			     le32_to_cpu(pkt->len_n_flags) &
-			     FH_RSCSR_FRAME_SIZE_MSK);
-
-		change = ((priv->_agn.statistics_bt.general.common.temperature !=
-			   pkt->u.stats_bt.general.common.temperature) ||
-			   ((priv->_agn.statistics_bt.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-			   (pkt->u.stats_bt.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt);
-#endif
-
-	} else {
-		IWL_DEBUG_RX(priv,
-			     "Statistics notification received (%d vs %d).\n",
-			     (int)sizeof(struct iwl_notif_statistics),
-			     le32_to_cpu(pkt->len_n_flags) &
-			     FH_RSCSR_FRAME_SIZE_MSK);
-
-		change = ((priv->_agn.statistics.general.common.temperature !=
-			   pkt->u.stats.general.common.temperature) ||
-			   ((priv->_agn.statistics.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-			   (pkt->u.stats.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
-#endif
-
-	}
-
-	iwl_recover_from_statistics(priv, pkt);
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics)
-		memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
-			sizeof(priv->_agn.statistics_bt));
-	else
-		memcpy(&priv->_agn.statistics, &pkt->u.stats,
-			sizeof(priv->_agn.statistics));
-
-	set_bit(STATUS_STATISTICS, &priv->status);
-
-	/* Reschedule the statistics timer to occur in
-	 * REG_RECALIB_PERIOD seconds to ensure we get a
-	 * thermal update even if the uCode doesn't give
-	 * us one */
-	mod_timer(&priv->statistics_periodic, jiffies +
-		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
-
-	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
-		iwl_rx_calc_noise(priv);
-		queue_work(priv->workqueue, &priv->run_time_calib_work);
-	}
-	if (priv->cfg->ops->lib->temp_ops.temperature && change)
-		priv->cfg->ops->lib->temp_ops.temperature(priv);
-}
-
-void iwl_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->_agn.accum_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->_agn.delta_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->_agn.max_delta, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->_agn.accum_statistics_bt, 0,
-			sizeof(struct iwl_bt_notif_statistics));
-		memset(&priv->_agn.delta_statistics_bt, 0,
-			sizeof(struct iwl_bt_notif_statistics));
-		memset(&priv->_agn.max_delta_bt, 0,
-			sizeof(struct iwl_bt_notif_statistics));
-#endif
-		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-	}
-	iwl_rx_statistics(priv, rxb);
-}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index 6d140bd..dfdbea6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -52,10 +52,14 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
 			      struct iwl_rxon_context *ctx,
 			      struct iwl_rxon_cmd *send)
 {
+	struct iwl_notification_wait disable_wait;
 	__le32 old_filter = send->filter_flags;
 	u8 old_dev_type = send->dev_type;
 	int ret;
 
+	iwlagn_init_notification_wait(priv, &disable_wait, NULL,
+				      REPLY_WIPAN_DEACTIVATION_COMPLETE);
+
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	send->dev_type = RXON_DEV_TYPE_P2P;
 	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
@@ -63,11 +67,18 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
 	send->filter_flags = old_filter;
 	send->dev_type = old_dev_type;
 
-	if (ret)
+	if (ret) {
 		IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
-
-	/* FIXME: WAIT FOR PAN DISABLE */
-	msleep(300);
+		iwlagn_remove_notification(priv, &disable_wait);
+	} else {
+		signed long wait_res;
+
+		wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ);
+		if (wait_res == 0) {
+			IWL_ERR(priv, "Timed out waiting for PAN disable\n");
+			ret = -EIO;
+		}
+	}
 
 	return ret;
 }
@@ -145,6 +156,23 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	/* always get timestamp with Rx frame */
 	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
 
+	if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) {
+		struct ieee80211_channel *chan = priv->_agn.hw_roc_channel;
+
+		iwl_set_rxon_channel(priv, chan, ctx);
+		iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
+		ctx->staging.filter_flags |=
+			RXON_FILTER_ASSOC_MSK |
+			RXON_FILTER_PROMISC_MSK |
+			RXON_FILTER_CTL2HOST_MSK;
+		ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
+		new_assoc = true;
+
+		if (memcmp(&ctx->staging, &ctx->active,
+			   sizeof(ctx->staging)) == 0)
+			return 0;
+	}
+
 	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
 	    !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
 		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
@@ -288,10 +316,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	 * If we issue a new RXON command which required a tune then we must
 	 * send a new TXPOWER command or we won't be able to Tx any frames.
 	 *
-	 * FIXME: which RXON requires a tune? Can we optimise this out in
-	 *        some cases?
+	 * It's expected we set power here if channel is changing.
 	 */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
 	if (ret) {
 		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 		return ret;
@@ -444,6 +471,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
 	struct iwl_rxon_context *tmp;
 	struct ieee80211_sta *sta;
 	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct ieee80211_sta_ht_cap *ht_cap;
 	bool need_multiple;
 
 	lockdep_assert_held(&priv->mutex);
@@ -452,23 +480,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
 	case NL80211_IFTYPE_STATION:
 		rcu_read_lock();
 		sta = ieee80211_find_sta(vif, bss_conf->bssid);
-		if (sta) {
-			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-			int maxstreams;
-
-			maxstreams = (ht_cap->mcs.tx_params &
-				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-			maxstreams += 1;
-
-			need_multiple = true;
-
-			if ((ht_cap->mcs.rx_mask[1] == 0) &&
-			    (ht_cap->mcs.rx_mask[2] == 0))
-				need_multiple = false;
-			if (maxstreams <= 1)
-				need_multiple = false;
-		} else {
+		if (!sta) {
 			/*
 			 * If at all, this can only happen through a race
 			 * when the AP disconnects us while we're still
@@ -476,7 +488,46 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
 			 * will soon tell us about that.
 			 */
 			need_multiple = false;
+			rcu_read_unlock();
+			break;
+		}
+
+		ht_cap = &sta->ht_cap;
+
+		need_multiple = true;
+
+		/*
+		 * If the peer advertises no support for receiving 2 and 3
+		 * stream MCS rates, it can't be transmitting them either.
+		 */
+		if (ht_cap->mcs.rx_mask[1] == 0 &&
+		    ht_cap->mcs.rx_mask[2] == 0) {
+			need_multiple = false;
+		} else if (!(ht_cap->mcs.tx_params &
+						IEEE80211_HT_MCS_TX_DEFINED)) {
+			/* If it can't TX MCS at all ... */
+			need_multiple = false;
+		} else if (ht_cap->mcs.tx_params &
+						IEEE80211_HT_MCS_TX_RX_DIFF) {
+			int maxstreams;
+
+			/*
+			 * But if it can receive them, it might still not
+			 * be able to transmit them, which is what we need
+			 * to check here -- so check the number of streams
+			 * it advertises for TX (if different from RX).
+			 */
+
+			maxstreams = (ht_cap->mcs.tx_params &
+				 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK);
+			maxstreams >>=
+				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			if (maxstreams <= 1)
+				need_multiple = false;
 		}
+
 		rcu_read_unlock();
 		break;
 	case NL80211_IFTYPE_ADHOC:
@@ -546,12 +597,10 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 
 	if (changes & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
-			iwl_led_associate(priv);
 			priv->timestamp = bss_conf->timestamp;
 			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 		} else {
 			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-			iwl_led_disassociate(priv);
 		}
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 24a11b8..a709d05 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -539,7 +539,14 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 	unsigned long flags;
 	bool is_agg = false;
 
-	if (info->control.vif)
+	/*
+	 * If the frame needs to go out off-channel, then
+	 * we'll have put the PAN context to that channel,
+	 * so make the frame go out there.
+	 */
+	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+		ctx = &priv->contexts[IWL_RXON_CTX_PAN];
+	else if (info->control.vif)
 		ctx = iwl_rxon_ctx_from_vif(info->control.vif);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -940,7 +947,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
  */
 void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
 {
-	int ch;
+	int ch, txq_id;
 	unsigned long flags;
 
 	/* Turn off all Tx DMA fifos */
@@ -959,6 +966,16 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
 			    iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!priv->txq)
+		return;
+
+	/* Unmap DMA from host system and free skb's */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		if (txq_id == priv->cmd_queue)
+			iwl_cmd_queue_unmap(priv);
+		else
+			iwl_tx_queue_unmap(priv, txq_id);
 }
 
 /*
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
index 24dabcd..d807e5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
@@ -308,14 +308,6 @@ void iwlagn_init_alive_start(struct iwl_priv *priv)
 {
 	int ret = 0;
 
-	/* Check alive response for "valid" sign from uCode */
-	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
-		goto restart;
-	}
-
 	/* initialize uCode was loaded... verify inst image.
 	 * This is a paranoid check, because we would not have gotten the
 	 * "initialize" alive if code weren't properly loaded.  */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c1cfd99..581dc9f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -59,6 +59,7 @@
 #include "iwl-sta.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
+#include "iwl-agn-led.h"
 
 
 /******************************************************************************
@@ -85,7 +86,6 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("iwl4965");
 
 static int iwlagn_ant_coupling;
 static bool iwlagn_bt_ch_announce = 1;
@@ -424,47 +424,6 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
 	return 0;
 }
 
-/******************************************************************************
- *
- * Generic RX handler implementations
- *
- ******************************************************************************/
-static void iwl_rx_reply_alive(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_alive_resp *palive;
-	struct delayed_work *pwork;
-
-	palive = &pkt->u.alive_frame;
-
-	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
-		       "0x%01X 0x%01X\n",
-		       palive->is_valid, palive->ver_type,
-		       palive->ver_subtype);
-
-	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
-		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-		memcpy(&priv->card_alive_init,
-		       &pkt->u.alive_frame,
-		       sizeof(struct iwl_init_alive_resp));
-		pwork = &priv->init_alive_start;
-	} else {
-		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-		memcpy(&priv->card_alive, &pkt->u.alive_frame,
-		       sizeof(struct iwl_alive_resp));
-		pwork = &priv->alive_start;
-	}
-
-	/* We delay the ALIVE response by 5ms to
-	 * give the HW RF Kill time to activate... */
-	if (palive->is_valid == UCODE_VALID_OK)
-		queue_delayed_work(priv->workqueue, pwork,
-				   msecs_to_jiffies(5));
-	else
-		IWL_WARN(priv, "uCode did not respond OK.\n");
-}
-
 static void iwl_bg_beacon_update(struct work_struct *work)
 {
 	struct iwl_priv *priv =
@@ -699,83 +658,6 @@ static void iwl_bg_ucode_trace(unsigned long data)
 	}
 }
 
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl4965_beacon_notif *beacon =
-		(struct iwl4965_beacon_notif *)pkt->u.raw;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-
-	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
-		"tsf %d %d rate %d\n",
-		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
-		beacon->beacon_notify_hdr.failure_frame,
-		le32_to_cpu(beacon->ibss_mgr_status),
-		le32_to_cpu(beacon->high_tsf),
-		le32_to_cpu(beacon->low_tsf), rate);
-#endif
-
-	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-
-	if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-		queue_work(priv->workqueue, &priv->beacon_update);
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-	unsigned long status = priv->status;
-
-	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
-			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-			  (flags & SW_CARD_DISABLED) ? "Kill" : "On",
-			  (flags & CT_CARD_DISABLED) ?
-			  "Reached" : "Not reached");
-
-	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
-		     CT_CARD_DISABLED)) {
-
-		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-		iwl_write_direct32(priv, HBUS_TARG_MBX_C,
-					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-
-		if (!(flags & RXON_CARD_DISABLED)) {
-			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-			iwl_write_direct32(priv, HBUS_TARG_MBX_C,
-					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-		}
-		if (flags & CT_CARD_DISABLED)
-			iwl_tt_enter_ct_kill(priv);
-	}
-	if (!(flags & CT_CARD_DISABLED))
-		iwl_tt_exit_ct_kill(priv);
-
-	if (flags & HW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-
-	if (!(flags & RXON_CARD_DISABLED))
-		iwl_scan_cancel(priv);
-
-	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
-		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-			test_bit(STATUS_RF_KILL_HW, &priv->status));
-	else
-		wake_up_interruptible(&priv->wait_command_queue);
-}
-
 static void iwl_bg_tx_flush(struct work_struct *work)
 {
 	struct iwl_priv *priv =
@@ -795,58 +677,13 @@ static void iwl_bg_tx_flush(struct work_struct *work)
 }
 
 /**
- * iwl_setup_rx_handlers - Initialize Rx handler callbacks
- *
- * Setup the RX handlers for each of the reply types sent from the uCode
- * to the host.
- *
- * This function chains into the hardware specific files for them to setup
- * any hardware specific handlers as well.
- */
-static void iwl_setup_rx_handlers(struct iwl_priv *priv)
-{
-	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
-	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
-	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
-	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-			iwl_rx_spectrum_measure_notif;
-	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
-	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-	    iwl_rx_pm_debug_statistics_notif;
-	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
-
-	/*
-	 * The same handler is used for both the REPLY to a discrete
-	 * statistics request from the host as well as for the periodic
-	 * statistics notifications (after received beacons) from the uCode.
-	 */
-	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
-	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
-
-	iwl_setup_rx_scan_handlers(priv);
-
-	/* status change handler */
-	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
-
-	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
-	    iwl_rx_missed_beacon_notif;
-	/* Rx handlers */
-	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy;
-	priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx;
-	/* block ack */
-	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
-	/* Set up hardware specific Rx handlers */
-	priv->cfg->ops->lib->rx_handler_setup(priv);
-}
-
-/**
  * iwl_rx_handle - Main entry function for receiving responses from uCode
  *
  * Uses the priv->rx_handlers callback function array to invoke
  * the appropriate handlers, including command responses,
  * frame-received notifications, and other notifications.
  */
-void iwl_rx_handle(struct iwl_priv *priv)
+static void iwl_rx_handle(struct iwl_priv *priv)
 {
 	struct iwl_rx_mem_buffer *rxb;
 	struct iwl_rx_packet *pkt;
@@ -910,6 +747,27 @@ void iwl_rx_handle(struct iwl_priv *priv)
 			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
 			(pkt->hdr.cmd != REPLY_TX);
 
+		/*
+		 * Do the notification wait before RX handlers so
+		 * even if the RX handler consumes the RXB we have
+		 * access to it in the notification wait entry.
+		 */
+		if (!list_empty(&priv->_agn.notif_waits)) {
+			struct iwl_notification_wait *w;
+
+			spin_lock(&priv->_agn.notif_wait_lock);
+			list_for_each_entry(w, &priv->_agn.notif_waits, list) {
+				if (w->cmd == pkt->hdr.cmd) {
+					w->triggered = true;
+					if (w->fn)
+						w->fn(priv, pkt);
+				}
+			}
+			spin_unlock(&priv->_agn.notif_wait_lock);
+
+			wake_up_all(&priv->_agn.notif_waitq);
+		}
+
 		/* Based on type of command response or notification,
 		 *   handle those that need handling via function in
 		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
@@ -1379,66 +1237,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 		iwl_enable_rfkill_int(priv);
 }
 
-/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
-#define ACK_CNT_RATIO (50)
-#define BA_TIMEOUT_CNT (5)
-#define BA_TIMEOUT_MAX (16)
-
-/**
- * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
- *
- * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding
- * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
- * operation state.
- */
-bool iwl_good_ack_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int actual_ack_cnt_delta, expected_ack_cnt_delta;
-	int ba_timeout_delta;
-
-	actual_ack_cnt_delta =
-		le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
-		le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
-	expected_ack_cnt_delta =
-		le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
-		le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
-	ba_timeout_delta =
-		le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
-		le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
-	if ((priv->_agn.agg_tids_count > 0) &&
-	    (expected_ack_cnt_delta > 0) &&
-	    (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
-		< ACK_CNT_RATIO) &&
-	    (ba_timeout_delta > BA_TIMEOUT_CNT)) {
-		IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d,"
-				" expected_ack_cnt = %d\n",
-				actual_ack_cnt_delta, expected_ack_cnt_delta);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		/*
-		 * This is ifdef'ed on DEBUGFS because otherwise the
-		 * statistics aren't available. If DEBUGFS is set but
-		 * DEBUG is not, these will just compile out.
-		 */
-		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
-				priv->_agn.delta_statistics.tx.rx_detected_cnt);
-		IWL_DEBUG_RADIO(priv,
-				"ack_or_ba_timeout_collision delta = %d\n",
-				priv->_agn.delta_statistics.tx.
-				ack_or_ba_timeout_collision);
-#endif
-		IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
-				ba_timeout_delta);
-		if (!actual_ack_cnt_delta &&
-		    (ba_timeout_delta >= BA_TIMEOUT_MAX))
-			rc = false;
-	}
-	return rc;
-}
-
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -2632,13 +2430,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
 
 	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
 
-	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Alive failed.\n");
-		goto restart;
-	}
-
 	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
 	 * This is a paranoid check, because we would not have gotten the
 	 * "runtime" alive if code weren't properly loaded.  */
@@ -2710,9 +2501,11 @@ static void iwl_alive_start(struct iwl_priv *priv)
 			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 	}
 
-	if (priv->cfg->bt_params &&
-	    !priv->cfg->bt_params->advanced_bt_coexist) {
-		/* Configure Bluetooth device coexistence support */
+	if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
+	    !priv->cfg->bt_params->advanced_bt_coexist)) {
+		/*
+		 * default is 2-wire BT coexexistence support
+		 */
 		priv->cfg->ops->hcmd->send_bt_config(priv);
 	}
 
@@ -2726,8 +2519,6 @@ static void iwl_alive_start(struct iwl_priv *priv)
 	/* At this point, the NIC is initialized and operational */
 	iwl_rf_kill_ct_config(priv);
 
-	iwl_leds_init(priv);
-
 	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
 	wake_up_interruptible(&priv->wait_command_queue);
 
@@ -2769,7 +2560,6 @@ static void __iwl_down(struct iwl_priv *priv)
 			 priv->cfg->bt_params->bt_init_traffic_load;
 	else
 		priv->bt_traffic_load = 0;
-	priv->bt_sco_active = false;
 	priv->bt_full_concurrent = false;
 	priv->bt_ci_compliance = 0;
 
@@ -3063,8 +2853,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
 	}
 
 	if (priv->start_calib) {
-		if (priv->cfg->bt_params &&
-		    priv->cfg->bt_params->bt_statistics) {
+		if (iwl_bt_statistics(priv)) {
 			iwl_chain_noise_calibration(priv,
 					(void *)&priv->_agn.statistics_bt);
 			iwl_sensitivity_calibration(priv,
@@ -3089,7 +2878,7 @@ static void iwl_bg_restart(struct work_struct *data)
 
 	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
 		struct iwl_rxon_context *ctx;
-		bool bt_sco, bt_full_concurrent;
+		bool bt_full_concurrent;
 		u8 bt_ci_compliance;
 		u8 bt_load;
 		u8 bt_status;
@@ -3108,7 +2897,6 @@ static void iwl_bg_restart(struct work_struct *data)
 		 * re-configure the hw when we reconfigure the BT
 		 * command.
 		 */
-		bt_sco = priv->bt_sco_active;
 		bt_full_concurrent = priv->bt_full_concurrent;
 		bt_ci_compliance = priv->bt_ci_compliance;
 		bt_load = priv->bt_traffic_load;
@@ -3116,7 +2904,6 @@ static void iwl_bg_restart(struct work_struct *data)
 
 		__iwl_down(priv);
 
-		priv->bt_sco_active = bt_sco;
 		priv->bt_full_concurrent = bt_full_concurrent;
 		priv->bt_ci_compliance = bt_ci_compliance;
 		priv->bt_traffic_load = bt_load;
@@ -3150,6 +2937,91 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
 	mutex_unlock(&priv->mutex);
 }
 
+static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+				 struct ieee80211_channel *chan,
+				 enum nl80211_channel_type channel_type,
+				 unsigned int wait)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	/* Not supported if we don't have PAN */
+	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) {
+		ret = -EOPNOTSUPP;
+		goto free;
+	}
+
+	/* Not supported on pre-P2P firmware */
+	if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
+					BIT(NL80211_IFTYPE_P2P_CLIENT))) {
+		ret = -EOPNOTSUPP;
+		goto free;
+	}
+
+	mutex_lock(&priv->mutex);
+
+	if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) {
+		/*
+		 * If the PAN context is free, use the normal
+		 * way of doing remain-on-channel offload + TX.
+		 */
+		ret = 1;
+		goto out;
+	}
+
+	/* TODO: queue up if scanning? */
+	if (test_bit(STATUS_SCANNING, &priv->status) ||
+	    priv->_agn.offchan_tx_skb) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * max_scan_ie_len doesn't include the blank SSID or the header,
+	 * so need to add that again here.
+	 */
+	if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	priv->_agn.offchan_tx_skb = skb;
+	priv->_agn.offchan_tx_timeout = wait;
+	priv->_agn.offchan_tx_chan = chan;
+
+	ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
+				IWL_SCAN_OFFCH_TX, chan->band);
+	if (ret)
+		priv->_agn.offchan_tx_skb = NULL;
+ out:
+	mutex_unlock(&priv->mutex);
+ free:
+	if (ret < 0)
+		kfree_skb(skb);
+
+	return ret;
+}
+
+static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	mutex_lock(&priv->mutex);
+
+	if (!priv->_agn.offchan_tx_skb)
+		return -EINVAL;
+
+	priv->_agn.offchan_tx_skb = NULL;
+
+	ret = iwl_scan_cancel_timeout(priv, 200);
+	if (ret)
+		ret = -EIO;
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -3178,6 +3050,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 		    IEEE80211_HW_SPECTRUM_MGMT |
 		    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
+	hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
 	if (!priv->cfg->base_params->broken_powersave)
 		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
@@ -3194,8 +3068,11 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 		hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
 	}
 
+	hw->wiphy->max_remain_on_channel_duration = 1000;
+
 	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
+			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
+			    WIPHY_FLAG_IBSS_RSN;
 
 	/*
 	 * For now, disable PS by default because it affects
@@ -3219,6 +3096,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 			&priv->bands[IEEE80211_BAND_5GHZ];
 
+	iwl_leds_init(priv);
+
 	ret = ieee80211_register_hw(priv->hw);
 	if (ret) {
 		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
@@ -3263,7 +3142,7 @@ int iwlagn_mac_start(struct ieee80211_hw *hw)
 		}
 	}
 
-	iwl_led_start(priv);
+	iwlagn_led_enable(priv);
 
 out:
 	priv->is_open = 1;
@@ -3294,7 +3173,7 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw)
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -3307,7 +3186,6 @@ int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		dev_kfree_skb_any(skb);
 
 	IWL_DEBUG_MACDUMP(priv, "leave\n");
-	return NETDEV_TX_OK;
 }
 
 void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
@@ -3345,6 +3223,14 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		return -EOPNOTSUPP;
 	}
 
+	/*
+	 * To support IBSS RSN, don't program group keys in IBSS, the
+	 * hardware will then not attempt to decrypt the frames.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
 	sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
 	if (sta_id == IWL_INVALID_STATION)
 		return -EINVAL;
@@ -3399,10 +3285,12 @@ int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size)
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret = -EINVAL;
+	struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
@@ -3457,11 +3345,28 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 		}
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/*
+		 * If the limit is 0, then it wasn't initialised yet,
+		 * use the default. We can do that since we take the
+		 * minimum below, and we don't want to go above our
+		 * default due to hardware restrictions.
+		 */
+		if (sta_priv->max_agg_bufsize == 0)
+			sta_priv->max_agg_bufsize =
+				LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
+		/*
+		 * Even though in theory the peer could have different
+		 * aggregation reorder buffer sizes for different sessions,
+		 * our ucode doesn't allow for that and has a global limit
+		 * for each station. Therefore, use the minimum of all the
+		 * aggregation sessions and our default value.
+		 */
+		sta_priv->max_agg_bufsize =
+			min(sta_priv->max_agg_bufsize, buf_size);
+
 		if (priv->cfg->ht_params &&
 		    priv->cfg->ht_params->use_rts_for_aggregation) {
-			struct iwl_station_priv *sta_priv =
-				(void *) sta->drv_priv;
-
 			/*
 			 * switch to RTS/CTS if it is the prefer protection
 			 * method for HT traffic
@@ -3469,9 +3374,13 @@ int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 
 			sta_priv->lq_sta.lq.general_params.flags |=
 				LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
-					&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		}
+
+		sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
+			sta_priv->max_agg_bufsize;
+
+		iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+				&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		ret = 0;
 		break;
 	}
@@ -3709,6 +3618,95 @@ done:
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
+static void iwlagn_disable_roc(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
+	struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel);
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->staging.dev_type = RXON_DEV_TYPE_2STA;
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl_set_rxon_channel(priv, chan, ctx);
+	iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
+
+	priv->_agn.hw_roc_channel = NULL;
+
+	iwlcore_commit_rxon(priv, ctx);
+
+	ctx->is_active = false;
+}
+
+static void iwlagn_bg_roc_done(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+					     _agn.hw_roc_work.work);
+
+	mutex_lock(&priv->mutex);
+	ieee80211_remain_on_channel_expired(priv->hw);
+	iwlagn_disable_roc(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
+				     struct ieee80211_channel *channel,
+				     enum nl80211_channel_type channel_type,
+				     int duration)
+{
+	struct iwl_priv *priv = hw->priv;
+	int err = 0;
+
+	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+		return -EOPNOTSUPP;
+
+	if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
+					BIT(NL80211_IFTYPE_P2P_CLIENT)))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&priv->mutex);
+
+	if (priv->contexts[IWL_RXON_CTX_PAN].is_active ||
+	    test_bit(STATUS_SCAN_HW, &priv->status)) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
+	priv->_agn.hw_roc_channel = channel;
+	priv->_agn.hw_roc_chantype = channel_type;
+	priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
+	iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
+	queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
+			   msecs_to_jiffies(duration + 20));
+
+	msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
+	ieee80211_ready_on_channel(priv->hw);
+
+ out:
+	mutex_unlock(&priv->mutex);
+
+	return err;
+}
+
+static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+		return -EOPNOTSUPP;
+
+	cancel_delayed_work_sync(&priv->_agn.hw_roc_work);
+
+	mutex_lock(&priv->mutex);
+	iwlagn_disable_roc(priv);
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -3730,6 +3728,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
 	INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
+	INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done);
 
 	iwl_setup_scan_deferred_work(priv);
 
@@ -3823,6 +3822,8 @@ static int iwl_init_drv(struct iwl_priv *priv)
 	priv->force_reset[IWL_FW_RESET].reset_duration =
 		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
+	priv->rx_statistics_jiffies = jiffies;
+
 	/* Choose which receivers/antennas to use */
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
 		priv->cfg->ops->hcmd->set_rxon_chain(priv,
@@ -3876,7 +3877,6 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 	kfree(priv->scan_cmd);
 }
 
-#ifdef CONFIG_IWL5000
 struct ieee80211_ops iwlagn_hw_ops = {
 	.tx = iwlagn_mac_tx,
 	.start = iwlagn_mac_start,
@@ -3898,14 +3898,17 @@ struct ieee80211_ops iwlagn_hw_ops = {
 	.channel_switch = iwlagn_mac_channel_switch,
 	.flush = iwlagn_mac_flush,
 	.tx_last_beacon = iwl_mac_tx_last_beacon,
+	.remain_on_channel = iwl_mac_remain_on_channel,
+	.cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
+	.offchannel_tx = iwl_mac_offchannel_tx,
+	.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
 };
-#endif
 
 static void iwl_hw_detect(struct iwl_priv *priv)
 {
 	priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
 	priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
-	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+	priv->rev_id = priv->pci_dev->revision;
 	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
 }
 
@@ -3967,12 +3970,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (cfg->mod_params->disable_hw_scan) {
 		dev_printk(KERN_DEBUG, &(pdev->dev),
 			"sw scan support is deprecated\n");
-#ifdef CONFIG_IWL5000
 		iwlagn_hw_ops.hw_scan = NULL;
-#endif
-#ifdef CONFIG_IWL4965
-		iwl4965_hw_ops.hw_scan = NULL;
-#endif
 	}
 
 	hw = iwl_alloc_all(cfg);
@@ -4025,6 +4023,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
 	priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
 		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
+#ifdef CONFIG_IWL_P2P
+	priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
+		BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
+#endif
 	priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
 	priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
 	priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
@@ -4272,6 +4274,9 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 	 * we need to set STATUS_EXIT_PENDING bit.
 	 */
 	set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	iwl_leds_exit(priv);
+
 	if (priv->mac80211_registered) {
 		ieee80211_unregister_hw(priv->hw);
 		priv->mac80211_registered = 0;
@@ -4344,12 +4349,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
-#ifdef CONFIG_IWL4965
-	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
-	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
-#endif /* CONFIG_IWL4965 */
-#ifdef CONFIG_IWL5000
-/* 5100 Series WiFi */
 	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
 	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
 	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
@@ -4492,7 +4491,48 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
 
-#endif /* CONFIG_IWL5000 */
+/* 2x00 Series */
+	{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+
+/* 2x30 Series */
+	{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
+
+/* 6x35 Series */
+	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
+
+/* 200 Series */
+	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl200_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0895, 0x0222, iwl200_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0422, iwl200_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0026, iwl200_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0895, 0x0226, iwl200_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0426, iwl200_bg_cfg)},
+
+/* 230 Series */
+	{IWL_PCI_DEVICE(0x0892, 0x0062, iwl230_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0893, 0x0262, iwl230_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0462, iwl230_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0066, iwl230_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)},
 
 	{0}
 };
@@ -4592,3 +4632,9 @@ MODULE_PARM_DESC(antenna_coupling,
 module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO);
 MODULE_PARM_DESC(bt_ch_inhibition,
 		 "Disable BT channel inhibition (default: enable)");
+
+module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO);
+MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
+
+module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
+MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index da30358..20f8e41 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -96,6 +96,17 @@ extern struct iwl_cfg iwl100_bgn_cfg;
 extern struct iwl_cfg iwl100_bg_cfg;
 extern struct iwl_cfg iwl130_bgn_cfg;
 extern struct iwl_cfg iwl130_bg_cfg;
+extern struct iwl_cfg iwl2000_2bgn_cfg;
+extern struct iwl_cfg iwl2000_2bg_cfg;
+extern struct iwl_cfg iwl2030_2bgn_cfg;
+extern struct iwl_cfg iwl2030_2bg_cfg;
+extern struct iwl_cfg iwl6035_2agn_cfg;
+extern struct iwl_cfg iwl6035_2abg_cfg;
+extern struct iwl_cfg iwl6035_2bg_cfg;
+extern struct iwl_cfg iwl200_bg_cfg;
+extern struct iwl_cfg iwl200_bgn_cfg;
+extern struct iwl_cfg iwl230_bg_cfg;
+extern struct iwl_cfg iwl230_bgn_cfg;
 
 extern struct iwl_mod_params iwlagn_mod_params;
 extern struct iwl_hcmd_ops iwlagn_hcmd;
@@ -110,8 +121,6 @@ void iwl_disable_ict(struct iwl_priv *priv);
 int iwl_alloc_isr_ict(struct iwl_priv *priv);
 void iwl_free_isr_ict(struct iwl_priv *priv);
 irqreturn_t iwl_isr_ict(int irq, void *data);
-bool iwl_good_ack_health(struct iwl_priv *priv,
-			 struct iwl_rx_packet *pkt);
 
 /* tx queue */
 void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
@@ -181,11 +190,7 @@ void iwlagn_rx_replenish_now(struct iwl_priv *priv);
 void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
 int iwlagn_rxq_stop(struct iwl_priv *priv);
 int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
-void iwlagn_rx_reply_rx(struct iwl_priv *priv,
-		     struct iwl_rx_mem_buffer *rxb);
-void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
-			 struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_handle(struct iwl_priv *priv);
+void iwl_setup_rx_handlers(struct iwl_priv *priv);
 
 /* tx */
 void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
@@ -235,16 +240,6 @@ static inline bool iwl_is_tx_success(u32 status)
 
 u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
 
-/* rx */
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb);
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-			  struct iwl_rx_packet *pkt);
-void iwl_rx_statistics(struct iwl_priv *priv,
-		       struct iwl_rx_mem_buffer *rxb);
-void iwl_reply_statistics(struct iwl_priv *priv,
-			  struct iwl_rx_mem_buffer *rxb);
-
 /* scan */
 int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwlagn_post_scan(struct iwl_priv *priv);
@@ -330,8 +325,23 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
 int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
 void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
 
+/* notification wait support */
+void __acquires(wait_entry)
+iwlagn_init_notification_wait(struct iwl_priv *priv,
+			      struct iwl_notification_wait *wait_entry,
+			      void (*fn)(struct iwl_priv *priv,
+					 struct iwl_rx_packet *pkt),
+			      u8 cmd);
+signed long __releases(wait_entry)
+iwlagn_wait_notification(struct iwl_priv *priv,
+			 struct iwl_notification_wait *wait_entry,
+			 unsigned long timeout);
+void __releases(wait_entry)
+iwlagn_remove_notification(struct iwl_priv *priv,
+			   struct iwl_notification_wait *wait_entry);
+
 /* mac80211 handlers (for 4965) */
-int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 int iwlagn_mac_start(struct ieee80211_hw *hw);
 void iwlagn_mac_stop(struct ieee80211_hw *hw);
 void iwlagn_configure_filter(struct ieee80211_hw *hw,
@@ -349,7 +359,8 @@ void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
 int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
 int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index f893d4a..ca42ffa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -178,7 +178,6 @@ enum {
 	REPLY_BT_COEX_PRIO_TABLE = 0xcc,
 	REPLY_BT_COEX_PROT_ENV = 0xcd,
 	REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
-	REPLY_BT_COEX_SCO = 0xcf,
 
 	/* PAN commands */
 	REPLY_WIPAN_PARAMS = 0xb2,
@@ -189,6 +188,7 @@ enum {
 	REPLY_WIPAN_WEPKEY = 0xb8,	/* use REPLY_WEPKEY structure */
 	REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9,
 	REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
+	REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd,
 
 	REPLY_MAX = 0xff
 };
@@ -2477,7 +2477,7 @@ struct iwl_bt_cmd {
 					IWLAGN_BT_VALID_BT4_TIMES | \
 					IWLAGN_BT_VALID_3W_LUT)
 
-struct iwlagn_bt_cmd {
+struct iwl_basic_bt_cmd {
 	u8 flags;
 	u8 ledtime; /* unused */
 	u8 max_kill;
@@ -2490,6 +2490,10 @@ struct iwlagn_bt_cmd {
 	__le32 bt3_lookup_table[12];
 	__le16 bt4_decision_time; /* unused */
 	__le16 valid;
+};
+
+struct iwl6000_bt_cmd {
+	struct iwl_basic_bt_cmd basic;
 	u8 prio_boost;
 	/*
 	 * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask
@@ -2499,6 +2503,18 @@ struct iwlagn_bt_cmd {
 	__le16 rx_prio_boost;	/* SW boost of WiFi rx priority */
 };
 
+struct iwl2000_bt_cmd {
+	struct iwl_basic_bt_cmd basic;
+	__le32 prio_boost;
+	/*
+	 * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask
+	 * if configure the following patterns
+	 */
+	u8 reserved;
+	u8 tx_prio_boost;	/* SW boost of WiFi tx priority */
+	__le16 rx_prio_boost;	/* SW boost of WiFi rx priority */
+};
+
 #define IWLAGN_BT_SCO_ACTIVE	cpu_to_le32(BIT(0))
 
 struct iwlagn_bt_sco_cmd {
@@ -2948,9 +2964,15 @@ struct iwl3945_scan_cmd {
 	u8 data[0];
 } __packed;
 
+enum iwl_scan_flags {
+	/* BIT(0) currently unused */
+	IWL_SCAN_FLAGS_ACTION_FRAME_TX	= BIT(1),
+	/* bits 2-7 reserved */
+};
+
 struct iwl_scan_cmd {
 	__le16 len;
-	u8 reserved0;
+	u8 scan_flags;		/* scan flags: see enum iwl_scan_flags */
 	u8 channel_count;	/* # channels in channel list */
 	__le16 quiet_time;	/* dwell only this # millisecs on quiet channel
 				 * (only for active scan) */
@@ -3082,6 +3104,13 @@ struct iwl4965_beacon_notif {
 	__le32 ibss_mgr_status;
 } __packed;
 
+struct iwlagn_beacon_notif {
+	struct iwlagn_tx_resp beacon_notify_hdr;
+	__le32 low_tsf;
+	__le32 high_tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
 /*
  * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
  */
@@ -4143,6 +4172,10 @@ enum iwl_bt_coex_profile_traffic_load {
  */
 };
 
+#define BT_SESSION_ACTIVITY_1_UART_MSG		0x1
+#define BT_SESSION_ACTIVITY_2_UART_MSG		0x2
+
+/* BT UART message - Share Part (BT -> WiFi) */
 #define BT_UART_MSG_FRAME1MSGTYPE_POS		(0)
 #define BT_UART_MSG_FRAME1MSGTYPE_MSK		\
 		(0x7 << BT_UART_MSG_FRAME1MSGTYPE_POS)
@@ -4227,9 +4260,12 @@ enum iwl_bt_coex_profile_traffic_load {
 #define BT_UART_MSG_FRAME7SNIFFACTIVITY_POS	(0)
 #define BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK	\
 		(0x7 << BT_UART_MSG_FRAME7SNIFFACTIVITY_POS)
-#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS	(3)
-#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK	\
-		(0x3 << BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS)
+#define BT_UART_MSG_FRAME7PAGE_POS		(3)
+#define BT_UART_MSG_FRAME7PAGE_MSK		\
+		(0x1 << BT_UART_MSG_FRAME7PAGE_POS)
+#define BT_UART_MSG_FRAME7INQUIRY_POS		(4)
+#define BT_UART_MSG_FRAME7INQUIRY_MSK		\
+		(0x1 << BT_UART_MSG_FRAME7INQUIRY_POS)
 #define BT_UART_MSG_FRAME7CONNECTABLE_POS	(5)
 #define BT_UART_MSG_FRAME7CONNECTABLE_MSK	\
 		(0x1 << BT_UART_MSG_FRAME7CONNECTABLE_POS)
@@ -4237,6 +4273,83 @@ enum iwl_bt_coex_profile_traffic_load {
 #define BT_UART_MSG_FRAME7RESERVED_MSK		\
 		(0x3 << BT_UART_MSG_FRAME7RESERVED_POS)
 
+/* BT Session Activity 2 UART message (BT -> WiFi) */
+#define BT_UART_MSG_2_FRAME1RESERVED1_POS	(5)
+#define BT_UART_MSG_2_FRAME1RESERVED1_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME1RESERVED1_POS)
+#define BT_UART_MSG_2_FRAME1RESERVED2_POS	(6)
+#define BT_UART_MSG_2_FRAME1RESERVED2_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME1RESERVED2_POS)
+
+#define BT_UART_MSG_2_FRAME2AGGTRAFFICLOAD_POS	(0)
+#define BT_UART_MSG_2_FRAME2AGGTRAFFICLOAD_MSK	\
+		(0x3F<<BT_UART_MSG_2_FRAME2AGGTRAFFICLOAD_POS)
+#define BT_UART_MSG_2_FRAME2RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME2RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME2RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME3BRLASTTXPOWER_POS	(0)
+#define BT_UART_MSG_2_FRAME3BRLASTTXPOWER_MSK	\
+		(0xF<<BT_UART_MSG_2_FRAME3BRLASTTXPOWER_POS)
+#define BT_UART_MSG_2_FRAME3INQPAGESRMODE_POS	(4)
+#define BT_UART_MSG_2_FRAME3INQPAGESRMODE_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME3INQPAGESRMODE_POS)
+#define BT_UART_MSG_2_FRAME3LEMASTER_POS	(5)
+#define BT_UART_MSG_2_FRAME3LEMASTER_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME3LEMASTER_POS)
+#define BT_UART_MSG_2_FRAME3RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME3RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME3RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME4LELASTTXPOWER_POS	(0)
+#define BT_UART_MSG_2_FRAME4LELASTTXPOWER_MSK	\
+		(0xF<<BT_UART_MSG_2_FRAME4LELASTTXPOWER_POS)
+#define BT_UART_MSG_2_FRAME4NUMLECONN_POS	(4)
+#define BT_UART_MSG_2_FRAME4NUMLECONN_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME4NUMLECONN_POS)
+#define BT_UART_MSG_2_FRAME4RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME4RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME4RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME5BTMINRSSI_POS	(0)
+#define BT_UART_MSG_2_FRAME5BTMINRSSI_MSK	\
+		(0xF<<BT_UART_MSG_2_FRAME5BTMINRSSI_POS)
+#define BT_UART_MSG_2_FRAME5LESCANINITMODE_POS	(4)
+#define BT_UART_MSG_2_FRAME5LESCANINITMODE_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME5LESCANINITMODE_POS)
+#define BT_UART_MSG_2_FRAME5LEADVERMODE_POS	(5)
+#define BT_UART_MSG_2_FRAME5LEADVERMODE_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME5LEADVERMODE_POS)
+#define BT_UART_MSG_2_FRAME5RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME5RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME5RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME6LECONNINTERVAL_POS	(0)
+#define BT_UART_MSG_2_FRAME6LECONNINTERVAL_MSK	\
+		(0x1F<<BT_UART_MSG_2_FRAME6LECONNINTERVAL_POS)
+#define BT_UART_MSG_2_FRAME6RFU_POS		(5)
+#define BT_UART_MSG_2_FRAME6RFU_MSK		\
+		(0x1<<BT_UART_MSG_2_FRAME6RFU_POS)
+#define BT_UART_MSG_2_FRAME6RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME6RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME6RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME7LECONNSLAVELAT_POS	(0)
+#define BT_UART_MSG_2_FRAME7LECONNSLAVELAT_MSK	\
+		(0x7<<BT_UART_MSG_2_FRAME7LECONNSLAVELAT_POS)
+#define BT_UART_MSG_2_FRAME7LEPROFILE1_POS	(3)
+#define BT_UART_MSG_2_FRAME7LEPROFILE1_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME7LEPROFILE1_POS)
+#define BT_UART_MSG_2_FRAME7LEPROFILE2_POS	(4)
+#define BT_UART_MSG_2_FRAME7LEPROFILE2_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME7LEPROFILE2_POS)
+#define BT_UART_MSG_2_FRAME7LEPROFILEOTHER_POS	(5)
+#define BT_UART_MSG_2_FRAME7LEPROFILEOTHER_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME7LEPROFILEOTHER_POS)
+#define BT_UART_MSG_2_FRAME7RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME7RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME7RESERVED_POS)
+
 
 struct iwl_bt_uart_msg {
 	u8 header;
@@ -4369,6 +4482,11 @@ int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
  * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
  */
 
+/*
+ * Minimum slot time in TU
+ */
+#define IWL_MIN_SLOT_TIME	20
+
 /**
  * struct iwl_wipan_slot
  * @width: Time in TU
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index efbde1f..6c30fa6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -43,11 +43,6 @@
 #include "iwl-helpers.h"
 
 
-MODULE_DESCRIPTION("iwl core");
-MODULE_VERSION(IWLWIFI_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-
 /*
  * set bt_coex_active to true, uCode will do kill/defer
  * every time the priority line is asserted (BT is sending signals on the
@@ -65,15 +60,12 @@ MODULE_LICENSE("GPL");
  * default: bt_coex_active = true (BT_COEX_ENABLE)
  */
 bool bt_coex_active = true;
-EXPORT_SYMBOL_GPL(bt_coex_active);
 module_param(bt_coex_active, bool, S_IRUGO);
 MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
 
 u32 iwl_debug_level;
-EXPORT_SYMBOL(iwl_debug_level);
 
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-EXPORT_SYMBOL(iwl_bcast_addr);
 
 
 /* This function both allocates and initializes hw and priv. */
@@ -98,7 +90,6 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
 out:
 	return hw;
 }
-EXPORT_SYMBOL(iwl_alloc_all);
 
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
@@ -219,15 +210,12 @@ int iwlcore_init_geos(struct iwl_priv *priv)
 		if (!is_channel_valid(ch))
 			continue;
 
-		if (is_channel_a_band(ch))
-			sband =  &priv->bands[IEEE80211_BAND_5GHZ];
-		else
-			sband =  &priv->bands[IEEE80211_BAND_2GHZ];
+		sband =  &priv->bands[ch->band];
 
 		geo_ch = &sband->channels[sband->n_channels++];
 
 		geo_ch->center_freq =
-				ieee80211_channel_to_frequency(ch->channel);
+			ieee80211_channel_to_frequency(ch->channel, ch->band);
 		geo_ch->max_power = ch->max_power_avg;
 		geo_ch->max_antenna_gain = 0xff;
 		geo_ch->hw_value = ch->channel;
@@ -275,7 +263,6 @@ int iwlcore_init_geos(struct iwl_priv *priv)
 
 	return 0;
 }
-EXPORT_SYMBOL(iwlcore_init_geos);
 
 /*
  * iwlcore_free_geos - undo allocations in iwlcore_init_geos
@@ -286,7 +273,6 @@ void iwlcore_free_geos(struct iwl_priv *priv)
 	kfree(priv->ieee_rates);
 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
 }
-EXPORT_SYMBOL(iwlcore_free_geos);
 
 static bool iwl_is_channel_extension(struct iwl_priv *priv,
 				     enum ieee80211_band band,
@@ -331,7 +317,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
 			le16_to_cpu(ctx->staging.channel),
 			ctx->ht.extension_chan_offset);
 }
-EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
 
 static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
 {
@@ -432,7 +417,6 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
 				sizeof(ctx->timing), &ctx->timing);
 }
-EXPORT_SYMBOL(iwl_send_rxon_timing);
 
 void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 			   int hw_decrypt)
@@ -445,7 +429,6 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
 
 }
-EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
 
 /* validate RXON structure is valid */
 int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
@@ -518,7 +501,6 @@ int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_check_rxon_cmd);
 
 /**
  * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
@@ -582,7 +564,6 @@ int iwl_full_rxon_required(struct iwl_priv *priv,
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_full_rxon_required);
 
 u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
 			    struct iwl_rxon_context *ctx)
@@ -596,7 +577,6 @@ u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
 	else
 		return IWL_RATE_6M_PLCP;
 }
-EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
 
 static void _iwl_set_rxon_ht(struct iwl_priv *priv,
 			     struct iwl_ht_config *ht_conf,
@@ -673,7 +653,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
 	for_each_context(priv, ctx)
 		_iwl_set_rxon_ht(priv, ht_conf, ctx);
 }
-EXPORT_SYMBOL(iwl_set_rxon_ht);
 
 /* Return valid, unused, channel for a passive scan to reset the RF */
 u8 iwl_get_single_channel_number(struct iwl_priv *priv,
@@ -714,7 +693,6 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv,
 
 	return channel;
 }
-EXPORT_SYMBOL(iwl_get_single_channel_number);
 
 /**
  * iwl_set_rxon_channel - Set the band and channel values in staging RXON
@@ -745,7 +723,6 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_set_rxon_channel);
 
 void iwl_set_flags_for_band(struct iwl_priv *priv,
 			    struct iwl_rxon_context *ctx,
@@ -769,7 +746,6 @@ void iwl_set_flags_for_band(struct iwl_priv *priv,
 		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
 	}
 }
-EXPORT_SYMBOL(iwl_set_flags_for_band);
 
 /*
  * initialize rxon structure with default values from eeprom
@@ -841,7 +817,6 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv,
 	ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
 	ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
 }
-EXPORT_SYMBOL(iwl_connection_init_rx_config);
 
 void iwl_set_rate(struct iwl_priv *priv)
 {
@@ -874,7 +849,6 @@ void iwl_set_rate(struct iwl_priv *priv)
 		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
 	}
 }
-EXPORT_SYMBOL(iwl_set_rate);
 
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
 {
@@ -894,35 +868,6 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
 		mutex_unlock(&priv->mutex);
 	}
 }
-EXPORT_SYMBOL(iwl_chswitch_done);
-
-void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
-	/*
-	 * MULTI-FIXME
-	 * See iwl_mac_channel_switch.
-	 */
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
-
-	if (priv->switch_rxon.switch_in_progress) {
-		if (!le32_to_cpu(csa->status) &&
-		    (csa->channel == priv->switch_rxon.channel)) {
-			rxon->channel = csa->channel;
-			ctx->staging.channel = csa->channel;
-			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-			      le16_to_cpu(csa->channel));
-			iwl_chswitch_done(priv, true);
-		} else {
-			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
-			      le16_to_cpu(csa->channel));
-			iwl_chswitch_done(priv, false);
-		}
-	}
-}
-EXPORT_SYMBOL(iwl_rx_csa);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 void iwl_print_rx_config_cmd(struct iwl_priv *priv,
@@ -944,13 +889,15 @@ void iwl_print_rx_config_cmd(struct iwl_priv *priv,
 	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
 	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
-EXPORT_SYMBOL(iwl_print_rx_config_cmd);
 #endif
 /**
  * iwl_irq_handle_error - called for HW or SW error interrupt from card
  */
 void iwl_irq_handle_error(struct iwl_priv *priv)
 {
+	unsigned int reload_msec;
+	unsigned long reload_jiffies;
+
 	/* Set the FW error flag -- cleared on iwl_down */
 	set_bit(STATUS_FW_ERROR, &priv->status);
 
@@ -994,6 +941,25 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
 	 * commands by clearing the INIT status bit */
 	clear_bit(STATUS_READY, &priv->status);
 
+	/*
+	 * If firmware keep reloading, then it indicate something
+	 * serious wrong and firmware having problem to recover
+	 * from it. Instead of keep trying which will fill the syslog
+	 * and hang the system, let's just stop it
+	 */
+	reload_jiffies = jiffies;
+	reload_msec = jiffies_to_msecs((long) reload_jiffies -
+				(long) priv->reload_jiffies);
+	priv->reload_jiffies = reload_jiffies;
+	if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
+		priv->reload_count++;
+		if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
+			IWL_ERR(priv, "BUG_ON, Stop restarting\n");
+			return;
+		}
+	} else
+		priv->reload_count = 0;
+
 	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
 			  "Restarting adapter due to uCode error.\n");
@@ -1002,7 +968,6 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
 			queue_work(priv->workqueue, &priv->restart);
 	}
 }
-EXPORT_SYMBOL(iwl_irq_handle_error);
 
 static int iwl_apm_stop_master(struct iwl_priv *priv)
 {
@@ -1039,7 +1004,6 @@ void iwl_apm_stop(struct iwl_priv *priv)
 	 */
 	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 }
-EXPORT_SYMBOL(iwl_apm_stop);
 
 
 /*
@@ -1154,13 +1118,14 @@ int iwl_apm_init(struct iwl_priv *priv)
 out:
 	return ret;
 }
-EXPORT_SYMBOL(iwl_apm_init);
 
 
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
 	int ret;
 	s8 prev_tx_power;
+	bool defer;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 	lockdep_assert_held(&priv->mutex);
 
@@ -1188,10 +1153,15 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 	if (!iwl_is_ready_rf(priv))
 		return -EIO;
 
-	/* scan complete use tx_power_next, need to be updated */
+	/* scan complete and commit_rxon use tx_power_next value,
+	 * it always need to be updated for newest request */
 	priv->tx_power_next = tx_power;
-	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
-		IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
+
+	/* do not set tx power when scanning or channel changing */
+	defer = test_bit(STATUS_SCANNING, &priv->status) ||
+		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+	if (defer && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
 		return 0;
 	}
 
@@ -1207,7 +1177,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 	}
 	return ret;
 }
-EXPORT_SYMBOL(iwl_set_tx_power);
 
 void iwl_send_bt_config(struct iwl_priv *priv)
 {
@@ -1231,7 +1200,6 @@ void iwl_send_bt_config(struct iwl_priv *priv)
 			     sizeof(struct iwl_bt_cmd), &bt_cmd))
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 }
-EXPORT_SYMBOL(iwl_send_bt_config);
 
 int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
 {
@@ -1249,46 +1217,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
 					sizeof(struct iwl_statistics_cmd),
 					&statistics_cmd);
 }
-EXPORT_SYMBOL(iwl_send_statistics_request);
-
-void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-			   struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
-	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
-		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
-#endif
-}
-EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
-
-void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
-			"notification for %s:\n", len,
-			get_cmd_string(pkt->hdr.cmd));
-	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
-}
-EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
-
-void iwl_rx_reply_error(struct iwl_priv *priv,
-			struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
-		"seq 0x%04X ser 0x%08X\n",
-		le32_to_cpu(pkt->u.err_resp.error_type),
-		get_cmd_string(pkt->u.err_resp.cmd_id),
-		pkt->u.err_resp.cmd_id,
-		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
-		le32_to_cpu(pkt->u.err_resp.error_info));
-}
-EXPORT_SYMBOL(iwl_rx_reply_error);
 
 void iwl_clear_isr_stats(struct iwl_priv *priv)
 {
@@ -1340,7 +1268,6 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return 0;
 }
-EXPORT_SYMBOL(iwl_mac_conf_tx);
 
 int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
 {
@@ -1348,7 +1275,6 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
 
 	return priv->ibss_manager == IWL_IBSS_MANAGER;
 }
-EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
 
 static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
@@ -1403,9 +1329,10 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_rxon_context *tmp, *ctx = NULL;
 	int err;
+	enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
 
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
-			   vif->type, vif->addr);
+			   viftype, vif->addr);
 
 	mutex_lock(&priv->mutex);
 
@@ -1429,7 +1356,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 			continue;
 		}
 
-		if (!(possible_modes & BIT(vif->type)))
+		if (!(possible_modes & BIT(viftype)))
 			continue;
 
 		/* have maybe usable context w/o interface */
@@ -1457,7 +1384,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return err;
 }
-EXPORT_SYMBOL(iwl_mac_add_interface);
 
 static void iwl_teardown_interface(struct iwl_priv *priv,
 				   struct ieee80211_vif *vif,
@@ -1510,7 +1436,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 }
-EXPORT_SYMBOL(iwl_mac_remove_interface);
 
 int iwl_alloc_txq_mem(struct iwl_priv *priv)
 {
@@ -1525,14 +1450,12 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv)
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_alloc_txq_mem);
 
 void iwl_free_txq_mem(struct iwl_priv *priv)
 {
 	kfree(priv->txq);
 	priv->txq = NULL;
 }
-EXPORT_SYMBOL(iwl_free_txq_mem);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 
@@ -1571,7 +1494,6 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
 	iwl_reset_traffic_log(priv);
 	return 0;
 }
-EXPORT_SYMBOL(iwl_alloc_traffic_mem);
 
 void iwl_free_traffic_mem(struct iwl_priv *priv)
 {
@@ -1581,7 +1503,6 @@ void iwl_free_traffic_mem(struct iwl_priv *priv)
 	kfree(priv->rx_traffic);
 	priv->rx_traffic = NULL;
 }
-EXPORT_SYMBOL(iwl_free_traffic_mem);
 
 void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
 		      u16 length, struct ieee80211_hdr *header)
@@ -1606,7 +1527,6 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
 			(priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
 	}
 }
-EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame);
 
 void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 		      u16 length, struct ieee80211_hdr *header)
@@ -1631,7 +1551,6 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 			(priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
 	}
 }
-EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
 
 const char *get_mgmt_string(int cmd)
 {
@@ -1675,7 +1594,6 @@ void iwl_clear_traffic_stats(struct iwl_priv *priv)
 {
 	memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
 	memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
-	priv->led_tpt = 0;
 }
 
 /*
@@ -1768,9 +1686,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
 		stats->data_cnt++;
 		stats->data_bytes += len;
 	}
-	iwl_leds_background(priv);
 }
-EXPORT_SYMBOL(iwl_update_stats);
 #endif
 
 static void iwl_force_rf_reset(struct iwl_priv *priv)
@@ -1909,7 +1825,6 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 	mutex_unlock(&priv->mutex);
 	return err;
 }
-EXPORT_SYMBOL(iwl_mac_change_interface);
 
 /*
  * On every watchdog tick we check (latest) time stamp. If it does not
@@ -1981,7 +1896,6 @@ void iwl_bg_watchdog(unsigned long data)
 	mod_timer(&priv->watchdog, jiffies +
 		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
 }
-EXPORT_SYMBOL(iwl_bg_watchdog);
 
 void iwl_setup_watchdog(struct iwl_priv *priv)
 {
@@ -1993,7 +1907,6 @@ void iwl_setup_watchdog(struct iwl_priv *priv)
 	else
 		del_timer(&priv->watchdog);
 }
-EXPORT_SYMBOL(iwl_setup_watchdog);
 
 /*
  * extended beacon time format
@@ -2019,7 +1932,6 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
 
 	return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
 }
-EXPORT_SYMBOL(iwl_usecs_to_beacons);
 
 /* base is usually what we get from ucode with each received frame,
  * the same as HW timer counter counting down
@@ -2047,7 +1959,6 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
 
 	return cpu_to_le32(res);
 }
-EXPORT_SYMBOL(iwl_add_beacon_time);
 
 #ifdef CONFIG_PM
 
@@ -2067,7 +1978,6 @@ int iwl_pci_suspend(struct device *device)
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_pci_suspend);
 
 int iwl_pci_resume(struct device *device)
 {
@@ -2096,7 +2006,6 @@ int iwl_pci_resume(struct device *device)
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_pci_resume);
 
 const struct dev_pm_ops iwl_pm_ops = {
 	.suspend = iwl_pci_suspend,
@@ -2106,6 +2015,5 @@ const struct dev_pm_ops iwl_pm_ops = {
 	.poweroff = iwl_pci_suspend,
 	.restore = iwl_pci_resume,
 };
-EXPORT_SYMBOL(iwl_pm_ops);
 
 #endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a347437..b316d83 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -63,6 +63,8 @@
 #ifndef __iwl_core_h__
 #define __iwl_core_h__
 
+#include "iwl-dev.h"
+
 /************************
  * forward declarations *
  ************************/
@@ -210,12 +212,7 @@ struct iwl_lib_ops {
 
 	/* temperature */
 	struct iwl_temp_ops temp_ops;
-	/* check for plcp health */
-	bool (*check_plcp_health)(struct iwl_priv *priv,
-					struct iwl_rx_packet *pkt);
-	/* check for ack health */
-	bool (*check_ack_health)(struct iwl_priv *priv,
-					struct iwl_rx_packet *pkt);
+
 	int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 
@@ -227,8 +224,6 @@ struct iwl_lib_ops {
 
 struct iwl_led_ops {
 	int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
-	int (*on)(struct iwl_priv *priv);
-	int (*off)(struct iwl_priv *priv);
 };
 
 /* NIC specific ops */
@@ -263,6 +258,8 @@ struct iwl_mod_params {
 	int amsdu_size_8K;	/* def: 1 = enable 8K amsdu size */
 	int antenna;  		/* def: 0 = both antennas (use diversity) */
 	int restart_fw;		/* def: 1 = restart firmware */
+	bool plcp_check;	/* def: true = enable plcp health check */
+	bool ack_check;		/* def: false = disable ack health check */
 };
 
 /*
@@ -307,7 +304,6 @@ struct iwl_base_params {
 	u16 led_compensation;
 	const bool broken_powersave;
 	int chain_noise_num_beacons;
-	const bool supports_idle;
 	bool adv_thermal_throttle;
 	bool support_ct_kill_exit;
 	const bool support_wimax_coexist;
@@ -342,6 +338,7 @@ struct iwl_bt_params {
 	u8 ampdu_factor;
 	u8 ampdu_density;
 	bool bt_sco_disable;
+	bool bt_session_2;
 };
 /*
  * @use_rts_for_aggregation: use rts/cts protection for HT traffic
@@ -366,6 +363,7 @@ struct iwl_ht_params {
  * @adv_pm: advance power management
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
+ * @iq_invert: I/Q inversion
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -415,6 +413,7 @@ struct iwl_cfg {
 	const bool adv_pm;
 	const bool rx_with_siso_diversity;
 	const bool internal_wimax_coex;
+	const bool iq_invert;
 };
 
 /***************************
@@ -444,10 +443,6 @@ bool iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
 void iwl_connection_init_rx_config(struct iwl_priv *priv,
 				   struct iwl_rxon_context *ctx);
 void iwl_set_rate(struct iwl_priv *priv);
-int iwl_set_decrypted_flag(struct iwl_priv *priv,
-			   struct ieee80211_hdr *hdr,
-			   u32 decrypt_res,
-			   struct ieee80211_rx_status *stats);
 void iwl_irq_handle_error(struct iwl_priv *priv);
 int iwl_mac_add_interface(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif);
@@ -494,46 +489,21 @@ static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
 				    __le16 fc, u16 len)
 {
-	struct traffic_stats	*stats;
-
-	if (is_tx)
-		stats = &priv->tx_stats;
-	else
-		stats = &priv->rx_stats;
-
-	if (ieee80211_is_data(fc)) {
-		/* data */
-		stats->data_bytes += len;
-	}
-	iwl_leds_background(priv);
 }
 #endif
-/*****************************************************
- * RX handlers.
- * **************************************************/
-void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-			   struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_reply_error(struct iwl_priv *priv,
-			struct iwl_rx_mem_buffer *rxb);
 
 /*****************************************************
 * RX
 ******************************************************/
 void iwl_cmd_queue_free(struct iwl_priv *priv);
+void iwl_cmd_queue_unmap(struct iwl_priv *priv);
 int iwl_rx_queue_alloc(struct iwl_priv *priv);
 void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
 				  struct iwl_rx_queue *q);
 int iwl_rx_queue_space(const struct iwl_rx_queue *q);
 void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-/* Handlers */
-void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
-					  struct iwl_rx_mem_buffer *rxb);
-void iwl_recover_from_statistics(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt);
+
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
-void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 
 /* TX helpers */
 
@@ -546,6 +516,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 			int slots_num, u32 txq_id);
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
+void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
 void iwl_setup_watchdog(struct iwl_priv *priv);
 /*****************************************************
  * TX power
@@ -582,6 +553,10 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 			       struct ieee80211_vif *vif);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
 void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
+int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   enum iwl_scan_type scan_type,
+				   enum ieee80211_band band);
 
 /* For faster active scanning, scan will move to the next channel if fewer than
  * PLCP_QUIET_THRESH packets are heard on this channel within
@@ -755,6 +730,17 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 	return priv->hw->wiphy->bands[band];
 }
 
+static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
+{
+	return priv->cfg->bt_params &&
+	       priv->cfg->bt_params->advanced_bt_coexist;
+}
+
+static inline bool iwl_bt_statistics(struct iwl_priv *priv)
+{
+	return priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics;
+}
+
 extern bool bt_coex_active;
 extern bool bt_siso_mode;
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index b80bf7d..f52bc04 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -290,7 +290,7 @@
 
 
 /* HW REV */
-#define CSR_HW_REV_TYPE_MSK            (0x00000F0)
+#define CSR_HW_REV_TYPE_MSK            (0x00001F0)
 #define CSR_HW_REV_TYPE_3945           (0x00000D0)
 #define CSR_HW_REV_TYPE_4965           (0x0000000)
 #define CSR_HW_REV_TYPE_5300           (0x0000020)
@@ -300,9 +300,15 @@
 #define CSR_HW_REV_TYPE_1000           (0x0000060)
 #define CSR_HW_REV_TYPE_6x00           (0x0000070)
 #define CSR_HW_REV_TYPE_6x50           (0x0000080)
-#define CSR_HW_REV_TYPE_6x50g2         (0x0000084)
-#define CSR_HW_REV_TYPE_6x00g2         (0x00000B0)
-#define CSR_HW_REV_TYPE_NONE           (0x00000F0)
+#define CSR_HW_REV_TYPE_6150           (0x0000084)
+#define CSR_HW_REV_TYPE_6x05	       (0x00000B0)
+#define CSR_HW_REV_TYPE_6x30	       CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_6x35	       CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_2x30	       (0x00000C0)
+#define CSR_HW_REV_TYPE_2x00	       (0x0000100)
+#define CSR_HW_REV_TYPE_200	       (0x0000110)
+#define CSR_HW_REV_TYPE_230	       (0x0000120)
+#define CSR_HW_REV_TYPE_NONE           (0x00001F0)
 
 /* EEPROM REG */
 #define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
@@ -376,6 +382,8 @@
 #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6	    (0x00000004)
 #define CSR_GP_DRIVER_REG_BIT_6050_1x2		    (0x00000008)
 
+#define CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER	    (0x00000080)
+
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
 #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 6fe80b5..8842411 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -207,18 +207,19 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
 	return ret;
 }
 
-#define BYTE1_MASK 0x000000ff;
-#define BYTE2_MASK 0x0000ffff;
-#define BYTE3_MASK 0x00ffffff;
 static ssize_t iwl_dbgfs_sram_read(struct file *file,
 					char __user *user_buf,
 					size_t count, loff_t *ppos)
 {
-	u32 val;
+	u32 val = 0;
 	char *buf;
 	ssize_t ret;
-	int i;
+	int i = 0;
+	bool device_format = false;
+	int offset = 0;
+	int len = 0;
 	int pos = 0;
+	int sram;
 	struct iwl_priv *priv = file->private_data;
 	size_t bufsz;
 
@@ -230,35 +231,62 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
 		else
 			priv->dbgfs_sram_len = priv->ucode_data.len;
 	}
-	bufsz =  30 + priv->dbgfs_sram_len * sizeof(char) * 10;
+	len = priv->dbgfs_sram_len;
+
+	if (len == -4) {
+		device_format = true;
+		len = 4;
+	}
+
+	bufsz =  50 + len * 4;
 	buf = kmalloc(bufsz, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
+
 	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
-			priv->dbgfs_sram_len);
+			 len);
 	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
 			priv->dbgfs_sram_offset);
-	for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
-		val = iwl_read_targ_mem(priv, priv->dbgfs_sram_offset + \
-					priv->dbgfs_sram_len - i);
-		if (i < 4) {
-			switch (i) {
-			case 1:
-				val &= BYTE1_MASK;
-				break;
-			case 2:
-				val &= BYTE2_MASK;
-				break;
-			case 3:
-				val &= BYTE3_MASK;
-				break;
-			}
+
+	/* adjust sram address since reads are only on even u32 boundaries */
+	offset = priv->dbgfs_sram_offset & 0x3;
+	sram = priv->dbgfs_sram_offset & ~0x3;
+
+	/* read the first u32 from sram */
+	val = iwl_read_targ_mem(priv, sram);
+
+	for (; len; len--) {
+		/* put the address at the start of every line */
+		if (i == 0)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%08X: ", sram + offset);
+
+		if (device_format)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%02x", (val >> (8 * (3 - offset))) & 0xff);
+		else
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%02x ", (val >> (8 * offset)) & 0xff);
+
+		/* if all bytes processed, read the next u32 from sram */
+		if (++offset == 4) {
+			sram += 4;
+			offset = 0;
+			val = iwl_read_targ_mem(priv, sram);
 		}
-		if (!(i % 16))
+
+		/* put in extra spaces and split lines for human readability */
+		if (++i == 16) {
+			i = 0;
 			pos += scnprintf(buf + pos, bufsz - pos, "\n");
-		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
+		} else if (!(i & 7)) {
+			pos += scnprintf(buf + pos, bufsz - pos, "   ");
+		} else if (!(i & 3)) {
+			pos += scnprintf(buf + pos, bufsz - pos, " ");
+		}
 	}
-	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	if (i)
+		pos += scnprintf(buf + pos, bufsz - pos, "\n");
 
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
@@ -282,6 +310,9 @@ static ssize_t iwl_dbgfs_sram_write(struct file *file,
 	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
 		priv->dbgfs_sram_offset = offset;
 		priv->dbgfs_sram_len = len;
+	} else if (sscanf(buf, "%x", &offset) == 1) {
+		priv->dbgfs_sram_offset = offset;
+		priv->dbgfs_sram_len = -4;
 	} else {
 		priv->dbgfs_sram_offset = 0;
 		priv->dbgfs_sram_len = 0;
@@ -668,29 +699,6 @@ static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf,
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
-static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
-				  size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char buf[256];
-	const size_t bufsz = sizeof(buf);
-
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "allow blinking: %s\n",
-			 (priv->allow_blinking) ? "True" : "False");
-	if (priv->allow_blinking) {
-		pos += scnprintf(buf + pos, bufsz - pos,
-				 "Led blinking rate: %u\n",
-				 priv->last_blink_rate);
-		pos += scnprintf(buf + pos, bufsz - pos,
-				 "Last blink time: %lu\n",
-				 priv->last_blink_time);
-	}
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
 static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
 				char __user *user_buf,
 				size_t count, loff_t *ppos)
@@ -856,7 +864,6 @@ DEBUGFS_READ_FILE_OPS(channels);
 DEBUGFS_READ_FILE_OPS(status);
 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 DEBUGFS_READ_FILE_OPS(qos);
-DEBUGFS_READ_FILE_OPS(led);
 DEBUGFS_READ_FILE_OPS(thermal_throttling);
 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
@@ -1580,10 +1587,9 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,
 			 "last traffic notif: %d\n",
 		priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load);
 	pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "
-			 "sco_active: %d, kill_ack_mask: %x, "
-			 "kill_cts_mask: %x\n",
-		priv->bt_ch_announce, priv->bt_sco_active,
-		priv->kill_ack_mask, priv->kill_cts_mask);
+			 "kill_ack_mask: %x, kill_cts_mask: %x\n",
+		priv->bt_ch_announce, priv->kill_ack_mask,
+		priv->kill_cts_mask);
 
 	pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");
 	switch (priv->bt_traffic_load) {
@@ -1725,7 +1731,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
-	DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
 	if (!priv->cfg->base_params->broken_powersave) {
 		DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
 				 S_IWUSR | S_IRUSR);
@@ -1759,13 +1764,13 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
 	if (priv->cfg->base_params->ucode_tracing)
 		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
-	if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)
+	if (iwl_bt_statistics(priv))
 		DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
-	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
+	if (iwl_advanced_bt_coexist(priv))
 		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
 	if (priv->cfg->base_params->sensitivity_calib_by_driver)
 		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
@@ -1783,7 +1788,6 @@ err:
 	iwl_dbgfs_unregister(priv);
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(iwl_dbgfs_register);
 
 /**
  * Remove the debugfs files and directories
@@ -1797,7 +1801,6 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
 	debugfs_remove_recursive(priv->debugfs_dir);
 	priv->debugfs_dir = NULL;
 }
-EXPORT_SYMBOL(iwl_dbgfs_unregister);
 
 
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 8dda678..68b953f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -34,6 +34,8 @@
 
 #include <linux/pci.h> /* for struct pci_device_id */
 #include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/leds.h>
 #include <net/ieee80211_radiotap.h>
 
 #include "iwl-eeprom.h"
@@ -41,14 +43,14 @@
 #include "iwl-prph.h"
 #include "iwl-fh.h"
 #include "iwl-debug.h"
-#include "iwl-4965-hw.h"
-#include "iwl-3945-hw.h"
 #include "iwl-agn-hw.h"
 #include "iwl-led.h"
 #include "iwl-power.h"
 #include "iwl-agn-rs.h"
 #include "iwl-agn-tt.h"
 
+#define U32_PAD(n)		((4-(n))&0x3)
+
 struct iwl_tx_queue;
 
 /* CT-KILL constants */
@@ -136,7 +138,7 @@ struct iwl_queue {
 				* space more than this */
 	int high_mark;         /* high watermark, stop queue if free
 				* space less than this */
-} __packed;
+};
 
 /* One for each TFD */
 struct iwl_tx_info {
@@ -507,6 +509,7 @@ struct iwl_station_priv {
 	atomic_t pending_frames;
 	bool client;
 	bool asleep;
+	u8 max_agg_bufsize;
 };
 
 /**
@@ -995,7 +998,6 @@ struct reply_agg_tx_error_statistics {
 	u32 unknown;
 };
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
 /* management statistics */
 enum iwl_mgmt_stats {
 	MANAGEMENT_ASSOC_REQ = 0,
@@ -1026,16 +1028,13 @@ enum iwl_ctrl_stats {
 };
 
 struct traffic_stats {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
 	u32 mgmt[MANAGEMENT_MAX];
 	u32 ctrl[CONTROL_MAX];
 	u32 data_cnt;
 	u64 data_bytes;
-};
-#else
-struct traffic_stats {
-	u64 data_bytes;
-};
 #endif
+};
 
 /*
  * iwl_switch_rxon: "channel switch" structure
@@ -1111,6 +1110,11 @@ struct iwl_event_log {
 /* BT Antenna Coupling Threshold (dB) */
 #define IWL_BT_ANTENNA_COUPLING_THRESHOLD	(35)
 
+/* Firmware reload counter and Timestamp */
+#define IWL_MIN_RELOAD_DURATION		1000 /* 1000 ms */
+#define IWL_MAX_CONTINUE_RELOAD_CNT	4
+
+
 enum iwl_reset {
 	IWL_RF_RESET = 0,
 	IWL_FW_RESET,
@@ -1139,6 +1143,33 @@ struct iwl_force_reset {
  */
 #define IWLAGN_EXT_BEACON_TIME_POS	22
 
+/**
+ * struct iwl_notification_wait - notification wait entry
+ * @list: list head for global list
+ * @fn: function called with the notification
+ * @cmd: command ID
+ *
+ * This structure is not used directly, to wait for a
+ * notification declare it on the stack, and call
+ * iwlagn_init_notification_wait() with appropriate
+ * parameters. Then do whatever will cause the ucode
+ * to notify the driver, and to wait for that then
+ * call iwlagn_wait_notification().
+ *
+ * Each notification is one-shot. If at some point we
+ * need to support multi-shot notifications (which
+ * can't be allocated on the stack) we need to modify
+ * the code for them.
+ */
+struct iwl_notification_wait {
+	struct list_head list;
+
+	void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt);
+
+	u8 cmd;
+	bool triggered;
+};
+
 enum iwl_rxon_context_id {
 	IWL_RXON_CTX_BSS,
 	IWL_RXON_CTX_PAN,
@@ -1199,6 +1230,12 @@ struct iwl_rxon_context {
 	} ht;
 };
 
+enum iwl_scan_type {
+	IWL_SCAN_NORMAL,
+	IWL_SCAN_RADIO_RESET,
+	IWL_SCAN_OFFCH_TX,
+};
+
 struct iwl_priv {
 
 	/* ieee device used by generic ieee processing code */
@@ -1230,12 +1267,16 @@ struct iwl_priv {
 	/* track IBSS manager (last beacon) status */
 	u32 ibss_manager;
 
-	/* storing the jiffies when the plcp error rate is received */
-	unsigned long plcp_jiffies;
+	/* jiffies when last recovery from statistics was performed */
+	unsigned long rx_statistics_jiffies;
 
 	/* force reset */
 	struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
 
+	/* firmware reload counter and timestamp */
+	unsigned long reload_jiffies;
+	int reload_count;
+
 	/* we allocate array of iwl_channel_info for NIC's valid channels.
 	 *    Access via channel # using indirect index array */
 	struct iwl_channel_info *channel_info;	/* channel info array */
@@ -1255,7 +1296,7 @@ struct iwl_priv {
 	enum ieee80211_band scan_band;
 	struct cfg80211_scan_request *scan_request;
 	struct ieee80211_vif *scan_vif;
-	bool is_internal_short_scan;
+	enum iwl_scan_type scan_type;
 	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
 	u8 mgmt_tx_ant;
 
@@ -1310,11 +1351,6 @@ struct iwl_priv {
 	struct iwl_init_alive_resp card_alive_init;
 	struct iwl_alive_resp card_alive;
 
-	unsigned long last_blink_time;
-	u8 last_blink_rate;
-	u8 allow_blinking;
-	u64 led_tpt;
-
 	u16 active_rate;
 
 	u8 start_calib;
@@ -1463,6 +1499,21 @@ struct iwl_priv {
 			struct iwl_bt_notif_statistics delta_statistics_bt;
 			struct iwl_bt_notif_statistics max_delta_bt;
 #endif
+
+			/* notification wait support */
+			struct list_head notif_waits;
+			spinlock_t notif_wait_lock;
+			wait_queue_head_t notif_waitq;
+
+			/* remain-on-channel offload support */
+			struct ieee80211_channel *hw_roc_channel;
+			struct delayed_work hw_roc_work;
+			enum nl80211_channel_type hw_roc_chantype;
+			int hw_roc_duration;
+
+			struct sk_buff *offchan_tx_skb;
+			int offchan_tx_timeout;
+			struct ieee80211_channel *offchan_tx_chan;
 		} _agn;
 #endif
 	};
@@ -1472,7 +1523,6 @@ struct iwl_priv {
 	u8 bt_status;
 	u8 bt_traffic_load, last_bt_traffic_load;
 	bool bt_ch_announce;
-	bool bt_sco_active;
 	bool bt_full_concurrent;
 	bool bt_ant_couple_ok;
 	__le32 kill_ack_mask;
@@ -1547,6 +1597,10 @@ struct iwl_priv {
 	bool hw_ready;
 
 	struct iwl_event_log event_log;
+
+	struct led_classdev led;
+	unsigned long blink_on, blink_off;
+	bool led_registered;
 }; /*iwl_priv */
 
 static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 358cfd7..833194a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -222,7 +222,6 @@ const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
 	BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
 	return &priv->eeprom[offset];
 }
-EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
 
 static int iwl_init_otp_access(struct iwl_priv *priv)
 {
@@ -382,7 +381,6 @@ const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
 {
 	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
 }
-EXPORT_SYMBOL(iwl_eeprom_query_addr);
 
 u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
 {
@@ -390,7 +388,6 @@ u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
 		return 0;
 	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
 }
-EXPORT_SYMBOL(iwl_eeprom_query16);
 
 /**
  * iwl_eeprom_init - read EEPROM contents
@@ -509,14 +506,12 @@ err:
 alloc_err:
 	return ret;
 }
-EXPORT_SYMBOL(iwl_eeprom_init);
 
 void iwl_eeprom_free(struct iwl_priv *priv)
 {
 	kfree(priv->eeprom);
 	priv->eeprom = NULL;
 }
-EXPORT_SYMBOL(iwl_eeprom_free);
 
 static void iwl_init_band_reference(const struct iwl_priv *priv,
 			int eep_band, int *eeprom_ch_count,
@@ -779,7 +774,6 @@ int iwl_init_channel_map(struct iwl_priv *priv)
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_init_channel_map);
 
 /*
  * iwl_free_channel_map - undo allocations in iwl_init_channel_map
@@ -789,7 +783,6 @@ void iwl_free_channel_map(struct iwl_priv *priv)
 	kfree(priv->channel_info);
 	priv->channel_count = 0;
 }
-EXPORT_SYMBOL(iwl_free_channel_map);
 
 /**
  * iwl_get_channel_info - Find driver's private channel info
@@ -818,4 +811,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
 
 	return NULL;
 }
-EXPORT_SYMBOL(iwl_get_channel_info);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 9e6f313..98aa8af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -247,13 +247,26 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_6050_TX_POWER_VERSION    (4)
 #define EEPROM_6050_EEPROM_VERSION	(0x532)
 
-/* 6x50g2 Specific */
-#define EEPROM_6050G2_TX_POWER_VERSION    (6)
-#define EEPROM_6050G2_EEPROM_VERSION	(0x553)
+/* 6150 Specific */
+#define EEPROM_6150_TX_POWER_VERSION    (6)
+#define EEPROM_6150_EEPROM_VERSION	(0x553)
+
+/* 6x05 Specific */
+#define EEPROM_6005_TX_POWER_VERSION    (6)
+#define EEPROM_6005_EEPROM_VERSION	(0x709)
+
+/* 6x30 Specific */
+#define EEPROM_6030_TX_POWER_VERSION    (6)
+#define EEPROM_6030_EEPROM_VERSION	(0x709)
+
+/* 2x00 Specific */
+#define EEPROM_2000_TX_POWER_VERSION    (6)
+#define EEPROM_2000_EEPROM_VERSION	(0x805)
+
+/* 6x35 Specific */
+#define EEPROM_6035_TX_POWER_VERSION    (6)
+#define EEPROM_6035_EEPROM_VERSION	(0x753)
 
-/* 6x00g2 Specific */
-#define EEPROM_6000G2_TX_POWER_VERSION    (6)
-#define EEPROM_6000G2_EEPROM_VERSION	(0x709)
 
 /* OTP */
 /* lower blocks contain EEPROM image and calibration data */
@@ -264,6 +277,7 @@ struct iwl_eeprom_enhanced_txpwr {
 #define OTP_MAX_LL_ITEMS_1000		(3)	/* OTP blocks for 1000 */
 #define OTP_MAX_LL_ITEMS_6x00		(4)	/* OTP blocks for 6x00 */
 #define OTP_MAX_LL_ITEMS_6x50		(7)	/* OTP blocks for 6x50 */
+#define OTP_MAX_LL_ITEMS_2x00		(4)	/* OTP blocks for 2x00 */
 
 /* 2.4 GHz */
 extern const u8 iwl_eeprom_band_1[14];
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index c373b53..02499f6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -108,12 +108,12 @@ const char *get_cmd_string(u8 cmd)
 		IWL_CMD(REPLY_WIPAN_WEPKEY);
 		IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
 		IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
+		IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
 	default:
 		return "UNKNOWN";
 
 	}
 }
-EXPORT_SYMBOL(get_cmd_string);
 
 #define HOST_COMPLETE_TIMEOUT (HZ / 2)
 
@@ -252,7 +252,6 @@ out:
 	mutex_unlock(&priv->sync_cmd_mutex);
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_cmd_sync);
 
 int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 {
@@ -261,7 +260,6 @@ int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 
 	return iwl_send_cmd_sync(priv, cmd);
 }
-EXPORT_SYMBOL(iwl_send_cmd);
 
 int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
 {
@@ -273,7 +271,6 @@ int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
 
 	return iwl_send_cmd_sync(priv, &cmd);
 }
-EXPORT_SYMBOL(iwl_send_cmd_pdu);
 
 int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
 			   u8 id, u16 len, const void *data,
@@ -292,4 +289,3 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
 
 	return iwl_send_cmd_async(priv, &cmd);
 }
-EXPORT_SYMBOL(iwl_send_cmd_pdu_async);
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 46ccdf4..d7f2a0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -48,31 +48,19 @@ module_param(led_mode, int, S_IRUGO);
 MODULE_PARM_DESC(led_mode, "0=system default, "
 		"1=On(RF On)/Off(RF Off), 2=blinking");
 
-static const struct {
-	u16 tpt;	/* Mb/s */
-	u8 on_time;
-	u8 off_time;
-} blink_tbl[] =
-{
-	{300, 25, 25},
-	{200, 40, 40},
-	{100, 55, 55},
-	{70, 65, 65},
-	{50, 75, 75},
-	{20, 85, 85},
-	{10, 95, 95},
-	{5, 110, 110},
-	{1, 130, 130},
-	{0, 167, 167},
-	/* SOLID_ON */
-	{-1, IWL_LED_SOLID, 0}
+static const struct ieee80211_tpt_blink iwl_blink[] = {
+	{ .throughput = 0 * 1024 - 1, .blink_time = 334 },
+	{ .throughput = 1 * 1024 - 1, .blink_time = 260 },
+	{ .throughput = 5 * 1024 - 1, .blink_time = 220 },
+	{ .throughput = 10 * 1024 - 1, .blink_time = 190 },
+	{ .throughput = 20 * 1024 - 1, .blink_time = 170 },
+	{ .throughput = 50 * 1024 - 1, .blink_time = 150 },
+	{ .throughput = 70 * 1024 - 1, .blink_time = 130 },
+	{ .throughput = 100 * 1024 - 1, .blink_time = 110 },
+	{ .throughput = 200 * 1024 - 1, .blink_time = 80 },
+	{ .throughput = 300 * 1024 - 1, .blink_time = 50 },
 };
 
-#define IWL_1MB_RATE (128 * 1024)
-#define IWL_LED_THRESHOLD (16)
-#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */
-#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
-
 /*
  * Adjust led blink rate to compensate on a MAC Clock difference on every HW
  * Led blink rate analysis showed an average deviation of 0% on 3945,
@@ -97,133 +85,102 @@ static inline u8 iwl_blink_compensation(struct iwl_priv *priv,
 }
 
 /* Set led pattern command */
-static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx)
+static int iwl_led_cmd(struct iwl_priv *priv,
+		       unsigned long on,
+		       unsigned long off)
 {
 	struct iwl_led_cmd led_cmd = {
 		.id = IWL_LED_LINK,
 		.interval = IWL_DEF_LED_INTRVL
 	};
+	int ret;
+
+	if (!test_bit(STATUS_READY, &priv->status))
+		return -EBUSY;
 
-	BUG_ON(idx > IWL_MAX_BLINK_TBL);
+	if (priv->blink_on == on && priv->blink_off == off)
+		return 0;
 
-	IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n",
+	IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
 			priv->cfg->base_params->led_compensation);
-	led_cmd.on =
-		iwl_blink_compensation(priv, blink_tbl[idx].on_time,
+	led_cmd.on = iwl_blink_compensation(priv, on,
 				priv->cfg->base_params->led_compensation);
-	led_cmd.off =
-		iwl_blink_compensation(priv, blink_tbl[idx].off_time,
+	led_cmd.off = iwl_blink_compensation(priv, off,
 				priv->cfg->base_params->led_compensation);
 
-	return priv->cfg->ops->led->cmd(priv, &led_cmd);
+	ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
+	if (!ret) {
+		priv->blink_on = on;
+		priv->blink_off = off;
+	}
+	return ret;
 }
 
-int iwl_led_start(struct iwl_priv *priv)
+static void iwl_led_brightness_set(struct led_classdev *led_cdev,
+				   enum led_brightness brightness)
 {
-	return priv->cfg->ops->led->on(priv);
-}
-EXPORT_SYMBOL(iwl_led_start);
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
+	unsigned long on = 0;
 
-int iwl_led_associate(struct iwl_priv *priv)
-{
-	IWL_DEBUG_LED(priv, "Associated\n");
-	if (priv->cfg->led_mode == IWL_LED_BLINK)
-		priv->allow_blinking = 1;
-	priv->last_blink_time = jiffies;
+	if (brightness > 0)
+		on = IWL_LED_SOLID;
 
-	return 0;
+	iwl_led_cmd(priv, on, 0);
 }
-EXPORT_SYMBOL(iwl_led_associate);
 
-int iwl_led_disassociate(struct iwl_priv *priv)
+static int iwl_led_blink_set(struct led_classdev *led_cdev,
+			     unsigned long *delay_on,
+			     unsigned long *delay_off)
 {
-	priv->allow_blinking = 0;
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
 
-	return 0;
+	return iwl_led_cmd(priv, *delay_on, *delay_off);
 }
-EXPORT_SYMBOL(iwl_led_disassociate);
 
-/*
- * calculate blink rate according to last second Tx/Rx activities
- */
-static int iwl_get_blink_rate(struct iwl_priv *priv)
-{
-	int i;
-	/* count both tx and rx traffic to be able to
-	 * handle traffic in either direction
-	 */
-	u64 current_tpt = priv->tx_stats.data_bytes +
-			  priv->rx_stats.data_bytes;
-	s64 tpt = current_tpt - priv->led_tpt;
-
-	if (tpt < 0) /* wraparound */
-		tpt = -tpt;
-
-	IWL_DEBUG_LED(priv, "tpt %lld current_tpt %llu\n",
-		(long long)tpt,
-		(unsigned long long)current_tpt);
-	priv->led_tpt = current_tpt;
-
-	if (!priv->allow_blinking)
-		i = IWL_MAX_BLINK_TBL;
-	else
-		for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
-			if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
-				break;
-
-	IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i);
-	return i;
-}
-
-/*
- * this function called from handler. Since setting Led command can
- * happen very frequent we postpone led command to be called from
- * REPLY handler so we know ucode is up
- */
-void iwl_leds_background(struct iwl_priv *priv)
+void iwl_leds_init(struct iwl_priv *priv)
 {
-	u8 blink_idx;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		priv->last_blink_time = 0;
-		return;
-	}
-	if (iwl_is_rfkill(priv)) {
-		priv->last_blink_time = 0;
-		return;
+	int mode = led_mode;
+	int ret;
+
+	if (mode == IWL_LED_DEFAULT)
+		mode = priv->cfg->led_mode;
+
+	priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
+				   wiphy_name(priv->hw->wiphy));
+	priv->led.brightness_set = iwl_led_brightness_set;
+	priv->led.blink_set = iwl_led_blink_set;
+	priv->led.max_brightness = 1;
+
+	switch (mode) {
+	case IWL_LED_DEFAULT:
+		WARN_ON(1);
+		break;
+	case IWL_LED_BLINK:
+		priv->led.default_trigger =
+			ieee80211_create_tpt_led_trigger(priv->hw,
+					IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
+					iwl_blink, ARRAY_SIZE(iwl_blink));
+		break;
+	case IWL_LED_RF_STATE:
+		priv->led.default_trigger =
+			ieee80211_get_radio_led_name(priv->hw);
+		break;
 	}
 
-	if (!priv->allow_blinking) {
-		priv->last_blink_time = 0;
-		if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
-			priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
-			iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX);
-		}
+	ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+	if (ret) {
+		kfree(priv->led.name);
 		return;
 	}
-	if (!priv->last_blink_time ||
-	    !time_after(jiffies, priv->last_blink_time +
-			msecs_to_jiffies(1000)))
-		return;
-
-	blink_idx = iwl_get_blink_rate(priv);
-
-	/* call only if blink rate change */
-	if (blink_idx != priv->last_blink_rate)
-		iwl_led_pattern(priv, blink_idx);
 
-	priv->last_blink_time = jiffies;
-	priv->last_blink_rate = blink_idx;
+	priv->led_registered = true;
 }
-EXPORT_SYMBOL(iwl_leds_background);
 
-void iwl_leds_init(struct iwl_priv *priv)
+void iwl_leds_exit(struct iwl_priv *priv)
 {
-	priv->last_blink_rate = 0;
-	priv->last_blink_time = 0;
-	priv->allow_blinking = 0;
-	if (led_mode != IWL_LED_DEFAULT &&
-	    led_mode != priv->cfg->led_mode)
-		priv->cfg->led_mode = led_mode;
+	if (!priv->led_registered)
+		return;
+
+	led_classdev_unregister(&priv->led);
+	kfree(priv->led.name);
 }
-EXPORT_SYMBOL(iwl_leds_init);
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h
index 9079b33..101eef1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-led.h
@@ -31,23 +31,14 @@
 struct iwl_priv;
 
 #define IWL_LED_SOLID 11
-#define IWL_LED_NAME_LEN 31
 #define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
 
 #define IWL_LED_ACTIVITY       (0<<1)
 #define IWL_LED_LINK           (1<<1)
 
-enum led_type {
-	IWL_LED_TRG_TX,
-	IWL_LED_TRG_RX,
-	IWL_LED_TRG_ASSOC,
-	IWL_LED_TRG_RADIO,
-	IWL_LED_TRG_MAX,
-};
-
 /*
  * LED mode
- *    IWL_LED_DEFAULT:  use system default
+ *    IWL_LED_DEFAULT:  use device default
  *    IWL_LED_RF_STATE: turn LED on/off based on RF state
  *			LED ON  = RF ON
  *			LED OFF = RF OFF
@@ -60,9 +51,6 @@ enum iwl_led_mode {
 };
 
 void iwl_leds_init(struct iwl_priv *priv);
-void iwl_leds_background(struct iwl_priv *priv);
-int iwl_led_start(struct iwl_priv *priv);
-int iwl_led_associate(struct iwl_priv *priv);
-int iwl_led_disassociate(struct iwl_priv *priv);
+void iwl_leds_exit(struct iwl_priv *priv);
 
 #endif /* __iwl_leds_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.c b/drivers/net/wireless/iwlwifi/iwl-legacy.c
deleted file mode 100644
index bb1a742..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-legacy.c
+++ /dev/null
@@ -1,662 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include <linux/kernel.h>
-#include <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-legacy.h"
-
-static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!ctx->is_active)
-		return;
-
-	ctx->qos_data.def_qos_parm.qos_flags = 0;
-
-	if (ctx->qos_data.qos_active)
-		ctx->qos_data.def_qos_parm.qos_flags |=
-			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
-
-	if (ctx->ht.enabled)
-		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
-
-	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
-		      ctx->qos_data.qos_active,
-		      ctx->qos_data.def_qos_parm.qos_flags);
-
-	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
-			       sizeof(struct iwl_qosparam_cmd),
-			       &ctx->qos_data.def_qos_parm, NULL);
-}
-
-/**
- * iwl_legacy_mac_config - mac80211 config callback
- */
-int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct iwl_priv *priv = hw->priv;
-	const struct iwl_channel_info *ch_info;
-	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_channel *channel = conf->channel;
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct iwl_rxon_context *ctx;
-	unsigned long flags = 0;
-	int ret = 0;
-	u16 ch;
-	int scan_active = 0;
-	bool ht_changed[NUM_IWL_RXON_CTX] = {};
-
-	if (WARN_ON(!priv->cfg->ops->legacy))
-		return -EOPNOTSUPP;
-
-	mutex_lock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-					channel->hw_value, changed);
-
-	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
-			test_bit(STATUS_SCANNING, &priv->status))) {
-		scan_active = 1;
-		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
-		       IEEE80211_CONF_CHANGE_CHANNEL)) {
-		/* mac80211 uses static for non-HT which is what we want */
-		priv->current_ht_config.smps = conf->smps_mode;
-
-		/*
-		 * Recalculate chain counts.
-		 *
-		 * If monitor mode is enabled then mac80211 will
-		 * set up the SM PS mode to OFF if an HT channel is
-		 * configured.
-		 */
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			for_each_context(priv, ctx)
-				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	/* during scanning mac80211 will delay channel setting until
-	 * scan finish with changed = 0
-	 */
-	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
-		if (scan_active)
-			goto set_ch_out;
-
-		ch = channel->hw_value;
-		ch_info = iwl_get_channel_info(priv, channel->band, ch);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-			ret = -EINVAL;
-			goto set_ch_out;
-		}
-
-		spin_lock_irqsave(&priv->lock, flags);
-
-		for_each_context(priv, ctx) {
-			/* Configure HT40 channels */
-			if (ctx->ht.enabled != conf_is_ht(conf)) {
-				ctx->ht.enabled = conf_is_ht(conf);
-				ht_changed[ctx->ctxid] = true;
-			}
-			if (ctx->ht.enabled) {
-				if (conf_is_ht40_minus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ctx->ht.is_40mhz = true;
-				} else if (conf_is_ht40_plus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ctx->ht.is_40mhz = true;
-				} else {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ctx->ht.is_40mhz = false;
-				}
-			} else
-				ctx->ht.is_40mhz = false;
-
-			/*
-			 * Default to no protection. Protection mode will
-			 * later be set from BSS config in iwl_ht_conf
-			 */
-			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
-
-			/* if we are switching from ht to 2.4 clear flags
-			 * from any ht related info since 2.4 does not
-			 * support ht */
-			if ((le16_to_cpu(ctx->staging.channel) != ch))
-				ctx->staging.flags = 0;
-
-			iwl_set_rxon_channel(priv, channel, ctx);
-			iwl_set_rxon_ht(priv, ht_conf);
-
-			iwl_set_flags_for_band(priv, ctx, channel->band,
-					       ctx->vif);
-		}
-
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		if (priv->cfg->ops->legacy->update_bcast_stations)
-			ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
-
- set_ch_out:
-		/* The list of supported rates and rate mask can be different
-		 * for each band; since the band may have changed, reset
-		 * the rate mask to what mac80211 lists */
-		iwl_set_rate(priv);
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_PS |
-			IEEE80211_CONF_CHANGE_IDLE)) {
-		ret = iwl_power_update_mode(priv, false);
-		if (ret)
-			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
-			priv->tx_power_user_lmt, conf->power_level);
-
-		iwl_set_tx_power(priv, conf->power_level, false);
-	}
-
-	if (!iwl_is_ready(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		goto out;
-	}
-
-	if (scan_active)
-		goto out;
-
-	for_each_context(priv, ctx) {
-		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
-			iwlcore_commit_rxon(priv, ctx);
-		else
-			IWL_DEBUG_INFO(priv,
-				"Not re-sending same RXON configuration.\n");
-		if (ht_changed[ctx->ctxid])
-			iwl_update_qos(priv, ctx);
-	}
-
-out:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_config);
-
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	/* IBSS can only be the IWL_RXON_CTX_BSS context */
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (WARN_ON(!priv->cfg->ops->legacy))
-		return;
-
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	spin_lock_irqsave(&priv->lock, flags);
-	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* new association get rid of ibss beacon skb */
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = NULL;
-
-	priv->timestamp = 0;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_scan_cancel_timeout(priv, 100);
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
-
-	/* we are restarting association process
-	 * clear RXON_FILTER_ASSOC_MSK bit
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
-
-	iwl_set_rate(priv);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
-
-static void iwl_ht_conf(struct iwl_priv *priv,
-			struct ieee80211_vif *vif)
-{
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct ieee80211_sta *sta;
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	IWL_DEBUG_ASSOC(priv, "enter:\n");
-
-	if (!ctx->ht.enabled)
-		return;
-
-	ctx->ht.protection =
-		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-	ctx->ht.non_gf_sta_present =
-		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-	ht_conf->single_chain_sufficient = false;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		rcu_read_lock();
-		sta = ieee80211_find_sta(vif, bss_conf->bssid);
-		if (sta) {
-			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-			int maxstreams;
-
-			maxstreams = (ht_cap->mcs.tx_params &
-				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-			maxstreams += 1;
-
-			if ((ht_cap->mcs.rx_mask[1] == 0) &&
-			    (ht_cap->mcs.rx_mask[2] == 0))
-				ht_conf->single_chain_sufficient = true;
-			if (maxstreams <= 1)
-				ht_conf->single_chain_sufficient = true;
-		} else {
-			/*
-			 * If at all, this can only happen through a race
-			 * when the AP disconnects us while we're still
-			 * setting up the connection, in that case mac80211
-			 * will soon tell us about that.
-			 */
-			ht_conf->single_chain_sufficient = true;
-		}
-		rcu_read_unlock();
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		ht_conf->single_chain_sufficient = true;
-		break;
-	default:
-		break;
-	}
-
-	IWL_DEBUG_ASSOC(priv, "leave\n");
-}
-
-static inline void iwl_set_no_assoc(struct iwl_priv *priv,
-				    struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	iwl_led_disassociate(priv);
-	/*
-	 * inform the ucode that there is no longer an
-	 * association and that no more packets should be
-	 * sent
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ctx->staging.assoc_id = 0;
-	iwlcore_commit_rxon(priv, ctx);
-}
-
-static void iwlcore_beacon_update(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	__le64 timestamp;
-	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
-
-	if (!skb)
-		return;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (!priv->beacon_ctx) {
-		IWL_ERR(priv, "update beacon but no beacon context!\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = skb;
-
-	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-	priv->timestamp = le64_to_cpu(timestamp);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return;
-	}
-
-	priv->cfg->ops->legacy->post_associate(priv);
-}
-
-void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	int ret;
-
-	if (WARN_ON(!priv->cfg->ops->legacy))
-		return;
-
-	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-	if (!iwl_is_alive(priv))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	if (changes & BSS_CHANGED_QOS) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&priv->lock, flags);
-		ctx->qos_data.qos_active = bss_conf->qos;
-		iwl_update_qos(priv, ctx);
-		spin_unlock_irqrestore(&priv->lock, flags);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		/*
-		 * the add_interface code must make sure we only ever
-		 * have a single interface that could be beaconing at
-		 * any time.
-		 */
-		if (vif->bss_conf.enable_beacon)
-			priv->beacon_ctx = ctx;
-		else
-			priv->beacon_ctx = NULL;
-	}
-
-	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
-		dev_kfree_skb(priv->beacon_skb);
-		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
-		iwl_send_rxon_timing(priv, ctx);
-
-	if (changes & BSS_CHANGED_BSSID) {
-		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
-
-		/*
-		 * If there is currently a HW scan going on in the
-		 * background then we need to cancel it else the RXON
-		 * below/in post_associate will fail.
-		 */
-		if (iwl_scan_cancel_timeout(priv, 100)) {
-			IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-			mutex_unlock(&priv->mutex);
-			return;
-		}
-
-		/* mac80211 only sets assoc when in STATION mode */
-		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-
-			/* currently needed in a few places */
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-		} else {
-			ctx->staging.filter_flags &=
-				~RXON_FILTER_ASSOC_MSK;
-		}
-
-	}
-
-	/*
-	 * This needs to be after setting the BSSID in case
-	 * mac80211 decides to do both changes at once because
-	 * it will invoke post_associate.
-	 */
-	if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
-		iwlcore_beacon_update(hw, vif);
-
-	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-				   bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-	}
-
-	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-		if (bss_conf->use_cts_prot)
-			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
-	}
-
-	if (changes & BSS_CHANGED_BASIC_RATES) {
-		/* XXX use this information
-		 *
-		 * To do that, remove code from iwl_set_rate() and put something
-		 * like this here:
-		 *
-		if (A-band)
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates;
-		else
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates >> 4;
-			ctx->staging.cck_basic_rates =
-				bss_conf->basic_rates & 0xF;
-		 */
-	}
-
-	if (changes & BSS_CHANGED_HT) {
-		iwl_ht_conf(priv, vif);
-
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-		if (bss_conf->assoc) {
-			priv->timestamp = bss_conf->timestamp;
-
-			iwl_led_associate(priv);
-
-			if (!iwl_is_rfkill(priv))
-				priv->cfg->ops->legacy->post_associate(priv);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
-		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
-				   changes);
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (!ret) {
-			/* Sync active_rxon with latest change. */
-			memcpy((void *)&ctx->active,
-				&ctx->staging,
-				sizeof(struct iwl_rxon_cmd));
-		}
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		if (vif->bss_conf.enable_beacon) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-			iwl_led_associate(priv);
-			priv->cfg->ops->legacy->config_ap(priv);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes & BSS_CHANGED_IBSS) {
-		ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
-							bss_conf->ibss_joined);
-		if (ret)
-			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
-				bss_conf->ibss_joined ? "add" : "remove",
-				bss_conf->bssid);
-	}
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
-
-irqreturn_t iwl_isr_legacy(int irq, void *data)
-{
-	struct iwl_priv *priv = data;
-	u32 inta, inta_mask;
-	u32 inta_fh;
-	unsigned long flags;
-	if (!priv)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Disable (but don't clear!) interrupts here to avoid
-	 *    back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the tasklet will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here. */
-	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
-	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-	/* Discover which interrupts are active/pending */
-	inta = iwl_read32(priv, CSR_INT);
-	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta && !inta_fh) {
-		IWL_DEBUG_ISR(priv,
-			"Ignore interrupt, inta == 0, inta_fh == 0\n");
-		goto none;
-	}
-
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		goto unplugged;
-	}
-
-	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-		      inta, inta_mask, inta_fh);
-
-	inta &= ~CSR_INT_BIT_SCD;
-
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-	if (likely(inta || inta_fh))
-		tasklet_schedule(&priv->irq_tasklet);
-
-unplugged:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_HANDLED;
-
-none:
-	/* re-enable interrupts here since we don't have anything to service. */
-	/* only Re-enable if disabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl_enable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_NONE;
-}
-EXPORT_SYMBOL(iwl_isr_legacy);
-
-/*
- *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
- *  function.
- */
-void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
-			       struct ieee80211_tx_info *info,
-			       __le16 fc, __le32 *tx_flags)
-{
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-		*tx_flags |= TX_CMD_FLG_RTS_MSK;
-		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-
-		if (!ieee80211_is_mgmt(fc))
-			return;
-
-		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-		case cpu_to_le16(IEEE80211_STYPE_AUTH):
-		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-			*tx_flags |= TX_CMD_FLG_CTS_MSK;
-			break;
-		}
-	} else if (info->control.rates[0].flags &
-		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
-		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-		*tx_flags |= TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-	}
-}
-EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
diff --git a/drivers/net/wireless/iwlwifi/iwl-legacy.h b/drivers/net/wireless/iwlwifi/iwl-legacy.h
deleted file mode 100644
index 9f7b2f9..0000000
--- a/drivers/net/wireless/iwlwifi/iwl-legacy.h
+++ /dev/null
@@ -1,79 +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) 2008 - 2010 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 - 2010 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_legacy_h__
-#define __iwl_legacy_h__
-
-/* mac80211 handlers */
-int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
-void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes);
-void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
-				struct ieee80211_tx_info *info,
-				__le16 fc, __le32 *tx_flags);
-
-irqreturn_t iwl_isr_legacy(int irq, void *data);
-
-#endif /* __iwl_legacy_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 1eec18d..576795e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -226,8 +226,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
 	else
 		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist) {
+	if (iwl_advanced_bt_coexist(priv)) {
 		if (!priv->cfg->bt_params->bt_sco_disable)
 			cmd->flags |= IWL_POWER_BT_SCO_ENA;
 		else
@@ -313,8 +312,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
 	else
 		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist) {
+	if (iwl_advanced_bt_coexist(priv)) {
 		if (!priv->cfg->bt_params->bt_sco_disable)
 			cmd->flags |= IWL_POWER_BT_SCO_ENA;
 		else
@@ -358,8 +356,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
 
 	if (priv->cfg->base_params->broken_powersave)
 		iwl_power_sleep_cam_cmd(priv, cmd);
-	else if (priv->cfg->base_params->supports_idle &&
-		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
+	else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
 		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
 	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
 		 priv->cfg->ops->lib->tt_ops.tt_power_mode &&
@@ -428,7 +425,6 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
 
 	return ret;
 }
-EXPORT_SYMBOL(iwl_power_set_mode);
 
 int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 {
@@ -437,7 +433,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 	iwl_power_build_cmd(priv, &cmd);
 	return iwl_power_set_mode(priv, &cmd, force);
 }
-EXPORT_SYMBOL(iwl_power_update_mode);
 
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
@@ -451,4 +446,3 @@ void iwl_power_initialize(struct iwl_priv *priv)
 	memset(&priv->power_data.sleep_cmd, 0,
 		sizeof(priv->power_data.sleep_cmd));
 }
-EXPORT_SYMBOL(iwl_power_initialize);
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 87a6fd8..6f9a2fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -29,6 +29,7 @@
 
 #include <linux/etherdevice.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <net/mac80211.h>
 #include <asm/unaligned.h>
 #include "iwl-eeprom.h"
@@ -37,7 +38,15 @@
 #include "iwl-sta.h"
 #include "iwl-io.h"
 #include "iwl-helpers.h"
-/************************** RX-FUNCTIONS ****************************/
+#include "iwl-agn-calib.h"
+#include "iwl-agn.h"
+
+/******************************************************************************
+ *
+ * RX path functions
+ *
+ ******************************************************************************/
+
 /*
  * Rx theory of operation
  *
@@ -118,7 +127,6 @@ int iwl_rx_queue_space(const struct iwl_rx_queue *q)
 		s = 0;
 	return s;
 }
-EXPORT_SYMBOL(iwl_rx_queue_space);
 
 /**
  * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
@@ -170,7 +178,6 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
  exit_unlock:
 	spin_unlock_irqrestore(&q->lock, flags);
 }
-EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
 
 int iwl_rx_queue_alloc(struct iwl_priv *priv)
 {
@@ -211,10 +218,105 @@ err_rb:
 err_bd:
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(iwl_rx_queue_alloc);
+
+/******************************************************************************
+ *
+ * Generic RX handler implementations
+ *
+ ******************************************************************************/
+
+static void iwl_rx_reply_alive(struct iwl_priv *priv,
+			       struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_alive_resp *palive;
+	struct delayed_work *pwork;
+
+	palive = &pkt->u.alive_frame;
+
+	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+		       "0x%01X 0x%01X\n",
+		       palive->is_valid, palive->ver_type,
+		       palive->ver_subtype);
+
+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
+		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		memcpy(&priv->card_alive_init,
+		       &pkt->u.alive_frame,
+		       sizeof(struct iwl_init_alive_resp));
+		pwork = &priv->init_alive_start;
+	} else {
+		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->alive_start;
+	}
+
+	/* We delay the ALIVE response by 5ms to
+	 * give the HW RF Kill time to activate... */
+	if (palive->is_valid == UCODE_VALID_OK)
+		queue_delayed_work(priv->workqueue, pwork,
+				   msecs_to_jiffies(5));
+	else {
+		IWL_WARN(priv, "%s uCode did not respond OK.\n",
+			(palive->ver_subtype == INITIALIZE_SUBTYPE) ?
+			"init" : "runtime");
+		/*
+		 * If fail to load init uCode,
+		 * let's try to load the init uCode again.
+		 * We should not get into this situation, but if it
+		 * does happen, we should not move on and loading "runtime"
+		 * without proper calibrate the device.
+		 */
+		if (palive->ver_subtype == INITIALIZE_SUBTYPE)
+			priv->ucode_type = UCODE_NONE;
+		queue_work(priv->workqueue, &priv->restart);
+	}
+}
+
+static void iwl_rx_reply_error(struct iwl_priv *priv,
+			       struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
+		"seq 0x%04X ser 0x%08X\n",
+		le32_to_cpu(pkt->u.err_resp.error_type),
+		get_cmd_string(pkt->u.err_resp.cmd_id),
+		pkt->u.err_resp.cmd_id,
+		le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
+		le32_to_cpu(pkt->u.err_resp.error_info));
+}
+
+static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+	/*
+	 * MULTI-FIXME
+	 * See iwl_mac_channel_switch.
+	 */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
+
+	if (priv->switch_rxon.switch_in_progress) {
+		if (!le32_to_cpu(csa->status) &&
+		    (csa->channel == priv->switch_rxon.channel)) {
+			rxon->channel = csa->channel;
+			ctx->staging.channel = csa->channel;
+			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_chswitch_done(priv, true);
+		} else {
+			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_chswitch_done(priv, false);
+		}
+	}
+}
 
 
-void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
+static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -229,48 +331,494 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 	memcpy(&priv->measure_report, report, sizeof(*report));
 	priv->measurement_status |= MEASUREMENT_READY;
 }
-EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
 
-void iwl_recover_from_statistics(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
+static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
+				  struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
+		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
+#endif
+}
+
+static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+					     struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
+			"notification for %s:\n", len,
+			get_cmd_string(pkt->hdr.cmd));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+}
+
+static void iwl_rx_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
+	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+	IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
+		"tsf:0x%.8x%.8x rate:%d\n",
+		status & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+#endif
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
+	if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+		queue_work(priv->workqueue, &priv->beacon_update);
+}
+
+/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
+#define ACK_CNT_RATIO (50)
+#define BA_TIMEOUT_CNT (5)
+#define BA_TIMEOUT_MAX (16)
+
+/**
+ * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
+ *
+ * When the ACK count ratio is low and aggregated BA timeout retries exceeding
+ * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
+ * operation state.
+ */
+static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt)
+{
+	int actual_delta, expected_delta, ba_timeout_delta;
+	struct statistics_tx *cur, *old;
+
+	if (priv->_agn.agg_tids_count)
+		return true;
+
+	if (iwl_bt_statistics(priv)) {
+		cur = &pkt->u.stats_bt.tx;
+		old = &priv->_agn.statistics_bt.tx;
+	} else {
+		cur = &pkt->u.stats.tx;
+		old = &priv->_agn.statistics.tx;
+	}
+
+	actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
+		       le32_to_cpu(old->actual_ack_cnt);
+	expected_delta = le32_to_cpu(cur->expected_ack_cnt) -
+			 le32_to_cpu(old->expected_ack_cnt);
+
+	/* Values should not be negative, but we do not trust the firmware */
+	if (actual_delta <= 0 || expected_delta <= 0)
+		return true;
+
+	ba_timeout_delta = le32_to_cpu(cur->agg.ba_timeout) -
+			   le32_to_cpu(old->agg.ba_timeout);
+
+	if ((actual_delta * 100 / expected_delta) < ACK_CNT_RATIO &&
+	    ba_timeout_delta > BA_TIMEOUT_CNT) {
+		IWL_DEBUG_RADIO(priv, "deltas: actual %d expected %d ba_timeout %d\n",
+				actual_delta, expected_delta, ba_timeout_delta);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		/*
+		 * This is ifdef'ed on DEBUGFS because otherwise the
+		 * statistics aren't available. If DEBUGFS is set but
+		 * DEBUG is not, these will just compile out.
+		 */
+		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n",
+				priv->_agn.delta_statistics.tx.rx_detected_cnt);
+		IWL_DEBUG_RADIO(priv,
+				"ack_or_ba_timeout_collision delta %d\n",
+				priv->_agn.delta_statistics.tx.ack_or_ba_timeout_collision);
+#endif
+
+		if (ba_timeout_delta >= BA_TIMEOUT_MAX)
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * iwl_good_plcp_health - checks for plcp error.
+ *
+ * When the plcp error is exceeding the thresholds, reset the radio
+ * to improve the throughput.
+ */
+static bool iwl_good_plcp_health(struct iwl_priv *priv,
+				 struct iwl_rx_packet *pkt, unsigned int msecs)
 {
+	int delta;
+	int threshold = priv->cfg->base_params->plcp_delta_threshold;
+
+	if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
+		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
+		return true;
+	}
+
+	if (iwl_bt_statistics(priv)) {
+		struct statistics_rx_bt *cur, *old;
+
+		cur = &pkt->u.stats_bt.rx;
+		old = &priv->_agn.statistics_bt.rx;
+
+		delta = le32_to_cpu(cur->ofdm.plcp_err) -
+			le32_to_cpu(old->ofdm.plcp_err) +
+			le32_to_cpu(cur->ofdm_ht.plcp_err) -
+			le32_to_cpu(old->ofdm_ht.plcp_err);
+	} else {
+		struct statistics_rx *cur, *old;
+
+		cur = &pkt->u.stats.rx;
+		old = &priv->_agn.statistics.rx;
+
+		delta = le32_to_cpu(cur->ofdm.plcp_err) -
+			le32_to_cpu(old->ofdm.plcp_err) +
+			le32_to_cpu(cur->ofdm_ht.plcp_err) -
+			le32_to_cpu(old->ofdm_ht.plcp_err);
+	}
+
+	/* Can be negative if firmware reseted statistics */
+	if (delta <= 0)
+		return true;
+
+	if ((delta * 100 / msecs) > threshold) {
+		IWL_DEBUG_RADIO(priv,
+				"plcp health threshold %u delta %d msecs %u\n",
+				threshold, delta, msecs);
+		return false;
+	}
+
+	return true;
+}
+
+static void iwl_recover_from_statistics(struct iwl_priv *priv,
+					struct iwl_rx_packet *pkt)
+{
+	const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
+	unsigned int msecs;
+	unsigned long stamp;
+
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
-	if (iwl_is_any_associated(priv)) {
-		if (priv->cfg->ops->lib->check_ack_health) {
-			if (!priv->cfg->ops->lib->check_ack_health(
-			    priv, pkt)) {
-				/*
-				 * low ack count detected
-				 * restart Firmware
-				 */
-				IWL_ERR(priv, "low ack count detected, "
-					"restart firmware\n");
-				if (!iwl_force_reset(priv, IWL_FW_RESET, false))
-					return;
-			}
+
+	stamp = jiffies;
+	msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
+
+	/* Only gather statistics and update time stamp when not associated */
+	if (!iwl_is_any_associated(priv))
+		goto out;
+
+	/* Do not check/recover when do not have enough statistics data */
+	if (msecs < 99)
+		return;
+
+	if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) {
+		IWL_ERR(priv, "low ack count detected, restart firmware\n");
+		if (!iwl_force_reset(priv, IWL_FW_RESET, false))
+			return;
+	}
+
+	if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs))
+		iwl_force_reset(priv, IWL_RF_RESET, false);
+
+out:
+	if (iwl_bt_statistics(priv))
+		memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
+			sizeof(priv->_agn.statistics_bt));
+	else
+		memcpy(&priv->_agn.statistics, &pkt->u.stats,
+			sizeof(priv->_agn.statistics));
+
+	priv->rx_statistics_jiffies = stamp;
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void iwl_rx_calc_noise(struct iwl_priv *priv)
+{
+	struct statistics_rx_non_phy *rx_info;
+	int num_active_rx = 0;
+	int total_silence = 0;
+	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
+	int last_rx_noise;
+
+	if (iwl_bt_statistics(priv))
+		rx_info = &(priv->_agn.statistics_bt.rx.general.common);
+	else
+		rx_info = &(priv->_agn.statistics.rx.general);
+	bcn_silence_a =
+		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+	bcn_silence_b =
+		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+	bcn_silence_c =
+		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+
+	if (bcn_silence_a) {
+		total_silence += bcn_silence_a;
+		num_active_rx++;
+	}
+	if (bcn_silence_b) {
+		total_silence += bcn_silence_b;
+		num_active_rx++;
+	}
+	if (bcn_silence_c) {
+		total_silence += bcn_silence_c;
+		num_active_rx++;
+	}
+
+	/* Average among active antennas */
+	if (num_active_rx)
+		last_rx_noise = (total_silence / num_active_rx) - 107;
+	else
+		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
+			bcn_silence_a, bcn_silence_b, bcn_silence_c,
+			last_rx_noise);
+}
+
+/*
+ *  based on the assumption of all statistics counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void iwl_accumulative_statistics(struct iwl_priv *priv,
+					__le32 *stats)
+{
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	int i, size;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+	struct statistics_general_common *general, *accum_general;
+	struct statistics_tx *tx, *accum_tx;
+
+	if (iwl_bt_statistics(priv)) {
+		prev_stats = (__le32 *)&priv->_agn.statistics_bt;
+		accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
+		size = sizeof(struct iwl_bt_notif_statistics);
+		general = &priv->_agn.statistics_bt.general.common;
+		accum_general = &priv->_agn.accum_statistics_bt.general.common;
+		tx = &priv->_agn.statistics_bt.tx;
+		accum_tx = &priv->_agn.accum_statistics_bt.tx;
+		delta = (u32 *)&priv->_agn.delta_statistics_bt;
+		max_delta = (u32 *)&priv->_agn.max_delta_bt;
+	} else {
+		prev_stats = (__le32 *)&priv->_agn.statistics;
+		accum_stats = (u32 *)&priv->_agn.accum_statistics;
+		size = sizeof(struct iwl_notif_statistics);
+		general = &priv->_agn.statistics.general.common;
+		accum_general = &priv->_agn.accum_statistics.general.common;
+		tx = &priv->_agn.statistics.tx;
+		accum_tx = &priv->_agn.accum_statistics.tx;
+		delta = (u32 *)&priv->_agn.delta_statistics;
+		max_delta = (u32 *)&priv->_agn.max_delta;
+	}
+	for (i = sizeof(__le32); i < size;
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
 		}
-		if (priv->cfg->ops->lib->check_plcp_health) {
-			if (!priv->cfg->ops->lib->check_plcp_health(
-			    priv, pkt)) {
-				/*
-				 * high plcp error detected
-				 * reset Radio
-				 */
-				iwl_force_reset(priv, IWL_RF_RESET, false);
-			}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	accum_general->temperature = general->temperature;
+	accum_general->temperature_m = general->temperature_m;
+	accum_general->ttl_timestamp = general->ttl_timestamp;
+	accum_tx->tx_power.ant_a = tx->tx_power.ant_a;
+	accum_tx->tx_power.ant_b = tx->tx_power.ant_b;
+	accum_tx->tx_power.ant_c = tx->tx_power.ant_c;
+#endif
+}
+
+static void iwl_rx_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	const int reg_recalib_period = 60;
+	int change;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (iwl_bt_statistics(priv)) {
+		IWL_DEBUG_RX(priv,
+			     "Statistics notification received (%d vs %d).\n",
+			     (int)sizeof(struct iwl_bt_notif_statistics),
+			     le32_to_cpu(pkt->len_n_flags) &
+			     FH_RSCSR_FRAME_SIZE_MSK);
+
+		change = ((priv->_agn.statistics_bt.general.common.temperature !=
+			   pkt->u.stats_bt.general.common.temperature) ||
+			   ((priv->_agn.statistics_bt.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+			   (pkt->u.stats_bt.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+
+		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt);
+	} else {
+		IWL_DEBUG_RX(priv,
+			     "Statistics notification received (%d vs %d).\n",
+			     (int)sizeof(struct iwl_notif_statistics),
+			     le32_to_cpu(pkt->len_n_flags) &
+			     FH_RSCSR_FRAME_SIZE_MSK);
+
+		change = ((priv->_agn.statistics.general.common.temperature !=
+			   pkt->u.stats.general.common.temperature) ||
+			   ((priv->_agn.statistics.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+			   (pkt->u.stats.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+
+		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+	}
+
+	iwl_recover_from_statistics(priv, pkt);
+
+	set_bit(STATUS_STATISTICS, &priv->status);
+
+	/* Reschedule the statistics timer to occur in
+	 * reg_recalib_period seconds to ensure we get a
+	 * thermal update even if the uCode doesn't give
+	 * us one */
+	mod_timer(&priv->statistics_periodic, jiffies +
+		  msecs_to_jiffies(reg_recalib_period * 1000));
+
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+		iwl_rx_calc_noise(priv);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
+	}
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
+}
+
+static void iwl_rx_reply_statistics(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		memset(&priv->_agn.accum_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.delta_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.max_delta, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.accum_statistics_bt, 0,
+			sizeof(struct iwl_bt_notif_statistics));
+		memset(&priv->_agn.delta_statistics_bt, 0,
+			sizeof(struct iwl_bt_notif_statistics));
+		memset(&priv->_agn.max_delta_bt, 0,
+			sizeof(struct iwl_bt_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl_rx_statistics(priv, rxb);
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void iwl_rx_card_state_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+	unsigned long status = priv->status;
+
+	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & CT_CARD_DISABLED) ?
+			  "Reached" : "Not reached");
+
+	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
+		     CT_CARD_DISABLED)) {
+
+		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+		iwl_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+
+		if (!(flags & RXON_CARD_DISABLED)) {
+			iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+				    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+			iwl_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
 		}
+		if (flags & CT_CARD_DISABLED)
+			iwl_tt_enter_ct_kill(priv);
+	}
+	if (!(flags & CT_CARD_DISABLED))
+		iwl_tt_exit_ct_kill(priv);
+
+	if (flags & HW_CARD_DISABLED)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+
+	if (!(flags & RXON_CARD_DISABLED))
+		iwl_scan_cancel(priv);
+
+	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
+	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
+	else
+		wake_up_interruptible(&priv->wait_command_queue);
+}
+
+static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+				       struct iwl_rx_mem_buffer *rxb)
+
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_missed_beacon_notif *missed_beacon;
+
+	missed_beacon = &pkt->u.missed_beacon;
+	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+	    priv->missed_beacon_threshold) {
+		IWL_DEBUG_CALIB(priv,
+		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+		    le32_to_cpu(missed_beacon->total_missed_becons),
+		    le32_to_cpu(missed_beacon->num_recvd_beacons),
+		    le32_to_cpu(missed_beacon->num_expected_beacons));
+		if (!test_bit(STATUS_SCANNING, &priv->status))
+			iwl_init_sensitivity(priv);
 	}
 }
-EXPORT_SYMBOL(iwl_recover_from_statistics);
+
+/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	priv->_agn.last_phy_res_valid = true;
+	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
+	       sizeof(struct iwl_rx_phy_res));
+}
 
 /*
  * returns non-zero if packet should be dropped
  */
-int iwl_set_decrypted_flag(struct iwl_priv *priv,
-			   struct ieee80211_hdr *hdr,
-			   u32 decrypt_res,
-			   struct ieee80211_rx_status *stats)
+static int iwl_set_decrypted_flag(struct iwl_priv *priv,
+				  struct ieee80211_hdr *hdr,
+				  u32 decrypt_res,
+				  struct ieee80211_rx_status *stats)
 {
 	u16 fc = le16_to_cpu(hdr->frame_control);
 
@@ -315,4 +863,264 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_set_decrypted_flag);
+
+static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
+					struct ieee80211_hdr *hdr,
+					u16 len,
+					u32 ampdu_status,
+					struct iwl_rx_mem_buffer *rxb,
+					struct ieee80211_rx_status *stats)
+{
+	struct sk_buff *skb;
+	__le16 fc = hdr->frame_control;
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!priv->is_open)) {
+		IWL_DEBUG_DROP_LIMIT(priv,
+		    "Dropping packet while interface is not open.\n");
+		return;
+	}
+
+	/* In case of HW accelerated crypto and bad decryption, drop */
+	if (!priv->cfg->mod_params->sw_crypto &&
+	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
+		return;
+
+	skb = dev_alloc_skb(128);
+	if (!skb) {
+		IWL_ERR(priv, "dev_alloc_skb failed\n");
+		return;
+	}
+
+	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+
+	iwl_update_stats(priv, false, fc, len);
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+	ieee80211_rx(priv->hw, skb);
+	priv->alloc_rxb_page--;
+	rxb->page = NULL;
+}
+
+static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
+{
+	u32 decrypt_out = 0;
+
+	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
+					RX_RES_STATUS_STATION_FOUND)
+		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
+				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
+
+	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
+
+	/* packet was not encrypted */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_NONE)
+		return decrypt_out;
+
+	/* packet was encrypted with unknown alg */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_ERR)
+		return decrypt_out;
+
+	/* decryption was not done in HW */
+	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
+					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
+		return decrypt_out;
+
+	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
+
+	case RX_RES_STATUS_SEC_TYPE_CCMP:
+		/* alg is CCM: check MIC only */
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
+			/* Bad MIC */
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+
+		break;
+
+	case RX_RES_STATUS_SEC_TYPE_TKIP:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
+			/* Bad TTAK */
+			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
+			break;
+		}
+		/* fall through if TTAK OK */
+	default:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+		break;
+	}
+
+	IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
+					decrypt_in, decrypt_out);
+
+	return decrypt_out;
+}
+
+/* Called for REPLY_RX (legacy ABG frames), or
+ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+static void iwl_rx_reply_rx(struct iwl_priv *priv,
+			    struct iwl_rx_mem_buffer *rxb)
+{
+	struct ieee80211_hdr *header;
+	struct ieee80211_rx_status rx_status;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_rx_phy_res *phy_res;
+	__le32 rx_pkt_status;
+	struct iwl_rx_mpdu_res_start *amsdu;
+	u32 len;
+	u32 ampdu_status;
+	u32 rate_n_flags;
+
+	/**
+	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
+	 *	REPLY_RX: physical layer info is in this buffer
+	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
+	 *		command and cached in priv->last_phy_res
+	 *
+	 * Here we set up local variables depending on which command is
+	 * received.
+	 */
+	if (pkt->hdr.cmd == REPLY_RX) {
+		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+				+ phy_res->cfg_phy_cnt);
+
+		len = le16_to_cpu(phy_res->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+				phy_res->cfg_phy_cnt + len);
+		ampdu_status = le32_to_cpu(rx_pkt_status);
+	} else {
+		if (!priv->_agn.last_phy_res_valid) {
+			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
+			return;
+		}
+		phy_res = &priv->_agn.last_phy_res;
+		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+		len = le16_to_cpu(amsdu->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+		ampdu_status = iwl_translate_rx_status(priv,
+						le32_to_cpu(rx_pkt_status));
+	}
+
+	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				phy_res->cfg_phy_cnt);
+		return;
+	}
+
+	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
+				le32_to_cpu(rx_pkt_status));
+		return;
+	}
+
+	/* This will be used in several places later */
+	rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
+
+	/* rx_status carries information about the packet to mac80211 */
+	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
+	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	rx_status.freq =
+		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+					       rx_status.band);
+	rx_status.rate_idx =
+		iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
+	rx_status.flag = 0;
+
+	/* TSF isn't reliable. In order to allow smooth user experience,
+	 * this W/A doesn't propagate it to the mac80211 */
+	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+
+	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
+
+	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
+	rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res);
+
+	iwl_dbg_log_rx_data_frame(priv, len, header);
+	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
+		rx_status.signal, (unsigned long long)rx_status.mactime);
+
+	/*
+	 * "antenna number"
+	 *
+	 * It seems that the antenna field in the phy flags value
+	 * is actually a bit field. This is undefined by radiotap,
+	 * it wants an actual antenna number but I always get "7"
+	 * for most legacy frames I receive indicating that the
+	 * same frame was received on all three RX chains.
+	 *
+	 * I think this field should be removed in favor of a
+	 * new 802.11n radiotap field "RX chains" that is defined
+	 * as a bitmask.
+	 */
+	rx_status.antenna =
+		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
+
+	/* set the preamble flag if appropriate */
+	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+		rx_status.flag |= RX_FLAG_SHORTPRE;
+
+	/* Set up the HT phy flags */
+	if (rate_n_flags & RATE_MCS_HT_MSK)
+		rx_status.flag |= RX_FLAG_HT;
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
+		rx_status.flag |= RX_FLAG_40MHZ;
+	if (rate_n_flags & RATE_MCS_SGI_MSK)
+		rx_status.flag |= RX_FLAG_SHORT_GI;
+
+	iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+				    rxb, &rx_status);
+}
+
+/**
+ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
+ *
+ * Setup the RX handlers for each of the reply types sent from the uCode
+ * to the host.
+ */
+void iwl_setup_rx_handlers(struct iwl_priv *priv)
+{
+	void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+
+	handlers = priv->rx_handlers;
+
+	handlers[REPLY_ALIVE]			= iwl_rx_reply_alive;
+	handlers[REPLY_ERROR]			= iwl_rx_reply_error;
+	handlers[CHANNEL_SWITCH_NOTIFICATION]	= iwl_rx_csa;
+	handlers[SPECTRUM_MEASURE_NOTIFICATION]	= iwl_rx_spectrum_measure_notif;
+	handlers[PM_SLEEP_NOTIFICATION]		= iwl_rx_pm_sleep_notif;
+	handlers[PM_DEBUG_STATISTIC_NOTIFIC]	= iwl_rx_pm_debug_statistics_notif;
+	handlers[BEACON_NOTIFICATION]		= iwl_rx_beacon_notif;
+
+	/*
+	 * The same handler is used for both the REPLY to a discrete
+	 * statistics request from the host as well as for the periodic
+	 * statistics notifications (after received beacons) from the uCode.
+	 */
+	handlers[REPLY_STATISTICS_CMD]		= iwl_rx_reply_statistics;
+	handlers[STATISTICS_NOTIFICATION]	= iwl_rx_statistics;
+
+	iwl_setup_rx_scan_handlers(priv);
+
+	handlers[CARD_STATE_NOTIFICATION]	= iwl_rx_card_state_notif;
+	handlers[MISSED_BEACONS_NOTIFICATION]	= iwl_rx_missed_beacon_notif;
+
+	/* Rx handlers */
+	handlers[REPLY_RX_PHY_CMD]		= iwl_rx_reply_rx_phy;
+	handlers[REPLY_RX_MPDU_CMD]		= iwl_rx_reply_rx;
+
+	/* block ack */
+	handlers[REPLY_COMPRESSED_BA]		= iwlagn_rx_reply_compressed_ba;
+
+	/* Set up hardware specific Rx handlers */
+	priv->cfg->ops->lib->rx_handler_setup(priv);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 12d9363..3a4d9e6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -101,7 +101,7 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
 		ieee80211_scan_completed(priv->hw, aborted);
 	}
 
-	priv->is_internal_short_scan = false;
+	priv->scan_type = IWL_SCAN_NORMAL;
 	priv->scan_vif = NULL;
 	priv->scan_request = NULL;
 }
@@ -155,7 +155,6 @@ int iwl_scan_cancel(struct iwl_priv *priv)
 	queue_work(priv->workqueue, &priv->abort_scan);
 	return 0;
 }
-EXPORT_SYMBOL(iwl_scan_cancel);
 
 /**
  * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
@@ -180,7 +179,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
 
 	return test_bit(STATUS_SCAN_HW, &priv->status);
 }
-EXPORT_SYMBOL(iwl_scan_cancel_timeout);
 
 /* Service response to REPLY_SCAN_CMD (0x80) */
 static void iwl_rx_reply_scan(struct iwl_priv *priv,
@@ -257,8 +255,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
 	queue_work(priv->workqueue, &priv->scan_completed);
 
 	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
-	    priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    iwl_advanced_bt_coexist(priv) &&
 	    priv->bt_status != scan_notif->bt_status) {
 		if (scan_notif->bt_status) {
 			/* BT on */
@@ -289,7 +286,6 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
 	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
 					iwl_rx_scan_complete_notif;
 }
-EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
 
 inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
 				     enum ieee80211_band band,
@@ -302,7 +298,6 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
 		return IWL_ACTIVE_DWELL_TIME_24 +
 			IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
 }
-EXPORT_SYMBOL(iwl_get_active_dwell_time);
 
 u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 			       enum ieee80211_band band,
@@ -334,7 +329,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 
 	return passive;
 }
-EXPORT_SYMBOL(iwl_get_passive_dwell_time);
 
 void iwl_init_scan_params(struct iwl_priv *priv)
 {
@@ -344,12 +338,11 @@ void iwl_init_scan_params(struct iwl_priv *priv)
 	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
 		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
 }
-EXPORT_SYMBOL(iwl_init_scan_params);
 
-static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
-					  struct ieee80211_vif *vif,
-					  bool internal,
-					  enum ieee80211_band band)
+int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   enum iwl_scan_type scan_type,
+				   enum ieee80211_band band)
 {
 	int ret;
 
@@ -377,17 +370,19 @@ static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
 	}
 
 	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
-			internal ? "internal short " : "");
+			scan_type == IWL_SCAN_NORMAL ? "" :
+			scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " :
+			"internal short ");
 
 	set_bit(STATUS_SCANNING, &priv->status);
-	priv->is_internal_short_scan = internal;
+	priv->scan_type = scan_type;
 	priv->scan_start = jiffies;
 	priv->scan_band = band;
 
 	ret = priv->cfg->ops->utils->request_scan(priv, vif);
 	if (ret) {
 		clear_bit(STATUS_SCANNING, &priv->status);
-		priv->is_internal_short_scan = false;
+		priv->scan_type = IWL_SCAN_NORMAL;
 		return ret;
 	}
 
@@ -412,7 +407,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 	mutex_lock(&priv->mutex);
 
 	if (test_bit(STATUS_SCANNING, &priv->status) &&
-	    !priv->is_internal_short_scan) {
+	    priv->scan_type != IWL_SCAN_NORMAL) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
 		ret = -EAGAIN;
 		goto out_unlock;
@@ -426,11 +421,11 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 	 * If an internal scan is in progress, just set
 	 * up the scan_request as per above.
 	 */
-	if (priv->is_internal_short_scan) {
+	if (priv->scan_type != IWL_SCAN_NORMAL) {
 		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
 		ret = 0;
 	} else
-		ret = iwl_scan_initiate(priv, vif, false,
+		ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL,
 					req->channels[0]->band);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -440,7 +435,6 @@ out_unlock:
 
 	return ret;
 }
-EXPORT_SYMBOL(iwl_mac_hw_scan);
 
 /*
  * internal short scan, this function should only been called while associated.
@@ -460,7 +454,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
 
 	mutex_lock(&priv->mutex);
 
-	if (priv->is_internal_short_scan == true) {
+	if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
 		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
 		goto unlock;
 	}
@@ -470,7 +464,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
 		goto unlock;
 	}
 
-	if (iwl_scan_initiate(priv, NULL, true, priv->band))
+	if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
 		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
  unlock:
 	mutex_unlock(&priv->mutex);
@@ -537,7 +531,6 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
 
 	return (u16)len;
 }
-EXPORT_SYMBOL(iwl_fill_probe_req);
 
 static void iwl_bg_abort_scan(struct work_struct *work)
 {
@@ -558,8 +551,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
 	    container_of(work, struct iwl_priv, scan_completed);
 	bool aborted;
 
-	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
-		       priv->is_internal_short_scan ? "internal short " : "");
+	IWL_DEBUG_SCAN(priv, "Completed scan.\n");
 
 	cancel_delayed_work(&priv->scan_check);
 
@@ -574,7 +566,13 @@ static void iwl_bg_scan_completed(struct work_struct *work)
 		goto out_settings;
 	}
 
-	if (priv->is_internal_short_scan && !aborted) {
+	if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) {
+		ieee80211_tx_status_irqsafe(priv->hw,
+					    priv->_agn.offchan_tx_skb);
+		priv->_agn.offchan_tx_skb = NULL;
+	}
+
+	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
 		int err;
 
 		/* Check if mac80211 requested scan during our internal scan */
@@ -582,7 +580,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
 			goto out_complete;
 
 		/* If so request a new scan */
-		err = iwl_scan_initiate(priv, priv->scan_vif, false,
+		err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
 					priv->scan_request->channels[0]->band);
 		if (err) {
 			IWL_DEBUG_SCAN(priv,
@@ -622,7 +620,6 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
 	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
 	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 }
-EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
 
 void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
 {
@@ -636,4 +633,3 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
 		mutex_unlock(&priv->mutex);
 	}
 }
-EXPORT_SYMBOL(iwl_cancel_scan_deferred_work);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 49493d1..bc90a12 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -169,7 +169,6 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_add_sta);
 
 static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
 				   struct ieee80211_sta *sta,
@@ -316,7 +315,6 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 	return sta_id;
 
 }
-EXPORT_SYMBOL_GPL(iwl_prep_station);
 
 #define STA_WAIT_TIMEOUT (HZ/2)
 
@@ -379,7 +377,6 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 	*sta_id_r = sta_id;
 	return ret;
 }
-EXPORT_SYMBOL(iwl_add_station_common);
 
 /**
  * iwl_sta_ucode_deactivate - deactivate ucode status for a station
@@ -513,7 +510,6 @@ out_err:
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(iwl_remove_station);
 
 /**
  * iwl_clear_ucode_stations - clear ucode station table bits
@@ -548,7 +544,6 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
 	if (!cleared)
 		IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
 }
-EXPORT_SYMBOL(iwl_clear_ucode_stations);
 
 /**
  * iwl_restore_stations() - Restore driver known stations to device
@@ -625,7 +620,6 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 	else
 		IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n");
 }
-EXPORT_SYMBOL(iwl_restore_stations);
 
 void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
@@ -668,7 +662,6 @@ void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 			priv->stations[sta_id].sta.sta.addr, ret);
 	iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
 }
-EXPORT_SYMBOL(iwl_reprogram_ap_sta);
 
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
 {
@@ -680,7 +673,6 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
 
 	return WEP_INVALID_OFFSET;
 }
-EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
 
 void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
 {
@@ -700,7 +692,6 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
 	}
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
-EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 static void iwl_dump_lq_cmd(struct iwl_priv *priv,
@@ -810,7 +801,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 	}
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_lq_cmd);
 
 int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
@@ -832,4 +822,3 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 	mutex_unlock(&priv->mutex);
 	return ret;
 }
-EXPORT_SYMBOL(iwl_mac_sta_remove);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 073b6ce..277c917 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -84,7 +84,23 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 	}
 	txq->need_update = 0;
 }
-EXPORT_SYMBOL(iwl_txq_update_write_ptr);
+
+/**
+ * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+
+	if (q->n_bd == 0)
+		return;
+
+	 while (q->write_ptr != q->read_ptr) {
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+}
 
 /**
  * iwl_tx_queue_free - Deallocate DMA queue.
@@ -97,17 +113,10 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr);
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
 {
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
 	struct device *dev = &priv->pci_dev->dev;
 	int i;
 
-	if (q->n_bd == 0)
-		return;
-
-	/* first, empty all BD's */
-	for (; q->write_ptr != q->read_ptr;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
-		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+	iwl_tx_queue_unmap(priv, txq_id);
 
 	/* De-alloc array of command/tx buffers */
 	for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
@@ -131,42 +140,35 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
 	/* 0-fill queue descriptor structure */
 	memset(txq, 0, sizeof(*txq));
 }
-EXPORT_SYMBOL(iwl_tx_queue_free);
 
 /**
- * iwl_cmd_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
+ * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
  */
-void iwl_cmd_queue_free(struct iwl_priv *priv)
+void iwl_cmd_queue_unmap(struct iwl_priv *priv)
 {
 	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
 	struct iwl_queue *q = &txq->q;
-	struct device *dev = &priv->pci_dev->dev;
 	int i;
 	bool huge = false;
 
 	if (q->n_bd == 0)
 		return;
 
-	for (; q->read_ptr != q->write_ptr;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+	while (q->read_ptr != q->write_ptr) {
 		/* we have no way to tell if it is a huge cmd ATM */
 		i = get_cmd_index(q, q->read_ptr, 0);
 
-		if (txq->meta[i].flags & CMD_SIZE_HUGE) {
+		if (txq->meta[i].flags & CMD_SIZE_HUGE)
 			huge = true;
-			continue;
-		}
+		else
+			pci_unmap_single(priv->pci_dev,
+					 dma_unmap_addr(&txq->meta[i], mapping),
+					 dma_unmap_len(&txq->meta[i], len),
+					 PCI_DMA_BIDIRECTIONAL);
 
-		pci_unmap_single(priv->pci_dev,
-				 dma_unmap_addr(&txq->meta[i], mapping),
-				 dma_unmap_len(&txq->meta[i], len),
-				 PCI_DMA_BIDIRECTIONAL);
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
 	}
+
 	if (huge) {
 		i = q->n_window;
 		pci_unmap_single(priv->pci_dev,
@@ -174,6 +176,23 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
 				 dma_unmap_len(&txq->meta[i], len),
 				 PCI_DMA_BIDIRECTIONAL);
 	}
+}
+
+/**
+ * iwl_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void iwl_cmd_queue_free(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	iwl_cmd_queue_unmap(priv);
 
 	/* De-alloc array of command/tx buffers */
 	for (i = 0; i <= TFD_CMD_SLOTS; i++)
@@ -193,7 +212,6 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
 	/* 0-fill queue descriptor structure */
 	memset(txq, 0, sizeof(*txq));
 }
-EXPORT_SYMBOL(iwl_cmd_queue_free);
 
 /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
  * DMA services
@@ -233,7 +251,6 @@ int iwl_queue_space(const struct iwl_queue *q)
 		s = 0;
 	return s;
 }
-EXPORT_SYMBOL(iwl_queue_space);
 
 
 /**
@@ -384,7 +401,6 @@ out_free_arrays:
 
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(iwl_tx_queue_init);
 
 void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 			int slots_num, u32 txq_id)
@@ -404,7 +420,6 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 	/* Tell device where to find queue */
 	priv->cfg->ops->lib->txq_init(priv, txq);
 }
-EXPORT_SYMBOL(iwl_tx_queue_reset);
 
 /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
 
@@ -641,4 +656,3 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 	}
 	meta->flags = 0;
 }
-EXPORT_SYMBOL(iwl_tx_cmd_complete);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
deleted file mode 100644
index 371abbf..0000000
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ /dev/null
@@ -1,4327 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-
-#include <net/ieee80211_radiotap.h>
-#include <net/mac80211.h>
-
-#include <asm/div64.h>
-
-#define DRV_NAME	"iwl3945"
-
-#include "iwl-fh.h"
-#include "iwl-3945-fh.h"
-#include "iwl-commands.h"
-#include "iwl-sta.h"
-#include "iwl-3945.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-dev.h"
-#include "iwl-spectrum.h"
-#include "iwl-legacy.h"
-
-/*
- * module name, copyright, version, etc.
- */
-
-#define DRV_DESCRIPTION	\
-"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define VD "d"
-#else
-#define VD
-#endif
-
-/*
- * add "s" to indicate spectrum measurement included.
- * we add it here to be consistent with previous releases in which
- * this was configurable.
- */
-#define DRV_VERSION  IWLWIFI_VERSION VD "s"
-#define DRV_COPYRIGHT	"Copyright(c) 2003-2010 Intel Corporation"
-#define DRV_AUTHOR     "<ilw@linux.intel.com>"
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-
- /* module parameters */
-struct iwl_mod_params iwl3945_mod_params = {
-	.sw_crypto = 1,
-	.restart_fw = 1,
-	/* the rest are 0 by default */
-};
-
-/**
- * iwl3945_get_antenna_flags - Get antenna flags for RXON command
- * @priv: eeprom and antenna fields are used to determine antenna flags
- *
- * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
- * iwl3945_mod_params.antenna specifies the antenna diversity mode:
- *
- * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
- * IWL_ANTENNA_MAIN      - Force MAIN antenna
- * IWL_ANTENNA_AUX       - Force AUX antenna
- */
-__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-
-	switch (iwl3945_mod_params.antenna) {
-	case IWL_ANTENNA_DIVERSITY:
-		return 0;
-
-	case IWL_ANTENNA_MAIN:
-		if (eeprom->antenna_switch_type)
-			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-
-	case IWL_ANTENNA_AUX:
-		if (eeprom->antenna_switch_type)
-			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-	}
-
-	/* bad antenna selector value */
-	IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
-		iwl3945_mod_params.antenna);
-
-	return 0;		/* "diversity" is default if error */
-}
-
-static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-				   struct ieee80211_key_conf *keyconf,
-				   u8 sta_id)
-{
-	unsigned long flags;
-	__le16 key_flags = 0;
-	int ret;
-
-	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
-	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-
-	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
-		key_flags |= STA_KEY_MULTICAST_MSK;
-
-	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;
-	key_flags &= ~STA_KEY_FLG_INVALID;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-	       keyconf->keylen);
-
-	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-	       keyconf->keylen);
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		priv->stations[sta_id].sta.key.key_offset =
-				 iwl_get_free_ucode_key_index(priv);
-	/* else, we are overriding an existing key => no need to allocated room
-	* in uCode. */
-
-	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	priv->stations[sta_id].sta.key.key_flags = key_flags;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
-	IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n");
-
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return ret;
-}
-
-static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-				  struct ieee80211_key_conf *keyconf,
-				  u8 sta_id)
-{
-	return -EOPNOTSUPP;
-}
-
-static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
-				  struct ieee80211_key_conf *keyconf,
-				  u8 sta_id)
-{
-	return -EOPNOTSUPP;
-}
-
-static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
-{
-	unsigned long flags;
-	struct iwl_addsta_cmd sta_cmd;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
-	memset(&priv->stations[sta_id].sta.key, 0,
-		sizeof(struct iwl4965_keyinfo));
-	priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
-	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
-	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
-			struct ieee80211_key_conf *keyconf, u8 sta_id)
-{
-	int ret = 0;
-
-	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
-
-	switch (keyconf->cipher) {
-	case WLAN_CIPHER_SUITE_CCMP:
-		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	case WLAN_CIPHER_SUITE_TKIP:
-		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	case WLAN_CIPHER_SUITE_WEP40:
-	case WLAN_CIPHER_SUITE_WEP104:
-		ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	default:
-		IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
-			keyconf->cipher);
-		ret = -EINVAL;
-	}
-
-	IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
-		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
-		      sta_id, ret);
-
-	return ret;
-}
-
-static int iwl3945_remove_static_key(struct iwl_priv *priv)
-{
-	int ret = -EOPNOTSUPP;
-
-	return ret;
-}
-
-static int iwl3945_set_static_key(struct iwl_priv *priv,
-				struct ieee80211_key_conf *key)
-{
-	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-	    key->cipher == WLAN_CIPHER_SUITE_WEP104)
-		return -EOPNOTSUPP;
-
-	IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
-	return -EINVAL;
-}
-
-static void iwl3945_clear_free_frames(struct iwl_priv *priv)
-{
-	struct list_head *element;
-
-	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
-		       priv->frames_count);
-
-	while (!list_empty(&priv->free_frames)) {
-		element = priv->free_frames.next;
-		list_del(element);
-		kfree(list_entry(element, struct iwl3945_frame, list));
-		priv->frames_count--;
-	}
-
-	if (priv->frames_count) {
-		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
-			    priv->frames_count);
-		priv->frames_count = 0;
-	}
-}
-
-static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
-{
-	struct iwl3945_frame *frame;
-	struct list_head *element;
-	if (list_empty(&priv->free_frames)) {
-		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
-		if (!frame) {
-			IWL_ERR(priv, "Could not allocate frame!\n");
-			return NULL;
-		}
-
-		priv->frames_count++;
-		return frame;
-	}
-
-	element = priv->free_frames.next;
-	list_del(element);
-	return list_entry(element, struct iwl3945_frame, list);
-}
-
-static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
-{
-	memset(frame, 0, sizeof(*frame));
-	list_add(&frame->list, &priv->free_frames);
-}
-
-unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
-				struct ieee80211_hdr *hdr,
-				int left)
-{
-
-	if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
-		return 0;
-
-	if (priv->beacon_skb->len > left)
-		return 0;
-
-	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
-
-	return priv->beacon_skb->len;
-}
-
-static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
-{
-	struct iwl3945_frame *frame;
-	unsigned int frame_size;
-	int rc;
-	u8 rate;
-
-	frame = iwl3945_get_free_frame(priv);
-
-	if (!frame) {
-		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
-			  "command.\n");
-		return -ENOMEM;
-	}
-
-	rate = iwl_rate_get_lowest_plcp(priv,
-				&priv->contexts[IWL_RXON_CTX_BSS]);
-
-	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
-
-	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-			      &frame->u.cmd[0]);
-
-	iwl3945_free_frame(priv, frame);
-
-	return rc;
-}
-
-static void iwl3945_unset_hw_params(struct iwl_priv *priv)
-{
-	if (priv->_3945.shared_virt)
-		dma_free_coherent(&priv->pci_dev->dev,
-				  sizeof(struct iwl3945_shared),
-				  priv->_3945.shared_virt,
-				  priv->_3945.shared_phys);
-}
-
-static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
-				      struct ieee80211_tx_info *info,
-				      struct iwl_device_cmd *cmd,
-				      struct sk_buff *skb_frag,
-				      int sta_id)
-{
-	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
-
-	tx_cmd->sec_ctl = 0;
-
-	switch (keyinfo->cipher) {
-	case WLAN_CIPHER_SUITE_CCMP:
-		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
-		memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
-		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
-		break;
-
-	case WLAN_CIPHER_SUITE_TKIP:
-		break;
-
-	case WLAN_CIPHER_SUITE_WEP104:
-		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-		/* fall through */
-	case WLAN_CIPHER_SUITE_WEP40:
-		tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
-		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
-
-		memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
-
-		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
-			     "with key %d\n", info->control.hw_key->hw_key_idx);
-		break;
-
-	default:
-		IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
-		break;
-	}
-}
-
-/*
- * handle build REPLY_TX command notification.
- */
-static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
-				  struct iwl_device_cmd *cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr, u8 std_id)
-{
-	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-	__le32 tx_flags = tx_cmd->tx_flags;
-	__le16 fc = hdr->frame_control;
-
-	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-		tx_flags |= TX_CMD_FLG_ACK_MSK;
-		if (ieee80211_is_mgmt(fc))
-			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-		if (ieee80211_is_probe_resp(fc) &&
-		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
-			tx_flags |= TX_CMD_FLG_TSF_MSK;
-	} else {
-		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
-		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-	}
-
-	tx_cmd->sta_id = std_id;
-	if (ieee80211_has_morefrags(fc))
-		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
-
-	if (ieee80211_is_data_qos(fc)) {
-		u8 *qc = ieee80211_get_qos_ctl(hdr);
-		tx_cmd->tid_tspec = qc[0] & 0xf;
-		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-	} else {
-		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-	}
-
-	priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
-
-	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-	if (ieee80211_is_mgmt(fc)) {
-		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
-			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
-		else
-			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
-	} else {
-		tx_cmd->timeout.pm_frame_timeout = 0;
-	}
-
-	tx_cmd->driver_txop = 0;
-	tx_cmd->tx_flags = tx_flags;
-	tx_cmd->next_frame_len = 0;
-}
-
-/*
- * start REPLY_TX command process
- */
-static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct iwl3945_tx_cmd *tx_cmd;
-	struct iwl_tx_queue *txq = NULL;
-	struct iwl_queue *q = NULL;
-	struct iwl_device_cmd *out_cmd;
-	struct iwl_cmd_meta *out_meta;
-	dma_addr_t phys_addr;
-	dma_addr_t txcmd_phys;
-	int txq_id = skb_get_queue_mapping(skb);
-	u16 len, idx, hdr_len;
-	u8 id;
-	u8 unicast;
-	u8 sta_id;
-	u8 tid = 0;
-	__le16 fc;
-	u8 wait_write_ptr = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
-		goto drop_unlock;
-	}
-
-	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
-		IWL_ERR(priv, "ERROR: No TX rate available.\n");
-		goto drop_unlock;
-	}
-
-	unicast = !is_multicast_ether_addr(hdr->addr1);
-	id = 0;
-
-	fc = hdr->frame_control;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (ieee80211_is_auth(fc))
-		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
-	else if (ieee80211_is_assoc_req(fc))
-		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
-	else if (ieee80211_is_reassoc_req(fc))
-		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
-#endif
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	hdr_len = ieee80211_hdrlen(fc);
-
-	/* Find index into station table for destination station */
-	sta_id = iwl_sta_id_or_broadcast(
-			priv, &priv->contexts[IWL_RXON_CTX_BSS],
-			info->control.sta);
-	if (sta_id == IWL_INVALID_STATION) {
-		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-			       hdr->addr1);
-		goto drop;
-	}
-
-	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
-
-	if (ieee80211_is_data_qos(fc)) {
-		u8 *qc = ieee80211_get_qos_ctl(hdr);
-		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-		if (unlikely(tid >= MAX_TID_COUNT))
-			goto drop;
-	}
-
-	/* Descriptor for chosen Tx queue */
-	txq = &priv->txq[txq_id];
-	q = &txq->q;
-
-	if ((iwl_queue_space(q) < q->high_mark))
-		goto drop;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	idx = get_cmd_index(q, q->write_ptr, 0);
-
-	/* Set up driver data for this TFD */
-	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
-	txq->txb[q->write_ptr].skb = skb;
-	txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	/* Init first empty entry in queue's array of Tx/cmd buffers */
-	out_cmd = txq->cmd[idx];
-	out_meta = &txq->meta[idx];
-	tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
-	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-	memset(tx_cmd, 0, sizeof(*tx_cmd));
-
-	/*
-	 * Set up the Tx-command (not MAC!) header.
-	 * Store the chosen Tx queue and TFD index within the sequence field;
-	 * after Tx, uCode's Tx response will return this value so driver can
-	 * locate the frame within the tx queue and do post-tx processing.
-	 */
-	out_cmd->hdr.cmd = REPLY_TX;
-	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-				INDEX_TO_SEQ(q->write_ptr)));
-
-	/* Copy MAC header from skb into command buffer */
-	memcpy(tx_cmd->hdr, hdr, hdr_len);
-
-
-	if (info->control.hw_key)
-		iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
-
-	/* TODO need this for burst mode later on */
-	iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
-
-	/* set is_hcca to 0; it probably will never be implemented */
-	iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
-
-	/* Total # bytes to be transmitted */
-	len = (u16)skb->len;
-	tx_cmd->len = cpu_to_le16(len);
-
-	iwl_dbg_log_tx_data_frame(priv, len, hdr);
-	iwl_update_stats(priv, true, fc, len);
-	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-
-	if (!ieee80211_has_morefrags(hdr->frame_control)) {
-		txq->need_update = 1;
-	} else {
-		wait_write_ptr = 1;
-		txq->need_update = 0;
-	}
-
-	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
-		     le16_to_cpu(out_cmd->hdr.sequence));
-	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-	iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
-	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
-			   ieee80211_hdrlen(fc));
-
-	/*
-	 * Use the first empty entry in this queue's command buffer array
-	 * to contain the Tx command and MAC header concatenated together
-	 * (payload data will be in another buffer).
-	 * Size of this varies, due to varying MAC header length.
-	 * If end is not dword aligned, we'll have 2 extra bytes at the end
-	 * of the MAC header (device reads on dword boundaries).
-	 * We'll tell device about this padding later.
-	 */
-	len = sizeof(struct iwl3945_tx_cmd) +
-			sizeof(struct iwl_cmd_header) + hdr_len;
-	len = (len + 3) & ~3;
-
-	/* Physical address of this Tx command's header (not MAC header!),
-	 * within command buffer array. */
-	txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-				    len, PCI_DMA_TODEVICE);
-	/* we do not map meta data ... so we can safely access address to
-	 * provide to unmap command*/
-	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-	dma_unmap_len_set(out_meta, len, len);
-
-	/* Add buffer containing Tx command and MAC(!) header to TFD's
-	 * first entry */
-	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-						   txcmd_phys, len, 1, 0);
-
-
-	/* Set up TFD's 2nd entry to point directly to remainder of skb,
-	 * if any (802.11 null frames have no payload). */
-	len = skb->len - hdr_len;
-	if (len) {
-		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-					   len, PCI_DMA_TODEVICE);
-		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-							   phys_addr, len,
-							   0, U32_PAD(len));
-	}
-
-
-	/* Tell device the write index *just past* this latest filled TFD */
-	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-	iwl_txq_update_write_ptr(priv, txq);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if ((iwl_queue_space(q) < q->high_mark)
-	    && priv->mac80211_registered) {
-		if (wait_write_ptr) {
-			spin_lock_irqsave(&priv->lock, flags);
-			txq->need_update = 1;
-			iwl_txq_update_write_ptr(priv, txq);
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-
-		iwl_stop_queue(priv, txq);
-	}
-
-	return 0;
-
-drop_unlock:
-	spin_unlock_irqrestore(&priv->lock, flags);
-drop:
-	return -1;
-}
-
-static int iwl3945_get_measurement(struct iwl_priv *priv,
-			       struct ieee80211_measurement_params *params,
-			       u8 type)
-{
-	struct iwl_spectrum_cmd spectrum;
-	struct iwl_rx_packet *pkt;
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
-		.data = (void *)&spectrum,
-		.flags = CMD_WANT_SKB,
-	};
-	u32 add_time = le64_to_cpu(params->start_time);
-	int rc;
-	int spectrum_resp_status;
-	int duration = le16_to_cpu(params->duration);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
-		add_time = iwl_usecs_to_beacons(priv,
-			le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
-			le16_to_cpu(ctx->timing.beacon_interval));
-
-	memset(&spectrum, 0, sizeof(spectrum));
-
-	spectrum.channel_count = cpu_to_le16(1);
-	spectrum.flags =
-	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
-	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
-	cmd.len = sizeof(spectrum);
-	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
-		spectrum.start_time =
-			iwl_add_beacon_time(priv,
-				priv->_3945.last_beacon_time, add_time,
-				le16_to_cpu(ctx->timing.beacon_interval));
-	else
-		spectrum.start_time = 0;
-
-	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
-	spectrum.channels[0].channel = params->channel;
-	spectrum.channels[0].type = type;
-	if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
-		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
-		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
-
-	rc = iwl_send_cmd_sync(priv, &cmd);
-	if (rc)
-		return rc;
-
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
-		rc = -EIO;
-	}
-
-	spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
-	switch (spectrum_resp_status) {
-	case 0:		/* Command will be handled */
-		if (pkt->u.spectrum.id != 0xff) {
-			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
-						pkt->u.spectrum.id);
-			priv->measurement_status &= ~MEASUREMENT_READY;
-		}
-		priv->measurement_status |= MEASUREMENT_ACTIVE;
-		rc = 0;
-		break;
-
-	case 1:		/* Command will not be handled */
-		rc = -EAGAIN;
-		break;
-	}
-
-	iwl_free_pages(priv, cmd.reply_page);
-
-	return rc;
-}
-
-static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
-			       struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_alive_resp *palive;
-	struct delayed_work *pwork;
-
-	palive = &pkt->u.alive_frame;
-
-	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
-		       "0x%01X 0x%01X\n",
-		       palive->is_valid, palive->ver_type,
-		       palive->ver_subtype);
-
-	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
-		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
-		       sizeof(struct iwl_alive_resp));
-		pwork = &priv->init_alive_start;
-	} else {
-		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-		memcpy(&priv->card_alive, &pkt->u.alive_frame,
-		       sizeof(struct iwl_alive_resp));
-		pwork = &priv->alive_start;
-		iwl3945_disable_events(priv);
-	}
-
-	/* We delay the ALIVE response by 5ms to
-	 * give the HW RF Kill time to activate... */
-	if (palive->is_valid == UCODE_VALID_OK)
-		queue_delayed_work(priv->workqueue, pwork,
-				   msecs_to_jiffies(5));
-	else
-		IWL_WARN(priv, "uCode did not respond OK.\n");
-}
-
-static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
-				 struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-#endif
-
-	IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
-}
-
-static void iwl3945_bg_beacon_update(struct work_struct *work)
-{
-	struct iwl_priv *priv =
-		container_of(work, struct iwl_priv, beacon_update);
-	struct sk_buff *beacon;
-
-	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-	beacon = ieee80211_beacon_get(priv->hw,
-			priv->contexts[IWL_RXON_CTX_BSS].vif);
-
-	if (!beacon) {
-		IWL_ERR(priv, "update beacon failed\n");
-		return;
-	}
-
-	mutex_lock(&priv->mutex);
-	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = beacon;
-	mutex_unlock(&priv->mutex);
-
-	iwl3945_send_beacon_cmd(priv);
-}
-
-static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u8 rate = beacon->beacon_notify_hdr.rate;
-
-	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
-		"tsf %d %d rate %d\n",
-		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
-		beacon->beacon_notify_hdr.failure_frame,
-		le32_to_cpu(beacon->ibss_mgr_status),
-		le32_to_cpu(beacon->high_tsf),
-		le32_to_cpu(beacon->low_tsf), rate);
-#endif
-
-	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-
-	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
-	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
-		queue_work(priv->workqueue, &priv->beacon_update);
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-	unsigned long status = priv->status;
-
-	IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
-			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
-
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-	if (flags & HW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-
-	iwl_scan_cancel(priv);
-
-	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     test_bit(STATUS_RF_KILL_HW, &priv->status)))
-		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-				test_bit(STATUS_RF_KILL_HW, &priv->status));
-	else
-		wake_up_interruptible(&priv->wait_command_queue);
-}
-
-/**
- * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
- *
- * Setup the RX handlers for each of the reply types sent from the uCode
- * to the host.
- *
- * This function chains into the hardware specific files for them to setup
- * any hardware specific handlers as well.
- */
-static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
-{
-	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
-	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
-	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
-	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
-	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-			iwl_rx_spectrum_measure_notif;
-	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
-	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-	    iwl_rx_pm_debug_statistics_notif;
-	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
-
-	/*
-	 * The same handler is used for both the REPLY to a discrete
-	 * statistics request from the host as well as for the periodic
-	 * statistics notifications (after received beacons) from the uCode.
-	 */
-	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
-	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
-
-	iwl_setup_rx_scan_handlers(priv);
-	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
-
-	/* Set up hardware specific Rx handlers */
-	iwl3945_hw_rx_handler_setup(priv);
-}
-
-/************************** RX-FUNCTIONS ****************************/
-/*
- * Rx theory of operation
- *
- * The host allocates 32 DMA target addresses and passes the host address
- * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
- * 0 to 31
- *
- * Rx Queue Indexes
- * The host/firmware share two index registers for managing the Rx buffers.
- *
- * The READ index maps to the first position that the firmware may be writing
- * to -- the driver can read up to (but not including) this position and get
- * good data.
- * The READ index is managed by the firmware once the card is enabled.
- *
- * The WRITE index maps to the last position the driver has read from -- the
- * position preceding WRITE is the last slot the firmware can place a packet.
- *
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
- * WRITE = READ.
- *
- * During initialization, the host sets up the READ queue position to the first
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
- *
- * When the firmware places a packet in a buffer, it will advance the READ index
- * and fire the RX interrupt.  The driver can then query the READ index and
- * process as many packets as possible, moving the WRITE index forward as it
- * resets the Rx queue buffers with new memory.
- *
- * The management in the driver is as follows:
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->rxq is replenished and the READ INDEX is updated (updating the
- *   'processed' and 'read' driver indexes as well)
- * + A received packet is processed and handed to the kernel network stack,
- *   detached from the iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
- *   were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
- *                            iwl3945_rx_queue_restock
- * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
- *                            queue, updates firmware pointers, and updates
- *                            the WRITE index.  If insufficient rx_free buffers
- *                            are available, schedules iwl3945_rx_replenish
- *
- * -- enable interrupts --
- * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
- *                            READ INDEX, detaching the SKB from the pool.
- *                            Moves the packet buffer from queue to rx_used.
- *                            Calls iwl3945_rx_queue_restock to refill any empty
- *                            slots.
- * ...
- *
- */
-
-/**
- * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
-					  dma_addr_t dma_addr)
-{
-	return cpu_to_le32((u32)dma_addr);
-}
-
-/**
- * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
- *
- * If there are slots in the RX queue that need to be restocked,
- * and we have free pre-allocated buffers, fill the ranks as much
- * as we can, pulling from rx_free.
- *
- * This moves the 'write' index forward to catch up with 'processed', and
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
-static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct list_head *element;
-	struct iwl_rx_mem_buffer *rxb;
-	unsigned long flags;
-	int write;
-
-	spin_lock_irqsave(&rxq->lock, flags);
-	write = rxq->write & ~0x7;
-	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-		/* Get next free Rx buffer, remove from free list */
-		element = rxq->rx_free.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
-
-		/* Point to Rx buffer via next RBD in circular buffer */
-		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
-		rxq->queue[rxq->write] = rxb;
-		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
-		rxq->free_count--;
-	}
-	spin_unlock_irqrestore(&rxq->lock, flags);
-	/* If the pre-allocated buffer pool is dropping low, schedule to
-	 * refill it */
-	if (rxq->free_count <= RX_LOW_WATERMARK)
-		queue_work(priv->workqueue, &priv->rx_replenish);
-
-
-	/* If we've added more space for the firmware to place data, tell it.
-	 * Increment device's write pointer in multiples of 8. */
-	if ((rxq->write_actual != (rxq->write & ~0x7))
-	    || (abs(rxq->write - rxq->read) > 7)) {
-		spin_lock_irqsave(&rxq->lock, flags);
-		rxq->need_update = 1;
-		spin_unlock_irqrestore(&rxq->lock, flags);
-		iwl_rx_queue_update_write_ptr(priv, rxq);
-	}
-}
-
-/**
- * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free
- *
- * When moving to rx_free an SKB is allocated for the slot.
- *
- * Also restock the Rx queue via iwl3945_rx_queue_restock.
- * This is called as a scheduled work item (except for during initialization)
- */
-static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct list_head *element;
-	struct iwl_rx_mem_buffer *rxb;
-	struct page *page;
-	unsigned long flags;
-	gfp_t gfp_mask = priority;
-
-	while (1) {
-		spin_lock_irqsave(&rxq->lock, flags);
-
-		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
-			return;
-		}
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		if (rxq->free_count > RX_LOW_WATERMARK)
-			gfp_mask |= __GFP_NOWARN;
-
-		if (priv->hw_params.rx_page_order > 0)
-			gfp_mask |= __GFP_COMP;
-
-		/* Alloc a new receive buffer */
-		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
-		if (!page) {
-			if (net_ratelimit())
-				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
-			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-			    net_ratelimit())
-				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
-					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
-					 rxq->free_count);
-			/* We don't reschedule replenish work here -- we will
-			 * call the restock method and if it still needs
-			 * more buffers it will schedule replenish */
-			break;
-		}
-
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
-			__free_pages(page, priv->hw_params.rx_page_order);
-			return;
-		}
-		element = rxq->rx_used.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		rxb->page = page;
-		/* Get physical address of RB/SKB */
-		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-
-		spin_lock_irqsave(&rxq->lock, flags);
-
-		list_add_tail(&rxb->list, &rxq->rx_free);
-		rxq->free_count++;
-		priv->alloc_rxb_page++;
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-	}
-}
-
-void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	unsigned long flags;
-	int i;
-	spin_lock_irqsave(&rxq->lock, flags);
-	INIT_LIST_HEAD(&rxq->rx_free);
-	INIT_LIST_HEAD(&rxq->rx_used);
-	/* Fill the rx_used queue with _all_ of the Rx buffers */
-	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-		/* In the reset function, these buffers may have been allocated
-		 * to an SKB, so we need to unmap and free potential storage */
-		if (rxq->pool[i].page != NULL) {
-			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			__iwl_free_pages(priv, rxq->pool[i].page);
-			rxq->pool[i].page = NULL;
-		}
-		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-	}
-
-	/* Set us so that we have processed and used all buffers, but have
-	 * not restocked the Rx queue with fresh buffers */
-	rxq->read = rxq->write = 0;
-	rxq->write_actual = 0;
-	rxq->free_count = 0;
-	spin_unlock_irqrestore(&rxq->lock, flags);
-}
-
-void iwl3945_rx_replenish(void *data)
-{
-	struct iwl_priv *priv = data;
-	unsigned long flags;
-
-	iwl3945_rx_allocate(priv, GFP_KERNEL);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl3945_rx_queue_restock(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void iwl3945_rx_replenish_now(struct iwl_priv *priv)
-{
-	iwl3945_rx_allocate(priv, GFP_ATOMIC);
-
-	iwl3945_rx_queue_restock(priv);
-}
-
-
-/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have its SKB set to NULL
- * This free routine walks the list of POOL entries and if SKB is set to
- * non NULL it is unmapped and freed
- */
-static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	int i;
-	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
-		if (rxq->pool[i].page != NULL) {
-			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			__iwl_free_pages(priv, rxq->pool[i].page);
-			rxq->pool[i].page = NULL;
-		}
-	}
-
-	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			  rxq->bd_dma);
-	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
-			  rxq->rb_stts, rxq->rb_stts_dma);
-	rxq->bd = NULL;
-	rxq->rb_stts  = NULL;
-}
-
-
-/* Convert linear signal-to-noise ratio into dB */
-static u8 ratio2dB[100] = {
-/*	 0   1   2   3   4   5   6   7   8   9 */
-	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
-	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
-	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
-	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
-	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
-	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
-	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
-	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
-	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
-	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
-};
-
-/* Calculates a relative dB value from a ratio of linear
- *   (i.e. not dB) signal levels.
- * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-int iwl3945_calc_db_from_ratio(int sig_ratio)
-{
-	/* 1000:1 or higher just report as 60 dB */
-	if (sig_ratio >= 1000)
-		return 60;
-
-	/* 100:1 or higher, divide by 10 and use table,
-	 *   add 20 dB to make up for divide by 10 */
-	if (sig_ratio >= 100)
-		return 20 + (int)ratio2dB[sig_ratio/10];
-
-	/* We shouldn't see this */
-	if (sig_ratio < 1)
-		return 0;
-
-	/* Use table for ratios 1:1 - 99:1 */
-	return (int)ratio2dB[sig_ratio];
-}
-
-/**
- * iwl3945_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
- */
-static void iwl3945_rx_handle(struct iwl_priv *priv)
-{
-	struct iwl_rx_mem_buffer *rxb;
-	struct iwl_rx_packet *pkt;
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	u32 r, i;
-	int reclaim;
-	unsigned long flags;
-	u8 fill_rx = 0;
-	u32 count = 8;
-	int total_empty = 0;
-
-	/* uCode's read index (stored in shared DRAM) indicates the last Rx
-	 * buffer that the driver may process (last buffer filled by ucode). */
-	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
-	i = rxq->read;
-
-	/* calculate total frames need to be restock after handling RX */
-	total_empty = r - rxq->write_actual;
-	if (total_empty < 0)
-		total_empty += RX_QUEUE_SIZE;
-
-	if (total_empty > (RX_QUEUE_SIZE / 2))
-		fill_rx = 1;
-	/* Rx interrupt, but nothing sent from uCode */
-	if (i == r)
-		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
-
-	while (i != r) {
-		int len;
-
-		rxb = rxq->queue[i];
-
-		/* If an RXB doesn't have a Rx queue slot associated with it,
-		 * then a bug has been introduced in the queue refilling
-		 * routines -- catch it here */
-		BUG_ON(rxb == NULL);
-
-		rxq->queue[i] = NULL;
-
-		pci_unmap_page(priv->pci_dev, rxb->page_dma,
-			       PAGE_SIZE << priv->hw_params.rx_page_order,
-			       PCI_DMA_FROMDEVICE);
-		pkt = rxb_addr(rxb);
-
-		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-		len += sizeof(u32); /* account for status word */
-		trace_iwlwifi_dev_rx(priv, pkt, len);
-
-		/* Reclaim a command buffer only if this packet is a response
-		 *   to a (driver-originated) command.
-		 * If the packet (e.g. Rx frame) originated from uCode,
-		 *   there is no command buffer to reclaim.
-		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
-		 *   but apparently a few don't get set; catch them here. */
-		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
-			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
-			(pkt->hdr.cmd != REPLY_TX);
-
-		/* Based on type of command response or notification,
-		 *   handle those that need handling via function in
-		 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
-		if (priv->rx_handlers[pkt->hdr.cmd]) {
-			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
-				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
-		} else {
-			/* No handling needed */
-			IWL_DEBUG_RX(priv,
-				"r %d i %d No handler needed for %s, 0x%02x\n",
-				r, i, get_cmd_string(pkt->hdr.cmd),
-				pkt->hdr.cmd);
-		}
-
-		/*
-		 * XXX: After here, we should always check rxb->page
-		 * against NULL before touching it or its virtual
-		 * memory (pkt). Because some rx_handler might have
-		 * already taken or freed the pages.
-		 */
-
-		if (reclaim) {
-			/* Invoke any callbacks, transfer the buffer to caller,
-			 * and fire off the (possibly) blocking iwl_send_cmd()
-			 * as we reclaim the driver command queue */
-			if (rxb->page)
-				iwl_tx_cmd_complete(priv, rxb);
-			else
-				IWL_WARN(priv, "Claim null rxb?\n");
-		}
-
-		/* Reuse the page if possible. For notification packets and
-		 * SKBs that fail to Rx correctly, add them back into the
-		 * rx_free list for reuse later. */
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (rxb->page != NULL) {
-			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
-				0, PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			list_add_tail(&rxb->list, &rxq->rx_free);
-			rxq->free_count++;
-		} else
-			list_add_tail(&rxb->list, &rxq->rx_used);
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		i = (i + 1) & RX_QUEUE_MASK;
-		/* If there are a lot of unused frames,
-		 * restock the Rx queue so ucode won't assert. */
-		if (fill_rx) {
-			count++;
-			if (count >= 8) {
-				rxq->read = i;
-				iwl3945_rx_replenish_now(priv);
-				count = 0;
-			}
-		}
-	}
-
-	/* Backtrack one entry */
-	rxq->read = i;
-	if (fill_rx)
-		iwl3945_rx_replenish_now(priv);
-	else
-		iwl3945_rx_queue_restock(priv);
-}
-
-/* call this function to flush any scheduled tasklet */
-static inline void iwl_synchronize_irq(struct iwl_priv *priv)
-{
-	/* wait to make sure we flush pending tasklet*/
-	synchronize_irq(priv->pci_dev->irq);
-	tasklet_kill(&priv->irq_tasklet);
-}
-
-static const char *desc_lookup(int i)
-{
-	switch (i) {
-	case 1:
-		return "FAIL";
-	case 2:
-		return "BAD_PARAM";
-	case 3:
-		return "BAD_CHECKSUM";
-	case 4:
-		return "NMI_INTERRUPT";
-	case 5:
-		return "SYSASSERT";
-	case 6:
-		return "FATAL_ERROR";
-	}
-
-	return "UNKNOWN";
-}
-
-#define ERROR_START_OFFSET  (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
-
-void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
-{
-	u32 i;
-	u32 desc, time, count, base, data1;
-	u32 blink1, blink2, ilink1, ilink2;
-
-	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
-		return;
-	}
-
-
-	count = iwl_read_targ_mem(priv, base);
-
-	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
-		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
-			priv->status, count);
-	}
-
-	IWL_ERR(priv, "Desc       Time       asrtPC  blink2 "
-		  "ilink1  nmiPC   Line\n");
-	for (i = ERROR_START_OFFSET;
-	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
-	     i += ERROR_ELEM_SIZE) {
-		desc = iwl_read_targ_mem(priv, base + i);
-		time =
-		    iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32));
-		blink1 =
-		    iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32));
-		blink2 =
-		    iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32));
-		ilink1 =
-		    iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32));
-		ilink2 =
-		    iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32));
-		data1 =
-		    iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
-
-		IWL_ERR(priv,
-			"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
-			desc_lookup(desc), desc, time, blink1, blink2,
-			ilink1, ilink2, data1);
-		trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,
-					0, blink1, blink2, ilink1, ilink2);
-	}
-}
-
-#define EVENT_START_OFFSET  (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
-				  u32 num_events, u32 mode,
-				  int pos, char **buf, size_t bufsz)
-{
-	u32 i;
-	u32 base;       /* SRAM byte address of event log header */
-	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
-	u32 ptr;        /* SRAM byte address of log data */
-	u32 ev, time, data; /* event log data */
-	unsigned long reg_flags;
-
-	if (num_events == 0)
-		return pos;
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
-	if (mode == 0)
-		event_size = 2 * sizeof(u32);
-	else
-		event_size = 3 * sizeof(u32);
-
-	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-	/* Make sure device is powered up for SRAM reads */
-	spin_lock_irqsave(&priv->reg_lock, reg_flags);
-	iwl_grab_nic_access(priv);
-
-	/* Set starting address; reads will auto-increment */
-	_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
-
-	/* "time" is actually "data" for mode 0 (no timestamp).
-	 * place event id # at far right for easier visual parsing. */
-	for (i = 0; i < num_events; i++) {
-		ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (mode == 0) {
-			/* data, ev */
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"0x%08x:%04u\n",
-						time, ev);
-			} else {
-				IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
-				trace_iwlwifi_dev_ucode_event(priv, 0,
-							      time, ev);
-			}
-		} else {
-			data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"%010u:0x%08x:%04u\n",
-						 time, data, ev);
-			} else {
-				IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
-					time, data, ev);
-				trace_iwlwifi_dev_ucode_event(priv, time,
-							      data, ev);
-			}
-		}
-	}
-
-	/* Allow device to power down */
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-	return pos;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
-				      u32 num_wraps, u32 next_entry,
-				      u32 size, u32 mode,
-				      int pos, char **buf, size_t bufsz)
-{
-	/*
-	 * display the newest DEFAULT_LOG_ENTRIES entries
-	 * i.e the entries just before the next ont that uCode would fill.
-	 */
-	if (num_wraps) {
-		if (next_entry < size) {
-			pos = iwl3945_print_event_log(priv,
-					     capacity - (size - next_entry),
-					     size - next_entry, mode,
-					     pos, buf, bufsz);
-			pos = iwl3945_print_event_log(priv, 0,
-						      next_entry, mode,
-						      pos, buf, bufsz);
-		} else
-			pos = iwl3945_print_event_log(priv, next_entry - size,
-						      size, mode,
-						      pos, buf, bufsz);
-	} else {
-		if (next_entry < size)
-			pos = iwl3945_print_event_log(priv, 0,
-						      next_entry, mode,
-						      pos, buf, bufsz);
-		else
-			pos = iwl3945_print_event_log(priv, next_entry - size,
-						      size, mode,
-						      pos, buf, bufsz);
-	}
-	return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-			    char **buf, bool display)
-{
-	u32 base;       /* SRAM byte address of event log header */
-	u32 capacity;   /* event log capacity in # entries */
-	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-	u32 num_wraps;  /* # times uCode wrapped to top of log */
-	u32 next_entry; /* index of next entry to be written by uCode */
-	u32 size;       /* # entries that we'll print */
-	int pos = 0;
-	size_t bufsz = 0;
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-		return  -EINVAL;
-	}
-
-	/* event log header */
-	capacity = iwl_read_targ_mem(priv, base);
-	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
-	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
-	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-	if (capacity > priv->cfg->base_params->max_event_log_size) {
-		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-			capacity, priv->cfg->base_params->max_event_log_size);
-		capacity = priv->cfg->base_params->max_event_log_size;
-	}
-
-	if (next_entry > priv->cfg->base_params->max_event_log_size) {
-		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-			next_entry, priv->cfg->base_params->max_event_log_size);
-		next_entry = priv->cfg->base_params->max_event_log_size;
-	}
-
-	size = num_wraps ? capacity : next_entry;
-
-	/* bail out if nothing in log */
-	if (size == 0) {
-		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-		return pos;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
-		size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-			? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-	size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-		? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
-	IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
-		  size);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (display) {
-		if (full_log)
-			bufsz = capacity * 48;
-		else
-			bufsz = size * 48;
-		*buf = kmalloc(bufsz, GFP_KERNEL);
-		if (!*buf)
-			return -ENOMEM;
-	}
-	if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
-		/* if uCode has wrapped back to top of log,
-		 * start at the oldest entry,
-		 * i.e the next one that uCode would fill.
-		 */
-		if (num_wraps)
-			pos = iwl3945_print_event_log(priv, next_entry,
-						capacity - next_entry, mode,
-						pos, buf, bufsz);
-
-		/* (then/else) start at top of log */
-		pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
-					      pos, buf, bufsz);
-	} else
-		pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-						    next_entry, size, mode,
-						    pos, buf, bufsz);
-#else
-	pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-					    next_entry, size, mode,
-					    pos, buf, bufsz);
-#endif
-	return pos;
-}
-
-static void iwl3945_irq_tasklet(struct iwl_priv *priv)
-{
-	u32 inta, handled = 0;
-	u32 inta_fh;
-	unsigned long flags;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u32 inta_mask;
-#endif
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Ack/clear/reset pending uCode interrupts.
-	 * Note:  Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
-	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
-	inta = iwl_read32(priv, CSR_INT);
-	iwl_write32(priv, CSR_INT, inta);
-
-	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
-	 * Any new interrupts that happen after this, either while we're
-	 * in this tasklet, or later, will show up in next ISR/tasklet. */
-	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
-		/* just for debug */
-		inta_mask = iwl_read32(priv, CSR_INT_MASK);
-		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, inta_mask, inta_fh);
-	}
-#endif
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
-	 * atomic, make sure that inta covers all the interrupts that
-	 * we've discovered, even if FH interrupt came in just after
-	 * reading CSR_INT. */
-	if (inta_fh & CSR39_FH_INT_RX_MASK)
-		inta |= CSR_INT_BIT_FH_RX;
-	if (inta_fh & CSR39_FH_INT_TX_MASK)
-		inta |= CSR_INT_BIT_FH_TX;
-
-	/* Now service all interrupt bits discovered above. */
-	if (inta & CSR_INT_BIT_HW_ERR) {
-		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
-
-		/* Tell the device to stop sending interrupts */
-		iwl_disable_interrupts(priv);
-
-		priv->isr_stats.hw++;
-		iwl_irq_handle_error(priv);
-
-		handled |= CSR_INT_BIT_HW_ERR;
-
-		return;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-		/* NIC fires this, but we don't use it, redundant with WAKEUP */
-		if (inta & CSR_INT_BIT_SCD) {
-			IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
-				      "the frame/frames.\n");
-			priv->isr_stats.sch++;
-		}
-
-		/* Alive notification via Rx interrupt will do the real work */
-		if (inta & CSR_INT_BIT_ALIVE) {
-			IWL_DEBUG_ISR(priv, "Alive interrupt\n");
-			priv->isr_stats.alive++;
-		}
-	}
-#endif
-	/* Safely ignore these bits for debug checks below */
-	inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
-
-	/* Error detected by uCode */
-	if (inta & CSR_INT_BIT_SW_ERR) {
-		IWL_ERR(priv, "Microcode SW error detected. "
-			"Restarting 0x%X.\n", inta);
-		priv->isr_stats.sw++;
-		iwl_irq_handle_error(priv);
-		handled |= CSR_INT_BIT_SW_ERR;
-	}
-
-	/* uCode wakes up after power-down sleep */
-	if (inta & CSR_INT_BIT_WAKEUP) {
-		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
-		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
-		iwl_txq_update_write_ptr(priv, &priv->txq[0]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[1]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[2]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[3]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
-
-		priv->isr_stats.wakeup++;
-		handled |= CSR_INT_BIT_WAKEUP;
-	}
-
-	/* All uCode command responses, including Tx command responses,
-	 * Rx "responses" (frame-received notification), and other
-	 * notifications from uCode come through here*/
-	if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
-		iwl3945_rx_handle(priv);
-		priv->isr_stats.rx++;
-		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
-	}
-
-	if (inta & CSR_INT_BIT_FH_TX) {
-		IWL_DEBUG_ISR(priv, "Tx interrupt\n");
-		priv->isr_stats.tx++;
-
-		iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
-		iwl_write_direct32(priv, FH39_TCSR_CREDIT
-					(FH39_SRVC_CHNL), 0x0);
-		handled |= CSR_INT_BIT_FH_TX;
-	}
-
-	if (inta & ~handled) {
-		IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
-		priv->isr_stats.unhandled++;
-	}
-
-	if (inta & ~priv->inta_mask) {
-		IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
-			 inta & ~priv->inta_mask);
-		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
-	}
-
-	/* Re-enable all interrupts */
-	/* only Re-enable if disabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl_enable_interrupts(priv);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-		inta = iwl_read32(priv, CSR_INT);
-		inta_mask = iwl_read32(priv, CSR_INT_MASK);
-		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-		IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
-	}
-#endif
-}
-
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
-					       struct ieee80211_vif *vif,
-					       enum ieee80211_band band,
-					       struct iwl3945_scan_channel *scan_ch)
-{
-	const struct ieee80211_supported_band *sband;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added = 0;
-	u8 channel = 0;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband) {
-		IWL_ERR(priv, "invalid band\n");
-		return added;
-	}
-
-	active_dwell = iwl_get_active_dwell_time(priv, band, 0);
-	passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-
-	channel = iwl_get_single_channel_number(priv, band);
-
-	if (channel) {
-		scan_ch->channel = channel;
-		scan_ch->type = 0;	/* passive */
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* Set txpower levels to defaults */
-		scan_ch->tpc.dsp_atten = 110;
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else
-			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-		added++;
-	} else
-		IWL_ERR(priv, "no valid channel found\n");
-	return added;
-}
-
-static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
-					 enum ieee80211_band band,
-				     u8 is_active, u8 n_probes,
-				     struct iwl3945_scan_channel *scan_ch,
-				     struct ieee80211_vif *vif)
-{
-	struct ieee80211_channel *chan;
-	const struct ieee80211_supported_band *sband;
-	const struct iwl_channel_info *ch_info;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added, i;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband)
-		return 0;
-
-	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
-	passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
-		chan = priv->scan_request->channels[i];
-
-		if (chan->band != band)
-			continue;
-
-		scan_ch->channel = chan->hw_value;
-
-		ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
-				       scan_ch->channel);
-			continue;
-		}
-
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* If passive , set up for auto-switch
-		 *  and use long active_dwell time.
-		 */
-		if (!is_active || is_channel_passive(ch_info) ||
-		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
-			scan_ch->type = 0;	/* passive */
-			if (IWL_UCODE_API(priv->ucode_ver) == 1)
-				scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
-		} else {
-			scan_ch->type = 1;	/* active */
-		}
-
-		/* Set direct probe bits. These may be used both for active
-		 * scan channels (probes gets sent right away),
-		 * or for passive channels (probes get se sent only after
-		 * hearing clear Rx packet).*/
-		if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
-			if (n_probes)
-				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
-		} else {
-			/* uCode v1 does not allow setting direct probe bits on
-			 * passive channel. */
-			if ((scan_ch->type & 1) && n_probes)
-				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
-		}
-
-		/* Set txpower levels to defaults */
-		scan_ch->tpc.dsp_atten = 110;
-		/* scan_pwr_info->tpc.dsp_atten; */
-
-		/*scan_pwr_info->tpc.tx_gain; */
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else {
-			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
-			 * power level:
-			 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
-			 */
-		}
-
-		IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n",
-			       scan_ch->channel,
-			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
-			       (scan_ch->type & 1) ?
-			       active_dwell : passive_dwell);
-
-		scan_ch++;
-		added++;
-	}
-
-	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
-	return added;
-}
-
-static void iwl3945_init_hw_rates(struct iwl_priv *priv,
-			      struct ieee80211_rate *rates)
-{
-	int i;
-
-	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
-		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
-		rates[i].hw_value = i; /* Rate scaling will work on indexes */
-		rates[i].hw_value_short = i;
-		rates[i].flags = 0;
-		if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
-			/*
-			 * If CCK != 1M then set short preamble rate flag.
-			 */
-			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
-				0 : IEEE80211_RATE_SHORT_PREAMBLE;
-		}
-	}
-}
-
-/******************************************************************************
- *
- * uCode download functions
- *
- ******************************************************************************/
-
-static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
-}
-
-/**
- * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
- *     looking at all data.
- */
-static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len)
-{
-	u32 val;
-	u32 save_len = len;
-	int rc = 0;
-	u32 errcnt;
-
-	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-			       IWL39_RTC_INST_LOWER_BOUND);
-
-	errcnt = 0;
-	for (; len > 0; len -= sizeof(u32), image++) {
-		/* read data comes through single port, auto-incr addr */
-		/* NOTE: Use the debugless read so we don't flood kernel log
-		 * if IWL_DL_IO is set */
-		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(priv, "uCode INST section is invalid at "
-				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
-				  save_len - len, val, le32_to_cpu(*image));
-			rc = -EIO;
-			errcnt++;
-			if (errcnt >= 20)
-				break;
-		}
-	}
-
-
-	if (!errcnt)
-		IWL_DEBUG_INFO(priv,
-			"ucode image in INSTRUCTION memory is good\n");
-
-	return rc;
-}
-
-
-/**
- * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
- *   using sample data 100 bytes apart.  If these sample points are good,
- *   it's a pretty good bet that everything between them is good, too.
- */
-static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
-{
-	u32 val;
-	int rc = 0;
-	u32 errcnt = 0;
-	u32 i;
-
-	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-	for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
-		/* read data comes through single port, auto-incr addr */
-		/* NOTE: Use the debugless read so we don't flood kernel log
-		 * if IWL_DL_IO is set */
-		iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-			i + IWL39_RTC_INST_LOWER_BOUND);
-		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (val != le32_to_cpu(*image)) {
-#if 0 /* Enable this if you want to see details */
-			IWL_ERR(priv, "uCode INST section is invalid at "
-				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
-				  i, val, *image);
-#endif
-			rc = -EIO;
-			errcnt++;
-			if (errcnt >= 3)
-				break;
-		}
-	}
-
-	return rc;
-}
-
-
-/**
- * iwl3945_verify_ucode - determine which instruction image is in SRAM,
- *    and verify its contents
- */
-static int iwl3945_verify_ucode(struct iwl_priv *priv)
-{
-	__le32 *image;
-	u32 len;
-	int rc = 0;
-
-	/* Try bootstrap */
-	image = (__le32 *)priv->ucode_boot.v_addr;
-	len = priv->ucode_boot.len;
-	rc = iwl3945_verify_inst_sparse(priv, image, len);
-	if (rc == 0) {
-		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
-		return 0;
-	}
-
-	/* Try initialize */
-	image = (__le32 *)priv->ucode_init.v_addr;
-	len = priv->ucode_init.len;
-	rc = iwl3945_verify_inst_sparse(priv, image, len);
-	if (rc == 0) {
-		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
-		return 0;
-	}
-
-	/* Try runtime/protocol */
-	image = (__le32 *)priv->ucode_code.v_addr;
-	len = priv->ucode_code.len;
-	rc = iwl3945_verify_inst_sparse(priv, image, len);
-	if (rc == 0) {
-		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
-		return 0;
-	}
-
-	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
-
-	/* Since nothing seems to match, show first several data entries in
-	 * instruction SRAM, so maybe visual inspection will give a clue.
-	 * Selection of bootstrap image (vs. other images) is arbitrary. */
-	image = (__le32 *)priv->ucode_boot.v_addr;
-	len = priv->ucode_boot.len;
-	rc = iwl3945_verify_inst_full(priv, image, len);
-
-	return rc;
-}
-
-static void iwl3945_nic_start(struct iwl_priv *priv)
-{
-	/* Remove all resets to allow NIC to operate */
-	iwl_write32(priv, CSR_RESET, 0);
-}
-
-#define IWL3945_UCODE_GET(item)						\
-static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
-{									\
-	return le32_to_cpu(ucode->u.v1.item);				\
-}
-
-static u32 iwl3945_ucode_get_header_size(u32 api_ver)
-{
-	return 24;
-}
-
-static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
-{
-	return (u8 *) ucode->u.v1.data;
-}
-
-IWL3945_UCODE_GET(inst_size);
-IWL3945_UCODE_GET(data_size);
-IWL3945_UCODE_GET(init_size);
-IWL3945_UCODE_GET(init_data_size);
-IWL3945_UCODE_GET(boot_size);
-
-/**
- * iwl3945_read_ucode - Read uCode images from disk file.
- *
- * Copy into buffers for card to fetch via bus-mastering
- */
-static int iwl3945_read_ucode(struct iwl_priv *priv)
-{
-	const struct iwl_ucode_header *ucode;
-	int ret = -EINVAL, index;
-	const struct firmware *ucode_raw;
-	/* firmware file name contains uCode/driver compatibility version */
-	const char *name_pre = priv->cfg->fw_name_pre;
-	const unsigned int api_max = priv->cfg->ucode_api_max;
-	const unsigned int api_min = priv->cfg->ucode_api_min;
-	char buf[25];
-	u8 *src;
-	size_t len;
-	u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
-
-	/* Ask kernel firmware_class module to get the boot firmware off disk.
-	 * request_firmware() is synchronous, file is in memory on return. */
-	for (index = api_max; index >= api_min; index--) {
-		sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
-		ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
-		if (ret < 0) {
-			IWL_ERR(priv, "%s firmware file req failed: %d\n",
-				  buf, ret);
-			if (ret == -ENOENT)
-				continue;
-			else
-				goto error;
-		} else {
-			if (index < api_max)
-				IWL_ERR(priv, "Loaded firmware %s, "
-					"which is deprecated. "
-					" Please use API v%u instead.\n",
-					  buf, api_max);
-			IWL_DEBUG_INFO(priv, "Got firmware '%s' file "
-				       "(%zd bytes) from disk\n",
-				       buf, ucode_raw->size);
-			break;
-		}
-	}
-
-	if (ret < 0)
-		goto error;
-
-	/* Make sure that we got at least our header! */
-	if (ucode_raw->size <  iwl3945_ucode_get_header_size(1)) {
-		IWL_ERR(priv, "File size way too small!\n");
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	/* Data from ucode file:  header followed by uCode images */
-	ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
-	priv->ucode_ver = le32_to_cpu(ucode->ver);
-	api_ver = IWL_UCODE_API(priv->ucode_ver);
-	inst_size = iwl3945_ucode_get_inst_size(ucode);
-	data_size = iwl3945_ucode_get_data_size(ucode);
-	init_size = iwl3945_ucode_get_init_size(ucode);
-	init_data_size = iwl3945_ucode_get_init_data_size(ucode);
-	boot_size = iwl3945_ucode_get_boot_size(ucode);
-	src = iwl3945_ucode_get_data(ucode);
-
-	/* api_ver should match the api version forming part of the
-	 * firmware filename ... but we don't check for that and only rely
-	 * on the API version read from firmware header from here on forward */
-
-	if (api_ver < api_min || api_ver > api_max) {
-		IWL_ERR(priv, "Driver unable to support your firmware API. "
-			  "Driver supports v%u, firmware is v%u.\n",
-			  api_max, api_ver);
-		priv->ucode_ver = 0;
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (api_ver != api_max)
-		IWL_ERR(priv, "Firmware has old API version. Expected %u, "
-			  "got %u. New firmware can be obtained "
-			  "from http://www.intellinuxwireless.org.\n",
-			  api_max, api_ver);
-
-	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
-		IWL_UCODE_MAJOR(priv->ucode_ver),
-		IWL_UCODE_MINOR(priv->ucode_ver),
-		IWL_UCODE_API(priv->ucode_ver),
-		IWL_UCODE_SERIAL(priv->ucode_ver));
-
-	snprintf(priv->hw->wiphy->fw_version,
-		 sizeof(priv->hw->wiphy->fw_version),
-		 "%u.%u.%u.%u",
-		 IWL_UCODE_MAJOR(priv->ucode_ver),
-		 IWL_UCODE_MINOR(priv->ucode_ver),
-		 IWL_UCODE_API(priv->ucode_ver),
-		 IWL_UCODE_SERIAL(priv->ucode_ver));
-
-	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
-		       priv->ucode_ver);
-	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
-		       inst_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
-		       data_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
-		       init_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
-		       init_data_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
-		       boot_size);
-
-
-	/* Verify size of file vs. image size info in file's header */
-	if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
-		inst_size + data_size + init_size +
-		init_data_size + boot_size) {
-
-		IWL_DEBUG_INFO(priv,
-			"uCode file size %zd does not match expected size\n",
-			ucode_raw->size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	/* Verify that uCode images will fit in card's SRAM */
-	if (inst_size > IWL39_MAX_INST_SIZE) {
-		IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
-			       inst_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	if (data_size > IWL39_MAX_DATA_SIZE) {
-		IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
-			       data_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (init_size > IWL39_MAX_INST_SIZE) {
-		IWL_DEBUG_INFO(priv,
-				"uCode init instr len %d too large to fit in\n",
-				init_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (init_data_size > IWL39_MAX_DATA_SIZE) {
-		IWL_DEBUG_INFO(priv,
-				"uCode init data len %d too large to fit in\n",
-				init_data_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (boot_size > IWL39_MAX_BSM_SIZE) {
-		IWL_DEBUG_INFO(priv,
-				"uCode boot instr len %d too large to fit in\n",
-				boot_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	/* Allocate ucode buffers for card's bus-master loading ... */
-
-	/* Runtime instructions and 2 copies of data:
-	 * 1) unmodified from disk
-	 * 2) backup cache for save/restore during power-downs */
-	priv->ucode_code.len = inst_size;
-	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
-
-	priv->ucode_data.len = data_size;
-	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
-
-	priv->ucode_data_backup.len = data_size;
-	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-
-	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-	    !priv->ucode_data_backup.v_addr)
-		goto err_pci_alloc;
-
-	/* Initialization instructions and data */
-	if (init_size && init_data_size) {
-		priv->ucode_init.len = init_size;
-		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
-
-		priv->ucode_init_data.len = init_data_size;
-		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-
-		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
-			goto err_pci_alloc;
-	}
-
-	/* Bootstrap (instructions only, no data) */
-	if (boot_size) {
-		priv->ucode_boot.len = boot_size;
-		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
-
-		if (!priv->ucode_boot.v_addr)
-			goto err_pci_alloc;
-	}
-
-	/* Copy images into buffers for card's bus-master reads ... */
-
-	/* Runtime instructions (first block of data in file) */
-	len = inst_size;
-	IWL_DEBUG_INFO(priv,
-		"Copying (but not loading) uCode instr len %zd\n", len);
-	memcpy(priv->ucode_code.v_addr, src, len);
-	src += len;
-
-	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
-		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
-
-	/* Runtime data (2nd block)
-	 * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
-	len = data_size;
-	IWL_DEBUG_INFO(priv,
-		"Copying (but not loading) uCode data len %zd\n", len);
-	memcpy(priv->ucode_data.v_addr, src, len);
-	memcpy(priv->ucode_data_backup.v_addr, src, len);
-	src += len;
-
-	/* Initialization instructions (3rd block) */
-	if (init_size) {
-		len = init_size;
-		IWL_DEBUG_INFO(priv,
-			"Copying (but not loading) init instr len %zd\n", len);
-		memcpy(priv->ucode_init.v_addr, src, len);
-		src += len;
-	}
-
-	/* Initialization data (4th block) */
-	if (init_data_size) {
-		len = init_data_size;
-		IWL_DEBUG_INFO(priv,
-			"Copying (but not loading) init data len %zd\n", len);
-		memcpy(priv->ucode_init_data.v_addr, src, len);
-		src += len;
-	}
-
-	/* Bootstrap instructions (5th block) */
-	len = boot_size;
-	IWL_DEBUG_INFO(priv,
-		"Copying (but not loading) boot instr len %zd\n", len);
-	memcpy(priv->ucode_boot.v_addr, src, len);
-
-	/* We have our copies now, allow OS release its copies */
-	release_firmware(ucode_raw);
-	return 0;
-
- err_pci_alloc:
-	IWL_ERR(priv, "failed to allocate pci memory\n");
-	ret = -ENOMEM;
-	iwl3945_dealloc_ucode_pci(priv);
-
- err_release:
-	release_firmware(ucode_raw);
-
- error:
-	return ret;
-}
-
-
-/**
- * iwl3945_set_ucode_ptrs - Set uCode address location
- *
- * Tell initialization uCode where to find runtime uCode.
- *
- * BSM registers initially contain pointers to initialization uCode.
- * We need to replace them to load runtime uCode inst and data,
- * and to save runtime data when powering down.
- */
-static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
-{
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-
-	/* bits 31:0 for 3945 */
-	pinst = priv->ucode_code.p_addr;
-	pdata = priv->ucode_data_backup.p_addr;
-
-	/* Tell bootstrap uCode where to find image to load */
-	iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
-	iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-				 priv->ucode_data.len);
-
-	/* Inst byte count must be last to set up, bit 31 signals uCode
-	 *   that all new ptr/size info is in place */
-	iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
-				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
-
-	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
-
-	return 0;
-}
-
-/**
- * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
- */
-static void iwl3945_init_alive_start(struct iwl_priv *priv)
-{
-	/* Check alive response for "valid" sign from uCode */
-	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
-		goto restart;
-	}
-
-	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
-	 * This is a paranoid check, because we would not have gotten the
-	 * "initialize" alive if code weren't properly loaded.  */
-	if (iwl3945_verify_ucode(priv)) {
-		/* Runtime instruction load was bad;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
-		goto restart;
-	}
-
-	/* Send pointers to protocol/runtime uCode image ... init code will
-	 * load and launch runtime uCode, which will send us another "Alive"
-	 * notification. */
-	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-	if (iwl3945_set_ucode_ptrs(priv)) {
-		/* Runtime instruction load won't happen;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
-		goto restart;
-	}
-	return;
-
- restart:
-	queue_work(priv->workqueue, &priv->restart);
-}
-
-/**
- * iwl3945_alive_start - called after REPLY_ALIVE notification received
- *                   from protocol/runtime uCode (initialization uCode's
- *                   Alive gets handled by iwl3945_init_alive_start()).
- */
-static void iwl3945_alive_start(struct iwl_priv *priv)
-{
-	int thermal_spin = 0;
-	u32 rfkill;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-
-	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Alive failed.\n");
-		goto restart;
-	}
-
-	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
-	 * This is a paranoid check, because we would not have gotten the
-	 * "runtime" alive if code weren't properly loaded.  */
-	if (iwl3945_verify_ucode(priv)) {
-		/* Runtime instruction load was bad;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
-		goto restart;
-	}
-
-	rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
-	IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
-
-	if (rfkill & 0x1) {
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-		/* if RFKILL is not on, then wait for thermal
-		 * sensor in adapter to kick in */
-		while (iwl3945_hw_get_temperature(priv) == 0) {
-			thermal_spin++;
-			udelay(10);
-		}
-
-		if (thermal_spin)
-			IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n",
-				       thermal_spin * 10);
-	} else
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-	/* After the ALIVE response, we can send commands to 3945 uCode */
-	set_bit(STATUS_ALIVE, &priv->status);
-
-	/* Enable watchdog to monitor the driver tx queues */
-	iwl_setup_watchdog(priv);
-
-	if (iwl_is_rfkill(priv))
-		return;
-
-	ieee80211_wake_queues(priv->hw);
-
-	priv->active_rate = IWL_RATES_MASK;
-
-	iwl_power_update_mode(priv, true);
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-		struct iwl3945_rxon_cmd *active_rxon =
-				(struct iwl3945_rxon_cmd *)(&ctx->active);
-
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	} else {
-		/* Initialize our rx_config data */
-		iwl_connection_init_rx_config(priv, ctx);
-	}
-
-	/* Configure Bluetooth device coexistence support */
-	priv->cfg->ops->hcmd->send_bt_config(priv);
-
-	/* Configure the adapter for unassociated operation */
-	iwl3945_commit_rxon(priv, ctx);
-
-	iwl3945_reg_txpower_periodic(priv);
-
-	iwl_leds_init(priv);
-
-	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
-	set_bit(STATUS_READY, &priv->status);
-	wake_up_interruptible(&priv->wait_command_queue);
-
-	return;
-
- restart:
-	queue_work(priv->workqueue, &priv->restart);
-}
-
-static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
-
-static void __iwl3945_down(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	int exit_pending;
-
-	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
-	 * to prevent rearm timer */
-	del_timer_sync(&priv->watchdog);
-
-	/* Station information will now be cleared in device */
-	iwl_clear_ucode_stations(priv, NULL);
-	iwl_dealloc_bcast_stations(priv);
-	iwl_clear_driver_stations(priv);
-
-	/* Unblock any waiting calls */
-	wake_up_interruptible_all(&priv->wait_command_queue);
-
-	/* Wipe out the EXIT_PENDING status bit if we are not actually
-	 * exiting the module */
-	if (!exit_pending)
-		clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	/* stop and reset the on-board processor */
-	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-	/* tell the device to stop sending interrupts */
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	iwl_synchronize_irq(priv);
-
-	if (priv->mac80211_registered)
-		ieee80211_stop_queues(priv->hw);
-
-	/* If we have not previously called iwl3945_init() then
-	 * clear all bits but the RF Kill bits and return */
-	if (!iwl_is_init(priv)) {
-		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-					STATUS_RF_KILL_HW |
-			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-					STATUS_GEO_CONFIGURED |
-				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-					STATUS_EXIT_PENDING;
-		goto exit;
-	}
-
-	/* ...otherwise clear out all the status bits but the RF Kill
-	 * bit and continue taking the NIC down. */
-	priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
-				STATUS_RF_KILL_HW |
-			test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
-				STATUS_GEO_CONFIGURED |
-			test_bit(STATUS_FW_ERROR, &priv->status) <<
-				STATUS_FW_ERROR |
-			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-				STATUS_EXIT_PENDING;
-
-	iwl3945_hw_txq_ctx_stop(priv);
-	iwl3945_hw_rxq_stop(priv);
-
-	/* Power-down device's busmaster DMA clocks */
-	iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-	udelay(5);
-
-	/* Stop the device, and put it in low power state */
-	iwl_apm_stop(priv);
-
- exit:
-	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
-
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-	priv->beacon_skb = NULL;
-
-	/* clear out any free frames */
-	iwl3945_clear_free_frames(priv);
-}
-
-static void iwl3945_down(struct iwl_priv *priv)
-{
-	mutex_lock(&priv->mutex);
-	__iwl3945_down(priv);
-	mutex_unlock(&priv->mutex);
-
-	iwl3945_cancel_deferred_work(priv);
-}
-
-#define MAX_HW_RESTARTS 5
-
-static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	unsigned long flags;
-	u8 sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
-	if (sta_id == IWL_INVALID_STATION) {
-		IWL_ERR(priv, "Unable to prepare broadcast station\n");
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-		return -EINVAL;
-	}
-
-	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
-	priv->stations[sta_id].used |= IWL_STA_BCAST;
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return 0;
-}
-
-static int __iwl3945_up(struct iwl_priv *priv)
-{
-	int rc, i;
-
-	rc = iwl3945_alloc_bcast_station(priv);
-	if (rc)
-		return rc;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
-		return -EIO;
-	}
-
-	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-		IWL_ERR(priv, "ucode not available for device bring up\n");
-		return -EIO;
-	}
-
-	/* If platform's RF_KILL switch is NOT set to KILL */
-	if (iwl_read32(priv, CSR_GP_CNTRL) &
-				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-	else {
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-		return -ENODEV;
-	}
-
-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-	rc = iwl3945_hw_nic_init(priv);
-	if (rc) {
-		IWL_ERR(priv, "Unable to int nic\n");
-		return rc;
-	}
-
-	/* make sure rfkill handshake bits are cleared */
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-	/* clear (again), then enable host interrupts */
-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-	iwl_enable_interrupts(priv);
-
-	/* really make sure rfkill handshake bits are cleared */
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-	/* Copy original ucode data image from disk into backup cache.
-	 * This will be used to initialize the on-board processor's
-	 * data SRAM for a clean start when the runtime program first loads. */
-	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
-	       priv->ucode_data.len);
-
-	/* We return success when we resume from suspend and rf_kill is on. */
-	if (test_bit(STATUS_RF_KILL_HW, &priv->status))
-		return 0;
-
-	for (i = 0; i < MAX_HW_RESTARTS; i++) {
-
-		/* load bootstrap state machine,
-		 * load bootstrap program into processor's memory,
-		 * prepare to load the "initialize" uCode */
-		rc = priv->cfg->ops->lib->load_ucode(priv);
-
-		if (rc) {
-			IWL_ERR(priv,
-				"Unable to set up bootstrap uCode: %d\n", rc);
-			continue;
-		}
-
-		/* start card; "initialize" will load runtime ucode */
-		iwl3945_nic_start(priv);
-
-		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
-
-		return 0;
-	}
-
-	set_bit(STATUS_EXIT_PENDING, &priv->status);
-	__iwl3945_down(priv);
-	clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	/* tried to restart and config the device for as long as our
-	 * patience could withstand */
-	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
-	return -EIO;
-}
-
-
-/*****************************************************************************
- *
- * Workqueue callbacks
- *
- *****************************************************************************/
-
-static void iwl3945_bg_init_alive_start(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, init_alive_start.work);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_init_alive_start(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-static void iwl3945_bg_alive_start(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, alive_start.work);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_alive_start(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-/*
- * 3945 cannot interrupt driver when hardware rf kill switch toggles;
- * driver must poll CSR_GP_CNTRL_REG register for change.  This register
- * *is* readable even when device has been SW_RESET into low power mode
- * (e.g. during RF KILL).
- */
-static void iwl3945_rfkill_poll(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
-	bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
-	bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
-			& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
-
-	if (new_rfkill != old_rfkill) {
-		if (new_rfkill)
-			set_bit(STATUS_RF_KILL_HW, &priv->status);
-		else
-			clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-		wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill);
-
-		IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
-				new_rfkill ? "disable radio" : "enable radio");
-	}
-
-	/* Keep this running, even if radio now enabled.  This will be
-	 * cancelled in mac_start() if system decides to start again */
-	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-			   round_jiffies_relative(2 * HZ));
-
-}
-
-int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_SCAN_CMD,
-		.len = sizeof(struct iwl3945_scan_cmd),
-		.flags = CMD_SIZE_HUGE,
-	};
-	struct iwl3945_scan_cmd *scan;
-	u8 n_probes = 0;
-	enum ieee80211_band band;
-	bool is_active = false;
-	int ret;
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (!priv->scan_cmd) {
-		priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
-					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-		if (!priv->scan_cmd) {
-			IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
-			return -ENOMEM;
-		}
-	}
-	scan = priv->scan_cmd;
-	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
-
-	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-		u16 interval = 0;
-		u32 extra;
-		u32 suspend_time = 100;
-		u32 scan_suspend_time = 100;
-		unsigned long flags;
-
-		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-
-		spin_lock_irqsave(&priv->lock, flags);
-		if (priv->is_internal_short_scan)
-			interval = 0;
-		else
-			interval = vif->bss_conf.beacon_int;
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		scan->suspend_time = 0;
-		scan->max_out_time = cpu_to_le32(200 * 1024);
-		if (!interval)
-			interval = suspend_time;
-		/*
-		 * suspend time format:
-		 *  0-19: beacon interval in usec (time before exec.)
-		 * 20-23: 0
-		 * 24-31: number of beacons (suspend between channels)
-		 */
-
-		extra = (suspend_time / interval) << 24;
-		scan_suspend_time = 0xFF0FFFFF &
-		    (extra | ((suspend_time % interval) * 1024));
-
-		scan->suspend_time = cpu_to_le32(scan_suspend_time);
-		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
-			       scan_suspend_time, interval);
-	}
-
-	if (priv->is_internal_short_scan) {
-		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else if (priv->scan_request->n_ssids) {
-		int i, p = 0;
-		IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
-		for (i = 0; i < priv->scan_request->n_ssids; i++) {
-			/* always does wildcard anyway */
-			if (!priv->scan_request->ssids[i].ssid_len)
-				continue;
-			scan->direct_scan[p].id = WLAN_EID_SSID;
-			scan->direct_scan[p].len =
-				priv->scan_request->ssids[i].ssid_len;
-			memcpy(scan->direct_scan[p].ssid,
-			       priv->scan_request->ssids[i].ssid,
-			       priv->scan_request->ssids[i].ssid_len);
-			n_probes++;
-			p++;
-		}
-		is_active = true;
-	} else
-		IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n");
-
-	/* We don't build a direct scan probe request; the uCode will do
-	 * that based on the direct_mask added to each channel entry */
-	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-	scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-	/* flags + rate selection */
-
-	switch (priv->scan_band) {
-	case IEEE80211_BAND_2GHZ:
-		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
-		band = IEEE80211_BAND_2GHZ;
-		break;
-	case IEEE80211_BAND_5GHZ:
-		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-		band = IEEE80211_BAND_5GHZ;
-		break;
-	default:
-		IWL_WARN(priv, "Invalid scan band\n");
-		return -EIO;
-	}
-
-	/*
-	 * If active scaning is requested but a certain channel
-	 * is marked passive, we can do active scanning if we
-	 * detect transmissions.
-	 */
-	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
-					IWL_GOOD_CRC_TH_DISABLED;
-
-	if (!priv->is_internal_short_scan) {
-		scan->tx_cmd.len = cpu_to_le16(
-			iwl_fill_probe_req(priv,
-				(struct ieee80211_mgmt *)scan->data,
-				vif->addr,
-				priv->scan_request->ie,
-				priv->scan_request->ie_len,
-				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-	} else {
-		/* use bcast addr, will not be transmitted but must be valid */
-		scan->tx_cmd.len = cpu_to_le16(
-			iwl_fill_probe_req(priv,
-				(struct ieee80211_mgmt *)scan->data,
-				iwl_bcast_addr, NULL, 0,
-				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-	}
-	/* select Rx antennas */
-	scan->flags |= iwl3945_get_antenna_flags(priv);
-
-	if (priv->is_internal_short_scan) {
-		scan->channel_count =
-			iwl3945_get_single_channel_for_scan(priv, vif, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
-		scan->channel_count =
-			iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
-	}
-
-	if (scan->channel_count == 0) {
-		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-		return -EIO;
-	}
-
-	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
-	    scan->channel_count * sizeof(struct iwl3945_scan_channel);
-	cmd.data = scan;
-	scan->len = cpu_to_le16(cmd.len);
-
-	set_bit(STATUS_SCAN_HW, &priv->status);
-	ret = iwl_send_cmd_sync(priv, &cmd);
-	if (ret)
-		clear_bit(STATUS_SCAN_HW, &priv->status);
-	return ret;
-}
-
-void iwl3945_post_scan(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-		iwl3945_commit_rxon(priv, ctx);
-}
-
-static void iwl3945_bg_restart(struct work_struct *data)
-{
-	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
-		struct iwl_rxon_context *ctx;
-		mutex_lock(&priv->mutex);
-		for_each_context(priv, ctx)
-			ctx->vif = NULL;
-		priv->is_open = 0;
-		mutex_unlock(&priv->mutex);
-		iwl3945_down(priv);
-		ieee80211_restart_hw(priv->hw);
-	} else {
-		iwl3945_down(priv);
-
-		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-			return;
-
-		mutex_lock(&priv->mutex);
-		__iwl3945_up(priv);
-		mutex_unlock(&priv->mutex);
-	}
-}
-
-static void iwl3945_bg_rx_replenish(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, rx_replenish);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_rx_replenish(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-void iwl3945_post_associate(struct iwl_priv *priv)
-{
-	int rc = 0;
-	struct ieee80211_conf *conf = NULL;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (!ctx->vif || !priv->is_open)
-		return;
-
-	if (ctx->vif->type == NL80211_IFTYPE_AP) {
-		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
-		return;
-	}
-
-	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl3945_commit_rxon(priv, ctx);
-
-	rc = iwl_send_rxon_timing(priv, ctx);
-	if (rc)
-		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
-			    "Attempting to continue.\n");
-
-	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-	ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
-
-	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
-
-	if (ctx->vif->bss_conf.use_short_preamble)
-		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-	else
-		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (ctx->vif->bss_conf.use_short_slot)
-			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-	}
-
-	iwl3945_commit_rxon(priv, ctx);
-
-	switch (ctx->vif->type) {
-	case NL80211_IFTYPE_STATION:
-		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		iwl3945_send_beacon_cmd(priv);
-		break;
-	default:
-		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			__func__, ctx->vif->type);
-		break;
-	}
-}
-
-/*****************************************************************************
- *
- * mac80211 entry point functions
- *
- *****************************************************************************/
-
-#define UCODE_READY_TIMEOUT	(2 * HZ)
-
-static int iwl3945_mac_start(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-	int ret;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	/* we should be verifying the device is ready to be opened */
-	mutex_lock(&priv->mutex);
-
-	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
-	 * ucode filename and max sizes are card-specific. */
-
-	if (!priv->ucode_code.len) {
-		ret = iwl3945_read_ucode(priv);
-		if (ret) {
-			IWL_ERR(priv, "Could not read microcode: %d\n", ret);
-			mutex_unlock(&priv->mutex);
-			goto out_release_irq;
-		}
-	}
-
-	ret = __iwl3945_up(priv);
-
-	mutex_unlock(&priv->mutex);
-
-	if (ret)
-		goto out_release_irq;
-
-	IWL_DEBUG_INFO(priv, "Start UP work.\n");
-
-	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
-	 * mac80211 will not be run successfully. */
-	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-			test_bit(STATUS_READY, &priv->status),
-			UCODE_READY_TIMEOUT);
-	if (!ret) {
-		if (!test_bit(STATUS_READY, &priv->status)) {
-			IWL_ERR(priv,
-				"Wait for START_ALIVE timeout after %dms.\n",
-				jiffies_to_msecs(UCODE_READY_TIMEOUT));
-			ret = -ETIMEDOUT;
-			goto out_release_irq;
-		}
-	}
-
-	/* ucode is running and will send rfkill notifications,
-	 * no need to poll the killswitch state anymore */
-	cancel_delayed_work(&priv->_3945.rfkill_poll);
-
-	iwl_led_start(priv);
-
-	priv->is_open = 1;
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
-
-out_release_irq:
-	priv->is_open = 0;
-	IWL_DEBUG_MAC80211(priv, "leave - failed\n");
-	return ret;
-}
-
-static void iwl3945_mac_stop(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!priv->is_open) {
-		IWL_DEBUG_MAC80211(priv, "leave - skip\n");
-		return;
-	}
-
-	priv->is_open = 0;
-
-	iwl3945_down(priv);
-
-	flush_workqueue(priv->workqueue);
-
-	/* start polling the killswitch state again */
-	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-			   round_jiffies_relative(2 * HZ));
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
-
-	if (iwl3945_tx_skb(priv, skb))
-		dev_kfree_skb_any(skb);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return NETDEV_TX_OK;
-}
-
-void iwl3945_config_ap(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_vif *vif = ctx->vif;
-	int rc = 0;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* The following should be done only at AP bring up */
-	if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) {
-
-		/* RXON - unassoc (to set timing command) */
-		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv, ctx);
-
-		/* RXON Timing */
-		rc = iwl_send_rxon_timing(priv, ctx);
-		if (rc)
-			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
-					"Attempting to continue.\n");
-
-		ctx->staging.assoc_id = 0;
-
-		if (vif->bss_conf.use_short_preamble)
-			ctx->staging.flags |=
-				RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-			if (vif->bss_conf.use_short_slot)
-				ctx->staging.flags |=
-					RXON_FLG_SHORT_SLOT_MSK;
-			else
-				ctx->staging.flags &=
-					~RXON_FLG_SHORT_SLOT_MSK;
-		}
-		/* restore RXON assoc */
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv, ctx);
-	}
-	iwl3945_send_beacon_cmd(priv);
-
-	/* FIXME - we need to add code here to detect a totally new
-	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-	 * clear sta table, add BCAST sta... */
-}
-
-static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-			       struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta,
-			       struct ieee80211_key_conf *key)
-{
-	struct iwl_priv *priv = hw->priv;
-	int ret = 0;
-	u8 sta_id = IWL_INVALID_STATION;
-	u8 static_key;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (iwl3945_mod_params.sw_crypto) {
-		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
-		return -EOPNOTSUPP;
-	}
-
-	static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS);
-
-	if (!static_key) {
-		sta_id = iwl_sta_id_or_broadcast(
-				priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
-		if (sta_id == IWL_INVALID_STATION)
-			return -EINVAL;
-	}
-
-	mutex_lock(&priv->mutex);
-	iwl_scan_cancel_timeout(priv, 100);
-
-	switch (cmd) {
-	case SET_KEY:
-		if (static_key)
-			ret = iwl3945_set_static_key(priv, key);
-		else
-			ret = iwl3945_set_dynamic_key(priv, key, sta_id);
-		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
-		break;
-	case DISABLE_KEY:
-		if (static_key)
-			ret = iwl3945_remove_static_key(priv);
-		else
-			ret = iwl3945_clear_sta_key_info(priv, sta_id);
-		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	mutex_unlock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return ret;
-}
-
-static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
-	int ret;
-	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
-	u8 sta_id;
-
-	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
-			sta->addr);
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
-			sta->addr);
-	sta_priv->common.sta_id = IWL_INVALID_STATION;
-
-
-	ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS],
-				     sta->addr, is_ap, sta, &sta_id);
-	if (ret) {
-		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
-			sta->addr, ret);
-		/* Should we return success if return code is EEXIST ? */
-		mutex_unlock(&priv->mutex);
-		return ret;
-	}
-
-	sta_priv->common.sta_id = sta_id;
-
-	/* Initialize rate scaling */
-	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
-		       sta->addr);
-	iwl3945_rs_rate_init(priv, sta, sta_id);
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-
-static void iwl3945_configure_filter(struct ieee80211_hw *hw,
-				     unsigned int changed_flags,
-				     unsigned int *total_flags,
-				     u64 multicast)
-{
-	struct iwl_priv *priv = hw->priv;
-	__le32 filter_or = 0, filter_nand = 0;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-#define CHK(test, flag)	do { \
-	if (*total_flags & (test))		\
-		filter_or |= (flag);		\
-	else					\
-		filter_nand |= (flag);		\
-	} while (0)
-
-	IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
-			changed_flags, *total_flags);
-
-	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
-	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
-
-#undef CHK
-
-	mutex_lock(&priv->mutex);
-
-	ctx->staging.filter_flags &= ~filter_nand;
-	ctx->staging.filter_flags |= filter_or;
-
-	/*
-	 * Not committing directly because hardware can perform a scan,
-	 * but even if hw is ready, committing here breaks for some reason,
-	 * we'll eventually commit the filter flags change anyway.
-	 */
-
-	mutex_unlock(&priv->mutex);
-
-	/*
-	 * Receiving all multicast frames is always enabled by the
-	 * default flags setup in iwl_connection_init_rx_config()
-	 * since we currently do not support programming multicast
-	 * filters into the device.
-	 */
-	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
-			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
-}
-
-
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
-}
-static ssize_t store_debug_level(struct device *d,
-				struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	unsigned long val;
-	int ret;
-
-	ret = strict_strtoul(buf, 0, &val);
-	if (ret)
-		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
-	else {
-		priv->debug_level = val;
-		if (iwl_alloc_traffic_mem(priv))
-			IWL_ERR(priv,
-				"Not enough memory to generate traffic log\n");
-	}
-	return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-			show_debug_level, store_debug_level);
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-static ssize_t show_temperature(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
-			     struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
-			      struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	char *p = (char *)buf;
-	u32 val;
-
-	val = simple_strtoul(p, &p, 10);
-	if (p == buf)
-		IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
-	else
-		iwl3945_hw_reg_set_txpower(priv, val);
-
-	return count;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static ssize_t show_flags(struct device *d,
-			  struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	return sprintf(buf, "0x%04X\n", ctx->active.flags);
-}
-
-static ssize_t store_flags(struct device *d,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	u32 flags = simple_strtoul(buf, NULL, 0);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	mutex_lock(&priv->mutex);
-	if (le32_to_cpu(ctx->staging.flags) != flags) {
-		/* Cancel any currently running scans... */
-		if (iwl_scan_cancel_timeout(priv, 100))
-			IWL_WARN(priv, "Could not cancel scan.\n");
-		else {
-			IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
-				       flags);
-			ctx->staging.flags = cpu_to_le32(flags);
-			iwl3945_commit_rxon(priv, ctx);
-		}
-	}
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
-
-static ssize_t show_filter_flags(struct device *d,
-				 struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	return sprintf(buf, "0x%04X\n",
-		le32_to_cpu(ctx->active.filter_flags));
-}
-
-static ssize_t store_filter_flags(struct device *d,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	u32 filter_flags = simple_strtoul(buf, NULL, 0);
-
-	mutex_lock(&priv->mutex);
-	if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
-		/* Cancel any currently running scans... */
-		if (iwl_scan_cancel_timeout(priv, 100))
-			IWL_WARN(priv, "Could not cancel scan.\n");
-		else {
-			IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
-				       "0x%04X\n", filter_flags);
-			ctx->staging.filter_flags =
-				cpu_to_le32(filter_flags);
-			iwl3945_commit_rxon(priv, ctx);
-		}
-	}
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
-		   store_filter_flags);
-
-static ssize_t show_measurement(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_spectrum_notification measure_report;
-	u32 size = sizeof(measure_report), len = 0, ofs = 0;
-	u8 *data = (u8 *)&measure_report;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (!(priv->measurement_status & MEASUREMENT_READY)) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return 0;
-	}
-	memcpy(&measure_report, &priv->measure_report, size);
-	priv->measurement_status = 0;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	while (size && (PAGE_SIZE - len)) {
-		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-				   PAGE_SIZE - len, 1);
-		len = strlen(buf);
-		if (PAGE_SIZE - len)
-			buf[len++] = '\n';
-
-		ofs += 16;
-		size -= min(size, 16U);
-	}
-
-	return len;
-}
-
-static ssize_t store_measurement(struct device *d,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_measurement_params params = {
-		.channel = le16_to_cpu(ctx->active.channel),
-		.start_time = cpu_to_le64(priv->_3945.last_tsf),
-		.duration = cpu_to_le16(1),
-	};
-	u8 type = IWL_MEASURE_BASIC;
-	u8 buffer[32];
-	u8 channel;
-
-	if (count) {
-		char *p = buffer;
-		strncpy(buffer, buf, min(sizeof(buffer), count));
-		channel = simple_strtoul(p, NULL, 0);
-		if (channel)
-			params.channel = channel;
-
-		p = buffer;
-		while (*p && *p != ' ')
-			p++;
-		if (*p)
-			type = simple_strtoul(p + 1, NULL, 0);
-	}
-
-	IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on "
-		       "channel %d (for '%s')\n", type, params.channel, buf);
-	iwl3945_get_measurement(priv, &params, type);
-
-	return count;
-}
-
-static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
-		   show_measurement, store_measurement);
-
-static ssize_t store_retry_rate(struct device *d,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-
-	priv->retry_rate = simple_strtoul(buf, NULL, 0);
-	if (priv->retry_rate <= 0)
-		priv->retry_rate = 1;
-
-	return count;
-}
-
-static ssize_t show_retry_rate(struct device *d,
-			       struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "%d", priv->retry_rate);
-}
-
-static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
-		   store_retry_rate);
-
-
-static ssize_t show_channels(struct device *d,
-			     struct device_attribute *attr, char *buf)
-{
-	/* all this shit doesn't belong into sysfs anyway */
-	return 0;
-}
-
-static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
-
-static ssize_t show_antenna(struct device *d,
-			    struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
-}
-
-static ssize_t store_antenna(struct device *d,
-			     struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d);
-	int ant;
-
-	if (count == 0)
-		return 0;
-
-	if (sscanf(buf, "%1i", &ant) != 1) {
-		IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n");
-		return count;
-	}
-
-	if ((ant >= 0) && (ant <= 2)) {
-		IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant);
-		iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
-	} else
-		IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant);
-
-
-	return count;
-}
-
-static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
-
-static ssize_t show_status(struct device *d,
-			   struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-	return sprintf(buf, "0x%08x\n", (int)priv->status);
-}
-
-static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
-
-static ssize_t dump_error_log(struct device *d,
-			      struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	char *p = (char *)buf;
-
-	if (p[0] == '1')
-		iwl3945_dump_nic_error_log(priv);
-
-	return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
-
-/*****************************************************************************
- *
- * driver setup and tear down
- *
- *****************************************************************************/
-
-static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
-{
-	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
-
-	init_waitqueue_head(&priv->wait_command_queue);
-
-	INIT_WORK(&priv->restart, iwl3945_bg_restart);
-	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-	INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
-	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
-	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
-	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
-
-	iwl_setup_scan_deferred_work(priv);
-
-	iwl3945_hw_setup_deferred_work(priv);
-
-	init_timer(&priv->watchdog);
-	priv->watchdog.data = (unsigned long)priv;
-	priv->watchdog.function = iwl_bg_watchdog;
-
-	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-		     iwl3945_irq_tasklet, (unsigned long)priv);
-}
-
-static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
-{
-	iwl3945_hw_cancel_deferred_work(priv);
-
-	cancel_delayed_work_sync(&priv->init_alive_start);
-	cancel_delayed_work(&priv->alive_start);
-	cancel_work_sync(&priv->beacon_update);
-
-	iwl_cancel_scan_deferred_work(priv);
-}
-
-static struct attribute *iwl3945_sysfs_entries[] = {
-	&dev_attr_antenna.attr,
-	&dev_attr_channels.attr,
-	&dev_attr_dump_errors.attr,
-	&dev_attr_flags.attr,
-	&dev_attr_filter_flags.attr,
-	&dev_attr_measurement.attr,
-	&dev_attr_retry_rate.attr,
-	&dev_attr_status.attr,
-	&dev_attr_temperature.attr,
-	&dev_attr_tx_power.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
-	&dev_attr_debug_level.attr,
-#endif
-	NULL
-};
-
-static struct attribute_group iwl3945_attribute_group = {
-	.name = NULL,		/* put in device directory */
-	.attrs = iwl3945_sysfs_entries,
-};
-
-struct ieee80211_ops iwl3945_hw_ops = {
-	.tx = iwl3945_mac_tx,
-	.start = iwl3945_mac_start,
-	.stop = iwl3945_mac_stop,
-	.add_interface = iwl_mac_add_interface,
-	.remove_interface = iwl_mac_remove_interface,
-	.change_interface = iwl_mac_change_interface,
-	.config = iwl_legacy_mac_config,
-	.configure_filter = iwl3945_configure_filter,
-	.set_key = iwl3945_mac_set_key,
-	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_legacy_mac_reset_tsf,
-	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
-	.hw_scan = iwl_mac_hw_scan,
-	.sta_add = iwl3945_mac_sta_add,
-	.sta_remove = iwl_mac_sta_remove,
-	.tx_last_beacon = iwl_mac_tx_last_beacon,
-};
-
-static int iwl3945_init_drv(struct iwl_priv *priv)
-{
-	int ret;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-
-	priv->retry_rate = 1;
-	priv->beacon_skb = NULL;
-
-	spin_lock_init(&priv->sta_lock);
-	spin_lock_init(&priv->hcmd_lock);
-
-	INIT_LIST_HEAD(&priv->free_frames);
-
-	mutex_init(&priv->mutex);
-	mutex_init(&priv->sync_cmd_mutex);
-
-	priv->ieee_channels = NULL;
-	priv->ieee_rates = NULL;
-	priv->band = IEEE80211_BAND_2GHZ;
-
-	priv->iw_mode = NL80211_IFTYPE_STATION;
-	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-
-	/* initialize force reset */
-	priv->force_reset[IWL_RF_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_RF_RESET;
-	priv->force_reset[IWL_FW_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
-
-
-	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
-	priv->tx_power_next = IWL_DEFAULT_TX_POWER;
-
-	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
-		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
-			 eeprom->version);
-		ret = -EINVAL;
-		goto err;
-	}
-	ret = iwl_init_channel_map(priv);
-	if (ret) {
-		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
-		goto err;
-	}
-
-	/* Set up txpower settings in driver for all channels */
-	if (iwl3945_txpower_set_from_eeprom(priv)) {
-		ret = -EIO;
-		goto err_free_channel_map;
-	}
-
-	ret = iwlcore_init_geos(priv);
-	if (ret) {
-		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
-		goto err_free_channel_map;
-	}
-	iwl3945_init_hw_rates(priv, priv->ieee_rates);
-
-	return 0;
-
-err_free_channel_map:
-	iwl_free_channel_map(priv);
-err:
-	return ret;
-}
-
-#define IWL3945_MAX_PROBE_REQUEST	200
-
-static int iwl3945_setup_mac(struct iwl_priv *priv)
-{
-	int ret;
-	struct ieee80211_hw *hw = priv->hw;
-
-	hw->rate_control_algorithm = "iwl-3945-rs";
-	hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
-	hw->vif_data_size = sizeof(struct iwl_vif_priv);
-
-	/* Tell mac80211 our characteristics */
-	hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_SPECTRUM_MGMT;
-
-	if (!priv->cfg->base_params->broken_powersave)
-		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
-			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
-
-	hw->wiphy->interface_modes =
-		priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
-
-	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
-
-	hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
-	/* we create the 802.11 header and a zero-length SSID element */
-	hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
-
-	/* Default value; 4 EDCA QOS priorities */
-	hw->queues = 4;
-
-	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-			&priv->bands[IEEE80211_BAND_2GHZ];
-
-	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-			&priv->bands[IEEE80211_BAND_5GHZ];
-
-	ret = ieee80211_register_hw(priv->hw);
-	if (ret) {
-		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
-		return ret;
-	}
-	priv->mac80211_registered = 1;
-
-	return 0;
-}
-
-static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int err = 0, i;
-	struct iwl_priv *priv;
-	struct ieee80211_hw *hw;
-	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-	struct iwl3945_eeprom *eeprom;
-	unsigned long flags;
-
-	/***********************
-	 * 1. Allocating HW data
-	 * ********************/
-
-	/* mac80211 allocates memory for this device instance, including
-	 *   space for this driver's private structure */
-	hw = iwl_alloc_all(cfg);
-	if (hw == NULL) {
-		pr_err("Can not allocate network device\n");
-		err = -ENOMEM;
-		goto out;
-	}
-	priv = hw->priv;
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-
-	priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
-
-	/* 3945 has only one valid context */
-	priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
-
-	for (i = 0; i < NUM_IWL_RXON_CTX; i++)
-		priv->contexts[i].ctxid = i;
-
-	priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
-	priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
-	priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
-	priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
-	priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
-	priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
-	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
-	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
-	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
-	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
-
-	/*
-	 * Disabling hardware scan means that mac80211 will perform scans
-	 * "the hard way", rather than using device's scan.
-	 */
-	if (iwl3945_mod_params.disable_hw_scan) {
-		dev_printk(KERN_DEBUG, &(pdev->dev),
-			"sw scan support is deprecated\n");
-		iwl3945_hw_ops.hw_scan = NULL;
-	}
-
-
-	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
-	priv->cfg = cfg;
-	priv->pci_dev = pdev;
-	priv->inta_mask = CSR_INI_SET_MASK;
-
-	if (iwl_alloc_traffic_mem(priv))
-		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
-
-	/***************************
-	 * 2. Initializing PCI bus
-	 * *************************/
-	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-				PCIE_LINK_STATE_CLKPM);
-
-	if (pci_enable_device(pdev)) {
-		err = -ENODEV;
-		goto out_ieee80211_free_hw;
-	}
-
-	pci_set_master(pdev);
-
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (err) {
-		IWL_WARN(priv, "No suitable DMA available.\n");
-		goto out_pci_disable_device;
-	}
-
-	pci_set_drvdata(pdev, priv);
-	err = pci_request_regions(pdev, DRV_NAME);
-	if (err)
-		goto out_pci_disable_device;
-
-	/***********************
-	 * 3. Read REV Register
-	 * ********************/
-	priv->hw_base = pci_iomap(pdev, 0, 0);
-	if (!priv->hw_base) {
-		err = -ENODEV;
-		goto out_pci_release_regions;
-	}
-
-	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-			(unsigned long long) pci_resource_len(pdev, 0));
-	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
-
-	/* We disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state */
-	pci_write_config_byte(pdev, 0x41, 0x00);
-
-	/* these spin locks will be used in apm_ops.init and EEPROM access
-	 * we should init now
-	 */
-	spin_lock_init(&priv->reg_lock);
-	spin_lock_init(&priv->lock);
-
-	/*
-	 * stop and reset the on-board processor just in case it is in a
-	 * strange state ... like being left stranded by a primary kernel
-	 * and this is now the kdump kernel trying to start up
-	 */
-	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-	/***********************
-	 * 4. Read EEPROM
-	 * ********************/
-
-	/* Read the EEPROM */
-	err = iwl_eeprom_init(priv);
-	if (err) {
-		IWL_ERR(priv, "Unable to init EEPROM\n");
-		goto out_iounmap;
-	}
-	/* MAC Address location in EEPROM same for 3945/4965 */
-	eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
-	SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
-
-	/***********************
-	 * 5. Setup HW Constants
-	 * ********************/
-	/* Device-specific setup */
-	if (iwl3945_hw_set_hw_params(priv)) {
-		IWL_ERR(priv, "failed to set hw settings\n");
-		goto out_eeprom_free;
-	}
-
-	/***********************
-	 * 6. Setup priv
-	 * ********************/
-
-	err = iwl3945_init_drv(priv);
-	if (err) {
-		IWL_ERR(priv, "initializing driver failed\n");
-		goto out_unset_hw_params;
-	}
-
-	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
-		priv->cfg->name);
-
-	/***********************
-	 * 7. Setup Services
-	 * ********************/
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	pci_enable_msi(priv->pci_dev);
-
-	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
-			  IRQF_SHARED, DRV_NAME, priv);
-	if (err) {
-		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-		goto out_disable_msi;
-	}
-
-	err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
-	if (err) {
-		IWL_ERR(priv, "failed to create sysfs device attributes\n");
-		goto out_release_irq;
-	}
-
-	iwl_set_rxon_channel(priv,
-			     &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
-			     &priv->contexts[IWL_RXON_CTX_BSS]);
-	iwl3945_setup_deferred_work(priv);
-	iwl3945_setup_rx_handlers(priv);
-	iwl_power_initialize(priv);
-
-	/*********************************
-	 * 8. Setup and Register mac80211
-	 * *******************************/
-
-	iwl_enable_interrupts(priv);
-
-	err = iwl3945_setup_mac(priv);
-	if (err)
-		goto  out_remove_sysfs;
-
-	err = iwl_dbgfs_register(priv, DRV_NAME);
-	if (err)
-		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
-
-	/* Start monitoring the killswitch */
-	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-			   2 * HZ);
-
-	return 0;
-
- out_remove_sysfs:
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
-	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
- out_release_irq:
-	free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
-	pci_disable_msi(priv->pci_dev);
-	iwlcore_free_geos(priv);
-	iwl_free_channel_map(priv);
- out_unset_hw_params:
-	iwl3945_unset_hw_params(priv);
- out_eeprom_free:
-	iwl_eeprom_free(priv);
- out_iounmap:
-	pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-	pci_release_regions(pdev);
- out_pci_disable_device:
-	pci_set_drvdata(pdev, NULL);
-	pci_disable_device(pdev);
- out_ieee80211_free_hw:
-	iwl_free_traffic_mem(priv);
-	ieee80211_free_hw(priv->hw);
- out:
-	return err;
-}
-
-static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
-{
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-	unsigned long flags;
-
-	if (!priv)
-		return;
-
-	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
-
-	iwl_dbgfs_unregister(priv);
-
-	set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	if (priv->mac80211_registered) {
-		ieee80211_unregister_hw(priv->hw);
-		priv->mac80211_registered = 0;
-	} else {
-		iwl3945_down(priv);
-	}
-
-	/*
-	 * Make sure device is reset to low power before unloading driver.
-	 * This may be redundant with iwl_down(), but there are paths to
-	 * run iwl_down() without calling apm_ops.stop(), and there are
-	 * paths to avoid running iwl_down() at all before leaving driver.
-	 * This (inexpensive) call *makes sure* device is reset.
-	 */
-	iwl_apm_stop(priv);
-
-	/* make sure we flush any pending irq or
-	 * tasklet for the driver
-	 */
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_synchronize_irq(priv);
-
-	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
-
-	cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
-
-	iwl3945_dealloc_ucode_pci(priv);
-
-	if (priv->rxq.bd)
-		iwl3945_rx_queue_free(priv, &priv->rxq);
-	iwl3945_hw_txq_ctx_free(priv);
-
-	iwl3945_unset_hw_params(priv);
-
-	/*netif_stop_queue(dev); */
-	flush_workqueue(priv->workqueue);
-
-	/* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
-	 * priv->workqueue... so we can't take down the workqueue
-	 * until now... */
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
-	iwl_free_traffic_mem(priv);
-
-	free_irq(pdev->irq, priv);
-	pci_disable_msi(pdev);
-
-	pci_iounmap(pdev, priv->hw_base);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-	iwl_free_channel_map(priv);
-	iwlcore_free_geos(priv);
-	kfree(priv->scan_cmd);
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	ieee80211_free_hw(priv->hw);
-}
-
-
-/*****************************************************************************
- *
- * driver and module entry point
- *
- *****************************************************************************/
-
-static struct pci_driver iwl3945_driver = {
-	.name = DRV_NAME,
-	.id_table = iwl3945_hw_card_ids,
-	.probe = iwl3945_pci_probe,
-	.remove = __devexit_p(iwl3945_pci_remove),
-	.driver.pm = IWL_PM_OPS,
-};
-
-static int __init iwl3945_init(void)
-{
-
-	int ret;
-	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
-	pr_info(DRV_COPYRIGHT "\n");
-
-	ret = iwl3945_rate_control_register();
-	if (ret) {
-		pr_err("Unable to register rate control algorithm: %d\n", ret);
-		return ret;
-	}
-
-	ret = pci_register_driver(&iwl3945_driver);
-	if (ret) {
-		pr_err("Unable to initialize PCI module\n");
-		goto error_register;
-	}
-
-	return ret;
-
-error_register:
-	iwl3945_rate_control_unregister();
-	return ret;
-}
-
-static void __exit iwl3945_exit(void)
-{
-	pci_unregister_driver(&iwl3945_driver);
-	iwl3945_rate_control_unregister();
-}
-
-MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
-
-module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO);
-MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO);
-MODULE_PARM_DESC(swcrypto,
-		 "using software crypto (default 1 [software])\n");
-#ifdef CONFIG_IWLWIFI_DEBUG
-module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "debug output mask");
-#endif
-module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
-		   int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan,
-		 "disable hardware scanning (default 0) (deprecated)");
-module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
-
-module_exit(iwl3945_exit);
-module_init(iwl3945_init);
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 5a49822..ed57e44 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -287,7 +287,8 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
 			return -EINVAL;
 		}
 
-		freq = ieee80211_channel_to_frequency(umac_bss->channel);
+		freq = ieee80211_channel_to_frequency(umac_bss->channel,
+						      band->band);
 		channel = ieee80211_get_channel(wiphy, freq);
 		signal = umac_bss->rssi * 100;
 
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index a944893..9a57cf6 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -543,7 +543,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
 	switch (le32_to_cpu(complete->status)) {
 	case UMAC_ASSOC_COMPLETE_SUCCESS:
 		chan = ieee80211_get_channel(wiphy,
-			ieee80211_channel_to_frequency(complete->channel));
+			ieee80211_channel_to_frequency(complete->channel,
+				complete->band == UMAC_BAND_2GHZ ?
+					IEEE80211_BAND_2GHZ :
+					IEEE80211_BAND_5GHZ));
 		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
 			/* Associated to a unallowed channel, disassociate. */
 			__iwm_invalidate_mlme_profile(iwm);
@@ -841,7 +844,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
 		goto err;
 	}
 
-	freq = ieee80211_channel_to_frequency(umac_bss->channel);
+	freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band);
 	channel = ieee80211_get_channel(wiphy, freq);
 	signal = umac_bss->rssi * 100;
 
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 698a1f7..30ef035 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -607,7 +607,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
 		/* No channel, no luck */
 		if (chan_no != -1) {
 			struct wiphy *wiphy = priv->wdev->wiphy;
-			int freq = ieee80211_channel_to_frequency(chan_no);
+			int freq = ieee80211_channel_to_frequency(chan_no,
+							IEEE80211_BAND_2GHZ);
 			struct ieee80211_channel *channel =
 				ieee80211_get_channel(wiphy, freq);
 
@@ -1597,7 +1598,8 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	survey->channel = ieee80211_get_channel(wiphy,
-		ieee80211_channel_to_frequency(priv->channel));
+		ieee80211_channel_to_frequency(priv->channel,
+					       IEEE80211_BAND_2GHZ));
 
 	ret = lbs_get_rssi(priv, &signal, &noise);
 	if (ret == 0) {
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 78c4da1..7e8a658 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -145,9 +145,13 @@ int lbs_update_hw_spec(struct lbs_private *priv)
 	if (priv->current_addr[0] == 0xff)
 		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
 
-	memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
-	if (priv->mesh_dev)
-		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
+	if (!priv->copied_hwaddr) {
+		memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
+		if (priv->mesh_dev)
+			memcpy(priv->mesh_dev->dev_addr,
+				priv->current_addr, ETH_ALEN);
+		priv->copied_hwaddr = 1;
+	}
 
 out:
 	lbs_deb_leave(LBS_DEB_CMD);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 18dd9a0..bc461eb 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -90,6 +90,7 @@ struct lbs_private {
 	void *card;
 	u8 fw_ready;
 	u8 surpriseremoved;
+	u8 setup_fw_on_resume;
 	int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
 	void (*reset_card) (struct lbs_private *priv);
 	int (*enter_deep_sleep) (struct lbs_private *priv);
@@ -101,6 +102,7 @@ struct lbs_private {
 	u32 fwcapinfo;
 	u16 regioncode;
 	u8 current_addr[ETH_ALEN];
+	u8 copied_hwaddr;
 
 	/* Command download */
 	u8 dnld_sent;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 5eac135..6cb6935 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -387,7 +387,7 @@ struct lbs_offset_value {
 struct mrvl_ie_domain_param_set {
 	struct mrvl_ie_header header;
 
-	u8 country_code[3];
+	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
 	struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
 } __packed;
 
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 0060023..f6c2cd6 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -20,10 +20,8 @@
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
-#include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
-#include <linux/semaphore.h>
 #include <linux/slab.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/spi.h>
@@ -34,6 +32,12 @@
 #include "dev.h"
 #include "if_spi.h"
 
+struct if_spi_packet {
+	struct list_head		list;
+	u16				blen;
+	u8				buffer[0] __attribute__((aligned(4)));
+};
+
 struct if_spi_card {
 	struct spi_device		*spi;
 	struct lbs_private		*priv;
@@ -51,18 +55,36 @@ struct if_spi_card {
 	unsigned long			spu_reg_delay;
 
 	/* Handles all SPI communication (except for FW load) */
-	struct task_struct		*spi_thread;
-	int				run_thread;
-
-	/* Used to wake up the spi_thread */
-	struct semaphore		spi_ready;
-	struct semaphore		spi_thread_terminated;
+	struct workqueue_struct		*workqueue;
+	struct work_struct		packet_work;
 
 	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
+
+	/* A buffer of incoming packets from libertas core.
+	 * Since we can't sleep in hw_host_to_card, we have to buffer
+	 * them. */
+	struct list_head		cmd_packet_list;
+	struct list_head		data_packet_list;
+
+	/* Protects cmd_packet_list and data_packet_list */
+	spinlock_t			buffer_lock;
 };
 
 static void free_if_spi_card(struct if_spi_card *card)
 {
+	struct list_head *cursor, *next;
+	struct if_spi_packet *packet;
+
+	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
+	list_for_each_safe(cursor, next, &card->data_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
 	spi_set_drvdata(card->spi, NULL);
 	kfree(card);
 }
@@ -622,7 +644,7 @@ out:
 /*
  * SPI Transfer Thread
  *
- * The SPI thread handles all SPI transfers, so there is no need for a lock.
+ * The SPI worker handles all SPI transfers, so there is no need for a lock.
  */
 
 /* Move a command from the card to the host */
@@ -742,6 +764,40 @@ out:
 	return err;
 }
 
+/* Move data or a command from the host to the card. */
+static void if_spi_h2c(struct if_spi_card *card,
+			struct if_spi_packet *packet, int type)
+{
+	int err = 0;
+	u16 int_type, port_reg;
+
+	switch (type) {
+	case MVMS_DAT:
+		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
+		port_reg = IF_SPI_DATA_RDWRPORT_REG;
+		break;
+	case MVMS_CMD:
+		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
+		port_reg = IF_SPI_CMD_RDWRPORT_REG;
+		break;
+	default:
+		lbs_pr_err("can't transfer buffer of type %d\n", type);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Write the data to the card */
+	err = spu_write(card, port_reg, packet->buffer, packet->blen);
+	if (err)
+		goto out;
+
+out:
+	kfree(packet);
+
+	if (err)
+		lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
 /* Inform the host about a card event */
 static void if_spi_e2h(struct if_spi_card *card)
 {
@@ -766,71 +822,88 @@ out:
 		lbs_pr_err("%s: error %d\n", __func__, err);
 }
 
-static int lbs_spi_thread(void *data)
+static void if_spi_host_to_card_worker(struct work_struct *work)
 {
 	int err;
-	struct if_spi_card *card = data;
+	struct if_spi_card *card;
 	u16 hiStatus;
+	unsigned long flags;
+	struct if_spi_packet *packet;
 
-	while (1) {
-		/* Wait to be woken up by one of two things.  First, our ISR
-		 * could tell us that something happened on the WLAN.
-		 * Secondly, libertas could call hw_host_to_card with more
-		 * data, which we might be able to send.
-		 */
-		do {
-			err = down_interruptible(&card->spi_ready);
-			if (!card->run_thread) {
-				up(&card->spi_thread_terminated);
-				do_exit(0);
-			}
-		} while (err == -EINTR);
+	card = container_of(work, struct if_spi_card, packet_work);
 
-		/* Read the host interrupt status register to see what we
-		 * can do. */
-		err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
-					&hiStatus);
-		if (err) {
-			lbs_pr_err("I/O error\n");
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* Read the host interrupt status register to see what we
+	 * can do. */
+	err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+				&hiStatus);
+	if (err) {
+		lbs_pr_err("I/O error\n");
+		goto err;
+	}
+
+	if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) {
+		err = if_spi_c2h_cmd(card);
+		if (err)
 			goto err;
-		}
+	}
+	if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) {
+		err = if_spi_c2h_data(card);
+		if (err)
+			goto err;
+	}
 
-		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) {
-			err = if_spi_c2h_cmd(card);
-			if (err)
-				goto err;
-		}
-		if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) {
-			err = if_spi_c2h_data(card);
-			if (err)
-				goto err;
+	/* workaround: in PS mode, the card does not set the Command
+	 * Download Ready bit, but it sets TX Download Ready. */
+	if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
+	   (card->priv->psstate != PS_STATE_FULL_POWER &&
+	    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
+		/* This means two things. First of all,
+		 * if there was a previous command sent, the card has
+		 * successfully received it.
+		 * Secondly, it is now ready to download another
+		 * command.
+		 */
+		lbs_host_to_card_done(card->priv);
+
+		/* Do we have any command packets from the host to
+		 * send? */
+		packet = NULL;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		if (!list_empty(&card->cmd_packet_list)) {
+			packet = (struct if_spi_packet *)(card->
+					cmd_packet_list.next);
+			list_del(&packet->list);
 		}
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 
-		/* workaround: in PS mode, the card does not set the Command
-		 * Download Ready bit, but it sets TX Download Ready. */
-		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
-		   (card->priv->psstate != PS_STATE_FULL_POWER &&
-		    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
-			lbs_host_to_card_done(card->priv);
+		if (packet)
+			if_spi_h2c(card, packet, MVMS_CMD);
+	}
+	if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
+		/* Do we have any data packets from the host to
+		 * send? */
+		packet = NULL;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		if (!list_empty(&card->data_packet_list)) {
+			packet = (struct if_spi_packet *)(card->
+					data_packet_list.next);
+			list_del(&packet->list);
 		}
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 
-		if (hiStatus & IF_SPI_HIST_CARD_EVENT)
-			if_spi_e2h(card);
+		if (packet)
+			if_spi_h2c(card, packet, MVMS_DAT);
+	}
+	if (hiStatus & IF_SPI_HIST_CARD_EVENT)
+		if_spi_e2h(card);
 
 err:
-		if (err)
-			lbs_pr_err("%s: got error %d\n", __func__, err);
-	}
-}
+	if (err)
+		lbs_pr_err("%s: got error %d\n", __func__, err);
 
-/* Block until lbs_spi_thread thread has terminated */
-static void if_spi_terminate_spi_thread(struct if_spi_card *card)
-{
-	/* It would be nice to use kthread_stop here, but that function
-	 * can't wake threads waiting for a semaphore. */
-	card->run_thread = 0;
-	up(&card->spi_ready);
-	down(&card->spi_thread_terminated);
+	lbs_deb_leave(LBS_DEB_SPI);
 }
 
 /*
@@ -842,18 +915,40 @@ static int if_spi_host_to_card(struct lbs_private *priv,
 				u8 type, u8 *buf, u16 nb)
 {
 	int err = 0;
+	unsigned long flags;
 	struct if_spi_card *card = priv->card;
+	struct if_spi_packet *packet;
+	u16 blen;
 
 	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
 
-	nb = ALIGN(nb, 4);
+	if (nb == 0) {
+		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
+		err = -EINVAL;
+		goto out;
+	}
+	blen = ALIGN(nb, 4);
+	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
+	if (!packet) {
+		err = -ENOMEM;
+		goto out;
+	}
+	packet->blen = blen;
+	memcpy(packet->buffer, buf, nb);
+	memset(packet->buffer + nb, 0, blen - nb);
 
 	switch (type) {
 	case MVMS_CMD:
-		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb);
+		priv->dnld_sent = DNLD_CMD_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->cmd_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 		break;
 	case MVMS_DAT:
-		err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb);
+		priv->dnld_sent = DNLD_DATA_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->data_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 		break;
 	default:
 		lbs_pr_err("can't transfer buffer of type %d", type);
@@ -861,6 +956,9 @@ static int if_spi_host_to_card(struct lbs_private *priv,
 		break;
 	}
 
+	/* Queue spi xfer work */
+	queue_work(card->workqueue, &card->packet_work);
+out:
 	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
 	return err;
 }
@@ -869,13 +967,14 @@ static int if_spi_host_to_card(struct lbs_private *priv,
  * Host Interrupts
  *
  * Service incoming interrupts from the WLAN device. We can't sleep here, so
- * don't try to talk on the SPI bus, just wake up the SPI thread.
+ * don't try to talk on the SPI bus, just queue the SPI xfer work.
  */
 static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
 {
 	struct if_spi_card *card = dev_id;
 
-	up(&card->spi_ready);
+	queue_work(card->workqueue, &card->packet_work);
+
 	return IRQ_HANDLED;
 }
 
@@ -883,56 +982,26 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
  * SPI callbacks
  */
 
-static int __devinit if_spi_probe(struct spi_device *spi)
+static int if_spi_init_card(struct if_spi_card *card)
 {
-	struct if_spi_card *card;
-	struct lbs_private *priv = NULL;
-	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
-	int err = 0, i;
+	struct spi_device *spi = card->spi;
+	int err, i;
 	u32 scratch;
-	struct sched_param param = { .sched_priority = 1 };
 	const struct firmware *helper = NULL;
 	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
-	if (!pdata) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	if (pdata->setup) {
-		err = pdata->setup(spi);
-		if (err)
-			goto out;
-	}
-
-	/* Allocate card structure to represent this specific device */
-	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
-	if (!card) {
-		err = -ENOMEM;
-		goto out;
-	}
-	spi_set_drvdata(spi, card);
-	card->pdata = pdata;
-	card->spi = spi;
-	card->prev_xfer_time = jiffies;
-
-	sema_init(&card->spi_ready, 0);
-	sema_init(&card->spi_thread_terminated, 0);
-
-	/* Initialize the SPI Interface Unit */
-	err = spu_init(card, pdata->use_dummy_writes);
+	err = spu_init(card, card->pdata->use_dummy_writes);
 	if (err)
-		goto free_card;
+		goto out;
 	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
 	if (err)
-		goto free_card;
+		goto out;
 
-	/* Firmware load */
 	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
 	if (err)
-		goto free_card;
+		goto out;
 	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
 		lbs_deb_spi("Firmware is already loaded for "
 			    "Marvell WLAN 802.11 adapter\n");
@@ -946,7 +1015,7 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 			lbs_pr_err("Unsupported chip_id: 0x%02x\n",
 					card->card_id);
 			err = -ENODEV;
-			goto free_card;
+			goto out;
 		}
 
 		err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
@@ -954,7 +1023,7 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 					&mainfw);
 		if (err) {
 			lbs_pr_err("failed to find firmware (%d)\n", err);
-			goto free_card;
+			goto out;
 		}
 
 		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
@@ -966,15 +1035,68 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 				spi->max_speed_hz);
 		err = if_spi_prog_helper_firmware(card, helper);
 		if (err)
-			goto free_card;
+			goto out;
 		err = if_spi_prog_main_firmware(card, mainfw);
 		if (err)
-			goto free_card;
+			goto out;
 		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
 	}
 
 	err = spu_set_interrupt_mode(card, 0, 1);
 	if (err)
+		goto out;
+
+out:
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
+
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
+
+	return err;
+}
+
+static int __devinit if_spi_probe(struct spi_device *spi)
+{
+	struct if_spi_card *card;
+	struct lbs_private *priv = NULL;
+	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
+	int err = 0;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	if (!pdata) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (pdata->setup) {
+		err = pdata->setup(spi);
+		if (err)
+			goto out;
+	}
+
+	/* Allocate card structure to represent this specific device */
+	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
+	if (!card) {
+		err = -ENOMEM;
+		goto teardown;
+	}
+	spi_set_drvdata(spi, card);
+	card->pdata = pdata;
+	card->spi = spi;
+	card->prev_xfer_time = jiffies;
+
+	INIT_LIST_HEAD(&card->cmd_packet_list);
+	INIT_LIST_HEAD(&card->data_packet_list);
+	spin_lock_init(&card->buffer_lock);
+
+	/* Initialize the SPI Interface Unit */
+
+	/* Firmware load */
+	err = if_spi_init_card(card);
+	if (err)
 		goto free_card;
 
 	/* Register our card with libertas.
@@ -993,27 +1115,16 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 	priv->fw_ready = 1;
 
 	/* Initialize interrupt handling stuff. */
-	card->run_thread = 1;
-	card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
-	if (IS_ERR(card->spi_thread)) {
-		card->run_thread = 0;
-		err = PTR_ERR(card->spi_thread);
-		lbs_pr_err("error creating SPI thread: err=%d\n", err);
-		goto remove_card;
-	}
-	if (sched_setscheduler(card->spi_thread, SCHED_FIFO, &param))
-		lbs_pr_err("Error setting scheduler, using default.\n");
+	card->workqueue = create_workqueue("libertas_spi");
+	INIT_WORK(&card->packet_work, if_spi_host_to_card_worker);
 
 	err = request_irq(spi->irq, if_spi_host_interrupt,
 			IRQF_TRIGGER_FALLING, "libertas_spi", card);
 	if (err) {
 		lbs_pr_err("can't get host irq line-- request_irq failed\n");
-		goto terminate_thread;
+		goto terminate_workqueue;
 	}
 
-	/* poke the IRQ handler so that we don't miss the first interrupt */
-	up(&card->spi_ready);
-
 	/* Start the card.
 	 * This will call register_netdev, and we'll start
 	 * getting interrupts... */
@@ -1028,18 +1139,16 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 
 release_irq:
 	free_irq(spi->irq, card);
-terminate_thread:
-	if_spi_terminate_spi_thread(card);
-remove_card:
+terminate_workqueue:
+	flush_workqueue(card->workqueue);
+	destroy_workqueue(card->workqueue);
 	lbs_remove_card(priv); /* will call free_netdev */
 free_card:
 	free_if_spi_card(card);
+teardown:
+	if (pdata->teardown)
+		pdata->teardown(spi);
 out:
-	if (helper)
-		release_firmware(helper);
-	if (mainfw)
-		release_firmware(mainfw);
-
 	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
 	return err;
 }
@@ -1056,7 +1165,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi)
 	lbs_remove_card(priv); /* will call free_netdev */
 
 	free_irq(spi->irq, card);
-	if_spi_terminate_spi_thread(card);
+	flush_workqueue(card->workqueue);
+	destroy_workqueue(card->workqueue);
 	if (card->pdata->teardown)
 		card->pdata->teardown(spi);
 	free_if_spi_card(card);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 6836a6d..ca8149c 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -539,6 +539,43 @@ static int lbs_thread(void *data)
 	return 0;
 }
 
+/**
+ * @brief This function gets the HW spec from the firmware and sets
+ *        some basic parameters.
+ *
+ *  @param priv    A pointer to struct lbs_private structure
+ *  @return        0 or -1
+ */
+static int lbs_setup_firmware(struct lbs_private *priv)
+{
+	int ret = -1;
+	s16 curlevel = 0, minlevel = 0, maxlevel = 0;
+
+	lbs_deb_enter(LBS_DEB_FW);
+
+	/* Read MAC address from firmware */
+	memset(priv->current_addr, 0xff, ETH_ALEN);
+	ret = lbs_update_hw_spec(priv);
+	if (ret)
+		goto done;
+
+	/* Read power levels if available */
+	ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
+	if (ret == 0) {
+		priv->txpower_cur = curlevel;
+		priv->txpower_min = minlevel;
+		priv->txpower_max = maxlevel;
+	}
+
+	/* Send cmd to FW to enable 11D function */
+	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
+
+	lbs_set_mac_control(priv);
+done:
+	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+	return ret;
+}
+
 int lbs_suspend(struct lbs_private *priv)
 {
 	int ret;
@@ -584,47 +621,13 @@ int lbs_resume(struct lbs_private *priv)
 			lbs_pr_err("deep sleep activation failed: %d\n", ret);
 	}
 
-	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_resume);
-
-/**
- * @brief This function gets the HW spec from the firmware and sets
- *        some basic parameters.
- *
- *  @param priv    A pointer to struct lbs_private structure
- *  @return 	   0 or -1
- */
-static int lbs_setup_firmware(struct lbs_private *priv)
-{
-	int ret = -1;
-	s16 curlevel = 0, minlevel = 0, maxlevel = 0;
-
-	lbs_deb_enter(LBS_DEB_FW);
-
-	/* Read MAC address from firmware */
-	memset(priv->current_addr, 0xff, ETH_ALEN);
-	ret = lbs_update_hw_spec(priv);
-	if (ret)
-		goto done;
-
-	/* Read power levels if available */
-	ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
-	if (ret == 0) {
-		priv->txpower_cur = curlevel;
-		priv->txpower_min = minlevel;
-		priv->txpower_max = maxlevel;
-	}
+	if (priv->setup_fw_on_resume)
+		ret = lbs_setup_firmware(priv);
 
-	/* Send cmd to FW to enable 11D function */
-	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
-
-	lbs_set_mac_control(priv);
-done:
 	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(lbs_resume);
 
 /**
  *  This function handles the timeout of command sending.
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index acf3bf6..9d097b9 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -918,7 +918,6 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
 			   char *buf)
 {
 	struct mrvl_mesh_defaults defs;
-	int maxlen;
 	int ret;
 
 	ret = mesh_get_default_parameters(dev, &defs);
@@ -931,13 +930,11 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
 		defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
 	}
 
-	/* SSID not null terminated: reserve room for \0 + \n */
-	maxlen = defs.meshie.val.mesh_id_len + 2;
-	maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
+	memcpy(buf, defs.meshie.val.mesh_id, defs.meshie.val.mesh_id_len);
+	buf[defs.meshie.val.mesh_id_len] = '\n';
+	buf[defs.meshie.val.mesh_id_len + 1] = '\0';
 
-	defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
-
-	return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
+	return defs.meshie.val.mesh_id_len + 1;
 }
 
 /**
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index 9278b3c..d400508 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -225,7 +225,7 @@ static void lbtf_free_adapter(struct lbtf_private *priv)
 	lbtf_deb_leave(LBTF_DEB_MAIN);
 }
 
-static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct lbtf_private *priv = hw->priv;
 
@@ -236,7 +236,6 @@ static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 * there are no buffered multicast frames to send
 	 */
 	ieee80211_stop_queues(priv->hw);
-	return NETDEV_TX_OK;
 }
 
 static void lbtf_tx_work(struct work_struct *work)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 454f045..56f439d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -541,7 +541,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
 }
 
 
-static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	bool ack;
 	struct ieee80211_tx_info *txi;
@@ -551,7 +551,7 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (skb->len < 10) {
 		/* Should not happen; just a sanity check for addr1 use */
 		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
 	ack = mac80211_hwsim_tx_frame(hw, skb);
@@ -571,7 +571,6 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack)
 		txi->flags |= IEEE80211_TX_STAT_ACK;
 	ieee80211_tx_status_irqsafe(hw, skb);
-	return NETDEV_TX_OK;
 }
 
 
@@ -943,7 +942,8 @@ static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw,
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       enum ieee80211_ampdu_mlme_action action,
-				       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+				       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+				       u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 9ecf840..3695227 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -232,6 +232,9 @@ struct mwl8k_priv {
 	struct completion firmware_loading_complete;
 };
 
+#define MAX_WEP_KEY_LEN         13
+#define NUM_WEP_KEYS            4
+
 /* Per interface specific private data */
 struct mwl8k_vif {
 	struct list_head list;
@@ -242,8 +245,21 @@ struct mwl8k_vif {
 
 	/* Non AMPDU sequence number assigned by driver.  */
 	u16 seqno;
+
+	/* Saved WEP keys */
+	struct {
+		u8 enabled;
+		u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN];
+	} wep_key_conf[NUM_WEP_KEYS];
+
+	/* BSSID */
+	u8 bssid[ETH_ALEN];
+
+	/* A flag to indicate is HW crypto is enabled for this bssid */
+	bool is_hw_crypto_enabled;
 };
 #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
+#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))
 
 struct mwl8k_sta {
 	/* Index into station database. Returned by UPDATE_STADB.  */
@@ -337,6 +353,7 @@ static const struct ieee80211_rate mwl8k_rates_50[] = {
 #define MWL8K_CMD_SET_RATEADAPT_MODE	0x0203
 #define MWL8K_CMD_BSS_START		0x1100		/* per-vif */
 #define MWL8K_CMD_SET_NEW_STN		0x1111		/* per-vif */
+#define MWL8K_CMD_UPDATE_ENCRYPTION	0x1122		/* per-vif */
 #define MWL8K_CMD_UPDATE_STADB		0x1123
 
 static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
@@ -375,6 +392,7 @@ static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
 		MWL8K_CMDNAME(SET_RATEADAPT_MODE);
 		MWL8K_CMDNAME(BSS_START);
 		MWL8K_CMDNAME(SET_NEW_STN);
+		MWL8K_CMDNAME(UPDATE_ENCRYPTION);
 		MWL8K_CMDNAME(UPDATE_STADB);
 	default:
 		snprintf(buf, bufsize, "0x%x", cmd);
@@ -715,10 +733,12 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos)
 		skb_pull(skb, sizeof(*tr) - hdrlen);
 }
 
-static inline void mwl8k_add_dma_header(struct sk_buff *skb)
+static void
+mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad)
 {
 	struct ieee80211_hdr *wh;
 	int hdrlen;
+	int reqd_hdrlen;
 	struct mwl8k_dma_data *tr;
 
 	/*
@@ -730,11 +750,13 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb)
 	wh = (struct ieee80211_hdr *)skb->data;
 
 	hdrlen = ieee80211_hdrlen(wh->frame_control);
-	if (hdrlen != sizeof(*tr))
-		skb_push(skb, sizeof(*tr) - hdrlen);
+	reqd_hdrlen = sizeof(*tr);
+
+	if (hdrlen != reqd_hdrlen)
+		skb_push(skb, reqd_hdrlen - hdrlen);
 
 	if (ieee80211_is_data_qos(wh->frame_control))
-		hdrlen -= 2;
+		hdrlen -= IEEE80211_QOS_CTL_LEN;
 
 	tr = (struct mwl8k_dma_data *)skb->data;
 	if (wh != &tr->wh)
@@ -747,9 +769,52 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb)
 	 * payload".  That is, everything except for the 802.11 header.
 	 * This includes all crypto material including the MIC.
 	 */
-	tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr));
+	tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad);
 }
 
+static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *wh;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_key_conf *key_conf;
+	int data_pad;
+
+	wh = (struct ieee80211_hdr *)skb->data;
+
+	tx_info = IEEE80211_SKB_CB(skb);
+
+	key_conf = NULL;
+	if (ieee80211_is_data(wh->frame_control))
+		key_conf = tx_info->control.hw_key;
+
+	/*
+	 * Make sure the packet header is in the DMA header format (4-address
+	 * without QoS), the necessary crypto padding between the header and the
+	 * payload has already been provided by mac80211, but it doesn't add tail
+	 * padding when HW crypto is enabled.
+	 *
+	 * We have the following trailer padding requirements:
+	 * - WEP: 4 trailer bytes (ICV)
+	 * - TKIP: 12 trailer bytes (8 MIC + 4 ICV)
+	 * - CCMP: 8 trailer bytes (MIC)
+	 */
+	data_pad = 0;
+	if (key_conf != NULL) {
+		switch (key_conf->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			data_pad = 4;
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			data_pad = 12;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			data_pad = 8;
+			break;
+		}
+	}
+	mwl8k_add_dma_header(skb, data_pad);
+}
 
 /*
  * Packet reception for 88w8366 AP firmware.
@@ -778,6 +843,13 @@ struct mwl8k_rxd_8366_ap {
 
 #define MWL8K_8366_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
+
 static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
 {
 	struct mwl8k_rxd_8366_ap *rxd = _rxd;
@@ -834,10 +906,16 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
 	} else {
 		status->band = IEEE80211_BAND_2GHZ;
 	}
-	status->freq = ieee80211_channel_to_frequency(rxd->channel);
+	status->freq = ieee80211_channel_to_frequency(rxd->channel,
+						      status->band);
 
 	*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))
+		status->flag |= RX_FLAG_MMIC_ERROR;
+
 	return le16_to_cpu(rxd->pkt_len);
 }
 
@@ -876,6 +954,11 @@ struct mwl8k_rxd_sta {
 #define MWL8K_STA_RATE_INFO_MCS_FORMAT		0x0001
 
 #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST		0x02
+#define MWL8K_STA_RX_CTRL_DECRYPT_ERROR		0x04
+/* ICV=0 or MIC=1 */
+#define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE		0x08
+/* Key is uploaded only in failure case */
+#define MWL8K_STA_RX_CTRL_KEY_INDEX			0x30
 
 static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
 {
@@ -931,9 +1014,13 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
 	} else {
 		status->band = IEEE80211_BAND_2GHZ;
 	}
-	status->freq = ieee80211_channel_to_frequency(rxd->channel);
+	status->freq = ieee80211_channel_to_frequency(rxd->channel,
+						      status->band);
 
 	*qos = rxd->qos_control;
+	if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
+	    (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE))
+		status->flag |= RX_FLAG_MMIC_ERROR;
 
 	return le16_to_cpu(rxd->pkt_len);
 }
@@ -969,13 +1056,12 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
 	}
 	memset(rxq->rxd, 0, size);
 
-	rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL);
+	rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
 	if (rxq->buf == NULL) {
 		wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n");
 		pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
 		return -ENOMEM;
 	}
-	memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf));
 
 	for (i = 0; i < MWL8K_RX_DESCS; i++) {
 		int desc_size;
@@ -1092,9 +1178,25 @@ static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
 		ieee80211_queue_work(hw, &priv->finalize_join_worker);
 }
 
+static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list,
+						   u8 *bssid)
+{
+	struct mwl8k_vif *mwl8k_vif;
+
+	list_for_each_entry(mwl8k_vif,
+			    vif_list, list) {
+		if (memcmp(bssid, mwl8k_vif->bssid,
+			   ETH_ALEN) == 0)
+			return mwl8k_vif;
+	}
+
+	return NULL;
+}
+
 static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
 {
 	struct mwl8k_priv *priv = hw->priv;
+	struct mwl8k_vif *mwl8k_vif = NULL;
 	struct mwl8k_rx_queue *rxq = priv->rxq + index;
 	int processed;
 
@@ -1104,6 +1206,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
 		void *rxd;
 		int pkt_len;
 		struct ieee80211_rx_status status;
+		struct ieee80211_hdr *wh;
 		__le16 qos;
 
 		skb = rxq->buf[rxq->head].skb;
@@ -1130,8 +1233,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
 
 		rxq->rxd_count--;
 
-		skb_put(skb, pkt_len);
-		mwl8k_remove_dma_header(skb, qos);
+		wh = &((struct mwl8k_dma_data *)skb->data)->wh;
 
 		/*
 		 * Check for a pending join operation.  Save a
@@ -1141,6 +1243,46 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
 		if (mwl8k_capture_bssid(priv, (void *)skb->data))
 			mwl8k_save_beacon(hw, skb);
 
+		if (ieee80211_has_protected(wh->frame_control)) {
+
+			/* Check if hw crypto has been enabled for
+			 * this bss. If yes, set the status flags
+			 * accordingly
+			 */
+			mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list,
+								wh->addr1);
+
+			if (mwl8k_vif != NULL &&
+			    mwl8k_vif->is_hw_crypto_enabled == true) {
+				/*
+				 * When MMIC ERROR is encountered
+				 * by the firmware, payload is
+				 * dropped and only 32 bytes of
+				 * mwl8k Firmware header is sent
+				 * to the host.
+				 *
+				 * We need to add four bytes of
+				 * key information.  In it
+				 * MAC80211 expects keyidx set to
+				 * 0 for triggering Counter
+				 * Measure of MMIC failure.
+				 */
+				if (status.flag & RX_FLAG_MMIC_ERROR) {
+					struct mwl8k_dma_data *tr;
+					tr = (struct mwl8k_dma_data *)skb->data;
+					memset((void *)&(tr->data), 0, 4);
+					pkt_len += 4;
+				}
+
+				if (!ieee80211_is_auth(wh->frame_control))
+					status.flag |= RX_FLAG_IV_STRIPPED |
+						       RX_FLAG_DECRYPTED |
+						       RX_FLAG_MMIC_STRIPPED;
+			}
+		}
+
+		skb_put(skb, pkt_len);
+		mwl8k_remove_dma_header(skb, qos);
 		memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 		ieee80211_rx_irqsafe(hw, skb);
 
@@ -1204,13 +1346,12 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
 	}
 	memset(txq->txd, 0, size);
 
-	txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL);
+	txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
 	if (txq->skb == NULL) {
 		wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n");
 		pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
 		return -ENOMEM;
 	}
-	memset(txq->skb, 0, MWL8K_TX_DESCS * sizeof(*txq->skb));
 
 	for (i = 0; i < MWL8K_TX_DESCS; i++) {
 		struct mwl8k_tx_desc *tx_desc;
@@ -1392,6 +1533,13 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
 
 		info = IEEE80211_SKB_CB(skb);
 		ieee80211_tx_info_clear_status(info);
+
+		/* Rate control is happening in the firmware.
+		 * Ensure no tx rate is being reported.
+		 */
+                info->status.rates[0].idx = -1;
+                info->status.rates[0].count = 1;
+
 		if (MWL8K_TXD_SUCCESS(status))
 			info->flags |= IEEE80211_TX_STAT_ACK;
 
@@ -1423,7 +1571,7 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
 	txq->txd = NULL;
 }
 
-static int
+static void
 mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 {
 	struct mwl8k_priv *priv = hw->priv;
@@ -1443,7 +1591,11 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 	else
 		qos = 0;
 
-	mwl8k_add_dma_header(skb);
+	if (priv->ap_fw)
+		mwl8k_encapsulate_tx_frame(skb);
+	else
+		mwl8k_add_dma_header(skb, 0);
+
 	wh = &((struct mwl8k_dma_data *)skb->data)->wh;
 
 	tx_info = IEEE80211_SKB_CB(skb);
@@ -1481,7 +1633,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 		wiphy_debug(hw->wiphy,
 			    "failed to dma map skb, dropping TX frame.\n");
 		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
 	spin_lock_bh(&priv->tx_lock);
@@ -1518,8 +1670,6 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 	mwl8k_tx_start(priv);
 
 	spin_unlock_bh(&priv->tx_lock);
-
-	return NETDEV_TX_OK;
 }
 
 
@@ -1974,8 +2124,18 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
 	cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
 	cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
 	cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
-	for (i = 0; i < MWL8K_TX_QUEUES; i++)
-		cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma);
+
+	/*
+	 * Mac80211 stack has Q0 as highest priority and Q3 as lowest in
+	 * that order. Firmware has Q3 as highest priority and Q0 as lowest
+	 * in that order. Map Q3 of mac80211 to Q0 of firmware so that the
+	 * priority is interpreted the right way in firmware.
+	 */
+	for (i = 0; i < MWL8K_TX_QUEUES; i++) {
+		int j = MWL8K_TX_QUEUES - 1 - i;
+		cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma);
+	}
+
 	cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
 				 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
 				 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON);
@@ -3099,6 +3259,274 @@ static int mwl8k_cmd_set_new_stn_del(struct ieee80211_hw *hw,
 }
 
 /*
+ * CMD_UPDATE_ENCRYPTION.
+ */
+
+#define MAX_ENCR_KEY_LENGTH	16
+#define MIC_KEY_LENGTH		8
+
+struct mwl8k_cmd_update_encryption {
+	struct mwl8k_cmd_pkt header;
+
+	__le32 action;
+	__le32 reserved;
+	__u8 mac_addr[6];
+	__u8 encr_type;
+
+} __attribute__((packed));
+
+struct mwl8k_cmd_set_key {
+	struct mwl8k_cmd_pkt header;
+
+	__le32 action;
+	__le32 reserved;
+	__le16 length;
+	__le16 key_type_id;
+	__le32 key_info;
+	__le32 key_id;
+	__le16 key_len;
+	__u8 key_material[MAX_ENCR_KEY_LENGTH];
+	__u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
+	__u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
+	__le16 tkip_rsc_low;
+	__le32 tkip_rsc_high;
+	__le16 tkip_tsc_low;
+	__le32 tkip_tsc_high;
+	__u8 mac_addr[6];
+} __attribute__((packed));
+
+enum {
+	MWL8K_ENCR_ENABLE,
+	MWL8K_ENCR_SET_KEY,
+	MWL8K_ENCR_REMOVE_KEY,
+	MWL8K_ENCR_SET_GROUP_KEY,
+};
+
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_WEP	0
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_DISABLE	1
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_TKIP	4
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED	7
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_AES	8
+
+enum {
+	MWL8K_ALG_WEP,
+	MWL8K_ALG_TKIP,
+	MWL8K_ALG_CCMP,
+};
+
+#define MWL8K_KEY_FLAG_TXGROUPKEY	0x00000004
+#define MWL8K_KEY_FLAG_PAIRWISE		0x00000008
+#define MWL8K_KEY_FLAG_TSC_VALID	0x00000040
+#define MWL8K_KEY_FLAG_WEP_TXKEY	0x01000000
+#define MWL8K_KEY_FLAG_MICKEY_VALID	0x02000000
+
+static int mwl8k_cmd_update_encryption_enable(struct ieee80211_hw *hw,
+					      struct ieee80211_vif *vif,
+					      u8 *addr,
+					      u8 encr_type)
+{
+	struct mwl8k_cmd_update_encryption *cmd;
+	int rc;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
+	cmd->header.length = cpu_to_le16(sizeof(*cmd));
+	cmd->action = cpu_to_le32(MWL8K_ENCR_ENABLE);
+	memcpy(cmd->mac_addr, addr, ETH_ALEN);
+	cmd->encr_type = encr_type;
+
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+	kfree(cmd);
+
+	return rc;
+}
+
+static int mwl8k_encryption_set_cmd_info(struct mwl8k_cmd_set_key *cmd,
+						u8 *addr,
+						struct ieee80211_key_conf *key)
+{
+	cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
+	cmd->header.length = cpu_to_le16(sizeof(*cmd));
+	cmd->length = cpu_to_le16(sizeof(*cmd) -
+				offsetof(struct mwl8k_cmd_set_key, length));
+	cmd->key_id = cpu_to_le32(key->keyidx);
+	cmd->key_len = cpu_to_le16(key->keylen);
+	memcpy(cmd->mac_addr, addr, ETH_ALEN);
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		cmd->key_type_id = cpu_to_le16(MWL8K_ALG_WEP);
+		if (key->keyidx == 0)
+			cmd->key_info =	cpu_to_le32(MWL8K_KEY_FLAG_WEP_TXKEY);
+
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		cmd->key_type_id = cpu_to_le16(MWL8K_ALG_TKIP);
+		cmd->key_info =	(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+			? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
+			: cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
+		cmd->key_info |= cpu_to_le32(MWL8K_KEY_FLAG_MICKEY_VALID
+						| MWL8K_KEY_FLAG_TSC_VALID);
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		cmd->key_type_id = cpu_to_le16(MWL8K_ALG_CCMP);
+		cmd->key_info =	(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+			? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
+			: cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw,
+						struct ieee80211_vif *vif,
+						u8 *addr,
+						struct ieee80211_key_conf *key)
+{
+	struct mwl8k_cmd_set_key *cmd;
+	int rc;
+	int keymlen;
+	u32 action;
+	u8 idx;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
+	if (rc < 0)
+		goto done;
+
+	idx = key->keyidx;
+
+	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+		action = MWL8K_ENCR_SET_KEY;
+	else
+		action = MWL8K_ENCR_SET_GROUP_KEY;
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		if (!mwl8k_vif->wep_key_conf[idx].enabled) {
+			memcpy(mwl8k_vif->wep_key_conf[idx].key, key,
+						sizeof(*key) + key->keylen);
+			mwl8k_vif->wep_key_conf[idx].enabled = 1;
+		}
+
+		keymlen = 0;
+		action = MWL8K_ENCR_SET_KEY;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		keymlen = key->keylen;
+		break;
+	default:
+		rc = -ENOTSUPP;
+		goto done;
+	}
+
+	memcpy(cmd->key_material, key->key, keymlen);
+	cmd->action = cpu_to_le32(action);
+
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+done:
+	kfree(cmd);
+
+	return rc;
+}
+
+static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
+						struct ieee80211_vif *vif,
+						u8 *addr,
+						struct ieee80211_key_conf *key)
+{
+	struct mwl8k_cmd_set_key *cmd;
+	int rc;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
+	if (rc < 0)
+		goto done;
+
+	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+			WLAN_CIPHER_SUITE_WEP104)
+		mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;
+
+	cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);
+
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+done:
+	kfree(cmd);
+
+	return rc;
+}
+
+static int mwl8k_set_key(struct ieee80211_hw *hw,
+			 enum set_key_cmd cmd_param,
+			 struct ieee80211_vif *vif,
+			 struct ieee80211_sta *sta,
+			 struct ieee80211_key_conf *key)
+{
+	int rc = 0;
+	u8 encr_type;
+	u8 *addr;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+
+	if (vif->type == NL80211_IFTYPE_STATION)
+		return -EOPNOTSUPP;
+
+	if (sta == NULL)
+		addr = hw->wiphy->perm_addr;
+	else
+		addr = sta->addr;
+
+	if (cmd_param == SET_KEY) {
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key);
+		if (rc)
+			goto out;
+
+		if ((key->cipher == WLAN_CIPHER_SUITE_WEP40)
+				|| (key->cipher == WLAN_CIPHER_SUITE_WEP104))
+			encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_WEP;
+		else
+			encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED;
+
+		rc = mwl8k_cmd_update_encryption_enable(hw, vif, addr,
+								encr_type);
+		if (rc)
+			goto out;
+
+		mwl8k_vif->is_hw_crypto_enabled = true;
+
+	} else {
+		rc = mwl8k_cmd_encryption_remove_key(hw, vif, addr, key);
+
+		if (rc)
+			goto out;
+
+		mwl8k_vif->is_hw_crypto_enabled = false;
+
+	}
+out:
+	return rc;
+}
+
+/*
  * CMD_UPDATE_STADB.
  */
 struct ewc_ht_info {
@@ -3310,22 +3738,19 @@ static void mwl8k_rx_poll(unsigned long data)
 /*
  * Core driver operations.
  */
-static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	int index = skb_get_queue_mapping(skb);
-	int rc;
 
 	if (!priv->radio_on) {
 		wiphy_debug(hw->wiphy,
 			    "dropped TX frame since radio disabled\n");
 		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
-	rc = mwl8k_txq_xmit(hw, index, skb);
-
-	return rc;
+	mwl8k_txq_xmit(hw, index, skb);
 }
 
 static int mwl8k_start(struct ieee80211_hw *hw)
@@ -3469,6 +3894,8 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
 	mwl8k_vif->vif = vif;
 	mwl8k_vif->macid = macid;
 	mwl8k_vif->seqno = 0;
+	memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN);
+	mwl8k_vif->is_hw_crypto_enabled = false;
 
 	/* Set the mac address.  */
 	mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
@@ -3528,9 +3955,13 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
 		if (rc)
 			goto out;
 
-		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7);
-		if (!rc)
-			rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
+		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3);
+		if (rc)
+			wiphy_warn(hw->wiphy, "failed to set # of RX antennas");
+		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
+		if (rc)
+			wiphy_warn(hw->wiphy, "failed to set # of TX antennas");
+
 	} else {
 		rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
 		if (rc)
@@ -3866,18 +4297,27 @@ static int mwl8k_sta_add(struct ieee80211_hw *hw,
 {
 	struct mwl8k_priv *priv = hw->priv;
 	int ret;
+	int i;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+	struct ieee80211_key_conf *key;
 
 	if (!priv->ap_fw) {
 		ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
 		if (ret >= 0) {
 			MWL8K_STA(sta)->peer_id = ret;
-			return 0;
+			ret = 0;
 		}
 
-		return ret;
+	} else {
+		ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
 	}
 
-	return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
+		if (mwl8k_vif->wep_key_conf[i].enabled)
+			mwl8k_set_key(hw, SET_KEY, vif, sta, key);
+	}
+	return ret;
 }
 
 static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
@@ -3894,12 +4334,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		if (!priv->wmm_enabled)
 			rc = mwl8k_cmd_set_wmm_mode(hw, 1);
 
-		if (!rc)
-			rc = mwl8k_cmd_set_edca_params(hw, queue,
+		if (!rc) {
+			int q = MWL8K_TX_QUEUES - 1 - queue;
+			rc = mwl8k_cmd_set_edca_params(hw, q,
 						       params->cw_min,
 						       params->cw_max,
 						       params->aifs,
 						       params->txop);
+		}
 
 		mwl8k_fw_unlock(hw);
 	}
@@ -3932,7 +4374,8 @@ static int mwl8k_get_survey(struct ieee80211_hw *hw, int idx,
 static int
 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		   enum ieee80211_ampdu_mlme_action action,
-		   struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+		   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+		   u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
@@ -3955,6 +4398,7 @@ static const struct ieee80211_ops mwl8k_ops = {
 	.bss_info_changed	= mwl8k_bss_info_changed,
 	.prepare_multicast	= mwl8k_prepare_multicast,
 	.configure_filter	= mwl8k_configure_filter,
+	.set_key                = mwl8k_set_key,
 	.set_rts_threshold	= mwl8k_set_rts_threshold,
 	.sta_add		= mwl8k_sta_add,
 	.sta_remove		= mwl8k_sta_remove,
@@ -4332,7 +4776,7 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv)
 	hw->queues = MWL8K_TX_QUEUES;
 
 	/* Set rssi values to dBm */
-	hw->flags |= IEEE80211_HW_SIGNAL_DBM;
+	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
 	hw->vif_data_size = sizeof(struct mwl8k_vif);
 	hw->sta_data_size = sizeof(struct mwl8k_sta);
 
diff --git a/drivers/net/wireless/orinoco/scan.c b/drivers/net/wireless/orinoco/scan.c
index 86cb54c..e99ca1c 100644
--- a/drivers/net/wireless/orinoco/scan.c
+++ b/drivers/net/wireless/orinoco/scan.c
@@ -111,6 +111,11 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv,
 
 	freq = ieee80211_dsss_chan_to_freq(le16_to_cpu(bss->a.channel));
 	channel = ieee80211_get_channel(wiphy, freq);
+	if (!channel) {
+		printk(KERN_DEBUG "Invalid channel designation %04X(%04X)",
+			bss->a.channel, freq);
+		return;	/* Then ignore it for now */
+	}
 	timestamp = 0;
 	capability = le16_to_cpu(bss->a.capabilities);
 	beacon_interval = le16_to_cpu(bss->a.beacon_interv);
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
index 25f965f..0ec55b5 100644
--- a/drivers/net/wireless/p54/Kconfig
+++ b/drivers/net/wireless/p54/Kconfig
@@ -43,9 +43,8 @@ config P54_SPI
 	tristate "Prism54 SPI (stlc45xx) support"
 	depends on P54_COMMON && SPI_MASTER && GENERIC_HARDIRQS
 	---help---
-	  This driver is for stlc4550 or stlc4560 based wireless chips.
-	  This driver is experimental, untested and will probably only work on
-	  Nokia's N800/N810 Portable Internet Tablet.
+	  This driver is for stlc4550 or stlc4560 based wireless chips
+	  such as Nokia's N800/N810 Portable Internet Tablet.
 
 	  If you choose to build a module, it'll be called p54spi.
 
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 35b09aa..13d750d 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -55,6 +55,17 @@ static struct ieee80211_rate p54_arates[] = {
 	{ .bitrate = 540, .hw_value = 11, },
 };
 
+static struct p54_rssi_db_entry p54_rssi_default = {
+	/*
+	 * The defaults are taken from usb-logs of the
+	 * vendor driver. So, they should be safe to
+	 * use in case we can't get a match from the
+	 * rssi <-> dBm conversion database.
+	 */
+	.mul = 130,
+	.add = -398,
+};
+
 #define CHAN_HAS_CAL		BIT(0)
 #define CHAN_HAS_LIMIT		BIT(1)
 #define CHAN_HAS_CURVE		BIT(2)
@@ -87,13 +98,27 @@ static int p54_get_band_from_freq(u16 freq)
 	return -1;
 }
 
+static int same_band(u16 freq, u16 freq2)
+{
+	return p54_get_band_from_freq(freq) == p54_get_band_from_freq(freq2);
+}
+
 static int p54_compare_channels(const void *_a,
 				const void *_b)
 {
 	const struct p54_channel_entry *a = _a;
 	const struct p54_channel_entry *b = _b;
 
-	return a->index - b->index;
+	return a->freq - b->freq;
+}
+
+static int p54_compare_rssichan(const void *_a,
+				const void *_b)
+{
+	const struct p54_rssi_db_entry *a = _a;
+	const struct p54_rssi_db_entry *b = _b;
+
+	return a->freq - b->freq;
 }
 
 static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
@@ -145,25 +170,26 @@ static int p54_generate_band(struct ieee80211_hw *dev,
 
 	for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
 			   (i < list->entries); i++) {
+		struct p54_channel_entry *chan = &list->channels[i];
 
-		if (list->channels[i].band != band)
+		if (chan->band != band)
 			continue;
 
-		if (list->channels[i].data != CHAN_HAS_ALL) {
-			wiphy_err(dev->wiphy,
-				  "%s%s%s is/are missing for channel:%d [%d MHz].\n",
-				  (list->channels[i].data & CHAN_HAS_CAL ? "" :
+		if (chan->data != CHAN_HAS_ALL) {
+			wiphy_err(dev->wiphy, "%s%s%s is/are missing for "
+				  "channel:%d [%d MHz].\n",
+				  (chan->data & CHAN_HAS_CAL ? "" :
 				   " [iqauto calibration data]"),
-				  (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
+				  (chan->data & CHAN_HAS_LIMIT ? "" :
 				   " [output power limits]"),
-				  (list->channels[i].data & CHAN_HAS_CURVE ? "" :
+				  (chan->data & CHAN_HAS_CURVE ? "" :
 				   " [curve data]"),
-				  list->channels[i].index, list->channels[i].freq);
+				  chan->index, chan->freq);
 			continue;
 		}
 
-		tmp->channels[j].band = list->channels[i].band;
-		tmp->channels[j].center_freq = list->channels[i].freq;
+		tmp->channels[j].band = chan->band;
+		tmp->channels[j].center_freq = chan->freq;
 		j++;
 	}
 
@@ -291,7 +317,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
 		}
 	}
 
-	/* sort the list by the channel index */
+	/* sort the channel list by frequency */
 	sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
 	     p54_compare_channels, NULL);
 
@@ -410,33 +436,121 @@ static int p54_convert_rev1(struct ieee80211_hw *dev,
 static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2",
 	"Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
 
-static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
-			     u16 type)
+static int p54_parse_rssical(struct ieee80211_hw *dev,
+			     u8 *data, int len, u16 type)
 {
 	struct p54_common *priv = dev->priv;
-	int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
-	int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
-	int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
-	int i;
+	struct p54_rssi_db_entry *entry;
+	size_t db_len, entries;
+	int offset = 0, i;
+
+	if (type != PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
+		entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
+		if (len != sizeof(struct pda_rssi_cal_entry) * entries) {
+			wiphy_err(dev->wiphy, "rssical size mismatch.\n");
+			goto err_data;
+		}
+	} else {
+		/*
+		 * Some devices (Dell 1450 USB, Xbow 5GHz card, etc...)
+		 * have an empty two byte header.
+		 */
+		if (*((__le16 *)&data[offset]) == cpu_to_le16(0))
+			offset += 2;
 
-	if (len != (entry_size * num_entries)) {
-		wiphy_err(dev->wiphy,
-			  "unknown rssi calibration data packing type:(%x) len:%d.\n",
-			  type, len);
+		entries = (len - offset) /
+			sizeof(struct pda_rssi_cal_ext_entry);
 
-		print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
-				     data, len);
+		if ((len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
+		    entries <= 0) {
+			wiphy_err(dev->wiphy, "invalid rssi database.\n");
+			goto err_data;
+		}
+	}
 
-		wiphy_err(dev->wiphy, "please report this issue.\n");
-		return;
+	db_len = sizeof(*entry) * entries;
+	priv->rssi_db = kzalloc(db_len + sizeof(*priv->rssi_db), GFP_KERNEL);
+	if (!priv->rssi_db)
+		return -ENOMEM;
+
+	priv->rssi_db->offset = 0;
+	priv->rssi_db->entries = entries;
+	priv->rssi_db->entry_size = sizeof(*entry);
+	priv->rssi_db->len = db_len;
+
+	entry = (void *)((unsigned long)priv->rssi_db->data + priv->rssi_db->offset);
+	if (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
+		struct pda_rssi_cal_ext_entry *cal = (void *) &data[offset];
+
+		for (i = 0; i < entries; i++) {
+			entry[i].freq = le16_to_cpu(cal[i].freq);
+			entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
+			entry[i].add = (s16) le16_to_cpu(cal[i].add);
+		}
+	} else {
+		struct pda_rssi_cal_entry *cal = (void *) &data[offset];
+
+		for (i = 0; i < entries; i++) {
+			u16 freq;
+			switch (i) {
+			case IEEE80211_BAND_2GHZ:
+				freq = 2437;
+				break;
+			case IEEE80211_BAND_5GHZ:
+				freq = 5240;
+				break;
+			}
+
+			entry[i].freq = freq;
+			entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
+			entry[i].add = (s16) le16_to_cpu(cal[i].add);
+		}
 	}
 
-	for (i = 0; i < num_entries; i++) {
-		struct pda_rssi_cal_entry *cal = data +
-						 (offset + i * entry_size);
-		priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
-		priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
+	/* sort the list by channel frequency */
+	sort(entry, entries, sizeof(*entry), p54_compare_rssichan, NULL);
+	return 0;
+
+err_data:
+	wiphy_err(dev->wiphy,
+		  "rssi calibration data packing type:(%x) len:%d.\n",
+		  type, len);
+
+	print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, data, len);
+
+	wiphy_err(dev->wiphy, "please report this issue.\n");
+	return -EINVAL;
+}
+
+struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
+{
+	struct p54_rssi_db_entry *entry;
+	int i, found = -1;
+
+	if (!priv->rssi_db)
+		return &p54_rssi_default;
+
+	entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset);
+	for (i = 0; i < priv->rssi_db->entries; i++) {
+		if (!same_band(freq, entry[i].freq))
+			continue;
+
+		if (found == -1) {
+			found = i;
+			continue;
+		}
+
+		/* nearest match */
+		if (abs(freq - entry[i].freq) <
+		    abs(freq - entry[found].freq)) {
+			found = i;
+			continue;
+		} else {
+			break;
+		}
 	}
+
+	return found < 0 ? &p54_rssi_default : &entry[found];
 }
 
 static void p54_parse_default_country(struct ieee80211_hw *dev,
@@ -627,21 +741,30 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
 		case PDR_RSSI_LINEAR_APPROXIMATION:
 		case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
 		case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
-			p54_parse_rssical(dev, entry->data, data_len,
-					  le16_to_cpu(entry->code));
+			err = p54_parse_rssical(dev, entry->data, data_len,
+						le16_to_cpu(entry->code));
+			if (err)
+				goto err;
 			break;
-		case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: {
-			__le16 *src = (void *) entry->data;
-			s16 *dst = (void *) &priv->rssical_db;
+		case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: {
+			struct pda_custom_wrapper *pda = (void *) entry->data;
+			__le16 *src;
+			u16 *dst;
 			int i;
 
-			if (data_len != sizeof(priv->rssical_db)) {
-				err = -EINVAL;
-				goto err;
-			}
-			for (i = 0; i < sizeof(priv->rssical_db) /
-					sizeof(*src); i++)
+			if (priv->rssi_db || data_len < sizeof(*pda))
+				break;
+
+			priv->rssi_db = p54_convert_db(pda, data_len);
+			if (!priv->rssi_db)
+				break;
+
+			src = (void *) priv->rssi_db->data;
+			dst = (void *) priv->rssi_db->data;
+
+			for (i = 0; i < priv->rssi_db->entries; i++)
 				*(dst++) = (s16) le16_to_cpu(*(src++));
+
 			}
 			break;
 		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
@@ -717,6 +840,8 @@ good_eeprom:
 		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
 	}
 
+	priv->cur_rssi = &p54_rssi_default;
+
 	wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n",
 		   dev->wiphy->perm_addr, priv->version,
 		   p54_rf_chips[priv->rxhw]);
@@ -727,9 +852,11 @@ err:
 	kfree(priv->iq_autocal);
 	kfree(priv->output_limit);
 	kfree(priv->curve_data);
+	kfree(priv->rssi_db);
 	priv->iq_autocal = NULL;
 	priv->output_limit = NULL;
 	priv->curve_data = NULL;
+	priv->rssi_db = NULL;
 
 	wiphy_err(dev->wiphy, "eeprom parse failed!\n");
 	return err;
diff --git a/drivers/net/wireless/p54/eeprom.h b/drivers/net/wireless/p54/eeprom.h
index 9051aef..afde72b 100644
--- a/drivers/net/wireless/p54/eeprom.h
+++ b/drivers/net/wireless/p54/eeprom.h
@@ -81,6 +81,12 @@ struct pda_pa_curve_data {
 	u8 data[0];
 } __packed;
 
+struct pda_rssi_cal_ext_entry {
+	__le16 freq;
+	__le16 mul;
+	__le16 add;
+} __packed;
+
 struct pda_rssi_cal_entry {
 	__le16 mul;
 	__le16 add;
@@ -179,6 +185,7 @@ struct pda_custom_wrapper {
 
 /* used by our modificated eeprom image */
 #define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM		0xDEAD
+#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2		0xCAFF
 #define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM	0xBEEF
 #define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM		0xB05D
 
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 92b9b1f..2fab7d2 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -397,9 +397,9 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
 	union p54_scan_body_union *body;
 	struct p54_scan_tail_rate *rate;
 	struct pda_rssi_cal_entry *rssi;
+	struct p54_rssi_db_entry *rssi_data;
 	unsigned int i;
 	void *entry;
-	int band = priv->hw->conf.channel->band;
 	__le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq);
 
 	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
@@ -503,13 +503,14 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
 	}
 
 	rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
-	rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
-	rssi->add = cpu_to_le16(priv->rssical_db[band].add);
+	rssi_data = p54_rssi_find(priv, le16_to_cpu(freq));
+	rssi->mul = cpu_to_le16(rssi_data->mul);
+	rssi->add = cpu_to_le16(rssi_data->add);
 	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
 		/* Longbow frontend needs ever more */
 		rssi = (void *) skb_put(skb, sizeof(*rssi));
-		rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
-		rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
+		rssi->mul = cpu_to_le16(rssi_data->longbow_unkn);
+		rssi->add = cpu_to_le16(rssi_data->longbow_unk2);
 	}
 
 	if (priv->fw_var >= 0x509) {
@@ -523,6 +524,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell)
 	hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
 
 	p54_tx(priv, skb);
+	priv->cur_rssi = rssi_data;
 	return 0;
 
 err:
@@ -557,6 +559,7 @@ int p54_set_edcf(struct p54_common *priv)
 {
 	struct sk_buff *skb;
 	struct p54_edcf *edcf;
+	u8 rtd;
 
 	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),
 			    P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
@@ -573,9 +576,15 @@ int p54_set_edcf(struct p54_common *priv)
 		edcf->sifs = 0x0a;
 		edcf->eofpad = 0x06;
 	}
+	/*
+	 * calculate the extra round trip delay according to the
+	 * formula from 802.11-2007 17.3.8.6.
+	 */
+	rtd = 3 * priv->coverage_class;
+	edcf->slottime += rtd;
+	edcf->round_trip_delay = cpu_to_le16(rtd);
 	/* (see prism54/isl_oid.h for further details) */
 	edcf->frameburst = cpu_to_le16(0);
-	edcf->round_trip_delay = cpu_to_le16(0);
 	edcf->flags = 0;
 	memset(edcf->mapping, 0, sizeof(edcf->mapping));
 	memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h
index 04b63ec..eb581ab 100644
--- a/drivers/net/wireless/p54/lmac.h
+++ b/drivers/net/wireless/p54/lmac.h
@@ -526,7 +526,7 @@ int p54_init_leds(struct p54_common *priv);
 void p54_unregister_leds(struct p54_common *priv);
 
 /* xmit functions */
-int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb);
+void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb);
 int p54_tx_cancel(struct p54_common *priv, __le32 req_id);
 void p54_tx(struct p54_common *priv, struct sk_buff *skb);
 
@@ -551,6 +551,7 @@ int p54_upload_key(struct p54_common *priv, u8 algo, int slot,
 /* eeprom */
 int p54_download_eeprom(struct p54_common *priv, void *buf,
 			u16 offset, u16 len);
+struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *p, const u16 freq);
 
 /* utility */
 u8 *p54_find_ie(struct sk_buff *skb, u8 ie);
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index 622d27b..356e6bb 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -157,7 +157,7 @@ static int p54_beacon_update(struct p54_common *priv,
 	 * to cancel the old beacon template by hand, instead the firmware
 	 * will release the previous one through the feedback mechanism.
 	 */
-	WARN_ON(p54_tx_80211(priv->hw, beacon));
+	p54_tx_80211(priv->hw, beacon);
 	priv->tsf_high32 = 0;
 	priv->tsf_low32 = 0;
 
@@ -524,6 +524,59 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,
 	return 0;
 }
 
+static unsigned int p54_flush_count(struct p54_common *priv)
+{
+	unsigned int total = 0, i;
+
+	BUILD_BUG_ON(P54_QUEUE_NUM > ARRAY_SIZE(priv->tx_stats));
+
+	/*
+	 * Because the firmware has the sole control over any frames
+	 * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they
+	 * don't really count as pending or active.
+	 */
+	for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++)
+		total += priv->tx_stats[i].len;
+	return total;
+}
+
+static void p54_flush(struct ieee80211_hw *dev, bool drop)
+{
+	struct p54_common *priv = dev->priv;
+	unsigned int total, i;
+
+	/*
+	 * Currently, it wouldn't really matter if we wait for one second
+	 * or 15 minutes. But once someone gets around and completes the
+	 * TODOs [ancel stuck frames / reset device] in p54_work, it will
+	 * suddenly make sense to wait that long.
+	 */
+	i = P54_STATISTICS_UPDATE * 2 / 20;
+
+	/*
+	 * In this case no locking is required because as we speak the
+	 * queues have already been stopped and no new frames can sneak
+	 * up from behind.
+	 */
+	while ((total = p54_flush_count(priv) && i--)) {
+		/* waste time */
+		msleep(20);
+	}
+
+	WARN(total, "tx flush timeout, unresponsive firmware");
+}
+
+static void p54_set_coverage_class(struct ieee80211_hw *dev, u8 coverage_class)
+{
+	struct p54_common *priv = dev->priv;
+
+	mutex_lock(&priv->conf_mutex);
+	/* support all coverage class values as in 802.11-2007 Table 7-27 */
+	priv->coverage_class = clamp_t(u8, coverage_class, 0, 31);
+	p54_set_edcf(priv);
+	mutex_unlock(&priv->conf_mutex);
+}
+
 static const struct ieee80211_ops p54_ops = {
 	.tx			= p54_tx_80211,
 	.start			= p54_start,
@@ -536,11 +589,13 @@ static const struct ieee80211_ops p54_ops = {
 	.sta_remove		= p54_sta_add_remove,
 	.set_key		= p54_set_key,
 	.config			= p54_config,
+	.flush			= p54_flush,
 	.bss_info_changed	= p54_bss_info_changed,
 	.configure_filter	= p54_configure_filter,
 	.conf_tx		= p54_conf_tx,
 	.get_stats		= p54_get_stats,
 	.get_survey		= p54_get_survey,
+	.set_coverage_class	= p54_set_coverage_class,
 };
 
 struct ieee80211_hw *p54_init_common(size_t priv_data_len)
@@ -611,7 +666,7 @@ EXPORT_SYMBOL_GPL(p54_init_common);
 
 int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
 {
-	struct p54_common *priv = dev->priv;
+	struct p54_common __maybe_unused *priv = dev->priv;
 	int err;
 
 	err = ieee80211_register_hw(dev);
@@ -642,10 +697,12 @@ void p54_free_common(struct ieee80211_hw *dev)
 	kfree(priv->iq_autocal);
 	kfree(priv->output_limit);
 	kfree(priv->curve_data);
+	kfree(priv->rssi_db);
 	kfree(priv->used_rxkeys);
 	priv->iq_autocal = NULL;
 	priv->output_limit = NULL;
 	priv->curve_data = NULL;
+	priv->rssi_db = NULL;
 	priv->used_rxkeys = NULL;
 	ieee80211_free_hw(dev);
 }
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 43a3b2e..50730fc 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -116,7 +116,8 @@ struct p54_edcf_queue_param {
 	__le16 txop;
 } __packed;
 
-struct p54_rssi_linear_approximation {
+struct p54_rssi_db_entry {
+	u16 freq;
 	s16 mul;
 	s16 add;
 	s16 longbow_unkn;
@@ -197,13 +198,14 @@ struct p54_common {
 	u8 rx_diversity_mask;
 	u8 tx_diversity_mask;
 	unsigned int output_power;
+	struct p54_rssi_db_entry *cur_rssi;
 	int noise;
 	/* calibration, output power limit and rssi<->dBm conversation data */
 	struct pda_iq_autocal_entry *iq_autocal;
 	unsigned int iq_autocal_len;
 	struct p54_cal_database *curve_data;
 	struct p54_cal_database *output_limit;
-	struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
+	struct p54_cal_database *rssi_db;
 	struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS];
 
 	/* BBP/MAC state */
@@ -215,6 +217,7 @@ struct p54_common {
 	u32 tsf_low32, tsf_high32;
 	u32 basic_rate_mask;
 	u16 aid;
+	u8 coverage_class;
 	bool powersave_override;
 	__le32 beacon_req_id;
 	struct completion beacon_comp;
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h
index d592cbd..0b7bfb0 100644
--- a/drivers/net/wireless/p54/p54spi_eeprom.h
+++ b/drivers/net/wireless/p54/p54spi_eeprom.h
@@ -65,9 +65,10 @@ static unsigned char p54spi_eeprom[] = {
 0x03, 0x00, 0x00, 0x11,		/* PDR_ANTENNA_GAIN */
 	0x08, 0x08, 0x08, 0x08,
 
-0x09, 0x00, 0xad, 0xde,		/* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */
-	0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0a, 0x00, 0xff, 0xca,		/* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2 */
+	0x01, 0x00, 0x0a, 0x00,
+	0x00, 0x00, 0x0a, 0x00,
+		0x85, 0x09, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
 
 /* struct pda_custom_wrapper */
 0x10, 0x06, 0x5d, 0xb0,		/* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */
@@ -671,7 +672,7 @@ static unsigned char p54spi_eeprom[] = {
 	0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
 
 0x02, 0x00, 0x00, 0x00,		/* PDR_END */
-	0x67, 0x99,
+	0xb6, 0x04,
 };
 
 #endif /* P54SPI_EEPROM_H */
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index f618b96..7834c26 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -273,11 +273,9 @@ void p54_tx(struct p54_common *priv, struct sk_buff *skb)
 
 static int p54_rssi_to_dbm(struct p54_common *priv, int rssi)
 {
-	int band = priv->hw->conf.channel->band;
-
 	if (priv->rxhw != 5) {
-		return ((rssi * priv->rssical_db[band].mul) / 64 +
-			 priv->rssical_db[band].add) / 4;
+		return ((rssi * priv->cur_rssi->mul) / 64 +
+			 priv->cur_rssi->add) / 4;
 	} else {
 		/*
 		 * TODO: find the correct formula
@@ -369,7 +367,7 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
 	rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
 	priv->tsf_low32 = tsf32;
 
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
 		header_len += hdr->align[0];
@@ -698,7 +696,7 @@ static u8 p54_convert_algo(u32 cipher)
 	}
 }
 
-int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
+void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct p54_common *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -719,12 +717,8 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
 			    &hdr_flags, &aid, &burst_allowed);
 
 	if (p54_tx_qos_accounting_alloc(priv, skb, queue)) {
-		if (!IS_QOS_QUEUE(queue)) {
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		} else {
-			return NETDEV_TX_BUSY;
-		}
+		dev_kfree_skb_any(skb);
+		return;
 	}
 
 	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
@@ -867,5 +861,4 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
 	p54info->extra_len = extra_len;
 
 	p54_tx(priv, skb);
-	return NETDEV_TX_OK;
 }
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 6f383cd..f630552 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -97,6 +97,18 @@ config RT2800PCI_RT35XX
 	  Support for these devices is non-functional at the moment and is
 	  intended for testers and developers.
 
+config RT2800PCI_RT53XX
+       bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+         This adds support for rt53xx wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT5390
+
+         Support for these devices is non-functional at the moment and is
+         intended for testers and developers.
+
 endif
 
 config RT2500USB
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 54ca49a..329f328 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -46,7 +46,7 @@
  * These indirect registers work with busy bits,
  * and we will try maximal REGISTER_BUSY_COUNT times to access
  * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
+ * between each attempt. When the busy bit is still set at that time,
  * the access attempt is considered to have failed,
  * and we will print an error.
  */
@@ -305,9 +305,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
 		 * Enable synchronisation.
 		 */
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 	}
 
@@ -647,6 +645,11 @@ static void rt2400pci_start_queue(struct data_queue *queue)
 		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow the tbtt tasklet to be scheduled.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
 		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -708,6 +711,11 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
 		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
 		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
+		/*
+		 * Wait for possibly running tbtt tasklets.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
 		break;
 	default:
 		break;
@@ -771,7 +779,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
 	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
 	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
+	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
 	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
 
@@ -787,13 +795,13 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
 
-	entry_priv = rt2x00dev->bcn[1].entries[0].priv_data;
+	entry_priv = rt2x00dev->atim->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
 	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
 
-	entry_priv = rt2x00dev->bcn[0].entries[0].priv_data;
+	entry_priv = rt2x00dev->bcn->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
 	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
 			   entry_priv->desc_dma);
@@ -963,9 +971,9 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF) ||
-		   (state == STATE_RADIO_IRQ_OFF_ISR);
+	int mask = (state == STATE_RADIO_IRQ_OFF);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -974,12 +982,20 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	if (state == STATE_RADIO_IRQ_ON) {
 		rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
 		rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+
+		/*
+		 * Enable tasklets.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
 	}
 
 	/*
 	 * Only toggle the interrupts bits we are going to use.
 	 * Non-checked interrupt bits are disabled by default.
 	 */
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
 	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
 	rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
 	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
@@ -987,6 +1003,17 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
 	rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
 	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished before
+		 * disabling the interrupts.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+	}
 }
 
 static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1059,9 +1086,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2400pci_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2400pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1106,19 +1131,21 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 3, &word);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
 	rt2x00_desc_write(txd, 3, word);
 
 	rt2x00_desc_read(txd, 4, &word);
-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low);
+	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
 	rt2x00_desc_write(txd, 4, word);
@@ -1139,7 +1166,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_RTS,
 			   test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_desc_write(txd, 0, word);
@@ -1183,8 +1210,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
 	/*
 	 * Enable beaconing again.
 	 */
-	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-	rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
@@ -1253,7 +1278,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
 static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 			     const enum data_queue_qid queue_idx)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 	struct queue_entry_priv_pci *entry_priv;
 	struct queue_entry *entry;
 	struct txdone_entry_desc txdesc;
@@ -1289,57 +1314,68 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
-static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)
+static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg;
 
 	/*
-	 * Handle interrupts, walk through all bits
-	 * and run the tasks, the bits are checked in order of
-	 * priority.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 1 - Beacon timer expired interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
-		rt2x00lib_beacondone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
 
-	/*
-	 * 2 - Rx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_RXDONE))
-		rt2x00pci_rxdone(rt2x00dev);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 3 - Atim ring transmit done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
-		rt2400pci_txdone(rt2x00dev, QID_ATIM);
+static void rt2400pci_txstatus_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	u32 reg;
 
 	/*
-	 * 4 - Priority ring transmit done interrupt.
+	 * Handle all tx queues.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
-		rt2400pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2400pci_txdone(rt2x00dev, QID_ATIM);
+	rt2400pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2400pci_txdone(rt2x00dev, QID_AC_VI);
 
 	/*
-	 * 5 - Tx ring transmit done interrupt.
+	 * Enable all TXDONE interrupts again.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
-		rt2400pci_txdone(rt2x00dev, QID_AC_VI);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
-	return IRQ_HANDLED;
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt2400pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+}
+
+static void rt2400pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
 }
 
 static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
+	u32 reg, mask;
 
 	/*
 	 * Get the interrupt sources & saved to local variable.
@@ -1354,14 +1390,44 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalues for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
+	mask = reg;
 
-	/* Disable interrupts, will be enabled again in the interrupt thread. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_OFF_ISR);
+	/*
+	 * Schedule tasklets for interrupt handling.
+	 */
+	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
 
-	return IRQ_WAKE_THREAD;
+	if (rt2x00_get_field32(reg, CSR7_RXDONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
+		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+		/*
+		 * Mask out all txdone interrupts.
+		 */
+		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
+	}
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	reg |= mask;
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -1574,6 +1640,7 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 */
 	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1655,7 +1722,9 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 	.irq_handler		= rt2400pci_interrupt,
-	.irq_handler_thread	= rt2400pci_interrupt_thread,
+	.txstatus_tasklet	= rt2400pci_txstatus_tasklet,
+	.tbtt_tasklet		= rt2400pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt2400pci_rxdone_tasklet,
 	.probe_hw		= rt2400pci_probe_hw,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index a9ff26a..5827787 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -293,7 +293,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
 				  struct rt2x00intf_conf *conf,
 				  const unsigned int flags)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
+	struct data_queue *queue = rt2x00dev->bcn;
 	unsigned int bcn_preload;
 	u32 reg;
 
@@ -311,9 +311,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
 		 * Enable synchronisation.
 		 */
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 	}
 
@@ -737,6 +735,11 @@ static void rt2500pci_start_queue(struct data_queue *queue)
 		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow the tbtt tasklet to be scheduled.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
 		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -798,6 +801,11 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
 		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
 		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
+		/*
+		 * Wait for possibly running tbtt tasklets.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
 		break;
 	default:
 		break;
@@ -857,7 +865,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
 	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
 	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
+	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
 	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
 
@@ -873,13 +881,13 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
 
-	entry_priv = rt2x00dev->bcn[1].entries[0].priv_data;
+	entry_priv = rt2x00dev->atim->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
 	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
 
-	entry_priv = rt2x00dev->bcn[0].entries[0].priv_data;
+	entry_priv = rt2x00dev->bcn->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
 	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
 			   entry_priv->desc_dma);
@@ -1118,9 +1126,9 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF) ||
-		   (state == STATE_RADIO_IRQ_OFF_ISR);
+	int mask = (state == STATE_RADIO_IRQ_OFF);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -1129,12 +1137,20 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	if (state == STATE_RADIO_IRQ_ON) {
 		rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
 		rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+
+		/*
+		 * Enable tasklets.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
 	}
 
 	/*
 	 * Only toggle the interrupts bits we are going to use.
 	 * Non-checked interrupt bits are disabled by default.
 	 */
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
 	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
 	rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
 	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
@@ -1142,6 +1158,16 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
 	rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
 	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+	}
 }
 
 static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1214,9 +1240,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2500pci_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2500pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1263,10 +1287,12 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 3, &word);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 3, word);
 
 	rt2x00_desc_read(txd, 10, &word);
@@ -1291,7 +1317,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
 	rt2x00_set_field32(&word, TXD_W0_OFDM,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
 	rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
@@ -1337,8 +1363,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
 	/*
 	 * Enable beaconing again.
 	 */
-	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-	rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
@@ -1386,7 +1410,7 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry,
 static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 			     const enum data_queue_qid queue_idx)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 	struct queue_entry_priv_pci *entry_priv;
 	struct queue_entry *entry;
 	struct txdone_entry_desc txdesc;
@@ -1422,58 +1446,68 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 	}
 }
 
-static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance)
+static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg;
 
 	/*
-	 * Handle interrupts, walk through all bits
-	 * and run the tasks, the bits are checked in order of
-	 * priority.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 1 - Beacon timer expired interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
-		rt2x00lib_beacondone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
 
-	/*
-	 * 2 - Rx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_RXDONE))
-		rt2x00pci_rxdone(rt2x00dev);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 3 - Atim ring transmit done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
-		rt2500pci_txdone(rt2x00dev, QID_ATIM);
+static void rt2500pci_txstatus_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	u32 reg;
 
 	/*
-	 * 4 - Priority ring transmit done interrupt.
+	 * Handle all tx queues.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
-		rt2500pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2500pci_txdone(rt2x00dev, QID_ATIM);
+	rt2500pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2500pci_txdone(rt2x00dev, QID_AC_VI);
 
 	/*
-	 * 5 - Tx ring transmit done interrupt.
+	 * Enable all TXDONE interrupts again.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
-		rt2500pci_txdone(rt2x00dev, QID_AC_VI);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	return IRQ_HANDLED;
+static void rt2500pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+}
+
+static void rt2500pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
 }
 
 static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
+	u32 reg, mask;
 
 	/*
 	 * Get the interrupt sources & saved to local variable.
@@ -1488,14 +1522,42 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalues for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
+	mask = reg;
 
-	/* Disable interrupts, will be enabled again in the interrupt thread. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_OFF_ISR);
+	/*
+	 * Schedule tasklets for interrupt handling.
+	 */
+	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
 
-	return IRQ_WAKE_THREAD;
+	if (rt2x00_get_field32(reg, CSR7_RXDONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
+		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+		/*
+		 * Mask out all txdone interrupts.
+		 */
+		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
+	}
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	reg |= mask;
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -1896,6 +1958,7 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	 */
 	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1952,7 +2015,9 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 	.irq_handler		= rt2500pci_interrupt,
-	.irq_handler_thread	= rt2500pci_interrupt_thread,
+	.txstatus_tasklet	= rt2500pci_txstatus_tasklet,
+	.tbtt_tasklet		= rt2500pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt2500pci_rxdone_tasklet,
 	.probe_hw		= rt2500pci_probe_hw,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 6b3b1de4..979fe65 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -478,9 +478,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
 		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
 
 		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
 		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
-		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
 		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
 	}
 
@@ -1056,9 +1054,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2500usb_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1104,7 +1100,7 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
 	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
 			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
 	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
 	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
@@ -1118,10 +1114,12 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
@@ -1799,6 +1797,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
 	}
 	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 4c55e85..70b9abb 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)
  * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
+ * RF5390 2.4G 1T1R
  */
 #define RF2820				0x0001
 #define RF2850				0x0002
@@ -65,6 +66,7 @@
 #define RF3320				0x000b
 #define RF3322				0x000c
 #define RF3853				0x000d
+#define RF5390				0x5390
 
 /*
  * Chipset revisions.
@@ -77,6 +79,7 @@
 #define REV_RT3071E			0x0211
 #define REV_RT3090E			0x0211
 #define REV_RT3390E			0x0211
+#define REV_RT5390F			0x0502
 
 /*
  * Signal information.
@@ -121,6 +124,13 @@
 #define E2PROM_CSR_RELOAD		FIELD32(0x00000080)
 
 /*
+ * AUX_CTRL: Aux/PCI-E related configuration
+ */
+#define AUX_CTRL			0x10c
+#define AUX_CTRL_WAKE_PCIE_EN		FIELD32(0x00000002)
+#define AUX_CTRL_FORCE_PCIE_CLK		FIELD32(0x00000400)
+
+/*
  * OPT_14: Unknown register used by rt3xxx devices.
  */
 #define OPT_14_CSR			0x0114
@@ -270,6 +280,7 @@
 
 /*
  * GPIO_CTRL_CFG:
+ * GPIOD: GPIO direction, 0: Output, 1: Input
  */
 #define GPIO_CTRL_CFG			0x0228
 #define GPIO_CTRL_CFG_BIT0		FIELD32(0x00000001)
@@ -280,7 +291,14 @@
 #define GPIO_CTRL_CFG_BIT5		FIELD32(0x00000020)
 #define GPIO_CTRL_CFG_BIT6		FIELD32(0x00000040)
 #define GPIO_CTRL_CFG_BIT7		FIELD32(0x00000080)
-#define GPIO_CTRL_CFG_BIT8		FIELD32(0x00000100)
+#define GPIO_CTRL_CFG_GPIOD_BIT0	FIELD32(0x00000100)
+#define GPIO_CTRL_CFG_GPIOD_BIT1	FIELD32(0x00000200)
+#define GPIO_CTRL_CFG_GPIOD_BIT2	FIELD32(0x00000400)
+#define GPIO_CTRL_CFG_GPIOD_BIT3	FIELD32(0x00000800)
+#define GPIO_CTRL_CFG_GPIOD_BIT4	FIELD32(0x00001000)
+#define GPIO_CTRL_CFG_GPIOD_BIT5	FIELD32(0x00002000)
+#define GPIO_CTRL_CFG_GPIOD_BIT6	FIELD32(0x00004000)
+#define GPIO_CTRL_CFG_GPIOD_BIT7	FIELD32(0x00008000)
 
 /*
  * MCU_CMD_CFG
@@ -372,8 +390,12 @@
 
 /*
  * US_CYC_CNT
+ * BT_MODE_EN: Bluetooth mode enable
+ * CLOCK CYCLE: Clock cycle count in 1us.
+ * PCI:0x21, PCIE:0x7d, USB:0x1e
  */
 #define US_CYC_CNT			0x02a4
+#define US_CYC_CNT_BT_MODE_EN		FIELD32(0x00000100)
 #define US_CYC_CNT_CLOCK_CYCLE		FIELD32(0x000000ff)
 
 /*
@@ -442,7 +464,7 @@
  */
 #define	RF_CSR_CFG			0x0500
 #define RF_CSR_CFG_DATA			FIELD32(0x000000ff)
-#define RF_CSR_CFG_REGNUM		FIELD32(0x00001f00)
+#define RF_CSR_CFG_REGNUM		FIELD32(0x00003f00)
 #define RF_CSR_CFG_WRITE		FIELD32(0x00010000)
 #define RF_CSR_CFG_BUSY			FIELD32(0x00020000)
 
@@ -1132,8 +1154,8 @@
  * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
  * PROTECT_CTRL: Protection control frame type for CCK TX
  *               0:none, 1:RTS/CTS, 2:CTS-to-self
- * PROTECT_NAV: TXOP protection type for CCK TX
- *              0:none, 1:ShortNAVprotect, 2:LongNAVProtect
+ * PROTECT_NAV_SHORT: TXOP protection type for CCK TX with short NAV
+ * PROTECT_NAV_LONG: TXOP protection type for CCK TX with long NAV
  * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
  * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
  * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
@@ -1145,7 +1167,8 @@
 #define CCK_PROT_CFG			0x1364
 #define CCK_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
 #define CCK_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
-#define CCK_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define CCK_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define CCK_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #define CCK_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
 #define CCK_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
 #define CCK_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
@@ -1160,7 +1183,8 @@
 #define OFDM_PROT_CFG			0x1368
 #define OFDM_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
 #define OFDM_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
-#define OFDM_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define OFDM_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define OFDM_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #define OFDM_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
 #define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
 #define OFDM_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
@@ -1175,7 +1199,8 @@
 #define MM20_PROT_CFG			0x136c
 #define MM20_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
 #define MM20_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
-#define MM20_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define MM20_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define MM20_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #define MM20_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
 #define MM20_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
 #define MM20_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
@@ -1190,7 +1215,8 @@
 #define MM40_PROT_CFG			0x1370
 #define MM40_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
 #define MM40_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
-#define MM40_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define MM40_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define MM40_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #define MM40_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
 #define MM40_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
 #define MM40_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
@@ -1205,7 +1231,8 @@
 #define GF20_PROT_CFG			0x1374
 #define GF20_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
 #define GF20_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
-#define GF20_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define GF20_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define GF20_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #define GF20_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
 #define GF20_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
 #define GF20_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
@@ -1220,7 +1247,8 @@
 #define GF40_PROT_CFG			0x1378
 #define GF40_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)
 #define GF40_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000)
-#define GF40_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000)
+#define GF40_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define GF40_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #define GF40_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)
 #define GF40_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)
 #define GF40_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000)
@@ -1697,11 +1725,14 @@ struct mac_iveiv_entry {
  */
 
 /*
- * BBP 1: TX Antenna & Power
- * POWER: 0 - normal, 1 - drop tx power by 6dBm, 2 - drop tx power by 12dBm,
- *	3 - increase tx power by 6dBm
+ * BBP 1: TX Antenna & Power Control
+ * POWER_CTRL:
+ * 0 - normal,
+ * 1 - drop tx power by 6dBm,
+ * 2 - drop tx power by 12dBm,
+ * 3 - increase tx power by 6dBm
  */
-#define BBP1_TX_POWER			FIELD8(0x07)
+#define BBP1_TX_POWER_CTRL		FIELD8(0x07)
 #define BBP1_TX_ANTENNA			FIELD8(0x18)
 
 /*
@@ -1715,6 +1746,13 @@ struct mac_iveiv_entry {
  */
 #define BBP4_TX_BF			FIELD8(0x01)
 #define BBP4_BANDWIDTH			FIELD8(0x18)
+#define BBP4_MAC_IF_CTRL		FIELD8(0x40)
+
+/*
+ * BBP 109
+ */
+#define BBP109_TX0_POWER		FIELD8(0x0f)
+#define BBP109_TX1_POWER		FIELD8(0xf0)
 
 /*
  * BBP 138: Unknown
@@ -1725,6 +1763,11 @@ struct mac_iveiv_entry {
 #define BBP138_TX_DAC2			FIELD8(0x40)
 
 /*
+ * BBP 152: Rx Ant
+ */
+#define BBP152_RX_DEFAULT_ANT		FIELD8(0x80)
+
+/*
  * RFCSR registers
  * The wordsize of the RFCSR is 8 bits.
  */
@@ -1733,12 +1776,18 @@ struct mac_iveiv_entry {
  * RFCSR 1:
  */
 #define RFCSR1_RF_BLOCK_EN		FIELD8(0x01)
+#define RFCSR1_PLL_PD			FIELD8(0x02)
 #define RFCSR1_RX0_PD			FIELD8(0x04)
 #define RFCSR1_TX0_PD			FIELD8(0x08)
 #define RFCSR1_RX1_PD			FIELD8(0x10)
 #define RFCSR1_TX1_PD			FIELD8(0x20)
 
 /*
+ * RFCSR 2:
+ */
+#define RFCSR2_RESCAL_EN		FIELD8(0x80)
+
+/*
  * RFCSR 6:
  */
 #define RFCSR6_R1			FIELD8(0x03)
@@ -1750,6 +1799,11 @@ struct mac_iveiv_entry {
 #define RFCSR7_RF_TUNING		FIELD8(0x01)
 
 /*
+ * RFCSR 11:
+ */
+#define RFCSR11_R			FIELD8(0x03)
+
+/*
  * RFCSR 12:
  */
 #define RFCSR12_TX_POWER		FIELD8(0x1f)
@@ -1770,6 +1824,7 @@ struct mac_iveiv_entry {
 #define RFCSR17_TXMIXER_GAIN		FIELD8(0x07)
 #define RFCSR17_TX_LO1_EN		FIELD8(0x08)
 #define RFCSR17_R			FIELD8(0x20)
+#define RFCSR17_CODE                   FIELD8(0x7f)
 
 /*
  * RFCSR 20:
@@ -1802,9 +1857,33 @@ struct mac_iveiv_entry {
 /*
  * RFCSR 30:
  */
+#define RFCSR30_TX_H20M			FIELD8(0x02)
+#define RFCSR30_RX_H20M			FIELD8(0x04)
+#define RFCSR30_RX_VCM			FIELD8(0x18)
 #define RFCSR30_RF_CALIBRATION		FIELD8(0x80)
 
 /*
+ * RFCSR 31:
+ */
+#define RFCSR31_RX_AGC_FC		FIELD8(0x1f)
+#define RFCSR31_RX_H20M			FIELD8(0x20)
+
+/*
+ * RFCSR 38:
+ */
+#define RFCSR38_RX_LO1_EN		FIELD8(0x20)
+
+/*
+ * RFCSR 39:
+ */
+#define RFCSR39_RX_LO2_EN		FIELD8(0x80)
+
+/*
+ * RFCSR 49:
+ */
+#define RFCSR49_TX			FIELD8(0x3f)
+
+/*
  * RF registers
  */
 
@@ -1837,6 +1916,11 @@ struct mac_iveiv_entry {
  */
 
 /*
+ * Chip ID
+ */
+#define EEPROM_CHIP_ID			0x0000
+
+/*
  * EEPROM Version
  */
 #define EEPROM_VERSION			0x0001
@@ -1989,23 +2073,26 @@ struct mac_iveiv_entry {
 #define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)
 
 /*
- * EEPROM Maximum TX power values
+ * EEPROM EIRP Maximum TX power values(unit: dbm)
  */
-#define EEPROM_MAX_TX_POWER		0x0027
-#define EEPROM_MAX_TX_POWER_24GHZ	FIELD16(0x00ff)
-#define EEPROM_MAX_TX_POWER_5GHZ	FIELD16(0xff00)
+#define EEPROM_EIRP_MAX_TX_POWER	0x0027
+#define EEPROM_EIRP_MAX_TX_POWER_2GHZ	FIELD16(0x00ff)
+#define EEPROM_EIRP_MAX_TX_POWER_5GHZ	FIELD16(0xff00)
 
 /*
  * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
  * This is delta in 40MHZ.
- * VALUE: Tx Power dalta value (MAX=4)
+ * VALUE: Tx Power dalta value, MAX=4(unit: dbm)
  * TYPE: 1: Plus the delta value, 0: minus the delta value
- * TXPOWER: Enable:
+ * ENABLE: enable tx power compensation for 40BW
  */
 #define EEPROM_TXPOWER_DELTA		0x0028
-#define EEPROM_TXPOWER_DELTA_VALUE	FIELD16(0x003f)
-#define EEPROM_TXPOWER_DELTA_TYPE	FIELD16(0x0040)
-#define EEPROM_TXPOWER_DELTA_TXPOWER	FIELD16(0x0080)
+#define EEPROM_TXPOWER_DELTA_VALUE_2G	FIELD16(0x003f)
+#define EEPROM_TXPOWER_DELTA_TYPE_2G	FIELD16(0x0040)
+#define EEPROM_TXPOWER_DELTA_ENABLE_2G	FIELD16(0x0080)
+#define EEPROM_TXPOWER_DELTA_VALUE_5G	FIELD16(0x3f00)
+#define EEPROM_TXPOWER_DELTA_TYPE_5G	FIELD16(0x4000)
+#define EEPROM_TXPOWER_DELTA_ENABLE_5G	FIELD16(0x8000)
 
 /*
  * EEPROM TXPOWER 802.11BG
@@ -2058,6 +2145,7 @@ struct mac_iveiv_entry {
 #define MCU_LED_LED_POLARITY		0x54
 #define MCU_RADAR			0x60
 #define MCU_BOOT_SIGNAL			0x72
+#define MCU_ANT_SELECT			0X73
 #define MCU_BBP_SIGNAL			0x80
 #define MCU_POWER_SAVE			0x83
 
@@ -2202,4 +2290,9 @@ struct mac_iveiv_entry {
 #define TXPOWER_A_TO_DEV(__txpower) \
 	clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
 
+/*
+ *  Board's maximun TX power limitation
+ */
+#define EIRP_MAX_TX_POWER_LIMIT	0x50
+
 #endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 54917a2..2ee6ceb 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -400,8 +400,15 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,
 	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
 
-	if (rt2x00_is_pci(rt2x00dev))
+	if (rt2x00_is_pci(rt2x00dev)) {
+		if (rt2x00_rt(rt2x00dev, RT5390)) {
+			rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+			rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
+			rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
+			rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+		}
 		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
+	}
 
 	/*
 	 * Disable DMA, will be reenabled later when enabling
@@ -465,14 +472,15 @@ void rt2800_write_tx_data(struct queue_entry *entry,
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W0_AMPDU,
 			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags));
-	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density);
-	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop);
-	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
+	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY,
+			   txdesc->u.ht.mpdu_density);
+	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop);
+	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);
 	rt2x00_set_field32(&word, TXWI_W0_BW,
 			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,
 			   test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags));
-	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc);
+	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);
 	rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
 	rt2x00_desc_write(txwi, 0, word);
 
@@ -481,7 +489,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
 			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));
 	rt2x00_set_field32(&word, TXWI_W1_NSEQ,
 			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags));
-	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
+	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);
 	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
 			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
 			   txdesc->key_idx : 0xff);
@@ -674,7 +682,7 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)
 	 * confuse the rate control algortihm by providing clearly wrong
 	 * data.
 	 */
-	if (aggr == 1 && ampdu == 0 && real_mcs != mcs) {
+	if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
 		skbdesc->tx_rate_idx = real_mcs;
 		mcs = real_mcs;
 	}
@@ -744,7 +752,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
 		if (pid >= QID_RX)
 			continue;
 
-		queue = rt2x00queue_get_queue(rt2x00dev, pid);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
 		if (unlikely(!queue))
 			continue;
 
@@ -773,13 +781,14 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 	unsigned int beacon_base;
 	unsigned int padding_len;
-	u32 reg;
+	u32 orig_reg, reg;
 
 	/*
 	 * Disable beaconing while we are reloading the beacon data,
 	 * otherwise we might be sending out invalid data.
 	 */
 	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	orig_reg = reg;
 	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
 	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
@@ -810,7 +819,14 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	 * Write entire beacon with TXWI and padding to register.
 	 */
 	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-	skb_pad(entry->skb, padding_len);
+	if (padding_len && skb_pad(entry->skb, padding_len)) {
+		ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+		/* skb freed by skb_pad() on failure */
+		entry->skb = NULL;
+		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
+		return;
+	}
+
 	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
@@ -818,8 +834,6 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 	/*
 	 * Enable beaconing again.
 	 */
-	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
-	rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
 	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
 	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
@@ -831,8 +845,8 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 }
 EXPORT_SYMBOL_GPL(rt2800_write_beacon);
 
-static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
-				       unsigned int beacon_base)
+static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
+						unsigned int beacon_base)
 {
 	int i;
 
@@ -845,6 +859,33 @@ static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 }
 
+void rt2800_clear_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	u32 reg;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+	/*
+	 * Clear beacon.
+	 */
+	rt2800_clear_beacon_register(rt2x00dev,
+				     HW_BEACON_OFFSET(entry->entry_idx));
+
+	/*
+	 * Enabled beaconing again.
+	 */
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_clear_beacon);
+
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 const struct rt2x00debug rt2800_rt2x00debug = {
 	.owner	= THIS_MODULE,
@@ -1005,7 +1046,7 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
 
 	memset(&wcid_entry, 0, sizeof(wcid_entry));
 	if (crypto->cmd == SET_KEY)
-		memcpy(&wcid_entry, crypto->address, ETH_ALEN);
+		memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
 	rt2800_register_multiwrite(rt2x00dev, offset,
 				      &wcid_entry, sizeof(wcid_entry));
 }
@@ -1060,27 +1101,44 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
 
+static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
+{
+	int idx;
+	u32 offset, reg;
+
+	/*
+	 * Search for the first free pairwise key entry and return the
+	 * corresponding index.
+	 *
+	 * Make sure the WCID starts _after_ the last possible shared key
+	 * entry (>32).
+	 *
+	 * Since parts of the pairwise key table might be shared with
+	 * the beacon frame buffers 6 & 7 we should only write into the
+	 * first 222 entries.
+	 */
+	for (idx = 33; idx <= 222; idx++) {
+		offset = MAC_WCID_ATTR_ENTRY(idx);
+		rt2800_register_read(rt2x00dev, offset, &reg);
+		if (!reg)
+			return idx;
+	}
+	return -1;
+}
+
 int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 			       struct rt2x00lib_crypto *crypto,
 			       struct ieee80211_key_conf *key)
 {
 	struct hw_key_entry key_entry;
 	u32 offset;
+	int idx;
 
 	if (crypto->cmd == SET_KEY) {
-		/*
-		 * 1 pairwise key is possible per AID, this means that the AID
-		 * equals our hw_key_idx. Make sure the WCID starts _after_ the
-		 * last possible shared key entry.
-		 *
-		 * Since parts of the pairwise key table might be shared with
-		 * the beacon frame buffers 6 & 7 we should only write into the
-		 * first 222 entries.
-		 */
-		if (crypto->aid > (222 - 32))
+		idx = rt2800_find_pairwise_keyslot(rt2x00dev);
+		if (idx < 0)
 			return -ENOSPC;
-
-		key->hw_key_idx = 32 + crypto->aid;
+		key->hw_key_idx = idx;
 
 		memcpy(key_entry.key, crypto->key,
 		       sizeof(key_entry.key));
@@ -1155,29 +1213,11 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
-		 * Clear current synchronisation setup.
-		 */
-		rt2800_clear_beacon(rt2x00dev,
-				    HW_BEACON_OFFSET(intf->beacon->entry_idx));
-		/*
 		 * Enable synchronisation.
 		 */
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
-		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE,
-				   (conf->sync == TSF_SYNC_ADHOC ||
-				    conf->sync == TSF_SYNC_AP_NONE));
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-		/*
-		 * Enable pre tbtt interrupt for beaconing modes
-		 */
-		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
-		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER,
-				   (conf->sync == TSF_SYNC_AP_NONE));
-		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
-
 	}
 
 	if (flags & CONFIG_UPDATE_MAC) {
@@ -1361,10 +1401,32 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,
 }
 EXPORT_SYMBOL_GPL(rt2800_config_erp);
 
+static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
+				     enum antenna ant)
+{
+	u32 reg;
+	u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0;
+	u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;
+
+	if (rt2x00_is_pci(rt2x00dev)) {
+		rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+		rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK, eesk_pin);
+		rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+	} else if (rt2x00_is_usb(rt2x00dev))
+		rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
+				   eesk_pin, 0);
+
+	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+	rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0);
+	rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, gpio_bit3);
+	rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+}
+
 void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 {
 	u8 r1;
 	u8 r3;
+	u16 eeprom;
 
 	rt2800_bbp_read(rt2x00dev, 1, &r1);
 	rt2800_bbp_read(rt2x00dev, 3, &r3);
@@ -1372,7 +1434,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 	/*
 	 * Configure the TX antenna.
 	 */
-	switch ((int)ant->tx) {
+	switch (ant->tx_chain_num) {
 	case 1:
 		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
 		break;
@@ -1387,8 +1449,18 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 	/*
 	 * Configure the RX antenna.
 	 */
-	switch ((int)ant->rx) {
+	switch (ant->rx_chain_num) {
 	case 1:
+		if (rt2x00_rt(rt2x00dev, RT3070) ||
+		    rt2x00_rt(rt2x00dev, RT3090) ||
+		    rt2x00_rt(rt2x00dev, RT3390)) {
+			rt2x00_eeprom_read(rt2x00dev,
+					   EEPROM_NIC_CONF1, &eeprom);
+			if (rt2x00_get_field16(eeprom,
+						EEPROM_NIC_CONF1_ANT_DIVERSITY))
+				rt2800_set_ant_diversity(rt2x00dev,
+						rt2x00dev->default_ant.rx);
+		}
 		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
 		break;
 	case 2:
@@ -1434,13 +1506,13 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
 {
 	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
 
-	if (rt2x00dev->default_ant.tx == 1)
+	if (rt2x00dev->default_ant.tx_chain_num == 1)
 		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
 
-	if (rt2x00dev->default_ant.rx == 1) {
+	if (rt2x00dev->default_ant.rx_chain_num == 1) {
 		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
 		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
-	} else if (rt2x00dev->default_ant.rx == 2)
+	} else if (rt2x00dev->default_ant.rx_chain_num == 2)
 		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
 
 	if (rf->channel > 14) {
@@ -1526,6 +1598,105 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
 	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
 
+
+#define RT5390_POWER_BOUND     0x27
+#define RT5390_FREQ_OFFSET_BOUND       0x5f
+
+static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	u8 rfcsr;
+	u16 eeprom;
+
+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+	if (info->default_power1 > RT5390_POWER_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT5390_POWER_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+	rt2800_rfcsr_write(rt2x00dev, 49, 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_RX0_PD, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+	if (rt2x00dev->freq_offset > RT5390_FREQ_OFFSET_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
+				  RT5390_FREQ_OFFSET_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+	if (rf->channel <= 14) {
+		int idx = rf->channel-1;
+
+		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) {
+			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+				/* r55/r59 value array of channel 1~14 */
+				static const char r55_bt_rev[] = {0x83, 0x83,
+					0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
+					0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
+				static const char r59_bt_rev[] = {0x0e, 0x0e,
+					0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
+					0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
+
+				rt2800_rfcsr_write(rt2x00dev, 55,
+						   r55_bt_rev[idx]);
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_bt_rev[idx]);
+			} else {
+				static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
+					0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
+					0x88, 0x88, 0x86, 0x85, 0x84};
+
+				rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
+			}
+		} else {
+			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+				static const char r55_nonbt_rev[] = {0x23, 0x23,
+					0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
+					0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+				static const char r59_nonbt_rev[] = {0x07, 0x07,
+					0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+					0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
+
+				rt2800_rfcsr_write(rt2x00dev, 55,
+						   r55_nonbt_rev[idx]);
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_nonbt_rev[idx]);
+			} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+				static const char r59_non_bt[] = {0x8f, 0x8f,
+					0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
+					0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
+
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_non_bt[idx]);
+			}
+		}
+	}
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+}
+
 static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 				  struct ieee80211_conf *conf,
 				  struct rf_channel *rf,
@@ -1550,6 +1721,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	    rt2x00_rf(rt2x00dev, RF3052) ||
 	    rt2x00_rf(rt2x00dev, RF3320))
 		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+	else if (rt2x00_rf(rt2x00dev, RF5390))
+		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
 	else
 		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
 
@@ -1562,12 +1735,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	rt2800_bbp_write(rt2x00dev, 86, 0);
 
 	if (rf->channel <= 14) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
-			rt2800_bbp_write(rt2x00dev, 82, 0x62);
-			rt2800_bbp_write(rt2x00dev, 75, 0x46);
-		} else {
-			rt2800_bbp_write(rt2x00dev, 82, 0x84);
-			rt2800_bbp_write(rt2x00dev, 75, 0x50);
+		if (!rt2x00_rt(rt2x00dev, RT5390)) {
+			if (test_bit(CONFIG_EXTERNAL_LNA_BG,
+				     &rt2x00dev->flags)) {
+				rt2800_bbp_write(rt2x00dev, 82, 0x62);
+				rt2800_bbp_write(rt2x00dev, 75, 0x46);
+			} else {
+				rt2800_bbp_write(rt2x00dev, 82, 0x84);
+				rt2800_bbp_write(rt2x00dev, 75, 0x50);
+			}
 		}
 	} else {
 		rt2800_bbp_write(rt2x00dev, 82, 0xf2);
@@ -1587,13 +1763,13 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	tx_pin = 0;
 
 	/* Turn on unused PA or LNA when not using 1T or 1R */
-	if (rt2x00dev->default_ant.tx != 1) {
+	if (rt2x00dev->default_ant.tx_chain_num == 2) {
 		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
 		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
 	}
 
 	/* Turn on unused PA or LNA when not using 1T or 1R */
-	if (rt2x00dev->default_ant.rx != 1) {
+	if (rt2x00dev->default_ant.rx_chain_num == 2) {
 		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
 		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
 	}
@@ -1637,30 +1813,116 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
 }
 
+static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
+				      enum ieee80211_band band)
+{
+	u16 eeprom;
+	u8 comp_en;
+	u8 comp_type;
+	int comp_value;
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
+
+	if (eeprom == 0xffff)
+		return 0;
+
+	if (band == IEEE80211_BAND_2GHZ) {
+		comp_en = rt2x00_get_field16(eeprom,
+				 EEPROM_TXPOWER_DELTA_ENABLE_2G);
+		if (comp_en) {
+			comp_type = rt2x00_get_field16(eeprom,
+					   EEPROM_TXPOWER_DELTA_TYPE_2G);
+			comp_value = rt2x00_get_field16(eeprom,
+					    EEPROM_TXPOWER_DELTA_VALUE_2G);
+			if (!comp_type)
+				comp_value = -comp_value;
+		}
+	} else {
+		comp_en = rt2x00_get_field16(eeprom,
+				 EEPROM_TXPOWER_DELTA_ENABLE_5G);
+		if (comp_en) {
+			comp_type = rt2x00_get_field16(eeprom,
+					   EEPROM_TXPOWER_DELTA_TYPE_5G);
+			comp_value = rt2x00_get_field16(eeprom,
+					    EEPROM_TXPOWER_DELTA_VALUE_5G);
+			if (!comp_type)
+				comp_value = -comp_value;
+		}
+	}
+
+	return comp_value;
+}
+
+static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev,
+				     int is_rate_b,
+				     enum ieee80211_band band,
+				     int power_level,
+				     u8 txpower)
+{
+	u32 reg;
+	u16 eeprom;
+	u8 criterion;
+	u8 eirp_txpower;
+	u8 eirp_txpower_criterion;
+	u8 reg_limit;
+	int bw_comp = 0;
+
+	if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
+		return txpower;
+
+	if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+		bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band);
+
+	if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) {
+		/*
+		 * Check if eirp txpower exceed txpower_limit.
+		 * We use OFDM 6M as criterion and its eirp txpower
+		 * is stored at EEPROM_EIRP_MAX_TX_POWER.
+		 * .11b data rate need add additional 4dbm
+		 * when calculating eirp txpower.
+		 */
+		rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
+		criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
+
+		rt2x00_eeprom_read(rt2x00dev,
+				   EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+
+		if (band == IEEE80211_BAND_2GHZ)
+			eirp_txpower_criterion = rt2x00_get_field16(eeprom,
+						 EEPROM_EIRP_MAX_TX_POWER_2GHZ);
+		else
+			eirp_txpower_criterion = rt2x00_get_field16(eeprom,
+						 EEPROM_EIRP_MAX_TX_POWER_5GHZ);
+
+		eirp_txpower = eirp_txpower_criterion + (txpower - criterion) +
+				       (is_rate_b ? 4 : 0) + bw_comp;
+
+		reg_limit = (eirp_txpower > power_level) ?
+					(eirp_txpower - power_level) : 0;
+	} else
+		reg_limit = 0;
+
+	return txpower + bw_comp - reg_limit;
+}
+
 static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
-				  const int max_txpower)
+				  struct ieee80211_conf *conf)
 {
 	u8 txpower;
-	u8 max_value = (u8)max_txpower;
 	u16 eeprom;
-	int i;
+	int i, is_rate_b;
 	u32 reg;
 	u8 r1;
 	u32 offset;
+	enum ieee80211_band band = conf->channel->band;
+	int power_level = conf->power_level;
 
 	/*
-	 * set to normal tx power mode: +/- 0dBm
+	 * set to normal bbp tx power control mode: +/- 0dBm
 	 */
 	rt2800_bbp_read(rt2x00dev, 1, &r1);
-	rt2x00_set_field8(&r1, BBP1_TX_POWER, 0);
+	rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0);
 	rt2800_bbp_write(rt2x00dev, 1, r1);
-
-	/*
-	 * The eeprom contains the tx power values for each rate. These
-	 * values map to 100% tx power. Each 16bit word contains four tx
-	 * power values and the order is the same as used in the TX_PWR_CFG
-	 * registers.
-	 */
 	offset = TX_PWR_CFG_0;
 
 	for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {
@@ -1674,73 +1936,99 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i,
 				   &eeprom);
 
-		/* TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
+		is_rate_b = i ? 0 : 1;
+		/*
+		 * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
 		 * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE0);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0, txpower);
 
-		/* TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
+		/*
+		 * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
 		 * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE1);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1, txpower);
 
-		/* TX_PWR_CFG_0: 55MBS, TX_PWR_CFG_1: 48MBS,
+		/*
+		 * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,
 		 * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE2);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2, txpower);
 
-		/* TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,
+		/*
+		 * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,
 		 * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE3);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
 
 		/* read the next four txpower values */
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1,
 				   &eeprom);
 
-		/* TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,
+		is_rate_b = 0;
+		/*
+		 * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,
 		 * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE0);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4, txpower);
 
-		/* TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,
+		/*
+		 * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,
 		 * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE1);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5, txpower);
 
-		/* TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,
+		/*
+		 * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,
 		 * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE2);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6, txpower);
 
-		/* TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,
+		/*
+		 * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,
 		 * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE3);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7, txpower);
 
 		rt2800_register_write(rt2x00dev, offset, reg);
 
@@ -1799,11 +2087,13 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
 	/* Always recalculate LNA gain before changing configuration */
 	rt2800_config_lna_gain(rt2x00dev, libconf);
 
-	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 		rt2800_config_channel(rt2x00dev, libconf->conf,
 				      &libconf->rf, &libconf->channel);
+		rt2800_config_txpower(rt2x00dev, libconf->conf);
+	}
 	if (flags & IEEE80211_CONF_CHANGE_POWER)
-		rt2800_config_txpower(rt2x00dev, libconf->conf->power_level);
+		rt2800_config_txpower(rt2x00dev, libconf->conf);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt2800_config_retry_limit(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
@@ -1832,7 +2122,8 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
 		if (rt2x00_rt(rt2x00dev, RT3070) ||
 		    rt2x00_rt(rt2x00dev, RT3071) ||
 		    rt2x00_rt(rt2x00dev, RT3090) ||
-		    rt2x00_rt(rt2x00dev, RT3390))
+		    rt2x00_rt(rt2x00dev, RT3390) ||
+		    rt2x00_rt(rt2x00dev, RT5390))
 			return 0x1c + (2 * rt2x00dev->lna_gain);
 		else
 			return 0x2e + rt2x00dev->lna_gain;
@@ -1964,6 +2255,10 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f);
+	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
 	} else {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -2032,7 +2327,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
 	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
-	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);
 	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
 	rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
@@ -2045,7 +2340,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
 	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
-	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);
 	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
 	rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
@@ -2058,7 +2353,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
 	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
-	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);
 	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
 	rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
@@ -2071,7 +2366,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
 	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
-	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);
 	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
 	rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
@@ -2084,7 +2379,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
 	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
-	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);
 	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
 	rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
@@ -2097,7 +2392,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
 	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
-	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV, 1);
+	rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);
 	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
 	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
 	rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
@@ -2180,26 +2475,30 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
 					      wcid, sizeof(wcid));
 
-		rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1);
+		rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0);
 		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
 	}
 
 	/*
 	 * Clear all beacons
 	 */
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7);
 
 	if (rt2x00_is_usb(rt2x00dev)) {
 		rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
 		rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 30);
 		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
+	} else if (rt2x00_is_pcie(rt2x00dev)) {
+		rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+		rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
+		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
 	}
 
 	rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
@@ -2335,15 +2634,31 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		     rt2800_wait_bbp_ready(rt2x00dev)))
 		return -EACCES;
 
-	if (rt2800_is_305x_soc(rt2x00dev))
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_bbp_read(rt2x00dev, 4, &value);
+		rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
+		rt2800_bbp_write(rt2x00dev, 4, value);
+	}
+
+	if (rt2800_is_305x_soc(rt2x00dev) ||
+	    rt2x00_rt(rt2x00dev, RT5390))
 		rt2800_bbp_write(rt2x00dev, 31, 0x08);
 
 	rt2800_bbp_write(rt2x00dev, 65, 0x2c);
 	rt2800_bbp_write(rt2x00dev, 66, 0x38);
 
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
 		rt2800_bbp_write(rt2x00dev, 69, 0x16);
 		rt2800_bbp_write(rt2x00dev, 73, 0x12);
+	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_bbp_write(rt2x00dev, 69, 0x12);
+		rt2800_bbp_write(rt2x00dev, 73, 0x13);
+		rt2800_bbp_write(rt2x00dev, 75, 0x46);
+		rt2800_bbp_write(rt2x00dev, 76, 0x28);
+		rt2800_bbp_write(rt2x00dev, 77, 0x59);
 	} else {
 		rt2800_bbp_write(rt2x00dev, 69, 0x12);
 		rt2800_bbp_write(rt2x00dev, 73, 0x10);
@@ -2354,7 +2669,8 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt(rt2x00dev, RT3070) ||
 	    rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
-	    rt2x00_rt(rt2x00dev, RT3390)) {
+	    rt2x00_rt(rt2x00dev, RT3390) ||
+	    rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_bbp_write(rt2x00dev, 79, 0x13);
 		rt2800_bbp_write(rt2x00dev, 80, 0x05);
 		rt2800_bbp_write(rt2x00dev, 81, 0x33);
@@ -2366,35 +2682,62 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	}
 
 	rt2800_bbp_write(rt2x00dev, 82, 0x62);
-	rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 83, 0x7a);
+	else
+		rt2800_bbp_write(rt2x00dev, 83, 0x6a);
 
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
 		rt2800_bbp_write(rt2x00dev, 84, 0x19);
+	else if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 84, 0x9a);
 	else
 		rt2800_bbp_write(rt2x00dev, 84, 0x99);
 
-	rt2800_bbp_write(rt2x00dev, 86, 0x00);
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 86, 0x38);
+	else
+		rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
 	rt2800_bbp_write(rt2x00dev, 91, 0x04);
-	rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 92, 0x02);
+	else
+		rt2800_bbp_write(rt2x00dev, 92, 0x00);
 
 	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+	    rt2x00_rt(rt2x00dev, RT5390) ||
 	    rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 	else
 		rt2800_bbp_write(rt2x00dev, 103, 0x00);
 
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 104, 0x92);
+
 	if (rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 105, 0x01);
+	else if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 105, 0x3c);
 	else
 		rt2800_bbp_write(rt2x00dev, 105, 0x05);
-	rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 106, 0x03);
+	else
+		rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 128, 0x12);
 
 	if (rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
-	    rt2x00_rt(rt2x00dev, RT3390)) {
+	    rt2x00_rt(rt2x00dev, RT3390) ||
+	    rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_bbp_read(rt2x00dev, 138, &value);
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
@@ -2406,6 +2749,42 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_bbp_write(rt2x00dev, 138, value);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		int ant, div_mode;
+
+		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;
+
+		/* check if this is a Bluetooth combo card */
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) {
+			u32 reg;
+
+			rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT6, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 0);
+			if (ant == 0)
+				rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 1);
+			else if (ant == 1)
+				rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 1);
+			rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+		}
+
+		rt2800_bbp_read(rt2x00dev, 152, &value);
+		if (ant == 0)
+			rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
+		else
+			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);
+	}
 
 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
@@ -2436,6 +2815,10 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
 	rt2800_bbp_write(rt2x00dev, 4, bbp);
 
+	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);
+	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
 	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
 	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
 	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
@@ -2491,18 +2874,28 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
 	    !rt2x00_rt(rt2x00dev, RT3390) &&
+	    !rt2x00_rt(rt2x00dev, RT5390) &&
 	    !rt2800_is_305x_soc(rt2x00dev))
 		return 0;
 
 	/*
 	 * Init RF calibration.
 	 */
-	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
-	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-	msleep(1);
-	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
-	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
+		rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+		msleep(1);
+		rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
+		rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+	} else {
+		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+		msleep(1);
+		rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+	}
 
 	if (rt2x00_rt(rt2x00dev, RT3070) ||
 	    rt2x00_rt(rt2x00dev, RT3071) ||
@@ -2510,7 +2903,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
 		rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
 		rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
-		rt2800_rfcsr_write(rt2x00dev, 7, 0x70);
+		rt2800_rfcsr_write(rt2x00dev, 7, 0x60);
 		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
 		rt2800_rfcsr_write(rt2x00dev, 10, 0x41);
 		rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
@@ -2593,6 +2986,87 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
 		rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
 		return 0;
+	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+		rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
+		rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+		rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+		rt2800_rfcsr_write(rt2x00dev, 12, 0xc6);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+		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, 0x00);
+
+		rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+		rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 25, 0xc0);
+		rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+		rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+
+		rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+		rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+		rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+		rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+		rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 40, 0x4b);
+		rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+		rt2800_rfcsr_write(rt2x00dev, 42, 0xd2);
+		rt2800_rfcsr_write(rt2x00dev, 43, 0x9a);
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+		rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 46, 0x7b);
+		rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+		rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
+
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 53, 0x84);
+		rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+		rt2800_rfcsr_write(rt2x00dev, 55, 0x44);
+		rt2800_rfcsr_write(rt2x00dev, 56, 0x22);
+		rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+		rt2800_rfcsr_write(rt2x00dev, 59, 0x63);
+
+		rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
+		rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
 	}
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -2602,12 +3076,12 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
 	} else if (rt2x00_rt(rt2x00dev, RT3071) ||
 		   rt2x00_rt(rt2x00dev, RT3090)) {
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
+
 		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
 		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
 		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-		rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
-
 		rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
 		rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
 		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -2619,6 +3093,10 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 				rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
 		}
 		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+		rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+		rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
 	} else if (rt2x00_rt(rt2x00dev, RT3390)) {
 		rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
 		rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
@@ -2642,21 +3120,23 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15);
 	}
 
-	/*
-	 * Set back to initial state
-	 */
-	rt2800_bbp_write(rt2x00dev, 24, 0);
+	if (!rt2x00_rt(rt2x00dev, RT5390)) {
+		/*
+		 * Set back to initial state
+		 */
+		rt2800_bbp_write(rt2x00dev, 24, 0);
 
-	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
-	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+		rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+		rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
 
-	/*
-	 * set BBP back to BW20
-	 */
-	rt2800_bbp_read(rt2x00dev, 4, &bbp);
-	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
-	rt2800_bbp_write(rt2x00dev, 4, bbp);
+		/*
+		 * Set BBP back to BW20
+		 */
+		rt2800_bbp_read(rt2x00dev, 4, &bbp);
+		rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+		rt2800_bbp_write(rt2x00dev, 4, bbp);
+	}
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
 	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -2668,24 +3148,29 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
 	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
 
-	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
-	if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
-	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
-	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
-			rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
-	}
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
-	if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1)
-		rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
-				  rt2x00_get_field16(eeprom,
-						   EEPROM_TXMIXER_GAIN_BG_VAL));
-	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+	if (!rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
+		if (rt2x00_rt(rt2x00dev, RT3070) ||
+		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+			if (!test_bit(CONFIG_EXTERNAL_LNA_BG,
+				      &rt2x00dev->flags))
+				rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+		}
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
+		if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1)
+			rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+					rt2x00_get_field16(eeprom,
+						EEPROM_TXMIXER_GAIN_BG_VAL));
+		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+	}
 
 	if (rt2x00_rt(rt2x00dev, RT3090)) {
 		rt2800_bbp_read(rt2x00dev, 138, &bbp);
 
+		/*  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(&bbp, BBP138_RX_ADC1, 0);
@@ -2719,10 +3204,9 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
 	}
 
-	if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) {
+	if (rt2x00_rt(rt2x00dev, RT3070)) {
 		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
-		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
-		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E))
+		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
 			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
 		else
 			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
@@ -2732,6 +3216,20 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
+		rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
+
+		rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
+		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+	}
+
 	return 0;
 }
 
@@ -2810,10 +3308,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
 
 	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
 	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
-	rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
 	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
 	/* Wait for DMA, ignore error */
@@ -2823,9 +3318,6 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
 }
 EXPORT_SYMBOL_GPL(rt2800_disable_radio);
 
@@ -2986,13 +3478,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 				   default_lna_gain);
 	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word);
-	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER);
-	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
@@ -3009,10 +3494,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 
 	/*
-	 * Identify RF chipset.
+	 * Identify RF chipset by EEPROM value
+	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
+	 * RT53xx: defined in "EEPROM_CHIP_ID" field
 	 */
-	value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 	rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+	if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390)
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
+	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));
@@ -3024,7 +3514,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
 	    !rt2x00_rt(rt2x00dev, RT3390) &&
-	    !rt2x00_rt(rt2x00dev, RT3572)) {
+	    !rt2x00_rt(rt2x00dev, RT3572) &&
+	    !rt2x00_rt(rt2x00dev, RT5390)) {
 		ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
 		return -ENODEV;
 	}
@@ -3038,7 +3529,8 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	    !rt2x00_rf(rt2x00dev, RF3021) &&
 	    !rt2x00_rf(rt2x00dev, RF3022) &&
 	    !rt2x00_rf(rt2x00dev, RF3052) &&
-	    !rt2x00_rf(rt2x00dev, RF3320)) {
+	    !rt2x00_rf(rt2x00dev, RF3320) &&
+	    !rt2x00_rf(rt2x00dev, RF5390)) {
 		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
 		return -ENODEV;
 	}
@@ -3046,11 +3538,35 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Identify default antenna configuration.
 	 */
-	rt2x00dev->default_ant.tx =
+	rt2x00dev->default_ant.tx_chain_num =
 	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH);
-	rt2x00dev->default_ant.rx =
+	rt2x00dev->default_ant.rx_chain_num =
 	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
 
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+
+	if (rt2x00_rt(rt2x00dev, RT3070) ||
+	    rt2x00_rt(rt2x00dev, RT3090) ||
+	    rt2x00_rt(rt2x00dev, RT3390)) {
+		value = rt2x00_get_field16(eeprom,
+				EEPROM_NIC_CONF1_ANT_DIVERSITY);
+		switch (value) {
+		case 0:
+		case 1:
+		case 2:
+			rt2x00dev->default_ant.tx = ANTENNA_A;
+			rt2x00dev->default_ant.rx = ANTENNA_A;
+			break;
+		case 3:
+			rt2x00dev->default_ant.tx = ANTENNA_A;
+			rt2x00dev->default_ant.rx = ANTENNA_B;
+			break;
+		}
+	} else {
+		rt2x00dev->default_ant.tx = ANTENNA_A;
+		rt2x00dev->default_ant.rx = ANTENNA_A;
+	}
+
 	/*
 	 * Read frequency offset and RF programming sequence.
 	 */
@@ -3084,6 +3600,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
 #endif /* CONFIG_RT2X00_LIB_LEDS */
 
+	/*
+	 * Check if support EIRP tx power limit feature.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+
+	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
+					EIRP_MAX_TX_POWER_LIMIT)
+		__set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
@@ -3236,7 +3761,6 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	char *default_power1;
 	char *default_power2;
 	unsigned int i;
-	unsigned short max_power;
 	u16 eeprom;
 
 	/*
@@ -3303,7 +3827,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 		   rt2x00_rf(rt2x00dev, RF2020) ||
 		   rt2x00_rf(rt2x00dev, RF3021) ||
 		   rt2x00_rf(rt2x00dev, RF3022) ||
-		   rt2x00_rf(rt2x00dev, RF3320)) {
+		   rt2x00_rf(rt2x00dev, RF3320) ||
+		   rt2x00_rf(rt2x00dev, RF5390)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals_3x;
 	} else if (rt2x00_rf(rt2x00dev, RF3052)) {
@@ -3361,26 +3886,21 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 
 	spec->channels_info = info;
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom);
-	max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ);
 	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
 	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
 
 	for (i = 0; i < 14; i++) {
-		info[i].max_power = max_power;
-		info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]);
-		info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]);
+		info[i].default_power1 = default_power1[i];
+		info[i].default_power2 = default_power2[i];
 	}
 
 	if (spec->num_channels > 14) {
-		max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ);
 		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
 		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
 
 		for (i = 14; i < spec->num_channels; i++) {
-			info[i].max_power = max_power;
-			info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]);
-			info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]);
+			info[i].default_power1 = default_power1[i];
+			info[i].default_power2 = default_power2[i];
 		}
 	}
 
@@ -3472,7 +3992,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 	if (queue_idx >= 4)
 		return 0;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 
 	/* Update WMM TXOP register */
 	offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
@@ -3530,7 +4050,8 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf);
 
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size)
 {
 	int ret = 0;
 
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index e3c995a..0c92d86 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -156,6 +156,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
 
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
+void rt2800_clear_beacon(struct queue_entry *entry);
 
 extern const struct rt2x00debug rt2800_rt2x00debug;
 
@@ -198,7 +199,8 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 u64 rt2800_get_tsf(struct ieee80211_hw *hw);
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size);
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 		      struct survey_info *survey);
 
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 3b3f1e4..808073a 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -200,11 +200,22 @@ static void rt2800pci_start_queue(struct data_queue *queue)
 		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow beacon tasklets to be scheduled for periodic
+		 * beacon updates.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+		tasklet_enable(&rt2x00dev->pretbtt_tasklet);
+
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
+		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
 		break;
 	default:
 		break;
@@ -250,6 +261,16 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
+		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+
+		/*
+		 * Wait for tbtt tasklets to finish.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
+		tasklet_disable(&rt2x00dev->pretbtt_tasklet);
 		break;
 	default:
 		break;
@@ -397,9 +418,9 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
 static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_ON) ||
-		   (state == STATE_RADIO_IRQ_ON_ISR);
+	int mask = (state == STATE_RADIO_IRQ_ON);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -408,8 +429,17 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	if (state == STATE_RADIO_IRQ_ON) {
 		rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
 		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+		/*
+		 * Enable tasklets. The beacon related tasklets are
+		 * enabled when the beacon queue is started.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
+		tasklet_enable(&rt2x00dev->autowake_tasklet);
 	}
 
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
@@ -430,6 +460,17 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
 	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished before
+		 * disabling the interrupts.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+		tasklet_disable(&rt2x00dev->autowake_tasklet);
+	}
 }
 
 static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
@@ -452,6 +493,13 @@ static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+		rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
+		rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
+		rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+	}
+
 	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
@@ -475,39 +523,23 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
 
 static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
-	u32 reg;
-
-	rt2800_disable_radio(rt2x00dev);
-
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
-
-	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
-
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+	if (rt2x00_is_soc(rt2x00dev)) {
+		rt2800_disable_radio(rt2x00dev);
+		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+	}
 }
 
 static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 {
-	/*
-	 * Always put the device to sleep (even when we intend to wakeup!)
-	 * if the device is booting and wasn't asleep it will return
-	 * failure when attempting to wakeup.
-	 */
-	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
-
 	if (state == STATE_AWAKE) {
-		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
+		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
+	} else if (state == STATE_SLEEP) {
+		rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
+		rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
 	}
 
 	return 0;
@@ -538,9 +570,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2800pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -696,7 +726,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 
 	while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
 		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
-		if (qid >= QID_RX) {
+		if (unlikely(qid >= QID_RX)) {
 			/*
 			 * Unknown queue, this shouldn't happen. Just drop
 			 * this tx status.
@@ -706,7 +736,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 			break;
 		}
 
-		queue = rt2x00queue_get_queue(rt2x00dev, qid);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
 		if (unlikely(queue == NULL)) {
 			/*
 			 * The queue is NULL, this shouldn't happen. Stop
@@ -717,7 +747,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 			break;
 		}
 
-		if (rt2x00queue_empty(queue)) {
+		if (unlikely(rt2x00queue_empty(queue))) {
 			/*
 			 * The queue is empty. Stop processing here
 			 * and drop the tx status.
@@ -732,45 +762,59 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 	}
 }
 
-static void rt2800pci_txstatus_tasklet(unsigned long data)
+static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00_field32 irq_field)
 {
-	rt2800pci_txdone((struct rt2x00_dev *)data);
-}
-
-static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
-{
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg;
 
 	/*
-	 * 1 - Pre TBTT interrupt.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
-		rt2x00lib_pretbtt(rt2x00dev);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
+	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00_set_field32(&reg, irq_field, 1);
+	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 2 - Beacondone interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
-		rt2x00lib_beacondone(rt2x00dev);
+static void rt2800pci_txstatus_tasklet(unsigned long data)
+{
+	rt2800pci_txdone((struct rt2x00_dev *)data);
 
 	/*
-	 * 3 - Rx ring done interrupt.
+	 * No need to enable the tx status interrupt here as we always
+	 * leave it enabled to minimize the possibility of a tx status
+	 * register overflow. See comment in interrupt handler.
 	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
-		rt2x00pci_rxdone(rt2x00dev);
+}
 
-	/*
-	 * 4 - Auto wakeup interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
-		rt2800pci_wakeup(rt2x00dev);
+static void rt2800pci_pretbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_pretbtt(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+}
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
+static void rt2800pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+}
 
-	return IRQ_HANDLED;
+static void rt2800pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
+}
+
+static void rt2800pci_autowake_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2800pci_wakeup(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
 }
 
 static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
@@ -791,7 +835,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
 	 *
 	 * Furthermore we don't disable the TX_FIFO_STATUS
 	 * interrupt here but leave it enabled so that the TX_STA_FIFO
-	 * can also be read while the interrupt thread gets executed.
+	 * can also be read while the tx status tasklet gets executed.
 	 *
 	 * Since we have only one producer and one consumer we don't
 	 * need to lock the kfifo.
@@ -816,8 +860,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
 static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
-	irqreturn_t ret = IRQ_HANDLED;
+	u32 reg, mask;
 
 	/* Read status and ACK all interrupts */
 	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
@@ -829,38 +872,44 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
-		rt2800pci_txstatus_interrupt(rt2x00dev);
+	/*
+	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+	 * for interrupts and interrupt masks we can just use the value of
+	 * INT_SOURCE_CSR to create the interrupt mask.
+	 */
+	mask = ~reg;
 
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) ||
-	    rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) ||
-	    rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) ||
-	    rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) {
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+		rt2800pci_txstatus_interrupt(rt2x00dev);
 		/*
-		 * All other interrupts are handled in the interrupt thread.
-		 * Store irqvalue for use in the interrupt thread.
+		 * Never disable the TX_FIFO_STATUS interrupt.
 		 */
-		rt2x00dev->irqvalue[0] = reg;
+		rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+	}
 
-		/*
-		 * Disable interrupts, will be enabled again in the
-		 * interrupt thread.
-		*/
-		rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-						      STATE_RADIO_IRQ_OFF_ISR);
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
+		tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
 
-		/*
-		 * Leave the TX_FIFO_STATUS interrupt enabled to not lose any
-		 * tx status reports.
-		 */
-		rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-		rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
-		rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
 
-		ret = IRQ_WAKE_THREAD;
-	}
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
 
-	return ret;
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
+		tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	reg &= mask;
+	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -928,6 +977,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (!modparam_nohwcrypt)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -975,8 +1025,11 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = {
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler		= rt2800pci_interrupt,
-	.irq_handler_thread	= rt2800pci_interrupt_thread,
-	.txstatus_tasklet       = rt2800pci_txstatus_tasklet,
+	.txstatus_tasklet	= rt2800pci_txstatus_tasklet,
+	.pretbtt_tasklet	= rt2800pci_pretbtt_tasklet,
+	.tbtt_tasklet		= rt2800pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt2800pci_rxdone_tasklet,
+	.autowake_tasklet	= rt2800pci_autowake_tasklet,
 	.probe_hw		= rt2800pci_probe_hw,
 	.get_firmware_name	= rt2800pci_get_firmware_name,
 	.check_firmware		= rt2800_check_firmware,
@@ -996,6 +1049,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.write_tx_desc		= rt2800pci_write_tx_desc,
 	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
+	.clear_beacon		= rt2800_clear_beacon,
 	.fill_rxdone		= rt2800pci_fill_rxdone,
 	.config_shared_key	= rt2800_config_shared_key,
 	.config_pairwise_key	= rt2800_config_pairwise_key,
@@ -1079,6 +1133,9 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
 	{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) },
 #endif
+#ifdef CONFIG_RT2800PCI_RT53XX
+	{ PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+#endif
 	{ 0, }
 };
 #endif /* CONFIG_PCI */
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 197a36c..f1a9214 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -253,9 +253,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
@@ -567,6 +565,7 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -639,6 +638,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_data		= rt2800usb_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
+	.clear_beacon		= rt2800_clear_beacon,
 	.get_tx_data_len	= rt2800usb_get_tx_data_len,
 	.fill_rxdone		= rt2800usb_fill_rxdone,
 	.config_shared_key	= rt2800_config_shared_key,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 84aaf39..a3940d7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -189,6 +189,7 @@ struct rt2x00_chip {
 #define RT3572		0x3572
 #define RT3593		0x3593	/* PCIe */
 #define RT3883		0x3883	/* WSOC */
+#define RT5390         0x5390  /* 2.4GHz */
 
 	u16 rf;
 	u16 rev;
@@ -225,6 +226,8 @@ struct channel_info {
 struct antenna_setup {
 	enum antenna rx;
 	enum antenna tx;
+	u8 rx_chain_num;
+	u8 tx_chain_num;
 };
 
 /*
@@ -368,6 +371,7 @@ struct rt2x00_intf {
 	 * dedicated beacon entry.
 	 */
 	struct queue_entry *beacon;
+	bool enable_beacon;
 
 	/*
 	 * Actions that needed rescheduling.
@@ -463,7 +467,6 @@ struct rt2x00lib_crypto {
 	const u8 *address;
 
 	u32 bssidx;
-	u32 aid;
 
 	u8 key[16];
 	u8 tx_mic[8];
@@ -511,14 +514,13 @@ struct rt2x00lib_ops {
 	irq_handler_t irq_handler;
 
 	/*
-	 * Threaded Interrupt handlers.
-	 */
-	irq_handler_t irq_handler_thread;
-
-	/*
 	 * TX status tasklet handler.
 	 */
 	void (*txstatus_tasklet) (unsigned long data);
+	void (*pretbtt_tasklet) (unsigned long data);
+	void (*tbtt_tasklet) (unsigned long data);
+	void (*rxdone_tasklet) (unsigned long data);
+	void (*autowake_tasklet) (unsigned long data);
 
 	/*
 	 * Device init handlers.
@@ -573,6 +575,7 @@ struct rt2x00lib_ops {
 			       struct txentry_desc *txdesc);
 	void (*write_beacon) (struct queue_entry *entry,
 			      struct txentry_desc *txdesc);
+	void (*clear_beacon) (struct queue_entry *entry);
 	int (*get_tx_data_len) (struct queue_entry *entry);
 
 	/*
@@ -658,12 +661,15 @@ enum rt2x00_flags {
 	DRIVER_REQUIRE_L2PAD,
 	DRIVER_REQUIRE_TXSTATUS_FIFO,
 	DRIVER_REQUIRE_TASKLET_CONTEXT,
+	DRIVER_REQUIRE_SW_SEQNO,
+	DRIVER_REQUIRE_HT_TX_DESC,
 
 	/*
 	 * Driver features
 	 */
 	CONFIG_SUPPORT_HW_BUTTON,
 	CONFIG_SUPPORT_HW_CRYPTO,
+	CONFIG_SUPPORT_POWER_LIMIT,
 	DRIVER_SUPPORT_CONTROL_FILTERS,
 	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
 	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
@@ -788,10 +794,12 @@ struct rt2x00_dev {
 	 *  - Open ap interface count.
 	 *  - Open sta interface count.
 	 *  - Association count.
+	 *  - Beaconing enabled count.
 	 */
 	unsigned int intf_ap_count;
 	unsigned int intf_sta_count;
 	unsigned int intf_associated;
+	unsigned int intf_beaconing;
 
 	/*
 	 * Link quality
@@ -857,6 +865,13 @@ struct rt2x00_dev {
 	 */
 	struct ieee80211_low_level_stats low_level_stats;
 
+	/**
+	 * Work queue for all work which should not be placed
+	 * on the mac80211 workqueue (because of dependencies
+	 * between various work structures).
+	 */
+	struct workqueue_struct *workqueue;
+
 	/*
 	 * Scheduled work.
 	 * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
@@ -872,14 +887,13 @@ struct rt2x00_dev {
 	struct work_struct txdone_work;
 
 	/*
-	 * Data queue arrays for RX, TX and Beacon.
-	 * The Beacon array also contains the Atim queue
-	 * if that is supported by the device.
+	 * Data queue arrays for RX, TX, Beacon and ATIM.
 	 */
 	unsigned int data_queues;
 	struct data_queue *rx;
 	struct data_queue *tx;
 	struct data_queue *bcn;
+	struct data_queue *atim;
 
 	/*
 	 * Firmware image.
@@ -887,12 +901,6 @@ struct rt2x00_dev {
 	const struct firmware *fw;
 
 	/*
-	 * Interrupt values, stored between interrupt service routine
-	 * and interrupt thread routine.
-	 */
-	u32 irqvalue[2];
-
-	/*
 	 * FIFO for storing tx status reports between isr and tasklet.
 	 */
 	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
@@ -901,6 +909,15 @@ struct rt2x00_dev {
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
+	struct tasklet_struct pretbtt_tasklet;
+	struct tasklet_struct tbtt_tasklet;
+	struct tasklet_struct rxdone_tasklet;
+	struct tasklet_struct autowake_tasklet;
+
+	/*
+	 * Protect the interrupt mask register.
+	 */
+	spinlock_t irqmask_lock;
 };
 
 /*
@@ -1046,12 +1063,24 @@ void rt2x00queue_map_txskb(struct queue_entry *entry);
 void rt2x00queue_unmap_skb(struct queue_entry *entry);
 
 /**
- * rt2x00queue_get_queue - Convert queue index to queue pointer
+ * rt2x00queue_get_tx_queue - Convert tx queue index to queue pointer
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  * @queue: rt2x00 queue index (see &enum data_queue_qid).
+ *
+ * Returns NULL for non tx queues.
  */
-struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
-					 const enum data_queue_qid queue);
+static inline struct data_queue *
+rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev,
+			 const enum data_queue_qid queue)
+{
+	if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
+		return &rt2x00dev->tx[queue];
+
+	if (queue == QID_ATIM)
+		return rt2x00dev->atim;
+
+	return NULL;
+}
 
 /**
  * rt2x00queue_get_entry - Get queue entry where the given index points to.
@@ -1168,7 +1197,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry);
 /*
  * mac80211 handlers.
  */
-int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 int rt2x00mac_start(struct ieee80211_hw *hw);
 void rt2x00mac_stop(struct ieee80211_hw *hw);
 int rt2x00mac_add_interface(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 9597a03..9de9dbe 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -121,7 +121,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 		return;
 
 	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
-		rt2x00queue_update_beacon(rt2x00dev, vif, true);
+		rt2x00queue_update_beacon(rt2x00dev, vif);
 }
 
 static void rt2x00lib_intf_scheduled(struct work_struct *work)
@@ -174,7 +174,13 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
 	    vif->type != NL80211_IFTYPE_WDS)
 		return;
 
-	rt2x00queue_update_beacon(rt2x00dev, vif, true);
+	/*
+	 * Update the beacon without locking. This is safe on PCI devices
+	 * as they only update the beacon periodically here. This should
+	 * never be called for USB devices.
+	 */
+	WARN_ON(rt2x00_is_usb(rt2x00dev));
+	rt2x00queue_update_beacon_locked(rt2x00dev, vif);
 }
 
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -183,9 +189,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 		return;
 
 	/* send buffered bc/mc frames out for every bssid */
-	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_bc_buffer_iter,
-					    rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00lib_bc_buffer_iter,
+						   rt2x00dev);
 	/*
 	 * Devices with pre tbtt interrupt don't need to update the beacon
 	 * here as they will fetch the next beacon directly prior to
@@ -195,9 +201,9 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
 		return;
 
 	/* fetch next beacon */
-	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_beaconupdate_iter,
-					    rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00lib_beaconupdate_iter,
+						   rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
@@ -207,9 +213,9 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
 		return;
 
 	/* fetch next beacon */
-	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_beaconupdate_iter,
-					    rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00lib_beaconupdate_iter,
+						   rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
@@ -649,7 +655,10 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry,
 			      const int channel, const int tx_power,
 			      const int value)
 {
-	entry->center_freq = ieee80211_channel_to_frequency(channel);
+	/* XXX: this assumption about the band is wrong for 802.11j */
+	entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	entry->center_freq = ieee80211_channel_to_frequency(channel,
+							    entry->band);
 	entry->hw_value = value;
 	entry->max_power = tx_power;
 	entry->max_antenna_gain = 0xff;
@@ -812,15 +821,29 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
 				     GFP_KERNEL);
 		if (status)
 			return status;
+	}
 
-		/* tasklet for processing the tx status reports. */
-		if (rt2x00dev->ops->lib->txstatus_tasklet)
-			tasklet_init(&rt2x00dev->txstatus_tasklet,
-				     rt2x00dev->ops->lib->txstatus_tasklet,
-				     (unsigned long)rt2x00dev);
-
+	/*
+	 * Initialize tasklets if used by the driver. Tasklets are
+	 * disabled until the interrupts are turned on. The driver
+	 * has to handle that.
+	 */
+#define RT2X00_TASKLET_INIT(taskletname) \
+	if (rt2x00dev->ops->lib->taskletname) { \
+		tasklet_init(&rt2x00dev->taskletname, \
+			     rt2x00dev->ops->lib->taskletname, \
+			     (unsigned long)rt2x00dev); \
+		tasklet_disable(&rt2x00dev->taskletname); \
 	}
 
+	RT2X00_TASKLET_INIT(txstatus_tasklet);
+	RT2X00_TASKLET_INIT(pretbtt_tasklet);
+	RT2X00_TASKLET_INIT(tbtt_tasklet);
+	RT2X00_TASKLET_INIT(rxdone_tasklet);
+	RT2X00_TASKLET_INIT(autowake_tasklet);
+
+#undef RT2X00_TASKLET_INIT
+
 	/*
 	 * Register HW.
 	 */
@@ -949,6 +972,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 {
 	int retval = -ENOMEM;
 
+	spin_lock_init(&rt2x00dev->irqmask_lock);
 	mutex_init(&rt2x00dev->csr_mutex);
 
 	set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
@@ -973,8 +997,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 		    BIT(NL80211_IFTYPE_WDS);
 
 	/*
-	 * Initialize configuration work.
+	 * Initialize work.
 	 */
+	rt2x00dev->workqueue =
+	    alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0);
+	if (!rt2x00dev->workqueue) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
 
 	/*
@@ -1033,6 +1064,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
 	cancel_work_sync(&rt2x00dev->intf_work);
 	cancel_work_sync(&rt2x00dev->rxdone_work);
 	cancel_work_sync(&rt2x00dev->txdone_work);
+	destroy_workqueue(rt2x00dev->workqueue);
 
 	/*
 	 * Free the tx status fifo.
@@ -1043,6 +1075,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
 	 * Kill the tx status tasklet.
 	 */
 	tasklet_kill(&rt2x00dev->txstatus_tasklet);
+	tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+	tasklet_kill(&rt2x00dev->tbtt_tasklet);
+	tasklet_kill(&rt2x00dev->rxdone_tasklet);
+	tasklet_kill(&rt2x00dev->autowake_tasklet);
 
 	/*
 	 * Uninitialize device.
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c
index b7ad46e..ae1219d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ht.c
+++ b/drivers/net/wireless/rt2x00/rt2x00ht.c
@@ -38,12 +38,12 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
 
 	if (tx_info->control.sta)
-		txdesc->mpdu_density =
+		txdesc->u.ht.mpdu_density =
 		    tx_info->control.sta->ht_cap.ampdu_density;
 
-	txdesc->ba_size = 7;	/* FIXME: What value is needed? */
+	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
 
-	txdesc->stbc =
+	txdesc->u.ht.stbc =
 	    (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT;
 
 	/*
@@ -51,25 +51,24 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 	 * mcs rate to be used
 	 */
 	if (txrate->flags & IEEE80211_TX_RC_MCS) {
-		txdesc->mcs = txrate->idx;
+		txdesc->u.ht.mcs = txrate->idx;
 
 		/*
 		 * MIMO PS should be set to 1 for STA's using dynamic SM PS
 		 * when using more then one tx stream (>MCS7).
 		 */
-		if (tx_info->control.sta && txdesc->mcs > 7 &&
+		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
 		    ((tx_info->control.sta->ht_cap.cap &
 		      IEEE80211_HT_CAP_SM_PS) >>
 		     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
 		    WLAN_HT_CAP_SM_PS_DYNAMIC)
 			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
 	} else {
-		txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
 		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			txdesc->mcs |= 0x08;
+			txdesc->u.ht.mcs |= 0x08;
 	}
 
-
 	/*
 	 * This frame is eligible for an AMPDU, however, don't aggregate
 	 * frames that are intended to probe a specific tx rate.
@@ -79,14 +78,6 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags);
 
 	/*
-	 * Determine HT Mix/Greenfield rate mode
-	 */
-	if (txrate->flags & IEEE80211_TX_RC_MCS)
-		txdesc->rate_mode = RATE_MODE_HT_MIX;
-	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
-		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
-
-	/*
 	 * Set 40Mhz mode if necessary (for legacy rates this will
 	 * duplicate the frame to both channels).
 	 */
@@ -106,11 +97,11 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry,
 	 * for frames not transmitted with TXOP_HTTXOP
 	 */
 	if (ieee80211_is_mgmt(hdr->frame_control))
-		txdesc->txop = TXOP_BACKOFF;
+		txdesc->u.ht.txop = TXOP_BACKOFF;
 	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-		txdesc->txop = TXOP_SIFS;
+		txdesc->u.ht.txop = TXOP_SIFS;
 	else
-		txdesc->txop = TXOP_HTTXOP;
+		txdesc->u.ht.txop = TXOP_HTTXOP;
 }
 
 u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index a105c50..2d94cba 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -157,14 +157,30 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 			       bool local);
 
 /**
- * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware
+ * rt2x00queue_update_beacon - Send new beacon from mac80211
+ *	to hardware. Handles locking by itself (mutex).
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  * @vif: Interface for which the beacon should be updated.
- * @enable_beacon: Enable beaconing
  */
 int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif,
-			      const bool enable_beacon);
+			      struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_update_beacon_locked - Send new beacon from mac80211
+ *	to hardware. Caller needs to ensure locking.
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_clear_beacon - Clear beacon in hardware
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+			     struct ieee80211_vif *vif);
 
 /**
  * rt2x00queue_index_inc - Index incrementation function
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index bfda60e..c975b0a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -417,7 +417,8 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)
 	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
 		return;
 
-	schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
+	ieee80211_queue_delayed_work(rt2x00dev->hw,
+				     &link->watchdog_work, WATCHDOG_INTERVAL);
 }
 
 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -441,7 +442,9 @@ static void rt2x00link_watchdog(struct work_struct *work)
 	rt2x00dev->ops->lib->watchdog(rt2x00dev);
 
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-		schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
+		ieee80211_queue_delayed_work(rt2x00dev->hw,
+					     &link->watchdog_work,
+					     WATCHDOG_INTERVAL);
 }
 
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index f3da051..661c6ba 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -99,7 +99,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
 	return retval;
 }
 
-int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -116,13 +116,13 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		goto exit_fail;
 
 	/*
-	 * Determine which queue to put packet on.
+	 * Use the ATIM queue if appropriate and present.
 	 */
 	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
 	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
-		queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM);
-	else
-		queue = rt2x00queue_get_queue(rt2x00dev, qid);
+		qid = QID_ATIM;
+
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
 	if (unlikely(!queue)) {
 		ERROR(rt2x00dev,
 		      "Attempt to send packet over invalid queue %d.\n"
@@ -139,9 +139,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 * either RTS or CTS-to-self frame and handles everything
 	 * inside the hardware.
 	 */
-	if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
-						IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
-	    !rt2x00dev->ops->hw->set_rts_threshold) {
+	if (!rt2x00dev->ops->hw->set_rts_threshold &&
+	    (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
+						IEEE80211_TX_RC_USE_CTS_PROTECT))) {
 		if (rt2x00queue_available(queue) <= 1)
 			goto exit_fail;
 
@@ -149,18 +149,17 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 			goto exit_fail;
 	}
 
-	if (rt2x00queue_write_tx_frame(queue, skb, false))
+	if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
 		goto exit_fail;
 
 	if (rt2x00queue_threshold(queue))
 		rt2x00queue_pause_queue(queue);
 
-	return NETDEV_TX_OK;
+	return;
 
  exit_fail:
 	ieee80211_stop_queue(rt2x00dev->hw, qid);
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_tx);
 
@@ -191,7 +190,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
+	struct data_queue *queue = rt2x00dev->bcn;
 	struct queue_entry *entry = NULL;
 	unsigned int i;
 
@@ -519,11 +518,9 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 	crypto.cmd = cmd;
 
-	if (sta) {
-		/* some drivers need the AID */
-		crypto.aid = sta->aid;
+	if (sta)
 		crypto.address = sta->addr;
-	} else
+	else
 		crypto.address = bcast_addr;
 
 	if (crypto.cipher == CIPHER_TKIP)
@@ -617,11 +614,47 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 				      bss_conf->bssid);
 
 	/*
-	 * Update the beacon.
+	 * Update the beacon. This is only required on USB devices. PCI
+	 * devices fetch beacons periodically.
 	 */
-	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED))
-		rt2x00queue_update_beacon(rt2x00dev, vif,
-					  bss_conf->enable_beacon);
+	if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev))
+		rt2x00queue_update_beacon(rt2x00dev, vif);
+
+	/*
+	 * Start/stop beaconing.
+	 */
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		if (!bss_conf->enable_beacon && intf->enable_beacon) {
+			rt2x00queue_clear_beacon(rt2x00dev, vif);
+			rt2x00dev->intf_beaconing--;
+			intf->enable_beacon = false;
+
+			if (rt2x00dev->intf_beaconing == 0) {
+				/*
+				 * Last beaconing interface disabled
+				 * -> stop beacon queue.
+				 */
+				mutex_lock(&intf->beacon_skb_mutex);
+				rt2x00queue_stop_queue(rt2x00dev->bcn);
+				mutex_unlock(&intf->beacon_skb_mutex);
+			}
+
+
+		} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
+			rt2x00dev->intf_beaconing++;
+			intf->enable_beacon = true;
+
+			if (rt2x00dev->intf_beaconing == 1) {
+				/*
+				 * First beaconing interface enabled
+				 * -> start beacon queue.
+				 */
+				mutex_lock(&intf->beacon_skb_mutex);
+				rt2x00queue_start_queue(rt2x00dev->bcn);
+				mutex_unlock(&intf->beacon_skb_mutex);
+			}
+		}
+	}
 
 	/*
 	 * When the association status has changed we must reset the link
@@ -657,7 +690,7 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct data_queue *queue;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 	if (unlikely(!queue))
 		return -EINVAL;
 
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index ace0b66..4dd82b0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -160,10 +160,9 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Register interrupt handler.
 	 */
-	status = request_threaded_irq(rt2x00dev->irq,
-				      rt2x00dev->ops->lib->irq_handler,
-				      rt2x00dev->ops->lib->irq_handler_thread,
-				      IRQF_SHARED, rt2x00dev->name, rt2x00dev);
+	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);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index ca82b3a..4b3c70e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -221,14 +221,17 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
 	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
 	unsigned long irqflags;
 
-	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) ||
-	    unlikely(!tx_info->control.vif))
+	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+		return;
+
+	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+
+	if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
 		return;
 
 	/*
-	 * Hardware should insert sequence counter.
-	 * FIXME: We insert a software sequence counter first for
-	 * hardware that doesn't support hardware sequence counting.
+	 * The hardware is not able to insert a sequence number. Assign a
+	 * software generated one here.
 	 *
 	 * This is wrong because beacons are not getting sequence
 	 * numbers assigned properly.
@@ -246,7 +249,6 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
 
 	spin_unlock_irqrestore(&intf->seqlock, irqflags);
 
-	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
 }
 
 static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
@@ -260,6 +262,16 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
 	unsigned int duration;
 	unsigned int residual;
 
+	/*
+	 * Determine with what IFS priority this frame should be send.
+	 * Set ifs to IFS_SIFS when the this is not the first fragment,
+	 * or this fragment came after RTS/CTS.
+	 */
+	if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+		txdesc->u.plcp.ifs = IFS_BACKOFF;
+	else
+		txdesc->u.plcp.ifs = IFS_SIFS;
+
 	/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
 	data_length = entry->skb->len + 4;
 	data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);
@@ -268,12 +280,12 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
 	 * PLCP setup
 	 * Length calculation depends on OFDM/CCK rate.
 	 */
-	txdesc->signal = hwrate->plcp;
-	txdesc->service = 0x04;
+	txdesc->u.plcp.signal = hwrate->plcp;
+	txdesc->u.plcp.service = 0x04;
 
 	if (hwrate->flags & DEV_RATE_OFDM) {
-		txdesc->length_high = (data_length >> 6) & 0x3f;
-		txdesc->length_low = data_length & 0x3f;
+		txdesc->u.plcp.length_high = (data_length >> 6) & 0x3f;
+		txdesc->u.plcp.length_low = data_length & 0x3f;
 	} else {
 		/*
 		 * Convert length to microseconds.
@@ -288,18 +300,18 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
 			 * Check if we need to set the Length Extension
 			 */
 			if (hwrate->bitrate == 110 && residual <= 30)
-				txdesc->service |= 0x80;
+				txdesc->u.plcp.service |= 0x80;
 		}
 
-		txdesc->length_high = (duration >> 8) & 0xff;
-		txdesc->length_low = duration & 0xff;
+		txdesc->u.plcp.length_high = (duration >> 8) & 0xff;
+		txdesc->u.plcp.length_low = duration & 0xff;
 
 		/*
 		 * When preamble is enabled we should set the
 		 * preamble bit for the signal.
 		 */
 		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			txdesc->signal |= 0x08;
+			txdesc->u.plcp.signal |= 0x08;
 	}
 }
 
@@ -309,9 +321,9 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-	struct ieee80211_rate *rate =
-	    ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
-	const struct rt2x00_rate *hwrate;
+	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+	struct ieee80211_rate *rate;
+	const struct rt2x00_rate *hwrate = NULL;
 
 	memset(txdesc, 0, sizeof(*txdesc));
 
@@ -365,42 +377,42 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 
 	/*
 	 * Beacons and probe responses require the tsf timestamp
-	 * to be inserted into the frame, except for a frame that has been injected
-	 * through a monitor interface. This latter is needed for testing a
-	 * monitor interface.
+	 * to be inserted into the frame.
 	 */
-	if ((ieee80211_is_beacon(hdr->frame_control) ||
-	    ieee80211_is_probe_resp(hdr->frame_control)) &&
-	    (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
+	if (ieee80211_is_beacon(hdr->frame_control) ||
+	    ieee80211_is_probe_resp(hdr->frame_control))
 		__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
 
-	/*
-	 * Determine with what IFS priority this frame should be send.
-	 * Set ifs to IFS_SIFS when the this is not the first fragment,
-	 * or this fragment came after RTS/CTS.
-	 */
 	if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) &&
-	    !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) {
+	    !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags))
 		__set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags);
-		txdesc->ifs = IFS_BACKOFF;
-	} else
-		txdesc->ifs = IFS_SIFS;
 
 	/*
 	 * Determine rate modulation.
 	 */
-	hwrate = rt2x00_get_rate(rate->hw_value);
-	txdesc->rate_mode = RATE_MODE_CCK;
-	if (hwrate->flags & DEV_RATE_OFDM)
-		txdesc->rate_mode = RATE_MODE_OFDM;
+	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
+	else if (txrate->flags & IEEE80211_TX_RC_MCS)
+		txdesc->rate_mode = RATE_MODE_HT_MIX;
+	else {
+		rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
+		hwrate = rt2x00_get_rate(rate->hw_value);
+		if (hwrate->flags & DEV_RATE_OFDM)
+			txdesc->rate_mode = RATE_MODE_OFDM;
+		else
+			txdesc->rate_mode = RATE_MODE_CCK;
+	}
 
 	/*
 	 * Apply TX descriptor handling by components
 	 */
 	rt2x00crypto_create_tx_descriptor(entry, txdesc);
-	rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
 	rt2x00queue_create_tx_descriptor_seq(entry, txdesc);
-	rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
+
+	if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
+		rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+	else
+		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
 
 static int rt2x00queue_write_tx_data(struct queue_entry *entry,
@@ -566,13 +578,10 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	return 0;
 }
 
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif,
-			      const bool enable_beacon)
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+			     struct ieee80211_vif *vif)
 {
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	struct skb_frame_desc *skbdesc;
-	struct txentry_desc txdesc;
 
 	if (unlikely(!intf->beacon))
 		return -ENOBUFS;
@@ -584,17 +593,36 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
 	 */
 	rt2x00queue_free_skb(intf->beacon);
 
-	if (!enable_beacon) {
-		rt2x00queue_stop_queue(intf->beacon->queue);
-		mutex_unlock(&intf->beacon_skb_mutex);
-		return 0;
-	}
+	/*
+	 * Clear beacon (single bssid devices don't need to clear the beacon
+	 * since the beacon queue will get stopped anyway).
+	 */
+	if (rt2x00dev->ops->lib->clear_beacon)
+		rt2x00dev->ops->lib->clear_beacon(intf->beacon);
+
+	mutex_unlock(&intf->beacon_skb_mutex);
+
+	return 0;
+}
+
+int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+	struct skb_frame_desc *skbdesc;
+	struct txentry_desc txdesc;
+
+	if (unlikely(!intf->beacon))
+		return -ENOBUFS;
+
+	/*
+	 * Clean up the beacon skb.
+	 */
+	rt2x00queue_free_skb(intf->beacon);
 
 	intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
-	if (!intf->beacon->skb) {
-		mutex_unlock(&intf->beacon_skb_mutex);
+	if (!intf->beacon->skb)
 		return -ENOMEM;
-	}
 
 	/*
 	 * Copy all TX descriptor information into txdesc,
@@ -611,13 +639,25 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
 	skbdesc->entry = intf->beacon;
 
 	/*
-	 * Send beacon to hardware and enable beacon genaration..
+	 * Send beacon to hardware.
 	 */
 	rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);
 
+	return 0;
+
+}
+
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+			      struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+	int ret;
+
+	mutex_lock(&intf->beacon_skb_mutex);
+	ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
 	mutex_unlock(&intf->beacon_skb_mutex);
 
-	return 0;
+	return ret;
 }
 
 void rt2x00queue_for_each_entry(struct data_queue *queue,
@@ -665,29 +705,6 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
 
-struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
-					 const enum data_queue_qid queue)
-{
-	int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-
-	if (queue == QID_RX)
-		return rt2x00dev->rx;
-
-	if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
-		return &rt2x00dev->tx[queue];
-
-	if (!rt2x00dev->bcn)
-		return NULL;
-
-	if (queue == QID_BEACON)
-		return &rt2x00dev->bcn[0];
-	else if (queue == QID_ATIM && atim)
-		return &rt2x00dev->bcn[1];
-
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
-
 struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
 					  enum queue_index index)
 {
@@ -885,7 +902,7 @@ void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
 	 * The queue flush has failed...
 	 */
 	if (unlikely(!rt2x00queue_empty(queue)))
-		WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid);
+		WARNING(queue->rt2x00dev, "Queue %d failed to flush\n", queue->qid);
 
 	/*
 	 * Restore the queue to the previous status
@@ -1063,7 +1080,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)
 		goto exit;
 
 	if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
-		status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
+		status = rt2x00queue_alloc_entries(rt2x00dev->atim,
 						   rt2x00dev->ops->atim);
 		if (status)
 			goto exit;
@@ -1137,6 +1154,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
 	rt2x00dev->rx = queue;
 	rt2x00dev->tx = &queue[1];
 	rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues];
+	rt2x00dev->atim = req_atim ? &queue[2 + rt2x00dev->ops->tx_queues] : NULL;
 
 	/*
 	 * Initialize queue parameters.
@@ -1153,9 +1171,9 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
 	tx_queue_for_each(rt2x00dev, queue)
 		rt2x00queue_init(rt2x00dev, queue, qid++);
 
-	rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_BEACON);
+	rt2x00queue_init(rt2x00dev, rt2x00dev->bcn, QID_BEACON);
 	if (req_atim)
-		rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_ATIM);
+		rt2x00queue_init(rt2x00dev, rt2x00dev->atim, QID_ATIM);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index fab8e26..0c8b0c6 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -305,20 +305,27 @@ struct txentry_desc {
 	u16 length;
 	u16 header_length;
 
-	u16 length_high;
-	u16 length_low;
-	u16 signal;
-	u16 service;
-
-	u16 mcs;
-	u16 stbc;
-	u16 ba_size;
-	u16 rate_mode;
-	u16 mpdu_density;
+	union {
+		struct {
+			u16 length_high;
+			u16 length_low;
+			u16 signal;
+			u16 service;
+			enum ifs ifs;
+		} plcp;
+
+		struct {
+			u16 mcs;
+			u8 stbc;
+			u8 ba_size;
+			u8 mpdu_density;
+			enum txop txop;
+		} ht;
+	} u;
+
+	enum rate_modulation rate_mode;
 
 	short retry_limit;
-	short ifs;
-	short txop;
 
 	enum cipher cipher;
 	u16 key_idx;
diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h
index e8259ae..6f867ee 100644
--- a/drivers/net/wireless/rt2x00/rt2x00reg.h
+++ b/drivers/net/wireless/rt2x00/rt2x00reg.h
@@ -85,8 +85,6 @@ enum dev_state {
 	STATE_RADIO_OFF,
 	STATE_RADIO_IRQ_ON,
 	STATE_RADIO_IRQ_OFF,
-	STATE_RADIO_IRQ_ON_ISR,
-	STATE_RADIO_IRQ_OFF_ISR,
 };
 
 /*
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 1a9937d..fbe735f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -227,7 +227,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	 * Schedule the delayed work for reading the TX status
 	 * from the device.
 	 */
-	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
+	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
 static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
@@ -320,7 +320,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	 * Schedule the delayed work for reading the RX status
 	 * from the device.
 	 */
-	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
+	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
 }
 
 static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
@@ -429,7 +429,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue)
 		 * Schedule the completion handler manually, when this
 		 * worker function runs, it should cleanup the queue.
 		 */
-		ieee80211_queue_work(queue->rt2x00dev->hw, completion);
+		queue_work(queue->rt2x00dev->workqueue, completion);
 
 		/*
 		 * Wait for a little while to give the driver
@@ -453,7 +453,7 @@ static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
 	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
 		" invoke forced tx handler\n", queue->qid);
 
-	ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
+	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
 }
 
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 8de44dd..77e8113 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -551,26 +551,14 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00intf_conf *conf,
 				const unsigned int flags)
 {
-	unsigned int beacon_base;
 	u32 reg;
 
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
-		 * Clear current synchronisation setup.
-		 * For the Beacon base registers, we only need to clear
-		 * the first byte since that byte contains the VALID and OWNER
-		 * bits which (when set to 0) will invalidate the entire beacon.
-		 */
-		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-		rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
-
-		/*
 		 * Enable synchronisation.
 		 */
 		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 	}
 
@@ -1154,6 +1142,11 @@ static void rt61pci_start_queue(struct data_queue *queue)
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow the tbtt tasklet to be scheduled.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+
 		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
@@ -1233,6 +1226,11 @@ static void rt61pci_stop_queue(struct data_queue *queue)
 		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+		/*
+		 * Wait for possibly running tbtt tasklets.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
 		break;
 	default:
 		break;
@@ -1719,9 +1717,9 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
 static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF) ||
-		   (state == STATE_RADIO_IRQ_OFF_ISR);
+	int mask = (state == STATE_RADIO_IRQ_OFF);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -1733,12 +1731,21 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 
 		rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
 		rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
+
+		/*
+		 * Enable tasklets.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
+		tasklet_enable(&rt2x00dev->autowake_tasklet);
 	}
 
 	/*
 	 * Only toggle the interrupts bits we are going to use.
 	 * Non-checked interrupt bits are disabled by default.
 	 */
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
 	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
@@ -1758,6 +1765,17 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
 	rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
 	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+		tasklet_disable(&rt2x00dev->autowake_tasklet);
+	}
 }
 
 static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1833,9 +1851,7 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt61pci_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt61pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1882,10 +1898,12 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
@@ -1930,7 +1948,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_OFDM,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
@@ -1962,13 +1980,14 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
 	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	unsigned int beacon_base;
 	unsigned int padding_len;
-	u32 reg;
+	u32 orig_reg, reg;
 
 	/*
 	 * Disable beaconing while we are reloading the beacon data,
 	 * otherwise we might be sending out invalid data.
 	 */
 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	orig_reg = reg;
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -1986,7 +2005,14 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
 	 * Write entire beacon with descriptor and padding to register.
 	 */
 	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-	skb_pad(entry->skb, padding_len);
+	if (padding_len && skb_pad(entry->skb, padding_len)) {
+		ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+		/* skb freed by skb_pad() on failure */
+		entry->skb = NULL;
+		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+		return;
+	}
+
 	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 	rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
 				      entry_priv->desc, TXINFO_SIZE);
@@ -2002,8 +2028,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
 	 */
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
 
-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -2014,6 +2038,32 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
 	entry->skb = NULL;
 }
 
+static void rt61pci_clear_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	u32 reg;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+	/*
+	 * Clear beacon.
+	 */
+	rt2x00pci_register_write(rt2x00dev,
+				 HW_BEACON_OFFSET(entry->entry_idx), 0);
+
+	/*
+	 * Enable beaconing again.
+	 */
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+}
+
 /*
  * RX control handlers
  */
@@ -2078,9 +2128,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
 
 		/*
-		 * FIXME: Legacy driver indicates that the frame does
-		 * contain the Michael Mic. Unfortunately, in rt2x00
-		 * the MIC seems to be missing completely...
+		 * The hardware has already checked the Michael Mic and has
+		 * stripped it from the frame. Signal this to mac80211.
 		 */
 		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
 
@@ -2143,7 +2192,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 		 * queue identication number.
 		 */
 		type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
-		queue = rt2x00queue_get_queue(rt2x00dev, type);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, type);
 		if (unlikely(!queue))
 			continue;
 
@@ -2211,61 +2260,77 @@ static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)
 	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance)
+static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				     struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
-	u32 reg_mcu = rt2x00dev->irqvalue[1];
+	u32 reg;
 
 	/*
-	 * Handle interrupts, walk through all bits
-	 * and run the tasks, the bits are checked in order of
-	 * priority.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 1 - Rx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
-		rt2x00pci_rxdone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
-	/*
-	 * 2 - Tx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE))
-		rt61pci_txdone(rt2x00dev);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 3 - Handle MCU command done.
-	 */
-	if (reg_mcu)
-		rt2x00pci_register_write(rt2x00dev,
-					 M2H_CMD_DONE_CSR, 0xffffffff);
+static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
+					 struct rt2x00_field32 irq_field)
+{
+	u32 reg;
 
 	/*
-	 * 4 - MCU Autowakeup interrupt.
+	 * Enable a single MCU interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
-	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
-		rt61pci_wakeup(rt2x00dev);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 5 - Beacon done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
-		rt2x00lib_beacondone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
-	return IRQ_HANDLED;
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt61pci_txstatus_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt61pci_txdone(rt2x00dev);
+	rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
+}
+
+static void rt61pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
+}
+
+static void rt61pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
 }
 
+static void rt61pci_autowake_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt61pci_wakeup(rt2x00dev);
+	rt2x00pci_register_write(rt2x00dev,
+				 M2H_CMD_DONE_CSR, 0xffffffff);
+	rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
+}
 
 static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg_mcu;
-	u32 reg;
+	u32 reg_mcu, mask_mcu;
+	u32 reg, mask;
 
 	/*
 	 * Get the interrupt sources & saved to local variable.
@@ -2283,14 +2348,46 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalues for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
-	rt2x00dev->irqvalue[1] = reg_mcu;
+	/*
+	 * Schedule tasklets for interrupt handling.
+	 */
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE))
+		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
+		tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+	/*
+	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+	 * for interrupts and interrupt masks we can just use the value of
+	 * INT_SOURCE_CSR to create the interrupt mask.
+	 */
+	mask = reg;
+	mask_mcu = reg_mcu;
 
-	/* Disable interrupts, will be enabled again in the interrupt thread. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_OFF_ISR);
-	return IRQ_WAKE_THREAD;
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	reg |= mask;
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+
+	rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+	reg |= mask_mcu;
+	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -2819,7 +2916,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 	if (queue_idx >= 4)
 		return 0;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 
 	/* Update WMM TXOP register */
 	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
@@ -2884,7 +2981,10 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 	.irq_handler		= rt61pci_interrupt,
-	.irq_handler_thread	= rt61pci_interrupt_thread,
+	.txstatus_tasklet	= rt61pci_txstatus_tasklet,
+	.tbtt_tasklet		= rt61pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt61pci_rxdone_tasklet,
+	.autowake_tasklet	= rt61pci_autowake_tasklet,
 	.probe_hw		= rt61pci_probe_hw,
 	.get_firmware_name	= rt61pci_get_firmware_name,
 	.check_firmware		= rt61pci_check_firmware,
@@ -2903,6 +3003,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 	.stop_queue		= rt61pci_stop_queue,
 	.write_tx_desc		= rt61pci_write_tx_desc,
 	.write_beacon		= rt61pci_write_beacon,
+	.clear_beacon		= rt61pci_clear_beacon,
 	.fill_rxdone		= rt61pci_fill_rxdone,
 	.config_shared_key	= rt61pci_config_shared_key,
 	.config_pairwise_key	= rt61pci_config_pairwise_key,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 029be3c..02f1148 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -502,26 +502,14 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
 				struct rt2x00intf_conf *conf,
 				const unsigned int flags)
 {
-	unsigned int beacon_base;
 	u32 reg;
 
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
-		 * Clear current synchronisation setup.
-		 * For the Beacon base registers we only need to clear
-		 * the first byte since that byte contains the VALID and OWNER
-		 * bits which (when set to 0) will invalidate the entire beacon.
-		 */
-		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-		rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
-
-		/*
 		 * Enable synchronisation.
 		 */
 		rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 	}
 
@@ -1440,9 +1428,7 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt73usb_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1488,7 +1474,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_OFDM,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
@@ -1513,10 +1499,12 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
@@ -1547,13 +1535,14 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	unsigned int beacon_base;
 	unsigned int padding_len;
-	u32 reg;
+	u32 orig_reg, reg;
 
 	/*
 	 * Disable beaconing while we are reloading the beacon data,
 	 * otherwise we might be sending out invalid data.
 	 */
 	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	orig_reg = reg;
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -1577,7 +1566,14 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
 	 * Write entire beacon with descriptor and padding to register.
 	 */
 	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-	skb_pad(entry->skb, padding_len);
+	if (padding_len && skb_pad(entry->skb, padding_len)) {
+		ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+		/* skb freed by skb_pad() on failure */
+		entry->skb = NULL;
+		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+		return;
+	}
+
 	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 	rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				      entry->skb->len + padding_len);
@@ -1590,8 +1586,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
 	 */
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
 
-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -1602,6 +1596,33 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
 	entry->skb = NULL;
 }
 
+static void rt73usb_clear_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	unsigned int beacon_base;
+	u32 reg;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+	/*
+	 * Clear beacon.
+	 */
+	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+	rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
+
+	/*
+	 * Enable beaconing again.
+	 */
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+}
+
 static int rt73usb_get_tx_data_len(struct queue_entry *entry)
 {
 	int length;
@@ -1698,9 +1719,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
 
 		/*
-		 * FIXME: Legacy driver indicates that the frame does
-		 * contain the Michael Mic. Unfortunately, in rt2x00
-		 * the MIC seems to be missing completely...
+		 * The hardware has already checked the Michael Mic and has
+		 * stripped it from the frame. Signal this to mac80211.
 		 */
 		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
 
@@ -2229,7 +2249,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 	if (queue_idx >= 4)
 		return 0;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 
 	/* Update WMM TXOP register */
 	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
@@ -2313,6 +2333,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
 	.flush_queue		= rt2x00usb_flush_queue,
 	.write_tx_desc		= rt73usb_write_tx_desc,
 	.write_beacon		= rt73usb_write_beacon,
+	.clear_beacon		= rt73usb_clear_beacon,
 	.get_tx_data_len	= rt73usb_get_tx_data_len,
 	.fill_rxdone		= rt73usb_fill_rxdone,
 	.config_shared_key	= rt73usb_config_shared_key,
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 5851cbc..80db5ca 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -146,7 +146,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
 			rx_status.freq = dev->conf.channel->center_freq;
 			rx_status.band = dev->conf.channel->band;
 			rx_status.mactime = le64_to_cpu(entry->tsft);
-			rx_status.flag |= RX_FLAG_TSFT;
+			rx_status.flag |= RX_FLAG_MACTIME_MPDU;
 			if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
 				rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 
@@ -240,7 +240,7 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -321,8 +321,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
-
-	return 0;
 }
 
 void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam)
@@ -687,7 +685,6 @@ static void rtl8180_beacon_work(struct work_struct *work)
 	struct ieee80211_hw *dev = vif_priv->dev;
 	struct ieee80211_mgmt *mgmt;
 	struct sk_buff *skb;
-	int err = 0;
 
 	/* don't overflow the tx ring */
 	if (ieee80211_queue_stopped(dev, 0))
@@ -708,8 +705,7 @@ static void rtl8180_beacon_work(struct work_struct *work)
 	/* TODO: use actual beacon queue */
 	skb_set_queue_mapping(skb, 0);
 
-	err = rtl8180_tx(dev, skb);
-	WARN_ON(err);
+	rtl8180_tx(dev, skb);
 
 resched:
 	/*
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 6b82cac..1e0be14 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -227,7 +227,7 @@ static void rtl8187_tx_cb(struct urb *urb)
 	}
 }
 
-static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -241,7 +241,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
 	flags = skb->len;
@@ -309,8 +309,6 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 		kfree_skb(skb);
 	}
 	usb_free_urb(urb);
-
-	return NETDEV_TX_OK;
 }
 
 static void rtl8187_rx_cb(struct urb *urb)
@@ -373,7 +371,7 @@ static void rtl8187_rx_cb(struct urb *urb)
 	rx_status.rate_idx = rate;
 	rx_status.freq = dev->conf.channel->center_freq;
 	rx_status.band = dev->conf.channel->band;
-	rx_status.flag |= RX_FLAG_TSFT;
+	rx_status.flag |= RX_FLAG_MACTIME_MPDU;
 	if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
 		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -871,23 +869,35 @@ static void rtl8187_work(struct work_struct *work)
 	/* The RTL8187 returns the retry count through register 0xFFFA. In
 	 * addition, it appears to be a cumulative retry count, not the
 	 * value for the current TX packet. When multiple TX entries are
-	 * queued, the retry count will be valid for the last one in the queue.
-	 * The "error" should not matter for purposes of rate setting. */
+	 * waiting in the queue, the retry count will be the total for all.
+	 * The "error" may matter for purposes of rate setting, but there is
+	 * no other choice with this hardware.
+	 */
 	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
 				    work.work);
 	struct ieee80211_tx_info *info;
 	struct ieee80211_hw *dev = priv->dev;
 	static u16 retry;
 	u16 tmp;
+	u16 avg_retry;
+	int length;
 
 	mutex_lock(&priv->conf_mutex);
 	tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA);
+	length = skb_queue_len(&priv->b_tx_status.queue);
+	if (unlikely(!length))
+		length = 1;
+	if (unlikely(tmp < retry))
+		tmp = retry;
+	avg_retry = (tmp - retry) / length;
 	while (skb_queue_len(&priv->b_tx_status.queue) > 0) {
 		struct sk_buff *old_skb;
 
 		old_skb = skb_dequeue(&priv->b_tx_status.queue);
 		info = IEEE80211_SKB_CB(old_skb);
-		info->status.rates[0].count = tmp - retry + 1;
+		info->status.rates[0].count = avg_retry + 1;
+		if (info->status.rates[0].count > RETRY_COUNT)
+			info->flags &= ~IEEE80211_TX_STAT_ACK;
 		ieee80211_tx_status_irqsafe(dev, old_skb);
 	}
 	retry = tmp;
@@ -933,8 +943,8 @@ static int rtl8187_start(struct ieee80211_hw *dev)
 		rtl818x_iowrite32(priv, &priv->map->TX_CONF,
 				  RTL818X_TX_CONF_HW_SEQNUM |
 				  RTL818X_TX_CONF_DISREQQSIZE |
-				  (7 << 8  /* short retry limit */) |
-				  (7 << 0  /* long retry limit */) |
+				  (RETRY_COUNT << 8  /* short retry limit */) |
+				  (RETRY_COUNT << 0  /* long retry limit */) |
 				  (7 << 21 /* MAX TX DMA */));
 		rtl8187_init_urbs(dev);
 		rtl8187b_init_status_urb(dev);
@@ -1378,6 +1388,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		     IEEE80211_HW_SIGNAL_DBM |
 		     IEEE80211_HW_RX_INCLUDES_FCS;
+	/* Initialize rate-control variables */
+	dev->max_rates = 1;
+	dev->max_rate_tries = RETRY_COUNT;
 
 	eeprom.data = dev;
 	eeprom.register_read = rtl8187_eeprom_register_read;
diff --git a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
index 0d7b142..f1cc907 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
@@ -35,6 +35,8 @@
 #define RFKILL_MASK_8187_89_97	0x2
 #define RFKILL_MASK_8198	0x4
 
+#define RETRY_COUNT		7
+
 struct rtl8187_rx_info {
 	struct urb *urb;
 	struct ieee80211_hw *dev;
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 7f6573f..ce49e0c 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -1,15 +1,33 @@
 config RTL8192CE
-	tristate "Realtek RTL8192CE/RTL8188SE Wireless Network Adapter"
-	depends on MAC80211 && EXPERIMENTAL
+	tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter"
+	depends on MAC80211 && PCI && EXPERIMENTAL
 	select FW_LOADER
 	select RTLWIFI
+	select RTL8192C_COMMON
 	---help---
 	This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe
 	wireless network adapters.
 
 	If you choose to build it as a module, it will be called rtl8192ce
 
+config RTL8192CU
+	tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
+	depends on MAC80211 && USB && EXPERIMENTAL
+	select FW_LOADER
+	select RTLWIFI
+	select RTL8192C_COMMON
+	---help---
+	This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB
+	wireless network adapters.
+
+	If you choose to build it as a module, it will be called rtl8192cu
+
 config RTLWIFI
 	tristate
-	depends on RTL8192CE
+	depends on RTL8192CE || RTL8192CU
+	default m
+
+config RTL8192C_COMMON
+	tristate
+	depends on RTL8192CE || RTL8192CU
 	default m
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile
index 2a7a438..ec9393f 100644
--- a/drivers/net/wireless/rtlwifi/Makefile
+++ b/drivers/net/wireless/rtlwifi/Makefile
@@ -5,9 +5,22 @@ rtlwifi-objs	:=		\
 		core.o		\
 		debug.o		\
 		efuse.o		\
-		pci.o		\
 		ps.o		\
 		rc.o		\
 		regd.o
 
+rtl8192c_common-objs +=		\
+
+ifneq ($(CONFIG_PCI),)
+rtlwifi-objs	+= pci.o
+endif
+
+ifneq ($(CONFIG_USB),)
+rtlwifi-objs	+= usb.o
+endif
+
+obj-$(CONFIG_RTL8192C_COMMON)	+= rtl8192c/
 obj-$(CONFIG_RTL8192CE)		+= rtl8192ce/
+obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index cf0b73e..bb0c781 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -144,7 +144,7 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
 		ht_cap->mcs.rx_mask[1] = 0xFF;
 		ht_cap->mcs.rx_mask[4] = 0x01;
 
-		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
+		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"));
@@ -153,7 +153,7 @@ static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
 		ht_cap->mcs.rx_mask[1] = 0x00;
 		ht_cap->mcs.rx_mask[4] = 0x01;
 
-		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
+		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
 	}
 }
 
@@ -283,13 +283,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
 	rtlmac->hw = hw;
 
 	/* <2> rate control register */
-	if (rtl_rate_control_register()) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("rtl: Unable to register rtl_rc,"
-			  "use default RC !!\n"));
-	} else {
-		hw->rate_control_algorithm = "rtl_rc";
-	}
+	hw->rate_control_algorithm = "rtl_rc";
 
 	/*
 	 * <3> init CRDA must come after init
@@ -325,8 +319,6 @@ int rtl_init_core(struct ieee80211_hw *hw)
 
 void rtl_deinit_core(struct ieee80211_hw *hw)
 {
-	 /*RC*/
-	rtl_rate_control_unregister();
 }
 
 void rtl_init_rx_config(struct ieee80211_hw *hw)
@@ -399,21 +391,21 @@ static void _rtl_query_protection_mode(struct ieee80211_hw *hw,
 	u8 rate_flag = info->control.rates[0].flags;
 
 	/* Common Settings */
-	tcb_desc->b_rts_stbc = false;
-	tcb_desc->b_cts_enable = false;
+	tcb_desc->rts_stbc = false;
+	tcb_desc->cts_enable = false;
 	tcb_desc->rts_sc = 0;
-	tcb_desc->b_rts_bw = false;
-	tcb_desc->b_rts_use_shortpreamble = false;
-	tcb_desc->b_rts_use_shortgi = false;
+	tcb_desc->rts_bw = false;
+	tcb_desc->rts_use_shortpreamble = false;
+	tcb_desc->rts_use_shortgi = false;
 
 	if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		/* Use CTS-to-SELF in protection mode. */
-		tcb_desc->b_rts_enable = true;
-		tcb_desc->b_cts_enable = true;
+		tcb_desc->rts_enable = true;
+		tcb_desc->cts_enable = true;
 		tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M];
 	} else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
 		/* Use RTS-CTS in protection mode. */
-		tcb_desc->b_rts_enable = true;
+		tcb_desc->rts_enable = true;
 		tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M];
 	}
 
@@ -429,7 +421,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 		if (mac->opmode == NL80211_IFTYPE_STATION)
 			tcb_desc->ratr_index = 0;
 		else if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			if (tcb_desc->b_multicast || tcb_desc->b_broadcast) {
+			if (tcb_desc->multicast || tcb_desc->broadcast) {
 				tcb_desc->hw_rate =
 				    rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M];
 				tcb_desc->use_driver_rate = 1;
@@ -439,7 +431,7 @@ static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (rtlpriv->dm.b_useramask) {
+	if (rtlpriv->dm.useramask) {
 		/* TODO we will differentiate adhoc and station futrue  */
 		tcb_desc->mac_id = 0;
 
@@ -461,19 +453,19 @@ static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	tcb_desc->b_packet_bw = false;
+	tcb_desc->packet_bw = false;
 
 	if (!mac->bw_40 || !mac->ht_enable)
 		return;
 
-	if (tcb_desc->b_multicast || tcb_desc->b_broadcast)
+	if (tcb_desc->multicast || tcb_desc->broadcast)
 		return;
 
 	/*use legency rate, shall use 20MHz */
 	if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M])
 		return;
 
-	tcb_desc->b_packet_bw = true;
+	tcb_desc->packet_bw = true;
 }
 
 static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw)
@@ -498,7 +490,7 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	struct ieee80211_rate *txrate;
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 
 	memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 
@@ -545,9 +537,9 @@ void rtl_get_tcb_desc(struct ieee80211_hw *hw,
 		}
 
 		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
-			tcb_desc->b_multicast = 1;
+			tcb_desc->multicast = 1;
 		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
-			tcb_desc->b_broadcast = 1;
+			tcb_desc->broadcast = 1;
 
 		_rtl_txrate_selectmode(hw, tcb_desc);
 		_rtl_query_bandwidth_mode(hw, tcb_desc);
@@ -570,7 +562,7 @@ bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 
 	if (ieee80211_is_auth(fc)) {
 		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n"));
@@ -587,7 +579,7 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN));
 	u8 category;
 
@@ -632,7 +624,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u16 ether_type;
 	u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
 	const struct iphdr *ip;
@@ -646,7 +638,6 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 	ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
 			      SNAP_SIZE + PROTOC_TYPE_SIZE);
 	ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
-	ether_type = ntohs(ether_type);
 
 	if (ETH_P_IP == ether_type) {
 		if (IPPROTO_UDP == ip->protocol) {
@@ -690,7 +681,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
 		}
 
 		return true;
-	} else if (0x86DD == ether_type) {
+	} else if (ETH_P_IPV6 == ether_type) {
+		/* IPv6 */
 		return true;
 	}
 
@@ -777,10 +769,10 @@ 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 b_busytraffic = false;
-	bool b_higher_busytraffic = false;
-	bool b_higher_busyrxtraffic = false;
-	bool b_higher_busytxtraffic = false;
+	bool busytraffic = false;
+	bool higher_busytraffic = false;
+	bool higher_busyrxtraffic = false;
+	bool higher_busytxtraffic = false;
 
 	u8 idx = 0;
 	u32 rx_cnt_inp4eriod = 0;
@@ -788,7 +780,7 @@ void rtl_watchdog_wq_callback(void *data)
 	u32 aver_rx_cnt_inperiod = 0;
 	u32 aver_tx_cnt_inperiod = 0;
 
-	bool benter_ps = false;
+	bool enter_ps = false;
 
 	if (is_hal_stop(rtlhal))
 		return;
@@ -832,29 +824,29 @@ void rtl_watchdog_wq_callback(void *data)
 
 		/* (2) check traffic busy */
 		if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100)
-			b_busytraffic = true;
+			busytraffic = true;
 
 		/* Higher Tx/Rx data. */
 		if (aver_rx_cnt_inperiod > 4000 ||
 		    aver_tx_cnt_inperiod > 4000) {
-			b_higher_busytraffic = true;
+			higher_busytraffic = true;
 
 			/* Extremely high Rx data. */
 			if (aver_rx_cnt_inperiod > 5000)
-				b_higher_busyrxtraffic = true;
+				higher_busyrxtraffic = true;
 			else
-				b_higher_busytxtraffic = false;
+				higher_busytxtraffic = false;
 		}
 
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		    (rtlpriv->link_info.num_rx_inperiod > 2))
-			benter_ps = false;
+			enter_ps = false;
 		else
-			benter_ps = true;
+			enter_ps = true;
 
 		/* LeisurePS only work in infra mode. */
-		if (benter_ps)
+		if (enter_ps)
 			rtl_lps_enter(hw);
 		else
 			rtl_lps_leave(hw);
@@ -863,9 +855,9 @@ void rtl_watchdog_wq_callback(void *data)
 	rtlpriv->link_info.num_rx_inperiod = 0;
 	rtlpriv->link_info.num_tx_inperiod = 0;
 
-	rtlpriv->link_info.b_busytraffic = b_busytraffic;
-	rtlpriv->link_info.b_higher_busytraffic = b_higher_busytraffic;
-	rtlpriv->link_info.b_higher_busyrxtraffic = b_higher_busyrxtraffic;
+	rtlpriv->link_info.busytraffic = busytraffic;
+	rtlpriv->link_info.higher_busytraffic = higher_busytraffic;
+	rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic;
 
 }
 
@@ -945,11 +937,16 @@ MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
 
 static int __init rtl_core_module_init(void)
 {
+	if (rtl_rate_control_register())
+		printk(KERN_ERR "rtlwifi: Unable to register rtl_rc,"
+		       "use default RC !!\n");
 	return 0;
 }
 
 static void __exit rtl_core_module_exit(void)
 {
+	 /*RC*/
+	rtl_rate_control_unregister();
 }
 
 module_init(rtl_core_module_init);
diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h
index 3de5a14..0430453 100644
--- a/drivers/net/wireless/rtlwifi/base.h
+++ b/drivers/net/wireless/rtlwifi/base.h
@@ -30,6 +30,7 @@
 #define __RTL_BASE_H__
 
 #define RTL_DUMMY_OFFSET	0
+#define RTL_RX_DESC_SIZE	24
 #define RTL_DUMMY_UNIT		8
 #define RTL_TX_DUMMY_SIZE	(RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT)
 #define RTL_TX_DESC_SIZE	32
@@ -52,46 +53,22 @@
 #define FRAME_OFFSET_SEQUENCE		22
 #define FRAME_OFFSET_ADDRESS4		24
 
-#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val)		\
-	WRITEEF2BYTE(_hdr, _val)
-#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val)	\
-	WRITEEF1BYTE(_hdr, _val)
-#define SET_80211_HDR_PWR_MGNT(_hdr, _val)		\
-	SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val)
-#define SET_80211_HDR_TO_DS(_hdr, _val)			\
-	SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val)
 
 #define SET_80211_PS_POLL_AID(_hdr, _val)		\
-	WRITEEF2BYTE(((u8 *)(_hdr)) + 2, _val)
+	(*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val))
 #define SET_80211_PS_POLL_BSSID(_hdr, _val)		\
-	CP_MACADDR(((u8 *)(_hdr)) + 4, (u8 *)(_val))
+	memcpy(((u8 *)(_hdr)) + 4, (u8 *)(_val), ETH_ALEN)
 #define SET_80211_PS_POLL_TA(_hdr, _val)		\
-	CP_MACADDR(((u8 *)(_hdr)) + 10, (u8 *)(_val))
+	memcpy(((u8 *)(_hdr)) + 10, (u8 *)(_val), ETH_ALEN)
 
 #define SET_80211_HDR_DURATION(_hdr, _val)	\
-	WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_DURATION, _val)
+	(*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val))
 #define SET_80211_HDR_ADDRESS1(_hdr, _val)	\
-	CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val))
+	memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val), ETH_ALEN)
 #define SET_80211_HDR_ADDRESS2(_hdr, _val)	\
-	CP_MACADDR((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val))
+	memcpy((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val), ETH_ALEN)
 #define SET_80211_HDR_ADDRESS3(_hdr, _val)	\
-	CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val))
-#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val)  \
-	WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val)
-
-#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val)	\
-	WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val)
-#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \
-	WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val)
-#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \
-	WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val)
-#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr)	\
-	READEF2BYTE(((u8 *)(__phdr)) + 34)
-#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \
-	WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val)
-#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \
-	SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \
-	(GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val))))
+	memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val), ETH_ALEN)
 
 int rtl_init_core(struct ieee80211_hw *hw);
 void rtl_deinit_core(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index d6a924a..e4f4aee 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -82,7 +82,7 @@ static void rtl_op_stop(struct ieee80211_hw *hw)
 	mutex_unlock(&rtlpriv->locks.conf_mutex);
 }
 
-static int rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -97,11 +97,10 @@ static int rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 	rtlpriv->intf_ops->adapter_tx(hw, skb);
 
-	return NETDEV_TX_OK;
+	return;
 
 err_free:
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 static int rtl_op_add_interface(struct ieee80211_hw *hw,
@@ -434,9 +433,9 @@ static int rtl_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
 
 	aci = _rtl_get_hal_qnum(queue);
 	mac->ac[aci].aifs = param->aifs;
-	mac->ac[aci].cw_min = param->cw_min;
-	mac->ac[aci].cw_max = param->cw_max;
-	mac->ac[aci].tx_op = param->txop;
+	mac->ac[aci].cw_min = cpu_to_le16(param->cw_min);
+	mac->ac[aci].cw_max = cpu_to_le16(param->cw_max);
+	mac->ac[aci].tx_op = cpu_to_le16(param->txop);
 	memcpy(&mac->edca_param[aci], param, sizeof(*param));
 	rtlpriv->cfg->ops->set_qos(hw, aci);
 	return 0;
@@ -552,6 +551,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 ("BSS_CHANGED_HT\n"));
 
+		rcu_read_lock();
 		sta = ieee80211_find_sta(mac->vif, mac->bssid);
 
 		if (sta) {
@@ -564,6 +564,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 				mac->current_ampdu_factor =
 				    sta->ht_cap.ampdu_factor;
 		}
+		rcu_read_unlock();
 
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY,
 					      (u8 *) (&mac->max_mss_density));
@@ -615,6 +616,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 		else
 			mac->mode = WIRELESS_MODE_G;
 
+		rcu_read_lock();
 		sta = ieee80211_find_sta(mac->vif, mac->bssid);
 
 		if (sta) {
@@ -649,6 +651,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 				 */
 			}
 		}
+		rcu_read_unlock();
 
 		/*mac80211 just give us CCK rates any time
 		 *So we add G rate in basic rates when
@@ -666,7 +669,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 					(u8 *) (&basic_rates));
 
-			if (rtlpriv->dm.b_useramask)
+			if (rtlpriv->dm.useramask)
 				rtlpriv->cfg->ops->update_rate_mask(hw, 0);
 			else
 				rtlpriv->cfg->ops->update_rate_table(hw);
@@ -681,7 +684,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 	 */
 	if (changed & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
-			if (ppsc->b_fwctrl_lps) {
+			if (ppsc->fwctrl_lps) {
 				u8 mstatus = RT_MEDIA_CONNECT;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						      HW_VAR_H2C_FW_JOINBSSRPT,
@@ -689,7 +692,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
 				ppsc->report_linked = true;
 			}
 		} else {
-			if (ppsc->b_fwctrl_lps) {
+			if (ppsc->fwctrl_lps) {
 				u8 mstatus = RT_MEDIA_DISCONNECT;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						      HW_VAR_H2C_FW_JOINBSSRPT,
@@ -748,7 +751,8 @@ static void rtl_op_sta_notify(struct ieee80211_hw *hw,
 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 * ssn)
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
@@ -817,7 +821,7 @@ static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
 		/* fix fwlps issue */
 		rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
 
-		if (rtlpriv->dm.b_useramask)
+		if (rtlpriv->dm.useramask)
 			rtlpriv->cfg->ops->update_rate_mask(hw, 0);
 		else
 			rtlpriv->cfg->ops->update_rate_table(hw);
diff --git a/drivers/net/wireless/rtlwifi/debug.h b/drivers/net/wireless/rtlwifi/debug.h
index 08bdec2..e4aa868 100644
--- a/drivers/net/wireless/rtlwifi/debug.h
+++ b/drivers/net/wireless/rtlwifi/debug.h
@@ -105,6 +105,7 @@
 #define COMP_MAC80211		BIT(26)
 #define COMP_REGD			BIT(27)
 #define COMP_CHAN			BIT(28)
+#define COMP_USB			BIT(29)
 
 /*--------------------------------------------------------------
 		Define the rt_print components
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c
index 62876cd..4f92cba 100644
--- a/drivers/net/wireless/rtlwifi/efuse.c
+++ b/drivers/net/wireless/rtlwifi/efuse.c
@@ -1169,21 +1169,3 @@ static u8 efuse_calculate_word_cnts(u8 word_en)
 	return word_cnts;
 }
 
-void efuse_reset_loader(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u16 tmp_u2b;
-
-	tmp_u2b = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN]);
-	rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN],
-		       (tmp_u2b & ~(BIT(12))));
-	udelay(10000);
-	rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN],
-		       (tmp_u2b | BIT(12)));
-	udelay(10000);
-}
-
-bool efuse_program_map(struct ieee80211_hw *hw, char *p_filename, u8 tabletype)
-{
-	return true;
-}
diff --git a/drivers/net/wireless/rtlwifi/efuse.h b/drivers/net/wireless/rtlwifi/efuse.h
index 2d39a4d..47774dd 100644
--- a/drivers/net/wireless/rtlwifi/efuse.h
+++ b/drivers/net/wireless/rtlwifi/efuse.h
@@ -117,8 +117,5 @@ extern bool efuse_shadow_update_chk(struct ieee80211_hw *hw);
 extern void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
 extern void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
 extern void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
-extern bool efuse_program_map(struct ieee80211_hw *hw,
-			      char *p_filename, u8 tabletype);
-extern void efuse_reset_loader(struct ieee80211_hw *hw);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 1758d44..9cd7703 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -50,7 +50,7 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
 	u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
 
 	ppsc->reg_rfps_level = 0;
-	ppsc->b_support_aspm = 0;
+	ppsc->support_aspm = 0;
 
 	/*Update PCI ASPM setting */
 	ppsc->const_amdpci_aspm = rtlpci->const_amdpci_aspm;
@@ -115,29 +115,29 @@ static void _rtl_pci_update_default_setting(struct ieee80211_hw *hw)
 	switch (rtlpci->const_support_pciaspm) {
 	case 0:{
 			/*Not support ASPM. */
-			bool b_support_aspm = false;
-			ppsc->b_support_aspm = b_support_aspm;
+			bool support_aspm = false;
+			ppsc->support_aspm = support_aspm;
 			break;
 		}
 	case 1:{
 			/*Support ASPM. */
-			bool b_support_aspm = true;
-			bool b_support_backdoor = true;
-			ppsc->b_support_aspm = b_support_aspm;
+			bool support_aspm = true;
+			bool support_backdoor = true;
+			ppsc->support_aspm = support_aspm;
 
 			/*if(priv->oem_id == RT_CID_TOSHIBA &&
 			   !priv->ndis_adapter.amd_l1_patch)
-			   b_support_backdoor = false; */
+			   support_backdoor = false; */
 
-			ppsc->b_support_backdoor = b_support_backdoor;
+			ppsc->support_backdoor = support_backdoor;
 
 			break;
 		}
 	case 2:
 		/*ASPM value set by chipset. */
 		if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) {
-			bool b_support_aspm = true;
-			ppsc->b_support_aspm = b_support_aspm;
+			bool support_aspm = true;
+			ppsc->support_aspm = support_aspm;
 		}
 		break;
 	default:
@@ -476,9 +476,9 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
 
 		skb = __skb_dequeue(&ring->queue);
 		pci_unmap_single(rtlpci->pdev,
-				 le32_to_cpu(rtlpriv->cfg->ops->
+				 rtlpriv->cfg->ops->
 					     get_desc((u8 *) entry, true,
-						      HW_DESC_TXBUFF_ADDR)),
+						      HW_DESC_TXBUFF_ADDR),
 				 skb->len, PCI_DMA_TODEVICE);
 
 		RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE,
@@ -557,7 +557,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 			return;
 		} else {
 			struct ieee80211_hdr *hdr;
-			u16 fc;
+			__le16 fc;
 			struct sk_buff *new_skb = NULL;
 
 			rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
@@ -583,9 +583,9 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 			 */
 
 			hdr = (struct ieee80211_hdr *)(skb->data);
-			fc = le16_to_cpu(hdr->frame_control);
+			fc = hdr->frame_control;
 
-			if (!stats.b_crc) {
+			if (!stats.crc) {
 				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
 				       sizeof(rx_status));
 
@@ -666,7 +666,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 
 		}
 done:
-		bufferaddress = cpu_to_le32(*((dma_addr_t *) skb->cb));
+		bufferaddress = (u32)(*((dma_addr_t *) skb->cb));
 		tmp_one = 1;
 		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
 					    HW_DESC_RXBUFF_ADDR,
@@ -690,75 +690,6 @@ done:
 
 }
 
-void _rtl_pci_tx_interrupt(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	int prio;
-
-	for (prio = 0; prio < RTL_PCI_MAX_TX_QUEUE_COUNT; prio++) {
-		struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio];
-
-		while (skb_queue_len(&ring->queue)) {
-			struct rtl_tx_desc *entry = &ring->desc[ring->idx];
-			struct sk_buff *skb;
-			struct ieee80211_tx_info *info;
-			u8 own;
-
-			/*
-			 *beacon packet will only use the first
-			 *descriptor defautly, and the own may not
-			 *be cleared by the hardware, and
-			 *beacon will free in prepare beacon
-			 */
-			if (prio == BEACON_QUEUE || prio == TXCMD_QUEUE ||
-			    prio == HCCA_QUEUE)
-				break;
-
-			own = (u8)rtlpriv->cfg->ops->get_desc((u8 *)entry,
-							       true,
-							       HW_DESC_OWN);
-
-			if (own)
-				break;
-
-			skb = __skb_dequeue(&ring->queue);
-			pci_unmap_single(rtlpci->pdev,
-					 le32_to_cpu(rtlpriv->cfg->ops->
-						     get_desc((u8 *) entry,
-						     true,
-						     HW_DESC_TXBUFF_ADDR)),
-					 skb->len, PCI_DMA_TODEVICE);
-
-			ring->idx = (ring->idx + 1) % ring->entries;
-
-			info = IEEE80211_SKB_CB(skb);
-			ieee80211_tx_info_clear_status(info);
-
-			info->flags |= IEEE80211_TX_STAT_ACK;
-			/*info->status.rates[0].count = 1; */
-
-			ieee80211_tx_status_irqsafe(hw, skb);
-
-			if ((ring->entries - skb_queue_len(&ring->queue))
-			    == 2 && prio != BEACON_QUEUE) {
-				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-					 ("more desc left, wake "
-					  "skb_queue@%d,ring->idx = %d,"
-					  "skb_queue_len = 0x%d\n",
-					  prio, ring->idx,
-					  skb_queue_len(&ring->queue)));
-
-				ieee80211_wake_queue(hw,
-						     skb_get_queue_mapping
-						     (skb));
-			}
-
-			skb = NULL;
-		}
-	}
-}
-
 static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 {
 	struct ieee80211_hw *hw = dev_id;
@@ -959,17 +890,17 @@ static void _rtl_pci_init_struct(struct ieee80211_hw *hw,
 	rtlhal->hw = hw;
 	rtlpci->pdev = pdev;
 
-	ppsc->b_inactiveps = false;
-	ppsc->b_leisure_ps = true;
-	ppsc->b_fwctrl_lps = true;
-	ppsc->b_reg_fwctrl_lps = 3;
+	ppsc->inactiveps = false;
+	ppsc->leisure_ps = true;
+	ppsc->fwctrl_lps = true;
+	ppsc->reg_fwctrl_lps = 3;
 	ppsc->reg_max_lps_awakeintvl = 5;
 
-	if (ppsc->b_reg_fwctrl_lps == 1)
+	if (ppsc->reg_fwctrl_lps == 1)
 		ppsc->fwctrl_psmode = FW_PS_MIN_MODE;
-	else if (ppsc->b_reg_fwctrl_lps == 2)
+	else if (ppsc->reg_fwctrl_lps == 2)
 		ppsc->fwctrl_psmode = FW_PS_MAX_MODE;
-	else if (ppsc->b_reg_fwctrl_lps == 3)
+	else if (ppsc->reg_fwctrl_lps == 3)
 		ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;
 
 	/*Tx/Rx related var */
@@ -1024,9 +955,8 @@ static int _rtl_pci_init_tx_ring(struct ieee80211_hw *hw,
 		 ("queue:%d, ring_addr:%p\n", prio, ring));
 
 	for (i = 0; i < entries; i++) {
-		nextdescaddress = cpu_to_le32((u32) dma +
-					      ((i + 1) % entries) *
-					      sizeof(*ring));
+		nextdescaddress = (u32) dma + ((i + 1) % entries) *
+					      sizeof(*ring);
 
 		rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]),
 					    true, HW_DESC_TX_NEXTDESC_ADDR,
@@ -1090,7 +1020,7 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw)
 					   rtlpci->rxbuffersize,
 					   PCI_DMA_FROMDEVICE);
 
-			bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
+			bufferaddress = (u32)(*((dma_addr_t *)skb->cb));
 			rtlpriv->cfg->ops->set_desc((u8 *)entry, false,
 						    HW_DESC_RXBUFF_ADDR,
 						    (u8 *)&bufferaddress);
@@ -1121,9 +1051,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
 		struct sk_buff *skb = __skb_dequeue(&ring->queue);
 
 		pci_unmap_single(rtlpci->pdev,
-				 le32_to_cpu(rtlpriv->cfg->
+				 rtlpriv->cfg->
 					     ops->get_desc((u8 *) entry, true,
-						   HW_DESC_TXBUFF_ADDR)),
+						   HW_DESC_TXBUFF_ADDR),
 				 skb->len, PCI_DMA_TODEVICE);
 		kfree_skb(skb);
 		ring->idx = (ring->idx + 1) % ring->entries;
@@ -1255,11 +1185,11 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
 				    __skb_dequeue(&ring->queue);
 
 				pci_unmap_single(rtlpci->pdev,
-						 le32_to_cpu(rtlpriv->cfg->ops->
+						 rtlpriv->cfg->ops->
 							 get_desc((u8 *)
 							 entry,
 							 true,
-							 HW_DESC_TXBUFF_ADDR)),
+							 HW_DESC_TXBUFF_ADDR),
 						 skb->len, PCI_DMA_TODEVICE);
 				kfree_skb(skb);
 				ring->idx = (ring->idx + 1) % ring->entries;
@@ -1273,7 +1203,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
 	return 0;
 }
 
-unsigned int _rtl_mac_to_hwqueue(u16 fc,
+static unsigned int _rtl_mac_to_hwqueue(__le16 fc,
 		unsigned int mac80211_queue_index)
 {
 	unsigned int hw_queue_index;
@@ -1312,7 +1242,7 @@ out:
 	return hw_queue_index;
 }
 
-int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1323,7 +1253,7 @@ int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	unsigned int queue_index, hw_queue;
 	unsigned long flags;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u8 *pda_addr = hdr->addr1;
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	/*ssn */
@@ -1429,7 +1359,7 @@ int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	return 0;
 }
 
-void rtl_pci_deinit(struct ieee80211_hw *hw)
+static void rtl_pci_deinit(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -1444,7 +1374,7 @@ void rtl_pci_deinit(struct ieee80211_hw *hw)
 
 }
 
-int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
+static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	int err;
@@ -1461,7 +1391,7 @@ int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
 	return 1;
 }
 
-int rtl_pci_start(struct ieee80211_hw *hw)
+static int rtl_pci_start(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -1496,7 +1426,7 @@ int rtl_pci_start(struct ieee80211_hw *hw)
 	return 0;
 }
 
-void rtl_pci_stop(struct ieee80211_hw *hw)
+static void rtl_pci_stop(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -1547,13 +1477,11 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 	struct pci_dev *bridge_pdev = pdev->bus->self;
 	u16 venderid;
 	u16 deviceid;
-	u8 revisionid;
 	u16 irqline;
 	u8 tmp;
 
 	venderid = pdev->vendor;
 	deviceid = pdev->device;
-	pci_read_config_byte(pdev, 0x8, &revisionid);
 	pci_read_config_word(pdev, 0x3C, &irqline);
 
 	if (deviceid == RTL_PCI_8192_DID ||
@@ -1564,7 +1492,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
 	    deviceid == RTL_PCI_8173_DID ||
 	    deviceid == RTL_PCI_8172_DID ||
 	    deviceid == RTL_PCI_8171_DID) {
-		switch (revisionid) {
+		switch (pdev->revision) {
 		case RTL_PCI_REVISION_ID_8192PCIE:
 			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 				 ("8192 PCI-E is found - "
@@ -1838,7 +1766,7 @@ fail3:
 	ieee80211_free_hw(hw);
 
 	if (rtlpriv->io.pci_mem_start != 0)
-		pci_iounmap(pdev, (void *)rtlpriv->io.pci_mem_start);
+		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 
 fail2:
 	pci_release_regions(pdev);
@@ -1888,7 +1816,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
 	}
 
 	if (rtlpriv->io.pci_mem_start != 0) {
-		pci_iounmap(pdev, (void *)rtlpriv->io.pci_mem_start);
+		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 		pci_release_regions(pdev);
 	}
 
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index d36a669..0caa814 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -244,34 +244,34 @@ int rtl_pci_resume(struct pci_dev *pdev);
 
 static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-	return 0xff & readb((u8 *) rtlpriv->io.pci_mem_start + addr);
+	return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-	return readw((u8 *) rtlpriv->io.pci_mem_start + addr);
+	return readw((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-	return readl((u8 *) rtlpriv->io.pci_mem_start + addr);
+	return readl((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
 {
-	writeb(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
+	writeb(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void pci_write16_async(struct rtl_priv *rtlpriv,
 				     u32 addr, u16 val)
 {
-	writew(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
+	writew(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void pci_write32_async(struct rtl_priv *rtlpriv,
 				     u32 addr, u32 val)
 {
-	writel(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
+	writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val)
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c
index d2326c1..6b7e217 100644
--- a/drivers/net/wireless/rtlwifi/ps.c
+++ b/drivers/net/wireless/rtlwifi/ps.c
@@ -86,7 +86,7 @@ bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	enum rf_pwrstate rtstate;
-	bool b_actionallowed = false;
+	bool actionallowed = false;
 	u16 rfwait_cnt = 0;
 	unsigned long flag;
 
@@ -139,13 +139,13 @@ no_protect:
 		ppsc->rfoff_reason &= (~changesource);
 
 		if ((changesource == RF_CHANGE_BY_HW) &&
-		    (ppsc->b_hwradiooff == true)) {
-			ppsc->b_hwradiooff = false;
+		    (ppsc->hwradiooff == true)) {
+			ppsc->hwradiooff = false;
 		}
 
 		if (!ppsc->rfoff_reason) {
 			ppsc->rfoff_reason = 0;
-			b_actionallowed = true;
+			actionallowed = true;
 		}
 
 		break;
@@ -153,17 +153,17 @@ no_protect:
 	case ERFOFF:
 
 		if ((changesource == RF_CHANGE_BY_HW)
-		    && (ppsc->b_hwradiooff == false)) {
-			ppsc->b_hwradiooff = true;
+		    && (ppsc->hwradiooff == false)) {
+			ppsc->hwradiooff = true;
 		}
 
 		ppsc->rfoff_reason |= changesource;
-		b_actionallowed = true;
+		actionallowed = true;
 		break;
 
 	case ERFSLEEP:
 		ppsc->rfoff_reason |= changesource;
-		b_actionallowed = true;
+		actionallowed = true;
 		break;
 
 	default:
@@ -172,7 +172,7 @@ no_protect:
 		break;
 	}
 
-	if (b_actionallowed)
+	if (actionallowed)
 		rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
 
 	if (!protect_or_not) {
@@ -181,7 +181,7 @@ no_protect:
 		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
 	}
 
-	return b_actionallowed;
+	return actionallowed;
 }
 EXPORT_SYMBOL(rtl_ps_set_rf_state);
 
@@ -191,7 +191,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 
-	ppsc->b_swrf_processing = true;
+	ppsc->swrf_processing = true;
 
 	if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) {
 		if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
@@ -213,7 +213,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
 		}
 	}
 
-	ppsc->b_swrf_processing = false;
+	ppsc->swrf_processing = false;
 }
 
 void rtl_ips_nic_off_wq_callback(void *data)
@@ -239,13 +239,13 @@ void rtl_ips_nic_off_wq_callback(void *data)
 	if (rtlpriv->sec.being_setkey)
 		return;
 
-	if (ppsc->b_inactiveps) {
+	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
 
 		/*
 		 *Do not enter IPS in the following conditions:
 		 *(1) RF is already OFF or Sleep
-		 *(2) b_swrf_processing (indicates the IPS is still under going)
+		 *(2) swrf_processing (indicates the IPS is still under going)
 		 *(3) Connectted (only disconnected can trigger IPS)
 		 *(4) IBSS (send Beacon)
 		 *(5) AP mode (send Beacon)
@@ -253,14 +253,14 @@ void rtl_ips_nic_off_wq_callback(void *data)
 		 */
 
 		if (rtstate == ERFON &&
-		    !ppsc->b_swrf_processing &&
+		    !ppsc->swrf_processing &&
 		    (mac->link_state == MAC80211_NOLINK) &&
 		    !mac->act_scanning) {
 			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 				 ("IPSEnter(): Turn off RF.\n"));
 
 			ppsc->inactive_pwrstate = ERFOFF;
-			ppsc->b_in_powersavemode = true;
+			ppsc->in_powersavemode = true;
 
 			/*rtl_pci_reset_trx_ring(hw); */
 			_rtl_ps_inactive_ps(hw);
@@ -290,15 +290,15 @@ void rtl_ips_nic_on(struct ieee80211_hw *hw)
 
 	spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
 
-	if (ppsc->b_inactiveps) {
+	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
 
 		if (rtstate != ERFON &&
-		    !ppsc->b_swrf_processing &&
+		    !ppsc->swrf_processing &&
 		    ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
 
 			ppsc->inactive_pwrstate = ERFON;
-			ppsc->b_in_powersavemode = false;
+			ppsc->in_powersavemode = false;
 
 			_rtl_ps_inactive_ps(hw);
 		}
@@ -370,9 +370,9 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
 	 *   mode and set RPWM to turn RF on.
 	 */
 
-	if ((ppsc->b_fwctrl_lps) && (ppsc->b_leisure_ps) &&
+	if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) &&
 	     ppsc->report_linked) {
-		bool b_fw_current_inps;
+		bool fw_current_inps;
 		if (ppsc->dot11_psmode == EACTIVE) {
 			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 				 ("FW LPS leave ps_mode:%x\n",
@@ -385,11 +385,11 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
 			rtlpriv->cfg->ops->set_hw_reg(hw,
 					HW_VAR_H2C_FW_PWRMODE,
 					(u8 *) (&fw_pwrmode));
-			b_fw_current_inps = false;
+			fw_current_inps = false;
 
 			rtlpriv->cfg->ops->set_hw_reg(hw,
 					HW_VAR_FW_PSMODE_STATUS,
-					(u8 *) (&b_fw_current_inps));
+					(u8 *) (&fw_current_inps));
 
 		} else {
 			if (rtl_get_fwlps_doze(hw)) {
@@ -398,10 +398,10 @@ static void rtl_lps_set_psmode(struct ieee80211_hw *hw, u8 rt_psmode)
 						 ppsc->fwctrl_psmode));
 
 				rpwm_val = 0x02;	/* RF off */
-				b_fw_current_inps = true;
+				fw_current_inps = true;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						HW_VAR_FW_PSMODE_STATUS,
-						(u8 *) (&b_fw_current_inps));
+						(u8 *) (&fw_current_inps));
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						HW_VAR_H2C_FW_PWRMODE,
 						(u8 *) (&ppsc->fwctrl_psmode));
@@ -425,13 +425,13 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	unsigned long flag;
 
-	if (!(ppsc->b_fwctrl_lps && ppsc->b_leisure_ps))
+	if (!(ppsc->fwctrl_lps && ppsc->leisure_ps))
 		return;
 
 	if (rtlpriv->sec.being_setkey)
 		return;
 
-	if (rtlpriv->link_info.b_busytraffic)
+	if (rtlpriv->link_info.busytraffic)
 		return;
 
 	/*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
@@ -446,7 +446,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
 
 	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
-	if (ppsc->b_leisure_ps) {
+	if (ppsc->leisure_ps) {
 		/* Idle for a while if we connect to AP a while ago. */
 		if (mac->cnt_after_linked >= 2) {
 			if (ppsc->dot11_psmode == EACTIVE) {
@@ -470,7 +470,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
 
 	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
-	if (ppsc->b_fwctrl_lps && ppsc->b_leisure_ps) {
+	if (ppsc->fwctrl_lps && ppsc->leisure_ps) {
 		if (ppsc->dot11_psmode != EACTIVE) {
 
 			/*FIX ME */
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/Makefile b/drivers/net/wireless/rtlwifi/rtl8192c/Makefile
new file mode 100644
index 0000000..aee42d7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/Makefile
@@ -0,0 +1,9 @@
+rtl8192c-common-objs :=		\
+		main.o		\
+		dm_common.o	\
+		fw_common.o	\
+		phy_common.o
+
+obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c-common.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
new file mode 100644
index 0000000..bb02327
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -0,0 +1,1398 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "dm_common.h"
+
+struct dig_t dm_digtable;
+static struct ps_t dm_pstable;
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
+	0x7f8001fe,
+	0x788001e2,
+	0x71c001c7,
+	0x6b8001ae,
+	0x65400195,
+	0x5fc0017f,
+	0x5a400169,
+	0x55400155,
+	0x50800142,
+	0x4c000130,
+	0x47c0011f,
+	0x43c0010f,
+	0x40000100,
+	0x3c8000f2,
+	0x390000e4,
+	0x35c000d7,
+	0x32c000cb,
+	0x300000c0,
+	0x2d4000b5,
+	0x2ac000ab,
+	0x288000a2,
+	0x26000098,
+	0x24000090,
+	0x22000088,
+	0x20000080,
+	0x1e400079,
+	0x1c800072,
+	0x1b00006c,
+	0x19800066,
+	0x18000060,
+	0x16c0005b,
+	0x15800056,
+	0x14400051,
+	0x1300004c,
+	0x12000048,
+	0x11000044,
+	0x10000040,
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
+	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
+	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
+	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
+	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
+	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
+	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
+	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
+	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
+	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
+	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
+	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
+	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
+	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
+	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
+	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
+	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
+	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
+	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
+	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
+	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
+	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
+	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
+	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
+	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
+	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
+	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
+	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
+	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
+	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
+	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
+	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
+	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
+	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
+	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
+	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
+};
+
+static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
+{
+	dm_digtable.dig_enable_flag = true;
+	dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+	dm_digtable.cur_igvalue = 0x20;
+	dm_digtable.pre_igvalue = 0x0;
+	dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+	dm_digtable.presta_connectstate = DIG_STA_DISCONNECT;
+	dm_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+	dm_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
+	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.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+	dm_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
+	dm_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+	dm_digtable.pre_cck_pd_state = CCK_PD_STAGE_MAX;
+	dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+}
+
+static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long rssi_val_min = 0;
+
+	if ((dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
+	    (dm_digtable.cursta_connectctate == DIG_STA_CONNECT)) {
+		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
+			rssi_val_min =
+			    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
+			     rtlpriv->dm.undecorated_smoothed_pwdb) ?
+			    rtlpriv->dm.undecorated_smoothed_pwdb :
+			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		else
+			rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
+	} else if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT ||
+		   dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT) {
+		rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
+	} else if (dm_digtable.curmultista_connectstate ==
+		   DIG_MULTISTA_CONNECT) {
+		rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+	}
+
+	return (u8) rssi_val_min;
+}
+
+static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+	u32 ret_value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
+	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
+	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
+	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
+	    falsealm_cnt->cnt_rate_illegal +
+	    falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
+
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
+	falsealm_cnt->cnt_cck_fail = ret_value;
+
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
+	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
+				 falsealm_cnt->cnt_rate_illegal +
+				 falsealm_cnt->cnt_crc8_fail +
+				 falsealm_cnt->cnt_mcs_fail +
+				 falsealm_cnt->cnt_cck_fail);
+
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 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",
+		  falsealm_cnt->cnt_parity_fail,
+		  falsealm_cnt->cnt_rate_illegal,
+		  falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail));
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
+		  falsealm_cnt->cnt_ofdm_fail,
+		  falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all));
+}
+
+static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value_igi = dm_digtable.cur_igvalue;
+
+	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
+		value_igi--;
+	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
+		value_igi += 0;
+	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
+		value_igi++;
+	else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
+		value_igi += 2;
+	if (value_igi > DM_DIG_FA_UPPER)
+		value_igi = DM_DIG_FA_UPPER;
+	else if (value_igi < DM_DIG_FA_LOWER)
+		value_igi = DM_DIG_FA_LOWER;
+	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
+		value_igi = 0x32;
+
+	dm_digtable.cur_igvalue = value_igi;
+	rtl92c_dm_write_dig(hw);
+}
+
+static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable.fa_highthresh) {
+		if ((dm_digtable.backoff_val - 2) <
+		    dm_digtable.backoff_val_range_min)
+			dm_digtable.backoff_val =
+			    dm_digtable.backoff_val_range_min;
+		else
+			dm_digtable.backoff_val -= 2;
+	} else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable.fa_lowthresh) {
+		if ((dm_digtable.backoff_val + 2) >
+		    dm_digtable.backoff_val_range_max)
+			dm_digtable.backoff_val =
+			    dm_digtable.backoff_val_range_max;
+		else
+			dm_digtable.backoff_val += 2;
+	}
+
+	if ((dm_digtable.rssi_val_min + 10 - dm_digtable.backoff_val) >
+	    dm_digtable.rx_gain_range_max)
+		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_max;
+	else if ((dm_digtable.rssi_val_min + 10 -
+		  dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
+		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_min;
+	else
+		dm_digtable.cur_igvalue = dm_digtable.rssi_val_min + 10 -
+		    dm_digtable.backoff_val;
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("rssi_val_min = %x backoff_val %x\n",
+		  dm_digtable.rssi_val_min, dm_digtable.backoff_val));
+
+	rtl92c_dm_write_dig(hw);
+}
+
+static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
+{
+	static u8 binitialized; /* initialized to false */
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+	bool multi_sta = false;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		multi_sta = true;
+
+	if ((multi_sta == false) || (dm_digtable.cursta_connectctate !=
+				     DIG_STA_DISCONNECT)) {
+		binitialized = false;
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+		return;
+	} else if (binitialized == false) {
+		binitialized = true;
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+		dm_digtable.cur_igvalue = 0x20;
+		rtl92c_dm_write_dig(hw);
+	}
+
+	if (dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) {
+		if ((rssi_strength < dm_digtable.rssi_lowthresh) &&
+		    (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
+
+			if (dm_digtable.dig_ext_port_stage ==
+			    DIG_EXT_PORT_STAGE_2) {
+				dm_digtable.cur_igvalue = 0x20;
+				rtl92c_dm_write_dig(hw);
+			}
+
+			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
+		} else if (rssi_strength > dm_digtable.rssi_highthresh) {
+			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
+			rtl92c_dm_ctrl_initgain_by_fa(hw);
+		}
+	} else if (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+		dm_digtable.cur_igvalue = 0x20;
+		rtl92c_dm_write_dig(hw);
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("curmultista_connectstate = "
+		  "%x dig_ext_port_stage %x\n",
+		  dm_digtable.curmultista_connectstate,
+		  dm_digtable.dig_ext_port_stage));
+}
+
+static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("presta_connectstate = %x,"
+		  " cursta_connectctate = %x\n",
+		  dm_digtable.presta_connectstate,
+		  dm_digtable.cursta_connectctate));
+
+	if (dm_digtable.presta_connectstate == dm_digtable.cursta_connectctate
+	    || dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT
+	    || dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+
+		if (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT) {
+			dm_digtable.rssi_val_min =
+			    rtl92c_dm_initial_gain_min_pwdb(hw);
+			rtl92c_dm_ctrl_initgain_by_rssi(hw);
+		}
+	} else {
+		dm_digtable.rssi_val_min = 0;
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+		dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+		dm_digtable.cur_igvalue = 0x20;
+		dm_digtable.pre_igvalue = 0;
+		rtl92c_dm_write_dig(hw);
+	}
+}
+
+static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+		dm_digtable.rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
+
+		if (dm_digtable.pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+			if (dm_digtable.rssi_val_min <= 25)
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_LowRssi;
+			else
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_HighRssi;
+		} else {
+			if (dm_digtable.rssi_val_min <= 20)
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_LowRssi;
+			else
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_HighRssi;
+		}
+	} else {
+		dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+	}
+
+	if (dm_digtable.pre_cck_pd_state != dm_digtable.cur_cck_pd_state) {
+		if (dm_digtable.cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
+				dm_digtable.cur_cck_fa_state =
+				    CCK_FA_STAGE_High;
+			else
+				dm_digtable.cur_cck_fa_state = CCK_FA_STAGE_Low;
+
+			if (dm_digtable.pre_cck_fa_state !=
+			    dm_digtable.cur_cck_fa_state) {
+				if (dm_digtable.cur_cck_fa_state ==
+				    CCK_FA_STAGE_Low)
+					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
+						      0x83);
+				else
+					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
+						      0xcd);
+
+				dm_digtable.pre_cck_fa_state =
+				    dm_digtable.cur_cck_fa_state;
+			}
+
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
+
+			if (IS_92C_SERIAL(rtlhal->version))
+				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
+					      MASKBYTE2, 0xd7);
+		} else {
+			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
+
+			if (IS_92C_SERIAL(rtlhal->version))
+				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
+					      MASKBYTE2, 0xd3);
+		}
+		dm_digtable.pre_cck_pd_state = dm_digtable.cur_cck_pd_state;
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("CCKPDStage=%x\n", dm_digtable.cur_cck_pd_state));
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("is92C=%x\n", IS_92C_SERIAL(rtlhal->version)));
+}
+
+static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	if (mac->act_scanning == true)
+		return;
+
+	if ((mac->link_state > MAC80211_NOLINK) &&
+	    (mac->link_state < MAC80211_LINKED))
+		dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT;
+	else if (mac->link_state >= MAC80211_LINKED)
+		dm_digtable.cursta_connectctate = DIG_STA_CONNECT;
+	else
+		dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+
+	rtl92c_dm_initial_gain_sta(hw);
+	rtl92c_dm_initial_gain_multi_sta(hw);
+	rtl92c_dm_cck_packet_detection_thresh(hw);
+
+	dm_digtable.presta_connectstate = dm_digtable.cursta_connectctate;
+
+}
+
+static void rtl92c_dm_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->dm.dm_initialgain_enable == false)
+		return;
+	if (dm_digtable.dig_enable_flag == false)
+		return;
+
+	rtl92c_dm_ctrl_initgain_by_twoport(hw);
+
+}
+
+static void rtl92c_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;
+}
+
+void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("cur_igvalue = 0x%x, "
+		  "pre_igvalue = 0x%x, backoff_val = %d\n",
+		  dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
+		  dm_digtable.backoff_val));
+
+	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
+		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+			      dm_digtable.cur_igvalue);
+		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+			      dm_digtable.cur_igvalue);
+
+		dm_digtable.pre_igvalue = dm_digtable.cur_igvalue;
+	}
+}
+EXPORT_SYMBOL(rtl92c_dm_write_dig);
+
+static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
+
+	u8 h2c_parameter[3] = { 0 };
+
+	return;
+
+	if (tmpentry_max_pwdb != 0) {
+		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
+		    tmpentry_max_pwdb;
+	} else {
+		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
+	}
+
+	if (tmpentry_min_pwdb != 0xff) {
+		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
+		    tmpentry_min_pwdb;
+	} else {
+		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
+	}
+
+	h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
+	h2c_parameter[0] = 0;
+
+	rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
+}
+
+void rtl92c_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;
+}
+EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
+
+static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	static u64 last_txok_cnt;
+	static u64 last_rxok_cnt;
+	u64 cur_txok_cnt;
+	u64 cur_rxok_cnt;
+	u32 edca_be_ul = 0x5ea42b;
+	u32 edca_be_dl = 0x5ea42b;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		goto dm_checkedcaturbo_exit;
+
+	if (mac->link_state != MAC80211_LINKED) {
+		rtlpriv->dm.current_turbo_edca = false;
+		return;
+	}
+
+	if (!mac->ht_enable) {	/*FIX MERGE */
+		if (!(edca_be_ul & 0xffff0000))
+			edca_be_ul |= 0x005e0000;
+
+		if (!(edca_be_dl & 0xffff0000))
+			edca_be_dl |= 0x005e0000;
+	}
+
+	if ((!rtlpriv->dm.is_any_nonbepkts) &&
+	    (!rtlpriv->dm.disable_framebursting)) {
+		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
+		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
+		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+			if (!rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv,
+						REG_EDCA_BE_PARAM,
+						edca_be_dl);
+				rtlpriv->dm.is_cur_rdlstate = true;
+			}
+		} else {
+			if (rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv,
+						REG_EDCA_BE_PARAM,
+						edca_be_ul);
+				rtlpriv->dm.is_cur_rdlstate = false;
+			}
+		}
+		rtlpriv->dm.current_turbo_edca = true;
+	} else {
+		if (rtlpriv->dm.current_turbo_edca) {
+			u8 tmp = AC0_BE;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_AC_PARAM,
+						      (u8 *) (&tmp));
+			rtlpriv->dm.current_turbo_edca = false;
+		}
+	}
+
+dm_checkedcaturbo_exit:
+	rtlpriv->dm.is_any_nonbepkts = false;
+	last_txok_cnt = rtlpriv->stats.txbytesunicast;
+	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
+							     *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 thermalvalue, delta, delta_lck, delta_iqk;
+	long ele_a, ele_d, temp_cck, val_x, value32;
+	long val_y, ele_c;
+	u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old;
+	int i;
+	bool is2t = IS_92C_SERIAL(rtlhal->version);
+	u8 txpwr_level[2] = {0, 0};
+	u8 ofdm_min_index = 6, rf;
+
+	rtlpriv->dm.txpower_trackingInit = true;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n"));
+
+	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
+
+	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));
+
+	rtl92c_phy_ap_calibrate(hw, (thermalvalue -
+				     rtlefuse->eeprom_thermalmeter));
+	if (is2t)
+		rf = 2;
+	else
+		rf = 1;
+
+	if (thermalvalue) {
+		ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+				      MASKDWORD) & MASKOFDM_D;
+
+		for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
+			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
+				ofdm_index_old[0] = (u8) i;
+
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					("Initial pathA ele_d reg0x%x = 0x%lx, "
+					 "ofdm_index=0x%x\n",
+					 ROFDM0_XATXIQIMBALANCE,
+					 ele_d, ofdm_index_old[0]));
+				break;
+			}
+		}
+
+		if (is2t) {
+			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
+					      MASKDWORD) & MASKOFDM_D;
+
+			for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
+				if (ele_d == (ofdmswing_table[i] &
+				    MASKOFDM_D)) {
+					ofdm_index_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_XBTXIQIMBALANCE, ele_d,
+					   ofdm_index_old[1]));
+					break;
+				}
+			}
+		}
+
+		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((void *)&temp_cck,
+					   (void *)&cckswing_table_ch14[i][2],
+					   4) == 0) {
+					cck_index_old = (u8) i;
+
+					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+						 DBG_LOUD,
+						 ("Initial reg0x%x = 0x%lx, "
+						  "cck_index=0x%x, ch 14 %d\n",
+						  RCCK0_TXFILTER2, temp_cck,
+						  cck_index_old,
+						  rtlpriv->dm.cck_inch14));
+					break;
+				}
+			} else {
+				if (memcmp((void *)&temp_cck,
+					   (void *)
+					   &cckswing_table_ch1ch13[i][2],
+					   4) == 0) {
+					cck_index_old = (u8) i;
+
+					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+						 DBG_LOUD,
+						 ("Initial reg0x%x = 0x%lx, "
+						  "cck_index=0x%x, ch14 %d\n",
+						  RCCK0_TXFILTER2, temp_cck,
+						  cck_index_old,
+						  rtlpriv->dm.cck_inch14));
+					break;
+				}
+			}
+		}
+
+		if (!rtlpriv->dm.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_index_old[i];
+			rtlpriv->dm.cck_index = cck_index_old;
+		}
+
+		delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
+		    (thermalvalue - rtlpriv->dm.thermalvalue) :
+		    (rtlpriv->dm.thermalvalue - 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));
+
+		if (delta_lck > 1) {
+			rtlpriv->dm.thermalvalue_lck = thermalvalue;
+			rtl92c_phy_lc_calibrate(hw);
+		}
+
+		if (delta > 0 && rtlpriv->dm.txpower_track_control) {
+			if (thermalvalue > rtlpriv->dm.thermalvalue) {
+				for (i = 0; i < rf; i++)
+					rtlpriv->dm.ofdm_index[i] -= delta;
+				rtlpriv->dm.cck_index -= delta;
+			} else {
+				for (i = 0; i < rf; i++)
+					rtlpriv->dm.ofdm_index[i] += delta;
+				rtlpriv->dm.cck_index += delta;
+			}
+
+			if (is2t) {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("temp OFDM_A_index=0x%x, "
+					  "OFDM_B_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  rtlpriv->dm.ofdm_index[0],
+					  rtlpriv->dm.ofdm_index[1],
+					  rtlpriv->dm.cck_index));
+			} else {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("temp OFDM_A_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  rtlpriv->dm.ofdm_index[0],
+					  rtlpriv->dm.cck_index));
+			}
+
+			if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
+				for (i = 0; i < rf; i++)
+					ofdm_index[i] =
+					    rtlpriv->dm.ofdm_index[i]
+					    + 1;
+				cck_index = rtlpriv->dm.cck_index + 1;
+			} else {
+				for (i = 0; i < rf; i++)
+					ofdm_index[i] =
+					    rtlpriv->dm.ofdm_index[i];
+				cck_index = rtlpriv->dm.cck_index;
+			}
+
+			for (i = 0; i < rf; i++) {
+				if (txpwr_level[i] >= 0 &&
+				    txpwr_level[i] <= 26) {
+					if (thermalvalue >
+					    rtlefuse->eeprom_thermalmeter) {
+						if (delta < 5)
+							ofdm_index[i] -= 1;
+
+						else
+							ofdm_index[i] -= 2;
+					} else if (delta > 5 && thermalvalue <
+						   rtlefuse->
+						   eeprom_thermalmeter) {
+						ofdm_index[i] += 1;
+					}
+				} else if (txpwr_level[i] >= 27 &&
+					   txpwr_level[i] <= 32
+					   && thermalvalue >
+					   rtlefuse->eeprom_thermalmeter) {
+					if (delta < 5)
+						ofdm_index[i] -= 1;
+
+					else
+						ofdm_index[i] -= 2;
+				} else if (txpwr_level[i] >= 32 &&
+					   txpwr_level[i] <= 38 &&
+					   thermalvalue >
+					   rtlefuse->eeprom_thermalmeter
+					   && delta > 5) {
+					ofdm_index[i] -= 1;
+				}
+			}
+
+			if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
+				if (thermalvalue >
+				    rtlefuse->eeprom_thermalmeter) {
+					if (delta < 5)
+						cck_index -= 1;
+
+					else
+						cck_index -= 2;
+				} else if (delta > 5 && thermalvalue <
+					   rtlefuse->eeprom_thermalmeter) {
+					cck_index += 1;
+				}
+			} else if (txpwr_level[i] >= 27 &&
+				   txpwr_level[i] <= 32 &&
+				   thermalvalue >
+				   rtlefuse->eeprom_thermalmeter) {
+				if (delta < 5)
+					cck_index -= 1;
+
+				else
+					cck_index -= 2;
+			} else if (txpwr_level[i] >= 32 &&
+				   txpwr_level[i] <= 38 &&
+				   thermalvalue > rtlefuse->eeprom_thermalmeter
+				   && delta > 5) {
+				cck_index -= 1;
+			}
+
+			for (i = 0; i < rf; i++) {
+				if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
+					ofdm_index[i] = OFDM_TABLE_SIZE - 1;
+
+				else if (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;
+
+			if (is2t) {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("new OFDM_A_index=0x%x, "
+					  "OFDM_B_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  ofdm_index[0], ofdm_index[1],
+					  cck_index));
+			} else {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("new OFDM_A_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  ofdm_index[0], cck_index));
+			}
+		}
+
+		if (rtlpriv->dm.txpower_track_control && delta != 0) {
+			ele_d =
+			    (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
+			val_x = rtlphy->reg_e94;
+			val_y = rtlphy->reg_e9c;
+
+			if (val_x != 0) {
+				if ((val_x & 0x00000200) != 0)
+					val_x = val_x | 0xFFFFFC00;
+				ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
+
+				if ((val_y & 0x00000200) != 0)
+					val_y = val_y | 0xFFFFFC00;
+				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
+
+				value32 = (ele_d << 22) |
+				    ((ele_c & 0x3F) << 16) | ele_a;
+
+				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					      MASKDWORD, value32);
+
+				value32 = (ele_c & 0x000003C0) >> 6;
+				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
+					      value32);
+
+				value32 = ((val_x * ele_d) >> 7) & 0x01;
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(31), value32);
+
+				value32 = ((val_y * ele_d) >> 7) & 0x01;
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(29), value32);
+			} else {
+				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					      MASKDWORD,
+					      ofdmswing_table[ofdm_index[0]]);
+
+				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
+					      0x00);
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(31) | BIT(29), 0x00);
+			}
+
+			if (!rtlpriv->dm.cck_inch14) {
+				rtl_write_byte(rtlpriv, 0xa22,
+					       cckswing_table_ch1ch13[cck_index]
+					       [0]);
+				rtl_write_byte(rtlpriv, 0xa23,
+					       cckswing_table_ch1ch13[cck_index]
+					       [1]);
+				rtl_write_byte(rtlpriv, 0xa24,
+					       cckswing_table_ch1ch13[cck_index]
+					       [2]);
+				rtl_write_byte(rtlpriv, 0xa25,
+					       cckswing_table_ch1ch13[cck_index]
+					       [3]);
+				rtl_write_byte(rtlpriv, 0xa26,
+					       cckswing_table_ch1ch13[cck_index]
+					       [4]);
+				rtl_write_byte(rtlpriv, 0xa27,
+					       cckswing_table_ch1ch13[cck_index]
+					       [5]);
+				rtl_write_byte(rtlpriv, 0xa28,
+					       cckswing_table_ch1ch13[cck_index]
+					       [6]);
+				rtl_write_byte(rtlpriv, 0xa29,
+					       cckswing_table_ch1ch13[cck_index]
+					       [7]);
+			} else {
+				rtl_write_byte(rtlpriv, 0xa22,
+					       cckswing_table_ch14[cck_index]
+					       [0]);
+				rtl_write_byte(rtlpriv, 0xa23,
+					       cckswing_table_ch14[cck_index]
+					       [1]);
+				rtl_write_byte(rtlpriv, 0xa24,
+					       cckswing_table_ch14[cck_index]
+					       [2]);
+				rtl_write_byte(rtlpriv, 0xa25,
+					       cckswing_table_ch14[cck_index]
+					       [3]);
+				rtl_write_byte(rtlpriv, 0xa26,
+					       cckswing_table_ch14[cck_index]
+					       [4]);
+				rtl_write_byte(rtlpriv, 0xa27,
+					       cckswing_table_ch14[cck_index]
+					       [5]);
+				rtl_write_byte(rtlpriv, 0xa28,
+					       cckswing_table_ch14[cck_index]
+					       [6]);
+				rtl_write_byte(rtlpriv, 0xa29,
+					       cckswing_table_ch14[cck_index]
+					       [7]);
+			}
+
+			if (is2t) {
+				ele_d = (ofdmswing_table[ofdm_index[1]] &
+					 0xFFC00000) >> 22;
+
+				val_x = rtlphy->reg_eb4;
+				val_y = rtlphy->reg_ebc;
+
+				if (val_x != 0) {
+					if ((val_x & 0x00000200) != 0)
+						val_x = val_x | 0xFFFFFC00;
+					ele_a = ((val_x * ele_d) >> 8) &
+					    0x000003FF;
+
+					if ((val_y & 0x00000200) != 0)
+						val_y = val_y | 0xFFFFFC00;
+					ele_c = ((val_y * ele_d) >> 8) &
+					    0x00003FF;
+
+					value32 = (ele_d << 22) |
+					    ((ele_c & 0x3F) << 16) | ele_a;
+					rtl_set_bbreg(hw,
+						      ROFDM0_XBTXIQIMBALANCE,
+						      MASKDWORD, value32);
+
+					value32 = (ele_c & 0x000003C0) >> 6;
+					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
+						      MASKH4BITS, value32);
+
+					value32 = ((val_x * ele_d) >> 7) & 0x01;
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(27), value32);
+
+					value32 = ((val_y * ele_d) >> 7) & 0x01;
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(25), value32);
+				} else {
+					rtl_set_bbreg(hw,
+						      ROFDM0_XBTXIQIMBALANCE,
+						      MASKDWORD,
+						      ofdmswing_table[ofdm_index
+								      [1]]);
+					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
+						      MASKH4BITS, 0x00);
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(27) | BIT(25), 0x00);
+				}
+
+			}
+		}
+
+		if (delta_iqk > 3) {
+			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+			rtl92c_phy_iq_calibrate(hw, false);
+		}
+
+		if (rtlpriv->dm.txpower_track_control)
+			rtlpriv->dm.thermalvalue = thermalvalue;
+	}
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
+
+}
+
+static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
+						struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.txpower_tracking = true;
+	rtlpriv->dm.txpower_trackingInit = false;
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("pMgntInfo->txpower_tracking = %d\n",
+		  rtlpriv->dm.txpower_tracking));
+}
+
+static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+	rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
+}
+
+static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
+{
+	rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
+}
+
+static void rtl92c_dm_check_txpower_tracking_thermal_meter(
+						struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	static u8 tm_trigger;
+
+	if (!rtlpriv->dm.txpower_tracking)
+		return;
+
+	if (!tm_trigger) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
+			      0x60);
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Trigger 92S Thermal Meter!!\n"));
+		tm_trigger = 1;
+		return;
+	} else {
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Schedule TxPowerTracking direct call!!\n"));
+		rtl92c_dm_txpower_tracking_directcall(hw);
+		tm_trigger = 0;
+	}
+}
+
+void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
+{
+	rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
+}
+EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
+
+void rtl92c_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;
+
+}
+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_rssithresh_for_ra, high_rssithresh_for_ra;
+
+	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) {
+
+		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.undecorated_smoothed_pwdb >
+		    (long)high_rssithresh_for_ra)
+			p_ra->ratr_state = DM_RATR_STA_HIGH;
+		else if (rtlpriv->dm.undecorated_smoothed_pwdb >
+			 (long)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.undecorated_smoothed_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));
+
+			rtlpriv->cfg->ops->update_rate_mask(hw,
+					p_ra->ratr_state);
+
+			p_ra->pre_ratr_state = p_ra->ratr_state;
+		}
+	}
+}
+
+static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
+{
+	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 rtl92c_dm_1r_cca(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (dm_pstable.rssi_val_min != 0) {
+		if (dm_pstable.pre_ccastate == CCA_2R) {
+			if (dm_pstable.rssi_val_min >= 35)
+				dm_pstable.cur_ccasate = CCA_1R;
+			else
+				dm_pstable.cur_ccasate = CCA_2R;
+		} else {
+			if (dm_pstable.rssi_val_min <= 30)
+				dm_pstable.cur_ccasate = CCA_2R;
+			else
+				dm_pstable.cur_ccasate = CCA_1R;
+		}
+	} else {
+		dm_pstable.cur_ccasate = CCA_MAX;
+	}
+
+	if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) {
+		if (dm_pstable.cur_ccasate == CCA_1R) {
+			if (get_rf_type(rtlphy) == RF_2T2R) {
+				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
+					      MASKBYTE0, 0x13);
+				rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20);
+			} else {
+				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
+					      MASKBYTE0, 0x23);
+				rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c);
+			}
+		} else {
+			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0,
+				      0x33);
+			rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63);
+		}
+		dm_pstable.pre_ccastate = dm_pstable.cur_ccasate;
+	}
+
+	RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n",
+					       (dm_pstable.cur_ccasate ==
+						0) ? "1RCCA" : "2RCCA"));
+}
+
+void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
+{
+	static u8 initialize;
+	static u32 reg_874, reg_c70, reg_85c, reg_a74;
+
+	if (initialize == 0) {
+		reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+					 MASKDWORD) & 0x1CC000) >> 14;
+
+		reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
+					 MASKDWORD) & BIT(3)) >> 3;
+
+		reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+					 MASKDWORD) & 0xFF000000) >> 24;
+
+		reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
+
+		initialize = 1;
+	}
+
+	if (!bforce_in_normal) {
+		if (dm_pstable.rssi_val_min != 0) {
+			if (dm_pstable.pre_rfstate == RF_NORMAL) {
+				if (dm_pstable.rssi_val_min >= 30)
+					dm_pstable.cur_rfstate = RF_SAVE;
+				else
+					dm_pstable.cur_rfstate = RF_NORMAL;
+			} else {
+				if (dm_pstable.rssi_val_min <= 25)
+					dm_pstable.cur_rfstate = RF_NORMAL;
+				else
+					dm_pstable.cur_rfstate = RF_SAVE;
+			}
+		} else {
+			dm_pstable.cur_rfstate = RF_MAX;
+		}
+	} else {
+		dm_pstable.cur_rfstate = RF_NORMAL;
+	}
+
+	if (dm_pstable.pre_rfstate != dm_pstable.cur_rfstate) {
+		if (dm_pstable.cur_rfstate == RF_SAVE) {
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0x1C0000, 0x2);
+			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
+			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+				      0xFF000000, 0x63);
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0xC000, 0x2);
+			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
+		} else {
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0x1CC000, reg_874);
+			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
+				      reg_c70);
+			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
+				      reg_85c);
+			rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+		}
+
+		dm_pstable.pre_rfstate = dm_pstable.cur_rfstate;
+	}
+}
+EXPORT_SYMBOL(rtl92c_dm_rf_saving);
+
+static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (((mac->link_state == MAC80211_NOLINK)) &&
+	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+		dm_pstable.rssi_val_min = 0;
+		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+			 ("Not connected to any\n"));
+	}
+
+	if (mac->link_state == MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			dm_pstable.rssi_val_min =
+			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+				 ("AP Client PWDB = 0x%lx\n",
+				  dm_pstable.rssi_val_min));
+		} else {
+			dm_pstable.rssi_val_min =
+			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+				 ("STA Default Port PWDB = 0x%lx\n",
+				  dm_pstable.rssi_val_min));
+		}
+	} else {
+		dm_pstable.rssi_val_min =
+		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+
+		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+			 ("AP Ext Port PWDB = 0x%lx\n",
+			  dm_pstable.rssi_val_min));
+	}
+
+	if (IS_92C_SERIAL(rtlhal->version))
+		rtl92c_dm_1r_cca(hw);
+}
+
+void rtl92c_dm_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+	rtl92c_dm_diginit(hw);
+	rtl92c_dm_init_dynamic_txpower(hw);
+	rtl92c_dm_init_edca_turbo(hw);
+	rtl92c_dm_init_rate_adaptive_mask(hw);
+	rtl92c_dm_initialize_txpower_tracking(hw);
+	rtl92c_dm_init_dynamic_bb_powersaving(hw);
+}
+EXPORT_SYMBOL(rtl92c_dm_init);
+
+void rtl92c_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->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
+					     fw_ps_awake)
+	    && (!ppsc->rfchange_inprogress)) {
+		rtl92c_dm_pwdb_monitor(hw);
+		rtl92c_dm_dig(hw);
+		rtl92c_dm_false_alarm_counter_statistics(hw);
+		rtl92c_dm_dynamic_bb_powersaving(hw);
+		rtlpriv->cfg->ops->dm_dynamic_txpower(hw);
+		rtl92c_dm_check_txpower_tracking(hw);
+		rtl92c_dm_refresh_rate_adaptive_mask(hw);
+		rtl92c_dm_check_edca_turbo(hw);
+
+	}
+}
+EXPORT_SYMBOL(rtl92c_dm_watchdog);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h
new file mode 100644
index 0000000..b9cbb0a
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h
@@ -0,0 +1,204 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef	__RTL92COMMON_DM_H__
+#define __RTL92COMMON_DM_H__
+
+#include "../wifi.h"
+#include "../rtl8192ce/def.h"
+#include "../rtl8192ce/reg.h"
+#include "fw_common.h"
+
+#define HAL_DM_DIG_DISABLE			BIT(0)
+#define HAL_DM_HIPWR_DISABLE			BIT(1)
+
+#define OFDM_TABLE_LENGTH			37
+#define CCK_TABLE_LENGTH			33
+
+#define OFDM_TABLE_SIZE				37
+#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_FA_UPPER				0x32
+#define DM_DIG_FA_LOWER				0x20
+#define DM_DIG_FA_TH0				0x20
+#define DM_DIG_FA_TH1				0x100
+#define DM_DIG_FA_TH2				0x200
+
+#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
+
+struct ps_t {
+	u8 pre_ccastate;
+	u8 cur_ccasate;
+	u8 pre_rfstate;
+	u8 cur_rfstate;
+	long rssi_val_min;
+};
+
+struct dig_t {
+	u8 dig_enable_flag;
+	u8 dig_ext_port_stage;
+	u32 rssi_lowthresh;
+	u32 rssi_highthresh;
+	u32 fa_lowthresh;
+	u32 fa_highthresh;
+	u8 cursta_connectctate;
+	u8 presta_connectstate;
+	u8 curmultista_connectstate;
+	u8 pre_igvalue;
+	u8 cur_igvalue;
+	char backoff_val;
+	char backoff_val_range_max;
+	char backoff_val_range_min;
+	u8 rx_gain_range_max;
+	u8 rx_gain_range_min;
+	u8 rssi_val_min;
+	u8 pre_cck_pd_state;
+	u8 cur_cck_pd_state;
+	u8 pre_cck_fa_state;
+	u8 cur_cck_fa_state;
+	u8 pre_ccastate;
+	u8 cur_ccasate;
+};
+
+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 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
+};
+
+extern struct dig_t dm_digtable;
+void rtl92c_dm_init(struct ieee80211_hw *hw);
+void rtl92c_dm_watchdog(struct ieee80211_hw *hw);
+void rtl92c_dm_write_dig(struct ieee80211_hw *hw);
+void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw);
+void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal);
+void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
new file mode 100644
index 0000000..5ef9137
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -0,0 +1,774 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include <linux/firmware.h>
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "../rtl8192ce/reg.h"
+#include "../rtl8192ce/def.h"
+#include "fw_common.h"
+
+static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
+		u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+		if (enable)
+			value32 |= MCUFWDL_EN;
+		else
+			value32 &= ~MCUFWDL_EN;
+		rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+	} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
+		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 _rtl92c_fw_block_write(struct ieee80211_hw *hw,
+				   const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 blockSize = sizeof(u32);
+	u8 *bufferPtr = (u8 *) buffer;
+	u32 *pu4BytePtr = (u32 *) buffer;
+	u32 i, offset, blockCount, remainSize;
+
+	blockCount = size / blockSize;
+	remainSize = size % blockSize;
+
+	for (i = 0; i < blockCount; i++) {
+		offset = i * blockSize;
+		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
+				*(pu4BytePtr + i));
+	}
+
+	if (remainSize) {
+		offset = blockCount * blockSize;
+		bufferPtr += offset;
+		for (i = 0; i < remainSize; i++) {
+			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
+						 offset + i), *(bufferPtr + i));
+		}
+	}
+}
+
+static void _rtl92c_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);
+	_rtl92c_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl92c_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 _rtl92c_write_fw(struct ieee80211_hw *hw,
+			     enum version_8192c version, u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 *bufferPtr = (u8 *) buffer;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
+
+	if (IS_CHIP_VER_B(version)) {
+		u32 pageNums, remainSize;
+		u32 page, offset;
+
+		if (IS_HARDWARE_TYPE_8192CE(rtlhal))
+			_rtl92c_fill_dummy(bufferPtr, &size);
+
+		pageNums = size / FW_8192C_PAGE_SIZE;
+		remainSize = size % FW_8192C_PAGE_SIZE;
+
+		if (pageNums > 4) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Page numbers should not greater then 4\n"));
+		}
+
+		for (page = 0; page < pageNums; page++) {
+			offset = page * FW_8192C_PAGE_SIZE;
+			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
+					      FW_8192C_PAGE_SIZE);
+		}
+
+		if (remainSize) {
+			offset = pageNums * FW_8192C_PAGE_SIZE;
+			page = pageNums;
+			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
+					      remainSize);
+		}
+	} else {
+		_rtl92c_fw_block_write(hw, buffer, size);
+	}
+}
+
+static int _rtl92c_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);
+
+	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;
+		}
+
+		mdelay(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 rtl92c_download_fw(struct ieee80211_hw *hw)
+{
+	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_8192c version = rtlhal->version;
+	const struct firmware *firmware;
+
+	printk(KERN_INFO "rtl8192cu: Loading firmware file %s\n",
+	       rtlpriv->cfg->fw_name);
+	err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
+			       rtlpriv->io.dev);
+	if (err) {
+		printk(KERN_ERR "rtl8192cu: Firmware loading failed\n");
+		return 1;
+	}
+
+	if (firmware->size > 0x4000) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is too big!\n"));
+		release_firmware(firmware);
+		return 1;
+	}
+
+	memcpy(rtlhal->pfirmware, firmware->data, firmware->size);
+	fwsize = firmware->size;
+	release_firmware(firmware);
+
+	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
+	pfwdata = (u8 *) rtlhal->pfirmware;
+
+	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,
+			  (uint)sizeof(struct rtl92c_firmware_header)));
+
+		pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
+		fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
+	}
+
+	_rtl92c_enable_fw_download(hw, true);
+	_rtl92c_write_fw(hw, version, pfwdata, fwsize);
+	_rtl92c_enable_fw_download(hw, false);
+
+	err = _rtl92c_fw_free_to_go(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is not ready to run!\n"));
+	} else {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 ("Firmware is ready to run!\n"));
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(rtl92c_download_fw);
+
+static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 val_hmetfr, val_mcutst_1;
+	bool result = false;
+
+	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+	val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
+
+	if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
+		result = true;
+	return result;
+}
+
+static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
+			      u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 boxnum;
+	u16 box_reg, box_extreg;
+	u8 u1b_tmp;
+	bool isfw_read = false;
+	u8 buf_index;
+	bool bwrite_sucess = false;
+	u8 wait_h2c_limmit = 100;
+	u8 wait_writeh2c_limmit = 100;
+	u8 boxcontent[4], boxextcontent[2];
+	u32 h2c_waitcounter = 0;
+	unsigned long flag;
+	u8 idx;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
+
+	while (true) {
+		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+		if (rtlhal->h2c_setinprogress) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("H2C set in progress! Wait to set.."
+				  "element_id(%d).\n", element_id));
+
+			while (rtlhal->h2c_setinprogress) {
+				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+						       flag);
+				h2c_waitcounter++;
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 ("Wait 100 us (%d times)...\n",
+					  h2c_waitcounter));
+				udelay(100);
+
+				if (h2c_waitcounter > 1000)
+					return;
+				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+						  flag);
+			}
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+		} else {
+			rtlhal->h2c_setinprogress = true;
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+			break;
+		}
+	}
+
+	while (!bwrite_sucess) {
+		wait_writeh2c_limmit--;
+		if (wait_writeh2c_limmit == 0) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Write H2C fail because no trigger "
+				  "for FW INT!\n"));
+			break;
+		}
+
+		boxnum = rtlhal->last_hmeboxnum;
+		switch (boxnum) {
+		case 0:
+			box_reg = REG_HMEBOX_0;
+			box_extreg = REG_HMEBOX_EXT_0;
+			break;
+		case 1:
+			box_reg = REG_HMEBOX_1;
+			box_extreg = REG_HMEBOX_EXT_1;
+			break;
+		case 2:
+			box_reg = REG_HMEBOX_2;
+			box_extreg = REG_HMEBOX_EXT_2;
+			break;
+		case 3:
+			box_reg = REG_HMEBOX_3;
+			box_extreg = REG_HMEBOX_EXT_3;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+
+		isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
+		while (!isfw_read) {
+
+			wait_h2c_limmit--;
+			if (wait_h2c_limmit == 0) {
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 ("Wating too long for FW read "
+					  "clear HMEBox(%d)!\n", boxnum));
+				break;
+			}
+
+			udelay(10);
+
+			isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
+			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("Wating for FW read clear HMEBox(%d)!!! "
+				  "0x1BF = %2x\n", boxnum, u1b_tmp));
+		}
+
+		if (!isfw_read) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("Write H2C register BOX[%d] fail!!!!! "
+				  "Fw do not read.\n", boxnum));
+			break;
+		}
+
+		memset(boxcontent, 0, sizeof(boxcontent));
+		memset(boxextcontent, 0, sizeof(boxextcontent));
+		boxcontent[0] = element_id;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("Write element_id box_reg(%4x) = %2x\n",
+			  box_reg, element_id));
+
+		switch (cmd_len) {
+		case 1:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index, 1);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 2:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index, 2);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 3:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index, 3);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 4:
+			boxcontent[0] |= (BIT(7));
+			memcpy((u8 *) (boxextcontent),
+			       p_cmdbuffer + buf_index, 2);
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index + 2, 2);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 5:
+			boxcontent[0] |= (BIT(7));
+			memcpy((u8 *) (boxextcontent),
+			       p_cmdbuffer + buf_index, 2);
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index + 2, 3);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+
+		bwrite_sucess = true;
+
+		rtlhal->last_hmeboxnum = boxnum + 1;
+		if (rtlhal->last_hmeboxnum == 4)
+			rtlhal->last_hmeboxnum = 0;
+
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("pHalData->last_hmeboxnum  = %d\n",
+			  rtlhal->last_hmeboxnum));
+	}
+
+	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+	rtlhal->h2c_setinprogress = false;
+	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
+}
+
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 tmp_cmdbuf[2];
+
+	if (rtlhal->fw_ready == false) {
+		RT_ASSERT(false, ("return H2C cmd because of Fw "
+				  "download fail!!!\n"));
+		return;
+	}
+
+	memset(tmp_cmdbuf, 0, 8);
+	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
+	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
+
+	return;
+}
+EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
+
+void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
+{
+	u8 u1b_tmp;
+	u8 delay = 100;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+
+	while (u1b_tmp & BIT(2)) {
+		delay--;
+		if (delay == 0) {
+			RT_ASSERT(false, ("8051 reset fail.\n"));
+			break;
+		}
+		udelay(50);
+		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+	}
+}
+EXPORT_SYMBOL(rtl92c_firmware_selfreset);
+
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1_h2c_set_pwrmode[3] = {0};
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
+
+	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+					      ppsc->reg_max_lps_awakeintvl);
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+		      u1_h2c_set_pwrmode, 3);
+	rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+
+}
+EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
+
+#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 rtl92c_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;
+	bool rtstatus;
+	u8 u1RsvdPageLoc[3] = {0};
+	bool b_dlok = false;
+
+	u8 *beacon;
+	u8 *p_pspoll;
+	u8 *nullfunc;
+	u8 *p_probersp;
+	/*---------------------------------------------------------
+				(1) beacon
+	---------------------------------------------------------*/
+	beacon = &reserved_page_packet[BEACON_PG * 128];
+	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+
+	/*-------------------------------------------------------
+				(2) ps-poll
+	--------------------------------------------------------*/
+	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+
+	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+
+	/*--------------------------------------------------------
+				(3) null data
+	---------------------------------------------------------*/
+	nullfunc = &reserved_page_packet[NULL_PG * 128];
+	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+
+	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+
+	/*---------------------------------------------------------
+				(4) probe response
+	----------------------------------------------------------*/
+	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+
+	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+
+	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      &reserved_page_packet[0], totalpacketlen);
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      u1RsvdPageLoc, 3);
+
+
+	skb = dev_alloc_skb(totalpacketlen);
+	memcpy((u8 *) skb_put(skb, totalpacketlen),
+	       &reserved_page_packet, totalpacketlen);
+
+	rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb);
+
+	if (rtstatus)
+		b_dlok = true;
+
+	if (b_dlok) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("Set RSVD page location to Fw.\n"));
+		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+				"H2C_RSVDPAGE:\n",
+				u1RsvdPageLoc, 3);
+		rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+				    sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+	} else
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
+}
+EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
+
+void rtl92c_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);
+
+	rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
+EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
new file mode 100644
index 0000000..3db33bd
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C__FW__H__
+#define __RTL92C__FW__H__
+
+#define FW_8192C_SIZE				0x3000
+#define FW_8192C_START_ADDRESS			0x1000
+#define FW_8192C_END_ADDRESS			0x3FFF
+#define FW_8192C_PAGE_SIZE			4096
+#define FW_8192C_POLLING_DELAY			5
+#define FW_8192C_POLLING_TIMEOUT_COUNT		100
+
+#define IS_FW_HEADER_EXIST(_pfwhdr)	\
+	((_pfwhdr->signature&0xFFF0) == 0x92C0 ||\
+	(_pfwhdr->signature&0xFFF0) == 0x88C0)
+
+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_AP_OFFLOAD = 0,
+	H2C_SETPWRMODE = 1,
+	H2C_JOINBSSRPT = 2,
+	H2C_RSVDPAGE = 3,
+	H2C_RSSI_REPORT = 5,
+	H2C_RA_MASK = 6,
+	MAX_H2CCMD
+};
+
+#define pagenum_128(_len)	(u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0))
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)			\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+
+int rtl92c_download_fw(struct ieee80211_hw *hw);
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+			 u32 cmd_len, u8 *p_cmdbuffer);
+void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
+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);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/main.c b/drivers/net/wireless/rtlwifi/rtl8192c/main.c
new file mode 100644
index 0000000..2f624fc
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/main.c
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+
+
+MODULE_AUTHOR("lizhaoming	<chaoming_li@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
+MODULE_AUTHOR("Georgia		<georgia@realtek.com>");
+MODULE_AUTHOR("Ziv Huang	<ziv_huang@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless");
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
new file mode 100644
index 0000000..a702282
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -0,0 +1,2042 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../rtl8192ce/reg.h"
+#include "../rtl8192ce/def.h"
+#include "dm_common.h"
+#include "phy_common.h"
+
+/* Define macro to shorten lines */
+#define MCS_TXPWR	mcs_txpwrlevel_origoffset
+
+u32 rtl92c_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 = _rtl92c_phy_calculate_bit_shift(bitmask);
+	returnvalue = (originalvalue & bitmask) >> bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
+					       "Addr[0x%x]=0x%x\n", bitmask,
+					       regaddr, originalvalue));
+
+	return returnvalue;
+
+}
+EXPORT_SYMBOL(rtl92c_phy_query_bb_reg);
+
+void rtl92c_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 = _rtl92c_phy_calculate_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));
+}
+EXPORT_SYMBOL(rtl92c_phy_set_bb_reg);
+
+u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+					 enum radio_path rfpath, u32 offset)
+{
+	RT_ASSERT(false, ("deprecated!\n"));
+	return 0;
+}
+EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read);
+
+void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+					   enum radio_path rfpath, u32 offset,
+					   u32 data)
+{
+	RT_ASSERT(false, ("deprecated!\n"));
+}
+EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write);
+
+u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
+				      enum radio_path rfpath, u32 offset)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+	u32 newoffset;
+	u32 tmplong, tmplong2;
+	u8 rfpi_enable = 0;
+	u32 retvalue;
+
+	offset &= 0x3f;
+	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 == RF90_PATH_A)
+		tmplong2 = tmplong;
+	else
+		tmplong2 = rtl_get_bbreg(hw, pphyreg->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, pphyreg->rfhssi_para2, MASKDWORD, tmplong2);
+	mdelay(1);
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+		      tmplong | BLSSIREADEDGE);
+	mdelay(1);
+	if (rfpath == RF90_PATH_A)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+						 BIT(8));
+	else if (rfpath == RF90_PATH_B)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+						 BIT(8));
+	if (rfpi_enable)
+		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+					 BLSSIREADBACKDATA);
+	else
+		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+					 BLSSIREADBACKDATA);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n",
+					       rfpath, pphyreg->rflssi_readback,
+					       retvalue));
+	return retvalue;
+}
+EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read);
+
+void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
+					enum radio_path rfpath, u32 offset,
+					u32 data)
+{
+	u32 data_and_addr;
+	u32 newoffset;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("stop\n"));
+		return;
+	}
+	offset &= 0x3f;
+	newoffset = offset;
+	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
+					       rfpath, pphyreg->rf3wire_offset,
+					       data_and_addr));
+}
+EXPORT_SYMBOL(_rtl92c_phy_rf_serial_write);
+
+u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask)
+{
+	u32 i;
+
+	for (i = 0; i <= 31; i++) {
+		if (((bitmask >> i) & 0x1) == 1)
+			break;
+	}
+	return i;
+}
+EXPORT_SYMBOL(_rtl92c_phy_calculate_bit_shift);
+
+static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
+	rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
+	rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
+	rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
+	rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
+}
+bool rtl92c_phy_rf_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtlpriv->cfg->ops->phy_rf6052_config(hw);
+}
+EXPORT_SYMBOL(rtl92c_phy_rf_config);
+
+bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	bool rtstatus;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
+	rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw,
+						 BASEBAND_CONFIG_PHY_REG);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
+		return false;
+	}
+	if (rtlphy->rf_type == RF_1T2R) {
+		_rtl92c_phy_bb_config_1t(hw);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
+	}
+	if (rtlefuse->autoload_failflag == false) {
+		rtlphy->pwrgroup_cnt = 0;
+		rtstatus = rtlpriv->cfg->ops->config_bb_with_pgheaderfile(hw,
+						   BASEBAND_CONFIG_PHY_REG);
+	}
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
+		return false;
+	}
+	rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw,
+						 BASEBAND_CONFIG_AGC_TAB);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
+		return false;
+	}
+	rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+						RFPGA0_XA_HSSIPARAMETER2,
+						0x200));
+	return true;
+}
+EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile);
+
+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (regaddr == RTXAGC_A_RATE18_06) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][0] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][0]));
+	}
+	if (regaddr == RTXAGC_A_RATE54_24) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][1] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][1]));
+	}
+	if (regaddr == RTXAGC_A_CCK1_MCS32) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][6] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][6]));
+	}
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][7] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][7]));
+	}
+	if (regaddr == RTXAGC_A_MCS03_MCS00) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][2] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][2]));
+	}
+	if (regaddr == RTXAGC_A_MCS07_MCS04) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][3] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][3]));
+	}
+	if (regaddr == RTXAGC_A_MCS11_MCS08) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][4] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][4]));
+	}
+	if (regaddr == RTXAGC_A_MCS15_MCS12) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][5] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][5]));
+	}
+	if (regaddr == RTXAGC_B_RATE18_06) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][8] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][8]));
+	}
+	if (regaddr == RTXAGC_B_RATE54_24) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9]));
+	}
+
+	if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14]));
+	}
+
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS03_MCS00) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS07_MCS04) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS11_MCS08) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS15_MCS12) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13]));
+
+		rtlphy->pwrgroup_cnt++;
+	}
+}
+EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset);
+
+void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->default_initialgain[0] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[1] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[2] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[3] =
+	    (u8) 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 = (u8) 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 _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_B].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[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_B].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[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+	    RFPGA0_XA_LSSIPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+	    RFPGA0_XB_LSSIPARAMETER;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_B].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[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
+	    RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
+	    RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
+	    RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
+	    RFPGA0_XCD_SWITCHCONTROL;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
+	    ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
+	    ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
+	    ROFDM0_XCRXIQIMBANLANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
+	    ROFDM0_XDRXIQIMBALANCE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
+	    ROFDM0_XATXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
+	    ROFDM0_XBTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
+	    ROFDM0_XCTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
+	    ROFDM0_XDTXIQIMBALANCE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
+	    RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
+	    RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
+	    RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
+	    RFPGA0_XD_LSSIREADBACK;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
+	    TRANSCEIVEA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
+	    TRANSCEIVEB_HSPI_READBACK;
+
+}
+EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition);
+
+void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 txpwr_level;
+	long txpwr_dbm;
+
+	txpwr_level = rtlphy->cur_cck_txpwridx;
+	txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw,
+						 WIRELESS_MODE_B, txpwr_level);
+	txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
+	    rtlefuse->legacy_ht_txpowerdiff;
+	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
+					 WIRELESS_MODE_G,
+					 txpwr_level) > txpwr_dbm)
+		txpwr_dbm =
+		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
+						 txpwr_level);
+	txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
+	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
+					 WIRELESS_MODE_N_24G,
+					 txpwr_level) > txpwr_dbm)
+		txpwr_dbm =
+		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
+						 txpwr_level);
+	*powerlevel = txpwr_dbm;
+}
+
+static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+				      u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 index = (channel - 1);
+
+	cckpowerlevel[RF90_PATH_A] =
+	    rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+	cckpowerlevel[RF90_PATH_B] =
+	    rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+	} else if (get_rf_type(rtlphy) == RF_2T2R) {
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+	}
+}
+
+static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw,
+					 u8 channel, u8 *cckpowerlevel,
+					 u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
+	u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+	if (rtlefuse->txpwr_fromeprom == false)
+		return;
+	_rtl92c_get_txpower_index(hw, channel,
+				  &cckpowerlevel[0], &ofdmpowerlevel[0]);
+	_rtl92c_ccxpower_index_check(hw,
+				     channel, &cckpowerlevel[0],
+				     &ofdmpowerlevel[0]);
+	rtlpriv->cfg->ops->phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+	rtlpriv->cfg->ops->phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0],
+						       channel);
+}
+EXPORT_SYMBOL(rtl92c_phy_set_txpower_level);
+
+bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 idx;
+	u8 rf_path;
+
+	u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
+						      WIRELESS_MODE_B,
+						      power_indbm);
+	u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
+						       WIRELESS_MODE_N_24G,
+						       power_indbm);
+	if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
+		ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
+	else
+		ofdmtxpwridx = 0;
+	RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
+		 ("%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
+		  power_indbm, ccktxpwridx, ofdmtxpwridx));
+	for (idx = 0; idx < 14; idx++) {
+		for (rf_path = 0; rf_path < 2; rf_path++) {
+			rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
+			rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
+			    ofdmtxpwridx;
+			rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
+			    ofdmtxpwridx;
+		}
+	}
+	rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+	return true;
+}
+EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm);
+
+void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval)
+{
+}
+EXPORT_SYMBOL(rtl92c_phy_set_beacon_hw_reg);
+
+u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+				enum wireless_mode wirelessmode,
+				long power_indbm)
+{
+	u8 txpwridx;
+	long offset;
+
+	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;
+	}
+
+	if ((power_indbm - offset) > 0)
+		txpwridx = (u8) ((power_indbm - offset) * 2);
+	else
+		txpwridx = 0;
+
+	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
+		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
+
+	return txpwridx;
+}
+EXPORT_SYMBOL(_rtl92c_phy_dbm_to_txpwr_Idx);
+
+long _rtl92c_phy_txpwr_idx_to_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;
+}
+EXPORT_SYMBOL(_rtl92c_phy_txpwr_idx_to_dbm);
+
+void rtl92c_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;
+		}
+	}
+}
+EXPORT_SYMBOL(rtl92c_phy_scan_operation_backup);
+
+void rtl92c_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)))
+		rtlpriv->cfg->ops->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;
+	}
+}
+EXPORT_SYMBOL(rtl92c_phy_set_bw_mode);
+
+void rtl92c_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 (!_rtl92c_phy_sw_chnl_step_by_step
+		    (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
+		     &rtlphy->sw_chnl_step, &delay)) {
+			if (delay > 0)
+				mdelay(delay);
+			else
+				continue;
+		} else
+			rtlphy->sw_chnl_inprogress = false;
+		break;
+	} while (true);
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+EXPORT_SYMBOL(rtl92c_phy_sw_chnl_callback);
+
+u8 rtl92c_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))) {
+		rtl92c_phy_sw_chnl_callback(hw);
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 ("sw_chnl_inprogress false schdule workitem\n"));
+		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;
+}
+EXPORT_SYMBOL(rtl92c_phy_sw_chnl);
+
+static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+					     u8 channel, u8 *stage, u8 *step,
+					     u32 *delay)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+	u32 precommoncmdcnt;
+	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+	u32 postcommoncmdcnt;
+	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+	u32 rfdependcmdcnt;
+	struct swchnlcmd *currentcmd = NULL;
+	u8 rfpath;
+	u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+	precommoncmdcnt = 0;
+	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					 MAX_PRECMD_CNT,
+					 CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
+	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					 MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+
+	postcommoncmdcnt = 0;
+
+	_rtl92c_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));
+
+	_rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+					 MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+					 RF_CHNLBW, channel, 10);
+
+	_rtl92c_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:
+			rtl92c_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 process\n"));
+			break;
+		}
+
+		break;
+	} while (true);
+
+	(*delay) = currentcmd->msdelay;
+	(*step)++;
+	return false;
+}
+
+static bool _rtl92c_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;
+}
+
+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath)
+{
+	return true;
+}
+EXPORT_SYMBOL(rtl8192_phy_check_is_legal_rfpath);
+
+static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
+{
+	u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
+	rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
+	rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
+	rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
+		      config_pathb ? 0x28160202 : 0x28160502);
+
+	if (config_pathb) {
+		rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
+		rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
+	}
+
+	rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
+	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);
+	reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
+
+	if (!(reg_eac & BIT(28)) &&
+	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+
+	if (!(reg_eac & BIT(27)) &&
+	    (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_eac & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static u8 _rtl92c_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 void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw,
+					       bool iqk_ok, long result[][8],
+					       u8 final_candidate, bool btxonly)
+{
+	u32 oldval_0, x, tx0_a, reg;
+	long y, tx0_c;
+
+	if (final_candidate == 0xFF)
+		return;
+	else if (iqk_ok) {
+		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					  MASKDWORD) >> 22) & 0x3FF;
+		x = result[final_candidate][0];
+		if ((x & 0x00000200) != 0)
+			x = x | 0xFFFFFC00;
+		tx0_a = (x * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31),
+			      ((x * oldval_0 >> 7) & 0x1));
+		y = result[final_candidate][1];
+		if ((y & 0x00000200) != 0)
+			y = y | 0xFFFFFC00;
+		tx0_c = (y * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
+			      ((tx0_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
+			      (tx0_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29),
+			      ((y * oldval_0 >> 7) & 0x1));
+		if (btxonly)
+			return;
+		reg = result[final_candidate][2];
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][3] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][3] >> 6) & 0xF;
+		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+	}
+}
+
+static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw,
+					       bool iqk_ok, long result[][8],
+					       u8 final_candidate, bool btxonly)
+{
+	u32 oldval_1, x, tx1_a, reg;
+	long y, tx1_c;
+
+	if (final_candidate == 0xFF)
+		return;
+	else if (iqk_ok) {
+		oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
+					  MASKDWORD) >> 22) & 0x3FF;
+		x = result[final_candidate][4];
+		if ((x & 0x00000200) != 0)
+			x = x | 0xFFFFFC00;
+		tx1_a = (x * oldval_1) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27),
+			      ((x * oldval_1 >> 7) & 0x1));
+		y = result[final_candidate][5];
+		if ((y & 0x00000200) != 0)
+			y = y | 0xFFFFFC00;
+		tx1_c = (y * oldval_1) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000,
+			      ((tx1_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000,
+			      (tx1_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25),
+			      ((y * oldval_1 >> 7) & 0x1));
+		if (btxonly)
+			return;
+		reg = result[final_candidate][6];
+		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][7] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][7] >> 6) & 0xF;
+		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
+	}
+}
+
+static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw,
+					    u32 *addareg, u32 *addabackup,
+					    u32 registernum)
+{
+	u32 i;
+
+	for (i = 0; i < registernum; i++)
+		addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
+}
+
+static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw,
+					   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 _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw,
+					      u32 *addareg, u32 *addabackup,
+					      u32 regiesternum)
+{
+	u32 i;
+
+	for (i = 0; i < regiesternum; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]);
+}
+
+static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw,
+					     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 _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw,
+				     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 _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+						u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	rtl_write_byte(rtlpriv, macreg[0], 0x3F);
+
+	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i],
+			       (u8) (macbackup[i] & (~BIT(3))));
+	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl92c_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 _rtl92c_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 _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw,
+					   long result[][8], u8 c1, u8 c2)
+{
+	u32 i, j, diff, simularity_bitmap, bound;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	u8 final_candidate[2] = { 0xFF, 0xFF };
+	bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version);
+
+	if (is2t)
+		bound = 8;
+	else
+		bound = 4;
+
+	simularity_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) && !simularity_bitmap) {
+				if (result[c1][i] + result[c1][i + 1] == 0)
+					final_candidate[(i / 4)] = c2;
+				else if (result[c2][i] + result[c2][i + 1] == 0)
+					final_candidate[(i / 4)] = c1;
+				else
+					simularity_bitmap = simularity_bitmap |
+					    (1 << i);
+			} else
+				simularity_bitmap =
+				    simularity_bitmap | (1 << i);
+		}
+	}
+
+	if (simularity_bitmap == 0) {
+		for (i = 0; i < (bound / 4); i++) {
+			if (final_candidate[i] != 0xFF) {
+				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+					result[3][j] =
+					    result[final_candidate[i]][j];
+				bresult = false;
+			}
+		}
+		return bresult;
+	} else if (!(simularity_bitmap & 0x0F)) {
+		for (i = 0; i < 4; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else if (!(simularity_bitmap & 0xF0) && is2t) {
+		for (i = 4; i < 8; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else {
+		return false;
+	}
+
+}
+
+static void _rtl92c_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;
+	u32 adda_reg[IQK_ADDA_REG_NUM] = {
+		0x85c, 0xe6c, 0xe70, 0xe74,
+		0xe78, 0xe7c, 0xe80, 0xe84,
+		0xe88, 0xe8c, 0xed0, 0xed4,
+		0xed8, 0xedc, 0xee0, 0xeec
+	};
+
+	u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+
+	const u32 retrycount = 2;
+
+	u32 bbvalue;
+
+	if (t == 0) {
+		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+
+		_rtl92c_phy_save_adda_registers(hw, adda_reg,
+						rtlphy->adda_backup, 16);
+		_rtl92c_phy_save_mac_registers(hw, iqk_mac_reg,
+					       rtlphy->iqk_mac_backup);
+	}
+	_rtl92c_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)
+		_rtl92c_phy_pi_mode_switch(hw, true);
+	if (t == 0) {
+		rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
+		rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
+		rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
+	}
+	rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
+	if (is2t) {
+		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
+	}
+	_rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg,
+					    rtlphy->iqk_mac_backup);
+	rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
+	if (is2t)
+		rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+	rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
+	rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
+	for (i = 0; i < retrycount; i++) {
+		patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t);
+		if (patha_ok == 0x03) {
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
+					0x3FF0000) >> 16;
+			break;
+		} else if (i == (retrycount - 1) && patha_ok == 0x01)
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94,
+						      MASKDWORD) & 0x3FF0000) >>
+						      16;
+		result[t][1] =
+		    (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
+
+	}
+
+	if (is2t) {
+		_rtl92c_phy_path_a_standby(hw);
+		_rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t);
+		for (i = 0; i < retrycount; i++) {
+			pathb_ok = _rtl92c_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, 0xc04, MASKDWORD, rtlphy->reg_c04);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
+	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
+	if (is2t)
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
+	if (t != 0) {
+		if (!rtlphy->rfpi_enable)
+			_rtl92c_phy_pi_mode_switch(hw, false);
+		_rtl92c_phy_reload_adda_registers(hw, adda_reg,
+						  rtlphy->adda_backup, 16);
+		_rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg,
+						 rtlphy->iqk_mac_backup);
+	}
+}
+
+static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw,
+				     char delta, bool is2t)
+{
+	/* This routine is deliberately dummied out for later fixes */
+#if 0
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+
+	u32 reg_d[PATH_NUM];
+	u32 tmpreg, index, offset, path, i, pathbound = PATH_NUM, apkbound;
+
+	u32 bb_backup[APK_BB_REG_NUM];
+	u32 bb_reg[APK_BB_REG_NUM] = {
+		0x904, 0xc04, 0x800, 0xc08, 0x874
+	};
+	u32 bb_ap_mode[APK_BB_REG_NUM] = {
+		0x00000020, 0x00a05430, 0x02040000,
+		0x000800e4, 0x00204000
+	};
+	u32 bb_normal_ap_mode[APK_BB_REG_NUM] = {
+		0x00000020, 0x00a05430, 0x02040000,
+		0x000800e4, 0x22204000
+	};
+
+	u32 afe_backup[APK_AFE_REG_NUM];
+	u32 afe_reg[APK_AFE_REG_NUM] = {
+		0x85c, 0xe6c, 0xe70, 0xe74, 0xe78,
+		0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
+		0xed0, 0xed4, 0xed8, 0xedc, 0xee0,
+		0xeec
+	};
+
+	u32 mac_backup[IQK_MAC_REG_NUM];
+	u32 mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+
+	u32 apk_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
+		{0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
+	};
+
+	u32 apk_normal_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c},
+		{0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
+	};
+
+	u32 apk_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
+		{0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
+	};
+
+	u32 apk_normal_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a},
+		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
+	};
+
+	u32 afe_on_off[PATH_NUM] = {
+		0x04db25a4, 0x0b1b25a4
+	};
+
+	u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c };
+
+	u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 };
+
+	u32 apk_value[PATH_NUM] = { 0x92fc0000, 0x12fc0000 };
+
+	u32 apk_normal_value[PATH_NUM] = { 0x92680000, 0x12680000 };
+
+	const char apk_delta_mapping[APK_BB_REG_NUM][13] = {
+		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
+	};
+
+	const u32 apk_normal_setting_value_1[13] = {
+		0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
+		0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
+		0x12680000, 0x00880000, 0x00880000
+	};
+
+	const u32 apk_normal_setting_value_2[16] = {
+		0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
+		0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
+		0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
+		0x00050006
+	};
+
+	const u32 apk_result[PATH_NUM][APK_BB_REG_NUM];
+
+	long bb_offset, delta_v, delta_offset;
+
+	if (!is2t)
+		pathbound = 1;
+
+	for (index = 0; index < PATH_NUM; index++) {
+		apk_offset[index] = apk_normal_offset[index];
+		apk_value[index] = apk_normal_value[index];
+		afe_on_off[index] = 0x6fdb25a4;
+	}
+
+	for (index = 0; index < APK_BB_REG_NUM; index++) {
+		for (path = 0; path < pathbound; path++) {
+			apk_rf_init_value[path][index] =
+			    apk_normal_rf_init_value[path][index];
+			apk_rf_value_0[path][index] =
+			    apk_normal_rf_value_0[path][index];
+		}
+		bb_ap_mode[index] = bb_normal_ap_mode[index];
+
+		apkbound = 6;
+	}
+
+	for (index = 0; index < APK_BB_REG_NUM; index++) {
+		if (index == 0)
+			continue;
+		bb_backup[index] = rtl_get_bbreg(hw, bb_reg[index], MASKDWORD);
+	}
+
+	_rtl92c_phy_save_mac_registers(hw, mac_reg, mac_backup);
+
+	_rtl92c_phy_save_adda_registers(hw, afe_reg, afe_backup, 16);
+
+	for (path = 0; path < pathbound; path++) {
+		if (path == RF90_PATH_A) {
+			offset = 0xb00;
+			for (index = 0; index < 11; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+
+			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
+
+			offset = 0xb68;
+			for (; index < 13; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
+
+			offset = 0xb00;
+			for (index = 0; index < 16; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_2
+					      [index]);
+
+				offset += 0x04;
+			}
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
+		} else if (path == RF90_PATH_B) {
+			offset = 0xb70;
+			for (index = 0; index < 10; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+			rtl_set_bbreg(hw, 0xb28, MASKDWORD, 0x12680000);
+			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
+
+			offset = 0xb68;
+			index = 11;
+			for (; index < 13; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
+
+			offset = 0xb60;
+			for (index = 0; index < 16; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_2
+					      [index]);
+
+				offset += 0x04;
+			}
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
+		}
+
+		reg_d[path] = rtl_get_rfreg(hw, (enum radio_path)path,
+					    0xd, MASKDWORD);
+
+		for (index = 0; index < APK_AFE_REG_NUM; index++)
+			rtl_set_bbreg(hw, afe_reg[index], MASKDWORD,
+				      afe_on_off[path]);
+
+		if (path == RF90_PATH_A) {
+			for (index = 0; index < APK_BB_REG_NUM; index++) {
+				if (index == 0)
+					continue;
+				rtl_set_bbreg(hw, bb_reg[index], MASKDWORD,
+					      bb_ap_mode[index]);
+			}
+		}
+
+		_rtl92c_phy_mac_setting_calibration(hw, mac_reg, mac_backup);
+
+		if (path == 0) {
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x0, MASKDWORD, 0x10000);
+		} else {
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASKDWORD,
+				      0x10000);
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
+				      0x1000f);
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
+				      0x20103);
+		}
+
+		delta_offset = ((delta + 14) / 2);
+		if (delta_offset < 0)
+			delta_offset = 0;
+		else if (delta_offset > 12)
+			delta_offset = 12;
+
+		for (index = 0; index < APK_BB_REG_NUM; index++) {
+			if (index != 1)
+				continue;
+
+			tmpreg = apk_rf_init_value[path][index];
+
+			if (!rtlefuse->apk_thermalmeterignore) {
+				bb_offset = (tmpreg & 0xF0000) >> 16;
+
+				if (!(tmpreg & BIT(15)))
+					bb_offset = -bb_offset;
+
+				delta_v =
+				    apk_delta_mapping[index][delta_offset];
+
+				bb_offset += delta_v;
+
+				if (bb_offset < 0) {
+					tmpreg = tmpreg & (~BIT(15));
+					bb_offset = -bb_offset;
+				} else {
+					tmpreg = tmpreg | BIT(15);
+				}
+
+				tmpreg =
+				    (tmpreg & 0xFFF0FFFF) | (bb_offset << 16);
+			}
+
+			rtl_set_rfreg(hw, (enum radio_path)path, 0xc,
+				      MASKDWORD, 0x8992e);
+			rtl_set_rfreg(hw, (enum radio_path)path, 0x0,
+				      MASKDWORD, apk_rf_value_0[path][index]);
+			rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
+				      MASKDWORD, tmpreg);
+
+			i = 0;
+			do {
+				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80000000);
+				rtl_set_bbreg(hw, apk_offset[path],
+					      MASKDWORD, apk_value[0]);
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("PHY_APCalibrate() offset 0x%x "
+					 "value 0x%x\n",
+					 apk_offset[path],
+					 rtl_get_bbreg(hw, apk_offset[path],
+						       MASKDWORD)));
+
+				mdelay(3);
+
+				rtl_set_bbreg(hw, apk_offset[path],
+					      MASKDWORD, apk_value[1]);
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("PHY_APCalibrate() offset 0x%x "
+					 "value 0x%x\n",
+					 apk_offset[path],
+					 rtl_get_bbreg(hw, apk_offset[path],
+						       MASKDWORD)));
+
+				mdelay(20);
+
+				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
+
+				if (path == RF90_PATH_A)
+					tmpreg = rtl_get_bbreg(hw, 0xbd8,
+							       0x03E00000);
+				else
+					tmpreg = rtl_get_bbreg(hw, 0xbd8,
+							       0xF8000000);
+
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("PHY_APCalibrate() offset "
+					 "0xbd8[25:21] %x\n", tmpreg));
+
+				i++;
+
+			} while (tmpreg > apkbound && i < 4);
+
+			apk_result[path][index] = tmpreg;
+		}
+	}
+
+	_rtl92c_phy_reload_mac_registers(hw, mac_reg, mac_backup);
+
+	for (index = 0; index < APK_BB_REG_NUM; index++) {
+		if (index == 0)
+			continue;
+		rtl_set_bbreg(hw, bb_reg[index], MASKDWORD, bb_backup[index]);
+	}
+
+	_rtl92c_phy_reload_adda_registers(hw, afe_reg, afe_backup, 16);
+
+	for (path = 0; path < pathbound; path++) {
+		rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
+			      MASKDWORD, reg_d[path]);
+
+		if (path == RF90_PATH_B) {
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
+				      0x1000f);
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
+				      0x20101);
+		}
+
+		if (apk_result[path][1] > 6)
+			apk_result[path][1] = 6;
+	}
+
+	for (path = 0; path < pathbound; path++) {
+		rtl_set_rfreg(hw, (enum radio_path)path, 0x3, MASKDWORD,
+			      ((apk_result[path][1] << 15) |
+			       (apk_result[path][1] << 10) |
+			       (apk_result[path][1] << 5) |
+			       apk_result[path][1]));
+
+		if (path == RF90_PATH_A)
+			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
+				      ((apk_result[path][1] << 15) |
+				       (apk_result[path][1] << 10) |
+				       (0x00 << 5) | 0x05));
+		else
+			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
+				      ((apk_result[path][1] << 15) |
+				       (apk_result[path][1] << 10) |
+				       (0x02 << 5) | 0x05));
+
+		rtl_set_rfreg(hw, (enum radio_path)path, 0xe, MASKDWORD,
+			      ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) |
+			       0x08));
+
+	}
+
+	rtlphy->apk_done = true;
+#endif
+}
+
+static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw,
+					  bool bmain, bool is2t)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (is_hal_stop(rtlhal)) {
+		rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
+		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 {
+		if (bmain)
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
+		else
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
+
+	}
+}
+
+#undef IQK_ADDA_REG_NUM
+#undef IQK_DELAY_TIME
+
+void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	long result[4][8];
+	u8 i, final_candidate;
+	bool patha_ok, pathb_ok;
+	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
+	    reg_ecc, reg_tmp = 0;
+	bool is12simular, is13simular, is23simular;
+	bool start_conttx = false, singletone = false;
+	u32 iqk_bb_reg[10] = {
+		ROFDM0_XARXIQIMBALANCE,
+		ROFDM0_XBRXIQIMBALANCE,
+		ROFDM0_ECCATHRESHOLD,
+		ROFDM0_AGCRSSITABLE,
+		ROFDM0_XATXIQIMBALANCE,
+		ROFDM0_XBTXIQIMBALANCE,
+		ROFDM0_XCTXIQIMBALANCE,
+		ROFDM0_XCTXAFE,
+		ROFDM0_XDTXAFE,
+		ROFDM0_RXIQEXTANTA
+	};
+
+	if (recovery) {
+		_rtl92c_phy_reload_adda_registers(hw,
+						  iqk_bb_reg,
+						  rtlphy->iqk_bb_backup, 10);
+		return;
+	}
+	if (start_conttx || singletone)
+		return;
+	for (i = 0; i < 8; i++) {
+		result[0][i] = 0;
+		result[1][i] = 0;
+		result[2][i] = 0;
+		result[3][i] = 0;
+	}
+	final_candidate = 0xff;
+	patha_ok = false;
+	pathb_ok = false;
+	is12simular = false;
+	is23simular = false;
+	is13simular = false;
+	for (i = 0; i < 3; i++) {
+		if (IS_92C_SERIAL(rtlhal->version))
+			_rtl92c_phy_iq_calibrate(hw, result, i, true);
+		else
+			_rtl92c_phy_iq_calibrate(hw, result, i, false);
+		if (i == 1) {
+			is12simular = _rtl92c_phy_simularity_compare(hw,
+								     result, 0,
+								     1);
+			if (is12simular) {
+				final_candidate = 0;
+				break;
+			}
+		}
+		if (i == 2) {
+			is13simular = _rtl92c_phy_simularity_compare(hw,
+								     result, 0,
+								     2);
+			if (is13simular) {
+				final_candidate = 0;
+				break;
+			}
+			is23simular = _rtl92c_phy_simularity_compare(hw,
+								     result, 1,
+								     2);
+			if (is23simular)
+				final_candidate = 1;
+			else {
+				for (i = 0; i < 8; i++)
+					reg_tmp += result[3][i];
+
+				if (reg_tmp != 0)
+					final_candidate = 3;
+				else
+					final_candidate = 0xFF;
+			}
+		}
+	}
+	for (i = 0; i < 4; i++) {
+		reg_e94 = result[i][0];
+		reg_e9c = result[i][1];
+		reg_ea4 = result[i][2];
+		reg_eac = result[i][3];
+		reg_eb4 = result[i][4];
+		reg_ebc = result[i][5];
+		reg_ec4 = result[i][6];
+		reg_ecc = result[i][7];
+	}
+	if (final_candidate != 0xff) {
+		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
+		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
+		reg_ea4 = result[final_candidate][2];
+		reg_eac = result[final_candidate][3];
+		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
+		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
+		reg_ec4 = result[final_candidate][6];
+		reg_ecc = result[final_candidate][7];
+		patha_ok = pathb_ok = true;
+	} else {
+		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
+		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
+	}
+	if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
+		_rtl92c_phy_path_a_fill_iqk_matrix(hw, patha_ok, result,
+						   final_candidate,
+						   (reg_ea4 == 0));
+	if (IS_92C_SERIAL(rtlhal->version)) {
+		if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */
+			_rtl92c_phy_path_b_fill_iqk_matrix(hw, pathb_ok,
+							   result,
+							   final_candidate,
+							   (reg_ec4 == 0));
+	}
+	_rtl92c_phy_save_adda_registers(hw, iqk_bb_reg,
+					rtlphy->iqk_bb_backup, 10);
+}
+EXPORT_SYMBOL(rtl92c_phy_iq_calibrate);
+
+void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool start_conttx = false, singletone = false;
+
+	if (start_conttx || singletone)
+		return;
+	if (IS_92C_SERIAL(rtlhal->version))
+		rtlpriv->cfg->ops->phy_lc_calibrate(hw, true);
+	else
+		rtlpriv->cfg->ops->phy_lc_calibrate(hw, false);
+}
+EXPORT_SYMBOL(rtl92c_phy_lc_calibrate);
+
+void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlphy->apk_done)
+		return;
+	if (IS_92C_SERIAL(rtlhal->version))
+		_rtl92c_phy_ap_calibrate(hw, delta, true);
+	else
+		_rtl92c_phy_ap_calibrate(hw, delta, false);
+}
+EXPORT_SYMBOL(rtl92c_phy_ap_calibrate);
+
+void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (IS_92C_SERIAL(rtlhal->version))
+		_rtl92c_phy_set_rfpath_switch(hw, bmain, true);
+	else
+		_rtl92c_phy_set_rfpath_switch(hw, bmain, false);
+}
+EXPORT_SYMBOL(rtl92c_phy_set_rfpath_switch);
+
+bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool postprocessing = false;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+		  iotype, rtlphy->set_io_inprogress));
+	do {
+		switch (iotype) {
+		case IO_CMD_RESUME_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 ("[IO CMD] Resume DM after scan.\n"));
+			postprocessing = true;
+			break;
+		case IO_CMD_PAUSE_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 ("[IO CMD] Pause DM before scan.\n"));
+			postprocessing = true;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+	} while (false);
+	if (postprocessing && !rtlphy->set_io_inprogress) {
+		rtlphy->set_io_inprogress = true;
+		rtlphy->current_io_type = iotype;
+	} else {
+		return false;
+	}
+	rtl92c_phy_set_io(hw);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
+	return true;
+}
+EXPORT_SYMBOL(rtl92c_phy_set_io_cmd);
+
+void rtl92c_phy_set_io(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("--->Cmd(%#x), set_io_inprogress(%d)\n",
+		  rtlphy->current_io_type, rtlphy->set_io_inprogress));
+	switch (rtlphy->current_io_type) {
+	case IO_CMD_RESUME_DM_BY_SCAN:
+		dm_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+		rtl92c_dm_write_dig(hw);
+		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+		break;
+	case IO_CMD_PAUSE_DM_BY_SCAN:
+		rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
+		dm_digtable.cur_igvalue = 0x17;
+		rtl92c_dm_write_dig(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	rtlphy->set_io_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("<---(%#x)\n", rtlphy->current_io_type));
+}
+EXPORT_SYMBOL(rtl92c_phy_set_io);
+
+void rtl92ce_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);
+}
+EXPORT_SYMBOL(rtl92ce_phy_set_rf_on);
+
+void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw)
+{
+	u32 u4b_tmp;
+	u8 delay = 5;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+	u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+	while (u4b_tmp != 0 && delay > 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+		u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+		delay--;
+	}
+	if (delay == 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 ("Switch RF timeout !!!.\n"));
+		return;
+	}
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+}
+EXPORT_SYMBOL(_rtl92c_phy_set_rf_sleep);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
new file mode 100644
index 0000000..53ffb09
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
@@ -0,0 +1,246 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_PHY_H__
+#define __RTL92C_PHY_H__
+
+#define MAX_PRECMD_CNT			16
+#define MAX_RFDEPENDCMD_CNT		16
+#define MAX_POSTCMD_CNT			16
+
+#define MAX_DOZE_WAITING_TIMES_9x	64
+
+#define RT_CANNOT_IO(hw)		false
+#define HIGHPOWER_RADIOA_ARRAYLEN	22
+
+#define MAX_TOLERANCE			5
+#define	IQK_DELAY_TIME			1
+
+#define	APK_BB_REG_NUM			5
+#define	APK_AFE_REG_NUM			16
+#define	APK_CURVE_REG_NUM		4
+#define	PATH_NUM			2
+
+#define LOOP_LIMIT			5
+#define MAX_STALL_TIME			50
+#define 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 RF90_PATH_MAX			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_DIF	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
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER	255
+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];
+};
+
+extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw,
+				   u32 regaddr, u32 bitmask);
+extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
+				  u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
+				   enum radio_path rfpath, u32 regaddr,
+				   u32 bitmask);
+extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
+				  enum radio_path rfpath, u32 regaddr,
+				  u32 bitmask, u32 data);
+extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+						 enum radio_path rfpath);
+extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw,
+					 long *powerlevel);
+extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw,
+					  long power_indbm);
+extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw,
+					     u8 operation);
+extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
+				   enum nl80211_channel_type ch_type);
+extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw);
+extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
+extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw,
+					 u16 beaconinterval);
+void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
+bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw,
+					      u32 rfpath);
+extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					  enum rf_pwrstate rfpwr_state);
+void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
+void rtl92c_phy_set_io(struct ieee80211_hw *hw);
+void rtl92c_bb_block_on(struct ieee80211_hw *hw);
+u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
+long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+				  enum wireless_mode wirelessmode,
+				  u8 txpwridx);
+u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+				enum wireless_mode wirelessmode,
+				long power_indbm);
+void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
+static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+					     u32 cmdtableidx, u32 cmdtablesz,
+					     enum swchnlcmd_id cmdid, u32 para1,
+					     u32 para2, u32 msdelay);
+static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+					     u8 channel, u8 *stage, u8 *step,
+					     u32 *delay);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile b/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile
index 0f0be7c..c0cb0cf 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile
@@ -1,6 +1,5 @@
 rtl8192ce-objs :=		\
 		dm.o		\
-		fw.o		\
 		hw.o		\
 		led.o		\
 		phy.o		\
@@ -10,3 +9,5 @@ rtl8192ce-objs :=		\
 		trx.o
 
 obj-$(CONFIG_RTL8192CE) += rtl8192ce.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 83cd648..2f577c8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -121,11 +121,37 @@
 #define CHIP_92C			0x01
 #define CHIP_88C			0x00
 
+/* Add vendor information into chip version definition.
+ * Add UMC B-Cut and RTL8723 chip info definition.
+ *
+ * BIT 7	Reserved
+ * BIT 6	UMC BCut
+ * BIT 5	Manufacturer(TSMC/UMC)
+ * BIT 4	TEST/NORMAL
+ * BIT 3	8723 Version
+ * BIT 2	8723?
+ * BIT 1	1T2R?
+ * BIT 0	88C/92C
+*/
+
 enum version_8192c {
 	VERSION_A_CHIP_92C = 0x01,
 	VERSION_A_CHIP_88C = 0x00,
 	VERSION_B_CHIP_92C = 0x11,
 	VERSION_B_CHIP_88C = 0x10,
+	VERSION_TEST_CHIP_88C = 0x00,
+	VERSION_TEST_CHIP_92C = 0x01,
+	VERSION_NORMAL_TSMC_CHIP_88C = 0x10,
+	VERSION_NORMAL_TSMC_CHIP_92C = 0x11,
+	VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13,
+	VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30,
+	VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31,
+	VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33,
+	VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34,
+	VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c,
+	VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70,
+	VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71,
+	VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73,
 	VERSION_UNKNOWN = 0x88,
 };
 
@@ -254,4 +280,122 @@ struct h2c_cmd_8192c {
 	u8 *p_cmdbuffer;
 };
 
+static inline u8 _rtl92c_get_chnl_group(u8 chnl)
+{
+	u8 group = 0;
+
+	if (chnl < 3)
+		group = 0;
+	else if (chnl < 9)
+		group = 1;
+	else
+		group = 2;
+
+	return group;
+}
+
+/* NOTE: reference to rtl8192c_rates struct */
+static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT,
+				       u8 desc_rate, bool first_ampdu)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int rate_idx = 0;
+
+	if (first_ampdu) {
+		if (false == isHT) {
+			switch (desc_rate) {
+			case DESC92C_RATE1M:
+				rate_idx = 0;
+				break;
+			case DESC92C_RATE2M:
+				rate_idx = 1;
+				break;
+			case DESC92C_RATE5_5M:
+				rate_idx = 2;
+				break;
+			case DESC92C_RATE11M:
+				rate_idx = 3;
+				break;
+			case DESC92C_RATE6M:
+				rate_idx = 4;
+				break;
+			case DESC92C_RATE9M:
+				rate_idx = 5;
+				break;
+			case DESC92C_RATE12M:
+				rate_idx = 6;
+				break;
+			case DESC92C_RATE18M:
+				rate_idx = 7;
+				break;
+			case DESC92C_RATE24M:
+				rate_idx = 8;
+				break;
+			case DESC92C_RATE36M:
+				rate_idx = 9;
+				break;
+			case DESC92C_RATE48M:
+				rate_idx = 10;
+				break;
+			case DESC92C_RATE54M:
+				rate_idx = 11;
+				break;
+			default:
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+					 ("Rate %d is not support, set to "
+					"1M rate.\n", desc_rate));
+				rate_idx = 0;
+				break;
+			}
+		} else {
+			rate_idx = 11;
+		}
+		return rate_idx;
+	}
+	switch (desc_rate) {
+	case DESC92C_RATE1M:
+		rate_idx = 0;
+		break;
+	case DESC92C_RATE2M:
+		rate_idx = 1;
+		break;
+	case DESC92C_RATE5_5M:
+		rate_idx = 2;
+		break;
+	case DESC92C_RATE11M:
+		rate_idx = 3;
+		break;
+	case DESC92C_RATE6M:
+		rate_idx = 4;
+		break;
+	case DESC92C_RATE9M:
+		rate_idx = 5;
+		break;
+	case DESC92C_RATE12M:
+		rate_idx = 6;
+		break;
+	case DESC92C_RATE18M:
+		rate_idx = 7;
+		break;
+	case DESC92C_RATE24M:
+		rate_idx = 8;
+		break;
+	case DESC92C_RATE36M:
+		rate_idx = 9;
+		break;
+	case DESC92C_RATE48M:
+		rate_idx = 10;
+		break;
+	case DESC92C_RATE54M:
+		rate_idx = 11;
+		break;
+	/* TODO: How to mapping MCS rate? */
+	/*  NOTE: referenc to __ieee80211_rx */
+	default:
+		rate_idx = 11;
+		break;
+	}
+	return rate_idx;
+}
+
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
index 62e7c64..7d76504 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
@@ -33,487 +33,15 @@
 #include "def.h"
 #include "phy.h"
 #include "dm.h"
-#include "fw.h"
 
-struct dig_t dm_digtable;
-static struct ps_t dm_pstable;
-
-static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
-	0x7f8001fe,
-	0x788001e2,
-	0x71c001c7,
-	0x6b8001ae,
-	0x65400195,
-	0x5fc0017f,
-	0x5a400169,
-	0x55400155,
-	0x50800142,
-	0x4c000130,
-	0x47c0011f,
-	0x43c0010f,
-	0x40000100,
-	0x3c8000f2,
-	0x390000e4,
-	0x35c000d7,
-	0x32c000cb,
-	0x300000c0,
-	0x2d4000b5,
-	0x2ac000ab,
-	0x288000a2,
-	0x26000098,
-	0x24000090,
-	0x22000088,
-	0x20000080,
-	0x1e400079,
-	0x1c800072,
-	0x1b00006c,
-	0x19800066,
-	0x18000060,
-	0x16c0005b,
-	0x15800056,
-	0x14400051,
-	0x1300004c,
-	0x12000048,
-	0x11000044,
-	0x10000040,
-};
-
-static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
-	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
-	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
-	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
-	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
-	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
-	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
-	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
-	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
-	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
-	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
-	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
-	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
-	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
-	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
-	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
-	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
-	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
-	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
-	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
-	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
-	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
-	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
-	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
-	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
-	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
-	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
-	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
-	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
-	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
-	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
-	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
-	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
-	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
-};
-
-static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
-	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
-	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
-	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
-	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
-	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
-	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
-	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
-	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
-	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
-	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
-	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
-	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
-};
-
-static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
-{
-	dm_digtable.dig_enable_flag = true;
-	dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-	dm_digtable.cur_igvalue = 0x20;
-	dm_digtable.pre_igvalue = 0x0;
-	dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
-	dm_digtable.presta_connectstate = DIG_STA_DISCONNECT;
-	dm_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
-	dm_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
-	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.backoff_val = DM_DIG_BACKOFF_DEFAULT;
-	dm_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
-	dm_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
-	dm_digtable.pre_cck_pd_state = CCK_PD_STAGE_MAX;
-	dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
-}
-
-static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	long rssi_val_min = 0;
-
-	if ((dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
-	    (dm_digtable.cursta_connectctate == DIG_STA_CONNECT)) {
-		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
-			rssi_val_min =
-			    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
-			     rtlpriv->dm.undecorated_smoothed_pwdb) ?
-			    rtlpriv->dm.undecorated_smoothed_pwdb :
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-		else
-			rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT ||
-		   dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT) {
-		rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable.curmultista_connectstate ==
-		   DIG_MULTISTA_CONNECT) {
-		rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-	}
-
-	return (u8) rssi_val_min;
-}
-
-static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
-{
-	u32 ret_value;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
-
-	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
-	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
-
-	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
-	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
-	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
-
-	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
-	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
-	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
-	    falsealm_cnt->cnt_rate_illegal +
-	    falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
-
-	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
-	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
-	falsealm_cnt->cnt_cck_fail = ret_value;
-
-	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
-	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
-	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
-				 falsealm_cnt->cnt_rate_illegal +
-				 falsealm_cnt->cnt_crc8_fail +
-				 falsealm_cnt->cnt_mcs_fail +
-				 falsealm_cnt->cnt_cck_fail);
-
-	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
-	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
-	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
-	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 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",
-		  falsealm_cnt->cnt_parity_fail,
-		  falsealm_cnt->cnt_rate_illegal,
-		  falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail));
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
-		  falsealm_cnt->cnt_ofdm_fail,
-		  falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all));
-}
-
-static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 value_igi = dm_digtable.cur_igvalue;
-
-	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
-		value_igi--;
-	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
-		value_igi += 0;
-	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
-		value_igi++;
-	else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
-		value_igi += 2;
-	if (value_igi > DM_DIG_FA_UPPER)
-		value_igi = DM_DIG_FA_UPPER;
-	else if (value_igi < DM_DIG_FA_LOWER)
-		value_igi = DM_DIG_FA_LOWER;
-	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
-		value_igi = 0x32;
-
-	dm_digtable.cur_igvalue = value_igi;
-	rtl92c_dm_write_dig(hw);
-}
-
-static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable.fa_highthresh) {
-		if ((dm_digtable.backoff_val - 2) <
-		    dm_digtable.backoff_val_range_min)
-			dm_digtable.backoff_val =
-			    dm_digtable.backoff_val_range_min;
-		else
-			dm_digtable.backoff_val -= 2;
-	} else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable.fa_lowthresh) {
-		if ((dm_digtable.backoff_val + 2) >
-		    dm_digtable.backoff_val_range_max)
-			dm_digtable.backoff_val =
-			    dm_digtable.backoff_val_range_max;
-		else
-			dm_digtable.backoff_val += 2;
-	}
-
-	if ((dm_digtable.rssi_val_min + 10 - dm_digtable.backoff_val) >
-	    dm_digtable.rx_gain_range_max)
-		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_max;
-	else if ((dm_digtable.rssi_val_min + 10 -
-		  dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
-		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_min;
-	else
-		dm_digtable.cur_igvalue = dm_digtable.rssi_val_min + 10 -
-		    dm_digtable.backoff_val;
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("rssi_val_min = %x backoff_val %x\n",
-		  dm_digtable.rssi_val_min, dm_digtable.backoff_val));
-
-	rtl92c_dm_write_dig(hw);
-}
-
-static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
-{
-	static u8 binitialized; /* initialized to false */
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-	bool b_multi_sta = false;
-
-	if (mac->opmode == NL80211_IFTYPE_ADHOC)
-		b_multi_sta = true;
-
-	if ((b_multi_sta == false) || (dm_digtable.cursta_connectctate !=
-				       DIG_STA_DISCONNECT)) {
-		binitialized = false;
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-		return;
-	} else if (binitialized == false) {
-		binitialized = true;
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
-		dm_digtable.cur_igvalue = 0x20;
-		rtl92c_dm_write_dig(hw);
-	}
-
-	if (dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) {
-		if ((rssi_strength < dm_digtable.rssi_lowthresh) &&
-		    (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
-
-			if (dm_digtable.dig_ext_port_stage ==
-			    DIG_EXT_PORT_STAGE_2) {
-				dm_digtable.cur_igvalue = 0x20;
-				rtl92c_dm_write_dig(hw);
-			}
-
-			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
-		} else if (rssi_strength > dm_digtable.rssi_highthresh) {
-			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
-			rtl92c_dm_ctrl_initgain_by_fa(hw);
-		}
-	} else if (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
-		dm_digtable.cur_igvalue = 0x20;
-		rtl92c_dm_write_dig(hw);
-	}
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("curmultista_connectstate = "
-		  "%x dig_ext_port_stage %x\n",
-		  dm_digtable.curmultista_connectstate,
-		  dm_digtable.dig_ext_port_stage));
-}
-
-static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("presta_connectstate = %x,"
-		  " cursta_connectctate = %x\n",
-		  dm_digtable.presta_connectstate,
-		  dm_digtable.cursta_connectctate));
-
-	if (dm_digtable.presta_connectstate == dm_digtable.cursta_connectctate
-	    || dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT
-	    || dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
-
-		if (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT) {
-			dm_digtable.rssi_val_min =
-			    rtl92c_dm_initial_gain_min_pwdb(hw);
-			rtl92c_dm_ctrl_initgain_by_rssi(hw);
-		}
-	} else {
-		dm_digtable.rssi_val_min = 0;
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-		dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
-		dm_digtable.cur_igvalue = 0x20;
-		dm_digtable.pre_igvalue = 0;
-		rtl92c_dm_write_dig(hw);
-	}
-}
-
-static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
-		dm_digtable.rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
-
-		if (dm_digtable.pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
-			if (dm_digtable.rssi_val_min <= 25)
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_LowRssi;
-			else
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_HighRssi;
-		} else {
-			if (dm_digtable.rssi_val_min <= 20)
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_LowRssi;
-			else
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_HighRssi;
-		}
-	} else {
-		dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
-	}
-
-	if (dm_digtable.pre_cck_pd_state != dm_digtable.cur_cck_pd_state) {
-		if (dm_digtable.cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
-			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
-				dm_digtable.cur_cck_fa_state =
-				    CCK_FA_STAGE_High;
-			else
-				dm_digtable.cur_cck_fa_state = CCK_FA_STAGE_Low;
-
-			if (dm_digtable.pre_cck_fa_state !=
-			    dm_digtable.cur_cck_fa_state) {
-				if (dm_digtable.cur_cck_fa_state ==
-				    CCK_FA_STAGE_Low)
-					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
-						      0x83);
-				else
-					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
-						      0xcd);
-
-				dm_digtable.pre_cck_fa_state =
-				    dm_digtable.cur_cck_fa_state;
-			}
-
-			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
-
-			if (IS_92C_SERIAL(rtlhal->version))
-				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
-					      MASKBYTE2, 0xd7);
-		} else {
-			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
-			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
-
-			if (IS_92C_SERIAL(rtlhal->version))
-				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
-					      MASKBYTE2, 0xd3);
-		}
-		dm_digtable.pre_cck_pd_state = dm_digtable.cur_cck_pd_state;
-	}
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("CCKPDStage=%x\n", dm_digtable.cur_cck_pd_state));
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("is92C=%x\n", IS_92C_SERIAL(rtlhal->version)));
-}
-
-static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
-{
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-
-	if (mac->act_scanning == true)
-		return;
-
-	if ((mac->link_state > MAC80211_NOLINK) &&
-	    (mac->link_state < MAC80211_LINKED))
-		dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT;
-	else if (mac->link_state >= MAC80211_LINKED)
-		dm_digtable.cursta_connectctate = DIG_STA_CONNECT;
-	else
-		dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
-
-	rtl92c_dm_initial_gain_sta(hw);
-	rtl92c_dm_initial_gain_multi_sta(hw);
-	rtl92c_dm_cck_packet_detection_thresh(hw);
-
-	dm_digtable.presta_connectstate = dm_digtable.cursta_connectctate;
-
-}
-
-static void rtl92c_dm_dig(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	if (rtlpriv->dm.b_dm_initialgain_enable == false)
-		return;
-	if (dm_digtable.dig_enable_flag == false)
-		return;
-
-	rtl92c_dm_ctrl_initgain_by_twoport(hw);
-
-}
-
-static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtlpriv->dm.bdynamic_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)
+void rtl92ce_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 undecorated_smoothed_pwdb;
 
-	if (!rtlpriv->dm.bdynamic_txpower_enable)
+	if (!rtlpriv->dm.dynamic_txpower_enable)
 		return;
 
 	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
@@ -583,891 +111,3 @@ static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
 
 	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
 }
-
-void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
-		 ("cur_igvalue = 0x%x, "
-		  "pre_igvalue = 0x%x, backoff_val = %d\n",
-		  dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
-		  dm_digtable.backoff_val));
-
-	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
-		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
-			      dm_digtable.cur_igvalue);
-		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
-			      dm_digtable.cur_igvalue);
-
-		dm_digtable.pre_igvalue = dm_digtable.cur_igvalue;
-	}
-}
-
-static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
-
-	u8 h2c_parameter[3] = { 0 };
-
-	return;
-
-	if (tmpentry_max_pwdb != 0) {
-		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
-		    tmpentry_max_pwdb;
-	} else {
-		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
-	}
-
-	if (tmpentry_min_pwdb != 0xff) {
-		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
-		    tmpentry_min_pwdb;
-	} else {
-		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
-	}
-
-	h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
-	h2c_parameter[0] = 0;
-
-	rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
-}
-
-void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	rtlpriv->dm.bcurrent_turbo_edca = false;
-	rtlpriv->dm.bis_any_nonbepkts = false;
-	rtlpriv->dm.bis_cur_rdlstate = false;
-}
-
-static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	static u64 last_txok_cnt;
-	static u64 last_rxok_cnt;
-	u64 cur_txok_cnt;
-	u64 cur_rxok_cnt;
-	u32 edca_be_ul = 0x5ea42b;
-	u32 edca_be_dl = 0x5ea42b;
-
-	if (mac->opmode == NL80211_IFTYPE_ADHOC)
-		goto dm_checkedcaturbo_exit;
-
-	if (mac->link_state != MAC80211_LINKED) {
-		rtlpriv->dm.bcurrent_turbo_edca = false;
-		return;
-	}
-
-	if (!mac->ht_enable) {	/*FIX MERGE */
-		if (!(edca_be_ul & 0xffff0000))
-			edca_be_ul |= 0x005e0000;
-
-		if (!(edca_be_dl & 0xffff0000))
-			edca_be_dl |= 0x005e0000;
-	}
-
-	if ((!rtlpriv->dm.bis_any_nonbepkts) &&
-	    (!rtlpriv->dm.b_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.bis_cur_rdlstate ||
-			    !rtlpriv->dm.bcurrent_turbo_edca) {
-				rtl_write_dword(rtlpriv,
-						REG_EDCA_BE_PARAM,
-						edca_be_dl);
-				rtlpriv->dm.bis_cur_rdlstate = true;
-			}
-		} else {
-			if (rtlpriv->dm.bis_cur_rdlstate ||
-			    !rtlpriv->dm.bcurrent_turbo_edca) {
-				rtl_write_dword(rtlpriv,
-						REG_EDCA_BE_PARAM,
-						edca_be_ul);
-				rtlpriv->dm.bis_cur_rdlstate = false;
-			}
-		}
-		rtlpriv->dm.bcurrent_turbo_edca = true;
-	} else {
-		if (rtlpriv->dm.bcurrent_turbo_edca) {
-			u8 tmp = AC0_BE;
-			rtlpriv->cfg->ops->set_hw_reg(hw,
-						      HW_VAR_AC_PARAM,
-						      (u8 *) (&tmp));
-			rtlpriv->dm.bcurrent_turbo_edca = false;
-		}
-	}
-
-dm_checkedcaturbo_exit:
-	rtlpriv->dm.bis_any_nonbepkts = false;
-	last_txok_cnt = rtlpriv->stats.txbytesunicast;
-	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
-}
-
-static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
-							     *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 thermalvalue, delta, delta_lck, delta_iqk;
-	long ele_a, ele_d, temp_cck, val_x, value32;
-	long val_y, ele_c;
-	u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old;
-	int i;
-	bool is2t = IS_92C_SERIAL(rtlhal->version);
-	u8 txpwr_level[2] = {0, 0};
-	u8 ofdm_min_index = 6, rf;
-
-	rtlpriv->dm.btxpower_trackingInit = true;
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n"));
-
-	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
-
-	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));
-
-	rtl92c_phy_ap_calibrate(hw, (thermalvalue -
-				     rtlefuse->eeprom_thermalmeter));
-	if (is2t)
-		rf = 2;
-	else
-		rf = 1;
-
-	if (thermalvalue) {
-		ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-				      MASKDWORD) & MASKOFDM_D;
-
-		for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
-			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
-				ofdm_index_old[0] = (u8) i;
-
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					("Initial pathA ele_d reg0x%x = 0x%lx, "
-					 "ofdm_index=0x%x\n",
-					 ROFDM0_XATXIQIMBALANCE,
-					 ele_d, ofdm_index_old[0]));
-				break;
-			}
-		}
-
-		if (is2t) {
-			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
-					      MASKDWORD) & MASKOFDM_D;
-
-			for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
-				if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
-					ofdm_index_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_XBTXIQIMBALANCE, ele_d,
-					   ofdm_index_old[1]));
-					break;
-				}
-			}
-		}
-
-		temp_cck =
-		    rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
-
-		for (i = 0; i < CCK_TABLE_LENGTH; i++) {
-			if (rtlpriv->dm.b_cck_inch14) {
-				if (memcmp((void *)&temp_cck,
-					   (void *)&cckswing_table_ch14[i][2],
-					   4) == 0) {
-					cck_index_old = (u8) i;
-
-					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
-						 DBG_LOUD,
-						 ("Initial reg0x%x = 0x%lx, "
-						  "cck_index=0x%x, ch 14 %d\n",
-						  RCCK0_TXFILTER2, temp_cck,
-						  cck_index_old,
-						  rtlpriv->dm.b_cck_inch14));
-					break;
-				}
-			} else {
-				if (memcmp((void *)&temp_cck,
-					   (void *)
-					   &cckswing_table_ch1ch13[i][2],
-					   4) == 0) {
-					cck_index_old = (u8) i;
-
-					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
-						 DBG_LOUD,
-						 ("Initial reg0x%x = 0x%lx, "
-						  "cck_index=0x%x, ch14 %d\n",
-						  RCCK0_TXFILTER2, temp_cck,
-						  cck_index_old,
-						  rtlpriv->dm.b_cck_inch14));
-					break;
-				}
-			}
-		}
-
-		if (!rtlpriv->dm.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_index_old[i];
-			rtlpriv->dm.cck_index = cck_index_old;
-		}
-
-		delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
-		    (thermalvalue - rtlpriv->dm.thermalvalue) :
-		    (rtlpriv->dm.thermalvalue - 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));
-
-		if (delta_lck > 1) {
-			rtlpriv->dm.thermalvalue_lck = thermalvalue;
-			rtl92c_phy_lc_calibrate(hw);
-		}
-
-		if (delta > 0 && rtlpriv->dm.txpower_track_control) {
-			if (thermalvalue > rtlpriv->dm.thermalvalue) {
-				for (i = 0; i < rf; i++)
-					rtlpriv->dm.ofdm_index[i] -= delta;
-				rtlpriv->dm.cck_index -= delta;
-			} else {
-				for (i = 0; i < rf; i++)
-					rtlpriv->dm.ofdm_index[i] += delta;
-				rtlpriv->dm.cck_index += delta;
-			}
-
-			if (is2t) {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("temp OFDM_A_index=0x%x, "
-					  "OFDM_B_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  rtlpriv->dm.ofdm_index[0],
-					  rtlpriv->dm.ofdm_index[1],
-					  rtlpriv->dm.cck_index));
-			} else {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("temp OFDM_A_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  rtlpriv->dm.ofdm_index[0],
-					  rtlpriv->dm.cck_index));
-			}
-
-			if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
-				for (i = 0; i < rf; i++)
-					ofdm_index[i] =
-					    rtlpriv->dm.ofdm_index[i]
-					    + 1;
-				cck_index = rtlpriv->dm.cck_index + 1;
-			} else {
-				for (i = 0; i < rf; i++)
-					ofdm_index[i] =
-					    rtlpriv->dm.ofdm_index[i];
-				cck_index = rtlpriv->dm.cck_index;
-			}
-
-			for (i = 0; i < rf; i++) {
-				if (txpwr_level[i] >= 0 &&
-				    txpwr_level[i] <= 26) {
-					if (thermalvalue >
-					    rtlefuse->eeprom_thermalmeter) {
-						if (delta < 5)
-							ofdm_index[i] -= 1;
-
-						else
-							ofdm_index[i] -= 2;
-					} else if (delta > 5 && thermalvalue <
-						   rtlefuse->
-						   eeprom_thermalmeter) {
-						ofdm_index[i] += 1;
-					}
-				} else if (txpwr_level[i] >= 27 &&
-					   txpwr_level[i] <= 32
-					   && thermalvalue >
-					   rtlefuse->eeprom_thermalmeter) {
-					if (delta < 5)
-						ofdm_index[i] -= 1;
-
-					else
-						ofdm_index[i] -= 2;
-				} else if (txpwr_level[i] >= 32 &&
-					   txpwr_level[i] <= 38 &&
-					   thermalvalue >
-					   rtlefuse->eeprom_thermalmeter
-					   && delta > 5) {
-					ofdm_index[i] -= 1;
-				}
-			}
-
-			if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
-				if (thermalvalue >
-				    rtlefuse->eeprom_thermalmeter) {
-					if (delta < 5)
-						cck_index -= 1;
-
-					else
-						cck_index -= 2;
-				} else if (delta > 5 && thermalvalue <
-					   rtlefuse->eeprom_thermalmeter) {
-					cck_index += 1;
-				}
-			} else if (txpwr_level[i] >= 27 &&
-				   txpwr_level[i] <= 32 &&
-				   thermalvalue >
-				   rtlefuse->eeprom_thermalmeter) {
-				if (delta < 5)
-					cck_index -= 1;
-
-				else
-					cck_index -= 2;
-			} else if (txpwr_level[i] >= 32 &&
-				   txpwr_level[i] <= 38 &&
-				   thermalvalue > rtlefuse->eeprom_thermalmeter
-				   && delta > 5) {
-				cck_index -= 1;
-			}
-
-			for (i = 0; i < rf; i++) {
-				if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
-					ofdm_index[i] = OFDM_TABLE_SIZE - 1;
-
-				else if (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;
-
-			if (is2t) {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("new OFDM_A_index=0x%x, "
-					  "OFDM_B_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  ofdm_index[0], ofdm_index[1],
-					  cck_index));
-			} else {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("new OFDM_A_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  ofdm_index[0], cck_index));
-			}
-		}
-
-		if (rtlpriv->dm.txpower_track_control && delta != 0) {
-			ele_d =
-			    (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
-			val_x = rtlphy->reg_e94;
-			val_y = rtlphy->reg_e9c;
-
-			if (val_x != 0) {
-				if ((val_x & 0x00000200) != 0)
-					val_x = val_x | 0xFFFFFC00;
-				ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
-
-				if ((val_y & 0x00000200) != 0)
-					val_y = val_y | 0xFFFFFC00;
-				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
-
-				value32 = (ele_d << 22) |
-				    ((ele_c & 0x3F) << 16) | ele_a;
-
-				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-					      MASKDWORD, value32);
-
-				value32 = (ele_c & 0x000003C0) >> 6;
-				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
-					      value32);
-
-				value32 = ((val_x * ele_d) >> 7) & 0x01;
-				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-					      BIT(31), value32);
-
-				value32 = ((val_y * ele_d) >> 7) & 0x01;
-				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-					      BIT(29), value32);
-			} else {
-				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-					      MASKDWORD,
-					      ofdmswing_table[ofdm_index[0]]);
-
-				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
-					      0x00);
-				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-					      BIT(31) | BIT(29), 0x00);
-			}
-
-			if (!rtlpriv->dm.b_cck_inch14) {
-				rtl_write_byte(rtlpriv, 0xa22,
-					       cckswing_table_ch1ch13[cck_index]
-					       [0]);
-				rtl_write_byte(rtlpriv, 0xa23,
-					       cckswing_table_ch1ch13[cck_index]
-					       [1]);
-				rtl_write_byte(rtlpriv, 0xa24,
-					       cckswing_table_ch1ch13[cck_index]
-					       [2]);
-				rtl_write_byte(rtlpriv, 0xa25,
-					       cckswing_table_ch1ch13[cck_index]
-					       [3]);
-				rtl_write_byte(rtlpriv, 0xa26,
-					       cckswing_table_ch1ch13[cck_index]
-					       [4]);
-				rtl_write_byte(rtlpriv, 0xa27,
-					       cckswing_table_ch1ch13[cck_index]
-					       [5]);
-				rtl_write_byte(rtlpriv, 0xa28,
-					       cckswing_table_ch1ch13[cck_index]
-					       [6]);
-				rtl_write_byte(rtlpriv, 0xa29,
-					       cckswing_table_ch1ch13[cck_index]
-					       [7]);
-			} else {
-				rtl_write_byte(rtlpriv, 0xa22,
-					       cckswing_table_ch14[cck_index]
-					       [0]);
-				rtl_write_byte(rtlpriv, 0xa23,
-					       cckswing_table_ch14[cck_index]
-					       [1]);
-				rtl_write_byte(rtlpriv, 0xa24,
-					       cckswing_table_ch14[cck_index]
-					       [2]);
-				rtl_write_byte(rtlpriv, 0xa25,
-					       cckswing_table_ch14[cck_index]
-					       [3]);
-				rtl_write_byte(rtlpriv, 0xa26,
-					       cckswing_table_ch14[cck_index]
-					       [4]);
-				rtl_write_byte(rtlpriv, 0xa27,
-					       cckswing_table_ch14[cck_index]
-					       [5]);
-				rtl_write_byte(rtlpriv, 0xa28,
-					       cckswing_table_ch14[cck_index]
-					       [6]);
-				rtl_write_byte(rtlpriv, 0xa29,
-					       cckswing_table_ch14[cck_index]
-					       [7]);
-			}
-
-			if (is2t) {
-				ele_d = (ofdmswing_table[ofdm_index[1]] &
-					 0xFFC00000) >> 22;
-
-				val_x = rtlphy->reg_eb4;
-				val_y = rtlphy->reg_ebc;
-
-				if (val_x != 0) {
-					if ((val_x & 0x00000200) != 0)
-						val_x = val_x | 0xFFFFFC00;
-					ele_a = ((val_x * ele_d) >> 8) &
-					    0x000003FF;
-
-					if ((val_y & 0x00000200) != 0)
-						val_y = val_y | 0xFFFFFC00;
-					ele_c = ((val_y * ele_d) >> 8) &
-					    0x00003FF;
-
-					value32 = (ele_d << 22) |
-					    ((ele_c & 0x3F) << 16) | ele_a;
-					rtl_set_bbreg(hw,
-						      ROFDM0_XBTXIQIMBALANCE,
-						      MASKDWORD, value32);
-
-					value32 = (ele_c & 0x000003C0) >> 6;
-					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
-						      MASKH4BITS, value32);
-
-					value32 = ((val_x * ele_d) >> 7) & 0x01;
-					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-						      BIT(27), value32);
-
-					value32 = ((val_y * ele_d) >> 7) & 0x01;
-					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-						      BIT(25), value32);
-				} else {
-					rtl_set_bbreg(hw,
-						      ROFDM0_XBTXIQIMBALANCE,
-						      MASKDWORD,
-						      ofdmswing_table[ofdm_index
-								      [1]]);
-					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
-						      MASKH4BITS, 0x00);
-					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-						      BIT(27) | BIT(25), 0x00);
-				}
-
-			}
-		}
-
-		if (delta_iqk > 3) {
-			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
-			rtl92c_phy_iq_calibrate(hw, false);
-		}
-
-		if (rtlpriv->dm.txpower_track_control)
-			rtlpriv->dm.thermalvalue = thermalvalue;
-	}
-
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
-
-}
-
-static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
-						struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtlpriv->dm.btxpower_tracking = true;
-	rtlpriv->dm.btxpower_trackingInit = false;
-
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 ("pMgntInfo->btxpower_tracking = %d\n",
-		  rtlpriv->dm.btxpower_tracking));
-}
-
-static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
-{
-	rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
-}
-
-static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
-{
-	rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
-}
-
-static void rtl92c_dm_check_txpower_tracking_thermal_meter(
-						struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	static u8 tm_trigger;
-
-	if (!rtlpriv->dm.btxpower_tracking)
-		return;
-
-	if (!tm_trigger) {
-		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
-			      0x60);
-		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-			 ("Trigger 92S Thermal Meter!!\n"));
-		tm_trigger = 1;
-		return;
-	} else {
-		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-			 ("Schedule TxPowerTracking direct call!!\n"));
-		rtl92c_dm_txpower_tracking_directcall(hw);
-		tm_trigger = 0;
-	}
-}
-
-void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
-{
-	rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
-}
-
-void rtl92c_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.b_useramask = true;
-	else
-		rtlpriv->dm.b_useramask = false;
-
-}
-
-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_rssithresh_for_ra, high_rssithresh_for_ra;
-
-	if (is_hal_stop(rtlhal)) {
-		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-			 ("<---- driver is going to unload\n"));
-		return;
-	}
-
-	if (!rtlpriv->dm.b_useramask) {
-		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-			("<---- driver does not control rate adaptive mask\n"));
-		return;
-	}
-
-	if (mac->link_state == MAC80211_LINKED) {
-
-		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.undecorated_smoothed_pwdb >
-		    (long)high_rssithresh_for_ra)
-			p_ra->ratr_state = DM_RATR_STA_HIGH;
-		else if (rtlpriv->dm.undecorated_smoothed_pwdb >
-			 (long)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.undecorated_smoothed_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));
-
-			rtlpriv->cfg->ops->update_rate_mask(hw,
-					p_ra->ratr_state);
-
-			p_ra->pre_ratr_state = p_ra->ratr_state;
-		}
-	}
-}
-
-static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
-{
-	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 rtl92c_dm_1r_cca(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	if (dm_pstable.rssi_val_min != 0) {
-		if (dm_pstable.pre_ccastate == CCA_2R) {
-			if (dm_pstable.rssi_val_min >= 35)
-				dm_pstable.cur_ccasate = CCA_1R;
-			else
-				dm_pstable.cur_ccasate = CCA_2R;
-		} else {
-			if (dm_pstable.rssi_val_min <= 30)
-				dm_pstable.cur_ccasate = CCA_2R;
-			else
-				dm_pstable.cur_ccasate = CCA_1R;
-		}
-	} else {
-		dm_pstable.cur_ccasate = CCA_MAX;
-	}
-
-	if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) {
-		if (dm_pstable.cur_ccasate == CCA_1R) {
-			if (get_rf_type(rtlphy) == RF_2T2R) {
-				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
-					      MASKBYTE0, 0x13);
-				rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20);
-			} else {
-				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
-					      MASKBYTE0, 0x23);
-				rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c);
-			}
-		} else {
-			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0,
-				      0x33);
-			rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63);
-		}
-		dm_pstable.pre_ccastate = dm_pstable.cur_ccasate;
-	}
-
-	RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n",
-					       (dm_pstable.cur_ccasate ==
-						0) ? "1RCCA" : "2RCCA"));
-}
-
-void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
-{
-	static u8 initialize;
-	static u32 reg_874, reg_c70, reg_85c, reg_a74;
-
-	if (initialize == 0) {
-		reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-					 MASKDWORD) & 0x1CC000) >> 14;
-
-		reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
-					 MASKDWORD) & BIT(3)) >> 3;
-
-		reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
-					 MASKDWORD) & 0xFF000000) >> 24;
-
-		reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
-
-		initialize = 1;
-	}
-
-	if (!bforce_in_normal) {
-		if (dm_pstable.rssi_val_min != 0) {
-			if (dm_pstable.pre_rfstate == RF_NORMAL) {
-				if (dm_pstable.rssi_val_min >= 30)
-					dm_pstable.cur_rfstate = RF_SAVE;
-				else
-					dm_pstable.cur_rfstate = RF_NORMAL;
-			} else {
-				if (dm_pstable.rssi_val_min <= 25)
-					dm_pstable.cur_rfstate = RF_NORMAL;
-				else
-					dm_pstable.cur_rfstate = RF_SAVE;
-			}
-		} else {
-			dm_pstable.cur_rfstate = RF_MAX;
-		}
-	} else {
-		dm_pstable.cur_rfstate = RF_NORMAL;
-	}
-
-	if (dm_pstable.pre_rfstate != dm_pstable.cur_rfstate) {
-		if (dm_pstable.cur_rfstate == RF_SAVE) {
-			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-				      0x1C0000, 0x2);
-			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
-			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
-				      0xFF000000, 0x63);
-			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-				      0xC000, 0x2);
-			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
-			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
-			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
-		} else {
-			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-				      0x1CC000, reg_874);
-			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
-				      reg_c70);
-			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
-				      reg_85c);
-			rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
-			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
-		}
-
-		dm_pstable.pre_rfstate = dm_pstable.cur_rfstate;
-	}
-}
-
-static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (((mac->link_state == MAC80211_NOLINK)) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
-		dm_pstable.rssi_val_min = 0;
-		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-			 ("Not connected to any\n"));
-	}
-
-	if (mac->link_state == MAC80211_LINKED) {
-		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			dm_pstable.rssi_val_min =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-				 ("AP Client PWDB = 0x%lx\n",
-				  dm_pstable.rssi_val_min));
-		} else {
-			dm_pstable.rssi_val_min =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
-			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-				 ("STA Default Port PWDB = 0x%lx\n",
-				  dm_pstable.rssi_val_min));
-		}
-	} else {
-		dm_pstable.rssi_val_min =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-
-		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-			 ("AP Ext Port PWDB = 0x%lx\n",
-			  dm_pstable.rssi_val_min));
-	}
-
-	if (IS_92C_SERIAL(rtlhal->version))
-		rtl92c_dm_1r_cca(hw);
-}
-
-void rtl92c_dm_init(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
-	rtl92c_dm_diginit(hw);
-	rtl92c_dm_init_dynamic_txpower(hw);
-	rtl92c_dm_init_edca_turbo(hw);
-	rtl92c_dm_init_rate_adaptive_mask(hw);
-	rtl92c_dm_initialize_txpower_tracking(hw);
-	rtl92c_dm_init_dynamic_bb_powersaving(hw);
-}
-
-void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	bool b_fw_current_inpsmode = false;
-	bool b_fw_ps_awake = true;
-
-	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
-				      (u8 *) (&b_fw_current_inpsmode));
-	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
-				      (u8 *) (&b_fw_ps_awake));
-
-	if ((ppsc->rfpwr_state == ERFON) && ((!b_fw_current_inpsmode) &&
-					     b_fw_ps_awake)
-	    && (!ppsc->rfchange_inprogress)) {
-		rtl92c_dm_pwdb_monitor(hw);
-		rtl92c_dm_dig(hw);
-		rtl92c_dm_false_alarm_counter_statistics(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_check_edca_turbo(hw);
-	}
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h
index 463439e..36302eb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h
@@ -192,5 +192,6 @@ void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw);
 void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw);
 void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
 void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal);
+void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c
deleted file mode 100644
index 11dd22b..0000000
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c
+++ /dev/null
@@ -1,804 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010  Realtek Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-
-#include <linux/firmware.h>
-#include "../wifi.h"
-#include "../pci.h"
-#include "../base.h"
-#include "reg.h"
-#include "def.h"
-#include "fw.h"
-#include "table.h"
-
-static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
-		u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
-		if (enable)
-			value32 |= MCUFWDL_EN;
-		else
-			value32 &= ~MCUFWDL_EN;
-		rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
-	} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
-		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 _rtl92c_fw_block_write(struct ieee80211_hw *hw,
-				   const u8 *buffer, u32 size)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 blockSize = sizeof(u32);
-	u8 *bufferPtr = (u8 *) buffer;
-	u32 *pu4BytePtr = (u32 *) buffer;
-	u32 i, offset, blockCount, remainSize;
-
-	blockCount = size / blockSize;
-	remainSize = size % blockSize;
-
-	for (i = 0; i < blockCount; i++) {
-		offset = i * blockSize;
-		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
-				*(pu4BytePtr + i));
-	}
-
-	if (remainSize) {
-		offset = blockCount * blockSize;
-		bufferPtr += offset;
-		for (i = 0; i < remainSize; i++) {
-			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
-						 offset + i), *(bufferPtr + i));
-		}
-	}
-}
-
-static void _rtl92c_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);
-	_rtl92c_fw_block_write(hw, buffer, size);
-}
-
-static void _rtl92c_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 _rtl92c_write_fw(struct ieee80211_hw *hw,
-			     enum version_8192c version, u8 *buffer, u32 size)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	bool is_version_b;
-	u8 *bufferPtr = (u8 *) buffer;
-
-	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
-
-	is_version_b = IS_CHIP_VER_B(version);
-	if (is_version_b) {
-		u32 pageNums, remainSize;
-		u32 page, offset;
-
-		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
-			_rtl92c_fill_dummy(bufferPtr, &size);
-
-		pageNums = size / FW_8192C_PAGE_SIZE;
-		remainSize = size % FW_8192C_PAGE_SIZE;
-
-		if (pageNums > 4) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("Page numbers should not greater then 4\n"));
-		}
-
-		for (page = 0; page < pageNums; page++) {
-			offset = page * FW_8192C_PAGE_SIZE;
-			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
-					      FW_8192C_PAGE_SIZE);
-		}
-
-		if (remainSize) {
-			offset = pageNums * FW_8192C_PAGE_SIZE;
-			page = pageNums;
-			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
-					      remainSize);
-		}
-	} else {
-		_rtl92c_fw_block_write(hw, buffer, size);
-	}
-}
-
-static int _rtl92c_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);
-
-	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;
-		}
-
-		mdelay(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 rtl92c_download_fw(struct ieee80211_hw *hw)
-{
-	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_8192c version = rtlhal->version;
-
-	const struct firmware *firmware = NULL;
-
-	err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
-			       rtlpriv->io.dev);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Failed to request firmware!\n"));
-		return 1;
-	}
-
-	if (firmware->size > 0x4000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-
-	memcpy(rtlhal->pfirmware, firmware->data, firmware->size);
-	fwsize = firmware->size;
-	release_firmware(firmware);
-
-	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
-	pfwdata = (u8 *) rtlhal->pfirmware;
-
-	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,
-			  (uint)sizeof(struct rtl92c_firmware_header)));
-
-		pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
-		fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
-	}
-
-	_rtl92c_enable_fw_download(hw, true);
-	_rtl92c_write_fw(hw, version, pfwdata, fwsize);
-	_rtl92c_enable_fw_download(hw, false);
-
-	err = _rtl92c_fw_free_to_go(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is not ready to run!\n"));
-	} else {
-		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-			 ("Firmware is ready to run!\n"));
-	}
-
-	return 0;
-}
-
-static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 val_hmetfr, val_mcutst_1;
-	bool result = false;
-
-	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
-	val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
-
-	if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
-		result = true;
-	return result;
-}
-
-static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
-			      u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	u8 boxnum;
-	u16 box_reg, box_extreg;
-	u8 u1b_tmp;
-	bool isfw_read = false;
-	u8 buf_index;
-	bool bwrite_sucess = false;
-	u8 wait_h2c_limmit = 100;
-	u8 wait_writeh2c_limmit = 100;
-	u8 boxcontent[4], boxextcontent[2];
-	u32 h2c_waitcounter = 0;
-	unsigned long flag;
-	u8 idx;
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
-
-	while (true) {
-		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
-		if (rtlhal->b_h2c_setinprogress) {
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 ("H2C set in progress! Wait to set.."
-				  "element_id(%d).\n", element_id));
-
-			while (rtlhal->b_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->b_h2c_setinprogress = true;
-			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
-			break;
-		}
-	}
-
-	while (!bwrite_sucess) {
-		wait_writeh2c_limmit--;
-		if (wait_writeh2c_limmit == 0) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("Write H2C fail because no trigger "
-				  "for FW INT!\n"));
-			break;
-		}
-
-		boxnum = rtlhal->last_hmeboxnum;
-		switch (boxnum) {
-		case 0:
-			box_reg = REG_HMEBOX_0;
-			box_extreg = REG_HMEBOX_EXT_0;
-			break;
-		case 1:
-			box_reg = REG_HMEBOX_1;
-			box_extreg = REG_HMEBOX_EXT_1;
-			break;
-		case 2:
-			box_reg = REG_HMEBOX_2;
-			box_extreg = REG_HMEBOX_EXT_2;
-			break;
-		case 3:
-			box_reg = REG_HMEBOX_3;
-			box_extreg = REG_HMEBOX_EXT_3;
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-
-		isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
-		while (!isfw_read) {
-
-			wait_h2c_limmit--;
-			if (wait_h2c_limmit == 0) {
-				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-					 ("Wating too long for FW read "
-					  "clear HMEBox(%d)!\n", boxnum));
-				break;
-			}
-
-			udelay(10);
-
-			isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
-			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 ("Wating for FW read clear HMEBox(%d)!!! "
-				  "0x1BF = %2x\n", boxnum, u1b_tmp));
-		}
-
-		if (!isfw_read) {
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 ("Write H2C register BOX[%d] fail!!!!! "
-				  "Fw do not read.\n", boxnum));
-			break;
-		}
-
-		memset(boxcontent, 0, sizeof(boxcontent));
-		memset(boxextcontent, 0, sizeof(boxextcontent));
-		boxcontent[0] = element_id;
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-			 ("Write element_id box_reg(%4x) = %2x\n",
-			  box_reg, element_id));
-
-		switch (cmd_len) {
-		case 1:
-			boxcontent[0] &= ~(BIT(7));
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index, 1);
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 2:
-			boxcontent[0] &= ~(BIT(7));
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index, 2);
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 3:
-			boxcontent[0] &= ~(BIT(7));
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index, 3);
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 4:
-			boxcontent[0] |= (BIT(7));
-			memcpy((u8 *) (boxextcontent),
-			       p_cmdbuffer + buf_index, 2);
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index + 2, 2);
-
-			for (idx = 0; idx < 2; idx++) {
-				rtl_write_byte(rtlpriv, box_extreg + idx,
-					       boxextcontent[idx]);
-			}
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 5:
-			boxcontent[0] |= (BIT(7));
-			memcpy((u8 *) (boxextcontent),
-			       p_cmdbuffer + buf_index, 2);
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index + 2, 3);
-
-			for (idx = 0; idx < 2; idx++) {
-				rtl_write_byte(rtlpriv, box_extreg + idx,
-					       boxextcontent[idx]);
-			}
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-
-		bwrite_sucess = true;
-
-		rtlhal->last_hmeboxnum = boxnum + 1;
-		if (rtlhal->last_hmeboxnum == 4)
-			rtlhal->last_hmeboxnum = 0;
-
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-			 ("pHalData->last_hmeboxnum  = %d\n",
-			  rtlhal->last_hmeboxnum));
-	}
-
-	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
-	rtlhal->b_h2c_setinprogress = false;
-	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
-}
-
-void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
-			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	u32 tmp_cmdbuf[2];
-
-	if (rtlhal->bfw_ready == false) {
-		RT_ASSERT(false, ("return H2C cmd because of Fw "
-				  "download fail!!!\n"));
-		return;
-	}
-
-	memset(tmp_cmdbuf, 0, 8);
-	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
-	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
-
-	return;
-}
-
-void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
-{
-	u8 u1b_tmp;
-	u8 delay = 100;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
-	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
-
-	while (u1b_tmp & BIT(2)) {
-		delay--;
-		if (delay == 0) {
-			RT_ASSERT(false, ("8051 reset fail.\n"));
-			break;
-		}
-		udelay(50);
-		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
-	}
-}
-
-void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 u1_h2c_set_pwrmode[3] = {0};
-	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
-
-	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
-	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
-	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
-					      ppsc->reg_max_lps_awakeintvl);
-
-	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
-		      "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
-		      u1_h2c_set_pwrmode, 3);
-	rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
-
-}
-
-static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
-				    struct sk_buff *skb)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	struct rtl8192_tx_ring *ring;
-	struct rtl_tx_desc *pdesc;
-	u8 own;
-	unsigned long flags;
-	struct sk_buff *pskb = NULL;
-
-	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];
-	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
-
-	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
-
-	__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 rtl92c_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;
-	bool rtstatus;
-	u8 u1RsvdPageLoc[3] = {0};
-	bool b_dlok = false;
-
-	u8 *beacon;
-	u8 *p_pspoll;
-	u8 *nullfunc;
-	u8 *p_probersp;
-	/*---------------------------------------------------------
-				(1) beacon
-	---------------------------------------------------------*/
-	beacon = &reserved_page_packet[BEACON_PG * 128];
-	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
-	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
-
-	/*-------------------------------------------------------
-				(2) ps-poll
-	--------------------------------------------------------*/
-	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
-	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
-	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
-	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
-
-	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
-
-	/*--------------------------------------------------------
-				(3) null data
-	---------------------------------------------------------*/
-	nullfunc = &reserved_page_packet[NULL_PG * 128];
-	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
-	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
-	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
-
-	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
-
-	/*---------------------------------------------------------
-				(4) probe response
-	----------------------------------------------------------*/
-	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
-	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
-	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
-	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
-
-	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
-
-	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
-
-	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
-		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
-		      &reserved_page_packet[0], totalpacketlen);
-	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
-		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
-		      u1RsvdPageLoc, 3);
-
-
-	skb = dev_alloc_skb(totalpacketlen);
-	memcpy((u8 *) skb_put(skb, totalpacketlen),
-	       &reserved_page_packet, totalpacketlen);
-
-	rtstatus = _rtl92c_cmd_send_packet(hw, skb);
-
-	if (rtstatus)
-		b_dlok = true;
-
-	if (b_dlok) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 ("Set RSVD page location to Fw.\n"));
-		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
-				"H2C_RSVDPAGE:\n",
-				u1RsvdPageLoc, 3);
-		rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
-				    sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
-	} else
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
-}
-
-void rtl92c_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);
-
-	rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h
deleted file mode 100644
index 3db33bd..0000000
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010  Realtek Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-
-#ifndef __RTL92C__FW__H__
-#define __RTL92C__FW__H__
-
-#define FW_8192C_SIZE				0x3000
-#define FW_8192C_START_ADDRESS			0x1000
-#define FW_8192C_END_ADDRESS			0x3FFF
-#define FW_8192C_PAGE_SIZE			4096
-#define FW_8192C_POLLING_DELAY			5
-#define FW_8192C_POLLING_TIMEOUT_COUNT		100
-
-#define IS_FW_HEADER_EXIST(_pfwhdr)	\
-	((_pfwhdr->signature&0xFFF0) == 0x92C0 ||\
-	(_pfwhdr->signature&0xFFF0) == 0x88C0)
-
-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_AP_OFFLOAD = 0,
-	H2C_SETPWRMODE = 1,
-	H2C_JOINBSSRPT = 2,
-	H2C_RSVDPAGE = 3,
-	H2C_RSSI_REPORT = 5,
-	H2C_RA_MASK = 6,
-	MAX_H2CCMD
-};
-
-#define pagenum_128(_len)	(u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0))
-
-#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)			\
-	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
-#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
-#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
-#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
-#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
-#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
-#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
-
-int rtl92c_download_fw(struct ieee80211_hw *hw);
-void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
-			 u32 cmd_len, u8 *p_cmdbuffer);
-void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
-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);
-
-#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 1c41a0c..05477f4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -37,7 +37,6 @@
 #include "def.h"
 #include "phy.h"
 #include "dm.h"
-#include "fw.h"
 #include "led.h"
 #include "hw.h"
 
@@ -124,7 +123,7 @@ void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 			break;
 		}
 	case HW_VAR_FW_PSMODE_STATUS:
-		*((bool *) (val)) = ppsc->b_fw_current_inpsmode;
+		*((bool *) (val)) = ppsc->fw_current_inpsmode;
 		break;
 	case HW_VAR_CORRECT_TSF:{
 		u64 tsf;
@@ -173,15 +172,15 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 			break;
 		}
 	case HW_VAR_BASIC_RATE:{
-			u16 b_rate_cfg = ((u16 *) val)[0];
+			u16 rate_cfg = ((u16 *) val)[0];
 			u8 rate_index = 0;
-			b_rate_cfg = b_rate_cfg & 0x15f;
-			b_rate_cfg |= 0x01;
-			rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff);
+			rate_cfg &= 0x15f;
+			rate_cfg |= 0x01;
+			rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
 			rtl_write_byte(rtlpriv, REG_RRSR + 1,
-				       (b_rate_cfg >> 8)&0xff);
-			while (b_rate_cfg > 0x1) {
-				b_rate_cfg = (b_rate_cfg >> 1);
+				       (rate_cfg >> 8)&0xff);
+			while (rate_cfg > 0x1) {
+				rate_cfg = (rate_cfg >> 1);
 				rate_index++;
 			}
 			rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
@@ -318,15 +317,17 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 		}
 	case HW_VAR_AC_PARAM:{
 			u8 e_aci = *((u8 *) val);
-			u32 u4b_ac_param = 0;
+			u32 u4b_ac_param;
+			u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min);
+			u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max);
+			u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op);
 
-			u4b_ac_param |= (u32) mac->ac[e_aci].aifs;
-			u4b_ac_param |= ((u32) mac->ac[e_aci].cw_min
+			u4b_ac_param = (u32) mac->ac[e_aci].aifs;
+			u4b_ac_param |= ((u32)cw_min
 					 & 0xF) << AC_PARAM_ECW_MIN_OFFSET;
-			u4b_ac_param |= ((u32) mac->ac[e_aci].cw_max &
+			u4b_ac_param |= ((u32)cw_max &
 					 0xF) << AC_PARAM_ECW_MAX_OFFSET;
-			u4b_ac_param |= (u32) mac->ac[e_aci].tx_op
-			    << AC_PARAM_TXOP_LIMIT_OFFSET;
+			u4b_ac_param |= (u32)tx_op << AC_PARAM_TXOP_OFFSET;
 
 			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
 				 ("queue:%x, ac_param:%x\n", e_aci,
@@ -469,12 +470,12 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 			break;
 		}
 	case HW_VAR_FW_PSMODE_STATUS:
-		ppsc->b_fw_current_inpsmode = *((bool *) val);
+		ppsc->fw_current_inpsmode = *((bool *) val);
 		break;
 	case HW_VAR_H2C_FW_JOINBSSRPT:{
 			u8 mstatus = (*(u8 *) val);
 			u8 tmp_regcr, tmp_reg422;
-			bool b_recover = false;
+			bool recover = false;
 
 			if (mstatus == RT_MEDIA_CONNECT) {
 				rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID,
@@ -491,7 +492,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 				    rtl_read_byte(rtlpriv,
 						  REG_FWHW_TXQ_CTRL + 2);
 				if (tmp_reg422 & BIT(6))
-					b_recover = true;
+					recover = true;
 				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
 					       tmp_reg422 & (~BIT(6)));
 
@@ -500,7 +501,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 				_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
 				_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
 
-				if (b_recover) {
+				if (recover) {
 					rtl_write_byte(rtlpriv,
 						       REG_FWHW_TXQ_CTRL + 2,
 						       tmp_reg422);
@@ -868,7 +869,7 @@ static void _rtl92ce_enable_aspm_back_door(struct ieee80211_hw *hw)
 	rtl_write_word(rtlpriv, 0x350, 0x870c);
 	rtl_write_byte(rtlpriv, 0x352, 0x1);
 
-	if (ppsc->b_support_backdoor)
+	if (ppsc->support_backdoor)
 		rtl_write_byte(rtlpriv, 0x349, 0x1b);
 	else
 		rtl_write_byte(rtlpriv, 0x349, 0x03);
@@ -940,15 +941,15 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
 			 ("Failed to download FW. Init HW "
 			  "without FW now..\n"));
 		err = 1;
-		rtlhal->bfw_ready = false;
+		rtlhal->fw_ready = false;
 		return err;
 	} else {
-		rtlhal->bfw_ready = true;
+		rtlhal->fw_ready = true;
 	}
 
 	rtlhal->last_hmeboxnum = 0;
-	rtl92c_phy_mac_config(hw);
-	rtl92c_phy_bb_config(hw);
+	rtl92ce_phy_mac_config(hw);
+	rtl92ce_phy_bb_config(hw);
 	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
 	rtl92c_phy_rf_config(hw);
 	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
@@ -1170,21 +1171,20 @@ void rtl92ce_set_qos(struct ieee80211_hw *hw, int aci)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-
 	u32 u4b_ac_param;
+	u16 cw_min = le16_to_cpu(mac->ac[aci].cw_min);
+	u16 cw_max = le16_to_cpu(mac->ac[aci].cw_max);
+	u16 tx_op = le16_to_cpu(mac->ac[aci].tx_op);
 
 	rtl92c_dm_init_edca_turbo(hw);
-
 	u4b_ac_param = (u32) mac->ac[aci].aifs;
-	u4b_ac_param |=
-	    ((u32) mac->ac[aci].cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET;
-	u4b_ac_param |=
-	    ((u32) mac->ac[aci].cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET;
-	u4b_ac_param |= (u32) mac->ac[aci].tx_op << AC_PARAM_TXOP_LIMIT_OFFSET;
+	u4b_ac_param |= (u32) ((cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET);
+	u4b_ac_param |= (u32) ((cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET);
+	u4b_ac_param |= (u32) (tx_op << AC_PARAM_TXOP_OFFSET);
 	RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG,
 		 ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n",
-		  aci, u4b_ac_param, mac->ac[aci].aifs, mac->ac[aci].cw_min,
-		  mac->ac[aci].cw_max, mac->ac[aci].tx_op));
+		  aci, u4b_ac_param, mac->ac[aci].aifs, cw_min,
+		  cw_max, tx_op));
 	switch (aci) {
 	case AC1_BK:
 		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
@@ -1237,7 +1237,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
 	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
-	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->bfw_ready)
+	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
 		rtl92c_firmware_selfreset(hw);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
 	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
@@ -1335,19 +1335,6 @@ void rtl92ce_update_interrupt_mask(struct ieee80211_hw *hw,
 	rtl92ce_enable_interrupt(hw);
 }
 
-static u8 _rtl92c_get_chnl_group(u8 chnl)
-{
-	u8 group;
-
-	if (chnl < 3)
-		group = 0;
-	else if (chnl < 9)
-		group = 1;
-	else
-		group = 2;
-	return group;
-}
-
 static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 						 bool autoload_fail,
 						 u8 *hwinfo)
@@ -1568,7 +1555,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 	rtlefuse->eeprom_thermalmeter = (tempval & 0x1f);
 
 	if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
-		rtlefuse->b_apk_thermalmeterignore = true;
+		rtlefuse->apk_thermalmeterignore = true;
 
 	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
 	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
@@ -1625,7 +1612,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
 
 	rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
 	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
-	rtlefuse->b_txpwr_fromeprom = true;
+	rtlefuse->txpwr_fromeprom = true;
 	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
 
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
@@ -1668,7 +1655,7 @@ static void _rtl92ce_hal_customized_behavior(struct ieee80211_hw *hw)
 
 	switch (rtlhal->oem_id) {
 	case RT_CID_819x_HP:
-		pcipriv->ledctl.bled_opendrain = true;
+		pcipriv->ledctl.led_opendrain = true;
 		break;
 	case RT_CID_819x_Lenovo:
 	case RT_CID_DEFAULT:
@@ -1693,10 +1680,10 @@ void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw)
 
 	rtlhal->version = _rtl92ce_read_chip_version(hw);
 	if (get_rf_type(rtlphy) == RF_1T1R)
-		rtlpriv->dm.brfpath_rxenable[0] = true;
+		rtlpriv->dm.rfpath_rxenable[0] = true;
 	else
-		rtlpriv->dm.brfpath_rxenable[0] =
-		    rtlpriv->dm.brfpath_rxenable[1] = true;
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    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);
@@ -1725,18 +1712,18 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw)
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
 	u32 ratr_value = (u32) mac->basic_rates;
-	u8 *p_mcsrate = mac->mcs;
+	u8 *mcsrate = mac->mcs;
 	u8 ratr_index = 0;
-	u8 b_nmode = mac->ht_enable;
+	u8 nmode = mac->ht_enable;
 	u8 mimo_ps = 1;
 	u16 shortgi_rate;
 	u32 tmp_ratr_value;
-	u8 b_curtxbw_40mhz = mac->bw_40;
-	u8 b_curshortgi_40mhz = mac->sgi_40;
-	u8 b_curshortgi_20mhz = mac->sgi_20;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
 	enum wireless_mode wirelessmode = mac->mode;
 
-	ratr_value |= EF2BYTE((*(u16 *) (p_mcsrate))) << 12;
+	ratr_value |= ((*(u16 *) (mcsrate))) << 12;
 
 	switch (wirelessmode) {
 	case WIRELESS_MODE_B:
@@ -1750,7 +1737,7 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw)
 		break;
 	case WIRELESS_MODE_N_24G:
 	case WIRELESS_MODE_N_5G:
-		b_nmode = 1;
+		nmode = 1;
 		if (mimo_ps == 0) {
 			ratr_value &= 0x0007F005;
 		} else {
@@ -1776,9 +1763,8 @@ void rtl92ce_update_hal_rate_table(struct ieee80211_hw *hw)
 
 	ratr_value &= 0x0FFFFFFF;
 
-	if (b_nmode && ((b_curtxbw_40mhz &&
-			 b_curshortgi_40mhz) || (!b_curtxbw_40mhz &&
-						 b_curshortgi_20mhz))) {
+	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz &&
+		       curshortgi_20mhz))) {
 
 		ratr_value |= 0x10000000;
 		tmp_ratr_value = (ratr_value >> 12);
@@ -1806,11 +1792,11 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 	u32 ratr_bitmap = (u32) mac->basic_rates;
 	u8 *p_mcsrate = mac->mcs;
 	u8 ratr_index;
-	u8 b_curtxbw_40mhz = mac->bw_40;
-	u8 b_curshortgi_40mhz = mac->sgi_40;
-	u8 b_curshortgi_20mhz = mac->sgi_20;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
 	enum wireless_mode wirelessmode = mac->mode;
-	bool b_shortgi = false;
+	bool shortgi = false;
 	u8 rate_mask[5];
 	u8 macid = 0;
 	u8 mimops = 1;
@@ -1852,7 +1838,7 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 		} else {
 			if (rtlphy->rf_type == RF_1T2R ||
 			    rtlphy->rf_type == RF_1T1R) {
-				if (b_curtxbw_40mhz) {
+				if (curtxbw_40mhz) {
 					if (rssi_level == 1)
 						ratr_bitmap &= 0x000f0000;
 					else if (rssi_level == 2)
@@ -1868,7 +1854,7 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 						ratr_bitmap &= 0x000ff005;
 				}
 			} else {
-				if (b_curtxbw_40mhz) {
+				if (curtxbw_40mhz) {
 					if (rssi_level == 1)
 						ratr_bitmap &= 0x0f0f0000;
 					else if (rssi_level == 2)
@@ -1886,13 +1872,13 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 			}
 		}
 
-		if ((b_curtxbw_40mhz && b_curshortgi_40mhz) ||
-		    (!b_curtxbw_40mhz && b_curshortgi_20mhz)) {
+		if ((curtxbw_40mhz && curshortgi_40mhz) ||
+		    (!curtxbw_40mhz && curshortgi_20mhz)) {
 
 			if (macid == 0)
-				b_shortgi = true;
+				shortgi = true;
 			else if (macid == 1)
-				b_shortgi = false;
+				shortgi = false;
 		}
 		break;
 	default:
@@ -1906,9 +1892,9 @@ void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
 	}
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 ("ratr_bitmap :%x\n", ratr_bitmap));
-	*(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) |
-				       (ratr_index << 28));
-	rate_mask[4] = macid | (b_shortgi ? 0x20 : 0x00) | 0x80;
+	*(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,
@@ -1940,13 +1926,13 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
 	u8 u1tmp;
-	bool b_actuallyset = false;
+	bool actuallyset = false;
 	unsigned long flag;
 
 	if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter))
 		return false;
 
-	if (ppsc->b_swrf_processing)
+	if (ppsc->swrf_processing)
 		return false;
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
@@ -1972,24 +1958,24 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
 	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
 	e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
 
-	if ((ppsc->b_hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+	if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
 		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 			 ("GPIOChangeRF  - HW Radio ON, RF ON\n"));
 
 		e_rfpowerstate_toset = ERFON;
-		ppsc->b_hwradiooff = false;
-		b_actuallyset = true;
-	} else if ((ppsc->b_hwradiooff == false)
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((ppsc->hwradiooff == false)
 		   && (e_rfpowerstate_toset == ERFOFF)) {
 		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 			 ("GPIOChangeRF  - HW Radio OFF, RF OFF\n"));
 
 		e_rfpowerstate_toset = ERFOFF;
-		ppsc->b_hwradiooff = true;
-		b_actuallyset = true;
+		ppsc->hwradiooff = true;
+		actuallyset = true;
 	}
 
-	if (b_actuallyset) {
+	if (actuallyset) {
 		if (e_rfpowerstate_toset == ERFON) {
 			if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
 			    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) {
@@ -2028,7 +2014,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
 	}
 
 	*valid = 1;
-	return !ppsc->b_hwradiooff;
+	return !ppsc->hwradiooff;
 
 }
 
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
index 305c819..a3dfdb6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
@@ -30,6 +30,8 @@
 #ifndef __RTL92CE_HW_H__
 #define __RTL92CE_HW_H__
 
+#define H2C_RA_MASK	6
+
 void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw);
 void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
@@ -53,5 +55,14 @@ void rtl92ce_enable_hw_security_config(struct ieee80211_hw *hw);
 void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index,
 		     u8 *p_macaddr, bool is_group, u8 enc_algo,
 		     bool is_wepkey, bool clear_all);
+bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+int rtl92c_download_fw(struct ieee80211_hw *hw);
+void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
+bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
index 78a0569..7b1da8d 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
@@ -57,7 +57,7 @@ void rtl92ce_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
 			 ("switch case not process\n"));
 		break;
 	}
-	pled->b_ledon = true;
+	pled->ledon = true;
 }
 
 void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
@@ -76,7 +76,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 		break;
 	case LED_PIN_LED0:
 		ledcfg &= 0xf0;
-		if (pcipriv->ledctl.bled_opendrain == true)
+		if (pcipriv->ledctl.led_opendrain == true)
 			rtl_write_byte(rtlpriv, REG_LEDCFG2,
 				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
 		else
@@ -92,7 +92,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
 			 ("switch case not process\n"));
 		break;
 	}
-	pled->b_ledon = false;
+	pled->ledon = false;
 }
 
 void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
index 4504411..d0541e8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
@@ -32,89 +32,13 @@
 #include "../ps.h"
 #include "reg.h"
 #include "def.h"
+#include "hw.h"
 #include "phy.h"
 #include "rf.h"
 #include "dm.h"
 #include "table.h"
 
-static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
-					 enum radio_path rfpath, u32 offset);
-static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
-					   enum radio_path rfpath, u32 offset,
-					   u32 data);
-static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
-				      enum radio_path rfpath, u32 offset);
-static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
-					enum radio_path rfpath, u32 offset,
-					u32 data);
-static u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
-static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
-static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
-static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
-						  u8 configtype);
-static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
-						    u8 configtype);
-static void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
-static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
-					     u32 cmdtableidx, u32 cmdtablesz,
-					     enum swchnlcmd_id cmdid, u32 para1,
-					     u32 para2, u32 msdelay);
-static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
-					     u8 channel, u8 *stage, u8 *step,
-					     u32 *delay);
-static u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
-				       enum wireless_mode wirelessmode,
-				       long power_indbm);
-static bool _rtl92c_phy_config_rf_external_pa(struct ieee80211_hw *hw,
-					      enum radio_path rfpath);
-static long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
-					 enum wireless_mode wirelessmode,
-					 u8 txpwridx);
-u32 rtl92c_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 = _rtl92c_phy_calculate_bit_shift(bitmask);
-	returnvalue = (originalvalue & bitmask) >> bitshift;
-
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
-					       "Addr[0x%x]=0x%x\n", bitmask,
-					       regaddr, originalvalue));
-
-	return returnvalue;
-
-}
-
-void rtl92c_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 = _rtl92c_phy_calculate_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 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
+u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw,
 			    enum radio_path rfpath, u32 regaddr, u32 bitmask)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -149,7 +73,7 @@ u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
 	return readback_value;
 }
 
-void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
+void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
 			   enum radio_path rfpath,
 			   u32 regaddr, u32 bitmask, u32 data)
 {
@@ -197,137 +121,25 @@ void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
 					       bitmask, data, rfpath));
 }
 
-static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
-					 enum radio_path rfpath, u32 offset)
-{
-	RT_ASSERT(false, ("deprecated!\n"));
-	return 0;
-}
-
-static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
-					   enum radio_path rfpath, u32 offset,
-					   u32 data)
-{
-	RT_ASSERT(false, ("deprecated!\n"));
-}
-
-static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
-				      enum radio_path rfpath, u32 offset)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
-	u32 newoffset;
-	u32 tmplong, tmplong2;
-	u8 rfpi_enable = 0;
-	u32 retvalue;
-
-	offset &= 0x3f;
-	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 == RF90_PATH_A)
-		tmplong2 = tmplong;
-	else
-		tmplong2 = rtl_get_bbreg(hw, pphyreg->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, pphyreg->rfhssi_para2, MASKDWORD, tmplong2);
-	mdelay(1);
-	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
-		      tmplong | BLSSIREADEDGE);
-	mdelay(1);
-	if (rfpath == RF90_PATH_A)
-		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
-						 BIT(8));
-	else if (rfpath == RF90_PATH_B)
-		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
-						 BIT(8));
-	if (rfpi_enable)
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
-					 BLSSIREADBACKDATA);
-	else
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
-					 BLSSIREADBACKDATA);
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n",
-					       rfpath, pphyreg->rflssi_readback,
-					       retvalue));
-	return retvalue;
-}
-
-static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
-					enum radio_path rfpath, u32 offset,
-					u32 data)
-{
-	u32 data_and_addr;
-	u32 newoffset;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
-
-	if (RT_CANNOT_IO(hw)) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("stop\n"));
-		return;
-	}
-	offset &= 0x3f;
-	newoffset = offset;
-	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
-	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
-					       rfpath, pphyreg->rf3wire_offset,
-					       data_and_addr));
-}
-
-static u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
-}
-
-static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw)
-{
-	rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
-	rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
-	rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
-	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
-	rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
-	rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
-}
-
-bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
+bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	bool is92c = IS_92C_SERIAL(rtlhal->version);
-	bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw);
+	bool rtstatus = _rtl92ce_phy_config_mac_with_headerfile(hw);
 
 	if (is92c)
 		rtl_write_byte(rtlpriv, 0x14, 0x71);
 	return rtstatus;
 }
 
-bool rtl92c_phy_bb_config(struct ieee80211_hw *hw)
+bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw)
 {
 	bool rtstatus = true;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u16 regval;
 	u32 regvaldw;
-	u8 b_reg_hwparafile = 1;
+	u8 reg_hwparafile = 1;
 
 	_rtl92c_phy_init_bb_rf_register_definition(hw);
 	regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
@@ -342,56 +154,12 @@ bool rtl92c_phy_bb_config(struct ieee80211_hw *hw)
 	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
 	regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
 	rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
-	if (b_reg_hwparafile == 1)
+	if (reg_hwparafile == 1)
 		rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
 	return rtstatus;
 }
 
-bool rtl92c_phy_rf_config(struct ieee80211_hw *hw)
-{
-	return rtl92c_phy_rf6052_config(hw);
-}
-
-static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	bool rtstatus;
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
-	rtstatus = _rtl92c_phy_config_bb_with_headerfile(hw,
-						 BASEBAND_CONFIG_PHY_REG);
-	if (rtstatus != true) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
-		return false;
-	}
-	if (rtlphy->rf_type == RF_1T2R) {
-		_rtl92c_phy_bb_config_1t(hw);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
-	}
-	if (rtlefuse->autoload_failflag == false) {
-		rtlphy->pwrgroup_cnt = 0;
-		rtstatus = _rtl92c_phy_config_bb_with_pgheaderfile(hw,
-						   BASEBAND_CONFIG_PHY_REG);
-	}
-	if (rtstatus != true) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
-		return false;
-	}
-	rtstatus = _rtl92c_phy_config_bb_with_headerfile(hw,
-						 BASEBAND_CONFIG_AGC_TAB);
-	if (rtstatus != true) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
-		return false;
-	}
-	rtlphy->bcck_high_power = (bool) (rtl_get_bbreg(hw,
-						RFPGA0_XA_HSSIPARAMETER2,
-						0x200));
-	return true;
-}
-
-static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
+bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 i;
@@ -408,11 +176,7 @@ static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
 	return true;
 }
 
-void rtl92c_phy_config_bb_external_pa(struct ieee80211_hw *hw)
-{
-}
-
-static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
 						  u8 configtype)
 {
 	int i;
@@ -456,7 +220,6 @@ static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
 				  phy_regarray_table[i],
 				  phy_regarray_table[i + 1]));
 		}
-		rtl92c_phy_config_bb_external_pa(hw);
 	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
 		for (i = 0; i < agctab_arraylen; i = i + 2) {
 			rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
@@ -472,175 +235,7 @@ static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
 	return true;
 }
 
-static void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
-						   u32 regaddr, u32 bitmask,
-						   u32 data)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	if (regaddr == RTXAGC_A_RATE18_06) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][0]));
-	}
-	if (regaddr == RTXAGC_A_RATE54_24) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][1]));
-	}
-	if (regaddr == RTXAGC_A_CCK1_MCS32) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][6]));
-	}
-	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][7]));
-	}
-	if (regaddr == RTXAGC_A_MCS03_MCS00) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][2]));
-	}
-	if (regaddr == RTXAGC_A_MCS07_MCS04) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][3]));
-	}
-	if (regaddr == RTXAGC_A_MCS11_MCS08) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][4]));
-	}
-	if (regaddr == RTXAGC_A_MCS15_MCS12) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][5]));
-	}
-	if (regaddr == RTXAGC_B_RATE18_06) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][8]));
-	}
-	if (regaddr == RTXAGC_B_RATE54_24) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][9]));
-	}
-
-	if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][14]));
-	}
-
-	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][15]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS03_MCS00) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][10]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS07_MCS04) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][11]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS11_MCS08) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][12]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS15_MCS12) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][13]));
-
-		rtlphy->pwrgroup_cnt++;
-	}
-}
-
-static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
 						    u8 configtype)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -679,13 +274,7 @@ static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
 	return true;
 }
 
-static bool _rtl92c_phy_config_rf_external_pa(struct ieee80211_hw *hw,
-					      enum radio_path rfpath)
-{
-	return true;
-}
-
-bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 					  enum radio_path rfpath)
 {
 
@@ -740,7 +329,6 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 				udelay(1);
 			}
 		}
-		_rtl92c_phy_config_rf_external_pa(hw, rfpath);
 		break;
 	case RF90_PATH_B:
 		for (i = 0; i < radiob_arraylen; i = i + 2) {
@@ -776,346 +364,7 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 	return true;
 }
 
-void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	rtlphy->default_initialgain[0] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
-	rtlphy->default_initialgain[1] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
-	rtlphy->default_initialgain[2] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
-	rtlphy->default_initialgain[3] =
-	    (u8) 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 = (u8) 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));
-}
-
-static void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
-	rtlphy->phyreg_def[RF90_PATH_B].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[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
-	rtlphy->phyreg_def[RF90_PATH_B].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[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
-	    RFPGA0_XA_LSSIPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
-	    RFPGA0_XB_LSSIPARAMETER;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
-	rtlphy->phyreg_def[RF90_PATH_B].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[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
-	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
-	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
-	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
-	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
-	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
-	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
-	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
-	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
-	    ROFDM0_XARXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
-	    ROFDM0_XBRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
-	    ROFDM0_XCRXIQIMBANLANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
-	    ROFDM0_XDRXIQIMBALANCE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
-	    ROFDM0_XATXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
-	    ROFDM0_XBTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
-	    ROFDM0_XCTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
-	    ROFDM0_XDTXIQIMBALANCE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
-	    RFPGA0_XA_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
-	    RFPGA0_XB_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
-	    RFPGA0_XC_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
-	    RFPGA0_XD_LSSIREADBACK;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
-	    TRANSCEIVEA_HSPI_READBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
-	    TRANSCEIVEB_HSPI_READBACK;
-
-}
-
-void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 txpwr_level;
-	long txpwr_dbm;
-
-	txpwr_level = rtlphy->cur_cck_txpwridx;
-	txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw,
-						 WIRELESS_MODE_B, txpwr_level);
-	txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
-	    rtlefuse->legacy_ht_txpowerdiff;
-	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
-					 WIRELESS_MODE_G,
-					 txpwr_level) > txpwr_dbm)
-		txpwr_dbm =
-		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
-						 txpwr_level);
-	txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
-	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
-					 WIRELESS_MODE_N_24G,
-					 txpwr_level) > txpwr_dbm)
-		txpwr_dbm =
-		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
-						 txpwr_level);
-	*powerlevel = txpwr_dbm;
-}
-
-static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
-				      u8 *cckpowerlevel, u8 *ofdmpowerlevel)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 index = (channel - 1);
-
-	cckpowerlevel[RF90_PATH_A] =
-	    rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
-	cckpowerlevel[RF90_PATH_B] =
-	    rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
-	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
-		ofdmpowerlevel[RF90_PATH_A] =
-		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
-		ofdmpowerlevel[RF90_PATH_B] =
-		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
-	} else if (get_rf_type(rtlphy) == RF_2T2R) {
-		ofdmpowerlevel[RF90_PATH_A] =
-		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
-		ofdmpowerlevel[RF90_PATH_B] =
-		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
-	}
-}
-
-static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw,
-					 u8 channel, u8 *cckpowerlevel,
-					 u8 *ofdmpowerlevel)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
-	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
-}
-
-void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
-{
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 cckpowerlevel[2], ofdmpowerlevel[2];
-
-	if (rtlefuse->b_txpwr_fromeprom == false)
-		return;
-	_rtl92c_get_txpower_index(hw, channel,
-				  &cckpowerlevel[0], &ofdmpowerlevel[0]);
-	_rtl92c_ccxpower_index_check(hw,
-				     channel, &cckpowerlevel[0],
-				     &ofdmpowerlevel[0]);
-	rtl92c_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
-	rtl92c_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
-}
-
-bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 idx;
-	u8 rf_path;
-
-	u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
-						      WIRELESS_MODE_B,
-						      power_indbm);
-	u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
-						       WIRELESS_MODE_N_24G,
-						       power_indbm);
-	if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
-		ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
-	else
-		ofdmtxpwridx = 0;
-	RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
-		 ("%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
-		  power_indbm, ccktxpwridx, ofdmtxpwridx));
-	for (idx = 0; idx < 14; idx++) {
-		for (rf_path = 0; rf_path < 2; rf_path++) {
-			rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
-			rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
-			    ofdmtxpwridx;
-			rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
-			    ofdmtxpwridx;
-		}
-	}
-	rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
-	return true;
-}
-
-void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval)
-{
-}
-
-static u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
-				       enum wireless_mode wirelessmode,
-				       long power_indbm)
-{
-	u8 txpwridx;
-	long offset;
-
-	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;
-	}
-
-	if ((power_indbm - offset) > 0)
-		txpwridx = (u8) ((power_indbm - offset) * 2);
-	else
-		txpwridx = 0;
-
-	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
-		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
-
-	return txpwridx;
-}
-
-static long _rtl92c_phy_txpwr_idx_to_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;
-}
-
-void rtl92c_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 rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
+void rtl92ce_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));
@@ -1183,656 +432,18 @@ void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
 	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
 }
 
-void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
-			    enum nl80211_channel_type ch_type)
+void _rtl92ce_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);
-	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)))
-		rtl92c_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;
-	}
-}
+	tmpreg = rtl_read_byte(rtlpriv, 0xd03);
 
-void rtl92c_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 (!_rtl92c_phy_sw_chnl_step_by_step
-		    (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
-		     &rtlphy->sw_chnl_step, &delay)) {
-			if (delay > 0)
-				mdelay(delay);
-			else
-				continue;
-		} else
-			rtlphy->sw_chnl_inprogress = false;
-		break;
-	} while (true);
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
-}
-
-u8 rtl92c_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))) {
-		rtl92c_phy_sw_chnl_callback(hw);
-		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-			 ("sw_chnl_inprogress false schdule workitem\n"));
-		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 bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
-					     u8 channel, u8 *stage, u8 *step,
-					     u32 *delay)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
-	u32 precommoncmdcnt;
-	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
-	u32 postcommoncmdcnt;
-	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
-	u32 rfdependcmdcnt;
-	struct swchnlcmd *currentcmd = NULL;
-	u8 rfpath;
-	u8 num_total_rfpath = rtlphy->num_total_rfpath;
-
-	precommoncmdcnt = 0;
-	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
-					 MAX_PRECMD_CNT,
-					 CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
-	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
-					 MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
-
-	postcommoncmdcnt = 0;
-
-	_rtl92c_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));
-
-	_rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
-					 MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
-					 RF_CHNLBW, channel, 10);
-
-	_rtl92c_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:
-			rtl92c_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 process\n"));
-			break;
-		}
-
-		break;
-	} while (true);
-
-	(*delay) = currentcmd->msdelay;
-	(*step)++;
-	return false;
-}
-
-static bool _rtl92c_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;
-}
-
-bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath)
-{
-	return true;
-}
-
-static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
-{
-	u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
-	u8 result = 0x00;
-
-	rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
-	rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
-	rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
-	rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
-		      config_pathb ? 0x28160202 : 0x28160502);
-
-	if (config_pathb) {
-		rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
-		rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
-		rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
-		rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
-	}
-
-	rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
-	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);
-	reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
-
-	if (!(reg_eac & BIT(28)) &&
-	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
-	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
-		result |= 0x01;
-	else
-		return result;
-
-	if (!(reg_eac & BIT(27)) &&
-	    (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
-	    (((reg_eac & 0x03FF0000) >> 16) != 0x36))
-		result |= 0x02;
-	return result;
-}
-
-static u8 _rtl92c_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 void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw,
-					       bool b_iqk_ok, long result[][8],
-					       u8 final_candidate, bool btxonly)
-{
-	u32 oldval_0, x, tx0_a, reg;
-	long y, tx0_c;
-
-	if (final_candidate == 0xFF)
-		return;
-	else if (b_iqk_ok) {
-		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-					  MASKDWORD) >> 22) & 0x3FF;
-		x = result[final_candidate][0];
-		if ((x & 0x00000200) != 0)
-			x = x | 0xFFFFFC00;
-		tx0_a = (x * oldval_0) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31),
-			      ((x * oldval_0 >> 7) & 0x1));
-		y = result[final_candidate][1];
-		if ((y & 0x00000200) != 0)
-			y = y | 0xFFFFFC00;
-		tx0_c = (y * oldval_0) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
-			      ((tx0_c & 0x3C0) >> 6));
-		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
-			      (tx0_c & 0x3F));
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29),
-			      ((y * oldval_0 >> 7) & 0x1));
-		if (btxonly)
-			return;
-		reg = result[final_candidate][2];
-		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
-		reg = result[final_candidate][3] & 0x3F;
-		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
-		reg = (result[final_candidate][3] >> 6) & 0xF;
-		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
-	}
-}
-
-static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw,
-					       bool b_iqk_ok, long result[][8],
-					       u8 final_candidate, bool btxonly)
-{
-	u32 oldval_1, x, tx1_a, reg;
-	long y, tx1_c;
-
-	if (final_candidate == 0xFF)
-		return;
-	else if (b_iqk_ok) {
-		oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
-					  MASKDWORD) >> 22) & 0x3FF;
-		x = result[final_candidate][4];
-		if ((x & 0x00000200) != 0)
-			x = x | 0xFFFFFC00;
-		tx1_a = (x * oldval_1) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a);
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27),
-			      ((x * oldval_1 >> 7) & 0x1));
-		y = result[final_candidate][5];
-		if ((y & 0x00000200) != 0)
-			y = y | 0xFFFFFC00;
-		tx1_c = (y * oldval_1) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000,
-			      ((tx1_c & 0x3C0) >> 6));
-		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000,
-			      (tx1_c & 0x3F));
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25),
-			      ((y * oldval_1 >> 7) & 0x1));
-		if (btxonly)
-			return;
-		reg = result[final_candidate][6];
-		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
-		reg = result[final_candidate][7] & 0x3F;
-		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
-		reg = (result[final_candidate][7] >> 6) & 0xF;
-		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
-	}
-}
-
-static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw,
-					    u32 *addareg, u32 *addabackup,
-					    u32 registernum)
-{
-	u32 i;
-
-	for (i = 0; i < registernum; i++)
-		addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
-}
-
-static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw,
-					   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 _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw,
-					      u32 *addareg, u32 *addabackup,
-					      u32 regiesternum)
-{
-	u32 i;
-
-	for (i = 0; i < regiesternum; i++)
-		rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]);
-}
-
-static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw,
-					     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 _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw,
-				     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 _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw,
-						u32 *macreg, u32 *macbackup)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 i;
-
-	rtl_write_byte(rtlpriv, macreg[0], 0x3F);
-
-	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
-		rtl_write_byte(rtlpriv, macreg[i],
-			       (u8) (macbackup[i] & (~BIT(3))));
-	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
-}
-
-static void _rtl92c_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 _rtl92c_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 _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw,
-					   long result[][8], u8 c1, u8 c2)
-{
-	u32 i, j, diff, simularity_bitmap, bound;
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	u8 final_candidate[2] = { 0xFF, 0xFF };
-	bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version);
-
-	if (is2t)
-		bound = 8;
-	else
-		bound = 4;
-
-	simularity_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) && !simularity_bitmap) {
-				if (result[c1][i] + result[c1][i + 1] == 0)
-					final_candidate[(i / 4)] = c2;
-				else if (result[c2][i] + result[c2][i + 1] == 0)
-					final_candidate[(i / 4)] = c1;
-				else
-					simularity_bitmap = simularity_bitmap |
-					    (1 << i);
-			} else
-				simularity_bitmap =
-				    simularity_bitmap | (1 << i);
-		}
-	}
-
-	if (simularity_bitmap == 0) {
-		for (i = 0; i < (bound / 4); i++) {
-			if (final_candidate[i] != 0xFF) {
-				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
-					result[3][j] =
-					    result[final_candidate[i]][j];
-				bresult = false;
-			}
-		}
-		return bresult;
-	} else if (!(simularity_bitmap & 0x0F)) {
-		for (i = 0; i < 4; i++)
-			result[3][i] = result[c1][i];
-		return false;
-	} else if (!(simularity_bitmap & 0xF0) && is2t) {
-		for (i = 4; i < 8; i++)
-			result[3][i] = result[c1][i];
-		return false;
-	} else {
-		return false;
-	}
-
-}
-
-static void _rtl92c_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;
-	u32 adda_reg[IQK_ADDA_REG_NUM] = {
-		0x85c, 0xe6c, 0xe70, 0xe74,
-		0xe78, 0xe7c, 0xe80, 0xe84,
-		0xe88, 0xe8c, 0xed0, 0xed4,
-		0xed8, 0xedc, 0xee0, 0xeec
-	};
-
-	u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
-		0x522, 0x550, 0x551, 0x040
-	};
-
-	const u32 retrycount = 2;
-
-	u32 bbvalue;
-
-	if (t == 0) {
-		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
-
-		_rtl92c_phy_save_adda_registers(hw, adda_reg,
-						rtlphy->adda_backup, 16);
-		_rtl92c_phy_save_mac_registers(hw, iqk_mac_reg,
-					       rtlphy->iqk_mac_backup);
-	}
-	_rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t);
-	if (t == 0) {
-		rtlphy->b_rfpi_enable = (u8) rtl_get_bbreg(hw,
-						   RFPGA0_XA_HSSIPARAMETER1,
-						   BIT(8));
-	}
-	if (!rtlphy->b_rfpi_enable)
-		_rtl92c_phy_pi_mode_switch(hw, true);
-	if (t == 0) {
-		rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
-		rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
-		rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
-	}
-	rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
-	rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
-	rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
-	if (is2t) {
-		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
-		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
-	}
-	_rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg,
-					    rtlphy->iqk_mac_backup);
-	rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
-	if (is2t)
-		rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
-	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
-	rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
-	rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
-	for (i = 0; i < retrycount; i++) {
-		patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t);
-		if (patha_ok == 0x03) {
-			result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
-					0x3FF0000) >> 16;
-			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
-					0x3FF0000) >> 16;
-			result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
-					0x3FF0000) >> 16;
-			result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
-					0x3FF0000) >> 16;
-			break;
-		} else if (i == (retrycount - 1) && patha_ok == 0x01)
-			result[t][0] = (rtl_get_bbreg(hw, 0xe94,
-						      MASKDWORD) & 0x3FF0000) >>
-						      16;
-		result[t][1] =
-		    (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
-
-	}
-
-	if (is2t) {
-		_rtl92c_phy_path_a_standby(hw);
-		_rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t);
-		for (i = 0; i < retrycount; i++) {
-			pathb_ok = _rtl92c_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, 0xc04, MASKDWORD, rtlphy->reg_c04);
-	rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
-	rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
-	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
-	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
-	if (is2t)
-		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
-	if (t != 0) {
-		if (!rtlphy->b_rfpi_enable)
-			_rtl92c_phy_pi_mode_switch(hw, false);
-		_rtl92c_phy_reload_adda_registers(hw, adda_reg,
-						  rtlphy->adda_backup, 16);
-		_rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg,
-						 rtlphy->iqk_mac_backup);
-	}
-}
-
-static void _rtl92c_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);
-
-	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)
+		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, RF90_PATH_A, 0x00, MASK12BITS);
@@ -1866,666 +477,6 @@ static void _rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
 	}
 }
 
-static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw,
-				     char delta, bool is2t)
-{
-	/* This routine is deliberately dummied out for later fixes */
-#if 0
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-
-	u32 reg_d[PATH_NUM];
-	u32 tmpreg, index, offset, path, i, pathbound = PATH_NUM, apkbound;
-
-	u32 bb_backup[APK_BB_REG_NUM];
-	u32 bb_reg[APK_BB_REG_NUM] = {
-		0x904, 0xc04, 0x800, 0xc08, 0x874
-	};
-	u32 bb_ap_mode[APK_BB_REG_NUM] = {
-		0x00000020, 0x00a05430, 0x02040000,
-		0x000800e4, 0x00204000
-	};
-	u32 bb_normal_ap_mode[APK_BB_REG_NUM] = {
-		0x00000020, 0x00a05430, 0x02040000,
-		0x000800e4, 0x22204000
-	};
-
-	u32 afe_backup[APK_AFE_REG_NUM];
-	u32 afe_reg[APK_AFE_REG_NUM] = {
-		0x85c, 0xe6c, 0xe70, 0xe74, 0xe78,
-		0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
-		0xed0, 0xed4, 0xed8, 0xedc, 0xee0,
-		0xeec
-	};
-
-	u32 mac_backup[IQK_MAC_REG_NUM];
-	u32 mac_reg[IQK_MAC_REG_NUM] = {
-		0x522, 0x550, 0x551, 0x040
-	};
-
-	u32 apk_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
-		{0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
-	};
-
-	u32 apk_normal_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c},
-		{0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
-	};
-
-	u32 apk_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
-		{0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
-	};
-
-	u32 apk_normal_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a},
-		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
-	};
-
-	u32 afe_on_off[PATH_NUM] = {
-		0x04db25a4, 0x0b1b25a4
-	};
-
-	u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c };
-
-	u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 };
-
-	u32 apk_value[PATH_NUM] = { 0x92fc0000, 0x12fc0000 };
-
-	u32 apk_normal_value[PATH_NUM] = { 0x92680000, 0x12680000 };
-
-	const char apk_delta_mapping[APK_BB_REG_NUM][13] = {
-		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
-	};
-
-	const u32 apk_normal_setting_value_1[13] = {
-		0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
-		0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
-		0x12680000, 0x00880000, 0x00880000
-	};
-
-	const u32 apk_normal_setting_value_2[16] = {
-		0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
-		0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
-		0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
-		0x00050006
-	};
-
-	const u32 apk_result[PATH_NUM][APK_BB_REG_NUM];
-
-	long bb_offset, delta_v, delta_offset;
-
-	if (!is2t)
-		pathbound = 1;
-
-	for (index = 0; index < PATH_NUM; index++) {
-		apk_offset[index] = apk_normal_offset[index];
-		apk_value[index] = apk_normal_value[index];
-		afe_on_off[index] = 0x6fdb25a4;
-	}
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		for (path = 0; path < pathbound; path++) {
-			apk_rf_init_value[path][index] =
-			    apk_normal_rf_init_value[path][index];
-			apk_rf_value_0[path][index] =
-			    apk_normal_rf_value_0[path][index];
-		}
-		bb_ap_mode[index] = bb_normal_ap_mode[index];
-
-		apkbound = 6;
-	}
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		if (index == 0)
-			continue;
-		bb_backup[index] = rtl_get_bbreg(hw, bb_reg[index], MASKDWORD);
-	}
-
-	_rtl92c_phy_save_mac_registers(hw, mac_reg, mac_backup);
-
-	_rtl92c_phy_save_adda_registers(hw, afe_reg, afe_backup, 16);
-
-	for (path = 0; path < pathbound; path++) {
-		if (path == RF90_PATH_A) {
-			offset = 0xb00;
-			for (index = 0; index < 11; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-
-			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
-
-			offset = 0xb68;
-			for (; index < 13; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
-
-			offset = 0xb00;
-			for (index = 0; index < 16; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_2
-					      [index]);
-
-				offset += 0x04;
-			}
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
-		} else if (path == RF90_PATH_B) {
-			offset = 0xb70;
-			for (index = 0; index < 10; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-			rtl_set_bbreg(hw, 0xb28, MASKDWORD, 0x12680000);
-			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
-
-			offset = 0xb68;
-			index = 11;
-			for (; index < 13; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
-
-			offset = 0xb60;
-			for (index = 0; index < 16; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_2
-					      [index]);
-
-				offset += 0x04;
-			}
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
-		}
-
-		reg_d[path] = rtl_get_rfreg(hw, (enum radio_path)path,
-					    0xd, MASKDWORD);
-
-		for (index = 0; index < APK_AFE_REG_NUM; index++)
-			rtl_set_bbreg(hw, afe_reg[index], MASKDWORD,
-				      afe_on_off[path]);
-
-		if (path == RF90_PATH_A) {
-			for (index = 0; index < APK_BB_REG_NUM; index++) {
-				if (index == 0)
-					continue;
-				rtl_set_bbreg(hw, bb_reg[index], MASKDWORD,
-					      bb_ap_mode[index]);
-			}
-		}
-
-		_rtl92c_phy_mac_setting_calibration(hw, mac_reg, mac_backup);
-
-		if (path == 0) {
-			rtl_set_rfreg(hw, RF90_PATH_B, 0x0, MASKDWORD, 0x10000);
-		} else {
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASKDWORD,
-				      0x10000);
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
-				      0x1000f);
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
-				      0x20103);
-		}
-
-		delta_offset = ((delta + 14) / 2);
-		if (delta_offset < 0)
-			delta_offset = 0;
-		else if (delta_offset > 12)
-			delta_offset = 12;
-
-		for (index = 0; index < APK_BB_REG_NUM; index++) {
-			if (index != 1)
-				continue;
-
-			tmpreg = apk_rf_init_value[path][index];
-
-			if (!rtlefuse->b_apk_thermalmeterignore) {
-				bb_offset = (tmpreg & 0xF0000) >> 16;
-
-				if (!(tmpreg & BIT(15)))
-					bb_offset = -bb_offset;
-
-				delta_v =
-				    apk_delta_mapping[index][delta_offset];
-
-				bb_offset += delta_v;
-
-				if (bb_offset < 0) {
-					tmpreg = tmpreg & (~BIT(15));
-					bb_offset = -bb_offset;
-				} else {
-					tmpreg = tmpreg | BIT(15);
-				}
-
-				tmpreg =
-				    (tmpreg & 0xFFF0FFFF) | (bb_offset << 16);
-			}
-
-			rtl_set_rfreg(hw, (enum radio_path)path, 0xc,
-				      MASKDWORD, 0x8992e);
-			rtl_set_rfreg(hw, (enum radio_path)path, 0x0,
-				      MASKDWORD, apk_rf_value_0[path][index]);
-			rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
-				      MASKDWORD, tmpreg);
-
-			i = 0;
-			do {
-				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80000000);
-				rtl_set_bbreg(hw, apk_offset[path],
-					      MASKDWORD, apk_value[0]);
-				RTPRINT(rtlpriv, FINIT, INIT_IQK,
-					("PHY_APCalibrate() offset 0x%x "
-					 "value 0x%x\n",
-					 apk_offset[path],
-					 rtl_get_bbreg(hw, apk_offset[path],
-						       MASKDWORD)));
-
-				mdelay(3);
-
-				rtl_set_bbreg(hw, apk_offset[path],
-					      MASKDWORD, apk_value[1]);
-				RTPRINT(rtlpriv, FINIT, INIT_IQK,
-					("PHY_APCalibrate() offset 0x%x "
-					 "value 0x%x\n",
-					 apk_offset[path],
-					 rtl_get_bbreg(hw, apk_offset[path],
-						       MASKDWORD)));
-
-				mdelay(20);
-
-				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
-
-				if (path == RF90_PATH_A)
-					tmpreg = rtl_get_bbreg(hw, 0xbd8,
-							       0x03E00000);
-				else
-					tmpreg = rtl_get_bbreg(hw, 0xbd8,
-							       0xF8000000);
-
-				RTPRINT(rtlpriv, FINIT, INIT_IQK,
-					("PHY_APCalibrate() offset "
-					 "0xbd8[25:21] %x\n", tmpreg));
-
-				i++;
-
-			} while (tmpreg > apkbound && i < 4);
-
-			apk_result[path][index] = tmpreg;
-		}
-	}
-
-	_rtl92c_phy_reload_mac_registers(hw, mac_reg, mac_backup);
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		if (index == 0)
-			continue;
-		rtl_set_bbreg(hw, bb_reg[index], MASKDWORD, bb_backup[index]);
-	}
-
-	_rtl92c_phy_reload_adda_registers(hw, afe_reg, afe_backup, 16);
-
-	for (path = 0; path < pathbound; path++) {
-		rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
-			      MASKDWORD, reg_d[path]);
-
-		if (path == RF90_PATH_B) {
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
-				      0x1000f);
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
-				      0x20101);
-		}
-
-		if (apk_result[path][1] > 6)
-			apk_result[path][1] = 6;
-	}
-
-	for (path = 0; path < pathbound; path++) {
-		rtl_set_rfreg(hw, (enum radio_path)path, 0x3, MASKDWORD,
-			      ((apk_result[path][1] << 15) |
-			       (apk_result[path][1] << 10) |
-			       (apk_result[path][1] << 5) |
-			       apk_result[path][1]));
-
-		if (path == RF90_PATH_A)
-			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
-				      ((apk_result[path][1] << 15) |
-				       (apk_result[path][1] << 10) |
-				       (0x00 << 5) | 0x05));
-		else
-			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
-				      ((apk_result[path][1] << 15) |
-				       (apk_result[path][1] << 10) |
-				       (0x02 << 5) | 0x05));
-
-		rtl_set_rfreg(hw, (enum radio_path)path, 0xe, MASKDWORD,
-			      ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) |
-			       0x08));
-
-	}
-
-	rtlphy->b_apk_done = true;
-#endif
-}
-
-static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw,
-					  bool bmain, bool is2t)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (is_hal_stop(rtlhal)) {
-		rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
-		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 {
-		if (bmain)
-			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
-		else
-			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
-
-	}
-}
-
-#undef IQK_ADDA_REG_NUM
-#undef IQK_DELAY_TIME
-
-void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	long result[4][8];
-	u8 i, final_candidate;
-	bool b_patha_ok, b_pathb_ok;
-	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
-	    reg_ecc, reg_tmp = 0;
-	bool is12simular, is13simular, is23simular;
-	bool b_start_conttx = false, b_singletone = false;
-	u32 iqk_bb_reg[10] = {
-		ROFDM0_XARXIQIMBALANCE,
-		ROFDM0_XBRXIQIMBALANCE,
-		ROFDM0_ECCATHRESHOLD,
-		ROFDM0_AGCRSSITABLE,
-		ROFDM0_XATXIQIMBALANCE,
-		ROFDM0_XBTXIQIMBALANCE,
-		ROFDM0_XCTXIQIMBALANCE,
-		ROFDM0_XCTXAFE,
-		ROFDM0_XDTXAFE,
-		ROFDM0_RXIQEXTANTA
-	};
-
-	if (b_recovery) {
-		_rtl92c_phy_reload_adda_registers(hw,
-						  iqk_bb_reg,
-						  rtlphy->iqk_bb_backup, 10);
-		return;
-	}
-	if (b_start_conttx || b_singletone)
-		return;
-	for (i = 0; i < 8; i++) {
-		result[0][i] = 0;
-		result[1][i] = 0;
-		result[2][i] = 0;
-		result[3][i] = 0;
-	}
-	final_candidate = 0xff;
-	b_patha_ok = false;
-	b_pathb_ok = false;
-	is12simular = false;
-	is23simular = false;
-	is13simular = false;
-	for (i = 0; i < 3; i++) {
-		if (IS_92C_SERIAL(rtlhal->version))
-			_rtl92c_phy_iq_calibrate(hw, result, i, true);
-		else
-			_rtl92c_phy_iq_calibrate(hw, result, i, false);
-		if (i == 1) {
-			is12simular = _rtl92c_phy_simularity_compare(hw,
-								     result, 0,
-								     1);
-			if (is12simular) {
-				final_candidate = 0;
-				break;
-			}
-		}
-		if (i == 2) {
-			is13simular = _rtl92c_phy_simularity_compare(hw,
-								     result, 0,
-								     2);
-			if (is13simular) {
-				final_candidate = 0;
-				break;
-			}
-			is23simular = _rtl92c_phy_simularity_compare(hw,
-								     result, 1,
-								     2);
-			if (is23simular)
-				final_candidate = 1;
-			else {
-				for (i = 0; i < 8; i++)
-					reg_tmp += result[3][i];
-
-				if (reg_tmp != 0)
-					final_candidate = 3;
-				else
-					final_candidate = 0xFF;
-			}
-		}
-	}
-	for (i = 0; i < 4; i++) {
-		reg_e94 = result[i][0];
-		reg_e9c = result[i][1];
-		reg_ea4 = result[i][2];
-		reg_eac = result[i][3];
-		reg_eb4 = result[i][4];
-		reg_ebc = result[i][5];
-		reg_ec4 = result[i][6];
-		reg_ecc = result[i][7];
-	}
-	if (final_candidate != 0xff) {
-		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
-		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
-		reg_ea4 = result[final_candidate][2];
-		reg_eac = result[final_candidate][3];
-		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
-		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
-		reg_ec4 = result[final_candidate][6];
-		reg_ecc = result[final_candidate][7];
-		b_patha_ok = b_pathb_ok = true;
-	} else {
-		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
-		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
-	}
-	if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
-		_rtl92c_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result,
-						   final_candidate,
-						   (reg_ea4 == 0));
-	if (IS_92C_SERIAL(rtlhal->version)) {
-		if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */
-			_rtl92c_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok,
-							   result,
-							   final_candidate,
-							   (reg_ec4 == 0));
-	}
-	_rtl92c_phy_save_adda_registers(hw, iqk_bb_reg,
-					rtlphy->iqk_bb_backup, 10);
-}
-
-void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	bool b_start_conttx = false, b_singletone = false;
-
-	if (b_start_conttx || b_singletone)
-		return;
-	if (IS_92C_SERIAL(rtlhal->version))
-		_rtl92c_phy_lc_calibrate(hw, true);
-	else
-		_rtl92c_phy_lc_calibrate(hw, false);
-}
-
-void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (rtlphy->b_apk_done)
-		return;
-	if (IS_92C_SERIAL(rtlhal->version))
-		_rtl92c_phy_ap_calibrate(hw, delta, true);
-	else
-		_rtl92c_phy_ap_calibrate(hw, delta, false);
-}
-
-void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (IS_92C_SERIAL(rtlhal->version))
-		_rtl92c_phy_set_rfpath_switch(hw, bmain, true);
-	else
-		_rtl92c_phy_set_rfpath_switch(hw, bmain, false);
-}
-
-bool rtl92c_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 b_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"));
-			b_postprocessing = true;
-			break;
-		case IO_CMD_PAUSE_DM_BY_SCAN:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-				 ("[IO CMD] Pause DM before scan.\n"));
-			b_postprocessing = true;
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-	} while (false);
-	if (b_postprocessing && !rtlphy->set_io_inprogress) {
-		rtlphy->set_io_inprogress = true;
-		rtlphy->current_io_type = iotype;
-	} else {
-		return false;
-	}
-	rtl92c_phy_set_io(hw);
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
-	return true;
-}
-
-void rtl92c_phy_set_io(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-		 ("--->Cmd(%#x), set_io_inprogress(%d)\n",
-		  rtlphy->current_io_type, rtlphy->set_io_inprogress));
-	switch (rtlphy->current_io_type) {
-	case IO_CMD_RESUME_DM_BY_SCAN:
-		dm_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
-		rtl92c_dm_write_dig(hw);
-		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
-		break;
-	case IO_CMD_PAUSE_DM_BY_SCAN:
-		rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
-		dm_digtable.cur_igvalue = 0x17;
-		rtl92c_dm_write_dig(hw);
-		break;
-	default:
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("switch case not process\n"));
-		break;
-	}
-	rtlphy->set_io_inprogress = false;
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-		 ("<---(%#x)\n", rtlphy->current_io_type));
-}
-
-void rtl92ce_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 _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw)
-{
-	u32 u4b_tmp;
-	u8 delay = 5;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
-	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
-	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
-	u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
-	while (u4b_tmp != 0 && delay > 0) {
-		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
-		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
-		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
-		u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
-		delay--;
-	}
-	if (delay == 0) {
-		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
-		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
-		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
-		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
-			 ("Switch RF timeout !!!.\n"));
-		return;
-	}
-	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
-	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
-}
-
 static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 					    enum rf_pwrstate rfpwr_state)
 {
@@ -2648,7 +599,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 				  jiffies_to_msecs(jiffies -
 						   ppsc->last_awake_jiffies)));
 			ppsc->last_sleep_jiffies = jiffies;
-			_rtl92ce_phy_set_rf_sleep(hw);
+			_rtl92c_phy_set_rf_sleep(hw);
 			break;
 		}
 	default:
@@ -2663,7 +614,7 @@ static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 	return bresult;
 }
 
-bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
+bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 				   enum rf_pwrstate rfpwr_state)
 {
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
index ca4daee..a37267e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
@@ -57,8 +57,6 @@
 #define IQK_MAC_REG_NUM			4
 
 #define RF90_PATH_MAX			2
-#define CHANNEL_MAX_NUMBER		14
-#define CHANNEL_GROUP_MAX		3
 
 #define CT_OFFSET_MAC_ADDR		0X16
 
@@ -78,9 +76,7 @@
 #define CT_OFFSET_CUSTOMER_ID		0x7F
 
 #define RTL92C_MAX_PATH_NUM		2
-#define CHANNEL_MAX_NUMBER		14
-#define CHANNEL_GROUP_MAX		3
-
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER	255
 enum swchnlcmd_id {
 	CMDID_END,
 	CMDID_SET_TXPOWEROWER_LEVEL,
@@ -195,11 +191,11 @@ extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
 extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
 				   enum radio_path rfpath, u32 regaddr,
 				   u32 bitmask);
-extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
+extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
 				  enum radio_path rfpath, u32 regaddr,
 				  u32 bitmask, u32 data);
 extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw);
-extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw);
+bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw);
 extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw);
 extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
 						 enum radio_path rfpath);
@@ -227,11 +223,32 @@ bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw,
 					      u32 rfpath);
 bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
-extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
+bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 					  enum rf_pwrstate rfpwr_state);
-void rtl92c_phy_config_bb_external_pa(struct ieee80211_hw *hw);
 void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
 bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
 void rtl92c_phy_set_io(struct ieee80211_hw *hw);
+void rtl92c_bb_block_on(struct ieee80211_hw *hw);
+u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
+				      enum radio_path rfpath, u32 offset);
+u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+					 enum radio_path rfpath, u32 offset);
+u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
+void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
+					enum radio_path rfpath, u32 offset,
+					u32 data);
+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data);
+void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+					   enum radio_path rfpath, u32 offset,
+					   u32 data);
+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data);
+bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
+void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
+bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
+void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
index 875d514..b0868a6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
@@ -63,7 +63,15 @@
 #define REG_LEDCFG3				0x004F
 #define REG_FSIMR				0x0050
 #define REG_FSISR				0x0054
-
+#define REG_HSIMR				0x0058
+#define REG_HSISR				0x005c
+
+/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */
+#define REG_GPIO_PIN_CTRL_2			0x0060
+/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */
+#define REG_GPIO_IO_SEL_2			0x0062
+/* RTL8723 WIFI/BT/GPS Multi-Function control source. */
+#define REG_MULTI_FUNC_CTRL			0x0068
 #define REG_MCUFWDL				0x0080
 
 #define REG_HMEBOX_EXT_0			0x0088
@@ -79,6 +87,7 @@
 #define REG_PCIE_MIO_INTD			0x00E8
 #define REG_HPON_FSM				0x00EC
 #define REG_SYS_CFG				0x00F0
+#define REG_GPIO_OUTSTS				0x00F4	/* For RTL8723 only.*/
 
 #define REG_CR					0x0100
 #define REG_PBP					0x0104
@@ -209,6 +218,8 @@
 #define REG_RDG_PIFS				0x0513
 #define REG_SIFS_CTX				0x0514
 #define REG_SIFS_TRX				0x0516
+#define REG_SIFS_CCK				0x0514
+#define REG_SIFS_OFDM				0x0516
 #define REG_AGGR_BREAK_TIME			0x051A
 #define REG_SLOT				0x051B
 #define REG_TX_PTCL_CTRL			0x0520
@@ -261,6 +272,10 @@
 #define REG_MAC_SPEC_SIFS			0x063A
 #define REG_RESP_SIFS_CCK			0x063C
 #define REG_RESP_SIFS_OFDM			0x063E
+/* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */
+#define REG_R2T_SIFS				0x063C
+/* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */
+#define REG_T2T_SIFS				0x063E
 #define REG_ACKTO				0x0640
 #define REG_CTS2TO				0x0641
 #define REG_EIFS				0x0642
@@ -641,9 +656,10 @@
 #define	STOPBE					BIT(1)
 #define	STOPBK					BIT(0)
 
-#define	RCR_APPFCS				BIT(31)
+#define	RCR_APP_FCS				BIT(31)
 #define	RCR_APP_MIC				BIT(30)
 #define	RCR_APP_ICV				BIT(29)
+#define	RCR_APP_PHYSTS				BIT(28)
 #define	RCR_APP_PHYST_RXFF			BIT(28)
 #define	RCR_APP_BA_SSN				BIT(27)
 #define	RCR_ENMBID				BIT(24)
@@ -759,6 +775,7 @@
 
 #define	BOOT_FROM_EEPROM			BIT(4)
 #define	EEPROM_EN				BIT(5)
+#define	EEPROMSEL				BOOT_FROM_EEPROM
 
 #define AFE_BGEN				BIT(0)
 #define AFE_MBEN				BIT(1)
@@ -876,6 +893,8 @@
 #define BD_MAC2					BIT(9)
 #define BD_MAC1					BIT(10)
 #define IC_MACPHY_MODE				BIT(11)
+#define BT_FUNC					BIT(16)
+#define VENDOR_ID				BIT(19)
 #define PAD_HWPD_IDN				BIT(22)
 #define TRP_VAUX_EN				BIT(23)
 #define TRP_BT_EN				BIT(24)
@@ -883,6 +902,28 @@
 #define BD_HCI_SEL				BIT(26)
 #define TYPE_ID					BIT(27)
 
+/* REG_GPIO_OUTSTS (For RTL8723 only) */
+#define	EFS_HCI_SEL				(BIT(0)|BIT(1))
+#define	PAD_HCI_SEL				(BIT(2)|BIT(3))
+#define	HCI_SEL					(BIT(4)|BIT(5))
+#define	PKG_SEL_HCI				BIT(6)
+#define	FEN_GPS					BIT(7)
+#define	FEN_BT					BIT(8)
+#define	FEN_WL					BIT(9)
+#define	FEN_PCI					BIT(10)
+#define	FEN_USB					BIT(11)
+#define	BTRF_HWPDN_N				BIT(12)
+#define	WLRF_HWPDN_N				BIT(13)
+#define	PDN_BT_N				BIT(14)
+#define	PDN_GPS_N				BIT(15)
+#define	BT_CTL_HWPDN				BIT(16)
+#define	GPS_CTL_HWPDN				BIT(17)
+#define	PPHY_SUSB				BIT(20)
+#define	UPHY_SUSB				BIT(21)
+#define	PCI_SUSEN				BIT(22)
+#define	USB_SUSEN				BIT(23)
+#define	RF_RL_ID			(BIT(31) | BIT(30) | BIT(29) | BIT(28))
+
 #define CHIP_VER_RTL_MASK			0xF000
 #define CHIP_VER_RTL_SHIFT			12
 
@@ -1035,7 +1076,7 @@
 #define _RARF_RC7(x)				(((x) & 0x1F) << 16)
 #define _RARF_RC8(x)				(((x) & 0x1F) << 24)
 
-#define AC_PARAM_TXOP_LIMIT_OFFSET		16
+#define AC_PARAM_TXOP_OFFSET			16
 #define AC_PARAM_ECW_MAX_OFFSET			12
 #define AC_PARAM_ECW_MIN_OFFSET			8
 #define AC_PARAM_AIFS_OFFSET			0
@@ -1184,6 +1225,30 @@
 
 #define	HAL_8192C_HW_GPIO_WPS_BIT		BIT(2)
 
+/* REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
+/* Enable GPIO[9] as WiFi HW PDn source */
+#define	WL_HWPDN_EN				BIT(0)
+/* WiFi HW PDn polarity control */
+#define	WL_HWPDN_SL				BIT(1)
+/* WiFi function enable */
+#define	WL_FUNC_EN				BIT(2)
+/* Enable GPIO[9] as WiFi RF HW PDn source */
+#define	WL_HWROF_EN				BIT(3)
+/* Enable GPIO[11] as BT HW PDn source */
+#define	BT_HWPDN_EN				BIT(16)
+/* BT HW PDn polarity control */
+#define	BT_HWPDN_SL				BIT(17)
+/* BT function enable */
+#define	BT_FUNC_EN				BIT(18)
+/* Enable GPIO[11] as BT/GPS RF HW PDn source */
+#define	BT_HWROF_EN				BIT(19)
+/* Enable GPIO[10] as GPS HW PDn source */
+#define	GPS_HWPDN_EN				BIT(20)
+/* GPS HW PDn polarity control */
+#define	GPS_HWPDN_SL				BIT(21)
+/* GPS function enable */
+#define	GPS_FUNC_EN				BIT(22)
+
 #define	RPMAC_RESET				0x100
 #define	RPMAC_TXSTART				0x104
 #define	RPMAC_TXLEGACYSIG			0x108
@@ -1496,7 +1561,7 @@
 #define	BTXHTSTBC				0x30
 #define	BTXHTADVANCECODING			0x40
 #define	BTXHTSHORTGI				0x80
-#define	BTXHTNUMBERHT_LT	F		0x300
+#define	BTXHTNUMBERHT_LTF			0x300
 #define	BTXHTCRC8				0x3fc00
 #define	BCOUNTERRESET				0x10000
 #define	BNUMOFOFDMTX				0xffff
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
index ffd8e04..669b116 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
@@ -61,7 +61,7 @@ void rtl92c_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
 	}
 }
 
-void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 				       u8 *ppowerlevel)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -410,7 +410,7 @@ static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
 	}
 }
 
-void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
 					u8 *ppowerlevel, u8 channel)
 {
 	u32 writeVal[2], powerBase0[2], powerBase1[2];
@@ -430,7 +430,7 @@ void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
 	}
 }
 
-bool rtl92c_phy_rf6052_config(struct ieee80211_hw *hw)
+bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
@@ -484,11 +484,11 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
 
 		switch (rfpath) {
 		case RF90_PATH_A:
-			rtstatus = rtl92c_phy_config_rf_with_headerfile(hw,
+			rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw,
 					(enum radio_path) rfpath);
 			break;
 		case RF90_PATH_B:
-			rtstatus = rtl92c_phy_config_rf_with_headerfile(hw,
+			rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw,
 					(enum radio_path) rfpath);
 			break;
 		case RF90_PATH_C:
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
index d3014f9..3aa520c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
@@ -40,5 +40,8 @@ extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 					      u8 *ppowerlevel);
 extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
 					       u8 *ppowerlevel, u8 channel);
-extern bool rtl92c_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index b366e88..b1cc4d4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -37,6 +37,7 @@
 #include "phy.h"
 #include "dm.h"
 #include "hw.h"
+#include "rf.h"
 #include "sw.h"
 #include "trx.h"
 #include "led.h"
@@ -46,13 +47,13 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-	rtlpriv->dm.b_dm_initialgain_enable = 1;
+	rtlpriv->dm.dm_initialgain_enable = 1;
 	rtlpriv->dm.dm_flag = 0;
-	rtlpriv->dm.b_disable_framebursting = 0;;
+	rtlpriv->dm.disable_framebursting = 0;
 	rtlpriv->dm.thermalvalue = 0;
 	rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
 
-	rtlpci->receive_config = (RCR_APPFCS |
+	rtlpci->receive_config = (RCR_APP_FCS |
 				  RCR_AMF |
 				  RCR_ADF |
 				  RCR_APP_MIC |
@@ -122,7 +123,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
 	.switch_channel = rtl92c_phy_sw_chnl,
 	.dm_watchdog = rtl92c_dm_watchdog,
 	.scan_operation_backup = rtl92c_phy_scan_operation_backup,
-	.set_rf_power_state = rtl92c_phy_set_rf_power_state,
+	.set_rf_power_state = rtl92ce_phy_set_rf_power_state,
 	.led_control = rtl92ce_led_control,
 	.set_desc = rtl92ce_set_desc,
 	.get_desc = rtl92ce_get_desc,
@@ -133,8 +134,17 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
 	.deinit_sw_leds = rtl92ce_deinit_sw_leds,
 	.get_bbreg = rtl92c_phy_query_bb_reg,
 	.set_bbreg = rtl92c_phy_set_bb_reg,
-	.get_rfreg = rtl92c_phy_query_rf_reg,
-	.set_rfreg = rtl92c_phy_set_rf_reg,
+	.get_rfreg = rtl92ce_phy_query_rf_reg,
+	.set_rfreg = rtl92ce_phy_set_rf_reg,
+	.cmd_send_packet = _rtl92c_cmd_send_packet,
+	.phy_rf6052_config = rtl92ce_phy_rf6052_config,
+	.phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower,
+	.phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower,
+	.config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile,
+	.config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile,
+	.phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
+	.phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
+	.dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
 };
 
 static struct rtl_mod_params rtl92ce_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h
index de1198c..36e6576 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h
@@ -33,5 +33,19 @@
 int rtl92c_init_sw_vars(struct ieee80211_hw *hw);
 void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw);
 void rtl92c_init_var_map(struct ieee80211_hw *hw);
+bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
+			     struct sk_buff *skb);
+void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel);
+void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					 u8 *ppowerlevel, u8 channel);
+bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+						  u8 configtype);
+bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+						    u8 configtype);
+void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
+u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw,
+			    enum radio_path rfpath, u32 regaddr, u32 bitmask);
+void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
 
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index bf5852f..aa2b581 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -36,7 +36,7 @@
 #include "trx.h"
 #include "led.h"
 
-static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(u16 fc,
+static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc,
 							  unsigned int
 							  skb_queue)
 {
@@ -245,24 +245,24 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 				       struct rtl_stats *pstats,
 				       struct rx_desc_92c *pdesc,
 				       struct rx_fwinfo_92c *p_drvinfo,
-				       bool bpacket_match_bssid,
-				       bool bpacket_toself,
-				       bool b_packet_beacon)
+				       bool packet_match_bssid,
+				       bool packet_toself,
+				       bool packet_beacon)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct phy_sts_cck_8192s_t *cck_buf;
 	s8 rx_pwr_all, rx_pwr[4];
-	u8 rf_rx_num, evm, pwdb_all;
+	u8 evm, pwdb_all, rf_rx_num = 0;
 	u8 i, max_spatial_stream;
-	u32 rssi, total_rssi;
+	u32 rssi, total_rssi = 0;
 	bool is_cck_rate;
 
 	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
-	pstats->b_packet_matchbssid = bpacket_match_bssid;
-	pstats->b_packet_toself = bpacket_toself;
-	pstats->b_is_cck = is_cck_rate;
-	pstats->b_packet_beacon = b_packet_beacon;
-	pstats->b_is_cck = is_cck_rate;
+	pstats->packet_matchbssid = packet_match_bssid;
+	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_signalquality[0] = -1;
 	pstats->rx_mimo_signalquality[1] = -1;
 
@@ -315,7 +315,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 		pstats->rx_pwdb_all = pwdb_all;
 		pstats->recvsignalpower = rx_pwr_all;
 
-		if (bpacket_match_bssid) {
+		if (packet_match_bssid) {
 			u8 sq;
 			if (pstats->rx_pwdb_all > 40)
 				sq = 100;
@@ -334,10 +334,10 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			pstats->rx_mimo_signalquality[1] = -1;
 		}
 	} else {
-		rtlpriv->dm.brfpath_rxenable[0] =
-		    rtlpriv->dm.brfpath_rxenable[1] = true;
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
 		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
-			if (rtlpriv->dm.brfpath_rxenable[i])
+			if (rtlpriv->dm.rfpath_rxenable[i])
 				rf_rx_num++;
 
 			rx_pwr[i] =
@@ -347,7 +347,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 			rtlpriv->stats.rx_snr_db[i] =
 			    (long)(p_drvinfo->rxsnr[i] / 2);
 
-			if (bpacket_match_bssid)
+			if (packet_match_bssid)
 				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 		}
 
@@ -366,7 +366,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 		for (i = 0; i < max_spatial_stream; i++) {
 			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 
-			if (bpacket_match_bssid) {
+			if (packet_match_bssid) {
 				if (i == 0)
 					pstats->signalquality =
 					    (u8) (evm & 0xff);
@@ -393,7 +393,7 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw,
 	u8 rfpath;
 	u32 last_rssi, tmpval;
 
-	if (pstats->b_packet_toself || pstats->b_packet_beacon) {
+	if (pstats->packet_toself || pstats->packet_beacon) {
 		rtlpriv->stats.rssi_calculate_cnt++;
 
 		if (rtlpriv->stats.ui_rssi.total_num++ >=
@@ -421,7 +421,7 @@ static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw,
 		pstats->rssi = rtlpriv->stats.signal_strength;
 	}
 
-	if (!pstats->b_is_cck && pstats->b_packet_toself) {
+	if (!pstats->is_cck && pstats->packet_toself) {
 		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
 		     rfpath++) {
 
@@ -463,7 +463,7 @@ static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw,
 					       struct rtl_stats *pstats)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	int weighting;
+	int weighting = 0;
 
 	if (rtlpriv->stats.recv_signal_power == 0)
 		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
@@ -493,7 +493,7 @@ static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw,
 		    rtlpriv->dm.undecorated_smoothed_pwdb;
 	}
 
-	if (pstats->b_packet_toself || pstats->b_packet_beacon) {
+	if (pstats->packet_toself || pstats->packet_beacon) {
 		if (undecorated_smoothed_pwdb < 0)
 			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
 
@@ -525,7 +525,7 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
 	u32 last_evm, n_spatialstream, tmpval;
 
 	if (pstats->signalquality != 0) {
-		if (pstats->b_packet_toself || pstats->b_packet_beacon) {
+		if (pstats->packet_toself || pstats->packet_beacon) {
 
 			if (rtlpriv->stats.ui_link_quality.total_num++ >=
 			    PHY_LINKQUALITY_SLID_WIN_MAX) {
@@ -595,8 +595,8 @@ static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw,
 				     struct rtl_stats *pcurrent_stats)
 {
 
-	if (!pcurrent_stats->b_packet_matchbssid &&
-	    !pcurrent_stats->b_packet_beacon)
+	if (!pcurrent_stats->packet_matchbssid &&
+	    !pcurrent_stats->packet_beacon)
 		return;
 
 	_rtl92ce_process_ui_rssi(hw, pcurrent_stats);
@@ -617,34 +617,36 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
 	u8 *tmp_buf;
 	u8 *praddr;
 	u8 *psaddr;
-	u16 fc, type;
-	bool b_packet_matchbssid, b_packet_toself, b_packet_beacon;
+	__le16 fc;
+	u16 type, c_fc;
+	bool packet_matchbssid, packet_toself, packet_beacon;
 
 	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
 
 	hdr = (struct ieee80211_hdr *)tmp_buf;
-	fc = le16_to_cpu(hdr->frame_control);
+	fc = hdr->frame_control;
+	c_fc = le16_to_cpu(fc);
 	type = WLAN_FC_GET_TYPE(fc);
 	praddr = hdr->addr1;
 	psaddr = hdr->addr2;
 
-	b_packet_matchbssid =
+	packet_matchbssid =
 	    ((IEEE80211_FTYPE_CTL != type) &&
 	     (!compare_ether_addr(mac->bssid,
-				  (fc & IEEE80211_FCTL_TODS) ?
-				  hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ?
+				  (c_fc & IEEE80211_FCTL_TODS) ?
+				  hdr->addr1 : (c_fc & IEEE80211_FCTL_FROMDS) ?
 				  hdr->addr2 : hdr->addr3)) &&
-	     (!pstats->b_hwerror) && (!pstats->b_crc) && (!pstats->b_icv));
+	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
 
-	b_packet_toself = b_packet_matchbssid &&
+	packet_toself = packet_matchbssid &&
 	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
 
 	if (ieee80211_is_beacon(fc))
-		b_packet_beacon = true;
+		packet_beacon = true;
 
 	_rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
-				   b_packet_matchbssid, b_packet_toself,
-				   b_packet_beacon);
+				   packet_matchbssid, packet_toself,
+				   packet_beacon);
 
 	_rtl92ce_process_phyinfo(hw, tmp_buf, pstats);
 }
@@ -662,14 +664,14 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
 	    RX_DRV_INFO_SIZE_UNIT;
 	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
-	stats->b_icv = (u16) GET_RX_DESC_ICV(pdesc);
-	stats->b_crc = (u16) GET_RX_DESC_CRC32(pdesc);
-	stats->b_hwerror = (stats->b_crc | stats->b_icv);
+	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	stats->hwerror = (stats->crc | stats->icv);
 	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
 	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
-	stats->b_shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
-	stats->b_isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
-	stats->b_isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+	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)
 				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
 	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
 	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
@@ -689,7 +691,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
 	if (GET_RX_DESC_RXHT(pdesc))
 		rx_status->flag |= RX_FLAG_HT;
 
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	if (stats->decrypted)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
@@ -727,27 +729,24 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	bool b_defaultadapter = true;
-
-	struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid);
-
+	bool defaultadapter = true;
+	struct ieee80211_sta *sta;
 	u8 *pdesc = (u8 *) pdesc_tx;
 	struct rtl_tcb_desc tcb_desc;
 	u8 *qc = ieee80211_get_qos_ctl(hdr);
 	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
 	u16 seq_number;
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u8 rate_flag = info->control.rates[0].flags;
 
 	enum rtl_desc_qsel fw_qsel =
-	    _rtl92ce_map_hwqueue_to_fwqueue(le16_to_cpu(hdr->frame_control),
-					    queue_index);
+	    _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index);
 
-	bool b_firstseg = ((hdr->seq_ctrl &
-			    cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+	bool firstseg = ((hdr->seq_ctrl &
+			  cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
 
-	bool b_lastseg = ((hdr->frame_control &
-			   cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+	bool lastseg = ((hdr->frame_control &
+			 cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
 
 	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
 					    skb->data, skb->len,
@@ -759,7 +758,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 
 	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c));
 
-	if (b_firstseg) {
+	if (firstseg) {
 		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
 
 		SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate);
@@ -774,25 +773,25 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 		}
 		SET_TX_DESC_SEQ(pdesc, seq_number);
 
-		SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.b_rts_enable &&
+		SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable &&
 						!tcb_desc.
-						b_cts_enable) ? 1 : 0));
+						cts_enable) ? 1 : 0));
 		SET_TX_DESC_HW_RTS_ENABLE(pdesc,
-					  ((tcb_desc.b_rts_enable
-					    || tcb_desc.b_cts_enable) ? 1 : 0));
-		SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.b_cts_enable) ? 1 : 0));
-		SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.b_rts_stbc) ? 1 : 0));
+					  ((tcb_desc.rts_enable
+					    || tcb_desc.cts_enable) ? 1 : 0));
+		SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0));
+		SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0));
 
 		SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate);
 		SET_TX_DESC_RTS_BW(pdesc, 0);
 		SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc);
 		SET_TX_DESC_RTS_SHORT(pdesc,
 				      ((tcb_desc.rts_rate <= DESC92C_RATE54M) ?
-				      (tcb_desc.b_rts_use_shortpreamble ? 1 : 0)
-				      : (tcb_desc.b_rts_use_shortgi ? 1 : 0)));
+				      (tcb_desc.rts_use_shortpreamble ? 1 : 0)
+				      : (tcb_desc.rts_use_shortgi ? 1 : 0)));
 
 		if (mac->bw_40) {
-			if (tcb_desc.b_packet_bw) {
+			if (tcb_desc.packet_bw) {
 				SET_TX_DESC_DATA_BW(pdesc, 1);
 				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
 			} else {
@@ -811,10 +810,13 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 		SET_TX_DESC_LINIP(pdesc, 0);
 		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
 
+		rcu_read_lock();
+		sta = ieee80211_find_sta(mac->vif, mac->bssid);
 		if (sta) {
 			u8 ampdu_density = sta->ht_cap.ampdu_density;
 			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
 		}
+		rcu_read_unlock();
 
 		if (info->control.hw_key) {
 			struct ieee80211_key_conf *keyconf =
@@ -854,14 +856,14 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 		}
 	}
 
-	SET_TX_DESC_FIRST_SEG(pdesc, (b_firstseg ? 1 : 0));
-	SET_TX_DESC_LAST_SEG(pdesc, (b_lastseg ? 1 : 0));
+	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) skb->len);
 
 	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
 
-	if (rtlpriv->dm.b_useramask) {
+	if (rtlpriv->dm.useramask) {
 		SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index);
 		SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id);
 	} else {
@@ -869,16 +871,16 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 		SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index);
 	}
 
-	if ((!ieee80211_is_data_qos(fc)) && ppsc->b_leisure_ps &&
-	    ppsc->b_fwctrl_lps) {
+	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
+	    ppsc->fwctrl_lps) {
 		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
 		SET_TX_DESC_PKT_ID(pdesc, 8);
 
-		if (!b_defaultadapter)
+		if (!defaultadapter)
 			SET_TX_DESC_QOS(pdesc, 1);
 	}
 
-	SET_TX_DESC_MORE_FRAG(pdesc, (b_lastseg ? 0 : 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))) {
@@ -889,8 +891,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
 }
 
 void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
-			     u8 *pdesc, bool b_firstseg,
-			     bool b_lastseg, struct sk_buff *skb)
+			     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));
@@ -901,11 +903,11 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
 					    PCI_DMA_TODEVICE);
 
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 
 	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
 
-	if (b_firstseg)
+	if (firstseg)
 		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
 
 	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
@@ -1029,3 +1031,36 @@ void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue)
 			       BIT(0) << (hw_queue));
 	}
 }
+
+bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
+			     struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl8192_tx_ring *ring;
+	struct rtl_tx_desc *pdesc;
+	u8 own;
+	unsigned long flags;
+	struct sk_buff *pskb = NULL;
+
+	ring = &rtlpci->tx_ring[BEACON_QUEUE];
+
+	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+
+	pskb = __skb_dequeue(&ring->queue);
+	if (pskb)
+		kfree_skb(pskb);
+
+	pdesc = &ring->desc[0];
+	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+
+	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+
+	__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;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
index 53d0e0a..803adcc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
@@ -40,470 +40,494 @@
 #define USB_HWDESC_HEADER_LEN			32
 #define CRCLENGTH				4
 
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask)		\
+	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\
+	BIT_LEN_MASK_32(__mask))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val)	\
+	(*(__le32 *)(__pdesc) = 				\
+	(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) &	\
+	(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) |		\
+	(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read/write various fields in RX or TX descriptors */
+
 #define SET_TX_DESC_PKT_SIZE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val)
 #define SET_TX_DESC_OFFSET(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val)
 #define SET_TX_DESC_BMC(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val)
 #define SET_TX_DESC_HTC(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val)
 #define SET_TX_DESC_LAST_SEG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
 #define SET_TX_DESC_FIRST_SEG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
 #define SET_TX_DESC_LINIP(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
 #define SET_TX_DESC_NO_ACM(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
 #define SET_TX_DESC_GF(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
 #define SET_TX_DESC_OWN(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
 
 #define GET_TX_DESC_PKT_SIZE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 0, 16)
+	SHIFT_AND_MASK_LE(__pdesc, 0, 16)
 #define GET_TX_DESC_OFFSET(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 16, 8)
+	SHIFT_AND_MASK_LE(__pdesc, 16, 8)
 #define GET_TX_DESC_BMC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 24, 1)
 #define GET_TX_DESC_HTC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 25, 1)
 #define GET_TX_DESC_LAST_SEG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 26, 1)
 #define GET_TX_DESC_FIRST_SEG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 27, 1)
 #define GET_TX_DESC_LINIP(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 28, 1)
 #define GET_TX_DESC_NO_ACM(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 29, 1)
 #define GET_TX_DESC_GF(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 30, 1)
 #define GET_TX_DESC_OWN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 31, 1)
 
 #define SET_TX_DESC_MACID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val)
 #define SET_TX_DESC_AGG_BREAK(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val)
 #define SET_TX_DESC_BK(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val)
 #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val)
 #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val)
 #define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val)
 #define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val)
 #define SET_TX_DESC_PIFS(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val)
 #define SET_TX_DESC_RATE_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val)
 #define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val)
 #define SET_TX_DESC_EN_DESC_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val)
 #define SET_TX_DESC_SEC_TYPE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val)
 #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 24, 8, __val)
 
 #define GET_TX_DESC_MACID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
 #define GET_TX_DESC_AGG_ENABLE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 5, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 5, 1)
 #define GET_TX_DESC_AGG_BREAK(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 6, 1)
 #define GET_TX_DESC_RDG_ENABLE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 7, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 7, 1)
 #define GET_TX_DESC_QUEUE_SEL(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 8, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 8, 5)
 #define GET_TX_DESC_RDG_NAV_EXT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+4, 13, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 13, 1)
 #define GET_TX_DESC_LSIG_TXOP_EN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
 #define GET_TX_DESC_PIFS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
 #define GET_TX_DESC_RATE_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
 #define GET_TX_DESC_NAV_USE_HDR(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+4, 20, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 20, 1)
 #define GET_TX_DESC_EN_DESC_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 21, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 21, 1)
 #define GET_TX_DESC_SEC_TYPE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 22, 2)
+	SHIFT_AND_MASK_LE(__pdesc+4, 22, 2)
 #define GET_TX_DESC_PKT_OFFSET(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 24, 8)
+	SHIFT_AND_MASK_LE(__pdesc+4, 24, 8)
 
 #define SET_TX_DESC_RTS_RC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val)
 #define SET_TX_DESC_DATA_RC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val)
 #define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val)
 #define SET_TX_DESC_MORE_FRAG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val)
 #define SET_TX_DESC_RAW(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val)
 #define SET_TX_DESC_CCX(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val)
 #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val)
 #define SET_TX_DESC_ANTSEL_A(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val)
 #define SET_TX_DESC_ANTSEL_B(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val)
 #define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val)
 #define SET_TX_DESC_TX_ANTL(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val)
 #define SET_TX_DESC_TX_ANT_HT(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val)
 
 #define GET_TX_DESC_RTS_RC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 0, 6)
+	SHIFT_AND_MASK_LE(__pdesc+8, 0, 6)
 #define GET_TX_DESC_DATA_RC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 6, 6)
+	SHIFT_AND_MASK_LE(__pdesc+8, 6, 6)
 #define GET_TX_DESC_BAR_RTY_TH(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 14, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 14, 2)
 #define GET_TX_DESC_MORE_FRAG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 17, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 17, 1)
 #define GET_TX_DESC_RAW(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 18, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 18, 1)
 #define GET_TX_DESC_CCX(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 19, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 19, 1)
 #define GET_TX_DESC_AMPDU_DENSITY(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+8, 20, 3)
+	SHIFT_AND_MASK_LE(__pdesc+8, 20, 3)
 #define GET_TX_DESC_ANTSEL_A(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 24, 1)
 #define GET_TX_DESC_ANTSEL_B(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 25, 1)
 #define GET_TX_DESC_TX_ANT_CCK(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 26, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 26, 2)
 #define GET_TX_DESC_TX_ANTL(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 28, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 28, 2)
 #define GET_TX_DESC_TX_ANT_HT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 30, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 30, 2)
 
 #define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val)
 #define SET_TX_DESC_TAIL_PAGE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val)
 #define SET_TX_DESC_SEQ(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val)
 #define SET_TX_DESC_PKT_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val)
 
 #define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+12, 0, 8)
+	SHIFT_AND_MASK_LE(__pdesc+12, 0, 8)
 #define GET_TX_DESC_TAIL_PAGE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 8, 8)
+	SHIFT_AND_MASK_LE(__pdesc+12, 8, 8)
 #define GET_TX_DESC_SEQ(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 16, 12)
+	SHIFT_AND_MASK_LE(__pdesc+12, 16, 12)
 #define GET_TX_DESC_PKT_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 28, 4)
+	SHIFT_AND_MASK_LE(__pdesc+12, 28, 4)
 
 #define SET_TX_DESC_RTS_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val)
 #define SET_TX_DESC_AP_DCFE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val)
 #define SET_TX_DESC_QOS(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val)
 #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val)
 #define SET_TX_DESC_USE_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val)
 #define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val)
 #define SET_TX_DESC_DISABLE_FB(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val)
 #define SET_TX_DESC_CTS2SELF(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val)
 #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val)
 #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val)
 #define SET_TX_DESC_PORT_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val)
 #define SET_TX_DESC_WAIT_DCTS(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val)
 #define SET_TX_DESC_CTS2AP_EN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val)
 #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val)
 #define SET_TX_DESC_TX_STBC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val)
 #define SET_TX_DESC_DATA_SHORT(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val)
 #define SET_TX_DESC_DATA_BW(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val)
 #define SET_TX_DESC_RTS_SHORT(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val)
 #define SET_TX_DESC_RTS_BW(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val)
 #define SET_TX_DESC_RTS_SC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val)
 #define SET_TX_DESC_RTS_STBC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val)
 
 #define GET_TX_DESC_RTS_RATE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+16, 0, 5)
 #define GET_TX_DESC_AP_DCFE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 5, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 5, 1)
 #define GET_TX_DESC_QOS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 6, 1)
 #define GET_TX_DESC_HWSEQ_EN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 7, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 7, 1)
 #define GET_TX_DESC_USE_RATE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 8, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 8, 1)
 #define GET_TX_DESC_DISABLE_RTS_FB(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+16, 9, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 9, 1)
 #define GET_TX_DESC_DISABLE_FB(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 10, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 10, 1)
 #define GET_TX_DESC_CTS2SELF(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 11, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 11, 1)
 #define GET_TX_DESC_RTS_ENABLE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 12, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 12, 1)
 #define GET_TX_DESC_HW_RTS_ENABLE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+16, 13, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 13, 1)
 #define GET_TX_DESC_PORT_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 14, 1)
 #define GET_TX_DESC_WAIT_DCTS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 18, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 18, 1)
 #define GET_TX_DESC_CTS2AP_EN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 19, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 19, 1)
 #define GET_TX_DESC_TX_SUB_CARRIER(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+16, 20, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 20, 2)
 #define GET_TX_DESC_TX_STBC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 22, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 22, 2)
 #define GET_TX_DESC_DATA_SHORT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 24, 1)
 #define GET_TX_DESC_DATA_BW(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 25, 1)
 #define GET_TX_DESC_RTS_SHORT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 26, 1)
 #define GET_TX_DESC_RTS_BW(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 27, 1)
 #define GET_TX_DESC_RTS_SC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 28, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 28, 2)
 #define GET_TX_DESC_RTS_STBC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 30, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 30, 2)
 
 #define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
 #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
 #define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val)
+	SET_BITS_OFFSET_LE(__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)
+	SET_BITS_OFFSET_LE(__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)
+	SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val)
 #define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val)
 #define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val)
 #define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val)
 
 #define GET_TX_DESC_TX_RATE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+20, 0, 6)
+	SHIFT_AND_MASK_LE(__pdesc+20, 0, 6)
 #define GET_TX_DESC_DATA_SHORTGI(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+20, 6, 1)
 #define GET_TX_DESC_CCX_TAG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+20, 7, 1)
+	SHIFT_AND_MASK_LE(__pdesc+20, 7, 1)
 #define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 8, 5)
+	SHIFT_AND_MASK_LE(__pdesc+20, 8, 5)
 #define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 13, 4)
+	SHIFT_AND_MASK_LE(__pdesc+20, 13, 4)
 #define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 17, 1)
+	SHIFT_AND_MASK_LE(__pdesc+20, 17, 1)
 #define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 18, 6)
+	SHIFT_AND_MASK_LE(__pdesc+20, 18, 6)
 #define GET_TX_DESC_USB_TXAGG_NUM(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 24, 8)
+	SHIFT_AND_MASK_LE(__pdesc+20, 24, 8)
 
 #define SET_TX_DESC_TXAGC_A(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val)
 #define SET_TX_DESC_TXAGC_B(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val)
 #define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val)
 #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val)
 #define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val)
 #define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val)
 #define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val)
+	SET_BITS_OFFSET_LE(__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)
+	SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val)
 
 #define GET_TX_DESC_TXAGC_A(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+24, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+24, 0, 5)
 #define GET_TX_DESC_TXAGC_B(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+24, 5, 5)
+	SHIFT_AND_MASK_LE(__pdesc+24, 5, 5)
 #define GET_TX_DESC_USE_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 10, 1)
+	SHIFT_AND_MASK_LE(__pdesc+24, 10, 1)
 #define GET_TX_DESC_MAX_AGG_NUM(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 11, 5)
+	SHIFT_AND_MASK_LE(__pdesc+24, 11, 5)
 #define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 16, 4)
 #define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 20, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 20, 4)
 #define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 24, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 24, 4)
 #define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 28, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 28, 4)
 
 #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val)
 #define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val)
 #define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val)
 #define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val)
 #define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val)
 
 #define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
+	SHIFT_AND_MASK_LE(__pdesc+28, 0, 16)
 #define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 16, 4)
 #define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 20, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 20, 4)
 #define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 24, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 24, 4)
 #define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 28, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 28, 4)
 
 #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val)
 #define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
-	SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val)
 
 #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+32, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+32, 0, 32)
 #define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc)	\
-	LE_BITS_TO_4BYTE(__pdesc+36, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+36, 0, 32)
 
 #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val)
 #define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
-	SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val)
 
 #define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+40, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+40, 0, 32)
 #define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc)	\
-	LE_BITS_TO_4BYTE(__pdesc+44, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+44, 0, 32)
 
 #define GET_RX_DESC_PKT_LEN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 0, 14)
+	SHIFT_AND_MASK_LE(__pdesc, 0, 14)
 #define GET_RX_DESC_CRC32(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 14, 1)
 #define GET_RX_DESC_ICV(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 15, 1)
 #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc, 16, 4)
 #define GET_RX_DESC_SECURITY(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 20, 3)
+	SHIFT_AND_MASK_LE(__pdesc, 20, 3)
 #define GET_RX_DESC_QOS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 23, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 23, 1)
 #define GET_RX_DESC_SHIFT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 24, 2)
+	SHIFT_AND_MASK_LE(__pdesc, 24, 2)
 #define GET_RX_DESC_PHYST(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 26, 1)
 #define GET_RX_DESC_SWDEC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 27, 1)
 #define GET_RX_DESC_LS(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 28, 1)
 #define GET_RX_DESC_FS(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 29, 1)
 #define GET_RX_DESC_EOR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 30, 1)
 #define GET_RX_DESC_OWN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 31, 1)
 
 #define SET_RX_DESC_PKT_LEN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val)
 #define SET_RX_DESC_EOR(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
 #define SET_RX_DESC_OWN(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
 
 #define GET_RX_DESC_MACID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
 #define GET_RX_DESC_TID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 5, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 5, 4)
 #define GET_RX_DESC_HWRSVD(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 9, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 9, 5)
 #define GET_RX_DESC_PAGGR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
 #define GET_RX_DESC_FAGGR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
 #define GET_RX_DESC_A1_FIT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
 #define GET_RX_DESC_A2_FIT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 20, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 20, 4)
 #define GET_RX_DESC_PAM(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 24, 1)
 #define GET_RX_DESC_PWR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 25, 1)
 #define GET_RX_DESC_MD(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 26, 1)
 #define GET_RX_DESC_MF(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 27, 1)
 #define GET_RX_DESC_TYPE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 28, 2)
+	SHIFT_AND_MASK_LE(__pdesc+4, 28, 2)
 #define GET_RX_DESC_MC(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 30, 1)
 #define GET_RX_DESC_BC(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 31, 1)
 #define GET_RX_DESC_SEQ(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 0, 12)
+	SHIFT_AND_MASK_LE(__pdesc+8, 0, 12)
 #define GET_RX_DESC_FRAG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
+	SHIFT_AND_MASK_LE(__pdesc+8, 12, 4)
 #define GET_RX_DESC_NEXT_PKT_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+8, 16, 14)
+	SHIFT_AND_MASK_LE(__pdesc+8, 16, 14)
 #define GET_RX_DESC_NEXT_IND(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 30, 1)
 #define GET_RX_DESC_RSVD(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 31, 1)
 
 #define GET_RX_DESC_RXMCS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 0, 6)
+	SHIFT_AND_MASK_LE(__pdesc+12, 0, 6)
 #define GET_RX_DESC_RXHT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 6, 1)
 #define GET_RX_DESC_SPLCP(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 8, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 8, 1)
 #define GET_RX_DESC_BW(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+12, 9, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 9, 1)
 #define GET_RX_DESC_HTC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 10, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 10, 1)
 #define GET_RX_DESC_HWPC_ERR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 14, 1)
 #define GET_RX_DESC_HWPC_IND(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 15, 1)
 #define GET_RX_DESC_IV0(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 16, 16)
+	SHIFT_AND_MASK_LE(__pdesc+12, 16, 16)
 
 #define GET_RX_DESC_IV1(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+16, 0, 32)
 #define GET_RX_DESC_TSFL(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+20, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+20, 0, 32)
 
 #define GET_RX_DESC_BUFF_ADDR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+24, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+24, 0, 32)
 #define GET_RX_DESC_BUFF_ADDR64(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+28, 0, 32)
 
 #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val)
 #define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) 	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val)
 
 #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)	\
 do {							\
@@ -711,4 +735,6 @@ void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue);
 void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 			     bool b_firstseg, bool b_lastseg,
 			     struct sk_buff *skb);
+bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
+
 #endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile b/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile
new file mode 100644
index 0000000..ad2de6b
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile
@@ -0,0 +1,14 @@
+rtl8192cu-objs :=		\
+		dm.o		\
+		hw.o		\
+		led.o		\
+		mac.o		\
+		phy.o		\
+		rf.o		\
+		sw.o		\
+		table.o		\
+		trx.o
+
+obj-$(CONFIG_RTL8192CU) += rtl8192cu.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/def.h b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
new file mode 100644
index 0000000..c54940e
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/def.h"
+
+/*-------------------------------------------------------------------------
+ *	Chip specific
+ *-------------------------------------------------------------------------*/
+#define CHIP_8723			BIT(2) /* RTL8723 With BT feature */
+#define CHIP_8723_DRV_REV		BIT(3) /* RTL8723 Driver Revised */
+#define NORMAL_CHIP			BIT(4)
+#define CHIP_VENDOR_UMC			BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT		BIT(6)
+
+#define IS_NORMAL_CHIP(version)		\
+	(((version) & NORMAL_CHIP) ? true : false)
+
+#define IS_8723_SERIES(version)		\
+	(((version) & CHIP_8723) ? true : false)
+
+#define IS_92C_1T2R(version)		\
+	(((version) & CHIP_92C) && ((version) & CHIP_92C_1T2R))
+
+#define IS_VENDOR_UMC(version)		\
+	(((version) & CHIP_VENDOR_UMC) ? true : false)
+
+#define IS_VENDOR_UMC_A_CUT(version)	\
+	(((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6) | BIT(7))) ? \
+	false : true) : false)
+
+#define IS_VENDOR_8723_A_CUT(version)	\
+	(((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6))) ? \
+	false : true) : false)
+
+#define CHIP_BONDING_92C_1T2R	0x1
+#define CHIP_BONDING_IDENTIFIER(_value)	(((_value) >> 22) & 0x3)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
new file mode 100644
index 0000000..f311bae
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+
+void rtl92cu_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 undecorated_smoothed_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_undecoratedsmoothed_pwdb == 0)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 ("Not connected to any\n"));
+
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+
+		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+
+	if (mac->link_state >= MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			undecorated_smoothed_pwdb =
+			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("AP Client PWDB = 0x%lx\n",
+				  undecorated_smoothed_pwdb));
+		} else {
+			undecorated_smoothed_pwdb =
+			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("STA Default Port PWDB = 0x%lx\n",
+				  undecorated_smoothed_pwdb));
+		}
+	} else {
+		undecorated_smoothed_pwdb =
+		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("AP Ext Port PWDB = 0x%lx\n",
+			  undecorated_smoothed_pwdb));
+	}
+
+	if (undecorated_smoothed_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 ((undecorated_smoothed_pwdb <
+		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undecorated_smoothed_pwdb >=
+		    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"));
+	} else if (undecorated_smoothed_pwdb <
+		   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("TXHIGHPWRLEVEL_NORMAL\n"));
+	}
+
+	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("PHY_SetTxPowerLevel8192S() Channel = %d\n",
+			  rtlphy->current_channel));
+		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+	}
+
+	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h
new file mode 100644
index 0000000..7f966c6
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/dm.h"
+
+void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
new file mode 100644
index 0000000..9444e76
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -0,0 +1,2504 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * 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 "../cam.h"
+#include "../ps.h"
+#include "../usb.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "mac.h"
+#include "dm.h"
+#include "hw.h"
+#include "trx.h"
+#include "led.h"
+#include "table.h"
+
+static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
+
+	rtlphy->hwparam_tables[MAC_REG].length = RTL8192CUMAC_2T_ARRAYLENGTH;
+	rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY;
+	if (IS_HIGHT_PA(rtlefuse->board_type)) {
+		rtlphy->hwparam_tables[PHY_REG_PG].length =
+			RTL8192CUPHY_REG_Array_PG_HPLength;
+		rtlphy->hwparam_tables[PHY_REG_PG].pdata =
+			RTL8192CUPHY_REG_Array_PG_HP;
+	} else {
+		rtlphy->hwparam_tables[PHY_REG_PG].length =
+			RTL8192CUPHY_REG_ARRAY_PGLENGTH;
+		rtlphy->hwparam_tables[PHY_REG_PG].pdata =
+			RTL8192CUPHY_REG_ARRAY_PG;
+	}
+	/* 2T */
+	rtlphy->hwparam_tables[PHY_REG_2T].length =
+			RTL8192CUPHY_REG_2TARRAY_LENGTH;
+	rtlphy->hwparam_tables[PHY_REG_2T].pdata =
+			RTL8192CUPHY_REG_2TARRAY;
+	rtlphy->hwparam_tables[RADIOA_2T].length =
+			RTL8192CURADIOA_2TARRAYLENGTH;
+	rtlphy->hwparam_tables[RADIOA_2T].pdata =
+			RTL8192CURADIOA_2TARRAY;
+	rtlphy->hwparam_tables[RADIOB_2T].length =
+			RTL8192CURADIOB_2TARRAYLENGTH;
+	rtlphy->hwparam_tables[RADIOB_2T].pdata =
+			RTL8192CU_RADIOB_2TARRAY;
+	rtlphy->hwparam_tables[AGCTAB_2T].length =
+			RTL8192CUAGCTAB_2TARRAYLENGTH;
+	rtlphy->hwparam_tables[AGCTAB_2T].pdata =
+			RTL8192CUAGCTAB_2TARRAY;
+	/* 1T */
+	if (IS_HIGHT_PA(rtlefuse->board_type)) {
+		rtlphy->hwparam_tables[PHY_REG_1T].length =
+			RTL8192CUPHY_REG_1T_HPArrayLength;
+		rtlphy->hwparam_tables[PHY_REG_1T].pdata =
+			RTL8192CUPHY_REG_1T_HPArray;
+		rtlphy->hwparam_tables[RADIOA_1T].length =
+			RTL8192CURadioA_1T_HPArrayLength;
+		rtlphy->hwparam_tables[RADIOA_1T].pdata =
+			RTL8192CURadioA_1T_HPArray;
+		rtlphy->hwparam_tables[RADIOB_1T].length =
+			RTL8192CURADIOB_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[RADIOB_1T].pdata =
+			RTL8192CU_RADIOB_1TARRAY;
+		rtlphy->hwparam_tables[AGCTAB_1T].length =
+			RTL8192CUAGCTAB_1T_HPArrayLength;
+		rtlphy->hwparam_tables[AGCTAB_1T].pdata =
+			Rtl8192CUAGCTAB_1T_HPArray;
+	} else {
+		rtlphy->hwparam_tables[PHY_REG_1T].length =
+			 RTL8192CUPHY_REG_1TARRAY_LENGTH;
+		rtlphy->hwparam_tables[PHY_REG_1T].pdata =
+			RTL8192CUPHY_REG_1TARRAY;
+		rtlphy->hwparam_tables[RADIOA_1T].length =
+			RTL8192CURADIOA_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[RADIOA_1T].pdata =
+			RTL8192CU_RADIOA_1TARRAY;
+		rtlphy->hwparam_tables[RADIOB_1T].length =
+			RTL8192CURADIOB_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[RADIOB_1T].pdata =
+			RTL8192CU_RADIOB_1TARRAY;
+		rtlphy->hwparam_tables[AGCTAB_1T].length =
+			RTL8192CUAGCTAB_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[AGCTAB_1T].pdata =
+			RTL8192CUAGCTAB_1TARRAY;
+	}
+}
+
+static void _rtl92cu_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));
+	u8 rf_path, index, tempval;
+	u16 i;
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 3; i++) {
+			if (!autoload_fail) {
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_cck[rf_path][i] =
+				    hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i];
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] =
+				    hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 +
+					   i];
+			} else {
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_cck[rf_path][i] =
+				    EEPROM_DEFAULT_TXPOWERLEVEL;
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] =
+				    EEPROM_DEFAULT_TXPOWERLEVEL;
+			}
+		}
+	}
+	for (i = 0; i < 3; i++) {
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
+		else
+			tempval = EEPROM_DEFAULT_HT40_2SDIFF;
+		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] =
+		    (tempval & 0xf);
+		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] =
+		    ((tempval & 0xf0) >> 4);
+	}
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				("RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path,
+				 i, rtlefuse->
+				 eeprom_chnlarea_txpwr_cck[rf_path][i]));
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				("RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->
+				 eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]));
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				("RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->
+				 eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+				 [i]));
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = _rtl92c_get_chnl_group((u8) i);
+			rtlefuse->txpwrlevel_cck[rf_path][i] =
+			    rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index];
+			rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
+			    rtlefuse->
+			    eeprom_chnlarea_txpwr_ht40_1s[rf_path][index];
+			if ((rtlefuse->
+			     eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] -
+			     rtlefuse->
+			     eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index])
+			    > 0) {
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
+				    rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_1s[rf_path]
+				    [index] - rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+				    [index];
+			} else {
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
+			}
+		}
+		for (i = 0; i < 14; i++) {
+			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],
+				 rtlefuse->txpwrlevel_ht40_2s[rf_path][i]));
+		}
+	}
+	for (i = 0; i < 3; i++) {
+		if (!autoload_fail) {
+			rtlefuse->eeprom_pwrlimit_ht40[i] =
+			    hwinfo[EEPROM_TXPWR_GROUP + i];
+			rtlefuse->eeprom_pwrlimit_ht20[i] =
+			    hwinfo[EEPROM_TXPWR_GROUP + 3 + i];
+		} else {
+			rtlefuse->eeprom_pwrlimit_ht40[i] = 0;
+			rtlefuse->eeprom_pwrlimit_ht20[i] = 0;
+		}
+	}
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = _rtl92c_get_chnl_group((u8) i);
+			if (rf_path == RF90_PATH_A) {
+				rtlefuse->pwrgroup_ht20[rf_path][i] =
+				    (rtlefuse->eeprom_pwrlimit_ht20[index]
+				     & 0xf);
+				rtlefuse->pwrgroup_ht40[rf_path][i] =
+				    (rtlefuse->eeprom_pwrlimit_ht40[index]
+				     & 0xf);
+			} else if (rf_path == RF90_PATH_B) {
+				rtlefuse->pwrgroup_ht20[rf_path][i] =
+				    ((rtlefuse->eeprom_pwrlimit_ht20[index]
+				      & 0xf0) >> 4);
+				rtlefuse->pwrgroup_ht40[rf_path][i] =
+				    ((rtlefuse->eeprom_pwrlimit_ht40[index]
+				      & 0xf0) >> 4);
+			}
+			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,
+				("RF-%d pwrgroup_ht40[%d] = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->pwrgroup_ht40[rf_path][i]));
+		}
+	}
+	for (i = 0; i < 14; i++) {
+		index = _rtl92c_get_chnl_group((u8) i);
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index];
+		else
+			tempval = EEPROM_DEFAULT_HT20_DIFF;
+		rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF);
+		rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] =
+		    ((tempval >> 4) & 0xF);
+		if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3))
+			rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0;
+		if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3))
+			rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0;
+		index = _rtl92c_get_chnl_group((u8) i);
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index];
+		else
+			tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF);
+		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] =
+		    ((tempval >> 4) & 0xF);
+	}
+	rtlefuse->legacy_ht_txpowerdiff =
+	    rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
+	for (i = 0; i < 14; i++)
+		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,
+			("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,
+			("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,
+			("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,
+		("eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory));
+	if (!autoload_fail) {
+		rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
+		rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B];
+	} else {
+		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",
+		 rtlefuse->eeprom_tssi[RF90_PATH_A],
+		 rtlefuse->eeprom_tssi[RF90_PATH_B]));
+	if (!autoload_fail)
+		tempval = hwinfo[EEPROM_THERMAL_METER];
+	else
+		tempval = EEPROM_DEFAULT_THERMALMETER;
+	rtlefuse->eeprom_thermalmeter = (tempval & 0x1f);
+	if (rtlefuse->eeprom_thermalmeter < 0x06 ||
+	    rtlefuse->eeprom_thermalmeter > 0x1c)
+		rtlefuse->eeprom_thermalmeter = 0x12;
+	if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
+		rtlefuse->apk_thermalmeterignore = true;
+	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		("thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter));
+}
+
+static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 boardType;
+
+	if (IS_NORMAL_CHIP(rtlhal->version)) {
+		boardType = ((contents[EEPROM_RF_OPT1]) &
+			    BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/
+	} else {
+		boardType = contents[EEPROM_RF_OPT4];
+		boardType &= BOARD_TYPE_TEST_MASK;
+	}
+	rtlefuse->board_type = boardType;
+	if (IS_HIGHT_PA(rtlefuse->board_type))
+		rtlefuse->external_pa = 1;
+	printk(KERN_INFO "rtl8192cu: Board Type %x\n", rtlefuse->board_type);
+
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	/* Antenna Diversity setting. */
+	if (registry_par->antdiv_cfg == 2) /* 2: From Efuse */
+		rtl_efuse->antenna_cfg = (contents[EEPROM_RF_OPT1]&0x18)>>3;
+	else
+		rtl_efuse->antenna_cfg = registry_par->antdiv_cfg; /* 0:OFF, */
+
+	printk(KERN_INFO "rtl8192cu: Antenna Config %x\n",
+	       rtl_efuse->antenna_cfg);
+#endif
+}
+
+#ifdef CONFIG_BT_COEXIST
+static void _update_bt_param(_adapter *padapter)
+{
+	struct btcoexist_priv	 *pbtpriv = &(padapter->halpriv.bt_coexist);
+	struct registry_priv	*registry_par = &padapter->registrypriv;
+	if (2 != registry_par->bt_iso) {
+		/* 0:Low, 1:High, 2:From Efuse */
+		pbtpriv->BT_Ant_isolation = registry_par->bt_iso;
+	}
+	if (registry_par->bt_sco == 1) {
+		/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy,
+		 * 5.OtherBusy */
+		pbtpriv->BT_Service = BT_OtherAction;
+	} else if (registry_par->bt_sco == 2) {
+		pbtpriv->BT_Service = BT_SCO;
+	} else if (registry_par->bt_sco == 4) {
+		pbtpriv->BT_Service = BT_Busy;
+	} else if (registry_par->bt_sco == 5) {
+		pbtpriv->BT_Service = BT_OtherBusy;
+	} else {
+		pbtpriv->BT_Service = BT_Idle;
+	}
+	pbtpriv->BT_Ampdu = registry_par->bt_ampdu;
+	pbtpriv->bCOBT = _TRUE;
+	pbtpriv->BtEdcaUL = 0;
+	pbtpriv->BtEdcaDL = 0;
+	pbtpriv->BtRssiState = 0xff;
+	pbtpriv->bInitSet = _FALSE;
+	pbtpriv->bBTBusyTraffic = _FALSE;
+	pbtpriv->bBTTrafficModeSet = _FALSE;
+	pbtpriv->bBTNonTrafficModeSet = _FALSE;
+	pbtpriv->CurrentState = 0;
+	pbtpriv->PreviousState = 0;
+	printk(KERN_INFO "rtl8192cu: BT Coexistance = %s\n",
+	       (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
+	if (pbtpriv->BT_Coexist) {
+		if (pbtpriv->BT_Ant_Num == Ant_x2)
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "Ant_Num = Antx2\n");
+		else if (pbtpriv->BT_Ant_Num == Ant_x1)
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "Ant_Num = Antx1\n");
+		switch (pbtpriv->BT_CoexistType) {
+		case BT_2Wire:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_2Wire\n");
+			break;
+		case BT_ISSC_3Wire:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_ISSC_3Wire\n");
+			break;
+		case BT_Accel:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_Accel\n");
+			break;
+		case BT_CSR_BC4:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_CSR_BC4\n");
+			break;
+		case BT_CSR_BC8:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_CSR_BC8\n");
+			break;
+		case BT_RTL8756:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_RTL8756\n");
+			break;
+		default:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = Unknown\n");
+			break;
+		}
+		printk(KERN_INFO "rtl8192cu: BlueTooth BT_Ant_isolation = %d\n",
+		       pbtpriv->BT_Ant_isolation);
+		switch (pbtpriv->BT_Service) {
+		case BT_OtherAction:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_OtherAction\n");
+			break;
+		case BT_SCO:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_SCO\n");
+			break;
+		case BT_Busy:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_Busy\n");
+			break;
+		case BT_OtherBusy:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_OtherBusy\n");
+			break;
+		default:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_Idle\n");
+			break;
+		}
+		printk(KERN_INFO "rtl8192cu: BT_RadioSharedType = 0x%x\n",
+		       pbtpriv->BT_RadioSharedType);
+	}
+}
+
+#define GET_BT_COEXIST(priv) (&priv->bt_coexist)
+
+static void _rtl92cu_read_bluetooth_coexistInfo(struct ieee80211_hw *hw,
+						u8 *contents,
+						bool bautoloadfailed);
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(Adapter);
+	bool isNormal = IS_NORMAL_CHIP(pHalData->VersionID);
+	struct btcoexist_priv	 *pbtpriv = &pHalData->bt_coexist;
+	u8	rf_opt4;
+
+	_rtw_memset(pbtpriv, 0, sizeof(struct btcoexist_priv));
+	if (AutoloadFail) {
+		pbtpriv->BT_Coexist = _FALSE;
+		pbtpriv->BT_CoexistType = BT_2Wire;
+		pbtpriv->BT_Ant_Num = Ant_x2;
+		pbtpriv->BT_Ant_isolation = 0;
+		pbtpriv->BT_RadioSharedType = BT_Radio_Shared;
+		return;
+	}
+	if (isNormal) {
+		if (pHalData->BoardType == BOARD_USB_COMBO)
+			pbtpriv->BT_Coexist = _TRUE;
+		else
+			pbtpriv->BT_Coexist = ((PROMContent[EEPROM_RF_OPT3] &
+					      0x20) >> 5); /* bit[5] */
+		rf_opt4 = PROMContent[EEPROM_RF_OPT4];
+		pbtpriv->BT_CoexistType = ((rf_opt4&0xe)>>1); /* bit [3:1] */
+		pbtpriv->BT_Ant_Num = (rf_opt4&0x1); /* bit [0] */
+		pbtpriv->BT_Ant_isolation = ((rf_opt4&0x10)>>4); /* bit [4] */
+		pbtpriv->BT_RadioSharedType = ((rf_opt4&0x20)>>5); /* bit [5] */
+	} else {
+		pbtpriv->BT_Coexist = (PROMContent[EEPROM_RF_OPT4] >> 4) ?
+				       _TRUE : _FALSE;
+	}
+	_update_bt_param(Adapter);
+}
+#endif
+
+static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u16 i, usvalue;
+	u8 hwinfo[HWSET_MAX_SIZE] = {0};
+	u16 eeprom_id;
+
+	if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+		rtl_efuse_shadow_map_update(hw);
+		memcpy((void *)hwinfo,
+		       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+		       HWSET_MAX_SIZE);
+	} else if (rtlefuse->epromtype == EEPROM_93C46) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("RTL819X Not boot from eeprom, check it !!"));
+	}
+	RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"),
+		      hwinfo, HWSET_MAX_SIZE);
+	eeprom_id = *((u16 *)&hwinfo[0]);
+	if (eeprom_id != RTL8190_EEPROM_ID) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("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;
+	for (i = 0; i < 6; i += 2) {
+		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
+		*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+	}
+	printk(KERN_INFO "rtl8192cu: MAC address: %pM\n", rtlefuse->dev_addr);
+	_rtl92cu_read_txpower_info_from_hwpg(hw,
+					   rtlefuse->autoload_failflag, hwinfo);
+	rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
+	rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 (" VID = 0x%02x PID = 0x%02x\n",
+		 rtlefuse->eeprom_vid, rtlefuse->eeprom_did));
+	rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
+	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+	rtlefuse->txpwr_fromeprom = true;
+	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid));
+	if (rtlhal->oem_id == RT_CID_DEFAULT) {
+		switch (rtlefuse->eeprom_oemid) {
+		case EEPROM_CID_DEFAULT:
+			if (rtlefuse->eeprom_did == 0x8176) {
+				if ((rtlefuse->eeprom_svid == 0x103C &&
+				     rtlefuse->eeprom_smid == 0x1629))
+					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;
+		}
+	}
+	_rtl92cu_read_board_type(hw, hwinfo);
+#ifdef CONFIG_BT_COEXIST
+	_rtl92cu_read_bluetooth_coexistInfo(hw, hwinfo,
+					    rtlefuse->autoload_failflag);
+#endif
+}
+
+static void _rtl92cu_hal_customized_behavior(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	switch (rtlhal->oem_id) {
+	case RT_CID_819x_HP:
+		usb_priv->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 rtl92cu_read_eeprom_info(struct ieee80211_hw *hw)
+{
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_u1b;
+
+	if (!IS_NORMAL_CHIP(rtlhal->version))
+		return;
+	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+	rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ?
+			       EEPROM_93C46 : EEPROM_BOOT_EFUSE;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n",
+		 (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE"));
+	rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n",
+		 (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!"));
+	_rtl92cu_read_adapter_info(hw);
+	_rtl92cu_hal_customized_behavior(hw);
+	return;
+}
+
+static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int		status = 0;
+	u16		value16;
+	u8		value8;
+	/*  polling autoload done. */
+	u32	pollingCount = 0;
+
+	do {
+		if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+				 ("Autoload Done!\n"));
+			break;
+		}
+		if (pollingCount++ > 100) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+				 ("Failed to polling REG_APS_FSMCO[PFM_ALDN]"
+				 " done!\n"));
+			return -ENODEV;
+		}
+	} while (true);
+	/* 0. RSV_CTRL 0x1C[7:0] = 0 unlock ISO/CLK/Power control register */
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0);
+	/* Power on when re-enter from IPS/Radio off/card disable */
+	/* enable SPS into PWM mode */
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+	udelay(100);
+	value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL);
+	if (0 == (value8 & LDV12_EN)) {
+		value8 |= LDV12_EN;
+		rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 (" power-on :REG_LDOV12D_CTRL Reg0x21:0x%02x.\n",
+			 value8));
+		udelay(100);
+		value8 = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL);
+		value8 &= ~ISO_MD2PP;
+		rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, value8);
+	}
+	/*  auto enable WLAN */
+	pollingCount = 0;
+	value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO);
+	value16 |= APFM_ONMAC;
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, value16);
+	do {
+		if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) {
+			printk(KERN_INFO "rtl8192cu: MAC auto ON okay!\n");
+			break;
+		}
+		if (pollingCount++ > 100) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+				 ("Failed to polling REG_APS_FSMCO[APFM_ONMAC]"
+				 " done!\n"));
+			return -ENODEV;
+		}
+	} while (true);
+	/* Enable Radio ,GPIO ,and LED function */
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x0812);
+	/* release RF digital isolation */
+	value16 = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL);
+	value16 &= ~ISO_DIOR;
+	rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, value16);
+	/* Reconsider when to do this operation after asking HWSD. */
+	pollingCount = 0;
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, (rtl_read_byte(rtlpriv,
+						REG_APSD_CTRL) & ~BIT(6)));
+	do {
+		pollingCount++;
+	} while ((pollingCount < 200) &&
+		 (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7)));
+	/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
+	value16 = rtl_read_word(rtlpriv,  REG_CR);
+	value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN |
+		    PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | ENSEC);
+	rtl_write_word(rtlpriv, REG_CR, value16);
+	return status;
+}
+
+static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw,
+					      bool wmm_enable,
+					      u8 out_ep_num,
+					      u8 queue_sel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool isChipN = IS_NORMAL_CHIP(rtlhal->version);
+	u32 outEPNum = (u32)out_ep_num;
+	u32 numHQ = 0;
+	u32 numLQ = 0;
+	u32 numNQ = 0;
+	u32 numPubQ;
+	u32 value32;
+	u8 value8;
+	u32 txQPageNum, txQPageUnit, txQRemainPage;
+
+	if (!wmm_enable) {
+		numPubQ = (isChipN) ? CHIP_B_PAGE_NUM_PUBQ :
+			  CHIP_A_PAGE_NUM_PUBQ;
+		txQPageNum = TX_TOTAL_PAGE_NUMBER - numPubQ;
+
+		txQPageUnit = txQPageNum/outEPNum;
+		txQRemainPage = txQPageNum % outEPNum;
+		if (queue_sel & TX_SELE_HQ)
+			numHQ = txQPageUnit;
+		if (queue_sel & TX_SELE_LQ)
+			numLQ = txQPageUnit;
+		/* HIGH priority queue always present in the configuration of
+		 * 2 out-ep. Remainder pages have assigned to High queue */
+		if ((outEPNum > 1) && (txQRemainPage))
+			numHQ += txQRemainPage;
+		/* NOTE: This step done before writting REG_RQPN. */
+		if (isChipN) {
+			if (queue_sel & TX_SELE_NQ)
+				numNQ = txQPageUnit;
+			value8 = (u8)_NPQ(numNQ);
+			rtl_write_byte(rtlpriv,  REG_RQPN_NPQ, value8);
+		}
+	} else {
+		/* for WMM ,number of out-ep must more than or equal to 2! */
+		numPubQ = isChipN ? WMM_CHIP_B_PAGE_NUM_PUBQ :
+			  WMM_CHIP_A_PAGE_NUM_PUBQ;
+		if (queue_sel & TX_SELE_HQ) {
+			numHQ = isChipN ? WMM_CHIP_B_PAGE_NUM_HPQ :
+				WMM_CHIP_A_PAGE_NUM_HPQ;
+		}
+		if (queue_sel & TX_SELE_LQ) {
+			numLQ = isChipN ? WMM_CHIP_B_PAGE_NUM_LPQ :
+				WMM_CHIP_A_PAGE_NUM_LPQ;
+		}
+		/* NOTE: This step done before writting REG_RQPN. */
+		if (isChipN) {
+			if (queue_sel & TX_SELE_NQ)
+				numNQ = WMM_CHIP_B_PAGE_NUM_NPQ;
+			value8 = (u8)_NPQ(numNQ);
+			rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
+		}
+	}
+	/* TX DMA */
+	value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
+	rtl_write_dword(rtlpriv, REG_RQPN, value32);
+}
+
+static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8	txpktbuf_bndy;
+	u8	value8;
+
+	if (!wmm_enable)
+		txpktbuf_bndy = TX_PAGE_BOUNDARY;
+	else /* for WMM */
+		txpktbuf_bndy = (IS_NORMAL_CHIP(rtlhal->version))
+						? WMM_CHIP_B_TX_PAGE_BOUNDARY
+						: WMM_CHIP_A_TX_PAGE_BOUNDARY;
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TDECTRL+1, txpktbuf_bndy);
+	rtl_write_word(rtlpriv,  (REG_TRXFF_BNDY + 2), 0x27FF);
+	value8 = _PSRX(RX_PAGE_SIZE_REG_VALUE) | _PSTX(PBP_128);
+	rtl_write_byte(rtlpriv, REG_PBP, value8);
+}
+
+static void _rtl92c_init_chipN_reg_priority(struct ieee80211_hw *hw, u16 beQ,
+					    u16 bkQ, u16 viQ, u16 voQ,
+					    u16 mgtQ, u16 hiQ)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7);
+
+	value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
+		   _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
+		   _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
+	rtl_write_word(rtlpriv,  REG_TRXDMA_CTRL, value16);
+}
+
+static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
+						    bool wmm_enable,
+						    u8 queue_sel)
+{
+	u16 uninitialized_var(value);
+
+	switch (queue_sel) {
+	case TX_SELE_HQ:
+		value = QUEUE_HIGH;
+		break;
+	case TX_SELE_LQ:
+		value = QUEUE_LOW;
+		break;
+	case TX_SELE_NQ:
+		value = QUEUE_NORMAL;
+		break;
+	default:
+		WARN_ON(1); /* Shall not reach here! */
+		break;
+	}
+	_rtl92c_init_chipN_reg_priority(hw, value, value, value, value,
+					value, value);
+	printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+}
+
+static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
+								bool wmm_enable,
+								u8 queue_sel)
+{
+	u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+	u16 uninitialized_var(valueHi);
+	u16 uninitialized_var(valueLow);
+
+	switch (queue_sel) {
+	case (TX_SELE_HQ | TX_SELE_LQ):
+		valueHi = QUEUE_HIGH;
+		valueLow = QUEUE_LOW;
+		break;
+	case (TX_SELE_NQ | TX_SELE_LQ):
+		valueHi = QUEUE_NORMAL;
+		valueLow = QUEUE_LOW;
+		break;
+	case (TX_SELE_HQ | TX_SELE_NQ):
+		valueHi = QUEUE_HIGH;
+		valueLow = QUEUE_NORMAL;
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+	if (!wmm_enable) {
+		beQ = valueLow;
+		bkQ = valueLow;
+		viQ = valueHi;
+		voQ = valueHi;
+		mgtQ = valueHi;
+		hiQ = valueHi;
+	} else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */
+		beQ = valueHi;
+		bkQ = valueLow;
+		viQ = valueLow;
+		voQ = valueHi;
+		mgtQ = valueHi;
+		hiQ = valueHi;
+	}
+	_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+	printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+}
+
+static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw,
+						      bool wmm_enable,
+						      u8 queue_sel)
+{
+	u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!wmm_enable) { /* typical setting */
+		beQ	= QUEUE_LOW;
+		bkQ	= QUEUE_LOW;
+		viQ	= QUEUE_NORMAL;
+		voQ	= QUEUE_HIGH;
+		mgtQ	= QUEUE_HIGH;
+		hiQ	= QUEUE_HIGH;
+	} else { /* for WMM */
+		beQ	= QUEUE_LOW;
+		bkQ	= QUEUE_NORMAL;
+		viQ	= QUEUE_NORMAL;
+		voQ	= QUEUE_HIGH;
+		mgtQ	= QUEUE_HIGH;
+		hiQ	= QUEUE_HIGH;
+	}
+	_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+		 ("Tx queue select :0x%02x..\n", queue_sel));
+}
+
+static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw,
+					       bool wmm_enable,
+					       u8 out_ep_num,
+					       u8 queue_sel)
+{
+	switch (out_ep_num) {
+	case 1:
+		_rtl92cu_init_chipN_one_out_ep_priority(hw, wmm_enable,
+							queue_sel);
+		break;
+	case 2:
+		_rtl92cu_init_chipN_two_out_ep_priority(hw, wmm_enable,
+							queue_sel);
+		break;
+	case 3:
+		_rtl92cu_init_chipN_three_out_ep_priority(hw, wmm_enable,
+							  queue_sel);
+		break;
+	default:
+		WARN_ON(1); /* Shall not reach here! */
+		break;
+	}
+}
+
+static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw,
+					       bool wmm_enable,
+					       u8 out_ep_num,
+					       u8 queue_sel)
+{
+	u8	hq_sele;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	switch (out_ep_num) {
+	case 2:	/* (TX_SELE_HQ|TX_SELE_LQ) */
+		if (!wmm_enable) /* typical setting */
+			hq_sele =  HQSEL_VOQ | HQSEL_VIQ | HQSEL_MGTQ |
+				   HQSEL_HIQ;
+		else	/* for WMM */
+			hq_sele = HQSEL_VOQ | HQSEL_BEQ | HQSEL_MGTQ |
+				  HQSEL_HIQ;
+		break;
+	case 1:
+		if (TX_SELE_LQ == queue_sel) {
+			/* map all endpoint to Low queue */
+			hq_sele = 0;
+		} else if (TX_SELE_HQ == queue_sel) {
+			/* map all endpoint to High queue */
+			hq_sele =  HQSEL_VOQ | HQSEL_VIQ | HQSEL_BEQ |
+				   HQSEL_BKQ | HQSEL_MGTQ | HQSEL_HIQ;
+		}
+		break;
+	default:
+		WARN_ON(1); /* Shall not reach here! */
+		break;
+	}
+	rtl_write_byte(rtlpriv, (REG_TRXDMA_CTRL+1), hq_sele);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+		 ("Tx queue select :0x%02x..\n", hq_sele));
+}
+
+static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw,
+						bool wmm_enable,
+						u8 out_ep_num,
+						u8 queue_sel)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		_rtl92cu_init_chipN_queue_priority(hw, wmm_enable, out_ep_num,
+						   queue_sel);
+	else
+		_rtl92cu_init_chipT_queue_priority(hw, wmm_enable, out_ep_num,
+						   queue_sel);
+}
+
+static void _rtl92cu_init_usb_aggregation(struct ieee80211_hw *hw)
+{
+}
+
+static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw)
+{
+	u16			value16;
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APP_FCS |
+		      RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL |
+		      RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32);
+	rtl_write_dword(rtlpriv, REG_RCR, mac->rx_conf);
+	/* Accept all multicast address */
+	rtl_write_dword(rtlpriv,  REG_MAR, 0xFFFFFFFF);
+	rtl_write_dword(rtlpriv,  REG_MAR + 4, 0xFFFFFFFF);
+	/* Accept all management frames */
+	value16 = 0xFFFF;
+	rtl92c_set_mgt_filter(hw, value16);
+	/* Reject all control frame - default value is 0 */
+	rtl92c_set_ctrl_filter(hw, 0x0);
+	/* Accept all data frames */
+	value16 = 0xFFFF;
+	rtl92c_set_data_filter(hw, value16);
+}
+
+static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+	int err = 0;
+	u32	boundary = 0;
+	u8 wmm_enable = false; /* TODO */
+	u8 out_ep_nums = rtlusb->out_ep_nums;
+	u8 queue_sel = rtlusb->out_queue_sel;
+	err = _rtl92cu_init_power_on(hw);
+
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			("Failed to init power on!\n"));
+		return err;
+	}
+	if (!wmm_enable) {
+		boundary = TX_PAGE_BOUNDARY;
+	} else { /* for WMM */
+		boundary = (IS_NORMAL_CHIP(rtlhal->version))
+					? WMM_CHIP_B_TX_PAGE_BOUNDARY
+					: WMM_CHIP_A_TX_PAGE_BOUNDARY;
+	}
+	if (false == rtl92c_init_llt_table(hw, boundary)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			("Failed to init LLT Table!\n"));
+		return -EINVAL;
+	}
+	_rtl92cu_init_queue_reserved_page(hw, wmm_enable, out_ep_nums,
+					  queue_sel);
+	_rtl92c_init_trx_buffer(hw, wmm_enable);
+	_rtl92cu_init_queue_priority(hw, wmm_enable, out_ep_nums,
+				     queue_sel);
+	/* Get Rx PHY status in order to report RSSI and others. */
+	rtl92c_init_driver_info_size(hw, RTL92C_DRIVER_INFO_SIZE);
+	rtl92c_init_interrupt(hw);
+	rtl92c_init_network_type(hw);
+	_rtl92cu_init_wmac_setting(hw);
+	rtl92c_init_adaptive_ctrl(hw);
+	rtl92c_init_edca(hw);
+	rtl92c_init_rate_fallback(hw);
+	rtl92c_init_retry_function(hw);
+	_rtl92cu_init_usb_aggregation(hw);
+	rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20);
+	rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version));
+	rtl92c_init_beacon_parameters(hw, rtlhal->version);
+	rtl92c_init_ampdu_aggregation(hw);
+	rtl92c_init_beacon_max_error(hw, true);
+	return err;
+}
+
+void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 sec_reg_value = 0x0;
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+		  rtlpriv->sec.pairwise_enc_algorithm,
+		  rtlpriv->sec.group_enc_algorithm));
+	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+			 ("not open sw 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;
+	}
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+	rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+		 ("The SECR-value %x\n", sec_reg_value));
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+static void _rtl92cu_hw_configure(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	/* To Fix MAC loopback mode fail. */
+	rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
+	rtl_write_byte(rtlpriv, 0x15, 0xe9);
+	/* HW SEQ CTRL */
+	/* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
+	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+	/* fixed USB interface interference issue */
+	rtl_write_byte(rtlpriv, 0xfe40, 0xe0);
+	rtl_write_byte(rtlpriv, 0xfe41, 0x8d);
+	rtl_write_byte(rtlpriv, 0xfe42, 0x80);
+	rtlusb->reg_bcn_ctrl_val = 0x18;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val);
+}
+
+static void _InitPABias(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 pa_setting;
+
+	/* FIXED PA current issue */
+	pa_setting = efuse_read_1byte(hw, 0x1FA);
+	if (!(pa_setting & BIT(0))) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x0F406);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x4F406);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x8F406);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0xCF406);
+	}
+	if (!(pa_setting & BIT(1)) && IS_NORMAL_CHIP(rtlhal->version) &&
+	    IS_92C_SERIAL(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x0F406);
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x4F406);
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x8F406);
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0xCF406);
+	}
+	if (!(pa_setting & BIT(4))) {
+		pa_setting = rtl_read_byte(rtlpriv, 0x16);
+		pa_setting &= 0x0F;
+		rtl_write_byte(rtlpriv, 0x16, pa_setting | 0x90);
+	}
+}
+
+static void _InitAntenna_Selection(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (pHalData->AntDivCfg == 0)
+		return;
+
+	if (rtlphy->rf_type == RF_1T1R) {
+		rtl_write_dword(rtlpriv, REG_LEDCFG0,
+				rtl_read_dword(rtlpriv,
+				REG_LEDCFG0)|BIT(23));
+		rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+		if (rtl_get_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300) ==
+		    Antenna_A)
+			pHalData->CurAntenna = Antenna_A;
+		else
+			pHalData->CurAntenna = Antenna_B;
+	}
+#endif
+}
+
+static void _dump_registers(struct ieee80211_hw *hw)
+{
+}
+
+static void _update_mac_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	mac->rx_conf = rtl_read_dword(rtlpriv, REG_RCR);
+	mac->rx_mgt_filter = rtl_read_word(rtlpriv, REG_RXFLTMAP0);
+	mac->rx_ctrl_filter = rtl_read_word(rtlpriv, REG_RXFLTMAP1);
+	mac->rx_data_filter = rtl_read_word(rtlpriv, REG_RXFLTMAP2);
+}
+
+int rtl92cu_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));
+	int err = 0;
+	static bool iqk_initialized;
+
+	rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU;
+	err = _rtl92cu_init_mac(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("init mac failed!\n"));
+		return err;
+	}
+	err = rtl92c_download_fw(hw);
+	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;
+	}
+	rtlhal->last_hmeboxnum = 0; /* h2c */
+	_rtl92cu_phy_param_tab_init(hw);
+	rtl92cu_phy_mac_config(hw);
+	rtl92cu_phy_bb_config(hw);
+	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+	rtl92c_phy_rf_config(hw);
+	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+	    !IS_92C_SERIAL(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+	}
+	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtl92cu_bb_block_on(hw);
+	rtl_cam_reset_all_entry(hw);
+	rtl92cu_enable_hw_security_config(hw);
+	ppsc->rfpwr_state = ERFON;
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+	if (ppsc->rfpwr_state == ERFON) {
+		rtl92c_phy_set_rfpath_switch(hw, 1);
+		if (iqk_initialized) {
+			rtl92c_phy_iq_calibrate(hw, false);
+		} else {
+			rtl92c_phy_iq_calibrate(hw, false);
+			iqk_initialized = true;
+		}
+		rtl92c_dm_check_txpower_tracking(hw);
+		rtl92c_phy_lc_calibrate(hw);
+	}
+	_rtl92cu_hw_configure(hw);
+	_InitPABias(hw);
+	_InitAntenna_Selection(hw);
+	_update_mac_setting(hw);
+	rtl92c_dm_init(hw);
+	_dump_registers(hw);
+	return err;
+}
+
+static void _DisableRFAFEAndResetBB(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+/**************************************
+a.	TXPAUSE 0x522[7:0] = 0xFF	Pause MAC TX queue
+b.	RF path 0 offset 0x00 = 0x00	disable RF
+c.	APSD_CTRL 0x600[7:0] = 0x40
+d.	SYS_FUNC_EN 0x02[7:0] = 0x16	reset BB state machine
+e.	SYS_FUNC_EN 0x02[7:0] = 0x14	reset BB state machine
+***************************************/
+	u8 eRFPath = 0, value8 = 0;
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_rfreg(hw, (enum radio_path)eRFPath, 0x0, MASKBYTE0, 0x0);
+
+	value8 |= APSDOFF;
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, value8); /*0x40*/
+	value8 = 0;
+	value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8);/*0x16*/
+	value8 &= (~FEN_BB_GLB_RSTn);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8); /*0x14*/
+}
+
+static void  _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlhal->fw_version <=  0x20) {
+		/*****************************
+		f. MCUFWDL 0x80[7:0]=0		reset MCU ready status
+		g. SYS_FUNC_EN 0x02[10]= 0	reset MCU reg, (8051 reset)
+		h. SYS_FUNC_EN 0x02[15-12]= 5	reset MAC reg, DCORE
+		i. SYS_FUNC_EN 0x02[10]= 1	enable MCU reg, (8051 enable)
+		******************************/
+		u16 valu16 = 0;
+
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+		valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+		rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 &
+			       (~FEN_CPUEN))); /* reset MCU ,8051 */
+		valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN)&0x0FFF;
+		rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 |
+			      (FEN_HWPDN|FEN_ELDR))); /* reset MAC */
+		valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+		rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 |
+			       FEN_CPUEN)); /* enable MCU ,8051 */
+	} else {
+		u8 retry_cnts = 0;
+
+		/* IF fw in RAM code, do reset */
+		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) {
+			/* reset MCU ready status */
+			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+			if (rtlhal->fw_ready) {
+				/* 8051 reset by self */
+				rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
+				while ((retry_cnts++ < 100) &&
+				       (FEN_CPUEN & rtl_read_word(rtlpriv,
+				       REG_SYS_FUNC_EN))) {
+					udelay(50);
+				}
+				if (retry_cnts >= 100) {
+					RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+						("#####=> 8051 reset failed!.."
+						".......................\n"););
+					/* if 8051 reset fail, reset MAC. */
+					rtl_write_byte(rtlpriv,
+						       REG_SYS_FUNC_EN + 1,
+						       0x50);
+					udelay(100);
+				}
+			}
+		}
+		/* Reset MAC and Enable 8051 */
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x54);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+	}
+	if (bWithoutHWSM) {
+		/*****************************
+		  Without HW auto state machine
+		g.SYS_CLKR 0x08[15:0] = 0x30A3		disable MAC clock
+		h.AFE_PLL_CTRL 0x28[7:0] = 0x80		disable AFE PLL
+		i.AFE_XTAL_CTRL 0x24[15:0] = 0x880F	gated AFE DIG_CLOCK
+		j.SYS_ISu_CTRL 0x00[7:0] = 0xF9		isolated digital to PON
+		******************************/
+		rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3);
+		rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
+		rtl_write_word(rtlpriv, REG_AFE_XTAL_CTRL, 0x880F);
+		rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xF9);
+	}
+}
+
+static void _ResetDigitalProcedure2(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+/*****************************
+k. SYS_FUNC_EN 0x03[7:0] = 0x44		disable ELDR runction
+l. SYS_CLKR 0x08[15:0] = 0x3083		disable ELDR clock
+m. SYS_ISO_CTRL 0x01[7:0] = 0x83	isolated ELDR to PON
+******************************/
+	rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3);
+	rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, 0x82);
+}
+
+static void _DisableGPIO(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+/***************************************
+j. GPIO_PIN_CTRL 0x44[31:0]=0x000
+k. Value = GPIO_PIN_CTRL[7:0]
+l.  GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write ext PIN level
+m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
+n. LEDCFG 0x4C[15:0] = 0x8080
+***************************************/
+	u8	value8;
+	u16	value16;
+	u32	value32;
+
+	/* 1. Disable GPIO[7:0] */
+	rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, 0x0000);
+	value32 = rtl_read_dword(rtlpriv, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
+	value8 = (u8) (value32&0x000000FF);
+	value32 |= ((value8<<8) | 0x00FF0000);
+	rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, value32);
+	/* 2. Disable GPIO[10:8] */
+	rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+3, 0x00);
+	value16 = rtl_read_word(rtlpriv, REG_GPIO_MUXCFG+2) & 0xFF0F;
+	value8 = (u8) (value16&0x000F);
+	value16 |= ((value8<<4) | 0x0780);
+	rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, value16);
+	/* 3. Disable LED0 & 1 */
+	rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
+}
+
+static void _DisableAnalog(struct ieee80211_hw *hw, bool bWithoutHWSM)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u16 value16 = 0;
+	u8 value8 = 0;
+
+	if (bWithoutHWSM) {
+		/*****************************
+		n. LDOA15_CTRL 0x20[7:0] = 0x04	 disable A15 power
+		o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
+		r. When driver call disable, the ASIC will turn off remaining
+		   clock automatically
+		******************************/
+		rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04);
+		value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL);
+		value8 &= (~LDV12_EN);
+		rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8);
+	}
+
+/*****************************
+h. SPS0_CTRL 0x11[7:0] = 0x23		enter PFM mode
+i. APS_FSMCO 0x04[15:0] = 0x4802	set USB suspend
+******************************/
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+	value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, (u16)value16);
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E);
+}
+
+static void _CardDisableHWSM(struct ieee80211_hw *hw)
+{
+	/* ==== RF Off Sequence ==== */
+	_DisableRFAFEAndResetBB(hw);
+	/* ==== Reset digital sequence   ====== */
+	_ResetDigitalProcedure1(hw, false);
+	/*  ==== Pull GPIO PIN to balance level and LED control ====== */
+	_DisableGPIO(hw);
+	/* ==== Disable analog sequence === */
+	_DisableAnalog(hw, false);
+}
+
+static void _CardDisableWithoutHWSM(struct ieee80211_hw *hw)
+{
+	/*==== RF Off Sequence ==== */
+	_DisableRFAFEAndResetBB(hw);
+	/*  ==== Reset digital sequence   ====== */
+	_ResetDigitalProcedure1(hw, true);
+	/*  ==== Pull GPIO PIN to balance level and LED control ====== */
+	_DisableGPIO(hw);
+	/*  ==== Reset digital sequence   ====== */
+	_ResetDigitalProcedure2(hw);
+	/*  ==== Disable analog sequence === */
+	_DisableAnalog(hw, true);
+}
+
+static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+				      u8 set_bits, u8 clear_bits)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtlusb->reg_bcn_ctrl_val |= set_bits;
+	rtlusb->reg_bcn_ctrl_val &= ~clear_bits;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlusb->reg_bcn_ctrl_val);
+}
+
+static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 tmp1byte = 0;
+	if (IS_NORMAL_CHIP(rtlhal->version)) {
+		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);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE,
+			       rtl_read_byte(rtlpriv, REG_TXPAUSE) | BIT(6));
+	}
+}
+
+static void _rtl92cu_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 tmp1byte = 0;
+
+	if (IS_NORMAL_CHIP(rtlhal->version)) {
+		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);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE,
+			       rtl_read_byte(rtlpriv, REG_TXPAUSE) & (~BIT(6)));
+	}
+}
+
+static void _rtl92cu_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(1));
+	else
+		_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
+}
+
+static void _rtl92cu_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		_rtl92cu_set_bcn_ctrl_reg(hw, BIT(1), 0);
+	else
+		_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+}
+
+static int _rtl92cu_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;
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
+	if (type == NL80211_IFTYPE_UNSPECIFIED || type ==
+	    NL80211_IFTYPE_STATION) {
+		_rtl92cu_stop_tx_beacon(hw);
+		_rtl92cu_enable_bcn_sub_func(hw);
+	} else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) {
+		_rtl92cu_resume_tx_beacon(hw);
+		_rtl92cu_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;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Network type %d not support!\n", type));
+		goto error_out;
+	}
+	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;
+error_out:
+	return 1;
+}
+
+void rtl92cu_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_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	enum nl80211_iftype opmode;
+
+	mac->link_state = MAC80211_NOLINK;
+	opmode = NL80211_IFTYPE_UNSPECIFIED;
+	_rtl92cu_set_media_status(hw, opmode);
+	rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+	if (rtlusb->disableHWSM)
+		_CardDisableHWSM(hw);
+	else
+		_CardDisableWithoutHWSM(hw);
+}
+
+void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+	/* dummy routine needed for callback from rtl_op_configure_filter() */
+}
+
+/*========================================================================== */
+
+static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
+			      enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 filterout_non_associated_bssid = false;
+
+	switch (type) {
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_STATION:
+		filterout_non_associated_bssid = true;
+		break;
+	case NL80211_IFTYPE_UNSPECIFIED:
+	case NL80211_IFTYPE_AP:
+	default:
+		break;
+	}
+	if (filterout_non_associated_bssid == true) {
+		if (IS_NORMAL_CHIP(rtlhal->version)) {
+			switch (rtlphy->current_io_type) {
+			case IO_CMD_RESUME_DM_BY_SCAN:
+				reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						 HW_VAR_RCR, (u8 *)(&reg_rcr));
+				/* enable update TSF */
+				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
+				break;
+			case IO_CMD_PAUSE_DM_BY_SCAN:
+				reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						 HW_VAR_RCR, (u8 *)(&reg_rcr));
+				/* disable update TSF */
+				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+				break;
+			}
+		} else {
+			reg_rcr |= (RCR_CBSSID);
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+						      (u8 *)(&reg_rcr));
+			_rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
+		}
+	} else if (filterout_non_associated_bssid == false) {
+		if (IS_NORMAL_CHIP(rtlhal->version)) {
+			reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+						      (u8 *)(&reg_rcr));
+			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+		} else {
+			reg_rcr &= (~RCR_CBSSID);
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+						      (u8 *)(&reg_rcr));
+			_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
+		}
+	}
+}
+
+int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+	if (_rtl92cu_set_media_status(hw, type))
+		return -EOPNOTSUPP;
+	_rtl92cu_set_check_bssid(hw, type);
+	return 0;
+}
+
+static void _InitBeaconParameters(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010);
+
+	/* TODO: Remove these magic number */
+	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);
+	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
+	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
+	/* Change beacon AIFS to the largest number
+	 * beacause test chip does not contension before sending beacon. */
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
+	else
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
+}
+
+static void _beacon_function_enable(struct ieee80211_hw *hw, bool Enable,
+				    bool Linked)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4) | BIT(3) | BIT(1)), 0x00);
+	rtl_write_byte(rtlpriv, REG_RD_CTRL+1, 0x6F);
+}
+
+void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval, atim_window;
+	u32 value32;
+
+	bcn_interval = mac->beacon_interval;
+	atim_window = 2;	/*FIX MERGE */
+	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	_InitBeaconParameters(hw);
+	rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+	/*
+	 * Force beacon frame transmission even after receiving beacon frame
+	 * from other ad hoc STA
+	 *
+	 *
+	 * Reset TSF Timer to zero, added by Roger. 2008.06.24
+	 */
+	value32 = rtl_read_dword(rtlpriv, REG_TCR);
+	value32 &= ~TSFRST;
+	rtl_write_dword(rtlpriv, REG_TCR, value32);
+	value32 |= TSFRST;
+	rtl_write_dword(rtlpriv, REG_TCR, value32);
+	RT_TRACE(rtlpriv, COMP_INIT|COMP_BEACON, DBG_LOUD,
+		 ("SetBeaconRelatedRegisters8192CUsb(): Set TCR(%x)\n",
+		 value32));
+	/* TODO: Modify later (Find the right parameters)
+	 * NOTE: Fix test chip's bug (about contention windows's randomness) */
+	if ((mac->opmode == NL80211_IFTYPE_ADHOC) ||
+	    (mac->opmode == NL80211_IFTYPE_AP)) {
+		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50);
+		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50);
+	}
+	_beacon_function_enable(hw, true, true);
+}
+
+void rtl92cu_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));
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+}
+
+void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr)
+{
+}
+
+void rtl92cu_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_mac *mac = rtl_mac(rtl_priv(hw));
+
+	switch (variable) {
+	case HW_VAR_RCR:
+		*((u32 *)(val)) = mac->rx_conf;
+		break;
+	case HW_VAR_RF_STATE:
+		*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+		break;
+	case HW_VAR_FWLPS_RF_ON:{
+			enum rf_pwrstate rfState;
+			u32 val_rcr;
+
+			rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
+						      (u8 *)(&rfState));
+			if (rfState == ERFOFF) {
+				*((bool *) (val)) = true;
+			} else {
+				val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+				val_rcr &= 0x00070000;
+				if (val_rcr)
+					*((bool *) (val)) = false;
+				else
+					*((bool *) (val)) = true;
+			}
+			break;
+		}
+	case HW_VAR_FW_PSMODE_STATUS:
+		*((bool *) (val)) = ppsc->fw_current_inpsmode;
+		break;
+	case HW_VAR_CORRECT_TSF:{
+			u64 tsf;
+			u32 *ptsf_low = (u32 *)&tsf;
+			u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+			*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+			*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+			*((u64 *)(val)) = tsf;
+			break;
+		}
+	case HW_VAR_MGT_FILTER:
+		*((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0);
+		break;
+	case HW_VAR_CTRL_FILTER:
+		*((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1);
+		break;
+	case HW_VAR_DATA_FILTER:
+		*((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+}
+
+void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	enum wireless_mode wirelessmode = mac->mode;
+	u8 idx = 0;
+
+	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 &= 0x15f;
+			/* TODO */
+			/* if (mac->current_network.vender == HT_IOT_PEER_CISCO
+			 *     && ((rate_cfg & 0x150) == 0)) {
+			 *	  rate_cfg |= 0x010;
+			 * } */
+			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 >>= 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_CCK + 1, val[0]);
+			rtl_write_byte(rtlpriv, REG_SIFS_OFDM + 1, val[1]);
+			rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+			rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+			rtl_write_byte(rtlpriv, REG_R2T_SIFS+1, val[0]);
+			rtl_write_byte(rtlpriv, REG_T2T_SIFS+1, val[0]);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("HW_VAR_SIFS\n"));
+			break;
+		}
+	case HW_VAR_SLOT_TIME:{
+			u8 e_aci;
+			u8 QOS_MODE = 1;
+
+			rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("HW_VAR_SLOT_TIME %x\n", val[0]));
+			if (QOS_MODE) {
+				for (e_aci = 0; e_aci < AC_MAX; e_aci++)
+					rtlpriv->cfg->ops->set_hw_reg(hw,
+								HW_VAR_AC_PARAM,
+								(u8 *)(&e_aci));
+			} else {
+				u8 sifstime = 0;
+				u8	u1bAIFS;
+
+				if (IS_WIRELESS_MODE_A(wirelessmode) ||
+				    IS_WIRELESS_MODE_N_24G(wirelessmode) ||
+				    IS_WIRELESS_MODE_N_5G(wirelessmode))
+					sifstime = 16;
+				else
+					sifstime = 10;
+				u1bAIFS = sifstime + (2 *  val[0]);
+				rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM,
+					       u1bAIFS);
+				rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM,
+					       u1bAIFS);
+				rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM,
+					       u1bAIFS);
+				rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM,
+					       u1bAIFS);
+			}
+			break;
+		}
+	case HW_VAR_ACK_PREAMBLE:{
+			u8 reg_tmp;
+			u8 short_preamble = (bool) (*(u8 *) val);
+			reg_tmp = 0;
+			if (short_preamble)
+				reg_tmp |= 0x80;
+			rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+			break;
+		}
+	case HW_VAR_AMPDU_MIN_SPACE:{
+			u8 min_spacing_to_set;
+			u8 sec_min_space;
+
+			min_spacing_to_set = *((u8 *) val);
+			if (min_spacing_to_set <= 7) {
+				switch (rtlpriv->sec.pairwise_enc_algorithm) {
+				case NO_ENCRYPTION:
+				case AESCCMP_ENCRYPTION:
+					sec_min_space = 0;
+					break;
+				case WEP40_ENCRYPTION:
+				case WEP104_ENCRYPTION:
+				case TKIP_ENCRYPTION:
+					sec_min_space = 6;
+					break;
+				default:
+					sec_min_space = 7;
+					break;
+				}
+				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);
+			density_to_set &= 0x1f;
+			mac->min_space_cfg &= 0x07;
+			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_toset;
+			u8 *p_regtoset = NULL;
+			u8 index = 0;
+
+			p_regtoset = regtoset_normal;
+			factor_toset = *((u8 *) val);
+			if (factor_toset <= 3) {
+				factor_toset = (1 << (factor_toset + 2));
+				if (factor_toset > 0xf)
+					factor_toset = 0xf;
+				for (index = 0; index < 4; index++) {
+					if ((p_regtoset[index] & 0xf0) >
+					    (factor_toset << 4))
+						p_regtoset[index] =
+						     (p_regtoset[index] & 0x0f)
+						     | (factor_toset << 4);
+					if ((p_regtoset[index] & 0x0f) >
+					     factor_toset)
+						p_regtoset[index] =
+						     (p_regtoset[index] & 0xf0)
+						     | (factor_toset);
+					rtl_write_byte(rtlpriv,
+						       (REG_AGGLEN_LMT + index),
+						       p_regtoset[index]);
+				}
+				RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+					 ("Set HW_VAR_AMPDU_FACTOR: %#x\n",
+					  factor_toset));
+			}
+			break;
+		}
+	case HW_VAR_AC_PARAM:{
+			u8 e_aci = *((u8 *) val);
+			u32 u4b_ac_param;
+			u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min);
+			u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max);
+			u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op);
+
+			u4b_ac_param = (u32) mac->ac[e_aci].aifs;
+			u4b_ac_param |= (u32) ((cw_min & 0xF) <<
+					 AC_PARAM_ECW_MIN_OFFSET);
+			u4b_ac_param |= (u32) ((cw_max & 0xF) <<
+					 AC_PARAM_ECW_MAX_OFFSET);
+			u4b_ac_param |= (u32) tx_op << AC_PARAM_TXOP_OFFSET;
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("queue:%x, ac_param:%x\n", e_aci,
+				  u4b_ac_param));
+			switch (e_aci) {
+			case AC1_BK:
+				rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM,
+						u4b_ac_param);
+				break;
+			case AC0_BE:
+				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+						u4b_ac_param);
+				break;
+			case AC2_VI:
+				rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM,
+						u4b_ac_param);
+				break;
+			case AC3_VO:
+				rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM,
+						u4b_ac_param);
+				break;
+			default:
+				RT_ASSERT(false, ("SetHwReg8185(): invalid"
+					  " aci: %d !\n", e_aci));
+				break;
+			}
+			if (rtlusb->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 | ((rtlusb->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]);
+			mac->rx_conf = ((u32 *) (val))[0];
+			RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG,
+				 ("### Set RCR(0x%08x) ###\n", mac->rx_conf));
+			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);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_DMESG, ("Set HW_VAR_R"
+				 "ETRY_LIMIT(0x%08x)\n", retry_limit));
+			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:
+		rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val));
+		break;
+	case HW_VAR_WPA_CONFIG:
+		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+		break;
+	case HW_VAR_SET_RPWM:{
+			u8 rpwm_val = rtl_read_byte(rtlpriv, REG_USB_HRPWM);
+
+			if (rpwm_val & BIT(7))
+				rtl_write_byte(rtlpriv, REG_USB_HRPWM,
+					       (*(u8 *)val));
+			else
+				rtl_write_byte(rtlpriv, REG_USB_HRPWM,
+					       ((*(u8 *)val) | BIT(7)));
+			break;
+		}
+	case HW_VAR_H2C_FW_PWRMODE:{
+			u8 psmode = (*(u8 *) val);
+
+			if ((psmode != FW_PS_ACTIVE_MODE) &&
+			   (!IS_92C_SERIAL(rtlhal->version)))
+				rtl92c_dm_rf_saving(hw, true);
+			rtl92c_set_fw_pwrmode_cmd(hw, (*(u8 *) val));
+			break;
+		}
+	case HW_VAR_FW_PSMODE_STATUS:
+		ppsc->fw_current_inpsmode = *((bool *) val);
+		break;
+	case HW_VAR_H2C_FW_JOINBSSRPT:{
+			u8 mstatus = (*(u8 *) val);
+			u8 tmp_reg422;
+			bool recover = false;
+
+			if (mstatus == RT_MEDIA_CONNECT) {
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+							 HW_VAR_AID, NULL);
+				rtl_write_byte(rtlpriv, REG_CR + 1, 0x03);
+				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
+				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+				tmp_reg422 = rtl_read_byte(rtlpriv,
+							REG_FWHW_TXQ_CTRL + 2);
+				if (tmp_reg422 & BIT(6))
+					recover = true;
+				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+					       tmp_reg422 & (~BIT(6)));
+				rtl92c_set_fw_rsvdpagepkt(hw, 0);
+				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
+				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
+				if (recover)
+					rtl_write_byte(rtlpriv,
+						 REG_FWHW_TXQ_CTRL + 2,
+						tmp_reg422 | BIT(6));
+				rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+			}
+			rtl92c_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+			break;
+		}
+	case HW_VAR_AID:{
+			u16 u2btmp;
+
+			u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+			u2btmp &= 0xC000;
+			rtl_write_word(rtlpriv, REG_BCN_PSR_RPT,
+				       (u2btmp | mac->assoc_id));
+			break;
+		}
+	case HW_VAR_CORRECT_TSF:{
+			u8 btype_ibss = ((u8 *) (val))[0];
+
+			if (btype_ibss == true)
+				_rtl92cu_stop_tx_beacon(hw);
+			_rtl92cu_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));
+			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
+			if (btype_ibss == true)
+				_rtl92cu_resume_tx_beacon(hw);
+			break;
+		}
+	case HW_VAR_MGT_FILTER:
+		rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *)val);
+		break;
+	case HW_VAR_CTRL_FILTER:
+		rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *)val);
+		break;
+	case HW_VAR_DATA_FILTER:
+		rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case "
+							"not process\n"));
+		break;
+	}
+}
+
+void rtl92cu_update_hal_rate_table(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));
+	u32 ratr_value = (u32) mac->basic_rates;
+	u8 *mcsrate = mac->mcs;
+	u8 ratr_index = 0;
+	u8 nmode = mac->ht_enable;
+	u8 mimo_ps = 1;
+	u16 shortgi_rate = 0;
+	u32 tmp_ratr_value = 0;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
+	enum wireless_mode wirelessmode = mac->mode;
+
+	ratr_value |= ((*(u16 *) (mcsrate))) << 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 == 0) {
+			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;
+			if (curtxbw_40mhz)
+				ratr_mask |= 0x00000010;
+			ratr_value &= ratr_mask;
+		}
+		break;
+	default:
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_value &= 0x000ff0ff;
+		else
+			ratr_value &= 0x0f0ff0ff;
+		break;
+	}
+	ratr_value &= 0x0FFFFFFF;
+	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+	    (!curtxbw_40mhz && curshortgi_20mhz))) {
+		ratr_value |= 0x10000000;
+		tmp_ratr_value = (ratr_value >> 12);
+		for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
+			if ((1 << shortgi_rate) & tmp_ratr_value)
+				break;
+		}
+		shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
+			       (shortgi_rate << 4) | (shortgi_rate);
+	}
+	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("%x\n", rtl_read_dword(rtlpriv,
+		 REG_ARFR0)));
+}
+
+void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u32 ratr_bitmap = (u32) mac->basic_rates;
+	u8 *p_mcsrate = mac->mcs;
+	u8 ratr_index = 0;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
+	enum wireless_mode wirelessmode = mac->mode;
+	bool shortgi = false;
+	u8 rate_mask[5];
+	u8 macid = 0;
+	u8 mimops = 1;
+
+	ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12);
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		ratr_index = RATR_INX_WIRELESS_B;
+		if (ratr_bitmap & 0x0000000c)
+			ratr_bitmap &= 0x0000000d;
+		else
+			ratr_bitmap &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_index = RATR_INX_WIRELESS_GB;
+		if (rssi_level == 1)
+			ratr_bitmap &= 0x00000f00;
+		else if (rssi_level == 2)
+			ratr_bitmap &= 0x00000ff0;
+		else
+			ratr_bitmap &= 0x00000ff5;
+		break;
+	case WIRELESS_MODE_A:
+		ratr_index = RATR_INX_WIRELESS_A;
+		ratr_bitmap &= 0x00000ff0;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+		if (mimops == 0) {
+			if (rssi_level == 1)
+				ratr_bitmap &= 0x00070000;
+			else if (rssi_level == 2)
+				ratr_bitmap &= 0x0007f000;
+			else
+				ratr_bitmap &= 0x0007f005;
+		} else {
+			if (rtlphy->rf_type == RF_1T2R ||
+			    rtlphy->rf_type == RF_1T1R) {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff005;
+				}
+			} else {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff005;
+				}
+			}
+		}
+		if ((curtxbw_40mhz && curshortgi_40mhz) ||
+		    (!curtxbw_40mhz && curshortgi_20mhz)) {
+			if (macid == 0)
+				shortgi = true;
+			else if (macid == 1)
+				shortgi = false;
+		}
+		break;
+	default:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_bitmap &= 0x000ff0ff;
+		else
+			ratr_bitmap &= 0x0f0ff0ff;
+		break;
+	}
+	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]));
+	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
+}
+
+void rtl92cu_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 rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+	u8 u1tmp = 0;
+	bool actuallyset = false;
+	unsigned long flag = 0;
+	/* to do - usb autosuspend */
+	u8 usb_autosuspend = 0;
+
+	if (ppsc->swrf_processing)
+		return false;
+	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+	if (ppsc->rfchange_inprogress) {
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+		return false;
+	} else {
+		ppsc->rfchange_inprogress = true;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	}
+	cur_rfstate = ppsc->rfpwr_state;
+	if (usb_autosuspend) {
+		/* to do................... */
+	} else {
+		if (ppsc->pwrdown_mode) {
+			u1tmp = rtl_read_byte(rtlpriv, REG_HSISR);
+			e_rfpowerstate_toset = (u1tmp & BIT(7)) ?
+					       ERFOFF : ERFON;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+				 ("pwrdown, 0x5c(BIT7)=%02x\n", u1tmp));
+		} else {
+			rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG,
+				       rtl_read_byte(rtlpriv,
+				       REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+			u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
+			e_rfpowerstate_toset  = (u1tmp & BIT(3)) ?
+						 ERFON : ERFOFF;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+				("GPIO_IN=%02x\n", u1tmp));
+		}
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("N-SS RF =%x\n",
+			 e_rfpowerstate_toset));
+	}
+	if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("GPIOChangeRF  - HW "
+			 "Radio ON, RF ON\n"));
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((!ppsc->hwradiooff) && (e_rfpowerstate_toset  ==
+		    ERFOFF)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("GPIOChangeRF  - HW"
+			 " Radio OFF\n"));
+		ppsc->hwradiooff = true;
+		actuallyset = true;
+	} else {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
+			 ("pHalData->bHwRadioOff and eRfPowerStateToSet do not"
+			 " match: pHalData->bHwRadioOff %x, eRfPowerStateToSet "
+			 "%x\n", ppsc->hwradiooff, e_rfpowerstate_toset));
+	}
+	if (actuallyset) {
+		ppsc->hwradiooff = 1;
+		if (e_rfpowerstate_toset == ERFON) {
+			if ((ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM) &&
+			     RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM))
+				RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
+			else if ((ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_PCI_D3)
+				 && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3))
+				RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3);
+		}
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+		/* For power down module, we need to enable register block
+		 * contrl reg at 0x1c. Then enable power down control bit
+		 * of register 0x04 BIT4 and BIT15 as 1.
+		 */
+		if (ppsc->pwrdown_mode && e_rfpowerstate_toset == ERFOFF) {
+			/* Enable register area 0x0-0xc. */
+			rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0);
+			if (IS_HARDWARE_TYPE_8723U(rtlhal)) {
+				/*
+				 * We should configure HW PDn source for WiFi
+				 * ONLY, and then our HW will be set in
+				 * power-down mode if PDn source from all
+				 * functions are configured.
+				 */
+				u1tmp = rtl_read_byte(rtlpriv,
+						      REG_MULTI_FUNC_CTRL);
+				rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL,
+					       (u1tmp|WL_HWPDN_EN));
+			} else {
+				rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x8812);
+			}
+		}
+		if (e_rfpowerstate_toset == ERFOFF) {
+			if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM)
+				RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
+			else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3)
+				RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3);
+		}
+	} else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) {
+		/* Enter D3 or ASPM after GPIO had been done. */
+		if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM)
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
+		else if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_PCI_D3)
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3);
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	} else {
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	}
+	*valid = 1;
+	return !ppsc->hwradiooff;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
new file mode 100644
index 0000000..62af555
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
@@ -0,0 +1,116 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_HW_H__
+#define __RTL92CU_HW_H__
+
+#define H2C_RA_MASK	6
+
+#define LLT_POLLING_LLT_THRESHOLD		20
+#define LLT_POLLING_READY_TIMEOUT_COUNT		100
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER		255
+
+#define RX_PAGE_SIZE_REG_VALUE			PBP_128
+/* Note: We will divide number of page equally for each queue
+ * other than public queue! */
+#define TX_TOTAL_PAGE_NUMBER			0xF8
+#define TX_PAGE_BOUNDARY			(TX_TOTAL_PAGE_NUMBER + 1)
+
+
+#define CHIP_B_PAGE_NUM_PUBQ			0xE7
+
+/* For Test Chip Setting
+ * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */
+#define CHIP_A_PAGE_NUM_PUBQ			0x7E
+
+
+/* For Chip A Setting */
+#define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER		0xF5
+#define WMM_CHIP_A_TX_PAGE_BOUNDARY		\
+	(WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */
+
+#define WMM_CHIP_A_PAGE_NUM_PUBQ		0xA3
+#define WMM_CHIP_A_PAGE_NUM_HPQ			0x29
+#define WMM_CHIP_A_PAGE_NUM_LPQ			0x29
+
+
+
+/* Note: For Chip B Setting ,modify later */
+#define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER		0xF5
+#define WMM_CHIP_B_TX_PAGE_BOUNDARY		\
+	(WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */
+
+#define WMM_CHIP_B_PAGE_NUM_PUBQ		0xB0
+#define WMM_CHIP_B_PAGE_NUM_HPQ			0x29
+#define WMM_CHIP_B_PAGE_NUM_LPQ			0x1C
+#define WMM_CHIP_B_PAGE_NUM_NPQ			0x1C
+
+#define BOARD_TYPE_NORMAL_MASK			0xE0
+#define BOARD_TYPE_TEST_MASK			0x0F
+
+/* should be renamed and moved to another file */
+enum _BOARD_TYPE_8192CUSB {
+	BOARD_USB_DONGLE		= 0,	/* USB dongle */
+	BOARD_USB_High_PA		= 1,	/* USB dongle - high power PA */
+	BOARD_MINICARD			= 2,	/* Minicard */
+	BOARD_USB_SOLO			= 3,	/* USB solo-Slim module */
+	BOARD_USB_COMBO			= 4,	/* USB Combo-Slim module */
+};
+
+#define IS_HIGHT_PA(boardtype)		\
+	((boardtype == BOARD_USB_High_PA) ? true : false)
+
+#define RTL92C_DRIVER_INFO_SIZE				4
+void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw);
+void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw);
+int rtl92cu_hw_init(struct ieee80211_hw *hw);
+void rtl92cu_card_disable(struct ieee80211_hw *hw);
+int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr);
+void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw);
+void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level);
+
+void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
+void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+u8 _rtl92c_get_chnl_group(u8 chnl);
+int rtl92c_download_fw(struct ieee80211_hw *hw);
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
+void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
+bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.c b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
new file mode 100644
index 0000000..332c743
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
@@ -0,0 +1,142 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../usb.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl92cu_init_led(struct ieee80211_hw *hw,
+			      struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+	pled->hw = hw;
+	pled->ledpin = ledpin;
+	pled->ledon = false;
+}
+
+static void _rtl92cu_deInit_led(struct rtl_led *pled)
+{
+}
+
+void rtl92cu_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));
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		rtl_write_byte(rtlpriv,
+			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6));
+		break;
+	case LED_PIN_LED1:
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	pled->ledon = true;
+}
+
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
+	u8 ledcfg;
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		ledcfg &= 0xf0;
+		if (usbpriv->ledctl.led_opendrain == true)
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+		else
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+		break;
+	case LED_PIN_LED1:
+		ledcfg &= 0x0f;
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	pled->ledon = false;
+}
+
+void rtl92cu_init_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
+	_rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led0), LED_PIN_LED0);
+	_rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
+	_rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led0));
+	_rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led1));
+}
+
+static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw,
+				    enum led_ctl_mode ledaction)
+{
+}
+
+void rtl92cu_led_control(struct ieee80211_hw *hw,
+			enum led_ctl_mode ledaction)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+	    (ledaction == LED_CTL_TX ||
+	     ledaction == LED_CTL_RX ||
+	     ledaction == LED_CTL_SITE_SURVEY ||
+	     ledaction == LED_CTL_LINK ||
+	     ledaction == LED_CTL_NO_LINK ||
+	     ledaction == LED_CTL_START_TO_LINK ||
+	     ledaction == LED_CTL_POWER_ON)) {
+		return;
+	}
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n",
+				ledaction));
+	_rtl92cu_sw_led_control(hw, ledaction);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/led.h b/drivers/net/wireless/rtlwifi/rtl8192cu/led.h
new file mode 100644
index 0000000..decaee4
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/led.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_LED_H__
+#define __RTL92CU_LED_H__
+
+void rtl92cu_init_sw_leds(struct ieee80211_hw *hw);
+void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw);
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
new file mode 100644
index 0000000..f8514cb
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
@@ -0,0 +1,1144 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+****************************************************************************/
+#include <linux/module.h>
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../usb.h"
+#include "../ps.h"
+#include "../cam.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "mac.h"
+#include "trx.h"
+
+/* macro to shorten lines */
+
+#define LINK_Q	ui_link_quality
+#define RX_EVM	rx_evm_percentage
+#define RX_SIGQ	rx_mimo_signalquality
+
+
+void rtl92c_read_chip_version(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	enum version_8192c chip_version = VERSION_UNKNOWN;
+	u32 value32;
+
+	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+	if (value32 & TRP_VAUX_EN) {
+		chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C :
+			       VERSION_TEST_CHIP_88C;
+	} else {
+		/* Normal mass production chip. */
+		chip_version = NORMAL_CHIP;
+		chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0);
+		chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0);
+		/* RTL8723 with BT function. */
+		chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0);
+		if (IS_VENDOR_UMC(chip_version))
+			chip_version |= ((value32 & CHIP_VER_RTL_MASK) ?
+					 CHIP_VENDOR_UMC_B_CUT : 0);
+		if (IS_92C_SERIAL(chip_version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
+			chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) ==
+				 CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0);
+		} else if (IS_8723_SERIES(chip_version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
+			chip_version |= ((value32 & RF_RL_ID) ?
+					  CHIP_8723_DRV_REV : 0);
+		}
+	}
+	rtlhal->version  = (enum version_8192c)chip_version;
+	switch (rtlhal->version) {
+	case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Chip Version ID: VERSION_B_CHIP_92C.\n"));
+		break;
+	case VERSION_NORMAL_TSMC_CHIP_92C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_92C.\n"));
+		break;
+	case VERSION_NORMAL_TSMC_CHIP_88C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_88C.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP_i"
+			"92C_1T2R_A_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP_"
+			"92C_A_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_88C_A_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_92C_1T2R_B_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_92C_B_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_88C_B_CUT.\n"));
+		break;
+	case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMA_UMC_CHIP"
+			"_8723_1T1R_A_CUT.\n"));
+		break;
+	case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMA_UMC_CHIP"
+			"_8723_1T1R_B_CUT.\n"));
+		break;
+	case VERSION_TEST_CHIP_92C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_TEST_CHIP_92C.\n"));
+		break;
+	case VERSION_TEST_CHIP_88C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_TEST_CHIP_88C.\n"));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: ???????????????.\n"));
+		break;
+	}
+	if (IS_92C_SERIAL(rtlhal->version))
+		rtlphy->rf_type =
+			 (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R;
+	else
+		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"));
+	if (get_rf_type(rtlphy) == RF_1T1R)
+		rtlpriv->dm.rfpath_rxenable[0] = true;
+	else
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("VersionID = 0x%4x\n",
+						rtlhal->version));
+}
+
+/**
+ * writeLLT - LLT table write access
+ * @io: io callback
+ * @address: LLT logical address.
+ * @data: LLT data content
+ *
+ * Realtek hardware access function.
+ *
+ */
+bool rtl92c_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! _LLT_OP_VALUE(%x)\n",
+				 address, _LLT_OP_VALUE(value)));
+			status = false;
+			break;
+		}
+	} while (++count);
+	return status;
+}
+/**
+ * rtl92c_init_LLT_table - Init LLT table
+ * @io: io callback
+ * @boundary:
+ *
+ * Realtek hardware access function.
+ *
+ */
+bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
+{
+	bool rst = true;
+	u32	i;
+
+	for (i = 0; i < (boundary - 1); i++) {
+		rst = rtl92c_llt_write(hw, i , i + 1);
+		if (true != rst) {
+			printk(KERN_ERR "===> %s #1 fail\n", __func__);
+			return rst;
+		}
+	}
+	/* end of list */
+	rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
+	if (true != rst) {
+		printk(KERN_ERR "===> %s #2 fail\n", __func__);
+		return rst;
+	}
+	/* Make the other pages as ring buffer
+	 * This ring buffer is used as beacon buffer if we config this MAC
+	 *  as two MAC transfer.
+	 * Otherwise used as local loopback buffer.
+	 */
+	for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
+		rst = rtl92c_llt_write(hw, i, (i + 1));
+		if (true != rst) {
+			printk(KERN_ERR "===> %s #3 fail\n", __func__);
+			return rst;
+		}
+	}
+	/* Let last entry point to the start entry of ring buffer */
+	rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
+	if (true != rst) {
+		printk(KERN_ERR "===> %s #4 fail\n", __func__);
+		return rst;
+	}
+	return rst;
+}
+void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
+		     u8 *p_macaddr, bool is_group, u8 enc_algo,
+		     bool is_wepkey, bool clear_all)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 *macaddr = p_macaddr;
+	u32 entry_id = 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,
+				("iillegal switch case\n"));
+			enc_algo = CAM_TKIP;
+			break;
+		}
+		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+			macaddr = cam_const_addr[key_index];
+			entry_id = key_index;
+		} else {
+			if (is_group) {
+				macaddr = cam_const_broad;
+				entry_id = key_index;
+			} else {
+				key_index = PAIRWISE_KEYIDX;
+				entry_id = CAM_PAIRWISE_KEY_POSITION;
+				is_pairwise = true;
+			}
+		}
+		if (rtlpriv->sec.key_len[key_index] == 0) {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 ("delete one entry\n"));
+			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+		} else {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+				 ("The insert KEY length is %d\n",
+				  rtlpriv->sec.key_len[PAIRWISE_KEYIDX]));
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+				 ("The insert KEY  is %x %x\n",
+				  rtlpriv->sec.key_buf[0][0],
+				  rtlpriv->sec.key_buf[0][1]));
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 ("add one entry\n"));
+			if (is_pairwise) {
+				RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
+					      "Pairwiase Key content :",
+					      rtlpriv->sec.pairwise_key,
+					      rtlpriv->sec.
+					      key_len[PAIRWISE_KEYIDX]);
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 ("set Pairwiase key\n"));
+
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						entry_id, enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.
+						key_buf[key_index]);
+			} else {
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 ("set group key\n"));
+				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+					rtl_cam_add_one_entry(hw,
+						rtlefuse->dev_addr,
+						PAIRWISE_KEYIDX,
+						CAM_PAIRWISE_KEY_POSITION,
+						enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf
+						[entry_id]);
+				}
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						entry_id, enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf[entry_id]);
+			}
+		}
+	}
+}
+
+u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS);
+}
+
+void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
+		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;
+	} else {
+		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
+				0xFFFFFFFF);
+		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
+				0xFFFFFFFF);
+		rtlusb->irq_enabled = true;
+	}
+}
+
+void rtl92c_init_interrupt(struct ieee80211_hw *hw)
+{
+	 rtl92c_enable_interrupt(hw);
+}
+
+void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
+	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
+	if (IS_HARDWARE_TYPE_8192CE(rtlhal))
+		rtlpci->irq_enabled = false;
+	else if (IS_HARDWARE_TYPE_8192CU(rtlhal))
+		rtlusb->irq_enabled = false;
+}
+
+void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u32 u4b_ac_param;
+
+	rtl92c_dm_init_edca_turbo(hw);
+	u4b_ac_param = (u32) mac->ac[aci].aifs;
+	u4b_ac_param |=
+	    ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) <<
+	    AC_PARAM_ECW_MIN_OFFSET;
+	u4b_ac_param |=
+	    ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) <<
+	    AC_PARAM_ECW_MAX_OFFSET;
+	u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) <<
+			 AC_PARAM_TXOP_OFFSET;
+	RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD,
+		 ("queue:%x, ac_param:%x\n", aci, u4b_ac_param));
+	switch (aci) {
+	case AC1_BK:
+		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
+		break;
+	case AC0_BE:
+		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param);
+		break;
+	case AC2_VI:
+		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param);
+		break;
+	case AC3_VO:
+		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param);
+		break;
+	default:
+		RT_ASSERT(false, ("invalid aci: %d !\n", aci));
+		break;
+	}
+}
+
+/*-------------------------------------------------------------------------
+ * HW MAC Address
+ *-------------------------------------------------------------------------*/
+void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr)
+{
+	u32 i;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	for (i = 0 ; i < ETH_ALEN ; i++)
+		rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i));
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("MAC Address: %02X-%02X-%02X-"
+		"%02X-%02X-%02X\n",
+		rtl_read_byte(rtlpriv, REG_MACID),
+		rtl_read_byte(rtlpriv, REG_MACID+1),
+		rtl_read_byte(rtlpriv, REG_MACID+2),
+		rtl_read_byte(rtlpriv, REG_MACID+3),
+		rtl_read_byte(rtlpriv, REG_MACID+4),
+		rtl_read_byte(rtlpriv, REG_MACID+5)));
+}
+
+void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
+}
+
+int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+	u8 value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		value = NT_NO_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to NO LINK!\n"));
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		value = NT_LINK_AD_HOC;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to Ad Hoc!\n"));
+		break;
+	case NL80211_IFTYPE_STATION:
+		value = NT_LINK_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to STA!\n"));
+		break;
+	case NL80211_IFTYPE_AP:
+		value = NT_AS_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to AP!\n"));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Network type %d not support!\n", type));
+		return -EOPNOTSUPP;
+	}
+	rtl_write_byte(rtlpriv, (REG_CR + 2), value);
+	return 0;
+}
+
+void rtl92c_init_network_type(struct ieee80211_hw *hw)
+{
+	rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED);
+}
+
+void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw)
+{
+	u16	value16;
+	u32	value32;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* Response Rate Set */
+	value32 = rtl_read_dword(rtlpriv, REG_RRSR);
+	value32 &= ~RATE_BITMAP_ALL;
+	value32 |= RATE_RRSR_CCK_ONLY_1M;
+	rtl_write_dword(rtlpriv, REG_RRSR, value32);
+	/* SIFS (used in NAV) */
+	value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
+	rtl_write_word(rtlpriv,  REG_SPEC_SIFS, value16);
+	/* Retry Limit */
+	value16 = _LRL(0x30) | _SRL(0x30);
+	rtl_write_dword(rtlpriv,  REG_RL, value16);
+}
+
+void rtl92c_init_rate_fallback(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* Set Data Auto Rate Fallback Retry Count register. */
+	rtl_write_dword(rtlpriv,  REG_DARFRC, 0x00000000);
+	rtl_write_dword(rtlpriv,  REG_DARFRC+4, 0x10080404);
+	rtl_write_dword(rtlpriv,  REG_RARFRC, 0x04030201);
+	rtl_write_dword(rtlpriv,  REG_RARFRC+4, 0x08070605);
+}
+
+static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
+				u8 ctx_sifs)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs);
+	rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs);
+}
+
+static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
+				 u8 ctx_sifs)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs);
+	rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs);
+}
+
+void rtl92c_init_edca_param(struct ieee80211_hw *hw,
+			    u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs)
+{
+	/* sequence: VO, VI, BE, BK ==> the same as 92C hardware design.
+	 * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function.
+	 */
+	u32 value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	value = (u32)aifs;
+	value |= ((u32)cw_min & 0xF) << 8;
+	value |= ((u32)cw_max & 0xF) << 12;
+	value |= (u32)txop << 16;
+	/* 92C hardware register sequence is the same as queue number. */
+	rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value);
+}
+
+void rtl92c_init_edca(struct ieee80211_hw *hw)
+{
+	u16 value16;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* disable EDCCA count down, to reduce collison and retry */
+	value16 = rtl_read_word(rtlpriv, REG_RD_CTRL);
+	value16 |= DIS_EDCA_CNT_DWN;
+	rtl_write_word(rtlpriv, REG_RD_CTRL, value16);
+	/* Update SIFS timing.  ??????????
+	 * pHalData->SifsTime = 0x0e0e0a0a; */
+	rtl92c_set_cck_sifs(hw, 0xa, 0xa);
+	rtl92c_set_ofdm_sifs(hw, 0xe, 0xe);
+	/* Set CCK/OFDM SIFS to be 10us. */
+	rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a);
+	rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010);
+	rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204);
+	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004);
+	/* TXOP */
+	rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B);
+	rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F);
+	rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324);
+	rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226);
+	/* PIFS */
+	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+	/* AGGR BREAK TIME Register */
+	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
+	rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02);
+	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02);
+}
+
+void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631);
+	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+	/* init AMPDU aggregation number, tuning for Tx's TP, */
+	rtl_write_word(rtlpriv, 0x4CA, 0x0708);
+}
+
+void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
+}
+
+void rtl92c_init_rdg_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF);
+	rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
+	rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
+}
+
+void rtl92c_init_retry_function(struct ieee80211_hw *hw)
+{
+	u8	value8;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL);
+	value8 |= EN_AMPDU_RTY_NEW;
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8);
+	/* Set ACK timeout */
+	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+}
+
+void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
+				   enum version_8192c version)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
+	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
+	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
+	else
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
+}
+
+void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0);
+}
+
+void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T;
+
+	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value);
+}
+
+u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_word(rtlpriv, REG_RXFLTMAP0);
+}
+
+void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter);
+}
+
+u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_word(rtlpriv, REG_RXFLTMAP1);
+}
+
+void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter);
+}
+
+u16 rtl92c_get_data_filter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_word(rtlpriv,  REG_RXFLTMAP2);
+}
+
+void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter);
+}
+/*==============================================================*/
+
+static u8 _rtl92c_query_rxpwrpercentage(char antpower)
+{
+	if ((antpower <= -100) || (antpower >= 20))
+		return 0;
+	else if (antpower >= 0)
+		return 100;
+	else
+		return 100 + antpower;
+}
+
+static u8 _rtl92c_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 _rtl92c_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 _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
+		long currsig)
+{
+	long retsig;
+
+	if (currsig >= 61 && currsig <= 100)
+		retsig = 90 + ((currsig - 60) / 4);
+	else if (currsig >= 41 && currsig <= 60)
+		retsig = 78 + ((currsig - 40) / 2);
+	else if (currsig >= 31 && currsig <= 40)
+		retsig = 66 + (currsig - 30);
+	else if (currsig >= 21 && currsig <= 30)
+		retsig = 54 + (currsig - 20);
+	else if (currsig >= 5 && currsig <= 20)
+		retsig = 42 + (((currsig - 5) * 2) / 3);
+	else if (currsig == 4)
+		retsig = 36;
+	else if (currsig == 3)
+		retsig = 27;
+	else if (currsig == 2)
+		retsig = 18;
+	else if (currsig == 1)
+		retsig = 9;
+	else
+		retsig = currsig;
+	return retsig;
+}
+
+static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
+				      struct rtl_stats *pstats,
+				      struct rx_desc_92c *pdesc,
+				      struct rx_fwinfo_92c *p_drvinfo,
+				      bool packet_match_bssid,
+				      bool packet_toself,
+				      bool packet_beacon)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct phy_sts_cck_8192s_t *cck_buf;
+	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_rate;
+
+	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+	pstats->packet_matchbssid = packet_match_bssid;
+	pstats->packet_toself = packet_toself;
+	pstats->is_cck = is_cck_rate;
+	pstats->packet_beacon = packet_beacon;
+	pstats->is_cck = is_cck_rate;
+	pstats->RX_SIGQ[0] = -1;
+	pstats->RX_SIGQ[1] = -1;
+	if (is_cck_rate) {
+		u8 report, cck_highpwr;
+		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
+		if (!in_powersavemode)
+			cck_highpwr = rtlphy->cck_high_power;
+		else
+			cck_highpwr = false;
+		if (!cck_highpwr) {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = cck_buf->cck_agc_rpt & 0xc0;
+			report = report >> 6;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+				break;
+			}
+		} else {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = p_drvinfo->cfosho[0] & 0x60;
+			report = report >> 5;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			}
+		}
+		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
+		pstats->rx_pwdb_all = pwdb_all;
+		pstats->recvsignalpower = rx_pwr_all;
+		if (packet_match_bssid) {
+			u8 sq;
+			if (pstats->rx_pwdb_all > 40)
+				sq = 100;
+			else {
+				sq = cck_buf->sq_rpt;
+				if (sq > 64)
+					sq = 0;
+				else if (sq < 20)
+					sq = 100;
+				else
+					sq = ((64 - sq) * 100) / 44;
+			}
+			pstats->signalquality = sq;
+			pstats->RX_SIGQ[0] = sq;
+			pstats->RX_SIGQ[1] = -1;
+		}
+	} else {
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
+			if (rtlpriv->dm.rfpath_rxenable[i])
+				rf_rx_num++;
+			rx_pwr[i] =
+			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
+			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+			rtlpriv->stats.rx_snr_db[i] =
+			    (long)(p_drvinfo->rxsnr[i] / 2);
+
+			if (packet_match_bssid)
+				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
+		}
+		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 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 (GET_RX_DESC_RX_MCS(pdesc) &&
+		    GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 &&
+		    GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+		for (i = 0; i < max_spatial_stream; i++) {
+			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+			if (packet_match_bssid) {
+				if (i == 0)
+					pstats->signalquality =
+					    (u8) (evm & 0xff);
+				pstats->RX_SIGQ[i] =
+				    (u8) (evm & 0xff);
+			}
+		}
+	}
+	if (is_cck_rate)
+		pstats->signalstrength =
+		    (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all));
+	else if (rf_rx_num != 0)
+		pstats->signalstrength =
+		    (u8) (_rtl92c_signal_scale_mapping
+			  (hw, total_rssi /= rf_rx_num));
+}
+
+static void _rtl92c_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 =
+		    _rtl92c_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 (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
+				continue;
+			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 _rtl92c_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 _rtl92c_process_pwdb(struct ieee80211_hw *hw,
+		struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undecorated_smoothed_pwdb = 0;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+		return;
+	} else {
+		undecorated_smoothed_pwdb =
+		    rtlpriv->dm.undecorated_smoothed_pwdb;
+	}
+	if (pstats->packet_toself || pstats->packet_beacon) {
+		if (undecorated_smoothed_pwdb < 0)
+			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
+			undecorated_smoothed_pwdb =
+			    (((undecorated_smoothed_pwdb) *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
+			    + 1;
+		} else {
+			undecorated_smoothed_pwdb =
+			    (((undecorated_smoothed_pwdb) *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+		}
+		rtlpriv->dm.undecorated_smoothed_pwdb =
+		    undecorated_smoothed_pwdb;
+		_rtl92c_update_rxsignalstatistics(hw, pstats);
+	}
+}
+
+static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw,
+					     struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 last_evm = 0, n_stream, tmpval;
+
+	if (pstats->signalquality != 0) {
+		if (pstats->packet_toself || pstats->packet_beacon) {
+			if (rtlpriv->stats.LINK_Q.total_num++ >=
+			    PHY_LINKQUALITY_SLID_WIN_MAX) {
+				rtlpriv->stats.LINK_Q.total_num =
+				    PHY_LINKQUALITY_SLID_WIN_MAX;
+				last_evm =
+				    rtlpriv->stats.LINK_Q.elements
+				    [rtlpriv->stats.LINK_Q.index];
+				rtlpriv->stats.LINK_Q.total_val -=
+				    last_evm;
+			}
+			rtlpriv->stats.LINK_Q.total_val +=
+			    pstats->signalquality;
+			rtlpriv->stats.LINK_Q.elements
+			   [rtlpriv->stats.LINK_Q.index++] =
+			    pstats->signalquality;
+			if (rtlpriv->stats.LINK_Q.index >=
+			    PHY_LINKQUALITY_SLID_WIN_MAX)
+				rtlpriv->stats.LINK_Q.index = 0;
+			tmpval = rtlpriv->stats.LINK_Q.total_val /
+			    rtlpriv->stats.LINK_Q.total_num;
+			rtlpriv->stats.signal_quality = tmpval;
+			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+			for (n_stream = 0; n_stream < 2;
+			     n_stream++) {
+				if (pstats->RX_SIGQ[n_stream] != -1) {
+					if (!rtlpriv->stats.RX_EVM[n_stream]) {
+						rtlpriv->stats.RX_EVM[n_stream]
+						 = pstats->RX_SIGQ[n_stream];
+					}
+					rtlpriv->stats.RX_EVM[n_stream] =
+					    ((rtlpriv->stats.RX_EVM
+					    [n_stream] *
+					    (RX_SMOOTH_FACTOR - 1)) +
+					    (pstats->RX_SIGQ
+					    [n_stream] * 1)) /
+					    (RX_SMOOTH_FACTOR);
+				}
+			}
+		}
+	} else {
+		;
+	}
+}
+
+static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw,
+				     u8 *buffer,
+				     struct rtl_stats *pcurrent_stats)
+{
+	if (!pcurrent_stats->packet_matchbssid &&
+	    !pcurrent_stats->packet_beacon)
+		return;
+	_rtl92c_process_ui_rssi(hw, pcurrent_stats);
+	_rtl92c_process_pwdb(hw, pcurrent_stats);
+	_rtl92c_process_LINK_Q(hw, pcurrent_stats);
+}
+
+void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+					       struct sk_buff *skb,
+					       struct rtl_stats *pstats,
+					       struct rx_desc_92c *pdesc,
+					       struct rx_fwinfo_92c *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, cpu_fc;
+	bool packet_matchbssid, packet_toself, packet_beacon;
+
+	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
+	hdr = (struct ieee80211_hdr *)tmp_buf;
+	fc = hdr->frame_control;
+	cpu_fc = le16_to_cpu(fc);
+	type = WLAN_FC_GET_TYPE(fc);
+	praddr = hdr->addr1;
+	psaddr = hdr->addr2;
+	packet_matchbssid =
+	    ((IEEE80211_FTYPE_CTL != type) &&
+	     (!compare_ether_addr(mac->bssid,
+			  (cpu_fc & IEEE80211_FCTL_TODS) ?
+			  hdr->addr1 : (cpu_fc & IEEE80211_FCTL_FROMDS) ?
+			  hdr->addr2 : hdr->addr3)) &&
+	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
+
+	packet_toself = packet_matchbssid &&
+	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+	if (ieee80211_is_beacon(fc))
+		packet_beacon = true;
+	_rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
+				   packet_matchbssid, packet_toself,
+				   packet_beacon);
+	_rtl92c_process_phyinfo(hw, tmp_buf, pstats);
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
new file mode 100644
index 0000000..298fdb7
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
@@ -0,0 +1,180 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * 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_MAC_H__
+#define __RTL92C_MAC_H__
+
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER		255
+#define DRIVER_EARLY_INT_TIME					0x05
+#define BCN_DMA_ATIME_INT_TIME				0x02
+
+void rtl92c_read_chip_version(struct ieee80211_hw *hw);
+bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data);
+bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary);
+void rtl92c_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 rtl92c_enable_interrupt(struct ieee80211_hw *hw);
+void rtl92c_disable_interrupt(struct ieee80211_hw *hw);
+void rtl92c_set_qos(struct ieee80211_hw *hw, int aci);
+
+
+/*---------------------------------------------------------------
+ *	Hardware init functions
+ *---------------------------------------------------------------*/
+void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr);
+void rtl92c_init_interrupt(struct ieee80211_hw *hw);
+void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size);
+
+int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92c_init_network_type(struct ieee80211_hw *hw);
+void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw);
+void rtl92c_init_rate_fallback(struct ieee80211_hw *hw);
+
+void rtl92c_init_edca_param(struct ieee80211_hw *hw,
+							u16 queue,
+							u16 txop,
+							u8 ecwmax,
+							u8 ecwmin,
+							u8 aifs);
+
+void rtl92c_init_edca(struct ieee80211_hw *hw);
+void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw);
+void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode);
+void rtl92c_init_rdg_setting(struct ieee80211_hw *hw);
+void rtl92c_init_retry_function(struct ieee80211_hw *hw);
+
+void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
+				   enum version_8192c version);
+
+void rtl92c_disable_fast_edca(struct ieee80211_hw *hw);
+void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T);
+
+/* For filter */
+u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw);
+void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter);
+u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw);
+void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter);
+u16 rtl92c_get_data_filter(struct ieee80211_hw *hw);
+void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);
+
+
+u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);
+
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+	(GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\
+	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\
+	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\
+	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M)
+
+struct rx_fwinfo_92c {
+	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 rx_desc_92c {
+	u32 length:14;
+	u32 crc32:1;
+	u32 icverror:1;
+	u32 drv_infosize:4;
+	u32 security:3;
+	u32 qos:1;
+	u32 shift:2;
+	u32 phystatus:1;
+	u32 swdec:1;
+	u32 lastseg:1;
+	u32 firstseg:1;
+	u32 eor:1;
+	u32 own:1;
+	u32 macid:5;	/* word 1 */
+	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;	/* word 2 */
+	u32 frag:4;
+	u32 nextpktlen:14;
+	u32 nextind:1;
+	u32 rsvd:1;
+	u32 rxmcs:6;	/* word 3 */
+	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;	/* word 4 */
+	u32 tsfl;	/* word 5 */
+	u32 bufferaddress;	/* word 6 */
+	u32 bufferaddress64;	/* word 7 */
+} __packed;
+
+enum rtl_desc_qsel rtl92c_map_hwqueue_to_fwqueue(u16 fc,
+							  unsigned int
+							  skb_queue);
+void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+				      struct sk_buff *skb,
+				      struct rtl_stats *pstats,
+				      struct rx_desc_92c *pdesc,
+				      struct rx_fwinfo_92c *p_drvinfo);
+
+/*---------------------------------------------------------------
+ *	Card disable functions
+ *---------------------------------------------------------------*/
+
+
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
new file mode 100644
index 0000000..4e020e6
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
@@ -0,0 +1,607 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+
+u32 rtl92cu_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;
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+					       "rfpath(%#x), bitmask(%#x)\n",
+					       regaddr, rfpath, bitmask));
+	if (rtlphy->rf_mode != RF_OP_BY_FW) {
+		original_value = _rtl92c_phy_rf_serial_read(hw,
+							    rfpath, regaddr);
+	} else {
+		original_value = _rtl92c_phy_fw_rf_serial_read(hw,
+							       rfpath, regaddr);
+	}
+	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+	readback_value = (original_value & bitmask) >> bitshift;
+	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 rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
+			   enum radio_path rfpath,
+			   u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 original_value, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		  regaddr, bitmask, data, rfpath));
+	if (rtlphy->rf_mode != RF_OP_BY_FW) {
+		if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = _rtl92c_phy_rf_serial_read(hw,
+								    rfpath,
+								    regaddr);
+			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			data =
+			    ((original_value & (~bitmask)) |
+			     (data << bitshift));
+		}
+		_rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data);
+	} else {
+		if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = _rtl92c_phy_fw_rf_serial_read(hw,
+								       rfpath,
+								       regaddr);
+			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			data =
+			    ((original_value & (~bitmask)) |
+			     (data << bitshift));
+		}
+		_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
+	}
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+					       "bitmask(%#x), data(%#x), rfpath(%#x)\n",
+					       regaddr, bitmask, data, rfpath));
+}
+
+bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
+{
+	bool rtstatus;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool is92c = IS_92C_SERIAL(rtlhal->version);
+
+	rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
+	if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal))
+		rtl_write_byte(rtlpriv, 0x14, 0x71);
+	return rtstatus;
+}
+
+bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
+{
+	bool rtstatus = true;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u16 regval;
+	u8 b_reg_hwparafile = 1;
+
+	_rtl92c_phy_init_bb_rf_register_definition(hw);
+	regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+	rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) |
+		       BIT(0) | BIT(1));
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
+	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
+			       FEN_DIO_PCIE |	FEN_BB_GLB_RSTn | FEN_BBRSTB);
+	} else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
+			       FEN_BB_GLB_RSTn | FEN_BBRSTB);
+		rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
+	}
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
+	if (b_reg_hwparafile == 1)
+		rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
+	return rtstatus;
+}
+
+bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 i;
+	u32 arraylength;
+	u32 *ptrarray;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n"));
+	arraylength =  rtlphy->hwparam_tables[MAC_REG].length ;
+	ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Img:RTL8192CEMAC_2T_ARRAY\n"));
+	for (i = 0; i < arraylength; i = i + 2)
+		rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+	return true;
+}
+
+bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+						  u8 configtype)
+{
+	int i;
+	u32 *phy_regarray_table;
+	u32 *agctab_array_table;
+	u16 phy_reg_arraylen, agctab_arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (IS_92C_SERIAL(rtlhal->version)) {
+		agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length;
+		agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_2T].pdata;
+		phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length;
+		phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata;
+	} else {
+		agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length;
+		agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_1T].pdata;
+		phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length;
+		phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata;
+	}
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+			if (phy_regarray_table[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table[i] == 0xf9)
+				udelay(1);
+			rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
+				      phy_regarray_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("The phy_regarray_table[0] is %x"
+				  " Rtl819XPHY_REGArray[1] is %x\n",
+				  phy_regarray_table[i],
+				  phy_regarray_table[i + 1]));
+		}
+	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+		for (i = 0; i < agctab_arraylen; i = i + 2) {
+			rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
+				      agctab_array_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("The agctab_array_table[0] is "
+				  "%x Rtl819XPHY_REGArray[1] is %x\n",
+				  agctab_array_table[i],
+				  agctab_array_table[i + 1]));
+		}
+	}
+	return true;
+}
+
+bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+						    u8 configtype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	int i;
+	u32 *phy_regarray_table_pg;
+	u16 phy_regarray_pg_len;
+
+	rtlphy->pwrgroup_cnt = 0;
+	phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length;
+	phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata;
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+			if (phy_regarray_table_pg[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table_pg[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table_pg[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table_pg[i] == 0xf9)
+				udelay(1);
+			_rtl92c_store_pwrIndex_diffrate_offset(hw,
+						  phy_regarray_table_pg[i],
+						  phy_regarray_table_pg[i + 1],
+						  phy_regarray_table_pg[i + 2]);
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 ("configtype != BaseBand_Config_PHY_REG\n"));
+	}
+	return true;
+}
+
+bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath)
+{
+	int i;
+	u32 *radioa_array_table;
+	u32 *radiob_array_table;
+	u16 radioa_arraylen, radiob_arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (IS_92C_SERIAL(rtlhal->version)) {
+		radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length;
+		radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata;
+		radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
+		radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_A:RTL8192CERADIOA_2TARRAY\n"));
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_B:RTL8192CE_RADIOB_2TARRAY\n"));
+	} else {
+		radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
+		radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
+		radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
+		radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_A:RTL8192CE_RADIOA_1TARRAY\n"));
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
+	switch (rfpath) {
+	case RF90_PATH_A:
+		for (i = 0; i < radioa_arraylen; i = i + 2) {
+			if (radioa_array_table[i] == 0xfe)
+				mdelay(50);
+			else if (radioa_array_table[i] == 0xfd)
+				mdelay(5);
+			else if (radioa_array_table[i] == 0xfc)
+				mdelay(1);
+			else if (radioa_array_table[i] == 0xfb)
+				udelay(50);
+			else if (radioa_array_table[i] == 0xfa)
+				udelay(5);
+			else if (radioa_array_table[i] == 0xf9)
+				udelay(1);
+			else {
+				rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+					      RFREG_OFFSET_MASK,
+					      radioa_array_table[i + 1]);
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_B:
+		for (i = 0; i < radiob_arraylen; i = i + 2) {
+			if (radiob_array_table[i] == 0xfe) {
+				mdelay(50);
+			} else if (radiob_array_table[i] == 0xfd)
+				mdelay(5);
+			else if (radiob_array_table[i] == 0xfc)
+				mdelay(1);
+			else if (radiob_array_table[i] == 0xfb)
+				udelay(50);
+			else if (radiob_array_table[i] == 0xfa)
+				udelay(5);
+			else if (radiob_array_table[i] == 0xf9)
+				udelay(1);
+			else {
+				rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
+					      RFREG_OFFSET_MASK,
+					      radiob_array_table[i + 1]);
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_C:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	case RF90_PATH_D:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	return true;
+}
+
+void rtl92cu_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;
+	}
+	rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+	rtlphy->set_bwmode_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+
+void rtl92cu_bb_block_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	mutex_lock(&rtlpriv->io.bb_mutex);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+	mutex_unlock(&rtlpriv->io.bb_mutex);
+}
+
+void _rtl92cu_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);
+
+	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, RF90_PATH_A, 0x00, MASK12BITS);
+		if (is2t)
+			rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
+						  MASK12BITS);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
+			      (rf_a_mode & 0x8FFFF) | 0x10000);
+		if (is2t)
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+				      (rf_b_mode & 0x8FFFF) | 0x10000);
+	}
+	lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
+	mdelay(100);
+	if ((tmpreg & 0x70) != 0) {
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
+		if (is2t)
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+				      rf_b_mode);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+	}
+}
+
+bool _rtl92cu_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));
+	bool bresult = true;
+	u8 i, queue_id;
+	struct rtl8192_tx_ring *ring = NULL;
+
+	ppsc->set_rfpowerstate_inprogress = true;
+	switch (rfpwr_state) {
+	case ERFON:
+		if ((ppsc->rfpwr_state == ERFOFF) &&
+		    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+			bool rtstatus;
+			u32 InitializeCount = 0;
+
+			do {
+				InitializeCount++;
+				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+					 ("IPS Set eRf nic enable\n"));
+				rtstatus = rtl_ps_enable_nic(hw);
+			} while ((rtstatus != true)
+				 && (InitializeCount < 10));
+			RT_CLEAR_PS_LEVEL(ppsc,
+					  RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 ("Set ERFON sleeped:%d ms\n",
+				  jiffies_to_msecs(jiffies -
+						   ppsc->
+						   last_sleep_jiffies)));
+			ppsc->last_awake_jiffies = jiffies;
+			rtl92ce_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 == BEACON_QUEUE) {
+				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,
+					 ("\nERFOFF: %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;
+		_rtl92c_phy_set_rf_sleep(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		bresult = false;
+		break;
+	}
+	if (bresult)
+		ppsc->rfpwr_state = rfpwr_state;
+	ppsc->set_rfpowerstate_inprogress = false;
+	return bresult;
+}
+
+bool rtl92cu_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 = false;
+
+	if (rfpwr_state == ppsc->rfpwr_state)
+		return bresult;
+	bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state);
+	return bresult;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h
new file mode 100644
index 0000000..0629955
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/phy.h"
+
+void rtl92cu_bb_block_on(struct ieee80211_hw *hw);
+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath);
+void rtl92c_phy_set_io(struct ieee80211_hw *hw);
+bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
+bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h b/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h
new file mode 100644
index 0000000..7f1be61
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/reg.h"
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
new file mode 100644
index 0000000..1c79c22
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
@@ -0,0 +1,493 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+
+static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
+
+void rtl92cu_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) | 0x0400);
+		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));
+		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 rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+				       u8 *ppowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	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 = 0;
+	bool turbo_scanoff = false;
+	u8 idx1, idx2;
+	u8 *ptr;
+
+	if (rtlhal->interface == INTF_PCI) {
+		if (rtlefuse->eeprom_regulatory != 0)
+			turbo_scanoff = true;
+	} else {
+		if ((rtlefuse->eeprom_regulatory != 0) ||
+		    (rtlefuse->external_pa))
+			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] = ppowerlevel[idx1] |
+				    (ppowerlevel[idx1] << 8) |
+				    (ppowerlevel[idx1] << 16) |
+				    (ppowerlevel[idx1] << 24);
+				if (rtlhal->interface == INTF_USB) {
+					if (tx_agc[idx1] > 0x20 &&
+					    rtlefuse->external_pa)
+						tx_agc[idx1] = 0x20;
+				}
+			}
+		}
+	} else {
+		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+		    TXHIGHPWRLEVEL_LEVEL1) {
+			tx_agc[RF90_PATH_A] = 0x10101010;
+			tx_agc[RF90_PATH_B] = 0x10101010;
+		} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			   TXHIGHPWRLEVEL_LEVEL1) {
+			tx_agc[RF90_PATH_A] = 0x00000000;
+			tx_agc[RF90_PATH_B] = 0x00000000;
+		} else{
+			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+				tx_agc[idx1] = ppowerlevel[idx1] |
+				    (ppowerlevel[idx1] << 8) |
+				    (ppowerlevel[idx1] << 16) |
+				    (ppowerlevel[idx1] << 24);
+			}
+			if (rtlefuse->eeprom_regulatory == 0) {
+				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
+					[0][6]) +
+					(rtlphy->mcs_txpwrlevel_origoffset
+					[0][7] <<  8);
+				tx_agc[RF90_PATH_A] += tmpval;
+				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
+					[0][14]) +
+					(rtlphy->mcs_txpwrlevel_origoffset
+					[0][15] << 24);
+				tx_agc[RF90_PATH_B] += tmpval;
+			}
+		}
+	}
+	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+		ptr = (u8 *) (&(tx_agc[idx1]));
+		for (idx2 = 0; idx2 < 4; idx2++) {
+			if (*ptr > RF6052_MAX_TX_PWR)
+				*ptr = RF6052_MAX_TX_PWR;
+			ptr++;
+		}
+	}
+	tmpval = tx_agc[RF90_PATH_A] & 0xff;
+	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, 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;
+	if (mac->mode == WIRELESS_MODE_B)
+		tmpval = tmpval & 0xff00ffff;
+	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 rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
+				      u8 *ppowerlevel, u8 channel,
+				      u32 *ofdmbase, u32 *mcsbase)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 powerBase0, powerBase1;
+	u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
+	u8 i, powerlevel[2];
+
+	for (i = 0; i < 2; i++) {
+		powerlevel[i] = ppowerlevel[i];
+		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+		powerBase0 = powerlevel[i] + legacy_pwrdiff;
+		powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
+		    (powerBase0 << 8) | powerBase0;
+		*(ofdmbase + i) = powerBase0;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			(" [OFDM power base index rf(%c) = 0x%x]\n",
+			 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
+	}
+	for (i = 0; i < 2; i++) {
+		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+			powerlevel[i] += ht20_pwrdiff;
+		}
+		powerBase1 = powerlevel[i];
+		powerBase1 = (powerBase1 << 24) |
+		    (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
+		*(mcsbase + i) = powerBase1;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			(" [MCS power base index rf(%c) = 0x%x]\n",
+			 ((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
+	}
+}
+
+static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
+						       u8 channel, u8 index,
+						       u32 *powerBase0,
+						       u32 *powerBase1,
+						       u32 *p_outwriteval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 i, chnlgroup = 0, pwr_diff_limit[4];
+	u32 writeVal, customer_limit, rf;
+
+	for (rf = 0; rf < 2; rf++) {
+		switch (rtlefuse->eeprom_regulatory) {
+		case 0:
+			chnlgroup = 0;
+			writeVal = rtlphy->mcs_txpwrlevel_origoffset
+			    [chnlgroup][index + (rf ? 8 : 0)]
+			    + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("RTK better performance,writeVal(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		case 1:
+			if (rtlphy->pwrgroup_cnt == 1)
+				chnlgroup = 0;
+			if (rtlphy->pwrgroup_cnt >= 3) {
+				if (channel <= 3)
+					chnlgroup = 0;
+				else if (channel >= 4 && channel <= 9)
+					chnlgroup = 1;
+				else if (channel > 9)
+					chnlgroup = 2;
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20)
+					chnlgroup++;
+				else
+					chnlgroup += 4;
+			}
+			writeVal = rtlphy->mcs_txpwrlevel_origoffset
+					[chnlgroup][index +
+					(rf ? 8 : 0)] +
+					((index < 2) ? powerBase0[rf] :
+					powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Realtek regulatory, 20MHz, "
+				"writeVal(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		case 2:
+			writeVal = ((index < 2) ? powerBase0[rf] :
+				   powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Better regulatory,writeVal(%c) = 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		case 3:
+			chnlgroup = 0;
+			if (rtlphy->current_chan_bw ==
+			    HT_CHANNEL_WIDTH_20_40) {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("customer's limit, 40MHzrf(%c) = "
+					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht40[rf]
+					[channel - 1]));
+			} else {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("customer's limit, 20MHz rf(%c) = "
+					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht20[rf]
+					[channel - 1]));
+			}
+			for (i = 0; i < 4; i++) {
+				pwr_diff_limit[i] =
+				    (u8) ((rtlphy->mcs_txpwrlevel_origoffset
+				    [chnlgroup][index + (rf ? 8 : 0)]
+				    & (0x7f << (i * 8))) >> (i * 8));
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20_40) {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->pwrgroup_ht40[rf]
+						[channel - 1])
+						pwr_diff_limit[i] = rtlefuse->
+						    pwrgroup_ht40[rf]
+						    [channel - 1];
+				} else {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->pwrgroup_ht20[rf]
+						[channel - 1])
+						pwr_diff_limit[i] =
+						    rtlefuse->pwrgroup_ht20[rf]
+						    [channel - 1];
+				}
+			}
+			customer_limit = (pwr_diff_limit[3] << 24) |
+			    (pwr_diff_limit[2] << 16) |
+			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Customer's limit rf(%c) = 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), customer_limit));
+			writeVal = customer_limit + ((index < 2) ?
+				   powerBase0[rf] : powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Customer, writeVal rf(%c)= 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		default:
+			chnlgroup = 0;
+			writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+				   [index + (rf ? 8 : 0)] + ((index < 2) ?
+				   powerBase0[rf] : powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
+				"performance, writeValrf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		}
+		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+		    TXHIGHPWRLEVEL_LEVEL1)
+			writeVal = 0x14141414;
+		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			 TXHIGHPWRLEVEL_LEVEL2)
+			writeVal = 0x00000000;
+		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
+			writeVal = writeVal - 0x06060606;
+		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			 TXHIGHPWRLEVEL_BT2)
+			writeVal = writeVal;
+		*(p_outwriteval + rf) = writeVal;
+	}
+}
+
+static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
+					 u8 index, u32 *pValue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	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));
+		if (((get_rf_type(rtlphy) == RF_2T2R) &&
+		     (regoffset == RTXAGC_A_MCS15_MCS12 ||
+		      regoffset == RTXAGC_B_MCS15_MCS12)) ||
+		    ((get_rf_type(rtlphy) != RF_2T2R) &&
+		     (regoffset == RTXAGC_A_MCS07_MCS04 ||
+		      regoffset == RTXAGC_B_MCS07_MCS04))) {
+			writeVal = pwr_val[3];
+			if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+			    regoffset == RTXAGC_A_MCS07_MCS04)
+				regoffset = 0xc90;
+			if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+			    regoffset == RTXAGC_B_MCS07_MCS04)
+				regoffset = 0xc98;
+			for (i = 0; i < 3; i++) {
+				writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+				rtl_write_byte(rtlpriv, (u32)(regoffset + i),
+					      (u8)writeVal);
+			}
+		}
+	}
+}
+
+void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel, u8 channel)
+{
+	u32 writeVal[2], powerBase0[2], powerBase1[2];
+	u8 index = 0;
+
+	rtl92c_phy_get_power_base(hw, ppowerlevel,
+				  channel, &powerBase0[0], &powerBase1[0]);
+	for (index = 0; index < 6; index++) {
+		_rtl92c_get_txpower_writeval_by_regulatory(hw,
+							   channel, index,
+							   &powerBase0[0],
+							   &powerBase1[0],
+							   &writeVal[0]);
+		_rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
+	}
+}
+
+bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool rtstatus = true;
+	u8 b_reg_hwparafile = 1;
+
+	if (rtlphy->rf_type == RF_1T1R)
+		rtlphy->num_total_rfpath = 1;
+	else
+		rtlphy->num_total_rfpath = 2;
+	if (b_reg_hwparafile == 1)
+		rtstatus = _rtl92c_phy_rf6052_config_parafile(hw);
+	return rtstatus;
+}
+
+static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 u4_regvalue = 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:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV << 16);
+			break;
+		}
+		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+		udelay(1);
+		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+		udelay(1);
+		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 = rtl92cu_phy_config_rf_with_headerfile(hw,
+					(enum radio_path) rfpath);
+			break;
+		case RF90_PATH_B:
+			rtstatus = rtl92cu_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, u4_regvalue);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			rtl_set_bbreg(hw, pphyreg->rfintfs,
+				      BRFSI_RFENV << 16, u4_regvalue);
+			break;
+		}
+		if (rtstatus != true) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("Radio[%d] Fail!!", rfpath));
+			goto phy_rf_cfg_fail;
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
+	return rtstatus;
+phy_rf_cfg_fail:
+	return rtstatus;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
new file mode 100644
index 0000000..86c2728
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_RF_H__
+#define __RTL92CU_RF_H__
+
+#define RF6052_MAX_TX_PWR		0x3F
+#define RF6052_MAX_REG			0x3F
+#define RF6052_MAX_PATH			2
+
+extern void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+					    u8 bandwidth);
+extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					      u8 *ppowerlevel);
+extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					       u8 *ppowerlevel, u8 channel);
+bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
new file mode 100644
index 0000000..71244a3
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -0,0 +1,336 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * 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 "../usb.h"
+#include "../efuse.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "mac.h"
+#include "dm.h"
+#include "rf.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+#include "hw.h"
+#include <linux/vmalloc.h>
+
+MODULE_AUTHOR("Georgia		<georgia@realtek.com>");
+MODULE_AUTHOR("Ziv Huang	<ziv_huang@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless");
+MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");
+
+static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_initialgain_enable = 1;
+	rtlpriv->dm.dm_flag = 0;
+	rtlpriv->dm.disable_framebursting = 0;
+	rtlpriv->dm.thermalvalue = 0;
+	rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
+	if (!rtlpriv->rtlhal.pfirmware) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't alloc buffer for fw.\n"));
+		return 1;
+	}
+	return 0;
+}
+
+static void rtl92cu_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;
+	}
+}
+
+static struct rtl_hal_ops rtl8192cu_hal_ops = {
+	.init_sw_vars = rtl92cu_init_sw_vars,
+	.deinit_sw_vars = rtl92cu_deinit_sw_vars,
+	.read_chip_version = rtl92c_read_chip_version,
+	.read_eeprom_info = rtl92cu_read_eeprom_info,
+	.enable_interrupt = rtl92c_enable_interrupt,
+	.disable_interrupt = rtl92c_disable_interrupt,
+	.hw_init = rtl92cu_hw_init,
+	.hw_disable = rtl92cu_card_disable,
+	.set_network_type = rtl92cu_set_network_type,
+	.set_chk_bssid = rtl92cu_set_check_bssid,
+	.set_qos = rtl92c_set_qos,
+	.set_bcn_reg = rtl92cu_set_beacon_related_registers,
+	.set_bcn_intv = rtl92cu_set_beacon_interval,
+	.update_interrupt_mask = rtl92cu_update_interrupt_mask,
+	.get_hw_reg = rtl92cu_get_hw_reg,
+	.set_hw_reg = rtl92cu_set_hw_reg,
+	.update_rate_table = rtl92cu_update_hal_rate_table,
+	.update_rate_mask = rtl92cu_update_hal_rate_mask,
+	.fill_tx_desc = rtl92cu_tx_fill_desc,
+	.fill_fake_txdesc = rtl92cu_fill_fake_txdesc,
+	.fill_tx_cmddesc = rtl92cu_tx_fill_cmddesc,
+	.cmd_send_packet = rtl92cu_cmd_send_packet,
+	.query_rx_desc = rtl92cu_rx_query_desc,
+	.set_channel_access = rtl92cu_update_channel_access_setting,
+	.radio_onoff_checking = rtl92cu_gpio_radio_on_off_checking,
+	.set_bw_mode = rtl92c_phy_set_bw_mode,
+	.switch_channel = rtl92c_phy_sw_chnl,
+	.dm_watchdog = rtl92c_dm_watchdog,
+	.scan_operation_backup = rtl92c_phy_scan_operation_backup,
+	.set_rf_power_state = rtl92cu_phy_set_rf_power_state,
+	.led_control = rtl92cu_led_control,
+	.enable_hw_sec = rtl92cu_enable_hw_security_config,
+	.set_key = rtl92c_set_key,
+	.init_sw_leds = rtl92cu_init_sw_leds,
+	.deinit_sw_leds = rtl92cu_deinit_sw_leds,
+	.get_bbreg = rtl92c_phy_query_bb_reg,
+	.set_bbreg = rtl92c_phy_set_bb_reg,
+	.get_rfreg = rtl92cu_phy_query_rf_reg,
+	.set_rfreg = rtl92cu_phy_set_rf_reg,
+	.phy_rf6052_config = rtl92cu_phy_rf6052_config,
+	.phy_rf6052_set_cck_txpower = rtl92cu_phy_rf6052_set_cck_txpower,
+	.phy_rf6052_set_ofdm_txpower = rtl92cu_phy_rf6052_set_ofdm_txpower,
+	.config_bb_with_headerfile = _rtl92cu_phy_config_bb_with_headerfile,
+	.config_bb_with_pgheaderfile = _rtl92cu_phy_config_bb_with_pgheaderfile,
+	.phy_lc_calibrate = _rtl92cu_phy_lc_calibrate,
+	.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
+	.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
+};
+
+static struct rtl_mod_params rtl92cu_mod_params = {
+	.sw_crypto = 0,
+};
+
+static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = {
+	/* rx */
+	.in_ep_num = RTL92C_USB_BULK_IN_NUM,
+	.rx_urb_num = RTL92C_NUM_RX_URBS,
+	.rx_max_size = RTL92C_SIZE_MAX_RX_BUFFER,
+	.usb_rx_hdl = rtl8192cu_rx_hdl,
+	.usb_rx_segregate_hdl = NULL, /* rtl8192c_rx_segregate_hdl; */
+	/* tx */
+	.usb_tx_cleanup = rtl8192c_tx_cleanup,
+	.usb_tx_post_hdl = rtl8192c_tx_post_hdl,
+	.usb_tx_aggregate_hdl = rtl8192c_tx_aggregate_hdl,
+	/* endpoint mapping */
+	.usb_endpoint_mapping = rtl8192cu_endpoint_mapping,
+	.usb_mq_to_hwq = rtl8192cu_mq_to_hwq,
+};
+
+static struct rtl_hal_cfg rtl92cu_hal_cfg = {
+	.name = "rtl92c_usb",
+	.fw_name = "rtlwifi/rtl8192cufw.bin",
+	.ops = &rtl8192cu_hal_ops,
+	.mod_params = &rtl92cu_mod_params,
+	.usb_interface_cfg = &rtl92cu_interface_cfg,
+
+	.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_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] = EFUSE_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[RWCAM] = REG_CAMCMD,
+	.maps[WCAMI] = REG_CAMWRITE,
+	.maps[RCAMO] = REG_CAMREAD,
+	.maps[CAMDBG] = REG_CAMDBG,
+	.maps[SECR] = REG_SECCFG,
+	.maps[SEC_CAM_NONE] = CAM_NONE,
+	.maps[SEC_CAM_WEP40] = CAM_WEP40,
+	.maps[SEC_CAM_TKIP] = CAM_TKIP,
+	.maps[SEC_CAM_AES] = CAM_AES,
+	.maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+	.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+	.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+	.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+	.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+	.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+	.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+	.maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+	.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+	.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+	.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+	.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+	.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+	.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+	.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+	.maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+	.maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
+	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
+	.maps[RTL_IMR_BcnInt] = IMR_BCNINT,
+	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+	.maps[RTL_IMR_RDU] = IMR_RDU,
+	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+	.maps[RTL_IMR_BDOK] = IMR_BDOK,
+	.maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
+	.maps[RTL_IMR_TBDER] = IMR_TBDER,
+	.maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
+	.maps[RTL_IMR_TBDOK] = IMR_TBDOK,
+	.maps[RTL_IMR_BKDOK] = IMR_BKDOK,
+	.maps[RTL_IMR_BEDOK] = IMR_BEDOK,
+	.maps[RTL_IMR_VIDOK] = IMR_VIDOK,
+	.maps[RTL_IMR_VODOK] = IMR_VODOK,
+	.maps[RTL_IMR_ROK] = IMR_ROK,
+	.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
+
+	.maps[RTL_RC_CCK_RATE1M] = 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,
+};
+
+#define USB_VENDER_ID_REALTEK		0x0bda
+
+/* 2010-10-19 DID_USB_V3.4 */
+static struct usb_device_id rtl8192c_usb_ids[] = {
+
+	/*=== Realtek demoboard ===*/
+	/* Default ID */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)},
+
+	/****** 8188CU ********/
+	/* 8188CE-VAU USB minCard */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)},
+	/* 8188cu 1*1 dongle */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8176, rtl92cu_hal_cfg)},
+	/* 8188cu 1*1 dongle, (b/g mode only) */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)},
+	/* 8188cu Slim Solo */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817a, rtl92cu_hal_cfg)},
+	/* 8188cu Slim Combo */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)},
+	/* 8188RU High-power USB Dongle */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)},
+	/* 8188CE-VAU USB minCard (b/g mode only) */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)},
+	/* 8188 Combo for BC4 */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
+
+	/****** 8192CU ********/
+	/* 8191cu 1*2 */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)},
+	/* 8192cu 2*2 */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)},
+	/* 8192CE-VAU USB minCard */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)},
+
+	/*=== Customer ID ===*/
+	/****** 8188CU ********/
+	{RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/
+	{RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
+	{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
+	{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
+	{RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+	{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
+	/* HP - Lite-On ,8188CUS Slim Combo */
+	{RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
+	{RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/
+	{RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/
+	{RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/
+	{RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/
+	{RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/
+	{RTL_USB_DEVICE(0x3358, 0x13d3, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
+	/* Russian customer -Azwave (8188CE-VAU  b/g mode only) */
+	{RTL_USB_DEVICE(0x3359, 0x13d3, rtl92cu_hal_cfg)},
+
+	/****** 8192CU ********/
+	{RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/
+	{RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
+	{RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
+	{RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Abocom -Abocom*/
+	{RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
+	{RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+	{RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+	{RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
+	{RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids);
+
+static struct usb_driver rtl8192cu_driver = {
+	.name = "rtl8192cu",
+	.probe = rtl_usb_probe,
+	.disconnect = rtl_usb_disconnect,
+	.id_table = rtl8192c_usb_ids,
+
+#ifdef CONFIG_PM
+	/* .suspend = rtl_usb_suspend, */
+	/* .resume = rtl_usb_resume, */
+	/* .reset_resume = rtl8192c_resume, */
+#endif /* CONFIG_PM */
+#ifdef CONFIG_AUTOSUSPEND
+	.supports_autosuspend = 1,
+#endif
+};
+
+static int __init rtl8192cu_init(void)
+{
+	return usb_register(&rtl8192cu_driver);
+}
+
+static void __exit rtl8192cu_exit(void)
+{
+	usb_deregister(&rtl8192cu_driver);
+}
+
+module_init(rtl8192cu_init);
+module_exit(rtl8192cu_exit);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
new file mode 100644
index 0000000..43b1177
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_SW_H__
+#define __RTL92CU_SW_H__
+
+#define EFUSE_MAX_SECTION	16
+
+void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					u8 *powerlevel);
+void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel, u8 channel);
+bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+					    u8 configtype);
+bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+						    u8 configtype);
+void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
+void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
+			   enum radio_path rfpath,
+			   u32 regaddr, u32 bitmask, u32 data);
+bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
+				   enum rf_pwrstate rfpwr_state);
+u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
+			    enum radio_path rfpath, u32 regaddr, u32 bitmask);
+void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.c b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c
new file mode 100644
index 0000000..d57ef5e
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/table.c
@@ -0,0 +1,1888 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "table.h"
+
+u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = {
+	0x024, 0x0011800f,
+	0x028, 0x00ffdb83,
+	0x800, 0x80040002,
+	0x804, 0x00000003,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390004,
+	0x828, 0x01000100,
+	0x82c, 0x00390004,
+	0x830, 0x27272727,
+	0x834, 0x27272727,
+	0x838, 0x27272727,
+	0x83c, 0x27272727,
+	0x840, 0x00010000,
+	0x844, 0x00010000,
+	0x848, 0x27272727,
+	0x84c, 0x27272727,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569a569a,
+	0x85c, 0x0c1b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x27272727,
+	0x86c, 0x2b2b2b27,
+	0x870, 0x07000700,
+	0x874, 0x22184000,
+	0x878, 0x08080808,
+	0x87c, 0x00000000,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xcc0000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121313,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x1a1b0000,
+	0xa24, 0x090e1317,
+	0xa28, 0x00000204,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xc00, 0x48071d40,
+	0xc04, 0x03a05633,
+	0xc08, 0x000000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x6954341e,
+	0xc54, 0x43bc0094,
+	0xc58, 0x6954341e,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c7f000d,
+	0xc74, 0x0186115b,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b99612,
+	0xc80, 0x40000100,
+	0xc84, 0x20f60000,
+	0xc88, 0x40000100,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020403,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x2a2a2a2a,
+	0xe04, 0x2a2a2a2a,
+	0xe08, 0x03902a2a,
+	0xe10, 0x2a2a2a2a,
+	0xe14, 0x2a2a2a2a,
+	0xe18, 0x2a2a2a2a,
+	0xe1c, 0x2a2a2a2a,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000010,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x63db25a4,
+	0xe70, 0x63db25a4,
+	0xe74, 0x0c1b25a4,
+	0xe78, 0x0c1b25a4,
+	0xe7c, 0x0c1b25a4,
+	0xe80, 0x0c1b25a4,
+	0xe84, 0x63db25a4,
+	0xe88, 0x0c1b25a4,
+	0xe8c, 0x63db25a4,
+	0xed0, 0x63db25a4,
+	0xed4, 0x63db25a4,
+	0xed8, 0x63db25a4,
+	0xedc, 0x001b25a4,
+	0xee0, 0x001b25a4,
+	0xeec, 0x6fdb25a4,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = {
+	0x024, 0x0011800f,
+	0x028, 0x00ffdb83,
+	0x800, 0x80040000,
+	0x804, 0x00000001,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390004,
+	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, 0x569a569a,
+	0x85c, 0x001b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x00000000,
+	0x86c, 0x32323200,
+	0x870, 0x07000700,
+	0x874, 0x22004000,
+	0x878, 0x00000808,
+	0x87c, 0x00000000,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xccc000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121111,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x1a1b0000,
+	0xa24, 0x090e1317,
+	0xa28, 0x00000204,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xc00, 0x48071d40,
+	0xc04, 0x03a05611,
+	0xc08, 0x000000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x6954341e,
+	0xc54, 0x43bc0094,
+	0xc58, 0x6954341e,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c7f000d,
+	0xc74, 0x018610db,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b91612,
+	0xc80, 0x40000100,
+	0xc84, 0x20f60000,
+	0xc88, 0x40000100,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020401,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x2a2a2a2a,
+	0xe04, 0x2a2a2a2a,
+	0xe08, 0x03902a2a,
+	0xe10, 0x2a2a2a2a,
+	0xe14, 0x2a2a2a2a,
+	0xe18, 0x2a2a2a2a,
+	0xe1c, 0x2a2a2a2a,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000008,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x631b25a0,
+	0xe70, 0x631b25a0,
+	0xe74, 0x081b25a0,
+	0xe78, 0x081b25a0,
+	0xe7c, 0x081b25a0,
+	0xe80, 0x081b25a0,
+	0xe84, 0x631b25a0,
+	0xe88, 0x081b25a0,
+	0xe8c, 0x631b25a0,
+	0xed0, 0x631b25a0,
+	0xed4, 0x631b25a0,
+	0xed8, 0x631b25a0,
+	0xedc, 0x001b25a0,
+	0xee0, 0x001b25a0,
+	0xeec, 0x6b1b25a0,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH] = {
+	0xe00, 0xffffffff, 0x07090c0c,
+	0xe04, 0xffffffff, 0x01020405,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x0b0c0c0e,
+	0xe14, 0xffffffff, 0x01030506,
+	0xe18, 0xffffffff, 0x0b0c0d0e,
+	0xe1c, 0xffffffff, 0x01030509,
+	0x830, 0xffffffff, 0x07090c0c,
+	0x834, 0xffffffff, 0x01020405,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x0b0c0d0e,
+	0x848, 0xffffffff, 0x01030509,
+	0x84c, 0xffffffff, 0x0b0c0d0e,
+	0x868, 0xffffffff, 0x01030509,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x06060606,
+	0xe14, 0xffffffff, 0x00020406,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x06060606,
+	0x848, 0xffffffff, 0x00020406,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+};
+
+u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb1,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e52c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00010255,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x00000000,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x000577c0,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287af,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x00014297,
+	0x013, 0x00010295,
+	0x013, 0x0000c298,
+	0x013, 0x0000819c,
+	0x013, 0x000040a8,
+	0x013, 0x0000001c,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x015, 0x000cf424,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb1,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e52c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287af,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x00014297,
+	0x013, 0x00010295,
+	0x013, 0x0000c298,
+	0x013, 0x0000819c,
+	0x013, 0x000040a8,
+	0x013, 0x0000001c,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x015, 0x000cf424,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+};
+
+u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb1,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e52c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00010255,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x00000000,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x000577c0,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287b3,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x0001429b,
+	0x013, 0x00010299,
+	0x013, 0x0000c29c,
+	0x013, 0x000081a0,
+	0x013, 0x000040ac,
+	0x013, 0x00000020,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f405,
+	0x015, 0x0004f405,
+	0x015, 0x0008f405,
+	0x015, 0x000cf405,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH] = {
+	0x0,
+};
+
+u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = {
+	0x420, 0x00000080,
+	0x423, 0x00000000,
+	0x430, 0x00000000,
+	0x431, 0x00000000,
+	0x432, 0x00000000,
+	0x433, 0x00000001,
+	0x434, 0x00000004,
+	0x435, 0x00000005,
+	0x436, 0x00000006,
+	0x437, 0x00000007,
+	0x438, 0x00000000,
+	0x439, 0x00000000,
+	0x43a, 0x00000000,
+	0x43b, 0x00000001,
+	0x43c, 0x00000004,
+	0x43d, 0x00000005,
+	0x43e, 0x00000006,
+	0x43f, 0x00000007,
+	0x440, 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,
+	0x462, 0x00000008,
+	0x463, 0x00000003,
+	0x4c8, 0x000000ff,
+	0x4c9, 0x00000008,
+	0x4cc, 0x000000ff,
+	0x4cd, 0x000000ff,
+	0x4ce, 0x00000001,
+	0x500, 0x00000026,
+	0x501, 0x000000a2,
+	0x502, 0x0000002f,
+	0x503, 0x00000000,
+	0x504, 0x00000028,
+	0x505, 0x000000a3,
+	0x506, 0x0000005e,
+	0x507, 0x00000000,
+	0x508, 0x0000002b,
+	0x509, 0x000000a4,
+	0x50a, 0x0000005e,
+	0x50b, 0x00000000,
+	0x50c, 0x0000004f,
+	0x50d, 0x000000a4,
+	0x50e, 0x00000000,
+	0x50f, 0x00000000,
+	0x512, 0x0000001c,
+	0x514, 0x0000000a,
+	0x515, 0x00000010,
+	0x516, 0x0000000a,
+	0x517, 0x00000010,
+	0x51a, 0x00000016,
+	0x524, 0x0000000f,
+	0x525, 0x0000004f,
+	0x546, 0x00000040,
+	0x547, 0x00000000,
+	0x550, 0x00000010,
+	0x551, 0x00000010,
+	0x559, 0x00000002,
+	0x55a, 0x00000002,
+	0x55d, 0x000000ff,
+	0x605, 0x00000030,
+	0x608, 0x0000000e,
+	0x609, 0x0000002a,
+	0x652, 0x00000020,
+	0x63c, 0x0000000a,
+	0x63d, 0x0000000e,
+	0x63e, 0x0000000a,
+	0x63f, 0x0000000e,
+	0x66e, 0x00000005,
+	0x700, 0x00000021,
+	0x701, 0x00000043,
+	0x702, 0x00000065,
+	0x703, 0x00000087,
+	0x708, 0x00000021,
+	0x709, 0x00000043,
+	0x70a, 0x00000065,
+	0x70b, 0x00000087,
+};
+
+u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7a060001,
+	0xc78, 0x79070001,
+	0xc78, 0x78080001,
+	0xc78, 0x77090001,
+	0xc78, 0x760a0001,
+	0xc78, 0x750b0001,
+	0xc78, 0x740c0001,
+	0xc78, 0x730d0001,
+	0xc78, 0x720e0001,
+	0xc78, 0x710f0001,
+	0xc78, 0x70100001,
+	0xc78, 0x6f110001,
+	0xc78, 0x6e120001,
+	0xc78, 0x6d130001,
+	0xc78, 0x6c140001,
+	0xc78, 0x6b150001,
+	0xc78, 0x6a160001,
+	0xc78, 0x69170001,
+	0xc78, 0x68180001,
+	0xc78, 0x67190001,
+	0xc78, 0x661a0001,
+	0xc78, 0x651b0001,
+	0xc78, 0x641c0001,
+	0xc78, 0x631d0001,
+	0xc78, 0x621e0001,
+	0xc78, 0x611f0001,
+	0xc78, 0x60200001,
+	0xc78, 0x49210001,
+	0xc78, 0x48220001,
+	0xc78, 0x47230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7a460001,
+	0xc78, 0x79470001,
+	0xc78, 0x78480001,
+	0xc78, 0x77490001,
+	0xc78, 0x764a0001,
+	0xc78, 0x754b0001,
+	0xc78, 0x744c0001,
+	0xc78, 0x734d0001,
+	0xc78, 0x724e0001,
+	0xc78, 0x714f0001,
+	0xc78, 0x70500001,
+	0xc78, 0x6f510001,
+	0xc78, 0x6e520001,
+	0xc78, 0x6d530001,
+	0xc78, 0x6c540001,
+	0xc78, 0x6b550001,
+	0xc78, 0x6a560001,
+	0xc78, 0x69570001,
+	0xc78, 0x68580001,
+	0xc78, 0x67590001,
+	0xc78, 0x665a0001,
+	0xc78, 0x655b0001,
+	0xc78, 0x645c0001,
+	0xc78, 0x635d0001,
+	0xc78, 0x625e0001,
+	0xc78, 0x615f0001,
+	0xc78, 0x60600001,
+	0xc78, 0x49610001,
+	0xc78, 0x48620001,
+	0xc78, 0x47630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
+
+u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7a060001,
+	0xc78, 0x79070001,
+	0xc78, 0x78080001,
+	0xc78, 0x77090001,
+	0xc78, 0x760a0001,
+	0xc78, 0x750b0001,
+	0xc78, 0x740c0001,
+	0xc78, 0x730d0001,
+	0xc78, 0x720e0001,
+	0xc78, 0x710f0001,
+	0xc78, 0x70100001,
+	0xc78, 0x6f110001,
+	0xc78, 0x6e120001,
+	0xc78, 0x6d130001,
+	0xc78, 0x6c140001,
+	0xc78, 0x6b150001,
+	0xc78, 0x6a160001,
+	0xc78, 0x69170001,
+	0xc78, 0x68180001,
+	0xc78, 0x67190001,
+	0xc78, 0x661a0001,
+	0xc78, 0x651b0001,
+	0xc78, 0x641c0001,
+	0xc78, 0x631d0001,
+	0xc78, 0x621e0001,
+	0xc78, 0x611f0001,
+	0xc78, 0x60200001,
+	0xc78, 0x49210001,
+	0xc78, 0x48220001,
+	0xc78, 0x47230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7a460001,
+	0xc78, 0x79470001,
+	0xc78, 0x78480001,
+	0xc78, 0x77490001,
+	0xc78, 0x764a0001,
+	0xc78, 0x754b0001,
+	0xc78, 0x744c0001,
+	0xc78, 0x734d0001,
+	0xc78, 0x724e0001,
+	0xc78, 0x714f0001,
+	0xc78, 0x70500001,
+	0xc78, 0x6f510001,
+	0xc78, 0x6e520001,
+	0xc78, 0x6d530001,
+	0xc78, 0x6c540001,
+	0xc78, 0x6b550001,
+	0xc78, 0x6a560001,
+	0xc78, 0x69570001,
+	0xc78, 0x68580001,
+	0xc78, 0x67590001,
+	0xc78, 0x665a0001,
+	0xc78, 0x655b0001,
+	0xc78, 0x645c0001,
+	0xc78, 0x635d0001,
+	0xc78, 0x625e0001,
+	0xc78, 0x615f0001,
+	0xc78, 0x60600001,
+	0xc78, 0x49610001,
+	0xc78, 0x48620001,
+	0xc78, 0x47630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
+
+u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = {
+	0x024, 0x0011800f,
+	0x028, 0x00ffdb83,
+	0x040, 0x000c0004,
+	0x800, 0x80040000,
+	0x804, 0x00000001,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	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, 0x569a569a,
+	0x85c, 0x001b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x00000000,
+	0x86c, 0x20202000,
+	0x870, 0x03000300,
+	0x874, 0x22004000,
+	0x878, 0x00000808,
+	0x87c, 0x00ffc3f1,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xccc000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121111,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x15160000,
+	0xa24, 0x070b0f12,
+	0xa28, 0x00000104,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	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, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x6954342e,
+	0xc54, 0x43bc0094,
+	0xc58, 0x6954342f,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c46000d,
+	0xc74, 0x018610db,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b91612,
+	0xc80, 0x24000090,
+	0xc84, 0x20f60000,
+	0xc88, 0x24000090,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020401,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x24242424,
+	0xe04, 0x24242424,
+	0xe08, 0x03902024,
+	0xe10, 0x24242424,
+	0xe14, 0x24242424,
+	0xe18, 0x24242424,
+	0xe1c, 0x24242424,
+	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, 0x631b25a0,
+	0xe70, 0x631b25a0,
+	0xe74, 0x081b25a0,
+	0xe78, 0x081b25a0,
+	0xe7c, 0x081b25a0,
+	0xe80, 0x081b25a0,
+	0xe84, 0x631b25a0,
+	0xe88, 0x081b25a0,
+	0xe8c, 0x631b25a0,
+	0xed0, 0x631b25a0,
+	0xed4, 0x631b25a0,
+	0xed8, 0x631b25a0,
+	0xedc, 0x001b25a0,
+	0xee0, 0x001b25a0,
+	0xeec, 0x6b1b25a0,
+	0xee8, 0x31555448,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = {
+	0xe00, 0xffffffff, 0x06080808,
+	0xe04, 0xffffffff, 0x00040406,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x04060608,
+	0xe14, 0xffffffff, 0x00020204,
+	0xe18, 0xffffffff, 0x04060608,
+	0xe1c, 0xffffffff, 0x00020204,
+	0x830, 0xffffffff, 0x06080808,
+	0x834, 0xffffffff, 0x00040406,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x04060608,
+	0x848, 0xffffffff, 0x00020204,
+	0x84c, 0xffffffff, 0x04060608,
+	0x868, 0xffffffff, 0x00020204,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+};
+
+u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb0,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e529,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00000255,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x0000083c,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x000977c0,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x000d8000,
+	0x012, 0x00090000,
+	0x012, 0x00051000,
+	0x012, 0x00012000,
+	0x013, 0x00028fb4,
+	0x013, 0x00024fa8,
+	0x013, 0x000207a4,
+	0x013, 0x0001c798,
+	0x013, 0x000183a4,
+	0x013, 0x00014398,
+	0x013, 0x000101a4,
+	0x013, 0x0000c198,
+	0x013, 0x000080a4,
+	0x013, 0x00004098,
+	0x013, 0x00000000,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f405,
+	0x015, 0x0004f405,
+	0x015, 0x0008f405,
+	0x015, 0x000cf405,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7b060001,
+	0xc78, 0x7b070001,
+	0xc78, 0x7b080001,
+	0xc78, 0x7a090001,
+	0xc78, 0x790a0001,
+	0xc78, 0x780b0001,
+	0xc78, 0x770c0001,
+	0xc78, 0x760d0001,
+	0xc78, 0x750e0001,
+	0xc78, 0x740f0001,
+	0xc78, 0x73100001,
+	0xc78, 0x72110001,
+	0xc78, 0x71120001,
+	0xc78, 0x70130001,
+	0xc78, 0x6f140001,
+	0xc78, 0x6e150001,
+	0xc78, 0x6d160001,
+	0xc78, 0x6c170001,
+	0xc78, 0x6b180001,
+	0xc78, 0x6a190001,
+	0xc78, 0x691a0001,
+	0xc78, 0x681b0001,
+	0xc78, 0x671c0001,
+	0xc78, 0x661d0001,
+	0xc78, 0x651e0001,
+	0xc78, 0x641f0001,
+	0xc78, 0x63200001,
+	0xc78, 0x62210001,
+	0xc78, 0x61220001,
+	0xc78, 0x60230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7b460001,
+	0xc78, 0x7b470001,
+	0xc78, 0x7b480001,
+	0xc78, 0x7a490001,
+	0xc78, 0x794a0001,
+	0xc78, 0x784b0001,
+	0xc78, 0x774c0001,
+	0xc78, 0x764d0001,
+	0xc78, 0x754e0001,
+	0xc78, 0x744f0001,
+	0xc78, 0x73500001,
+	0xc78, 0x72510001,
+	0xc78, 0x71520001,
+	0xc78, 0x70530001,
+	0xc78, 0x6f540001,
+	0xc78, 0x6e550001,
+	0xc78, 0x6d560001,
+	0xc78, 0x6c570001,
+	0xc78, 0x6b580001,
+	0xc78, 0x6a590001,
+	0xc78, 0x695a0001,
+	0xc78, 0x685b0001,
+	0xc78, 0x675c0001,
+	0xc78, 0x665d0001,
+	0xc78, 0x655e0001,
+	0xc78, 0x645f0001,
+	0xc78, 0x63600001,
+	0xc78, 0x62610001,
+	0xc78, 0x61620001,
+	0xc78, 0x60630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/table.h b/drivers/net/wireless/rtlwifi/rtl8192cu/table.h
new file mode 100644
index 0000000..c3d5cd8
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/table.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_TABLE__H_
+#define __RTL92CU_TABLE__H_
+
+#include <linux/types.h>
+
+#define RTL8192CUPHY_REG_2TARRAY_LENGTH		374
+extern u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH];
+#define RTL8192CUPHY_REG_1TARRAY_LENGTH		374
+extern u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH];
+
+#define RTL8192CUPHY_REG_ARRAY_PGLENGTH		336
+extern u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH];
+
+#define RTL8192CURADIOA_2TARRAYLENGTH	282
+extern u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH];
+#define RTL8192CURADIOB_2TARRAYLENGTH	78
+extern u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH];
+#define RTL8192CURADIOA_1TARRAYLENGTH	282
+extern u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH];
+#define RTL8192CURADIOB_1TARRAYLENGTH	1
+extern u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH];
+
+#define RTL8192CUMAC_2T_ARRAYLENGTH		172
+extern u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH];
+
+#define RTL8192CUAGCTAB_2TARRAYLENGTH	320
+extern u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH];
+#define RTL8192CUAGCTAB_1TARRAYLENGTH	320
+extern u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH];
+
+#define RTL8192CUPHY_REG_1T_HPArrayLength 378
+extern u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength];
+
+#define RTL8192CUPHY_REG_Array_PG_HPLength 336
+extern u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength];
+
+#define RTL8192CURadioA_1T_HPArrayLength 282
+extern u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength];
+#define RTL8192CUAGCTAB_1T_HPArrayLength 320
+extern u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength];
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
new file mode 100644
index 0000000..d0b0d43
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
@@ -0,0 +1,687 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * 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 "../usb.h"
+#include "../ps.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "mac.h"
+#include "trx.h"
+
+static int _ConfigVerTOutEP(struct ieee80211_hw *hw)
+{
+	u8 ep_cfg, txqsele;
+	u8 ep_nums = 0;
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+
+	rtlusb->out_queue_sel = 0;
+	ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL);
+	ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT;
+	switch (ep_cfg)	{
+	case 0:		/* 2 bulk OUT, 1 bulk IN */
+	case 3:
+		rtlusb->out_queue_sel  = TX_SELE_HQ | TX_SELE_LQ;
+		ep_nums = 2;
+		break;
+	case 1:	/* 1 bulk IN/OUT => map all endpoint to Low queue */
+	case 2:	/* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */
+		txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS);
+		if (txqsele & 0x0F) /* /map all endpoint to High queue */
+			rtlusb->out_queue_sel =  TX_SELE_HQ;
+		else if (txqsele&0xF0) /* map all endpoint to Low queue */
+			rtlusb->out_queue_sel =  TX_SELE_LQ;
+		ep_nums = 1;
+		break;
+	default:
+		break;
+	}
+	return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
+}
+
+static int _ConfigVerNOutEP(struct ieee80211_hw *hw)
+{
+	u8 ep_cfg;
+	u8 ep_nums = 0;
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+
+	rtlusb->out_queue_sel = 0;
+	/* Normal and High queue */
+	ep_cfg =  rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1));
+	if (ep_cfg & USB_NORMAL_SIE_EP_MASK) {
+		rtlusb->out_queue_sel |= TX_SELE_HQ;
+		ep_nums++;
+	}
+	if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) {
+		rtlusb->out_queue_sel |= TX_SELE_NQ;
+		ep_nums++;
+	}
+	/* Low queue */
+	ep_cfg =  rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2));
+	if (ep_cfg & USB_NORMAL_SIE_EP_MASK) {
+		rtlusb->out_queue_sel |= TX_SELE_LQ;
+		ep_nums++;
+	}
+	return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
+}
+
+static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB,
+			     bool  bwificfg, struct rtl_ep_map *ep_map)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (bwificfg) { /* for WMM */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB Chip-B & WMM Setting.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VO] = 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	} else { /* typical setting */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB typical Setting.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	}
+}
+
+static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool  bwificfg,
+			       struct rtl_ep_map *ep_map)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	if (bwificfg) { /* for WMM */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB 3EP Setting for WMM.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 5;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	} else { /* typical setting */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB 3EP Setting for typical.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 5;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 5;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	}
+}
+
+static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
+{
+	ep_map->ep_mapping[RTL_TXQ_BE]	= 2;
+	ep_map->ep_mapping[RTL_TXQ_BK]	= 2;
+	ep_map->ep_mapping[RTL_TXQ_VI]	= 2;
+	ep_map->ep_mapping[RTL_TXQ_VO] = 2;
+	ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+	ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+	ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+}
+static int _out_ep_mapping(struct ieee80211_hw *hw)
+{
+	int err = 0;
+	bool bIsChipN, bwificfg = false;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+	struct rtl_ep_map *ep_map = &(rtlusb->ep_map);
+
+	bIsChipN = IS_NORMAL_CHIP(rtlhal->version);
+	switch (rtlusb->out_ep_nums) {
+	case 2:
+		_TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map);
+		break;
+	case 3:
+		/* Test chip doesn't support three out EPs. */
+		if (!bIsChipN) {
+			err  =  -EINVAL;
+			goto err_out;
+		}
+		_ThreeOutEpMapping(hw, bIsChipN, ep_map);
+		break;
+	case 1:
+		_OneOutEpMapping(hw, ep_map);
+		break;
+	default:
+		err  =  -EINVAL;
+		break;
+	}
+err_out:
+	return err;
+
+}
+/* endpoint mapping */
+int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	int error = 0;
+	if (likely(IS_NORMAL_CHIP(rtlhal->version)))
+		error = _ConfigVerNOutEP(hw);
+	else
+		error = _ConfigVerTOutEP(hw);
+	if (error)
+		goto err_out;
+	error = _out_ep_mapping(hw);
+	if (error)
+		goto err_out;
+err_out:
+	return error;
+}
+
+u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index)
+{
+	u16 hw_queue_index;
+
+	if (unlikely(ieee80211_is_beacon(fc))) {
+		hw_queue_index = RTL_TXQ_BCN;
+		goto out;
+	}
+	if (ieee80211_is_mgmt(fc)) {
+		hw_queue_index = RTL_TXQ_MGT;
+		goto out;
+	}
+	switch (mac80211_queue_index) {
+	case 0:
+		hw_queue_index = RTL_TXQ_VO;
+		break;
+	case 1:
+		hw_queue_index = RTL_TXQ_VI;
+		break;
+	case 2:
+		hw_queue_index = RTL_TXQ_BE;
+		break;
+	case 3:
+		hw_queue_index = RTL_TXQ_BK;
+		break;
+	default:
+		hw_queue_index = RTL_TXQ_BE;
+		RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n",
+			  mac80211_queue_index));
+		break;
+	}
+out:
+	return hw_queue_index;
+}
+
+static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw,
+					 __le16 fc, u16 mac80211_queue_index)
+{
+	enum rtl_desc_qsel qsel;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (unlikely(ieee80211_is_beacon(fc))) {
+		qsel = QSLT_BEACON;
+		goto out;
+	}
+	if (ieee80211_is_mgmt(fc)) {
+		qsel = QSLT_MGNT;
+		goto out;
+	}
+	switch (mac80211_queue_index) {
+	case 0:	/* VO */
+		qsel = QSLT_VO;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("VO queue, set qsel = 0x%x\n", QSLT_VO));
+		break;
+	case 1:	/* VI */
+		qsel = QSLT_VI;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("VI queue, set qsel = 0x%x\n", QSLT_VI));
+		break;
+	case 3:	/* BK */
+		qsel = QSLT_BK;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("BK queue, set qsel = 0x%x\n", QSLT_BK));
+		break;
+	case 2:	/* BE */
+	default:
+		qsel = QSLT_BE;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("BE queue, set qsel = 0x%x\n", QSLT_BE));
+		break;
+	}
+out:
+	return qsel;
+}
+
+/* =============================================================== */
+
+/*----------------------------------------------------------------------
+ *
+ *	Rx handler
+ *
+ *---------------------------------------------------------------------- */
+bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *stats,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *p_desc, struct sk_buff *skb)
+{
+	struct rx_fwinfo_92c *p_drvinfo;
+	struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+	u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc);
+
+	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+	stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) *
+				 RX_DRV_INFO_SIZE_UNIT;
+	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	stats->hwerror = (stats->crc | stats->icv);
+	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+	stats->rate = (u8) GET_RX_DESC_RX_MCS(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)
+				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
+	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+	if (GET_RX_DESC_CRC32(pdesc))
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+	if (!GET_RX_DESC_SWDEC(pdesc))
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	if (GET_RX_DESC_BW(pdesc))
+		rx_status->flag |= RX_FLAG_40MHZ;
+	if (GET_RX_DESC_RX_HT(pdesc))
+		rx_status->flag |= RX_FLAG_HT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	if (stats->decrypted)
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	rx_status->rate_idx = _rtl92c_rate_mapping(hw,
+						(bool)GET_RX_DESC_RX_HT(pdesc),
+						(u8)GET_RX_DESC_RX_MCS(pdesc),
+						(bool)GET_RX_DESC_PAGGR(pdesc));
+	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
+	if (phystatus == true) {
+		p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
+		rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
+						 p_drvinfo);
+	}
+	/*rx_status->qual = stats->signal; */
+	rx_status->signal = stats->rssi + 10;
+	/*rx_status->noise = -stats->noise; */
+	return true;
+}
+
+#define RTL_RX_DRV_INFO_UNIT		8
+
+static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ieee80211_rx_status *rx_status =
+		 (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb);
+	u32 skb_len, pkt_len, drvinfo_len;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *rxdesc;
+	struct rtl_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+	};
+	struct rx_fwinfo_92c *p_drvinfo;
+	bool bv;
+	__le16 fc;
+	struct ieee80211_hdr *hdr;
+
+	memset(rx_status, 0, sizeof(rx_status));
+	rxdesc	= skb->data;
+	skb_len	= skb->len;
+	drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT);
+	pkt_len		= GET_RX_DESC_PKT_LEN(rxdesc);
+	/* TODO: Error recovery. drop this skb or something. */
+	WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len));
+	stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc);
+	stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) *
+				RX_DRV_INFO_SIZE_UNIT;
+	stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03);
+	stats.icv = (u16) GET_RX_DESC_ICV(rxdesc);
+	stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc);
+	stats.hwerror = (stats.crc | stats.icv);
+	stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc);
+	stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc);
+	stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc);
+	stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1)
+				   && (GET_RX_DESC_FAGGR(rxdesc) == 1));
+	stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc);
+	stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc);
+	/* TODO: is center_freq changed when doing scan? */
+	/* TODO: Shall we add protection or just skip those two step? */
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+	if (GET_RX_DESC_CRC32(rxdesc))
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+	if (!GET_RX_DESC_SWDEC(rxdesc))
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	if (GET_RX_DESC_BW(rxdesc))
+		rx_status->flag |= RX_FLAG_40MHZ;
+	if (GET_RX_DESC_RX_HT(rxdesc))
+		rx_status->flag |= RX_FLAG_HT;
+	/* Data rate */
+	rx_status->rate_idx = _rtl92c_rate_mapping(hw,
+						(bool)GET_RX_DESC_RX_HT(rxdesc),
+						(u8)GET_RX_DESC_RX_MCS(rxdesc),
+						(bool)GET_RX_DESC_PAGGR(rxdesc)
+						);
+	/*  There is a phy status after this rx descriptor. */
+	if (GET_RX_DESC_PHY_STATUS(rxdesc)) {
+		p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE);
+		rtl92c_translate_rx_signal_stuff(hw, skb, &stats,
+				 (struct rx_desc_92c *)rxdesc, p_drvinfo);
+	}
+	skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE));
+	hdr = (struct ieee80211_hdr *)(skb->data);
+	fc = hdr->frame_control;
+	bv = ieee80211_is_probe_resp(fc);
+	if (bv)
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("Got probe response frame.\n"));
+	if (ieee80211_is_beacon(fc))
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("Got beacon frame.\n"));
+	if (ieee80211_is_data(fc))
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Got data frame.\n"));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 ("Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:"
+		 "0x%02X\n", fc, (u32)hdr->addr1[0], (u32)hdr->addr1[1],
+		 (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);
+}
+
+void  rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb)
+{
+	_rtl_rx_process(hw, skb);
+}
+
+void rtl8192c_rx_segregate_hdl(
+	struct ieee80211_hw *hw,
+	struct sk_buff *skb,
+	struct sk_buff_head *skb_list)
+{
+}
+
+/*----------------------------------------------------------------------
+ *
+ *	Tx handler
+ *
+ *---------------------------------------------------------------------- */
+void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff  *skb)
+{
+}
+
+int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb,
+			 struct sk_buff *skb)
+{
+	return 0;
+}
+
+struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw,
+					   struct sk_buff_head *list)
+{
+	return skb_dequeue(list);
+}
+
+/*======================================== trx ===============================*/
+
+static void _rtl_fill_usb_tx_desc(u8 *txdesc)
+{
+	SET_TX_DESC_OWN(txdesc, 1);
+	SET_TX_DESC_LAST_SEG(txdesc, 1);
+	SET_TX_DESC_FIRST_SEG(txdesc, 1);
+}
+/**
+ *	For HW recovery information
+ */
+static void _rtl_tx_desc_checksum(u8 *txdesc)
+{
+	u16 *ptr = (u16 *)txdesc;
+	u16	checksum = 0;
+	u32 index;
+
+	/* Clear first */
+	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
+	for (index = 0; index < 16; index++)
+		checksum = checksum ^ (*(ptr + index));
+	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
+}
+
+void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info, struct sk_buff *skb,
+			  unsigned int queue_index)
+{
+	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));
+	bool defaultadapter = true;
+	struct ieee80211_sta *sta;
+	struct rtl_tcb_desc tcb_desc;
+	u8 *qc = ieee80211_get_qos_ctl(hdr);
+	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+	u16 seq_number;
+	__le16 fc = hdr->frame_control;
+	u8 rate_flag = info->control.rates[0].flags;
+	u16 pktlen = skb->len;
+	enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc,
+						skb_get_queue_mapping(skb));
+	u8 *txdesc;
+
+	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+	rtl_get_tcb_desc(hw, info, skb, &tcb_desc);
+	txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE);
+	memset(txdesc, 0, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_PKT_SIZE(txdesc, pktlen);
+	SET_TX_DESC_LINIP(txdesc, 0);
+	SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET);
+	SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate);
+	if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble)
+		SET_TX_DESC_DATA_SHORTGI(txdesc, 1);
+	if (mac->tids[tid].agg.agg_state == RTL_AGG_ON &&
+		    info->flags & IEEE80211_TX_CTL_AMPDU) {
+		SET_TX_DESC_AGG_ENABLE(txdesc, 1);
+		SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14);
+	} else {
+		SET_TX_DESC_AGG_BREAK(txdesc, 1);
+	}
+	SET_TX_DESC_SEQ(txdesc, seq_number);
+	SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable &&
+			       !tcb_desc.cts_enable) ? 1 : 0));
+	SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable ||
+				  tcb_desc.cts_enable) ? 1 : 0));
+	SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0));
+	SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0));
+	SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate);
+	SET_TX_DESC_RTS_BW(txdesc, 0);
+	SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc);
+	SET_TX_DESC_RTS_SHORT(txdesc,
+			      ((tcb_desc.rts_rate <= DESC92C_RATE54M) ?
+			       (tcb_desc.rts_use_shortpreamble ? 1 : 0)
+			       : (tcb_desc.rts_use_shortgi ? 1 : 0)));
+	if (mac->bw_40) {
+		if (tcb_desc.packet_bw) {
+			SET_TX_DESC_DATA_BW(txdesc, 1);
+			SET_TX_DESC_DATA_SC(txdesc, 3);
+		} else {
+			SET_TX_DESC_DATA_BW(txdesc, 0);
+				if (rate_flag & IEEE80211_TX_RC_DUP_DATA)
+					SET_TX_DESC_DATA_SC(txdesc,
+							  mac->cur_40_prime_sc);
+			}
+	} else {
+		SET_TX_DESC_DATA_BW(txdesc, 0);
+		SET_TX_DESC_DATA_SC(txdesc, 0);
+	}
+	rcu_read_lock();
+	sta = ieee80211_find_sta(mac->vif, mac->bssid);
+	if (sta) {
+		u8 ampdu_density = sta->ht_cap.ampdu_density;
+		SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density);
+	}
+	rcu_read_unlock();
+	if (info->control.hw_key) {
+		struct ieee80211_key_conf *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(txdesc, 0x1);
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			SET_TX_DESC_SEC_TYPE(txdesc, 0x3);
+			break;
+		default:
+			SET_TX_DESC_SEC_TYPE(txdesc, 0x0);
+			break;
+		}
+	}
+	SET_TX_DESC_PKT_ID(txdesc, 0);
+	SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel);
+	SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F);
+	SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF);
+	SET_TX_DESC_DISABLE_FB(txdesc, 0);
+	SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0);
+	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(txdesc, 1);
+			SET_TX_DESC_HTC(txdesc, 1);
+		}
+	}
+	if (rtlpriv->dm.useramask) {
+		SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index);
+		SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id);
+	} else {
+		SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index);
+		SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index);
+	}
+	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
+	      ppsc->fwctrl_lps) {
+		SET_TX_DESC_HWSEQ_EN(txdesc, 1);
+		SET_TX_DESC_PKT_ID(txdesc, 8);
+		if (!defaultadapter)
+			SET_TX_DESC_QOS(txdesc, 1);
+	}
+	if (ieee80211_has_morefrags(fc))
+		SET_TX_DESC_MORE_FRAG(txdesc, 1);
+	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
+	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
+		SET_TX_DESC_BMC(txdesc, 1);
+	_rtl_fill_usb_tx_desc(txdesc);
+	_rtl_tx_desc_checksum(txdesc);
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, (" %s ==>\n", __func__));
+}
+
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
+			      u32 buffer_len, bool bIsPsPoll)
+{
+	/* Clear all status */
+	memset(pDesc, 0, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */
+	SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */
+	SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
+	SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */
+	SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
+	/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error
+	 * vlaue by Hw. */
+	if (bIsPsPoll) {
+		SET_TX_DESC_NAV_USE_HDR(pDesc, 1);
+	} else {
+		SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */
+		SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */
+	}
+	SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */
+	SET_TX_DESC_OWN(pDesc, 1);
+	SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M);
+	_rtl_tx_desc_checksum(pDesc);
+}
+
+void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
+			     u8 *pdesc, bool firstseg,
+			     bool lastseg, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 fw_queue = QSLT_BEACON;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+
+	memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
+	if (firstseg)
+		SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE);
+	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_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);
+		SET_TX_DESC_PKT_ID(pdesc, 8);
+	}
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content\n",
+		      pdesc, RTL_TX_DESC_SIZE);
+}
+
+bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	return true;
+}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h
new file mode 100644
index 0000000..b396d46
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h
@@ -0,0 +1,430 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_TRX_H__
+#define __RTL92CU_TRX_H__
+
+#define RTL92C_USB_BULK_IN_NUM			1
+#define RTL92C_NUM_RX_URBS			8
+#define RTL92C_NUM_TX_URBS			32
+
+#define RTL92C_SIZE_MAX_RX_BUFFER		15360   /* 8192 */
+#define RX_DRV_INFO_SIZE_UNIT			8
+
+enum usb_rx_agg_mode {
+	USB_RX_AGG_DISABLE,
+	USB_RX_AGG_DMA,
+	USB_RX_AGG_USB,
+	USB_RX_AGG_DMA_USB
+};
+
+#define TX_SELE_HQ				BIT(0)	/* High Queue */
+#define TX_SELE_LQ				BIT(1)	/* Low Queue */
+#define TX_SELE_NQ				BIT(2)	/* Normal Queue */
+
+#define RTL_USB_TX_AGG_NUM_DESC			5
+
+#define RTL_USB_RX_AGG_PAGE_NUM			4
+#define RTL_USB_RX_AGG_PAGE_TIMEOUT		3
+
+#define RTL_USB_RX_AGG_BLOCK_NUM		5
+#define RTL_USB_RX_AGG_BLOCK_TIMEOUT		3
+
+/*======================== rx status =========================================*/
+
+struct rx_drv_info_92c {
+	/*
+	 * Driver info contain PHY status and other variabel size info
+	 * PHY Status content as below
+	 */
+
+	/* DWORD 0 */
+	u8 gain_trsw[4];
+
+	/* DWORD 1 */
+	u8 pwdb_all;
+	u8 cfosho[4];
+
+	/* DWORD 2 */
+	u8 cfotail[4];
+
+	/* DWORD 3 */
+	s8 rxevm[2];
+	s8 rxsnr[4];
+
+	/* DWORD 4 */
+	u8 pdsnr[2];
+
+	/* DWORD 5 */
+	u8 csi_current[2];
+	u8 csi_target[2];
+
+	/* DWORD 6 */
+	u8 sigevm;
+	u8 max_ex_pwr;
+	u8 ex_intf_flag:1;
+	u8 sgi_en:1;
+	u8 rxsc:2;
+	u8 reserve:4;
+} __packed;
+
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __bits)		\
+	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\
+	BIT_LEN_MASK_32(__bits))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val)	\
+	(*(__le32 *)(__pdesc) = 				\
+	(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) &	\
+	(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) |		\
+	(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read various fields in RX descriptor */
+
+/* DWORD 0 */
+#define GET_RX_DESC_PKT_LEN(__rxdesc)		\
+	SHIFT_AND_MASK_LE((__rxdesc), 0, 14)
+#define GET_RX_DESC_CRC32(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 14, 1)
+#define GET_RX_DESC_ICV(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 15, 1)
+#define GET_RX_DESC_DRVINFO_SIZE(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 20, 3)
+#define GET_RX_DESC_QOS(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 24, 2)
+#define GET_RX_DESC_PHY_STATUS(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 27, 1)
+#define GET_RX_DESC_LAST_SEG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 28, 1)
+#define GET_RX_DESC_FIRST_SEG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 29, 1)
+#define GET_RX_DESC_EOR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 30, 1)
+#define GET_RX_DESC_OWN(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 31, 1)
+
+/* DWORD 1 */
+#define GET_RX_DESC_MACID(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 5, 4)
+#define GET_RX_DESC_PAGGR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 25, 1)
+#define GET_RX_DESC_MORE_DATA(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 26, 1)
+#define GET_RX_DESC_MORE_FRAG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 31, 1)
+
+/* DWORD 2 */
+#define GET_RX_DESC_SEQ(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 12, 4)
+#define GET_RX_DESC_USB_AGG_PKTNUM(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 16, 8)
+#define GET_RX_DESC_NEXT_IND(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 30, 1)
+
+/* DWORD 3 */
+#define GET_RX_DESC_RX_MCS(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 0, 6)
+#define GET_RX_DESC_RX_HT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 6, 1)
+#define GET_RX_DESC_AMSDU(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 7, 1)
+#define GET_RX_DESC_SPLCP(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 10, 1)
+#define GET_RX_DESC_TCP_CHK_RPT(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 11, 1)
+#define GET_RX_DESC_IP_CHK_RPT(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 12, 1)
+#define GET_RX_DESC_TCP_CHK_VALID(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 13, 1)
+#define GET_RX_DESC_HWPC_ERR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 16, 16)
+
+/* DWORD 4 */
+#define GET_RX_DESC_IV1(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+16, 0, 32)
+
+/* DWORD 5 */
+#define GET_RX_DESC_TSFL(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+20, 0, 32)
+
+/*======================= tx desc ============================================*/
+
+/* macros to set various fields in TX descriptor */
+
+/* Dword 0 */
+#define SET_TX_DESC_PKT_SIZE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 0, 16, __value)
+#define SET_TX_DESC_OFFSET(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 16, 8, __value)
+#define SET_TX_DESC_BMC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 24, 1, __value)
+#define SET_TX_DESC_HTC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 25, 1, __value)
+#define SET_TX_DESC_LAST_SEG(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 26, 1, __value)
+#define SET_TX_DESC_FIRST_SEG(__txdesc, __value)	\
+	 SET_BITS_OFFSET_LE(__txdesc, 27, 1, __value)
+#define SET_TX_DESC_LINIP(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 28, 1, __value)
+#define SET_TX_DESC_NO_ACM(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 29, 1, __value)
+#define SET_TX_DESC_GF(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 30, 1, __value)
+#define SET_TX_DESC_OWN(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 31, 1, __value)
+
+
+/* Dword 1 */
+#define SET_TX_DESC_MACID(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 0, 5, __value)
+#define SET_TX_DESC_AGG_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 5, 1, __value)
+#define SET_TX_DESC_AGG_BREAK(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 6, 1, __value)
+#define SET_TX_DESC_RDG_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 7, 1, __value)
+#define SET_TX_DESC_QUEUE_SEL(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 8, 5, __value)
+#define SET_TX_DESC_RDG_NAV_EXT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 13, 1, __value)
+#define SET_TX_DESC_LSIG_TXOP_EN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 14, 1, __value)
+#define SET_TX_DESC_PIFS(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 15, 1, __value)
+#define SET_TX_DESC_RATE_ID(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value)
+#define SET_TX_DESC_RA_BRSR_ID(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value)
+#define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 20, 1, __value)
+#define SET_TX_DESC_EN_DESC_ID(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 21, 1, __value)
+#define SET_TX_DESC_SEC_TYPE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 22, 2, __value)
+#define SET_TX_DESC_PKT_OFFSET(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 26, 5, __value)
+
+/* Dword 2 */
+#define SET_TX_DESC_RTS_RC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 0, 6, __value)
+#define SET_TX_DESC_DATA_RC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 6, 6, __value)
+#define SET_TX_DESC_BAR_RTY_TH(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 14, 2, __value)
+#define SET_TX_DESC_MORE_FRAG(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 17, 1, __value)
+#define SET_TX_DESC_RAW(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 18, 1, __value)
+#define SET_TX_DESC_CCX(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 19, 1, __value)
+#define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 20, 3, __value)
+#define SET_TX_DESC_ANTSEL_A(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 24, 1, __value)
+#define SET_TX_DESC_ANTSEL_B(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 25, 1, __value)
+#define SET_TX_DESC_TX_ANT_CCK(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 26, 2, __value)
+#define SET_TX_DESC_TX_ANTL(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 28, 2, __value)
+#define SET_TX_DESC_TX_ANT_HT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 30, 2, __value)
+
+/* Dword 3 */
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+12, 0, 8, __value)
+#define SET_TX_DESC_TAIL_PAGE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+12, 8, 8, __value)
+#define SET_TX_DESC_SEQ(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+12, 16, 12, __value)
+#define SET_TX_DESC_PKT_ID(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+12, 28, 4, __value)
+
+/* Dword 4 */
+#define SET_TX_DESC_RTS_RATE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 0, 5, __value)
+#define SET_TX_DESC_AP_DCFE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 5, 1, __value)
+#define SET_TX_DESC_QOS(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 6, 1, __value)
+#define SET_TX_DESC_HWSEQ_EN(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 7, 1, __value)
+#define SET_TX_DESC_USE_RATE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 8, 1, __value)
+#define SET_TX_DESC_DISABLE_RTS_FB(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 9, 1, __value)
+#define SET_TX_DESC_DISABLE_FB(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 10, 1, __value)
+#define SET_TX_DESC_CTS2SELF(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 11, 1, __value)
+#define SET_TX_DESC_RTS_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 12, 1, __value)
+#define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 13, 1, __value)
+#define SET_TX_DESC_WAIT_DCTS(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 18, 1, __value)
+#define SET_TX_DESC_CTS2AP_EN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 19, 1, __value)
+#define SET_TX_DESC_DATA_SC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 20, 2, __value)
+#define SET_TX_DESC_DATA_STBC(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 22, 2, __value)
+#define SET_TX_DESC_DATA_SHORT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 24, 1, __value)
+#define SET_TX_DESC_DATA_BW(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 25, 1, __value)
+#define SET_TX_DESC_RTS_SHORT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 26, 1, __value)
+#define SET_TX_DESC_RTS_BW(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 27, 1, __value)
+#define SET_TX_DESC_RTS_SC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 28, 2, __value)
+#define SET_TX_DESC_RTS_STBC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 30, 2, __value)
+
+/* Dword 5 */
+#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+20, 8, 5, __value)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+20, 13, 4, __value)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+20, 17, 1, __value)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+20, 18, 6, __value)
+#define SET_TX_DESC_USB_TXAGG_NUM(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+20, 24, 8, __value)
+
+/* Dword 6 */
+#define SET_TX_DESC_TXAGC_A(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+24, 0, 5, __value)
+#define SET_TX_DESC_TXAGC_B(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+24, 5, 5, __value)
+#define SET_TX_DESC_USB_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 10, 1, __value)
+#define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 11, 5, __value)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 16, 4, __value)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 20, 4, __value)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 24, 4, __value)
+#define SET_TX_DESC_MCSG7_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 28, 4, __value)
+
+/* Dword 7 */
+#define SET_TX_DESC_TX_DESC_CHECKSUM(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+28, 0, 16, __value)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 16, 4, __value)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 20, 4, __value)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 24, 4, __value)
+#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 28, 4, __value)
+
+
+int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
+u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
+bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *stats,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *p_desc, struct sk_buff *skb);
+void  rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb);
+void rtl8192c_rx_segregate_hdl(struct ieee80211_hw *, struct sk_buff *,
+			       struct sk_buff_head *);
+void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff  *skb);
+int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb,
+			 struct sk_buff *skb);
+struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *,
+					   struct sk_buff_head *);
+void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info, struct sk_buff *skb,
+			  unsigned int queue_index);
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
+			      u32 buffer_len, bool bIsPsPoll);
+void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
+			     u8 *pdesc, bool b_firstseg,
+			     bool b_lastseg, struct sk_buff *skb);
+bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
new file mode 100644
index 0000000..a4b2613
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -0,0 +1,1035 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2011  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+#include <linux/usb.h>
+#include "core.h"
+#include "wifi.h"
+#include "usb.h"
+#include "base.h"
+#include "ps.h"
+
+#define	REALTEK_USB_VENQT_READ			0xC0
+#define	REALTEK_USB_VENQT_WRITE			0x40
+#define REALTEK_USB_VENQT_CMD_REQ		0x05
+#define	REALTEK_USB_VENQT_CMD_IDX		0x00
+
+#define REALTEK_USB_VENQT_MAX_BUF_SIZE		254
+
+static void usbctrl_async_callback(struct urb *urb)
+{
+	if (urb)
+		kfree(urb->context);
+}
+
+static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
+					  u16 value, u16 index, void *pdata,
+					  u16 len)
+{
+	int rc;
+	unsigned int pipe;
+	u8 reqtype;
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
+	struct rtl819x_async_write_data {
+		u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE];
+		struct usb_ctrlrequest dr;
+	} *buf;
+
+	pipe = usb_sndctrlpipe(udev, 0); /* write_out */
+	reqtype =  REALTEK_USB_VENQT_WRITE;
+
+	buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	dr = &buf->dr;
+
+	dr->bRequestType = reqtype;
+	dr->bRequest = request;
+	dr->wValue = cpu_to_le16(value);
+	dr->wIndex = cpu_to_le16(index);
+	dr->wLength = cpu_to_le16(len);
+	memcpy(buf, pdata, len);
+	usb_fill_control_urb(urb, udev, pipe,
+			     (unsigned char *)dr, buf, len,
+			     usbctrl_async_callback, buf);
+	rc = usb_submit_urb(urb, GFP_ATOMIC);
+	if (rc < 0)
+		kfree(buf);
+	usb_free_urb(urb);
+	return rc;
+}
+
+static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
+					u16 value, u16 index, void *pdata,
+					u16 len)
+{
+	unsigned int pipe;
+	int status;
+	u8 reqtype;
+
+	pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
+	reqtype =  REALTEK_USB_VENQT_READ;
+
+	status = usb_control_msg(udev, pipe, request, reqtype, value, index,
+				 pdata, len, 0); /* max. timeout */
+
+	if (status < 0)
+		printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! "
+		       "status:0x%x value=0x%x\n", value, status,
+		       *(u32 *)pdata);
+	return status;
+}
+
+static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+{
+	u8 request;
+	u16 wvalue;
+	u16 index;
+	u32 *data;
+	u32 ret;
+
+	data = kmalloc(sizeof(u32), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	request = REALTEK_USB_VENQT_CMD_REQ;
+	index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
+
+	wvalue = (u16)addr;
+	_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
+	ret = *data;
+	kfree(data);
+	return ret;
+}
+
+static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+}
+
+static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+}
+
+static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return _usb_read_sync(to_usb_device(dev), addr, 4);
+}
+
+static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
+			     u16 len)
+{
+	u8 request;
+	u16 wvalue;
+	u16 index;
+	u32 data;
+
+	request = REALTEK_USB_VENQT_CMD_REQ;
+	index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
+	wvalue = (u16)(addr&0x0000ffff);
+	data = val;
+	_usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data,
+				       len);
+}
+
+static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	_usb_write_async(to_usb_device(dev), addr, val, 1);
+}
+
+static void _usb_write16_async(struct rtl_priv *rtlpriv, u32 addr, u16 val)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	_usb_write_async(to_usb_device(dev), addr, val, 2);
+}
+
+static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	_usb_write_async(to_usb_device(dev), addr, val, 4);
+}
+
+static int _usb_nbytes_read_write(struct usb_device *udev, bool read, u32 addr,
+				  u16 len, u8 *pdata)
+{
+	int status;
+	u8 request;
+	u16 wvalue;
+	u16 index;
+
+	request = REALTEK_USB_VENQT_CMD_REQ;
+	index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
+	wvalue = (u16)addr;
+	if (read)
+		status = _usbctrl_vendorreq_sync_read(udev, request, wvalue,
+						      index, pdata, len);
+	else
+		status = _usbctrl_vendorreq_async_write(udev, request, wvalue,
+							index, pdata, len);
+	return status;
+}
+
+static int _usb_readN_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			   u8 *pdata)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return _usb_nbytes_read_write(to_usb_device(dev), true, addr, len,
+				       pdata);
+}
+
+static int _usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			     u8 *pdata)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return _usb_nbytes_read_write(to_usb_device(dev), false, addr, len,
+				      pdata);
+}
+
+static void _rtl_usb_io_handler_init(struct device *dev,
+				     struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->io.dev = dev;
+	mutex_init(&rtlpriv->io.bb_mutex);
+	rtlpriv->io.write8_async	= _usb_write8_async;
+	rtlpriv->io.write16_async	= _usb_write16_async;
+	rtlpriv->io.write32_async	= _usb_write32_async;
+	rtlpriv->io.writeN_async	= _usb_writeN_async;
+	rtlpriv->io.read8_sync		= _usb_read8_sync;
+	rtlpriv->io.read16_sync		= _usb_read16_sync;
+	rtlpriv->io.read32_sync		= _usb_read32_sync;
+	rtlpriv->io.readN_sync		= _usb_readN_sync;
+}
+
+static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	mutex_destroy(&rtlpriv->io.bb_mutex);
+}
+
+/**
+ *
+ *	Default aggregation handler. Do nothing and just return the oldest skb.
+ */
+static struct sk_buff *_none_usb_tx_aggregate_hdl(struct ieee80211_hw *hw,
+						  struct sk_buff_head *list)
+{
+	return skb_dequeue(list);
+}
+
+#define IS_HIGH_SPEED_USB(udev) \
+		((USB_SPEED_HIGH == (udev)->speed) ? true : false)
+
+static int _rtl_usb_init_tx(struct ieee80211_hw *hw)
+{
+	u32 i;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtlusb->max_bulk_out_size = IS_HIGH_SPEED_USB(rtlusb->udev)
+						    ? USB_HIGH_SPEED_BULK_SIZE
+						    : USB_FULL_SPEED_BULK_SIZE;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("USB Max Bulk-out Size=%d\n",
+		 rtlusb->max_bulk_out_size));
+
+	for (i = 0; i < __RTL_TXQ_NUM; i++) {
+		u32 ep_num = rtlusb->ep_map.ep_mapping[i];
+		if (!ep_num) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+				 ("Invalid endpoint map setting!\n"));
+			return -EINVAL;
+		}
+	}
+
+	rtlusb->usb_tx_post_hdl =
+		 rtlpriv->cfg->usb_interface_cfg->usb_tx_post_hdl;
+	rtlusb->usb_tx_cleanup	=
+		 rtlpriv->cfg->usb_interface_cfg->usb_tx_cleanup;
+	rtlusb->usb_tx_aggregate_hdl =
+		 (rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl)
+		 ? rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl
+		 : &_none_usb_tx_aggregate_hdl;
+
+	init_usb_anchor(&rtlusb->tx_submitted);
+	for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
+		skb_queue_head_init(&rtlusb->tx_skb_queue[i]);
+		init_usb_anchor(&rtlusb->tx_pending[i]);
+	}
+	return 0;
+}
+
+static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+
+	rtlusb->rx_max_size = rtlpriv->cfg->usb_interface_cfg->rx_max_size;
+	rtlusb->rx_urb_num = rtlpriv->cfg->usb_interface_cfg->rx_urb_num;
+	rtlusb->in_ep = rtlpriv->cfg->usb_interface_cfg->in_ep_num;
+	rtlusb->usb_rx_hdl = rtlpriv->cfg->usb_interface_cfg->usb_rx_hdl;
+	rtlusb->usb_rx_segregate_hdl =
+		rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl;
+
+	printk(KERN_INFO "rtl8192cu: rx_max_size %d, rx_urb_num %d, in_ep %d\n",
+		rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep);
+	init_usb_anchor(&rtlusb->rx_submitted);
+	return 0;
+}
+
+static int _rtl_usb_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+	int err;
+	u8 epidx;
+	struct usb_interface	*usb_intf = rtlusb->intf;
+	u8 epnums = usb_intf->cur_altsetting->desc.bNumEndpoints;
+
+	rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0;
+	for (epidx = 0; epidx < epnums; epidx++) {
+		struct usb_endpoint_descriptor *pep_desc;
+		pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc;
+
+		if (usb_endpoint_dir_in(pep_desc))
+			rtlusb->in_ep_nums++;
+		else if (usb_endpoint_dir_out(pep_desc))
+			rtlusb->out_ep_nums++;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB EP(0x%02x), MaxPacketSize=%d ,Interval=%d.\n",
+			 pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
+			 pep_desc->bInterval));
+	}
+	if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num)
+		return -EINVAL ;
+
+	/* usb endpoint mapping */
+	err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
+	rtlusb->usb_mq_to_hwq =  rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
+	_rtl_usb_init_tx(hw);
+	_rtl_usb_init_rx(hw);
+	return err;
+}
+
+static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtlhal->hw = hw;
+	ppsc->inactiveps = false;
+	ppsc->leisure_ps = false;
+	ppsc->fwctrl_lps = false;
+	ppsc->reg_fwctrl_lps = 3;
+	ppsc->reg_max_lps_awakeintvl = 5;
+	ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;
+
+	 /* IBSS */
+	mac->beacon_interval = 100;
+
+	 /* AMPDU */
+	mac->min_space_cfg = 0;
+	mac->max_mss_density = 0;
+
+	/* set sane AMPDU defaults */
+	mac->current_ampdu_density = 7;
+	mac->current_ampdu_factor = 3;
+
+	/* QOS */
+	rtlusb->acm_method = eAcmWay2_SW;
+
+	/* IRQ */
+	/* HIMR - turn all on */
+	rtlusb->irq_mask[0] = 0xFFFFFFFF;
+	/* HIMR_EX - turn all on */
+	rtlusb->irq_mask[1] = 0xFFFFFFFF;
+	rtlusb->disableHWSM =  true;
+	return 0;
+}
+
+#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)
+{
+	struct sk_buff *skb;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	skb = __dev_alloc_skb((rtlusb->rx_max_size + __RADIO_TAP_SIZE_RSV),
+			       gfp_mask);
+	if (!skb) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Failed to __dev_alloc_skb!!\n"))
+		return ERR_PTR(-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);
+
+	_rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep);
+	return skb;
+}
+
+#undef __RADIO_TAP_SIZE_RSV
+
+static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
+				    struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *rxdesc = skb->data;
+	struct ieee80211_hdr *hdr;
+	bool unicast = false;
+	__le16 fc;
+	struct ieee80211_rx_status rx_status = {0};
+	struct rtl_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+	};
+
+	skb_pull(skb, RTL_RX_DESC_SIZE);
+	rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
+	skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
+	hdr = (struct ieee80211_hdr *)(skb->data);
+	fc = hdr->frame_control;
+	if (!stats.crc) {
+		memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+		if (is_broadcast_ether_addr(hdr->addr1)) {
+			/*TODO*/;
+		} else if (is_multicast_ether_addr(hdr->addr1)) {
+			/*TODO*/
+		} else {
+			unicast = true;
+			rtlpriv->stats.rxbytesunicast +=  skb->len;
+		}
+
+		rtl_is_special_data(hw, skb, false);
+
+		if (ieee80211_is_data(fc)) {
+			rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+			if (unicast)
+				rtlpriv->link_info.num_rx_inperiod++;
+		}
+	}
+}
+
+static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
+				      struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *rxdesc = skb->data;
+	struct ieee80211_hdr *hdr;
+	bool unicast = false;
+	__le16 fc;
+	struct ieee80211_rx_status rx_status = {0};
+	struct rtl_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+	};
+
+	skb_pull(skb, RTL_RX_DESC_SIZE);
+	rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
+	skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
+	hdr = (struct ieee80211_hdr *)(skb->data);
+	fc = hdr->frame_control;
+	if (!stats.crc) {
+		memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+		if (is_broadcast_ether_addr(hdr->addr1)) {
+			/*TODO*/;
+		} else if (is_multicast_ether_addr(hdr->addr1)) {
+			/*TODO*/
+		} else {
+			unicast = true;
+			rtlpriv->stats.rxbytesunicast +=  skb->len;
+		}
+
+		rtl_is_special_data(hw, skb, false);
+
+		if (ieee80211_is_data(fc)) {
+			rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+			if (unicast)
+				rtlpriv->link_info.num_rx_inperiod++;
+		}
+		if (likely(rtl_action_proc(hw, skb, false))) {
+			struct sk_buff *uskb = NULL;
+			u8 *pdata;
+
+			uskb = dev_alloc_skb(skb->len + 128);
+			memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
+			       sizeof(rx_status));
+			pdata = (u8 *)skb_put(uskb, skb->len);
+			memcpy(pdata, skb->data, skb->len);
+			dev_kfree_skb_any(skb);
+			ieee80211_rx_irqsafe(hw, uskb);
+		} else {
+			dev_kfree_skb_any(skb);
+		}
+	}
+}
+
+static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct sk_buff *_skb;
+	struct sk_buff_head rx_queue;
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	skb_queue_head_init(&rx_queue);
+	if (rtlusb->usb_rx_segregate_hdl)
+		rtlusb->usb_rx_segregate_hdl(hw, skb, &rx_queue);
+	WARN_ON(skb_queue_empty(&rx_queue));
+	while (!skb_queue_empty(&rx_queue)) {
+		_skb = skb_dequeue(&rx_queue);
+		_rtl_usb_rx_process_agg(hw, skb);
+		ieee80211_rx_irqsafe(hw, skb);
+	}
+}
+
+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 ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int err = 0;
+
+	if (unlikely(IS_USB_STOP(rtlusb)))
+		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);
+
+		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);
+			printk(KERN_ERR "rtlwifi: rx agg not supported\n");
+		}
+		goto resubmit;
+	}
+
+	switch (_urb->status) {
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		goto free;
+	default:
+		break;
+	}
+
+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)) {
+		usb_unanchor_urb(_urb);
+		goto free;
+	}
+	return;
+
+free:
+	dev_kfree_skb_irq(skb);
+}
+
+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);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	WARN_ON(0 == rtlusb->rx_urb_num);
+	/* 1600 == 1514 + max WLAN header + rtk info */
+	WARN_ON(rtlusb->rx_max_size < 1600);
+
+	for (i = 0; i < rtlusb->rx_urb_num; i++) {
+		err = -ENOMEM;
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 ("Failed to alloc URB!!\n"))
+			goto err_out;
+		}
+
+		skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
+		if (IS_ERR(skb)) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 ("Failed to prep_rx_urb!!\n"))
+			err = PTR_ERR(skb);
+			goto err_out;
+		}
+
+		usb_anchor_urb(urb, &rtlusb->rx_submitted);
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err)
+			goto err_out;
+		usb_free_urb(urb);
+	}
+	return 0;
+
+err_out:
+	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+	return err;
+}
+
+static int rtl_usb_start(struct ieee80211_hw *hw)
+{
+	int err;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	err = rtlpriv->cfg->ops->hw_init(hw);
+	rtl_init_rx_config(hw);
+
+	/* Enable software */
+	SET_USB_START(rtlusb);
+	/* should after adapter start and interrupt enable. */
+	set_hal_start(rtlhal);
+
+	/* Start bulk IN */
+	_rtl_usb_receive(hw);
+
+	return err;
+}
+/**
+ *
+ *
+ */
+
+/*=======================  tx =========================================*/
+static void rtl_usb_cleanup(struct ieee80211_hw *hw)
+{
+	u32 i;
+	struct sk_buff *_skb;
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct ieee80211_tx_info *txinfo;
+
+	SET_USB_STOP(rtlusb);
+
+	/* clean up rx stuff. */
+	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+
+	/* clean up tx stuff */
+	for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
+		while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) {
+			rtlusb->usb_tx_cleanup(hw, _skb);
+			txinfo = IEEE80211_SKB_CB(_skb);
+			ieee80211_tx_info_clear_status(txinfo);
+			txinfo->flags |= IEEE80211_TX_STAT_ACK;
+			ieee80211_tx_status_irqsafe(hw, _skb);
+		}
+		usb_kill_anchored_urbs(&rtlusb->tx_pending[i]);
+	}
+	usb_kill_anchored_urbs(&rtlusb->tx_submitted);
+}
+
+/**
+ *
+ * We may add some struct into struct rtl_usb later. Do deinit here.
+ *
+ */
+static void rtl_usb_deinit(struct ieee80211_hw *hw)
+{
+	rtl_usb_cleanup(hw);
+}
+
+static void rtl_usb_stop(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	/* should after adapter start and interrupt enable. */
+	set_hal_stop(rtlhal);
+	/* Enable software */
+	SET_USB_STOP(rtlusb);
+	rtl_usb_deinit(hw);
+	rtlpriv->cfg->ops->hw_disable(hw);
+}
+
+static void _rtl_submit_tx_urb(struct ieee80211_hw *hw, struct urb *_urb)
+{
+	int err;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	usb_anchor_urb(_urb, &rtlusb->tx_submitted);
+	err = usb_submit_urb(_urb, GFP_ATOMIC);
+	if (err < 0) {
+		struct sk_buff *skb;
+
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Failed to submit urb.\n"));
+		usb_unanchor_urb(_urb);
+		skb = (struct sk_buff *)_urb->context;
+		kfree_skb(skb);
+	}
+	usb_free_urb(_urb);
+}
+
+static int _usb_tx_post(struct ieee80211_hw *hw, struct urb *urb,
+			struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct ieee80211_tx_info *txinfo;
+
+	rtlusb->usb_tx_post_hdl(hw, urb, skb);
+	skb_pull(skb, RTL_TX_HEADER_SIZE);
+	txinfo = IEEE80211_SKB_CB(skb);
+	ieee80211_tx_info_clear_status(txinfo);
+	txinfo->flags |= IEEE80211_TX_STAT_ACK;
+
+	if (urb->status) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Urb has error status 0x%X\n", urb->status));
+		goto out;
+	}
+	/*  TODO:	statistics */
+out:
+	ieee80211_tx_status_irqsafe(hw, skb);
+	return urb->status;
+}
+
+static void _rtl_tx_complete(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 ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
+	int err;
+
+	if (unlikely(IS_USB_STOP(rtlusb)))
+		return;
+	err = _usb_tx_post(hw, urb, skb);
+	if (err) {
+		/* Ignore error and keep issuiing other urbs */
+		return;
+	}
+}
+
+static struct urb *_rtl_usb_tx_urb_setup(struct ieee80211_hw *hw,
+				struct sk_buff *skb, u32 ep_num)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct urb *_urb;
+
+	WARN_ON(NULL == skb);
+	_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!_urb) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Can't allocate URB for bulk out!\n"));
+		kfree_skb(skb);
+		return NULL;
+	}
+	_rtl_install_trx_info(rtlusb, skb, ep_num);
+	usb_fill_bulk_urb(_urb, rtlusb->udev, usb_sndbulkpipe(rtlusb->udev,
+			  ep_num), skb->data, skb->len, _rtl_tx_complete, skb);
+	_urb->transfer_flags |= URB_ZERO_PACKET;
+	return _urb;
+}
+
+static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
+		       enum rtl_txq qnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	u32 ep_num;
+	struct urb *_urb = NULL;
+	struct sk_buff *_skb = NULL;
+	struct sk_buff_head *skb_list;
+	struct usb_anchor *urb_list;
+
+	WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl);
+	if (unlikely(IS_USB_STOP(rtlusb))) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("USB device is stopping...\n"));
+		kfree_skb(skb);
+		return;
+	}
+	ep_num = rtlusb->ep_map.ep_mapping[qnum];
+	skb_list = &rtlusb->tx_skb_queue[ep_num];
+	_skb = skb;
+	_urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num);
+	if (unlikely(!_urb)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't allocate urb. Drop skb!\n"));
+		return;
+	}
+	urb_list = &rtlusb->tx_pending[ep_num];
+	_rtl_submit_tx_urb(hw, _urb);
+}
+
+static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb,
+			    u16 hw_queue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct rtl_tx_desc *pdesc = NULL;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+	u8 *pda_addr = hdr->addr1;
+	/* ssn */
+	u8 *qc = NULL;
+	u8 tid = 0;
+	u16 seq_number = 0;
+
+	if (ieee80211_is_mgmt(fc))
+		rtl_tx_mgmt_proc(hw, skb);
+	rtl_action_proc(hw, skb, true);
+	if (is_multicast_ether_addr(pda_addr))
+		rtlpriv->stats.txbytesmulticast += skb->len;
+	else if (is_broadcast_ether_addr(pda_addr))
+		rtlpriv->stats.txbytesbroadcast += skb->len;
+	else
+		rtlpriv->stats.txbytesunicast += skb->len;
+	if (ieee80211_is_data_qos(fc)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		seq_number = (le16_to_cpu(hdr->seq_ctrl) &
+			     IEEE80211_SCTL_SEQ) >> 4;
+		seq_number += 1;
+		seq_number <<= 4;
+	}
+	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb,
+					hw_queue);
+	if (!ieee80211_has_morefrags(hdr->frame_control)) {
+		if (qc)
+			mac->tids[tid].seq_number = seq_number;
+	}
+	if (ieee80211_is_data(fc))
+		rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX);
+}
+
+static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+	u16 hw_queue;
+
+	if (unlikely(is_hal_stop(rtlhal)))
+		goto err_free;
+	hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb));
+	_rtl_usb_tx_preprocess(hw, skb, hw_queue);
+	_rtl_usb_transmit(hw, skb, hw_queue);
+	return NETDEV_TX_OK;
+
+err_free:
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw,
+					struct sk_buff *skb)
+{
+	return false;
+}
+
+static struct rtl_intf_ops rtl_usb_ops = {
+	.adapter_start = rtl_usb_start,
+	.adapter_stop = rtl_usb_stop,
+	.adapter_tx = rtl_usb_tx,
+	.waitq_insert = rtl_usb_tx_chk_waitq_insert,
+};
+
+int __devinit rtl_usb_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	int err;
+	struct ieee80211_hw *hw = NULL;
+	struct rtl_priv *rtlpriv = NULL;
+	struct usb_device	*udev;
+	struct rtl_usb_priv *usb_priv;
+
+	hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) +
+				sizeof(struct rtl_usb_priv), &rtl_ops);
+	if (!hw) {
+		RT_ASSERT(false, ("%s : ieee80211 alloc failed\n", __func__));
+		return -ENOMEM;
+	}
+	rtlpriv = hw->priv;
+	SET_IEEE80211_DEV(hw, &intf->dev);
+	udev = interface_to_usbdev(intf);
+	usb_get_dev(udev);
+	usb_priv = rtl_usbpriv(hw);
+	memset(usb_priv, 0, sizeof(*usb_priv));
+	usb_priv->dev.intf = intf;
+	usb_priv->dev.udev = udev;
+	usb_set_intfdata(intf, hw);
+	/* init cfg & intf_ops */
+	rtlpriv->rtlhal.interface = INTF_USB;
+	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info);
+	rtlpriv->intf_ops = &rtl_usb_ops;
+	rtl_dbgp_flag_init(hw);
+	/* Init IO handler */
+	_rtl_usb_io_handler_init(&udev->dev, hw);
+	rtlpriv->cfg->ops->read_chip_version(hw);
+	/*like read eeprom and so on */
+	rtlpriv->cfg->ops->read_eeprom_info(hw);
+	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't init_sw_vars.\n"));
+		goto error_out;
+	}
+	rtlpriv->cfg->ops->init_sw_leds(hw);
+	err = _rtl_usb_init(hw);
+	err = _rtl_usb_init_sw(hw);
+	/* Init mac80211 sw */
+	err = rtl_init_core(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't allocate sw for mac80211.\n"));
+		goto error_out;
+	}
+
+	/*init rfkill */
+	/* rtl_init_rfkill(hw); */
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+			 ("Can't register mac80211 hw.\n"));
+		goto error_out;
+	} else {
+		rtlpriv->mac80211.mac80211_registered = 1;
+	}
+	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+	return 0;
+error_out:
+	rtl_deinit_core(hw);
+	_rtl_usb_io_handler_release(hw);
+	ieee80211_free_hw(hw);
+	usb_put_dev(udev);
+	return -ENODEV;
+}
+EXPORT_SYMBOL(rtl_usb_probe);
+
+void rtl_usb_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	if (unlikely(!rtlpriv))
+		return;
+	/*ieee80211_unregister_hw will call ops_stop */
+	if (rtlmac->mac80211_registered == 1) {
+		ieee80211_unregister_hw(hw);
+		rtlmac->mac80211_registered = 0;
+	} else {
+		rtl_deinit_deferred_work(hw);
+		rtlpriv->intf_ops->adapter_stop(hw);
+	}
+	/*deinit rfkill */
+	/* rtl_deinit_rfkill(hw); */
+	rtl_usb_deinit(hw);
+	rtl_deinit_core(hw);
+	rtlpriv->cfg->ops->deinit_sw_leds(hw);
+	rtlpriv->cfg->ops->deinit_sw_vars(hw);
+	_rtl_usb_io_handler_release(hw);
+	usb_put_dev(rtlusb->udev);
+	usb_set_intfdata(intf, NULL);
+	ieee80211_free_hw(hw);
+}
+EXPORT_SYMBOL(rtl_usb_disconnect);
+
+int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message)
+{
+	return 0;
+}
+EXPORT_SYMBOL(rtl_usb_suspend);
+
+int rtl_usb_resume(struct usb_interface *pusb_intf)
+{
+	return 0;
+}
+EXPORT_SYMBOL(rtl_usb_resume);
diff --git a/drivers/net/wireless/rtlwifi/usb.h b/drivers/net/wireless/rtlwifi/usb.h
new file mode 100644
index 0000000..abadfe9
--- /dev/null
+++ b/drivers/net/wireless/rtlwifi/usb.h
@@ -0,0 +1,164 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2011  Realtek 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+
+#ifndef __RTL_USB_H__
+#define __RTL_USB_H__
+
+#include <linux/usb.h>
+#include <linux/skbuff.h>
+
+#define RTL_USB_DEVICE(vend, prod, cfg) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.driver_info = (kernel_ulong_t)&(cfg)
+
+#define USB_HIGH_SPEED_BULK_SIZE	512
+#define USB_FULL_SPEED_BULK_SIZE	64
+
+
+#define RTL_USB_MAX_TXQ_NUM		4		/* max tx queue */
+#define RTL_USB_MAX_EP_NUM		6		/* max ep number */
+#define RTL_USB_MAX_TX_URBS_NUM		8
+
+enum rtl_txq {
+	/* These definitions shall be consistent with value
+	 * returned by skb_get_queue_mapping
+	 *------------------------------------*/
+	RTL_TXQ_BK,
+	RTL_TXQ_BE,
+	RTL_TXQ_VI,
+	RTL_TXQ_VO,
+	/*------------------------------------*/
+	RTL_TXQ_BCN,
+	RTL_TXQ_MGT,
+	RTL_TXQ_HI,
+
+	/* Must be last */
+	__RTL_TXQ_NUM,
+};
+
+struct rtl_ep_map {
+	u32 ep_mapping[__RTL_TXQ_NUM];
+};
+
+struct _trx_info {
+	struct rtl_usb *rtlusb;
+	u32 ep_num;
+};
+
+static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb,
+					 struct sk_buff *skb,
+					 u32 ep_num)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	info->rate_driver_data[0] = rtlusb;
+	info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num;
+}
+
+
+/*  Add suspend/resume later */
+enum rtl_usb_state {
+	USB_STATE_STOP	= 0,
+	USB_STATE_START	= 1,
+};
+
+#define IS_USB_STOP(rtlusb_ptr) (USB_STATE_STOP == (rtlusb_ptr)->state)
+#define IS_USB_START(rtlusb_ptr) (USB_STATE_START == (rtlusb_ptr)->state)
+#define SET_USB_STOP(rtlusb_ptr) \
+	do {							\
+		(rtlusb_ptr)->state = USB_STATE_STOP;		\
+	} while (0)
+
+#define SET_USB_START(rtlusb_ptr)				\
+	do { \
+		(rtlusb_ptr)->state = USB_STATE_START;		\
+	} while (0)
+
+struct rtl_usb {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	enum rtl_usb_state state;
+
+	/* Bcn control register setting */
+	u32 reg_bcn_ctrl_val;
+	/* for 88/92cu card disable */
+	u8	disableHWSM;
+	/*QOS & EDCA */
+	enum acm_method acm_method;
+	/* irq  . HIMR,HIMR_EX */
+	u32 irq_mask[2];
+	bool irq_enabled;
+
+	u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index);
+
+	/* Tx */
+	u8 out_ep_nums ;
+	u8 out_queue_sel;
+	struct rtl_ep_map ep_map;
+
+	u32 max_bulk_out_size;
+	u32 tx_submitted_urbs;
+	struct sk_buff_head tx_skb_queue[RTL_USB_MAX_EP_NUM];
+
+	struct usb_anchor tx_pending[RTL_USB_MAX_EP_NUM];
+	struct usb_anchor tx_submitted;
+
+	struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *,
+						struct sk_buff_head *);
+	int (*usb_tx_post_hdl)(struct ieee80211_hw *,
+			       struct urb *, struct sk_buff *);
+	void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *);
+
+	/* Rx */
+	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;
+	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 *);
+};
+
+struct rtl_usb_priv {
+	struct rtl_usb dev;
+	struct rtl_led_ctl ledctl;
+};
+
+#define rtl_usbpriv(hw)	 (((struct rtl_usb_priv *)(rtl_priv(hw))->priv))
+#define rtl_usbdev(usbpriv)	(&((usbpriv)->dev))
+
+
+
+int __devinit rtl_usb_probe(struct usb_interface *intf,
+			    const struct usb_device_id *id);
+void rtl_usb_disconnect(struct usb_interface *intf);
+int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
+int rtl_usb_resume(struct usb_interface *pusb_intf);
+
+#endif
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index d44d796..01226f8 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -34,6 +34,8 @@
 #include <linux/firmware.h>
 #include <linux/version.h>
 #include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/usb.h>
 #include <net/mac80211.h>
 #include "debug.h"
 
@@ -82,6 +84,19 @@
 #define MAC80211_3ADDR_LEN			24
 #define MAC80211_4ADDR_LEN			30
 
+#define CHANNEL_MAX_NUMBER	(14 + 24 + 21)	/* 14 is the max channel no */
+#define CHANNEL_GROUP_MAX	(3 + 9)	/*  ch1~3, 4~9, 10~14 = three groups */
+#define MAX_PG_GROUP			13
+#define	CHANNEL_GROUP_MAX_2G		3
+#define	CHANNEL_GROUP_IDX_5GL		3
+#define	CHANNEL_GROUP_IDX_5GM		6
+#define	CHANNEL_GROUP_IDX_5GH		9
+#define	CHANNEL_GROUP_MAX_5G		9
+#define CHANNEL_MAX_NUMBER_2G		14
+#define AVG_THERMAL_NUM			8
+
+/* for early mode */
+#define EM_HDR_LEN			8
 enum intf_type {
 	INTF_PCI = 0,
 	INTF_USB = 1,
@@ -113,11 +128,38 @@ enum hardware_type {
 	HARDWARE_TYPE_RTL8192CU,
 	HARDWARE_TYPE_RTL8192DE,
 	HARDWARE_TYPE_RTL8192DU,
+	HARDWARE_TYPE_RTL8723E,
+	HARDWARE_TYPE_RTL8723U,
 
-	/*keep it last*/
+	/* keep it last */
 	HARDWARE_TYPE_NUM
 };
 
+#define IS_HARDWARE_TYPE_8192SU(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192SU)
+#define IS_HARDWARE_TYPE_8192SE(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
+#define IS_HARDWARE_TYPE_8192CE(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
+#define IS_HARDWARE_TYPE_8192CU(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU)
+#define IS_HARDWARE_TYPE_8192DE(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
+#define IS_HARDWARE_TYPE_8192DU(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192DU)
+#define IS_HARDWARE_TYPE_8723E(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8723E)
+#define IS_HARDWARE_TYPE_8723U(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8723U)
+#define	IS_HARDWARE_TYPE_8192S(rtlhal)			\
+(IS_HARDWARE_TYPE_8192SE(rtlhal) || IS_HARDWARE_TYPE_8192SU(rtlhal))
+#define	IS_HARDWARE_TYPE_8192C(rtlhal)			\
+(IS_HARDWARE_TYPE_8192CE(rtlhal) || IS_HARDWARE_TYPE_8192CU(rtlhal))
+#define	IS_HARDWARE_TYPE_8192D(rtlhal)			\
+(IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal))
+#define	IS_HARDWARE_TYPE_8723(rtlhal)			\
+(IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal))
+
 enum scan_operation_backup_opt {
 	SCAN_OPT_BACKUP = 0,
 	SCAN_OPT_RESTORE,
@@ -315,6 +357,7 @@ enum rf_type {
 	RF_1T1R = 0,
 	RF_1T2R = 1,
 	RF_2T2R = 2,
+	RF_2T2R_GREEN = 3,
 };
 
 enum ht_channel_width {
@@ -359,6 +402,8 @@ enum rtl_var_map {
 	EFUSE_LOADER_CLK_EN,
 	EFUSE_ANA8M,
 	EFUSE_HWSET_MAX_SIZE,
+	EFUSE_MAX_SECTION_MAP,
+	EFUSE_REAL_CONTENT_SIZE,
 
 	/*CAM map */
 	RWCAM,
@@ -397,6 +442,7 @@ enum rtl_var_map {
 	RTL_IMR_ATIMEND,	/*For 92C,ATIM Window End Interrupt */
 	RTL_IMR_BDOK,		/*Beacon Queue DMA OK Interrup */
 	RTL_IMR_HIGHDOK,	/*High Queue DMA OK Interrupt */
+	RTL_IMR_COMDOK,		/*Command Queue DMA OK Interrupt*/
 	RTL_IMR_TBDOK,		/*Transmit Beacon OK interrup */
 	RTL_IMR_MGNTDOK,	/*Management Queue DMA OK Interrupt */
 	RTL_IMR_TBDER,		/*For 92C,Transmit Beacon Error Interrupt */
@@ -405,7 +451,8 @@ 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_IMR_TBDER)*/
+	RTL_IBSS_INT_MASKS,	/*(RTL_IMR_BcnInt | RTL_IMR_TBDOK |
+				 * RTL_IMR_TBDER) */
 
 	/*CCK Rates, TxHT = 0 */
 	RTL_RC_CCK_RATE1M,
@@ -481,6 +528,19 @@ enum acm_method {
 	eAcmWay2_SW = 2,
 };
 
+enum macphy_mode {
+	SINGLEMAC_SINGLEPHY = 0,
+	DUALMAC_DUALPHY,
+	DUALMAC_SINGLEPHY,
+};
+
+enum band_type {
+	BAND_ON_2_4G = 0,
+	BAND_ON_5G,
+	BAND_ON_BOTH,
+	BANDMAX
+};
+
 /*aci/aifsn Field.
 Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/
 union aci_aifsn {
@@ -505,6 +565,17 @@ enum wireless_mode {
 	WIRELESS_MODE_N_5G = 0x20
 };
 
+#define IS_WIRELESS_MODE_A(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_A)
+#define IS_WIRELESS_MODE_B(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_B)
+#define IS_WIRELESS_MODE_G(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_G)
+#define IS_WIRELESS_MODE_N_24G(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_N_24G)
+#define IS_WIRELESS_MODE_N_5G(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_N_5G)
+
 enum ratr_table_mode {
 	RATR_INX_WIRELESS_NGB = 0,
 	RATR_INX_WIRELESS_NG = 1,
@@ -574,11 +645,11 @@ struct rtl_probe_rsp {
 struct rtl_led {
 	void *hw;
 	enum rtl_led_pin ledpin;
-	bool b_ledon;
+	bool ledon;
 };
 
 struct rtl_led_ctl {
-	bool bled_opendrain;
+	bool led_opendrain;
 	struct rtl_led sw_led0;
 	struct rtl_led sw_led1;
 };
@@ -603,6 +674,8 @@ struct false_alarm_statistics {
 	u32 cnt_rate_illegal;
 	u32 cnt_crc8_fail;
 	u32 cnt_mcs_fail;
+	u32 cnt_fast_fsync_fail;
+	u32 cnt_sb_search_fail;
 	u32 cnt_ofdm_fail;
 	u32 cnt_cck_fail;
 	u32 cnt_all;
@@ -690,6 +763,32 @@ struct rtl_rfkill {
 	bool rfkill_state;	/*0 is off, 1 is on */
 };
 
+#define IQK_MATRIX_REG_NUM	8
+#define IQK_MATRIX_SETTINGS_NUM	(1 + 24 + 21)
+struct iqk_matrix_regs {
+	bool b_iqk_done;
+	long value[1][IQK_MATRIX_REG_NUM];
+};
+
+struct phy_parameters {
+	u16 length;
+	u32 *pdata;
+};
+
+enum hw_param_tab_index {
+	PHY_REG_2T,
+	PHY_REG_1T,
+	PHY_REG_PG,
+	RADIOA_2T,
+	RADIOB_2T,
+	RADIOA_1T,
+	RADIOB_1T,
+	MAC_REG,
+	AGCTAB_2T,
+	AGCTAB_1T,
+	MAX_TAB
+};
+
 struct rtl_phy {
 	struct bb_reg_def phyreg_def[4];	/*Radio A/B/C/D */
 	struct init_gain initgain_backup;
@@ -705,8 +804,9 @@ struct rtl_phy {
 	u8 current_channel;
 	u8 h2c_box_num;
 	u8 set_io_inprogress;
+	u8 lck_inprogress;
 
-	/*record for power tracking*/
+	/* record for power tracking */
 	s32 reg_e94;
 	s32 reg_e9c;
 	s32 reg_ea4;
@@ -723,26 +823,32 @@ struct rtl_phy {
 	u32 iqk_mac_backup[IQK_MAC_REG_NUM];
 	u32 iqk_bb_backup[10];
 
-	bool b_rfpi_enable;
+	/* Dual mac */
+	bool need_iqk;
+	struct iqk_matrix_regs iqk_matrix_regsetting[IQK_MATRIX_SETTINGS_NUM];
+
+	bool rfpi_enable;
 
 	u8 pwrgroup_cnt;
-	u8 bcck_high_power;
-	/* 3 groups of pwr diff by rates*/
-	u32 mcs_txpwrlevel_origoffset[4][16];
+	u8 cck_high_power;
+	/* MAX_PG_GROUP groups of pwr diff by rates */
+	u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16];
 	u8 default_initialgain[4];
 
-	/*the current Tx power level*/
+	/* the current Tx power level */
 	u8 cur_cck_txpwridx;
 	u8 cur_ofdm24g_txpwridx;
 
 	u32 rfreg_chnlval[2];
-	bool b_apk_done;
+	bool apk_done;
+	u32 reg_rf3c[2];	/* pathA / pathB  */
 
-	/*fsync*/
 	u8 framesync;
 	u32 framesync_c34;
 
 	u8 num_total_rfpath;
+	struct phy_parameters hwparam_tables[MAX_TAB];
+	u16 rf_pathmap;
 };
 
 #define MAX_TID_COUNT				9
@@ -768,6 +874,7 @@ struct rtl_tid_data {
 struct rtl_priv;
 struct rtl_io {
 	struct device *dev;
+	struct mutex bb_mutex;
 
 	/*PCI MEM map */
 	unsigned long pci_mem_end;	/*shared mem end        */
@@ -779,11 +886,14 @@ struct rtl_io {
 	void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
 	void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
 	void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
-
-	 u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
-	 u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
-	 u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
-
+	int (*writeN_async) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			     u8 *pdata);
+
+	u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
+	u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
+	u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
+	int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			    u8 *pdata);
 };
 
 struct rtl_mac {
@@ -815,16 +925,24 @@ struct rtl_mac {
 	bool act_scanning;
 	u8 cnt_after_linked;
 
-	 /*RDG*/ bool rdg_en;
+	/* early mode */
+	/* skb wait queue */
+	struct sk_buff_head skb_waitq[MAX_TID_COUNT];
+	u8 earlymode_threshold;
+
+	/*RDG*/
+	bool rdg_en;
 
-	 /*AP*/ u8 bssid[6];
-	u8 mcs[16];	/*16 bytes mcs for HT rates.*/
-	u32 basic_rates; /*b/g rates*/
+	/*AP*/
+	u8 bssid[6];
+	u32 vendor;
+	u8 mcs[16];	/* 16 bytes mcs for HT rates. */
+	u32 basic_rates; /* b/g rates */
 	u8 ht_enable;
 	u8 sgi_40;
 	u8 sgi_20;
 	u8 bw_40;
-	u8 mode;		/*wireless mode*/
+	u8 mode;		/* wireless mode */
 	u8 slot_time;
 	u8 short_preamble;
 	u8 use_cts_protect;
@@ -835,9 +953,11 @@ struct rtl_mac {
 	u8 retry_long;
 	u16 assoc_id;
 
-	 /*IBSS*/ int beacon_interval;
+	/*IBSS*/
+	int beacon_interval;
 
-	 /*AMPDU*/ u8 min_space_cfg;	/*For Min spacing configurations */
+	/*AMPDU*/
+	u8 min_space_cfg;	/*For Min spacing configurations */
 	u8 max_mss_density;
 	u8 current_ampdu_factor;
 	u8 current_ampdu_density;
@@ -852,17 +972,54 @@ struct rtl_hal {
 
 	enum intf_type interface;
 	u16 hw_type;		/*92c or 92d or 92s and so on */
+	u8 ic_class;
 	u8 oem_id;
-	u8 version;		/*version of chip */
+	u32 version;		/*version of chip */
 	u8 state;		/*stop 0, start 1 */
 
 	/*firmware */
+	u32 fwsize;
 	u8 *pfirmware;
-	bool b_h2c_setinprogress;
+	u16 fw_version;
+	u16 fw_subversion;
+	bool h2c_setinprogress;
 	u8 last_hmeboxnum;
-	bool bfw_ready;
+	bool fw_ready;
 	/*Reserve page start offset except beacon in TxQ. */
 	u8 fw_rsvdpage_startoffset;
+	u8 h2c_txcmd_seq;
+
+	/* FW Cmd IO related */
+	u16 fwcmd_iomap;
+	u32 fwcmd_ioparam;
+	bool set_fwcmd_inprogress;
+	u8 current_fwcmd_io;
+
+	/**/
+	bool driver_going2unload;
+
+	/*AMPDU init min space*/
+	u8 minspace_cfg;	/*For Min spacing configurations */
+
+	/* Dual mac */
+	enum macphy_mode macphymode;
+	enum band_type current_bandtype;	/* 0:2.4G, 1:5G */
+	enum band_type current_bandtypebackup;
+	enum band_type bandset;
+	/* dual MAC 0--Mac0 1--Mac1 */
+	u32 interfaceindex;
+	/* just for DualMac S3S4 */
+	u8 macphyctl_reg;
+	bool earlymode_enable;
+	/* Dual mac*/
+	bool during_mac0init_radiob;
+	bool during_mac1init_radioa;
+	bool reloadtxpowerindex;
+	/* True if IMR or IQK  have done
+	for 2.4G in scan progress */
+	bool load_imrandiqk_setting_for2g;
+
+	bool disable_amsdu_8k;
 };
 
 struct rtl_security {
@@ -887,48 +1044,61 @@ struct rtl_security {
 };
 
 struct rtl_dm {
-	/*PHY status for DM */
+	/*PHY status for Dynamic Management */
 	long entry_min_undecoratedsmoothed_pwdb;
 	long undecorated_smoothed_pwdb;	/*out dm */
 	long entry_max_undecoratedsmoothed_pwdb;
-	bool b_dm_initialgain_enable;
-	bool bdynamic_txpower_enable;
-	bool bcurrent_turbo_edca;
-	bool bis_any_nonbepkts;	/*out dm */
-	bool bis_cur_rdlstate;
-	bool btxpower_trackingInit;
-	bool b_disable_framebursting;
-	bool b_cck_inch14;
-	bool btxpower_tracking;
-	bool b_useramask;
-	bool brfpath_rxenable[4];
-
+	bool dm_initialgain_enable;
+	bool dynamic_txpower_enable;
+	bool current_turbo_edca;
+	bool is_any_nonbepkts;	/*out dm */
+	bool is_cur_rdlstate;
+	bool txpower_trackingInit;
+	bool disable_framebursting;
+	bool cck_inch14;
+	bool txpower_tracking;
+	bool useramask;
+	bool rfpath_rxenable[4];
+	bool inform_fw_driverctrldm;
+	bool current_mrc_switch;
+	u8 txpowercount;
+
+	u8 thermalvalue_rxgain;
 	u8 thermalvalue_iqk;
 	u8 thermalvalue_lck;
 	u8 thermalvalue;
 	u8 last_dtp_lvl;
+	u8 thermalvalue_avg[AVG_THERMAL_NUM];
+	u8 thermalvalue_avg_index;
+	bool done_txpower;
 	u8 dynamic_txhighpower_lvl;	/*Tx high power level */
-	u8 dm_flag;	/*Indicate if each dynamic mechanism's status. */
+	u8 dm_flag;		/*Indicate each dynamic mechanism's status. */
 	u8 dm_type;
 	u8 txpower_track_control;
-
+	bool interrupt_migration;
+	bool disable_tx_int;
 	char ofdm_index[2];
 	char cck_index;
+	u8 power_index_backup[6];
 };
 
-#define	EFUSE_MAX_LOGICAL_SIZE			 128
+#define	EFUSE_MAX_LOGICAL_SIZE			256
 
 struct rtl_efuse {
-	bool bautoLoad_ok;
+	bool autoLoad_ok;
 	bool bootfromefuse;
 	u16 max_physical_size;
-	u8 contents[EFUSE_MAX_LOGICAL_SIZE];
 
 	u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE];
 	u16 efuse_usedbytes;
 	u8 efuse_usedpercentage;
+#ifdef EFUSE_REPG_WORKAROUND
+	bool efuse_re_pg_sec1flag;
+	u8 efuse_re_pg_data[8];
+#endif
 
 	u8 autoload_failflag;
+	u8 autoload_status;
 
 	short epromtype;
 	u16 eeprom_vid;
@@ -938,69 +1108,90 @@ struct rtl_efuse {
 	u8 eeprom_oemid;
 	u16 eeprom_channelplan;
 	u8 eeprom_version;
+	u8 board_type;
+	u8 external_pa;
 
 	u8 dev_addr[6];
 
-	bool b_txpwr_fromeprom;
+	bool txpwr_fromeprom;
+	u8 eeprom_crystalcap;
 	u8 eeprom_tssi[2];
-	u8 eeprom_pwrlimit_ht20[3];
-	u8 eeprom_pwrlimit_ht40[3];
-	u8 eeprom_chnlarea_txpwr_cck[2][3];
-	u8 eeprom_chnlarea_txpwr_ht40_1s[2][3];
-	u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][3];
-	u8 txpwrlevel_cck[2][14];
-	u8 txpwrlevel_ht40_1s[2][14];	/*For HT 40MHZ pwr */
-	u8 txpwrlevel_ht40_2s[2][14];	/*For HT 40MHZ pwr */
+	u8 eeprom_tssi_5g[3][2]; /* for 5GL/5GM/5GH band. */
+	u8 eeprom_pwrlimit_ht20[CHANNEL_GROUP_MAX];
+	u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX];
+	u8 eeprom_chnlarea_txpwr_cck[2][CHANNEL_GROUP_MAX_2G];
+	u8 eeprom_chnlarea_txpwr_ht40_1s[2][CHANNEL_GROUP_MAX];
+	u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][CHANNEL_GROUP_MAX];
+	u8 txpwrlevel_cck[2][CHANNEL_MAX_NUMBER_2G];
+	u8 txpwrlevel_ht40_1s[2][CHANNEL_MAX_NUMBER];	/*For HT 40MHZ pwr */
+	u8 txpwrlevel_ht40_2s[2][CHANNEL_MAX_NUMBER];	/*For HT 40MHZ pwr */
+
+	u8 internal_pa_5g[2];	/* pathA / pathB */
+	u8 eeprom_c9;
+	u8 eeprom_cc;
 
 	/*For power group */
-	u8 pwrgroup_ht20[2][14];
-	u8 pwrgroup_ht40[2][14];
-
-	char txpwr_ht20diff[2][14];	/*HT 20<->40 Pwr diff */
-	u8 txpwr_legacyhtdiff[2][14];	/*For HT<->legacy pwr diff */
+	u8 eeprom_pwrgroup[2][3];
+	u8 pwrgroup_ht20[2][CHANNEL_MAX_NUMBER];
+	u8 pwrgroup_ht40[2][CHANNEL_MAX_NUMBER];
+
+	char txpwr_ht20diff[2][CHANNEL_MAX_NUMBER]; /*HT 20<->40 Pwr diff */
+	/*For HT<->legacy pwr diff*/
+	u8 txpwr_legacyhtdiff[2][CHANNEL_MAX_NUMBER];
+	u8 txpwr_safetyflag;			/* Band edge enable flag */
+	u16 eeprom_txpowerdiff;
+	u8 legacy_httxpowerdiff;	/* Legacy to HT rate power diff */
+	u8 antenna_txpwdiff[3];
 
 	u8 eeprom_regulatory;
 	u8 eeprom_thermalmeter;
-	/*ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */
-	u8 thermalmeter[2];
+	u8 thermalmeter[2]; /*ThermalMeter, index 0 for RFIC0, 1 for RFIC1 */
+	u16 tssi_13dbm;
+	u8 crystalcap;		/* CrystalCap. */
+	u8 delta_iqk;
+	u8 delta_lck;
 
 	u8 legacy_ht_txpowerdiff;	/*Legacy to HT rate power diff */
-	bool b_apk_thermalmeterignore;
+	bool apk_thermalmeterignore;
+
+	bool b1x1_recvcombine;
+	bool b1ss_support;
+
+	/*channel plan */
+	u8 channel_plan;
 };
 
 struct rtl_ps_ctl {
+	bool pwrdomain_protect;
 	bool set_rfpowerstate_inprogress;
-	bool b_in_powersavemode;
+	bool in_powersavemode;
 	bool rfchange_inprogress;
-	bool b_swrf_processing;
-	bool b_hwradiooff;
-
-	u32 last_sleep_jiffies;
-	u32 last_awake_jiffies;
-	u32 last_delaylps_stamp_jiffies;
+	bool swrf_processing;
+	bool hwradiooff;
 
 	/*
 	 * just for PCIE ASPM
 	 * If it supports ASPM, Offset[560h] = 0x40,
 	 * otherwise Offset[560h] = 0x00.
 	 * */
-	bool b_support_aspm;
-	bool b_support_backdoor;
+	bool support_aspm;
+	bool support_backdoor;
 
 	/*for LPS */
 	enum rt_psmode dot11_psmode;	/*Power save mode configured. */
-	bool b_leisure_ps;
-	bool b_fwctrl_lps;
+	bool swctrl_lps;
+	bool leisure_ps;
+	bool fwctrl_lps;
 	u8 fwctrl_psmode;
 	/*For Fw control LPS mode */
-	u8 b_reg_fwctrl_lps;
+	u8 reg_fwctrl_lps;
 	/*Record Fw PS mode status. */
-	bool b_fw_current_inpsmode;
+	bool fw_current_inpsmode;
 	u8 reg_max_lps_awakeintvl;
 	bool report_linked;
 
 	/*for IPS */
-	bool b_inactiveps;
+	bool inactiveps;
 
 	u32 rfoff_reason;
 
@@ -1011,8 +1202,26 @@ struct rtl_ps_ctl {
 	/*just for PCIE ASPM */
 	u8 const_amdpci_aspm;
 
+	bool pwrdown_mode;
+
 	enum rf_pwrstate inactive_pwrstate;
 	enum rf_pwrstate rfpwr_state;	/*cur power state */
+
+	/* for SW LPS*/
+	bool sw_ps_enabled;
+	bool state;
+	bool state_inap;
+	bool multi_buffered;
+	u16 nullfunc_seq;
+	unsigned int dtim_counter;
+	unsigned int sleep_ms;
+	unsigned long last_sleep_jiffies;
+	unsigned long last_awake_jiffies;
+	unsigned long last_delaylps_stamp_jiffies;
+	unsigned long last_dtim;
+	unsigned long last_beacon;
+	unsigned long last_action;
+	unsigned long last_slept;
 };
 
 struct rtl_stats {
@@ -1038,10 +1247,10 @@ struct rtl_stats {
 	s32 recvsignalpower;
 	s8 rxpower;		/*in dBm Translate from PWdB */
 	u8 signalstrength;	/*in 0-100 index. */
-	u16 b_hwerror:1;
-	u16 b_crc:1;
-	u16 b_icv:1;
-	u16 b_shortpreamble:1;
+	u16 hwerror:1;
+	u16 crc:1;
+	u16 icv:1;
+	u16 shortpreamble:1;
 	u16 antenna:1;
 	u16 decrypted:1;
 	u16 wakeup:1;
@@ -1050,15 +1259,16 @@ struct rtl_stats {
 
 	u8 rx_drvinfo_size;
 	u8 rx_bufshift;
-	bool b_isampdu;
+	bool isampdu;
+	bool isfirst_ampdu;
 	bool rx_is40Mhzpacket;
 	u32 rx_pwdb_all;
 	u8 rx_mimo_signalstrength[4];	/*in 0~100 index */
 	s8 rx_mimo_signalquality[2];
-	bool b_packet_matchbssid;
-	bool b_is_cck;
-	bool b_packet_toself;
-	bool b_packet_beacon;	/*for rssi */
+	bool packet_matchbssid;
+	bool is_cck;
+	bool packet_toself;
+	bool packet_beacon;	/*for rssi */
 	char cck_adc_pwdb[4];	/*for rx path selection */
 };
 
@@ -1069,23 +1279,23 @@ struct rt_link_detect {
 	u32 num_tx_inperiod;
 	u32 num_rx_inperiod;
 
-	bool b_busytraffic;
-	bool b_higher_busytraffic;
-	bool b_higher_busyrxtraffic;
+	bool busytraffic;
+	bool higher_busytraffic;
+	bool higher_busyrxtraffic;
 };
 
 struct rtl_tcb_desc {
-	u8 b_packet_bw:1;
-	u8 b_multicast:1;
-	u8 b_broadcast:1;
-
-	u8 b_rts_stbc:1;
-	u8 b_rts_enable:1;
-	u8 b_cts_enable:1;
-	u8 b_rts_use_shortpreamble:1;
-	u8 b_rts_use_shortgi:1;
+	u8 packet_bw:1;
+	u8 multicast:1;
+	u8 broadcast:1;
+
+	u8 rts_stbc:1;
+	u8 rts_enable:1;
+	u8 cts_enable:1;
+	u8 rts_use_shortpreamble:1;
+	u8 rts_use_shortgi:1;
 	u8 rts_sc:1;
-	u8 b_rts_bw:1;
+	u8 rts_bw:1;
 	u8 rts_rate;
 
 	u8 use_shortgi:1;
@@ -1096,20 +1306,34 @@ struct rtl_tcb_desc {
 	u8 ratr_index;
 	u8 mac_id;
 	u8 hw_rate;
+
+	u8 last_inipkt:1;
+	u8 cmd_or_init:1;
+	u8 queue_index;
+
+	/* early mode */
+	u8 empkt_num;
+	/* The max value by HW */
+	u32 empkt_len[5];
 };
 
 struct rtl_hal_ops {
 	int (*init_sw_vars) (struct ieee80211_hw *hw);
 	void (*deinit_sw_vars) (struct ieee80211_hw *hw);
+	void (*read_chip_version)(struct ieee80211_hw *hw);
 	void (*read_eeprom_info) (struct ieee80211_hw *hw);
 	void (*interrupt_recognized) (struct ieee80211_hw *hw,
 				      u32 *p_inta, u32 *p_intb);
 	int (*hw_init) (struct ieee80211_hw *hw);
 	void (*hw_disable) (struct ieee80211_hw *hw);
+	void (*hw_suspend) (struct ieee80211_hw *hw);
+	void (*hw_resume) (struct ieee80211_hw *hw);
 	void (*enable_interrupt) (struct ieee80211_hw *hw);
 	void (*disable_interrupt) (struct ieee80211_hw *hw);
 	int (*set_network_type) (struct ieee80211_hw *hw,
 				 enum nl80211_iftype type);
+	void (*set_chk_bssid)(struct ieee80211_hw *hw,
+				bool check_bssid);
 	void (*set_bw_mode) (struct ieee80211_hw *hw,
 			     enum nl80211_channel_type ch_type);
 	 u8(*switch_channel) (struct ieee80211_hw *hw);
@@ -1126,23 +1350,26 @@ struct rtl_hal_ops {
 			      struct ieee80211_hdr *hdr, u8 *pdesc_tx,
 			      struct ieee80211_tx_info *info,
 			      struct sk_buff *skb, unsigned int queue_index);
+	void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 * pDesc,
+				  u32 buffer_len, bool bIsPsPoll);
 	void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc,
-				 bool b_firstseg, bool b_lastseg,
+				 bool firstseg, bool lastseg,
 				 struct sk_buff *skb);
-	 bool(*query_rx_desc) (struct ieee80211_hw *hw,
+	bool (*cmd_send_packet)(struct ieee80211_hw *hw, struct sk_buff *skb);
+	bool (*query_rx_desc) (struct ieee80211_hw *hw,
 			       struct rtl_stats *stats,
 			       struct ieee80211_rx_status *rx_status,
 			       u8 *pdesc, struct sk_buff *skb);
 	void (*set_channel_access) (struct ieee80211_hw *hw);
-	 bool(*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid);
+	bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid);
 	void (*dm_watchdog) (struct ieee80211_hw *hw);
 	void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation);
-	 bool(*set_rf_power_state) (struct ieee80211_hw *hw,
+	bool (*set_rf_power_state) (struct ieee80211_hw *hw,
 				    enum rf_pwrstate rfpwr_state);
 	void (*led_control) (struct ieee80211_hw *hw,
 			     enum led_ctl_mode ledaction);
 	void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val);
-	 u32(*get_desc) (u8 *pdesc, bool istx, u8 desc_name);
+	u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name);
 	void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue);
 	void (*enable_hw_sec) (struct ieee80211_hw *hw);
 	void (*set_key) (struct ieee80211_hw *hw, u32 key_index,
@@ -1150,22 +1377,36 @@ struct rtl_hal_ops {
 			 bool is_wepkey, bool clear_all);
 	void (*init_sw_leds) (struct ieee80211_hw *hw);
 	void (*deinit_sw_leds) (struct ieee80211_hw *hw);
-	 u32(*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+	u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
 	void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
 			   u32 data);
-	 u32(*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
+	u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
 			  u32 regaddr, u32 bitmask);
 	void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
 			   u32 regaddr, u32 bitmask, u32 data);
+	bool (*phy_rf6052_config) (struct ieee80211_hw *hw);
+	void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw,
+					    u8 *powerlevel);
+	void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw,
+					     u8 *ppowerlevel, u8 channel);
+	bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw,
+					   u8 configtype);
+	bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw,
+					     u8 configtype);
+	void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t);
+	void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw);
+	void (*dm_dynamic_txpower) (struct ieee80211_hw *hw);
 };
 
 struct rtl_intf_ops {
 	/*com */
+	void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
 	int (*adapter_start) (struct ieee80211_hw *hw);
 	void (*adapter_stop) (struct ieee80211_hw *hw);
 
 	int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb);
 	int (*reset_trx_ring) (struct ieee80211_hw *hw);
+	bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb);
 
 	/*pci */
 	void (*disable_aspm) (struct ieee80211_hw *hw);
@@ -1179,11 +1420,36 @@ struct rtl_mod_params {
 	int sw_crypto;
 };
 
+struct rtl_hal_usbint_cfg {
+	/* data - rx */
+	u32 in_ep_num;
+	u32 rx_urb_num;
+	u32 rx_max_size;
+
+	/* op - rx */
+	void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *);
+	void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *,
+				     struct sk_buff_head *);
+
+	/* tx */
+	void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *);
+	int (*usb_tx_post_hdl)(struct ieee80211_hw *, struct urb *,
+			       struct sk_buff *);
+	struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *,
+						struct sk_buff_head *);
+
+	/* endpoint mapping */
+	int (*usb_endpoint_mapping)(struct ieee80211_hw *hw);
+	u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index);
+};
+
 struct rtl_hal_cfg {
+	u8 bar_id;
 	char *name;
 	char *fw_name;
 	struct rtl_hal_ops *ops;
 	struct rtl_mod_params *mod_params;
+	struct rtl_hal_usbint_cfg *usb_interface_cfg;
 
 	/*this map used for some registers or vars
 	   defined int HAL but used in MAIN */
@@ -1202,6 +1468,11 @@ struct rtl_locks {
 	spinlock_t rf_ps_lock;
 	spinlock_t rf_lock;
 	spinlock_t lps_lock;
+	spinlock_t waitq_lock;
+	spinlock_t tx_urb_lock;
+
+	/*Dual mac*/
+	spinlock_t cck_and_rw_pagea_lock;
 };
 
 struct rtl_works {
@@ -1218,12 +1489,20 @@ struct rtl_works {
 	struct workqueue_struct *rtl_wq;
 	struct delayed_work watchdog_wq;
 	struct delayed_work ips_nic_off_wq;
+
+	/* For SW LPS */
+	struct delayed_work ps_work;
+	struct delayed_work ps_rfon_wq;
 };
 
 struct rtl_debug {
 	u32 dbgp_type[DBGP_TYPE_MAX];
 	u32 global_debuglevel;
 	u64 global_debugcomponents;
+
+	/* add for proc debug */
+	struct proc_dir_entry *proc_dir;
+	char proc_name[20];
 };
 
 struct rtl_priv {
@@ -1274,6 +1553,91 @@ struct rtl_priv {
 #define rtl_efuse(rtlpriv)	(&((rtlpriv)->efuse))
 #define rtl_psc(rtlpriv)	(&((rtlpriv)->psc))
 
+
+/***************************************
+    Bluetooth Co-existance Related
+****************************************/
+
+enum bt_ant_num {
+	ANT_X2 = 0,
+	ANT_X1 = 1,
+};
+
+enum bt_co_type {
+	BT_2WIRE = 0,
+	BT_ISSC_3WIRE = 1,
+	BT_ACCEL = 2,
+	BT_CSR_BC4 = 3,
+	BT_CSR_BC8 = 4,
+	BT_RTL8756 = 5,
+};
+
+enum bt_cur_state {
+	BT_OFF = 0,
+	BT_ON = 1,
+};
+
+enum bt_service_type {
+	BT_SCO = 0,
+	BT_A2DP = 1,
+	BT_HID = 2,
+	BT_HID_IDLE = 3,
+	BT_SCAN = 4,
+	BT_IDLE = 5,
+	BT_OTHER_ACTION = 6,
+	BT_BUSY = 7,
+	BT_OTHERBUSY = 8,
+	BT_PAN = 9,
+};
+
+enum bt_radio_shared {
+	BT_RADIO_SHARED = 0,
+	BT_RADIO_INDIVIDUAL = 1,
+};
+
+struct bt_coexist_info {
+
+	/* EEPROM BT info. */
+	u8 eeprom_bt_coexist;
+	u8 eeprom_bt_type;
+	u8 eeprom_bt_ant_num;
+	u8 eeprom_bt_ant_isolation;
+	u8 eeprom_bt_radio_shared;
+
+	u8 bt_coexistence;
+	u8 bt_ant_num;
+	u8 bt_coexist_type;
+	u8 bt_state;
+	u8 bt_cur_state;	/* 0:on, 1:off */
+	u8 bt_ant_isolation;	/* 0:good, 1:bad */
+	u8 bt_pape_ctrl;	/* 0:SW, 1:SW/HW dynamic */
+	u8 bt_service;
+	u8 bt_radio_shared_type;
+	u8 bt_rfreg_origin_1e;
+	u8 bt_rfreg_origin_1f;
+	u8 bt_rssi_state;
+	u32 ratio_tx;
+	u32 ratio_pri;
+	u32 bt_edca_ul;
+	u32 bt_edca_dl;
+
+	bool b_init_set;
+	bool b_bt_busy_traffic;
+	bool b_bt_traffic_mode_set;
+	bool b_bt_non_traffic_mode_set;
+
+	bool b_fw_coexist_all_off;
+	bool b_sw_coexist_all_off;
+	u32 current_state;
+	u32 previous_state;
+	u8 bt_pre_rssi_state;
+
+	u8 b_reg_bt_iso;
+	u8 b_reg_bt_sco;
+
+};
+
+
 /****************************************
 	mem access macro define start
 	Call endian free function when
@@ -1281,7 +1645,7 @@ struct rtl_priv {
 	2. Before write integer to IO.
 	3. After read integer from IO.
 ****************************************/
-/* Convert little data endian to host */
+/* Convert little data endian to host ordering */
 #define EF1BYTE(_val)		\
 	((u8)(_val))
 #define EF2BYTE(_val)		\
@@ -1289,27 +1653,21 @@ struct rtl_priv {
 #define EF4BYTE(_val)		\
 	(le32_to_cpu(_val))
 
-/* Read data from memory */
-#define READEF1BYTE(_ptr)	\
-	EF1BYTE(*((u8 *)(_ptr)))
+/* Read le16 data from memory and convert to host ordering */
 #define READEF2BYTE(_ptr)	\
 	EF2BYTE(*((u16 *)(_ptr)))
-#define READEF4BYTE(_ptr)	\
-	EF4BYTE(*((u32 *)(_ptr)))
 
-/* Write data to memory */
-#define WRITEEF1BYTE(_ptr, _val)	\
-	(*((u8 *)(_ptr))) = EF1BYTE(_val)
+/* Write le16 data to memory in host ordering */
 #define WRITEEF2BYTE(_ptr, _val)	\
 	(*((u16 *)(_ptr))) = EF2BYTE(_val)
-#define WRITEEF4BYTE(_ptr, _val)	\
-	(*((u32 *)(_ptr))) = EF4BYTE(_val)
-
-/*Example:
-BIT_LEN_MASK_32(0) => 0x00000000
-BIT_LEN_MASK_32(1) => 0x00000001
-BIT_LEN_MASK_32(2) => 0x00000003
-BIT_LEN_MASK_32(32) => 0xFFFFFFFF*/
+
+/* Create a bit mask
+ * Examples:
+ * BIT_LEN_MASK_32(0) => 0x00000000
+ * BIT_LEN_MASK_32(1) => 0x00000001
+ * BIT_LEN_MASK_32(2) => 0x00000003
+ * BIT_LEN_MASK_32(32) => 0xFFFFFFFF
+ */
 #define BIT_LEN_MASK_32(__bitlen)	 \
 	(0xFFFFFFFF >> (32 - (__bitlen)))
 #define BIT_LEN_MASK_16(__bitlen)	 \
@@ -1317,9 +1675,11 @@ BIT_LEN_MASK_32(32) => 0xFFFFFFFF*/
 #define BIT_LEN_MASK_8(__bitlen) \
 	(0xFF >> (8 - (__bitlen)))
 
-/*Example:
-BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
-BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000*/
+/* Create an offset bit mask
+ * Examples:
+ * BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
+ * BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000
+ */
 #define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) \
 	(BIT_LEN_MASK_32(__bitlen) << (__bitoffset))
 #define BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) \
@@ -1328,8 +1688,9 @@ BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000*/
 	(BIT_LEN_MASK_8(__bitlen) << (__bitoffset))
 
 /*Description:
-Return 4-byte value in host byte ordering from
-4-byte pointer in little-endian system.*/
+ * Return 4-byte value in host byte ordering from
+ * 4-byte pointer in little-endian system.
+ */
 #define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \
 	(EF4BYTE(*((u32 *)(__pstart))))
 #define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \
@@ -1337,28 +1698,10 @@ Return 4-byte value in host byte ordering from
 #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \
 	(EF1BYTE(*((u8 *)(__pstart))))
 
-/*Description:
-Translate subfield (continuous bits in little-endian) of 4-byte
-value to host byte ordering.*/
-#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
-	( \
-		(LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset))  & \
-		BIT_LEN_MASK_32(__bitlen) \
-	)
-#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
-	( \
-		(LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \
-		BIT_LEN_MASK_16(__bitlen) \
-	)
-#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
-	( \
-		(LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \
-		BIT_LEN_MASK_8(__bitlen) \
-	)
-
-/*Description:
-Mask subfield (continuous bits in little-endian) of 4-byte value
-and return the result in 4-byte value in host byte ordering.*/
+/* Description:
+ * Mask subfield (continuous bits in little-endian) of 4-byte value
+ * and return the result in 4-byte value in host byte ordering.
+ */
 #define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
 		LE_P4BYTE_TO_HOST_4BYTE(__pstart)  & \
@@ -1375,20 +1718,9 @@ and return the result in 4-byte value in host byte ordering.*/
 		(~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \
 	)
 
-/*Description:
-Set subfield of little-endian 4-byte value to specified value.	*/
-#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \
-	*((u32 *)(__pstart)) = EF4BYTE \
-	( \
-		LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \
-		((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \
-	);
-#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \
-	*((u16 *)(__pstart)) = EF2BYTE \
-	( \
-		LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \
-		((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \
-	);
+/* Description:
+ * Set subfield of little-endian 4-byte value to specified value.
+ */
 #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \
 	*((u8 *)(__pstart)) = EF1BYTE \
 	( \
@@ -1400,13 +1732,14 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 	mem access macro define end
 ****************************************/
 
-#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC)
+#define byte(x, n) ((x >> (8 * n)) & 0xff)
+
 #define RTL_WATCH_DOG_TIME	2000
 #define MSECS(t)		msecs_to_jiffies(t)
-#define WLAN_FC_GET_VERS(fc)	((fc) & IEEE80211_FCTL_VERS)
-#define WLAN_FC_GET_TYPE(fc)	((fc) & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc)	((fc) & IEEE80211_FCTL_STYPE)
-#define WLAN_FC_MORE_DATA(fc)	((fc) & IEEE80211_FCTL_MOREDATA)
+#define WLAN_FC_GET_VERS(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_VERS)
+#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)
@@ -1420,6 +1753,8 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 #define	RT_RF_OFF_LEVL_FW_32K		BIT(5)	/*FW in 32k */
 /*Always enable ASPM and Clock Req in initialization.*/
 #define	RT_RF_PS_LEVEL_ALWAYS_ASPM	BIT(6)
+/* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/
+#define	RT_PS_LEVEL_ASPM		BIT(7)
 /*When LPS is on, disable 2R if no packet is received or transmittd.*/
 #define	RT_RF_LPS_DISALBE_2R		BIT(30)
 #define	RT_RF_LPS_LEVEL_ASPM		BIT(31)	/*LPS with ASPM */
@@ -1433,15 +1768,6 @@ Set subfield of little-endian 4-byte value to specified value.	*/
 #define container_of_dwork_rtl(x, y, z) \
 	container_of(container_of(x, struct delayed_work, work), y, z)
 
-#define FILL_OCTET_STRING(_os, _octet, _len)	\
-		(_os).octet = (u8 *)(_octet);		\
-		(_os).length = (_len);
-
-#define CP_MACADDR(des, src)	\
-	((des)[0] = (src)[0], (des)[1] = (src)[1],\
-	(des)[2] = (src)[2], (des)[3] = (src)[3],\
-	(des)[4] = (src)[4], (des)[5] = (src)[5])
-
 static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr)
 {
 	return rtlpriv->io.read8_sync(rtlpriv, addr);
diff --git a/drivers/net/wireless/wl1251/acx.c b/drivers/net/wireless/wl1251/acx.c
index 64a0214..ef8370e 100644
--- a/drivers/net/wireless/wl1251/acx.c
+++ b/drivers/net/wireless/wl1251/acx.c
@@ -776,6 +776,31 @@ out:
 	return ret;
 }
 
+int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
+			u8 depth, enum wl1251_acx_low_rssi_type type)
+{
+	struct acx_low_rssi *rssi;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx low rssi");
+
+	rssi = kzalloc(sizeof(*rssi), GFP_KERNEL);
+	if (!rssi)
+		return -ENOMEM;
+
+	rssi->threshold = threshold;
+	rssi->weight = weight;
+	rssi->depth = depth;
+	rssi->type = type;
+
+	ret = wl1251_cmd_configure(wl, ACX_LOW_RSSI, rssi, sizeof(*rssi));
+	if (ret < 0)
+		wl1251_warning("failed to set low rssi threshold: %d", ret);
+
+	kfree(rssi);
+	return ret;
+}
+
 int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
 {
 	struct acx_preamble *acx;
@@ -978,6 +1003,34 @@ out:
 	return ret;
 }
 
+int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
+			  u8 max_consecutive)
+{
+	struct wl1251_acx_bet_enable *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx bet enable");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->enable = mode;
+	acx->max_consecutive = max_consecutive;
+
+	ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("wl1251 acx bet enable failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
 int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifs, u16 txop)
 {
diff --git a/drivers/net/wireless/wl1251/acx.h b/drivers/net/wireless/wl1251/acx.h
index efcc3aa..c2ba100 100644
--- a/drivers/net/wireless/wl1251/acx.h
+++ b/drivers/net/wireless/wl1251/acx.h
@@ -399,6 +399,49 @@ struct acx_rts_threshold {
 	u8 pad[2];
 } __packed;
 
+enum wl1251_acx_low_rssi_type {
+	/*
+	 * The event is a "Level" indication which keeps triggering
+	 * as long as the average RSSI is below the threshold.
+	 */
+	WL1251_ACX_LOW_RSSI_TYPE_LEVEL = 0,
+
+	/*
+	 * The event is an "Edge" indication which triggers
+	 * only when the RSSI threshold is crossed from above.
+	 */
+	WL1251_ACX_LOW_RSSI_TYPE_EDGE = 1,
+};
+
+struct acx_low_rssi {
+	struct acx_header header;
+
+	/*
+	 * The threshold (in dBm) below (or above after low rssi
+	 * indication) which the firmware generates an interrupt to the
+	 * host. This parameter is signed.
+	 */
+	s8 threshold;
+
+	/*
+	 * The weight of the current RSSI sample, before adding the new
+	 * sample, that is used to calculate the average RSSI.
+	 */
+	u8 weight;
+
+	/*
+	 * The number of Beacons/Probe response frames that will be
+	 * received before issuing the Low or Regained RSSI event.
+	 */
+	u8 depth;
+
+	/*
+	 * Configures how the Low RSSI Event is triggered. Refer to
+	 * enum wl1251_acx_low_rssi_type for more.
+	 */
+	u8 type;
+} __packed;
+
 struct acx_beacon_filter_option {
 	struct acx_header header;
 
@@ -1164,6 +1207,31 @@ struct wl1251_acx_wr_tbtt_and_dtim {
 	u8  padding;
 } __packed;
 
+enum wl1251_acx_bet_mode {
+	WL1251_ACX_BET_DISABLE = 0,
+	WL1251_ACX_BET_ENABLE = 1,
+};
+
+struct wl1251_acx_bet_enable {
+	struct acx_header header;
+
+	/*
+	 * Specifies if beacon early termination procedure is enabled or
+	 * disabled, see enum wl1251_acx_bet_mode.
+	 */
+	u8 enable;
+
+	/*
+	 * Specifies the maximum number of consecutive beacons that may be
+	 * early terminated. After this number is reached at least one full
+	 * beacon must be correctly received in FW before beacon ET
+	 * resumes. Range 0 - 255.
+	 */
+	u8 max_consecutive;
+
+	u8 padding[2];
+} __packed;
+
 struct wl1251_acx_ac_cfg {
 	struct acx_header header;
 
@@ -1393,6 +1461,8 @@ int wl1251_acx_cca_threshold(struct wl1251 *wl);
 int wl1251_acx_bcn_dtim_options(struct wl1251 *wl);
 int wl1251_acx_aid(struct wl1251 *wl, u16 aid);
 int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask);
+int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
+			u8 depth, enum wl1251_acx_low_rssi_type type);
 int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
 int wl1251_acx_cts_protect(struct wl1251 *wl,
 			    enum acx_ctsprotect_type ctsprotect);
@@ -1401,6 +1471,8 @@ int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime);
 int wl1251_acx_rate_policies(struct wl1251 *wl);
 int wl1251_acx_mem_cfg(struct wl1251 *wl);
 int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
+int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
+			  u8 max_consecutive);
 int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifs, u16 txop);
 int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c
index 712372e..dfc4579 100644
--- a/drivers/net/wireless/wl1251/event.c
+++ b/drivers/net/wireless/wl1251/event.c
@@ -90,6 +90,24 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 		}
 	}
 
+	if (wl->vif && wl->rssi_thold) {
+		if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) {
+			wl1251_debug(DEBUG_EVENT,
+				     "ROAMING_TRIGGER_LOW_RSSI_EVENT");
+			ieee80211_cqm_rssi_notify(wl->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+				GFP_KERNEL);
+		}
+
+		if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
+			wl1251_debug(DEBUG_EVENT,
+				     "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
+			ieee80211_cqm_rssi_notify(wl->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+				GFP_KERNEL);
+		}
+	}
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index 40372ba..12c9e63 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -375,7 +375,7 @@ out:
 	mutex_unlock(&wl->mutex);
 }
 
-static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1251 *wl = hw->priv;
 	unsigned long flags;
@@ -401,8 +401,6 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		wl->tx_queue_stopped = true;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
-
-	return NETDEV_TX_OK;
 }
 
 static int wl1251_op_start(struct ieee80211_hw *hw)
@@ -502,6 +500,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
 	wl->psm = 0;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+	wl->rssi_thold = 0;
 	wl->channel = WL1251_DEFAULT_CHANNEL;
 
 	wl1251_debugfs_reset(wl);
@@ -959,6 +958,16 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
 	if (ret < 0)
 		goto out;
 
+	if (changed & BSS_CHANGED_CQM) {
+		ret = wl1251_acx_low_rssi(wl, bss_conf->cqm_rssi_thold,
+					  WL1251_DEFAULT_LOW_RSSI_WEIGHT,
+					  WL1251_DEFAULT_LOW_RSSI_DEPTH,
+					  WL1251_ACX_LOW_RSSI_TYPE_EDGE);
+		if (ret < 0)
+			goto out;
+		wl->rssi_thold = bss_conf->cqm_rssi_thold;
+	}
+
 	if (changed & BSS_CHANGED_BSSID) {
 		memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
 
@@ -1313,9 +1322,11 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_BEACON_FILTER |
-		IEEE80211_HW_SUPPORTS_UAPSD;
+		IEEE80211_HW_SUPPORTS_UAPSD |
+		IEEE80211_HW_SUPPORTS_CQM_RSSI;
 
-	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+					 BIT(NL80211_IFTYPE_ADHOC);
 	wl->hw->wiphy->max_scan_ssids = 1;
 	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
 
@@ -1377,6 +1388,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
 	wl->psm_requested = false;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+	wl->rssi_thold = 0;
 	wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
 	wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
 	wl->vif = NULL;
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c
index 5ed47c8..9cc5147 100644
--- a/drivers/net/wireless/wl1251/ps.c
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -58,7 +58,6 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl)
 	unsigned long delay;
 
 	if (wl->psm) {
-		cancel_delayed_work(&wl->elp_work);
 		delay = msecs_to_jiffies(ELP_ENTRY_DELAY);
 		ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
 	}
@@ -69,6 +68,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
 	unsigned long timeout, start;
 	u32 elp_reg;
 
+	if (delayed_work_pending(&wl->elp_work))
+		cancel_delayed_work(&wl->elp_work);
+
 	if (!wl->elp)
 		return 0;
 
@@ -102,38 +104,6 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
 	return 0;
 }
 
-static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable)
-{
-	int ret;
-
-	if (enable) {
-		wl1251_debug(DEBUG_PSM, "sleep auth psm/elp");
-
-		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
-		if (ret < 0)
-			return ret;
-
-		wl1251_ps_elp_sleep(wl);
-	} else {
-		wl1251_debug(DEBUG_PSM, "sleep auth cam");
-
-		/*
-		 * When the target is in ELP, we can only
-		 * access the ELP control register. Thus,
-		 * we have to wake the target up before
-		 * changing the power authorization.
-		 */
-
-		wl1251_ps_elp_wakeup(wl);
-
-		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
 int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 {
 	int ret;
@@ -153,11 +123,16 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
+		ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_ENABLE,
+					    WL1251_DEFAULT_BET_CONSECUTIVE);
+		if (ret < 0)
+			return ret;
+
 		ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
 
-		ret = wl1251_ps_set_elp(wl, true);
+		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
 		if (ret < 0)
 			return ret;
 
@@ -166,7 +141,14 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 	case STATION_ACTIVE_MODE:
 	default:
 		wl1251_debug(DEBUG_PSM, "leaving psm");
-		ret = wl1251_ps_set_elp(wl, false);
+
+		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
+		if (ret < 0)
+			return ret;
+
+		/* disable BET */
+		ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_DISABLE,
+					    WL1251_DEFAULT_BET_CONSECUTIVE);
 		if (ret < 0)
 			return ret;
 
diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/wl1251/rx.c
index efa5360..c1b3b3f 100644
--- a/drivers/net/wireless/wl1251/rx.c
+++ b/drivers/net/wireless/wl1251/rx.c
@@ -78,9 +78,10 @@ static void wl1251_rx_status(struct wl1251 *wl,
 	 */
 	wl->noise = desc->rssi - desc->snr / 2;
 
-	status->freq = ieee80211_channel_to_frequency(desc->channel);
+	status->freq = ieee80211_channel_to_frequency(desc->channel,
+						      status->band);
 
-	status->flag |= RX_FLAG_TSFT;
+	status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -95,8 +96,52 @@ static void wl1251_rx_status(struct wl1251 *wl,
 	if (unlikely(!(desc->flags & RX_DESC_VALID_FCS)))
 		status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
+	switch (desc->rate) {
+		/* skip 1 and 12 Mbps because they have same value 0x0a */
+	case RATE_2MBPS:
+		status->rate_idx = 1;
+		break;
+	case RATE_5_5MBPS:
+		status->rate_idx = 2;
+		break;
+	case RATE_11MBPS:
+		status->rate_idx = 3;
+		break;
+	case RATE_6MBPS:
+		status->rate_idx = 4;
+		break;
+	case RATE_9MBPS:
+		status->rate_idx = 5;
+		break;
+	case RATE_18MBPS:
+		status->rate_idx = 7;
+		break;
+	case RATE_24MBPS:
+		status->rate_idx = 8;
+		break;
+	case RATE_36MBPS:
+		status->rate_idx = 9;
+		break;
+	case RATE_48MBPS:
+		status->rate_idx = 10;
+		break;
+	case RATE_54MBPS:
+		status->rate_idx = 11;
+		break;
+	}
+
+	/* for 1 and 12 Mbps we have to check the modulation */
+	if (desc->rate == RATE_1MBPS) {
+		if (!(desc->mod_pre & OFDM_RATE_BIT))
+			/* CCK -> RATE_1MBPS */
+			status->rate_idx = 0;
+		else
+			/* OFDM -> RATE_12MBPS */
+			status->rate_idx = 6;
+	}
 
-	/* FIXME: set status->rate_idx */
+	if (desc->mod_pre & SHORT_PREAMBLE_BIT)
+		status->flag |= RX_FLAG_SHORTPRE;
 }
 
 static void wl1251_rx_body(struct wl1251 *wl,
diff --git a/drivers/net/wireless/wl1251/tx.c b/drivers/net/wireless/wl1251/tx.c
index 554b4f9..28121c5 100644
--- a/drivers/net/wireless/wl1251/tx.c
+++ b/drivers/net/wireless/wl1251/tx.c
@@ -213,16 +213,30 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
 		wl1251_debug(DEBUG_TX, "skb offset %d", offset);
 
 		/* check whether the current skb can be used */
-		if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
-			unsigned char *src = skb->data;
+		if (skb_cloned(skb) || (skb_tailroom(skb) < offset)) {
+			struct sk_buff *newskb = skb_copy_expand(skb, 0, 3,
+								 GFP_KERNEL);
+
+			if (unlikely(newskb == NULL)) {
+				wl1251_error("Can't allocate skb!");
+				return -EINVAL;
+			}
 
-			/* align the buffer on a 4-byte boundary */
+			tx_hdr = (struct tx_double_buffer_desc *) newskb->data;
+
+			dev_kfree_skb_any(skb);
+			wl->tx_frames[tx_hdr->id] = skb = newskb;
+
+			offset = (4 - (long)skb->data) & 0x03;
+			wl1251_debug(DEBUG_TX, "new skb offset %d", offset);
+		}
+
+		/* align the buffer on a 4-byte boundary */
+		if (offset) {
+			unsigned char *src = skb->data;
 			skb_reserve(skb, offset);
 			memmove(skb->data, src, skb->len);
 			tx_hdr = (struct tx_double_buffer_desc *) skb->data;
-		} else {
-			wl1251_info("No handler, fixme!");
-			return -EINVAL;
 		}
 	}
 
@@ -368,7 +382,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
 {
 	struct ieee80211_tx_info *info;
 	struct sk_buff *skb;
-	int hdrlen, ret;
+	int hdrlen;
 	u8 *frame;
 
 	skb = wl->tx_frames[result->id];
@@ -407,40 +421,12 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
 	ieee80211_tx_status(wl->hw, skb);
 
 	wl->tx_frames[result->id] = NULL;
-
-	if (wl->tx_queue_stopped) {
-		wl1251_debug(DEBUG_TX, "cb: queue was stopped");
-
-		skb = skb_dequeue(&wl->tx_queue);
-
-		/* The skb can be NULL because tx_work might have been
-		   scheduled before the queue was stopped making the
-		   queue empty */
-
-		if (skb) {
-			ret = wl1251_tx_frame(wl, skb);
-			if (ret == -EBUSY) {
-				/* firmware buffer is still full */
-				wl1251_debug(DEBUG_TX, "cb: fw buffer "
-					     "still full");
-				skb_queue_head(&wl->tx_queue, skb);
-				return;
-			} else if (ret < 0) {
-				dev_kfree_skb(skb);
-				return;
-			}
-		}
-
-		wl1251_debug(DEBUG_TX, "cb: waking queues");
-		ieee80211_wake_queues(wl->hw);
-		wl->tx_queue_stopped = false;
-	}
 }
 
 /* Called upon reception of a TX complete interrupt */
 void wl1251_tx_complete(struct wl1251 *wl)
 {
-	int i, result_index, num_complete = 0;
+	int i, result_index, num_complete = 0, queue_len;
 	struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
 	unsigned long flags;
 
@@ -471,18 +457,22 @@ void wl1251_tx_complete(struct wl1251 *wl)
 		}
 	}
 
-	if (wl->tx_queue_stopped
-	    &&
-	    skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){
+	queue_len = skb_queue_len(&wl->tx_queue);
 
-		/* firmware buffer has space, restart queues */
+	if ((num_complete > 0) && (queue_len > 0)) {
+		/* firmware buffer has space, reschedule tx_work */
+		wl1251_debug(DEBUG_TX, "tx_complete: reschedule tx_work");
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	}
+
+	if (wl->tx_queue_stopped &&
+	    queue_len <= WL1251_TX_QUEUE_LOW_WATERMARK) {
+		/* tx_queue has space, restart queues */
 		wl1251_debug(DEBUG_TX, "tx_complete: waking queues");
 		spin_lock_irqsave(&wl->wl_lock, flags);
 		ieee80211_wake_queues(wl->hw);
 		wl->tx_queue_stopped = false;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
-		ieee80211_queue_work(wl->hw, &wl->tx_work);
-
 	}
 
 	/* Every completed frame needs to be acknowledged */
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
index c0ce2c8..bb23cd5 100644
--- a/drivers/net/wireless/wl1251/wl1251.h
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -370,6 +370,8 @@ struct wl1251 {
 	/* in dBm */
 	int power_level;
 
+	int rssi_thold;
+
 	struct wl1251_stats stats;
 	struct wl1251_debugfs debugfs;
 
@@ -410,6 +412,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl);
 
 #define WL1251_DEFAULT_CHANNEL 0
 
+#define WL1251_DEFAULT_BET_CONSECUTIVE 10
+
 #define CHIP_ID_1251_PG10	           (0x7010101)
 #define CHIP_ID_1251_PG11	           (0x7020101)
 #define CHIP_ID_1251_PG12	           (0x7030101)
@@ -431,4 +435,7 @@ void wl1251_disable_interrupts(struct wl1251 *wl);
 #define WL1251_PART_WORK_REG_START	REGISTERS_BASE
 #define WL1251_PART_WORK_REG_SIZE	REGISTERS_WORK_SIZE
 
+#define WL1251_DEFAULT_LOW_RSSI_WEIGHT          10
+#define WL1251_DEFAULT_LOW_RSSI_DEPTH           10
+
 #endif
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h
index 1846280..1417b14 100644
--- a/drivers/net/wireless/wl1251/wl12xx_80211.h
+++ b/drivers/net/wireless/wl1251/wl12xx_80211.h
@@ -54,7 +54,6 @@
 
 /* This really should be 8, but not for our firmware */
 #define MAX_SUPPORTED_RATES 32
-#define COUNTRY_STRING_LEN 3
 #define MAX_COUNTRY_TRIPLETS 32
 
 /* Headers */
@@ -98,7 +97,7 @@ struct country_triplet {
 
 struct wl12xx_ie_country {
 	struct wl12xx_ie_header header;
-	u8 country_string[COUNTRY_STRING_LEN];
+	u8 country_string[IEEE80211_COUNTRY_STRING_LEN];
 	struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
 } __packed;
 
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 0e65bce..692ebff 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -54,7 +54,7 @@ config WL12XX_SDIO
 
 config WL12XX_SDIO_TEST
 	tristate "TI wl12xx SDIO testing support"
-	depends on WL12XX && MMC
+	depends on WL12XX && MMC && WL12XX_SDIO
 	default n
 	---help---
 	  This module adds support for the SDIO bus testing with the
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index cc4068d..a3db755 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -751,10 +751,10 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
 	return 0;
 }
 
-int wl1271_acx_rate_policies(struct wl1271 *wl)
+int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
 {
-	struct acx_rate_policy *acx;
-	struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
+	struct acx_sta_rate_policy *acx;
+	struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
 	int idx = 0;
 	int ret = 0;
 
@@ -783,6 +783,10 @@ int wl1271_acx_rate_policies(struct wl1271 *wl)
 
 	acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
 
+	wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
+		acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
+		acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
+
 	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("Setting of rate policies failed: %d", ret);
@@ -794,6 +798,38 @@ out:
 	return ret;
 }
 
+int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
+		      u8 idx)
+{
+	struct acx_ap_rate_policy *acx;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_ACX, "acx ap rate policy");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->rate_policy.enabled_rates = cpu_to_le32(c->enabled_rates);
+	acx->rate_policy.short_retry_limit = c->short_retry_limit;
+	acx->rate_policy.long_retry_limit = c->long_retry_limit;
+	acx->rate_policy.aflags = c->aflags;
+
+	acx->rate_policy_idx = cpu_to_le32(idx);
+
+	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("Setting of ap rate policy failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
 int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifsn, u16 txop)
 {
@@ -915,9 +951,9 @@ out:
 	return ret;
 }
 
-int wl1271_acx_mem_cfg(struct wl1271 *wl)
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
 {
-	struct wl1271_acx_config_memory *mem_conf;
+	struct wl1271_acx_ap_config_memory *mem_conf;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@@ -929,10 +965,10 @@ int wl1271_acx_mem_cfg(struct wl1271 *wl)
 	}
 
 	/* memory config */
-	mem_conf->num_stations = DEFAULT_NUM_STATIONS;
-	mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
-	mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
-	mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+	mem_conf->num_stations = wl->conf.mem.num_stations;
+	mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
+	mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
+	mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
 	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
 
 	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
@@ -947,13 +983,45 @@ out:
 	return ret;
 }
 
-int wl1271_acx_init_mem_config(struct wl1271 *wl)
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
 {
+	struct wl1271_acx_sta_config_memory *mem_conf;
 	int ret;
 
-	ret = wl1271_acx_mem_cfg(wl);
-	if (ret < 0)
-		return ret;
+	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
+
+	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+	if (!mem_conf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* memory config */
+	mem_conf->num_stations = wl->conf.mem.num_stations;
+	mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
+	mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
+	mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
+	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
+	mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
+	mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
+	mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks;
+	mem_conf->tx_min = wl->conf.mem.tx_min;
+
+	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+				   sizeof(*mem_conf));
+	if (ret < 0) {
+		wl1271_warning("wl1271 mem config failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(mem_conf);
+	return ret;
+}
+
+int wl1271_acx_init_mem_config(struct wl1271 *wl)
+{
+	int ret;
 
 	wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
 				     GFP_KERNEL);
@@ -1233,6 +1301,7 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 	struct wl1271_acx_ht_capabilities *acx;
 	u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	int ret = 0;
+	u32 ht_capabilites = 0;
 
 	wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
 
@@ -1244,27 +1313,26 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 
 	/* Allow HT Operation ? */
 	if (allow_ht_operation) {
-		acx->ht_capabilites =
+		ht_capabilites =
 			WL1271_ACX_FW_CAP_HT_OPERATION;
 		if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
-			acx->ht_capabilites |=
+			ht_capabilites |=
 				WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
 		if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
-			acx->ht_capabilites |=
+			ht_capabilites |=
 				WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
 		if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
-			acx->ht_capabilites |=
+			ht_capabilites |=
 				WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
 
 		/* get data from A-MPDU parameters field */
 		acx->ampdu_max_length = ht_cap->ampdu_factor;
 		acx->ampdu_min_spacing = ht_cap->ampdu_density;
-
-		memcpy(acx->mac_address, mac_address, ETH_ALEN);
-	} else { /* HT operations are not allowed */
-		acx->ht_capabilites = 0;
 	}
 
+	memcpy(acx->mac_address, mac_address, ETH_ALEN);
+	acx->ht_capabilites = cpu_to_le32(ht_capabilites);
+
 	ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx ht capabilities setting failed: %d", ret);
@@ -1293,7 +1361,8 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
 	acx->ht_protection =
 		(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
 	acx->rifs_mode = 0;
-	acx->gf_protection = 0;
+	acx->gf_protection =
+		!!(ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 	acx->ht_tx_burst_limit = 0;
 	acx->dual_cts_protection = 0;
 
@@ -1309,6 +1378,91 @@ out:
 	return ret;
 }
 
+/* Configure BA session initiator/receiver parameters setting in the FW. */
+int wl1271_acx_set_ba_session(struct wl1271 *wl,
+			       enum ieee80211_back_parties direction,
+			       u8 tid_index, u8 policy)
+{
+	struct wl1271_acx_ba_session_policy *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx ba session setting");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* ANY role */
+	acx->role_id = 0xff;
+	acx->tid = tid_index;
+	acx->enable = policy;
+	acx->ba_direction = direction;
+
+	switch (direction) {
+	case WLAN_BACK_INITIATOR:
+		acx->win_size = wl->conf.ht.tx_ba_win_size;
+		acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
+		break;
+	case WLAN_BACK_RECIPIENT:
+		acx->win_size = RX_BA_WIN_SIZE;
+		acx->inactivity_timeout = 0;
+		break;
+	default:
+		wl1271_error("Incorrect acx command id=%x\n", direction);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = wl1271_cmd_configure(wl,
+				   ACX_BA_SESSION_POLICY_CFG,
+				   acx,
+				   sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx ba session setting failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+/* setup BA session receiver setting in the FW. */
+int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
+					bool enable)
+{
+	struct wl1271_acx_ba_receiver_setup *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx ba receiver session setting");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Single link for now */
+	acx->link_id = 1;
+	acx->tid = tid_index;
+	acx->enable = enable;
+	acx->win_size = 0;
+	acx->ssn = ssn;
+
+	ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
+				   sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx ba receiver session failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
 {
 	struct wl1271_acx_fw_tsf_information *tsf_info;
@@ -1334,3 +1488,82 @@ out:
 	kfree(tsf_info);
 	return ret;
 }
+
+int wl1271_acx_max_tx_retry(struct wl1271 *wl)
+{
+	struct wl1271_acx_max_tx_retry *acx = NULL;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx max tx retry");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx)
+		return -ENOMEM;
+
+	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
+
+	ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx max tx retry failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1271_acx_config_ps(struct wl1271 *wl)
+{
+	struct wl1271_acx_config_ps *config_ps;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx config ps");
+
+	config_ps = kzalloc(sizeof(*config_ps), GFP_KERNEL);
+	if (!config_ps) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	config_ps->exit_retries = wl->conf.conn.psm_exit_retries;
+	config_ps->enter_retries = wl->conf.conn.psm_entry_retries;
+	config_ps->null_data_rate = cpu_to_le32(wl->basic_rate);
+
+	ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps,
+				   sizeof(*config_ps));
+
+	if (ret < 0) {
+		wl1271_warning("acx config ps failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(config_ps);
+	return ret;
+}
+
+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr)
+{
+	struct wl1271_acx_inconnection_sta *acx = NULL;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx set inconnaction sta %pM", addr);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx)
+		return -ENOMEM;
+
+	memcpy(acx->addr, addr, ETH_ALEN);
+
+	ret = wl1271_cmd_configure(wl, ACX_UPDATE_INCONNECTION_STA_LIST,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx set inconnaction sta failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 7bd8e4d..dd19b01 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -133,7 +133,6 @@ enum {
 
 #define DEFAULT_UCAST_PRIORITY          0
 #define DEFAULT_RX_Q_PRIORITY           0
-#define DEFAULT_NUM_STATIONS            1
 #define DEFAULT_RXQ_PRIORITY            0 /* low 0 .. 15 high  */
 #define DEFAULT_RXQ_TYPE                0x07    /* All frames, Data/Ctrl/Mgmt */
 #define TRACE_BUFFER_MAX_SIZE           256
@@ -747,13 +746,23 @@ struct acx_rate_class {
 #define ACX_TX_BASIC_RATE      0
 #define ACX_TX_AP_FULL_RATE    1
 #define ACX_TX_RATE_POLICY_CNT 2
-struct acx_rate_policy {
+struct acx_sta_rate_policy {
 	struct acx_header header;
 
 	__le32 rate_class_cnt;
 	struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
 } __packed;
 
+
+#define ACX_TX_AP_MODE_MGMT_RATE 4
+#define ACX_TX_AP_MODE_BCST_RATE 5
+struct acx_ap_rate_policy {
+	struct acx_header header;
+
+	__le32 rate_policy_idx;
+	struct acx_rate_class rate_policy;
+} __packed;
+
 struct acx_ac_cfg {
 	struct acx_header header;
 	u8 ac;
@@ -787,12 +796,9 @@ struct acx_tx_config_options {
 	__le16 tx_compl_threshold;   /* number of packets */
 } __packed;
 
-#define ACX_RX_MEM_BLOCKS     70
-#define ACX_TX_MIN_MEM_BLOCKS 40
 #define ACX_TX_DESCRIPTORS    32
-#define ACX_NUM_SSID_PROFILES 1
 
-struct wl1271_acx_config_memory {
+struct wl1271_acx_ap_config_memory {
 	struct acx_header header;
 
 	u8 rx_mem_block_num;
@@ -802,6 +808,20 @@ struct wl1271_acx_config_memory {
 	__le32 total_tx_descriptors;
 } __packed;
 
+struct wl1271_acx_sta_config_memory {
+	struct acx_header header;
+
+	u8 rx_mem_block_num;
+	u8 tx_min_mem_block_num;
+	u8 num_stations;
+	u8 num_ssid_profiles;
+	__le32 total_tx_descriptors;
+	u8 dyn_mem_enable;
+	u8 tx_free_req;
+	u8 rx_free_req;
+	u8 tx_min;
+} __packed;
+
 struct wl1271_acx_mem_map {
 	struct acx_header header;
 
@@ -1051,6 +1071,59 @@ struct wl1271_acx_ht_information {
 	u8 padding[3];
 } __packed;
 
+#define RX_BA_WIN_SIZE 8
+
+struct wl1271_acx_ba_session_policy {
+	struct acx_header header;
+	/*
+	 * Specifies role Id, Range 0-7, 0xFF means ANY role.
+	 * Future use. For now this field is irrelevant
+	 */
+	u8 role_id;
+	/*
+	 * Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id.
+	 * Not applicable if Role Id is set to ANY.
+	 */
+	u8 link_id;
+
+	u8 tid;
+
+	u8 enable;
+
+	/* Windows size in number of packets */
+	u16 win_size;
+
+	/*
+	 * As initiator inactivity timeout in time units(TU) of 1024us.
+	 * As receiver reserved
+	 */
+	u16 inactivity_timeout;
+
+	/* Initiator = 1/Receiver = 0 */
+	u8 ba_direction;
+
+	u8 padding[3];
+} __packed;
+
+struct wl1271_acx_ba_receiver_setup {
+	struct acx_header header;
+
+	/* Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id */
+	u8 link_id;
+
+	u8 tid;
+
+	u8 enable;
+
+	u8 padding[1];
+
+	/* Windows size in number of packets */
+	u16 win_size;
+
+	/* BA session starting sequence number.  RANGE 0-FFF */
+	u16 ssn;
+} __packed;
+
 struct wl1271_acx_fw_tsf_information {
 	struct acx_header header;
 
@@ -1062,6 +1135,33 @@ struct wl1271_acx_fw_tsf_information {
 	u8 padding[3];
 } __packed;
 
+struct wl1271_acx_max_tx_retry {
+	struct acx_header header;
+
+	/*
+	 * the number of frames transmission failures before
+	 * issuing the aging event.
+	 */
+	__le16 max_tx_retry;
+	u8 padding_1[2];
+} __packed;
+
+struct wl1271_acx_config_ps {
+	struct acx_header header;
+
+	u8 exit_retries;
+	u8 enter_retries;
+	u8 padding[2];
+	__le32 null_data_rate;
+} __packed;
+
+struct wl1271_acx_inconnection_sta {
+	struct acx_header header;
+
+	u8 addr[ETH_ALEN];
+	u8 padding1[2];
+} __packed;
+
 enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
@@ -1113,22 +1213,24 @@ enum {
 	ACX_RSSI_SNR_WEIGHTS        = 0x0052,
 	ACX_KEEP_ALIVE_MODE         = 0x0053,
 	ACX_SET_KEEP_ALIVE_CONFIG   = 0x0054,
-	ACX_BA_SESSION_RESPONDER_POLICY = 0x0055,
-	ACX_BA_SESSION_INITIATOR_POLICY = 0x0056,
+	ACX_BA_SESSION_POLICY_CFG   = 0x0055,
+	ACX_BA_SESSION_RX_SETUP     = 0x0056,
 	ACX_PEER_HT_CAP             = 0x0057,
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
 	ACX_SET_DCO_ITRIM_PARAMS    = 0x0061,
+	ACX_GEN_FW_CMD              = 0x0070,
+	ACX_HOST_IF_CFG_BITMAP      = 0x0071,
+	ACX_MAX_TX_FAILURE          = 0x0072,
+	ACX_UPDATE_INCONNECTION_STA_LIST = 0x0073,
 	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
 	DOT11_CUR_TX_PWR            = 0x100D,
 	DOT11_RX_DOT11_MODE         = 0x1012,
 	DOT11_RTS_THRESHOLD         = 0x1013,
 	DOT11_GROUP_ADDRESS_TBL     = 0x1014,
 	ACX_PM_CONFIG               = 0x1016,
-
-	MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
-
-	MAX_IE = 0xFFFF
+	ACX_CONFIG_PS               = 0x1017,
+	ACX_CONFIG_HANGOVER         = 0x1018,
 };
 
 
@@ -1160,7 +1262,9 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
 int wl1271_acx_cts_protect(struct wl1271 *wl,
 			   enum acx_ctsprotect_type ctsprotect);
 int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
-int wl1271_acx_rate_policies(struct wl1271 *wl);
+int wl1271_acx_sta_rate_policies(struct wl1271 *wl);
+int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
+		      u8 idx);
 int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifsn, u16 txop);
 int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
@@ -1168,7 +1272,8 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
 		       u32 apsd_conf0, u32 apsd_conf1);
 int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold);
 int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
@@ -1185,6 +1290,14 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 				    bool allow_ht_operation);
 int wl1271_acx_set_ht_information(struct wl1271 *wl,
 				   u16 ht_operation_mode);
+int wl1271_acx_set_ba_session(struct wl1271 *wl,
+			      enum ieee80211_back_parties direction,
+			      u8 tid_index, u8 policy);
+int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
+				       bool enable);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
+int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_config_ps(struct wl1271 *wl);
+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 4df04f8..6934dff 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -28,6 +28,7 @@
 #include "boot.h"
 #include "io.h"
 #include "event.h"
+#include "rx.h"
 
 static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
 	[PART_DOWN] = {
@@ -100,6 +101,22 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
 	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
 }
 
+static void wl1271_parse_fw_ver(struct wl1271 *wl)
+{
+	int ret;
+
+	ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
+		     &wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
+		     &wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
+		     &wl->chip.fw_ver[4]);
+
+	if (ret != 5) {
+		wl1271_warning("fw version incorrect value");
+		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
+		return;
+	}
+}
+
 static void wl1271_boot_fw_version(struct wl1271 *wl)
 {
 	struct wl1271_static_data static_data;
@@ -107,11 +124,13 @@ static void wl1271_boot_fw_version(struct wl1271 *wl)
 	wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
 		    false);
 
-	strncpy(wl->chip.fw_ver, static_data.fw_version,
-		sizeof(wl->chip.fw_ver));
+	strncpy(wl->chip.fw_ver_str, static_data.fw_version,
+		sizeof(wl->chip.fw_ver_str));
 
 	/* make sure the string is NULL-terminated */
-	wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
+	wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';
+
+	wl1271_parse_fw_ver(wl);
 }
 
 static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
@@ -231,7 +250,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
 	 */
 	if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
 	    wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
-		if (wl->nvs->general_params.dual_mode_select)
+		/* for now 11a is unsupported in AP mode */
+		if (wl->bss_type != BSS_TYPE_AP_BSS &&
+		    wl->nvs->general_params.dual_mode_select)
 			wl->enable_11a = true;
 	}
 
@@ -431,6 +452,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 		PSPOLL_DELIVERY_FAILURE_EVENT_ID |
 		SOFT_GEMINI_SENSE_EVENT_ID;
 
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
+
 	ret = wl1271_event_unmask(wl);
 	if (ret < 0) {
 		wl1271_error("EVENT mask setting failed");
@@ -464,6 +488,9 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
 	fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
 
 	wl->hw_pg_ver = (s8)fuse;
+
+	if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
+		wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
 }
 
 /* uploads NVS and firmware */
@@ -595,8 +622,7 @@ int wl1271_boot(struct wl1271 *wl)
 	wl1271_boot_enable_interrupts(wl);
 
 	/* set the wl1271 default filters */
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+	wl1271_set_default_filters(wl);
 
 	wl1271_event_mbox_config(wl);
 
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index d67dcff..17229b8 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -59,6 +59,11 @@ struct wl1271_static_data {
 #define PG_VER_MASK          0x3c
 #define PG_VER_OFFSET        2
 
+#define PG_MAJOR_VER_MASK    0x3
+#define PG_MAJOR_VER_OFFSET  0x0
+#define PG_MINOR_VER_MASK    0xc
+#define PG_MINOR_VER_OFFSET  0x2
+
 #define CMD_MBOX_ADDRESS     0x407B4
 
 #define POLARITY_LOW         BIT(1)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 0106628..f0aa7ab 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -36,6 +36,7 @@
 #include "wl12xx_80211.h"
 #include "cmd.h"
 #include "event.h"
+#include "tx.h"
 
 #define WL1271_CMD_FAST_POLL_COUNT       50
 
@@ -62,6 +63,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
 	cmd->status = 0;
 
 	WARN_ON(len % 4 != 0);
+	WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags));
 
 	wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
 
@@ -221,7 +223,7 @@ int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
  * Poll the mailbox event field until any of the bits in the mask is set or a
  * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
  */
-static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
+static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
 {
 	u32 events_vector, event;
 	unsigned long timeout;
@@ -230,7 +232,8 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
 
 	do {
 		if (time_after(jiffies, timeout)) {
-			ieee80211_queue_work(wl->hw, &wl->recovery_work);
+			wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
+				     (int)mask);
 			return -ETIMEDOUT;
 		}
 
@@ -248,6 +251,19 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
 	return 0;
 }
 
+static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
+{
+	int ret;
+
+	ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
+	if (ret != 0) {
+		ieee80211_queue_work(wl->hw, &wl->recovery_work);
+		return ret;
+	}
+
+	return 0;
+}
+
 int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 {
 	struct wl1271_cmd_join *join;
@@ -271,6 +287,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 	join->rx_filter_options = cpu_to_le32(wl->rx_filter);
 	join->bss_type = bss_type;
 	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	join->supported_rate_set = cpu_to_le32(wl->rate_set);
 
 	if (wl->band == IEEE80211_BAND_5GHZ)
 		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -288,6 +305,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 	wl->tx_security_last_seq = 0;
 	wl->tx_security_seq = 0;
 
+	wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
+		join->basic_rate_set, join->supported_rate_set);
+
 	ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd join");
@@ -439,7 +459,7 @@ out:
 	return ret;
 }
 
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
 {
 	struct wl1271_cmd_ps_params *ps_params = NULL;
 	int ret = 0;
@@ -453,10 +473,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
 	}
 
 	ps_params->ps_mode = ps_mode;
-	ps_params->send_null_data = send;
-	ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
-	ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
-	ps_params->null_data_rate = cpu_to_le32(rates);
 
 	ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
 			      sizeof(*ps_params), 0);
@@ -490,8 +506,8 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
 	cmd->len = cpu_to_le16(buf_len);
 	cmd->template_type = template_id;
 	cmd->enabled_rates = cpu_to_le32(rates);
-	cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit;
-	cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit;
+	cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit;
+	cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit;
 	cmd->index = index;
 
 	if (buf)
@@ -659,15 +675,15 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
 
 	/* llc layer */
 	memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header));
-	tmpl.llc_type = htons(ETH_P_ARP);
+	tmpl.llc_type = cpu_to_be16(ETH_P_ARP);
 
 	/* arp header */
 	arp_hdr = &tmpl.arp_hdr;
-	arp_hdr->ar_hrd = htons(ARPHRD_ETHER);
-	arp_hdr->ar_pro = htons(ETH_P_IP);
+	arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER);
+	arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP);
 	arp_hdr->ar_hln = ETH_ALEN;
 	arp_hdr->ar_pln = 4;
-	arp_hdr->ar_op = htons(ARPOP_REPLY);
+	arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
 
 	/* arp payload */
 	memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN);
@@ -702,9 +718,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
 				       wl->basic_rate);
 }
 
-int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
+int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
 {
-	struct wl1271_cmd_set_keys *cmd;
+	struct wl1271_cmd_set_sta_keys *cmd;
 	int ret = 0;
 
 	wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
@@ -731,11 +747,42 @@ out:
 	return ret;
 }
 
-int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
+{
+	struct wl1271_cmd_set_ap_keys *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->key_id = id;
+	cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
+	cmd->key_action = cpu_to_le16(KEY_SET_ID);
+	cmd->key_type = KEY_WEP;
+
+	ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+
+	return ret;
+}
+
+int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		       u8 key_size, const u8 *key, const u8 *addr,
 		       u32 tx_seq_32, u16 tx_seq_16)
 {
-	struct wl1271_cmd_set_keys *cmd;
+	struct wl1271_cmd_set_sta_keys *cmd;
 	int ret = 0;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -788,6 +835,67 @@ out:
 	return ret;
 }
 
+int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+			u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
+			u16 tx_seq_16)
+{
+	struct wl1271_cmd_set_ap_keys *cmd;
+	int ret = 0;
+	u8 lid_type;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	if (hlid == WL1271_AP_BROADCAST_HLID) {
+		if (key_type == KEY_WEP)
+			lid_type = WEP_DEFAULT_LID_TYPE;
+		else
+			lid_type = BROADCAST_LID_TYPE;
+	} else {
+		lid_type = UNICAST_LID_TYPE;
+	}
+
+	wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d"
+		     " hlid: %d", (int)action, (int)id, (int)lid_type,
+		     (int)key_type, (int)hlid);
+
+	cmd->lid_key_type = lid_type;
+	cmd->hlid = hlid;
+	cmd->key_action = cpu_to_le16(action);
+	cmd->key_size = key_size;
+	cmd->key_type = key_type;
+	cmd->key_id = id;
+	cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
+	cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
+
+	if (key_type == KEY_TKIP) {
+		/*
+		 * We get the key in the following form:
+		 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
+		 * but the target is expecting:
+		 * TKIP - RX MIC - TX MIC
+		 */
+		memcpy(cmd->key, key, 16);
+		memcpy(cmd->key + 16, key + 24, 8);
+		memcpy(cmd->key + 24, key + 16, 8);
+	} else {
+		memcpy(cmd->key, key, key_size);
+	}
+
+	wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd));
+
+	ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_warning("could not set ap keys");
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
 int wl1271_cmd_disconnect(struct wl1271 *wl)
 {
 	struct wl1271_cmd_disconnect *cmd;
@@ -850,3 +958,180 @@ out_free:
 out:
 	return ret;
 }
+
+int wl1271_cmd_start_bss(struct wl1271 *wl)
+{
+	struct wl1271_cmd_bss_start *cmd;
+	struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd start bss");
+
+	/*
+	 * FIXME: We currently do not support hidden SSID. The real SSID
+	 * should be fetched from mac80211 first.
+	 */
+	if (wl->ssid_len == 0) {
+		wl1271_warning("Hidden SSID currently not supported for AP");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
+
+	cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
+	cmd->bss_index = WL1271_AP_BSS_INDEX;
+	cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
+	cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
+	cmd->dtim_interval = bss_conf->dtim_period;
+	cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
+	cmd->channel = wl->channel;
+	cmd->ssid_len = wl->ssid_len;
+	cmd->ssid_type = SSID_TYPE_PUBLIC;
+	memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
+
+	switch (wl->band) {
+	case IEEE80211_BAND_2GHZ:
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		cmd->band = RADIO_BAND_5GHZ;
+		break;
+	default:
+		wl1271_warning("bss start - unknown band: %d", (int)wl->band);
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd start bss");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_stop_bss(struct wl1271 *wl)
+{
+	struct wl1271_cmd_bss_start *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd stop bss");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->bss_index = WL1271_AP_BSS_INDEX;
+
+	ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd stop bss");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
+{
+	struct wl1271_cmd_add_sta *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* currently we don't support UAPSD */
+	cmd->sp_len = 0;
+
+	memcpy(cmd->addr, sta->addr, ETH_ALEN);
+	cmd->bss_index = WL1271_AP_BSS_INDEX;
+	cmd->aid = sta->aid;
+	cmd->hlid = hlid;
+
+	/*
+	 * FIXME: Does STA support QOS? We need to propagate this info from
+	 * hostapd. Currently not that important since this is only used for
+	 * sending the correct flavor of null-data packet in response to a
+	 * trigger.
+	 */
+	cmd->wmm = 0;
+
+	cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
+						sta->supp_rates[wl->band]));
+
+	wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
+
+	ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd add sta");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
+{
+	struct wl1271_cmd_remove_sta *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->hlid = hlid;
+	/* We never send a deauth, mac80211 is in charge of this */
+	cmd->reason_opcode = 0;
+	cmd->send_deauth_flag = 0;
+
+	ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd remove sta");
+		goto out_free;
+	}
+
+	/*
+	 * We are ok with a timeout here. The event is sometimes not sent
+	 * due to a firmware bug.
+	 */
+	wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID);
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 2a1d9db..54c12e7 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -39,7 +39,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
 			   size_t len);
 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
@@ -54,12 +54,20 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
 int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
 int wl1271_build_qos_null_data(struct wl1271 *wl);
 int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
-int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
-int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
-		       u8 key_size, const u8 *key, const u8 *addr,
-		       u32 tx_seq_32, u16 tx_seq_16);
+int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id);
+int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
+int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+			   u8 key_size, const u8 *key, const u8 *addr,
+			   u32 tx_seq_32, u16 tx_seq_16);
+int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+			  u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
+			  u16 tx_seq_16);
 int wl1271_cmd_disconnect(struct wl1271 *wl);
 int wl1271_cmd_set_sta_state(struct wl1271 *wl);
+int wl1271_cmd_start_bss(struct wl1271 *wl);
+int wl1271_cmd_stop_bss(struct wl1271 *wl);
+int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
+int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
@@ -98,6 +106,12 @@ enum wl1271_commands {
 	CMD_STOP_PERIODIC_SCAN       = 51,
 	CMD_SET_STA_STATE            = 52,
 
+	/* AP mode commands */
+	CMD_BSS_START                = 60,
+	CMD_BSS_STOP                 = 61,
+	CMD_ADD_STA                  = 62,
+	CMD_REMOVE_STA               = 63,
+
 	NUM_COMMANDS,
 	MAX_COMMAND_ID = 0xFFFF,
 };
@@ -126,6 +140,14 @@ enum cmd_templ {
 				  * For CTS-to-self (FastCTS) mechanism
 				  * for BT/WLAN coexistence (SoftGemini). */
 	CMD_TEMPL_ARP_RSP,
+	CMD_TEMPL_LINK_MEASUREMENT_REPORT,
+
+	/* AP-mode specific */
+	CMD_TEMPL_AP_BEACON = 13,
+	CMD_TEMPL_AP_PROBE_RESPONSE,
+	CMD_TEMPL_AP_ARP_RSP,
+	CMD_TEMPL_DEAUTH_AP,
+
 	CMD_TEMPL_MAX = 0xff
 };
 
@@ -195,6 +217,7 @@ struct wl1271_cmd_join {
 	 * ACK or CTS frames).
 	 */
 	__le32 basic_rate_set;
+	__le32 supported_rate_set;
 	u8 dtim_interval;
 	/*
 	 * bits 0-2: This bitwise field specifies the type
@@ -257,20 +280,11 @@ struct wl1271_cmd_ps_params {
 	struct wl1271_cmd_header header;
 
 	u8 ps_mode; /* STATION_* */
-	u8 send_null_data; /* Do we have to send NULL data packet ? */
-	u8 retries; /* Number of retires for the initial NULL data packet */
-
-	 /*
-	  * TUs during which the target stays awake after switching
-	  * to power save mode.
-	  */
-	u8 hang_over_period;
-	__le32 null_data_rate;
+	u8 padding[3];
 } __packed;
 
 /* HW encryption keys */
 #define NUM_ACCESS_CATEGORIES_COPY 4
-#define MAX_KEY_SIZE 32
 
 enum wl1271_cmd_key_action {
 	KEY_ADD_OR_REPLACE = 1,
@@ -289,7 +303,7 @@ enum wl1271_cmd_key_type {
 
 /* FIXME: Add description for key-types */
 
-struct wl1271_cmd_set_keys {
+struct wl1271_cmd_set_sta_keys {
 	struct wl1271_cmd_header header;
 
 	/* Ignored for default WEP key */
@@ -318,6 +332,57 @@ struct wl1271_cmd_set_keys {
 	__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
 } __packed;
 
+enum wl1271_cmd_lid_key_type {
+	UNICAST_LID_TYPE     = 0,
+	BROADCAST_LID_TYPE   = 1,
+	WEP_DEFAULT_LID_TYPE = 2
+};
+
+struct wl1271_cmd_set_ap_keys {
+	struct wl1271_cmd_header header;
+
+	/*
+	 * Indicates whether the HLID is a unicast key set
+	 * or broadcast key set. A special value 0xFF is
+	 * used to indicate that the HLID is on WEP-default
+	 * (multi-hlids). of type wl1271_cmd_lid_key_type.
+	 */
+	u8 hlid;
+
+	/*
+	 * In WEP-default network (hlid == 0xFF) used to
+	 * indicate which network STA/IBSS/AP role should be
+	 * changed
+	 */
+	u8 lid_key_type;
+
+	/*
+	 * Key ID - For TKIP and AES key types, this field
+	 * indicates the value that should be inserted into
+	 * the KeyID field of frames transmitted using this
+	 * key entry. For broadcast keys the index use as a
+	 * marker for TX/RX key.
+	 * For WEP default network (HLID=0xFF), this field
+	 * indicates the ID of the key to add or remove.
+	 */
+	u8 key_id;
+	u8 reserved_1;
+
+	/* key_action_e */
+	__le16 key_action;
+
+	/* key size in bytes */
+	u8 key_size;
+
+	/* key_type_e */
+	u8 key_type;
+
+	/* This field holds the security key data to add to the STA table */
+	u8 key[MAX_KEY_SIZE];
+	__le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
+	__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
+} __packed;
+
 struct wl1271_cmd_test_header {
 	u8 id;
 	u8 padding[3];
@@ -412,4 +477,68 @@ struct wl1271_cmd_set_sta_state {
 	u8 padding[3];
 } __packed;
 
+enum wl1271_ssid_type {
+	SSID_TYPE_PUBLIC = 0,
+	SSID_TYPE_HIDDEN = 1
+};
+
+struct wl1271_cmd_bss_start {
+	struct wl1271_cmd_header header;
+
+	/* wl1271_ssid_type */
+	u8 ssid_type;
+	u8 ssid_len;
+	u8 ssid[IW_ESSID_MAX_SIZE];
+	u8 padding_1[2];
+
+	/* Basic rate set */
+	__le32 basic_rate_set;
+	/* Aging period in seconds*/
+	__le16 aging_period;
+
+	/*
+	 * This field specifies the time between target beacon
+	 * transmission times (TBTTs), in time units (TUs).
+	 * Valid values are 1 to 1024.
+	 */
+	__le16 beacon_interval;
+	u8 bssid[ETH_ALEN];
+	u8 bss_index;
+	/* Radio band */
+	u8 band;
+	u8 channel;
+	/* The host link id for the AP's global queue */
+	u8 global_hlid;
+	/* The host link id for the AP's broadcast queue */
+	u8 broadcast_hlid;
+	/* DTIM count */
+	u8 dtim_interval;
+	/* Beacon expiry time in ms */
+	u8 beacon_expiry;
+	u8 padding_2[3];
+} __packed;
+
+struct wl1271_cmd_add_sta {
+	struct wl1271_cmd_header header;
+
+	u8 addr[ETH_ALEN];
+	u8 hlid;
+	u8 aid;
+	u8 psd_type[NUM_ACCESS_CATEGORIES_COPY];
+	__le32 supported_rates;
+	u8 bss_index;
+	u8 sp_len;
+	u8 wmm;
+	u8 padding1;
+} __packed;
+
+struct wl1271_cmd_remove_sta {
+	struct wl1271_cmd_header header;
+
+	u8 hlid;
+	u8 reason_opcode;
+	u8 send_deauth_flag;
+	u8 padding1;
+} __packed;
+
 #endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index a16b361..856a8a2 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -496,6 +496,26 @@ struct conf_rx_settings {
 					CONF_HW_BIT_RATE_2MBPS)
 #define CONF_TX_RATE_RETRY_LIMIT       10
 
+/*
+ * Rates supported for data packets when operating as AP. Note the absense
+ * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
+ * one. The rate dropped is not mandatory under any operating mode.
+ */
+#define CONF_TX_AP_ENABLED_RATES       (CONF_HW_BIT_RATE_1MBPS | \
+	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS |      \
+	CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS |        \
+	CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS |      \
+	CONF_HW_BIT_RATE_18MBPS | CONF_HW_BIT_RATE_24MBPS |      \
+	CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS |      \
+	CONF_HW_BIT_RATE_54MBPS)
+
+/*
+ * Default rates for management traffic when operating in AP mode. This
+ * should be configured according to the basic rate set of the AP
+ */
+#define CONF_TX_AP_DEFAULT_MGMT_RATES  (CONF_HW_BIT_RATE_1MBPS | \
+	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
+
 struct conf_tx_rate_class {
 
 	/*
@@ -636,9 +656,9 @@ struct conf_tx_settings {
 
 	/*
 	 * Configuration for rate classes for TX (currently only one
-	 * rate class supported.)
+	 * rate class supported). Used in non-AP mode.
 	 */
-	struct conf_tx_rate_class rc_conf;
+	struct conf_tx_rate_class sta_rc_conf;
 
 	/*
 	 * Configuration for access categories for TX rate control.
@@ -647,6 +667,28 @@ struct conf_tx_settings {
 	struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT];
 
 	/*
+	 * Configuration for rate classes in AP-mode. These rate classes
+	 * are for the AC TX queues
+	 */
+	struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT];
+
+	/*
+	 * Management TX rate class for AP-mode.
+	 */
+	struct conf_tx_rate_class ap_mgmt_conf;
+
+	/*
+	 * Broadcast TX rate class for AP-mode.
+	 */
+	struct conf_tx_rate_class ap_bcst_conf;
+
+	/*
+	 * AP-mode - allow this number of TX retries to a station before an
+	 * event is triggered from FW.
+	 */
+	u16 ap_max_tx_retries;
+
+	/*
 	 * Configuration for TID parameters.
 	 */
 	u8 tid_conf_count;
@@ -687,6 +729,12 @@ struct conf_tx_settings {
 	 * Range: CONF_HW_BIT_RATE_* bit mask
 	 */
 	u32 basic_rate_5;
+
+	/*
+	 * TX retry limits for templates
+	 */
+	u8 tmpl_short_retry_limit;
+	u8 tmpl_long_retry_limit;
 };
 
 enum {
@@ -912,6 +960,14 @@ struct conf_conn_settings {
 	u8 psm_entry_retries;
 
 	/*
+	 * Specifies the maximum number of times to try PSM exit if it fails
+	 * (if sending the appropriate null-func message fails.)
+	 *
+	 * Range 0 - 255
+	 */
+	u8 psm_exit_retries;
+
+	/*
 	 * Specifies the maximum number of times to try transmit the PSM entry
 	 * null-func frame for each PSM entry attempt
 	 *
@@ -1036,30 +1092,30 @@ struct conf_scan_settings {
 	/*
 	 * The minimum time to wait on each channel for active scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 min_dwell_time_active;
+	u32 min_dwell_time_active;
 
 	/*
 	 * The maximum time to wait on each channel for active scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 max_dwell_time_active;
+	u32 max_dwell_time_active;
 
 	/*
-	 * The maximum time to wait on each channel for passive scans
+	 * The minimum time to wait on each channel for passive scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 min_dwell_time_passive;
+	u32 min_dwell_time_passive;
 
 	/*
 	 * The maximum time to wait on each channel for passive scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 max_dwell_time_passive;
+	u32 max_dwell_time_passive;
 
 	/*
 	 * Number of probe requests to transmit on each active scan channel
@@ -1090,6 +1146,51 @@ struct conf_rf_settings {
 	u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
 };
 
+struct conf_ht_setting {
+	u16 tx_ba_win_size;
+	u16 inactivity_timeout;
+};
+
+struct conf_memory_settings {
+	/* Number of stations supported in IBSS mode */
+	u8 num_stations;
+
+	/* Number of ssid profiles used in IBSS mode */
+	u8 ssid_profiles;
+
+	/* Number of memory buffers allocated to rx pool */
+	u8 rx_block_num;
+
+	/* Minimum number of blocks allocated to tx pool */
+	u8 tx_min_block_num;
+
+	/* Disable/Enable dynamic memory */
+	u8 dynamic_memory;
+
+	/*
+	 * Minimum required free tx memory blocks in order to assure optimum
+	 * performence
+	 *
+	 * Range: 0-120
+	 */
+	u8 min_req_tx_blocks;
+
+	/*
+	 * Minimum required free rx memory blocks in order to assure optimum
+	 * performence
+	 *
+	 * Range: 0-120
+	 */
+	u8 min_req_rx_blocks;
+
+	/*
+	 * Minimum number of mem blocks (free+used) guaranteed for TX
+	 *
+	 * Range: 0-120
+	 */
+	u8 tx_min;
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
@@ -1100,6 +1201,8 @@ struct conf_drv_settings {
 	struct conf_roam_trigger_settings roam_trigger;
 	struct conf_scan_settings scan;
 	struct conf_rf_settings rf;
+	struct conf_ht_setting ht;
+	struct conf_memory_settings mem;
 };
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index ec60777..8e75b09 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -99,7 +99,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl)
 
 	mutex_lock(&wl->mutex);
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -261,27 +261,25 @@ static ssize_t gpio_power_write(struct file *file,
 	unsigned long value;
 	int ret;
 
-	mutex_lock(&wl->mutex);
-
 	len = min(count, sizeof(buf) - 1);
 	if (copy_from_user(buf, user_buf, len)) {
-		ret = -EFAULT;
-		goto out;
+		return -EFAULT;
 	}
 	buf[len] = '\0';
 
 	ret = strict_strtoul(buf, 0, &value);
 	if (ret < 0) {
 		wl1271_warning("illegal value in gpio_power");
-		goto out;
+		return -EINVAL;
 	}
 
+	mutex_lock(&wl->mutex);
+
 	if (value)
 		wl1271_power_on(wl);
 	else
 		wl1271_power_off(wl);
 
-out:
 	mutex_unlock(&wl->mutex);
 	return count;
 }
@@ -293,12 +291,13 @@ static const struct file_operations gpio_power_ops = {
 	.llseek = default_llseek,
 };
 
-static int wl1271_debugfs_add_files(struct wl1271 *wl)
+static int wl1271_debugfs_add_files(struct wl1271 *wl,
+				     struct dentry *rootdir)
 {
 	int ret = 0;
 	struct dentry *entry, *stats;
 
-	stats = debugfs_create_dir("fw-statistics", wl->rootdir);
+	stats = debugfs_create_dir("fw-statistics", rootdir);
 	if (!stats || IS_ERR(stats)) {
 		entry = stats;
 		goto err;
@@ -395,16 +394,11 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl)
 	DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
 	DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
 
-	DEBUGFS_ADD(tx_queue_len, wl->rootdir);
-	DEBUGFS_ADD(retry_count, wl->rootdir);
-	DEBUGFS_ADD(excessive_retries, wl->rootdir);
-
-	DEBUGFS_ADD(gpio_power, wl->rootdir);
+	DEBUGFS_ADD(tx_queue_len, rootdir);
+	DEBUGFS_ADD(retry_count, rootdir);
+	DEBUGFS_ADD(excessive_retries, rootdir);
 
-	entry = debugfs_create_x32("debug_level", 0600, wl->rootdir,
-				   &wl12xx_debug_level);
-	if (!entry || IS_ERR(entry))
-		goto err;
+	DEBUGFS_ADD(gpio_power, rootdir);
 
 	return 0;
 
@@ -419,7 +413,7 @@ err:
 
 void wl1271_debugfs_reset(struct wl1271 *wl)
 {
-	if (!wl->rootdir)
+	if (!wl->stats.fw_stats)
 		return;
 
 	memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
@@ -430,13 +424,13 @@ void wl1271_debugfs_reset(struct wl1271 *wl)
 int wl1271_debugfs_init(struct wl1271 *wl)
 {
 	int ret;
+	struct dentry *rootdir;
 
-	wl->rootdir = debugfs_create_dir(KBUILD_MODNAME,
-					 wl->hw->wiphy->debugfsdir);
+	rootdir = debugfs_create_dir(KBUILD_MODNAME,
+				     wl->hw->wiphy->debugfsdir);
 
-	if (IS_ERR(wl->rootdir)) {
-		ret = PTR_ERR(wl->rootdir);
-		wl->rootdir = NULL;
+	if (IS_ERR(rootdir)) {
+		ret = PTR_ERR(rootdir);
 		goto err;
 	}
 
@@ -450,7 +444,7 @@ int wl1271_debugfs_init(struct wl1271 *wl)
 
 	wl->stats.fw_stats_update = jiffies;
 
-	ret = wl1271_debugfs_add_files(wl);
+	ret = wl1271_debugfs_add_files(wl, rootdir);
 
 	if (ret < 0)
 		goto err_file;
@@ -462,8 +456,7 @@ err_file:
 	wl->stats.fw_stats = NULL;
 
 err_fw:
-	debugfs_remove_recursive(wl->rootdir);
-	wl->rootdir = NULL;
+	debugfs_remove_recursive(rootdir);
 
 err:
 	return ret;
@@ -473,8 +466,4 @@ void wl1271_debugfs_exit(struct wl1271 *wl)
 {
 	kfree(wl->stats.fw_stats);
 	wl->stats.fw_stats = NULL;
-
-	debugfs_remove_recursive(wl->rootdir);
-	wl->rootdir = NULL;
-
 }
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index f9146f5..1b170c5 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -135,20 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
 		/* go to extremely low power mode */
 		wl1271_ps_elp_sleep(wl);
 		break;
-	case EVENT_EXIT_POWER_SAVE_FAIL:
-		wl1271_debug(DEBUG_PSM, "PSM exit failed");
-
-		if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
-			wl->psm_entry_retry = 0;
-			break;
-		}
-
-		/* make sure the firmware goes to active mode - the frame to
-		   be sent next will indicate to the AP, that we are active. */
-		ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
-					 wl->basic_rate, false);
-		break;
-	case EVENT_EXIT_POWER_SAVE_SUCCESS:
 	default:
 		break;
 	}
@@ -186,6 +172,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 	int ret;
 	u32 vector;
 	bool beacon_loss = false;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
 	wl1271_event_mbox_dump(mbox);
 
@@ -218,21 +205,21 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 	 * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
 	 *
 	 */
-	if (vector & BSS_LOSE_EVENT_ID) {
+	if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) {
 		wl1271_info("Beacon loss detected.");
 
 		/* indicate to the stack, that beacons have been lost */
 		beacon_loss = true;
 	}
 
-	if (vector & PS_REPORT_EVENT_ID) {
+	if ((vector & PS_REPORT_EVENT_ID) && !is_ap) {
 		wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
 		ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
+	if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap)
 		wl1271_event_pspoll_delivery_fail(wl);
 
 	if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index 6cce014..0e80886 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -59,6 +59,7 @@ enum {
 	BSS_LOSE_EVENT_ID			 = BIT(18),
 	REGAINED_BSS_EVENT_ID			 = BIT(19),
 	ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID	 = BIT(20),
+	STA_REMOVE_COMPLETE_EVENT_ID		 = BIT(21), /* AP */
 	SOFT_GEMINI_SENSE_EVENT_ID		 = BIT(22),
 	SOFT_GEMINI_PREDICTION_EVENT_ID		 = BIT(23),
 	SOFT_GEMINI_AVALANCHE_EVENT_ID		 = BIT(24),
@@ -74,8 +75,6 @@ enum {
 enum {
 	EVENT_ENTER_POWER_SAVE_FAIL = 0,
 	EVENT_ENTER_POWER_SAVE_SUCCESS,
-	EVENT_EXIT_POWER_SAVE_FAIL,
-	EVENT_EXIT_POWER_SAVE_SUCCESS,
 };
 
 struct event_debug_report {
@@ -115,7 +114,12 @@ struct event_mailbox {
 	u8 scheduled_scan_status;
 	u8 ps_status;
 
-	u8 reserved_5[29];
+	/* AP FW only */
+	u8 hlid_removed;
+	__le16 sta_aging_status;
+	__le16 sta_tx_retry_exceeded;
+
+	u8 reserved_5[24];
 } __packed;
 
 int wl1271_event_unmask(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 785a530..6072fe4 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -30,27 +30,9 @@
 #include "acx.h"
 #include "cmd.h"
 #include "reg.h"
+#include "tx.h"
 
-static int wl1271_init_hwenc_config(struct wl1271 *wl)
-{
-	int ret;
-
-	ret = wl1271_acx_feature_cfg(wl);
-	if (ret < 0) {
-		wl1271_warning("couldn't set feature config");
-		return ret;
-	}
-
-	ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
-	if (ret < 0) {
-		wl1271_warning("couldn't set default key");
-		return ret;
-	}
-
-	return 0;
-}
-
-int wl1271_init_templates_config(struct wl1271 *wl)
+int wl1271_sta_init_templates_config(struct wl1271 *wl)
 {
 	int ret, i;
 
@@ -118,6 +100,132 @@ int wl1271_init_templates_config(struct wl1271 *wl)
 	return 0;
 }
 
+static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
+{
+	struct wl12xx_disconn_template *tmpl;
+	int ret;
+
+	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
+	if (!tmpl) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					     IEEE80211_STYPE_DEAUTH);
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
+				      tmpl, sizeof(*tmpl), 0,
+				      wl1271_tx_min_rate_get(wl));
+
+out:
+	kfree(tmpl);
+	return ret;
+}
+
+static int wl1271_ap_init_null_template(struct wl1271 *wl)
+{
+	struct ieee80211_hdr_3addr *nullfunc;
+	int ret;
+
+	nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
+	if (!nullfunc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+					      IEEE80211_STYPE_NULLFUNC |
+					      IEEE80211_FCTL_FROMDS);
+
+	/* nullfunc->addr1 is filled by FW */
+
+	memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
+	memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
+				      sizeof(*nullfunc), 0,
+				      wl1271_tx_min_rate_get(wl));
+
+out:
+	kfree(nullfunc);
+	return ret;
+}
+
+static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
+{
+	struct ieee80211_qos_hdr *qosnull;
+	int ret;
+
+	qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
+	if (!qosnull) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+					     IEEE80211_STYPE_QOS_NULLFUNC |
+					     IEEE80211_FCTL_FROMDS);
+
+	/* qosnull->addr1 is filled by FW */
+
+	memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
+	memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
+				      sizeof(*qosnull), 0,
+				      wl1271_tx_min_rate_get(wl));
+
+out:
+	kfree(qosnull);
+	return ret;
+}
+
+static int wl1271_ap_init_templates_config(struct wl1271 *wl)
+{
+	int ret;
+
+	/*
+	 * Put very large empty placeholders for all templates. These
+	 * reserve memory for later.
+	 */
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
+				      sizeof
+				      (struct wl12xx_probe_resp_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
+				      sizeof
+				      (struct wl12xx_beacon_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
+				      sizeof
+				      (struct wl12xx_disconn_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
+				      sizeof(struct wl12xx_null_data_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
+				      sizeof
+				      (struct wl12xx_qos_null_data_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
 {
 	int ret;
@@ -145,10 +253,6 @@ int wl1271_init_phy_config(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
-	if (ret < 0)
-		return ret;
-
 	ret = wl1271_acx_service_period_timeout(wl);
 	if (ret < 0)
 		return ret;
@@ -213,11 +317,199 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
 	return 0;
 }
 
+static int wl1271_sta_hw_init(struct wl1271 *wl)
+{
+	int ret;
+
+	ret = wl1271_cmd_ext_radio_parms(wl);
+	if (ret < 0)
+		return ret;
+
+	/* PS config */
+	ret = wl1271_acx_config_ps(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_sta_init_templates_config(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize connection monitoring thresholds */
+	ret = wl1271_acx_conn_monit_params(wl, false);
+	if (ret < 0)
+		return ret;
+
+	/* Beacon filtering */
+	ret = wl1271_init_beacon_filter(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Bluetooth WLAN coexistence */
+	ret = wl1271_init_pta(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Beacons and broadcast settings */
+	ret = wl1271_init_beacon_broadcast(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Configure for ELP power saving */
+	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+	if (ret < 0)
+		return ret;
+
+	/* Configure rssi/snr averaging weights */
+	ret = wl1271_acx_rssi_snr_avg_weights(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_sta_rate_policies(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_sta_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
+{
+	int ret, i;
+
+	ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
+	if (ret < 0) {
+		wl1271_warning("couldn't set default key");
+		return ret;
+	}
+
+	/* disable all keep-alive templates */
+	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
+		ret = wl1271_acx_keep_alive_config(wl, i,
+						   ACX_KEEP_ALIVE_TPL_INVALID);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* disable the keep-alive feature */
+	ret = wl1271_acx_keep_alive_mode(wl, false);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wl1271_ap_hw_init(struct wl1271 *wl)
+{
+	int ret, i;
+
+	ret = wl1271_ap_init_templates_config(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Configure for power always on */
+	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+	if (ret < 0)
+		return ret;
+
+	/* Configure initial TX rate classes */
+	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
+		ret = wl1271_acx_ap_rate_policy(wl,
+				&wl->conf.tx.ap_rc_conf[i], i);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = wl1271_acx_ap_rate_policy(wl,
+					&wl->conf.tx.ap_mgmt_conf,
+					ACX_TX_AP_MODE_MGMT_RATE);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_ap_rate_policy(wl,
+					&wl->conf.tx.ap_bcst_conf,
+					ACX_TX_AP_MODE_BCST_RATE);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_max_tx_retry(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_ap_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
+{
+	int ret;
+
+	ret = wl1271_ap_init_deauth_template(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_ap_init_null_template(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_ap_init_qos_null_template(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void wl1271_check_ba_support(struct wl1271 *wl)
+{
+	/* validate FW cose ver x.x.x.50-60.x */
+	if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
+	    (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
+		wl->ba_support = true;
+		return;
+	}
+
+	wl->ba_support = false;
+}
+
+static int wl1271_set_ba_policies(struct wl1271 *wl)
+{
+	u8 tid_index;
+	int ret = 0;
+
+	/* Reset the BA RX indicators */
+	wl->ba_rx_bitmap = 0;
+
+	/* validate that FW support BA */
+	wl1271_check_ba_support(wl);
+
+	if (wl->ba_support)
+		/* 802.11n initiator BA session setting */
+		for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
+		     ++tid_index) {
+			ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
+							tid_index, true);
+			if (ret < 0)
+				break;
+		}
+
+	return ret;
+}
+
 int wl1271_hw_init(struct wl1271 *wl)
 {
 	struct conf_tx_ac_category *conf_ac;
 	struct conf_tx_tid *conf_tid;
 	int ret, i;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
 	ret = wl1271_cmd_general_parms(wl);
 	if (ret < 0)
@@ -227,12 +519,12 @@ int wl1271_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_cmd_ext_radio_parms(wl);
-	if (ret < 0)
-		return ret;
+	/* Mode specific init */
+	if (is_ap)
+		ret = wl1271_ap_hw_init(wl);
+	else
+		ret = wl1271_sta_hw_init(wl);
 
-	/* Template settings */
-	ret = wl1271_init_templates_config(wl);
 	if (ret < 0)
 		return ret;
 
@@ -259,16 +551,6 @@ int wl1271_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Initialize connection monitoring thresholds */
-	ret = wl1271_acx_conn_monit_params(wl, false);
-	if (ret < 0)
-		goto out_free_memmap;
-
-	/* Beacon filtering */
-	ret = wl1271_init_beacon_filter(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Configure TX patch complete interrupt behavior */
 	ret = wl1271_acx_tx_config_options(wl);
 	if (ret < 0)
@@ -279,21 +561,11 @@ int wl1271_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Bluetooth WLAN coexistence */
-	ret = wl1271_init_pta(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Energy detection */
 	ret = wl1271_init_energy_detection(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Beacons and boradcast settings */
-	ret = wl1271_init_beacon_broadcast(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Default fragmentation threshold */
 	ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
 	if (ret < 0)
@@ -321,23 +593,13 @@ int wl1271_hw_init(struct wl1271 *wl)
 			goto out_free_memmap;
 	}
 
-	/* Configure TX rate classes */
-	ret = wl1271_acx_rate_policies(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Enable data path */
 	ret = wl1271_cmd_data_path(wl, 1);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Configure for ELP power saving */
-	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Configure HW encryption */
-	ret = wl1271_init_hwenc_config(wl);
+	ret = wl1271_acx_feature_cfg(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
@@ -346,21 +608,17 @@ int wl1271_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* disable all keep-alive templates */
-	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
-		ret = wl1271_acx_keep_alive_config(wl, i,
-						   ACX_KEEP_ALIVE_TPL_INVALID);
-		if (ret < 0)
-			goto out_free_memmap;
-	}
+	/* Mode specific init - post mem init */
+	if (is_ap)
+		ret = wl1271_ap_hw_init_post_mem(wl);
+	else
+		ret = wl1271_sta_hw_init_post_mem(wl);
 
-	/* disable the keep-alive feature */
-	ret = wl1271_acx_keep_alive_mode(wl, false);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Configure rssi/snr averaging weights */
-	ret = wl1271_acx_rssi_snr_avg_weights(wl);
+	/* Configure initiator BA sessions policies */
+	ret = wl1271_set_ba_policies(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h
index 7762421..3a8bd3f 100644
--- a/drivers/net/wireless/wl12xx/init.h
+++ b/drivers/net/wireless/wl12xx/init.h
@@ -27,7 +27,7 @@
 #include "wl12xx.h"
 
 int wl1271_hw_init_power_auth(struct wl1271 *wl);
-int wl1271_init_templates_config(struct wl1271 *wl);
+int wl1271_sta_init_templates_config(struct wl1271 *wl);
 int wl1271_init_phy_config(struct wl1271 *wl);
 int wl1271_init_pta(struct wl1271 *wl);
 int wl1271_init_energy_detection(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index 844b32b..c1aac82 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -168,5 +168,6 @@ void wl1271_unregister_hw(struct wl1271 *wl);
 int wl1271_init_ieee80211(struct wl1271 *wl);
 struct ieee80211_hw *wl1271_alloc_hw(void);
 int wl1271_free_hw(struct wl1271 *wl);
+irqreturn_t wl1271_irq(int irq, void *data);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 062247e..8b3c8d1 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -116,11 +116,11 @@ static struct conf_drv_settings default_conf = {
 	},
 	.tx = {
 		.tx_energy_detection         = 0,
-		.rc_conf                     = {
+		.sta_rc_conf                 = {
 			.enabled_rates       = 0,
 			.short_retry_limit   = 10,
 			.long_retry_limit    = 10,
-			.aflags              = 0
+			.aflags              = 0,
 		},
 		.ac_conf_count               = 4,
 		.ac_conf                     = {
@@ -153,6 +153,45 @@ static struct conf_drv_settings default_conf = {
 				.tx_op_limit = 1504,
 			},
 		},
+		.ap_rc_conf                  = {
+			[0] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[1] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[2] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[3] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+		},
+		.ap_mgmt_conf = {
+			.enabled_rates       = CONF_TX_AP_DEFAULT_MGMT_RATES,
+			.short_retry_limit   = 10,
+			.long_retry_limit    = 10,
+			.aflags              = 0,
+		},
+		.ap_bcst_conf = {
+			.enabled_rates       = CONF_HW_BIT_RATE_1MBPS,
+			.short_retry_limit   = 10,
+			.long_retry_limit    = 10,
+			.aflags              = 0,
+		},
+		.ap_max_tx_retries = 100,
 		.tid_conf_count = 4,
 		.tid_conf = {
 			[CONF_TX_AC_BE] = {
@@ -193,6 +232,8 @@ static struct conf_drv_settings default_conf = {
 		.tx_compl_threshold          = 4,
 		.basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
 		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
+		.tmpl_short_retry_limit      = 10,
+		.tmpl_long_retry_limit       = 10,
 	},
 	.conn = {
 		.wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
@@ -215,6 +256,7 @@ static struct conf_drv_settings default_conf = {
 		.bet_enable                  = CONF_BET_MODE_ENABLE,
 		.bet_max_consecutive         = 10,
 		.psm_entry_retries           = 5,
+		.psm_exit_retries            = 255,
 		.psm_entry_nullfunc_retries  = 3,
 		.psm_entry_hangover_period   = 1,
 		.keep_alive_interval         = 55000,
@@ -233,13 +275,13 @@ static struct conf_drv_settings default_conf = {
 		.avg_weight_rssi_beacon       = 20,
 		.avg_weight_rssi_data         = 10,
 		.avg_weight_snr_beacon        = 20,
-		.avg_weight_snr_data          = 10
+		.avg_weight_snr_data          = 10,
 	},
 	.scan = {
 		.min_dwell_time_active        = 7500,
 		.max_dwell_time_active        = 30000,
-		.min_dwell_time_passive       = 30000,
-		.max_dwell_time_passive       = 60000,
+		.min_dwell_time_passive       = 100000,
+		.max_dwell_time_passive       = 100000,
 		.num_probe_reqs               = 2,
 	},
 	.rf = {
@@ -252,9 +294,24 @@ static struct conf_drv_settings default_conf = {
 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		},
 	},
+	.ht = {
+		.tx_ba_win_size = 64,
+		.inactivity_timeout = 10000,
+	},
+	.mem = {
+		.num_stations                 = 1,
+		.ssid_profiles                = 1,
+		.rx_block_num                 = 70,
+		.tx_min_block_num             = 40,
+		.dynamic_memory               = 0,
+		.min_req_tx_blocks            = 100,
+		.min_req_rx_blocks            = 22,
+		.tx_min                       = 27,
+	}
 };
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl);
+static void wl1271_free_ap_keys(struct wl1271 *wl);
 
 
 static void wl1271_device_release(struct device *dev)
@@ -317,7 +374,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
 	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -393,7 +450,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_init_templates_config(wl);
+	ret = wl1271_sta_init_templates_config(wl);
 	if (ret < 0)
 		return ret;
 
@@ -425,6 +482,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_free_memmap;
 
+	ret = wl1271_acx_sta_mem_cfg(wl);
+	if (ret < 0)
+		goto out_free_memmap;
+
 	/* Default fragmentation threshold */
 	ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
 	if (ret < 0)
@@ -476,14 +537,71 @@ static int wl1271_plt_init(struct wl1271 *wl)
 	return ret;
 }
 
+static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
+{
+	bool fw_ps;
+
+	/* only regulate station links */
+	if (hlid < WL1271_AP_STA_HLID_START)
+		return;
+
+	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+
+	/*
+	 * Wake up from high level PS if the STA is asleep with too little
+	 * blocks in FW or if the STA is awake.
+	 */
+	if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
+		wl1271_ps_link_end(wl, hlid);
+
+	/* Start high-level PS if the STA is asleep with enough blocks in FW */
+	else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+		wl1271_ps_link_start(wl, hlid, true);
+}
+
+static void wl1271_irq_update_links_status(struct wl1271 *wl,
+				       struct wl1271_fw_ap_status *status)
+{
+	u32 cur_fw_ps_map;
+	u8 hlid;
+
+	cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
+	if (wl->ap_fw_ps_map != cur_fw_ps_map) {
+		wl1271_debug(DEBUG_PSM,
+			     "link ps prev 0x%x cur 0x%x changed 0x%x",
+			     wl->ap_fw_ps_map, cur_fw_ps_map,
+			     wl->ap_fw_ps_map ^ cur_fw_ps_map);
+
+		wl->ap_fw_ps_map = cur_fw_ps_map;
+	}
+
+	for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
+		u8 cnt = status->tx_lnk_free_blks[hlid] -
+			wl->links[hlid].prev_freed_blks;
+
+		wl->links[hlid].prev_freed_blks =
+			status->tx_lnk_free_blks[hlid];
+		wl->links[hlid].allocated_blks -= cnt;
+
+		wl1271_irq_ps_regulate_link(wl, hlid,
+					    wl->links[hlid].allocated_blks);
+	}
+}
+
 static void wl1271_fw_status(struct wl1271 *wl,
-			     struct wl1271_fw_status *status)
+			     struct wl1271_fw_full_status *full_status)
 {
+	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
 	u32 total = 0;
 	int i;
 
-	wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+				sizeof(struct wl1271_fw_ap_status), false);
+	else
+		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+				sizeof(struct wl1271_fw_sta_status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -507,22 +625,54 @@ static void wl1271_fw_status(struct wl1271 *wl,
 	if (total)
 		clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
 
+	/* for AP update num of allocated TX blocks per link and ps status */
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl1271_irq_update_links_status(wl, &full_status->ap);
+
 	/* update the host-chipset time offset */
 	getnstimeofday(&ts);
 	wl->time_offset = (timespec_to_ns(&ts) >> 10) -
 		(s64)le32_to_cpu(status->fw_localtime);
 }
 
-#define WL1271_IRQ_MAX_LOOPS 10
+static void wl1271_flush_deferred_work(struct wl1271 *wl)
+{
+	struct sk_buff *skb;
+
+	/* Pass all received frames to the network stack */
+	while ((skb = skb_dequeue(&wl->deferred_rx_queue)))
+		ieee80211_rx_ni(wl->hw, skb);
+
+	/* Return sent skbs to the network stack */
+	while ((skb = skb_dequeue(&wl->deferred_tx_queue)))
+		ieee80211_tx_status(wl->hw, skb);
+}
+
+static void wl1271_netstack_work(struct work_struct *work)
+{
+	struct wl1271 *wl =
+		container_of(work, struct wl1271, netstack_work);
+
+	do {
+		wl1271_flush_deferred_work(wl);
+	} while (skb_queue_len(&wl->deferred_rx_queue));
+}
+
+#define WL1271_IRQ_MAX_LOOPS 256
 
-static void wl1271_irq_work(struct work_struct *work)
+irqreturn_t wl1271_irq(int irq, void *cookie)
 {
 	int ret;
 	u32 intr;
 	int loopcount = WL1271_IRQ_MAX_LOOPS;
+	struct wl1271 *wl = (struct wl1271 *)cookie;
+	bool done = false;
+	unsigned int defer_count;
 	unsigned long flags;
-	struct wl1271 *wl =
-		container_of(work, struct wl1271, irq_work);
+
+	/* TX might be handled here, avoid redundant work */
+	set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
+	cancel_work_sync(&wl->tx_work);
 
 	mutex_lock(&wl->mutex);
 
@@ -531,26 +681,27 @@ static void wl1271_irq_work(struct work_struct *work)
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, true);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) {
-		clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-		loopcount--;
+	while (!done && loopcount--) {
+		/*
+		 * In order to avoid a race with the hardirq, clear the flag
+		 * before acknowledging the chip. Since the mutex is held,
+		 * wl1271_ps_elp_wakeup cannot be called concurrently.
+		 */
+		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
+		smp_mb__after_clear_bit();
 
 		wl1271_fw_status(wl, wl->fw_status);
-		intr = le32_to_cpu(wl->fw_status->intr);
+		intr = le32_to_cpu(wl->fw_status->common.intr);
+		intr &= WL1271_INTR_MASK;
 		if (!intr) {
-			wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
-			spin_lock_irqsave(&wl->wl_lock, flags);
+			done = true;
 			continue;
 		}
 
-		intr &= WL1271_INTR_MASK;
-
 		if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
 			wl1271_error("watchdog interrupt received! "
 				     "starting recovery.");
@@ -560,25 +711,35 @@ static void wl1271_irq_work(struct work_struct *work)
 			goto out;
 		}
 
-		if (intr & WL1271_ACX_INTR_DATA) {
+		if (likely(intr & WL1271_ACX_INTR_DATA)) {
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
-			/* check for tx results */
-			if (wl->fw_status->tx_results_counter !=
-			    (wl->tx_results_count & 0xff))
-				wl1271_tx_complete(wl);
+			wl1271_rx(wl, &wl->fw_status->common);
 
 			/* Check if any tx blocks were freed */
+			spin_lock_irqsave(&wl->wl_lock, flags);
 			if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
 			    wl->tx_queue_count) {
+				spin_unlock_irqrestore(&wl->wl_lock, flags);
 				/*
 				 * In order to avoid starvation of the TX path,
 				 * call the work function directly.
 				 */
 				wl1271_tx_work_locked(wl);
+			} else {
+				spin_unlock_irqrestore(&wl->wl_lock, flags);
 			}
 
-			wl1271_rx(wl, wl->fw_status);
+			/* check for tx results */
+			if (wl->fw_status->common.tx_results_counter !=
+			    (wl->tx_results_count & 0xff))
+				wl1271_tx_complete(wl);
+
+			/* Make sure the deferred queues don't get too long */
+			defer_count = skb_queue_len(&wl->deferred_tx_queue) +
+				      skb_queue_len(&wl->deferred_rx_queue);
+			if (defer_count > WL1271_DEFERRED_QUEUE_LIMIT)
+				wl1271_flush_deferred_work(wl);
 		}
 
 		if (intr & WL1271_ACX_INTR_EVENT_A) {
@@ -597,28 +758,48 @@ static void wl1271_irq_work(struct work_struct *work)
 
 		if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
 	}
 
-	if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->irq_work);
-	else
-		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
 	wl1271_ps_elp_sleep(wl);
 
 out:
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	/* In case TX was not handled here, queue TX work */
+	clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
+	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
+	    wl->tx_queue_count)
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
 	mutex_unlock(&wl->mutex);
+
+	return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(wl1271_irq);
 
 static int wl1271_fetch_firmware(struct wl1271 *wl)
 {
 	const struct firmware *fw;
+	const char *fw_name;
 	int ret;
 
-	ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl));
+	switch (wl->bss_type) {
+	case BSS_TYPE_AP_BSS:
+		fw_name = WL1271_AP_FW_NAME;
+		break;
+	case BSS_TYPE_IBSS:
+	case BSS_TYPE_STA_BSS:
+		fw_name = WL1271_FW_NAME;
+		break;
+	default:
+		wl1271_error("no compatible firmware for bss_type %d",
+			     wl->bss_type);
+		return -EINVAL;
+	}
+
+	wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name);
+
+	ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl));
 
 	if (ret < 0) {
 		wl1271_error("could not get firmware: %d", ret);
@@ -632,6 +813,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
 		goto out;
 	}
 
+	vfree(wl->fw);
 	wl->fw_len = fw->size;
 	wl->fw = vmalloc(wl->fw_len);
 
@@ -642,7 +824,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
 	}
 
 	memcpy(wl->fw, fw->data, wl->fw_len);
-
+	wl->fw_bss_type = wl->bss_type;
 	ret = 0;
 
 out:
@@ -778,7 +960,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 		goto out;
 	}
 
-	if (wl->fw == NULL) {
+	/* Make sure the firmware type matches the BSS type */
+	if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) {
 		ret = wl1271_fetch_firmware(wl);
 		if (ret < 0)
 			goto out;
@@ -811,6 +994,8 @@ int wl1271_plt_start(struct wl1271 *wl)
 		goto out;
 	}
 
+	wl->bss_type = BSS_TYPE_STA_BSS;
+
 	while (retries) {
 		retries--;
 		ret = wl1271_chip_wakeup(wl);
@@ -827,11 +1012,10 @@ int wl1271_plt_start(struct wl1271 *wl)
 
 		wl->state = WL1271_STATE_PLT;
 		wl1271_notice("firmware booted in PLT mode (%s)",
-			      wl->chip.fw_ver);
+			      wl->chip.fw_ver_str);
 		goto out;
 
 irq_disable:
-		wl1271_disable_interrupts(wl);
 		mutex_unlock(&wl->mutex);
 		/* Unlocking the mutex in the middle of handling is
 		   inherently unsafe. In this case we deem it safe to do,
@@ -840,7 +1024,9 @@ irq_disable:
 		   work function will not do anything.) Also, any other
 		   possible concurrent operations will fail due to the
 		   current state, hence the wl1271 struct should be safe. */
-		cancel_work_sync(&wl->irq_work);
+		wl1271_disable_interrupts(wl);
+		wl1271_flush_deferred_work(wl);
+		cancel_work_sync(&wl->netstack_work);
 		mutex_lock(&wl->mutex);
 power_off:
 		wl1271_power_off(wl);
@@ -854,12 +1040,10 @@ out:
 	return ret;
 }
 
-int wl1271_plt_stop(struct wl1271 *wl)
+int __wl1271_plt_stop(struct wl1271 *wl)
 {
 	int ret = 0;
 
-	mutex_lock(&wl->mutex);
-
 	wl1271_notice("power down");
 
 	if (wl->state != WL1271_STATE_PLT) {
@@ -869,70 +1053,46 @@ int wl1271_plt_stop(struct wl1271 *wl)
 		goto out;
 	}
 
-	wl1271_disable_interrupts(wl);
 	wl1271_power_off(wl);
 
 	wl->state = WL1271_STATE_OFF;
 	wl->rx_counter = 0;
 
-out:
 	mutex_unlock(&wl->mutex);
-
-	cancel_work_sync(&wl->irq_work);
+	wl1271_disable_interrupts(wl);
+	wl1271_flush_deferred_work(wl);
+	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->recovery_work);
+	mutex_lock(&wl->mutex);
+out:
+	return ret;
+}
+
+int wl1271_plt_stop(struct wl1271 *wl)
+{
+	int ret;
 
+	mutex_lock(&wl->mutex);
+	ret = __wl1271_plt_stop(wl);
+	mutex_unlock(&wl->mutex);
 	return ret;
 }
 
-static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
-	struct ieee80211_sta *sta = txinfo->control.sta;
 	unsigned long flags;
 	int q;
+	u8 hlid = 0;
 
-	/*
-	 * peek into the rates configured in the STA entry.
-	 * The rates set after connection stage, The first block only BG sets:
-	 * the compare is for bit 0-16 of sta_rate_set. The second block add
-	 * HT rates in case of HT supported.
-	 */
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	if (sta &&
-	    (sta->supp_rates[conf->channel->band] !=
-	    (wl->sta_rate_set & HW_BG_RATES_MASK))) {
-		wl->sta_rate_set = sta->supp_rates[conf->channel->band];
-		set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
-	}
-
-#ifdef CONFIG_WL12XX_HT
-	if (sta &&
-	    sta->ht_cap.ht_supported &&
-	    ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) !=
-	      sta->ht_cap.mcs.rx_mask[0])) {
-		/* Clean MCS bits before setting them */
-		wl->sta_rate_set &= HW_BG_RATES_MASK;
-		wl->sta_rate_set |=
-			(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
-		set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
-	}
-#endif
-	wl->tx_queue_count++;
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
-	/* queue the packet */
 	q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
-	skb_queue_tail(&wl->tx_queue[q], skb);
 
-	/*
-	 * The chip specific setup must run before the first TX packet -
-	 * before that, the tx_work will not be initialized!
-	 */
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		hlid = wl1271_tx_get_hlid(skb);
 
-	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	spin_lock_irqsave(&wl->wl_lock, flags);
+
+	wl->tx_queue_count++;
 
 	/*
 	 * The workqueue is slow to process the tx_queue and we need stop
@@ -940,14 +1100,28 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 */
 	if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
 		wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
 		ieee80211_stop_queues(wl->hw);
 		set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
 
-	return NETDEV_TX_OK;
+	/* queue the packet */
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
+		skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
+	} else {
+		skb_queue_tail(&wl->tx_queue[q], skb);
+	}
+
+	/*
+	 * The chip specific setup must run before the first TX packet -
+	 * before that, the tx_work will not be initialized!
+	 */
+
+	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
+	    !test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
 }
 
 static struct notifier_block wl1271_dev_notifier = {
@@ -967,6 +1141,9 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
 	 *
 	 * The MAC address is first known when the corresponding interface
 	 * is added. That is where we will initialize the hardware.
+	 *
+	 * In addition, we currently have different firmwares for AP and managed
+	 * operation. We will know which to boot according to interface type.
 	 */
 
 	return 0;
@@ -1006,6 +1183,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 		wl->bss_type = BSS_TYPE_IBSS;
 		wl->set_bss_type = BSS_TYPE_STA_BSS;
 		break;
+	case NL80211_IFTYPE_AP:
+		wl->bss_type = BSS_TYPE_AP_BSS;
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		goto out;
@@ -1038,7 +1218,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 		break;
 
 irq_disable:
-		wl1271_disable_interrupts(wl);
 		mutex_unlock(&wl->mutex);
 		/* Unlocking the mutex in the middle of handling is
 		   inherently unsafe. In this case we deem it safe to do,
@@ -1047,7 +1226,9 @@ irq_disable:
 		   work function will not do anything.) Also, any other
 		   possible concurrent operations will fail due to the
 		   current state, hence the wl1271 struct should be safe. */
-		cancel_work_sync(&wl->irq_work);
+		wl1271_disable_interrupts(wl);
+		wl1271_flush_deferred_work(wl);
+		cancel_work_sync(&wl->netstack_work);
 		mutex_lock(&wl->mutex);
 power_off:
 		wl1271_power_off(wl);
@@ -1061,11 +1242,11 @@ power_off:
 
 	wl->vif = vif;
 	wl->state = WL1271_STATE_ON;
-	wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
+	wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str);
 
 	/* update hw/fw version info in wiphy struct */
 	wiphy->hw_version = wl->chip.id;
-	strncpy(wiphy->fw_version, wl->chip.fw_ver,
+	strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
 		sizeof(wiphy->fw_version));
 
 	/*
@@ -1113,12 +1294,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
 
 	wl->state = WL1271_STATE_OFF;
 
-	wl1271_disable_interrupts(wl);
-
 	mutex_unlock(&wl->mutex);
 
+	wl1271_disable_interrupts(wl);
+	wl1271_flush_deferred_work(wl);
 	cancel_delayed_work_sync(&wl->scan_complete_work);
-	cancel_work_sync(&wl->irq_work);
+	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->tx_work);
 	cancel_delayed_work_sync(&wl->pspoll_work);
 	cancel_delayed_work_sync(&wl->elp_work);
@@ -1147,10 +1328,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
 	wl->time_offset = 0;
 	wl->session_counter = 0;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
-	wl->sta_rate_set = 0;
 	wl->flags = 0;
 	wl->vif = NULL;
 	wl->filters = 0;
+	wl1271_free_ap_keys(wl);
+	memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
+	wl->ap_fw_ps_map = 0;
+	wl->ap_ps_map = 0;
 
 	for (i = 0; i < NUM_TX_QUEUES; i++)
 		wl->tx_blocks_freed[i] = 0;
@@ -1186,8 +1370,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
 
 static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
 {
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+	wl1271_set_default_filters(wl);
 
 	/* combine requested filters with current filter config */
 	filters = wl->filters | filters;
@@ -1322,25 +1505,7 @@ static void wl1271_set_band_rate(struct wl1271 *wl)
 		wl->basic_rate_set = wl->conf.tx.basic_rate_5;
 }
 
-static u32 wl1271_min_rate_get(struct wl1271 *wl)
-{
-	int i;
-	u32 rate = 0;
-
-	if (!wl->basic_rate_set) {
-		WARN_ON(1);
-		wl->basic_rate_set = wl->conf.tx.basic_rate;
-	}
-
-	for (i = 0; !rate; i++) {
-		if ((wl->basic_rate_set >> i) & 0x1)
-			rate = 1 << i;
-	}
-
-	return rate;
-}
-
-static int wl1271_handle_idle(struct wl1271 *wl, bool idle)
+static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
 {
 	int ret;
 
@@ -1350,9 +1515,8 @@ static int wl1271_handle_idle(struct wl1271 *wl, bool idle)
 			if (ret < 0)
 				goto out;
 		}
-		wl->rate_set = wl1271_min_rate_get(wl);
-		wl->sta_rate_set = 0;
-		ret = wl1271_acx_rate_policies(wl);
+		wl->rate_set = wl1271_tx_min_rate_get(wl);
+		ret = wl1271_acx_sta_rate_policies(wl);
 		if (ret < 0)
 			goto out;
 		ret = wl1271_acx_keep_alive_config(
@@ -1381,14 +1545,17 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 	struct wl1271 *wl = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	int channel, ret = 0;
+	bool is_ap;
 
 	channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
 
-	wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s",
+	wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s"
+		     " changed 0x%x",
 		     channel,
 		     conf->flags & IEEE80211_CONF_PS ? "on" : "off",
 		     conf->power_level,
-		     conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use");
+		     conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use",
+			 changed);
 
 	/*
 	 * mac80211 will go to idle nearly immediately after transmitting some
@@ -1406,7 +1573,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1417,31 +1586,34 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 		wl->band = conf->channel->band;
 		wl->channel = channel;
 
-		/*
-		 * FIXME: the mac80211 should really provide a fixed rate
-		 * to use here. for now, just use the smallest possible rate
-		 * for the band as a fixed rate for association frames and
-		 * other control messages.
-		 */
-		if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
-			wl1271_set_band_rate(wl);
-
-		wl->basic_rate = wl1271_min_rate_get(wl);
-		ret = wl1271_acx_rate_policies(wl);
-		if (ret < 0)
-			wl1271_warning("rate policy for update channel "
-				       "failed %d", ret);
+		if (!is_ap) {
+			/*
+			 * FIXME: the mac80211 should really provide a fixed
+			 * rate to use here. for now, just use the smallest
+			 * possible rate for the band as a fixed rate for
+			 * association frames and other control messages.
+			 */
+			if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+				wl1271_set_band_rate(wl);
 
-		if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
-			ret = wl1271_join(wl, false);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
-				wl1271_warning("cmd join to update channel "
+				wl1271_warning("rate policy for channel "
 					       "failed %d", ret);
+
+			if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+				ret = wl1271_join(wl, false);
+				if (ret < 0)
+					wl1271_warning("cmd join on channel "
+						       "failed %d", ret);
+			}
 		}
 	}
 
-	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
-		ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE);
+	if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) {
+		ret = wl1271_sta_handle_idle(wl,
+					conf->flags & IEEE80211_CONF_IDLE);
 		if (ret < 0)
 			wl1271_warning("idle mode change failed %d", ret);
 	}
@@ -1548,7 +1720,8 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
 	struct wl1271 *wl = hw->priv;
 	int ret;
 
-	wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
+	wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x"
+		     " total %x", changed, *total);
 
 	mutex_lock(&wl->mutex);
 
@@ -1558,19 +1731,20 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-
-	if (*total & FIF_ALLMULTI)
-		ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
-	else if (fp)
-		ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
-						   fp->mc_list,
-						   fp->mc_list_length);
-	if (ret < 0)
-		goto out_sleep;
+	if (wl->bss_type != BSS_TYPE_AP_BSS) {
+		if (*total & FIF_ALLMULTI)
+			ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
+		else if (fp)
+			ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
+							   fp->mc_list,
+							   fp->mc_list_length);
+		if (ret < 0)
+			goto out_sleep;
+	}
 
 	/* determine, whether supported filter values have changed */
 	if (changed == 0)
@@ -1593,38 +1767,192 @@ out:
 	kfree(fp);
 }
 
+static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type,
+			u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
+			u16 tx_seq_16)
+{
+	struct wl1271_ap_key *ap_key;
+	int i;
+
+	wl1271_debug(DEBUG_CRYPT, "record ap key id %d", (int)id);
+
+	if (key_size > MAX_KEY_SIZE)
+		return -EINVAL;
+
+	/*
+	 * Find next free entry in ap_keys. Also check we are not replacing
+	 * an existing key.
+	 */
+	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		if (wl->recorded_ap_keys[i] == NULL)
+			break;
+
+		if (wl->recorded_ap_keys[i]->id == id) {
+			wl1271_warning("trying to record key replacement");
+			return -EINVAL;
+		}
+	}
+
+	if (i == MAX_NUM_KEYS)
+		return -EBUSY;
+
+	ap_key = kzalloc(sizeof(*ap_key), GFP_KERNEL);
+	if (!ap_key)
+		return -ENOMEM;
+
+	ap_key->id = id;
+	ap_key->key_type = key_type;
+	ap_key->key_size = key_size;
+	memcpy(ap_key->key, key, key_size);
+	ap_key->hlid = hlid;
+	ap_key->tx_seq_32 = tx_seq_32;
+	ap_key->tx_seq_16 = tx_seq_16;
+
+	wl->recorded_ap_keys[i] = ap_key;
+	return 0;
+}
+
+static void wl1271_free_ap_keys(struct wl1271 *wl)
+{
+	int i;
+
+	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		kfree(wl->recorded_ap_keys[i]);
+		wl->recorded_ap_keys[i] = NULL;
+	}
+}
+
+static int wl1271_ap_init_hwenc(struct wl1271 *wl)
+{
+	int i, ret = 0;
+	struct wl1271_ap_key *key;
+	bool wep_key_added = false;
+
+	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		if (wl->recorded_ap_keys[i] == NULL)
+			break;
+
+		key = wl->recorded_ap_keys[i];
+		ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE,
+					    key->id, key->key_type,
+					    key->key_size, key->key,
+					    key->hlid, key->tx_seq_32,
+					    key->tx_seq_16);
+		if (ret < 0)
+			goto out;
+
+		if (key->key_type == KEY_WEP)
+			wep_key_added = true;
+	}
+
+	if (wep_key_added) {
+		ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key);
+		if (ret < 0)
+			goto out;
+	}
+
+out:
+	wl1271_free_ap_keys(wl);
+	return ret;
+}
+
+static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+		       u8 key_size, const u8 *key, u32 tx_seq_32,
+		       u16 tx_seq_16, struct ieee80211_sta *sta)
+{
+	int ret;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+
+	if (is_ap) {
+		struct wl1271_station *wl_sta;
+		u8 hlid;
+
+		if (sta) {
+			wl_sta = (struct wl1271_station *)sta->drv_priv;
+			hlid = wl_sta->hlid;
+		} else {
+			hlid = WL1271_AP_BROADCAST_HLID;
+		}
+
+		if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+			/*
+			 * We do not support removing keys after AP shutdown.
+			 * Pretend we do to make mac80211 happy.
+			 */
+			if (action != KEY_ADD_OR_REPLACE)
+				return 0;
+
+			ret = wl1271_record_ap_key(wl, id,
+					     key_type, key_size,
+					     key, hlid, tx_seq_32,
+					     tx_seq_16);
+		} else {
+			ret = wl1271_cmd_set_ap_key(wl, action,
+					     id, key_type, key_size,
+					     key, hlid, tx_seq_32,
+					     tx_seq_16);
+		}
+
+		if (ret < 0)
+			return ret;
+	} else {
+		const u8 *addr;
+		static const u8 bcast_addr[ETH_ALEN] = {
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+		};
+
+		addr = sta ? sta->addr : bcast_addr;
+
+		if (is_zero_ether_addr(addr)) {
+			/* We dont support TX only encryption */
+			return -EOPNOTSUPP;
+		}
+
+		/* The wl1271 does not allow to remove unicast keys - they
+		   will be cleared automatically on next CMD_JOIN. Ignore the
+		   request silently, as we dont want the mac80211 to emit
+		   an error message. */
+		if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr))
+			return 0;
+
+		ret = wl1271_cmd_set_sta_key(wl, action,
+					     id, key_type, key_size,
+					     key, addr, tx_seq_32,
+					     tx_seq_16);
+		if (ret < 0)
+			return ret;
+
+		/* the default WEP key needs to be configured at least once */
+		if (key_type == KEY_WEP) {
+			ret = wl1271_cmd_set_sta_default_wep_key(wl,
+							wl->default_key);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_sta *sta,
 			     struct ieee80211_key_conf *key_conf)
 {
 	struct wl1271 *wl = hw->priv;
-	const u8 *addr;
 	int ret;
 	u32 tx_seq_32 = 0;
 	u16 tx_seq_16 = 0;
 	u8 key_type;
 
-	static const u8 bcast_addr[ETH_ALEN] =
-		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
 	wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
 
-	addr = sta ? sta->addr : bcast_addr;
-
-	wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
-	wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
+	wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x sta: %p", cmd, sta);
 	wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
 		     key_conf->cipher, key_conf->keyidx,
 		     key_conf->keylen, key_conf->flags);
 	wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
 
-	if (is_zero_ether_addr(addr)) {
-		/* We dont support TX only encryption */
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
 	mutex_lock(&wl->mutex);
 
 	if (unlikely(wl->state == WL1271_STATE_OFF)) {
@@ -1632,7 +1960,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		goto out_unlock;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out_unlock;
 
@@ -1671,36 +1999,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 	switch (cmd) {
 	case SET_KEY:
-		ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
-					 key_conf->keyidx, key_type,
-					 key_conf->keylen, key_conf->key,
-					 addr, tx_seq_32, tx_seq_16);
+		ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE,
+				 key_conf->keyidx, key_type,
+				 key_conf->keylen, key_conf->key,
+				 tx_seq_32, tx_seq_16, sta);
 		if (ret < 0) {
 			wl1271_error("Could not add or replace key");
 			goto out_sleep;
 		}
-
-		/* the default WEP key needs to be configured at least once */
-		if (key_type == KEY_WEP) {
-			ret = wl1271_cmd_set_default_wep_key(wl,
-							     wl->default_key);
-			if (ret < 0)
-				goto out_sleep;
-		}
 		break;
 
 	case DISABLE_KEY:
-		/* The wl1271 does not allow to remove unicast keys - they
-		   will be cleared automatically on next CMD_JOIN. Ignore the
-		   request silently, as we dont want the mac80211 to emit
-		   an error message. */
-		if (!is_broadcast_ether_addr(addr))
-			break;
-
-		ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
-					 key_conf->keyidx, key_type,
-					 key_conf->keylen, key_conf->key,
-					 addr, 0, 0);
+		ret = wl1271_set_key(wl, KEY_REMOVE,
+				     key_conf->keyidx, key_type,
+				     key_conf->keylen, key_conf->key,
+				     0, 0, sta);
 		if (ret < 0) {
 			wl1271_error("Could not remove key");
 			goto out_sleep;
@@ -1719,7 +2032,6 @@ out_sleep:
 out_unlock:
 	mutex_unlock(&wl->mutex);
 
-out:
 	return ret;
 }
 
@@ -1751,7 +2063,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1777,7 +2089,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1805,7 +2117,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1821,7 +2133,7 @@ out:
 	return ret;
 }
 
-static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
+static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
 			    int offset)
 {
 	u8 *ptr = skb->data + offset;
@@ -1831,89 +2143,213 @@ static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
 		if (ptr[0] == WLAN_EID_SSID) {
 			wl->ssid_len = ptr[1];
 			memcpy(wl->ssid, ptr+2, wl->ssid_len);
-			return;
+			return 0;
 		}
 		ptr += (ptr[1] + 2);
 	}
+
 	wl1271_error("No SSID in IEs!\n");
+	return -ENOENT;
 }
 
-static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif,
+static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
 				       struct ieee80211_bss_conf *bss_conf,
 				       u32 changed)
 {
-	enum wl1271_cmd_ps_mode mode;
-	struct wl1271 *wl = hw->priv;
-	struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid);
-	bool do_join = false;
-	bool set_assoc = false;
-	int ret;
+	int ret = 0;
 
-	wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		if (bss_conf->use_short_slot)
+			ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
+		else
+			ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
+		if (ret < 0) {
+			wl1271_warning("Set slot time failed %d", ret);
+			goto out;
+		}
+	}
 
-	mutex_lock(&wl->mutex);
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		if (bss_conf->use_short_preamble)
+			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
+		else
+			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
+	}
 
-	if (unlikely(wl->state == WL1271_STATE_OFF))
-		goto out;
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		if (bss_conf->use_cts_prot)
+			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
+		else
+			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
+		if (ret < 0) {
+			wl1271_warning("Set ctsprotect failed %d", ret);
+			goto out;
+		}
+	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
-	if (ret < 0)
-		goto out;
+out:
+	return ret;
+}
+
+static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
+					  struct ieee80211_vif *vif,
+					  struct ieee80211_bss_conf *bss_conf,
+					  u32 changed)
+{
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+	int ret = 0;
 
-	if ((changed & BSS_CHANGED_BEACON_INT) &&
-	    (wl->bss_type == BSS_TYPE_IBSS)) {
-		wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d",
+	if ((changed & BSS_CHANGED_BEACON_INT)) {
+		wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d",
 			bss_conf->beacon_int);
 
 		wl->beacon_int = bss_conf->beacon_int;
-		do_join = true;
 	}
 
-	if ((changed & BSS_CHANGED_BEACON) &&
-	    (wl->bss_type == BSS_TYPE_IBSS)) {
-		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+	if ((changed & BSS_CHANGED_BEACON)) {
+		struct ieee80211_hdr *hdr;
+		int ieoffset = offsetof(struct ieee80211_mgmt,
+					u.beacon.variable);
+		struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
+		u16 tmpl_id;
+
+		if (!beacon)
+			goto out;
+
+		wl1271_debug(DEBUG_MASTER, "beacon updated");
+
+		ret = wl1271_ssid_set(wl, beacon, ieoffset);
+		if (ret < 0) {
+			dev_kfree_skb(beacon);
+			goto out;
+		}
+		tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
+				  CMD_TEMPL_BEACON;
+		ret = wl1271_cmd_template_set(wl, tmpl_id,
+					      beacon->data,
+					      beacon->len, 0,
+					      wl1271_tx_min_rate_get(wl));
+		if (ret < 0) {
+			dev_kfree_skb(beacon);
+			goto out;
+		}
 
-		wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated");
+		hdr = (struct ieee80211_hdr *) beacon->data;
+		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+						 IEEE80211_STYPE_PROBE_RESP);
+
+		tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
+				  CMD_TEMPL_PROBE_RESPONSE;
+		ret = wl1271_cmd_template_set(wl,
+					      tmpl_id,
+					      beacon->data,
+					      beacon->len, 0,
+					      wl1271_tx_min_rate_get(wl));
+		dev_kfree_skb(beacon);
+		if (ret < 0)
+			goto out;
+	}
 
-		if (beacon) {
-			struct ieee80211_hdr *hdr;
-			int ieoffset = offsetof(struct ieee80211_mgmt,
-						u.beacon.variable);
+out:
+	return ret;
+}
 
-			wl1271_ssid_set(wl, beacon, ieoffset);
+/* AP mode changes */
+static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *bss_conf,
+				       u32 changed)
+{
+	int ret = 0;
 
-			ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
-						      beacon->data,
-						      beacon->len, 0,
-						      wl1271_min_rate_get(wl));
+	if ((changed & BSS_CHANGED_BASIC_RATES)) {
+		u32 rates = bss_conf->basic_rates;
+		struct conf_tx_rate_class mgmt_rc;
+
+		wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
+		wl->basic_rate = wl1271_tx_min_rate_get(wl);
+		wl1271_debug(DEBUG_AP, "basic rates: 0x%x",
+			     wl->basic_rate_set);
+
+		/* update the AP management rate policy with the new rates */
+		mgmt_rc.enabled_rates = wl->basic_rate_set;
+		mgmt_rc.long_retry_limit = 10;
+		mgmt_rc.short_retry_limit = 10;
+		mgmt_rc.aflags = 0;
+		ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc,
+						ACX_TX_AP_MODE_MGMT_RATE);
+		if (ret < 0) {
+			wl1271_error("AP mgmt policy change failed %d", ret);
+			goto out;
+		}
+	}
 
-			if (ret < 0) {
-				dev_kfree_skb(beacon);
-				goto out_sleep;
-			}
+	ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed);
+	if (ret < 0)
+		goto out;
 
-			hdr = (struct ieee80211_hdr *) beacon->data;
-			hdr->frame_control = cpu_to_le16(
-				IEEE80211_FTYPE_MGMT |
-				IEEE80211_STYPE_PROBE_RESP);
+	if ((changed & BSS_CHANGED_BEACON_ENABLED)) {
+		if (bss_conf->enable_beacon) {
+			if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+				ret = wl1271_cmd_start_bss(wl);
+				if (ret < 0)
+					goto out;
 
-			ret = wl1271_cmd_template_set(wl,
-						      CMD_TEMPL_PROBE_RESPONSE,
-						      beacon->data,
-						      beacon->len, 0,
-						      wl1271_min_rate_get(wl));
-			dev_kfree_skb(beacon);
-			if (ret < 0)
-				goto out_sleep;
+				set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+				wl1271_debug(DEBUG_AP, "started AP");
 
-			/* Need to update the SSID (for filtering etc) */
-			do_join = true;
+				ret = wl1271_ap_init_hwenc(wl);
+				if (ret < 0)
+					goto out;
+			}
+		} else {
+			if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+				ret = wl1271_cmd_stop_bss(wl);
+				if (ret < 0)
+					goto out;
+
+				clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+				wl1271_debug(DEBUG_AP, "stopped AP");
+			}
 		}
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
-	    (wl->bss_type == BSS_TYPE_IBSS)) {
+	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
+	if (ret < 0)
+		goto out;
+out:
+	return;
+}
+
+/* STA/IBSS mode changes */
+static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
+					struct ieee80211_vif *vif,
+					struct ieee80211_bss_conf *bss_conf,
+					u32 changed)
+{
+	bool do_join = false, set_assoc = false;
+	bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+	u32 sta_rate_set = 0;
+	int ret;
+	struct ieee80211_sta *sta;
+	bool sta_exists = false;
+	struct ieee80211_sta_ht_cap sta_ht_cap;
+
+	if (is_ibss) {
+		ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf,
+						     changed);
+		if (ret < 0)
+			goto out;
+	}
+
+	if ((changed & BSS_CHANGED_BEACON_INT)  && is_ibss)
+		do_join = true;
+
+	/* Need to update the SSID (for filtering etc) */
+	if ((changed & BSS_CHANGED_BEACON) && is_ibss)
+		do_join = true;
+
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) {
 		wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s",
 			     bss_conf->enable_beacon ? "enabled" : "disabled");
 
@@ -1924,7 +2360,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 		do_join = true;
 	}
 
-	if (changed & BSS_CHANGED_CQM) {
+	if ((changed & BSS_CHANGED_CQM)) {
 		bool enable = false;
 		if (bss_conf->cqm_rssi_thold)
 			enable = true;
@@ -1942,24 +2378,70 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 	     * and enable the BSSID filter
 	     */
 	    memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
-			memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
+		memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
 
+		if (!is_zero_ether_addr(wl->bssid)) {
 			ret = wl1271_cmd_build_null_data(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			ret = wl1271_build_qos_null_data(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* filter out all packets not from this BSSID */
 			wl1271_configure_filters(wl, 0);
 
 			/* Need to update the BSSID (for filtering etc) */
 			do_join = true;
+		}
 	}
 
-	if (changed & BSS_CHANGED_ASSOC) {
+	rcu_read_lock();
+	sta = ieee80211_find_sta(vif, bss_conf->bssid);
+	if (sta)  {
+		/* save the supp_rates of the ap */
+		sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
+		if (sta->ht_cap.ht_supported)
+			sta_rate_set |=
+			    (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
+		sta_ht_cap = sta->ht_cap;
+		sta_exists = true;
+	}
+	rcu_read_unlock();
+
+	if (sta_exists) {
+		/* handle new association with HT and HT information change */
+		if ((changed & BSS_CHANGED_HT) &&
+		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
+							     true);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap true failed %d",
+					       ret);
+				goto out;
+			}
+			ret = wl1271_acx_set_ht_information(wl,
+						bss_conf->ht_operation_mode);
+			if (ret < 0) {
+				wl1271_warning("Set ht information failed %d",
+					       ret);
+				goto out;
+			}
+		}
+		/* handle new association without HT and disassociation */
+		else if (changed & BSS_CHANGED_ASSOC) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
+							     false);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap false failed %d",
+					       ret);
+				goto out;
+			}
+		}
+	}
+
+	if ((changed & BSS_CHANGED_ASSOC)) {
 		if (bss_conf->assoc) {
 			u32 rates;
 			int ieoffset;
@@ -1975,10 +2457,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 			rates = bss_conf->basic_rates;
 			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
 									 rates);
-			wl->basic_rate = wl1271_min_rate_get(wl);
-			ret = wl1271_acx_rate_policies(wl);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			if (sta_rate_set)
+				wl->rate_set = wl1271_tx_enabled_rates_get(wl,
+								sta_rate_set);
+			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/*
 			 * with wl1271, we don't need to update the
@@ -1988,7 +2473,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 			 */
 			ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/*
 			 * Get a template for hardware connection maintenance
@@ -2002,17 +2487,19 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 			/* enable the connection monitoring feature */
 			ret = wl1271_acx_conn_monit_params(wl, true);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* If we want to go in PSM but we're not there yet */
 			if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
 			    !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+				enum wl1271_cmd_ps_mode mode;
+
 				mode = STATION_POWER_SAVE_MODE;
 				ret = wl1271_ps_set_mode(wl, mode,
 							 wl->basic_rate,
 							 true);
 				if (ret < 0)
-					goto out_sleep;
+					goto out;
 			}
 		} else {
 			/* use defaults when not associated */
@@ -2029,10 +2516,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 
 			/* revert back to minimum rates for the current band */
 			wl1271_set_band_rate(wl);
-			wl->basic_rate = wl1271_min_rate_get(wl);
-			ret = wl1271_acx_rate_policies(wl);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* disable connection monitor features */
 			ret = wl1271_acx_conn_monit_params(wl, false);
@@ -2040,74 +2527,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 			/* Disable the keep-alive feature */
 			ret = wl1271_acx_keep_alive_mode(wl, false);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* restore the bssid filter and go to dummy bssid */
 			wl1271_unjoin(wl);
 			wl1271_dummy_join(wl);
 		}
-
 	}
 
-	if (changed & BSS_CHANGED_ERP_SLOT) {
-		if (bss_conf->use_short_slot)
-			ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
-		else
-			ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
-		if (ret < 0) {
-			wl1271_warning("Set slot time failed %d", ret);
-			goto out_sleep;
-		}
-	}
-
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		if (bss_conf->use_short_preamble)
-			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
-		else
-			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
-	}
-
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		if (bss_conf->use_cts_prot)
-			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
-		else
-			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
-		if (ret < 0) {
-			wl1271_warning("Set ctsprotect failed %d", ret);
-			goto out_sleep;
-		}
-	}
-
-	/*
-	 * Takes care of: New association with HT enable,
-	 *                HT information change in beacon.
-	 */
-	if (sta &&
-	    (changed & BSS_CHANGED_HT) &&
-	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
-		ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true);
-		if (ret < 0) {
-			wl1271_warning("Set ht cap true failed %d", ret);
-			goto out_sleep;
-		}
-			ret = wl1271_acx_set_ht_information(wl,
-				bss_conf->ht_operation_mode);
-		if (ret < 0) {
-			wl1271_warning("Set ht information failed %d", ret);
-			goto out_sleep;
-		}
-	}
-	/*
-	 * Takes care of: New association without HT,
-	 *                Disassociation.
-	 */
-	else if (sta && (changed & BSS_CHANGED_ASSOC)) {
-		ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false);
-		if (ret < 0) {
-			wl1271_warning("Set ht cap false failed %d", ret);
-			goto out_sleep;
-		}
-	}
+	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
+	if (ret < 0)
+		goto out;
 
 	if (changed & BSS_CHANGED_ARP_FILTER) {
 		__be32 addr = bss_conf->arp_addr_list[0];
@@ -2124,29 +2554,57 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 			ret = wl1271_cmd_build_arp_rsp(wl, addr);
 			if (ret < 0) {
 				wl1271_warning("build arp rsp failed: %d", ret);
-				goto out_sleep;
+				goto out;
 			}
 
 			ret = wl1271_acx_arp_ip_filter(wl,
-				(ACX_ARP_FILTER_ARP_FILTERING |
-				 ACX_ARP_FILTER_AUTO_ARP),
+				ACX_ARP_FILTER_ARP_FILTERING,
 				addr);
 		} else
 			ret = wl1271_acx_arp_ip_filter(wl, 0, addr);
 
 		if (ret < 0)
-			goto out_sleep;
+			goto out;
 	}
 
 	if (do_join) {
 		ret = wl1271_join(wl, set_assoc);
 		if (ret < 0) {
 			wl1271_warning("cmd join failed %d", ret);
-			goto out_sleep;
+			goto out;
 		}
 	}
 
-out_sleep:
+out:
+	return;
+}
+
+static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *bss_conf,
+				       u32 changed)
+{
+	struct wl1271 *wl = hw->priv;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+	int ret;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x",
+		     (int)changed);
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	if (is_ap)
+		wl1271_bss_info_changed_ap(wl, vif, bss_conf, changed);
+	else
+		wl1271_bss_info_changed_sta(wl, vif, bss_conf, changed);
+
 	wl1271_ps_elp_sleep(wl);
 
 out:
@@ -2158,42 +2616,66 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
 {
 	struct wl1271 *wl = hw->priv;
 	u8 ps_scheme;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&wl->mutex);
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
 
-	if (unlikely(wl->state == WL1271_STATE_OFF)) {
-		ret = -EAGAIN;
-		goto out;
-	}
-
-	ret = wl1271_ps_elp_wakeup(wl, false);
-	if (ret < 0)
-		goto out;
-
-	/* the txop is confed in units of 32us by the mac80211, we need us */
-	ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
-				params->cw_min, params->cw_max,
-				params->aifs, params->txop << 5);
-	if (ret < 0)
-		goto out_sleep;
-
 	if (params->uapsd)
 		ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER;
 	else
 		ps_scheme = CONF_PS_SCHEME_LEGACY;
 
-	ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
-				 CONF_CHANNEL_TYPE_EDCF,
-				 wl1271_tx_get_queue(queue),
-				 ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0);
-	if (ret < 0)
-		goto out_sleep;
+	if (wl->state == WL1271_STATE_OFF) {
+		/*
+		 * If the state is off, the parameters will be recorded and
+		 * configured on init. This happens in AP-mode.
+		 */
+		struct conf_tx_ac_category *conf_ac =
+			&wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)];
+		struct conf_tx_tid *conf_tid =
+			&wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)];
+
+		conf_ac->ac = wl1271_tx_get_queue(queue);
+		conf_ac->cw_min = (u8)params->cw_min;
+		conf_ac->cw_max = params->cw_max;
+		conf_ac->aifsn = params->aifs;
+		conf_ac->tx_op_limit = params->txop << 5;
+
+		conf_tid->queue_id = wl1271_tx_get_queue(queue);
+		conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF;
+		conf_tid->tsid = wl1271_tx_get_queue(queue);
+		conf_tid->ps_scheme = ps_scheme;
+		conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY;
+		conf_tid->apsd_conf[0] = 0;
+		conf_tid->apsd_conf[1] = 0;
+	} else {
+		ret = wl1271_ps_elp_wakeup(wl);
+		if (ret < 0)
+			goto out;
+
+		/*
+		 * the txop is confed in units of 32us by the mac80211,
+		 * we need us
+		 */
+		ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
+					params->cw_min, params->cw_max,
+					params->aifs, params->txop << 5);
+		if (ret < 0)
+			goto out_sleep;
+
+		ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
+					 CONF_CHANNEL_TYPE_EDCF,
+					 wl1271_tx_get_queue(queue),
+					 ps_scheme, CONF_ACK_POLICY_LEGACY,
+					 0, 0);
+		if (ret < 0)
+			goto out_sleep;
 
 out_sleep:
-	wl1271_ps_elp_sleep(wl);
+		wl1271_ps_elp_sleep(wl);
+	}
 
 out:
 	mutex_unlock(&wl->mutex);
@@ -2215,7 +2697,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw)
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -2247,6 +2729,184 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
 	return 0;
 }
 
+static int wl1271_allocate_sta(struct wl1271 *wl,
+			     struct ieee80211_sta *sta,
+			     u8 *hlid)
+{
+	struct wl1271_station *wl_sta;
+	int id;
+
+	id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS);
+	if (id >= AP_MAX_STATIONS) {
+		wl1271_warning("could not allocate HLID - too much stations");
+		return -EBUSY;
+	}
+
+	wl_sta = (struct wl1271_station *)sta->drv_priv;
+	__set_bit(id, wl->ap_hlid_map);
+	wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
+	*hlid = wl_sta->hlid;
+	memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
+	return 0;
+}
+
+static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
+{
+	int id = hlid - WL1271_AP_STA_HLID_START;
+
+	if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+		return;
+
+	__clear_bit(id, wl->ap_hlid_map);
+	memset(wl->links[hlid].addr, 0, ETH_ALEN);
+	wl1271_tx_reset_link_queues(wl, hlid);
+	__clear_bit(hlid, &wl->ap_ps_map);
+	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+}
+
+static int wl1271_op_sta_add(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_sta *sta)
+{
+	struct wl1271 *wl = hw->priv;
+	int ret = 0;
+	u8 hlid;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS)
+		goto out;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
+
+	ret = wl1271_allocate_sta(wl, sta, &hlid);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out_free_sta;
+
+	ret = wl1271_cmd_add_sta(wl, sta, hlid);
+	if (ret < 0)
+		goto out_sleep;
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out_free_sta:
+	if (ret < 0)
+		wl1271_free_sta(wl, hlid);
+
+out:
+	mutex_unlock(&wl->mutex);
+	return ret;
+}
+
+static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta)
+{
+	struct wl1271 *wl = hw->priv;
+	struct wl1271_station *wl_sta;
+	int ret = 0, id;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS)
+		goto out;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
+
+	wl_sta = (struct wl1271_station *)sta->drv_priv;
+	id = wl_sta->hlid - WL1271_AP_STA_HLID_START;
+	if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
+	if (ret < 0)
+		goto out_sleep;
+
+	wl1271_free_sta(wl, wl_sta->hlid);
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+	return ret;
+}
+
+int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			   enum ieee80211_ampdu_mlme_action action,
+			   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			   u8 buf_size)
+{
+	struct wl1271 *wl = hw->priv;
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		if (wl->ba_support) {
+			ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
+								 true);
+			if (!ret)
+				wl->ba_rx_bitmap |= BIT(tid);
+		} else {
+			ret = -ENOTSUPP;
+		}
+		break;
+
+	case IEEE80211_AMPDU_RX_STOP:
+		ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
+		if (!ret)
+			wl->ba_rx_bitmap &= ~BIT(tid);
+		break;
+
+	/*
+	 * The BA initiator session management in FW independently.
+	 * Falling break here on purpose for all TX APDU commands.
+	 */
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		ret = -EINVAL;
+		break;
+
+	default:
+		wl1271_error("Incorrect ampdu action id=%x\n", action);
+		ret = -EINVAL;
+	}
+
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_rate wl1271_rates[] = {
 	{ .bitrate = 10,
@@ -2305,6 +2965,7 @@ static struct ieee80211_channel wl1271_channels[] = {
 	{ .hw_value = 11, .center_freq = 2462, .max_power = 25 },
 	{ .hw_value = 12, .center_freq = 2467, .max_power = 25 },
 	{ .hw_value = 13, .center_freq = 2472, .max_power = 25 },
+	{ .hw_value = 14, .center_freq = 2484, .max_power = 25 },
 };
 
 /* mapping to indexes for wl1271_rates */
@@ -2493,6 +3154,9 @@ static const struct ieee80211_ops wl1271_ops = {
 	.conf_tx = wl1271_op_conf_tx,
 	.get_tsf = wl1271_op_get_tsf,
 	.get_survey = wl1271_op_get_survey,
+	.sta_add = wl1271_op_sta_add,
+	.sta_remove = wl1271_op_sta_remove,
+	.ampdu_action = wl1271_op_ampdu_action,
 	CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
@@ -2562,7 +3226,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev,
 	if (wl->state == WL1271_STATE_OFF)
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -2607,6 +3271,18 @@ int wl1271_register_hw(struct wl1271 *wl)
 	if (wl->mac80211_registered)
 		return 0;
 
+	ret = wl1271_fetch_nvs(wl);
+	if (ret == 0) {
+		u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
+
+		wl->mac_addr[0] = nvs_ptr[11];
+		wl->mac_addr[1] = nvs_ptr[10];
+		wl->mac_addr[2] = nvs_ptr[6];
+		wl->mac_addr[3] = nvs_ptr[5];
+		wl->mac_addr[4] = nvs_ptr[4];
+		wl->mac_addr[5] = nvs_ptr[3];
+	}
+
 	SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
 
 	ret = ieee80211_register_hw(wl->hw);
@@ -2629,6 +3305,9 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw);
 
 void wl1271_unregister_hw(struct wl1271 *wl)
 {
+	if (wl->state == WL1271_STATE_PLT)
+		__wl1271_plt_stop(wl);
+
 	unregister_netdevice_notifier(&wl1271_dev_notifier);
 	ieee80211_unregister_hw(wl->hw);
 	wl->mac80211_registered = false;
@@ -2661,13 +3340,15 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
 		IEEE80211_HW_SUPPORTS_UAPSD |
 		IEEE80211_HW_HAS_RATE_CONTROL |
 		IEEE80211_HW_CONNECTION_MONITOR |
-		IEEE80211_HW_SUPPORTS_CQM_RSSI;
+		IEEE80211_HW_SUPPORTS_CQM_RSSI |
+		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+		IEEE80211_HW_AP_LINK_PS;
 
 	wl->hw->wiphy->cipher_suites = cipher_suites;
 	wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
 	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
+		BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
 	wl->hw->wiphy->max_scan_ssids = 1;
 	/*
 	 * Maximum length of elements in scanning probe request templates
@@ -2676,8 +3357,20 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
 	 */
 	wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
 			sizeof(struct ieee80211_header);
-	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
-	wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
+
+	/*
+	 * We keep local copies of the band structs because we need to
+	 * modify them on a per-device basis.
+	 */
+	memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz,
+	       sizeof(wl1271_band_2ghz));
+	memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz,
+	       sizeof(wl1271_band_5ghz));
+
+	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+		&wl->bands[IEEE80211_BAND_2GHZ];
+	wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+		&wl->bands[IEEE80211_BAND_5GHZ];
 
 	wl->hw->queues = 4;
 	wl->hw->max_rates = 1;
@@ -2686,6 +3379,10 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
 
 	SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
 
+	wl->hw->sta_data_size = sizeof(struct wl1271_station);
+
+	wl->hw->max_rx_aggregation_subframes = 8;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
@@ -2697,7 +3394,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	struct ieee80211_hw *hw;
 	struct platform_device *plat_dev = NULL;
 	struct wl1271 *wl;
-	int i, ret;
+	int i, j, ret;
 	unsigned int order;
 
 	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
@@ -2725,9 +3422,16 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	for (i = 0; i < NUM_TX_QUEUES; i++)
 		skb_queue_head_init(&wl->tx_queue[i]);
 
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		for (j = 0; j < AP_MAX_LINKS; j++)
+			skb_queue_head_init(&wl->links[j].tx_queue[i]);
+
+	skb_queue_head_init(&wl->deferred_rx_queue);
+	skb_queue_head_init(&wl->deferred_tx_queue);
+
 	INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
 	INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
-	INIT_WORK(&wl->irq_work, wl1271_irq_work);
+	INIT_WORK(&wl->netstack_work, wl1271_netstack_work);
 	INIT_WORK(&wl->tx_work, wl1271_tx_work);
 	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
 	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
@@ -2735,19 +3439,25 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
 	wl->default_key = 0;
 	wl->rx_counter = 0;
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+	wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
+	wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
 	wl->psm_entry_retry = 0;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
 	wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
 	wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
-	wl->sta_rate_set = 0;
 	wl->band = IEEE80211_BAND_2GHZ;
 	wl->vif = NULL;
 	wl->flags = 0;
 	wl->sg_enabled = true;
 	wl->hw_pg_ver = -1;
+	wl->bss_type = MAX_BSS_TYPE;
+	wl->set_bss_type = MAX_BSS_TYPE;
+	wl->fw_bss_type = MAX_BSS_TYPE;
+	wl->last_tx_hlid = 0;
+	wl->ap_ps_map = 0;
+	wl->ap_fw_ps_map = 0;
+	wl->quirks = 0;
 
 	memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
 	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
@@ -2837,11 +3547,11 @@ int wl1271_free_hw(struct wl1271 *wl)
 }
 EXPORT_SYMBOL_GPL(wl1271_free_hw);
 
-u32 wl12xx_debug_level;
+u32 wl12xx_debug_level = DEBUG_NONE;
 EXPORT_SYMBOL_GPL(wl12xx_debug_level);
-module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE);
+module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 60a3738..971f13e 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -24,6 +24,7 @@
 #include "reg.h"
 #include "ps.h"
 #include "io.h"
+#include "tx.h"
 
 #define WL1271_WAKEUP_TIMEOUT 500
 
@@ -68,7 +69,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
 	}
 }
 
-int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
+int wl1271_ps_elp_wakeup(struct wl1271 *wl)
 {
 	DECLARE_COMPLETION_ONSTACK(compl);
 	unsigned long flags;
@@ -86,7 +87,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
 	 * the completion variable in one entity.
 	 */
 	spin_lock_irqsave(&wl->wl_lock, flags);
-	if (work_pending(&wl->irq_work) || chip_awake)
+	if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
 		pending = true;
 	else
 		wl->elp_compl = &compl;
@@ -139,8 +140,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 			return ret;
 		}
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
-					 rates, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
 
@@ -149,7 +149,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 	case STATION_ACTIVE_MODE:
 	default:
 		wl1271_debug(DEBUG_PSM, "leaving psm");
-		ret = wl1271_ps_elp_wakeup(wl, false);
+		ret = wl1271_ps_elp_wakeup(wl);
 		if (ret < 0)
 			return ret;
 
@@ -163,8 +163,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 		if (ret < 0)
 			return ret;
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
-					 rates, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
 		if (ret < 0)
 			return ret;
 
@@ -175,4 +174,81 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 	return ret;
 }
 
+static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
+{
+	int i, filtered = 0;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
+	unsigned long flags;
+
+	/* filter all frames currently the low level queus for this hlid */
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+			info = IEEE80211_SKB_CB(skb);
+			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+			info->status.rates[0].idx = -1;
+			ieee80211_tx_status(wl->hw, skb);
+			filtered++;
+		}
+	}
+
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	wl->tx_queue_count -= filtered;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	wl1271_handle_tx_low_watermark(wl);
+}
+
+void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
+{
+	struct ieee80211_sta *sta;
+
+	if (test_bit(hlid, &wl->ap_ps_map))
+		return;
+
+	wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
+		     "clean_queues %d", hlid, wl->links[hlid].allocated_blks,
+		     clean_queues);
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
+	if (!sta) {
+		wl1271_error("could not find sta %pM for starting ps",
+			     wl->links[hlid].addr);
+		rcu_read_unlock();
+		return;
+	}
 
+	ieee80211_sta_ps_transition_ni(sta, true);
+	rcu_read_unlock();
+
+	/* do we want to filter all frames from this link's queues? */
+	if (clean_queues)
+		wl1271_ps_filter_frames(wl, hlid);
+
+	__set_bit(hlid, &wl->ap_ps_map);
+}
+
+void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid)
+{
+	struct ieee80211_sta *sta;
+
+	if (!test_bit(hlid, &wl->ap_ps_map))
+		return;
+
+	wl1271_debug(DEBUG_PSM, "end mac80211 PSM on hlid %d", hlid);
+
+	__clear_bit(hlid, &wl->ap_ps_map);
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
+	if (!sta) {
+		wl1271_error("could not find sta %pM for ending ps",
+			     wl->links[hlid].addr);
+		goto end;
+	}
+
+	ieee80211_sta_ps_transition_ni(sta, false);
+end:
+	rcu_read_unlock();
+}
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h
index 8415060..c41bd0a 100644
--- a/drivers/net/wireless/wl12xx/ps.h
+++ b/drivers/net/wireless/wl12xx/ps.h
@@ -30,7 +30,9 @@
 int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 		       u32 rates, bool send);
 void wl1271_ps_elp_sleep(struct wl1271 *wl);
-int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
+int wl1271_ps_elp_wakeup(struct wl1271 *wl);
 void wl1271_elp_work(struct work_struct *work);
+void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
+void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
 
 #endif /* __WL1271_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 682304c..919b59f 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -29,14 +29,14 @@
 #include "rx.h"
 #include "io.h"
 
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
+static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
 				  u32 drv_rx_counter)
 {
 	return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
 		RX_MEM_BLOCK_MASK;
 }
 
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
+static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
 				 u32 drv_rx_counter)
 {
 	return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
@@ -76,7 +76,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
 	 */
 	wl->noise = desc->rssi - (desc->snr >> 1);
 
-	status->freq = ieee80211_channel_to_frequency(desc->channel);
+	status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band);
 
 	if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -92,7 +92,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 {
 	struct wl1271_rx_descriptor *desc;
 	struct sk_buff *skb;
-	u16 *fc;
+	struct ieee80211_hdr *hdr;
 	u8 *buf;
 	u8 beacon = 0;
 
@@ -118,8 +118,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 	/* now we pull the descriptor out of the buffer */
 	skb_pull(skb, sizeof(*desc));
 
-	fc = (u16 *)skb->data;
-	if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
+	hdr = (struct ieee80211_hdr *)skb->data;
+	if (ieee80211_is_beacon(hdr->frame_control))
 		beacon = 1;
 
 	wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
@@ -129,12 +129,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length)
 
 	skb_trim(skb, skb->len - desc->pad_len);
 
-	ieee80211_rx_ni(wl->hw, skb);
+	skb_queue_tail(&wl->deferred_rx_queue, skb);
+	ieee80211_queue_work(wl->hw, &wl->netstack_work);
 
 	return 0;
 }
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 {
 	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
 	u32 buf_size;
@@ -198,6 +199,22 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
 			pkt_offset += pkt_length;
 		}
 	}
-	wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
-			cpu_to_le32(wl->rx_counter));
+
+	/*
+	 * Write the driver's packet counter to the FW. This is only required
+	 * for older hardware revisions
+	 */
+	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
+		wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+}
+
+void wl1271_set_default_filters(struct wl1271 *wl)
+{
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
+		wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
+	} else {
+		wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
+		wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
+	}
 }
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 3abb26f..75fabf8 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -30,10 +30,6 @@
 #define WL1271_RX_MAX_RSSI -30
 #define WL1271_RX_MIN_RSSI -95
 
-#define WL1271_RX_ALIGN_TO 4
-#define WL1271_RX_ALIGN(len) (((len) + WL1271_RX_ALIGN_TO - 1) & \
-			     ~(WL1271_RX_ALIGN_TO - 1))
-
 #define SHORT_PREAMBLE_BIT   BIT(0)
 #define OFDM_RATE_BIT        BIT(6)
 #define PBCC_RATE_BIT        BIT(7)
@@ -86,8 +82,9 @@
 /*
  * RX Descriptor status
  *
- * Bits 0-2 - status
- * Bits 3-7 - reserved
+ * Bits 0-2 - error code
+ * Bits 3-5 - process_id tag (AP mode FW)
+ * Bits 6-7 - reserved
  */
 #define WL1271_RX_DESC_STATUS_MASK      0x07
 
@@ -110,12 +107,16 @@ struct wl1271_rx_descriptor {
 	u8  snr;
 	__le32 timestamp;
 	u8  packet_class;
-	u8  process_id;
+	union {
+		u8  process_id; /* STA FW */
+		u8  hlid; /* AP FW */
+	} __packed;
 	u8  pad_len;
 	u8  reserved;
 } __packed;
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
+void wl1271_set_default_filters(struct wl1271 *wl);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 6f897b9..420653a 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -27,6 +27,7 @@
 #include "cmd.h"
 #include "scan.h"
 #include "acx.h"
+#include "ps.h"
 
 void wl1271_scan_complete_work(struct work_struct *work)
 {
@@ -40,10 +41,11 @@ void wl1271_scan_complete_work(struct work_struct *work)
 
 	mutex_lock(&wl->mutex);
 
-	if (wl->scan.state == WL1271_SCAN_STATE_IDLE) {
-		mutex_unlock(&wl->mutex);
-		return;
-	}
+	if (wl->state == WL1271_STATE_OFF)
+		goto out;
+
+	if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
+		goto out;
 
 	wl->scan.state = WL1271_SCAN_STATE_IDLE;
 	kfree(wl->scan.scanned_ch);
@@ -52,13 +54,19 @@ void wl1271_scan_complete_work(struct work_struct *work)
 	ieee80211_scan_completed(wl->hw, false);
 
 	/* restore hardware connection monitoring template */
-	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
-		wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
+	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+		if (wl1271_ps_elp_wakeup(wl) == 0) {
+			wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
+			wl1271_ps_elp_sleep(wl);
+		}
+	}
 
 	if (wl->scan.failed) {
 		wl1271_info("Scan completed due to error.");
 		ieee80211_queue_work(wl->hw, &wl->recovery_work);
 	}
+
+out:
 	mutex_unlock(&wl->mutex);
 
 }
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 93cbb8d..5b9dbea 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -28,6 +28,7 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 #include <linux/gpio.h>
 #include <linux/wl12xx.h>
 #include <linux/pm_runtime.h>
@@ -60,7 +61,7 @@ static struct device *wl1271_sdio_wl_to_dev(struct wl1271 *wl)
 	return &(wl_to_func(wl)->dev);
 }
 
-static irqreturn_t wl1271_irq(int irq, void *cookie)
+static irqreturn_t wl1271_hardirq(int irq, void *cookie)
 {
 	struct wl1271 *wl = cookie;
 	unsigned long flags;
@@ -69,17 +70,14 @@ static irqreturn_t wl1271_irq(int irq, void *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_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->irq_work);
-	set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
@@ -106,8 +104,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
 	int ret;
 	struct sdio_func *func = wl_to_func(wl);
 
-	sdio_claim_host(func);
-
 	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
 		((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
 		wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
@@ -123,8 +119,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
 		wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
 	}
 
-	sdio_release_host(func);
-
 	if (ret)
 		wl1271_error("sdio read failed (%d)", ret);
 }
@@ -135,8 +129,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
 	int ret;
 	struct sdio_func *func = wl_to_func(wl);
 
-	sdio_claim_host(func);
-
 	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
 		sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
 		wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
@@ -152,8 +144,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
 			ret = sdio_memcpy_toio(func, addr, buf, len);
 	}
 
-	sdio_release_host(func);
-
 	if (ret)
 		wl1271_error("sdio write failed (%d)", ret);
 }
@@ -163,14 +153,18 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
 	struct sdio_func *func = wl_to_func(wl);
 	int ret;
 
-	/* Power up the card */
+	/* Make sure the card will not be powered off by runtime PM */
 	ret = pm_runtime_get_sync(&func->dev);
 	if (ret < 0)
 		goto out;
 
+	/* Runtime PM might be disabled, so power up the card manually */
+	ret = mmc_power_restore_host(func->card->host);
+	if (ret < 0)
+		goto out;
+
 	sdio_claim_host(func);
 	sdio_enable_func(func);
-	sdio_release_host(func);
 
 out:
 	return ret;
@@ -179,12 +173,17 @@ out:
 static int wl1271_sdio_power_off(struct wl1271 *wl)
 {
 	struct sdio_func *func = wl_to_func(wl);
+	int ret;
 
-	sdio_claim_host(func);
 	sdio_disable_func(func);
 	sdio_release_host(func);
 
-	/* Power down the card */
+	/* Runtime PM might be disabled, so power off the card manually */
+	ret = mmc_power_save_host(func->card->host);
+	if (ret < 0)
+		return ret;
+
+	/* Let runtime PM know the card is powered off */
 	return pm_runtime_put_sync(&func->dev);
 }
 
@@ -241,14 +240,14 @@ static int __devinit wl1271_probe(struct sdio_func *func,
 	wl->irq = wlan_data->irq;
 	wl->ref_clock = wlan_data->board_ref_clock;
 
-	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
+	ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   DRIVER_NAME, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
 		goto out_free;
 	}
 
-	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
 	disable_irq(wl->irq);
 
 	ret = wl1271_init_ieee80211(wl);
@@ -271,7 +270,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
  out_irq:
 	free_irq(wl->irq, wl);
 
-
  out_free:
 	wl1271_free_hw(wl);
 
@@ -345,3 +343,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL1271_AP_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 7145ea5..18cf017 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -110,6 +110,7 @@ static void wl1271_spi_reset(struct wl1271 *wl)
 	spi_message_add_tail(&t, &m);
 
 	spi_sync(wl_to_spi(wl), &m);
+
 	wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
 	kfree(cmd);
 }
@@ -319,28 +320,23 @@ static void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
 	spi_sync(wl_to_spi(wl), &m);
 }
 
-static irqreturn_t wl1271_irq(int irq, void *cookie)
+static irqreturn_t wl1271_hardirq(int irq, void *cookie)
 {
-	struct wl1271 *wl;
+	struct wl1271 *wl = cookie;
 	unsigned long flags;
 
 	wl1271_debug(DEBUG_IRQ, "IRQ");
 
-	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_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->irq_work);
-	set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
@@ -412,14 +408,14 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 		goto out_free;
 	}
 
-	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
+	ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   DRIVER_NAME, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
 		goto out_free;
 	}
 
-	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
 	disable_irq(wl->irq);
 
 	ret = wl1271_init_ieee80211(wl);
@@ -494,4 +490,5 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL1271_AP_FW_NAME);
 MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index b44c75c..5e9ef7d 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/etherdevice.h>
 
 #include "wl12xx.h"
 #include "io.h"
@@ -30,6 +31,23 @@
 #include "ps.h"
 #include "tx.h"
 
+static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
+{
+	int ret;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+
+	if (is_ap)
+		ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
+	else
+		ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
+
+	if (ret < 0)
+		return ret;
+
+	wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id);
+	return 0;
+}
+
 static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
 {
 	int id;
@@ -52,8 +70,65 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
 	}
 }
 
+static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
+						 struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+
+	/*
+	 * add the station to the known list before transmitting the
+	 * authentication response. this way it won't get de-authed by FW
+	 * when transmitting too soon.
+	 */
+	hdr = (struct ieee80211_hdr *)(skb->data +
+				       sizeof(struct wl1271_tx_hw_descr));
+	if (ieee80211_is_auth(hdr->frame_control))
+		wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
+}
+
+static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
+{
+	bool fw_ps;
+	u8 tx_blks;
+
+	/* only regulate station links */
+	if (hlid < WL1271_AP_STA_HLID_START)
+		return;
+
+	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+	tx_blks = wl->links[hlid].allocated_blks;
+
+	/*
+	 * 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.
+	 */
+	if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+		wl1271_ps_link_start(wl, hlid, true);
+}
+
+u8 wl1271_tx_get_hlid(struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
+
+	if (control->control.sta) {
+		struct wl1271_station *wl_sta;
+
+		wl_sta = (struct wl1271_station *)
+				control->control.sta->drv_priv;
+		return wl_sta->hlid;
+	} else {
+		struct ieee80211_hdr *hdr;
+
+		hdr = (struct ieee80211_hdr *)skb->data;
+		if (ieee80211_is_mgmt(hdr->frame_control))
+			return WL1271_AP_GLOBAL_HLID;
+		else
+			return WL1271_AP_BROADCAST_HLID;
+	}
+}
+
 static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
-				u32 buf_offset)
+				u32 buf_offset, u8 hlid)
 {
 	struct wl1271_tx_hw_descr *desc;
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
@@ -82,6 +157,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 
 		wl->tx_blocks_available -= total_blocks;
 
+		if (wl->bss_type == BSS_TYPE_AP_BSS)
+			wl->links[hlid].allocated_blks += total_blocks;
+
 		ret = 0;
 
 		wl1271_debug(DEBUG_TX,
@@ -95,11 +173,12 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 }
 
 static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
-			      u32 extra, struct ieee80211_tx_info *control)
+			      u32 extra, struct ieee80211_tx_info *control,
+			      u8 hlid)
 {
 	struct timespec ts;
 	struct wl1271_tx_hw_descr *desc;
-	int pad, ac;
+	int pad, ac, rate_idx;
 	s64 hosttime;
 	u16 tx_attr;
 
@@ -117,7 +196,11 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
 	getnstimeofday(&ts);
 	hosttime = (timespec_to_ns(&ts) >> 10);
 	desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
-	desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS)
+		desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
+	else
+		desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
 
 	/* configure the tx attributes */
 	tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
@@ -125,25 +208,49 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
 	/* queue (we use same identifiers for tid's and ac's */
 	ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 	desc->tid = ac;
-	desc->aid = TX_HW_DEFAULT_AID;
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS) {
+		desc->aid = hlid;
+
+		/* if the packets are destined for AP (have a STA entry)
+		   send them with AP rate policies, otherwise use default
+		   basic rates */
+		if (control->control.sta)
+			rate_idx = ACX_TX_AP_FULL_RATE;
+		else
+			rate_idx = ACX_TX_BASIC_RATE;
+	} else {
+		desc->hlid = hlid;
+		switch (hlid) {
+		case WL1271_AP_GLOBAL_HLID:
+			rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
+			break;
+		case WL1271_AP_BROADCAST_HLID:
+			rate_idx = ACX_TX_AP_MODE_BCST_RATE;
+			break;
+		default:
+			rate_idx = ac;
+			break;
+		}
+	}
+
+	tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
 	desc->reserved = 0;
 
 	/* align the length (and store in terms of words) */
-	pad = WL1271_TX_ALIGN(skb->len);
+	pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
 	desc->length = cpu_to_le16(pad >> 2);
 
 	/* calculate number of padding bytes */
 	pad = pad - skb->len;
 	tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
 
-	/* if the packets are destined for AP (have a STA entry) send them
-	   with AP rate policies, otherwise use default basic rates */
-	if (control->control.sta)
-		tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
-
 	desc->tx_attr = cpu_to_le16(tx_attr);
 
-	wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
+	wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
+		"tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
+		le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
+		le16_to_cpu(desc->life_time), desc->total_mem_blocks);
 }
 
 /* caller must hold wl->mutex */
@@ -153,8 +260,8 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 	struct ieee80211_tx_info *info;
 	u32 extra = 0;
 	int ret = 0;
-	u8 idx;
 	u32 total_len;
+	u8 hlid;
 
 	if (!skb)
 		return -EINVAL;
@@ -166,29 +273,43 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 		extra = WL1271_TKIP_IV_SPACE;
 
 	if (info->control.hw_key) {
-		idx = info->control.hw_key->hw_key_idx;
+		bool is_wep;
+		u8 idx = info->control.hw_key->hw_key_idx;
+		u32 cipher = info->control.hw_key->cipher;
 
-		/* FIXME: do we have to do this if we're not using WEP? */
-		if (unlikely(wl->default_key != idx)) {
-			ret = wl1271_cmd_set_default_wep_key(wl, idx);
+		is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
+			 (cipher == WLAN_CIPHER_SUITE_WEP104);
+
+		if (unlikely(is_wep && wl->default_key != idx)) {
+			ret = wl1271_set_default_wep_key(wl, idx);
 			if (ret < 0)
 				return ret;
 			wl->default_key = idx;
 		}
 	}
 
-	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset);
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		hlid = wl1271_tx_get_hlid(skb);
+	else
+		hlid = TX_HW_DEFAULT_AID;
+
+	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
 	if (ret < 0)
 		return ret;
 
-	wl1271_tx_fill_hdr(wl, skb, extra, info);
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		wl1271_tx_ap_update_inconnection_sta(wl, skb);
+		wl1271_tx_regulate_link(wl, hlid);
+	}
+
+	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
 
 	/*
 	 * The length of each packet is stored in terms of words. Thus, we must
 	 * pad the skb data to make sure its length is aligned.
 	 * The number of padding bytes is computed and set in wl1271_tx_fill_hdr
 	 */
-	total_len = WL1271_TX_ALIGN(skb->len);
+	total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
 	memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
 	memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
 
@@ -222,7 +343,7 @@ u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
 	return enabled_rates;
 }
 
-static void handle_tx_low_watermark(struct wl1271 *wl)
+void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
 {
 	unsigned long flags;
 
@@ -236,7 +357,7 @@ static void handle_tx_low_watermark(struct wl1271 *wl)
 	}
 }
 
-static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
+static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
@@ -262,12 +383,69 @@ out:
 	return skb;
 }
 
+static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
+{
+	struct sk_buff *skb = NULL;
+	unsigned long flags;
+	int i, h, start_hlid;
+
+	/* start from the link after the last one */
+	start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
+
+	/* dequeue according to AC, round robin on each link */
+	for (i = 0; i < AP_MAX_LINKS; i++) {
+		h = (start_hlid + i) % AP_MAX_LINKS;
+
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+		if (skb)
+			goto out;
+	}
+
+out:
+	if (skb) {
+		wl->last_tx_hlid = h;
+		spin_lock_irqsave(&wl->wl_lock, flags);
+		wl->tx_queue_count--;
+		spin_unlock_irqrestore(&wl->wl_lock, flags);
+	} else {
+		wl->last_tx_hlid = 0;
+	}
+
+	return skb;
+}
+
+static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
+{
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		return wl1271_ap_skb_dequeue(wl);
+
+	return wl1271_sta_skb_dequeue(wl);
+}
+
 static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
 {
 	unsigned long flags;
 	int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 
-	skb_queue_head(&wl->tx_queue[q], skb);
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		u8 hlid = wl1271_tx_get_hlid(skb);
+		skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
+
+		/* make sure we dequeue the same packet next time */
+		wl->last_tx_hlid = (hlid + AP_MAX_LINKS - 1) % AP_MAX_LINKS;
+	} else {
+		skb_queue_head(&wl->tx_queue[q], skb);
+	}
+
 	spin_lock_irqsave(&wl->wl_lock, flags);
 	wl->tx_queue_count++;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
@@ -277,38 +455,16 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
 {
 	struct sk_buff *skb;
 	bool woken_up = false;
-	u32 sta_rates = 0;
 	u32 buf_offset = 0;
 	bool sent_packets = false;
 	int ret;
 
-	/* check if the rates supported by the AP have changed */
-	if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
-					&wl->flags))) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
-		sta_rates = wl->sta_rate_set;
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-	}
-
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	/* if rates have changed, re-configure the rate policy */
-	if (unlikely(sta_rates)) {
-		ret = wl1271_ps_elp_wakeup(wl, false);
-		if (ret < 0)
-			goto out;
-		woken_up = true;
-
-		wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
-		wl1271_acx_rate_policies(wl);
-	}
-
 	while ((skb = wl1271_skb_dequeue(wl))) {
 		if (!woken_up) {
-			ret = wl1271_ps_elp_wakeup(wl, false);
+			ret = wl1271_ps_elp_wakeup(wl);
 			if (ret < 0)
 				goto out_ack;
 			woken_up = true;
@@ -350,9 +506,15 @@ out_ack:
 		sent_packets = true;
 	}
 	if (sent_packets) {
-		/* interrupt the firmware with the new packets */
-		wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
-		handle_tx_low_watermark(wl);
+		/*
+		 * Interrupt the firmware with the new packets. This is only
+		 * required for older hardware revisions
+		 */
+		if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
+			wl1271_write32(wl, WL1271_HOST_WR_ACCESS,
+				       wl->tx_packets_count);
+
+		wl1271_handle_tx_low_watermark(wl);
 	}
 
 out:
@@ -427,7 +589,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 		     result->rate_class_index, result->status);
 
 	/* return the packet to the stack */
-	ieee80211_tx_status(wl->hw, skb);
+	skb_queue_tail(&wl->deferred_tx_queue, skb);
+	ieee80211_queue_work(wl->hw, &wl->netstack_work);
 	wl1271_free_tx_id(wl, result->id);
 }
 
@@ -469,34 +632,92 @@ void wl1271_tx_complete(struct wl1271 *wl)
 	}
 }
 
+void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
+{
+	struct sk_buff *skb;
+	int i, total = 0;
+	unsigned long flags;
+	struct ieee80211_tx_info *info;
+
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+			wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
+			info = IEEE80211_SKB_CB(skb);
+			info->status.rates[0].idx = -1;
+			info->status.rates[0].count = 0;
+			ieee80211_tx_status(wl->hw, skb);
+			total++;
+		}
+	}
+
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	wl->tx_queue_count -= total;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	wl1271_handle_tx_low_watermark(wl);
+}
+
 /* caller must hold wl->mutex */
 void wl1271_tx_reset(struct wl1271 *wl)
 {
 	int i;
 	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
 
 	/* TX failure */
-	for (i = 0; i < NUM_TX_QUEUES; i++) {
-		while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
-			wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
-			ieee80211_tx_status(wl->hw, skb);
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		for (i = 0; i < AP_MAX_LINKS; i++) {
+			wl1271_tx_reset_link_queues(wl, i);
+			wl->links[i].allocated_blks = 0;
+			wl->links[i].prev_freed_blks = 0;
+		}
+
+		wl->last_tx_hlid = 0;
+	} else {
+		for (i = 0; i < NUM_TX_QUEUES; i++) {
+			while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
+				wl1271_debug(DEBUG_TX, "freeing skb 0x%p",
+					     skb);
+				info = IEEE80211_SKB_CB(skb);
+				info->status.rates[0].idx = -1;
+				info->status.rates[0].count = 0;
+				ieee80211_tx_status(wl->hw, skb);
+			}
 		}
 	}
+
 	wl->tx_queue_count = 0;
 
 	/*
 	 * Make sure the driver is at a consistent state, in case this
 	 * function is called from a context other than interface removal.
 	 */
-	handle_tx_low_watermark(wl);
+	wl1271_handle_tx_low_watermark(wl);
 
-	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
-		if (wl->tx_frames[i] != NULL) {
-			skb = wl->tx_frames[i];
-			wl1271_free_tx_id(wl, i);
-			wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
-			ieee80211_tx_status(wl->hw, skb);
+	for (i = 0; i < ACX_TX_DESCRIPTORS; i++) {
+		if (wl->tx_frames[i] == NULL)
+			continue;
+
+		skb = wl->tx_frames[i];
+		wl1271_free_tx_id(wl, i);
+		wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
+
+		/* Remove private headers before passing the skb to mac80211 */
+		info = IEEE80211_SKB_CB(skb);
+		skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
+		if (info->control.hw_key &&
+		    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+			int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+			memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data,
+				hdrlen);
+			skb_pull(skb, WL1271_TKIP_IV_SPACE);
 		}
+
+		info->status.rates[0].idx = -1;
+		info->status.rates[0].count = 0;
+
+		ieee80211_tx_status(wl->hw, skb);
+	}
 }
 
 #define WL1271_TX_FLUSH_TIMEOUT 500000
@@ -509,8 +730,8 @@ void wl1271_tx_flush(struct wl1271 *wl)
 
 	while (!time_after(jiffies, timeout)) {
 		mutex_lock(&wl->mutex);
-		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
-			     wl->tx_frames_cnt);
+		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
+			     wl->tx_frames_cnt, wl->tx_queue_count);
 		if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
 			mutex_unlock(&wl->mutex);
 			return;
@@ -521,3 +742,21 @@ void wl1271_tx_flush(struct wl1271 *wl)
 
 	wl1271_warning("Unable to flush all TX buffers, timed out.");
 }
+
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
+{
+	int i;
+	u32 rate = 0;
+
+	if (!wl->basic_rate_set) {
+		WARN_ON(1);
+		wl->basic_rate_set = wl->conf.tx.basic_rate;
+	}
+
+	for (i = 0; !rate; i++) {
+		if ((wl->basic_rate_set >> i) & 0x1)
+			rate = 1 << i;
+	}
+
+	return rate;
+}
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 903e5dc..02f07fa 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -29,6 +29,7 @@
 #define TX_HW_BLOCK_SIZE                 252
 
 #define TX_HW_MGMT_PKT_LIFETIME_TU       2000
+#define TX_HW_AP_MODE_PKT_LIFETIME_TU    8000
 /* The chipset reference driver states, that the "aid" value 1
  * is for infra-BSS, but is still always used */
 #define TX_HW_DEFAULT_AID                1
@@ -52,8 +53,6 @@
 #define TX_HW_RESULT_QUEUE_LEN_MASK      0xf
 
 #define WL1271_TX_ALIGN_TO 4
-#define WL1271_TX_ALIGN(len) (((len) + WL1271_TX_ALIGN_TO - 1) & \
-			     ~(WL1271_TX_ALIGN_TO - 1))
 #define WL1271_TKIP_IV_SPACE 4
 
 struct wl1271_tx_hw_descr {
@@ -77,8 +76,12 @@ struct wl1271_tx_hw_descr {
 	u8 id;
 	/* The packet TID value (as User-Priority) */
 	u8 tid;
-	/* Identifier of the remote STA in IBSS, 1 in infra-BSS */
-	u8 aid;
+	union {
+		/* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
+		u8 aid;
+		/* AP - host link ID (HLID) */
+		u8 hlid;
+	} __packed;
 	u8 reserved;
 } __packed;
 
@@ -146,5 +149,9 @@ void wl1271_tx_reset(struct wl1271 *wl);
 void wl1271_tx_flush(struct wl1271 *wl);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
+u8 wl1271_tx_get_hlid(struct sk_buff *skb);
+void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
+void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9050dd9..86be83e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -38,6 +38,13 @@
 #define DRIVER_NAME "wl1271"
 #define DRIVER_PREFIX DRIVER_NAME ": "
 
+/*
+ * FW versions support BA 11n
+ * versions marks x.x.x.50-60.x
+ */
+#define WL12XX_BA_SUPPORT_FW_COST_VER2_START    50
+#define WL12XX_BA_SUPPORT_FW_COST_VER2_END      60
+
 enum {
 	DEBUG_NONE	= 0,
 	DEBUG_IRQ	= BIT(0),
@@ -57,6 +64,8 @@ enum {
 	DEBUG_SDIO	= BIT(14),
 	DEBUG_FILTERS   = BIT(15),
 	DEBUG_ADHOC     = BIT(16),
+	DEBUG_AP	= BIT(17),
+	DEBUG_MASTER	= (DEBUG_ADHOC | DEBUG_AP),
 	DEBUG_ALL	= ~0,
 };
 
@@ -103,17 +112,28 @@ extern u32 wl12xx_debug_level;
 				       true);				\
 	} while (0)
 
-#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN |	\
+#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN |	\
 				  CFG_BSSID_FILTER_EN | \
 				  CFG_MC_FILTER_EN)
 
-#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN |  \
+#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN |  \
 				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN |   \
 				  CFG_RX_CTL_EN | CFG_RX_BCN_EN |     \
 				  CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
 
-#define WL1271_FW_NAME "wl1271-fw.bin"
-#define WL1271_NVS_NAME "wl1271-nvs.bin"
+#define WL1271_DEFAULT_AP_RX_CONFIG  0
+
+#define WL1271_DEFAULT_AP_RX_FILTER  (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
+				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
+				  CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
+				  CFG_RX_ASSOC_EN)
+
+
+
+#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
+#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
+
+#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
 
 #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
 #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
@@ -129,6 +149,25 @@ extern u32 wl12xx_debug_level;
 #define WL1271_DEFAULT_BEACON_INT  100
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
+#define WL1271_AP_GLOBAL_HLID      0
+#define WL1271_AP_BROADCAST_HLID   1
+#define WL1271_AP_STA_HLID_START   2
+
+/*
+ * When in AP-mode, we allow (at least) this number of mem-blocks
+ * to be transmitted to FW for a STA in PS-mode. Only when packets are
+ * present in the FW buffers it will wake the sleeping STA. We want to put
+ * enough packets for the driver to transmit all of its buffered data before
+ * the STA goes to sleep again. But we don't want to take too much mem-blocks
+ * as it might hurt the throughput of active STAs.
+ * The number of blocks (18) is enough for 2 large packets.
+ */
+#define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)
+
+#define WL1271_AP_BSS_INDEX        0
+#define WL1271_AP_DEF_INACTIV_SEC  300
+#define WL1271_AP_DEF_BEACON_EXP   20
+
 #define ACX_TX_DESCRIPTORS         32
 
 #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
@@ -161,10 +200,13 @@ struct wl1271_partition_set {
 
 struct wl1271;
 
+#define WL12XX_NUM_FW_VER 5
+
 /* FIXME: I'm not sure about this structure name */
 struct wl1271_chip {
 	u32 id;
-	char fw_ver[21];
+	char fw_ver_str[ETHTOOL_BUSINFO_LEN];
+	unsigned int fw_ver[WL12XX_NUM_FW_VER];
 };
 
 struct wl1271_stats {
@@ -178,8 +220,13 @@ struct wl1271_stats {
 #define NUM_TX_QUEUES              4
 #define NUM_RX_PKT_DESC            8
 
-/* FW status registers */
-struct wl1271_fw_status {
+#define AP_MAX_STATIONS            5
+
+/* Broadcast and Global links + links to stations */
+#define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
+
+/* FW status registers common for AP/STA */
+struct wl1271_fw_common_status {
 	__le32 intr;
 	u8  fw_rx_counter;
 	u8  drv_rx_counter;
@@ -188,9 +235,43 @@ struct wl1271_fw_status {
 	__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
 	__le32 tx_released_blks[NUM_TX_QUEUES];
 	__le32 fw_localtime;
-	__le32 padding[2];
 } __packed;
 
+/* FW status registers for AP */
+struct wl1271_fw_ap_status {
+	struct wl1271_fw_common_status common;
+
+	/* Next fields valid only in AP FW */
+
+	/*
+	 * A bitmap (where each bit represents a single HLID)
+	 * to indicate if the station is in PS mode.
+	 */
+	__le32 link_ps_bitmap;
+
+	/* Number of freed MBs per HLID */
+	u8 tx_lnk_free_blks[AP_MAX_LINKS];
+	u8 padding_1[1];
+} __packed;
+
+/* FW status registers for STA */
+struct wl1271_fw_sta_status {
+	struct wl1271_fw_common_status common;
+
+	u8  tx_total;
+	u8  reserved1;
+	__le16 reserved2;
+} __packed;
+
+struct wl1271_fw_full_status {
+	union {
+		struct wl1271_fw_common_status common;
+		struct wl1271_fw_sta_status sta;
+		struct wl1271_fw_ap_status ap;
+	};
+} __packed;
+
+
 struct wl1271_rx_mem_pool_addr {
 	u32 addr;
 	u32 addr_extra;
@@ -218,6 +299,48 @@ struct wl1271_if_operations {
 	void (*disable_irq)(struct wl1271 *wl);
 };
 
+#define MAX_NUM_KEYS 14
+#define MAX_KEY_SIZE 32
+
+struct wl1271_ap_key {
+	u8 id;
+	u8 key_type;
+	u8 key_size;
+	u8 key[MAX_KEY_SIZE];
+	u8 hlid;
+	u32 tx_seq_32;
+	u16 tx_seq_16;
+};
+
+enum wl12xx_flags {
+	WL1271_FLAG_STA_ASSOCIATED,
+	WL1271_FLAG_JOINED,
+	WL1271_FLAG_GPIO_POWER,
+	WL1271_FLAG_TX_QUEUE_STOPPED,
+	WL1271_FLAG_TX_PENDING,
+	WL1271_FLAG_IN_ELP,
+	WL1271_FLAG_PSM,
+	WL1271_FLAG_PSM_REQUESTED,
+	WL1271_FLAG_IRQ_RUNNING,
+	WL1271_FLAG_IDLE,
+	WL1271_FLAG_IDLE_REQUESTED,
+	WL1271_FLAG_PSPOLL_FAILURE,
+	WL1271_FLAG_STA_STATE_SENT,
+	WL1271_FLAG_FW_TX_BUSY,
+	WL1271_FLAG_AP_STARTED
+};
+
+struct wl1271_link {
+	/* AP-mode - TX queue per AC in link */
+	struct sk_buff_head tx_queue[NUM_TX_QUEUES];
+
+	/* accounting for allocated / available TX blocks in FW */
+	u8 allocated_blks;
+	u8 prev_freed_blks;
+
+	u8 addr[ETH_ALEN];
+};
+
 struct wl1271 {
 	struct platform_device *plat_dev;
 	struct ieee80211_hw *hw;
@@ -236,21 +359,6 @@ struct wl1271 {
 	enum wl1271_state state;
 	struct mutex mutex;
 
-#define WL1271_FLAG_STA_RATES_CHANGED  (0)
-#define WL1271_FLAG_STA_ASSOCIATED     (1)
-#define WL1271_FLAG_JOINED             (2)
-#define WL1271_FLAG_GPIO_POWER         (3)
-#define WL1271_FLAG_TX_QUEUE_STOPPED   (4)
-#define WL1271_FLAG_IN_ELP             (5)
-#define WL1271_FLAG_PSM                (6)
-#define WL1271_FLAG_PSM_REQUESTED      (7)
-#define WL1271_FLAG_IRQ_PENDING        (8)
-#define WL1271_FLAG_IRQ_RUNNING        (9)
-#define WL1271_FLAG_IDLE              (10)
-#define WL1271_FLAG_IDLE_REQUESTED    (11)
-#define WL1271_FLAG_PSPOLL_FAILURE    (12)
-#define WL1271_FLAG_STA_STATE_SENT    (13)
-#define WL1271_FLAG_FW_TX_BUSY        (14)
 	unsigned long flags;
 
 	struct wl1271_partition_set part;
@@ -262,6 +370,7 @@ struct wl1271 {
 
 	u8 *fw;
 	size_t fw_len;
+	u8 fw_bss_type;
 	struct wl1271_nvs_file *nvs;
 	size_t nvs_len;
 
@@ -295,6 +404,12 @@ struct wl1271 {
 	struct sk_buff_head tx_queue[NUM_TX_QUEUES];
 	int tx_queue_count;
 
+	/* Frames received, not handled yet by mac80211 */
+	struct sk_buff_head deferred_rx_queue;
+
+	/* Frames sent, not returned yet to mac80211 */
+	struct sk_buff_head deferred_tx_queue;
+
 	struct work_struct tx_work;
 
 	/* Pending TX frames */
@@ -315,8 +430,8 @@ struct wl1271 {
 	/* Intermediate buffer, used for packet aggregation */
 	u8 *aggr_buf;
 
-	/* The target interrupt mask */
-	struct work_struct irq_work;
+	/* Network stack work  */
+	struct work_struct netstack_work;
 
 	/* Hardware recovery work */
 	struct work_struct recovery_work;
@@ -343,7 +458,6 @@ struct wl1271 {
 	 *	bits 16-23 - 802.11n   MCS index mask
 	 * support only 1 stream, thus only 8 bits for the MCS rates (0-7).
 	 */
-	u32 sta_rate_set;
 	u32 basic_rate_set;
 	u32 basic_rate;
 	u32 rate_set;
@@ -378,13 +492,12 @@ struct wl1271 {
 	int last_rssi_event;
 
 	struct wl1271_stats stats;
-	struct dentry *rootdir;
 
 	__le32 buffer_32;
 	u32 buffer_cmd;
 	u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
 
-	struct wl1271_fw_status *fw_status;
+	struct wl1271_fw_full_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
 
 	struct ieee80211_vif *vif;
@@ -400,6 +513,41 @@ struct wl1271 {
 
 	/* Most recently reported noise in dBm */
 	s8 noise;
+
+	/* map for HLIDs of associated stations - when operating in AP mode */
+	unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)];
+
+	/* recoreded keys for AP-mode - set here before AP startup */
+	struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS];
+
+	/* bands supported by this instance of wl12xx */
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+	/* RX BA constraint value */
+	bool ba_support;
+	u8 ba_rx_bitmap;
+
+	/*
+	 * AP-mode - links indexed by HLID. The global and broadcast links
+	 * are always active.
+	 */
+	struct wl1271_link links[AP_MAX_LINKS];
+
+	/* the hlid of the link where the last transmitted skb came from */
+	int last_tx_hlid;
+
+	/* AP-mode - a bitmap of links currently in PS mode according to FW */
+	u32 ap_fw_ps_map;
+
+	/* AP-mode - a bitmap of links currently in PS mode in mac80211 */
+	unsigned long ap_ps_map;
+
+	/* Quirks of specific hardware revisions */
+	unsigned int quirks;
+};
+
+struct wl1271_station {
+	u8 hlid;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
@@ -414,6 +562,8 @@ int wl1271_plt_stop(struct wl1271 *wl);
 #define WL1271_TX_QUEUE_LOW_WATERMARK  10
 #define WL1271_TX_QUEUE_HIGH_WATERMARK 25
 
+#define WL1271_DEFERRED_QUEUE_LIMIT    64
+
 /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
    on in case is has been shut down shortly before */
 #define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */
@@ -423,4 +573,9 @@ int wl1271_plt_stop(struct wl1271 *wl);
 #define HW_BG_RATES_MASK	0xffff
 #define HW_HT_RATES_OFFSET	16
 
+/* Quirks */
+
+/* Each RX/TX transaction requires an end-of-transaction transfer */
+#define WL12XX_QUIRK_END_OF_TRANSACTION	BIT(0)
+
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index be21032..18fe542 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -55,7 +55,6 @@
 
 /* This really should be 8, but not for our firmware */
 #define MAX_SUPPORTED_RATES 32
-#define COUNTRY_STRING_LEN 3
 #define MAX_COUNTRY_TRIPLETS 32
 
 /* Headers */
@@ -99,7 +98,7 @@ struct country_triplet {
 
 struct wl12xx_ie_country {
 	struct wl12xx_ie_header header;
-	u8 country_string[COUNTRY_STRING_LEN];
+	u8 country_string[IEEE80211_COUNTRY_STRING_LEN];
 	struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
 } __packed;
 
@@ -138,13 +137,13 @@ struct wl12xx_arp_rsp_template {
 	struct ieee80211_hdr_3addr hdr;
 
 	u8 llc_hdr[sizeof(rfc1042_header)];
-	u16 llc_type;
+	__be16 llc_type;
 
 	struct arphdr arp_hdr;
 	u8 sender_hw[ETH_ALEN];
-	u32 sender_ip;
+	__be32 sender_ip;
 	u8 target_hw[ETH_ALEN];
-	u32 target_ip;
+	__be32 target_ip;
 } __packed;
 
 
@@ -160,4 +159,9 @@ struct wl12xx_probe_resp_template {
 	struct wl12xx_ie_country country;
 } __packed;
 
+struct wl12xx_disconn_template {
+	struct ieee80211_header header;
+	__le16 disconn_reason;
+} __packed;
+
 #endif
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 1907eaf..5728a91 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -5,7 +5,5 @@ zd1211rw-objs := zd_chip.o zd_mac.o \
 		zd_rf_al7230b.o zd_rf_uw2453.o \
 		zd_rf.o zd_usb.o
 
-ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_ZD1211RW_DEBUG) := -DDEBUG
 
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 6a9b660..a73a305 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -108,25 +108,17 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
 {
 	int r;
 	int i;
-	zd_addr_t *a16;
-	u16 *v16;
+	zd_addr_t a16[USB_MAX_IOREAD32_COUNT * 2];
+	u16 v16[USB_MAX_IOREAD32_COUNT * 2];
 	unsigned int count16;
 
 	if (count > USB_MAX_IOREAD32_COUNT)
 		return -EINVAL;
 
-	/* Allocate a single memory block for values and addresses. */
-	count16 = 2*count;
-	/* zd_addr_t is __nocast, so the kmalloc needs an explicit cast */
-	a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
-		                   GFP_KERNEL);
-	if (!a16) {
-		dev_dbg_f(zd_chip_dev(chip),
-			  "error ENOMEM in allocation of a16\n");
-		r = -ENOMEM;
-		goto out;
-	}
-	v16 = (u16 *)(a16 + count16);
+	/* Use stack for values and addresses. */
+	count16 = 2 * count;
+	BUG_ON(count16 * sizeof(zd_addr_t) > sizeof(a16));
+	BUG_ON(count16 * sizeof(u16) > sizeof(v16));
 
 	for (i = 0; i < count; i++) {
 		int j = 2*i;
@@ -139,7 +131,7 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
 	if (r) {
 		dev_dbg_f(zd_chip_dev(chip),
 			  "error: zd_ioread16v_locked. Error number %d\n", r);
-		goto out;
+		return r;
 	}
 
 	for (i = 0; i < count; i++) {
@@ -147,18 +139,19 @@ int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr
 		values[i] = (v16[j] << 16) | v16[j+1];
 	}
 
-out:
-	kfree((void *)a16);
-	return r;
+	return 0;
 }
 
-int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
-	           unsigned int count)
+static int _zd_iowrite32v_async_locked(struct zd_chip *chip,
+				       const struct zd_ioreq32 *ioreqs,
+				       unsigned int count)
 {
 	int i, j, r;
-	struct zd_ioreq16 *ioreqs16;
+	struct zd_ioreq16 ioreqs16[USB_MAX_IOWRITE32_COUNT * 2];
 	unsigned int count16;
 
+	/* Use stack for values and addresses. */
+
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
 
 	if (count == 0)
@@ -166,15 +159,8 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
 	if (count > USB_MAX_IOWRITE32_COUNT)
 		return -EINVAL;
 
-	/* Allocate a single memory block for values and addresses. */
-	count16 = 2*count;
-	ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_KERNEL);
-	if (!ioreqs16) {
-		r = -ENOMEM;
-		dev_dbg_f(zd_chip_dev(chip),
-			  "error %d in ioreqs16 allocation\n", r);
-		goto out;
-	}
+	count16 = 2 * count;
+	BUG_ON(count16 * sizeof(struct zd_ioreq16) > sizeof(ioreqs16));
 
 	for (i = 0; i < count; i++) {
 		j = 2*i;
@@ -185,18 +171,30 @@ int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
 		ioreqs16[j+1].addr  = ioreqs[i].addr;
 	}
 
-	r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16);
+	r = zd_usb_iowrite16v_async(&chip->usb, ioreqs16, count16);
 #ifdef DEBUG
 	if (r) {
 		dev_dbg_f(zd_chip_dev(chip),
 			  "error %d in zd_usb_write16v\n", r);
 	}
 #endif /* DEBUG */
-out:
-	kfree(ioreqs16);
 	return r;
 }
 
+int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+			  unsigned int count)
+{
+	int r;
+
+	zd_usb_iowrite16v_async_start(&chip->usb);
+	r = _zd_iowrite32v_async_locked(chip, ioreqs, count);
+	if (r) {
+		zd_usb_iowrite16v_async_end(&chip->usb, 0);
+		return r;
+	}
+	return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
+}
+
 int zd_iowrite16a_locked(struct zd_chip *chip,
                   const struct zd_ioreq16 *ioreqs, unsigned int count)
 {
@@ -204,6 +202,8 @@ int zd_iowrite16a_locked(struct zd_chip *chip,
 	unsigned int i, j, t, max;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+	zd_usb_iowrite16v_async_start(&chip->usb);
+
 	for (i = 0; i < count; i += j + t) {
 		t = 0;
 		max = count-i;
@@ -216,8 +216,9 @@ int zd_iowrite16a_locked(struct zd_chip *chip,
 			}
 		}
 
-		r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j);
+		r = zd_usb_iowrite16v_async(&chip->usb, &ioreqs[i], j);
 		if (r) {
+			zd_usb_iowrite16v_async_end(&chip->usb, 0);
 			dev_dbg_f(zd_chip_dev(chip),
 				  "error zd_usb_iowrite16v. Error number %d\n",
 				  r);
@@ -225,7 +226,7 @@ int zd_iowrite16a_locked(struct zd_chip *chip,
 		}
 	}
 
-	return 0;
+	return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
 }
 
 /* Writes a variable number of 32 bit registers. The functions will split
@@ -238,6 +239,8 @@ int zd_iowrite32a_locked(struct zd_chip *chip,
 	int r;
 	unsigned int i, j, t, max;
 
+	zd_usb_iowrite16v_async_start(&chip->usb);
+
 	for (i = 0; i < count; i += j + t) {
 		t = 0;
 		max = count-i;
@@ -250,8 +253,9 @@ int zd_iowrite32a_locked(struct zd_chip *chip,
 			}
 		}
 
-		r = _zd_iowrite32v_locked(chip, &ioreqs[i], j);
+		r = _zd_iowrite32v_async_locked(chip, &ioreqs[i], j);
 		if (r) {
+			zd_usb_iowrite16v_async_end(&chip->usb, 0);
 			dev_dbg_f(zd_chip_dev(chip),
 				"error _zd_iowrite32v_locked."
 				" Error number %d\n", r);
@@ -259,7 +263,7 @@ int zd_iowrite32a_locked(struct zd_chip *chip,
 		}
 	}
 
-	return 0;
+	return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
 }
 
 int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
@@ -370,16 +374,12 @@ error:
 	return r;
 }
 
-/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
- *              CR_MAC_ADDR_P2 must be overwritten
- */
-int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr,
+				    const struct zd_ioreq32 *in_reqs,
+				    const char *type)
 {
 	int r;
-	struct zd_ioreq32 reqs[2] = {
-		[0] = { .addr = CR_MAC_ADDR_P1 },
-		[1] = { .addr = CR_MAC_ADDR_P2 },
-	};
+	struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]};
 
 	if (mac_addr) {
 		reqs[0].value = (mac_addr[3] << 24)
@@ -388,9 +388,9 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
 			      |  mac_addr[0];
 		reqs[1].value = (mac_addr[5] <<  8)
 			      |  mac_addr[4];
-		dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr);
+		dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr);
 	} else {
-		dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
+		dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type);
 	}
 
 	mutex_lock(&chip->mutex);
@@ -399,6 +399,29 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
 	return r;
 }
 
+/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
+ *              CR_MAC_ADDR_P2 must be overwritten
+ */
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+{
+	static const struct zd_ioreq32 reqs[2] = {
+		[0] = { .addr = CR_MAC_ADDR_P1 },
+		[1] = { .addr = CR_MAC_ADDR_P2 },
+	};
+
+	return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac");
+}
+
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+	static const struct zd_ioreq32 reqs[2] = {
+		[0] = { .addr = CR_BSSID_P1 },
+		[1] = { .addr = CR_BSSID_P2 },
+	};
+
+	return zd_write_mac_addr_common(chip, bssid, reqs, "bssid");
+}
+
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
 {
 	int r;
@@ -849,11 +872,12 @@ static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
 static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
 {
 	struct zd_ioreq32 reqs[3];
+	u16 b_interval = s->beacon_interval & 0xffff;
 
-	if (s->beacon_interval <= 5)
-		s->beacon_interval = 5;
-	if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval)
-		s->pre_tbtt = s->beacon_interval - 1;
+	if (b_interval <= 5)
+		b_interval = 5;
+	if (s->pre_tbtt < 4 || s->pre_tbtt >= b_interval)
+		s->pre_tbtt = b_interval - 1;
 	if (s->atim_wnd_period >= s->pre_tbtt)
 		s->atim_wnd_period = s->pre_tbtt - 1;
 
@@ -862,31 +886,57 @@ static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
 	reqs[1].addr = CR_PRE_TBTT;
 	reqs[1].value = s->pre_tbtt;
 	reqs[2].addr = CR_BCN_INTERVAL;
-	reqs[2].value = s->beacon_interval;
+	reqs[2].value = (s->beacon_interval & ~0xffff) | b_interval;
 
 	return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
 }
 
 
-static int set_beacon_interval(struct zd_chip *chip, u32 interval)
+static int set_beacon_interval(struct zd_chip *chip, u16 interval,
+			       u8 dtim_period, int type)
 {
 	int r;
 	struct aw_pt_bi s;
+	u32 b_interval, mode_flag;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+
+	if (interval > 0) {
+		switch (type) {
+		case NL80211_IFTYPE_ADHOC:
+		case NL80211_IFTYPE_MESH_POINT:
+			mode_flag = BCN_MODE_IBSS;
+			break;
+		case NL80211_IFTYPE_AP:
+			mode_flag = BCN_MODE_AP;
+			break;
+		default:
+			mode_flag = 0;
+			break;
+		}
+	} else {
+		dtim_period = 0;
+		mode_flag = 0;
+	}
+
+	b_interval = mode_flag | (dtim_period << 16) | interval;
+
+	r = zd_iowrite32_locked(chip, b_interval, CR_BCN_INTERVAL);
+	if (r)
+		return r;
 	r = get_aw_pt_bi(chip, &s);
 	if (r)
 		return r;
-	s.beacon_interval = interval;
 	return set_aw_pt_bi(chip, &s);
 }
 
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval)
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+			   int type)
 {
 	int r;
 
 	mutex_lock(&chip->mutex);
-	r = set_beacon_interval(chip, interval);
+	r = set_beacon_interval(chip, interval, dtim_period, type);
 	mutex_unlock(&chip->mutex);
 	return r;
 }
@@ -905,7 +955,7 @@ static int hw_init(struct zd_chip *chip)
 	if (r)
 		return r;
 
-	return set_beacon_interval(chip, 100);
+	return set_beacon_interval(chip, 100, 0, NL80211_IFTYPE_UNSPECIFIED);
 }
 
 static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
@@ -1407,6 +1457,9 @@ void zd_chip_disable_int(struct zd_chip *chip)
 	mutex_lock(&chip->mutex);
 	zd_usb_disable_int(&chip->usb);
 	mutex_unlock(&chip->mutex);
+
+	/* cancel pending interrupt work */
+	cancel_work_sync(&zd_chip_to_mac(chip)->process_intr);
 }
 
 int zd_chip_enable_rxtx(struct zd_chip *chip)
@@ -1416,6 +1469,7 @@ int zd_chip_enable_rxtx(struct zd_chip *chip)
 	mutex_lock(&chip->mutex);
 	zd_usb_enable_tx(&chip->usb);
 	r = zd_usb_enable_rx(&chip->usb);
+	zd_tx_watchdog_enable(&chip->usb);
 	mutex_unlock(&chip->mutex);
 	return r;
 }
@@ -1423,6 +1477,7 @@ int zd_chip_enable_rxtx(struct zd_chip *chip)
 void zd_chip_disable_rxtx(struct zd_chip *chip)
 {
 	mutex_lock(&chip->mutex);
+	zd_tx_watchdog_disable(&chip->usb);
 	zd_usb_disable_rx(&chip->usb);
 	zd_usb_disable_tx(&chip->usb);
 	mutex_unlock(&chip->mutex);
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index f8bbf7d..14e4402 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -546,6 +546,7 @@ enum {
 #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
 	RX_FILTER_CFEND | RX_FILTER_CFACK)
 
+#define BCN_MODE_AP			0x1000000
 #define BCN_MODE_IBSS			0x2000000
 
 /* Monitor mode sets filter to 0xfffff */
@@ -881,6 +882,7 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
 u8  zd_chip_get_channel(struct zd_chip *chip);
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid);
 int zd_chip_switch_radio_on(struct zd_chip *chip);
 int zd_chip_switch_radio_off(struct zd_chip *chip);
 int zd_chip_enable_int(struct zd_chip *chip);
@@ -920,7 +922,8 @@ enum led_status {
 
 int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
 
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+			   int type);
 
 static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
 {
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 6ac597f..5463ca9 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -45,7 +45,7 @@ typedef u16 __nocast zd_addr_t;
 #ifdef DEBUG
 #  define ZD_ASSERT(x) \
 do { \
-	if (!(x)) { \
+	if (unlikely(!(x))) { \
 		pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
 			__FILE__, __LINE__, __stringify(x)); \
 		dump_stack(); \
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 6107304..5037c8b 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -138,6 +138,12 @@ static const struct ieee80211_channel zd_channels[] = {
 static void housekeeping_init(struct zd_mac *mac);
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
+static void beacon_init(struct zd_mac *mac);
+static void beacon_enable(struct zd_mac *mac);
+static void beacon_disable(struct zd_mac *mac);
+static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
+static int zd_mac_config_beacon(struct ieee80211_hw *hw,
+				struct sk_buff *beacon);
 
 static int zd_reg2alpha2(u8 regdomain, char *alpha2)
 {
@@ -231,6 +237,26 @@ static int set_rx_filter(struct zd_mac *mac)
 	return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
 }
 
+static int set_mac_and_bssid(struct zd_mac *mac)
+{
+	int r;
+
+	if (!mac->vif)
+		return -1;
+
+	r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
+	if (r)
+		return r;
+
+	/* Vendor driver after setting MAC either sets BSSID for AP or
+	 * filter for other modes.
+	 */
+	if (mac->type != NL80211_IFTYPE_AP)
+		return set_rx_filter(mac);
+	else
+		return zd_write_bssid(&mac->chip, mac->vif->addr);
+}
+
 static int set_mc_hash(struct zd_mac *mac)
 {
 	struct zd_mc_hash hash;
@@ -238,7 +264,7 @@ static int set_mc_hash(struct zd_mac *mac)
 	return zd_chip_set_multicast_hash(&mac->chip, &hash);
 }
 
-static int zd_op_start(struct ieee80211_hw *hw)
+int zd_op_start(struct ieee80211_hw *hw)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct zd_chip *chip = &mac->chip;
@@ -275,6 +301,8 @@ static int zd_op_start(struct ieee80211_hw *hw)
 		goto disable_rxtx;
 
 	housekeeping_enable(mac);
+	beacon_enable(mac);
+	set_bit(ZD_DEVICE_RUNNING, &mac->flags);
 	return 0;
 disable_rxtx:
 	zd_chip_disable_rxtx(chip);
@@ -286,19 +314,22 @@ out:
 	return r;
 }
 
-static void zd_op_stop(struct ieee80211_hw *hw)
+void zd_op_stop(struct ieee80211_hw *hw)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct zd_chip *chip = &mac->chip;
 	struct sk_buff *skb;
 	struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
 
+	clear_bit(ZD_DEVICE_RUNNING, &mac->flags);
+
 	/* The order here deliberately is a little different from the open()
 	 * method, since we need to make sure there is no opportunity for RX
 	 * frames to be processed by mac80211 after we have stopped it.
 	 */
 
 	zd_chip_disable_rxtx(chip);
+	beacon_disable(mac);
 	housekeeping_disable(mac);
 	flush_workqueue(zd_workqueue);
 
@@ -311,6 +342,68 @@ static void zd_op_stop(struct ieee80211_hw *hw)
 		dev_kfree_skb_any(skb);
 }
 
+int zd_restore_settings(struct zd_mac *mac)
+{
+	struct sk_buff *beacon;
+	struct zd_mc_hash multicast_hash;
+	unsigned int short_preamble;
+	int r, beacon_interval, beacon_period;
+	u8 channel;
+
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+
+	spin_lock_irq(&mac->lock);
+	multicast_hash = mac->multicast_hash;
+	short_preamble = mac->short_preamble;
+	beacon_interval = mac->beacon.interval;
+	beacon_period = mac->beacon.period;
+	channel = mac->channel;
+	spin_unlock_irq(&mac->lock);
+
+	r = set_mac_and_bssid(mac);
+	if (r < 0) {
+		dev_dbg_f(zd_mac_dev(mac), "set_mac_and_bssid failed, %d\n", r);
+		return r;
+	}
+
+	r = zd_chip_set_channel(&mac->chip, channel);
+	if (r < 0) {
+		dev_dbg_f(zd_mac_dev(mac), "zd_chip_set_channel failed, %d\n",
+			  r);
+		return r;
+	}
+
+	set_rts_cts(mac, short_preamble);
+
+	r = zd_chip_set_multicast_hash(&mac->chip, &multicast_hash);
+	if (r < 0) {
+		dev_dbg_f(zd_mac_dev(mac),
+			  "zd_chip_set_multicast_hash failed, %d\n", r);
+		return r;
+	}
+
+	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
+	    mac->type == NL80211_IFTYPE_ADHOC ||
+	    mac->type == NL80211_IFTYPE_AP) {
+		if (mac->vif != NULL) {
+			beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+			if (beacon) {
+				zd_mac_config_beacon(mac->hw, beacon);
+				kfree_skb(beacon);
+			}
+		}
+
+		zd_set_beacon_interval(&mac->chip, beacon_interval,
+					beacon_period, mac->type);
+
+		spin_lock_irq(&mac->lock);
+		mac->beacon.last_update = jiffies;
+		spin_unlock_irq(&mac->lock);
+	}
+
+	return 0;
+}
+
 /**
  * zd_mac_tx_status - reports tx status of a packet if required
  * @hw - a &struct ieee80211_hw pointer
@@ -574,64 +667,120 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
 static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
-	int r;
+	int r, ret, num_cmds, req_pos = 0;
 	u32 tmp, j = 0;
 	/* 4 more bytes for tail CRC */
 	u32 full_len = beacon->len + 4;
+	unsigned long end_jiffies, message_jiffies;
+	struct zd_ioreq32 *ioreqs;
 
-	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
+	/* Alloc memory for full beacon write at once. */
+	num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
+	ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
+	if (!ioreqs)
+		return -ENOMEM;
+
+	mutex_lock(&mac->chip.mutex);
+
+	r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
 	if (r < 0)
-		return r;
-	r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+		goto out;
+	r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
 	if (r < 0)
-		return r;
+		goto release_sema;
 
+	end_jiffies = jiffies + HZ / 2; /*~500ms*/
+	message_jiffies = jiffies + HZ / 10; /*~100ms*/
 	while (tmp & 0x2) {
-		r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+		r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
 		if (r < 0)
-			return r;
-		if ((++j % 100) == 0) {
-			printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
-			if (j >= 500)  {
-				printk(KERN_ERR "Giving up beacon config.\n");
-				return -ETIMEDOUT;
+			goto release_sema;
+		if (time_is_before_eq_jiffies(message_jiffies)) {
+			message_jiffies = jiffies + HZ / 10;
+			dev_err(zd_mac_dev(mac),
+					"CR_BCN_FIFO_SEMAPHORE not ready\n");
+			if (time_is_before_eq_jiffies(end_jiffies))  {
+				dev_err(zd_mac_dev(mac),
+						"Giving up beacon config.\n");
+				r = -ETIMEDOUT;
+				goto reset_device;
 			}
 		}
-		msleep(1);
+		msleep(20);
 	}
 
-	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
-	if (r < 0)
-		return r;
+	ioreqs[req_pos].addr = CR_BCN_FIFO;
+	ioreqs[req_pos].value = full_len - 1;
+	req_pos++;
 	if (zd_chip_is_zd1211b(&mac->chip)) {
-		r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
-		if (r < 0)
-			return r;
+		ioreqs[req_pos].addr = CR_BCN_LENGTH;
+		ioreqs[req_pos].value = full_len - 1;
+		req_pos++;
 	}
 
 	for (j = 0 ; j < beacon->len; j++) {
-		r = zd_iowrite32(&mac->chip, CR_BCN_FIFO,
-				*((u8 *)(beacon->data + j)));
-		if (r < 0)
-			return r;
+		ioreqs[req_pos].addr = CR_BCN_FIFO;
+		ioreqs[req_pos].value = *((u8 *)(beacon->data + j));
+		req_pos++;
 	}
 
 	for (j = 0; j < 4; j++) {
-		r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
-		if (r < 0)
-			return r;
+		ioreqs[req_pos].addr = CR_BCN_FIFO;
+		ioreqs[req_pos].value = 0x0;
+		req_pos++;
 	}
 
-	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
-	if (r < 0)
-		return r;
+	BUG_ON(req_pos != num_cmds);
+
+	r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);
+
+release_sema:
+	/*
+	 * Try very hard to release device beacon semaphore, as otherwise
+	 * device/driver can be left in unusable state.
+	 */
+	end_jiffies = jiffies + HZ / 2; /*~500ms*/
+	ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
+	while (ret < 0) {
+		if (time_is_before_eq_jiffies(end_jiffies)) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+
+		msleep(20);
+		ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
+	}
+
+	if (ret < 0)
+		dev_err(zd_mac_dev(mac), "Could not release "
+					 "CR_BCN_FIFO_SEMAPHORE!\n");
+	if (r < 0 || ret < 0) {
+		if (r >= 0)
+			r = ret;
+		goto out;
+	}
 
 	/* 802.11b/g 2.4G CCK 1Mb
 	 * 802.11a, not yet implemented, uses different values (see GPL vendor
 	 * driver)
 	 */
-	return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
-			(full_len << 19));
+	r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
+				CR_BCN_PLCP_CFG);
+out:
+	mutex_unlock(&mac->chip.mutex);
+	kfree(ioreqs);
+	return r;
+
+reset_device:
+	mutex_unlock(&mac->chip.mutex);
+	kfree(ioreqs);
+
+	/* semaphore stuck, reset device to avoid fw freeze later */
+	dev_warn(zd_mac_dev(mac), "CR_BCN_FIFO_SEMAPHORE stuck, "
+				  "reseting device...");
+	usb_queue_reset_device(mac->chip.usb.intf);
+
+	return r;
 }
 
 static int fill_ctrlset(struct zd_mac *mac,
@@ -701,7 +850,7 @@ static int fill_ctrlset(struct zd_mac *mac,
  * control block of the skbuff will be initialized. If necessary the incoming
  * mac80211 queues will be stopped.
  */
-static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -716,11 +865,10 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	r = zd_usb_tx(&mac->chip.usb, skb);
 	if (r)
 		goto fail;
-	return 0;
+	return;
 
 fail:
 	dev_kfree_skb(skb);
-	return 0;
 }
 
 /**
@@ -779,6 +927,13 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
 
 		mac->ack_pending = 1;
 		mac->ack_signal = stats->signal;
+
+		/* Prevent pending tx-packet on AP-mode */
+		if (mac->type == NL80211_IFTYPE_AP) {
+			skb = __skb_dequeue(q);
+			zd_mac_tx_status(hw, skb, mac->ack_signal, NULL);
+			mac->ack_pending = 0;
+		}
 	}
 
 	spin_unlock_irqrestore(&q->lock, flags);
@@ -882,13 +1037,16 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
 	case NL80211_IFTYPE_MESH_POINT:
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP:
 		mac->type = vif->type;
 		break;
 	default:
 		return -EOPNOTSUPP;
 	}
 
-	return zd_write_mac_addr(&mac->chip, vif->addr);
+	mac->vif = vif;
+
+	return set_mac_and_bssid(mac);
 }
 
 static void zd_op_remove_interface(struct ieee80211_hw *hw,
@@ -896,7 +1054,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	mac->type = NL80211_IFTYPE_UNSPECIFIED;
-	zd_set_beacon_interval(&mac->chip, 0);
+	mac->vif = NULL;
+	zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
 	zd_write_mac_addr(&mac->chip, NULL);
 }
 
@@ -905,49 +1064,67 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct ieee80211_conf *conf = &hw->conf;
 
+	spin_lock_irq(&mac->lock);
+	mac->channel = conf->channel->hw_value;
+	spin_unlock_irq(&mac->lock);
+
 	return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
 }
 
-static void zd_process_intr(struct work_struct *work)
+static void zd_beacon_done(struct zd_mac *mac)
 {
-	u16 int_status;
-	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
+	struct sk_buff *skb, *beacon;
 
-	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
-	if (int_status & INT_CFG_NEXT_BCN)
-		dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
-	else
-		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
-
-	zd_chip_enable_hwint(&mac->chip);
-}
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		return;
+	if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP)
+		return;
 
+	/*
+	 * Send out buffered broad- and multicast frames.
+	 */
+	while (!ieee80211_queue_stopped(mac->hw, 0)) {
+		skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+		if (!skb)
+			break;
+		zd_op_tx(mac->hw, skb);
+	}
 
-static void set_multicast_hash_handler(struct work_struct *work)
-{
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_multicast_hash_work);
-	struct zd_mc_hash hash;
+	/*
+	 * Fetch next beacon so that tim_count is updated.
+	 */
+	beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+	if (beacon) {
+		zd_mac_config_beacon(mac->hw, beacon);
+		kfree_skb(beacon);
+	}
 
 	spin_lock_irq(&mac->lock);
-	hash = mac->multicast_hash;
+	mac->beacon.last_update = jiffies;
 	spin_unlock_irq(&mac->lock);
-
-	zd_chip_set_multicast_hash(&mac->chip, &hash);
 }
 
-static void set_rx_filter_handler(struct work_struct *work)
+static void zd_process_intr(struct work_struct *work)
 {
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_rx_filter_work);
-	int r;
+	u16 int_status;
+	unsigned long flags;
+	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
 
-	dev_dbg_f(zd_mac_dev(mac), "\n");
-	r = set_rx_filter(mac);
-	if (r)
-		dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
+	spin_lock_irqsave(&mac->lock, flags);
+	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4));
+	spin_unlock_irqrestore(&mac->lock, flags);
+
+	if (int_status & INT_CFG_NEXT_BCN) {
+		/*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/
+		zd_beacon_done(mac);
+	} else {
+		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
+	}
+
+	zd_chip_enable_hwint(&mac->chip);
 }
 
+
 static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
 				   struct netdev_hw_addr_list *mc_list)
 {
@@ -979,6 +1156,7 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
 	};
 	struct zd_mac *mac = zd_hw_mac(hw);
 	unsigned long flags;
+	int r;
 
 	/* Only deal with supported flags */
 	changed_flags &= SUPPORTED_FIF_FLAGS;
@@ -1000,11 +1178,13 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
 	mac->multicast_hash = hash;
 	spin_unlock_irqrestore(&mac->lock, flags);
 
-	/* XXX: these can be called here now, can sleep now! */
-	queue_work(zd_workqueue, &mac->set_multicast_hash_work);
+	zd_chip_set_multicast_hash(&mac->chip, &hash);
 
-	if (changed_flags & FIF_CONTROL)
-		queue_work(zd_workqueue, &mac->set_rx_filter_work);
+	if (changed_flags & FIF_CONTROL) {
+		r = set_rx_filter(mac);
+		if (r)
+			dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r);
+	}
 
 	/* no handling required for FIF_OTHER_BSS as we don't currently
 	 * do BSSID filtering */
@@ -1016,20 +1196,9 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
 	 * time. */
 }
 
-static void set_rts_cts_work(struct work_struct *work)
+static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble)
 {
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_rts_cts_work);
-	unsigned long flags;
-	unsigned int short_preamble;
-
 	mutex_lock(&mac->chip.mutex);
-
-	spin_lock_irqsave(&mac->lock, flags);
-	mac->updating_rts_rate = 0;
-	short_preamble = mac->short_preamble;
-	spin_unlock_irqrestore(&mac->lock, flags);
-
 	zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
 	mutex_unlock(&mac->chip.mutex);
 }
@@ -1040,33 +1209,42 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
 				   u32 changes)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
-	unsigned long flags;
 	int associated;
 
 	dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
 
 	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
-	    mac->type == NL80211_IFTYPE_ADHOC) {
+	    mac->type == NL80211_IFTYPE_ADHOC ||
+	    mac->type == NL80211_IFTYPE_AP) {
 		associated = true;
 		if (changes & BSS_CHANGED_BEACON) {
 			struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
 
 			if (beacon) {
+				zd_chip_disable_hwint(&mac->chip);
 				zd_mac_config_beacon(hw, beacon);
+				zd_chip_enable_hwint(&mac->chip);
 				kfree_skb(beacon);
 			}
 		}
 
 		if (changes & BSS_CHANGED_BEACON_ENABLED) {
-			u32 interval;
+			u16 interval = 0;
+			u8 period = 0;
 
-			if (bss_conf->enable_beacon)
-				interval = BCN_MODE_IBSS |
-						bss_conf->beacon_int;
-			else
-				interval = 0;
+			if (bss_conf->enable_beacon) {
+				period = bss_conf->dtim_period;
+				interval = bss_conf->beacon_int;
+			}
 
-			zd_set_beacon_interval(&mac->chip, interval);
+			spin_lock_irq(&mac->lock);
+			mac->beacon.period = period;
+			mac->beacon.interval = interval;
+			mac->beacon.last_update = jiffies;
+			spin_unlock_irq(&mac->lock);
+
+			zd_set_beacon_interval(&mac->chip, interval, period,
+					       mac->type);
 		}
 	} else
 		associated = is_valid_ether_addr(bss_conf->bssid);
@@ -1078,15 +1256,11 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
 	/* TODO: do hardware bssid filtering */
 
 	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		spin_lock_irqsave(&mac->lock, flags);
+		spin_lock_irq(&mac->lock);
 		mac->short_preamble = bss_conf->use_short_preamble;
-		if (!mac->updating_rts_rate) {
-			mac->updating_rts_rate = 1;
-			/* FIXME: should disable TX here, until work has
-			 * completed and RTS_CTS reg is updated */
-			queue_work(zd_workqueue, &mac->set_rts_cts_work);
-		}
-		spin_unlock_irqrestore(&mac->lock, flags);
+		spin_unlock_irq(&mac->lock);
+
+		set_rts_cts(mac, bss_conf->use_short_preamble);
 	}
 }
 
@@ -1138,12 +1312,14 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
 	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
 
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_SIGNAL_UNSPEC;
+		    IEEE80211_HW_SIGNAL_UNSPEC |
+		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_MESH_POINT) |
 		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
+		BIT(NL80211_IFTYPE_ADHOC) |
+		BIT(NL80211_IFTYPE_AP);
 
 	hw->max_signal = 100;
 	hw->queues = 1;
@@ -1160,15 +1336,82 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
 
 	zd_chip_init(&mac->chip, hw, intf);
 	housekeeping_init(mac);
-	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
-	INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
-	INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
+	beacon_init(mac);
 	INIT_WORK(&mac->process_intr, zd_process_intr);
 
 	SET_IEEE80211_DEV(hw, &intf->dev);
 	return hw;
 }
 
+#define BEACON_WATCHDOG_DELAY round_jiffies_relative(HZ)
+
+static void beacon_watchdog_handler(struct work_struct *work)
+{
+	struct zd_mac *mac =
+		container_of(work, struct zd_mac, beacon.watchdog_work.work);
+	struct sk_buff *beacon;
+	unsigned long timeout;
+	int interval, period;
+
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		goto rearm;
+	if (mac->type != NL80211_IFTYPE_AP || !mac->vif)
+		goto rearm;
+
+	spin_lock_irq(&mac->lock);
+	interval = mac->beacon.interval;
+	period = mac->beacon.period;
+	timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+	spin_unlock_irq(&mac->lock);
+
+	if (interval > 0 && time_is_before_jiffies(timeout)) {
+		dev_dbg_f(zd_mac_dev(mac), "beacon interrupt stalled, "
+					   "restarting. "
+					   "(interval: %d, dtim: %d)\n",
+					   interval, period);
+
+		zd_chip_disable_hwint(&mac->chip);
+
+		beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+		if (beacon) {
+			zd_mac_config_beacon(mac->hw, beacon);
+			kfree_skb(beacon);
+		}
+
+		zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
+
+		zd_chip_enable_hwint(&mac->chip);
+
+		spin_lock_irq(&mac->lock);
+		mac->beacon.last_update = jiffies;
+		spin_unlock_irq(&mac->lock);
+	}
+
+rearm:
+	queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
+			   BEACON_WATCHDOG_DELAY);
+}
+
+static void beacon_init(struct zd_mac *mac)
+{
+	INIT_DELAYED_WORK(&mac->beacon.watchdog_work, beacon_watchdog_handler);
+}
+
+static void beacon_enable(struct zd_mac *mac)
+{
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+
+	mac->beacon.last_update = jiffies;
+	queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
+			   BEACON_WATCHDOG_DELAY);
+}
+
+static void beacon_disable(struct zd_mac *mac)
+{
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+	cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+}
+
 #define LINK_LED_WORK_DELAY HZ
 
 static void link_led_handler(struct work_struct *work)
@@ -1179,6 +1422,9 @@ static void link_led_handler(struct work_struct *work)
 	int is_associated;
 	int r;
 
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		goto requeue;
+
 	spin_lock_irq(&mac->lock);
 	is_associated = mac->associated;
 	spin_unlock_irq(&mac->lock);
@@ -1188,6 +1434,7 @@ static void link_led_handler(struct work_struct *work)
 	if (r)
 		dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
 
+requeue:
 	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
 		           LINK_LED_WORK_DELAY);
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index a6d86b9..f8c93c3 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -163,6 +163,17 @@ struct housekeeping {
 	struct delayed_work link_led_work;
 };
 
+struct beacon {
+	struct delayed_work watchdog_work;
+	unsigned long last_update;
+	u16 interval;
+	u8 period;
+};
+
+enum zd_device_flags {
+	ZD_DEVICE_RUNNING,
+};
+
 #define ZD_MAC_STATS_BUFFER_SIZE 16
 
 #define ZD_MAC_MAX_ACK_WAITERS 50
@@ -172,17 +183,19 @@ struct zd_mac {
 	spinlock_t lock;
 	spinlock_t intr_lock;
 	struct ieee80211_hw *hw;
+	struct ieee80211_vif *vif;
 	struct housekeeping housekeeping;
-	struct work_struct set_multicast_hash_work;
+	struct beacon beacon;
 	struct work_struct set_rts_cts_work;
-	struct work_struct set_rx_filter_work;
 	struct work_struct process_intr;
 	struct zd_mc_hash multicast_hash;
 	u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
 	u8 regdomain;
 	u8 default_regdomain;
+	u8 channel;
 	int type;
 	int associated;
+	unsigned long flags;
 	struct sk_buff_head ack_wait_queue;
 	struct ieee80211_channel channels[14];
 	struct ieee80211_rate rates[12];
@@ -191,9 +204,6 @@ struct zd_mac {
 	/* Short preamble (used for RTS/CTS) */
 	unsigned int short_preamble:1;
 
-	/* flags to indicate update in progress */
-	unsigned int updating_rts_rate:1;
-
 	/* whether to pass frames with CRC errors to stack */
 	unsigned int pass_failed_fcs:1;
 
@@ -304,6 +314,10 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length);
 void zd_mac_tx_failed(struct urb *urb);
 void zd_mac_tx_to_dev(struct sk_buff *skb, int error);
 
+int zd_op_start(struct ieee80211_hw *hw);
+void zd_op_stop(struct ieee80211_hw *hw);
+int zd_restore_settings(struct zd_mac *mac);
+
 #ifdef DEBUG
 void zd_dump_rx_status(const struct rx_status *status);
 #else
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 06041cb..81e8048 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -377,8 +377,10 @@ static inline void handle_regs_int(struct urb *urb)
 	int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
 	if (int_num == CR_INTERRUPT) {
 		struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
+		spin_lock(&mac->lock);
 		memcpy(&mac->intr_buffer, urb->transfer_buffer,
 				USB_MAX_EP_INT_BUFFER);
+		spin_unlock(&mac->lock);
 		schedule_work(&mac->process_intr);
 	} else if (intr->read_regs_enabled) {
 		intr->read_regs.length = len = urb->actual_length;
@@ -409,8 +411,10 @@ static void int_urb_complete(struct urb *urb)
 	case -ENOENT:
 	case -ECONNRESET:
 	case -EPIPE:
-		goto kfree;
+		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+		return;
 	default:
+		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
 		goto resubmit;
 	}
 
@@ -441,12 +445,11 @@ static void int_urb_complete(struct urb *urb)
 resubmit:
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r) {
-		dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb);
-		goto kfree;
+		dev_dbg_f(urb_dev(urb), "error: resubmit urb %p err code %d\n",
+			  urb, r);
+		/* TODO: add worker to reset intr->urb */
 	}
 	return;
-kfree:
-	kfree(urb->transfer_buffer);
 }
 
 static inline int int_urb_interval(struct usb_device *udev)
@@ -477,9 +480,8 @@ static inline int usb_int_enabled(struct zd_usb *usb)
 int zd_usb_enable_int(struct zd_usb *usb)
 {
 	int r;
-	struct usb_device *udev;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct zd_usb_interrupt *intr = &usb->intr;
-	void *transfer_buffer = NULL;
 	struct urb *urb;
 
 	dev_dbg_f(zd_usb_dev(usb), "\n");
@@ -500,20 +502,21 @@ int zd_usb_enable_int(struct zd_usb *usb)
 	intr->urb = urb;
 	spin_unlock_irq(&intr->lock);
 
-	/* TODO: make it a DMA buffer */
 	r = -ENOMEM;
-	transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL);
-	if (!transfer_buffer) {
+	intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER,
+					  GFP_KERNEL, &intr->buffer_dma);
+	if (!intr->buffer) {
 		dev_dbg_f(zd_usb_dev(usb),
 			"couldn't allocate transfer_buffer\n");
 		goto error_set_urb_null;
 	}
 
-	udev = zd_usb_to_usbdev(usb);
 	usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN),
-			 transfer_buffer, USB_MAX_EP_INT_BUFFER,
+			 intr->buffer, USB_MAX_EP_INT_BUFFER,
 			 int_urb_complete, usb,
 			 intr->interval);
+	urb->transfer_dma = intr->buffer_dma;
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
 	r = usb_submit_urb(urb, GFP_KERNEL);
@@ -525,7 +528,8 @@ int zd_usb_enable_int(struct zd_usb *usb)
 
 	return 0;
 error:
-	kfree(transfer_buffer);
+	usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
+			  intr->buffer, intr->buffer_dma);
 error_set_urb_null:
 	spin_lock_irq(&intr->lock);
 	intr->urb = NULL;
@@ -539,8 +543,11 @@ out:
 void zd_usb_disable_int(struct zd_usb *usb)
 {
 	unsigned long flags;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct zd_usb_interrupt *intr = &usb->intr;
 	struct urb *urb;
+	void *buffer;
+	dma_addr_t buffer_dma;
 
 	spin_lock_irqsave(&intr->lock, flags);
 	urb = intr->urb;
@@ -549,11 +556,18 @@ void zd_usb_disable_int(struct zd_usb *usb)
 		return;
 	}
 	intr->urb = NULL;
+	buffer = intr->buffer;
+	buffer_dma = intr->buffer_dma;
+	intr->buffer = NULL;
 	spin_unlock_irqrestore(&intr->lock, flags);
 
 	usb_kill_urb(urb);
 	dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb);
 	usb_free_urb(urb);
+
+	if (buffer)
+		usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
+				  buffer, buffer_dma);
 }
 
 static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
@@ -601,6 +615,7 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
 static void rx_urb_complete(struct urb *urb)
 {
+	int r;
 	struct zd_usb *usb;
 	struct zd_usb_rx *rx;
 	const u8 *buffer;
@@ -615,6 +630,7 @@ static void rx_urb_complete(struct urb *urb)
 	case -ENOENT:
 	case -ECONNRESET:
 	case -EPIPE:
+		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
 		return;
 	default:
 		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
@@ -626,6 +642,8 @@ static void rx_urb_complete(struct urb *urb)
 	usb = urb->context;
 	rx = &usb->rx;
 
+	zd_usb_reset_rx_idle_timer(usb);
+
 	if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
 		/* If there is an old first fragment, we don't care. */
 		dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
@@ -654,7 +672,9 @@ static void rx_urb_complete(struct urb *urb)
 	}
 
 resubmit:
-	usb_submit_urb(urb, GFP_ATOMIC);
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		dev_dbg_f(urb_dev(urb), "urb %p resubmit error %d\n", urb, r);
 }
 
 static struct urb *alloc_rx_urb(struct zd_usb *usb)
@@ -690,7 +710,7 @@ static void free_rx_urb(struct urb *urb)
 	usb_free_urb(urb);
 }
 
-int zd_usb_enable_rx(struct zd_usb *usb)
+static int __zd_usb_enable_rx(struct zd_usb *usb)
 {
 	int i, r;
 	struct zd_usb_rx *rx = &usb->rx;
@@ -742,7 +762,21 @@ error:
 	return r;
 }
 
-void zd_usb_disable_rx(struct zd_usb *usb)
+int zd_usb_enable_rx(struct zd_usb *usb)
+{
+	int r;
+	struct zd_usb_rx *rx = &usb->rx;
+
+	mutex_lock(&rx->setup_mutex);
+	r = __zd_usb_enable_rx(usb);
+	mutex_unlock(&rx->setup_mutex);
+
+	zd_usb_reset_rx_idle_timer(usb);
+
+	return r;
+}
+
+static void __zd_usb_disable_rx(struct zd_usb *usb)
 {
 	int i;
 	unsigned long flags;
@@ -769,6 +803,40 @@ void zd_usb_disable_rx(struct zd_usb *usb)
 	spin_unlock_irqrestore(&rx->lock, flags);
 }
 
+void zd_usb_disable_rx(struct zd_usb *usb)
+{
+	struct zd_usb_rx *rx = &usb->rx;
+
+	mutex_lock(&rx->setup_mutex);
+	__zd_usb_disable_rx(usb);
+	mutex_unlock(&rx->setup_mutex);
+
+	cancel_delayed_work_sync(&rx->idle_work);
+}
+
+static void zd_usb_reset_rx(struct zd_usb *usb)
+{
+	bool do_reset;
+	struct zd_usb_rx *rx = &usb->rx;
+	unsigned long flags;
+
+	mutex_lock(&rx->setup_mutex);
+
+	spin_lock_irqsave(&rx->lock, flags);
+	do_reset = rx->urbs != NULL;
+	spin_unlock_irqrestore(&rx->lock, flags);
+
+	if (do_reset) {
+		__zd_usb_disable_rx(usb);
+		__zd_usb_enable_rx(usb);
+	}
+
+	mutex_unlock(&rx->setup_mutex);
+
+	if (do_reset)
+		zd_usb_reset_rx_idle_timer(usb);
+}
+
 /**
  * zd_usb_disable_tx - disable transmission
  * @usb: the zd1211rw-private USB structure
@@ -779,19 +847,21 @@ void zd_usb_disable_tx(struct zd_usb *usb)
 {
 	struct zd_usb_tx *tx = &usb->tx;
 	unsigned long flags;
-	struct list_head *pos, *n;
+
+	atomic_set(&tx->enabled, 0);
+
+	/* kill all submitted tx-urbs */
+	usb_kill_anchored_urbs(&tx->submitted);
 
 	spin_lock_irqsave(&tx->lock, flags);
-	list_for_each_safe(pos, n, &tx->free_urb_list) {
-		list_del(pos);
-		usb_free_urb(list_entry(pos, struct urb, urb_list));
-	}
-	tx->enabled = 0;
+	WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
+	WARN_ON(tx->submitted_urbs != 0);
 	tx->submitted_urbs = 0;
+	spin_unlock_irqrestore(&tx->lock, flags);
+
 	/* The stopped state is ignored, relying on ieee80211_wake_queues()
 	 * in a potentionally following zd_usb_enable_tx().
 	 */
-	spin_unlock_irqrestore(&tx->lock, flags);
 }
 
 /**
@@ -807,63 +877,13 @@ void zd_usb_enable_tx(struct zd_usb *usb)
 	struct zd_usb_tx *tx = &usb->tx;
 
 	spin_lock_irqsave(&tx->lock, flags);
-	tx->enabled = 1;
+	atomic_set(&tx->enabled, 1);
 	tx->submitted_urbs = 0;
 	ieee80211_wake_queues(zd_usb_to_hw(usb));
 	tx->stopped = 0;
 	spin_unlock_irqrestore(&tx->lock, flags);
 }
 
-/**
- * alloc_tx_urb - provides an tx URB
- * @usb: a &struct zd_usb pointer
- *
- * Allocates a new URB. If possible takes the urb from the free list in
- * usb->tx.
- */
-static struct urb *alloc_tx_urb(struct zd_usb *usb)
-{
-	struct zd_usb_tx *tx = &usb->tx;
-	unsigned long flags;
-	struct list_head *entry;
-	struct urb *urb;
-
-	spin_lock_irqsave(&tx->lock, flags);
-	if (list_empty(&tx->free_urb_list)) {
-		urb = usb_alloc_urb(0, GFP_ATOMIC);
-		goto out;
-	}
-	entry = tx->free_urb_list.next;
-	list_del(entry);
-	urb = list_entry(entry, struct urb, urb_list);
-out:
-	spin_unlock_irqrestore(&tx->lock, flags);
-	return urb;
-}
-
-/**
- * free_tx_urb - frees a used tx URB
- * @usb: a &struct zd_usb pointer
- * @urb: URB to be freed
- *
- * Frees the transmission URB, which means to put it on the free URB
- * list.
- */
-static void free_tx_urb(struct zd_usb *usb, struct urb *urb)
-{
-	struct zd_usb_tx *tx = &usb->tx;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tx->lock, flags);
-	if (!tx->enabled) {
-		usb_free_urb(urb);
-		goto out;
-	}
-	list_add(&urb->urb_list, &tx->free_urb_list);
-out:
-	spin_unlock_irqrestore(&tx->lock, flags);
-}
-
 static void tx_dec_submitted_urbs(struct zd_usb *usb)
 {
 	struct zd_usb_tx *tx = &usb->tx;
@@ -905,6 +925,16 @@ static void tx_urb_complete(struct urb *urb)
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
 	struct zd_usb *usb;
+	struct zd_usb_tx *tx;
+
+	skb = (struct sk_buff *)urb->context;
+	info = IEEE80211_SKB_CB(skb);
+	/*
+	 * grab 'usb' pointer before handing off the skb (since
+	 * it might be freed by zd_mac_tx_to_dev or mac80211)
+	 */
+	usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
+	tx = &usb->tx;
 
 	switch (urb->status) {
 	case 0:
@@ -922,20 +952,16 @@ static void tx_urb_complete(struct urb *urb)
 		goto resubmit;
 	}
 free_urb:
-	skb = (struct sk_buff *)urb->context;
-	/*
-	 * grab 'usb' pointer before handing off the skb (since
-	 * it might be freed by zd_mac_tx_to_dev or mac80211)
-	 */
-	info = IEEE80211_SKB_CB(skb);
-	usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
+	skb_unlink(skb, &usb->tx.submitted_skbs);
 	zd_mac_tx_to_dev(skb, urb->status);
-	free_tx_urb(usb, urb);
+	usb_free_urb(urb);
 	tx_dec_submitted_urbs(usb);
 	return;
 resubmit:
+	usb_anchor_urb(urb, &tx->submitted);
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r) {
+		usb_unanchor_urb(urb);
 		dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
 		goto free_urb;
 	}
@@ -956,10 +982,17 @@ resubmit:
 int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
 {
 	int r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct urb *urb;
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (!atomic_read(&tx->enabled)) {
+		r = -ENOENT;
+		goto out;
+	}
 
-	urb = alloc_tx_urb(usb);
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		r = -ENOMEM;
 		goto out;
@@ -968,17 +1001,118 @@ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
 	usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
 		          skb->data, skb->len, tx_urb_complete, skb);
 
+	info->rate_driver_data[1] = (void *)jiffies;
+	skb_queue_tail(&tx->submitted_skbs, skb);
+	usb_anchor_urb(urb, &tx->submitted);
+
 	r = usb_submit_urb(urb, GFP_ATOMIC);
-	if (r)
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r);
+		usb_unanchor_urb(urb);
+		skb_unlink(skb, &tx->submitted_skbs);
 		goto error;
+	}
 	tx_inc_submitted_urbs(usb);
 	return 0;
 error:
-	free_tx_urb(usb, urb);
+	usb_free_urb(urb);
 out:
 	return r;
 }
 
+static bool zd_tx_timeout(struct zd_usb *usb)
+{
+	struct zd_usb_tx *tx = &usb->tx;
+	struct sk_buff_head *q = &tx->submitted_skbs;
+	struct sk_buff *skb, *skbnext;
+	struct ieee80211_tx_info *info;
+	unsigned long flags, trans_start;
+	bool have_timedout = false;
+
+	spin_lock_irqsave(&q->lock, flags);
+	skb_queue_walk_safe(q, skb, skbnext) {
+		info = IEEE80211_SKB_CB(skb);
+		trans_start = (unsigned long)info->rate_driver_data[1];
+
+		if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) {
+			have_timedout = true;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return have_timedout;
+}
+
+static void zd_tx_watchdog_handler(struct work_struct *work)
+{
+	struct zd_usb *usb =
+		container_of(work, struct zd_usb, tx.watchdog_work.work);
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled)
+		goto out;
+	if (!zd_tx_timeout(usb))
+		goto out;
+
+	/* TX halted, try reset */
+	dev_warn(zd_usb_dev(usb), "TX-stall detected, reseting device...");
+
+	usb_queue_reset_device(usb->intf);
+
+	/* reset will stop this worker, don't rearm */
+	return;
+out:
+	queue_delayed_work(zd_workqueue, &tx->watchdog_work,
+			   ZD_TX_WATCHDOG_INTERVAL);
+}
+
+void zd_tx_watchdog_enable(struct zd_usb *usb)
+{
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (!tx->watchdog_enabled) {
+		dev_dbg_f(zd_usb_dev(usb), "\n");
+		queue_delayed_work(zd_workqueue, &tx->watchdog_work,
+				   ZD_TX_WATCHDOG_INTERVAL);
+		tx->watchdog_enabled = 1;
+	}
+}
+
+void zd_tx_watchdog_disable(struct zd_usb *usb)
+{
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (tx->watchdog_enabled) {
+		dev_dbg_f(zd_usb_dev(usb), "\n");
+		tx->watchdog_enabled = 0;
+		cancel_delayed_work_sync(&tx->watchdog_work);
+	}
+}
+
+static void zd_rx_idle_timer_handler(struct work_struct *work)
+{
+	struct zd_usb *usb =
+		container_of(work, struct zd_usb, rx.idle_work.work);
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		return;
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	/* 30 seconds since last rx, reset rx */
+	zd_usb_reset_rx(usb);
+}
+
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
+{
+	struct zd_usb_rx *rx = &usb->rx;
+
+	cancel_delayed_work(&rx->idle_work);
+	queue_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
+}
+
 static inline void init_usb_interrupt(struct zd_usb *usb)
 {
 	struct zd_usb_interrupt *intr = &usb->intr;
@@ -993,22 +1127,27 @@ static inline void init_usb_rx(struct zd_usb *usb)
 {
 	struct zd_usb_rx *rx = &usb->rx;
 	spin_lock_init(&rx->lock);
+	mutex_init(&rx->setup_mutex);
 	if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
 		rx->usb_packet_size = 512;
 	} else {
 		rx->usb_packet_size = 64;
 	}
 	ZD_ASSERT(rx->fragment_length == 0);
+	INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
 }
 
 static inline void init_usb_tx(struct zd_usb *usb)
 {
 	struct zd_usb_tx *tx = &usb->tx;
 	spin_lock_init(&tx->lock);
-	tx->enabled = 0;
+	atomic_set(&tx->enabled, 0);
 	tx->stopped = 0;
-	INIT_LIST_HEAD(&tx->free_urb_list);
+	skb_queue_head_init(&tx->submitted_skbs);
+	init_usb_anchor(&tx->submitted);
 	tx->submitted_urbs = 0;
+	tx->watchdog_enabled = 0;
+	INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler);
 }
 
 void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
@@ -1017,6 +1156,7 @@ void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
 	memset(usb, 0, sizeof(*usb));
 	usb->intf = usb_get_intf(intf);
 	usb_set_intfdata(usb->intf, hw);
+	init_usb_anchor(&usb->submitted_cmds);
 	init_usb_interrupt(usb);
 	init_usb_tx(usb);
 	init_usb_rx(usb);
@@ -1240,6 +1380,7 @@ static void disconnect(struct usb_interface *intf)
 	ieee80211_unregister_hw(hw);
 
 	/* Just in case something has gone wrong! */
+	zd_usb_disable_tx(usb);
 	zd_usb_disable_rx(usb);
 	zd_usb_disable_int(usb);
 
@@ -1255,11 +1396,92 @@ static void disconnect(struct usb_interface *intf)
 	dev_dbg(&intf->dev, "disconnected\n");
 }
 
+static void zd_usb_resume(struct zd_usb *usb)
+{
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+	int r;
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	r = zd_op_start(zd_usb_to_hw(usb));
+	if (r < 0) {
+		dev_warn(zd_usb_dev(usb), "Device resume failed "
+			 "with error code %d. Retrying...\n", r);
+		if (usb->was_running)
+			set_bit(ZD_DEVICE_RUNNING, &mac->flags);
+		usb_queue_reset_device(usb->intf);
+		return;
+	}
+
+	if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
+		r = zd_restore_settings(mac);
+		if (r < 0) {
+			dev_dbg(zd_usb_dev(usb),
+				"failed to restore settings, %d\n", r);
+			return;
+		}
+	}
+}
+
+static void zd_usb_stop(struct zd_usb *usb)
+{
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	zd_op_stop(zd_usb_to_hw(usb));
+
+	zd_usb_disable_tx(usb);
+	zd_usb_disable_rx(usb);
+	zd_usb_disable_int(usb);
+
+	usb->initialized = 0;
+}
+
+static int pre_reset(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct zd_mac *mac;
+	struct zd_usb *usb;
+
+	if (!hw || intf->condition != USB_INTERFACE_BOUND)
+		return 0;
+
+	mac = zd_hw_mac(hw);
+	usb = &mac->chip.usb;
+
+	usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags);
+
+	zd_usb_stop(usb);
+
+	mutex_lock(&mac->chip.mutex);
+	return 0;
+}
+
+static int post_reset(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct zd_mac *mac;
+	struct zd_usb *usb;
+
+	if (!hw || intf->condition != USB_INTERFACE_BOUND)
+		return 0;
+
+	mac = zd_hw_mac(hw);
+	usb = &mac->chip.usb;
+
+	mutex_unlock(&mac->chip.mutex);
+
+	if (usb->was_running)
+		zd_usb_resume(usb);
+	return 0;
+}
+
 static struct usb_driver driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= usb_ids,
 	.probe		= probe,
 	.disconnect	= disconnect,
+	.pre_reset	= pre_reset,
+	.post_reset	= post_reset,
 };
 
 struct workqueue_struct *zd_workqueue;
@@ -1393,30 +1615,35 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 		return -EWOULDBLOCK;
 	}
 	if (!usb_int_enabled(usb)) {
-		 dev_dbg_f(zd_usb_dev(usb),
+		dev_dbg_f(zd_usb_dev(usb),
 			  "error: usb interrupt not enabled\n");
 		return -EWOULDBLOCK;
 	}
 
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	BUILD_BUG_ON(sizeof(struct usb_req_read_regs) + USB_MAX_IOREAD16_COUNT *
+		     sizeof(__le16) > sizeof(usb->req_buf));
+	BUG_ON(sizeof(struct usb_req_read_regs) + count * sizeof(__le16) >
+	       sizeof(usb->req_buf));
+
 	req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
-	req = kmalloc(req_len, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
+	req = (void *)usb->req_buf;
+
 	req->id = cpu_to_le16(USB_REQ_READ_REGS);
 	for (i = 0; i < count; i++)
 		req->addr[i] = cpu_to_le16((u16)addresses[i]);
 
 	udev = zd_usb_to_usbdev(usb);
 	prepare_read_regs_int(usb);
-	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-		         req, req_len, &actual_req_len, 1000 /* ms */);
+	r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
+			      req, req_len, &actual_req_len, 50 /* ms */);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg(). Error number %d\n", r);
+			"error in usb_interrupt_msg(). Error number %d\n", r);
 		goto error;
 	}
 	if (req_len != actual_req_len) {
-		dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n"
+		dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n"
 			" req_len %d != actual_req_len %d\n",
 			req_len, actual_req_len);
 		r = -EIO;
@@ -1424,7 +1651,7 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 	}
 
 	timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion,
-	                                      msecs_to_jiffies(1000));
+					      msecs_to_jiffies(50));
 	if (!timeout) {
 		disable_read_regs_int(usb);
 		dev_dbg_f(zd_usb_dev(usb), "read timed out\n");
@@ -1434,17 +1661,106 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
 
 	r = get_results(usb, values, req, count);
 error:
-	kfree(req);
 	return r;
 }
 
-int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
-	              unsigned int count)
+static void iowrite16v_urb_complete(struct urb *urb)
+{
+	struct zd_usb *usb = urb->context;
+
+	if (urb->status && !usb->cmd_error)
+		usb->cmd_error = urb->status;
+}
+
+static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
+{
+	int r = 0;
+	struct urb *urb = usb->urb_async_waiting;
+
+	if (!urb)
+		return 0;
+
+	usb->urb_async_waiting = NULL;
+
+	if (!last)
+		urb->transfer_flags |= URB_NO_INTERRUPT;
+
+	usb_anchor_urb(urb, &usb->submitted_cmds);
+	r = usb_submit_urb(urb, GFP_KERNEL);
+	if (r) {
+		usb_unanchor_urb(urb);
+		dev_dbg_f(zd_usb_dev(usb),
+			"error in usb_submit_urb(). Error number %d\n", r);
+		goto error;
+	}
+
+	/* fall-through with r == 0 */
+error:
+	usb_free_urb(urb);
+	return r;
+}
+
+void zd_usb_iowrite16v_async_start(struct zd_usb *usb)
+{
+	ZD_ASSERT(usb_anchor_empty(&usb->submitted_cmds));
+	ZD_ASSERT(usb->urb_async_waiting == NULL);
+	ZD_ASSERT(!usb->in_async);
+
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+
+	usb->in_async = 1;
+	usb->cmd_error = 0;
+	usb->urb_async_waiting = NULL;
+}
+
+int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout)
+{
+	int r;
+
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	ZD_ASSERT(usb->in_async);
+
+	/* Submit last iowrite16v URB */
+	r = zd_submit_waiting_urb(usb, true);
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb),
+			"error in zd_submit_waiting_usb(). "
+			"Error number %d\n", r);
+
+		usb_kill_anchored_urbs(&usb->submitted_cmds);
+		goto error;
+	}
+
+	if (timeout)
+		timeout = usb_wait_anchor_empty_timeout(&usb->submitted_cmds,
+							timeout);
+	if (!timeout) {
+		usb_kill_anchored_urbs(&usb->submitted_cmds);
+		if (usb->cmd_error == -ENOENT) {
+			dev_dbg_f(zd_usb_dev(usb), "timed out");
+			r = -ETIMEDOUT;
+			goto error;
+		}
+	}
+
+	r = usb->cmd_error;
+error:
+	usb->in_async = 0;
+	return r;
+}
+
+int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+			    unsigned int count)
 {
 	int r;
 	struct usb_device *udev;
 	struct usb_req_write_regs *req = NULL;
-	int i, req_len, actual_req_len;
+	int i, req_len;
+	struct urb *urb;
+	struct usb_host_endpoint *ep;
+
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	ZD_ASSERT(usb->in_async);
 
 	if (count == 0)
 		return 0;
@@ -1460,11 +1776,23 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 		return -EWOULDBLOCK;
 	}
 
+	udev = zd_usb_to_usbdev(usb);
+
+	ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT));
+	if (!ep)
+		return -ENOENT;
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return -ENOMEM;
+
 	req_len = sizeof(struct usb_req_write_regs) +
 		  count * sizeof(struct reg_data);
 	req = kmalloc(req_len, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
+	if (!req) {
+		r = -ENOMEM;
+		goto error;
+	}
 
 	req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
 	for (i = 0; i < count; i++) {
@@ -1473,29 +1801,44 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 		rw->value = cpu_to_le16(ioreqs[i].value);
 	}
 
-	udev = zd_usb_to_usbdev(usb);
-	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-		         req, req_len, &actual_req_len, 1000 /* ms */);
+	usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
+			 req, req_len, iowrite16v_urb_complete, usb,
+			 ep->desc.bInterval);
+	urb->transfer_flags |= URB_FREE_BUFFER | URB_SHORT_NOT_OK;
+
+	/* Submit previous URB */
+	r = zd_submit_waiting_urb(usb, false);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg(). Error number %d\n", r);
-		goto error;
-	}
-	if (req_len != actual_req_len) {
-		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg()"
-			" req_len %d != actual_req_len %d\n",
-			req_len, actual_req_len);
-		r = -EIO;
+			"error in zd_submit_waiting_usb(). "
+			"Error number %d\n", r);
 		goto error;
 	}
 
-	/* FALL-THROUGH with r == 0 */
+	/* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs
+	 * of currect batch except for very last.
+	 */
+	usb->urb_async_waiting = urb;
+	return 0;
 error:
-	kfree(req);
+	usb_free_urb(urb);
 	return r;
 }
 
+int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+			unsigned int count)
+{
+	int r;
+
+	zd_usb_iowrite16v_async_start(usb);
+	r = zd_usb_iowrite16v_async(usb, ioreqs, count);
+	if (r) {
+		zd_usb_iowrite16v_async_end(usb, 0);
+		return r;
+	}
+	return zd_usb_iowrite16v_async_end(usb, 50 /* ms */);
+}
+
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
 {
 	int r;
@@ -1537,14 +1880,19 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
 			"error %d: Couldn't read CR203\n", r);
-		goto out;
+		return r;
 	}
 	bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
 
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	BUILD_BUG_ON(sizeof(struct usb_req_rfwrite) +
+		     USB_MAX_RFWRITE_BIT_COUNT * sizeof(__le16) >
+		     sizeof(usb->req_buf));
+	BUG_ON(sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16) >
+	       sizeof(usb->req_buf));
+
 	req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
-	req = kmalloc(req_len, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
+	req = (void *)usb->req_buf;
 
 	req->id = cpu_to_le16(USB_REQ_WRITE_RF);
 	/* 1: 3683a, but not used in ZYDAS driver */
@@ -1559,15 +1907,15 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
 	}
 
 	udev = zd_usb_to_usbdev(usb);
-	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-		         req, req_len, &actual_req_len, 1000 /* ms */);
+	r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
+			      req, req_len, &actual_req_len, 50 /* ms */);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg(). Error number %d\n", r);
+			"error in usb_interrupt_msg(). Error number %d\n", r);
 		goto out;
 	}
 	if (req_len != actual_req_len) {
-		dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()"
+		dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()"
 			" req_len %d != actual_req_len %d\n",
 			req_len, actual_req_len);
 		r = -EIO;
@@ -1576,6 +1924,5 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
 
 	/* FALL-THROUGH with r == 0 */
 out:
-	kfree(req);
 	return r;
 }
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 1b1655c..b3df2c8 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -32,6 +32,10 @@
 #define ZD_USB_TX_HIGH  5
 #define ZD_USB_TX_LOW   2
 
+#define ZD_TX_TIMEOUT		(HZ * 5)
+#define ZD_TX_WATCHDOG_INTERVAL	round_jiffies_relative(HZ)
+#define ZD_RX_IDLE_INTERVAL	round_jiffies_relative(30 * HZ)
+
 enum devicetype {
 	DEVICE_ZD1211  = 0,
 	DEVICE_ZD1211B = 1,
@@ -162,6 +166,8 @@ struct zd_usb_interrupt {
 	struct read_regs_int read_regs;
 	spinlock_t lock;
 	struct urb *urb;
+	void *buffer;
+	dma_addr_t buffer_dma;
 	int interval;
 	u8 read_regs_enabled:1;
 };
@@ -175,7 +181,9 @@ static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
 
 struct zd_usb_rx {
 	spinlock_t lock;
-	u8 fragment[2*USB_MAX_RX_SIZE];
+	struct mutex setup_mutex;
+	struct delayed_work idle_work;
+	u8 fragment[2 * USB_MAX_RX_SIZE];
 	unsigned int fragment_length;
 	unsigned int usb_packet_size;
 	struct urb **urbs;
@@ -184,19 +192,21 @@ struct zd_usb_rx {
 
 /**
  * struct zd_usb_tx - structure used for transmitting frames
+ * @enabled: atomic enabled flag, indicates whether tx is enabled
  * @lock: lock for transmission
- * @free_urb_list: list of free URBs, contains all the URBs, which can be used
+ * @submitted: anchor for URBs sent to device
  * @submitted_urbs: atomic integer that counts the URBs having sent to the
  *	device, which haven't been completed
- * @enabled: enabled flag, indicates whether tx is enabled
  * @stopped: indicates whether higher level tx queues are stopped
  */
 struct zd_usb_tx {
+	atomic_t enabled;
 	spinlock_t lock;
-	struct list_head free_urb_list;
+	struct delayed_work watchdog_work;
+	struct sk_buff_head submitted_skbs;
+	struct usb_anchor submitted;
 	int submitted_urbs;
-	int enabled;
-	int stopped;
+	u8 stopped:1, watchdog_enabled:1;
 };
 
 /* Contains the usb parts. The structure doesn't require a lock because intf
@@ -207,7 +217,11 @@ struct zd_usb {
 	struct zd_usb_rx rx;
 	struct zd_usb_tx tx;
 	struct usb_interface *intf;
-	u8 is_zd1211b:1, initialized:1;
+	struct usb_anchor submitted_cmds;
+	struct urb *urb_async_waiting;
+	int cmd_error;
+	u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */
+	u8 is_zd1211b:1, initialized:1, was_running:1, in_async:1;
 };
 
 #define zd_usb_dev(usb) (&usb->intf->dev)
@@ -234,12 +248,17 @@ void zd_usb_clear(struct zd_usb *usb);
 
 int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
 
+void zd_tx_watchdog_enable(struct zd_usb *usb);
+void zd_tx_watchdog_disable(struct zd_usb *usb);
+
 int zd_usb_enable_int(struct zd_usb *usb);
 void zd_usb_disable_int(struct zd_usb *usb);
 
 int zd_usb_enable_rx(struct zd_usb *usb);
 void zd_usb_disable_rx(struct zd_usb *usb);
 
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb);
+
 void zd_usb_enable_tx(struct zd_usb *usb);
 void zd_usb_disable_tx(struct zd_usb *usb);
 
@@ -254,6 +273,10 @@ static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value,
 	return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1);
 }
 
+void zd_usb_iowrite16v_async_start(struct zd_usb *usb);
+int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout);
+int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+			    unsigned int count);
 int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 	              unsigned int count);
 
diff --git a/drivers/net/xen-netback/Makefile b/drivers/net/xen-netback/Makefile
new file mode 100644
index 0000000..e346e81
--- /dev/null
+++ b/drivers/net/xen-netback/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_XEN_NETDEV_BACKEND) := xen-netback.o
+
+xen-netback-y := netback.o xenbus.o interface.o
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
new file mode 100644
index 0000000..5d7bbf2
--- /dev/null
+++ b/drivers/net/xen-netback/common.h
@@ -0,0 +1,161 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * 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 __XEN_NETBACK__COMMON_H__
+#define __XEN_NETBACK__COMMON_H__
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/io.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include <xen/interface/io/netif.h>
+#include <xen/interface/grant_table.h>
+#include <xen/grant_table.h>
+#include <xen/xenbus.h>
+
+struct xen_netbk;
+
+struct xenvif {
+	/* Unique identifier for this interface. */
+	domid_t          domid;
+	unsigned int     handle;
+
+	/* Reference to netback processing backend. */
+	struct xen_netbk *netbk;
+
+	u8               fe_dev_addr[6];
+
+	/* Physical parameters of the comms window. */
+	grant_handle_t   tx_shmem_handle;
+	grant_ref_t      tx_shmem_ref;
+	grant_handle_t   rx_shmem_handle;
+	grant_ref_t      rx_shmem_ref;
+	unsigned int     irq;
+
+	/* List of frontends to notify after a batch of frames sent. */
+	struct list_head notify_list;
+
+	/* The shared rings and indexes. */
+	struct xen_netif_tx_back_ring tx;
+	struct xen_netif_rx_back_ring rx;
+	struct vm_struct *tx_comms_area;
+	struct vm_struct *rx_comms_area;
+
+	/* Flags that must not be set in dev->features */
+	u32 features_disabled;
+
+	/* Frontend feature information. */
+	u8 can_sg:1;
+	u8 gso:1;
+	u8 gso_prefix:1;
+	u8 csum:1;
+
+	/* Internal feature information. */
+	u8 can_queue:1;	    /* can queue packets for receiver? */
+
+	/*
+	 * Allow xenvif_start_xmit() to peek ahead in the rx request
+	 * ring.  This is a prediction of what rx_req_cons will be
+	 * once all queued skbs are put on the ring.
+	 */
+	RING_IDX rx_req_cons_peek;
+
+	/* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
+	unsigned long   credit_bytes;
+	unsigned long   credit_usec;
+	unsigned long   remaining_credit;
+	struct timer_list credit_timeout;
+
+	/* Statistics */
+	unsigned long rx_gso_checksum_fixup;
+
+	/* Miscellaneous private stuff. */
+	struct list_head schedule_list;
+	atomic_t         refcnt;
+	struct net_device *dev;
+
+	wait_queue_head_t waiting_to_free;
+};
+
+#define XEN_NETIF_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
+#define XEN_NETIF_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
+
+struct xenvif *xenvif_alloc(struct device *parent,
+			    domid_t domid,
+			    unsigned int handle);
+
+int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
+		   unsigned long rx_ring_ref, unsigned int evtchn);
+void xenvif_disconnect(struct xenvif *vif);
+
+void xenvif_get(struct xenvif *vif);
+void xenvif_put(struct xenvif *vif);
+
+int xenvif_xenbus_init(void);
+
+int xenvif_schedulable(struct xenvif *vif);
+
+int xen_netbk_rx_ring_full(struct xenvif *vif);
+
+int xen_netbk_must_stop_queue(struct xenvif *vif);
+
+/* (Un)Map communication rings. */
+void xen_netbk_unmap_frontend_rings(struct xenvif *vif);
+int xen_netbk_map_frontend_rings(struct xenvif *vif,
+				 grant_ref_t tx_ring_ref,
+				 grant_ref_t rx_ring_ref);
+
+/* (De)Register a xenvif with the netback backend. */
+void xen_netbk_add_xenvif(struct xenvif *vif);
+void xen_netbk_remove_xenvif(struct xenvif *vif);
+
+/* (De)Schedule backend processing for a xenvif */
+void xen_netbk_schedule_xenvif(struct xenvif *vif);
+void xen_netbk_deschedule_xenvif(struct xenvif *vif);
+
+/* Check for SKBs from frontend and schedule backend processing */
+void xen_netbk_check_rx_xenvif(struct xenvif *vif);
+/* Receive an SKB from the frontend */
+void xenvif_receive_skb(struct xenvif *vif, struct sk_buff *skb);
+
+/* Queue an SKB for transmission to the frontend */
+void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb);
+/* Notify xenvif that ring now has space to send an skb to the frontend */
+void xenvif_notify_tx_completion(struct xenvif *vif);
+
+/* Returns number of ring slots required to send an skb to the frontend */
+unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb);
+
+#endif /* __XEN_NETBACK__COMMON_H__ */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
new file mode 100644
index 0000000..de569cc
--- /dev/null
+++ b/drivers/net/xen-netback/interface.c
@@ -0,0 +1,424 @@
+/*
+ * Network-device interface management.
+ *
+ * Copyright (c) 2004-2005, Keir Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * 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 "common.h"
+
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+
+#include <xen/events.h>
+#include <asm/xen/hypercall.h>
+
+#define XENVIF_QUEUE_LENGTH 32
+
+void xenvif_get(struct xenvif *vif)
+{
+	atomic_inc(&vif->refcnt);
+}
+
+void xenvif_put(struct xenvif *vif)
+{
+	if (atomic_dec_and_test(&vif->refcnt))
+		wake_up(&vif->waiting_to_free);
+}
+
+int xenvif_schedulable(struct xenvif *vif)
+{
+	return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
+}
+
+static int xenvif_rx_schedulable(struct xenvif *vif)
+{
+	return xenvif_schedulable(vif) && !xen_netbk_rx_ring_full(vif);
+}
+
+static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
+{
+	struct xenvif *vif = dev_id;
+
+	if (vif->netbk == NULL)
+		return IRQ_NONE;
+
+	xen_netbk_schedule_xenvif(vif);
+
+	if (xenvif_rx_schedulable(vif))
+		netif_wake_queue(vif->dev);
+
+	return IRQ_HANDLED;
+}
+
+static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+
+	BUG_ON(skb->dev != dev);
+
+	if (vif->netbk == NULL)
+		goto drop;
+
+	/* Drop the packet if the target domain has no receive buffers. */
+	if (!xenvif_rx_schedulable(vif))
+		goto drop;
+
+	/* Reserve ring slots for the worst-case number of fragments. */
+	vif->rx_req_cons_peek += xen_netbk_count_skb_slots(vif, skb);
+	xenvif_get(vif);
+
+	if (vif->can_queue && xen_netbk_must_stop_queue(vif))
+		netif_stop_queue(dev);
+
+	xen_netbk_queue_tx_skb(vif, skb);
+
+	return NETDEV_TX_OK;
+
+ drop:
+	vif->dev->stats.tx_dropped++;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+void xenvif_receive_skb(struct xenvif *vif, struct sk_buff *skb)
+{
+	netif_rx_ni(skb);
+}
+
+void xenvif_notify_tx_completion(struct xenvif *vif)
+{
+	if (netif_queue_stopped(vif->dev) && xenvif_rx_schedulable(vif))
+		netif_wake_queue(vif->dev);
+}
+
+static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	return &vif->dev->stats;
+}
+
+static void xenvif_up(struct xenvif *vif)
+{
+	xen_netbk_add_xenvif(vif);
+	enable_irq(vif->irq);
+	xen_netbk_check_rx_xenvif(vif);
+}
+
+static void xenvif_down(struct xenvif *vif)
+{
+	disable_irq(vif->irq);
+	xen_netbk_deschedule_xenvif(vif);
+	xen_netbk_remove_xenvif(vif);
+}
+
+static int xenvif_open(struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (netif_carrier_ok(dev))
+		xenvif_up(vif);
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int xenvif_close(struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (netif_carrier_ok(dev))
+		xenvif_down(vif);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static int xenvif_change_mtu(struct net_device *dev, int mtu)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	int max = vif->can_sg ? 65535 - VLAN_ETH_HLEN : ETH_DATA_LEN;
+
+	if (mtu > max)
+		return -EINVAL;
+	dev->mtu = mtu;
+	return 0;
+}
+
+static void xenvif_set_features(struct xenvif *vif)
+{
+	struct net_device *dev = vif->dev;
+	u32 features = dev->features;
+
+	if (vif->can_sg)
+		features |= NETIF_F_SG;
+	if (vif->gso || vif->gso_prefix)
+		features |= NETIF_F_TSO;
+	if (vif->csum)
+		features |= NETIF_F_IP_CSUM;
+
+	features &= ~(vif->features_disabled);
+
+	if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN)
+		dev->mtu = ETH_DATA_LEN;
+
+	dev->features = features;
+}
+
+static int xenvif_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (data) {
+		if (!vif->csum)
+			return -EOPNOTSUPP;
+		vif->features_disabled &= ~NETIF_F_IP_CSUM;
+	} else {
+		vif->features_disabled |= NETIF_F_IP_CSUM;
+	}
+
+	xenvif_set_features(vif);
+	return 0;
+}
+
+static int xenvif_set_sg(struct net_device *dev, u32 data)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (data) {
+		if (!vif->can_sg)
+			return -EOPNOTSUPP;
+		vif->features_disabled &= ~NETIF_F_SG;
+	} else {
+		vif->features_disabled |= NETIF_F_SG;
+	}
+
+	xenvif_set_features(vif);
+	return 0;
+}
+
+static int xenvif_set_tso(struct net_device *dev, u32 data)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (data) {
+		if (!vif->gso && !vif->gso_prefix)
+			return -EOPNOTSUPP;
+		vif->features_disabled &= ~NETIF_F_TSO;
+	} else {
+		vif->features_disabled |= NETIF_F_TSO;
+	}
+
+	xenvif_set_features(vif);
+	return 0;
+}
+
+static const struct xenvif_stat {
+	char name[ETH_GSTRING_LEN];
+	u16 offset;
+} xenvif_stats[] = {
+	{
+		"rx_gso_checksum_fixup",
+		offsetof(struct xenvif, rx_gso_checksum_fixup)
+	},
+};
+
+static int xenvif_get_sset_count(struct net_device *dev, int string_set)
+{
+	switch (string_set) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(xenvif_stats);
+	default:
+		return -EINVAL;
+	}
+}
+
+static void xenvif_get_ethtool_stats(struct net_device *dev,
+				     struct ethtool_stats *stats, u64 * data)
+{
+	void *vif = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++)
+		data[i] = *(unsigned long *)(vif + xenvif_stats[i].offset);
+}
+
+static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       xenvif_stats[i].name, ETH_GSTRING_LEN);
+		break;
+	}
+}
+
+static struct ethtool_ops xenvif_ethtool_ops = {
+	.get_tx_csum	= ethtool_op_get_tx_csum,
+	.set_tx_csum	= xenvif_set_tx_csum,
+	.get_sg		= ethtool_op_get_sg,
+	.set_sg		= xenvif_set_sg,
+	.get_tso	= ethtool_op_get_tso,
+	.set_tso	= xenvif_set_tso,
+	.get_link	= ethtool_op_get_link,
+
+	.get_sset_count = xenvif_get_sset_count,
+	.get_ethtool_stats = xenvif_get_ethtool_stats,
+	.get_strings = xenvif_get_strings,
+};
+
+static struct net_device_ops xenvif_netdev_ops = {
+	.ndo_start_xmit	= xenvif_start_xmit,
+	.ndo_get_stats	= xenvif_get_stats,
+	.ndo_open	= xenvif_open,
+	.ndo_stop	= xenvif_close,
+	.ndo_change_mtu	= xenvif_change_mtu,
+};
+
+struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
+			    unsigned int handle)
+{
+	int err;
+	struct net_device *dev;
+	struct xenvif *vif;
+	char name[IFNAMSIZ] = {};
+
+	snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
+	dev = alloc_netdev(sizeof(struct xenvif), name, ether_setup);
+	if (dev == NULL) {
+		pr_warn("Could not allocate netdev\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	SET_NETDEV_DEV(dev, parent);
+
+	vif = netdev_priv(dev);
+	vif->domid  = domid;
+	vif->handle = handle;
+	vif->netbk  = NULL;
+	vif->can_sg = 1;
+	vif->csum = 1;
+	atomic_set(&vif->refcnt, 1);
+	init_waitqueue_head(&vif->waiting_to_free);
+	vif->dev = dev;
+	INIT_LIST_HEAD(&vif->schedule_list);
+	INIT_LIST_HEAD(&vif->notify_list);
+
+	vif->credit_bytes = vif->remaining_credit = ~0UL;
+	vif->credit_usec  = 0UL;
+	init_timer(&vif->credit_timeout);
+	/* Initialize 'expires' now: it's used to track the credit window. */
+	vif->credit_timeout.expires = jiffies;
+
+	dev->netdev_ops	= &xenvif_netdev_ops;
+	xenvif_set_features(vif);
+	SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
+
+	dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
+
+	/*
+	 * Initialise a dummy MAC address. We choose the numerically
+	 * largest non-broadcast address to prevent the address getting
+	 * stolen by an Ethernet bridge for STP purposes.
+	 * (FE:FF:FF:FF:FF:FF)
+	 */
+	memset(dev->dev_addr, 0xFF, ETH_ALEN);
+	dev->dev_addr[0] &= ~0x01;
+
+	netif_carrier_off(dev);
+
+	err = register_netdev(dev);
+	if (err) {
+		netdev_warn(dev, "Could not register device: err=%d\n", err);
+		free_netdev(dev);
+		return ERR_PTR(err);
+	}
+
+	netdev_dbg(dev, "Successfully created xenvif\n");
+	return vif;
+}
+
+int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
+		   unsigned long rx_ring_ref, unsigned int evtchn)
+{
+	int err = -ENOMEM;
+
+	/* Already connected through? */
+	if (vif->irq)
+		return 0;
+
+	xenvif_set_features(vif);
+
+	err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
+	if (err < 0)
+		goto err;
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		vif->domid, evtchn, xenvif_interrupt, 0,
+		vif->dev->name, vif);
+	if (err < 0)
+		goto err_unmap;
+	vif->irq = err;
+	disable_irq(vif->irq);
+
+	xenvif_get(vif);
+
+	rtnl_lock();
+	netif_carrier_on(vif->dev);
+	if (netif_running(vif->dev))
+		xenvif_up(vif);
+	rtnl_unlock();
+
+	return 0;
+err_unmap:
+	xen_netbk_unmap_frontend_rings(vif);
+err:
+	return err;
+}
+
+void xenvif_disconnect(struct xenvif *vif)
+{
+	struct net_device *dev = vif->dev;
+	if (netif_carrier_ok(dev)) {
+		rtnl_lock();
+		netif_carrier_off(dev); /* discard queued packets */
+		if (netif_running(dev))
+			xenvif_down(vif);
+		rtnl_unlock();
+		xenvif_put(vif);
+	}
+
+	atomic_dec(&vif->refcnt);
+	wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
+
+	del_timer_sync(&vif->credit_timeout);
+
+	if (vif->irq)
+		unbind_from_irqhandler(vif->irq, vif);
+
+	unregister_netdev(vif->dev);
+
+	xen_netbk_unmap_frontend_rings(vif);
+
+	free_netdev(vif->dev);
+}
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
new file mode 100644
index 0000000..0e4851b
--- /dev/null
+++ b/drivers/net/xen-netback/netback.c
@@ -0,0 +1,1745 @@
+/*
+ * Back-end of the driver for virtual network devices. This portion of the
+ * driver exports a 'unified' network-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A
+ * reference front-end implementation can be found in:
+ *  drivers/net/xen-netfront.c
+ *
+ * Copyright (c) 2002-2005, K A Fraser
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * 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 "common.h"
+
+#include <linux/kthread.h>
+#include <linux/if_vlan.h>
+#include <linux/udp.h>
+
+#include <net/tcp.h>
+
+#include <xen/events.h>
+#include <xen/interface/memory.h>
+
+#include <asm/xen/hypercall.h>
+#include <asm/xen/page.h>
+
+struct pending_tx_info {
+	struct xen_netif_tx_request req;
+	struct xenvif *vif;
+};
+typedef unsigned int pending_ring_idx_t;
+
+struct netbk_rx_meta {
+	int id;
+	int size;
+	int gso_size;
+};
+
+#define MAX_PENDING_REQS 256
+
+#define MAX_BUFFER_OFFSET PAGE_SIZE
+
+/* extra field used in struct page */
+union page_ext {
+	struct {
+#if BITS_PER_LONG < 64
+#define IDX_WIDTH   8
+#define GROUP_WIDTH (BITS_PER_LONG - IDX_WIDTH)
+		unsigned int group:GROUP_WIDTH;
+		unsigned int idx:IDX_WIDTH;
+#else
+		unsigned int group, idx;
+#endif
+	} e;
+	void *mapping;
+};
+
+struct xen_netbk {
+	wait_queue_head_t wq;
+	struct task_struct *task;
+
+	struct sk_buff_head rx_queue;
+	struct sk_buff_head tx_queue;
+
+	struct timer_list net_timer;
+
+	struct page *mmap_pages[MAX_PENDING_REQS];
+
+	pending_ring_idx_t pending_prod;
+	pending_ring_idx_t pending_cons;
+	struct list_head net_schedule_list;
+
+	/* Protect the net_schedule_list in netif. */
+	spinlock_t net_schedule_list_lock;
+
+	atomic_t netfront_count;
+
+	struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
+	struct gnttab_copy tx_copy_ops[MAX_PENDING_REQS];
+
+	u16 pending_ring[MAX_PENDING_REQS];
+
+	/*
+	 * Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
+	 * head/fragment page uses 2 copy operations because it
+	 * straddles two buffers in the frontend.
+	 */
+	struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
+	struct netbk_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+};
+
+static struct xen_netbk *xen_netbk;
+static int xen_netbk_group_nr;
+
+void xen_netbk_add_xenvif(struct xenvif *vif)
+{
+	int i;
+	int min_netfront_count;
+	int min_group = 0;
+	struct xen_netbk *netbk;
+
+	min_netfront_count = atomic_read(&xen_netbk[0].netfront_count);
+	for (i = 0; i < xen_netbk_group_nr; i++) {
+		int netfront_count = atomic_read(&xen_netbk[i].netfront_count);
+		if (netfront_count < min_netfront_count) {
+			min_group = i;
+			min_netfront_count = netfront_count;
+		}
+	}
+
+	netbk = &xen_netbk[min_group];
+
+	vif->netbk = netbk;
+	atomic_inc(&netbk->netfront_count);
+}
+
+void xen_netbk_remove_xenvif(struct xenvif *vif)
+{
+	struct xen_netbk *netbk = vif->netbk;
+	vif->netbk = NULL;
+	atomic_dec(&netbk->netfront_count);
+}
+
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx);
+static void make_tx_response(struct xenvif *vif,
+			     struct xen_netif_tx_request *txp,
+			     s8       st);
+static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
+					     u16      id,
+					     s8       st,
+					     u16      offset,
+					     u16      size,
+					     u16      flags);
+
+static inline unsigned long idx_to_pfn(struct xen_netbk *netbk,
+				       unsigned int idx)
+{
+	return page_to_pfn(netbk->mmap_pages[idx]);
+}
+
+static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk,
+					 unsigned int idx)
+{
+	return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx));
+}
+
+/* extra field used in struct page */
+static inline void set_page_ext(struct page *pg, struct xen_netbk *netbk,
+				unsigned int idx)
+{
+	unsigned int group = netbk - xen_netbk;
+	union page_ext ext = { .e = { .group = group + 1, .idx = idx } };
+
+	BUILD_BUG_ON(sizeof(ext) > sizeof(ext.mapping));
+	pg->mapping = ext.mapping;
+}
+
+static int get_page_ext(struct page *pg,
+			unsigned int *pgroup, unsigned int *pidx)
+{
+	union page_ext ext = { .mapping = pg->mapping };
+	struct xen_netbk *netbk;
+	unsigned int group, idx;
+
+	group = ext.e.group - 1;
+
+	if (group < 0 || group >= xen_netbk_group_nr)
+		return 0;
+
+	netbk = &xen_netbk[group];
+
+	idx = ext.e.idx;
+
+	if ((idx < 0) || (idx >= MAX_PENDING_REQS))
+		return 0;
+
+	if (netbk->mmap_pages[idx] != pg)
+		return 0;
+
+	*pgroup = group;
+	*pidx = idx;
+
+	return 1;
+}
+
+/*
+ * This is the amount of packet we copy rather than map, so that the
+ * guest can't fiddle with the contents of the headers while we do
+ * packet processing on them (netfilter, routing, etc).
+ */
+#define PKT_PROT_LEN    (ETH_HLEN + \
+			 VLAN_HLEN + \
+			 sizeof(struct iphdr) + MAX_IPOPTLEN + \
+			 sizeof(struct tcphdr) + MAX_TCP_OPTION_SPACE)
+
+static inline pending_ring_idx_t pending_index(unsigned i)
+{
+	return i & (MAX_PENDING_REQS-1);
+}
+
+static inline pending_ring_idx_t nr_pending_reqs(struct xen_netbk *netbk)
+{
+	return MAX_PENDING_REQS -
+		netbk->pending_prod + netbk->pending_cons;
+}
+
+static void xen_netbk_kick_thread(struct xen_netbk *netbk)
+{
+	wake_up(&netbk->wq);
+}
+
+static int max_required_rx_slots(struct xenvif *vif)
+{
+	int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
+
+	if (vif->can_sg || vif->gso || vif->gso_prefix)
+		max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
+
+	return max;
+}
+
+int xen_netbk_rx_ring_full(struct xenvif *vif)
+{
+	RING_IDX peek   = vif->rx_req_cons_peek;
+	RING_IDX needed = max_required_rx_slots(vif);
+
+	return ((vif->rx.sring->req_prod - peek) < needed) ||
+	       ((vif->rx.rsp_prod_pvt + XEN_NETIF_RX_RING_SIZE - peek) < needed);
+}
+
+int xen_netbk_must_stop_queue(struct xenvif *vif)
+{
+	if (!xen_netbk_rx_ring_full(vif))
+		return 0;
+
+	vif->rx.sring->req_event = vif->rx_req_cons_peek +
+		max_required_rx_slots(vif);
+	mb(); /* request notification /then/ check the queue */
+
+	return xen_netbk_rx_ring_full(vif);
+}
+
+/*
+ * Returns true if we should start a new receive buffer instead of
+ * adding 'size' bytes to a buffer which currently contains 'offset'
+ * bytes.
+ */
+static bool start_new_rx_buffer(int offset, unsigned long size, int head)
+{
+	/* simple case: we have completely filled the current buffer. */
+	if (offset == MAX_BUFFER_OFFSET)
+		return true;
+
+	/*
+	 * complex case: start a fresh buffer if the current frag
+	 * would overflow the current buffer but only if:
+	 *     (i)   this frag would fit completely in the next buffer
+	 * and (ii)  there is already some data in the current buffer
+	 * and (iii) this is not the head buffer.
+	 *
+	 * Where:
+	 * - (i) stops us splitting a frag into two copies
+	 *   unless the frag is too large for a single buffer.
+	 * - (ii) stops us from leaving a buffer pointlessly empty.
+	 * - (iii) stops us leaving the first buffer
+	 *   empty. Strictly speaking this is already covered
+	 *   by (ii) but is explicitly checked because
+	 *   netfront relies on the first buffer being
+	 *   non-empty and can crash otherwise.
+	 *
+	 * This means we will effectively linearise small
+	 * frags but do not needlessly split large buffers
+	 * into multiple copies tend to give large frags their
+	 * own buffers as before.
+	 */
+	if ((offset + size > MAX_BUFFER_OFFSET) &&
+	    (size <= MAX_BUFFER_OFFSET) && offset && !head)
+		return true;
+
+	return false;
+}
+
+/*
+ * Figure out how many ring slots we're going to need to send @skb to
+ * the guest. This function is essentially a dry run of
+ * netbk_gop_frag_copy.
+ */
+unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
+{
+	unsigned int count;
+	int i, copy_off;
+
+	count = DIV_ROUND_UP(
+			offset_in_page(skb->data)+skb_headlen(skb), PAGE_SIZE);
+
+	copy_off = skb_headlen(skb) % PAGE_SIZE;
+
+	if (skb_shinfo(skb)->gso_size)
+		count++;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		unsigned long size = skb_shinfo(skb)->frags[i].size;
+		unsigned long bytes;
+		while (size > 0) {
+			BUG_ON(copy_off > MAX_BUFFER_OFFSET);
+
+			if (start_new_rx_buffer(copy_off, size, 0)) {
+				count++;
+				copy_off = 0;
+			}
+
+			bytes = size;
+			if (copy_off + bytes > MAX_BUFFER_OFFSET)
+				bytes = MAX_BUFFER_OFFSET - copy_off;
+
+			copy_off += bytes;
+			size -= bytes;
+		}
+	}
+	return count;
+}
+
+struct netrx_pending_operations {
+	unsigned copy_prod, copy_cons;
+	unsigned meta_prod, meta_cons;
+	struct gnttab_copy *copy;
+	struct netbk_rx_meta *meta;
+	int copy_off;
+	grant_ref_t copy_gref;
+};
+
+static struct netbk_rx_meta *get_next_rx_buffer(struct xenvif *vif,
+						struct netrx_pending_operations *npo)
+{
+	struct netbk_rx_meta *meta;
+	struct xen_netif_rx_request *req;
+
+	req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
+
+	meta = npo->meta + npo->meta_prod++;
+	meta->gso_size = 0;
+	meta->size = 0;
+	meta->id = req->id;
+
+	npo->copy_off = 0;
+	npo->copy_gref = req->gref;
+
+	return meta;
+}
+
+/*
+ * Set up the grant operations for this fragment. If it's a flipping
+ * interface, we also set up the unmap request from here.
+ */
+static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
+				struct netrx_pending_operations *npo,
+				struct page *page, unsigned long size,
+				unsigned long offset, int *head)
+{
+	struct gnttab_copy *copy_gop;
+	struct netbk_rx_meta *meta;
+	/*
+	 * These variables a used iff get_page_ext returns true,
+	 * in which case they are guaranteed to be initialized.
+	 */
+	unsigned int uninitialized_var(group), uninitialized_var(idx);
+	int foreign = get_page_ext(page, &group, &idx);
+	unsigned long bytes;
+
+	/* Data must not cross a page boundary. */
+	BUG_ON(size + offset > PAGE_SIZE);
+
+	meta = npo->meta + npo->meta_prod - 1;
+
+	while (size > 0) {
+		BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET);
+
+		if (start_new_rx_buffer(npo->copy_off, size, *head)) {
+			/*
+			 * Netfront requires there to be some data in the head
+			 * buffer.
+			 */
+			BUG_ON(*head);
+
+			meta = get_next_rx_buffer(vif, npo);
+		}
+
+		bytes = size;
+		if (npo->copy_off + bytes > MAX_BUFFER_OFFSET)
+			bytes = MAX_BUFFER_OFFSET - npo->copy_off;
+
+		copy_gop = npo->copy + npo->copy_prod++;
+		copy_gop->flags = GNTCOPY_dest_gref;
+		if (foreign) {
+			struct xen_netbk *netbk = &xen_netbk[group];
+			struct pending_tx_info *src_pend;
+
+			src_pend = &netbk->pending_tx_info[idx];
+
+			copy_gop->source.domid = src_pend->vif->domid;
+			copy_gop->source.u.ref = src_pend->req.gref;
+			copy_gop->flags |= GNTCOPY_source_gref;
+		} else {
+			void *vaddr = page_address(page);
+			copy_gop->source.domid = DOMID_SELF;
+			copy_gop->source.u.gmfn = virt_to_mfn(vaddr);
+		}
+		copy_gop->source.offset = offset;
+		copy_gop->dest.domid = vif->domid;
+
+		copy_gop->dest.offset = npo->copy_off;
+		copy_gop->dest.u.ref = npo->copy_gref;
+		copy_gop->len = bytes;
+
+		npo->copy_off += bytes;
+		meta->size += bytes;
+
+		offset += bytes;
+		size -= bytes;
+
+		/* Leave a gap for the GSO descriptor. */
+		if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix)
+			vif->rx.req_cons++;
+
+		*head = 0; /* There must be something in this buffer now. */
+
+	}
+}
+
+/*
+ * Prepare an SKB to be transmitted to the frontend.
+ *
+ * This function is responsible for allocating grant operations, meta
+ * structures, etc.
+ *
+ * It returns the number of meta structures consumed. The number of
+ * ring slots used is always equal to the number of meta slots used
+ * plus the number of GSO descriptors used. Currently, we use either
+ * zero GSO descriptors (for non-GSO packets) or one descriptor (for
+ * frontend-side LRO).
+ */
+static int netbk_gop_skb(struct sk_buff *skb,
+			 struct netrx_pending_operations *npo)
+{
+	struct xenvif *vif = netdev_priv(skb->dev);
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	int i;
+	struct xen_netif_rx_request *req;
+	struct netbk_rx_meta *meta;
+	unsigned char *data;
+	int head = 1;
+	int old_meta_prod;
+
+	old_meta_prod = npo->meta_prod;
+
+	/* Set up a GSO prefix descriptor, if necessary */
+	if (skb_shinfo(skb)->gso_size && vif->gso_prefix) {
+		req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
+		meta = npo->meta + npo->meta_prod++;
+		meta->gso_size = skb_shinfo(skb)->gso_size;
+		meta->size = 0;
+		meta->id = req->id;
+	}
+
+	req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
+	meta = npo->meta + npo->meta_prod++;
+
+	if (!vif->gso_prefix)
+		meta->gso_size = skb_shinfo(skb)->gso_size;
+	else
+		meta->gso_size = 0;
+
+	meta->size = 0;
+	meta->id = req->id;
+	npo->copy_off = 0;
+	npo->copy_gref = req->gref;
+
+	data = skb->data;
+	while (data < skb_tail_pointer(skb)) {
+		unsigned int offset = offset_in_page(data);
+		unsigned int len = PAGE_SIZE - offset;
+
+		if (data + len > skb_tail_pointer(skb))
+			len = skb_tail_pointer(skb) - data;
+
+		netbk_gop_frag_copy(vif, skb, npo,
+				    virt_to_page(data), len, offset, &head);
+		data += len;
+	}
+
+	for (i = 0; i < nr_frags; i++) {
+		netbk_gop_frag_copy(vif, skb, npo,
+				    skb_shinfo(skb)->frags[i].page,
+				    skb_shinfo(skb)->frags[i].size,
+				    skb_shinfo(skb)->frags[i].page_offset,
+				    &head);
+	}
+
+	return npo->meta_prod - old_meta_prod;
+}
+
+/*
+ * This is a twin to netbk_gop_skb.  Assume that netbk_gop_skb was
+ * used to set up the operations on the top of
+ * netrx_pending_operations, which have since been done.  Check that
+ * they didn't give any errors and advance over them.
+ */
+static int netbk_check_gop(struct xenvif *vif, int nr_meta_slots,
+			   struct netrx_pending_operations *npo)
+{
+	struct gnttab_copy     *copy_op;
+	int status = XEN_NETIF_RSP_OKAY;
+	int i;
+
+	for (i = 0; i < nr_meta_slots; i++) {
+		copy_op = npo->copy + npo->copy_cons++;
+		if (copy_op->status != GNTST_okay) {
+			netdev_dbg(vif->dev,
+				   "Bad status %d from copy to DOM%d.\n",
+				   copy_op->status, vif->domid);
+			status = XEN_NETIF_RSP_ERROR;
+		}
+	}
+
+	return status;
+}
+
+static void netbk_add_frag_responses(struct xenvif *vif, int status,
+				     struct netbk_rx_meta *meta,
+				     int nr_meta_slots)
+{
+	int i;
+	unsigned long offset;
+
+	/* No fragments used */
+	if (nr_meta_slots <= 1)
+		return;
+
+	nr_meta_slots--;
+
+	for (i = 0; i < nr_meta_slots; i++) {
+		int flags;
+		if (i == nr_meta_slots - 1)
+			flags = 0;
+		else
+			flags = XEN_NETRXF_more_data;
+
+		offset = 0;
+		make_rx_response(vif, meta[i].id, status, offset,
+				 meta[i].size, flags);
+	}
+}
+
+struct skb_cb_overlay {
+	int meta_slots_used;
+};
+
+static void xen_netbk_rx_action(struct xen_netbk *netbk)
+{
+	struct xenvif *vif = NULL, *tmp;
+	s8 status;
+	u16 irq, flags;
+	struct xen_netif_rx_response *resp;
+	struct sk_buff_head rxq;
+	struct sk_buff *skb;
+	LIST_HEAD(notify);
+	int ret;
+	int nr_frags;
+	int count;
+	unsigned long offset;
+	struct skb_cb_overlay *sco;
+
+	struct netrx_pending_operations npo = {
+		.copy  = netbk->grant_copy_op,
+		.meta  = netbk->meta,
+	};
+
+	skb_queue_head_init(&rxq);
+
+	count = 0;
+
+	while ((skb = skb_dequeue(&netbk->rx_queue)) != NULL) {
+		vif = netdev_priv(skb->dev);
+		nr_frags = skb_shinfo(skb)->nr_frags;
+
+		sco = (struct skb_cb_overlay *)skb->cb;
+		sco->meta_slots_used = netbk_gop_skb(skb, &npo);
+
+		count += nr_frags + 1;
+
+		__skb_queue_tail(&rxq, skb);
+
+		/* Filled the batch queue? */
+		if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE)
+			break;
+	}
+
+	BUG_ON(npo.meta_prod > ARRAY_SIZE(netbk->meta));
+
+	if (!npo.copy_prod)
+		return;
+
+	BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op));
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op,
+					npo.copy_prod);
+	BUG_ON(ret != 0);
+
+	while ((skb = __skb_dequeue(&rxq)) != NULL) {
+		sco = (struct skb_cb_overlay *)skb->cb;
+
+		vif = netdev_priv(skb->dev);
+
+		if (netbk->meta[npo.meta_cons].gso_size && vif->gso_prefix) {
+			resp = RING_GET_RESPONSE(&vif->rx,
+						vif->rx.rsp_prod_pvt++);
+
+			resp->flags = XEN_NETRXF_gso_prefix | XEN_NETRXF_more_data;
+
+			resp->offset = netbk->meta[npo.meta_cons].gso_size;
+			resp->id = netbk->meta[npo.meta_cons].id;
+			resp->status = sco->meta_slots_used;
+
+			npo.meta_cons++;
+			sco->meta_slots_used--;
+		}
+
+
+		vif->dev->stats.tx_bytes += skb->len;
+		vif->dev->stats.tx_packets++;
+
+		status = netbk_check_gop(vif, sco->meta_slots_used, &npo);
+
+		if (sco->meta_slots_used == 1)
+			flags = 0;
+		else
+			flags = XEN_NETRXF_more_data;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+			flags |= XEN_NETRXF_csum_blank | XEN_NETRXF_data_validated;
+		else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+			/* remote but checksummed. */
+			flags |= XEN_NETRXF_data_validated;
+
+		offset = 0;
+		resp = make_rx_response(vif, netbk->meta[npo.meta_cons].id,
+					status, offset,
+					netbk->meta[npo.meta_cons].size,
+					flags);
+
+		if (netbk->meta[npo.meta_cons].gso_size && !vif->gso_prefix) {
+			struct xen_netif_extra_info *gso =
+				(struct xen_netif_extra_info *)
+				RING_GET_RESPONSE(&vif->rx,
+						  vif->rx.rsp_prod_pvt++);
+
+			resp->flags |= XEN_NETRXF_extra_info;
+
+			gso->u.gso.size = netbk->meta[npo.meta_cons].gso_size;
+			gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+			gso->u.gso.pad = 0;
+			gso->u.gso.features = 0;
+
+			gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+			gso->flags = 0;
+		}
+
+		netbk_add_frag_responses(vif, status,
+					 netbk->meta + npo.meta_cons + 1,
+					 sco->meta_slots_used);
+
+		RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret);
+		irq = vif->irq;
+		if (ret && list_empty(&vif->notify_list))
+			list_add_tail(&vif->notify_list, &notify);
+
+		xenvif_notify_tx_completion(vif);
+
+		xenvif_put(vif);
+		npo.meta_cons += sco->meta_slots_used;
+		dev_kfree_skb(skb);
+	}
+
+	list_for_each_entry_safe(vif, tmp, &notify, notify_list) {
+		notify_remote_via_irq(vif->irq);
+		list_del_init(&vif->notify_list);
+	}
+
+	/* More work to do? */
+	if (!skb_queue_empty(&netbk->rx_queue) &&
+			!timer_pending(&netbk->net_timer))
+		xen_netbk_kick_thread(netbk);
+}
+
+void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb)
+{
+	struct xen_netbk *netbk = vif->netbk;
+
+	skb_queue_tail(&netbk->rx_queue, skb);
+
+	xen_netbk_kick_thread(netbk);
+}
+
+static void xen_netbk_alarm(unsigned long data)
+{
+	struct xen_netbk *netbk = (struct xen_netbk *)data;
+	xen_netbk_kick_thread(netbk);
+}
+
+static int __on_net_schedule_list(struct xenvif *vif)
+{
+	return !list_empty(&vif->schedule_list);
+}
+
+/* Must be called with net_schedule_list_lock held */
+static void remove_from_net_schedule_list(struct xenvif *vif)
+{
+	if (likely(__on_net_schedule_list(vif))) {
+		list_del_init(&vif->schedule_list);
+		xenvif_put(vif);
+	}
+}
+
+static struct xenvif *poll_net_schedule_list(struct xen_netbk *netbk)
+{
+	struct xenvif *vif = NULL;
+
+	spin_lock_irq(&netbk->net_schedule_list_lock);
+	if (list_empty(&netbk->net_schedule_list))
+		goto out;
+
+	vif = list_first_entry(&netbk->net_schedule_list,
+			       struct xenvif, schedule_list);
+	if (!vif)
+		goto out;
+
+	xenvif_get(vif);
+
+	remove_from_net_schedule_list(vif);
+out:
+	spin_unlock_irq(&netbk->net_schedule_list_lock);
+	return vif;
+}
+
+void xen_netbk_schedule_xenvif(struct xenvif *vif)
+{
+	unsigned long flags;
+	struct xen_netbk *netbk = vif->netbk;
+
+	if (__on_net_schedule_list(vif))
+		goto kick;
+
+	spin_lock_irqsave(&netbk->net_schedule_list_lock, flags);
+	if (!__on_net_schedule_list(vif) &&
+	    likely(xenvif_schedulable(vif))) {
+		list_add_tail(&vif->schedule_list, &netbk->net_schedule_list);
+		xenvif_get(vif);
+	}
+	spin_unlock_irqrestore(&netbk->net_schedule_list_lock, flags);
+
+kick:
+	smp_mb();
+	if ((nr_pending_reqs(netbk) < (MAX_PENDING_REQS/2)) &&
+	    !list_empty(&netbk->net_schedule_list))
+		xen_netbk_kick_thread(netbk);
+}
+
+void xen_netbk_deschedule_xenvif(struct xenvif *vif)
+{
+	struct xen_netbk *netbk = vif->netbk;
+	spin_lock_irq(&netbk->net_schedule_list_lock);
+	remove_from_net_schedule_list(vif);
+	spin_unlock_irq(&netbk->net_schedule_list_lock);
+}
+
+void xen_netbk_check_rx_xenvif(struct xenvif *vif)
+{
+	int more_to_do;
+
+	RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, more_to_do);
+
+	if (more_to_do)
+		xen_netbk_schedule_xenvif(vif);
+}
+
+static void tx_add_credit(struct xenvif *vif)
+{
+	unsigned long max_burst, max_credit;
+
+	/*
+	 * Allow a burst big enough to transmit a jumbo packet of up to 128kB.
+	 * Otherwise the interface can seize up due to insufficient credit.
+	 */
+	max_burst = RING_GET_REQUEST(&vif->tx, vif->tx.req_cons)->size;
+	max_burst = min(max_burst, 131072UL);
+	max_burst = max(max_burst, vif->credit_bytes);
+
+	/* Take care that adding a new chunk of credit doesn't wrap to zero. */
+	max_credit = vif->remaining_credit + vif->credit_bytes;
+	if (max_credit < vif->remaining_credit)
+		max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
+
+	vif->remaining_credit = min(max_credit, max_burst);
+}
+
+static void tx_credit_callback(unsigned long data)
+{
+	struct xenvif *vif = (struct xenvif *)data;
+	tx_add_credit(vif);
+	xen_netbk_check_rx_xenvif(vif);
+}
+
+static void netbk_tx_err(struct xenvif *vif,
+			 struct xen_netif_tx_request *txp, RING_IDX end)
+{
+	RING_IDX cons = vif->tx.req_cons;
+
+	do {
+		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
+		if (cons >= end)
+			break;
+		txp = RING_GET_REQUEST(&vif->tx, cons++);
+	} while (1);
+	vif->tx.req_cons = cons;
+	xen_netbk_check_rx_xenvif(vif);
+	xenvif_put(vif);
+}
+
+static int netbk_count_requests(struct xenvif *vif,
+				struct xen_netif_tx_request *first,
+				struct xen_netif_tx_request *txp,
+				int work_to_do)
+{
+	RING_IDX cons = vif->tx.req_cons;
+	int frags = 0;
+
+	if (!(first->flags & XEN_NETTXF_more_data))
+		return 0;
+
+	do {
+		if (frags >= work_to_do) {
+			netdev_dbg(vif->dev, "Need more frags\n");
+			return -frags;
+		}
+
+		if (unlikely(frags >= MAX_SKB_FRAGS)) {
+			netdev_dbg(vif->dev, "Too many frags\n");
+			return -frags;
+		}
+
+		memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
+		       sizeof(*txp));
+		if (txp->size > first->size) {
+			netdev_dbg(vif->dev, "Frags galore\n");
+			return -frags;
+		}
+
+		first->size -= txp->size;
+		frags++;
+
+		if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
+			netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n",
+				 txp->offset, txp->size);
+			return -frags;
+		}
+	} while ((txp++)->flags & XEN_NETTXF_more_data);
+	return frags;
+}
+
+static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
+					 struct sk_buff *skb,
+					 unsigned long pending_idx)
+{
+	struct page *page;
+	page = alloc_page(GFP_KERNEL|__GFP_COLD);
+	if (!page)
+		return NULL;
+	set_page_ext(page, netbk, pending_idx);
+	netbk->mmap_pages[pending_idx] = page;
+	return page;
+}
+
+static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
+						  struct xenvif *vif,
+						  struct sk_buff *skb,
+						  struct xen_netif_tx_request *txp,
+						  struct gnttab_copy *gop)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	skb_frag_t *frags = shinfo->frags;
+	unsigned long pending_idx = *((u16 *)skb->data);
+	int i, start;
+
+	/* Skip first skb fragment if it is on same page as header fragment. */
+	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+	for (i = start; i < shinfo->nr_frags; i++, txp++) {
+		struct page *page;
+		pending_ring_idx_t index;
+		struct pending_tx_info *pending_tx_info =
+			netbk->pending_tx_info;
+
+		index = pending_index(netbk->pending_cons++);
+		pending_idx = netbk->pending_ring[index];
+		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		if (!page)
+			return NULL;
+
+		netbk->mmap_pages[pending_idx] = page;
+
+		gop->source.u.ref = txp->gref;
+		gop->source.domid = vif->domid;
+		gop->source.offset = txp->offset;
+
+		gop->dest.u.gmfn = virt_to_mfn(page_address(page));
+		gop->dest.domid = DOMID_SELF;
+		gop->dest.offset = txp->offset;
+
+		gop->len = txp->size;
+		gop->flags = GNTCOPY_source_gref;
+
+		gop++;
+
+		memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
+		xenvif_get(vif);
+		pending_tx_info[pending_idx].vif = vif;
+		frags[i].page = (void *)pending_idx;
+	}
+
+	return gop;
+}
+
+static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
+				  struct sk_buff *skb,
+				  struct gnttab_copy **gopp)
+{
+	struct gnttab_copy *gop = *gopp;
+	int pending_idx = *((u16 *)skb->data);
+	struct pending_tx_info *pending_tx_info = netbk->pending_tx_info;
+	struct xenvif *vif = pending_tx_info[pending_idx].vif;
+	struct xen_netif_tx_request *txp;
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	int i, err, start;
+
+	/* Check status of header. */
+	err = gop->status;
+	if (unlikely(err)) {
+		pending_ring_idx_t index;
+		index = pending_index(netbk->pending_prod++);
+		txp = &pending_tx_info[pending_idx].req;
+		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
+		netbk->pending_ring[index] = pending_idx;
+		xenvif_put(vif);
+	}
+
+	/* Skip first skb fragment if it is on same page as header fragment. */
+	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+	for (i = start; i < nr_frags; i++) {
+		int j, newerr;
+		pending_ring_idx_t index;
+
+		pending_idx = (unsigned long)shinfo->frags[i].page;
+
+		/* Check error status: if okay then remember grant handle. */
+		newerr = (++gop)->status;
+		if (likely(!newerr)) {
+			/* Had a previous error? Invalidate this fragment. */
+			if (unlikely(err))
+				xen_netbk_idx_release(netbk, pending_idx);
+			continue;
+		}
+
+		/* Error on this fragment: respond to client with an error. */
+		txp = &netbk->pending_tx_info[pending_idx].req;
+		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
+		index = pending_index(netbk->pending_prod++);
+		netbk->pending_ring[index] = pending_idx;
+		xenvif_put(vif);
+
+		/* Not the first error? Preceding frags already invalidated. */
+		if (err)
+			continue;
+
+		/* First error: invalidate header and preceding fragments. */
+		pending_idx = *((u16 *)skb->data);
+		xen_netbk_idx_release(netbk, pending_idx);
+		for (j = start; j < i; j++) {
+			pending_idx = (unsigned long)shinfo->frags[i].page;
+			xen_netbk_idx_release(netbk, pending_idx);
+		}
+
+		/* Remember the error: invalidate all subsequent fragments. */
+		err = newerr;
+	}
+
+	*gopp = gop + 1;
+	return err;
+}
+
+static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	int i;
+
+	for (i = 0; i < nr_frags; i++) {
+		skb_frag_t *frag = shinfo->frags + i;
+		struct xen_netif_tx_request *txp;
+		unsigned long pending_idx;
+
+		pending_idx = (unsigned long)frag->page;
+
+		txp = &netbk->pending_tx_info[pending_idx].req;
+		frag->page = virt_to_page(idx_to_kaddr(netbk, pending_idx));
+		frag->size = txp->size;
+		frag->page_offset = txp->offset;
+
+		skb->len += txp->size;
+		skb->data_len += txp->size;
+		skb->truesize += txp->size;
+
+		/* Take an extra reference to offset xen_netbk_idx_release */
+		get_page(netbk->mmap_pages[pending_idx]);
+		xen_netbk_idx_release(netbk, pending_idx);
+	}
+}
+
+static int xen_netbk_get_extras(struct xenvif *vif,
+				struct xen_netif_extra_info *extras,
+				int work_to_do)
+{
+	struct xen_netif_extra_info extra;
+	RING_IDX cons = vif->tx.req_cons;
+
+	do {
+		if (unlikely(work_to_do-- <= 0)) {
+			netdev_dbg(vif->dev, "Missing extra info\n");
+			return -EBADR;
+		}
+
+		memcpy(&extra, RING_GET_REQUEST(&vif->tx, cons),
+		       sizeof(extra));
+		if (unlikely(!extra.type ||
+			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+			vif->tx.req_cons = ++cons;
+			netdev_dbg(vif->dev,
+				   "Invalid extra type: %d\n", extra.type);
+			return -EINVAL;
+		}
+
+		memcpy(&extras[extra.type - 1], &extra, sizeof(extra));
+		vif->tx.req_cons = ++cons;
+	} while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
+
+	return work_to_do;
+}
+
+static int netbk_set_skb_gso(struct xenvif *vif,
+			     struct sk_buff *skb,
+			     struct xen_netif_extra_info *gso)
+{
+	if (!gso->u.gso.size) {
+		netdev_dbg(vif->dev, "GSO size must not be zero.\n");
+		return -EINVAL;
+	}
+
+	/* Currently only TCPv4 S.O. is supported. */
+	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+		netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type);
+		return -EINVAL;
+	}
+
+	skb_shinfo(skb)->gso_size = gso->u.gso.size;
+	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+
+	/* Header must be checked, and gso_segs computed. */
+	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+	skb_shinfo(skb)->gso_segs = 0;
+
+	return 0;
+}
+
+static int checksum_setup(struct xenvif *vif, struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	unsigned char *th;
+	int err = -EPROTO;
+	int recalculate_partial_csum = 0;
+
+	/*
+	 * A GSO SKB must be CHECKSUM_PARTIAL. However some buggy
+	 * peers can fail to set NETRXF_csum_blank when sending a GSO
+	 * frame. In this case force the SKB to CHECKSUM_PARTIAL and
+	 * recalculate the partial checksum.
+	 */
+	if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) {
+		vif->rx_gso_checksum_fixup++;
+		skb->ip_summed = CHECKSUM_PARTIAL;
+		recalculate_partial_csum = 1;
+	}
+
+	/* A non-CHECKSUM_PARTIAL SKB does not require setup. */
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return 0;
+
+	if (skb->protocol != htons(ETH_P_IP))
+		goto out;
+
+	iph = (void *)skb->data;
+	th = skb->data + 4 * iph->ihl;
+	if (th >= skb_tail_pointer(skb))
+		goto out;
+
+	skb->csum_start = th - skb->head;
+	switch (iph->protocol) {
+	case IPPROTO_TCP:
+		skb->csum_offset = offsetof(struct tcphdr, check);
+
+		if (recalculate_partial_csum) {
+			struct tcphdr *tcph = (struct tcphdr *)th;
+			tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+							 skb->len - iph->ihl*4,
+							 IPPROTO_TCP, 0);
+		}
+		break;
+	case IPPROTO_UDP:
+		skb->csum_offset = offsetof(struct udphdr, check);
+
+		if (recalculate_partial_csum) {
+			struct udphdr *udph = (struct udphdr *)th;
+			udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+							 skb->len - iph->ihl*4,
+							 IPPROTO_UDP, 0);
+		}
+		break;
+	default:
+		if (net_ratelimit())
+			netdev_err(vif->dev,
+				   "Attempting to checksum a non-TCP/UDP packet, dropping a protocol %d packet\n",
+				   iph->protocol);
+		goto out;
+	}
+
+	if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+		goto out;
+
+	err = 0;
+
+out:
+	return err;
+}
+
+static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
+{
+	unsigned long now = jiffies;
+	unsigned long next_credit =
+		vif->credit_timeout.expires +
+		msecs_to_jiffies(vif->credit_usec / 1000);
+
+	/* Timer could already be pending in rare cases. */
+	if (timer_pending(&vif->credit_timeout))
+		return true;
+
+	/* Passed the point where we can replenish credit? */
+	if (time_after_eq(now, next_credit)) {
+		vif->credit_timeout.expires = now;
+		tx_add_credit(vif);
+	}
+
+	/* Still too big to send right now? Set a callback. */
+	if (size > vif->remaining_credit) {
+		vif->credit_timeout.data     =
+			(unsigned long)vif;
+		vif->credit_timeout.function =
+			tx_credit_callback;
+		mod_timer(&vif->credit_timeout,
+			  next_credit);
+
+		return true;
+	}
+
+	return false;
+}
+
+static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
+{
+	struct gnttab_copy *gop = netbk->tx_copy_ops, *request_gop;
+	struct sk_buff *skb;
+	int ret;
+
+	while (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+		!list_empty(&netbk->net_schedule_list)) {
+		struct xenvif *vif;
+		struct xen_netif_tx_request txreq;
+		struct xen_netif_tx_request txfrags[MAX_SKB_FRAGS];
+		struct page *page;
+		struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1];
+		u16 pending_idx;
+		RING_IDX idx;
+		int work_to_do;
+		unsigned int data_len;
+		pending_ring_idx_t index;
+
+		/* Get a netif from the list with work to do. */
+		vif = poll_net_schedule_list(netbk);
+		if (!vif)
+			continue;
+
+		RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
+		if (!work_to_do) {
+			xenvif_put(vif);
+			continue;
+		}
+
+		idx = vif->tx.req_cons;
+		rmb(); /* Ensure that we see the request before we copy it. */
+		memcpy(&txreq, RING_GET_REQUEST(&vif->tx, idx), sizeof(txreq));
+
+		/* Credit-based scheduling. */
+		if (txreq.size > vif->remaining_credit &&
+		    tx_credit_exceeded(vif, txreq.size)) {
+			xenvif_put(vif);
+			continue;
+		}
+
+		vif->remaining_credit -= txreq.size;
+
+		work_to_do--;
+		vif->tx.req_cons = ++idx;
+
+		memset(extras, 0, sizeof(extras));
+		if (txreq.flags & XEN_NETTXF_extra_info) {
+			work_to_do = xen_netbk_get_extras(vif, extras,
+							  work_to_do);
+			idx = vif->tx.req_cons;
+			if (unlikely(work_to_do < 0)) {
+				netbk_tx_err(vif, &txreq, idx);
+				continue;
+			}
+		}
+
+		ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do);
+		if (unlikely(ret < 0)) {
+			netbk_tx_err(vif, &txreq, idx - ret);
+			continue;
+		}
+		idx += ret;
+
+		if (unlikely(txreq.size < ETH_HLEN)) {
+			netdev_dbg(vif->dev,
+				   "Bad packet size: %d\n", txreq.size);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+
+		/* No crossing a page as the payload mustn't fragment. */
+		if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
+			netdev_dbg(vif->dev,
+				   "txreq.offset: %x, size: %u, end: %lu\n",
+				   txreq.offset, txreq.size,
+				   (txreq.offset&~PAGE_MASK) + txreq.size);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+
+		index = pending_index(netbk->pending_cons);
+		pending_idx = netbk->pending_ring[index];
+
+		data_len = (txreq.size > PKT_PROT_LEN &&
+			    ret < MAX_SKB_FRAGS) ?
+			PKT_PROT_LEN : txreq.size;
+
+		skb = alloc_skb(data_len + NET_SKB_PAD + NET_IP_ALIGN,
+				GFP_ATOMIC | __GFP_NOWARN);
+		if (unlikely(skb == NULL)) {
+			netdev_dbg(vif->dev,
+				   "Can't allocate a skb in start_xmit.\n");
+			netbk_tx_err(vif, &txreq, idx);
+			break;
+		}
+
+		/* Packets passed to netif_rx() must have some headroom. */
+		skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
+
+		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
+			struct xen_netif_extra_info *gso;
+			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+
+			if (netbk_set_skb_gso(vif, skb, gso)) {
+				kfree_skb(skb);
+				netbk_tx_err(vif, &txreq, idx);
+				continue;
+			}
+		}
+
+		/* XXX could copy straight to head */
+		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		if (!page) {
+			kfree_skb(skb);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+
+		netbk->mmap_pages[pending_idx] = page;
+
+		gop->source.u.ref = txreq.gref;
+		gop->source.domid = vif->domid;
+		gop->source.offset = txreq.offset;
+
+		gop->dest.u.gmfn = virt_to_mfn(page_address(page));
+		gop->dest.domid = DOMID_SELF;
+		gop->dest.offset = txreq.offset;
+
+		gop->len = txreq.size;
+		gop->flags = GNTCOPY_source_gref;
+
+		gop++;
+
+		memcpy(&netbk->pending_tx_info[pending_idx].req,
+		       &txreq, sizeof(txreq));
+		netbk->pending_tx_info[pending_idx].vif = vif;
+		*((u16 *)skb->data) = pending_idx;
+
+		__skb_put(skb, data_len);
+
+		skb_shinfo(skb)->nr_frags = ret;
+		if (data_len < txreq.size) {
+			skb_shinfo(skb)->nr_frags++;
+			skb_shinfo(skb)->frags[0].page =
+				(void *)(unsigned long)pending_idx;
+		} else {
+			/* Discriminate from any valid pending_idx value. */
+			skb_shinfo(skb)->frags[0].page = (void *)~0UL;
+		}
+
+		__skb_queue_tail(&netbk->tx_queue, skb);
+
+		netbk->pending_cons++;
+
+		request_gop = xen_netbk_get_requests(netbk, vif,
+						     skb, txfrags, gop);
+		if (request_gop == NULL) {
+			kfree_skb(skb);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+		gop = request_gop;
+
+		vif->tx.req_cons = idx;
+		xen_netbk_check_rx_xenvif(vif);
+
+		if ((gop-netbk->tx_copy_ops) >= ARRAY_SIZE(netbk->tx_copy_ops))
+			break;
+	}
+
+	return gop - netbk->tx_copy_ops;
+}
+
+static void xen_netbk_tx_submit(struct xen_netbk *netbk)
+{
+	struct gnttab_copy *gop = netbk->tx_copy_ops;
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(&netbk->tx_queue)) != NULL) {
+		struct xen_netif_tx_request *txp;
+		struct xenvif *vif;
+		u16 pending_idx;
+		unsigned data_len;
+
+		pending_idx = *((u16 *)skb->data);
+		vif = netbk->pending_tx_info[pending_idx].vif;
+		txp = &netbk->pending_tx_info[pending_idx].req;
+
+		/* Check the remap error code. */
+		if (unlikely(xen_netbk_tx_check_gop(netbk, skb, &gop))) {
+			netdev_dbg(vif->dev, "netback grant failed.\n");
+			skb_shinfo(skb)->nr_frags = 0;
+			kfree_skb(skb);
+			continue;
+		}
+
+		data_len = skb->len;
+		memcpy(skb->data,
+		       (void *)(idx_to_kaddr(netbk, pending_idx)|txp->offset),
+		       data_len);
+		if (data_len < txp->size) {
+			/* Append the packet payload as a fragment. */
+			txp->offset += data_len;
+			txp->size -= data_len;
+		} else {
+			/* Schedule a response immediately. */
+			xen_netbk_idx_release(netbk, pending_idx);
+		}
+
+		if (txp->flags & XEN_NETTXF_csum_blank)
+			skb->ip_summed = CHECKSUM_PARTIAL;
+		else if (txp->flags & XEN_NETTXF_data_validated)
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		xen_netbk_fill_frags(netbk, skb);
+
+		/*
+		 * If the initial fragment was < PKT_PROT_LEN then
+		 * pull through some bytes from the other fragments to
+		 * increase the linear region to PKT_PROT_LEN bytes.
+		 */
+		if (skb_headlen(skb) < PKT_PROT_LEN && skb_is_nonlinear(skb)) {
+			int target = min_t(int, skb->len, PKT_PROT_LEN);
+			__pskb_pull_tail(skb, target - skb_headlen(skb));
+		}
+
+		skb->dev      = vif->dev;
+		skb->protocol = eth_type_trans(skb, skb->dev);
+
+		if (checksum_setup(vif, skb)) {
+			netdev_dbg(vif->dev,
+				   "Can't setup checksum in net_tx_action\n");
+			kfree_skb(skb);
+			continue;
+		}
+
+		vif->dev->stats.rx_bytes += skb->len;
+		vif->dev->stats.rx_packets++;
+
+		xenvif_receive_skb(vif, skb);
+	}
+}
+
+/* Called after netfront has transmitted */
+static void xen_netbk_tx_action(struct xen_netbk *netbk)
+{
+	unsigned nr_gops;
+	int ret;
+
+	nr_gops = xen_netbk_tx_build_gops(netbk);
+
+	if (nr_gops == 0)
+		return;
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
+					netbk->tx_copy_ops, nr_gops);
+	BUG_ON(ret);
+
+	xen_netbk_tx_submit(netbk);
+
+}
+
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
+{
+	struct xenvif *vif;
+	struct pending_tx_info *pending_tx_info;
+	pending_ring_idx_t index;
+
+	/* Already complete? */
+	if (netbk->mmap_pages[pending_idx] == NULL)
+		return;
+
+	pending_tx_info = &netbk->pending_tx_info[pending_idx];
+
+	vif = pending_tx_info->vif;
+
+	make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY);
+
+	index = pending_index(netbk->pending_prod++);
+	netbk->pending_ring[index] = pending_idx;
+
+	xenvif_put(vif);
+
+	netbk->mmap_pages[pending_idx]->mapping = 0;
+	put_page(netbk->mmap_pages[pending_idx]);
+	netbk->mmap_pages[pending_idx] = NULL;
+}
+
+static void make_tx_response(struct xenvif *vif,
+			     struct xen_netif_tx_request *txp,
+			     s8       st)
+{
+	RING_IDX i = vif->tx.rsp_prod_pvt;
+	struct xen_netif_tx_response *resp;
+	int notify;
+
+	resp = RING_GET_RESPONSE(&vif->tx, i);
+	resp->id     = txp->id;
+	resp->status = st;
+
+	if (txp->flags & XEN_NETTXF_extra_info)
+		RING_GET_RESPONSE(&vif->tx, ++i)->status = XEN_NETIF_RSP_NULL;
+
+	vif->tx.rsp_prod_pvt = ++i;
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->tx, notify);
+	if (notify)
+		notify_remote_via_irq(vif->irq);
+}
+
+static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
+					     u16      id,
+					     s8       st,
+					     u16      offset,
+					     u16      size,
+					     u16      flags)
+{
+	RING_IDX i = vif->rx.rsp_prod_pvt;
+	struct xen_netif_rx_response *resp;
+
+	resp = RING_GET_RESPONSE(&vif->rx, i);
+	resp->offset     = offset;
+	resp->flags      = flags;
+	resp->id         = id;
+	resp->status     = (s16)size;
+	if (st < 0)
+		resp->status = (s16)st;
+
+	vif->rx.rsp_prod_pvt = ++i;
+
+	return resp;
+}
+
+static inline int rx_work_todo(struct xen_netbk *netbk)
+{
+	return !skb_queue_empty(&netbk->rx_queue);
+}
+
+static inline int tx_work_todo(struct xen_netbk *netbk)
+{
+
+	if (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+			!list_empty(&netbk->net_schedule_list))
+		return 1;
+
+	return 0;
+}
+
+static int xen_netbk_kthread(void *data)
+{
+	struct xen_netbk *netbk = data;
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(netbk->wq,
+				rx_work_todo(netbk) ||
+				tx_work_todo(netbk) ||
+				kthread_should_stop());
+		cond_resched();
+
+		if (kthread_should_stop())
+			break;
+
+		if (rx_work_todo(netbk))
+			xen_netbk_rx_action(netbk);
+
+		if (tx_work_todo(netbk))
+			xen_netbk_tx_action(netbk);
+	}
+
+	return 0;
+}
+
+void xen_netbk_unmap_frontend_rings(struct xenvif *vif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	if (vif->tx.sring) {
+		gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr,
+				    GNTMAP_host_map, vif->tx_shmem_handle);
+
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+			BUG();
+	}
+
+	if (vif->rx.sring) {
+		gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr,
+				    GNTMAP_host_map, vif->rx_shmem_handle);
+
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+			BUG();
+	}
+	if (vif->rx_comms_area)
+		free_vm_area(vif->rx_comms_area);
+	if (vif->tx_comms_area)
+		free_vm_area(vif->tx_comms_area);
+}
+
+int xen_netbk_map_frontend_rings(struct xenvif *vif,
+				 grant_ref_t tx_ring_ref,
+				 grant_ref_t rx_ring_ref)
+{
+	struct gnttab_map_grant_ref op;
+	struct xen_netif_tx_sring *txs;
+	struct xen_netif_rx_sring *rxs;
+
+	int err = -ENOMEM;
+
+	vif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (vif->tx_comms_area == NULL)
+		goto err;
+
+	vif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (vif->rx_comms_area == NULL)
+		goto err;
+
+	gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr,
+			  GNTMAP_host_map, tx_ring_ref, vif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		netdev_warn(vif->dev,
+			    "failed to map tx ring. err=%d status=%d\n",
+			    err, op.status);
+		err = op.status;
+		goto err;
+	}
+
+	vif->tx_shmem_ref    = tx_ring_ref;
+	vif->tx_shmem_handle = op.handle;
+
+	txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr;
+	BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE);
+
+	gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr,
+			  GNTMAP_host_map, rx_ring_ref, vif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		netdev_warn(vif->dev,
+			    "failed to map rx ring. err=%d status=%d\n",
+			    err, op.status);
+		err = op.status;
+		goto err;
+	}
+
+	vif->rx_shmem_ref     = rx_ring_ref;
+	vif->rx_shmem_handle  = op.handle;
+	vif->rx_req_cons_peek = 0;
+
+	rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr;
+	BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE);
+
+	return 0;
+
+err:
+	xen_netbk_unmap_frontend_rings(vif);
+	return err;
+}
+
+static int __init netback_init(void)
+{
+	int i;
+	int rc = 0;
+	int group;
+
+	if (!xen_pv_domain())
+		return -ENODEV;
+
+	xen_netbk_group_nr = num_online_cpus();
+	xen_netbk = vzalloc(sizeof(struct xen_netbk) * xen_netbk_group_nr);
+	if (!xen_netbk) {
+		printk(KERN_ALERT "%s: out of memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (group = 0; group < xen_netbk_group_nr; group++) {
+		struct xen_netbk *netbk = &xen_netbk[group];
+		skb_queue_head_init(&netbk->rx_queue);
+		skb_queue_head_init(&netbk->tx_queue);
+
+		init_timer(&netbk->net_timer);
+		netbk->net_timer.data = (unsigned long)netbk;
+		netbk->net_timer.function = xen_netbk_alarm;
+
+		netbk->pending_cons = 0;
+		netbk->pending_prod = MAX_PENDING_REQS;
+		for (i = 0; i < MAX_PENDING_REQS; i++)
+			netbk->pending_ring[i] = i;
+
+		init_waitqueue_head(&netbk->wq);
+		netbk->task = kthread_create(xen_netbk_kthread,
+					     (void *)netbk,
+					     "netback/%u", group);
+
+		if (IS_ERR(netbk->task)) {
+			printk(KERN_ALERT "kthread_run() fails at netback\n");
+			del_timer(&netbk->net_timer);
+			rc = PTR_ERR(netbk->task);
+			goto failed_init;
+		}
+
+		kthread_bind(netbk->task, group);
+
+		INIT_LIST_HEAD(&netbk->net_schedule_list);
+
+		spin_lock_init(&netbk->net_schedule_list_lock);
+
+		atomic_set(&netbk->netfront_count, 0);
+
+		wake_up_process(netbk->task);
+	}
+
+	rc = xenvif_xenbus_init();
+	if (rc)
+		goto failed_init;
+
+	return 0;
+
+failed_init:
+	while (--group >= 0) {
+		struct xen_netbk *netbk = &xen_netbk[group];
+		for (i = 0; i < MAX_PENDING_REQS; i++) {
+			if (netbk->mmap_pages[i])
+				__free_page(netbk->mmap_pages[i]);
+		}
+		del_timer(&netbk->net_timer);
+		kthread_stop(netbk->task);
+	}
+	vfree(xen_netbk);
+	return rc;
+
+}
+
+module_init(netback_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
new file mode 100644
index 0000000..22b8c35
--- /dev/null
+++ b/drivers/net/xen-netback/xenbus.c
@@ -0,0 +1,490 @@
+/*
+ * Xenbus code for netif backend
+ *
+ * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ * Copyright (C) 2005 XenSource Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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 "common.h"
+
+struct backend_info {
+	struct xenbus_device *dev;
+	struct xenvif *vif;
+	enum xenbus_state frontend_state;
+	struct xenbus_watch hotplug_status_watch;
+	int have_hotplug_status_watch:1;
+};
+
+static int connect_rings(struct backend_info *);
+static void connect(struct backend_info *);
+static void backend_create_xenvif(struct backend_info *be);
+static void unregister_hotplug_status_watch(struct backend_info *be);
+
+static int netback_remove(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	unregister_hotplug_status_watch(be);
+	if (be->vif) {
+		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
+		xenvif_disconnect(be->vif);
+		be->vif = NULL;
+	}
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+
+/**
+ * Entry point to this code when a new device is created.  Allocate the basic
+ * structures and switch to InitWait.
+ */
+static int netback_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id)
+{
+	const char *message;
+	struct xenbus_transaction xbt;
+	int err;
+	int sg;
+	struct backend_info *be = kzalloc(sizeof(struct backend_info),
+					  GFP_KERNEL);
+	if (!be) {
+		xenbus_dev_fatal(dev, -ENOMEM,
+				 "allocating backend structure");
+		return -ENOMEM;
+	}
+
+	be->dev = dev;
+	dev_set_drvdata(&dev->dev, be);
+
+	sg = 1;
+
+	do {
+		err = xenbus_transaction_start(&xbt);
+		if (err) {
+			xenbus_dev_fatal(dev, err, "starting transaction");
+			goto fail;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", sg);
+		if (err) {
+			message = "writing feature-sg";
+			goto abort_transaction;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
+				    "%d", sg);
+		if (err) {
+			message = "writing feature-gso-tcpv4";
+			goto abort_transaction;
+		}
+
+		/* We support rx-copy path. */
+		err = xenbus_printf(xbt, dev->nodename,
+				    "feature-rx-copy", "%d", 1);
+		if (err) {
+			message = "writing feature-rx-copy";
+			goto abort_transaction;
+		}
+
+		/*
+		 * We don't support rx-flip path (except old guests who don't
+		 * grok this feature flag).
+		 */
+		err = xenbus_printf(xbt, dev->nodename,
+				    "feature-rx-flip", "%d", 0);
+		if (err) {
+			message = "writing feature-rx-flip";
+			goto abort_transaction;
+		}
+
+		err = xenbus_transaction_end(xbt, 0);
+	} while (err == -EAGAIN);
+
+	if (err) {
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto fail;
+	}
+
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto fail;
+
+	/* This kicks hotplug scripts, so do it immediately. */
+	backend_create_xenvif(be);
+
+	return 0;
+
+abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, err, "%s", message);
+fail:
+	pr_debug("failed");
+	netback_remove(dev);
+	return err;
+}
+
+
+/*
+ * Handle the creation of the hotplug script environment.  We add the script
+ * and vif variables to the environment, for the benefit of the vif-* hotplug
+ * scripts.
+ */
+static int netback_uevent(struct xenbus_device *xdev,
+			  struct kobj_uevent_env *env)
+{
+	struct backend_info *be = dev_get_drvdata(&xdev->dev);
+	char *val;
+
+	val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
+	if (IS_ERR(val)) {
+		int err = PTR_ERR(val);
+		xenbus_dev_fatal(xdev, err, "reading script");
+		return err;
+	} else {
+		if (add_uevent_var(env, "script=%s", val)) {
+			kfree(val);
+			return -ENOMEM;
+		}
+		kfree(val);
+	}
+
+	if (!be || !be->vif)
+		return 0;
+
+	return add_uevent_var(env, "vif=%s", be->vif->dev->name);
+}
+
+
+static void backend_create_xenvif(struct backend_info *be)
+{
+	int err;
+	long handle;
+	struct xenbus_device *dev = be->dev;
+
+	if (be->vif != NULL)
+		return;
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading handle");
+		return;
+	}
+
+	be->vif = xenvif_alloc(&dev->dev, dev->otherend_id, handle);
+	if (IS_ERR(be->vif)) {
+		err = PTR_ERR(be->vif);
+		be->vif = NULL;
+		xenbus_dev_fatal(dev, err, "creating interface");
+		return;
+	}
+
+	kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
+}
+
+
+static void disconnect_backend(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	if (be->vif) {
+		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
+		xenvif_disconnect(be->vif);
+		be->vif = NULL;
+	}
+}
+
+/**
+ * Callback received when the frontend's state changes.
+ */
+static void frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	pr_debug("frontend state %s", xenbus_strstate(frontend_state));
+
+	be->frontend_state = frontend_state;
+
+	switch (frontend_state) {
+	case XenbusStateInitialising:
+		if (dev->state == XenbusStateClosed) {
+			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
+			       __func__, dev->nodename);
+			xenbus_switch_state(dev, XenbusStateInitWait);
+		}
+		break;
+
+	case XenbusStateInitialised:
+		break;
+
+	case XenbusStateConnected:
+		if (dev->state == XenbusStateConnected)
+			break;
+		backend_create_xenvif(be);
+		if (be->vif)
+			connect(be);
+		break;
+
+	case XenbusStateClosing:
+		if (be->vif)
+			kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+		disconnect_backend(dev);
+		xenbus_switch_state(dev, XenbusStateClosing);
+		break;
+
+	case XenbusStateClosed:
+		xenbus_switch_state(dev, XenbusStateClosed);
+		if (xenbus_dev_is_online(dev))
+			break;
+		/* fall through if not online */
+	case XenbusStateUnknown:
+		device_unregister(&dev->dev);
+		break;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+
+static void xen_net_read_rate(struct xenbus_device *dev,
+			      unsigned long *bytes, unsigned long *usec)
+{
+	char *s, *e;
+	unsigned long b, u;
+	char *ratestr;
+
+	/* Default to unlimited bandwidth. */
+	*bytes = ~0UL;
+	*usec = 0;
+
+	ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
+	if (IS_ERR(ratestr))
+		return;
+
+	s = ratestr;
+	b = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != ','))
+		goto fail;
+
+	s = e + 1;
+	u = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != '\0'))
+		goto fail;
+
+	*bytes = b;
+	*usec = u;
+
+	kfree(ratestr);
+	return;
+
+ fail:
+	pr_warn("Failed to parse network rate limit. Traffic unlimited.\n");
+	kfree(ratestr);
+}
+
+static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
+{
+	char *s, *e, *macstr;
+	int i;
+
+	macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
+	if (IS_ERR(macstr))
+		return PTR_ERR(macstr);
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		mac[i] = simple_strtoul(s, &e, 16);
+		if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
+			kfree(macstr);
+			return -ENOENT;
+		}
+		s = e+1;
+	}
+
+	kfree(macstr);
+	return 0;
+}
+
+static void unregister_hotplug_status_watch(struct backend_info *be)
+{
+	if (be->have_hotplug_status_watch) {
+		unregister_xenbus_watch(&be->hotplug_status_watch);
+		kfree(be->hotplug_status_watch.node);
+	}
+	be->have_hotplug_status_watch = 0;
+}
+
+static void hotplug_status_changed(struct xenbus_watch *watch,
+				   const char **vec,
+				   unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       hotplug_status_watch);
+	char *str;
+	unsigned int len;
+
+	str = xenbus_read(XBT_NIL, be->dev->nodename, "hotplug-status", &len);
+	if (IS_ERR(str))
+		return;
+	if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) {
+		xenbus_switch_state(be->dev, XenbusStateConnected);
+		/* Not interested in this watch anymore. */
+		unregister_hotplug_status_watch(be);
+	}
+	kfree(str);
+}
+
+static void connect(struct backend_info *be)
+{
+	int err;
+	struct xenbus_device *dev = be->dev;
+
+	err = connect_rings(be);
+	if (err)
+		return;
+
+	err = xen_net_read_mac(dev, be->vif->fe_dev_addr);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
+		return;
+	}
+
+	xen_net_read_rate(dev, &be->vif->credit_bytes,
+			  &be->vif->credit_usec);
+	be->vif->remaining_credit = be->vif->credit_bytes;
+
+	unregister_hotplug_status_watch(be);
+	err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
+				   hotplug_status_changed,
+				   "%s/%s", dev->nodename, "hotplug-status");
+	if (err) {
+		/* Switch now, since we can't do a watch. */
+		xenbus_switch_state(dev, XenbusStateConnected);
+	} else {
+		be->have_hotplug_status_watch = 1;
+	}
+
+	netif_wake_queue(be->vif->dev);
+}
+
+
+static int connect_rings(struct backend_info *be)
+{
+	struct xenvif *vif = be->vif;
+	struct xenbus_device *dev = be->dev;
+	unsigned long tx_ring_ref, rx_ring_ref;
+	unsigned int evtchn, rx_copy;
+	int err;
+	int val;
+
+	err = xenbus_gather(XBT_NIL, dev->otherend,
+			    "tx-ring-ref", "%lu", &tx_ring_ref,
+			    "rx-ring-ref", "%lu", &rx_ring_ref,
+			    "event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "reading %s/ring-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
+			   &rx_copy);
+	if (err == -ENOENT) {
+		err = 0;
+		rx_copy = 0;
+	}
+	if (err < 0) {
+		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
+				 dev->otherend);
+		return err;
+	}
+	if (!rx_copy)
+		return -EOPNOTSUPP;
+
+	if (vif->dev->tx_queue_len != 0) {
+		if (xenbus_scanf(XBT_NIL, dev->otherend,
+				 "feature-rx-notify", "%d", &val) < 0)
+			val = 0;
+		if (val)
+			vif->can_queue = 1;
+		else
+			/* Must be non-zero for pfifo_fast to work. */
+			vif->dev->tx_queue_len = 1;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->can_sg = !!val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->gso = !!val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->gso_prefix = !!val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->csum = !val;
+
+	/* Map the shared frame, irq etc. */
+	err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "mapping shared-frames %lu/%lu port %u",
+				 tx_ring_ref, rx_ring_ref, evtchn);
+		return err;
+	}
+	return 0;
+}
+
+
+/* ** Driver Registration ** */
+
+
+static const struct xenbus_device_id netback_ids[] = {
+	{ "vif" },
+	{ "" }
+};
+
+
+static struct xenbus_driver netback = {
+	.name = "vif",
+	.owner = THIS_MODULE,
+	.ids = netback_ids,
+	.probe = netback_probe,
+	.remove = netback_remove,
+	.uevent = netback_uevent,
+	.otherend_changed = frontend_changed,
+};
+
+int xenvif_xenbus_init(void)
+{
+	return xenbus_register_backend(&netback);
+}
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index da1f121..5c8d9c3 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -122,7 +122,7 @@ struct netfront_info {
 	struct mmu_update rx_mmu[NET_RX_RING_SIZE];
 
 	/* Statistics */
-	int rx_gso_checksum_fixup;
+	unsigned long rx_gso_checksum_fixup;
 };
 
 struct netfront_rx_info {
@@ -359,7 +359,7 @@ static void xennet_tx_buf_gc(struct net_device *dev)
 			struct xen_netif_tx_response *txrsp;
 
 			txrsp = RING_GET_RESPONSE(&np->tx, cons);
-			if (txrsp->status == NETIF_RSP_NULL)
+			if (txrsp->status == XEN_NETIF_RSP_NULL)
 				continue;
 
 			id  = txrsp->id;
@@ -416,7 +416,7 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
 	   larger than a page), split it it into page-sized chunks. */
 	while (len > PAGE_SIZE - offset) {
 		tx->size = PAGE_SIZE - offset;
-		tx->flags |= NETTXF_more_data;
+		tx->flags |= XEN_NETTXF_more_data;
 		len -= tx->size;
 		data += tx->size;
 		offset = 0;
@@ -442,7 +442,7 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
 	for (i = 0; i < frags; i++) {
 		skb_frag_t *frag = skb_shinfo(skb)->frags + i;
 
-		tx->flags |= NETTXF_more_data;
+		tx->flags |= XEN_NETTXF_more_data;
 
 		id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
 		np->tx_skbs[id].skb = skb_get(skb);
@@ -517,10 +517,10 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	tx->flags = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		/* local packet? */
-		tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
+		tx->flags |= XEN_NETTXF_csum_blank | XEN_NETTXF_data_validated;
 	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
 		/* remote but checksummed. */
-		tx->flags |= NETTXF_data_validated;
+		tx->flags |= XEN_NETTXF_data_validated;
 
 	if (skb_shinfo(skb)->gso_size) {
 		struct xen_netif_extra_info *gso;
@@ -531,7 +531,7 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (extra)
 			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
 		else
-			tx->flags |= 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;
@@ -651,7 +651,7 @@ static int xennet_get_responses(struct netfront_info *np,
 	int err = 0;
 	unsigned long ret;
 
-	if (rx->flags & NETRXF_extra_info) {
+	if (rx->flags & XEN_NETRXF_extra_info) {
 		err = xennet_get_extras(np, extras, rp);
 		cons = np->rx.rsp_cons;
 	}
@@ -688,7 +688,7 @@ static int xennet_get_responses(struct netfront_info *np,
 		__skb_queue_tail(list, skb);
 
 next:
-		if (!(rx->flags & NETRXF_more_data))
+		if (!(rx->flags & XEN_NETRXF_more_data))
 			break;
 
 		if (cons + frags == rp) {
@@ -983,9 +983,9 @@ err:
 		skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
 		skb->len += skb->data_len;
 
-		if (rx->flags & NETRXF_csum_blank)
+		if (rx->flags & XEN_NETRXF_csum_blank)
 			skb->ip_summed = CHECKSUM_PARTIAL;
-		else if (rx->flags & NETRXF_data_validated)
+		else if (rx->flags & XEN_NETRXF_data_validated)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		__skb_queue_tail(&rxq, skb);
@@ -1692,7 +1692,7 @@ static void xennet_get_ethtool_stats(struct net_device *dev,
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(xennet_stats); i++)
-		data[i] = *(int *)(np + xennet_stats[i].offset);
+		data[i] = *(unsigned long *)(np + xennet_stats[i].offset);
 }
 
 static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data)
diff --git a/drivers/net/xilinx_emaclite.c b/drivers/net/xilinx_emaclite.c
index cad66ce..2642af4 100644
--- a/drivers/net/xilinx_emaclite.c
+++ b/drivers/net/xilinx_emaclite.c
@@ -1101,8 +1101,7 @@ static struct net_device_ops xemaclite_netdev_ops;
  * Return:	0, if the driver is bound to the Emaclite device, or
  *		a negative error if there is failure.
  */
-static int __devinit xemaclite_of_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
 {
 	struct resource r_irq; /* Interrupt resources */
 	struct resource r_mem; /* IO mem resources */
@@ -1288,7 +1287,7 @@ static struct of_device_id xemaclite_of_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, xemaclite_of_match);
 
-static struct of_platform_driver xemaclite_of_driver = {
+static struct platform_driver xemaclite_of_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1306,7 +1305,7 @@ static struct of_platform_driver xemaclite_of_driver = {
 static int __init xemaclite_init(void)
 {
 	/* No kernel boot options used, we just need to register the driver */
-	return of_register_platform_driver(&xemaclite_of_driver);
+	return platform_driver_register(&xemaclite_of_driver);
 }
 
 /**
@@ -1314,7 +1313,7 @@ static int __init xemaclite_init(void)
  */
 static void __exit xemaclite_cleanup(void)
 {
-	of_unregister_platform_driver(&xemaclite_of_driver);
+	platform_driver_unregister(&xemaclite_of_driver);
 }
 
 module_init(xemaclite_init);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 3c6e100..d06a637 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -69,4 +69,10 @@ config OF_MDIO
 	help
 	  OpenFirmware MDIO bus (Ethernet PHY) accessors
 
+config OF_PCI
+	def_tristate PCI
+	depends on PCI && (PPC || MICROBLAZE || X86)
+	help
+	  OpenFirmware PCI bus accessors
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 3ab21a0..f7861ed 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_OF_I2C)	+= of_i2c.o
 obj-$(CONFIG_OF_NET)	+= of_net.o
 obj-$(CONFIG_OF_SPI)	+= of_spi.o
 obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
+obj-$(CONFIG_OF_PCI)	+= of_pci.o
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 45d8653..62b4b32 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -47,40 +47,6 @@ void of_dev_put(struct platform_device *dev)
 }
 EXPORT_SYMBOL(of_dev_put);
 
-static ssize_t devspec_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct platform_device *ofdev;
-
-	ofdev = to_platform_device(dev);
-	return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
-}
-
-static ssize_t name_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct platform_device *ofdev;
-
-	ofdev = to_platform_device(dev);
-	return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
-}
-
-static ssize_t modalias_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
-	buf[len] = '\n';
-	buf[len+1] = 0;
-	return len+1;
-}
-
-struct device_attribute of_platform_device_attrs[] = {
-	__ATTR_RO(devspec),
-	__ATTR_RO(name),
-	__ATTR_RO(modalias),
-	__ATTR_NULL
-};
-
 int of_device_add(struct platform_device *ofdev)
 {
 	BUG_ON(ofdev->dev.of_node == NULL);
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 0000000..ac1ec54
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,92 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <asm/prom.h>
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev:       the device whose interrupt is to be resolved
+ * @out_irq:    structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+	struct device_node *dn, *ppnode;
+	struct pci_dev *ppdev;
+	u32 lspec;
+	__be32 lspec_be;
+	__be32 laddr[3];
+	u8 pin;
+	int rc;
+
+	/* Check if we have a device node, if yes, fallback to standard
+	 * device tree parsing
+	 */
+	dn = pci_device_to_OF_node(pdev);
+	if (dn) {
+		rc = of_irq_map_one(dn, 0, out_irq);
+		if (!rc)
+			return rc;
+	}
+
+	/* Ok, we don't, time to have fun. Let's start by building up an
+	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
+	 * for PCI. If you do different, then don't use that routine.
+	 */
+	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+	if (rc != 0)
+		return rc;
+	/* No pin, exit */
+	if (pin == 0)
+		return -ENODEV;
+
+	/* Now we walk up the PCI tree */
+	lspec = pin;
+	for (;;) {
+		/* Get the pci_dev of our parent */
+		ppdev = pdev->bus->self;
+
+		/* Ouch, it's a host bridge... */
+		if (ppdev == NULL) {
+			ppnode = pci_bus_to_OF_node(pdev->bus);
+
+			/* No node for host bridge ? give up */
+			if (ppnode == NULL)
+				return -EINVAL;
+		} else {
+			/* We found a P2P bridge, check if it has a node */
+			ppnode = pci_device_to_OF_node(ppdev);
+		}
+
+		/* Ok, we have found a parent with a device-node, hand over to
+		 * the OF parsing code.
+		 * We build a unit address from the linux device to be used for
+		 * resolution. Note that we use the linux bus number which may
+		 * not match your firmware bus numbering.
+		 * Fortunately, in most cases, interrupt-map-mask doesn't
+		 * include the bus number as part of the matching.
+		 * You should still be careful about that though if you intend
+		 * to rely on this function (you ship  a firmware that doesn't
+		 * create device nodes for all PCI devices).
+		 */
+		if (ppnode)
+			break;
+
+		/* We can only get here if we hit a P2P bridge with no node,
+		 * let's do standard swizzling and try again
+		 */
+		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+		pdev = ppdev;
+	}
+
+	lspec_be = cpu_to_be32(lspec);
+	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+	laddr[1]  = laddr[2] = cpu_to_be32(0);
+	return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index c01cd1a..1ce4c45 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -42,471 +42,10 @@ struct platform_device *of_find_device_by_node(struct device_node *np)
 }
 EXPORT_SYMBOL(of_find_device_by_node);
 
-static int platform_driver_probe_shim(struct platform_device *pdev)
-{
-	struct platform_driver *pdrv;
-	struct of_platform_driver *ofpdrv;
-	const struct of_device_id *match;
-
-	pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
-	ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
-
-	/* There is an unlikely chance that an of_platform driver might match
-	 * on a non-OF platform device.  If so, then of_match_device() will
-	 * come up empty.  Return -EINVAL in this case so other drivers get
-	 * the chance to bind. */
-	match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
-	return match ? ofpdrv->probe(pdev, match) : -EINVAL;
-}
-
-static void platform_driver_shutdown_shim(struct platform_device *pdev)
-{
-	struct platform_driver *pdrv;
-	struct of_platform_driver *ofpdrv;
-
-	pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
-	ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
-	ofpdrv->shutdown(pdev);
-}
-
-/**
- * of_register_platform_driver
- */
-int of_register_platform_driver(struct of_platform_driver *drv)
-{
-	char *of_name;
-
-	/* setup of_platform_driver to platform_driver adaptors */
-	drv->platform_driver.driver = drv->driver;
-
-	/* Prefix the driver name with 'of:' to avoid namespace collisions
-	 * and bogus matches.  There are some drivers in the tree that
-	 * register both an of_platform_driver and a platform_driver with
-	 * the same name.  This is a temporary measure until they are all
-	 * cleaned up --gcl July 29, 2010 */
-	of_name = kmalloc(strlen(drv->driver.name) + 5, GFP_KERNEL);
-	if (!of_name)
-		return -ENOMEM;
-	sprintf(of_name, "of:%s", drv->driver.name);
-	drv->platform_driver.driver.name = of_name;
-
-	if (drv->probe)
-		drv->platform_driver.probe = platform_driver_probe_shim;
-	drv->platform_driver.remove = drv->remove;
-	if (drv->shutdown)
-		drv->platform_driver.shutdown = platform_driver_shutdown_shim;
-	drv->platform_driver.suspend = drv->suspend;
-	drv->platform_driver.resume = drv->resume;
-
-	return platform_driver_register(&drv->platform_driver);
-}
-EXPORT_SYMBOL(of_register_platform_driver);
-
-void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
-	platform_driver_unregister(&drv->platform_driver);
-	kfree(drv->platform_driver.driver.name);
-	drv->platform_driver.driver.name = NULL;
-}
-EXPORT_SYMBOL(of_unregister_platform_driver);
-
 #if defined(CONFIG_PPC_DCR)
 #include <asm/dcr.h>
 #endif
 
-extern struct device_attribute of_platform_device_attrs[];
-
-static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
-{
-	const struct of_device_id *matches = drv->of_match_table;
-
-	if (!matches)
-		return 0;
-
-	return of_match_device(matches, dev) != NULL;
-}
-
-static int of_platform_device_probe(struct device *dev)
-{
-	int error = -ENODEV;
-	struct of_platform_driver *drv;
-	struct platform_device *of_dev;
-	const struct of_device_id *match;
-
-	drv = to_of_platform_driver(dev->driver);
-	of_dev = to_platform_device(dev);
-
-	if (!drv->probe)
-		return error;
-
-	of_dev_get(of_dev);
-
-	match = of_match_device(drv->driver.of_match_table, dev);
-	if (match)
-		error = drv->probe(of_dev, match);
-	if (error)
-		of_dev_put(of_dev);
-
-	return error;
-}
-
-static int of_platform_device_remove(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-
-	if (dev->driver && drv->remove)
-		drv->remove(of_dev);
-	return 0;
-}
-
-static void of_platform_device_shutdown(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-
-	if (dev->driver && drv->shutdown)
-		drv->shutdown(of_dev);
-}
-
-#ifdef CONFIG_PM_SLEEP
-
-static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(of_dev, mesg);
-	return ret;
-}
-
-static int of_platform_legacy_resume(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(of_dev);
-	return ret;
-}
-
-static int of_platform_pm_prepare(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (drv && drv->pm && drv->pm->prepare)
-		ret = drv->pm->prepare(dev);
-
-	return ret;
-}
-
-static void of_platform_pm_complete(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-
-	if (drv && drv->pm && drv->pm->complete)
-		drv->pm->complete(dev);
-}
-
-#ifdef CONFIG_SUSPEND
-
-static int of_platform_pm_suspend(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->suspend)
-			ret = drv->pm->suspend(dev);
-	} else {
-		ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_suspend_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->suspend_noirq)
-			ret = drv->pm->suspend_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_resume(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->resume)
-			ret = drv->pm->resume(dev);
-	} else {
-		ret = of_platform_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_resume_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->resume_noirq)
-			ret = drv->pm->resume_noirq(dev);
-	}
-
-	return ret;
-}
-
-#else /* !CONFIG_SUSPEND */
-
-#define of_platform_pm_suspend		NULL
-#define of_platform_pm_resume		NULL
-#define of_platform_pm_suspend_noirq	NULL
-#define of_platform_pm_resume_noirq	NULL
-
-#endif /* !CONFIG_SUSPEND */
-
-#ifdef CONFIG_HIBERNATION
-
-static int of_platform_pm_freeze(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->freeze)
-			ret = drv->pm->freeze(dev);
-	} else {
-		ret = of_platform_legacy_suspend(dev, PMSG_FREEZE);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_freeze_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->freeze_noirq)
-			ret = drv->pm->freeze_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_thaw(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->thaw)
-			ret = drv->pm->thaw(dev);
-	} else {
-		ret = of_platform_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_thaw_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->thaw_noirq)
-			ret = drv->pm->thaw_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_poweroff(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->poweroff)
-			ret = drv->pm->poweroff(dev);
-	} else {
-		ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_poweroff_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->poweroff_noirq)
-			ret = drv->pm->poweroff_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_restore(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->restore)
-			ret = drv->pm->restore(dev);
-	} else {
-		ret = of_platform_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_restore_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->restore_noirq)
-			ret = drv->pm->restore_noirq(dev);
-	}
-
-	return ret;
-}
-
-#else /* !CONFIG_HIBERNATION */
-
-#define of_platform_pm_freeze		NULL
-#define of_platform_pm_thaw		NULL
-#define of_platform_pm_poweroff		NULL
-#define of_platform_pm_restore		NULL
-#define of_platform_pm_freeze_noirq	NULL
-#define of_platform_pm_thaw_noirq		NULL
-#define of_platform_pm_poweroff_noirq	NULL
-#define of_platform_pm_restore_noirq	NULL
-
-#endif /* !CONFIG_HIBERNATION */
-
-static struct dev_pm_ops of_platform_dev_pm_ops = {
-	.prepare = of_platform_pm_prepare,
-	.complete = of_platform_pm_complete,
-	.suspend = of_platform_pm_suspend,
-	.resume = of_platform_pm_resume,
-	.freeze = of_platform_pm_freeze,
-	.thaw = of_platform_pm_thaw,
-	.poweroff = of_platform_pm_poweroff,
-	.restore = of_platform_pm_restore,
-	.suspend_noirq = of_platform_pm_suspend_noirq,
-	.resume_noirq = of_platform_pm_resume_noirq,
-	.freeze_noirq = of_platform_pm_freeze_noirq,
-	.thaw_noirq = of_platform_pm_thaw_noirq,
-	.poweroff_noirq = of_platform_pm_poweroff_noirq,
-	.restore_noirq = of_platform_pm_restore_noirq,
-};
-
-#define OF_PLATFORM_PM_OPS_PTR	(&of_platform_dev_pm_ops)
-
-#else /* !CONFIG_PM_SLEEP */
-
-#define OF_PLATFORM_PM_OPS_PTR	NULL
-
-#endif /* !CONFIG_PM_SLEEP */
-
-int of_bus_type_init(struct bus_type *bus, const char *name)
-{
-	bus->name = name;
-	bus->match = of_platform_bus_match;
-	bus->probe = of_platform_device_probe;
-	bus->remove = of_platform_device_remove;
-	bus->shutdown = of_platform_device_shutdown;
-	bus->dev_attrs = of_platform_device_attrs;
-	bus->pm = OF_PLATFORM_PM_OPS_PTR;
-	return bus_register(bus);
-}
-
-int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
-{
-	/*
-	 * Temporary: of_platform_bus used to be distinct from the platform
-	 * bus.  It isn't anymore, and so drivers on the platform bus need
-	 * to be registered in a special way.
-	 *
-	 * After all of_platform_bus_type drivers are converted to
-	 * platform_drivers, this exception can be removed.
-	 */
-	if (bus == &platform_bus_type)
-		return of_register_platform_driver(drv);
-
-	/* register with core */
-	drv->driver.bus = bus;
-	return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL(of_register_driver);
-
-void of_unregister_driver(struct of_platform_driver *drv)
-{
-	if (drv->driver.bus == &platform_bus_type)
-		of_unregister_platform_driver(drv);
-	else
-		driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(of_unregister_driver);
-
 #if !defined(CONFIG_SPARC)
 /*
  * The following routines scan a subtree and registers a device for
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 59f5544..b8ef8dd 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -258,8 +258,10 @@ op_add_sample(struct oprofile_cpu_buffer *cpu_buf,
  */
 static int
 log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
-	   unsigned long backtrace, int is_kernel, unsigned long event)
+	   unsigned long backtrace, int is_kernel, unsigned long event,
+	   struct task_struct *task)
 {
+	struct task_struct *tsk = task ? task : current;
 	cpu_buf->sample_received++;
 
 	if (pc == ESCAPE_CODE) {
@@ -267,7 +269,7 @@ log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
 		return 0;
 	}
 
-	if (op_add_code(cpu_buf, backtrace, is_kernel, current))
+	if (op_add_code(cpu_buf, backtrace, is_kernel, tsk))
 		goto fail;
 
 	if (op_add_sample(cpu_buf, pc, event))
@@ -292,7 +294,8 @@ static inline void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)
 
 static inline void
 __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
-			  unsigned long event, int is_kernel)
+			  unsigned long event, int is_kernel,
+			  struct task_struct *task)
 {
 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
 	unsigned long backtrace = oprofile_backtrace_depth;
@@ -301,7 +304,7 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
 	 * if log_sample() fail we can't backtrace since we lost the
 	 * source of this event
 	 */
-	if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event))
+	if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event, task))
 		/* failed */
 		return;
 
@@ -313,10 +316,17 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
 	oprofile_end_trace(cpu_buf);
 }
 
+void oprofile_add_ext_hw_sample(unsigned long pc, struct pt_regs * const regs,
+				unsigned long event, int is_kernel,
+				struct task_struct *task)
+{
+	__oprofile_add_ext_sample(pc, regs, event, is_kernel, task);
+}
+
 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
 			     unsigned long event, int is_kernel)
 {
-	__oprofile_add_ext_sample(pc, regs, event, is_kernel);
+	__oprofile_add_ext_sample(pc, regs, event, is_kernel, NULL);
 }
 
 void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
@@ -332,7 +342,7 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
 		pc = ESCAPE_CODE; /* as this causes an early return. */
 	}
 
-	__oprofile_add_ext_sample(pc, regs, event, is_kernel);
+	__oprofile_add_ext_sample(pc, regs, event, is_kernel, NULL);
 }
 
 /*
@@ -403,7 +413,7 @@ int oprofile_write_commit(struct op_entry *entry)
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
 {
 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
-	log_sample(cpu_buf, pc, 0, is_kernel, event);
+	log_sample(cpu_buf, pc, 0, is_kernel, event, NULL);
 }
 
 void oprofile_add_trace(unsigned long pc)
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
index 0107251..3ef4462 100644
--- a/drivers/oprofile/timer_int.c
+++ b/drivers/oprofile/timer_int.c
@@ -97,7 +97,7 @@ static struct notifier_block __refdata oprofile_cpu_notifier = {
 	.notifier_call = oprofile_cpu_notify,
 };
 
-int __init oprofile_timer_init(struct oprofile_operations *ops)
+int oprofile_timer_init(struct oprofile_operations *ops)
 {
 	int rc;
 
@@ -113,7 +113,7 @@ int __init oprofile_timer_init(struct oprofile_operations *ops)
 	return 0;
 }
 
-void __exit oprofile_timer_exit(void)
+void oprofile_timer_exit(void)
 {
 	unregister_hotcpu_notifier(&oprofile_cpu_notifier);
 }
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index 9383063..bcd5d54 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -296,25 +296,25 @@ static struct pci_port_ops dino_port_ops = {
 	.outl	= dino_out32
 };
 
-static void dino_mask_irq(unsigned int irq)
+static void dino_mask_irq(struct irq_data *d)
 {
-	struct dino_device *dino_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
+	struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 
-	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
+	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq);
 
 	/* Clear the matching bit in the IMR register */
 	dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
 	__raw_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR);
 }
 
-static void dino_unmask_irq(unsigned int irq)
+static void dino_unmask_irq(struct irq_data *d)
 {
-	struct dino_device *dino_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
+	struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 	u32 tmp;
 
-	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
+	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq);
 
 	/*
 	** clear pending IRQ bits
@@ -346,9 +346,9 @@ static void dino_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip dino_interrupt_type = {
-	.name	= "GSC-PCI",
-	.unmask	= dino_unmask_irq,
-	.mask	= dino_mask_irq,
+	.name		= "GSC-PCI",
+	.irq_unmask	= dino_unmask_irq,
+	.irq_mask	= dino_mask_irq,
 };
 
 
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index e860038..deeec32 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -144,8 +144,9 @@ static unsigned int eisa_irq_level __read_mostly; /* default to edge triggered *
 
 
 /* called by free irq */
-static void eisa_mask_irq(unsigned int irq)
+static void eisa_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 
 	EISA_DBG("disable irq %d\n", irq);
@@ -164,8 +165,9 @@ static void eisa_mask_irq(unsigned int irq)
 }
 
 /* called by request irq */
-static void eisa_unmask_irq(unsigned int irq)
+static void eisa_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 	EISA_DBG("enable irq %d\n", irq);
 		
@@ -183,9 +185,9 @@ static void eisa_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip eisa_interrupt_type = {
-	.name	=	"EISA",
-	.unmask	=	eisa_unmask_irq,
-	.mask	=	eisa_mask_irq,
+	.name		=	"EISA",
+	.irq_unmask	=	eisa_unmask_irq,
+	.irq_mask	=	eisa_mask_irq,
 };
 
 static irqreturn_t eisa_irq(int wax_irq, void *intr_dev)
diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
index 772b193..ef31080 100644
--- a/drivers/parisc/gsc.c
+++ b/drivers/parisc/gsc.c
@@ -105,13 +105,13 @@ int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit)
 	return NO_IRQ;
 }
 
-static void gsc_asic_mask_irq(unsigned int irq)
+static void gsc_asic_mask_irq(struct irq_data *d)
 {
-	struct gsc_asic *irq_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
+	struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32);
 	u32 imr;
 
-	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq,
+	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq,
 			irq_dev->name, imr);
 
 	/* Disable the IRQ line by clearing the bit in the IMR */
@@ -120,13 +120,13 @@ static void gsc_asic_mask_irq(unsigned int irq)
 	gsc_writel(imr, irq_dev->hpa + OFFSET_IMR);
 }
 
-static void gsc_asic_unmask_irq(unsigned int irq)
+static void gsc_asic_unmask_irq(struct irq_data *d)
 {
-	struct gsc_asic *irq_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
+	struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32);
 	u32 imr;
 
-	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq,
+	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq,
 			irq_dev->name, imr);
 
 	/* Enable the IRQ line by setting the bit in the IMR */
@@ -140,9 +140,9 @@ static void gsc_asic_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip gsc_asic_interrupt_type = {
-	.name	=	"GSC-ASIC",
-	.unmask	=	gsc_asic_unmask_irq,
-	.mask	=	gsc_asic_mask_irq,
+	.name		=	"GSC-ASIC",
+	.irq_unmask	=	gsc_asic_unmask_irq,
+	.irq_mask	=	gsc_asic_mask_irq,
 };
 
 int gsc_assign_irq(struct irq_chip *type, void *data)
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
index 0327894..95930d0 100644
--- a/drivers/parisc/iosapic.c
+++ b/drivers/parisc/iosapic.c
@@ -615,10 +615,10 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
 }
 
 
-static void iosapic_mask_irq(unsigned int irq)
+static void iosapic_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 	u32 d0, d1;
 
 	spin_lock_irqsave(&iosapic_lock, flags);
@@ -628,9 +628,9 @@ static void iosapic_mask_irq(unsigned int irq)
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
 
-static void iosapic_unmask_irq(unsigned int irq)
+static void iosapic_unmask_irq(struct irq_data *d)
 {
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 	u32 d0, d1;
 
 	/* data is initialized by fixup_irq */
@@ -666,34 +666,34 @@ printk("\n");
 	 * enables their IRQ. It can lead to "interesting" race conditions
 	 * in the driver initialization sequence.
 	 */
-	DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq,
+	DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq,
 			vi->eoi_addr, vi->eoi_data);
 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
 }
 
-static void iosapic_eoi_irq(unsigned int irq)
+static void iosapic_eoi_irq(struct irq_data *d)
 {
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 
 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
-	cpu_eoi_irq(irq);
+	cpu_eoi_irq(d);
 }
 
 #ifdef CONFIG_SMP
-static int iosapic_set_affinity_irq(unsigned int irq,
-				     const struct cpumask *dest)
+static int iosapic_set_affinity_irq(struct irq_data *d,
+				    const struct cpumask *dest, bool force)
 {
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 	u32 d0, d1, dummy_d0;
 	unsigned long flags;
 	int dest_cpu;
 
-	dest_cpu = cpu_check_affinity(irq, dest);
+	dest_cpu = cpu_check_affinity(d, dest);
 	if (dest_cpu < 0)
 		return -1;
 
-	cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
-	vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
+	cpumask_copy(d->affinity, cpumask_of(dest_cpu));
+	vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	/* d1 contains the destination CPU, so only want to set that
@@ -708,13 +708,13 @@ static int iosapic_set_affinity_irq(unsigned int irq,
 #endif
 
 static struct irq_chip iosapic_interrupt_type = {
-	.name	=	"IO-SAPIC-level",
-	.unmask	=	iosapic_unmask_irq,
-	.mask	=	iosapic_mask_irq,
-	.ack	=	cpu_ack_irq,
-	.eoi	=	iosapic_eoi_irq,
+	.name		=	"IO-SAPIC-level",
+	.irq_unmask	=	iosapic_unmask_irq,
+	.irq_mask	=	iosapic_mask_irq,
+	.irq_ack	=	cpu_ack_irq,
+	.irq_eoi	=	iosapic_eoi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity =	iosapic_set_affinity_irq,
+	.irq_set_affinity =	iosapic_set_affinity_irq,
 #endif
 };
 
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index 2824153..a4d8ff6 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -286,8 +286,9 @@ superio_init(struct pci_dev *pcidev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init);
 
-static void superio_mask_irq(unsigned int irq)
+static void superio_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	u8 r8;
 
 	if ((irq < 1) || (irq == 2) || (irq > 7)) {
@@ -303,8 +304,9 @@ static void superio_mask_irq(unsigned int irq)
 	outb (r8,IC_PIC1+1);
 }
 
-static void superio_unmask_irq(unsigned int irq)
+static void superio_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	u8 r8;
 
 	if ((irq < 1) || (irq == 2) || (irq > 7)) {
@@ -320,9 +322,9 @@ static void superio_unmask_irq(unsigned int irq)
 }
 
 static struct irq_chip superio_interrupt_type = {
-	.name	=	SUPERIO,
-	.unmask	=	superio_unmask_irq,
-	.mask	=	superio_mask_irq,
+	.name		=	SUPERIO,
+	.irq_unmask	=	superio_unmask_irq,
+	.irq_mask	=	superio_mask_irq,
 };
 
 #ifdef DEBUG_SUPERIO_INIT
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 55ba118..910c5a2 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -286,7 +286,7 @@ static struct parport_operations parport_sunbpp_ops =
 	.owner		= THIS_MODULE,
 };
 
-static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bpp_probe(struct platform_device *op)
 {
 	struct parport_operations *ops;
 	struct bpp_regs __iomem *regs;
@@ -381,7 +381,7 @@ static const struct of_device_id bpp_match[] = {
 
 MODULE_DEVICE_TABLE(of, bpp_match);
 
-static struct of_platform_driver bpp_sbus_driver = {
+static struct platform_driver bpp_sbus_driver = {
 	.driver = {
 		.name = "bpp",
 		.owner = THIS_MODULE,
@@ -393,12 +393,12 @@ static struct of_platform_driver bpp_sbus_driver = {
 
 static int __init parport_sunbpp_init(void)
 {
-	return of_register_platform_driver(&bpp_sbus_driver);
+	return platform_driver_register(&bpp_sbus_driver);
 }
 
 static void __exit parport_sunbpp_exit(void)
 {
-	of_unregister_platform_driver(&bpp_sbus_driver);
+	platform_driver_unregister(&bpp_sbus_driver);
 }
 
 MODULE_AUTHOR("Derrick J Brashear");
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index a9523fd..c8ff646 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -87,3 +87,5 @@ config PCI_IOAPIC
 	depends on ACPI
 	depends on HOTPLUG
 	default y
+
+select NLS if (DMI || ACPI)
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 98e6fdf..98d61c8 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 obj-$(CONFIG_X86) += setup-bus.o
 obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
 obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
 obj-$(CONFIG_PARISC) += setup-bus.o
 obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
 obj-$(CONFIG_PPC) += setup-bus.o
@@ -53,8 +54,9 @@ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
 
 #
 # ACPI Related PCI FW Functions
+# ACPI _DSM provided firmware instance and string name
 #
-obj-$(CONFIG_ACPI)    += pci-acpi.o
+obj-$(CONFIG_ACPI)    += pci-acpi.o pci-label.o
 
 # SMBIOS provided firmware instance and labels
 obj-$(CONFIG_DMI)    += pci-label.o
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index cb23aa2..e610cfe 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -212,6 +212,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
 
 	pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
 	if (pdev) {
+		pdev->current_state = PCI_D0;
 		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 		pci_dev_put(pdev);
 	}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 88246dd..d86ea8b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -431,7 +431,7 @@ static void pci_device_shutdown(struct device *dev)
 	pci_msix_shutdown(pci_dev);
 }
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 
 /* Auxiliary functions used for system resume and run-time resume. */
 
@@ -1059,7 +1059,7 @@ static int pci_pm_runtime_idle(struct device *dev)
 
 #endif /* !CONFIG_PM_RUNTIME */
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 
 const struct dev_pm_ops pci_dev_pm_ops = {
 	.prepare = pci_pm_prepare,
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c
index 90c0a72..77cb2a1 100644
--- a/drivers/pci/pci-label.c
+++ b/drivers/pci/pci-label.c
@@ -5,6 +5,13 @@
  * by Narendra K <Narendra_K@dell.com>,
  * Jordan Hargrave <Jordan_Hargrave@dell.com>
  *
+ * PCI Firmware Specification Revision 3.1 section 4.6.7 (DSM for Naming a
+ * PCI or PCI Express Device Under Operating Systems) defines an instance
+ * number and string name. This code retrieves them and exports them to sysfs.
+ * If the system firmware does not provide the ACPI _DSM (Device Specific
+ * Method), then the SMBIOS type 41 instance number and string is exported to
+ * sysfs.
+ *
  * SMBIOS defines type 41 for onboard pci devices. This code retrieves
  * the instance number and string from the type 41 record and exports
  * it to sysfs.
@@ -19,8 +26,29 @@
 #include <linux/pci_ids.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/nls.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <acpi/acpi_bus.h>
 #include "pci.h"
 
+#define	DEVICE_LABEL_DSM	0x07
+
+#ifndef CONFIG_DMI
+
+static inline int
+pci_create_smbiosname_file(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline void
+pci_remove_smbiosname_file(struct pci_dev *pdev)
+{
+}
+
+#else
+
 enum smbios_attr_enum {
 	SMBIOS_ATTR_NONE = 0,
 	SMBIOS_ATTR_LABEL_SHOW,
@@ -120,9 +148,7 @@ static struct attribute_group smbios_attr_group = {
 static int
 pci_create_smbiosname_file(struct pci_dev *pdev)
 {
-	if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group))
-		return 0;
-	return -ENODEV;
+	return sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group);
 }
 
 static void
@@ -131,13 +157,227 @@ pci_remove_smbiosname_file(struct pci_dev *pdev)
 	sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);
 }
 
+#endif
+
+#ifndef CONFIG_ACPI
+
+static inline int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline bool
+device_has_dsm(struct device *dev)
+{
+	return false;
+}
+
+#else
+
+static const char device_label_dsm_uuid[] = {
+	0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
+	0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
+};
+
+enum acpi_attr_enum {
+	ACPI_ATTR_NONE = 0,
+	ACPI_ATTR_LABEL_SHOW,
+	ACPI_ATTR_INDEX_SHOW,
+};
+
+static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
+{
+	int len;
+	len = utf16s_to_utf8s((const wchar_t *)obj->
+			      package.elements[1].string.pointer,
+			      obj->package.elements[1].string.length,
+			      UTF16_LITTLE_ENDIAN,
+			      buf, PAGE_SIZE);
+	buf[len] = '\n';
+}
+
+static int
+dsm_get_label(acpi_handle handle, int func,
+	      struct acpi_buffer *output,
+	      char *buf, enum acpi_attr_enum attribute)
+{
+	struct acpi_object_list input;
+	union acpi_object params[4];
+	union acpi_object *obj;
+	int len = 0;
+
+	int err;
+
+	input.count = 4;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(device_label_dsm_uuid);
+	params[0].buffer.pointer = (char *)device_label_dsm_uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = 0x02;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = func;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+
+	err = acpi_evaluate_object(handle, "_DSM", &input, output);
+	if (err)
+		return -1;
+
+	obj = (union acpi_object *)output->pointer;
+
+	switch (obj->type) {
+	case ACPI_TYPE_PACKAGE:
+		if (obj->package.count != 2)
+			break;
+		len = obj->package.elements[0].integer.value;
+		if (buf) {
+			if (attribute == ACPI_ATTR_INDEX_SHOW)
+				scnprintf(buf, PAGE_SIZE, "%llu\n",
+				obj->package.elements[0].integer.value);
+			else if (attribute == ACPI_ATTR_LABEL_SHOW)
+				dsm_label_utf16s_to_utf8s(obj, buf);
+			kfree(output->pointer);
+			return strlen(buf);
+		}
+		kfree(output->pointer);
+		return len;
+	break;
+	default:
+		kfree(output->pointer);
+	}
+	return -1;
+}
+
+static bool
+device_has_dsm(struct device *dev)
+{
+	acpi_handle handle;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return FALSE;
+
+	if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL,
+			  ACPI_ATTR_NONE) > 0)
+		return TRUE;
+
+	return FALSE;
+}
+
+static mode_t
+acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n)
+{
+	struct device *dev;
+
+	dev = container_of(kobj, struct device, kobj);
+
+	if (device_has_dsm(dev))
+		return S_IRUGO;
+
+	return 0;
+}
+
+static ssize_t
+acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return -1;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, buf, ACPI_ATTR_LABEL_SHOW);
+
+	if (length < 1)
+		return -1;
+
+	return length;
+}
+
+static ssize_t
+acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return -1;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, buf, ACPI_ATTR_INDEX_SHOW);
+
+	if (length < 0)
+		return -1;
+
+	return length;
+
+}
+
+static struct device_attribute acpi_attr_label = {
+	.attr = {.name = "label", .mode = 0444},
+	.show = acpilabel_show,
+};
+
+static struct device_attribute acpi_attr_index = {
+	.attr = {.name = "acpi_index", .mode = 0444},
+	.show = acpiindex_show,
+};
+
+static struct attribute *acpi_attributes[] = {
+	&acpi_attr_label.attr,
+	&acpi_attr_index.attr,
+	NULL,
+};
+
+static struct attribute_group acpi_attr_group = {
+	.attrs = acpi_attributes,
+	.is_visible = acpi_index_string_exist,
+};
+
+static int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return sysfs_create_group(&pdev->dev.kobj, &acpi_attr_group);
+}
+
+static int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	sysfs_remove_group(&pdev->dev.kobj, &acpi_attr_group);
+	return 0;
+}
+#endif
+
 void pci_create_firmware_label_files(struct pci_dev *pdev)
 {
-	if (!pci_create_smbiosname_file(pdev))
-		;
+	if (device_has_dsm(&pdev->dev))
+		pci_create_acpi_index_label_files(pdev);
+	else
+		pci_create_smbiosname_file(pdev);
 }
 
 void pci_remove_firmware_label_files(struct pci_dev *pdev)
 {
-	pci_remove_smbiosname_file(pdev);
+	if (device_has_dsm(&pdev->dev))
+		pci_remove_acpi_index_label_files(pdev);
+	else
+		pci_remove_smbiosname_file(pdev);
 }
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index ea25e5b..c85438a 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1088,7 +1088,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
 		attr->write = write_vpd_attr;
 		retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
 		if (retval) {
-			kfree(dev->vpd->attr);
+			kfree(attr);
 			return retval;
 		}
 		dev->vpd->attr = attr;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index f69d6e0..a6ec200 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -11,7 +11,7 @@
 extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
-#ifndef CONFIG_DMI
+#if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
 static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
 { return; }
 static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index b3cf622..f62079f 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -27,6 +27,10 @@
 #include <linux/stddef.h>
 #include "aerdrv.h"
 
+/* Override the existing corrected and uncorrected error masks */
+static int aer_mask_override;
+module_param(aer_mask_override, bool, 0);
+
 struct aer_error_inj {
 	u8 bus;
 	u8 dev;
@@ -322,7 +326,7 @@ static int aer_inject(struct aer_error_inj *einj)
 	unsigned long flags;
 	unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
 	int pos_cap_err, rp_pos_cap_err;
-	u32 sever, cor_mask, uncor_mask;
+	u32 sever, cor_mask, uncor_mask, cor_mask_orig, uncor_mask_orig;
 	int ret = 0;
 
 	dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
@@ -361,6 +365,18 @@ static int aer_inject(struct aer_error_inj *einj)
 		goto out_put;
 	}
 
+	if (aer_mask_override) {
+		cor_mask_orig = cor_mask;
+		cor_mask &= !(einj->cor_status);
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
+				       cor_mask);
+
+		uncor_mask_orig = uncor_mask;
+		uncor_mask &= !(einj->uncor_status);
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
+				       uncor_mask);
+	}
+
 	spin_lock_irqsave(&inject_lock, flags);
 
 	err = __find_aer_error_by_dev(dev);
@@ -378,14 +394,16 @@ static int aer_inject(struct aer_error_inj *einj)
 	err->header_log2 = einj->header_log2;
 	err->header_log3 = einj->header_log3;
 
-	if (einj->cor_status && !(einj->cor_status & ~cor_mask)) {
+	if (!aer_mask_override && einj->cor_status &&
+	    !(einj->cor_status & ~cor_mask)) {
 		ret = -EINVAL;
 		printk(KERN_WARNING "The correctable error(s) is masked "
 				"by device\n");
 		spin_unlock_irqrestore(&inject_lock, flags);
 		goto out_put;
 	}
-	if (einj->uncor_status && !(einj->uncor_status & ~uncor_mask)) {
+	if (!aer_mask_override && einj->uncor_status &&
+	    !(einj->uncor_status & ~uncor_mask)) {
 		ret = -EINVAL;
 		printk(KERN_WARNING "The uncorrectable error(s) is masked "
 				"by device\n");
@@ -425,6 +443,13 @@ static int aer_inject(struct aer_error_inj *einj)
 	}
 	spin_unlock_irqrestore(&inject_lock, flags);
 
+	if (aer_mask_override) {
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
+				       cor_mask_orig);
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
+				       uncor_mask_orig);
+	}
+
 	ret = pci_bus_set_aer_ops(dev->bus);
 	if (ret)
 		goto out_put;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index c84900d..44cbbba 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -764,6 +764,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 		if (pci_find_bus(pci_domain_nr(bus), max+1))
 			goto out;
 		child = pci_add_new_bus(bus, dev, ++max);
+		if (!child)
+			goto out;
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->secondary)   <<  8)
@@ -777,7 +779,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
 			buses &= ~0xff000000;
 			buses |= CARDBUS_LATENCY_TIMER << 24;
 		}
-			
+
 		/*
 		 * We need to blast all three values with a single write.
 		 */
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 53a786f..bd80f63 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -533,6 +533,17 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	quirk_piix4_acpi);
 
+#define ICH_PMBASE	0x40
+#define ICH_ACPI_CNTL	0x44
+#define  ICH4_ACPI_EN	0x10
+#define  ICH6_ACPI_EN	0x80
+#define ICH4_GPIOBASE	0x58
+#define ICH4_GPIO_CNTL	0x5c
+#define  ICH4_GPIO_EN	0x10
+#define ICH6_GPIOBASE	0x48
+#define ICH6_GPIO_CNTL	0x4c
+#define  ICH6_GPIO_EN	0x10
+
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
  *	0x40 (128 bytes of ACPI, GPIO & TCO registers)
@@ -541,12 +552,33 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	qui
 static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
+	/*
+	 * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict
+	 * with low legacy (and fixed) ports. We don't know the decoding
+	 * priority and can't tell whether the legacy device or the one created
+	 * here is really at that address.  This happens on boards with broken
+	 * BIOSes.
+	*/
+
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH4_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH4 ACPI/GPIO/TCO");
+	}
 
-	pci_read_config_dword(dev, 0x58, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
+	pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH4_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
+	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi);
@@ -562,12 +594,25 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_ESB_1,		qui
 static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH6_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH6 ACPI/GPIO/TCO");
+	}
 
-	pci_read_config_dword(dev, 0x48, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+	pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH6_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
+	}
 }
 
 static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
@@ -2618,58 +2663,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
 
 #endif /* CONFIG_PCI_MSI */
 
-#ifdef CONFIG_PCI_IOV
-
-/*
- * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
- * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
- * old Flash Memory Space.
- */
-static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
-{
-	int pos, flags;
-	u32 bar, start, size;
-
-	if (PAGE_SIZE > 0x10000)
-		return;
-
-	flags = pci_resource_flags(dev, 0);
-	if ((flags & PCI_BASE_ADDRESS_SPACE) !=
-			PCI_BASE_ADDRESS_SPACE_MEMORY ||
-	    (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
-			PCI_BASE_ADDRESS_MEM_TYPE_32)
-		return;
-
-	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
-	if (!pos)
-		return;
-
-	pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
-	if (bar & PCI_BASE_ADDRESS_MEM_MASK)
-		return;
-
-	start = pci_resource_start(dev, 1);
-	size = pci_resource_len(dev, 1);
-	if (!start || size != 0x400000 || start & (size - 1))
-		return;
-
-	pci_resource_flags(dev, 1) = 0;
-	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
-
-	dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov);
-
-#endif	/* CONFIG_PCI_IOV */
-
 /* Allow manual resource allocation for PCI hotplug bridges
  * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
  * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6),
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 66cb8f4..89d0a6a 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -33,11 +33,32 @@ struct resource_list_x {
 	struct pci_dev *dev;
 	resource_size_t start;
 	resource_size_t end;
+	resource_size_t add_size;
 	unsigned long flags;
 };
 
-static void add_to_failed_list(struct resource_list_x *head,
-				 struct pci_dev *dev, struct resource *res)
+#define free_list(type, head) do {                      \
+	struct type *list, *tmp;			\
+	for (list = (head)->next; list;) {		\
+		tmp = list;				\
+		list = list->next;			\
+		kfree(tmp);				\
+	}						\
+	(head)->next = NULL;				\
+} while (0)
+
+/**
+ * add_to_list() - add a new resource tracker to the list
+ * @head:	Head of the list
+ * @dev:	device corresponding to which the resource
+ *		belongs
+ * @res:	The resource to be tracked
+ * @add_size:	additional size to be optionally added
+ *              to the resource
+ */
+static void add_to_list(struct resource_list_x *head,
+		 struct pci_dev *dev, struct resource *res,
+		 resource_size_t add_size)
 {
 	struct resource_list_x *list = head;
 	struct resource_list_x *ln = list->next;
@@ -45,7 +66,7 @@ static void add_to_failed_list(struct resource_list_x *head,
 
 	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
 	if (!tmp) {
-		pr_warning("add_to_failed_list: kmalloc() failed!\n");
+		pr_warning("add_to_list: kmalloc() failed!\n");
 		return;
 	}
 
@@ -55,20 +76,14 @@ static void add_to_failed_list(struct resource_list_x *head,
 	tmp->start = res->start;
 	tmp->end = res->end;
 	tmp->flags = res->flags;
+	tmp->add_size = add_size;
 	list->next = tmp;
 }
 
-static void free_failed_list(struct resource_list_x *head)
+static void add_to_failed_list(struct resource_list_x *head,
+				struct pci_dev *dev, struct resource *res)
 {
-	struct resource_list_x *list, *tmp;
-
-	for (list = head->next; list;) {
-		tmp = list;
-		list = list->next;
-		kfree(tmp);
-	}
-
-	head->next = NULL;
+	add_to_list(head, dev, res, 0);
 }
 
 static void __dev_sort_resources(struct pci_dev *dev,
@@ -91,18 +106,88 @@ static void __dev_sort_resources(struct pci_dev *dev,
 	pdev_sort_resources(dev, head);
 }
 
-static void __assign_resources_sorted(struct resource_list *head,
-				 struct resource_list_x *fail_head)
+static inline void reset_resource(struct resource *res)
+{
+	res->start = 0;
+	res->end = 0;
+	res->flags = 0;
+}
+
+/**
+ * adjust_resources_sorted() - satisfy any additional resource requests
+ *
+ * @add_head : head of the list tracking requests requiring additional
+ *             resources
+ * @head     : head of the list tracking requests with allocated
+ *             resources
+ *
+ * Walk through each element of the add_head and try to procure
+ * additional resources for the element, provided the element
+ * is in the head list.
+ */
+static void adjust_resources_sorted(struct resource_list_x *add_head,
+		struct resource_list *head)
 {
 	struct resource *res;
-	struct resource_list *list, *tmp;
+	struct resource_list_x *list, *tmp, *prev;
+	struct resource_list *hlist;
+	resource_size_t add_size;
 	int idx;
 
-	for (list = head->next; list;) {
+	prev = add_head;
+	for (list = add_head->next; list;) {
 		res = list->res;
+		/* skip resource that has been reset */
+		if (!res->flags)
+			goto out;
+
+		/* skip this resource if not found in head list */
+		for (hlist = head->next; hlist && hlist->res != res;
+				hlist = hlist->next);
+		if (!hlist) { /* just skip */
+			prev = list;
+			list = list->next;
+			continue;
+		}
+
 		idx = res - &list->dev->resource[0];
+		add_size=list->add_size;
+		if (!resource_size(res) && add_size) {
+			 res->end = res->start + add_size - 1;
+			 if(pci_assign_resource(list->dev, idx))
+				reset_resource(res);
+		} else if (add_size) {
+			adjust_resource(res, res->start,
+				resource_size(res) + add_size);
+		}
+out:
+		tmp = list;
+		prev->next = list = list->next;
+		kfree(tmp);
+	}
+}
+
+/**
+ * assign_requested_resources_sorted() - satisfy resource requests
+ *
+ * @head : head of the list tracking requests for resources
+ * @failed_list : head of the list tracking requests that could
+ *		not be allocated
+ *
+ * Satisfy resource requests of each element in the list. Add
+ * requests that could not satisfied to the failed_list.
+ */
+static void assign_requested_resources_sorted(struct resource_list *head,
+				 struct resource_list_x *fail_head)
+{
+	struct resource *res;
+	struct resource_list *list;
+	int idx;
 
-		if (pci_assign_resource(list->dev, idx)) {
+	for (list = head->next; list; list = list->next) {
+		res = list->res;
+		idx = res - &list->dev->resource[0];
+		if (resource_size(res) && pci_assign_resource(list->dev, idx)) {
 			if (fail_head && !pci_is_root_bus(list->dev->bus)) {
 				/*
 				 * if the failed res is for ROM BAR, and it will
@@ -112,16 +197,25 @@ static void __assign_resources_sorted(struct resource_list *head,
 				      (!(res->flags & IORESOURCE_ROM_ENABLE))))
 					add_to_failed_list(fail_head, list->dev, res);
 			}
-			res->start = 0;
-			res->end = 0;
-			res->flags = 0;
+			reset_resource(res);
 		}
-		tmp = list;
-		list = list->next;
-		kfree(tmp);
 	}
 }
 
+static void __assign_resources_sorted(struct resource_list *head,
+				 struct resource_list_x *add_head,
+				 struct resource_list_x *fail_head)
+{
+	/* Satisfy the must-have resource requests */
+	assign_requested_resources_sorted(head, fail_head);
+
+	/* Try to satisfy any additional nice-to-have resource
+		requests */
+	if (add_head)
+		adjust_resources_sorted(add_head, head);
+	free_list(resource_list, head);
+}
+
 static void pdev_assign_resources_sorted(struct pci_dev *dev,
 				 struct resource_list_x *fail_head)
 {
@@ -129,11 +223,12 @@ static void pdev_assign_resources_sorted(struct pci_dev *dev,
 
 	head.next = NULL;
 	__dev_sort_resources(dev, &head);
-	__assign_resources_sorted(&head, fail_head);
+	__assign_resources_sorted(&head, NULL, fail_head);
 
 }
 
 static void pbus_assign_resources_sorted(const struct pci_bus *bus,
+					 struct resource_list_x *add_head,
 					 struct resource_list_x *fail_head)
 {
 	struct pci_dev *dev;
@@ -143,7 +238,7 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus,
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		__dev_sort_resources(dev, &head);
 
-	__assign_resources_sorted(&head, fail_head);
+	__assign_resources_sorted(&head, add_head, fail_head);
 }
 
 void pci_setup_cardbus(struct pci_bus *bus)
@@ -404,15 +499,62 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
 	return NULL;
 }
 
-/* Sizing the IO windows of the PCI-PCI bridge is trivial,
-   since these windows have 4K granularity and the IO ranges
-   of non-bridge PCI devices are limited to 256 bytes.
-   We must be careful with the ISA aliasing though. */
-static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
+static resource_size_t calculate_iosize(resource_size_t size,
+		resource_size_t min_size,
+		resource_size_t size1,
+		resource_size_t old_size,
+		resource_size_t align)
+{
+	if (size < min_size)
+		size = min_size;
+	if (old_size == 1 )
+		old_size = 0;
+	/* To be fixed in 2.5: we should have sort of HAVE_ISA
+	   flag in the struct pci_bus. */
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+	size = (size & 0xff) + ((size & ~0xffUL) << 2);
+#endif
+	size = ALIGN(size + size1, align);
+	if (size < old_size)
+		size = old_size;
+	return size;
+}
+
+static resource_size_t calculate_memsize(resource_size_t size,
+		resource_size_t min_size,
+		resource_size_t size1,
+		resource_size_t old_size,
+		resource_size_t align)
+{
+	if (size < min_size)
+		size = min_size;
+	if (old_size == 1 )
+		old_size = 0;
+	if (size < old_size)
+		size = old_size;
+	size = ALIGN(size + size1, align);
+	return size;
+}
+
+/**
+ * pbus_size_io() - size the io window of a given bus
+ *
+ * @bus : the bus
+ * @min_size : the minimum io window that must to be allocated
+ * @add_size : additional optional io window
+ * @add_head : track the additional io window on this list
+ *
+ * Sizing the IO windows of the PCI-PCI bridge is trivial,
+ * since these windows have 4K granularity and the IO ranges
+ * of non-bridge PCI devices are limited to 256 bytes.
+ * We must be careful with the ISA aliasing though.
+ */
+static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
+		resource_size_t add_size, struct resource_list_x *add_head)
 {
 	struct pci_dev *dev;
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
-	unsigned long size = 0, size1 = 0, old_size;
+	unsigned long size = 0, size0 = 0, size1 = 0;
 
 	if (!b_res)
  		return;
@@ -435,20 +577,12 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
 				size1 += r_size;
 		}
 	}
-	if (size < min_size)
-		size = min_size;
-	old_size = resource_size(b_res);
-	if (old_size == 1)
-		old_size = 0;
-/* To be fixed in 2.5: we should have sort of HAVE_ISA
-   flag in the struct pci_bus. */
-#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
-	size = (size & 0xff) + ((size & ~0xffUL) << 2);
-#endif
-	size = ALIGN(size + size1, 4096);
-	if (size < old_size)
-		size = old_size;
-	if (!size) {
+	size0 = calculate_iosize(size, min_size, size1,
+			resource_size(b_res), 4096);
+	size1 = !add_size? size0:
+		calculate_iosize(size, min_size+add_size, size1,
+			resource_size(b_res), 4096);
+	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
 				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
@@ -458,17 +592,30 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
 	}
 	/* Alignment of the IO window is always 4K */
 	b_res->start = 4096;
-	b_res->end = b_res->start + size - 1;
+	b_res->end = b_res->start + size0 - 1;
 	b_res->flags |= IORESOURCE_STARTALIGN;
+	if (size1 > size0 && add_head)
+		add_to_list(add_head, bus->self, b_res, size1-size0);
 }
 
-/* Calculate the size of the bus and minimal alignment which
-   guarantees that all child resources fit in this size. */
+/**
+ * pbus_size_mem() - size the memory window of a given bus
+ *
+ * @bus : the bus
+ * @min_size : the minimum memory window that must to be allocated
+ * @add_size : additional optional memory window
+ * @add_head : track the additional memory window on this list
+ *
+ * Calculate the size of the bus and minimal alignment which
+ * guarantees that all child resources fit in this size.
+ */
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
-			 unsigned long type, resource_size_t min_size)
+			 unsigned long type, resource_size_t min_size,
+			resource_size_t add_size,
+			struct resource_list_x *add_head)
 {
 	struct pci_dev *dev;
-	resource_size_t min_align, align, size, old_size;
+	resource_size_t min_align, align, size, size0, size1;
 	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
@@ -516,14 +663,6 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			mem64_mask &= r->flags & IORESOURCE_MEM_64;
 		}
 	}
-	if (size < min_size)
-		size = min_size;
-	old_size = resource_size(b_res);
-	if (old_size == 1)
-		old_size = 0;
-	if (size < old_size)
-		size = old_size;
-
 	align = 0;
 	min_align = 0;
 	for (order = 0; order <= max_order; order++) {
@@ -537,8 +676,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size = ALIGN(size, min_align);
-	if (!size) {
+	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align);
+	size1 = !add_size ? size :
+		calculate_memsize(size, min_size+add_size, 0,
+				resource_size(b_res), align);
+	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
 				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
@@ -547,9 +689,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
 		return 1;
 	}
 	b_res->start = min_align;
-	b_res->end = size + min_align - 1;
-	b_res->flags |= IORESOURCE_STARTALIGN;
-	b_res->flags |= mem64_mask;
+	b_res->end = size0 + min_align - 1;
+	b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
+	if (size1 > size0 && add_head)
+		add_to_list(add_head, bus->self, b_res, size1-size0);
 	return 1;
 }
 
@@ -602,11 +745,12 @@ static void pci_bus_size_cardbus(struct pci_bus *bus)
 	}
 }
 
-void __ref pci_bus_size_bridges(struct pci_bus *bus)
+void __ref __pci_bus_size_bridges(struct pci_bus *bus,
+			struct resource_list_x *add_head)
 {
 	struct pci_dev *dev;
 	unsigned long mask, prefmask;
-	resource_size_t min_mem_size = 0, min_io_size = 0;
+	resource_size_t additional_mem_size = 0, additional_io_size = 0;
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		struct pci_bus *b = dev->subordinate;
@@ -620,7 +764,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
 
 		case PCI_CLASS_BRIDGE_PCI:
 		default:
-			pci_bus_size_bridges(b);
+			__pci_bus_size_bridges(b, add_head);
 			break;
 		}
 	}
@@ -637,11 +781,14 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
 	case PCI_CLASS_BRIDGE_PCI:
 		pci_bridge_check_ranges(bus);
 		if (bus->self->is_hotplug_bridge) {
-			min_io_size  = pci_hotplug_io_size;
-			min_mem_size = pci_hotplug_mem_size;
+			additional_io_size  = pci_hotplug_io_size;
+			additional_mem_size = pci_hotplug_mem_size;
 		}
+		/*
+		 * Follow thru
+		 */
 	default:
-		pbus_size_io(bus, min_io_size);
+		pbus_size_io(bus, 0, additional_io_size, add_head);
 		/* If the bridge supports prefetchable range, size it
 		   separately. If it doesn't, or its prefetchable window
 		   has already been allocated by arch code, try
@@ -649,30 +796,36 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
 		   resources. */
 		mask = IORESOURCE_MEM;
 		prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-		if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size))
+		if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head))
 			mask = prefmask; /* Success, size non-prefetch only. */
 		else
-			min_mem_size += min_mem_size;
-		pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size);
+			additional_mem_size += additional_mem_size;
+		pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head);
 		break;
 	}
 }
+
+void __ref pci_bus_size_bridges(struct pci_bus *bus)
+{
+	__pci_bus_size_bridges(bus, NULL);
+}
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
 static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
+					 struct resource_list_x *add_head,
 					 struct resource_list_x *fail_head)
 {
 	struct pci_bus *b;
 	struct pci_dev *dev;
 
-	pbus_assign_resources_sorted(bus, fail_head);
+	pbus_assign_resources_sorted(bus, add_head, fail_head);
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		b = dev->subordinate;
 		if (!b)
 			continue;
 
-		__pci_bus_assign_resources(b, fail_head);
+		__pci_bus_assign_resources(b, add_head, fail_head);
 
 		switch (dev->class >> 8) {
 		case PCI_CLASS_BRIDGE_PCI:
@@ -694,7 +847,7 @@ static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
 
 void __ref pci_bus_assign_resources(const struct pci_bus *bus)
 {
-	__pci_bus_assign_resources(bus, NULL);
+	__pci_bus_assign_resources(bus, NULL, NULL);
 }
 EXPORT_SYMBOL(pci_bus_assign_resources);
 
@@ -709,7 +862,7 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,
 	if (!b)
 		return;
 
-	__pci_bus_assign_resources(b, fail_head);
+	__pci_bus_assign_resources(b, NULL, fail_head);
 
 	switch (bridge->class >> 8) {
 	case PCI_CLASS_BRIDGE_PCI:
@@ -842,17 +995,21 @@ void __init
 pci_assign_unassigned_resources(void)
 {
 	struct pci_bus *bus;
-
+	struct resource_list_x add_list; /* list of resources that
+					want additional resources */
+	add_list.next = NULL;
 	/* Depth first, calculate sizes and alignments of all
 	   subordinate buses. */
 	list_for_each_entry(bus, &pci_root_buses, node) {
-		pci_bus_size_bridges(bus);
+		__pci_bus_size_bridges(bus, &add_list);
 	}
+
 	/* Depth last, allocate resources and update the hardware. */
 	list_for_each_entry(bus, &pci_root_buses, node) {
-		pci_bus_assign_resources(bus);
+		__pci_bus_assign_resources(bus, &add_list, NULL);
 		pci_enable_bridges(bus);
 	}
+	BUG_ON(add_list.next);
 
 	/* dump the resource on buses */
 	list_for_each_entry(bus, &pci_root_buses, node) {
@@ -882,7 +1039,7 @@ again:
 
 	if (tried_times >= 2) {
 		/* still fail, don't need to try more */
-		free_failed_list(&head);
+		free_list(resource_list_x, &head);
 		goto enable_all;
 	}
 
@@ -913,7 +1070,7 @@ again:
 
 		list = list->next;
 	}
-	free_failed_list(&head);
+	free_list(resource_list_x, &head);
 
 	goto again;
 
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index 3a5a6fc..492b7d8 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -243,7 +243,7 @@ struct pci_ops pcifront_bus_ops = {
 
 #ifdef CONFIG_PCI_MSI
 static int pci_frontend_enable_msix(struct pci_dev *dev,
-				    int **vector, int nvec)
+				    int vector[], int nvec)
 {
 	int err;
 	int i;
@@ -277,18 +277,24 @@ static int pci_frontend_enable_msix(struct pci_dev *dev,
 	if (likely(!err)) {
 		if (likely(!op.value)) {
 			/* we get the result */
-			for (i = 0; i < nvec; i++)
-				*(*vector+i) = op.msix_entries[i].vector;
-			return 0;
+			for (i = 0; i < nvec; i++) {
+				if (op.msix_entries[i].vector <= 0) {
+					dev_warn(&dev->dev, "MSI-X entry %d is invalid: %d!\n",
+						i, op.msix_entries[i].vector);
+					err = -EINVAL;
+					vector[i] = -1;
+					continue;
+				}
+				vector[i] = op.msix_entries[i].vector;
+			}
 		} else {
 			printk(KERN_DEBUG "enable msix get value %x\n",
 				op.value);
-			return op.value;
 		}
 	} else {
 		dev_err(&dev->dev, "enable msix get err %x\n", err);
-		return err;
 	}
+	return err;
 }
 
 static void pci_frontend_disable_msix(struct pci_dev *dev)
@@ -310,7 +316,7 @@ static void pci_frontend_disable_msix(struct pci_dev *dev)
 		dev_err(&dev->dev, "pci_disable_msix get err %x\n", err);
 }
 
-static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector)
+static int pci_frontend_enable_msi(struct pci_dev *dev, int vector[])
 {
 	int err;
 	struct xen_pci_op op = {
@@ -324,7 +330,13 @@ static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector)
 
 	err = do_pci_op(pdev, &op);
 	if (likely(!err)) {
-		*(*vector) = op.value;
+		vector[0] = op.value;
+		if (op.value <= 0) {
+			dev_warn(&dev->dev, "MSI entry is invalid: %d!\n",
+				op.value);
+			err = -EINVAL;
+			vector[0] = -1;
+		}
 	} else {
 		dev_err(&dev->dev, "pci frontend enable msi failed for dev "
 				    "%x:%x\n", op.bus, op.devfn);
@@ -733,8 +745,7 @@ static void free_pdev(struct pcifront_device *pdev)
 
 	pcifront_free_roots(pdev);
 
-	/*For PCIE_AER error handling job*/
-	flush_scheduled_work();
+	cancel_work_sync(&pdev->op_work);
 
 	if (pdev->irq >= 0)
 		unbind_from_irqhandler(pdev->irq, pdev);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 546d302..6defd4a 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -181,8 +181,7 @@ static struct pccard_operations electra_cf_ops = {
 	.set_mem_map		= electra_cf_set_mem_map,
 };
 
-static int __devinit electra_cf_probe(struct platform_device *ofdev,
-				      const struct of_device_id *match)
+static int __devinit electra_cf_probe(struct platform_device *ofdev)
 {
 	struct device *device = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -356,7 +355,7 @@ static const struct of_device_id electra_cf_match[] = {
 };
 MODULE_DEVICE_TABLE(of, electra_cf_match);
 
-static struct of_platform_driver electra_cf_driver = {
+static struct platform_driver electra_cf_driver = {
 	.driver = {
 		.name = (char *)driver_name,
 		.owner = THIS_MODULE,
@@ -368,13 +367,13 @@ static struct of_platform_driver electra_cf_driver = {
 
 static int __init electra_cf_init(void)
 {
-	return of_register_platform_driver(&electra_cf_driver);
+	return platform_driver_register(&electra_cf_driver);
 }
 module_init(electra_cf_init);
 
 static void __exit electra_cf_exit(void)
 {
-	of_unregister_platform_driver(&electra_cf_driver);
+	platform_driver_unregister(&electra_cf_driver);
 }
 module_exit(electra_cf_exit);
 
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 0db4827..271a590 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -1148,8 +1148,7 @@ static struct pccard_operations m8xx_services = {
 	.set_mem_map = m8xx_set_mem_map,
 };
 
-static int __init m8xx_probe(struct platform_device *ofdev,
-			     const struct of_device_id *match)
+static int __init m8xx_probe(struct platform_device *ofdev)
 {
 	struct pcmcia_win *w;
 	unsigned int i, m, hwirq;
@@ -1295,7 +1294,7 @@ static const struct of_device_id m8xx_pcmcia_match[] = {
 
 MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
 
-static struct of_platform_driver m8xx_pcmcia_driver = {
+static struct platform_driver m8xx_pcmcia_driver = {
 	.driver = {
 		.name = driver_name,
 		.owner = THIS_MODULE,
@@ -1307,12 +1306,12 @@ static struct of_platform_driver m8xx_pcmcia_driver = {
 
 static int __init m8xx_init(void)
 {
-	return of_register_platform_driver(&m8xx_pcmcia_driver);
+	return platform_driver_register(&m8xx_pcmcia_driver);
 }
 
 static void __exit m8xx_exit(void)
 {
-	of_unregister_platform_driver(&m8xx_pcmcia_driver);
+	platform_driver_unregister(&m8xx_pcmcia_driver);
 }
 
 module_init(m8xx_init);
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index a59af5b..222dfb7 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -138,6 +138,24 @@ config TC1100_WMI
 	  This is a driver for the WMI extensions (wireless and bluetooth power
 	  control) of the HP Compaq TC1100 tablet.
 
+config HP_ACCEL
+	tristate "HP laptop accelerometer"
+	depends on INPUT && ACPI
+	select SENSORS_LIS3LV02D
+	select NEW_LEDS
+	select LEDS_CLASS
+	help
+	  This driver provides support for the "Mobile Data Protection System 3D"
+	  or "3D DriveGuard" feature of HP laptops. On such systems the driver
+	  should load automatically (via ACPI alias).
+
+	  Support for a led indicating disk protection will be provided as
+	  hp::hddprotect. For more information on the feature, refer to
+	  Documentation/hwmon/lis3lv02d.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called hp_accel.
+
 config HP_WMI
 	tristate "HP WMI extras"
 	depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 4ec4ff8..299aefb 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_DELL_WMI)		+= dell-wmi.o
 obj-$(CONFIG_ACER_WMI)		+= acer-wmi.o
 obj-$(CONFIG_ACERHDF)		+= acerhdf.o
+obj-$(CONFIG_HP_ACCEL)		+= hp_accel.o
 obj-$(CONFIG_HP_WMI)		+= hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)	+= tc1100-wmi.o
 obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 38b34a7..c978470 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -39,7 +39,6 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-#include <linux/dmi.h>
 
 #include <acpi/acpi_drivers.h>
 
@@ -1032,6 +1031,7 @@ static int __devinit acer_backlight_init(struct device *dev)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = max_brightness;
 	bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
 				       &props);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index f3aa6a7..5a6f7d7 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -667,6 +667,7 @@ static int asus_backlight_init(struct asus_laptop *asus)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = 15;
+	props.type = BACKLIGHT_PLATFORM;
 
 	bd = backlight_device_register(ASUS_LAPTOP_FILE,
 				       &asus->platform_device->dev, asus,
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index fe49593..f503607 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -1507,6 +1507,7 @@ static int __init asus_acpi_init(void)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	asus_backlight_device = backlight_device_register("asus", NULL, NULL,
 							  &asus_backlight_data,
diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c
index 9111354..94f93b6 100644
--- a/drivers/platform/x86/classmate-laptop.c
+++ b/drivers/platform/x86/classmate-laptop.c
@@ -564,6 +564,7 @@ static int cmpc_ipml_add(struct acpi_device *acpi)
 		return -ENOMEM;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 7;
 	ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
 					     acpi->handle, &cmpc_bl_ops,
diff --git a/drivers/platform/x86/compal-laptop.c b/drivers/platform/x86/compal-laptop.c
index 034572b..eb95878 100644
--- a/drivers/platform/x86/compal-laptop.c
+++ b/drivers/platform/x86/compal-laptop.c
@@ -970,6 +970,7 @@ static int __init compal_init(void)
 	if (!acpi_video_backlight_support()) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = BACKLIGHT_LEVEL_MAX;
 		compalbl_device = backlight_device_register(DRIVER_NAME,
 							    NULL, NULL,
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index ad24ef3..de301aa 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -671,6 +671,7 @@ static int __init dell_init(void)
 	if (max_intensity) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = max_intensity;
 		dell_backlight_device = backlight_device_register("dell_backlight",
 								  &platform_device->dev,
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 49d9ad7..6605bea 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1147,6 +1147,7 @@ static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	bd = backlight_device_register(EEEPC_LAPTOP_FILE,
 				       &eeepc->platform_device->dev, eeepc,
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 95e3b09..493054c 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -1128,6 +1128,7 @@ static int __init fujitsu_init(void)
 
 		memset(&props, 0, sizeof(struct backlight_properties));
 		max_brightness = fujitsu->max_brightness;
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = max_brightness - 1;
 		fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
 							       NULL, NULL,
diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c
new file mode 100644
index 0000000..1b52d00
--- /dev/null
+++ b/drivers/platform/x86/hp_accel.c
@@ -0,0 +1,404 @@
+/*
+ *  hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008 Eric Piel
+ *  Copyright (C) 2008-2009 Pavel Machek
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/leds.h>
+#include <linux/atomic.h>
+#include <acpi/acpi_drivers.h>
+#include "../../misc/lis3lv02d/lis3lv02d.h"
+
+#define DRIVER_NAME     "hp_accel"
+#define ACPI_MDPS_CLASS "accelerometer"
+
+/* Delayed LEDs infrastructure ------------------------------------ */
+
+/* Special LED class that can defer work */
+struct delayed_led_classdev {
+	struct led_classdev led_classdev;
+	struct work_struct work;
+	enum led_brightness new_brightness;
+
+	unsigned int led;		/* For driver */
+	void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
+};
+
+static inline void delayed_set_status_worker(struct work_struct *work)
+{
+	struct delayed_led_classdev *data =
+			container_of(work, struct delayed_led_classdev, work);
+
+	data->set_brightness(data, data->new_brightness);
+}
+
+static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
+			      enum led_brightness brightness)
+{
+	struct delayed_led_classdev *data = container_of(led_cdev,
+			     struct delayed_led_classdev, led_classdev);
+	data->new_brightness = brightness;
+	schedule_work(&data->work);
+}
+
+/* HP-specific accelerometer driver ------------------------------------ */
+
+/* For automatic insertion of the module */
+static struct acpi_device_id lis3lv02d_device_ids[] = {
+	{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
+
+
+/**
+ * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
+ * @lis3: pointer to the device struct
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
+{
+	struct acpi_device *dev = lis3->bus_priv;
+	if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
+				 NULL, NULL) != AE_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * lis3lv02d_acpi_read - ACPI ALRD method: read a register
+ * @lis3: pointer to the device struct
+ * @reg:    the register to read
+ * @ret:    result of the operation
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
+{
+	struct acpi_device *dev = lis3->bus_priv;
+	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+	struct acpi_object_list args = { 1, &arg0 };
+	unsigned long long lret;
+	acpi_status status;
+
+	arg0.integer.value = reg;
+
+	status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
+	*ret = lret;
+	return (status != AE_OK) ? -EINVAL : 0;
+}
+
+/**
+ * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
+ * @lis3: pointer to the device struct
+ * @reg:    the register to write to
+ * @val:    the value to write
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
+{
+	struct acpi_device *dev = lis3->bus_priv;
+	unsigned long long ret; /* Not used when writting */
+	union acpi_object in_obj[2];
+	struct acpi_object_list args = { 2, in_obj };
+
+	in_obj[0].type          = ACPI_TYPE_INTEGER;
+	in_obj[0].integer.value = reg;
+	in_obj[1].type          = ACPI_TYPE_INTEGER;
+	in_obj[1].integer.value = val;
+
+	if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
+{
+	lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
+	pr_info("hardware type %s found\n", dmi->ident);
+
+	return 1;
+}
+
+/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
+ * If the value is negative, the opposite of the hw value is used. */
+#define DEFINE_CONV(name, x, y, z)			      \
+	static union axis_conversion lis3lv02d_axis_##name = \
+		{ .as_array = { x, y, z } }
+DEFINE_CONV(normal, 1, 2, 3);
+DEFINE_CONV(y_inverted, 1, -2, 3);
+DEFINE_CONV(x_inverted, -1, 2, 3);
+DEFINE_CONV(z_inverted, 1, 2, -3);
+DEFINE_CONV(xy_swap, 2, 1, 3);
+DEFINE_CONV(xy_rotated_left, -2, 1, 3);
+DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
+DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
+DEFINE_CONV(xy_rotated_right, 2, -1, 3);
+DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
+
+#define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
+	.ident = _ident,				\
+	.callback = lis3lv02d_dmi_matched,		\
+	.matches = {					\
+		DMI_MATCH(DMI_PRODUCT_NAME, _name)	\
+	},						\
+	.driver_data = &lis3lv02d_axis_##_axis		\
+}
+
+#define AXIS_DMI_MATCH2(_ident, _class1, _name1,	\
+				_class2, _name2,	\
+				_axis) {		\
+	.ident = _ident,				\
+	.callback = lis3lv02d_dmi_matched,		\
+	.matches = {					\
+		DMI_MATCH(DMI_##_class1, _name1),	\
+		DMI_MATCH(DMI_##_class2, _name2),	\
+	},						\
+	.driver_data = &lis3lv02d_axis_##_axis		\
+}
+static struct dmi_system_id lis3lv02d_dmi_ids[] = {
+	/* product names are truncated to match all kinds of a same model */
+	AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
+	AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
+	AXIS_DMI_MATCH("NX9420", "HP Compaq nx9420", x_inverted),
+	AXIS_DMI_MATCH("NW9440", "HP Compaq nw9440", x_inverted),
+	AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted),
+	AXIS_DMI_MATCH("NC2710", "HP Compaq 2710", xy_swap),
+	AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted),
+	AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
+	AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
+	AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
+	AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
+	AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
+	AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
+	AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
+	AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
+	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
+	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
+	/* Intel-based HP Pavilion dv5 */
+	AXIS_DMI_MATCH2("HPDV5_I",
+			PRODUCT_NAME, "HP Pavilion dv5",
+			BOARD_NAME, "3603",
+			x_inverted),
+	/* AMD-based HP Pavilion dv5 */
+	AXIS_DMI_MATCH2("HPDV5_A",
+			PRODUCT_NAME, "HP Pavilion dv5",
+			BOARD_NAME, "3600",
+			y_inverted),
+	AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
+	AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
+	AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
+	AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
+	AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
+	AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
+	AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
+	AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
+	AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
+	{ NULL, }
+/* Laptop models without axis info (yet):
+ * "NC6910" "HP Compaq 6910"
+ * "NC2400" "HP Compaq nc2400"
+ * "NX74x0" "HP Compaq nx74"
+ * "NX6325" "HP Compaq nx6325"
+ * "NC4400" "HP Compaq nc4400"
+ */
+};
+
+static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
+{
+	struct acpi_device *dev = lis3_dev.bus_priv;
+	unsigned long long ret; /* Not used when writing */
+	union acpi_object in_obj[1];
+	struct acpi_object_list args = { 1, in_obj };
+
+	in_obj[0].type          = ACPI_TYPE_INTEGER;
+	in_obj[0].integer.value = !!value;
+
+	acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
+}
+
+static struct delayed_led_classdev hpled_led = {
+	.led_classdev = {
+		.name			= "hp::hddprotect",
+		.default_trigger	= "none",
+		.brightness_set		= delayed_sysfs_set,
+		.flags                  = LED_CORE_SUSPENDRESUME,
+	},
+	.set_brightness = hpled_set,
+};
+
+static acpi_status
+lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
+{
+	if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+		struct acpi_resource_extended_irq *irq;
+		u32 *device_irq = context;
+
+		irq = &resource->data.extended_irq;
+		*device_irq = irq->interrupts[0];
+	}
+
+	return AE_OK;
+}
+
+static void lis3lv02d_enum_resources(struct acpi_device *device)
+{
+	acpi_status status;
+
+	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+					lis3lv02d_get_resource, &lis3_dev.irq);
+	if (ACPI_FAILURE(status))
+		printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
+}
+
+static int lis3lv02d_add(struct acpi_device *device)
+{
+	int ret;
+
+	if (!device)
+		return -EINVAL;
+
+	lis3_dev.bus_priv = device;
+	lis3_dev.init = lis3lv02d_acpi_init;
+	lis3_dev.read = lis3lv02d_acpi_read;
+	lis3_dev.write = lis3lv02d_acpi_write;
+	strcpy(acpi_device_name(device), DRIVER_NAME);
+	strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
+	device->driver_data = &lis3_dev;
+
+	/* obtain IRQ number of our device from ACPI */
+	lis3lv02d_enum_resources(device);
+
+	/* If possible use a "standard" axes order */
+	if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
+		pr_info("Using custom axes %d,%d,%d\n",
+			lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+	} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+		pr_info("laptop model unknown, using default axes configuration\n");
+		lis3_dev.ac = lis3lv02d_axis_normal;
+	}
+
+	/* call the core layer do its init */
+	ret = lis3lv02d_init_device(&lis3_dev);
+	if (ret)
+		return ret;
+
+	INIT_WORK(&hpled_led.work, delayed_set_status_worker);
+	ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+	if (ret) {
+		lis3lv02d_joystick_disable();
+		lis3lv02d_poweroff(&lis3_dev);
+		flush_work(&hpled_led.work);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int lis3lv02d_remove(struct acpi_device *device, int type)
+{
+	if (!device)
+		return -EINVAL;
+
+	lis3lv02d_joystick_disable();
+	lis3lv02d_poweroff(&lis3_dev);
+
+	led_classdev_unregister(&hpled_led.led_classdev);
+	flush_work(&hpled_led.work);
+
+	return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+
+#ifdef CONFIG_PM
+static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+{
+	/* make sure the device is off when we suspend */
+	lis3lv02d_poweroff(&lis3_dev);
+	return 0;
+}
+
+static int lis3lv02d_resume(struct acpi_device *device)
+{
+	lis3lv02d_poweron(&lis3_dev);
+	return 0;
+}
+#else
+#define lis3lv02d_suspend NULL
+#define lis3lv02d_resume NULL
+#endif
+
+/* For the HP MDPS aka 3D Driveguard */
+static struct acpi_driver lis3lv02d_driver = {
+	.name  = DRIVER_NAME,
+	.class = ACPI_MDPS_CLASS,
+	.ids   = lis3lv02d_device_ids,
+	.ops = {
+		.add     = lis3lv02d_add,
+		.remove  = lis3lv02d_remove,
+		.suspend = lis3lv02d_suspend,
+		.resume  = lis3lv02d_resume,
+	}
+};
+
+static int __init lis3lv02d_init_module(void)
+{
+	int ret;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	ret = acpi_bus_register_driver(&lis3lv02d_driver);
+	if (ret < 0)
+		return ret;
+
+	pr_info("driver loaded\n");
+
+	return 0;
+}
+
+static void __exit lis3lv02d_exit_module(void)
+{
+	acpi_bus_unregister_driver(&lis3lv02d_driver);
+}
+
+MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init_module);
+module_exit(lis3lv02d_exit_module);
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 7e9bb6d..142d385 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -804,6 +804,7 @@ static int __init msi_init(void)
 	} else {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = MSI_LCD_LEVEL_MAX - 1;
 		msibl_device = backlight_device_register("msi-laptop-bl", NULL,
 							 NULL, &msibl_ops,
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
index 35278ad..d5419c9 100644
--- a/drivers/platform/x86/msi-wmi.c
+++ b/drivers/platform/x86/msi-wmi.c
@@ -254,6 +254,7 @@ static int __init msi_wmi_init(void)
 	if (!acpi_video_backlight_support()) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
 		backlight = backlight_device_register(DRV_NAME, NULL, NULL,
 						      &msi_backlight_ops,
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index cc1e0ba..05be30e 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -602,6 +602,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
 	}
 	/* initialize backlight */
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
 	pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
 						   &pcc_backlight_ops, &props);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 5e83370..13d8d63 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1305,8 +1305,9 @@ static int sony_nc_add(struct acpi_device *device)
 		       "controlled by ACPI video driver\n");
 	} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
 						&handle))) {
-							struct backlight_properties props;
+		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
 		sony_backlight_device = backlight_device_register("sony", NULL,
 								  NULL,
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index eb99223..947bdca 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -6307,6 +6307,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
 		return 1;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = bright_maxlvl;
 	props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
 	ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index 209cced..63f42a2 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -1018,6 +1018,7 @@ static int __init toshiba_acpi_init(void)
 		create_toshiba_proc_entries();
 	}
 
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 	toshiba_backlight_device = backlight_device_register("toshiba",
 							     &toshiba_acpi.p_dev->dev,
diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h
index 19bc736..fa4e0a5 100644
--- a/drivers/pnp/base.h
+++ b/drivers/pnp/base.h
@@ -142,7 +142,9 @@ void __pnp_remove_device(struct pnp_dev *dev);
 int pnp_check_port(struct pnp_dev *dev, struct resource *res);
 int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
 int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
+#ifdef CONFIG_ISA_DMA_API
 int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
+#endif
 
 char *pnp_resource_type_name(struct resource *res);
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 0a15664..ed9ce50 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -171,6 +171,7 @@ __add:
 	return 0;
 }
 
+#ifdef CONFIG_ISA_DMA_API
 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 {
 	struct resource *res, local_res;
@@ -210,6 +211,7 @@ __add:
 	pnp_add_dma_resource(dev, res->start, res->flags);
 	return 0;
 }
+#endif /* CONFIG_ISA_DMA_API */
 
 void pnp_init_resources(struct pnp_dev *dev)
 {
@@ -234,7 +236,8 @@ static void pnp_clean_resource_table(struct pnp_dev *dev)
 static int pnp_assign_resources(struct pnp_dev *dev, int set)
 {
 	struct pnp_option *option;
-	int nport = 0, nmem = 0, nirq = 0, ndma = 0;
+	int nport = 0, nmem = 0, nirq = 0;
+	int ndma __maybe_unused = 0;
 	int ret = 0;
 
 	pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
@@ -256,9 +259,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int set)
 		case IORESOURCE_IRQ:
 			ret = pnp_assign_irq(dev, &option->u.irq, nirq++);
 			break;
+#ifdef CONFIG_ISA_DMA_API
 		case IORESOURCE_DMA:
 			ret = pnp_assign_dma(dev, &option->u.dma, ndma++);
 			break;
+#endif
 		default:
 			ret = -EINVAL;
 			break;
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index a925e6b..b0ecacb 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -409,9 +409,9 @@ int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
 	return 1;
 }
 
+#ifdef CONFIG_ISA_DMA_API
 int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 {
-#ifndef CONFIG_IA64
 	int i;
 	struct pnp_dev *tdev;
 	struct resource *tres;
@@ -466,11 +466,8 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 	}
 
 	return 1;
-#else
-	/* IA64 does not have legacy DMA */
-	return 0;
-#endif
 }
+#endif /* CONFIG_ISA_DMA_API */
 
 unsigned long pnp_resource_type(struct resource *res)
 {
diff --git a/drivers/pps/clients/Makefile b/drivers/pps/clients/Makefile
index 42517da..4feb7e9 100644
--- a/drivers/pps/clients/Makefile
+++ b/drivers/pps/clients/Makefile
@@ -6,6 +6,4 @@ obj-$(CONFIG_PPS_CLIENT_KTIMER)	+= pps-ktimer.o
 obj-$(CONFIG_PPS_CLIENT_LDISC)	+= pps-ldisc.o
 obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o
 
-ifeq ($(CONFIG_PPS_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
diff --git a/drivers/pps/generators/pps_gen_parport.c b/drivers/pps/generators/pps_gen_parport.c
index b93af3e..dcd39fb 100644
--- a/drivers/pps/generators/pps_gen_parport.c
+++ b/drivers/pps/generators/pps_gen_parport.c
@@ -216,11 +216,6 @@ static void parport_attach(struct parport *port)
 
 	hrtimer_init(&device.timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	device.timer.function = hrtimer_event;
-#ifdef CONFIG_PREEMPT_RT
-	/* hrtimer interrupt will run in the interrupt context with this */
-	device.timer.irqsafe = 1;
-#endif
-
 	hrtimer_start(&device.timer, next_intr_time(&device), HRTIMER_MODE_ABS);
 
 	return;
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile
index b6139fe..89b8eca 100644
--- a/drivers/rapidio/Makefile
+++ b/drivers/rapidio/Makefile
@@ -5,6 +5,4 @@ obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
 
 obj-$(CONFIG_RAPIDIO)		+= switches/
 
-ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile
index 48d67a6..c4d3acc 100644
--- a/drivers/rapidio/switches/Makefile
+++ b/drivers/rapidio/switches/Makefile
@@ -7,7 +7,3 @@ obj-$(CONFIG_RAPIDIO_CPS_XX)	+= idtcps.o
 obj-$(CONFIG_RAPIDIO_TSI568)	+= tsi568.o
 obj-$(CONFIG_RAPIDIO_TSI500)	+= tsi500.o
 obj-$(CONFIG_RAPIDIO_CPS_GEN2)	+= idt_gen2.o
-
-ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 4941cad..e187887 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -985,4 +985,14 @@ config RTC_DRV_LPC32XX
 	  This driver can also be buillt as a module. If so, the module
 	  will be called rtc-lpc32xx.
 
+config RTC_DRV_TEGRA
+	tristate "NVIDIA Tegra Internal RTC driver"
+	depends on RTC_CLASS && ARCH_TEGRA
+	help
+	  If you say yes here you get support for the
+	  Tegra 200 series internal RTC module.
+
+	  This drive can also be built as a module. If so, the module
+	  will be called rtc-tegra.
+
 endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 2afdaf3..ca91c3c 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -2,9 +2,7 @@
 # Makefile for RTC class/drivers.
 #
 
-ifeq ($(CONFIG_RTC_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_RTC_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_RTC_LIB)		+= rtc-lib.o
 obj-$(CONFIG_RTC_HCTOSYS)	+= hctosys.o
@@ -93,6 +91,7 @@ obj-$(CONFIG_RTC_DRV_STARFIRE)	+= rtc-starfire.o
 obj-$(CONFIG_RTC_DRV_STK17TA8)	+= rtc-stk17ta8.o
 obj-$(CONFIG_RTC_DRV_STMP)	+= rtc-stmp3xxx.o
 obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o
+obj-$(CONFIG_RTC_DRV_TEGRA)	+= rtc-tegra.o
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
 obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl.o
 obj-$(CONFIG_RTC_DRV_TX4939)	+= rtc-tx4939.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index c404b61..09b4437 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -117,6 +117,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 					struct module *owner)
 {
 	struct rtc_device *rtc;
+	struct rtc_wkalrm alrm;
 	int id, err;
 
 	if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
@@ -166,6 +167,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
 	rtc->pie_timer.function = rtc_pie_update_irq;
 	rtc->pie_enabled = 0;
 
+	/* Check to see if there is an ALARM already set in hw */
+	err = __rtc_read_alarm(rtc, &alrm);
+
+	if (!err && !rtc_valid_tm(&alrm.time))
+		rtc_set_alarm(rtc, &alrm);
+
 	strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
 	dev_set_name(&rtc->dev, "rtc%d", id);
 
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index cb2f072..8ec6b06 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -116,6 +116,186 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)
 }
 EXPORT_SYMBOL_GPL(rtc_set_mmss);
 
+static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+	int err;
+
+	err = mutex_lock_interruptible(&rtc->ops_lock);
+	if (err)
+		return err;
+
+	if (rtc->ops == NULL)
+		err = -ENODEV;
+	else if (!rtc->ops->read_alarm)
+		err = -EINVAL;
+	else {
+		memset(alarm, 0, sizeof(struct rtc_wkalrm));
+		err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
+	}
+
+	mutex_unlock(&rtc->ops_lock);
+	return err;
+}
+
+int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+	int err;
+	struct rtc_time before, now;
+	int first_time = 1;
+	unsigned long t_now, t_alm;
+	enum { none, day, month, year } missing = none;
+	unsigned days;
+
+	/* The lower level RTC driver may return -1 in some fields,
+	 * creating invalid alarm->time values, for reasons like:
+	 *
+	 *   - The hardware may not be capable of filling them in;
+	 *     many alarms match only on time-of-day fields, not
+	 *     day/month/year calendar data.
+	 *
+	 *   - Some hardware uses illegal values as "wildcard" match
+	 *     values, which non-Linux firmware (like a BIOS) may try
+	 *     to set up as e.g. "alarm 15 minutes after each hour".
+	 *     Linux uses only oneshot alarms.
+	 *
+	 * When we see that here, we deal with it by using values from
+	 * a current RTC timestamp for any missing (-1) values.  The
+	 * RTC driver prevents "periodic alarm" modes.
+	 *
+	 * But this can be racey, because some fields of the RTC timestamp
+	 * may have wrapped in the interval since we read the RTC alarm,
+	 * which would lead to us inserting inconsistent values in place
+	 * of the -1 fields.
+	 *
+	 * Reading the alarm and timestamp in the reverse sequence
+	 * would have the same race condition, and not solve the issue.
+	 *
+	 * So, we must first read the RTC timestamp,
+	 * then read the RTC alarm value,
+	 * and then read a second RTC timestamp.
+	 *
+	 * If any fields of the second timestamp have changed
+	 * when compared with the first timestamp, then we know
+	 * our timestamp may be inconsistent with that used by
+	 * the low-level rtc_read_alarm_internal() function.
+	 *
+	 * So, when the two timestamps disagree, we just loop and do
+	 * the process again to get a fully consistent set of values.
+	 *
+	 * This could all instead be done in the lower level driver,
+	 * but since more than one lower level RTC implementation needs it,
+	 * then it's probably best best to do it here instead of there..
+	 */
+
+	/* Get the "before" timestamp */
+	err = rtc_read_time(rtc, &before);
+	if (err < 0)
+		return err;
+	do {
+		if (!first_time)
+			memcpy(&before, &now, sizeof(struct rtc_time));
+		first_time = 0;
+
+		/* get the RTC alarm values, which may be incomplete */
+		err = rtc_read_alarm_internal(rtc, alarm);
+		if (err)
+			return err;
+
+		/* full-function RTCs won't have such missing fields */
+		if (rtc_valid_tm(&alarm->time) == 0)
+			return 0;
+
+		/* get the "after" timestamp, to detect wrapped fields */
+		err = rtc_read_time(rtc, &now);
+		if (err < 0)
+			return err;
+
+		/* note that tm_sec is a "don't care" value here: */
+	} while (   before.tm_min   != now.tm_min
+		 || before.tm_hour  != now.tm_hour
+		 || before.tm_mon   != now.tm_mon
+		 || before.tm_year  != now.tm_year);
+
+	/* Fill in the missing alarm fields using the timestamp; we
+	 * know there's at least one since alarm->time is invalid.
+	 */
+	if (alarm->time.tm_sec == -1)
+		alarm->time.tm_sec = now.tm_sec;
+	if (alarm->time.tm_min == -1)
+		alarm->time.tm_min = now.tm_min;
+	if (alarm->time.tm_hour == -1)
+		alarm->time.tm_hour = now.tm_hour;
+
+	/* For simplicity, only support date rollover for now */
+	if (alarm->time.tm_mday == -1) {
+		alarm->time.tm_mday = now.tm_mday;
+		missing = day;
+	}
+	if (alarm->time.tm_mon == -1) {
+		alarm->time.tm_mon = now.tm_mon;
+		if (missing == none)
+			missing = month;
+	}
+	if (alarm->time.tm_year == -1) {
+		alarm->time.tm_year = now.tm_year;
+		if (missing == none)
+			missing = year;
+	}
+
+	/* with luck, no rollover is needed */
+	rtc_tm_to_time(&now, &t_now);
+	rtc_tm_to_time(&alarm->time, &t_alm);
+	if (t_now < t_alm)
+		goto done;
+
+	switch (missing) {
+
+	/* 24 hour rollover ... if it's now 10am Monday, an alarm that
+	 * that will trigger at 5am will do so at 5am Tuesday, which
+	 * could also be in the next month or year.  This is a common
+	 * case, especially for PCs.
+	 */
+	case day:
+		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
+		t_alm += 24 * 60 * 60;
+		rtc_time_to_tm(t_alm, &alarm->time);
+		break;
+
+	/* Month rollover ... if it's the 31th, an alarm on the 3rd will
+	 * be next month.  An alarm matching on the 30th, 29th, or 28th
+	 * may end up in the month after that!  Many newer PCs support
+	 * this type of alarm.
+	 */
+	case month:
+		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month");
+		do {
+			if (alarm->time.tm_mon < 11)
+				alarm->time.tm_mon++;
+			else {
+				alarm->time.tm_mon = 0;
+				alarm->time.tm_year++;
+			}
+			days = rtc_month_days(alarm->time.tm_mon,
+					alarm->time.tm_year);
+		} while (days < alarm->time.tm_mday);
+		break;
+
+	/* Year rollover ... easy except for leap years! */
+	case year:
+		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
+		do {
+			alarm->time.tm_year++;
+		} while (rtc_valid_tm(&alarm->time) != 0);
+		break;
+
+	default:
+		dev_warn(&rtc->dev, "alarm rollover not handled\n");
+	}
+
+done:
+	return 0;
+}
+
 int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 {
 	int err;
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 26d1cf5..518a76e 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -183,33 +183,6 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	return 0;
 }
 
-/*
- * Handle commands from user-space
- */
-static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
-			unsigned long arg)
-{
-	int ret = 0;
-
-	pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
-
-	/* important:  scrub old status before enabling IRQs */
-	switch (cmd) {
-	case RTC_UIE_OFF:	/* update off */
-		at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
-		break;
-	case RTC_UIE_ON:	/* update on */
-		at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
-		at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-
-	return ret;
-}
-
 static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	pr_debug("%s(): cmd=%08x\n", __func__, enabled);
@@ -269,7 +242,6 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
 }
 
 static const struct rtc_class_ops at91_rtc_ops = {
-	.ioctl		= at91_rtc_ioctl,
 	.read_time	= at91_rtc_readtime,
 	.set_time	= at91_rtc_settime,
 	.read_alarm	= at91_rtc_readalarm,
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 5469c52..a3ad957 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -216,33 +216,6 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	return 0;
 }
 
-/*
- * Handle commands from user-space
- */
-static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
-			unsigned long arg)
-{
-	struct sam9_rtc *rtc = dev_get_drvdata(dev);
-	int ret = 0;
-	u32 mr = rtt_readl(rtc, MR);
-
-	dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr);
-
-	switch (cmd) {
-	case RTC_UIE_OFF:		/* update off */
-		rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
-		break;
-	case RTC_UIE_ON:		/* update on */
-		rtt_writel(rtc, MR, mr | AT91_RTT_RTTINCIEN);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-
-	return ret;
-}
-
 static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct sam9_rtc *rtc = dev_get_drvdata(dev);
@@ -303,7 +276,6 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc)
 }
 
 static const struct rtc_class_ops at91_rtc_ops = {
-	.ioctl		= at91_rtc_ioctl,
 	.read_time	= at91_rtc_readtime,
 	.set_time	= at91_rtc_settime,
 	.read_alarm	= at91_rtc_readalarm,
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index 17971d9..ca9cff8 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -240,32 +240,6 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc)
 	 */
 	bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY);
 }
-static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	struct bfin_rtc *rtc = dev_get_drvdata(dev);
-	int ret = 0;
-
-	dev_dbg_stamp(dev);
-
-	bfin_rtc_sync_pending(dev);
-
-	switch (cmd) {
-	case RTC_UIE_ON:
-		dev_dbg_stamp(dev);
-		bfin_rtc_int_set(RTC_ISTAT_SEC);
-		break;
-	case RTC_UIE_OFF:
-		dev_dbg_stamp(dev);
-		bfin_rtc_int_clear(~RTC_ISTAT_SEC);
-		break;
-
-	default:
-		dev_dbg_stamp(dev);
-		ret = -ENOIOCTLCMD;
-	}
-
-	return ret;
-}
 
 static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
@@ -358,7 +332,6 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq)
 }
 
 static struct rtc_class_ops bfin_rtc_ops = {
-	.ioctl         = bfin_rtc_ioctl,
 	.read_time     = bfin_rtc_read_time,
 	.set_time      = bfin_rtc_set_time,
 	.read_alarm    = bfin_rtc_read_alarm,
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index c7ff8df..911e75c 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -37,6 +37,8 @@
 #include <linux/mod_devicetable.h>
 #include <linux/log2.h>
 #include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <asm-generic/rtc.h>
@@ -375,50 +377,6 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 	return 0;
 }
 
-static int cmos_irq_set_freq(struct device *dev, int freq)
-{
-	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
-	int		f;
-	unsigned long	flags;
-
-	if (!is_valid_irq(cmos->irq))
-		return -ENXIO;
-
-	if (!is_power_of_2(freq))
-		return -EINVAL;
-	/* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
-	f = ffs(freq);
-	if (f-- > 16)
-		return -EINVAL;
-	f = 16 - f;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	hpet_set_periodic_freq(freq);
-	CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-static int cmos_irq_set_state(struct device *dev, int enabled)
-{
-	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
-	unsigned long	flags;
-
-	if (!is_valid_irq(cmos->irq))
-		return -ENXIO;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-
-	if (enabled)
-		cmos_irq_enable(cmos, RTC_PIE);
-	else
-		cmos_irq_disable(cmos, RTC_PIE);
-
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return 0;
-}
-
 static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
@@ -438,25 +396,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int cmos_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
-	unsigned long	flags;
-
-	if (!is_valid_irq(cmos->irq))
-		return -EINVAL;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-
-	if (enabled)
-		cmos_irq_enable(cmos, RTC_UIE);
-	else
-		cmos_irq_disable(cmos, RTC_UIE);
-
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return 0;
-}
-
 #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
 
 static int cmos_procfs(struct device *dev, struct seq_file *seq)
@@ -501,10 +440,7 @@ static const struct rtc_class_ops cmos_rtc_ops = {
 	.read_alarm		= cmos_read_alarm,
 	.set_alarm		= cmos_set_alarm,
 	.proc			= cmos_procfs,
-	.irq_set_freq		= cmos_irq_set_freq,
-	.irq_set_state		= cmos_irq_set_state,
 	.alarm_irq_enable	= cmos_alarm_irq_enable,
-	.update_irq_enable	= cmos_update_irq_enable,
 };
 
 /*----------------------------------------------------------------*/
@@ -1123,6 +1059,47 @@ static struct pnp_driver cmos_pnp_driver = {
 
 #endif	/* CONFIG_PNP */
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_cmos_match[] = {
+	{
+		.compatible = "motorola,mc146818",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_cmos_match);
+
+static __init void cmos_of_init(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct rtc_time time;
+	int ret;
+	const __be32 *val;
+
+	if (!node)
+		return;
+
+	val = of_get_property(node, "ctrl-reg", NULL);
+	if (val)
+		CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL);
+
+	val = of_get_property(node, "freq-reg", NULL);
+	if (val)
+		CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
+
+	get_rtc_time(&time);
+	ret = rtc_valid_tm(&time);
+	if (ret) {
+		struct rtc_time def_time = {
+			.tm_year = 1,
+			.tm_mday = 1,
+		};
+		set_rtc_time(&def_time);
+	}
+}
+#else
+static inline void cmos_of_init(struct platform_device *pdev) {}
+#define of_cmos_match NULL
+#endif
 /*----------------------------------------------------------------*/
 
 /* Platform setup should have set up an RTC device, when PNP is
@@ -1131,6 +1108,7 @@ static struct pnp_driver cmos_pnp_driver = {
 
 static int __init cmos_platform_probe(struct platform_device *pdev)
 {
+	cmos_of_init(pdev);
 	cmos_wake_setup(&pdev->dev);
 	return cmos_do_probe(&pdev->dev,
 			platform_get_resource(pdev, IORESOURCE_IO, 0),
@@ -1162,6 +1140,7 @@ static struct platform_driver cmos_platform_driver = {
 #ifdef CONFIG_PM
 		.pm		= &cmos_pm_ops,
 #endif
+		.of_match_table = of_cmos_match,
 	}
 };
 
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c
index 34647fc..8d46838 100644
--- a/drivers/rtc/rtc-davinci.c
+++ b/drivers/rtc/rtc-davinci.c
@@ -231,10 +231,6 @@ davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 	case RTC_WIE_OFF:
 		rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN;
 		break;
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		ret = -ENOTTY;
-		break;
 	default:
 		ret = -ENOIOCTLCMD;
 	}
@@ -473,55 +469,6 @@ static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 	return 0;
 }
 
-static int davinci_rtc_irq_set_state(struct device *dev, int enabled)
-{
-	struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
-	unsigned long flags;
-	u8 rtc_ctrl;
-
-	spin_lock_irqsave(&davinci_rtc_lock, flags);
-
-	rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL);
-
-	if (enabled) {
-		while (rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL)
-		       & PRTCSS_RTC_CTRL_WDTBUS)
-			cpu_relax();
-
-		rtc_ctrl |= PRTCSS_RTC_CTRL_TE;
-		rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL);
-
-		rtcss_write(davinci_rtc, 0x0, PRTCSS_RTC_CLKC_CNT);
-
-		rtc_ctrl |= PRTCSS_RTC_CTRL_TIEN |
-			    PRTCSS_RTC_CTRL_TMMD |
-			    PRTCSS_RTC_CTRL_TMRFLG;
-	} else
-		rtc_ctrl &= ~PRTCSS_RTC_CTRL_TIEN;
-
-	rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL);
-
-	spin_unlock_irqrestore(&davinci_rtc_lock, flags);
-
-	return 0;
-}
-
-static int davinci_rtc_irq_set_freq(struct device *dev, int freq)
-{
-	struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
-	unsigned long flags;
-	u16 tmr_counter = (0x8000 >> (ffs(freq) - 1));
-
-	spin_lock_irqsave(&davinci_rtc_lock, flags);
-
-	rtcss_write(davinci_rtc, tmr_counter & 0xFF, PRTCSS_RTC_TMR0);
-	rtcss_write(davinci_rtc, (tmr_counter & 0xFF00) >> 8, PRTCSS_RTC_TMR1);
-
-	spin_unlock_irqrestore(&davinci_rtc_lock, flags);
-
-	return 0;
-}
-
 static struct rtc_class_ops davinci_rtc_ops = {
 	.ioctl			= davinci_rtc_ioctl,
 	.read_time		= davinci_rtc_read_time,
@@ -529,8 +476,6 @@ static struct rtc_class_ops davinci_rtc_ops = {
 	.alarm_irq_enable	= davinci_rtc_alarm_irq_enable,
 	.read_alarm		= davinci_rtc_read_alarm,
 	.set_alarm		= davinci_rtc_set_alarm,
-	.irq_set_state		= davinci_rtc_irq_set_state,
-	.irq_set_freq		= davinci_rtc_irq_set_freq,
 };
 
 static int __init davinci_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index d834a63..e6e71de 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -25,6 +25,7 @@
 #include <linux/bcd.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 #define DS1374_REG_TOD0		0x00 /* Time of Day */
 #define DS1374_REG_TOD1		0x01
@@ -409,32 +410,38 @@ static int __devexit ds1374_remove(struct i2c_client *client)
 }
 
 #ifdef CONFIG_PM
-static int ds1374_suspend(struct i2c_client *client, pm_message_t state)
+static int ds1374_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	if (client->irq >= 0 && device_may_wakeup(&client->dev))
 		enable_irq_wake(client->irq);
 	return 0;
 }
 
-static int ds1374_resume(struct i2c_client *client)
+static int ds1374_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	if (client->irq >= 0 && device_may_wakeup(&client->dev))
 		disable_irq_wake(client->irq);
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
+
+#define DS1374_PM (&ds1374_pm)
 #else
-#define ds1374_suspend	NULL
-#define ds1374_resume	NULL
+#define DS1374_PM NULL
 #endif
 
 static struct i2c_driver ds1374_driver = {
 	.driver = {
 		.name = "rtc-ds1374",
 		.owner = THIS_MODULE,
+		.pm = DS1374_PM,
 	},
 	.probe = ds1374_probe,
-	.suspend = ds1374_suspend,
-	.resume = ds1374_resume,
 	.remove = __devexit_p(ds1374_remove),
 	.id_table = ds1374_id,
 };
diff --git a/drivers/rtc/rtc-ds1390.c b/drivers/rtc/rtc-ds1390.c
index 26a86d2..b038d2c 100644
--- a/drivers/rtc/rtc-ds1390.c
+++ b/drivers/rtc/rtc-ds1390.c
@@ -158,7 +158,7 @@ static int __devinit ds1390_probe(struct spi_device *spi)
 
 static int __devexit ds1390_remove(struct spi_device *spi)
 {
-	struct ds1390 *chip = platform_get_drvdata(spi);
+	struct ds1390 *chip = spi_get_drvdata(spi);
 
 	rtc_device_unregister(chip->rtc);
 	kfree(chip);
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 37268e9..fbabc77 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -397,29 +397,12 @@ static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int ds1511_rtc_update_irq_enable(struct device *dev,
-	unsigned int enabled)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-	if (pdata->irq <= 0)
-		return -EINVAL;
-	if (enabled)
-		pdata->irqen |= RTC_UF;
-	else
-		pdata->irqen &= ~RTC_UF;
-	ds1511_rtc_update_alarm(pdata);
-	return 0;
-}
-
 static const struct rtc_class_ops ds1511_rtc_ops = {
 	.read_time		= ds1511_rtc_read_time,
 	.set_time		= ds1511_rtc_set_time,
 	.read_alarm		= ds1511_rtc_read_alarm,
 	.set_alarm		= ds1511_rtc_set_alarm,
 	.alarm_irq_enable	= ds1511_rtc_alarm_irq_enable,
-	.update_irq_enable	= ds1511_rtc_update_irq_enable,
 };
 
  static ssize_t
@@ -485,7 +468,7 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj,
 static struct bin_attribute ds1511_nvram_attr = {
 	.attr = {
 		.name = "nvram",
-		.mode = S_IRUGO | S_IWUGO,
+		.mode = S_IRUGO | S_IWUSR,
 	},
 	.size = DS1511_RAM_MAX,
 	.read = ds1511_nvram_read,
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index ff432e2..fee41b9 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -227,29 +227,12 @@ static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int ds1553_rtc_update_irq_enable(struct device *dev,
-	unsigned int enabled)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-	if (pdata->irq <= 0)
-		return -EINVAL;
-	if (enabled)
-		pdata->irqen |= RTC_UF;
-	else
-		pdata->irqen &= ~RTC_UF;
-	ds1553_rtc_update_alarm(pdata);
-	return 0;
-}
-
 static const struct rtc_class_ops ds1553_rtc_ops = {
 	.read_time		= ds1553_rtc_read_time,
 	.set_time		= ds1553_rtc_set_time,
 	.read_alarm		= ds1553_rtc_read_alarm,
 	.set_alarm		= ds1553_rtc_set_alarm,
 	.alarm_irq_enable	= ds1553_rtc_alarm_irq_enable,
-	.update_irq_enable	= ds1553_rtc_update_irq_enable,
 };
 
 static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 9507354..27b7bf6 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -339,23 +339,6 @@ static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int ds3232_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
-
-	if (client->irq <= 0)
-		return -EINVAL;
-
-	if (enabled)
-		ds3232->rtc->irq_data |= RTC_UF;
-	else
-		ds3232->rtc->irq_data &= ~RTC_UF;
-
-	ds3232_update_alarm(client);
-	return 0;
-}
-
 static irqreturn_t ds3232_irq(int irq, void *dev_id)
 {
 	struct i2c_client *client = dev_id;
@@ -406,7 +389,6 @@ static const struct rtc_class_ops ds3232_rtc_ops = {
 	.read_alarm = ds3232_read_alarm,
 	.set_alarm = ds3232_set_alarm,
 	.alarm_irq_enable = ds3232_alarm_irq_enable,
-	.update_irq_enable = ds3232_update_irq_enable,
 };
 
 static int __devinit ds3232_probe(struct i2c_client *client,
diff --git a/drivers/rtc/rtc-ds3234.c b/drivers/rtc/rtc-ds3234.c
index a774ca3..bbd2622 100644
--- a/drivers/rtc/rtc-ds3234.c
+++ b/drivers/rtc/rtc-ds3234.c
@@ -158,7 +158,7 @@ static int __devinit ds3234_probe(struct spi_device *spi)
 
 static int __devexit ds3234_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = platform_get_drvdata(spi);
+	struct rtc_device *rtc = spi_get_drvdata(spi);
 
 	rtc_device_unregister(rtc);
 	return 0;
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c
index 468200c..da8beb8 100644
--- a/drivers/rtc/rtc-isl1208.c
+++ b/drivers/rtc/rtc-isl1208.c
@@ -39,6 +39,8 @@
 #define ISL1208_REG_SR_BAT     (1<<1)	/* battery */
 #define ISL1208_REG_SR_RTCF    (1<<0)	/* rtc fail */
 #define ISL1208_REG_INT 0x08
+#define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
+#define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
 #define ISL1208_REG_09  0x09	/* reserved */
 #define ISL1208_REG_ATR 0x0a
 #define ISL1208_REG_DTR 0x0b
@@ -202,6 +204,30 @@ isl1208_i2c_set_usr(struct i2c_client *client, u16 usr)
 }
 
 static int
+isl1208_rtc_toggle_alarm(struct i2c_client *client, int enable)
+{
+	int icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT);
+
+	if (icr < 0) {
+		dev_err(&client->dev, "%s: reading INT failed\n", __func__);
+		return icr;
+	}
+
+	if (enable)
+		icr |= ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM;
+	else
+		icr &= ~(ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM);
+
+	icr = i2c_smbus_write_byte_data(client, ISL1208_REG_INT, icr);
+	if (icr < 0) {
+		dev_err(&client->dev, "%s: writing INT failed\n", __func__);
+		return icr;
+	}
+
+	return 0;
+}
+
+static int
 isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
 {
 	struct i2c_client *const client = to_i2c_client(dev);
@@ -288,9 +314,8 @@ isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 {
 	struct rtc_time *const tm = &alarm->time;
 	u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
-	int sr;
+	int icr, yr, sr = isl1208_i2c_get_sr(client);
 
-	sr = isl1208_i2c_get_sr(client);
 	if (sr < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return sr;
@@ -313,6 +338,73 @@ isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 		bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
 	tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
 
+	/* The alarm doesn't store the year so get it from the rtc section */
+	yr = i2c_smbus_read_byte_data(client, ISL1208_REG_YR);
+	if (yr < 0) {
+		dev_err(&client->dev, "%s: reading RTC YR failed\n", __func__);
+		return yr;
+	}
+	tm->tm_year = bcd2bin(yr) + 100;
+
+	icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT);
+	if (icr < 0) {
+		dev_err(&client->dev, "%s: reading INT failed\n", __func__);
+		return icr;
+	}
+	alarm->enabled = !!(icr & ISL1208_REG_INT_ALME);
+
+	return 0;
+}
+
+static int
+isl1208_i2c_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+{
+	struct rtc_time *alarm_tm = &alarm->time;
+	u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
+	const int offs = ISL1208_REG_SCA;
+	unsigned long rtc_secs, alarm_secs;
+	struct rtc_time rtc_tm;
+	int err, enable;
+
+	err = isl1208_i2c_read_time(client, &rtc_tm);
+	if (err)
+		return err;
+	err = rtc_tm_to_time(&rtc_tm, &rtc_secs);
+	if (err)
+		return err;
+	err = rtc_tm_to_time(alarm_tm, &alarm_secs);
+	if (err)
+		return err;
+
+	/* If the alarm time is before the current time disable the alarm */
+	if (!alarm->enabled || alarm_secs <= rtc_secs)
+		enable = 0x00;
+	else
+		enable = 0x80;
+
+	/* Program the alarm and enable it for each setting */
+	regs[ISL1208_REG_SCA - offs] = bin2bcd(alarm_tm->tm_sec) | enable;
+	regs[ISL1208_REG_MNA - offs] = bin2bcd(alarm_tm->tm_min) | enable;
+	regs[ISL1208_REG_HRA - offs] = bin2bcd(alarm_tm->tm_hour) |
+		ISL1208_REG_HR_MIL | enable;
+
+	regs[ISL1208_REG_DTA - offs] = bin2bcd(alarm_tm->tm_mday) | enable;
+	regs[ISL1208_REG_MOA - offs] = bin2bcd(alarm_tm->tm_mon + 1) | enable;
+	regs[ISL1208_REG_DWA - offs] = bin2bcd(alarm_tm->tm_wday & 7) | enable;
+
+	/* write ALARM registers */
+	err = isl1208_i2c_set_regs(client, offs, regs,
+				  ISL1208_ALARM_SECTION_LEN);
+	if (err < 0) {
+		dev_err(&client->dev, "%s: writing ALARM section failed\n",
+			__func__);
+		return err;
+	}
+
+	err = isl1208_rtc_toggle_alarm(client, enable);
+	if (err)
+		return err;
+
 	return 0;
 }
 
@@ -391,12 +483,63 @@ isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 	return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm);
 }
 
+static int
+isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
+}
+
+static irqreturn_t
+isl1208_rtc_interrupt(int irq, void *data)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	struct i2c_client *client = data;
+	int handled = 0, sr, err;
+
+	/*
+	 * I2C reads get NAK'ed if we read straight away after an interrupt?
+	 * Using a mdelay/msleep didn't seem to help either, so we work around
+	 * this by continually trying to read the register for a short time.
+	 */
+	while (1) {
+		sr = isl1208_i2c_get_sr(client);
+		if (sr >= 0)
+			break;
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(&client->dev, "%s: reading SR failed\n",
+				__func__);
+			return sr;
+		}
+	}
+
+	if (sr & ISL1208_REG_SR_ALM) {
+		dev_dbg(&client->dev, "alarm!\n");
+
+		/* Clear the alarm */
+		sr &= ~ISL1208_REG_SR_ALM;
+		sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
+		if (sr < 0)
+			dev_err(&client->dev, "%s: writing SR failed\n",
+				__func__);
+		else
+			handled = 1;
+
+		/* Disable the alarm */
+		err = isl1208_rtc_toggle_alarm(client, 0);
+		if (err)
+			return err;
+	}
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
 static const struct rtc_class_ops isl1208_rtc_ops = {
 	.proc = isl1208_rtc_proc,
 	.read_time = isl1208_rtc_read_time,
 	.set_time = isl1208_rtc_set_time,
 	.read_alarm = isl1208_rtc_read_alarm,
-	/*.set_alarm    = isl1208_rtc_set_alarm, */
+	.set_alarm = isl1208_rtc_set_alarm,
 };
 
 /* sysfs interface */
@@ -488,11 +631,29 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	dev_info(&client->dev,
 		 "chip found, driver version " DRV_VERSION "\n");
 
+	if (client->irq > 0) {
+		rc = request_threaded_irq(client->irq, NULL,
+					  isl1208_rtc_interrupt,
+					  IRQF_SHARED,
+					  isl1208_driver.driver.name, client);
+		if (!rc) {
+			device_init_wakeup(&client->dev, 1);
+			enable_irq_wake(client->irq);
+		} else {
+			dev_err(&client->dev,
+				"Unable to request irq %d, no alarm support\n",
+				client->irq);
+			client->irq = 0;
+		}
+	}
+
 	rtc = rtc_device_register(isl1208_driver.driver.name,
 				  &client->dev, &isl1208_rtc_ops,
 				  THIS_MODULE);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
+	if (IS_ERR(rtc)) {
+		rc = PTR_ERR(rtc);
+		goto exit_free_irq;
+	}
 
 	i2c_set_clientdata(client, rtc);
 
@@ -514,6 +675,9 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
 
 exit_unregister:
 	rtc_device_unregister(rtc);
+exit_free_irq:
+	if (client->irq)
+		free_irq(client->irq, client);
 
 	return rc;
 }
@@ -525,6 +689,8 @@ isl1208_remove(struct i2c_client *client)
 
 	sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
 	rtc_device_unregister(rtc);
+	if (client->irq)
+		free_irq(client->irq, client);
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c
index 2e16f72..b647363 100644
--- a/drivers/rtc/rtc-jz4740.c
+++ b/drivers/rtc/rtc-jz4740.c
@@ -168,12 +168,6 @@ static int jz4740_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 	return ret;
 }
 
-static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable)
-{
-	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
-	return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable);
-}
-
 static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 {
 	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
@@ -185,7 +179,6 @@ static struct rtc_class_ops jz4740_rtc_ops = {
 	.set_mmss	= jz4740_rtc_set_mmss,
 	.read_alarm	= jz4740_rtc_read_alarm,
 	.set_alarm	= jz4740_rtc_set_alarm,
-	.update_irq_enable = jz4740_rtc_update_irq_enable,
 	.alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
 };
 
diff --git a/drivers/rtc/rtc-m41t94.c b/drivers/rtc/rtc-m41t94.c
index c8c97a4..e259ed7 100644
--- a/drivers/rtc/rtc-m41t94.c
+++ b/drivers/rtc/rtc-m41t94.c
@@ -136,7 +136,7 @@ static int __devinit m41t94_probe(struct spi_device *spi)
 
 static int __devexit m41t94_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = platform_get_drvdata(spi);
+	struct rtc_device *rtc = spi_get_drvdata(spi);
 
 	if (rtc)
 		rtc_device_unregister(rtc);
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 5314b15..c420064 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -282,12 +282,6 @@ static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
-static int mc13xxx_rtc_update_irq_enable(struct device *dev,
-		unsigned int enabled)
-{
-	return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_1HZ);
-}
-
 static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
 		unsigned int enabled)
 {
@@ -300,7 +294,6 @@ static const struct rtc_class_ops mc13xxx_rtc_ops = {
 	.read_alarm = mc13xxx_rtc_read_alarm,
 	.set_alarm = mc13xxx_rtc_set_alarm,
 	.alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable,
-	.update_irq_enable = mc13xxx_rtc_update_irq_enable,
 };
 
 static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index dfcdf09..09ccd8d 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -240,36 +240,15 @@ static int mpc5121_rtc_alarm_irq_enable(struct device *dev,
 	return 0;
 }
 
-static int mpc5121_rtc_update_irq_enable(struct device *dev,
-					 unsigned int enabled)
-{
-	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
-	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
-	int val;
-
-	val = in_8(&regs->int_enable);
-
-	if (enabled)
-		val = (val & ~0x8) | 0x1;
-	else
-		val &= ~0x1;
-
-	out_8(&regs->int_enable, val);
-
-	return 0;
-}
-
 static const struct rtc_class_ops mpc5121_rtc_ops = {
 	.read_time = mpc5121_rtc_read_time,
 	.set_time = mpc5121_rtc_set_time,
 	.read_alarm = mpc5121_rtc_read_alarm,
 	.set_alarm = mpc5121_rtc_set_alarm,
 	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
-	.update_irq_enable = mpc5121_rtc_update_irq_enable,
 };
 
-static int __devinit mpc5121_rtc_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc5121_rtc_probe(struct platform_device *op)
 {
 	struct mpc5121_rtc_data *rtc;
 	int err = 0;
@@ -364,7 +343,7 @@ static struct of_device_id mpc5121_rtc_match[] __devinitdata = {
 	{},
 };
 
-static struct of_platform_driver mpc5121_rtc_driver = {
+static struct platform_driver mpc5121_rtc_driver = {
 	.driver = {
 		.name = "mpc5121-rtc",
 		.owner = THIS_MODULE,
@@ -376,13 +355,13 @@ static struct of_platform_driver mpc5121_rtc_driver = {
 
 static int __init mpc5121_rtc_init(void)
 {
-	return of_register_platform_driver(&mpc5121_rtc_driver);
+	return platform_driver_register(&mpc5121_rtc_driver);
 }
 module_init(mpc5121_rtc_init);
 
 static void __exit mpc5121_rtc_exit(void)
 {
-	of_unregister_platform_driver(&mpc5121_rtc_driver);
+	platform_driver_unregister(&mpc5121_rtc_driver);
 }
 module_exit(mpc5121_rtc_exit);
 
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index 1db62db..b86bc32 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -62,6 +62,17 @@ static inline int is_intr(u8 rtc_intr)
 	return rtc_intr & RTC_IRQMASK;
 }
 
+static inline unsigned char vrtc_is_updating(void)
+{
+	unsigned char uip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return uip;
+}
+
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
@@ -76,7 +87,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
 {
 	unsigned long flags;
 
-	if (rtc_is_updating())
+	if (vrtc_is_updating())
 		mdelay(20);
 
 	spin_lock_irqsave(&rtc_lock, flags);
@@ -236,25 +247,6 @@ static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 	return 0;
 }
 
-static int mrst_irq_set_state(struct device *dev, int enabled)
-{
-	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
-	unsigned long	flags;
-
-	if (!mrst->irq)
-		return -ENXIO;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-
-	if (enabled)
-		mrst_irq_enable(mrst, RTC_PIE);
-	else
-		mrst_irq_disable(mrst, RTC_PIE);
-
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return 0;
-}
-
 /* Currently, the vRTC doesn't support UIE ON/OFF */
 static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
@@ -301,7 +293,6 @@ static const struct rtc_class_ops mrst_rtc_ops = {
 	.read_alarm	= mrst_read_alarm,
 	.set_alarm	= mrst_set_alarm,
 	.proc		= mrst_procfs,
-	.irq_set_state	= mrst_irq_set_state,
 	.alarm_irq_enable = mrst_rtc_alarm_irq_enable,
 };
 
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 0b06c1e..826ab64 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -274,12 +274,6 @@ static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int mxc_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	mxc_rtc_irq_enable(dev, RTC_1HZ_BIT, enabled);
-	return 0;
-}
-
 /*
  * This function reads the current RTC time into tm in Gregorian date.
  */
@@ -368,7 +362,6 @@ static struct rtc_class_ops mxc_rtc_ops = {
 	.read_alarm		= mxc_rtc_read_alarm,
 	.set_alarm		= mxc_rtc_set_alarm,
 	.alarm_irq_enable	= mxc_rtc_alarm_irq_enable,
-	.update_irq_enable	= mxc_rtc_update_irq_enable,
 };
 
 static int __init mxc_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c
index ddb0857..781068d 100644
--- a/drivers/rtc/rtc-nuc900.c
+++ b/drivers/rtc/rtc-nuc900.c
@@ -134,20 +134,6 @@ static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm,
 	gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16;
 }
 
-static int nuc900_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
-
-	if (enabled)
-		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)|
-				(TICKINTENB), rtc->rtc_reg + REG_RTC_RIER);
-	else
-		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)&
-				(~TICKINTENB), rtc->rtc_reg + REG_RTC_RIER);
-
-	return 0;
-}
-
 static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
@@ -234,7 +220,6 @@ static struct rtc_class_ops nuc900_rtc_ops = {
 	.read_alarm = nuc900_rtc_read_alarm,
 	.set_alarm = nuc900_rtc_set_alarm,
 	.alarm_irq_enable = nuc900_alarm_irq_enable,
-	.update_irq_enable = nuc900_update_irq_enable,
 };
 
 static int __devinit nuc900_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index b4dbf3a..de0dd7b 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -135,44 +135,6 @@ static irqreturn_t rtc_irq(int irq, void *rtc)
 	return IRQ_HANDLED;
 }
 
-#ifdef	CONFIG_RTC_INTF_DEV
-
-static int
-omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	u8 reg;
-
-	switch (cmd) {
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
-
-	local_irq_disable();
-	rtc_wait_not_busy();
-	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
-	switch (cmd) {
-	/* UIE = Update Interrupt Enable (1/second) */
-	case RTC_UIE_OFF:
-		reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER;
-		break;
-	case RTC_UIE_ON:
-		reg |= OMAP_RTC_INTERRUPTS_IT_TIMER;
-		break;
-	}
-	rtc_wait_not_busy();
-	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
-	local_irq_enable();
-
-	return 0;
-}
-
-#else
-#define	omap_rtc_ioctl	NULL
-#endif
-
 static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	u8 reg;
@@ -313,7 +275,6 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 }
 
 static struct rtc_class_ops omap_rtc_ops = {
-	.ioctl		= omap_rtc_ioctl,
 	.read_time	= omap_rtc_read_time,
 	.set_time	= omap_rtc_set_time,
 	.read_alarm	= omap_rtc_read_alarm,
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c
index 25c0b3f..a633abc 100644
--- a/drivers/rtc/rtc-pcap.c
+++ b/drivers/rtc/rtc-pcap.c
@@ -131,18 +131,12 @@ static int pcap_rtc_alarm_irq_enable(struct device *dev, unsigned int en)
 	return pcap_rtc_irq_enable(dev, PCAP_IRQ_TODA, en);
 }
 
-static int pcap_rtc_update_irq_enable(struct device *dev, unsigned int en)
-{
-	return pcap_rtc_irq_enable(dev, PCAP_IRQ_1HZ, en);
-}
-
 static const struct rtc_class_ops pcap_rtc_ops = {
 	.read_time = pcap_rtc_read_time,
 	.read_alarm = pcap_rtc_read_alarm,
 	.set_alarm = pcap_rtc_set_alarm,
 	.set_mmss = pcap_rtc_set_mmss,
 	.alarm_irq_enable = pcap_rtc_alarm_irq_enable,
-	.update_irq_enable = pcap_rtc_update_irq_enable,
 };
 
 static int __devinit pcap_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 16edf94..f90c574 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -106,25 +106,6 @@ pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int
-pcf50633_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
-	int err;
-
-	if (enabled)
-		err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
-	else
-		err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
-
-	if (err < 0)
-		return err;
-
-	rtc->second_enabled = enabled;
-
-	return 0;
-}
-
 static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pcf50633_rtc *rtc;
@@ -262,8 +243,7 @@ static struct rtc_class_ops pcf50633_rtc_ops = {
 	.set_time		= pcf50633_rtc_set_time,
 	.read_alarm		= pcf50633_rtc_read_alarm,
 	.set_alarm		= pcf50633_rtc_set_alarm,
-	.alarm_irq_enable 	= pcf50633_rtc_alarm_irq_enable,
-	.update_irq_enable 	= pcf50633_rtc_update_irq_enable,
+	.alarm_irq_enable	= pcf50633_rtc_alarm_irq_enable,
 };
 
 static void pcf50633_rtc_irq(int irq, void *data)
diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c
index bbdb2f0..1d28d44 100644
--- a/drivers/rtc/rtc-pl030.c
+++ b/drivers/rtc/rtc-pl030.c
@@ -35,11 +35,6 @@ static irqreturn_t pl030_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
 static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct pl030_rtc *rtc = dev_get_drvdata(dev);
@@ -96,14 +91,13 @@ static int pl030_set_time(struct device *dev, struct rtc_time *tm)
 }
 
 static const struct rtc_class_ops pl030_ops = {
-	.ioctl		= pl030_ioctl,
 	.read_time	= pl030_read_time,
 	.set_time	= pl030_set_time,
 	.read_alarm	= pl030_read_alarm,
 	.set_alarm	= pl030_set_alarm,
 };
 
-static int pl030_probe(struct amba_device *dev, struct amba_id *id)
+static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct pl030_rtc *rtc;
 	int ret;
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index b7a6690..ff1b84b 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -293,57 +293,6 @@ static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 	return ret;
 }
 
-/* Periodic interrupt is only available in ST variants. */
-static int pl031_irq_set_state(struct device *dev, int enabled)
-{
-	struct pl031_local *ldata = dev_get_drvdata(dev);
-
-	if (enabled == 1) {
-		/* Clear any pending timer interrupt. */
-		writel(RTC_BIT_PI, ldata->base + RTC_ICR);
-
-		writel(readl(ldata->base + RTC_IMSC) | RTC_BIT_PI,
-			ldata->base + RTC_IMSC);
-
-		/* Now start the timer */
-		writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN,
-			ldata->base + RTC_TCR);
-
-	} else {
-		writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI),
-			ldata->base + RTC_IMSC);
-
-		/* Also stop the timer */
-		writel(readl(ldata->base + RTC_TCR) & (~RTC_TCR_EN),
-			ldata->base + RTC_TCR);
-	}
-	/* Wait at least 1 RTC32 clock cycle to ensure next access
-	 * to RTC_TCR will succeed.
-	 */
-	udelay(40);
-
-	return 0;
-}
-
-static int pl031_irq_set_freq(struct device *dev, int freq)
-{
-	struct pl031_local *ldata = dev_get_drvdata(dev);
-
-	/* Cant set timer if it is already enabled */
-	if (readl(ldata->base + RTC_TCR) & RTC_TCR_EN) {
-		dev_err(dev, "can't change frequency while timer enabled\n");
-		return -EINVAL;
-	}
-
-	/* If self start bit in RTC_TCR is set timer will start here,
-	 * but we never set that bit. Instead we start the timer when
-	 * set_state is called with enabled == 1.
-	 */
-	writel(RTC_TIMER_FREQ / freq, ldata->base + RTC_TLR);
-
-	return 0;
-}
-
 static int pl031_remove(struct amba_device *adev)
 {
 	struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
@@ -358,7 +307,7 @@ static int pl031_remove(struct amba_device *adev)
 	return 0;
 }
 
-static int pl031_probe(struct amba_device *adev, struct amba_id *id)
+static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret;
 	struct pl031_local *ldata;
@@ -440,8 +389,6 @@ static struct rtc_class_ops stv1_pl031_ops = {
 	.read_alarm = pl031_read_alarm,
 	.set_alarm = pl031_set_alarm,
 	.alarm_irq_enable = pl031_alarm_irq_enable,
-	.irq_set_state = pl031_irq_set_state,
-	.irq_set_freq = pl031_irq_set_freq,
 };
 
 /* And the second ST derivative */
@@ -451,8 +398,6 @@ static struct rtc_class_ops stv2_pl031_ops = {
 	.read_alarm = pl031_stv2_read_alarm,
 	.set_alarm = pl031_stv2_set_alarm,
 	.alarm_irq_enable = pl031_alarm_irq_enable,
-	.irq_set_state = pl031_irq_set_state,
-	.irq_set_freq = pl031_irq_set_freq,
 };
 
 static struct amba_id pl031_ids[] = {
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c
index 242bbf8..0a59fda 100644
--- a/drivers/rtc/rtc-proc.c
+++ b/drivers/rtc/rtc-proc.c
@@ -69,6 +69,14 @@ static int rtc_proc_show(struct seq_file *seq, void *offset)
 				alrm.enabled ? "yes" : "no");
 		seq_printf(seq, "alrm_pending\t: %s\n",
 				alrm.pending ? "yes" : "no");
+		seq_printf(seq, "update IRQ enabled\t: %s\n",
+			(rtc->uie_rtctimer.enabled) ? "yes" : "no");
+		seq_printf(seq, "periodic IRQ enabled\t: %s\n",
+			(rtc->pie_enabled) ? "yes" : "no");
+		seq_printf(seq, "periodic IRQ frequency\t: %d\n",
+			rtc->irq_freq);
+		seq_printf(seq, "max user IRQ frequency\t: %d\n",
+			rtc->max_user_freq);
 	}
 
 	seq_printf(seq, "24hr\t\t: yes\n");
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index 29e867a..fc9f499 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -209,32 +209,6 @@ static void pxa_rtc_release(struct device *dev)
 	free_irq(pxa_rtc->irq_1Hz, dev);
 }
 
-static int pxa_periodic_irq_set_freq(struct device *dev, int freq)
-{
-	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-	int period_ms;
-
-	if (freq < 1 || freq > MAXFREQ_PERIODIC)
-		return -EINVAL;
-
-	period_ms = 1000 / freq;
-	rtc_writel(pxa_rtc, PIAR, period_ms);
-
-	return 0;
-}
-
-static int pxa_periodic_irq_set_state(struct device *dev, int enabled)
-{
-	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-
-	if (enabled)
-		rtsr_set_bits(pxa_rtc, RTSR_PIALE | RTSR_PICE);
-	else
-		rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_PICE);
-
-	return 0;
-}
-
 static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
@@ -250,21 +224,6 @@ static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int pxa_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-
-	spin_lock_irq(&pxa_rtc->lock);
-
-	if (enabled)
-		rtsr_set_bits(pxa_rtc, RTSR_HZE);
-	else
-		rtsr_clear_bits(pxa_rtc, RTSR_HZE);
-
-	spin_unlock_irq(&pxa_rtc->lock);
-	return 0;
-}
-
 static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
@@ -346,10 +305,7 @@ static const struct rtc_class_ops pxa_rtc_ops = {
 	.read_alarm = pxa_rtc_read_alarm,
 	.set_alarm = pxa_rtc_set_alarm,
 	.alarm_irq_enable = pxa_alarm_irq_enable,
-	.update_irq_enable = pxa_update_irq_enable,
 	.proc = pxa_rtc_proc,
-	.irq_set_state = pxa_periodic_irq_set_state,
-	.irq_set_freq = pxa_periodic_irq_set_freq,
 };
 
 static int __init pxa_rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c
index 6aaa155..85c1b84 100644
--- a/drivers/rtc/rtc-rs5c372.c
+++ b/drivers/rtc/rtc-rs5c372.c
@@ -281,57 +281,6 @@ static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	return rs5c372_set_datetime(to_i2c_client(dev), tm);
 }
 
-#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
-
-static int
-rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	struct i2c_client	*client = to_i2c_client(dev);
-	struct rs5c372		*rs5c = i2c_get_clientdata(client);
-	unsigned char		buf;
-	int			status, addr;
-
-	buf = rs5c->regs[RS5C_REG_CTRL1];
-	switch (cmd) {
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		/* some 327a modes use a different IRQ pin for 1Hz irqs */
-		if (rs5c->type == rtc_rs5c372a
-				&& (buf & RS5C372A_CTRL1_SL1))
-			return -ENOIOCTLCMD;
-	default:
-		return -ENOIOCTLCMD;
-	}
-
-	status = rs5c_get_regs(rs5c);
-	if (status < 0)
-		return status;
-
-	addr = RS5C_ADDR(RS5C_REG_CTRL1);
-	switch (cmd) {
-	case RTC_UIE_OFF:	/* update off */
-		buf &= ~RS5C_CTRL1_CT_MASK;
-		break;
-	case RTC_UIE_ON:	/* update on */
-		buf &= ~RS5C_CTRL1_CT_MASK;
-		buf |= RS5C_CTRL1_CT4;
-		break;
-	}
-
-	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
-		printk(KERN_WARNING "%s: can't update alarm\n",
-			rs5c->rtc->name);
-		status = -EIO;
-	} else
-		rs5c->regs[RS5C_REG_CTRL1] = buf;
-
-	return status;
-}
-
-#else
-#define	rs5c_rtc_ioctl	NULL
-#endif
-
 
 static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
@@ -480,7 +429,6 @@ static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq)
 
 static const struct rtc_class_ops rs5c372_rtc_ops = {
 	.proc		= rs5c372_rtc_proc,
-	.ioctl		= rs5c_rtc_ioctl,
 	.read_time	= rs5c372_rtc_read_time,
 	.set_time	= rs5c372_rtc_set_time,
 	.read_alarm	= rs5c_read_alarm,
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index af32a62..fde172f 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -424,37 +424,12 @@ static int rx8025_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int rx8025_irq_set_state(struct device *dev, int enabled)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct rx8025_data *rx8025 = i2c_get_clientdata(client);
-	int ctrl1;
-	int err;
-
-	if (client->irq <= 0)
-		return -ENXIO;
-
-	ctrl1 = rx8025->ctrl1 & ~RX8025_BIT_CTRL1_CT;
-	if (enabled)
-		ctrl1 |= RX8025_BIT_CTRL1_CT_1HZ;
-	if (ctrl1 != rx8025->ctrl1) {
-		rx8025->ctrl1 = ctrl1;
-		err = rx8025_write_reg(rx8025->client, RX8025_REG_CTRL1,
-				       rx8025->ctrl1);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
 static struct rtc_class_ops rx8025_rtc_ops = {
 	.read_time = rx8025_get_time,
 	.set_time = rx8025_set_time,
 	.read_alarm = rx8025_read_alarm,
 	.set_alarm = rx8025_set_alarm,
 	.alarm_irq_enable = rx8025_alarm_irq_enable,
-	.irq_set_state  = rx8025_irq_set_state,
 };
 
 /*
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index b80fa28..7149649 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -93,37 +93,6 @@ static int s3c_rtc_setaie(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int s3c_rtc_setpie(struct device *dev, int enabled)
-{
-	unsigned int tmp;
-
-	pr_debug("%s: pie=%d\n", __func__, enabled);
-
-	spin_lock_irq(&s3c_rtc_pie_lock);
-
-	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
-		tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
-		tmp &= ~S3C64XX_RTCCON_TICEN;
-
-		if (enabled)
-			tmp |= S3C64XX_RTCCON_TICEN;
-
-		writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
-	} else {
-		tmp = readb(s3c_rtc_base + S3C2410_TICNT);
-		tmp &= ~S3C2410_TICNT_ENABLE;
-
-		if (enabled)
-			tmp |= S3C2410_TICNT_ENABLE;
-
-		writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
-	}
-
-	spin_unlock_irq(&s3c_rtc_pie_lock);
-
-	return 0;
-}
-
 static int s3c_rtc_setfreq(struct device *dev, int freq)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -379,8 +348,6 @@ static const struct rtc_class_ops s3c_rtcops = {
 	.set_time	= s3c_rtc_settime,
 	.read_alarm	= s3c_rtc_getalarm,
 	.set_alarm	= s3c_rtc_setalarm,
-	.irq_set_freq	= s3c_rtc_setfreq,
-	.irq_set_state	= s3c_rtc_setpie,
 	.proc		= s3c_rtc_proc,
 	.alarm_irq_enable = s3c_rtc_setaie,
 };
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 5dfe5ff..0b40bb8 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -43,7 +43,6 @@
 #define RTC_DEF_TRIM		0
 
 static const unsigned long RTC_FREQ = 1024;
-static unsigned long timer_freq;
 static struct rtc_time rtc_alarm;
 static DEFINE_SPINLOCK(sa1100_rtc_lock);
 
@@ -156,114 +155,11 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int sa1100_irq_set_freq(struct device *dev, int freq)
-{
-	if (freq < 1 || freq > timer_freq) {
-		return -EINVAL;
-	} else {
-		struct rtc_device *rtc = (struct rtc_device *)dev;
-
-		rtc->irq_freq = freq;
-
-		return 0;
-	}
-}
-
-static int rtc_timer1_count;
-
-static int sa1100_irq_set_state(struct device *dev, int enabled)
-{
-	spin_lock_irq(&sa1100_rtc_lock);
-	if (enabled) {
-		struct rtc_device *rtc = (struct rtc_device *)dev;
-
-		OSMR1 = timer_freq / rtc->irq_freq + OSCR;
-		OIER |= OIER_E1;
-		rtc_timer1_count = 1;
-	} else {
-		OIER &= ~OIER_E1;
-	}
-	spin_unlock_irq(&sa1100_rtc_lock);
-
-	return 0;
-}
-
-static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
-{
-	unsigned long diff;
-	unsigned long period = timer_freq / rtc->irq_freq;
-
-	spin_lock_irq(&sa1100_rtc_lock);
-
-	do {
-		OSMR1 += period;
-		diff = OSMR1 - OSCR;
-		/* If OSCR > OSMR1, diff is a very large number (unsigned
-		 * math). This means we have a lost interrupt. */
-	} while (diff > period);
-	OIER |= OIER_E1;
-
-	spin_unlock_irq(&sa1100_rtc_lock);
-
-	return 0;
-}
-
-static irqreturn_t timer1_interrupt(int irq, void *dev_id)
-{
-	struct platform_device *pdev = to_platform_device(dev_id);
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	/*
-	 * If we match for the first time, rtc_timer1_count will be 1.
-	 * Otherwise, we wrapped around (very unlikely but
-	 * still possible) so compute the amount of missed periods.
-	 * The match reg is updated only when the data is actually retrieved
-	 * to avoid unnecessary interrupts.
-	 */
-	OSSR = OSSR_M1;	/* clear match on timer1 */
-
-	rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
-
-	if (rtc_timer1_count == 1)
-		rtc_timer1_count =
-			(rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
-
-	/* retrigger. */
-	sa1100_timer1_retrigger(rtc);
-
-	return IRQ_HANDLED;
-}
-
-static int sa1100_rtc_read_callback(struct device *dev, int data)
-{
-	if (data & RTC_PF) {
-		struct rtc_device *rtc = (struct rtc_device *)dev;
-
-		/* interpolate missed periods and set match for the next */
-		unsigned long period = timer_freq / rtc->irq_freq;
-		unsigned long oscr = OSCR;
-		unsigned long osmr1 = OSMR1;
-		unsigned long missed = (oscr - osmr1)/period;
-		data += missed << 8;
-		OSSR = OSSR_M1;	/* clear match on timer 1 */
-		OSMR1 = osmr1 + (missed + 1)*period;
-		/* Ensure we didn't miss another match in the mean time.
-		 * Here we compare (match - OSCR) 8 instead of 0 --
-		 * see comment in pxa_timer_interrupt() for explanation.
-		 */
-		while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
-			data += 0x100;
-			OSSR = OSSR_M1;	/* clear match on timer 1 */
-			OSMR1 = osmr1 + period;
-		}
-	}
-	return data;
-}
-
 static int sa1100_rtc_open(struct device *dev)
 {
 	int ret;
-	struct rtc_device *rtc = (struct rtc_device *)dev;
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
 		"rtc 1Hz", dev);
@@ -277,19 +173,11 @@ static int sa1100_rtc_open(struct device *dev)
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
-	ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
-		"rtc timer", dev);
-	if (ret) {
-		dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
-		goto fail_pi;
-	}
 	rtc->max_user_freq = RTC_FREQ;
-	sa1100_irq_set_freq(dev, RTC_FREQ);
+	rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
 
 	return 0;
 
- fail_pi:
-	free_irq(IRQ_RTCAlrm, dev);
  fail_ai:
 	free_irq(IRQ_RTC1Hz, dev);
  fail_ui:
@@ -304,30 +192,10 @@ static void sa1100_rtc_release(struct device *dev)
 	OSSR = OSSR_M1;
 	spin_unlock_irq(&sa1100_rtc_lock);
 
-	free_irq(IRQ_OST1, dev);
 	free_irq(IRQ_RTCAlrm, dev);
 	free_irq(IRQ_RTC1Hz, dev);
 }
 
-
-static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
-		unsigned long arg)
-{
-	switch (cmd) {
-	case RTC_UIE_OFF:
-		spin_lock_irq(&sa1100_rtc_lock);
-		RTSR &= ~RTSR_HZE;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	case RTC_UIE_ON:
-		spin_lock_irq(&sa1100_rtc_lock);
-		RTSR |= RTSR_HZE;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	}
-	return -ENOIOCTLCMD;
-}
-
 static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	spin_lock_irq(&sa1100_rtc_lock);
@@ -386,31 +254,20 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	struct rtc_device *rtc = (struct rtc_device *)dev;
-
-	seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
-	seq_printf(seq, "update_IRQ\t: %s\n",
-			(RTSR & RTSR_HZE) ? "yes" : "no");
-	seq_printf(seq, "periodic_IRQ\t: %s\n",
-			(OIER & OIER_E1) ? "yes" : "no");
-	seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
-	seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
+	seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
+	seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
 
 	return 0;
 }
 
 static const struct rtc_class_ops sa1100_rtc_ops = {
 	.open = sa1100_rtc_open,
-	.read_callback = sa1100_rtc_read_callback,
 	.release = sa1100_rtc_release,
-	.ioctl = sa1100_rtc_ioctl,
 	.read_time = sa1100_rtc_read_time,
 	.set_time = sa1100_rtc_set_time,
 	.read_alarm = sa1100_rtc_read_alarm,
 	.set_alarm = sa1100_rtc_set_alarm,
 	.proc = sa1100_rtc_proc,
-	.irq_set_freq = sa1100_irq_set_freq,
-	.irq_set_state = sa1100_irq_set_state,
 	.alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
 };
 
@@ -418,8 +275,6 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
 {
 	struct rtc_device *rtc;
 
-	timer_freq = get_clock_tick_rate();
-
 	/*
 	 * According to the manual we should be able to let RTTR be zero
 	 * and then a default diviser for a 32.768KHz clock is used.
@@ -445,11 +300,6 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, rtc);
 
-	/* Set the irq_freq */
-	/*TODO: Find out who is messing with this value after we initialize
-	 * it here.*/
-	rtc->irq_freq = RTC_FREQ;
-
 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
 	 * See also the comments in sa1100_rtc_interrupt().
 	 *
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 93314a9..e55dc1a 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -344,27 +344,6 @@ static inline void sh_rtc_setcie(struct device *dev, unsigned int enable)
 	spin_unlock_irq(&rtc->lock);
 }
 
-static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	struct sh_rtc *rtc = dev_get_drvdata(dev);
-	unsigned int ret = 0;
-
-	switch (cmd) {
-	case RTC_UIE_OFF:
-		rtc->periodic_freq &= ~PF_OXS;
-		sh_rtc_setcie(dev, 0);
-		break;
-	case RTC_UIE_ON:
-		rtc->periodic_freq |= PF_OXS;
-		sh_rtc_setcie(dev, 1);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-
-	return ret;
-}
-
 static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	sh_rtc_setaie(dev, enabled);
@@ -598,13 +577,10 @@ static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 }
 
 static struct rtc_class_ops sh_rtc_ops = {
-	.ioctl		= sh_rtc_ioctl,
 	.read_time	= sh_rtc_read_time,
 	.set_time	= sh_rtc_set_time,
 	.read_alarm	= sh_rtc_read_alarm,
 	.set_alarm	= sh_rtc_set_alarm,
-	.irq_set_state	= sh_rtc_irq_set_state,
-	.irq_set_freq	= sh_rtc_irq_set_freq,
 	.proc		= sh_rtc_proc,
 	.alarm_irq_enable = sh_rtc_alarm_irq_enable,
 };
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 7e7d0c8..572e953 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -115,19 +115,6 @@ static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled)
 	return 0;
 }
 
-static int stmp3xxx_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
-
-	if (enabled)
-		stmp3xxx_setl(BM_RTC_CTRL_ONEMSEC_IRQ_EN,
-				rtc_data->io + HW_RTC_CTRL);
-	else
-		stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN,
-				rtc_data->io + HW_RTC_CTRL);
-	return 0;
-}
-
 static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
@@ -149,8 +136,6 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 static struct rtc_class_ops stmp3xxx_rtc_ops = {
 	.alarm_irq_enable =
 			  stmp3xxx_alarm_irq_enable,
-	.update_irq_enable =
-			  stmp3xxx_update_irq_enable,
 	.read_time	= stmp3xxx_rtc_gettime,
 	.set_mmss	= stmp3xxx_rtc_set_mmss,
 	.read_alarm	= stmp3xxx_rtc_read_alarm,
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
new file mode 100644
index 0000000..2fc31aa
--- /dev/null
+++ b/drivers/rtc/rtc-tegra.c
@@ -0,0 +1,488 @@
+/*
+ * An RTC driver for the NVIDIA Tegra 200 series internal RTC.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+/* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */
+#define TEGRA_RTC_REG_BUSY			0x004
+#define TEGRA_RTC_REG_SECONDS			0x008
+/* when msec is read, the seconds are buffered into shadow seconds. */
+#define TEGRA_RTC_REG_SHADOW_SECONDS		0x00c
+#define TEGRA_RTC_REG_MILLI_SECONDS		0x010
+#define TEGRA_RTC_REG_SECONDS_ALARM0		0x014
+#define TEGRA_RTC_REG_SECONDS_ALARM1		0x018
+#define TEGRA_RTC_REG_MILLI_SECONDS_ALARM0	0x01c
+#define TEGRA_RTC_REG_INTR_MASK			0x028
+/* write 1 bits to clear status bits */
+#define TEGRA_RTC_REG_INTR_STATUS		0x02c
+
+/* bits in INTR_MASK */
+#define TEGRA_RTC_INTR_MASK_MSEC_CDN_ALARM	(1<<4)
+#define TEGRA_RTC_INTR_MASK_SEC_CDN_ALARM	(1<<3)
+#define TEGRA_RTC_INTR_MASK_MSEC_ALARM		(1<<2)
+#define TEGRA_RTC_INTR_MASK_SEC_ALARM1		(1<<1)
+#define TEGRA_RTC_INTR_MASK_SEC_ALARM0		(1<<0)
+
+/* bits in INTR_STATUS */
+#define TEGRA_RTC_INTR_STATUS_MSEC_CDN_ALARM	(1<<4)
+#define TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM	(1<<3)
+#define TEGRA_RTC_INTR_STATUS_MSEC_ALARM	(1<<2)
+#define TEGRA_RTC_INTR_STATUS_SEC_ALARM1	(1<<1)
+#define TEGRA_RTC_INTR_STATUS_SEC_ALARM0	(1<<0)
+
+struct tegra_rtc_info {
+	struct platform_device	*pdev;
+	struct rtc_device	*rtc_dev;
+	void __iomem		*rtc_base; /* NULL if not initialized. */
+	int			tegra_rtc_irq; /* alarm and periodic irq */
+	spinlock_t		tegra_rtc_lock;
+};
+
+/* RTC hardware is busy when it is updating its values over AHB once
+ * every eight 32kHz clocks (~250uS).
+ * outside of these updates the CPU is free to write.
+ * CPU is always free to read.
+ */
+static inline u32 tegra_rtc_check_busy(struct tegra_rtc_info *info)
+{
+	return readl(info->rtc_base + TEGRA_RTC_REG_BUSY) & 1;
+}
+
+/* Wait for hardware to be ready for writing.
+ * This function tries to maximize the amount of time before the next update.
+ * It does this by waiting for the RTC to become busy with its periodic update,
+ * then returning once the RTC first becomes not busy.
+ * This periodic update (where the seconds and milliseconds are copied to the
+ * AHB side) occurs every eight 32kHz clocks (~250uS).
+ * The behavior of this function allows us to make some assumptions without
+ * introducing a race, because 250uS is plenty of time to read/write a value.
+ */
+static int tegra_rtc_wait_while_busy(struct device *dev)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+
+	int retries = 500; /* ~490 us is the worst case, ~250 us is best. */
+
+	/* first wait for the RTC to become busy. this is when it
+	 * posts its updated seconds+msec registers to AHB side. */
+	while (tegra_rtc_check_busy(info)) {
+		if (!retries--)
+			goto retry_failed;
+		udelay(1);
+	}
+
+	/* now we have about 250 us to manipulate registers */
+	return 0;
+
+retry_failed:
+	dev_err(dev, "write failed:retry count exceeded.\n");
+	return -ETIMEDOUT;
+}
+
+static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec, msec;
+	unsigned long sl_irq_flags;
+
+	/* RTC hardware copies seconds to shadow seconds when a read
+	 * of milliseconds occurs. use a lock to keep other threads out. */
+	spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+
+	msec = readl(info->rtc_base + TEGRA_RTC_REG_MILLI_SECONDS);
+	sec = readl(info->rtc_base + TEGRA_RTC_REG_SHADOW_SECONDS);
+
+	spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+
+	rtc_time_to_tm(sec, tm);
+
+	dev_vdbg(dev, "time read as %lu. %d/%d/%d %d:%02u:%02u\n",
+		sec,
+		tm->tm_mon + 1,
+		tm->tm_mday,
+		tm->tm_year + 1900,
+		tm->tm_hour,
+		tm->tm_min,
+		tm->tm_sec
+	);
+
+	return 0;
+}
+
+static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec;
+	int ret;
+
+	/* convert tm to seconds. */
+	ret = rtc_valid_tm(tm);
+	if (ret)
+		return ret;
+
+	rtc_tm_to_time(tm, &sec);
+
+	dev_vdbg(dev, "time set to %lu. %d/%d/%d %d:%02u:%02u\n",
+		sec,
+		tm->tm_mon+1,
+		tm->tm_mday,
+		tm->tm_year+1900,
+		tm->tm_hour,
+		tm->tm_min,
+		tm->tm_sec
+	);
+
+	/* seconds only written if wait succeeded. */
+	ret = tegra_rtc_wait_while_busy(dev);
+	if (!ret)
+		writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS);
+
+	dev_vdbg(dev, "time read back as %d\n",
+		readl(info->rtc_base + TEGRA_RTC_REG_SECONDS));
+
+	return ret;
+}
+
+static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec;
+	unsigned tmp;
+
+	sec = readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+
+	if (sec == 0) {
+		/* alarm is disabled. */
+		alarm->enabled = 0;
+		alarm->time.tm_mon = -1;
+		alarm->time.tm_mday = -1;
+		alarm->time.tm_year = -1;
+		alarm->time.tm_hour = -1;
+		alarm->time.tm_min = -1;
+		alarm->time.tm_sec = -1;
+	} else {
+		/* alarm is enabled. */
+		alarm->enabled = 1;
+		rtc_time_to_tm(sec, &alarm->time);
+	}
+
+	tmp = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	alarm->pending = (tmp & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0;
+
+	return 0;
+}
+
+static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned status;
+	unsigned long sl_irq_flags;
+
+	tegra_rtc_wait_while_busy(dev);
+	spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+
+	/* read the original value, and OR in the flag. */
+	status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+	if (enabled)
+		status |= TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* set it */
+	else
+		status &= ~TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* clear it */
+
+	writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+
+	spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+
+	return 0;
+}
+
+static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec;
+
+	if (alarm->enabled)
+		rtc_tm_to_time(&alarm->time, &sec);
+	else
+		sec = 0;
+
+	tegra_rtc_wait_while_busy(dev);
+	writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+	dev_vdbg(dev, "alarm read back as %d\n",
+		readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0));
+
+	/* if successfully written and alarm is enabled ... */
+	if (sec) {
+		tegra_rtc_alarm_irq_enable(dev, 1);
+
+		dev_vdbg(dev, "alarm set as %lu. %d/%d/%d %d:%02u:%02u\n",
+			sec,
+			alarm->time.tm_mon+1,
+			alarm->time.tm_mday,
+			alarm->time.tm_year+1900,
+			alarm->time.tm_hour,
+			alarm->time.tm_min,
+			alarm->time.tm_sec);
+	} else {
+		/* disable alarm if 0 or write error. */
+		dev_vdbg(dev, "alarm disabled\n");
+		tegra_rtc_alarm_irq_enable(dev, 0);
+	}
+
+	return 0;
+}
+
+static int tegra_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	if (!dev || !dev->driver)
+		return 0;
+
+	return seq_printf(seq, "name\t\t: %s\n", dev_name(dev));
+}
+
+static irqreturn_t tegra_rtc_irq_handler(int irq, void *data)
+{
+	struct device *dev = data;
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long events = 0;
+	unsigned status;
+	unsigned long sl_irq_flags;
+
+	status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	if (status) {
+		/* clear the interrupt masks and status on any irq. */
+		tegra_rtc_wait_while_busy(dev);
+		spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+		writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+		writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+		spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+	}
+
+	/* check if Alarm */
+	if ((status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0))
+		events |= RTC_IRQF | RTC_AF;
+
+	/* check if Periodic */
+	if ((status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM))
+		events |= RTC_IRQF | RTC_PF;
+
+	rtc_update_irq(info->rtc_dev, 1, events);
+
+	return IRQ_HANDLED;
+}
+
+static struct rtc_class_ops tegra_rtc_ops = {
+	.read_time	= tegra_rtc_read_time,
+	.set_time	= tegra_rtc_set_time,
+	.read_alarm	= tegra_rtc_read_alarm,
+	.set_alarm	= tegra_rtc_set_alarm,
+	.proc		= tegra_rtc_proc,
+	.alarm_irq_enable = tegra_rtc_alarm_irq_enable,
+};
+
+static int __devinit tegra_rtc_probe(struct platform_device *pdev)
+{
+	struct tegra_rtc_info *info;
+	struct resource *res;
+	int ret;
+
+	info = kzalloc(sizeof(struct tegra_rtc_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Unable to allocate resources for device.\n");
+		ret = -EBUSY;
+		goto err_free_info;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev,
+			"Unable to request mem region for device.\n");
+		ret = -EBUSY;
+		goto err_free_info;
+	}
+
+	info->tegra_rtc_irq = platform_get_irq(pdev, 0);
+	if (info->tegra_rtc_irq <= 0) {
+		ret = -EBUSY;
+		goto err_release_mem_region;
+	}
+
+	info->rtc_base = ioremap_nocache(res->start, resource_size(res));
+	if (!info->rtc_base) {
+		dev_err(&pdev->dev, "Unable to grab IOs for device.\n");
+		ret = -EBUSY;
+		goto err_release_mem_region;
+	}
+
+	/* set context info. */
+	info->pdev = pdev;
+	info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock);
+
+	platform_set_drvdata(pdev, info);
+
+	/* clear out the hardware. */
+	writel(0, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+	writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	info->rtc_dev = rtc_device_register(
+		pdev->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",
+			ret);
+		goto err_iounmap;
+	}
+
+	ret = request_irq(info->tegra_rtc_irq, tegra_rtc_irq_handler,
+		IRQF_TRIGGER_HIGH, "rtc alarm", &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Unable to request interrupt for device (err=%d).\n",
+			ret);
+		goto err_dev_unreg;
+	}
+
+	dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
+
+	return 0;
+
+err_dev_unreg:
+	rtc_device_unregister(info->rtc_dev);
+err_iounmap:
+	iounmap(info->rtc_base);
+err_release_mem_region:
+	release_mem_region(res->start, resource_size(res));
+err_free_info:
+	kfree(info);
+
+	return ret;
+}
+
+static int __devexit tegra_rtc_remove(struct platform_device *pdev)
+{
+	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EBUSY;
+
+	free_irq(info->tegra_rtc_irq, &pdev->dev);
+	rtc_device_unregister(info->rtc_dev);
+	iounmap(info->rtc_base);
+	release_mem_region(res->start, resource_size(res));
+	kfree(info);
+
+	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);
+
+	tegra_rtc_wait_while_busy(dev);
+
+	/* only use ALARM0 as a wake source. */
+	writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	writel(TEGRA_RTC_INTR_STATUS_SEC_ALARM0,
+		info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+
+	dev_vdbg(dev, "alarm sec = %d\n",
+		readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0));
+
+	dev_vdbg(dev, "Suspend (device_may_wakeup=%d) irq:%d\n",
+		device_may_wakeup(dev), info->tegra_rtc_irq);
+
+	/* leave the alarms on as a wake source. */
+	if (device_may_wakeup(dev))
+		enable_irq_wake(info->tegra_rtc_irq);
+
+	return 0;
+}
+
+static int tegra_rtc_resume(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+
+	dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n",
+		device_may_wakeup(dev));
+	/* alarms were left on as a wake source, turn them off. */
+	if (device_may_wakeup(dev))
+		disable_irq_wake(info->tegra_rtc_irq);
+
+	return 0;
+}
+#endif
+
+static void tegra_rtc_shutdown(struct platform_device *pdev)
+{
+	dev_vdbg(&pdev->dev, "disabling interrupts.\n");
+	tegra_rtc_alarm_irq_enable(&pdev->dev, 0);
+}
+
+MODULE_ALIAS("platform:tegra_rtc");
+static struct platform_driver tegra_rtc_driver = {
+	.remove		= __devexit_p(tegra_rtc_remove),
+	.shutdown	= tegra_rtc_shutdown,
+	.driver		= {
+		.name	= "tegra_rtc",
+		.owner	= THIS_MODULE,
+	},
+#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_AUTHOR("Jon Mayo <jmayo@nvidia.com>");
+MODULE_DESCRIPTION("driver for Tegra internal RTC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index a82d6fe..7e96254 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -78,11 +78,16 @@ static ssize_t test_irq_store(struct device *dev,
 	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
 	retval = count;
-	if (strncmp(buf, "tick", 4) == 0)
+	if (strncmp(buf, "tick", 4) == 0 && rtc->pie_enabled)
 		rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF);
-	else if (strncmp(buf, "alarm", 5) == 0)
-		rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
-	else if (strncmp(buf, "update", 6) == 0)
+	else if (strncmp(buf, "alarm", 5) == 0) {
+		struct rtc_wkalrm alrm;
+		int err = rtc_read_alarm(rtc, &alrm);
+
+		if (!err && alrm.enabled)
+			rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
+
+	} else if (strncmp(buf, "update", 6) == 0 && rtc->uie_rtctimer.enabled)
 		rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF);
 	else
 		retval = -EINVAL;
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index ed1b868..f9a2799 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -213,18 +213,6 @@ static int twl_rtc_alarm_irq_enable(struct device *dev, unsigned enabled)
 	return ret;
 }
 
-static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled)
-{
-	int ret;
-
-	if (enabled)
-		ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-	else
-		ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-
-	return ret;
-}
-
 /*
  * Gets current TWL RTC time and date parameters.
  *
@@ -433,7 +421,6 @@ static struct rtc_class_ops twl_rtc_ops = {
 	.read_alarm	= twl_rtc_read_alarm,
 	.set_alarm	= twl_rtc_set_alarm,
 	.alarm_irq_enable = twl_rtc_alarm_irq_enable,
-	.update_irq_enable = twl_rtc_update_irq_enable,
 };
 
 /*----------------------------------------------------------------------*/
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 769190a..c5698cd 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -207,36 +207,6 @@ static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
 	return 0;
 }
 
-static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
-{
-	u64 count;
-
-	if (!is_power_of_2(freq))
-		return -EINVAL;
-	count = RTC_FREQUENCY;
-	do_div(count, freq);
-
-	spin_lock_irq(&rtc_lock);
-
-	periodic_count = count;
-	rtc1_write(RTCL1LREG, periodic_count);
-	rtc1_write(RTCL1HREG, periodic_count >> 16);
-
-	spin_unlock_irq(&rtc_lock);
-
-	return 0;
-}
-
-static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled)
-{
-	if (enabled)
-		enable_irq(pie_irq);
-	else
-		disable_irq(pie_irq);
-
-	return 0;
-}
-
 static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
 	switch (cmd) {
@@ -308,8 +278,6 @@ static const struct rtc_class_ops vr41xx_rtc_ops = {
 	.set_time	= vr41xx_rtc_set_time,
 	.read_alarm	= vr41xx_rtc_read_alarm,
 	.set_alarm	= vr41xx_rtc_set_alarm,
-	.irq_set_freq	= vr41xx_rtc_irq_set_freq,
-	.irq_set_state	= vr41xx_rtc_irq_set_state,
 };
 
 static int __devinit rtc_probe(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index 82931dc..bdc909b 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -315,21 +315,6 @@ static int wm831x_rtc_alarm_irq_enable(struct device *dev,
 		return wm831x_rtc_stop_alarm(wm831x_rtc);
 }
 
-static int wm831x_rtc_update_irq_enable(struct device *dev,
-					unsigned int enabled)
-{
-	struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev);
-	int val;
-
-	if (enabled)
-		val = 1 << WM831X_RTC_PINT_FREQ_SHIFT;
-	else
-		val = 0;
-
-	return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL,
-			       WM831X_RTC_PINT_FREQ_MASK, val);
-}
-
 static irqreturn_t wm831x_alm_irq(int irq, void *data)
 {
 	struct wm831x_rtc *wm831x_rtc = data;
@@ -354,7 +339,6 @@ static const struct rtc_class_ops wm831x_rtc_ops = {
 	.read_alarm = wm831x_rtc_readalarm,
 	.set_alarm = wm831x_rtc_setalarm,
 	.alarm_irq_enable = wm831x_rtc_alarm_irq_enable,
-	.update_irq_enable = wm831x_rtc_update_irq_enable,
 };
 
 #ifdef CONFIG_PM
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index 3d0dc76..6642142 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -302,26 +302,6 @@ static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	return ret;
 }
 
-static int wm8350_rtc_update_irq_enable(struct device *dev,
-					unsigned int enabled)
-{
-	struct wm8350 *wm8350 = dev_get_drvdata(dev);
-
-	/* Suppress duplicate changes since genirq nests enable and
-	 * disable calls. */
-	if (enabled == wm8350->rtc.update_enabled)
-		return 0;
-
-	if (enabled)
-		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
-	else
-		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
-
-	wm8350->rtc.update_enabled = enabled;
-
-	return 0;
-}
-
 static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data)
 {
 	struct wm8350 *wm8350 = data;
@@ -357,7 +337,6 @@ static const struct rtc_class_ops wm8350_rtc_ops = {
 	.read_alarm = wm8350_rtc_readalarm,
 	.set_alarm = wm8350_rtc_setalarm,
 	.alarm_irq_enable = wm8350_rtc_alarm_irq_enable,
-	.update_irq_enable = wm8350_rtc_update_irq_enable,
 };
 
 #ifdef CONFIG_PM
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index a9fe23d..379d859 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2648,6 +2648,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
 		dasd_sfree_request(cqr, startdev);
 		return ERR_PTR(-EAGAIN);
 	}
+	len_to_track_end = 0;
 	/*
 	 * A tidaw can address 4k of memory, but must not cross page boundaries
 	 * We can let the block layer handle this by setting
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index 5ad44da..8065881 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -455,9 +455,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs,
 	return 0;
 }
 
-int
-kbd_ioctl(struct kbd_data *kbd, struct file *file,
-	  unsigned int cmd, unsigned long arg)
+int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
 {
 	void __user *argp;
 	unsigned int ct;
diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h
index 5ccfe9c..7e736aa 100644
--- a/drivers/s390/char/keyboard.h
+++ b/drivers/s390/char/keyboard.h
@@ -36,7 +36,7 @@ void kbd_free(struct kbd_data *);
 void kbd_ascebc(struct kbd_data *, unsigned char *);
 
 void kbd_keycode(struct kbd_data *, unsigned int);
-int kbd_ioctl(struct kbd_data *, struct file *, unsigned int, unsigned long);
+int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
 
 /*
  * Helper Functions.
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 911822db..d33554df 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -1718,9 +1718,8 @@ tty3270_wait_until_sent(struct tty_struct *tty, int timeout)
 {
 }
 
-static int
-tty3270_ioctl(struct tty_struct *tty, struct file *file,
-	      unsigned int cmd, unsigned long arg)
+static int tty3270_ioctl(struct tty_struct *tty, unsigned int cmd,
+			 unsigned long arg)
 {
 	struct tty3270 *tp;
 
@@ -1729,13 +1728,12 @@ tty3270_ioctl(struct tty_struct *tty, struct file *file,
 		return -ENODEV;
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
-	return kbd_ioctl(tp->kbd, file, cmd, arg);
+	return kbd_ioctl(tp->kbd, cmd, arg);
 }
 
 #ifdef CONFIG_COMPAT
-static long
-tty3270_compat_ioctl(struct tty_struct *tty, struct file *file,
-	      unsigned int cmd, unsigned long arg)
+static long tty3270_compat_ioctl(struct tty_struct *tty,
+				 unsigned int cmd, unsigned long arg)
 {
 	struct tty3270 *tp;
 
@@ -1744,7 +1742,7 @@ tty3270_compat_ioctl(struct tty_struct *tty, struct file *file,
 		return -ENODEV;
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
-	return kbd_ioctl(tp->kbd, file, cmd, (unsigned long)compat_ptr(arg));
+	return kbd_ioctl(tp->kbd, cmd, (unsigned long)compat_ptr(arg));
 }
 #endif
 
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 3c3f3ff..e950f1a 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
 
 static void chsc_subchannel_irq(struct subchannel *sch)
 {
-	struct chsc_private *private = sch->private;
+	struct chsc_private *private = dev_get_drvdata(&sch->dev);
 	struct chsc_request *request = private->request;
 	struct irb *irb = (struct irb *)&S390_lowcore.irb;
 
@@ -80,13 +80,14 @@ static int chsc_subchannel_probe(struct subchannel *sch)
 	private = kzalloc(sizeof(*private), GFP_KERNEL);
 	if (!private)
 		return -ENOMEM;
+	dev_set_drvdata(&sch->dev, private);
 	ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
 	if (ret) {
 		CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
 			 sch->schid.ssid, sch->schid.sch_no, ret);
+		dev_set_drvdata(&sch->dev, NULL);
 		kfree(private);
 	} else {
-		sch->private = private;
 		if (dev_get_uevent_suppress(&sch->dev)) {
 			dev_set_uevent_suppress(&sch->dev, 0);
 			kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
@@ -100,8 +101,8 @@ static int chsc_subchannel_remove(struct subchannel *sch)
 	struct chsc_private *private;
 
 	cio_disable_subchannel(sch);
-	private = sch->private;
-	sch->private = NULL;
+	private = dev_get_drvdata(&sch->dev);
+	dev_set_drvdata(&sch->dev, NULL);
 	if (private->request) {
 		complete(&private->request->completion);
 		put_device(&sch->dev);
@@ -147,7 +148,10 @@ static struct css_device_id chsc_subchannel_ids[] = {
 MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
 
 static struct css_driver chsc_subchannel_driver = {
-	.owner = THIS_MODULE,
+	.drv = {
+		.owner = THIS_MODULE,
+		.name = "chsc_subchannel",
+	},
 	.subchannel_type = chsc_subchannel_ids,
 	.irq = chsc_subchannel_irq,
 	.probe = chsc_subchannel_probe,
@@ -157,7 +161,6 @@ static struct css_driver chsc_subchannel_driver = {
 	.freeze = chsc_subchannel_freeze,
 	.thaw = chsc_subchannel_restore,
 	.restore = chsc_subchannel_restore,
-	.name = "chsc_subchannel",
 };
 
 static int __init chsc_init_dbfs(void)
@@ -241,7 +244,7 @@ static int chsc_async(struct chsc_async_area *chsc_area,
 	chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
 	while ((sch = chsc_get_next_subchannel(sch))) {
 		spin_lock(sch->lock);
-		private = sch->private;
+		private = dev_get_drvdata(&sch->dev);
 		if (private->request) {
 			spin_unlock(sch->lock);
 			ret = -EBUSY;
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 430f875..cbde448 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -84,29 +84,14 @@ out_unregister:
 
 arch_initcall (cio_debug_init);
 
-int
-cio_set_options (struct subchannel *sch, int flags)
+int cio_set_options(struct subchannel *sch, int flags)
 {
-       sch->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
-       sch->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
-       sch->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
-       return 0;
-}
+	struct io_subchannel_private *priv = to_io_private(sch);
 
-/* FIXME: who wants to use this? */
-int
-cio_get_options (struct subchannel *sch)
-{
-       int flags;
-
-       flags = 0;
-       if (sch->options.suspend)
-		flags |= DOIO_ALLOW_SUSPEND;
-       if (sch->options.prefetch)
-		flags |= DOIO_DENY_PREFETCH;
-       if (sch->options.inter)
-		flags |= DOIO_SUPPRESS_INTER;
-       return flags;
+	priv->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
+	priv->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
+	priv->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
+	return 0;
 }
 
 static int
@@ -139,21 +124,21 @@ cio_start_key (struct subchannel *sch,	/* subchannel structure */
 	       __u8 lpm,		/* logical path mask */
 	       __u8 key)                /* storage key */
 {
+	struct io_subchannel_private *priv = to_io_private(sch);
+	union orb *orb = &priv->orb;
 	int ccode;
-	union orb *orb;
 
 	CIO_TRACE_EVENT(5, "stIO");
 	CIO_TRACE_EVENT(5, dev_name(&sch->dev));
 
-	orb = &to_io_private(sch)->orb;
 	memset(orb, 0, sizeof(union orb));
 	/* sch is always under 2G. */
 	orb->cmd.intparm = (u32)(addr_t)sch;
 	orb->cmd.fmt = 1;
 
-	orb->cmd.pfch = sch->options.prefetch == 0;
-	orb->cmd.spnd = sch->options.suspend;
-	orb->cmd.ssic = sch->options.suspend && sch->options.inter;
+	orb->cmd.pfch = priv->options.prefetch == 0;
+	orb->cmd.spnd = priv->options.suspend;
+	orb->cmd.ssic = priv->options.suspend && priv->options.inter;
 	orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm;
 #ifdef CONFIG_64BIT
 	/*
@@ -630,11 +615,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs)
 	irb = (struct irb *)&S390_lowcore.irb;
 	do {
 		kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
-		/*
-		 * Non I/O-subchannel thin interrupts are processed differently
-		 */
-		if (tpi_info->adapter_IO == 1 &&
-		    tpi_info->int_type == IO_INTERRUPT_TYPE) {
+		if (tpi_info->adapter_IO) {
 			do_adapter_IO(tpi_info->isc);
 			continue;
 		}
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index bf7f80f..155a82b 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -84,13 +84,6 @@ struct subchannel {
 		SUBCHANNEL_TYPE_MSG = 2,
 		SUBCHANNEL_TYPE_ADM = 3,
 	} st;			/* subchannel type */
-
-	struct {
-		unsigned int suspend:1; /* allow suspend */
-		unsigned int prefetch:1;/* deny prefetch */
-		unsigned int inter:1;   /* suppress intermediate interrupts */
-	} __attribute__ ((packed)) options;
-
 	__u8 vpm;		/* verified path mask */
 	__u8 lpm;		/* logical path mask */
 	__u8 opm;               /* operational path mask */
@@ -99,14 +92,11 @@ struct subchannel {
 	struct chsc_ssd_info ssd_info;	/* subchannel description */
 	struct device dev;	/* entry in device tree */
 	struct css_driver *driver;
-	void *private; /* private per subchannel type data */
 	enum sch_todo todo;
 	struct work_struct todo_work;
 	struct schib_config config;
 } __attribute__ ((aligned(8)));
 
-#define IO_INTERRUPT_TYPE	   0 /* I/O interrupt type */
-
 #define to_subchannel(n) container_of(n, struct subchannel, dev)
 
 extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
@@ -120,7 +110,6 @@ extern int cio_start (struct subchannel *, struct ccw1 *, __u8);
 extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8);
 extern int cio_cancel (struct subchannel *);
 extern int cio_set_options (struct subchannel *, int);
-extern int cio_get_options (struct subchannel *);
 extern int cio_update_schib(struct subchannel *sch);
 extern int cio_commit_config(struct subchannel *sch);
 
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 24d8e97..c47b25f 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -35,6 +35,7 @@ int css_init_done = 0;
 int max_ssid;
 
 struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1];
+static struct bus_type css_bus_type;
 
 int
 for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
@@ -1214,7 +1215,7 @@ static const struct dev_pm_ops css_pm_ops = {
 	.restore = css_pm_restore,
 };
 
-struct bus_type css_bus_type = {
+static struct bus_type css_bus_type = {
 	.name     = "css",
 	.match    = css_bus_match,
 	.probe    = css_probe,
@@ -1233,9 +1234,7 @@ struct bus_type css_bus_type = {
  */
 int css_driver_register(struct css_driver *cdrv)
 {
-	cdrv->drv.name = cdrv->name;
 	cdrv->drv.bus = &css_bus_type;
-	cdrv->drv.owner = cdrv->owner;
 	return driver_register(&cdrv->drv);
 }
 EXPORT_SYMBOL_GPL(css_driver_register);
@@ -1253,4 +1252,3 @@ void css_driver_unregister(struct css_driver *cdrv)
 EXPORT_SYMBOL_GPL(css_driver_unregister);
 
 MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(css_bus_type);
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 7e37886..80ebddd 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -63,7 +63,6 @@ struct subchannel;
 struct chp_link;
 /**
  * struct css_driver - device driver for subchannels
- * @owner: owning module
  * @subchannel_type: subchannel type supported by this driver
  * @drv: embedded device driver structure
  * @irq: called on interrupts
@@ -78,10 +77,8 @@ struct chp_link;
  * @thaw: undo work done in @freeze
  * @restore: callback for restoring after hibernation
  * @settle: wait for asynchronous work to finish
- * @name: name of the device driver
  */
 struct css_driver {
-	struct module *owner;
 	struct css_device_id *subchannel_type;
 	struct device_driver drv;
 	void (*irq)(struct subchannel *);
@@ -96,16 +93,10 @@ struct css_driver {
 	int (*thaw) (struct subchannel *);
 	int (*restore)(struct subchannel *);
 	int (*settle)(void);
-	const char *name;
 };
 
 #define to_cssdriver(n) container_of(n, struct css_driver, drv)
 
-/*
- * all css_drivers have the css_bus_type
- */
-extern struct bus_type css_bus_type;
-
 extern int css_driver_register(struct css_driver *);
 extern void css_driver_unregister(struct css_driver *);
 
@@ -140,7 +131,6 @@ struct channel_subsystem {
 };
 #define to_css(dev) container_of(dev, struct channel_subsystem, device)
 
-extern struct bus_type css_bus_type;
 extern struct channel_subsystem *channel_subsystems[];
 
 /* Helper functions to build lists for the slow path. */
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index b7eaff9..e50b121 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -172,9 +172,11 @@ static int io_subchannel_settle(void)
 }
 
 static struct css_driver io_subchannel_driver = {
-	.owner = THIS_MODULE,
+	.drv = {
+		.owner = THIS_MODULE,
+		.name = "io_subchannel",
+	},
 	.subchannel_type = io_subchannel_ids,
-	.name = "io_subchannel",
 	.irq = io_subchannel_irq,
 	.sch_event = io_subchannel_sch_event,
 	.chp_event = io_subchannel_chp_event,
@@ -1030,6 +1032,7 @@ static void io_subchannel_init_fields(struct subchannel *sch)
  */
 static int io_subchannel_probe(struct subchannel *sch)
 {
+	struct io_subchannel_private *io_priv;
 	struct ccw_device *cdev;
 	int rc;
 
@@ -1073,10 +1076,11 @@ static int io_subchannel_probe(struct subchannel *sch)
 	if (rc)
 		goto out_schedule;
 	/* Allocate I/O subchannel private data. */
-	sch->private = kzalloc(sizeof(struct io_subchannel_private),
-			       GFP_KERNEL | GFP_DMA);
-	if (!sch->private)
+	io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
+	if (!io_priv)
 		goto out_schedule;
+
+	set_io_private(sch, io_priv);
 	css_schedule_eval(sch->schid);
 	return 0;
 
@@ -1090,6 +1094,7 @@ out_schedule:
 static int
 io_subchannel_remove (struct subchannel *sch)
 {
+	struct io_subchannel_private *io_priv = to_io_private(sch);
 	struct ccw_device *cdev;
 
 	cdev = sch_get_cdev(sch);
@@ -1099,11 +1104,12 @@ io_subchannel_remove (struct subchannel *sch)
 	/* Set ccw device to not operational and drop reference. */
 	spin_lock_irq(cdev->ccwlock);
 	sch_set_cdev(sch, NULL);
+	set_io_private(sch, NULL);
 	cdev->private->state = DEV_STATE_NOT_OPER;
 	spin_unlock_irq(cdev->ccwlock);
 	ccw_device_unregister(cdev);
 out_free:
-	kfree(sch->private);
+	kfree(io_priv);
 	sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
 	return 0;
 }
@@ -1553,11 +1559,12 @@ spinlock_t * cio_get_console_lock(void)
 static int ccw_device_console_enable(struct ccw_device *cdev,
 				     struct subchannel *sch)
 {
+	struct io_subchannel_private *io_priv = cio_get_console_priv();
 	int rc;
 
 	/* Attach subchannel private data. */
-	sch->private = cio_get_console_priv();
-	memset(sch->private, 0, sizeof(struct io_subchannel_private));
+	memset(io_priv, 0, sizeof(*io_priv));
+	set_io_private(sch, io_priv);
 	io_subchannel_init_fields(sch);
 	rc = cio_commit_config(sch);
 	if (rc)
diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h
index d024d2c..ba31ad8 100644
--- a/drivers/s390/cio/io_sch.h
+++ b/drivers/s390/cio/io_sch.h
@@ -5,68 +5,36 @@
 #include <asm/schid.h>
 #include <asm/ccwdev.h>
 #include "css.h"
-
-/*
- * command-mode operation request block
- */
-struct cmd_orb {
-	u32 intparm;	/* interruption parameter */
-	u32 key  : 4;	/* flags, like key, suspend control, etc. */
-	u32 spnd : 1;	/* suspend control */
-	u32 res1 : 1;	/* reserved */
-	u32 mod  : 1;	/* modification control */
-	u32 sync : 1;	/* synchronize control */
-	u32 fmt  : 1;	/* format control */
-	u32 pfch : 1;	/* prefetch control */
-	u32 isic : 1;	/* initial-status-interruption control */
-	u32 alcc : 1;	/* address-limit-checking control */
-	u32 ssic : 1;	/* suppress-suspended-interr. control */
-	u32 res2 : 1;	/* reserved */
-	u32 c64  : 1;	/* IDAW/QDIO 64 bit control  */
-	u32 i2k  : 1;	/* IDAW 2/4kB block size control */
-	u32 lpm  : 8;	/* logical path mask */
-	u32 ils  : 1;	/* incorrect length */
-	u32 zero : 6;	/* reserved zeros */
-	u32 orbx : 1;	/* ORB extension control */
-	u32 cpa;	/* channel program address */
-}  __attribute__ ((packed, aligned(4)));
-
-/*
- * transport-mode operation request block
- */
-struct tm_orb {
-	u32 intparm;
-	u32 key:4;
-	u32 :9;
-	u32 b:1;
-	u32 :2;
-	u32 lpm:8;
-	u32 :7;
-	u32 x:1;
-	u32 tcw;
-	u32 prio:8;
-	u32 :8;
-	u32 rsvpgm:8;
-	u32 :8;
-	u32 :32;
-	u32 :32;
-	u32 :32;
-	u32 :32;
-}  __attribute__ ((packed, aligned(4)));
-
-union orb {
-	struct cmd_orb cmd;
-	struct tm_orb tm;
-}  __attribute__ ((packed, aligned(4)));
+#include "orb.h"
 
 struct io_subchannel_private {
 	union orb orb;		/* operation request block */
 	struct ccw1 sense_ccw;	/* static ccw for sense command */
-} __attribute__ ((aligned(8)));
+	struct ccw_device *cdev;/* pointer to the child ccw device */
+	struct {
+		unsigned int suspend:1;	/* allow suspend */
+		unsigned int prefetch:1;/* deny prefetch */
+		unsigned int inter:1;	/* suppress intermediate interrupts */
+	} __packed options;
+} __aligned(8);
 
-#define to_io_private(n) ((struct io_subchannel_private *)n->private)
-#define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
-#define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
+#define to_io_private(n) ((struct io_subchannel_private *) \
+			  dev_get_drvdata(&(n)->dev))
+#define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p))
+
+static inline struct ccw_device *sch_get_cdev(struct subchannel *sch)
+{
+	struct io_subchannel_private *priv = to_io_private(sch);
+	return priv ? priv->cdev : NULL;
+}
+
+static inline void sch_set_cdev(struct subchannel *sch,
+				struct ccw_device *cdev)
+{
+	struct io_subchannel_private *priv = to_io_private(sch);
+	if (priv)
+		priv->cdev = cdev;
+}
 
 #define MAX_CIWS 8
 
@@ -191,23 +159,6 @@ struct ccw_device_private {
 	void *cmb_wait;			/* deferred cmb enable/disable */
 };
 
-static inline int ssch(struct subchannel_id schid, union orb *addr)
-{
-	register struct subchannel_id reg1 asm("1") = schid;
-	int ccode = -EIO;
-
-	asm volatile(
-		"	ssch	0(%2)\n"
-		"0:	ipm	%0\n"
-		"	srl	%0,28\n"
-		"1:\n"
-		EX_TABLE(0b, 1b)
-		: "+d" (ccode)
-		: "d" (reg1), "a" (addr), "m" (*addr)
-		: "cc", "memory");
-	return ccode;
-}
-
 static inline int rsch(struct subchannel_id schid)
 {
 	register struct subchannel_id reg1 asm("1") = schid;
@@ -223,21 +174,6 @@ static inline int rsch(struct subchannel_id schid)
 	return ccode;
 }
 
-static inline int csch(struct subchannel_id schid)
-{
-	register struct subchannel_id reg1 asm("1") = schid;
-	int ccode;
-
-	asm volatile(
-		"	csch\n"
-		"	ipm	%0\n"
-		"	srl	%0,28"
-		: "=d" (ccode)
-		: "d" (reg1)
-		: "cc");
-	return ccode;
-}
-
 static inline int hsch(struct subchannel_id schid)
 {
 	register struct subchannel_id reg1 asm("1") = schid;
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h
index fac0615..4d80fc6 100644
--- a/drivers/s390/cio/ioasm.h
+++ b/drivers/s390/cio/ioasm.h
@@ -3,6 +3,8 @@
 
 #include <asm/chpid.h>
 #include <asm/schid.h>
+#include "orb.h"
+#include "cio.h"
 
 /*
  * TPI info structure
@@ -87,6 +89,38 @@ static inline int tsch(struct subchannel_id schid, struct irb *addr)
 	return ccode;
 }
 
+static inline int ssch(struct subchannel_id schid, union orb *addr)
+{
+	register struct subchannel_id reg1 asm("1") = schid;
+	int ccode = -EIO;
+
+	asm volatile(
+		"	ssch	0(%2)\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
+		"1:\n"
+		EX_TABLE(0b, 1b)
+		: "+d" (ccode)
+		: "d" (reg1), "a" (addr), "m" (*addr)
+		: "cc", "memory");
+	return ccode;
+}
+
+static inline int csch(struct subchannel_id schid)
+{
+	register struct subchannel_id reg1 asm("1") = schid;
+	int ccode;
+
+	asm volatile(
+		"	csch\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode)
+		: "d" (reg1)
+		: "cc");
+	return ccode;
+}
+
 static inline int tpi(struct tpi_info *addr)
 {
 	int ccode;
diff --git a/drivers/s390/cio/orb.h b/drivers/s390/cio/orb.h
new file mode 100644
index 0000000..45a9865
--- /dev/null
+++ b/drivers/s390/cio/orb.h
@@ -0,0 +1,67 @@
+/*
+ * Orb related data structures.
+ *
+ * Copyright IBM Corp. 2007, 2011
+ *
+ * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ *	      Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ *	      Sebastian Ott <sebott@linux.vnet.ibm.com>
+ */
+
+#ifndef S390_ORB_H
+#define S390_ORB_H
+
+/*
+ * Command-mode operation request block
+ */
+struct cmd_orb {
+	u32 intparm;	/* interruption parameter */
+	u32 key:4;	/* flags, like key, suspend control, etc. */
+	u32 spnd:1;	/* suspend control */
+	u32 res1:1;	/* reserved */
+	u32 mod:1;	/* modification control */
+	u32 sync:1;	/* synchronize control */
+	u32 fmt:1;	/* format control */
+	u32 pfch:1;	/* prefetch control */
+	u32 isic:1;	/* initial-status-interruption control */
+	u32 alcc:1;	/* address-limit-checking control */
+	u32 ssic:1;	/* suppress-suspended-interr. control */
+	u32 res2:1;	/* reserved */
+	u32 c64:1;	/* IDAW/QDIO 64 bit control  */
+	u32 i2k:1;	/* IDAW 2/4kB block size control */
+	u32 lpm:8;	/* logical path mask */
+	u32 ils:1;	/* incorrect length */
+	u32 zero:6;	/* reserved zeros */
+	u32 orbx:1;	/* ORB extension control */
+	u32 cpa;	/* channel program address */
+}  __packed __aligned(4);
+
+/*
+ * Transport-mode operation request block
+ */
+struct tm_orb {
+	u32 intparm;
+	u32 key:4;
+	u32:9;
+	u32 b:1;
+	u32:2;
+	u32 lpm:8;
+	u32:7;
+	u32 x:1;
+	u32 tcw;
+	u32 prio:8;
+	u32:8;
+	u32 rsvpgm:8;
+	u32:8;
+	u32:32;
+	u32:32;
+	u32:32;
+	u32:32;
+}  __packed __aligned(4);
+
+union orb {
+	struct cmd_orb cmd;
+	struct tm_orb tm;
+}  __packed __aligned(4);
+
+#endif /* S390_ORB_H */
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index f47a714..af3f7b0 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -225,7 +225,8 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
 /*****************************************************************************/
 #define QETH_MAX_QUEUES 4
 #define QETH_IN_BUF_SIZE_DEFAULT 65536
-#define QETH_IN_BUF_COUNT_DEFAULT 16
+#define QETH_IN_BUF_COUNT_DEFAULT 64
+#define QETH_IN_BUF_COUNT_HSDEFAULT 128
 #define QETH_IN_BUF_COUNT_MIN 8
 #define QETH_IN_BUF_COUNT_MAX 128
 #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
@@ -741,7 +742,6 @@ struct qeth_card {
 	/* QDIO buffer handling */
 	struct qeth_qdio_info qdio;
 	struct qeth_perf_stats perf_stats;
-	int use_hard_stop;
 	int read_or_write_problem;
 	struct qeth_osn_info osn_info;
 	struct qeth_discipline discipline;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 019ae58..25eef304 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -302,12 +302,15 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,
 	int com = cmd->hdr.command;
 	ipa_name = qeth_get_ipa_cmd_name(com);
 	if (rc)
-		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s returned x%X \"%s\"\n",
-				ipa_name, com, QETH_CARD_IFNAME(card),
-					rc, qeth_get_ipa_msg(rc));
+		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned "
+				"x%X \"%s\"\n",
+				ipa_name, com, dev_name(&card->gdev->dev),
+				QETH_CARD_IFNAME(card), rc,
+				qeth_get_ipa_msg(rc));
 	else
-		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s succeeded\n",
-				ipa_name, com, QETH_CARD_IFNAME(card));
+		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n",
+				ipa_name, com, dev_name(&card->gdev->dev),
+				QETH_CARD_IFNAME(card));
 }
 
 static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
@@ -1023,7 +1026,10 @@ static void qeth_init_qdio_info(struct qeth_card *card)
 	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
 	/* inbound */
 	card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
-	card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
+	if (card->info.type == QETH_CARD_TYPE_IQD)
+		card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_HSDEFAULT;
+	else
+		card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
 	card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
 	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
 	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
@@ -1083,7 +1089,6 @@ static int qeth_setup_card(struct qeth_card *card)
 	card->data.state  = CH_STATE_DOWN;
 	card->state = CARD_STATE_DOWN;
 	card->lan_online = 0;
-	card->use_hard_stop = 0;
 	card->read_or_write_problem = 0;
 	card->dev = NULL;
 	spin_lock_init(&card->vlanlock);
@@ -1732,20 +1737,22 @@ int qeth_send_control_data(struct qeth_card *card, int len,
 		};
 	}
 
+	if (reply->rc == -EIO)
+		goto error;
 	rc = reply->rc;
 	qeth_put_reply(reply);
 	return rc;
 
 time_err:
+	reply->rc = -ETIME;
 	spin_lock_irqsave(&reply->card->lock, flags);
 	list_del_init(&reply->list);
 	spin_unlock_irqrestore(&reply->card->lock, flags);
-	reply->rc = -ETIME;
 	atomic_inc(&reply->received);
+error:
 	atomic_set(&card->write.irq_pending, 0);
 	qeth_release_buffer(iob->channel, iob);
 	card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
-	wake_up(&reply->wait_q);
 	rc = reply->rc;
 	qeth_put_reply(reply);
 	return rc;
@@ -2490,45 +2497,19 @@ int qeth_send_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
 }
 EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
 
-static int qeth_send_startstoplan(struct qeth_card *card,
-		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, prot);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
-	return rc;
-}
-
 int qeth_send_startlan(struct qeth_card *card)
 {
 	int rc;
+	struct qeth_cmd_buffer *iob;
 
 	QETH_DBF_TEXT(SETUP, 2, "strtlan");
 
-	rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, 0);
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0);
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(qeth_send_startlan);
 
-int qeth_send_stoplan(struct qeth_card *card)
-{
-	int rc = 0;
-
-	/*
-	 * TODO: according to the IPA format document page 14,
-	 * TCP/IP (we!) never issue a STOPLAN
-	 * is this right ?!?
-	 */
-	QETH_DBF_TEXT(SETUP, 2, "stoplan");
-
-	rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 0);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(qeth_send_stoplan);
-
 int qeth_default_setadapterparms_cb(struct qeth_card *card,
 		struct qeth_reply *reply, unsigned long data)
 {
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index ada0fe7..6fbaacb 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -202,17 +202,19 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac)
 		kfree(mc);
 }
 
-static void qeth_l2_del_all_mc(struct qeth_card *card)
+static void qeth_l2_del_all_mc(struct qeth_card *card, int del)
 {
 	struct qeth_mc_mac *mc, *tmp;
 
 	spin_lock_bh(&card->mclock);
 	list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
-		if (mc->is_vmac)
-			qeth_l2_send_setdelmac(card, mc->mc_addr,
+		if (del) {
+			if (mc->is_vmac)
+				qeth_l2_send_setdelmac(card, mc->mc_addr,
 					IPA_CMD_DELVMAC, NULL);
-		else
-			qeth_l2_send_delgroupmac(card, mc->mc_addr);
+			else
+				qeth_l2_send_delgroupmac(card, mc->mc_addr);
+		}
 		list_del(&mc->list);
 		kfree(mc);
 	}
@@ -288,18 +290,13 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
 				 qeth_l2_send_setdelvlan_cb, NULL);
 }
 
-static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
+static void qeth_l2_process_vlans(struct qeth_card *card)
 {
 	struct qeth_vlan_vid *id;
 	QETH_CARD_TEXT(card, 3, "L2prcvln");
 	spin_lock_bh(&card->vlanlock);
 	list_for_each_entry(id, &card->vid_list, list) {
-		if (clear)
-			qeth_l2_send_setdelvlan(card, id->vid,
-				IPA_CMD_DELVLAN);
-		else
-			qeth_l2_send_setdelvlan(card, id->vid,
-				IPA_CMD_SETVLAN);
+		qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
 	}
 	spin_unlock_bh(&card->vlanlock);
 }
@@ -379,19 +376,11 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
 			dev_close(card->dev);
 			rtnl_unlock();
 		}
-		if (!card->use_hard_stop ||
-			recovery_mode) {
-			__u8 *mac = &card->dev->dev_addr[0];
-			rc = qeth_l2_send_delmac(card, mac);
-			QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc);
-		}
+		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 		card->state = CARD_STATE_SOFTSETUP;
 	}
 	if (card->state == CARD_STATE_SOFTSETUP) {
-		qeth_l2_process_vlans(card, 1);
-		if (!card->use_hard_stop ||
-			recovery_mode)
-			qeth_l2_del_all_mc(card);
+		qeth_l2_del_all_mc(card, 0);
 		qeth_clear_ipacmd_list(card);
 		card->state = CARD_STATE_HARDSETUP;
 	}
@@ -405,7 +394,6 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
 		qeth_clear_cmd_buffers(&card->read);
 		qeth_clear_cmd_buffers(&card->write);
 	}
-	card->use_hard_stop = 0;
 	return rc;
 }
 
@@ -705,7 +693,7 @@ static void qeth_l2_set_multicast_list(struct net_device *dev)
 	if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
 	    (card->state != CARD_STATE_UP))
 		return;
-	qeth_l2_del_all_mc(card);
+	qeth_l2_del_all_mc(card, 1);
 	spin_lock_bh(&card->mclock);
 	netdev_for_each_mc_addr(ha, dev)
 		qeth_l2_add_mc(card, ha->addr, 0);
@@ -907,10 +895,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 	qeth_set_allowed_threads(card, 0, 1);
 	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
-	if (cgdev->state == CCWGROUP_ONLINE) {
-		card->use_hard_stop = 1;
+	if (cgdev->state == CCWGROUP_ONLINE)
 		qeth_l2_set_offline(cgdev);
-	}
 
 	if (card->dev) {
 		unregister_netdev(card->dev);
@@ -1040,7 +1026,7 @@ contin:
 
 	if (card->info.type != QETH_CARD_TYPE_OSN &&
 	    card->info.type != QETH_CARD_TYPE_OSM)
-		qeth_l2_process_vlans(card, 0);
+		qeth_l2_process_vlans(card);
 
 	netif_tx_disable(card->dev);
 
@@ -1076,7 +1062,6 @@ contin:
 	return 0;
 
 out_remove:
-	card->use_hard_stop = 1;
 	qeth_l2_stop_card(card, 0);
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
@@ -1144,7 +1129,6 @@ static int qeth_l2_recover(void *ptr)
 	QETH_CARD_TEXT(card, 2, "recover2");
 	dev_warn(&card->gdev->dev,
 		"A recovery process has been started for the device\n");
-	card->use_hard_stop = 1;
 	__qeth_l2_set_offline(card->gdev, 1);
 	rc = __qeth_l2_set_online(card->gdev, 1);
 	if (!rc)
@@ -1191,7 +1175,6 @@ static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
 	if (gdev->state == CCWGROUP_OFFLINE)
 		return 0;
 	if (card->state == CARD_STATE_UP) {
-		card->use_hard_stop = 1;
 		__qeth_l2_set_offline(card->gdev, 1);
 	} else
 		__qeth_l2_set_offline(card->gdev, 0);
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index d09b0c4..142e5f6 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -510,8 +510,7 @@ static void qeth_l3_set_ip_addr_list(struct qeth_card *card)
 	kfree(tbd_list);
 }
 
-static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
-					int recover)
+static void qeth_l3_clear_ip_list(struct qeth_card *card, int recover)
 {
 	struct qeth_ipaddr *addr, *tmp;
 	unsigned long flags;
@@ -530,11 +529,6 @@ static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
 		addr = list_entry(card->ip_list.next,
 				  struct qeth_ipaddr, entry);
 		list_del_init(&addr->entry);
-		if (clean) {
-			spin_unlock_irqrestore(&card->ip_lock, flags);
-			qeth_l3_deregister_addr_entry(card, addr);
-			spin_lock_irqsave(&card->ip_lock, flags);
-		}
 		if (!recover || addr->is_multicast) {
 			kfree(addr);
 			continue;
@@ -1611,29 +1605,6 @@ static int qeth_l3_start_ipassists(struct qeth_card *card)
 	return 0;
 }
 
-static int qeth_l3_put_unique_id(struct qeth_card *card)
-{
-
-	int rc = 0;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_CARD_TEXT(card, 2, "puniqeid");
-
-	if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
-		UNIQUE_ID_NOT_BY_CARD)
-		return -1;
-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
-				     QETH_PROT_IPV6);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
-				card->info.unique_id;
-	memcpy(&cmd->data.create_destroy_addr.unique_id[0],
-	       card->dev->dev_addr, OSA_ADDR_LEN);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-	return rc;
-}
-
 static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
 		struct qeth_reply *reply, unsigned long data)
 {
@@ -2324,25 +2295,14 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
 			dev_close(card->dev);
 			rtnl_unlock();
 		}
-		if (!card->use_hard_stop) {
-			rc = qeth_send_stoplan(card);
-			if (rc)
-				QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
-		}
 		card->state = CARD_STATE_SOFTSETUP;
 	}
 	if (card->state == CARD_STATE_SOFTSETUP) {
-		qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1);
+		qeth_l3_clear_ip_list(card, 1);
 		qeth_clear_ipacmd_list(card);
 		card->state = CARD_STATE_HARDSETUP;
 	}
 	if (card->state == CARD_STATE_HARDSETUP) {
-		if (!card->use_hard_stop &&
-		    (card->info.type != QETH_CARD_TYPE_IQD)) {
-			rc = qeth_l3_put_unique_id(card);
-			if (rc)
-				QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
-		}
 		qeth_qdio_clear_card(card, 0);
 		qeth_clear_qdio_buffers(card);
 		qeth_clear_working_pool_list(card);
@@ -2352,7 +2312,6 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
 		qeth_clear_cmd_buffers(&card->read);
 		qeth_clear_cmd_buffers(&card->write);
 	}
-	card->use_hard_stop = 0;
 	return rc;
 }
 
@@ -3433,6 +3392,8 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 			if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
 				card->dev->dev_id = card->info.unique_id &
 							 0xffff;
+			if (!card->info.guestlan)
+				card->dev->features |= NETIF_F_GRO;
 		}
 	} else if (card->info.type == QETH_CARD_TYPE_IQD) {
 		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
@@ -3471,6 +3432,9 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 	card->discipline.output_handler = (qdio_handler_t *)
 		qeth_qdio_output_handler;
 	card->discipline.recover = qeth_l3_recover;
+	if ((card->info.type == QETH_CARD_TYPE_OSD) ||
+	    (card->info.type == QETH_CARD_TYPE_OSX))
+		card->options.checksum_type = HW_CHECKSUMMING;
 	return 0;
 }
 
@@ -3483,17 +3447,15 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
 	qeth_set_allowed_threads(card, 0, 1);
 	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
-	if (cgdev->state == CCWGROUP_ONLINE) {
-		card->use_hard_stop = 1;
+	if (cgdev->state == CCWGROUP_ONLINE)
 		qeth_l3_set_offline(cgdev);
-	}
 
 	if (card->dev) {
 		unregister_netdev(card->dev);
 		card->dev = NULL;
 	}
 
-	qeth_l3_clear_ip_list(card, 0, 0);
+	qeth_l3_clear_ip_list(card, 0);
 	qeth_l3_clear_ipato_list(card);
 	return;
 }
@@ -3594,7 +3556,6 @@ contin:
 	mutex_unlock(&card->discipline_mutex);
 	return 0;
 out_remove:
-	card->use_hard_stop = 1;
 	qeth_l3_stop_card(card, 0);
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
@@ -3663,7 +3624,6 @@ static int qeth_l3_recover(void *ptr)
 	QETH_CARD_TEXT(card, 2, "recover2");
 	dev_warn(&card->gdev->dev,
 		"A recovery process has been started for the device\n");
-	card->use_hard_stop = 1;
 	__qeth_l3_set_offline(card->gdev, 1);
 	rc = __qeth_l3_set_online(card->gdev, 1);
 	if (!rc)
@@ -3684,7 +3644,6 @@ static int qeth_l3_recover(void *ptr)
 static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	qeth_l3_clear_ip_list(card, 0, 0);
 	qeth_qdio_clear_card(card, 0);
 	qeth_clear_qdio_buffers(card);
 }
@@ -3700,7 +3659,6 @@ static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
 	if (gdev->state == CCWGROUP_OFFLINE)
 		return 0;
 	if (card->state == CARD_STATE_UP) {
-		card->use_hard_stop = 1;
 		__qeth_l3_set_offline(card->gdev, 1);
 	} else
 		__qeth_l3_set_offline(card->gdev, 0);
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 51c666f..645b0fc 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -122,36 +122,21 @@ static int __init zfcp_module_init(void)
 {
 	int retval = -ENOMEM;
 
-	zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn",
-					sizeof(struct zfcp_fc_gpn_ft_req));
-	if (!zfcp_data.gpn_ft_cache)
-		goto out;
-
-	zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb",
-					sizeof(struct fsf_qtcb));
-	if (!zfcp_data.qtcb_cache)
+	zfcp_fsf_qtcb_cache = zfcp_cache_hw_align("zfcp_fsf_qtcb",
+						  sizeof(struct fsf_qtcb));
+	if (!zfcp_fsf_qtcb_cache)
 		goto out_qtcb_cache;
 
-	zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr",
-					sizeof(struct fsf_status_read_buffer));
-	if (!zfcp_data.sr_buffer_cache)
-		goto out_sr_cache;
+	zfcp_fc_req_cache = zfcp_cache_hw_align("zfcp_fc_req",
+						sizeof(struct zfcp_fc_req));
+	if (!zfcp_fc_req_cache)
+		goto out_fc_cache;
 
-	zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid",
-					sizeof(struct zfcp_fc_gid_pn));
-	if (!zfcp_data.gid_pn_cache)
-		goto out_gid_cache;
-
-	zfcp_data.adisc_cache = zfcp_cache_hw_align("zfcp_adisc",
-					sizeof(struct zfcp_fc_els_adisc));
-	if (!zfcp_data.adisc_cache)
-		goto out_adisc_cache;
-
-	zfcp_data.scsi_transport_template =
+	zfcp_scsi_transport_template =
 		fc_attach_transport(&zfcp_transport_functions);
-	if (!zfcp_data.scsi_transport_template)
+	if (!zfcp_scsi_transport_template)
 		goto out_transport;
-	scsi_transport_reserve_device(zfcp_data.scsi_transport_template,
+	scsi_transport_reserve_device(zfcp_scsi_transport_template,
 				      sizeof(struct zfcp_scsi_dev));
 
 
@@ -175,18 +160,12 @@ static int __init zfcp_module_init(void)
 out_ccw_register:
 	misc_deregister(&zfcp_cfdc_misc);
 out_misc:
-	fc_release_transport(zfcp_data.scsi_transport_template);
+	fc_release_transport(zfcp_scsi_transport_template);
 out_transport:
-	kmem_cache_destroy(zfcp_data.adisc_cache);
-out_adisc_cache:
-	kmem_cache_destroy(zfcp_data.gid_pn_cache);
-out_gid_cache:
-	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
-out_sr_cache:
-	kmem_cache_destroy(zfcp_data.qtcb_cache);
+	kmem_cache_destroy(zfcp_fc_req_cache);
+out_fc_cache:
+	kmem_cache_destroy(zfcp_fsf_qtcb_cache);
 out_qtcb_cache:
-	kmem_cache_destroy(zfcp_data.gpn_ft_cache);
-out:
 	return retval;
 }
 
@@ -196,12 +175,9 @@ static void __exit zfcp_module_exit(void)
 {
 	ccw_driver_unregister(&zfcp_ccw_driver);
 	misc_deregister(&zfcp_cfdc_misc);
-	fc_release_transport(zfcp_data.scsi_transport_template);
-	kmem_cache_destroy(zfcp_data.adisc_cache);
-	kmem_cache_destroy(zfcp_data.gid_pn_cache);
-	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
-	kmem_cache_destroy(zfcp_data.qtcb_cache);
-	kmem_cache_destroy(zfcp_data.gpn_ft_cache);
+	fc_release_transport(zfcp_scsi_transport_template);
+	kmem_cache_destroy(zfcp_fc_req_cache);
+	kmem_cache_destroy(zfcp_fsf_qtcb_cache);
 }
 
 module_exit(zfcp_module_exit);
@@ -260,18 +236,18 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
 		return -ENOMEM;
 
 	adapter->pool.qtcb_pool =
-		mempool_create_slab_pool(4, zfcp_data.qtcb_cache);
+		mempool_create_slab_pool(4, zfcp_fsf_qtcb_cache);
 	if (!adapter->pool.qtcb_pool)
 		return -ENOMEM;
 
-	adapter->pool.status_read_data =
-		mempool_create_slab_pool(FSF_STATUS_READS_RECOM,
-					 zfcp_data.sr_buffer_cache);
-	if (!adapter->pool.status_read_data)
+	BUILD_BUG_ON(sizeof(struct fsf_status_read_buffer) > PAGE_SIZE);
+	adapter->pool.sr_data =
+		mempool_create_page_pool(FSF_STATUS_READS_RECOM, 0);
+	if (!adapter->pool.sr_data)
 		return -ENOMEM;
 
 	adapter->pool.gid_pn =
-		mempool_create_slab_pool(1, zfcp_data.gid_pn_cache);
+		mempool_create_slab_pool(1, zfcp_fc_req_cache);
 	if (!adapter->pool.gid_pn)
 		return -ENOMEM;
 
@@ -290,8 +266,8 @@ static void zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter)
 		mempool_destroy(adapter->pool.qtcb_pool);
 	if (adapter->pool.status_read_req)
 		mempool_destroy(adapter->pool.status_read_req);
-	if (adapter->pool.status_read_data)
-		mempool_destroy(adapter->pool.status_read_data);
+	if (adapter->pool.sr_data)
+		mempool_destroy(adapter->pool.sr_data);
 	if (adapter->pool.gid_pn)
 		mempool_destroy(adapter->pool.gid_pn);
 }
@@ -386,6 +362,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
 	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
 	INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
+	INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
 
 	if (zfcp_qdio_setup(adapter))
 		goto failed;
@@ -437,7 +414,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 	adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
 	adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
-	if (!zfcp_adapter_scsi_register(adapter))
+	if (!zfcp_scsi_adapter_register(adapter))
 		return adapter;
 
 failed:
@@ -451,10 +428,11 @@ void zfcp_adapter_unregister(struct zfcp_adapter *adapter)
 
 	cancel_work_sync(&adapter->scan_work);
 	cancel_work_sync(&adapter->stat_work);
+	cancel_work_sync(&adapter->ns_up_work);
 	zfcp_destroy_adapter_work_queue(adapter);
 
 	zfcp_fc_wka_ports_force_offline(adapter->gs);
-	zfcp_adapter_scsi_unregister(adapter);
+	zfcp_scsi_adapter_unregister(adapter);
 	sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
 
 	zfcp_erp_thread_kill(adapter);
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 9ae1d0a..527ba48 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -89,7 +89,6 @@ struct zfcp_reqlist;
 #define ZFCP_STATUS_LUN_READONLY		0x00000008
 
 /* FSF request status (this does not have a common part) */
-#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT	0x00000002
 #define ZFCP_STATUS_FSFREQ_ERROR		0x00000008
 #define ZFCP_STATUS_FSFREQ_CLEANUP		0x00000010
 #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED	0x00000040
@@ -108,7 +107,7 @@ struct zfcp_adapter_mempool {
 	mempool_t *scsi_req;
 	mempool_t *scsi_abort;
 	mempool_t *status_read_req;
-	mempool_t *status_read_data;
+	mempool_t *sr_data;
 	mempool_t *gid_pn;
 	mempool_t *qtcb_pool;
 };
@@ -190,6 +189,7 @@ struct zfcp_adapter {
 	struct fsf_qtcb_bottom_port *stats_reset_data;
 	unsigned long		stats_reset;
 	struct work_struct	scan_work;
+	struct work_struct	ns_up_work;
 	struct service_level	service_level;
 	struct workqueue_struct	*work_queue;
 	struct device_dma_parameters dma_parms;
@@ -314,15 +314,4 @@ struct zfcp_fsf_req {
 	void			(*handler)(struct zfcp_fsf_req *);
 };
 
-/* driver data */
-struct zfcp_data {
-	struct scsi_host_template scsi_host_template;
-	struct scsi_transport_template *scsi_transport_template;
-	struct kmem_cache	*gpn_ft_cache;
-	struct kmem_cache	*qtcb_cache;
-	struct kmem_cache	*sr_buffer_cache;
-	struct kmem_cache	*gid_pn_cache;
-	struct kmem_cache	*adisc_cache;
-};
-
 #endif /* ZFCP_DEF_H */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index e003e30..e1b4f80 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -732,7 +732,7 @@ static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *act)
 	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
 		return ZFCP_ERP_FAILED;
 
-	if (mempool_resize(act->adapter->pool.status_read_data,
+	if (mempool_resize(act->adapter->pool.sr_data,
 			   act->adapter->stat_read_buf_num, GFP_KERNEL))
 		return ZFCP_ERP_FAILED;
 
@@ -1231,8 +1231,10 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
 		if (result == ZFCP_ERP_SUCCEEDED) {
 			register_service_level(&adapter->service_level);
 			queue_work(adapter->work_queue, &adapter->scan_work);
+			queue_work(adapter->work_queue, &adapter->ns_up_work);
 		} else
 			unregister_service_level(&adapter->service_level);
+
 		kref_put(&adapter->ref, zfcp_adapter_release);
 		break;
 	}
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 6e32528..03627cfd 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -80,6 +80,7 @@ extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long);
 extern void zfcp_erp_timeout_handler(unsigned long);
 
 /* zfcp_fc.c */
+extern struct kmem_cache *zfcp_fc_req_cache;
 extern void zfcp_fc_enqueue_event(struct zfcp_adapter *,
 				enum fc_host_event_code event_code, u32);
 extern void zfcp_fc_post_event(struct work_struct *);
@@ -95,8 +96,10 @@ extern int zfcp_fc_gs_setup(struct zfcp_adapter *);
 extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
 extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
 extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
+extern void zfcp_fc_sym_name_update(struct work_struct *);
 
 /* zfcp_fsf.c */
+extern struct kmem_cache *zfcp_fsf_qtcb_cache;
 extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *);
 extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
@@ -139,9 +142,9 @@ extern struct zfcp_fsf_req *zfcp_fsf_get_req(struct zfcp_qdio *,
 					     struct qdio_buffer *);
 
 /* zfcp_scsi.c */
-extern struct zfcp_data zfcp_data;
-extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
-extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
+extern struct scsi_transport_template *zfcp_scsi_transport_template;
+extern int zfcp_scsi_adapter_register(struct zfcp_adapter *);
+extern void zfcp_scsi_adapter_unregister(struct zfcp_adapter *);
 extern struct fc_function_template zfcp_transport_functions;
 extern void zfcp_scsi_rport_work(struct work_struct *);
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 30cf91a..297e6b7 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -11,11 +11,14 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/utsname.h>
 #include <scsi/fc/fc_els.h>
 #include <scsi/libfc.h>
 #include "zfcp_ext.h"
 #include "zfcp_fc.h"
 
+struct kmem_cache *zfcp_fc_req_cache;
+
 static u32 zfcp_fc_rscn_range_mask[] = {
 	[ELS_ADDR_FMT_PORT]		= 0xFFFFFF,
 	[ELS_ADDR_FMT_AREA]		= 0xFFFF00,
@@ -260,24 +263,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req)
 		zfcp_fc_incoming_rscn(fsf_req);
 }
 
-static void zfcp_fc_ns_gid_pn_eval(void *data)
+static void zfcp_fc_ns_gid_pn_eval(struct zfcp_fc_req *fc_req)
 {
-	struct zfcp_fc_gid_pn *gid_pn = data;
-	struct zfcp_fsf_ct_els *ct = &gid_pn->ct;
-	struct zfcp_fc_gid_pn_req *gid_pn_req = sg_virt(ct->req);
-	struct zfcp_fc_gid_pn_resp *gid_pn_resp = sg_virt(ct->resp);
-	struct zfcp_port *port = gid_pn->port;
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp;
 
-	if (ct->status)
+	if (ct_els->status)
 		return;
-	if (gid_pn_resp->ct_hdr.ct_cmd != FC_FS_ACC)
+	if (gid_pn_rsp->ct_hdr.ct_cmd != FC_FS_ACC)
 		return;
 
-	/* paranoia */
-	if (gid_pn_req->gid_pn.fn_wwpn != port->wwpn)
-		return;
 	/* looks like a valid d_id */
-	port->d_id = ntoh24(gid_pn_resp->gid_pn.fp_fid);
+	ct_els->port->d_id = ntoh24(gid_pn_rsp->gid_pn.fp_fid);
 }
 
 static void zfcp_fc_complete(void *data)
@@ -285,69 +282,73 @@ static void zfcp_fc_complete(void *data)
 	complete(data);
 }
 
+static void zfcp_fc_ct_ns_init(struct fc_ct_hdr *ct_hdr, u16 cmd, u16 mr_size)
+{
+	ct_hdr->ct_rev = FC_CT_REV;
+	ct_hdr->ct_fs_type = FC_FST_DIR;
+	ct_hdr->ct_fs_subtype = FC_NS_SUBTYPE;
+	ct_hdr->ct_cmd = cmd;
+	ct_hdr->ct_mr_size = mr_size / 4;
+}
+
 static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
-				     struct zfcp_fc_gid_pn *gid_pn)
+				     struct zfcp_fc_req *fc_req)
 {
 	struct zfcp_adapter *adapter = port->adapter;
 	DECLARE_COMPLETION_ONSTACK(completion);
+	struct zfcp_fc_gid_pn_req *gid_pn_req = &fc_req->u.gid_pn.req;
+	struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp;
 	int ret;
 
 	/* setup parameters for send generic command */
-	gid_pn->port = port;
-	gid_pn->ct.handler = zfcp_fc_complete;
-	gid_pn->ct.handler_data = &completion;
-	gid_pn->ct.req = &gid_pn->sg_req;
-	gid_pn->ct.resp = &gid_pn->sg_resp;
-	sg_init_one(&gid_pn->sg_req, &gid_pn->gid_pn_req,
-		    sizeof(struct zfcp_fc_gid_pn_req));
-	sg_init_one(&gid_pn->sg_resp, &gid_pn->gid_pn_resp,
-		    sizeof(struct zfcp_fc_gid_pn_resp));
-
-	/* setup nameserver request */
-	gid_pn->gid_pn_req.ct_hdr.ct_rev = FC_CT_REV;
-	gid_pn->gid_pn_req.ct_hdr.ct_fs_type = FC_FST_DIR;
-	gid_pn->gid_pn_req.ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE;
-	gid_pn->gid_pn_req.ct_hdr.ct_options = 0;
-	gid_pn->gid_pn_req.ct_hdr.ct_cmd = FC_NS_GID_PN;
-	gid_pn->gid_pn_req.ct_hdr.ct_mr_size = ZFCP_FC_CT_SIZE_PAGE / 4;
-	gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn;
-
-	ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct,
+	fc_req->ct_els.port = port;
+	fc_req->ct_els.handler = zfcp_fc_complete;
+	fc_req->ct_els.handler_data = &completion;
+	fc_req->ct_els.req = &fc_req->sg_req;
+	fc_req->ct_els.resp = &fc_req->sg_rsp;
+	sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req));
+	sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp));
+
+	zfcp_fc_ct_ns_init(&gid_pn_req->ct_hdr,
+			   FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE);
+	gid_pn_req->gid_pn.fn_wwpn = port->wwpn;
+
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, &fc_req->ct_els,
 			       adapter->pool.gid_pn_req,
 			       ZFCP_FC_CTELS_TMO);
 	if (!ret) {
 		wait_for_completion(&completion);
-		zfcp_fc_ns_gid_pn_eval(gid_pn);
+		zfcp_fc_ns_gid_pn_eval(fc_req);
 	}
 	return ret;
 }
 
 /**
- * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
+ * zfcp_fc_ns_gid_pn - initiate GID_PN nameserver request
  * @port: port where GID_PN request is needed
  * return: -ENOMEM on error, 0 otherwise
  */
 static int zfcp_fc_ns_gid_pn(struct zfcp_port *port)
 {
 	int ret;
-	struct zfcp_fc_gid_pn *gid_pn;
+	struct zfcp_fc_req *fc_req;
 	struct zfcp_adapter *adapter = port->adapter;
 
-	gid_pn = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC);
-	if (!gid_pn)
+	fc_req = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC);
+	if (!fc_req)
 		return -ENOMEM;
 
-	memset(gid_pn, 0, sizeof(*gid_pn));
+	memset(fc_req, 0, sizeof(*fc_req));
 
 	ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
 	if (ret)
 		goto out;
 
-	ret = zfcp_fc_ns_gid_pn_request(port, gid_pn);
+	ret = zfcp_fc_ns_gid_pn_request(port, fc_req);
 
 	zfcp_fc_wka_port_put(&adapter->gs->ds);
 out:
-	mempool_free(gid_pn, adapter->pool.gid_pn);
+	mempool_free(fc_req, adapter->pool.gid_pn);
 	return ret;
 }
 
@@ -419,11 +420,11 @@ void zfcp_fc_plogi_evaluate(struct zfcp_port *port, struct fc_els_flogi *plogi)
 
 static void zfcp_fc_adisc_handler(void *data)
 {
-	struct zfcp_fc_els_adisc *adisc = data;
-	struct zfcp_port *port = adisc->els.port;
-	struct fc_els_adisc *adisc_resp = &adisc->adisc_resp;
+	struct zfcp_fc_req *fc_req = data;
+	struct zfcp_port *port = fc_req->ct_els.port;
+	struct fc_els_adisc *adisc_resp = &fc_req->u.adisc.rsp;
 
-	if (adisc->els.status) {
+	if (fc_req->ct_els.status) {
 		/* request rejected or timed out */
 		zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
 					    "fcadh_1");
@@ -445,42 +446,42 @@ static void zfcp_fc_adisc_handler(void *data)
  out:
 	atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
 	put_device(&port->dev);
-	kmem_cache_free(zfcp_data.adisc_cache, adisc);
+	kmem_cache_free(zfcp_fc_req_cache, fc_req);
 }
 
 static int zfcp_fc_adisc(struct zfcp_port *port)
 {
-	struct zfcp_fc_els_adisc *adisc;
+	struct zfcp_fc_req *fc_req;
 	struct zfcp_adapter *adapter = port->adapter;
+	struct Scsi_Host *shost = adapter->scsi_host;
 	int ret;
 
-	adisc = kmem_cache_zalloc(zfcp_data.adisc_cache, GFP_ATOMIC);
-	if (!adisc)
+	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_ATOMIC);
+	if (!fc_req)
 		return -ENOMEM;
 
-	adisc->els.port = port;
-	adisc->els.req = &adisc->req;
-	adisc->els.resp = &adisc->resp;
-	sg_init_one(adisc->els.req, &adisc->adisc_req,
+	fc_req->ct_els.port = port;
+	fc_req->ct_els.req = &fc_req->sg_req;
+	fc_req->ct_els.resp = &fc_req->sg_rsp;
+	sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req,
 		    sizeof(struct fc_els_adisc));
-	sg_init_one(adisc->els.resp, &adisc->adisc_resp,
+	sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp,
 		    sizeof(struct fc_els_adisc));
 
-	adisc->els.handler = zfcp_fc_adisc_handler;
-	adisc->els.handler_data = adisc;
+	fc_req->ct_els.handler = zfcp_fc_adisc_handler;
+	fc_req->ct_els.handler_data = fc_req;
 
 	/* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
 	   without FC-AL-2 capability, so we don't set it */
-	adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host);
-	adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host);
-	adisc->adisc_req.adisc_cmd = ELS_ADISC;
-	hton24(adisc->adisc_req.adisc_port_id,
-	       fc_host_port_id(adapter->scsi_host));
+	fc_req->u.adisc.req.adisc_wwpn = fc_host_port_name(shost);
+	fc_req->u.adisc.req.adisc_wwnn = fc_host_node_name(shost);
+	fc_req->u.adisc.req.adisc_cmd = ELS_ADISC;
+	hton24(fc_req->u.adisc.req.adisc_port_id, fc_host_port_id(shost));
 
-	ret = zfcp_fsf_send_els(adapter, port->d_id, &adisc->els,
+	ret = zfcp_fsf_send_els(adapter, port->d_id, &fc_req->ct_els,
 				ZFCP_FC_CTELS_TMO);
 	if (ret)
-		kmem_cache_free(zfcp_data.adisc_cache, adisc);
+		kmem_cache_free(zfcp_fc_req_cache, fc_req);
 
 	return ret;
 }
@@ -528,68 +529,42 @@ void zfcp_fc_test_link(struct zfcp_port *port)
 		put_device(&port->dev);
 }
 
-static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num)
+static struct zfcp_fc_req *zfcp_alloc_sg_env(int buf_num)
 {
-	struct scatterlist *sg = &gpn_ft->sg_req;
-
-	kmem_cache_free(zfcp_data.gpn_ft_cache, sg_virt(sg));
-	zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
-
-	kfree(gpn_ft);
-}
+	struct zfcp_fc_req *fc_req;
 
-static struct zfcp_fc_gpn_ft *zfcp_alloc_sg_env(int buf_num)
-{
-	struct zfcp_fc_gpn_ft *gpn_ft;
-	struct zfcp_fc_gpn_ft_req *req;
-
-	gpn_ft = kzalloc(sizeof(*gpn_ft), GFP_KERNEL);
-	if (!gpn_ft)
+	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL);
+	if (!fc_req)
 		return NULL;
 
-	req = kmem_cache_zalloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
-	if (!req) {
-		kfree(gpn_ft);
-		gpn_ft = NULL;
-		goto out;
+	if (zfcp_sg_setup_table(&fc_req->sg_rsp, buf_num)) {
+		kmem_cache_free(zfcp_fc_req_cache, fc_req);
+		return NULL;
 	}
-	sg_init_one(&gpn_ft->sg_req, req, sizeof(*req));
 
-	if (zfcp_sg_setup_table(gpn_ft->sg_resp, buf_num)) {
-		zfcp_free_sg_env(gpn_ft, buf_num);
-		gpn_ft = NULL;
-	}
-out:
-	return gpn_ft;
-}
+	sg_init_one(&fc_req->sg_req, &fc_req->u.gpn_ft.req,
+		    sizeof(struct zfcp_fc_gpn_ft_req));
 
+	return fc_req;
+}
 
-static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
+static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req,
 			       struct zfcp_adapter *adapter, int max_bytes)
 {
-	struct zfcp_fsf_ct_els *ct = &gpn_ft->ct;
-	struct zfcp_fc_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_gpn_ft_req *req = &fc_req->u.gpn_ft.req;
 	DECLARE_COMPLETION_ONSTACK(completion);
 	int ret;
 
-	/* prepare CT IU for GPN_FT */
-	req->ct_hdr.ct_rev = FC_CT_REV;
-	req->ct_hdr.ct_fs_type = FC_FST_DIR;
-	req->ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE;
-	req->ct_hdr.ct_options = 0;
-	req->ct_hdr.ct_cmd = FC_NS_GPN_FT;
-	req->ct_hdr.ct_mr_size = max_bytes / 4;
-	req->gpn_ft.fn_domain_id_scope = 0;
-	req->gpn_ft.fn_area_id_scope = 0;
+	zfcp_fc_ct_ns_init(&req->ct_hdr, FC_NS_GPN_FT, max_bytes);
 	req->gpn_ft.fn_fc4_type = FC_TYPE_FCP;
 
-	/* prepare zfcp_send_ct */
-	ct->handler = zfcp_fc_complete;
-	ct->handler_data = &completion;
-	ct->req = &gpn_ft->sg_req;
-	ct->resp = gpn_ft->sg_resp;
+	ct_els->handler = zfcp_fc_complete;
+	ct_els->handler_data = &completion;
+	ct_els->req = &fc_req->sg_req;
+	ct_els->resp = &fc_req->sg_rsp;
 
-	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL,
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
 			       ZFCP_FC_CTELS_TMO);
 	if (!ret)
 		wait_for_completion(&completion);
@@ -610,11 +585,11 @@ static void zfcp_fc_validate_port(struct zfcp_port *port, struct list_head *lh)
 	list_move_tail(&port->list, lh);
 }
 
-static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
+static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req,
 			       struct zfcp_adapter *adapter, int max_entries)
 {
-	struct zfcp_fsf_ct_els *ct = &gpn_ft->ct;
-	struct scatterlist *sg = gpn_ft->sg_resp;
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct scatterlist *sg = &fc_req->sg_rsp;
 	struct fc_ct_hdr *hdr = sg_virt(sg);
 	struct fc_gpn_ft_resp *acc = sg_virt(sg);
 	struct zfcp_port *port, *tmp;
@@ -623,7 +598,7 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
 	u32 d_id;
 	int ret = 0, x, last = 0;
 
-	if (ct->status)
+	if (ct_els->status)
 		return -EIO;
 
 	if (hdr->ct_cmd != FC_FS_ACC) {
@@ -687,7 +662,7 @@ void zfcp_fc_scan_ports(struct work_struct *work)
 	struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
 						    scan_work);
 	int ret, i;
-	struct zfcp_fc_gpn_ft *gpn_ft;
+	struct zfcp_fc_req *fc_req;
 	int chain, max_entries, buf_num, max_bytes;
 
 	chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
@@ -702,25 +677,145 @@ void zfcp_fc_scan_ports(struct work_struct *work)
 	if (zfcp_fc_wka_port_get(&adapter->gs->ds))
 		return;
 
-	gpn_ft = zfcp_alloc_sg_env(buf_num);
-	if (!gpn_ft)
+	fc_req = zfcp_alloc_sg_env(buf_num);
+	if (!fc_req)
 		goto out;
 
 	for (i = 0; i < 3; i++) {
-		ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes);
+		ret = zfcp_fc_send_gpn_ft(fc_req, adapter, max_bytes);
 		if (!ret) {
-			ret = zfcp_fc_eval_gpn_ft(gpn_ft, adapter, max_entries);
+			ret = zfcp_fc_eval_gpn_ft(fc_req, adapter, max_entries);
 			if (ret == -EAGAIN)
 				ssleep(1);
 			else
 				break;
 		}
 	}
-	zfcp_free_sg_env(gpn_ft, buf_num);
+	zfcp_sg_free_table(&fc_req->sg_rsp, buf_num);
+	kmem_cache_free(zfcp_fc_req_cache, fc_req);
 out:
 	zfcp_fc_wka_port_put(&adapter->gs->ds);
 }
 
+static int zfcp_fc_gspn(struct zfcp_adapter *adapter,
+			struct zfcp_fc_req *fc_req)
+{
+	DECLARE_COMPLETION_ONSTACK(completion);
+	char devno[] = "DEVNO:";
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_gspn_req *gspn_req = &fc_req->u.gspn.req;
+	struct zfcp_fc_gspn_rsp *gspn_rsp = &fc_req->u.gspn.rsp;
+	int ret;
+
+	zfcp_fc_ct_ns_init(&gspn_req->ct_hdr, FC_NS_GSPN_ID,
+			   FC_SYMBOLIC_NAME_SIZE);
+	hton24(gspn_req->gspn.fp_fid, fc_host_port_id(adapter->scsi_host));
+
+	sg_init_one(&fc_req->sg_req, gspn_req, sizeof(*gspn_req));
+	sg_init_one(&fc_req->sg_rsp, gspn_rsp, sizeof(*gspn_rsp));
+
+	ct_els->handler = zfcp_fc_complete;
+	ct_els->handler_data = &completion;
+	ct_els->req = &fc_req->sg_req;
+	ct_els->resp = &fc_req->sg_rsp;
+
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
+			       ZFCP_FC_CTELS_TMO);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&completion);
+	if (ct_els->status)
+		return ct_els->status;
+
+	if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_NPIV &&
+	    !(strstr(gspn_rsp->gspn.fp_name, devno)))
+		snprintf(fc_host_symbolic_name(adapter->scsi_host),
+			 FC_SYMBOLIC_NAME_SIZE, "%s%s %s NAME: %s",
+			 gspn_rsp->gspn.fp_name, devno,
+			 dev_name(&adapter->ccw_device->dev),
+			 init_utsname()->nodename);
+	else
+		strlcpy(fc_host_symbolic_name(adapter->scsi_host),
+			gspn_rsp->gspn.fp_name, FC_SYMBOLIC_NAME_SIZE);
+
+	return 0;
+}
+
+static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
+			 struct zfcp_fc_req *fc_req)
+{
+	DECLARE_COMPLETION_ONSTACK(completion);
+	struct Scsi_Host *shost = adapter->scsi_host;
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_rspn_req *rspn_req = &fc_req->u.rspn.req;
+	struct fc_ct_hdr *rspn_rsp = &fc_req->u.rspn.rsp;
+	int ret, len;
+
+	zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID,
+			   FC_SYMBOLIC_NAME_SIZE);
+	hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost));
+	len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
+		      FC_SYMBOLIC_NAME_SIZE);
+	rspn_req->rspn.fr_name_len = len;
+
+	sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req));
+	sg_init_one(&fc_req->sg_rsp, rspn_rsp, sizeof(*rspn_rsp));
+
+	ct_els->handler = zfcp_fc_complete;
+	ct_els->handler_data = &completion;
+	ct_els->req = &fc_req->sg_req;
+	ct_els->resp = &fc_req->sg_rsp;
+
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
+			       ZFCP_FC_CTELS_TMO);
+	if (!ret)
+		wait_for_completion(&completion);
+}
+
+/**
+ * zfcp_fc_sym_name_update - Retrieve and update the symbolic port name
+ * @work: ns_up_work of the adapter where to update the symbolic port name
+ *
+ * Retrieve the current symbolic port name that may have been set by
+ * the hardware using the GSPN request and update the fc_host
+ * symbolic_name sysfs attribute. When running in NPIV mode (and hence
+ * the port name is unique for this system), update the symbolic port
+ * name to add Linux specific information and update the FC nameserver
+ * using the RSPN request.
+ */
+void zfcp_fc_sym_name_update(struct work_struct *work)
+{
+	struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
+						    ns_up_work);
+	int ret;
+	struct zfcp_fc_req *fc_req;
+
+	if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT &&
+	    fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
+		return;
+
+	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL);
+	if (!fc_req)
+		return;
+
+	ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
+	if (ret)
+		goto out_free;
+
+	ret = zfcp_fc_gspn(adapter, fc_req);
+	if (ret || fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
+		goto out_ds_put;
+
+	memset(fc_req, 0, sizeof(*fc_req));
+	zfcp_fc_rspn(adapter, fc_req);
+
+out_ds_put:
+	zfcp_fc_wka_port_put(&adapter->gs->ds);
+out_free:
+	kmem_cache_free(zfcp_fc_req_cache, fc_req);
+}
+
 static void zfcp_fc_ct_els_job_handler(void *data)
 {
 	struct fc_bsg_job *job = data;
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h
index b464ae0..4561f3b 100644
--- a/drivers/s390/scsi/zfcp_fc.h
+++ b/drivers/s390/scsi/zfcp_fc.h
@@ -64,33 +64,16 @@ struct zfcp_fc_gid_pn_req {
 } __packed;
 
 /**
- * struct zfcp_fc_gid_pn_resp - container for ct header plus gid_pn response
+ * struct zfcp_fc_gid_pn_rsp - container for ct header plus gid_pn response
  * @ct_hdr: FC GS common transport header
  * @gid_pn: GID_PN response
  */
-struct zfcp_fc_gid_pn_resp {
+struct zfcp_fc_gid_pn_rsp {
 	struct fc_ct_hdr	ct_hdr;
 	struct fc_gid_pn_resp	gid_pn;
 } __packed;
 
 /**
- * struct zfcp_fc_gid_pn - everything required in zfcp for gid_pn request
- * @ct: data passed to zfcp_fsf for issuing fsf request
- * @sg_req: scatterlist entry for request data
- * @sg_resp: scatterlist entry for response data
- * @gid_pn_req: GID_PN request data
- * @gid_pn_resp: GID_PN response data
- */
-struct zfcp_fc_gid_pn {
-	struct zfcp_fsf_ct_els ct;
-	struct scatterlist sg_req;
-	struct scatterlist sg_resp;
-	struct zfcp_fc_gid_pn_req gid_pn_req;
-	struct zfcp_fc_gid_pn_resp gid_pn_resp;
-	struct zfcp_port *port;
-};
-
-/**
  * struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request
  * @ct_hdr: FC GS common transport header
  * @gpn_ft: GPN_FT request
@@ -101,41 +84,72 @@ struct zfcp_fc_gpn_ft_req {
 } __packed;
 
 /**
- * struct zfcp_fc_gpn_ft_resp - container for ct header plus gpn_ft response
+ * struct zfcp_fc_gspn_req - container for ct header plus GSPN_ID request
  * @ct_hdr: FC GS common transport header
- * @gpn_ft: Array of gpn_ft response data to fill one memory page
+ * @gspn: GSPN_ID request
  */
-struct zfcp_fc_gpn_ft_resp {
+struct zfcp_fc_gspn_req {
 	struct fc_ct_hdr	ct_hdr;
-	struct fc_gpn_ft_resp	gpn_ft[ZFCP_FC_GPN_FT_ENT_PAGE];
+	struct fc_gid_pn_resp	gspn;
 } __packed;
 
 /**
- * struct zfcp_fc_gpn_ft - zfcp data for gpn_ft request
- * @ct: data passed to zfcp_fsf for issuing fsf request
- * @sg_req: scatter list entry for gpn_ft request
- * @sg_resp: scatter list entries for gpn_ft responses (per memory page)
+ * struct zfcp_fc_gspn_rsp - container for ct header plus GSPN_ID response
+ * @ct_hdr: FC GS common transport header
+ * @gspn: GSPN_ID response
+ * @name: The name string of the GSPN_ID response
  */
-struct zfcp_fc_gpn_ft {
-	struct zfcp_fsf_ct_els ct;
-	struct scatterlist sg_req;
-	struct scatterlist sg_resp[ZFCP_FC_GPN_FT_NUM_BUFS];
-};
+struct zfcp_fc_gspn_rsp {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_gspn_resp	gspn;
+	char			name[FC_SYMBOLIC_NAME_SIZE];
+} __packed;
 
 /**
- * struct zfcp_fc_els_adisc - everything required in zfcp for issuing ELS ADISC
- * @els: data required for issuing els fsf command
- * @req: scatterlist entry for ELS ADISC request
- * @resp: scatterlist entry for ELS ADISC response
- * @adisc_req: ELS ADISC request data
- * @adisc_resp: ELS ADISC response data
+ * struct zfcp_fc_rspn_req - container for ct header plus RSPN_ID request
+ * @ct_hdr: FC GS common transport header
+ * @rspn: RSPN_ID request
+ * @name: The name string of the RSPN_ID request
  */
-struct zfcp_fc_els_adisc {
-	struct zfcp_fsf_ct_els els;
-	struct scatterlist req;
-	struct scatterlist resp;
-	struct fc_els_adisc adisc_req;
-	struct fc_els_adisc adisc_resp;
+struct zfcp_fc_rspn_req {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_ns_rspn	rspn;
+	char			name[FC_SYMBOLIC_NAME_SIZE];
+} __packed;
+
+/**
+ * struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp
+ * @ct_els: data required for issuing fsf command
+ * @sg_req: scatterlist entry for request data
+ * @sg_rsp: scatterlist entry for response data
+ * @u: request specific data
+ */
+struct zfcp_fc_req {
+	struct zfcp_fsf_ct_els				ct_els;
+	struct scatterlist				sg_req;
+	struct scatterlist				sg_rsp;
+	union {
+		struct {
+			struct fc_els_adisc		req;
+			struct fc_els_adisc		rsp;
+		} adisc;
+		struct {
+			struct zfcp_fc_gid_pn_req	req;
+			struct zfcp_fc_gid_pn_rsp	rsp;
+		} gid_pn;
+		struct {
+			struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1];
+			struct zfcp_fc_gpn_ft_req	req;
+		} gpn_ft;
+		struct {
+			struct zfcp_fc_gspn_req		req;
+			struct zfcp_fc_gspn_rsp		rsp;
+		} gspn;
+		struct {
+			struct zfcp_fc_rspn_req		req;
+			struct fc_ct_hdr		rsp;
+		} rspn;
+	} u;
 };
 
 /**
@@ -192,14 +206,21 @@ struct zfcp_fc_wka_ports {
  * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
  * @fcp: fcp_cmnd to setup
  * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
+ * @tm: task management flags to setup task management command
  */
 static inline
-void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
+void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
+			 u8 tm_flags)
 {
 	char tag[2];
 
 	int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
 
+	if (unlikely(tm_flags)) {
+		fcp->fc_tm_flags = tm_flags;
+		return;
+	}
+
 	if (scsi_populate_tag_msg(scsi, tag)) {
 		switch (tag[0]) {
 		case MSG_ORDERED_TAG:
@@ -226,19 +247,6 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
 }
 
 /**
- * zfcp_fc_fcp_tm - setup FCP command as task management command
- * @fcp: fcp_cmnd to setup
- * @dev: scsi_device where to send the task management command
- * @tm: task management flags to setup tm command
- */
-static inline
-void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
-{
-	int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
-	fcp->fc_tm_flags |= tm_flags;
-}
-
-/**
  * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
  * @fcp_rsp: FCP RSP IU to evaluate
  * @scsi: SCSI command where to update status and sense buffer
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 60ff9d1..a0e05ef 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -18,6 +18,8 @@
 #include "zfcp_qdio.h"
 #include "zfcp_reqlist.h"
 
+struct kmem_cache *zfcp_fsf_qtcb_cache;
+
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
 {
 	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
@@ -83,7 +85,7 @@ void zfcp_fsf_req_free(struct zfcp_fsf_req *req)
 	}
 
 	if (likely(req->qtcb))
-		kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
+		kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb);
 	kfree(req);
 }
 
@@ -212,7 +214,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
 
 	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
 		zfcp_dbf_hba_fsf_uss("fssrh_1", req);
-		mempool_free(sr_buf, adapter->pool.status_read_data);
+		mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
 		zfcp_fsf_req_free(req);
 		return;
 	}
@@ -265,7 +267,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
 		break;
 	}
 
-	mempool_free(sr_buf, adapter->pool.status_read_data);
+	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
 	zfcp_fsf_req_free(req);
 
 	atomic_inc(&adapter->stat_miss);
@@ -628,7 +630,7 @@ static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
 	if (likely(pool))
 		qtcb = mempool_alloc(pool, GFP_ATOMIC);
 	else
-		qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);
+		qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC);
 
 	if (unlikely(!qtcb))
 		return NULL;
@@ -723,6 +725,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
 	struct zfcp_adapter *adapter = qdio->adapter;
 	struct zfcp_fsf_req *req;
 	struct fsf_status_read_buffer *sr_buf;
+	struct page *page;
 	int retval = -EIO;
 
 	spin_lock_irq(&qdio->req_q_lock);
@@ -736,11 +739,12 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
 		goto out;
 	}
 
-	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
-	if (!sr_buf) {
+	page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC);
+	if (!page) {
 		retval = -ENOMEM;
 		goto failed_buf;
 	}
+	sr_buf = page_address(page);
 	memset(sr_buf, 0, sizeof(*sr_buf));
 	req->data = sr_buf;
 
@@ -755,7 +759,7 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio)
 
 failed_req_send:
 	req->data = NULL;
-	mempool_free(sr_buf, adapter->pool.status_read_data);
+	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
 failed_buf:
 	zfcp_dbf_hba_fsf_uss("fssr__1", req);
 	zfcp_fsf_req_free(req);
@@ -1552,7 +1556,7 @@ int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *wka_port)
 				  SBAL_FLAGS0_TYPE_READ,
 				  qdio->adapter->pool.erp_req);
 
-	if (unlikely(IS_ERR(req))) {
+	if (IS_ERR(req)) {
 		retval = PTR_ERR(req);
 		goto out;
 	}
@@ -1605,7 +1609,7 @@ int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *wka_port)
 				  SBAL_FLAGS0_TYPE_READ,
 				  qdio->adapter->pool.erp_req);
 
-	if (unlikely(IS_ERR(req))) {
+	if (IS_ERR(req)) {
 		retval = PTR_ERR(req);
 		goto out;
 	}
@@ -2206,7 +2210,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
 	zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
 
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
-	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
+	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
 
 	if (scsi_prot_sg_count(scsi_cmnd)) {
 		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
@@ -2284,7 +2288,6 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
 		goto out;
 	}
 
-	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
 	req->data = scmnd;
 	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
 	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
@@ -2296,7 +2299,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
-	zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
+	zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags);
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
 	if (!zfcp_fsf_req_send(req))
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index ddb5800..2a4991d 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -292,7 +292,37 @@ static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
 	return SUCCESS;
 }
 
-int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
+struct scsi_transport_template *zfcp_scsi_transport_template;
+
+static struct scsi_host_template zfcp_scsi_host_template = {
+	.module			 = THIS_MODULE,
+	.name			 = "zfcp",
+	.queuecommand		 = zfcp_scsi_queuecommand,
+	.eh_abort_handler	 = zfcp_scsi_eh_abort_handler,
+	.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
+	.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
+	.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
+	.slave_alloc		 = zfcp_scsi_slave_alloc,
+	.slave_configure	 = zfcp_scsi_slave_configure,
+	.slave_destroy		 = zfcp_scsi_slave_destroy,
+	.change_queue_depth	 = zfcp_scsi_change_queue_depth,
+	.proc_name		 = "zfcp",
+	.can_queue		 = 4096,
+	.this_id		 = -1,
+	.sg_tablesize		 = ZFCP_QDIO_MAX_SBALES_PER_REQ,
+	.max_sectors		 = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8),
+	.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
+	.cmd_per_lun		 = 1,
+	.use_clustering		 = 1,
+	.shost_attrs		 = zfcp_sysfs_shost_attrs,
+	.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
+};
+
+/**
+ * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer
+ * @adapter: The zfcp adapter to register with the SCSI midlayer
+ */
+int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter)
 {
 	struct ccw_dev_id dev_id;
 
@@ -301,7 +331,7 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
 
 	ccw_device_get_id(adapter->ccw_device, &dev_id);
 	/* register adapter as SCSI host with mid layer of SCSI stack */
-	adapter->scsi_host = scsi_host_alloc(&zfcp_data.scsi_host_template,
+	adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template,
 					     sizeof (struct zfcp_adapter *));
 	if (!adapter->scsi_host) {
 		dev_err(&adapter->ccw_device->dev,
@@ -316,7 +346,7 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
 	adapter->scsi_host->max_channel = 0;
 	adapter->scsi_host->unique_id = dev_id.devno;
 	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
-	adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;
+	adapter->scsi_host->transportt = zfcp_scsi_transport_template;
 
 	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;
 
@@ -328,7 +358,11 @@ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
 	return 0;
 }
 
-void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
+/**
+ * zfcp_scsi_adapter_unregister - Unregister SCSI and FC host from SCSI midlayer
+ * @adapter: The zfcp adapter to unregister.
+ */
+void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter)
 {
 	struct Scsi_Host *shost;
 	struct zfcp_port *port;
@@ -346,8 +380,6 @@ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
 	scsi_remove_host(shost);
 	scsi_host_put(shost);
 	adapter->scsi_host = NULL;
-
-	return;
 }
 
 static struct fc_host_statistics*
@@ -688,33 +720,8 @@ struct fc_function_template zfcp_transport_functions = {
 	/* no functions registered for following dynamic attributes but
 	   directly set by LLDD */
 	.show_host_port_type = 1,
+	.show_host_symbolic_name = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
 	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };
-
-struct zfcp_data zfcp_data = {
-	.scsi_host_template = {
-		.name			 = "zfcp",
-		.module			 = THIS_MODULE,
-		.proc_name		 = "zfcp",
-		.change_queue_depth	 = zfcp_scsi_change_queue_depth,
-		.slave_alloc		 = zfcp_scsi_slave_alloc,
-		.slave_configure	 = zfcp_scsi_slave_configure,
-		.slave_destroy		 = zfcp_scsi_slave_destroy,
-		.queuecommand		 = zfcp_scsi_queuecommand,
-		.eh_abort_handler	 = zfcp_scsi_eh_abort_handler,
-		.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
-		.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
-		.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
-		.can_queue		 = 4096,
-		.this_id		 = -1,
-		.sg_tablesize		 = ZFCP_QDIO_MAX_SBALES_PER_REQ,
-		.cmd_per_lun		 = 1,
-		.use_clustering		 = 1,
-		.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
-		.max_sectors		 = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8),
-		.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
-		.shost_attrs		 = zfcp_sysfs_shost_attrs,
-	},
-};
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 614a5e1..5f94d22 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -361,8 +361,7 @@ fail:
 extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
 extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
 
-static int __devinit bbc_i2c_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static int __devinit bbc_i2c_probe(struct platform_device *op)
 {
 	struct bbc_i2c_bus *bp;
 	int err, index = 0;
@@ -413,7 +412,7 @@ static const struct of_device_id bbc_i2c_match[] = {
 };
 MODULE_DEVICE_TABLE(of, bbc_i2c_match);
 
-static struct of_platform_driver bbc_i2c_driver = {
+static struct platform_driver bbc_i2c_driver = {
 	.driver = {
 		.name = "bbc_i2c",
 		.owner = THIS_MODULE,
@@ -425,12 +424,12 @@ static struct of_platform_driver bbc_i2c_driver = {
 
 static int __init bbc_i2c_init(void)
 {
-	return of_register_platform_driver(&bbc_i2c_driver);
+	return platform_driver_register(&bbc_i2c_driver);
 }
 
 static void __exit bbc_i2c_exit(void)
 {
-	of_unregister_platform_driver(&bbc_i2c_driver);
+	platform_driver_unregister(&bbc_i2c_driver);
 }
 
 module_init(bbc_i2c_init);
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 55f71ea..740da446 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -171,8 +171,7 @@ static struct miscdevice d7s_miscdev = {
 	.fops		= &d7s_fops
 };
 
-static int __devinit d7s_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit d7s_probe(struct platform_device *op)
 {
 	struct device_node *opts;
 	int err = -EINVAL;
@@ -266,7 +265,7 @@ static const struct of_device_id d7s_match[] = {
 };
 MODULE_DEVICE_TABLE(of, d7s_match);
 
-static struct of_platform_driver d7s_driver = {
+static struct platform_driver d7s_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -278,12 +277,12 @@ static struct of_platform_driver d7s_driver = {
 
 static int __init d7s_init(void)
 {
-	return of_register_platform_driver(&d7s_driver);
+	return platform_driver_register(&d7s_driver);
 }
 
 static void __exit d7s_exit(void)
 {
-	of_unregister_platform_driver(&d7s_driver);
+	platform_driver_unregister(&d7s_driver);
 }
 
 module_init(d7s_init);
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 8ce414e..be7b4e5 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -1028,8 +1028,7 @@ static int kenvctrld(void *__unused)
 	return 0;
 }
 
-static int __devinit envctrl_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static int __devinit envctrl_probe(struct platform_device *op)
 {
 	struct device_node *dp;
 	int index, err;
@@ -1129,7 +1128,7 @@ static const struct of_device_id envctrl_match[] = {
 };
 MODULE_DEVICE_TABLE(of, envctrl_match);
 
-static struct of_platform_driver envctrl_driver = {
+static struct platform_driver envctrl_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1141,12 +1140,12 @@ static struct of_platform_driver envctrl_driver = {
 
 static int __init envctrl_init(void)
 {
-	return of_register_platform_driver(&envctrl_driver);
+	return platform_driver_register(&envctrl_driver);
 }
 
 static void __exit envctrl_exit(void)
 {
-	of_unregister_platform_driver(&envctrl_driver);
+	platform_driver_unregister(&envctrl_driver);
 }
 
 module_init(envctrl_init);
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 2b4b4b6..73dd4e7 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -160,8 +160,7 @@ static const struct file_operations flash_fops = {
 
 static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
 
-static int __devinit flash_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit flash_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct device_node *parent;
@@ -207,7 +206,7 @@ static const struct of_device_id flash_match[] = {
 };
 MODULE_DEVICE_TABLE(of, flash_match);
 
-static struct of_platform_driver flash_driver = {
+static struct platform_driver flash_driver = {
 	.driver = {
 		.name = "flash",
 		.owner = THIS_MODULE,
@@ -219,12 +218,12 @@ static struct of_platform_driver flash_driver = {
 
 static int __init flash_init(void)
 {
-	return of_register_platform_driver(&flash_driver);
+	return platform_driver_register(&flash_driver);
 }
 
 static void __exit flash_cleanup(void)
 {
-	of_unregister_platform_driver(&flash_driver);
+	platform_driver_unregister(&flash_driver);
 }
 
 module_init(flash_init);
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 1b345be..ebce963 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -348,8 +348,7 @@ static void uctrl_get_external_status(struct uctrl_driver *driver)
 	
 }
 
-static int __devinit uctrl_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit uctrl_probe(struct platform_device *op)
 {
 	struct uctrl_driver *p;
 	int err = -ENOMEM;
@@ -425,7 +424,7 @@ static const struct of_device_id uctrl_match[] = {
 };
 MODULE_DEVICE_TABLE(of, uctrl_match);
 
-static struct of_platform_driver uctrl_driver = {
+static struct platform_driver uctrl_driver = {
 	.driver = {
 		.name = "uctrl",
 		.owner = THIS_MODULE,
@@ -438,12 +437,12 @@ static struct of_platform_driver uctrl_driver = {
 
 static int __init uctrl_init(void)
 {
-	return of_register_platform_driver(&uctrl_driver);
+	return platform_driver_register(&uctrl_driver);
 }
 
 static void __exit uctrl_exit(void)
 {
-	of_unregister_platform_driver(&uctrl_driver);
+	platform_driver_unregister(&uctrl_driver);
 }
 
 module_init(uctrl_init);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 8616496..4a1f029 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -381,6 +381,7 @@ config ISCSI_BOOT_SYSFS
 
 source "drivers/scsi/cxgbi/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
+source "drivers/scsi/bnx2fc/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
 
 config SGIWD93_SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 2e9a87e..7ad0b8a 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_LIBFC)		+= libfc/
 obj-$(CONFIG_LIBFCOE)		+= fcoe/
 obj-$(CONFIG_FCOE)		+= fcoe/
 obj-$(CONFIG_FCOE_FNIC)		+= fnic/
+obj-$(CONFIG_SCSI_BNX2X_FCOE)	+= libfc/ fcoe/ bnx2fc/
 obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	libiscsi_tcp.o iscsi_tcp.o
 obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
 obj-$(CONFIG_ISCSI_BOOT_SYSFS)	+= iscsi_boot_sysfs.o
@@ -165,7 +166,7 @@ scsi_mod-$(CONFIG_SCSI_NETLINK)	+= scsi_netlink.o
 scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
 scsi_mod-y			+= scsi_trace.o
-scsi_mod-$(CONFIG_PM_OPS)	+= scsi_pm.o
+scsi_mod-$(CONFIG_PM)		+= scsi_pm.o
 
 scsi_tgt-y			+= scsi_tgt_lib.o scsi_tgt_if.o
 
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 9a5629f..e7cd2fc 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -936,8 +936,7 @@ static void NCR5380_exit(struct Scsi_Host *instance)
 {
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-	cancel_delayed_work(&hostdata->coroutine);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&hostdata->coroutine);
 }
 
 /**
diff --git a/drivers/scsi/aacraid/Makefile b/drivers/scsi/aacraid/Makefile
index f1cca4e..92df4d6 100644
--- a/drivers/scsi/aacraid/Makefile
+++ b/drivers/scsi/aacraid/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
 aacraid-objs	:= linit.o aachba.o commctrl.o comminit.o commsup.o \
 		   dpcsup.o rx.o sa.o rkt.o nark.o
 
-EXTRA_CFLAGS	:= -Idrivers/scsi
+ccflags-y	:= -Idrivers/scsi
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index be5558a..95ee503 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -672,7 +672,7 @@ struct scb_data {
 /************************ Target Mode Definitions *****************************/
 
 /*
- * Connection desciptor for select-in requests in target mode.
+ * Connection descriptor for select-in requests in target mode.
  */
 struct target_cmd {
 	uint8_t scsiid;		/* Our ID and the initiator's ID */
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index e4e651c..17444bc 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -618,7 +618,7 @@ struct scb_data {
 /************************ Target Mode Definitions *****************************/
 
 /*
- * Connection desciptor for select-in requests in target mode.
+ * Connection descriptor for select-in requests in target mode.
  */
 struct target_cmd {
 	uint8_t scsiid;		/* Our ID and the initiator's ID */
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 3f5a542..e021b48 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -4780,7 +4780,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
 	SLIST_INIT(&scb_data->sg_maps);
 
 	/* Allocate SCB resources */
-	scb_data->scbarray = (struct scb *)kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC);
+	scb_data->scbarray = kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC);
 	if (scb_data->scbarray == NULL)
 		return (ENOMEM);
 	memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC);
diff --git a/drivers/scsi/aic94xx/Makefile b/drivers/scsi/aic94xx/Makefile
index e78ce0f..c0a15c7 100644
--- a/drivers/scsi/aic94xx/Makefile
+++ b/drivers/scsi/aic94xx/Makefile
@@ -22,9 +22,7 @@
 # along with the aic94xx driver; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-ifeq ($(CONFIG_AIC94XX_DEBUG),y)
-	EXTRA_CFLAGS += -DASD_DEBUG -DASD_ENTER_EXIT
-endif
+ccflags-$(CONFIG_AIC94XX_DEBUG) := -DASD_DEBUG -DASD_ENTER_EXIT
 
 obj-$(CONFIG_SCSI_AIC94XX) += aic94xx.o
 aic94xx-y += aic94xx_init.o \
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c
index 984bd52..da7b988 100644
--- a/drivers/scsi/arcmsr/arcmsr_hba.c
+++ b/drivers/scsi/arcmsr/arcmsr_hba.c
@@ -1020,7 +1020,7 @@ static void arcmsr_remove(struct pci_dev *pdev)
 	int poll_count = 0;
 	arcmsr_free_sysfs_attr(acb);
 	scsi_remove_host(host);
-	flush_scheduled_work();
+	flush_work_sync(&acb->arcmsr_do_message_isr_bh);
 	del_timer_sync(&acb->eternal_timer);
 	arcmsr_disable_outbound_ints(acb);
 	arcmsr_stop_adapter_bgrb(acb);
@@ -1066,7 +1066,7 @@ static void arcmsr_shutdown(struct pci_dev *pdev)
 		(struct AdapterControlBlock *)host->hostdata;
 	del_timer_sync(&acb->eternal_timer);
 	arcmsr_disable_outbound_ints(acb);
-	flush_scheduled_work();
+	flush_work_sync(&acb->arcmsr_do_message_isr_bh);
 	arcmsr_stop_adapter_bgrb(acb);
 	arcmsr_flush_adapter_cache(acb);
 }
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c
index eaaa881..868cc55 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.c
+++ b/drivers/scsi/be2iscsi/be_iscsi.c
@@ -210,28 +210,20 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
 }
 
 /**
- * beiscsi_conn_get_param - get the iscsi parameter
- * @cls_conn: pointer to iscsi cls conn
+ * beiscsi_ep_get_param - get the iscsi parameter
+ * @ep: pointer to iscsi ep
  * @param: parameter type identifier
  * @buf: buffer pointer
  *
  * returns iscsi parameter
  */
-int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
 			   enum iscsi_param param, char *buf)
 {
-	struct beiscsi_endpoint *beiscsi_ep;
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
 	int len = 0;
 
 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param);
-	beiscsi_ep = beiscsi_conn->ep;
-	if (!beiscsi_ep) {
-		SE_DEBUG(DBG_LVL_1,
-			 "In beiscsi_conn_get_param , no beiscsi_ep\n");
-		return -ENODEV;
-	}
 
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
@@ -244,7 +236,7 @@ int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
 			len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
 		break;
 	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
+		return -ENOSYS;
 	}
 	return len;
 }
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h
index 8950a70..9c53279 100644
--- a/drivers/scsi/be2iscsi/be_iscsi.h
+++ b/drivers/scsi/be2iscsi/be_iscsi.h
@@ -48,8 +48,8 @@ int beiscsi_conn_bind(struct iscsi_cls_session *cls_session,
 		      struct iscsi_cls_conn *cls_conn,
 		      uint64_t transport_fd, int is_leading);
 
-int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
-			   enum iscsi_param param, char *buf);
+int beiscsi_ep_get_param(struct iscsi_endpoint *ep, enum iscsi_param param,
+			 char *buf);
 
 int beiscsi_get_host_param(struct Scsi_Host *shost,
 			   enum iscsi_host_param param, char *buf);
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index 79cefbe..24e20ba 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -4277,7 +4277,7 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev,
 
 	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
 		 phba->shost->host_no);
-	phba->wq = create_workqueue(phba->wq_name);
+	phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
 	if (!phba->wq) {
 		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
 				"Failed to allocate work queue\n");
@@ -4384,7 +4384,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
 	.bind_conn = beiscsi_conn_bind,
 	.destroy_conn = iscsi_conn_teardown,
 	.set_param = beiscsi_set_param,
-	.get_conn_param = beiscsi_conn_get_param,
+	.get_conn_param = iscsi_conn_get_param,
 	.get_session_param = iscsi_session_get_param,
 	.get_host_param = beiscsi_get_host_param,
 	.start_conn = beiscsi_conn_start,
@@ -4395,6 +4395,7 @@ struct iscsi_transport beiscsi_iscsi_transport = {
 	.alloc_pdu = beiscsi_alloc_pdu,
 	.parse_pdu_itt = beiscsi_parse_pdu,
 	.get_stats = beiscsi_conn_get_stats,
+	.get_ep_param = beiscsi_ep_get_param,
 	.ep_connect = beiscsi_ep_connect,
 	.ep_poll = beiscsi_ep_poll,
 	.ep_disconnect = beiscsi_ep_disconnect,
diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
new file mode 100644
index 0000000..69d031d
--- /dev/null
+++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
@@ -0,0 +1,1080 @@
+#ifndef __57XX_FCOE_HSI_LINUX_LE__
+#define __57XX_FCOE_HSI_LINUX_LE__
+
+/*
+ * common data for all protocols
+ */
+struct b577xx_doorbell_hdr {
+	u8 header;
+#define B577XX_DOORBELL_HDR_RX (0x1<<0)
+#define B577XX_DOORBELL_HDR_RX_SHIFT 0
+#define B577XX_DOORBELL_HDR_DB_TYPE (0x1<<1)
+#define B577XX_DOORBELL_HDR_DB_TYPE_SHIFT 1
+#define B577XX_DOORBELL_HDR_DPM_SIZE (0x3<<2)
+#define B577XX_DOORBELL_HDR_DPM_SIZE_SHIFT 2
+#define B577XX_DOORBELL_HDR_CONN_TYPE (0xF<<4)
+#define B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT 4
+};
+
+/*
+ * doorbell message sent to the chip
+ */
+struct b577xx_doorbell_set_prod {
+#if defined(__BIG_ENDIAN)
+	u16 prod;
+	u8 zero_fill1;
+	struct b577xx_doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+	struct b577xx_doorbell_hdr header;
+	u8 zero_fill1;
+	u16 prod;
+#endif
+};
+
+
+struct regpair {
+	__le32 lo;
+	__le32 hi;
+};
+
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ */
+struct fcoe_abts_rsp_union {
+	u32 r_ctl;
+	u32 abts_rsp_payload[7];
+};
+
+
+/*
+ * 4 regs size
+ */
+struct fcoe_bd_ctx {
+	u32 buf_addr_hi;
+	u32 buf_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 rsrv0;
+	u16 buf_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 buf_len;
+	u16 rsrv0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 rsrv1;
+	u16 flags;
+#elif defined(__LITTLE_ENDIAN)
+	u16 flags;
+	u16 rsrv1;
+#endif
+};
+
+
+struct fcoe_cleanup_flow_info {
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u16 task_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 task_id;
+	u16 reserved1;
+#endif
+	u32 reserved2[7];
+};
+
+
+struct fcoe_fcp_cmd_payload {
+	u32 opaque[8];
+};
+
+struct fcoe_fc_hdr {
+#if defined(__BIG_ENDIAN)
+	u8 cs_ctl;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 cs_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 r_ctl;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 r_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 seq_id;
+	u8 df_ctl;
+	u16 seq_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u16 seq_cnt;
+	u8 df_ctl;
+	u8 seq_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 type;
+	u8 f_ctl[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 f_ctl[3];
+	u8 type;
+#endif
+	u32 parameters;
+#if defined(__BIG_ENDIAN)
+	u16 ox_id;
+	u16 rx_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_id;
+	u16 ox_id;
+#endif
+};
+
+struct fcoe_fc_frame {
+	struct fcoe_fc_hdr fc_hdr;
+	u32 reserved0[2];
+};
+
+union fcoe_cmd_flow_info {
+	struct fcoe_fcp_cmd_payload fcp_cmd_payload;
+	struct fcoe_fc_frame mp_fc_frame;
+};
+
+
+
+struct fcoe_fcp_rsp_flags {
+	u8 flags;
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
+};
+
+
+struct fcoe_fcp_rsp_payload {
+	struct regpair reserved0;
+	u32 fcp_resid;
+#if defined(__BIG_ENDIAN)
+	u16 retry_delay_timer;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	u8 scsi_status_code;
+#elif defined(__LITTLE_ENDIAN)
+	u8 scsi_status_code;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	u16 retry_delay_timer;
+#endif
+	u32 fcp_rsp_len;
+	u32 fcp_sns_len;
+};
+
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ */
+struct fcoe_fcp_rsp_union {
+	struct fcoe_fcp_rsp_payload payload;
+	struct regpair reserved0;
+};
+
+
+struct fcoe_fcp_xfr_rdy_payload {
+	u32 burst_len;
+	u32 data_ro;
+};
+
+struct fcoe_read_flow_info {
+	struct fcoe_fc_hdr fc_data_in_hdr;
+	u32 reserved[2];
+};
+
+struct fcoe_write_flow_info {
+	struct fcoe_fc_hdr fc_data_out_hdr;
+	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
+};
+
+union fcoe_rsp_flow_info {
+	struct fcoe_fcp_rsp_union fcp_rsp;
+	struct fcoe_abts_rsp_union abts_rsp;
+};
+
+/*
+ * 32 bytes used for general purposes
+ */
+union fcoe_general_task_ctx {
+	union fcoe_cmd_flow_info cmd_info;
+	struct fcoe_read_flow_info read_info;
+	struct fcoe_write_flow_info write_info;
+	union fcoe_rsp_flow_info rsp_info;
+	struct fcoe_cleanup_flow_info cleanup_info;
+	u32 comp_info[8];
+};
+
+
+/*
+ * FCoE KCQ CQE parameters
+ */
+union fcoe_kcqe_params {
+	u32 reserved0[4];
+};
+
+/*
+ * FCoE KCQ CQE
+ */
+struct fcoe_kcqe {
+	u32 fcoe_conn_id;
+	u32 completion_status;
+	u32 fcoe_conn_context_id;
+	union fcoe_kcqe_params params;
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 qe_self_seq;
+#elif defined(__LITTLE_ENDIAN)
+	u16 qe_self_seq;
+	u8 op_code;
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE KWQE header
+ */
+struct fcoe_kwqe_header {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+	u8 op_code;
+#elif defined(__LITTLE_ENDIAN)
+	u8 op_code;
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE firmware init request 1
+ */
+struct fcoe_kwqe_init1 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 num_tasks;
+#elif defined(__LITTLE_ENDIAN)
+	u16 num_tasks;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 task_list_pbl_addr_lo;
+	u32 task_list_pbl_addr_hi;
+	u32 dummy_buffer_addr_lo;
+	u32 dummy_buffer_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 rq_num_wqes;
+	u16 sq_num_wqes;
+#elif defined(__LITTLE_ENDIAN)
+	u16 sq_num_wqes;
+	u16 rq_num_wqes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 cq_num_wqes;
+	u16 rq_buffer_log_size;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_buffer_log_size;
+	u16 cq_num_wqes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+	u8 num_sessions_log;
+	u16 mtu;
+#elif defined(__LITTLE_ENDIAN)
+	u16 mtu;
+	u8 num_sessions_log;
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE firmware init request 2
+ */
+struct fcoe_kwqe_init2 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 hash_tbl_pbl_addr_lo;
+	u32 hash_tbl_pbl_addr_hi;
+	u32 t2_hash_tbl_addr_lo;
+	u32 t2_hash_tbl_addr_hi;
+	u32 t2_ptr_hash_tbl_addr_lo;
+	u32 t2_ptr_hash_tbl_addr_hi;
+	u32 free_list_count;
+};
+
+/*
+ * FCoE firmware init request 3
+ */
+struct fcoe_kwqe_init3 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 error_bit_map_lo;
+	u32 error_bit_map_hi;
+#if defined(__BIG_ENDIAN)
+	u8 reserved21[3];
+	u8 cached_session_enable;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cached_session_enable;
+	u8 reserved21[3];
+#endif
+	u32 reserved2[4];
+};
+
+/*
+ * FCoE connection offload request 1
+ */
+struct fcoe_kwqe_conn_offload1 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 fcoe_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 fcoe_conn_id;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 sq_addr_lo;
+	u32 sq_addr_hi;
+	u32 rq_pbl_addr_lo;
+	u32 rq_pbl_addr_hi;
+	u32 rq_first_pbe_addr_lo;
+	u32 rq_first_pbe_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u16 rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_prod;
+	u16 reserved0;
+#endif
+};
+
+/*
+ * FCoE connection offload request 2
+ */
+struct fcoe_kwqe_conn_offload2 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 tx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_max_fc_pay_len;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 cq_addr_lo;
+	u32 cq_addr_hi;
+	u32 xferq_addr_lo;
+	u32 xferq_addr_hi;
+	u32 conn_db_addr_lo;
+	u32 conn_db_addr_hi;
+	u32 reserved1;
+};
+
+/*
+ * FCoE connection offload request 3
+ */
+struct fcoe_kwqe_conn_offload3 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+#elif defined(__LITTLE_ENDIAN)
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+	struct fcoe_kwqe_header hdr;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 tx_max_conc_seqs_c3;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 tx_max_conc_seqs_c3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+#endif
+	u32 reserved;
+	u32 confq_first_pbe_addr_lo;
+	u32 confq_first_pbe_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 rx_max_fc_pay_len;
+	u16 tx_total_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_total_conc_seqs;
+	u16 rx_max_fc_pay_len;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 rx_open_seqs_exch_c3;
+	u8 rx_max_conc_seqs_c3;
+	u16 rx_total_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_total_conc_seqs;
+	u8 rx_max_conc_seqs_c3;
+	u8 rx_open_seqs_exch_c3;
+#endif
+};
+
+/*
+ * FCoE connection offload request 4
+ */
+struct fcoe_kwqe_conn_offload4 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u8 reserved2;
+	u8 e_d_tov_timer_val;
+#elif defined(__LITTLE_ENDIAN)
+	u8 e_d_tov_timer_val;
+	u8 reserved2;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u8 src_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u8 dst_mac_addr_hi16[2];
+	u8 src_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 src_mac_addr_hi16[2];
+	u8 dst_mac_addr_hi16[2];
+#endif
+	u8 dst_mac_addr_lo32[4];
+	u32 lcq_addr_lo;
+	u32 lcq_addr_hi;
+	u32 confq_pbl_base_addr_lo;
+	u32 confq_pbl_base_addr_hi;
+};
+
+/*
+ * FCoE connection enable request
+ */
+struct fcoe_kwqe_conn_enable_disable {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u8 src_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+	u8 src_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 src_mac_addr_hi16[2];
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+#endif
+	u8 dst_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 dst_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 dst_mac_addr_hi16[2];
+	u16 reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 vlan_flag;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 vlan_flag;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 reserved3;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 reserved3;
+#endif
+	u32 context_id;
+	u32 conn_id;
+	u32 reserved4;
+};
+
+/*
+ * FCoE connection destroy request
+ */
+struct fcoe_kwqe_conn_destroy {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 context_id;
+	u32 conn_id;
+	u32 reserved1[5];
+};
+
+/*
+ * FCoe destroy request
+ */
+struct fcoe_kwqe_destroy {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 reserved1[7];
+};
+
+/*
+ * FCoe statistics request
+ */
+struct fcoe_kwqe_stat {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 stat_params_addr_lo;
+	u32 stat_params_addr_hi;
+	u32 reserved1[5];
+};
+
+/*
+ * FCoE KWQ WQE
+ */
+union fcoe_kwqe {
+	struct fcoe_kwqe_init1 init1;
+	struct fcoe_kwqe_init2 init2;
+	struct fcoe_kwqe_init3 init3;
+	struct fcoe_kwqe_conn_offload1 conn_offload1;
+	struct fcoe_kwqe_conn_offload2 conn_offload2;
+	struct fcoe_kwqe_conn_offload3 conn_offload3;
+	struct fcoe_kwqe_conn_offload4 conn_offload4;
+	struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
+	struct fcoe_kwqe_conn_destroy conn_destroy;
+	struct fcoe_kwqe_destroy destroy;
+	struct fcoe_kwqe_stat statistics;
+};
+
+struct fcoe_mul_sges_ctx {
+	struct regpair cur_sge_addr;
+#if defined(__BIG_ENDIAN)
+	u8 sgl_size;
+	u8 cur_sge_idx;
+	u16 cur_sge_off;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cur_sge_off;
+	u8 cur_sge_idx;
+	u8 sgl_size;
+#endif
+};
+
+struct fcoe_s_stat_ctx {
+	u8 flags;
+#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
+#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
+#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
+#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
+#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
+#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
+#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
+#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
+};
+
+struct fcoe_seq_ctx {
+#if defined(__BIG_ENDIAN)
+	u16 low_seq_cnt;
+	struct fcoe_s_stat_ctx s_stat;
+	u8 seq_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 seq_id;
+	struct fcoe_s_stat_ctx s_stat;
+	u16 low_seq_cnt;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 err_seq_cnt;
+	u16 high_seq_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u16 high_seq_cnt;
+	u16 err_seq_cnt;
+#endif
+	u32 low_exp_ro;
+	u32 high_exp_ro;
+};
+
+
+struct fcoe_single_sge_ctx {
+	struct regpair cur_buf_addr;
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u16 cur_buf_rem;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cur_buf_rem;
+	u16 reserved0;
+#endif
+};
+
+union fcoe_sgl_ctx {
+	struct fcoe_single_sge_ctx single_sge;
+	struct fcoe_mul_sges_ctx mul_sges;
+};
+
+
+
+/*
+ * FCoE SQ element
+ */
+struct fcoe_sqe {
+	u16 wqe;
+#define FCOE_SQE_TASK_ID (0x7FFF<<0)
+#define FCOE_SQE_TASK_ID_SHIFT 0
+#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+struct fcoe_task_ctx_entry_tx_only {
+	union fcoe_sgl_ctx sgl_ctx;
+};
+
+struct fcoe_task_ctx_entry_txwr_rxrd {
+#if defined(__BIG_ENDIAN)
+	u16 verify_tx_seq;
+	u8 init_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
+	u8 tx_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+#elif defined(__LITTLE_ENDIAN)
+	u8 tx_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+	u8 init_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
+	u16 verify_tx_seq;
+#endif
+};
+
+/*
+ * Common section. Both TX and RX processing might write and read from it in
+ * different flows
+ */
+struct fcoe_task_ctx_entry_tx_rx_cmn {
+	u32 data_2_trns;
+	union fcoe_general_task_ctx general;
+#if defined(__BIG_ENDIAN)
+	u16 tx_low_seq_cnt;
+	struct fcoe_s_stat_ctx tx_s_stat;
+	u8 tx_seq_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 tx_seq_id;
+	struct fcoe_s_stat_ctx tx_s_stat;
+	u16 tx_low_seq_cnt;
+#endif
+	u32 common_flags;
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
+};
+
+struct fcoe_task_ctx_entry_rxwr_txrd {
+#if defined(__BIG_ENDIAN)
+	u16 rx_id;
+	u16 rx_flags;
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_flags;
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
+	u16 rx_id;
+#endif
+};
+
+struct fcoe_task_ctx_entry_rx_only {
+	struct fcoe_seq_ctx seq_ctx;
+	struct fcoe_seq_ctx ooo_seq_ctx;
+	u32 rsrv3;
+	union fcoe_sgl_ctx sgl_ctx;
+};
+
+struct fcoe_task_ctx_entry {
+	struct fcoe_task_ctx_entry_tx_only tx_wr_only;
+	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
+	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
+	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
+	struct fcoe_task_ctx_entry_rx_only rx_wr_only;
+	u32 reserved[4];
+};
+
+
+/*
+ * FCoE XFRQ element
+ */
+struct fcoe_xfrqe {
+	u16 wqe;
+#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
+#define FCOE_XFRQE_TASK_ID_SHIFT 0
+#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * FCoE CONFQ element
+ */
+struct fcoe_confqe {
+#if defined(__BIG_ENDIAN)
+	u16 rx_id;
+	u16 ox_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 ox_id;
+	u16 rx_id;
+#endif
+	u32 param;
+};
+
+
+/*
+ * FCoE conection data base
+ */
+struct fcoe_conn_db {
+#if defined(__BIG_ENDIAN)
+	u16 rsrv0;
+	u16 rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_prod;
+	u16 rsrv0;
+#endif
+	u32 rsrv1;
+	struct regpair cq_arm;
+};
+
+
+/*
+ * FCoE CQ element
+ */
+struct fcoe_cqe {
+	u16 wqe;
+#define FCOE_CQE_CQE_INFO (0x3FFF<<0)
+#define FCOE_CQE_CQE_INFO_SHIFT 0
+#define FCOE_CQE_CQE_TYPE (0x1<<14)
+#define FCOE_CQE_CQE_TYPE_SHIFT 14
+#define FCOE_CQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_CQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * FCoE error/warning resporting entry
+ */
+struct fcoe_err_report_entry {
+	u32 err_warn_bitmap_lo;
+	u32 err_warn_bitmap_hi;
+	u32 tx_buf_off;
+	u32 rx_buf_off;
+	struct fcoe_fc_hdr fc_hdr;
+};
+
+
+/*
+ * FCoE hash table entry (32 bytes)
+ */
+struct fcoe_hash_table_entry {
+#if defined(__BIG_ENDIAN)
+	u8 d_id_0;
+	u8 s_id_2;
+	u8 s_id_1;
+	u8 s_id_0;
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id_0;
+	u8 s_id_1;
+	u8 s_id_2;
+	u8 d_id_0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 dst_mac_addr_hi;
+	u8 d_id_2;
+	u8 d_id_1;
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id_1;
+	u8 d_id_2;
+	u16 dst_mac_addr_hi;
+#endif
+	u32 dst_mac_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 vlan_id;
+	u16 src_mac_addr_hi;
+#elif defined(__LITTLE_ENDIAN)
+	u16 src_mac_addr_hi;
+	u16 vlan_id;
+#endif
+	u32 src_mac_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 reserved0;
+	u8 vlan_flag;
+#elif defined(__LITTLE_ENDIAN)
+	u8 vlan_flag;
+	u8 reserved0;
+	u16 reserved1;
+#endif
+	u32 reserved2;
+	u32 field_id;
+#define FCOE_HASH_TABLE_ENTRY_CID (0xFFFFFF<<0)
+#define FCOE_HASH_TABLE_ENTRY_CID_SHIFT 0
+#define FCOE_HASH_TABLE_ENTRY_RESERVED3 (0x7F<<24)
+#define FCOE_HASH_TABLE_ENTRY_RESERVED3_SHIFT 24
+#define FCOE_HASH_TABLE_ENTRY_VALID (0x1<<31)
+#define FCOE_HASH_TABLE_ENTRY_VALID_SHIFT 31
+};
+
+/*
+ * FCoE pending work request CQE
+ */
+struct fcoe_pend_wq_cqe {
+	u16 wqe;
+#define FCOE_PEND_WQ_CQE_TASK_ID (0x3FFF<<0)
+#define FCOE_PEND_WQ_CQE_TASK_ID_SHIFT 0
+#define FCOE_PEND_WQ_CQE_CQE_TYPE (0x1<<14)
+#define FCOE_PEND_WQ_CQE_CQE_TYPE_SHIFT 14
+#define FCOE_PEND_WQ_CQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_PEND_WQ_CQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * FCoE RX statistics parameters section#0
+ */
+struct fcoe_rx_stat_params_section0 {
+	u32 fcoe_ver_cnt;
+	u32 fcoe_rx_pkt_cnt;
+	u32 fcoe_rx_byte_cnt;
+	u32 fcoe_rx_drop_pkt_cnt;
+};
+
+
+/*
+ * FCoE RX statistics parameters section#1
+ */
+struct fcoe_rx_stat_params_section1 {
+	u32 fc_crc_cnt;
+	u32 eofa_del_cnt;
+	u32 miss_frame_cnt;
+	u32 seq_timeout_cnt;
+	u32 drop_seq_cnt;
+	u32 fcoe_rx_drop_pkt_cnt;
+	u32 fcp_rx_pkt_cnt;
+	u32 reserved0;
+};
+
+
+/*
+ * FCoE TX statistics parameters
+ */
+struct fcoe_tx_stat_params {
+	u32 fcoe_tx_pkt_cnt;
+	u32 fcoe_tx_byte_cnt;
+	u32 fcp_tx_pkt_cnt;
+	u32 reserved0;
+};
+
+/*
+ * FCoE statistics parameters
+ */
+struct fcoe_statistics_params {
+	struct fcoe_tx_stat_params tx_stat;
+	struct fcoe_rx_stat_params_section0 rx_stat0;
+	struct fcoe_rx_stat_params_section1 rx_stat1;
+};
+
+
+/*
+ * FCoE t2 hash table entry (64 bytes)
+ */
+struct fcoe_t2_hash_table_entry {
+	struct fcoe_hash_table_entry data;
+	struct regpair next;
+	struct regpair reserved0[3];
+};
+
+/*
+ * FCoE unsolicited CQE
+ */
+struct fcoe_unsolicited_cqe {
+	u16 wqe;
+#define FCOE_UNSOLICITED_CQE_SUBTYPE (0x3<<0)
+#define FCOE_UNSOLICITED_CQE_SUBTYPE_SHIFT 0
+#define FCOE_UNSOLICITED_CQE_PKT_LEN (0xFFF<<2)
+#define FCOE_UNSOLICITED_CQE_PKT_LEN_SHIFT 2
+#define FCOE_UNSOLICITED_CQE_CQE_TYPE (0x1<<14)
+#define FCOE_UNSOLICITED_CQE_CQE_TYPE_SHIFT 14
+#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+#endif /* __57XX_FCOE_HSI_LINUX_LE__ */
diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig
new file mode 100644
index 0000000..6a38080
--- /dev/null
+++ b/drivers/scsi/bnx2fc/Kconfig
@@ -0,0 +1,11 @@
+config SCSI_BNX2X_FCOE
+	tristate "Broadcom NetXtreme II FCoE support"
+	depends on PCI
+	select NETDEVICES
+	select NETDEV_1000
+	select LIBFC
+	select LIBFCOE
+	select CNIC
+	---help---
+	This driver supports FCoE offload for the Broadcom NetXtreme II
+	devices.
diff --git a/drivers/scsi/bnx2fc/Makefile b/drivers/scsi/bnx2fc/Makefile
new file mode 100644
index 0000000..a92695a
--- /dev/null
+++ b/drivers/scsi/bnx2fc/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SCSI_BNX2X_FCOE) += bnx2fc.o
+
+bnx2fc-y := bnx2fc_els.o bnx2fc_fcoe.o bnx2fc_hwi.o bnx2fc_io.o bnx2fc_tgt.o
diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h
new file mode 100644
index 0000000..df2fc09
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc.h
@@ -0,0 +1,511 @@
+#ifndef _BNX2FC_H_
+#define _BNX2FC_H_
+/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
+ *
+ * Copyright (c) 2008 - 2010 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/kthread.h>
+#include <linux/crc32.h>
+#include <linux/cpu.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+#include <scsi/fc_encode.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/fc/fc_fip.h>
+#include <scsi/fc/fc_fc2.h>
+#include <scsi/fc_frame.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/fc/fc_fcp.h>
+
+#include "57xx_hsi_bnx2fc.h"
+#include "bnx2fc_debug.h"
+#include "../../net/cnic_if.h"
+#include "bnx2fc_constants.h"
+
+#define BNX2FC_NAME		"bnx2fc"
+#define BNX2FC_VERSION		"1.0.0"
+
+#define PFX			"bnx2fc: "
+
+#define BNX2X_DOORBELL_PCI_BAR		2
+
+#define BNX2FC_MAX_BD_LEN		0xffff
+#define BNX2FC_BD_SPLIT_SZ		0x8000
+#define BNX2FC_MAX_BDS_PER_CMD		256
+
+#define BNX2FC_SQ_WQES_MAX	256
+
+#define BNX2FC_SCSI_MAX_SQES	((3 * BNX2FC_SQ_WQES_MAX) / 8)
+#define BNX2FC_TM_MAX_SQES	((BNX2FC_SQ_WQES_MAX) / 2)
+#define BNX2FC_ELS_MAX_SQES	(BNX2FC_TM_MAX_SQES - 1)
+
+#define BNX2FC_RQ_WQES_MAX	16
+#define BNX2FC_CQ_WQES_MAX	(BNX2FC_SQ_WQES_MAX + BNX2FC_RQ_WQES_MAX)
+
+#define BNX2FC_NUM_MAX_SESS	128
+#define BNX2FC_NUM_MAX_SESS_LOG	(ilog2(BNX2FC_NUM_MAX_SESS))
+
+#define BNX2FC_MAX_OUTSTANDING_CMNDS	4096
+#define BNX2FC_MIN_PAYLOAD		256
+#define BNX2FC_MAX_PAYLOAD		2048
+
+#define BNX2FC_RQ_BUF_SZ		256
+#define BNX2FC_RQ_BUF_LOG_SZ		(ilog2(BNX2FC_RQ_BUF_SZ))
+
+#define BNX2FC_SQ_WQE_SIZE		(sizeof(struct fcoe_sqe))
+#define BNX2FC_CQ_WQE_SIZE		(sizeof(struct fcoe_cqe))
+#define BNX2FC_RQ_WQE_SIZE		(BNX2FC_RQ_BUF_SZ)
+#define BNX2FC_XFERQ_WQE_SIZE		(sizeof(struct fcoe_xfrqe))
+#define BNX2FC_CONFQ_WQE_SIZE		(sizeof(struct fcoe_confqe))
+#define BNX2FC_5771X_DB_PAGE_SIZE	128
+
+#define BNX2FC_MAX_TASKS		BNX2FC_MAX_OUTSTANDING_CMNDS
+#define BNX2FC_TASK_SIZE		128
+#define	BNX2FC_TASKS_PER_PAGE		(PAGE_SIZE/BNX2FC_TASK_SIZE)
+#define BNX2FC_TASK_CTX_ARR_SZ		(BNX2FC_MAX_TASKS/BNX2FC_TASKS_PER_PAGE)
+
+#define BNX2FC_MAX_ROWS_IN_HASH_TBL	8
+#define BNX2FC_HASH_TBL_CHUNK_SIZE	(16 * 1024)
+
+#define BNX2FC_MAX_SEQS			255
+
+#define BNX2FC_READ			(1 << 1)
+#define BNX2FC_WRITE			(1 << 0)
+
+#define BNX2FC_MIN_XID			0
+#define BNX2FC_MAX_XID			(BNX2FC_MAX_OUTSTANDING_CMNDS - 1)
+#define FCOE_MIN_XID			(BNX2FC_MAX_OUTSTANDING_CMNDS)
+#define FCOE_MAX_XID		\
+			(BNX2FC_MAX_OUTSTANDING_CMNDS + (nr_cpu_ids * 256))
+#define BNX2FC_MAX_LUN			0xFFFF
+#define BNX2FC_MAX_FCP_TGT		256
+#define BNX2FC_MAX_CMD_LEN		16
+
+#define BNX2FC_TM_TIMEOUT		60	/* secs */
+#define BNX2FC_IO_TIMEOUT		20000UL	/* msecs */
+
+#define BNX2FC_WAIT_CNT			120
+#define BNX2FC_FW_TIMEOUT		(3 * HZ)
+
+#define PORT_MAX			2
+
+#define CMD_SCSI_STATUS(Cmnd)		((Cmnd)->SCp.Status)
+
+/* FC FCP Status */
+#define	FC_GOOD				0
+
+#define BNX2FC_RNID_HBA			0x7
+
+/* bnx2fc driver uses only one instance of fcoe_percpu_s */
+extern struct fcoe_percpu_s bnx2fc_global;
+
+extern struct workqueue_struct *bnx2fc_wq;
+
+struct bnx2fc_percpu_s {
+	struct task_struct *iothread;
+	struct list_head work_list;
+	spinlock_t fp_work_lock;
+};
+
+
+struct bnx2fc_hba {
+	struct list_head link;
+	struct cnic_dev *cnic;
+	struct pci_dev *pcidev;
+	struct net_device *netdev;
+	struct net_device *phys_dev;
+	unsigned long reg_with_cnic;
+		#define BNX2FC_CNIC_REGISTERED           1
+	struct packet_type fcoe_packet_type;
+	struct packet_type fip_packet_type;
+	struct bnx2fc_cmd_mgr *cmd_mgr;
+	struct workqueue_struct *timer_work_queue;
+	struct kref kref;
+	spinlock_t hba_lock;
+	struct mutex hba_mutex;
+	unsigned long adapter_state;
+		#define ADAPTER_STATE_UP		0
+		#define ADAPTER_STATE_GOING_DOWN	1
+		#define ADAPTER_STATE_LINK_DOWN		2
+		#define ADAPTER_STATE_READY		3
+	u32 flags;
+	unsigned long init_done;
+		#define BNX2FC_FW_INIT_DONE		0
+		#define BNX2FC_CTLR_INIT_DONE		1
+		#define BNX2FC_CREATE_DONE		2
+	struct fcoe_ctlr ctlr;
+	u8 vlan_enabled;
+	int vlan_id;
+	u32 next_conn_id;
+	struct fcoe_task_ctx_entry **task_ctx;
+	dma_addr_t *task_ctx_dma;
+	struct regpair *task_ctx_bd_tbl;
+	dma_addr_t task_ctx_bd_dma;
+
+	int hash_tbl_segment_count;
+	void **hash_tbl_segments;
+	void *hash_tbl_pbl;
+	dma_addr_t hash_tbl_pbl_dma;
+	struct fcoe_t2_hash_table_entry *t2_hash_tbl;
+	dma_addr_t t2_hash_tbl_dma;
+	char *t2_hash_tbl_ptr;
+	dma_addr_t t2_hash_tbl_ptr_dma;
+
+	char *dummy_buffer;
+	dma_addr_t dummy_buf_dma;
+
+	struct fcoe_statistics_params *stats_buffer;
+	dma_addr_t stats_buf_dma;
+
+	/*
+	 * PCI related info.
+	 */
+	u16 pci_did;
+	u16 pci_vid;
+	u16 pci_sdid;
+	u16 pci_svid;
+	u16 pci_func;
+	u16 pci_devno;
+
+	struct task_struct *l2_thread;
+
+	/* linkdown handling */
+	wait_queue_head_t shutdown_wait;
+	int wait_for_link_down;
+
+	/*destroy handling */
+	struct timer_list destroy_timer;
+	wait_queue_head_t destroy_wait;
+
+	/* Active list of offloaded sessions */
+	struct bnx2fc_rport *tgt_ofld_list[BNX2FC_NUM_MAX_SESS];
+	int num_ofld_sess;
+
+	/* statistics */
+	struct completion stat_req_done;
+};
+
+#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_hba, ctlr)
+
+struct bnx2fc_cmd_mgr {
+	struct bnx2fc_hba *hba;
+	u16 next_idx;
+	struct list_head *free_list;
+	spinlock_t *free_list_lock;
+	struct io_bdt **io_bdt_pool;
+	struct bnx2fc_cmd **cmds;
+};
+
+struct bnx2fc_rport {
+	struct fcoe_port *port;
+	struct fc_rport *rport;
+	struct fc_rport_priv *rdata;
+	void __iomem *ctx_base;
+#define DPM_TRIGER_TYPE		0x40
+	u32 fcoe_conn_id;
+	u32 context_id;
+	u32 sid;
+
+	unsigned long flags;
+#define BNX2FC_FLAG_SESSION_READY	0x1
+#define BNX2FC_FLAG_OFFLOADED		0x2
+#define BNX2FC_FLAG_DISABLED		0x3
+#define BNX2FC_FLAG_DESTROYED		0x4
+#define BNX2FC_FLAG_OFLD_REQ_CMPL	0x5
+#define BNX2FC_FLAG_DESTROY_CMPL	0x6
+#define BNX2FC_FLAG_CTX_ALLOC_FAILURE	0x7
+#define BNX2FC_FLAG_UPLD_REQ_COMPL	0x8
+#define BNX2FC_FLAG_EXPL_LOGO		0x9
+
+	u32 max_sqes;
+	u32 max_rqes;
+	u32 max_cqes;
+
+	struct fcoe_sqe *sq;
+	dma_addr_t sq_dma;
+	u16 sq_prod_idx;
+	u8 sq_curr_toggle_bit;
+	u32 sq_mem_size;
+
+	struct fcoe_cqe *cq;
+	dma_addr_t cq_dma;
+	u32 cq_cons_idx;
+	u8 cq_curr_toggle_bit;
+	u32 cq_mem_size;
+
+	void *rq;
+	dma_addr_t rq_dma;
+	u32 rq_prod_idx;
+	u32 rq_cons_idx;
+	u32 rq_mem_size;
+
+	void *rq_pbl;
+	dma_addr_t rq_pbl_dma;
+	u32 rq_pbl_size;
+
+	struct fcoe_xfrqe *xferq;
+	dma_addr_t xferq_dma;
+	u32 xferq_mem_size;
+
+	struct fcoe_confqe *confq;
+	dma_addr_t confq_dma;
+	u32 confq_mem_size;
+
+	void *confq_pbl;
+	dma_addr_t confq_pbl_dma;
+	u32 confq_pbl_size;
+
+	struct fcoe_conn_db *conn_db;
+	dma_addr_t conn_db_dma;
+	u32 conn_db_mem_size;
+
+	struct fcoe_sqe *lcq;
+	dma_addr_t lcq_dma;
+	u32 lcq_mem_size;
+
+	void *ofld_req[4];
+	dma_addr_t ofld_req_dma[4];
+	void *enbl_req;
+	dma_addr_t enbl_req_dma;
+
+	spinlock_t tgt_lock;
+	spinlock_t cq_lock;
+	atomic_t num_active_ios;
+	u32 flush_in_prog;
+	unsigned long work_time_slice;
+	unsigned long timestamp;
+	struct list_head free_task_list;
+	struct bnx2fc_cmd *pending_queue[BNX2FC_SQ_WQES_MAX+1];
+	atomic_t pi;
+	atomic_t ci;
+	struct list_head active_cmd_queue;
+	struct list_head els_queue;
+	struct list_head io_retire_queue;
+	struct list_head active_tm_queue;
+
+	struct timer_list ofld_timer;
+	wait_queue_head_t ofld_wait;
+
+	struct timer_list upld_timer;
+	wait_queue_head_t upld_wait;
+};
+
+struct bnx2fc_mp_req {
+	u8 tm_flags;
+
+	u32 req_len;
+	void *req_buf;
+	dma_addr_t req_buf_dma;
+	struct fcoe_bd_ctx *mp_req_bd;
+	dma_addr_t mp_req_bd_dma;
+	struct fc_frame_header req_fc_hdr;
+
+	u32 resp_len;
+	void *resp_buf;
+	dma_addr_t resp_buf_dma;
+	struct fcoe_bd_ctx *mp_resp_bd;
+	dma_addr_t mp_resp_bd_dma;
+	struct fc_frame_header resp_fc_hdr;
+};
+
+struct bnx2fc_els_cb_arg {
+	struct bnx2fc_cmd *aborted_io_req;
+	struct bnx2fc_cmd *io_req;
+	u16 l2_oxid;
+};
+
+/* bnx2fc command structure */
+struct bnx2fc_cmd {
+	struct list_head link;
+	u8 on_active_queue;
+	u8 on_tmf_queue;
+	u8 cmd_type;
+#define BNX2FC_SCSI_CMD		1
+#define BNX2FC_TASK_MGMT_CMD		2
+#define BNX2FC_ABTS			3
+#define BNX2FC_ELS			4
+#define BNX2FC_CLEANUP			5
+	u8 io_req_flags;
+	struct kref refcount;
+	struct fcoe_port *port;
+	struct bnx2fc_rport *tgt;
+	struct scsi_cmnd *sc_cmd;
+	struct bnx2fc_cmd_mgr *cmd_mgr;
+	struct bnx2fc_mp_req mp_req;
+	void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg);
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct delayed_work timeout_work; /* timer for ULP timeouts */
+	struct completion tm_done;
+	int wait_for_comp;
+	u16 xid;
+	struct fcoe_task_ctx_entry *task;
+	struct io_bdt *bd_tbl;
+	struct fcp_rsp *rsp;
+	size_t data_xfer_len;
+	unsigned long req_flags;
+#define BNX2FC_FLAG_ISSUE_RRQ		0x1
+#define BNX2FC_FLAG_ISSUE_ABTS		0x2
+#define BNX2FC_FLAG_ABTS_DONE		0x3
+#define BNX2FC_FLAG_TM_COMPL		0x4
+#define BNX2FC_FLAG_TM_TIMEOUT		0x5
+#define BNX2FC_FLAG_IO_CLEANUP		0x6
+#define BNX2FC_FLAG_RETIRE_OXID		0x7
+#define	BNX2FC_FLAG_EH_ABORT		0x8
+#define BNX2FC_FLAG_IO_COMPL		0x9
+#define BNX2FC_FLAG_ELS_DONE		0xa
+#define BNX2FC_FLAG_ELS_TIMEOUT		0xb
+	u32 fcp_resid;
+	u32 fcp_rsp_len;
+	u32 fcp_sns_len;
+	u8 cdb_status; /* SCSI IO status */
+	u8 fcp_status; /* FCP IO status */
+	u8 fcp_rsp_code;
+	u8 scsi_comp_flags;
+};
+
+struct io_bdt {
+	struct bnx2fc_cmd *io_req;
+	struct fcoe_bd_ctx *bd_tbl;
+	dma_addr_t bd_tbl_dma;
+	u16 bd_valid;
+};
+
+struct bnx2fc_work {
+	struct list_head list;
+	struct bnx2fc_rport *tgt;
+	u16 wqe;
+};
+struct bnx2fc_unsol_els {
+	struct fc_lport *lport;
+	struct fc_frame *fp;
+	struct work_struct unsol_els_work;
+};
+
+
+
+struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type);
+void bnx2fc_cmd_release(struct kref *ref);
+int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd);
+int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba);
+int bnx2fc_send_fw_fcoe_destroy_msg(struct bnx2fc_hba *hba);
+int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt);
+int bnx2fc_send_session_disable_req(struct fcoe_port *port,
+				    struct bnx2fc_rport *tgt);
+int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
+					struct bnx2fc_rport *tgt);
+int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt);
+void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
+					u32 num_cqe);
+int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba);
+void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba);
+int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba);
+void bnx2fc_free_fw_resc(struct bnx2fc_hba *hba);
+struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
+						u16 min_xid, u16 max_xid);
+void bnx2fc_cmd_mgr_free(struct bnx2fc_cmd_mgr *cmgr);
+void bnx2fc_get_link_state(struct bnx2fc_hba *hba);
+char *bnx2fc_get_next_rqe(struct bnx2fc_rport *tgt, u8 num_items);
+void bnx2fc_return_rqe(struct bnx2fc_rport *tgt, u8 num_items);
+int bnx2fc_get_paged_crc_eof(struct sk_buff *skb, int tlen);
+int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req);
+int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp);
+int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp);
+int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp);
+int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req);
+int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req);
+void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
+			  unsigned int timer_msec);
+int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req);
+void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
+			      struct fcoe_task_ctx_entry *task,
+			      u16 orig_xid);
+void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
+			 struct fcoe_task_ctx_entry *task);
+void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task);
+void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid);
+void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt);
+int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd);
+int bnx2fc_eh_host_reset(struct scsi_cmnd *sc_cmd);
+int bnx2fc_eh_target_reset(struct scsi_cmnd *sc_cmd);
+int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd);
+void bnx2fc_rport_event_handler(struct fc_lport *lport,
+				struct fc_rport_priv *rport,
+				enum fc_rport_event event);
+void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
+				   struct fcoe_task_ctx_entry *task,
+				   u8 num_rq);
+void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
+			       struct fcoe_task_ctx_entry *task,
+			       u8 num_rq);
+void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
+			       struct fcoe_task_ctx_entry *task,
+			       u8 num_rq);
+void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task,
+			     u8 num_rq);
+void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
+			      struct fcoe_task_ctx_entry *task,
+			      u8 num_rq);
+void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
+			   struct fcp_cmnd *fcp_cmnd);
+
+
+
+void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt);
+struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
+				      struct fc_frame *fp, unsigned int op,
+				      void (*resp)(struct fc_seq *,
+						   struct fc_frame *,
+						   void *),
+				      void *arg, u32 timeout);
+int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
+void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
+struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
+					     u32 port_id);
+void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
+				   unsigned char *buf,
+				   u32 frame_len, u16 l2_oxid);
+int bnx2fc_send_stat_req(struct bnx2fc_hba *hba);
+
+#endif
diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h
new file mode 100644
index 0000000..fe77691
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h
@@ -0,0 +1,206 @@
+#ifndef __BNX2FC_CONSTANTS_H_
+#define __BNX2FC_CONSTANTS_H_
+
+/**
+ * This file defines HSI constants for the FCoE flows
+ */
+
+/* KWQ/KCQ FCoE layer code */
+#define FCOE_KWQE_LAYER_CODE   (7)
+
+/* KWQ (kernel work queue) request op codes */
+#define FCOE_KWQE_OPCODE_INIT1			(0)
+#define FCOE_KWQE_OPCODE_INIT2			(1)
+#define FCOE_KWQE_OPCODE_INIT3			(2)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN1	(3)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN2	(4)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN3	(5)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN4	(6)
+#define FCOE_KWQE_OPCODE_ENABLE_CONN	(7)
+#define FCOE_KWQE_OPCODE_DISABLE_CONN	(8)
+#define FCOE_KWQE_OPCODE_DESTROY_CONN	(9)
+#define FCOE_KWQE_OPCODE_DESTROY		(10)
+#define FCOE_KWQE_OPCODE_STAT			(11)
+
+/* KCQ (kernel completion queue) response op codes */
+#define FCOE_KCQE_OPCODE_INIT_FUNC				(0x10)
+#define FCOE_KCQE_OPCODE_DESTROY_FUNC			(0x11)
+#define FCOE_KCQE_OPCODE_STAT_FUNC				(0x12)
+#define FCOE_KCQE_OPCODE_OFFLOAD_CONN			(0x15)
+#define FCOE_KCQE_OPCODE_ENABLE_CONN			(0x16)
+#define FCOE_KCQE_OPCODE_DISABLE_CONN			(0x17)
+#define FCOE_KCQE_OPCODE_DESTROY_CONN			(0x18)
+#define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION  (0x20)
+#define FCOE_KCQE_OPCODE_FCOE_ERROR				(0x21)
+
+/* KCQ (kernel completion queue) completion status */
+#define FCOE_KCQE_COMPLETION_STATUS_SUCCESS				(0x0)
+#define FCOE_KCQE_COMPLETION_STATUS_ERROR				(0x1)
+#define FCOE_KCQE_COMPLETION_STATUS_INVALID_OPCODE		(0x2)
+#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE	(0x3)
+#define FCOE_KCQE_COMPLETION_STATUS_CTX_FREE_FAILURE	(0x4)
+#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR			(0x5)
+
+/* Unsolicited CQE type */
+#define FCOE_UNSOLICITED_FRAME_CQE_TYPE			0
+#define FCOE_ERROR_DETECTION_CQE_TYPE			1
+#define FCOE_WARNING_DETECTION_CQE_TYPE			2
+
+/* Task context constants */
+/* After driver has initialize the task in case timer services required */
+#define	FCOE_TASK_TX_STATE_INIT					0
+/* In case timer services are required then shall be updated by Xstorm after
+ * start processing the task. In case no timer facilities are required then the
+ * driver would initialize the state to this value */
+#define	FCOE_TASK_TX_STATE_NORMAL				1
+/* Task is under abort procedure. Updated in order to stop processing of
+ * pending WQEs on this task */
+#define	FCOE_TASK_TX_STATE_ABORT				2
+/* For E_D_T_TOV timer expiration in Xstorm (Class 2 only) */
+#define	FCOE_TASK_TX_STATE_ERROR				3
+/* For REC_TOV timer expiration indication received from Xstorm */
+#define	FCOE_TASK_TX_STATE_WARNING				4
+/* For completed unsolicited task */
+#define	FCOE_TASK_TX_STATE_UNSOLICITED_COMPLETED		5
+/* For exchange cleanup request task */
+#define	FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP			6
+/* For sequence cleanup request task */
+#define	FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP			7
+/* Mark task as aborted and indicate that ABTS was not transmitted */
+#define	FCOE_TASK_TX_STATE_BEFORE_ABTS_TX			8
+/* Mark task as aborted and indicate that ABTS was transmitted */
+#define	FCOE_TASK_TX_STATE_AFTER_ABTS_TX			9
+/* For completion the ABTS task. */
+#define	FCOE_TASK_TX_STATE_ABTS_TX_COMPLETED			10
+/* Mark task as aborted and indicate that Exchange cleanup was not transmitted
+ */
+#define	FCOE_TASK_TX_STATE_BEFORE_EXCHANGE_CLEANUP_TX		11
+/* Mark task as aborted and indicate that Exchange cleanup was transmitted */
+#define	FCOE_TASK_TX_STATE_AFTER_EXCHANGE_CLEANUP_TX		12
+
+#define	FCOE_TASK_RX_STATE_NORMAL				0
+#define	FCOE_TASK_RX_STATE_COMPLETED				1
+/* Obsolete: Intermediate completion (middle path with local completion) */
+#define	FCOE_TASK_RX_STATE_INTER_COMP				2
+/* For REC_TOV timer expiration indication received from Xstorm */
+#define	FCOE_TASK_RX_STATE_WARNING				3
+/* For E_D_T_TOV timer expiration in Ustorm */
+#define	FCOE_TASK_RX_STATE_ERROR				4
+/* ABTS ACC arrived wait for local completion to finally complete the task. */
+#define	FCOE_TASK_RX_STATE_ABTS_ACC_ARRIVED			5
+/* local completion arrived wait for ABTS ACC to finally complete the task. */
+#define	FCOE_TASK_RX_STATE_ABTS_LOCAL_COMP_ARRIVED		6
+/* Special completion indication in case of task was aborted. */
+#define FCOE_TASK_RX_STATE_ABTS_COMPLETED			7
+/* Special completion indication in case of task was cleaned. */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED		8
+/* Special completion indication (in task requested the exchange cleanup) in
+ * case cleaned task is in non-valid. */
+#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED		9
+/* Special completion indication (in task requested the sequence cleanup) in
+ * case cleaned task was already returned to normal. */
+#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP		10
+/* Exchange cleanup arrived wait until xfer will be handled to finally
+ * complete the task. */
+#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_ARRIVED		11
+/* Xfer handled, wait for exchange cleanup to finally complete the task. */
+#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_HANDLED_XFER	12
+
+#define	FCOE_TASK_TYPE_WRITE			0
+#define	FCOE_TASK_TYPE_READ				1
+#define	FCOE_TASK_TYPE_MIDPATH			2
+#define	FCOE_TASK_TYPE_UNSOLICITED		3
+#define	FCOE_TASK_TYPE_ABTS				4
+#define	FCOE_TASK_TYPE_EXCHANGE_CLEANUP	5
+#define	FCOE_TASK_TYPE_SEQUENCE_CLEANUP	6
+
+#define FCOE_TASK_DEV_TYPE_DISK			0
+#define FCOE_TASK_DEV_TYPE_TAPE			1
+
+#define FCOE_TASK_CLASS_TYPE_3			0
+#define FCOE_TASK_CLASS_TYPE_2			1
+
+/* Everest FCoE connection type */
+#define B577XX_FCOE_CONNECTION_TYPE		4
+
+/* Error codes for Error Reporting in fast path flows */
+/* XFER error codes */
+#define FCOE_ERROR_CODE_XFER_OOO_RO					0
+#define FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED				1
+#define FCOE_ERROR_CODE_XFER_NULL_BURST_LEN				2
+#define FCOE_ERROR_CODE_XFER_RO_GREATER_THAN_DATA2TRNS			3
+#define FCOE_ERROR_CODE_XFER_INVALID_PAYLOAD_SIZE			4
+#define FCOE_ERROR_CODE_XFER_TASK_TYPE_NOT_WRITE			5
+#define FCOE_ERROR_CODE_XFER_PEND_XFER_SET				6
+#define FCOE_ERROR_CODE_XFER_OPENED_SEQ					7
+#define FCOE_ERROR_CODE_XFER_FCTL					8
+
+/* FCP RSP error codes */
+#define FCOE_ERROR_CODE_FCP_RSP_BIDI_FLAGS_SET				9
+#define FCOE_ERROR_CODE_FCP_RSP_UNDERFLOW				10
+#define FCOE_ERROR_CODE_FCP_RSP_OVERFLOW				11
+#define FCOE_ERROR_CODE_FCP_RSP_INVALID_LENGTH_FIELD			12
+#define FCOE_ERROR_CODE_FCP_RSP_INVALID_SNS_FIELD			13
+#define FCOE_ERROR_CODE_FCP_RSP_INVALID_PAYLOAD_SIZE			14
+#define FCOE_ERROR_CODE_FCP_RSP_PEND_XFER_SET				15
+#define FCOE_ERROR_CODE_FCP_RSP_OPENED_SEQ				16
+#define FCOE_ERROR_CODE_FCP_RSP_FCTL					17
+#define FCOE_ERROR_CODE_FCP_RSP_LAST_SEQ_RESET				18
+#define FCOE_ERROR_CODE_FCP_RSP_CONF_REQ_NOT_SUPPORTED_YET		19
+
+/* FCP DATA error codes */
+#define FCOE_ERROR_CODE_DATA_OOO_RO					20
+#define FCOE_ERROR_CODE_DATA_EXCEEDS_DEFINED_MAX_FRAME_SIZE		21
+#define FCOE_ERROR_CODE_DATA_EXCEEDS_DATA2TRNS				22
+#define FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET			23
+#define FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET			24
+#define FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET				25
+#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET			26
+#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ			27
+#define FCOE_ERROR_CODE_DATA_FCTL					28
+
+/* Middle path error codes */
+#define FCOE_ERROR_CODE_MIDPATH_TYPE_NOT_ELS				29
+#define FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET			30
+#define FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET			31
+#define FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET			32
+#define FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET			33
+#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_FCTL				34
+#define FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY				35
+#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL				36
+
+/* ABTS error codes */
+#define FCOE_ERROR_CODE_ABTS_REPLY_F_CTL				37
+#define FCOE_ERROR_CODE_ABTS_REPLY_DDF_RCTL_FIELD			38
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_BLS_RCTL			39
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL			40
+#define FCOE_ERROR_CODE_ABTS_REPLY_RCTL_GENERAL_MISMATCH		41
+
+/* Common error codes */
+#define FCOE_ERROR_CODE_COMMON_MIDDLE_FRAME_WITH_PAD			42
+#define FCOE_ERROR_CODE_COMMON_SEQ_INIT_IN_TCE				43
+#define FCOE_ERROR_CODE_COMMON_FC_HDR_RX_ID_MISMATCH			44
+#define FCOE_ERROR_CODE_COMMON_INCORRECT_SEQ_CNT			45
+#define FCOE_ERROR_CODE_COMMON_DATA_FC_HDR_FCP_TYPE_MISMATCH		46
+#define FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES			47
+#define FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR				48
+#define FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG			49
+#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED		50
+
+/* Unsolicited Rx error codes */
+#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_ELS			51
+#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_BLS			52
+#define FCOE_ERROR_CODE_UNSOLICITED_FCTL_ELS				53
+#define FCOE_ERROR_CODE_UNSOLICITED_FCTL_BLS				54
+#define FCOE_ERROR_CODE_UNSOLICITED_R_CTL				55
+
+#define FCOE_ERROR_CODE_RW_TASK_DDF_RCTL_INFO_FIELD			56
+#define FCOE_ERROR_CODE_RW_TASK_INVALID_RCTL				57
+#define FCOE_ERROR_CODE_RW_TASK_RCTL_GENERAL_MISMATCH			58
+
+/* Timer error codes */
+#define FCOE_ERROR_CODE_E_D_TOV_TIMER_EXPIRATION			60
+#define FCOE_ERROR_CODE_REC_TOV_TIMER_EXPIRATION			61
+
+
+#endif /* BNX2FC_CONSTANTS_H_ */
diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h
new file mode 100644
index 0000000..7f6aff6
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h
@@ -0,0 +1,70 @@
+#ifndef __BNX2FC_DEBUG__
+#define __BNX2FC_DEBUG__
+
+/* Log level bit mask */
+#define LOG_IO		0x01	/* scsi cmd error, cleanup */
+#define LOG_TGT		0x02	/* Session setup, cleanup, etc' */
+#define LOG_HBA		0x04	/* lport events, link, mtu, etc' */
+#define LOG_ELS		0x08	/* ELS logs */
+#define LOG_MISC	0x10	/* fcoe L2 frame related logs*/
+#define LOG_ALL		0xff	/* LOG all messages */
+
+extern unsigned int bnx2fc_debug_level;
+
+#define BNX2FC_CHK_LOGGING(LEVEL, CMD)					\
+	do {								\
+		if (unlikely(bnx2fc_debug_level & LEVEL))		\
+			do {						\
+				CMD;					\
+			} while (0);					\
+	} while (0)
+
+#define BNX2FC_ELS_DBG(fmt, arg...)					\
+	BNX2FC_CHK_LOGGING(LOG_ELS,					\
+			   printk(KERN_ALERT PFX fmt, ##arg))
+
+#define BNX2FC_MISC_DBG(fmt, arg...)					\
+	BNX2FC_CHK_LOGGING(LOG_MISC,					\
+			   printk(KERN_ALERT PFX fmt, ##arg))
+
+#define BNX2FC_IO_DBG(io_req, fmt, arg...)				\
+	do {								\
+		if (!io_req || !io_req->port || !io_req->port->lport ||	\
+		    !io_req->port->lport->host)				\
+			BNX2FC_CHK_LOGGING(LOG_IO,			\
+			   printk(KERN_ALERT PFX "NULL " fmt, ##arg));	\
+		else							\
+			BNX2FC_CHK_LOGGING(LOG_IO,			\
+			   shost_printk(KERN_ALERT,			\
+				   (io_req)->port->lport->host,		\
+				   PFX "xid:0x%x " fmt,			\
+				   (io_req)->xid, ##arg));		\
+	} while (0)
+
+#define BNX2FC_TGT_DBG(tgt, fmt, arg...)				\
+	do {								\
+		if (!tgt || !tgt->port || !tgt->port->lport ||		\
+		    !tgt->port->lport->host || !tgt->rport)		\
+			BNX2FC_CHK_LOGGING(LOG_TGT,			\
+			   printk(KERN_ALERT PFX "NULL " fmt, ##arg));	\
+		else							\
+			BNX2FC_CHK_LOGGING(LOG_TGT,			\
+			   shost_printk(KERN_ALERT,			\
+				   (tgt)->port->lport->host,		\
+				   PFX "port:%x " fmt,			\
+				   (tgt)->rport->port_id, ##arg));	\
+	} while (0)
+
+
+#define BNX2FC_HBA_DBG(lport, fmt, arg...)				\
+	do {								\
+		if (!lport || !lport->host)				\
+			BNX2FC_CHK_LOGGING(LOG_HBA,			\
+			   printk(KERN_ALERT PFX "NULL " fmt, ##arg));	\
+		else							\
+			BNX2FC_CHK_LOGGING(LOG_HBA,			\
+			   shost_printk(KERN_ALERT, lport->host,	\
+				   PFX fmt, ##arg));			\
+	} while (0)
+
+#endif
diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c
new file mode 100644
index 0000000..7a11a25
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_els.c
@@ -0,0 +1,515 @@
+/*
+ * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * This file contains helper routines that handle ELS requests
+ * and responses.
+ *
+ * Copyright (c) 2008 - 2010 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
+			     void *arg);
+static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
+			      void *arg);
+static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
+			void *data, u32 data_len,
+			void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
+			struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec);
+
+static void bnx2fc_rrq_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+	struct bnx2fc_cmd *orig_io_req;
+	struct bnx2fc_cmd *rrq_req;
+	int rc = 0;
+
+	BUG_ON(!cb_arg);
+	rrq_req = cb_arg->io_req;
+	orig_io_req = cb_arg->aborted_io_req;
+	BUG_ON(!orig_io_req);
+	BNX2FC_ELS_DBG("rrq_compl: orig xid = 0x%x, rrq_xid = 0x%x\n",
+		   orig_io_req->xid, rrq_req->xid);
+
+	kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+
+	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rrq_req->req_flags)) {
+		/*
+		 * els req is timed out. cleanup the IO with FW and
+		 * drop the completion. Remove from active_cmd_queue.
+		 */
+		BNX2FC_ELS_DBG("rrq xid - 0x%x timed out, clean it up\n",
+			   rrq_req->xid);
+
+		if (rrq_req->on_active_queue) {
+			list_del_init(&rrq_req->link);
+			rrq_req->on_active_queue = 0;
+			rc = bnx2fc_initiate_cleanup(rrq_req);
+			BUG_ON(rc);
+		}
+	}
+	kfree(cb_arg);
+}
+int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
+{
+
+	struct fc_els_rrq rrq;
+	struct bnx2fc_rport *tgt = aborted_io_req->tgt;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	struct bnx2fc_els_cb_arg *cb_arg = NULL;
+	u32 sid = tgt->sid;
+	u32 r_a_tov = lport->r_a_tov;
+	unsigned long start = jiffies;
+	int rc;
+
+	BNX2FC_ELS_DBG("Sending RRQ orig_xid = 0x%x\n",
+		   aborted_io_req->xid);
+	memset(&rrq, 0, sizeof(rrq));
+
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_NOIO);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for RRQ\n");
+		rc = -ENOMEM;
+		goto rrq_err;
+	}
+
+	cb_arg->aborted_io_req = aborted_io_req;
+
+	rrq.rrq_cmd = ELS_RRQ;
+	hton24(rrq.rrq_s_id, sid);
+	rrq.rrq_ox_id = htons(aborted_io_req->xid);
+	rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
+
+retry_rrq:
+	rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
+				 bnx2fc_rrq_compl, cb_arg,
+				 r_a_tov);
+	if (rc == -ENOMEM) {
+		if (time_after(jiffies, start + (10 * HZ))) {
+			BNX2FC_ELS_DBG("rrq Failed\n");
+			rc = FAILED;
+			goto rrq_err;
+		}
+		msleep(20);
+		goto retry_rrq;
+	}
+rrq_err:
+	if (rc) {
+		BNX2FC_ELS_DBG("RRQ failed - release orig io req 0x%x\n",
+			aborted_io_req->xid);
+		kfree(cb_arg);
+		spin_lock_bh(&tgt->tgt_lock);
+		kref_put(&aborted_io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+	}
+	return rc;
+}
+
+static void bnx2fc_l2_els_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+	struct bnx2fc_cmd *els_req;
+	struct bnx2fc_rport *tgt;
+	struct bnx2fc_mp_req *mp_req;
+	struct fc_frame_header *fc_hdr;
+	unsigned char *buf;
+	void *resp_buf;
+	u32 resp_len, hdr_len;
+	u16 l2_oxid;
+	int frame_len;
+	int rc = 0;
+
+	l2_oxid = cb_arg->l2_oxid;
+	BNX2FC_ELS_DBG("ELS COMPL - l2_oxid = 0x%x\n", l2_oxid);
+
+	els_req = cb_arg->io_req;
+	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &els_req->req_flags)) {
+		/*
+		 * els req is timed out. cleanup the IO with FW and
+		 * drop the completion. libfc will handle the els timeout
+		 */
+		if (els_req->on_active_queue) {
+			list_del_init(&els_req->link);
+			els_req->on_active_queue = 0;
+			rc = bnx2fc_initiate_cleanup(els_req);
+			BUG_ON(rc);
+		}
+		goto free_arg;
+	}
+
+	tgt = els_req->tgt;
+	mp_req = &(els_req->mp_req);
+	fc_hdr = &(mp_req->resp_fc_hdr);
+	resp_len = mp_req->resp_len;
+	resp_buf = mp_req->resp_buf;
+
+	buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+	if (!buf) {
+		printk(KERN_ERR PFX "Unable to alloc mp buf\n");
+		goto free_arg;
+	}
+	hdr_len = sizeof(*fc_hdr);
+	if (hdr_len + resp_len > PAGE_SIZE) {
+		printk(KERN_ERR PFX "l2_els_compl: resp len is "
+				    "beyond page size\n");
+		goto free_buf;
+	}
+	memcpy(buf, fc_hdr, hdr_len);
+	memcpy(buf + hdr_len, resp_buf, resp_len);
+	frame_len = hdr_len + resp_len;
+
+	bnx2fc_process_l2_frame_compl(tgt, buf, frame_len, l2_oxid);
+
+free_buf:
+	kfree(buf);
+free_arg:
+	kfree(cb_arg);
+}
+
+int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp)
+{
+	struct fc_els_adisc *adisc;
+	struct fc_frame_header *fh;
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	u32 r_a_tov = lport->r_a_tov;
+	int rc;
+
+	fh = fc_frame_header_get(fp);
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for ADISC\n");
+		return -ENOMEM;
+	}
+
+	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
+
+	BNX2FC_ELS_DBG("send ADISC: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
+	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
+	/* adisc is initialized by libfc */
+	rc = bnx2fc_initiate_els(tgt, ELS_ADISC, adisc, sizeof(*adisc),
+				 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
+	if (rc)
+		kfree(cb_arg);
+	return rc;
+}
+
+int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp)
+{
+	struct fc_els_logo *logo;
+	struct fc_frame_header *fh;
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	u32 r_a_tov = lport->r_a_tov;
+	int rc;
+
+	fh = fc_frame_header_get(fp);
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
+		return -ENOMEM;
+	}
+
+	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
+
+	BNX2FC_ELS_DBG("Send LOGO: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
+	logo = fc_frame_payload_get(fp, sizeof(*logo));
+	/* logo is initialized by libfc */
+	rc = bnx2fc_initiate_els(tgt, ELS_LOGO, logo, sizeof(*logo),
+				 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
+	if (rc)
+		kfree(cb_arg);
+	return rc;
+}
+
+int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
+{
+	struct fc_els_rls *rls;
+	struct fc_frame_header *fh;
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	u32 r_a_tov = lport->r_a_tov;
+	int rc;
+
+	fh = fc_frame_header_get(fp);
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
+		return -ENOMEM;
+	}
+
+	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
+
+	rls = fc_frame_payload_get(fp, sizeof(*rls));
+	/* rls is initialized by libfc */
+	rc = bnx2fc_initiate_els(tgt, ELS_RLS, rls, sizeof(*rls),
+				  bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
+	if (rc)
+		kfree(cb_arg);
+	return rc;
+}
+
+static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
+			void *data, u32 data_len,
+			void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
+			struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
+{
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct fc_rport *rport = tgt->rport;
+	struct fc_lport *lport = port->lport;
+	struct bnx2fc_cmd *els_req;
+	struct bnx2fc_mp_req *mp_req;
+	struct fc_frame_header *fc_hdr;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	int rc = 0;
+	int task_idx, index;
+	u32 did, sid;
+	u16 xid;
+
+	rc = fc_remote_port_chkready(rport);
+	if (rc) {
+		printk(KERN_ALERT PFX "els 0x%x: rport not ready\n", op);
+		rc = -EINVAL;
+		goto els_err;
+	}
+	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+		printk(KERN_ALERT PFX "els 0x%x: link is not ready\n", op);
+		rc = -EINVAL;
+		goto els_err;
+	}
+	if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
+	     (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
+		printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
+		rc = -EINVAL;
+		goto els_err;
+	}
+	els_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ELS);
+	if (!els_req) {
+		rc = -ENOMEM;
+		goto els_err;
+	}
+
+	els_req->sc_cmd = NULL;
+	els_req->port = port;
+	els_req->tgt = tgt;
+	els_req->cb_func = cb_func;
+	cb_arg->io_req = els_req;
+	els_req->cb_arg = cb_arg;
+
+	mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
+	rc = bnx2fc_init_mp_req(els_req);
+	if (rc == FAILED) {
+		printk(KERN_ALERT PFX "ELS MP request init failed\n");
+		spin_lock_bh(&tgt->tgt_lock);
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		rc = -ENOMEM;
+		goto els_err;
+	} else {
+		/* rc SUCCESS */
+		rc = 0;
+	}
+
+	/* Set the data_xfer_len to the size of ELS payload */
+	mp_req->req_len = data_len;
+	els_req->data_xfer_len = mp_req->req_len;
+
+	/* Fill ELS Payload */
+	if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
+		memcpy(mp_req->req_buf, data, data_len);
+	} else {
+		printk(KERN_ALERT PFX "Invalid ELS op 0x%x\n", op);
+		els_req->cb_func = NULL;
+		els_req->cb_arg = NULL;
+		spin_lock_bh(&tgt->tgt_lock);
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		rc = -EINVAL;
+	}
+
+	if (rc)
+		goto els_err;
+
+	/* Fill FC header */
+	fc_hdr = &(mp_req->req_fc_hdr);
+
+	did = tgt->rport->port_id;
+	sid = tgt->sid;
+
+	__fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
+			   FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+			   FC_FC_SEQ_INIT, 0);
+
+	/* Obtain exchange id */
+	xid = els_req->xid;
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_mp_task(els_req, task);
+
+	spin_lock_bh(&tgt->tgt_lock);
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		printk(KERN_ERR PFX "initiate_els.. session not ready\n");
+		els_req->cb_func = NULL;
+		els_req->cb_arg = NULL;
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return -EINVAL;
+	}
+
+	if (timer_msec)
+		bnx2fc_cmd_timer_set(els_req, timer_msec);
+	bnx2fc_add_2_sq(tgt, xid);
+
+	els_req->on_active_queue = 1;
+	list_add_tail(&els_req->link, &tgt->els_queue);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+	spin_unlock_bh(&tgt->tgt_lock);
+
+els_err:
+	return rc;
+}
+
+void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
+			      struct fcoe_task_ctx_entry *task, u8 num_rq)
+{
+	struct bnx2fc_mp_req *mp_req;
+	struct fc_frame_header *fc_hdr;
+	u64 *hdr;
+	u64 *temp_hdr;
+
+	BNX2FC_ELS_DBG("Entered process_els_compl xid = 0x%x"
+			"cmd_type = %d\n", els_req->xid, els_req->cmd_type);
+
+	if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
+			     &els_req->req_flags)) {
+		BNX2FC_ELS_DBG("Timer context finished processing this "
+			   "els - 0x%x\n", els_req->xid);
+		/* This IO doesnt receive cleanup completion */
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		return;
+	}
+
+	/* Cancel the timeout_work, as we received the response */
+	if (cancel_delayed_work(&els_req->timeout_work))
+		kref_put(&els_req->refcount,
+			 bnx2fc_cmd_release); /* drop timer hold */
+
+	if (els_req->on_active_queue) {
+		list_del_init(&els_req->link);
+		els_req->on_active_queue = 0;
+	}
+
+	mp_req = &(els_req->mp_req);
+	fc_hdr = &(mp_req->resp_fc_hdr);
+
+	hdr = (u64 *)fc_hdr;
+	temp_hdr = (u64 *)
+		&task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	hdr[0] = cpu_to_be64(temp_hdr[0]);
+	hdr[1] = cpu_to_be64(temp_hdr[1]);
+	hdr[2] = cpu_to_be64(temp_hdr[2]);
+
+	mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+
+	/* Parse ELS response */
+	if ((els_req->cb_func) && (els_req->cb_arg)) {
+		els_req->cb_func(els_req->cb_arg);
+		els_req->cb_arg = NULL;
+	}
+
+	kref_put(&els_req->refcount, bnx2fc_cmd_release);
+}
+
+static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
+			      void *arg)
+{
+	struct fcoe_ctlr *fip = arg;
+	struct fc_exch *exch = fc_seq_exch(seq);
+	struct fc_lport *lport = exch->lp;
+	u8 *mac;
+	struct fc_frame_header *fh;
+	u8 op;
+
+	if (IS_ERR(fp))
+		goto done;
+
+	mac = fr_cb(fp)->granted_mac;
+	if (is_zero_ether_addr(mac)) {
+		fh = fc_frame_header_get(fp);
+		if (fh->fh_type != FC_TYPE_ELS) {
+			printk(KERN_ERR PFX "bnx2fc_flogi_resp:"
+				"fh_type != FC_TYPE_ELS\n");
+			fc_frame_free(fp);
+			return;
+		}
+		op = fc_frame_payload_op(fp);
+		if (lport->vport) {
+			if (op == ELS_LS_RJT) {
+				printk(KERN_ERR PFX "bnx2fc_flogi_resp is LS_RJT\n");
+				fc_vport_terminate(lport->vport);
+				fc_frame_free(fp);
+				return;
+			}
+		}
+		if (fcoe_ctlr_recv_flogi(fip, lport, fp)) {
+			fc_frame_free(fp);
+			return;
+		}
+	}
+	fip->update_mac(lport, mac);
+done:
+	fc_lport_flogi_resp(seq, fp, lport);
+}
+
+static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
+			     void *arg)
+{
+	struct fcoe_ctlr *fip = arg;
+	struct fc_exch *exch = fc_seq_exch(seq);
+	struct fc_lport *lport = exch->lp;
+	static u8 zero_mac[ETH_ALEN] = { 0 };
+
+	if (!IS_ERR(fp))
+		fip->update_mac(lport, zero_mac);
+	fc_lport_logo_resp(seq, fp, lport);
+}
+
+struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
+				      struct fc_frame *fp, unsigned int op,
+				      void (*resp)(struct fc_seq *,
+						   struct fc_frame *,
+						   void *),
+				      void *arg, u32 timeout)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_ctlr *fip = &hba->ctlr;
+	struct fc_frame_header *fh = fc_frame_header_get(fp);
+
+	switch (op) {
+	case ELS_FLOGI:
+	case ELS_FDISC:
+		return fc_elsct_send(lport, did, fp, op, bnx2fc_flogi_resp,
+				     fip, timeout);
+	case ELS_LOGO:
+		/* only hook onto fabric logouts, not port logouts */
+		if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
+			break;
+		return fc_elsct_send(lport, did, fp, op, bnx2fc_logo_resp,
+				     fip, timeout);
+	}
+	return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
+}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
new file mode 100644
index 0000000..e476e87
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -0,0 +1,2535 @@
+/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * This file contains the code that interacts with libfc, libfcoe,
+ * cnic modules to create FCoE instances, send/receive non-offloaded
+ * FIP/FCoE packets, listen to link events etc.
+ *
+ * Copyright (c) 2008 - 2010 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+static struct list_head adapter_list;
+static u32 adapter_count;
+static DEFINE_MUTEX(bnx2fc_dev_lock);
+DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
+
+#define DRV_MODULE_NAME		"bnx2fc"
+#define DRV_MODULE_VERSION	BNX2FC_VERSION
+#define DRV_MODULE_RELDATE	"Jan 25, 2011"
+
+
+static char version[] __devinitdata =
+		"Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+		" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+
+MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define BNX2FC_MAX_QUEUE_DEPTH	256
+#define BNX2FC_MIN_QUEUE_DEPTH	32
+#define FCOE_WORD_TO_BYTE  4
+
+static struct scsi_transport_template	*bnx2fc_transport_template;
+static struct scsi_transport_template	*bnx2fc_vport_xport_template;
+
+struct workqueue_struct *bnx2fc_wq;
+
+/* bnx2fc structure needs only one instance of the fcoe_percpu_s structure.
+ * Here the io threads are per cpu but the l2 thread is just one
+ */
+struct fcoe_percpu_s bnx2fc_global;
+DEFINE_SPINLOCK(bnx2fc_global_lock);
+
+static struct cnic_ulp_ops bnx2fc_cnic_cb;
+static struct libfc_function_template bnx2fc_libfc_fcn_templ;
+static struct scsi_host_template bnx2fc_shost_template;
+static struct fc_function_template bnx2fc_transport_function;
+static struct fc_function_template bnx2fc_vport_xport_function;
+static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
+static int bnx2fc_destroy(struct net_device *net_device);
+static int bnx2fc_enable(struct net_device *netdev);
+static int bnx2fc_disable(struct net_device *netdev);
+
+static void bnx2fc_recv_frame(struct sk_buff *skb);
+
+static void bnx2fc_start_disc(struct bnx2fc_hba *hba);
+static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
+static int bnx2fc_net_config(struct fc_lport *lp);
+static int bnx2fc_lport_config(struct fc_lport *lport);
+static int bnx2fc_em_config(struct fc_lport *lport);
+static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
+static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba);
+static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba);
+static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+				  struct device *parent, int npiv);
+static void bnx2fc_destroy_work(struct work_struct *work);
+
+static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
+static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);
+
+static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
+static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba);
+
+static void bnx2fc_port_shutdown(struct fc_lport *lport);
+static void bnx2fc_stop(struct bnx2fc_hba *hba);
+static int __init bnx2fc_mod_init(void);
+static void __exit bnx2fc_mod_exit(void);
+
+unsigned int bnx2fc_debug_level;
+module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
+
+static int bnx2fc_cpu_callback(struct notifier_block *nfb,
+			     unsigned long action, void *hcpu);
+/* notification function for CPU hotplug events */
+static struct notifier_block bnx2fc_cpu_notifier = {
+	.notifier_call = bnx2fc_cpu_callback,
+};
+
+static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
+{
+	struct fcoe_percpu_s *bg;
+	struct fcoe_rcv_info *fr;
+	struct sk_buff_head *list;
+	struct sk_buff *skb, *next;
+	struct sk_buff *head;
+
+	bg = &bnx2fc_global;
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+	list = &bg->fcoe_rx_list;
+	head = list->next;
+	for (skb = head; skb != (struct sk_buff *)list;
+	     skb = next) {
+		next = skb->next;
+		fr = fcoe_dev_from_skb(skb);
+		if (fr->fr_dev == lp) {
+			__skb_unlink(skb, list);
+			kfree_skb(skb);
+		}
+	}
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+}
+
+int bnx2fc_get_paged_crc_eof(struct sk_buff *skb, int tlen)
+{
+	int rc;
+	spin_lock(&bnx2fc_global_lock);
+	rc = fcoe_get_paged_crc_eof(skb, tlen, &bnx2fc_global);
+	spin_unlock(&bnx2fc_global_lock);
+
+	return rc;
+}
+
+static void bnx2fc_abort_io(struct fc_lport *lport)
+{
+	/*
+	 * This function is no-op for bnx2fc, but we do
+	 * not want to leave it as NULL either, as libfc
+	 * can call the default function which is
+	 * fc_fcp_abort_io.
+	 */
+}
+
+static void bnx2fc_cleanup(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_rport *tgt;
+	int i;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	mutex_lock(&hba->hba_mutex);
+	spin_lock_bh(&hba->hba_lock);
+	for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
+		tgt = hba->tgt_ofld_list[i];
+		if (tgt) {
+			/* Cleanup IOs belonging to requested vport */
+			if (tgt->port == port) {
+				spin_unlock_bh(&hba->hba_lock);
+				BNX2FC_TGT_DBG(tgt, "flush/cleanup\n");
+				bnx2fc_flush_active_ios(tgt);
+				spin_lock_bh(&hba->hba_lock);
+			}
+		}
+	}
+	spin_unlock_bh(&hba->hba_lock);
+	mutex_unlock(&hba->hba_mutex);
+}
+
+static int bnx2fc_xmit_l2_frame(struct bnx2fc_rport *tgt,
+			     struct fc_frame *fp)
+{
+	struct fc_rport_priv *rdata = tgt->rdata;
+	struct fc_frame_header *fh;
+	int rc = 0;
+
+	fh = fc_frame_header_get(fp);
+	BNX2FC_TGT_DBG(tgt, "Xmit L2 frame rport = 0x%x, oxid = 0x%x, "
+			"r_ctl = 0x%x\n", rdata->ids.port_id,
+			ntohs(fh->fh_ox_id), fh->fh_r_ctl);
+	if ((fh->fh_type == FC_TYPE_ELS) &&
+	    (fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
+
+		switch (fc_frame_payload_op(fp)) {
+		case ELS_ADISC:
+			rc = bnx2fc_send_adisc(tgt, fp);
+			break;
+		case ELS_LOGO:
+			rc = bnx2fc_send_logo(tgt, fp);
+			break;
+		case ELS_RLS:
+			rc = bnx2fc_send_rls(tgt, fp);
+			break;
+		default:
+			break;
+		}
+	} else if ((fh->fh_type ==  FC_TYPE_BLS) &&
+	    (fh->fh_r_ctl == FC_RCTL_BA_ABTS))
+		BNX2FC_TGT_DBG(tgt, "ABTS frame\n");
+	else {
+		BNX2FC_TGT_DBG(tgt, "Send L2 frame type 0x%x "
+				"rctl 0x%x thru non-offload path\n",
+				fh->fh_type, fh->fh_r_ctl);
+		return -ENODEV;
+	}
+	if (rc)
+		return -ENOMEM;
+	else
+		return 0;
+}
+
+/**
+ * bnx2fc_xmit - bnx2fc's FCoE frame transmit function
+ *
+ * @lport:	the associated local port
+ * @fp:	the fc_frame to be transmitted
+ */
+static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
+{
+	struct ethhdr		*eh;
+	struct fcoe_crc_eof	*cp;
+	struct sk_buff		*skb;
+	struct fc_frame_header	*fh;
+	struct bnx2fc_hba	*hba;
+	struct fcoe_port	*port;
+	struct fcoe_hdr		*hp;
+	struct bnx2fc_rport	*tgt;
+	struct fcoe_dev_stats	*stats;
+	u8			sof, eof;
+	u32			crc;
+	unsigned int		hlen, tlen, elen;
+	int			wlen, rc = 0;
+
+	port = (struct fcoe_port *)lport_priv(lport);
+	hba = port->priv;
+
+	fh = fc_frame_header_get(fp);
+
+	skb = fp_skb(fp);
+	if (!lport->link_up) {
+		BNX2FC_HBA_DBG(lport, "bnx2fc_xmit link down\n");
+		kfree_skb(skb);
+		return 0;
+	}
+
+	if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
+		if (!hba->ctlr.sel_fcf) {
+			BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n");
+			kfree_skb(skb);
+			return -EINVAL;
+		}
+		if (fcoe_ctlr_els_send(&hba->ctlr, lport, skb))
+			return 0;
+	}
+
+	sof = fr_sof(fp);
+	eof = fr_eof(fp);
+
+	/*
+	 * Snoop the frame header to check if the frame is for
+	 * an offloaded session
+	 */
+	/*
+	 * tgt_ofld_list access is synchronized using
+	 * both hba mutex and hba lock. Atleast hba mutex or
+	 * hba lock needs to be held for read access.
+	 */
+
+	spin_lock_bh(&hba->hba_lock);
+	tgt = bnx2fc_tgt_lookup(port, ntoh24(fh->fh_d_id));
+	if (tgt && (test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
+		/* This frame is for offloaded session */
+		BNX2FC_HBA_DBG(lport, "xmit: Frame is for offloaded session "
+				"port_id = 0x%x\n", ntoh24(fh->fh_d_id));
+		spin_unlock_bh(&hba->hba_lock);
+		rc = bnx2fc_xmit_l2_frame(tgt, fp);
+		if (rc != -ENODEV) {
+			kfree_skb(skb);
+			return rc;
+		}
+	} else {
+		spin_unlock_bh(&hba->hba_lock);
+	}
+
+	elen = sizeof(struct ethhdr);
+	hlen = sizeof(struct fcoe_hdr);
+	tlen = sizeof(struct fcoe_crc_eof);
+	wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
+
+	skb->ip_summed = CHECKSUM_NONE;
+	crc = fcoe_fc_crc(fp);
+
+	/* copy port crc and eof to the skb buff */
+	if (skb_is_nonlinear(skb)) {
+		skb_frag_t *frag;
+		if (bnx2fc_get_paged_crc_eof(skb, tlen)) {
+			kfree_skb(skb);
+			return -ENOMEM;
+		}
+		frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
+		cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+				+ frag->page_offset;
+	} else {
+		cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
+	}
+
+	memset(cp, 0, sizeof(*cp));
+	cp->fcoe_eof = eof;
+	cp->fcoe_crc32 = cpu_to_le32(~crc);
+	if (skb_is_nonlinear(skb)) {
+		kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
+		cp = NULL;
+	}
+
+	/* adjust skb network/transport offsets to match mac/fcoe/port */
+	skb_push(skb, elen + hlen);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb->mac_len = elen;
+	skb->protocol = htons(ETH_P_FCOE);
+	skb->dev = hba->netdev;
+
+	/* fill up mac and fcoe headers */
+	eh = eth_hdr(skb);
+	eh->h_proto = htons(ETH_P_FCOE);
+	if (hba->ctlr.map_dest)
+		fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
+	else
+		/* insert GW address */
+		memcpy(eh->h_dest, hba->ctlr.dest_addr, ETH_ALEN);
+
+	if (unlikely(hba->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+		memcpy(eh->h_source, hba->ctlr.ctl_src_addr, ETH_ALEN);
+	else
+		memcpy(eh->h_source, port->data_src_addr, ETH_ALEN);
+
+	hp = (struct fcoe_hdr *)(eh + 1);
+	memset(hp, 0, sizeof(*hp));
+	if (FC_FCOE_VER)
+		FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
+	hp->fcoe_sof = sof;
+
+	/* fcoe lso, mss is in max_payload which is non-zero for FCP data */
+	if (lport->seq_offload && fr_max_payload(fp)) {
+		skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
+		skb_shinfo(skb)->gso_size = fr_max_payload(fp);
+	} else {
+		skb_shinfo(skb)->gso_type = 0;
+		skb_shinfo(skb)->gso_size = 0;
+	}
+
+	/*update tx stats */
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->TxFrames++;
+	stats->TxWords += wlen;
+	put_cpu();
+
+	/* send down to lld */
+	fr_dev(fp) = lport;
+	if (port->fcoe_pending_queue.qlen)
+		fcoe_check_wait_queue(lport, skb);
+	else if (fcoe_start_io(skb))
+		fcoe_check_wait_queue(lport, skb);
+
+	return 0;
+}
+
+/**
+ * bnx2fc_rcv - This is bnx2fc's receive function called by NET_RX_SOFTIRQ
+ *
+ * @skb:	the receive socket buffer
+ * @dev:	associated net device
+ * @ptype:	context
+ * @olddev:	last device
+ *
+ * This function receives the packet and builds FC frame and passes it up
+ */
+static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
+		struct packet_type *ptype, struct net_device *olddev)
+{
+	struct fc_lport *lport;
+	struct bnx2fc_hba *hba;
+	struct fc_frame_header *fh;
+	struct fcoe_rcv_info *fr;
+	struct fcoe_percpu_s *bg;
+	unsigned short oxid;
+
+	hba = container_of(ptype, struct bnx2fc_hba, fcoe_packet_type);
+	lport = hba->ctlr.lp;
+
+	if (unlikely(lport == NULL)) {
+		printk(KERN_ALERT PFX "bnx2fc_rcv: lport is NULL\n");
+		goto err;
+	}
+
+	if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
+		printk(KERN_ALERT PFX "bnx2fc_rcv: Wrong FC type frame\n");
+		goto err;
+	}
+
+	/*
+	 * Check for minimum frame length, and make sure required FCoE
+	 * and FC headers are pulled into the linear data area.
+	 */
+	if (unlikely((skb->len < FCOE_MIN_FRAME) ||
+	    !pskb_may_pull(skb, FCOE_HEADER_LEN)))
+		goto err;
+
+	skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
+	fh = (struct fc_frame_header *) skb_transport_header(skb);
+
+	oxid = ntohs(fh->fh_ox_id);
+
+	fr = fcoe_dev_from_skb(skb);
+	fr->fr_dev = lport;
+	fr->ptype = ptype;
+
+	bg = &bnx2fc_global;
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+
+	__skb_queue_tail(&bg->fcoe_rx_list, skb);
+	if (bg->fcoe_rx_list.qlen == 1)
+		wake_up_process(bg->thread);
+
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+
+	return 0;
+err:
+	kfree_skb(skb);
+	return -1;
+}
+
+static int bnx2fc_l2_rcv_thread(void *arg)
+{
+	struct fcoe_percpu_s *bg = arg;
+	struct sk_buff *skb;
+
+	set_user_nice(current, -20);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (!kthread_should_stop()) {
+		schedule();
+		set_current_state(TASK_RUNNING);
+		spin_lock_bh(&bg->fcoe_rx_list.lock);
+		while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL) {
+			spin_unlock_bh(&bg->fcoe_rx_list.lock);
+			bnx2fc_recv_frame(skb);
+			spin_lock_bh(&bg->fcoe_rx_list.lock);
+		}
+		spin_unlock_bh(&bg->fcoe_rx_list.lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+	set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+
+static void bnx2fc_recv_frame(struct sk_buff *skb)
+{
+	u32 fr_len;
+	struct fc_lport *lport;
+	struct fcoe_rcv_info *fr;
+	struct fcoe_dev_stats *stats;
+	struct fc_frame_header *fh;
+	struct fcoe_crc_eof crc_eof;
+	struct fc_frame *fp;
+	struct fc_lport *vn_port;
+	struct fcoe_port *port;
+	u8 *mac = NULL;
+	u8 *dest_mac = NULL;
+	struct fcoe_hdr *hp;
+
+	fr = fcoe_dev_from_skb(skb);
+	lport = fr->fr_dev;
+	if (unlikely(lport == NULL)) {
+		printk(KERN_ALERT PFX "Invalid lport struct\n");
+		kfree_skb(skb);
+		return;
+	}
+
+	if (skb_is_nonlinear(skb))
+		skb_linearize(skb);
+	mac = eth_hdr(skb)->h_source;
+	dest_mac = eth_hdr(skb)->h_dest;
+
+	/* Pull the header */
+	hp = (struct fcoe_hdr *) skb_network_header(skb);
+	fh = (struct fc_frame_header *) skb_transport_header(skb);
+	skb_pull(skb, sizeof(struct fcoe_hdr));
+	fr_len = skb->len - sizeof(struct fcoe_crc_eof);
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->RxFrames++;
+	stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+
+	fp = (struct fc_frame *)skb;
+	fc_frame_init(fp);
+	fr_dev(fp) = lport;
+	fr_sof(fp) = hp->fcoe_sof;
+	if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+	fr_eof(fp) = crc_eof.fcoe_eof;
+	fr_crc(fp) = crc_eof.fcoe_crc32;
+	if (pskb_trim(skb, fr_len)) {
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+
+	fh = fc_frame_header_get(fp);
+
+	vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
+	if (vn_port) {
+		port = lport_priv(vn_port);
+		if (compare_ether_addr(port->data_src_addr, dest_mac)
+		    != 0) {
+			BNX2FC_HBA_DBG(lport, "fpma mismatch\n");
+			put_cpu();
+			kfree_skb(skb);
+			return;
+		}
+	}
+	if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
+	    fh->fh_type == FC_TYPE_FCP) {
+		/* Drop FCP data. We dont this in L2 path */
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+	if (fh->fh_r_ctl == FC_RCTL_ELS_REQ &&
+	    fh->fh_type == FC_TYPE_ELS) {
+		switch (fc_frame_payload_op(fp)) {
+		case ELS_LOGO:
+			if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) {
+				/* drop non-FIP LOGO */
+				put_cpu();
+				kfree_skb(skb);
+				return;
+			}
+			break;
+		}
+	}
+	if (le32_to_cpu(fr_crc(fp)) !=
+			~crc32(~0, skb->data, fr_len)) {
+		if (stats->InvalidCRCCount < 5)
+			printk(KERN_WARNING PFX "dropping frame with "
+			       "CRC error\n");
+		stats->InvalidCRCCount++;
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+	put_cpu();
+	fc_exch_recv(lport, fp);
+}
+
+/**
+ * bnx2fc_percpu_io_thread - thread per cpu for ios
+ *
+ * @arg:	ptr to bnx2fc_percpu_info structure
+ */
+int bnx2fc_percpu_io_thread(void *arg)
+{
+	struct bnx2fc_percpu_s *p = arg;
+	struct bnx2fc_work *work, *tmp;
+	LIST_HEAD(work_list);
+
+	set_user_nice(current, -20);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (!kthread_should_stop()) {
+		schedule();
+		set_current_state(TASK_RUNNING);
+		spin_lock_bh(&p->fp_work_lock);
+		while (!list_empty(&p->work_list)) {
+			list_splice_init(&p->work_list, &work_list);
+			spin_unlock_bh(&p->fp_work_lock);
+
+			list_for_each_entry_safe(work, tmp, &work_list, list) {
+				list_del_init(&work->list);
+				bnx2fc_process_cq_compl(work->tgt, work->wqe);
+				kfree(work);
+			}
+
+			spin_lock_bh(&p->fp_work_lock);
+		}
+		spin_unlock_bh(&p->fp_work_lock);
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+	set_current_state(TASK_RUNNING);
+
+	return 0;
+}
+
+static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
+{
+	struct fc_host_statistics *bnx2fc_stats;
+	struct fc_lport *lport = shost_priv(shost);
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_statistics_params *fw_stats;
+	int rc = 0;
+
+	fw_stats = (struct fcoe_statistics_params *)hba->stats_buffer;
+	if (!fw_stats)
+		return NULL;
+
+	bnx2fc_stats = fc_get_host_stats(shost);
+
+	init_completion(&hba->stat_req_done);
+	if (bnx2fc_send_stat_req(hba))
+		return bnx2fc_stats;
+	rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ));
+	if (!rc) {
+		BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
+		return bnx2fc_stats;
+	}
+	bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat1.fc_crc_cnt;
+	bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
+	bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
+	bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
+	bnx2fc_stats->rx_words += (fw_stats->rx_stat0.fcoe_rx_byte_cnt) / 4;
+
+	bnx2fc_stats->dumped_frames = 0;
+	bnx2fc_stats->lip_count = 0;
+	bnx2fc_stats->nos_count = 0;
+	bnx2fc_stats->loss_of_sync_count = 0;
+	bnx2fc_stats->loss_of_signal_count = 0;
+	bnx2fc_stats->prim_seq_protocol_err_count = 0;
+
+	return bnx2fc_stats;
+}
+
+static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct Scsi_Host *shost = lport->host;
+	int rc = 0;
+
+	shost->max_cmd_len = BNX2FC_MAX_CMD_LEN;
+	shost->max_lun = BNX2FC_MAX_LUN;
+	shost->max_id = BNX2FC_MAX_FCP_TGT;
+	shost->max_channel = 0;
+	if (lport->vport)
+		shost->transportt = bnx2fc_vport_xport_template;
+	else
+		shost->transportt = bnx2fc_transport_template;
+
+	/* Add the new host to SCSI-ml */
+	rc = scsi_add_host(lport->host, dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Error on scsi_add_host\n");
+		return rc;
+	}
+	if (!lport->vport)
+		fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
+	sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s",
+		BNX2FC_NAME, BNX2FC_VERSION,
+		hba->netdev->name);
+
+	return 0;
+}
+
+static int  bnx2fc_mfs_update(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *netdev = hba->netdev;
+	u32 mfs;
+	u32 max_mfs;
+
+	mfs = netdev->mtu - (sizeof(struct fcoe_hdr) +
+			     sizeof(struct fcoe_crc_eof));
+	max_mfs = BNX2FC_MAX_PAYLOAD + sizeof(struct fc_frame_header);
+	BNX2FC_HBA_DBG(lport, "mfs = %d, max_mfs = %d\n", mfs, max_mfs);
+	if (mfs > max_mfs)
+		mfs = max_mfs;
+
+	/* Adjust mfs to be a multiple of 256 bytes */
+	mfs = (((mfs - sizeof(struct fc_frame_header)) / BNX2FC_MIN_PAYLOAD) *
+			BNX2FC_MIN_PAYLOAD);
+	mfs = mfs + sizeof(struct fc_frame_header);
+
+	BNX2FC_HBA_DBG(lport, "Set MFS = %d\n", mfs);
+	if (fc_set_mfs(lport, mfs))
+		return -EINVAL;
+	return 0;
+}
+static void bnx2fc_link_speed_update(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *netdev = hba->netdev;
+	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+
+	if (!dev_ethtool_get_settings(netdev, &ecmd)) {
+		lport->link_supported_speeds &=
+			~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+		if (ecmd.supported & (SUPPORTED_1000baseT_Half |
+				      SUPPORTED_1000baseT_Full))
+			lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
+		if (ecmd.supported & SUPPORTED_10000baseT_Full)
+			lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
+
+		if (ecmd.speed == SPEED_1000)
+			lport->link_speed = FC_PORTSPEED_1GBIT;
+		if (ecmd.speed == SPEED_10000)
+			lport->link_speed = FC_PORTSPEED_10GBIT;
+	}
+	return;
+}
+static int bnx2fc_link_ok(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *dev = hba->phys_dev;
+	int rc = 0;
+
+	if ((dev->flags & IFF_UP) && netif_carrier_ok(dev))
+		clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+	else {
+		set_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+		rc = -1;
+	}
+	return rc;
+}
+
+/**
+ * bnx2fc_get_link_state - get network link state
+ *
+ * @hba:	adapter instance pointer
+ *
+ * updates adapter structure flag based on netdev state
+ */
+void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
+{
+	if (test_bit(__LINK_STATE_NOCARRIER, &hba->netdev->state))
+		set_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+	else
+		clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+}
+
+static int bnx2fc_net_config(struct fc_lport *lport)
+{
+	struct bnx2fc_hba *hba;
+	struct fcoe_port *port;
+	u64 wwnn, wwpn;
+
+	port = lport_priv(lport);
+	hba = port->priv;
+
+	/* require support for get_pauseparam ethtool op. */
+	if (!hba->phys_dev->ethtool_ops ||
+	    !hba->phys_dev->ethtool_ops->get_pauseparam)
+		return -EOPNOTSUPP;
+
+	if (bnx2fc_mfs_update(lport))
+		return -EINVAL;
+
+	skb_queue_head_init(&port->fcoe_pending_queue);
+	port->fcoe_pending_queue_active = 0;
+	setup_timer(&port->timer, fcoe_queue_timer, (unsigned long) lport);
+
+	bnx2fc_link_speed_update(lport);
+
+	if (!lport->vport) {
+		wwnn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 1, 0);
+		BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn);
+		fc_set_wwnn(lport, wwnn);
+
+		wwpn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 2, 0);
+		BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn);
+		fc_set_wwpn(lport, wwpn);
+	}
+
+	return 0;
+}
+
+static void bnx2fc_destroy_timer(unsigned long data)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)data;
+
+	BNX2FC_HBA_DBG(hba->ctlr.lp, "ERROR:bnx2fc_destroy_timer - "
+		   "Destroy compl not received!!\n");
+	hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+	wake_up_interruptible(&hba->destroy_wait);
+}
+
+/**
+ * bnx2fc_indicate_netevent - Generic netdev event handler
+ *
+ * @context:	adapter structure pointer
+ * @event:	event type
+ *
+ * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
+ * NETDEV_CHANGE_MTU events
+ */
+static void bnx2fc_indicate_netevent(void *context, unsigned long event)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
+	struct fc_lport *lport = hba->ctlr.lp;
+	struct fc_lport *vport;
+	u32 link_possible = 1;
+
+	if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		BNX2FC_MISC_DBG("driver not ready. event=%s %ld\n",
+			   hba->netdev->name, event);
+		return;
+	}
+
+	/*
+	 * ASSUMPTION:
+	 * indicate_netevent cannot be called from cnic unless bnx2fc
+	 * does register_device
+	 */
+	BUG_ON(!lport);
+
+	BNX2FC_HBA_DBG(lport, "enter netevent handler - event=%s %ld\n",
+				hba->netdev->name, event);
+
+	switch (event) {
+	case NETDEV_UP:
+		BNX2FC_HBA_DBG(lport, "Port up, adapter_state = %ld\n",
+			hba->adapter_state);
+		if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
+			printk(KERN_ERR "indicate_netevent: "\
+					"adapter is not UP!!\n");
+		/* fall thru to update mfs if MTU has changed */
+	case NETDEV_CHANGEMTU:
+		BNX2FC_HBA_DBG(lport, "NETDEV_CHANGEMTU event\n");
+		bnx2fc_mfs_update(lport);
+		mutex_lock(&lport->lp_mutex);
+		list_for_each_entry(vport, &lport->vports, list)
+			bnx2fc_mfs_update(vport);
+		mutex_unlock(&lport->lp_mutex);
+		break;
+
+	case NETDEV_DOWN:
+		BNX2FC_HBA_DBG(lport, "Port down\n");
+		clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+		clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+		link_possible = 0;
+		break;
+
+	case NETDEV_GOING_DOWN:
+		BNX2FC_HBA_DBG(lport, "Port going down\n");
+		set_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+		link_possible = 0;
+		break;
+
+	case NETDEV_CHANGE:
+		BNX2FC_HBA_DBG(lport, "NETDEV_CHANGE\n");
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unkonwn netevent %ld", event);
+		return;
+	}
+
+	bnx2fc_link_speed_update(lport);
+
+	if (link_possible && !bnx2fc_link_ok(lport)) {
+		printk(KERN_ERR "indicate_netevent: call ctlr_link_up\n");
+		fcoe_ctlr_link_up(&hba->ctlr);
+	} else {
+		printk(KERN_ERR "indicate_netevent: call ctlr_link_down\n");
+		if (fcoe_ctlr_link_down(&hba->ctlr)) {
+			clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+			mutex_lock(&lport->lp_mutex);
+			list_for_each_entry(vport, &lport->vports, list)
+				fc_host_port_type(vport->host) =
+							FC_PORTTYPE_UNKNOWN;
+			mutex_unlock(&lport->lp_mutex);
+			fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+			per_cpu_ptr(lport->dev_stats,
+				    get_cpu())->LinkFailureCount++;
+			put_cpu();
+			fcoe_clean_pending_queue(lport);
+
+			init_waitqueue_head(&hba->shutdown_wait);
+			BNX2FC_HBA_DBG(lport, "indicate_netevent "
+					     "num_ofld_sess = %d\n",
+				   hba->num_ofld_sess);
+			hba->wait_for_link_down = 1;
+			BNX2FC_HBA_DBG(lport, "waiting for uploads to "
+					     "compl proc = %s\n",
+				   current->comm);
+			wait_event_interruptible(hba->shutdown_wait,
+						 (hba->num_ofld_sess == 0));
+			BNX2FC_HBA_DBG(lport, "wakeup - num_ofld_sess = %d\n",
+				hba->num_ofld_sess);
+			hba->wait_for_link_down = 0;
+
+			if (signal_pending(current))
+				flush_signals(current);
+		}
+	}
+}
+
+static int bnx2fc_libfc_config(struct fc_lport *lport)
+{
+
+	/* Set the function pointers set by bnx2fc driver */
+	memcpy(&lport->tt, &bnx2fc_libfc_fcn_templ,
+		sizeof(struct libfc_function_template));
+	fc_elsct_init(lport);
+	fc_exch_init(lport);
+	fc_rport_init(lport);
+	fc_disc_init(lport);
+	return 0;
+}
+
+static int bnx2fc_em_config(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+
+	if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, FCOE_MIN_XID,
+				FCOE_MAX_XID, NULL)) {
+		printk(KERN_ERR PFX "em_config:fc_exch_mgr_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
+					    BNX2FC_MAX_XID);
+
+	if (!hba->cmd_mgr) {
+		printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
+		fc_exch_mgr_free(lport);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int bnx2fc_lport_config(struct fc_lport *lport)
+{
+	lport->link_up = 0;
+	lport->qfull = 0;
+	lport->max_retry_count = 3;
+	lport->max_rport_retry_count = 3;
+	lport->e_d_tov = 2 * 1000;
+	lport->r_a_tov = 10 * 1000;
+
+	/* REVISIT: enable when supporting tape devices
+	lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
+				FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
+	*/
+	lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS);
+	lport->does_npiv = 1;
+
+	memset(&lport->rnid_gen, 0, sizeof(struct fc_els_rnid_gen));
+	lport->rnid_gen.rnid_atype = BNX2FC_RNID_HBA;
+
+	/* alloc stats structure */
+	if (fc_lport_init_stats(lport))
+		return -ENOMEM;
+
+	/* Finish fc_lport configuration */
+	fc_lport_config(lport);
+
+	return 0;
+}
+
+/**
+ * bnx2fc_fip_recv - handle a received FIP frame.
+ *
+ * @skb: the received skb
+ * @dev: associated &net_device
+ * @ptype: the &packet_type structure which was used to register this handler.
+ * @orig_dev: original receive &net_device, in case @ dev is a bond.
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev,
+			   struct packet_type *ptype,
+			   struct net_device *orig_dev)
+{
+	struct bnx2fc_hba *hba;
+	hba = container_of(ptype, struct bnx2fc_hba, fip_packet_type);
+	fcoe_ctlr_recv(&hba->ctlr, skb);
+	return 0;
+}
+
+/**
+ * bnx2fc_update_src_mac - Update Ethernet MAC filters.
+ *
+ * @fip: FCoE controller.
+ * @old: Unicast MAC address to delete if the MAC is non-zero.
+ * @new: Unicast MAC address to add.
+ *
+ * Remove any previously-set unicast MAC filter.
+ * Add secondary FCoE MAC address filter for our OUI.
+ */
+static void bnx2fc_update_src_mac(struct fc_lport *lport, u8 *addr)
+{
+	struct fcoe_port *port = lport_priv(lport);
+
+	memcpy(port->data_src_addr, addr, ETH_ALEN);
+}
+
+/**
+ * bnx2fc_get_src_mac - return the ethernet source address for an lport
+ *
+ * @lport: libfc port
+ */
+static u8 *bnx2fc_get_src_mac(struct fc_lport *lport)
+{
+	struct fcoe_port *port;
+
+	port = (struct fcoe_port *)lport_priv(lport);
+	return port->data_src_addr;
+}
+
+/**
+ * bnx2fc_fip_send - send an Ethernet-encapsulated FIP frame.
+ *
+ * @fip: FCoE controller.
+ * @skb: FIP Packet.
+ */
+static void bnx2fc_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	skb->dev = bnx2fc_from_ctlr(fip)->netdev;
+	dev_queue_xmit(skb);
+}
+
+static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
+{
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_lport *n_port = shost_priv(shost);
+	struct fcoe_port *port = lport_priv(n_port);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *netdev = hba->netdev;
+	struct fc_lport *vn_port;
+
+	if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "vn ports cannot be created on"
+			"this hba\n");
+		return -EIO;
+	}
+	mutex_lock(&bnx2fc_dev_lock);
+	vn_port = bnx2fc_if_create(hba, &vport->dev, 1);
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	if (IS_ERR(vn_port)) {
+		printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
+			netdev->name);
+		return -EIO;
+	}
+
+	if (disabled) {
+		fc_vport_set_state(vport, FC_VPORT_DISABLED);
+	} else {
+		vn_port->boot_time = jiffies;
+		fc_lport_init(vn_port);
+		fc_fabric_login(vn_port);
+		fc_vport_setlink(vn_port);
+	}
+	return 0;
+}
+
+static int bnx2fc_vport_destroy(struct fc_vport *vport)
+{
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_lport *n_port = shost_priv(shost);
+	struct fc_lport *vn_port = vport->dd_data;
+	struct fcoe_port *port = lport_priv(vn_port);
+
+	mutex_lock(&n_port->lp_mutex);
+	list_del(&vn_port->list);
+	mutex_unlock(&n_port->lp_mutex);
+	queue_work(bnx2fc_wq, &port->destroy_work);
+	return 0;
+}
+
+static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable)
+{
+	struct fc_lport *lport = vport->dd_data;
+
+	if (disable) {
+		fc_vport_set_state(vport, FC_VPORT_DISABLED);
+		fc_fabric_logoff(lport);
+	} else {
+		lport->boot_time = jiffies;
+		fc_fabric_login(lport);
+		fc_vport_setlink(lport);
+	}
+	return 0;
+}
+
+
+static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
+{
+	struct net_device *netdev = hba->netdev;
+	struct net_device *physdev = hba->phys_dev;
+	struct netdev_hw_addr *ha;
+	int sel_san_mac = 0;
+
+	/* Do not support for bonding device */
+	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
+			(netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
+			(netdev->priv_flags & IFF_MASTER_8023AD)) {
+		return -EOPNOTSUPP;
+	}
+
+	/* setup Source MAC Address */
+	rcu_read_lock();
+	for_each_dev_addr(physdev, ha) {
+		BNX2FC_MISC_DBG("net_config: ha->type = %d, fip_mac = ",
+				ha->type);
+		printk(KERN_INFO "%2x:%2x:%2x:%2x:%2x:%2x\n", ha->addr[0],
+				ha->addr[1], ha->addr[2], ha->addr[3],
+				ha->addr[4], ha->addr[5]);
+
+		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
+		    (is_valid_ether_addr(ha->addr))) {
+			memcpy(hba->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+			sel_san_mac = 1;
+			BNX2FC_MISC_DBG("Found SAN MAC\n");
+		}
+	}
+	rcu_read_unlock();
+
+	if (!sel_san_mac)
+		return -ENODEV;
+
+	hba->fip_packet_type.func = bnx2fc_fip_recv;
+	hba->fip_packet_type.type = htons(ETH_P_FIP);
+	hba->fip_packet_type.dev = netdev;
+	dev_add_pack(&hba->fip_packet_type);
+
+	hba->fcoe_packet_type.func = bnx2fc_rcv;
+	hba->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+	hba->fcoe_packet_type.dev = netdev;
+	dev_add_pack(&hba->fcoe_packet_type);
+
+	return 0;
+}
+
+static int bnx2fc_attach_transport(void)
+{
+	bnx2fc_transport_template =
+		fc_attach_transport(&bnx2fc_transport_function);
+
+	if (bnx2fc_transport_template == NULL) {
+		printk(KERN_ERR PFX "Failed to attach FC transport\n");
+		return -ENODEV;
+	}
+
+	bnx2fc_vport_xport_template =
+		fc_attach_transport(&bnx2fc_vport_xport_function);
+	if (bnx2fc_vport_xport_template == NULL) {
+		printk(KERN_ERR PFX
+		       "Failed to attach FC transport for vport\n");
+		fc_release_transport(bnx2fc_transport_template);
+		bnx2fc_transport_template = NULL;
+		return -ENODEV;
+	}
+	return 0;
+}
+static void bnx2fc_release_transport(void)
+{
+	fc_release_transport(bnx2fc_transport_template);
+	fc_release_transport(bnx2fc_vport_xport_template);
+	bnx2fc_transport_template = NULL;
+	bnx2fc_vport_xport_template = NULL;
+}
+
+static void bnx2fc_interface_release(struct kref *kref)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *netdev;
+	struct net_device *phys_dev;
+
+	hba = container_of(kref, struct bnx2fc_hba, kref);
+	BNX2FC_HBA_DBG(hba->ctlr.lp, "Interface is being released\n");
+
+	netdev = hba->netdev;
+	phys_dev = hba->phys_dev;
+
+	/* tear-down FIP controller */
+	if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done))
+		fcoe_ctlr_destroy(&hba->ctlr);
+
+	/* Free the command manager */
+	if (hba->cmd_mgr) {
+		bnx2fc_cmd_mgr_free(hba->cmd_mgr);
+		hba->cmd_mgr = NULL;
+	}
+	dev_put(netdev);
+	module_put(THIS_MODULE);
+}
+
+static inline void bnx2fc_interface_get(struct bnx2fc_hba *hba)
+{
+	kref_get(&hba->kref);
+}
+
+static inline void bnx2fc_interface_put(struct bnx2fc_hba *hba)
+{
+	kref_put(&hba->kref, bnx2fc_interface_release);
+}
+static void bnx2fc_interface_destroy(struct bnx2fc_hba *hba)
+{
+	bnx2fc_unbind_pcidev(hba);
+	kfree(hba);
+}
+
+/**
+ * bnx2fc_interface_create - create a new fcoe instance
+ *
+ * @cnic:	pointer to cnic device
+ *
+ * Creates a new FCoE instance on the given device which include allocating
+ *	hba structure, scsi_host and lport structures.
+ */
+static struct bnx2fc_hba *bnx2fc_interface_create(struct cnic_dev *cnic)
+{
+	struct bnx2fc_hba *hba;
+	int rc;
+
+	hba = kzalloc(sizeof(*hba), GFP_KERNEL);
+	if (!hba) {
+		printk(KERN_ERR PFX "Unable to allocate hba structure\n");
+		return NULL;
+	}
+	spin_lock_init(&hba->hba_lock);
+	mutex_init(&hba->hba_mutex);
+
+	hba->cnic = cnic;
+	rc = bnx2fc_bind_pcidev(hba);
+	if (rc)
+		goto bind_err;
+	hba->phys_dev = cnic->netdev;
+	/* will get overwritten after we do vlan discovery */
+	hba->netdev = hba->phys_dev;
+
+	init_waitqueue_head(&hba->shutdown_wait);
+	init_waitqueue_head(&hba->destroy_wait);
+
+	return hba;
+bind_err:
+	printk(KERN_ERR PFX "create_interface: bind error\n");
+	kfree(hba);
+	return NULL;
+}
+
+static int bnx2fc_interface_setup(struct bnx2fc_hba *hba,
+				  enum fip_state fip_mode)
+{
+	int rc = 0;
+	struct net_device *netdev = hba->netdev;
+	struct fcoe_ctlr *fip = &hba->ctlr;
+
+	dev_hold(netdev);
+	kref_init(&hba->kref);
+
+	hba->flags = 0;
+
+	/* Initialize FIP */
+	memset(fip, 0, sizeof(*fip));
+	fcoe_ctlr_init(fip, fip_mode);
+	hba->ctlr.send = bnx2fc_fip_send;
+	hba->ctlr.update_mac = bnx2fc_update_src_mac;
+	hba->ctlr.get_src_addr = bnx2fc_get_src_mac;
+	set_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done);
+
+	rc = bnx2fc_netdev_setup(hba);
+	if (rc)
+		goto setup_err;
+
+	hba->next_conn_id = 0;
+
+	memset(hba->tgt_ofld_list, 0, sizeof(hba->tgt_ofld_list));
+	hba->num_ofld_sess = 0;
+
+	return 0;
+
+setup_err:
+	fcoe_ctlr_destroy(&hba->ctlr);
+	dev_put(netdev);
+	bnx2fc_interface_put(hba);
+	return rc;
+}
+
+/**
+ * bnx2fc_if_create - Create FCoE instance on a given interface
+ *
+ * @hba:	FCoE interface to create a local port on
+ * @parent:	Device pointer to be the parent in sysfs for the SCSI host
+ * @npiv:	Indicates if the port is vport or not
+ *
+ * Creates a fc_lport instance and a Scsi_Host instance and configure them.
+ *
+ * Returns:	Allocated fc_lport or an error pointer
+ */
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+				  struct device *parent, int npiv)
+{
+	struct fc_lport		*lport = NULL;
+	struct fcoe_port	*port;
+	struct Scsi_Host	*shost;
+	struct fc_vport		*vport = dev_to_vport(parent);
+	int			rc = 0;
+
+	/* Allocate Scsi_Host structure */
+	if (!npiv) {
+		lport = libfc_host_alloc(&bnx2fc_shost_template,
+					  sizeof(struct fcoe_port));
+	} else {
+		lport = libfc_vport_create(vport,
+					   sizeof(struct fcoe_port));
+	}
+
+	if (!lport) {
+		printk(KERN_ERR PFX "could not allocate scsi host structure\n");
+		return NULL;
+	}
+	shost = lport->host;
+	port = lport_priv(lport);
+	port->lport = lport;
+	port->priv = hba;
+	INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
+
+	/* Configure fcoe_port */
+	rc = bnx2fc_lport_config(lport);
+	if (rc)
+		goto lp_config_err;
+
+	if (npiv) {
+		vport = dev_to_vport(parent);
+		printk(KERN_ERR PFX "Setting vport names, 0x%llX 0x%llX\n",
+			vport->node_name, vport->port_name);
+		fc_set_wwnn(lport, vport->node_name);
+		fc_set_wwpn(lport, vport->port_name);
+	}
+	/* Configure netdev and networking properties of the lport */
+	rc = bnx2fc_net_config(lport);
+	if (rc) {
+		printk(KERN_ERR PFX "Error on bnx2fc_net_config\n");
+		goto lp_config_err;
+	}
+
+	rc = bnx2fc_shost_config(lport, parent);
+	if (rc) {
+		printk(KERN_ERR PFX "Couldnt configure shost for %s\n",
+			hba->netdev->name);
+		goto lp_config_err;
+	}
+
+	/* Initialize the libfc library */
+	rc = bnx2fc_libfc_config(lport);
+	if (rc) {
+		printk(KERN_ERR PFX "Couldnt configure libfc\n");
+		goto shost_err;
+	}
+	fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+
+	/* Allocate exchange manager */
+	if (!npiv) {
+		rc = bnx2fc_em_config(lport);
+		if (rc) {
+			printk(KERN_ERR PFX "Error on bnx2fc_em_config\n");
+			goto shost_err;
+		}
+	}
+
+	bnx2fc_interface_get(hba);
+	return lport;
+
+shost_err:
+	scsi_remove_host(shost);
+lp_config_err:
+	scsi_host_put(lport->host);
+	return NULL;
+}
+
+static void bnx2fc_netdev_cleanup(struct bnx2fc_hba *hba)
+{
+	/* Dont listen for Ethernet packets anymore */
+	__dev_remove_pack(&hba->fcoe_packet_type);
+	__dev_remove_pack(&hba->fip_packet_type);
+	synchronize_net();
+}
+
+static void bnx2fc_if_destroy(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+
+	BNX2FC_HBA_DBG(hba->ctlr.lp, "ENTERED bnx2fc_if_destroy\n");
+	/* Stop the transmit retry timer */
+	del_timer_sync(&port->timer);
+
+	/* Free existing transmit skbs */
+	fcoe_clean_pending_queue(lport);
+
+	bnx2fc_interface_put(hba);
+
+	/* Free queued packets for the receive thread */
+	bnx2fc_clean_rx_queue(lport);
+
+	/* Detach from scsi-ml */
+	fc_remove_host(lport->host);
+	scsi_remove_host(lport->host);
+
+	/*
+	 * Note that only the physical lport will have the exchange manager.
+	 * for vports, this function is NOP
+	 */
+	fc_exch_mgr_free(lport);
+
+	/* Free memory used by statistical counters */
+	fc_lport_free_stats(lport);
+
+	/* Release Scsi_Host */
+	scsi_host_put(lport->host);
+}
+
+/**
+ * bnx2fc_destroy - Destroy a bnx2fc FCoE interface
+ *
+ * @buffer: The name of the Ethernet interface to be destroyed
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_destroy(struct net_device *netdev)
+{
+	struct bnx2fc_hba *hba = NULL;
+	struct net_device *phys_dev;
+	int rc = 0;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	mutex_lock(&bnx2fc_dev_lock);
+#ifdef CONFIG_SCSI_BNX2X_FCOE_MODULE
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto netdev_err;
+	}
+#endif
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN)
+		phys_dev = vlan_dev_real_dev(netdev);
+	else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -ENODEV;
+		goto netdev_err;
+	}
+
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba || !hba->ctlr.lp) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_destroy: hba or lport not found\n");
+		goto netdev_err;
+	}
+
+	if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "bnx2fc_destroy: Create not called\n");
+		goto netdev_err;
+	}
+
+	bnx2fc_netdev_cleanup(hba);
+
+	bnx2fc_stop(hba);
+
+	bnx2fc_if_destroy(hba->ctlr.lp);
+
+	destroy_workqueue(hba->timer_work_queue);
+
+	if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
+		bnx2fc_fw_destroy(hba);
+
+	clear_bit(BNX2FC_CREATE_DONE, &hba->init_done);
+netdev_err:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+static void bnx2fc_destroy_work(struct work_struct *work)
+{
+	struct fcoe_port *port;
+	struct fc_lport *lport;
+
+	port = container_of(work, struct fcoe_port, destroy_work);
+	lport = port->lport;
+
+	BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
+
+	bnx2fc_port_shutdown(lport);
+	rtnl_lock();
+	mutex_lock(&bnx2fc_dev_lock);
+	bnx2fc_if_destroy(lport);
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+}
+
+static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba)
+{
+	bnx2fc_free_fw_resc(hba);
+	bnx2fc_free_task_ctx(hba);
+}
+
+/**
+ * bnx2fc_bind_adapter_devices - binds bnx2fc adapter with the associated
+ *			pci structure
+ *
+ * @hba:		Adapter instance
+ */
+static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba)
+{
+	if (bnx2fc_setup_task_ctx(hba))
+		goto mem_err;
+
+	if (bnx2fc_setup_fw_resc(hba))
+		goto mem_err;
+
+	return 0;
+mem_err:
+	bnx2fc_unbind_adapter_devices(hba);
+	return -ENOMEM;
+}
+
+static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
+{
+	struct cnic_dev *cnic;
+
+	if (!hba->cnic) {
+		printk(KERN_ERR PFX "cnic is NULL\n");
+		return -ENODEV;
+	}
+	cnic = hba->cnic;
+	hba->pcidev = cnic->pcidev;
+	if (hba->pcidev)
+		pci_dev_get(hba->pcidev);
+
+	return 0;
+}
+
+static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
+{
+	if (hba->pcidev)
+		pci_dev_put(hba->pcidev);
+	hba->pcidev = NULL;
+}
+
+
+
+/**
+ * bnx2fc_ulp_start - cnic callback to initialize & start adapter instance
+ *
+ * @handle:	transport handle pointing to adapter struture
+ *
+ * This function maps adapter structure to pcidev structure and initiates
+ *	firmware handshake to enable/initialize on-chip FCoE components.
+ *	This bnx2fc - cnic interface api callback is used after following
+ *	conditions are met -
+ *	a) underlying network interface is up (marked by event NETDEV_UP
+ *		from netdev
+ *	b) bnx2fc adatper structure is registered.
+ */
+static void bnx2fc_ulp_start(void *handle)
+{
+	struct bnx2fc_hba *hba = handle;
+	struct fc_lport *lport = hba->ctlr.lp;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	mutex_lock(&bnx2fc_dev_lock);
+
+	if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
+		goto start_disc;
+
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done))
+		bnx2fc_fw_init(hba);
+
+start_disc:
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	BNX2FC_MISC_DBG("bnx2fc started.\n");
+
+	/* Kick off Fabric discovery*/
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "ulp_init: start discovery\n");
+		lport->tt.frame_send = bnx2fc_xmit;
+		bnx2fc_start_disc(hba);
+	}
+}
+
+static void bnx2fc_port_shutdown(struct fc_lport *lport)
+{
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	fc_fabric_logoff(lport);
+	fc_lport_destroy(lport);
+}
+
+static void bnx2fc_stop(struct bnx2fc_hba *hba)
+{
+	struct fc_lport *lport;
+	struct fc_lport *vport;
+
+	BNX2FC_MISC_DBG("ENTERED %s - init_done = %ld\n", __func__,
+		   hba->init_done);
+	if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done) &&
+	    test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		lport = hba->ctlr.lp;
+		bnx2fc_port_shutdown(lport);
+		BNX2FC_HBA_DBG(lport, "bnx2fc_stop: waiting for %d "
+				"offloaded sessions\n",
+				hba->num_ofld_sess);
+		wait_event_interruptible(hba->shutdown_wait,
+					 (hba->num_ofld_sess == 0));
+		mutex_lock(&lport->lp_mutex);
+		list_for_each_entry(vport, &lport->vports, list)
+			fc_host_port_type(vport->host) = FC_PORTTYPE_UNKNOWN;
+		mutex_unlock(&lport->lp_mutex);
+		fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+		fcoe_ctlr_link_down(&hba->ctlr);
+		fcoe_clean_pending_queue(lport);
+
+		mutex_lock(&hba->hba_mutex);
+		clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+		clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+
+		clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+		mutex_unlock(&hba->hba_mutex);
+	}
+}
+
+static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
+{
+#define BNX2FC_INIT_POLL_TIME		(1000 / HZ)
+	int rc = -1;
+	int i = HZ;
+
+	rc = bnx2fc_bind_adapter_devices(hba);
+	if (rc) {
+		printk(KERN_ALERT PFX
+			"bnx2fc_bind_adapter_devices failed - rc = %d\n", rc);
+		goto err_out;
+	}
+
+	rc = bnx2fc_send_fw_fcoe_init_msg(hba);
+	if (rc) {
+		printk(KERN_ALERT PFX
+			"bnx2fc_send_fw_fcoe_init_msg failed - rc = %d\n", rc);
+		goto err_unbind;
+	}
+
+	/*
+	 * Wait until the adapter init message is complete, and adapter
+	 * state is UP.
+	 */
+	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
+		msleep(BNX2FC_INIT_POLL_TIME);
+
+	if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) {
+		printk(KERN_ERR PFX "bnx2fc_start: %s failed to initialize.  "
+				"Ignoring...\n",
+				hba->cnic->netdev->name);
+		rc = -1;
+		goto err_unbind;
+	}
+
+
+	/* Mark HBA to indicate that the FW INIT is done */
+	set_bit(BNX2FC_FW_INIT_DONE, &hba->init_done);
+	return 0;
+
+err_unbind:
+	bnx2fc_unbind_adapter_devices(hba);
+err_out:
+	return rc;
+}
+
+static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
+{
+	if (test_and_clear_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		if (bnx2fc_send_fw_fcoe_destroy_msg(hba) == 0) {
+			init_timer(&hba->destroy_timer);
+			hba->destroy_timer.expires = BNX2FC_FW_TIMEOUT +
+								jiffies;
+			hba->destroy_timer.function = bnx2fc_destroy_timer;
+			hba->destroy_timer.data = (unsigned long)hba;
+			add_timer(&hba->destroy_timer);
+			wait_event_interruptible(hba->destroy_wait,
+						 (hba->flags &
+						  BNX2FC_FLAG_DESTROY_CMPL));
+			/* This should never happen */
+			if (signal_pending(current))
+				flush_signals(current);
+
+			del_timer_sync(&hba->destroy_timer);
+		}
+		bnx2fc_unbind_adapter_devices(hba);
+	}
+}
+
+/**
+ * bnx2fc_ulp_stop - cnic callback to shutdown adapter instance
+ *
+ * @handle:	transport handle pointing to adapter structure
+ *
+ * Driver checks if adapter is already in shutdown mode, if not start
+ *	the shutdown process.
+ */
+static void bnx2fc_ulp_stop(void *handle)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)handle;
+
+	printk(KERN_ERR "ULP_STOP\n");
+
+	mutex_lock(&bnx2fc_dev_lock);
+	bnx2fc_stop(hba);
+	bnx2fc_fw_destroy(hba);
+	mutex_unlock(&bnx2fc_dev_lock);
+}
+
+static void bnx2fc_start_disc(struct bnx2fc_hba *hba)
+{
+	struct fc_lport *lport;
+	int wait_cnt = 0;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	/* Kick off FIP/FLOGI */
+	if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "Init not done yet\n");
+		return;
+	}
+
+	lport = hba->ctlr.lp;
+	BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n");
+
+	if (!bnx2fc_link_ok(lport)) {
+		BNX2FC_HBA_DBG(lport, "ctlr_link_up\n");
+		fcoe_ctlr_link_up(&hba->ctlr);
+		fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
+		set_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+	}
+
+	/* wait for the FCF to be selected before issuing FLOGI */
+	while (!hba->ctlr.sel_fcf) {
+		msleep(250);
+		/* give up after 3 secs */
+		if (++wait_cnt > 12)
+			break;
+	}
+	fc_lport_init(lport);
+	fc_fabric_login(lport);
+}
+
+
+/**
+ * bnx2fc_ulp_init - Initialize an adapter instance
+ *
+ * @dev :	cnic device handle
+ * Called from cnic_register_driver() context to initialize all
+ *	enumerated cnic devices. This routine allocates adapter structure
+ *	and other device specific resources.
+ */
+static void bnx2fc_ulp_init(struct cnic_dev *dev)
+{
+	struct bnx2fc_hba *hba;
+	int rc = 0;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	/* bnx2fc works only when bnx2x is loaded */
+	if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+		printk(KERN_ERR PFX "bnx2fc FCoE not supported on %s,"
+				    " flags: %lx\n",
+			dev->netdev->name, dev->flags);
+		return;
+	}
+
+	/* Configure FCoE interface */
+	hba = bnx2fc_interface_create(dev);
+	if (!hba) {
+		printk(KERN_ERR PFX "hba initialization failed\n");
+		return;
+	}
+
+	/* Add HBA to the adapter list */
+	mutex_lock(&bnx2fc_dev_lock);
+	list_add_tail(&hba->link, &adapter_list);
+	adapter_count++;
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
+	rc = dev->register_device(dev, CNIC_ULP_FCOE,
+						(void *) hba);
+	if (rc)
+		printk(KERN_ALERT PFX "register_device failed, rc = %d\n", rc);
+	else
+		set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
+}
+
+
+static int bnx2fc_disable(struct net_device *netdev)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *phys_dev;
+	struct ethtool_drvinfo drvinfo;
+	int rc = 0;
+
+	if (!rtnl_trylock()) {
+		printk(KERN_ERR PFX "retrying for rtnl_lock\n");
+		return -EIO;
+	}
+
+	mutex_lock(&bnx2fc_dev_lock);
+
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN)
+		phys_dev = vlan_dev_real_dev(netdev);
+	else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	/* verify if the physical device is a netxtreme2 device */
+	if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
+		if (strcmp(drvinfo.driver, "bnx2x")) {
+			printk(KERN_ERR PFX "Not a netxtreme2 device\n");
+			rc = -ENODEV;
+			goto nodev;
+		}
+	} else {
+		printk(KERN_ERR PFX "unable to obtain drv_info\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	printk(KERN_ERR PFX "phys_dev is netxtreme2 device\n");
+
+	/* obtain hba and initialize rest of the structure */
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba || !hba->ctlr.lp) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_disable: hba or lport not found\n");
+	} else {
+		fcoe_ctlr_link_down(&hba->ctlr);
+		fcoe_clean_pending_queue(hba->ctlr.lp);
+	}
+
+nodev:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+
+static int bnx2fc_enable(struct net_device *netdev)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *phys_dev;
+	struct ethtool_drvinfo drvinfo;
+	int rc = 0;
+
+	if (!rtnl_trylock()) {
+		printk(KERN_ERR PFX "retrying for rtnl_lock\n");
+		return -EIO;
+	}
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	mutex_lock(&bnx2fc_dev_lock);
+
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN)
+		phys_dev = vlan_dev_real_dev(netdev);
+	else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+	/* verify if the physical device is a netxtreme2 device */
+	if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
+		if (strcmp(drvinfo.driver, "bnx2x")) {
+			printk(KERN_ERR PFX "Not a netxtreme2 device\n");
+			rc = -ENODEV;
+			goto nodev;
+		}
+	} else {
+		printk(KERN_ERR PFX "unable to obtain drv_info\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	/* obtain hba and initialize rest of the structure */
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba || !hba->ctlr.lp) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_enable: hba or lport not found\n");
+	} else if (!bnx2fc_link_ok(hba->ctlr.lp))
+		fcoe_ctlr_link_up(&hba->ctlr);
+
+nodev:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+/**
+ * bnx2fc_create - Create bnx2fc FCoE interface
+ *
+ * @buffer: The name of Ethernet interface to create on
+ * @kp:     The associated kernel param
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *phys_dev;
+	struct fc_lport *lport;
+	struct ethtool_drvinfo drvinfo;
+	int rc = 0;
+	int vlan_id;
+
+	BNX2FC_MISC_DBG("Entered bnx2fc_create\n");
+	if (fip_mode != FIP_MODE_FABRIC) {
+		printk(KERN_ERR "fip mode not FABRIC\n");
+		return -EIO;
+	}
+
+	if (!rtnl_trylock()) {
+		printk(KERN_ERR "trying for rtnl_lock\n");
+		return -EIO;
+	}
+	mutex_lock(&bnx2fc_dev_lock);
+
+#ifdef CONFIG_SCSI_BNX2X_FCOE_MODULE
+	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
+		rc = -ENODEV;
+		goto mod_err;
+	}
+#endif
+
+	if (!try_module_get(THIS_MODULE)) {
+		rc = -EINVAL;
+		goto mod_err;
+	}
+
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN) {
+		phys_dev = vlan_dev_real_dev(netdev);
+		vlan_id = vlan_dev_vlan_id(netdev);
+	} else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -EINVAL;
+		goto netdev_err;
+	}
+	/* verify if the physical device is a netxtreme2 device */
+	if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
+		if (strcmp(drvinfo.driver, "bnx2x")) {
+			printk(KERN_ERR PFX "Not a netxtreme2 device\n");
+			rc = -EINVAL;
+			goto netdev_err;
+		}
+	} else {
+		printk(KERN_ERR PFX "unable to obtain drv_info\n");
+		rc = -EINVAL;
+		goto netdev_err;
+	}
+
+	/* obtain hba and initialize rest of the structure */
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_create: hba not found\n");
+		goto netdev_err;
+	}
+
+	if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		rc = bnx2fc_fw_init(hba);
+		if (rc)
+			goto netdev_err;
+	}
+
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		rc = -EEXIST;
+		goto netdev_err;
+	}
+
+	/* update netdev with vlan netdev */
+	hba->netdev = netdev;
+	hba->vlan_id = vlan_id;
+	hba->vlan_enabled = 1;
+
+	rc = bnx2fc_interface_setup(hba, fip_mode);
+	if (rc) {
+		printk(KERN_ERR PFX "bnx2fc_interface_setup failed\n");
+		goto ifput_err;
+	}
+
+	hba->timer_work_queue =
+			create_singlethread_workqueue("bnx2fc_timer_wq");
+	if (!hba->timer_work_queue) {
+		printk(KERN_ERR PFX "ulp_init could not create timer_wq\n");
+		rc = -EINVAL;
+		goto ifput_err;
+	}
+
+	lport = bnx2fc_if_create(hba, &hba->pcidev->dev, 0);
+	if (!lport) {
+		printk(KERN_ERR PFX "Failed to create interface (%s)\n",
+			netdev->name);
+		bnx2fc_netdev_cleanup(hba);
+		rc = -EINVAL;
+		goto if_create_err;
+	}
+
+	lport->boot_time = jiffies;
+
+	/* Make this master N_port */
+	hba->ctlr.lp = lport;
+
+	set_bit(BNX2FC_CREATE_DONE, &hba->init_done);
+	printk(KERN_ERR PFX "create: START DISC\n");
+	bnx2fc_start_disc(hba);
+	/*
+	 * Release from kref_init in bnx2fc_interface_setup, on success
+	 * lport should be holding a reference taken in bnx2fc_if_create
+	 */
+	bnx2fc_interface_put(hba);
+	/* put netdev that was held while calling dev_get_by_name */
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return 0;
+
+if_create_err:
+	destroy_workqueue(hba->timer_work_queue);
+ifput_err:
+	bnx2fc_interface_put(hba);
+netdev_err:
+	module_put(THIS_MODULE);
+mod_err:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+/**
+ * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc adapter instance
+ *
+ * @cnic:	Pointer to cnic device instance
+ *
+ **/
+static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic)
+{
+	struct list_head *list;
+	struct list_head *temp;
+	struct bnx2fc_hba *hba;
+
+	/* Called with bnx2fc_dev_lock held */
+	list_for_each_safe(list, temp, &adapter_list) {
+		hba = (struct bnx2fc_hba *)list;
+		if (hba->cnic == cnic)
+			return hba;
+	}
+	return NULL;
+}
+
+static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev)
+{
+	struct list_head *list;
+	struct list_head *temp;
+	struct bnx2fc_hba *hba;
+
+	/* Called with bnx2fc_dev_lock held */
+	list_for_each_safe(list, temp, &adapter_list) {
+		hba = (struct bnx2fc_hba *)list;
+		if (hba->phys_dev == phys_dev)
+			return hba;
+	}
+	printk(KERN_ERR PFX "hba_lookup: hba NULL\n");
+	return NULL;
+}
+
+/**
+ * bnx2fc_ulp_exit - shuts down adapter instance and frees all resources
+ *
+ * @dev		cnic device handle
+ */
+static void bnx2fc_ulp_exit(struct cnic_dev *dev)
+{
+	struct bnx2fc_hba *hba;
+
+	BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n");
+
+	if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+		printk(KERN_ERR PFX "bnx2fc port check: %s, flags: %lx\n",
+			dev->netdev->name, dev->flags);
+		return;
+	}
+
+	mutex_lock(&bnx2fc_dev_lock);
+	hba = bnx2fc_find_hba_for_cnic(dev);
+	if (!hba) {
+		printk(KERN_ERR PFX "bnx2fc_ulp_exit: hba not found, dev 0%p\n",
+		       dev);
+		mutex_unlock(&bnx2fc_dev_lock);
+		return;
+	}
+
+	list_del_init(&hba->link);
+	adapter_count--;
+
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		/* destroy not called yet, move to quiesced list */
+		bnx2fc_netdev_cleanup(hba);
+		bnx2fc_if_destroy(hba->ctlr.lp);
+	}
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	bnx2fc_ulp_stop(hba);
+	/* unregister cnic device */
+	if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
+		hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
+	bnx2fc_interface_destroy(hba);
+}
+
+/**
+ * bnx2fc_fcoe_reset - Resets the fcoe
+ *
+ * @shost: shost the reset is from
+ *
+ * Returns: always 0
+ */
+static int bnx2fc_fcoe_reset(struct Scsi_Host *shost)
+{
+	struct fc_lport *lport = shost_priv(shost);
+	fc_lport_reset(lport);
+	return 0;
+}
+
+
+static bool bnx2fc_match(struct net_device *netdev)
+{
+	mutex_lock(&bnx2fc_dev_lock);
+	if (netdev->priv_flags & IFF_802_1Q_VLAN) {
+		struct net_device *phys_dev = vlan_dev_real_dev(netdev);
+
+		if (bnx2fc_hba_lookup(phys_dev)) {
+			mutex_unlock(&bnx2fc_dev_lock);
+			return true;
+		}
+	}
+	mutex_unlock(&bnx2fc_dev_lock);
+	return false;
+}
+
+
+static struct fcoe_transport bnx2fc_transport = {
+	.name = {"bnx2fc"},
+	.attached = false,
+	.list = LIST_HEAD_INIT(bnx2fc_transport.list),
+	.match = bnx2fc_match,
+	.create = bnx2fc_create,
+	.destroy = bnx2fc_destroy,
+	.enable = bnx2fc_enable,
+	.disable = bnx2fc_disable,
+};
+
+/**
+ * bnx2fc_percpu_thread_create - Create a receive thread for an
+ *				 online CPU
+ *
+ * @cpu: cpu index for the online cpu
+ */
+static void bnx2fc_percpu_thread_create(unsigned int cpu)
+{
+	struct bnx2fc_percpu_s *p;
+	struct task_struct *thread;
+
+	p = &per_cpu(bnx2fc_percpu, cpu);
+
+	thread = kthread_create(bnx2fc_percpu_io_thread,
+				(void *)p,
+				"bnx2fc_thread/%d", cpu);
+	/* bind thread to the cpu */
+	if (likely(!IS_ERR(p->iothread))) {
+		kthread_bind(thread, cpu);
+		p->iothread = thread;
+		wake_up_process(thread);
+	}
+}
+
+static void bnx2fc_percpu_thread_destroy(unsigned int cpu)
+{
+	struct bnx2fc_percpu_s *p;
+	struct task_struct *thread;
+	struct bnx2fc_work *work, *tmp;
+	LIST_HEAD(work_list);
+
+	BNX2FC_MISC_DBG("destroying io thread for CPU %d\n", cpu);
+
+	/* Prevent any new work from being queued for this CPU */
+	p = &per_cpu(bnx2fc_percpu, cpu);
+	spin_lock_bh(&p->fp_work_lock);
+	thread = p->iothread;
+	p->iothread = NULL;
+
+
+	/* Free all work in the list */
+	list_for_each_entry_safe(work, tmp, &work_list, list) {
+		list_del_init(&work->list);
+		bnx2fc_process_cq_compl(work->tgt, work->wqe);
+		kfree(work);
+	}
+
+	spin_unlock_bh(&p->fp_work_lock);
+
+	if (thread)
+		kthread_stop(thread);
+}
+
+/**
+ * bnx2fc_cpu_callback - Handler for CPU hotplug events
+ *
+ * @nfb:    The callback data block
+ * @action: The event triggering the callback
+ * @hcpu:   The index of the CPU that the event is for
+ *
+ * This creates or destroys per-CPU data for fcoe
+ *
+ * Returns NOTIFY_OK always.
+ */
+static int bnx2fc_cpu_callback(struct notifier_block *nfb,
+			     unsigned long action, void *hcpu)
+{
+	unsigned cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		printk(PFX "CPU %x online: Create Rx thread\n", cpu);
+		bnx2fc_percpu_thread_create(cpu);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		printk(PFX "CPU %x offline: Remove Rx thread\n", cpu);
+		bnx2fc_percpu_thread_destroy(cpu);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+/**
+ * bnx2fc_mod_init - module init entry point
+ *
+ * Initialize driver wide global data structures, and register
+ * with cnic module
+ **/
+static int __init bnx2fc_mod_init(void)
+{
+	struct fcoe_percpu_s *bg;
+	struct task_struct *l2_thread;
+	int rc = 0;
+	unsigned int cpu = 0;
+	struct bnx2fc_percpu_s *p;
+
+	printk(KERN_INFO PFX "%s", version);
+
+	/* register as a fcoe transport */
+	rc = fcoe_transport_attach(&bnx2fc_transport);
+	if (rc) {
+		printk(KERN_ERR "failed to register an fcoe transport, check "
+			"if libfcoe is loaded\n");
+		goto out;
+	}
+
+	INIT_LIST_HEAD(&adapter_list);
+	mutex_init(&bnx2fc_dev_lock);
+	adapter_count = 0;
+
+	/* Attach FC transport template */
+	rc = bnx2fc_attach_transport();
+	if (rc)
+		goto detach_ft;
+
+	bnx2fc_wq = alloc_workqueue("bnx2fc", 0, 0);
+	if (!bnx2fc_wq) {
+		rc = -ENOMEM;
+		goto release_bt;
+	}
+
+	bg = &bnx2fc_global;
+	skb_queue_head_init(&bg->fcoe_rx_list);
+	l2_thread = kthread_create(bnx2fc_l2_rcv_thread,
+				   (void *)bg,
+				   "bnx2fc_l2_thread");
+	if (IS_ERR(l2_thread)) {
+		rc = PTR_ERR(l2_thread);
+		goto free_wq;
+	}
+	wake_up_process(l2_thread);
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+	bg->thread = l2_thread;
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+
+	for_each_possible_cpu(cpu) {
+		p = &per_cpu(bnx2fc_percpu, cpu);
+		INIT_LIST_HEAD(&p->work_list);
+		spin_lock_init(&p->fp_work_lock);
+	}
+
+	for_each_online_cpu(cpu) {
+		bnx2fc_percpu_thread_create(cpu);
+	}
+
+	/* Initialize per CPU interrupt thread */
+	register_hotcpu_notifier(&bnx2fc_cpu_notifier);
+
+	cnic_register_driver(CNIC_ULP_FCOE, &bnx2fc_cnic_cb);
+
+	return 0;
+
+free_wq:
+	destroy_workqueue(bnx2fc_wq);
+release_bt:
+	bnx2fc_release_transport();
+detach_ft:
+	fcoe_transport_detach(&bnx2fc_transport);
+out:
+	return rc;
+}
+
+static void __exit bnx2fc_mod_exit(void)
+{
+	LIST_HEAD(to_be_deleted);
+	struct bnx2fc_hba *hba, *next;
+	struct fcoe_percpu_s *bg;
+	struct task_struct *l2_thread;
+	struct sk_buff *skb;
+	unsigned int cpu = 0;
+
+	/*
+	 * NOTE: Since cnic calls register_driver routine rtnl_lock,
+	 * it will have higher precedence than bnx2fc_dev_lock.
+	 * unregister_device() cannot be called with bnx2fc_dev_lock
+	 * held.
+	 */
+	mutex_lock(&bnx2fc_dev_lock);
+	list_splice(&adapter_list, &to_be_deleted);
+	INIT_LIST_HEAD(&adapter_list);
+	adapter_count = 0;
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	/* Unregister with cnic */
+	list_for_each_entry_safe(hba, next, &to_be_deleted, link) {
+		list_del_init(&hba->link);
+		printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p, kref = %d\n",
+			hba, atomic_read(&hba->kref.refcount));
+		bnx2fc_ulp_stop(hba);
+		/* unregister cnic device */
+		if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED,
+				       &hba->reg_with_cnic))
+			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
+		bnx2fc_interface_destroy(hba);
+	}
+	cnic_unregister_driver(CNIC_ULP_FCOE);
+
+	/* Destroy global thread */
+	bg = &bnx2fc_global;
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+	l2_thread = bg->thread;
+	bg->thread = NULL;
+	while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL)
+		kfree_skb(skb);
+
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+
+	if (l2_thread)
+		kthread_stop(l2_thread);
+
+	unregister_hotcpu_notifier(&bnx2fc_cpu_notifier);
+
+	/* Destroy per cpu threads */
+	for_each_online_cpu(cpu) {
+		bnx2fc_percpu_thread_destroy(cpu);
+	}
+
+	destroy_workqueue(bnx2fc_wq);
+	/*
+	 * detach from scsi transport
+	 * must happen after all destroys are done
+	 */
+	bnx2fc_release_transport();
+
+	/* detach from fcoe transport */
+	fcoe_transport_detach(&bnx2fc_transport);
+}
+
+module_init(bnx2fc_mod_init);
+module_exit(bnx2fc_mod_exit);
+
+static struct fc_function_template bnx2fc_transport_function = {
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_active_fc4s = 1,
+	.show_host_maxframe_size = 1,
+
+	.show_host_port_id = 1,
+	.show_host_supported_speeds = 1,
+	.get_host_speed = fc_get_host_speed,
+	.show_host_speed = 1,
+	.show_host_port_type = 1,
+	.get_host_port_state = fc_get_host_port_state,
+	.show_host_port_state = 1,
+	.show_host_symbolic_name = 1,
+
+	.dd_fcrport_size = (sizeof(struct fc_rport_libfc_priv) +
+				sizeof(struct bnx2fc_rport)),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.show_host_fabric_name = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+	.show_starget_port_id = 1,
+	.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+	.get_fc_host_stats = bnx2fc_get_host_stats,
+
+	.issue_fc_host_lip = bnx2fc_fcoe_reset,
+
+	.terminate_rport_io = fc_rport_terminate_io,
+
+	.vport_create = bnx2fc_vport_create,
+	.vport_delete = bnx2fc_vport_destroy,
+	.vport_disable = bnx2fc_vport_disable,
+};
+
+static struct fc_function_template bnx2fc_vport_xport_function = {
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_active_fc4s = 1,
+	.show_host_maxframe_size = 1,
+
+	.show_host_port_id = 1,
+	.show_host_supported_speeds = 1,
+	.get_host_speed = fc_get_host_speed,
+	.show_host_speed = 1,
+	.show_host_port_type = 1,
+	.get_host_port_state = fc_get_host_port_state,
+	.show_host_port_state = 1,
+	.show_host_symbolic_name = 1,
+
+	.dd_fcrport_size = (sizeof(struct fc_rport_libfc_priv) +
+				sizeof(struct bnx2fc_rport)),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.show_host_fabric_name = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+	.show_starget_port_id = 1,
+	.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+	.get_fc_host_stats = fc_get_host_stats,
+	.issue_fc_host_lip = bnx2fc_fcoe_reset,
+	.terminate_rport_io = fc_rport_terminate_io,
+};
+
+/**
+ * scsi_host_template structure used while registering with SCSI-ml
+ */
+static struct scsi_host_template bnx2fc_shost_template = {
+	.module			= THIS_MODULE,
+	.name			= "Broadcom Offload FCoE Initiator",
+	.queuecommand		= bnx2fc_queuecommand,
+	.eh_abort_handler	= bnx2fc_eh_abort,	  /* abts */
+	.eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
+	.eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */
+	.eh_host_reset_handler	= fc_eh_host_reset,
+	.slave_alloc		= fc_slave_alloc,
+	.change_queue_depth	= fc_change_queue_depth,
+	.change_queue_type	= fc_change_queue_type,
+	.this_id		= -1,
+	.cmd_per_lun		= 3,
+	.can_queue		= (BNX2FC_MAX_OUTSTANDING_CMNDS/2),
+	.use_clustering		= ENABLE_CLUSTERING,
+	.sg_tablesize		= BNX2FC_MAX_BDS_PER_CMD,
+	.max_sectors		= 512,
+};
+
+static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
+	.frame_send		= bnx2fc_xmit,
+	.elsct_send		= bnx2fc_elsct_send,
+	.fcp_abort_io		= bnx2fc_abort_io,
+	.fcp_cleanup		= bnx2fc_cleanup,
+	.rport_event_callback	= bnx2fc_rport_event_handler,
+};
+
+/**
+ * bnx2fc_cnic_cb - global template of bnx2fc - cnic driver interface
+ *			structure carrying callback function pointers
+ */
+static struct cnic_ulp_ops bnx2fc_cnic_cb = {
+	.owner			= THIS_MODULE,
+	.cnic_init		= bnx2fc_ulp_init,
+	.cnic_exit		= bnx2fc_ulp_exit,
+	.cnic_start		= bnx2fc_ulp_start,
+	.cnic_stop		= bnx2fc_ulp_stop,
+	.indicate_kcqes		= bnx2fc_indicate_kcqe,
+	.indicate_netevent	= bnx2fc_indicate_netevent,
+};
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
new file mode 100644
index 0000000..4f40968
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -0,0 +1,1868 @@
+/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * This file contains the code that low level functions that interact
+ * with 57712 FCoE firmware.
+ *
+ * Copyright (c) 2008 - 2010 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+DECLARE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
+
+static void bnx2fc_fastpath_notification(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *new_cqe_kcqe);
+static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *ofld_kcqe);
+static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
+						struct fcoe_kcqe *ofld_kcqe);
+static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code);
+static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *conn_destroy);
+
+int bnx2fc_send_stat_req(struct bnx2fc_hba *hba)
+{
+	struct fcoe_kwqe_stat stat_req;
+	struct kwqe *kwqe_arr[2];
+	int num_kwqes = 1;
+	int rc = 0;
+
+	memset(&stat_req, 0x00, sizeof(struct fcoe_kwqe_stat));
+	stat_req.hdr.op_code = FCOE_KWQE_OPCODE_STAT;
+	stat_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	stat_req.stat_params_addr_lo = (u32) hba->stats_buf_dma;
+	stat_req.stat_params_addr_hi = (u32) ((u64)hba->stats_buf_dma >> 32);
+
+	kwqe_arr[0] = (struct kwqe *) &stat_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+/**
+ * bnx2fc_send_fw_fcoe_init_msg - initiates initial handshake with FCoE f/w
+ *
+ * @hba:	adapter structure pointer
+ *
+ * Send down FCoE firmware init KWQEs which initiates the initial handshake
+ *	with the f/w.
+ *
+ */
+int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
+{
+	struct fcoe_kwqe_init1 fcoe_init1;
+	struct fcoe_kwqe_init2 fcoe_init2;
+	struct fcoe_kwqe_init3 fcoe_init3;
+	struct kwqe *kwqe_arr[3];
+	int num_kwqes = 3;
+	int rc = 0;
+
+	if (!hba->cnic) {
+		printk(KERN_ALERT PFX "hba->cnic NULL during fcoe fw init\n");
+		return -ENODEV;
+	}
+
+	/* fill init1 KWQE */
+	memset(&fcoe_init1, 0x00, sizeof(struct fcoe_kwqe_init1));
+	fcoe_init1.hdr.op_code = FCOE_KWQE_OPCODE_INIT1;
+	fcoe_init1.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	fcoe_init1.num_tasks = BNX2FC_MAX_TASKS;
+	fcoe_init1.sq_num_wqes = BNX2FC_SQ_WQES_MAX;
+	fcoe_init1.rq_num_wqes = BNX2FC_RQ_WQES_MAX;
+	fcoe_init1.rq_buffer_log_size = BNX2FC_RQ_BUF_LOG_SZ;
+	fcoe_init1.cq_num_wqes = BNX2FC_CQ_WQES_MAX;
+	fcoe_init1.dummy_buffer_addr_lo = (u32) hba->dummy_buf_dma;
+	fcoe_init1.dummy_buffer_addr_hi = (u32) ((u64)hba->dummy_buf_dma >> 32);
+	fcoe_init1.task_list_pbl_addr_lo = (u32) hba->task_ctx_bd_dma;
+	fcoe_init1.task_list_pbl_addr_hi =
+				(u32) ((u64) hba->task_ctx_bd_dma >> 32);
+	fcoe_init1.mtu = hba->netdev->mtu;
+
+	fcoe_init1.flags = (PAGE_SHIFT <<
+				FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT);
+
+	fcoe_init1.num_sessions_log = BNX2FC_NUM_MAX_SESS_LOG;
+
+	/* fill init2 KWQE */
+	memset(&fcoe_init2, 0x00, sizeof(struct fcoe_kwqe_init2));
+	fcoe_init2.hdr.op_code = FCOE_KWQE_OPCODE_INIT2;
+	fcoe_init2.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
+	fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
+					   ((u64) hba->hash_tbl_pbl_dma >> 32);
+
+	fcoe_init2.t2_hash_tbl_addr_lo = (u32) hba->t2_hash_tbl_dma;
+	fcoe_init2.t2_hash_tbl_addr_hi = (u32)
+					  ((u64) hba->t2_hash_tbl_dma >> 32);
+
+	fcoe_init2.t2_ptr_hash_tbl_addr_lo = (u32) hba->t2_hash_tbl_ptr_dma;
+	fcoe_init2.t2_ptr_hash_tbl_addr_hi = (u32)
+					((u64) hba->t2_hash_tbl_ptr_dma >> 32);
+
+	fcoe_init2.free_list_count = BNX2FC_NUM_MAX_SESS;
+
+	/* fill init3 KWQE */
+	memset(&fcoe_init3, 0x00, sizeof(struct fcoe_kwqe_init3));
+	fcoe_init3.hdr.op_code = FCOE_KWQE_OPCODE_INIT3;
+	fcoe_init3.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+	fcoe_init3.error_bit_map_lo = 0xffffffff;
+	fcoe_init3.error_bit_map_hi = 0xffffffff;
+
+
+	kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
+	kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
+	kwqe_arr[2] = (struct kwqe *) &fcoe_init3;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+int bnx2fc_send_fw_fcoe_destroy_msg(struct bnx2fc_hba *hba)
+{
+	struct fcoe_kwqe_destroy fcoe_destroy;
+	struct kwqe *kwqe_arr[2];
+	int num_kwqes = 1;
+	int rc = -1;
+
+	/* fill destroy KWQE */
+	memset(&fcoe_destroy, 0x00, sizeof(struct fcoe_kwqe_destroy));
+	fcoe_destroy.hdr.op_code = FCOE_KWQE_OPCODE_DESTROY;
+	fcoe_destroy.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+	kwqe_arr[0] = (struct kwqe *) &fcoe_destroy;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_ofld_req - initiates FCoE Session offload process
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt)
+{
+	struct fc_lport *lport = port->lport;
+	struct bnx2fc_hba *hba = port->priv;
+	struct kwqe *kwqe_arr[4];
+	struct fcoe_kwqe_conn_offload1 ofld_req1;
+	struct fcoe_kwqe_conn_offload2 ofld_req2;
+	struct fcoe_kwqe_conn_offload3 ofld_req3;
+	struct fcoe_kwqe_conn_offload4 ofld_req4;
+	struct fc_rport_priv *rdata = tgt->rdata;
+	struct fc_rport *rport = tgt->rport;
+	int num_kwqes = 4;
+	u32 port_id;
+	int rc = 0;
+	u16 conn_id;
+
+	/* Initialize offload request 1 structure */
+	memset(&ofld_req1, 0x00, sizeof(struct fcoe_kwqe_conn_offload1));
+
+	ofld_req1.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN1;
+	ofld_req1.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+
+	conn_id = (u16)tgt->fcoe_conn_id;
+	ofld_req1.fcoe_conn_id = conn_id;
+
+
+	ofld_req1.sq_addr_lo = (u32) tgt->sq_dma;
+	ofld_req1.sq_addr_hi = (u32)((u64) tgt->sq_dma >> 32);
+
+	ofld_req1.rq_pbl_addr_lo = (u32) tgt->rq_pbl_dma;
+	ofld_req1.rq_pbl_addr_hi = (u32)((u64) tgt->rq_pbl_dma >> 32);
+
+	ofld_req1.rq_first_pbe_addr_lo = (u32) tgt->rq_dma;
+	ofld_req1.rq_first_pbe_addr_hi =
+				(u32)((u64) tgt->rq_dma >> 32);
+
+	ofld_req1.rq_prod = 0x8000;
+
+	/* Initialize offload request 2 structure */
+	memset(&ofld_req2, 0x00, sizeof(struct fcoe_kwqe_conn_offload2));
+
+	ofld_req2.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN2;
+	ofld_req2.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	ofld_req2.tx_max_fc_pay_len = rdata->maxframe_size;
+
+	ofld_req2.cq_addr_lo = (u32) tgt->cq_dma;
+	ofld_req2.cq_addr_hi = (u32)((u64)tgt->cq_dma >> 32);
+
+	ofld_req2.xferq_addr_lo = (u32) tgt->xferq_dma;
+	ofld_req2.xferq_addr_hi = (u32)((u64)tgt->xferq_dma >> 32);
+
+	ofld_req2.conn_db_addr_lo = (u32)tgt->conn_db_dma;
+	ofld_req2.conn_db_addr_hi = (u32)((u64)tgt->conn_db_dma >> 32);
+
+	/* Initialize offload request 3 structure */
+	memset(&ofld_req3, 0x00, sizeof(struct fcoe_kwqe_conn_offload3));
+
+	ofld_req3.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN3;
+	ofld_req3.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	ofld_req3.vlan_tag = hba->vlan_id <<
+				FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT;
+	ofld_req3.vlan_tag |= 3 << FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT;
+
+	port_id = fc_host_port_id(lport->host);
+	if (port_id == 0) {
+		BNX2FC_HBA_DBG(lport, "ofld_req: port_id = 0, link down?\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Store s_id of the initiator for further reference. This will
+	 * be used during disable/destroy during linkdown processing as
+	 * when the lport is reset, the port_id also is reset to 0
+	 */
+	tgt->sid = port_id;
+	ofld_req3.s_id[0] = (port_id & 0x000000FF);
+	ofld_req3.s_id[1] = (port_id & 0x0000FF00) >> 8;
+	ofld_req3.s_id[2] = (port_id & 0x00FF0000) >> 16;
+
+	port_id = rport->port_id;
+	ofld_req3.d_id[0] = (port_id & 0x000000FF);
+	ofld_req3.d_id[1] = (port_id & 0x0000FF00) >> 8;
+	ofld_req3.d_id[2] = (port_id & 0x00FF0000) >> 16;
+
+	ofld_req3.tx_total_conc_seqs = rdata->max_seq;
+
+	ofld_req3.tx_max_conc_seqs_c3 = rdata->max_seq;
+	ofld_req3.rx_max_fc_pay_len  = lport->mfs;
+
+	ofld_req3.rx_total_conc_seqs = BNX2FC_MAX_SEQS;
+	ofld_req3.rx_max_conc_seqs_c3 = BNX2FC_MAX_SEQS;
+	ofld_req3.rx_open_seqs_exch_c3 = 1;
+
+	ofld_req3.confq_first_pbe_addr_lo = tgt->confq_dma;
+	ofld_req3.confq_first_pbe_addr_hi = (u32)((u64) tgt->confq_dma >> 32);
+
+	/* set mul_n_port_ids supported flag to 0, until it is supported */
+	ofld_req3.flags = 0;
+	/*
+	ofld_req3.flags |= (((lport->send_sp_features & FC_SP_FT_MNA) ? 1:0) <<
+			    FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT);
+	*/
+	/* Info from PLOGI response */
+	ofld_req3.flags |= (((rdata->sp_features & FC_SP_FT_EDTR) ? 1 : 0) <<
+			     FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT);
+
+	ofld_req3.flags |= (((rdata->sp_features & FC_SP_FT_SEQC) ? 1 : 0) <<
+			     FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT);
+
+	/* vlan flag */
+	ofld_req3.flags |= (hba->vlan_enabled <<
+			    FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
+
+	/* C2_VALID and ACK flags are not set as they are not suppported */
+
+
+	/* Initialize offload request 4 structure */
+	memset(&ofld_req4, 0x00, sizeof(struct fcoe_kwqe_conn_offload4));
+	ofld_req4.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN4;
+	ofld_req4.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	ofld_req4.e_d_tov_timer_val = lport->e_d_tov / 20;
+
+
+	ofld_req4.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+							/* local mac */
+	ofld_req4.src_mac_addr_lo32[1] =  port->data_src_addr[4];
+	ofld_req4.src_mac_addr_lo32[2] =  port->data_src_addr[3];
+	ofld_req4.src_mac_addr_lo32[3] =  port->data_src_addr[2];
+	ofld_req4.src_mac_addr_hi16[0] =  port->data_src_addr[1];
+	ofld_req4.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+	ofld_req4.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	ofld_req4.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
+	ofld_req4.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
+	ofld_req4.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
+	ofld_req4.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
+	ofld_req4.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+
+	ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
+	ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
+
+	ofld_req4.confq_pbl_base_addr_lo = (u32) tgt->confq_pbl_dma;
+	ofld_req4.confq_pbl_base_addr_hi =
+					(u32)((u64) tgt->confq_pbl_dma >> 32);
+
+	kwqe_arr[0] = (struct kwqe *) &ofld_req1;
+	kwqe_arr[1] = (struct kwqe *) &ofld_req2;
+	kwqe_arr[2] = (struct kwqe *) &ofld_req3;
+	kwqe_arr[3] = (struct kwqe *) &ofld_req4;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_enable_req - initiates FCoE Session enablement
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt)
+{
+	struct kwqe *kwqe_arr[2];
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_kwqe_conn_enable_disable enbl_req;
+	struct fc_lport *lport = port->lport;
+	struct fc_rport *rport = tgt->rport;
+	int num_kwqes = 1;
+	int rc = 0;
+	u32 port_id;
+
+	memset(&enbl_req, 0x00,
+	       sizeof(struct fcoe_kwqe_conn_enable_disable));
+	enbl_req.hdr.op_code = FCOE_KWQE_OPCODE_ENABLE_CONN;
+	enbl_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	enbl_req.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+							/* local mac */
+	enbl_req.src_mac_addr_lo32[1] =  port->data_src_addr[4];
+	enbl_req.src_mac_addr_lo32[2] =  port->data_src_addr[3];
+	enbl_req.src_mac_addr_lo32[3] =  port->data_src_addr[2];
+	enbl_req.src_mac_addr_hi16[0] =  port->data_src_addr[1];
+	enbl_req.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+
+	enbl_req.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	enbl_req.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
+	enbl_req.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
+	enbl_req.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
+	enbl_req.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
+	enbl_req.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+
+	port_id = fc_host_port_id(lport->host);
+	if (port_id != tgt->sid) {
+		printk(KERN_ERR PFX "WARN: enable_req port_id = 0x%x,"
+				"sid = 0x%x\n", port_id, tgt->sid);
+		port_id = tgt->sid;
+	}
+	enbl_req.s_id[0] = (port_id & 0x000000FF);
+	enbl_req.s_id[1] = (port_id & 0x0000FF00) >> 8;
+	enbl_req.s_id[2] = (port_id & 0x00FF0000) >> 16;
+
+	port_id = rport->port_id;
+	enbl_req.d_id[0] = (port_id & 0x000000FF);
+	enbl_req.d_id[1] = (port_id & 0x0000FF00) >> 8;
+	enbl_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
+	enbl_req.vlan_tag = hba->vlan_id <<
+				FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
+	enbl_req.vlan_tag |= 3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
+	enbl_req.vlan_flag = hba->vlan_enabled;
+	enbl_req.context_id = tgt->context_id;
+	enbl_req.conn_id = tgt->fcoe_conn_id;
+
+	kwqe_arr[0] = (struct kwqe *) &enbl_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_disable_req - initiates FCoE Session disable
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+int bnx2fc_send_session_disable_req(struct fcoe_port *port,
+				    struct bnx2fc_rport *tgt)
+{
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_kwqe_conn_enable_disable disable_req;
+	struct kwqe *kwqe_arr[2];
+	struct fc_rport *rport = tgt->rport;
+	int num_kwqes = 1;
+	int rc = 0;
+	u32 port_id;
+
+	memset(&disable_req, 0x00,
+	       sizeof(struct fcoe_kwqe_conn_enable_disable));
+	disable_req.hdr.op_code = FCOE_KWQE_OPCODE_DISABLE_CONN;
+	disable_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	disable_req.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+	disable_req.src_mac_addr_lo32[2] =  port->data_src_addr[3];
+	disable_req.src_mac_addr_lo32[3] =  port->data_src_addr[2];
+	disable_req.src_mac_addr_hi16[0] =  port->data_src_addr[1];
+	disable_req.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+
+	disable_req.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	disable_req.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
+	disable_req.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
+	disable_req.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
+	disable_req.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
+	disable_req.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+
+	port_id = tgt->sid;
+	disable_req.s_id[0] = (port_id & 0x000000FF);
+	disable_req.s_id[1] = (port_id & 0x0000FF00) >> 8;
+	disable_req.s_id[2] = (port_id & 0x00FF0000) >> 16;
+
+
+	port_id = rport->port_id;
+	disable_req.d_id[0] = (port_id & 0x000000FF);
+	disable_req.d_id[1] = (port_id & 0x0000FF00) >> 8;
+	disable_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
+	disable_req.context_id = tgt->context_id;
+	disable_req.conn_id = tgt->fcoe_conn_id;
+	disable_req.vlan_tag = hba->vlan_id <<
+				FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
+	disable_req.vlan_tag |=
+			3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
+	disable_req.vlan_flag = hba->vlan_enabled;
+
+	kwqe_arr[0] = (struct kwqe *) &disable_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_destroy_req - initiates FCoE Session destroy
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
+					struct bnx2fc_rport *tgt)
+{
+	struct fcoe_kwqe_conn_destroy destroy_req;
+	struct kwqe *kwqe_arr[2];
+	int num_kwqes = 1;
+	int rc = 0;
+
+	memset(&destroy_req, 0x00, sizeof(struct fcoe_kwqe_conn_destroy));
+	destroy_req.hdr.op_code = FCOE_KWQE_OPCODE_DESTROY_CONN;
+	destroy_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	destroy_req.context_id = tgt->context_id;
+	destroy_req.conn_id = tgt->fcoe_conn_id;
+
+	kwqe_arr[0] = (struct kwqe *) &destroy_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+static void bnx2fc_unsol_els_work(struct work_struct *work)
+{
+	struct bnx2fc_unsol_els *unsol_els;
+	struct fc_lport *lport;
+	struct fc_frame *fp;
+
+	unsol_els = container_of(work, struct bnx2fc_unsol_els, unsol_els_work);
+	lport = unsol_els->lport;
+	fp = unsol_els->fp;
+	fc_exch_recv(lport, fp);
+	kfree(unsol_els);
+}
+
+void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
+				   unsigned char *buf,
+				   u32 frame_len, u16 l2_oxid)
+{
+	struct fcoe_port *port = tgt->port;
+	struct fc_lport *lport = port->lport;
+	struct bnx2fc_unsol_els *unsol_els;
+	struct fc_frame_header *fh;
+	struct fc_frame *fp;
+	struct sk_buff *skb;
+	u32 payload_len;
+	u32 crc;
+	u8 op;
+
+
+	unsol_els = kzalloc(sizeof(*unsol_els), GFP_ATOMIC);
+	if (!unsol_els) {
+		BNX2FC_TGT_DBG(tgt, "Unable to allocate unsol_work\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, "l2_frame_compl l2_oxid = 0x%x, frame_len = %d\n",
+		l2_oxid, frame_len);
+
+	payload_len = frame_len - sizeof(struct fc_frame_header);
+
+	fp = fc_frame_alloc(lport, payload_len);
+	if (!fp) {
+		printk(KERN_ERR PFX "fc_frame_alloc failure\n");
+		return;
+	}
+
+	fh = (struct fc_frame_header *) fc_frame_header_get(fp);
+	/* Copy FC Frame header and payload into the frame */
+	memcpy(fh, buf, frame_len);
+
+	if (l2_oxid != FC_XID_UNKNOWN)
+		fh->fh_ox_id = htons(l2_oxid);
+
+	skb = fp_skb(fp);
+
+	if ((fh->fh_r_ctl == FC_RCTL_ELS_REQ) ||
+	    (fh->fh_r_ctl == FC_RCTL_ELS_REP)) {
+
+		if (fh->fh_type == FC_TYPE_ELS) {
+			op = fc_frame_payload_op(fp);
+			if ((op == ELS_TEST) ||	(op == ELS_ESTC) ||
+			    (op == ELS_FAN) || (op == ELS_CSU)) {
+				/*
+				 * No need to reply for these
+				 * ELS requests
+				 */
+				printk(KERN_ERR PFX "dropping ELS 0x%x\n", op);
+				kfree_skb(skb);
+				return;
+			}
+		}
+		crc = fcoe_fc_crc(fp);
+		fc_frame_init(fp);
+		fr_dev(fp) = lport;
+		fr_sof(fp) = FC_SOF_I3;
+		fr_eof(fp) = FC_EOF_T;
+		fr_crc(fp) = cpu_to_le32(~crc);
+		unsol_els->lport = lport;
+		unsol_els->fp = fp;
+		INIT_WORK(&unsol_els->unsol_els_work, bnx2fc_unsol_els_work);
+		queue_work(bnx2fc_wq, &unsol_els->unsol_els_work);
+	} else {
+		BNX2FC_HBA_DBG(lport, "fh_r_ctl = 0x%x\n", fh->fh_r_ctl);
+		kfree_skb(skb);
+	}
+}
+
+static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
+{
+	u8 num_rq;
+	struct fcoe_err_report_entry *err_entry;
+	unsigned char *rq_data;
+	unsigned char *buf = NULL, *buf1;
+	int i;
+	u16 xid;
+	u32 frame_len, len;
+	struct bnx2fc_cmd *io_req = NULL;
+	struct fcoe_task_ctx_entry *task, *task_page;
+	struct bnx2fc_hba *hba = tgt->port->priv;
+	int task_idx, index;
+	int rc = 0;
+
+
+	BNX2FC_TGT_DBG(tgt, "Entered UNSOL COMPLETION wqe = 0x%x\n", wqe);
+	switch (wqe & FCOE_UNSOLICITED_CQE_SUBTYPE) {
+	case FCOE_UNSOLICITED_FRAME_CQE_TYPE:
+		frame_len = (wqe & FCOE_UNSOLICITED_CQE_PKT_LEN) >>
+			     FCOE_UNSOLICITED_CQE_PKT_LEN_SHIFT;
+
+		num_rq = (frame_len + BNX2FC_RQ_BUF_SZ - 1) / BNX2FC_RQ_BUF_SZ;
+
+		rq_data = (unsigned char *)bnx2fc_get_next_rqe(tgt, num_rq);
+		if (rq_data) {
+			buf = rq_data;
+		} else {
+			buf1 = buf = kmalloc((num_rq * BNX2FC_RQ_BUF_SZ),
+					      GFP_ATOMIC);
+
+			if (!buf1) {
+				BNX2FC_TGT_DBG(tgt, "Memory alloc failure\n");
+				break;
+			}
+
+			for (i = 0; i < num_rq; i++) {
+				rq_data = (unsigned char *)
+					   bnx2fc_get_next_rqe(tgt, 1);
+				len = BNX2FC_RQ_BUF_SZ;
+				memcpy(buf1, rq_data, len);
+				buf1 += len;
+			}
+		}
+		bnx2fc_process_l2_frame_compl(tgt, buf, frame_len,
+					      FC_XID_UNKNOWN);
+
+		if (buf != rq_data)
+			kfree(buf);
+		bnx2fc_return_rqe(tgt, num_rq);
+		break;
+
+	case FCOE_ERROR_DETECTION_CQE_TYPE:
+		/*
+		 *In case of error reporting CQE a single RQ entry
+		 * is consumes.
+		 */
+		spin_lock_bh(&tgt->tgt_lock);
+		num_rq = 1;
+		err_entry = (struct fcoe_err_report_entry *)
+			     bnx2fc_get_next_rqe(tgt, 1);
+		xid = err_entry->fc_hdr.ox_id;
+		BNX2FC_TGT_DBG(tgt, "Unsol Error Frame OX_ID = 0x%x\n", xid);
+		BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x\n",
+			err_entry->err_warn_bitmap_hi,
+			err_entry->err_warn_bitmap_lo);
+		BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
+			err_entry->tx_buf_off, err_entry->rx_buf_off);
+
+		bnx2fc_return_rqe(tgt, 1);
+
+		if (xid > BNX2FC_MAX_XID) {
+			BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n",
+				   xid);
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+		index = xid % BNX2FC_TASKS_PER_PAGE;
+		task_page = (struct fcoe_task_ctx_entry *)
+						hba->task_ctx[task_idx];
+		task = &(task_page[index]);
+
+		io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
+		if (!io_req) {
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		if (io_req->cmd_type != BNX2FC_SCSI_CMD) {
+			printk(KERN_ERR PFX "err_warn: Not a SCSI cmd\n");
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		if (test_and_clear_bit(BNX2FC_FLAG_IO_CLEANUP,
+				       &io_req->req_flags)) {
+			BNX2FC_IO_DBG(io_req, "unsol_err: cleanup in "
+					    "progress.. ignore unsol err\n");
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		/*
+		 * If ABTS is already in progress, and FW error is
+		 * received after that, do not cancel the timeout_work
+		 * and let the error recovery continue by explicitly
+		 * logging out the target, when the ABTS eventually
+		 * times out.
+		 */
+		if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+				      &io_req->req_flags)) {
+			/*
+			 * Cancel the timeout_work, as we received IO
+			 * completion with FW error.
+			 */
+			if (cancel_delayed_work(&io_req->timeout_work))
+				kref_put(&io_req->refcount,
+					 bnx2fc_cmd_release); /* timer hold */
+
+			rc = bnx2fc_initiate_abts(io_req);
+			if (rc != SUCCESS) {
+				BNX2FC_IO_DBG(io_req, "err_warn: initiate_abts "
+					"failed. issue cleanup\n");
+				rc = bnx2fc_initiate_cleanup(io_req);
+				BUG_ON(rc);
+			}
+		} else
+			printk(KERN_ERR PFX "err_warn: io_req (0x%x) already "
+					    "in ABTS processing\n", xid);
+		spin_unlock_bh(&tgt->tgt_lock);
+		break;
+
+	case FCOE_WARNING_DETECTION_CQE_TYPE:
+		/*
+		 *In case of warning reporting CQE a single RQ entry
+		 * is consumes.
+		 */
+		num_rq = 1;
+		err_entry = (struct fcoe_err_report_entry *)
+			     bnx2fc_get_next_rqe(tgt, 1);
+		xid = cpu_to_be16(err_entry->fc_hdr.ox_id);
+		BNX2FC_TGT_DBG(tgt, "Unsol Warning Frame OX_ID = 0x%x\n", xid);
+		BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x",
+			err_entry->err_warn_bitmap_hi,
+			err_entry->err_warn_bitmap_lo);
+		BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
+			err_entry->tx_buf_off, err_entry->rx_buf_off);
+
+		bnx2fc_return_rqe(tgt, 1);
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unsol Compl: Invalid CQE Subtype\n");
+		break;
+	}
+}
+
+void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
+{
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_cmd *io_req;
+	int task_idx, index;
+	u16 xid;
+	u8  cmd_type;
+	u8 rx_state = 0;
+	u8 num_rq;
+
+	spin_lock_bh(&tgt->tgt_lock);
+	xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
+	if (xid >= BNX2FC_MAX_TASKS) {
+		printk(KERN_ALERT PFX "ERROR:xid out of range\n");
+		spin_unlock_bh(&tgt->tgt_lock);
+		return;
+	}
+	task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+	task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+
+	num_rq = ((task->rx_wr_tx_rd.rx_flags &
+		   FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE) >>
+		   FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT);
+
+	io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
+
+	if (io_req == NULL) {
+		printk(KERN_ERR PFX "ERROR? cq_compl - io_req is NULL\n");
+		spin_unlock_bh(&tgt->tgt_lock);
+		return;
+	}
+
+	/* Timestamp IO completion time */
+	cmd_type = io_req->cmd_type;
+
+	/* optimized completion path */
+	if (cmd_type == BNX2FC_SCSI_CMD) {
+		rx_state = ((task->rx_wr_tx_rd.rx_flags &
+			    FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE) >>
+			    FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT);
+
+		if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
+			bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
+			spin_unlock_bh(&tgt->tgt_lock);
+			return;
+		}
+	}
+
+	/* Process other IO completion types */
+	switch (cmd_type) {
+	case BNX2FC_SCSI_CMD:
+		if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
+			bnx2fc_process_abts_compl(io_req, task, num_rq);
+		else if (rx_state ==
+			 FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED)
+			bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+		else
+			printk(KERN_ERR PFX "Invalid rx state - %d\n",
+				rx_state);
+		break;
+
+	case BNX2FC_TASK_MGMT_CMD:
+		BNX2FC_IO_DBG(io_req, "Processing TM complete\n");
+		bnx2fc_process_tm_compl(io_req, task, num_rq);
+		break;
+
+	case BNX2FC_ABTS:
+		/*
+		 * ABTS request received by firmware. ABTS response
+		 * will be delivered to the task belonging to the IO
+		 * that was aborted
+		 */
+		BNX2FC_IO_DBG(io_req, "cq_compl- ABTS sent out by fw\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		break;
+
+	case BNX2FC_ELS:
+		BNX2FC_IO_DBG(io_req, "cq_compl - call process_els_compl\n");
+		bnx2fc_process_els_compl(io_req, task, num_rq);
+		break;
+
+	case BNX2FC_CLEANUP:
+		BNX2FC_IO_DBG(io_req, "cq_compl- cleanup resp rcvd\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Invalid cmd_type %d\n", cmd_type);
+		break;
+	}
+	spin_unlock_bh(&tgt->tgt_lock);
+}
+
+struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
+{
+	struct bnx2fc_work *work;
+	work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC);
+	if (!work)
+		return NULL;
+
+	INIT_LIST_HEAD(&work->list);
+	work->tgt = tgt;
+	work->wqe = wqe;
+	return work;
+}
+
+int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
+{
+	struct fcoe_cqe *cq;
+	u32 cq_cons;
+	struct fcoe_cqe *cqe;
+	u16 wqe;
+	bool more_cqes_found = false;
+
+	/*
+	 * cq_lock is a low contention lock used to protect
+	 * the CQ data structure from being freed up during
+	 * the upload operation
+	 */
+	spin_lock_bh(&tgt->cq_lock);
+
+	if (!tgt->cq) {
+		printk(KERN_ERR PFX "process_new_cqes: cq is NULL\n");
+		spin_unlock_bh(&tgt->cq_lock);
+		return 0;
+	}
+	cq = tgt->cq;
+	cq_cons = tgt->cq_cons_idx;
+	cqe = &cq[cq_cons];
+
+	do {
+		more_cqes_found ^= true;
+
+		while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
+		       (tgt->cq_curr_toggle_bit <<
+		       FCOE_CQE_TOGGLE_BIT_SHIFT)) {
+
+			/* new entry on the cq */
+			if (wqe & FCOE_CQE_CQE_TYPE) {
+				/* Unsolicited event notification */
+				bnx2fc_process_unsol_compl(tgt, wqe);
+			} else {
+				struct bnx2fc_work *work = NULL;
+				struct bnx2fc_percpu_s *fps = NULL;
+				unsigned int cpu = wqe % num_possible_cpus();
+
+				fps = &per_cpu(bnx2fc_percpu, cpu);
+				spin_lock_bh(&fps->fp_work_lock);
+				if (unlikely(!fps->iothread))
+					goto unlock;
+
+				work = bnx2fc_alloc_work(tgt, wqe);
+				if (work)
+					list_add_tail(&work->list,
+							&fps->work_list);
+unlock:
+				spin_unlock_bh(&fps->fp_work_lock);
+
+				/* Pending work request completion */
+				if (fps->iothread && work)
+					wake_up_process(fps->iothread);
+				else
+					bnx2fc_process_cq_compl(tgt, wqe);
+			}
+			cqe++;
+			tgt->cq_cons_idx++;
+
+			if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
+				tgt->cq_cons_idx = 0;
+				cqe = cq;
+				tgt->cq_curr_toggle_bit =
+					1 - tgt->cq_curr_toggle_bit;
+			}
+		}
+		/* Re-arm CQ */
+		if (more_cqes_found) {
+			tgt->conn_db->cq_arm.lo = -1;
+			wmb();
+		}
+	} while (more_cqes_found);
+
+	/*
+	 * Commit tgt->cq_cons_idx change to the memory
+	 * spin_lock implies full memory barrier, no need to smp_wmb
+	 */
+
+	spin_unlock_bh(&tgt->cq_lock);
+	return 0;
+}
+
+/**
+ * bnx2fc_fastpath_notification - process global event queue (KCQ)
+ *
+ * @hba:		adapter structure pointer
+ * @new_cqe_kcqe:	pointer to newly DMA'd KCQ entry
+ *
+ * Fast path event notification handler
+ */
+static void bnx2fc_fastpath_notification(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *new_cqe_kcqe)
+{
+	u32 conn_id = new_cqe_kcqe->fcoe_conn_id;
+	struct bnx2fc_rport *tgt = hba->tgt_ofld_list[conn_id];
+
+	if (!tgt) {
+		printk(KERN_ALERT PFX "conn_id 0x%x not valid\n", conn_id);
+		return;
+	}
+
+	bnx2fc_process_new_cqes(tgt);
+}
+
+/**
+ * bnx2fc_process_ofld_cmpl - process FCoE session offload completion
+ *
+ * @hba:	adapter structure pointer
+ * @ofld_kcqe:	connection offload kcqe pointer
+ *
+ * handle session offload completion, enable the session if offload is
+ * successful.
+ */
+static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *ofld_kcqe)
+{
+	struct bnx2fc_rport		*tgt;
+	struct fcoe_port		*port;
+	u32				conn_id;
+	u32				context_id;
+	int				rc;
+
+	conn_id = ofld_kcqe->fcoe_conn_id;
+	context_id = ofld_kcqe->fcoe_conn_context_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "ERROR:ofld_cmpl: No pending ofld req\n");
+		return;
+	}
+	BNX2FC_TGT_DBG(tgt, "Entered ofld compl - context_id = 0x%x\n",
+		ofld_kcqe->fcoe_conn_context_id);
+	port = tgt->port;
+	if (hba != tgt->port->priv) {
+		printk(KERN_ALERT PFX "ERROR:ofld_cmpl: HBA mis-match\n");
+		goto ofld_cmpl_err;
+	}
+	/*
+	 * cnic has allocated a context_id for this session; use this
+	 * while enabling the session.
+	 */
+	tgt->context_id = context_id;
+	if (ofld_kcqe->completion_status) {
+		if (ofld_kcqe->completion_status ==
+				FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE) {
+			printk(KERN_ERR PFX "unable to allocate FCoE context "
+				"resources\n");
+			set_bit(BNX2FC_FLAG_CTX_ALLOC_FAILURE, &tgt->flags);
+		}
+		goto ofld_cmpl_err;
+	} else {
+
+		/* now enable the session */
+		rc = bnx2fc_send_session_enable_req(port, tgt);
+		if (rc) {
+			printk(KERN_ALERT PFX "enable session failed\n");
+			goto ofld_cmpl_err;
+		}
+	}
+	return;
+ofld_cmpl_err:
+	set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->ofld_wait);
+}
+
+/**
+ * bnx2fc_process_enable_conn_cmpl - process FCoE session enable completion
+ *
+ * @hba:	adapter structure pointer
+ * @ofld_kcqe:	connection offload kcqe pointer
+ *
+ * handle session enable completion, mark the rport as ready
+ */
+
+static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
+						struct fcoe_kcqe *ofld_kcqe)
+{
+	struct bnx2fc_rport		*tgt;
+	u32				conn_id;
+	u32				context_id;
+
+	context_id = ofld_kcqe->fcoe_conn_context_id;
+	conn_id = ofld_kcqe->fcoe_conn_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "ERROR:enbl_cmpl: No pending ofld req\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, "Enable compl - context_id = 0x%x\n",
+		ofld_kcqe->fcoe_conn_context_id);
+
+	/*
+	 * context_id should be the same for this target during offload
+	 * and enable
+	 */
+	if (tgt->context_id != context_id) {
+		printk(KERN_ALERT PFX "context id mis-match\n");
+		return;
+	}
+	if (hba != tgt->port->priv) {
+		printk(KERN_ALERT PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
+		goto enbl_cmpl_err;
+	}
+	if (ofld_kcqe->completion_status) {
+		goto enbl_cmpl_err;
+	} else {
+		/* enable successful - rport ready for issuing IOs */
+		set_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+		wake_up_interruptible(&tgt->ofld_wait);
+	}
+	return;
+
+enbl_cmpl_err:
+	set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->ofld_wait);
+}
+
+static void bnx2fc_process_conn_disable_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *disable_kcqe)
+{
+
+	struct bnx2fc_rport		*tgt;
+	u32				conn_id;
+
+	conn_id = disable_kcqe->fcoe_conn_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "ERROR: disable_cmpl: No disable req\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, PFX "disable_cmpl: conn_id %d\n", conn_id);
+
+	if (disable_kcqe->completion_status) {
+		printk(KERN_ALERT PFX "ERROR: Disable failed with cmpl status %d\n",
+			disable_kcqe->completion_status);
+		return;
+	} else {
+		/* disable successful */
+		BNX2FC_TGT_DBG(tgt, "disable successful\n");
+		clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_DISABLED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+		wake_up_interruptible(&tgt->upld_wait);
+	}
+}
+
+static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *destroy_kcqe)
+{
+	struct bnx2fc_rport		*tgt;
+	u32				conn_id;
+
+	conn_id = destroy_kcqe->fcoe_conn_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "destroy_cmpl: No destroy req\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, "destroy_cmpl: conn_id %d\n", conn_id);
+
+	if (destroy_kcqe->completion_status) {
+		printk(KERN_ALERT PFX "Destroy conn failed, cmpl status %d\n",
+			destroy_kcqe->completion_status);
+		return;
+	} else {
+		/* destroy successful */
+		BNX2FC_TGT_DBG(tgt, "upload successful\n");
+		clear_bit(BNX2FC_FLAG_DISABLED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_DESTROYED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+		wake_up_interruptible(&tgt->upld_wait);
+	}
+}
+
+static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code)
+{
+	switch (err_code) {
+	case FCOE_KCQE_COMPLETION_STATUS_INVALID_OPCODE:
+		printk(KERN_ERR PFX "init_failure due to invalid opcode\n");
+		break;
+
+	case FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE:
+		printk(KERN_ERR PFX "init failed due to ctx alloc failure\n");
+		break;
+
+	case FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR:
+		printk(KERN_ERR PFX "init_failure due to NIC error\n");
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
+	}
+}
+
+/**
+ * bnx2fc_indicae_kcqe - process KCQE
+ *
+ * @hba:	adapter structure pointer
+ * @kcqe:	kcqe pointer
+ * @num_cqe:	Number of completion queue elements
+ *
+ * Generic KCQ event handler
+ */
+void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
+					u32 num_cqe)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
+	int i = 0;
+	struct fcoe_kcqe *kcqe = NULL;
+
+	while (i < num_cqe) {
+		kcqe = (struct fcoe_kcqe *) kcq[i++];
+
+		switch (kcqe->op_code) {
+		case FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION:
+			bnx2fc_fastpath_notification(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_OFFLOAD_CONN:
+			bnx2fc_process_ofld_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_ENABLE_CONN:
+			bnx2fc_process_enable_conn_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_INIT_FUNC:
+			if (kcqe->completion_status !=
+					FCOE_KCQE_COMPLETION_STATUS_SUCCESS) {
+				bnx2fc_init_failure(hba,
+						kcqe->completion_status);
+			} else {
+				set_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+				bnx2fc_get_link_state(hba);
+				printk(KERN_INFO PFX "[%.2x]: FCOE_INIT passed\n",
+					(u8)hba->pcidev->bus->number);
+			}
+			break;
+
+		case FCOE_KCQE_OPCODE_DESTROY_FUNC:
+			if (kcqe->completion_status !=
+					FCOE_KCQE_COMPLETION_STATUS_SUCCESS) {
+
+				printk(KERN_ERR PFX "DESTROY failed\n");
+			} else {
+				printk(KERN_ERR PFX "DESTROY success\n");
+			}
+			hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+			wake_up_interruptible(&hba->destroy_wait);
+			break;
+
+		case FCOE_KCQE_OPCODE_DISABLE_CONN:
+			bnx2fc_process_conn_disable_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_DESTROY_CONN:
+			bnx2fc_process_conn_destroy_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_STAT_FUNC:
+			if (kcqe->completion_status !=
+			    FCOE_KCQE_COMPLETION_STATUS_SUCCESS)
+				printk(KERN_ERR PFX "STAT failed\n");
+			complete(&hba->stat_req_done);
+			break;
+
+		case FCOE_KCQE_OPCODE_FCOE_ERROR:
+			/* fall thru */
+		default:
+			printk(KERN_ALERT PFX "unknown opcode 0x%x\n",
+								kcqe->op_code);
+		}
+	}
+}
+
+void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid)
+{
+	struct fcoe_sqe *sqe;
+
+	sqe = &tgt->sq[tgt->sq_prod_idx];
+
+	/* Fill SQ WQE */
+	sqe->wqe = xid << FCOE_SQE_TASK_ID_SHIFT;
+	sqe->wqe |= tgt->sq_curr_toggle_bit << FCOE_SQE_TOGGLE_BIT_SHIFT;
+
+	/* Advance SQ Prod Idx */
+	if (++tgt->sq_prod_idx == BNX2FC_SQ_WQES_MAX) {
+		tgt->sq_prod_idx = 0;
+		tgt->sq_curr_toggle_bit = 1 - tgt->sq_curr_toggle_bit;
+	}
+}
+
+void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt)
+{
+	struct b577xx_doorbell_set_prod ev_doorbell;
+	u32 msg;
+
+	wmb();
+
+	memset(&ev_doorbell, 0, sizeof(struct b577xx_doorbell_set_prod));
+	ev_doorbell.header.header = B577XX_DOORBELL_HDR_DB_TYPE;
+
+	ev_doorbell.prod = tgt->sq_prod_idx |
+				(tgt->sq_curr_toggle_bit << 15);
+	ev_doorbell.header.header |= B577XX_FCOE_CONNECTION_TYPE <<
+					B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
+	msg = *((u32 *)&ev_doorbell);
+	writel(cpu_to_le32(msg), tgt->ctx_base);
+
+	mmiowb();
+
+}
+
+int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt)
+{
+	u32 context_id = tgt->context_id;
+	struct fcoe_port *port = tgt->port;
+	u32 reg_off;
+	resource_size_t reg_base;
+	struct bnx2fc_hba *hba = port->priv;
+
+	reg_base = pci_resource_start(hba->pcidev,
+					BNX2X_DOORBELL_PCI_BAR);
+	reg_off = BNX2FC_5771X_DB_PAGE_SIZE *
+			(context_id & 0x1FFFF) + DPM_TRIGER_TYPE;
+	tgt->ctx_base = ioremap_nocache(reg_base + reg_off, 4);
+	if (!tgt->ctx_base)
+		return -ENOMEM;
+	return 0;
+}
+
+char *bnx2fc_get_next_rqe(struct bnx2fc_rport *tgt, u8 num_items)
+{
+	char *buf = (char *)tgt->rq + (tgt->rq_cons_idx * BNX2FC_RQ_BUF_SZ);
+
+	if (tgt->rq_cons_idx + num_items > BNX2FC_RQ_WQES_MAX)
+		return NULL;
+
+	tgt->rq_cons_idx += num_items;
+
+	if (tgt->rq_cons_idx >= BNX2FC_RQ_WQES_MAX)
+		tgt->rq_cons_idx -= BNX2FC_RQ_WQES_MAX;
+
+	return buf;
+}
+
+void bnx2fc_return_rqe(struct bnx2fc_rport *tgt, u8 num_items)
+{
+	/* return the rq buffer */
+	u32 next_prod_idx = tgt->rq_prod_idx + num_items;
+	if ((next_prod_idx & 0x7fff) == BNX2FC_RQ_WQES_MAX) {
+		/* Wrap around RQ */
+		next_prod_idx += 0x8000 - BNX2FC_RQ_WQES_MAX;
+	}
+	tgt->rq_prod_idx = next_prod_idx;
+	tgt->conn_db->rq_prod = tgt->rq_prod_idx;
+}
+
+void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
+			      struct fcoe_task_ctx_entry *task,
+			      u16 orig_xid)
+{
+	u8 task_type = FCOE_TASK_TYPE_EXCHANGE_CLEANUP;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	u32 context_id = tgt->context_id;
+
+	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+	/* Tx Write Rx Read */
+	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
+	task->tx_wr_rx_rd.init_flags = task_type <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+	/* Common */
+	task->cmn.common_flags = context_id <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
+	task->cmn.general.cleanup_info.task_id = orig_xid;
+
+
+}
+
+void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
+				struct fcoe_task_ctx_entry *task)
+{
+	struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct fc_frame_header *fc_hdr;
+	u8 task_type = 0;
+	u64 *hdr;
+	u64 temp_hdr[3];
+	u32 context_id;
+
+
+	/* Obtain task_type */
+	if ((io_req->cmd_type == BNX2FC_TASK_MGMT_CMD) ||
+	    (io_req->cmd_type == BNX2FC_ELS)) {
+		task_type = FCOE_TASK_TYPE_MIDPATH;
+	} else if (io_req->cmd_type == BNX2FC_ABTS) {
+		task_type = FCOE_TASK_TYPE_ABTS;
+	}
+
+	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+	/* Setup the task from io_req for easy reference */
+	io_req->task = task;
+
+	BNX2FC_IO_DBG(io_req, "Init MP task for cmd_type = %d task_type = %d\n",
+		io_req->cmd_type, task_type);
+
+	/* Tx only */
+	if ((task_type == FCOE_TASK_TYPE_MIDPATH) ||
+	    (task_type == FCOE_TASK_TYPE_UNSOLICITED)) {
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+				(u32)mp_req->mp_req_bd_dma;
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+				(u32)((u64)mp_req->mp_req_bd_dma >> 32);
+		task->tx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+		BNX2FC_IO_DBG(io_req, "init_mp_task - bd_dma = 0x%llx\n",
+			      (unsigned long long)mp_req->mp_req_bd_dma);
+	}
+
+	/* Tx Write Rx Read */
+	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_INIT <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
+	task->tx_wr_rx_rd.init_flags = task_type <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+
+	/* Common */
+	task->cmn.data_2_trns = io_req->data_xfer_len;
+	context_id = tgt->context_id;
+	task->cmn.common_flags = context_id <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+			FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+
+	/* Rx Write Tx Read */
+	fc_hdr = &(mp_req->req_fc_hdr);
+	if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+		fc_hdr->fh_ox_id = cpu_to_be16(io_req->xid);
+		fc_hdr->fh_rx_id = htons(0xffff);
+		task->rx_wr_tx_rd.rx_id = 0xffff;
+	} else if (task_type == FCOE_TASK_TYPE_UNSOLICITED) {
+		fc_hdr->fh_rx_id = cpu_to_be16(io_req->xid);
+	}
+
+	/* Fill FC Header into middle path buffer */
+	hdr = (u64 *) &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	memcpy(temp_hdr, fc_hdr, sizeof(temp_hdr));
+	hdr[0] = cpu_to_be64(temp_hdr[0]);
+	hdr[1] = cpu_to_be64(temp_hdr[1]);
+	hdr[2] = cpu_to_be64(temp_hdr[2]);
+
+	/* Rx Only */
+	if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+
+		task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+				(u32)mp_req->mp_resp_bd_dma;
+		task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+				(u32)((u64)mp_req->mp_resp_bd_dma >> 32);
+		task->rx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+	}
+}
+
+void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task)
+{
+	u8 task_type;
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct io_bdt *bd_tbl = io_req->bd_tbl;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	u64 *fcp_cmnd;
+	u64 tmp_fcp_cmnd[4];
+	u32 context_id;
+	int cnt, i;
+	int bd_count;
+
+	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+	/* Setup the task from io_req for easy reference */
+	io_req->task = task;
+
+	if (sc_cmd->sc_data_direction == DMA_TO_DEVICE)
+		task_type = FCOE_TASK_TYPE_WRITE;
+	else
+		task_type = FCOE_TASK_TYPE_READ;
+
+	/* Tx only */
+	if (task_type == FCOE_TASK_TYPE_WRITE) {
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+				(u32)bd_tbl->bd_tbl_dma;
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+				(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+		task->tx_wr_only.sgl_ctx.mul_sges.sgl_size =
+				bd_tbl->bd_valid;
+	}
+
+	/*Tx Write Rx Read */
+	/* Init state to NORMAL */
+	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
+	task->tx_wr_rx_rd.init_flags = task_type <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+
+	/* Common */
+	task->cmn.data_2_trns = io_req->data_xfer_len;
+	context_id = tgt->context_id;
+	task->cmn.common_flags = context_id <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+			FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+
+	/* Set initiative ownership */
+	task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT;
+
+	/* Set initial seq counter */
+	task->cmn.tx_low_seq_cnt = 1;
+
+	/* Set state to "waiting for the first packet" */
+	task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME;
+
+	/* Fill FCP_CMND IU */
+	fcp_cmnd = (u64 *)
+		    task->cmn.general.cmd_info.fcp_cmd_payload.opaque;
+	bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
+
+	/* swap fcp_cmnd */
+	cnt = sizeof(struct fcp_cmnd) / sizeof(u64);
+
+	for (i = 0; i < cnt; i++) {
+		*fcp_cmnd = cpu_to_be64(tmp_fcp_cmnd[i]);
+		fcp_cmnd++;
+	}
+
+	/* Rx Write Tx Read */
+	task->rx_wr_tx_rd.rx_id = 0xffff;
+
+	/* Rx Only */
+	if (task_type == FCOE_TASK_TYPE_READ) {
+
+		bd_count = bd_tbl->bd_valid;
+		if (bd_count == 1) {
+
+			struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.lo =
+					fcoe_bd_tbl->buf_addr_lo;
+			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.hi =
+					fcoe_bd_tbl->buf_addr_hi;
+			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_rem =
+					fcoe_bd_tbl->buf_len;
+			task->tx_wr_rx_rd.init_flags |= 1 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT;
+		} else {
+
+			task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+					(u32)bd_tbl->bd_tbl_dma;
+			task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+					(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+			task->rx_wr_only.sgl_ctx.mul_sges.sgl_size =
+					bd_tbl->bd_valid;
+		}
+	}
+}
+
+/**
+ * bnx2fc_setup_task_ctx - allocate and map task context
+ *
+ * @hba:	pointer to adapter structure
+ *
+ * allocate memory for task context, and associated BD table to be used
+ * by firmware
+ *
+ */
+int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
+{
+	int rc = 0;
+	struct regpair *task_ctx_bdt;
+	dma_addr_t addr;
+	int i;
+
+	/*
+	 * Allocate task context bd table. A page size of bd table
+	 * can map 256 buffers. Each buffer contains 32 task context
+	 * entries. Hence the limit with one page is 8192 task context
+	 * entries.
+	 */
+	hba->task_ctx_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+						  PAGE_SIZE,
+						  &hba->task_ctx_bd_dma,
+						  GFP_KERNEL);
+	if (!hba->task_ctx_bd_tbl) {
+		printk(KERN_ERR PFX "unable to allocate task context BDT\n");
+		rc = -1;
+		goto out;
+	}
+	memset(hba->task_ctx_bd_tbl, 0, PAGE_SIZE);
+
+	/*
+	 * Allocate task_ctx which is an array of pointers pointing to
+	 * a page containing 32 task contexts
+	 */
+	hba->task_ctx = kzalloc((BNX2FC_TASK_CTX_ARR_SZ * sizeof(void *)),
+				 GFP_KERNEL);
+	if (!hba->task_ctx) {
+		printk(KERN_ERR PFX "unable to allocate task context array\n");
+		rc = -1;
+		goto out1;
+	}
+
+	/*
+	 * Allocate task_ctx_dma which is an array of dma addresses
+	 */
+	hba->task_ctx_dma = kmalloc((BNX2FC_TASK_CTX_ARR_SZ *
+					sizeof(dma_addr_t)), GFP_KERNEL);
+	if (!hba->task_ctx_dma) {
+		printk(KERN_ERR PFX "unable to alloc context mapping array\n");
+		rc = -1;
+		goto out2;
+	}
+
+	task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl;
+	for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+
+		hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev,
+						      PAGE_SIZE,
+						      &hba->task_ctx_dma[i],
+						      GFP_KERNEL);
+		if (!hba->task_ctx[i]) {
+			printk(KERN_ERR PFX "unable to alloc task context\n");
+			rc = -1;
+			goto out3;
+		}
+		memset(hba->task_ctx[i], 0, PAGE_SIZE);
+		addr = (u64)hba->task_ctx_dma[i];
+		task_ctx_bdt->hi = cpu_to_le32((u64)addr >> 32);
+		task_ctx_bdt->lo = cpu_to_le32((u32)addr);
+		task_ctx_bdt++;
+	}
+	return 0;
+
+out3:
+	for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+		if (hba->task_ctx[i]) {
+
+			dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				hba->task_ctx[i], hba->task_ctx_dma[i]);
+			hba->task_ctx[i] = NULL;
+		}
+	}
+
+	kfree(hba->task_ctx_dma);
+	hba->task_ctx_dma = NULL;
+out2:
+	kfree(hba->task_ctx);
+	hba->task_ctx = NULL;
+out1:
+	dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+			hba->task_ctx_bd_tbl, hba->task_ctx_bd_dma);
+	hba->task_ctx_bd_tbl = NULL;
+out:
+	return rc;
+}
+
+void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba)
+{
+	int i;
+
+	if (hba->task_ctx_bd_tbl) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				    hba->task_ctx_bd_tbl,
+				    hba->task_ctx_bd_dma);
+		hba->task_ctx_bd_tbl = NULL;
+	}
+
+	if (hba->task_ctx) {
+		for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+			if (hba->task_ctx[i]) {
+				dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+						    hba->task_ctx[i],
+						    hba->task_ctx_dma[i]);
+				hba->task_ctx[i] = NULL;
+			}
+		}
+		kfree(hba->task_ctx);
+		hba->task_ctx = NULL;
+	}
+
+	kfree(hba->task_ctx_dma);
+	hba->task_ctx_dma = NULL;
+}
+
+static void bnx2fc_free_hash_table(struct bnx2fc_hba *hba)
+{
+	int i;
+	int segment_count;
+	int hash_table_size;
+	u32 *pbl;
+
+	segment_count = hba->hash_tbl_segment_count;
+	hash_table_size = BNX2FC_NUM_MAX_SESS * BNX2FC_MAX_ROWS_IN_HASH_TBL *
+		sizeof(struct fcoe_hash_table_entry);
+
+	pbl = hba->hash_tbl_pbl;
+	for (i = 0; i < segment_count; ++i) {
+		dma_addr_t dma_address;
+
+		dma_address = le32_to_cpu(*pbl);
+		++pbl;
+		dma_address += ((u64)le32_to_cpu(*pbl)) << 32;
+		++pbl;
+		dma_free_coherent(&hba->pcidev->dev,
+				  BNX2FC_HASH_TBL_CHUNK_SIZE,
+				  hba->hash_tbl_segments[i],
+				  dma_address);
+
+	}
+
+	if (hba->hash_tbl_pbl) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				    hba->hash_tbl_pbl,
+				    hba->hash_tbl_pbl_dma);
+		hba->hash_tbl_pbl = NULL;
+	}
+}
+
+static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba)
+{
+	int i;
+	int hash_table_size;
+	int segment_count;
+	int segment_array_size;
+	int dma_segment_array_size;
+	dma_addr_t *dma_segment_array;
+	u32 *pbl;
+
+	hash_table_size = BNX2FC_NUM_MAX_SESS * BNX2FC_MAX_ROWS_IN_HASH_TBL *
+		sizeof(struct fcoe_hash_table_entry);
+
+	segment_count = hash_table_size + BNX2FC_HASH_TBL_CHUNK_SIZE - 1;
+	segment_count /= BNX2FC_HASH_TBL_CHUNK_SIZE;
+	hba->hash_tbl_segment_count = segment_count;
+
+	segment_array_size = segment_count * sizeof(*hba->hash_tbl_segments);
+	hba->hash_tbl_segments = kzalloc(segment_array_size, GFP_KERNEL);
+	if (!hba->hash_tbl_segments) {
+		printk(KERN_ERR PFX "hash table pointers alloc failed\n");
+		return -ENOMEM;
+	}
+	dma_segment_array_size = segment_count * sizeof(*dma_segment_array);
+	dma_segment_array = kzalloc(dma_segment_array_size, GFP_KERNEL);
+	if (!dma_segment_array) {
+		printk(KERN_ERR PFX "hash table pointers (dma) alloc failed\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < segment_count; ++i) {
+		hba->hash_tbl_segments[i] =
+			dma_alloc_coherent(&hba->pcidev->dev,
+					   BNX2FC_HASH_TBL_CHUNK_SIZE,
+					   &dma_segment_array[i],
+					   GFP_KERNEL);
+		if (!hba->hash_tbl_segments[i]) {
+			printk(KERN_ERR PFX "hash segment alloc failed\n");
+			while (--i >= 0) {
+				dma_free_coherent(&hba->pcidev->dev,
+						    BNX2FC_HASH_TBL_CHUNK_SIZE,
+						    hba->hash_tbl_segments[i],
+						    dma_segment_array[i]);
+				hba->hash_tbl_segments[i] = NULL;
+			}
+			kfree(dma_segment_array);
+			return -ENOMEM;
+		}
+		memset(hba->hash_tbl_segments[i], 0,
+		       BNX2FC_HASH_TBL_CHUNK_SIZE);
+	}
+
+	hba->hash_tbl_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+					       PAGE_SIZE,
+					       &hba->hash_tbl_pbl_dma,
+					       GFP_KERNEL);
+	if (!hba->hash_tbl_pbl) {
+		printk(KERN_ERR PFX "hash table pbl alloc failed\n");
+		kfree(dma_segment_array);
+		return -ENOMEM;
+	}
+	memset(hba->hash_tbl_pbl, 0, PAGE_SIZE);
+
+	pbl = hba->hash_tbl_pbl;
+	for (i = 0; i < segment_count; ++i) {
+		u64 paddr = dma_segment_array[i];
+		*pbl = cpu_to_le32((u32) paddr);
+		++pbl;
+		*pbl = cpu_to_le32((u32) (paddr >> 32));
+		++pbl;
+	}
+	pbl = hba->hash_tbl_pbl;
+	i = 0;
+	while (*pbl && *(pbl + 1)) {
+		u32 lo;
+		u32 hi;
+		lo = *pbl;
+		++pbl;
+		hi = *pbl;
+		++pbl;
+		++i;
+	}
+	kfree(dma_segment_array);
+	return 0;
+}
+
+/**
+ * bnx2fc_setup_fw_resc - Allocate and map hash table and dummy buffer
+ *
+ * @hba:	Pointer to adapter structure
+ *
+ */
+int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
+{
+	u64 addr;
+	u32 mem_size;
+	int i;
+
+	if (bnx2fc_allocate_hash_table(hba))
+		return -ENOMEM;
+
+	mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
+	hba->t2_hash_tbl_ptr = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+						  &hba->t2_hash_tbl_ptr_dma,
+						  GFP_KERNEL);
+	if (!hba->t2_hash_tbl_ptr) {
+		printk(KERN_ERR PFX "unable to allocate t2 hash table ptr\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+	memset(hba->t2_hash_tbl_ptr, 0x00, mem_size);
+
+	mem_size = BNX2FC_NUM_MAX_SESS *
+				sizeof(struct fcoe_t2_hash_table_entry);
+	hba->t2_hash_tbl = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+					      &hba->t2_hash_tbl_dma,
+					      GFP_KERNEL);
+	if (!hba->t2_hash_tbl) {
+		printk(KERN_ERR PFX "unable to allocate t2 hash table\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+	memset(hba->t2_hash_tbl, 0x00, mem_size);
+	for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
+		addr = (unsigned long) hba->t2_hash_tbl_dma +
+			 ((i+1) * sizeof(struct fcoe_t2_hash_table_entry));
+		hba->t2_hash_tbl[i].next.lo = addr & 0xffffffff;
+		hba->t2_hash_tbl[i].next.hi = addr >> 32;
+	}
+
+	hba->dummy_buffer = dma_alloc_coherent(&hba->pcidev->dev,
+					       PAGE_SIZE, &hba->dummy_buf_dma,
+					       GFP_KERNEL);
+	if (!hba->dummy_buffer) {
+		printk(KERN_ERR PFX "unable to alloc MP Dummy Buffer\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+
+	hba->stats_buffer = dma_alloc_coherent(&hba->pcidev->dev,
+					       PAGE_SIZE,
+					       &hba->stats_buf_dma,
+					       GFP_KERNEL);
+	if (!hba->stats_buffer) {
+		printk(KERN_ERR PFX "unable to alloc Stats Buffer\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+	memset(hba->stats_buffer, 0x00, PAGE_SIZE);
+
+	return 0;
+}
+
+void bnx2fc_free_fw_resc(struct bnx2fc_hba *hba)
+{
+	u32 mem_size;
+
+	if (hba->stats_buffer) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				  hba->stats_buffer, hba->stats_buf_dma);
+		hba->stats_buffer = NULL;
+	}
+
+	if (hba->dummy_buffer) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				  hba->dummy_buffer, hba->dummy_buf_dma);
+		hba->dummy_buffer = NULL;
+	}
+
+	if (hba->t2_hash_tbl_ptr) {
+		mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
+		dma_free_coherent(&hba->pcidev->dev, mem_size,
+				    hba->t2_hash_tbl_ptr,
+				    hba->t2_hash_tbl_ptr_dma);
+		hba->t2_hash_tbl_ptr = NULL;
+	}
+
+	if (hba->t2_hash_tbl) {
+		mem_size = BNX2FC_NUM_MAX_SESS *
+			    sizeof(struct fcoe_t2_hash_table_entry);
+		dma_free_coherent(&hba->pcidev->dev, mem_size,
+				    hba->t2_hash_tbl, hba->t2_hash_tbl_dma);
+		hba->t2_hash_tbl = NULL;
+	}
+	bnx2fc_free_hash_table(hba);
+}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
new file mode 100644
index 0000000..0f1dd23
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -0,0 +1,1833 @@
+/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * IO manager and SCSI IO processing.
+ *
+ * Copyright (c) 2008 - 2010 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
+			   int bd_index);
+static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
+static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
+static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
+			       struct bnx2fc_cmd *io_req);
+static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req);
+static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
+static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
+				 struct fcoe_fcp_rsp_payload *fcp_rsp,
+				 u8 num_rq);
+
+void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
+			  unsigned int timer_msec)
+{
+	struct bnx2fc_hba *hba = io_req->port->priv;
+
+	if (queue_delayed_work(hba->timer_work_queue, &io_req->timeout_work,
+				  msecs_to_jiffies(timer_msec)))
+		kref_get(&io_req->refcount);
+}
+
+static void bnx2fc_cmd_timeout(struct work_struct *work)
+{
+	struct bnx2fc_cmd *io_req = container_of(work, struct bnx2fc_cmd,
+						 timeout_work.work);
+	struct fc_lport *lport;
+	struct fc_rport_priv *rdata;
+	u8 cmd_type = io_req->cmd_type;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	int logo_issued;
+	int rc;
+
+	BNX2FC_IO_DBG(io_req, "cmd_timeout, cmd_type = %d,"
+		      "req_flags = %lx\n", cmd_type, io_req->req_flags);
+
+	spin_lock_bh(&tgt->tgt_lock);
+	if (test_and_clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags)) {
+		clear_bit(BNX2FC_FLAG_RETIRE_OXID, &io_req->req_flags);
+		/*
+		 * ideally we should hold the io_req until RRQ complets,
+		 * and release io_req from timeout hold.
+		 */
+		spin_unlock_bh(&tgt->tgt_lock);
+		bnx2fc_send_rrq(io_req);
+		return;
+	}
+	if (test_and_clear_bit(BNX2FC_FLAG_RETIRE_OXID, &io_req->req_flags)) {
+		BNX2FC_IO_DBG(io_req, "IO ready for reuse now\n");
+		goto done;
+	}
+
+	switch (cmd_type) {
+	case BNX2FC_SCSI_CMD:
+		if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+							&io_req->req_flags)) {
+			/* Handle eh_abort timeout */
+			BNX2FC_IO_DBG(io_req, "eh_abort timed out\n");
+			complete(&io_req->tm_done);
+		} else if (test_bit(BNX2FC_FLAG_ISSUE_ABTS,
+				    &io_req->req_flags)) {
+			/* Handle internally generated ABTS timeout */
+			BNX2FC_IO_DBG(io_req, "ABTS timed out refcnt = %d\n",
+					io_req->refcount.refcount.counter);
+			if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+					       &io_req->req_flags))) {
+
+				lport = io_req->port->lport;
+				rdata = io_req->tgt->rdata;
+				logo_issued = test_and_set_bit(
+						BNX2FC_FLAG_EXPL_LOGO,
+						&tgt->flags);
+				kref_put(&io_req->refcount, bnx2fc_cmd_release);
+				spin_unlock_bh(&tgt->tgt_lock);
+
+				/* Explicitly logo the target */
+				if (!logo_issued) {
+					BNX2FC_IO_DBG(io_req, "Explicit "
+						   "logo - tgt flags = 0x%lx\n",
+						   tgt->flags);
+
+					mutex_lock(&lport->disc.disc_mutex);
+					lport->tt.rport_logoff(rdata);
+					mutex_unlock(&lport->disc.disc_mutex);
+				}
+				return;
+			}
+		} else {
+			/* Hanlde IO timeout */
+			BNX2FC_IO_DBG(io_req, "IO timed out. issue ABTS\n");
+			if (test_and_set_bit(BNX2FC_FLAG_IO_COMPL,
+					     &io_req->req_flags)) {
+				BNX2FC_IO_DBG(io_req, "IO completed before "
+							   " timer expiry\n");
+				goto done;
+			}
+
+			if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+					      &io_req->req_flags)) {
+				rc = bnx2fc_initiate_abts(io_req);
+				if (rc == SUCCESS)
+					goto done;
+				/*
+				 * Explicitly logo the target if
+				 * abts initiation fails
+				 */
+				lport = io_req->port->lport;
+				rdata = io_req->tgt->rdata;
+				logo_issued = test_and_set_bit(
+						BNX2FC_FLAG_EXPL_LOGO,
+						&tgt->flags);
+				kref_put(&io_req->refcount, bnx2fc_cmd_release);
+				spin_unlock_bh(&tgt->tgt_lock);
+
+				if (!logo_issued) {
+					BNX2FC_IO_DBG(io_req, "Explicit "
+						   "logo - tgt flags = 0x%lx\n",
+						   tgt->flags);
+
+
+					mutex_lock(&lport->disc.disc_mutex);
+					lport->tt.rport_logoff(rdata);
+					mutex_unlock(&lport->disc.disc_mutex);
+				}
+				return;
+			} else {
+				BNX2FC_IO_DBG(io_req, "IO already in "
+						      "ABTS processing\n");
+			}
+		}
+		break;
+	case BNX2FC_ELS:
+
+		if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
+			BNX2FC_IO_DBG(io_req, "ABTS for ELS timed out\n");
+
+			if (!test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+					      &io_req->req_flags)) {
+				lport = io_req->port->lport;
+				rdata = io_req->tgt->rdata;
+				logo_issued = test_and_set_bit(
+						BNX2FC_FLAG_EXPL_LOGO,
+						&tgt->flags);
+				kref_put(&io_req->refcount, bnx2fc_cmd_release);
+				spin_unlock_bh(&tgt->tgt_lock);
+
+				/* Explicitly logo the target */
+				if (!logo_issued) {
+					BNX2FC_IO_DBG(io_req, "Explicitly logo"
+						   "(els)\n");
+					mutex_lock(&lport->disc.disc_mutex);
+					lport->tt.rport_logoff(rdata);
+					mutex_unlock(&lport->disc.disc_mutex);
+				}
+				return;
+			}
+		} else {
+			/*
+			 * Handle ELS timeout.
+			 * tgt_lock is used to sync compl path and timeout
+			 * path. If els compl path is processing this IO, we
+			 * have nothing to do here, just release the timer hold
+			 */
+			BNX2FC_IO_DBG(io_req, "ELS timed out\n");
+			if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
+					       &io_req->req_flags))
+				goto done;
+
+			/* Indicate the cb_func that this ELS is timed out */
+			set_bit(BNX2FC_FLAG_ELS_TIMEOUT, &io_req->req_flags);
+
+			if ((io_req->cb_func) && (io_req->cb_arg)) {
+				io_req->cb_func(io_req->cb_arg);
+				io_req->cb_arg = NULL;
+			}
+		}
+		break;
+	default:
+		printk(KERN_ERR PFX "cmd_timeout: invalid cmd_type %d\n",
+			cmd_type);
+		break;
+	}
+
+done:
+	/* release the cmd that was held when timer was set */
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	spin_unlock_bh(&tgt->tgt_lock);
+}
+
+static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code)
+{
+	/* Called with host lock held */
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+
+	/*
+	 * active_cmd_queue may have other command types as well,
+	 * and during flush operation,  we want to error back only
+	 * scsi commands.
+	 */
+	if (io_req->cmd_type != BNX2FC_SCSI_CMD)
+		return;
+
+	BNX2FC_IO_DBG(io_req, "scsi_done. err_code = 0x%x\n", err_code);
+	bnx2fc_unmap_sg_list(io_req);
+	io_req->sc_cmd = NULL;
+	if (!sc_cmd) {
+		printk(KERN_ERR PFX "scsi_done - sc_cmd NULL. "
+				    "IO(0x%x) already cleaned up\n",
+		       io_req->xid);
+		return;
+	}
+	sc_cmd->result = err_code << 16;
+
+	BNX2FC_IO_DBG(io_req, "sc=%p, result=0x%x, retries=%d, allowed=%d\n",
+		sc_cmd, host_byte(sc_cmd->result), sc_cmd->retries,
+		sc_cmd->allowed);
+	scsi_set_resid(sc_cmd, scsi_bufflen(sc_cmd));
+	sc_cmd->SCp.ptr = NULL;
+	sc_cmd->scsi_done(sc_cmd);
+}
+
+struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
+						u16 min_xid, u16 max_xid)
+{
+	struct bnx2fc_cmd_mgr *cmgr;
+	struct io_bdt *bdt_info;
+	struct bnx2fc_cmd *io_req;
+	size_t len;
+	u32 mem_size;
+	u16 xid;
+	int i;
+	int num_ios;
+	size_t bd_tbl_sz;
+
+	if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
+		printk(KERN_ERR PFX "cmd_mgr_alloc: Invalid min_xid 0x%x \
+					and max_xid 0x%x\n", min_xid, max_xid);
+		return NULL;
+	}
+	BNX2FC_MISC_DBG("min xid 0x%x, max xid 0x%x\n", min_xid, max_xid);
+
+	num_ios = max_xid - min_xid + 1;
+	len = (num_ios * (sizeof(struct bnx2fc_cmd *)));
+	len += sizeof(struct bnx2fc_cmd_mgr);
+
+	cmgr = kzalloc(len, GFP_KERNEL);
+	if (!cmgr) {
+		printk(KERN_ERR PFX "failed to alloc cmgr\n");
+		return NULL;
+	}
+
+	cmgr->free_list = kzalloc(sizeof(*cmgr->free_list) *
+				  num_possible_cpus(), GFP_KERNEL);
+	if (!cmgr->free_list) {
+		printk(KERN_ERR PFX "failed to alloc free_list\n");
+		goto mem_err;
+	}
+
+	cmgr->free_list_lock = kzalloc(sizeof(*cmgr->free_list_lock) *
+				       num_possible_cpus(), GFP_KERNEL);
+	if (!cmgr->free_list_lock) {
+		printk(KERN_ERR PFX "failed to alloc free_list_lock\n");
+		goto mem_err;
+	}
+
+	cmgr->hba = hba;
+	cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
+
+	for (i = 0; i < num_possible_cpus(); i++)  {
+		INIT_LIST_HEAD(&cmgr->free_list[i]);
+		spin_lock_init(&cmgr->free_list_lock[i]);
+	}
+
+	/* Pre-allocated pool of bnx2fc_cmds */
+	xid = BNX2FC_MIN_XID;
+	for (i = 0; i < num_ios; i++) {
+		io_req = kzalloc(sizeof(*io_req), GFP_KERNEL);
+
+		if (!io_req) {
+			printk(KERN_ERR PFX "failed to alloc io_req\n");
+			goto mem_err;
+		}
+
+		INIT_LIST_HEAD(&io_req->link);
+		INIT_DELAYED_WORK(&io_req->timeout_work, bnx2fc_cmd_timeout);
+
+		io_req->xid = xid++;
+		if (io_req->xid >= BNX2FC_MAX_OUTSTANDING_CMNDS)
+			printk(KERN_ERR PFX "ERROR allocating xids - 0x%x\n",
+				io_req->xid);
+		list_add_tail(&io_req->link,
+			&cmgr->free_list[io_req->xid % num_possible_cpus()]);
+		io_req++;
+	}
+
+	/* Allocate pool of io_bdts - one for each bnx2fc_cmd */
+	mem_size = num_ios * sizeof(struct io_bdt *);
+	cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL);
+	if (!cmgr->io_bdt_pool) {
+		printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n");
+		goto mem_err;
+	}
+
+	mem_size = sizeof(struct io_bdt);
+	for (i = 0; i < num_ios; i++) {
+		cmgr->io_bdt_pool[i] = kmalloc(mem_size, GFP_KERNEL);
+		if (!cmgr->io_bdt_pool[i]) {
+			printk(KERN_ERR PFX "failed to alloc "
+				"io_bdt_pool[%d]\n", i);
+			goto mem_err;
+		}
+	}
+
+	/* Allocate an map fcoe_bdt_ctx structures */
+	bd_tbl_sz = BNX2FC_MAX_BDS_PER_CMD * sizeof(struct fcoe_bd_ctx);
+	for (i = 0; i < num_ios; i++) {
+		bdt_info = cmgr->io_bdt_pool[i];
+		bdt_info->bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+						      bd_tbl_sz,
+						      &bdt_info->bd_tbl_dma,
+						      GFP_KERNEL);
+		if (!bdt_info->bd_tbl) {
+			printk(KERN_ERR PFX "failed to alloc "
+				"bdt_tbl[%d]\n", i);
+			goto mem_err;
+		}
+	}
+
+	return cmgr;
+
+mem_err:
+	bnx2fc_cmd_mgr_free(cmgr);
+	return NULL;
+}
+
+void bnx2fc_cmd_mgr_free(struct bnx2fc_cmd_mgr *cmgr)
+{
+	struct io_bdt *bdt_info;
+	struct bnx2fc_hba *hba = cmgr->hba;
+	size_t bd_tbl_sz;
+	u16 min_xid = BNX2FC_MIN_XID;
+	u16 max_xid = BNX2FC_MAX_XID;
+	int num_ios;
+	int i;
+
+	num_ios = max_xid - min_xid + 1;
+
+	/* Free fcoe_bdt_ctx structures */
+	if (!cmgr->io_bdt_pool)
+		goto free_cmd_pool;
+
+	bd_tbl_sz = BNX2FC_MAX_BDS_PER_CMD * sizeof(struct fcoe_bd_ctx);
+	for (i = 0; i < num_ios; i++) {
+		bdt_info = cmgr->io_bdt_pool[i];
+		if (bdt_info->bd_tbl) {
+			dma_free_coherent(&hba->pcidev->dev, bd_tbl_sz,
+					    bdt_info->bd_tbl,
+					    bdt_info->bd_tbl_dma);
+			bdt_info->bd_tbl = NULL;
+		}
+	}
+
+	/* Destroy io_bdt pool */
+	for (i = 0; i < num_ios; i++) {
+		kfree(cmgr->io_bdt_pool[i]);
+		cmgr->io_bdt_pool[i] = NULL;
+	}
+
+	kfree(cmgr->io_bdt_pool);
+	cmgr->io_bdt_pool = NULL;
+
+free_cmd_pool:
+	kfree(cmgr->free_list_lock);
+
+	/* Destroy cmd pool */
+	if (!cmgr->free_list)
+		goto free_cmgr;
+
+	for (i = 0; i < num_possible_cpus(); i++)  {
+		struct list_head *list;
+		struct list_head *tmp;
+
+		list_for_each_safe(list, tmp, &cmgr->free_list[i]) {
+			struct bnx2fc_cmd *io_req = (struct bnx2fc_cmd *)list;
+			list_del(&io_req->link);
+			kfree(io_req);
+		}
+	}
+	kfree(cmgr->free_list);
+free_cmgr:
+	/* Free command manager itself */
+	kfree(cmgr);
+}
+
+struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
+{
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+	struct bnx2fc_cmd *io_req;
+	struct list_head *listp;
+	struct io_bdt *bd_tbl;
+	u32 max_sqes;
+	u16 xid;
+
+	max_sqes = tgt->max_sqes;
+	switch (type) {
+	case BNX2FC_TASK_MGMT_CMD:
+		max_sqes = BNX2FC_TM_MAX_SQES;
+		break;
+	case BNX2FC_ELS:
+		max_sqes = BNX2FC_ELS_MAX_SQES;
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * NOTE: Free list insertions and deletions are protected with
+	 * cmgr lock
+	 */
+	spin_lock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+	if ((list_empty(&(cmd_mgr->free_list[smp_processor_id()]))) ||
+	    (tgt->num_active_ios.counter  >= max_sqes)) {
+		BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
+			"ios(%d):sqes(%d)\n",
+			tgt->num_active_ios.counter, tgt->max_sqes);
+		if (list_empty(&(cmd_mgr->free_list[smp_processor_id()])))
+			printk(KERN_ERR PFX "elstm_alloc: list_empty\n");
+		spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+		return NULL;
+	}
+
+	listp = (struct list_head *)
+			cmd_mgr->free_list[smp_processor_id()].next;
+	list_del_init(listp);
+	io_req = (struct bnx2fc_cmd *) listp;
+	xid = io_req->xid;
+	cmd_mgr->cmds[xid] = io_req;
+	atomic_inc(&tgt->num_active_ios);
+	spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+
+	INIT_LIST_HEAD(&io_req->link);
+
+	io_req->port = port;
+	io_req->cmd_mgr = cmd_mgr;
+	io_req->req_flags = 0;
+	io_req->cmd_type = type;
+
+	/* Bind io_bdt for this io_req */
+	/* Have a static link between io_req and io_bdt_pool */
+	bd_tbl = io_req->bd_tbl = cmd_mgr->io_bdt_pool[xid];
+	bd_tbl->io_req = io_req;
+
+	/* Hold the io_req  against deletion */
+	kref_init(&io_req->refcount);
+	return io_req;
+}
+static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
+{
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+	struct bnx2fc_cmd *io_req;
+	struct list_head *listp;
+	struct io_bdt *bd_tbl;
+	u32 max_sqes;
+	u16 xid;
+
+	max_sqes = BNX2FC_SCSI_MAX_SQES;
+	/*
+	 * NOTE: Free list insertions and deletions are protected with
+	 * cmgr lock
+	 */
+	spin_lock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+	if ((list_empty(&cmd_mgr->free_list[smp_processor_id()])) ||
+	    (tgt->num_active_ios.counter  >= max_sqes)) {
+		spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+		return NULL;
+	}
+
+	listp = (struct list_head *)
+		cmd_mgr->free_list[smp_processor_id()].next;
+	list_del_init(listp);
+	io_req = (struct bnx2fc_cmd *) listp;
+	xid = io_req->xid;
+	cmd_mgr->cmds[xid] = io_req;
+	atomic_inc(&tgt->num_active_ios);
+	spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+
+	INIT_LIST_HEAD(&io_req->link);
+
+	io_req->port = port;
+	io_req->cmd_mgr = cmd_mgr;
+	io_req->req_flags = 0;
+
+	/* Bind io_bdt for this io_req */
+	/* Have a static link between io_req and io_bdt_pool */
+	bd_tbl = io_req->bd_tbl = cmd_mgr->io_bdt_pool[xid];
+	bd_tbl->io_req = io_req;
+
+	/* Hold the io_req  against deletion */
+	kref_init(&io_req->refcount);
+	return io_req;
+}
+
+void bnx2fc_cmd_release(struct kref *ref)
+{
+	struct bnx2fc_cmd *io_req = container_of(ref,
+						struct bnx2fc_cmd, refcount);
+	struct bnx2fc_cmd_mgr *cmd_mgr = io_req->cmd_mgr;
+
+	spin_lock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+	if (io_req->cmd_type != BNX2FC_SCSI_CMD)
+		bnx2fc_free_mp_resc(io_req);
+	cmd_mgr->cmds[io_req->xid] = NULL;
+	/* Delete IO from retire queue */
+	list_del_init(&io_req->link);
+	/* Add it to the free list */
+	list_add(&io_req->link,
+			&cmd_mgr->free_list[smp_processor_id()]);
+	atomic_dec(&io_req->tgt->num_active_ios);
+	spin_unlock_bh(&cmd_mgr->free_list_lock[smp_processor_id()]);
+}
+
+static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
+{
+	struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
+	struct bnx2fc_hba *hba = io_req->port->priv;
+	size_t sz = sizeof(struct fcoe_bd_ctx);
+
+	/* clear tm flags */
+	mp_req->tm_flags = 0;
+	if (mp_req->mp_req_bd) {
+		dma_free_coherent(&hba->pcidev->dev, sz,
+				     mp_req->mp_req_bd,
+				     mp_req->mp_req_bd_dma);
+		mp_req->mp_req_bd = NULL;
+	}
+	if (mp_req->mp_resp_bd) {
+		dma_free_coherent(&hba->pcidev->dev, sz,
+				     mp_req->mp_resp_bd,
+				     mp_req->mp_resp_bd_dma);
+		mp_req->mp_resp_bd = NULL;
+	}
+	if (mp_req->req_buf) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				     mp_req->req_buf,
+				     mp_req->req_buf_dma);
+		mp_req->req_buf = NULL;
+	}
+	if (mp_req->resp_buf) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				     mp_req->resp_buf,
+				     mp_req->resp_buf_dma);
+		mp_req->resp_buf = NULL;
+	}
+}
+
+int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
+{
+	struct bnx2fc_mp_req *mp_req;
+	struct fcoe_bd_ctx *mp_req_bd;
+	struct fcoe_bd_ctx *mp_resp_bd;
+	struct bnx2fc_hba *hba = io_req->port->priv;
+	dma_addr_t addr;
+	size_t sz;
+
+	mp_req = (struct bnx2fc_mp_req *)&(io_req->mp_req);
+	memset(mp_req, 0, sizeof(struct bnx2fc_mp_req));
+
+	mp_req->req_len = sizeof(struct fcp_cmnd);
+	io_req->data_xfer_len = mp_req->req_len;
+	mp_req->req_buf = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+					     &mp_req->req_buf_dma,
+					     GFP_ATOMIC);
+	if (!mp_req->req_buf) {
+		printk(KERN_ERR PFX "unable to alloc MP req buffer\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+
+	mp_req->resp_buf = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+					      &mp_req->resp_buf_dma,
+					      GFP_ATOMIC);
+	if (!mp_req->resp_buf) {
+		printk(KERN_ERR PFX "unable to alloc TM resp buffer\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+	memset(mp_req->req_buf, 0, PAGE_SIZE);
+	memset(mp_req->resp_buf, 0, PAGE_SIZE);
+
+	/* Allocate and map mp_req_bd and mp_resp_bd */
+	sz = sizeof(struct fcoe_bd_ctx);
+	mp_req->mp_req_bd = dma_alloc_coherent(&hba->pcidev->dev, sz,
+						 &mp_req->mp_req_bd_dma,
+						 GFP_ATOMIC);
+	if (!mp_req->mp_req_bd) {
+		printk(KERN_ERR PFX "unable to alloc MP req bd\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+	mp_req->mp_resp_bd = dma_alloc_coherent(&hba->pcidev->dev, sz,
+						 &mp_req->mp_resp_bd_dma,
+						 GFP_ATOMIC);
+	if (!mp_req->mp_req_bd) {
+		printk(KERN_ERR PFX "unable to alloc MP resp bd\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+	/* Fill bd table */
+	addr = mp_req->req_buf_dma;
+	mp_req_bd = mp_req->mp_req_bd;
+	mp_req_bd->buf_addr_lo = (u32)addr & 0xffffffff;
+	mp_req_bd->buf_addr_hi = (u32)((u64)addr >> 32);
+	mp_req_bd->buf_len = PAGE_SIZE;
+	mp_req_bd->flags = 0;
+
+	/*
+	 * MP buffer is either a task mgmt command or an ELS.
+	 * So the assumption is that it consumes a single bd
+	 * entry in the bd table
+	 */
+	mp_resp_bd = mp_req->mp_resp_bd;
+	addr = mp_req->resp_buf_dma;
+	mp_resp_bd->buf_addr_lo = (u32)addr & 0xffffffff;
+	mp_resp_bd->buf_addr_hi = (u32)((u64)addr >> 32);
+	mp_resp_bd->buf_len = PAGE_SIZE;
+	mp_resp_bd->flags = 0;
+
+	return SUCCESS;
+}
+
+static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
+{
+	struct fc_lport *lport;
+	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct fcoe_port *port;
+	struct bnx2fc_hba *hba;
+	struct bnx2fc_rport *tgt;
+	struct bnx2fc_cmd *io_req;
+	struct bnx2fc_mp_req *tm_req;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct Scsi_Host *host = sc_cmd->device->host;
+	struct fc_frame_header *fc_hdr;
+	struct fcp_cmnd *fcp_cmnd;
+	int task_idx, index;
+	int rc = SUCCESS;
+	u16 xid;
+	u32 sid, did;
+	unsigned long start = jiffies;
+
+	lport = shost_priv(host);
+	port = lport_priv(lport);
+	hba = port->priv;
+
+	if (rport == NULL) {
+		printk(KERN_ALERT PFX "device_reset: rport is NULL\n");
+		rc = FAILED;
+		goto tmf_err;
+	}
+
+	rc = fc_block_scsi_eh(sc_cmd);
+	if (rc)
+		return rc;
+
+	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+		printk(KERN_ERR PFX "device_reset: link is not ready\n");
+		rc = FAILED;
+		goto tmf_err;
+	}
+	/* rport and tgt are allocated together, so tgt should be non-NULL */
+	tgt = (struct bnx2fc_rport *)&rp[1];
+
+	if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
+		printk(KERN_ERR PFX "device_reset: tgt not offloaded\n");
+		rc = FAILED;
+		goto tmf_err;
+	}
+retry_tmf:
+	io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_TASK_MGMT_CMD);
+	if (!io_req) {
+		if (time_after(jiffies, start + HZ)) {
+			printk(KERN_ERR PFX "tmf: Failed TMF");
+			rc = FAILED;
+			goto tmf_err;
+		}
+		msleep(20);
+		goto retry_tmf;
+	}
+	/* Initialize rest of io_req fields */
+	io_req->sc_cmd = sc_cmd;
+	io_req->port = port;
+	io_req->tgt = tgt;
+
+	tm_req = (struct bnx2fc_mp_req *)&(io_req->mp_req);
+
+	rc = bnx2fc_init_mp_req(io_req);
+	if (rc == FAILED) {
+		printk(KERN_ERR PFX "Task mgmt MP request init failed\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		goto tmf_err;
+	}
+
+	/* Set TM flags */
+	io_req->io_req_flags = 0;
+	tm_req->tm_flags = tm_flags;
+
+	/* Fill FCP_CMND */
+	bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)tm_req->req_buf);
+	fcp_cmnd = (struct fcp_cmnd *)tm_req->req_buf;
+	memset(fcp_cmnd->fc_cdb, 0,  sc_cmd->cmd_len);
+	fcp_cmnd->fc_dl = 0;
+
+	/* Fill FC header */
+	fc_hdr = &(tm_req->req_fc_hdr);
+	sid = tgt->sid;
+	did = rport->port_id;
+	__fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, did, sid,
+			   FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+			   FC_FC_SEQ_INIT, 0);
+	/* Obtain exchange id */
+	xid = io_req->xid;
+
+	BNX2FC_TGT_DBG(tgt, "Initiate TMF - xid = 0x%x\n", xid);
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_mp_task(io_req, task);
+
+	sc_cmd->SCp.ptr = (char *)io_req;
+
+	/* Obtain free SQ entry */
+	spin_lock_bh(&tgt->tgt_lock);
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Enqueue the io_req to active_tm_queue */
+	io_req->on_tmf_queue = 1;
+	list_add_tail(&io_req->link, &tgt->active_tm_queue);
+
+	init_completion(&io_req->tm_done);
+	io_req->wait_for_comp = 1;
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+	spin_unlock_bh(&tgt->tgt_lock);
+
+	rc = wait_for_completion_timeout(&io_req->tm_done,
+					 BNX2FC_TM_TIMEOUT * HZ);
+	spin_lock_bh(&tgt->tgt_lock);
+
+	io_req->wait_for_comp = 0;
+	if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags)))
+		set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags);
+
+	spin_unlock_bh(&tgt->tgt_lock);
+
+	if (!rc) {
+		printk(KERN_ERR PFX "task mgmt command failed...\n");
+		rc = FAILED;
+	} else {
+		printk(KERN_ERR PFX "task mgmt command success...\n");
+		rc = SUCCESS;
+	}
+tmf_err:
+	return rc;
+}
+
+int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
+{
+	struct fc_lport *lport;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct fc_rport *rport = tgt->rport;
+	struct fc_rport_priv *rdata = tgt->rdata;
+	struct bnx2fc_hba *hba;
+	struct fcoe_port *port;
+	struct bnx2fc_cmd *abts_io_req;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct fc_frame_header *fc_hdr;
+	struct bnx2fc_mp_req *abts_req;
+	int task_idx, index;
+	u32 sid, did;
+	u16 xid;
+	int rc = SUCCESS;
+	u32 r_a_tov = rdata->r_a_tov;
+
+	/* called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_abts\n");
+
+	port = io_req->port;
+	hba = port->priv;
+	lport = port->lport;
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		printk(KERN_ERR PFX "initiate_abts: tgt not offloaded\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	if (rport == NULL) {
+		printk(KERN_ALERT PFX "initiate_abts: rport is NULL\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+		printk(KERN_ERR PFX "initiate_abts: link is not ready\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	abts_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ABTS);
+	if (!abts_io_req) {
+		printk(KERN_ERR PFX "abts: couldnt allocate cmd\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	/* Initialize rest of io_req fields */
+	abts_io_req->sc_cmd = NULL;
+	abts_io_req->port = port;
+	abts_io_req->tgt = tgt;
+	abts_io_req->data_xfer_len = 0; /* No data transfer for ABTS */
+
+	abts_req = (struct bnx2fc_mp_req *)&(abts_io_req->mp_req);
+	memset(abts_req, 0, sizeof(struct bnx2fc_mp_req));
+
+	/* Fill FC header */
+	fc_hdr = &(abts_req->req_fc_hdr);
+
+	/* Obtain oxid and rxid for the original exchange to be aborted */
+	fc_hdr->fh_ox_id = htons(io_req->xid);
+	fc_hdr->fh_rx_id = htons(io_req->task->rx_wr_tx_rd.rx_id);
+
+	sid = tgt->sid;
+	did = rport->port_id;
+
+	__fc_fill_fc_hdr(fc_hdr, FC_RCTL_BA_ABTS, did, sid,
+			   FC_TYPE_BLS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+			   FC_FC_SEQ_INIT, 0);
+
+	xid = abts_io_req->xid;
+	BNX2FC_IO_DBG(abts_io_req, "ABTS io_req\n");
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_mp_task(abts_io_req, task);
+
+	/*
+	 * ABTS task is a temporary task that will be cleaned up
+	 * irrespective of ABTS response. We need to start the timer
+	 * for the original exchange, as the CQE is posted for the original
+	 * IO request.
+	 *
+	 * Timer for ABTS is started only when it is originated by a
+	 * TM request. For the ABTS issued as part of ULP timeout,
+	 * scsi-ml maintains the timers.
+	 */
+
+	/* if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags))*/
+	bnx2fc_cmd_timer_set(io_req, 2 * r_a_tov);
+
+	/* Obtain free SQ entry */
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+
+abts_err:
+	return rc;
+}
+
+int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
+{
+	struct fc_lport *lport;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct bnx2fc_hba *hba;
+	struct fcoe_port *port;
+	struct bnx2fc_cmd *cleanup_io_req;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	int task_idx, index;
+	u16 xid, orig_xid;
+	int rc = 0;
+
+	/* ASSUMPTION: called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_cleanup\n");
+
+	port = io_req->port;
+	hba = port->priv;
+	lport = port->lport;
+
+	cleanup_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_CLEANUP);
+	if (!cleanup_io_req) {
+		printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
+		rc = -1;
+		goto cleanup_err;
+	}
+
+	/* Initialize rest of io_req fields */
+	cleanup_io_req->sc_cmd = NULL;
+	cleanup_io_req->port = port;
+	cleanup_io_req->tgt = tgt;
+	cleanup_io_req->data_xfer_len = 0; /* No data transfer for cleanup */
+
+	xid = cleanup_io_req->xid;
+
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	orig_xid = io_req->xid;
+
+	BNX2FC_IO_DBG(io_req, "CLEANUP io_req xid = 0x%x\n", xid);
+
+	bnx2fc_init_cleanup_task(cleanup_io_req, task, orig_xid);
+
+	/* Obtain free SQ entry */
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+
+cleanup_err:
+	return rc;
+}
+
+/**
+ * bnx2fc_eh_target_reset: Reset a target
+ *
+ * @sc_cmd:	SCSI command
+ *
+ * Set from SCSI host template to send task mgmt command to the target
+ *	and wait for the response
+ */
+int bnx2fc_eh_target_reset(struct scsi_cmnd *sc_cmd)
+{
+	return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_TGT_RESET);
+}
+
+/**
+ * bnx2fc_eh_device_reset - Reset a single LUN
+ *
+ * @sc_cmd:	SCSI command
+ *
+ * Set from SCSI host template to send task mgmt command to the target
+ *	and wait for the response
+ */
+int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
+{
+	return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
+}
+
+/**
+ * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding
+ *			SCSI command
+ *
+ * @sc_cmd:	SCSI_ML command pointer
+ *
+ * SCSI abort request handler
+ */
+int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
+{
+	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct bnx2fc_cmd *io_req;
+	struct fc_lport *lport;
+	struct bnx2fc_rport *tgt;
+	int rc = FAILED;
+
+
+	rc = fc_block_scsi_eh(sc_cmd);
+	if (rc)
+		return rc;
+
+	lport = shost_priv(sc_cmd->device->host);
+	if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
+		printk(KERN_ALERT PFX "eh_abort: link not ready\n");
+		return rc;
+	}
+
+	tgt = (struct bnx2fc_rport *)&rp[1];
+
+	BNX2FC_TGT_DBG(tgt, "Entered bnx2fc_eh_abort\n");
+
+	spin_lock_bh(&tgt->tgt_lock);
+	io_req = (struct bnx2fc_cmd *)sc_cmd->SCp.ptr;
+	if (!io_req) {
+		/* Command might have just completed */
+		printk(KERN_ERR PFX "eh_abort: io_req is NULL\n");
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+	BNX2FC_IO_DBG(io_req, "eh_abort - refcnt = %d\n",
+		      io_req->refcount.refcount.counter);
+
+	/* Hold IO request across abort processing */
+	kref_get(&io_req->refcount);
+
+	BUG_ON(tgt != io_req->tgt);
+
+	/* Remove the io_req from the active_q. */
+	/*
+	 * Task Mgmt functions (LUN RESET & TGT RESET) will not
+	 * issue an ABTS on this particular IO req, as the
+	 * io_req is no longer in the active_q.
+	 */
+	if (tgt->flush_in_prog) {
+		printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+			"flush in progress\n", io_req->xid);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+
+	if (io_req->on_active_queue == 0) {
+		printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+				"not on active_q\n", io_req->xid);
+		/*
+		 * This condition can happen only due to the FW bug,
+		 * where we do not receive cleanup response from
+		 * the FW. Handle this case gracefully by erroring
+		 * back the IO request to SCSI-ml
+		 */
+		bnx2fc_scsi_done(io_req, DID_ABORT);
+
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+
+	/*
+	 * Only eh_abort processing will remove the IO from
+	 * active_cmd_q before processing the request. this is
+	 * done to avoid race conditions between IOs aborted
+	 * as part of task management completion and eh_abort
+	 * processing
+	 */
+	list_del_init(&io_req->link);
+	io_req->on_active_queue = 0;
+	/* Move IO req to retire queue */
+	list_add_tail(&io_req->link, &tgt->io_retire_queue);
+
+	init_completion(&io_req->tm_done);
+	io_req->wait_for_comp = 1;
+
+	if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
+		/* Cancel the current timer running on this io_req */
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+		set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
+		rc = bnx2fc_initiate_abts(io_req);
+	} else {
+		printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+				"already in abts processing\n", io_req->xid);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+	if (rc == FAILED) {
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return rc;
+	}
+	spin_unlock_bh(&tgt->tgt_lock);
+
+	wait_for_completion(&io_req->tm_done);
+
+	spin_lock_bh(&tgt->tgt_lock);
+	io_req->wait_for_comp = 0;
+	if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+				    &io_req->req_flags))) {
+		/* Let the scsi-ml try to recover this command */
+		printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
+		       io_req->xid);
+		rc = FAILED;
+	} else {
+		/*
+		 * We come here even when there was a race condition
+		 * between timeout and abts completion, and abts
+		 * completion happens just in time.
+		 */
+		BNX2FC_IO_DBG(io_req, "abort succeeded\n");
+		rc = SUCCESS;
+		bnx2fc_scsi_done(io_req, DID_ABORT);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	}
+
+	/* release the reference taken in eh_abort */
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	spin_unlock_bh(&tgt->tgt_lock);
+	return rc;
+}
+
+void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
+				  struct fcoe_task_ctx_entry *task,
+				  u8 num_rq)
+{
+	BNX2FC_IO_DBG(io_req, "Entered process_cleanup_compl "
+			      "refcnt = %d, cmd_type = %d\n",
+		   io_req->refcount.refcount.counter, io_req->cmd_type);
+	bnx2fc_scsi_done(io_req, DID_ERROR);
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+}
+
+void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
+			       struct fcoe_task_ctx_entry *task,
+			       u8 num_rq)
+{
+	u32 r_ctl;
+	u32 r_a_tov = FC_DEF_R_A_TOV;
+	u8 issue_rrq = 0;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+
+	BNX2FC_IO_DBG(io_req, "Entered process_abts_compl xid = 0x%x"
+			      "refcnt = %d, cmd_type = %d\n",
+		   io_req->xid,
+		   io_req->refcount.refcount.counter, io_req->cmd_type);
+
+	if (test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+				       &io_req->req_flags)) {
+		BNX2FC_IO_DBG(io_req, "Timer context finished processing"
+				" this io\n");
+		return;
+	}
+
+	/* Do not issue RRQ as this IO is already cleanedup */
+	if (test_and_set_bit(BNX2FC_FLAG_IO_CLEANUP,
+				&io_req->req_flags))
+		goto io_compl;
+
+	/*
+	 * For ABTS issued due to SCSI eh_abort_handler, timeout
+	 * values are maintained by scsi-ml itself. Cancel timeout
+	 * in case ABTS issued as part of task management function
+	 * or due to FW error.
+	 */
+	if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags))
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+
+	r_ctl = task->cmn.general.rsp_info.abts_rsp.r_ctl;
+
+	switch (r_ctl) {
+	case FC_RCTL_BA_ACC:
+		/*
+		 * Dont release this cmd yet. It will be relesed
+		 * after we get RRQ response
+		 */
+		BNX2FC_IO_DBG(io_req, "ABTS response - ACC Send RRQ\n");
+		issue_rrq = 1;
+		break;
+
+	case FC_RCTL_BA_RJT:
+		BNX2FC_IO_DBG(io_req, "ABTS response - RJT\n");
+		break;
+	default:
+		printk(KERN_ERR PFX "Unknown ABTS response\n");
+		break;
+	}
+
+	if (issue_rrq) {
+		BNX2FC_IO_DBG(io_req, "Issue RRQ after R_A_TOV\n");
+		set_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags);
+	}
+	set_bit(BNX2FC_FLAG_RETIRE_OXID, &io_req->req_flags);
+	bnx2fc_cmd_timer_set(io_req, r_a_tov);
+
+io_compl:
+	if (io_req->wait_for_comp) {
+		if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+				       &io_req->req_flags))
+			complete(&io_req->tm_done);
+	} else {
+		/*
+		 * We end up here when ABTS is issued as
+		 * in asynchronous context, i.e., as part
+		 * of task management completion, or
+		 * when FW error is received or when the
+		 * ABTS is issued when the IO is timed
+		 * out.
+		 */
+
+		if (io_req->on_active_queue) {
+			list_del_init(&io_req->link);
+			io_req->on_active_queue = 0;
+			/* Move IO req to retire queue */
+			list_add_tail(&io_req->link, &tgt->io_retire_queue);
+		}
+		bnx2fc_scsi_done(io_req, DID_ERROR);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	}
+}
+
+static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct list_head *list;
+	struct list_head *tmp;
+	struct bnx2fc_cmd *cmd;
+	int tm_lun = sc_cmd->device->lun;
+	int rc = 0;
+	int lun;
+
+	/* called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_lun_reset_cmpl\n");
+	/*
+	 * Walk thru the active_ios queue and ABORT the IO
+	 * that matches with the LUN that was reset
+	 */
+	list_for_each_safe(list, tmp, &tgt->active_cmd_queue) {
+		BNX2FC_TGT_DBG(tgt, "LUN RST cmpl: scan for pending IOs\n");
+		cmd = (struct bnx2fc_cmd *)list;
+		lun = cmd->sc_cmd->device->lun;
+		if (lun == tm_lun) {
+			/* Initiate ABTS on this cmd */
+			if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+					      &cmd->req_flags)) {
+				/* cancel the IO timeout */
+				if (cancel_delayed_work(&io_req->timeout_work))
+					kref_put(&io_req->refcount,
+						 bnx2fc_cmd_release);
+							/* timer hold */
+				rc = bnx2fc_initiate_abts(cmd);
+				/* abts shouldnt fail in this context */
+				WARN_ON(rc != SUCCESS);
+			} else
+				printk(KERN_ERR PFX "lun_rst: abts already in"
+					" progress for this IO 0x%x\n",
+					cmd->xid);
+		}
+	}
+}
+
+static void bnx2fc_tgt_reset_cmpl(struct bnx2fc_cmd *io_req)
+{
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct list_head *list;
+	struct list_head *tmp;
+	struct bnx2fc_cmd *cmd;
+	int rc = 0;
+
+	/* called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_tgt_reset_cmpl\n");
+	/*
+	 * Walk thru the active_ios queue and ABORT the IO
+	 * that matches with the LUN that was reset
+	 */
+	list_for_each_safe(list, tmp, &tgt->active_cmd_queue) {
+		BNX2FC_TGT_DBG(tgt, "TGT RST cmpl: scan for pending IOs\n");
+		cmd = (struct bnx2fc_cmd *)list;
+		/* Initiate ABTS */
+		if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+							&cmd->req_flags)) {
+			/* cancel the IO timeout */
+			if (cancel_delayed_work(&io_req->timeout_work))
+				kref_put(&io_req->refcount,
+					 bnx2fc_cmd_release); /* timer hold */
+			rc = bnx2fc_initiate_abts(cmd);
+			/* abts shouldnt fail in this context */
+			WARN_ON(rc != SUCCESS);
+
+		} else
+			printk(KERN_ERR PFX "tgt_rst: abts already in progress"
+				" for this IO 0x%x\n", cmd->xid);
+	}
+}
+
+void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task, u8 num_rq)
+{
+	struct bnx2fc_mp_req *tm_req;
+	struct fc_frame_header *fc_hdr;
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	u64 *hdr;
+	u64 *temp_hdr;
+	void *rsp_buf;
+
+	/* Called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered process_tm_compl\n");
+
+	if (!(test_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags)))
+		set_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags);
+	else {
+		/* TM has already timed out and we got
+		 * delayed completion. Ignore completion
+		 * processing.
+		 */
+		return;
+	}
+
+	tm_req = &(io_req->mp_req);
+	fc_hdr = &(tm_req->resp_fc_hdr);
+	hdr = (u64 *)fc_hdr;
+	temp_hdr = (u64 *)
+		&task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	hdr[0] = cpu_to_be64(temp_hdr[0]);
+	hdr[1] = cpu_to_be64(temp_hdr[1]);
+	hdr[2] = cpu_to_be64(temp_hdr[2]);
+
+	tm_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+
+	rsp_buf = tm_req->resp_buf;
+
+	if (fc_hdr->fh_r_ctl == FC_RCTL_DD_CMD_STATUS) {
+		bnx2fc_parse_fcp_rsp(io_req,
+				     (struct fcoe_fcp_rsp_payload *)
+				     rsp_buf, num_rq);
+		if (io_req->fcp_rsp_code == 0) {
+			/* TM successful */
+			if (tm_req->tm_flags & FCP_TMF_LUN_RESET)
+				bnx2fc_lun_reset_cmpl(io_req);
+			else if (tm_req->tm_flags & FCP_TMF_TGT_RESET)
+				bnx2fc_tgt_reset_cmpl(io_req);
+		}
+	} else {
+		printk(KERN_ERR PFX "tmf's fc_hdr r_ctl = 0x%x\n",
+			fc_hdr->fh_r_ctl);
+	}
+	if (!sc_cmd->SCp.ptr) {
+		printk(KERN_ALERT PFX "tm_compl: SCp.ptr is NULL\n");
+		return;
+	}
+	switch (io_req->fcp_status) {
+	case FC_GOOD:
+		if (io_req->cdb_status == 0) {
+			/* Good IO completion */
+			sc_cmd->result = DID_OK << 16;
+		} else {
+			/* Transport status is good, SCSI status not good */
+			sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+		}
+		if (io_req->fcp_resid)
+			scsi_set_resid(sc_cmd, io_req->fcp_resid);
+		break;
+
+	default:
+		BNX2FC_IO_DBG(io_req, "process_tm_compl: fcp_status = %d\n",
+			   io_req->fcp_status);
+		break;
+	}
+
+	sc_cmd = io_req->sc_cmd;
+	io_req->sc_cmd = NULL;
+
+	/* check if the io_req exists in tgt's tmf_q */
+	if (io_req->on_tmf_queue) {
+
+		list_del_init(&io_req->link);
+		io_req->on_tmf_queue = 0;
+	} else {
+
+		printk(KERN_ALERT PFX "Command not on active_cmd_queue!\n");
+		return;
+	}
+
+	sc_cmd->SCp.ptr = NULL;
+	sc_cmd->scsi_done(sc_cmd);
+
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	if (io_req->wait_for_comp) {
+		BNX2FC_IO_DBG(io_req, "tm_compl - wake up the waiter\n");
+		complete(&io_req->tm_done);
+	}
+}
+
+static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
+			   int bd_index)
+{
+	struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
+	int frag_size, sg_frags;
+
+	sg_frags = 0;
+	while (sg_len) {
+		if (sg_len >= BNX2FC_BD_SPLIT_SZ)
+			frag_size = BNX2FC_BD_SPLIT_SZ;
+		else
+			frag_size = sg_len;
+		bd[bd_index + sg_frags].buf_addr_lo = addr & 0xffffffff;
+		bd[bd_index + sg_frags].buf_addr_hi  = addr >> 32;
+		bd[bd_index + sg_frags].buf_len = (u16)frag_size;
+		bd[bd_index + sg_frags].flags = 0;
+
+		addr += (u64) frag_size;
+		sg_frags++;
+		sg_len -= frag_size;
+	}
+	return sg_frags;
+
+}
+
+static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc = io_req->sc_cmd;
+	struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
+	struct scatterlist *sg;
+	int byte_count = 0;
+	int sg_count = 0;
+	int bd_count = 0;
+	int sg_frags;
+	unsigned int sg_len;
+	u64 addr;
+	int i;
+
+	sg_count = scsi_dma_map(sc);
+	scsi_for_each_sg(sc, sg, sg_count, i) {
+		sg_len = sg_dma_len(sg);
+		addr = sg_dma_address(sg);
+		if (sg_len > BNX2FC_MAX_BD_LEN) {
+			sg_frags = bnx2fc_split_bd(io_req, addr, sg_len,
+						   bd_count);
+		} else {
+
+			sg_frags = 1;
+			bd[bd_count].buf_addr_lo = addr & 0xffffffff;
+			bd[bd_count].buf_addr_hi  = addr >> 32;
+			bd[bd_count].buf_len = (u16)sg_len;
+			bd[bd_count].flags = 0;
+		}
+		bd_count += sg_frags;
+		byte_count += sg_len;
+	}
+	if (byte_count != scsi_bufflen(sc))
+		printk(KERN_ERR PFX "byte_count = %d != scsi_bufflen = %d, "
+			"task_id = 0x%x\n", byte_count, scsi_bufflen(sc),
+			io_req->xid);
+	return bd_count;
+}
+
+static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc = io_req->sc_cmd;
+	struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
+	int bd_count;
+
+	if (scsi_sg_count(sc))
+		bd_count = bnx2fc_map_sg(io_req);
+	else {
+		bd_count = 0;
+		bd[0].buf_addr_lo = bd[0].buf_addr_hi = 0;
+		bd[0].buf_len = bd[0].flags = 0;
+	}
+	io_req->bd_tbl->bd_valid = bd_count;
+}
+
+static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc = io_req->sc_cmd;
+
+	if (io_req->bd_tbl->bd_valid && sc) {
+		scsi_dma_unmap(sc);
+		io_req->bd_tbl->bd_valid = 0;
+	}
+}
+
+void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
+				  struct fcp_cmnd *fcp_cmnd)
+{
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	char tag[2];
+
+	memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
+
+	int_to_scsilun(sc_cmd->device->lun,
+			(struct scsi_lun *) fcp_cmnd->fc_lun);
+
+
+	fcp_cmnd->fc_dl = htonl(io_req->data_xfer_len);
+	memcpy(fcp_cmnd->fc_cdb, sc_cmd->cmnd, sc_cmd->cmd_len);
+
+	fcp_cmnd->fc_cmdref = 0;
+	fcp_cmnd->fc_pri_ta = 0;
+	fcp_cmnd->fc_tm_flags = io_req->mp_req.tm_flags;
+	fcp_cmnd->fc_flags = io_req->io_req_flags;
+
+	if (scsi_populate_tag_msg(sc_cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			fcp_cmnd->fc_pri_ta = FCP_PTA_HEADQ;
+			break;
+		case ORDERED_QUEUE_TAG:
+			fcp_cmnd->fc_pri_ta = FCP_PTA_ORDERED;
+			break;
+		default:
+			fcp_cmnd->fc_pri_ta = FCP_PTA_SIMPLE;
+			break;
+		}
+	} else {
+		fcp_cmnd->fc_pri_ta = 0;
+	}
+}
+
+static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
+				 struct fcoe_fcp_rsp_payload *fcp_rsp,
+				 u8 num_rq)
+{
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	u8 rsp_flags = fcp_rsp->fcp_flags.flags;
+	u32 rq_buff_len = 0;
+	int i;
+	unsigned char *rq_data;
+	unsigned char *dummy;
+	int fcp_sns_len = 0;
+	int fcp_rsp_len = 0;
+
+	io_req->fcp_status = FC_GOOD;
+	io_req->fcp_resid = fcp_rsp->fcp_resid;
+
+	io_req->scsi_comp_flags = rsp_flags;
+	CMD_SCSI_STATUS(sc_cmd) = io_req->cdb_status =
+				fcp_rsp->scsi_status_code;
+
+	/* Fetch fcp_rsp_info and fcp_sns_info if available */
+	if (num_rq) {
+
+		/*
+		 * We do not anticipate num_rq >1, as the linux defined
+		 * SCSI_SENSE_BUFFERSIZE is 96 bytes + 8 bytes of FCP_RSP_INFO
+		 * 256 bytes of single rq buffer is good enough to hold this.
+		 */
+
+		if (rsp_flags &
+		    FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID) {
+			fcp_rsp_len = rq_buff_len
+					= fcp_rsp->fcp_rsp_len;
+		}
+
+		if (rsp_flags &
+		    FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID) {
+			fcp_sns_len = fcp_rsp->fcp_sns_len;
+			rq_buff_len += fcp_rsp->fcp_sns_len;
+		}
+
+		io_req->fcp_rsp_len = fcp_rsp_len;
+		io_req->fcp_sns_len = fcp_sns_len;
+
+		if (rq_buff_len > num_rq * BNX2FC_RQ_BUF_SZ) {
+			/* Invalid sense sense length. */
+			printk(KERN_ALERT PFX "invalid sns length %d\n",
+				rq_buff_len);
+			/* reset rq_buff_len */
+			rq_buff_len =  num_rq * BNX2FC_RQ_BUF_SZ;
+		}
+
+		rq_data = bnx2fc_get_next_rqe(tgt, 1);
+
+		if (num_rq > 1) {
+			/* We do not need extra sense data */
+			for (i = 1; i < num_rq; i++)
+				dummy = bnx2fc_get_next_rqe(tgt, 1);
+		}
+
+		/* fetch fcp_rsp_code */
+		if ((fcp_rsp_len == 4) || (fcp_rsp_len == 8)) {
+			/* Only for task management function */
+			io_req->fcp_rsp_code = rq_data[3];
+			printk(KERN_ERR PFX "fcp_rsp_code = %d\n",
+				io_req->fcp_rsp_code);
+		}
+
+		/* fetch sense data */
+		rq_data += fcp_rsp_len;
+
+		if (fcp_sns_len > SCSI_SENSE_BUFFERSIZE) {
+			printk(KERN_ERR PFX "Truncating sense buffer\n");
+			fcp_sns_len = SCSI_SENSE_BUFFERSIZE;
+		}
+
+		memset(sc_cmd->sense_buffer, 0, sizeof(sc_cmd->sense_buffer));
+		if (fcp_sns_len)
+			memcpy(sc_cmd->sense_buffer, rq_data, fcp_sns_len);
+
+		/* return RQ entries */
+		for (i = 0; i < num_rq; i++)
+			bnx2fc_return_rqe(tgt, 1);
+	}
+}
+
+/**
+ * bnx2fc_queuecommand - Queuecommand function of the scsi template
+ *
+ * @host:	The Scsi_Host the command was issued to
+ * @sc_cmd:	struct scsi_cmnd to be executed
+ *
+ * This is the IO strategy routine, called by SCSI-ML
+ **/
+int bnx2fc_queuecommand(struct Scsi_Host *host,
+			struct scsi_cmnd *sc_cmd)
+{
+	struct fc_lport *lport = shost_priv(host);
+	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct bnx2fc_rport *tgt;
+	struct bnx2fc_cmd *io_req;
+	int rc = 0;
+	int rval;
+
+	rval = fc_remote_port_chkready(rport);
+	if (rval) {
+		sc_cmd->result = rval;
+		sc_cmd->scsi_done(sc_cmd);
+		return 0;
+	}
+
+	if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit_qcmd;
+	}
+
+	/* rport and tgt are allocated together, so tgt should be non-NULL */
+	tgt = (struct bnx2fc_rport *)&rp[1];
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		/*
+		 * Session is not offloaded yet. Let SCSI-ml retry
+		 * the command.
+		 */
+		rc = SCSI_MLQUEUE_TARGET_BUSY;
+		goto exit_qcmd;
+	}
+
+	io_req = bnx2fc_cmd_alloc(tgt);
+	if (!io_req) {
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit_qcmd;
+	}
+	io_req->sc_cmd = sc_cmd;
+
+	if (bnx2fc_post_io_req(tgt, io_req)) {
+		printk(KERN_ERR PFX "Unable to post io_req\n");
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit_qcmd;
+	}
+exit_qcmd:
+	return rc;
+}
+
+void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
+				   struct fcoe_task_ctx_entry *task,
+				   u8 num_rq)
+{
+	struct fcoe_fcp_rsp_payload *fcp_rsp;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct scsi_cmnd *sc_cmd;
+	struct Scsi_Host *host;
+
+
+	/* scsi_cmd_cmpl is called with tgt lock held */
+
+	if (test_and_set_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags)) {
+		/* we will not receive ABTS response for this IO */
+		BNX2FC_IO_DBG(io_req, "Timer context finished processing "
+			   "this scsi cmd\n");
+	}
+
+	/* Cancel the timeout_work, as we received IO completion */
+	if (cancel_delayed_work(&io_req->timeout_work))
+		kref_put(&io_req->refcount,
+			 bnx2fc_cmd_release); /* drop timer hold */
+
+	sc_cmd = io_req->sc_cmd;
+	if (sc_cmd == NULL) {
+		printk(KERN_ERR PFX "scsi_cmd_compl - sc_cmd is NULL\n");
+		return;
+	}
+
+	/* Fetch fcp_rsp from task context and perform cmd completion */
+	fcp_rsp = (struct fcoe_fcp_rsp_payload *)
+		   &(task->cmn.general.rsp_info.fcp_rsp.payload);
+
+	/* parse fcp_rsp and obtain sense data from RQ if available */
+	bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
+
+	host = sc_cmd->device->host;
+	if (!sc_cmd->SCp.ptr) {
+		printk(KERN_ERR PFX "SCp.ptr is NULL\n");
+		return;
+	}
+	io_req->sc_cmd = NULL;
+
+	if (io_req->on_active_queue) {
+		list_del_init(&io_req->link);
+		io_req->on_active_queue = 0;
+		/* Move IO req to retire queue */
+		list_add_tail(&io_req->link, &tgt->io_retire_queue);
+	} else {
+		/* This should not happen, but could have been pulled
+		 * by bnx2fc_flush_active_ios(), or during a race
+		 * between command abort and (late) completion.
+		 */
+		BNX2FC_IO_DBG(io_req, "xid not on active_cmd_queue\n");
+		if (io_req->wait_for_comp)
+			if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+					       &io_req->req_flags))
+				complete(&io_req->tm_done);
+	}
+
+	bnx2fc_unmap_sg_list(io_req);
+
+	switch (io_req->fcp_status) {
+	case FC_GOOD:
+		if (io_req->cdb_status == 0) {
+			/* Good IO completion */
+			sc_cmd->result = DID_OK << 16;
+		} else {
+			/* Transport status is good, SCSI status not good */
+			BNX2FC_IO_DBG(io_req, "scsi_cmpl: cdb_status = %d"
+				 " fcp_resid = 0x%x\n",
+				io_req->cdb_status, io_req->fcp_resid);
+			sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+		}
+		if (io_req->fcp_resid)
+			scsi_set_resid(sc_cmd, io_req->fcp_resid);
+		break;
+	default:
+		printk(KERN_ALERT PFX "scsi_cmd_compl: fcp_status = %d\n",
+			io_req->fcp_status);
+		break;
+	}
+	sc_cmd->SCp.ptr = NULL;
+	sc_cmd->scsi_done(sc_cmd);
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+}
+
+static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
+			       struct bnx2fc_cmd *io_req)
+{
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct fc_lport *lport = port->lport;
+	struct fcoe_dev_stats *stats;
+	int task_idx, index;
+	u16 xid;
+
+	/* Initialize rest of io_req fields */
+	io_req->cmd_type = BNX2FC_SCSI_CMD;
+	io_req->port = port;
+	io_req->tgt = tgt;
+	io_req->data_xfer_len = scsi_bufflen(sc_cmd);
+	sc_cmd->SCp.ptr = (char *)io_req;
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		io_req->io_req_flags = BNX2FC_READ;
+		stats->InputRequests++;
+		stats->InputBytes += io_req->data_xfer_len;
+	} else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
+		io_req->io_req_flags = BNX2FC_WRITE;
+		stats->OutputRequests++;
+		stats->OutputBytes += io_req->data_xfer_len;
+	} else {
+		io_req->io_req_flags = 0;
+		stats->ControlRequests++;
+	}
+	put_cpu();
+
+	xid = io_req->xid;
+
+	/* Build buffer descriptor list for firmware from sg list */
+	bnx2fc_build_bd_list_from_sg(io_req);
+
+	task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_task(io_req, task);
+
+	spin_lock_bh(&tgt->tgt_lock);
+
+	if (tgt->flush_in_prog) {
+		printk(KERN_ERR PFX "Flush in progress..Host Busy\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return -EAGAIN;
+	}
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		printk(KERN_ERR PFX "Session not ready...post_io\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return -EAGAIN;
+	}
+
+	/* Time IO req */
+	bnx2fc_cmd_timer_set(io_req, BNX2FC_IO_TIMEOUT);
+	/* Obtain free SQ entry */
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Enqueue the io_req to active_cmd_queue */
+
+	io_req->on_active_queue = 1;
+	/* move io_req from pending_queue to active_queue */
+	list_add_tail(&io_req->link, &tgt->active_cmd_queue);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+	spin_unlock_bh(&tgt->tgt_lock);
+	return 0;
+}
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
new file mode 100644
index 0000000..7ea93af
--- /dev/null
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -0,0 +1,844 @@
+/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2010 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+static void bnx2fc_upld_timer(unsigned long data);
+static void bnx2fc_ofld_timer(unsigned long data);
+static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
+			   struct fcoe_port *port,
+			   struct fc_rport_priv *rdata);
+static u32 bnx2fc_alloc_conn_id(struct bnx2fc_hba *hba,
+				struct bnx2fc_rport *tgt);
+static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
+			      struct bnx2fc_rport *tgt);
+static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
+			      struct bnx2fc_rport *tgt);
+static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id);
+
+static void bnx2fc_upld_timer(unsigned long data)
+{
+
+	struct bnx2fc_rport *tgt = (struct bnx2fc_rport *)data;
+
+	BNX2FC_TGT_DBG(tgt, "upld_timer - Upload compl not received!!\n");
+	/* fake upload completion */
+	clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+	set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->upld_wait);
+}
+
+static void bnx2fc_ofld_timer(unsigned long data)
+{
+
+	struct bnx2fc_rport *tgt = (struct bnx2fc_rport *)data;
+
+	BNX2FC_TGT_DBG(tgt, "entered bnx2fc_ofld_timer\n");
+	/* NOTE: This function should never be called, as
+	 * offload should never timeout
+	 */
+	/*
+	 * If the timer has expired, this session is dead
+	 * Clear offloaded flag and logout of this device.
+	 * Since OFFLOADED flag is cleared, this case
+	 * will be considered as offload error and the
+	 * port will be logged off, and conn_id, session
+	 * resources are freed up in bnx2fc_offload_session
+	 */
+	clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+	set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->ofld_wait);
+}
+
+static void bnx2fc_offload_session(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt,
+					struct fc_rport_priv *rdata)
+{
+	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport *rport = rdata->rport;
+	struct bnx2fc_hba *hba = port->priv;
+	int rval;
+	int i = 0;
+
+	/* Initialize bnx2fc_rport */
+	/* NOTE: tgt is already bzero'd */
+	rval = bnx2fc_init_tgt(tgt, port, rdata);
+	if (rval) {
+		printk(KERN_ERR PFX "Failed to allocate conn id for "
+			"port_id (%6x)\n", rport->port_id);
+		goto ofld_err;
+	}
+
+	/* Allocate session resources */
+	rval = bnx2fc_alloc_session_resc(hba, tgt);
+	if (rval) {
+		printk(KERN_ERR PFX "Failed to allocate resources\n");
+		goto ofld_err;
+	}
+
+	/*
+	 * Initialize FCoE session offload process.
+	 * Upon completion of offload process add
+	 * rport to list of rports
+	 */
+retry_ofld:
+	clear_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	rval = bnx2fc_send_session_ofld_req(port, tgt);
+	if (rval) {
+		printk(KERN_ERR PFX "ofld_req failed\n");
+		goto ofld_err;
+	}
+
+	/*
+	 * wait for the session is offloaded and enabled. 3 Secs
+	 * should be ample time for this process to complete.
+	 */
+	setup_timer(&tgt->ofld_timer, bnx2fc_ofld_timer, (unsigned long)tgt);
+	mod_timer(&tgt->ofld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+	wait_event_interruptible(tgt->ofld_wait,
+				 (test_bit(
+				  BNX2FC_FLAG_OFLD_REQ_CMPL,
+				  &tgt->flags)));
+	if (signal_pending(current))
+		flush_signals(current);
+
+	del_timer_sync(&tgt->ofld_timer);
+
+	if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) {
+		if (test_and_clear_bit(BNX2FC_FLAG_CTX_ALLOC_FAILURE,
+				       &tgt->flags)) {
+			BNX2FC_TGT_DBG(tgt, "ctx_alloc_failure, "
+				"retry ofld..%d\n", i++);
+			msleep_interruptible(1000);
+			if (i > 3) {
+				i = 0;
+				goto ofld_err;
+			}
+			goto retry_ofld;
+		}
+		goto ofld_err;
+	}
+	if (bnx2fc_map_doorbell(tgt)) {
+		printk(KERN_ERR PFX "map doorbell failed - no mem\n");
+		/* upload will take care of cleaning up sess resc */
+		lport->tt.rport_logoff(rdata);
+	}
+	return;
+
+ofld_err:
+	/* couldn't offload the session. log off from this rport */
+	BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n");
+	lport->tt.rport_logoff(rdata);
+	/* Free session resources */
+	bnx2fc_free_session_resc(hba, tgt);
+	if (tgt->fcoe_conn_id != -1)
+		bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+}
+
+void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
+{
+	struct bnx2fc_cmd *io_req;
+	struct list_head *list;
+	struct list_head *tmp;
+	int rc;
+	int i = 0;
+	BNX2FC_TGT_DBG(tgt, "Entered flush_active_ios - %d\n",
+		       tgt->num_active_ios.counter);
+
+	spin_lock_bh(&tgt->tgt_lock);
+	tgt->flush_in_prog = 1;
+
+	list_for_each_safe(list, tmp, &tgt->active_cmd_queue) {
+		i++;
+		io_req = (struct bnx2fc_cmd *)list;
+		list_del_init(&io_req->link);
+		io_req->on_active_queue = 0;
+		BNX2FC_IO_DBG(io_req, "cmd_queue cleanup\n");
+
+		if (cancel_delayed_work(&io_req->timeout_work)) {
+			if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+						&io_req->req_flags)) {
+				/* Handle eh_abort timeout */
+				BNX2FC_IO_DBG(io_req, "eh_abort for IO "
+					      "cleaned up\n");
+				complete(&io_req->tm_done);
+			}
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+		}
+
+		set_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags);
+		set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags);
+		rc = bnx2fc_initiate_cleanup(io_req);
+		BUG_ON(rc);
+	}
+
+	list_for_each_safe(list, tmp, &tgt->els_queue) {
+		i++;
+		io_req = (struct bnx2fc_cmd *)list;
+		list_del_init(&io_req->link);
+		io_req->on_active_queue = 0;
+
+		BNX2FC_IO_DBG(io_req, "els_queue cleanup\n");
+
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+
+		if ((io_req->cb_func) && (io_req->cb_arg)) {
+			io_req->cb_func(io_req->cb_arg);
+			io_req->cb_arg = NULL;
+		}
+
+		rc = bnx2fc_initiate_cleanup(io_req);
+		BUG_ON(rc);
+	}
+
+	list_for_each_safe(list, tmp, &tgt->io_retire_queue) {
+		i++;
+		io_req = (struct bnx2fc_cmd *)list;
+		list_del_init(&io_req->link);
+
+		BNX2FC_IO_DBG(io_req, "retire_queue flush\n");
+
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount, bnx2fc_cmd_release);
+
+		clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags);
+	}
+
+	BNX2FC_TGT_DBG(tgt, "IOs flushed = %d\n", i);
+	i = 0;
+	spin_unlock_bh(&tgt->tgt_lock);
+	/* wait for active_ios to go to 0 */
+	while ((tgt->num_active_ios.counter != 0) && (i++ < BNX2FC_WAIT_CNT))
+		msleep(25);
+	if (tgt->num_active_ios.counter != 0)
+		printk(KERN_ERR PFX "CLEANUP on port 0x%x:"
+				    " active_ios = %d\n",
+			tgt->rdata->ids.port_id, tgt->num_active_ios.counter);
+	spin_lock_bh(&tgt->tgt_lock);
+	tgt->flush_in_prog = 0;
+	spin_unlock_bh(&tgt->tgt_lock);
+}
+
+static void bnx2fc_upload_session(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt)
+{
+	struct bnx2fc_hba *hba = port->priv;
+
+	BNX2FC_TGT_DBG(tgt, "upload_session: active_ios = %d\n",
+		tgt->num_active_ios.counter);
+
+	/*
+	 * Called with hba->hba_mutex held.
+	 * This is a blocking call
+	 */
+	clear_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+	bnx2fc_send_session_disable_req(port, tgt);
+
+	/*
+	 * wait for upload to complete. 3 Secs
+	 * should be sufficient time for this process to complete.
+	 */
+	setup_timer(&tgt->upld_timer, bnx2fc_upld_timer, (unsigned long)tgt);
+	mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+	BNX2FC_TGT_DBG(tgt, "waiting for disable compl\n");
+	wait_event_interruptible(tgt->upld_wait,
+				 (test_bit(
+				  BNX2FC_FLAG_UPLD_REQ_COMPL,
+				  &tgt->flags)));
+
+	if (signal_pending(current))
+		flush_signals(current);
+
+	del_timer_sync(&tgt->upld_timer);
+
+	/*
+	 * traverse thru the active_q and tmf_q and cleanup
+	 * IOs in these lists
+	 */
+	BNX2FC_TGT_DBG(tgt, "flush/upload - disable wait flags = 0x%lx\n",
+		       tgt->flags);
+	bnx2fc_flush_active_ios(tgt);
+
+	/* Issue destroy KWQE */
+	if (test_bit(BNX2FC_FLAG_DISABLED, &tgt->flags)) {
+		BNX2FC_TGT_DBG(tgt, "send destroy req\n");
+		clear_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+		bnx2fc_send_session_destroy_req(hba, tgt);
+
+		/* wait for destroy to complete */
+		setup_timer(&tgt->upld_timer,
+			    bnx2fc_upld_timer, (unsigned long)tgt);
+		mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+		wait_event_interruptible(tgt->upld_wait,
+					 (test_bit(
+					  BNX2FC_FLAG_UPLD_REQ_COMPL,
+					  &tgt->flags)));
+
+		if (!(test_bit(BNX2FC_FLAG_DESTROYED, &tgt->flags)))
+			printk(KERN_ERR PFX "ERROR!! destroy timed out\n");
+
+		BNX2FC_TGT_DBG(tgt, "destroy wait complete flags = 0x%lx\n",
+			tgt->flags);
+		if (signal_pending(current))
+			flush_signals(current);
+
+		del_timer_sync(&tgt->upld_timer);
+
+	} else
+		printk(KERN_ERR PFX "ERROR!! DISABLE req timed out, destroy"
+				" not sent to FW\n");
+
+	/* Free session resources */
+	spin_lock_bh(&tgt->cq_lock);
+	bnx2fc_free_session_resc(hba, tgt);
+	bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+	spin_unlock_bh(&tgt->cq_lock);
+}
+
+static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
+			   struct fcoe_port *port,
+			   struct fc_rport_priv *rdata)
+{
+
+	struct fc_rport *rport = rdata->rport;
+	struct bnx2fc_hba *hba = port->priv;
+
+	tgt->rport = rport;
+	tgt->rdata = rdata;
+	tgt->port = port;
+
+	if (hba->num_ofld_sess >= BNX2FC_NUM_MAX_SESS) {
+		BNX2FC_TGT_DBG(tgt, "exceeded max sessions. logoff this tgt\n");
+		tgt->fcoe_conn_id = -1;
+		return -1;
+	}
+
+	tgt->fcoe_conn_id = bnx2fc_alloc_conn_id(hba, tgt);
+	if (tgt->fcoe_conn_id == -1)
+		return -1;
+
+	BNX2FC_TGT_DBG(tgt, "init_tgt - conn_id = 0x%x\n", tgt->fcoe_conn_id);
+
+	tgt->max_sqes = BNX2FC_SQ_WQES_MAX;
+	tgt->max_rqes = BNX2FC_RQ_WQES_MAX;
+	tgt->max_cqes = BNX2FC_CQ_WQES_MAX;
+
+	/* Initialize the toggle bit */
+	tgt->sq_curr_toggle_bit = 1;
+	tgt->cq_curr_toggle_bit = 1;
+	tgt->sq_prod_idx = 0;
+	tgt->cq_cons_idx = 0;
+	tgt->rq_prod_idx = 0x8000;
+	tgt->rq_cons_idx = 0;
+	atomic_set(&tgt->num_active_ios, 0);
+
+	tgt->work_time_slice = 2;
+
+	spin_lock_init(&tgt->tgt_lock);
+	spin_lock_init(&tgt->cq_lock);
+
+	/* Initialize active_cmd_queue list */
+	INIT_LIST_HEAD(&tgt->active_cmd_queue);
+
+	/* Initialize IO retire queue */
+	INIT_LIST_HEAD(&tgt->io_retire_queue);
+
+	INIT_LIST_HEAD(&tgt->els_queue);
+
+	/* Initialize active_tm_queue list */
+	INIT_LIST_HEAD(&tgt->active_tm_queue);
+
+	init_waitqueue_head(&tgt->ofld_wait);
+	init_waitqueue_head(&tgt->upld_wait);
+
+	return 0;
+}
+
+/**
+ * This event_callback is called after successful completion of libfc
+ * initiated target login. bnx2fc can proceed with initiating the session
+ * establishment.
+ */
+void bnx2fc_rport_event_handler(struct fc_lport *lport,
+				struct fc_rport_priv *rdata,
+				enum fc_rport_event event)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct fc_rport *rport = rdata->rport;
+	struct fc_rport_libfc_priv *rp;
+	struct bnx2fc_rport *tgt;
+	u32 port_id;
+
+	BNX2FC_HBA_DBG(lport, "rport_event_hdlr: event = %d, port_id = 0x%x\n",
+		event, rdata->ids.port_id);
+	switch (event) {
+	case RPORT_EV_READY:
+		if (!rport) {
+			printk(KERN_ALERT PFX "rport is NULL: ERROR!\n");
+			break;
+		}
+
+		rp = rport->dd_data;
+		if (rport->port_id == FC_FID_DIR_SERV) {
+			/*
+			 * bnx2fc_rport structure doesnt exist for
+			 * directory server.
+			 * We should not come here, as lport will
+			 * take care of fabric login
+			 */
+			printk(KERN_ALERT PFX "%x - rport_event_handler ERROR\n",
+				rdata->ids.port_id);
+			break;
+		}
+
+		if (rdata->spp_type != FC_TYPE_FCP) {
+			BNX2FC_HBA_DBG(lport, "not FCP type target."
+				   " not offloading\n");
+			break;
+		}
+		if (!(rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET)) {
+			BNX2FC_HBA_DBG(lport, "not FCP_TARGET"
+				   " not offloading\n");
+			break;
+		}
+
+		/*
+		 * Offlaod process is protected with hba mutex.
+		 * Use the same mutex_lock for upload process too
+		 */
+		mutex_lock(&hba->hba_mutex);
+		tgt = (struct bnx2fc_rport *)&rp[1];
+
+		/* This can happen when ADISC finds the same target */
+		if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) {
+			BNX2FC_TGT_DBG(tgt, "already offloaded\n");
+			mutex_unlock(&hba->hba_mutex);
+			return;
+		}
+
+		/*
+		 * Offload the session. This is a blocking call, and will
+		 * wait until the session is offloaded.
+		 */
+		bnx2fc_offload_session(port, tgt, rdata);
+
+		BNX2FC_TGT_DBG(tgt, "OFFLOAD num_ofld_sess = %d\n",
+			hba->num_ofld_sess);
+
+		if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) {
+			/*
+			 * Session is offloaded and enabled. Map
+			 * doorbell register for this target
+			 */
+			BNX2FC_TGT_DBG(tgt, "sess offloaded\n");
+			/* This counter is protected with hba mutex */
+			hba->num_ofld_sess++;
+
+			set_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
+		} else {
+			/*
+			 * Offload or enable would have failed.
+			 * In offload/enable completion path, the
+			 * rport would have already been removed
+			 */
+			BNX2FC_TGT_DBG(tgt, "Port is being logged off as "
+				   "offloaded flag not set\n");
+		}
+		mutex_unlock(&hba->hba_mutex);
+		break;
+	case RPORT_EV_LOGO:
+	case RPORT_EV_FAILED:
+	case RPORT_EV_STOP:
+		port_id = rdata->ids.port_id;
+		if (port_id == FC_FID_DIR_SERV)
+			break;
+
+		if (!rport) {
+			printk(KERN_ALERT PFX "%x - rport not created Yet!!\n",
+				port_id);
+			break;
+		}
+		rp = rport->dd_data;
+		mutex_lock(&hba->hba_mutex);
+		/*
+		 * Perform session upload. Note that rdata->peers is already
+		 * removed from disc->rports list before we get this event.
+		 */
+		tgt = (struct bnx2fc_rport *)&rp[1];
+
+		if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) {
+			mutex_unlock(&hba->hba_mutex);
+			break;
+		}
+		clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
+
+		bnx2fc_upload_session(port, tgt);
+		hba->num_ofld_sess--;
+		BNX2FC_TGT_DBG(tgt, "UPLOAD num_ofld_sess = %d\n",
+			hba->num_ofld_sess);
+		/*
+		 * Try to wake up the linkdown wait thread. If num_ofld_sess
+		 * is 0, the waiting therad wakes up
+		 */
+		if ((hba->wait_for_link_down) &&
+		    (hba->num_ofld_sess == 0)) {
+			wake_up_interruptible(&hba->shutdown_wait);
+		}
+		if (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags)) {
+			printk(KERN_ERR PFX "Relogin to the tgt\n");
+			mutex_lock(&lport->disc.disc_mutex);
+			lport->tt.rport_login(rdata);
+			mutex_unlock(&lport->disc.disc_mutex);
+		}
+		mutex_unlock(&hba->hba_mutex);
+
+		break;
+
+	case RPORT_EV_NONE:
+		break;
+	}
+}
+
+/**
+ * bnx2fc_tgt_lookup() - Lookup a bnx2fc_rport by port_id
+ *
+ * @port:  fcoe_port struct to lookup the target port on
+ * @port_id: The remote port ID to look up
+ */
+struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
+					     u32 port_id)
+{
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_rport *tgt;
+	struct fc_rport_priv *rdata;
+	int i;
+
+	for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
+		tgt = hba->tgt_ofld_list[i];
+		if ((tgt) && (tgt->port == port)) {
+			rdata = tgt->rdata;
+			if (rdata->ids.port_id == port_id) {
+				if (rdata->rp_state != RPORT_ST_DELETE) {
+					BNX2FC_TGT_DBG(tgt, "rport "
+						"obtained\n");
+					return tgt;
+				} else {
+					printk(KERN_ERR PFX "rport 0x%x "
+						"is in DELETED state\n",
+						rdata->ids.port_id);
+					return NULL;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+
+
+/**
+ * bnx2fc_alloc_conn_id - allocates FCOE Connection id
+ *
+ * @hba:	pointer to adapter structure
+ * @tgt:	pointer to bnx2fc_rport structure
+ */
+static u32 bnx2fc_alloc_conn_id(struct bnx2fc_hba *hba,
+				struct bnx2fc_rport *tgt)
+{
+	u32 conn_id, next;
+
+	/* called with hba mutex held */
+
+	/*
+	 * tgt_ofld_list access is synchronized using
+	 * both hba mutex and hba lock. Atleast hba mutex or
+	 * hba lock needs to be held for read access.
+	 */
+
+	spin_lock_bh(&hba->hba_lock);
+	next = hba->next_conn_id;
+	conn_id = hba->next_conn_id++;
+	if (hba->next_conn_id == BNX2FC_NUM_MAX_SESS)
+		hba->next_conn_id = 0;
+
+	while (hba->tgt_ofld_list[conn_id] != NULL) {
+		conn_id++;
+		if (conn_id == BNX2FC_NUM_MAX_SESS)
+			conn_id = 0;
+
+		if (conn_id == next) {
+			/* No free conn_ids are available */
+			spin_unlock_bh(&hba->hba_lock);
+			return -1;
+		}
+	}
+	hba->tgt_ofld_list[conn_id] = tgt;
+	tgt->fcoe_conn_id = conn_id;
+	spin_unlock_bh(&hba->hba_lock);
+	return conn_id;
+}
+
+static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id)
+{
+	/* called with hba mutex held */
+	spin_lock_bh(&hba->hba_lock);
+	hba->tgt_ofld_list[conn_id] = NULL;
+	hba->next_conn_id = conn_id;
+	spin_unlock_bh(&hba->hba_lock);
+}
+
+/**
+ *bnx2fc_alloc_session_resc - Allocate qp resources for the session
+ *
+ */
+static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
+					struct bnx2fc_rport *tgt)
+{
+	dma_addr_t page;
+	int num_pages;
+	u32 *pbl;
+
+	/* Allocate and map SQ */
+	tgt->sq_mem_size = tgt->max_sqes * BNX2FC_SQ_WQE_SIZE;
+	tgt->sq_mem_size = (tgt->sq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+				     &tgt->sq_dma, GFP_KERNEL);
+	if (!tgt->sq) {
+		printk(KERN_ALERT PFX "unable to allocate SQ memory %d\n",
+			tgt->sq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->sq, 0, tgt->sq_mem_size);
+
+	/* Allocate and map CQ */
+	tgt->cq_mem_size = tgt->max_cqes * BNX2FC_CQ_WQE_SIZE;
+	tgt->cq_mem_size = (tgt->cq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+				     &tgt->cq_dma, GFP_KERNEL);
+	if (!tgt->cq) {
+		printk(KERN_ALERT PFX "unable to allocate CQ memory %d\n",
+			tgt->cq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->cq, 0, tgt->cq_mem_size);
+
+	/* Allocate and map RQ and RQ PBL */
+	tgt->rq_mem_size = tgt->max_rqes * BNX2FC_RQ_WQE_SIZE;
+	tgt->rq_mem_size = (tgt->rq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+					&tgt->rq_dma, GFP_KERNEL);
+	if (!tgt->rq) {
+		printk(KERN_ALERT PFX "unable to allocate RQ memory %d\n",
+			tgt->rq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->rq, 0, tgt->rq_mem_size);
+
+	tgt->rq_pbl_size = (tgt->rq_mem_size / PAGE_SIZE) * sizeof(void *);
+	tgt->rq_pbl_size = (tgt->rq_pbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+					 &tgt->rq_pbl_dma, GFP_KERNEL);
+	if (!tgt->rq_pbl) {
+		printk(KERN_ALERT PFX "unable to allocate RQ PBL %d\n",
+			tgt->rq_pbl_size);
+		goto mem_alloc_failure;
+	}
+
+	memset(tgt->rq_pbl, 0, tgt->rq_pbl_size);
+	num_pages = tgt->rq_mem_size / PAGE_SIZE;
+	page = tgt->rq_dma;
+	pbl = (u32 *)tgt->rq_pbl;
+
+	while (num_pages--) {
+		*pbl = (u32)page;
+		pbl++;
+		*pbl = (u32)((u64)page >> 32);
+		pbl++;
+		page += PAGE_SIZE;
+	}
+
+	/* Allocate and map XFERQ */
+	tgt->xferq_mem_size = tgt->max_sqes * BNX2FC_XFERQ_WQE_SIZE;
+	tgt->xferq_mem_size = (tgt->xferq_mem_size + (PAGE_SIZE - 1)) &
+			       PAGE_MASK;
+
+	tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
+					&tgt->xferq_dma, GFP_KERNEL);
+	if (!tgt->xferq) {
+		printk(KERN_ALERT PFX "unable to allocate XFERQ %d\n",
+			tgt->xferq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->xferq, 0, tgt->xferq_mem_size);
+
+	/* Allocate and map CONFQ & CONFQ PBL */
+	tgt->confq_mem_size = tgt->max_sqes * BNX2FC_CONFQ_WQE_SIZE;
+	tgt->confq_mem_size = (tgt->confq_mem_size + (PAGE_SIZE - 1)) &
+			       PAGE_MASK;
+
+	tgt->confq = dma_alloc_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
+					&tgt->confq_dma, GFP_KERNEL);
+	if (!tgt->confq) {
+		printk(KERN_ALERT PFX "unable to allocate CONFQ %d\n",
+			tgt->confq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->confq, 0, tgt->confq_mem_size);
+
+	tgt->confq_pbl_size =
+		(tgt->confq_mem_size / PAGE_SIZE) * sizeof(void *);
+	tgt->confq_pbl_size =
+		(tgt->confq_pbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+					    tgt->confq_pbl_size,
+					    &tgt->confq_pbl_dma, GFP_KERNEL);
+	if (!tgt->confq_pbl) {
+		printk(KERN_ALERT PFX "unable to allocate CONFQ PBL %d\n",
+			tgt->confq_pbl_size);
+		goto mem_alloc_failure;
+	}
+
+	memset(tgt->confq_pbl, 0, tgt->confq_pbl_size);
+	num_pages = tgt->confq_mem_size / PAGE_SIZE;
+	page = tgt->confq_dma;
+	pbl = (u32 *)tgt->confq_pbl;
+
+	while (num_pages--) {
+		*pbl = (u32)page;
+		pbl++;
+		*pbl = (u32)((u64)page >> 32);
+		pbl++;
+		page += PAGE_SIZE;
+	}
+
+	/* Allocate and map ConnDB */
+	tgt->conn_db_mem_size = sizeof(struct fcoe_conn_db);
+
+	tgt->conn_db = dma_alloc_coherent(&hba->pcidev->dev,
+					  tgt->conn_db_mem_size,
+					  &tgt->conn_db_dma, GFP_KERNEL);
+	if (!tgt->conn_db) {
+		printk(KERN_ALERT PFX "unable to allocate conn_db %d\n",
+						tgt->conn_db_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->conn_db, 0, tgt->conn_db_mem_size);
+
+
+	/* Allocate and map LCQ */
+	tgt->lcq_mem_size = (tgt->max_sqes + 8) * BNX2FC_SQ_WQE_SIZE;
+	tgt->lcq_mem_size = (tgt->lcq_mem_size + (PAGE_SIZE - 1)) &
+			     PAGE_MASK;
+
+	tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+				      &tgt->lcq_dma, GFP_KERNEL);
+
+	if (!tgt->lcq) {
+		printk(KERN_ALERT PFX "unable to allocate lcq %d\n",
+		       tgt->lcq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->lcq, 0, tgt->lcq_mem_size);
+
+	/* Arm CQ */
+	tgt->conn_db->cq_arm.lo = -1;
+	tgt->conn_db->rq_prod = 0x8000;
+
+	return 0;
+
+mem_alloc_failure:
+	bnx2fc_free_session_resc(hba, tgt);
+	bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+	return -ENOMEM;
+}
+
+/**
+ * bnx2i_free_session_resc - free qp resources for the session
+ *
+ * @hba:	adapter structure pointer
+ * @tgt:	bnx2fc_rport structure pointer
+ *
+ * Free QP resources - SQ/RQ/CQ/XFERQ memory and PBL
+ */
+static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
+						struct bnx2fc_rport *tgt)
+{
+	BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
+
+	if (tgt->ctx_base) {
+		iounmap(tgt->ctx_base);
+		tgt->ctx_base = NULL;
+	}
+	/* Free LCQ */
+	if (tgt->lcq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+				    tgt->lcq, tgt->lcq_dma);
+		tgt->lcq = NULL;
+	}
+	/* Free connDB */
+	if (tgt->conn_db) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->conn_db_mem_size,
+				    tgt->conn_db, tgt->conn_db_dma);
+		tgt->conn_db = NULL;
+	}
+	/* Free confq  and confq pbl */
+	if (tgt->confq_pbl) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->confq_pbl_size,
+				    tgt->confq_pbl, tgt->confq_pbl_dma);
+		tgt->confq_pbl = NULL;
+	}
+	if (tgt->confq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
+				    tgt->confq, tgt->confq_dma);
+		tgt->confq = NULL;
+	}
+	/* Free XFERQ */
+	if (tgt->xferq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
+				    tgt->xferq, tgt->xferq_dma);
+		tgt->xferq = NULL;
+	}
+	/* Free RQ PBL and RQ */
+	if (tgt->rq_pbl) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+				    tgt->rq_pbl, tgt->rq_pbl_dma);
+		tgt->rq_pbl = NULL;
+	}
+	if (tgt->rq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+				    tgt->rq, tgt->rq_dma);
+		tgt->rq = NULL;
+	}
+	/* Free CQ */
+	if (tgt->cq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+				    tgt->cq, tgt->cq_dma);
+		tgt->cq = NULL;
+	}
+	/* Free SQ */
+	if (tgt->sq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+				    tgt->sq, tgt->sq_dma);
+		tgt->sq = NULL;
+	}
+}
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h
index e1ca5fe..cfd5902 100644
--- a/drivers/scsi/bnx2i/bnx2i.h
+++ b/drivers/scsi/bnx2i/bnx2i.h
@@ -360,7 +360,7 @@ struct bnx2i_hba {
 		#define ADAPTER_STATE_LINK_DOWN		2
 		#define ADAPTER_STATE_INIT_FAILED	31
 	unsigned int mtu_supported;
-		#define BNX2I_MAX_MTU_SUPPORTED		1500
+		#define BNX2I_MAX_MTU_SUPPORTED		9000
 
 	struct Scsi_Host *shost;
 
@@ -751,6 +751,8 @@ extern int bnx2i_send_iscsi_login(struct bnx2i_conn *conn,
 				  struct iscsi_task *mtask);
 extern int bnx2i_send_iscsi_tmf(struct bnx2i_conn *conn,
 				  struct iscsi_task *mtask);
+extern int bnx2i_send_iscsi_text(struct bnx2i_conn *conn,
+				 struct iscsi_task *mtask);
 extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn,
 				    struct bnx2i_cmd *cmnd);
 extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn,
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
index 96505e3..1da34c0 100644
--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
+++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
@@ -445,6 +445,56 @@ int bnx2i_send_iscsi_tmf(struct bnx2i_conn *bnx2i_conn,
 }
 
 /**
+ * bnx2i_send_iscsi_text - post iSCSI text WQE to hardware
+ * @conn:	iscsi connection
+ * @mtask:	driver command structure which is requesting
+ *		a WQE to sent to chip for further processing
+ *
+ * prepare and post an iSCSI Text request WQE to CNIC firmware
+ */
+int bnx2i_send_iscsi_text(struct bnx2i_conn *bnx2i_conn,
+			  struct iscsi_task *mtask)
+{
+	struct bnx2i_cmd *bnx2i_cmd;
+	struct bnx2i_text_request *text_wqe;
+	struct iscsi_text *text_hdr;
+	u32 dword;
+
+	bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
+	text_hdr = (struct iscsi_text *)mtask->hdr;
+	text_wqe = (struct bnx2i_text_request *) bnx2i_conn->ep->qp.sq_prod_qe;
+
+	memset(text_wqe, 0, sizeof(struct bnx2i_text_request));
+
+	text_wqe->op_code = text_hdr->opcode;
+	text_wqe->op_attr = text_hdr->flags;
+	text_wqe->data_length = ntoh24(text_hdr->dlength);
+	text_wqe->itt = mtask->itt |
+		(ISCSI_TASK_TYPE_MPATH << ISCSI_TEXT_REQUEST_TYPE_SHIFT);
+	text_wqe->ttt = be32_to_cpu(text_hdr->ttt);
+
+	text_wqe->cmd_sn = be32_to_cpu(text_hdr->cmdsn);
+
+	text_wqe->resp_bd_list_addr_lo = (u32) bnx2i_conn->gen_pdu.resp_bd_dma;
+	text_wqe->resp_bd_list_addr_hi =
+			(u32) ((u64) bnx2i_conn->gen_pdu.resp_bd_dma >> 32);
+
+	dword = ((1 << ISCSI_TEXT_REQUEST_NUM_RESP_BDS_SHIFT) |
+		 (bnx2i_conn->gen_pdu.resp_buf_size <<
+		  ISCSI_TEXT_REQUEST_RESP_BUFFER_LENGTH_SHIFT));
+	text_wqe->resp_buffer = dword;
+	text_wqe->bd_list_addr_lo = (u32) bnx2i_conn->gen_pdu.req_bd_dma;
+	text_wqe->bd_list_addr_hi =
+			(u32) ((u64) bnx2i_conn->gen_pdu.req_bd_dma >> 32);
+	text_wqe->num_bds = 1;
+	text_wqe->cq_index = 0; /* CQ# used for completion, 5771x only */
+
+	bnx2i_ring_dbell_update_sq_params(bnx2i_conn, 1);
+	return 0;
+}
+
+
+/**
  * bnx2i_send_iscsi_scsicmd - post iSCSI scsicmd request WQE to hardware
  * @conn:	iscsi connection
  * @cmd:	driver command structure which is requesting
@@ -490,15 +540,18 @@ int bnx2i_send_iscsi_nopout(struct bnx2i_conn *bnx2i_conn,
 	bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
 	nopout_hdr = (struct iscsi_nopout *)task->hdr;
 	nopout_wqe = (struct bnx2i_nop_out_request *)ep->qp.sq_prod_qe;
+
+	memset(nopout_wqe, 0x00, sizeof(struct bnx2i_nop_out_request));
+
 	nopout_wqe->op_code = nopout_hdr->opcode;
 	nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL;
 	memcpy(nopout_wqe->lun, nopout_hdr->lun, 8);
 
 	if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
-		u32 tmp = nopout_hdr->lun[0];
+		u32 tmp = nopout_wqe->lun[0];
 		/* 57710 requires LUN field to be swapped */
-		nopout_hdr->lun[0] = nopout_hdr->lun[1];
-		nopout_hdr->lun[1] = tmp;
+		nopout_wqe->lun[0] = nopout_wqe->lun[1];
+		nopout_wqe->lun[1] = tmp;
 	}
 
 	nopout_wqe->itt = ((u16)task->itt |
@@ -1425,6 +1478,68 @@ done:
 	return 0;
 }
 
+
+/**
+ * bnx2i_process_text_resp - this function handles iscsi text response
+ * @session:	iscsi session pointer
+ * @bnx2i_conn:	iscsi connection pointer
+ * @cqe:	pointer to newly DMA'ed CQE entry for processing
+ *
+ * process iSCSI Text Response CQE&  complete it to open-iscsi user daemon
+ */
+static int bnx2i_process_text_resp(struct iscsi_session *session,
+				   struct bnx2i_conn *bnx2i_conn,
+				   struct cqe *cqe)
+{
+	struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
+	struct iscsi_task *task;
+	struct bnx2i_text_response *text;
+	struct iscsi_text_rsp *resp_hdr;
+	int pld_len;
+	int pad_len;
+
+	text = (struct bnx2i_text_response *) cqe;
+	spin_lock(&session->lock);
+	task = iscsi_itt_to_task(conn, text->itt & ISCSI_LOGIN_RESPONSE_INDEX);
+	if (!task)
+		goto done;
+
+	resp_hdr = (struct iscsi_text_rsp *)&bnx2i_conn->gen_pdu.resp_hdr;
+	memset(resp_hdr, 0, sizeof(struct iscsi_hdr));
+	resp_hdr->opcode = text->op_code;
+	resp_hdr->flags = text->response_flags;
+	resp_hdr->hlength = 0;
+
+	hton24(resp_hdr->dlength, text->data_length);
+	resp_hdr->itt = task->hdr->itt;
+	resp_hdr->ttt = cpu_to_be32(text->ttt);
+	resp_hdr->statsn = task->hdr->exp_statsn;
+	resp_hdr->exp_cmdsn = cpu_to_be32(text->exp_cmd_sn);
+	resp_hdr->max_cmdsn = cpu_to_be32(text->max_cmd_sn);
+	pld_len = text->data_length;
+	bnx2i_conn->gen_pdu.resp_wr_ptr = bnx2i_conn->gen_pdu.resp_buf +
+					  pld_len;
+	pad_len = 0;
+	if (pld_len & 0x3)
+		pad_len = 4 - (pld_len % 4);
+
+	if (pad_len) {
+		int i = 0;
+		for (i = 0; i < pad_len; i++) {
+			bnx2i_conn->gen_pdu.resp_wr_ptr[0] = 0;
+			bnx2i_conn->gen_pdu.resp_wr_ptr++;
+		}
+	}
+	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr,
+			     bnx2i_conn->gen_pdu.resp_buf,
+			     bnx2i_conn->gen_pdu.resp_wr_ptr -
+			     bnx2i_conn->gen_pdu.resp_buf);
+done:
+	spin_unlock(&session->lock);
+	return 0;
+}
+
+
 /**
  * bnx2i_process_tmf_resp - this function handles iscsi TMF response
  * @session:		iscsi session pointer
@@ -1766,6 +1881,10 @@ static void bnx2i_process_new_cqes(struct bnx2i_conn *bnx2i_conn)
 			bnx2i_process_tmf_resp(session, bnx2i_conn,
 					       qp->cq_cons_qe);
 			break;
+		case ISCSI_OP_TEXT_RSP:
+			bnx2i_process_text_resp(session, bnx2i_conn,
+						qp->cq_cons_qe);
+			break;
 		case ISCSI_OP_LOGOUT_RSP:
 			bnx2i_process_logout_resp(session, bnx2i_conn,
 						  qp->cq_cons_qe);
diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
index 72a7b2d..1d24a28 100644
--- a/drivers/scsi/bnx2i/bnx2i_init.c
+++ b/drivers/scsi/bnx2i/bnx2i_init.c
@@ -18,8 +18,8 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list);
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.6.2.2"
-#define DRV_MODULE_RELDATE	"Nov 23, 2010"
+#define DRV_MODULE_VERSION	"2.6.2.3"
+#define DRV_MODULE_RELDATE	"Dec 31, 2010"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -29,7 +29,7 @@ static char version[] __devinitdata =
 MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
 	      "Eddie Wai <eddie.wai@broadcom.com>");
 
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711"
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
 		   " iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
@@ -88,9 +88,11 @@ void bnx2i_identify_device(struct bnx2i_hba *hba)
 	    (hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
 		set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
 		hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
-	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E)
+	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710  ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711  ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57712  ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57712E)
 		set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
 	else
 		printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
@@ -161,6 +163,21 @@ void bnx2i_start(void *handle)
 	struct bnx2i_hba *hba = handle;
 	int i = HZ;
 
+	if (!hba->cnic->max_iscsi_conn) {
+		printk(KERN_ALERT "bnx2i: dev %s does not support "
+			"iSCSI\n", hba->netdev->name);
+
+		if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
+			mutex_lock(&bnx2i_dev_lock);
+			list_del_init(&hba->link);
+			adapter_count--;
+			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
+			clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
+			mutex_unlock(&bnx2i_dev_lock);
+			bnx2i_free_hba(hba);
+		}
+		return;
+	}
 	bnx2i_send_fw_iscsi_init_msg(hba);
 	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
 		msleep(BNX2I_INIT_POLL_TIME);
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
index f0dce26..1809f9c 100644
--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
+++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
@@ -1092,6 +1092,9 @@ static int bnx2i_iscsi_send_generic_request(struct iscsi_task *task)
 	case ISCSI_OP_SCSI_TMFUNC:
 		rc = bnx2i_send_iscsi_tmf(bnx2i_conn, task);
 		break;
+	case ISCSI_OP_TEXT:
+		rc = bnx2i_send_iscsi_text(bnx2i_conn, task);
+		break;
 	default:
 		iscsi_conn_printk(KERN_ALERT, bnx2i_conn->cls_conn->dd_data,
 				  "send_gen: unsupported op 0x%x\n",
@@ -1455,42 +1458,40 @@ static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
 
 
 /**
- * bnx2i_conn_get_param - return iscsi connection parameter to caller
- * @cls_conn:	pointer to iscsi cls conn
+ * bnx2i_ep_get_param - return iscsi ep parameter to caller
+ * @ep:		pointer to iscsi endpoint
  * @param:	parameter type identifier
  * @buf: 	buffer pointer
  *
- * returns iSCSI connection parameters
+ * returns iSCSI ep parameters
  */
-static int bnx2i_conn_get_param(struct iscsi_cls_conn *cls_conn,
-				enum iscsi_param param, char *buf)
+static int bnx2i_ep_get_param(struct iscsi_endpoint *ep,
+			      enum iscsi_param param, char *buf)
 {
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct bnx2i_conn *bnx2i_conn = conn->dd_data;
-	int len = 0;
+	struct bnx2i_endpoint *bnx2i_ep = ep->dd_data;
+	struct bnx2i_hba *hba = bnx2i_ep->hba;
+	int len = -ENOTCONN;
 
-	if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba))
-		goto out;
+	if (!hba)
+		return -ENOTCONN;
 
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
-		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
-		if (bnx2i_conn->ep->cm_sk)
-			len = sprintf(buf, "%hu\n",
-				      bnx2i_conn->ep->cm_sk->dst_port);
-		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
+		mutex_lock(&hba->net_dev_lock);
+		if (bnx2i_ep->cm_sk)
+			len = sprintf(buf, "%hu\n", bnx2i_ep->cm_sk->dst_port);
+		mutex_unlock(&hba->net_dev_lock);
 		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
-		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
-		if (bnx2i_conn->ep->cm_sk)
-			len = sprintf(buf, "%pI4\n",
-				      &bnx2i_conn->ep->cm_sk->dst_ip);
-		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
+		mutex_lock(&hba->net_dev_lock);
+		if (bnx2i_ep->cm_sk)
+			len = sprintf(buf, "%pI4\n", &bnx2i_ep->cm_sk->dst_ip);
+		mutex_unlock(&hba->net_dev_lock);
 		break;
 	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
+		return -ENOSYS;
 	}
-out:
+
 	return len;
 }
 
@@ -1935,13 +1936,13 @@ static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep)
 		cnic_dev_10g = 1;
 
 	switch (bnx2i_ep->state) {
-	case EP_STATE_CONNECT_FAILED:
 	case EP_STATE_CLEANUP_FAILED:
 	case EP_STATE_OFLD_FAILED:
 	case EP_STATE_DISCONN_TIMEDOUT:
 		ret = 0;
 		break;
 	case EP_STATE_CONNECT_START:
+	case EP_STATE_CONNECT_FAILED:
 	case EP_STATE_CONNECT_COMPL:
 	case EP_STATE_ULP_UPDATE_START:
 	case EP_STATE_ULP_UPDATE_COMPL:
@@ -2167,7 +2168,8 @@ struct iscsi_transport bnx2i_iscsi_transport = {
 	.name			= "bnx2i",
 	.caps			= CAP_RECOVERY_L0 | CAP_HDRDGST |
 				  CAP_MULTI_R2T | CAP_DATADGST |
-				  CAP_DATA_PATH_OFFLOAD,
+				  CAP_DATA_PATH_OFFLOAD |
+				  CAP_TEXT_NEGO,
 	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
 				  ISCSI_MAX_XMIT_DLENGTH |
 				  ISCSI_HDRDGST_EN |
@@ -2200,7 +2202,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
 	.bind_conn		= bnx2i_conn_bind,
 	.destroy_conn		= bnx2i_conn_destroy,
 	.set_param		= iscsi_set_param,
-	.get_conn_param		= bnx2i_conn_get_param,
+	.get_conn_param		= iscsi_conn_get_param,
 	.get_session_param	= iscsi_session_get_param,
 	.get_host_param		= bnx2i_host_get_param,
 	.start_conn		= bnx2i_conn_start,
@@ -2209,6 +2211,7 @@ struct iscsi_transport bnx2i_iscsi_transport = {
 	.xmit_task		= bnx2i_task_xmit,
 	.get_stats		= bnx2i_conn_get_stats,
 	/* TCP connect - disconnect - option-2 interface calls */
+	.get_ep_param		= bnx2i_ep_get_param,
 	.ep_connect		= bnx2i_ep_connect,
 	.ep_poll		= bnx2i_ep_poll,
 	.ep_disconnect		= bnx2i_ep_disconnect,
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig
index 5cf4e98..11dff23 100644
--- a/drivers/scsi/cxgbi/cxgb3i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig
@@ -1,6 +1,8 @@
 config SCSI_CXGB3_ISCSI
 	tristate "Chelsio T3 iSCSI support"
-	depends on CHELSIO_T3_DEPENDS
+	depends on PCI && INET
+	select NETDEVICES
+	select NETDEV_10000
 	select CHELSIO_T3
 	select SCSI_ISCSI_ATTRS
 	---help---
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index a129a17..fc2cdb6 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -105,7 +105,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
 	/* owner and name should be set already */
 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
 				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
-				CAP_PADDING_OFFLOAD,
+				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
 	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
 				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
@@ -137,7 +137,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
 	.destroy_conn	= iscsi_tcp_conn_teardown,
 	.start_conn	= iscsi_conn_start,
 	.stop_conn	= iscsi_conn_stop,
-	.get_conn_param	= cxgbi_get_conn_param,
+	.get_conn_param	= iscsi_conn_get_param,
 	.set_param	= cxgbi_set_conn_param,
 	.get_stats	= cxgbi_get_conn_stats,
 	/* pdu xmit req from user space */
@@ -152,6 +152,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = {
 	.xmit_pdu	= cxgbi_conn_xmit_pdu,
 	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
 	/* TCP connect/disconnect */
+	.get_ep_param	= cxgbi_get_ep_param,
 	.ep_connect	= cxgbi_ep_connect,
 	.ep_poll	= cxgbi_ep_poll,
 	.ep_disconnect	= cxgbi_ep_disconnect,
@@ -1108,10 +1109,11 @@ static int ddp_set_map(struct cxgbi_sock *csk, struct cxgbi_pagepod_hdr *hdr,
 		csk, idx, npods, gl);
 
 	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
+		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
+						PPOD_SIZE, 0, GFP_ATOMIC);
 
-		/* hold on to the skb until we clear the ddp mapping */
-		skb_get(skb);
+		if (!skb)
+			return -ENOMEM;
 
 		ulp_mem_io_set_hdr(skb, pm_addr);
 		cxgbi_ddp_ppod_set((struct cxgbi_pagepod *)(skb->head +
@@ -1136,56 +1138,20 @@ static void ddp_clear_map(struct cxgbi_hba *chba, unsigned int tag,
 		cdev, idx, npods, tag);
 
 	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
+		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
+						PPOD_SIZE, 0, GFP_ATOMIC);
 
 		if (!skb) {
-			pr_err("tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
+			pr_err("tag 0x%x, 0x%x, %d/%u, skb OOM.\n",
 				tag, idx, i, npods);
 			continue;
 		}
-		ddp->gl_skb[idx] = NULL;
-		memset(skb->head + sizeof(struct ulp_mem_io), 0, PPOD_SIZE);
 		ulp_mem_io_set_hdr(skb, pm_addr);
 		skb->priority = CPL_PRIORITY_CONTROL;
 		cxgb3_ofld_send(cdev->lldev, skb);
 	}
 }
 
-static void ddp_free_gl_skb(struct cxgbi_ddp_info *ddp, int idx, int cnt)
-{
-	int i;
-
-	log_debug(1 << CXGBI_DBG_DDP,
-		"ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
-
-	for (i = 0; i < cnt; i++, idx++)
-		if (ddp->gl_skb[idx]) {
-			kfree_skb(ddp->gl_skb[idx]);
-			ddp->gl_skb[idx] = NULL;
-		}
-}
-
-static int ddp_alloc_gl_skb(struct cxgbi_ddp_info *ddp, int idx,
-				   int cnt, gfp_t gfp)
-{
-	int i;
-
-	log_debug(1 << CXGBI_DBG_DDP,
-		"ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
-
-	for (i = 0; i < cnt; i++) {
-		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
-						PPOD_SIZE, 0, gfp);
-		if (skb)
-			ddp->gl_skb[idx + i] = skb;
-		else {
-			ddp_free_gl_skb(ddp, idx, i);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
 				       unsigned int tid, int pg_idx, bool reply)
 {
@@ -1316,8 +1282,6 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev)
 	}
 	tdev->ulp_iscsi = ddp;
 
-	cdev->csk_ddp_free_gl_skb = ddp_free_gl_skb;
-	cdev->csk_ddp_alloc_gl_skb = ddp_alloc_gl_skb;
 	cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
 	cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
 	cdev->csk_ddp_set = ddp_set_map;
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
index 5f5e339..20593fd 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
@@ -24,10 +24,21 @@
 
 extern cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
 
-#define cxgb3i_get_private_ipv4addr(ndev) \
-	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
-#define cxgb3i_set_private_ipv4addr(ndev, addr) \
-	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
+static inline unsigned int cxgb3i_get_private_ipv4addr(struct net_device *ndev)
+{
+	return ((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr;
+}
+
+static inline void cxgb3i_set_private_ipv4addr(struct net_device *ndev,
+						unsigned int addr)
+{
+	struct port_info *pi =  (struct port_info *)netdev_priv(ndev);
+
+	pi->iscsic.flags = addr ? 1 : 0;
+	pi->iscsi_ipv4addr = addr;
+	if (addr)
+		memcpy(pi->iscsic.mac_addr, ndev->dev_addr, ETH_ALEN);
+}
 
 struct cpl_iscsi_hdr_norss {
 	union opcode_tid ot;
diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig
index bb94b39..d5302c2 100644
--- a/drivers/scsi/cxgbi/cxgb4i/Kconfig
+++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig
@@ -1,6 +1,8 @@
 config SCSI_CXGB4_ISCSI
 	tristate "Chelsio T4 iSCSI support"
-	depends on CHELSIO_T4_DEPENDS
+	depends on PCI && INET
+	select NETDEVICES
+	select NETDEV_10000
 	select CHELSIO_T4
 	select SCSI_ISCSI_ATTRS
 	---help---
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index 8c04fad..f3a4cd7 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -106,7 +106,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
 	.name		= DRV_MODULE_NAME,
 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
 				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
-				CAP_PADDING_OFFLOAD,
+				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
 	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
 				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
@@ -138,7 +138,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
 	.destroy_conn	= iscsi_tcp_conn_teardown,
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_conn_stop,
-	.get_conn_param	= cxgbi_get_conn_param,
+	.get_conn_param	= iscsi_conn_get_param,
 	.set_param	= cxgbi_set_conn_param,
 	.get_stats	= cxgbi_get_conn_stats,
 	/* pdu xmit req from user space */
@@ -153,6 +153,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = {
 	.xmit_pdu	= cxgbi_conn_xmit_pdu,
 	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
 	/* TCP connect/disconnect */
+	.get_ep_param	= cxgbi_get_ep_param,
 	.ep_connect	= cxgbi_ep_connect,
 	.ep_poll	= cxgbi_ep_poll,
 	.ep_disconnect	= cxgbi_ep_disconnect,
@@ -1425,8 +1426,6 @@ static int cxgb4i_ddp_init(struct cxgbi_device *cdev)
 	cxgbi_ddp_page_size_factor(pgsz_factor);
 	cxgb4_iscsi_init(lldi->ports[0], tagmask, pgsz_factor);
 
-	cdev->csk_ddp_free_gl_skb = NULL;
-	cdev->csk_ddp_alloc_gl_skb = NULL;
 	cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
 	cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
 	cdev->csk_ddp_set = ddp_set_map;
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index d2ad3d6..de764ea 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -451,26 +451,13 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
 }
 
 static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr,
-					__be16 sport, __be16 dport, u8 tos)
+				      __be16 sport, __be16 dport, u8 tos)
 {
 	struct rtable *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			.ip4_u = {
-				.daddr = daddr,
-				.saddr = saddr,
-				.tos = tos }
-			},
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			.ports = {
-				.sport = sport,
-				.dport = dport }
-			}
-	};
 
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+	rt = ip_route_output_ports(&init_net, NULL, daddr, saddr,
+				   dport, sport, IPPROTO_TCP, tos, 0);
+	if (IS_ERR(rt))
 		return NULL;
 
 	return rt;
@@ -543,6 +530,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
 	csk->dst = dst;
 	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
 	csk->daddr.sin_port = daddr->sin_port;
+	csk->daddr.sin_family = daddr->sin_family;
 	csk->saddr.sin_addr.s_addr = rt->rt_src;
 
 	return csk;
@@ -1277,12 +1265,6 @@ static int ddp_tag_reserve(struct cxgbi_sock *csk, unsigned int tid,
 		return idx;
 	}
 
-	if (cdev->csk_ddp_alloc_gl_skb) {
-		err = cdev->csk_ddp_alloc_gl_skb(ddp, idx, npods, gfp);
-		if (err < 0)
-			goto unmark_entries;
-	}
-
 	tag = cxgbi_ddp_tag_base(tformat, sw_tag);
 	tag |= idx << PPOD_IDX_SHIFT;
 
@@ -1293,11 +1275,8 @@ static int ddp_tag_reserve(struct cxgbi_sock *csk, unsigned int tid,
 	hdr.page_offset = htonl(gl->offset);
 
 	err = cdev->csk_ddp_set(csk, &hdr, idx, npods, gl);
-	if (err < 0) {
-		if (cdev->csk_ddp_free_gl_skb)
-			cdev->csk_ddp_free_gl_skb(ddp, idx, npods);
+	if (err < 0)
 		goto unmark_entries;
-	}
 
 	ddp->idx_last = idx;
 	log_debug(1 << CXGBI_DBG_DDP,
@@ -1363,8 +1342,6 @@ static void ddp_destroy(struct kref *kref)
 					>> PPOD_PAGES_SHIFT;
 			pr_info("cdev 0x%p, ddp %d + %d.\n", cdev, i, npods);
 			kfree(gl);
-			if (cdev->csk_ddp_free_gl_skb)
-				cdev->csk_ddp_free_gl_skb(ddp, i, npods);
 			i += npods;
 		} else
 			i++;
@@ -1407,8 +1384,6 @@ int cxgbi_ddp_init(struct cxgbi_device *cdev,
 		return -ENOMEM;
 	}
 	ddp->gl_map = (struct cxgbi_gather_list **)(ddp + 1);
-	ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
-				ppmax * sizeof(struct cxgbi_gather_list *));
 	cdev->ddp = ddp;
 
 	spin_lock_init(&ddp->map_lock);
@@ -1908,13 +1883,16 @@ EXPORT_SYMBOL_GPL(cxgbi_conn_alloc_pdu);
 
 static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
 {
-	u8 submode = 0;
+	if (hcrc || dcrc) {
+		u8 submode = 0;
 
-	if (hcrc)
-		submode |= 1;
-	if (dcrc)
-		submode |= 2;
-	cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+		if (hcrc)
+			submode |= 1;
+		if (dcrc)
+			submode |= 2;
+		cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+	} else
+		cxgbi_skcb_ulp_mode(skb) = 0;
 }
 
 int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
@@ -2210,32 +2188,34 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
 }
 EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
 
-int cxgbi_get_conn_param(struct iscsi_cls_conn *cls_conn,
-			enum iscsi_param param, char *buf)
+int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
+		       char *buf)
 {
-	struct iscsi_conn *iconn = cls_conn->dd_data;
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_sock *csk;
 	int len;
 
 	log_debug(1 << CXGBI_DBG_ISCSI,
-		"cls_conn 0x%p, param %d.\n", cls_conn, param);
+		"cls_conn 0x%p, param %d.\n", ep, param);
 
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
-		spin_lock_bh(&iconn->session->lock);
-		len = sprintf(buf, "%hu\n", iconn->portal_port);
-		spin_unlock_bh(&iconn->session->lock);
-		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
-		spin_lock_bh(&iconn->session->lock);
-		len = sprintf(buf, "%s\n", iconn->portal_address);
-		spin_unlock_bh(&iconn->session->lock);
-		break;
+		if (!cep)
+			return -ENOTCONN;
+
+		csk = cep->csk;
+		if (!csk)
+			return -ENOTCONN;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+						 &csk->daddr, param, buf);
 	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
+		return -ENOSYS;
 	}
 	return len;
 }
-EXPORT_SYMBOL_GPL(cxgbi_get_conn_param);
+EXPORT_SYMBOL_GPL(cxgbi_get_ep_param);
 
 struct iscsi_cls_conn *
 cxgbi_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
@@ -2302,11 +2282,6 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
 	cxgbi_conn_max_xmit_dlength(conn);
 	cxgbi_conn_max_recv_dlength(conn);
 
-	spin_lock_bh(&conn->session->lock);
-	sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
-	conn->portal_port = ntohs(csk->daddr.sin_port);
-	spin_unlock_bh(&conn->session->lock);
-
 	log_debug(1 << CXGBI_DBG_ISCSI,
 		"cls 0x%p,0x%p, ep 0x%p, cconn 0x%p, csk 0x%p.\n",
 		cls_session, cls_conn, ep, cconn, csk);
diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h
index c57d59d..0a20fd5 100644
--- a/drivers/scsi/cxgbi/libcxgbi.h
+++ b/drivers/scsi/cxgbi/libcxgbi.h
@@ -131,7 +131,6 @@ struct cxgbi_ddp_info {
 	unsigned int rsvd_tag_mask;
 	spinlock_t map_lock;
 	struct cxgbi_gather_list **gl_map;
-	struct sk_buff **gl_skb;
 };
 
 #define DDP_PGIDX_MAX		4
@@ -536,8 +535,6 @@ struct cxgbi_device {
 	struct cxgbi_ddp_info *ddp;
 
 	void (*dev_ddp_cleanup)(struct cxgbi_device *);
-	void (*csk_ddp_free_gl_skb)(struct cxgbi_ddp_info *, int, int);
-	int (*csk_ddp_alloc_gl_skb)(struct cxgbi_ddp_info *, int, int, gfp_t);
 	int (*csk_ddp_set)(struct cxgbi_sock *, struct cxgbi_pagepod_hdr *,
 				unsigned int, unsigned int,
 				struct cxgbi_gather_list *);
@@ -715,7 +712,7 @@ void cxgbi_cleanup_task(struct iscsi_task *task);
 void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
 int cxgbi_set_conn_param(struct iscsi_cls_conn *,
 			enum iscsi_param, char *, int);
-int cxgbi_get_conn_param(struct iscsi_cls_conn *, enum iscsi_param, char *);
+int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param, char *);
 struct iscsi_cls_conn *cxgbi_create_conn(struct iscsi_cls_session *, u32);
 int cxgbi_bind_conn(struct iscsi_cls_session *,
 			struct iscsi_cls_conn *, u64, int);
diff --git a/drivers/scsi/device_handler/scsi_dh.c b/drivers/scsi/device_handler/scsi_dh.c
index b837c5b..564e6ec 100644
--- a/drivers/scsi/device_handler/scsi_dh.c
+++ b/drivers/scsi/device_handler/scsi_dh.c
@@ -25,16 +25,9 @@
 #include <scsi/scsi_dh.h>
 #include "../scsi_priv.h"
 
-struct scsi_dh_devinfo_list {
-	struct list_head node;
-	char vendor[9];
-	char model[17];
-	struct scsi_device_handler *handler;
-};
-
 static DEFINE_SPINLOCK(list_lock);
 static LIST_HEAD(scsi_dh_list);
-static LIST_HEAD(scsi_dh_dev_list);
+static int scsi_dh_list_idx = 1;
 
 static struct scsi_device_handler *get_device_handler(const char *name)
 {
@@ -51,40 +44,18 @@ static struct scsi_device_handler *get_device_handler(const char *name)
 	return found;
 }
 
-
-static struct scsi_device_handler *
-scsi_dh_cache_lookup(struct scsi_device *sdev)
+static struct scsi_device_handler *get_device_handler_by_idx(int idx)
 {
-	struct scsi_dh_devinfo_list *tmp;
-	struct scsi_device_handler *found_dh = NULL;
+	struct scsi_device_handler *tmp, *found = NULL;
 
 	spin_lock(&list_lock);
-	list_for_each_entry(tmp, &scsi_dh_dev_list, node) {
-		if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) &&
-		    !strncmp(sdev->model, tmp->model, strlen(tmp->model))) {
-			found_dh = tmp->handler;
+	list_for_each_entry(tmp, &scsi_dh_list, list) {
+		if (tmp->idx == idx) {
+			found = tmp;
 			break;
 		}
 	}
 	spin_unlock(&list_lock);
-
-	return found_dh;
-}
-
-static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
-				  struct scsi_device *sdev)
-{
-	int i, found = 0;
-
-	for(i = 0; scsi_dh->devlist[i].vendor; i++) {
-		if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
-			     strlen(scsi_dh->devlist[i].vendor)) &&
-		    !strncmp(sdev->model, scsi_dh->devlist[i].model,
-			     strlen(scsi_dh->devlist[i].model))) {
-			found = 1;
-			break;
-		}
-	}
 	return found;
 }
 
@@ -102,41 +73,14 @@ device_handler_match(struct scsi_device_handler *scsi_dh,
 		     struct scsi_device *sdev)
 {
 	struct scsi_device_handler *found_dh = NULL;
-	struct scsi_dh_devinfo_list *tmp;
+	int idx;
 
-	found_dh = scsi_dh_cache_lookup(sdev);
-	if (found_dh)
-		return found_dh;
+	idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
+					  SCSI_DEVINFO_DH);
+	found_dh = get_device_handler_by_idx(idx);
 
-	if (scsi_dh) {
-		if (scsi_dh_handler_lookup(scsi_dh, sdev))
-			found_dh = scsi_dh;
-	} else {
-		struct scsi_device_handler *tmp_dh;
-
-		spin_lock(&list_lock);
-		list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
-			if (scsi_dh_handler_lookup(tmp_dh, sdev))
-				found_dh = tmp_dh;
-		}
-		spin_unlock(&list_lock);
-	}
-
-	if (found_dh) { /* If device is found, add it to the cache */
-		tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-		if (tmp) {
-			strncpy(tmp->vendor, sdev->vendor, 8);
-			strncpy(tmp->model, sdev->model, 16);
-			tmp->vendor[8] = '\0';
-			tmp->model[16] = '\0';
-			tmp->handler = found_dh;
-			spin_lock(&list_lock);
-			list_add(&tmp->node, &scsi_dh_dev_list);
-			spin_unlock(&list_lock);
-		} else {
-			found_dh = NULL;
-		}
-	}
+	if (scsi_dh && found_dh != scsi_dh)
+		found_dh = NULL;
 
 	return found_dh;
 }
@@ -373,12 +317,25 @@ static int scsi_dh_notifier_remove(struct device *dev, void *data)
  */
 int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
 {
+	int i;
+
 	if (get_device_handler(scsi_dh->name))
 		return -EBUSY;
 
 	spin_lock(&list_lock);
+	scsi_dh->idx = scsi_dh_list_idx++;
 	list_add(&scsi_dh->list, &scsi_dh_list);
 	spin_unlock(&list_lock);
+
+	for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+		scsi_dev_info_list_add_keyed(0,
+					scsi_dh->devlist[i].vendor,
+					scsi_dh->devlist[i].model,
+					NULL,
+					scsi_dh->idx,
+					SCSI_DEVINFO_DH);
+	}
+
 	bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
 	printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
 
@@ -395,7 +352,7 @@ EXPORT_SYMBOL_GPL(scsi_register_device_handler);
  */
 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
 {
-	struct scsi_dh_devinfo_list *tmp, *pos;
+	int i;
 
 	if (!get_device_handler(scsi_dh->name))
 		return -ENODEV;
@@ -403,14 +360,14 @@ int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
 	bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
 			 scsi_dh_notifier_remove);
 
+	for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+		scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
+					     scsi_dh->devlist[i].model,
+					     SCSI_DEVINFO_DH);
+	}
+
 	spin_lock(&list_lock);
 	list_del(&scsi_dh->list);
-	list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
-		if (pos->handler == scsi_dh) {
-			list_del(&pos->node);
-			kfree(pos);
-		}
-	}
 	spin_unlock(&list_lock);
 	printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
 
@@ -576,6 +533,10 @@ static int __init scsi_dh_init(void)
 {
 	int r;
 
+	r = scsi_dev_info_add_list(SCSI_DEVINFO_DH, "SCSI Device Handler");
+	if (r)
+		return r;
+
 	r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
 
 	if (!r)
@@ -590,6 +551,7 @@ static void __exit scsi_dh_exit(void)
 	bus_for_each_dev(&scsi_bus_type, NULL, NULL,
 			 scsi_dh_sysfs_attr_remove);
 	bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
+	scsi_dev_info_remove_list(SCSI_DEVINFO_DH);
 }
 
 module_init(scsi_dh_init);
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index 6b72932..7cae0bc 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -253,13 +253,15 @@ static void stpg_endio(struct request *req, int error)
 {
 	struct alua_dh_data *h = req->end_io_data;
 	struct scsi_sense_hdr sense_hdr;
-	unsigned err = SCSI_DH_IO;
+	unsigned err = SCSI_DH_OK;
 
 	if (error || host_byte(req->errors) != DID_OK ||
-			msg_byte(req->errors) != COMMAND_COMPLETE)
+			msg_byte(req->errors) != COMMAND_COMPLETE) {
+		err = SCSI_DH_IO;
 		goto done;
+	}
 
-	if (err == SCSI_DH_IO && h->senselen > 0) {
+	if (h->senselen > 0) {
 		err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
 					   &sense_hdr);
 		if (!err) {
@@ -285,7 +287,8 @@ static void stpg_endio(struct request *req, int error)
 			    print_alua_state(h->state));
 	}
 done:
-	blk_put_request(req);
+	req->end_io_data = NULL;
+	__blk_put_request(req->q, req);
 	if (h->callback_fn) {
 		h->callback_fn(h->callback_data, err);
 		h->callback_fn = h->callback_data = NULL;
@@ -303,7 +306,6 @@ done:
 static unsigned submit_stpg(struct alua_dh_data *h)
 {
 	struct request *rq;
-	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 	int stpg_len = 8;
 	struct scsi_device *sdev = h->sdev;
 
@@ -332,7 +334,7 @@ static unsigned submit_stpg(struct alua_dh_data *h)
 	rq->end_io_data = h;
 
 	blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
-	return err;
+	return SCSI_DH_OK;
 }
 
 /*
@@ -730,7 +732,9 @@ static const struct scsi_dh_devlist alua_dev_list[] = {
 	{"Pillar", "Axiom" },
 	{"Intel", "Multi-Flex"},
 	{"NETAPP", "LUN"},
+	{"NETAPP", "LUN C-Mode"},
 	{"AIX", "NVDISK"},
+	{"Promise", "VTrak"},
 	{NULL, NULL}
 };
 
@@ -759,7 +763,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
 	unsigned long flags;
 	int err = SCSI_DH_OK;
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
diff --git a/drivers/scsi/device_handler/scsi_dh_emc.c b/drivers/scsi/device_handler/scsi_dh_emc.c
index 6faf472..48441f6 100644
--- a/drivers/scsi/device_handler/scsi_dh_emc.c
+++ b/drivers/scsi/device_handler/scsi_dh_emc.c
@@ -650,7 +650,7 @@ static int clariion_bus_attach(struct scsi_device *sdev)
 	unsigned long flags;
 	int err;
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
index e391664..b479f1e 100644
--- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c
+++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c
@@ -225,7 +225,8 @@ static void start_stop_endio(struct request *req, int error)
 		}
 	}
 done:
-	blk_put_request(req);
+	req->end_io_data = NULL;
+	__blk_put_request(req->q, req);
 	if (h->callback_fn) {
 		h->callback_fn(h->callback_data, err);
 		h->callback_fn = h->callback_data = NULL;
@@ -338,8 +339,8 @@ static int hp_sw_bus_attach(struct scsi_device *sdev)
 	unsigned long flags;
 	int ret;
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
-			       + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
+			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n",
 			    HP_SW_NAME);
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 5be3ae1..293c183 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -281,11 +281,13 @@ static struct request *get_rdac_req(struct scsi_device *sdev,
 }
 
 static struct request *rdac_failover_get(struct scsi_device *sdev,
-					 struct rdac_dh_data *h)
+			struct rdac_dh_data *h, struct list_head *list)
 {
 	struct request *rq;
 	struct rdac_mode_common *common;
 	unsigned data_size;
+	struct rdac_queue_data *qdata;
+	u8 *lun_table;
 
 	if (h->ctlr->use_ms10) {
 		struct rdac_pg_expanded *rdac_pg;
@@ -298,6 +300,7 @@ static struct request *rdac_failover_get(struct scsi_device *sdev,
 		rdac_pg->subpage_code = 0x1;
 		rdac_pg->page_len[0] = 0x01;
 		rdac_pg->page_len[1] = 0x28;
+		lun_table = rdac_pg->lun_table;
 	} else {
 		struct rdac_pg_legacy *rdac_pg;
 
@@ -307,11 +310,16 @@ static struct request *rdac_failover_get(struct scsi_device *sdev,
 		common = &rdac_pg->common;
 		rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
 		rdac_pg->page_len = 0x68;
+		lun_table = rdac_pg->lun_table;
 	}
 	common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
 	common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
 	common->rdac_options = RDAC_FORCED_QUIESENCE;
 
+	list_for_each_entry(qdata, list, entry) {
+		lun_table[qdata->h->lun] = 0x81;
+	}
+
 	/* get request for block layer packet command */
 	rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE);
 	if (!rq)
@@ -565,7 +573,6 @@ static void send_mode_select(struct work_struct *work)
 	int err, retry_cnt = RDAC_RETRY_COUNT;
 	struct rdac_queue_data *tmp, *qdata;
 	LIST_HEAD(list);
-	u8 *lun_table;
 
 	spin_lock(&ctlr->ms_lock);
 	list_splice_init(&ctlr->ms_head, &list);
@@ -573,21 +580,12 @@ static void send_mode_select(struct work_struct *work)
 	ctlr->ms_sdev = NULL;
 	spin_unlock(&ctlr->ms_lock);
 
-	if (ctlr->use_ms10)
-		lun_table = ctlr->mode_select.expanded.lun_table;
-	else
-		lun_table = ctlr->mode_select.legacy.lun_table;
-
 retry:
 	err = SCSI_DH_RES_TEMP_UNAVAIL;
-	rq = rdac_failover_get(sdev, h);
+	rq = rdac_failover_get(sdev, h, &list);
 	if (!rq)
 		goto done;
 
-	list_for_each_entry(qdata, &list, entry) {
-		lun_table[qdata->h->lun] = 0x81;
-	}
-
 	RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
 		"%s MODE_SELECT command",
 		(char *) h->ctlr->array_name, h->ctlr->index,
@@ -769,6 +767,7 @@ static const struct scsi_dh_devlist rdac_dev_list[] = {
 	{"DELL", "MD32xx"},
 	{"DELL", "MD32xxi"},
 	{"DELL", "MD36xxi"},
+	{"DELL", "MD36xxf"},
 	{"LSI", "INF-01-00"},
 	{"ENGENIO", "INF-01-00"},
 	{"STK", "FLEXLINE 380"},
@@ -800,7 +799,7 @@ static int rdac_bus_attach(struct scsi_device *sdev)
 	int err;
 	char array_name[ARRAY_LABEL_LEN];
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
@@ -906,4 +905,5 @@ module_exit(rdac_exit);
 
 MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver");
 MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
+MODULE_VERSION("01.00.0000.0000");
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile
index 950f276..f6d37d0 100644
--- a/drivers/scsi/fcoe/Makefile
+++ b/drivers/scsi/fcoe/Makefile
@@ -1,2 +1,4 @@
 obj-$(CONFIG_FCOE) += fcoe.o
 obj-$(CONFIG_LIBFCOE) += libfcoe.o
+
+libfcoe-objs := fcoe_ctlr.o fcoe_transport.o
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 9f9600b..bde6ee5 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -31,6 +31,7 @@
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/ctype.h>
+#include <linux/workqueue.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_transport.h>
@@ -58,6 +59,8 @@ MODULE_PARM_DESC(ddp_min, "Minimum I/O size in bytes for "	\
 
 DEFINE_MUTEX(fcoe_config_mutex);
 
+static struct workqueue_struct *fcoe_wq;
+
 /* fcoe_percpu_clean completion.  Waiter protected by fcoe_create_mutex */
 static DECLARE_COMPLETION(fcoe_flush_completion);
 
@@ -72,7 +75,6 @@ static int fcoe_xmit(struct fc_lport *, struct fc_frame *);
 static int fcoe_rcv(struct sk_buff *, struct net_device *,
 		    struct packet_type *, struct net_device *);
 static int fcoe_percpu_receive_thread(void *);
-static void fcoe_clean_pending_queue(struct fc_lport *);
 static void fcoe_percpu_clean(struct fc_lport *);
 static int fcoe_link_speed_update(struct fc_lport *);
 static int fcoe_link_ok(struct fc_lport *);
@@ -80,7 +82,6 @@ static int fcoe_link_ok(struct fc_lport *);
 static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
 static int fcoe_hostlist_add(const struct fc_lport *);
 
-static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
 static int fcoe_device_notification(struct notifier_block *, ulong, void *);
 static void fcoe_dev_setup(void);
 static void fcoe_dev_cleanup(void);
@@ -101,10 +102,11 @@ static int fcoe_ddp_done(struct fc_lport *, u16);
 
 static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
 
-static int fcoe_create(const char *, struct kernel_param *);
-static int fcoe_destroy(const char *, struct kernel_param *);
-static int fcoe_enable(const char *, struct kernel_param *);
-static int fcoe_disable(const char *, struct kernel_param *);
+static bool fcoe_match(struct net_device *netdev);
+static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode);
+static int fcoe_destroy(struct net_device *netdev);
+static int fcoe_enable(struct net_device *netdev);
+static int fcoe_disable(struct net_device *netdev);
 
 static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
 				      u32 did, struct fc_frame *,
@@ -117,24 +119,6 @@ static void fcoe_recv_frame(struct sk_buff *skb);
 
 static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
 
-module_param_call(create, fcoe_create, NULL, (void *)FIP_MODE_FABRIC, S_IWUSR);
-__MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
-module_param_call(create_vn2vn, fcoe_create, NULL,
-		  (void *)FIP_MODE_VN2VN, S_IWUSR);
-__MODULE_PARM_TYPE(create_vn2vn, "string");
-MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
-		 "on an Ethernet interface");
-module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
-module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(enable, "string");
-MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
-module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(disable, "string");
-MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
-
 /* notification function for packets from net device */
 static struct notifier_block fcoe_notifier = {
 	.notifier_call = fcoe_device_notification,
@@ -145,8 +129,8 @@ static struct notifier_block fcoe_cpu_notifier = {
 	.notifier_call = fcoe_cpu_callback,
 };
 
-static struct scsi_transport_template *fcoe_transport_template;
-static struct scsi_transport_template *fcoe_vport_transport_template;
+static struct scsi_transport_template *fcoe_nport_scsi_transport;
+static struct scsi_transport_template *fcoe_vport_scsi_transport;
 
 static int fcoe_vport_destroy(struct fc_vport *);
 static int fcoe_vport_create(struct fc_vport *, bool disabled);
@@ -163,7 +147,7 @@ static struct libfc_function_template fcoe_libfc_fcn_templ = {
 	.lport_set_port_id = fcoe_set_port_id,
 };
 
-struct fc_function_template fcoe_transport_function = {
+struct fc_function_template fcoe_nport_fc_functions = {
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
 	.show_host_supported_classes = 1,
@@ -203,7 +187,7 @@ struct fc_function_template fcoe_transport_function = {
 	.bsg_request = fc_lport_bsg_request,
 };
 
-struct fc_function_template fcoe_vport_transport_function = {
+struct fc_function_template fcoe_vport_fc_functions = {
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
 	.show_host_supported_classes = 1,
@@ -285,9 +269,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
 	}
 
 	/* Do not support for bonding device */
-	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
-	    (netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
-	    (netdev->priv_flags & IFF_MASTER_8023AD)) {
+	if (netdev->priv_flags & IFF_BONDING && netdev->flags & IFF_MASTER) {
 		FCOE_NETDEV_DBG(netdev, "Bonded interfaces not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -356,10 +338,18 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
 	struct fcoe_interface *fcoe;
 	int err;
 
+	if (!try_module_get(THIS_MODULE)) {
+		FCOE_NETDEV_DBG(netdev,
+				"Could not get a reference to the module\n");
+		fcoe = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
 	fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL);
 	if (!fcoe) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
-		return NULL;
+		fcoe = ERR_PTR(-ENOMEM);
+		goto out_nomod;
 	}
 
 	dev_hold(netdev);
@@ -378,9 +368,15 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
 		fcoe_ctlr_destroy(&fcoe->ctlr);
 		kfree(fcoe);
 		dev_put(netdev);
-		return NULL;
+		fcoe = ERR_PTR(err);
+		goto out_nomod;
 	}
 
+	goto out;
+
+out_nomod:
+	module_put(THIS_MODULE);
+out:
 	return fcoe;
 }
 
@@ -442,6 +438,7 @@ static void fcoe_interface_release(struct kref *kref)
 	fcoe_ctlr_destroy(&fcoe->ctlr);
 	kfree(fcoe);
 	dev_put(netdev);
+	module_put(THIS_MODULE);
 }
 
 /**
@@ -505,7 +502,7 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
 static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 
 	rtnl_lock();
 	if (!is_zero_ether_addr(port->data_src_addr))
@@ -561,17 +558,6 @@ static int fcoe_lport_config(struct fc_lport *lport)
 }
 
 /**
- * fcoe_queue_timer() - The fcoe queue timer
- * @lport: The local port
- *
- * Calls fcoe_check_wait_queue on timeout
- */
-static void fcoe_queue_timer(ulong lport)
-{
-	fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
-}
-
-/**
  * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
  * @netdev: the associated net device
  * @wwn: the output WWN
@@ -650,7 +636,7 @@ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev)
 
 	/* Setup lport private data to point to fcoe softc */
 	port = lport_priv(lport);
-	fcoe = port->fcoe;
+	fcoe = port->priv;
 
 	/*
 	 * Determine max frame size based on underlying device and optional
@@ -708,9 +694,9 @@ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev)
 	lport->host->max_cmd_len = FCOE_MAX_CMD_LEN;
 
 	if (lport->vport)
-		lport->host->transportt = fcoe_vport_transport_template;
+		lport->host->transportt = fcoe_vport_scsi_transport;
 	else
-		lport->host->transportt = fcoe_transport_template;
+		lport->host->transportt = fcoe_nport_scsi_transport;
 
 	/* add the new host to the SCSI-ml */
 	rc = scsi_add_host(lport->host, dev);
@@ -760,7 +746,7 @@ bool fcoe_oem_match(struct fc_frame *fp)
 static inline int fcoe_em_config(struct fc_lport *lport)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct fcoe_interface *oldfcoe = NULL;
 	struct net_device *old_real_dev, *cur_real_dev;
 	u16 min_xid = FCOE_MIN_XID;
@@ -844,7 +830,7 @@ skip_oem:
 static void fcoe_if_destroy(struct fc_lport *lport)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct net_device *netdev = fcoe->netdev;
 
 	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
@@ -886,7 +872,6 @@ static void fcoe_if_destroy(struct fc_lport *lport)
 
 	/* Release the Scsi_Host */
 	scsi_host_put(lport->host);
-	module_put(THIS_MODULE);
 }
 
 /**
@@ -941,8 +926,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 				       struct device *parent, int npiv)
 {
 	struct net_device *netdev = fcoe->netdev;
-	struct fc_lport *lport = NULL;
+	struct fc_lport *lport, *n_port;
 	struct fcoe_port *port;
+	struct Scsi_Host *shost;
 	int rc;
 	/*
 	 * parent is only a vport if npiv is 1,
@@ -952,13 +938,11 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 
 	FCOE_NETDEV_DBG(netdev, "Create Interface\n");
 
-	if (!npiv) {
-		lport = libfc_host_alloc(&fcoe_shost_template,
-					 sizeof(struct fcoe_port));
-	} else	{
-		lport = libfc_vport_create(vport,
-					   sizeof(struct fcoe_port));
-	}
+	if (!npiv)
+		lport = libfc_host_alloc(&fcoe_shost_template, sizeof(*port));
+	else
+		lport = libfc_vport_create(vport, sizeof(*port));
+
 	if (!lport) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
 		rc = -ENOMEM;
@@ -966,7 +950,9 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 	}
 	port = lport_priv(lport);
 	port->lport = lport;
-	port->fcoe = fcoe;
+	port->priv = fcoe;
+	port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH;
+	port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH;
 	INIT_WORK(&port->destroy_work, fcoe_destroy_work);
 
 	/* configure a fc_lport including the exchange manager */
@@ -1009,24 +995,27 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
 		goto out_lp_destroy;
 	}
 
-	if (!npiv) {
-		/*
-		 * fcoe_em_alloc() and fcoe_hostlist_add() both
-		 * need to be atomic with respect to other changes to the
-		 * hostlist since fcoe_em_alloc() looks for an existing EM
-		 * instance on host list updated by fcoe_hostlist_add().
-		 *
-		 * This is currently handled through the fcoe_config_mutex
-		 * begin held.
-		 */
-
+	/*
+	 * fcoe_em_alloc() and fcoe_hostlist_add() both
+	 * need to be atomic with respect to other changes to the
+	 * hostlist since fcoe_em_alloc() looks for an existing EM
+	 * instance on host list updated by fcoe_hostlist_add().
+	 *
+	 * This is currently handled through the fcoe_config_mutex
+	 * begin held.
+	 */
+	if (!npiv)
 		/* lport exch manager allocation */
 		rc = fcoe_em_config(lport);
-		if (rc) {
-			FCOE_NETDEV_DBG(netdev, "Could not configure the EM "
-					"for the interface\n");
-			goto out_lp_destroy;
-		}
+	else {
+		shost = vport_to_shost(vport);
+		n_port = shost_priv(shost);
+		rc = fc_exch_mgr_list_clone(n_port, lport);
+	}
+
+	if (rc) {
+		FCOE_NETDEV_DBG(netdev, "Could not configure the EM\n");
+		goto out_lp_destroy;
 	}
 
 	fcoe_interface_get(fcoe);
@@ -1050,11 +1039,12 @@ out:
 static int __init fcoe_if_init(void)
 {
 	/* attach to scsi transport */
-	fcoe_transport_template = fc_attach_transport(&fcoe_transport_function);
-	fcoe_vport_transport_template =
-		fc_attach_transport(&fcoe_vport_transport_function);
+	fcoe_nport_scsi_transport =
+		fc_attach_transport(&fcoe_nport_fc_functions);
+	fcoe_vport_scsi_transport =
+		fc_attach_transport(&fcoe_vport_fc_functions);
 
-	if (!fcoe_transport_template) {
+	if (!fcoe_nport_scsi_transport) {
 		printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n");
 		return -ENODEV;
 	}
@@ -1071,10 +1061,10 @@ static int __init fcoe_if_init(void)
  */
 int __exit fcoe_if_exit(void)
 {
-	fc_release_transport(fcoe_transport_template);
-	fc_release_transport(fcoe_vport_transport_template);
-	fcoe_transport_template = NULL;
-	fcoe_vport_transport_template = NULL;
+	fc_release_transport(fcoe_nport_scsi_transport);
+	fc_release_transport(fcoe_vport_scsi_transport);
+	fcoe_nport_scsi_transport = NULL;
+	fcoe_vport_scsi_transport = NULL;
 	return 0;
 }
 
@@ -1361,108 +1351,22 @@ err2:
 }
 
 /**
- * fcoe_start_io() - Start FCoE I/O
- * @skb: The packet to be transmitted
- *
- * This routine is called from the net device to start transmitting
- * FCoE packets.
- *
- * Returns: 0 for success
- */
-static inline int fcoe_start_io(struct sk_buff *skb)
-{
-	struct sk_buff *nskb;
-	int rc;
-
-	nskb = skb_clone(skb, GFP_ATOMIC);
-	rc = dev_queue_xmit(nskb);
-	if (rc != 0)
-		return rc;
-	kfree_skb(skb);
-	return 0;
-}
-
-/**
- * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
+ * fcoe_alloc_paged_crc_eof() - Allocate a page to be used for the trailer CRC
  * @skb:  The packet to be transmitted
  * @tlen: The total length of the trailer
  *
- * This routine allocates a page for frame trailers. The page is re-used if
- * there is enough room left on it for the current trailer. If there isn't
- * enough buffer left a new page is allocated for the trailer. Reference to
- * the page from this function as well as the skbs using the page fragments
- * ensure that the page is freed at the appropriate time.
- *
  * Returns: 0 for success
  */
-static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
+static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
 {
 	struct fcoe_percpu_s *fps;
-	struct page *page;
+	int rc;
 
 	fps = &get_cpu_var(fcoe_percpu);
-	page = fps->crc_eof_page;
-	if (!page) {
-		page = alloc_page(GFP_ATOMIC);
-		if (!page) {
-			put_cpu_var(fcoe_percpu);
-			return -ENOMEM;
-		}
-		fps->crc_eof_page = page;
-		fps->crc_eof_offset = 0;
-	}
-
-	get_page(page);
-	skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
-			   fps->crc_eof_offset, tlen);
-	skb->len += tlen;
-	skb->data_len += tlen;
-	skb->truesize += tlen;
-	fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
-
-	if (fps->crc_eof_offset >= PAGE_SIZE) {
-		fps->crc_eof_page = NULL;
-		fps->crc_eof_offset = 0;
-		put_page(page);
-	}
+	rc = fcoe_get_paged_crc_eof(skb, tlen, fps);
 	put_cpu_var(fcoe_percpu);
-	return 0;
-}
 
-/**
- * fcoe_fc_crc() - Calculates the CRC for a given frame
- * @fp: The frame to be checksumed
- *
- * This uses crc32() routine to calculate the CRC for a frame
- *
- * Return: The 32 bit CRC value
- */
-u32 fcoe_fc_crc(struct fc_frame *fp)
-{
-	struct sk_buff *skb = fp_skb(fp);
-	struct skb_frag_struct *frag;
-	unsigned char *data;
-	unsigned long off, len, clen;
-	u32 crc;
-	unsigned i;
-
-	crc = crc32(~0, skb->data, skb_headlen(skb));
-
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		frag = &skb_shinfo(skb)->frags[i];
-		off = frag->page_offset;
-		len = frag->size;
-		while (len > 0) {
-			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
-			data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
-					   KM_SKB_DATA_SOFTIRQ);
-			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
-			kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
-			off += clen;
-			len -= clen;
-		}
-	}
-	return crc;
+	return rc;
 }
 
 /**
@@ -1485,7 +1389,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 	unsigned int tlen;		/* trailer length */
 	unsigned int elen;		/* eth header, may include vlan */
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	u8 sof, eof;
 	struct fcoe_hdr *hp;
 
@@ -1526,7 +1430,7 @@ int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp)
 	/* copy port crc and eof to the skb buff */
 	if (skb_is_nonlinear(skb)) {
 		skb_frag_t *frag;
-		if (fcoe_get_paged_crc_eof(skb, tlen)) {
+		if (fcoe_alloc_paged_crc_eof(skb, tlen)) {
 			kfree_skb(skb);
 			return -ENOMEM;
 		}
@@ -1606,6 +1510,56 @@ static void fcoe_percpu_flush_done(struct sk_buff *skb)
 }
 
 /**
+ * fcoe_filter_frames() - filter out bad fcoe frames, i.e. bad CRC
+ * @lport: The local port the frame was received on
+ * @fp:	   The received frame
+ *
+ * Return: 0 on passing filtering checks
+ */
+static inline int fcoe_filter_frames(struct fc_lport *lport,
+				     struct fc_frame *fp)
+{
+	struct fcoe_interface *fcoe;
+	struct fc_frame_header *fh;
+	struct sk_buff *skb = (struct sk_buff *)fp;
+	struct fcoe_dev_stats *stats;
+
+	/*
+	 * We only check CRC if no offload is available and if it is
+	 * it's solicited data, in which case, the FCP layer would
+	 * check it during the copy.
+	 */
+	if (lport->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY)
+		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+	else
+		fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
+
+	fh = (struct fc_frame_header *) skb_transport_header(skb);
+	fh = fc_frame_header_get(fp);
+	if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP)
+		return 0;
+
+	fcoe = ((struct fcoe_port *)lport_priv(lport))->priv;
+	if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO &&
+	    ntoh24(fh->fh_s_id) == FC_FID_FLOGI) {
+		FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n");
+		return -EINVAL;
+	}
+
+	if (!(fr_flags(fp) & FCPHF_CRC_UNCHECKED) ||
+	    le32_to_cpu(fr_crc(fp)) == ~crc32(~0, skb->data, skb->len)) {
+		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+		return 0;
+	}
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->InvalidCRCCount++;
+	if (stats->InvalidCRCCount < 5)
+		printk(KERN_WARNING "fcoe: dropping frame with CRC error\n");
+	return -EINVAL;
+}
+
+/**
  * fcoe_recv_frame() - process a single received frame
  * @skb: frame to process
  */
@@ -1615,7 +1569,6 @@ static void fcoe_recv_frame(struct sk_buff *skb)
 	struct fc_lport *lport;
 	struct fcoe_rcv_info *fr;
 	struct fcoe_dev_stats *stats;
-	struct fc_frame_header *fh;
 	struct fcoe_crc_eof crc_eof;
 	struct fc_frame *fp;
 	struct fcoe_port *port;
@@ -1646,7 +1599,6 @@ static void fcoe_recv_frame(struct sk_buff *skb)
 	 * was done in fcoe_rcv already.
 	 */
 	hp = (struct fcoe_hdr *) skb_network_header(skb);
-	fh = (struct fc_frame_header *) skb_transport_header(skb);
 
 	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
 	if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
@@ -1679,35 +1631,11 @@ static void fcoe_recv_frame(struct sk_buff *skb)
 	if (pskb_trim(skb, fr_len))
 		goto drop;
 
-	/*
-	 * We only check CRC if no offload is available and if it is
-	 * it's solicited data, in which case, the FCP layer would
-	 * check it during the copy.
-	 */
-	if (lport->crc_offload &&
-	    skb->ip_summed == CHECKSUM_UNNECESSARY)
-		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
-	else
-		fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
-
-	fh = fc_frame_header_get(fp);
-	if ((fh->fh_r_ctl != FC_RCTL_DD_SOL_DATA ||
-	    fh->fh_type != FC_TYPE_FCP) &&
-	    (fr_flags(fp) & FCPHF_CRC_UNCHECKED)) {
-		if (le32_to_cpu(fr_crc(fp)) !=
-		    ~crc32(~0, skb->data, fr_len)) {
-			if (stats->InvalidCRCCount < 5)
-				printk(KERN_WARNING "fcoe: dropping "
-				       "frame with CRC error\n");
-			stats->InvalidCRCCount++;
-			goto drop;
-		}
-		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+	if (!fcoe_filter_frames(lport, fp)) {
+		put_cpu();
+		fc_exch_recv(lport, fp);
+		return;
 	}
-	put_cpu();
-	fc_exch_recv(lport, fp);
-	return;
-
 drop:
 	stats->ErrorFrames++;
 	put_cpu();
@@ -1746,64 +1674,6 @@ int fcoe_percpu_receive_thread(void *arg)
 }
 
 /**
- * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
- * @lport: The local port whose backlog is to be cleared
- *
- * This empties the wait_queue, dequeues the head of the wait_queue queue
- * and calls fcoe_start_io() for each packet. If all skb have been
- * transmitted it returns the qlen. If an error occurs it restores
- * wait_queue (to try again later) and returns -1.
- *
- * The wait_queue is used when the skb transmit fails. The failed skb
- * will go in the wait_queue which will be emptied by the timer function or
- * by the next skb transmit.
- */
-static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
-{
-	struct fcoe_port *port = lport_priv(lport);
-	int rc;
-
-	spin_lock_bh(&port->fcoe_pending_queue.lock);
-
-	if (skb)
-		__skb_queue_tail(&port->fcoe_pending_queue, skb);
-
-	if (port->fcoe_pending_queue_active)
-		goto out;
-	port->fcoe_pending_queue_active = 1;
-
-	while (port->fcoe_pending_queue.qlen) {
-		/* keep qlen > 0 until fcoe_start_io succeeds */
-		port->fcoe_pending_queue.qlen++;
-		skb = __skb_dequeue(&port->fcoe_pending_queue);
-
-		spin_unlock_bh(&port->fcoe_pending_queue.lock);
-		rc = fcoe_start_io(skb);
-		spin_lock_bh(&port->fcoe_pending_queue.lock);
-
-		if (rc) {
-			__skb_queue_head(&port->fcoe_pending_queue, skb);
-			/* undo temporary increment above */
-			port->fcoe_pending_queue.qlen--;
-			break;
-		}
-		/* undo temporary increment above */
-		port->fcoe_pending_queue.qlen--;
-	}
-
-	if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
-		lport->qfull = 0;
-	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
-		mod_timer(&port->timer, jiffies + 2);
-	port->fcoe_pending_queue_active = 0;
-out:
-	if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
-		lport->qfull = 1;
-	spin_unlock_bh(&port->fcoe_pending_queue.lock);
-	return;
-}
-
-/**
  * fcoe_dev_setup() - Setup the link change notification interface
  */
 static void fcoe_dev_setup(void)
@@ -1874,7 +1744,7 @@ static int fcoe_device_notification(struct notifier_block *notifier,
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
 		fcoe_interface_cleanup(fcoe);
-		schedule_work(&port->destroy_work);
+		queue_work(fcoe_wq, &port->destroy_work);
 		goto out;
 		break;
 	case NETDEV_FEAT_CHANGE:
@@ -1900,39 +1770,16 @@ out:
 }
 
 /**
- * fcoe_if_to_netdev() - Parse a name buffer to get a net device
- * @buffer: The name of the net device
- *
- * Returns: NULL or a ptr to net_device
- */
-static struct net_device *fcoe_if_to_netdev(const char *buffer)
-{
-	char *cp;
-	char ifname[IFNAMSIZ + 2];
-
-	if (buffer) {
-		strlcpy(ifname, buffer, IFNAMSIZ);
-		cp = ifname + strlen(ifname);
-		while (--cp >= ifname && *cp == '\n')
-			*cp = '\0';
-		return dev_get_by_name(&init_net, ifname);
-	}
-	return NULL;
-}
-
-/**
  * fcoe_disable() - Disables a FCoE interface
- * @buffer: The name of the Ethernet interface to be disabled
- * @kp:	    The associated kernel parameter
+ * @netdev  : The net_device object the Ethernet interface to create on
  *
- * Called from sysfs.
+ * Called from fcoe transport.
  *
  * Returns: 0 for success
  */
-static int fcoe_disable(const char *buffer, struct kernel_param *kp)
+static int fcoe_disable(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -1948,16 +1795,9 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp)
 	}
 #endif
 
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
-		goto out_nodev;
-	}
-
 	if (!rtnl_trylock()) {
-		dev_put(netdev);
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 	fcoe = fcoe_hostlist_lookup_port(netdev);
@@ -1969,7 +1809,6 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp)
 	} else
 		rc = -ENODEV;
 
-	dev_put(netdev);
 out_nodev:
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -1977,17 +1816,15 @@ out_nodev:
 
 /**
  * fcoe_enable() - Enables a FCoE interface
- * @buffer: The name of the Ethernet interface to be enabled
- * @kp:     The associated kernel parameter
+ * @netdev  : The net_device object the Ethernet interface to create on
  *
- * Called from sysfs.
+ * Called from fcoe transport.
  *
  * Returns: 0 for success
  */
-static int fcoe_enable(const char *buffer, struct kernel_param *kp)
+static int fcoe_enable(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -2002,17 +1839,9 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp)
 		goto out_nodev;
 	}
 #endif
-
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
-		goto out_nodev;
-	}
-
 	if (!rtnl_trylock()) {
-		dev_put(netdev);
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 	fcoe = fcoe_hostlist_lookup_port(netdev);
@@ -2023,7 +1852,6 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp)
 	else if (!fcoe_link_ok(fcoe->ctlr.lp))
 		fcoe_ctlr_link_up(&fcoe->ctlr);
 
-	dev_put(netdev);
 out_nodev:
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -2031,17 +1859,15 @@ out_nodev:
 
 /**
  * fcoe_destroy() - Destroy a FCoE interface
- * @buffer: The name of the Ethernet interface to be destroyed
- * @kp:	    The associated kernel parameter
+ * @netdev  : The net_device object the Ethernet interface to create on
  *
- * Called from sysfs.
+ * Called from fcoe transport
  *
  * Returns: 0 for success
  */
-static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
+static int fcoe_destroy(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -2056,32 +1882,21 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
 		goto out_nodev;
 	}
 #endif
-
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
-		goto out_nodev;
-	}
-
 	if (!rtnl_trylock()) {
-		dev_put(netdev);
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 	fcoe = fcoe_hostlist_lookup_port(netdev);
 	if (!fcoe) {
 		rtnl_unlock();
 		rc = -ENODEV;
-		goto out_putdev;
+		goto out_nodev;
 	}
 	fcoe_interface_cleanup(fcoe);
 	list_del(&fcoe->list);
 	/* RTNL mutex is dropped by fcoe_if_destroy */
 	fcoe_if_destroy(fcoe->ctlr.lp);
-
-out_putdev:
-	dev_put(netdev);
 out_nodev:
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -2104,27 +1919,39 @@ static void fcoe_destroy_work(struct work_struct *work)
 }
 
 /**
+ * fcoe_match() - Check if the FCoE is supported on the given netdevice
+ * @netdev  : The net_device object the Ethernet interface to create on
+ *
+ * Called from fcoe transport.
+ *
+ * Returns: always returns true as this is the default FCoE transport,
+ * i.e., support all netdevs.
+ */
+static bool fcoe_match(struct net_device *netdev)
+{
+	return true;
+}
+
+/**
  * fcoe_create() - Create a fcoe interface
- * @buffer: The name of the Ethernet interface to create on
- * @kp:	    The associated kernel param
+ * @netdev  : The net_device object the Ethernet interface to create on
+ * @fip_mode: The FIP mode for this creation
  *
- * Called from sysfs.
+ * Called from fcoe transport
  *
  * Returns: 0 for success
  */
-static int fcoe_create(const char *buffer, struct kernel_param *kp)
+static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
 {
-	enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
 	int rc;
 	struct fcoe_interface *fcoe;
 	struct fc_lport *lport;
-	struct net_device *netdev;
 
 	mutex_lock(&fcoe_config_mutex);
 
 	if (!rtnl_trylock()) {
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 #ifdef CONFIG_FCOE_MODULE
@@ -2135,31 +1962,20 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	 */
 	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
 		rc = -ENODEV;
-		goto out_nomod;
-	}
-#endif
-
-	if (!try_module_get(THIS_MODULE)) {
-		rc = -EINVAL;
-		goto out_nomod;
-	}
-
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
 		goto out_nodev;
 	}
+#endif
 
 	/* look for existing lport */
 	if (fcoe_hostlist_lookup(netdev)) {
 		rc = -EEXIST;
-		goto out_putdev;
+		goto out_nodev;
 	}
 
 	fcoe = fcoe_interface_create(netdev, fip_mode);
-	if (!fcoe) {
-		rc = -ENOMEM;
-		goto out_putdev;
+	if (IS_ERR(fcoe)) {
+		rc = PTR_ERR(fcoe);
+		goto out_nodev;
 	}
 
 	lport = fcoe_if_create(fcoe, &netdev->dev, 0);
@@ -2188,18 +2004,13 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
 	 * should be holding a reference taken in fcoe_if_create().
 	 */
 	fcoe_interface_put(fcoe);
-	dev_put(netdev);
 	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
 
 	return 0;
 out_free:
 	fcoe_interface_put(fcoe);
-out_putdev:
-	dev_put(netdev);
 out_nodev:
-	module_put(THIS_MODULE);
-out_nomod:
 	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -2214,8 +2025,7 @@ out_nomod:
  */
 int fcoe_link_speed_update(struct fc_lport *lport)
 {
-	struct fcoe_port *port = lport_priv(lport);
-	struct net_device *netdev = port->fcoe->netdev;
+	struct net_device *netdev = fcoe_netdev(lport);
 	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 
 	if (!dev_ethtool_get_settings(netdev, &ecmd)) {
@@ -2246,8 +2056,7 @@ int fcoe_link_speed_update(struct fc_lport *lport)
  */
 int fcoe_link_ok(struct fc_lport *lport)
 {
-	struct fcoe_port *port = lport_priv(lport);
-	struct net_device *netdev = port->fcoe->netdev;
+	struct net_device *netdev = fcoe_netdev(lport);
 
 	if (netif_oper_up(netdev))
 		return 0;
@@ -2311,24 +2120,6 @@ void fcoe_percpu_clean(struct fc_lport *lport)
 }
 
 /**
- * fcoe_clean_pending_queue() - Dequeue a skb and free it
- * @lport: The local port to dequeue a skb on
- */
-void fcoe_clean_pending_queue(struct fc_lport *lport)
-{
-	struct fcoe_port  *port = lport_priv(lport);
-	struct sk_buff *skb;
-
-	spin_lock_bh(&port->fcoe_pending_queue.lock);
-	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
-		spin_unlock_bh(&port->fcoe_pending_queue.lock);
-		kfree_skb(skb);
-		spin_lock_bh(&port->fcoe_pending_queue.lock);
-	}
-	spin_unlock_bh(&port->fcoe_pending_queue.lock);
-}
-
-/**
  * fcoe_reset() - Reset a local port
  * @shost: The SCSI host associated with the local port to be reset
  *
@@ -2337,7 +2128,13 @@ void fcoe_clean_pending_queue(struct fc_lport *lport)
 int fcoe_reset(struct Scsi_Host *shost)
 {
 	struct fc_lport *lport = shost_priv(shost);
-	fc_lport_reset(lport);
+	struct fcoe_port *port = lport_priv(lport);
+	struct fcoe_interface *fcoe = port->priv;
+
+	fcoe_ctlr_link_down(&fcoe->ctlr);
+	fcoe_clean_pending_queue(fcoe->ctlr.lp);
+	if (!fcoe_link_ok(fcoe->ctlr.lp))
+		fcoe_ctlr_link_up(&fcoe->ctlr);
 	return 0;
 }
 
@@ -2395,12 +2192,24 @@ static int fcoe_hostlist_add(const struct fc_lport *lport)
 	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
 	if (!fcoe) {
 		port = lport_priv(lport);
-		fcoe = port->fcoe;
+		fcoe = port->priv;
 		list_add_tail(&fcoe->list, &fcoe_hostlist);
 	}
 	return 0;
 }
 
+
+static struct fcoe_transport fcoe_sw_transport = {
+	.name = {FCOE_TRANSPORT_DEFAULT},
+	.attached = false,
+	.list = LIST_HEAD_INIT(fcoe_sw_transport.list),
+	.match = fcoe_match,
+	.create = fcoe_create,
+	.destroy = fcoe_destroy,
+	.enable = fcoe_enable,
+	.disable = fcoe_disable,
+};
+
 /**
  * fcoe_init() - Initialize fcoe.ko
  *
@@ -2412,6 +2221,18 @@ static int __init fcoe_init(void)
 	unsigned int cpu;
 	int rc = 0;
 
+	fcoe_wq = alloc_workqueue("fcoe", 0, 0);
+	if (!fcoe_wq)
+		return -ENOMEM;
+
+	/* register as a fcoe transport */
+	rc = fcoe_transport_attach(&fcoe_sw_transport);
+	if (rc) {
+		printk(KERN_ERR "failed to register an fcoe transport, check "
+			"if libfcoe is loaded\n");
+		return rc;
+	}
+
 	mutex_lock(&fcoe_config_mutex);
 
 	for_each_possible_cpu(cpu) {
@@ -2442,6 +2263,7 @@ out_free:
 		fcoe_percpu_thread_destroy(cpu);
 	}
 	mutex_unlock(&fcoe_config_mutex);
+	destroy_workqueue(fcoe_wq);
 	return rc;
 }
 module_init(fcoe_init);
@@ -2467,7 +2289,7 @@ static void __exit fcoe_exit(void)
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
 		fcoe_interface_cleanup(fcoe);
-		schedule_work(&port->destroy_work);
+		queue_work(fcoe_wq, &port->destroy_work);
 	}
 	rtnl_unlock();
 
@@ -2478,16 +2300,21 @@ static void __exit fcoe_exit(void)
 
 	mutex_unlock(&fcoe_config_mutex);
 
-	/* flush any asyncronous interface destroys,
-	 * this should happen after the netdev notifier is unregistered */
-	flush_scheduled_work();
-	/* That will flush out all the N_Ports on the hostlist, but now we
-	 * may have NPIV VN_Ports scheduled for destruction */
-	flush_scheduled_work();
+	/*
+	 * destroy_work's may be chained but destroy_workqueue()
+	 * can take care of them. Just kill the fcoe_wq.
+	 */
+	destroy_workqueue(fcoe_wq);
 
-	/* detach from scsi transport
-	 * must happen after all destroys are done, therefor after the flush */
+	/*
+	 * Detaching from the scsi transport must happen after all
+	 * destroys are done on the fcoe_wq. destroy_workqueue will
+	 * enusre the fcoe_wq is flushed.
+	 */
 	fcoe_if_exit();
+
+	/* detach from fcoe transport */
+	fcoe_transport_detach(&fcoe_sw_transport);
 }
 module_exit(fcoe_exit);
 
@@ -2559,7 +2386,7 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did,
 				      void *arg, u32 timeout)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct fcoe_ctlr *fip = &fcoe->ctlr;
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 
@@ -2592,7 +2419,7 @@ static int fcoe_vport_create(struct fc_vport *vport, bool disabled)
 	struct Scsi_Host *shost = vport_to_shost(vport);
 	struct fc_lport *n_port = shost_priv(shost);
 	struct fcoe_port *port = lport_priv(n_port);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct net_device *netdev = fcoe->netdev;
 	struct fc_lport *vn_port;
 
@@ -2632,7 +2459,7 @@ static int fcoe_vport_destroy(struct fc_vport *vport)
 	mutex_lock(&n_port->lp_mutex);
 	list_del(&vn_port->list);
 	mutex_unlock(&n_port->lp_mutex);
-	schedule_work(&port->destroy_work);
+	queue_work(fcoe_wq, &port->destroy_work);
 	return 0;
 }
 
@@ -2736,7 +2563,7 @@ static void fcoe_set_port_id(struct fc_lport *lport,
 			     u32 port_id, struct fc_frame *fp)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 
 	if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
 		fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
index c69b2c5..408a6fd 100644
--- a/drivers/scsi/fcoe/fcoe.h
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -24,7 +24,7 @@
 #include <linux/kthread.h>
 
 #define FCOE_MAX_QUEUE_DEPTH	256
-#define FCOE_LOW_QUEUE_DEPTH	32
+#define FCOE_MIN_QUEUE_DEPTH	32
 
 #define FCOE_WORD_TO_BYTE	4
 
@@ -40,12 +40,6 @@
 #define FCOE_MIN_XID		0x0000	/* the min xid supported by fcoe_sw */
 #define FCOE_MAX_XID		0x0FFF	/* the max xid supported by fcoe_sw */
 
-/*
- * Max MTU for FCoE: 14 (FCoE header) + 24 (FC header) + 2112 (max FC payload)
- * + 4 (FC CRC) + 4 (FCoE trailer) =  2158 bytes
- */
-#define FCOE_MTU	2158
-
 unsigned int fcoe_debug_logging;
 module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
@@ -71,21 +65,6 @@ do {                                                            	\
 				  netdev->name, ##args);)
 
 /**
- * struct fcoe_percpu_s - The per-CPU context for FCoE receive threads
- * @thread:	    The thread context
- * @fcoe_rx_list:   The queue of pending packets to process
- * @page:	    The memory page for calculating frame trailer CRCs
- * @crc_eof_offset: The offset into the CRC page pointing to available
- *		    memory for a new trailer
- */
-struct fcoe_percpu_s {
-	struct task_struct *thread;
-	struct sk_buff_head fcoe_rx_list;
-	struct page *crc_eof_page;
-	int crc_eof_offset;
-};
-
-/**
  * struct fcoe_interface - A FCoE interface
  * @list:	      Handle for a list of FCoE interfaces
  * @netdev:	      The associated net device
@@ -108,30 +87,6 @@ struct fcoe_interface {
 	struct kref	   kref;
 };
 
-/**
- * struct fcoe_port - The FCoE private structure
- * @fcoe:		       The associated fcoe interface
- * @lport:		       The associated local port
- * @fcoe_pending_queue:	       The pending Rx queue of skbs
- * @fcoe_pending_queue_active: Indicates if the pending queue is active
- * @timer:		       The queue timer
- * @destroy_work:	       Handle for work context
- *			       (to prevent RTNL deadlocks)
- * @data_srt_addr:	       Source address for data
- *
- * An instance of this structure is to be allocated along with the
- * Scsi_Host and libfc fc_lport structures.
- */
-struct fcoe_port {
-	struct fcoe_interface *fcoe;
-	struct fc_lport	      *lport;
-	struct sk_buff_head   fcoe_pending_queue;
-	u8		      fcoe_pending_queue_active;
-	struct timer_list     timer;
-	struct work_struct    destroy_work;
-	u8		      data_src_addr[ETH_ALEN];
-};
-
 #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)
 
 /**
@@ -140,7 +95,8 @@ struct fcoe_port {
  */
 static inline struct net_device *fcoe_netdev(const struct fc_lport *lport)
 {
-	return ((struct fcoe_port *)lport_priv(lport))->fcoe->netdev;
+	return ((struct fcoe_interface *)
+			((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
 }
 
 #endif /* _FCOE_H_ */
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
new file mode 100644
index 0000000..c93f007
--- /dev/null
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -0,0 +1,2682 @@
+/*
+ * Copyright (c) 2008-2009 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2009 Intel Corporation.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <net/rtnetlink.h>
+
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fip.h>
+#include <scsi/fc/fc_encaps.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/fc/fc_fcp.h>
+
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+
+#include "libfcoe.h"
+
+#define	FCOE_CTLR_MIN_FKA	500		/* min keep alive (mS) */
+#define	FCOE_CTLR_DEF_FKA	FIP_DEF_FKA	/* default keep alive (mS) */
+
+static void fcoe_ctlr_timeout(unsigned long);
+static void fcoe_ctlr_timer_work(struct work_struct *);
+static void fcoe_ctlr_recv_work(struct work_struct *);
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
+
+static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
+static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
+static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
+static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
+
+static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
+static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
+static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
+static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS;
+
+static const char * const fcoe_ctlr_states[] = {
+	[FIP_ST_DISABLED] =	"DISABLED",
+	[FIP_ST_LINK_WAIT] =	"LINK_WAIT",
+	[FIP_ST_AUTO] =		"AUTO",
+	[FIP_ST_NON_FIP] =	"NON_FIP",
+	[FIP_ST_ENABLED] =	"ENABLED",
+	[FIP_ST_VNMP_START] =	"VNMP_START",
+	[FIP_ST_VNMP_PROBE1] =	"VNMP_PROBE1",
+	[FIP_ST_VNMP_PROBE2] =	"VNMP_PROBE2",
+	[FIP_ST_VNMP_CLAIM] =	"VNMP_CLAIM",
+	[FIP_ST_VNMP_UP] =	"VNMP_UP",
+};
+
+static const char *fcoe_ctlr_state(enum fip_state state)
+{
+	const char *cp = "unknown";
+
+	if (state < ARRAY_SIZE(fcoe_ctlr_states))
+		cp = fcoe_ctlr_states[state];
+	if (!cp)
+		cp = "unknown";
+	return cp;
+}
+
+/**
+ * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state.
+ * @fip: The FCoE controller
+ * @state: The new state
+ */
+static void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state)
+{
+	if (state == fip->state)
+		return;
+	if (fip->lp)
+		LIBFCOE_FIP_DBG(fip, "state %s -> %s\n",
+			fcoe_ctlr_state(fip->state), fcoe_ctlr_state(state));
+	fip->state = state;
+}
+
+/**
+ * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid
+ * @fcf: The FCF to check
+ *
+ * Return non-zero if FCF fcoe_size has been validated.
+ */
+static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf)
+{
+	return (fcf->flags & FIP_FL_SOL) != 0;
+}
+
+/**
+ * fcoe_ctlr_fcf_usable() - Check if a FCF is usable
+ * @fcf: The FCF to check
+ *
+ * Return non-zero if the FCF is usable.
+ */
+static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf)
+{
+	u16 flags = FIP_FL_SOL | FIP_FL_AVAIL;
+
+	return (fcf->flags & flags) == flags;
+}
+
+/**
+ * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses
+ * @fip: The FCoE controller
+ */
+static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip)
+{
+	if (fip->mode == FIP_MODE_VN2VN)
+		hton24(fip->dest_addr, FIP_VN_FC_MAP);
+	else
+		hton24(fip->dest_addr, FIP_DEF_FC_MAP);
+	hton24(fip->dest_addr + 3, 0);
+	fip->map_dest = 1;
+}
+
+/**
+ * fcoe_ctlr_init() - Initialize the FCoE Controller instance
+ * @fip: The FCoE controller to initialize
+ */
+void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
+{
+	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
+	fip->mode = mode;
+	INIT_LIST_HEAD(&fip->fcfs);
+	mutex_init(&fip->ctlr_mutex);
+	spin_lock_init(&fip->ctlr_lock);
+	fip->flogi_oxid = FC_XID_UNKNOWN;
+	setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
+	INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
+	INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
+	skb_queue_head_init(&fip->fip_recv_list);
+}
+EXPORT_SYMBOL(fcoe_ctlr_init);
+
+/**
+ * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller
+ * @fip: The FCoE controller whose FCFs are to be reset
+ *
+ * Called with &fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf *next;
+
+	fip->sel_fcf = NULL;
+	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
+		list_del(&fcf->list);
+		kfree(fcf);
+	}
+	fip->fcf_count = 0;
+	fip->sel_time = 0;
+}
+
+/**
+ * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller
+ * @fip: The FCoE controller to tear down
+ *
+ * This is called by FCoE drivers before freeing the &fcoe_ctlr.
+ *
+ * The receive handler will have been deleted before this to guarantee
+ * that no more recv_work will be scheduled.
+ *
+ * The timer routine will simply return once we set FIP_ST_DISABLED.
+ * This guarantees that no further timeouts or work will be scheduled.
+ */
+void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
+{
+	cancel_work_sync(&fip->recv_work);
+	skb_queue_purge(&fip->fip_recv_list);
+
+	mutex_lock(&fip->ctlr_mutex);
+	fcoe_ctlr_set_state(fip, FIP_ST_DISABLED);
+	fcoe_ctlr_reset_fcfs(fip);
+	mutex_unlock(&fip->ctlr_mutex);
+	del_timer_sync(&fip->timer);
+	cancel_work_sync(&fip->timer_work);
+}
+EXPORT_SYMBOL(fcoe_ctlr_destroy);
+
+/**
+ * fcoe_ctlr_announce() - announce new FCF selection
+ * @fip: The FCoE controller
+ *
+ * Also sets the destination MAC for FCoE and control packets
+ *
+ * Called with neither ctlr_mutex nor ctlr_lock held.
+ */
+static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *sel;
+	struct fcoe_fcf *fcf;
+
+	mutex_lock(&fip->ctlr_mutex);
+	spin_lock_bh(&fip->ctlr_lock);
+
+	kfree_skb(fip->flogi_req);
+	fip->flogi_req = NULL;
+	list_for_each_entry(fcf, &fip->fcfs, list)
+		fcf->flogi_sent = 0;
+
+	spin_unlock_bh(&fip->ctlr_lock);
+	sel = fip->sel_fcf;
+
+	if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
+		goto unlock;
+	if (!is_zero_ether_addr(fip->dest_addr)) {
+		printk(KERN_NOTICE "libfcoe: host%d: "
+		       "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
+		       fip->lp->host->host_no, fip->dest_addr);
+		memset(fip->dest_addr, 0, ETH_ALEN);
+	}
+	if (sel) {
+		printk(KERN_INFO "libfcoe: host%d: FIP selected "
+		       "Fibre-Channel Forwarder MAC %pM\n",
+		       fip->lp->host->host_no, sel->fcf_mac);
+		memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
+		fip->map_dest = 0;
+	}
+unlock:
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
+ * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port
+ * @fip: The FCoE controller to get the maximum FCoE size from
+ *
+ * Returns the maximum packet size including the FCoE header and trailer,
+ * but not including any Ethernet or VLAN headers.
+ */
+static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip)
+{
+	/*
+	 * Determine the max FCoE frame size allowed, including
+	 * FCoE header and trailer.
+	 * Note:  lp->mfs is currently the payload size, not the frame size.
+	 */
+	return fip->lp->mfs + sizeof(struct fc_frame_header) +
+		sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof);
+}
+
+/**
+ * fcoe_ctlr_solicit() - Send a FIP solicitation
+ * @fip: The FCoE controller to send the solicitation on
+ * @fcf: The destination FCF (if NULL, a multicast solicitation is sent)
+ */
+static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
+{
+	struct sk_buff *skb;
+	struct fip_sol {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct {
+			struct fip_mac_desc mac;
+			struct fip_wwn_desc wwnn;
+			struct fip_size_desc size;
+		} __packed desc;
+	}  __packed * sol;
+	u32 fcoe_size;
+
+	skb = dev_alloc_skb(sizeof(*sol));
+	if (!skb)
+		return;
+
+	sol = (struct fip_sol *)skb->data;
+
+	memset(sol, 0, sizeof(*sol));
+	memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN);
+	memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+	sol->eth.h_proto = htons(ETH_P_FIP);
+
+	sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	sol->fip.fip_op = htons(FIP_OP_DISC);
+	sol->fip.fip_subcode = FIP_SC_SOL;
+	sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW);
+	sol->fip.fip_flags = htons(FIP_FL_FPMA);
+	if (fip->spma)
+		sol->fip.fip_flags |= htons(FIP_FL_SPMA);
+
+	sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
+	sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW;
+	memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+	sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+	sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
+	put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
+
+	fcoe_size = fcoe_ctlr_fcoe_size(fip);
+	sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
+	sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW;
+	sol->desc.size.fd_size = htons(fcoe_size);
+
+	skb_put(skb, sizeof(*sol));
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	fip->send(fip, skb);
+
+	if (!fcf)
+		fip->sol_time = jiffies;
+}
+
+/**
+ * fcoe_ctlr_link_up() - Start FCoE controller
+ * @fip: The FCoE controller to start
+ *
+ * Called from the LLD when the network link is ready.
+ */
+void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
+{
+	mutex_lock(&fip->ctlr_mutex);
+	if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
+		mutex_unlock(&fip->ctlr_mutex);
+		fc_linkup(fip->lp);
+	} else if (fip->state == FIP_ST_LINK_WAIT) {
+		fcoe_ctlr_set_state(fip, fip->mode);
+		switch (fip->mode) {
+		default:
+			LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode);
+			/* fall-through */
+		case FIP_MODE_AUTO:
+			LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
+			/* fall-through */
+		case FIP_MODE_FABRIC:
+		case FIP_MODE_NON_FIP:
+			mutex_unlock(&fip->ctlr_mutex);
+			fc_linkup(fip->lp);
+			fcoe_ctlr_solicit(fip, NULL);
+			break;
+		case FIP_MODE_VN2VN:
+			fcoe_ctlr_vn_start(fip);
+			mutex_unlock(&fip->ctlr_mutex);
+			fc_linkup(fip->lp);
+			break;
+		}
+	} else
+		mutex_unlock(&fip->ctlr_mutex);
+}
+EXPORT_SYMBOL(fcoe_ctlr_link_up);
+
+/**
+ * fcoe_ctlr_reset() - Reset a FCoE controller
+ * @fip:       The FCoE controller to reset
+ */
+static void fcoe_ctlr_reset(struct fcoe_ctlr *fip)
+{
+	fcoe_ctlr_reset_fcfs(fip);
+	del_timer(&fip->timer);
+	fip->ctlr_ka_time = 0;
+	fip->port_ka_time = 0;
+	fip->sol_time = 0;
+	fip->flogi_oxid = FC_XID_UNKNOWN;
+	fcoe_ctlr_map_dest(fip);
+}
+
+/**
+ * fcoe_ctlr_link_down() - Stop a FCoE controller
+ * @fip: The FCoE controller to be stopped
+ *
+ * Returns non-zero if the link was up and now isn't.
+ *
+ * Called from the LLD when the network link is not ready.
+ * There may be multiple calls while the link is down.
+ */
+int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
+{
+	int link_dropped;
+
+	LIBFCOE_FIP_DBG(fip, "link down.\n");
+	mutex_lock(&fip->ctlr_mutex);
+	fcoe_ctlr_reset(fip);
+	link_dropped = fip->state != FIP_ST_LINK_WAIT;
+	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
+	mutex_unlock(&fip->ctlr_mutex);
+
+	if (link_dropped)
+		fc_linkdown(fip->lp);
+	return link_dropped;
+}
+EXPORT_SYMBOL(fcoe_ctlr_link_down);
+
+/**
+ * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF
+ * @fip:   The FCoE controller to send the FKA on
+ * @lport: libfc fc_lport to send from
+ * @ports: 0 for controller keep-alive, 1 for port keep-alive
+ * @sa:	   The source MAC address
+ *
+ * A controller keep-alive is sent every fka_period (typically 8 seconds).
+ * The source MAC is the native MAC address.
+ *
+ * A port keep-alive is sent every 90 seconds while logged in.
+ * The source MAC is the assigned mapped source address.
+ * The destination is the FCF's F-port.
+ */
+static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
+				      struct fc_lport *lport,
+				      int ports, u8 *sa)
+{
+	struct sk_buff *skb;
+	struct fip_kal {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct fip_mac_desc mac;
+	} __packed * kal;
+	struct fip_vn_desc *vn;
+	u32 len;
+	struct fc_lport *lp;
+	struct fcoe_fcf *fcf;
+
+	fcf = fip->sel_fcf;
+	lp = fip->lp;
+	if (!fcf || (ports && !lp->port_id))
+		return;
+
+	len = sizeof(*kal) + ports * sizeof(*vn);
+	skb = dev_alloc_skb(len);
+	if (!skb)
+		return;
+
+	kal = (struct fip_kal *)skb->data;
+	memset(kal, 0, len);
+	memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
+	memcpy(kal->eth.h_source, sa, ETH_ALEN);
+	kal->eth.h_proto = htons(ETH_P_FIP);
+
+	kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	kal->fip.fip_op = htons(FIP_OP_CTRL);
+	kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE;
+	kal->fip.fip_dl_len = htons((sizeof(kal->mac) +
+				     ports * sizeof(*vn)) / FIP_BPW);
+	kal->fip.fip_flags = htons(FIP_FL_FPMA);
+	if (fip->spma)
+		kal->fip.fip_flags |= htons(FIP_FL_SPMA);
+
+	kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
+	kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
+	memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+	if (ports) {
+		vn = (struct fip_vn_desc *)(kal + 1);
+		vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
+		vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
+		memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
+		hton24(vn->fd_fc_id, lport->port_id);
+		put_unaligned_be64(lport->wwpn, &vn->fd_wwpn);
+	}
+	skb_put(skb, len);
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	fip->send(fip, skb);
+}
+
+/**
+ * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it
+ * @fip:   The FCoE controller for the ELS frame
+ * @dtype: The FIP descriptor type for the frame
+ * @skb:   The FCoE ELS frame including FC header but no FCoE headers
+ * @d_id:  The destination port ID.
+ *
+ * Returns non-zero error code on failure.
+ *
+ * The caller must check that the length is a multiple of 4.
+ *
+ * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes).
+ * Headroom includes the FIP encapsulation description, FIP header, and
+ * Ethernet header.  The tailroom is for the FIP MAC descriptor.
+ */
+static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
+			    u8 dtype, struct sk_buff *skb, u32 d_id)
+{
+	struct fip_encaps_head {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct fip_encaps encaps;
+	} __packed * cap;
+	struct fc_frame_header *fh;
+	struct fip_mac_desc *mac;
+	struct fcoe_fcf *fcf;
+	size_t dlen;
+	u16 fip_flags;
+	u8 op;
+
+	fh = (struct fc_frame_header *)skb->data;
+	op = *(u8 *)(fh + 1);
+	dlen = sizeof(struct fip_encaps) + skb->len;	/* len before push */
+	cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
+	memset(cap, 0, sizeof(*cap));
+
+	if (lport->point_to_multipoint) {
+		if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest))
+			return -ENODEV;
+		fip_flags = 0;
+	} else {
+		fcf = fip->sel_fcf;
+		if (!fcf)
+			return -ENODEV;
+		fip_flags = fcf->flags;
+		fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA :
+					 FIP_FL_FPMA;
+		if (!fip_flags)
+			return -ENODEV;
+		memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
+	}
+	memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+	cap->eth.h_proto = htons(ETH_P_FIP);
+
+	cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	cap->fip.fip_op = htons(FIP_OP_LS);
+	if (op == ELS_LS_ACC || op == ELS_LS_RJT)
+		cap->fip.fip_subcode = FIP_SC_REP;
+	else
+		cap->fip.fip_subcode = FIP_SC_REQ;
+	cap->fip.fip_flags = htons(fip_flags);
+
+	cap->encaps.fd_desc.fip_dtype = dtype;
+	cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
+
+	if (op != ELS_LS_RJT) {
+		dlen += sizeof(*mac);
+		mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
+		memset(mac, 0, sizeof(*mac));
+		mac->fd_desc.fip_dtype = FIP_DT_MAC;
+		mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
+		if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) {
+			memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
+		} else if (fip->mode == FIP_MODE_VN2VN) {
+			hton24(mac->fd_mac, FIP_VN_FC_MAP);
+			hton24(mac->fd_mac + 3, fip->port_id);
+		} else if (fip_flags & FIP_FL_SPMA) {
+			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n");
+			memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN);
+		} else {
+			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n");
+			/* FPMA only FLOGI.  Must leave the MAC desc zeroed. */
+		}
+	}
+	cap->fip.fip_dl_len = htons(dlen / FIP_BPW);
+
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	return 0;
+}
+
+/**
+ * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate.
+ * @fip:	FCoE controller.
+ * @lport:	libfc fc_lport to send from
+ * @skb:	FCoE ELS frame including FC header but no FCoE headers.
+ *
+ * Returns a non-zero error code if the frame should not be sent.
+ * Returns zero if the caller should send the frame with FCoE encapsulation.
+ *
+ * The caller must check that the length is a multiple of 4.
+ * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
+ * The the skb must also be an fc_frame.
+ *
+ * This is called from the lower-level driver with spinlocks held,
+ * so we must not take a mutex here.
+ */
+int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
+		       struct sk_buff *skb)
+{
+	struct fc_frame *fp;
+	struct fc_frame_header *fh;
+	u16 old_xid;
+	u8 op;
+	u8 mac[ETH_ALEN];
+
+	fp = container_of(skb, struct fc_frame, skb);
+	fh = (struct fc_frame_header *)skb->data;
+	op = *(u8 *)(fh + 1);
+
+	if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) {
+		old_xid = fip->flogi_oxid;
+		fip->flogi_oxid = ntohs(fh->fh_ox_id);
+		if (fip->state == FIP_ST_AUTO) {
+			if (old_xid == FC_XID_UNKNOWN)
+				fip->flogi_count = 0;
+			fip->flogi_count++;
+			if (fip->flogi_count < 3)
+				goto drop;
+			fcoe_ctlr_map_dest(fip);
+			return 0;
+		}
+		if (fip->state == FIP_ST_NON_FIP)
+			fcoe_ctlr_map_dest(fip);
+	}
+
+	if (fip->state == FIP_ST_NON_FIP)
+		return 0;
+	if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN)
+		goto drop;
+	switch (op) {
+	case ELS_FLOGI:
+		op = FIP_DT_FLOGI;
+		if (fip->mode == FIP_MODE_VN2VN)
+			break;
+		spin_lock_bh(&fip->ctlr_lock);
+		kfree_skb(fip->flogi_req);
+		fip->flogi_req = skb;
+		fip->flogi_req_send = 1;
+		spin_unlock_bh(&fip->ctlr_lock);
+		schedule_work(&fip->timer_work);
+		return -EINPROGRESS;
+	case ELS_FDISC:
+		if (ntoh24(fh->fh_s_id))
+			return 0;
+		op = FIP_DT_FDISC;
+		break;
+	case ELS_LOGO:
+		if (fip->mode == FIP_MODE_VN2VN) {
+			if (fip->state != FIP_ST_VNMP_UP)
+				return -EINVAL;
+			if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI)
+				return -EINVAL;
+		} else {
+			if (fip->state != FIP_ST_ENABLED)
+				return 0;
+			if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
+				return 0;
+		}
+		op = FIP_DT_LOGO;
+		break;
+	case ELS_LS_ACC:
+		/*
+		 * If non-FIP, we may have gotten an SID by accepting an FLOGI
+		 * from a point-to-point connection.  Switch to using
+		 * the source mac based on the SID.  The destination
+		 * MAC in this case would have been set by receving the
+		 * FLOGI.
+		 */
+		if (fip->state == FIP_ST_NON_FIP) {
+			if (fip->flogi_oxid == FC_XID_UNKNOWN)
+				return 0;
+			fip->flogi_oxid = FC_XID_UNKNOWN;
+			fc_fcoe_set_mac(mac, fh->fh_d_id);
+			fip->update_mac(lport, mac);
+		}
+		/* fall through */
+	case ELS_LS_RJT:
+		op = fr_encaps(fp);
+		if (op)
+			break;
+		return 0;
+	default:
+		if (fip->state != FIP_ST_ENABLED &&
+		    fip->state != FIP_ST_VNMP_UP)
+			goto drop;
+		return 0;
+	}
+	LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n",
+			op, ntoh24(fh->fh_d_id));
+	if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id)))
+		goto drop;
+	fip->send(fip, skb);
+	return -EINPROGRESS;
+drop:
+	kfree_skb(skb);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(fcoe_ctlr_els_send);
+
+/**
+ * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller
+ * @fip: The FCoE controller to free FCFs on
+ *
+ * Called with lock held and preemption disabled.
+ *
+ * An FCF is considered old if we have missed two advertisements.
+ * That is, there have been no valid advertisement from it for 2.5
+ * times its keep-alive period.
+ *
+ * In addition, determine the time when an FCF selection can occur.
+ *
+ * Also, increment the MissDiscAdvCount when no advertisement is received
+ * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB).
+ *
+ * Returns the time in jiffies for the next call.
+ */
+static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf *next;
+	unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
+	unsigned long deadline;
+	unsigned long sel_time = 0;
+	struct fcoe_dev_stats *stats;
+
+	stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());
+
+	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
+		deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
+		if (fip->sel_fcf == fcf) {
+			if (time_after(jiffies, deadline)) {
+				stats->MissDiscAdvCount++;
+				printk(KERN_INFO "libfcoe: host%d: "
+				       "Missing Discovery Advertisement "
+				       "for fab %16.16llx count %lld\n",
+				       fip->lp->host->host_no, fcf->fabric_name,
+				       stats->MissDiscAdvCount);
+			} else if (time_after(next_timer, deadline))
+				next_timer = deadline;
+		}
+
+		deadline += fcf->fka_period;
+		if (time_after_eq(jiffies, deadline)) {
+			if (fip->sel_fcf == fcf)
+				fip->sel_fcf = NULL;
+			list_del(&fcf->list);
+			WARN_ON(!fip->fcf_count);
+			fip->fcf_count--;
+			kfree(fcf);
+			stats->VLinkFailureCount++;
+		} else {
+			if (time_after(next_timer, deadline))
+				next_timer = deadline;
+			if (fcoe_ctlr_mtu_valid(fcf) &&
+			    (!sel_time || time_before(sel_time, fcf->time)))
+				sel_time = fcf->time;
+		}
+	}
+	put_cpu();
+	if (sel_time && !fip->sel_fcf && !fip->sel_time) {
+		sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+		fip->sel_time = sel_time;
+	}
+
+	return next_timer;
+}
+
+/**
+ * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry
+ * @fip: The FCoE controller receiving the advertisement
+ * @skb: The received FIP advertisement frame
+ * @fcf: The resulting FCF entry
+ *
+ * Returns zero on a valid parsed advertisement,
+ * otherwise returns non zero value.
+ */
+static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip,
+			       struct sk_buff *skb, struct fcoe_fcf *fcf)
+{
+	struct fip_header *fiph;
+	struct fip_desc *desc = NULL;
+	struct fip_wwn_desc *wwn;
+	struct fip_fab_desc *fab;
+	struct fip_fka_desc *fka;
+	unsigned long t;
+	size_t rlen;
+	size_t dlen;
+	u32 desc_mask;
+
+	memset(fcf, 0, sizeof(*fcf));
+	fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA);
+
+	fiph = (struct fip_header *)skb->data;
+	fcf->flags = ntohs(fiph->fip_flags);
+
+	/*
+	 * mask of required descriptors. validating each one clears its bit.
+	 */
+	desc_mask = BIT(FIP_DT_PRI) | BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
+			BIT(FIP_DT_FAB) | BIT(FIP_DT_FKA);
+
+	rlen = ntohs(fiph->fip_dl_len) * 4;
+	if (rlen + sizeof(*fiph) > skb->len)
+		return -EINVAL;
+
+	desc = (struct fip_desc *)(fiph + 1);
+	while (rlen > 0) {
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen < sizeof(*desc) || dlen > rlen)
+			return -EINVAL;
+		/* Drop Adv if there are duplicate critical descriptors */
+		if ((desc->fip_dtype < 32) &&
+		    !(desc_mask & 1U << desc->fip_dtype)) {
+			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
+					"Descriptors in FIP adv\n");
+			return -EINVAL;
+		}
+		switch (desc->fip_dtype) {
+		case FIP_DT_PRI:
+			if (dlen != sizeof(struct fip_pri_desc))
+				goto len_err;
+			fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri;
+			desc_mask &= ~BIT(FIP_DT_PRI);
+			break;
+		case FIP_DT_MAC:
+			if (dlen != sizeof(struct fip_mac_desc))
+				goto len_err;
+			memcpy(fcf->fcf_mac,
+			       ((struct fip_mac_desc *)desc)->fd_mac,
+			       ETH_ALEN);
+			if (!is_valid_ether_addr(fcf->fcf_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC addr %pM in FIP adv\n",
+					fcf->fcf_mac);
+				return -EINVAL;
+			}
+			desc_mask &= ~BIT(FIP_DT_MAC);
+			break;
+		case FIP_DT_NAME:
+			if (dlen != sizeof(struct fip_wwn_desc))
+				goto len_err;
+			wwn = (struct fip_wwn_desc *)desc;
+			fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn);
+			desc_mask &= ~BIT(FIP_DT_NAME);
+			break;
+		case FIP_DT_FAB:
+			if (dlen != sizeof(struct fip_fab_desc))
+				goto len_err;
+			fab = (struct fip_fab_desc *)desc;
+			fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn);
+			fcf->vfid = ntohs(fab->fd_vfid);
+			fcf->fc_map = ntoh24(fab->fd_map);
+			desc_mask &= ~BIT(FIP_DT_FAB);
+			break;
+		case FIP_DT_FKA:
+			if (dlen != sizeof(struct fip_fka_desc))
+				goto len_err;
+			fka = (struct fip_fka_desc *)desc;
+			if (fka->fd_flags & FIP_FKA_ADV_D)
+				fcf->fd_flags = 1;
+			t = ntohl(fka->fd_fka_period);
+			if (t >= FCOE_CTLR_MIN_FKA)
+				fcf->fka_period = msecs_to_jiffies(t);
+			desc_mask &= ~BIT(FIP_DT_FKA);
+			break;
+		case FIP_DT_MAP_OUI:
+		case FIP_DT_FCOE_SIZE:
+		case FIP_DT_FLOGI:
+		case FIP_DT_FDISC:
+		case FIP_DT_LOGO:
+		case FIP_DT_ELP:
+		default:
+			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+					"in FIP adv\n", desc->fip_dtype);
+			/* standard says ignore unknown descriptors >= 128 */
+			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+				return -EINVAL;
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+	if (!fcf->fc_map || (fcf->fc_map & 0x10000))
+		return -EINVAL;
+	if (!fcf->switch_name)
+		return -EINVAL;
+	if (desc_mask) {
+		LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n",
+				desc_mask);
+		return -EINVAL;
+	}
+	return 0;
+
+len_err:
+	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
+			desc->fip_dtype, dlen);
+	return -EINVAL;
+}
+
+/**
+ * fcoe_ctlr_recv_adv() - Handle an incoming advertisement
+ * @fip: The FCoE controller receiving the advertisement
+ * @skb: The received FIP packet
+ */
+static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf new;
+	struct fcoe_fcf *found;
+	unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
+	int first = 0;
+	int mtu_valid;
+
+	if (fcoe_ctlr_parse_adv(fip, skb, &new))
+		return;
+
+	mutex_lock(&fip->ctlr_mutex);
+	first = list_empty(&fip->fcfs);
+	found = NULL;
+	list_for_each_entry(fcf, &fip->fcfs, list) {
+		if (fcf->switch_name == new.switch_name &&
+		    fcf->fabric_name == new.fabric_name &&
+		    fcf->fc_map == new.fc_map &&
+		    compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
+			found = fcf;
+			break;
+		}
+	}
+	if (!found) {
+		if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT)
+			goto out;
+
+		fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC);
+		if (!fcf)
+			goto out;
+
+		fip->fcf_count++;
+		memcpy(fcf, &new, sizeof(new));
+		list_add(&fcf->list, &fip->fcfs);
+	} else {
+		/*
+		 * Update the FCF's keep-alive descriptor flags.
+		 * Other flag changes from new advertisements are
+		 * ignored after a solicited advertisement is
+		 * received and the FCF is selectable (usable).
+		 */
+		fcf->fd_flags = new.fd_flags;
+		if (!fcoe_ctlr_fcf_usable(fcf))
+			fcf->flags = new.flags;
+
+		if (fcf == fip->sel_fcf && !fcf->fd_flags) {
+			fip->ctlr_ka_time -= fcf->fka_period;
+			fip->ctlr_ka_time += new.fka_period;
+			if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+				mod_timer(&fip->timer, fip->ctlr_ka_time);
+		}
+		fcf->fka_period = new.fka_period;
+		memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
+	}
+	mtu_valid = fcoe_ctlr_mtu_valid(fcf);
+	fcf->time = jiffies;
+	if (!found)
+		LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
+				fcf->fabric_name, fcf->fcf_mac);
+
+	/*
+	 * If this advertisement is not solicited and our max receive size
+	 * hasn't been verified, send a solicited advertisement.
+	 */
+	if (!mtu_valid)
+		fcoe_ctlr_solicit(fip, fcf);
+
+	/*
+	 * If its been a while since we did a solicit, and this is
+	 * the first advertisement we've received, do a multicast
+	 * solicitation to gather as many advertisements as we can
+	 * before selection occurs.
+	 */
+	if (first && time_after(jiffies, fip->sol_time + sol_tov))
+		fcoe_ctlr_solicit(fip, NULL);
+
+	/*
+	 * Put this FCF at the head of the list for priority among equals.
+	 * This helps in the case of an NPV switch which insists we use
+	 * the FCF that answers multicast solicitations, not the others that
+	 * are sending periodic multicast advertisements.
+	 */
+	if (mtu_valid) {
+		list_del(&fcf->list);
+		list_add(&fcf->list, &fip->fcfs);
+	}
+
+	/*
+	 * If this is the first validated FCF, note the time and
+	 * set a timer to trigger selection.
+	 */
+	if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) {
+		fip->sel_time = jiffies +
+			msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+		if (!timer_pending(&fip->timer) ||
+		    time_before(fip->sel_time, fip->timer.expires))
+			mod_timer(&fip->timer, fip->sel_time);
+	}
+out:
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
+ * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame
+ * @fip: The FCoE controller which received the packet
+ * @skb: The received FIP packet
+ */
+static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fip_header *fiph;
+	struct fc_frame *fp = (struct fc_frame *)skb;
+	struct fc_frame_header *fh = NULL;
+	struct fip_desc *desc;
+	struct fip_encaps *els;
+	struct fcoe_dev_stats *stats;
+	enum fip_desc_type els_dtype = 0;
+	u8 els_op;
+	u8 sub;
+	u8 granted_mac[ETH_ALEN] = { 0 };
+	size_t els_len = 0;
+	size_t rlen;
+	size_t dlen;
+	u32 desc_mask = 0;
+	u32 desc_cnt = 0;
+
+	fiph = (struct fip_header *)skb->data;
+	sub = fiph->fip_subcode;
+	if (sub != FIP_SC_REQ && sub != FIP_SC_REP)
+		goto drop;
+
+	rlen = ntohs(fiph->fip_dl_len) * 4;
+	if (rlen + sizeof(*fiph) > skb->len)
+		goto drop;
+
+	desc = (struct fip_desc *)(fiph + 1);
+	while (rlen > 0) {
+		desc_cnt++;
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen < sizeof(*desc) || dlen > rlen)
+			goto drop;
+		/* Drop ELS if there are duplicate critical descriptors */
+		if (desc->fip_dtype < 32) {
+			if (desc_mask & 1U << desc->fip_dtype) {
+				LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
+						"Descriptors in FIP ELS\n");
+				goto drop;
+			}
+			desc_mask |= (1 << desc->fip_dtype);
+		}
+		switch (desc->fip_dtype) {
+		case FIP_DT_MAC:
+			if (desc_cnt == 1) {
+				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
+						"received out of order\n");
+				goto drop;
+			}
+
+			if (dlen != sizeof(struct fip_mac_desc))
+				goto len_err;
+			memcpy(granted_mac,
+			       ((struct fip_mac_desc *)desc)->fd_mac,
+			       ETH_ALEN);
+			break;
+		case FIP_DT_FLOGI:
+		case FIP_DT_FDISC:
+		case FIP_DT_LOGO:
+		case FIP_DT_ELP:
+			if (desc_cnt != 1) {
+				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
+						"received out of order\n");
+				goto drop;
+			}
+			if (fh)
+				goto drop;
+			if (dlen < sizeof(*els) + sizeof(*fh) + 1)
+				goto len_err;
+			els_len = dlen - sizeof(*els);
+			els = (struct fip_encaps *)desc;
+			fh = (struct fc_frame_header *)(els + 1);
+			els_dtype = desc->fip_dtype;
+			break;
+		default:
+			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+					"in FIP adv\n", desc->fip_dtype);
+			/* standard says ignore unknown descriptors >= 128 */
+			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+				goto drop;
+			if (desc_cnt <= 2) {
+				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
+						"received out of order\n");
+				goto drop;
+			}
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+
+	if (!fh)
+		goto drop;
+	els_op = *(u8 *)(fh + 1);
+
+	if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
+	    sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
+		if (els_op == ELS_LS_ACC) {
+			if (!is_valid_ether_addr(granted_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC address %pM in FIP ELS\n",
+					granted_mac);
+				goto drop;
+			}
+			memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
+
+			if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+				fip->flogi_oxid = FC_XID_UNKNOWN;
+				if (els_dtype == FIP_DT_FLOGI)
+					fcoe_ctlr_announce(fip);
+			}
+		} else if (els_dtype == FIP_DT_FLOGI &&
+			   !fcoe_ctlr_flogi_retry(fip))
+			goto drop;	/* retrying FLOGI so drop reject */
+	}
+
+	if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
+	    (!(1U << FIP_DT_MAC & desc_mask)))) {
+		LIBFCOE_FIP_DBG(fip, "Missing critical descriptors "
+				"in FIP ELS\n");
+		goto drop;
+	}
+
+	/*
+	 * Convert skb into an fc_frame containing only the ELS.
+	 */
+	skb_pull(skb, (u8 *)fh - skb->data);
+	skb_trim(skb, els_len);
+	fp = (struct fc_frame *)skb;
+	fc_frame_init(fp);
+	fr_sof(fp) = FC_SOF_I3;
+	fr_eof(fp) = FC_EOF_T;
+	fr_dev(fp) = lport;
+	fr_encaps(fp) = els_dtype;
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->RxFrames++;
+	stats->RxWords += skb->len / FIP_BPW;
+	put_cpu();
+
+	fc_exch_recv(lport, fp);
+	return;
+
+len_err:
+	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
+			desc->fip_dtype, dlen);
+drop:
+	kfree_skb(skb);
+}
+
+/**
+ * fcoe_ctlr_recv_els() - Handle an incoming link reset frame
+ * @fip: The FCoE controller that received the frame
+ * @fh:	 The received FIP header
+ *
+ * There may be multiple VN_Port descriptors.
+ * The overall length has already been checked.
+ */
+static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
+				     struct fip_header *fh)
+{
+	struct fip_desc *desc;
+	struct fip_mac_desc *mp;
+	struct fip_wwn_desc *wp;
+	struct fip_vn_desc *vp;
+	size_t rlen;
+	size_t dlen;
+	struct fcoe_fcf *fcf = fip->sel_fcf;
+	struct fc_lport *lport = fip->lp;
+	struct fc_lport *vn_port = NULL;
+	u32 desc_mask;
+	int is_vn_port = 0;
+
+	LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
+
+	if (!fcf || !lport->port_id)
+		return;
+
+	/*
+	 * mask of required descriptors.  Validating each one clears its bit.
+	 */
+	desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID);
+
+	rlen = ntohs(fh->fip_dl_len) * FIP_BPW;
+	desc = (struct fip_desc *)(fh + 1);
+	while (rlen >= sizeof(*desc)) {
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen > rlen)
+			return;
+		/* Drop CVL if there are duplicate critical descriptors */
+		if ((desc->fip_dtype < 32) &&
+		    !(desc_mask & 1U << desc->fip_dtype)) {
+			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
+					"Descriptors in FIP CVL\n");
+			return;
+		}
+		switch (desc->fip_dtype) {
+		case FIP_DT_MAC:
+			mp = (struct fip_mac_desc *)desc;
+			if (dlen < sizeof(*mp))
+				return;
+			if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac))
+				return;
+			desc_mask &= ~BIT(FIP_DT_MAC);
+			break;
+		case FIP_DT_NAME:
+			wp = (struct fip_wwn_desc *)desc;
+			if (dlen < sizeof(*wp))
+				return;
+			if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name)
+				return;
+			desc_mask &= ~BIT(FIP_DT_NAME);
+			break;
+		case FIP_DT_VN_ID:
+			vp = (struct fip_vn_desc *)desc;
+			if (dlen < sizeof(*vp))
+				return;
+			if (compare_ether_addr(vp->fd_mac,
+					       fip->get_src_addr(lport)) == 0 &&
+			    get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
+			    ntoh24(vp->fd_fc_id) == lport->port_id) {
+				desc_mask &= ~BIT(FIP_DT_VN_ID);
+				break;
+			}
+			/* check if clr_vlink is for NPIV port */
+			mutex_lock(&lport->lp_mutex);
+			list_for_each_entry(vn_port, &lport->vports, list) {
+				if (compare_ether_addr(vp->fd_mac,
+				    fip->get_src_addr(vn_port)) == 0 &&
+				    (get_unaligned_be64(&vp->fd_wwpn)
+							== vn_port->wwpn) &&
+				    (ntoh24(vp->fd_fc_id) ==
+					    fc_host_port_id(vn_port->host))) {
+					desc_mask &= ~BIT(FIP_DT_VN_ID);
+					is_vn_port = 1;
+					break;
+				}
+			}
+			mutex_unlock(&lport->lp_mutex);
+
+			break;
+		default:
+			/* standard says ignore unknown descriptors >= 128 */
+			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+				return;
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+
+	/*
+	 * reset only if all required descriptors were present and valid.
+	 */
+	if (desc_mask) {
+		LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n",
+				desc_mask);
+	} else {
+		LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
+
+		if (is_vn_port)
+			fc_lport_reset(vn_port);
+		else {
+			mutex_lock(&fip->ctlr_mutex);
+			per_cpu_ptr(lport->dev_stats,
+				    get_cpu())->VLinkFailureCount++;
+			put_cpu();
+			fcoe_ctlr_reset(fip);
+			mutex_unlock(&fip->ctlr_mutex);
+
+			fc_lport_reset(fip->lp);
+			fcoe_ctlr_solicit(fip, NULL);
+		}
+	}
+}
+
+/**
+ * fcoe_ctlr_recv() - Receive a FIP packet
+ * @fip: The FCoE controller that received the packet
+ * @skb: The received FIP packet
+ *
+ * This may be called from either NET_RX_SOFTIRQ or IRQ.
+ */
+void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	skb_queue_tail(&fip->fip_recv_list, skb);
+	schedule_work(&fip->recv_work);
+}
+EXPORT_SYMBOL(fcoe_ctlr_recv);
+
+/**
+ * fcoe_ctlr_recv_handler() - Receive a FIP frame
+ * @fip: The FCoE controller that received the frame
+ * @skb: The received FIP frame
+ *
+ * Returns non-zero if the frame is dropped.
+ */
+static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fip_header *fiph;
+	struct ethhdr *eh;
+	enum fip_state state;
+	u16 op;
+	u8 sub;
+
+	if (skb_linearize(skb))
+		goto drop;
+	if (skb->len < sizeof(*fiph))
+		goto drop;
+	eh = eth_hdr(skb);
+	if (fip->mode == FIP_MODE_VN2VN) {
+		if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
+		    compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) &&
+		    compare_ether_addr(eh->h_dest, fcoe_all_p2p))
+			goto drop;
+	} else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
+		   compare_ether_addr(eh->h_dest, fcoe_all_enode))
+		goto drop;
+	fiph = (struct fip_header *)skb->data;
+	op = ntohs(fiph->fip_op);
+	sub = fiph->fip_subcode;
+
+	if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
+		goto drop;
+	if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
+		goto drop;
+
+	mutex_lock(&fip->ctlr_mutex);
+	state = fip->state;
+	if (state == FIP_ST_AUTO) {
+		fip->map_dest = 0;
+		fcoe_ctlr_set_state(fip, FIP_ST_ENABLED);
+		state = FIP_ST_ENABLED;
+		LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
+	}
+	mutex_unlock(&fip->ctlr_mutex);
+
+	if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
+		return fcoe_ctlr_vn_recv(fip, skb);
+
+	if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
+	    state != FIP_ST_VNMP_CLAIM)
+		goto drop;
+
+	if (op == FIP_OP_LS) {
+		fcoe_ctlr_recv_els(fip, skb);	/* consumes skb */
+		return 0;
+	}
+
+	if (state != FIP_ST_ENABLED)
+		goto drop;
+
+	if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
+		fcoe_ctlr_recv_adv(fip, skb);
+	else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
+		fcoe_ctlr_recv_clr_vlink(fip, fiph);
+	kfree_skb(skb);
+	return 0;
+drop:
+	kfree_skb(skb);
+	return -1;
+}
+
+/**
+ * fcoe_ctlr_select() - Select the best FCF (if possible)
+ * @fip: The FCoE controller
+ *
+ * Returns the selected FCF, or NULL if none are usable.
+ *
+ * If there are conflicting advertisements, no FCF can be chosen.
+ *
+ * If there is already a selected FCF, this will choose a better one or
+ * an equivalent one that hasn't already been sent a FLOGI.
+ *
+ * Called with lock held.
+ */
+static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf *best = fip->sel_fcf;
+	struct fcoe_fcf *first;
+
+	first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
+
+	list_for_each_entry(fcf, &fip->fcfs, list) {
+		LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
+				"VFID %d mac %pM map %x val %d "
+				"sent %u pri %u\n",
+				fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
+				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
+				fcf->flogi_sent, fcf->pri);
+		if (fcf->fabric_name != first->fabric_name ||
+		    fcf->vfid != first->vfid ||
+		    fcf->fc_map != first->fc_map) {
+			LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
+					"or FC-MAP\n");
+			return NULL;
+		}
+		if (fcf->flogi_sent)
+			continue;
+		if (!fcoe_ctlr_fcf_usable(fcf)) {
+			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
+					"map %x %svalid %savailable\n",
+					fcf->fabric_name, fcf->fc_map,
+					(fcf->flags & FIP_FL_SOL) ? "" : "in",
+					(fcf->flags & FIP_FL_AVAIL) ?
+					"" : "un");
+			continue;
+		}
+		if (!best || fcf->pri < best->pri || best->flogi_sent)
+			best = fcf;
+	}
+	fip->sel_fcf = best;
+	if (best) {
+		LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac);
+		fip->port_ka_time = jiffies +
+			msecs_to_jiffies(FIP_VN_KA_PERIOD);
+		fip->ctlr_ka_time = jiffies + best->fka_period;
+		if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+			mod_timer(&fip->timer, fip->ctlr_ka_time);
+	}
+	return best;
+}
+
+/**
+ * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error if it could not be sent.
+ *
+ * Called with ctlr_mutex and ctlr_lock held.
+ * Caller must verify that fip->sel_fcf is not NULL.
+ */
+static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
+{
+	struct sk_buff *skb;
+	struct sk_buff *skb_orig;
+	struct fc_frame_header *fh;
+	int error;
+
+	skb_orig = fip->flogi_req;
+	if (!skb_orig)
+		return -EINVAL;
+
+	/*
+	 * Clone and send the FLOGI request.  If clone fails, use original.
+	 */
+	skb = skb_clone(skb_orig, GFP_ATOMIC);
+	if (!skb) {
+		skb = skb_orig;
+		fip->flogi_req = NULL;
+	}
+	fh = (struct fc_frame_header *)skb->data;
+	error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
+				 ntoh24(fh->fh_d_id));
+	if (error) {
+		kfree_skb(skb);
+		return error;
+	}
+	fip->send(fip, skb);
+	fip->sel_fcf->flogi_sent = 1;
+	return 0;
+}
+
+/**
+ * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error code if there's no FLOGI request to retry or
+ * no alternate FCF available.
+ */
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	int error;
+
+	mutex_lock(&fip->ctlr_mutex);
+	spin_lock_bh(&fip->ctlr_lock);
+	LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
+	fcf = fcoe_ctlr_select(fip);
+	if (!fcf || fcf->flogi_sent) {
+		kfree_skb(fip->flogi_req);
+		fip->flogi_req = NULL;
+		error = -ENOENT;
+	} else {
+		fcoe_ctlr_solicit(fip, NULL);
+		error = fcoe_ctlr_flogi_send_locked(fip);
+	}
+	spin_unlock_bh(&fip->ctlr_lock);
+	mutex_unlock(&fip->ctlr_mutex);
+	return error;
+}
+
+
+/**
+ * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
+ * @fip: The FCoE controller that timed out
+ *
+ * Done here because fcoe_ctlr_els_send() can't get mutex.
+ *
+ * Called with ctlr_mutex held.  The caller must not hold ctlr_lock.
+ */
+static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+
+	spin_lock_bh(&fip->ctlr_lock);
+	fcf = fip->sel_fcf;
+	if (!fcf || !fip->flogi_req_send)
+		goto unlock;
+
+	LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
+
+	/*
+	 * If this FLOGI is being sent due to a timeout retry
+	 * to the same FCF as before, select a different FCF if possible.
+	 */
+	if (fcf->flogi_sent) {
+		LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
+		fcf = fcoe_ctlr_select(fip);
+		if (!fcf || fcf->flogi_sent) {
+			LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
+			list_for_each_entry(fcf, &fip->fcfs, list)
+				fcf->flogi_sent = 0;
+			fcf = fcoe_ctlr_select(fip);
+		}
+	}
+	if (fcf) {
+		fcoe_ctlr_flogi_send_locked(fip);
+		fip->flogi_req_send = 0;
+	} else /* XXX */
+		LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
+unlock:
+	spin_unlock_bh(&fip->ctlr_lock);
+}
+
+/**
+ * fcoe_ctlr_timeout() - FIP timeout handler
+ * @arg: The FCoE controller that timed out
+ */
+static void fcoe_ctlr_timeout(unsigned long arg)
+{
+	struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
+
+	schedule_work(&fip->timer_work);
+}
+
+/**
+ * fcoe_ctlr_timer_work() - Worker thread function for timer work
+ * @work: Handle to a FCoE controller
+ *
+ * Ages FCFs.  Triggers FCF selection if possible.
+ * Sends keep-alives and resets.
+ */
+static void fcoe_ctlr_timer_work(struct work_struct *work)
+{
+	struct fcoe_ctlr *fip;
+	struct fc_lport *vport;
+	u8 *mac;
+	u8 reset = 0;
+	u8 send_ctlr_ka = 0;
+	u8 send_port_ka = 0;
+	struct fcoe_fcf *sel;
+	struct fcoe_fcf *fcf;
+	unsigned long next_timer;
+
+	fip = container_of(work, struct fcoe_ctlr, timer_work);
+	if (fip->mode == FIP_MODE_VN2VN)
+		return fcoe_ctlr_vn_timeout(fip);
+	mutex_lock(&fip->ctlr_mutex);
+	if (fip->state == FIP_ST_DISABLED) {
+		mutex_unlock(&fip->ctlr_mutex);
+		return;
+	}
+
+	fcf = fip->sel_fcf;
+	next_timer = fcoe_ctlr_age_fcfs(fip);
+
+	sel = fip->sel_fcf;
+	if (!sel && fip->sel_time) {
+		if (time_after_eq(jiffies, fip->sel_time)) {
+			sel = fcoe_ctlr_select(fip);
+			fip->sel_time = 0;
+		} else if (time_after(next_timer, fip->sel_time))
+			next_timer = fip->sel_time;
+	}
+
+	if (sel && fip->flogi_req_send)
+		fcoe_ctlr_flogi_send(fip);
+	else if (!sel && fcf)
+		reset = 1;
+
+	if (sel && !sel->fd_flags) {
+		if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
+			fip->ctlr_ka_time = jiffies + sel->fka_period;
+			send_ctlr_ka = 1;
+		}
+		if (time_after(next_timer, fip->ctlr_ka_time))
+			next_timer = fip->ctlr_ka_time;
+
+		if (time_after_eq(jiffies, fip->port_ka_time)) {
+			fip->port_ka_time = jiffies +
+				msecs_to_jiffies(FIP_VN_KA_PERIOD);
+			send_port_ka = 1;
+		}
+		if (time_after(next_timer, fip->port_ka_time))
+			next_timer = fip->port_ka_time;
+	}
+	if (!list_empty(&fip->fcfs))
+		mod_timer(&fip->timer, next_timer);
+	mutex_unlock(&fip->ctlr_mutex);
+
+	if (reset) {
+		fc_lport_reset(fip->lp);
+		/* restart things with a solicitation */
+		fcoe_ctlr_solicit(fip, NULL);
+	}
+
+	if (send_ctlr_ka)
+		fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr);
+
+	if (send_port_ka) {
+		mutex_lock(&fip->lp->lp_mutex);
+		mac = fip->get_src_addr(fip->lp);
+		fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac);
+		list_for_each_entry(vport, &fip->lp->vports, list) {
+			mac = fip->get_src_addr(vport);
+			fcoe_ctlr_send_keep_alive(fip, vport, 1, mac);
+		}
+		mutex_unlock(&fip->lp->lp_mutex);
+	}
+}
+
+/**
+ * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames
+ * @recv_work: Handle to a FCoE controller
+ */
+static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
+{
+	struct fcoe_ctlr *fip;
+	struct sk_buff *skb;
+
+	fip = container_of(recv_work, struct fcoe_ctlr, recv_work);
+	while ((skb = skb_dequeue(&fip->fip_recv_list)))
+		fcoe_ctlr_recv_handler(fip, skb);
+}
+
+/**
+ * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response
+ * @fip: The FCoE controller
+ * @fp:	 The FC frame to snoop
+ *
+ * Snoop potential response to FLOGI or even incoming FLOGI.
+ *
+ * The caller has checked that we are waiting for login as indicated
+ * by fip->flogi_oxid != FC_XID_UNKNOWN.
+ *
+ * The caller is responsible for freeing the frame.
+ * Fill in the granted_mac address.
+ *
+ * Return non-zero if the frame should not be delivered to libfc.
+ */
+int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport,
+			 struct fc_frame *fp)
+{
+	struct fc_frame_header *fh;
+	u8 op;
+	u8 *sa;
+
+	sa = eth_hdr(&fp->skb)->h_source;
+	fh = fc_frame_header_get(fp);
+	if (fh->fh_type != FC_TYPE_ELS)
+		return 0;
+
+	op = fc_frame_payload_op(fp);
+	if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
+	    fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+
+		mutex_lock(&fip->ctlr_mutex);
+		if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) {
+			mutex_unlock(&fip->ctlr_mutex);
+			return -EINVAL;
+		}
+		fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
+		LIBFCOE_FIP_DBG(fip,
+				"received FLOGI LS_ACC using non-FIP mode\n");
+
+		/*
+		 * FLOGI accepted.
+		 * If the src mac addr is FC_OUI-based, then we mark the
+		 * address_mode flag to use FC_OUI-based Ethernet DA.
+		 * Otherwise we use the FCoE gateway addr
+		 */
+		if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) {
+			fcoe_ctlr_map_dest(fip);
+		} else {
+			memcpy(fip->dest_addr, sa, ETH_ALEN);
+			fip->map_dest = 0;
+		}
+		fip->flogi_oxid = FC_XID_UNKNOWN;
+		mutex_unlock(&fip->ctlr_mutex);
+		fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id);
+	} else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
+		/*
+		 * Save source MAC for point-to-point responses.
+		 */
+		mutex_lock(&fip->ctlr_mutex);
+		if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
+			memcpy(fip->dest_addr, sa, ETH_ALEN);
+			fip->map_dest = 0;
+			if (fip->state == FIP_ST_AUTO)
+				LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. "
+						"Setting non-FIP mode\n");
+			fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
+		}
+		mutex_unlock(&fip->ctlr_mutex);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(fcoe_ctlr_recv_flogi);
+
+/**
+ * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN
+ * @mac:    The MAC address to convert
+ * @scheme: The scheme to use when converting
+ * @port:   The port indicator for converting
+ *
+ * Returns: u64 fc world wide name
+ */
+u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
+		      unsigned int scheme, unsigned int port)
+{
+	u64 wwn;
+	u64 host_mac;
+
+	/* The MAC is in NO, so flip only the low 48 bits */
+	host_mac = ((u64) mac[0] << 40) |
+		((u64) mac[1] << 32) |
+		((u64) mac[2] << 24) |
+		((u64) mac[3] << 16) |
+		((u64) mac[4] << 8) |
+		(u64) mac[5];
+
+	WARN_ON(host_mac >= (1ULL << 48));
+	wwn = host_mac | ((u64) scheme << 60);
+	switch (scheme) {
+	case 1:
+		WARN_ON(port != 0);
+		break;
+	case 2:
+		WARN_ON(port >= 0xfff);
+		wwn |= (u64) port << 48;
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+
+	return wwn;
+}
+EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
+
+/**
+ * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv
+ * @rdata: libfc remote port
+ */
+static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
+{
+	return (struct fcoe_rport *)(rdata + 1);
+}
+
+/**
+ * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply.
+ * @fip: The FCoE controller
+ * @sub: sub-opcode for probe request, reply, or advertisement.
+ * @dest: The destination Ethernet MAC address
+ * @min_len: minimum size of the Ethernet payload to be sent
+ */
+static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
+			      enum fip_vn2vn_subcode sub,
+			      const u8 *dest, size_t min_len)
+{
+	struct sk_buff *skb;
+	struct fip_frame {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct fip_mac_desc mac;
+		struct fip_wwn_desc wwnn;
+		struct fip_vn_desc vn;
+	} __packed * frame;
+	struct fip_fc4_feat *ff;
+	struct fip_size_desc *size;
+	u32 fcp_feat;
+	size_t len;
+	size_t dlen;
+
+	len = sizeof(*frame);
+	dlen = 0;
+	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
+		dlen = sizeof(struct fip_fc4_feat) +
+		       sizeof(struct fip_size_desc);
+		len += dlen;
+	}
+	dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn);
+	len = max(len, min_len + sizeof(struct ethhdr));
+
+	skb = dev_alloc_skb(len);
+	if (!skb)
+		return;
+
+	frame = (struct fip_frame *)skb->data;
+	memset(frame, 0, len);
+	memcpy(frame->eth.h_dest, dest, ETH_ALEN);
+	memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+	frame->eth.h_proto = htons(ETH_P_FIP);
+
+	frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	frame->fip.fip_op = htons(FIP_OP_VN2VN);
+	frame->fip.fip_subcode = sub;
+	frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
+
+	frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
+	frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
+	memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+	frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+	frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW;
+	put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn);
+
+	frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID;
+	frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW;
+	hton24(frame->vn.fd_mac, FIP_VN_FC_MAP);
+	hton24(frame->vn.fd_mac + 3, fip->port_id);
+	hton24(frame->vn.fd_fc_id, fip->port_id);
+	put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn);
+
+	/*
+	 * For claims, add FC-4 features.
+	 * TBD: Add interface to get fc-4 types and features from libfc.
+	 */
+	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
+		ff = (struct fip_fc4_feat *)(frame + 1);
+		ff->fd_desc.fip_dtype = FIP_DT_FC4F;
+		ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW;
+		ff->fd_fts = fip->lp->fcts;
+
+		fcp_feat = 0;
+		if (fip->lp->service_params & FCP_SPPF_INIT_FCN)
+			fcp_feat |= FCP_FEAT_INIT;
+		if (fip->lp->service_params & FCP_SPPF_TARG_FCN)
+			fcp_feat |= FCP_FEAT_TARG;
+		fcp_feat <<= (FC_TYPE_FCP * 4) % 32;
+		ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat);
+
+		size = (struct fip_size_desc *)(ff + 1);
+		size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
+		size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW;
+		size->fd_size = htons(fcoe_ctlr_fcoe_size(fip));
+	}
+
+	skb_put(skb, len);
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+
+	fip->send(fip, skb);
+}
+
+/**
+ * fcoe_ctlr_vn_rport_callback - Event handler for rport events.
+ * @lport: The lport which is receiving the event
+ * @rdata: remote port private data
+ * @event: The event that occured
+ *
+ * Locking Note:  The rport lock must not be held when calling this function.
+ */
+static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport,
+					struct fc_rport_priv *rdata,
+					enum fc_rport_event event)
+{
+	struct fcoe_ctlr *fip = lport->disc.priv;
+	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
+
+	LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n",
+			rdata->ids.port_id, event);
+
+	mutex_lock(&fip->ctlr_mutex);
+	switch (event) {
+	case RPORT_EV_READY:
+		frport->login_count = 0;
+		break;
+	case RPORT_EV_LOGO:
+	case RPORT_EV_FAILED:
+	case RPORT_EV_STOP:
+		frport->login_count++;
+		if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) {
+			LIBFCOE_FIP_DBG(fip,
+					"rport FLOGI limited port_id %6.6x\n",
+					rdata->ids.port_id);
+			lport->tt.rport_logoff(rdata);
+		}
+		break;
+	default:
+		break;
+	}
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = {
+	.event_callback = fcoe_ctlr_vn_rport_callback,
+};
+
+/**
+ * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
+{
+	mutex_lock(&lport->disc.disc_mutex);
+	lport->disc.disc_callback = NULL;
+	mutex_unlock(&lport->disc.disc_mutex);
+}
+
+/**
+ * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called through the local port template for discovery.
+ * Called without the ctlr_mutex held.
+ */
+static void fcoe_ctlr_disc_stop(struct fc_lport *lport)
+{
+	struct fcoe_ctlr *fip = lport->disc.priv;
+
+	mutex_lock(&fip->ctlr_mutex);
+	fcoe_ctlr_disc_stop_locked(lport);
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
+ * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called through the local port template for discovery.
+ * Called without the ctlr_mutex held.
+ */
+static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport)
+{
+	fcoe_ctlr_disc_stop(lport);
+	lport->tt.rport_flush_queue();
+	synchronize_rcu();
+}
+
+/**
+ * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id
+ * @fip: The FCoE controller
+ *
+ * Called with fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
+{
+	unsigned long wait;
+	u32 port_id;
+
+	fcoe_ctlr_disc_stop_locked(fip->lp);
+
+	/*
+	 * Get proposed port ID.
+	 * If this is the first try after link up, use any previous port_id.
+	 * If there was none, use the low bits of the port_name.
+	 * On subsequent tries, get the next random one.
+	 * Don't use reserved IDs, use another non-zero value, just as random.
+	 */
+	port_id = fip->port_id;
+	if (fip->probe_tries)
+		port_id = prandom32(&fip->rnd_state) & 0xffff;
+	else if (!port_id)
+		port_id = fip->lp->wwpn & 0xffff;
+	if (!port_id || port_id == 0xffff)
+		port_id = 1;
+	fip->port_id = port_id;
+
+	if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
+		fip->probe_tries++;
+		wait = random32() % FIP_VN_PROBE_WAIT;
+	} else
+		wait = FIP_VN_RLIM_INT;
+	mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
+	fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START);
+}
+
+/**
+ * fcoe_ctlr_vn_start() - Start in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called with fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
+{
+	fip->probe_tries = 0;
+	prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
+	fcoe_ctlr_vn_restart(fip);
+}
+
+/**
+ * fcoe_ctlr_vn_parse - parse probe request or response
+ * @fip: The FCoE controller
+ * @skb: incoming packet
+ * @rdata: buffer for resulting parsed VN entry plus fcoe_rport
+ *
+ * Returns non-zero error number on error.
+ * Does not consume the packet.
+ */
+static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
+			      struct sk_buff *skb,
+			      struct fc_rport_priv *rdata)
+{
+	struct fip_header *fiph;
+	struct fip_desc *desc = NULL;
+	struct fip_mac_desc *macd = NULL;
+	struct fip_wwn_desc *wwn = NULL;
+	struct fip_vn_desc *vn = NULL;
+	struct fip_size_desc *size = NULL;
+	struct fcoe_rport *frport;
+	size_t rlen;
+	size_t dlen;
+	u32 desc_mask = 0;
+	u32 dtype;
+	u8 sub;
+
+	memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
+	frport = fcoe_ctlr_rport(rdata);
+
+	fiph = (struct fip_header *)skb->data;
+	frport->flags = ntohs(fiph->fip_flags);
+
+	sub = fiph->fip_subcode;
+	switch (sub) {
+	case FIP_SC_VN_PROBE_REQ:
+	case FIP_SC_VN_PROBE_REP:
+	case FIP_SC_VN_BEACON:
+		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
+			    BIT(FIP_DT_VN_ID);
+		break;
+	case FIP_SC_VN_CLAIM_NOTIFY:
+	case FIP_SC_VN_CLAIM_REP:
+		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
+			    BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) |
+			    BIT(FIP_DT_FCOE_SIZE);
+		break;
+	default:
+		LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
+		return -EINVAL;
+	}
+
+	rlen = ntohs(fiph->fip_dl_len) * 4;
+	if (rlen + sizeof(*fiph) > skb->len)
+		return -EINVAL;
+
+	desc = (struct fip_desc *)(fiph + 1);
+	while (rlen > 0) {
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen < sizeof(*desc) || dlen > rlen)
+			return -EINVAL;
+
+		dtype = desc->fip_dtype;
+		if (dtype < 32) {
+			if (!(desc_mask & BIT(dtype))) {
+				LIBFCOE_FIP_DBG(fip,
+						"unexpected or duplicated desc "
+						"desc type %u in "
+						"FIP VN2VN subtype %u\n",
+						dtype, sub);
+				return -EINVAL;
+			}
+			desc_mask &= ~BIT(dtype);
+		}
+
+		switch (dtype) {
+		case FIP_DT_MAC:
+			if (dlen != sizeof(struct fip_mac_desc))
+				goto len_err;
+			macd = (struct fip_mac_desc *)desc;
+			if (!is_valid_ether_addr(macd->fd_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC addr %pM in FIP VN2VN\n",
+					 macd->fd_mac);
+				return -EINVAL;
+			}
+			memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
+			break;
+		case FIP_DT_NAME:
+			if (dlen != sizeof(struct fip_wwn_desc))
+				goto len_err;
+			wwn = (struct fip_wwn_desc *)desc;
+			rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+			break;
+		case FIP_DT_VN_ID:
+			if (dlen != sizeof(struct fip_vn_desc))
+				goto len_err;
+			vn = (struct fip_vn_desc *)desc;
+			memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
+			rdata->ids.port_id = ntoh24(vn->fd_fc_id);
+			rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
+			break;
+		case FIP_DT_FC4F:
+			if (dlen != sizeof(struct fip_fc4_feat))
+				goto len_err;
+			break;
+		case FIP_DT_FCOE_SIZE:
+			if (dlen != sizeof(struct fip_size_desc))
+				goto len_err;
+			size = (struct fip_size_desc *)desc;
+			frport->fcoe_len = ntohs(size->fd_size);
+			break;
+		default:
+			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+					"in FIP probe\n", dtype);
+			/* standard says ignore unknown descriptors >= 128 */
+			if (dtype < FIP_DT_VENDOR_BASE)
+				return -EINVAL;
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+	return 0;
+
+len_err:
+	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
+			dtype, dlen);
+	return -EINVAL;
+}
+
+/**
+ * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification.
+ * @fip: The FCoE controller
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
+{
+	fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0);
+	fip->sol_time = jiffies;
+}
+
+/**
+ * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
+ * @fip: The FCoE controller
+ * @rdata: parsed remote port with frport from the probe request
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
+				   struct fc_rport_priv *rdata)
+{
+	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
+
+	if (rdata->ids.port_id != fip->port_id)
+		return;
+
+	switch (fip->state) {
+	case FIP_ST_VNMP_CLAIM:
+	case FIP_ST_VNMP_UP:
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
+				  frport->enode_mac, 0);
+		break;
+	case FIP_ST_VNMP_PROBE1:
+	case FIP_ST_VNMP_PROBE2:
+		/*
+		 * Decide whether to reply to the Probe.
+		 * Our selected address is never a "recorded" one, so
+		 * only reply if our WWPN is greater and the
+		 * Probe's REC bit is not set.
+		 * If we don't reply, we will change our address.
+		 */
+		if (fip->lp->wwpn > rdata->ids.port_name &&
+		    !(frport->flags & FIP_FL_REC_OR_P2P)) {
+			fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
+					  frport->enode_mac, 0);
+			break;
+		}
+		/* fall through */
+	case FIP_ST_VNMP_START:
+		fcoe_ctlr_vn_restart(fip);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
+ * @fip: The FCoE controller
+ * @rdata: parsed remote port with frport from the probe request
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
+				   struct fc_rport_priv *rdata)
+{
+	if (rdata->ids.port_id != fip->port_id)
+		return;
+	switch (fip->state) {
+	case FIP_ST_VNMP_START:
+	case FIP_ST_VNMP_PROBE1:
+	case FIP_ST_VNMP_PROBE2:
+	case FIP_ST_VNMP_CLAIM:
+		fcoe_ctlr_vn_restart(fip);
+		break;
+	case FIP_ST_VNMP_UP:
+		fcoe_ctlr_vn_send_claim(fip);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
+ * @fip: The FCoE controller
+ * @new: newly-parsed remote port with frport as a template for new rdata
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fc_rport_identifiers *ids;
+	struct fcoe_rport *frport;
+	u32 port_id;
+
+	port_id = new->ids.port_id;
+	if (port_id == fip->port_id)
+		return;
+
+	mutex_lock(&lport->disc.disc_mutex);
+	rdata = lport->tt.rport_create(lport, port_id);
+	if (!rdata) {
+		mutex_unlock(&lport->disc.disc_mutex);
+		return;
+	}
+
+	rdata->ops = &fcoe_ctlr_vn_rport_ops;
+	rdata->disc_id = lport->disc.disc_id;
+
+	ids = &rdata->ids;
+	if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
+	    (ids->node_name != -1 && ids->node_name != new->ids.node_name))
+		lport->tt.rport_logoff(rdata);
+	ids->port_name = new->ids.port_name;
+	ids->node_name = new->ids.node_name;
+	mutex_unlock(&lport->disc.disc_mutex);
+
+	frport = fcoe_ctlr_rport(rdata);
+	LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
+			port_id, frport->fcoe_len ? "old" : "new");
+	*frport = *fcoe_ctlr_rport(new);
+	frport->time = 0;
+}
+
+/**
+ * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address
+ * @fip: The FCoE controller
+ * @port_id:  The port_id of the remote VN_node
+ * @mac: buffer which will hold the VN_NODE destination MAC address, if found.
+ *
+ * Returns non-zero error if no remote port found.
+ */
+static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+	int ret = -1;
+
+	rcu_read_lock();
+	rdata = lport->tt.rport_lookup(lport, port_id);
+	if (rdata) {
+		frport = fcoe_ctlr_rport(rdata);
+		memcpy(mac, frport->enode_mac, ETH_ALEN);
+		ret = 0;
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
+/**
+ * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
+ * @fip: The FCoE controller
+ * @new: newly-parsed remote port with frport as a template for new rdata
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
+				      struct fc_rport_priv *new)
+{
+	struct fcoe_rport *frport = fcoe_ctlr_rport(new);
+
+	if (frport->flags & FIP_FL_REC_OR_P2P) {
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		return;
+	}
+	switch (fip->state) {
+	case FIP_ST_VNMP_START:
+	case FIP_ST_VNMP_PROBE1:
+	case FIP_ST_VNMP_PROBE2:
+		if (new->ids.port_id == fip->port_id)
+			fcoe_ctlr_vn_restart(fip);
+		break;
+	case FIP_ST_VNMP_CLAIM:
+	case FIP_ST_VNMP_UP:
+		if (new->ids.port_id == fip->port_id) {
+			if (new->ids.port_name > fip->lp->wwpn) {
+				fcoe_ctlr_vn_restart(fip);
+				break;
+			}
+			fcoe_ctlr_vn_send_claim(fip);
+			break;
+		}
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
+				  min((u32)frport->fcoe_len,
+				      fcoe_ctlr_fcoe_size(fip)));
+		fcoe_ctlr_vn_add(fip, new);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * fcoe_ctlr_vn_claim_resp() - handle received Claim Response
+ * @fip: The FCoE controller that received the frame
+ * @new: newly-parsed remote port with frport from the Claim Response
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
+				    struct fc_rport_priv *new)
+{
+	LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
+			new->ids.port_id, fcoe_ctlr_state(fip->state));
+	if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
+		fcoe_ctlr_vn_add(fip, new);
+}
+
+/**
+ * fcoe_ctlr_vn_beacon() - handle received beacon.
+ * @fip: The FCoE controller that received the frame
+ * @new: newly-parsed remote port with frport from the Beacon
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
+				struct fc_rport_priv *new)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+
+	frport = fcoe_ctlr_rport(new);
+	if (frport->flags & FIP_FL_REC_OR_P2P) {
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		return;
+	}
+	mutex_lock(&lport->disc.disc_mutex);
+	rdata = lport->tt.rport_lookup(lport, new->ids.port_id);
+	if (rdata)
+		kref_get(&rdata->kref);
+	mutex_unlock(&lport->disc.disc_mutex);
+	if (rdata) {
+		if (rdata->ids.node_name == new->ids.node_name &&
+		    rdata->ids.port_name == new->ids.port_name) {
+			frport = fcoe_ctlr_rport(rdata);
+			if (!frport->time && fip->state == FIP_ST_VNMP_UP)
+				lport->tt.rport_login(rdata);
+			frport->time = jiffies;
+		}
+		kref_put(&rdata->kref, lport->tt.rport_destroy);
+		return;
+	}
+	if (fip->state != FIP_ST_VNMP_UP)
+		return;
+
+	/*
+	 * Beacon from a new neighbor.
+	 * Send a claim notify if one hasn't been sent recently.
+	 * Don't add the neighbor yet.
+	 */
+	LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
+			new->ids.port_id);
+	if (time_after(jiffies,
+		       fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
+		fcoe_ctlr_vn_send_claim(fip);
+}
+
+/**
+ * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons
+ * @fip: The FCoE controller
+ *
+ * Called with ctlr_mutex held.
+ * Called only in state FIP_ST_VNMP_UP.
+ * Returns the soonest time for next age-out or a time far in the future.
+ */
+static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+	unsigned long next_time;
+	unsigned long deadline;
+
+	next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
+	mutex_lock(&lport->disc.disc_mutex);
+	list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
+		frport = fcoe_ctlr_rport(rdata);
+		if (!frport->time)
+			continue;
+		deadline = frport->time +
+			   msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
+		if (time_after_eq(jiffies, deadline)) {
+			frport->time = 0;
+			LIBFCOE_FIP_DBG(fip,
+				"port %16.16llx fc_id %6.6x beacon expired\n",
+				rdata->ids.port_name, rdata->ids.port_id);
+			lport->tt.rport_logoff(rdata);
+		} else if (time_before(deadline, next_time))
+			next_time = deadline;
+	}
+	mutex_unlock(&lport->disc.disc_mutex);
+	return next_time;
+}
+
+/**
+ * fcoe_ctlr_vn_recv() - Receive a FIP frame
+ * @fip: The FCoE controller that received the frame
+ * @skb: The received FIP frame
+ *
+ * Returns non-zero if the frame is dropped.
+ * Always consumes the frame.
+ */
+static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fip_header *fiph;
+	enum fip_vn2vn_subcode sub;
+	struct {
+		struct fc_rport_priv rdata;
+		struct fcoe_rport frport;
+	} buf;
+	int rc;
+
+	fiph = (struct fip_header *)skb->data;
+	sub = fiph->fip_subcode;
+
+	rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
+	if (rc) {
+		LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
+		goto drop;
+	}
+
+	mutex_lock(&fip->ctlr_mutex);
+	switch (sub) {
+	case FIP_SC_VN_PROBE_REQ:
+		fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_PROBE_REP:
+		fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_CLAIM_NOTIFY:
+		fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_CLAIM_REP:
+		fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_BEACON:
+		fcoe_ctlr_vn_beacon(fip, &buf.rdata);
+		break;
+	default:
+		LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
+		rc = -1;
+		break;
+	}
+	mutex_unlock(&fip->ctlr_mutex);
+drop:
+	kfree_skb(skb);
+	return rc;
+}
+
+/**
+ * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
+ * @lport: The local port
+ * @fp: The received frame
+ *
+ * This should never be called since we don't see RSCNs or other
+ * fabric-generated ELSes.
+ */
+static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp)
+{
+	struct fc_seq_els_data rjt_data;
+
+	rjt_data.reason = ELS_RJT_UNSUP;
+	rjt_data.explan = ELS_EXPL_NONE;
+	lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
+	fc_frame_free(fp);
+}
+
+/**
+ * fcoe_ctlr_disc_recv - start discovery for VN2VN mode.
+ * @fip: The FCoE controller
+ *
+ * This sets a flag indicating that remote ports should be created
+ * and started for the peers we discover.  We use the disc_callback
+ * pointer as that flag.  Peers already discovered are created here.
+ *
+ * The lport lock is held during this call. The callback must be done
+ * later, without holding either the lport or discovery locks.
+ * The fcoe_ctlr lock may also be held during this call.
+ */
+static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *,
+						  enum fc_disc_event),
+				 struct fc_lport *lport)
+{
+	struct fc_disc *disc = &lport->disc;
+	struct fcoe_ctlr *fip = disc->priv;
+
+	mutex_lock(&disc->disc_mutex);
+	disc->disc_callback = callback;
+	disc->disc_id = (disc->disc_id + 2) | 1;
+	disc->pending = 1;
+	schedule_work(&fip->timer_work);
+	mutex_unlock(&disc->disc_mutex);
+}
+
+/**
+ * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state.
+ * @fip: The FCoE controller
+ *
+ * Starts the FLOGI and PLOGI login process to each discovered rport for which
+ * we've received at least one beacon.
+ * Performs the discovery complete callback.
+ */
+static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_disc *disc = &lport->disc;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+	void (*callback)(struct fc_lport *, enum fc_disc_event);
+
+	mutex_lock(&disc->disc_mutex);
+	callback = disc->pending ? disc->disc_callback : NULL;
+	disc->pending = 0;
+	list_for_each_entry_rcu(rdata, &disc->rports, peers) {
+		frport = fcoe_ctlr_rport(rdata);
+		if (frport->time)
+			lport->tt.rport_login(rdata);
+	}
+	mutex_unlock(&disc->disc_mutex);
+	if (callback)
+		callback(lport, DISC_EV_SUCCESS);
+}
+
+/**
+ * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode.
+ * @fip: The FCoE controller
+ */
+static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
+{
+	unsigned long next_time;
+	u8 mac[ETH_ALEN];
+	u32 new_port_id = 0;
+
+	mutex_lock(&fip->ctlr_mutex);
+	switch (fip->state) {
+	case FIP_ST_VNMP_START:
+		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
+		break;
+	case FIP_ST_VNMP_PROBE1:
+		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+		break;
+	case FIP_ST_VNMP_PROBE2:
+		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM);
+		new_port_id = fip->port_id;
+		hton24(mac, FIP_VN_FC_MAP);
+		hton24(mac + 3, new_port_id);
+		fcoe_ctlr_map_dest(fip);
+		fip->update_mac(fip->lp, mac);
+		fcoe_ctlr_vn_send_claim(fip);
+		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+		break;
+	case FIP_ST_VNMP_CLAIM:
+		/*
+		 * This may be invoked either by starting discovery so don't
+		 * go to the next state unless it's been long enough.
+		 */
+		next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+		if (time_after_eq(jiffies, next_time)) {
+			fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
+			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
+					  fcoe_all_vn2vn, 0);
+			next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+			fip->port_ka_time = next_time;
+		}
+		fcoe_ctlr_vn_disc(fip);
+		break;
+	case FIP_ST_VNMP_UP:
+		next_time = fcoe_ctlr_vn_age(fip);
+		if (time_after_eq(jiffies, fip->port_ka_time)) {
+			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
+					  fcoe_all_vn2vn, 0);
+			fip->port_ka_time = jiffies +
+				 msecs_to_jiffies(FIP_VN_BEACON_INT +
+					(random32() % FIP_VN_BEACON_FUZZ));
+		}
+		if (time_before(fip->port_ka_time, next_time))
+			next_time = fip->port_ka_time;
+		break;
+	case FIP_ST_LINK_WAIT:
+		goto unlock;
+	default:
+		WARN(1, "unexpected state %d\n", fip->state);
+		goto unlock;
+	}
+	mod_timer(&fip->timer, next_time);
+unlock:
+	mutex_unlock(&fip->ctlr_mutex);
+
+	/* If port ID is new, notify local port after dropping ctlr_mutex */
+	if (new_port_id)
+		fc_lport_set_local_id(fip->lp, new_port_id);
+}
+
+/**
+ * fcoe_libfc_config() - Sets up libfc related properties for local port
+ * @lp: The local port to configure libfc for
+ * @fip: The FCoE controller in use by the local port
+ * @tt: The libfc function template
+ * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
+ *
+ * Returns : 0 for success
+ */
+int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
+		      const struct libfc_function_template *tt, int init_fcp)
+{
+	/* Set the function pointers set by the LLDD */
+	memcpy(&lport->tt, tt, sizeof(*tt));
+	if (init_fcp && fc_fcp_init(lport))
+		return -ENOMEM;
+	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);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_libfc_config);
diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
new file mode 100644
index 0000000..2586841
--- /dev/null
+++ b/drivers/scsi/fcoe/fcoe_transport.c
@@ -0,0 +1,770 @@
+/*
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms 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.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/errno.h>
+#include <linux/crc32.h>
+#include <scsi/libfcoe.h>
+
+#include "libfcoe.h"
+
+MODULE_AUTHOR("Open-FCoE.org");
+MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
+MODULE_LICENSE("GPL v2");
+
+static int fcoe_transport_create(const char *, struct kernel_param *);
+static int fcoe_transport_destroy(const char *, struct kernel_param *);
+static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
+static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
+static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
+static int fcoe_transport_enable(const char *, struct kernel_param *);
+static int fcoe_transport_disable(const char *, struct kernel_param *);
+static int libfcoe_device_notification(struct notifier_block *notifier,
+				    ulong event, void *ptr);
+
+static LIST_HEAD(fcoe_transports);
+static DEFINE_MUTEX(ft_mutex);
+static LIST_HEAD(fcoe_netdevs);
+static DEFINE_MUTEX(fn_mutex);
+
+unsigned int libfcoe_debug_logging;
+module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+
+module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
+__MODULE_PARM_TYPE(show, "string");
+MODULE_PARM_DESC(show, " Show attached FCoE transports");
+
+module_param_call(create, fcoe_transport_create, NULL,
+		  (void *)FIP_MODE_FABRIC, S_IWUSR);
+__MODULE_PARM_TYPE(create, "string");
+MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
+
+module_param_call(create_vn2vn, fcoe_transport_create, NULL,
+		  (void *)FIP_MODE_VN2VN, S_IWUSR);
+__MODULE_PARM_TYPE(create_vn2vn, "string");
+MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
+		 "on an Ethernet interface");
+
+module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(destroy, "string");
+MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
+
+module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(enable, "string");
+MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
+
+module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(disable, "string");
+MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
+
+/* notification function for packets from net device */
+static struct notifier_block libfcoe_notifier = {
+	.notifier_call = libfcoe_device_notification,
+};
+
+/**
+ * fcoe_fc_crc() - Calculates the CRC for a given frame
+ * @fp: The frame to be checksumed
+ *
+ * This uses crc32() routine to calculate the CRC for a frame
+ *
+ * Return: The 32 bit CRC value
+ */
+u32 fcoe_fc_crc(struct fc_frame *fp)
+{
+	struct sk_buff *skb = fp_skb(fp);
+	struct skb_frag_struct *frag;
+	unsigned char *data;
+	unsigned long off, len, clen;
+	u32 crc;
+	unsigned i;
+
+	crc = crc32(~0, skb->data, skb_headlen(skb));
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		frag = &skb_shinfo(skb)->frags[i];
+		off = frag->page_offset;
+		len = frag->size;
+		while (len > 0) {
+			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
+			data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
+					   KM_SKB_DATA_SOFTIRQ);
+			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
+			kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
+			off += clen;
+			len -= clen;
+		}
+	}
+	return crc;
+}
+EXPORT_SYMBOL_GPL(fcoe_fc_crc);
+
+/**
+ * fcoe_start_io() - Start FCoE I/O
+ * @skb: The packet to be transmitted
+ *
+ * This routine is called from the net device to start transmitting
+ * FCoE packets.
+ *
+ * Returns: 0 for success
+ */
+int fcoe_start_io(struct sk_buff *skb)
+{
+	struct sk_buff *nskb;
+	int rc;
+
+	nskb = skb_clone(skb, GFP_ATOMIC);
+	if (!nskb)
+		return -ENOMEM;
+	rc = dev_queue_xmit(nskb);
+	if (rc != 0)
+		return rc;
+	kfree_skb(skb);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_start_io);
+
+
+/**
+ * fcoe_clean_pending_queue() - Dequeue a skb and free it
+ * @lport: The local port to dequeue a skb on
+ */
+void fcoe_clean_pending_queue(struct fc_lport *lport)
+{
+	struct fcoe_port  *port = lport_priv(lport);
+	struct sk_buff *skb;
+
+	spin_lock_bh(&port->fcoe_pending_queue.lock);
+	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
+		spin_unlock_bh(&port->fcoe_pending_queue.lock);
+		kfree_skb(skb);
+		spin_lock_bh(&port->fcoe_pending_queue.lock);
+	}
+	spin_unlock_bh(&port->fcoe_pending_queue.lock);
+}
+EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
+
+/**
+ * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
+ * @lport: The local port whose backlog is to be cleared
+ *
+ * This empties the wait_queue, dequeues the head of the wait_queue queue
+ * and calls fcoe_start_io() for each packet. If all skb have been
+ * transmitted it returns the qlen. If an error occurs it restores
+ * wait_queue (to try again later) and returns -1.
+ *
+ * The wait_queue is used when the skb transmit fails. The failed skb
+ * will go in the wait_queue which will be emptied by the timer function or
+ * by the next skb transmit.
+ */
+void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	int rc;
+
+	spin_lock_bh(&port->fcoe_pending_queue.lock);
+
+	if (skb)
+		__skb_queue_tail(&port->fcoe_pending_queue, skb);
+
+	if (port->fcoe_pending_queue_active)
+		goto out;
+	port->fcoe_pending_queue_active = 1;
+
+	while (port->fcoe_pending_queue.qlen) {
+		/* keep qlen > 0 until fcoe_start_io succeeds */
+		port->fcoe_pending_queue.qlen++;
+		skb = __skb_dequeue(&port->fcoe_pending_queue);
+
+		spin_unlock_bh(&port->fcoe_pending_queue.lock);
+		rc = fcoe_start_io(skb);
+		spin_lock_bh(&port->fcoe_pending_queue.lock);
+
+		if (rc) {
+			__skb_queue_head(&port->fcoe_pending_queue, skb);
+			/* undo temporary increment above */
+			port->fcoe_pending_queue.qlen--;
+			break;
+		}
+		/* undo temporary increment above */
+		port->fcoe_pending_queue.qlen--;
+	}
+
+	if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
+		lport->qfull = 0;
+	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
+		mod_timer(&port->timer, jiffies + 2);
+	port->fcoe_pending_queue_active = 0;
+out:
+	if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
+		lport->qfull = 1;
+	spin_unlock_bh(&port->fcoe_pending_queue.lock);
+}
+EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
+
+/**
+ * fcoe_queue_timer() - The fcoe queue timer
+ * @lport: The local port
+ *
+ * Calls fcoe_check_wait_queue on timeout
+ */
+void fcoe_queue_timer(ulong lport)
+{
+	fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
+}
+EXPORT_SYMBOL_GPL(fcoe_queue_timer);
+
+/**
+ * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
+ * @skb:  The packet to be transmitted
+ * @tlen: The total length of the trailer
+ * @fps:  The fcoe context
+ *
+ * This routine allocates a page for frame trailers. The page is re-used if
+ * there is enough room left on it for the current trailer. If there isn't
+ * enough buffer left a new page is allocated for the trailer. Reference to
+ * the page from this function as well as the skbs using the page fragments
+ * ensure that the page is freed at the appropriate time.
+ *
+ * Returns: 0 for success
+ */
+int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
+			   struct fcoe_percpu_s *fps)
+{
+	struct page *page;
+
+	page = fps->crc_eof_page;
+	if (!page) {
+		page = alloc_page(GFP_ATOMIC);
+		if (!page)
+			return -ENOMEM;
+
+		fps->crc_eof_page = page;
+		fps->crc_eof_offset = 0;
+	}
+
+	get_page(page);
+	skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
+			   fps->crc_eof_offset, tlen);
+	skb->len += tlen;
+	skb->data_len += tlen;
+	skb->truesize += tlen;
+	fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
+
+	if (fps->crc_eof_offset >= PAGE_SIZE) {
+		fps->crc_eof_page = NULL;
+		fps->crc_eof_offset = 0;
+		put_page(page);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
+
+/**
+ * fcoe_transport_lookup - find an fcoe transport that matches a netdev
+ * @netdev: The netdev to look for from all attached transports
+ *
+ * Returns : ptr to the fcoe transport that supports this netdev or NULL
+ * if not found.
+ *
+ * The ft_mutex should be held when this is called
+ */
+static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
+{
+	struct fcoe_transport *ft = NULL;
+
+	list_for_each_entry(ft, &fcoe_transports, list)
+		if (ft->match && ft->match(netdev))
+			return ft;
+	return NULL;
+}
+
+/**
+ * fcoe_transport_attach - Attaches an FCoE transport
+ * @ft: The fcoe transport to be attached
+ *
+ * Returns : 0 for success
+ */
+int fcoe_transport_attach(struct fcoe_transport *ft)
+{
+	int rc = 0;
+
+	mutex_lock(&ft_mutex);
+	if (ft->attached) {
+		LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
+				       ft->name);
+		rc = -EEXIST;
+		goto out_attach;
+	}
+
+	/* Add default transport to the tail */
+	if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
+		list_add(&ft->list, &fcoe_transports);
+	else
+		list_add_tail(&ft->list, &fcoe_transports);
+
+	ft->attached = true;
+	LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
+
+out_attach:
+	mutex_unlock(&ft_mutex);
+	return rc;
+}
+EXPORT_SYMBOL(fcoe_transport_attach);
+
+/**
+ * fcoe_transport_attach - Detaches an FCoE transport
+ * @ft: The fcoe transport to be attached
+ *
+ * Returns : 0 for success
+ */
+int fcoe_transport_detach(struct fcoe_transport *ft)
+{
+	int rc = 0;
+
+	mutex_lock(&ft_mutex);
+	if (!ft->attached) {
+		LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
+			ft->name);
+		rc = -ENODEV;
+		goto out_attach;
+	}
+
+	list_del(&ft->list);
+	ft->attached = false;
+	LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
+
+out_attach:
+	mutex_unlock(&ft_mutex);
+	return rc;
+
+}
+EXPORT_SYMBOL(fcoe_transport_detach);
+
+static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
+{
+	int i, j;
+	struct fcoe_transport *ft = NULL;
+
+	i = j = sprintf(buffer, "Attached FCoE transports:");
+	mutex_lock(&ft_mutex);
+	list_for_each_entry(ft, &fcoe_transports, list) {
+		i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
+		if (i >= PAGE_SIZE)
+			break;
+	}
+	mutex_unlock(&ft_mutex);
+	if (i == j)
+		i += snprintf(&buffer[i], IFNAMSIZ, "none");
+	return i;
+}
+
+static int __init fcoe_transport_init(void)
+{
+	register_netdevice_notifier(&libfcoe_notifier);
+	return 0;
+}
+
+static int __exit fcoe_transport_exit(void)
+{
+	struct fcoe_transport *ft;
+
+	unregister_netdevice_notifier(&libfcoe_notifier);
+	mutex_lock(&ft_mutex);
+	list_for_each_entry(ft, &fcoe_transports, list)
+		printk(KERN_ERR "FCoE transport %s is still attached!\n",
+		      ft->name);
+	mutex_unlock(&ft_mutex);
+	return 0;
+}
+
+
+static int fcoe_add_netdev_mapping(struct net_device *netdev,
+					struct fcoe_transport *ft)
+{
+	struct fcoe_netdev_mapping *nm;
+
+	nm = kmalloc(sizeof(*nm), GFP_KERNEL);
+	if (!nm) {
+		printk(KERN_ERR "Unable to allocate netdev_mapping");
+		return -ENOMEM;
+	}
+
+	nm->netdev = netdev;
+	nm->ft = ft;
+
+	mutex_lock(&fn_mutex);
+	list_add(&nm->list, &fcoe_netdevs);
+	mutex_unlock(&fn_mutex);
+	return 0;
+}
+
+
+static void fcoe_del_netdev_mapping(struct net_device *netdev)
+{
+	struct fcoe_netdev_mapping *nm = NULL, *tmp;
+
+	mutex_lock(&fn_mutex);
+	list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
+		if (nm->netdev == netdev) {
+			list_del(&nm->list);
+			kfree(nm);
+			mutex_unlock(&fn_mutex);
+			return;
+		}
+	}
+	mutex_unlock(&fn_mutex);
+}
+
+
+/**
+ * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
+ * it was created
+ *
+ * Returns : ptr to the fcoe transport that supports this netdev or NULL
+ * if not found.
+ *
+ * The ft_mutex should be held when this is called
+ */
+static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
+{
+	struct fcoe_transport *ft = NULL;
+	struct fcoe_netdev_mapping *nm;
+
+	mutex_lock(&fn_mutex);
+	list_for_each_entry(nm, &fcoe_netdevs, list) {
+		if (netdev == nm->netdev) {
+			ft = nm->ft;
+			mutex_unlock(&fn_mutex);
+			return ft;
+		}
+	}
+
+	mutex_unlock(&fn_mutex);
+	return NULL;
+}
+
+/**
+ * fcoe_if_to_netdev() - Parse a name buffer to get a net device
+ * @buffer: The name of the net device
+ *
+ * Returns: NULL or a ptr to net_device
+ */
+static struct net_device *fcoe_if_to_netdev(const char *buffer)
+{
+	char *cp;
+	char ifname[IFNAMSIZ + 2];
+
+	if (buffer) {
+		strlcpy(ifname, buffer, IFNAMSIZ);
+		cp = ifname + strlen(ifname);
+		while (--cp >= ifname && *cp == '\n')
+			*cp = '\0';
+		return dev_get_by_name(&init_net, ifname);
+	}
+	return NULL;
+}
+
+/**
+ * libfcoe_device_notification() - Handler for net device events
+ * @notifier: The context of the notification
+ * @event:    The type of event
+ * @ptr:      The net device that the event was on
+ *
+ * This function is called by the Ethernet driver in case of link change event.
+ *
+ * Returns: 0 for success
+ */
+static int libfcoe_device_notification(struct notifier_block *notifier,
+				    ulong event, void *ptr)
+{
+	struct net_device *netdev = ptr;
+
+	switch (event) {
+	case NETDEV_UNREGISTER:
+		printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n",
+				netdev->name);
+		fcoe_del_netdev_mapping(netdev);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+
+/**
+ * fcoe_transport_create() - Create a fcoe interface
+ * @buffer: The name of the Ethernet interface to create on
+ * @kp:	    The associated kernel param
+ *
+ * Called from sysfs. This holds the ft_mutex while calling the
+ * registered fcoe transport's create function.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+	enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev) {
+		LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
+		goto out_nodev;
+	}
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (ft) {
+		LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
+				      "FCoE instance on %s.\n",
+				      ft->name, netdev->name);
+		rc = -EEXIST;
+		goto out_putdev;
+	}
+
+	ft = fcoe_transport_lookup(netdev);
+	if (!ft) {
+		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
+				      netdev->name);
+		goto out_putdev;
+	}
+
+	rc = fcoe_add_netdev_mapping(netdev, ft);
+	if (rc) {
+		LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
+				      "for FCoE transport %s for %s.\n",
+				      ft->name, netdev->name);
+		goto out_putdev;
+	}
+
+	/* pass to transport create */
+	rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
+	if (rc)
+		fcoe_del_netdev_mapping(netdev);
+
+	LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
+			      ft->name, (rc) ? "failed" : "succeeded",
+			      netdev->name);
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * fcoe_transport_destroy() - Destroy a FCoE interface
+ * @buffer: The name of the Ethernet interface to be destroyed
+ * @kp:	    The associated kernel parameter
+ *
+ * Called from sysfs. This holds the ft_mutex while calling the
+ * registered fcoe transport's destroy function.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev) {
+		LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
+		goto out_nodev;
+	}
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (!ft) {
+		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
+				      netdev->name);
+		goto out_putdev;
+	}
+
+	/* pass to transport destroy */
+	rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
+	fcoe_del_netdev_mapping(netdev);
+	LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
+			      ft->name, (rc) ? "failed" : "succeeded",
+			      netdev->name);
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * fcoe_transport_disable() - Disables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be disabled
+ * @kp:	    The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev)
+		goto out_nodev;
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (!ft)
+		goto out_putdev;
+
+	rc = ft->disable ? ft->disable(netdev) : -ENODEV;
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * fcoe_transport_enable() - Enables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be enabled
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev)
+		goto out_nodev;
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (!ft)
+		goto out_putdev;
+
+	rc = ft->enable ? ft->enable(netdev) : -ENODEV;
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * libfcoe_init() - Initialization routine for libfcoe.ko
+ */
+static int __init libfcoe_init(void)
+{
+	fcoe_transport_init();
+
+	return 0;
+}
+module_init(libfcoe_init);
+
+/**
+ * libfcoe_exit() - Tear down libfcoe.ko
+ */
+static void __exit libfcoe_exit(void)
+{
+	fcoe_transport_exit();
+}
+module_exit(libfcoe_exit);
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
deleted file mode 100644
index 625c6be..0000000
--- a/drivers/scsi/fcoe/libfcoe.c
+++ /dev/null
@@ -1,2708 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Cisco Systems, Inc.  All rights reserved.
- * Copyright (c) 2009 Intel Corporation.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Maintained at www.Open-FCoE.org
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/errno.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <net/rtnetlink.h>
-
-#include <scsi/fc/fc_els.h>
-#include <scsi/fc/fc_fs.h>
-#include <scsi/fc/fc_fip.h>
-#include <scsi/fc/fc_encaps.h>
-#include <scsi/fc/fc_fcoe.h>
-#include <scsi/fc/fc_fcp.h>
-
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
-
-MODULE_AUTHOR("Open-FCoE.org");
-MODULE_DESCRIPTION("FIP discovery protocol support for FCoE HBAs");
-MODULE_LICENSE("GPL v2");
-
-#define	FCOE_CTLR_MIN_FKA	500		/* min keep alive (mS) */
-#define	FCOE_CTLR_DEF_FKA	FIP_DEF_FKA	/* default keep alive (mS) */
-
-static void fcoe_ctlr_timeout(unsigned long);
-static void fcoe_ctlr_timer_work(struct work_struct *);
-static void fcoe_ctlr_recv_work(struct work_struct *);
-static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
-
-static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
-static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
-static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
-static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
-
-static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
-static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
-static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
-static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS;
-
-unsigned int libfcoe_debug_logging;
-module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
-
-#define LIBFCOE_LOGGING	    0x01 /* General logging, not categorized */
-#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
-
-#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD)		\
-do {							\
-	if (unlikely(libfcoe_debug_logging & LEVEL))	\
-		do {					\
-			CMD;				\
-		} while (0);				\
-} while (0)
-
-#define LIBFCOE_DBG(fmt, args...)					\
-	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\
-			      printk(KERN_INFO "libfcoe: " fmt, ##args);)
-
-#define LIBFCOE_FIP_DBG(fip, fmt, args...)				\
-	LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING,			\
-			      printk(KERN_INFO "host%d: fip: " fmt, 	\
-				     (fip)->lp->host->host_no, ##args);)
-
-static const char *fcoe_ctlr_states[] = {
-	[FIP_ST_DISABLED] =	"DISABLED",
-	[FIP_ST_LINK_WAIT] =	"LINK_WAIT",
-	[FIP_ST_AUTO] =		"AUTO",
-	[FIP_ST_NON_FIP] =	"NON_FIP",
-	[FIP_ST_ENABLED] =	"ENABLED",
-	[FIP_ST_VNMP_START] =	"VNMP_START",
-	[FIP_ST_VNMP_PROBE1] =	"VNMP_PROBE1",
-	[FIP_ST_VNMP_PROBE2] =	"VNMP_PROBE2",
-	[FIP_ST_VNMP_CLAIM] =	"VNMP_CLAIM",
-	[FIP_ST_VNMP_UP] =	"VNMP_UP",
-};
-
-static const char *fcoe_ctlr_state(enum fip_state state)
-{
-	const char *cp = "unknown";
-
-	if (state < ARRAY_SIZE(fcoe_ctlr_states))
-		cp = fcoe_ctlr_states[state];
-	if (!cp)
-		cp = "unknown";
-	return cp;
-}
-
-/**
- * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state.
- * @fip: The FCoE controller
- * @state: The new state
- */
-static void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state)
-{
-	if (state == fip->state)
-		return;
-	if (fip->lp)
-		LIBFCOE_FIP_DBG(fip, "state %s -> %s\n",
-			fcoe_ctlr_state(fip->state), fcoe_ctlr_state(state));
-	fip->state = state;
-}
-
-/**
- * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid
- * @fcf: The FCF to check
- *
- * Return non-zero if FCF fcoe_size has been validated.
- */
-static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf)
-{
-	return (fcf->flags & FIP_FL_SOL) != 0;
-}
-
-/**
- * fcoe_ctlr_fcf_usable() - Check if a FCF is usable
- * @fcf: The FCF to check
- *
- * Return non-zero if the FCF is usable.
- */
-static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf)
-{
-	u16 flags = FIP_FL_SOL | FIP_FL_AVAIL;
-
-	return (fcf->flags & flags) == flags;
-}
-
-/**
- * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses
- * @fip: The FCoE controller
- */
-static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip)
-{
-	if (fip->mode == FIP_MODE_VN2VN)
-		hton24(fip->dest_addr, FIP_VN_FC_MAP);
-	else
-		hton24(fip->dest_addr, FIP_DEF_FC_MAP);
-	hton24(fip->dest_addr + 3, 0);
-	fip->map_dest = 1;
-}
-
-/**
- * fcoe_ctlr_init() - Initialize the FCoE Controller instance
- * @fip: The FCoE controller to initialize
- */
-void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
-{
-	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
-	fip->mode = mode;
-	INIT_LIST_HEAD(&fip->fcfs);
-	mutex_init(&fip->ctlr_mutex);
-	spin_lock_init(&fip->ctlr_lock);
-	fip->flogi_oxid = FC_XID_UNKNOWN;
-	setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
-	INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
-	INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
-	skb_queue_head_init(&fip->fip_recv_list);
-}
-EXPORT_SYMBOL(fcoe_ctlr_init);
-
-/**
- * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller
- * @fip: The FCoE controller whose FCFs are to be reset
- *
- * Called with &fcoe_ctlr lock held.
- */
-static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *next;
-
-	fip->sel_fcf = NULL;
-	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
-		list_del(&fcf->list);
-		kfree(fcf);
-	}
-	fip->fcf_count = 0;
-	fip->sel_time = 0;
-}
-
-/**
- * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller
- * @fip: The FCoE controller to tear down
- *
- * This is called by FCoE drivers before freeing the &fcoe_ctlr.
- *
- * The receive handler will have been deleted before this to guarantee
- * that no more recv_work will be scheduled.
- *
- * The timer routine will simply return once we set FIP_ST_DISABLED.
- * This guarantees that no further timeouts or work will be scheduled.
- */
-void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
-{
-	cancel_work_sync(&fip->recv_work);
-	skb_queue_purge(&fip->fip_recv_list);
-
-	mutex_lock(&fip->ctlr_mutex);
-	fcoe_ctlr_set_state(fip, FIP_ST_DISABLED);
-	fcoe_ctlr_reset_fcfs(fip);
-	mutex_unlock(&fip->ctlr_mutex);
-	del_timer_sync(&fip->timer);
-	cancel_work_sync(&fip->timer_work);
-}
-EXPORT_SYMBOL(fcoe_ctlr_destroy);
-
-/**
- * fcoe_ctlr_announce() - announce new FCF selection
- * @fip: The FCoE controller
- *
- * Also sets the destination MAC for FCoE and control packets
- *
- * Called with neither ctlr_mutex nor ctlr_lock held.
- */
-static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *sel;
-	struct fcoe_fcf *fcf;
-
-	mutex_lock(&fip->ctlr_mutex);
-	spin_lock_bh(&fip->ctlr_lock);
-
-	kfree_skb(fip->flogi_req);
-	fip->flogi_req = NULL;
-	list_for_each_entry(fcf, &fip->fcfs, list)
-		fcf->flogi_sent = 0;
-
-	spin_unlock_bh(&fip->ctlr_lock);
-	sel = fip->sel_fcf;
-
-	if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
-		goto unlock;
-	if (!is_zero_ether_addr(fip->dest_addr)) {
-		printk(KERN_NOTICE "libfcoe: host%d: "
-		       "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
-		       fip->lp->host->host_no, fip->dest_addr);
-		memset(fip->dest_addr, 0, ETH_ALEN);
-	}
-	if (sel) {
-		printk(KERN_INFO "libfcoe: host%d: FIP selected "
-		       "Fibre-Channel Forwarder MAC %pM\n",
-		       fip->lp->host->host_no, sel->fcf_mac);
-		memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
-		fip->map_dest = 0;
-	}
-unlock:
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-/**
- * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port
- * @fip: The FCoE controller to get the maximum FCoE size from
- *
- * Returns the maximum packet size including the FCoE header and trailer,
- * but not including any Ethernet or VLAN headers.
- */
-static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip)
-{
-	/*
-	 * Determine the max FCoE frame size allowed, including
-	 * FCoE header and trailer.
-	 * Note:  lp->mfs is currently the payload size, not the frame size.
-	 */
-	return fip->lp->mfs + sizeof(struct fc_frame_header) +
-		sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof);
-}
-
-/**
- * fcoe_ctlr_solicit() - Send a FIP solicitation
- * @fip: The FCoE controller to send the solicitation on
- * @fcf: The destination FCF (if NULL, a multicast solicitation is sent)
- */
-static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
-{
-	struct sk_buff *skb;
-	struct fip_sol {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct {
-			struct fip_mac_desc mac;
-			struct fip_wwn_desc wwnn;
-			struct fip_size_desc size;
-		} __attribute__((packed)) desc;
-	}  __attribute__((packed)) *sol;
-	u32 fcoe_size;
-
-	skb = dev_alloc_skb(sizeof(*sol));
-	if (!skb)
-		return;
-
-	sol = (struct fip_sol *)skb->data;
-
-	memset(sol, 0, sizeof(*sol));
-	memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN);
-	memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
-	sol->eth.h_proto = htons(ETH_P_FIP);
-
-	sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	sol->fip.fip_op = htons(FIP_OP_DISC);
-	sol->fip.fip_subcode = FIP_SC_SOL;
-	sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW);
-	sol->fip.fip_flags = htons(FIP_FL_FPMA);
-	if (fip->spma)
-		sol->fip.fip_flags |= htons(FIP_FL_SPMA);
-
-	sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
-	sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW;
-	memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-
-	sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
-	sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
-	put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
-
-	fcoe_size = fcoe_ctlr_fcoe_size(fip);
-	sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
-	sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW;
-	sol->desc.size.fd_size = htons(fcoe_size);
-
-	skb_put(skb, sizeof(*sol));
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	fip->send(fip, skb);
-
-	if (!fcf)
-		fip->sol_time = jiffies;
-}
-
-/**
- * fcoe_ctlr_link_up() - Start FCoE controller
- * @fip: The FCoE controller to start
- *
- * Called from the LLD when the network link is ready.
- */
-void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
-{
-	mutex_lock(&fip->ctlr_mutex);
-	if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
-		mutex_unlock(&fip->ctlr_mutex);
-		fc_linkup(fip->lp);
-	} else if (fip->state == FIP_ST_LINK_WAIT) {
-		fcoe_ctlr_set_state(fip, fip->mode);
-		switch (fip->mode) {
-		default:
-			LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode);
-			/* fall-through */
-		case FIP_MODE_AUTO:
-			LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
-			/* fall-through */
-		case FIP_MODE_FABRIC:
-		case FIP_MODE_NON_FIP:
-			mutex_unlock(&fip->ctlr_mutex);
-			fc_linkup(fip->lp);
-			fcoe_ctlr_solicit(fip, NULL);
-			break;
-		case FIP_MODE_VN2VN:
-			fcoe_ctlr_vn_start(fip);
-			mutex_unlock(&fip->ctlr_mutex);
-			fc_linkup(fip->lp);
-			break;
-		}
-	} else
-		mutex_unlock(&fip->ctlr_mutex);
-}
-EXPORT_SYMBOL(fcoe_ctlr_link_up);
-
-/**
- * fcoe_ctlr_reset() - Reset a FCoE controller
- * @fip:       The FCoE controller to reset
- */
-static void fcoe_ctlr_reset(struct fcoe_ctlr *fip)
-{
-	fcoe_ctlr_reset_fcfs(fip);
-	del_timer(&fip->timer);
-	fip->ctlr_ka_time = 0;
-	fip->port_ka_time = 0;
-	fip->sol_time = 0;
-	fip->flogi_oxid = FC_XID_UNKNOWN;
-	fcoe_ctlr_map_dest(fip);
-}
-
-/**
- * fcoe_ctlr_link_down() - Stop a FCoE controller
- * @fip: The FCoE controller to be stopped
- *
- * Returns non-zero if the link was up and now isn't.
- *
- * Called from the LLD when the network link is not ready.
- * There may be multiple calls while the link is down.
- */
-int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
-{
-	int link_dropped;
-
-	LIBFCOE_FIP_DBG(fip, "link down.\n");
-	mutex_lock(&fip->ctlr_mutex);
-	fcoe_ctlr_reset(fip);
-	link_dropped = fip->state != FIP_ST_LINK_WAIT;
-	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
-	mutex_unlock(&fip->ctlr_mutex);
-
-	if (link_dropped)
-		fc_linkdown(fip->lp);
-	return link_dropped;
-}
-EXPORT_SYMBOL(fcoe_ctlr_link_down);
-
-/**
- * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF
- * @fip:   The FCoE controller to send the FKA on
- * @lport: libfc fc_lport to send from
- * @ports: 0 for controller keep-alive, 1 for port keep-alive
- * @sa:	   The source MAC address
- *
- * A controller keep-alive is sent every fka_period (typically 8 seconds).
- * The source MAC is the native MAC address.
- *
- * A port keep-alive is sent every 90 seconds while logged in.
- * The source MAC is the assigned mapped source address.
- * The destination is the FCF's F-port.
- */
-static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
-				      struct fc_lport *lport,
-				      int ports, u8 *sa)
-{
-	struct sk_buff *skb;
-	struct fip_kal {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct fip_mac_desc mac;
-	} __attribute__((packed)) *kal;
-	struct fip_vn_desc *vn;
-	u32 len;
-	struct fc_lport *lp;
-	struct fcoe_fcf *fcf;
-
-	fcf = fip->sel_fcf;
-	lp = fip->lp;
-	if (!fcf || (ports && !lp->port_id))
-		return;
-
-	len = sizeof(*kal) + ports * sizeof(*vn);
-	skb = dev_alloc_skb(len);
-	if (!skb)
-		return;
-
-	kal = (struct fip_kal *)skb->data;
-	memset(kal, 0, len);
-	memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
-	memcpy(kal->eth.h_source, sa, ETH_ALEN);
-	kal->eth.h_proto = htons(ETH_P_FIP);
-
-	kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	kal->fip.fip_op = htons(FIP_OP_CTRL);
-	kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE;
-	kal->fip.fip_dl_len = htons((sizeof(kal->mac) +
-				     ports * sizeof(*vn)) / FIP_BPW);
-	kal->fip.fip_flags = htons(FIP_FL_FPMA);
-	if (fip->spma)
-		kal->fip.fip_flags |= htons(FIP_FL_SPMA);
-
-	kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
-	kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
-	memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-	if (ports) {
-		vn = (struct fip_vn_desc *)(kal + 1);
-		vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
-		vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
-		memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
-		hton24(vn->fd_fc_id, lport->port_id);
-		put_unaligned_be64(lport->wwpn, &vn->fd_wwpn);
-	}
-	skb_put(skb, len);
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	fip->send(fip, skb);
-}
-
-/**
- * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it
- * @fip:   The FCoE controller for the ELS frame
- * @dtype: The FIP descriptor type for the frame
- * @skb:   The FCoE ELS frame including FC header but no FCoE headers
- * @d_id:  The destination port ID.
- *
- * Returns non-zero error code on failure.
- *
- * The caller must check that the length is a multiple of 4.
- *
- * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes).
- * Headroom includes the FIP encapsulation description, FIP header, and
- * Ethernet header.  The tailroom is for the FIP MAC descriptor.
- */
-static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
-			    u8 dtype, struct sk_buff *skb, u32 d_id)
-{
-	struct fip_encaps_head {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct fip_encaps encaps;
-	} __attribute__((packed)) *cap;
-	struct fc_frame_header *fh;
-	struct fip_mac_desc *mac;
-	struct fcoe_fcf *fcf;
-	size_t dlen;
-	u16 fip_flags;
-	u8 op;
-
-	fh = (struct fc_frame_header *)skb->data;
-	op = *(u8 *)(fh + 1);
-	dlen = sizeof(struct fip_encaps) + skb->len;	/* len before push */
-	cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
-	memset(cap, 0, sizeof(*cap));
-
-	if (lport->point_to_multipoint) {
-		if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest))
-			return -ENODEV;
-		fip_flags = 0;
-	} else {
-		fcf = fip->sel_fcf;
-		if (!fcf)
-			return -ENODEV;
-		fip_flags = fcf->flags;
-		fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA :
-					 FIP_FL_FPMA;
-		if (!fip_flags)
-			return -ENODEV;
-		memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
-	}
-	memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
-	cap->eth.h_proto = htons(ETH_P_FIP);
-
-	cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	cap->fip.fip_op = htons(FIP_OP_LS);
-	if (op == ELS_LS_ACC || op == ELS_LS_RJT)
-		cap->fip.fip_subcode = FIP_SC_REP;
-	else
-		cap->fip.fip_subcode = FIP_SC_REQ;
-	cap->fip.fip_flags = htons(fip_flags);
-
-	cap->encaps.fd_desc.fip_dtype = dtype;
-	cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
-
-	if (op != ELS_LS_RJT) {
-		dlen += sizeof(*mac);
-		mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
-		memset(mac, 0, sizeof(*mac));
-		mac->fd_desc.fip_dtype = FIP_DT_MAC;
-		mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
-		if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) {
-			memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
-		} else if (fip->mode == FIP_MODE_VN2VN) {
-			hton24(mac->fd_mac, FIP_VN_FC_MAP);
-			hton24(mac->fd_mac + 3, fip->port_id);
-		} else if (fip_flags & FIP_FL_SPMA) {
-			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n");
-			memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN);
-		} else {
-			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n");
-			/* FPMA only FLOGI.  Must leave the MAC desc zeroed. */
-		}
-	}
-	cap->fip.fip_dl_len = htons(dlen / FIP_BPW);
-
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	return 0;
-}
-
-/**
- * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate.
- * @fip:	FCoE controller.
- * @lport:	libfc fc_lport to send from
- * @skb:	FCoE ELS frame including FC header but no FCoE headers.
- *
- * Returns a non-zero error code if the frame should not be sent.
- * Returns zero if the caller should send the frame with FCoE encapsulation.
- *
- * The caller must check that the length is a multiple of 4.
- * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
- * The the skb must also be an fc_frame.
- *
- * This is called from the lower-level driver with spinlocks held,
- * so we must not take a mutex here.
- */
-int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
-		       struct sk_buff *skb)
-{
-	struct fc_frame *fp;
-	struct fc_frame_header *fh;
-	u16 old_xid;
-	u8 op;
-	u8 mac[ETH_ALEN];
-
-	fp = container_of(skb, struct fc_frame, skb);
-	fh = (struct fc_frame_header *)skb->data;
-	op = *(u8 *)(fh + 1);
-
-	if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) {
-		old_xid = fip->flogi_oxid;
-		fip->flogi_oxid = ntohs(fh->fh_ox_id);
-		if (fip->state == FIP_ST_AUTO) {
-			if (old_xid == FC_XID_UNKNOWN)
-				fip->flogi_count = 0;
-			fip->flogi_count++;
-			if (fip->flogi_count < 3)
-				goto drop;
-			fcoe_ctlr_map_dest(fip);
-			return 0;
-		}
-		if (fip->state == FIP_ST_NON_FIP)
-			fcoe_ctlr_map_dest(fip);
-	}
-
-	if (fip->state == FIP_ST_NON_FIP)
-		return 0;
-	if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN)
-		goto drop;
-	switch (op) {
-	case ELS_FLOGI:
-		op = FIP_DT_FLOGI;
-		if (fip->mode == FIP_MODE_VN2VN)
-			break;
-		spin_lock_bh(&fip->ctlr_lock);
-		kfree_skb(fip->flogi_req);
-		fip->flogi_req = skb;
-		fip->flogi_req_send = 1;
-		spin_unlock_bh(&fip->ctlr_lock);
-		schedule_work(&fip->timer_work);
-		return -EINPROGRESS;
-	case ELS_FDISC:
-		if (ntoh24(fh->fh_s_id))
-			return 0;
-		op = FIP_DT_FDISC;
-		break;
-	case ELS_LOGO:
-		if (fip->mode == FIP_MODE_VN2VN) {
-			if (fip->state != FIP_ST_VNMP_UP)
-				return -EINVAL;
-			if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI)
-				return -EINVAL;
-		} else {
-			if (fip->state != FIP_ST_ENABLED)
-				return 0;
-			if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
-				return 0;
-		}
-		op = FIP_DT_LOGO;
-		break;
-	case ELS_LS_ACC:
-		/*
-		 * If non-FIP, we may have gotten an SID by accepting an FLOGI
-		 * from a point-to-point connection.  Switch to using
-		 * the source mac based on the SID.  The destination
-		 * MAC in this case would have been set by receving the
-		 * FLOGI.
-		 */
-		if (fip->state == FIP_ST_NON_FIP) {
-			if (fip->flogi_oxid == FC_XID_UNKNOWN)
-				return 0;
-			fip->flogi_oxid = FC_XID_UNKNOWN;
-			fc_fcoe_set_mac(mac, fh->fh_d_id);
-			fip->update_mac(lport, mac);
-		}
-		/* fall through */
-	case ELS_LS_RJT:
-		op = fr_encaps(fp);
-		if (op)
-			break;
-		return 0;
-	default:
-		if (fip->state != FIP_ST_ENABLED &&
-		    fip->state != FIP_ST_VNMP_UP)
-			goto drop;
-		return 0;
-	}
-	LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n",
-			op, ntoh24(fh->fh_d_id));
-	if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id)))
-		goto drop;
-	fip->send(fip, skb);
-	return -EINPROGRESS;
-drop:
-	kfree_skb(skb);
-	return -EINVAL;
-}
-EXPORT_SYMBOL(fcoe_ctlr_els_send);
-
-/**
- * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller
- * @fip: The FCoE controller to free FCFs on
- *
- * Called with lock held and preemption disabled.
- *
- * An FCF is considered old if we have missed two advertisements.
- * That is, there have been no valid advertisement from it for 2.5
- * times its keep-alive period.
- *
- * In addition, determine the time when an FCF selection can occur.
- *
- * Also, increment the MissDiscAdvCount when no advertisement is received
- * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB).
- *
- * Returns the time in jiffies for the next call.
- */
-static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *next;
-	unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
-	unsigned long deadline;
-	unsigned long sel_time = 0;
-	struct fcoe_dev_stats *stats;
-
-	stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());
-
-	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
-		deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
-		if (fip->sel_fcf == fcf) {
-			if (time_after(jiffies, deadline)) {
-				stats->MissDiscAdvCount++;
-				printk(KERN_INFO "libfcoe: host%d: "
-				       "Missing Discovery Advertisement "
-				       "for fab %16.16llx count %lld\n",
-				       fip->lp->host->host_no, fcf->fabric_name,
-				       stats->MissDiscAdvCount);
-			} else if (time_after(next_timer, deadline))
-				next_timer = deadline;
-		}
-
-		deadline += fcf->fka_period;
-		if (time_after_eq(jiffies, deadline)) {
-			if (fip->sel_fcf == fcf)
-				fip->sel_fcf = NULL;
-			list_del(&fcf->list);
-			WARN_ON(!fip->fcf_count);
-			fip->fcf_count--;
-			kfree(fcf);
-			stats->VLinkFailureCount++;
-		} else {
-			if (time_after(next_timer, deadline))
-				next_timer = deadline;
-			if (fcoe_ctlr_mtu_valid(fcf) &&
-			    (!sel_time || time_before(sel_time, fcf->time)))
-				sel_time = fcf->time;
-		}
-	}
-	put_cpu();
-	if (sel_time && !fip->sel_fcf && !fip->sel_time) {
-		sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
-		fip->sel_time = sel_time;
-	}
-
-	return next_timer;
-}
-
-/**
- * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry
- * @fip: The FCoE controller receiving the advertisement
- * @skb: The received FIP advertisement frame
- * @fcf: The resulting FCF entry
- *
- * Returns zero on a valid parsed advertisement,
- * otherwise returns non zero value.
- */
-static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip,
-			       struct sk_buff *skb, struct fcoe_fcf *fcf)
-{
-	struct fip_header *fiph;
-	struct fip_desc *desc = NULL;
-	struct fip_wwn_desc *wwn;
-	struct fip_fab_desc *fab;
-	struct fip_fka_desc *fka;
-	unsigned long t;
-	size_t rlen;
-	size_t dlen;
-	u32 desc_mask;
-
-	memset(fcf, 0, sizeof(*fcf));
-	fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA);
-
-	fiph = (struct fip_header *)skb->data;
-	fcf->flags = ntohs(fiph->fip_flags);
-
-	/*
-	 * mask of required descriptors. validating each one clears its bit.
-	 */
-	desc_mask = BIT(FIP_DT_PRI) | BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
-			BIT(FIP_DT_FAB) | BIT(FIP_DT_FKA);
-
-	rlen = ntohs(fiph->fip_dl_len) * 4;
-	if (rlen + sizeof(*fiph) > skb->len)
-		return -EINVAL;
-
-	desc = (struct fip_desc *)(fiph + 1);
-	while (rlen > 0) {
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen < sizeof(*desc) || dlen > rlen)
-			return -EINVAL;
-		/* Drop Adv if there are duplicate critical descriptors */
-		if ((desc->fip_dtype < 32) &&
-		    !(desc_mask & 1U << desc->fip_dtype)) {
-			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
-					"Descriptors in FIP adv\n");
-			return -EINVAL;
-		}
-		switch (desc->fip_dtype) {
-		case FIP_DT_PRI:
-			if (dlen != sizeof(struct fip_pri_desc))
-				goto len_err;
-			fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri;
-			desc_mask &= ~BIT(FIP_DT_PRI);
-			break;
-		case FIP_DT_MAC:
-			if (dlen != sizeof(struct fip_mac_desc))
-				goto len_err;
-			memcpy(fcf->fcf_mac,
-			       ((struct fip_mac_desc *)desc)->fd_mac,
-			       ETH_ALEN);
-			if (!is_valid_ether_addr(fcf->fcf_mac)) {
-				LIBFCOE_FIP_DBG(fip,
-					"Invalid MAC addr %pM in FIP adv\n",
-					fcf->fcf_mac);
-				return -EINVAL;
-			}
-			desc_mask &= ~BIT(FIP_DT_MAC);
-			break;
-		case FIP_DT_NAME:
-			if (dlen != sizeof(struct fip_wwn_desc))
-				goto len_err;
-			wwn = (struct fip_wwn_desc *)desc;
-			fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn);
-			desc_mask &= ~BIT(FIP_DT_NAME);
-			break;
-		case FIP_DT_FAB:
-			if (dlen != sizeof(struct fip_fab_desc))
-				goto len_err;
-			fab = (struct fip_fab_desc *)desc;
-			fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn);
-			fcf->vfid = ntohs(fab->fd_vfid);
-			fcf->fc_map = ntoh24(fab->fd_map);
-			desc_mask &= ~BIT(FIP_DT_FAB);
-			break;
-		case FIP_DT_FKA:
-			if (dlen != sizeof(struct fip_fka_desc))
-				goto len_err;
-			fka = (struct fip_fka_desc *)desc;
-			if (fka->fd_flags & FIP_FKA_ADV_D)
-				fcf->fd_flags = 1;
-			t = ntohl(fka->fd_fka_period);
-			if (t >= FCOE_CTLR_MIN_FKA)
-				fcf->fka_period = msecs_to_jiffies(t);
-			desc_mask &= ~BIT(FIP_DT_FKA);
-			break;
-		case FIP_DT_MAP_OUI:
-		case FIP_DT_FCOE_SIZE:
-		case FIP_DT_FLOGI:
-		case FIP_DT_FDISC:
-		case FIP_DT_LOGO:
-		case FIP_DT_ELP:
-		default:
-			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
-					"in FIP adv\n", desc->fip_dtype);
-			/* standard says ignore unknown descriptors >= 128 */
-			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
-				return -EINVAL;
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-	if (!fcf->fc_map || (fcf->fc_map & 0x10000))
-		return -EINVAL;
-	if (!fcf->switch_name)
-		return -EINVAL;
-	if (desc_mask) {
-		LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n",
-				desc_mask);
-		return -EINVAL;
-	}
-	return 0;
-
-len_err:
-	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
-			desc->fip_dtype, dlen);
-	return -EINVAL;
-}
-
-/**
- * fcoe_ctlr_recv_adv() - Handle an incoming advertisement
- * @fip: The FCoE controller receiving the advertisement
- * @skb: The received FIP packet
- */
-static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf new;
-	struct fcoe_fcf *found;
-	unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
-	int first = 0;
-	int mtu_valid;
-
-	if (fcoe_ctlr_parse_adv(fip, skb, &new))
-		return;
-
-	mutex_lock(&fip->ctlr_mutex);
-	first = list_empty(&fip->fcfs);
-	found = NULL;
-	list_for_each_entry(fcf, &fip->fcfs, list) {
-		if (fcf->switch_name == new.switch_name &&
-		    fcf->fabric_name == new.fabric_name &&
-		    fcf->fc_map == new.fc_map &&
-		    compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
-			found = fcf;
-			break;
-		}
-	}
-	if (!found) {
-		if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT)
-			goto out;
-
-		fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC);
-		if (!fcf)
-			goto out;
-
-		fip->fcf_count++;
-		memcpy(fcf, &new, sizeof(new));
-		list_add(&fcf->list, &fip->fcfs);
-	} else {
-		/*
-		 * Update the FCF's keep-alive descriptor flags.
-		 * Other flag changes from new advertisements are
-		 * ignored after a solicited advertisement is
-		 * received and the FCF is selectable (usable).
-		 */
-		fcf->fd_flags = new.fd_flags;
-		if (!fcoe_ctlr_fcf_usable(fcf))
-			fcf->flags = new.flags;
-
-		if (fcf == fip->sel_fcf && !fcf->fd_flags) {
-			fip->ctlr_ka_time -= fcf->fka_period;
-			fip->ctlr_ka_time += new.fka_period;
-			if (time_before(fip->ctlr_ka_time, fip->timer.expires))
-				mod_timer(&fip->timer, fip->ctlr_ka_time);
-		}
-		fcf->fka_period = new.fka_period;
-		memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
-	}
-	mtu_valid = fcoe_ctlr_mtu_valid(fcf);
-	fcf->time = jiffies;
-	if (!found)
-		LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
-				fcf->fabric_name, fcf->fcf_mac);
-
-	/*
-	 * If this advertisement is not solicited and our max receive size
-	 * hasn't been verified, send a solicited advertisement.
-	 */
-	if (!mtu_valid)
-		fcoe_ctlr_solicit(fip, fcf);
-
-	/*
-	 * If its been a while since we did a solicit, and this is
-	 * the first advertisement we've received, do a multicast
-	 * solicitation to gather as many advertisements as we can
-	 * before selection occurs.
-	 */
-	if (first && time_after(jiffies, fip->sol_time + sol_tov))
-		fcoe_ctlr_solicit(fip, NULL);
-
-	/*
-	 * Put this FCF at the head of the list for priority among equals.
-	 * This helps in the case of an NPV switch which insists we use
-	 * the FCF that answers multicast solicitations, not the others that
-	 * are sending periodic multicast advertisements.
-	 */
-	if (mtu_valid) {
-		list_del(&fcf->list);
-		list_add(&fcf->list, &fip->fcfs);
-	}
-
-	/*
-	 * If this is the first validated FCF, note the time and
-	 * set a timer to trigger selection.
-	 */
-	if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) {
-		fip->sel_time = jiffies +
-			msecs_to_jiffies(FCOE_CTLR_START_DELAY);
-		if (!timer_pending(&fip->timer) ||
-		    time_before(fip->sel_time, fip->timer.expires))
-			mod_timer(&fip->timer, fip->sel_time);
-	}
-out:
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-/**
- * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame
- * @fip: The FCoE controller which received the packet
- * @skb: The received FIP packet
- */
-static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fip_header *fiph;
-	struct fc_frame *fp = (struct fc_frame *)skb;
-	struct fc_frame_header *fh = NULL;
-	struct fip_desc *desc;
-	struct fip_encaps *els;
-	struct fcoe_dev_stats *stats;
-	enum fip_desc_type els_dtype = 0;
-	u8 els_op;
-	u8 sub;
-	u8 granted_mac[ETH_ALEN] = { 0 };
-	size_t els_len = 0;
-	size_t rlen;
-	size_t dlen;
-	u32 desc_mask = 0;
-	u32 desc_cnt = 0;
-
-	fiph = (struct fip_header *)skb->data;
-	sub = fiph->fip_subcode;
-	if (sub != FIP_SC_REQ && sub != FIP_SC_REP)
-		goto drop;
-
-	rlen = ntohs(fiph->fip_dl_len) * 4;
-	if (rlen + sizeof(*fiph) > skb->len)
-		goto drop;
-
-	desc = (struct fip_desc *)(fiph + 1);
-	while (rlen > 0) {
-		desc_cnt++;
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen < sizeof(*desc) || dlen > rlen)
-			goto drop;
-		/* Drop ELS if there are duplicate critical descriptors */
-		if (desc->fip_dtype < 32) {
-			if (desc_mask & 1U << desc->fip_dtype) {
-				LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
-						"Descriptors in FIP ELS\n");
-				goto drop;
-			}
-			desc_mask |= (1 << desc->fip_dtype);
-		}
-		switch (desc->fip_dtype) {
-		case FIP_DT_MAC:
-			if (desc_cnt == 1) {
-				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
-						"received out of order\n");
-				goto drop;
-			}
-
-			if (dlen != sizeof(struct fip_mac_desc))
-				goto len_err;
-			memcpy(granted_mac,
-			       ((struct fip_mac_desc *)desc)->fd_mac,
-			       ETH_ALEN);
-			break;
-		case FIP_DT_FLOGI:
-		case FIP_DT_FDISC:
-		case FIP_DT_LOGO:
-		case FIP_DT_ELP:
-			if (desc_cnt != 1) {
-				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
-						"received out of order\n");
-				goto drop;
-			}
-			if (fh)
-				goto drop;
-			if (dlen < sizeof(*els) + sizeof(*fh) + 1)
-				goto len_err;
-			els_len = dlen - sizeof(*els);
-			els = (struct fip_encaps *)desc;
-			fh = (struct fc_frame_header *)(els + 1);
-			els_dtype = desc->fip_dtype;
-			break;
-		default:
-			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
-					"in FIP adv\n", desc->fip_dtype);
-			/* standard says ignore unknown descriptors >= 128 */
-			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
-				goto drop;
-			if (desc_cnt <= 2) {
-				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
-						"received out of order\n");
-				goto drop;
-			}
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-
-	if (!fh)
-		goto drop;
-	els_op = *(u8 *)(fh + 1);
-
-	if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
-	    sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
-		if (els_op == ELS_LS_ACC) {
-			if (!is_valid_ether_addr(granted_mac)) {
-				LIBFCOE_FIP_DBG(fip,
-					"Invalid MAC address %pM in FIP ELS\n",
-					granted_mac);
-				goto drop;
-			}
-			memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
-
-			if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
-				fip->flogi_oxid = FC_XID_UNKNOWN;
-				if (els_dtype == FIP_DT_FLOGI)
-					fcoe_ctlr_announce(fip);
-			}
-		} else if (els_dtype == FIP_DT_FLOGI &&
-			   !fcoe_ctlr_flogi_retry(fip))
-			goto drop;	/* retrying FLOGI so drop reject */
-	}
-
-	if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
-	    (!(1U << FIP_DT_MAC & desc_mask)))) {
-		LIBFCOE_FIP_DBG(fip, "Missing critical descriptors "
-				"in FIP ELS\n");
-		goto drop;
-	}
-
-	/*
-	 * Convert skb into an fc_frame containing only the ELS.
-	 */
-	skb_pull(skb, (u8 *)fh - skb->data);
-	skb_trim(skb, els_len);
-	fp = (struct fc_frame *)skb;
-	fc_frame_init(fp);
-	fr_sof(fp) = FC_SOF_I3;
-	fr_eof(fp) = FC_EOF_T;
-	fr_dev(fp) = lport;
-	fr_encaps(fp) = els_dtype;
-
-	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
-	stats->RxFrames++;
-	stats->RxWords += skb->len / FIP_BPW;
-	put_cpu();
-
-	fc_exch_recv(lport, fp);
-	return;
-
-len_err:
-	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
-			desc->fip_dtype, dlen);
-drop:
-	kfree_skb(skb);
-}
-
-/**
- * fcoe_ctlr_recv_els() - Handle an incoming link reset frame
- * @fip: The FCoE controller that received the frame
- * @fh:	 The received FIP header
- *
- * There may be multiple VN_Port descriptors.
- * The overall length has already been checked.
- */
-static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
-				     struct fip_header *fh)
-{
-	struct fip_desc *desc;
-	struct fip_mac_desc *mp;
-	struct fip_wwn_desc *wp;
-	struct fip_vn_desc *vp;
-	size_t rlen;
-	size_t dlen;
-	struct fcoe_fcf *fcf = fip->sel_fcf;
-	struct fc_lport *lport = fip->lp;
-	struct fc_lport *vn_port = NULL;
-	u32 desc_mask;
-	int is_vn_port = 0;
-
-	LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
-
-	if (!fcf || !lport->port_id)
-		return;
-
-	/*
-	 * mask of required descriptors.  Validating each one clears its bit.
-	 */
-	desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID);
-
-	rlen = ntohs(fh->fip_dl_len) * FIP_BPW;
-	desc = (struct fip_desc *)(fh + 1);
-	while (rlen >= sizeof(*desc)) {
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen > rlen)
-			return;
-		/* Drop CVL if there are duplicate critical descriptors */
-		if ((desc->fip_dtype < 32) &&
-		    !(desc_mask & 1U << desc->fip_dtype)) {
-			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
-					"Descriptors in FIP CVL\n");
-			return;
-		}
-		switch (desc->fip_dtype) {
-		case FIP_DT_MAC:
-			mp = (struct fip_mac_desc *)desc;
-			if (dlen < sizeof(*mp))
-				return;
-			if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac))
-				return;
-			desc_mask &= ~BIT(FIP_DT_MAC);
-			break;
-		case FIP_DT_NAME:
-			wp = (struct fip_wwn_desc *)desc;
-			if (dlen < sizeof(*wp))
-				return;
-			if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name)
-				return;
-			desc_mask &= ~BIT(FIP_DT_NAME);
-			break;
-		case FIP_DT_VN_ID:
-			vp = (struct fip_vn_desc *)desc;
-			if (dlen < sizeof(*vp))
-				return;
-			if (compare_ether_addr(vp->fd_mac,
-					       fip->get_src_addr(lport)) == 0 &&
-			    get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
-			    ntoh24(vp->fd_fc_id) == lport->port_id) {
-				desc_mask &= ~BIT(FIP_DT_VN_ID);
-				break;
-			}
-			/* check if clr_vlink is for NPIV port */
-			mutex_lock(&lport->lp_mutex);
-			list_for_each_entry(vn_port, &lport->vports, list) {
-				if (compare_ether_addr(vp->fd_mac,
-				    fip->get_src_addr(vn_port)) == 0 &&
-				    (get_unaligned_be64(&vp->fd_wwpn)
-							== vn_port->wwpn) &&
-				    (ntoh24(vp->fd_fc_id) ==
-					    fc_host_port_id(vn_port->host))) {
-					desc_mask &= ~BIT(FIP_DT_VN_ID);
-					is_vn_port = 1;
-					break;
-				}
-			}
-			mutex_unlock(&lport->lp_mutex);
-
-			break;
-		default:
-			/* standard says ignore unknown descriptors >= 128 */
-			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
-				return;
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-
-	/*
-	 * reset only if all required descriptors were present and valid.
-	 */
-	if (desc_mask) {
-		LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n",
-				desc_mask);
-	} else {
-		LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
-
-		if (is_vn_port)
-			fc_lport_reset(vn_port);
-		else {
-			mutex_lock(&fip->ctlr_mutex);
-			per_cpu_ptr(lport->dev_stats,
-				    get_cpu())->VLinkFailureCount++;
-			put_cpu();
-			fcoe_ctlr_reset(fip);
-			mutex_unlock(&fip->ctlr_mutex);
-
-			fc_lport_reset(fip->lp);
-			fcoe_ctlr_solicit(fip, NULL);
-		}
-	}
-}
-
-/**
- * fcoe_ctlr_recv() - Receive a FIP packet
- * @fip: The FCoE controller that received the packet
- * @skb: The received FIP packet
- *
- * This may be called from either NET_RX_SOFTIRQ or IRQ.
- */
-void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	skb_queue_tail(&fip->fip_recv_list, skb);
-	schedule_work(&fip->recv_work);
-}
-EXPORT_SYMBOL(fcoe_ctlr_recv);
-
-/**
- * fcoe_ctlr_recv_handler() - Receive a FIP frame
- * @fip: The FCoE controller that received the frame
- * @skb: The received FIP frame
- *
- * Returns non-zero if the frame is dropped.
- */
-static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fip_header *fiph;
-	struct ethhdr *eh;
-	enum fip_state state;
-	u16 op;
-	u8 sub;
-
-	if (skb_linearize(skb))
-		goto drop;
-	if (skb->len < sizeof(*fiph))
-		goto drop;
-	eh = eth_hdr(skb);
-	if (fip->mode == FIP_MODE_VN2VN) {
-		if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
-		    compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) &&
-		    compare_ether_addr(eh->h_dest, fcoe_all_p2p))
-			goto drop;
-	} else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
-		   compare_ether_addr(eh->h_dest, fcoe_all_enode))
-		goto drop;
-	fiph = (struct fip_header *)skb->data;
-	op = ntohs(fiph->fip_op);
-	sub = fiph->fip_subcode;
-
-	if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
-		goto drop;
-	if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
-		goto drop;
-
-	mutex_lock(&fip->ctlr_mutex);
-	state = fip->state;
-	if (state == FIP_ST_AUTO) {
-		fip->map_dest = 0;
-		fcoe_ctlr_set_state(fip, FIP_ST_ENABLED);
-		state = FIP_ST_ENABLED;
-		LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
-	}
-	mutex_unlock(&fip->ctlr_mutex);
-
-	if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
-		return fcoe_ctlr_vn_recv(fip, skb);
-
-	if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
-	    state != FIP_ST_VNMP_CLAIM)
-		goto drop;
-
-	if (op == FIP_OP_LS) {
-		fcoe_ctlr_recv_els(fip, skb);	/* consumes skb */
-		return 0;
-	}
-
-	if (state != FIP_ST_ENABLED)
-		goto drop;
-
-	if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
-		fcoe_ctlr_recv_adv(fip, skb);
-	else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
-		fcoe_ctlr_recv_clr_vlink(fip, fiph);
-	kfree_skb(skb);
-	return 0;
-drop:
-	kfree_skb(skb);
-	return -1;
-}
-
-/**
- * fcoe_ctlr_select() - Select the best FCF (if possible)
- * @fip: The FCoE controller
- *
- * Returns the selected FCF, or NULL if none are usable.
- *
- * If there are conflicting advertisements, no FCF can be chosen.
- *
- * If there is already a selected FCF, this will choose a better one or
- * an equivalent one that hasn't already been sent a FLOGI.
- *
- * Called with lock held.
- */
-static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *best = fip->sel_fcf;
-	struct fcoe_fcf *first;
-
-	first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
-
-	list_for_each_entry(fcf, &fip->fcfs, list) {
-		LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
-				"VFID %d mac %pM map %x val %d "
-				"sent %u pri %u\n",
-				fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
-				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
-				fcf->flogi_sent, fcf->pri);
-		if (fcf->fabric_name != first->fabric_name ||
-		    fcf->vfid != first->vfid ||
-		    fcf->fc_map != first->fc_map) {
-			LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
-					"or FC-MAP\n");
-			return NULL;
-		}
-		if (fcf->flogi_sent)
-			continue;
-		if (!fcoe_ctlr_fcf_usable(fcf)) {
-			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
-					"map %x %svalid %savailable\n",
-					fcf->fabric_name, fcf->fc_map,
-					(fcf->flags & FIP_FL_SOL) ? "" : "in",
-					(fcf->flags & FIP_FL_AVAIL) ?
-					"" : "un");
-			continue;
-		}
-		if (!best || fcf->pri < best->pri || best->flogi_sent)
-			best = fcf;
-	}
-	fip->sel_fcf = best;
-	if (best) {
-		LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac);
-		fip->port_ka_time = jiffies +
-			msecs_to_jiffies(FIP_VN_KA_PERIOD);
-		fip->ctlr_ka_time = jiffies + best->fka_period;
-		if (time_before(fip->ctlr_ka_time, fip->timer.expires))
-			mod_timer(&fip->timer, fip->ctlr_ka_time);
-	}
-	return best;
-}
-
-/**
- * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
- * @fip: The FCoE controller
- *
- * Returns non-zero error if it could not be sent.
- *
- * Called with ctlr_mutex and ctlr_lock held.
- * Caller must verify that fip->sel_fcf is not NULL.
- */
-static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
-{
-	struct sk_buff *skb;
-	struct sk_buff *skb_orig;
-	struct fc_frame_header *fh;
-	int error;
-
-	skb_orig = fip->flogi_req;
-	if (!skb_orig)
-		return -EINVAL;
-
-	/*
-	 * Clone and send the FLOGI request.  If clone fails, use original.
-	 */
-	skb = skb_clone(skb_orig, GFP_ATOMIC);
-	if (!skb) {
-		skb = skb_orig;
-		fip->flogi_req = NULL;
-	}
-	fh = (struct fc_frame_header *)skb->data;
-	error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
-				 ntoh24(fh->fh_d_id));
-	if (error) {
-		kfree_skb(skb);
-		return error;
-	}
-	fip->send(fip, skb);
-	fip->sel_fcf->flogi_sent = 1;
-	return 0;
-}
-
-/**
- * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
- * @fip: The FCoE controller
- *
- * Returns non-zero error code if there's no FLOGI request to retry or
- * no alternate FCF available.
- */
-static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	int error;
-
-	mutex_lock(&fip->ctlr_mutex);
-	spin_lock_bh(&fip->ctlr_lock);
-	LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
-	fcf = fcoe_ctlr_select(fip);
-	if (!fcf || fcf->flogi_sent) {
-		kfree_skb(fip->flogi_req);
-		fip->flogi_req = NULL;
-		error = -ENOENT;
-	} else {
-		fcoe_ctlr_solicit(fip, NULL);
-		error = fcoe_ctlr_flogi_send_locked(fip);
-	}
-	spin_unlock_bh(&fip->ctlr_lock);
-	mutex_unlock(&fip->ctlr_mutex);
-	return error;
-}
-
-
-/**
- * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
- * @fip: The FCoE controller that timed out
- *
- * Done here because fcoe_ctlr_els_send() can't get mutex.
- *
- * Called with ctlr_mutex held.  The caller must not hold ctlr_lock.
- */
-static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-
-	spin_lock_bh(&fip->ctlr_lock);
-	fcf = fip->sel_fcf;
-	if (!fcf || !fip->flogi_req_send)
-		goto unlock;
-
-	LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
-
-	/*
-	 * If this FLOGI is being sent due to a timeout retry
-	 * to the same FCF as before, select a different FCF if possible.
-	 */
-	if (fcf->flogi_sent) {
-		LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
-		fcf = fcoe_ctlr_select(fip);
-		if (!fcf || fcf->flogi_sent) {
-			LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
-			list_for_each_entry(fcf, &fip->fcfs, list)
-				fcf->flogi_sent = 0;
-			fcf = fcoe_ctlr_select(fip);
-		}
-	}
-	if (fcf) {
-		fcoe_ctlr_flogi_send_locked(fip);
-		fip->flogi_req_send = 0;
-	} else /* XXX */
-		LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
-unlock:
-	spin_unlock_bh(&fip->ctlr_lock);
-}
-
-/**
- * fcoe_ctlr_timeout() - FIP timeout handler
- * @arg: The FCoE controller that timed out
- */
-static void fcoe_ctlr_timeout(unsigned long arg)
-{
-	struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
-
-	schedule_work(&fip->timer_work);
-}
-
-/**
- * fcoe_ctlr_timer_work() - Worker thread function for timer work
- * @work: Handle to a FCoE controller
- *
- * Ages FCFs.  Triggers FCF selection if possible.
- * Sends keep-alives and resets.
- */
-static void fcoe_ctlr_timer_work(struct work_struct *work)
-{
-	struct fcoe_ctlr *fip;
-	struct fc_lport *vport;
-	u8 *mac;
-	u8 reset = 0;
-	u8 send_ctlr_ka = 0;
-	u8 send_port_ka = 0;
-	struct fcoe_fcf *sel;
-	struct fcoe_fcf *fcf;
-	unsigned long next_timer;
-
-	fip = container_of(work, struct fcoe_ctlr, timer_work);
-	if (fip->mode == FIP_MODE_VN2VN)
-		return fcoe_ctlr_vn_timeout(fip);
-	mutex_lock(&fip->ctlr_mutex);
-	if (fip->state == FIP_ST_DISABLED) {
-		mutex_unlock(&fip->ctlr_mutex);
-		return;
-	}
-
-	fcf = fip->sel_fcf;
-	next_timer = fcoe_ctlr_age_fcfs(fip);
-
-	sel = fip->sel_fcf;
-	if (!sel && fip->sel_time) {
-		if (time_after_eq(jiffies, fip->sel_time)) {
-			sel = fcoe_ctlr_select(fip);
-			fip->sel_time = 0;
-		} else if (time_after(next_timer, fip->sel_time))
-			next_timer = fip->sel_time;
-	}
-
-	if (sel && fip->flogi_req_send)
-		fcoe_ctlr_flogi_send(fip);
-	else if (!sel && fcf)
-		reset = 1;
-
-	if (sel && !sel->fd_flags) {
-		if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
-			fip->ctlr_ka_time = jiffies + sel->fka_period;
-			send_ctlr_ka = 1;
-		}
-		if (time_after(next_timer, fip->ctlr_ka_time))
-			next_timer = fip->ctlr_ka_time;
-
-		if (time_after_eq(jiffies, fip->port_ka_time)) {
-			fip->port_ka_time = jiffies +
-				msecs_to_jiffies(FIP_VN_KA_PERIOD);
-			send_port_ka = 1;
-		}
-		if (time_after(next_timer, fip->port_ka_time))
-			next_timer = fip->port_ka_time;
-	}
-	if (!list_empty(&fip->fcfs))
-		mod_timer(&fip->timer, next_timer);
-	mutex_unlock(&fip->ctlr_mutex);
-
-	if (reset) {
-		fc_lport_reset(fip->lp);
-		/* restart things with a solicitation */
-		fcoe_ctlr_solicit(fip, NULL);
-	}
-
-	if (send_ctlr_ka)
-		fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr);
-
-	if (send_port_ka) {
-		mutex_lock(&fip->lp->lp_mutex);
-		mac = fip->get_src_addr(fip->lp);
-		fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac);
-		list_for_each_entry(vport, &fip->lp->vports, list) {
-			mac = fip->get_src_addr(vport);
-			fcoe_ctlr_send_keep_alive(fip, vport, 1, mac);
-		}
-		mutex_unlock(&fip->lp->lp_mutex);
-	}
-}
-
-/**
- * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames
- * @recv_work: Handle to a FCoE controller
- */
-static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
-{
-	struct fcoe_ctlr *fip;
-	struct sk_buff *skb;
-
-	fip = container_of(recv_work, struct fcoe_ctlr, recv_work);
-	while ((skb = skb_dequeue(&fip->fip_recv_list)))
-		fcoe_ctlr_recv_handler(fip, skb);
-}
-
-/**
- * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response
- * @fip: The FCoE controller
- * @fp:	 The FC frame to snoop
- *
- * Snoop potential response to FLOGI or even incoming FLOGI.
- *
- * The caller has checked that we are waiting for login as indicated
- * by fip->flogi_oxid != FC_XID_UNKNOWN.
- *
- * The caller is responsible for freeing the frame.
- * Fill in the granted_mac address.
- *
- * Return non-zero if the frame should not be delivered to libfc.
- */
-int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport,
-			 struct fc_frame *fp)
-{
-	struct fc_frame_header *fh;
-	u8 op;
-	u8 *sa;
-
-	sa = eth_hdr(&fp->skb)->h_source;
-	fh = fc_frame_header_get(fp);
-	if (fh->fh_type != FC_TYPE_ELS)
-		return 0;
-
-	op = fc_frame_payload_op(fp);
-	if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
-	    fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
-
-		mutex_lock(&fip->ctlr_mutex);
-		if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) {
-			mutex_unlock(&fip->ctlr_mutex);
-			return -EINVAL;
-		}
-		fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
-		LIBFCOE_FIP_DBG(fip,
-				"received FLOGI LS_ACC using non-FIP mode\n");
-
-		/*
-		 * FLOGI accepted.
-		 * If the src mac addr is FC_OUI-based, then we mark the
-		 * address_mode flag to use FC_OUI-based Ethernet DA.
-		 * Otherwise we use the FCoE gateway addr
-		 */
-		if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) {
-			fcoe_ctlr_map_dest(fip);
-		} else {
-			memcpy(fip->dest_addr, sa, ETH_ALEN);
-			fip->map_dest = 0;
-		}
-		fip->flogi_oxid = FC_XID_UNKNOWN;
-		mutex_unlock(&fip->ctlr_mutex);
-		fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id);
-	} else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
-		/*
-		 * Save source MAC for point-to-point responses.
-		 */
-		mutex_lock(&fip->ctlr_mutex);
-		if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
-			memcpy(fip->dest_addr, sa, ETH_ALEN);
-			fip->map_dest = 0;
-			if (fip->state == FIP_ST_AUTO)
-				LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. "
-						"Setting non-FIP mode\n");
-			fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
-		}
-		mutex_unlock(&fip->ctlr_mutex);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(fcoe_ctlr_recv_flogi);
-
-/**
- * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN
- * @mac:    The MAC address to convert
- * @scheme: The scheme to use when converting
- * @port:   The port indicator for converting
- *
- * Returns: u64 fc world wide name
- */
-u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
-		      unsigned int scheme, unsigned int port)
-{
-	u64 wwn;
-	u64 host_mac;
-
-	/* The MAC is in NO, so flip only the low 48 bits */
-	host_mac = ((u64) mac[0] << 40) |
-		((u64) mac[1] << 32) |
-		((u64) mac[2] << 24) |
-		((u64) mac[3] << 16) |
-		((u64) mac[4] << 8) |
-		(u64) mac[5];
-
-	WARN_ON(host_mac >= (1ULL << 48));
-	wwn = host_mac | ((u64) scheme << 60);
-	switch (scheme) {
-	case 1:
-		WARN_ON(port != 0);
-		break;
-	case 2:
-		WARN_ON(port >= 0xfff);
-		wwn |= (u64) port << 48;
-		break;
-	default:
-		WARN_ON(1);
-		break;
-	}
-
-	return wwn;
-}
-EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
-
-/**
- * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv
- * @rdata: libfc remote port
- */
-static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
-{
-	return (struct fcoe_rport *)(rdata + 1);
-}
-
-/**
- * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply.
- * @fip: The FCoE controller
- * @sub: sub-opcode for probe request, reply, or advertisement.
- * @dest: The destination Ethernet MAC address
- * @min_len: minimum size of the Ethernet payload to be sent
- */
-static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
-			      enum fip_vn2vn_subcode sub,
-			      const u8 *dest, size_t min_len)
-{
-	struct sk_buff *skb;
-	struct fip_frame {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct fip_mac_desc mac;
-		struct fip_wwn_desc wwnn;
-		struct fip_vn_desc vn;
-	} __attribute__((packed)) *frame;
-	struct fip_fc4_feat *ff;
-	struct fip_size_desc *size;
-	u32 fcp_feat;
-	size_t len;
-	size_t dlen;
-
-	len = sizeof(*frame);
-	dlen = 0;
-	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
-		dlen = sizeof(struct fip_fc4_feat) +
-		       sizeof(struct fip_size_desc);
-		len += dlen;
-	}
-	dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn);
-	len = max(len, min_len + sizeof(struct ethhdr));
-
-	skb = dev_alloc_skb(len);
-	if (!skb)
-		return;
-
-	frame = (struct fip_frame *)skb->data;
-	memset(frame, 0, len);
-	memcpy(frame->eth.h_dest, dest, ETH_ALEN);
-	memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
-	frame->eth.h_proto = htons(ETH_P_FIP);
-
-	frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	frame->fip.fip_op = htons(FIP_OP_VN2VN);
-	frame->fip.fip_subcode = sub;
-	frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
-
-	frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
-	frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
-	memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-
-	frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
-	frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW;
-	put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn);
-
-	frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID;
-	frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW;
-	hton24(frame->vn.fd_mac, FIP_VN_FC_MAP);
-	hton24(frame->vn.fd_mac + 3, fip->port_id);
-	hton24(frame->vn.fd_fc_id, fip->port_id);
-	put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn);
-
-	/*
-	 * For claims, add FC-4 features.
-	 * TBD: Add interface to get fc-4 types and features from libfc.
-	 */
-	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
-		ff = (struct fip_fc4_feat *)(frame + 1);
-		ff->fd_desc.fip_dtype = FIP_DT_FC4F;
-		ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW;
-		ff->fd_fts = fip->lp->fcts;
-
-		fcp_feat = 0;
-		if (fip->lp->service_params & FCP_SPPF_INIT_FCN)
-			fcp_feat |= FCP_FEAT_INIT;
-		if (fip->lp->service_params & FCP_SPPF_TARG_FCN)
-			fcp_feat |= FCP_FEAT_TARG;
-		fcp_feat <<= (FC_TYPE_FCP * 4) % 32;
-		ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat);
-
-		size = (struct fip_size_desc *)(ff + 1);
-		size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
-		size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW;
-		size->fd_size = htons(fcoe_ctlr_fcoe_size(fip));
-	}
-
-	skb_put(skb, len);
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-
-	fip->send(fip, skb);
-}
-
-/**
- * fcoe_ctlr_vn_rport_callback - Event handler for rport events.
- * @lport: The lport which is receiving the event
- * @rdata: remote port private data
- * @event: The event that occured
- *
- * Locking Note:  The rport lock must not be held when calling this function.
- */
-static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport,
-					struct fc_rport_priv *rdata,
-					enum fc_rport_event event)
-{
-	struct fcoe_ctlr *fip = lport->disc.priv;
-	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
-
-	LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n",
-			rdata->ids.port_id, event);
-
-	mutex_lock(&fip->ctlr_mutex);
-	switch (event) {
-	case RPORT_EV_READY:
-		frport->login_count = 0;
-		break;
-	case RPORT_EV_LOGO:
-	case RPORT_EV_FAILED:
-	case RPORT_EV_STOP:
-		frport->login_count++;
-		if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) {
-			LIBFCOE_FIP_DBG(fip,
-					"rport FLOGI limited port_id %6.6x\n",
-					rdata->ids.port_id);
-			lport->tt.rport_logoff(rdata);
-		}
-		break;
-	default:
-		break;
-	}
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = {
-	.event_callback = fcoe_ctlr_vn_rport_callback,
-};
-
-/**
- * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
-{
-	mutex_lock(&lport->disc.disc_mutex);
-	lport->disc.disc_callback = NULL;
-	mutex_unlock(&lport->disc.disc_mutex);
-}
-
-/**
- * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called through the local port template for discovery.
- * Called without the ctlr_mutex held.
- */
-static void fcoe_ctlr_disc_stop(struct fc_lport *lport)
-{
-	struct fcoe_ctlr *fip = lport->disc.priv;
-
-	mutex_lock(&fip->ctlr_mutex);
-	fcoe_ctlr_disc_stop_locked(lport);
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-/**
- * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called through the local port template for discovery.
- * Called without the ctlr_mutex held.
- */
-static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport)
-{
-	fcoe_ctlr_disc_stop(lport);
-	lport->tt.rport_flush_queue();
-	synchronize_rcu();
-}
-
-/**
- * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id
- * @fip: The FCoE controller
- *
- * Called with fcoe_ctlr lock held.
- */
-static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
-{
-	unsigned long wait;
-	u32 port_id;
-
-	fcoe_ctlr_disc_stop_locked(fip->lp);
-
-	/*
-	 * Get proposed port ID.
-	 * If this is the first try after link up, use any previous port_id.
-	 * If there was none, use the low bits of the port_name.
-	 * On subsequent tries, get the next random one.
-	 * Don't use reserved IDs, use another non-zero value, just as random.
-	 */
-	port_id = fip->port_id;
-	if (fip->probe_tries)
-		port_id = prandom32(&fip->rnd_state) & 0xffff;
-	else if (!port_id)
-		port_id = fip->lp->wwpn & 0xffff;
-	if (!port_id || port_id == 0xffff)
-		port_id = 1;
-	fip->port_id = port_id;
-
-	if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
-		fip->probe_tries++;
-		wait = random32() % FIP_VN_PROBE_WAIT;
-	} else
-		wait = FIP_VN_RLIM_INT;
-	mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
-	fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START);
-}
-
-/**
- * fcoe_ctlr_vn_start() - Start in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called with fcoe_ctlr lock held.
- */
-static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
-{
-	fip->probe_tries = 0;
-	prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
-	fcoe_ctlr_vn_restart(fip);
-}
-
-/**
- * fcoe_ctlr_vn_parse - parse probe request or response
- * @fip: The FCoE controller
- * @skb: incoming packet
- * @rdata: buffer for resulting parsed VN entry plus fcoe_rport
- *
- * Returns non-zero error number on error.
- * Does not consume the packet.
- */
-static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
-			      struct sk_buff *skb,
-			      struct fc_rport_priv *rdata)
-{
-	struct fip_header *fiph;
-	struct fip_desc *desc = NULL;
-	struct fip_mac_desc *macd = NULL;
-	struct fip_wwn_desc *wwn = NULL;
-	struct fip_vn_desc *vn = NULL;
-	struct fip_size_desc *size = NULL;
-	struct fcoe_rport *frport;
-	size_t rlen;
-	size_t dlen;
-	u32 desc_mask = 0;
-	u32 dtype;
-	u8 sub;
-
-	memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
-	frport = fcoe_ctlr_rport(rdata);
-
-	fiph = (struct fip_header *)skb->data;
-	frport->flags = ntohs(fiph->fip_flags);
-
-	sub = fiph->fip_subcode;
-	switch (sub) {
-	case FIP_SC_VN_PROBE_REQ:
-	case FIP_SC_VN_PROBE_REP:
-	case FIP_SC_VN_BEACON:
-		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
-			    BIT(FIP_DT_VN_ID);
-		break;
-	case FIP_SC_VN_CLAIM_NOTIFY:
-	case FIP_SC_VN_CLAIM_REP:
-		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
-			    BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) |
-			    BIT(FIP_DT_FCOE_SIZE);
-		break;
-	default:
-		LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
-		return -EINVAL;
-	}
-
-	rlen = ntohs(fiph->fip_dl_len) * 4;
-	if (rlen + sizeof(*fiph) > skb->len)
-		return -EINVAL;
-
-	desc = (struct fip_desc *)(fiph + 1);
-	while (rlen > 0) {
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen < sizeof(*desc) || dlen > rlen)
-			return -EINVAL;
-
-		dtype = desc->fip_dtype;
-		if (dtype < 32) {
-			if (!(desc_mask & BIT(dtype))) {
-				LIBFCOE_FIP_DBG(fip,
-						"unexpected or duplicated desc "
-						"desc type %u in "
-						"FIP VN2VN subtype %u\n",
-						dtype, sub);
-				return -EINVAL;
-			}
-			desc_mask &= ~BIT(dtype);
-		}
-
-		switch (dtype) {
-		case FIP_DT_MAC:
-			if (dlen != sizeof(struct fip_mac_desc))
-				goto len_err;
-			macd = (struct fip_mac_desc *)desc;
-			if (!is_valid_ether_addr(macd->fd_mac)) {
-				LIBFCOE_FIP_DBG(fip,
-					"Invalid MAC addr %pM in FIP VN2VN\n",
-					 macd->fd_mac);
-				return -EINVAL;
-			}
-			memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
-			break;
-		case FIP_DT_NAME:
-			if (dlen != sizeof(struct fip_wwn_desc))
-				goto len_err;
-			wwn = (struct fip_wwn_desc *)desc;
-			rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
-			break;
-		case FIP_DT_VN_ID:
-			if (dlen != sizeof(struct fip_vn_desc))
-				goto len_err;
-			vn = (struct fip_vn_desc *)desc;
-			memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
-			rdata->ids.port_id = ntoh24(vn->fd_fc_id);
-			rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
-			break;
-		case FIP_DT_FC4F:
-			if (dlen != sizeof(struct fip_fc4_feat))
-				goto len_err;
-			break;
-		case FIP_DT_FCOE_SIZE:
-			if (dlen != sizeof(struct fip_size_desc))
-				goto len_err;
-			size = (struct fip_size_desc *)desc;
-			frport->fcoe_len = ntohs(size->fd_size);
-			break;
-		default:
-			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
-					"in FIP probe\n", dtype);
-			/* standard says ignore unknown descriptors >= 128 */
-			if (dtype < FIP_DT_VENDOR_BASE)
-				return -EINVAL;
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-	return 0;
-
-len_err:
-	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
-			dtype, dlen);
-	return -EINVAL;
-}
-
-/**
- * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification.
- * @fip: The FCoE controller
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
-{
-	fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0);
-	fip->sol_time = jiffies;
-}
-
-/**
- * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
- * @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
-				   struct fc_rport_priv *rdata)
-{
-	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
-
-	if (rdata->ids.port_id != fip->port_id)
-		return;
-
-	switch (fip->state) {
-	case FIP_ST_VNMP_CLAIM:
-	case FIP_ST_VNMP_UP:
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
-				  frport->enode_mac, 0);
-		break;
-	case FIP_ST_VNMP_PROBE1:
-	case FIP_ST_VNMP_PROBE2:
-		/*
-		 * Decide whether to reply to the Probe.
-		 * Our selected address is never a "recorded" one, so
-		 * only reply if our WWPN is greater and the
-		 * Probe's REC bit is not set.
-		 * If we don't reply, we will change our address.
-		 */
-		if (fip->lp->wwpn > rdata->ids.port_name &&
-		    !(frport->flags & FIP_FL_REC_OR_P2P)) {
-			fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
-					  frport->enode_mac, 0);
-			break;
-		}
-		/* fall through */
-	case FIP_ST_VNMP_START:
-		fcoe_ctlr_vn_restart(fip);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
- * @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
-				   struct fc_rport_priv *rdata)
-{
-	if (rdata->ids.port_id != fip->port_id)
-		return;
-	switch (fip->state) {
-	case FIP_ST_VNMP_START:
-	case FIP_ST_VNMP_PROBE1:
-	case FIP_ST_VNMP_PROBE2:
-	case FIP_ST_VNMP_CLAIM:
-		fcoe_ctlr_vn_restart(fip);
-		break;
-	case FIP_ST_VNMP_UP:
-		fcoe_ctlr_vn_send_claim(fip);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
- * @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fc_rport_identifiers *ids;
-	struct fcoe_rport *frport;
-	u32 port_id;
-
-	port_id = new->ids.port_id;
-	if (port_id == fip->port_id)
-		return;
-
-	mutex_lock(&lport->disc.disc_mutex);
-	rdata = lport->tt.rport_create(lport, port_id);
-	if (!rdata) {
-		mutex_unlock(&lport->disc.disc_mutex);
-		return;
-	}
-
-	rdata->ops = &fcoe_ctlr_vn_rport_ops;
-	rdata->disc_id = lport->disc.disc_id;
-
-	ids = &rdata->ids;
-	if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
-	    (ids->node_name != -1 && ids->node_name != new->ids.node_name))
-		lport->tt.rport_logoff(rdata);
-	ids->port_name = new->ids.port_name;
-	ids->node_name = new->ids.node_name;
-	mutex_unlock(&lport->disc.disc_mutex);
-
-	frport = fcoe_ctlr_rport(rdata);
-	LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
-			port_id, frport->fcoe_len ? "old" : "new");
-	*frport = *fcoe_ctlr_rport(new);
-	frport->time = 0;
-}
-
-/**
- * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address
- * @fip: The FCoE controller
- * @port_id:  The port_id of the remote VN_node
- * @mac: buffer which will hold the VN_NODE destination MAC address, if found.
- *
- * Returns non-zero error if no remote port found.
- */
-static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-	int ret = -1;
-
-	rcu_read_lock();
-	rdata = lport->tt.rport_lookup(lport, port_id);
-	if (rdata) {
-		frport = fcoe_ctlr_rport(rdata);
-		memcpy(mac, frport->enode_mac, ETH_ALEN);
-		ret = 0;
-	}
-	rcu_read_unlock();
-	return ret;
-}
-
-/**
- * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
- * @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
-				      struct fc_rport_priv *new)
-{
-	struct fcoe_rport *frport = fcoe_ctlr_rport(new);
-
-	if (frport->flags & FIP_FL_REC_OR_P2P) {
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		return;
-	}
-	switch (fip->state) {
-	case FIP_ST_VNMP_START:
-	case FIP_ST_VNMP_PROBE1:
-	case FIP_ST_VNMP_PROBE2:
-		if (new->ids.port_id == fip->port_id)
-			fcoe_ctlr_vn_restart(fip);
-		break;
-	case FIP_ST_VNMP_CLAIM:
-	case FIP_ST_VNMP_UP:
-		if (new->ids.port_id == fip->port_id) {
-			if (new->ids.port_name > fip->lp->wwpn) {
-				fcoe_ctlr_vn_restart(fip);
-				break;
-			}
-			fcoe_ctlr_vn_send_claim(fip);
-			break;
-		}
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
-				  min((u32)frport->fcoe_len,
-				      fcoe_ctlr_fcoe_size(fip)));
-		fcoe_ctlr_vn_add(fip, new);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- * fcoe_ctlr_vn_claim_resp() - handle received Claim Response
- * @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Claim Response
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
-				    struct fc_rport_priv *new)
-{
-	LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
-			new->ids.port_id, fcoe_ctlr_state(fip->state));
-	if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
-		fcoe_ctlr_vn_add(fip, new);
-}
-
-/**
- * fcoe_ctlr_vn_beacon() - handle received beacon.
- * @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Beacon
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
-				struct fc_rport_priv *new)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-
-	frport = fcoe_ctlr_rport(new);
-	if (frport->flags & FIP_FL_REC_OR_P2P) {
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		return;
-	}
-	mutex_lock(&lport->disc.disc_mutex);
-	rdata = lport->tt.rport_lookup(lport, new->ids.port_id);
-	if (rdata)
-		kref_get(&rdata->kref);
-	mutex_unlock(&lport->disc.disc_mutex);
-	if (rdata) {
-		if (rdata->ids.node_name == new->ids.node_name &&
-		    rdata->ids.port_name == new->ids.port_name) {
-			frport = fcoe_ctlr_rport(rdata);
-			if (!frport->time && fip->state == FIP_ST_VNMP_UP)
-				lport->tt.rport_login(rdata);
-			frport->time = jiffies;
-		}
-		kref_put(&rdata->kref, lport->tt.rport_destroy);
-		return;
-	}
-	if (fip->state != FIP_ST_VNMP_UP)
-		return;
-
-	/*
-	 * Beacon from a new neighbor.
-	 * Send a claim notify if one hasn't been sent recently.
-	 * Don't add the neighbor yet.
-	 */
-	LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
-			new->ids.port_id);
-	if (time_after(jiffies,
-		       fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
-		fcoe_ctlr_vn_send_claim(fip);
-}
-
-/**
- * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons
- * @fip: The FCoE controller
- *
- * Called with ctlr_mutex held.
- * Called only in state FIP_ST_VNMP_UP.
- * Returns the soonest time for next age-out or a time far in the future.
- */
-static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-	unsigned long next_time;
-	unsigned long deadline;
-
-	next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
-	mutex_lock(&lport->disc.disc_mutex);
-	list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
-		frport = fcoe_ctlr_rport(rdata);
-		if (!frport->time)
-			continue;
-		deadline = frport->time +
-			   msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
-		if (time_after_eq(jiffies, deadline)) {
-			frport->time = 0;
-			LIBFCOE_FIP_DBG(fip,
-				"port %16.16llx fc_id %6.6x beacon expired\n",
-				rdata->ids.port_name, rdata->ids.port_id);
-			lport->tt.rport_logoff(rdata);
-		} else if (time_before(deadline, next_time))
-			next_time = deadline;
-	}
-	mutex_unlock(&lport->disc.disc_mutex);
-	return next_time;
-}
-
-/**
- * fcoe_ctlr_vn_recv() - Receive a FIP frame
- * @fip: The FCoE controller that received the frame
- * @skb: The received FIP frame
- *
- * Returns non-zero if the frame is dropped.
- * Always consumes the frame.
- */
-static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fip_header *fiph;
-	enum fip_vn2vn_subcode sub;
-	struct {
-		struct fc_rport_priv rdata;
-		struct fcoe_rport frport;
-	} buf;
-	int rc;
-
-	fiph = (struct fip_header *)skb->data;
-	sub = fiph->fip_subcode;
-
-	rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
-	if (rc) {
-		LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
-		goto drop;
-	}
-
-	mutex_lock(&fip->ctlr_mutex);
-	switch (sub) {
-	case FIP_SC_VN_PROBE_REQ:
-		fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_PROBE_REP:
-		fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_CLAIM_NOTIFY:
-		fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_CLAIM_REP:
-		fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_BEACON:
-		fcoe_ctlr_vn_beacon(fip, &buf.rdata);
-		break;
-	default:
-		LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
-		rc = -1;
-		break;
-	}
-	mutex_unlock(&fip->ctlr_mutex);
-drop:
-	kfree_skb(skb);
-	return rc;
-}
-
-/**
- * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
- * @lport: The local port
- * @fp: The received frame
- *
- * This should never be called since we don't see RSCNs or other
- * fabric-generated ELSes.
- */
-static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp)
-{
-	struct fc_seq_els_data rjt_data;
-
-	rjt_data.reason = ELS_RJT_UNSUP;
-	rjt_data.explan = ELS_EXPL_NONE;
-	lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
-	fc_frame_free(fp);
-}
-
-/**
- * fcoe_ctlr_disc_recv - start discovery for VN2VN mode.
- * @fip: The FCoE controller
- *
- * This sets a flag indicating that remote ports should be created
- * and started for the peers we discover.  We use the disc_callback
- * pointer as that flag.  Peers already discovered are created here.
- *
- * The lport lock is held during this call. The callback must be done
- * later, without holding either the lport or discovery locks.
- * The fcoe_ctlr lock may also be held during this call.
- */
-static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *,
-						  enum fc_disc_event),
-				 struct fc_lport *lport)
-{
-	struct fc_disc *disc = &lport->disc;
-	struct fcoe_ctlr *fip = disc->priv;
-
-	mutex_lock(&disc->disc_mutex);
-	disc->disc_callback = callback;
-	disc->disc_id = (disc->disc_id + 2) | 1;
-	disc->pending = 1;
-	schedule_work(&fip->timer_work);
-	mutex_unlock(&disc->disc_mutex);
-}
-
-/**
- * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state.
- * @fip: The FCoE controller
- *
- * Starts the FLOGI and PLOGI login process to each discovered rport for which
- * we've received at least one beacon.
- * Performs the discovery complete callback.
- */
-static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_disc *disc = &lport->disc;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-	void (*callback)(struct fc_lport *, enum fc_disc_event);
-
-	mutex_lock(&disc->disc_mutex);
-	callback = disc->pending ? disc->disc_callback : NULL;
-	disc->pending = 0;
-	list_for_each_entry_rcu(rdata, &disc->rports, peers) {
-		frport = fcoe_ctlr_rport(rdata);
-		if (frport->time)
-			lport->tt.rport_login(rdata);
-	}
-	mutex_unlock(&disc->disc_mutex);
-	if (callback)
-		callback(lport, DISC_EV_SUCCESS);
-}
-
-/**
- * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode.
- * @fip: The FCoE controller
- */
-static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
-{
-	unsigned long next_time;
-	u8 mac[ETH_ALEN];
-	u32 new_port_id = 0;
-
-	mutex_lock(&fip->ctlr_mutex);
-	switch (fip->state) {
-	case FIP_ST_VNMP_START:
-		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
-		break;
-	case FIP_ST_VNMP_PROBE1:
-		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-		break;
-	case FIP_ST_VNMP_PROBE2:
-		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM);
-		new_port_id = fip->port_id;
-		hton24(mac, FIP_VN_FC_MAP);
-		hton24(mac + 3, new_port_id);
-		fcoe_ctlr_map_dest(fip);
-		fip->update_mac(fip->lp, mac);
-		fcoe_ctlr_vn_send_claim(fip);
-		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-		break;
-	case FIP_ST_VNMP_CLAIM:
-		/*
-		 * This may be invoked either by starting discovery so don't
-		 * go to the next state unless it's been long enough.
-		 */
-		next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-		if (time_after_eq(jiffies, next_time)) {
-			fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
-			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
-					  fcoe_all_vn2vn, 0);
-			next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-			fip->port_ka_time = next_time;
-		}
-		fcoe_ctlr_vn_disc(fip);
-		break;
-	case FIP_ST_VNMP_UP:
-		next_time = fcoe_ctlr_vn_age(fip);
-		if (time_after_eq(jiffies, fip->port_ka_time)) {
-			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
-					  fcoe_all_vn2vn, 0);
-			fip->port_ka_time = jiffies +
-				 msecs_to_jiffies(FIP_VN_BEACON_INT +
-					(random32() % FIP_VN_BEACON_FUZZ));
-		}
-		if (time_before(fip->port_ka_time, next_time))
-			next_time = fip->port_ka_time;
-		break;
-	case FIP_ST_LINK_WAIT:
-		goto unlock;
-	default:
-		WARN(1, "unexpected state %d\n", fip->state);
-		goto unlock;
-	}
-	mod_timer(&fip->timer, next_time);
-unlock:
-	mutex_unlock(&fip->ctlr_mutex);
-
-	/* If port ID is new, notify local port after dropping ctlr_mutex */
-	if (new_port_id)
-		fc_lport_set_local_id(fip->lp, new_port_id);
-}
-
-/**
- * fcoe_libfc_config() - Sets up libfc related properties for local port
- * @lp: The local port to configure libfc for
- * @fip: The FCoE controller in use by the local port
- * @tt: The libfc function template
- * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
- *
- * Returns : 0 for success
- */
-int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
-		      const struct libfc_function_template *tt, int init_fcp)
-{
-	/* Set the function pointers set by the LLDD */
-	memcpy(&lport->tt, tt, sizeof(*tt));
-	if (init_fcp && fc_fcp_init(lport))
-		return -ENOMEM;
-	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);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_libfc_config);
diff --git a/drivers/scsi/fcoe/libfcoe.h b/drivers/scsi/fcoe/libfcoe.h
new file mode 100644
index 0000000..6af5fc3
--- /dev/null
+++ b/drivers/scsi/fcoe/libfcoe.h
@@ -0,0 +1,31 @@
+#ifndef _FCOE_LIBFCOE_H_
+#define _FCOE_LIBFCOE_H_
+
+extern unsigned int libfcoe_debug_logging;
+#define LIBFCOE_LOGGING	    0x01 /* General logging, not categorized */
+#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
+#define LIBFCOE_TRANSPORT_LOGGING	0x04 /* FCoE transport logging */
+
+#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD)		\
+do {							\
+	if (unlikely(libfcoe_debug_logging & LEVEL))	\
+		do {					\
+			CMD;				\
+		} while (0);				\
+} while (0)
+
+#define LIBFCOE_DBG(fmt, args...)					\
+	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\
+			      printk(KERN_INFO "libfcoe: " fmt, ##args);)
+
+#define LIBFCOE_FIP_DBG(fip, fmt, args...)				\
+	LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING,			\
+			      printk(KERN_INFO "host%d: fip: " fmt,	\
+				     (fip)->lp->host->host_no, ##args);)
+
+#define LIBFCOE_TRANSPORT_DBG(fmt, args...)				\
+	LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING,		\
+			      printk(KERN_INFO "%s: " fmt,		\
+				     __func__, ##args);)
+
+#endif /* _FCOE_LIBFCOE_H_ */
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 92f1850..671cde9 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -37,7 +37,7 @@
 
 #define DRV_NAME		"fnic"
 #define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
-#define DRV_VERSION		"1.4.0.145"
+#define DRV_VERSION		"1.5.0.1"
 #define PFX			DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
diff --git a/drivers/scsi/fnic/vnic_dev.c b/drivers/scsi/fnic/vnic_dev.c
index db71014..b576be7 100644
--- a/drivers/scsi/fnic/vnic_dev.c
+++ b/drivers/scsi/fnic/vnic_dev.c
@@ -654,7 +654,7 @@ void vnic_dev_unregister(struct vnic_dev *vdev)
 				vdev->linkstatus_pa);
 		if (vdev->stats)
 			pci_free_consistent(vdev->pdev,
-				sizeof(struct vnic_dev),
+				sizeof(struct vnic_stats),
 				vdev->stats, vdev->stats_pa);
 		if (vdev->fw_info)
 			pci_free_consistent(vdev->pdev,
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 12deffc..415ad4f 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -74,6 +74,10 @@ static int hpsa_allow_any;
 module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(hpsa_allow_any,
 		"Allow hpsa driver to access unknown HP Smart Array hardware");
+static int hpsa_simple_mode;
+module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hpsa_simple_mode,
+	"Use 'simple mode' rather than 'performant mode'");
 
 /* define the PCI info for the cards we can control */
 static const struct pci_device_id hpsa_pci_device_id[] = {
@@ -85,11 +89,13 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324a},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324b},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3233},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3250},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3251},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3350},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3351},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3352},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3353},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3354},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3355},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3356},
 	{PCI_VENDOR_ID_HP,     PCI_ANY_ID,	PCI_ANY_ID, PCI_ANY_ID,
 		PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
 	{0,}
@@ -109,11 +115,13 @@ static struct board_type products[] = {
 	{0x3249103C, "Smart Array P812", &SA5_access},
 	{0x324a103C, "Smart Array P712m", &SA5_access},
 	{0x324b103C, "Smart Array P711m", &SA5_access},
-	{0x3250103C, "Smart Array", &SA5_access},
-	{0x3250113C, "Smart Array", &SA5_access},
-	{0x3250123C, "Smart Array", &SA5_access},
-	{0x3250133C, "Smart Array", &SA5_access},
-	{0x3250143C, "Smart Array", &SA5_access},
+	{0x3350103C, "Smart Array", &SA5_access},
+	{0x3351103C, "Smart Array", &SA5_access},
+	{0x3352103C, "Smart Array", &SA5_access},
+	{0x3353103C, "Smart Array", &SA5_access},
+	{0x3354103C, "Smart Array", &SA5_access},
+	{0x3355103C, "Smart Array", &SA5_access},
+	{0x3356103C, "Smart Array", &SA5_access},
 	{0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
@@ -147,17 +155,7 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
 static int hpsa_slave_alloc(struct scsi_device *sdev);
 static void hpsa_slave_destroy(struct scsi_device *sdev);
 
-static ssize_t raid_level_show(struct device *dev,
-	struct device_attribute *attr, char *buf);
-static ssize_t lunid_show(struct device *dev,
-	struct device_attribute *attr, char *buf);
-static ssize_t unique_id_show(struct device *dev,
-	struct device_attribute *attr, char *buf);
-static ssize_t host_show_firmware_revision(struct device *dev,
-	     struct device_attribute *attr, char *buf);
 static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
-static ssize_t host_store_rescan(struct device *dev,
-	 struct device_attribute *attr, const char *buf, size_t count);
 static int check_for_unit_attention(struct ctlr_info *h,
 	struct CommandList *c);
 static void check_ioctl_unit_attention(struct ctlr_info *h,
@@ -173,47 +171,10 @@ static int __devinit hpsa_find_cfg_addrs(struct pci_dev *pdev,
 static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
 	unsigned long *memory_bar);
 static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
-
-static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
-static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
-static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
-static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
-static DEVICE_ATTR(firmware_revision, S_IRUGO,
-	host_show_firmware_revision, NULL);
-
-static struct device_attribute *hpsa_sdev_attrs[] = {
-	&dev_attr_raid_level,
-	&dev_attr_lunid,
-	&dev_attr_unique_id,
-	NULL,
-};
-
-static struct device_attribute *hpsa_shost_attrs[] = {
-	&dev_attr_rescan,
-	&dev_attr_firmware_revision,
-	NULL,
-};
-
-static struct scsi_host_template hpsa_driver_template = {
-	.module			= THIS_MODULE,
-	.name			= "hpsa",
-	.proc_name		= "hpsa",
-	.queuecommand		= hpsa_scsi_queue_command,
-	.scan_start		= hpsa_scan_start,
-	.scan_finished		= hpsa_scan_finished,
-	.change_queue_depth	= hpsa_change_queue_depth,
-	.this_id		= -1,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.eh_device_reset_handler = hpsa_eh_device_reset_handler,
-	.ioctl			= hpsa_ioctl,
-	.slave_alloc		= hpsa_slave_alloc,
-	.slave_destroy		= hpsa_slave_destroy,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl		= hpsa_compat_ioctl,
-#endif
-	.sdev_attrs = hpsa_sdev_attrs,
-	.shost_attrs = hpsa_shost_attrs,
-};
+static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
+	void __iomem *vaddr, int wait_for_ready);
+#define BOARD_NOT_READY 0
+#define BOARD_READY 1
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
 {
@@ -291,67 +252,63 @@ static ssize_t host_show_firmware_revision(struct device *dev,
 		fwrev[0], fwrev[1], fwrev[2], fwrev[3]);
 }
 
-/* Enqueuing and dequeuing functions for cmdlists. */
-static inline void addQ(struct hlist_head *list, struct CommandList *c)
+static ssize_t host_show_commands_outstanding(struct device *dev,
+	     struct device_attribute *attr, char *buf)
 {
-	hlist_add_head(&c->list, list);
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct ctlr_info *h = shost_to_hba(shost);
+
+	return snprintf(buf, 20, "%d\n", h->commands_outstanding);
 }
 
-static inline u32 next_command(struct ctlr_info *h)
+static ssize_t host_show_transport_mode(struct device *dev,
+	struct device_attribute *attr, char *buf)
 {
-	u32 a;
-
-	if (unlikely(h->transMethod != CFGTBL_Trans_Performant))
-		return h->access.command_completed(h);
+	struct ctlr_info *h;
+	struct Scsi_Host *shost = class_to_shost(dev);
 
-	if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
-		a = *(h->reply_pool_head); /* Next cmd in ring buffer */
-		(h->reply_pool_head)++;
-		h->commands_outstanding--;
-	} else {
-		a = FIFO_EMPTY;
-	}
-	/* Check for wraparound */
-	if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
-		h->reply_pool_head = h->reply_pool;
-		h->reply_pool_wraparound ^= 1;
-	}
-	return a;
+	h = shost_to_hba(shost);
+	return snprintf(buf, 20, "%s\n",
+		h->transMethod & CFGTBL_Trans_Performant ?
+			"performant" : "simple");
 }
 
-/* set_performant_mode: Modify the tag for cciss performant
- * set bit 0 for pull model, bits 3-1 for block fetch
- * register number
- */
-static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
-{
-	if (likely(h->transMethod == CFGTBL_Trans_Performant))
-		c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
-}
+/* List of controllers which cannot be reset on kexec with reset_devices */
+static u32 unresettable_controller[] = {
+	0x324a103C, /* Smart Array P712m */
+	0x324b103C, /* SmartArray P711m */
+	0x3223103C, /* Smart Array P800 */
+	0x3234103C, /* Smart Array P400 */
+	0x3235103C, /* Smart Array P400i */
+	0x3211103C, /* Smart Array E200i */
+	0x3212103C, /* Smart Array E200 */
+	0x3213103C, /* Smart Array E200i */
+	0x3214103C, /* Smart Array E200i */
+	0x3215103C, /* Smart Array E200i */
+	0x3237103C, /* Smart Array E500 */
+	0x323D103C, /* Smart Array P700m */
+	0x409C0E11, /* Smart Array 6400 */
+	0x409D0E11, /* Smart Array 6400 EM */
+};
 
-static void enqueue_cmd_and_start_io(struct ctlr_info *h,
-	struct CommandList *c)
+static int ctlr_is_resettable(struct ctlr_info *h)
 {
-	unsigned long flags;
+	int i;
 
-	set_performant_mode(h, c);
-	spin_lock_irqsave(&h->lock, flags);
-	addQ(&h->reqQ, c);
-	h->Qdepth++;
-	start_io(h);
-	spin_unlock_irqrestore(&h->lock, flags);
+	for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++)
+		if (unresettable_controller[i] == h->board_id)
+			return 0;
+	return 1;
 }
 
-static inline void removeQ(struct CommandList *c)
+static ssize_t host_show_resettable(struct device *dev,
+	struct device_attribute *attr, char *buf)
 {
-	if (WARN_ON(hlist_unhashed(&c->list)))
-		return;
-	hlist_del_init(&c->list);
-}
+	struct ctlr_info *h;
+	struct Scsi_Host *shost = class_to_shost(dev);
 
-static inline int is_hba_lunid(unsigned char scsi3addr[])
-{
-	return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0;
+	h = shost_to_hba(shost);
+	return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
 }
 
 static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
@@ -359,15 +316,6 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
 	return (scsi3addr[3] & 0xC0) == 0x40;
 }
 
-static inline int is_scsi_rev_5(struct ctlr_info *h)
-{
-	if (!h->hba_inquiry_data)
-		return 0;
-	if ((h->hba_inquiry_data[2] & 0x07) == 5)
-		return 1;
-	return 0;
-}
-
 static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
 	"UNKNOWN"
 };
@@ -459,6 +407,129 @@ static ssize_t unique_id_show(struct device *dev,
 			sn[12], sn[13], sn[14], sn[15]);
 }
 
+static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
+static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
+static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
+static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
+static DEVICE_ATTR(firmware_revision, S_IRUGO,
+	host_show_firmware_revision, NULL);
+static DEVICE_ATTR(commands_outstanding, S_IRUGO,
+	host_show_commands_outstanding, NULL);
+static DEVICE_ATTR(transport_mode, S_IRUGO,
+	host_show_transport_mode, NULL);
+static DEVICE_ATTR(resettable, S_IRUGO,
+	host_show_resettable, NULL);
+
+static struct device_attribute *hpsa_sdev_attrs[] = {
+	&dev_attr_raid_level,
+	&dev_attr_lunid,
+	&dev_attr_unique_id,
+	NULL,
+};
+
+static struct device_attribute *hpsa_shost_attrs[] = {
+	&dev_attr_rescan,
+	&dev_attr_firmware_revision,
+	&dev_attr_commands_outstanding,
+	&dev_attr_transport_mode,
+	&dev_attr_resettable,
+	NULL,
+};
+
+static struct scsi_host_template hpsa_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "hpsa",
+	.proc_name		= "hpsa",
+	.queuecommand		= hpsa_scsi_queue_command,
+	.scan_start		= hpsa_scan_start,
+	.scan_finished		= hpsa_scan_finished,
+	.change_queue_depth	= hpsa_change_queue_depth,
+	.this_id		= -1,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.eh_device_reset_handler = hpsa_eh_device_reset_handler,
+	.ioctl			= hpsa_ioctl,
+	.slave_alloc		= hpsa_slave_alloc,
+	.slave_destroy		= hpsa_slave_destroy,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl		= hpsa_compat_ioctl,
+#endif
+	.sdev_attrs = hpsa_sdev_attrs,
+	.shost_attrs = hpsa_shost_attrs,
+};
+
+
+/* Enqueuing and dequeuing functions for cmdlists. */
+static inline void addQ(struct list_head *list, struct CommandList *c)
+{
+	list_add_tail(&c->list, list);
+}
+
+static inline u32 next_command(struct ctlr_info *h)
+{
+	u32 a;
+
+	if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
+		return h->access.command_completed(h);
+
+	if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
+		a = *(h->reply_pool_head); /* Next cmd in ring buffer */
+		(h->reply_pool_head)++;
+		h->commands_outstanding--;
+	} else {
+		a = FIFO_EMPTY;
+	}
+	/* Check for wraparound */
+	if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
+		h->reply_pool_head = h->reply_pool;
+		h->reply_pool_wraparound ^= 1;
+	}
+	return a;
+}
+
+/* set_performant_mode: Modify the tag for cciss performant
+ * set bit 0 for pull model, bits 3-1 for block fetch
+ * register number
+ */
+static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
+{
+	if (likely(h->transMethod & CFGTBL_Trans_Performant))
+		c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
+}
+
+static void enqueue_cmd_and_start_io(struct ctlr_info *h,
+	struct CommandList *c)
+{
+	unsigned long flags;
+
+	set_performant_mode(h, c);
+	spin_lock_irqsave(&h->lock, flags);
+	addQ(&h->reqQ, c);
+	h->Qdepth++;
+	start_io(h);
+	spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static inline void removeQ(struct CommandList *c)
+{
+	if (WARN_ON(list_empty(&c->list)))
+		return;
+	list_del_init(&c->list);
+}
+
+static inline int is_hba_lunid(unsigned char scsi3addr[])
+{
+	return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0;
+}
+
+static inline int is_scsi_rev_5(struct ctlr_info *h)
+{
+	if (!h->hba_inquiry_data)
+		return 0;
+	if ((h->hba_inquiry_data[2] & 0x07) == 5)
+		return 1;
+	return 0;
+}
+
 static int hpsa_find_target_lun(struct ctlr_info *h,
 	unsigned char scsi3addr[], int bus, int *target, int *lun)
 {
@@ -1130,6 +1201,10 @@ static void complete_scsi_command(struct CommandList *cp,
 		cmd->result = DID_TIME_OUT << 16;
 		dev_warn(&h->pdev->dev, "cp %p timedout\n", cp);
 		break;
+	case CMD_UNABORTABLE:
+		cmd->result = DID_ERROR << 16;
+		dev_warn(&h->pdev->dev, "Command unabortable\n");
+		break;
 	default:
 		cmd->result = DID_ERROR << 16;
 		dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n",
@@ -1160,7 +1235,7 @@ static int hpsa_scsi_detect(struct ctlr_info *h)
 	sh->sg_tablesize = h->maxsgentries;
 	h->scsi_host = sh;
 	sh->hostdata[0] = (unsigned long) h;
-	sh->irq = h->intr[PERF_MODE_INT];
+	sh->irq = h->intr[h->intr_mode];
 	sh->unique_id = sh->irq;
 	error = scsi_add_host(sh, &h->pdev->dev);
 	if (error)
@@ -1295,6 +1370,9 @@ static void hpsa_scsi_interpret_error(struct CommandList *cp)
 	case CMD_TIMEOUT:
 		dev_warn(d, "cp %p timed out\n", cp);
 		break;
+	case CMD_UNABORTABLE:
+		dev_warn(d, "Command unabortable\n");
+		break;
 	default:
 		dev_warn(d, "cp %p returned unknown status %x\n", cp,
 				ei->CommandStatus);
@@ -1595,6 +1673,8 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
 	if (lun == 0) /* if lun is 0, then obviously we have a lun 0. */
 		return 0;
 
+	memset(scsi3addr, 0, 8);
+	scsi3addr[3] = target;
 	if (is_hba_lunid(scsi3addr))
 		return 0; /* Don't add the RAID controller here. */
 
@@ -1609,8 +1689,6 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
 		return 0;
 	}
 
-	memset(scsi3addr, 0, 8);
-	scsi3addr[3] = target;
 	if (hpsa_update_device_info(h, scsi3addr, this_device))
 		return 0;
 	(*nmsa2xxx_enclosures)++;
@@ -2199,7 +2277,7 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
 
 	c->cmdindex = i;
 
-	INIT_HLIST_NODE(&c->list);
+	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (u32) cmd_dma_handle;
 	temp64.val = (u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -2237,7 +2315,7 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
 	}
 	memset(c->err_info, 0, sizeof(*c->err_info));
 
-	INIT_HLIST_NODE(&c->list);
+	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (u32) cmd_dma_handle;
 	temp64.val = (u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -2267,7 +2345,7 @@ static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
 	pci_free_consistent(h->pdev, sizeof(*c->err_info),
 			    c->err_info, (dma_addr_t) temp64.val);
 	pci_free_consistent(h->pdev, sizeof(*c),
-			    c, (dma_addr_t) c->busaddr);
+			    c, (dma_addr_t) (c->busaddr & DIRECT_LOOKUP_MASK));
 }
 
 #ifdef CONFIG_COMPAT
@@ -2281,6 +2359,7 @@ static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
 	int err;
 	u32 cp;
 
+	memset(&arg64, 0, sizeof(arg64));
 	err = 0;
 	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
 			   sizeof(arg64.LUN_info));
@@ -2317,6 +2396,7 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
 	int err;
 	u32 cp;
 
+	memset(&arg64, 0, sizeof(arg64));
 	err = 0;
 	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
 			   sizeof(arg64.LUN_info));
@@ -2433,15 +2513,17 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
 		if (buff == NULL)
 			return -EFAULT;
-	}
-	if (iocommand.Request.Type.Direction == XFER_WRITE) {
-		/* Copy the data into the buffer we created */
-		if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
-			kfree(buff);
-			return -EFAULT;
+		if (iocommand.Request.Type.Direction == XFER_WRITE) {
+			/* Copy the data into the buffer we created */
+			if (copy_from_user(buff, iocommand.buf,
+				iocommand.buf_size)) {
+				kfree(buff);
+				return -EFAULT;
+			}
+		} else {
+			memset(buff, 0, iocommand.buf_size);
 		}
-	} else
-		memset(buff, 0, iocommand.buf_size);
+	}
 	c = cmd_special_alloc(h);
 	if (c == NULL) {
 		kfree(buff);
@@ -2487,8 +2569,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		cmd_special_free(h, c);
 		return -EFAULT;
 	}
-
-	if (iocommand.Request.Type.Direction == XFER_READ) {
+	if (iocommand.Request.Type.Direction == XFER_READ &&
+		iocommand.buf_size > 0) {
 		/* Copy the data out of the buffer we created */
 		if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
 			kfree(buff);
@@ -2581,14 +2663,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 	}
 	c->cmd_type = CMD_IOCTL_PEND;
 	c->Header.ReplyQueue = 0;
-
-	if (ioc->buf_size > 0) {
-		c->Header.SGList = sg_used;
-		c->Header.SGTotal = sg_used;
-	} else {
-		c->Header.SGList = 0;
-		c->Header.SGTotal = 0;
-	}
+	c->Header.SGList = c->Header.SGTotal = sg_used;
 	memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
 	c->Header.Tag.lower = c->busaddr;
 	memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
@@ -2605,7 +2680,8 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		}
 	}
 	hpsa_scsi_do_simple_cmd_core(h, c);
-	hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
+	if (sg_used)
+		hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
 	check_ioctl_unit_attention(h, c);
 	/* Copy the error information out */
 	memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
@@ -2614,7 +2690,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
 		status = -EFAULT;
 		goto cleanup1;
 	}
-	if (ioc->Request.Type.Direction == XFER_READ) {
+	if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) {
 		/* Copy the data out of the buffer we created */
 		BYTE __user *ptr = ioc->buf;
 		for (i = 0; i < sg_used; i++) {
@@ -2810,8 +2886,8 @@ static void start_io(struct ctlr_info *h)
 {
 	struct CommandList *c;
 
-	while (!hlist_empty(&h->reqQ)) {
-		c = hlist_entry(h->reqQ.first, struct CommandList, list);
+	while (!list_empty(&h->reqQ)) {
+		c = list_entry(h->reqQ.next, struct CommandList, list);
 		/* can't do anything if fifo is full */
 		if ((h->access.fifo_full(h))) {
 			dev_warn(&h->pdev->dev, "fifo full\n");
@@ -2867,20 +2943,22 @@ static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
 
 static inline u32 hpsa_tag_contains_index(u32 tag)
 {
-#define DIRECT_LOOKUP_BIT 0x10
 	return tag & DIRECT_LOOKUP_BIT;
 }
 
 static inline u32 hpsa_tag_to_index(u32 tag)
 {
-#define DIRECT_LOOKUP_SHIFT 5
 	return tag >> DIRECT_LOOKUP_SHIFT;
 }
 
-static inline u32 hpsa_tag_discard_error_bits(u32 tag)
+
+static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag)
 {
-#define HPSA_ERROR_BITS 0x03
-	return tag & ~HPSA_ERROR_BITS;
+#define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1)
+#define HPSA_SIMPLE_ERROR_BITS 0x03
+	if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
+		return tag & ~HPSA_SIMPLE_ERROR_BITS;
+	return tag & ~HPSA_PERF_ERROR_BITS;
 }
 
 /* process completion of an indexed ("direct lookup") command */
@@ -2904,10 +2982,9 @@ static inline u32 process_nonindexed_cmd(struct ctlr_info *h,
 {
 	u32 tag;
 	struct CommandList *c = NULL;
-	struct hlist_node *tmp;
 
-	tag = hpsa_tag_discard_error_bits(raw_tag);
-	hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+	tag = hpsa_tag_discard_error_bits(h, raw_tag);
+	list_for_each_entry(c, &h->cmpQ, list) {
 		if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) {
 			finish_cmd(c, raw_tag);
 			return next_command(h);
@@ -2957,7 +3034,10 @@ static irqreturn_t do_hpsa_intr_msi(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-/* Send a message CDB to the firmware. */
+/* Send a message CDB to the firmware. Careful, this only works
+ * in simple mode, not performant mode due to the tag lookup.
+ * We only ever use this immediately after a controller reset.
+ */
 static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 						unsigned char type)
 {
@@ -3023,7 +3103,7 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 
 	for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
 		tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
-		if (hpsa_tag_discard_error_bits(tag) == paddr32)
+		if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr32)
 			break;
 		msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
 	}
@@ -3055,38 +3135,6 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 #define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
 #define hpsa_noop(p) hpsa_message(p, 3, 0)
 
-static __devinit int hpsa_reset_msi(struct pci_dev *pdev)
-{
-/* the #defines are stolen from drivers/pci/msi.h. */
-#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
-#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
-
-	int pos;
-	u16 control = 0;
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
-	if (pos) {
-		pci_read_config_word(pdev, msi_control_reg(pos), &control);
-		if (control & PCI_MSI_FLAGS_ENABLE) {
-			dev_info(&pdev->dev, "resetting MSI\n");
-			pci_write_config_word(pdev, msi_control_reg(pos),
-					control & ~PCI_MSI_FLAGS_ENABLE);
-		}
-	}
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
-	if (pos) {
-		pci_read_config_word(pdev, msi_control_reg(pos), &control);
-		if (control & PCI_MSIX_FLAGS_ENABLE) {
-			dev_info(&pdev->dev, "resetting MSI-X\n");
-			pci_write_config_word(pdev, msi_control_reg(pos),
-					control & ~PCI_MSIX_FLAGS_ENABLE);
-		}
-	}
-
-	return 0;
-}
-
 static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 	void * __iomem vaddr, bool use_doorbell)
 {
@@ -3142,17 +3190,17 @@ static int hpsa_controller_hard_reset(struct pci_dev *pdev,
  */
 static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 {
-	u16 saved_config_space[32];
 	u64 cfg_offset;
 	u32 cfg_base_addr;
 	u64 cfg_base_addr_index;
 	void __iomem *vaddr;
 	unsigned long paddr;
 	u32 misc_fw_support, active_transport;
-	int rc, i;
+	int rc;
 	struct CfgTable __iomem *cfgtable;
 	bool use_doorbell;
 	u32 board_id;
+	u16 command_register;
 
 	/* For controllers as old as the P600, this is very nearly
 	 * the same thing as
@@ -3162,14 +3210,6 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	 * pci_set_power_state(pci_dev, PCI_D0);
 	 * pci_restore_state(pci_dev);
 	 *
-	 * but we can't use these nice canned kernel routines on
-	 * kexec, because they also check the MSI/MSI-X state in PCI
-	 * configuration space and do the wrong thing when it is
-	 * set/cleared.  Also, the pci_save/restore_state functions
-	 * violate the ordering requirements for restoring the
-	 * configuration space from the CCISS document (see the
-	 * comment below).  So we roll our own ....
-	 *
 	 * For controllers newer than the P600, the pci power state
 	 * method of resetting doesn't work so we have another way
 	 * using the doorbell register.
@@ -3182,13 +3222,21 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	 * likely not be happy.  Just forbid resetting this conjoined mess.
 	 * The 640x isn't really supported by hpsa anyway.
 	 */
-	hpsa_lookup_board_id(pdev, &board_id);
+	rc = hpsa_lookup_board_id(pdev, &board_id);
+	if (rc < 0) {
+		dev_warn(&pdev->dev, "Not resetting device.\n");
+		return -ENODEV;
+	}
 	if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
 		return -ENOTSUPP;
 
-	for (i = 0; i < 32; i++)
-		pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
-
+	/* Save the PCI command register */
+	pci_read_config_word(pdev, 4, &command_register);
+	/* Turn the board off.  This is so that later pci_restore_state()
+	 * won't turn the board on before the rest of config space is ready.
+	 */
+	pci_disable_device(pdev);
+	pci_save_state(pdev);
 
 	/* find the first memory BAR, so we can find the cfg table */
 	rc = hpsa_pci_find_memory_BAR(pdev, &paddr);
@@ -3214,46 +3262,47 @@ static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 	misc_fw_support = readl(&cfgtable->misc_fw_support);
 	use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
 
-	/* The doorbell reset seems to cause lockups on some Smart
-	 * Arrays (e.g. P410, P410i, maybe others).  Until this is
-	 * fixed or at least isolated, avoid the doorbell reset.
-	 */
-	use_doorbell = 0;
-
 	rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
 	if (rc)
 		goto unmap_cfgtable;
 
-	/* Restore the PCI configuration space.  The Open CISS
-	 * Specification says, "Restore the PCI Configuration
-	 * Registers, offsets 00h through 60h. It is important to
-	 * restore the command register, 16-bits at offset 04h,
-	 * last. Do not restore the configuration status register,
-	 * 16-bits at offset 06h."  Note that the offset is 2*i.
-	 */
-	for (i = 0; i < 32; i++) {
-		if (i == 2 || i == 3)
-			continue;
-		pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+	pci_restore_state(pdev);
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_warn(&pdev->dev, "failed to enable device.\n");
+		goto unmap_cfgtable;
 	}
-	wmb();
-	pci_write_config_word(pdev, 4, saved_config_space[2]);
+	pci_write_config_word(pdev, 4, command_register);
 
 	/* Some devices (notably the HP Smart Array 5i Controller)
 	   need a little pause here */
 	msleep(HPSA_POST_RESET_PAUSE_MSECS);
 
+	/* Wait for board to become not ready, then ready. */
+	dev_info(&pdev->dev, "Waiting for board to become ready.\n");
+	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
+	if (rc)
+		dev_warn(&pdev->dev,
+			"failed waiting for board to become not ready\n");
+	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
+	if (rc) {
+		dev_warn(&pdev->dev,
+			"failed waiting for board to become ready\n");
+		goto unmap_cfgtable;
+	}
+	dev_info(&pdev->dev, "board ready.\n");
+
 	/* Controller should be in simple mode at this point.  If it's not,
 	 * It means we're on one of those controllers which doesn't support
 	 * the doorbell reset method and on which the PCI power management reset
 	 * method doesn't work (P800, for example.)
-	 * In those cases, pretend the reset worked and hope for the best.
+	 * In those cases, don't try to proceed, as it generally doesn't work.
 	 */
 	active_transport = readl(&cfgtable->TransportActive);
 	if (active_transport & PERFORMANT_MODE) {
 		dev_warn(&pdev->dev, "Unable to successfully reset controller,"
-			" proceeding anyway.\n");
-		rc = -ENOTSUPP;
+			" Ignoring controller.\n");
+		rc = -ENODEV;
 	}
 
 unmap_cfgtable:
@@ -3386,7 +3435,7 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h)
 default_int_mode:
 #endif				/* CONFIG_PCI_MSI */
 	/* if we get here we're going to use the default interrupt mode */
-	h->intr[PERF_MODE_INT] = h->pdev->irq;
+	h->intr[h->intr_mode] = h->pdev->irq;
 }
 
 static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
@@ -3438,18 +3487,28 @@ static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
 	return -ENODEV;
 }
 
-static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h)
+static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
+	void __iomem *vaddr, int wait_for_ready)
 {
-	int i;
+	int i, iterations;
 	u32 scratchpad;
+	if (wait_for_ready)
+		iterations = HPSA_BOARD_READY_ITERATIONS;
+	else
+		iterations = HPSA_BOARD_NOT_READY_ITERATIONS;
 
-	for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) {
-		scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
-		if (scratchpad == HPSA_FIRMWARE_READY)
-			return 0;
+	for (i = 0; i < iterations; i++) {
+		scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET);
+		if (wait_for_ready) {
+			if (scratchpad == HPSA_FIRMWARE_READY)
+				return 0;
+		} else {
+			if (scratchpad != HPSA_FIRMWARE_READY)
+				return 0;
+		}
 		msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS);
 	}
-	dev_warn(&h->pdev->dev, "board not ready, timed out.\n");
+	dev_warn(&pdev->dev, "board not ready, timed out.\n");
 	return -ENODEV;
 }
 
@@ -3497,6 +3556,11 @@ static int __devinit hpsa_find_cfgtables(struct ctlr_info *h)
 static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
 {
 	h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
+
+	/* Limit commands in memory limited kdump scenario. */
+	if (reset_devices && h->max_commands > 32)
+		h->max_commands = 32;
+
 	if (h->max_commands < 16) {
 		dev_warn(&h->pdev->dev, "Controller reports "
 			"max supported commands of %d, an obvious lie. "
@@ -3571,16 +3635,21 @@ static inline void hpsa_p600_dma_prefetch_quirk(struct ctlr_info *h)
 static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 {
 	int i;
+	u32 doorbell_value;
+	unsigned long flags;
 
 	/* under certain very rare conditions, this can take awhile.
 	 * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
 	 * as we enter this code.)
 	 */
 	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
-		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+		spin_lock_irqsave(&h->lock, flags);
+		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
+		spin_unlock_irqrestore(&h->lock, flags);
+		if (!(doorbell_value & CFGTBL_ChangeReq))
 			break;
 		/* delay and try again */
-		msleep(10);
+		usleep_range(10000, 20000);
 	}
 }
 
@@ -3603,6 +3672,7 @@ static int __devinit hpsa_enter_simple_mode(struct ctlr_info *h)
 			"unable to get board into simple mode\n");
 		return -ENODEV;
 	}
+	h->transMethod = CFGTBL_Trans_Simple;
 	return 0;
 }
 
@@ -3641,7 +3711,7 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)
 		err = -ENOMEM;
 		goto err_out_free_res;
 	}
-	err = hpsa_wait_for_board_ready(h);
+	err = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
 	if (err)
 		goto err_out_free_res;
 	err = hpsa_find_cfgtables(h);
@@ -3710,8 +3780,6 @@ static __devinit int hpsa_init_reset_devices(struct pci_dev *pdev)
 		return 0; /* just try to do the kdump anyhow. */
 	if (rc)
 		return -ENODEV;
-	if (hpsa_reset_msi(pdev))
-		return -ENODEV;
 
 	/* Now try to get the controller to respond to a no-op */
 	for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
@@ -3749,8 +3817,11 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
 
 	h->pdev = pdev;
 	h->busy_initializing = 1;
-	INIT_HLIST_HEAD(&h->cmpQ);
-	INIT_HLIST_HEAD(&h->reqQ);
+	h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
+	INIT_LIST_HEAD(&h->cmpQ);
+	INIT_LIST_HEAD(&h->reqQ);
+	spin_lock_init(&h->lock);
+	spin_lock_init(&h->scan_lock);
 	rc = hpsa_pci_init(h);
 	if (rc != 0)
 		goto clean1;
@@ -3777,20 +3848,20 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
 
 	if (h->msix_vector || h->msi_vector)
-		rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_msi,
+		rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_msi,
 				IRQF_DISABLED, h->devname, h);
 	else
-		rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_intx,
+		rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_intx,
 				IRQF_DISABLED, h->devname, h);
 	if (rc) {
 		dev_err(&pdev->dev, "unable to get irq %d for %s\n",
-		       h->intr[PERF_MODE_INT], h->devname);
+		       h->intr[h->intr_mode], h->devname);
 		goto clean2;
 	}
 
 	dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
 	       h->devname, pdev->device,
-	       h->intr[PERF_MODE_INT], dac ? "" : " not");
+	       h->intr[h->intr_mode], dac ? "" : " not");
 
 	h->cmd_pool_bits =
 	    kmalloc(((h->nr_cmds + BITS_PER_LONG -
@@ -3810,8 +3881,6 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
 	}
 	if (hpsa_allocate_sg_chain_blocks(h))
 		goto clean4;
-	spin_lock_init(&h->lock);
-	spin_lock_init(&h->scan_lock);
 	init_waitqueue_head(&h->scan_wait_queue);
 	h->scan_finished = 1; /* no scan currently in progress */
 
@@ -3843,7 +3912,7 @@ clean4:
 			    h->nr_cmds * sizeof(struct ErrorInfo),
 			    h->errinfo_pool,
 			    h->errinfo_pool_dhandle);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 clean2:
 clean1:
 	h->busy_initializing = 0;
@@ -3887,7 +3956,7 @@ static void hpsa_shutdown(struct pci_dev *pdev)
 	 */
 	hpsa_flush_cache(h);
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 #ifdef CONFIG_PCI_MSI
 	if (h->msix_vector)
 		pci_disable_msix(h->pdev);
@@ -3989,7 +4058,8 @@ static void  calc_bucket_map(int bucket[], int num_buckets,
 	}
 }
 
-static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h)
+static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
+	u32 use_short_tags)
 {
 	int i;
 	unsigned long register_value;
@@ -4037,7 +4107,7 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h)
 	writel(0, &h->transtable->RepQCtrAddrHigh32);
 	writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32);
 	writel(0, &h->transtable->RepQAddr0High32);
-	writel(CFGTBL_Trans_Performant,
+	writel(CFGTBL_Trans_Performant | use_short_tags,
 		&(h->cfgtable->HostWrite.TransportRequest));
 	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
 	hpsa_wait_for_mode_change_ack(h);
@@ -4047,12 +4117,18 @@ static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h)
 					" performant mode\n");
 		return;
 	}
+	/* Change the access methods to the performant access methods */
+	h->access = SA5_performant_access;
+	h->transMethod = CFGTBL_Trans_Performant;
 }
 
 static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 {
 	u32 trans_support;
 
+	if (hpsa_simple_mode)
+		return;
+
 	trans_support = readl(&(h->cfgtable->TransportSupport));
 	if (!(trans_support & PERFORMANT_MODE))
 		return;
@@ -4072,11 +4148,8 @@ static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 		|| (h->blockFetchTable == NULL))
 		goto clean_up;
 
-	hpsa_enter_performant_mode(h);
-
-	/* Change the access methods to the performant access methods */
-	h->access = SA5_performant_access;
-	h->transMethod = CFGTBL_Trans_Performant;
+	hpsa_enter_performant_mode(h,
+		trans_support & CFGTBL_Trans_use_short_tags);
 
 	return;
 
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 19586e1..621a153 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -72,11 +72,12 @@ struct ctlr_info {
 	unsigned int intr[4];
 	unsigned int msix_vector;
 	unsigned int msi_vector;
+	int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
 	struct access_method access;
 
 	/* queue and queue Info */
-	struct hlist_head reqQ;
-	struct hlist_head cmpQ;
+	struct list_head reqQ;
+	struct list_head cmpQ;
 	unsigned int Qdepth;
 	unsigned int maxQsinceinit;
 	unsigned int maxSG;
@@ -154,12 +155,16 @@ struct ctlr_info {
  * HPSA_BOARD_READY_ITERATIONS are derived from those.
  */
 #define HPSA_BOARD_READY_WAIT_SECS (120)
+#define HPSA_BOARD_NOT_READY_WAIT_SECS (10)
 #define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
 #define HPSA_BOARD_READY_POLL_INTERVAL \
 	((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
 #define HPSA_BOARD_READY_ITERATIONS \
 	((HPSA_BOARD_READY_WAIT_SECS * 1000) / \
 		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
+#define HPSA_BOARD_NOT_READY_ITERATIONS \
+	((HPSA_BOARD_NOT_READY_WAIT_SECS * 1000) / \
+		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
 #define HPSA_POST_RESET_PAUSE_MSECS (3000)
 #define HPSA_POST_RESET_NOOP_RETRIES (12)
 
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index f5c4c3c..1846490 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -104,6 +104,7 @@
 
 #define CFGTBL_Trans_Simple     0x00000002l
 #define CFGTBL_Trans_Performant 0x00000004l
+#define CFGTBL_Trans_use_short_tags 0x20000000l
 
 #define CFGTBL_BusType_Ultra2   0x00000001l
 #define CFGTBL_BusType_Ultra3   0x00000002l
@@ -265,6 +266,7 @@ struct ErrorInfo {
 
 #define DIRECT_LOOKUP_SHIFT 5
 #define DIRECT_LOOKUP_BIT 0x10
+#define DIRECT_LOOKUP_MASK (~((1 << DIRECT_LOOKUP_SHIFT) - 1))
 
 #define HPSA_ERROR_BIT          0x02
 struct ctlr_info; /* defined in hpsa.h */
@@ -291,7 +293,7 @@ struct CommandList {
 	struct ctlr_info	   *h;
 	int			   cmd_type;
 	long			   cmdindex;
-	struct hlist_node list;
+	struct list_head list;
 	struct request *rq;
 	struct completion *waiting;
 	void   *scsi_cmd;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 9c5c8be..0621238 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1301,7 +1301,7 @@ static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg,
 			ipr_clear_res_target(res);
 			list_move_tail(&res->queue, &ioa_cfg->free_res_q);
 		}
-	} else if (!res->sdev) {
+	} else if (!res->sdev || res->del_from_ml) {
 		res->add_to_ml = 1;
 		if (ioa_cfg->allow_ml_add_del)
 			schedule_work(&ioa_cfg->work_q);
@@ -3104,7 +3104,10 @@ restart:
 				did_work = 1;
 				sdev = res->sdev;
 				if (!scsi_device_get(sdev)) {
-					list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+					if (!res->add_to_ml)
+						list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+					else
+						res->del_from_ml = 0;
 					spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 					scsi_remove_device(sdev);
 					scsi_device_put(sdev);
@@ -6219,11 +6222,10 @@ static struct ata_port_operations ipr_sata_ops = {
 };
 
 static struct ata_port_info sata_port_info = {
-	.flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
-	ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-	.pio_mask	= 0x10, /* pio4 */
-	.mwdma_mask = 0x07,
-	.udma_mask	= 0x7f, /* udma0-6 */
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
+	.pio_mask	= ATA_PIO4_ONLY,
+	.mwdma_mask	= ATA_MWDMA2,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &ipr_sata_ops
 };
 
@@ -8865,7 +8867,7 @@ static void __ipr_remove(struct pci_dev *pdev)
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
 	wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
-	flush_scheduled_work();
+	flush_work_sync(&ioa_cfg->work_q);
 	spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
 
 	spin_lock(&ipr_driver_lock);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index fec47de..a860452 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -608,54 +608,12 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
 	iscsi_sw_tcp_release_conn(conn);
 }
 
-static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
-				 char *buf, int *port,
-				 int (*getname)(struct socket *,
-						struct sockaddr *,
-						int *addrlen))
-{
-	struct sockaddr_storage *addr;
-	struct sockaddr_in6 *sin6;
-	struct sockaddr_in *sin;
-	int rc = 0, len;
-
-	addr = kmalloc(sizeof(*addr), GFP_KERNEL);
-	if (!addr)
-		return -ENOMEM;
-
-	if (getname(sock, (struct sockaddr *) addr, &len)) {
-		rc = -ENODEV;
-		goto free_addr;
-	}
-
-	switch (addr->ss_family) {
-	case AF_INET:
-		sin = (struct sockaddr_in *)addr;
-		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, "%pI4", &sin->sin_addr.s_addr);
-		*port = be16_to_cpu(sin->sin_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	case AF_INET6:
-		sin6 = (struct sockaddr_in6 *)addr;
-		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, "%pI6", &sin6->sin6_addr);
-		*port = be16_to_cpu(sin6->sin6_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	}
-free_addr:
-	kfree(addr);
-	return rc;
-}
-
 static int
 iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
 		       struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
 		       int is_leading)
 {
-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
-	struct iscsi_host *ihost = shost_priv(shost);
+	struct iscsi_session *session = cls_session->dd_data;
 	struct iscsi_conn *conn = cls_conn->dd_data;
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
@@ -670,27 +628,15 @@ iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
 				  "sockfd_lookup failed %d\n", err);
 		return -EEXIST;
 	}
-	/*
-	 * copy these values now because if we drop the session
-	 * userspace may still want to query the values since we will
-	 * be using them for the reconnect
-	 */
-	err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address,
-				    &conn->portal_port, kernel_getpeername);
-	if (err)
-		goto free_socket;
-
-	err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address,
-				    &ihost->local_port, kernel_getsockname);
-	if (err)
-		goto free_socket;
 
 	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
 	if (err)
 		goto free_socket;
 
+	spin_lock_bh(&session->lock);
 	/* bind iSCSI connection and socket */
 	tcp_sw_conn->sock = sock;
+	spin_unlock_bh(&session->lock);
 
 	/* setup Socket parameters */
 	sk = sock->sk;
@@ -752,24 +698,74 @@ static int iscsi_sw_tcp_conn_get_param(struct iscsi_cls_conn *cls_conn,
 				       enum iscsi_param param, char *buf)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
-	int len;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+	struct sockaddr_in6 addr;
+	int rc, len;
 
 	switch(param) {
 	case ISCSI_PARAM_CONN_PORT:
-		spin_lock_bh(&conn->session->lock);
-		len = sprintf(buf, "%hu\n", conn->portal_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
 		spin_lock_bh(&conn->session->lock);
-		len = sprintf(buf, "%s\n", conn->portal_address);
+		if (!tcp_sw_conn || !tcp_sw_conn->sock) {
+			spin_unlock_bh(&conn->session->lock);
+			return -ENOTCONN;
+		}
+		rc = kernel_getpeername(tcp_sw_conn->sock,
+					(struct sockaddr *)&addr, &len);
 		spin_unlock_bh(&conn->session->lock);
-		break;
+		if (rc)
+			return rc;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+						 &addr, param, buf);
 	default:
 		return iscsi_conn_get_param(cls_conn, param, buf);
 	}
 
-	return len;
+	return 0;
+}
+
+static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
+				       enum iscsi_host_param param, char *buf)
+{
+	struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
+	struct iscsi_session *session = tcp_sw_host->session;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct iscsi_sw_tcp_conn *tcp_sw_conn;
+	struct sockaddr_in6 addr;
+	int rc, len;
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+		spin_lock_bh(&session->lock);
+		conn = session->leadconn;
+		if (!conn) {
+			spin_unlock_bh(&session->lock);
+			return -ENOTCONN;
+		}
+		tcp_conn = conn->dd_data;
+
+		tcp_sw_conn = tcp_conn->dd_data;
+		if (!tcp_sw_conn->sock) {
+			spin_unlock_bh(&session->lock);
+			return -ENOTCONN;
+		}
+
+		rc = kernel_getsockname(tcp_sw_conn->sock,
+					(struct sockaddr *)&addr, &len);
+		spin_unlock_bh(&session->lock);
+		if (rc)
+			return rc;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+						 &addr, param, buf);
+	default:
+		return iscsi_host_get_param(shost, param, buf);
+	}
+
+	return 0;
 }
 
 static void
@@ -797,6 +793,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
 {
 	struct iscsi_cls_session *cls_session;
 	struct iscsi_session *session;
+	struct iscsi_sw_tcp_host *tcp_sw_host;
 	struct Scsi_Host *shost;
 
 	if (ep) {
@@ -804,7 +801,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
 		return NULL;
 	}
 
-	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1);
+	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht,
+				 sizeof(struct iscsi_sw_tcp_host), 1);
 	if (!shost)
 		return NULL;
 	shost->transportt = iscsi_sw_tcp_scsi_transport;
@@ -825,6 +823,8 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
 	if (!cls_session)
 		goto remove_host;
 	session = cls_session->dd_data;
+	tcp_sw_host = iscsi_host_priv(shost);
+	tcp_sw_host->session = session;
 
 	shost->can_queue = session->scsi_cmds_max;
 	if (iscsi_tcp_r2tpool_alloc(session))
@@ -929,7 +929,7 @@ static struct iscsi_transport iscsi_sw_tcp_transport = {
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_sw_tcp_conn_stop,
 	/* iscsi host params */
-	.get_host_param		= iscsi_host_get_param,
+	.get_host_param		= iscsi_sw_tcp_host_get_param,
 	.set_host_param		= iscsi_host_set_param,
 	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index 94644ba..666fe09 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -55,6 +55,10 @@ struct iscsi_sw_tcp_conn {
 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
 };
 
+struct iscsi_sw_tcp_host {
+	struct iscsi_session	*session;
+};
+
 struct iscsi_sw_tcp_hdrbuf {
 	struct iscsi_hdr	hdrbuf;
 	char			hdrextbuf[ISCSI_MAX_AHS_SIZE +
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index d21367d..28231ba 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -38,7 +38,7 @@ u16	fc_cpu_mask;		/* cpu mask for possible cpus */
 EXPORT_SYMBOL(fc_cpu_mask);
 static u16	fc_cpu_order;	/* 2's power to represent total possible cpus */
 static struct kmem_cache *fc_em_cachep;	       /* cache for exchanges */
-struct workqueue_struct *fc_exch_workqueue;
+static struct workqueue_struct *fc_exch_workqueue;
 
 /*
  * Structure and function definitions for managing Fibre Channel Exchanges
@@ -558,6 +558,22 @@ static struct fc_seq *fc_seq_start_next(struct fc_seq *sp)
 	return sp;
 }
 
+/*
+ * Set the response handler for the exchange associated with a sequence.
+ */
+static void fc_seq_set_resp(struct fc_seq *sp,
+			    void (*resp)(struct fc_seq *, struct fc_frame *,
+					 void *),
+			    void *arg)
+{
+	struct fc_exch *ep = fc_seq_exch(sp);
+
+	spin_lock_bh(&ep->ex_lock);
+	ep->resp = resp;
+	ep->arg = arg;
+	spin_unlock_bh(&ep->ex_lock);
+}
+
 /**
  * fc_seq_exch_abort() - Abort an exchange and sequence
  * @req_sp:	The sequence to be aborted
@@ -650,13 +666,10 @@ static void fc_exch_timeout(struct work_struct *work)
 		if (e_stat & ESB_ST_ABNORMAL)
 			rc = fc_exch_done_locked(ep);
 		spin_unlock_bh(&ep->ex_lock);
+		if (!rc)
+			fc_exch_delete(ep);
 		if (resp)
 			resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
-		if (!rc) {
-			/* delete the exchange if it's already being aborted */
-			fc_exch_delete(ep);
-			return;
-		}
 		fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
 		goto done;
 	}
@@ -1266,6 +1279,8 @@ free:
  * @fp:    The request frame
  *
  * On success, the sequence pointer will be returned and also in fr_seq(@fp).
+ * A reference will be held on the exchange/sequence for the caller, which
+ * must call fc_seq_release().
  */
 static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
 {
@@ -1283,6 +1298,15 @@ static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
 }
 
 /**
+ * fc_seq_release() - Release the hold
+ * @sp:    The sequence.
+ */
+static void fc_seq_release(struct fc_seq *sp)
+{
+	fc_exch_release(fc_seq_exch(sp));
+}
+
+/**
  * fc_exch_recv_req() - Handler for an incoming request
  * @lport: The local port that received the request
  * @mp:	   The EM that the exchange is on
@@ -2151,6 +2175,7 @@ err:
 		fc_exch_mgr_del(ema);
 	return -ENOMEM;
 }
+EXPORT_SYMBOL(fc_exch_mgr_list_clone);
 
 /**
  * fc_exch_mgr_alloc() - Allocate an exchange manager
@@ -2254,16 +2279,45 @@ void fc_exch_mgr_free(struct fc_lport *lport)
 EXPORT_SYMBOL(fc_exch_mgr_free);
 
 /**
+ * fc_find_ema() - Lookup and return appropriate Exchange Manager Anchor depending
+ * upon 'xid'.
+ * @f_ctl: f_ctl
+ * @lport: The local port the frame was received on
+ * @fh: The received frame header
+ */
+static struct fc_exch_mgr_anchor *fc_find_ema(u32 f_ctl,
+					      struct fc_lport *lport,
+					      struct fc_frame_header *fh)
+{
+	struct fc_exch_mgr_anchor *ema;
+	u16 xid;
+
+	if (f_ctl & FC_FC_EX_CTX)
+		xid = ntohs(fh->fh_ox_id);
+	else {
+		xid = ntohs(fh->fh_rx_id);
+		if (xid == FC_XID_UNKNOWN)
+			return list_entry(lport->ema_list.prev,
+					  typeof(*ema), ema_list);
+	}
+
+	list_for_each_entry(ema, &lport->ema_list, ema_list) {
+		if ((xid >= ema->mp->min_xid) &&
+		    (xid <= ema->mp->max_xid))
+			return ema;
+	}
+	return NULL;
+}
+/**
  * fc_exch_recv() - Handler for received frames
  * @lport: The local port the frame was received on
- * @fp:	   The received frame
+ * @fp:	The received frame
  */
 void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
 {
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	struct fc_exch_mgr_anchor *ema;
-	u32 f_ctl, found = 0;
-	u16 oxid;
+	u32 f_ctl;
 
 	/* lport lock ? */
 	if (!lport || lport->state == LPORT_ST_DISABLED) {
@@ -2274,24 +2328,17 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
 	}
 
 	f_ctl = ntoh24(fh->fh_f_ctl);
-	oxid = ntohs(fh->fh_ox_id);
-	if (f_ctl & FC_FC_EX_CTX) {
-		list_for_each_entry(ema, &lport->ema_list, ema_list) {
-			if ((oxid >= ema->mp->min_xid) &&
-			    (oxid <= ema->mp->max_xid)) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (!found) {
-			FC_LPORT_DBG(lport, "Received response for out "
-				     "of range oxid:%hx\n", oxid);
-			fc_frame_free(fp);
-			return;
-		}
-	} else
-		ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list);
+	ema = fc_find_ema(f_ctl, lport, fh);
+	if (!ema) {
+		FC_LPORT_DBG(lport, "Unable to find Exchange Manager Anchor,"
+				    "fc_ctl <0x%x>, xid <0x%x>\n",
+				     f_ctl,
+				     (f_ctl & FC_FC_EX_CTX) ?
+				     ntohs(fh->fh_ox_id) :
+				     ntohs(fh->fh_rx_id));
+		fc_frame_free(fp);
+		return;
+	}
 
 	/*
 	 * If frame is marked invalid, just drop it.
@@ -2329,6 +2376,9 @@ int fc_exch_init(struct fc_lport *lport)
 	if (!lport->tt.seq_start_next)
 		lport->tt.seq_start_next = fc_seq_start_next;
 
+	if (!lport->tt.seq_set_resp)
+		lport->tt.seq_set_resp = fc_seq_set_resp;
+
 	if (!lport->tt.exch_seq_send)
 		lport->tt.exch_seq_send = fc_exch_seq_send;
 
@@ -2350,6 +2400,9 @@ int fc_exch_init(struct fc_lport *lport)
 	if (!lport->tt.seq_assign)
 		lport->tt.seq_assign = fc_seq_assign;
 
+	if (!lport->tt.seq_release)
+		lport->tt.seq_release = fc_seq_release;
+
 	return 0;
 }
 EXPORT_SYMBOL(fc_exch_init);
@@ -2357,7 +2410,7 @@ EXPORT_SYMBOL(fc_exch_init);
 /**
  * fc_setup_exch_mgr() - Setup an exchange manager
  */
-int fc_setup_exch_mgr()
+int fc_setup_exch_mgr(void)
 {
 	fc_em_cachep = kmem_cache_create("libfc_em", sizeof(struct fc_exch),
 					 0, SLAB_HWCACHE_ALIGN, NULL);
@@ -2395,7 +2448,7 @@ int fc_setup_exch_mgr()
 /**
  * fc_destroy_exch_mgr() - Destroy an exchange manager
  */
-void fc_destroy_exch_mgr()
+void fc_destroy_exch_mgr(void)
 {
 	destroy_workqueue(fc_exch_workqueue);
 	kmem_cache_destroy(fc_em_cachep);
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 5962d1a..b1b03af 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -42,7 +42,7 @@
 
 #include "fc_libfc.h"
 
-struct kmem_cache *scsi_pkt_cachep;
+static struct kmem_cache *scsi_pkt_cachep;
 
 /* SRB state definitions */
 #define FC_SRB_FREE		0		/* cmd is free */
@@ -155,6 +155,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lport, gfp_t gfp)
 	if (fsp) {
 		memset(fsp, 0, sizeof(*fsp));
 		fsp->lp = lport;
+		fsp->xfer_ddp = FC_XID_UNKNOWN;
 		atomic_set(&fsp->ref_cnt, 1);
 		init_timer(&fsp->timer);
 		INIT_LIST_HEAD(&fsp->list);
@@ -1201,6 +1202,7 @@ unlock:
 static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
 {
 	int rc = FAILED;
+	unsigned long ticks_left;
 
 	if (fc_fcp_send_abort(fsp))
 		return FAILED;
@@ -1209,13 +1211,13 @@ static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
 	fsp->wait_for_comp = 1;
 
 	spin_unlock_bh(&fsp->scsi_pkt_lock);
-	rc = wait_for_completion_timeout(&fsp->tm_done, FC_SCSI_TM_TOV);
+	ticks_left = wait_for_completion_timeout(&fsp->tm_done,
+							FC_SCSI_TM_TOV);
 	spin_lock_bh(&fsp->scsi_pkt_lock);
 	fsp->wait_for_comp = 0;
 
-	if (!rc) {
+	if (!ticks_left) {
 		FC_FCP_DBG(fsp, "target abort cmd  failed\n");
-		rc = FAILED;
 	} else if (fsp->state & FC_SRB_ABORTED) {
 		FC_FCP_DBG(fsp, "target abort cmd  passed\n");
 		rc = SUCCESS;
@@ -1321,7 +1323,7 @@ static void fc_tm_done(struct fc_seq *seq, struct fc_frame *fp, void *arg)
 		 *
 		 * scsi-eh will escalate for when either happens.
 		 */
-		goto out;
+		return;
 	}
 
 	if (fc_fcp_lock_pkt(fsp))
@@ -1787,15 +1789,14 @@ static inline int fc_fcp_lport_queue_ready(struct fc_lport *lport)
 
 /**
  * fc_queuecommand() - The queuecommand function of the SCSI template
+ * @shost: The Scsi_Host that the command was issued to
  * @cmd:   The scsi_cmnd to be executed
- * @done:  The callback function to be called when the scsi_cmnd is complete
  *
- * This is the i/o strategy routine, called by the SCSI layer. This routine
- * is called with the host_lock held.
+ * This is the i/o strategy routine, called by the SCSI layer.
  */
-static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
+int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
 {
-	struct fc_lport *lport;
+	struct fc_lport *lport = shost_priv(shost);
 	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
 	struct fc_fcp_pkt *fsp;
 	struct fc_rport_libfc_priv *rpriv;
@@ -1803,15 +1804,12 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs
 	int rc = 0;
 	struct fcoe_dev_stats *stats;
 
-	lport = shost_priv(sc_cmd->device->host);
-
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
 		sc_cmd->result = rval;
-		done(sc_cmd);
+		sc_cmd->scsi_done(sc_cmd);
 		return 0;
 	}
-	spin_unlock_irq(lport->host->host_lock);
 
 	if (!*(struct fc_remote_port **)rport->dd_data) {
 		/*
@@ -1819,7 +1817,7 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs
 		 * online
 		 */
 		sc_cmd->result = DID_IMM_RETRY << 16;
-		done(sc_cmd);
+		sc_cmd->scsi_done(sc_cmd);
 		goto out;
 	}
 
@@ -1842,10 +1840,7 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs
 	 * build the libfc request pkt
 	 */
 	fsp->cmd = sc_cmd;	/* save the cmd */
-	fsp->lp = lport;	/* save the softc ptr */
 	fsp->rport = rport;	/* set the remote port ptr */
-	fsp->xfer_ddp = FC_XID_UNKNOWN;
-	sc_cmd->scsi_done = done;
 
 	/*
 	 * set up the transfer length
@@ -1886,11 +1881,8 @@ static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scs
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 	}
 out:
-	spin_lock_irq(lport->host->host_lock);
 	return rc;
 }
-
-DEF_SCSI_QCMD(fc_queuecommand)
 EXPORT_SYMBOL(fc_queuecommand);
 
 /**
@@ -2112,7 +2104,6 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
 	 * the sc passed in is not setup for execution like when sent
 	 * through the queuecommand callout.
 	 */
-	fsp->lp = lport;	/* save the softc ptr */
 	fsp->rport = rport;	/* set the remote port ptr */
 
 	/*
@@ -2245,7 +2236,7 @@ void fc_fcp_destroy(struct fc_lport *lport)
 }
 EXPORT_SYMBOL(fc_fcp_destroy);
 
-int fc_setup_fcp()
+int fc_setup_fcp(void)
 {
 	int rc = 0;
 
@@ -2261,7 +2252,7 @@ int fc_setup_fcp()
 	return rc;
 }
 
-void fc_destroy_fcp()
+void fc_destroy_fcp(void)
 {
 	if (scsi_pkt_cachep)
 		kmem_cache_destroy(scsi_pkt_cachep);
diff --git a/drivers/scsi/libfc/fc_libfc.c b/drivers/scsi/libfc/fc_libfc.c
index 6a48c28..b773512 100644
--- a/drivers/scsi/libfc/fc_libfc.c
+++ b/drivers/scsi/libfc/fc_libfc.c
@@ -35,6 +35,27 @@ unsigned int fc_debug_logging;
 module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
 
+DEFINE_MUTEX(fc_prov_mutex);
+static LIST_HEAD(fc_local_ports);
+struct blocking_notifier_head fc_lport_notifier_head =
+		BLOCKING_NOTIFIER_INIT(fc_lport_notifier_head);
+EXPORT_SYMBOL(fc_lport_notifier_head);
+
+/*
+ * Providers which primarily send requests and PRLIs.
+ */
+struct fc4_prov *fc_active_prov[FC_FC4_PROV_SIZE] = {
+	[0] = &fc_rport_t0_prov,
+	[FC_TYPE_FCP] = &fc_rport_fcp_init,
+};
+
+/*
+ * Providers which receive requests.
+ */
+struct fc4_prov *fc_passive_prov[FC_FC4_PROV_SIZE] = {
+	[FC_TYPE_ELS] = &fc_lport_els_prov,
+};
+
 /**
  * libfc_init() - Initialize libfc.ko
  */
@@ -210,3 +231,102 @@ void fc_fill_reply_hdr(struct fc_frame *fp, const struct fc_frame *in_fp,
 	fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset);
 }
 EXPORT_SYMBOL(fc_fill_reply_hdr);
+
+/**
+ * fc_fc4_conf_lport_params() - Modify "service_params" of specified lport
+ * if there is service provider (target provider) registered with libfc
+ * for specified "fc_ft_type"
+ * @lport: Local port which service_params needs to be modified
+ * @type: FC-4 type, such as FC_TYPE_FCP
+ */
+void fc_fc4_conf_lport_params(struct fc_lport *lport, enum fc_fh_type type)
+{
+	struct fc4_prov *prov_entry;
+	BUG_ON(type >= FC_FC4_PROV_SIZE);
+	BUG_ON(!lport);
+	prov_entry = fc_passive_prov[type];
+	if (type == FC_TYPE_FCP) {
+		if (prov_entry && prov_entry->recv)
+			lport->service_params |= FCP_SPPF_TARG_FCN;
+	}
+}
+
+void fc_lport_iterate(void (*notify)(struct fc_lport *, void *), void *arg)
+{
+	struct fc_lport *lport;
+
+	mutex_lock(&fc_prov_mutex);
+	list_for_each_entry(lport, &fc_local_ports, lport_list)
+		notify(lport, arg);
+	mutex_unlock(&fc_prov_mutex);
+}
+EXPORT_SYMBOL(fc_lport_iterate);
+
+/**
+ * fc_fc4_register_provider() - register FC-4 upper-level provider.
+ * @type: FC-4 type, such as FC_TYPE_FCP
+ * @prov: structure describing provider including ops vector.
+ *
+ * Returns 0 on success, negative error otherwise.
+ */
+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *prov)
+{
+	struct fc4_prov **prov_entry;
+	int ret = 0;
+
+	if (type >= FC_FC4_PROV_SIZE)
+		return -EINVAL;
+	mutex_lock(&fc_prov_mutex);
+	prov_entry = (prov->recv ? fc_passive_prov : fc_active_prov) + type;
+	if (*prov_entry)
+		ret = -EBUSY;
+	else
+		*prov_entry = prov;
+	mutex_unlock(&fc_prov_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(fc_fc4_register_provider);
+
+/**
+ * fc_fc4_deregister_provider() - deregister FC-4 upper-level provider.
+ * @type: FC-4 type, such as FC_TYPE_FCP
+ * @prov: structure describing provider including ops vector.
+ */
+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov)
+{
+	BUG_ON(type >= FC_FC4_PROV_SIZE);
+	mutex_lock(&fc_prov_mutex);
+	if (prov->recv)
+		rcu_assign_pointer(fc_passive_prov[type], NULL);
+	else
+		rcu_assign_pointer(fc_active_prov[type], NULL);
+	mutex_unlock(&fc_prov_mutex);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL(fc_fc4_deregister_provider);
+
+/**
+ * fc_fc4_add_lport() - add new local port to list and run notifiers.
+ * @lport:  The new local port.
+ */
+void fc_fc4_add_lport(struct fc_lport *lport)
+{
+	mutex_lock(&fc_prov_mutex);
+	list_add_tail(&lport->lport_list, &fc_local_ports);
+	blocking_notifier_call_chain(&fc_lport_notifier_head,
+				     FC_LPORT_EV_ADD, lport);
+	mutex_unlock(&fc_prov_mutex);
+}
+
+/**
+ * fc_fc4_del_lport() - remove local port from list and run notifiers.
+ * @lport:  The new local port.
+ */
+void fc_fc4_del_lport(struct fc_lport *lport)
+{
+	mutex_lock(&fc_prov_mutex);
+	list_del(&lport->lport_list);
+	blocking_notifier_call_chain(&fc_lport_notifier_head,
+				     FC_LPORT_EV_DEL, lport);
+	mutex_unlock(&fc_prov_mutex);
+}
diff --git a/drivers/scsi/libfc/fc_libfc.h b/drivers/scsi/libfc/fc_libfc.h
index eea0c35..fedc819 100644
--- a/drivers/scsi/libfc/fc_libfc.h
+++ b/drivers/scsi/libfc/fc_libfc.h
@@ -94,6 +94,17 @@ extern unsigned int fc_debug_logging;
 				(lport)->host->host_no,	##args))
 
 /*
+ * FC-4 Providers.
+ */
+extern struct fc4_prov *fc_active_prov[];	/* providers without recv */
+extern struct fc4_prov *fc_passive_prov[];	/* providers with recv */
+extern struct mutex fc_prov_mutex;		/* lock over table changes */
+
+extern struct fc4_prov fc_rport_t0_prov;	/* type 0 provider */
+extern struct fc4_prov fc_lport_els_prov;	/* ELS provider */
+extern struct fc4_prov fc_rport_fcp_init;	/* FCP initiator provider */
+
+/*
  * Set up direct-data placement for this I/O request
  */
 void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid);
@@ -112,6 +123,9 @@ void fc_destroy_fcp(void);
  * Internal libfc functions
  */
 const char *fc_els_resp_type(struct fc_frame *);
+extern void fc_fc4_add_lport(struct fc_lport *);
+extern void fc_fc4_del_lport(struct fc_lport *);
+extern void fc_fc4_conf_lport_params(struct fc_lport *, enum fc_fh_type);
 
 /*
  * Copies a buffer into an sg list
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index c5a10f9..8c08b21 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -633,6 +633,7 @@ int fc_lport_destroy(struct fc_lport *lport)
 	lport->tt.fcp_abort_io(lport);
 	lport->tt.disc_stop_final(lport);
 	lport->tt.exch_mgr_reset(lport, 0, 0);
+	fc_fc4_del_lport(lport);
 	return 0;
 }
 EXPORT_SYMBOL(fc_lport_destroy);
@@ -849,7 +850,7 @@ out:
 }
 
 /**
- * fc_lport_recv_req() - The generic lport request handler
+ * fc_lport_recv_els_req() - The generic lport ELS request handler
  * @lport: The local port that received the request
  * @fp:	   The request frame
  *
@@ -859,9 +860,9 @@ out:
  * Locking Note: This function should not be called with the lport
  *		 lock held becuase it will grab the lock.
  */
-static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
+static void fc_lport_recv_els_req(struct fc_lport *lport,
+				  struct fc_frame *fp)
 {
-	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	void (*recv)(struct fc_lport *, struct fc_frame *);
 
 	mutex_lock(&lport->lp_mutex);
@@ -873,8 +874,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
 	 */
 	if (!lport->link_up)
 		fc_frame_free(fp);
-	else if (fh->fh_type == FC_TYPE_ELS &&
-		 fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
+	else {
 		/*
 		 * Check opcode.
 		 */
@@ -903,14 +903,62 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
 		}
 
 		recv(lport, fp);
-	} else {
-		FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
-			     fr_eof(fp));
-		fc_frame_free(fp);
 	}
 	mutex_unlock(&lport->lp_mutex);
 }
 
+static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len,
+			     const struct fc_els_spp *spp_in,
+			     struct fc_els_spp *spp_out)
+{
+	return FC_SPP_RESP_INVL;
+}
+
+struct fc4_prov fc_lport_els_prov = {
+	.prli = fc_lport_els_prli,
+	.recv = fc_lport_recv_els_req,
+};
+
+/**
+ * fc_lport_recv_req() - The generic lport request handler
+ * @lport: The lport that received the request
+ * @fp: The frame the request is in
+ *
+ * Locking Note: This function should not be called with the lport
+ *		 lock held becuase it may grab the lock.
+ */
+static void fc_lport_recv_req(struct fc_lport *lport,
+			      struct fc_frame *fp)
+{
+	struct fc_frame_header *fh = fc_frame_header_get(fp);
+	struct fc_seq *sp = fr_seq(fp);
+	struct fc4_prov *prov;
+
+	/*
+	 * Use RCU read lock and module_lock to be sure module doesn't
+	 * deregister and get unloaded while we're calling it.
+	 * try_module_get() is inlined and accepts a NULL parameter.
+	 * Only ELSes and FCP target ops should come through here.
+	 * The locking is unfortunate, and a better scheme is being sought.
+	 */
+
+	rcu_read_lock();
+	if (fh->fh_type >= FC_FC4_PROV_SIZE)
+		goto drop;
+	prov = rcu_dereference(fc_passive_prov[fh->fh_type]);
+	if (!prov || !try_module_get(prov->module))
+		goto drop;
+	rcu_read_unlock();
+	prov->recv(lport, fp);
+	module_put(prov->module);
+	return;
+drop:
+	rcu_read_unlock();
+	FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type);
+	fc_frame_free(fp);
+	lport->tt.exch_done(sp);
+}
+
 /**
  * fc_lport_reset() - Reset a local port
  * @lport: The local port which should be reset
@@ -1542,6 +1590,7 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
  */
 int fc_lport_config(struct fc_lport *lport)
 {
+	INIT_LIST_HEAD(&lport->ema_list);
 	INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
 	mutex_init(&lport->lp_mutex);
 
@@ -1549,6 +1598,7 @@ int fc_lport_config(struct fc_lport *lport)
 
 	fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
 	fc_lport_add_fc4_type(lport, FC_TYPE_CT);
+	fc_fc4_conf_lport_params(lport, FC_TYPE_FCP);
 
 	return 0;
 }
@@ -1586,6 +1636,7 @@ int fc_lport_init(struct fc_lport *lport)
 		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
 	if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
 		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
+	fc_fc4_add_lport(lport);
 
 	return 0;
 }
diff --git a/drivers/scsi/libfc/fc_npiv.c b/drivers/scsi/libfc/fc_npiv.c
index dd2b43b..f33b897 100644
--- a/drivers/scsi/libfc/fc_npiv.c
+++ b/drivers/scsi/libfc/fc_npiv.c
@@ -37,9 +37,7 @@ struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize)
 
 	vn_port = libfc_host_alloc(shost->hostt, privsize);
 	if (!vn_port)
-		goto err_out;
-	if (fc_exch_mgr_list_clone(n_port, vn_port))
-		goto err_put;
+		return vn_port;
 
 	vn_port->vport = vport;
 	vport->dd_data = vn_port;
@@ -49,11 +47,6 @@ struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize)
 	mutex_unlock(&n_port->lp_mutex);
 
 	return vn_port;
-
-err_put:
-	scsi_host_put(vn_port->host);
-err_out:
-	return NULL;
 }
 EXPORT_SYMBOL(libfc_vport_create);
 
@@ -86,6 +79,7 @@ struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id)
 
 	return lport;
 }
+EXPORT_SYMBOL(fc_vport_id_lookup);
 
 /*
  * When setting the link state of vports during an lport state change, it's
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index a7175ad..49e1ccc 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -58,7 +58,7 @@
 
 #include "fc_libfc.h"
 
-struct workqueue_struct *rport_event_queue;
+static struct workqueue_struct *rport_event_queue;
 
 static void fc_rport_enter_flogi(struct fc_rport_priv *);
 static void fc_rport_enter_plogi(struct fc_rport_priv *);
@@ -145,8 +145,10 @@ static struct fc_rport_priv *fc_rport_create(struct fc_lport *lport,
 	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
-	if (port_id != FC_FID_DIR_SERV)
+	if (port_id != FC_FID_DIR_SERV) {
+		rdata->lld_event_callback = lport->tt.rport_event_callback;
 		list_add_rcu(&rdata->peers, &lport->disc.rports);
+	}
 	return rdata;
 }
 
@@ -257,6 +259,8 @@ static void fc_rport_work(struct work_struct *work)
 	struct fc_rport_operations *rport_ops;
 	struct fc_rport_identifiers ids;
 	struct fc_rport *rport;
+	struct fc4_prov *prov;
+	u8 type;
 
 	mutex_lock(&rdata->rp_mutex);
 	event = rdata->event;
@@ -300,12 +304,25 @@ static void fc_rport_work(struct work_struct *work)
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
 		}
+		if (rdata->lld_event_callback) {
+			FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
+			rdata->lld_event_callback(lport, rdata, event);
+		}
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 		break;
 
 	case RPORT_EV_FAILED:
 	case RPORT_EV_LOGO:
 	case RPORT_EV_STOP:
+		if (rdata->prli_count) {
+			mutex_lock(&fc_prov_mutex);
+			for (type = 1; type < FC_FC4_PROV_SIZE; type++) {
+				prov = fc_passive_prov[type];
+				if (prov && prov->prlo)
+					prov->prlo(rdata);
+			}
+			mutex_unlock(&fc_prov_mutex);
+		}
 		port_id = rdata->ids.port_id;
 		mutex_unlock(&rdata->rp_mutex);
 
@@ -313,6 +330,10 @@ static void fc_rport_work(struct work_struct *work)
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
 		}
+		if (rdata->lld_event_callback) {
+			FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
+			rdata->lld_event_callback(lport, rdata, event);
+		}
 		cancel_delayed_work_sync(&rdata->retry_work);
 
 		/*
@@ -336,6 +357,7 @@ static void fc_rport_work(struct work_struct *work)
 			if (port_id == FC_FID_DIR_SERV) {
 				rdata->event = RPORT_EV_NONE;
 				mutex_unlock(&rdata->rp_mutex);
+				kref_put(&rdata->kref, lport->tt.rport_destroy);
 			} else if ((rdata->flags & FC_RP_STARTED) &&
 				   rdata->major_retries <
 				   lport->max_rport_retry_count) {
@@ -575,7 +597,7 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
 
 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
 	if (PTR_ERR(fp) == -FC_EX_CLOSED)
-		return fc_rport_error(rdata, fp);
+		goto out;
 
 	if (rdata->retries < rdata->local_port->max_rport_retry_count) {
 		FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
@@ -588,7 +610,8 @@ static void fc_rport_error_retry(struct fc_rport_priv *rdata,
 		return;
 	}
 
-	return fc_rport_error(rdata, fp);
+out:
+	fc_rport_error(rdata, fp);
 }
 
 /**
@@ -878,6 +901,9 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 		rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
 		rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
 
+		/* save plogi response sp_features for further reference */
+		rdata->sp_features = ntohs(plp->fl_csp.sp_features);
+
 		if (lport->point_to_multipoint)
 			fc_rport_login_complete(rdata, fp);
 		csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
@@ -949,6 +975,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		struct fc_els_prli prli;
 		struct fc_els_spp spp;
 	} *pp;
+	struct fc_els_spp temp_spp;
+	struct fc4_prov *prov;
 	u32 roles = FC_RPORT_ROLE_UNKNOWN;
 	u32 fcp_parm = 0;
 	u8 op;
@@ -983,6 +1011,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
 		FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
 			     pp->spp.spp_flags);
+		rdata->spp_type = pp->spp.spp_type;
 		if (resp_code != FC_SPP_RESP_ACK) {
 			if (resp_code == FC_SPP_RESP_CONF)
 				fc_rport_error(rdata, fp);
@@ -996,6 +1025,15 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
 		fcp_parm = ntohl(pp->spp.spp_params);
 		if (fcp_parm & FCP_SPPF_RETRY)
 			rdata->flags |= FC_RP_FLAGS_RETRY;
+		if (fcp_parm & FCP_SPPF_CONF_COMPL)
+			rdata->flags |= FC_RP_FLAGS_CONF_REQ;
+
+		prov = fc_passive_prov[FC_TYPE_FCP];
+		if (prov) {
+			memset(&temp_spp, 0, sizeof(temp_spp));
+			prov->prli(rdata, pp->prli.prli_spp_len,
+				   &pp->spp, &temp_spp);
+		}
 
 		rdata->supported_classes = FC_COS_CLASS3;
 		if (fcp_parm & FCP_SPPF_INIT_FCN)
@@ -1033,6 +1071,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 		struct fc_els_spp spp;
 	} *pp;
 	struct fc_frame *fp;
+	struct fc4_prov *prov;
 
 	/*
 	 * If the rport is one of the well known addresses
@@ -1054,9 +1093,20 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata)
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI,
-				  fc_rport_prli_resp, rdata,
-				  2 * lport->r_a_tov))
+	fc_prli_fill(lport, fp);
+
+	prov = fc_passive_prov[FC_TYPE_FCP];
+	if (prov) {
+		pp = fc_frame_payload_get(fp, sizeof(*pp));
+		prov->prli(rdata, sizeof(pp->spp), NULL, &pp->spp);
+	}
+
+	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rdata->ids.port_id,
+		       fc_host_port_id(lport->host), FC_TYPE_ELS,
+		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
+
+	if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
+				    NULL, rdata, 2 * lport->r_a_tov))
 		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
@@ -1642,9 +1692,9 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 	unsigned int len;
 	unsigned int plen;
 	enum fc_els_spp_resp resp;
+	enum fc_els_spp_resp passive;
 	struct fc_seq_els_data rjt_data;
-	u32 fcp_parm;
-	u32 roles = FC_RPORT_ROLE_UNKNOWN;
+	struct fc4_prov *prov;
 
 	FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
 		     fc_rport_state(rdata));
@@ -1678,46 +1728,42 @@ static void fc_rport_recv_prli_req(struct fc_rport_priv *rdata,
 	pp->prli.prli_len = htons(len);
 	len -= sizeof(struct fc_els_prli);
 
-	/* reinitialize remote port roles */
-	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
-
 	/*
 	 * Go through all the service parameter pages and build
 	 * response.  If plen indicates longer SPP than standard,
 	 * use that.  The entire response has been pre-cleared above.
 	 */
 	spp = &pp->spp;
+	mutex_lock(&fc_prov_mutex);
 	while (len >= plen) {
+		rdata->spp_type = rspp->spp_type;
 		spp->spp_type = rspp->spp_type;
 		spp->spp_type_ext = rspp->spp_type_ext;
-		spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
-		resp = FC_SPP_RESP_ACK;
-
-		switch (rspp->spp_type) {
-		case 0:	/* common to all FC-4 types */
-			break;
-		case FC_TYPE_FCP:
-			fcp_parm = ntohl(rspp->spp_params);
-			if (fcp_parm & FCP_SPPF_RETRY)
-				rdata->flags |= FC_RP_FLAGS_RETRY;
-			rdata->supported_classes = FC_COS_CLASS3;
-			if (fcp_parm & FCP_SPPF_INIT_FCN)
-				roles |= FC_RPORT_ROLE_FCP_INITIATOR;
-			if (fcp_parm & FCP_SPPF_TARG_FCN)
-				roles |= FC_RPORT_ROLE_FCP_TARGET;
-			rdata->ids.roles = roles;
-
-			spp->spp_params = htonl(lport->service_params);
-			break;
-		default:
-			resp = FC_SPP_RESP_INVL;
-			break;
+		resp = 0;
+
+		if (rspp->spp_type < FC_FC4_PROV_SIZE) {
+			prov = fc_active_prov[rspp->spp_type];
+			if (prov)
+				resp = prov->prli(rdata, plen, rspp, spp);
+			prov = fc_passive_prov[rspp->spp_type];
+			if (prov) {
+				passive = prov->prli(rdata, plen, rspp, spp);
+				if (!resp || passive == FC_SPP_RESP_ACK)
+					resp = passive;
+			}
+		}
+		if (!resp) {
+			if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)
+				resp |= FC_SPP_RESP_CONF;
+			else
+				resp |= FC_SPP_RESP_INVL;
 		}
 		spp->spp_flags |= resp;
 		len -= plen;
 		rspp = (struct fc_els_spp *)((char *)rspp + plen);
 		spp = (struct fc_els_spp *)((char *)spp + plen);
 	}
+	mutex_unlock(&fc_prov_mutex);
 
 	/*
 	 * Send LS_ACC.	 If this fails, the originator should retry.
@@ -1887,9 +1933,82 @@ int fc_rport_init(struct fc_lport *lport)
 EXPORT_SYMBOL(fc_rport_init);
 
 /**
+ * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator.
+ * @rdata: remote port private
+ * @spp_len: service parameter page length
+ * @rspp: received service parameter page
+ * @spp: response service parameter page
+ *
+ * Returns the value for the response code to be placed in spp_flags;
+ * Returns 0 if not an initiator.
+ */
+static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len,
+			     const struct fc_els_spp *rspp,
+			     struct fc_els_spp *spp)
+{
+	struct fc_lport *lport = rdata->local_port;
+	u32 fcp_parm;
+
+	fcp_parm = ntohl(rspp->spp_params);
+	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
+	if (fcp_parm & FCP_SPPF_INIT_FCN)
+		rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+	if (fcp_parm & FCP_SPPF_TARG_FCN)
+		rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+	if (fcp_parm & FCP_SPPF_RETRY)
+		rdata->flags |= FC_RP_FLAGS_RETRY;
+	rdata->supported_classes = FC_COS_CLASS3;
+
+	if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR))
+		return 0;
+
+	spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
+
+	/*
+	 * OR in our service parameters with other providers (target), if any.
+	 */
+	fcp_parm = ntohl(spp->spp_params);
+	spp->spp_params = htonl(fcp_parm | lport->service_params);
+	return FC_SPP_RESP_ACK;
+}
+
+/*
+ * FC-4 provider ops for FCP initiator.
+ */
+struct fc4_prov fc_rport_fcp_init = {
+	.prli = fc_rport_fcp_prli,
+};
+
+/**
+ * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0
+ * @rdata: remote port private
+ * @spp_len: service parameter page length
+ * @rspp: received service parameter page
+ * @spp: response service parameter page
+ */
+static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len,
+			    const struct fc_els_spp *rspp,
+			    struct fc_els_spp *spp)
+{
+	if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR)
+		return FC_SPP_RESP_INVL;
+	return FC_SPP_RESP_ACK;
+}
+
+/*
+ * FC-4 provider ops for type 0 service parameters.
+ *
+ * This handles the special case of type 0 which is always successful
+ * but doesn't do anything otherwise.
+ */
+struct fc4_prov fc_rport_t0_prov = {
+	.prli = fc_rport_t0_prli,
+};
+
+/**
  * fc_setup_rport() - Initialize the rport_event_queue
  */
-int fc_setup_rport()
+int fc_setup_rport(void)
 {
 	rport_event_queue = create_singlethread_workqueue("fc_rport_eq");
 	if (!rport_event_queue)
@@ -1900,7 +2019,7 @@ int fc_setup_rport()
 /**
  * fc_destroy_rport() - Destroy the rport_event_queue
  */
-void fc_destroy_rport()
+void fc_destroy_rport(void)
 {
 	destroy_workqueue(rport_event_queue);
 }
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index da8b615..0c550d5 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -3352,6 +3352,47 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session,
 }
 EXPORT_SYMBOL_GPL(iscsi_session_get_param);
 
+int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
+			      enum iscsi_param param, char *buf)
+{
+	struct sockaddr_in6 *sin6 = NULL;
+	struct sockaddr_in *sin = NULL;
+	int len;
+
+	switch (addr->ss_family) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)addr;
+		break;
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)addr;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_ADDRESS:
+	case ISCSI_HOST_PARAM_IPADDRESS:
+		if (sin)
+			len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr);
+		else
+			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
+		break;
+	case ISCSI_PARAM_CONN_PORT:
+		if (sin)
+			len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
+		else
+			len = sprintf(buf, "%hu\n",
+				      be16_to_cpu(sin6->sin6_port));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_get_addr_param);
+
 int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
 			 enum iscsi_param param, char *buf)
 {
@@ -3416,9 +3457,6 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param,
 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
 		len = sprintf(buf, "%s\n", ihost->initiatorname);
 		break;
-	case ISCSI_HOST_PARAM_IPADDRESS:
-		len = sprintf(buf, "%s\n", ihost->local_address);
-		break;
 	default:
 		return -ENOSYS;
 	}
diff --git a/drivers/scsi/libsas/Kconfig b/drivers/scsi/libsas/Kconfig
index 18f33cd..9dafe64 100644
--- a/drivers/scsi/libsas/Kconfig
+++ b/drivers/scsi/libsas/Kconfig
@@ -46,11 +46,3 @@ config SCSI_SAS_HOST_SMP
 		Allows sas hosts to receive SMP frames.  Selecting this
 		option builds an SMP interpreter into libsas.  Say
 		N here if you want to save the few kb this consumes.
-
-config SCSI_SAS_LIBSAS_DEBUG
-	bool "Compile the SAS Domain Transport Attributes in debug mode"
-	default y
-	depends on SCSI_SAS_LIBSAS
-	help
-		Compiles the SAS Layer in debug mode.  In debug mode, the
-		SAS Layer prints diagnostic and debug messages.
diff --git a/drivers/scsi/libsas/Makefile b/drivers/scsi/libsas/Makefile
index 1ad1323..2e70140 100644
--- a/drivers/scsi/libsas/Makefile
+++ b/drivers/scsi/libsas/Makefile
@@ -21,10 +21,6 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-ifeq ($(CONFIG_SCSI_SAS_LIBSAS_DEBUG),y)
-	EXTRA_CFLAGS += -DSAS_DEBUG
-endif
-
 obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas.o
 libsas-y +=  sas_init.o     \
 		sas_phy.o      \
@@ -36,4 +32,4 @@ libsas-y +=  sas_init.o     \
 		sas_scsi_host.o \
 		sas_task.o
 libsas-$(CONFIG_SCSI_SAS_ATA) +=	sas_ata.o
-libsas-$(CONFIG_SCSI_SAS_HOST_SMP) +=	sas_host_smp.o
\ No newline at end of file
+libsas-$(CONFIG_SCSI_SAS_HOST_SMP) +=	sas_host_smp.o
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index e1a395b..31fc21f 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -71,13 +71,13 @@ static enum ata_completion_errors sas_to_ata_err(struct task_status_struct *ts)
 		case SAS_SG_ERR:
 			return AC_ERR_INVALID;
 
-		case SAM_STAT_CHECK_CONDITION:
 		case SAS_OPEN_TO:
 		case SAS_OPEN_REJECT:
 			SAS_DPRINTK("%s: Saw error %d.  What to do?\n",
 				    __func__, ts->stat);
 			return AC_ERR_OTHER;
 
+		case SAM_STAT_CHECK_CONDITION:
 		case SAS_ABORTED_TASK:
 			return AC_ERR_DEV;
 
@@ -107,13 +107,15 @@ static void sas_ata_task_done(struct sas_task *task)
 	sas_ha = dev->port->ha;
 
 	spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
-	if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD) {
+	if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
+	    ((stat->stat == SAM_STAT_CHECK_CONDITION &&
+	      dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
 		ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
 		qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
 		dev->sata_dev.sstatus = resp->sstatus;
 		dev->sata_dev.serror = resp->serror;
 		dev->sata_dev.scontrol = resp->scontrol;
-	} else if (stat->stat != SAM_STAT_GOOD) {
+	} else {
 		ac = sas_to_ata_err(stat);
 		if (ac) {
 			SAS_DPRINTK("%s: SAS error %x\n", __func__,
@@ -238,37 +240,43 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc)
 	return true;
 }
 
-static void sas_ata_phy_reset(struct ata_port *ap)
+static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
+			       unsigned long deadline)
 {
+	struct ata_port *ap = link->ap;
 	struct domain_device *dev = ap->private_data;
 	struct sas_internal *i =
 		to_sas_internal(dev->port->ha->core.shost->transportt);
 	int res = TMF_RESP_FUNC_FAILED;
+	int ret = 0;
 
 	if (i->dft->lldd_I_T_nexus_reset)
 		res = i->dft->lldd_I_T_nexus_reset(dev);
 
-	if (res != TMF_RESP_FUNC_COMPLETE)
+	if (res != TMF_RESP_FUNC_COMPLETE) {
 		SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__);
+		ret = -EAGAIN;
+	}
 
 	switch (dev->sata_dev.command_set) {
 		case ATA_COMMAND_SET:
 			SAS_DPRINTK("%s: Found ATA device.\n", __func__);
-			ap->link.device[0].class = ATA_DEV_ATA;
+			*class = ATA_DEV_ATA;
 			break;
 		case ATAPI_COMMAND_SET:
 			SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
-			ap->link.device[0].class = ATA_DEV_ATAPI;
+			*class = ATA_DEV_ATAPI;
 			break;
 		default:
 			SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
 				    __func__,
 				    dev->sata_dev.command_set);
-			ap->link.device[0].class = ATA_DEV_UNKNOWN;
+			*class = ATA_DEV_UNKNOWN;
 			break;
 	}
 
 	ap->cbl = ATA_CBL_SATA;
+	return ret;
 }
 
 static void sas_ata_post_internal(struct ata_queued_cmd *qc)
@@ -299,57 +307,12 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)
 	}
 }
 
-static int sas_ata_scr_write(struct ata_link *link, unsigned int sc_reg_in,
-			      u32 val)
-{
-	struct domain_device *dev = link->ap->private_data;
-
-	SAS_DPRINTK("STUB %s\n", __func__);
-	switch (sc_reg_in) {
-		case SCR_STATUS:
-			dev->sata_dev.sstatus = val;
-			break;
-		case SCR_CONTROL:
-			dev->sata_dev.scontrol = val;
-			break;
-		case SCR_ERROR:
-			dev->sata_dev.serror = val;
-			break;
-		case SCR_ACTIVE:
-			dev->sata_dev.ap->link.sactive = val;
-			break;
-		default:
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in,
-			    u32 *val)
-{
-	struct domain_device *dev = link->ap->private_data;
-
-	SAS_DPRINTK("STUB %s\n", __func__);
-	switch (sc_reg_in) {
-		case SCR_STATUS:
-			*val = dev->sata_dev.sstatus;
-			return 0;
-		case SCR_CONTROL:
-			*val = dev->sata_dev.scontrol;
-			return 0;
-		case SCR_ERROR:
-			*val = dev->sata_dev.serror;
-			return 0;
-		case SCR_ACTIVE:
-			*val = dev->sata_dev.ap->link.sactive;
-			return 0;
-		default:
-			return -EINVAL;
-	}
-}
-
 static struct ata_port_operations sas_sata_ops = {
-	.phy_reset		= sas_ata_phy_reset,
+	.prereset		= ata_std_prereset,
+	.softreset		= NULL,
+	.hardreset		= sas_ata_hard_reset,
+	.postreset		= ata_std_postreset,
+	.error_handler		= ata_std_error_handler,
 	.post_internal_cmd	= sas_ata_post_internal,
 	.qc_defer               = ata_std_qc_defer,
 	.qc_prep		= ata_noop_qc_prep,
@@ -357,15 +320,12 @@ static struct ata_port_operations sas_sata_ops = {
 	.qc_fill_rtf		= sas_ata_qc_fill_rtf,
 	.port_start		= ata_sas_port_start,
 	.port_stop		= ata_sas_port_stop,
-	.scr_read		= sas_ata_scr_read,
-	.scr_write		= sas_ata_scr_write
 };
 
 static struct ata_port_info sata_port_info = {
-	.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
-		ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ,
-	.pio_mask = 0x1f, /* PIO0-4 */
-	.mwdma_mask = 0x07, /* MWDMA0-2 */
+	.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ,
+	.pio_mask = ATA_PIO4,
+	.mwdma_mask = ATA_MWDMA2,
 	.udma_mask = ATA_UDMA6,
 	.port_ops = &sas_sata_ops
 };
@@ -781,3 +741,81 @@ int sas_discover_sata(struct domain_device *dev)
 
 	return res;
 }
+
+void sas_ata_strategy_handler(struct Scsi_Host *shost)
+{
+	struct scsi_device *sdev;
+
+	shost_for_each_device(sdev, shost) {
+		struct domain_device *ddev = sdev_to_domain_dev(sdev);
+		struct ata_port *ap = ddev->sata_dev.ap;
+
+		if (!dev_is_sata(ddev))
+			continue;
+
+		ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");
+		ata_scsi_port_error_handler(shost, ap);
+	}
+}
+
+int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
+		      enum blk_eh_timer_return *rtn)
+{
+	struct domain_device *ddev = cmd_to_domain_dev(cmd);
+
+	if (!dev_is_sata(ddev) || task)
+		return 0;
+
+	/* we're a sata device with no task, so this must be a libata
+	 * eh timeout.  Ideally should hook into libata timeout
+	 * handling, but there's no point, it just wants to activate
+	 * the eh thread */
+	*rtn = BLK_EH_NOT_HANDLED;
+	return 1;
+}
+
+int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
+	       struct list_head *done_q)
+{
+	int rtn = 0;
+	struct scsi_cmnd *cmd, *n;
+	struct ata_port *ap;
+
+	do {
+		LIST_HEAD(sata_q);
+
+		ap = NULL;
+
+		list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
+			struct domain_device *ddev = cmd_to_domain_dev(cmd);
+
+			if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
+				continue;
+			if (ap && ap != ddev->sata_dev.ap)
+				continue;
+			ap = ddev->sata_dev.ap;
+			rtn = 1;
+			list_move(&cmd->eh_entry, &sata_q);
+		}
+
+		if (!list_empty(&sata_q)) {
+			ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata cmd error handler\n");
+			ata_scsi_cmd_error_handler(shost, ap, &sata_q);
+			/*
+			 * ata's error handler may leave the cmd on the list
+			 * so make sure they don't remain on a stack list
+			 * about to go out of scope.
+			 *
+			 * This looks strange, since the commands are
+			 * now part of no list, but the next error
+			 * action will be ata_port_error_handler()
+			 * which takes no list and sweeps them up
+			 * anyway from the ata tag array.
+			 */
+			while (!list_empty(&sata_q))
+				list_del_init(sata_q.next);
+		}
+	} while (ap);
+
+	return rtn;
+}
diff --git a/drivers/scsi/libsas/sas_dump.c b/drivers/scsi/libsas/sas_dump.c
index c17c250..fc46093 100644
--- a/drivers/scsi/libsas/sas_dump.c
+++ b/drivers/scsi/libsas/sas_dump.c
@@ -24,8 +24,6 @@
 
 #include "sas_dump.h"
 
-#ifdef SAS_DEBUG
-
 static const char *sas_hae_str[] = {
 	[0] = "HAE_RESET",
 };
@@ -72,5 +70,3 @@ void sas_dump_port(struct asd_sas_port *port)
 	SAS_DPRINTK("port%d: oob_mode:0x%x\n", port->id, port->oob_mode);
 	SAS_DPRINTK("port%d: num_phys:%d\n", port->id, port->num_phys);
 }
-
-#endif /* SAS_DEBUG */
diff --git a/drivers/scsi/libsas/sas_dump.h b/drivers/scsi/libsas/sas_dump.h
index 47b45d4..800e4c6 100644
--- a/drivers/scsi/libsas/sas_dump.h
+++ b/drivers/scsi/libsas/sas_dump.h
@@ -24,19 +24,7 @@
 
 #include "sas_internal.h"
 
-#ifdef SAS_DEBUG
-
 void sas_dprint_porte(int phyid, enum port_event pe);
 void sas_dprint_phye(int phyid, enum phy_event pe);
 void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he);
 void sas_dump_port(struct asd_sas_port *port);
-
-#else /* SAS_DEBUG */
-
-static inline void sas_dprint_porte(int phyid, enum port_event pe) { }
-static inline void sas_dprint_phye(int phyid, enum phy_event pe) { }
-static inline void sas_dprint_hae(struct sas_ha_struct *sas_ha,
-				  enum ha_event he) { }
-static inline void sas_dump_port(struct asd_sas_port *port) { }
-
-#endif /* SAS_DEBUG */
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 505ffe3..f3f693b 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -244,6 +244,11 @@ static int sas_ex_phy_discover_helper(struct domain_device *dev, u8 *disc_req,
 		 * dev to host FIS as described in section G.5 of
 		 * sas-2 r 04b */
 		dr = &((struct smp_resp *)disc_resp)->disc;
+		if (memcmp(dev->sas_addr, dr->attached_sas_addr,
+			  SAS_ADDR_SIZE) == 0) {
+			sas_printk("Found loopback topology, just ignore it!\n");
+			return 0;
+		}
 		if (!(dr->attached_dev_type == 0 &&
 		      dr->attached_sata_dev))
 			break;
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 0001374..8b538bd 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -33,11 +33,7 @@
 
 #define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__)
 
-#ifdef SAS_DEBUG
-#define SAS_DPRINTK(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__)
-#else
-#define SAS_DPRINTK(fmt, ...)
-#endif
+#define SAS_DPRINTK(fmt, ...) printk(KERN_DEBUG "sas: " fmt, ## __VA_ARGS__)
 
 #define TO_SAS_TASK(_scsi_cmd)  ((void *)(_scsi_cmd)->host_scribble)
 #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 9a7aaf5..f6e189f 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -663,11 +663,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
 	 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
 	 * command we see here has no sas_task and is thus unknown to the HA.
 	 */
-	if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
-		scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
+	if (!sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q))
+		if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
+			scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
 
 out:
+	/* now link into libata eh --- if we have any ata devices */
+	sas_ata_strategy_handler(shost);
+
 	scsi_eh_flush_done_q(&ha->eh_done_q);
+
 	SAS_DPRINTK("--- Exit %s\n", __func__);
 	return;
 }
@@ -676,6 +681,10 @@ enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
 {
 	struct sas_task *task = TO_SAS_TASK(cmd);
 	unsigned long flags;
+	enum blk_eh_timer_return rtn;
+
+	if (sas_ata_timed_out(cmd, task, &rtn))
+		return rtn;
 
 	if (!task) {
 		cmd->request->timeout /= 2;
diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile
index ad05d6e..14de249 100644
--- a/drivers/scsi/lpfc/Makefile
+++ b/drivers/scsi/lpfc/Makefile
@@ -19,10 +19,8 @@
 # *******************************************************************/
 ######################################################################
 
-ifneq ($(GCOV),)
-  EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage
-  EXTRA_CFLAGS += -O0
-endif
+ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage
+ccflags-$(GCOV) += -O0
 
 obj-$(CONFIG_SCSI_LPFC) := lpfc.o
 
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 746dd3d..b64c6da 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -325,6 +325,7 @@ struct lpfc_vport {
 #define FC_VPORT_CVL_RCVD	0x400000 /* VLink failed due to CVL	 */
 #define FC_VFI_REGISTERED	0x800000 /* VFI is registered */
 #define FC_FDISC_COMPLETED	0x1000000/* FDISC completed */
+#define FC_DISC_DELAYED		0x2000000/* Delay NPort discovery */
 
 	uint32_t ct_flags;
 #define FC_CT_RFF_ID		0x1	 /* RFF_ID accepted by switch */
@@ -348,6 +349,8 @@ struct lpfc_vport {
 
 	uint32_t fc_myDID;	/* fibre channel S_ID */
 	uint32_t fc_prevDID;	/* previous fibre channel S_ID */
+	struct lpfc_name fabric_portname;
+	struct lpfc_name fabric_nodename;
 
 	int32_t stopped;   /* HBA has not been restarted since last ERATT */
 	uint8_t fc_linkspeed;	/* Link speed after last READ_LA */
@@ -372,6 +375,7 @@ struct lpfc_vport {
 #define WORKER_DISC_TMO                0x1	/* vport: Discovery timeout */
 #define WORKER_ELS_TMO                 0x2	/* vport: ELS timeout */
 #define WORKER_FDMI_TMO                0x4	/* vport: FDMI timeout */
+#define WORKER_DELAYED_DISC_TMO        0x8	/* vport: delayed discovery */
 
 #define WORKER_MBOX_TMO                0x100	/* hba: MBOX timeout */
 #define WORKER_HB_TMO                  0x200	/* hba: Heart beat timeout */
@@ -382,6 +386,7 @@ struct lpfc_vport {
 
 	struct timer_list fc_fdmitmo;
 	struct timer_list els_tmofunc;
+	struct timer_list delayed_disc_tmo;
 
 	int unreg_vpi_cmpl;
 
@@ -548,6 +553,8 @@ struct lpfc_hba {
 #define LPFC_SLI3_CRP_ENABLED		0x08
 #define LPFC_SLI3_BG_ENABLED		0x20
 #define LPFC_SLI3_DSS_ENABLED		0x40
+#define LPFC_SLI4_PERFH_ENABLED		0x80
+#define LPFC_SLI4_PHWQ_ENABLED		0x100
 	uint32_t iocb_cmd_size;
 	uint32_t iocb_rsp_size;
 
@@ -655,7 +662,7 @@ struct lpfc_hba {
 #define LPFC_INITIALIZE_LINK              0	/* do normal init_link mbox */
 #define LPFC_DELAY_INIT_LINK              1	/* layered driver hold off */
 #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2	/* wait, manual intervention */
-
+	uint32_t cfg_enable_dss;
 	lpfc_vpd_t vpd;		/* vital product data */
 
 	struct pci_dev *pcidev;
@@ -792,6 +799,10 @@ struct lpfc_hba {
 	struct dentry *debug_slow_ring_trc;
 	struct lpfc_debugfs_trc *slow_ring_trc;
 	atomic_t slow_ring_trc_cnt;
+	/* iDiag debugfs sub-directory */
+	struct dentry *idiag_root;
+	struct dentry *idiag_pci_cfg;
+	struct dentry *idiag_que_info;
 #endif
 
 	/* Used for deferred freeing of ELS data buffers */
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 3512abb..e7c020d 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -623,10 +623,14 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
 	int status = 0;
 	int cnt = 0;
 	int i;
+	int rc;
 
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &status, &online_compl,
+	rc = lpfc_workq_post_event(phba, &status, &online_compl,
 			      LPFC_EVT_OFFLINE_PREP);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
@@ -652,7 +656,10 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
 	}
 
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &status, &online_compl, type);
+	rc = lpfc_workq_post_event(phba, &status, &online_compl, type);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
@@ -671,6 +678,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
  *
  * Notes:
  * Assumes any error from lpfc_do_offline() will be negative.
+ * Do not make this function static.
  *
  * Returns:
  * lpfc_do_offline() return code if not zero
@@ -682,6 +690,7 @@ lpfc_selective_reset(struct lpfc_hba *phba)
 {
 	struct completion online_compl;
 	int status = 0;
+	int rc;
 
 	if (!phba->cfg_enable_hba_reset)
 		return -EIO;
@@ -692,8 +701,11 @@ lpfc_selective_reset(struct lpfc_hba *phba)
 		return status;
 
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &status, &online_compl,
+	rc = lpfc_workq_post_event(phba, &status, &online_compl,
 			      LPFC_EVT_ONLINE);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
@@ -812,14 +824,17 @@ lpfc_board_mode_store(struct device *dev, struct device_attribute *attr,
 	struct lpfc_hba   *phba = vport->phba;
 	struct completion online_compl;
 	int status=0;
+	int rc;
 
 	if (!phba->cfg_enable_hba_reset)
 		return -EACCES;
 	init_completion(&online_compl);
 
 	if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
-		lpfc_workq_post_event(phba, &status, &online_compl,
+		rc = lpfc_workq_post_event(phba, &status, &online_compl,
 				      LPFC_EVT_ONLINE);
+		if (rc == 0)
+			return -ENOMEM;
 		wait_for_completion(&online_compl);
 	} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
 		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -1279,6 +1294,28 @@ lpfc_fips_rev_show(struct device *dev,  struct device_attribute *attr,
 }
 
 /**
+ * lpfc_dss_show - Return the current state of dss and the configured state
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the formatted text.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_dss_show(struct device *dev, struct device_attribute *attr,
+	      char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
+	return snprintf(buf, PAGE_SIZE, "%s - %sOperational\n",
+			(phba->cfg_enable_dss) ? "Enabled" : "Disabled",
+			(phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ?
+				"" : "Not ");
+}
+
+/**
  * lpfc_param_show - Return a cfg attribute value in decimal
  *
  * Description:
@@ -1597,13 +1634,13 @@ lpfc_##attr##_store(struct device *dev, struct device_attribute *attr, \
 
 #define LPFC_ATTR(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_init(name, defval, minval, maxval)
 
 #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1611,7 +1648,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
 
 #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1622,7 +1659,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
 
 #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_hex_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1630,7 +1667,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
 
 #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_hex_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1641,13 +1678,13 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
 
 #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_init(name, defval, minval, maxval)
 
 #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1655,7 +1692,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
 
 #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1666,7 +1703,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
 
 #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_hex_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1674,7 +1711,7 @@ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL)
 
 #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_hex_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1718,7 +1755,7 @@ static DEVICE_ATTR(npiv_info, S_IRUGO, lpfc_npiv_info_show, NULL);
 static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
 static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL);
 static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL);
-
+static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL);
 
 static char *lpfc_soft_wwn_key = "C99G71SL8032A";
 
@@ -1813,6 +1850,7 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
 	int stat1=0, stat2=0;
 	unsigned int i, j, cnt=count;
 	u8 wwpn[8];
+	int rc;
 
 	if (!phba->cfg_enable_hba_reset)
 		return -EACCES;
@@ -1863,7 +1901,11 @@ lpfc_soft_wwpn_store(struct device *dev, struct device_attribute *attr,
 				"0463 lpfc_soft_wwpn attribute set failed to "
 				"reinit adapter - %d\n", stat1);
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE);
+	rc = lpfc_workq_post_event(phba, &stat2, &online_compl,
+				   LPFC_EVT_ONLINE);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 	if (stat2)
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -1954,7 +1996,7 @@ static DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
 
 
 static int lpfc_poll = 0;
-module_param(lpfc_poll, int, 0);
+module_param(lpfc_poll, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
 		 " 0 - none,"
 		 " 1 - poll with interrupts enabled"
@@ -1964,21 +2006,21 @@ static DEVICE_ATTR(lpfc_poll, S_IRUGO | S_IWUSR,
 		   lpfc_poll_show, lpfc_poll_store);
 
 int  lpfc_sli_mode = 0;
-module_param(lpfc_sli_mode, int, 0);
+module_param(lpfc_sli_mode, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
 		 " 0 - auto (SLI-3 if supported),"
 		 " 2 - select SLI-2 even on SLI-3 capable HBAs,"
 		 " 3 - select SLI-3");
 
 int lpfc_enable_npiv = 1;
-module_param(lpfc_enable_npiv, int, 0);
+module_param(lpfc_enable_npiv, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");
 lpfc_param_show(enable_npiv);
 lpfc_param_init(enable_npiv, 1, 0, 1);
 static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
 
 int lpfc_enable_rrq;
-module_param(lpfc_enable_rrq, int, 0);
+module_param(lpfc_enable_rrq, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
 lpfc_param_show(enable_rrq);
 lpfc_param_init(enable_rrq, 0, 0, 1);
@@ -2040,7 +2082,7 @@ static DEVICE_ATTR(txcmplq_hw, S_IRUGO,
 			 lpfc_txcmplq_hw_show, NULL);
 
 int lpfc_iocb_cnt = 2;
-module_param(lpfc_iocb_cnt, int, 1);
+module_param(lpfc_iocb_cnt, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_iocb_cnt,
 	"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
 lpfc_param_show(iocb_cnt);
@@ -2192,7 +2234,7 @@ static DEVICE_ATTR(lpfc_nodev_tmo, S_IRUGO | S_IWUSR,
 # disappear until the timer expires. Value range is [0,255]. Default
 # value is 30.
 */
-module_param(lpfc_devloss_tmo, int, 0);
+module_param(lpfc_devloss_tmo, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_devloss_tmo,
 		 "Seconds driver will hold I/O waiting "
 		 "for a device to come back");
@@ -2302,7 +2344,7 @@ LPFC_VPORT_ATTR_R(peer_port_login, 0, 0, 1,
 # Default value of this parameter is 1.
 */
 static int lpfc_restrict_login = 1;
-module_param(lpfc_restrict_login, int, 0);
+module_param(lpfc_restrict_login, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_restrict_login,
 		 "Restrict virtual ports login to remote initiators.");
 lpfc_vport_param_show(restrict_login);
@@ -2473,7 +2515,7 @@ lpfc_topology_store(struct device *dev, struct device_attribute *attr,
 	return -EINVAL;
 }
 static int lpfc_topology = 0;
-module_param(lpfc_topology, int, 0);
+module_param(lpfc_topology, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
 lpfc_param_show(topology)
 lpfc_param_init(topology, 0, 0, 6)
@@ -2915,7 +2957,7 @@ lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
 }
 
 static int lpfc_link_speed = 0;
-module_param(lpfc_link_speed, int, 0);
+module_param(lpfc_link_speed, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
 lpfc_param_show(link_speed)
 
@@ -3043,7 +3085,7 @@ lpfc_aer_support_store(struct device *dev, struct device_attribute *attr,
 }
 
 static int lpfc_aer_support = 1;
-module_param(lpfc_aer_support, int, 1);
+module_param(lpfc_aer_support, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support");
 lpfc_param_show(aer_support)
 
@@ -3155,7 +3197,7 @@ LPFC_VPORT_ATTR_RW(use_adisc, 0, 0, 1,
 # The value is set in milliseconds.
 */
 static int lpfc_max_scsicmpl_time;
-module_param(lpfc_max_scsicmpl_time, int, 0);
+module_param(lpfc_max_scsicmpl_time, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_max_scsicmpl_time,
 	"Use command completion time to control queue depth");
 lpfc_vport_param_show(max_scsicmpl_time);
@@ -3331,7 +3373,7 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support");
 */
 unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION;
 
-module_param(lpfc_prot_mask, uint, 0);
+module_param(lpfc_prot_mask, uint, S_IRUGO);
 MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
 
 /*
@@ -3343,9 +3385,28 @@ MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
 #
 */
 unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP;
-module_param(lpfc_prot_guard, byte, 0);
+module_param(lpfc_prot_guard, byte, S_IRUGO);
 MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type");
 
+/*
+ * Delay initial NPort discovery when Clean Address bit is cleared in
+ * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed.
+ * This parameter can have value 0 or 1.
+ * When this parameter is set to 0, no delay is added to the initial
+ * discovery.
+ * When this parameter is set to non-zero value, initial Nport discovery is
+ * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC
+ * accept and FCID/Fabric name/Fabric portname is changed.
+ * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion
+ * when Clean Address bit is cleared in FLOGI/FDISC
+ * accept and FCID/Fabric name/Fabric portname is changed.
+ * Default value is 0.
+ */
+int lpfc_delay_discovery;
+module_param(lpfc_delay_discovery, int, S_IRUGO);
+MODULE_PARM_DESC(lpfc_delay_discovery,
+	"Delay NPort discovery when Clean Address bit is cleared. "
+	"Allowed values: 0,1.");
 
 /*
  * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
@@ -3437,6 +3498,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
 	&dev_attr_txcmplq_hw,
 	&dev_attr_lpfc_fips_level,
 	&dev_attr_lpfc_fips_rev,
+	&dev_attr_lpfc_dss,
 	NULL,
 };
 
@@ -4639,6 +4701,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
 	lpfc_aer_support_init(phba, lpfc_aer_support);
 	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
 	lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
+	phba->cfg_enable_dss = 1;
 	return;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index 17fde52..3d40023 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -53,9 +53,9 @@ void lpfc_unreg_vpi(struct lpfc_hba *, uint16_t, LPFC_MBOXQ_t *);
 void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
 void lpfc_supported_pages(struct lpfcMboxq *);
-void lpfc_sli4_params(struct lpfcMboxq *);
+void lpfc_pc_sli4_params(struct lpfcMboxq *);
 int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
-
+int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
 struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
 void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
 void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
@@ -167,6 +167,8 @@ int lpfc_ns_cmd(struct lpfc_vport *, int, uint8_t, uint32_t);
 int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
 void lpfc_fdmi_tmo(unsigned long);
 void lpfc_fdmi_timeout_handler(struct lpfc_vport *);
+void lpfc_delayed_disc_tmo(unsigned long);
+void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
 
 int lpfc_config_port_prep(struct lpfc_hba *);
 int lpfc_config_port_post(struct lpfc_hba *);
@@ -341,6 +343,7 @@ extern struct fc_function_template lpfc_transport_functions;
 extern struct fc_function_template lpfc_vport_transport_functions;
 extern int lpfc_sli_mode;
 extern int lpfc_enable_npiv;
+extern int lpfc_delay_discovery;
 
 int  lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
 int  lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *,	size_t);
@@ -423,6 +426,6 @@ int lpfc_send_rrq(struct lpfc_hba *, struct lpfc_node_rrq *);
 int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
 	uint16_t, uint16_t, uint16_t);
 void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
-void lpfc_cleanup_vports_rrqs(struct lpfc_vport *);
+void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
 struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
 	uint32_t);
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index c004fa9..d9edfd9 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1738,6 +1738,55 @@ fdmi_cmd_exit:
 	return 1;
 }
 
+/**
+ * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
+ * @ptr - Context object of the timer.
+ *
+ * This function set the WORKER_DELAYED_DISC_TMO flag and wake up
+ * the worker thread.
+ **/
+void
+lpfc_delayed_disc_tmo(unsigned long ptr)
+{
+	struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t tmo_posted;
+	unsigned long iflag;
+
+	spin_lock_irqsave(&vport->work_port_lock, iflag);
+	tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO;
+	if (!tmo_posted)
+		vport->work_port_events |= WORKER_DELAYED_DISC_TMO;
+	spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+
+	if (!tmo_posted)
+		lpfc_worker_wake_up(phba);
+	return;
+}
+
+/**
+ * lpfc_delayed_disc_timeout_handler - Function called by worker thread to
+ *      handle delayed discovery.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This function start nport discovery of the vport.
+ **/
+void
+lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	spin_lock_irq(shost->host_lock);
+	if (!(vport->fc_flag & FC_DISC_DELAYED)) {
+		spin_unlock_irq(shost->host_lock);
+		return;
+	}
+	vport->fc_flag &= ~FC_DISC_DELAYED;
+	spin_unlock_irq(shost->host_lock);
+
+	lpfc_do_scr_ns_plogi(vport->phba, vport);
+}
+
 void
 lpfc_fdmi_tmo(unsigned long ptr)
 {
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index a80d938..a753581 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2007-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2007-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -57,8 +57,8 @@
  * # mount -t debugfs none /sys/kernel/debug
  *
  * The lpfc debugfs directory hierarchy is:
- * lpfc/lpfcX/vportY
- * where X is the lpfc hba unique_id
+ * /sys/kernel/debug/lpfc/fnX/vportY
+ * where X is the lpfc hba function unique_id
  * where Y is the vport VPI on that hba
  *
  * Debugging services available per vport:
@@ -82,52 +82,34 @@
  *                               the HBA. X MUST also be a power of 2.
  */
 static int lpfc_debugfs_enable = 1;
-module_param(lpfc_debugfs_enable, int, 0);
+module_param(lpfc_debugfs_enable, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
 
 /* This MUST be a power of 2 */
 static int lpfc_debugfs_max_disc_trc;
-module_param(lpfc_debugfs_max_disc_trc, int, 0);
+module_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
 	"Set debugfs discovery trace depth");
 
 /* This MUST be a power of 2 */
 static int lpfc_debugfs_max_slow_ring_trc;
-module_param(lpfc_debugfs_max_slow_ring_trc, int, 0);
+module_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
 	"Set debugfs slow ring trace depth");
 
 static int lpfc_debugfs_mask_disc_trc;
-module_param(lpfc_debugfs_mask_disc_trc, int, 0);
+module_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
 	"Set debugfs discovery trace mask");
 
 #include <linux/debugfs.h>
 
-/* size of output line, for discovery_trace and slow_ring_trace */
-#define LPFC_DEBUG_TRC_ENTRY_SIZE 100
-
-/* nodelist output buffer size */
-#define LPFC_NODELIST_SIZE 8192
-#define LPFC_NODELIST_ENTRY_SIZE 120
-
-/* dumpHBASlim output buffer size */
-#define LPFC_DUMPHBASLIM_SIZE 4096
-
-/* dumpHostSlim output buffer size */
-#define LPFC_DUMPHOSTSLIM_SIZE 4096
-
-/* hbqinfo output buffer size */
-#define LPFC_HBQINFO_SIZE 8192
-
-struct lpfc_debug {
-	char *buffer;
-	int  len;
-};
-
 static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
 static unsigned long lpfc_debugfs_start_time = 0L;
 
+/* iDiag */
+static struct lpfc_idiag idiag;
+
 /**
  * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
  * @vport: The vport to gather the log info from.
@@ -996,8 +978,6 @@ lpfc_debugfs_dumpDataDif_write(struct file *file, const char __user *buf,
 	return nbytes;
 }
 
-
-
 /**
  * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
  * @inode: The inode pointer that contains a vport pointer.
@@ -1099,6 +1079,7 @@ lpfc_debugfs_read(struct file *file, char __user *buf,
 		  size_t nbytes, loff_t *ppos)
 {
 	struct lpfc_debug *debug = file->private_data;
+
 	return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
 				       debug->len);
 }
@@ -1137,6 +1118,776 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
+/*
+ * iDiag debugfs file access methods
+ */
+
+/*
+ * iDiag PCI config space register access methods:
+ *
+ * The PCI config space register accessees of read, write, read-modify-write
+ * for set bits, and read-modify-write for clear bits to SLI4 PCI functions
+ * are provided. In the proper SLI4 PCI function's debugfs iDiag directory,
+ *
+ *      /sys/kernel/debug/lpfc/fn<#>/iDiag
+ *
+ * the access is through the debugfs entry pciCfg:
+ *
+ * 1. For PCI config space register read access, there are two read methods:
+ *    A) read a single PCI config space register in the size of a byte
+ *    (8 bits), a word (16 bits), or a dword (32 bits); or B) browse through
+ *    the 4K extended PCI config space.
+ *
+ *    A) Read a single PCI config space register consists of two steps:
+ *
+ *    Step-1: Set up PCI config space register read command, the command
+ *    syntax is,
+ *
+ *        echo 1 <where> <count> > pciCfg
+ *
+ *    where, 1 is the iDiag command for PCI config space read, <where> is the
+ *    offset from the beginning of the device's PCI config space to read from,
+ *    and <count> is the size of PCI config space register data to read back,
+ *    it will be 1 for reading a byte (8 bits), 2 for reading a word (16 bits
+ *    or 2 bytes), or 4 for reading a dword (32 bits or 4 bytes).
+ *
+ *    Setp-2: Perform the debugfs read operation to execute the idiag command
+ *    set up in Step-1,
+ *
+ *        cat pciCfg
+ *
+ *    Examples:
+ *    To read PCI device's vendor-id and device-id from PCI config space,
+ *
+ *        echo 1 0 4 > pciCfg
+ *        cat pciCfg
+ *
+ *    To read PCI device's currnt command from config space,
+ *
+ *        echo 1 4 2 > pciCfg
+ *        cat pciCfg
+ *
+ *    B) Browse through the entire 4K extended PCI config space also consists
+ *    of two steps:
+ *
+ *    Step-1: Set up PCI config space register browsing command, the command
+ *    syntax is,
+ *
+ *        echo 1 0 4096 > pciCfg
+ *
+ *    where, 1 is the iDiag command for PCI config space read, 0 must be used
+ *    as the offset for PCI config space register browse, and 4096 must be
+ *    used as the count for PCI config space register browse.
+ *
+ *    Step-2: Repeately issue the debugfs read operation to browse through
+ *    the entire PCI config space registers:
+ *
+ *        cat pciCfg
+ *        cat pciCfg
+ *        cat pciCfg
+ *        ...
+ *
+ *    When browsing to the end of the 4K PCI config space, the browse method
+ *    shall wrap around to start reading from beginning again, and again...
+ *
+ * 2. For PCI config space register write access, it supports a single PCI
+ *    config space register write in the size of a byte (8 bits), a word
+ *    (16 bits), or a dword (32 bits). The command syntax is,
+ *
+ *        echo 2 <where> <count> <value> > pciCfg
+ *
+ *    where, 2 is the iDiag command for PCI config space write, <where> is
+ *    the offset from the beginning of the device's PCI config space to write
+ *    into, <count> is the size of data to write into the PCI config space,
+ *    it will be 1 for writing a byte (8 bits), 2 for writing a word (16 bits
+ *    or 2 bytes), or 4 for writing a dword (32 bits or 4 bytes), and <value>
+ *    is the data to be written into the PCI config space register at the
+ *    offset.
+ *
+ *    Examples:
+ *    To disable PCI device's interrupt assertion,
+ *
+ *    1) Read in device's PCI config space register command field <cmd>:
+ *
+ *           echo 1 4 2 > pciCfg
+ *           cat pciCfg
+ *
+ *    2) Set bit 10 (Interrupt Disable bit) in the <cmd>:
+ *
+ *           <cmd> = <cmd> | (1 < 10)
+ *
+ *    3) Write the modified command back:
+ *
+ *           echo 2 4 2 <cmd> > pciCfg
+ *
+ * 3. For PCI config space register set bits access, it supports a single PCI
+ *    config space register set bits in the size of a byte (8 bits), a word
+ *    (16 bits), or a dword (32 bits). The command syntax is,
+ *
+ *        echo 3 <where> <count> <bitmask> > pciCfg
+ *
+ *    where, 3 is the iDiag command for PCI config space set bits, <where> is
+ *    the offset from the beginning of the device's PCI config space to set
+ *    bits into, <count> is the size of the bitmask to set into the PCI config
+ *    space, it will be 1 for setting a byte (8 bits), 2 for setting a word
+ *    (16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 bytes), and
+ *    <bitmask> is the bitmask, indicating the bits to be set into the PCI
+ *    config space register at the offset. The logic performed to the content
+ *    of the PCI config space register, regval, is,
+ *
+ *        regval |= <bitmask>
+ *
+ * 4. For PCI config space register clear bits access, it supports a single
+ *    PCI config space register clear bits in the size of a byte (8 bits),
+ *    a word (16 bits), or a dword (32 bits). The command syntax is,
+ *
+ *        echo 4 <where> <count> <bitmask> > pciCfg
+ *
+ *    where, 4 is the iDiag command for PCI config space clear bits, <where>
+ *    is the offset from the beginning of the device's PCI config space to
+ *    clear bits from, <count> is the size of the bitmask to set into the PCI
+ *    config space, it will be 1 for setting a byte (8 bits), 2 for setting
+ *    a word(16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4
+ *    bytes), and <bitmask> is the bitmask, indicating the bits to be cleared
+ *    from the PCI config space register at the offset. the logic performed
+ *    to the content of the PCI config space register, regval, is,
+ *
+ *        regval &= ~<bitmask>
+ *
+ * Note, for all single register read, write, set bits, or clear bits access,
+ * the offset (<where>) must be aligned with the size of the data:
+ *
+ * For data size of byte (8 bits), the offset must be aligned to the byte
+ * boundary; for data size of word (16 bits), the offset must be aligned
+ * to the word boundary; while for data size of dword (32 bits), the offset
+ * must be aligned to the dword boundary. Otherwise, the interface will
+ * return the error:
+ *
+ *     "-bash: echo: write error: Invalid argument".
+ *
+ * For example:
+ *
+ *     echo 1 2 4 > pciCfg
+ *     -bash: echo: write error: Invalid argument
+ *
+ * Note also, all of the numbers in the command fields for all read, write,
+ * set bits, and clear bits PCI config space register command fields can be
+ * either decimal or hex.
+ *
+ * For example,
+ *     echo 1 0 4096 > pciCfg
+ *
+ * will be the same as
+ *     echo 1 0 0x1000 > pciCfg
+ *
+ * And,
+ *     echo 2 155 1 10 > pciCfg
+ *
+ * will be
+ *     echo 2 0x9b 1 0xa > pciCfg
+ */
+
+/**
+ * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space
+ * @buf: The pointer to the user space buffer.
+ * @nbytes: The number of bytes in the user space buffer.
+ * @idiag_cmd: pointer to the idiag command struct.
+ *
+ * This routine reads data from debugfs user space buffer and parses the
+ * buffer for getting the idiag command and arguments. The while space in
+ * between the set of data is used as the parsing separator.
+ *
+ * This routine returns 0 when successful, it returns proper error code
+ * back to the user space in error conditions.
+ */
+static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
+			      struct lpfc_idiag_cmd *idiag_cmd)
+{
+	char mybuf[64];
+	char *pbuf, *step_str;
+	int bsize, i;
+
+	/* Protect copy from user */
+	if (!access_ok(VERIFY_READ, buf, nbytes))
+		return -EFAULT;
+
+	memset(mybuf, 0, sizeof(mybuf));
+	memset(idiag_cmd, 0, sizeof(*idiag_cmd));
+	bsize = min(nbytes, (sizeof(mybuf)-1));
+
+	if (copy_from_user(mybuf, buf, bsize))
+		return -EFAULT;
+	pbuf = &mybuf[0];
+	step_str = strsep(&pbuf, "\t ");
+
+	/* The opcode must present */
+	if (!step_str)
+		return -EINVAL;
+
+	idiag_cmd->opcode = simple_strtol(step_str, NULL, 0);
+	if (idiag_cmd->opcode == 0)
+		return -EINVAL;
+
+	for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) {
+		step_str = strsep(&pbuf, "\t ");
+		if (!step_str)
+			return 0;
+		idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0);
+	}
+	return 0;
+}
+
+/**
+ * lpfc_idiag_open - idiag open debugfs
+ * @inode: The inode pointer that contains a pointer to phba.
+ * @file: The file pointer to attach the file operation.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It
+ * gets the reference to phba from the i_private field in @inode, it then
+ * allocates buffer for the file operation, performs the necessary PCI config
+ * space read into the allocated buffer according to the idiag user command
+ * setup, and then returns a pointer to buffer in the private_data field in
+ * @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an
+ * negative error value.
+ **/
+static int
+lpfc_idiag_open(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug;
+
+	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+	if (!debug)
+		return -ENOMEM;
+
+	debug->i_private = inode->i_private;
+	debug->buffer = NULL;
+	file->private_data = debug;
+
+	return 0;
+}
+
+/**
+ * lpfc_idiag_release - Release idiag access file operation
+ * @inode: The inode pointer that contains a vport pointer. (unused)
+ * @file: The file pointer that contains the buffer to release.
+ *
+ * Description:
+ * This routine is the generic release routine for the idiag access file
+ * operation, it frees the buffer that was allocated when the debugfs file
+ * was opened.
+ *
+ * Returns:
+ * This function returns zero.
+ **/
+static int
+lpfc_idiag_release(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug = file->private_data;
+
+	/* Free the buffers to the file operation */
+	kfree(debug->buffer);
+	kfree(debug);
+
+	return 0;
+}
+
+/**
+ * lpfc_idiag_cmd_release - Release idiag cmd access file operation
+ * @inode: The inode pointer that contains a vport pointer. (unused)
+ * @file: The file pointer that contains the buffer to release.
+ *
+ * Description:
+ * This routine frees the buffer that was allocated when the debugfs file
+ * was opened. It also reset the fields in the idiag command struct in the
+ * case the command is not continuous browsing of the data structure.
+ *
+ * Returns:
+ * This function returns zero.
+ **/
+static int
+lpfc_idiag_cmd_release(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug = file->private_data;
+
+	/* Read PCI config register, if not read all, clear command fields */
+	if ((debug->op == LPFC_IDIAG_OP_RD) &&
+	    (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD))
+		if ((idiag.cmd.data[1] == sizeof(uint8_t)) ||
+		    (idiag.cmd.data[1] == sizeof(uint16_t)) ||
+		    (idiag.cmd.data[1] == sizeof(uint32_t)))
+			memset(&idiag, 0, sizeof(idiag));
+
+	/* Write PCI config register, clear command fields */
+	if ((debug->op == LPFC_IDIAG_OP_WR) &&
+	    (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR))
+		memset(&idiag, 0, sizeof(idiag));
+
+	/* Free the buffers to the file operation */
+	kfree(debug->buffer);
+	kfree(debug);
+
+	return 0;
+}
+
+/**
+ * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba pci config space according to the
+ * idiag command, and copies to user @buf. Depending on the PCI config space
+ * read command setup, it does either a single register read of a byte
+ * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all
+ * registers from the 4K extended PCI config space.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
+		       loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+	int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE;
+	int where, count;
+	char *pbuffer;
+	struct pci_dev *pdev;
+	uint32_t u32val;
+	uint16_t u16val;
+	uint8_t u8val;
+
+	pdev = phba->pcidev;
+	if (!pdev)
+		return 0;
+
+	/* This is a user read operation */
+	debug->op = LPFC_IDIAG_OP_RD;
+
+	if (!debug->buffer)
+		debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL);
+	if (!debug->buffer)
+		return 0;
+	pbuffer = debug->buffer;
+
+	if (*ppos)
+		return 0;
+
+	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
+		where = idiag.cmd.data[0];
+		count = idiag.cmd.data[1];
+	} else
+		return 0;
+
+	/* Read single PCI config space register */
+	switch (count) {
+	case SIZE_U8: /* byte (8 bits) */
+		pci_read_config_byte(pdev, where, &u8val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%03x: %02x\n", where, u8val);
+		break;
+	case SIZE_U16: /* word (16 bits) */
+		pci_read_config_word(pdev, where, &u16val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%03x: %04x\n", where, u16val);
+		break;
+	case SIZE_U32: /* double word (32 bits) */
+		pci_read_config_dword(pdev, where, &u32val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%03x: %08x\n", where, u32val);
+		break;
+	case LPFC_PCI_CFG_SIZE: /* browse all */
+		goto pcicfg_browse;
+		break;
+	default:
+		/* illegal count */
+		len = 0;
+		break;
+	}
+	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+
+pcicfg_browse:
+
+	/* Browse all PCI config space registers */
+	offset_label = idiag.offset.last_rd;
+	offset = offset_label;
+
+	/* Read PCI config space */
+	len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+			"%03x: ", offset_label);
+	while (index > 0) {
+		pci_read_config_dword(pdev, offset, &u32val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%08x ", u32val);
+		offset += sizeof(uint32_t);
+		index -= sizeof(uint32_t);
+		if (!index)
+			len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+					"\n");
+		else if (!(index % (8 * sizeof(uint32_t)))) {
+			offset_label += (8 * sizeof(uint32_t));
+			len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+					"\n%03x: ", offset_label);
+		}
+	}
+
+	/* Set up the offset for next portion of pci cfg read */
+	idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
+	if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+		idiag.offset.last_rd = 0;
+
+	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and
+ * then perform the syntax check for PCI config space read or write command
+ * accordingly. In the case of PCI config space read command, it sets up
+ * the command in the idiag command struct for the debugfs read operation.
+ * In the case of PCI config space write operation, it executes the write
+ * operation into the PCI config space accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ */
+static ssize_t
+lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
+			size_t nbytes, loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+	uint32_t where, value, count;
+	uint32_t u32val;
+	uint16_t u16val;
+	uint8_t u8val;
+	struct pci_dev *pdev;
+	int rc;
+
+	pdev = phba->pcidev;
+	if (!pdev)
+		return -EFAULT;
+
+	/* This is a user write operation */
+	debug->op = LPFC_IDIAG_OP_WR;
+
+	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+	if (rc)
+		return rc;
+
+	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
+		/* Read command from PCI config space, set up command fields */
+		where = idiag.cmd.data[0];
+		count = idiag.cmd.data[1];
+		if (count == LPFC_PCI_CFG_SIZE) {
+			if (where != 0)
+				goto error_out;
+		} else if ((count != sizeof(uint8_t)) &&
+			   (count != sizeof(uint16_t)) &&
+			   (count != sizeof(uint32_t)))
+			goto error_out;
+		if (count == sizeof(uint8_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
+				goto error_out;
+			if (where % sizeof(uint8_t))
+				goto error_out;
+		}
+		if (count == sizeof(uint16_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
+				goto error_out;
+			if (where % sizeof(uint16_t))
+				goto error_out;
+		}
+		if (count == sizeof(uint32_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
+				goto error_out;
+			if (where % sizeof(uint32_t))
+				goto error_out;
+		}
+	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR ||
+		   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST ||
+		   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+		/* Write command to PCI config space, read-modify-write */
+		where = idiag.cmd.data[0];
+		count = idiag.cmd.data[1];
+		value = idiag.cmd.data[2];
+		/* Sanity checks */
+		if ((count != sizeof(uint8_t)) &&
+		    (count != sizeof(uint16_t)) &&
+		    (count != sizeof(uint32_t)))
+			goto error_out;
+		if (count == sizeof(uint8_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
+				goto error_out;
+			if (where % sizeof(uint8_t))
+				goto error_out;
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
+				pci_write_config_byte(pdev, where,
+						      (uint8_t)value);
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
+				rc = pci_read_config_byte(pdev, where, &u8val);
+				if (!rc) {
+					u8val |= (uint8_t)value;
+					pci_write_config_byte(pdev, where,
+							      u8val);
+				}
+			}
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+				rc = pci_read_config_byte(pdev, where, &u8val);
+				if (!rc) {
+					u8val &= (uint8_t)(~value);
+					pci_write_config_byte(pdev, where,
+							      u8val);
+				}
+			}
+		}
+		if (count == sizeof(uint16_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
+				goto error_out;
+			if (where % sizeof(uint16_t))
+				goto error_out;
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
+				pci_write_config_word(pdev, where,
+						      (uint16_t)value);
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
+				rc = pci_read_config_word(pdev, where, &u16val);
+				if (!rc) {
+					u16val |= (uint16_t)value;
+					pci_write_config_word(pdev, where,
+							      u16val);
+				}
+			}
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+				rc = pci_read_config_word(pdev, where, &u16val);
+				if (!rc) {
+					u16val &= (uint16_t)(~value);
+					pci_write_config_word(pdev, where,
+							      u16val);
+				}
+			}
+		}
+		if (count == sizeof(uint32_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
+				goto error_out;
+			if (where % sizeof(uint32_t))
+				goto error_out;
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
+				pci_write_config_dword(pdev, where, value);
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
+				rc = pci_read_config_dword(pdev, where,
+							   &u32val);
+				if (!rc) {
+					u32val |= value;
+					pci_write_config_dword(pdev, where,
+							       u32val);
+				}
+			}
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+				rc = pci_read_config_dword(pdev, where,
+							   &u32val);
+				if (!rc) {
+					u32val &= ~value;
+					pci_write_config_dword(pdev, where,
+							       u32val);
+				}
+			}
+		}
+	} else
+		/* All other opecodes are illegal for now */
+		goto error_out;
+
+	return nbytes;
+error_out:
+	memset(&idiag, 0, sizeof(idiag));
+	return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_queinfo_read - idiag debugfs read queue information
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba SLI4 PCI function queue information,
+ * and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
+			loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+	int len = 0, fcp_qidx;
+	char *pbuffer;
+
+	if (!debug->buffer)
+		debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL);
+	if (!debug->buffer)
+		return 0;
+	pbuffer = debug->buffer;
+
+	if (*ppos)
+		return 0;
+
+	/* Get slow-path event queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path EQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], EQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.sp_eq->queue_id,
+			phba->sli4_hba.sp_eq->entry_count,
+			phba->sli4_hba.sp_eq->host_index,
+			phba->sli4_hba.sp_eq->hba_index);
+
+	/* Get fast-path event queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Fast-path EQ information:\n");
+	for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) {
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\tID [%02d], EQE-COUNT [%04d], "
+				"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+				phba->sli4_hba.fp_eq[fcp_qidx]->queue_id,
+				phba->sli4_hba.fp_eq[fcp_qidx]->entry_count,
+				phba->sli4_hba.fp_eq[fcp_qidx]->host_index,
+				phba->sli4_hba.fp_eq[fcp_qidx]->hba_index);
+	}
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+
+	/* Get mailbox complete queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Mailbox CQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated EQ-ID [%02d]:\n",
+			phba->sli4_hba.mbx_cq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], CQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.mbx_cq->queue_id,
+			phba->sli4_hba.mbx_cq->entry_count,
+			phba->sli4_hba.mbx_cq->host_index,
+			phba->sli4_hba.mbx_cq->hba_index);
+
+	/* Get slow-path complete queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path CQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated EQ-ID [%02d]:\n",
+			phba->sli4_hba.els_cq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], CQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.els_cq->queue_id,
+			phba->sli4_hba.els_cq->entry_count,
+			phba->sli4_hba.els_cq->host_index,
+			phba->sli4_hba.els_cq->hba_index);
+
+	/* Get fast-path complete queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Fast-path CQ information:\n");
+	for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) {
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\t\tAssociated EQ-ID [%02d]:\n",
+				phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid);
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+		"\tID [%02d], EQE-COUNT [%04d], "
+		"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+		phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id,
+		phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count,
+		phba->sli4_hba.fcp_cq[fcp_qidx]->host_index,
+		phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index);
+	}
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+
+	/* Get mailbox queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Mailbox MQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated CQ-ID [%02d]:\n",
+			phba->sli4_hba.mbx_wq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], MQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.mbx_wq->queue_id,
+			phba->sli4_hba.mbx_wq->entry_count,
+			phba->sli4_hba.mbx_wq->host_index,
+			phba->sli4_hba.mbx_wq->hba_index);
+
+	/* Get slow-path work queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path WQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated CQ-ID [%02d]:\n",
+			phba->sli4_hba.els_wq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], WQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.els_wq->queue_id,
+			phba->sli4_hba.els_wq->entry_count,
+			phba->sli4_hba.els_wq->host_index,
+			phba->sli4_hba.els_wq->hba_index);
+
+	/* Get fast-path work queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Fast-path WQ information:\n");
+	for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) {
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\t\tAssociated CQ-ID [%02d]:\n",
+				phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid);
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\tID [%02d], WQE-COUNT [%04d], "
+				"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+				phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id,
+				phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count,
+				phba->sli4_hba.fcp_wq[fcp_qidx]->host_index,
+				phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index);
+	}
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+
+	/* Get receive queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path RQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated CQ-ID [%02d]:\n",
+			phba->sli4_hba.hdr_rq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], RHQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+			phba->sli4_hba.hdr_rq->queue_id,
+			phba->sli4_hba.hdr_rq->entry_count,
+			phba->sli4_hba.hdr_rq->host_index,
+			phba->sli4_hba.hdr_rq->hba_index);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], RDQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+			phba->sli4_hba.dat_rq->queue_id,
+			phba->sli4_hba.dat_rq->entry_count,
+			phba->sli4_hba.dat_rq->host_index,
+			phba->sli4_hba.dat_rq->hba_index);
+
+	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
 #undef lpfc_debugfs_op_disc_trc
 static const struct file_operations lpfc_debugfs_op_disc_trc = {
 	.owner =        THIS_MODULE,
@@ -1213,6 +1964,28 @@ static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
 
 static struct dentry *lpfc_debugfs_root = NULL;
 static atomic_t lpfc_debugfs_hba_count;
+
+/*
+ * File operations for the iDiag debugfs
+ */
+#undef lpfc_idiag_op_pciCfg
+static const struct file_operations lpfc_idiag_op_pciCfg = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_idiag_open,
+	.llseek =       lpfc_debugfs_lseek,
+	.read =         lpfc_idiag_pcicfg_read,
+	.write =        lpfc_idiag_pcicfg_write,
+	.release =      lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_queInfo
+static const struct file_operations lpfc_idiag_op_queInfo = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_idiag_open,
+	.read =         lpfc_idiag_queinfo_read,
+	.release =      lpfc_idiag_release,
+};
+
 #endif
 
 /**
@@ -1249,8 +2022,8 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
 	if (!lpfc_debugfs_start_time)
 		lpfc_debugfs_start_time = jiffies;
 
-	/* Setup lpfcX directory for specific HBA */
-	snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
+	/* Setup funcX directory for specific HBA PCI function */
+	snprintf(name, sizeof(name), "fn%d", phba->brd_no);
 	if (!phba->hba_debugfs_root) {
 		phba->hba_debugfs_root =
 			debugfs_create_dir(name, lpfc_debugfs_root);
@@ -1275,28 +2048,38 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
 		}
 
 		/* Setup dumpHBASlim */
-		snprintf(name, sizeof(name), "dumpHBASlim");
-		phba->debug_dumpHBASlim =
-			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
-				 phba->hba_debugfs_root,
-				 phba, &lpfc_debugfs_op_dumpHBASlim);
-		if (!phba->debug_dumpHBASlim) {
-			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-				"0413 Cannot create debugfs dumpHBASlim\n");
-			goto debug_failed;
-		}
+		if (phba->sli_rev < LPFC_SLI_REV4) {
+			snprintf(name, sizeof(name), "dumpHBASlim");
+			phba->debug_dumpHBASlim =
+				debugfs_create_file(name,
+					S_IFREG|S_IRUGO|S_IWUSR,
+					phba->hba_debugfs_root,
+					phba, &lpfc_debugfs_op_dumpHBASlim);
+			if (!phba->debug_dumpHBASlim) {
+				lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+						 "0413 Cannot create debugfs "
+						"dumpHBASlim\n");
+				goto debug_failed;
+			}
+		} else
+			phba->debug_dumpHBASlim = NULL;
 
 		/* Setup dumpHostSlim */
-		snprintf(name, sizeof(name), "dumpHostSlim");
-		phba->debug_dumpHostSlim =
-			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
-				 phba->hba_debugfs_root,
-				 phba, &lpfc_debugfs_op_dumpHostSlim);
-		if (!phba->debug_dumpHostSlim) {
-			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-				"0414 Cannot create debugfs dumpHostSlim\n");
-			goto debug_failed;
-		}
+		if (phba->sli_rev < LPFC_SLI_REV4) {
+			snprintf(name, sizeof(name), "dumpHostSlim");
+			phba->debug_dumpHostSlim =
+				debugfs_create_file(name,
+					S_IFREG|S_IRUGO|S_IWUSR,
+					phba->hba_debugfs_root,
+					phba, &lpfc_debugfs_op_dumpHostSlim);
+			if (!phba->debug_dumpHostSlim) {
+				lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+						 "0414 Cannot create debugfs "
+						 "dumpHostSlim\n");
+				goto debug_failed;
+			}
+		} else
+			phba->debug_dumpHBASlim = NULL;
 
 		/* Setup dumpData */
 		snprintf(name, sizeof(name), "dumpData");
@@ -1322,8 +2105,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
 			goto debug_failed;
 		}
 
-
-
 		/* Setup slow ring trace */
 		if (lpfc_debugfs_max_slow_ring_trc) {
 			num = lpfc_debugfs_max_slow_ring_trc - 1;
@@ -1342,7 +2123,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
 			}
 		}
 
-
 		snprintf(name, sizeof(name), "slow_ring_trace");
 		phba->debug_slow_ring_trc =
 			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
@@ -1434,6 +2214,53 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
 				 "0409 Cant create debugfs nodelist\n");
 		goto debug_failed;
 	}
+
+	/*
+	 * iDiag debugfs root entry points for SLI4 device only
+	 */
+	if (phba->sli_rev < LPFC_SLI_REV4)
+		goto debug_failed;
+
+	snprintf(name, sizeof(name), "iDiag");
+	if (!phba->idiag_root) {
+		phba->idiag_root =
+			debugfs_create_dir(name, phba->hba_debugfs_root);
+		if (!phba->idiag_root) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "2922 Can't create idiag debugfs\n");
+			goto debug_failed;
+		}
+		/* Initialize iDiag data structure */
+		memset(&idiag, 0, sizeof(idiag));
+	}
+
+	/* iDiag read PCI config space */
+	snprintf(name, sizeof(name), "pciCfg");
+	if (!phba->idiag_pci_cfg) {
+		phba->idiag_pci_cfg =
+			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+				phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
+		if (!phba->idiag_pci_cfg) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "2923 Can't create idiag debugfs\n");
+			goto debug_failed;
+		}
+		idiag.offset.last_rd = 0;
+	}
+
+	/* iDiag get PCI function queue information */
+	snprintf(name, sizeof(name), "queInfo");
+	if (!phba->idiag_que_info) {
+		phba->idiag_que_info =
+			debugfs_create_file(name, S_IFREG|S_IRUGO,
+			phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
+		if (!phba->idiag_que_info) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "2924 Can't create idiag debugfs\n");
+			goto debug_failed;
+		}
+	}
+
 debug_failed:
 	return;
 #endif
@@ -1508,8 +2335,31 @@ lpfc_debugfs_terminate(struct lpfc_vport *vport)
 			phba->debug_slow_ring_trc = NULL;
 		}
 
+		/*
+		 * iDiag release
+		 */
+		if (phba->sli_rev == LPFC_SLI_REV4) {
+			if (phba->idiag_que_info) {
+				/* iDiag queInfo */
+				debugfs_remove(phba->idiag_que_info);
+				phba->idiag_que_info = NULL;
+			}
+			if (phba->idiag_pci_cfg) {
+				/* iDiag pciCfg */
+				debugfs_remove(phba->idiag_pci_cfg);
+				phba->idiag_pci_cfg = NULL;
+			}
+
+			/* Finally remove the iDiag debugfs root */
+			if (phba->idiag_root) {
+				/* iDiag root */
+				debugfs_remove(phba->idiag_root);
+				phba->idiag_root = NULL;
+			}
+		}
+
 		if (phba->hba_debugfs_root) {
-			debugfs_remove(phba->hba_debugfs_root); /* lpfcX */
+			debugfs_remove(phba->hba_debugfs_root); /* fnX */
 			phba->hba_debugfs_root = NULL;
 			atomic_dec(&lpfc_debugfs_hba_count);
 		}
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 03c7313..91b9a94 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2007 Emulex.  All rights reserved.                *
+ * Copyright (C) 2007-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -22,6 +22,44 @@
 #define _H_LPFC_DEBUG_FS
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+
+/* size of output line, for discovery_trace and slow_ring_trace */
+#define LPFC_DEBUG_TRC_ENTRY_SIZE 100
+
+/* nodelist output buffer size */
+#define LPFC_NODELIST_SIZE 8192
+#define LPFC_NODELIST_ENTRY_SIZE 120
+
+/* dumpHBASlim output buffer size */
+#define LPFC_DUMPHBASLIM_SIZE 4096
+
+/* dumpHostSlim output buffer size */
+#define LPFC_DUMPHOSTSLIM_SIZE 4096
+
+/* hbqinfo output buffer size */
+#define LPFC_HBQINFO_SIZE 8192
+
+/* rdPciConf output buffer size */
+#define LPFC_PCI_CFG_SIZE 4096
+#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
+#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
+
+/* queue info output buffer size */
+#define LPFC_QUE_INFO_GET_BUF_SIZE 2048
+
+#define SIZE_U8  sizeof(uint8_t)
+#define SIZE_U16 sizeof(uint16_t)
+#define SIZE_U32 sizeof(uint32_t)
+
+struct lpfc_debug {
+	char *i_private;
+	char op;
+#define LPFC_IDIAG_OP_RD 1
+#define LPFC_IDIAG_OP_WR 2
+	char *buffer;
+	int  len;
+};
+
 struct lpfc_debugfs_trc {
 	char *fmt;
 	uint32_t data1;
@@ -30,6 +68,26 @@ struct lpfc_debugfs_trc {
 	uint32_t seq_cnt;
 	unsigned long jif;
 };
+
+struct lpfc_idiag_offset {
+	uint32_t last_rd;
+};
+
+#define LPFC_IDIAG_CMD_DATA_SIZE 4
+struct lpfc_idiag_cmd {
+	uint32_t opcode;
+#define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001
+#define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002
+#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
+#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
+	uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
+};
+
+struct lpfc_idiag {
+	uint32_t active;
+	struct lpfc_idiag_cmd cmd;
+	struct lpfc_idiag_offset offset;
+};
 #endif
 
 /* Mask for discovery_trace */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index c62d567..8e28edf 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -485,6 +485,59 @@ fail:
 }
 
 /**
+ * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @sp: pointer to service parameter data structure.
+ *
+ * This routine is called from FLOGI/FDISC completion handler functions.
+ * lpfc_check_clean_addr_bit return 1 when FCID/Fabric portname/ Fabric
+ * node nodename is changed in the completion service parameter else return
+ * 0. This function also set flag in the vport data structure to delay
+ * NP_Port discovery after the FLOGI/FDISC completion if Clean address bit
+ * in FLOGI/FDISC response is cleared and FCID/Fabric portname/ Fabric
+ * node nodename is changed in the completion service parameter.
+ *
+ * Return code
+ *   0 - FCID and Fabric Nodename and Fabric portname is not changed.
+ *   1 - FCID or Fabric Nodename or Fabric portname is changed.
+ *
+ **/
+static uint8_t
+lpfc_check_clean_addr_bit(struct lpfc_vport *vport,
+		struct serv_parm *sp)
+{
+	uint8_t fabric_param_changed = 0;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	if ((vport->fc_prevDID != vport->fc_myDID) ||
+		memcmp(&vport->fabric_portname, &sp->portName,
+			sizeof(struct lpfc_name)) ||
+		memcmp(&vport->fabric_nodename, &sp->nodeName,
+			sizeof(struct lpfc_name)))
+		fabric_param_changed = 1;
+
+	/*
+	 * Word 1 Bit 31 in common service parameter is overloaded.
+	 * Word 1 Bit 31 in FLOGI request is multiple NPort request
+	 * Word 1 Bit 31 in FLOGI response is clean address bit
+	 *
+	 * If fabric parameter is changed and clean address bit is
+	 * cleared delay nport discovery if
+	 * - vport->fc_prevDID != 0 (not initial discovery) OR
+	 * - lpfc_delay_discovery module parameter is set.
+	 */
+	if (fabric_param_changed && !sp->cmn.clean_address_bit &&
+	    (vport->fc_prevDID || lpfc_delay_discovery)) {
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag |= FC_DISC_DELAYED;
+		spin_unlock_irq(shost->host_lock);
+	}
+
+	return fabric_param_changed;
+}
+
+
+/**
  * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port
  * @vport: pointer to a host virtual N_Port data structure.
  * @ndlp: pointer to a node-list data structure.
@@ -512,6 +565,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_nodelist *np;
 	struct lpfc_nodelist *next_np;
+	uint8_t fabric_param_changed;
 
 	spin_lock_irq(shost->host_lock);
 	vport->fc_flag |= FC_FABRIC;
@@ -544,6 +598,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		ndlp->nlp_class_sup |= FC_COS_CLASS4;
 	ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
 				sp->cmn.bbRcvSizeLsb;
+
+	fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
+	memcpy(&vport->fabric_portname, &sp->portName,
+			sizeof(struct lpfc_name));
+	memcpy(&vport->fabric_nodename, &sp->nodeName,
+			sizeof(struct lpfc_name));
 	memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
 
 	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
@@ -565,7 +625,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 		}
 	}
 
-	if ((vport->fc_prevDID != vport->fc_myDID) &&
+	if (fabric_param_changed &&
 		!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
 
 		/* If our NportID changed, we need to ensure all
@@ -2203,6 +2263,7 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_sli *psli;
+	struct lpfcMboxq *mbox;
 
 	psli = &phba->sli;
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
@@ -2260,6 +2321,21 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 					NLP_EVT_CMPL_LOGO);
 out:
 	lpfc_els_free_iocb(phba, cmdiocb);
+	/* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */
+	if ((vport->fc_flag & FC_PT2PT) &&
+		!(vport->fc_flag & FC_PT2PT_PLOGI)) {
+		phba->pport->fc_myDID = 0;
+		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+		if (mbox) {
+			lpfc_config_link(phba, mbox);
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mbox->vport = vport;
+			if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) ==
+				MBX_NOT_FINISHED) {
+				mempool_free(mbox, phba->mbox_mem_pool);
+			}
+		}
+	}
 	return;
 }
 
@@ -2745,7 +2821,8 @@ lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
 		}
 		break;
 	case ELS_CMD_FDISC:
-		lpfc_issue_els_fdisc(vport, ndlp, retry);
+		if (!(vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI))
+			lpfc_issue_els_fdisc(vport, ndlp, retry);
 		break;
 	}
 	return;
@@ -2815,9 +2892,17 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
 	switch (irsp->ulpStatus) {
 	case IOSTAT_FCP_RSP_ERROR:
+		break;
 	case IOSTAT_REMOTE_STOP:
+		if (phba->sli_rev == LPFC_SLI_REV4) {
+			/* This IO was aborted by the target, we don't
+			 * know the rxid and because we did not send the
+			 * ABTS we cannot generate and RRQ.
+			 */
+			lpfc_set_rrq_active(phba, ndlp,
+					 cmdiocb->sli4_xritag, 0, 0);
+		}
 		break;
-
 	case IOSTAT_LOCAL_REJECT:
 		switch ((irsp->un.ulpWord[4] & 0xff)) {
 		case IOERR_LOOP_OPEN_FAILURE:
@@ -4013,28 +4098,34 @@ lpfc_els_clear_rrq(struct lpfc_vport *vport,
 	uint8_t *pcmd;
 	struct RRQ *rrq;
 	uint16_t rxid;
+	uint16_t xri;
 	struct lpfc_node_rrq *prrq;
 
 
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt);
 	pcmd += sizeof(uint32_t);
 	rrq = (struct RRQ *)pcmd;
-	rxid = bf_get(rrq_oxid, rrq);
+	rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg);
+	rxid = be16_to_cpu(bf_get(rrq_rxid, rrq));
 
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 			"2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
 			" x%x x%x\n",
-			bf_get(rrq_did, rrq),
-			bf_get(rrq_oxid, rrq),
+			be32_to_cpu(bf_get(rrq_did, rrq)),
+			be16_to_cpu(bf_get(rrq_oxid, rrq)),
 			rxid,
 			iocb->iotag, iocb->iocb.ulpContext);
 
 	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
 		"Clear RRQ:  did:x%x flg:x%x exchg:x%.08x",
 		ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
-	prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID);
+	if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq)))
+		xri = be16_to_cpu(bf_get(rrq_oxid, rrq));
+	else
+		xri = rxid;
+	prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID);
 	if (prrq)
-		lpfc_clr_rrq_active(phba, rxid, prrq);
+		lpfc_clr_rrq_active(phba, xri, prrq);
 	return;
 }
 
@@ -6166,6 +6257,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 	if (vport->load_flag & FC_UNLOADING)
 		goto dropit;
 
+	/* If NPort discovery is delayed drop incoming ELS */
+	if ((vport->fc_flag & FC_DISC_DELAYED) &&
+			(cmd != ELS_CMD_PLOGI))
+		goto dropit;
+
 	ndlp = lpfc_findnode_did(vport, did);
 	if (!ndlp) {
 		/* Cannot find existing Fabric ndlp, so allocate a new one */
@@ -6218,6 +6314,12 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 		ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
 
 		lpfc_send_els_event(vport, ndlp, payload);
+
+		/* If Nport discovery is delayed, reject PLOGIs */
+		if (vport->fc_flag & FC_DISC_DELAYED) {
+			rjt_err = LSRJT_UNABLE_TPC;
+			break;
+		}
 		if (vport->port_state < LPFC_DISC_AUTH) {
 			if (!(phba->pport->fc_flag & FC_PT2PT) ||
 				(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -6596,6 +6698,21 @@ void
 lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp, *ndlp_fdmi;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	/*
+	 * If lpfc_delay_discovery parameter is set and the clean address
+	 * bit is cleared and fc fabric parameters chenged, delay FC NPort
+	 * discovery.
+	 */
+	spin_lock_irq(shost->host_lock);
+	if (vport->fc_flag & FC_DISC_DELAYED) {
+		spin_unlock_irq(shost->host_lock);
+		mod_timer(&vport->delayed_disc_tmo,
+			jiffies + HZ * phba->fc_ratov);
+		return;
+	}
+	spin_unlock_irq(shost->host_lock);
 
 	ndlp = lpfc_findnode_did(vport, NameServer_DID);
 	if (!ndlp) {
@@ -6938,6 +7055,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 	struct lpfc_nodelist *next_np;
 	IOCB_t *irsp = &rspiocb->iocb;
 	struct lpfc_iocbq *piocb;
+	struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
+	struct serv_parm *sp;
+	uint8_t fabric_param_changed;
 
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 			 "0123 FDISC completes. x%x/x%x prevDID: x%x\n",
@@ -6981,7 +7101,14 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
 	vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
 	lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
-	if ((vport->fc_prevDID != vport->fc_myDID) &&
+	prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+	sp = prsp->virt + sizeof(uint32_t);
+	fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
+	memcpy(&vport->fabric_portname, &sp->portName,
+		sizeof(struct lpfc_name));
+	memcpy(&vport->fabric_nodename, &sp->nodeName,
+		sizeof(struct lpfc_name));
+	if (fabric_param_changed &&
 		!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
 		/* If our NportID changed, we need to ensure all
 		 * remaining NPORTs get unreg_login'ed so we can
@@ -7582,6 +7709,32 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
 }
 
 /**
+ * lpfc_sli4_vport_delete_els_xri_aborted -Remove all ndlp references for vport
+ * @vport: pointer to lpfc vport data structure.
+ *
+ * This routine is invoked by the vport cleanup for deletions and the cleanup
+ * for an ndlp on removal.
+ **/
+void
+lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
+	unsigned long iflag = 0;
+
+	spin_lock_irqsave(&phba->hbalock, iflag);
+	spin_lock(&phba->sli4_hba.abts_sgl_list_lock);
+	list_for_each_entry_safe(sglq_entry, sglq_next,
+			&phba->sli4_hba.lpfc_abts_els_sgl_list, list) {
+		if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport)
+			sglq_entry->ndlp = NULL;
+	}
+	spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
+	return;
+}
+
+/**
  * lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort
  * @phba: pointer to lpfc hba data structure.
  * @axri: pointer to the els xri abort wcqe structure.
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index bb01596..154c715 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -658,6 +658,8 @@ lpfc_work_done(struct lpfc_hba *phba)
 				lpfc_ramp_down_queue_handler(phba);
 			if (work_port_events & WORKER_RAMP_UP_QUEUE)
 				lpfc_ramp_up_queue_handler(phba);
+			if (work_port_events & WORKER_DELAYED_DISC_TMO)
+				lpfc_delayed_disc_timeout_handler(vport);
 		}
 	lpfc_destroy_vport_work_array(phba, vports);
 
@@ -838,6 +840,11 @@ lpfc_linkdown_port(struct lpfc_vport *vport)
 
 	lpfc_port_link_failure(vport);
 
+	/* Stop delayed Nport discovery */
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag &= ~FC_DISC_DELAYED;
+	spin_unlock_irq(shost->host_lock);
+	del_timer_sync(&vport->delayed_disc_tmo);
 }
 
 int
@@ -3160,7 +3167,7 @@ lpfc_mbx_cmpl_unreg_vpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 	spin_unlock_irq(shost->host_lock);
 	vport->unreg_vpi_cmpl = VPORT_OK;
 	mempool_free(pmb, phba->mbox_mem_pool);
-	lpfc_cleanup_vports_rrqs(vport);
+	lpfc_cleanup_vports_rrqs(vport, NULL);
 	/*
 	 * This shost reference might have been taken at the beginning of
 	 * lpfc_vport_delete()
@@ -3900,6 +3907,8 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 	if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
 		return;
 	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+	if (vport->phba->sli_rev == LPFC_SLI_REV4)
+		lpfc_cleanup_vports_rrqs(vport, ndlp);
 	lpfc_nlp_put(ndlp);
 	return;
 }
@@ -4289,7 +4298,7 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 
 	list_del_init(&ndlp->els_retry_evt.evt_listp);
 	list_del_init(&ndlp->dev_loss_evt.evt_listp);
-
+	lpfc_cleanup_vports_rrqs(vport, ndlp);
 	lpfc_unreg_rpi(vport, ndlp);
 
 	return 0;
@@ -4426,10 +4435,11 @@ lpfc_findnode_did(struct lpfc_vport *vport, uint32_t did)
 {
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp;
+	unsigned long iflags;
 
-	spin_lock_irq(shost->host_lock);
+	spin_lock_irqsave(shost->host_lock, iflags);
 	ndlp = __lpfc_findnode_did(vport, did);
-	spin_unlock_irq(shost->host_lock);
+	spin_unlock_irqrestore(shost->host_lock, iflags);
 	return ndlp;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index 96ed3ba..94ae37c 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -341,6 +341,12 @@ struct csp {
 	uint8_t bbCreditMsb;
 	uint8_t bbCreditlsb;	/* FC Word 0, byte 3 */
 
+/*
+ * Word 1 Bit 31 in common service parameter is overloaded.
+ * Word 1 Bit 31 in FLOGI request is multiple NPort request
+ * Word 1 Bit 31 in FLOGI response is clean address bit
+ */
+#define clean_address_bit request_multiple_Nport /* Word 1, bit 31 */
 #ifdef __BIG_ENDIAN_BITFIELD
 	uint16_t request_multiple_Nport:1;	/* FC Word 1, bit 31 */
 	uint16_t randomOffset:1;	/* FC Word 1, bit 30 */
@@ -3198,7 +3204,10 @@ typedef struct {
 #define IOERR_SLER_RRQ_RJT_ERR        0x4C
 #define IOERR_SLER_RRQ_RETRY_ERR      0x4D
 #define IOERR_SLER_ABTS_ERR           0x4E
-
+#define IOERR_ELXSEC_KEY_UNWRAP_ERROR		0xF0
+#define IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR	0xF1
+#define IOERR_ELXSEC_CRYPTO_ERROR		0xF2
+#define IOERR_ELXSEC_CRYPTO_COMPARE_ERROR	0xF3
 #define IOERR_DRVR_MASK               0x100
 #define IOERR_SLI_DOWN                0x101  /* ulpStatus  - Driver defined */
 #define IOERR_SLI_BRESET              0x102
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 94c1aa1..c7178d6 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -778,6 +778,7 @@ struct mbox_header {
 #define LPFC_MBOX_OPCODE_QUERY_FW_CFG		0x3A
 #define LPFC_MBOX_OPCODE_FUNCTION_RESET		0x3D
 #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT		0x5A
+#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS	0xB5
 
 /* FCoE Opcodes */
 #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE			0x01
@@ -1852,6 +1853,9 @@ struct lpfc_mbx_request_features {
 #define lpfc_mbx_rq_ftr_rq_ifip_SHIFT		7
 #define lpfc_mbx_rq_ftr_rq_ifip_MASK		0x00000001
 #define lpfc_mbx_rq_ftr_rq_ifip_WORD		word2
+#define lpfc_mbx_rq_ftr_rq_perfh_SHIFT		11
+#define lpfc_mbx_rq_ftr_rq_perfh_MASK		0x00000001
+#define lpfc_mbx_rq_ftr_rq_perfh_WORD		word2
 	uint32_t word3;
 #define lpfc_mbx_rq_ftr_rsp_iaab_SHIFT		0
 #define lpfc_mbx_rq_ftr_rsp_iaab_MASK		0x00000001
@@ -1877,6 +1881,9 @@ struct lpfc_mbx_request_features {
 #define lpfc_mbx_rq_ftr_rsp_ifip_SHIFT		7
 #define lpfc_mbx_rq_ftr_rsp_ifip_MASK		0x00000001
 #define lpfc_mbx_rq_ftr_rsp_ifip_WORD		word3
+#define lpfc_mbx_rq_ftr_rsp_perfh_SHIFT		11
+#define lpfc_mbx_rq_ftr_rsp_perfh_MASK		0x00000001
+#define lpfc_mbx_rq_ftr_rsp_perfh_WORD		word3
 };
 
 struct lpfc_mbx_supp_pages {
@@ -1935,7 +1942,7 @@ struct lpfc_mbx_supp_pages {
 #define LPFC_SLI4_PARAMETERS		2
 };
 
-struct lpfc_mbx_sli4_params {
+struct lpfc_mbx_pc_sli4_params {
 	uint32_t word1;
 #define qs_SHIFT				0
 #define qs_MASK					0x00000001
@@ -2051,6 +2058,88 @@ struct lpfc_mbx_sli4_params {
 	uint32_t rsvd_13_63[51];
 };
 
+struct lpfc_sli4_parameters {
+	uint32_t word0;
+#define cfg_prot_type_SHIFT			0
+#define cfg_prot_type_MASK			0x000000FF
+#define cfg_prot_type_WORD			word0
+	uint32_t word1;
+#define cfg_ft_SHIFT				0
+#define cfg_ft_MASK				0x00000001
+#define cfg_ft_WORD				word1
+#define cfg_sli_rev_SHIFT			4
+#define cfg_sli_rev_MASK			0x0000000f
+#define cfg_sli_rev_WORD			word1
+#define cfg_sli_family_SHIFT			8
+#define cfg_sli_family_MASK			0x0000000f
+#define cfg_sli_family_WORD			word1
+#define cfg_if_type_SHIFT			12
+#define cfg_if_type_MASK			0x0000000f
+#define cfg_if_type_WORD			word1
+#define cfg_sli_hint_1_SHIFT			16
+#define cfg_sli_hint_1_MASK			0x000000ff
+#define cfg_sli_hint_1_WORD			word1
+#define cfg_sli_hint_2_SHIFT			24
+#define cfg_sli_hint_2_MASK			0x0000001f
+#define cfg_sli_hint_2_WORD			word1
+	uint32_t word2;
+	uint32_t word3;
+	uint32_t word4;
+#define cfg_cqv_SHIFT				14
+#define cfg_cqv_MASK				0x00000003
+#define cfg_cqv_WORD				word4
+	uint32_t word5;
+	uint32_t word6;
+#define cfg_mqv_SHIFT				14
+#define cfg_mqv_MASK				0x00000003
+#define cfg_mqv_WORD				word6
+	uint32_t word7;
+	uint32_t word8;
+#define cfg_wqv_SHIFT				14
+#define cfg_wqv_MASK				0x00000003
+#define cfg_wqv_WORD				word8
+	uint32_t word9;
+	uint32_t word10;
+#define cfg_rqv_SHIFT				14
+#define cfg_rqv_MASK				0x00000003
+#define cfg_rqv_WORD				word10
+	uint32_t word11;
+#define cfg_rq_db_window_SHIFT			28
+#define cfg_rq_db_window_MASK			0x0000000f
+#define cfg_rq_db_window_WORD			word11
+	uint32_t word12;
+#define cfg_fcoe_SHIFT				0
+#define cfg_fcoe_MASK				0x00000001
+#define cfg_fcoe_WORD				word12
+#define cfg_phwq_SHIFT				15
+#define cfg_phwq_MASK				0x00000001
+#define cfg_phwq_WORD				word12
+#define cfg_loopbk_scope_SHIFT			28
+#define cfg_loopbk_scope_MASK			0x0000000f
+#define cfg_loopbk_scope_WORD			word12
+	uint32_t sge_supp_len;
+	uint32_t word14;
+#define cfg_sgl_page_cnt_SHIFT			0
+#define cfg_sgl_page_cnt_MASK			0x0000000f
+#define cfg_sgl_page_cnt_WORD			word14
+#define cfg_sgl_page_size_SHIFT			8
+#define cfg_sgl_page_size_MASK			0x000000ff
+#define cfg_sgl_page_size_WORD			word14
+#define cfg_sgl_pp_align_SHIFT			16
+#define cfg_sgl_pp_align_MASK			0x000000ff
+#define cfg_sgl_pp_align_WORD			word14
+	uint32_t word15;
+	uint32_t word16;
+	uint32_t word17;
+	uint32_t word18;
+	uint32_t word19;
+};
+
+struct lpfc_mbx_get_sli4_parameters {
+	struct mbox_header header;
+	struct lpfc_sli4_parameters sli4_parameters;
+};
+
 /* Mailbox Completion Queue Error Messages */
 #define MB_CQE_STATUS_SUCCESS 			0x0
 #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES	0x1
@@ -2103,7 +2192,8 @@ struct lpfc_mqe {
 		struct lpfc_mbx_post_hdr_tmpl hdr_tmpl;
 		struct lpfc_mbx_query_fw_cfg query_fw_cfg;
 		struct lpfc_mbx_supp_pages supp_pages;
-		struct lpfc_mbx_sli4_params sli4_params;
+		struct lpfc_mbx_pc_sli4_params sli4_params;
+		struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
 		struct lpfc_mbx_nop nop;
 	} un;
 };
@@ -2381,6 +2471,10 @@ struct wqe_common {
 #define wqe_wqes_SHIFT        15
 #define wqe_wqes_MASK         0x00000001
 #define wqe_wqes_WORD         word10
+/* Note that this field overlaps above fields */
+#define wqe_wqid_SHIFT        1
+#define wqe_wqid_MASK         0x0000007f
+#define wqe_wqid_WORD         word10
 #define wqe_pri_SHIFT         16
 #define wqe_pri_MASK          0x00000007
 #define wqe_pri_WORD          word10
@@ -2599,7 +2693,8 @@ struct fcp_iwrite64_wqe {
 	uint32_t total_xfer_len;
 	uint32_t initial_xfer_len;
 	struct wqe_common wqe_com;     /* words 6-11 */
-	uint32_t rsvd_12_15[4];         /* word 12-15 */
+	uint32_t rsrvd12;
+	struct ulp_bde64 ph_bde;       /* words 13-15 */
 };
 
 struct fcp_iread64_wqe {
@@ -2608,7 +2703,8 @@ struct fcp_iread64_wqe {
 	uint32_t total_xfer_len;       /* word 4 */
 	uint32_t rsrvd5;               /* word 5 */
 	struct wqe_common wqe_com;     /* words 6-11 */
-	uint32_t rsvd_12_15[4];         /* word 12-15 */
+	uint32_t rsrvd12;
+	struct ulp_bde64 ph_bde;       /* words 13-15 */
 };
 
 struct fcp_icmnd64_wqe {
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 6d0b36a..35665cf 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -460,7 +460,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G)
 		&& !(phba->lmt & LMT_16Gb))) {
 		/* Reset link speed to auto */
-		lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
 			"1302 Invalid speed for this board: "
 			"Reset link speed to auto: x%x\n",
 			phba->cfg_link_speed);
@@ -945,17 +945,13 @@ static void
 lpfc_rrq_timeout(unsigned long ptr)
 {
 	struct lpfc_hba *phba;
-	uint32_t tmo_posted;
 	unsigned long iflag;
 
 	phba = (struct lpfc_hba *)ptr;
 	spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
-	tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE;
-	if (!tmo_posted)
-		phba->hba_flag |= HBA_RRQ_ACTIVE;
+	phba->hba_flag |= HBA_RRQ_ACTIVE;
 	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
-	if (!tmo_posted)
-		lpfc_worker_wake_up(phba);
+	lpfc_worker_wake_up(phba);
 }
 
 /**
@@ -2280,6 +2276,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
 		/* Wait for any activity on ndlps to settle */
 		msleep(10);
 	}
+	lpfc_cleanup_vports_rrqs(vport, NULL);
 }
 
 /**
@@ -2295,6 +2292,7 @@ lpfc_stop_vport_timers(struct lpfc_vport *vport)
 {
 	del_timer_sync(&vport->els_tmofunc);
 	del_timer_sync(&vport->fc_fdmitmo);
+	del_timer_sync(&vport->delayed_disc_tmo);
 	lpfc_can_disctmo(vport);
 	return;
 }
@@ -2355,6 +2353,10 @@ lpfc_stop_hba_timers(struct lpfc_hba *phba)
 	del_timer_sync(&phba->fabric_block_timer);
 	del_timer_sync(&phba->eratt_poll);
 	del_timer_sync(&phba->hb_tmofunc);
+	if (phba->sli_rev == LPFC_SLI_REV4) {
+		del_timer_sync(&phba->rrq_tmr);
+		phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+	}
 	phba->hb_outstanding = 0;
 
 	switch (phba->pci_dev_grp) {
@@ -2732,6 +2734,11 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
 	init_timer(&vport->els_tmofunc);
 	vport->els_tmofunc.function = lpfc_els_timeout;
 	vport->els_tmofunc.data = (unsigned long)vport;
+
+	init_timer(&vport->delayed_disc_tmo);
+	vport->delayed_disc_tmo.function = lpfc_delayed_disc_tmo;
+	vport->delayed_disc_tmo.data = (unsigned long)vport;
+
 	error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
 	if (error)
 		goto out_put_shost;
@@ -4283,36 +4290,37 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
 		goto out_free_bsmbx;
 	}
 
-	/* Get the Supported Pages. It is always available. */
+	/* Get the Supported Pages if PORT_CAPABILITIES is supported by port. */
 	lpfc_supported_pages(mboxq);
 	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	if (unlikely(rc)) {
-		rc = -EIO;
-		mempool_free(mboxq, phba->mbox_mem_pool);
-		goto out_free_bsmbx;
-	}
-
-	mqe = &mboxq->u.mqe;
-	memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3),
-	       LPFC_MAX_SUPPORTED_PAGES);
-	for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) {
-		switch (pn_page[i]) {
-		case LPFC_SLI4_PARAMETERS:
-			phba->sli4_hba.pc_sli4_params.supported = 1;
-			break;
-		default:
-			break;
+	if (!rc) {
+		mqe = &mboxq->u.mqe;
+		memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3),
+		       LPFC_MAX_SUPPORTED_PAGES);
+		for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) {
+			switch (pn_page[i]) {
+			case LPFC_SLI4_PARAMETERS:
+				phba->sli4_hba.pc_sli4_params.supported = 1;
+				break;
+			default:
+				break;
+			}
+		}
+		/* Read the port's SLI4 Parameters capabilities if supported. */
+		if (phba->sli4_hba.pc_sli4_params.supported)
+			rc = lpfc_pc_sli4_params_get(phba, mboxq);
+		if (rc) {
+			mempool_free(mboxq, phba->mbox_mem_pool);
+			rc = -EIO;
+			goto out_free_bsmbx;
 		}
 	}
-
-	/* Read the port's SLI4 Parameters capabilities if supported. */
-	if (phba->sli4_hba.pc_sli4_params.supported)
-		rc = lpfc_pc_sli4_params_get(phba, mboxq);
+	/*
+	 * Get sli4 parameters that override parameters from Port capabilities.
+	 * If this call fails it is not a critical error so continue loading.
+	 */
+	lpfc_get_sli4_parameters(phba, mboxq);
 	mempool_free(mboxq, phba->mbox_mem_pool);
-	if (rc) {
-		rc = -EIO;
-		goto out_free_bsmbx;
-	}
 	/* Create all the SLI4 queues */
 	rc = lpfc_sli4_queue_create(phba);
 	if (rc)
@@ -7810,7 +7818,7 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 	mqe = &mboxq->u.mqe;
 
 	/* Read the port's SLI4 Parameters port capabilities */
-	lpfc_sli4_params(mboxq);
+	lpfc_pc_sli4_params(mboxq);
 	if (!phba->sli4_hba.intr_enable)
 		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
 	else {
@@ -7854,6 +7862,66 @@ lpfc_pc_sli4_params_get(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
 }
 
 /**
+ * lpfc_get_sli4_parameters - Get the SLI4 Config PARAMETERS.
+ * @phba: Pointer to HBA context object.
+ * @mboxq: Pointer to the mailboxq memory for the mailbox command response.
+ *
+ * This function is called in the SLI4 code path to read the port's
+ * sli4 capabilities.
+ *
+ * This function may be be called from any context that can block-wait
+ * for the completion.  The expectation is that this routine is called
+ * typically from probe_one or from the online routine.
+ **/
+int
+lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+	int rc;
+	struct lpfc_mqe *mqe = &mboxq->u.mqe;
+	struct lpfc_pc_sli4_params *sli4_params;
+	int length;
+	struct lpfc_sli4_parameters *mbx_sli4_parameters;
+
+	/* Read the port's SLI4 Config Parameters */
+	length = (sizeof(struct lpfc_mbx_get_sli4_parameters) -
+		  sizeof(struct lpfc_sli4_cfg_mhdr));
+	lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+			 LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS,
+			 length, LPFC_SLI4_MBX_EMBED);
+	if (!phba->sli4_hba.intr_enable)
+		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+	else
+		rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
+			lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
+	if (unlikely(rc))
+		return rc;
+	sli4_params = &phba->sli4_hba.pc_sli4_params;
+	mbx_sli4_parameters = &mqe->un.get_sli4_parameters.sli4_parameters;
+	sli4_params->if_type = bf_get(cfg_if_type, mbx_sli4_parameters);
+	sli4_params->sli_rev = bf_get(cfg_sli_rev, mbx_sli4_parameters);
+	sli4_params->sli_family = bf_get(cfg_sli_family, mbx_sli4_parameters);
+	sli4_params->featurelevel_1 = bf_get(cfg_sli_hint_1,
+					     mbx_sli4_parameters);
+	sli4_params->featurelevel_2 = bf_get(cfg_sli_hint_2,
+					     mbx_sli4_parameters);
+	if (bf_get(cfg_phwq, mbx_sli4_parameters))
+		phba->sli3_options |= LPFC_SLI4_PHWQ_ENABLED;
+	else
+		phba->sli3_options &= ~LPFC_SLI4_PHWQ_ENABLED;
+	sli4_params->sge_supp_len = mbx_sli4_parameters->sge_supp_len;
+	sli4_params->loopbk_scope = bf_get(loopbk_scope, mbx_sli4_parameters);
+	sli4_params->cqv = bf_get(cfg_cqv, mbx_sli4_parameters);
+	sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters);
+	sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters);
+	sli4_params->rqv = bf_get(cfg_rqv, mbx_sli4_parameters);
+	sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
+					    mbx_sli4_parameters);
+	sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align,
+					   mbx_sli4_parameters);
+	return 0;
+}
+
+/**
  * lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem.
  * @pdev: pointer to PCI device
  * @pid: pointer to PCI device identifier
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 23403c6..dba32df 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1263,7 +1263,8 @@ lpfc_config_port(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
 	if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) {
 		if (phba->cfg_enable_bg)
 			mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */
-		mb->un.varCfgPort.cdss = 1; /* Configure Security */
+		if (phba->cfg_enable_dss)
+			mb->un.varCfgPort.cdss = 1; /* Configure Security */
 		mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
 		mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */
 		mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count();
@@ -1692,7 +1693,7 @@ lpfc_sli4_mbox_cmd_free(struct lpfc_hba *phba, struct lpfcMboxq *mbox)
  * @mbox: pointer to lpfc mbox command.
  * @subsystem: The sli4 config sub mailbox subsystem.
  * @opcode: The sli4 config sub mailbox command opcode.
- * @length: Length of the sli4 config mailbox command.
+ * @length: Length of the sli4 config mailbox command (including sub-header).
  *
  * This routine sets up the header fields of SLI4 specific mailbox command
  * for sending IOCTL command.
@@ -1723,14 +1724,14 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
 	if (emb) {
 		/* Set up main header fields */
 		bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1);
-		sli4_config->header.cfg_mhdr.payload_length =
-					LPFC_MBX_CMD_HDR_LENGTH + length;
+		sli4_config->header.cfg_mhdr.payload_length = length;
 		/* Set up sub-header fields following main header */
 		bf_set(lpfc_mbox_hdr_opcode,
 			&sli4_config->header.cfg_shdr.request, opcode);
 		bf_set(lpfc_mbox_hdr_subsystem,
 			&sli4_config->header.cfg_shdr.request, subsystem);
-		sli4_config->header.cfg_shdr.request.request_length = length;
+		sli4_config->header.cfg_shdr.request.request_length =
+			length - LPFC_MBX_CMD_HDR_LENGTH;
 		return length;
 	}
 
@@ -1902,6 +1903,7 @@ lpfc_request_features(struct lpfc_hba *phba, struct lpfcMboxq *mboxq)
 
 	/* Set up host requested features. */
 	bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1);
+	bf_set(lpfc_mbx_rq_ftr_rq_perfh, &mboxq->u.mqe.un.req_ftrs, 1);
 
 	/* Enable DIF (block guard) only if configured to do so. */
 	if (phba->cfg_enable_bg)
@@ -2159,17 +2161,16 @@ lpfc_supported_pages(struct lpfcMboxq *mbox)
 }
 
 /**
- * lpfc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params
- *                    mailbox command.
+ * lpfc_pc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params mbox cmd.
  * @mbox: pointer to lpfc mbox command to initialize.
  *
  * The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to
  * retrieve the particular SLI4 features supported by the port.
  **/
 void
-lpfc_sli4_params(struct lpfcMboxq *mbox)
+lpfc_pc_sli4_params(struct lpfcMboxq *mbox)
 {
-	struct lpfc_mbx_sli4_params *sli4_params;
+	struct lpfc_mbx_pc_sli4_params *sli4_params;
 
 	memset(mbox, 0, sizeof(*mbox));
 	sli4_params = &mbox->u.mqe.un.sli4_params;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index d85a742..52b3515 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -350,7 +350,11 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 	ndlp->nlp_maxframe =
 		((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
 
-	/* no need to reg_login if we are already in one of these states */
+	/*
+	 * Need to unreg_login if we are already in one of these states and
+	 * change to NPR state. This will block the port until after the ACC
+	 * completes and the reg_login is issued and completed.
+	 */
 	switch (ndlp->nlp_state) {
 	case  NLP_STE_NPR_NODE:
 		if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
@@ -359,8 +363,9 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 	case  NLP_STE_PRLI_ISSUE:
 	case  NLP_STE_UNMAPPED_NODE:
 	case  NLP_STE_MAPPED_NODE:
-		lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
-		return 1;
+		lpfc_unreg_rpi(vport, ndlp);
+		ndlp->nlp_prev_state = ndlp->nlp_state;
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 	}
 
 	if ((vport->fc_flag & FC_PT2PT) &&
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index c97751c..bf34178 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -609,6 +609,32 @@ lpfc_new_scsi_buf_s3(struct lpfc_vport *vport, int num_to_alloc)
 }
 
 /**
+ * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport
+ * @vport: pointer to lpfc vport data structure.
+ *
+ * This routine is invoked by the vport cleanup for deletions and the cleanup
+ * for an ndlp on removal.
+ **/
+void
+lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_scsi_buf *psb, *next_psb;
+	unsigned long iflag = 0;
+
+	spin_lock_irqsave(&phba->hbalock, iflag);
+	spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock);
+	list_for_each_entry_safe(psb, next_psb,
+				&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
+		if (psb->rdata && psb->rdata->pnode
+			&& psb->rdata->pnode->vport == vport)
+			psb->rdata = NULL;
+	}
+	spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
+}
+
+/**
  * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort
  * @phba: pointer to lpfc hba data structure.
  * @axri: pointer to the fcp xri abort wcqe structure.
@@ -640,7 +666,11 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
 			psb->status = IOSTAT_SUCCESS;
 			spin_unlock(
 				&phba->sli4_hba.abts_scsi_buf_list_lock);
-			ndlp = psb->rdata->pnode;
+			if (psb->rdata && psb->rdata->pnode)
+				ndlp = psb->rdata->pnode;
+			else
+				ndlp = NULL;
+
 			rrq_empty = list_empty(&phba->active_rrq_list);
 			spin_unlock_irqrestore(&phba->hbalock, iflag);
 			if (ndlp)
@@ -964,36 +994,29 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 static struct lpfc_scsi_buf*
 lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
-	struct  lpfc_scsi_buf *lpfc_cmd = NULL;
-	struct  lpfc_scsi_buf *start_lpfc_cmd = NULL;
-	struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+	struct lpfc_scsi_buf *lpfc_cmd ;
 	unsigned long iflag = 0;
 	int found = 0;
 
 	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-	list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
-	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
-	while (!found && lpfc_cmd) {
+	list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
+							list) {
 		if (lpfc_test_rrq_active(phba, ndlp,
-					 lpfc_cmd->cur_iocbq.sli4_xritag)) {
-			lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
-			spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-			list_remove_head(scsi_buf_list, lpfc_cmd,
-					 struct lpfc_scsi_buf, list);
-			spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
-						 iflag);
-			if (lpfc_cmd == start_lpfc_cmd) {
-				lpfc_cmd = NULL;
-				break;
-			} else
-				continue;
-		}
+					 lpfc_cmd->cur_iocbq.sli4_xritag))
+			continue;
+		list_del(&lpfc_cmd->list);
 		found = 1;
 		lpfc_cmd->seg_cnt = 0;
 		lpfc_cmd->nonsg_phys = 0;
 		lpfc_cmd->prot_seg_cnt = 0;
+		break;
 	}
-	return  lpfc_cmd;
+	spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
+						 iflag);
+	if (!found)
+		return NULL;
+	else
+		return  lpfc_cmd;
 }
 /**
  * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
@@ -1981,12 +2004,14 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
 	struct scatterlist *sgel = NULL;
 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
 	struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl;
+	struct sli4_sge *first_data_sgl;
 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
 	dma_addr_t physaddr;
 	uint32_t num_bde = 0;
 	uint32_t dma_len;
 	uint32_t dma_offset = 0;
 	int nseg;
+	struct ulp_bde64 *bde;
 
 	/*
 	 * There are three possibilities here - use scatter-gather segment, use
@@ -2011,7 +2036,7 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
 		bf_set(lpfc_sli4_sge_last, sgl, 0);
 		sgl->word2 = cpu_to_le32(sgl->word2);
 		sgl += 1;
-
+		first_data_sgl = sgl;
 		lpfc_cmd->seg_cnt = nseg;
 		if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:"
@@ -2047,6 +2072,17 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd)
 			dma_offset += dma_len;
 			sgl++;
 		}
+		/* setup the performance hint (first data BDE) if enabled */
+		if (phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) {
+			bde = (struct ulp_bde64 *)
+					&(iocb_cmd->unsli3.sli3Words[5]);
+			bde->addrLow = first_data_sgl->addr_lo;
+			bde->addrHigh = first_data_sgl->addr_hi;
+			bde->tus.f.bdeSize =
+					le32_to_cpu(first_data_sgl->sge_len);
+			bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+			bde->tus.w = cpu_to_le32(bde->tus.w);
+		}
 	} else {
 		sgl += 1;
 		/* clear the last flag in the fcp_rsp map entry */
@@ -2471,6 +2507,16 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 			lpfc_worker_wake_up(phba);
 			break;
 		case IOSTAT_LOCAL_REJECT:
+		case IOSTAT_REMOTE_STOP:
+			if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR ||
+			    lpfc_cmd->result ==
+					IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR ||
+			    lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR ||
+			    lpfc_cmd->result ==
+					IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) {
+				cmd->result = ScsiResult(DID_NO_CONNECT, 0);
+				break;
+			}
 			if (lpfc_cmd->result == IOERR_INVALID_RPI ||
 			    lpfc_cmd->result == IOERR_NO_RESOURCES ||
 			    lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
@@ -2478,7 +2524,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 				cmd->result = ScsiResult(DID_REQUEUE, 0);
 				break;
 			}
-
 			if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
 			     lpfc_cmd->result == IOERR_TX_DMA_FAILED) &&
 			     pIocbOut->iocb.unsli3.sli3_bg.bgstat) {
@@ -2497,7 +2542,17 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 							"on unprotected cmd\n");
 				}
 			}
-
+			if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP)
+				&& (phba->sli_rev == LPFC_SLI_REV4)
+				&& (pnode && NLP_CHK_NODE_ACT(pnode))) {
+				/* This IO was aborted by the target, we don't
+				 * know the rxid and because we did not send the
+				 * ABTS we cannot generate and RRQ.
+				 */
+				lpfc_set_rrq_active(phba, pnode,
+						lpfc_cmd->cur_iocbq.sli4_xritag,
+						0, 0);
+			}
 		/* else: fall through */
 		default:
 			cmd->result = ScsiResult(DID_ERROR, 0);
@@ -2508,9 +2563,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
 		    || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
 			cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED,
 						 SAM_STAT_BUSY);
-	} else {
+	} else
 		cmd->result = ScsiResult(DID_OK, 0);
-	}
 
 	if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) {
 		uint32_t *lp = (uint32_t *)cmd->sense_buffer;
@@ -3004,11 +3058,11 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
 	 * transport is still transitioning.
 	 */
 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
-		cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
+		cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
 		goto out_fail_command;
 	}
 	if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
-		goto out_host_busy;
+		goto out_tgt_busy;
 
 	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
 	if (lpfc_cmd == NULL) {
@@ -3125,6 +3179,9 @@ lpfc_queuecommand_lck(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
  out_host_busy:
 	return SCSI_MLQUEUE_HOST_BUSY;
 
+ out_tgt_busy:
+	return SCSI_MLQUEUE_TARGET_BUSY;
+
  out_fail_command:
 	done(cmnd);
 	return 0;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index a359d2b..2ee0374 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -96,7 +96,8 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe)
 	/* set consumption flag every once in a while */
 	if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL))
 		bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
-
+	if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
+		bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
 	lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
 
 	/* Update the host index before invoking device */
@@ -534,15 +535,35 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 	uint16_t adj_xri;
 	struct lpfc_node_rrq *rrq;
 	int empty;
+	uint32_t did = 0;
+
+
+	if (!ndlp)
+		return -EINVAL;
+
+	if (!phba->cfg_enable_rrq)
+		return -EINVAL;
+
+	if (phba->pport->load_flag & FC_UNLOADING) {
+		phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+		goto out;
+	}
+	did = ndlp->nlp_DID;
 
 	/*
 	 * set the active bit even if there is no mem available.
 	 */
 	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
-	if (!ndlp)
-		return -EINVAL;
+
+	if (NLP_CHK_FREE_REQ(ndlp))
+		goto out;
+
+	if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
+		goto out;
+
 	if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
-		return -EINVAL;
+		goto out;
+
 	rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
 	if (rrq) {
 		rrq->send_rrq = send_rrq;
@@ -553,14 +574,7 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 		rrq->vport = ndlp->vport;
 		rrq->rxid = rxid;
 		empty = list_empty(&phba->active_rrq_list);
-		if (phba->cfg_enable_rrq && send_rrq)
-			/*
-			 * We need the xri before we can add this to the
-			 * phba active rrq list.
-			 */
-			rrq->send_rrq = send_rrq;
-		else
-			rrq->send_rrq = 0;
+		rrq->send_rrq = send_rrq;
 		list_add_tail(&rrq->list, &phba->active_rrq_list);
 		if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
 			phba->hba_flag |= HBA_RRQ_ACTIVE;
@@ -569,40 +583,49 @@ __lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 		}
 		return 0;
 	}
-	return -ENOMEM;
+out:
+	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+			"2921 Can't set rrq active xri:0x%x rxid:0x%x"
+			" DID:0x%x Send:%d\n",
+			xritag, rxid, did, send_rrq);
+	return -EINVAL;
 }
 
 /**
- * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
  * @phba: Pointer to HBA context object.
  * @xritag: xri used in this exchange.
  * @rrq: The RRQ to be cleared.
  *
- * This function is called with hbalock held. This function
  **/
-static void
-__lpfc_clr_rrq_active(struct lpfc_hba *phba,
-			uint16_t xritag,
-			struct lpfc_node_rrq *rrq)
+void
+lpfc_clr_rrq_active(struct lpfc_hba *phba,
+		    uint16_t xritag,
+		    struct lpfc_node_rrq *rrq)
 {
 	uint16_t adj_xri;
-	struct lpfc_nodelist *ndlp;
+	struct lpfc_nodelist *ndlp = NULL;
 
-	ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
+	if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp))
+		ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
 
 	/* The target DID could have been swapped (cable swap)
 	 * we should use the ndlp from the findnode if it is
 	 * available.
 	 */
-	if (!ndlp)
+	if ((!ndlp) && rrq->ndlp)
 		ndlp = rrq->ndlp;
 
+	if (!ndlp)
+		goto out;
+
 	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
 	if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) {
 		rrq->send_rrq = 0;
 		rrq->xritag = 0;
 		rrq->rrq_stop_time = 0;
 	}
+out:
 	mempool_free(rrq, phba->rrq_pool);
 }
 
@@ -627,34 +650,34 @@ lpfc_handle_rrq_active(struct lpfc_hba *phba)
 	struct lpfc_node_rrq *nextrrq;
 	unsigned long next_time;
 	unsigned long iflags;
+	LIST_HEAD(send_rrq);
 
 	spin_lock_irqsave(&phba->hbalock, iflags);
 	phba->hba_flag &= ~HBA_RRQ_ACTIVE;
 	next_time = jiffies + HZ * (phba->fc_ratov + 1);
 	list_for_each_entry_safe(rrq, nextrrq,
-			&phba->active_rrq_list, list) {
-		if (time_after(jiffies, rrq->rrq_stop_time)) {
-			list_del(&rrq->list);
-			if (!rrq->send_rrq)
-				/* this call will free the rrq */
-				__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
-			else {
-			/* if we send the rrq then the completion handler
-			 *  will clear the bit in the xribitmap.
-			 */
-				spin_unlock_irqrestore(&phba->hbalock, iflags);
-				if (lpfc_send_rrq(phba, rrq)) {
-					lpfc_clr_rrq_active(phba, rrq->xritag,
-								 rrq);
-				}
-				spin_lock_irqsave(&phba->hbalock, iflags);
-			}
-		} else if  (time_before(rrq->rrq_stop_time, next_time))
+				 &phba->active_rrq_list, list) {
+		if (time_after(jiffies, rrq->rrq_stop_time))
+			list_move(&rrq->list, &send_rrq);
+		else if (time_before(rrq->rrq_stop_time, next_time))
 			next_time = rrq->rrq_stop_time;
 	}
 	spin_unlock_irqrestore(&phba->hbalock, iflags);
 	if (!list_empty(&phba->active_rrq_list))
 		mod_timer(&phba->rrq_tmr, next_time);
+	list_for_each_entry_safe(rrq, nextrrq, &send_rrq, list) {
+		list_del(&rrq->list);
+		if (!rrq->send_rrq)
+			/* this call will free the rrq */
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+		else if (lpfc_send_rrq(phba, rrq)) {
+			/* if we send the rrq then the completion handler
+			*  will clear the bit in the xribitmap.
+			*/
+			lpfc_clr_rrq_active(phba, rrq->xritag,
+					    rrq);
+		}
+	}
 }
 
 /**
@@ -692,29 +715,37 @@ lpfc_get_active_rrq(struct lpfc_vport *vport, uint16_t xri, uint32_t did)
 /**
  * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport.
  * @vport: Pointer to vport context object.
- *
- * Remove all active RRQs for this vport from the phba->active_rrq_list and
- * clear the rrq.
+ * @ndlp: Pointer to the lpfc_node_list structure.
+ * If ndlp is NULL Remove all active RRQs for this vport from the
+ * phba->active_rrq_list and clear the rrq.
+ * If ndlp is not NULL then only remove rrqs for this vport & this ndlp.
  **/
 void
-lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport)
+lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 
 {
 	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_node_rrq *rrq;
 	struct lpfc_node_rrq *nextrrq;
 	unsigned long iflags;
+	LIST_HEAD(rrq_list);
 
 	if (phba->sli_rev != LPFC_SLI_REV4)
 		return;
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
-		if (rrq->vport == vport) {
-			list_del(&rrq->list);
-			__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
-		}
+	if (!ndlp) {
+		lpfc_sli4_vport_delete_els_xri_aborted(vport);
+		lpfc_sli4_vport_delete_fcp_xri_aborted(vport);
 	}
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list)
+		if ((rrq->vport == vport) && (!ndlp  || rrq->ndlp == ndlp))
+			list_move(&rrq->list, &rrq_list);
 	spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+	list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
+		list_del(&rrq->list);
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+	}
 }
 
 /**
@@ -732,24 +763,27 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
 	struct lpfc_node_rrq *nextrrq;
 	unsigned long next_time;
 	unsigned long iflags;
+	LIST_HEAD(rrq_list);
 
 	if (phba->sli_rev != LPFC_SLI_REV4)
 		return;
 	spin_lock_irqsave(&phba->hbalock, iflags);
 	phba->hba_flag &= ~HBA_RRQ_ACTIVE;
 	next_time = jiffies + HZ * (phba->fc_ratov * 2);
-	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+	list_splice_init(&phba->active_rrq_list, &rrq_list);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+	list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
 		list_del(&rrq->list);
-		__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
 	}
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
 	if (!list_empty(&phba->active_rrq_list))
 		mod_timer(&phba->rrq_tmr, next_time);
 }
 
 
 /**
- * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
  * @phba: Pointer to HBA context object.
  * @ndlp: Targets nodelist pointer for this exchange.
  * @xritag the xri in the bitmap to test.
@@ -758,8 +792,8 @@ lpfc_cleanup_wt_rrqs(struct lpfc_hba *phba)
  * returns 0 = rrq not active for this xri
  *         1 = rrq is valid for this xri.
  **/
-static int
-__lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+int
+lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 			uint16_t  xritag)
 {
 	uint16_t adj_xri;
@@ -802,52 +836,6 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 }
 
 /**
- * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @xritag: xri used in this exchange.
- * @rrq: The RRQ to be cleared.
- *
- * This function is takes the hbalock.
- **/
-void
-lpfc_clr_rrq_active(struct lpfc_hba *phba,
-			uint16_t xritag,
-			struct lpfc_node_rrq *rrq)
-{
-	unsigned long iflags;
-
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	__lpfc_clr_rrq_active(phba, xritag, rrq);
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
-	return;
-}
-
-
-
-/**
- * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @ndlp: Targets nodelist pointer for this exchange.
- * @xritag the xri in the bitmap to test.
- *
- * This function takes the hbalock.
- * returns 0 = rrq not active for this xri
- *         1 = rrq is valid for this xri.
- **/
-int
-lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-			uint16_t  xritag)
-{
-	int ret;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	ret = __lpfc_test_rrq_active(phba, ndlp, xritag);
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
-	return ret;
-}
-
-/**
  * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool
  * @phba: Pointer to HBA context object.
  * @piocb: Pointer to the iocbq.
@@ -884,7 +872,7 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq)
 			return NULL;
 		adj_xri = sglq->sli4_xritag -
 				phba->sli4_hba.max_cfg_param.xri_base;
-		if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
+		if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
 			/* This xri has an rrq outstanding for this DID.
 			 * put it back in the list and get another xri.
 			 */
@@ -969,7 +957,8 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
 		} else {
 			sglq->state = SGL_FREED;
 			sglq->ndlp = NULL;
-			list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list);
+			list_add_tail(&sglq->list,
+				&phba->sli4_hba.lpfc_sgl_list);
 
 			/* Check if TXQ queue needs to be serviced */
 			if (pring->txq_cnt)
@@ -4817,7 +4806,10 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
 				"0378 No support for fcpi mode.\n");
 		ftr_rsp++;
 	}
-
+	if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs))
+		phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED;
+	else
+		phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED;
 	/*
 	 * If the port cannot support the host's requested features
 	 * then turn off the global config parameters to disable the
@@ -5004,7 +4996,8 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
 	spin_lock_irq(&phba->hbalock);
 	phba->link_state = LPFC_LINK_DOWN;
 	spin_unlock_irq(&phba->hbalock);
-	rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+	if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
+		rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
 out_unset_queue:
 	/* Unset all the queues set up in this routine when error out */
 	if (rc)
@@ -10478,6 +10471,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
 	cq->type = type;
 	cq->subtype = subtype;
 	cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response);
+	cq->assoc_qid = eq->queue_id;
 	cq->host_index = 0;
 	cq->hba_index = 0;
 
@@ -10672,6 +10666,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
 		goto out;
 	}
 	mq->type = LPFC_MQ;
+	mq->assoc_qid = cq->queue_id;
 	mq->subtype = subtype;
 	mq->host_index = 0;
 	mq->hba_index = 0;
@@ -10759,6 +10754,7 @@ lpfc_wq_create(struct lpfc_hba *phba, struct lpfc_queue *wq,
 		goto out;
 	}
 	wq->type = LPFC_WQ;
+	wq->assoc_qid = cq->queue_id;
 	wq->subtype = subtype;
 	wq->host_index = 0;
 	wq->hba_index = 0;
@@ -10876,6 +10872,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
 		goto out;
 	}
 	hrq->type = LPFC_HRQ;
+	hrq->assoc_qid = cq->queue_id;
 	hrq->subtype = subtype;
 	hrq->host_index = 0;
 	hrq->hba_index = 0;
@@ -10936,6 +10933,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
 		goto out;
 	}
 	drq->type = LPFC_DRQ;
+	drq->assoc_qid = cq->queue_id;
 	drq->subtype = subtype;
 	drq->host_index = 0;
 	drq->hba_index = 0;
@@ -11189,7 +11187,7 @@ lpfc_rq_destroy(struct lpfc_hba *phba, struct lpfc_queue *hrq,
 	if (!mbox)
 		return -ENOMEM;
 	length = (sizeof(struct lpfc_mbx_rq_destroy) -
-		  sizeof(struct mbox_header));
+		  sizeof(struct lpfc_sli4_cfg_mhdr));
 	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
 			 LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY,
 			 length, LPFC_SLI4_MBX_EMBED);
@@ -11279,7 +11277,7 @@ lpfc_sli4_post_sgl(struct lpfc_hba *phba,
 	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
 			LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
 			sizeof(struct lpfc_mbx_post_sgl_pages) -
-			sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED);
+			sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED);
 
 	post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *)
 				&mbox->u.mqe.un.post_sgl_pages;
@@ -12402,7 +12400,8 @@ lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page)
 	lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
 			 LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE,
 			 sizeof(struct lpfc_mbx_post_hdr_tmpl) -
-			 sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED);
+			 sizeof(struct lpfc_sli4_cfg_mhdr),
+			 LPFC_SLI4_MBX_EMBED);
 	bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt,
 	       hdr_tmpl, rpi_page->page_count);
 	bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl,
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index c7217d5..595056b 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -125,9 +125,9 @@ struct lpfc_queue {
 	uint32_t entry_count;	/* Number of entries to support on the queue */
 	uint32_t entry_size;	/* Size of each queue entry. */
 	uint32_t queue_id;	/* Queue ID assigned by the hardware */
+	uint32_t assoc_qid;     /* Queue ID associated with, for CQ/WQ/MQ */
 	struct list_head page_list;
 	uint32_t page_count;	/* Number of pages allocated for this queue */
-
 	uint32_t host_index;	/* The host's index for putting or getting */
 	uint32_t hba_index;	/* The last known hba index for get or put */
 	union sli4_qe qe[1];	/* array to index entries (must be last) */
@@ -359,6 +359,10 @@ struct lpfc_pc_sli4_params {
 	uint32_t hdr_pp_align;
 	uint32_t sgl_pages_max;
 	uint32_t sgl_pp_align;
+	uint8_t cqv;
+	uint8_t mqv;
+	uint8_t wqv;
+	uint8_t rqv;
 };
 
 /* SLI4 HBA data structure entries */
@@ -562,6 +566,8 @@ void lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *,
 			       struct sli4_wcqe_xri_aborted *);
 void lpfc_sli4_els_xri_aborted(struct lpfc_hba *,
 			       struct sli4_wcqe_xri_aborted *);
+void lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *);
+void lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *);
 int lpfc_sli4_brdreset(struct lpfc_hba *);
 int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *);
 void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 386cf92..0a4d376 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.20"
+#define LPFC_DRIVER_VERSION "8.3.21"
 #define LPFC_DRIVER_NAME		"lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME	"lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME	"lpfc:fp"
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index 6b8d295..30ba544 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -464,6 +464,7 @@ disable_vport(struct fc_vport *fc_vport)
 	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
 	long timeout;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
 	ndlp = lpfc_findnode_did(vport, Fabric_DID);
 	if (ndlp && NLP_CHK_NODE_ACT(ndlp)
@@ -498,6 +499,9 @@ disable_vport(struct fc_vport *fc_vport)
 	 * scsi_host_put() to release the vport.
 	 */
 	lpfc_mbx_unreg_vpi(vport);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+	spin_unlock_irq(shost->host_lock);
 
 	lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
 	lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 9aa0485..c212694 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -1412,7 +1412,7 @@ megaraid_isr_memmapped(int irq, void *devp)
  * @nstatus - number of completed commands
  * @status - status of the last command completed
  *
- * Complete the comamnds and call the scsi mid-layer callback hooks.
+ * Complete the commands and call the scsi mid-layer callback hooks.
  */
 static void
 mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
@@ -4296,7 +4296,7 @@ mega_support_cluster(adapter_t *adapter)
  * @adapter - pointer to our soft state
  * @dma_handle - DMA address of the buffer
  *
- * Issue internal comamnds while interrupts are available.
+ * Issue internal commands while interrupts are available.
  * We only issue direct mailbox commands from within the driver. ioctl()
  * interface using these routines can issue passthru commands.
  */
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 1b5e375..635b228 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -33,9 +33,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.05.29-rc1"
-#define MEGASAS_RELDATE				"Dec. 7, 2010"
-#define MEGASAS_EXT_VERSION			"Tue. Dec. 7 17:00:00 PDT 2010"
+#define MEGASAS_VERSION				"00.00.05.34-rc1"
+#define MEGASAS_RELDATE				"Feb. 24, 2011"
+#define MEGASAS_EXT_VERSION			"Thu. Feb. 24 17:00:00 PDT 2011"
 
 /*
  * Device IDs
@@ -723,6 +723,7 @@ struct megasas_ctrl_info {
 						MEGASAS_MAX_DEV_PER_CHANNEL)
 
 #define MEGASAS_MAX_SECTORS                    (2*1024)
+#define MEGASAS_MAX_SECTORS_IEEE		(2*128)
 #define MEGASAS_DBG_LVL				1
 
 #define MEGASAS_FW_BUSY				1
@@ -1477,4 +1478,7 @@ struct megasas_mgmt_info {
 	int max_index;
 };
 
+#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
+#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
+
 #endif				/*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 5d6d07b..bbd10c8 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -18,12 +18,13 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  *  FILE: megaraid_sas_base.c
- *  Version : v00.00.05.29-rc1
+ *  Version : v00.00.05.34-rc1
  *
  *  Authors: LSI Corporation
  *           Sreenivas Bagalkote
  *           Sumant Patro
  *           Bo Yang
+ *           Adam Radford <linuxraid@lsi.com>
  *
  *  Send feedback to: <megaraidlinux@lsi.com>
  *
@@ -134,7 +135,11 @@ spinlock_t poll_aen_lock;
 void
 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 		     u8 alt_status);
-
+static u32
+megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs);
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance,
+		       struct megasas_register_set __iomem *reg_set);
 static irqreturn_t megasas_isr(int irq, void *devp);
 static u32
 megasas_init_adapter_mfi(struct megasas_instance *instance);
@@ -554,6 +559,8 @@ static int
 megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
+
 	/*
 	 * Check if it is our interrupt
 	 */
@@ -564,6 +571,15 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
 	}
 
 	/*
+	 * Check if it is our interrupt
+	 */
+	if ((megasas_read_fw_status_reg_gen2(regs) & MFI_STATE_MASK) ==
+	    MFI_STATE_FAULT) {
+		mfiStatus = MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+	} else
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+
+	/*
 	 * Clear the interrupt by writing back the same value
 	 */
 	writel(status, &regs->outbound_intr_status);
@@ -573,7 +589,7 @@ megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
 	*/
 	readl(&regs->outbound_intr_status);
 
-	return 1;
+	return mfiStatus;
 }
 
 /**
@@ -597,17 +613,6 @@ megasas_fire_cmd_skinny(struct megasas_instance *instance,
 }
 
 /**
- * megasas_adp_reset_skinny -	For controller reset
- * @regs:				MFI register set
- */
-static int
-megasas_adp_reset_skinny(struct megasas_instance *instance,
-			struct megasas_register_set __iomem *regs)
-{
-	return 0;
-}
-
-/**
  * megasas_check_reset_skinny -	For controller reset check
  * @regs:				MFI register set
  */
@@ -625,7 +630,7 @@ static struct megasas_instance_template megasas_instance_template_skinny = {
 	.disable_intr = megasas_disable_intr_skinny,
 	.clear_intr = megasas_clear_intr_skinny,
 	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
-	.adp_reset = megasas_adp_reset_skinny,
+	.adp_reset = megasas_adp_reset_gen2,
 	.check_reset = megasas_check_reset_skinny,
 	.service_isr = megasas_isr,
 	.tasklet = megasas_complete_cmd_dpc,
@@ -740,20 +745,28 @@ megasas_adp_reset_gen2(struct megasas_instance *instance,
 {
 	u32			retry = 0 ;
 	u32			HostDiag;
+	u32			*seq_offset = &reg_set->seq_offset;
+	u32			*hostdiag_offset = &reg_set->host_diag;
+
+	if (instance->instancet == &megasas_instance_template_skinny) {
+		seq_offset = &reg_set->fusion_seq_offset;
+		hostdiag_offset = &reg_set->fusion_host_diag;
+	}
+
+	writel(0, seq_offset);
+	writel(4, seq_offset);
+	writel(0xb, seq_offset);
+	writel(2, seq_offset);
+	writel(7, seq_offset);
+	writel(0xd, seq_offset);
 
-	writel(0, &reg_set->seq_offset);
-	writel(4, &reg_set->seq_offset);
-	writel(0xb, &reg_set->seq_offset);
-	writel(2, &reg_set->seq_offset);
-	writel(7, &reg_set->seq_offset);
-	writel(0xd, &reg_set->seq_offset);
 	msleep(1000);
 
-	HostDiag = (u32)readl(&reg_set->host_diag);
+	HostDiag = (u32)readl(hostdiag_offset);
 
 	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
 		msleep(100);
-		HostDiag = (u32)readl(&reg_set->host_diag);
+		HostDiag = (u32)readl(hostdiag_offset);
 		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
 					retry, HostDiag);
 
@@ -764,14 +777,14 @@ megasas_adp_reset_gen2(struct megasas_instance *instance,
 
 	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
 
-	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+	writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset);
 
 	ssleep(10);
 
-	HostDiag = (u32)readl(&reg_set->host_diag);
+	HostDiag = (u32)readl(hostdiag_offset);
 	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
 		msleep(100);
-		HostDiag = (u32)readl(&reg_set->host_diag);
+		HostDiag = (u32)readl(hostdiag_offset);
 		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
 				retry, HostDiag);
 
@@ -877,7 +890,7 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance,
  * @instance:				Adapter soft state
  * @cmd_to_abort:			Previously issued cmd to be aborted
  *
- * MFI firmware can abort previously issued AEN comamnd (automatic event
+ * MFI firmware can abort previously issued AEN command (automatic event
  * notification). The megasas_issue_blocked_abort_cmd() issues such abort
  * cmd and waits for return status.
  * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
@@ -2503,7 +2516,9 @@ megasas_deplete_reply_queue(struct megasas_instance *instance,
 	if ((mfiStatus = instance->instancet->clear_intr(
 						instance->reg_set)
 						) == 0) {
-		return IRQ_NONE;
+		/* Hardware may not set outbound_intr_status in MSI-X mode */
+		if (!instance->msi_flag)
+			return IRQ_NONE;
 	}
 
 	instance->mfiStatus = mfiStatus;
@@ -2611,7 +2626,9 @@ megasas_transition_to_ready(struct megasas_instance* instance)
 		case MFI_STATE_FAULT:
 
 			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
-			return -ENODEV;
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_FAULT;
+			break;
 
 		case MFI_STATE_WAIT_HANDSHAKE:
 			/*
@@ -3424,7 +3441,6 @@ fail_reply_queue:
 	megasas_free_cmds(instance);
 
 fail_alloc_cmds:
-	iounmap(instance->reg_set);
 	return 1;
 }
 
@@ -3494,7 +3510,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
 
 	/* Get operational params, sge flags, send init cmd to controller */
 	if (instance->instancet->init_adapter(instance))
-		return -ENODEV;
+		goto fail_init_adapter;
 
 	printk(KERN_ERR "megasas: INIT adapter done\n");
 
@@ -3543,7 +3559,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
 	* Setup tasklet for cmd completion
 	*/
 
-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
 		(unsigned long)instance);
 
 	/* Initialize the cmd completion timer */
@@ -3553,6 +3569,7 @@ static int megasas_init_fw(struct megasas_instance *instance)
 				MEGASAS_COMPLETION_TIMER_INTERVAL);
 	return 0;
 
+fail_init_adapter:
 fail_ready_state:
 	iounmap(instance->reg_set);
 
@@ -3820,6 +3837,10 @@ static int megasas_io_attach(struct megasas_instance *instance)
 			instance->max_fw_cmds - MEGASAS_INT_CMDS;
 	host->this_id = instance->init_id;
 	host->sg_tablesize = instance->max_num_sge;
+
+	if (instance->fw_support_ieee)
+		instance->max_sectors_per_req = MEGASAS_MAX_SECTORS_IEEE;
+
 	/*
 	 * Check if the module parameter value for max_sectors can be used
 	 */
@@ -3899,9 +3920,26 @@ fail_set_dma_mask:
 static int __devinit
 megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	int rval;
+	int rval, pos;
 	struct Scsi_Host *host;
 	struct megasas_instance *instance;
+	u16 control = 0;
+
+	/* Reset MSI-X in the kdump kernel */
+	if (reset_devices) {
+		pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+		if (pos) {
+			pci_read_config_word(pdev, msi_control_reg(pos),
+					     &control);
+			if (control & PCI_MSIX_FLAGS_ENABLE) {
+				dev_info(&pdev->dev, "resetting MSI-X\n");
+				pci_write_config_word(pdev,
+						      msi_control_reg(pos),
+						      control &
+						      ~PCI_MSIX_FLAGS_ENABLE);
+			}
+		}
+	}
 
 	/*
 	 * Announce PCI information
@@ -4039,12 +4077,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	else
 		INIT_WORK(&instance->work_init, process_fw_state_change_wq);
 
-	/*
-	 * Initialize MFI Firmware
-	 */
-	if (megasas_init_fw(instance))
-		goto fail_init_mfi;
-
 	/* Try to enable MSI-X */
 	if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
 	    (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
@@ -4054,6 +4086,12 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 		instance->msi_flag = 1;
 
 	/*
+	 * Initialize MFI Firmware
+	 */
+	if (megasas_init_fw(instance))
+		goto fail_init_mfi;
+
+	/*
 	 * Register IRQ
 	 */
 	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
@@ -4105,24 +4143,23 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	instance->instancet->disable_intr(instance->reg_set);
 	free_irq(instance->msi_flag ? instance->msixentry.vector :
 		 instance->pdev->irq, instance);
+fail_irq:
+	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+		megasas_release_fusion(instance);
+	else
+		megasas_release_mfi(instance);
+      fail_init_mfi:
 	if (instance->msi_flag)
 		pci_disable_msix(instance->pdev);
-
-      fail_irq:
-      fail_init_mfi:
       fail_alloc_dma_buf:
 	if (instance->evt_detail)
 		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
 				    instance->evt_detail,
 				    instance->evt_detail_h);
 
-	if (instance->producer) {
+	if (instance->producer)
 		pci_free_consistent(pdev, sizeof(u32), instance->producer,
 				    instance->producer_h);
-		megasas_release_mfi(instance);
-	} else {
-		megasas_release_fusion(instance);
-	}
 	if (instance->consumer)
 		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
 				    instance->consumer_h);
@@ -4242,9 +4279,8 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state)
 	/* cancel the delayed work if this work still in queue */
 	if (instance->ev != NULL) {
 		struct megasas_aen_event *ev = instance->ev;
-		cancel_delayed_work(
+		cancel_delayed_work_sync(
 			(struct delayed_work *)&ev->hotplug_work);
-		flush_scheduled_work();
 		instance->ev = NULL;
 	}
 
@@ -4297,6 +4333,10 @@ megasas_resume(struct pci_dev *pdev)
 	if (megasas_set_dma_mask(pdev))
 		goto fail_set_dma_mask;
 
+	/* Now re-enable MSI-X */
+	if (instance->msi_flag)
+		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+
 	/*
 	 * Initialize MFI Firmware
 	 */
@@ -4333,10 +4373,6 @@ megasas_resume(struct pci_dev *pdev)
 	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
 		     (unsigned long)instance);
 
-	/* Now re-enable MSI-X */
-	if (instance->msi_flag)
-		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
-
 	/*
 	 * Register IRQ
 	 */
@@ -4417,9 +4453,8 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev)
 	/* cancel the delayed work if this work still in queue*/
 	if (instance->ev != NULL) {
 		struct megasas_aen_event *ev = instance->ev;
-		cancel_delayed_work(
+		cancel_delayed_work_sync(
 			(struct delayed_work *)&ev->hotplug_work);
-		flush_scheduled_work();
 		instance->ev = NULL;
 	}
 
@@ -4611,6 +4646,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance,
 	 * For each user buffer, create a mirror buffer and copy in
 	 */
 	for (i = 0; i < ioc->sge_count; i++) {
+		if (!ioc->sgl[i].iov_len)
+			continue;
+
 		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
 						    ioc->sgl[i].iov_len,
 						    &buf_handle, GFP_KERNEL);
@@ -5177,6 +5215,7 @@ megasas_aen_polling(struct work_struct *work)
 			break;
 
 		case MR_EVT_LD_OFFLINE:
+		case MR_EVT_CFG_CLEARED:
 		case MR_EVT_LD_DELETED:
 			megasas_get_ld_list(instance);
 			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index 53fa96a..8fe3a45 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -39,7 +39,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index c1e09d5..145a8cf 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -38,7 +38,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
@@ -82,6 +81,10 @@ u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
 struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
 
 u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+
+void
+megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
+
 u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
 		      struct LD_LOAD_BALANCE_INFO *lbInfo);
 u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
@@ -984,13 +987,15 @@ megasas_init_adapter_fusion(struct megasas_instance *instance)
 
 	return 0;
 
-fail_alloc_cmds:
-fail_alloc_mfi_cmds:
 fail_map_info:
 	if (i == 1)
 		dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
 				  fusion->ld_map[0], fusion->ld_map_phys[0]);
 fail_ioc_init:
+	megasas_free_cmds_fusion(instance);
+fail_alloc_cmds:
+	megasas_free_cmds(instance);
+fail_alloc_mfi_cmds:
 	return 1;
 }
 
@@ -1432,8 +1437,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
 	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
 
 	/* Check if this is a system PD I/O */
-	if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
-	    (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
+	if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
 		io_request->Function = 0;
 		io_request->DevHandle =
 			local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
@@ -1456,7 +1460,7 @@ megasas_build_dcdb_fusion(struct megasas_instance *instance,
 			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
 	}
 	io_request->RaidContext.VirtualDiskTgtId = device_id;
-	io_request->LUN[0] = scmd->device->lun;
+	io_request->LUN[1] = scmd->device->lun;
 	io_request->DataLength = scsi_bufflen(scmd);
 }
 
@@ -1480,7 +1484,7 @@ megasas_build_io_fusion(struct megasas_instance *instance,
 	device_id = MEGASAS_DEV_INDEX(instance, scp);
 
 	/* Zero out some fields so they don't get reused */
-	io_request->LUN[0] = 0;
+	io_request->LUN[1] = 0;
 	io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
 	io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
 	io_request->EEDPFlags = 0;
@@ -1744,7 +1748,7 @@ complete_cmd_fusion(struct megasas_instance *instance)
 	wmb();
 	writel(fusion->last_reply_idx,
 	       &instance->reg_set->reply_post_host_index);
-
+	megasas_check_and_restore_queue_depth(instance);
 	return IRQ_HANDLED;
 }
 
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
index 8be75e6..a3e6038 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -8,7 +8,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.16
+ *  mpi2.h Version:  02.00.17
  *
  *  Version History
  *  ---------------
@@ -63,6 +63,7 @@
  *                      function codes, 0xF0 to 0xFF.
  *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
  *                      Added alternative defines for the SGE Direction bit.
+ *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
  */
 
@@ -88,7 +89,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x10)
+#define MPI2_HEADER_VERSION_UNIT            (0x11)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
index d76a658..f5b9c76 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.15
+ *    mpi2_cnfg.h Version:  02.00.16
  *
  *  Version History
  *  ---------------
@@ -125,6 +125,8 @@
  *                      define.
  *                      Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
  *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
+ *  08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
+ *                      defines.
  *  --------------------------------------------------------------------------
  */
 
@@ -745,8 +747,6 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
 #define MPI2_IOUNITPAGE1_DISABLE_IR                     (0x00000040)
 #define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
 #define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID        (0x00000004)
-#define MPI2_IOUNITPAGE1_MULTI_PATHING                  (0x00000002)
-#define MPI2_IOUNITPAGE1_SINGLE_PATHING                 (0x00000000)
 
 
 /* IO Unit Page 3 */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
deleted file mode 100644
index b1e88f2..0000000
--- a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
+++ /dev/null
@@ -1,384 +0,0 @@
- ==============================
- Fusion-MPT MPI 2.0 Header File Change History
- ==============================
-
- Copyright (c) 2000-2010 LSI Corporation.
-
- ---------------------------------------
- Header Set Release Version:    02.00.14
- Header Set Release Date:       10-28-09
- ---------------------------------------
-
- Filename               Current version     Prior version
- ----------             ---------------     -------------
- mpi2.h                 02.00.14            02.00.13
- mpi2_cnfg.h            02.00.13            02.00.12
- mpi2_init.h            02.00.08            02.00.07
- mpi2_ioc.h             02.00.13            02.00.12
- mpi2_raid.h            02.00.04            02.00.04
- mpi2_sas.h             02.00.03            02.00.02
- mpi2_targ.h            02.00.03            02.00.03
- mpi2_tool.h            02.00.04            02.00.04
- mpi2_type.h            02.00.00            02.00.00
- mpi2_ra.h              02.00.00            02.00.00
- mpi2_hbd.h             02.00.00
- mpi2_history.txt       02.00.14            02.00.13
-
-
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
-
-mpi2.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-04-07  02.00.01  Bumped MPI2_HEADER_VERSION_UNIT.
- *  06-26-07  02.00.02  Bumped MPI2_HEADER_VERSION_UNIT.
- *  08-31-07  02.00.03  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Moved ReplyPostHostIndex register to offset 0x6C of the
- *                      MPI2_SYSTEM_INTERFACE_REGS and modified the define for
- *                      MPI2_REPLY_POST_HOST_INDEX_OFFSET.
- *                      Added union of request descriptors.
- *                      Added union of reply descriptors.
- *  10-31-07  02.00.04  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added define for MPI2_VERSION_02_00.
- *                      Fixed the size of the FunctionDependent5 field in the
- *                      MPI2_DEFAULT_REPLY structure.
- *  12-18-07  02.00.05  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Removed the MPI-defined Fault Codes and extended the
- *                      product specific codes up to 0xEFFF.
- *                      Added a sixth key value for the WriteSequence register
- *                      and changed the flush value to 0x0.
- *                      Added message function codes for Diagnostic Buffer Post
- *                      and Diagnsotic Release.
- *                      New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
- *                      Moved MPI2_VERSION_UNION from mpi2_ioc.h.
- *  02-29-08  02.00.06  Bumped MPI2_HEADER_VERSION_UNIT.
- *  03-03-08  02.00.07  Bumped MPI2_HEADER_VERSION_UNIT.
- *  05-21-08  02.00.08  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added #defines for marking a reply descriptor as unused.
- *  06-27-08  02.00.09  Bumped MPI2_HEADER_VERSION_UNIT.
- *  10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Moved LUN field defines from mpi2_init.h.
- *  01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
- *  05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      In all request and reply descriptors, replaced VF_ID
- *                      field with MSIxIndex field.
- *                      Removed DevHandle field from
- *                      MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
- *                      bytes reserved.
- *                      Added RAID Accelerator functionality.
- *  07-30-09  02.00.13  Bumped MPI2_HEADER_VERSION_UNIT.
- *  10-28-09  02.00.14  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added MSI-x index mask and shift for Reply Post Host
- *                      Index register.
- *                      Added function code for Host Based Discovery Action.
- *  --------------------------------------------------------------------------
-
-mpi2_cnfg.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-04-07  02.00.01  Added defines for SAS IO Unit Page 2 PhyFlags.
- *                      Added Manufacturing Page 11.
- *                      Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
- *                      define.
- *  06-26-07  02.00.02  Adding generic structure for product-specific
- *                      Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
- *                      Rework of BIOS Page 2 configuration page.
- *                      Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
- *                      forms.
- *                      Added configuration pages IOC Page 8 and Driver
- *                      Persistent Mapping Page 0.
- *  08-31-07  02.00.03  Modified configuration pages dealing with Integrated
- *                      RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
- *                      RAID Physical Disk Pages 0 and 1, RAID Configuration
- *                      Page 0).
- *                      Added new value for AccessStatus field of SAS Device
- *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
- *  10-31-07  02.00.04  Added missing SEPDevHandle field to
- *                      MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- *  12-18-07  02.00.05  Modified IO Unit Page 0 to use 32-bit version fields for
- *                      NVDATA.
- *                      Modified IOC Page 7 to use masks and added field for
- *                      SASBroadcastPrimitiveMasks.
- *                      Added MPI2_CONFIG_PAGE_BIOS_4.
- *                      Added MPI2_CONFIG_PAGE_LOG_0.
- *  02-29-08  02.00.06  Modified various names to make them 32-character unique.
- *                      Added SAS Device IDs.
- *                      Updated Integrated RAID configuration pages including
- *                      Manufacturing Page 4, IOC Page 6, and RAID Configuration
- *                      Page 0.
- *  05-21-08  02.00.07  Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
- *                      Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
- *                      Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
- *                      Added missing MaxNumRoutedSasAddresses field to
- *                      MPI2_CONFIG_PAGE_EXPANDER_0.
- *                      Added SAS Port Page 0.
- *                      Modified structure layout for
- *                      MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
- *  06-27-08  02.00.08  Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
- *                      MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
- *  10-02-08  02.00.09  Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
- *                      to 0x000000FF.
- *                      Added two new values for the Physical Disk Coercion Size
- *                      bits in the Flags field of Manufacturing Page 4.
- *                      Added product-specific Manufacturing pages 16 to 31.
- *                      Modified Flags bits for controlling write cache on SATA
- *                      drives in IO Unit Page 1.
- *                      Added new bit to AdditionalControlFlags of SAS IO Unit
- *                      Page 1 to control Invalid Topology Correction.
- *                      Added SupportedPhysDisks field to RAID Volume Page 1 and
- *                      added related defines.
- *                      Added additional defines for RAID Volume Page 0
- *                      VolumeStatusFlags field.
- *                      Modified meaning of RAID Volume Page 0 VolumeSettings
- *                      define for auto-configure of hot-swap drives.
- *                      Added PhysDiskAttributes field (and related defines) to
- *                      RAID Physical Disk Page 0.
- *                      Added MPI2_SAS_PHYINFO_PHY_VACANT define.
- *                      Added three new DiscoveryStatus bits for SAS IO Unit
- *                      Page 0 and SAS Expander Page 0.
- *                      Removed multiplexing information from SAS IO Unit pages.
- *                      Added BootDeviceWaitTime field to SAS IO Unit Page 4.
- *                      Removed Zone Address Resolved bit from PhyInfo and from
- *                      Expander Page 0 Flags field.
- *                      Added two new AccessStatus values to SAS Device Page 0
- *                      for indicating routing problems. Added 3 reserved words
- *                      to this page.
- *  01-19-09  02.00.10  Fixed defines for GPIOVal field of IO Unit Page 3.
- *                      Inserted missing reserved field into structure for IOC
- *                      Page 6.
- *                      Added more pending task bits to RAID Volume Page 0
- *                      VolumeStatusFlags defines.
- *                      Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
- *                      Added a new DiscoveryStatus bit for SAS IO Unit Page 0
- *                      and SAS Expander Page 0 to flag a downstream initiator
- *                      when in simplified routing mode.
- *                      Removed SATA Init Failure defines for DiscoveryStatus
- *                      fields of SAS IO Unit Page 0 and SAS Expander Page 0.
- *                      Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
- *                      Added PortGroups, DmaGroup, and ControlGroup fields to
- *                      SAS Device Page 0.
- *  05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
- *                      Unit Page 6.
- *                      Added expander reduced functionality data to SAS
- *                      Expander Page 0.
- *                      Added SAS PHY Page 2 and SAS PHY Page 3.
- *  07-30-09  02.00.12  Added IO Unit Page 7.
- *                      Added new device ids.
- *                      Added SAS IO Unit Page 5.
- *                      Added partial and slumber power management capable flags
- *                      to SAS Device Page 0 Flags field.
- *                      Added PhyInfo defines for power condition.
- *                      Added Ethernet configuration pages.
- *  10-28-09  02.00.13  Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
- *                      Added SAS PHY Page 4 structure and defines.
- *  --------------------------------------------------------------------------
-
-mpi2_init.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  10-31-07  02.00.01  Fixed name for pMpi2SCSITaskManagementRequest_t.
- *  12-18-07  02.00.02  Modified Task Management Target Reset Method defines.
- *  02-29-08  02.00.03  Added Query Task Set and Query Unit Attention.
- *  03-03-08  02.00.04  Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
- *  05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
- *  10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
- *                      Control field Task Attribute flags.
- *                      Moved LUN field defines to mpi2.h becasue they are
- *                      common to many structures.
- *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
- *                      Query Asynchronous Event.
- *                      Defined two new bits in the SlotStatus field of the SCSI
- *                      Enclosure Processor Request and Reply.
- *  10-28-09  02.00.08  Added defines for decoding the ResponseInfo bytes for
- *                      both SCSI IO Error Reply and SCSI Task Management Reply.
- *                      Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
- *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
- *  --------------------------------------------------------------------------
-
-mpi2_ioc.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-04-07  02.00.01  In IOCFacts Reply structure, renamed MaxDevices to
- *                      MaxTargets.
- *                      Added TotalImageSize field to FWDownload Request.
- *                      Added reserved words to FWUpload Request.
- *  06-26-07  02.00.02  Added IR Configuration Change List Event.
- *  08-31-07  02.00.03  Removed SystemReplyQueueDepth field from the IOCInit
- *                      request and replaced it with
- *                      ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
- *                      Replaced the MinReplyQueueDepth field of the IOCFacts
- *                      reply with MaxReplyDescriptorPostQueueDepth.
- *                      Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
- *                      depth for the Reply Descriptor Post Queue.
- *                      Added SASAddress field to Initiator Device Table
- *                      Overflow Event data.
- *  10-31-07  02.00.04  Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
- *                      for SAS Initiator Device Status Change Event data.
- *                      Modified Reason Code defines for SAS Topology Change
- *                      List Event data, including adding a bit for PHY Vacant
- *                      status, and adding a mask for the Reason Code.
- *                      Added define for
- *                      MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
- *                      Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
- *  12-18-07  02.00.05  Added Boot Status defines for the IOCExceptions field of
- *                      the IOCFacts Reply.
- *                      Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- *                      Moved MPI2_VERSION_UNION to mpi2.h.
- *                      Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
- *                      instead of enables, and added SASBroadcastPrimitiveMasks
- *                      field.
- *                      Added Log Entry Added Event and related structure.
- *  02-29-08  02.00.06  Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
- *                      Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
- *                      Added MaxVolumes and MaxPersistentEntries fields to
- *                      IOCFacts reply.
- *                      Added ProtocalFlags and IOCCapabilities fields to
- *                      MPI2_FW_IMAGE_HEADER.
- *                      Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
- *  03-03-08  02.00.07  Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
- *                      a U16 (from a U32).
- *                      Removed extra 's' from EventMasks name.
- *  06-27-08  02.00.08  Fixed an offset in a comment.
- *  10-02-08  02.00.09  Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
- *                      Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
- *                      renamed MinReplyFrameSize to ReplyFrameSize.
- *                      Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
- *                      Added two new RAIDOperation values for Integrated RAID
- *                      Operations Status Event data.
- *                      Added four new IR Configuration Change List Event data
- *                      ReasonCode values.
- *                      Added two new ReasonCode defines for SAS Device Status
- *                      Change Event data.
- *                      Added three new DiscoveryStatus bits for the SAS
- *                      Discovery event data.
- *                      Added Multiplexing Status Change bit to the PhyStatus
- *                      field of the SAS Topology Change List event data.
- *                      Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
- *                      BootFlags are now product-specific.
- *                      Added defines for the indivdual signature bytes
- *                      for MPI2_INIT_IMAGE_FOOTER.
- *  01-19-09  02.00.10  Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
- *                      Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
- *                      define.
- *                      Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
- *                      define.
- *                      Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
- *  05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
- *                      Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
- *                      Added two new reason codes for SAS Device Status Change
- *                      Event.
- *                      Added new event: SAS PHY Counter.
- *  07-30-09  02.00.12  Added GPIO Interrupt event define and structure.
- *                      Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- *                      Added new product id family for 2208.
- *  10-28-09  02.00.13  Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
- *                      Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
- *                      Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
- *                      Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
- *                      Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
- *                      Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
- *                      Added Host Based Discovery Phy Event data.
- *                      Added defines for ProductID Product field
- *                      (MPI2_FW_HEADER_PID_).
- *                      Modified values for SAS ProductID Family
- *                      (MPI2_FW_HEADER_PID_FAMILY_).
- *  --------------------------------------------------------------------------
-
-mpi2_raid.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  08-31-07  02.00.01  Modifications to RAID Action request and reply,
- *                      including the Actions and ActionData.
- *  02-29-08  02.00.02  Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
- *  05-21-08  02.00.03  Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
- *                      the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
- *                      can be sized by the build environment.
- *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
- *                      VolumeCreationFlags and marked the old one as obsolete.
- *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
- *  --------------------------------------------------------------------------
-
-mpi2_sas.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-26-07  02.00.01  Added Clear All Persistent Operation to SAS IO Unit
- *                      Control Request.
- *  10-02-08  02.00.02  Added Set IOC Parameter Operation to SAS IO Unit Control
- *                      Request.
- *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
- *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
- *  05-12-10  02.00.04  Modified some comments.
- *  --------------------------------------------------------------------------
-
-mpi2_targ.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  08-31-07  02.00.01  Added Command Buffer Data Location Address Space bits to
- *                      BufferPostFlags field of CommandBufferPostBase Request.
- *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
- *  10-02-08  02.00.03  Removed NextCmdBufferOffset from
- *                      MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST.
- *                      Target Status Send Request only takes a single SGE for
- *                      response data.
- *  --------------------------------------------------------------------------
-
-mpi2_tool.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
- *                      structures and defines.
- *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
- *  05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
- *  07-30-09  02.00.04  Added ExtendedType field to DiagnosticBufferPost request
- *                      and reply messages.
- *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
- *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
- *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
- *  --------------------------------------------------------------------------
-
-mpi2_type.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  --------------------------------------------------------------------------
-
-mpi2_ra.h
- *  05-06-09  02.00.00  Initial version.
- *  --------------------------------------------------------------------------
-
-mpi2_hbd.h
- *  10-28-09  02.00.00  Initial version.
- *  --------------------------------------------------------------------------
-
-
-mpi2_history.txt         Parts list history
-
-Filename     02.00.14  02.00.13  02.00.12
-----------   --------  --------  --------
-mpi2.h       02.00.14  02.00.13  02.00.12
-mpi2_cnfg.h  02.00.13  02.00.12  02.00.11
-mpi2_init.h  02.00.08  02.00.07  02.00.07
-mpi2_ioc.h   02.00.13  02.00.12  02.00.11
-mpi2_raid.h  02.00.04  02.00.04  02.00.03
-mpi2_sas.h   02.00.03  02.00.02  02.00.02
-mpi2_targ.h  02.00.03  02.00.03  02.00.03
-mpi2_tool.h  02.00.04  02.00.04  02.00.03
-mpi2_type.h  02.00.00  02.00.00  02.00.00
-mpi2_ra.h    02.00.00  02.00.00  02.00.00
-mpi2_hbd.h   02.00.00
-
-Filename     02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
-----------   --------  --------  --------  --------  --------  --------
-mpi2.h       02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
-mpi2_cnfg.h  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06  02.00.06
-mpi2_init.h  02.00.06  02.00.06  02.00.05  02.00.05  02.00.04  02.00.03
-mpi2_ioc.h   02.00.10  02.00.09  02.00.08  02.00.07  02.00.07  02.00.06
-mpi2_raid.h  02.00.03  02.00.03  02.00.03  02.00.03  02.00.02  02.00.02
-mpi2_sas.h   02.00.02  02.00.02  02.00.01  02.00.01  02.00.01  02.00.01
-mpi2_targ.h  02.00.03  02.00.03  02.00.02  02.00.02  02.00.02  02.00.02
-mpi2_tool.h  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02
-mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
-
-Filename     02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-----------   --------  --------  --------  --------  --------  --------
-mpi2.h       02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-mpi2_cnfg.h  02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-mpi2_init.h  02.00.02  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00
-mpi2_ioc.h   02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-mpi2_raid.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
-mpi2_sas.h   02.00.01  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00
-mpi2_targ.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
-mpi2_tool.h  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
-mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
-
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
index 608f6d6..fdffde1 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
@@ -6,7 +6,7 @@
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  February 9, 2007
  *
- *  mpi2_sas.h Version:  02.00.04
+ *  mpi2_sas.h Version:  02.00.05
  *
  *  Version History
  *  ---------------
@@ -21,6 +21,7 @@
  *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
  *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
  *  05-12-10  02.00.04  Modified some comments.
+ *  08-11-10  02.00.05  Added NCQ operations to SAS IO Unit Control.
  *  --------------------------------------------------------------------------
  */
 
@@ -163,7 +164,7 @@ typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
     U32                     Reserved4;          /* 0x14 */
     U32                     DataLength;         /* 0x18 */
     U8                      CommandFIS[20];     /* 0x1C */
-    MPI2_SGE_IO_UNION       SGL;                /* 0x20 */
+    MPI2_SGE_IO_UNION       SGL;                /* 0x30 */
 } MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
   Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
 
@@ -246,6 +247,8 @@ typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
 #define MPI2_SAS_OP_REMOVE_DEVICE               (0x0D)
 #define MPI2_SAS_OP_LOOKUP_MAPPING              (0x0E)
 #define MPI2_SAS_OP_SET_IOC_PARAMETER           (0x0F)
+#define MPI2_SAS_OP_DEV_ENABLE_NCQ              (0x14)
+#define MPI2_SAS_OP_DEV_DISABLE_NCQ             (0x15)
 #define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN        (0x80)
 
 /* values for the PrimFlags field */
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
index 5c6e3a6..2a4bced 100644
--- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
@@ -6,7 +6,7 @@
  *          Title:  MPI diagnostic tool structures and definitions
  *  Creation Date:  March 26, 2007
  *
- *    mpi2_tool.h Version:  02.00.05
+ *    mpi2_tool.h Version:  02.00.06
  *
  *  Version History
  *  ---------------
@@ -23,6 +23,8 @@
  *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
  *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
  *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
+ *  08-11-10  02.00.06  Added defines that were missing for Diagnostic Buffer
+ *                      Post Request.
  *  --------------------------------------------------------------------------
  */
 
@@ -354,6 +356,10 @@ typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST
 /* count of the number of buffer types */
 #define MPI2_DIAG_BUF_TYPE_COUNT                    (0x03)
 
+/* values for the Flags field */
+#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL          (0x00000002)
+#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE        (0x00000001)
+
 
 /****************************************************************************
 *  Diagnostic Buffer Post reply
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 9ead039..e8a6f1c 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -752,20 +752,19 @@ static u8
 _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
 	int i;
-	u8 cb_idx = 0xFF;
-
-	if (smid >= ioc->hi_priority_smid) {
-		if (smid < ioc->internal_smid) {
-			i = smid - ioc->hi_priority_smid;
-			cb_idx = ioc->hpr_lookup[i].cb_idx;
-		} else if (smid <= ioc->hba_queue_depth)  {
-			i = smid - ioc->internal_smid;
-			cb_idx = ioc->internal_lookup[i].cb_idx;
-		}
-	} else {
+	u8 cb_idx;
+
+	if (smid < ioc->hi_priority_smid) {
 		i = smid - 1;
 		cb_idx = ioc->scsi_lookup[i].cb_idx;
-	}
+	} else if (smid < ioc->internal_smid) {
+		i = smid - ioc->hi_priority_smid;
+		cb_idx = ioc->hpr_lookup[i].cb_idx;
+	} else if (smid <= ioc->hba_queue_depth) {
+		i = smid - ioc->internal_smid;
+		cb_idx = ioc->internal_lookup[i].cb_idx;
+	} else
+		cb_idx = 0xFF;
 	return cb_idx;
 }
 
@@ -1430,7 +1429,7 @@ mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
     struct scsi_cmnd *scmd)
 {
 	unsigned long flags;
-	struct request_tracker *request;
+	struct scsiio_tracker *request;
 	u16 smid;
 
 	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
@@ -1442,7 +1441,7 @@ mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx,
 	}
 
 	request = list_entry(ioc->free_list.next,
-	    struct request_tracker, tracker_list);
+	    struct scsiio_tracker, tracker_list);
 	request->scmd = scmd;
 	request->cb_idx = cb_idx;
 	smid = request->smid;
@@ -1496,48 +1495,47 @@ mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 	struct chain_tracker *chain_req, *next;
 
 	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-	if (smid >= ioc->hi_priority_smid) {
-		if (smid < ioc->internal_smid) {
-			/* hi-priority */
-			i = smid - ioc->hi_priority_smid;
-			ioc->hpr_lookup[i].cb_idx = 0xFF;
-			list_add_tail(&ioc->hpr_lookup[i].tracker_list,
-			    &ioc->hpr_free_list);
-		} else {
-			/* internal queue */
-			i = smid - ioc->internal_smid;
-			ioc->internal_lookup[i].cb_idx = 0xFF;
-			list_add_tail(&ioc->internal_lookup[i].tracker_list,
-			    &ioc->internal_free_list);
+	if (smid < ioc->hi_priority_smid) {
+		/* scsiio queue */
+		i = smid - 1;
+		if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
+			list_for_each_entry_safe(chain_req, next,
+			    &ioc->scsi_lookup[i].chain_list, tracker_list) {
+				list_del_init(&chain_req->tracker_list);
+				list_add_tail(&chain_req->tracker_list,
+				    &ioc->free_chain_list);
+			}
 		}
+		ioc->scsi_lookup[i].cb_idx = 0xFF;
+		ioc->scsi_lookup[i].scmd = NULL;
+		list_add_tail(&ioc->scsi_lookup[i].tracker_list,
+		    &ioc->free_list);
 		spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-		return;
-	}
 
-	/* scsiio queue */
-	i = smid - 1;
-	if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
-		list_for_each_entry_safe(chain_req, next,
-		    &ioc->scsi_lookup[i].chain_list, tracker_list) {
-			list_del_init(&chain_req->tracker_list);
-			list_add_tail(&chain_req->tracker_list,
-			    &ioc->free_chain_list);
+		/*
+		 * See _wait_for_commands_to_complete() call with regards
+		 * to this code.
+		 */
+		if (ioc->shost_recovery && ioc->pending_io_count) {
+			if (ioc->pending_io_count == 1)
+				wake_up(&ioc->reset_wq);
+			ioc->pending_io_count--;
 		}
+		return;
+	} else if (smid < ioc->internal_smid) {
+		/* hi-priority */
+		i = smid - ioc->hi_priority_smid;
+		ioc->hpr_lookup[i].cb_idx = 0xFF;
+		list_add_tail(&ioc->hpr_lookup[i].tracker_list,
+		    &ioc->hpr_free_list);
+	} else if (smid <= ioc->hba_queue_depth) {
+		/* internal queue */
+		i = smid - ioc->internal_smid;
+		ioc->internal_lookup[i].cb_idx = 0xFF;
+		list_add_tail(&ioc->internal_lookup[i].tracker_list,
+		    &ioc->internal_free_list);
 	}
-	ioc->scsi_lookup[i].cb_idx = 0xFF;
-	ioc->scsi_lookup[i].scmd = NULL;
-	list_add_tail(&ioc->scsi_lookup[i].tracker_list,
-	    &ioc->free_list);
 	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
-	/*
-	 * See _wait_for_commands_to_complete() call with regards to this code.
-	 */
-	if (ioc->shost_recovery && ioc->pending_io_count) {
-		if (ioc->pending_io_count == 1)
-			wake_up(&ioc->reset_wq);
-		ioc->pending_io_count--;
-	}
 }
 
 /**
@@ -1725,6 +1723,31 @@ _base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
 }
 
 /**
+ * _base_display_intel_branding - Display branding string
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
+{
+	if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_INTEL &&
+	    ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008) {
+
+		switch (ioc->pdev->subsystem_device) {
+		case MPT2SAS_INTEL_RMS2LL080_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_INTEL_RMS2LL080_BRANDING);
+			break;
+		case MPT2SAS_INTEL_RMS2LL040_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_INTEL_RMS2LL040_BRANDING);
+			break;
+		}
+	}
+}
+
+/**
  * _base_display_ioc_capabilities - Disply IOC's capabilities.
  * @ioc: per adapter object
  *
@@ -1754,6 +1777,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
 	    ioc->bios_pg3.BiosVersion & 0x000000FF);
 
 	_base_display_dell_branding(ioc);
+	_base_display_intel_branding(ioc);
 
 	printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
 
@@ -2252,9 +2276,9 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
 	    ioc->name, (unsigned long long) ioc->request_dma));
 	total_sz += sz;
 
-	sz = ioc->scsiio_depth * sizeof(struct request_tracker);
+	sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
 	ioc->scsi_lookup_pages = get_order(sz);
-	ioc->scsi_lookup = (struct request_tracker *)__get_free_pages(
+	ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
 	    GFP_KERNEL, ioc->scsi_lookup_pages);
 	if (!ioc->scsi_lookup) {
 		printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, "
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 283568c..a3f8aa9 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -69,8 +69,8 @@
 #define MPT2SAS_DRIVER_NAME		"mpt2sas"
 #define MPT2SAS_AUTHOR	"LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION	"LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION		"07.100.00.00"
-#define MPT2SAS_MAJOR_VERSION		07
+#define MPT2SAS_DRIVER_VERSION		"08.100.00.00"
+#define MPT2SAS_MAJOR_VERSION		08
 #define MPT2SAS_MINOR_VERSION		100
 #define MPT2SAS_BUILD_VERSION		00
 #define MPT2SAS_RELEASE_VERSION		00
@@ -101,7 +101,8 @@
 #define MPT_NAME_LENGTH			32	/* generic length of strings */
 #define MPT_STRING_LENGTH		64
 
-#define	MPT_MAX_CALLBACKS		16
+#define MPT_MAX_CALLBACKS		16
+
 
 #define	 CAN_SLEEP			1
 #define  NO_SLEEP			0
@@ -154,6 +155,20 @@
 #define MPT2SAS_DELL_6GBPS_SAS_SSDID               0x1F22
 
 /*
+ * Intel HBA branding
+ */
+#define MPT2SAS_INTEL_RMS2LL080_BRANDING	\
+				"Intel Integrated RAID Module RMS2LL080"
+#define MPT2SAS_INTEL_RMS2LL040_BRANDING	\
+				"Intel Integrated RAID Module RMS2LL040"
+
+/*
+ * Intel HBA SSDIDs
+ */
+#define MPT2SAS_INTEL_RMS2LL080_SSDID          0x350E
+#define MPT2SAS_INTEL_RMS2LL040_SSDID          0x350F
+
+/*
  * per target private data
  */
 #define MPT_TARGET_FLAGS_RAID_COMPONENT	0x01
@@ -431,14 +446,14 @@ struct chain_tracker {
 };
 
 /**
- * struct request_tracker - firmware request tracker
+ * struct scsiio_tracker - scsi mf request tracker
  * @smid: system message id
  * @scmd: scsi request pointer
  * @cb_idx: callback index
  * @chain_list: list of chains associated to this IO
  * @tracker_list: list of free request (ioc->free_list)
  */
-struct request_tracker {
+struct scsiio_tracker {
 	u16	smid;
 	struct scsi_cmnd *scmd;
 	u8	cb_idx;
@@ -447,6 +462,19 @@ struct request_tracker {
 };
 
 /**
+ * struct request_tracker - misc mf request tracker
+ * @smid: system message id
+ * @scmd: scsi request pointer
+ * @cb_idx: callback index
+ * @tracker_list: list of free request (ioc->free_list)
+ */
+struct request_tracker {
+	u16	smid;
+	u8	cb_idx;
+	struct list_head tracker_list;
+};
+
+/**
  * struct _tr_list - target reset list
  * @handle: device handle
  * @state: state machine
@@ -709,7 +737,7 @@ struct MPT2SAS_ADAPTER {
 	u8		*request;
 	dma_addr_t	request_dma;
 	u32		request_dma_sz;
-	struct request_tracker *scsi_lookup;
+	struct scsiio_tracker *scsi_lookup;
 	ulong		scsi_lookup_pages;
 	spinlock_t 	scsi_lookup_lock;
 	struct list_head free_list;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 5ded3db..6ceb775 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -6975,7 +6975,6 @@ _scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 	u32 device_state;
 
 	mpt2sas_base_stop_watchdog(ioc);
-	flush_scheduled_work();
 	scsi_block_requests(shost);
 	device_state = pci_choose_state(pdev, state);
 	printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
diff --git a/drivers/scsi/mvsas/Makefile b/drivers/scsi/mvsas/Makefile
index 52ac426..ffbf759 100644
--- a/drivers/scsi/mvsas/Makefile
+++ b/drivers/scsi/mvsas/Makefile
@@ -21,9 +21,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-ifeq ($(CONFIG_SCSI_MVSAS_DEBUG),y)
-	EXTRA_CFLAGS += -DMV_DEBUG
-endif
+ccflags-$(CONFIG_SCSI_MVSAS_DEBUG) := -DMV_DEBUG
 
 obj-$(CONFIG_SCSI_MVSAS) += mvsas.o
 mvsas-y +=  mv_init.o  \
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index b37c8a3..86afb13f 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -1005,11 +1005,23 @@ int osd_req_read_sg(struct osd_request *or,
 	const struct osd_sg_entry *sglist, unsigned numentries)
 {
 	u64 len;
-	int ret = _add_sg_continuation_descriptor(or, sglist, numentries, &len);
+	u64 off;
+	int ret;
 
-	if (ret)
-		return ret;
-	osd_req_read(or, obj, 0, bio, len);
+	if (numentries > 1) {
+		off = 0;
+		ret = _add_sg_continuation_descriptor(or, sglist, numentries,
+						      &len);
+		if (ret)
+			return ret;
+	} else {
+		/* Optimize the case of single segment, read_sg is a
+		 * bidi operation.
+		 */
+		len = sglist->len;
+		off = sglist->offset;
+	}
+	osd_req_read(or, obj, off, bio, len);
 
 	return 0;
 }
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 54de1d1..521e218 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -1484,7 +1484,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst
 	int			dbg              = debugging;
 #endif
 
-	if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
+	if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
 		return (-EIO);
 
 	printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
@@ -2296,7 +2296,7 @@ static int osst_write_header(struct osst_tape * STp, struct osst_request ** aSRp
 	if (STp->raw) return 0;
 
 	if (STp->header_cache == NULL) {
-		if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
+		if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
 			printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
 			return (-ENOMEM);
 		}
@@ -2484,7 +2484,7 @@ static int __osst_analyze_headers(struct osst_tape * STp, struct osst_request **
 				   name, ppos, update_frame_cntr);
 #endif
 		if (STp->header_cache == NULL) {
-			if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
+			if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
 				printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
 				return 0;
 			}
@@ -5851,9 +5851,7 @@ static int osst_probe(struct device *dev)
 	/* if this is the first attach, build the infrastructure */
 	write_lock(&os_scsi_tapes_lock);
 	if (os_scsi_tapes == NULL) {
-		os_scsi_tapes =
-			(struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
-				   GFP_ATOMIC);
+		os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
 		if (os_scsi_tapes == NULL) {
 			write_unlock(&os_scsi_tapes_lock);
 			printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
diff --git a/drivers/scsi/pcmcia/Makefile b/drivers/scsi/pcmcia/Makefile
index eca3790..683bf14 100644
--- a/drivers/scsi/pcmcia/Makefile
+++ b/drivers/scsi/pcmcia/Makefile
@@ -1,5 +1,5 @@
 
-EXTRA_CFLAGS		+= -Idrivers/scsi
+ccflags-y		:= -Idrivers/scsi
 
 # 16-bit client drivers
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogic_cs.o
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index d8db013..18b6c55 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1382,53 +1382,50 @@ static u32 mpi_msg_consume(struct pm8001_hba_info *pm8001_ha,
 	return MPI_IO_STATUS_BUSY;
 }
 
-static void pm8001_work_queue(struct work_struct *work)
+static void pm8001_work_fn(struct work_struct *work)
 {
-	struct delayed_work *dw = container_of(work, struct delayed_work, work);
-	struct pm8001_wq *wq = container_of(dw, struct pm8001_wq, work_q);
+	struct pm8001_work *pw = container_of(work, struct pm8001_work, work);
 	struct pm8001_device *pm8001_dev;
-	struct domain_device	*dev;
+	struct domain_device *dev;
 
-	switch (wq->handler) {
+	switch (pw->handler) {
 	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	case IO_DS_IN_ERROR:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	case IO_DS_NON_OPERATIONAL:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	}
-	list_del(&wq->entry);
-	kfree(wq);
+	kfree(pw);
 }
 
 static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
 			       int handler)
 {
-	struct pm8001_wq *wq;
+	struct pm8001_work *pw;
 	int ret = 0;
 
-	wq = kmalloc(sizeof(struct pm8001_wq), GFP_ATOMIC);
-	if (wq) {
-		wq->pm8001_ha = pm8001_ha;
-		wq->data = data;
-		wq->handler = handler;
-		INIT_DELAYED_WORK(&wq->work_q, pm8001_work_queue);
-		list_add_tail(&wq->entry, &pm8001_ha->wq_list);
-		schedule_delayed_work(&wq->work_q, 0);
+	pw = kmalloc(sizeof(struct pm8001_work), GFP_ATOMIC);
+	if (pw) {
+		pw->pm8001_ha = pm8001_ha;
+		pw->data = data;
+		pw->handler = handler;
+		INIT_WORK(&pw->work, pm8001_work_fn);
+		queue_work(pm8001_wq, &pw->work);
 	} else
 		ret = -ENOMEM;
 
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index b95285f..002360d 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -51,6 +51,8 @@ static int pm8001_id;
 
 LIST_HEAD(hba_list);
 
+struct workqueue_struct *pm8001_wq;
+
 /**
  * The main structure which LLDD must register for scsi core.
  */
@@ -134,7 +136,6 @@ static void __devinit pm8001_phy_init(struct pm8001_hba_info *pm8001_ha,
 static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 {
 	int i;
-	struct pm8001_wq *wq;
 
 	if (!pm8001_ha)
 		return;
@@ -150,8 +151,7 @@ static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 	PM8001_CHIP_DISP->chip_iounmap(pm8001_ha);
 	if (pm8001_ha->shost)
 		scsi_host_put(pm8001_ha->shost);
-	list_for_each_entry(wq, &pm8001_ha->wq_list, entry)
-		cancel_delayed_work(&wq->work_q);
+	flush_workqueue(pm8001_wq);
 	kfree(pm8001_ha->tags);
 	kfree(pm8001_ha);
 }
@@ -381,7 +381,6 @@ pm8001_pci_alloc(struct pci_dev *pdev, u32 chip_id, struct Scsi_Host *shost)
 	pm8001_ha->sas = sha;
 	pm8001_ha->shost = shost;
 	pm8001_ha->id = pm8001_id++;
-	INIT_LIST_HEAD(&pm8001_ha->wq_list);
 	pm8001_ha->logging_level = 0x01;
 	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
 #ifdef PM8001_USE_TASKLET
@@ -758,7 +757,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 	int i , pos;
 	u32 device_state;
 	pm8001_ha = sha->lldd_ha;
-	flush_scheduled_work();
+	flush_workqueue(pm8001_wq);
 	scsi_block_requests(pm8001_ha->shost);
 	pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
 	if (pos == 0) {
@@ -870,17 +869,26 @@ static struct pci_driver pm8001_pci_driver = {
  */
 static int __init pm8001_init(void)
 {
-	int rc;
+	int rc = -ENOMEM;
+
+	pm8001_wq = alloc_workqueue("pm8001", 0, 0);
+	if (!pm8001_wq)
+		goto err;
+
 	pm8001_id = 0;
 	pm8001_stt = sas_domain_attach_transport(&pm8001_transport_ops);
 	if (!pm8001_stt)
-		return -ENOMEM;
+		goto err_wq;
 	rc = pci_register_driver(&pm8001_pci_driver);
 	if (rc)
-		goto err_out;
+		goto err_tp;
 	return 0;
-err_out:
+
+err_tp:
 	sas_release_transport(pm8001_stt);
+err_wq:
+	destroy_workqueue(pm8001_wq);
+err:
 	return rc;
 }
 
@@ -888,6 +896,7 @@ static void __exit pm8001_exit(void)
 {
 	pci_unregister_driver(&pm8001_pci_driver);
 	sas_release_transport(pm8001_stt);
+	destroy_workqueue(pm8001_wq);
 }
 
 module_init(pm8001_init);
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 7f064f9..bdb6b27 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -50,6 +50,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <scsi/libsas.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/sas_ata.h>
@@ -379,18 +380,16 @@ struct pm8001_hba_info {
 #ifdef PM8001_USE_TASKLET
 	struct tasklet_struct	tasklet;
 #endif
-	struct list_head 	wq_list;
 	u32			logging_level;
 	u32			fw_status;
 	const struct firmware 	*fw_image;
 };
 
-struct pm8001_wq {
-	struct delayed_work work_q;
+struct pm8001_work {
+	struct work_struct work;
 	struct pm8001_hba_info *pm8001_ha;
 	void *data;
 	int handler;
-	struct list_head entry;
 };
 
 struct pm8001_fw_image_header {
@@ -460,6 +459,9 @@ struct fw_control_ex {
 	void			*param3;
 };
 
+/* pm8001 workqueue */
+extern struct workqueue_struct *pm8001_wq;
+
 /******************** function prototype *********************/
 int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out);
 void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha);
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 321cf3a..bcf858e 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -5454,7 +5454,7 @@ static void __devexit pmcraid_remove(struct pci_dev *pdev)
 	pmcraid_shutdown(pdev);
 
 	pmcraid_disable_interrupts(pinstance, ~0);
-	flush_scheduled_work();
+	flush_work_sync(&pinstance->worker_q);
 
 	pmcraid_kill_tasklets(pinstance);
 	pmcraid_unregister_interrupt_handler(pinstance);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index ccfc8e7..6c51c0a 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2402,13 +2402,13 @@ struct qla_hw_data {
 	volatile struct {
 		uint32_t	mbox_int		:1;
 		uint32_t	mbox_busy		:1;
-
 		uint32_t	disable_risc_code_load	:1;
 		uint32_t	enable_64bit_addressing	:1;
 		uint32_t	enable_lip_reset	:1;
 		uint32_t	enable_target_reset	:1;
 		uint32_t	enable_lip_full_login	:1;
 		uint32_t	enable_led_scheme	:1;
+
 		uint32_t	msi_enabled		:1;
 		uint32_t	msix_enabled		:1;
 		uint32_t	disable_serdes		:1;
@@ -2417,6 +2417,7 @@ struct qla_hw_data {
 		uint32_t	pci_channel_io_perm_failure	:1;
 		uint32_t	fce_enabled		:1;
 		uint32_t	fac_supported		:1;
+
 		uint32_t	chip_reset_done		:1;
 		uint32_t	port0			:1;
 		uint32_t	running_gold_fw		:1;
@@ -2424,9 +2425,11 @@ struct qla_hw_data {
 		uint32_t	cpu_affinity_enabled	:1;
 		uint32_t	disable_msix_handshake	:1;
 		uint32_t	fcp_prio_enabled	:1;
-		uint32_t	fw_hung	:1;
-		uint32_t        quiesce_owner:1;
+		uint32_t	isp82xx_fw_hung:1;
+
+		uint32_t	quiesce_owner:1;
 		uint32_t	thermal_supported:1;
+		uint32_t	isp82xx_reset_hdlr_active:1;
 		/* 26 bits */
 	} flags;
 
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 89e900a..d48326e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -565,6 +565,7 @@ extern int qla82xx_mbx_intr_enable(scsi_qla_host_t *);
 extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
 extern void qla82xx_start_iocbs(srb_t *);
 extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
+extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *);
 
 /* BSG related functions */
 extern int qla24xx_bsg_request(struct fc_bsg_job *);
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 4c08392..74a91b6 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -121,8 +121,11 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 
 	rval = QLA_FUNCTION_FAILED;
 	if (ms_pkt->entry_status != 0) {
-		DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",
-		    vha->host_no, routine, ms_pkt->entry_status));
+		DEBUG2_3(printk(KERN_WARNING "scsi(%ld): %s failed, error status "
+		    "(%x) on port_id: %02x%02x%02x.\n",
+		    vha->host_no, routine, ms_pkt->entry_status,
+		    vha->d_id.b.domain, vha->d_id.b.area,
+		    vha->d_id.b.al_pa));
 	} else {
 		if (IS_FWI2_CAPABLE(ha))
 			comp_status = le16_to_cpu(
@@ -136,8 +139,10 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 			if (ct_rsp->header.response !=
 			    __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
 				DEBUG2_3(printk("scsi(%ld): %s failed, "
-				    "rejected request:\n", vha->host_no,
-				    routine));
+				    "rejected request on port_id: %02x%02x%02x\n",
+				    vha->host_no, routine,
+				    vha->d_id.b.domain, vha->d_id.b.area,
+				    vha->d_id.b.al_pa));
 				DEBUG2_3(qla2x00_dump_buffer(
 				    (uint8_t *)&ct_rsp->header,
 				    sizeof(struct ct_rsp_hdr)));
@@ -147,8 +152,10 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt,
 			break;
 		default:
 			DEBUG2_3(printk("scsi(%ld): %s failed, completion "
-			    "status (%x).\n", vha->host_no, routine,
-			    comp_status));
+			    "status (%x) on port_id: %02x%02x%02x.\n",
+			    vha->host_no, routine, comp_status,
+			    vha->d_id.b.domain, vha->d_id.b.area,
+			    vha->d_id.b.al_pa));
 			break;
 		}
 	}
@@ -1965,7 +1972,7 @@ qla2x00_gff_id(scsi_qla_host_t *vha, sw_info_t *list)
 			    "scsi(%ld): GFF_ID issue IOCB failed "
 			    "(%d).\n", vha->host_no, rval));
 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
-			       "GPN_ID") != QLA_SUCCESS) {
+			       "GFF_ID") != QLA_SUCCESS) {
 			DEBUG2_3(printk(KERN_INFO
 			    "scsi(%ld): GFF_ID IOCB status had a "
 			    "failure status code\n", vha->host_no));
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index d9479c3..8575808 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1967,7 +1967,7 @@ qla2x00_fw_ready(scsi_qla_host_t *vha)
 		} else {
 			/* Mailbox cmd failed. Timeout on min_wait. */
 			if (time_after_eq(jiffies, mtime) ||
-			    (IS_QLA82XX(ha) && ha->flags.fw_hung))
+				ha->flags.isp82xx_fw_hung)
 				break;
 		}
 
@@ -3945,8 +3945,13 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 	struct qla_hw_data *ha = vha->hw;
 	struct scsi_qla_host *vp;
 	unsigned long flags;
+	fc_port_t *fcport;
 
-	vha->flags.online = 0;
+	/* For ISP82XX, driver waits for completion of the commands.
+	 * online flag should be set.
+	 */
+	if (!IS_QLA82XX(ha))
+		vha->flags.online = 0;
 	ha->flags.chip_reset_done = 0;
 	clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 	ha->qla_stats.total_isp_aborts++;
@@ -3954,7 +3959,10 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 	qla_printk(KERN_INFO, ha,
 	    "Performing ISP error recovery - ha= %p.\n", ha);
 
-	/* Chip reset does not apply to 82XX */
+	/* For ISP82XX, reset_chip is just disabling interrupts.
+	 * Driver waits for the completion of the commands.
+	 * the interrupts need to be enabled.
+	 */
 	if (!IS_QLA82XX(ha))
 		ha->isp_ops->reset_chip(vha);
 
@@ -3980,14 +3988,31 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
 			    LOOP_DOWN_TIME);
 	}
 
+	/* Clear all async request states across all VPs. */
+	list_for_each_entry(fcport, &vha->vp_fcports, list)
+		fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+	spin_lock_irqsave(&ha->vport_slock, flags);
+	list_for_each_entry(vp, &ha->vp_list, list) {
+		atomic_inc(&vp->vref_count);
+		spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+		list_for_each_entry(fcport, &vp->vp_fcports, list)
+			fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+
+		spin_lock_irqsave(&ha->vport_slock, flags);
+		atomic_dec(&vp->vref_count);
+	}
+	spin_unlock_irqrestore(&ha->vport_slock, flags);
+
 	if (!ha->flags.eeh_busy) {
 		/* Make sure for ISP 82XX IO DMA is complete */
 		if (IS_QLA82XX(ha)) {
-			if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
-				WAIT_HOST) == QLA_SUCCESS) {
-				DEBUG2(qla_printk(KERN_INFO, ha,
-				"Done wait for pending commands\n"));
-			}
+			qla82xx_chip_reset_cleanup(vha);
+
+			/* Done waiting for pending commands.
+			 * Reset the online flag.
+			 */
+			vha->flags.online = 0;
 		}
 
 		/* Requeue all commands in outstanding command list. */
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 4c1ba62..d78d589 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -328,6 +328,7 @@ qla2x00_start_scsi(srb_t *sp)
 	struct qla_hw_data *ha;
 	struct req_que *req;
 	struct rsp_que *rsp;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -406,7 +407,22 @@ qla2x00_start_scsi(srb_t *sp)
 	cmd_pkt->lun = cpu_to_le16(sp->cmd->device->lun);
 
 	/* Update tagged queuing modifier */
-	cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_HEAD_TAG);
+			break;
+		case ORDERED_QUEUE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_ORDERED_TAG);
+			break;
+		default:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_SIMPLE_TAG);
+			break;
+		}
+	}
 
 	/* Load SCSI command packet. */
 	memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
@@ -971,6 +987,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
 	uint16_t		fcp_cmnd_len;
 	struct fcp_cmnd		*fcp_cmnd;
 	dma_addr_t		crc_ctx_dma;
+	char			tag[2];
 
 	cmd = sp->cmd;
 
@@ -1068,9 +1085,27 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt,
 	    LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
 	cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32(
 	    MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
-	fcp_cmnd->task_attribute = 0;
 	fcp_cmnd->task_management = 0;
 
+	/*
+	 * Update tagged queuing modifier if using command tag queuing
+	 */
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+		    fcp_cmnd->task_attribute = TSK_HEAD_OF_QUEUE;
+		    break;
+		case ORDERED_QUEUE_TAG:
+		    fcp_cmnd->task_attribute = TSK_ORDERED;
+		    break;
+		default:
+		    fcp_cmnd->task_attribute = 0;
+		    break;
+		}
+	} else {
+		fcp_cmnd->task_attribute = 0;
+	}
+
 	cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
 
 	DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data"
@@ -1177,6 +1212,7 @@ qla24xx_start_scsi(srb_t *sp)
 	struct scsi_cmnd *cmd = sp->cmd;
 	struct scsi_qla_host *vha = sp->fcport->vha;
 	struct qla_hw_data *ha = vha->hw;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -1260,6 +1296,18 @@ qla24xx_start_scsi(srb_t *sp)
 	int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
 	host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
+	/* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			cmd_pkt->task = TSK_HEAD_OF_QUEUE;
+			break;
+		case ORDERED_QUEUE_TAG:
+			cmd_pkt->task = TSK_ORDERED;
+			break;
+		}
+	}
+
 	/* Load SCSI command packet. */
 	memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
 	host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index e473e9f..7a7c0ec 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -71,6 +71,13 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 		return QLA_FUNCTION_TIMEOUT;
 	}
 
+	if (ha->flags.isp82xx_fw_hung) {
+		/* Setting Link-Down error */
+		mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+		rval = QLA_FUNCTION_FAILED;
+		goto premature_exit;
+	}
+
 	/*
 	 * Wait for active mailbox commands to finish by waiting at most tov
 	 * seconds. This is to serialize actual issuing of mailbox cmds during
@@ -83,13 +90,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 		return QLA_FUNCTION_TIMEOUT;
 	}
 
-	if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
-		/* Setting Link-Down error */
-		mcp->mb[0] = MBS_LINK_DOWN_ERROR;
-		rval = QLA_FUNCTION_FAILED;
-		goto premature_exit;
-	}
-
 	ha->flags.mbox_busy = 1;
 	/* Save mailbox command for debug */
 	ha->mcp = mcp;
@@ -223,7 +223,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 		ha->flags.mbox_int = 0;
 		clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
-		if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
+		if (ha->flags.isp82xx_fw_hung) {
 			ha->flags.mbox_busy = 0;
 			/* Setting Link-Down error */
 			mcp->mb[0] = MBS_LINK_DOWN_ERROR;
@@ -2462,22 +2462,19 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport,
 		    "-- completion status (%x).\n", __func__,
 		    vha->host_no, le16_to_cpu(sts->comp_status)));
 		rval = QLA_FUNCTION_FAILED;
-	} else if (!(le16_to_cpu(sts->scsi_status) &
-	    SS_RESPONSE_INFO_LEN_VALID)) {
-		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-		    "-- no response info (%x).\n", __func__, vha->host_no,
-		    le16_to_cpu(sts->scsi_status)));
-		rval = QLA_FUNCTION_FAILED;
-	} else if (le32_to_cpu(sts->rsp_data_len) < 4) {
-		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-		    "-- not enough response info (%d).\n", __func__,
-		    vha->host_no, le32_to_cpu(sts->rsp_data_len)));
-		rval = QLA_FUNCTION_FAILED;
-	} else if (sts->data[3]) {
-		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-		    "-- response (%x).\n", __func__,
-		    vha->host_no, sts->data[3]));
-		rval = QLA_FUNCTION_FAILED;
+	} else if (le16_to_cpu(sts->scsi_status) &
+	    SS_RESPONSE_INFO_LEN_VALID) {
+		if (le32_to_cpu(sts->rsp_data_len) < 4) {
+			DEBUG2_3_11(printk("%s(%ld): ignoring inconsistent "
+			    "data length -- not enough response info (%d).\n",
+			    __func__, vha->host_no,
+			    le32_to_cpu(sts->rsp_data_len)));
+		} else if (sts->data[3]) {
+			DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+			    "-- response (%x).\n", __func__,
+			    vha->host_no, sts->data[3]));
+			rval = QLA_FUNCTION_FAILED;
+		}
 	}
 
 	/* Issue marker IOCB. */
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index fdb96a3..76ec876 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -7,6 +7,7 @@
 #include "qla_def.h"
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <scsi/scsi_tcq.h>
 
 #define MASK(n)			((1ULL<<(n))-1)
 #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | \
@@ -2547,7 +2548,7 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
 			dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
 			*dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
 			*dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
-			*dsd_seg++ = dsd_list_len;
+			cmd_pkt->fcp_data_dseg_len = dsd_list_len;
 		} else {
 			*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
 			*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
@@ -2620,6 +2621,7 @@ qla82xx_start_scsi(srb_t *sp)
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req = NULL;
 	struct rsp_que *rsp = NULL;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -2770,6 +2772,22 @@ sufficient_dsds:
 		int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
 		host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
+		/*
+		 * Update tagged queuing modifier -- default is TSK_SIMPLE (0).
+		 */
+		if (scsi_populate_tag_msg(cmd, tag)) {
+			switch (tag[0]) {
+			case HEAD_OF_QUEUE_TAG:
+				ctx->fcp_cmnd->task_attribute =
+				    TSK_HEAD_OF_QUEUE;
+				break;
+			case ORDERED_QUEUE_TAG:
+				ctx->fcp_cmnd->task_attribute =
+				    TSK_ORDERED;
+				break;
+			}
+		}
+
 		/* build FCP_CMND IU */
 		memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
 		int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun);
@@ -2835,6 +2853,20 @@ sufficient_dsds:
 		host_to_fcp_swap((uint8_t *)&cmd_pkt->lun,
 			sizeof(cmd_pkt->lun));
 
+		/*
+		 * Update tagged queuing modifier -- default is TSK_SIMPLE (0).
+		 */
+		if (scsi_populate_tag_msg(cmd, tag)) {
+			switch (tag[0]) {
+			case HEAD_OF_QUEUE_TAG:
+				cmd_pkt->task = TSK_HEAD_OF_QUEUE;
+				break;
+			case ORDERED_QUEUE_TAG:
+				cmd_pkt->task = TSK_ORDERED;
+				break;
+			}
+		}
+
 		/* Load SCSI command packet. */
 		memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
 		host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
@@ -3457,46 +3489,28 @@ qla82xx_need_reset_handler(scsi_qla_host_t *vha)
 	}
 }
 
-static void
+int
 qla82xx_check_fw_alive(scsi_qla_host_t *vha)
 {
-	uint32_t fw_heartbeat_counter, halt_status;
-	struct qla_hw_data *ha = vha->hw;
+	uint32_t fw_heartbeat_counter;
+	int status = 0;
 
-	fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+	fw_heartbeat_counter = qla82xx_rd_32(vha->hw,
+		QLA82XX_PEG_ALIVE_COUNTER);
 	/* all 0xff, assume AER/EEH in progress, ignore */
 	if (fw_heartbeat_counter == 0xffffffff)
-		return;
+		return status;
 	if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
 		vha->seconds_since_last_heartbeat++;
 		/* FW not alive after 2 seconds */
 		if (vha->seconds_since_last_heartbeat == 2) {
 			vha->seconds_since_last_heartbeat = 0;
-			halt_status = qla82xx_rd_32(ha,
-				QLA82XX_PEG_HALT_STATUS1);
-			if (halt_status & HALT_STATUS_UNRECOVERABLE) {
-				set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
-			} else {
-				qla_printk(KERN_INFO, ha,
-					"scsi(%ld): %s - detect abort needed\n",
-					vha->host_no, __func__);
-				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
-			}
-			qla2xxx_wake_dpc(vha);
-			ha->flags.fw_hung = 1;
-			if (ha->flags.mbox_busy) {
-				ha->flags.mbox_int = 1;
-				DEBUG2(qla_printk(KERN_ERR, ha,
-					"Due to fw hung, doing premature "
-					"completion of mbx command\n"));
-				if (test_bit(MBX_INTR_WAIT,
-					&ha->mbx_cmd_flags))
-					complete(&ha->mbx_intr_comp);
-			}
+			status = 1;
 		}
 	} else
 		vha->seconds_since_last_heartbeat = 0;
 	vha->fw_heartbeat_counter = fw_heartbeat_counter;
+	return status;
 }
 
 /*
@@ -3557,6 +3571,8 @@ qla82xx_device_state_handler(scsi_qla_host_t *vha)
 			break;
 		case QLA82XX_DEV_NEED_RESET:
 			qla82xx_need_reset_handler(vha);
+			dev_init_timeout = jiffies +
+				(ha->nx_dev_init_timeout * HZ);
 			break;
 		case QLA82XX_DEV_NEED_QUIESCENT:
 			qla82xx_need_qsnt_handler(vha);
@@ -3596,30 +3612,18 @@ exit:
 
 void qla82xx_watchdog(scsi_qla_host_t *vha)
 {
-	uint32_t dev_state;
+	uint32_t dev_state, halt_status;
 	struct qla_hw_data *ha = vha->hw;
 
-	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-
 	/* don't poll if reset is going on */
-	if (!(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
-		test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-		test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))) {
-		if (dev_state == QLA82XX_DEV_NEED_RESET) {
+	if (!ha->flags.isp82xx_reset_hdlr_active) {
+		dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		if (dev_state == QLA82XX_DEV_NEED_RESET &&
+		    !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
 			qla_printk(KERN_WARNING, ha,
-				"%s(): Adapter reset needed!\n", __func__);
+			    "%s(): Adapter reset needed!\n", __func__);
 			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 			qla2xxx_wake_dpc(vha);
-			ha->flags.fw_hung = 1;
-			if (ha->flags.mbox_busy) {
-				ha->flags.mbox_int = 1;
-				DEBUG2(qla_printk(KERN_ERR, ha,
-					"Need reset, doing premature "
-					"completion of mbx command\n"));
-				if (test_bit(MBX_INTR_WAIT,
-					&ha->mbx_cmd_flags))
-					complete(&ha->mbx_intr_comp);
-			}
 		} else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
 			!test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
 			DEBUG(qla_printk(KERN_INFO, ha,
@@ -3629,6 +3633,31 @@ void qla82xx_watchdog(scsi_qla_host_t *vha)
 			qla2xxx_wake_dpc(vha);
 		} else {
 			qla82xx_check_fw_alive(vha);
+			if (qla82xx_check_fw_alive(vha)) {
+				halt_status = qla82xx_rd_32(ha,
+				    QLA82XX_PEG_HALT_STATUS1);
+				if (halt_status & HALT_STATUS_UNRECOVERABLE) {
+					set_bit(ISP_UNRECOVERABLE,
+					    &vha->dpc_flags);
+				} else {
+					qla_printk(KERN_INFO, ha,
+					    "scsi(%ld): %s - detect abort needed\n",
+					    vha->host_no, __func__);
+					set_bit(ISP_ABORT_NEEDED,
+					    &vha->dpc_flags);
+				}
+				qla2xxx_wake_dpc(vha);
+				ha->flags.isp82xx_fw_hung = 1;
+				if (ha->flags.mbox_busy) {
+					ha->flags.mbox_int = 1;
+					DEBUG2(qla_printk(KERN_ERR, ha,
+					    "Due to fw hung, doing premature "
+					    "completion of mbx command\n"));
+					if (test_bit(MBX_INTR_WAIT,
+					    &ha->mbx_cmd_flags))
+						complete(&ha->mbx_intr_comp);
+				}
+			}
 		}
 	}
 }
@@ -3663,6 +3692,7 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
 			"Exiting.\n", __func__, vha->host_no);
 		return QLA_SUCCESS;
 	}
+	ha->flags.isp82xx_reset_hdlr_active = 1;
 
 	qla82xx_idc_lock(ha);
 	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
@@ -3683,7 +3713,8 @@ qla82xx_abort_isp(scsi_qla_host_t *vha)
 	qla82xx_idc_unlock(ha);
 
 	if (rval == QLA_SUCCESS) {
-		ha->flags.fw_hung = 0;
+		ha->flags.isp82xx_fw_hung = 0;
+		ha->flags.isp82xx_reset_hdlr_active = 0;
 		qla82xx_restart_isp(vha);
 	}
 
@@ -3791,3 +3822,71 @@ int qla2x00_wait_for_fcoe_ctx_reset(scsi_qla_host_t *vha)
 
 	return status;
 }
+
+void
+qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
+{
+	int i;
+	unsigned long flags;
+	struct qla_hw_data *ha = vha->hw;
+
+	/* Check if 82XX firmware is alive or not
+	 * We may have arrived here from NEED_RESET
+	 * detection only
+	 */
+	if (!ha->flags.isp82xx_fw_hung) {
+		for (i = 0; i < 2; i++) {
+			msleep(1000);
+			if (qla82xx_check_fw_alive(vha)) {
+				ha->flags.isp82xx_fw_hung = 1;
+				if (ha->flags.mbox_busy) {
+					ha->flags.mbox_int = 1;
+					complete(&ha->mbx_intr_comp);
+				}
+				break;
+			}
+		}
+	}
+
+	/* Abort all commands gracefully if fw NOT hung */
+	if (!ha->flags.isp82xx_fw_hung) {
+		int cnt, que;
+		srb_t *sp;
+		struct req_que *req;
+
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		for (que = 0; que < ha->max_req_queues; que++) {
+			req = ha->req_q_map[que];
+			if (!req)
+				continue;
+			for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+				sp = req->outstanding_cmds[cnt];
+				if (sp) {
+					if (!sp->ctx ||
+					    (sp->flags & SRB_FCP_CMND_DMA_VALID)) {
+						spin_unlock_irqrestore(
+						    &ha->hardware_lock, flags);
+						if (ha->isp_ops->abort_command(sp)) {
+							qla_printk(KERN_INFO, ha,
+							    "scsi(%ld): mbx abort command failed in %s\n",
+							    vha->host_no, __func__);
+						} else {
+							qla_printk(KERN_INFO, ha,
+							    "scsi(%ld): mbx abort command success in %s\n",
+							    vha->host_no, __func__);
+						}
+						spin_lock_irqsave(&ha->hardware_lock, flags);
+					}
+				}
+			}
+		}
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		/* Wait for pending cmds (physical and virtual) to complete */
+		if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
+		    WAIT_HOST) == QLA_SUCCESS) {
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "Done wait for pending commands\n"));
+		}
+	}
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f27724d..75a966c 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -349,7 +349,7 @@ static int qla25xx_setup_mode(struct scsi_qla_host *vha)
 				"Can't create request queue\n");
 			goto fail;
 		}
-		ha->wq = create_workqueue("qla2xxx_wq");
+		ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
 		vha->req = ha->req_q_map[req];
 		options |= BIT_1;
 		for (ques = 1; ques < ha->max_rsp_queues; ques++) {
@@ -506,7 +506,7 @@ qla24xx_fw_version_str(struct scsi_qla_host *vha, char *str)
 
 static inline srb_t *
 qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
-    struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+	struct scsi_cmnd *cmd)
 {
 	srb_t *sp;
 	struct qla_hw_data *ha = vha->hw;
@@ -520,14 +520,13 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
 	sp->cmd = cmd;
 	sp->flags = 0;
 	CMD_SP(cmd) = (void *)sp;
-	cmd->scsi_done = done;
 	sp->ctx = NULL;
 
 	return sp;
 }
 
 static int
-qla2xxx_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -537,7 +536,6 @@ qla2xxx_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)
 	srb_t *sp;
 	int rval;
 
-	spin_unlock_irq(vha->host->host_lock);
 	if (ha->flags.eeh_busy) {
 		if (ha->flags.pci_channel_io_perm_failure)
 			cmd->result = DID_NO_CONNECT << 16;
@@ -569,40 +567,32 @@ qla2xxx_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)
 		goto qc24_target_busy;
 	}
 
-	sp = qla2x00_get_new_sp(base_vha, fcport, cmd, done);
+	sp = qla2x00_get_new_sp(base_vha, fcport, cmd);
 	if (!sp)
-		goto qc24_host_busy_lock;
+		goto qc24_host_busy;
 
 	rval = ha->isp_ops->start_scsi(sp);
 	if (rval != QLA_SUCCESS)
 		goto qc24_host_busy_free_sp;
 
-	spin_lock_irq(vha->host->host_lock);
-
 	return 0;
 
 qc24_host_busy_free_sp:
 	qla2x00_sp_free_dma(sp);
 	mempool_free(sp, ha->srb_mempool);
 
-qc24_host_busy_lock:
-	spin_lock_irq(vha->host->host_lock);
+qc24_host_busy:
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc24_target_busy:
-	spin_lock_irq(vha->host->host_lock);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 qc24_fail_command:
-	spin_lock_irq(vha->host->host_lock);
-	done(cmd);
+	cmd->scsi_done(cmd);
 
 	return 0;
 }
 
-static DEF_SCSI_QCMD(qla2xxx_queuecommand)
-
-
 /*
  * qla2x00_eh_wait_on_command
  *    Waits for the command to be returned by the Firmware for some
@@ -821,17 +811,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 {
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	srb_t *sp;
-	int ret = SUCCESS;
+	int ret;
 	unsigned int id, lun;
 	unsigned long flags;
 	int wait = 0;
 	struct qla_hw_data *ha = vha->hw;
 
-	fc_block_scsi_eh(cmd);
-
 	if (!CMD_SP(cmd))
 		return SUCCESS;
 
+	ret = fc_block_scsi_eh(cmd);
+	if (ret != 0)
+		return ret;
+	ret = SUCCESS;
+
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
@@ -940,11 +933,13 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
 	int err;
 
-	fc_block_scsi_eh(cmd);
-
 	if (!fcport)
 		return FAILED;
 
+	err = fc_block_scsi_eh(cmd);
+	if (err != 0)
+		return err;
+
 	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
 	    vha->host_no, cmd->device->id, cmd->device->lun, name);
 
@@ -1018,14 +1013,17 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
 	int ret = FAILED;
 	unsigned int id, lun;
 
-	fc_block_scsi_eh(cmd);
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
 	if (!fcport)
 		return ret;
 
+	ret = fc_block_scsi_eh(cmd);
+	if (ret != 0)
+		return ret;
+	ret = FAILED;
+
 	qla_printk(KERN_INFO, vha->hw,
 	    "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
 
@@ -1078,14 +1076,17 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
 	unsigned int id, lun;
 	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
-	fc_block_scsi_eh(cmd);
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
 	if (!fcport)
 		return ret;
 
+	ret = fc_block_scsi_eh(cmd);
+	if (ret != 0)
+		return ret;
+	ret = FAILED;
+
 	qla_printk(KERN_INFO, ha,
 	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
 
@@ -3805,7 +3806,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 		ha->flags.eeh_busy = 1;
 		/* For ISP82XX complete any pending mailbox cmd */
 		if (IS_QLA82XX(ha)) {
-			ha->flags.fw_hung = 1;
+			ha->flags.isp82xx_fw_hung = 1;
 			if (ha->flags.mbox_busy) {
 				ha->flags.mbox_int = 1;
 				DEBUG2(qla_printk(KERN_ERR, ha,
@@ -3945,7 +3946,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
 			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
 			    QLA82XX_DEV_READY);
 			qla82xx_idc_unlock(ha);
-			ha->flags.fw_hung = 0;
+			ha->flags.isp82xx_fw_hung = 0;
 			rval = qla82xx_restart_isp(base_vha);
 			qla82xx_idc_lock(ha);
 			/* Clear driver state register */
@@ -3958,7 +3959,7 @@ uint32_t qla82xx_error_recovery(scsi_qla_host_t *base_vha)
 		    "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
 		if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
 		    QLA82XX_DEV_READY)) {
-			ha->flags.fw_hung = 0;
+			ha->flags.isp82xx_fw_hung = 0;
 			rval = qla82xx_restart_isp(base_vha);
 			qla82xx_idc_lock(ha);
 			qla82xx_set_drv_active(base_vha);
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index cf0075a..3a260c3 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.05-k0"
+#define QLA2XXX_VERSION      "8.03.07.00"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	3
-#define QLA_DRIVER_PATCH_VER	5
+#define QLA_DRIVER_PATCH_VER	7
 #define QLA_DRIVER_BETA_VER	0
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index 6ffbe97..03e028e 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -1027,7 +1027,7 @@ void qla4xxx_process_aen(struct scsi_qla_host * ha, uint8_t process_aen)
 					((ddb_entry->default_time2wait +
 					  4) * HZ);
 
-				DEBUG2(printk("scsi%ld: ddb [%d] initate"
+				DEBUG2(printk("scsi%ld: ddb [%d] initiate"
 					      " RELOGIN after %d seconds\n",
 					      ha->host_no,
 					      ddb_entry->fw_ddb_index,
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 3fc1d25..967836e 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -812,7 +812,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
 					);
 				start_dpc++;
 				DEBUG(printk("scsi%ld:%d:%d: ddb [%d] "
-					     "initate relogin after"
+					     "initiate relogin after"
 					     " %d seconds\n",
 					     ha->host_no, ddb_entry->bus,
 					     ddb_entry->target,
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 664c957..e2d45c9 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1292,15 +1292,19 @@ static struct scsi_host_template qpti_template = {
 	.use_clustering		= ENABLE_CLUSTERING,
 };
 
-static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit qpti_sbus_probe(struct platform_device *op)
 {
-	struct scsi_host_template *tpnt = match->data;
+	struct scsi_host_template *tpnt;
 	struct device_node *dp = op->dev.of_node;
 	struct Scsi_Host *host;
 	struct qlogicpti *qpti;
 	static int nqptis;
 	const char *fcode;
 
+	if (!op->dev.of_match)
+		return -EINVAL;
+	tpnt = op->dev.of_match->data;
+
 	/* Sometimes Antares cards come up not completely
 	 * setup, and we get a report of a zero IRQ.
 	 */
@@ -1457,7 +1461,7 @@ static const struct of_device_id qpti_match[] = {
 };
 MODULE_DEVICE_TABLE(of, qpti_match);
 
-static struct of_platform_driver qpti_sbus_driver = {
+static struct platform_driver qpti_sbus_driver = {
 	.driver = {
 		.name = "qpti",
 		.owner = THIS_MODULE,
@@ -1469,12 +1473,12 @@ static struct of_platform_driver qpti_sbus_driver = {
 
 static int __init qpti_init(void)
 {
-	return of_register_platform_driver(&qpti_sbus_driver);
+	return platform_driver_register(&qpti_sbus_driver);
 }
 
 static void __exit qpti_exit(void)
 {
-	of_unregister_platform_driver(&qpti_sbus_driver);
+	platform_driver_unregister(&qpti_sbus_driver);
 }
 
 MODULE_DESCRIPTION("QlogicISP SBUS driver");
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index a6b2d72..fa5758c 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -89,32 +89,34 @@ static const char * scsi_debug_version_date = "20100324";
 /* With these defaults, this driver will make 1 host with 1 target
  * (id 0) containing 1 logical unit (lun 0). That is 1 device.
  */
+#define DEF_ATO 1
 #define DEF_DELAY   1
 #define DEF_DEV_SIZE_MB   8
-#define DEF_EVERY_NTH   0
-#define DEF_NUM_PARTS   0
-#define DEF_OPTS   0
-#define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
-#define DEF_PTYPE   0
+#define DEF_DIF 0
+#define DEF_DIX 0
 #define DEF_D_SENSE   0
-#define DEF_NO_LUN_0   0
-#define DEF_VIRTUAL_GB   0
+#define DEF_EVERY_NTH   0
 #define DEF_FAKE_RW	0
-#define DEF_VPD_USE_HOSTNO 1
-#define DEF_SECTOR_SIZE 512
-#define DEF_DIX 0
-#define DEF_DIF 0
 #define DEF_GUARD 0
-#define DEF_ATO 1
-#define DEF_PHYSBLK_EXP 0
+#define DEF_LBPU 0
+#define DEF_LBPWS 0
+#define DEF_LBPWS10 0
 #define DEF_LOWEST_ALIGNED 0
+#define DEF_NO_LUN_0   0
+#define DEF_NUM_PARTS   0
+#define DEF_OPTS   0
 #define DEF_OPT_BLKS 64
+#define DEF_PHYSBLK_EXP 0
+#define DEF_PTYPE   0
+#define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
+#define DEF_SECTOR_SIZE 512
+#define DEF_UNMAP_ALIGNMENT 0
+#define DEF_UNMAP_GRANULARITY 1
 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
 #define DEF_UNMAP_MAX_DESC 256
-#define DEF_UNMAP_GRANULARITY 1
-#define DEF_UNMAP_ALIGNMENT 0
-#define DEF_TPWS 0
-#define DEF_TPU 0
+#define DEF_VIRTUAL_GB   0
+#define DEF_VPD_USE_HOSTNO 1
+#define DEF_WRITESAME_LENGTH 0xFFFF
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -144,6 +146,7 @@ static const char * scsi_debug_version_date = "20100324";
 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
 #define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
+#define OPT_MEDIUM_ERR_NUM    10     /* number of consecutive medium errs */
 
 /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
  * or "peripheral device" addressing (value 0) */
@@ -155,36 +158,38 @@ static const char * scsi_debug_version_date = "20100324";
 #define SCSI_DEBUG_CANQUEUE  255
 
 static int scsi_debug_add_host = DEF_NUM_HOST;
+static int scsi_debug_ato = DEF_ATO;
 static int scsi_debug_delay = DEF_DELAY;
 static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
+static int scsi_debug_dif = DEF_DIF;
+static int scsi_debug_dix = DEF_DIX;
+static int scsi_debug_dsense = DEF_D_SENSE;
 static int scsi_debug_every_nth = DEF_EVERY_NTH;
+static int scsi_debug_fake_rw = DEF_FAKE_RW;
+static int scsi_debug_guard = DEF_GUARD;
+static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int scsi_debug_max_luns = DEF_MAX_LUNS;
 static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
-static int scsi_debug_num_parts = DEF_NUM_PARTS;
+static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
 static int scsi_debug_no_uld = 0;
+static int scsi_debug_num_parts = DEF_NUM_PARTS;
 static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
+static int scsi_debug_opt_blks = DEF_OPT_BLKS;
 static int scsi_debug_opts = DEF_OPTS;
-static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
+static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
 static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
-static int scsi_debug_dsense = DEF_D_SENSE;
-static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
+static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
+static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
 static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
-static int scsi_debug_fake_rw = DEF_FAKE_RW;
 static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
-static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
-static int scsi_debug_dix = DEF_DIX;
-static int scsi_debug_dif = DEF_DIF;
-static int scsi_debug_guard = DEF_GUARD;
-static int scsi_debug_ato = DEF_ATO;
-static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
-static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
-static int scsi_debug_opt_blks = DEF_OPT_BLKS;
-static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
-static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
-static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
+static unsigned int scsi_debug_lbpu = DEF_LBPU;
+static unsigned int scsi_debug_lbpws = DEF_LBPWS;
+static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
 static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
-static unsigned int scsi_debug_tpws = DEF_TPWS;
-static unsigned int scsi_debug_tpu = DEF_TPU;
+static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
+static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
+static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
+static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
 
 static int scsi_debug_cmnd_count = 0;
 
@@ -206,6 +211,11 @@ static int sdebug_sectors_per;		/* sectors per cylinder */
 
 #define SCSI_DEBUG_MAX_CMD_LEN 32
 
+static unsigned int scsi_debug_lbp(void)
+{
+	return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10;
+}
+
 struct sdebug_dev_info {
 	struct list_head dev_list;
 	unsigned char sense_buff[SDEBUG_SENSE_LEN];	/* weak nexus */
@@ -727,7 +737,7 @@ static int inquiry_evpd_b0(unsigned char * arr)
 	/* Optimal Transfer Length */
 	put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
 
-	if (scsi_debug_tpu) {
+	if (scsi_debug_lbpu) {
 		/* Maximum Unmap LBA Count */
 		put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
 
@@ -744,7 +754,10 @@ static int inquiry_evpd_b0(unsigned char * arr)
 	/* Optimal Unmap Granularity */
 	put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
 
-	return 0x3c; /* Mandatory page length for thin provisioning */
+	/* Maximum WRITE SAME Length */
+	put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
+
+	return 0x3c; /* Mandatory page length for Logical Block Provisioning */
 
 	return sizeof(vpdb0_data);
 }
@@ -767,12 +780,15 @@ static int inquiry_evpd_b2(unsigned char *arr)
 	memset(arr, 0, 0x8);
 	arr[0] = 0;			/* threshold exponent */
 
-	if (scsi_debug_tpu)
+	if (scsi_debug_lbpu)
 		arr[1] = 1 << 7;
 
-	if (scsi_debug_tpws)
+	if (scsi_debug_lbpws)
 		arr[1] |= 1 << 6;
 
+	if (scsi_debug_lbpws10)
+		arr[1] |= 1 << 5;
+
 	return 0x8;
 }
 
@@ -831,7 +847,8 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
 			arr[n++] = 0x89;  /* ATA information */
 			arr[n++] = 0xb0;  /* Block limits (SBC) */
 			arr[n++] = 0xb1;  /* Block characteristics (SBC) */
-			arr[n++] = 0xb2;  /* Thin provisioning (SBC) */
+			if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
+				arr[n++] = 0xb2;
 			arr[3] = n - 4;	  /* number of supported VPD pages */
 		} else if (0x80 == cmd[2]) { /* unit serial number */
 			arr[1] = cmd[2];	/*sanity */
@@ -879,7 +896,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
 		} else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
 			arr[1] = cmd[2];        /*sanity */
 			arr[3] = inquiry_evpd_b1(&arr[4]);
-		} else if (0xb2 == cmd[2]) { /* Thin provisioning (SBC) */
+		} else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
 			arr[1] = cmd[2];        /*sanity */
 			arr[3] = inquiry_evpd_b2(&arr[4]);
 		} else {
@@ -1053,8 +1070,8 @@ static int resp_readcap16(struct scsi_cmnd * scp,
 	arr[13] = scsi_debug_physblk_exp & 0xf;
 	arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
 
-	if (scsi_debug_tpu || scsi_debug_tpws)
-		arr[14] |= 0x80; /* TPE */
+	if (scsi_debug_lbp())
+		arr[14] |= 0x80; /* LBPME */
 
 	arr[15] = scsi_debug_lowest_aligned & 0xff;
 
@@ -1791,15 +1808,15 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
 		return ret;
 
 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
-	    (lba <= OPT_MEDIUM_ERR_ADDR) &&
+	    (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
 	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
 		/* claim unrecoverable read error */
-		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
-				0);
+		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
 		/* set info field and valid bit for fixed descriptor */
 		if (0x70 == (devip->sense_buff[0] & 0x7f)) {
 			devip->sense_buff[0] |= 0x80;	/* Valid bit */
-			ret = OPT_MEDIUM_ERR_ADDR;
+			ret = (lba < OPT_MEDIUM_ERR_ADDR)
+			      ? OPT_MEDIUM_ERR_ADDR : (int)lba;
 			devip->sense_buff[3] = (ret >> 24) & 0xff;
 			devip->sense_buff[4] = (ret >> 16) & 0xff;
 			devip->sense_buff[5] = (ret >> 8) & 0xff;
@@ -2084,6 +2101,12 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
 	if (ret)
 		return ret;
 
+	if (num > scsi_debug_write_same_length) {
+		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+				0);
+		return check_condition_result;
+	}
+
 	write_lock_irqsave(&atomic_rw, iflags);
 
 	if (unmap && scsi_debug_unmap_granularity) {
@@ -2695,37 +2718,40 @@ static int schedule_resp(struct scsi_cmnd * cmnd,
    /sys/bus/pseudo/drivers/scsi_debug directory is changed.
  */
 module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
+module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
 module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
 module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
+module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
+module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
 module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
 module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
 module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
+module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
+module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
+module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
+module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
+module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
 module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
 module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
 module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
 module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
 module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
 module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
+module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
 module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
+module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
 module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
 module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
-module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
-module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
-		   S_IRUGO | S_IWUSR);
 module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
-module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
-module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
-module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
-module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
-module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
-module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
-module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
+module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
+module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
 module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
 module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
-module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
-module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
-module_param_named(tpu, scsi_debug_tpu, int, S_IRUGO);
-module_param_named(tpws, scsi_debug_tpws, int, S_IRUGO);
+module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
+module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
+		   S_IRUGO | S_IWUSR);
+module_param_named(write_same_length, scsi_debug_write_same_length, int,
+		   S_IRUGO | S_IWUSR);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2733,36 +2759,38 @@ MODULE_LICENSE("GPL");
 MODULE_VERSION(SCSI_DEBUG_VERSION);
 
 MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
+MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
 MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
+MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
+MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
 MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
 MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
+MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
+MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
+MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
 MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
 MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))");
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
 MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
 MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
+MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
 MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
+MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
-MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
-MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
 MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
-MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
-MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
-MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
-MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
-MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
-MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
-MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
+MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
+MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
 MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
 MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
-MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
-MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
-MODULE_PARM_DESC(tpu, "enable TP, support UNMAP command (def=0)");
-MODULE_PARM_DESC(tpws, "enable TP, support WRITE SAME(16) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
+MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
+MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
 
 static char sdebug_info[256];
 
@@ -3150,7 +3178,7 @@ static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf)
 {
 	ssize_t count;
 
-	if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
+	if (!scsi_debug_lbp())
 		return scnprintf(buf, PAGE_SIZE, "0-%u\n",
 				 sdebug_store_sectors);
 
@@ -3333,8 +3361,8 @@ static int __init scsi_debug_init(void)
 		memset(dif_storep, 0xff, dif_size);
 	}
 
-	/* Thin Provisioning */
-	if (scsi_debug_tpu || scsi_debug_tpws) {
+	/* Logical Block Provisioning */
+	if (scsi_debug_lbp()) {
 		unsigned int map_bytes;
 
 		scsi_debug_unmap_max_blocks =
@@ -3664,7 +3692,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
 			errsts = resp_readcap16(SCpnt, devip);
 		else if (cmd[1] == SAI_GET_LBA_STATUS) {
 
-			if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
+			if (scsi_debug_lbp() == 0) {
 				mk_sense_buffer(devip, ILLEGAL_REQUEST,
 						INVALID_COMMAND_OPCODE, 0);
 				errsts = check_condition_result;
@@ -3775,8 +3803,10 @@ write:
 		}
 		break;
 	case WRITE_SAME_16:
+	case WRITE_SAME:
 		if (cmd[1] & 0x8) {
-			if (scsi_debug_tpws == 0) {
+			if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
+			    (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
 				mk_sense_buffer(devip, ILLEGAL_REQUEST,
 						INVALID_FIELD_IN_CDB, 0);
 				errsts = check_condition_result;
@@ -3785,8 +3815,6 @@ write:
 		}
 		if (errsts)
 			break;
-		/* fall through */
-	case WRITE_SAME:
 		errsts = check_readiness(SCpnt, 0, devip);
 		if (errsts)
 			break;
@@ -3798,7 +3826,7 @@ write:
 		if (errsts)
 			break;
 
-		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
+		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 43fad4c..82e9e5c 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -382,6 +382,91 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
 EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
 
 /**
+ * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
+ * @vendor:	vendor string
+ * @model:	model (product) string
+ * @key:	specify list to use
+ *
+ * Description:
+ * 	Remove and destroy one dev_info entry for @vendor, @model
+ * 	in list specified by @key.
+ *
+ * Returns: 0 OK, -error on failure.
+ **/
+int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
+{
+	struct scsi_dev_info_list *devinfo, *found = NULL;
+	struct scsi_dev_info_list_table *devinfo_table =
+		scsi_devinfo_lookup_by_key(key);
+
+	if (IS_ERR(devinfo_table))
+		return PTR_ERR(devinfo_table);
+
+	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
+			    dev_info_list) {
+		if (devinfo->compatible) {
+			/*
+			 * Behave like the older version of get_device_flags.
+			 */
+			size_t max;
+			/*
+			 * XXX why skip leading spaces? If an odd INQUIRY
+			 * value, that should have been part of the
+			 * scsi_static_device_list[] entry, such as "  FOO"
+			 * rather than "FOO". Since this code is already
+			 * here, and we don't know what device it is
+			 * trying to work with, leave it as-is.
+			 */
+			max = 8;	/* max length of vendor */
+			while ((max > 0) && *vendor == ' ') {
+				max--;
+				vendor++;
+			}
+			/*
+			 * XXX removing the following strlen() would be
+			 * good, using it means that for a an entry not in
+			 * the list, we scan every byte of every vendor
+			 * listed in scsi_static_device_list[], and never match
+			 * a single one (and still have to compare at
+			 * least the first byte of each vendor).
+			 */
+			if (memcmp(devinfo->vendor, vendor,
+				    min(max, strlen(devinfo->vendor))))
+				continue;
+			/*
+			 * Skip spaces again.
+			 */
+			max = 16;	/* max length of model */
+			while ((max > 0) && *model == ' ') {
+				max--;
+				model++;
+			}
+			if (memcmp(devinfo->model, model,
+				   min(max, strlen(devinfo->model))))
+				continue;
+			found = devinfo;
+		} else {
+			if (!memcmp(devinfo->vendor, vendor,
+				     sizeof(devinfo->vendor)) &&
+			     !memcmp(devinfo->model, model,
+				      sizeof(devinfo->model)))
+				found = devinfo;
+		}
+		if (found)
+			break;
+	}
+
+	if (found) {
+		list_del(&found->dev_info_list);
+		kfree(found);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
+
+/**
  * scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list.
  * @dev_list:	string of device flags to add
  *
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 45c7564..633c239 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -3,14 +3,14 @@
  *
  *  SCSI error/timeout handling
  *      Initial versions: Eric Youngdale.  Based upon conversations with
- *                        Leonard Zubkoff and David Miller at Linux Expo, 
+ *                        Leonard Zubkoff and David Miller at Linux Expo,
  *                        ideas originating from all over the place.
  *
  *	Restructured scsi_unjam_host and associated functions.
  *	September 04, 2002 Mike Anderson (andmike@us.ibm.com)
  *
  *	Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
- *	minor  cleanups.
+ *	minor cleanups.
  *	September 30, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
@@ -129,14 +129,15 @@ enum blk_eh_timer_return scsi_times_out(struct request *req)
 {
 	struct scsi_cmnd *scmd = req->special;
 	enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
+	struct Scsi_Host *host = scmd->device->host;
 
 	trace_scsi_dispatch_cmd_timeout(scmd);
 	scsi_log_completion(scmd, TIMEOUT_ERROR);
 
-	if (scmd->device->host->transportt->eh_timed_out)
-		rtn = scmd->device->host->transportt->eh_timed_out(scmd);
-	else if (scmd->device->host->hostt->eh_timed_out)
-		rtn = scmd->device->host->hostt->eh_timed_out(scmd);
+	if (host->transportt->eh_timed_out)
+		rtn = host->transportt->eh_timed_out(scmd);
+	else if (host->hostt->eh_timed_out)
+		rtn = host->hostt->eh_timed_out(scmd);
 
 	if (unlikely(rtn == BLK_EH_NOT_HANDLED &&
 		     !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
@@ -195,7 +196,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
 				++total_failures;
 				if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD)
 					++cmd_cancel;
-				else 
+				else
 					++cmd_failed;
 			}
 		}
@@ -214,7 +215,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
 
 	SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d"
 					  " devices require eh work\n",
-				  total_failures, devices_failed));
+				   total_failures, devices_failed));
 }
 #endif
 
@@ -223,7 +224,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  * @scmd:	Cmd to have sense checked.
  *
  * Return value:
- * 	SUCCESS or FAILED or NEEDS_RETRY
+ *	SUCCESS or FAILED or NEEDS_RETRY or TARGET_ERROR
  *
  * Notes:
  *	When a deferred error is detected the current command has
@@ -294,7 +295,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 			return NEEDS_RETRY;
 		}
 		/*
-		 * if the device is in the process of becoming ready, we 
+		 * if the device is in the process of becoming ready, we
 		 * should retry.
 		 */
 		if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
@@ -326,17 +327,19 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 		 */
 		return SUCCESS;
 
-		/* these three are not supported */
+		/* these are not supported */
 	case COPY_ABORTED:
 	case VOLUME_OVERFLOW:
 	case MISCOMPARE:
-		return SUCCESS;
+	case BLANK_CHECK:
+	case DATA_PROTECT:
+		return TARGET_ERROR;
 
 	case MEDIUM_ERROR:
 		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
 		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
 		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
-			return SUCCESS;
+			return TARGET_ERROR;
 		}
 		return NEEDS_RETRY;
 
@@ -344,11 +347,9 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 		if (scmd->device->retry_hwerror)
 			return ADD_TO_MLQUEUE;
 		else
-			return SUCCESS;
+			return TARGET_ERROR;
 
 	case ILLEGAL_REQUEST:
-	case BLANK_CHECK:
-	case DATA_PROTECT:
 	default:
 		return SUCCESS;
 	}
@@ -488,7 +489,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
  */
 static void scsi_eh_done(struct scsi_cmnd *scmd)
 {
-	struct completion     *eh_action;
+	struct completion *eh_action;
 
 	SCSI_LOG_ERROR_RECOVERY(3,
 		printk("%s scmd: %p result: %x\n",
@@ -507,22 +508,23 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
 {
 	unsigned long flags;
 	int rtn;
+	struct Scsi_Host *host = scmd->device->host;
+	struct scsi_host_template *hostt = host->hostt;
 
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
 					  __func__));
 
-	if (!scmd->device->host->hostt->eh_host_reset_handler)
+	if (!hostt->eh_host_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
+	rtn = hostt->eh_host_reset_handler(scmd);
 
 	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
+		if (!hostt->skip_settle_delay)
 			ssleep(HOST_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+		spin_lock_irqsave(host->host_lock, flags);
+		scsi_report_bus_reset(host, scmd_channel(scmd));
+		spin_unlock_irqrestore(host->host_lock, flags);
 	}
 
 	return rtn;
@@ -536,22 +538,23 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
 {
 	unsigned long flags;
 	int rtn;
+	struct Scsi_Host *host = scmd->device->host;
+	struct scsi_host_template *hostt = host->hostt;
 
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
 					  __func__));
 
-	if (!scmd->device->host->hostt->eh_bus_reset_handler)
+	if (!hostt->eh_bus_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
+	rtn = hostt->eh_bus_reset_handler(scmd);
 
 	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
+		if (!hostt->skip_settle_delay)
 			ssleep(BUS_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+		spin_lock_irqsave(host->host_lock, flags);
+		scsi_report_bus_reset(host, scmd_channel(scmd));
+		spin_unlock_irqrestore(host->host_lock, flags);
 	}
 
 	return rtn;
@@ -577,16 +580,18 @@ static int scsi_try_target_reset(struct scsi_cmnd *scmd)
 {
 	unsigned long flags;
 	int rtn;
+	struct Scsi_Host *host = scmd->device->host;
+	struct scsi_host_template *hostt = host->hostt;
 
-	if (!scmd->device->host->hostt->eh_target_reset_handler)
+	if (!hostt->eh_target_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
+	rtn = hostt->eh_target_reset_handler(scmd);
 	if (rtn == SUCCESS) {
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
+		spin_lock_irqsave(host->host_lock, flags);
 		__starget_for_each_device(scsi_target(scmd->device), NULL,
 					  __scsi_report_device_reset);
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+		spin_unlock_irqrestore(host->host_lock, flags);
 	}
 
 	return rtn;
@@ -605,27 +610,28 @@ static int scsi_try_target_reset(struct scsi_cmnd *scmd)
 static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
 {
 	int rtn;
+	struct scsi_host_template *hostt = scmd->device->host->hostt;
 
-	if (!scmd->device->host->hostt->eh_device_reset_handler)
+	if (!hostt->eh_device_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+	rtn = hostt->eh_device_reset_handler(scmd);
 	if (rtn == SUCCESS)
 		__scsi_report_device_reset(scmd->device, NULL);
 	return rtn;
 }
 
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
 {
-	if (!scmd->device->host->hostt->eh_abort_handler)
+	if (!hostt->eh_abort_handler)
 		return FAILED;
 
-	return scmd->device->host->hostt->eh_abort_handler(scmd);
+	return hostt->eh_abort_handler(scmd);
 }
 
 static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
-	if (scsi_try_to_abort_cmd(scmd) != SUCCESS)
+	if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS)
 		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
 			if (scsi_try_target_reset(scmd) != SUCCESS)
 				if (scsi_try_bus_reset(scmd) != SUCCESS)
@@ -787,6 +793,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
 		case SUCCESS:
 		case NEEDS_RETRY:
 		case FAILED:
+		case TARGET_ERROR:
 			break;
 		case ADD_TO_MLQUEUE:
 			rtn = NEEDS_RETRY;
@@ -845,7 +852,7 @@ EXPORT_SYMBOL(scsi_eh_finish_cmd);
  *
  * Description:
  *    See if we need to request sense information.  if so, then get it
- *    now, so we have a better idea of what to do.  
+ *    now, so we have a better idea of what to do.
  *
  * Notes:
  *    This has the unfortunate side effect that if a shost adapter does
@@ -957,7 +964,7 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
 		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
 						  "0x%p\n", current->comm,
 						  scmd));
-		rtn = scsi_try_to_abort_cmd(scmd);
+		rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd);
 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
 			scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
 			if (!scsi_device_online(scmd->device) ||
@@ -965,7 +972,6 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
 			    !scsi_eh_tur(scmd)) {
 				scsi_eh_finish_cmd(scmd, done_q);
 			}
-				
 		} else
 			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting"
 							  " cmd failed:"
@@ -1009,7 +1015,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
  *
  * Notes:
  *    If commands are failing due to not ready, initializing command required,
- *	try revalidating the device, which will end up sending a start unit. 
+ *	try revalidating the device, which will end up sending a start unit.
  */
 static int scsi_eh_stu(struct Scsi_Host *shost,
 			      struct list_head *work_q,
@@ -1063,7 +1069,7 @@ static int scsi_eh_stu(struct Scsi_Host *shost,
  *    Try a bus device reset.  Still, look to see whether we have multiple
  *    devices that are jammed or not - if we have multiple devices, it
  *    makes no sense to try bus_device_reset - we really would need to try
- *    a bus_reset instead. 
+ *    a bus_reset instead.
  */
 static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
 				    struct list_head *work_q,
@@ -1163,7 +1169,7 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
 }
 
 /**
- * scsi_eh_bus_reset - send a bus reset 
+ * scsi_eh_bus_reset - send a bus reset
  * @shost:	&scsi host being recovered.
  * @work_q:     &list_head for pending commands.
  * @done_q:	&list_head for processed commands.
@@ -1180,7 +1186,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
 	 * we really want to loop over the various channels, and do this on
 	 * a channel by channel basis.  we should also check to see if any
 	 * of the failed commands are on soft_reset devices, and if so, skip
-	 * the reset.  
+	 * the reset.
 	 */
 
 	for (channel = 0; channel <= shost->max_channel; channel++) {
@@ -1222,7 +1228,7 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost,
 }
 
 /**
- * scsi_eh_host_reset - send a host reset 
+ * scsi_eh_host_reset - send a host reset
  * @work_q:	list_head for processed commands.
  * @done_q:	list_head for processed commands.
  */
@@ -1375,7 +1381,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 		return SUCCESS;
 		/*
 		 * when the low level driver returns did_soft_error,
-		 * it is responsible for keeping an internal retry counter 
+		 * it is responsible for keeping an internal retry counter
 		 * in order to avoid endless loops (db)
 		 *
 		 * actually this is a bug in this function here.  we should
@@ -1413,7 +1419,6 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 			 */
 			break;
 		/* fallthrough */
-
 	case DID_BUS_BUSY:
 	case DID_PARITY:
 		goto maybe_retry;
@@ -1469,6 +1474,14 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 		rtn = scsi_check_sense(scmd);
 		if (rtn == NEEDS_RETRY)
 			goto maybe_retry;
+		else if (rtn == TARGET_ERROR) {
+			/*
+			 * Need to modify host byte to signal a
+			 * permanent target failure
+			 */
+			scmd->result |= (DID_TARGET_FAILURE << 16);
+			rtn = SUCCESS;
+		}
 		/* if rtn == FAILED, we have no sense information;
 		 * returning FAILED will wake the error handler thread
 		 * to collect the sense and redo the decide
@@ -1486,6 +1499,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 	case RESERVATION_CONFLICT:
 		sdev_printk(KERN_INFO, scmd->device,
 			    "reservation conflict\n");
+		scmd->result |= (DID_NEXUS_FAILURE << 16);
 		return SUCCESS; /* causes immediate i/o error */
 	default:
 		return FAILED;
@@ -1972,7 +1986,7 @@ int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
 		if (sb_len > 7)
 			sshdr->additional_length = sense_buffer[7];
 	} else {
-		/* 
+		/*
 		 * fixed format
 		 */
 		if (sb_len > 2)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index fb2bb35..2d63c8a 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -667,6 +667,30 @@ void scsi_release_buffers(struct scsi_cmnd *cmd)
 }
 EXPORT_SYMBOL(scsi_release_buffers);
 
+static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
+{
+	int error = 0;
+
+	switch(host_byte(result)) {
+	case DID_TRANSPORT_FAILFAST:
+		error = -ENOLINK;
+		break;
+	case DID_TARGET_FAILURE:
+		cmd->result |= (DID_OK << 16);
+		error = -EREMOTEIO;
+		break;
+	case DID_NEXUS_FAILURE:
+		cmd->result |= (DID_OK << 16);
+		error = -EBADE;
+		break;
+	default:
+		error = -EIO;
+		break;
+	}
+
+	return error;
+}
+
 /*
  * Function:    scsi_io_completion()
  *
@@ -737,7 +761,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 				req->sense_len = len;
 			}
 			if (!sense_deferred)
-				error = -EIO;
+				error = __scsi_error_from_host_byte(cmd, result);
 		}
 
 		req->resid_len = scsi_get_resid(cmd);
@@ -796,7 +820,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 	if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
 		return;
 
-	error = -EIO;
+	error = __scsi_error_from_host_byte(cmd, result);
 
 	if (host_byte(result) == DID_RESET) {
 		/* Third party bus reset or reset for error recovery
@@ -843,6 +867,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 				description = "Host Data Integrity Failure";
 				action = ACTION_FAIL;
 				error = -EILSEQ;
+			/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
+			} else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
+				   (cmd->cmnd[0] == UNMAP ||
+				    cmd->cmnd[0] == WRITE_SAME_16 ||
+				    cmd->cmnd[0] == WRITE_SAME)) {
+				description = "Discard failure";
+				action = ACTION_FAIL;
 			} else
 				action = ACTION_FAIL;
 			break;
@@ -1038,6 +1069,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
 	cmd->request = req;
 
 	cmd->cmnd = req->cmd;
+	cmd->prot_op = SCSI_PROT_NORMAL;
 
 	return cmd;
 }
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index b4056d1..2a58895 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -45,6 +45,7 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)
 enum {
 	SCSI_DEVINFO_GLOBAL = 0,
 	SCSI_DEVINFO_SPI,
+	SCSI_DEVINFO_DH,
 };
 
 extern int scsi_get_device_flags(struct scsi_device *sdev,
@@ -56,6 +57,7 @@ extern int scsi_get_device_flags_keyed(struct scsi_device *sdev,
 extern int scsi_dev_info_list_add_keyed(int compatible, char *vendor,
 					char *model, char *strflags,
 					int flags, int key);
+extern int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key);
 extern int scsi_dev_info_add_list(int key, const char *name);
 extern int scsi_dev_info_remove_list(int key);
 
@@ -146,7 +148,7 @@ static inline void scsi_netlink_exit(void) {}
 #endif
 
 /* scsi_pm.c */
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 extern const struct dev_pm_ops scsi_bus_pm_ops;
 #endif
 #ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 490ce21..e44ff64 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -383,7 +383,7 @@ struct bus_type scsi_bus_type = {
         .name		= "scsi",
         .match		= scsi_bus_match,
 	.uevent		= scsi_bus_uevent,
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 	.pm		= &scsi_bus_pm_ops,
 #endif
 };
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
index c399be9..f672820 100644
--- a/drivers/scsi/scsi_tgt_lib.c
+++ b/drivers/scsi/scsi_tgt_lib.c
@@ -629,7 +629,7 @@ static int __init scsi_tgt_init(void)
 	if (!scsi_tgt_cmd_cache)
 		return -ENOMEM;
 
-	scsi_tgtd = create_workqueue("scsi_tgtd");
+	scsi_tgtd = alloc_workqueue("scsi_tgtd", 0, 1);
 	if (!scsi_tgtd) {
 		err = -ENOMEM;
 		goto free_kmemcache;
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index f905ecb..b421839 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -954,6 +954,7 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
 	if (dd_size)
 		conn->dd_data = &conn[1];
 
+	mutex_init(&conn->ep_mutex);
 	INIT_LIST_HEAD(&conn->conn_list);
 	conn->transport = transport;
 	conn->cid = cid;
@@ -975,7 +976,6 @@ iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
 
 	spin_lock_irqsave(&connlock, flags);
 	list_add(&conn->conn_list, &connlist);
-	conn->active = 1;
 	spin_unlock_irqrestore(&connlock, flags);
 
 	ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
@@ -1001,7 +1001,6 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn)
 	unsigned long flags;
 
 	spin_lock_irqsave(&connlock, flags);
-	conn->active = 0;
 	list_del(&conn->conn_list);
 	spin_unlock_irqrestore(&connlock, flags);
 
@@ -1430,6 +1429,29 @@ release_host:
 	return err;
 }
 
+static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+				  u64 ep_handle)
+{
+	struct iscsi_cls_conn *conn;
+	struct iscsi_endpoint *ep;
+
+	if (!transport->ep_disconnect)
+		return -EINVAL;
+
+	ep = iscsi_lookup_endpoint(ep_handle);
+	if (!ep)
+		return -EINVAL;
+	conn = ep->conn;
+	if (conn) {
+		mutex_lock(&conn->ep_mutex);
+		conn->ep = NULL;
+		mutex_unlock(&conn->ep_mutex);
+	}
+
+	transport->ep_disconnect(ep);
+	return 0;
+}
+
 static int
 iscsi_if_transport_ep(struct iscsi_transport *transport,
 		      struct iscsi_uevent *ev, int msg_type)
@@ -1454,14 +1476,8 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
 						   ev->u.ep_poll.timeout_ms);
 		break;
 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
-		if (!transport->ep_disconnect)
-			return -EINVAL;
-
-		ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle);
-		if (!ep)
-			return -EINVAL;
-
-		transport->ep_disconnect(ep);
+		rc = iscsi_if_ep_disconnect(transport,
+					    ev->u.ep_disconnect.ep_handle);
 		break;
 	}
 	return rc;
@@ -1609,12 +1625,31 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
 		session = iscsi_session_lookup(ev->u.b_conn.sid);
 		conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
 
-		if (session && conn)
-			ev->r.retcode =	transport->bind_conn(session, conn,
-					ev->u.b_conn.transport_eph,
-					ev->u.b_conn.is_leading);
-		else
+		if (conn && conn->ep)
+			iscsi_if_ep_disconnect(transport, conn->ep->id);
+
+		if (!session || !conn) {
 			err = -EINVAL;
+			break;
+		}
+
+		ev->r.retcode =	transport->bind_conn(session, conn,
+						ev->u.b_conn.transport_eph,
+						ev->u.b_conn.is_leading);
+		if (ev->r.retcode || !transport->ep_connect)
+			break;
+
+		ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
+		if (ep) {
+			ep->conn = conn;
+
+			mutex_lock(&conn->ep_mutex);
+			conn->ep = ep;
+			mutex_unlock(&conn->ep_mutex);
+		} else
+			iscsi_cls_conn_printk(KERN_ERR, conn,
+					      "Could not set ep conn "
+					      "binding\n");
 		break;
 	case ISCSI_UEVENT_SET_PARAM:
 		err = iscsi_set_param(transport, ev);
@@ -1747,13 +1782,48 @@ iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
 iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
 iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
 iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
-iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
 iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
 iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
-iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
 iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
 iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
 
+#define iscsi_conn_ep_attr_show(param)					\
+static ssize_t show_conn_ep_param_##param(struct device *dev,		\
+					  struct device_attribute *attr,\
+					  char *buf)			\
+{									\
+	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
+	struct iscsi_transport *t = conn->transport;			\
+	struct iscsi_endpoint *ep;					\
+	ssize_t rc;							\
+									\
+	/*								\
+	 * Need to make sure ep_disconnect does not free the LLD's	\
+	 * interconnect resources while we are trying to read them.	\
+	 */								\
+	mutex_lock(&conn->ep_mutex);					\
+	ep = conn->ep;							\
+	if (!ep && t->ep_connect) {					\
+		mutex_unlock(&conn->ep_mutex);				\
+		return -ENOTCONN;					\
+	}								\
+									\
+	if (ep)								\
+		rc = t->get_ep_param(ep, param, buf);			\
+	else								\
+		rc = t->get_conn_param(conn, param, buf);		\
+	mutex_unlock(&conn->ep_mutex);					\
+	return rc;							\
+}
+
+#define iscsi_conn_ep_attr(field, param)				\
+	iscsi_conn_ep_attr_show(param)					\
+static ISCSI_CLASS_ATTR(conn, field, S_IRUGO,				\
+			show_conn_ep_param_##param, NULL);
+
+iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
+
 /*
  * iSCSI session attrs
  */
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index e567302..7ff61d7 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -96,6 +96,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 #define SD_MINORS	0
 #endif
 
+static void sd_config_discard(struct scsi_disk *, unsigned int);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
@@ -294,7 +295,54 @@ sd_show_thin_provisioning(struct device *dev, struct device_attribute *attr,
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
-	return snprintf(buf, 20, "%u\n", sdkp->thin_provisioning);
+	return snprintf(buf, 20, "%u\n", sdkp->lbpme);
+}
+
+static const char *lbp_mode[] = {
+	[SD_LBP_FULL]		= "full",
+	[SD_LBP_UNMAP]		= "unmap",
+	[SD_LBP_WS16]		= "writesame_16",
+	[SD_LBP_WS10]		= "writesame_10",
+	[SD_LBP_ZERO]		= "writesame_zero",
+	[SD_LBP_DISABLE]	= "disabled",
+};
+
+static ssize_t
+sd_show_provisioning_mode(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+	return snprintf(buf, 20, "%s\n", lbp_mode[sdkp->provisioning_mode]);
+}
+
+static ssize_t
+sd_store_provisioning_mode(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+	struct scsi_device *sdp = sdkp->device;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (sdp->type != TYPE_DISK)
+		return -EINVAL;
+
+	if (!strncmp(buf, lbp_mode[SD_LBP_UNMAP], 20))
+		sd_config_discard(sdkp, SD_LBP_UNMAP);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_WS16], 20))
+		sd_config_discard(sdkp, SD_LBP_WS16);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_WS10], 20))
+		sd_config_discard(sdkp, SD_LBP_WS10);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_ZERO], 20))
+		sd_config_discard(sdkp, SD_LBP_ZERO);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_DISABLE], 20))
+		sd_config_discard(sdkp, SD_LBP_DISABLE);
+	else
+		return -EINVAL;
+
+	return count;
 }
 
 static struct device_attribute sd_disk_attrs[] = {
@@ -309,6 +357,8 @@ static struct device_attribute sd_disk_attrs[] = {
 	__ATTR(protection_mode, S_IRUGO, sd_show_protection_mode, NULL),
 	__ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
 	__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
+	__ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
+	       sd_store_provisioning_mode),
 	__ATTR_NULL,
 };
 
@@ -433,6 +483,49 @@ static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif)
 	scsi_set_prot_type(scmd, dif);
 }
 
+static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
+{
+	struct request_queue *q = sdkp->disk->queue;
+	unsigned int logical_block_size = sdkp->device->sector_size;
+	unsigned int max_blocks = 0;
+
+	q->limits.discard_zeroes_data = sdkp->lbprz;
+	q->limits.discard_alignment = sdkp->unmap_alignment;
+	q->limits.discard_granularity =
+		max(sdkp->physical_block_size,
+		    sdkp->unmap_granularity * logical_block_size);
+
+	switch (mode) {
+
+	case SD_LBP_DISABLE:
+		q->limits.max_discard_sectors = 0;
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+		return;
+
+	case SD_LBP_UNMAP:
+		max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+		break;
+
+	case SD_LBP_WS16:
+		max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+		break;
+
+	case SD_LBP_WS10:
+		max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+		break;
+
+	case SD_LBP_ZERO:
+		max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+		q->limits.discard_zeroes_data = 1;
+		break;
+	}
+
+	q->limits.max_discard_sectors = max_blocks * (logical_block_size >> 9);
+	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+
+	sdkp->provisioning_mode = mode;
+}
+
 /**
  * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
  * @sdp: scsi device to operate one
@@ -449,6 +542,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 	unsigned int nr_sectors = bio_sectors(bio);
 	unsigned int len;
 	int ret;
+	char *buf;
 	struct page *page;
 
 	if (sdkp->device->sector_size == 4096) {
@@ -464,8 +558,9 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 	if (!page)
 		return BLKPREP_DEFER;
 
-	if (sdkp->unmap) {
-		char *buf = page_address(page);
+	switch (sdkp->provisioning_mode) {
+	case SD_LBP_UNMAP:
+		buf = page_address(page);
 
 		rq->cmd_len = 10;
 		rq->cmd[0] = UNMAP;
@@ -477,7 +572,9 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 		put_unaligned_be32(nr_sectors, &buf[16]);
 
 		len = 24;
-	} else {
+		break;
+
+	case SD_LBP_WS16:
 		rq->cmd_len = 16;
 		rq->cmd[0] = WRITE_SAME_16;
 		rq->cmd[1] = 0x8; /* UNMAP */
@@ -485,11 +582,30 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 		put_unaligned_be32(nr_sectors, &rq->cmd[10]);
 
 		len = sdkp->device->sector_size;
+		break;
+
+	case SD_LBP_WS10:
+	case SD_LBP_ZERO:
+		rq->cmd_len = 10;
+		rq->cmd[0] = WRITE_SAME;
+		if (sdkp->provisioning_mode == SD_LBP_WS10)
+			rq->cmd[1] = 0x8; /* UNMAP */
+		put_unaligned_be32(sector, &rq->cmd[2]);
+		put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+
+		len = sdkp->device->sector_size;
+		break;
+
+	default:
+		ret = BLKPREP_KILL;
+		goto out;
 	}
 
 	blk_add_request_payload(rq, page, len);
 	ret = scsi_setup_blk_pc_cmnd(sdp, rq);
 	rq->buffer = page_address(page);
+
+out:
 	if (ret != BLKPREP_OK) {
 		__free_page(page);
 		rq->buffer = NULL;
@@ -1251,12 +1367,10 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 	struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
 	int sense_valid = 0;
 	int sense_deferred = 0;
+	unsigned char op = SCpnt->cmnd[0];
 
-	if (SCpnt->request->cmd_flags & REQ_DISCARD) {
-		if (!result)
-			scsi_set_resid(SCpnt, 0);
-		return good_bytes;
-	}
+	if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
+		scsi_set_resid(SCpnt, 0);
 
 	if (result) {
 		sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1295,10 +1409,17 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 		SCpnt->result = 0;
 		memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 		break;
-	case ABORTED_COMMAND: /* DIF: Target detected corruption */
-	case ILLEGAL_REQUEST: /* DIX: Host detected corruption */
-		if (sshdr.asc == 0x10)
+	case ABORTED_COMMAND:
+		if (sshdr.asc == 0x10)  /* DIF: Target detected corruption */
+			good_bytes = sd_completed_bytes(SCpnt);
+		break;
+	case ILLEGAL_REQUEST:
+		if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
 			good_bytes = sd_completed_bytes(SCpnt);
+		/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
+		if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
+		    (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
+			sd_config_discard(sdkp, SD_LBP_DISABLE);
 		break;
 	default:
 		break;
@@ -1596,17 +1717,13 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
 		sd_printk(KERN_NOTICE, sdkp,
 			  "physical block alignment offset: %u\n", alignment);
 
-	if (buffer[14] & 0x80) { /* TPE */
-		struct request_queue *q = sdp->request_queue;
+	if (buffer[14] & 0x80) { /* LBPME */
+		sdkp->lbpme = 1;
 
-		sdkp->thin_provisioning = 1;
-		q->limits.discard_granularity = sdkp->physical_block_size;
-		q->limits.max_discard_sectors = 0xffffffff;
+		if (buffer[14] & 0x40) /* LBPRZ */
+			sdkp->lbprz = 1;
 
-		if (buffer[14] & 0x40) /* TPRZ */
-			q->limits.discard_zeroes_data = 1;
-
-		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+		sd_config_discard(sdkp, SD_LBP_WS16);
 	}
 
 	sdkp->capacity = lba + 1;
@@ -2091,7 +2208,6 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer)
  */
 static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
-	struct request_queue *q = sdkp->disk->queue;
 	unsigned int sector_sz = sdkp->device->sector_size;
 	const int vpd_len = 64;
 	unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
@@ -2106,39 +2222,46 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
 	blk_queue_io_opt(sdkp->disk->queue,
 			 get_unaligned_be32(&buffer[12]) * sector_sz);
 
-	/* Thin provisioning enabled and page length indicates TP support */
-	if (sdkp->thin_provisioning && buffer[3] == 0x3c) {
-		unsigned int lba_count, desc_count, granularity;
+	if (buffer[3] == 0x3c) {
+		unsigned int lba_count, desc_count;
 
-		lba_count = get_unaligned_be32(&buffer[20]);
-		desc_count = get_unaligned_be32(&buffer[24]);
-
-		if (lba_count && desc_count) {
-			if (sdkp->tpvpd && !sdkp->tpu)
-				sdkp->unmap = 0;
-			else
-				sdkp->unmap = 1;
-		}
+		sdkp->max_ws_blocks =
+			(u32) min_not_zero(get_unaligned_be64(&buffer[36]),
+					   (u64)0xffffffff);
 
-		if (sdkp->tpvpd && !sdkp->tpu && !sdkp->tpws) {
-			sd_printk(KERN_ERR, sdkp, "Thin provisioning is " \
-				  "enabled but neither TPU, nor TPWS are " \
-				  "set. Disabling discard!\n");
+		if (!sdkp->lbpme)
 			goto out;
-		}
 
-		if (lba_count)
-			q->limits.max_discard_sectors =
-				lba_count * sector_sz >> 9;
+		lba_count = get_unaligned_be32(&buffer[20]);
+		desc_count = get_unaligned_be32(&buffer[24]);
 
-		granularity = get_unaligned_be32(&buffer[28]);
+		if (lba_count && desc_count)
+			sdkp->max_unmap_blocks = lba_count;
 
-		if (granularity)
-			q->limits.discard_granularity = granularity * sector_sz;
+		sdkp->unmap_granularity = get_unaligned_be32(&buffer[28]);
 
 		if (buffer[32] & 0x80)
-			q->limits.discard_alignment =
+			sdkp->unmap_alignment =
 				get_unaligned_be32(&buffer[32]) & ~(1 << 31);
+
+		if (!sdkp->lbpvpd) { /* LBP VPD page not provided */
+
+			if (sdkp->max_unmap_blocks)
+				sd_config_discard(sdkp, SD_LBP_UNMAP);
+			else
+				sd_config_discard(sdkp, SD_LBP_WS16);
+
+		} else {	/* LBP VPD page tells us what to use */
+
+			if (sdkp->lbpu && sdkp->max_unmap_blocks)
+				sd_config_discard(sdkp, SD_LBP_UNMAP);
+			else if (sdkp->lbpws)
+				sd_config_discard(sdkp, SD_LBP_WS16);
+			else if (sdkp->lbpws10)
+				sd_config_discard(sdkp, SD_LBP_WS10);
+			else
+				sd_config_discard(sdkp, SD_LBP_DISABLE);
+		}
 	}
 
  out:
@@ -2172,15 +2295,15 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
 }
 
 /**
- * sd_read_thin_provisioning - Query thin provisioning VPD page
+ * sd_read_block_provisioning - Query provisioning VPD page
  * @disk: disk to query
  */
-static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
+static void sd_read_block_provisioning(struct scsi_disk *sdkp)
 {
 	unsigned char *buffer;
 	const int vpd_len = 8;
 
-	if (sdkp->thin_provisioning == 0)
+	if (sdkp->lbpme == 0)
 		return;
 
 	buffer = kmalloc(vpd_len, GFP_KERNEL);
@@ -2188,9 +2311,10 @@ static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
 	if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len))
 		goto out;
 
-	sdkp->tpvpd = 1;
-	sdkp->tpu   = (buffer[5] >> 7) & 1;	/* UNMAP */
-	sdkp->tpws  = (buffer[5] >> 6) & 1;	/* WRITE SAME(16) with UNMAP */
+	sdkp->lbpvpd	= 1;
+	sdkp->lbpu	= (buffer[5] >> 7) & 1;	/* UNMAP */
+	sdkp->lbpws	= (buffer[5] >> 6) & 1;	/* WRITE SAME(16) with UNMAP */
+	sdkp->lbpws10	= (buffer[5] >> 5) & 1;	/* WRITE SAME(10) with UNMAP */
 
  out:
 	kfree(buffer);
@@ -2247,7 +2371,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
 		sd_read_capacity(sdkp, buffer);
 
 		if (sd_try_extended_inquiry(sdp)) {
-			sd_read_thin_provisioning(sdkp);
+			sd_read_block_provisioning(sdkp);
 			sd_read_block_limits(sdkp);
 			sd_read_block_characteristics(sdkp);
 		}
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index c9d8f6c..6ad798b 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -43,6 +43,15 @@ enum {
 	SD_MEMPOOL_SIZE = 2,	/* CDB pool size */
 };
 
+enum {
+	SD_LBP_FULL = 0,	/* Full logical block provisioning */
+	SD_LBP_UNMAP,		/* Use UNMAP command */
+	SD_LBP_WS16,		/* Use WRITE SAME(16) with UNMAP bit */
+	SD_LBP_WS10,		/* Use WRITE SAME(10) with UNMAP bit */
+	SD_LBP_ZERO,		/* Use WRITE SAME(10) with zero payload */
+	SD_LBP_DISABLE,		/* Discard disabled due to failed cmd */
+};
+
 struct scsi_disk {
 	struct scsi_driver *driver;	/* always &sd_template */
 	struct scsi_device *device;
@@ -50,21 +59,27 @@ struct scsi_disk {
 	struct gendisk	*disk;
 	atomic_t	openers;
 	sector_t	capacity;	/* size in 512-byte sectors */
+	u32		max_ws_blocks;
+	u32		max_unmap_blocks;
+	u32		unmap_granularity;
+	u32		unmap_alignment;
 	u32		index;
 	unsigned int	physical_block_size;
 	u8		media_present;
 	u8		write_prot;
 	u8		protection_type;/* Data Integrity Field */
+	u8		provisioning_mode;
 	unsigned	ATO : 1;	/* state of disk ATO bit */
 	unsigned	WCE : 1;	/* state of disk WCE bit */
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
 	unsigned	first_scan : 1;
-	unsigned	thin_provisioning : 1;
-	unsigned	unmap : 1;
-	unsigned	tpws : 1;
-	unsigned	tpu : 1;
-	unsigned	tpvpd : 1;
+	unsigned	lbpme : 1;
+	unsigned	lbprz : 1;
+	unsigned	lbpu : 1;
+	unsigned	lbpws : 1;
+	unsigned	lbpws10 : 1;
+	unsigned	lbpvpd : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c
index 193b37b..676fe9a 100644
--- a/drivers/scsi/sun_esp.c
+++ b/drivers/scsi/sun_esp.c
@@ -562,7 +562,7 @@ fail:
 	return err;
 }
 
-static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit esp_sbus_probe(struct platform_device *op)
 {
 	struct device_node *dma_node = NULL;
 	struct device_node *dp = op->dev.of_node;
@@ -632,7 +632,7 @@ static const struct of_device_id esp_match[] = {
 };
 MODULE_DEVICE_TABLE(of, esp_match);
 
-static struct of_platform_driver esp_sbus_driver = {
+static struct platform_driver esp_sbus_driver = {
 	.driver = {
 		.name = "esp",
 		.owner = THIS_MODULE,
@@ -644,12 +644,12 @@ static struct of_platform_driver esp_sbus_driver = {
 
 static int __init sunesp_init(void)
 {
-	return of_register_platform_driver(&esp_sbus_driver);
+	return platform_driver_register(&esp_sbus_driver);
 }
 
 static void __exit sunesp_exit(void)
 {
-	of_unregister_platform_driver(&esp_sbus_driver);
+	platform_driver_unregister(&esp_sbus_driver);
 }
 
 MODULE_DESCRIPTION("Sun ESP SCSI driver");
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index bb233a9..fc14b8d 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -53,6 +53,12 @@ if SPI_MASTER
 
 comment "SPI Master Controller Drivers"
 
+config SPI_ALTERA
+	tristate "Altera SPI Controller"
+	select SPI_BITBANG
+	help
+	  This is the driver for the Altera SPI Controller.
+
 config SPI_ATH79
 	tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
 	depends on ATH79 && GENERIC_GPIO
@@ -161,13 +167,13 @@ config SPI_IMX_VER_0_0
 	def_bool y if SOC_IMX21 || SOC_IMX27
 
 config SPI_IMX_VER_0_4
-	def_bool y if ARCH_MX31
+	def_bool y if SOC_IMX31
 
 config SPI_IMX_VER_0_7
-	def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51 || ARCH_MX53
+	def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
 
 config SPI_IMX_VER_2_3
-	def_bool y if ARCH_MX51 || ARCH_MX53
+	def_bool y if SOC_IMX51 || SOC_IMX53
 
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
@@ -231,6 +237,13 @@ config SPI_FSL_ESPI
 	  From MPC8536, 85xx platform uses the controller, and all P10xx,
 	  P20xx, P30xx,P40xx, P50xx uses this controller.
 
+config SPI_OC_TINY
+	tristate "OpenCores tiny SPI"
+	depends on GENERIC_GPIO
+	select SPI_BITBANG
+	help
+	  This is the driver for OpenCores tiny SPI master controller.
+
 config SPI_OMAP_UWIRE
 	tristate "OMAP1 MicroWire"
 	depends on ARCH_OMAP1
@@ -330,6 +343,12 @@ config SPI_SH_MSIOF
 	help
 	  SPI driver for SuperH MSIOF blocks.
 
+config SPI_SH
+	tristate "SuperH SPI controller"
+	depends on SUPERH
+	help
+	  SPI driver for SuperH SPI blocks.
+
 config SPI_SH_SCI
 	tristate "SuperH SCI SPI controller"
 	depends on SUPERH
@@ -350,6 +369,16 @@ config SPI_TEGRA
 	help
 	  SPI driver for NVidia Tegra SoCs
 
+config SPI_TI_SSP
+	tristate "TI Sequencer Serial Port - SPI Support"
+	depends on MFD_TI_SSP
+	help
+	  This selects an SPI master implementation using a TI sequencer
+	  serial port.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ti-ssp-spi.
+
 config SPI_TOPCLIFF_PCH
 	tristate "Topcliff PCH SPI Controller"
 	depends on PCI
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 86d1b5f..fd2fc5f 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -9,6 +9,7 @@ ccflags-$(CONFIG_SPI_DEBUG) := -DDEBUG
 obj-$(CONFIG_SPI_MASTER)		+= spi.o
 
 # SPI master controller drivers (bus)
+obj-$(CONFIG_SPI_ALTERA)		+= spi_altera.o
 obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
 obj-$(CONFIG_SPI_ATH79)			+= ath79_spi.o
 obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)		+= pxa2xx_spi_pci.o
+obj-$(CONFIG_SPI_OC_TINY)		+= spi_oc_tiny.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
@@ -43,9 +45,11 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
 obj-$(CONFIG_SPI_TEGRA)			+= spi_tegra.o
+obj-$(CONFIG_SPI_TI_SSP)		+= ti-ssp-spi.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
+obj-$(CONFIG_SPI_SH)			+= spi_sh.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
diff --git a/drivers/spi/amba-pl022.c b/drivers/spi/amba-pl022.c
index 71a1219..5c2b092 100644
--- a/drivers/spi/amba-pl022.c
+++ b/drivers/spi/amba-pl022.c
@@ -329,15 +329,16 @@ struct vendor_data {
 /**
  * struct pl022 - This is the private SSP driver data structure
  * @adev: AMBA device model hookup
- * @vendor: Vendor data for the IP block
- * @phybase: The physical memory where the SSP device resides
- * @virtbase: The virtual memory where the SSP is mapped
+ * @vendor: vendor data for the IP block
+ * @phybase: the physical memory where the SSP device resides
+ * @virtbase: the virtual memory where the SSP is mapped
+ * @clk: outgoing clock "SPICLK" for the SPI bus
  * @master: SPI framework hookup
  * @master_info: controller-specific data from machine setup
- * @regs: SSP controller register's virtual address
- * @pump_messages: Work struct for scheduling work to the workqueue
- * @lock: spinlock to syncronise access to driver data
  * @workqueue: a workqueue on which any spi_message request is queued
+ * @pump_messages: work struct for scheduling work to the workqueue
+ * @queue_lock: spinlock to syncronise access to message queue
+ * @queue: message queue
  * @busy: workqueue is busy
  * @running: workqueue is running
  * @pump_transfers: Tasklet used in Interrupt Transfer mode
@@ -348,8 +349,14 @@ struct vendor_data {
  * @tx_end: end position in TX buffer to be read
  * @rx: current position in RX buffer to be written
  * @rx_end: end position in RX buffer to be written
- * @readingtype: the type of read currently going on
- * @writingtype: the type or write currently going on
+ * @read: the type of read currently going on
+ * @write: the type of write currently going on
+ * @exp_fifo_level: expected FIFO level
+ * @dma_rx_channel: optional channel for RX DMA
+ * @dma_tx_channel: optional channel for TX DMA
+ * @sgt_rx: scattertable for the RX transfer
+ * @sgt_tx: scattertable for the TX transfer
+ * @dummypage: a dummy page used for driving data on the bus with DMA
  */
 struct pl022 {
 	struct amba_device		*adev;
@@ -397,8 +404,8 @@ struct pl022 {
  * @cpsr: Value of Clock prescale register
  * @n_bytes: how many bytes(power of 2) reqd for a given data width of client
  * @enable_dma: Whether to enable DMA or not
- * @write: function ptr to be used to write when doing xfer for this chip
  * @read: function ptr to be used to read when doing xfer for this chip
+ * @write: function ptr to be used to write when doing xfer for this chip
  * @cs_control: chip select callback provided by chip
  * @xfer_type: polling/interrupt/DMA
  *
@@ -508,9 +515,10 @@ static void giveback(struct pl022 *pl022)
 	msg->state = NULL;
 	if (msg->complete)
 		msg->complete(msg->context);
-	/* This message is completed, so let's turn off the clocks! */
+	/* This message is completed, so let's turn off the clocks & power */
 	clk_disable(pl022->clk);
 	amba_pclk_disable(pl022->adev);
+	amba_vcore_disable(pl022->adev);
 }
 
 /**
@@ -917,7 +925,6 @@ static int configure_dma(struct pl022 *pl022)
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 	struct dma_async_tx_descriptor *rxdesc;
 	struct dma_async_tx_descriptor *txdesc;
-	dma_cookie_t cookie;
 
 	/* Check that the channels are available */
 	if (!rxchan || !txchan)
@@ -962,10 +969,8 @@ static int configure_dma(struct pl022 *pl022)
 		tx_conf.dst_addr_width = rx_conf.src_addr_width;
 	BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
 
-	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
-				       (unsigned long) &rx_conf);
-	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
-				       (unsigned long) &tx_conf);
+	dmaengine_slave_config(rxchan, &rx_conf);
+	dmaengine_slave_config(txchan, &tx_conf);
 
 	/* Create sglists for the transfers */
 	pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
@@ -1018,23 +1023,17 @@ static int configure_dma(struct pl022 *pl022)
 	rxdesc->callback_param = pl022;
 
 	/* Submit and fire RX and TX with TX last so we're ready to read! */
-	cookie = rxdesc->tx_submit(rxdesc);
-	if (dma_submit_error(cookie))
-		goto err_submit_rx;
-	cookie = txdesc->tx_submit(txdesc);
-	if (dma_submit_error(cookie))
-		goto err_submit_tx;
-	rxchan->device->device_issue_pending(rxchan);
-	txchan->device->device_issue_pending(txchan);
+	dmaengine_submit(rxdesc);
+	dmaengine_submit(txdesc);
+	dma_async_issue_pending(rxchan);
+	dma_async_issue_pending(txchan);
 
 	return 0;
 
-err_submit_tx:
-err_submit_rx:
 err_txdesc:
-	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+	dmaengine_terminate_all(txchan);
 err_rxdesc:
-	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
+	dmaengine_terminate_all(rxchan);
 	dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 err_tx_sgmap:
@@ -1101,8 +1100,8 @@ static void terminate_dma(struct pl022 *pl022)
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 
-	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
-	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+	dmaengine_terminate_all(rxchan);
+	dmaengine_terminate_all(txchan);
 	unmap_free_dma_scatter(pl022);
 }
 
@@ -1482,9 +1481,11 @@ static void pump_messages(struct work_struct *work)
 	/* Setup the SPI using the per chip configuration */
 	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
 	/*
-	 * We enable the clocks here, then the clocks will be disabled when
-	 * giveback() is called in each method (poll/interrupt/DMA)
+	 * We enable the core voltage and clocks here, then the clocks
+	 * and core will be disabled when giveback() is called in each method
+	 * (poll/interrupt/DMA)
 	 */
+	amba_vcore_enable(pl022->adev);
 	amba_pclk_enable(pl022->adev);
 	clk_enable(pl022->clk);
 	restore_state(pl022);
@@ -1910,8 +1911,6 @@ static int pl022_setup(struct spi_device *spi)
 	    && ((pl022->master_info)->enable_dma)) {
 		chip->enable_dma = true;
 		dev_dbg(&spi->dev, "DMA mode set in controller state\n");
-		if (status < 0)
-			goto err_config_params;
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
 			       SSP_DMACR_MASK_RXDMAE, 0);
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
@@ -2021,7 +2020,7 @@ static void pl022_cleanup(struct spi_device *spi)
 
 
 static int __devinit
-pl022_probe(struct amba_device *adev, struct amba_id *id)
+pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct device *dev = &adev->dev;
 	struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
@@ -2130,8 +2129,12 @@ pl022_probe(struct amba_device *adev, struct amba_id *id)
 		goto err_spi_register;
 	}
 	dev_dbg(dev, "probe succeded\n");
-	/* Disable the silicon block pclk and clock it when needed */
+	/*
+	 * Disable the silicon block pclk and any voltage domain and just
+	 * power it up and clock it when it's needed
+	 */
 	amba_pclk_disable(adev);
+	amba_vcore_disable(adev);
 	return 0;
 
  err_spi_register:
@@ -2196,9 +2199,11 @@ static int pl022_suspend(struct amba_device *adev, pm_message_t state)
 		return status;
 	}
 
+	amba_vcore_enable(adev);
 	amba_pclk_enable(adev);
 	load_ssp_default_config(pl022);
 	amba_pclk_disable(adev);
+	amba_vcore_disable(adev);
 	dev_dbg(&adev->dev, "suspended\n");
 	return 0;
 }
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 6beab99..1f0ed80 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -571,6 +571,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 		unsigned long tx_reg, rx_reg;
 		struct edmacc_param param;
 		void *rx_buf;
+		int b, c;
 
 		dma = &dspi->dma;
 
@@ -591,22 +592,38 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 
 		if (t->tx_buf) {
 			t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
-						dspi->wcount, DMA_TO_DEVICE);
+						t->len, DMA_TO_DEVICE);
 			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
 				dev_dbg(sdev, "Unable to DMA map %d bytes"
-						"TX buffer\n", dspi->wcount);
+						"TX buffer\n", t->len);
 				return -ENOMEM;
 			}
 		}
 
+		/*
+		 * If number of words is greater than 65535, then we need
+		 * to configure a 3 dimension transfer.  Use the BCNTRLD
+		 * feature to allow for transfers that aren't even multiples
+		 * of 65535 (or any other possible b size) by first transferring
+		 * the remainder amount then grabbing the next N blocks of
+		 * 65535 words.
+		 */
+
+		c = dspi->wcount / (SZ_64K - 1);	/* N 65535 Blocks */
+		b = dspi->wcount - c * (SZ_64K - 1);	/* Remainder */
+		if (b)
+			c++;
+		else
+			b = SZ_64K - 1;
+
 		param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
 		param.src = t->tx_buf ? t->tx_dma : tx_reg;
-		param.a_b_cnt = dspi->wcount << 16 | data_type;
+		param.a_b_cnt = b << 16 | data_type;
 		param.dst = tx_reg;
 		param.src_dst_bidx = t->tx_buf ? data_type : 0;
-		param.link_bcntrld = 0xffff;
-		param.src_dst_cidx = 0;
-		param.ccnt = 1;
+		param.link_bcntrld = 0xffffffff;
+		param.src_dst_cidx = t->tx_buf ? data_type : 0;
+		param.ccnt = c;
 		edma_write_slot(dma->tx_channel, &param);
 		edma_link(dma->tx_channel, dma->dummy_param_slot);
 
@@ -624,7 +641,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 
 		if (t->rx_buf) {
 			rx_buf = t->rx_buf;
-			rx_buf_count = dspi->rcount;
+			rx_buf_count = t->len;
 		} else {
 			rx_buf = dspi->rx_tmp_buf;
 			rx_buf_count = sizeof(dspi->rx_tmp_buf);
@@ -636,19 +653,19 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 			dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
 								rx_buf_count);
 			if (t->tx_buf)
-				dma_unmap_single(NULL, t->tx_dma, dspi->wcount,
+				dma_unmap_single(NULL, t->tx_dma, t->len,
 								DMA_TO_DEVICE);
 			return -ENOMEM;
 		}
 
 		param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
 		param.src = rx_reg;
-		param.a_b_cnt = dspi->rcount << 16 | data_type;
+		param.a_b_cnt = b << 16 | data_type;
 		param.dst = t->rx_dma;
 		param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
-		param.link_bcntrld = 0xffff;
-		param.src_dst_cidx = 0;
-		param.ccnt = 1;
+		param.link_bcntrld = 0xffffffff;
+		param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
+		param.ccnt = c;
 		edma_write_slot(dma->rx_channel, &param);
 
 		if (pdata->cshold_bug)
@@ -675,7 +692,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
 	if (spicfg->io_type == SPI_IO_TYPE_DMA) {
 
 		if (t->tx_buf)
-			dma_unmap_single(NULL, t->tx_dma, dspi->wcount,
+			dma_unmap_single(NULL, t->tx_dma, t->len,
 								DMA_TO_DEVICE);
 
 		dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
@@ -790,7 +807,6 @@ static int davinci_spi_probe(struct platform_device *pdev)
 	struct resource *r, *mem;
 	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
 	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
-	resource_size_t	dma_eventq = SPI_NO_RESOURCE;
 	int i = 0, ret = 0;
 	u32 spipc0;
 
@@ -878,17 +894,13 @@ static int davinci_spi_probe(struct platform_device *pdev)
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 	if (r)
 		dma_tx_chan = r->start;
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
-	if (r)
-		dma_eventq = r->start;
 
 	dspi->bitbang.txrx_bufs = davinci_spi_bufs;
 	if (dma_rx_chan != SPI_NO_RESOURCE &&
-	    dma_tx_chan != SPI_NO_RESOURCE &&
-	    dma_eventq != SPI_NO_RESOURCE) {
+	    dma_tx_chan != SPI_NO_RESOURCE) {
 		dspi->dma.rx_channel = dma_rx_chan;
 		dspi->dma.tx_channel = dma_tx_chan;
-		dspi->dma.eventq = dma_eventq;
+		dspi->dma.eventq = pdata->dma_event_q;
 
 		ret = davinci_spi_request_dma(dspi);
 		if (ret)
@@ -897,7 +909,7 @@ static int davinci_spi_probe(struct platform_device *pdev)
 		dev_info(&pdev->dev, "DMA: supported\n");
 		dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
 				"event queue: %d\n", dma_rx_chan, dma_tx_chan,
-				dma_eventq);
+				pdata->dma_event_q);
 	}
 
 	dspi->get_rx = davinci_spi_rx_buf_u8;
diff --git a/drivers/spi/dw_spi.c b/drivers/spi/dw_spi.c
index 22af77f..9a61964 100644
--- a/drivers/spi/dw_spi.c
+++ b/drivers/spi/dw_spi.c
@@ -22,10 +22,10 @@
 #include <linux/highmem.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-
-#include <linux/spi/dw_spi.h>
 #include <linux/spi/spi.h>
 
+#include "dw_spi.h"
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #endif
diff --git a/drivers/spi/dw_spi.h b/drivers/spi/dw_spi.h
new file mode 100644
index 0000000..fb0bce5
--- /dev/null
+++ b/drivers/spi/dw_spi.h
@@ -0,0 +1,234 @@
+#ifndef DW_SPI_HEADER_H
+#define DW_SPI_HEADER_H
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+
+#define SPI_TMOD_OFFSET			8
+#define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+/* Bit fields in ISR, IMR, RISR, 7 bits */
+#define SPI_INT_TXEI			(1 << 0)
+#define SPI_INT_TXOI			(1 << 1)
+#define SPI_INT_RXUI			(1 << 2)
+#define SPI_INT_RXOI			(1 << 3)
+#define SPI_INT_RXFI			(1 << 4)
+#define SPI_INT_MSTI			(1 << 5)
+
+/* TX RX interrupt level threshhold, max can be 256 */
+#define SPI_INT_THRESHOLD		32
+
+enum dw_ssi_type {
+	SSI_MOTO_SPI = 0,
+	SSI_TI_SSP,
+	SSI_NS_MICROWIRE,
+};
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+	u32	dr;		/* Currently oper as 32 bits,
+				though only low 16 bits matters */
+} __packed;
+
+struct dw_spi;
+struct dw_spi_dma_ops {
+	int (*dma_init)(struct dw_spi *dws);
+	void (*dma_exit)(struct dw_spi *dws);
+	int (*dma_transfer)(struct dw_spi *dws, int cs_change);
+};
+
+struct dw_spi {
+	struct spi_master	*master;
+	struct spi_device	*cur_dev;
+	struct device		*parent_dev;
+	enum dw_ssi_type	type;
+
+	void __iomem		*regs;
+	unsigned long		paddr;
+	u32			iolen;
+	int			irq;
+	u32			fifo_len;	/* depth of the FIFO buffer */
+	u32			max_freq;	/* max bus freq supported */
+
+	u16			bus_num;
+	u16			num_cs;		/* supported slave numbers */
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct	pump_messages;
+	spinlock_t		lock;
+	struct list_head	queue;
+	int			busy;
+	int			run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct	pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message	*cur_msg;
+	struct spi_transfer	*cur_transfer;
+	struct chip_data	*cur_chip;
+	struct chip_data	*prev_chip;
+	size_t			len;
+	void			*tx;
+	void			*tx_end;
+	void			*rx;
+	void			*rx_end;
+	int			dma_mapped;
+	dma_addr_t		rx_dma;
+	dma_addr_t		tx_dma;
+	size_t			rx_map_len;
+	size_t			tx_map_len;
+	u8			n_bytes;	/* current is a 1/2 bytes op */
+	u8			max_bits_per_word;	/* maxim is 16b */
+	u32			dma_width;
+	int			cs_change;
+	int			(*write)(struct dw_spi *dws);
+	int			(*read)(struct dw_spi *dws);
+	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
+	void			(*cs_control)(u32 command);
+
+	/* Dma info */
+	int			dma_inited;
+	struct dma_chan		*txchan;
+	struct scatterlist	tx_sgl;
+	struct dma_chan		*rxchan;
+	struct scatterlist	rx_sgl;
+	int			dma_chan_done;
+	struct device		*dma_dev;
+	dma_addr_t		dma_addr; /* phy address of the Data register */
+	struct dw_spi_dma_ops	*dma_ops;
+	void			*dma_priv; /* platform relate info */
+	struct pci_dev		*dmac;
+
+	/* Bus interface info */
+	void			*priv;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs;
+#endif
+};
+
+#define dw_readl(dw, name) \
+	__raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+	__raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_readw(dw, name) \
+	__raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+	__raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+
+static inline void spi_enable_chip(struct dw_spi *dws, int enable)
+{
+	dw_writel(dws, ssienr, (enable ? 1 : 0));
+}
+
+static inline void spi_set_clk(struct dw_spi *dws, u16 div)
+{
+	dw_writel(dws, baudr, div);
+}
+
+static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
+{
+	if (cs > dws->num_cs)
+		return;
+
+	if (dws->cs_control)
+		dws->cs_control(1);
+
+	dw_writel(dws, ser, 1 << cs);
+}
+
+/* Disable IRQ bits */
+static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) & ~mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/* Enable IRQ bits */
+static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) | mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/*
+ * Each SPI slave device to work with dw_api controller should
+ * has such a structure claiming its working mode (PIO/DMA etc),
+ * which can be save in the "controller_data" member of the
+ * struct spi_device
+ */
+struct dw_spi_chip {
+	u8 poll_mode;	/* 0 for contoller polling mode */
+	u8 type;	/* SPI/SSP/Micrwire */
+	u8 enable_dma;
+	void (*cs_control)(u32 command);
+};
+
+extern int dw_spi_add_host(struct dw_spi *dws);
+extern void dw_spi_remove_host(struct dw_spi *dws);
+extern int dw_spi_suspend_host(struct dw_spi *dws);
+extern int dw_spi_resume_host(struct dw_spi *dws);
+extern void dw_spi_xfer_done(struct dw_spi *dws);
+
+/* platform related setup */
+extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
+#endif /* DW_SPI_HEADER_H */
diff --git a/drivers/spi/dw_spi_mid.c b/drivers/spi/dw_spi_mid.c
index c91c966..4891782 100644
--- a/drivers/spi/dw_spi_mid.c
+++ b/drivers/spi/dw_spi_mid.c
@@ -22,7 +22,8 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/dw_spi.h>
+
+#include "dw_spi.h"
 
 #ifdef CONFIG_SPI_DW_MID_DMA
 #include <linux/intel_mid_dma.h>
diff --git a/drivers/spi/dw_spi_mmio.c b/drivers/spi/dw_spi_mmio.c
index 2fa012c..e0e813d 100644
--- a/drivers/spi/dw_spi_mmio.c
+++ b/drivers/spi/dw_spi_mmio.c
@@ -13,8 +13,10 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/spi/dw_spi.h>
 #include <linux/spi/spi.h>
+#include <linux/scatterlist.h>
+
+#include "dw_spi.h"
 
 #define DRIVER_NAME "dw_spi_mmio"
 
diff --git a/drivers/spi/dw_spi_pci.c b/drivers/spi/dw_spi_pci.c
index 49ec3aa..ad260aa 100644
--- a/drivers/spi/dw_spi_pci.c
+++ b/drivers/spi/dw_spi_pci.c
@@ -20,9 +20,10 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/spi/dw_spi.h>
 #include <linux/spi/spi.h>
 
+#include "dw_spi.h"
+
 #define DRIVER_NAME "dw_spi_pci"
 
 struct dw_spi_pci {
diff --git a/drivers/spi/mpc512x_psc_spi.c b/drivers/spi/mpc512x_psc_spi.c
index 77d9e7e..6a5b423 100644
--- a/drivers/spi/mpc512x_psc_spi.c
+++ b/drivers/spi/mpc512x_psc_spi.c
@@ -507,8 +507,7 @@ static int __devexit mpc512x_psc_spi_do_remove(struct device *dev)
 	return 0;
 }
 
-static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op,
-					      const struct of_device_id *match)
+static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
 {
 	const u32 *regaddr_p;
 	u64 regaddr64, size64;
@@ -551,7 +550,7 @@ static struct of_device_id mpc512x_psc_spi_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
 
-static struct of_platform_driver mpc512x_psc_spi_of_driver = {
+static struct platform_driver mpc512x_psc_spi_of_driver = {
 	.probe = mpc512x_psc_spi_of_probe,
 	.remove = __devexit_p(mpc512x_psc_spi_of_remove),
 	.driver = {
@@ -563,13 +562,13 @@ static struct of_platform_driver mpc512x_psc_spi_of_driver = {
 
 static int __init mpc512x_psc_spi_init(void)
 {
-	return of_register_platform_driver(&mpc512x_psc_spi_of_driver);
+	return platform_driver_register(&mpc512x_psc_spi_of_driver);
 }
 module_init(mpc512x_psc_spi_init);
 
 static void __exit mpc512x_psc_spi_exit(void)
 {
-	of_unregister_platform_driver(&mpc512x_psc_spi_of_driver);
+	platform_driver_unregister(&mpc512x_psc_spi_of_driver);
 }
 module_exit(mpc512x_psc_spi_exit);
 
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 8a904c1..e30baf0 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -450,8 +450,7 @@ free_master:
 	return ret;
 }
 
-static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op,
-	const struct of_device_id *match)
+static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
 {
 	const u32 *regaddr_p;
 	u64 regaddr64, size64;
@@ -503,7 +502,7 @@ static const struct of_device_id mpc52xx_psc_spi_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
 
-static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
+static struct platform_driver mpc52xx_psc_spi_of_driver = {
 	.probe = mpc52xx_psc_spi_of_probe,
 	.remove = __devexit_p(mpc52xx_psc_spi_of_remove),
 	.driver = {
@@ -515,13 +514,13 @@ static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
 
 static int __init mpc52xx_psc_spi_init(void)
 {
-	return of_register_platform_driver(&mpc52xx_psc_spi_of_driver);
+	return platform_driver_register(&mpc52xx_psc_spi_of_driver);
 }
 module_init(mpc52xx_psc_spi_init);
 
 static void __exit mpc52xx_psc_spi_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver);
+	platform_driver_unregister(&mpc52xx_psc_spi_of_driver);
 }
 module_exit(mpc52xx_psc_spi_exit);
 
diff --git a/drivers/spi/mpc52xx_spi.c b/drivers/spi/mpc52xx_spi.c
index 84439f6..015a974 100644
--- a/drivers/spi/mpc52xx_spi.c
+++ b/drivers/spi/mpc52xx_spi.c
@@ -390,8 +390,7 @@ static int mpc52xx_spi_transfer(struct spi_device *spi, struct spi_message *m)
 /*
  * OF Platform Bus Binding
  */
-static int __devinit mpc52xx_spi_probe(struct platform_device *op,
-				       const struct of_device_id *match)
+static int __devinit mpc52xx_spi_probe(struct platform_device *op)
 {
 	struct spi_master *master;
 	struct mpc52xx_spi *ms;
@@ -556,7 +555,7 @@ static const struct of_device_id mpc52xx_spi_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, mpc52xx_spi_match);
 
-static struct of_platform_driver mpc52xx_spi_of_driver = {
+static struct platform_driver mpc52xx_spi_of_driver = {
 	.driver = {
 		.name = "mpc52xx-spi",
 		.owner = THIS_MODULE,
@@ -568,13 +567,13 @@ static struct of_platform_driver mpc52xx_spi_of_driver = {
 
 static int __init mpc52xx_spi_init(void)
 {
-	return of_register_platform_driver(&mpc52xx_spi_of_driver);
+	return platform_driver_register(&mpc52xx_spi_of_driver);
 }
 module_init(mpc52xx_spi_init);
 
 static void __exit mpc52xx_spi_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_spi_of_driver);
+	platform_driver_unregister(&mpc52xx_spi_of_driver);
 }
 module_exit(mpc52xx_spi_exit);
 
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index abb1ffb..3a5ed06 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005, 2006 Nokia Corporation
  * Author:	Samuel Ortiz <samuel.ortiz@nokia.com> and
- *		Juha Yrjölä <juha.yrjola@nokia.com>
+ *		Juha Yrjďż˝lďż˝ <juha.yrjola@nokia.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/spi/spi.h>
 
@@ -46,7 +47,6 @@
 #define OMAP2_MCSPI_MAX_CTRL 		4
 
 #define OMAP2_MCSPI_REVISION		0x00
-#define OMAP2_MCSPI_SYSCONFIG		0x10
 #define OMAP2_MCSPI_SYSSTATUS		0x14
 #define OMAP2_MCSPI_IRQSTATUS		0x18
 #define OMAP2_MCSPI_IRQENABLE		0x1c
@@ -63,13 +63,6 @@
 
 /* per-register bitmasks: */
 
-#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE	BIT(4)
-#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP	BIT(2)
-#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	BIT(0)
-#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	BIT(1)
-
-#define OMAP2_MCSPI_SYSSTATUS_RESETDONE	BIT(0)
-
 #define OMAP2_MCSPI_MODULCTRL_SINGLE	BIT(0)
 #define OMAP2_MCSPI_MODULCTRL_MS	BIT(2)
 #define OMAP2_MCSPI_MODULCTRL_STEST	BIT(3)
@@ -122,13 +115,12 @@ struct omap2_mcspi {
 	spinlock_t		lock;
 	struct list_head	msg_queue;
 	struct spi_master	*master;
-	struct clk		*ick;
-	struct clk		*fck;
 	/* Virtual base address of the controller */
 	void __iomem		*base;
 	unsigned long		phys;
 	/* SPI1 has 4 channels, while SPI2 has 2 */
 	struct omap2_mcspi_dma	*dma_channels;
+	struct  device		*dev;
 };
 
 struct omap2_mcspi_cs {
@@ -144,7 +136,6 @@ struct omap2_mcspi_cs {
  * corresponding registers are modified.
  */
 struct omap2_mcspi_regs {
-	u32 sysconfig;
 	u32 modulctrl;
 	u32 wakeupenable;
 	struct list_head cs;
@@ -268,9 +259,6 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
 	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
 			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
 
-	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG,
-			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig);
-
 	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
 			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
 
@@ -280,20 +268,12 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
 }
 static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
 {
-	clk_disable(mcspi->ick);
-	clk_disable(mcspi->fck);
+	pm_runtime_put_sync(mcspi->dev);
 }
 
 static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
 {
-	if (clk_enable(mcspi->ick))
-		return -ENODEV;
-	if (clk_enable(mcspi->fck))
-		return -ENODEV;
-
-	omap2_mcspi_restore_ctx(mcspi);
-
-	return 0;
+	return pm_runtime_get_sync(mcspi->dev);
 }
 
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
@@ -487,6 +467,9 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 	rx_reg		= base + OMAP2_MCSPI_RX0;
 	chstat_reg	= base + OMAP2_MCSPI_CHSTAT0;
 
+	if (c < (word_len>>3))
+		return 0;
+
 	if (word_len <= 8) {
 		u8		*rx;
 		const u8	*tx;
@@ -534,7 +517,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 				dev_vdbg(&spi->dev, "read-%d %02x\n",
 						word_len, *(rx - 1));
 			}
-		} while (c);
+		} while (c > (word_len>>3));
 	} else if (word_len <= 16) {
 		u16		*rx;
 		const u16	*tx;
@@ -581,7 +564,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 				dev_vdbg(&spi->dev, "read-%d %04x\n",
 						word_len, *(rx - 1));
 			}
-		} while (c);
+		} while (c > (word_len>>3));
 	} else if (word_len <= 32) {
 		u32		*rx;
 		const u32	*tx;
@@ -628,7 +611,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 				dev_vdbg(&spi->dev, "read-%d %08x\n",
 						word_len, *(rx - 1));
 			}
-		} while (c);
+		} while (c > (word_len>>3));
 	}
 
 	/* for TX_ONLY mode, be sure all words have shifted out */
@@ -651,6 +634,17 @@ out:
 	return count - c;
 }
 
+static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
+{
+	u32 div;
+
+	for (div = 0; div < 15; div++)
+		if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
+			return div;
+
+	return 15;
+}
+
 /* called only when no transfer is active to this device */
 static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 		struct spi_transfer *t)
@@ -673,12 +667,8 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	if (t && t->speed_hz)
 		speed_hz = t->speed_hz;
 
-	if (speed_hz) {
-		while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div))
-					> speed_hz)
-			div++;
-	} else
-		div = 15;
+	speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
+	div = omap2_mcspi_calc_divisor(speed_hz);
 
 	l = mcspi_cached_chconf0(spi);
 
@@ -715,7 +705,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	mcspi_write_chconf0(spi, l);
 
 	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
-			OMAP2_MCSPI_MAX_FREQ / (1 << div),
+			OMAP2_MCSPI_MAX_FREQ >> div,
 			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
 			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
 
@@ -819,8 +809,9 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 			return ret;
 	}
 
-	if (omap2_mcspi_enable_clocks(mcspi))
-		return -ENODEV;
+	ret = omap2_mcspi_enable_clocks(mcspi);
+	if (ret < 0)
+		return ret;
 
 	ret = omap2_mcspi_setup_transfer(spi, NULL);
 	omap2_mcspi_disable_clocks(mcspi);
@@ -863,10 +854,11 @@ static void omap2_mcspi_work(struct work_struct *work)
 	struct omap2_mcspi	*mcspi;
 
 	mcspi = container_of(work, struct omap2_mcspi, work);
-	spin_lock_irq(&mcspi->lock);
 
-	if (omap2_mcspi_enable_clocks(mcspi))
-		goto out;
+	if (omap2_mcspi_enable_clocks(mcspi) < 0)
+		return;
+
+	spin_lock_irq(&mcspi->lock);
 
 	/* We only enable one channel at a time -- the one whose message is
 	 * at the head of the queue -- although this controller would gladly
@@ -979,10 +971,9 @@ static void omap2_mcspi_work(struct work_struct *work)
 		spin_lock_irq(&mcspi->lock);
 	}
 
-	omap2_mcspi_disable_clocks(mcspi);
-
-out:
 	spin_unlock_irq(&mcspi->lock);
+
+	omap2_mcspi_disable_clocks(mcspi);
 }
 
 static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
@@ -1015,10 +1006,10 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
 					t->bits_per_word);
 			return -EINVAL;
 		}
-		if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) {
-			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
-					t->speed_hz,
-					OMAP2_MCSPI_MAX_FREQ/(1<<16));
+		if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
+			dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n",
+				t->speed_hz,
+				OMAP2_MCSPI_MAX_FREQ >> 15);
 			return -EINVAL;
 		}
 
@@ -1058,25 +1049,15 @@ static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
 	return 0;
 }
 
-static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
+static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
 {
 	struct spi_master	*master = mcspi->master;
 	u32			tmp;
+	int ret = 0;
 
-	if (omap2_mcspi_enable_clocks(mcspi))
-		return -1;
-
-	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
-			OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
-	do {
-		tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
-	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
-
-	tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
-		OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
-		OMAP2_MCSPI_SYSCONFIG_SMARTIDLE;
-	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp);
-	omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp;
+	ret = omap2_mcspi_enable_clocks(mcspi);
+	if (ret < 0)
+		return ret;
 
 	tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
 	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
@@ -1087,91 +1068,26 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
 	return 0;
 }
 
-static u8 __initdata spi1_rxdma_id [] = {
-	OMAP24XX_DMA_SPI1_RX0,
-	OMAP24XX_DMA_SPI1_RX1,
-	OMAP24XX_DMA_SPI1_RX2,
-	OMAP24XX_DMA_SPI1_RX3,
-};
-
-static u8 __initdata spi1_txdma_id [] = {
-	OMAP24XX_DMA_SPI1_TX0,
-	OMAP24XX_DMA_SPI1_TX1,
-	OMAP24XX_DMA_SPI1_TX2,
-	OMAP24XX_DMA_SPI1_TX3,
-};
-
-static u8 __initdata spi2_rxdma_id[] = {
-	OMAP24XX_DMA_SPI2_RX0,
-	OMAP24XX_DMA_SPI2_RX1,
-};
-
-static u8 __initdata spi2_txdma_id[] = {
-	OMAP24XX_DMA_SPI2_TX0,
-	OMAP24XX_DMA_SPI2_TX1,
-};
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \
-	|| defined(CONFIG_ARCH_OMAP4)
-static u8 __initdata spi3_rxdma_id[] = {
-	OMAP24XX_DMA_SPI3_RX0,
-	OMAP24XX_DMA_SPI3_RX1,
-};
+static int omap_mcspi_runtime_resume(struct device *dev)
+{
+	struct omap2_mcspi	*mcspi;
+	struct spi_master	*master;
 
-static u8 __initdata spi3_txdma_id[] = {
-	OMAP24XX_DMA_SPI3_TX0,
-	OMAP24XX_DMA_SPI3_TX1,
-};
-#endif
+	master = dev_get_drvdata(dev);
+	mcspi = spi_master_get_devdata(master);
+	omap2_mcspi_restore_ctx(mcspi);
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static u8 __initdata spi4_rxdma_id[] = {
-	OMAP34XX_DMA_SPI4_RX0,
-};
+	return 0;
+}
 
-static u8 __initdata spi4_txdma_id[] = {
-	OMAP34XX_DMA_SPI4_TX0,
-};
-#endif
 
 static int __init omap2_mcspi_probe(struct platform_device *pdev)
 {
 	struct spi_master	*master;
+	struct omap2_mcspi_platform_config *pdata = pdev->dev.platform_data;
 	struct omap2_mcspi	*mcspi;
 	struct resource		*r;
 	int			status = 0, i;
-	const u8		*rxdma_id, *txdma_id;
-	unsigned		num_chipselect;
-
-	switch (pdev->id) {
-	case 1:
-		rxdma_id = spi1_rxdma_id;
-		txdma_id = spi1_txdma_id;
-		num_chipselect = 4;
-		break;
-	case 2:
-		rxdma_id = spi2_rxdma_id;
-		txdma_id = spi2_txdma_id;
-		num_chipselect = 2;
-		break;
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \
-	|| defined(CONFIG_ARCH_OMAP4)
-	case 3:
-		rxdma_id = spi3_rxdma_id;
-		txdma_id = spi3_txdma_id;
-		num_chipselect = 2;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-	case 4:
-		rxdma_id = spi4_rxdma_id;
-		txdma_id = spi4_txdma_id;
-		num_chipselect = 1;
-		break;
-#endif
-	default:
-		return -EINVAL;
-	}
 
 	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
 	if (master == NULL) {
@@ -1188,7 +1104,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
 	master->setup = omap2_mcspi_setup;
 	master->transfer = omap2_mcspi_transfer;
 	master->cleanup = omap2_mcspi_cleanup;
-	master->num_chipselect = num_chipselect;
+	master->num_chipselect = pdata->num_cs;
 
 	dev_set_drvdata(&pdev->dev, master);
 
@@ -1206,49 +1122,62 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
+	r->start += pdata->regs_offset;
+	r->end += pdata->regs_offset;
 	mcspi->phys = r->start;
 	mcspi->base = ioremap(r->start, r->end - r->start + 1);
 	if (!mcspi->base) {
 		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
 		status = -ENOMEM;
-		goto err1aa;
+		goto err2;
 	}
 
+	mcspi->dev = &pdev->dev;
 	INIT_WORK(&mcspi->work, omap2_mcspi_work);
 
 	spin_lock_init(&mcspi->lock);
 	INIT_LIST_HEAD(&mcspi->msg_queue);
 	INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs);
 
-	mcspi->ick = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(mcspi->ick)) {
-		dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
-		status = PTR_ERR(mcspi->ick);
-		goto err1a;
-	}
-	mcspi->fck = clk_get(&pdev->dev, "fck");
-	if (IS_ERR(mcspi->fck)) {
-		dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
-		status = PTR_ERR(mcspi->fck);
-		goto err2;
-	}
-
 	mcspi->dma_channels = kcalloc(master->num_chipselect,
 			sizeof(struct omap2_mcspi_dma),
 			GFP_KERNEL);
 
 	if (mcspi->dma_channels == NULL)
-		goto err3;
+		goto err2;
+
+	for (i = 0; i < master->num_chipselect; i++) {
+		char dma_ch_name[14];
+		struct resource *dma_res;
+
+		sprintf(dma_ch_name, "rx%d", i);
+		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+							dma_ch_name);
+		if (!dma_res) {
+			dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
+			status = -ENODEV;
+			break;
+		}
 
-	for (i = 0; i < num_chipselect; i++) {
 		mcspi->dma_channels[i].dma_rx_channel = -1;
-		mcspi->dma_channels[i].dma_rx_sync_dev = rxdma_id[i];
+		mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
+		sprintf(dma_ch_name, "tx%d", i);
+		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+							dma_ch_name);
+		if (!dma_res) {
+			dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
+			status = -ENODEV;
+			break;
+		}
+
 		mcspi->dma_channels[i].dma_tx_channel = -1;
-		mcspi->dma_channels[i].dma_tx_sync_dev = txdma_id[i];
+		mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
 	}
 
-	if (omap2_mcspi_reset(mcspi) < 0)
-		goto err4;
+	pm_runtime_enable(&pdev->dev);
+
+	if (status || omap2_mcspi_master_setup(mcspi) < 0)
+		goto err3;
 
 	status = spi_register_master(master);
 	if (status < 0)
@@ -1257,17 +1186,13 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev)
 	return status;
 
 err4:
-	kfree(mcspi->dma_channels);
+	spi_master_put(master);
 err3:
-	clk_put(mcspi->fck);
+	kfree(mcspi->dma_channels);
 err2:
-	clk_put(mcspi->ick);
-err1a:
-	iounmap(mcspi->base);
-err1aa:
 	release_mem_region(r->start, (r->end - r->start) + 1);
+	iounmap(mcspi->base);
 err1:
-	spi_master_put(master);
 	return status;
 }
 
@@ -1283,9 +1208,7 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
 	mcspi = spi_master_get_devdata(master);
 	dma_channels = mcspi->dma_channels;
 
-	clk_put(mcspi->fck);
-	clk_put(mcspi->ick);
-
+	omap2_mcspi_disable_clocks(mcspi);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(r->start, (r->end - r->start) + 1);
 
@@ -1336,6 +1259,7 @@ static int omap2_mcspi_resume(struct device *dev)
 
 static const struct dev_pm_ops omap2_mcspi_pm_ops = {
 	.resume = omap2_mcspi_resume,
+	.runtime_resume	= omap_mcspi_runtime_resume,
 };
 
 static struct platform_driver omap2_mcspi_driver = {
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c
index 9592883..a429b01 100644
--- a/drivers/spi/pxa2xx_spi.c
+++ b/drivers/spi/pxa2xx_spi.c
@@ -1557,9 +1557,7 @@ static int __devinit pxa2xx_spi_probe(struct platform_device *pdev)
 	drv_data->ssp = ssp;
 
 	master->dev.parent = &pdev->dev;
-#ifdef CONFIG_OF
 	master->dev.of_node = pdev->dev.of_node;
-#endif
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
diff --git a/drivers/spi/pxa2xx_spi_pci.c b/drivers/spi/pxa2xx_spi_pci.c
index 19752b0..378e504 100644
--- a/drivers/spi/pxa2xx_spi_pci.c
+++ b/drivers/spi/pxa2xx_spi_pci.c
@@ -89,9 +89,7 @@ static int __devinit ce4100_spi_probe(struct pci_dev *dev,
 		goto err_nomem;
 
 	pdev->dev.parent = &dev->dev;
-#ifdef CONFIG_OF
 	pdev->dev.of_node = dev->dev.of_node;
-#endif
 	ssp = &spi_info->ssp;
 	ssp->phys_base = pci_resource_start(dev, 0);
 	ssp->mmio_base = ioremap(phys_beg, phys_len);
diff --git a/drivers/spi/spi_altera.c b/drivers/spi/spi_altera.c
new file mode 100644
index 0000000..4813a63
--- /dev/null
+++ b/drivers/spi/spi_altera.c
@@ -0,0 +1,339 @@
+/*
+ * Altera SPI driver
+ *
+ * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on spi_s3c24xx.c, which is:
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#define DRV_NAME "spi_altera"
+
+#define ALTERA_SPI_RXDATA	0
+#define ALTERA_SPI_TXDATA	4
+#define ALTERA_SPI_STATUS	8
+#define ALTERA_SPI_CONTROL	12
+#define ALTERA_SPI_SLAVE_SEL	20
+
+#define ALTERA_SPI_STATUS_ROE_MSK	0x8
+#define ALTERA_SPI_STATUS_TOE_MSK	0x10
+#define ALTERA_SPI_STATUS_TMT_MSK	0x20
+#define ALTERA_SPI_STATUS_TRDY_MSK	0x40
+#define ALTERA_SPI_STATUS_RRDY_MSK	0x80
+#define ALTERA_SPI_STATUS_E_MSK		0x100
+
+#define ALTERA_SPI_CONTROL_IROE_MSK	0x8
+#define ALTERA_SPI_CONTROL_ITOE_MSK	0x10
+#define ALTERA_SPI_CONTROL_ITRDY_MSK	0x40
+#define ALTERA_SPI_CONTROL_IRRDY_MSK	0x80
+#define ALTERA_SPI_CONTROL_IE_MSK	0x100
+#define ALTERA_SPI_CONTROL_SSO_MSK	0x400
+
+struct altera_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem *base;
+	int irq;
+	int len;
+	int count;
+	int bytes_per_word;
+	unsigned long imr;
+
+	/* data buffers */
+	const unsigned char *tx;
+	unsigned char *rx;
+};
+
+static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static void altera_spi_chipsel(struct spi_device *spi, int value)
+{
+	struct altera_spi *hw = altera_spi_to_hw(spi);
+
+	if (spi->mode & SPI_CS_HIGH) {
+		switch (value) {
+		case BITBANG_CS_INACTIVE:
+			writel(1 << spi->chip_select,
+			       hw->base + ALTERA_SPI_SLAVE_SEL);
+			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+
+		case BITBANG_CS_ACTIVE:
+			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
+			break;
+		}
+	} else {
+		switch (value) {
+		case BITBANG_CS_INACTIVE:
+			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+
+		case BITBANG_CS_ACTIVE:
+			writel(1 << spi->chip_select,
+			       hw->base + ALTERA_SPI_SLAVE_SEL);
+			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+		}
+	}
+}
+
+static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	return 0;
+}
+
+static int altera_spi_setup(struct spi_device *spi)
+{
+	return 0;
+}
+
+static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
+{
+	if (hw->tx) {
+		switch (hw->bytes_per_word) {
+		case 1:
+			return hw->tx[count];
+		case 2:
+			return (hw->tx[count * 2]
+				| (hw->tx[count * 2 + 1] << 8));
+		}
+	}
+	return 0;
+}
+
+static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct altera_spi *hw = altera_spi_to_hw(spi);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->count = 0;
+	hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8;
+	hw->len = t->len / hw->bytes_per_word;
+
+	if (hw->irq >= 0) {
+		/* enable receive interrupt */
+		hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
+		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+
+		/* send the first byte */
+		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
+
+		wait_for_completion(&hw->done);
+		/* disable receive interrupt */
+		hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
+		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+	} else {
+		/* send the first byte */
+		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
+
+		while (1) {
+			unsigned int rxd;
+
+			while (!(readl(hw->base + ALTERA_SPI_STATUS) &
+				 ALTERA_SPI_STATUS_RRDY_MSK))
+				cpu_relax();
+
+			rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+			if (hw->rx) {
+				switch (hw->bytes_per_word) {
+				case 1:
+					hw->rx[hw->count] = rxd;
+					break;
+				case 2:
+					hw->rx[hw->count * 2] = rxd;
+					hw->rx[hw->count * 2 + 1] = rxd >> 8;
+					break;
+				}
+			}
+
+			hw->count++;
+
+			if (hw->count < hw->len)
+				writel(hw_txbyte(hw, hw->count),
+				       hw->base + ALTERA_SPI_TXDATA);
+			else
+				break;
+		}
+
+	}
+
+	return hw->count * hw->bytes_per_word;
+}
+
+static irqreturn_t altera_spi_irq(int irq, void *dev)
+{
+	struct altera_spi *hw = dev;
+	unsigned int rxd;
+
+	rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+	if (hw->rx) {
+		switch (hw->bytes_per_word) {
+		case 1:
+			hw->rx[hw->count] = rxd;
+			break;
+		case 2:
+			hw->rx[hw->count * 2] = rxd;
+			hw->rx[hw->count * 2 + 1] = rxd >> 8;
+			break;
+		}
+	}
+
+	hw->count++;
+
+	if (hw->count < hw->len)
+		writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
+	else
+		complete(&hw->done);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit altera_spi_probe(struct platform_device *pdev)
+{
+	struct altera_spi_platform_data *platp = pdev->dev.platform_data;
+	struct altera_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	int err = -ENODEV;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
+	if (!master)
+		return err;
+
+	/* setup the master state. */
+	master->bus_num = pdev->id;
+	master->num_chipselect = 16;
+	master->mode_bits = SPI_CS_HIGH;
+	master->setup = altera_spi_setup;
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	/* setup the state for the bitbang driver */
+	hw->bitbang.master = spi_master_get(master);
+	if (!hw->bitbang.master)
+		return err;
+	hw->bitbang.setup_transfer = altera_spi_setupxfer;
+	hw->bitbang.chipselect = altera_spi_chipsel;
+	hw->bitbang.txrx_bufs = altera_spi_txrx;
+
+	/* find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     pdev->name))
+		goto exit_busy;
+	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!hw->base)
+		goto exit_busy;
+	/* program defaults into the registers */
+	hw->imr = 0;		/* disable spi interrupts */
+	writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+	writel(0, hw->base + ALTERA_SPI_STATUS);	/* clear status reg */
+	if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)
+		readl(hw->base + ALTERA_SPI_RXDATA);	/* flush rxdata */
+	/* irq is optional */
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq >= 0) {
+		init_completion(&hw->done);
+		err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
+				       pdev->name, hw);
+		if (err)
+			goto exit;
+	}
+	/* find platform data */
+	if (!platp)
+		hw->bitbang.master->dev.of_node = pdev->dev.of_node;
+
+	/* register our spi controller */
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err)
+		goto exit;
+	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
+
+	return 0;
+
+exit_busy:
+	err = -EBUSY;
+exit:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return err;
+}
+
+static int __devexit altera_spi_remove(struct platform_device *dev)
+{
+	struct altera_spi *hw = platform_get_drvdata(dev);
+	struct spi_master *master = hw->bitbang.master;
+
+	spi_bitbang_stop(&hw->bitbang);
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id altera_spi_match[] = {
+	{ .compatible = "ALTR,spi-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_spi_match);
+#else /* CONFIG_OF */
+#define altera_spi_match NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver altera_spi_driver = {
+	.probe = altera_spi_probe,
+	.remove = __devexit_p(altera_spi_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = NULL,
+		.of_match_table = altera_spi_match,
+	},
+};
+
+static int __init altera_spi_init(void)
+{
+	return platform_driver_register(&altera_spi_driver);
+}
+module_init(altera_spi_init);
+
+static void __exit altera_spi_exit(void)
+{
+	platform_driver_unregister(&altera_spi_driver);
+}
+module_exit(altera_spi_exit);
+
+MODULE_DESCRIPTION("Altera SPI driver");
+MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c
index 3f22351..a284624 100644
--- a/drivers/spi/spi_bfin5xx.c
+++ b/drivers/spi/spi_bfin5xx.c
@@ -425,6 +425,7 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
 	int n_bytes = drv_data->n_bytes;
+	int loop = 0;
 
 	/* wait until transfer finished. */
 	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
@@ -435,10 +436,15 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 		/* last read */
 		if (drv_data->rx) {
 			dev_dbg(&drv_data->pdev->dev, "last read\n");
-			if (n_bytes == 2)
-				*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-			else if (n_bytes == 1)
-				*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+			if (n_bytes % 2) {
+				u16 *buf = (u16 *)drv_data->rx;
+				for (loop = 0; loop < n_bytes / 2; loop++)
+					*buf++ = read_RDBR(drv_data);
+			} else {
+				u8 *buf = (u8 *)drv_data->rx;
+				for (loop = 0; loop < n_bytes; loop++)
+					*buf++ = read_RDBR(drv_data);
+			}
 			drv_data->rx += n_bytes;
 		}
 
@@ -458,29 +464,53 @@ static irqreturn_t bfin_spi_pio_irq_handler(int irq, void *dev_id)
 	if (drv_data->rx && drv_data->tx) {
 		/* duplex */
 		dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
-		if (drv_data->n_bytes == 2) {
-			*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-			write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		} else if (drv_data->n_bytes == 1) {
-			*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-			write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->rx;
+			u16 *buf2 = (u16 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf2++);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->rx;
+			u8 *buf2 = (u8 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf2++);
+			}
 		}
 	} else if (drv_data->rx) {
 		/* read */
 		dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
-		if (drv_data->n_bytes == 2)
-			*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-		else if (drv_data->n_bytes == 1)
-			*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-		write_TDBR(drv_data, chip->idle_tx_val);
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->rx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, chip->idle_tx_val);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->rx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, chip->idle_tx_val);
+			}
+		}
 	} else if (drv_data->tx) {
 		/* write */
 		dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
-		bfin_spi_dummy_read(drv_data);
-		if (drv_data->n_bytes == 2)
-			write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		else if (drv_data->n_bytes == 1)
-			write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf++);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf++);
+			}
+		}
 	}
 
 	if (drv_data->tx)
@@ -623,6 +653,7 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		message->state = bfin_spi_next_transfer(drv_data);
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&drv_data->pump_transfers);
+		return;
 	}
 
 	if (transfer->tx_buf != NULL) {
@@ -651,16 +682,16 @@ static void bfin_spi_pump_transfers(unsigned long data)
 
 	/* Bits per word setup */
 	bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
-	if (bits_per_word == 8) {
-		drv_data->n_bytes = 1;
-		drv_data->len = transfer->len;
-		cr_width = 0;
-		drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
-	} else if (bits_per_word == 16) {
-		drv_data->n_bytes = 2;
+	if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) {
+		drv_data->n_bytes = bits_per_word/8;
 		drv_data->len = (transfer->len) >> 1;
 		cr_width = BIT_CTL_WORDSIZE;
 		drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
+	} else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) {
+		drv_data->n_bytes = bits_per_word/8;
+		drv_data->len = transfer->len;
+		cr_width = 0;
+		drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
 	} else {
 		dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
 		message->status = -EINVAL;
@@ -815,10 +846,19 @@ static void bfin_spi_pump_transfers(unsigned long data)
 		if (drv_data->tx == NULL)
 			write_TDBR(drv_data, chip->idle_tx_val);
 		else {
-			if (bits_per_word == 8)
-				write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-			else
-				write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+			int loop;
+			if (bits_per_word % 16 == 0) {
+				u16 *buf = (u16 *)drv_data->tx;
+				for (loop = 0; loop < bits_per_word / 16;
+						loop++) {
+					write_TDBR(drv_data, *buf++);
+				}
+			} else if (bits_per_word % 8 == 0) {
+				u8 *buf = (u8 *)drv_data->tx;
+				for (loop = 0; loop < bits_per_word / 8; loop++)
+					write_TDBR(drv_data, *buf++);
+			}
+
 			drv_data->tx += drv_data->n_bytes;
 		}
 
@@ -1031,7 +1071,7 @@ static int bfin_spi_setup(struct spi_device *spi)
 		chip->ctl_reg &= bfin_ctl_reg;
 	}
 
-	if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+	if (spi->bits_per_word % 8) {
 		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
 				spi->bits_per_word);
 		goto error;
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c
index 8b55724..14a63f6 100644
--- a/drivers/spi/spi_bitbang.c
+++ b/drivers/spi/spi_bitbang.c
@@ -259,10 +259,6 @@ static void bitbang_work(struct work_struct *work)
 	struct spi_bitbang	*bitbang =
 		container_of(work, struct spi_bitbang, work);
 	unsigned long		flags;
-	int			(*setup_transfer)(struct spi_device *,
-					struct spi_transfer *);
-
-	setup_transfer = bitbang->setup_transfer;
 
 	spin_lock_irqsave(&bitbang->lock, flags);
 	bitbang->busy = 1;
@@ -300,11 +296,7 @@ static void bitbang_work(struct work_struct *work)
 
 			/* init (-1) or override (1) transfer params */
 			if (do_setup != 0) {
-				if (!setup_transfer) {
-					status = -ENOPROTOOPT;
-					break;
-				}
-				status = setup_transfer(spi, t);
+				status = bitbang->setup_transfer(spi, t);
 				if (status < 0)
 					break;
 				if (do_setup == -1)
@@ -465,6 +457,9 @@ int spi_bitbang_start(struct spi_bitbang *bitbang)
 		}
 	} else if (!bitbang->master->setup)
 		return -EINVAL;
+	if (bitbang->master->transfer == spi_bitbang_transfer &&
+			!bitbang->setup_transfer)
+		return -EINVAL;
 
 	/* this task is the only thing to touch the SPI bits */
 	bitbang->busy = 0;
diff --git a/drivers/spi/spi_fsl_espi.c b/drivers/spi/spi_fsl_espi.c
index a99e233..900e921 100644
--- a/drivers/spi/spi_fsl_espi.c
+++ b/drivers/spi/spi_fsl_espi.c
@@ -685,8 +685,7 @@ static int of_fsl_espi_get_chipselects(struct device *dev)
 	return 0;
 }
 
-static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
-					const struct of_device_id *ofid)
+static int __devinit of_fsl_espi_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -695,7 +694,7 @@ static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
 	struct resource irq;
 	int ret = -ENOMEM;
 
-	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	ret = of_mpc8xxx_spi_probe(ofdev);
 	if (ret)
 		return ret;
 
@@ -736,7 +735,7 @@ static const struct of_device_id of_fsl_espi_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
 
-static struct of_platform_driver fsl_espi_driver = {
+static struct platform_driver fsl_espi_driver = {
 	.driver = {
 		.name = "fsl_espi",
 		.owner = THIS_MODULE,
@@ -748,13 +747,13 @@ static struct of_platform_driver fsl_espi_driver = {
 
 static int __init fsl_espi_init(void)
 {
-	return of_register_platform_driver(&fsl_espi_driver);
+	return platform_driver_register(&fsl_espi_driver);
 }
 module_init(fsl_espi_init);
 
 static void __exit fsl_espi_exit(void)
 {
-	of_unregister_platform_driver(&fsl_espi_driver);
+	platform_driver_unregister(&fsl_espi_driver);
 }
 module_exit(fsl_espi_exit);
 
diff --git a/drivers/spi/spi_fsl_lib.c b/drivers/spi/spi_fsl_lib.c
index 5cd741f..ff59f42 100644
--- a/drivers/spi/spi_fsl_lib.c
+++ b/drivers/spi/spi_fsl_lib.c
@@ -189,8 +189,7 @@ int __devexit mpc8xxx_spi_remove(struct device *dev)
 	return 0;
 }
 
-int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-					const struct of_device_id *ofid)
+int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
diff --git a/drivers/spi/spi_fsl_lib.h b/drivers/spi/spi_fsl_lib.h
index 281e060..cbe881b 100644
--- a/drivers/spi/spi_fsl_lib.h
+++ b/drivers/spi/spi_fsl_lib.h
@@ -118,7 +118,6 @@ extern const char *mpc8xxx_spi_strmode(unsigned int flags);
 extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
 		unsigned int irq);
 extern int mpc8xxx_spi_remove(struct device *dev);
-extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-				const struct of_device_id *ofid);
+extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
 
 #endif /* __SPI_FSL_LIB_H__ */
diff --git a/drivers/spi/spi_fsl_spi.c b/drivers/spi/spi_fsl_spi.c
index 7ca52d3..7963c9b 100644
--- a/drivers/spi/spi_fsl_spi.c
+++ b/drivers/spi/spi_fsl_spi.c
@@ -1042,8 +1042,7 @@ static int of_fsl_spi_free_chipselects(struct device *dev)
 	return 0;
 }
 
-static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
-					const struct of_device_id *ofid)
+static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -1052,7 +1051,7 @@ static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
 	struct resource irq;
 	int ret = -ENOMEM;
 
-	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	ret = of_mpc8xxx_spi_probe(ofdev);
 	if (ret)
 		return ret;
 
@@ -1100,7 +1099,7 @@ static const struct of_device_id of_fsl_spi_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
 
-static struct of_platform_driver of_fsl_spi_driver = {
+static struct platform_driver of_fsl_spi_driver = {
 	.driver = {
 		.name = "fsl_spi",
 		.owner = THIS_MODULE,
@@ -1177,13 +1176,13 @@ static void __exit legacy_driver_unregister(void) {}
 static int __init fsl_spi_init(void)
 {
 	legacy_driver_register();
-	return of_register_platform_driver(&of_fsl_spi_driver);
+	return platform_driver_register(&of_fsl_spi_driver);
 }
 module_init(fsl_spi_init);
 
 static void __exit fsl_spi_exit(void)
 {
-	of_unregister_platform_driver(&of_fsl_spi_driver);
+	platform_driver_unregister(&of_fsl_spi_driver);
 	legacy_driver_unregister();
 }
 module_exit(fsl_spi_exit);
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
index 1cf9d5f..69d6dba 100644
--- a/drivers/spi/spi_imx.c
+++ b/drivers/spi/spi_imx.c
@@ -174,7 +174,7 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 #define SPI_IMX2_3_CTRL		0x08
 #define SPI_IMX2_3_CTRL_ENABLE		(1 <<  0)
 #define SPI_IMX2_3_CTRL_XCH		(1 <<  2)
-#define SPI_IMX2_3_CTRL_MODE(cs)	(1 << ((cs) +  4))
+#define SPI_IMX2_3_CTRL_MODE_MASK	(0xf << 4)
 #define SPI_IMX2_3_CTRL_POSTDIV_OFFSET	8
 #define SPI_IMX2_3_CTRL_PREDIV_OFFSET	12
 #define SPI_IMX2_3_CTRL_CS(cs)		((cs) << 18)
@@ -253,8 +253,14 @@ static int __maybe_unused spi_imx2_3_config(struct spi_imx_data *spi_imx,
 {
 	u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
 
-	/* set master mode */
-	ctrl |= SPI_IMX2_3_CTRL_MODE(config->cs);
+	/*
+	 * The hardware seems to have a race condition when changing modes. The
+	 * current assumption is that the selection of the channel arrives
+	 * earlier in the hardware than the mode bits when they are written at
+	 * the same time.
+	 * So set master mode for all channels as we do not support slave mode.
+	 */
+	ctrl |= SPI_IMX2_3_CTRL_MODE_MASK;
 
 	/* set clock speed */
 	ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
diff --git a/drivers/spi/spi_oc_tiny.c b/drivers/spi/spi_oc_tiny.c
new file mode 100644
index 0000000..f1bde66
--- /dev/null
+++ b/drivers/spi/spi_oc_tiny.c
@@ -0,0 +1,425 @@
+/*
+ * OpenCores tiny SPI master driver
+ *
+ * http://opencores.org/project,tiny_spi
+ *
+ * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on spi_s3c24xx.c, which is:
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_oc_tiny.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+
+#define DRV_NAME "spi_oc_tiny"
+
+#define TINY_SPI_RXDATA 0
+#define TINY_SPI_TXDATA 4
+#define TINY_SPI_STATUS 8
+#define TINY_SPI_CONTROL 12
+#define TINY_SPI_BAUD 16
+
+#define TINY_SPI_STATUS_TXE 0x1
+#define TINY_SPI_STATUS_TXR 0x2
+
+struct tiny_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem *base;
+	int irq;
+	unsigned int freq;
+	unsigned int baudwidth;
+	unsigned int baud;
+	unsigned int speed_hz;
+	unsigned int mode;
+	unsigned int len;
+	unsigned int txc, rxc;
+	const u8 *txp;
+	u8 *rxp;
+	unsigned int gpio_cs_count;
+	int *gpio_cs;
+};
+
+static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1;
+}
+
+static void tiny_spi_chipselect(struct spi_device *spi, int is_active)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	if (hw->gpio_cs_count) {
+		gpio_set_value(hw->gpio_cs[spi->chip_select],
+			(spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+	}
+}
+
+static int tiny_spi_setup_transfer(struct spi_device *spi,
+				   struct spi_transfer *t)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+	unsigned int baud = hw->baud;
+
+	if (t) {
+		if (t->speed_hz && t->speed_hz != hw->speed_hz)
+			baud = tiny_spi_baud(spi, t->speed_hz);
+	}
+	writel(baud, hw->base + TINY_SPI_BAUD);
+	writel(hw->mode, hw->base + TINY_SPI_CONTROL);
+	return 0;
+}
+
+static int tiny_spi_setup(struct spi_device *spi)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	if (spi->max_speed_hz != hw->speed_hz) {
+		hw->speed_hz = spi->max_speed_hz;
+		hw->baud = tiny_spi_baud(spi, hw->speed_hz);
+	}
+	hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA);
+	return 0;
+}
+
+static inline void tiny_spi_wait_txr(struct tiny_spi *hw)
+{
+	while (!(readb(hw->base + TINY_SPI_STATUS) &
+		 TINY_SPI_STATUS_TXR))
+		cpu_relax();
+}
+
+static inline void tiny_spi_wait_txe(struct tiny_spi *hw)
+{
+	while (!(readb(hw->base + TINY_SPI_STATUS) &
+		 TINY_SPI_STATUS_TXE))
+		cpu_relax();
+}
+
+static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+	const u8 *txp = t->tx_buf;
+	u8 *rxp = t->rx_buf;
+	unsigned int i;
+
+	if (hw->irq >= 0) {
+		/* use intrrupt driven data transfer */
+		hw->len = t->len;
+		hw->txp = t->tx_buf;
+		hw->rxp = t->rx_buf;
+		hw->txc = 0;
+		hw->rxc = 0;
+
+		/* send the first byte */
+		if (t->len > 1) {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
+		} else {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
+		}
+
+		wait_for_completion(&hw->done);
+	} else if (txp && rxp) {
+		/* we need to tighten the transfer loop */
+		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 rx, tx = *txp++;
+				tiny_spi_wait_txr(hw);
+				rx = readb(hw->base + TINY_SPI_TXDATA);
+				writeb(tx, hw->base + TINY_SPI_TXDATA);
+				*rxp++ = rx;
+			}
+			tiny_spi_wait_txr(hw);
+			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		}
+		tiny_spi_wait_txe(hw);
+		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+	} else if (rxp) {
+		writeb(0, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(0,
+			       hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 rx;
+				tiny_spi_wait_txr(hw);
+				rx = readb(hw->base + TINY_SPI_TXDATA);
+				writeb(0, hw->base + TINY_SPI_TXDATA);
+				*rxp++ = rx;
+			}
+			tiny_spi_wait_txr(hw);
+			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		}
+		tiny_spi_wait_txe(hw);
+		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+	} else if (txp) {
+		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 tx = *txp++;
+				tiny_spi_wait_txr(hw);
+				writeb(tx, hw->base + TINY_SPI_TXDATA);
+			}
+		}
+		tiny_spi_wait_txe(hw);
+	} else {
+		writeb(0, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(0, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				tiny_spi_wait_txr(hw);
+				writeb(0, hw->base + TINY_SPI_TXDATA);
+			}
+		}
+		tiny_spi_wait_txe(hw);
+	}
+	return t->len;
+}
+
+static irqreturn_t tiny_spi_irq(int irq, void *dev)
+{
+	struct tiny_spi *hw = dev;
+
+	writeb(0, hw->base + TINY_SPI_STATUS);
+	if (hw->rxc + 1 == hw->len) {
+		if (hw->rxp)
+			*hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+		hw->rxc++;
+		complete(&hw->done);
+	} else {
+		if (hw->rxp)
+			*hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		hw->rxc++;
+		if (hw->txc < hw->len) {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXR,
+			       hw->base + TINY_SPI_STATUS);
+		} else {
+			writeb(TINY_SPI_STATUS_TXE,
+			       hw->base + TINY_SPI_STATUS);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+
+static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+{
+	struct tiny_spi *hw = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int i;
+	const __be32 *val;
+	int len;
+
+	if (!np)
+		return 0;
+	hw->gpio_cs_count = of_gpio_count(np);
+	if (hw->gpio_cs_count) {
+		hw->gpio_cs = devm_kzalloc(&pdev->dev,
+				hw->gpio_cs_count * sizeof(unsigned int),
+				GFP_KERNEL);
+		if (!hw->gpio_cs)
+			return -ENOMEM;
+	}
+	for (i = 0; i < hw->gpio_cs_count; i++) {
+		hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL);
+		if (hw->gpio_cs[i] < 0)
+			return -ENODEV;
+	}
+	hw->bitbang.master->dev.of_node = pdev->dev.of_node;
+	val = of_get_property(pdev->dev.of_node,
+			      "clock-frequency", &len);
+	if (val && len >= sizeof(__be32))
+		hw->freq = be32_to_cpup(val);
+	val = of_get_property(pdev->dev.of_node, "baud-width", &len);
+	if (val && len >= sizeof(__be32))
+		hw->baudwidth = be32_to_cpup(val);
+	return 0;
+}
+#else /* !CONFIG_OF */
+static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif /* CONFIG_OF */
+
+static int __devinit tiny_spi_probe(struct platform_device *pdev)
+{
+	struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
+	struct tiny_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	unsigned int i;
+	int err = -ENODEV;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
+	if (!master)
+		return err;
+
+	/* setup the master state. */
+	master->bus_num = pdev->id;
+	master->num_chipselect = 255;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	master->setup = tiny_spi_setup;
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	/* setup the state for the bitbang driver */
+	hw->bitbang.master = spi_master_get(master);
+	if (!hw->bitbang.master)
+		return err;
+	hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
+	hw->bitbang.chipselect = tiny_spi_chipselect;
+	hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
+
+	/* find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     pdev->name))
+		goto exit_busy;
+	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!hw->base)
+		goto exit_busy;
+	/* irq is optional */
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq >= 0) {
+		init_completion(&hw->done);
+		err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0,
+				       pdev->name, hw);
+		if (err)
+			goto exit;
+	}
+	/* find platform data */
+	if (platp) {
+		hw->gpio_cs_count = platp->gpio_cs_count;
+		hw->gpio_cs = platp->gpio_cs;
+		if (platp->gpio_cs_count && !platp->gpio_cs)
+			goto exit_busy;
+		hw->freq = platp->freq;
+		hw->baudwidth = platp->baudwidth;
+	} else {
+		err = tiny_spi_of_probe(pdev);
+		if (err)
+			goto exit;
+	}
+	for (i = 0; i < hw->gpio_cs_count; i++) {
+		err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev));
+		if (err)
+			goto exit_gpio;
+		gpio_direction_output(hw->gpio_cs[i], 1);
+	}
+	hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count);
+
+	/* register our spi controller */
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err)
+		goto exit;
+	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
+
+	return 0;
+
+exit_gpio:
+	while (i-- > 0)
+		gpio_free(hw->gpio_cs[i]);
+exit_busy:
+	err = -EBUSY;
+exit:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return err;
+}
+
+static int __devexit tiny_spi_remove(struct platform_device *pdev)
+{
+	struct tiny_spi *hw = platform_get_drvdata(pdev);
+	struct spi_master *master = hw->bitbang.master;
+	unsigned int i;
+
+	spi_bitbang_stop(&hw->bitbang);
+	for (i = 0; i < hw->gpio_cs_count; i++)
+		gpio_free(hw->gpio_cs[i]);
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id tiny_spi_match[] = {
+	{ .compatible = "opencores,tiny-spi-rtlsvn2", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tiny_spi_match);
+#else /* CONFIG_OF */
+#define tiny_spi_match NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver tiny_spi_driver = {
+	.probe = tiny_spi_probe,
+	.remove = __devexit_p(tiny_spi_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = NULL,
+		.of_match_table = tiny_spi_match,
+	},
+};
+
+static int __init tiny_spi_init(void)
+{
+	return platform_driver_register(&tiny_spi_driver);
+}
+module_init(tiny_spi_init);
+
+static void __exit tiny_spi_exit(void)
+{
+	platform_driver_unregister(&tiny_spi_driver);
+}
+module_exit(tiny_spi_exit);
+
+MODULE_DESCRIPTION("OpenCores tiny SPI driver");
+MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/spi/spi_ppc4xx.c b/drivers/spi/spi_ppc4xx.c
index 80e172d..2a298c0 100644
--- a/drivers/spi/spi_ppc4xx.c
+++ b/drivers/spi/spi_ppc4xx.c
@@ -390,8 +390,7 @@ static void free_gpios(struct ppc4xx_spi *hw)
 /*
  * platform_device layer stuff...
  */
-static int __init spi_ppc4xx_of_probe(struct platform_device *op,
-				      const struct of_device_id *match)
+static int __init spi_ppc4xx_of_probe(struct platform_device *op)
 {
 	struct ppc4xx_spi *hw;
 	struct spi_master *master;
@@ -586,7 +585,7 @@ static const struct of_device_id spi_ppc4xx_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match);
 
-static struct of_platform_driver spi_ppc4xx_of_driver = {
+static struct platform_driver spi_ppc4xx_of_driver = {
 	.probe = spi_ppc4xx_of_probe,
 	.remove = __exit_p(spi_ppc4xx_of_remove),
 	.driver = {
@@ -598,13 +597,13 @@ static struct of_platform_driver spi_ppc4xx_of_driver = {
 
 static int __init spi_ppc4xx_init(void)
 {
-	return of_register_platform_driver(&spi_ppc4xx_of_driver);
+	return platform_driver_register(&spi_ppc4xx_of_driver);
 }
 module_init(spi_ppc4xx_init);
 
 static void __exit spi_ppc4xx_exit(void)
 {
-	of_unregister_platform_driver(&spi_ppc4xx_of_driver);
+	platform_driver_unregister(&spi_ppc4xx_of_driver);
 }
 module_exit(spi_ppc4xx_exit);
 
diff --git a/drivers/spi/spi_sh.c b/drivers/spi/spi_sh.c
new file mode 100644
index 0000000..869a07d
--- /dev/null
+++ b/drivers/spi/spi_sh.c
@@ -0,0 +1,543 @@
+/*
+ * SH SPI bus driver
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ *
+ * Based on pxa2xx_spi.c:
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound Labs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+
+#define SPI_SH_TBR		0x00
+#define SPI_SH_RBR		0x00
+#define SPI_SH_CR1		0x08
+#define SPI_SH_CR2		0x10
+#define SPI_SH_CR3		0x18
+#define SPI_SH_CR4		0x20
+#define SPI_SH_CR5		0x28
+
+/* CR1 */
+#define SPI_SH_TBE		0x80
+#define SPI_SH_TBF		0x40
+#define SPI_SH_RBE		0x20
+#define SPI_SH_RBF		0x10
+#define SPI_SH_PFONRD		0x08
+#define SPI_SH_SSDB		0x04
+#define SPI_SH_SSD		0x02
+#define SPI_SH_SSA		0x01
+
+/* CR2 */
+#define SPI_SH_RSTF		0x80
+#define SPI_SH_LOOPBK		0x40
+#define SPI_SH_CPOL		0x20
+#define SPI_SH_CPHA		0x10
+#define SPI_SH_L1M0		0x08
+
+/* CR3 */
+#define SPI_SH_MAX_BYTE		0xFF
+
+/* CR4 */
+#define SPI_SH_TBEI		0x80
+#define SPI_SH_TBFI		0x40
+#define SPI_SH_RBEI		0x20
+#define SPI_SH_RBFI		0x10
+#define SPI_SH_WPABRT		0x04
+#define SPI_SH_SSS		0x01
+
+/* CR8 */
+#define SPI_SH_P1L0		0x80
+#define SPI_SH_PP1L0		0x40
+#define SPI_SH_MUXI		0x20
+#define SPI_SH_MUXIRQ		0x10
+
+#define SPI_SH_FIFO_SIZE	32
+#define SPI_SH_SEND_TIMEOUT	(3 * HZ)
+#define SPI_SH_RECEIVE_TIMEOUT	(HZ >> 3)
+
+#undef DEBUG
+
+struct spi_sh_data {
+	void __iomem *addr;
+	int irq;
+	struct spi_master *master;
+	struct list_head queue;
+	struct workqueue_struct *workqueue;
+	struct work_struct ws;
+	unsigned long cr1;
+	wait_queue_head_t wait;
+	spinlock_t lock;
+};
+
+static void spi_sh_write(struct spi_sh_data *ss, unsigned long data,
+			     unsigned long offset)
+{
+	writel(data, ss->addr + offset);
+}
+
+static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset)
+{
+	return readl(ss->addr + offset);
+}
+
+static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val,
+				unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = spi_sh_read(ss, offset);
+	tmp |= val;
+	spi_sh_write(ss, tmp, offset);
+}
+
+static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val,
+				unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = spi_sh_read(ss, offset);
+	tmp &= ~val;
+	spi_sh_write(ss, tmp, offset);
+}
+
+static void clear_fifo(struct spi_sh_data *ss)
+{
+	spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
+	spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
+}
+
+static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss)
+{
+	int timeout = 100000;
+
+	while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
+		udelay(10);
+		if (timeout-- < 0)
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss)
+{
+	int timeout = 100000;
+
+	while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) {
+		udelay(10);
+		if (timeout-- < 0)
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
+			struct spi_transfer *t)
+{
+	int i, retval = 0;
+	int remain = t->len;
+	int cur_len;
+	unsigned char *data;
+	unsigned long tmp;
+	long ret;
+
+	if (t->len)
+		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	data = (unsigned char *)t->tx_buf;
+	while (remain > 0) {
+		cur_len = min(SPI_SH_FIFO_SIZE, remain);
+		for (i = 0; i < cur_len &&
+				!(spi_sh_read(ss, SPI_SH_CR4) &
+							SPI_SH_WPABRT) &&
+				!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF);
+				i++)
+			spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR);
+
+		if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) {
+			/* Abort SPI operation */
+			spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4);
+			retval = -EIO;
+			break;
+		}
+
+		cur_len = i;
+
+		remain -= cur_len;
+		data += cur_len;
+
+		if (remain > 0) {
+			ss->cr1 &= ~SPI_SH_TBE;
+			spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
+			ret = wait_event_interruptible_timeout(ss->wait,
+						 ss->cr1 & SPI_SH_TBE,
+						 SPI_SH_SEND_TIMEOUT);
+			if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) {
+				printk(KERN_ERR "%s: timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+		}
+	}
+
+	if (list_is_last(&t->transfer_list, &mesg->transfers)) {
+		tmp = spi_sh_read(ss, SPI_SH_CR1);
+		tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
+		spi_sh_write(ss, tmp, SPI_SH_CR1);
+		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+		ss->cr1 &= ~SPI_SH_TBE;
+		spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
+		ret = wait_event_interruptible_timeout(ss->wait,
+					 ss->cr1 & SPI_SH_TBE,
+					 SPI_SH_SEND_TIMEOUT);
+		if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) {
+			printk(KERN_ERR "%s: timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return retval;
+}
+
+static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
+			  struct spi_transfer *t)
+{
+	int i;
+	int remain = t->len;
+	int cur_len;
+	unsigned char *data;
+	unsigned long tmp;
+	long ret;
+
+	if (t->len > SPI_SH_MAX_BYTE)
+		spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3);
+	else
+		spi_sh_write(ss, t->len, SPI_SH_CR3);
+
+	tmp = spi_sh_read(ss, SPI_SH_CR1);
+	tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
+	spi_sh_write(ss, tmp, SPI_SH_CR1);
+	spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	spi_sh_wait_write_buffer_empty(ss);
+
+	data = (unsigned char *)t->rx_buf;
+	while (remain > 0) {
+		if (remain >= SPI_SH_FIFO_SIZE) {
+			ss->cr1 &= ~SPI_SH_RBF;
+			spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4);
+			ret = wait_event_interruptible_timeout(ss->wait,
+						 ss->cr1 & SPI_SH_RBF,
+						 SPI_SH_RECEIVE_TIMEOUT);
+			if (ret == 0 &&
+			    spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
+				printk(KERN_ERR "%s: timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+		}
+
+		cur_len = min(SPI_SH_FIFO_SIZE, remain);
+		for (i = 0; i < cur_len; i++) {
+			if (spi_sh_wait_receive_buffer(ss))
+				break;
+			data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR);
+		}
+
+		remain -= cur_len;
+		data += cur_len;
+	}
+
+	/* deassert CS when SPI is receiving. */
+	if (t->len > SPI_SH_MAX_BYTE) {
+		clear_fifo(ss);
+		spi_sh_write(ss, 1, SPI_SH_CR3);
+	} else {
+		spi_sh_write(ss, 0, SPI_SH_CR3);
+	}
+
+	return 0;
+}
+
+static void spi_sh_work(struct work_struct *work)
+{
+	struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws);
+	struct spi_message *mesg;
+	struct spi_transfer *t;
+	unsigned long flags;
+	int ret;
+
+	pr_debug("%s: enter\n", __func__);
+
+	spin_lock_irqsave(&ss->lock, flags);
+	while (!list_empty(&ss->queue)) {
+		mesg = list_entry(ss->queue.next, struct spi_message, queue);
+		list_del_init(&mesg->queue);
+
+		spin_unlock_irqrestore(&ss->lock, flags);
+		list_for_each_entry(t, &mesg->transfers, transfer_list) {
+			pr_debug("tx_buf = %p, rx_buf = %p\n",
+					t->tx_buf, t->rx_buf);
+			pr_debug("len = %d, delay_usecs = %d\n",
+					t->len, t->delay_usecs);
+
+			if (t->tx_buf) {
+				ret = spi_sh_send(ss, mesg, t);
+				if (ret < 0)
+					goto error;
+			}
+			if (t->rx_buf) {
+				ret = spi_sh_receive(ss, mesg, t);
+				if (ret < 0)
+					goto error;
+			}
+			mesg->actual_length += t->len;
+		}
+		spin_lock_irqsave(&ss->lock, flags);
+
+		mesg->status = 0;
+		mesg->complete(mesg->context);
+	}
+
+	clear_fifo(ss);
+	spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1);
+	udelay(100);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+
+	clear_fifo(ss);
+
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return;
+
+ error:
+	mesg->status = ret;
+	mesg->complete(mesg->context);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+	clear_fifo(ss);
+
+}
+
+static int spi_sh_setup(struct spi_device *spi)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	pr_debug("%s: enter\n", __func__);
+
+	spi_sh_write(ss, 0xfe, SPI_SH_CR1);	/* SPI sycle stop */
+	spi_sh_write(ss, 0x00, SPI_SH_CR1);	/* CR1 init */
+	spi_sh_write(ss, 0x00, SPI_SH_CR3);	/* CR3 init */
+
+	clear_fifo(ss);
+
+	/* 1/8 clock */
+	spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2);
+	udelay(10);
+
+	return 0;
+}
+
+static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	pr_debug("%s: enter\n", __func__);
+	pr_debug("\tmode = %02x\n", spi->mode);
+
+	spin_lock_irqsave(&ss->lock, flags);
+
+	mesg->actual_length = 0;
+	mesg->status = -EINPROGRESS;
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	list_add_tail(&mesg->queue, &ss->queue);
+	queue_work(ss->workqueue, &ss->ws);
+
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return 0;
+}
+
+static void spi_sh_cleanup(struct spi_device *spi)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+
+	pr_debug("%s: enter\n", __func__);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+}
+
+static irqreturn_t spi_sh_irq(int irq, void *_ss)
+{
+	struct spi_sh_data *ss = (struct spi_sh_data *)_ss;
+	unsigned long cr1;
+
+	cr1 = spi_sh_read(ss, SPI_SH_CR1);
+	if (cr1 & SPI_SH_TBE)
+		ss->cr1 |= SPI_SH_TBE;
+	if (cr1 & SPI_SH_TBF)
+		ss->cr1 |= SPI_SH_TBF;
+	if (cr1 & SPI_SH_RBE)
+		ss->cr1 |= SPI_SH_RBE;
+	if (cr1 & SPI_SH_RBF)
+		ss->cr1 |= SPI_SH_RBF;
+
+	if (ss->cr1) {
+		spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4);
+		wake_up(&ss->wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devexit spi_sh_remove(struct platform_device *pdev)
+{
+	struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev);
+
+	destroy_workqueue(ss->workqueue);
+	free_irq(ss->irq, ss);
+	iounmap(ss->addr);
+	spi_master_put(ss->master);
+
+	return 0;
+}
+
+static int __devinit spi_sh_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct spi_master *master;
+	struct spi_sh_data *ss;
+	int ret, irq;
+
+	/* get base addr */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(res == NULL)) {
+		dev_err(&pdev->dev, "invalid resource\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "platform_get_irq error\n");
+		return -ENODEV;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "spi_alloc_master error.\n");
+		return -ENOMEM;
+	}
+
+	ss = spi_master_get_devdata(master);
+	dev_set_drvdata(&pdev->dev, ss);
+
+	ss->irq = irq;
+	ss->master = master;
+	ss->addr = ioremap(res->start, resource_size(res));
+	if (ss->addr == NULL) {
+		dev_err(&pdev->dev, "ioremap error.\n");
+		ret = -ENOMEM;
+		goto error1;
+	}
+	INIT_LIST_HEAD(&ss->queue);
+	spin_lock_init(&ss->lock);
+	INIT_WORK(&ss->ws, spi_sh_work);
+	init_waitqueue_head(&ss->wait);
+	ss->workqueue = create_singlethread_workqueue(
+					dev_name(master->dev.parent));
+	if (ss->workqueue == NULL) {
+		dev_err(&pdev->dev, "create workqueue error\n");
+		ret = -EBUSY;
+		goto error2;
+	}
+
+	ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "request_irq error\n");
+		goto error3;
+	}
+
+	master->num_chipselect = 2;
+	master->bus_num = pdev->id;
+	master->setup = spi_sh_setup;
+	master->transfer = spi_sh_transfer;
+	master->cleanup = spi_sh_cleanup;
+
+	ret = spi_register_master(master);
+	if (ret < 0) {
+		printk(KERN_ERR "spi_register_master error.\n");
+		goto error4;
+	}
+
+	return 0;
+
+ error4:
+	free_irq(irq, ss);
+ error3:
+	destroy_workqueue(ss->workqueue);
+ error2:
+	iounmap(ss->addr);
+ error1:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static struct platform_driver spi_sh_driver = {
+	.probe = spi_sh_probe,
+	.remove = __devexit_p(spi_sh_remove),
+	.driver = {
+		.name = "sh_spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init spi_sh_init(void)
+{
+	return platform_driver_register(&spi_sh_driver);
+}
+module_init(spi_sh_init);
+
+static void __exit spi_sh_exit(void)
+{
+	platform_driver_unregister(&spi_sh_driver);
+}
+module_exit(spi_sh_exit);
+
+MODULE_DESCRIPTION("SH SPI bus driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:sh_spi");
diff --git a/drivers/spi/spi_sh_msiof.c b/drivers/spi/spi_sh_msiof.c
index 2c665fcea..e00d94b 100644
--- a/drivers/spi/spi_sh_msiof.c
+++ b/drivers/spi/spi_sh_msiof.c
@@ -9,22 +9,22 @@
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/platform_device.h>
-#include <linux/completion.h>
 #include <linux/pm_runtime.h>
-#include <linux/gpio.h>
-#include <linux/bitmap.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
 
+#include <linux/spi/sh_msiof.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
-#include <linux/spi/sh_msiof.h>
 
 #include <asm/unaligned.h>
 
@@ -67,7 +67,7 @@ struct sh_msiof_spi_priv {
 #define STR_TEOF  (1 << 23)
 #define STR_REOF  (1 << 7)
 
-static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
+static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
 {
 	switch (reg_offs) {
 	case TSCR:
@@ -79,7 +79,7 @@ static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
 }
 
 static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs,
-			   unsigned long value)
+			   u32 value)
 {
 	switch (reg_offs) {
 	case TSCR:
@@ -93,10 +93,10 @@ static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs,
 }
 
 static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p,
-				    unsigned long clr, unsigned long set)
+				    u32 clr, u32 set)
 {
-	unsigned long mask = clr | set;
-	unsigned long data;
+	u32 mask = clr | set;
+	u32 data;
 	int k;
 
 	data = sh_msiof_read(p, CTR);
@@ -166,10 +166,10 @@ static void sh_msiof_spi_set_clk_regs(struct sh_msiof_spi_priv *p,
 }
 
 static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
-				      int cpol, int cpha,
-				      int tx_hi_z, int lsb_first)
+				      u32 cpol, u32 cpha,
+				      u32 tx_hi_z, u32 lsb_first)
 {
-	unsigned long tmp;
+	u32 tmp;
 	int edge;
 
 	/*
@@ -187,7 +187,7 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
 	tmp |= cpol << 30; /* TSCKIZ */
 	tmp |= cpol << 28; /* RSCKIZ */
 
-	edge = cpol ? cpha : !cpha;
+	edge = cpol ^ !cpha;
 
 	tmp |= edge << 27; /* TEDG */
 	tmp |= edge << 26; /* REDG */
@@ -197,11 +197,9 @@ static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
 
 static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, void *rx_buf,
-				       int bits, int words)
+				       u32 bits, u32 words)
 {
-	unsigned long dr2;
-
-	dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
+	u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
 
 	if (tx_buf)
 		sh_msiof_write(p, TMDR2, dr2);
@@ -222,7 +220,7 @@ static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
 static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
 				      const void *tx_buf, int words, int fs)
 {
-	const unsigned char *buf_8 = tx_buf;
+	const u8 *buf_8 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -232,7 +230,7 @@ static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, int words, int fs)
 {
-	const unsigned short *buf_16 = tx_buf;
+	const u16 *buf_16 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -242,7 +240,7 @@ static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p,
 					const void *tx_buf, int words, int fs)
 {
-	const unsigned short *buf_16 = tx_buf;
+	const u16 *buf_16 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -252,7 +250,7 @@ static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, int words, int fs)
 {
-	const unsigned int *buf_32 = tx_buf;
+	const u32 *buf_32 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -262,17 +260,37 @@ static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p,
 					const void *tx_buf, int words, int fs)
 {
-	const unsigned int *buf_32 = tx_buf;
+	const u32 *buf_32 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
 		sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs);
 }
 
+static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p,
+					const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs));
+}
+
+static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p,
+					 const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs));
+}
+
 static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p,
 				     void *rx_buf, int words, int fs)
 {
-	unsigned char *buf_8 = rx_buf;
+	u8 *buf_8 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -282,7 +300,7 @@ static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p,
 				      void *rx_buf, int words, int fs)
 {
-	unsigned short *buf_16 = rx_buf;
+	u16 *buf_16 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -292,7 +310,7 @@ static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p,
 				       void *rx_buf, int words, int fs)
 {
-	unsigned short *buf_16 = rx_buf;
+	u16 *buf_16 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -302,7 +320,7 @@ static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p,
 				      void *rx_buf, int words, int fs)
 {
-	unsigned int *buf_32 = rx_buf;
+	u32 *buf_32 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -312,19 +330,40 @@ static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p,
 static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p,
 				       void *rx_buf, int words, int fs)
 {
-	unsigned int *buf_32 = rx_buf;
+	u32 *buf_32 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
 		put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]);
 }
 
+static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs);
+}
+
+static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
+}
+
 static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
 {
 	int bits;
 
 	bits = t ? t->bits_per_word : 0;
-	bits = bits ? bits : spi->bits_per_word;
+	if (!bits)
+		bits = spi->bits_per_word;
 	return bits;
 }
 
@@ -334,7 +373,8 @@ static unsigned long sh_msiof_spi_hz(struct spi_device *spi,
 	unsigned long hz;
 
 	hz = t ? t->speed_hz : 0;
-	hz = hz ? hz : spi->max_speed_hz;
+	if (!hz)
+		hz = spi->max_speed_hz;
 	return hz;
 }
 
@@ -468,9 +508,17 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 	int bytes_done;
 	int words;
 	int n;
+	bool swab;
 
 	bits = sh_msiof_spi_bits(spi, t);
 
+	if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
+		bits = 32;
+		swab = true;
+	} else {
+		swab = false;
+	}
+
 	/* setup bytes per word and fifo read/write functions */
 	if (bits <= 8) {
 		bytes_per_word = 1;
@@ -487,6 +535,17 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
 			rx_fifo = sh_msiof_spi_read_fifo_16u;
 		else
 			rx_fifo = sh_msiof_spi_read_fifo_16;
+	} else if (swab) {
+		bytes_per_word = 4;
+		if ((unsigned long)t->tx_buf & 0x03)
+			tx_fifo = sh_msiof_spi_write_fifo_s32u;
+		else
+			tx_fifo = sh_msiof_spi_write_fifo_s32;
+
+		if ((unsigned long)t->rx_buf & 0x03)
+			rx_fifo = sh_msiof_spi_read_fifo_s32u;
+		else
+			rx_fifo = sh_msiof_spi_read_fifo_s32;
 	} else {
 		bytes_per_word = 4;
 		if ((unsigned long)t->tx_buf & 0x03)
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 6034282..d9fd862 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -30,6 +30,7 @@
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/compat.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spidev.h>
@@ -471,6 +472,16 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	return retval;
 }
 
+#ifdef CONFIG_COMPAT
+static long
+spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#else
+#define spidev_compat_ioctl NULL
+#endif /* CONFIG_COMPAT */
+
 static int spidev_open(struct inode *inode, struct file *filp)
 {
 	struct spidev_data	*spidev;
@@ -543,6 +554,7 @@ static const struct file_operations spidev_fops = {
 	.write =	spidev_write,
 	.read =		spidev_read,
 	.unlocked_ioctl = spidev_ioctl,
+	.compat_ioctl = spidev_compat_ioctl,
 	.open =		spidev_open,
 	.release =	spidev_release,
 	.llseek =	no_llseek,
diff --git a/drivers/spi/ti-ssp-spi.c b/drivers/spi/ti-ssp-spi.c
new file mode 100644
index 0000000..ee22795
--- /dev/null
+++ b/drivers/spi/ti-ssp-spi.c
@@ -0,0 +1,402 @@
+/*
+ * Sequencer Serial Port (SSP) based SPI master driver
+ *
+ * Copyright (C) 2010 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/ti_ssp.h>
+
+#define MODE_BITS	(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
+
+struct ti_ssp_spi {
+	struct spi_master		*master;
+	struct device			*dev;
+	spinlock_t			lock;
+	struct list_head		msg_queue;
+	struct completion		complete;
+	bool				shutdown;
+	struct workqueue_struct		*workqueue;
+	struct work_struct		work;
+	u8				mode, bpw;
+	int				cs_active;
+	u32				pc_en, pc_dis, pc_wr, pc_rd;
+	void				(*select)(int cs);
+};
+
+static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
+{
+	u32 ret;
+
+	ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
+	return ret;
+}
+
+static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
+{
+	ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
+}
+
+static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
+		       struct spi_transfer *t)
+{
+	int count;
+
+	if (hw->bpw <= 8) {
+		u8		*rx = t->rx_buf;
+		const u8	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 1) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	} else if (hw->bpw <= 16) {
+		u16		*rx = t->rx_buf;
+		const u16	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 2) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	} else {
+		u32		*rx = t->rx_buf;
+		const u32	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 4) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	}
+
+	msg->actual_length += count; /* bytes transferred */
+
+	dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
+		t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
+		hw->bpw, count, (count < t->len) ? " (under)" : "");
+
+	return (count < t->len) ? -EIO : 0; /* left over data */
+}
+
+static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
+{
+	cs_active = !!cs_active;
+	if (cs_active == hw->cs_active)
+		return;
+	ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
+	hw->cs_active = cs_active;
+}
+
+#define __SHIFT_OUT(bits)	(SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
+				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
+#define __SHIFT_IN(bits)	(SSP_OPCODE_SHIFT | SSP_IN_MODE  | \
+				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
+
+static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
+{
+	int error, idx = 0;
+	u32 seqram[16];
+	u32 cs_en, cs_dis, clk;
+	u32 topbits, botbits;
+
+	mode &= MODE_BITS;
+	if (mode == hw->mode && bpw == hw->bpw)
+		return 0;
+
+	cs_en  = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
+	cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW  : SSP_CS_HIGH;
+	clk    = (mode & SPI_CPOL)    ? SSP_CLK_HIGH : SSP_CLK_LOW;
+
+	/* Construct instructions */
+
+	/* Disable Chip Select */
+	hw->pc_dis = idx;
+	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
+	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_dis | clk;
+
+	/* Enable Chip Select */
+	hw->pc_en = idx;
+	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
+	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_en | clk;
+
+	/* Reads and writes need to be split for bpw > 16 */
+	topbits = (bpw > 16) ? 16 : bpw;
+	botbits = bpw - topbits;
+
+	/* Write */
+	hw->pc_wr = idx;
+	seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
+	if (botbits)
+		seqram[idx++] = __SHIFT_OUT(botbits)  | SSP_DATA_REG;
+	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
+
+	/* Read */
+	hw->pc_rd = idx;
+	if (botbits)
+		seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
+	seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
+	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
+
+	error = ti_ssp_load(hw->dev, 0, seqram, idx);
+	if (error < 0)
+		return error;
+
+	error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
+					  0 : SSP_EARLY_DIN));
+	if (error < 0)
+		return error;
+
+	hw->bpw = bpw;
+	hw->mode = mode;
+
+	return error;
+}
+
+static void ti_ssp_spi_work(struct work_struct *work)
+{
+	struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
+
+	spin_lock(&hw->lock);
+
+	 while (!list_empty(&hw->msg_queue)) {
+		struct spi_message	*m;
+		struct spi_device	*spi;
+		struct spi_transfer	*t = NULL;
+		int			status = 0;
+
+		m = container_of(hw->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+
+		spin_unlock(&hw->lock);
+
+		spi = m->spi;
+
+		if (hw->select)
+			hw->select(spi->chip_select);
+
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			int bpw = spi->bits_per_word;
+			int xfer_status;
+
+			if (t->bits_per_word)
+				bpw = t->bits_per_word;
+
+			if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
+				break;
+
+			ti_ssp_spi_chip_select(hw, 1);
+
+			xfer_status = ti_ssp_spi_txrx(hw, m, t);
+			if (xfer_status < 0)
+				status = xfer_status;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (t->cs_change)
+				ti_ssp_spi_chip_select(hw, 0);
+		}
+
+		ti_ssp_spi_chip_select(hw, 0);
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock(&hw->lock);
+	}
+
+	if (hw->shutdown)
+		complete(&hw->complete);
+
+	spin_unlock(&hw->lock);
+}
+
+static int ti_ssp_spi_setup(struct spi_device *spi)
+{
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct ti_ssp_spi	*hw;
+	struct spi_transfer	*t;
+	int			error = 0;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	hw = spi_master_get_devdata(spi->master);
+
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->len && !(t->rx_buf || t->tx_buf)) {
+			dev_err(&spi->dev, "invalid xfer, no buffer\n");
+			return -EINVAL;
+		}
+
+		if (t->len && t->rx_buf && t->tx_buf) {
+			dev_err(&spi->dev, "invalid xfer, full duplex\n");
+			return -EINVAL;
+		}
+
+		if (t->bits_per_word > 32) {
+			dev_err(&spi->dev, "invalid xfer width %d\n",
+				t->bits_per_word);
+			return -EINVAL;
+		}
+	}
+
+	spin_lock(&hw->lock);
+	if (hw->shutdown) {
+		error = -ESHUTDOWN;
+		goto error_unlock;
+	}
+	list_add_tail(&m->queue, &hw->msg_queue);
+	queue_work(hw->workqueue, &hw->work);
+error_unlock:
+	spin_unlock(&hw->lock);
+	return error;
+}
+
+static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
+{
+	const struct ti_ssp_spi_data *pdata;
+	struct ti_ssp_spi *hw;
+	struct spi_master *master;
+	struct device *dev = &pdev->dev;
+	int error = 0;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(dev, "platform data not found\n");
+		return -EINVAL;
+	}
+
+	master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
+	if (!master) {
+		dev_err(dev, "cannot allocate SPI master\n");
+		return -ENOMEM;
+	}
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	hw->master = master;
+	hw->dev = dev;
+	hw->select = pdata->select;
+
+	spin_lock_init(&hw->lock);
+	init_completion(&hw->complete);
+	INIT_LIST_HEAD(&hw->msg_queue);
+	INIT_WORK(&hw->work, ti_ssp_spi_work);
+
+	hw->workqueue = create_singlethread_workqueue(dev_name(dev));
+	if (!hw->workqueue) {
+		error = -ENOMEM;
+		dev_err(dev, "work queue creation failed\n");
+		goto error_wq;
+	}
+
+	error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
+	if (error < 0) {
+		dev_err(dev, "io setup failed\n");
+		goto error_iosel;
+	}
+
+	master->bus_num		= pdev->id;
+	master->num_chipselect	= pdata->num_cs;
+	master->mode_bits	= MODE_BITS;
+	master->flags		= SPI_MASTER_HALF_DUPLEX;
+	master->setup		= ti_ssp_spi_setup;
+	master->transfer	= ti_ssp_spi_transfer;
+
+	error = spi_register_master(master);
+	if (error) {
+		dev_err(dev, "master registration failed\n");
+		goto error_reg;
+	}
+
+	return 0;
+
+error_reg:
+error_iosel:
+	destroy_workqueue(hw->workqueue);
+error_wq:
+	spi_master_put(master);
+	return error;
+}
+
+static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
+{
+	struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
+	int error;
+
+	hw->shutdown = 1;
+	while (!list_empty(&hw->msg_queue)) {
+		error = wait_for_completion_interruptible(&hw->complete);
+		if (error < 0) {
+			hw->shutdown = 0;
+			return error;
+		}
+	}
+	destroy_workqueue(hw->workqueue);
+	spi_unregister_master(hw->master);
+
+	return 0;
+}
+
+static struct platform_driver ti_ssp_spi_driver = {
+	.probe		= ti_ssp_spi_probe,
+	.remove		= __devexit_p(ti_ssp_spi_remove),
+	.driver		= {
+		.name	= "ti-ssp-spi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ti_ssp_spi_init(void)
+{
+	return platform_driver_register(&ti_ssp_spi_driver);
+}
+module_init(ti_ssp_spi_init);
+
+static void __exit ti_ssp_spi_exit(void)
+{
+	platform_driver_unregister(&ti_ssp_spi_driver);
+}
+module_exit(ti_ssp_spi_exit);
+
+MODULE_DESCRIPTION("SSP SPI Master");
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ti-ssp-spi");
diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c
index 7adaef6..4d2c75d 100644
--- a/drivers/spi/xilinx_spi.c
+++ b/drivers/spi/xilinx_spi.c
@@ -351,14 +351,12 @@ static irqreturn_t xilinx_spi_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id xilinx_spi_of_match[] = {
 	{ .compatible = "xlnx,xps-spi-2.00.a", },
 	{ .compatible = "xlnx,xps-spi-2.00.b", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-#endif
 
 struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 	u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
@@ -394,9 +392,7 @@ struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 
 	master->bus_num = bus_num;
 	master->num_chipselect = num_cs;
-#ifdef CONFIG_OF
 	master->dev.of_node = dev->of_node;
-#endif
 
 	xspi->mem = *mem;
 	xspi->irq = irq;
@@ -539,9 +535,7 @@ static struct platform_driver xilinx_spi_driver = {
 	.driver = {
 		.name = XILINX_SPI_NAME,
 		.owner = THIS_MODULE,
-#ifdef CONFIG_OF
 		.of_match_table = xilinx_spi_of_match,
-#endif
 	},
 };
 
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 3918d2c..e05ba6e 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -1192,10 +1192,10 @@ void ssb_device_enable(struct ssb_device *dev, u32 core_specific_flags)
 }
 EXPORT_SYMBOL(ssb_device_enable);
 
-/* Wait for a bit in a register to get set or unset.
+/* Wait for bitmask in a register to get set or cleared.
  * timeout is in units of ten-microseconds */
-static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
-			int timeout, int set)
+static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask,
+			 int timeout, int set)
 {
 	int i;
 	u32 val;
@@ -1203,7 +1203,7 @@ static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
 	for (i = 0; i < timeout; i++) {
 		val = ssb_read32(dev, reg);
 		if (set) {
-			if (val & bitmask)
+			if ((val & bitmask) == bitmask)
 				return 0;
 		} else {
 			if (!(val & bitmask))
@@ -1220,20 +1220,38 @@ static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
 
 void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
 {
-	u32 reject;
+	u32 reject, val;
 
 	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
 		return;
 
 	reject = ssb_tmslow_reject_bitmask(dev);
-	ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
-	ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1);
-	ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
-	ssb_write32(dev, SSB_TMSLOW,
-		    SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
-		    reject | SSB_TMSLOW_RESET |
-		    core_specific_flags);
-	ssb_flush_tmslow(dev);
+
+	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_CLOCK) {
+		ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
+		ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1);
+		ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
+
+		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) {
+			val = ssb_read32(dev, SSB_IMSTATE);
+			val |= SSB_IMSTATE_REJECT;
+			ssb_write32(dev, SSB_IMSTATE, val);
+			ssb_wait_bits(dev, SSB_IMSTATE, SSB_IMSTATE_BUSY, 1000,
+				      0);
+		}
+
+		ssb_write32(dev, SSB_TMSLOW,
+			SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+			reject | SSB_TMSLOW_RESET |
+			core_specific_flags);
+		ssb_flush_tmslow(dev);
+
+		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) {
+			val = ssb_read32(dev, SSB_IMSTATE);
+			val &= ~SSB_IMSTATE_REJECT;
+			ssb_write32(dev, SSB_IMSTATE, val);
+		}
+	}
 
 	ssb_write32(dev, SSB_TMSLOW,
 		    reject | SSB_TMSLOW_RESET |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 158449e..a467b20 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -468,10 +468,14 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in)
 		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
 	} else {
 		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+		SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
 	}
 	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 	     SSB_SPROM4_ANTAVAIL_A_SHIFT);
@@ -641,7 +645,7 @@ static int sprom_extract(struct ssb_bus *bus, struct ssb_sprom *out,
 		break;
 	default:
 		ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
-			   "  revision %d detected. Will extract"
+			   " revision %d detected. Will extract"
 			   " v1\n", out->revision);
 		out->revision = 1;
 		sprom_extract_r123(out, in);
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 5c8fcfc..ccaa200 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -41,6 +41,10 @@ config STAGING_EXCLUDE_BUILD
 
 if !STAGING_EXCLUDE_BUILD
 
+source "drivers/staging/tty/Kconfig"
+
+source "drivers/staging/generic_serial/Kconfig"
+
 source "drivers/staging/et131x/Kconfig"
 
 source "drivers/staging/slicoss/Kconfig"
@@ -87,12 +91,12 @@ source "drivers/staging/rtl8192e/Kconfig"
 
 source "drivers/staging/rtl8712/Kconfig"
 
+source "drivers/staging/rts_pstor/Kconfig"
+
 source "drivers/staging/frontier/Kconfig"
 
 source "drivers/staging/pohmelfs/Kconfig"
 
-source "drivers/staging/autofs/Kconfig"
-
 source "drivers/staging/phison/Kconfig"
 
 source "drivers/staging/line6/Kconfig"
@@ -127,6 +131,8 @@ source "drivers/staging/cs5535_gpio/Kconfig"
 
 source "drivers/staging/zram/Kconfig"
 
+source "drivers/staging/zcache/Kconfig"
+
 source "drivers/staging/wlags49_h2/Kconfig"
 
 source "drivers/staging/wlags49_h25/Kconfig"
@@ -141,16 +147,12 @@ source "drivers/staging/crystalhd/Kconfig"
 
 source "drivers/staging/cxt1e1/Kconfig"
 
-source "drivers/staging/ti-st/Kconfig"
-
 source "drivers/staging/xgifb/Kconfig"
 
 source "drivers/staging/msm/Kconfig"
 
 source "drivers/staging/lirc/Kconfig"
 
-source "drivers/staging/smbfs/Kconfig"
-
 source "drivers/staging/easycap/Kconfig"
 
 source "drivers/staging/solo6x10/Kconfig"
@@ -179,5 +181,7 @@ source "drivers/staging/cptm1217/Kconfig"
 
 source "drivers/staging/ste_rmi4/Kconfig"
 
+source "drivers/staging/gma500/Kconfig"
+
 endif # !STAGING_EXCLUDE_BUILD
 endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index d538863..3b223cb 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -3,6 +3,8 @@
 # fix for build system bug...
 obj-$(CONFIG_STAGING)		+= staging.o
 
+obj-y += tty/
+obj-y += generic_serial/
 obj-$(CONFIG_ET131X)		+= et131x/
 obj-$(CONFIG_SLICOSS)		+= slicoss/
 obj-$(CONFIG_VIDEO_GO7007)	+= go7007/
@@ -27,14 +29,13 @@ obj-$(CONFIG_R8187SE)		+= rtl8187se/
 obj-$(CONFIG_RTL8192U)		+= rtl8192u/
 obj-$(CONFIG_RTL8192E)		+= rtl8192e/
 obj-$(CONFIG_R8712U)		+= rtl8712/
+obj-$(CONFIG_RTS_PSTOR)		+= rts_pstor/
 obj-$(CONFIG_SPECTRA)		+= spectra/
 obj-$(CONFIG_TRANZPORT)		+= frontier/
 obj-$(CONFIG_POHMELFS)		+= pohmelfs/
-obj-$(CONFIG_AUTOFS_FS)		+= autofs/
 obj-$(CONFIG_IDE_PHISON)	+= phison/
 obj-$(CONFIG_LINE6_USB)		+= line6/
 obj-$(CONFIG_USB_SERIAL_QUATECH2)	+= serqt_usb2/
-obj-$(CONFIG_SMB_FS)		+= smbfs/
 obj-$(CONFIG_USB_SERIAL_QUATECH_USB2)	+= quatech_usb2/
 obj-$(CONFIG_OCTEON_ETHERNET)	+= octeon/
 obj-$(CONFIG_VT6655)		+= vt6655/
@@ -46,6 +47,8 @@ obj-$(CONFIG_DX_SEP)            += sep/
 obj-$(CONFIG_IIO)		+= iio/
 obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio/
 obj-$(CONFIG_ZRAM)		+= zram/
+obj-$(CONFIG_XVMALLOC)		+= zram/
+obj-$(CONFIG_ZCACHE)		+= zcache/
 obj-$(CONFIG_WLAGS49_H2)	+= wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)	+= wlags49_h25/
 obj-$(CONFIG_SAMSUNG_LAPTOP)	+= samsung-laptop/
@@ -53,7 +56,6 @@ obj-$(CONFIG_FB_SM7XX)		+= sm7xx/
 obj-$(CONFIG_VIDEO_DT3155)	+= dt3155v4l/
 obj-$(CONFIG_CRYSTALHD)		+= crystalhd/
 obj-$(CONFIG_CXT1E1)		+= cxt1e1/
-obj-$(CONFIG_TI_ST)		+= ti-st/
 obj-$(CONFIG_FB_XGI)		+= xgifb/
 obj-$(CONFIG_MSM_STAGING)	+= msm/
 obj-$(CONFIG_EASYCAP)		+= easycap/
@@ -61,12 +63,13 @@ obj-$(CONFIG_SOLO6X10)		+= solo6x10/
 obj-$(CONFIG_TIDSPBRIDGE)	+= tidspbridge/
 obj-$(CONFIG_ACPI_QUICKSTART)	+= quickstart/
 obj-$(CONFIG_WESTBRIDGE_ASTORIA)	+= westbridge/astoria/
-obj-$(CONFIG_SBE_2T3E3)	+= sbe-2t3e3/
+obj-$(CONFIG_SBE_2T3E3)		+= sbe-2t3e3/
 obj-$(CONFIG_ATH6K_LEGACY)	+= ath6kl/
 obj-$(CONFIG_USB_ENESTORAGE)	+= keucr/
-obj-$(CONFIG_BCM_WIMAX)	+= bcm/
+obj-$(CONFIG_BCM_WIMAX)		+= bcm/
 obj-$(CONFIG_FT1000)		+= ft1000/
-obj-$(CONFIG_SND_INTEL_SST)		+= intel_sst/
-obj-$(CONFIG_SPEAKUP)	+= speakup/
+obj-$(CONFIG_SND_INTEL_SST)	+= intel_sst/
+obj-$(CONFIG_SPEAKUP)		+= speakup/
 obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217)	+= cptm1217/
 obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4)	+= ste_rmi4/
+obj-$(CONFIG_DRM_PSB)		+= gma500/
diff --git a/drivers/staging/ath6kl/TODO b/drivers/staging/ath6kl/TODO
index d462927..019df4b 100644
--- a/drivers/staging/ath6kl/TODO
+++ b/drivers/staging/ath6kl/TODO
@@ -1,8 +1,25 @@
-- The driver is a stop-gap measure until a proper mac80211 driver is available.
-- The driver does not conform to the Linux coding style.
-- The driver has been tested on a wide variety of embedded platforms running different versions of the Linux kernel but may still have bringup/performance issues with a new platform.
-- Pls use the following link to get information about the driver's architecture, exposed APIs, supported features, limitations, testing, hardware availability and other details.
-	http://wireless.kernel.org/en/users/Drivers/ath6kl
-- Pls send any patches to
+TODO:
+
+We are working hard on cleaning up the driver. There's sooooooooo much todo
+so instead of editign this file please use the wiki:
+
+http://wireless.kernel.org/en/users/Drivers/ath6kl
+
+There's a respective TODO page there. Please also subscribe to the wiki page
+to get e-mail updates on changes.
+
+IRC:
+
+We *really* need to coordinate development for ath6kl as the cleanup
+patches will break pretty much any other patches. Please use IRC to
+help coordinate better:
+
+irc.freenode.net
+#ath6kl
+
+Send patches to:
+
 	- Greg Kroah-Hartman <greg@kroah.com>
-	- Vipin Mehta <vmehta@atheros.com>
+	- Luis R. Rodriguez <mcgrof@gmail.com>
+	- Joe Perches <joe@perches.com>
+	- Naveen Singh <nsingh@atheros.com>
diff --git a/drivers/staging/ath6kl/bmi/include/bmi_internal.h b/drivers/staging/ath6kl/bmi/include/bmi_internal.h
index a44027c..6ae2ea7 100644
--- a/drivers/staging/ath6kl/bmi/include/bmi_internal.h
+++ b/drivers/staging/ath6kl/bmi/include/bmi_internal.h
@@ -39,17 +39,17 @@
 #define BMI_COMMUNICATION_TIMEOUT       100000
 
 /* ------ Global Variable Declarations ------- */
-static A_BOOL bmiDone;
-
-A_STATUS
-bmiBufferSend(HIF_DEVICE *device,
-              A_UCHAR *buffer,
-              A_UINT32 length);
-
-A_STATUS
-bmiBufferReceive(HIF_DEVICE *device,
-                 A_UCHAR *buffer,
-                 A_UINT32 length,
-                 A_BOOL want_timeout);
+static bool bmiDone;
+
+int
+bmiBufferSend(struct hif_device *device,
+              u8 *buffer,
+              u32 length);
+
+int
+bmiBufferReceive(struct hif_device *device,
+                 u8 *buffer,
+                 u32 length,
+                 bool want_timeout);
 
 #endif
diff --git a/drivers/staging/ath6kl/bmi/src/bmi.c b/drivers/staging/ath6kl/bmi/src/bmi.c
index f17f563..9268bf3 100644
--- a/drivers/staging/ath6kl/bmi/src/bmi.c
+++ b/drivers/staging/ath6kl/bmi/src/bmi.c
@@ -33,7 +33,7 @@
 #include "bmi_internal.h"
 
 #ifdef ATH_DEBUG_MODULE
-static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
+static struct ath_debug_mask_description bmi_debug_desc[] = {
     { ATH_DEBUG_BMI , "BMI Tracing"},
 };
 
@@ -53,21 +53,21 @@ and does not use the HTC protocol nor even DMA -- it is intentionally kept
 very simple.
 */
 
-static A_BOOL pendingEventsFuncCheck = FALSE; 
-static A_UINT32 *pBMICmdCredits;
-static A_UCHAR *pBMICmdBuf;
+static bool pendingEventsFuncCheck = false;
+static u32 *pBMICmdCredits;
+static u8 *pBMICmdBuf;
 #define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
-                       sizeof(A_UINT32) /* cmd */ + \
-                       sizeof(A_UINT32) /* addr */ + \
-                       sizeof(A_UINT32))/* length */
+                       sizeof(u32) /* cmd */ + \
+                       sizeof(u32) /* addr */ + \
+                       sizeof(u32))/* length */
 #define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
     
 /* APIs visible to the driver */
 void
 BMIInit(void)
 {
-    bmiDone = FALSE;
-    pendingEventsFuncCheck = FALSE;
+    bmiDone = false;
+    pendingEventsFuncCheck = false;
 
     /*
      * On some platforms, it's not possible to DMA to a static variable
@@ -79,12 +79,12 @@ BMIInit(void)
      * bus stack.
      */
     if (!pBMICmdCredits) {
-        pBMICmdCredits = (A_UINT32 *)A_MALLOC_NOWAIT(4);
+        pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4);
         A_ASSERT(pBMICmdCredits);
     }
 
     if (!pBMICmdBuf) {
-        pBMICmdBuf = (A_UCHAR *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
+        pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
         A_ASSERT(pBMICmdBuf);
     }
     
@@ -105,23 +105,23 @@ BMICleanup(void)
     }
 }
 
-A_STATUS
-BMIDone(HIF_DEVICE *device)
+int
+BMIDone(struct hif_device *device)
 {
-    A_STATUS status;
-    A_UINT32 cid;
+    int status;
+    u32 cid;
 
     if (bmiDone) {
         AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
-        return A_OK;
+        return 0;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
-    bmiDone = TRUE;
+    bmiDone = true;
     cid = BMI_DONE;
 
-    status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
-    if (status != A_OK) {
+    status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
@@ -138,14 +138,14 @@ BMIDone(HIF_DEVICE *device)
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
+int
+BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
 {
-    A_STATUS status;
-    A_UINT32 cid;
+    int status;
+    u32 cid;
 
     if (bmiDone) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
@@ -155,24 +155,24 @@ BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
     cid = BMI_GET_TARGET_INFO;
 
-    status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
-    if (status != A_OK) {
+    status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
-                                                sizeof(targ_info->target_ver), TRUE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
+                                                sizeof(targ_info->target_ver), true);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
         return A_ERROR;
     }
 
     if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
         /* Determine how many bytes are in the Target's targ_info */
-        status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
-                                            sizeof(targ_info->target_info_byte_count), TRUE);
-        if (status != A_OK) {
+        status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count,
+                                            sizeof(targ_info->target_info_byte_count), true);
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
             return A_ERROR;
         }
@@ -185,9 +185,9 @@ BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
 
         /* Read the remainder of the targ_info */
         status = bmiBufferReceive(device,
-                        ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
-                        sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), TRUE);
-        if (status != A_OK) {
+                        ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
+                        sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
                         					targ_info->target_info_byte_count));
             return A_ERROR;
@@ -197,19 +197,19 @@ BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
         							targ_info->target_ver, targ_info->target_type));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIReadMemory(HIF_DEVICE *device,
-              A_UINT32 address,
-              A_UCHAR *buffer,
-              A_UINT32 length)
+int
+BMIReadMemory(struct hif_device *device,
+              u32 address,
+              u8 *buffer,
+              u32 length)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 remaining, rxlen;
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 remaining, rxlen;
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
@@ -231,44 +231,44 @@ BMIReadMemory(HIF_DEVICE *device,
     {
         rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
         offset = 0;
-        A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
         offset += sizeof(cid);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+        memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
         offset += sizeof(address);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
+        memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
         offset += sizeof(length);
 
         status = bmiBufferSend(device, pBMICmdBuf, offset);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
             return A_ERROR;
         }
-        status = bmiBufferReceive(device, pBMICmdBuf, rxlen, TRUE);
-        if (status != A_OK) {
+        status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true);
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
             return A_ERROR;
         }
-        A_MEMCPY(&buffer[length - remaining], pBMICmdBuf, rxlen);
+        memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen);
         remaining -= rxlen; address += rxlen;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIWriteMemory(HIF_DEVICE *device,
-               A_UINT32 address,
-               A_UCHAR *buffer,
-               A_UINT32 length)
+int
+BMIWriteMemory(struct hif_device *device,
+               u32 address,
+               u8 *buffer,
+               u32 length)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 remaining, txlen;
-    const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
-    A_UCHAR alignedBuffer[BMI_DATASZ_MAX];
-    A_UCHAR *src;
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 remaining, txlen;
+    const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
+    u8 alignedBuffer[BMI_DATASZ_MAX];
+    u8 *src;
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
@@ -300,16 +300,16 @@ BMIWriteMemory(HIF_DEVICE *device,
             txlen = (BMI_DATASZ_MAX - header);
         }
         offset = 0;
-        A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
         offset += sizeof(cid);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+        memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
         offset += sizeof(address);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
+        memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
         offset += sizeof(txlen);
-        A_MEMCPY(&(pBMICmdBuf[offset]), src, txlen);
+        memcpy(&(pBMICmdBuf[offset]), src, txlen);
         offset += txlen;
         status = bmiBufferSend(device, pBMICmdBuf, offset);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
             return A_ERROR;
         }
@@ -318,17 +318,17 @@ BMIWriteMemory(HIF_DEVICE *device,
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIExecute(HIF_DEVICE *device,
-           A_UINT32 address,
-           A_UINT32 *param)
+int
+BMIExecute(struct hif_device *device,
+           u32 address,
+           u32 *param)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
@@ -345,37 +345,37 @@ BMIExecute(HIF_DEVICE *device,
     cid = BMI_EXECUTE;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
-    A_MEMCPY(&(pBMICmdBuf[offset]), param, sizeof(*param));
+    memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
     offset += sizeof(*param);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), FALSE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
         return A_ERROR;
     }
 
-    A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
+    memcpy(param, pBMICmdBuf, sizeof(*param));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMISetAppStart(HIF_DEVICE *device,
-               A_UINT32 address)
+int
+BMISetAppStart(struct hif_device *device,
+               u32 address)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
@@ -392,28 +392,28 @@ BMISetAppStart(HIF_DEVICE *device,
     cid = BMI_SET_APP_START;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIReadSOCRegister(HIF_DEVICE *device,
-                   A_UINT32 address,
-                   A_UINT32 *param)
+int
+BMIReadSOCRegister(struct hif_device *device,
+                   u32 address,
+                   u32 *param)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
@@ -430,36 +430,36 @@ BMIReadSOCRegister(HIF_DEVICE *device,
     cid = BMI_READ_SOC_REGISTER;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
 
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), TRUE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
         return A_ERROR;
     }
-    A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
+    memcpy(param, pBMICmdBuf, sizeof(*param));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIWriteSOCRegister(HIF_DEVICE *device,
-                    A_UINT32 address,
-                    A_UINT32 param)
+int
+BMIWriteSOCRegister(struct hif_device *device,
+                    u32 address,
+                    u32 param)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
@@ -476,33 +476,33 @@ BMIWriteSOCRegister(HIF_DEVICE *device,
     cid = BMI_WRITE_SOC_REGISTER;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &param, sizeof(param));
+    memcpy(&(pBMICmdBuf[offset]), &param, sizeof(param));
     offset += sizeof(param);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIrompatchInstall(HIF_DEVICE *device,
-                   A_UINT32 ROM_addr,
-                   A_UINT32 RAM_addr,
-                   A_UINT32 nbytes,
-                   A_UINT32 do_activate,
-                   A_UINT32 *rompatch_id)
+int
+BMIrompatchInstall(struct hif_device *device,
+                   u32 ROM_addr,
+                   u32 RAM_addr,
+                   u32 nbytes,
+                   u32 do_activate,
+                   u32 *rompatch_id)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
 				sizeof(nbytes) + sizeof(do_activate)));
@@ -521,40 +521,40 @@ BMIrompatchInstall(HIF_DEVICE *device,
     cid = BMI_ROMPATCH_INSTALL;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
+    memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
     offset += sizeof(ROM_addr);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
+    memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
     offset += sizeof(RAM_addr);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
+    memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
     offset += sizeof(nbytes);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
+    memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
     offset += sizeof(do_activate);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), TRUE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
         return A_ERROR;
     }
-    A_MEMCPY(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
+    memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIrompatchUninstall(HIF_DEVICE *device,
-                     A_UINT32 rompatch_id)
+int
+BMIrompatchUninstall(struct hif_device *device,
+                     u32 rompatch_id)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
@@ -571,30 +571,30 @@ BMIrompatchUninstall(HIF_DEVICE *device,
     cid = BMI_ROMPATCH_UNINSTALL;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
+    memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
     offset += sizeof(rompatch_id);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-_BMIrompatchChangeActivation(HIF_DEVICE *device,
-                             A_UINT32 rompatch_count,
-                             A_UINT32 *rompatch_list,
-                             A_UINT32 do_activate)
+static int
+_BMIrompatchChangeActivation(struct hif_device *device,
+                             u32 rompatch_count,
+                             u32 *rompatch_list,
+                             u32 do_activate)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 length;
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 length;
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
     memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
@@ -611,50 +611,50 @@ _BMIrompatchChangeActivation(HIF_DEVICE *device,
     cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
+    memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
     offset += sizeof(rompatch_count);
     length = rompatch_count * sizeof(*rompatch_list);
-    A_MEMCPY(&(pBMICmdBuf[offset]), rompatch_list, length);
+    memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
     offset += length;
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIrompatchActivate(HIF_DEVICE *device,
-                    A_UINT32 rompatch_count,
-                    A_UINT32 *rompatch_list)
+int
+BMIrompatchActivate(struct hif_device *device,
+                    u32 rompatch_count,
+                    u32 *rompatch_list)
 {
     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
 }
 
-A_STATUS
-BMIrompatchDeactivate(HIF_DEVICE *device,
-                      A_UINT32 rompatch_count,
-                      A_UINT32 *rompatch_list)
+int
+BMIrompatchDeactivate(struct hif_device *device,
+                      u32 rompatch_count,
+                      u32 *rompatch_list)
 {
     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
 }
 
-A_STATUS
-BMILZData(HIF_DEVICE *device,
-          A_UCHAR *buffer,
-          A_UINT32 length)
+int
+BMILZData(struct hif_device *device,
+          u8 *buffer,
+          u32 length)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 remaining, txlen;
-    const A_UINT32 header = sizeof(cid) + sizeof(length);
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 remaining, txlen;
+    const u32 header = sizeof(cid) + sizeof(length);
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
@@ -676,14 +676,14 @@ BMILZData(HIF_DEVICE *device,
         txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
                                        remaining : (BMI_DATASZ_MAX - header);
         offset = 0;
-        A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
         offset += sizeof(cid);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
+        memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
         offset += sizeof(txlen);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
+        memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
         offset += txlen;
         status = bmiBufferSend(device, pBMICmdBuf, offset);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
             return A_ERROR;
         }
@@ -692,16 +692,16 @@ BMILZData(HIF_DEVICE *device,
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMILZStreamStart(HIF_DEVICE *device,
-                 A_UINT32 address)
+int
+BMILZStreamStart(struct hif_device *device,
+                 u32 address)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
@@ -717,31 +717,31 @@ BMILZStreamStart(HIF_DEVICE *device,
 
     cid = BMI_LZ_STREAM_START;
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
 /* BMI Access routines */
-A_STATUS
-bmiBufferSend(HIF_DEVICE *device,
-              A_UCHAR *buffer,
-              A_UINT32 length)
+int
+bmiBufferSend(struct hif_device *device,
+              u8 *buffer,
+              u32 length)
 {
-    A_STATUS status;
-    A_UINT32 timeout;
-    A_UINT32 address;
-    A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
+    int status;
+    u32 timeout;
+    u32 address;
+    u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
 
     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
                        &mboxAddress[0], sizeof(mboxAddress));
@@ -755,9 +755,9 @@ bmiBufferSend(HIF_DEVICE *device,
         /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
          * a decrement, while the remaining 3 bytes has no effect.  The rationale behind this is to
          * make all HIF accesses 4-byte aligned */
-        status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, 4,
+        status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4,
             HIF_RD_SYNC_BYTE_INC, NULL);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
             return A_ERROR;
         }
@@ -769,7 +769,7 @@ bmiBufferSend(HIF_DEVICE *device,
         address = mboxAddress[ENDPOINT1];
         status = HIFReadWrite(device, address, buffer, length,
             HIF_WR_SYNC_BYTE_INC, NULL);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
             return A_ERROR;
         }
@@ -781,16 +781,16 @@ bmiBufferSend(HIF_DEVICE *device,
     return status;
 }
 
-A_STATUS
-bmiBufferReceive(HIF_DEVICE *device,
-                 A_UCHAR *buffer,
-                 A_UINT32 length,
-                 A_BOOL want_timeout)
+int
+bmiBufferReceive(struct hif_device *device,
+                 u8 *buffer,
+                 u32 length,
+                 bool want_timeout)
 {
-    A_STATUS status;
-    A_UINT32 address;
-    A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
-    HIF_PENDING_EVENTS_INFO     hifPendingEvents;
+    int status;
+    u32 address;
+    u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
+    struct hif_pending_events_info     hifPendingEvents;
     static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
     
     if (!pendingEventsFuncCheck) {
@@ -800,7 +800,7 @@ bmiBufferReceive(HIF_DEVICE *device,
                            HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
                            &getPendingEventsFunc,
                            sizeof(getPendingEventsFunc));
-        pendingEventsFuncCheck = TRUE;
+        pendingEventsFuncCheck = true;
     }
                        
     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
@@ -857,8 +857,8 @@ bmiBufferReceive(HIF_DEVICE *device,
          * NB: word_available is declared static for esoteric reasons
          * having to do with protection on some OSes.
          */
-        static A_UINT32 word_available;
-        A_UINT32 timeout;
+        static u32 word_available;
+        u32 timeout;
 
         word_available = 0;
         timeout = BMI_COMMUNICATION_TIMEOUT;
@@ -868,20 +868,20 @@ bmiBufferReceive(HIF_DEVICE *device,
                 status = getPendingEventsFunc(device,
                                               &hifPendingEvents,
                                               NULL);
-                if (status != A_OK) {
+                if (status) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
                     break;
                 }
   
-                if (hifPendingEvents.AvailableRecvBytes >= sizeof(A_UINT32)) {
+                if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
                     word_available = 1;    
                 }
                 continue;    
             }
             
-            status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (A_UINT8 *)&word_available,
+            status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
                 sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
                 return A_ERROR;
             }
@@ -920,7 +920,7 @@ bmiBufferReceive(HIF_DEVICE *device,
      *   reduce BMI_DATASZ_MAX to 32 or 64
      */
     if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
-        A_UINT32 timeout;
+        u32 timeout;
 
         *pBMICmdCredits = 0;
         timeout = BMI_COMMUNICATION_TIMEOUT;
@@ -930,9 +930,9 @@ bmiBufferReceive(HIF_DEVICE *device,
             /* read the counter using a 4-byte read.  Since the counter is NOT auto-decrementing,
              * we can read this counter multiple times using a non-incrementing address mode.
              * The rationale here is to make all HIF accesses a multiple of 4 bytes */
-            status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
+            status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
                 HIF_RD_SYNC_BYTE_FIX, NULL);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
                 return A_ERROR;
             }
@@ -949,62 +949,62 @@ bmiBufferReceive(HIF_DEVICE *device,
 
     address = mboxAddress[ENDPOINT1];
     status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIFastDownload(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length)
+int
+BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
 {
-    A_STATUS status = A_ERROR;
-    A_UINT32  lastWord = 0;
-    A_UINT32  lastWordOffset = length & ~0x3;
-    A_UINT32  unalignedBytes = length & 0x3;
+    int status = A_ERROR;
+    u32 lastWord = 0;
+    u32 lastWordOffset = length & ~0x3;
+    u32 unalignedBytes = length & 0x3;
 
     status = BMILZStreamStart (device, address);
-    if (A_FAILED(status)) {
+    if (status) {
             return A_ERROR;
     }
 
     if (unalignedBytes) {
             /* copy the last word into a zero padded buffer */
-        A_MEMCPY(&lastWord, &buffer[lastWordOffset], unalignedBytes);
+        memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
     }
 
     status = BMILZData(device, buffer, lastWordOffset);
 
-    if (A_FAILED(status)) {
+    if (status) {
         return A_ERROR;
     }
 
     if (unalignedBytes) {
-        status = BMILZData(device, (A_UINT8 *)&lastWord, 4);
+        status = BMILZData(device, (u8 *)&lastWord, 4);
     }
 
-    if (A_SUCCESS(status)) {
+    if (!status) {
         //
         // Close compressed stream and open a new (fake) one.  This serves mainly to flush Target caches.
         //
         status = BMILZStreamStart (device, 0x00);
-        if (A_FAILED(status)) {
+        if (status) {
            return A_ERROR;
         }
     }
 	return status;
 }
 
-A_STATUS
-BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length)
+int
+BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
 {
     return bmiBufferSend(device, buffer, length);
 }
 
-A_STATUS
-BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout)
+int
+BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
 {
     return bmiBufferReceive(device, buffer, length, want_timeout);
 }
diff --git a/drivers/staging/ath6kl/hif/common/hif_sdio_common.h b/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
index 0f4e913..93a2adc 100644
--- a/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
+++ b/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
@@ -58,7 +58,7 @@
 #define HIF_DEFAULT_IO_BLOCK_SIZE          128
 
     /* set extended MBOX window information for SDIO interconnects */
-static INLINE void SetExtendedMboxWindowInfo(A_UINT16 Manfid, HIF_DEVICE_MBOX_INFO *pInfo)
+static INLINE void SetExtendedMboxWindowInfo(u16 Manfid, struct hif_device_mbox_info *pInfo)
 {
     switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) {                   
         case MANUFACTURER_ID_AR6002_BASE :
@@ -74,7 +74,7 @@ static INLINE void SetExtendedMboxWindowInfo(A_UINT16 Manfid, HIF_DEVICE_MBOX_IN
             pInfo->GMboxSize = HIF_GMBOX_WIDTH;
             break;
         default:
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
     }
 }
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h b/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
index 857f35f..6341560 100644
--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
+++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
@@ -47,19 +47,17 @@
 #define HIF_MBOX2_BLOCK_SIZE               HIF_MBOX_BLOCK_SIZE
 #define HIF_MBOX3_BLOCK_SIZE               HIF_MBOX_BLOCK_SIZE
 
-struct _HIF_SCATTER_REQ_PRIV;
-
 typedef struct bus_request {
     struct bus_request *next;       /* link list of available requests */
     struct bus_request *inusenext;  /* link list of in use requests */
     struct semaphore sem_req;
-    A_UINT32 address;               /* request data */
-    A_UCHAR *buffer;
-    A_UINT32 length;
-    A_UINT32 request;
+    u32 address;               /* request data */
+    u8 *buffer;
+    u32 length;
+    u32 request;
     void *context;
-    A_STATUS status;
-    struct _HIF_SCATTER_REQ_PRIV *pScatterReq;      /* this request is a scatter request */
+    int status;
+    struct hif_scatter_req_priv *pScatterReq;      /* this request is a scatter request */
 } BUS_REQUEST;
 
 struct hif_device {
@@ -76,11 +74,11 @@ struct hif_device {
     BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */
     void     *claimedContext;
     HTC_CALLBACKS htcCallbacks;
-    A_UINT8     *dma_buffer;
-    DL_LIST      ScatterReqHead;                /* scatter request list head */
-    A_BOOL       scatter_enabled;               /* scatter enabled flag */
-    A_BOOL   is_suspend;
-    A_BOOL   is_disabled;
+    u8 *dma_buffer;
+    struct dl_list      ScatterReqHead;                /* scatter request list head */
+    bool       scatter_enabled;               /* scatter enabled flag */
+    bool   is_suspend;
+    bool   is_disabled;
     atomic_t   irqHandling;
     HIF_DEVICE_POWER_CHANGE_TYPE powerConfig;
     const struct sdio_device_id *id;
@@ -90,9 +88,9 @@ struct hif_device {
 #define CMD53_FIXED_ADDRESS 1
 #define CMD53_INCR_ADDRESS  2
 
-BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device);
-void hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest);
-void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device);
+void hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest);
+void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest);
 
 #ifdef HIF_LINUX_MMC_SCATTER_SUPPORT
 
@@ -100,28 +98,28 @@ void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest);
 #define MAX_SCATTER_ENTRIES_PER_REQ      16
 #define MAX_SCATTER_REQ_TRANSFER_SIZE    32*1024
 
-typedef struct _HIF_SCATTER_REQ_PRIV {
-    HIF_SCATTER_REQ     *pHifScatterReq;  /* HIF scatter request with allocated entries */   
-    HIF_DEVICE          *device;          /* this device */
+struct hif_scatter_req_priv {
+    struct hif_scatter_req     *pHifScatterReq;  /* HIF scatter request with allocated entries */   
+    struct hif_device          *device;          /* this device */
     BUS_REQUEST         *busrequest;      /* request associated with request */
         /* scatter list for linux */    
     struct scatterlist  sgentries[MAX_SCATTER_ENTRIES_PER_REQ];   
-} HIF_SCATTER_REQ_PRIV;
+};
 
 #define ATH_DEBUG_SCATTER  ATH_DEBUG_MAKE_MODULE_MASK(0)
 
-A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo);
-void CleanupHIFScatterResources(HIF_DEVICE *device);
-A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo);
+void CleanupHIFScatterResources(struct hif_device *device);
+int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest);
 
 #else  // HIF_LINUX_MMC_SCATTER_SUPPORT
 
-static inline A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo) 
+static inline int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo)
 {
     return A_ENOTSUP;
 }
 
-static inline A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest) 
+static inline int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     return A_ENOTSUP;
 }
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
index e96662b..e6d9cd8 100644
--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
+++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
@@ -46,7 +46,7 @@
  */
 #define BUFFER_NEEDS_BOUNCE(buffer)  (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer)))
 #else
-#define BUFFER_NEEDS_BOUNCE(buffer)   (FALSE)
+#define BUFFER_NEEDS_BOUNCE(buffer)   (false)
 #endif
 
 /* ATHENV */
@@ -58,16 +58,16 @@ static int hifDeviceResume(struct device *dev);
 #endif /* CONFIG_PM */
 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id);
 static void hifDeviceRemoved(struct sdio_func *func);
-static HIF_DEVICE *addHifDevice(struct sdio_func *func);
-static HIF_DEVICE *getHifDevice(struct sdio_func *func);
-static void delHifDevice(HIF_DEVICE * device);
+static struct hif_device *addHifDevice(struct sdio_func *func);
+static struct hif_device *getHifDevice(struct sdio_func *func);
+static void delHifDevice(struct hif_device * device);
 static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte);
 static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte);
 
 int reset_sdio_on_unload = 0;
 module_param(reset_sdio_on_unload, int, 0644);
 
-extern A_UINT32 nohifscattersupport;
+extern u32 nohifscattersupport;
 
 
 /* ------ Static Variables ------ */
@@ -102,13 +102,13 @@ static struct dev_pm_ops ar6k_device_pm_ops = {
 static int registered = 0;
 
 OSDRV_CALLBACKS osdrvCallbacks;
-extern A_UINT32 onebitmode;
-extern A_UINT32 busspeedlow;
-extern A_UINT32 debughif;
+extern u32 onebitmode;
+extern u32 busspeedlow;
+extern u32 debughif;
 
 static void ResetAllCards(void);
-static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func);
-static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func);
+static int hifDisableFunc(struct hif_device *device, struct sdio_func *func);
+static int hifEnableFunc(struct hif_device *device, struct sdio_func *func);
 
 #ifdef DEBUG
 
@@ -123,7 +123,7 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif,
 
 
 /* ------ Functions ------ */
-A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks)
+int HIFInit(OSDRV_CALLBACKS *callbacks)
 {
     int status;
     AR_DEBUG_ASSERT(callbacks != NULL);
@@ -148,23 +148,23 @@ A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks)
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 
 }
 
-static A_STATUS
-__HIFReadWrite(HIF_DEVICE *device,
-             A_UINT32 address,
-             A_UCHAR *buffer,
-             A_UINT32 length,
-             A_UINT32 request,
+static int
+__HIFReadWrite(struct hif_device *device,
+             u32 address,
+             u8 *buffer,
+             u32 length,
+             u32 request,
              void *context)
 {
-    A_UINT8 opcode;
-    A_STATUS    status = A_OK;
+    u8 opcode;
+    int    status = 0;
     int     ret;
-    A_UINT8 *tbuffer;
-    A_BOOL   bounced = FALSE;
+    u8 *tbuffer;
+    bool   bounced = false;
 
     AR_DEBUG_ASSERT(device != NULL);
     AR_DEBUG_ASSERT(device->func != NULL);
@@ -243,7 +243,7 @@ __HIFReadWrite(HIF_DEVICE *device,
                     /* copy the write data to the dma buffer */
                 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
                 memcpy(tbuffer, buffer, length);
-                bounced = TRUE;
+                bounced = true;
             } else {
                 tbuffer = buffer;    
             }
@@ -265,7 +265,7 @@ __HIFReadWrite(HIF_DEVICE *device,
                 AR_DEBUG_ASSERT(device->dma_buffer != NULL);
                 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
                 tbuffer = device->dma_buffer;
-                bounced = TRUE;
+                bounced = true;
             } else {
                 tbuffer = buffer;    
             }
@@ -299,12 +299,12 @@ __HIFReadWrite(HIF_DEVICE *device,
                             ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret));
             status = A_ERROR;
         }
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
-void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     unsigned long flags;
     BUS_REQUEST *async;
@@ -329,15 +329,15 @@ void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest)
 
 
 /* queue a read/write request */
-A_STATUS
-HIFReadWrite(HIF_DEVICE *device,
-             A_UINT32 address,
-             A_UCHAR *buffer,
-             A_UINT32 length,
-             A_UINT32 request,
+int
+HIFReadWrite(struct hif_device *device,
+             u32 address,
+             u8 *buffer,
+             u32 length,
+             u32 request,
              void *context)
 {
-    A_STATUS    status = A_OK;
+    int    status = 0;
     BUS_REQUEST *busrequest;
 
 
@@ -375,7 +375,7 @@ HIFReadWrite(HIF_DEVICE *device,
                     /* interrupted, exit */
                     return A_ERROR;
                 } else {
-                    A_STATUS status = busrequest->status;
+                    int status = busrequest->status;
                     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n", 
 						      (unsigned long)busrequest, busrequest->status));
                     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request));
@@ -400,12 +400,12 @@ HIFReadWrite(HIF_DEVICE *device,
 /* thread to serialize all requests, both sync and async */
 static int async_task(void *param)
  {
-    HIF_DEVICE *device;
+    struct hif_device *device;
     BUS_REQUEST *request;
-    A_STATUS status;
+    int status;
     unsigned long flags;
 
-    device = (HIF_DEVICE *)param;
+    device = (struct hif_device *)param;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n"));
     set_current_state(TASK_INTERRUPTIBLE);
     while(!device->async_shutdown) {
@@ -465,10 +465,10 @@ static int async_task(void *param)
     return 0;
 }
 
-static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, A_UINT32 flags, A_UINT32 *resp)
+static s32 IssueSDCommand(struct hif_device *device, u32 opcode, u32 arg, u32 flags, u32 *resp)
 {
     struct mmc_command cmd;
-    A_INT32 err;
+    s32 err;
     struct mmc_host *host;
     struct sdio_func *func;
 
@@ -488,14 +488,14 @@ static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg,
     return err;
 }
 
-A_STATUS ReinitSDIO(HIF_DEVICE *device)
+int ReinitSDIO(struct hif_device *device)
 {
-    A_INT32 err;
+    s32 err;
     struct mmc_host *host;
     struct mmc_card *card;
 	struct sdio_func *func;
-    A_UINT8  cmd52_resp;
-    A_UINT32 clock;
+    u8 cmd52_resp;
+    u32 clock;
 
     func = device->func;
     card = func->card;
@@ -506,9 +506,9 @@ A_STATUS ReinitSDIO(HIF_DEVICE *device)
 
     do {
         if (!device->is_suspend) {
-            A_UINT32 resp;
-            A_UINT16 rca;
-            A_UINT32 i;
+            u32 resp;
+            u16 rca;
+            u32 i;
             int bit = fls(host->ocr_avail) - 1;
             /* emulate the mmc_power_up(...) */
             host->ios.vdd = bit;
@@ -644,13 +644,13 @@ A_STATUS ReinitSDIO(HIF_DEVICE *device)
     sdio_release_host(func);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n"));
 
-    return (err) ? A_ERROR : A_OK;
+    return (err) ? A_ERROR : 0;
 }
 
-A_STATUS
-PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
+int
+PowerStateChangeNotify(struct hif_device *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 #if defined(CONFIG_PM)
 	struct sdio_func *func = device->func;
     int old_reset_val;
@@ -678,7 +678,7 @@ PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
             if (device->powerConfig == HIF_DEVICE_POWER_CUT) {
                 status = ReinitSDIO(device);
             }
-            if (status == A_OK) {
+            if (status == 0) {
                 status = hifEnableFunc(device, func);
             }
             break;
@@ -690,29 +690,29 @@ PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
     return status;
 }
 
-A_STATUS
-HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
-                   void *config, A_UINT32 configLen)
+int
+HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode,
+                   void *config, u32 configLen)
 {
-    A_UINT32 count;
-    A_STATUS status = A_OK;
+    u32 count;
+    int status = 0;
     
     switch(opcode) {
         case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
-            ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
-            ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
-            ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
-            ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
+            ((u32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
+            ((u32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
+            ((u32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
+            ((u32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
             break;
 
         case HIF_DEVICE_GET_MBOX_ADDR:
             for (count = 0; count < 4; count ++) {
-                ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
+                ((u32 *)config)[count] = HIF_MBOX_START_ADDR(count);
             }
             
-            if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) {    
-                SetExtendedMboxWindowInfo((A_UINT16)device->func->device,
-                                          (HIF_DEVICE_MBOX_INFO *)config);
+            if (configLen >= sizeof(struct hif_device_mbox_info)) {    
+                SetExtendedMboxWindowInfo((u16)device->func->device,
+                                          (struct hif_device_mbox_info *)config);
             }
                         
             break;
@@ -723,14 +723,14 @@ HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
             if (!device->scatter_enabled) {
                 return A_ENOTSUP;    
             }
-            status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config);
-            if (A_FAILED(status)) {
-                device->scatter_enabled = FALSE;           
+            status = SetupHIFScatterSupport(device, (struct hif_device_scatter_support_info *)config);
+            if (status) {
+                device->scatter_enabled = false;
             }
             break; 
         case HIF_DEVICE_GET_OS_DEVICE:
                 /* pass back a pointer to the SDIO function's "dev" struct */
-            ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev;
+            ((struct hif_device_os_device_info *)config)->pOSDevice = &device->func->dev;
             break; 
         case HIF_DEVICE_POWER_STATE_CHANGE:
             status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config);
@@ -745,7 +745,7 @@ HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
 }
 
 void
-HIFShutDownDevice(HIF_DEVICE *device)
+HIFShutDownDevice(struct hif_device *device)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n"));
     if (device != NULL) {
@@ -774,8 +774,8 @@ HIFShutDownDevice(HIF_DEVICE *device)
 static void
 hifIRQHandler(struct sdio_func *func)
 {
-    A_STATUS status;
-    HIF_DEVICE *device;
+    int status;
+    struct hif_device *device;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));
 
     device = getHifDevice(func);
@@ -785,19 +785,19 @@ hifIRQHandler(struct sdio_func *func)
     status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
     sdio_claim_host(device->func);
     atomic_set(&device->irqHandling, 0);
-    AR_DEBUG_ASSERT(status == A_OK || status == A_ECANCELED);
+    AR_DEBUG_ASSERT(status == 0 || status == A_ECANCELED);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
 }
 
 /* handle HTC startup via thread*/
 static int startup_task(void *param)
 {
-    HIF_DEVICE *device;
+    struct hif_device *device;
 
-    device = (HIF_DEVICE *)param;
+    device = (struct hif_device *)param;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n"));
         /* start  up inform DRV layer */
-    if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) {
+    if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
     }
     return 0;
@@ -806,15 +806,15 @@ static int startup_task(void *param)
 #if defined(CONFIG_PM)
 static int enable_task(void *param)
 {
-    HIF_DEVICE *device;
-    device = (HIF_DEVICE *)param;
+    struct hif_device *device;
+    device = (struct hif_device *)param;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call  from resume_task\n"));
 
         /* start  up inform DRV layer */
     if (device && 
         device->claimedContext && 
         osdrvCallbacks.devicePowerChangeHandler &&
-        osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != A_OK) 
+        osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != 0)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
     }
@@ -826,7 +826,7 @@ static int enable_task(void *param)
 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
 {
     int ret;
-    HIF_DEVICE * device;
+    struct hif_device * device;
     int count;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
@@ -837,7 +837,7 @@ static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
     device = getHifDevice(func);
 
     device->id = id;
-    device->is_disabled = TRUE;
+    device->is_disabled = true;
 
     spin_lock_init(&device->lock);
 
@@ -848,7 +848,7 @@ static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
     if (!nohifscattersupport) {
             /* try to allow scatter operation on all instances,
              * unless globally overridden */
-        device->scatter_enabled = TRUE;
+        device->scatter_enabled = true;
     }
 
     /* Initialize the bus requests to be used later */
@@ -866,7 +866,7 @@ static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id
 
 
 void
-HIFAckInterrupt(HIF_DEVICE *device)
+HIFAckInterrupt(struct hif_device *device)
 {
     AR_DEBUG_ASSERT(device != NULL);
 
@@ -874,7 +874,7 @@ HIFAckInterrupt(HIF_DEVICE *device)
 }
 
 void
-HIFUnMaskInterrupt(HIF_DEVICE *device)
+HIFUnMaskInterrupt(struct hif_device *device)
 {
     int ret;
 
@@ -890,7 +890,7 @@ HIFUnMaskInterrupt(HIF_DEVICE *device)
     AR_DEBUG_ASSERT(ret == 0);
 }
 
-void HIFMaskInterrupt(HIF_DEVICE *device)
+void HIFMaskInterrupt(struct hif_device *device)
 {
     int ret;
     AR_DEBUG_ASSERT(device != NULL);
@@ -910,7 +910,7 @@ void HIFMaskInterrupt(HIF_DEVICE *device)
     AR_DEBUG_ASSERT(ret == 0);
 }
 
-BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device)
+BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device)
 {
     BUS_REQUEST *busrequest;
     unsigned long flag;
@@ -930,7 +930,7 @@ BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device)
 }
 
 void
-hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     unsigned long flag;
 
@@ -949,10 +949,10 @@ hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest)
     spin_unlock_irqrestore(&device->lock, flag);
 }
 
-static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func)
+static int hifDisableFunc(struct hif_device *device, struct sdio_func *func)
 {
     int ret;
-    A_STATUS status = A_OK;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n"));
     device = getHifDevice(func);
@@ -988,20 +988,20 @@ static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func)
 
     sdio_release_host(device->func);
 
-    if (status == A_OK) {
-        device->is_disabled = TRUE;
+    if (status == 0) {
+        device->is_disabled = true;
     }
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n"));
 
     return status;
 }
 
-static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
+static int hifEnableFunc(struct hif_device *device, struct sdio_func *func)
 {
     struct task_struct* pTask;
     const char *taskName = NULL;
     int (*taskFunc)(void *) = NULL;
-    int ret = A_OK;
+    int ret = 0;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n"));
     device = getHifDevice(func);
@@ -1036,7 +1036,7 @@ static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
 					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
             return A_ERROR;
         }
-        device->is_disabled = FALSE;
+        device->is_disabled = false;
         /* create async I/O thread */
         if (!device->async_task) {
             device->async_shutdown = 0;
@@ -1055,7 +1055,7 @@ static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
     if (!device->claimedContext) {
         taskFunc = startup_task;
         taskName = "AR6K startup";
-        ret = A_OK;
+        ret = 0;
 #if defined(CONFIG_PM)
     } else {
         taskFunc = enable_task;
@@ -1080,22 +1080,23 @@ static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
 static int hifDeviceSuspend(struct device *dev)
 {
     struct sdio_func *func=dev_to_sdio_func(dev);
-    A_STATUS status = A_OK;
-    HIF_DEVICE *device;   
+    int status = 0;
+    struct hif_device *device;   
 
     device = getHifDevice(func);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceSuspend\n"));
     if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
-        device->is_suspend = TRUE; /* set true first for PowerStateChangeNotify(..) */
+        device->is_suspend = true; /* set true first for PowerStateChangeNotify(..) */
         status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext);
-        if (status != A_OK) {
-            device->is_suspend = FALSE;
+        if (status) {
+            device->is_suspend = false;
         }
     }
+    CleanupHIFScatterResources(device);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceSuspend\n"));
 
     switch (status) {
-    case A_OK:
+    case 0:
         return 0;
     case A_EBUSY:
         return -EBUSY; /* Hack for kernel in order to support deep sleep and wow */
@@ -1107,27 +1108,27 @@ static int hifDeviceSuspend(struct device *dev)
 static int hifDeviceResume(struct device *dev)
 {
     struct sdio_func *func=dev_to_sdio_func(dev);
-    A_STATUS status = A_OK;
-    HIF_DEVICE *device;   
+    int status = 0;
+    struct hif_device *device;   
 
     device = getHifDevice(func);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceResume\n"));
     if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
         status = osdrvCallbacks.deviceResumeHandler(device->claimedContext);
-        if (status == A_OK) {
-            device->is_suspend = FALSE;
+        if (status == 0) {
+            device->is_suspend = false;
         }
     }
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceResume\n"));
 
-    return A_SUCCESS(status) ? 0 : status;
+    return status;
 }
 #endif /* CONFIG_PM */
 
 static void hifDeviceRemoved(struct sdio_func *func)
 {
-    A_STATUS status = A_OK;
-    HIF_DEVICE *device;
+    int status = 0;
+    struct hif_device *device;
     AR_DEBUG_ASSERT(func != NULL);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
@@ -1137,25 +1138,25 @@ static void hifDeviceRemoved(struct sdio_func *func)
     }
 
     if (device->is_disabled) {
-        device->is_disabled = FALSE;
+        device->is_disabled = false;
     } else {
         status = hifDisableFunc(device, func);
     }
     CleanupHIFScatterResources(device);
      
     delHifDevice(device);
-    AR_DEBUG_ASSERT(status == A_OK);
+    AR_DEBUG_ASSERT(status == 0);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
 }
 
 /*
  * This should be moved to AR6K HTC layer.
  */
-A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device)
+int hifWaitForPendingRecv(struct hif_device *device)
 {
-    A_INT32 cnt = 10;
-    A_UINT8 host_int_status;
-    A_STATUS status = A_OK;
+    s32 cnt = 10;
+    u8 host_int_status;
+    int status = 0;
 
     do {            		    
         while (atomic_read(&device->irqHandling)) {
@@ -1165,9 +1166,9 @@ A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device)
 		/* check if there is any pending irq due to force done */
 		host_int_status = 0;
 	    status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS,
-				    (A_UINT8 *)&host_int_status, sizeof(host_int_status),
+				    (u8 *)&host_int_status, sizeof(host_int_status),
 			  	     HIF_RD_SYNC_BYTE_INC, NULL);
-	    host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)) : 0;
+	    host_int_status = !status ? (host_int_status & (1 << 0)) : 0;
 		if (host_int_status) {
 	        schedule(); /* schedule for next dsrHandler */
 		}
@@ -1178,17 +1179,17 @@ A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device)
                             ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__));
      }
 
-    return A_OK;
+    return 0;
 }
     
 
-static HIF_DEVICE *
+static struct hif_device *
 addHifDevice(struct sdio_func *func)
 {
-    HIF_DEVICE *hifdevice;
+    struct hif_device *hifdevice;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n"));
     AR_DEBUG_ASSERT(func != NULL);
-    hifdevice = kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL);
+    hifdevice = kzalloc(sizeof(struct hif_device), GFP_KERNEL);
     AR_DEBUG_ASSERT(hifdevice != NULL);
 #if HIF_USE_DMA_BOUNCE_BUFFER
     hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
@@ -1201,21 +1202,19 @@ addHifDevice(struct sdio_func *func)
     return hifdevice;
 }
 
-static HIF_DEVICE *
+static struct hif_device *
 getHifDevice(struct sdio_func *func)
 {
     AR_DEBUG_ASSERT(func != NULL);
-    return (HIF_DEVICE *)sdio_get_drvdata(func);
+    return (struct hif_device *)sdio_get_drvdata(func);
 }
 
 static void
-delHifDevice(HIF_DEVICE * device)
+delHifDevice(struct hif_device * device)
 {
     AR_DEBUG_ASSERT(device!= NULL);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
-    if (device->dma_buffer != NULL) {
-        kfree(device->dma_buffer);
-    }
+    kfree(device->dma_buffer);
     kfree(device);
 }
 
@@ -1223,27 +1222,27 @@ static void ResetAllCards(void)
 {
 }
 
-void HIFClaimDevice(HIF_DEVICE  *device, void *context)
+void HIFClaimDevice(struct hif_device  *device, void *context)
 {
     device->claimedContext = context;
 }
 
-void HIFReleaseDevice(HIF_DEVICE  *device)
+void HIFReleaseDevice(struct hif_device  *device)
 {
     device->claimedContext = NULL;
 }
 
-A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks)
+int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks)
 {
     if (device->htcCallbacks.context != NULL) {
             /* already in use! */
         return A_ERROR;
     }
     device->htcCallbacks = *callbacks;
-    return A_OK;
+    return 0;
 }
 
-void HIFDetachHTC(HIF_DEVICE *device)
+void HIFDetachHTC(struct hif_device *device)
 {
     A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
 }
@@ -1280,7 +1279,7 @@ static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsi
 {
     struct mmc_command ioCmd;
     unsigned long      arg;
-    A_INT32 err;
+    s32 err;
     
     memset(&ioCmd,0,sizeof(ioCmd));
     SDIO_SET_CMD52_READ_ARG(arg,0,address);
diff --git a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
index ee8b477..a1fdcc1 100644
--- a/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
+++ b/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
@@ -48,7 +48,7 @@
             (((address) & 0x1FFFF) << 9)        | \
             ((bytes_blocks) & 0x1FF)
             
-static void FreeScatterReq(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
+static void FreeScatterReq(struct hif_device *device, struct hif_scatter_req *pReq)
 {   
     unsigned long flag;
 
@@ -60,9 +60,9 @@ static void FreeScatterReq(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
         
 }
 
-static HIF_SCATTER_REQ *AllocScatterReq(HIF_DEVICE *device) 
+static struct hif_scatter_req *AllocScatterReq(struct hif_device *device) 
 {
-    DL_LIST       *pItem; 
+    struct dl_list       *pItem; 
     unsigned long flag;
 
     spin_lock_irqsave(&device->lock, flag);
@@ -72,24 +72,24 @@ static HIF_SCATTER_REQ *AllocScatterReq(HIF_DEVICE *device)
     spin_unlock_irqrestore(&device->lock, flag);
     
     if (pItem != NULL) {
-        return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink);
     }
     
     return NULL;   
 }
 
     /* called by async task to perform the operation synchronously using direct MMC APIs  */
-A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     int                     i;
-    A_UINT8                 rw;
-    A_UINT8                 opcode;
+    u8 rw;
+    u8 opcode;
     struct mmc_request      mmcreq;
     struct mmc_command      cmd;
     struct mmc_data         data;
-    HIF_SCATTER_REQ_PRIV   *pReqPriv;   
-    HIF_SCATTER_REQ        *pReq;       
-    A_STATUS                status = A_OK;
+    struct hif_scatter_req_priv   *pReqPriv;   
+    struct hif_scatter_req        *pReq;       
+    int                status = 0;
     struct                  scatterlist *pSg;
     
     pReqPriv = busrequest->pScatterReq;
@@ -176,7 +176,7 @@ A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest)
         AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error));   
     }
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n",
               (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks));        
     }
@@ -199,11 +199,11 @@ A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest)
 }
 
     /* callback to issue a read-write scatter request */
-static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
+static int HifReadWriteScatter(struct hif_device *device, struct hif_scatter_req *pReq)
 {
-    A_STATUS             status = A_EINVAL;
-    A_UINT32             request = pReq->Request;
-    HIF_SCATTER_REQ_PRIV *pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0];
+    int             status = A_EINVAL;
+    u32 request = pReq->Request;
+    struct hif_scatter_req_priv *pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0];
     
     do {
         
@@ -237,7 +237,7 @@ static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
         }
         
         if (pReq->TotalLength == 0) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;    
         }
         
@@ -260,26 +260,26 @@ static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
             AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest));
                 /* wake thread, it will process and then take care of the async callback */
             up(&device->sem_async);
-            status = A_OK;
+            status = 0;
         }           
        
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
+    if (status && (request & HIF_ASYNCHRONOUS)) {
         pReq->CompletionStatus = status;
         pReq->CompletionRoutine(pReq);
-        status = A_OK;
+        status = 0;
     }
         
     return status;  
 }
 
     /* setup of HIF scatter resources */
-A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo)
+int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo)
 {
-    A_STATUS              status = A_ERROR;   
+    int              status = A_ERROR;
     int                   i;
-    HIF_SCATTER_REQ_PRIV *pReqPriv;
+    struct hif_scatter_req_priv *pReqPriv;
     BUS_REQUEST          *busrequest;
         
     do {
@@ -297,23 +297,23 @@ A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_I
         
         for (i = 0; i < MAX_SCATTER_REQUESTS; i++) {    
                 /* allocate the private request blob */
-            pReqPriv = (HIF_SCATTER_REQ_PRIV *)A_MALLOC(sizeof(HIF_SCATTER_REQ_PRIV));
+            pReqPriv = (struct hif_scatter_req_priv *)A_MALLOC(sizeof(struct hif_scatter_req_priv));
             if (NULL == pReqPriv) {
                 break;    
             }
-            A_MEMZERO(pReqPriv, sizeof(HIF_SCATTER_REQ_PRIV));
+            A_MEMZERO(pReqPriv, sizeof(struct hif_scatter_req_priv));
                 /* save the device instance*/
             pReqPriv->device = device;      
                 /* allocate the scatter request */
-            pReqPriv->pHifScatterReq = (HIF_SCATTER_REQ *)A_MALLOC(sizeof(HIF_SCATTER_REQ) + 
-                                         (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM))); 
+            pReqPriv->pHifScatterReq = (struct hif_scatter_req *)A_MALLOC(sizeof(struct hif_scatter_req) + 
+                                         (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item))); 
            
             if (NULL == pReqPriv->pHifScatterReq) {
                 A_FREE(pReqPriv);
                 break;      
             }           
                 /* just zero the main part of the scatter request */
-            A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(HIF_SCATTER_REQ));
+            A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(struct hif_scatter_req));
                 /* back pointer to the private struct */
             pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv;
                 /* allocate a bus request for this scatter request */
@@ -344,11 +344,11 @@ A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_I
         pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ;
         pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE;
      
-        status = A_OK;
+        status = 0;
         
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         CleanupHIFScatterResources(device);   
     }
     
@@ -356,10 +356,10 @@ A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_I
 }
 
     /* clean up scatter support */
-void CleanupHIFScatterResources(HIF_DEVICE *device)
+void CleanupHIFScatterResources(struct hif_device *device)
 {
-    HIF_SCATTER_REQ_PRIV    *pReqPriv;
-    HIF_SCATTER_REQ         *pReq;
+    struct hif_scatter_req_priv    *pReqPriv;
+    struct hif_scatter_req         *pReq;
     
         /* empty the free list */
         
@@ -371,7 +371,7 @@ void CleanupHIFScatterResources(HIF_DEVICE *device)
             break;    
         }   
         
-        pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0];
+        pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0];
         A_ASSERT(pReqPriv != NULL);
         
         if (pReqPriv->busrequest != NULL) {
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
index 1efc85c..eeddf60 100644
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
@@ -35,21 +35,21 @@
 
 #define MAILBOX_FOR_BLOCK_SIZE          1
 
-A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
+int DevEnableInterrupts(struct ar6k_device *pDev);
+int DevDisableInterrupts(struct ar6k_device *pDev);
 
-static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev);
+static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev);
 
-void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket)
+void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket)
 {
     LOCK_AR6K(pDev);
     HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
     UNLOCK_AR6K(pDev);
 }
 
-HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
+struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev)
 {
-    HTC_PACKET *pPacket;
+    struct htc_packet *pPacket;
 
     LOCK_AR6K(pDev);
     pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
@@ -58,13 +58,13 @@ HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
     return pPacket;
 }
 
-void DevCleanup(AR6K_DEVICE *pDev)
+void DevCleanup(struct ar6k_device *pDev)
 {
     DevCleanupGMbox(pDev);
 
     if (pDev->HifAttached) {
         HIFDetachHTC(pDev->HIFDevice);
-        pDev->HifAttached = FALSE;
+        pDev->HifAttached = false;
     }
 
     DevCleanupVirtualScatterSupport(pDev);
@@ -74,10 +74,10 @@ void DevCleanup(AR6K_DEVICE *pDev)
     }
 }
 
-A_STATUS DevSetup(AR6K_DEVICE *pDev)
+int DevSetup(struct ar6k_device *pDev)
 {
-    A_UINT32 blocksizes[AR6K_MAILBOXES];
-    A_STATUS status = A_OK;
+    u32 blocksizes[AR6K_MAILBOXES];
+    int status = 0;
     int      i;
     HTC_CALLBACKS htcCallbacks;
 
@@ -96,24 +96,24 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
 
         status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
-        pDev->HifAttached = TRUE;
+        pDev->HifAttached = true;
 
             /* get the addresses for all 4 mailboxes */
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
                                     &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
             /* carve up register I/O packets (these are for ASYNC register I/O ) */
         for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) {
-            HTC_PACKET *pIOPacket;
+            struct htc_packet *pIOPacket;
             pIOPacket = &pDev->RegIOBuffers[i].HtcPacket;
             SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket,
                                           pDev,
@@ -127,8 +127,8 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     blocksizes, sizeof(blocksizes));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
@@ -174,14 +174,14 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
                     AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
                         ("HIF requests that DSR yield per %d RECV packets \n",
                         pDev->HifIRQYieldParams.RecvPacketYieldCount));
-                    pDev->DSRCanYield = TRUE;
+                    pDev->DSRCanYield = true;
                 }
                 break;
             case HIF_DEVICE_IRQ_ASYNC_SYNC:
                 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
                 break;
             default:
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
         }
 
         pDev->HifMaskUmaskRecvEvent = NULL;
@@ -197,18 +197,18 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
 
         status = DevDisableInterrupts(pDev);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
         status = DevSetupGMbox(pDev);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (pDev->HifAttached) {
             HIFDetachHTC(pDev->HIFDevice);
-            pDev->HifAttached = FALSE;
+            pDev->HifAttached = false;
         }
     }
 
@@ -216,10 +216,10 @@ A_STATUS DevSetup(AR6K_DEVICE *pDev)
 
 }
 
-A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
+int DevEnableInterrupts(struct ar6k_device *pDev)
 {
-    A_STATUS                  status;
-    AR6K_IRQ_ENABLE_REGISTERS regs;
+    int                  status;
+    struct ar6k_irq_enable_registers regs;
 
     LOCK_AR6K(pDev);
 
@@ -254,7 +254,7 @@ A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
         COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK);
 
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
     UNLOCK_AR6K(pDev);
 
@@ -266,7 +266,7 @@ A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         /* Can't write it for some reason */
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Failed to update interrupt control registers err: %d\n", status));
@@ -276,9 +276,9 @@ A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
     return status;
 }
 
-A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
+int DevDisableInterrupts(struct ar6k_device *pDev)
 {
-    AR6K_IRQ_ENABLE_REGISTERS regs;
+    struct ar6k_irq_enable_registers regs;
 
     LOCK_AR6K(pDev);
         /* Disable all interrupts */
@@ -287,7 +287,7 @@ A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
     pDev->IrqEnableRegisters.error_status_enable = 0;
     pDev->IrqEnableRegisters.counter_int_status_enable = 0;
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
     UNLOCK_AR6K(pDev);
 
@@ -301,7 +301,7 @@ A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
 }
 
 /* enable device interrupts */
-A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
+int DevUnmaskInterrupts(struct ar6k_device *pDev)
 {
     /* for good measure, make sure interrupt are disabled before unmasking at the HIF
      * layer.
@@ -309,7 +309,7 @@ A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
      * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
      * The AR6K interrupt enables reset back to an "enabled" state when this happens.
      *  */
-    A_STATUS IntStatus = A_OK;
+    int IntStatus = 0;
     DevDisableInterrupts(pDev);
 
 #ifdef THREAD_X
@@ -327,7 +327,7 @@ A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
 }
 
 /* disable all device interrupts */
-A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
+int DevMaskInterrupts(struct ar6k_device *pDev)
 {
         /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while
          * we zero out our shadow registers in DevDisableInterrupts()*/
@@ -337,13 +337,13 @@ A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
 }
 
 /* callback when our fetch to enable/disable completes */
-static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevDoEnableDisableRecvAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" Failed to disable receiver, status:%d \n", pPacket->Status));
     }
@@ -355,10 +355,10 @@ static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacke
 /* disable packet reception (used in case the host runs out of buffers)
  * this is the "override" method when the HIF reports another methods to
  * disable recv events */
-static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
+static int DevDoEnableDisableRecvOverride(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode)
 {
-    A_STATUS                  status = A_OK;
-    HTC_PACKET                *pIOPacket = NULL;
+    int                  status = 0;
+    struct htc_packet                *pIOPacket = NULL;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
             EnableRecv,AsyncMode));
@@ -371,7 +371,7 @@ static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableR
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
@@ -391,9 +391,9 @@ static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableR
                                              EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
                                              NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status) && (pIOPacket != NULL)) {
+    if (status && (pIOPacket != NULL)) {
         AR6KFreeIOPacket(pDev,pIOPacket);
     }
 
@@ -403,11 +403,11 @@ static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableR
 /* disable packet reception (used in case the host runs out of buffers)
  * this is the "normal" method using the interrupt enable registers through
  * the host I/F */
-static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
+static int DevDoEnableDisableRecvNormal(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode)
 {
-    A_STATUS                  status = A_OK;
-    HTC_PACKET                *pIOPacket = NULL;
-    AR6K_IRQ_ENABLE_REGISTERS regs;
+    int                  status = 0;
+    struct htc_packet                *pIOPacket = NULL;
+    struct ar6k_irq_enable_registers regs;
 
         /* take the lock to protect interrupt enable shadows */
     LOCK_AR6K(pDev);
@@ -419,7 +419,7 @@ static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRec
     }
 
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
     UNLOCK_AR6K(pDev);
 
     do {
@@ -430,12 +430,12 @@ static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRec
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
                 /* copy values to write to our async I/O buffer */
-            A_MEMCPY(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
+            memcpy(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
 
                 /* stick in our completion routine when the I/O operation completes */
             pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
@@ -460,9 +460,9 @@ static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRec
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status) && (pIOPacket != NULL)) {
+    if (status && (pIOPacket != NULL)) {
         AR6KFreeIOPacket(pDev,pIOPacket);
     }
 
@@ -470,29 +470,29 @@ static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRec
 }
 
 
-A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
+int DevStopRecv(struct ar6k_device *pDev, bool AsyncMode)
 {
     if (NULL == pDev->HifMaskUmaskRecvEvent) {
-        return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode);
+        return DevDoEnableDisableRecvNormal(pDev,false,AsyncMode);
     } else {
-        return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode);
+        return DevDoEnableDisableRecvOverride(pDev,false,AsyncMode);
     }
 }
 
-A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
+int DevEnableRecv(struct ar6k_device *pDev, bool AsyncMode)
 {
     if (NULL == pDev->HifMaskUmaskRecvEvent) {
-        return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode);
+        return DevDoEnableDisableRecvNormal(pDev,true,AsyncMode);
     } else {
-        return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode);
+        return DevDoEnableDisableRecvOverride(pDev,true,AsyncMode);
     }
 }
 
-A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending)
+int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending)
 {
-    A_STATUS    status          = A_OK;
-    A_UCHAR     host_int_status = 0x0;
-    A_UINT32    counter         = 0x0;
+    int    status          = 0;
+    u8     host_int_status = 0x0;
+    u32 counter         = 0x0;
 
     if(TimeoutInMs < 100)
     {
@@ -507,25 +507,25 @@ A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pb
         status = HIFReadWrite(pDev->HIFDevice,
                               HOST_INT_STATUS_ADDRESS,
                              &host_int_status,
-                              sizeof(A_UCHAR),
+                              sizeof(u8),
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
-        if(A_FAILED(status))
+        if (status)
         {
             AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
             break;
         }
 
-        host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0;
+        host_int_status = !status ? (host_int_status & (1 << 0)):0;
         if(!host_int_status)
         {
-            status          = A_OK;
-           *pbIsRecvPending = FALSE;
+            status          = 0;
+           *pbIsRecvPending = false;
             break;
         }
         else
         {
-            *pbIsRecvPending = TRUE;
+            *pbIsRecvPending = true;
         }
 
         A_MDELAY(100);
@@ -536,9 +536,9 @@ A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pb
     return status;
 }
 
-void DevDumpRegisters(AR6K_DEVICE               *pDev,
-                      AR6K_IRQ_PROC_REGISTERS   *pIrqProcRegs,
-                      AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
+void DevDumpRegisters(struct ar6k_device               *pDev,
+                      struct ar6k_irq_proc_registers   *pIrqProcRegs,
+                      struct ar6k_irq_enable_registers *pIrqEnableRegs)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n"));
@@ -585,39 +585,39 @@ void DevDumpRegisters(AR6K_DEVICE               *pDev,
 }
 
 
-#define DEV_GET_VIRT_DMA_INFO(p)  ((DEV_SCATTER_DMA_VIRTUAL_INFO *)((p)->HIFPrivate[0]))
+#define DEV_GET_VIRT_DMA_INFO(p)  ((struct dev_scatter_dma_virtual_info *)((p)->HIFPrivate[0]))
 
-static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
+static struct hif_scatter_req *DevAllocScatterReq(struct hif_device *Context)
 {
-    DL_LIST *pItem;
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct dl_list *pItem;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
     LOCK_AR6K(pDev);
     pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead);
     UNLOCK_AR6K(pDev);
     if (pItem != NULL) {
-        return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink);
     }
     return NULL;
 }
 
-static void DevFreeScatterReq(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
+static void DevFreeScatterReq(struct hif_device *Context, struct hif_scatter_req *pReq)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
     LOCK_AR6K(pDev);
     DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink);
     UNLOCK_AR6K(pDev);
 }
 
-A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA)
+int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA)
 {
-    A_UINT8         *pDMABuffer = NULL;
+    u8 *pDMABuffer = NULL;
     int             i, remaining;
-    A_UINT32        length;
+    u32 length;
 
     pDMABuffer = pReq->pScatterBounceBuffer;
 
     if (pDMABuffer == NULL) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return A_EINVAL;
     }
 
@@ -628,30 +628,30 @@ A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA
         length = min((int)pReq->ScatterList[i].Length, remaining);
 
         if (length != (int)pReq->ScatterList[i].Length) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
                 /* there is a problem with the scatter list */
             return A_EINVAL;
         }
 
         if (FromDMA) {
                 /* from DMA buffer */
-            A_MEMCPY(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
+            memcpy(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
         } else {
                 /* to DMA buffer */
-            A_MEMCPY(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
+            memcpy(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
         }
 
         pDMABuffer += length;
         remaining -= length;
     }
 
-    return A_OK;
+    return 0;
 }
 
-static void DevReadWriteScatterAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevReadWriteScatterAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE     *pDev = (AR6K_DEVICE *)Context;
-    HIF_SCATTER_REQ *pReq = (HIF_SCATTER_REQ *)pPacket->pPktContext;
+    struct ar6k_device     *pDev = (struct ar6k_device *)Context;
+    struct hif_scatter_req *pReq = (struct hif_scatter_req *)pPacket->pPktContext;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
     
@@ -664,12 +664,12 @@ static void DevReadWriteScatterAsyncHandler(void *Context, HTC_PACKET *pPacket)
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n"));
 }
 
-static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
+static int DevReadWriteScatter(struct hif_device *Context, struct hif_scatter_req *pReq)
 {
-    AR6K_DEVICE     *pDev = (AR6K_DEVICE *)Context;
-    A_STATUS        status = A_OK;
-    HTC_PACKET      *pIOPacket = NULL;
-    A_UINT32        request = pReq->Request;
+    struct ar6k_device     *pDev = (struct ar6k_device *)Context;
+    int        status = 0;
+    struct htc_packet      *pIOPacket = NULL;
+    u32 request = pReq->Request;
 
     do {
 
@@ -680,7 +680,7 @@ static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
         }
 
         if (pReq->TotalLength == 0) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -719,27 +719,27 @@ static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
                               request,
                               (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if ((status != A_PENDING) && A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
+    if ((status != A_PENDING) && status && (request & HIF_ASYNCHRONOUS)) {
         if (pIOPacket != NULL) {
             AR6KFreeIOPacket(pDev,pIOPacket);
         }
         pReq->CompletionStatus = status;
         pReq->CompletionRoutine(pReq);
-        status = A_OK;
+        status = 0;
     }
 
     return status;
 }
 
 
-static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev)
+static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev)
 {
-    HIF_SCATTER_REQ *pReq;
+    struct hif_scatter_req *pReq;
 
     while (1) {
-        pReq = DevAllocScatterReq((HIF_DEVICE *)pDev);
+        pReq = DevAllocScatterReq((struct hif_device *)pDev);
         if (NULL == pReq) {
             break;
         }
@@ -749,23 +749,23 @@ static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev)
 }
 
     /* function to set up virtual scatter support if HIF layer has not implemented the interface */
-static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
+static int DevSetupVirtualScatterSupport(struct ar6k_device *pDev)
 {
-    A_STATUS                     status = A_OK;
+    int                     status = 0;
     int                          bufferSize, sgreqSize;
     int                          i;
-    DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo;
-    HIF_SCATTER_REQ              *pReq;
+    struct dev_scatter_dma_virtual_info *pVirtualInfo;
+    struct hif_scatter_req              *pReq;
 
-    bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
+    bufferSize = sizeof(struct dev_scatter_dma_virtual_info) +
                 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
 
-    sgreqSize = sizeof(HIF_SCATTER_REQ) +
-                    (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM));
+    sgreqSize = sizeof(struct hif_scatter_req) +
+                    (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item));
 
     for (i = 0; i < AR6K_SCATTER_REQS; i++) {
             /* allocate the scatter request, buffer info and the actual virtual buffer itself */
-        pReq = (HIF_SCATTER_REQ *)A_MALLOC(sgreqSize + bufferSize);
+        pReq = (struct hif_scatter_req *)A_MALLOC(sgreqSize + bufferSize);
 
         if (NULL == pReq) {
             status = A_NO_MEMORY;
@@ -775,8 +775,8 @@ static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
         A_MEMZERO(pReq, sgreqSize);
 
             /* the virtual DMA starts after the scatter request struct */
-        pVirtualInfo = (DEV_SCATTER_DMA_VIRTUAL_INFO *)((A_UINT8 *)pReq + sgreqSize);
-        A_MEMZERO(pVirtualInfo, sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO));
+        pVirtualInfo = (struct dev_scatter_dma_virtual_info *)((u8 *)pReq + sgreqSize);
+        A_MEMZERO(pVirtualInfo, sizeof(struct dev_scatter_dma_virtual_info));
 
         pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0];
             /* align buffer to cache line in case host controller can actually DMA this */
@@ -787,10 +787,10 @@ static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
         pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
         pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer;
             /* free request to the list */
-        DevFreeScatterReq((HIF_DEVICE *)pDev,pReq);
+        DevFreeScatterReq((struct hif_device *)pDev,pReq);
     }
 
-    if (A_FAILED(status)) {
+    if (status) {
         DevCleanupVirtualScatterSupport(pDev);
     } else {
         pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
@@ -804,16 +804,25 @@ static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
             pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
             pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
         }
-        pDev->ScatterIsVirtual = TRUE;
+        pDev->ScatterIsVirtual = true;
     }
 
     return status;
 }
 
+int DevCleanupMsgBundling(struct ar6k_device *pDev)
+{
+    if(NULL != pDev)
+    {
+        DevCleanupVirtualScatterSupport(pDev);
+    }
+
+    return 0;
+}
 
-A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
+int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer)
 {
-    A_STATUS status;
+    int status;
 
     if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) {
         AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
@@ -825,14 +834,14 @@ A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
                                 &pDev->HifScatterInfo,
                                 sizeof(pDev->HifScatterInfo));
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
             ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status));
 
             /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */
         status = DevSetupVirtualScatterSupport(pDev);
 
-        if (A_SUCCESS(status)) {
+        if (!status) {
              AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
                 ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n",
                     DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
@@ -844,7 +853,7 @@ A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
                     DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
     }
 
-    if (A_SUCCESS(status)) {
+    if (!status) {
             /* for the recv path, the maximum number of bytes per recv bundle is just limited
              * by the maximum transfer size at the HIF layer */
         pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
@@ -876,21 +885,21 @@ A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
     return status;
 }
 
-A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async)
+int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async)
 {
-    A_STATUS status;
+    int status;
 
     if (Read) {
             /* read operation */
         pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX;
         pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
-        A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
+        A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
     } else {
-        A_UINT32 mailboxWidth;
+        u32 mailboxWidth;
 
             /* write operation */
         pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC;
-        A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
+        A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
         if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) {
                 /* for large writes use the extended address */
             pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
@@ -919,11 +928,11 @@ A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq
 
     status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (Async) {
             pScatterReq->CompletionStatus = status;
             pScatterReq->CompletionRoutine(pScatterReq);
-            return A_OK;
+            return 0;
         }
         return status;
     }
@@ -936,7 +945,7 @@ A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq
         DEV_FINISH_SCATTER_OPERATION(pScatterReq);
     } else {
         if (status == A_PENDING) {
-            status = A_OK;
+            status = 0;
         }
     }
 
@@ -1002,16 +1011,16 @@ A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq
 
 #define TEST_CREDITS_RECV_TIMEOUT 100
 
-static A_UINT8  g_Buffer[TOTAL_BYTES];
-static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES];
-static A_UINT32 g_BlockSizes[AR6K_MAILBOXES];
+static u8 g_Buffer[TOTAL_BYTES];
+static u32 g_MailboxAddrs[AR6K_MAILBOXES];
+static u32 g_BlockSizes[AR6K_MAILBOXES];
 
 #define BUFFER_PROC_LIST_DEPTH 4
 
-typedef struct _BUFFER_PROC_LIST{
-    A_UINT8  *pBuffer;
-    A_UINT32 length;
-}BUFFER_PROC_LIST;
+struct buffer_proc_list {
+    u8 *pBuffer;
+    u32 length;
+};
 
 
 #define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
@@ -1023,9 +1032,9 @@ typedef struct _BUFFER_PROC_LIST{
 }
 
 /* a simple and crude way to send different "message" sizes */
-static void AssembleBufferList(BUFFER_PROC_LIST *pList)
+static void AssembleBufferList(struct buffer_proc_list *pList)
 {
-    A_UINT8 *pBuffer = g_Buffer;
+    u8 *pBuffer = g_Buffer;
 
 #if BUFFER_PROC_LIST_DEPTH < 4
 #error "Buffer processing list depth is not deep enough!!"
@@ -1038,17 +1047,17 @@ static void AssembleBufferList(BUFFER_PROC_LIST *pList)
 
 }
 
-#define FILL_ZERO     TRUE
-#define FILL_COUNTING FALSE
-static void InitBuffers(A_BOOL Zero)
+#define FILL_ZERO     true
+#define FILL_COUNTING false
+static void InitBuffers(bool Zero)
 {
-    A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer;
+    u16 *pBuffer16 = (u16 *)g_Buffer;
     int      i;
 
         /* fill buffer with 16 bit counting pattern or zeros */
     for (i = 0; i <  (TOTAL_BYTES / 2) ; i++) {
         if (!Zero) {
-            pBuffer16[i] = (A_UINT16)i;
+            pBuffer16[i] = (u16)i;
         } else {
             pBuffer16[i] = 0;
         }
@@ -1056,11 +1065,11 @@ static void InitBuffers(A_BOOL Zero)
 }
 
 
-static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
+static bool CheckOneBuffer(u16 *pBuffer16, int Length)
 {
     int      i;
-    A_UINT16 startCount;
-    A_BOOL   success = TRUE;
+    u16 startCount;
+    bool   success = true;
 
         /* get the starting count */
     startCount = pBuffer16[0];
@@ -1069,10 +1078,10 @@ static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
         /* scan the buffer and verify */
     for (i = 0; i < (Length / 2) ; i++,startCount++) {
             /* target will invert all the data */
-        if ((A_UINT16)pBuffer16[i] != (A_UINT16)~startCount) {
-            success = FALSE;
+        if ((u16)pBuffer16[i] != (u16)~startCount) {
+            success = false;
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n",
-                        pBuffer16[i], ((A_UINT16)~startCount), i, Length));
+                        pBuffer16[i], ((u16)~startCount), i, Length));
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n",
                         pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3]));
             break;
@@ -1082,21 +1091,21 @@ static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
     return success;
 }
 
-static A_BOOL CheckBuffers(void)
+static bool CheckBuffers(void)
 {
     int      i;
-    A_BOOL   success = TRUE;
-    BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
+    bool   success = true;
+    struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH];
 
         /* assemble the list */
     AssembleBufferList(checkList);
 
         /* scan the buffers and verify */
     for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) {
-        success = CheckOneBuffer((A_UINT16 *)checkList[i].pBuffer, checkList[i].length);
+        success = CheckOneBuffer((u16 *)checkList[i].pBuffer, checkList[i].length);
         if (!success) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
-                        (A_UINT32)checkList[i].pBuffer, checkList[i].length));
+                        (u32)checkList[i].pBuffer, checkList[i].length));
             break;
         }
     }
@@ -1105,10 +1114,10 @@ static A_BOOL CheckBuffers(void)
 }
 
     /* find the end marker for the last buffer we will be sending */
-static A_UINT16 GetEndMarker(void)
+static u16 GetEndMarker(void)
 {
-    A_UINT8  *pBuffer;
-    BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
+    u8 *pBuffer;
+    struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH];
 
         /* fill up buffers with the normal counting pattern */
     InitBuffers(FILL_COUNTING);
@@ -1119,17 +1128,17 @@ static A_UINT16 GetEndMarker(void)
     pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]);
 
         /* the last count in the last buffer is the marker */
-    return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8);
+    return (u16)pBuffer[0] | ((u16)pBuffer[1] << 8);
 }
 
 #define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
 
 /* send the ordered buffers to the target */
-static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
+static int SendBuffers(struct ar6k_device *pDev, int mbox)
 {
-    A_STATUS         status = A_OK;
-    A_UINT32         request = HIF_WR_SYNC_BLOCK_INC;
-    BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH];
+    int         status = 0;
+    u32 request = HIF_WR_SYNC_BLOCK_INC;
+    struct buffer_proc_list sendList[BUFFER_PROC_LIST_DEPTH];
     int              i;
     int              totalBytes = 0;
     int              paddedLength;
@@ -1156,7 +1165,7 @@ static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
                               paddedLength,
                               request,
                               NULL);
-        if (status != A_OK) {
+        if (status) {
             break;
         }
         totalBytes += sendList[i].length;
@@ -1169,20 +1178,20 @@ static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
 }
 
 /* poll the mailbox credit counter until we get a credit or timeout */
-static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
+static int GetCredits(struct ar6k_device *pDev, int mbox, int *pCredits)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      timeout = TEST_CREDITS_RECV_TIMEOUT;
-    A_UINT8  credits = 0;
-    A_UINT32 address;
+    u8 credits = 0;
+    u32 address;
 
-    while (TRUE) {
+    while (true) {
 
             /* Read the counter register to get credits, this auto-decrements  */
         address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
         status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
                               HIF_RD_SYNC_BYTE_FIX, NULL);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
             status = A_ERROR;
@@ -1207,7 +1216,7 @@ static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
 
     }
 
-    if (status == A_OK) {
+    if (status == 0) {
         *pCredits = credits;
     }
 
@@ -1216,11 +1225,11 @@ static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
 
 
 /* wait for the buffers to come back */
-static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
+static int RecvBuffers(struct ar6k_device *pDev, int mbox)
 {
-    A_STATUS         status = A_OK;
-    A_UINT32         request = HIF_RD_SYNC_BLOCK_INC;
-    BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH];
+    int         status = 0;
+    u32 request = HIF_RD_SYNC_BLOCK_INC;
+    struct buffer_proc_list recvList[BUFFER_PROC_LIST_DEPTH];
     int              curBuffer;
     int              credits;
     int              i;
@@ -1244,7 +1253,7 @@ static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
              * until we get at least 1 credit or it times out */
         status = GetCredits(pDev, mbox, &credits);
 
-        if (status != A_OK) {
+        if (status) {
             break;
         }
 
@@ -1264,7 +1273,7 @@ static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
                                   paddedLength,
                                   request,
                                   NULL);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n",
                         recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox]));
                 break;
@@ -1275,7 +1284,7 @@ static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
             curBuffer++;
         }
 
-        if (status != A_OK) {
+        if (status) {
             break;
         }
             /* go back and get some more */
@@ -1283,7 +1292,7 @@ static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
     }
 
     if (totalBytes != TEST_BYTES) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
     }  else {
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n",
             mbox, totalBytes, totalwPadding));
@@ -1294,15 +1303,15 @@ static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
 
 }
 
-static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
+static int DoOneMboxHWTest(struct ar6k_device *pDev, int mbox)
 {
-    A_STATUS status;
+    int status;
 
     do {
             /* send out buffers */
         status = SendBuffers(pDev,mbox);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
             break;
         }
@@ -1310,7 +1319,7 @@ static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
             /* go get them, this will block */
         status =  RecvBuffers(pDev, mbox);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
             break;
         }
@@ -1324,21 +1333,21 @@ static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
 
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
 
-    }  while (FALSE);
+    }  while (false);
 
     return status;
 }
 
 /* here is where the test starts */
-A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
+int DoMboxHWTest(struct ar6k_device *pDev)
 {
     int      i;
-    A_STATUS status;
+    int status;
     int      credits = 0;
-    A_UINT8  params[4];
+    u8 params[4];
     int      numBufs;
     int      bufferSize;
-    A_UINT16 temp;
+    u16 temp;
 
 
     AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START -  \n"));
@@ -1348,8 +1357,8 @@ A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
                                     g_MailboxAddrs, sizeof(g_MailboxAddrs));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
@@ -1357,8 +1366,8 @@ A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     g_BlockSizes, sizeof(g_BlockSizes));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
@@ -1380,7 +1389,7 @@ A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
              * mailbox 0 */
         status = GetCredits(pDev, 0, &credits);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
             break;
         }
@@ -1395,13 +1404,13 @@ A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
             break;
         }
 
         numBufs = params[0];
-        bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]);
+        bufferSize = (int)(((u16)params[2] << 8) | (u16)params[1]);
 
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE,
             ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n",
@@ -1418,29 +1427,29 @@ A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
 
         status = HIFReadWrite(pDev->HIFDevice,
                               SCRATCH_ADDRESS + 4,
-                              (A_UINT8 *)&temp,
+                              (u8 *)&temp,
                               2,
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
             break;
         }
 
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
 
-        temp = (A_UINT16)g_BlockSizes[1];
+        temp = (u16)g_BlockSizes[1];
             /* convert to a mask */
         temp = temp - 1;
         status = HIFReadWrite(pDev->HIFDevice,
                               SCRATCH_ADDRESS + 6,
-                              (A_UINT8 *)&temp,
+                              (u8 *)&temp,
                               2,
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
             break;
         }
@@ -1450,14 +1459,14 @@ A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
             /* execute the test on each mailbox */
         for (i = 0; i < AR6K_MAILBOXES; i++) {
             status = DoOneMboxHWTest(pDev, i);
-            if (status != A_OK) {
+            if (status) {
                 break;
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
-    if (status == A_OK) {
+    if (status == 0) {
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! -  \n"));
     } else {
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! -  \n"));
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k.h b/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
index b30fd87..1ff2218 100644
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
@@ -43,40 +43,40 @@
 //#define MBOXHW_UNIT_TEST 1
 
 #include "athstartpack.h"
-typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS {
-    A_UINT8                      host_int_status;
-    A_UINT8                      cpu_int_status;
-    A_UINT8                      error_int_status;
-    A_UINT8                      counter_int_status;
-    A_UINT8                      mbox_frame;
-    A_UINT8                      rx_lookahead_valid;
-    A_UINT8                      host_int_status2;
-    A_UINT8                      gmbox_rx_avail;
-    A_UINT32                     rx_lookahead[2];
-    A_UINT32                     rx_gmbox_lookahead_alias[2];
-} POSTPACK AR6K_IRQ_PROC_REGISTERS;
-
-#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
-
-typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS {
-    A_UINT8                      int_status_enable;
-    A_UINT8                      cpu_int_status_enable;
-    A_UINT8                      error_status_enable;
-    A_UINT8                      counter_int_status_enable;
-} POSTPACK AR6K_IRQ_ENABLE_REGISTERS;
-
-typedef PREPACK struct _AR6K_GMBOX_CTRL_REGISTERS {
-    A_UINT8                      int_status_enable;
-} POSTPACK AR6K_GMBOX_CTRL_REGISTERS;
+PREPACK struct ar6k_irq_proc_registers {
+    u8 host_int_status;
+    u8 cpu_int_status;
+    u8 error_int_status;
+    u8 counter_int_status;
+    u8 mbox_frame;
+    u8 rx_lookahead_valid;
+    u8 host_int_status2;
+    u8 gmbox_rx_avail;
+    u32 rx_lookahead[2];
+    u32 rx_gmbox_lookahead_alias[2];
+} POSTPACK;
+
+#define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers)
+
+PREPACK struct ar6k_irq_enable_registers {
+    u8 int_status_enable;
+    u8 cpu_int_status_enable;
+    u8 error_status_enable;
+    u8 counter_int_status_enable;
+} POSTPACK;
+
+PREPACK struct ar6k_gmbox_ctrl_registers {
+    u8 int_status_enable;
+} POSTPACK;
 
 #include "athendpack.h"
 
-#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS)
+#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers)
 
 #define AR6K_REG_IO_BUFFER_SIZE     32
 #define AR6K_MAX_REG_IO_BUFFERS     8
-#define FROM_DMA_BUFFER TRUE
-#define TO_DMA_BUFFER   FALSE
+#define FROM_DMA_BUFFER true
+#define TO_DMA_BUFFER   false
 #define AR6K_SCATTER_ENTRIES_PER_REQ            16
 #define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER      16*1024
 #define AR6K_SCATTER_REQS                       4
@@ -89,107 +89,107 @@ typedef PREPACK struct _AR6K_GMBOX_CTRL_REGISTERS {
 #define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER      4*1024
 
 /* buffers for ASYNC I/O */
-typedef struct AR6K_ASYNC_REG_IO_BUFFER {
-    HTC_PACKET    HtcPacket;   /* we use an HTC packet as a wrapper for our async register-based I/O */
-    A_UINT8       _Pad1[A_CACHE_LINE_PAD];
-    A_UINT8       Buffer[AR6K_REG_IO_BUFFER_SIZE];  /* cache-line safe with pads around */
-    A_UINT8       _Pad2[A_CACHE_LINE_PAD];
-} AR6K_ASYNC_REG_IO_BUFFER;
-
-typedef struct _AR6K_GMBOX_INFO { 
+struct ar6k_async_reg_io_buffer {
+    struct htc_packet    HtcPacket;   /* we use an HTC packet as a wrapper for our async register-based I/O */
+    u8 _Pad1[A_CACHE_LINE_PAD];
+    u8 Buffer[AR6K_REG_IO_BUFFER_SIZE];  /* cache-line safe with pads around */
+    u8 _Pad2[A_CACHE_LINE_PAD];
+};
+
+struct ar6k_gmbox_info { 
     void        *pProtocolContext;
-    A_STATUS    (*pMessagePendingCallBack)(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes);
-    A_STATUS    (*pCreditsPendingCallback)(void *pContext, int NumCredits,  A_BOOL CreditIRQEnabled);
-    void        (*pTargetFailureCallback)(void *pContext, A_STATUS Status);
+    int    (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes);
+    int    (*pCreditsPendingCallback)(void *pContext, int NumCredits,  bool CreditIRQEnabled);
+    void        (*pTargetFailureCallback)(void *pContext, int Status);
     void        (*pStateDumpCallback)(void *pContext);
-    A_BOOL      CreditCountIRQEnabled;    
-} AR6K_GMBOX_INFO; 
+    bool      CreditCountIRQEnabled;
+}; 
 
-typedef struct _AR6K_DEVICE {
+struct ar6k_device {
     A_MUTEX_T                   Lock;
-    A_UINT8       _Pad1[A_CACHE_LINE_PAD];
-    AR6K_IRQ_PROC_REGISTERS     IrqProcRegisters;   /* cache-line safe with pads around */
-    A_UINT8       _Pad2[A_CACHE_LINE_PAD];
-    AR6K_IRQ_ENABLE_REGISTERS   IrqEnableRegisters; /* cache-line safe with pads around */
-    A_UINT8       _Pad3[A_CACHE_LINE_PAD];
+    u8 _Pad1[A_CACHE_LINE_PAD];
+    struct ar6k_irq_proc_registers     IrqProcRegisters;   /* cache-line safe with pads around */
+    u8 _Pad2[A_CACHE_LINE_PAD];
+    struct ar6k_irq_enable_registers   IrqEnableRegisters; /* cache-line safe with pads around */
+    u8 _Pad3[A_CACHE_LINE_PAD];
     void                        *HIFDevice;
-    A_UINT32                    BlockSize;
-    A_UINT32                    BlockMask;
-    HIF_DEVICE_MBOX_INFO        MailBoxInfo;
+    u32 BlockSize;
+    u32 BlockMask;
+    struct hif_device_mbox_info        MailBoxInfo;
     HIF_PENDING_EVENTS_FUNC     GetPendingEventsFunc;
     void                        *HTCContext;
-    HTC_PACKET_QUEUE            RegisterIOList;
-    AR6K_ASYNC_REG_IO_BUFFER    RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
+    struct htc_packet_queue            RegisterIOList;
+    struct ar6k_async_reg_io_buffer    RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
     void                        (*TargetFailureCallback)(void *Context);
-    A_STATUS                    (*MessagePendingCallback)(void *Context, 
-                                                          A_UINT32 LookAheads[], 
+    int                    (*MessagePendingCallback)(void *Context,
+                                                          u32 LookAheads[],
                                                           int NumLookAheads, 
-                                                          A_BOOL *pAsyncProc,
+                                                          bool *pAsyncProc,
                                                           int *pNumPktsFetched);
     HIF_DEVICE_IRQ_PROCESSING_MODE  HifIRQProcessingMode;
     HIF_MASK_UNMASK_RECV_EVENT      HifMaskUmaskRecvEvent;
-    A_BOOL                          HifAttached;
-    HIF_DEVICE_IRQ_YIELD_PARAMS     HifIRQYieldParams;
-    A_BOOL                          DSRCanYield;
+    bool                          HifAttached;
+    struct hif_device_irq_yield_params     HifIRQYieldParams;
+    bool                          DSRCanYield;
     int                             CurrentDSRRecvCount;
-    HIF_DEVICE_SCATTER_SUPPORT_INFO HifScatterInfo;
-    DL_LIST                         ScatterReqHead; 
-    A_BOOL                          ScatterIsVirtual;    
+    struct hif_device_scatter_support_info HifScatterInfo;
+    struct dl_list                         ScatterReqHead; 
+    bool                          ScatterIsVirtual;
     int                             MaxRecvBundleSize;
     int                             MaxSendBundleSize;
-    AR6K_GMBOX_INFO                 GMboxInfo;
-    A_BOOL                          GMboxEnabled; 
-    AR6K_GMBOX_CTRL_REGISTERS       GMboxControlRegisters;
+    struct ar6k_gmbox_info                 GMboxInfo;
+    bool                          GMboxEnabled;
+    struct ar6k_gmbox_ctrl_registers       GMboxControlRegisters;
     int                             RecheckIRQStatusCnt;
-} AR6K_DEVICE;
+};
 
 #define LOCK_AR6K(p)      A_MUTEX_LOCK(&(p)->Lock);
 #define UNLOCK_AR6K(p)    A_MUTEX_UNLOCK(&(p)->Lock);
 #define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1  /* note: no need to lock this, it only gets set */
 
-A_STATUS DevSetup(AR6K_DEVICE *pDev);
-void     DevCleanup(AR6K_DEVICE *pDev);
-A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
-                            A_UINT32    *pLookAhead,
+int DevSetup(struct ar6k_device *pDev);
+void     DevCleanup(struct ar6k_device *pDev);
+int DevUnmaskInterrupts(struct ar6k_device *pDev);
+int DevMaskInterrupts(struct ar6k_device *pDev);
+int DevPollMboxMsgRecv(struct ar6k_device *pDev,
+                            u32 *pLookAhead,
                             int          TimeoutMS);
-A_STATUS DevRWCompletionHandler(void *context, A_STATUS status);
-A_STATUS DevDsrHandler(void *context);
-A_STATUS DevCheckPendingRecvMsgsAsync(void *context);
-void     DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev);
-void     DevDumpRegisters(AR6K_DEVICE               *pDev,
-                          AR6K_IRQ_PROC_REGISTERS   *pIrqProcRegs,
-                          AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs);
-
-#define DEV_STOP_RECV_ASYNC TRUE
-#define DEV_STOP_RECV_SYNC  FALSE
-#define DEV_ENABLE_RECV_ASYNC TRUE
-#define DEV_ENABLE_RECV_SYNC  FALSE
-A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
-A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
-A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending);
+int DevRWCompletionHandler(void *context, int status);
+int DevDsrHandler(void *context);
+int DevCheckPendingRecvMsgsAsync(void *context);
+void     DevAsyncIrqProcessComplete(struct ar6k_device *pDev);
+void     DevDumpRegisters(struct ar6k_device               *pDev,
+                          struct ar6k_irq_proc_registers   *pIrqProcRegs,
+                          struct ar6k_irq_enable_registers *pIrqEnableRegs);
+
+#define DEV_STOP_RECV_ASYNC true
+#define DEV_STOP_RECV_SYNC  false
+#define DEV_ENABLE_RECV_ASYNC true
+#define DEV_ENABLE_RECV_SYNC  false
+int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode);
+int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode);
+int DevEnableInterrupts(struct ar6k_device *pDev);
+int DevDisableInterrupts(struct ar6k_device *pDev);
+int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending);
 
 #define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask)))
 #define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length)
 #define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0)
 
-static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) {
-    A_UINT32 paddedLength;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
-    A_STATUS status;
+static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) {
+    u32 paddedLength;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
+    int status;
 
        /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength);
 
 #if 0                    
     if (paddedLength > pPacket->BufferLength) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         if (pPacket->Completion != NULL) {
             COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
-            return A_OK;
+            return 0;
         }
         return A_EINVAL;
     }
@@ -212,29 +212,29 @@ static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_U
         pPacket->Status = status;
     } else {
         if (status == A_PENDING) {
-            status = A_OK;    
+            status = 0;
         }    
     }
 
     return status;
 }
                     
-static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) {
-    A_UINT32 paddedLength;
-    A_STATUS status;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) {
+    u32 paddedLength;
+    int status;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
 
         /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength);
                     
     if (paddedLength > pPacket->BufferLength) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
                     paddedLength,RecvLength,pPacket->BufferLength));
         if (pPacket->Completion != NULL) {
             COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
-            return A_OK;
+            return 0;
         }
         return A_EINVAL;
     }
@@ -272,27 +272,33 @@ static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_U
  *  
  */
   
-A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA);
+int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA);
     
     /* copy any READ data back into scatter list */        
-#define DEV_FINISH_SCATTER_OPERATION(pR)                      \
-    if (A_SUCCESS((pR)->CompletionStatus) &&                  \
-        !((pR)->Request & HIF_WRITE) &&                       \
-         ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {   \
-         (pR)->CompletionStatus = DevCopyScatterListToFromDMABuffer((pR),FROM_DMA_BUFFER); \
-    }
+#define DEV_FINISH_SCATTER_OPERATION(pR)				\
+do {									\
+	if (!((pR)->CompletionStatus) &&				\
+	    !((pR)->Request & HIF_WRITE) &&				\
+	    ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {		\
+		(pR)->CompletionStatus =				\
+			DevCopyScatterListToFromDMABuffer((pR),		\
+							  FROM_DMA_BUFFER); \
+	}								\
+} while (0)
     
     /* copy any WRITE data to bounce buffer */
-static INLINE A_STATUS DEV_PREPARE_SCATTER_OPERATION(HIF_SCATTER_REQ *pReq)  { 
+static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq)  {
     if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
         return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);    
     } else {
-        return A_OK;    
+        return 0;
     }
 }
         
     
-A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer);
+int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer);
+
+int DevCleanupMsgBundling(struct ar6k_device *pDev);
                                   
 #define DEV_GET_MAX_MSG_PER_BUNDLE(pDev)        (pDev)->HifScatterInfo.MaxScatterEntries
 #define DEV_GET_MAX_BUNDLE_LENGTH(pDev)         (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
@@ -305,25 +311,25 @@ A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer);
 #define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev)   (pDev)->MaxRecvBundleSize
 #define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)   (pDev)->MaxSendBundleSize
 
-#define DEV_SCATTER_READ  TRUE
-#define DEV_SCATTER_WRITE FALSE
-#define DEV_SCATTER_ASYNC TRUE
-#define DEV_SCATTER_SYNC  FALSE
-A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async);
+#define DEV_SCATTER_READ  true
+#define DEV_SCATTER_WRITE false
+#define DEV_SCATTER_ASYNC true
+#define DEV_SCATTER_SYNC  false
+int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async);
 
 #ifdef MBOXHW_UNIT_TEST
-A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev);
+int DoMboxHWTest(struct ar6k_device *pDev);
 #endif
 
     /* completely virtual */
-typedef struct _DEV_SCATTER_DMA_VIRTUAL_INFO {
-    A_UINT8            *pVirtDmaBuffer;      /* dma-able buffer - CPU accessible address */
-    A_UINT8            DataArea[1];      /* start of data area */
-} DEV_SCATTER_DMA_VIRTUAL_INFO;
+struct dev_scatter_dma_virtual_info {
+    u8 *pVirtDmaBuffer;      /* dma-able buffer - CPU accessible address */
+    u8 DataArea[1];      /* start of data area */
+};
 
 
 
-void     DumpAR6KDevState(AR6K_DEVICE *pDev);
+void     DumpAR6KDevState(struct ar6k_device *pDev);
 
 /**************************************************/
 /****** GMBOX functions and definitions
@@ -333,21 +339,21 @@ void     DumpAR6KDevState(AR6K_DEVICE *pDev);
 
 #ifdef ATH_AR6K_ENABLE_GMBOX
 
-void     DevCleanupGMbox(AR6K_DEVICE *pDev);
-A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev);
-A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev);
-void     DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev);
+void     DevCleanupGMbox(struct ar6k_device *pDev);
+int DevSetupGMbox(struct ar6k_device *pDev);
+int DevCheckGMboxInterrupts(struct ar6k_device *pDev);
+void     DevNotifyGMboxTargetFailure(struct ar6k_device *pDev);
 
 #else
 
     /* compiled out */
 #define DevCleanupGMbox(p)
-#define DevCheckGMboxInterrupts(p) A_OK
+#define DevCheckGMboxInterrupts(p) 0
 #define DevNotifyGMboxTargetFailure(p)
 
-static INLINE A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) {
-    pDev->GMboxEnabled = FALSE;
-    return A_OK;    
+static INLINE int DevSetupGMbox(struct ar6k_device *pDev) {
+    pDev->GMboxEnabled = false;
+    return 0;
 }
 
 #endif
@@ -355,12 +361,12 @@ static INLINE A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) {
 #ifdef ATH_AR6K_ENABLE_GMBOX
 
     /* GMBOX protocol modules must expose each of these internal APIs */
-HCI_TRANSPORT_HANDLE GMboxAttachProtocol(AR6K_DEVICE *pDev, HCI_TRANSPORT_CONFIG_INFO *pInfo);
-A_STATUS             GMboxProtocolInstall(AR6K_DEVICE *pDev);
-void                 GMboxProtocolUninstall(AR6K_DEVICE *pDev);
+HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo);
+int             GMboxProtocolInstall(struct ar6k_device *pDev);
+void                 GMboxProtocolUninstall(struct ar6k_device *pDev);
 
     /* API used by GMBOX protocol modules */
-AR6K_DEVICE  *HTCGetAR6KDevice(void *HTCHandle);
+struct ar6k_device  *HTCGetAR6KDevice(void *HTCHandle);
 #define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
 {                                                                  \
     (pDev)->GMboxInfo.pProtocolContext = (context);                \
@@ -372,11 +378,11 @@ AR6K_DEVICE  *HTCGetAR6KDevice(void *HTCHandle);
 
 #define DEV_GMBOX_GET_PROTOCOL(pDev)  (pDev)->GMboxInfo.pProtocolContext
 
-A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength);
-A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength);
+int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength);
+int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength);
 
-#define PROC_IO_ASYNC TRUE
-#define PROC_IO_SYNC  FALSE
+#define PROC_IO_ASYNC true
+#define PROC_IO_SYNC  false
 typedef enum GMBOX_IRQ_ACTION_TYPE {
     GMBOX_ACTION_NONE = 0,
     GMBOX_DISABLE_ALL,
@@ -387,11 +393,11 @@ typedef enum GMBOX_IRQ_ACTION_TYPE {
     GMBOX_CREDIT_IRQ_DISABLE,
 } GMBOX_IRQ_ACTION_TYPE;
 
-A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE, A_BOOL AsyncMode);
-A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits);
-A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize);
-A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes);
-A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int SignalNumber, int AckTimeoutMS);
+int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode);
+int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits);
+int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize);
+int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes);
+int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS);
 
 #endif
 
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
index 920123b..5e6d1e0 100644
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
@@ -33,17 +33,17 @@
 #include "htc_packet.h"
 #include "ar6k.h"
 
-extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
-extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
+extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket);
+extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev);
 
-static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev);
+static int DevServiceDebugInterrupt(struct ar6k_device *pDev);
 
 #define DELAY_PER_INTERVAL_MS 10  /* 10 MS delay per polling interval */
 
 /* completion routine for ALL HIF layer async I/O */
-A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
+int DevRWCompletionHandler(void *context, int status)
 {
-    HTC_PACKET *pPacket = (HTC_PACKET *)context;
+    struct htc_packet *pPacket = (struct htc_packet *)context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                 ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n",
@@ -55,26 +55,26 @@ A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                 ("-DevRWCompletionHandler\n"));
 
-    return A_OK;
+    return 0;
 }
 
 /* mailbox recv message polling */
-A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
-                            A_UINT32    *pLookAhead,
+int DevPollMboxMsgRecv(struct ar6k_device *pDev,
+                            u32 *pLookAhead,
                             int          TimeoutMS)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
 
     A_ASSERT(timeout > 0);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
 
-    while (TRUE) {
+    while (true) {
 
         if (pDev->GetPendingEventsFunc != NULL) {
 
-            HIF_PENDING_EVENTS_INFO events;
+            struct hif_pending_events_info events;
 
 #ifdef THREAD_X
 			events.Polling =1;
@@ -85,7 +85,7 @@ A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
             status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
                                             &events,
                                             NULL);
-            if (A_FAILED(status))
+            if (status)
             {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
                 break;
@@ -104,12 +104,12 @@ A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
                 /* load the register table */
             status = HIFReadWrite(pDev->HIFDevice,
                                   HOST_INT_STATUS_ADDRESS,
-                                  (A_UINT8 *)&pDev->IrqProcRegisters,
+                                  (u8 *)&pDev->IrqProcRegisters,
                                   AR6K_IRQ_PROC_REGS_SIZE,
                                   HIF_RD_SYNC_BYTE_INC,
                                   NULL);
 
-            if (A_FAILED(status)){
+            if (status){
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
                 break;
             }
@@ -152,11 +152,11 @@ A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
     return status;
 }
 
-static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceCPUInterrupt(struct ar6k_device *pDev)
 {
-    A_STATUS status;
-    A_UINT8  cpu_int_status;
-    A_UINT8  regBuffer[4];
+    int status;
+    u8 cpu_int_status;
+    u8 regBuffer[4];
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
     cpu_int_status = pDev->IrqProcRegisters.cpu_int_status &
@@ -187,16 +187,16 @@ static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
                           HIF_WR_SYNC_BYTE_FIX,
                           NULL);
 
-    A_ASSERT(status == A_OK);
+    A_ASSERT(status == 0);
     return status;
 }
 
 
-static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceErrorInterrupt(struct ar6k_device *pDev)
 {
-    A_STATUS status;
-    A_UINT8  error_int_status;
-    A_UINT8  regBuffer[4];
+    int status;
+    u8 error_int_status;
+    u8 regBuffer[4];
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
     error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F;
@@ -241,14 +241,14 @@ static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
                           HIF_WR_SYNC_BYTE_FIX,
                           NULL);
 
-    A_ASSERT(status == A_OK);
+    A_ASSERT(status == 0);
     return status;
 }
 
-static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceDebugInterrupt(struct ar6k_device *pDev)
 {
-    A_UINT32 dummy;
-    A_STATUS status;
+    u32 dummy;
+    int status;
 
     /* Send a target failure event to the application */
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
@@ -266,18 +266,18 @@ static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
         /* read counter to clear interrupt */
     status = HIFReadWrite(pDev->HIFDevice,
                           COUNT_DEC_ADDRESS,
-                          (A_UINT8 *)&dummy,
+                          (u8 *)&dummy,
                           4,
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
 
-    A_ASSERT(status == A_OK);
+    A_ASSERT(status == 0);
     return status;
 }
 
-static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceCounterInterrupt(struct ar6k_device *pDev)
 {
-    A_UINT8 counter_int_status;
+    u8 counter_int_status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
 
@@ -296,21 +296,21 @@ static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
         return DevServiceDebugInterrupt(pDev);
     }
 
-    return A_OK;
+    return 0;
 }
 
 /* callback when our fetch to get interrupt status registers completes */
-static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevGetEventAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
-    A_UINT32    lookAhead = 0;
-    A_BOOL      otherInts = FALSE;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
+    u32 lookAhead = 0;
+    bool      otherInts = false;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
     do {
 
-        if (A_FAILED(pPacket->Status)) {
+        if (pPacket->Status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     (" GetEvents I/O request failed, status:%d \n", pPacket->Status));
             /* bail out, don't unmask HIF interrupt */
@@ -319,7 +319,7 @@ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
 
         if (pDev->GetPendingEventsFunc != NULL) {
                 /* the HIF layer collected the information for us */
-            HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacket->pBuffer;
+            struct hif_pending_events_info *pEvents = (struct hif_pending_events_info *)pPacket->pBuffer;
             if (pEvents->Events & HIF_RECV_MSG_AVAIL) {
                 lookAhead = pEvents->LookAhead;
                 if (0 == lookAhead) {
@@ -327,12 +327,12 @@ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
                 }
             }
             if (pEvents->Events & HIF_OTHER_EVENTS) {
-                otherInts = TRUE;
+                otherInts = true;
             }
         } else {
                 /* standard interrupt table handling.... */
-            AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer;
-            A_UINT8                 host_int_status;
+            struct ar6k_irq_proc_registers *pReg = (struct ar6k_irq_proc_registers *)pPacket->pBuffer;
+            u8 host_int_status;
 
             host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable;
 
@@ -349,7 +349,7 @@ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
 
             if (host_int_status) {
                     /* there are other interrupts to handle */
-                otherInts = TRUE;
+                otherInts = true;
             }
         }
 
@@ -363,7 +363,7 @@ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
             HIFAckInterrupt(pDev->HIFDevice);
         } else {
             int      fetched = 0;
-            A_STATUS status;
+            int status;
 
             AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
                     (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n",
@@ -372,14 +372,14 @@ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
                  * go get the next message */
             status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched);
 
-            if (A_SUCCESS(status) && !fetched) {
+            if (!status && !fetched) {
                     /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */
                 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n"));
                 DevAsyncIrqProcessComplete(pDev);
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
         /* free this IO packet */
     AR6KFreeIOPacket(pDev,pPacket);
@@ -388,11 +388,11 @@ static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
 
 /* called by the HTC layer when it wants us to check if the device has any more pending
  * recv messages, this starts off a series of async requests to read interrupt registers  */
-A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
+int DevCheckPendingRecvMsgsAsync(void *context)
 {
-    AR6K_DEVICE  *pDev = (AR6K_DEVICE *)context;
-    A_STATUS      status = A_OK;
-    HTC_PACKET   *pIOPacket;
+    struct ar6k_device  *pDev = (struct ar6k_device *)context;
+    int      status = 0;
+    struct htc_packet   *pIOPacket;
 
     /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can
      * cause us to switch contexts */
@@ -428,7 +428,7 @@ A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
                 /* there should be only 1 asynchronous request out at a time to read these registers
                  * so this should actually never happen */
             status = A_NO_MEMORY;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -439,7 +439,7 @@ A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
         if (pDev->GetPendingEventsFunc) {
                 /* HIF layer has it's own mechanism, pass the IO to it.. */
             status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
-                                                (HIF_PENDING_EVENTS_INFO *)pIOPacket->pBuffer,
+                                                (struct hif_pending_events_info *)pIOPacket->pBuffer,
                                                 pIOPacket);
 
         } else {
@@ -453,25 +453,25 @@ A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
         }
 
         AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n"));
-   } while (FALSE);
+   } while (false);
 
    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
 
    return status;
 }
 
-void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev)
+void DevAsyncIrqProcessComplete(struct ar6k_device *pDev)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n"));
     HIFAckInterrupt(pDev->HIFDevice);
 }
 
 /* process pending interrupts synchronously */
-static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pASyncProcessing)
+static int ProcessPendingIRQs(struct ar6k_device *pDev, bool *pDone, bool *pASyncProcessing)
 {
-    A_STATUS    status = A_OK;
-    A_UINT8     host_int_status = 0;
-    A_UINT32    lookAhead = 0;
+    int    status = 0;
+    u8 host_int_status = 0;
+    u32 lookAhead = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev));
 
@@ -490,7 +490,7 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
             }
 
             if (pDev->GetPendingEventsFunc != NULL) {
-                HIF_PENDING_EVENTS_INFO events;
+                struct hif_pending_events_info events;
 
 #ifdef THREAD_X
             events.Polling= 0;
@@ -501,7 +501,7 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
                                                 &events,
                                                 NULL);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
@@ -545,12 +545,12 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
 #endif /* CONFIG_MMC_SDHCI_S3C */
         status = HIFReadWrite(pDev->HIFDevice,
                               HOST_INT_STATUS_ADDRESS,
-                              (A_UINT8 *)&pDev->IrqProcRegisters,
+                              (u8 *)&pDev->IrqProcRegisters,
                               AR6K_IRQ_PROC_REGS_SIZE,
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -591,19 +591,19 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
             status = DevCheckGMboxInterrupts(pDev);
         }
 
-    } while (FALSE);
+    } while (false);
 
 
     do {
 
             /* did the interrupt status fetches succeed? */
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
         if ((0 == host_int_status) && (0 == lookAhead)) {
                 /* nothing to process, the caller can use this to break out of a loop */
-            *pDone = TRUE;
+            *pDone = true;
             break;
         }
 
@@ -617,14 +617,14 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
                  * completion routine of the callers read request. This can improve performance
                  * by reducing context switching when we rapidly pull packets */
             status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched);
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
             if (!fetched) {
                     /* HTC could not pull any messages out due to lack of resources */
                     /* force DSR handler to ack the interrupt */
-                *pASyncProcessing = FALSE;
+                *pASyncProcessing = false;
                 pDev->RecheckIRQStatusCnt = 0;
             }
         }
@@ -637,7 +637,7 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
         if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
                 /* CPU Interrupt */
             status = DevServiceCPUInterrupt(pDev);
-            if (A_FAILED(status)){
+            if (status){
                 break;
             }
         }
@@ -645,7 +645,7 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
         if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
                 /* Error Interrupt */
             status = DevServiceErrorInterrupt(pDev);
-            if (A_FAILED(status)){
+            if (status){
                 break;
             }
         }
@@ -653,12 +653,12 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
         if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
                 /* Counter Interrupt */
             status = DevServiceCounterInterrupt(pDev);
-            if (A_FAILED(status)){
+            if (status){
                 break;
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
         /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake
          * the target, if upper layers determine that we are in a low-throughput mode, we can
@@ -670,7 +670,7 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
          * messages from the mailbox before exiting the ISR routine. */
     if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPendingEventsFunc == NULL)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing done \n"));
-        *pDone = TRUE;
+        *pDone = true;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n",
@@ -681,12 +681,12 @@ static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pAS
 
 
 /* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/
-A_STATUS DevDsrHandler(void *context)
+int DevDsrHandler(void *context)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
-    A_STATUS    status = A_OK;
-    A_BOOL      done = FALSE;
-    A_BOOL      asyncProc = FALSE;
+    struct ar6k_device *pDev = (struct ar6k_device *)context;
+    int    status = 0;
+    bool      done = false;
+    bool      asyncProc = false;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
@@ -697,13 +697,13 @@ A_STATUS DevDsrHandler(void *context)
 
     while (!done) {
         status = ProcessPendingIRQs(pDev, &done, &asyncProc);
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
         if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
             /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */
-            asyncProc = FALSE;
+            asyncProc = false;
             /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers.
              * this has a nice side effect of blocking us until all async read requests are completed.
              * This behavior is required on some HIF implementations that do not allow ASYNC
@@ -725,7 +725,7 @@ A_STATUS DevDsrHandler(void *context)
 
     }
 
-    if (A_SUCCESS(status) && !asyncProc) {
+    if (!status && !asyncProc) {
             /* Ack the interrupt only if :
              *  1. we did not get any errors in processing interrupts
              *  2. there are no outstanding async processing requests */
@@ -744,26 +744,26 @@ A_STATUS DevDsrHandler(void *context)
 }
 
 #ifdef ATH_DEBUG_MODULE
-void DumpAR6KDevState(AR6K_DEVICE *pDev)
+void DumpAR6KDevState(struct ar6k_device *pDev)
 {
-    A_STATUS                    status;
-    AR6K_IRQ_ENABLE_REGISTERS   regs;
-    AR6K_IRQ_PROC_REGISTERS     procRegs;
+    int                    status;
+    struct ar6k_irq_enable_registers   regs;
+    struct ar6k_irq_proc_registers     procRegs;
 
     LOCK_AR6K(pDev);
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
     UNLOCK_AR6K(pDev);
 
         /* load the register table from the device */
     status = HIFReadWrite(pDev->HIFDevice,
                           HOST_INT_STATUS_ADDRESS,
-                          (A_UINT8 *)&procRegs,
+                          (u8 *)&procRegs,
                           AR6K_IRQ_PROC_REGS_SIZE,
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
             ("DumpAR6KDevState : Failed to read register table (%d) \n",status));
         return;
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
index e3d270d..3740011 100644
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
@@ -54,18 +54,18 @@
 
 
     /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */ 
-extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
-extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
+extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket);
+extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev);
 
 
 /* callback when our fetch to enable/disable completes */
-static void DevGMboxIRQActionAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevGMboxIRQActionAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status));
     }
@@ -74,26 +74,26 @@ static void DevGMboxIRQActionAsyncHandler(void *Context, HTC_PACKET *pPacket)
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n"));
 }
 
-static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
+static int DevGMboxCounterEnableDisable(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode)
 {
-    A_STATUS                  status = A_OK;
-    AR6K_IRQ_ENABLE_REGISTERS regs;
-    HTC_PACKET                *pIOPacket = NULL;  
+    int                  status = 0;
+    struct ar6k_irq_enable_registers regs;
+    struct htc_packet                *pIOPacket = NULL;  
     
     LOCK_AR6K(pDev);
     
     if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
-        pDev->GMboxInfo.CreditCountIRQEnabled = TRUE;
+        pDev->GMboxInfo.CreditCountIRQEnabled = true;
         pDev->IrqEnableRegisters.counter_int_status_enable |=
             COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER);
         pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01);
     } else {
-        pDev->GMboxInfo.CreditCountIRQEnabled = FALSE;
+        pDev->GMboxInfo.CreditCountIRQEnabled = false;
         pDev->IrqEnableRegisters.counter_int_status_enable &=
             ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER));    
     }
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
     UNLOCK_AR6K(pDev);
 
@@ -105,12 +105,12 @@ static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
                 /* copy values to write to our async I/O buffer */
-            A_MEMCPY(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+            memcpy(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
                 /* stick in our completion routine when the I/O operation completes */
             pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
@@ -135,9 +135,9 @@ static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION
                               AR6K_IRQ_ENABLE_REGS_SIZE,
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);    
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));    
     } else {
@@ -155,11 +155,11 @@ static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION
 }
 
 
-A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
+int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode)
 {
-    A_STATUS      status = A_OK;
-    HTC_PACKET    *pIOPacket = NULL;   
-    A_UINT8       GMboxIntControl[4];
+    int      status = 0;
+    struct htc_packet    *pIOPacket = NULL;   
+    u8 GMboxIntControl[4];
 
     if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
         return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode);
@@ -192,7 +192,7 @@ A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A
             break;
         case GMBOX_ACTION_NONE:
         default:
-            A_ASSERT(FALSE);    
+            A_ASSERT(false);
             break;
     }
     
@@ -211,12 +211,12 @@ A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
                 /* copy values to write to our async I/O buffer */
-            A_MEMCPY(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
+            memcpy(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
 
                 /* stick in our completion routine when the I/O operation completes */
             pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
@@ -242,9 +242,9 @@ A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A
                               HIF_WR_SYNC_BYTE_FIX,
                               NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));    
     } else {
@@ -261,18 +261,18 @@ A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A
     return status;
 }
 
-void DevCleanupGMbox(AR6K_DEVICE *pDev)
+void DevCleanupGMbox(struct ar6k_device *pDev)
 {
     if (pDev->GMboxEnabled) {
-        pDev->GMboxEnabled = FALSE;
+        pDev->GMboxEnabled = false;
         GMboxProtocolUninstall(pDev);        
     }
 }
 
-A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev)
+int DevSetupGMbox(struct ar6k_device *pDev)
 {
-    A_STATUS    status = A_OK;
-    A_UINT8     muxControl[4];
+    int    status = 0;
+    u8 muxControl[4];
     
     do {
         
@@ -285,7 +285,7 @@ A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev)
                     
         status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
        
@@ -305,29 +305,29 @@ A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev)
                               HIF_WR_SYNC_BYTE_FIX,  /* hit this register 4 times */
                               NULL);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
         status = GMboxProtocolInstall(pDev);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
-        pDev->GMboxEnabled = TRUE;
+        pDev->GMboxEnabled = true;
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
-A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
+int DevCheckGMboxInterrupts(struct ar6k_device *pDev)
 {
-    A_STATUS status = A_OK;
-    A_UINT8  counter_int_status;
+    int status = 0;
+    u8 counter_int_status;
     int      credits;
-    A_UINT8  host_int_status2;
+    u8 host_int_status2;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n"));
      
@@ -348,7 +348,7 @@ A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
             status = A_ECOMM;    
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
                 pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status);        
             }
@@ -360,12 +360,12 @@ A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
                 A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL);
                 status = pDev->GMboxInfo.pMessagePendingCallBack(
                                 pDev->GMboxInfo.pProtocolContext,
-                                (A_UINT8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
+                                (u8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
                                 pDev->IrqProcRegisters.gmbox_rx_avail);
             }
         } 
         
-        if (A_FAILED(status)) {
+        if (status) {
            break;                
         }
         
@@ -378,7 +378,7 @@ A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
                 /* do synchronous read */
             status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits);
             
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
             
@@ -388,7 +388,7 @@ A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
                                                              pDev->GMboxInfo.CreditCountIRQEnabled);
         }
         
-    } while (FALSE);
+    } while (false);
     
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status));
     
@@ -396,12 +396,12 @@ A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
 }
 
 
-A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength) 
+int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength)
 {
-    A_UINT32 paddedLength;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
-    A_STATUS status;
-    A_UINT32 address;
+    u32 paddedLength;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
+    int status;
+    u32 address;
     
        /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength);
@@ -426,31 +426,31 @@ A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLen
         pPacket->Status = status;
     } else {
         if (status == A_PENDING) {
-            status = A_OK;    
+            status = 0;
         }    
     }
 
     return status;
 }
 
-A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength) 
+int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength)
 {
     
-    A_UINT32 paddedLength;
-    A_STATUS status;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+    u32 paddedLength;
+    int status;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
 
         /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength);
                     
     if (paddedLength > pPacket->BufferLength) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
                     paddedLength,ReadLength,pPacket->BufferLength));
         if (pPacket->Completion != NULL) {
             COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
-            return A_OK;
+            return 0;
         }
         return A_EINVAL;
     }
@@ -477,7 +477,7 @@ A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLengt
 }
 
 
-static int ProcessCreditCounterReadBuffer(A_UINT8 *pBuffer, int Length)
+static int ProcessCreditCounterReadBuffer(u8 *pBuffer, int Length)
 {
     int     credits = 0;
     
@@ -516,13 +516,13 @@ static int ProcessCreditCounterReadBuffer(A_UINT8 *pBuffer, int Length)
    
 
 /* callback when our fetch to enable/disable completes */
-static void DevGMboxReadCreditsAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevGMboxReadCreditsAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("Read Credit Operation failed! status:%d \n", pPacket->Status));
     } else {
@@ -539,10 +539,10 @@ static void DevGMboxReadCreditsAsyncHandler(void *Context, HTC_PACKET *pPacket)
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n"));
 }
 
-A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits)
+int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits)
 {
-    A_STATUS    status = A_OK;
-    HTC_PACKET  *pIOPacket = NULL;  
+    int    status = 0;
+    struct htc_packet  *pIOPacket = NULL;  
     
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC"));
                                             
@@ -552,7 +552,7 @@ A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCr
 
         if (NULL == pIOPacket) {
             status = A_NO_MEMORY;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
         
@@ -581,15 +581,15 @@ A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCr
                               AR6K_REG_IO_BUFFER_SIZE,
                               HIF_RD_SYNC_BYTE_FIX,
                               NULL);    
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" DevGMboxReadCreditCounter failed! status:%d \n", status));          
     }
     
     if (pIOPacket != NULL) {
-        if (A_SUCCESS(status)) {
+        if (!status) {
                 /* sync mode processing */
             *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);     
         }
@@ -602,10 +602,10 @@ A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCr
     return status;
 }
 
-A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize)
+int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize)
 {
-    A_STATUS    status;
-    A_UINT8     buffer[4];
+    int    status;
+    u8 buffer[4];
        
     status = HIFReadWrite(pDev->HIFDevice,
                           AR6K_GMBOX_CREDIT_SIZE_ADDRESS,
@@ -614,7 +614,7 @@ A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize)
                           HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
                           NULL);    
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         if (buffer[0] == 0) {
             *pCreditSize = 256;    
         } else {   
@@ -626,7 +626,7 @@ A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize)
     return status;
 }
 
-void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev)
+void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev)
 {
         /* Target ASSERTED!!! */
     if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
@@ -634,17 +634,17 @@ void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev)
     }
 }
 
-A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes)
+int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes)
 {
 
-    A_STATUS                    status = A_OK;
-    AR6K_IRQ_PROC_REGISTERS     procRegs;
+    int                    status = 0;
+    struct ar6k_irq_proc_registers     procRegs;
     int                         maxCopy;
   
     do {
             /* on entry the caller provides the length of the lookahead buffer */
         if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             status = A_EINVAL;
             break;    
         }
@@ -654,12 +654,12 @@ A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer,
             /* load the register table from the device */
         status = HIFReadWrite(pDev->HIFDevice,
                               HOST_INT_STATUS_ADDRESS,
-                              (A_UINT8 *)&procRegs,
+                              (u8 *)&procRegs,
                               AR6K_IRQ_PROC_REGS_SIZE,
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status));
             break;
@@ -667,20 +667,20 @@ A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer,
         
         if (procRegs.gmbox_rx_avail > 0) {
             int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail;
-            A_MEMCPY(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
+            memcpy(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
             *pLookAheadBytes = bytes;
         }
         
-    } while (FALSE);
+    } while (false);
        
     return status; 
 }
 
-A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeoutMS)
+int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int Signal, int AckTimeoutMS)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      i;
-    A_UINT8  buffer[4];
+    u8 buffer[4];
     
     A_MEMZERO(buffer, sizeof(buffer));
     
@@ -701,14 +701,14 @@ A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeou
                               HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
                               NULL);    
                           
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
-    } while (FALSE);
+    } while (false);
     
     
-    if (A_SUCCESS(status)) {        
+    if (!status) {
             /* now read back the register to see if the bit cleared */
         while (AckTimeoutMS) {        
             status = HIFReadWrite(pDev->HIFDevice,
@@ -718,7 +718,7 @@ A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeou
                                   HIF_RD_SYNC_BYTE_FIX,
                                   NULL);    
                           
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
                             
diff --git a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
index db6d30c..c6488e0 100644
--- a/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
+++ b/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
@@ -56,17 +56,17 @@
 #define BAUD_TIMEOUT_MS           1
 #define BTPWRSAV_TIMEOUT_MS       1  
 
-typedef struct {
-    HCI_TRANSPORT_CONFIG_INFO   HCIConfig;
-    A_BOOL                      HCIAttached;
-    A_BOOL                      HCIStopped;
-    A_UINT32                    RecvStateFlags;
-    A_UINT32                    SendStateFlags;
+struct gmbox_proto_hci_uart {
+    struct hci_transport_config_info   HCIConfig;
+    bool                      HCIAttached;
+    bool                      HCIStopped;
+    u32 RecvStateFlags;
+    u32 SendStateFlags;
     HCI_TRANSPORT_PACKET_TYPE   WaitBufferType;
-    HTC_PACKET_QUEUE            SendQueue;         /* write queue holding HCI Command and ACL packets */
-    HTC_PACKET_QUEUE            HCIACLRecvBuffers;  /* recv queue holding buffers for incomming ACL packets */
-    HTC_PACKET_QUEUE            HCIEventBuffers;    /* recv queue holding buffers for incomming event packets */
-    AR6K_DEVICE                 *pDev;
+    struct htc_packet_queue            SendQueue;         /* write queue holding HCI Command and ACL packets */
+    struct htc_packet_queue            HCIACLRecvBuffers;  /* recv queue holding buffers for incomming ACL packets */
+    struct htc_packet_queue            HCIEventBuffers;    /* recv queue holding buffers for incomming event packets */
+    struct ar6k_device                 *pDev;
     A_MUTEX_T                   HCIRxLock;
     A_MUTEX_T                   HCITxLock;
     int                         CreditsMax;
@@ -75,18 +75,23 @@ typedef struct {
     int                         CreditSize;
     int                         CreditsCurrentSeek;
     int                         SendProcessCount;
-} GMBOX_PROTO_HCI_UART;
+};
 
 #define LOCK_HCI_RX(t)   A_MUTEX_LOCK(&(t)->HCIRxLock);
 #define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock);
 #define LOCK_HCI_TX(t)   A_MUTEX_LOCK(&(t)->HCITxLock);
 #define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock);
 
-#define DO_HCI_RECV_INDICATION(p,pt) \
-{   AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n",  \
-      (unsigned long)(pt),(pt)->Status, A_SUCCESS((pt)->Status) ? (pt)->ActualLength : 0, HCI_GET_PACKET_TYPE(pt))); \
-    (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt));                                 \
-}
+#define DO_HCI_RECV_INDICATION(p, pt)				\
+do {								\
+	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,					\
+			("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \
+			 (unsigned long)(pt),				\
+			 (pt)->Status,					\
+			 !(pt)->Status ? (pt)->ActualLength : 0,	\
+			 HCI_GET_PACKET_TYPE(pt)));			\
+	(p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt));	\
+} while (0)
 
 #define DO_HCI_SEND_INDICATION(p,pt) \
 {   AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n",  \
@@ -94,9 +99,9 @@ typedef struct {
     (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt));                            \
 }
     
-static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous);
+static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous);
 
-static void HCIUartCleanup(GMBOX_PROTO_HCI_UART *pProtocol)
+static void HCIUartCleanup(struct gmbox_proto_hci_uart *pProtocol)
 {
     A_ASSERT(pProtocol != NULL);
     
@@ -106,12 +111,12 @@ static void HCIUartCleanup(GMBOX_PROTO_HCI_UART *pProtocol)
     A_FREE(pProtocol);    
 }
 
-static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
+static int InitTxCreditState(struct gmbox_proto_hci_uart *pProt)
 {
-    A_STATUS    status;
+    int    status;
     int         credits;
     int         creditPollCount = CREDIT_POLL_COUNT;
-    A_BOOL      gotCredits = FALSE;
+    bool      gotCredits = false;
 
     pProt->CreditsConsumed = 0;
     
@@ -120,7 +125,7 @@ static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
         if (pProt->CreditsMax != 0) {
             /* we can only call this only once per target reset */
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called!  \n"));
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             status = A_EINVAL;
             break; 
         }
@@ -135,7 +140,7 @@ static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
 
             status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
     
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
             
@@ -145,7 +150,7 @@ static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
                 A_MDELAY(HCI_DELAY_PER_INTERVAL_MS);
                 continue;  
             } else {
-                gotCredits = TRUE;    
+                gotCredits = true;
             }
             
             if (0 == credits) {
@@ -155,7 +160,7 @@ static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
             pProt->CreditsMax += credits;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -169,13 +174,13 @@ static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
             /* now get the size */
         status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
                
-    } while (FALSE);
+    } while (false);
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         pProt->CreditsAvailable = pProt->CreditsMax;
         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n",
             pProt->CreditsAvailable, pProt->CreditSize));    
@@ -184,13 +189,13 @@ static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
     return status;
 }
 
-static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL CreditIRQEnabled)
+static int CreditsAvailableCallback(void *pContext, int Credits, bool CreditIRQEnabled)
 {
-    GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;    
-    A_BOOL               enableCreditIrq = FALSE;   
-    A_BOOL               disableCreditIrq = FALSE;
-    A_BOOL               doPendingSends = FALSE;
-    A_STATUS             status = A_OK;
+    struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext;    
+    bool               enableCreditIrq = false;
+    bool               disableCreditIrq = false;
+    bool               doPendingSends = false;
+    int             status = 0;
     
     /** this callback is called under 2 conditions:
      *   1. The credit IRQ interrupt was enabled and signaled.
@@ -209,7 +214,7 @@ static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL Cre
         if (0 == Credits) {
             if (!CreditIRQEnabled) {
                     /* enable credit IRQ */
-                enableCreditIrq = TRUE;    
+                enableCreditIrq = true;
             }
             break;
         }
@@ -235,19 +240,19 @@ static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL Cre
                 /* we have enough credits to fullfill at least 1 packet waiting in the queue */
             pProt->CreditsCurrentSeek = 0;
             pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS;  
-            doPendingSends = TRUE;  
+            doPendingSends = true;
             if (CreditIRQEnabled) {
                     /* credit IRQ was enabled, we shouldn't need it anymore */
-                disableCreditIrq = TRUE;    
+                disableCreditIrq = true;
             }      
         } else {
                 /* not enough credits yet, enable credit IRQ if we haven't already */
             if (!CreditIRQEnabled) {               
-                enableCreditIrq = TRUE;    
+                enableCreditIrq = true;
             }    
         }
                       
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_HCI_TX(pProt);
 
@@ -262,23 +267,23 @@ static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL Cre
     }
        
     if (doPendingSends) {
-        HCITrySend(pProt, NULL, FALSE);
+        HCITrySend(pProt, NULL, false);
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n"));
     return status;
 }
 
-static INLINE void NotifyTransportFailure(GMBOX_PROTO_HCI_UART  *pProt, A_STATUS status)
+static INLINE void NotifyTransportFailure(struct gmbox_proto_hci_uart  *pProt, int status)
 {
     if (pProt->HCIConfig.TransportFailure != NULL) {
         pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status);
     }
 }
 
-static void FailureCallback(void *pContext, A_STATUS Status)
+static void FailureCallback(void *pContext, int Status)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)pContext; 
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)pContext; 
     
         /* target assertion occured */           
     NotifyTransportFailure(pProt, Status);  
@@ -286,7 +291,7 @@ static void FailureCallback(void *pContext, A_STATUS Status)
 
 static void StateDumpCallback(void *pContext)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)pContext;
    
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n"));    
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags   :  0x%X \n",pProt->RecvStateFlags));
@@ -299,15 +304,15 @@ static void StateDumpCallback(void *pContext)
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n"));
 }
 
-static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes)
+static int HCIUartMessagePending(void *pContext, u8 LookAheadBytes[], int ValidBytes)
 {
-    GMBOX_PROTO_HCI_UART        *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
-    A_STATUS                    status = A_OK;
+    struct gmbox_proto_hci_uart        *pProt = (struct gmbox_proto_hci_uart *)pContext;
+    int                    status = 0;
     int                         totalRecvLength = 0;
     HCI_TRANSPORT_PACKET_TYPE   pktType = HCI_PACKET_INVALID;
-    A_BOOL                      recvRefillCalled = FALSE;
-    A_BOOL                      blockRecv = FALSE;
-    HTC_PACKET                  *pPacket = NULL;
+    bool                      recvRefillCalled = false;
+    bool                      blockRecv = false;
+    struct htc_packet                  *pPacket = NULL;
     
     /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */
     
@@ -348,7 +353,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
                 break;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
                 
@@ -361,7 +366,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
             LOCK_HCI_RX(pProt);
     
         } else {
-            HTC_PACKET_QUEUE *pQueue;
+            struct htc_packet_queue *pQueue;
                 /* user is using a refill handler that can refill multiple HTC buffers */
             
                 /* select buffer queue */
@@ -377,7 +382,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
                     pktType));
                     /* check for refill handler */
                 if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) {
-                    recvRefillCalled = TRUE;
+                    recvRefillCalled = true;
                     UNLOCK_HCI_RX(pProt);
                         /* call the re-fill handler */
                     pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
@@ -402,7 +407,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
                 /* this is not an error, we simply need to mark that we are waiting for buffers.*/
             pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS;
             pProt->WaitBufferType = pktType;
-            blockRecv = TRUE;
+            blockRecv = true;
             break;
         }
         
@@ -413,7 +418,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
             break;
         }
         
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_HCI_RX(pProt);
     
@@ -421,7 +426,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
         
     do {
         
-        if (A_FAILED(status) || (NULL == pPacket)) {
+        if (status || (NULL == pPacket)) {
             break;    
         } 
         
@@ -433,7 +438,7 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
                 
         status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength);     
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -471,14 +476,14 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
             /* adjust buffer to move past packet ID */
         pPacket->pBuffer++;
         pPacket->ActualLength = totalRecvLength - 1;
-        pPacket->Status = A_OK;
+        pPacket->Status = 0;
             /* indicate packet */
         DO_HCI_RECV_INDICATION(pProt,pPacket);
         pPacket = NULL;
         
             /* check if we need to refill recv buffers */        
         if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) {           
-            HTC_PACKET_QUEUE *pQueue;
+            struct htc_packet_queue *pQueue;
             int              watermark;
 
             if (pktType == HCI_ACL_TYPE) {
@@ -500,16 +505,16 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
             }
         }   
         
-    } while (FALSE);
+    } while (false);
         
         /* check if we need to disable the reciever */
-    if (A_FAILED(status) || blockRecv) {
+    if (status || blockRecv) {
         DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC); 
     }
     
         /* see if we need to recycle the recv buffer */    
-    if (A_FAILED(status) && (pPacket != NULL)) {
-        HTC_PACKET_QUEUE queue;
+    if (status && (pPacket != NULL)) {
+        struct htc_packet_queue queue;
         
         if (A_EPROTO == status) {
             DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet");    
@@ -527,12 +532,12 @@ static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[],
     return status;
 }
 
-static void HCISendPacketCompletion(void *Context, HTC_PACKET *pPacket)
+static void HCISendPacketCompletion(void *Context, struct htc_packet *pPacket)
 {
-    GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)Context;
+    struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)Context;
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket));
     
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n",
             (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength));        
     }
@@ -542,16 +547,16 @@ static void HCISendPacketCompletion(void *Context, HTC_PACKET *pPacket)
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n"));
 }
 
-static A_STATUS SeekCreditsSynch(GMBOX_PROTO_HCI_UART *pProt)
+static int SeekCreditsSynch(struct gmbox_proto_hci_uart *pProt)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      credits;
     int      retry = 100;
     
-    while (TRUE) {                
+    while (true) {
         credits = 0;
         status =  DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);   
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         LOCK_HCI_TX(pProt);
@@ -574,13 +579,13 @@ static A_STATUS SeekCreditsSynch(GMBOX_PROTO_HCI_UART *pProt)
     return status;
 }
 
-static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous)
+static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous)
 {   
-    A_STATUS    status = A_OK;
+    int    status = 0;
     int         transferLength;
     int         creditsRequired, remainder;
-    A_UINT8     hciUartType;
-    A_BOOL      synchSendComplete = FALSE;
+    u8 hciUartType;
+    bool      synchSendComplete = false;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket,
             Synchronous ? "SYNC" :"ASYNC"));
@@ -603,14 +608,14 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
                     /* in synchronous mode, the send queue can only hold 1 packet */
                 if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
                     status = A_EBUSY;
-                    A_ASSERT(FALSE);
+                    A_ASSERT(false);
                     break;    
                 }             
                 
                 if (pProt->SendProcessCount > 1) {
                         /* another thread or task is draining the TX queues  */
                     status = A_EBUSY;
-                    A_ASSERT(FALSE);
+                    A_ASSERT(false);
                     break;
                 } 
                   
@@ -667,11 +672,11 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
                     break;
                 default:
                     status = A_EINVAL;
-                    A_ASSERT(FALSE);
+                    A_ASSERT(false);
                     break;
             }
                        
-            if (A_FAILED(status)) {
+            if (status) {
                 break;   
             }
             
@@ -701,7 +706,7 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
                     UNLOCK_HCI_TX(pProt);
                     status = SeekCreditsSynch(pProt);
                     LOCK_HCI_TX(pProt);
-                    if (A_FAILED(status)) {
+                    if (status) {
                         break;    
                     }                    
                     /* fall through and continue processing this send op */                    
@@ -751,7 +756,7 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
             
             status = DevGMboxWrite(pProt->pDev,pPacket,transferLength);            
             if (Synchronous) {            
-                synchSendComplete = TRUE;
+                synchSendComplete = true;
             } else {
                 pPacket = NULL;    
             }
@@ -760,7 +765,7 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
               
         }
         
-    } while (FALSE);
+    } while (false);
         
     pProt->SendProcessCount--;
     A_ASSERT(pProt->SendProcessCount >= 0);
@@ -768,9 +773,9 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
     
     if (Synchronous) {
         A_ASSERT(pPacket != NULL);
-        if (A_SUCCESS(status) && (!synchSendComplete)) {
+        if (!status && (!synchSendComplete)) {
             status = A_EBUSY;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             LOCK_HCI_TX(pProt);
             if (pPacket->ListLink.pNext != NULL) {
                     /* remove from the queue */
@@ -779,7 +784,7 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
             UNLOCK_HCI_TX(pProt);
         }
     } else {   
-        if (A_FAILED(status) && (pPacket != NULL)) {
+        if (status && (pPacket != NULL)) {
             pPacket->Status = status;
             DO_HCI_SEND_INDICATION(pProt,pPacket); 
         }
@@ -789,10 +794,10 @@ static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_B
     return status;    
 }
 
-static void FlushSendQueue(GMBOX_PROTO_HCI_UART *pProt)
+static void FlushSendQueue(struct gmbox_proto_hci_uart *pProt)
 {
-    HTC_PACKET          *pPacket;
-    HTC_PACKET_QUEUE    discardQueue;
+    struct htc_packet          *pPacket;
+    struct htc_packet_queue    discardQueue;
     
     INIT_HTC_PACKET_QUEUE(&discardQueue);
     
@@ -813,10 +818,10 @@ static void FlushSendQueue(GMBOX_PROTO_HCI_UART *pProt)
     
 }
 
-static void FlushRecvBuffers(GMBOX_PROTO_HCI_UART *pProt)
+static void FlushRecvBuffers(struct gmbox_proto_hci_uart *pProt)
 {
-    HTC_PACKET_QUEUE discardQueue;
-    HTC_PACKET *pPacket;
+    struct htc_packet_queue discardQueue;
+    struct htc_packet *pPacket;
     
     INIT_HTC_PACKET_QUEUE(&discardQueue);
     
@@ -841,14 +846,14 @@ static void FlushRecvBuffers(GMBOX_PROTO_HCI_UART *pProt)
 
 /*** protocol module install entry point ***/
 
-A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
+int GMboxProtocolInstall(struct ar6k_device *pDev)
 {
-    A_STATUS                status = A_OK;
-    GMBOX_PROTO_HCI_UART    *pProtocol = NULL;
+    int                status = 0;
+    struct gmbox_proto_hci_uart    *pProtocol = NULL;
         
     do {
         
-        pProtocol = A_MALLOC(sizeof(GMBOX_PROTO_HCI_UART));
+        pProtocol = A_MALLOC(sizeof(struct gmbox_proto_hci_uart));
         
         if (NULL == pProtocol) {
             status = A_NO_MEMORY;
@@ -863,9 +868,9 @@ A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
         A_MUTEX_INIT(&pProtocol->HCIRxLock);
         A_MUTEX_INIT(&pProtocol->HCITxLock);
      
-    } while (FALSE);
+    } while (false);
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         LOCK_AR6K(pDev);
         DEV_GMBOX_SET_PROTOCOL(pDev,
                                HCIUartMessagePending,
@@ -884,9 +889,9 @@ A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
 }
 
 /*** protocol module uninstall entry point ***/
-void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
+void GMboxProtocolUninstall(struct ar6k_device *pDev)
 {
-    GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
+    struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev);
     
     if (pProtocol != NULL) {
         
@@ -894,7 +899,7 @@ void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
         if (pProtocol->HCIAttached) {
             A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL);
             pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext);
-            pProtocol->HCIAttached = FALSE;    
+            pProtocol->HCIAttached = false;
         }
         
         HCIUartCleanup(pProtocol);
@@ -903,10 +908,10 @@ void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
     
 }
 
-static A_STATUS NotifyTransportReady(GMBOX_PROTO_HCI_UART  *pProt)
+static int NotifyTransportReady(struct gmbox_proto_hci_uart  *pProt)
 {
-    HCI_TRANSPORT_PROPERTIES props;
-    A_STATUS                 status = A_OK;
+    struct hci_transport_properties props;
+    int                 status = 0;
     
     do {
         
@@ -924,17 +929,17 @@ static A_STATUS NotifyTransportReady(GMBOX_PROTO_HCI_UART  *pProt)
                                                     pProt->HCIConfig.pContext);
         }
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
 /***********  HCI UART protocol implementation ************************************************/
 
-HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo)
+HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo)
 {
-    GMBOX_PROTO_HCI_UART  *pProtocol = NULL; 
-    AR6K_DEVICE           *pDev;
+    struct gmbox_proto_hci_uart  *pProtocol = NULL; 
+    struct ar6k_device           *pDev;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n"));
     
@@ -944,7 +949,7 @@ HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_I
     
     do {
         
-        pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
+        pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev);
         
         if (NULL == pProtocol) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n"));
@@ -956,14 +961,14 @@ HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_I
             break;    
         }
         
-        A_MEMCPY(&pProtocol->HCIConfig, pInfo, sizeof(HCI_TRANSPORT_CONFIG_INFO));
+        memcpy(&pProtocol->HCIConfig, pInfo, sizeof(struct hci_transport_config_info));
         
         A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL);
         A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL);
         
-        pProtocol->HCIAttached = TRUE;
+        pProtocol->HCIAttached = true;
         
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_AR6K(pDev);
     
@@ -978,8 +983,8 @@ HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_I
 
 void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
 {
-    GMBOX_PROTO_HCI_UART  *pProtocol = (GMBOX_PROTO_HCI_UART *)HciTrans; 
-    AR6K_DEVICE           *pDev = pProtocol->pDev;
+    struct gmbox_proto_hci_uart  *pProtocol = (struct gmbox_proto_hci_uart *)HciTrans; 
+    struct ar6k_device           *pDev = pProtocol->pDev;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n"));
     
@@ -989,19 +994,19 @@ void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
         UNLOCK_AR6K(pDev);
         return;
     }
-    pProtocol->HCIAttached = FALSE;
+    pProtocol->HCIAttached = false;
     UNLOCK_AR6K(pDev);
     
     HCI_TransportStop(HciTrans);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n"));
 }
 
-A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue)
+int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans; 
-    A_STATUS              status = A_OK;
-    A_BOOL                unblockRecv = FALSE;
-    HTC_PACKET            *pPacket;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans; 
+    int              status = 0;
+    bool                unblockRecv = false;
+    struct htc_packet            *pPacket;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n"));
     
@@ -1039,15 +1044,15 @@ A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_Q
                         pProt->WaitBufferType));
                 pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS;
                 pProt->WaitBufferType = HCI_PACKET_INVALID;
-                unblockRecv = TRUE;
+                unblockRecv = true;
             }
         }
         
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_HCI_RX(pProt);
     
-    if (A_FAILED(status)) {
+    if (status) {
         while (!HTC_QUEUE_EMPTY(pQueue)) {
             pPacket = HTC_PACKET_DEQUEUE(pQueue);      
             pPacket->Status = A_ECANCELED;
@@ -1061,19 +1066,19 @@ A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_Q
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n"));
     
-    return A_OK;    
+    return 0;
 }
 
-A_STATUS HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous)
+int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;  
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;  
     
     return HCITrySend(pProt,pPacket,Synchronous);
 }
 
 void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans; 
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans; 
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n"));
      
@@ -1083,7 +1088,7 @@ void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
         AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
         return;    
     }
-    pProt->HCIStopped = TRUE;
+    pProt->HCIStopped = true;
     UNLOCK_AR6K(pProt->pDev);
      
         /* disable interrupts */
@@ -1097,69 +1102,69 @@ void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
 }
 
-A_STATUS HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
+int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
 {
-    A_STATUS              status;
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+    int              status;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n"));
     
         /* set stopped in case we have a problem in starting */
-    pProt->HCIStopped = TRUE;
+    pProt->HCIStopped = true;
     
     do {
         
         status = InitTxCreditState(pProt);   
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }     
         
         status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC);   
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;   
         } 
             /* enable recv */   
         status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;   
         } 
             /* signal bridge side to power up BT */
         status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS);
         
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n"));
             break;   
         } 
         
             /* we made it */
-        pProt->HCIStopped = FALSE;
+        pProt->HCIStopped = false;
         
-    } while (FALSE);
+    } while (false);
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n"));
     
     return status;
 }
 
-A_STATUS HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
+int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
     return DevGMboxIRQAction(pProt->pDev, 
                              Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE, 
                              PROC_IO_SYNC);
                              
 }
 
-A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
-                                       HTC_PACKET           *pPacket,
+int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
+                                       struct htc_packet           *pPacket,
                                        int                  MaxPollMS)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
-    A_STATUS              status = A_OK;
-    A_UINT8               lookAhead[8];
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
+    int              status = 0;
+    u8 lookAhead[8];
     int                   bytes;
     int                   totalRecvLength;
     
@@ -1173,7 +1178,7 @@ A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
         
         bytes = sizeof(lookAhead);
         status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes);
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }        
                 
@@ -1199,19 +1204,19 @@ A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
                 break;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
         pPacket->Completion = NULL;
         status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength); 
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
         pPacket->pBuffer++;
         pPacket->ActualLength = totalRecvLength - 1;
-        pPacket->Status = A_OK;        
+        pPacket->Status = 0;
         break; 
     }
     
@@ -1225,12 +1230,12 @@ A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
 
 #define LSB_SCRATCH_IDX     4
 #define MSB_SCRATCH_IDX     5
-A_STATUS HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud)
+int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
-    HIF_DEVICE *pHIFDevice = (HIF_DEVICE *)(pProt->pDev->HIFDevice);
-    A_UINT32 scaledBaud, scratchAddr;
-    A_STATUS status = A_OK;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
+    struct hif_device *pHIFDevice = (struct hif_device *)(pProt->pDev->HIFDevice);
+    u32 scaledBaud, scratchAddr;
+    int status = 0;
 
     /* Divide the desired baud rate by 100
      * Store the LSB in the local scratch register 4 and the MSB in the local
@@ -1242,24 +1247,24 @@ A_STATUS HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud)
     scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX);
     scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK;
     status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);                     
-    if (A_OK != status) {
+    if (0 != status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!"));            
         return status;
     }
 
     /* Now interrupt the target to tell it about the baud rate */
     status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS);
-    if (A_OK != status) {
+    if (0 != status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!"));            
     }
     
     return status;
 }
 
-A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
+int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable)
 {
-    A_STATUS status;
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+    int status;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
                              
     if (Enable) {
         status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS);
@@ -1267,7 +1272,7 @@ A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enab
         status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS);
     }
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n"));
     } else {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n"));
diff --git a/drivers/staging/ath6kl/htc2/htc.c b/drivers/staging/ath6kl/htc2/htc.c
index 7df62a2..d40bb14 100644
--- a/drivers/staging/ath6kl/htc2/htc.c
+++ b/drivers/staging/ath6kl/htc2/htc.c
@@ -23,7 +23,7 @@
 #include "htc_internal.h"
 
 #ifdef ATH_DEBUG_MODULE
-static ATH_DEBUG_MASK_DESCRIPTION g_HTCDebugDescription[] = {
+static struct ath_debug_mask_description g_HTCDebugDescription[] = {
     { ATH_DEBUG_SEND , "Send"},
     { ATH_DEBUG_RECV , "Recv"},
     { ATH_DEBUG_SYNC , "Sync"},
@@ -41,18 +41,18 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
 #endif
 
 static void HTCReportFailure(void *Context);
-static void ResetEndpointStates(HTC_TARGET *target);
+static void ResetEndpointStates(struct htc_target *target);
 
-void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList)
+void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList)
 {
     LOCK_HTC(target);
     HTC_PACKET_ENQUEUE(pList,pPacket);
     UNLOCK_HTC(target);
 }
 
-HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target,  HTC_PACKET_QUEUE *pList)
+struct htc_packet *HTCAllocControlBuffer(struct htc_target *target,  struct htc_packet_queue *pList)
 {
-    HTC_PACKET *pPacket;
+    struct htc_packet *pPacket;
 
     LOCK_HTC(target);
     pPacket = HTC_PACKET_DEQUEUE(pList);
@@ -62,9 +62,9 @@ HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target,  HTC_PACKET_QUEUE *pList)
 }
 
 /* cleanup the HTC instance */
-static void HTCCleanup(HTC_TARGET *target)
+static void HTCCleanup(struct htc_target *target)
 {
-    A_INT32 i;
+    s32 i;
 
     DevCleanup(&target->Device);
     
@@ -90,13 +90,13 @@ static void HTCCleanup(HTC_TARGET *target)
 }
 
 /* registered target arrival callback from the HIF layer */
-HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
+HTC_HANDLE HTCCreate(void *hif_handle, struct htc_init_info *pInfo)
 {
-    HTC_TARGET              *target = NULL;
-    A_STATUS                 status = A_OK;
+    struct htc_target              *target = NULL;
+    int                 status = 0;
     int                      i;
-    A_UINT32                 ctrl_bufsz;
-    A_UINT32                 blocksizes[HTC_MAILBOX_NUM_MAX];
+    u32 ctrl_bufsz;
+    u32 blocksizes[HTC_MAILBOX_NUM_MAX];
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n"));
 
@@ -105,13 +105,13 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
     do {
 
             /* allocate target memory */
-        if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) {
+        if ((target = (struct htc_target *)A_MALLOC(sizeof(struct htc_target))) == NULL) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
             status = A_ERROR;
             break;
         }
 
-        A_MEMZERO(target, sizeof(HTC_TARGET));
+        A_MEMZERO(target, sizeof(struct htc_target));
         A_MUTEX_INIT(&target->HTCLock);
         A_MUTEX_INIT(&target->HTCRxLock);
         A_MUTEX_INIT(&target->HTCTxLock);
@@ -130,14 +130,14 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
         target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;
         target->EpWaitingForBuffers = ENDPOINT_MAX;
 
-        A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO));
+        memcpy(&target->HTCInitInfo,pInfo,sizeof(struct htc_init_info));
         
         ResetEndpointStates(target);
           
             /* setup device layer */
         status = DevSetup(&target->Device);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -145,7 +145,7 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
         /* get the block sizes */
         status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     blocksizes, sizeof(blocksizes));
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n"));
             break;
         }
@@ -165,13 +165,13 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
             }
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
             /* carve up buffers/packets for control messages */
         for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) {
-            HTC_PACKET *pControlPacket;
+            struct htc_packet *pControlPacket;
             pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
             SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket,
                                           target,
@@ -182,7 +182,7 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
         }
 
         for (;i < NUM_CONTROL_BUFFERS;i++) {
-             HTC_PACKET *pControlPacket;
+             struct htc_packet *pControlPacket;
              pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
              INIT_HTC_PACKET_INFO(pControlPacket,
                                   target->HTCControlBuffers[i].Buffer,
@@ -190,9 +190,9 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
              HTC_FREE_CONTROL_TX(target,pControlPacket);
         }
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (target != NULL) {
             HTCCleanup(target);
             target = NULL;
@@ -206,7 +206,7 @@ HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
 
 void  HTCDestroy(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy ..  Destroying :0x%lX \n",(unsigned long)target));
     HTCCleanup(target);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n"));
@@ -216,21 +216,21 @@ void  HTCDestroy(HTC_HANDLE HTCHandle)
  * HIF requests */
 void *HTCGetHifDevice(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     return target->Device.HIFDevice;
 }
 
 /* wait for the target to arrive (sends HTC Ready message)
  * this operation is fully synchronous and the message is polled for */
-A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
+int HTCWaitTarget(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET              *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_STATUS                 status;
-    HTC_PACKET              *pPacket = NULL;
+    struct htc_target              *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    int                 status;
+    struct htc_packet              *pPacket = NULL;
     HTC_READY_EX_MSG        *pRdyMsg;
 
-    HTC_SERVICE_CONNECT_REQ  connect;
-    HTC_SERVICE_CONNECT_RESP resp;
+    struct htc_service_connect_req  connect;
+    struct htc_service_connect_resp resp;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target));
 
@@ -240,7 +240,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
 
         status = DoMboxHWTest(&target->Device);
 
-        if (status != A_OK) {
+        if (status) {
             break;
         }
 
@@ -249,7 +249,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
             /* we should be getting 1 control message that the target is ready */
         status = HTCWaitforControlMessage(target, &pPacket);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
             break;
         }
@@ -260,7 +260,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
         if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) ||
             (pPacket->ActualLength < sizeof(HTC_READY_MSG))) {
                 /* this message is not valid */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -268,7 +268,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
         
         if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) {
               /* this message is not valid */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -305,7 +305,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
                 /* limit what HTC can handle */
             target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle);          
                 /* target supports message bundling, setup device layer */
-            if (A_FAILED(DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle))) {
+            if (DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle)) {
                     /* device layer can't handle bundling */
                 target->MaxMsgPerBundle = 0;        
             } else {
@@ -320,10 +320,10 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
                     (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle));    
            
             if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) {           
-                target->SendBundlingEnabled = TRUE;
+                target->SendBundlingEnabled = true;
             }            
             if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) {    
-                target->RecvBundlingEnabled = TRUE;    
+                target->RecvBundlingEnabled = true;
             }
                             
             if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) {
@@ -331,7 +331,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
                         target->TargetCreditSize));    
                     /* disallow send bundling since the credit size is not aligned to a block size
                      * the I/O block padding will spill into the next credit buffer which is fatal */
-                target->SendBundlingEnabled = FALSE;
+                target->SendBundlingEnabled = false;
             }
         }
            
@@ -351,11 +351,11 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
                                    &connect,
                                    &resp);
 
-        if (!A_FAILED(status)) {
+        if (!status) {
             break;
         }
 
-    } while (FALSE);
+    } while (false);
 
     if (pPacket != NULL) {
         HTC_FREE_CONTROL_RX(target,pPacket);
@@ -369,11 +369,11 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
 
 
 /* Start HTC, enable interrupts and let the target know host has finished setup */
-A_STATUS HTCStart(HTC_HANDLE HTCHandle)
+int HTCStart(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_PACKET *pPacket;
-    A_STATUS   status;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_packet *pPacket;
+    int   status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
 
@@ -419,26 +419,26 @@ A_STATUS HTCStart(HTC_HANDLE HTCHandle)
             * target that the setup phase is complete */
         status = HTCSendSetupComplete(target);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
             /* unmask interrupts */
         status = DevUnmaskInterrupts(&target->Device);
 
-        if (A_FAILED(status)) {
+        if (status) {
             HTCStop(target);
         }
 
-    } while (FALSE);
+    } while (false);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
     return status;
 }
 
-static void ResetEndpointStates(HTC_TARGET *target)
+static void ResetEndpointStates(struct htc_target *target)
 {
-    HTC_ENDPOINT        *pEndpoint;
+    struct htc_endpoint        *pEndpoint;
     int                  i;
 
     for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
@@ -463,7 +463,7 @@ static void ResetEndpointStates(HTC_TARGET *target)
 /* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
 void HTCStop(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
 
     LOCK_HTC(target);
@@ -486,6 +486,8 @@ void HTCStop(HTC_HANDLE HTCHandle)
         /* flush all recv buffers */
     HTCFlushRecvBuffers(target);
 
+    DevCleanupMsgBundling(&target->Device);
+
     ResetEndpointStates(target);
    
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
@@ -494,7 +496,7 @@ void HTCStop(HTC_HANDLE HTCHandle)
 #ifdef ATH_DEBUG_MODULE
 void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     LOCK_HTC_TX(target);
 
@@ -509,9 +511,9 @@ void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
  * which uses a mechanism to report errors from the target (i.e. special interrupts) */
 static void HTCReportFailure(void *Context)
 {
-    HTC_TARGET *target = (HTC_TARGET *)Context;
+    struct htc_target *target = (struct htc_target *)Context;
 
-    target->TargetFailure = TRUE;
+    target->TargetFailure = true;
 
     if (target->HTCInitInfo.TargetFailure != NULL) {
             /* let upper layer know, it needs to call HTCStop() */
@@ -519,27 +521,27 @@ static void HTCReportFailure(void *Context)
     }
 }
 
-A_BOOL HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
+bool HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
                                 HTC_ENDPOINT_ID          Endpoint,
                                 HTC_ENDPOINT_STAT_ACTION Action,
-                                HTC_ENDPOINT_STATS       *pStats)
+                                struct htc_endpoint_stats       *pStats)
 {
 
 #ifdef HTC_EP_STAT_PROFILING
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_BOOL     clearStats = FALSE;
-    A_BOOL     sample = FALSE;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    bool     clearStats = false;
+    bool     sample = false;
 
     switch (Action) {
         case HTC_EP_STAT_SAMPLE :
-            sample = TRUE;
+            sample = true;
             break;
         case HTC_EP_STAT_SAMPLE_AND_CLEAR :
-            sample = TRUE;
-            clearStats = TRUE;
+            sample = true;
+            clearStats = true;
             break;
         case HTC_EP_STAT_CLEAR :
-            clearStats = TRUE;
+            clearStats = true;
             break;
         default:
             break;
@@ -554,26 +556,26 @@ A_BOOL HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
     if (sample) {
         A_ASSERT(pStats != NULL);
             /* return the stats to the caller */
-        A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
+        memcpy(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
     }
 
     if (clearStats) {
             /* reset stats */
-        A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
+        A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
     }
 
     UNLOCK_HTC_RX(target);
     UNLOCK_HTC_TX(target);
 
-    return TRUE;
+    return true;
 #else
-    return FALSE;
+    return false;
 #endif
 }
 
-AR6K_DEVICE  *HTCGetAR6KDevice(void *HTCHandle)
+struct ar6k_device  *HTCGetAR6KDevice(void *HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     return &target->Device;
 }
 
diff --git a/drivers/staging/ath6kl/htc2/htc_internal.h b/drivers/staging/ath6kl/htc2/htc_internal.h
index bd6754b..9425ed9 100644
--- a/drivers/staging/ath6kl/htc2/htc_internal.h
+++ b/drivers/staging/ath6kl/htc2/htc_internal.h
@@ -65,27 +65,27 @@ extern "C" {
 
 #define HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE  (1 << 0)
 
-typedef struct _HTC_ENDPOINT {
+struct htc_endpoint {
     HTC_ENDPOINT_ID             Id;
     HTC_SERVICE_ID              ServiceID;      /* service ID this endpoint is bound to
                                                    non-zero value means this endpoint is in use */
-    HTC_PACKET_QUEUE            TxQueue;        /* HTC frame buffer TX queue */
-    HTC_PACKET_QUEUE            RxBuffers;      /* HTC frame buffer RX list */
-    HTC_ENDPOINT_CREDIT_DIST    CreditDist;     /* credit distribution structure (exposed to driver layer) */
-    HTC_EP_CALLBACKS            EpCallBacks;    /* callbacks associated with this endpoint */
+    struct htc_packet_queue            TxQueue;        /* HTC frame buffer TX queue */
+    struct htc_packet_queue            RxBuffers;      /* HTC frame buffer RX list */
+    struct htc_endpoint_credit_dist    CreditDist;     /* credit distribution structure (exposed to driver layer) */
+    struct htc_ep_callbacks            EpCallBacks;    /* callbacks associated with this endpoint */
     int                         MaxTxQueueDepth;   /* max depth of the TX queue before we need to
                                                       call driver's full handler */
     int                         MaxMsgLength;        /* max length of endpoint message */
     int                         TxProcessCount;  /* reference count to continue tx processing */
-    HTC_PACKET_QUEUE            RecvIndicationQueue;    /* recv packets ready to be indicated */
+    struct htc_packet_queue            RecvIndicationQueue;    /* recv packets ready to be indicated */
     int                         RxProcessCount;         /* reference count to allow single processing context */
-    struct  _HTC_TARGET         *target;                /* back pointer to target */
-    A_UINT8                     SeqNo;                  /* TX seq no (helpful) for debugging */
-    A_UINT32                    LocalConnectionFlags;   /* local connection flags */
+    struct htc_target           *target;                /* back pointer to target */
+    u8 SeqNo;                  /* TX seq no (helpful) for debugging */
+    u32 LocalConnectionFlags;   /* local connection flags */
 #ifdef HTC_EP_STAT_PROFILING
-    HTC_ENDPOINT_STATS          EndPointStats;          /* endpoint statistics */
+    struct htc_endpoint_stats          EndPointStats;          /* endpoint statistics */
 #endif
-} HTC_ENDPOINT;
+};
 
 #ifdef HTC_EP_STAT_PROFILING
 #define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count);
@@ -99,21 +99,21 @@ typedef struct _HTC_ENDPOINT {
 #define NUM_CONTROL_TX_BUFFERS  2
 #define NUM_CONTROL_RX_BUFFERS  (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
 
-typedef struct HTC_CONTROL_BUFFER {
-    HTC_PACKET    HtcPacket;
-    A_UINT8       *Buffer;
-} HTC_CONTROL_BUFFER;
+struct htc_control_buffer {
+    struct htc_packet    HtcPacket;
+    u8 *Buffer;
+};
 
 #define HTC_RECV_WAIT_BUFFERS        (1 << 0)
 #define HTC_OP_STATE_STOPPING        (1 << 0)
 
 /* our HTC target state */
-typedef struct _HTC_TARGET {
-    HTC_ENDPOINT                EndPoint[ENDPOINT_MAX];
-    HTC_CONTROL_BUFFER          HTCControlBuffers[NUM_CONTROL_BUFFERS];
-    HTC_ENDPOINT_CREDIT_DIST   *EpCreditDistributionListHead;
-    HTC_PACKET_QUEUE            ControlBufferTXFreeList;
-    HTC_PACKET_QUEUE            ControlBufferRXFreeList;
+struct htc_target {
+    struct htc_endpoint                EndPoint[ENDPOINT_MAX];
+    struct htc_control_buffer          HTCControlBuffers[NUM_CONTROL_BUFFERS];
+    struct htc_endpoint_credit_dist   *EpCreditDistributionListHead;
+    struct htc_packet_queue            ControlBufferTXFreeList;
+    struct htc_packet_queue            ControlBufferRXFreeList;
     HTC_CREDIT_DIST_CALLBACK    DistributeCredits;
     HTC_CREDIT_INIT_CALLBACK    InitCredits;
     void                       *pCredDistContext;
@@ -122,22 +122,22 @@ typedef struct _HTC_TARGET {
     A_MUTEX_T                   HTCLock;
     A_MUTEX_T                   HTCRxLock;
     A_MUTEX_T                   HTCTxLock;
-    AR6K_DEVICE                 Device;         /* AR6K - specific state */
-    A_UINT32                    OpStateFlags;
-    A_UINT32                    RecvStateFlags;
+    struct ar6k_device                 Device;         /* AR6K - specific state */
+    u32 OpStateFlags;
+    u32 RecvStateFlags;
     HTC_ENDPOINT_ID             EpWaitingForBuffers;
-    A_BOOL                      TargetFailure;
+    bool                      TargetFailure;
 #ifdef HTC_CAPTURE_LAST_FRAME
-    HTC_FRAME_HDR               LastFrameHdr;  /* useful for debugging */
-    A_UINT8                     LastTrailer[256];
-    A_UINT8                     LastTrailerLength;
+    struct htc_frame_hdr               LastFrameHdr;  /* useful for debugging */
+    u8 LastTrailer[256];
+    u8 LastTrailerLength;
 #endif
-    HTC_INIT_INFO               HTCInitInfo;
-    A_UINT8                     HTCTargetVersion;
+    struct htc_init_info               HTCInitInfo;
+    u8 HTCTargetVersion;
     int                         MaxMsgPerBundle;       /* max messages per bundle for HTC */
-    A_BOOL                      SendBundlingEnabled;   /* run time enable for send bundling (dynamic) */
+    bool                      SendBundlingEnabled;   /* run time enable for send bundling (dynamic) */
     int                         RecvBundlingEnabled;   /* run time enable for recv bundling (dynamic) */
-} HTC_TARGET;
+};
 
 #define HTC_STOPPING(t) ((t)->OpStateFlags & HTC_OP_STATE_STOPPING)
 #define LOCK_HTC(t)      A_MUTEX_LOCK(&(t)->HTCLock);
@@ -147,7 +147,7 @@ typedef struct _HTC_TARGET {
 #define LOCK_HTC_TX(t)   A_MUTEX_LOCK(&(t)->HTCTxLock);
 #define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock);
 
-#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))
+#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((struct htc_target *)(hnd))
 #define HTC_RECYCLE_RX_PKT(target,p,e)                           \
 {                                                                \
     if ((p)->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_NO_RECYCLE) {  \
@@ -162,27 +162,27 @@ typedef struct _HTC_TARGET {
 }
 
 /* internal HTC functions */
-void        HTCControlTxComplete(void *Context, HTC_PACKET *pPacket);
-void        HTCControlRecv(void *Context, HTC_PACKET *pPacket);
-A_STATUS    HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket);
-HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList);
-void        HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList);
-A_STATUS    HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket);
-void        HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket);
-A_STATUS    HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], int NumLookAheads, A_BOOL *pAsyncProc, int *pNumPktsFetched);
-void        HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
-A_STATUS    HTCSendSetupComplete(HTC_TARGET *target);
-void        HTCFlushRecvBuffers(HTC_TARGET *target);
-void        HTCFlushSendPkts(HTC_TARGET *target);
+void        HTCControlTxComplete(void *Context, struct htc_packet *pPacket);
+void        HTCControlRecv(void *Context, struct htc_packet *pPacket);
+int    HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket);
+struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList);
+void        HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList);
+int    HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket);
+void        HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket);
+int    HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched);
+void        HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
+int    HTCSendSetupComplete(struct htc_target *target);
+void        HTCFlushRecvBuffers(struct htc_target *target);
+void        HTCFlushSendPkts(struct htc_target *target);
 
 #ifdef ATH_DEBUG_MODULE
-void        DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist);
-void        DumpCreditDistStates(HTC_TARGET *target);
-void 		DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
+void        DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist);
+void        DumpCreditDistStates(struct htc_target *target);
+void 		DebugDumpBytes(u8 *buffer, u16 length, char *pDescription);
 #endif
 
-static INLINE HTC_PACKET *HTC_ALLOC_CONTROL_TX(HTC_TARGET *target) {
-    HTC_PACKET *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
+static INLINE struct htc_packet *HTC_ALLOC_CONTROL_TX(struct htc_target *target) {
+    struct htc_packet *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
     if (pPacket != NULL) {
             /* set payload pointer area with some headroom */
         pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH;
@@ -200,14 +200,14 @@ static INLINE HTC_PACKET *HTC_ALLOC_CONTROL_TX(HTC_TARGET *target) {
 
 #define HTC_PREPARE_SEND_PKT(pP,sendflags,ctrl0,ctrl1)       \
 {                                                   \
-    A_UINT8 *pHdrBuf;                               \
+    u8 *pHdrBuf;                               \
     (pP)->pBuffer -= HTC_HDR_LENGTH;                \
     pHdrBuf = (pP)->pBuffer;                        \
-    A_SET_UINT16_FIELD(pHdrBuf,HTC_FRAME_HDR,PayloadLen,(A_UINT16)(pP)->ActualLength);  \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,Flags,(sendflags));                         \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,EndpointID, (A_UINT8)(pP)->Endpoint); \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,ControlBytes[0], (A_UINT8)(ctrl0));   \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,ControlBytes[1], (A_UINT8)(ctrl1));   \
+    A_SET_UINT16_FIELD(pHdrBuf,struct htc_frame_hdr,PayloadLen,(u16)(pP)->ActualLength);  \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,Flags,(sendflags));                         \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,EndpointID, (u8)(pP)->Endpoint); \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[0], (u8)(ctrl0));   \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[1], (u8)(ctrl1));   \
 }
 
 #define HTC_UNPREPARE_SEND_PKT(pP)     \
diff --git a/drivers/staging/ath6kl/htc2/htc_recv.c b/drivers/staging/ath6kl/htc2/htc_recv.c
index 3503657..c208801 100644
--- a/drivers/staging/ath6kl/htc2/htc_recv.c
+++ b/drivers/staging/ath6kl/htc2/htc_recv.c
@@ -50,8 +50,8 @@
 #define HTC_RX_STAT_PROFILE(t,ep,lookAhead)
 #endif
 
-static void DoRecvCompletion(HTC_ENDPOINT     *pEndpoint,
-                             HTC_PACKET_QUEUE *pQueueToIndicate)
+static void DoRecvCompletion(struct htc_endpoint     *pEndpoint,
+                             struct htc_packet_queue *pQueueToIndicate)
 {           
     
     do {
@@ -69,7 +69,7 @@ static void DoRecvCompletion(HTC_ENDPOINT     *pEndpoint,
                                                      pQueueToIndicate);
             INIT_HTC_PACKET_QUEUE(pQueueToIndicate);        
         } else {
-            HTC_PACKET *pPacket;  
+            struct htc_packet *pPacket;  
             /* using legacy EpRecv */         
             do {
                 pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
@@ -79,23 +79,23 @@ static void DoRecvCompletion(HTC_ENDPOINT     *pEndpoint,
             } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));                                              
         }
         
-    } while (FALSE);
+    } while (false);
 
 }
 
-static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
-                                         A_UINT8    *pBuffer,
+static INLINE int HTCProcessTrailer(struct htc_target *target,
+                                         u8 *pBuffer,
                                          int         Length,
-                                         A_UINT32   *pNextLookAheads,
+                                         u32 *pNextLookAheads,
                                          int        *pNumLookAheads,
                                          HTC_ENDPOINT_ID FromEndpoint)
 {
     HTC_RECORD_HDR          *pRecord;
-    A_UINT8                 *pRecordBuf;
+    u8 *pRecordBuf;
     HTC_LOOKAHEAD_REPORT    *pLookAhead;
-    A_UINT8                 *pOrigBuffer;
+    u8 *pOrigBuffer;
     int                     origLength;
-    A_STATUS                status;
+    int                status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
 
@@ -105,7 +105,7 @@ static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
 
     pOrigBuffer = pBuffer;
     origLength = Length;
-    status = A_OK;
+    status = 0;
     
     while (Length > 0) {
 
@@ -149,14 +149,14 @@ static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
                                 pLookAhead->PostValid));
 
                         /* look ahead bytes are valid, copy them over */
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
+                    ((u8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
+                    ((u8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
+                    ((u8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
+                    ((u8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
 
 #ifdef ATH_DEBUG_MODULE
                     if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
-                        DebugDumpBytes((A_UINT8 *)pNextLookAheads,4,"Next Look Ahead");
+                        DebugDumpBytes((u8 *)pNextLookAheads,4,"Next Look Ahead");
                     }
 #endif
                         /* just one normal lookahead */
@@ -182,16 +182,16 @@ static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
                             HTC_HOST_MAX_MSG_PER_BUNDLE) {
                             /* this should never happen, the target restricts the number
                              * of messages per bundle configured by the host */        
-                        A_ASSERT(FALSE);
+                        A_ASSERT(false);
                         status = A_EPROTO;
                         break;        
                     }
                                          
                     for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) {
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
+                        ((u8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
+                        ((u8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
+                        ((u8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
+                        ((u8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
                         pBundledLookAheadRpt++;
                     }
                     
@@ -204,7 +204,7 @@ static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
                 break;
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -214,7 +214,7 @@ static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
     }
 
 #ifdef ATH_DEBUG_MODULE
-    if (A_FAILED(status)) {
+    if (status) {
         DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
     }
 #endif
@@ -226,16 +226,16 @@ static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
 
 /* process a received message (i.e. strip off header, process any trailer data)
  * note : locks must be released when this function is called */
-static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target, 
-                                     HTC_PACKET *pPacket, 
-                                     A_UINT32   *pNextLookAheads, 
+static int HTCProcessRecvHeader(struct htc_target *target,
+                                     struct htc_packet *pPacket, 
+                                     u32 *pNextLookAheads,
                                      int        *pNumLookAheads)
 {
-    A_UINT8   temp;
-    A_UINT8   *pBuf;
-    A_STATUS  status = A_OK;
-    A_UINT16  payloadLen;
-    A_UINT32  lookAhead;
+    u8 temp;
+    u8 *pBuf;
+    int  status = 0;
+    u16 payloadLen;
+    u32 lookAhead;
 
     pBuf = pPacket->pBuffer;
     
@@ -252,12 +252,12 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
     do {
         /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to
          * retrieve 16 bit fields */
-        payloadLen = A_GET_UINT16_FIELD(pBuf, HTC_FRAME_HDR, PayloadLen);
+        payloadLen = A_GET_UINT16_FIELD(pBuf, struct htc_frame_hdr, PayloadLen);
         
-        ((A_UINT8 *)&lookAhead)[0] = pBuf[0];
-        ((A_UINT8 *)&lookAhead)[1] = pBuf[1];
-        ((A_UINT8 *)&lookAhead)[2] = pBuf[2];
-        ((A_UINT8 *)&lookAhead)[3] = pBuf[3];
+        ((u8 *)&lookAhead)[0] = pBuf[0];
+        ((u8 *)&lookAhead)[1] = pBuf[1];
+        ((u8 *)&lookAhead)[2] = pBuf[2];
+        ((u8 *)&lookAhead)[3] = pBuf[3];
 
         if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
                 /* refresh expected hdr, since this was unknown at the time we grabbed the packets
@@ -277,10 +277,10 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
                 break;    
             }
             
-            if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, EndpointID)) {
+            if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID)) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n", 
-                    A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, EndpointID), pPacket->Endpoint));
+                    A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID), pPacket->Endpoint));
                 status = A_EPROTO;
                 break;      
             }   
@@ -293,10 +293,10 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
                     ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n", 
                         (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags));
 #ifdef ATH_DEBUG_MODULE
-             DebugDumpBytes((A_UINT8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
-             DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header");
+             DebugDumpBytes((u8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
+             DebugDumpBytes(pBuf,sizeof(struct htc_frame_hdr),"Current Frame Header");
 #ifdef HTC_CAPTURE_LAST_FRAME
-            DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header");
+            DebugDumpBytes((u8 *)&target->LastFrameHdr,sizeof(struct htc_frame_hdr),"Last Frame Header");
             if (target->LastTrailerLength != 0) {
                 DebugDumpBytes(target->LastTrailer,
                                target->LastTrailerLength,
@@ -309,13 +309,13 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
         }
 
             /* get flags */
-        temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, Flags);
+        temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, Flags);
 
         if (temp & HTC_FLAGS_RECV_TRAILER) {
             /* this packet has a trailer */
 
                 /* extract the trailer length in control byte 0 */
-            temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, ControlBytes[0]);
+            temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, ControlBytes[0]);
 
             if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
@@ -341,12 +341,12 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
                                        pNumLookAheads,
                                        pPacket->Endpoint);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
 #ifdef HTC_CAPTURE_LAST_FRAME
-            A_MEMCPY(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
+            memcpy(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
             target->LastTrailerLength = temp;
 #endif
                 /* trim length by trailer bytes */
@@ -363,16 +363,16 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
         pPacket->pBuffer += HTC_HDR_LENGTH;
         pPacket->ActualLength -= HTC_HDR_LENGTH;
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
             /* dump the whole packet */
 #ifdef ATH_DEBUG_MODULE
         DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT");
 #endif
     } else {
 #ifdef HTC_CAPTURE_LAST_FRAME
-        A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(HTC_FRAME_HDR));
+        memcpy(&target->LastFrameHdr,pBuf,sizeof(struct htc_frame_hdr));
 #endif
         if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
             if (pPacket->ActualLength > 0) {
@@ -385,14 +385,14 @@ static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target,
     return status;
 }
 
-static INLINE void HTCAsyncRecvCheckMorePackets(HTC_TARGET  *target, 
-                                                A_UINT32    NextLookAheads[], 
+static INLINE void HTCAsyncRecvCheckMorePackets(struct htc_target  *target, 
+                                                u32 NextLookAheads[],
                                                 int         NumLookAheads,
-                                                A_BOOL      CheckMoreMsgs)
+                                                bool      CheckMoreMsgs)
 {
         /* was there a lookahead for the next packet? */
     if (NumLookAheads > 0) {
-        A_STATUS nextStatus;
+        int nextStatus;
         int      fetched = 0;
         AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                         ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n",
@@ -405,12 +405,12 @@ static INLINE void HTCAsyncRecvCheckMorePackets(HTC_TARGET  *target,
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Next look ahead from recv header was INVALID\n"));
 #ifdef ATH_DEBUG_MODULE
-            DebugDumpBytes((A_UINT8 *)NextLookAheads,
-                            NumLookAheads * (sizeof(A_UINT32)),
+            DebugDumpBytes((u8 *)NextLookAheads,
+                            NumLookAheads * (sizeof(u32)),
                             "BAD lookaheads from lookahead report");
 #endif
         }
-        if (A_SUCCESS(nextStatus) && !fetched) {
+        if (!nextStatus && !fetched) {
                 /* we could not fetch any more packets due to resources */
             DevAsyncIrqProcessComplete(&target->Device);        
         }
@@ -432,9 +432,9 @@ static INLINE void HTCAsyncRecvCheckMorePackets(HTC_TARGET  *target,
 }      
 
     /* unload the recv completion queue */
-static INLINE void DrainRecvIndicationQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
+static INLINE void DrainRecvIndicationQueue(struct htc_target *target, struct htc_endpoint *pEndpoint)
 {
-    HTC_PACKET_QUEUE     recvCompletions;
+    struct htc_packet_queue     recvCompletions;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n"));
                 
@@ -454,7 +454,7 @@ static INLINE void DrainRecvIndicationQueue(HTC_TARGET *target, HTC_ENDPOINT *pE
     
     /******* at this point only 1 thread may enter ******/
      
-    while (TRUE) { 
+    while (true) {
                 
             /* transfer items from main recv queue to the local one so we can release the lock */ 
         HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue);
@@ -496,11 +496,11 @@ static INLINE void DrainRecvIndicationQueue(HTC_TARGET *target, HTC_ENDPOINT *pE
     (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS; 
    
    /* note: this function can be called with the RX lock held */     
-static INLINE void SetRxPacketIndicationFlags(A_UINT32      LookAhead, 
-                                              HTC_ENDPOINT  *pEndpoint, 
-                                              HTC_PACKET    *pPacket)
+static INLINE void SetRxPacketIndicationFlags(u32 LookAhead,
+                                              struct htc_endpoint  *pEndpoint, 
+                                              struct htc_packet    *pPacket)
 {
-    HTC_FRAME_HDR *pHdr = (HTC_FRAME_HDR *)&LookAhead;
+    struct htc_frame_hdr *pHdr = (struct htc_frame_hdr *)&LookAhead;
         /* check to see if the "next" packet is from the same endpoint of the
            completing packet */
     if (pHdr->EndpointID == pPacket->Endpoint) {
@@ -515,14 +515,14 @@ static INLINE void SetRxPacketIndicationFlags(A_UINT32      LookAhead,
      
 /* asynchronous completion handler for recv packet fetching, when the device layer
  * completes a read request, it will call this completion handler */
-void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
+void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket)
 {
-    HTC_TARGET      *target = (HTC_TARGET *)Context;
-    HTC_ENDPOINT    *pEndpoint;
-    A_UINT32        nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+    struct htc_target      *target = (struct htc_target *)Context;
+    struct htc_endpoint    *pEndpoint;
+    u32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
     int             numLookAheads = 0;
-    A_STATUS        status;
-    A_BOOL          checkMorePkts = TRUE;
+    int        status;
+    bool          checkMorePkts = true;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n",
                 (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint));
@@ -537,7 +537,7 @@ void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
 
     do {
         
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n",
                 pPacket->Status, pPacket->Endpoint));
             break;
@@ -545,7 +545,7 @@ void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
             /* process the header for any trailer data */
         status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
         
@@ -554,7 +554,7 @@ void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
                  * It was fetched one message at a time.  There may be other asynchronous reads queued behind this one.
                  * Do no issue another check for more packets since the last one in the series of requests
                  * will handle it */
-            checkMorePkts = FALSE;    
+            checkMorePkts = false;
         }
           
         DUMP_RECV_PKT_INFO(pPacket);    
@@ -568,9 +568,9 @@ void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
             /* check for more recv packets before indicating */
         HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
          AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                          ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
                          status));
@@ -587,12 +587,12 @@ void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
 /* synchronously wait for a control message from the target,
  * This function is used at initialization time ONLY.  At init messages
  * on ENDPOINT 0 are expected. */
-A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket)
+int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket)
 {
-    A_STATUS        status;
-    A_UINT32        lookAhead;
-    HTC_PACKET      *pPacket = NULL;
-    HTC_FRAME_HDR   *pHdr;
+    int        status;
+    u32 lookAhead;
+    struct htc_packet      *pPacket = NULL;
+    struct htc_frame_hdr   *pHdr;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
 
@@ -605,7 +605,7 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
                                     &lookAhead,
                                     HTC_TARGET_RESPONSE_TIMEOUT);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -613,18 +613,18 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
                 ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
 
             /* check the lookahead */
-        pHdr = (HTC_FRAME_HDR *)&lookAhead;
+        pHdr = (struct htc_frame_hdr *)&lookAhead;
 
         if (pHdr->EndpointID != ENDPOINT_0) {
                 /* unexpected endpoint number, should be zero */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
                 /* bad message */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -632,7 +632,7 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
         pPacket = HTC_ALLOC_CONTROL_RX(target);
 
         if (pPacket == NULL) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_NO_MEMORY;
             break;
         }
@@ -642,7 +642,7 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
         pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
 
         if (pPacket->ActualLength > pPacket->BufferLength) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -653,7 +653,7 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
             /* get the message from the device, this will block */
         status = HTCIssueRecv(target, pPacket);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -662,7 +662,7 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
 
         pPacket->Status = status;
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
                      status));
@@ -672,9 +672,9 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
             /* give the caller this control message packet, they are responsible to free */
         *ppControlPacket = pPacket;
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (pPacket != NULL) {
                 /* cleanup buffer on error */
             HTC_FREE_CONTROL_RX(target,pPacket);
@@ -686,26 +686,26 @@ A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPack
     return status;
 }
 
-static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target, 
-                                         A_UINT32         LookAheads[], 
+static int AllocAndPrepareRxPackets(struct htc_target       *target,
+                                         u32 LookAheads[],
                                          int              Messages,                                        
-                                         HTC_ENDPOINT     *pEndpoint, 
-                                         HTC_PACKET_QUEUE *pQueue)
+                                         struct htc_endpoint     *pEndpoint, 
+                                         struct htc_packet_queue *pQueue)
 {
-    A_STATUS         status = A_OK;
-    HTC_PACKET      *pPacket;
-    HTC_FRAME_HDR   *pHdr;
+    int         status = 0;
+    struct htc_packet      *pPacket;
+    struct htc_frame_hdr   *pHdr;
     int              i,j;
     int              numMessages;
     int              fullLength;
-    A_BOOL           noRecycle;
+    bool           noRecycle;
             
         /* lock RX while we assemble the packet buffers */
     LOCK_HTC_RX(target);
                         
     for (i = 0; i < Messages; i++) {   
          
-        pHdr = (HTC_FRAME_HDR *)&LookAheads[i];
+        pHdr = (struct htc_frame_hdr *)&LookAheads[i];
 
         if (pHdr->EndpointID >= ENDPOINT_MAX) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID));
@@ -724,7 +724,7 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
        
         if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
-                    pHdr->PayloadLen, (A_UINT32)HTC_MAX_PAYLOAD_LENGTH));
+                    pHdr->PayloadLen, (u32)HTC_MAX_PAYLOAD_LENGTH));
             status = A_EPROTO;
             break;
         }
@@ -751,7 +751,7 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
                 ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages));           
         }
      
-        fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR));
+        fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(struct htc_frame_hdr));
             
             /* get packet buffers for each message, if there was a bundle detected in the header,
              * use pHdr as a template to fetch all packets in the bundle */        
@@ -759,11 +759,11 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
             
                 /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup,
                  * they must be explicitly returned */
-            noRecycle = FALSE;
+            noRecycle = false;
                                                                                    
             if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) {
                 UNLOCK_HTC_RX(target);
-                noRecycle = TRUE;
+                noRecycle = true;
                     /* user is using a per-packet allocation callback */
                 pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext,
                                                              pEndpoint->Id,
@@ -776,7 +776,7 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
                 INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen);                
                     /* threshold was hit, call the special recv allocation callback */        
                 UNLOCK_HTC_RX(target);
-                noRecycle = TRUE;
+                noRecycle = true;
                     /* user wants to allocate packets above a certain threshold */
                 pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext,
                                                                    pEndpoint->Id,
@@ -816,7 +816,7 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
                 /* clear flags */
             pPacket->PktInfo.AsRx.HTCRxFlags = 0;
             pPacket->PktInfo.AsRx.IndicationFlags = 0;
-            pPacket->Status = A_OK;
+            pPacket->Status = 0;
             
             if (noRecycle) {
                     /* flag that these packets cannot be recycled, they have to be returned to the 
@@ -832,7 +832,7 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
             }
     
                 /* make sure this message can fit in the endpoint buffer */
-            if ((A_UINT32)fullLength > pPacket->BufferLength) {
+            if ((u32)fullLength > pPacket->BufferLength) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n",
                         pHdr->PayloadLen, fullLength, pPacket->BufferLength));
@@ -856,10 +856,10 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
             pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             if (A_NO_RESOURCE == status) {
                     /* this is actually okay */
-                status = A_OK;    
+                status = 0;
             }
             break;    
         }
@@ -868,7 +868,7 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
     
     UNLOCK_HTC_RX(target);
     
-    if (A_FAILED(status)) {
+    if (status) {
         while (!HTC_QUEUE_EMPTY(pQueue)) {
             pPacket = HTC_PACKET_DEQUEUE(pQueue);
                 /* recycle all allocated packets */
@@ -879,37 +879,37 @@ static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target,
     return status; 
 }
 
-static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
+static void HTCAsyncRecvScatterCompletion(struct hif_scatter_req *pScatterReq)
 {
     int                 i;    
-    HTC_PACKET          *pPacket;
-    HTC_ENDPOINT        *pEndpoint;
-    A_UINT32            lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+    struct htc_packet          *pPacket;
+    struct htc_endpoint        *pEndpoint;
+    u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
     int                 numLookAheads = 0;
-    HTC_TARGET          *target = (HTC_TARGET *)pScatterReq->Context;
-    A_STATUS            status;
-    A_BOOL              partialBundle = FALSE;
-    HTC_PACKET_QUEUE    localRecvQueue;
-    A_BOOL              procError = FALSE;
+    struct htc_target          *target = (struct htc_target *)pScatterReq->Context;
+    int            status;
+    bool              partialBundle = false;
+    struct htc_packet_queue    localRecvQueue;
+    bool              procError = false;
            
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion  TotLen: %d  Entries: %d\n",
         pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
     
     A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
            
-    if (A_FAILED(pScatterReq->CompletionStatus)) {
+    if (pScatterReq->CompletionStatus) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));            
     }
     
     if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) {
-        partialBundle = TRUE;    
+        partialBundle = true;
     }
     
     DEV_FINISH_SCATTER_OPERATION(pScatterReq);
     
     INIT_HTC_PACKET_QUEUE(&localRecvQueue);
         
-    pPacket = (HTC_PACKET *)pScatterReq->ScatterList[0].pCallerContexts[0];
+    pPacket = (struct htc_packet *)pScatterReq->ScatterList[0].pCallerContexts[0];
         /* note: all packets in a scatter req are for the same endpoint ! */
     pEndpoint = &target->EndPoint[pPacket->Endpoint];
          
@@ -917,20 +917,20 @@ static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
         /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock
          * as it processes credit reports */
     for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
-        pPacket = (HTC_PACKET *)pScatterReq->ScatterList[i].pCallerContexts[0];
+        pPacket = (struct htc_packet *)pScatterReq->ScatterList[i].pCallerContexts[0];
         A_ASSERT(pPacket != NULL);       
             /* reset count, we are only interested in the look ahead in the last packet when we
              * break out of this loop */
         numLookAheads = 0;
         
-        if (A_SUCCESS(pScatterReq->CompletionStatus)) {      
+        if (!pScatterReq->CompletionStatus) {
                 /* process header for each of the recv packets */            
             status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads);
         } else {
             status = A_ERROR;    
         }
         
-        if (A_SUCCESS(status)) {    
+        if (!status) {
 #ifdef HTC_EP_STAT_PROFILING
             LOCK_HTC_RX(target);              
             HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
@@ -956,7 +956,7 @@ static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
                 /* recycle failed recv */
             HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
                 /* set flag and continue processing the remaining scatter entries */
-            procError = TRUE;
+            procError = true;
         }   
     
     }
@@ -975,7 +975,7 @@ static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
         HTCAsyncRecvCheckMorePackets(target,
                                      lookAheads,
                                      numLookAheads,
-                                     partialBundle ? FALSE : TRUE);
+                                     partialBundle ? false : true);
     }
     
         /* now drain the indication queue */
@@ -984,18 +984,18 @@ static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n"));
 }
 
-static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET        *target,
-                                         HTC_PACKET_QUEUE  *pRecvPktQueue, 
-                                         HTC_PACKET_QUEUE  *pSyncCompletionQueue,
+static int HTCIssueRecvPacketBundle(struct htc_target        *target,
+                                         struct htc_packet_queue  *pRecvPktQueue, 
+                                         struct htc_packet_queue  *pSyncCompletionQueue,
                                          int               *pNumPacketsFetched,
-                                         A_BOOL             PartialBundle)
+                                         bool             PartialBundle)
 {
-    A_STATUS        status = A_OK;
-    HIF_SCATTER_REQ *pScatterReq;
+    int        status = 0;
+    struct hif_scatter_req *pScatterReq;
     int             i, totalLength;
     int             pktsToScatter;
-    HTC_PACKET      *pPacket;
-    A_BOOL          asyncMode = (pSyncCompletionQueue == NULL) ? TRUE : FALSE;
+    struct htc_packet      *pPacket;
+    bool          asyncMode = (pSyncCompletionQueue == NULL) ? true : false;
     int             scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device);
         
     pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue);
@@ -1004,7 +1004,7 @@ static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET        *target,
     if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) {
             /* we were forced to split this bundle receive operation
              * all packets in this partial bundle must have their lookaheads ignored */
-        PartialBundle = TRUE;
+        PartialBundle = true;
             /* this would only happen if the target ignored our max bundle limit */
         AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
                          ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n",
@@ -1085,7 +1085,7 @@ static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET        *target,
         
         status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode);
         
-        if (A_SUCCESS(status)) {
+        if (!status) {
             *pNumPacketsFetched = i;    
         }
         
@@ -1094,7 +1094,7 @@ static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET        *target,
             DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq);   
         }
         
-    } while (FALSE);
+    } while (false);
    
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n",
             status,*pNumPacketsFetched));
@@ -1102,7 +1102,7 @@ static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET        *target,
     return status;
 }
 
-static INLINE void CheckRecvWaterMark(HTC_ENDPOINT    *pEndpoint)
+static INLINE void CheckRecvWaterMark(struct htc_endpoint    *pEndpoint)
 {  
         /* see if endpoint is using a refill watermark 
          * ** no need to use a lock here, since we are only inspecting...
@@ -1117,17 +1117,17 @@ static INLINE void CheckRecvWaterMark(HTC_ENDPOINT    *pEndpoint)
 }
 
 /* callback when device layer or lookahead report parsing detects a pending message */
-A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], int NumLookAheads, A_BOOL *pAsyncProc, int *pNumPktsFetched)
+int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched)
 {
-    HTC_TARGET      *target = (HTC_TARGET *)Context;
-    A_STATUS         status = A_OK;
-    HTC_PACKET      *pPacket;
-    HTC_ENDPOINT    *pEndpoint;
-    A_BOOL          asyncProc = FALSE;
-    A_UINT32        lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+    struct htc_target      *target = (struct htc_target *)Context;
+    int         status = 0;
+    struct htc_packet      *pPacket;
+    struct htc_endpoint    *pEndpoint;
+    bool          asyncProc = false;
+    u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
     int             pktsFetched;
-    HTC_PACKET_QUEUE recvPktQueue, syncCompletedPktsQueue;
-    A_BOOL          partialBundle;
+    struct htc_packet_queue recvPktQueue, syncCompletedPktsQueue;
+    bool          partialBundle;
     HTC_ENDPOINT_ID id;
     int             totalFetched = 0;
     
@@ -1141,7 +1141,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
             /* We use async mode to get the packets if the device layer supports it.
              * The device layer interfaces with HIF in which HIF may have restrictions on
              * how interrupts are processed */
-        asyncProc = TRUE;
+        asyncProc = true;
     }
 
     if (pAsyncProc != NULL) {
@@ -1150,14 +1150,14 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
     }
     
     if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return A_EPROTO; 
     }
         
         /* on first entry copy the lookaheads into our temp array for processing */
-    A_MEMCPY(lookAheads, MsgLookAheads, (sizeof(A_UINT32)) * NumLookAheads);  
+    memcpy(lookAheads, MsgLookAheads, (sizeof(u32)) * NumLookAheads);
             
-    while (TRUE) {
+    while (true) {
         
             /* reset packets queues */
         INIT_HTC_PACKET_QUEUE(&recvPktQueue);
@@ -1165,12 +1165,12 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
         
         if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
             status = A_EPROTO;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;    
         }
    
             /* first lookahead sets the expected endpoint IDs for all packets in a bundle */
-        id = ((HTC_FRAME_HDR *)&lookAheads[0])->EndpointID;
+        id = ((struct htc_frame_hdr *)&lookAheads[0])->EndpointID;
         pEndpoint = &target->EndPoint[id];
         
         if (id >= ENDPOINT_MAX) {
@@ -1186,7 +1186,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
                                           NumLookAheads,
                                           pEndpoint, 
                                           &recvPktQueue);        
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
  
@@ -1200,7 +1200,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
             /* we've got packet buffers for all we can currently fetch, 
              * this count is not valid anymore  */
         NumLookAheads = 0;
-        partialBundle = FALSE;
+        partialBundle = false;
        
             /* now go fetch the list of HTC packets */
         while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {   
@@ -1214,14 +1214,14 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
                                                   asyncProc ? NULL : &syncCompletedPktsQueue,
                                                   &pktsFetched,
                                                   partialBundle);                                                   
-                if (A_FAILED(status)) {
+                if (status) {
                     break;
                 }
                 
                 if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) {
                         /* we couldn't fetch all packets at one time, this creates a broken
                          * bundle  */
-                    partialBundle = TRUE;    
+                    partialBundle = true;
                 }                                                                     
             }
             
@@ -1248,7 +1248,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
                                     
                     /* go fetch the packet */
                 status = HTCIssueRecv(target, pPacket);              
-                if (A_FAILED(status)) {
+                if (status) {
                     break;
                 }  
                                
@@ -1261,7 +1261,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
             
         }
 
-        if (A_SUCCESS(status)) {  
+        if (!status) {
             CheckRecvWaterMark(pEndpoint);
         }
             
@@ -1283,7 +1283,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
              
              /* unload sync completion queue */      
         while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
-            HTC_PACKET_QUEUE    container;
+            struct htc_packet_queue    container;
            
             pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
             A_ASSERT(pPacket != NULL);
@@ -1295,7 +1295,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
                 /* process header for each of the recv packets
                  * note: the lookahead of the last packet is useful for us to continue in this loop */            
             status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads);
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
             
@@ -1317,7 +1317,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
             DO_RCV_COMPLETION(pEndpoint,&container);
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
             
@@ -1346,7 +1346,7 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
         REF_IRQ_STATUS_RECHECK(&target->Device);
     }
     
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Failed to get pending recv messages (%d) \n",status));
             /* cleanup any packets we allocated but didn't use to actually fetch any packets */                        
@@ -1385,18 +1385,18 @@ A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], i
     return status;
 }
 
-A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
+int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint;
-    A_BOOL          unblockRecv = FALSE;
-    A_STATUS        status = A_OK;
-    HTC_PACKET      *pFirstPacket;
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint;
+    bool          unblockRecv = false;
+    int        status = 0;
+    struct htc_packet      *pFirstPacket;
 
     pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
     
     if (NULL == pFirstPacket) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return A_EINVAL;    
     }
     
@@ -1415,7 +1415,7 @@ A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQu
         LOCK_HTC_RX(target);
 
         if (HTC_STOPPING(target)) {
-            HTC_PACKET *pPacket;
+            struct htc_packet *pPacket;
             
             UNLOCK_HTC_RX(target);
             
@@ -1438,7 +1438,7 @@ A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQu
                     target->EpWaitingForBuffers));
                 target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
                 target->EpWaitingForBuffers = ENDPOINT_MAX;
-                unblockRecv = TRUE;
+                unblockRecv = true;
             }
         }
 
@@ -1449,23 +1449,23 @@ A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQu
             DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
         }
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
 /* Makes a buffer available to the HTC module */
-A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
+int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
 {
-    HTC_PACKET_QUEUE queue;
+    struct htc_packet_queue queue;
     INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); 
     return HTCAddReceivePktMultiple(HTCHandle, &queue);       
 }
 
 void HTCUnblockRecv(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_BOOL      unblockRecv = FALSE;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    bool      unblockRecv = false;
 
     LOCK_HTC_RX(target);
 
@@ -1475,7 +1475,7 @@ void HTCUnblockRecv(HTC_HANDLE HTCHandle)
             target->EpWaitingForBuffers));
         target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
         target->EpWaitingForBuffers = ENDPOINT_MAX;
-        unblockRecv = TRUE;
+        unblockRecv = true;
     }
 
     UNLOCK_HTC_RX(target);
@@ -1486,10 +1486,10 @@ void HTCUnblockRecv(HTC_HANDLE HTCHandle)
     }
 }
 
-static void HTCFlushRxQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET_QUEUE *pQueue)
+static void HTCFlushRxQueue(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet_queue *pQueue)
 {
-    HTC_PACKET  *pPacket;
-    HTC_PACKET_QUEUE container;
+    struct htc_packet  *pPacket;
+    struct htc_packet_queue container;
     
     LOCK_HTC_RX(target);
 
@@ -1512,7 +1512,7 @@ static void HTCFlushRxQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PAC
     UNLOCK_HTC_RX(target);
 }
 
-static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
+static void HTCFlushEndpointRX(struct htc_target *target, struct htc_endpoint *pEndpoint)
 {
         /* flush any recv indications not already made */
     HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue);
@@ -1520,9 +1520,9 @@ static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
     HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers);
 }
 
-void HTCFlushRecvBuffers(HTC_TARGET *target)
+void HTCFlushRecvBuffers(struct htc_target *target)
 {
-    HTC_ENDPOINT    *pEndpoint;
+    struct htc_endpoint    *pEndpoint;
     int             i;
 
     for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
@@ -1538,7 +1538,7 @@ void HTCFlushRecvBuffers(HTC_TARGET *target)
 
 void HTCEnableRecv(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     if (!HTC_STOPPING(target)) {
             /* re-enable */
@@ -1548,7 +1548,7 @@ void HTCEnableRecv(HTC_HANDLE HTCHandle)
 
 void HTCDisableRecv(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     if (!HTC_STOPPING(target)) {
             /* disable */
@@ -1559,16 +1559,16 @@ void HTCDisableRecv(HTC_HANDLE HTCHandle)
 int HTCGetNumRecvBuffers(HTC_HANDLE      HTCHandle,
                          HTC_ENDPOINT_ID Endpoint)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);    
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);    
     return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers));
 }
 
-A_STATUS HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
-                               A_UINT32     TimeoutInMs,
-                               A_BOOL      *pbIsRecvPending)
+int HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
+                               u32 TimeoutInMs,
+                               bool      *pbIsRecvPending)
 {
-    A_STATUS    status  = A_OK;
-    HTC_TARGET *target  = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    int    status  = 0;
+    struct htc_target *target  = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     status = DevWaitForPendingRecv(&target->Device,
                                     TimeoutInMs,
diff --git a/drivers/staging/ath6kl/htc2/htc_send.c b/drivers/staging/ath6kl/htc2/htc_send.c
index bc7ee78..6f4050a 100644
--- a/drivers/staging/ath6kl/htc2/htc_send.c
+++ b/drivers/staging/ath6kl/htc2/htc_send.c
@@ -43,8 +43,8 @@ typedef enum _HTC_SEND_QUEUE_RESULT {
                            (reason));                                    \
 }
 
-static void DoSendCompletion(HTC_ENDPOINT       *pEndpoint,
-                             HTC_PACKET_QUEUE   *pQueueToIndicate)
+static void DoSendCompletion(struct htc_endpoint       *pEndpoint,
+                             struct htc_packet_queue   *pQueueToIndicate)
 {           
     do {
                 
@@ -62,7 +62,7 @@ static void DoSendCompletion(HTC_ENDPOINT       *pEndpoint,
                 /* all packets are now owned by the callback, reset queue to be safe */
             INIT_HTC_PACKET_QUEUE(pQueueToIndicate);                                                      
         } else {
-            HTC_PACKET *pPacket;  
+            struct htc_packet *pPacket;  
             /* using legacy EpTxComplete */         
             do {
                 pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
@@ -72,16 +72,16 @@ static void DoSendCompletion(HTC_ENDPOINT       *pEndpoint,
             } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));                                              
         }
         
-    } while (FALSE);
+    } while (false);
 
 }
 
 /* do final completion on sent packet */
-static INLINE void CompleteSentPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET *pPacket)
+static INLINE void CompleteSentPacket(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet *pPacket)
 {
     pPacket->Completion = NULL;  
     
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
             ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n",
                 pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed));                
@@ -101,11 +101,11 @@ static INLINE void CompleteSentPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoin
 
 /* our internal send packet completion handler when packets are submited to the AR6K device
  * layer */
-static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
+static void HTCSendPktCompletionHandler(void *Context, struct htc_packet *pPacket)
 {
-    HTC_TARGET      *target = (HTC_TARGET *)Context;
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[pPacket->Endpoint];
-    HTC_PACKET_QUEUE container;
+    struct htc_target      *target = (struct htc_target *)Context;
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[pPacket->Endpoint];
+    struct htc_packet_queue container;
     
     CompleteSentPacket(target,pEndpoint,pPacket);
     INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
@@ -113,19 +113,19 @@ static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
     DO_EP_TX_COMPLETION(pEndpoint,&container);
 }
 
-A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket)
+int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket)
 {
-    A_STATUS status;
-    A_BOOL   sync = FALSE;
+    int status;
+    bool   sync = false;
 
     if (pPacket->Completion == NULL) {
             /* mark that this request was synchronously issued */
-        sync = TRUE;
+        sync = true;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
                     ("+-HTCIssueSend: transmit length : %d (%s) \n",
-                    pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH,
+                    pPacket->ActualLength + (u32)HTC_HDR_LENGTH,
                     sync ? "SYNC" : "ASYNC" ));
 
         /* send message to device */
@@ -146,21 +146,21 @@ A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket)
 }
 
     /* get HTC send packets from the TX queue on an endpoint */
-static INLINE void GetHTCSendPackets(HTC_TARGET        *target, 
-                                     HTC_ENDPOINT      *pEndpoint, 
-                                     HTC_PACKET_QUEUE  *pQueue)
+static INLINE void GetHTCSendPackets(struct htc_target        *target, 
+                                     struct htc_endpoint      *pEndpoint, 
+                                     struct htc_packet_queue  *pQueue)
 {
     int          creditsRequired;
     int          remainder;
-    A_UINT8      sendFlags;
-    HTC_PACKET   *pPacket;
+    u8 sendFlags;
+    struct htc_packet   *pPacket;
     unsigned int transferLength;
 
     /****** NOTE : the TX lock is held when this function is called *****************/
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n"));
      
         /* loop until we can grab as many packets out of the queue as we can */       
-    while (TRUE) {    
+    while (true) {
         
         sendFlags = 0;   
             /* get packet at head, but don't remove it */
@@ -264,14 +264,14 @@ static INLINE void GetHTCSendPackets(HTC_TARGET        *target,
      
 }
 
-static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
+static void HTCAsyncSendScatterCompletion(struct hif_scatter_req *pScatterReq)
 {
     int                 i;    
-    HTC_PACKET          *pPacket;
-    HTC_ENDPOINT        *pEndpoint = (HTC_ENDPOINT *)pScatterReq->Context;
-    HTC_TARGET          *target = (HTC_TARGET *)pEndpoint->target;
-    A_STATUS            status = A_OK;
-    HTC_PACKET_QUEUE    sendCompletes;
+    struct htc_packet          *pPacket;
+    struct htc_endpoint        *pEndpoint = (struct htc_endpoint *)pScatterReq->Context;
+    struct htc_target          *target = (struct htc_target *)pEndpoint->target;
+    int            status = 0;
+    struct htc_packet_queue    sendCompletes;
     
     INIT_HTC_PACKET_QUEUE(&sendCompletes);
           
@@ -280,14 +280,14 @@ static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
     
     DEV_FINISH_SCATTER_OPERATION(pScatterReq);
            
-    if (A_FAILED(pScatterReq->CompletionStatus)) {
+    if (pScatterReq->CompletionStatus) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));            
         status = A_ERROR;
     }
     
         /* walk through the scatter list and process */
     for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
-        pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
+        pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
         A_ASSERT(pPacket != NULL);
         pPacket->Status = status;
         CompleteSentPacket(target,pEndpoint,pPacket);
@@ -309,21 +309,21 @@ static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
      *    - a message that will consume a partial credit will stop the bundling process early 
      *    - we drop below the minimum number of messages for a bundle 
      * */
-static void HTCIssueSendBundle(HTC_ENDPOINT      *pEndpoint, 
-                               HTC_PACKET_QUEUE  *pQueue, 
+static void HTCIssueSendBundle(struct htc_endpoint      *pEndpoint, 
+                               struct htc_packet_queue  *pQueue, 
                                int               *pBundlesSent, 
                                int               *pTotalBundlesPkts)
 {
     int                 pktsToScatter;
     unsigned int        scatterSpaceRemaining;
-    HIF_SCATTER_REQ     *pScatterReq = NULL;
+    struct hif_scatter_req     *pScatterReq = NULL;
     int                 i, packetsInScatterReq;
     unsigned int        transferLength;
-    HTC_PACKET          *pPacket;
-    A_BOOL              done = FALSE;
+    struct htc_packet          *pPacket;
+    bool              done = false;
     int                 bundlesSent = 0;
     int                 totalPktsInBundle = 0;
-    HTC_TARGET          *target = pEndpoint->target;
+    struct htc_target          *target = pEndpoint->target;
     int                 creditRemainder = 0;
     int                 creditPad;
     
@@ -361,7 +361,7 @@ static void HTCIssueSendBundle(HTC_ENDPOINT      *pEndpoint,
             
             pPacket = HTC_GET_PKT_AT_HEAD(pQueue);        
             if (pPacket == NULL) {
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;    
             }
             
@@ -400,7 +400,7 @@ static void HTCIssueSendBundle(HTC_ENDPOINT      *pEndpoint,
                        
             if (NULL == pPacket) {
                     /* can't bundle */
-                done = TRUE;
+                done = true;
                 break;    
             }         
                
@@ -450,7 +450,7 @@ static void HTCIssueSendBundle(HTC_ENDPOINT      *pEndpoint,
             if (packetsInScatterReq > 0) {
                     /* work backwards to requeue requests */
                 for (i = (packetsInScatterReq - 1); i >= 0; i--) {
-                    pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
+                    pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
                     if (pPacket != NULL) {
                             /* undo any prep */
                         HTC_UNPREPARE_SEND_PKT(pPacket);
@@ -477,12 +477,12 @@ static void HTCIssueSendBundle(HTC_ENDPOINT      *pEndpoint,
 /*
  * if there are no credits, the packet(s) remains in the queue.
  * this function returns the result of the attempt to send a queue of HTC packets */
-static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
-                                        HTC_ENDPOINT     *pEndpoint,
-                                        HTC_PACKET_QUEUE *pCallersSendQueue)
+static HTC_SEND_QUEUE_RESULT HTCTrySend(struct htc_target       *target,
+                                        struct htc_endpoint     *pEndpoint,
+                                        struct htc_packet_queue *pCallersSendQueue)
 {
-    HTC_PACKET_QUEUE      sendQueue; /* temp queue to hold packets at various stages */
-    HTC_PACKET            *pPacket;
+    struct htc_packet_queue      sendQueue; /* temp queue to hold packets at various stages */
+    struct htc_packet            *pPacket;
     int                   bundlesSent;
     int                   pktsInBundles;
     int                   overflow;
@@ -546,7 +546,7 @@ static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
             
                 /* the caller's queue has all the packets that won't fit*/                
                 /* walk through the caller's queue and indicate each one to the send full handler */            
-            ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, HTC_PACKET, ListLink) {            
+            ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, struct htc_packet, ListLink) {            
                 
                 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n", 
                                             (unsigned long)pPacket));    
@@ -571,7 +571,7 @@ static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
             } 
         }
         
-    } while (FALSE);
+    } while (false);
     
     if (result != HTC_SEND_QUEUE_OK) {
         AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend:  \n"));
@@ -602,7 +602,7 @@ static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
             
         /* now drain the endpoint TX queue for transmission as long as we have enough
          * credits */
-    while (TRUE) {
+    while (true) {
           
         if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) {
             break;
@@ -623,7 +623,7 @@ static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
         bundlesSent = 0;
         pktsInBundles = 0;
      
-        while (TRUE) {
+        while (true) {
             
                 /* try to send a bundle on each pass */            
             if ((target->SendBundlingEnabled) &&
@@ -668,11 +668,11 @@ static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
     return HTC_SEND_QUEUE_OK;
 }
 
-A_STATUS  HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
+int  HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint;
-    HTC_PACKET      *pPacket;
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint;
+    struct htc_packet      *pPacket;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n",
                     (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
@@ -705,13 +705,13 @@ A_STATUS  HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
 
-    return A_OK;   
+    return 0;
 }
 
 /* HTC API - HTCSendPkt */
-A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
+int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
 {
-    HTC_PACKET_QUEUE queue;
+    struct htc_packet_queue queue;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
                     ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n",
@@ -721,10 +721,10 @@ A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
 }
 
 /* check TX queues to drain because of credit distribution update */
-static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
+static INLINE void HTCCheckEndpointTxQueues(struct htc_target *target)
 {
-    HTC_ENDPOINT                *pEndpoint;
-    HTC_ENDPOINT_CREDIT_DIST    *pDistItem;
+    struct htc_endpoint                *pEndpoint;
+    struct htc_endpoint_credit_dist    *pDistItem;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
     pDistItem = target->EpCreditDistributionListHead;
@@ -734,7 +734,7 @@ static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
          * NOTE: no locks need to be taken since the distribution list
          * is not dynamic (cannot be re-ordered) and we are not modifying any state */
     while (pDistItem != NULL) {
-        pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
+        pEndpoint = (struct htc_endpoint *)pDistItem->pHTCReserved;
 
         if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
@@ -753,12 +753,12 @@ static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
 }
 
 /* process credit reports and call distribution function */
-void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
+void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
 {
     int             i;
-    HTC_ENDPOINT    *pEndpoint;
+    struct htc_endpoint    *pEndpoint;
     int             totalCredits = 0;
-    A_BOOL          doDist = FALSE;
+    bool          doDist = false;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
 
@@ -767,7 +767,7 @@ void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEnt
 
     for (i = 0; i < NumEntries; i++, pRpt++) {
         if (pRpt->EndpointID >= ENDPOINT_MAX) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
@@ -807,7 +807,7 @@ void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEnt
                  * will handle giving out credits back to the endpoints */
             pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
                 /* flag that we have to do the distribution */
-            doDist = TRUE;
+            doDist = true;
         }
         
             /* refresh tx depth for distribution function that will recover these credits
@@ -838,11 +838,11 @@ void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEnt
 }
 
 /* flush endpoint TX queue */
-static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
+static void HTCFlushEndpointTX(struct htc_target *target, struct htc_endpoint *pEndpoint, HTC_TX_TAG Tag)
 {
-    HTC_PACKET          *pPacket;
-    HTC_PACKET_QUEUE    discardQueue;
-    HTC_PACKET_QUEUE    container;
+    struct htc_packet          *pPacket;
+    struct htc_packet_queue    discardQueue;
+    struct htc_packet_queue    container;
 
         /* initialize the discard queue */
     INIT_HTC_PACKET_QUEUE(&discardQueue);
@@ -850,7 +850,7 @@ static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_
     LOCK_HTC_TX(target);
 
         /* interate from the front of the TX queue and flush out packets */
-    ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, HTC_PACKET, ListLink) {
+    ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, struct htc_packet, ListLink) {
 
             /* check for removal */
         if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
@@ -879,7 +879,7 @@ static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_
 
 }
 
-void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
+void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d  ServiceID: 0x%X    --------------\n",
                         pEPDist->Endpoint, pEPDist->ServiceID));
@@ -895,13 +895,13 @@ void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist    : %d \n", pEPDist->TxCreditsToDist));
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth       : %d \n", 
-                    HTC_PACKET_QUEUE_DEPTH(&((HTC_ENDPOINT *)pEPDist->pHTCReserved)->TxQueue)));                                      
+                    HTC_PACKET_QUEUE_DEPTH(&((struct htc_endpoint *)pEPDist->pHTCReserved)->TxQueue)));                                      
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
 }
 
-void DumpCreditDistStates(HTC_TARGET *target)
+void DumpCreditDistStates(struct htc_target *target)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
+    struct htc_endpoint_credit_dist *pEPList = target->EpCreditDistributionListHead;
 
     while (pEPList != NULL) {
         DumpCreditDist(pEPList);
@@ -917,9 +917,9 @@ void DumpCreditDistStates(HTC_TARGET *target)
 }
 
 /* flush all send packets from all endpoint queues */
-void HTCFlushSendPkts(HTC_TARGET *target)
+void HTCFlushSendPkts(struct htc_target *target)
 {
-    HTC_ENDPOINT    *pEndpoint;
+    struct htc_endpoint    *pEndpoint;
     int             i;
 
     if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
@@ -941,11 +941,11 @@ void HTCFlushSendPkts(HTC_TARGET *target)
 /* HTC API to flush an endpoint's TX queue*/
 void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[Endpoint];
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[Endpoint];
 
     if (pEndpoint->ServiceID == 0) {
-        AR_DEBUG_ASSERT(FALSE);
+        AR_DEBUG_ASSERT(false);
         /* not in use.. */
         return;
     }
@@ -956,14 +956,14 @@ void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG
 /* HTC API to indicate activity to the credit distribution function */
 void HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
                                HTC_ENDPOINT_ID Endpoint,
-                               A_BOOL          Active)
+                               bool          Active)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[Endpoint];
-    A_BOOL          doDist = FALSE;
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[Endpoint];
+    bool          doDist = false;
 
     if (pEndpoint->ServiceID == 0) {
-        AR_DEBUG_ASSERT(FALSE);
+        AR_DEBUG_ASSERT(false);
         /* not in use.. */
         return;
     }
@@ -974,13 +974,13 @@ void HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
         if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
                 /* mark active now */
             pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
-            doDist = TRUE;
+            doDist = true;
         }
     } else {
         if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
                 /* mark inactive now */
             pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
-            doDist = TRUE;
+            doDist = true;
         }
     }
 
@@ -1005,19 +1005,19 @@ void HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
     }
 }
 
-A_BOOL HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
+bool HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
                            HTC_ENDPOINT_ID Endpoint)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[Endpoint];
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[Endpoint];
 
     if (pEndpoint->ServiceID == 0) {
-        return FALSE;
+        return false;
     }
     
     if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
-        return TRUE;
+        return true;
     }
     
-    return FALSE;
+    return false;
 }
diff --git a/drivers/staging/ath6kl/htc2/htc_services.c b/drivers/staging/ath6kl/htc2/htc_services.c
index 64fddc0..c48070c 100644
--- a/drivers/staging/ath6kl/htc2/htc_services.c
+++ b/drivers/staging/ath6kl/htc2/htc_services.c
@@ -22,21 +22,21 @@
 //==============================================================================
 #include "htc_internal.h"
 
-void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket)
+void HTCControlTxComplete(void *Context, struct htc_packet *pPacket)
 {
         /* not implemented
          * we do not send control TX frames during normal runtime, only during setup  */
-    AR_DEBUG_ASSERT(FALSE);
+    AR_DEBUG_ASSERT(false);
 }
 
     /* callback when a control message arrives on this endpoint */
-void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
+void HTCControlRecv(void *Context, struct htc_packet *pPacket)
 {
     AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);
 
     if (pPacket->Status == A_ECANCELED) {
         /* this is a flush operation, return the control packet back to the pool */
-        HTC_FREE_CONTROL_RX((HTC_TARGET*)Context,pPacket);    
+        HTC_FREE_CONTROL_RX((struct htc_target*)Context,pPacket);    
         return;
     }  
     
@@ -44,7 +44,7 @@ void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
     if (pPacket->ActualLength > 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("HTCControlRecv, got message with length:%d \n",
-                        pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH));
+                        pPacket->ActualLength + (u32)HTC_HDR_LENGTH));
 
 #ifdef ATH_DEBUG_MODULE
             /* dump header and message */
@@ -54,13 +54,13 @@ void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
 #endif
     }
 
-    HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket,&((HTC_TARGET*)Context)->EndPoint[0]);
+    HTC_RECYCLE_RX_PKT((struct htc_target*)Context,pPacket,&((struct htc_target*)Context)->EndPoint[0]);
 }
 
-A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
+int HTCSendSetupComplete(struct htc_target *target)
 {
-    HTC_PACKET             *pSendPacket = NULL;
-    A_STATUS                status;
+    struct htc_packet             *pSendPacket = NULL;
+    int                status;
 
     do {
            /* allocate a packet to send to the target */
@@ -73,7 +73,7 @@ A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
 
         if (target->HTCTargetVersion >= HTC_VERSION_2P1) {
             HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx;
-            A_UINT32                  setupFlags = 0;
+            u32 setupFlags = 0;
                    
             pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer;
             A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
@@ -83,10 +83,10 @@ A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
                 setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; 
                 pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle;
             }    
-            A_MEMCPY(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags));            
+            memcpy(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags));            
             SET_HTC_PACKET_INFO_TX(pSendPacket,
                                    NULL,
-                                   (A_UINT8 *)pSetupCompleteEx,
+                                   (u8 *)pSetupCompleteEx,
                                    sizeof(HTC_SETUP_COMPLETE_EX_MSG),
                                    ENDPOINT_0,
                                    HTC_SERVICE_TX_PACKET_TAG);
@@ -99,7 +99,7 @@ A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
             pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID;   
             SET_HTC_PACKET_INFO_TX(pSendPacket,
                                    NULL,
-                                   (A_UINT8 *)pSetupComplete,
+                                   (u8 *)pSetupComplete,
                                    sizeof(HTC_SETUP_COMPLETE_MSG),
                                    ENDPOINT_0,
                                    HTC_SERVICE_TX_PACKET_TAG);
@@ -111,7 +111,7 @@ A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
             /* send the message */
         status = HTCIssueSend(target,pSendPacket);
 
-    } while (FALSE);
+    } while (false);
 
     if (pSendPacket != NULL) {
         HTC_FREE_CONTROL_TX(target,pSendPacket);
@@ -121,18 +121,18 @@ A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
 }
 
 
-A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
-                           HTC_SERVICE_CONNECT_REQ  *pConnectReq,
-                           HTC_SERVICE_CONNECT_RESP *pConnectResp)
+int HTCConnectService(HTC_HANDLE               HTCHandle,
+                           struct htc_service_connect_req  *pConnectReq,
+                           struct htc_service_connect_resp *pConnectResp)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_STATUS                            status = A_OK;
-    HTC_PACKET                          *pRecvPacket = NULL;
-    HTC_PACKET                          *pSendPacket = NULL;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    int                            status = 0;
+    struct htc_packet                          *pRecvPacket = NULL;
+    struct htc_packet                          *pSendPacket = NULL;
     HTC_CONNECT_SERVICE_RESPONSE_MSG    *pResponseMsg;
     HTC_CONNECT_SERVICE_MSG             *pConnectMsg;
     HTC_ENDPOINT_ID                     assignedEndpoint = ENDPOINT_MAX;
-    HTC_ENDPOINT                        *pEndpoint;
+    struct htc_endpoint                        *pEndpoint;
     unsigned int                        maxMsgSize = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%lX SvcID:0x%X \n",
@@ -151,7 +151,7 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
             pSendPacket = HTC_ALLOC_CONTROL_TX(target);
 
             if (NULL == pSendPacket) {
-                AR_DEBUG_ASSERT(FALSE);
+                AR_DEBUG_ASSERT(false);
                 status = A_NO_MEMORY;
                 break;
             }
@@ -166,7 +166,7 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
             if ((pConnectReq->pMetaData != NULL) &&
                 (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
                     /* copy meta data into message buffer (after header ) */
-                A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
+                memcpy((u8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
                          pConnectReq->pMetaData,
                          pConnectReq->MetaDataLength);
                 pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength;
@@ -174,7 +174,7 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
 
             SET_HTC_PACKET_INFO_TX(pSendPacket,
                                    NULL,
-                                   (A_UINT8 *)pConnectMsg,
+                                   (u8 *)pConnectMsg,
                                    sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength,
                                    ENDPOINT_0,
                                    HTC_SERVICE_TX_PACKET_TAG);
@@ -184,14 +184,14 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
             HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0);
             status = HTCIssueSend(target,pSendPacket);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
                 /* wait for response */
             status = HTCWaitforControlMessage(target, &pRecvPacket);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
                 /* we controlled the buffer creation so it has to be properly aligned */
@@ -200,7 +200,7 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
             if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) ||
                 (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) {
                     /* this message is not valid */
-                AR_DEBUG_ASSERT(FALSE);
+                AR_DEBUG_ASSERT(false);
                 status = A_EPROTO;
                 break;
             }
@@ -224,8 +224,8 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
                     /* caller supplied a buffer and the target responded with data */
                 int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength);
                     /* copy the meta data */
-                A_MEMCPY(pConnectResp->pMetaData,
-                         ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
+                memcpy(pConnectResp->pMetaData,
+                         ((u8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
                          copyLength);
                 pConnectResp->ActualLength = copyLength;
             }
@@ -236,12 +236,12 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
         status = A_EPROTO;
 
         if (assignedEndpoint >= ENDPOINT_MAX) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
         if (0 == maxMsgSize) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
@@ -249,7 +249,7 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
         pEndpoint->Id = assignedEndpoint;
         if (pEndpoint->ServiceID != 0) {
             /* endpoint already in use! */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
@@ -275,7 +275,7 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
                  * since the host will actually issue smaller messages in the Send path */
             if (pConnectReq->MaxSendMsgSize > maxMsgSize) {
                     /* can't be larger than the maximum the target can support */
-                AR_DEBUG_ASSERT(FALSE);
+                AR_DEBUG_ASSERT(false);
                 break;       
             }
             pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize;
@@ -290,9 +290,9 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
             /* save local connection flags */
         pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags;
         
-        status = A_OK;
+        status = 0;
 
-    } while (FALSE);
+    } while (false);
 
     if (pSendPacket != NULL) {
         HTC_FREE_CONTROL_TX(target,pSendPacket);
@@ -307,9 +307,9 @@ A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
     return status;
 }
 
-static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *pEpDist)
+static void AddToEndpointDistList(struct htc_target *target, struct htc_endpoint_credit_dist *pEpDist)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEntry,*pLastEntry;
+    struct htc_endpoint_credit_dist *pCurEntry,*pLastEntry;
 
     if (NULL == target->EpCreditDistributionListHead) {
         target->EpCreditDistributionListHead = pEpDist;
@@ -336,10 +336,10 @@ static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *
 
 /* default credit init callback */
 static void HTCDefaultCreditInit(void                     *Context,
-                                 HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                                 struct htc_endpoint_credit_dist *pEPList,
                                  int                      TotalCredits)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
     int                      totalEps = 0;
     int                      creditsPerEndpoint;
 
@@ -360,7 +360,7 @@ static void HTCDefaultCreditInit(void                     *Context,
 
         if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) {
                 /* too many endpoints and not enough credits */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
             /* our minimum is set for at least 1 max message */
@@ -379,10 +379,10 @@ static void HTCDefaultCreditInit(void                     *Context,
 
 /* default credit distribution callback, NOTE, this callback holds the TX lock */
 void HTCDefaultCreditDist(void                     *Context,
-                          HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
+                          struct htc_endpoint_credit_dist *pEPDistList,
                           HTC_CREDIT_DIST_REASON   Reason)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
 
     if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) {
         pCurEpDist = pEPDistList;
@@ -408,7 +408,7 @@ void HTCSetCreditDistribution(HTC_HANDLE               HTCHandle,
                               HTC_SERVICE_ID           ServicePriorityOrder[],
                               int                      ListLength)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     int i;
     int ep;
 
diff --git a/drivers/staging/ath6kl/include/a_debug.h b/drivers/staging/ath6kl/include/a_debug.h
index 5a1b01f..d433942 100644
--- a/drivers/staging/ath6kl/include/a_debug.h
+++ b/drivers/staging/ath6kl/include/a_debug.h
@@ -57,7 +57,7 @@ extern "C" {
     /* macro to make a module-specific masks */
 #define ATH_DEBUG_MAKE_MODULE_MASK(index)  (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index)))
 
-void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
+void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription);
 
 /* Debug support on a per-module basis
  *
@@ -95,7 +95,7 @@ void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
  *   #define ATH_DEBUG_BMI  ATH_DEBUG_MAKE_MODULE_MASK(0)
  *
  *   #ifdef DEBUG
- *   static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
+ *   static struct ath_debug_mask_description bmi_debug_desc[] = {
  *       { ATH_DEBUG_BMI , "BMI Tracing"},   <== description of the module specific mask
  *   };
  *
@@ -118,24 +118,24 @@ void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
 #define ATH_DEBUG_MAX_MASK_DESC_LENGTH   32
 #define ATH_DEBUG_MAX_MOD_DESC_LENGTH    64
 
-typedef struct {
-    A_UINT32 Mask;
-    A_CHAR   Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH];
-} ATH_DEBUG_MASK_DESCRIPTION;
+struct ath_debug_mask_description {
+    u32 Mask;
+    char Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH];
+};
 
 #define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0)
 
 typedef struct  _ATH_DEBUG_MODULE_DBG_INFO{
     struct _ATH_DEBUG_MODULE_DBG_INFO *pNext;
-    A_CHAR                      ModuleName[16];
-    A_CHAR                      ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH];
-    A_UINT32                    Flags;
-    A_UINT32                    CurrentMask;
+    char ModuleName[16];
+    char ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH];
+    u32 Flags;
+    u32 CurrentMask;
     int                         MaxDescriptions;
-    ATH_DEBUG_MASK_DESCRIPTION  *pMaskDescriptions; /* pointer to array of descriptions */
+    struct ath_debug_mask_description  *pMaskDescriptions; /* pointer to array of descriptions */
 } ATH_DEBUG_MODULE_DBG_INFO;
 
-#define ATH_DEBUG_DESCRIPTION_COUNT(d)  (int)((sizeof((d))) / (sizeof(ATH_DEBUG_MASK_DESCRIPTION)))
+#define ATH_DEBUG_DESCRIPTION_COUNT(d)  (int)((sizeof((d))) / (sizeof(struct ath_debug_mask_description)))
 
 #define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s)
 #define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask
@@ -181,9 +181,9 @@ void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo);
 
 #endif
 
-A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask);
-A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask);
-void a_dump_module_debug_info_by_name(A_CHAR *module_name);
+int a_get_module_mask(char *module_name, u32 *pMask);
+int a_set_module_mask(char *module_name, u32 Mask);
+void a_dump_module_debug_info_by_name(char *module_name);
 void a_module_debug_support_init(void);
 void a_module_debug_support_cleanup(void);
 
diff --git a/drivers/staging/ath6kl/include/a_drv_api.h b/drivers/staging/ath6kl/include/a_drv_api.h
index 7d077c6..5e098cb 100644
--- a/drivers/staging/ath6kl/include/a_drv_api.h
+++ b/drivers/staging/ath6kl/include/a_drv_api.h
@@ -188,10 +188,10 @@ extern "C" {
     ar6000_dbglog_event((ar), (dropped), (buffer), (length));
 
 #define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \
-    ar6000_indicate_tx_activity((devt),(trafficClass), TRUE)
+    ar6000_indicate_tx_activity((devt),(trafficClass), true)
 
 #define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \
-    ar6000_indicate_tx_activity((devt),(trafficClass), FALSE)
+    ar6000_indicate_tx_activity((devt),(trafficClass), false)
 #define A_WMI_Ac2EndpointID(devht, ac)\
     ar6000_ac2_endpoint_id((devht), (ac))
 
diff --git a/drivers/staging/ath6kl/include/aggr_recv_api.h b/drivers/staging/ath6kl/include/aggr_recv_api.h
index 0682bb4..67a0584 100644
--- a/drivers/staging/ath6kl/include/aggr_recv_api.h
+++ b/drivers/staging/ath6kl/include/aggr_recv_api.h
@@ -30,7 +30,7 @@ extern "C" {
 
 typedef void (* RX_CALLBACK)(void * dev, void *osbuf);
 
-typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, A_UINT16 num);
+typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, u16 num);
 
 /*
  * aggr_init:
@@ -64,7 +64,7 @@ aggr_register_rx_dispatcher(void *cntxt, void * dev,  RX_CALLBACK fn);
  * up to the indicated sequence number.
  */
 void
-aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no);
+aggr_process_bar(void *cntxt, u8 tid, u16 seq_no);
 
 
 /*
@@ -82,7 +82,7 @@ aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no);
  * in hold_q to OS.
  */
 void
-aggr_recv_addba_req_evt(void * cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_sz);
+aggr_recv_addba_req_evt(void * cntxt, u8 tid, u16 seq_no, u8 win_sz);
 
 
 /*
@@ -93,7 +93,7 @@ aggr_recv_addba_req_evt(void * cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_
  * aggr is not enabled on any tid.
  */
 void
-aggr_recv_delba_req_evt(void * cntxt, A_UINT8 tid);
+aggr_recv_delba_req_evt(void * cntxt, u8 tid);
 
 
 
@@ -108,7 +108,7 @@ aggr_recv_delba_req_evt(void * cntxt, A_UINT8 tid);
  * callback may be called to deliver frames in order.
  */
 void
-aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu, void **osbuf);
+aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf);
 
 
 /*
diff --git a/drivers/staging/ath6kl/include/ar3kconfig.h b/drivers/staging/ath6kl/include/ar3kconfig.h
index a10788c..91bc4ee 100644
--- a/drivers/staging/ath6kl/include/ar3kconfig.h
+++ b/drivers/staging/ath6kl/include/ar3kconfig.h
@@ -38,25 +38,25 @@ extern "C" {
 #define AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP        (1 << 3)
 
 
-typedef struct {
-    A_UINT32                 Flags;           /* config flags */
+struct ar3k_config_info {
+    u32 Flags;           /* config flags */
     void                     *pHCIDev;        /* HCI bridge device     */
-    HCI_TRANSPORT_PROPERTIES *pHCIProps;      /* HCI bridge props      */
-    HIF_DEVICE               *pHIFDevice;     /* HIF layer device      */
+    struct hci_transport_properties *pHCIProps;      /* HCI bridge props      */
+    struct hif_device               *pHIFDevice;     /* HIF layer device      */
     
-    A_UINT32                 AR3KBaudRate;    /* AR3K operational baud rate */
-    A_UINT16                 AR6KScale;       /* AR6K UART scale value */    
-    A_UINT16                 AR6KStep;        /* AR6K UART step value  */
+    u32 AR3KBaudRate;    /* AR3K operational baud rate */
+    u16 AR6KScale;       /* AR6K UART scale value */
+    u16 AR6KStep;        /* AR6K UART step value  */
     struct hci_dev           *pBtStackHCIDev; /* BT Stack HCI dev */
-    A_UINT32                 PwrMgmtEnabled;  /* TLPM enabled? */  
-    A_UINT16                 IdleTimeout;     /* TLPM idle timeout */
-    A_UINT16                 WakeupTimeout;   /* TLPM wakeup timeout */
-    A_UINT8                  bdaddr[6];       /* Bluetooth device address */
-} AR3K_CONFIG_INFO;
+    u32 PwrMgmtEnabled;  /* TLPM enabled? */
+    u16 IdleTimeout;     /* TLPM idle timeout */
+    u16 WakeupTimeout;   /* TLPM wakeup timeout */
+    u8 bdaddr[6];       /* Bluetooth device address */
+};
                                                                                         
-A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfigInfo);
+int AR3KConfigure(struct ar3k_config_info *pConfigInfo);
 
-A_STATUS AR3KConfigureExit(void *config);
+int AR3KConfigureExit(void *config);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/ar6000_diag.h b/drivers/staging/ath6kl/include/ar6000_diag.h
index b53512e..739c01c 100644
--- a/drivers/staging/ath6kl/include/ar6000_diag.h
+++ b/drivers/staging/ath6kl/include/ar6000_diag.h
@@ -25,24 +25,24 @@
 #define AR6000_DIAG_H_
 
 
-A_STATUS
-ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int
+ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS
-ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int
+ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS
-ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                    A_UCHAR *data, A_UINT32 length);
+int
+ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,
+                    u8 *data, u32 length);
 
-A_STATUS
-ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                     A_UCHAR *data, A_UINT32 length);
+int
+ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address,
+                     u8 *data, u32 length);
 
-A_STATUS
-ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval);
+int
+ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval);
 
 void
-ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs);
+ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs);
 
 #endif /*AR6000_DIAG_H_*/
diff --git a/drivers/staging/ath6kl/include/ar6kap_common.h b/drivers/staging/ath6kl/include/ar6kap_common.h
index 9b1b8bf..532d8eb 100644
--- a/drivers/staging/ath6kl/include/ar6kap_common.h
+++ b/drivers/staging/ath6kl/include/ar6kap_common.h
@@ -32,11 +32,11 @@
  * Used with AR6000_XIOCTL_AP_GET_STA_LIST
  */
 typedef struct {
-    A_UINT8     mac[ATH_MAC_LEN];
-    A_UINT8     aid;
-    A_UINT8     keymgmt;
-    A_UINT8     ucipher;
-    A_UINT8     auth;
+    u8 mac[ATH_MAC_LEN];
+    u8 aid;
+    u8 keymgmt;
+    u8 ucipher;
+    u8 auth;
 } station_t;
 typedef struct {
     station_t sta[AP_MAX_NUM_STA];
diff --git a/drivers/staging/ath6kl/include/athbtfilter.h b/drivers/staging/ath6kl/include/athbtfilter.h
index dbe68bb..81456ee 100644
--- a/drivers/staging/ath6kl/include/athbtfilter.h
+++ b/drivers/staging/ath6kl/include/athbtfilter.h
@@ -61,11 +61,11 @@ typedef enum _ATHBT_STATE {
 
 typedef void   (*ATHBT_INDICATE_STATE_FN)(void *pContext, ATHBT_STATE_INDICATION Indication, ATHBT_STATE State, unsigned char LMPVersion);
 
-typedef struct _ATHBT_FILTER_INSTANCE {
+struct athbt_filter_instance {
 #ifdef UNDER_CE
     WCHAR                       *pWlanAdapterName;  /* filled in by user */
 #else
-    char                        *pWlanAdapterName;  /* filled in by user */
+    char *pWlanAdapterName;  /* filled in by user */
 #endif /* UNDER_CE */
     int                         FilterEnabled;      /* filtering is enabled */
     int                         Attached;           /* filter library is attached */
@@ -74,7 +74,7 @@ typedef struct _ATHBT_FILTER_INSTANCE {
     ATHBT_FILTER_DATA_FN        pFilterAclDataOut;  /* function ptr to filter ACL data out (to radio) */
     ATHBT_FILTER_DATA_FN        pFilterAclDataIn;   /* function ptr to filter ACL data in (from radio) */
     ATHBT_INDICATE_STATE_FN     pIndicateState;     /* function ptr to indicate a state */
-} ATH_BT_FILTER_INSTANCE;
+}; /* XXX: unused ? */
 
 
 /* API MACROS */
diff --git a/drivers/staging/ath6kl/include/bmi.h b/drivers/staging/ath6kl/include/bmi.h
index 27aa98d..eb1e756 100644
--- a/drivers/staging/ath6kl/include/bmi.h
+++ b/drivers/staging/ath6kl/include/bmi.h
@@ -43,90 +43,90 @@ BMIInit(void);
 void
 BMICleanup(void);
 
-A_STATUS
-BMIDone(HIF_DEVICE *device);
-
-A_STATUS
-BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info);
-
-A_STATUS
-BMIReadMemory(HIF_DEVICE *device,
-              A_UINT32 address,
-              A_UCHAR *buffer,
-              A_UINT32 length);
-
-A_STATUS
-BMIWriteMemory(HIF_DEVICE *device,
-               A_UINT32 address,
-               A_UCHAR *buffer,
-               A_UINT32 length);
-
-A_STATUS
-BMIExecute(HIF_DEVICE *device,
-           A_UINT32 address,
-           A_UINT32 *param);
-
-A_STATUS
-BMISetAppStart(HIF_DEVICE *device,
-               A_UINT32 address);
-
-A_STATUS
-BMIReadSOCRegister(HIF_DEVICE *device,
-                   A_UINT32 address,
-                   A_UINT32 *param);
-
-A_STATUS
-BMIWriteSOCRegister(HIF_DEVICE *device,
-                    A_UINT32 address,
-                    A_UINT32 param);
-
-A_STATUS
-BMIrompatchInstall(HIF_DEVICE *device,
-                   A_UINT32 ROM_addr,
-                   A_UINT32 RAM_addr,
-                   A_UINT32 nbytes,
-                   A_UINT32 do_activate,
-                   A_UINT32 *patch_id);
-
-A_STATUS
-BMIrompatchUninstall(HIF_DEVICE *device,
-                     A_UINT32 rompatch_id);
-
-A_STATUS
-BMIrompatchActivate(HIF_DEVICE *device,
-                    A_UINT32 rompatch_count,
-                    A_UINT32 *rompatch_list);
-
-A_STATUS
-BMIrompatchDeactivate(HIF_DEVICE *device,
-                      A_UINT32 rompatch_count,
-                      A_UINT32 *rompatch_list);
-
-A_STATUS
-BMILZStreamStart(HIF_DEVICE *device,
-                 A_UINT32 address);
-
-A_STATUS
-BMILZData(HIF_DEVICE *device,
-          A_UCHAR *buffer,
-          A_UINT32 length);
-
-A_STATUS
-BMIFastDownload(HIF_DEVICE *device,
-                A_UINT32 address,
-                A_UCHAR *buffer,
-                A_UINT32 length);
-
-A_STATUS
-BMIRawWrite(HIF_DEVICE *device,
-            A_UCHAR *buffer,
-            A_UINT32 length);
-
-A_STATUS
-BMIRawRead(HIF_DEVICE *device, 
-           A_UCHAR *buffer, 
-           A_UINT32 length, 
-           A_BOOL want_timeout);
+int
+BMIDone(struct hif_device *device);
+
+int
+BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info);
+
+int
+BMIReadMemory(struct hif_device *device,
+              u32 address,
+              u8 *buffer,
+              u32 length);
+
+int
+BMIWriteMemory(struct hif_device *device,
+               u32 address,
+               u8 *buffer,
+               u32 length);
+
+int
+BMIExecute(struct hif_device *device,
+           u32 address,
+           u32 *param);
+
+int
+BMISetAppStart(struct hif_device *device,
+               u32 address);
+
+int
+BMIReadSOCRegister(struct hif_device *device,
+                   u32 address,
+                   u32 *param);
+
+int
+BMIWriteSOCRegister(struct hif_device *device,
+                    u32 address,
+                    u32 param);
+
+int
+BMIrompatchInstall(struct hif_device *device,
+                   u32 ROM_addr,
+                   u32 RAM_addr,
+                   u32 nbytes,
+                   u32 do_activate,
+                   u32 *patch_id);
+
+int
+BMIrompatchUninstall(struct hif_device *device,
+                     u32 rompatch_id);
+
+int
+BMIrompatchActivate(struct hif_device *device,
+                    u32 rompatch_count,
+                    u32 *rompatch_list);
+
+int
+BMIrompatchDeactivate(struct hif_device *device,
+                      u32 rompatch_count,
+                      u32 *rompatch_list);
+
+int
+BMILZStreamStart(struct hif_device *device,
+                 u32 address);
+
+int
+BMILZData(struct hif_device *device,
+          u8 *buffer,
+          u32 length);
+
+int
+BMIFastDownload(struct hif_device *device,
+                u32 address,
+                u8 *buffer,
+                u32 length);
+
+int
+BMIRawWrite(struct hif_device *device,
+            u8 *buffer,
+            u32 length);
+
+int
+BMIRawRead(struct hif_device *device, 
+           u8 *buffer, 
+           u32 length,
+           bool want_timeout);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h b/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h
index e3291cf..4a9b275 100644
--- a/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h
+++ b/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h
@@ -29,28 +29,28 @@
  * This must match the state saved by the target exception handler.
  */
 struct XTensa_exception_frame_s {
-    A_UINT32 xt_pc;
-    A_UINT32 xt_ps;
-    A_UINT32 xt_sar;
-    A_UINT32 xt_vpri;
-    A_UINT32 xt_a2;
-    A_UINT32 xt_a3;
-    A_UINT32 xt_a4;
-    A_UINT32 xt_a5;
-    A_UINT32 xt_exccause;
-    A_UINT32 xt_lcount;
-    A_UINT32 xt_lbeg;
-    A_UINT32 xt_lend;
+    u32 xt_pc;
+    u32 xt_ps;
+    u32 xt_sar;
+    u32 xt_vpri;
+    u32 xt_a2;
+    u32 xt_a3;
+    u32 xt_a4;
+    u32 xt_a5;
+    u32 xt_exccause;
+    u32 xt_lcount;
+    u32 xt_lbeg;
+    u32 xt_lend;
 
-    A_UINT32 epc1, epc2, epc3, epc4;
+    u32 epc1, epc2, epc3, epc4;
 
     /* Extra info to simplify post-mortem stack walkback */
 #define AR6002_REGDUMP_FRAMES 10
     struct {
-        A_UINT32 a0;  /* pc */
-        A_UINT32 a1;  /* sp */
-        A_UINT32 a2;
-        A_UINT32 a3;
+        u32 a0;  /* pc */
+        u32 a1;  /* sp */
+        u32 a2;
+        u32 a3;
     } wb[AR6002_REGDUMP_FRAMES];
 };
 typedef struct XTensa_exception_frame_s CPU_exception_frame_t; 
diff --git a/drivers/staging/ath6kl/include/common/AR6002/addrs.h b/drivers/staging/ath6kl/include/common/AR6002/addrs.h
index eaaccf4..bbf8d42 100644
--- a/drivers/staging/ath6kl/include/common/AR6002/addrs.h
+++ b/drivers/staging/ath6kl/include/common/AR6002/addrs.h
@@ -29,13 +29,13 @@
 
 #if defined(AR6002_REV2)
 #define AR6K_RAM_START 0x00500000
-#define TARG_RAM_OFFSET(vaddr) ((A_UINT32)(vaddr) & 0xfffff)
+#define TARG_RAM_OFFSET(vaddr) ((u32)(vaddr) & 0xfffff)
 #define TARG_RAM_SZ (184*1024)
 #define TARG_ROM_SZ (80*1024)
 #endif
 #if defined(AR6002_REV4) || defined(AR6003)
 #define AR6K_RAM_START 0x00540000
-#define TARG_RAM_OFFSET(vaddr) (((A_UINT32)(vaddr) & 0xfffff) - 0x40000)
+#define TARG_RAM_OFFSET(vaddr) (((u32)(vaddr) & 0xfffff) - 0x40000)
 #define TARG_RAM_SZ (256*1024)
 #define TARG_ROM_SZ (256*1024)
 #endif
@@ -49,7 +49,7 @@
 #define TARG_RAM_ADDRS(byte_offset) AR6K_RAM_ADDR(byte_offset)
 
 #define AR6K_ROM_START 0x004e0000
-#define TARG_ROM_OFFSET(vaddr) (((A_UINT32)(vaddr) & 0x1fffff) - 0xe0000)
+#define TARG_ROM_OFFSET(vaddr) (((u32)(vaddr) & 0x1fffff) - 0xe0000)
 #define AR6K_ROM_ADDR(byte_offset) (AR6K_ROM_START+(byte_offset))
 #define TARG_ROM_ADDRS(byte_offset) AR6K_ROM_ADDR(byte_offset)
 
diff --git a/drivers/staging/ath6kl/include/common/a_hci.h b/drivers/staging/ath6kl/include/common/a_hci.h
index f294346..08cb013 100644
--- a/drivers/staging/ath6kl/include/common/a_hci.h
+++ b/drivers/staging/ath6kl/include/common/a_hci.h
@@ -242,161 +242,161 @@ typedef enum {
 
 /* Command pkt */
 typedef struct  hci_cmd_pkt_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     params[255];
+    u16 opcode;
+    u8 param_length;
+    u8 params[255];
 } POSTPACK HCI_CMD_PKT;
 
 #define ACL_DATA_HDR_SIZE   4   /* hdl_and flags + data_len */
 /* Data pkt */
 typedef struct  hci_acl_data_pkt_t {
-    A_UINT16    hdl_and_flags;
-    A_UINT16    data_len;
-    A_UINT8     data[Max80211_PAL_PDU_Size];
+    u16 hdl_and_flags;
+    u16 data_len;
+    u8 data[Max80211_PAL_PDU_Size];
 } POSTPACK HCI_ACL_DATA_PKT;
 
 /* Event pkt */
 typedef struct  hci_event_pkt_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     params[256];
+    u8 event_code;
+    u8 param_len;
+    u8 params[256];
 } POSTPACK HCI_EVENT_PKT;
 
 
 /*============== HCI Command definitions ======================= */
 typedef struct hci_cmd_phy_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     link_key_len;
-    A_UINT8     link_key_type;
-    A_UINT8     link_key[LINK_KEY_LEN];
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u8 link_key_len;
+    u8 link_key_type;
+    u8 link_key[LINK_KEY_LEN];
 } POSTPACK HCI_CMD_PHY_LINK;
 
 typedef struct  hci_cmd_write_rem_amp_assoc_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT16    len_so_far;
-    A_UINT16    amp_assoc_remaining_len;
-    A_UINT8     amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u16 len_so_far;
+    u16 amp_assoc_remaining_len;
+    u8 amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
 } POSTPACK HCI_CMD_WRITE_REM_AMP_ASSOC;
 
 
 typedef struct  hci_cmd_opcode_hdl_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
 } POSTPACK HCI_CMD_READ_LINK_QUAL,
            HCI_CMD_FLUSH,
            HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT;
 
 typedef struct  hci_cmd_read_local_amp_assoc_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT16    len_so_far;
-    A_UINT16    max_rem_amp_assoc_len;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u16 len_so_far;
+    u16 max_rem_amp_assoc_len;
 } POSTPACK HCI_CMD_READ_LOCAL_AMP_ASSOC;
 
 
 typedef struct hci_cmd_set_event_mask_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT64    mask;
+    u16 opcode;
+    u8 param_length;
+    u64 mask;
 }POSTPACK HCI_CMD_SET_EVT_MASK, HCI_CMD_SET_EVT_MASK_PG_2;
 
 
 typedef struct  hci_cmd_enhanced_flush_t{
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
-    A_UINT8     type;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
+    u8 type;
 } POSTPACK HCI_CMD_ENHANCED_FLUSH;
 
 
 typedef struct  hci_cmd_write_timeout_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    timeout;
+    u16 opcode;
+    u8 param_length;
+    u16 timeout;
 } POSTPACK  HCI_CMD_WRITE_TIMEOUT;
 
 typedef struct  hci_cmd_write_link_supervision_timeout_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
-    A_UINT16    timeout;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
+    u16 timeout;
 } POSTPACK HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT;
 
 typedef struct  hci_cmd_write_flow_control_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     mode;
+    u16 opcode;
+    u8 param_length;
+    u8 mode;
 } POSTPACK  HCI_CMD_WRITE_FLOW_CONTROL;
 
 typedef struct  location_data_cfg_t {
-    A_UINT8     reg_domain_aware;
-    A_UINT8     reg_domain[3];
-    A_UINT8     reg_options;
+    u8 reg_domain_aware;
+    u8 reg_domain[3];
+    u8 reg_options;
 } POSTPACK LOCATION_DATA_CFG;
 
 typedef struct  hci_cmd_write_location_data_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
+    u16 opcode;
+    u8 param_length;
     LOCATION_DATA_CFG   cfg;
 } POSTPACK  HCI_CMD_WRITE_LOCATION_DATA;
 
 
 typedef struct  flow_spec_t {
-    A_UINT8     id;
-    A_UINT8     service_type;
-    A_UINT16    max_sdu;
-    A_UINT32    sdu_inter_arrival_time;
-    A_UINT32    access_latency;
-    A_UINT32    flush_timeout;
+    u8 id;
+    u8 service_type;
+    u16 max_sdu;
+    u32 sdu_inter_arrival_time;
+    u32 access_latency;
+    u32 flush_timeout;
 } POSTPACK FLOW_SPEC;
 
 
 typedef struct  hci_cmd_create_logical_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
     FLOW_SPEC   tx_flow_spec;
     FLOW_SPEC   rx_flow_spec;
 } POSTPACK HCI_CMD_CREATE_LOGICAL_LINK;
 
 typedef struct  hci_cmd_flow_spec_modify_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
     FLOW_SPEC   tx_flow_spec;
     FLOW_SPEC   rx_flow_spec;
 } POSTPACK HCI_CMD_FLOW_SPEC_MODIFY;
 
 typedef struct hci_cmd_logical_link_cancel_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     tx_flow_spec_id;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u8 tx_flow_spec_id;
 } POSTPACK HCI_CMD_LOGICAL_LINK_CANCEL;
 
 typedef struct  hci_cmd_disconnect_logical_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    logical_link_hdl;
+    u16 opcode;
+    u8 param_length;
+    u16 logical_link_hdl;
 } POSTPACK HCI_CMD_DISCONNECT_LOGICAL_LINK;
 
 typedef struct  hci_cmd_disconnect_phy_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
 } POSTPACK HCI_CMD_DISCONNECT_PHY_LINK;
 
 typedef struct  hci_cmd_srm_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     mode;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u8 mode;
 } POSTPACK HCI_CMD_SHORT_RANGE_MODE;
 /*============== HCI Command definitions end ======================= */
 
@@ -406,175 +406,175 @@ typedef struct  hci_cmd_srm_t {
 
 /* Command complete event */
 typedef struct  hci_event_cmd_complete_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     num_hci_cmd_pkts;
-    A_UINT16    opcode;
-    A_UINT8     params[255];
+    u8 event_code;
+    u8 param_len;
+    u8 num_hci_cmd_pkts;
+    u16 opcode;
+    u8 params[255];
 } POSTPACK HCI_EVENT_CMD_COMPLETE;
 
 
 /* Command status event */
 typedef struct  hci_event_cmd_status_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     num_hci_cmd_pkts;
-    A_UINT16    opcode;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 num_hci_cmd_pkts;
+    u16 opcode;
 } POSTPACK HCI_EVENT_CMD_STATUS;
 
 /* Hardware Error event */
 typedef struct  hci_event_hw_err_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     hw_err_code;
+    u8 event_code;
+    u8 param_len;
+    u8 hw_err_code;
 } POSTPACK HCI_EVENT_HW_ERR;
 
 /* Flush occured event */
 /* Qos Violation event */
 typedef struct  hci_event_handle_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT16    handle;
+    u8 event_code;
+    u8 param_len;
+    u16 handle;
 } POSTPACK HCI_EVENT_FLUSH_OCCRD,
            HCI_EVENT_QOS_VIOLATION;
 
 /* Loopback command event */
 typedef struct hci_loopback_cmd_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     params[252];
+    u8 event_code;
+    u8 param_len;
+    u8 params[252];
 } POSTPACK HCI_EVENT_LOOPBACK_CMD;
 
 /* Data buffer overflow event */
 typedef struct  hci_data_buf_overflow_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     link_type;
+    u8 event_code;
+    u8 param_len;
+    u8 link_type;
 } POSTPACK  HCI_EVENT_DATA_BUF_OVERFLOW;
 
 /* Enhanced Flush complete event */
 typedef struct hci_enhanced_flush_complt_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT16    hdl;
+    u8 event_code;
+    u8 param_len;
+    u16 hdl;
 } POSTPACK  HCI_EVENT_ENHANCED_FLUSH_COMPLT;
 
 /* Channel select event */
 typedef struct  hci_event_chan_select_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     phy_link_hdl;
+    u8 event_code;
+    u8 param_len;
+    u8 phy_link_hdl;
 } POSTPACK HCI_EVENT_CHAN_SELECT;
 
 /* Physical Link Complete event */
 typedef struct  hci_event_phy_link_complete_event_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     phy_link_hdl;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 phy_link_hdl;
 } POSTPACK HCI_EVENT_PHY_LINK_COMPLETE;
 
 /* Logical Link complete event */
 typedef struct hci_event_logical_link_complete_event_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT16    logical_link_hdl;
-    A_UINT8     phy_hdl;
-    A_UINT8     tx_flow_id;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u16 logical_link_hdl;
+    u8 phy_hdl;
+    u8 tx_flow_id;
 } POSTPACK HCI_EVENT_LOGICAL_LINK_COMPLETE_EVENT;
 
 /* Disconnect Logical Link complete event */
 typedef struct hci_event_disconnect_logical_link_event_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT16    logical_link_hdl;
-    A_UINT8     reason;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u16 logical_link_hdl;
+    u8 reason;
 } POSTPACK HCI_EVENT_DISCONNECT_LOGICAL_LINK_EVENT;
 
 /* Disconnect Physical Link complete event */
 typedef struct hci_event_disconnect_phy_link_complete_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     reason;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 phy_link_hdl;
+    u8 reason;
 } POSTPACK HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE;
 
 typedef struct hci_event_physical_link_loss_early_warning_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     phy_hdl;
-    A_UINT8     reason;
+    u8 event_code;
+    u8 param_len;
+    u8 phy_hdl;
+    u8 reason;
 } POSTPACK HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING;
 
 typedef struct hci_event_physical_link_recovery_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     phy_hdl;
+    u8 event_code;
+    u8 param_len;
+    u8 phy_hdl;
 } POSTPACK HCI_EVENT_PHY_LINK_RECOVERY;
 
 
 /* Flow spec modify complete event */
 /* Flush event */
 typedef struct hci_event_status_handle_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT16    handle;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u16 handle;
 } POSTPACK HCI_EVENT_FLOW_SPEC_MODIFY,
            HCI_EVENT_FLUSH;
 
 
 /* Num of completed data blocks event */
 typedef struct hci_event_num_of_compl_data_blks_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT16    num_data_blks;
-    A_UINT8     num_handles;
-    A_UINT8     params[255];
+    u8 event_code;
+    u8 param_len;
+    u16 num_data_blks;
+    u8 num_handles;
+    u8 params[255];
 } POSTPACK HCI_EVENT_NUM_COMPL_DATA_BLKS;
 
 /* Short range mode change complete event */
 typedef struct  hci_srm_cmpl_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     phy_link;
-    A_UINT8     state;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 phy_link;
+    u8 state;
 } POSTPACK HCI_EVENT_SRM_COMPL;
 
 typedef struct hci_event_amp_status_change_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     amp_status;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 amp_status;
 } POSTPACK HCI_EVENT_AMP_STATUS_CHANGE;
 
 /*============== Event definitions end =========================== */
 
 
 typedef struct  local_amp_info_resp_t {
-    A_UINT8     status;
-    A_UINT8     amp_status;
-    A_UINT32    total_bw;           /* kbps */
-    A_UINT32    max_guranteed_bw;   /* kbps */
-    A_UINT32    min_latency;
-    A_UINT32    max_pdu_size;
-    A_UINT8     amp_type;
-    A_UINT16    pal_capabilities;
-    A_UINT16    amp_assoc_len;
-    A_UINT32    max_flush_timeout;  /* in ms */
-    A_UINT32    be_flush_timeout;   /* in ms */
+    u8 status;
+    u8 amp_status;
+    u32 total_bw;           /* kbps */
+    u32 max_guranteed_bw;   /* kbps */
+    u32 min_latency;
+    u32 max_pdu_size;
+    u8 amp_type;
+    u16 pal_capabilities;
+    u16 amp_assoc_len;
+    u32 max_flush_timeout;  /* in ms */
+    u32 be_flush_timeout;   /* in ms */
 } POSTPACK  LOCAL_AMP_INFO;
 
 typedef struct  amp_assoc_cmd_resp_t{
-    A_UINT8     status;
-    A_UINT8     phy_hdl;
-    A_UINT16    amp_assoc_len;
-    A_UINT8     amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
+    u8 status;
+    u8 phy_hdl;
+    u16 amp_assoc_len;
+    u8 amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
 }POSTPACK AMP_ASSOC_CMD_RESP;
 
 
@@ -618,64 +618,64 @@ enum PAL_HCI_CMD_STATUS {
 /* Following are event return parameters.. part of HCI events 
  */
 typedef struct  timeout_read_t {
-    A_UINT8     status;
-    A_UINT16    timeout;
+    u8 status;
+    u16 timeout;
 }POSTPACK TIMEOUT_INFO;
 
 typedef struct  link_supervision_timeout_read_t {
-    A_UINT8     status;
-    A_UINT16    hdl;
-    A_UINT16    timeout;
+    u8 status;
+    u16 hdl;
+    u16 timeout;
 }POSTPACK LINK_SUPERVISION_TIMEOUT_INFO;
 
 typedef struct  status_hdl_t {
-    A_UINT8     status;
-    A_UINT16    hdl;
+    u8 status;
+    u16 hdl;
 }POSTPACK INFO_STATUS_HDL;
 
 typedef struct write_remote_amp_assoc_t{
-    A_UINT8     status;
-    A_UINT8     hdl;
+    u8 status;
+    u8 hdl;
 }POSTPACK WRITE_REMOTE_AMP_ASSOC_INFO;
 
 typedef struct  read_loc_info_t {
-    A_UINT8             status;
+    u8 status;
     LOCATION_DATA_CFG   loc;
 }POSTPACK READ_LOC_INFO;
 
 typedef struct  read_flow_ctrl_mode_t {
-    A_UINT8     status;
-    A_UINT8     mode;
+    u8 status;
+    u8 mode;
 }POSTPACK READ_FLWCTRL_INFO;
 
 typedef struct  read_data_blk_size_t {
-    A_UINT8     status;
-    A_UINT16    max_acl_data_pkt_len;
-    A_UINT16    data_block_len;
-    A_UINT16    total_num_data_blks;
+    u8 status;
+    u16 max_acl_data_pkt_len;
+    u16 data_block_len;
+    u16 total_num_data_blks;
 }POSTPACK READ_DATA_BLK_SIZE_INFO;
 
 /* Read Link quality info */
 typedef struct link_qual_t {
-    A_UINT8     status;
-    A_UINT16    hdl;
-    A_UINT8     link_qual;
+    u8 status;
+    u16 hdl;
+    u8 link_qual;
 } POSTPACK READ_LINK_QUAL_INFO,
             READ_RSSI_INFO;
 
 typedef struct ll_cancel_resp_t {
-    A_UINT8 status;
-    A_UINT8 phy_link_hdl;
-    A_UINT8 tx_flow_spec_id;
+    u8 status;
+    u8 phy_link_hdl;
+    u8 tx_flow_spec_id;
 } POSTPACK LL_CANCEL_RESP;
 
 typedef struct read_local_ver_info_t {
-    A_UINT8     status;
-    A_UINT8     hci_version;
-    A_UINT16    hci_revision;
-    A_UINT8     pal_version;
-    A_UINT16    manf_name;
-    A_UINT16    pal_sub_ver;
+    u8 status;
+    u8 hci_version;
+    u16 hci_revision;
+    u8 pal_version;
+    u16 manf_name;
+    u16 pal_sub_ver;
 } POSTPACK READ_LOCAL_VER_INFO;
 
 
diff --git a/drivers/staging/ath6kl/include/common/athdefs.h b/drivers/staging/ath6kl/include/common/athdefs.h
index b59bfd3..7492248 100644
--- a/drivers/staging/ath6kl/include/common/athdefs.h
+++ b/drivers/staging/ath6kl/include/common/athdefs.h
@@ -31,54 +31,45 @@
 
 /*
  * Generic error codes that can be used by hw, sta, ap, sim, dk
- * and any other environments. Since these are enums, feel free to
- * add any more codes that you need.
+ * and any other environments.
+ * Feel free to add any more non-zero codes that you need.
  */
 
-typedef enum {
-    A_ERROR = -1,               /* Generic error return */
-    A_OK = 0,                   /* success */
-                                /* Following values start at 1 */
-    A_DEVICE_NOT_FOUND,         /* not able to find PCI device */
-    A_NO_MEMORY,                /* not able to allocate memory, not available */
-    A_MEMORY_NOT_AVAIL,         /* memory region is not free for mapping */
-    A_NO_FREE_DESC,             /* no free descriptors available */
-    A_BAD_ADDRESS,              /* address does not match descriptor */
-    A_WIN_DRIVER_ERROR,         /* used in NT_HW version, if problem at init */
-    A_REGS_NOT_MAPPED,          /* registers not correctly mapped */
-    A_EPERM,                    /* Not superuser */
-    A_EACCES,                   /* Access denied */
-    A_ENOENT,                   /* No such entry, search failed, etc. */
-    A_EEXIST,                   /* The object already exists (can't create) */
-    A_EFAULT,                   /* Bad address fault */
-    A_EBUSY,                    /* Object is busy */
-    A_EINVAL,                   /* Invalid parameter */
-    A_EMSGSIZE,                 /* Inappropriate message buffer length */
-    A_ECANCELED,                /* Operation canceled */
-    A_ENOTSUP,                  /* Operation not supported */
-    A_ECOMM,                    /* Communication error on send */
-    A_EPROTO,                   /* Protocol error */
-    A_ENODEV,                   /* No such device */
-    A_EDEVNOTUP,                /* device is not UP */
-    A_NO_RESOURCE,              /* No resources for requested operation */
-    A_HARDWARE,                 /* Hardware failure */
-    A_PENDING,                  /* Asynchronous routine; will send up results la
-ter (typically in callback) */
-    A_EBADCHANNEL,              /* The channel cannot be used */
-    A_DECRYPT_ERROR,            /* Decryption error */
-    A_PHY_ERROR,                /* RX PHY error */
-    A_CONSUMED                  /* Object was consumed */
-} A_STATUS;
-
-#define A_SUCCESS(x)        (x == A_OK)
-#define A_FAILED(x)         (!A_SUCCESS(x))
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
+#define A_ERROR			(-1)	/* Generic error return */
+#define A_DEVICE_NOT_FOUND	1	/* not able to find PCI device */
+#define A_NO_MEMORY		2	/* not able to allocate memory,
+					 * not avail#defineable */
+#define A_MEMORY_NOT_AVAIL	3	/* memory region is not free for
+					 * mapping */
+#define A_NO_FREE_DESC		4	/* no free descriptors available */
+#define A_BAD_ADDRESS		5	/* address does not match descriptor */
+#define A_WIN_DRIVER_ERROR	6	/* used in NT_HW version,
+					 * if problem at init */
+#define A_REGS_NOT_MAPPED	7	/* registers not correctly mapped */
+#define A_EPERM			8	/* Not superuser */
+#define A_EACCES		0	/* Access denied */
+#define A_ENOENT		10	/* No such entry, search failed, etc. */
+#define A_EEXIST		11	/* The object already exists
+					 * (can't create) */
+#define A_EFAULT		12	/* Bad address fault */
+#define A_EBUSY			13	/* Object is busy */
+#define A_EINVAL		14	/* Invalid parameter */
+#define A_EMSGSIZE		15	/* Bad message buffer length */
+#define A_ECANCELED		16	/* Operation canceled */
+#define A_ENOTSUP		17	/* Operation not supported */
+#define A_ECOMM			18	/* Communication error on send */
+#define A_EPROTO		19	/* Protocol error */
+#define A_ENODEV		20	/* No such device */
+#define A_EDEVNOTUP		21	/* device is not UP */
+#define A_NO_RESOURCE		22	/* No resources for
+					 * requested operation */
+#define A_HARDWARE		23	/* Hardware failure */
+#define A_PENDING		24	/* Asynchronous routine; will send up
+					 * results later
+					 * (typically in callback) */
+#define A_EBADCHANNEL		25	/* The channel cannot be used */
+#define A_DECRYPT_ERROR		26	/* Decryption error */
+#define A_PHY_ERROR		27	/* RX PHY error */
+#define A_CONSUMED		28	/* Object was consumed */
 
 #endif /* __ATHDEFS_H__ */
diff --git a/drivers/staging/ath6kl/include/common/bmi_msg.h b/drivers/staging/ath6kl/include/common/bmi_msg.h
index f9687d3..e76624c 100644
--- a/drivers/staging/ath6kl/include/common/bmi_msg.h
+++ b/drivers/staging/ath6kl/include/common/bmi_msg.h
@@ -65,7 +65,7 @@
         /*
          * Semantics: Host is done using BMI
          * Request format:
-         *    A_UINT32      command (BMI_DONE)
+         *    u32 command (BMI_DONE)
          * Response format: none
          */
 
@@ -73,21 +73,21 @@
         /*
          * Semantics: Host reads AR6K memory
          * Request format:
-         *    A_UINT32      command (BMI_READ_MEMORY)
-         *    A_UINT32      address
-         *    A_UINT32      length, at most BMI_DATASZ_MAX
+         *    u32 command (BMI_READ_MEMORY)
+         *    u32 address
+         *    u32 length, at most BMI_DATASZ_MAX
          * Response format:
-         *    A_UINT8       data[length]
+         *    u8 data[length]
          */
 
 #define BMI_WRITE_MEMORY                    3
         /*
          * Semantics: Host writes AR6K memory
          * Request format:
-         *    A_UINT32       command (BMI_WRITE_MEMORY)
-         *    A_UINT32      address
-         *    A_UINT32      length, at most BMI_DATASZ_MAX
-         *    A_UINT8       data[length]
+         *    u32 command (BMI_WRITE_MEMORY)
+         *    u32 address
+         *    u32 length, at most BMI_DATASZ_MAX
+         *    u8 data[length]
          * Response format: none
          */
 
@@ -95,19 +95,19 @@
         /*
          * Semantics: Causes AR6K to execute code
          * Request format:
-         *    A_UINT32      command (BMI_EXECUTE)
-         *    A_UINT32      address
-         *    A_UINT32      parameter
+         *    u32 command (BMI_EXECUTE)
+         *    u32 address
+         *    u32 parameter
          * Response format:
-         *    A_UINT32      return value
+         *    u32 return value
          */
 
 #define BMI_SET_APP_START                   5
         /*
          * Semantics: Set Target application starting address
          * Request format:
-         *    A_UINT32      command (BMI_SET_APP_START)
-         *    A_UINT32      address
+         *    u32 command (BMI_SET_APP_START)
+         *    u32 address
          * Response format: none
          */
 
@@ -115,19 +115,19 @@
         /*
          * Semantics: Read a 32-bit Target SOC register.
          * Request format:
-         *    A_UINT32      command (BMI_READ_REGISTER)
-         *    A_UINT32      address
+         *    u32 command (BMI_READ_REGISTER)
+         *    u32 address
          * Response format: 
-         *    A_UINT32      value
+         *    u32 value
          */
 
 #define BMI_WRITE_SOC_REGISTER              7
         /*
          * Semantics: Write a 32-bit Target SOC register.
          * Request format:
-         *    A_UINT32      command (BMI_WRITE_REGISTER)
-         *    A_UINT32      address
-         *    A_UINT32      value
+         *    u32 command (BMI_WRITE_REGISTER)
+         *    u32 address
+         *    u32 value
          *
          * Response format: none
          */
@@ -137,18 +137,18 @@
         /*
          * Semantics: Fetch the 4-byte Target information
          * Request format:
-         *    A_UINT32      command (BMI_GET_TARGET_ID/INFO)
+         *    u32 command (BMI_GET_TARGET_ID/INFO)
          * Response format1 (old firmware):
-         *    A_UINT32      TargetVersionID
+         *    u32 TargetVersionID
          * Response format2 (newer firmware):
-         *    A_UINT32      TARGET_VERSION_SENTINAL
+         *    u32 TARGET_VERSION_SENTINAL
          *    struct bmi_target_info;
          */
 
 PREPACK struct bmi_target_info {
-    A_UINT32 target_info_byte_count; /* size of this structure */
-    A_UINT32 target_ver;             /* Target Version ID */
-    A_UINT32 target_type;            /* Target type */
+    u32 target_info_byte_count; /* size of this structure */
+    u32 target_ver;             /* Target Version ID */
+    u32 target_type;            /* Target type */
 } POSTPACK;
 #define TARGET_VERSION_SENTINAL 0xffffffff
 #define TARGET_TYPE_AR6001 1
@@ -160,14 +160,14 @@ PREPACK struct bmi_target_info {
         /*
          * Semantics: Install a ROM Patch.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_INSTALL)
-         *    A_UINT32      Target ROM Address
-         *    A_UINT32      Target RAM Address or Value (depending on Target Type)
-         *    A_UINT32      Size, in bytes
-         *    A_UINT32      Activate? 1-->activate;
+         *    u32 command (BMI_ROMPATCH_INSTALL)
+         *    u32 Target ROM Address
+         *    u32 Target RAM Address or Value (depending on Target Type)
+         *    u32 Size, in bytes
+         *    u32 Activate? 1-->activate;
          *                            0-->install but do not activate
          * Response format:
-         *    A_UINT32      PatchID
+         *    u32 PatchID
          */
 
 #define BMI_ROMPATCH_UNINSTALL             10
@@ -175,8 +175,8 @@ PREPACK struct bmi_target_info {
          * Semantics: Uninstall a previously-installed ROM Patch,
          * automatically deactivating, if necessary.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_UNINSTALL)
-         *    A_UINT32      PatchID
+         *    u32 command (BMI_ROMPATCH_UNINSTALL)
+         *    u32 PatchID
          *
          * Response format: none
          */
@@ -185,9 +185,9 @@ PREPACK struct bmi_target_info {
         /*
          * Semantics: Activate a list of previously-installed ROM Patches.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_ACTIVATE)
-         *    A_UINT32      rompatch_count
-         *    A_UINT32      PatchID[rompatch_count]
+         *    u32 command (BMI_ROMPATCH_ACTIVATE)
+         *    u32 rompatch_count
+         *    u32 PatchID[rompatch_count]
          *
          * Response format: none
          */
@@ -196,9 +196,9 @@ PREPACK struct bmi_target_info {
         /*
          * Semantics: Deactivate a list of active ROM Patches.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_DEACTIVATE)
-         *    A_UINT32      rompatch_count
-         *    A_UINT32      PatchID[rompatch_count]
+         *    u32 command (BMI_ROMPATCH_DEACTIVATE)
+         *    u32 rompatch_count
+         *    u32 PatchID[rompatch_count]
          *
          * Response format: none
          */
@@ -213,8 +213,8 @@ PREPACK struct bmi_target_info {
          * output from the compressed input stream.  This BMI
          * command should be followed by a series of 1 or more
          * BMI_LZ_DATA commands.
-         *    A_UINT32      command (BMI_LZ_STREAM_START)
-         *    A_UINT32      address
+         *    u32 command (BMI_LZ_STREAM_START)
+         *    u32 address
          * Note: Not supported on all versions of ROM firmware.
          */
 
@@ -226,10 +226,10 @@ PREPACK struct bmi_target_info {
          * of BMI_LZ_DATA commands are considered part of a single
          * input stream until another BMI_LZ_STREAM_START is issued.
          * Request format:
-         *    A_UINT32      command (BMI_LZ_DATA)
-         *    A_UINT32      length (of compressed data),
+         *    u32 command (BMI_LZ_DATA)
+         *    u32 length (of compressed data),
          *                  at most BMI_DATASZ_MAX
-         *    A_UINT8       CompressedData[length]
+         *    u8 CompressedData[length]
          * Response format: none
          * Note: Not supported on all versions of ROM firmware.
          */
diff --git a/drivers/staging/ath6kl/include/common/btcoexGpio.h b/drivers/staging/ath6kl/include/common/btcoexGpio.h
index bc067f5..9d5a239 100644
--- a/drivers/staging/ath6kl/include/common/btcoexGpio.h
+++ b/drivers/staging/ath6kl/include/common/btcoexGpio.h
@@ -71,8 +71,8 @@
 
 
 
-extern void btcoexDbgPulseWord(A_UINT32 gpioPinMask);
-extern void btcoexDbgPulse(A_UINT32 pin);
+extern void btcoexDbgPulseWord(u32 gpioPinMask);
+extern void btcoexDbgPulse(u32 pin);
 
 #ifdef CONFIG_BTCOEX_ENABLE_GPIO_DEBUG
 #define BTCOEX_DBG_PULSE_WORD(gpioPinMask)  (btcoexDbgPulseWord(gpioPinMask))
diff --git a/drivers/staging/ath6kl/include/common/dbglog.h b/drivers/staging/ath6kl/include/common/dbglog.h
index 382d9a2..3a3d00d 100644
--- a/drivers/staging/ath6kl/include/common/dbglog.h
+++ b/drivers/staging/ath6kl/include/common/dbglog.h
@@ -89,31 +89,31 @@ extern "C" {
 
 PREPACK struct dbglog_buf_s {
     struct dbglog_buf_s *next;
-    A_UINT8             *buffer;
-    A_UINT32             bufsize;
-    A_UINT32             length;
-    A_UINT32             count;
-    A_UINT32             free;
+    u8 *buffer;
+    u32 bufsize;
+    u32 length;
+    u32 count;
+    u32 free;
 } POSTPACK;
 
 PREPACK struct dbglog_hdr_s {
     struct dbglog_buf_s *dbuf;
-    A_UINT32             dropped;
+    u32 dropped;
 } POSTPACK;
 
 PREPACK struct dbglog_config_s {
-    A_UINT32                    cfgvalid; /* Mask with valid config bits */
+    u32 cfgvalid; /* Mask with valid config bits */
     union {
         /* TODO: Take care of endianness */
         struct {
-            A_UINT32            mmask:16; /* Mask of modules with logging on */
-            A_UINT32            rep:1; /* Reporting enabled or not */
-            A_UINT32            tsr:3; /* Time stamp resolution. Def: 1 ms */
-            A_UINT32            size:10; /* Report size in number of messages */
-            A_UINT32            reserved:2;
+            u32 mmask:16; /* Mask of modules with logging on */
+            u32 rep:1; /* Reporting enabled or not */
+            u32 tsr:3; /* Time stamp resolution. Def: 1 ms */
+            u32 size:10; /* Report size in number of messages */
+            u32 reserved:2;
         } dbglog_config;
 
-        A_UINT32                value;
+        u32 value;
     } u;
 } POSTPACK;
 
diff --git a/drivers/staging/ath6kl/include/common/dset_internal.h b/drivers/staging/ath6kl/include/common/dset_internal.h
index 2460f0e..6947533 100644
--- a/drivers/staging/ath6kl/include/common/dset_internal.h
+++ b/drivers/staging/ath6kl/include/common/dset_internal.h
@@ -42,13 +42,13 @@
 typedef PREPACK struct dset_descriptor_s {
   struct dset_descriptor_s  *next;         /* List link. NULL only at the last
                                               descriptor */
-  A_UINT16                   id;           /* Dset ID */
-  A_UINT16                   size;         /* Dset size. */
+  u16 id;           /* Dset ID */
+  u16 size;         /* Dset size. */
   void                      *DataPtr;      /* Pointer to raw data for standard
                                               DataSet or pointer to original
                                               dset_descriptor for patched
                                               DataSet */
-  A_UINT32                   data_type;    /* DSET_TYPE_*, above */
+  u32 data_type;    /* DSET_TYPE_*, above */
 
   void                      *AuxPtr;       /* Additional data that might
                                               needed for data_type. For
diff --git a/drivers/staging/ath6kl/include/common/dsetid.h b/drivers/staging/ath6kl/include/common/dsetid.h
index d08fdeb..090e309 100644
--- a/drivers/staging/ath6kl/include/common/dsetid.h
+++ b/drivers/staging/ath6kl/include/common/dsetid.h
@@ -81,8 +81,8 @@
  * This allows for patches to be stored in flash.
  */
 PREPACK struct patch_s {
-    A_UINT32 *address;
-    A_UINT32  data;
+    u32 *address;
+    u32 data;
 } POSTPACK ;
 
 /*
@@ -92,23 +92,23 @@ PREPACK struct patch_s {
  * patch code.  The "data" in a PATCH_SKIP tells how many
  * bytes of length "patch_s" to skip.
  */
-#define PATCH_SKIP      ((A_UINT32 *)0x00000000)
+#define PATCH_SKIP      ((u32 *)0x00000000)
 
 /*
  * Execute code at the address specified by "data".
  * The address of the patch structure is passed as
  * the one parameter.
  */
-#define PATCH_CODE_ABS  ((A_UINT32 *)0x00000001)
+#define PATCH_CODE_ABS  ((u32 *)0x00000001)
 
 /*
  * Same as PATCH_CODE_ABS, but treat "data" as an
  * offset from the start of the patch word.
  */
-#define PATCH_CODE_REL  ((A_UINT32 *)0x00000002)
+#define PATCH_CODE_REL  ((u32 *)0x00000002)
 
 /* Mark the end of this patch DataSet. */
-#define PATCH_END       ((A_UINT32 *)0xffffffff)
+#define PATCH_END       ((u32 *)0xffffffff)
 
 /*
  * A DataSet which contains a Binary Patch to some other DataSet
diff --git a/drivers/staging/ath6kl/include/common/epping_test.h b/drivers/staging/ath6kl/include/common/epping_test.h
index f8aeb3f..5c40d8a 100644
--- a/drivers/staging/ath6kl/include/common/epping_test.h
+++ b/drivers/staging/ath6kl/include/common/epping_test.h
@@ -30,7 +30,7 @@
 #endif
 
     /* alignment to 4-bytes */
-#define EPPING_ALIGNMENT_PAD  (((sizeof(HTC_FRAME_HDR) + 3) & (~0x3)) - sizeof(HTC_FRAME_HDR))
+#define EPPING_ALIGNMENT_PAD  (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) - sizeof(struct htc_frame_hdr))
 
 #ifndef A_OFFSETOF
 #define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field))
@@ -41,28 +41,28 @@
 #define HCI_RSVD_EXPECTED_PKT_TYPE_RECV_OFFSET  7 
   
 typedef PREPACK struct {    
-    A_UINT8     _HCIRsvd[8];           /* reserved for HCI packet header (GMBOX) testing */
-    A_UINT8     StreamEcho_h;          /* stream no. to echo this packet on (filled by host) */
-    A_UINT8     StreamEchoSent_t;      /* stream no. packet was echoed to (filled by target)
+    u8 _HCIRsvd[8];           /* reserved for HCI packet header (GMBOX) testing */
+    u8 StreamEcho_h;          /* stream no. to echo this packet on (filled by host) */
+    u8 StreamEchoSent_t;      /* stream no. packet was echoed to (filled by target)
                                           When echoed: StreamEchoSent_t == StreamEcho_h */
-    A_UINT8     StreamRecv_t;          /* stream no. that target received this packet on (filled by target) */
-    A_UINT8     StreamNo_h;            /* stream number to send on (filled by host) */   
-    A_UINT8     Magic_h[4];            /* magic number to filter for this packet on the host*/
-    A_UINT8     _rsvd[6];              /* reserved fields that must be set to a "reserved" value
+    u8 StreamRecv_t;          /* stream no. that target received this packet on (filled by target) */
+    u8 StreamNo_h;            /* stream number to send on (filled by host) */
+    u8 Magic_h[4];            /* magic number to filter for this packet on the host*/
+    u8 _rsvd[6];              /* reserved fields that must be set to a "reserved" value
                                           since this packet maps to a 14-byte ethernet frame we want 
                                           to make sure ethertype field is set to something unknown */
                                           
-    A_UINT8     _pad[2];               /* padding for alignment */                      
-    A_UINT8     TimeStamp[8];          /* timestamp of packet (host or target) */
-    A_UINT32    HostContext_h;         /* 4 byte host context, target echos this back */
-    A_UINT32    SeqNo;                 /* sequence number (set by host or target) */   
-    A_UINT16    Cmd_h;                 /* ping command (filled by host) */  
-    A_UINT16    CmdFlags_h;            /* optional flags */
-    A_UINT8     CmdBuffer_h[8];        /* buffer for command (host -> target) */
-    A_UINT8     CmdBuffer_t[8];        /* buffer for command (target -> host) */  
-    A_UINT16    DataLength;            /* length of data */
-    A_UINT16    DataCRC;               /* 16 bit CRC of data */
-    A_UINT16    HeaderCRC;             /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */                       
+    u8 _pad[2];               /* padding for alignment */
+    u8 TimeStamp[8];          /* timestamp of packet (host or target) */
+    u32 HostContext_h;         /* 4 byte host context, target echos this back */
+    u32 SeqNo;                 /* sequence number (set by host or target) */
+    u16 Cmd_h;                 /* ping command (filled by host) */
+    u16 CmdFlags_h;            /* optional flags */
+    u8 CmdBuffer_h[8];        /* buffer for command (host -> target) */
+    u8 CmdBuffer_t[8];        /* buffer for command (target -> host) */
+    u16 DataLength;            /* length of data */
+    u16 DataCRC;               /* 16 bit CRC of data */
+    u16 HeaderCRC;             /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */
 } POSTPACK EPPING_HEADER;
 
 #define EPPING_PING_MAGIC_0               0xAA
@@ -97,9 +97,9 @@ typedef PREPACK struct {
 
     /* test command parameters may be no more than 8 bytes */
 typedef PREPACK struct {    
-    A_UINT16  BurstCnt;       /* number of packets to burst together (for HTC 2.1 testing) */
-    A_UINT16  PacketLength;   /* length of packet to generate including header */      
-    A_UINT16  Flags;          /* flags */
+    u16 BurstCnt;       /* number of packets to burst together (for HTC 2.1 testing) */
+    u16 PacketLength;   /* length of packet to generate including header */
+    u16 Flags;          /* flags */
 
 #define EPPING_CONT_RX_DATA_CRC     (1 << 0)  /* Add CRC to all data */
 #define EPPING_CONT_RX_RANDOM_DATA  (1 << 1)  /* randomize the data pattern */
@@ -107,7 +107,7 @@ typedef PREPACK struct {
 } POSTPACK EPPING_CONT_RX_PARAMS;
 
 #define EPPING_HDR_CRC_OFFSET    A_OFFSETOF(EPPING_HEADER,StreamNo_h)
-#define EPPING_HDR_BYTES_CRC     (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(A_UINT16)))
+#define EPPING_HDR_BYTES_CRC     (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(u16)))
 
 #define HCI_TRANSPORT_STREAM_NUM  16  /* this number is higher than the define WMM AC classes so we
                                          can use this to distinguish packets */
diff --git a/drivers/staging/ath6kl/include/common/gmboxif.h b/drivers/staging/ath6kl/include/common/gmboxif.h
index 4d8d85f..dd9afbd 100644
--- a/drivers/staging/ath6kl/include/common/gmboxif.h
+++ b/drivers/staging/ath6kl/include/common/gmboxif.h
@@ -41,23 +41,23 @@
 
     /* definitions for BT HCI packets */
 typedef PREPACK struct {
-    A_UINT16 Flags_ConnHandle;
-    A_UINT16 Length;
+    u16 Flags_ConnHandle;
+    u16 Length;
 } POSTPACK BT_HCI_ACL_HEADER;
 
 typedef PREPACK struct {
-    A_UINT16 Flags_ConnHandle;
-    A_UINT8  Length;
+    u16 Flags_ConnHandle;
+    u8 Length;
 } POSTPACK BT_HCI_SCO_HEADER;
 
 typedef PREPACK struct {
-    A_UINT16 OpCode;
-    A_UINT8  ParamLength;
+    u16 OpCode;
+    u8 ParamLength;
 } POSTPACK BT_HCI_COMMAND_HEADER;
 
 typedef PREPACK struct {
-    A_UINT8  EventCode;
-    A_UINT8  ParamLength;
+    u8 EventCode;
+    u8 ParamLength;
 } POSTPACK BT_HCI_EVENT_HEADER;
 
 /* MBOX host interrupt signal assignments */
diff --git a/drivers/staging/ath6kl/include/common/htc.h b/drivers/staging/ath6kl/include/common/htc.h
index f96cf7d..b9d4495 100644
--- a/drivers/staging/ath6kl/include/common/htc.h
+++ b/drivers/staging/ath6kl/include/common/htc.h
@@ -31,7 +31,7 @@
 #define A_OFFSETOF(type,field) (unsigned long)(&(((type *)NULL)->field))
 
 #define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \
-        (((A_UINT16)(((A_UINT8 *)(p))[(highbyte)])) << 8 | (A_UINT16)(((A_UINT8 *)(p))[(lowbyte)]))
+        (((u16)(((u8 *)(p))[(highbyte)])) << 8 | (u16)(((u8 *)(p))[(lowbyte)]))
         
 /* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a 
  * structure using only the type and field name.
@@ -43,15 +43,15 @@
 
 #define A_SET_UINT16_FIELD(p,type,field,value) \
 {                                              \
-    ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (A_UINT8)(value);        \
-    ((A_UINT8 *)(p))[A_OFFSETOF(type,field) + 1] = (A_UINT8)((value) >> 8); \
+    ((u8 *)(p))[A_OFFSETOF(type,field)] = (u8)(value);        \
+    ((u8 *)(p))[A_OFFSETOF(type,field) + 1] = (u8)((value) >> 8); \
 }
   
 #define A_GET_UINT8_FIELD(p,type,field) \
-            ((A_UINT8 *)(p))[A_OFFSETOF(type,field)]
+            ((u8 *)(p))[A_OFFSETOF(type,field)]
             
 #define A_SET_UINT8_FIELD(p,type,field,value) \
-    ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (value)
+    ((u8 *)(p))[A_OFFSETOF(type,field)] = (value)
 
 /****** DANGER DANGER ***************
  * 
@@ -66,20 +66,20 @@
  */
 
 /* HTC frame header */
-typedef PREPACK struct _HTC_FRAME_HDR{
+PREPACK struct htc_frame_hdr {
         /* do not remove or re-arrange these fields, these are minimally required
          * to take advantage of 4-byte lookaheads in some hardware implementations */
-    A_UINT8   EndpointID;
-    A_UINT8   Flags;
-    A_UINT16  PayloadLen;       /* length of data (including trailer) that follows the header */
+    u8 EndpointID;
+    u8 Flags;
+    u16 PayloadLen;       /* length of data (including trailer) that follows the header */
     
     /***** end of 4-byte lookahead ****/
     
-    A_UINT8   ControlBytes[2];
+    u8 ControlBytes[2];
     
     /* message payload starts after the header */
     
-} POSTPACK HTC_FRAME_HDR;
+} POSTPACK;
 
 /* frame header flags */
 
@@ -94,9 +94,9 @@ typedef PREPACK struct _HTC_FRAME_HDR{
 #define HTC_FLAGS_RECV_BUNDLE_CNT_MASK (0xF0)  /* bits 7..4  */
 #define HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT 4
 
-#define HTC_HDR_LENGTH  (sizeof(HTC_FRAME_HDR))
+#define HTC_HDR_LENGTH  (sizeof(struct htc_frame_hdr))
 #define HTC_MAX_TRAILER_LENGTH   255
-#define HTC_MAX_PAYLOAD_LENGTH   (4096 - sizeof(HTC_FRAME_HDR))
+#define HTC_MAX_PAYLOAD_LENGTH   (4096 - sizeof(struct htc_frame_hdr))
 
 /* HTC control message IDs */
 
@@ -110,25 +110,25 @@ typedef PREPACK struct _HTC_FRAME_HDR{
          
 /* base message ID header */
 typedef PREPACK struct {
-    A_UINT16 MessageID;    
+    u16 MessageID;
 } POSTPACK HTC_UNKNOWN_MSG;
                                                      
 /* HTC ready message
  * direction : target-to-host  */
 typedef PREPACK struct {
-    A_UINT16  MessageID;    /* ID */
-    A_UINT16  CreditCount;  /* number of credits the target can offer */       
-    A_UINT16  CreditSize;   /* size of each credit */
-    A_UINT8   MaxEndpoints; /* maximum number of endpoints the target has resources for */
-    A_UINT8   _Pad1;
+    u16 MessageID;    /* ID */
+    u16 CreditCount;  /* number of credits the target can offer */
+    u16 CreditSize;   /* size of each credit */
+    u8 MaxEndpoints; /* maximum number of endpoints the target has resources for */
+    u8 _Pad1;
 } POSTPACK HTC_READY_MSG;
 
     /* extended HTC ready message */
 typedef PREPACK struct {
     HTC_READY_MSG   Version2_0_Info;   /* legacy version 2.0 information at the front... */
     /* extended information */
-    A_UINT8         HTCVersion;
-    A_UINT8         MaxMsgsPerHTCBundle;
+    u8 HTCVersion;
+    u8 MaxMsgsPerHTCBundle;
 } POSTPACK HTC_READY_EX_MSG;
 
 #define HTC_VERSION_2P0  0x00  
@@ -139,9 +139,9 @@ typedef PREPACK struct {
 /* connect service
  * direction : host-to-target */
 typedef PREPACK struct {
-    A_UINT16  MessageID;
-    A_UINT16  ServiceID;           /* service ID of the service to connect to */       
-    A_UINT16  ConnectionFlags;     /* connection flags */
+    u16 MessageID;
+    u16 ServiceID;           /* service ID of the service to connect to */
+    u16 ConnectionFlags;     /* connection flags */
 
 #define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2)  /* reduce credit dribbling when 
                                                              the host needs credits */  
@@ -151,8 +151,8 @@ typedef PREPACK struct {
 #define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS     0x2
 #define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY             0x3
                                                              
-    A_UINT8   ServiceMetaLength;   /* length of meta data that follows */
-    A_UINT8   _Pad1;
+    u8 ServiceMetaLength;   /* length of meta data that follows */
+    u8 _Pad1;
     
     /* service-specific meta data starts after the header */
     
@@ -161,29 +161,29 @@ typedef PREPACK struct {
 /* connect response
  * direction : target-to-host */
 typedef PREPACK struct {
-    A_UINT16  MessageID;
-    A_UINT16  ServiceID;            /* service ID that the connection request was made */
-    A_UINT8   Status;               /* service connection status */ 
-    A_UINT8   EndpointID;           /* assigned endpoint ID */
-    A_UINT16  MaxMsgSize;           /* maximum expected message size on this endpoint */
-    A_UINT8   ServiceMetaLength;    /* length of meta data that follows */
-    A_UINT8   _Pad1;               
+    u16 MessageID;
+    u16 ServiceID;            /* service ID that the connection request was made */
+    u8 Status;               /* service connection status */
+    u8 EndpointID;           /* assigned endpoint ID */
+    u16 MaxMsgSize;           /* maximum expected message size on this endpoint */
+    u8 ServiceMetaLength;    /* length of meta data that follows */
+    u8 _Pad1;
     
     /* service-specific meta data starts after the header */
     
 } POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG;
 
 typedef PREPACK struct {
-    A_UINT16  MessageID;
+    u16 MessageID;
     /* currently, no other fields */
 } POSTPACK HTC_SETUP_COMPLETE_MSG;
 
     /* extended setup completion message */
 typedef PREPACK struct {
-    A_UINT16  MessageID;
-    A_UINT32  SetupFlags;
-    A_UINT8   MaxMsgsPerBundledRecv;
-    A_UINT8   Rsvd[3];
+    u16 MessageID;
+    u32 SetupFlags;
+    u8 MaxMsgsPerBundledRecv;
+    u8 Rsvd[3];
 } POSTPACK HTC_SETUP_COMPLETE_EX_MSG;
 
 #define HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV     (1 << 0)
@@ -204,19 +204,19 @@ typedef PREPACK struct {
 #define HTC_RECORD_LOOKAHEAD_BUNDLE 3
 
 typedef PREPACK struct {
-    A_UINT8 RecordID;     /* Record ID */
-    A_UINT8 Length;       /* Length of record */
+    u8 RecordID;     /* Record ID */
+    u8 Length;       /* Length of record */
 } POSTPACK HTC_RECORD_HDR;
 
 typedef PREPACK struct {
-    A_UINT8 EndpointID;     /* Endpoint that owns these credits */
-    A_UINT8 Credits;        /* credits to report since last report */
+    u8 EndpointID;     /* Endpoint that owns these credits */
+    u8 Credits;        /* credits to report since last report */
 } POSTPACK HTC_CREDIT_REPORT;
 
 typedef PREPACK struct {    
-    A_UINT8 PreValid;         /* pre valid guard */
-    A_UINT8 LookAhead[4];     /* 4 byte lookahead */
-    A_UINT8 PostValid;        /* post valid guard */
+    u8 PreValid;         /* pre valid guard */
+    u8 LookAhead[4];     /* 4 byte lookahead */
+    u8 PostValid;        /* post valid guard */
     
    /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes.
     * The PreValid bytes must equal the inverse of the PostValid byte */
@@ -224,7 +224,7 @@ typedef PREPACK struct {
 } POSTPACK HTC_LOOKAHEAD_REPORT;
 
 typedef PREPACK struct {    
-    A_UINT8 LookAhead[4];     /* 4 byte lookahead */    
+    u8 LookAhead[4];     /* 4 byte lookahead */
 } POSTPACK HTC_BUNDLED_LOOKAHEAD_REPORT;
 
 #ifndef ATH_TARGET
diff --git a/drivers/staging/ath6kl/include/common/ini_dset.h b/drivers/staging/ath6kl/include/common/ini_dset.h
index 8cf1af8..8bfc759 100644
--- a/drivers/staging/ath6kl/include/common/ini_dset.h
+++ b/drivers/staging/ath6kl/include/common/ini_dset.h
@@ -74,9 +74,9 @@ typedef enum {
 } WHAL_INI_DATA_ID;
 
 typedef PREPACK struct {
-    A_UINT16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common
-    A_UINT16 offset;
-    A_UINT32 newValue;
+    u16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common
+    u16 offset;
+    u32 newValue;
 } POSTPACK INI_DSET_REG_OVERRIDE;
 
 #endif
diff --git a/drivers/staging/ath6kl/include/common/pkt_log.h b/drivers/staging/ath6kl/include/common/pkt_log.h
index 331cc04..a3719ad 100644
--- a/drivers/staging/ath6kl/include/common/pkt_log.h
+++ b/drivers/staging/ath6kl/include/common/pkt_log.h
@@ -31,11 +31,11 @@ extern "C" {
 /* Pkt log info */
 typedef PREPACK struct pkt_log_t {
     struct info_t {
-        A_UINT16    st;
-        A_UINT16    end;
-        A_UINT16    cur;
+        u16 st;
+        u16 end;
+        u16 cur;
     }info[4096];
-    A_UINT16    last_idx;
+    u16 last_idx;
 }POSTPACK PACKET_LOG;
 
 
diff --git a/drivers/staging/ath6kl/include/common/regdump.h b/drivers/staging/ath6kl/include/common/regdump.h
index ff79b48..aa64821 100644
--- a/drivers/staging/ath6kl/include/common/regdump.h
+++ b/drivers/staging/ath6kl/include/common/regdump.h
@@ -42,10 +42,10 @@
  * the diagnostic window.
  */
 PREPACK struct register_dump_s {
-    A_UINT32 target_id;               /* Target ID */
-    A_UINT32 assline;                 /* Line number (if assertion failure) */
-    A_UINT32 pc;                      /* Program Counter at time of exception */
-    A_UINT32 badvaddr;                /* Virtual address causing exception */
+    u32 target_id;               /* Target ID */
+    u32 assline;                 /* Line number (if assertion failure) */
+    u32 pc;                      /* Program Counter at time of exception */
+    u32 badvaddr;                /* Virtual address causing exception */
     CPU_exception_frame_t exc_frame;  /* CPU-specific exception info */
 
     /* Could copy top of stack here, too.... */
diff --git a/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h b/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h
index c6844d6..4904040 100644
--- a/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h
+++ b/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h
@@ -124,12 +124,12 @@ enum searchType {
  * instance of table).
  */
 typedef PREPACK struct dbMasterTable_t {    /* Hold ptrs to Table data structures */
-    A_UCHAR     numOfEntries;
-    A_CHAR      entrySize;      /* Entry size per table row */
-    A_CHAR      searchType;     /* Index based access or key based */
-    A_CHAR      reserved[3];    /* for alignment */
-    A_UINT16    tableSize;      /* Size of this table */
-    A_CHAR      *dataPtr;       /* Ptr to the actual Table */
+    u8     numOfEntries;
+    char entrySize;      /* Entry size per table row */
+    char searchType;     /* Index based access or key based */
+    char reserved[3];    /* for alignment */
+    u16 tableSize;      /* Size of this table */
+    char *dataPtr;       /* Ptr to the actual Table */
 } POSTPACK dbMasterTable;    /* Master table - table of tables */
 
 
@@ -145,22 +145,22 @@ typedef PREPACK struct dbMasterTable_t {    /* Hold ptrs to Table data structure
 #define BMZERO {0,0}    /* BMLEN zeros */
 
 #define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh) \
-      {((((_fa >= 0) && (_fa < 32)) ? (((A_UINT32) 1) << _fa) : 0) | \
-    (((_fb >= 0) && (_fb < 32)) ? (((A_UINT32) 1) << _fb) : 0) | \
-    (((_fc >= 0) && (_fc < 32)) ? (((A_UINT32) 1) << _fc) : 0) | \
-    (((_fd >= 0) && (_fd < 32)) ? (((A_UINT32) 1) << _fd) : 0) | \
-    (((_fe >= 0) && (_fe < 32)) ? (((A_UINT32) 1) << _fe) : 0) | \
-    (((_ff >= 0) && (_ff < 32)) ? (((A_UINT32) 1) << _ff) : 0) | \
-    (((_fg >= 0) && (_fg < 32)) ? (((A_UINT32) 1) << _fg) : 0) | \
-    (((_fh >= 0) && (_fh < 32)) ? (((A_UINT32) 1) << _fh) : 0)), \
-       ((((_fa > 31) && (_fa < 64)) ? (((A_UINT32) 1) << (_fa - 32)) : 0) | \
-        (((_fb > 31) && (_fb < 64)) ? (((A_UINT32) 1) << (_fb - 32)) : 0) | \
-        (((_fc > 31) && (_fc < 64)) ? (((A_UINT32) 1) << (_fc - 32)) : 0) | \
-        (((_fd > 31) && (_fd < 64)) ? (((A_UINT32) 1) << (_fd - 32)) : 0) | \
-        (((_fe > 31) && (_fe < 64)) ? (((A_UINT32) 1) << (_fe - 32)) : 0) | \
-        (((_ff > 31) && (_ff < 64)) ? (((A_UINT32) 1) << (_ff - 32)) : 0) | \
-        (((_fg > 31) && (_fg < 64)) ? (((A_UINT32) 1) << (_fg - 32)) : 0) | \
-        (((_fh > 31) && (_fh < 64)) ? (((A_UINT32) 1) << (_fh - 32)) : 0))}
+      {((((_fa >= 0) && (_fa < 32)) ? (((u32) 1) << _fa) : 0) | \
+    (((_fb >= 0) && (_fb < 32)) ? (((u32) 1) << _fb) : 0) | \
+    (((_fc >= 0) && (_fc < 32)) ? (((u32) 1) << _fc) : 0) | \
+    (((_fd >= 0) && (_fd < 32)) ? (((u32) 1) << _fd) : 0) | \
+    (((_fe >= 0) && (_fe < 32)) ? (((u32) 1) << _fe) : 0) | \
+    (((_ff >= 0) && (_ff < 32)) ? (((u32) 1) << _ff) : 0) | \
+    (((_fg >= 0) && (_fg < 32)) ? (((u32) 1) << _fg) : 0) | \
+    (((_fh >= 0) && (_fh < 32)) ? (((u32) 1) << _fh) : 0)), \
+       ((((_fa > 31) && (_fa < 64)) ? (((u32) 1) << (_fa - 32)) : 0) | \
+        (((_fb > 31) && (_fb < 64)) ? (((u32) 1) << (_fb - 32)) : 0) | \
+        (((_fc > 31) && (_fc < 64)) ? (((u32) 1) << (_fc - 32)) : 0) | \
+        (((_fd > 31) && (_fd < 64)) ? (((u32) 1) << (_fd - 32)) : 0) | \
+        (((_fe > 31) && (_fe < 64)) ? (((u32) 1) << (_fe - 32)) : 0) | \
+        (((_ff > 31) && (_ff < 64)) ? (((u32) 1) << (_ff - 32)) : 0) | \
+        (((_fg > 31) && (_fg < 64)) ? (((u32) 1) << (_fg - 32)) : 0) | \
+        (((_fh > 31) && (_fh < 64)) ? (((u32) 1) << (_fh - 32)) : 0))}
 
 
 /*
@@ -169,12 +169,12 @@ typedef PREPACK struct dbMasterTable_t {    /* Hold ptrs to Table data structure
  */
 
 typedef PREPACK struct reg_dmn_pair_mapping {
-    A_UINT16 regDmnEnum;    /* 16 bit reg domain pair */
-    A_UINT16 regDmn5GHz;    /* 5GHz reg domain */
-    A_UINT16 regDmn2GHz;    /* 2GHz reg domain */
-    A_UINT8  flags5GHz;     /* Requirements flags (AdHoc disallow etc) */
-    A_UINT8  flags2GHz;     /* Requirements flags (AdHoc disallow etc) */
-    A_UINT32 pscanMask;     /* Passive Scan flags which can override unitary domain passive scan
+    u16 regDmnEnum;    /* 16 bit reg domain pair */
+    u16 regDmn5GHz;    /* 5GHz reg domain */
+    u16 regDmn2GHz;    /* 2GHz reg domain */
+    u8 flags5GHz;     /* Requirements flags (AdHoc disallow etc) */
+    u8 flags2GHz;     /* Requirements flags (AdHoc disallow etc) */
+    u32 pscanMask;     /* Passive Scan flags which can override unitary domain passive scan
                                    flags.  This value is used as a mask on the unitary flags*/
 } POSTPACK REG_DMN_PAIR_MAPPING;
 
@@ -188,10 +188,10 @@ typedef PREPACK struct reg_dmn_pair_mapping {
 #define MCS_HT40_G_NO  (0 << 3)
 
 typedef PREPACK struct {
-    A_UINT16    countryCode;       
-    A_UINT16    regDmnEnum;
-    A_CHAR      isoName[3];
-    A_CHAR      allowMode;  /* what mode is allowed - bit 0: OFDM; bit 1: MCS_HT20; bit 2: MCS_HT40_A; bit 3: MCS_HT40_G */
+    u16 countryCode;
+    u16 regDmnEnum;
+    char isoName[3];
+    char allowMode;  /* what mode is allowed - bit 0: OFDM; bit 1: MCS_HT20; bit 2: MCS_HT40_A; bit 3: MCS_HT40_G */
 } POSTPACK COUNTRY_CODE_TO_ENUM_RD;
 
 /* lower 16 bits of ht40ChanMask */
@@ -209,29 +209,29 @@ typedef PREPACK struct {
 #define FREQ_QUARTER_RATE   0x20000
 
 typedef PREPACK struct RegDmnFreqBand {
-    A_UINT16    lowChannel;     /* Low channel center in MHz */
-    A_UINT16    highChannel;    /* High Channel center in MHz */
-    A_UINT8     power;          /* Max power (dBm) for channel range */
-    A_UINT8     channelSep;     /* Channel separation within the band */
-    A_UINT8     useDfs;         /* Use DFS in the RegDomain if corresponding bit is set */
-    A_UINT8     mode;           /* Mode of operation */
-    A_UINT32    usePassScan;    /* Use Passive Scan in the RegDomain if corresponding bit is set */
-    A_UINT32    ht40ChanMask;   /* lower 16 bits: indicate which frequencies in the block is HT40 capable 
+    u16 lowChannel;     /* Low channel center in MHz */
+    u16 highChannel;    /* High Channel center in MHz */
+    u8 power;          /* Max power (dBm) for channel range */
+    u8 channelSep;     /* Channel separation within the band */
+    u8 useDfs;         /* Use DFS in the RegDomain if corresponding bit is set */
+    u8 mode;           /* Mode of operation */
+    u32 usePassScan;    /* Use Passive Scan in the RegDomain if corresponding bit is set */
+    u32 ht40ChanMask;   /* lower 16 bits: indicate which frequencies in the block is HT40 capable
                                    upper 16 bits: what rate (half/quarter) the channel is  */
 } POSTPACK REG_DMN_FREQ_BAND;
 
 
 
 typedef PREPACK struct regDomain {
-    A_UINT16    regDmnEnum;     /* value from EnumRd table */
-    A_UINT8     rdCTL;
-    A_UINT8     maxAntGain;
-    A_UINT8     dfsMask;        /* DFS bitmask for 5Ghz tables */
-    A_UINT8     flags;          /* Requirement flags (AdHoc disallow etc) */
-    A_UINT16    reserved;       /* for alignment */
-    A_UINT32    pscan;          /* Bitmask for passive scan */
-    A_UINT32    chan11a[BMLEN]; /* 64 bit bitmask for channel/band selection */
-    A_UINT32    chan11bg[BMLEN];/* 64 bit bitmask for channel/band selection */
+    u16 regDmnEnum;     /* value from EnumRd table */
+    u8 rdCTL;
+    u8 maxAntGain;
+    u8 dfsMask;        /* DFS bitmask for 5Ghz tables */
+    u8 flags;          /* Requirement flags (AdHoc disallow etc) */
+    u16 reserved;       /* for alignment */
+    u32 pscan;          /* Bitmask for passive scan */
+    u32 chan11a[BMLEN]; /* 64 bit bitmask for channel/band selection */
+    u32 chan11bg[BMLEN];/* 64 bit bitmask for channel/band selection */
 } POSTPACK REG_DOMAIN;
 
 #endif /* __REG_DBSCHEMA_H__ */
diff --git a/drivers/staging/ath6kl/include/common/targaddrs.h b/drivers/staging/ath6kl/include/common/targaddrs.h
index e8cf703..794ae21 100644
--- a/drivers/staging/ath6kl/include/common/targaddrs.h
+++ b/drivers/staging/ath6kl/include/common/targaddrs.h
@@ -83,13 +83,13 @@ PREPACK struct host_interest_s {
      * Pointer to application-defined area, if any.
      * Set by Target application during startup.
      */
-    A_UINT32               hi_app_host_interest;                      /* 0x00 */
+    u32 hi_app_host_interest;                      /* 0x00 */
 
     /* Pointer to register dump area, valid after Target crash. */
-    A_UINT32               hi_failure_state;                          /* 0x04 */
+    u32 hi_failure_state;                          /* 0x04 */
 
     /* Pointer to debug logging header */
-    A_UINT32               hi_dbglog_hdr;                             /* 0x08 */
+    u32 hi_dbglog_hdr;                             /* 0x08 */
 
     /* Indicates whether or not flash is present on Target.
      * NB: flash_is_present indicator is here not just
@@ -99,36 +99,36 @@ PREPACK struct host_interest_s {
      * so that it doesn't get reinitialized with the rest
      * of data.
      */
-    A_UINT32               hi_flash_is_present;                       /* 0x0c */
+    u32 hi_flash_is_present;                       /* 0x0c */
 
     /*
      * General-purpose flag bits, similar to AR6000_OPTION_* flags.
      * Can be used by application rather than by OS.
      */
-    A_UINT32               hi_option_flag;                            /* 0x10 */
+    u32 hi_option_flag;                            /* 0x10 */
 
     /*
      * Boolean that determines whether or not to
      * display messages on the serial port.
      */
-    A_UINT32               hi_serial_enable;                          /* 0x14 */
+    u32 hi_serial_enable;                          /* 0x14 */
 
     /* Start address of Flash DataSet index, if any */
-    A_UINT32               hi_dset_list_head;                         /* 0x18 */
+    u32 hi_dset_list_head;                         /* 0x18 */
 
     /* Override Target application start address */
-    A_UINT32               hi_app_start;                              /* 0x1c */
+    u32 hi_app_start;                              /* 0x1c */
 
     /* Clock and voltage tuning */
-    A_UINT32               hi_skip_clock_init;                        /* 0x20 */
-    A_UINT32               hi_core_clock_setting;                     /* 0x24 */
-    A_UINT32               hi_cpu_clock_setting;                      /* 0x28 */
-    A_UINT32               hi_system_sleep_setting;                   /* 0x2c */
-    A_UINT32               hi_xtal_control_setting;                   /* 0x30 */
-    A_UINT32               hi_pll_ctrl_setting_24ghz;                 /* 0x34 */
-    A_UINT32               hi_pll_ctrl_setting_5ghz;                  /* 0x38 */
-    A_UINT32               hi_ref_voltage_trim_setting;               /* 0x3c */
-    A_UINT32               hi_clock_info;                             /* 0x40 */
+    u32 hi_skip_clock_init;                        /* 0x20 */
+    u32 hi_core_clock_setting;                     /* 0x24 */
+    u32 hi_cpu_clock_setting;                      /* 0x28 */
+    u32 hi_system_sleep_setting;                   /* 0x2c */
+    u32 hi_xtal_control_setting;                   /* 0x30 */
+    u32 hi_pll_ctrl_setting_24ghz;                 /* 0x34 */
+    u32 hi_pll_ctrl_setting_5ghz;                  /* 0x38 */
+    u32 hi_ref_voltage_trim_setting;               /* 0x3c */
+    u32 hi_clock_info;                             /* 0x40 */
 
     /*
      * Flash configuration overrides, used only
@@ -136,49 +136,49 @@ PREPACK struct host_interest_s {
      * (When using flash, modify the global variables
      * with equivalent names.)
      */
-    A_UINT32               hi_bank0_addr_value;                       /* 0x44 */
-    A_UINT32               hi_bank0_read_value;                       /* 0x48 */
-    A_UINT32               hi_bank0_write_value;                      /* 0x4c */
-    A_UINT32               hi_bank0_config_value;                     /* 0x50 */
+    u32 hi_bank0_addr_value;                       /* 0x44 */
+    u32 hi_bank0_read_value;                       /* 0x48 */
+    u32 hi_bank0_write_value;                      /* 0x4c */
+    u32 hi_bank0_config_value;                     /* 0x50 */
 
     /* Pointer to Board Data  */
-    A_UINT32               hi_board_data;                             /* 0x54 */
-    A_UINT32               hi_board_data_initialized;                 /* 0x58 */
+    u32 hi_board_data;                             /* 0x54 */
+    u32 hi_board_data_initialized;                 /* 0x58 */
 
-    A_UINT32               hi_dset_RAM_index_table;                   /* 0x5c */
+    u32 hi_dset_RAM_index_table;                   /* 0x5c */
 
-    A_UINT32               hi_desired_baud_rate;                      /* 0x60 */
-    A_UINT32               hi_dbglog_config;                          /* 0x64 */
-    A_UINT32               hi_end_RAM_reserve_sz;                     /* 0x68 */
-    A_UINT32               hi_mbox_io_block_sz;                       /* 0x6c */
+    u32 hi_desired_baud_rate;                      /* 0x60 */
+    u32 hi_dbglog_config;                          /* 0x64 */
+    u32 hi_end_RAM_reserve_sz;                     /* 0x68 */
+    u32 hi_mbox_io_block_sz;                       /* 0x6c */
 
-    A_UINT32               hi_num_bpatch_streams;                     /* 0x70 -- unused */
-    A_UINT32               hi_mbox_isr_yield_limit;                   /* 0x74 */
+    u32 hi_num_bpatch_streams;                     /* 0x70 -- unused */
+    u32 hi_mbox_isr_yield_limit;                   /* 0x74 */
 
-    A_UINT32               hi_refclk_hz;                              /* 0x78 */
-    A_UINT32               hi_ext_clk_detected;                       /* 0x7c */
-    A_UINT32               hi_dbg_uart_txpin;                         /* 0x80 */
-    A_UINT32               hi_dbg_uart_rxpin;                         /* 0x84 */
-    A_UINT32               hi_hci_uart_baud;                          /* 0x88 */
-    A_UINT32               hi_hci_uart_pin_assignments;               /* 0x8C */
+    u32 hi_refclk_hz;                              /* 0x78 */
+    u32 hi_ext_clk_detected;                       /* 0x7c */
+    u32 hi_dbg_uart_txpin;                         /* 0x80 */
+    u32 hi_dbg_uart_rxpin;                         /* 0x84 */
+    u32 hi_hci_uart_baud;                          /* 0x88 */
+    u32 hi_hci_uart_pin_assignments;               /* 0x8C */
         /* NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts pin */
-    A_UINT32               hi_hci_uart_baud_scale_val;                /* 0x90 */
-    A_UINT32               hi_hci_uart_baud_step_val;                 /* 0x94 */
+    u32 hi_hci_uart_baud_scale_val;                /* 0x90 */
+    u32 hi_hci_uart_baud_step_val;                 /* 0x94 */
 
-    A_UINT32               hi_allocram_start;                         /* 0x98 */
-    A_UINT32               hi_allocram_sz;                            /* 0x9c */
-    A_UINT32               hi_hci_bridge_flags;                       /* 0xa0 */
-    A_UINT32               hi_hci_uart_support_pins;                  /* 0xa4 */
+    u32 hi_allocram_start;                         /* 0x98 */
+    u32 hi_allocram_sz;                            /* 0x9c */
+    u32 hi_hci_bridge_flags;                       /* 0xa0 */
+    u32 hi_hci_uart_support_pins;                  /* 0xa4 */
         /* NOTE: byte [0] = RESET pin (bit 7 is polarity), bytes[1]..bytes[3] are for future use */
-    A_UINT32               hi_hci_uart_pwr_mgmt_params;               /* 0xa8 */
+    u32 hi_hci_uart_pwr_mgmt_params;               /* 0xa8 */
         /* 0xa8 - [0]: 1 = enable, 0 = disable
          *        [1]: 0 = UART FC active low, 1 = UART FC active high
          * 0xa9 - [7:0]: wakeup timeout in ms
          * 0xaa, 0xab - [15:0]: idle timeout in ms
          */       
     /* Pointer to extended board Data  */
-    A_UINT32               hi_board_ext_data;                         /* 0xac */
-    A_UINT32               hi_board_ext_data_initialized;             /* 0xb0 */
+    u32 hi_board_ext_data;                         /* 0xac */
+    u32 hi_board_ext_data_initialized;             /* 0xb0 */
 } POSTPACK;
 
 /* Bits defined in hi_option_flag */
@@ -207,10 +207,10 @@ PREPACK struct host_interest_s {
  * Example: target_addr = AR6002_HOST_INTEREST_ITEM_ADDRESS(hi_board_data);
  */
 #define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \
-    (A_UINT32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
+    (u32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
 
 #define AR6003_HOST_INTEREST_ITEM_ADDRESS(item) \
-    (A_UINT32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item)))
+    (u32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item)))
 
 #define HOST_INTEREST_DBGLOG_IS_ENABLED() \
         (!(HOST_INTEREST->hi_option_flag & HI_OPTION_DISABLE_DBGLOG))
@@ -233,7 +233,7 @@ PREPACK struct host_interest_s {
 #define AR6003_BOARD_EXT_DATA_ADDRESS     0x57E600
 
 
-/* # of A_UINT32 entries in targregs, used by DIAG_FETCH_TARG_REGS */
+/* # of u32 entries in targregs, used by DIAG_FETCH_TARG_REGS */
 #define AR6003_FETCH_TARG_REGS_COUNT 64
 
 #endif /* !__ASSEMBLER__ */
diff --git a/drivers/staging/ath6kl/include/common/testcmd.h b/drivers/staging/ath6kl/include/common/testcmd.h
index d6616f0..9ca1f2a 100644
--- a/drivers/staging/ath6kl/include/common/testcmd.h
+++ b/drivers/staging/ath6kl/include/common/testcmd.h
@@ -82,20 +82,20 @@ typedef enum {
 } TCMD_WLAN_MODE;
 
 typedef PREPACK struct {
-    A_UINT32                testCmdId;
-    A_UINT32                mode;
-    A_UINT32                freq;
-    A_UINT32                dataRate;
-    A_INT32                 txPwr;
-    A_UINT32                antenna;
-    A_UINT32                enANI;
-    A_UINT32                scramblerOff;
-    A_UINT32                aifsn;
-    A_UINT16                pktSz;
-    A_UINT16                txPattern;
-    A_UINT32                shortGuard;
-    A_UINT32                numPackets;
-    A_UINT32                wlanMode;
+    u32 testCmdId;
+    u32 mode;
+    u32 freq;
+    u32 dataRate;
+    s32 txPwr;
+    u32 antenna;
+    u32 enANI;
+    u32 scramblerOff;
+    u32 aifsn;
+    u16 pktSz;
+    u16 txPattern;
+    u32 shortGuard;
+    u32 numPackets;
+    u32 wlanMode;
 } POSTPACK TCMD_CONT_TX;
 
 #define TCMD_TXPATTERN_ZERONE                 0x1
@@ -124,29 +124,29 @@ typedef enum {
 } TCMD_CONT_RX_ACT;
 
 typedef PREPACK struct {
-    A_UINT32         testCmdId;
-    A_UINT32        act;
-    A_UINT32        enANI;
+    u32 testCmdId;
+    u32 act;
+    u32 enANI;
     PREPACK union {
         struct PREPACK TCMD_CONT_RX_PARA {
-            A_UINT32    freq;
-            A_UINT32    antenna;
-            A_UINT32    wlanMode;
+            u32 freq;
+            u32 antenna;
+            u32 wlanMode;
         } POSTPACK para;
         struct PREPACK TCMD_CONT_RX_REPORT {
-            A_UINT32    totalPkt;
-            A_INT32     rssiInDBm;
-            A_UINT32    crcErrPkt;
-            A_UINT32    secErrPkt;
-            A_UINT16    rateCnt[TCMD_MAX_RATES];
-            A_UINT16    rateCntShortGuard[TCMD_MAX_RATES];
+            u32 totalPkt;
+            s32 rssiInDBm;
+            u32 crcErrPkt;
+            u32 secErrPkt;
+            u16 rateCnt[TCMD_MAX_RATES];
+            u16 rateCntShortGuard[TCMD_MAX_RATES];
         } POSTPACK report;
         struct PREPACK TCMD_CONT_RX_MAC {
-            A_UCHAR    addr[ATH_MAC_LEN];
+            u8    addr[ATH_MAC_LEN];
         } POSTPACK mac;
         struct PREPACK TCMD_CONT_RX_ANT_SWITCH_TABLE {
-            A_UINT32                antswitch1;
-            A_UINT32                antswitch2;
+            u32 antswitch1;
+            u32 antswitch2;
         }POSTPACK antswitchtable;
     } POSTPACK u;
 } POSTPACK TCMD_CONT_RX;
@@ -162,8 +162,8 @@ typedef enum {
 } TCMD_PM_MODE;
 
 typedef PREPACK struct {
-    A_UINT32  testCmdId;
-    A_UINT32  mode;
+    u32 testCmdId;
+    u32 mode;
 } POSTPACK TCMD_PM;
 
 typedef enum {
diff --git a/drivers/staging/ath6kl/include/common/wlan_dset.h b/drivers/staging/ath6kl/include/common/wlan_dset.h
index 864a60c..e775b25 100644
--- a/drivers/staging/ath6kl/include/common/wlan_dset.h
+++ b/drivers/staging/ath6kl/include/common/wlan_dset.h
@@ -25,9 +25,9 @@
 
 typedef PREPACK struct wow_config_dset {
 
-    A_UINT8 valid_dset;
-    A_UINT8 gpio_enable;
-    A_UINT16 gpio_pin;
+    u8 valid_dset;
+    u8 gpio_enable;
+    u16 gpio_pin;
 } POSTPACK WOW_CONFIG_DSET;
 
 #endif
diff --git a/drivers/staging/ath6kl/include/common/wmi.h b/drivers/staging/ath6kl/include/common/wmi.h
index c75d310..c645af3 100644
--- a/drivers/staging/ath6kl/include/common/wmi.h
+++ b/drivers/staging/ath6kl/include/common/wmi.h
@@ -70,24 +70,24 @@ extern "C" {
 #endif
 
 PREPACK struct host_app_area_s {
-    A_UINT32 wmi_protocol_ver;
+    u32 wmi_protocol_ver;
 } POSTPACK;
 
 /*
  * Data Path
  */
 typedef PREPACK struct {
-    A_UINT8     dstMac[ATH_MAC_LEN];
-    A_UINT8     srcMac[ATH_MAC_LEN];
-    A_UINT16    typeOrLen;
+    u8 dstMac[ATH_MAC_LEN];
+    u8 srcMac[ATH_MAC_LEN];
+    u16 typeOrLen;
 } POSTPACK ATH_MAC_HDR;
 
 typedef PREPACK struct {
-    A_UINT8     dsap;
-    A_UINT8     ssap;
-    A_UINT8     cntl;
-    A_UINT8     orgCode[3];
-    A_UINT16    etherType;
+    u8 dsap;
+    u8 ssap;
+    u8 cntl;
+    u8 orgCode[3];
+    u16 etherType;
 } POSTPACK ATH_LLC_SNAP_HDR;
 
 typedef enum {
@@ -160,8 +160,8 @@ typedef enum {
 #define WMI_DATA_HDR_SET_META(h, _v)    ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_META_MASK << WMI_DATA_HDR_META_SHIFT)) | ((_v) << WMI_DATA_HDR_META_SHIFT))
 
 typedef PREPACK struct {
-    A_INT8      rssi;
-    A_UINT8     info;               /* usage of 'info' field(8-bit):
+    s8 rssi;
+    u8 info;               /* usage of 'info' field(8-bit):
                                      *  b1:b0       - WMI_MSG_TYPE
                                      *  b4:b3:b2    - UP(tid)
                                      *  b5          - Used in AP mode. More-data in tx dir, PS in rx.
@@ -170,12 +170,12 @@ typedef PREPACK struct {
                                      *                 ACL data(2)
                                      */
 
-    A_UINT16    info2;              /* usage of 'info2' field(16-bit):
+    u16 info2;              /* usage of 'info2' field(16-bit):
                                      * b11:b0       - seq_no
                                      * b12          - A-MSDU?
                                      * b15:b13      - META_DATA_VERSION 0 - 7
                                      */
-    A_UINT16    reserved;
+    u16 reserved;
 } POSTPACK WMI_DATA_HDR;
 
 /*
@@ -195,17 +195,17 @@ typedef PREPACK struct {
 #endif
 
 typedef PREPACK struct {
-    A_UINT8     pktID;           /* The packet ID to identify the tx request */
-    A_UINT8     ratePolicyID;    /* The rate policy to be used for the tx of this frame */
+    u8 pktID;           /* The packet ID to identify the tx request */
+    u8 ratePolicyID;    /* The rate policy to be used for the tx of this frame */
 } POSTPACK WMI_TX_META_V1;
 
 
 #define WMI_CSUM_DIR_TX (0x1)
 #define TX_CSUM_CALC_FILL (0x1)
 typedef PREPACK struct {
-    A_UINT8    csumStart;       /*Offset from start of the WMI header for csum calculation to begin */
-    A_UINT8    csumDest;        /*Offset from start of WMI header where final csum goes*/
-    A_UINT8     csumFlags;    /*number of bytes over which csum is calculated*/
+    u8 csumStart;       /*Offset from start of the WMI header for csum calculation to begin */
+    u8 csumDest;        /*Offset from start of WMI header where final csum goes*/
+    u8 csumFlags;    /*number of bytes over which csum is calculated*/
 } POSTPACK WMI_TX_META_V2;
 
 
@@ -242,17 +242,17 @@ typedef PREPACK struct {
 #endif
 
 typedef PREPACK struct {
-    A_UINT8     status; /* one of WMI_RX_STATUS_... */
-    A_UINT8     rix;    /* rate index mapped to rate at which this packet was received. */
-    A_UINT8     rssi;   /* rssi of packet */
-    A_UINT8     channel;/* rf channel during packet reception */
-    A_UINT16    flags;  /* a combination of WMI_RX_FLAGS_... */
+    u8 status; /* one of WMI_RX_STATUS_... */
+    u8 rix;    /* rate index mapped to rate at which this packet was received. */
+    u8 rssi;   /* rssi of packet */
+    u8 channel;/* rf channel during packet reception */
+    u16 flags;  /* a combination of WMI_RX_FLAGS_... */
 } POSTPACK WMI_RX_META_V1;
 
 #define RX_CSUM_VALID_FLAG (0x1)
 typedef PREPACK struct {
-    A_UINT16    csum;
-    A_UINT8     csumFlags;/* bit 0 set -partial csum valid
+    u16 csum;
+    u8 csumFlags;/* bit 0 set -partial csum valid
                              bit 1 set -test mode */
 } POSTPACK WMI_RX_META_V2;
 
@@ -264,15 +264,15 @@ typedef PREPACK struct {
  * Control Path
  */
 typedef PREPACK struct {
-    A_UINT16    commandId;
+    u16 commandId;
 /*
  * info1 - 16 bits
  * b03:b00 - id
  * b15:b04 - unused
  */
-    A_UINT16    info1;
+    u16 info1;
 
-    A_UINT16    reserved;      /* For alignment */
+    u16 reserved;      /* For alignment */
 } POSTPACK WMI_CMD_HDR;        /* used for commands and events */
 
 /*
@@ -422,17 +422,24 @@ typedef enum {
     WMI_AP_SET_11BG_RATESET_CMDID,
     WMI_SET_PMK_CMDID,
     WMI_MCAST_FILTER_CMDID,
-	/* COEX CMDID AR6003*/
-	WMI_SET_BTCOEX_FE_ANT_CMDID,
-	WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
-	WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
-	WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
-	WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
-	WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
-	WMI_SET_BTCOEX_DEBUG_CMDID,
-	WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
-	WMI_GET_BTCOEX_STATS_CMDID,
-	WMI_GET_BTCOEX_CONFIG_CMDID,
+    /* COEX CMDID AR6003*/
+    WMI_SET_BTCOEX_FE_ANT_CMDID,
+    WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
+    WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
+    WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
+    WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
+    WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
+    WMI_SET_BTCOEX_DEBUG_CMDID,
+    WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
+    WMI_GET_BTCOEX_STATS_CMDID,
+    WMI_GET_BTCOEX_CONFIG_CMDID,
+    WMI_GET_PMK_CMDID,
+    WMI_SET_PASSPHRASE_CMDID,
+    WMI_ENABLE_WAC_CMDID,
+    WMI_WAC_SCAN_REPLY_CMDID,
+    WMI_WAC_CTRL_REQ_CMDID,
+    WMI_SET_DIV_PARAMS_CMDID,
+    WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
 } WMI_COMMAND_ID;
 
 /*
@@ -522,34 +529,41 @@ typedef enum {
 #define DEFAULT_CONNECT_CTRL_FLAGS    (CONNECT_CSA_FOLLOW_BSS)
 
 typedef PREPACK struct {
-    A_UINT8     networkType;
-    A_UINT8     dot11AuthMode;
-    A_UINT8     authMode;
-    A_UINT8     pairwiseCryptoType;
-    A_UINT8     pairwiseCryptoLen;
-    A_UINT8     groupCryptoType;
-    A_UINT8     groupCryptoLen;
-    A_UINT8     ssidLength;
-    A_UCHAR     ssid[WMI_MAX_SSID_LEN];
-    A_UINT16    channel;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT32    ctrl_flags;
+    u8 networkType;
+    u8 dot11AuthMode;
+    u8 authMode;
+    u8 pairwiseCryptoType;
+    u8 pairwiseCryptoLen;
+    u8 groupCryptoType;
+    u8 groupCryptoLen;
+    u8 ssidLength;
+    u8     ssid[WMI_MAX_SSID_LEN];
+    u16 channel;
+    u8 bssid[ATH_MAC_LEN];
+    u32 ctrl_flags;
 } POSTPACK WMI_CONNECT_CMD;
 
 /*
  * WMI_RECONNECT_CMDID
  */
 typedef PREPACK struct {
-    A_UINT16    channel;                    /* hint */
-    A_UINT8     bssid[ATH_MAC_LEN];         /* mandatory if set */
+    u16 channel;                    /* hint */
+    u8 bssid[ATH_MAC_LEN];         /* mandatory if set */
 } POSTPACK WMI_RECONNECT_CMD;
 
 #define WMI_PMK_LEN     32
 typedef PREPACK struct {
-    A_UINT8 pmk[WMI_PMK_LEN];
+    u8 pmk[WMI_PMK_LEN];
 } POSTPACK WMI_SET_PMK_CMD;
 
 /*
+ * WMI_SET_EXCESS_TX_RETRY_THRES_CMDID
+ */
+typedef PREPACK struct {
+    A_UINT32 threshold;
+} POSTPACK WMI_SET_EXCESS_TX_RETRY_THRES_CMD;
+
+/*
  * WMI_ADD_CIPHER_KEY_CMDID
  */
 typedef enum {
@@ -572,21 +586,21 @@ typedef enum {
 #define KEY_OP_VALID_MASK   0x03
 
 typedef PREPACK struct {
-    A_UINT8     keyIndex;
-    A_UINT8     keyType;
-    A_UINT8     keyUsage;           /* KEY_USAGE */
-    A_UINT8     keyLength;
-    A_UINT8     keyRSC[8];          /* key replay sequence counter */
-    A_UINT8     key[WMI_MAX_KEY_LEN];
-    A_UINT8     key_op_ctrl;       /* Additional Key Control information */
-    A_UINT8    key_macaddr[ATH_MAC_LEN];
+    u8 keyIndex;
+    u8 keyType;
+    u8 keyUsage;           /* KEY_USAGE */
+    u8 keyLength;
+    u8 keyRSC[8];          /* key replay sequence counter */
+    u8 key[WMI_MAX_KEY_LEN];
+    u8 key_op_ctrl;       /* Additional Key Control information */
+    u8 key_macaddr[ATH_MAC_LEN];
 } POSTPACK WMI_ADD_CIPHER_KEY_CMD;
 
 /*
  * WMI_DELETE_CIPHER_KEY_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     keyIndex;
+    u8 keyIndex;
 } POSTPACK WMI_DELETE_CIPHER_KEY_CMD;
 
 #define WMI_KRK_LEN     16
@@ -594,7 +608,7 @@ typedef PREPACK struct {
  * WMI_ADD_KRK_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     krk[WMI_KRK_LEN];
+    u8 krk[WMI_KRK_LEN];
 } POSTPACK WMI_ADD_KRK_CMD;
 
 /*
@@ -606,7 +620,7 @@ typedef enum {
 } WMI_TKIP_CM_CONTROL;
 
 typedef PREPACK struct {
-    A_UINT8  cm_en;                     /* WMI_TKIP_CM_CONTROL */
+    u8 cm_en;                     /* WMI_TKIP_CM_CONTROL */
 } POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD;
 
 /*
@@ -621,9 +635,9 @@ typedef enum {
 } PMKID_ENABLE_FLG;
 
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT8     enable;                 /* PMKID_ENABLE_FLG */
-    A_UINT8     pmkid[WMI_PMKID_LEN];
+    u8 bssid[ATH_MAC_LEN];
+    u8 enable;                 /* PMKID_ENABLE_FLG */
+    u8 pmkid[WMI_PMKID_LEN];
 } POSTPACK WMI_SET_PMKID_CMD;
 
 /*
@@ -635,13 +649,13 @@ typedef enum {
 } WMI_SCAN_TYPE;
 
 typedef PREPACK struct {
-    A_BOOL   forceFgScan;
-    A_BOOL   isLegacy;        /* For Legacy Cisco AP compatibility */
-    A_UINT32 homeDwellTime;   /* Maximum duration in the home channel(milliseconds) */
-    A_UINT32 forceScanInterval;    /* Time interval between scans (milliseconds)*/
-    A_UINT8  scanType;           /* WMI_SCAN_TYPE */
-    A_UINT8  numChannels;            /* how many channels follow */
-    A_UINT16 channelList[1];         /* channels in Mhz */
+    u32   forceFgScan;
+    u32   isLegacy;        /* For Legacy Cisco AP compatibility */
+    u32 homeDwellTime;   /* Maximum duration in the home channel(milliseconds) */
+    u32 forceScanInterval;    /* Time interval between scans (milliseconds)*/
+    u8 scanType;           /* WMI_SCAN_TYPE */
+    u8 numChannels;            /* how many channels follow */
+    u16 channelList[1];         /* channels in Mhz */
 } POSTPACK WMI_START_SCAN_CMD;
 
 /*
@@ -676,16 +690,16 @@ typedef enum {
 
 
 typedef PREPACK struct {
-    A_UINT16    fg_start_period;        /* seconds */
-    A_UINT16    fg_end_period;          /* seconds */
-    A_UINT16    bg_period;              /* seconds */
-    A_UINT16    maxact_chdwell_time;    /* msec */
-    A_UINT16    pas_chdwell_time;       /* msec */
-    A_UINT8     shortScanRatio;         /* how many shorts scan for one long */
-    A_UINT8     scanCtrlFlags;
-    A_UINT16    minact_chdwell_time;    /* msec */
-    A_UINT16    maxact_scan_per_ssid;   /* max active scans per ssid */
-    A_UINT32    max_dfsch_act_time;  /* msecs */
+    u16 fg_start_period;        /* seconds */
+    u16 fg_end_period;          /* seconds */
+    u16 bg_period;              /* seconds */
+    u16 maxact_chdwell_time;    /* msec */
+    u16 pas_chdwell_time;       /* msec */
+    u8 shortScanRatio;         /* how many shorts scan for one long */
+    u8 scanCtrlFlags;
+    u16 minact_chdwell_time;    /* msec */
+    u16 maxact_scan_per_ssid;   /* max active scans per ssid */
+    u32 max_dfsch_act_time;  /* msecs */
 } POSTPACK WMI_SCAN_PARAMS_CMD;
 
 /*
@@ -703,10 +717,10 @@ typedef enum {
 } WMI_BSS_FILTER;
 
 typedef PREPACK struct {
-    A_UINT8    bssFilter;                      /* see WMI_BSS_FILTER */
-    A_UINT8    reserved1;                      /* For alignment */
-    A_UINT16   reserved2;                      /* For alignment */
-    A_UINT32   ieMask;
+    u8 bssFilter;                      /* see WMI_BSS_FILTER */
+    u8 reserved1;                      /* For alignment */
+    u16 reserved2;                      /* For alignment */
+    u32 ieMask;
 } POSTPACK WMI_BSS_FILTER_CMD;
 
 /*
@@ -721,10 +735,10 @@ typedef enum {
 } WMI_SSID_FLAG;
 
 typedef PREPACK struct {
-    A_UINT8     entryIndex;                     /* 0 to MAX_PROBED_SSID_INDEX */
-    A_UINT8     flag;                           /* WMI_SSID_FLG */
-    A_UINT8     ssidLength;
-    A_UINT8     ssid[32];
+    u8 entryIndex;                     /* 0 to MAX_PROBED_SSID_INDEX */
+    u8 flag;                           /* WMI_SSID_FLG */
+    u8 ssidLength;
+    u8 ssid[32];
 } POSTPACK WMI_PROBED_SSID_CMD;
 
 /*
@@ -737,15 +751,15 @@ typedef PREPACK struct {
 #define MAX_LISTEN_BEACONS 50
 
 typedef PREPACK struct {
-    A_UINT16     listenInterval;
-    A_UINT16     numBeacons;
+    u16 listenInterval;
+    u16 numBeacons;
 } POSTPACK WMI_LISTEN_INT_CMD;
 
 /*
  * WMI_SET_BEACON_INT_CMDID
  */
 typedef PREPACK struct {
-    A_UINT16     beaconInterval;
+    u16 beaconInterval;
 } POSTPACK WMI_BEACON_INT_CMD;
 
 /*
@@ -759,8 +773,8 @@ typedef PREPACK struct {
 #define MAX_BMISS_BEACONS  50
 
 typedef PREPACK struct {
-    A_UINT16     bmissTime;
-    A_UINT16     numBeacons;
+    u16 bmissTime;
+    u16 numBeacons;
 } POSTPACK WMI_BMISS_TIME_CMD;
 
 /*
@@ -772,25 +786,25 @@ typedef enum {
 } WMI_POWER_MODE;
 
 typedef PREPACK struct {
-    A_UINT8     powerMode;      /* WMI_POWER_MODE */
+    u8 powerMode;      /* WMI_POWER_MODE */
 } POSTPACK WMI_POWER_MODE_CMD;
 
 typedef PREPACK struct {
-    A_INT8 status;      /* WMI_SET_PARAMS_REPLY */
+    s8 status;      /* WMI_SET_PARAMS_REPLY */
 } POSTPACK WMI_SET_PARAMS_REPLY;
 
 typedef PREPACK struct {
-    A_UINT32 opcode;
-    A_UINT32 length;
-    A_CHAR buffer[1];      /* WMI_SET_PARAMS */
+    u32 opcode;
+    u32 length;
+    char buffer[1];      /* WMI_SET_PARAMS */
 } POSTPACK WMI_SET_PARAMS_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 multicast_mac[ATH_MAC_LEN];      /* WMI_SET_MCAST_FILTER */
+    u8 multicast_mac[ATH_MAC_LEN];      /* WMI_SET_MCAST_FILTER */
 } POSTPACK WMI_SET_MCAST_FILTER_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 enable;      /* WMI_MCAST_FILTER */
+    u8 enable;      /* WMI_MCAST_FILTER */
 } POSTPACK WMI_MCAST_FILTER_CMD;
 
 /*
@@ -819,12 +833,12 @@ typedef enum {
 } POWER_SAVE_FAIL_EVENT_POLICY;
 
 typedef PREPACK struct {
-    A_UINT16    idle_period;             /* msec */
-    A_UINT16    pspoll_number;
-    A_UINT16    dtim_policy;
-    A_UINT16    tx_wakeup_policy;
-    A_UINT16    num_tx_to_wakeup;
-    A_UINT16    ps_fail_event_policy;
+    u16 idle_period;             /* msec */
+    u16 pspoll_number;
+    u16 dtim_policy;
+    u16 tx_wakeup_policy;
+    u16 num_tx_to_wakeup;
+    u16 ps_fail_event_policy;
 } POSTPACK WMI_POWER_PARAMS_CMD;
 
 /* Adhoc power save types */
@@ -836,10 +850,10 @@ typedef enum {
 } WMI_ADHOC_PS_TYPE;
 
 typedef PREPACK struct {
-    A_UINT8    power_saving;
-    A_UINT8    ttl; /* number of beacon periods */
-    A_UINT16   atim_windows;          /* msec */
-    A_UINT16   timeout_value;         /* msec */
+    u8 power_saving;
+    u8 ttl; /* number of beacon periods */
+    u16 atim_windows;          /* msec */
+    u16 timeout_value;         /* msec */
 } POSTPACK WMI_IBSS_PM_CAPS_CMD;
 
 /* AP power save types */
@@ -849,10 +863,10 @@ typedef enum {
 } WMI_AP_PS_TYPE;
 
 typedef PREPACK struct {
-    A_UINT32   idle_time;   /* in msec */
-    A_UINT32   ps_period;   /* in usec */
-    A_UINT8    sleep_period; /* in ps periods */
-    A_UINT8    psType;
+    u32 idle_time;   /* in msec */
+    u32 ps_period;   /* in usec */
+    u8 sleep_period; /* in ps periods */
+    u8 psType;
 } POSTPACK WMI_AP_PS_CMD;
 
 /*
@@ -866,17 +880,17 @@ typedef enum {
 } APSD_TIM_POLICY;
 
 typedef PREPACK struct {
-    A_UINT16    psPollTimeout;          /* msec */
-    A_UINT16    triggerTimeout;         /* msec */
-    A_UINT32    apsdTimPolicy;      /* TIM behavior with  ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */
-    A_UINT32    simulatedAPSDTimPolicy;      /* TIM behavior with  simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */
+    u16 psPollTimeout;          /* msec */
+    u16 triggerTimeout;         /* msec */
+    u32 apsdTimPolicy;      /* TIM behavior with  ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */
+    u32 simulatedAPSDTimPolicy;      /* TIM behavior with  simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */
 } POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD;
 
 /*
  * WMI_SET_VOICE_PKT_SIZE_CMDID
  */
 typedef PREPACK struct {
-    A_UINT16    voicePktSize;
+    u16 voicePktSize;
 } POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD;
 
 /*
@@ -890,14 +904,14 @@ typedef enum {
 } APSD_SP_LEN_TYPE;
 
 typedef PREPACK struct {
-    A_UINT8    maxSPLen;
+    u8 maxSPLen;
 } POSTPACK WMI_SET_MAX_SP_LEN_CMD;
 
 /*
  * WMI_SET_DISC_TIMEOUT_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     disconnectTimeout;          /* seconds */
+    u8 disconnectTimeout;          /* seconds */
 } POSTPACK WMI_DISC_TIMEOUT_CMD;
 
 typedef enum {
@@ -921,47 +935,47 @@ typedef enum {
  * WMI_SYNCHRONIZE_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8 dataSyncMap;
+    u8 dataSyncMap;
 } POSTPACK WMI_SYNC_CMD;
 
 /*
  * WMI_CREATE_PSTREAM_CMDID
  */
 typedef PREPACK struct {
-    A_UINT32        minServiceInt;           /* in milli-sec */
-    A_UINT32        maxServiceInt;           /* in milli-sec */
-    A_UINT32        inactivityInt;           /* in milli-sec */
-    A_UINT32        suspensionInt;           /* in milli-sec */
-    A_UINT32        serviceStartTime;
-    A_UINT32        minDataRate;             /* in bps */
-    A_UINT32        meanDataRate;            /* in bps */
-    A_UINT32        peakDataRate;            /* in bps */
-    A_UINT32        maxBurstSize;
-    A_UINT32        delayBound;
-    A_UINT32        minPhyRate;              /* in bps */
-    A_UINT32        sba;
-    A_UINT32        mediumTime;
-    A_UINT16        nominalMSDU;             /* in octects */
-    A_UINT16        maxMSDU;                 /* in octects */
-    A_UINT8         trafficClass;
-    A_UINT8         trafficDirection;        /* DIR_TYPE */
-    A_UINT8         rxQueueNum;
-    A_UINT8         trafficType;             /* TRAFFIC_TYPE */
-    A_UINT8         voicePSCapability;       /* VOICEPS_CAP_TYPE */
-    A_UINT8         tsid;
-    A_UINT8         userPriority;            /* 802.1D user priority */
-    A_UINT8         nominalPHY;              /* nominal phy rate */
+    u32 minServiceInt;           /* in milli-sec */
+    u32 maxServiceInt;           /* in milli-sec */
+    u32 inactivityInt;           /* in milli-sec */
+    u32 suspensionInt;           /* in milli-sec */
+    u32 serviceStartTime;
+    u32 minDataRate;             /* in bps */
+    u32 meanDataRate;            /* in bps */
+    u32 peakDataRate;            /* in bps */
+    u32 maxBurstSize;
+    u32 delayBound;
+    u32 minPhyRate;              /* in bps */
+    u32 sba;
+    u32 mediumTime;
+    u16 nominalMSDU;             /* in octects */
+    u16 maxMSDU;                 /* in octects */
+    u8 trafficClass;
+    u8 trafficDirection;        /* DIR_TYPE */
+    u8 rxQueueNum;
+    u8 trafficType;             /* TRAFFIC_TYPE */
+    u8 voicePSCapability;       /* VOICEPS_CAP_TYPE */
+    u8 tsid;
+    u8 userPriority;            /* 802.1D user priority */
+    u8 nominalPHY;              /* nominal phy rate */
 } POSTPACK WMI_CREATE_PSTREAM_CMD;
 
 /*
  * WMI_DELETE_PSTREAM_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficDirection;
-    A_UINT8     trafficClass;
-    A_UINT8     tsid;
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficDirection;
+    u8 trafficClass;
+    u8 tsid;
 } POSTPACK WMI_DELETE_PSTREAM_CMD;
 
 /*
@@ -978,11 +992,11 @@ typedef enum {
 #define WMI_MAX_CHANNELS        32
 
 typedef PREPACK struct {
-    A_UINT8     reserved1;
-    A_UINT8     scanParam;              /* set if enable scan */
-    A_UINT8     phyMode;                /* see WMI_PHY_MODE */
-    A_UINT8     numChannels;            /* how many channels follow */
-    A_UINT16    channelList[1];         /* channels in Mhz */
+    u8 reserved1;
+    u8 scanParam;              /* set if enable scan */
+    u8 phyMode;                /* see WMI_PHY_MODE */
+    u8 numChannels;            /* how many channels follow */
+    u16 channelList[1];         /* channels in Mhz */
 } POSTPACK WMI_CHANNEL_PARAMS_CMD;
 
 
@@ -995,21 +1009,21 @@ typedef PREPACK struct {
  */
 
 typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{
-    A_UINT32    pollTime;               /* Polling time as a factor of LI */
-    A_INT16     thresholdAbove1_Val;          /* lowest of upper */
-    A_INT16     thresholdAbove2_Val;
-    A_INT16     thresholdAbove3_Val;
-    A_INT16     thresholdAbove4_Val;
-    A_INT16     thresholdAbove5_Val;
-    A_INT16     thresholdAbove6_Val;          /* highest of upper */
-    A_INT16     thresholdBelow1_Val;         /* lowest of bellow */
-    A_INT16     thresholdBelow2_Val;
-    A_INT16     thresholdBelow3_Val;
-    A_INT16     thresholdBelow4_Val;
-    A_INT16     thresholdBelow5_Val;
-    A_INT16     thresholdBelow6_Val;         /* highest of bellow */
-    A_UINT8     weight;                  /* "alpha" */
-    A_UINT8     reserved[3];
+    u32 pollTime;               /* Polling time as a factor of LI */
+    s16 thresholdAbove1_Val;          /* lowest of upper */
+    s16 thresholdAbove2_Val;
+    s16 thresholdAbove3_Val;
+    s16 thresholdAbove4_Val;
+    s16 thresholdAbove5_Val;
+    s16 thresholdAbove6_Val;          /* highest of upper */
+    s16 thresholdBelow1_Val;         /* lowest of bellow */
+    s16 thresholdBelow2_Val;
+    s16 thresholdBelow3_Val;
+    s16 thresholdBelow4_Val;
+    s16 thresholdBelow5_Val;
+    s16 thresholdBelow6_Val;         /* highest of bellow */
+    u8 weight;                  /* "alpha" */
+    u8 reserved[3];
 } POSTPACK  WMI_RSSI_THRESHOLD_PARAMS_CMD;
 
 /*
@@ -1018,33 +1032,33 @@ typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{
  */
 
 typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{
-    A_UINT32    pollTime;               /* Polling time as a factor of LI */
-    A_UINT8     weight;                  /* "alpha" */
-    A_UINT8     thresholdAbove1_Val;      /* lowest of uppper*/
-    A_UINT8     thresholdAbove2_Val;
-    A_UINT8     thresholdAbove3_Val;
-    A_UINT8     thresholdAbove4_Val;      /* highest of upper */
-    A_UINT8     thresholdBelow1_Val;     /* lowest of bellow */
-    A_UINT8     thresholdBelow2_Val;
-    A_UINT8     thresholdBelow3_Val;
-    A_UINT8     thresholdBelow4_Val;     /* highest of bellow */
-    A_UINT8     reserved[3];
+    u32 pollTime;               /* Polling time as a factor of LI */
+    u8 weight;                  /* "alpha" */
+    u8 thresholdAbove1_Val;      /* lowest of uppper*/
+    u8 thresholdAbove2_Val;
+    u8 thresholdAbove3_Val;
+    u8 thresholdAbove4_Val;      /* highest of upper */
+    u8 thresholdBelow1_Val;     /* lowest of bellow */
+    u8 thresholdBelow2_Val;
+    u8 thresholdBelow3_Val;
+    u8 thresholdBelow4_Val;     /* highest of bellow */
+    u8 reserved[3];
 } POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD;
 
 /*
  *  WMI_LQ_THRESHOLD_PARAMS_CMDID
  */
 typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS {
-    A_UINT8     enable;
-    A_UINT8     thresholdAbove1_Val;
-    A_UINT8     thresholdAbove2_Val;
-    A_UINT8     thresholdAbove3_Val;
-    A_UINT8     thresholdAbove4_Val;
-    A_UINT8     thresholdBelow1_Val;
-    A_UINT8     thresholdBelow2_Val;
-    A_UINT8     thresholdBelow3_Val;
-    A_UINT8     thresholdBelow4_Val;
-    A_UINT8     reserved[3];
+    u8 enable;
+    u8 thresholdAbove1_Val;
+    u8 thresholdAbove2_Val;
+    u8 thresholdAbove3_Val;
+    u8 thresholdAbove4_Val;
+    u8 thresholdBelow1_Val;
+    u8 thresholdBelow2_Val;
+    u8 thresholdBelow3_Val;
+    u8 thresholdBelow4_Val;
+    u8 reserved[3];
 } POSTPACK  WMI_LQ_THRESHOLD_PARAMS_CMD;
 
 typedef enum {
@@ -1058,12 +1072,12 @@ typedef enum {
 } WMI_PREAMBLE_POLICY;
 
 typedef PREPACK struct {
-    A_UINT8     status;
-    A_UINT8     preamblePolicy;
+    u8 status;
+    u8 preamblePolicy;
 }POSTPACK WMI_SET_LPREAMBLE_CMD;
 
 typedef PREPACK struct {
-    A_UINT16    threshold;
+    u16 threshold;
 }POSTPACK WMI_SET_RTS_CMD;
 
 /*
@@ -1073,14 +1087,14 @@ typedef PREPACK struct {
  *  via event, unless the bitmask is set again.
  */
 typedef PREPACK struct {
-    A_UINT32    bitmask;
+    u32 bitmask;
 } POSTPACK  WMI_TARGET_ERROR_REPORT_BITMASK;
 
 /*
  * WMI_SET_TX_PWR_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     dbM;                  /* in dbM units */
+    u8 dbM;                  /* in dbM units */
 } POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY;
 
 /*
@@ -1095,9 +1109,9 @@ typedef PREPACK struct {
 #define WMI_MAX_ASSOC_INFO_LEN     240
 
 typedef PREPACK struct {
-    A_UINT8     ieType;
-    A_UINT8     bufferSize;
-    A_UINT8     assocInfo[1];       /* up to WMI_MAX_ASSOC_INFO_LEN */
+    u8 ieType;
+    u8 bufferSize;
+    u8 assocInfo[1];       /* up to WMI_MAX_ASSOC_INFO_LEN */
 } POSTPACK WMI_SET_ASSOC_INFO_CMD;
 
 
@@ -1111,15 +1125,15 @@ typedef PREPACK struct {
 #define WMI_MAX_BAD_AP_INDEX      1
 
 typedef PREPACK struct {
-    A_UINT8     badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u8 badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_ADD_BAD_AP_CMD;
 
 /*
  * WMI_DELETE_BAD_AP_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
+    u8 badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
 } POSTPACK WMI_DELETE_BAD_AP_CMD;
 
 /*
@@ -1132,11 +1146,11 @@ typedef PREPACK struct {
 #define WMI_DEFAULT_AIFSN_ACPARAM   2
 #define WMI_MAX_AIFSN_ACPARAM       15
 typedef PREPACK struct {
-    A_UINT16 txop;                      /* in units of 32 usec */
-    A_UINT8  eCWmin;
-    A_UINT8  eCWmax;
-    A_UINT8  aifsn;
-    A_UINT8  ac;
+    u16 txop;                      /* in units of 32 usec */
+    u8 eCWmin;
+    u8 eCWmax;
+    u8 aifsn;
+    u8 ac;
 } POSTPACK WMI_SET_ACCESS_PARAMS_CMD;
 
 
@@ -1155,10 +1169,10 @@ typedef enum {
 } WMI_FRAMETYPE;
 
 typedef PREPACK struct {
-    A_UINT8 frameType;                      /* WMI_FRAMETYPE */
-    A_UINT8 trafficClass;                   /* applies only to DATA_FRAMETYPE */
-    A_UINT8 maxRetries;
-    A_UINT8 enableNotify;
+    u8 frameType;                      /* WMI_FRAMETYPE */
+    u8 trafficClass;                   /* applies only to DATA_FRAMETYPE */
+    u8 maxRetries;
+    u8 enableNotify;
 } POSTPACK WMI_SET_RETRY_LIMITS_CMD;
 
 /*
@@ -1198,31 +1212,31 @@ typedef enum {
  */
 
 typedef PREPACK struct {
-        A_UINT8 bssid[ATH_MAC_LEN];
-        A_INT8  bias;
+        u8 bssid[ATH_MAC_LEN];
+        s8 bias;
 } POSTPACK WMI_BSS_BIAS;
 
 typedef PREPACK struct {
-        A_UINT8 numBss;
+        u8 numBss;
         WMI_BSS_BIAS bssBias[1];
 } POSTPACK WMI_BSS_BIAS_INFO;
 
 typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS {
-        A_UINT16 lowrssi_scan_period;
-        A_INT16  lowrssi_scan_threshold;
-        A_INT16  lowrssi_roam_threshold;
-        A_UINT8  roam_rssi_floor;
-        A_UINT8  reserved[1];              /* For alignment */
+        u16 lowrssi_scan_period;
+        s16 lowrssi_scan_threshold;
+        s16 lowrssi_roam_threshold;
+        u8 roam_rssi_floor;
+        u8 reserved[1];              /* For alignment */
 } POSTPACK WMI_LOWRSSI_SCAN_PARAMS;
 
 typedef PREPACK struct {
     PREPACK union {
-        A_UINT8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */
-        A_UINT8 roamMode;           /* WMI_SET_ROAM_MODE  */
+        u8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */
+        u8 roamMode;           /* WMI_SET_ROAM_MODE  */
         WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */
         WMI_LOWRSSI_SCAN_PARAMS lrScanParams;
     } POSTPACK info;
-    A_UINT8   roamCtrlType ;
+    u8 roamCtrlType ;
 } POSTPACK WMI_SET_ROAM_CTRL_CMD;
 
 /*
@@ -1234,26 +1248,26 @@ typedef enum {
 } BT_WLAN_CONN_PRECEDENCE;
 
 typedef PREPACK struct {
-    A_UINT8 precedence;
+    u8 precedence;
 } POSTPACK WMI_SET_BT_WLAN_CONN_PRECEDENCE;
 
 /*
  * WMI_ENABLE_RM_CMDID
  */
 typedef PREPACK struct {
-        A_BOOL enable_radio_measurements;
+        u32 enable_radio_measurements;
 } POSTPACK WMI_ENABLE_RM_CMD;
 
 /*
  * WMI_SET_MAX_OFFHOME_DURATION_CMDID
  */
 typedef PREPACK struct {
-        A_UINT8 max_offhome_duration;
+        u8 max_offhome_duration;
 } POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 frequency;
-    A_UINT8  threshold;
+    u32 frequency;
+    u8 threshold;
 } POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD;
 /*---------------------- BTCOEX RELATED -------------------------------------*/
 /*----------------------COMMON to AR6002 and AR6003 -------------------------*/
@@ -1286,8 +1300,8 @@ typedef enum {
 } BT_STREAM_STATUS;
 
 typedef PREPACK struct {
-    A_UINT8 streamType;
-    A_UINT8 status;
+    u8 streamType;
+    u8 status;
 } POSTPACK WMI_SET_BT_STATUS_CMD;
 
 typedef enum {
@@ -1329,13 +1343,13 @@ typedef enum {
 #define BT_SCO_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16)
 
 typedef PREPACK struct {
-    A_UINT32 numScoCyclesForceTrigger;  /* Number SCO cycles after which
+    u32 numScoCyclesForceTrigger;  /* Number SCO cycles after which
                                            force a pspoll. default = 10 */
-    A_UINT32 dataResponseTimeout;       /* Timeout Waiting for Downlink pkt
+    u32 dataResponseTimeout;       /* Timeout Waiting for Downlink pkt
                                            in response for ps-poll,
                                            default = 10 msecs */
-    A_UINT32  stompScoRules;
-    A_UINT32 scoOptFlags;               /* SCO Options Flags :
+    u32 stompScoRules;
+    u32 scoOptFlags;               /* SCO Options Flags :
                                             bits:     meaning:
                                              0        Allow Close Range Optimization
                                              1        Force awake during close range
@@ -1346,23 +1360,23 @@ typedef PREPACK struct {
                                              16..23   Low Data Rate Max Cnt
                                         */
 
-    A_UINT8 stompDutyCyleVal;           /* Sco cycles to limit ps-poll queuing
+    u8 stompDutyCyleVal;           /* Sco cycles to limit ps-poll queuing
                                            if stomped */
-    A_UINT8 stompDutyCyleMaxVal;        /*firm ware increases stomp duty cycle
+    u8 stompDutyCyleMaxVal;        /*firm ware increases stomp duty cycle
                                           gradually uptill this value on need basis*/
-    A_UINT8 psPollLatencyFraction;      /* Fraction of idle
+    u8 psPollLatencyFraction;      /* Fraction of idle
                                            period, within which
                                            additional ps-polls
                                            can be queued */
-    A_UINT8 noSCOSlots;                 /* Number of SCO Tx/Rx slots.
+    u8 noSCOSlots;                 /* Number of SCO Tx/Rx slots.
                                            HVx, EV3, 2EV3 = 2 */
-    A_UINT8 noIdleSlots;                /* Number of Bluetooth idle slots between
+    u8 noIdleSlots;                /* Number of Bluetooth idle slots between
                                            consecutive SCO Tx/Rx slots
                                            HVx, EV3 = 4
                                            2EV3 = 10 */
-    A_UINT8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/
-    A_UINT8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/
-    A_UINT8 scoOptRtsCount;
+    u8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/
+    u8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/
+    u8 scoOptRtsCount;
 } POSTPACK BT_PARAMS_SCO;
 
 #define BT_A2DP_ALLOW_CLOSE_RANGE_OPT  (1 << 0)
@@ -1377,13 +1391,13 @@ typedef PREPACK struct {
 #define BT_A2DP_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16)
 
 typedef PREPACK struct {
-    A_UINT32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for
+    u32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for
                                     wlan, after it identifies the idle time
                                     default (30 msecs) */
-    A_UINT32 a2dpBurstCntMin;   /* Minimum number of bluetooth data frames
+    u32 a2dpBurstCntMin;   /* Minimum number of bluetooth data frames
                                    to replenish Wlan Usage  limit (default 3) */
-    A_UINT32 a2dpDataRespTimeout;
-    A_UINT32 a2dpOptFlags;      /* A2DP Option flags:
+    u32 a2dpDataRespTimeout;
+    u32 a2dpOptFlags;      /* A2DP Option flags:
                                        bits:    meaning:
                                         0       Allow Close Range Optimization
                                         1       Force awake during close range
@@ -1393,23 +1407,23 @@ typedef PREPACK struct {
                                         8..15   Low Data Rate Min Cnt
                                         16..23  Low Data Rate Max Cnt
                                  */
-    A_UINT8 isCoLocatedBtRoleMaster;
-    A_UINT8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/
-    A_UINT8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/
-    A_UINT8 a2dpOptRtsCount;
+    u8 isCoLocatedBtRoleMaster;
+    u8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/
+    u8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/
+    u8 a2dpOptRtsCount;
 }POSTPACK BT_PARAMS_A2DP;
 
 /* During BT ftp/ BT OPP or any another data based acl profile on bluetooth
    (non a2dp).*/
 typedef PREPACK struct {
-    A_UINT32 aclWlanMediumUsageTime;  /* Wlan usage time during Acl (non-a2dp)
+    u32 aclWlanMediumUsageTime;  /* Wlan usage time during Acl (non-a2dp)
                                        coexistence (default 30 msecs) */
-    A_UINT32 aclBtMediumUsageTime;   /* Bt usage time during acl coexistence
+    u32 aclBtMediumUsageTime;   /* Bt usage time during acl coexistence
                                        (default 30 msecs)*/
-    A_UINT32 aclDataRespTimeout;
-    A_UINT32 aclDetectTimeout;      /* ACL coexistence enabled if we get
+    u32 aclDataRespTimeout;
+    u32 aclDetectTimeout;      /* ACL coexistence enabled if we get
                                        10 Pkts in X msec(default 100 msecs) */
-    A_UINT32 aclmaxPktCnt;          /* No of ACL pkts to receive before
+    u32 aclmaxPktCnt;          /* No of ACL pkts to receive before
                                          enabling ACL coex */
 
 }POSTPACK BT_PARAMS_ACLCOEX;
@@ -1419,16 +1433,16 @@ typedef PREPACK struct {
         BT_PARAMS_SCO scoParams;
         BT_PARAMS_A2DP a2dpParams;
         BT_PARAMS_ACLCOEX  aclCoexParams;
-        A_UINT8 antType;         /* 0 -Disabled (default)
+        u8 antType;         /* 0 -Disabled (default)
                                      1 - BT_ANT_TYPE_DUAL
                                      2 - BT_ANT_TYPE_SPLITTER
                                      3 - BT_ANT_TYPE_SWITCH */
-        A_UINT8 coLocatedBtDev;  /* 0 - BT_COLOCATED_DEV_BTS4020 (default)
+        u8 coLocatedBtDev;  /* 0 - BT_COLOCATED_DEV_BTS4020 (default)
                                      1 - BT_COLCATED_DEV_CSR
                                      2 - BT_COLOCATED_DEV_VALKYRIe
                                    */
     } POSTPACK info;
-    A_UINT8 paramType ;
+    u8 paramType ;
 } POSTPACK WMI_SET_BT_PARAMS_CMD;
 
 /************************ END AR6002 BTCOEX *******************************/
@@ -1448,7 +1462,7 @@ typedef enum {
 }WMI_BTCOEX_FE_ANT_TYPE;
 
 typedef PREPACK struct {
-	A_UINT8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end
+	u8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end
                                 2 - WMI_BTCOEX_FE_ANT_DUAL for dual antenna front end
                                     (for isolations less 35dB, for higher isolation there
                                     is not need to pass this command).
@@ -1461,7 +1475,7 @@ typedef PREPACK struct {
  * bluetooth chip type.Based on bluetooth device, different coexistence protocol would be used.
  */
 typedef PREPACK struct {
-	A_UINT8	btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA)
+	u8 btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA)
                                     2 - CSR BT  (3 wire PTA)
                                     3 - Atheros 3001 BT (3 wire PTA)
                                     4 - STE bluetooth (4-wire ePTA)
@@ -1478,20 +1492,20 @@ typedef PREPACK struct {
  * During this the station will be  power-save mode.
  */
 typedef PREPACK struct {
-	A_UINT32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data
+	u32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data
                                             (via pspoll) is configured by this parameter.
                                             "default = 10 ms" */
 
-	A_UINT32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state
+	u32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state
                                              for configured duration, after inquiry completion
                                              . This is to ensure other bluetooth transactions
                                              (RDP, SDP profiles, link key exchange ...etc)
                                              goes through smoothly without wifi stomping.
                                              default = 10 secs*/
 
-	A_UINT32 maxpageStomp;                 /*Applicable only for STE-BT interface. Currently not
+	u32 maxpageStomp;                 /*Applicable only for STE-BT interface. Currently not
                                              used */
-	A_UINT32 btInquiryPageFlag;           /* Not used */
+	u32 btInquiryPageFlag;           /* Not used */
 }POSTPACK WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD;
 
 /*---------------------WMI_SET_BTCOEX_SCO_CONFIG_CMDID ---------------*/
@@ -1509,14 +1523,14 @@ typedef PREPACK struct {
 #define WMI_SCO_CONFIG_FLAG_IS_BT_MASTER         (1 << 2)
 #define WMI_SCO_CONFIG_FLAG_FW_DETECT_OF_PER     (1 << 3)
 typedef PREPACK struct {
-	A_UINT32 scoSlots;					/* Number of SCO Tx/Rx slots.
+	u32 scoSlots;					/* Number of SCO Tx/Rx slots.
 										   HVx, EV3, 2EV3 = 2 */
-	A_UINT32 scoIdleSlots;				/* Number of Bluetooth idle slots between
+	u32 scoIdleSlots;				/* Number of Bluetooth idle slots between
 										   consecutive SCO Tx/Rx slots
 										   HVx, EV3 = 4
 										   2EV3 = 10
                                          */
- 	A_UINT32 scoFlags;				   /* SCO Options Flags :
+	u32 scoFlags;				   /* SCO Options Flags :
 										  bits:	   meaning:
  										  0   Allow Close Range Optimization
  										  1   Is EDR capable or Not
@@ -1524,21 +1538,21 @@ typedef PREPACK struct {
                                           3   Firmware determines the periodicity of SCO.
 							  			 */
 
-    A_UINT32 linkId;                      /* applicable to STE-BT - not used */
+    u32 linkId;                      /* applicable to STE-BT - not used */
 }POSTPACK BTCOEX_SCO_CONFIG;
 
 typedef PREPACK struct {
-	A_UINT32  scoCyclesForceTrigger;	/* Number SCO cycles after which
+	u32 scoCyclesForceTrigger;	/* Number SCO cycles after which
 											force a pspoll. default = 10 */
-    A_UINT32 scoDataResponseTimeout;	 /* Timeout Waiting for Downlink pkt
+    u32 scoDataResponseTimeout;	 /* Timeout Waiting for Downlink pkt
 											in response for ps-poll,
 											default = 20 msecs */
 
-	A_UINT32 scoStompDutyCyleVal;		 /* not implemented */
+	u32 scoStompDutyCyleVal;		 /* not implemented */
 
-	A_UINT32 scoStompDutyCyleMaxVal;     /*Not implemented */
+	u32 scoStompDutyCyleMaxVal;     /*Not implemented */
 
-	A_UINT32 scoPsPollLatencyFraction; 	 /* Fraction of idle
+	u32 scoPsPollLatencyFraction; 	 /* Fraction of idle
 											period, within which
 											additional ps-polls can be queued
                                             1 - 1/4 of idle duration
@@ -1549,29 +1563,29 @@ typedef PREPACK struct {
 }POSTPACK BTCOEX_PSPOLLMODE_SCO_CONFIG;
 
 typedef PREPACK struct {
-	A_UINT32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in
+	u32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in
                                    opt mode. If exceeds the configured value,
                                    switch to ps-poll mode
                                   default = 3 */
 
-	A_UINT32 scoContStompMax;   /* max number of continous stomp allowed in opt mode.
+	u32 scoContStompMax;   /* max number of continous stomp allowed in opt mode.
                                    if excedded switch to pspoll mode
                                     default = 3 */
 
-	A_UINT32 scoMinlowRateMbps; /* Low rate threshold */
+	u32 scoMinlowRateMbps; /* Low rate threshold */
 
-	A_UINT32 scoLowRateCnt;     /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms.
+	u32 scoLowRateCnt;     /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms.
                                    If exceeded switch/stay to ps-poll mode, lower stay in opt mode.
                                    default = 36
                                  */
 
-	A_UINT32 scoHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
+	u32 scoHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
                                   ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms,
                                   if exceeded switch/stay in opt mode and if lower switch/stay in  pspoll mode.
                                   default = 5 (80% of high rates)
                                  */
 
-	A_UINT32 scoMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
+	u32 scoMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
                                    max number of aggregates if it was negogiated to higher value
                                    default = 1
                                    Recommended value Basic rate headsets = 1, EDR (2-EV3)  =4.
@@ -1579,8 +1593,8 @@ typedef PREPACK struct {
 }POSTPACK BTCOEX_OPTMODE_SCO_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 scanInterval;
-    A_UINT32 maxScanStompCnt;
+    u32 scanInterval;
+    u32 maxScanStompCnt;
 }POSTPACK BTCOEX_WLANSCAN_SCO_CONFIG;
 
 typedef PREPACK struct {
@@ -1608,7 +1622,7 @@ typedef PREPACK struct {
 #define WMI_A2DP_CONFIG_FLAG_FIND_BT_ROLE          (1 << 4)
 
 typedef PREPACK struct {
-    A_UINT32 a2dpFlags;      /* A2DP Option flags:
+    u32 a2dpFlags;      /* A2DP Option flags:
 		                        bits:    meaning:
                		            0       Allow Close Range Optimization
        	                     	1       IS EDR capable
@@ -1616,19 +1630,19 @@ typedef PREPACK struct {
                                 3       a2dp traffic is high priority
                                 4       Fw detect the role of bluetooth.
                              */
-	A_UINT32 linkId;         /* Applicable only to STE-BT - not used */
+	u32 linkId;         /* Applicable only to STE-BT - not used */
 
 }POSTPACK BTCOEX_A2DP_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for
+    u32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for
                       			wlan, after it identifies the idle time
                                 default (30 msecs) */
 
-    A_UINT32 a2dpMinBurstCnt;   /* Minimum number of bluetooth data frames
+    u32 a2dpMinBurstCnt;   /* Minimum number of bluetooth data frames
                   				to replenish Wlan Usage  limit (default 3) */
 
-    A_UINT32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink
+    u32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink
                                      by stomping on  bluetooth
                                      after ps-poll is acknowledged.
                                      default = 20 ms
@@ -1636,25 +1650,25 @@ typedef PREPACK struct {
 }POSTPACK BTCOEX_PSPOLLMODE_A2DP_CONFIG;
 
 typedef PREPACK struct {
-	A_UINT32 a2dpMinlowRateMbps;  /* Low rate threshold */
+	u32 a2dpMinlowRateMbps;  /* Low rate threshold */
 
-	A_UINT32 a2dpLowRateCnt;    /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms.
+	u32 a2dpLowRateCnt;    /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms.
                                    If exceeded switch/stay to ps-poll mode, lower stay in opt mode.
                                    default = 36
                                  */
 
-	A_UINT32 a2dpHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
+	u32 a2dpHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
                                   ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms,
                                   if exceeded switch/stay in opt mode and if lower switch/stay in  pspoll mode.
                                   default = 5 (80% of high rates)
                                  */
 
-	A_UINT32 a2dpMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
+	u32 a2dpMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
                                    max number of aggregates if it was negogiated to higher value
                                    default = 1
                                   Recommended value Basic rate headsets = 1, EDR (2-EV3)  =8.
                                  */
-	A_UINT32 a2dpPktStompCnt;    /*number of a2dp pkts that can be stomped per burst.
+	u32 a2dpPktStompCnt;    /*number of a2dp pkts that can be stomped per burst.
                                    default = 6*/
 
 }POSTPACK BTCOEX_OPTMODE_A2DP_CONFIG;
@@ -1683,15 +1697,15 @@ typedef PREPACK struct {
 #define WMI_ACLCOEX_FLAGS_DISABLE_FW_DETECTION (1 << 1)
 
 typedef PREPACK struct {
-    A_UINT32 aclWlanMediumDur; 	    /* Wlan usage time during Acl (non-a2dp)
+    u32 aclWlanMediumDur; 	    /* Wlan usage time during Acl (non-a2dp)
                      					coexistence (default 30 msecs)
                                     */
 
-    A_UINT32 aclBtMediumDur; 	   /* Bt usage time during acl coexistence
+    u32 aclBtMediumDur; 	   /* Bt usage time during acl coexistence
 					                     (default 30 msecs)
                                    */
 
-	A_UINT32 aclDetectTimeout;	   /* BT activity observation time limit.
+	u32 aclDetectTimeout;	   /* BT activity observation time limit.
 									  In this time duration, number of bt pkts are counted.
 									  If the Cnt reaches "aclPktCntLowerLimit" value
 									  for "aclIterToEnableCoex" iteration continuously,
@@ -1703,7 +1717,7 @@ typedef PREPACK struct {
     								  -default 100 msecs
                                     */
 
-	 A_UINT32 aclPktCntLowerLimit;   /* Acl Pkt Cnt to be received in duration of
+	 u32 aclPktCntLowerLimit;   /* Acl Pkt Cnt to be received in duration of
 										"aclDetectTimeout" for
 										"aclIterForEnDis" times to enabling ACL coex.
                                         Similar logic is used to disable acl coexistence.
@@ -1713,28 +1727,28 @@ typedef PREPACK struct {
                                         default = 10
                                    */
 
-	 A_UINT32 aclIterForEnDis;      /* number of Iteration of "aclPktCntLowerLimit" for Enabling and
+	 u32 aclIterForEnDis;      /* number of Iteration of "aclPktCntLowerLimit" for Enabling and
                                        Disabling Acl Coexistence.
                                        default = 3
                                      */
 
-	 A_UINT32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than
+	 u32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than
 									  "aclPktCntUpperLimit" seen in "aclDetectTimeout",
 									  ACL coexistence is enabled right away.
 									  - default 15*/
 
-	A_UINT32 aclCoexFlags;			/* A2DP Option flags:
+	u32 aclCoexFlags;			/* A2DP Option flags:
 		  	                          bits:    meaning:
        		                          0       Allow Close Range Optimization
                     		          1       disable Firmware detection
                                       (Currently supported configuration is aclCoexFlags =0)
                       			 	*/
-	A_UINT32 linkId;                /* Applicable only for STE-BT - not used */
+	u32 linkId;                /* Applicable only for STE-BT - not used */
 
 }POSTPACK BTCOEX_ACLCOEX_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 aclDataRespTimeout;   /* Max duration firmware waits for downlink
+    u32 aclDataRespTimeout;   /* Max duration firmware waits for downlink
                                       by stomping on  bluetooth
                                       after ps-poll is acknowledged.
                                      default = 20 ms */
@@ -1744,11 +1758,11 @@ typedef PREPACK struct {
 
 /* Not implemented yet*/
 typedef PREPACK struct {
-	A_UINT32 aclCoexMinlowRateMbps;
-	A_UINT32 aclCoexLowRateCnt;
-	A_UINT32 aclCoexHighPktRatio;
-	A_UINT32 aclCoexMaxAggrSize;
-	A_UINT32 aclPktStompCnt;
+	u32 aclCoexMinlowRateMbps;
+	u32 aclCoexLowRateCnt;
+	u32 aclCoexHighPktRatio;
+	u32 aclCoexMaxAggrSize;
+	u32 aclPktStompCnt;
 }POSTPACK BTCOEX_OPTMODE_ACLCOEX_CONFIG;
 
 typedef PREPACK struct {
@@ -1766,39 +1780,39 @@ typedef enum {
 }WMI_BTCOEX_BT_PROFILE;
 
 typedef PREPACK struct {
-	A_UINT32 btProfileType;
-	A_UINT32 btOperatingStatus;
-	A_UINT32 btLinkId;
+	u32 btProfileType;
+	u32 btOperatingStatus;
+	u32 btLinkId;
 }WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD;
 
 /*--------------------- WMI_SET_BTCOEX_DEBUG_CMDID ---------------------*/
 /* Used for firmware development and debugging */
 typedef PREPACK struct {
-	A_UINT32 btcoexDbgParam1;
-	A_UINT32 btcoexDbgParam2;
-	A_UINT32 btcoexDbgParam3;
-	A_UINT32 btcoexDbgParam4;
-	A_UINT32 btcoexDbgParam5;
+	u32 btcoexDbgParam1;
+	u32 btcoexDbgParam2;
+	u32 btcoexDbgParam3;
+	u32 btcoexDbgParam4;
+	u32 btcoexDbgParam5;
 }WMI_SET_BTCOEX_DEBUG_CMD;
 
 /*---------------------WMI_GET_BTCOEX_CONFIG_CMDID --------------------- */
 /* Command to firmware to get configuration parameters of the bt profile
  * reported via WMI_BTCOEX_CONFIG_EVENTID */
 typedef PREPACK struct {
-	A_UINT32 btProfileType; /* 1 - SCO
+	u32 btProfileType; /* 1 - SCO
                                2 - A2DP
                                3 - INQUIRY_PAGE
                                4 - ACLCOEX
                             */
-	A_UINT32 linkId;    /* not used */
+	u32 linkId;    /* not used */
 }WMI_GET_BTCOEX_CONFIG_CMD;
 
 /*------------------WMI_REPORT_BTCOEX_CONFIG_EVENTID------------------- */
 /* Event from firmware to host, sent in response to WMI_GET_BTCOEX_CONFIG_CMDID
  * */
 typedef PREPACK struct {
-	A_UINT32 btProfileType;
-	A_UINT32 linkId; /* not used */
+	u32 btProfileType;
+	u32 linkId; /* not used */
 	PREPACK union {
 		WMI_SET_BTCOEX_SCO_CONFIG_CMD scoConfigCmd;
 		WMI_SET_BTCOEX_A2DP_CONFIG_CMD a2dpConfigCmd;
@@ -1810,32 +1824,32 @@ typedef PREPACK struct {
 /*------------- WMI_REPORT_BTCOEX_BTCOEX_STATS_EVENTID--------------------*/
 /* Used for firmware development and debugging*/
 typedef PREPACK struct {
-	A_UINT32 highRatePktCnt;
-	A_UINT32 firstBmissCnt;
-	A_UINT32 psPollFailureCnt;
-	A_UINT32 nullFrameFailureCnt;
-	A_UINT32 optModeTransitionCnt;
+	u32 highRatePktCnt;
+	u32 firstBmissCnt;
+	u32 psPollFailureCnt;
+	u32 nullFrameFailureCnt;
+	u32 optModeTransitionCnt;
 }BTCOEX_GENERAL_STATS;
 
 typedef PREPACK struct {
-	A_UINT32	scoStompCntAvg;
-	A_UINT32	scoStompIn100ms;
-	A_UINT32 	scoMaxContStomp;
-	A_UINT32	scoAvgNoRetries;
-	A_UINT32	scoMaxNoRetriesIn100ms;
+	u32 scoStompCntAvg;
+	u32 scoStompIn100ms;
+	u32 scoMaxContStomp;
+	u32 scoAvgNoRetries;
+	u32 scoMaxNoRetriesIn100ms;
 }BTCOEX_SCO_STATS;
 
 typedef PREPACK struct {
-	A_UINT32  	a2dpBurstCnt;
-	A_UINT32	a2dpMaxBurstCnt;
-	A_UINT32	a2dpAvgIdletimeIn100ms;
-	A_UINT32	a2dpAvgStompCnt;
+	u32 a2dpBurstCnt;
+	u32 a2dpMaxBurstCnt;
+	u32 a2dpAvgIdletimeIn100ms;
+	u32 a2dpAvgStompCnt;
 }BTCOEX_A2DP_STATS;
 
 typedef PREPACK struct {
-	A_UINT32	aclPktCntInBtTime;
-	A_UINT32	aclStompCntInWlanTime;
-	A_UINT32	aclPktCntIn100ms;
+	u32 aclPktCntInBtTime;
+	u32 aclStompCntInWlanTime;
+	u32 aclPktCntIn100ms;
 }BTCOEX_ACLCOEX_STATS;
 
 typedef PREPACK struct {
@@ -1848,7 +1862,7 @@ typedef PREPACK struct {
 
 /*--------------------------END OF BTCOEX -------------------------------------*/
 typedef PREPACK struct {
-    A_UINT32 sleepState;
+    u32 sleepState;
 }WMI_REPORT_SLEEP_STATE_EVENT;
 
 typedef enum {
@@ -1861,13 +1875,13 @@ typedef enum {
 } TARGET_EVENT_REPORT_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 evtConfig;
+    u32 evtConfig;
 } POSTPACK WMI_SET_TARGET_EVENT_REPORT_CMD;
 
 
 typedef PREPACK struct {
-    A_UINT16    cmd_buf_sz;     /* HCI cmd buffer size */
-    A_UINT8     buf[1];         /* Absolute HCI cmd */
+    u16 cmd_buf_sz;     /* HCI cmd buffer size */
+    u8 buf[1];         /* Absolute HCI cmd */
 } POSTPACK WMI_HCI_CMD;
 
 /*
@@ -1878,13 +1892,13 @@ typedef PREPACK struct {
  * WMI_GET_CHANNEL_LIST_CMDID reply
  */
 typedef PREPACK struct {
-    A_UINT8     reserved1;
-    A_UINT8     numChannels;            /* number of channels in reply */
-    A_UINT16    channelList[1];         /* channel in Mhz */
+    u8 reserved1;
+    u8 numChannels;            /* number of channels in reply */
+    u16 channelList[1];         /* channel in Mhz */
 } POSTPACK WMI_CHANNEL_LIST_REPLY;
 
 typedef enum {
-    A_SUCCEEDED = A_OK,
+    A_SUCCEEDED = 0,
     A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250,
     A_SUCCEEDED_MODIFY_STREAM=251,
     A_FAILED_INVALID_STREAM = 252,
@@ -1893,19 +1907,19 @@ typedef enum {
 } PSTREAM_REPLY_STATUS;
 
 typedef PREPACK struct {
-    A_UINT8     status;                 /* PSTREAM_REPLY_STATUS */
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficClass;
-    A_UINT8     trafficDirection;       /* DIR_TYPE */
+    u8 status;                 /* PSTREAM_REPLY_STATUS */
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficClass;
+    u8 trafficDirection;       /* DIR_TYPE */
 } POSTPACK WMI_CRE_PRIORITY_STREAM_REPLY;
 
 typedef PREPACK struct {
-    A_UINT8     status;                 /* PSTREAM_REPLY_STATUS */
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficDirection;       /* DIR_TYPE */
-    A_UINT8     trafficClass;
+    u8 status;                 /* PSTREAM_REPLY_STATUS */
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficDirection;       /* DIR_TYPE */
+    u8 trafficClass;
 } POSTPACK WMI_DEL_PRIORITY_STREAM_REPLY;
 
 /*
@@ -1976,15 +1990,15 @@ typedef enum {
 } WMI_PHY_CAPABILITY;
 
 typedef PREPACK struct {
-    A_UINT8     macaddr[ATH_MAC_LEN];
-    A_UINT8     phyCapability;              /* WMI_PHY_CAPABILITY */
+    u8 macaddr[ATH_MAC_LEN];
+    u8 phyCapability;              /* WMI_PHY_CAPABILITY */
 } POSTPACK WMI_READY_EVENT_1;
 
 typedef PREPACK struct {
-    A_UINT32    sw_version;
-    A_UINT32    abi_version;
-    A_UINT8     macaddr[ATH_MAC_LEN];
-    A_UINT8     phyCapability;              /* WMI_PHY_CAPABILITY */
+    u32 sw_version;
+    u32 abi_version;
+    u8 macaddr[ATH_MAC_LEN];
+    u8 phyCapability;              /* WMI_PHY_CAPABILITY */
 } POSTPACK WMI_READY_EVENT_2;
 
 #if defined(ATH_TARGET)
@@ -2002,15 +2016,15 @@ typedef PREPACK struct {
  * Connect Event
  */
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT16    listenInterval;
-    A_UINT16    beaconInterval;
-    A_UINT32    networkType;
-    A_UINT8     beaconIeLen;
-    A_UINT8     assocReqLen;
-    A_UINT8     assocRespLen;
-    A_UINT8     assocInfo[1];
+    u16 channel;
+    u8 bssid[ATH_MAC_LEN];
+    u16 listenInterval;
+    u16 beaconInterval;
+    u32 networkType;
+    u8 beaconIeLen;
+    u8 assocReqLen;
+    u8 assocRespLen;
+    u8 assocInfo[1];
 } POSTPACK WMI_CONNECT_EVENT;
 
 /*
@@ -2033,11 +2047,11 @@ typedef enum {
 } WMI_DISCONNECT_REASON;
 
 typedef PREPACK struct {
-    A_UINT16    protocolReasonStatus;  /* reason code, see 802.11 spec. */
-    A_UINT8     bssid[ATH_MAC_LEN];    /* set if known */
-    A_UINT8     disconnectReason ;      /* see WMI_DISCONNECT_REASON */
-    A_UINT8     assocRespLen;
-    A_UINT8     assocInfo[1];
+    u16 protocolReasonStatus;  /* reason code, see 802.11 spec. */
+    u8 bssid[ATH_MAC_LEN];    /* set if known */
+    u8 disconnectReason ;      /* see WMI_DISCONNECT_REASON */
+    u8 assocRespLen;
+    u8 assocInfo[1];
 } POSTPACK WMI_DISCONNECT_EVENT;
 
 /*
@@ -2059,12 +2073,12 @@ enum {
 };
 
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     frameType;          /* see WMI_BI_FTYPE */
-    A_UINT8     snr;
-    A_INT16     rssi;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT32    ieMask;
+    u16 channel;
+    u8 frameType;          /* see WMI_BI_FTYPE */
+    u8 snr;
+    s16 rssi;
+    u8 bssid[ATH_MAC_LEN];
+    u32 ieMask;
 } POSTPACK WMI_BSS_INFO_HDR;
 
 /*
@@ -2076,11 +2090,11 @@ typedef PREPACK struct {
  * - Remove rssi and compute it on the host. rssi = snr - 95
  */
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     frameType;          /* see WMI_BI_FTYPE */
-    A_UINT8     snr;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT16    ieMask;
+    u16 channel;
+    u8 frameType;          /* see WMI_BI_FTYPE */
+    u8 snr;
+    u8 bssid[ATH_MAC_LEN];
+    u16 ieMask;
 } POSTPACK WMI_BSS_INFO_HDR2;
 
 /*
@@ -2093,29 +2107,29 @@ typedef enum {
 } WMI_ERROR_CODE;
 
 typedef PREPACK struct {
-    A_UINT16    commandId;
-    A_UINT8     errorCode;
+    u16 commandId;
+    u8 errorCode;
 } POSTPACK WMI_CMD_ERROR_EVENT;
 
 /*
  * New Regulatory Domain Event
  */
 typedef PREPACK struct {
-    A_UINT32    regDomain;
+    u32 regDomain;
 } POSTPACK WMI_REG_DOMAIN_EVENT;
 
 typedef PREPACK struct {
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficDirection;
-    A_UINT8     trafficClass;
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficDirection;
+    u8 trafficClass;
 } POSTPACK WMI_PSTREAM_TIMEOUT_EVENT;
 
 typedef PREPACK struct {
-    A_UINT8     reserve1;
-    A_UINT8     reserve2;
-    A_UINT8     reserve3;
-    A_UINT8     trafficClass;
+    u8 reserve1;
+    u8 reserve2;
+    u8 reserve3;
+    u8 trafficClass;
 } POSTPACK WMI_ACM_REJECT_EVENT;
 
 /*
@@ -2134,12 +2148,12 @@ typedef enum {
 } WMI_BSS_FLAGS;
 
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT8     bssFlags;            /* see WMI_BSS_FLAGS */
+    u8 bssid[ATH_MAC_LEN];
+    u8 bssFlags;            /* see WMI_BSS_FLAGS */
 } POSTPACK WMI_NEIGHBOR_INFO;
 
 typedef PREPACK struct {
-    A_INT8      numberOfAps;
+    s8 numberOfAps;
     WMI_NEIGHBOR_INFO neighbor[1];
 } POSTPACK WMI_NEIGHBOR_REPORT_EVENT;
 
@@ -2147,15 +2161,15 @@ typedef PREPACK struct {
  * TKIP MIC Error Event
  */
 typedef PREPACK struct {
-    A_UINT8 keyid;
-    A_UINT8 ismcast;
+    u8 keyid;
+    u8 ismcast;
 } POSTPACK WMI_TKIP_MICERR_EVENT;
 
 /*
  * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new)
  */
 typedef PREPACK struct {
-    A_INT32 status;
+    s32 status;
 } POSTPACK WMI_SCAN_COMPLETE_EVENT;
 
 #define MAX_OPT_DATA_LEN 1400
@@ -2164,7 +2178,7 @@ typedef PREPACK struct {
  * WMI_SET_ADHOC_BSSID_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_SET_ADHOC_BSSID_CMD;
 
 /*
@@ -2176,7 +2190,7 @@ typedef enum {
 } OPT_MODE_TYPE;
 
 typedef PREPACK struct {
-    A_UINT8     optMode;
+    u8 optMode;
 } POSTPACK WMI_SET_OPT_MODE_CMD;
 
 /*
@@ -2190,12 +2204,12 @@ typedef enum {
 } WMI_OPT_FTYPE;
 
 typedef PREPACK struct {
-    A_UINT16    optIEDataLen;
-    A_UINT8     frmType;
-    A_UINT8     dstAddr[ATH_MAC_LEN];
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT8     reserved;               /* For alignment */
-    A_UINT8     optIEData[1];
+    u16 optIEDataLen;
+    u8 frmType;
+    u8 dstAddr[ATH_MAC_LEN];
+    u8 bssid[ATH_MAC_LEN];
+    u8 reserved;               /* For alignment */
+    u8 optIEData[1];
 } POSTPACK WMI_OPT_TX_FRAME_CMD;
 
 /*
@@ -2205,84 +2219,84 @@ typedef PREPACK struct {
  * The 802.11 header is not included.
  */
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     frameType;          /* see WMI_OPT_FTYPE */
-    A_INT8      snr;
-    A_UINT8     srcAddr[ATH_MAC_LEN];
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u16 channel;
+    u8 frameType;          /* see WMI_OPT_FTYPE */
+    s8 snr;
+    u8 srcAddr[ATH_MAC_LEN];
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_OPT_RX_INFO_HDR;
 
 /*
  * Reporting statistics.
  */
 typedef PREPACK struct {
-    A_UINT32   tx_packets;
-    A_UINT32   tx_bytes;
-    A_UINT32   tx_unicast_pkts;
-    A_UINT32   tx_unicast_bytes;
-    A_UINT32   tx_multicast_pkts;
-    A_UINT32   tx_multicast_bytes;
-    A_UINT32   tx_broadcast_pkts;
-    A_UINT32   tx_broadcast_bytes;
-    A_UINT32   tx_rts_success_cnt;
-    A_UINT32   tx_packet_per_ac[4];
-    A_UINT32   tx_errors_per_ac[4];
-
-    A_UINT32   tx_errors;
-    A_UINT32   tx_failed_cnt;
-    A_UINT32   tx_retry_cnt;
-    A_UINT32   tx_mult_retry_cnt;
-    A_UINT32   tx_rts_fail_cnt;
-    A_INT32    tx_unicast_rate;
+    u32 tx_packets;
+    u32 tx_bytes;
+    u32 tx_unicast_pkts;
+    u32 tx_unicast_bytes;
+    u32 tx_multicast_pkts;
+    u32 tx_multicast_bytes;
+    u32 tx_broadcast_pkts;
+    u32 tx_broadcast_bytes;
+    u32 tx_rts_success_cnt;
+    u32 tx_packet_per_ac[4];
+    u32 tx_errors_per_ac[4];
+
+    u32 tx_errors;
+    u32 tx_failed_cnt;
+    u32 tx_retry_cnt;
+    u32 tx_mult_retry_cnt;
+    u32 tx_rts_fail_cnt;
+    s32 tx_unicast_rate;
 }POSTPACK tx_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32   rx_packets;
-    A_UINT32   rx_bytes;
-    A_UINT32   rx_unicast_pkts;
-    A_UINT32   rx_unicast_bytes;
-    A_UINT32   rx_multicast_pkts;
-    A_UINT32   rx_multicast_bytes;
-    A_UINT32   rx_broadcast_pkts;
-    A_UINT32   rx_broadcast_bytes;
-    A_UINT32   rx_fragment_pkt;
-
-    A_UINT32   rx_errors;
-    A_UINT32   rx_crcerr;
-    A_UINT32   rx_key_cache_miss;
-    A_UINT32   rx_decrypt_err;
-    A_UINT32   rx_duplicate_frames;
-    A_INT32    rx_unicast_rate;
+    u32 rx_packets;
+    u32 rx_bytes;
+    u32 rx_unicast_pkts;
+    u32 rx_unicast_bytes;
+    u32 rx_multicast_pkts;
+    u32 rx_multicast_bytes;
+    u32 rx_broadcast_pkts;
+    u32 rx_broadcast_bytes;
+    u32 rx_fragment_pkt;
+
+    u32 rx_errors;
+    u32 rx_crcerr;
+    u32 rx_key_cache_miss;
+    u32 rx_decrypt_err;
+    u32 rx_duplicate_frames;
+    s32 rx_unicast_rate;
 }POSTPACK rx_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32   tkip_local_mic_failure;
-    A_UINT32   tkip_counter_measures_invoked;
-    A_UINT32   tkip_replays;
-    A_UINT32   tkip_format_errors;
-    A_UINT32   ccmp_format_errors;
-    A_UINT32   ccmp_replays;
+    u32 tkip_local_mic_failure;
+    u32 tkip_counter_measures_invoked;
+    u32 tkip_replays;
+    u32 tkip_format_errors;
+    u32 ccmp_format_errors;
+    u32 ccmp_replays;
 }POSTPACK tkip_ccmp_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32   power_save_failure_cnt;
-    A_UINT16   stop_tx_failure_cnt;
-    A_UINT16   atim_tx_failure_cnt;
-    A_UINT16   atim_rx_failure_cnt;
-    A_UINT16   bcn_rx_failure_cnt;
+    u32 power_save_failure_cnt;
+    u16 stop_tx_failure_cnt;
+    u16 atim_tx_failure_cnt;
+    u16 atim_rx_failure_cnt;
+    u16 bcn_rx_failure_cnt;
 }POSTPACK pm_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32    cs_bmiss_cnt;
-    A_UINT32    cs_lowRssi_cnt;
-    A_UINT16    cs_connect_cnt;
-    A_UINT16    cs_disconnect_cnt;
-    A_INT16     cs_aveBeacon_rssi;
-    A_UINT16    cs_roam_count;
-    A_INT16     cs_rssi;
-    A_UINT8     cs_snr;
-    A_UINT8     cs_aveBeacon_snr;
-    A_UINT8     cs_lastRoam_msec;
+    u32 cs_bmiss_cnt;
+    u32 cs_lowRssi_cnt;
+    u16 cs_connect_cnt;
+    u16 cs_disconnect_cnt;
+    s16 cs_aveBeacon_rssi;
+    u16 cs_roam_count;
+    s16 cs_rssi;
+    u8 cs_snr;
+    u8 cs_aveBeacon_snr;
+    u8 cs_lastRoam_msec;
 } POSTPACK cserv_stats_t;
 
 typedef PREPACK struct {
@@ -2292,21 +2306,21 @@ typedef PREPACK struct {
 }POSTPACK wlan_net_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32    arp_received;
-    A_UINT32    arp_matched;
-    A_UINT32    arp_replied;
+    u32 arp_received;
+    u32 arp_matched;
+    u32 arp_replied;
 } POSTPACK arp_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32    wow_num_pkts_dropped;
-    A_UINT16    wow_num_events_discarded;
-    A_UINT8     wow_num_host_pkt_wakeups;
-    A_UINT8     wow_num_host_event_wakeups;
+    u32 wow_num_pkts_dropped;
+    u16 wow_num_events_discarded;
+    u8 wow_num_host_pkt_wakeups;
+    u8 wow_num_host_event_wakeups;
 } POSTPACK wlan_wow_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32            lqVal;
-    A_INT32             noise_floor_calibation;
+    u32 lqVal;
+    s32 noise_floor_calibation;
     pm_stats_t          pmStats;
     wlan_net_stats_t    txrxStats;
     wlan_wow_stats_t    wowStats;
@@ -2335,8 +2349,8 @@ typedef enum{
 }WMI_RSSI_THRESHOLD_VAL;
 
 typedef PREPACK struct {
-    A_INT16 rssi;
-    A_UINT8 range;
+    s16 rssi;
+    u8 range;
 }POSTPACK WMI_RSSI_THRESHOLD_EVENT;
 
 /*
@@ -2353,11 +2367,11 @@ typedef enum{
 } WMI_TARGET_ERROR_VAL;
 
 typedef PREPACK struct {
-    A_UINT32 errorVal;
+    u32 errorVal;
 }POSTPACK  WMI_TARGET_ERROR_REPORT_EVENT;
 
 typedef PREPACK struct {
-    A_UINT8 retrys;
+    u8 retrys;
 }POSTPACK  WMI_TX_RETRY_ERR_EVENT;
 
 typedef enum{
@@ -2372,8 +2386,8 @@ typedef enum{
 } WMI_SNR_THRESHOLD_VAL;
 
 typedef PREPACK struct {
-    A_UINT8 range;  /* WMI_SNR_THRESHOLD_VAL */
-    A_UINT8 snr;
+    u8 range;  /* WMI_SNR_THRESHOLD_VAL */
+    u8 snr;
 }POSTPACK  WMI_SNR_THRESHOLD_EVENT;
 
 typedef enum{
@@ -2388,8 +2402,8 @@ typedef enum{
 } WMI_LQ_THRESHOLD_VAL;
 
 typedef PREPACK struct {
-    A_INT32 lq;
-    A_UINT8 range;  /* WMI_LQ_THRESHOLD_VAL */
+    s32 lq;
+    u8 range;  /* WMI_LQ_THRESHOLD_VAL */
 }POSTPACK  WMI_LQ_THRESHOLD_EVENT;
 /*
  * WMI_REPORT_ROAM_TBL_EVENTID
@@ -2397,20 +2411,20 @@ typedef PREPACK struct {
 #define MAX_ROAM_TBL_CAND   5
 
 typedef PREPACK struct {
-    A_INT32 roam_util;
-    A_UINT8 bssid[ATH_MAC_LEN];
-    A_INT8  rssi;
-    A_INT8  rssidt;
-    A_INT8  last_rssi;
-    A_INT8  util;
-    A_INT8  bias;
-    A_UINT8 reserved; /* For alignment */
+    s32 roam_util;
+    u8 bssid[ATH_MAC_LEN];
+    s8 rssi;
+    s8 rssidt;
+    s8 last_rssi;
+    s8 util;
+    s8 bias;
+    u8 reserved; /* For alignment */
 } POSTPACK WMI_BSS_ROAM_INFO;
 
 
 typedef PREPACK struct {
-    A_UINT16  roamMode;
-    A_UINT16  numEntries;
+    u16 roamMode;
+    u16 numEntries;
     WMI_BSS_ROAM_INFO bssRoamInfo[1];
 } POSTPACK WMI_TARGET_ROAM_TBL;
 
@@ -2418,8 +2432,8 @@ typedef PREPACK struct {
  * WMI_HCI_EVENT_EVENTID
  */
 typedef PREPACK struct {
-    A_UINT16    evt_buf_sz;     /* HCI event buffer size */
-    A_UINT8     buf[1];         /* HCI  event */
+    u16 evt_buf_sz;     /* HCI event buffer size */
+    u8 buf[1];         /* HCI  event */
 } POSTPACK WMI_HCI_EVENT;
 
 /*
@@ -2435,10 +2449,10 @@ typedef enum {
 #define WMM_TSPEC_IE_LEN   63
 
 typedef PREPACK struct {
-    A_UINT8 ac;
-    A_UINT8 cac_indication;
-    A_UINT8 statusCode;
-    A_UINT8 tspecSuggestion[WMM_TSPEC_IE_LEN];
+    u8 ac;
+    u8 cac_indication;
+    u8 statusCode;
+    u8 tspecSuggestion[WMM_TSPEC_IE_LEN];
 }POSTPACK  WMI_CAC_EVENT;
 
 /*
@@ -2450,8 +2464,8 @@ typedef enum {
 } APLIST_VER;
 
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT16    channel;
+    u8 bssid[ATH_MAC_LEN];
+    u16 channel;
 } POSTPACK  WMI_AP_INFO_V1;
 
 typedef PREPACK union {
@@ -2459,8 +2473,8 @@ typedef PREPACK union {
 } POSTPACK WMI_AP_INFO;
 
 typedef PREPACK struct {
-    A_UINT8     apListVer;
-    A_UINT8     numAP;
+    u8 apListVer;
+    u8 numAP;
     WMI_AP_INFO apList[1];
 } POSTPACK WMI_APLIST_EVENT;
 
@@ -2506,14 +2520,14 @@ typedef enum {
 } WMI_BIT_RATE;
 
 typedef PREPACK struct {
-    A_INT8      rateIndex;          /* see WMI_BIT_RATE */
-    A_INT8      mgmtRateIndex;
-    A_INT8      ctlRateIndex;
+    s8 rateIndex;          /* see WMI_BIT_RATE */
+    s8 mgmtRateIndex;
+    s8 ctlRateIndex;
 } POSTPACK WMI_BIT_RATE_CMD;
 
 
 typedef PREPACK struct {
-    A_INT8      rateIndex;          /* see WMI_BIT_RATE */
+    s8 rateIndex;          /* see WMI_BIT_RATE */
 } POSTPACK  WMI_BIT_RATE_REPLY;
 
 
@@ -2522,43 +2536,43 @@ typedef PREPACK struct {
  *
  * Get fix rates cmd uses same definition as set fix rates cmd
  */
-#define FIX_RATE_1Mb            ((A_UINT32)0x1)
-#define FIX_RATE_2Mb            ((A_UINT32)0x2)
-#define FIX_RATE_5_5Mb          ((A_UINT32)0x4)
-#define FIX_RATE_11Mb           ((A_UINT32)0x8)
-#define FIX_RATE_6Mb            ((A_UINT32)0x10)
-#define FIX_RATE_9Mb            ((A_UINT32)0x20)
-#define FIX_RATE_12Mb           ((A_UINT32)0x40)
-#define FIX_RATE_18Mb           ((A_UINT32)0x80)
-#define FIX_RATE_24Mb           ((A_UINT32)0x100)
-#define FIX_RATE_36Mb           ((A_UINT32)0x200)
-#define FIX_RATE_48Mb           ((A_UINT32)0x400)
-#define FIX_RATE_54Mb           ((A_UINT32)0x800)
-#define FIX_RATE_MCS_0_20       ((A_UINT32)0x1000)
-#define FIX_RATE_MCS_1_20       ((A_UINT32)0x2000)
-#define FIX_RATE_MCS_2_20       ((A_UINT32)0x4000)
-#define FIX_RATE_MCS_3_20       ((A_UINT32)0x8000)
-#define FIX_RATE_MCS_4_20       ((A_UINT32)0x10000)
-#define FIX_RATE_MCS_5_20       ((A_UINT32)0x20000)
-#define FIX_RATE_MCS_6_20       ((A_UINT32)0x40000)
-#define FIX_RATE_MCS_7_20       ((A_UINT32)0x80000)
-#define FIX_RATE_MCS_0_40       ((A_UINT32)0x100000)
-#define FIX_RATE_MCS_1_40       ((A_UINT32)0x200000)
-#define FIX_RATE_MCS_2_40       ((A_UINT32)0x400000)
-#define FIX_RATE_MCS_3_40       ((A_UINT32)0x800000)
-#define FIX_RATE_MCS_4_40       ((A_UINT32)0x1000000)
-#define FIX_RATE_MCS_5_40       ((A_UINT32)0x2000000)
-#define FIX_RATE_MCS_6_40       ((A_UINT32)0x4000000)
-#define FIX_RATE_MCS_7_40       ((A_UINT32)0x8000000)
-
-typedef PREPACK struct {
-    A_UINT32      fixRateMask;          /* see WMI_BIT_RATE */
+#define FIX_RATE_1Mb            ((u32)0x1)
+#define FIX_RATE_2Mb            ((u32)0x2)
+#define FIX_RATE_5_5Mb          ((u32)0x4)
+#define FIX_RATE_11Mb           ((u32)0x8)
+#define FIX_RATE_6Mb            ((u32)0x10)
+#define FIX_RATE_9Mb            ((u32)0x20)
+#define FIX_RATE_12Mb           ((u32)0x40)
+#define FIX_RATE_18Mb           ((u32)0x80)
+#define FIX_RATE_24Mb           ((u32)0x100)
+#define FIX_RATE_36Mb           ((u32)0x200)
+#define FIX_RATE_48Mb           ((u32)0x400)
+#define FIX_RATE_54Mb           ((u32)0x800)
+#define FIX_RATE_MCS_0_20       ((u32)0x1000)
+#define FIX_RATE_MCS_1_20       ((u32)0x2000)
+#define FIX_RATE_MCS_2_20       ((u32)0x4000)
+#define FIX_RATE_MCS_3_20       ((u32)0x8000)
+#define FIX_RATE_MCS_4_20       ((u32)0x10000)
+#define FIX_RATE_MCS_5_20       ((u32)0x20000)
+#define FIX_RATE_MCS_6_20       ((u32)0x40000)
+#define FIX_RATE_MCS_7_20       ((u32)0x80000)
+#define FIX_RATE_MCS_0_40       ((u32)0x100000)
+#define FIX_RATE_MCS_1_40       ((u32)0x200000)
+#define FIX_RATE_MCS_2_40       ((u32)0x400000)
+#define FIX_RATE_MCS_3_40       ((u32)0x800000)
+#define FIX_RATE_MCS_4_40       ((u32)0x1000000)
+#define FIX_RATE_MCS_5_40       ((u32)0x2000000)
+#define FIX_RATE_MCS_6_40       ((u32)0x4000000)
+#define FIX_RATE_MCS_7_40       ((u32)0x8000000)
+
+typedef PREPACK struct {
+    u32 fixRateMask;          /* see WMI_BIT_RATE */
 } POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY;
 
 typedef PREPACK struct {
-    A_UINT8        bEnableMask;
-    A_UINT8        frameType;               /*type and subtype*/
-    A_UINT32     frameRateMask;          /* see WMI_BIT_RATE */
+    u8 bEnableMask;
+    u8 frameType;               /*type and subtype*/
+    u32 frameRateMask;          /* see WMI_BIT_RATE */
 } POSTPACK WMI_FRAME_RATES_CMD, WMI_FRAME_RATES_REPLY;
 
 /*
@@ -2572,7 +2586,7 @@ typedef enum {
 } WMI_AUTH_MODE;
 
 typedef PREPACK struct {
-    A_UINT8 mode;
+    u8 mode;
 } POSTPACK WMI_SET_AUTH_MODE_CMD;
 
 /*
@@ -2586,7 +2600,7 @@ typedef enum {
 } WMI_REASSOC_MODE;
 
 typedef PREPACK struct {
-    A_UINT8 mode;
+    u8 mode;
 }POSTPACK WMI_SET_REASSOC_MODE_CMD;
 
 typedef enum {
@@ -2594,21 +2608,21 @@ typedef enum {
 } ROAM_DATA_TYPE;
 
 typedef PREPACK struct {
-    A_UINT32        disassoc_time;
-    A_UINT32        no_txrx_time;
-    A_UINT32        assoc_time;
-    A_UINT32        allow_txrx_time;
-    A_UINT8         disassoc_bssid[ATH_MAC_LEN];
-    A_INT8          disassoc_bss_rssi;
-    A_UINT8         assoc_bssid[ATH_MAC_LEN];
-    A_INT8          assoc_bss_rssi;
+    u32 disassoc_time;
+    u32 no_txrx_time;
+    u32 assoc_time;
+    u32 allow_txrx_time;
+    u8 disassoc_bssid[ATH_MAC_LEN];
+    s8 disassoc_bss_rssi;
+    u8 assoc_bssid[ATH_MAC_LEN];
+    s8 assoc_bss_rssi;
 } POSTPACK WMI_TARGET_ROAM_TIME;
 
 typedef PREPACK struct {
     PREPACK union {
         WMI_TARGET_ROAM_TIME roamTime;
     } POSTPACK u;
-    A_UINT8 roamDataType ;
+    u8 roamDataType ;
 } POSTPACK WMI_TARGET_ROAM_DATA;
 
 typedef enum {
@@ -2617,11 +2631,11 @@ typedef enum {
 } WMI_WMM_STATUS;
 
 typedef PREPACK struct {
-    A_UINT8    status;
+    u8 status;
 }POSTPACK WMI_SET_WMM_CMD;
 
 typedef PREPACK struct {
-    A_UINT8    status;
+    u8 status;
 }POSTPACK WMI_SET_QOS_SUPP_CMD;
 
 typedef enum {
@@ -2630,16 +2644,16 @@ typedef enum {
 } WMI_TXOP_CFG;
 
 typedef PREPACK struct {
-    A_UINT8    txopEnable;
+    u8 txopEnable;
 }POSTPACK WMI_SET_WMM_TXOP_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 keepaliveInterval;
+    u8 keepaliveInterval;
 } POSTPACK WMI_SET_KEEPALIVE_CMD;
 
 typedef PREPACK struct {
-    A_BOOL configured;
-    A_UINT8 keepaliveInterval;
+    u32 configured;
+    u8 keepaliveInterval;
 } POSTPACK WMI_GET_KEEPALIVE_CMD;
 
 /*
@@ -2648,9 +2662,9 @@ typedef PREPACK struct {
 #define WMI_MAX_IE_LEN  255
 
 typedef PREPACK struct {
-    A_UINT8 mgmtFrmType;  /* one of WMI_MGMT_FRAME_TYPE */
-    A_UINT8 ieLen;    /* Length  of the IE that should be added to the MGMT frame */
-    A_UINT8 ieInfo[1];
+    u8 mgmtFrmType;  /* one of WMI_MGMT_FRAME_TYPE */
+    u8 ieLen;    /* Length  of the IE that should be added to the MGMT frame */
+    u8 ieInfo[1];
 } POSTPACK WMI_SET_APPIE_CMD;
 
 /*
@@ -2665,12 +2679,12 @@ typedef enum {
 }WHAL_CMDID;
 
 typedef PREPACK struct {
-    A_UINT8 cabTimeOut;
+    u8 cabTimeOut;
 } POSTPACK WHAL_SETCABTO_PARAM;
 
 typedef PREPACK struct {
-    A_UINT8  whalCmdId;
-    A_UINT8 data[1];
+    u8 whalCmdId;
+    u8 data[1];
 } POSTPACK WHAL_PARAMCMD;
 
 
@@ -2682,43 +2696,43 @@ typedef PREPACK struct {
 #define MAC_MAX_FILTERS_PER_LIST 4
 
 typedef PREPACK struct {
-    A_UINT8 wow_valid_filter;
-    A_UINT8 wow_filter_id;
-    A_UINT8 wow_filter_size;
-    A_UINT8 wow_filter_offset;
-    A_UINT8 wow_filter_mask[WOW_MASK_SIZE];
-    A_UINT8 wow_filter_pattern[WOW_PATTERN_SIZE];
+    u8 wow_valid_filter;
+    u8 wow_filter_id;
+    u8 wow_filter_size;
+    u8 wow_filter_offset;
+    u8 wow_filter_mask[WOW_MASK_SIZE];
+    u8 wow_filter_pattern[WOW_PATTERN_SIZE];
 } POSTPACK WOW_FILTER;
 
 
 typedef PREPACK struct {
-    A_UINT8 wow_valid_list;
-    A_UINT8 wow_list_id;
-    A_UINT8 wow_num_filters;
-    A_UINT8 wow_total_list_size;
+    u8 wow_valid_list;
+    u8 wow_list_id;
+    u8 wow_num_filters;
+    u8 wow_total_list_size;
     WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST];
 } POSTPACK WOW_FILTER_LIST;
 
 typedef PREPACK struct {
-    A_UINT8 valid_filter;
-    A_UINT8 mac_addr[ATH_MAC_LEN];
+    u8 valid_filter;
+    u8 mac_addr[ATH_MAC_LEN];
 } POSTPACK MAC_FILTER;
 
 
 typedef PREPACK struct {
-    A_UINT8 total_list_size;
-    A_UINT8 enable;
+    u8 total_list_size;
+    u8 enable;
     MAC_FILTER list[MAC_MAX_FILTERS_PER_LIST];
 } POSTPACK MAC_FILTER_LIST;
 
 #define MAX_IP_ADDRS  2
 typedef PREPACK struct {
-    A_UINT32 ips[MAX_IP_ADDRS];  /* IP in Network Byte Order */
+    u32 ips[MAX_IP_ADDRS];  /* IP in Network Byte Order */
 } POSTPACK WMI_SET_IP_CMD;
 
 typedef PREPACK struct {
-    A_BOOL awake;
-    A_BOOL asleep;
+    u32 awake;
+    u32 asleep;
 } POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD;
 
 typedef enum {
@@ -2726,40 +2740,40 @@ typedef enum {
 } WMI_WOW_FILTER;
 
 typedef PREPACK struct {
-    A_BOOL enable_wow;
+    u32 enable_wow;
     WMI_WOW_FILTER filter;
-    A_UINT16 hostReqDelay;
+    u16 hostReqDelay;
 } POSTPACK WMI_SET_WOW_MODE_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 filter_list_id;
+    u8 filter_list_id;
 } POSTPACK WMI_GET_WOW_LIST_CMD;
 
 /*
  * WMI_GET_WOW_LIST_CMD reply
  */
 typedef PREPACK struct {
-    A_UINT8     num_filters;     /* number of patterns in reply */
-    A_UINT8     this_filter_num; /*  this is filter # x of total num_filters */
-    A_UINT8     wow_mode;
-    A_UINT8     host_mode;
+    u8 num_filters;     /* number of patterns in reply */
+    u8 this_filter_num; /*  this is filter # x of total num_filters */
+    u8 wow_mode;
+    u8 host_mode;
     WOW_FILTER  wow_filters[1];
 } POSTPACK WMI_GET_WOW_LIST_REPLY;
 
 typedef PREPACK struct {
-    A_UINT8 filter_list_id;
-    A_UINT8 filter_size;
-    A_UINT8 filter_offset;
-    A_UINT8 filter[1];
+    u8 filter_list_id;
+    u8 filter_size;
+    u8 filter_offset;
+    u8 filter[1];
 } POSTPACK WMI_ADD_WOW_PATTERN_CMD;
 
 typedef PREPACK struct {
-    A_UINT16 filter_list_id;
-    A_UINT16 filter_id;
+    u16 filter_list_id;
+    u16 filter_id;
 } POSTPACK WMI_DEL_WOW_PATTERN_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 macaddr[ATH_MAC_LEN];
+    u8 macaddr[ATH_MAC_LEN];
 } POSTPACK WMI_SET_MAC_ADDRESS_CMD;
 
 /*
@@ -2769,11 +2783,11 @@ typedef PREPACK struct {
 #define WMI_AKMP_MULTI_PMKID_EN   0x000001
 
 typedef PREPACK struct {
-    A_UINT32    akmpInfo;
+    u32 akmpInfo;
 } POSTPACK WMI_SET_AKMP_PARAMS_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 pmkid[WMI_PMKID_LEN];
+    u8 pmkid[WMI_PMKID_LEN];
 } POSTPACK WMI_PMKID;
 
 /*
@@ -2782,7 +2796,7 @@ typedef PREPACK struct {
 #define WMI_MAX_PMKID_CACHE   8
 
 typedef PREPACK struct {
-    A_UINT32    numPMKID;
+    u32 numPMKID;
     WMI_PMKID   pmkidList[WMI_MAX_PMKID_CACHE];
 } POSTPACK WMI_SET_PMKID_LIST_CMD;
 
@@ -2791,34 +2805,34 @@ typedef PREPACK struct {
  * Following the Number of PMKIDs is the list of PMKIDs
  */
 typedef PREPACK struct {
-    A_UINT32    numPMKID;
-    A_UINT8     bssidList[ATH_MAC_LEN][1];
+    u32 numPMKID;
+    u8 bssidList[ATH_MAC_LEN][1];
     WMI_PMKID   pmkidList[1];
 } POSTPACK WMI_PMKID_LIST_REPLY;
 
 typedef PREPACK struct {
-    A_UINT16 oldChannel;
-    A_UINT32 newChannel;
+    u16 oldChannel;
+    u32 newChannel;
 } POSTPACK WMI_CHANNEL_CHANGE_EVENT;
 
 typedef PREPACK struct {
-    A_UINT32 version;
+    u32 version;
 } POSTPACK WMI_WLAN_VERSION_EVENT;
 
 
 /* WMI_ADDBA_REQ_EVENTID */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     win_sz;
-    A_UINT16    st_seq_no;
-    A_UINT8     status;         /* f/w response for ADDBA Req; OK(0) or failure(!=0) */
+    u8 tid;
+    u8 win_sz;
+    u16 st_seq_no;
+    u8 status;         /* f/w response for ADDBA Req; OK(0) or failure(!=0) */
 } POSTPACK WMI_ADDBA_REQ_EVENT;
 
 /* WMI_ADDBA_RESP_EVENTID */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     status;         /* OK(0), failure (!=0) */
-    A_UINT16    amsdu_sz;       /* Three values: Not supported(0), 3839, 8k */
+    u8 tid;
+    u8 status;         /* OK(0), failure (!=0) */
+    u16 amsdu_sz;       /* Three values: Not supported(0), 3839, 8k */
 } POSTPACK WMI_ADDBA_RESP_EVENT;
 
 /* WMI_DELBA_EVENTID
@@ -2826,9 +2840,9 @@ typedef PREPACK struct {
  * Host is notified of this
  */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     is_peer_initiator;
-    A_UINT16    reason_code;
+    u8 tid;
+    u8 is_peer_initiator;
+    u16 reason_code;
 } POSTPACK WMI_DELBA_EVENT;
 
 
@@ -2836,8 +2850,8 @@ typedef PREPACK struct {
 #define WAPI_REKEY_UCAST    1
 #define WAPI_REKEY_MCAST    2
 typedef PREPACK struct {
-    A_UINT8     type;
-    A_UINT8     macAddr[ATH_MAC_LEN];
+    u8 type;
+    u8 macAddr[ATH_MAC_LEN];
 } POSTPACK WMI_WAPIREKEY_EVENT;
 #endif
 
@@ -2847,8 +2861,8 @@ typedef PREPACK struct {
  * on each tid, in each direction
  */
 typedef PREPACK struct {
-    A_UINT16    tx_allow_aggr;  /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/
-    A_UINT16    rx_allow_aggr;  /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/
+    u16 tx_allow_aggr;  /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/
+    u16 rx_allow_aggr;  /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/
 } POSTPACK WMI_ALLOW_AGGR_CMD;
 
 /* WMI_ADDBA_REQ_CMDID
@@ -2856,7 +2870,7 @@ typedef PREPACK struct {
  * on the given tid
  */
 typedef PREPACK struct {
-    A_UINT8     tid;
+    u8 tid;
 } POSTPACK WMI_ADDBA_REQ_CMD;
 
 /* WMI_DELBA_REQ_CMDID
@@ -2864,8 +2878,8 @@ typedef PREPACK struct {
  * is_send_initiator indicates if it's or tx or rx side
  */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     is_sender_initiator;
+    u8 tid;
+    u8 is_sender_initiator;
 
 } POSTPACK WMI_DELBA_REQ_CMD;
 
@@ -2874,8 +2888,8 @@ typedef PREPACK struct {
 #define PEER_FIRST_NODE_JOIN_EVENT 0x10
 #define PEER_LAST_NODE_LEAVE_EVENT 0x11
 typedef PREPACK struct {
-    A_UINT8 eventCode;
-    A_UINT8 peerMacAddr[ATH_MAC_LEN];
+    u8 eventCode;
+    u8 peerMacAddr[ATH_MAC_LEN];
 } POSTPACK WMI_PEER_NODE_EVENT;
 
 #define IEEE80211_FRAME_TYPE_MGT          0x00
@@ -2893,21 +2907,21 @@ typedef PREPACK struct {
 #define TX_COMPLETE_STATUS_TIMEOUT 3
 #define TX_COMPLETE_STATUS_OTHER   4
 
-    A_UINT8 status; /* one of TX_COMPLETE_STATUS_... */
-    A_UINT8 pktID; /* packet ID to identify parent packet */
-    A_UINT8 rateIdx; /* rate index on successful transmission */
-    A_UINT8 ackFailures; /* number of ACK failures in tx attempt */
+    u8 status; /* one of TX_COMPLETE_STATUS_... */
+    u8 pktID; /* packet ID to identify parent packet */
+    u8 rateIdx; /* rate index on successful transmission */
+    u8 ackFailures; /* number of ACK failures in tx attempt */
 #if 0 /* optional params currently ommitted. */
-    A_UINT32 queueDelay; // usec delay measured Tx Start time - host delivery time
-    A_UINT32 mediaDelay; // usec delay measured ACK rx time - host delivery time
+    u32 queueDelay; // usec delay measured Tx Start time - host delivery time
+    u32 mediaDelay; // usec delay measured ACK rx time - host delivery time
 #endif
 } POSTPACK TX_COMPLETE_MSG_V1; /* version 1 of tx complete msg */
 
 typedef PREPACK struct {
-    A_UINT8 numMessages; /* number of tx comp msgs following this struct */
-    A_UINT8 msgLen; /* length in bytes for each individual msg following this struct */
-    A_UINT8 msgType; /* version of tx complete msg data following this struct */
-    A_UINT8 reserved; /* individual messages follow this header */
+    u8 numMessages; /* number of tx comp msgs following this struct */
+    u8 msgLen; /* length in bytes for each individual msg following this struct */
+    u8 msgType; /* version of tx complete msg data following this struct */
+    u8 reserved; /* individual messages follow this header */
 } POSTPACK WMI_TX_COMPLETE_EVENT;
 
 #define WMI_TXCOMPLETE_VERSION_1 (0x01)
@@ -2946,7 +2960,7 @@ typedef PREPACK struct {
 #define HIDDEN_SSID_FALSE   0
 #define HIDDEN_SSID_TRUE    1
 typedef PREPACK struct {
-    A_UINT8     hidden_ssid;
+    u8 hidden_ssid;
 } POSTPACK WMI_AP_HIDDEN_SSID_CMD;
 
 /*
@@ -2957,7 +2971,7 @@ typedef PREPACK struct {
 #define AP_ACL_DENY_MAC         0x02
 #define AP_ACL_RETAIN_LIST_MASK 0x80
 typedef PREPACK struct {
-    A_UINT8     policy;
+    u8 policy;
 } POSTPACK WMI_AP_ACL_POLICY_CMD;
 
 /*
@@ -2966,33 +2980,33 @@ typedef PREPACK struct {
 #define ADD_MAC_ADDR    1
 #define DEL_MAC_ADDR    2
 typedef PREPACK struct {
-    A_UINT8     action;
-    A_UINT8     index;
-    A_UINT8     mac[ATH_MAC_LEN];
-    A_UINT8     wildcard;
+    u8 action;
+    u8 index;
+    u8 mac[ATH_MAC_LEN];
+    u8 wildcard;
 } POSTPACK WMI_AP_ACL_MAC_CMD;
 
 typedef PREPACK struct {
-    A_UINT16    index;
-    A_UINT8     acl_mac[AP_ACL_SIZE][ATH_MAC_LEN];
-    A_UINT8     wildcard[AP_ACL_SIZE];
-    A_UINT8     policy;
+    u16 index;
+    u8 acl_mac[AP_ACL_SIZE][ATH_MAC_LEN];
+    u8 wildcard[AP_ACL_SIZE];
+    u8 policy;
 } POSTPACK WMI_AP_ACL;
 
 /*
  * Used with WMI_AP_SET_NUM_STA_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     num_sta;
+    u8 num_sta;
 } POSTPACK WMI_AP_SET_NUM_STA_CMD;
 
 /*
  * Used with WMI_AP_SET_MLME_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8    mac[ATH_MAC_LEN];
-    A_UINT16   reason;              /* 802.11 reason code */
-    A_UINT8    cmd;                 /* operation to perform */
+    u8 mac[ATH_MAC_LEN];
+    u16 reason;              /* 802.11 reason code */
+    u8 cmd;                 /* operation to perform */
 #define WMI_AP_MLME_ASSOC       1   /* associate station */
 #define WMI_AP_DISASSOC         2   /* disassociate station */
 #define WMI_AP_DEAUTH           3   /* deauthenticate station */
@@ -3001,108 +3015,108 @@ typedef PREPACK struct {
 } POSTPACK WMI_AP_SET_MLME_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 period;
+    u32 period;
 } POSTPACK WMI_AP_CONN_INACT_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 period_min;
-    A_UINT32 dwell_ms;
+    u32 period_min;
+    u32 dwell_ms;
 } POSTPACK WMI_AP_PROT_SCAN_TIME_CMD;
 
 typedef PREPACK struct {
-    A_BOOL flag;
-    A_UINT16 aid;
+    u32 flag;
+    u16 aid;
 } POSTPACK WMI_AP_SET_PVB_CMD;
 
 #define WMI_DISABLE_REGULATORY_CODE "FF"
 
 typedef PREPACK struct {
-    A_UCHAR countryCode[3];
+    u8 countryCode[3];
 } POSTPACK WMI_AP_SET_COUNTRY_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 dtim;
+    u8 dtim;
 } POSTPACK WMI_AP_SET_DTIM_CMD;
 
 typedef PREPACK struct {
-    A_UINT8  band; /* specifies which band to apply these values */
-    A_UINT8  enable; /* allows 11n to be disabled on a per band basis */    
-    A_UINT8  chan_width_40M_supported;
-    A_UINT8  short_GI_20MHz;
-    A_UINT8  short_GI_40MHz;
-    A_UINT8  intolerance_40MHz;
-    A_UINT8  max_ampdu_len_exp;
+    u8 band; /* specifies which band to apply these values */
+    u8 enable; /* allows 11n to be disabled on a per band basis */
+    u8 chan_width_40M_supported;
+    u8 short_GI_20MHz;
+    u8 short_GI_40MHz;
+    u8 intolerance_40MHz;
+    u8 max_ampdu_len_exp;
 } POSTPACK WMI_SET_HT_CAP_CMD;
 
 typedef PREPACK struct {
-    A_UINT8   sta_chan_width;
+    u8 sta_chan_width;
 } POSTPACK WMI_SET_HT_OP_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 rateMasks[8];
+    u32 rateMasks[8];
 } POSTPACK WMI_SET_TX_SELECT_RATES_CMD;
 
 typedef PREPACK struct {
-    A_UINT32    sgiMask;
-    A_UINT8     sgiPERThreshold;
+    u32 sgiMask;
+    u8 sgiPERThreshold;
 } POSTPACK WMI_SET_TX_SGI_PARAM_CMD;
 
 #define DEFAULT_SGI_MASK 0x08080000
 #define DEFAULT_SGI_PER 10
 
 typedef PREPACK struct {
-    A_UINT32 rateField; /* 1 bit per rate corresponding to index */
-    A_UINT8 id;
-    A_UINT8 shortTrys;
-    A_UINT8 longTrys;
-    A_UINT8 reserved; /* padding */
+    u32 rateField; /* 1 bit per rate corresponding to index */
+    u8 id;
+    u8 shortTrys;
+    u8 longTrys;
+    u8 reserved; /* padding */
 } POSTPACK WMI_SET_RATE_POLICY_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */
-    A_UINT8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 <default> */
-    A_UINT8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target <default> */
-    A_UINT8 reserved[1]; /* alignment */
+    u8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */
+    u8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 <default> */
+    u8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target <default> */
+    u8 reserved[1]; /* alignment */
 } POSTPACK WMI_RX_FRAME_FORMAT_CMD;
 
 
 typedef PREPACK struct {
-    A_UINT8 enable;     /* 1 == device operates in thin mode , 0 == normal mode <default> */
-    A_UINT8 reserved[3];
+    u8 enable;     /* 1 == device operates in thin mode , 0 == normal mode <default> */
+    u8 reserved[3];
 } POSTPACK WMI_SET_THIN_MODE_CMD;
 
 /* AP mode events */
 /* WMI_PS_POLL_EVENT */
 typedef PREPACK struct {
-    A_UINT16 aid;
+    u16 aid;
 } POSTPACK WMI_PSPOLL_EVENT;
 
 typedef PREPACK struct {
-    A_UINT32 tx_bytes;
-    A_UINT32 tx_pkts;
-    A_UINT32 tx_error;
-    A_UINT32 tx_discard;
-    A_UINT32 rx_bytes;
-    A_UINT32 rx_pkts;
-    A_UINT32 rx_error;
-    A_UINT32 rx_discard;
-    A_UINT32 aid;
+    u32 tx_bytes;
+    u32 tx_pkts;
+    u32 tx_error;
+    u32 tx_discard;
+    u32 rx_bytes;
+    u32 rx_pkts;
+    u32 rx_error;
+    u32 rx_discard;
+    u32 aid;
 } POSTPACK WMI_PER_STA_STAT;
 
 #define AP_GET_STATS    0
 #define AP_CLEAR_STATS  1
 
 typedef PREPACK struct {
-    A_UINT32            action;
+    u32 action;
     WMI_PER_STA_STAT    sta[AP_MAX_NUM_STA+1];
 } POSTPACK WMI_AP_MODE_STAT;
-#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(A_UINT32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT)))
+#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(u32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT)))
 
 #define AP_11BG_RATESET1        1
 #define AP_11BG_RATESET2        2
 #define DEF_AP_11BG_RATESET     AP_11BG_RATESET1
 typedef PREPACK struct {
-    A_UINT8 rateset;
+    u8 rateset;
 } POSTPACK WMI_AP_SET_11BG_RATESET_CMD;
 /*
  * End of AP mode definitions
diff --git a/drivers/staging/ath6kl/include/common/wmi_thin.h b/drivers/staging/ath6kl/include/common/wmi_thin.h
index 35391ed..0a8364c 100644
--- a/drivers/staging/ath6kl/include/common/wmi_thin.h
+++ b/drivers/staging/ath6kl/include/common/wmi_thin.h
@@ -101,9 +101,9 @@ typedef enum{
  *  disabled by default but can be enabled using this structure and the 
  *  WMI_THIN_CONFIG_CMDID. */
 typedef PREPACK struct {
-    A_UINT8     version; /* the versioned type of messages to use or 0 to disable */
-    A_UINT8     countThreshold; /* msg count threshold triggering a tx complete message */
-    A_UINT16    timeThreshold; /* timeout interval in MSEC triggering a tx complete message */       
+    u8 version; /* the versioned type of messages to use or 0 to disable */
+    u8 countThreshold; /* msg count threshold triggering a tx complete message */
+    u16 timeThreshold; /* timeout interval in MSEC triggering a tx complete message */
 } POSTPACK WMI_THIN_CONFIG_TXCOMPLETE;
 
 /* WMI_THIN_CONFIG_DECRYPT_ERR -- Used to configure behavior for received frames 
@@ -111,22 +111,22 @@ typedef PREPACK struct {
  *  without notification. Alternately, the MAC Header is forwarded to the host 
  *  with the failed status. */
 typedef PREPACK struct {
-    A_UINT8     enable; /* 1 == send decrypt errors to the host, 0 == don't */
-    A_UINT8     reserved[3]; /* align padding */
+    u8 enable; /* 1 == send decrypt errors to the host, 0 == don't */
+    u8 reserved[3]; /* align padding */
 } POSTPACK WMI_THIN_CONFIG_DECRYPT_ERR;
 
 /* WMI_THIN_CONFIG_TX_MAC_RULES -- Used to configure behavior for transmitted
  *  frames that require partial MAC header construction. These rules 
  *  are used by the target to indicate which fields need to be written. */
 typedef PREPACK struct {
-    A_UINT32    rules; /* combination of WMI_WRT_... values */     
+    u32 rules; /* combination of WMI_WRT_... values */
 } POSTPACK WMI_THIN_CONFIG_TX_MAC_RULES;
 
 /* WMI_THIN_CONFIG_RX_FILTER_RULES -- Used to configure behavior for received
  *  frames as to which frames should get forwarded to the host and which
  *  should get processed internally. */
 typedef PREPACK struct {
-    A_UINT32    rules; /* combination of WMI_FILT_... values */     
+    u32 rules; /* combination of WMI_FILT_... values */
 } POSTPACK WMI_THIN_CONFIG_RX_FILTER_RULES;
 
 /* WMI_THIN_CONFIG_CMD -- Used to contain some combination of the above
@@ -138,9 +138,9 @@ typedef PREPACK struct {
 #define WMI_THIN_CFG_DECRYPT        0x00000002
 #define WMI_THIN_CFG_MAC_RULES      0x00000004
 #define WMI_THIN_CFG_FILTER_RULES   0x00000008
-    A_UINT32    cfgField;   /* combination of WMI_THIN_CFG_... describes contents of config command */
-    A_UINT16    length;     /* length in bytes of appended sub-commands */        
-    A_UINT8     reserved[2];   /* align padding */
+    u32 cfgField;   /* combination of WMI_THIN_CFG_... describes contents of config command */
+    u16 length;     /* length in bytes of appended sub-commands */
+    u8 reserved[2];   /* align padding */
 } POSTPACK WMI_THIN_CONFIG_CMD;
 
 /* MIB Access Identifiers tailored for Symbian. */
@@ -176,35 +176,35 @@ enum {
 };
 
 typedef PREPACK struct {
-    A_UINT8 addr[ATH_MAC_LEN];
+    u8 addr[ATH_MAC_LEN];
 } POSTPACK WMI_THIN_MIB_STA_MAC;
 
 typedef PREPACK struct {
-    A_UINT32 time; // units == msec
+    u32 time; // units == msec
 } POSTPACK WMI_THIN_MIB_RX_LIFE_TIME;
 
 typedef PREPACK struct {
-    A_UINT8 enable; //1 = on, 0 = off
+    u8 enable; //1 = on, 0 = off
 } POSTPACK WMI_THIN_MIB_CTS_TO_SELF;
 
 typedef PREPACK struct {
-    A_UINT32 time; // units == usec
+    u32 time; // units == usec
 } POSTPACK WMI_THIN_MIB_SLOT_TIME;
 
 typedef PREPACK struct {
-    A_UINT16 length; //units == bytes
+    u16 length; //units == bytes
 } POSTPACK WMI_THIN_MIB_RTS_THRESHOLD;
 
 typedef PREPACK struct {
-    A_UINT8 type; // type of frame
-    A_UINT8 rate; // tx rate to be used (one of WMI_BIT_RATE)
-    A_UINT16 length; // num bytes following this structure as the template data
+    u8 type; // type of frame
+    u8 rate; // tx rate to be used (one of WMI_BIT_RATE)
+    u16 length; // num bytes following this structure as the template data
 } POSTPACK WMI_THIN_MIB_TEMPLATE_FRAME;
 
 typedef PREPACK struct {
 #define FRAME_FILTER_PROMISCUOUS 0x00000001
 #define FRAME_FILTER_BSSID       0x00000002
-    A_UINT32 filterMask; 
+    u32 filterMask;
 } POSTPACK WMI_THIN_MIB_RXFRAME_FILTER;
 
 
@@ -212,110 +212,110 @@ typedef PREPACK struct {
 #define IE_FILTER_TREATMENT_APPEAR 2
 
 typedef PREPACK struct {
-    A_UINT8 ie;
-    A_UINT8 treatment;
+    u8 ie;
+    u8 treatment;
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER_TABLE;
 
 typedef PREPACK struct {
-    A_UINT8 ie;
-    A_UINT8 treatment;
-    A_UINT8 oui[3];
-    A_UINT8 type;
-    A_UINT16 version;
+    u8 ie;
+    u8 treatment;
+    u8 oui[3];
+    u8 type;
+    u16 version;
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER_TABLE_OUI;
 
 typedef PREPACK struct {
-    A_UINT16 numElements;
-    A_UINT8 entrySize; // sizeof(WMI_THIN_MIB_BEACON_FILTER_TABLE) on host cpu may be 2 may be 4
-    A_UINT8 reserved;
+    u16 numElements;
+    u8 entrySize; // sizeof(WMI_THIN_MIB_BEACON_FILTER_TABLE) on host cpu may be 2 may be 4
+    u8 reserved;
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER_TABLE_HEADER; 
 
 typedef PREPACK struct {
-    A_UINT32 count; /* num beacons between deliveries */
-    A_UINT8 enable;
-    A_UINT8 reserved[3];
+    u32 count; /* num beacons between deliveries */
+    u8 enable;
+    u8 reserved[3];
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER;
 
 typedef PREPACK struct {
-    A_UINT32 count; /* num consec lost beacons after which send event */
+    u32 count; /* num consec lost beacons after which send event */
 } POSTPACK WMI_THIN_MIB_BEACON_LOST_COUNT;
 
 typedef PREPACK struct {
-    A_UINT8 rssi; /* the low threshold which can trigger an event warning */
-    A_UINT8 tolerance; /* the range above and below the threshold to prevent event flooding to the host. */
-    A_UINT8 count; /* the sample count of consecutive frames necessary to trigger an event. */
-    A_UINT8 reserved[1]; /* padding */
+    u8 rssi; /* the low threshold which can trigger an event warning */
+    u8 tolerance; /* the range above and below the threshold to prevent event flooding to the host. */
+    u8 count; /* the sample count of consecutive frames necessary to trigger an event. */
+    u8 reserved[1]; /* padding */
 } POSTPACK WMI_THIN_MIB_RSSI_THRESHOLD;
 
 
 typedef PREPACK struct {
-    A_UINT32 cap;
-    A_UINT32 rxRateField;
-    A_UINT32 beamForming;
-    A_UINT8 addr[ATH_MAC_LEN];
-    A_UINT8 enable;        
-    A_UINT8 stbc;
-    A_UINT8 maxAMPDU;    
-    A_UINT8 msduSpacing;
-    A_UINT8 mcsFeedback;   
-    A_UINT8 antennaSelCap;    
+    u32 cap;
+    u32 rxRateField;
+    u32 beamForming;
+    u8 addr[ATH_MAC_LEN];
+    u8 enable;
+    u8 stbc;
+    u8 maxAMPDU;
+    u8 msduSpacing;
+    u8 mcsFeedback;
+    u8 antennaSelCap;
 } POSTPACK WMI_THIN_MIB_HT_CAP;
 
 typedef PREPACK struct {
-    A_UINT32 infoField;
-    A_UINT32 basicRateField;
-    A_UINT8 protection;
-    A_UINT8 secondChanneloffset;
-    A_UINT8 channelWidth;
-    A_UINT8 reserved;
+    u32 infoField;
+    u32 basicRateField;
+    u8 protection;
+    u8 secondChanneloffset;
+    u8 channelWidth;
+    u8 reserved;
 } POSTPACK WMI_THIN_MIB_HT_OP;
 
 typedef PREPACK struct {
 #define SECOND_BEACON_PRIMARY   1
 #define SECOND_BEACON_EITHER    2
 #define SECOND_BEACON_SECONDARY 3
-    A_UINT8 cfg;
-    A_UINT8 reserved[3]; /* padding */
+    u8 cfg;
+    u8 reserved[3]; /* padding */
 } POSTPACK WMI_THIN_MIB_HT_2ND_BEACON;
 
 typedef PREPACK struct {
-    A_UINT8 txTIDField;
-    A_UINT8 rxTIDField;
-    A_UINT8 reserved[2]; /* padding */
+    u8 txTIDField;
+    u8 rxTIDField;
+    u8 reserved[2]; /* padding */
 } POSTPACK WMI_THIN_MIB_HT_BLOCK_ACK;
 
 typedef PREPACK struct {
-    A_UINT8 enableLong; // 1 == long preamble, 0 == short preamble
-    A_UINT8 reserved[3];
+    u8 enableLong; // 1 == long preamble, 0 == short preamble
+    u8 reserved[3];
 } POSTPACK WMI_THIN_MIB_PREAMBLE;
 
 typedef PREPACK struct {    
-    A_UINT16    length;     /* the length in bytes of the appended MIB data */
-    A_UINT8     mibID;      /* the ID of the MIB element being set */
-    A_UINT8     reserved; /* align padding */
+    u16 length;     /* the length in bytes of the appended MIB data */
+    u8 mibID;      /* the ID of the MIB element being set */
+    u8 reserved; /* align padding */
 } POSTPACK WMI_THIN_SET_MIB_CMD;
 
 typedef PREPACK struct {    
-    A_UINT8     mibID;      /* the ID of the MIB element being set */
-    A_UINT8     reserved[3]; /* align padding */
+    u8 mibID;      /* the ID of the MIB element being set */
+    u8 reserved[3]; /* align padding */
 } POSTPACK WMI_THIN_GET_MIB_CMD;
 
 typedef PREPACK struct {
-    A_UINT32    basicRateMask; /* bit mask of basic rates */
-    A_UINT32    beaconIntval; /* TUs */
-    A_UINT16    atimWindow; /* TUs */
-    A_UINT16    channel; /* frequency in Mhz */
-    A_UINT8     networkType; /* INFRA_NETWORK | ADHOC_NETWORK */
-    A_UINT8     ssidLength; /* 0 - 32 */
-    A_UINT8     probe;      /* != 0 : issue probe req at start */
-    A_UINT8     reserved;   /* alignment */    
-    A_UCHAR     ssid[WMI_MAX_SSID_LEN];    
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u32 basicRateMask; /* bit mask of basic rates */
+    u32 beaconIntval; /* TUs */
+    u16 atimWindow; /* TUs */
+    u16 channel; /* frequency in Mhz */
+    u8 networkType; /* INFRA_NETWORK | ADHOC_NETWORK */
+    u8 ssidLength; /* 0 - 32 */
+    u8 probe;      /* != 0 : issue probe req at start */
+    u8 reserved;   /* alignment */
+    u8     ssid[WMI_MAX_SSID_LEN];    
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_THIN_JOIN_CMD;
 
 typedef PREPACK struct {
-    A_UINT16 dtim; /* dtim interval in num beacons */
-    A_UINT16 aid; /* 80211 AID from Assoc resp */   
+    u16 dtim; /* dtim interval in num beacons */
+    u16 aid; /* 80211 AID from Assoc resp */
 } POSTPACK WMI_THIN_POST_ASSOC_CMD;
 
 typedef enum {
@@ -336,8 +336,8 @@ typedef enum {
 }WMI_THIN_JOIN_RESULT;
 
 typedef PREPACK struct {
-    A_UINT8 result; /* the result of the join cmd. one of WMI_THIN_JOIN_RESULT */
-    A_UINT8 reserved[3]; /* alignment */
+    u8 result; /* the result of the join cmd. one of WMI_THIN_JOIN_RESULT */
+    u8 reserved[3]; /* alignment */
 } POSTPACK WMI_THIN_JOIN_EVENT;
 
 #ifdef __cplusplus
diff --git a/drivers/staging/ath6kl/include/common/wmix.h b/drivers/staging/ath6kl/include/common/wmix.h
index 87046e3..5ebb828 100644
--- a/drivers/staging/ath6kl/include/common/wmix.h
+++ b/drivers/staging/ath6kl/include/common/wmix.h
@@ -55,7 +55,7 @@ extern "C" {
  * WMI_EVENT_ID=WMI_EXTENSION_EVENTID.
  */
 typedef PREPACK struct {
-    A_UINT32    commandId;
+    u32 commandId;
 } POSTPACK WMIX_CMD_HDR;
 
 typedef enum {
@@ -96,10 +96,10 @@ typedef enum {
  * DataSet Open Request Event
  */
 typedef PREPACK struct {
-    A_UINT32 dset_id;
-    A_UINT32 targ_dset_handle;  /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_fn;     /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_arg;    /* echo'ed, not used by Host, */
+    u32 dset_id;
+    u32 targ_dset_handle;  /* echo'ed, not used by Host, */
+    u32 targ_reply_fn;     /* echo'ed, not used by Host, */
+    u32 targ_reply_arg;    /* echo'ed, not used by Host, */
 } POSTPACK WMIX_DSETOPENREQ_EVENT;
 
 /*
@@ -107,7 +107,7 @@ typedef PREPACK struct {
  * DataSet Close Event
  */
 typedef PREPACK struct {
-    A_UINT32 access_cookie;
+    u32 access_cookie;
 } POSTPACK WMIX_DSETCLOSE_EVENT;
 
 /*
@@ -115,31 +115,31 @@ typedef PREPACK struct {
  * DataSet Data Request Event
  */
 typedef PREPACK struct {
-    A_UINT32 access_cookie;
-    A_UINT32 offset;
-    A_UINT32 length;
-    A_UINT32 targ_buf;         /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_fn;    /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_arg;   /* echo'ed, not used by Host, */
+    u32 access_cookie;
+    u32 offset;
+    u32 length;
+    u32 targ_buf;         /* echo'ed, not used by Host, */
+    u32 targ_reply_fn;    /* echo'ed, not used by Host, */
+    u32 targ_reply_arg;   /* echo'ed, not used by Host, */
 } POSTPACK WMIX_DSETDATAREQ_EVENT;
 
 typedef PREPACK struct {
-    A_UINT32              status;
-    A_UINT32              targ_dset_handle;
-    A_UINT32              targ_reply_fn;
-    A_UINT32              targ_reply_arg;
-    A_UINT32              access_cookie;
-    A_UINT32              size;
-    A_UINT32              version;
+    u32 status;
+    u32 targ_dset_handle;
+    u32 targ_reply_fn;
+    u32 targ_reply_arg;
+    u32 access_cookie;
+    u32 size;
+    u32 version;
 } POSTPACK WMIX_DSETOPEN_REPLY_CMD;
 
 typedef PREPACK struct {
-    A_UINT32              status;
-    A_UINT32              targ_buf;
-    A_UINT32              targ_reply_fn;
-    A_UINT32              targ_reply_arg;
-    A_UINT32              length;
-    A_UINT8               buf[1];
+    u32 status;
+    u32 targ_buf;
+    u32 targ_reply_fn;
+    u32 targ_reply_arg;
+    u32 length;
+    u8 buf[1];
 } POSTPACK WMIX_DSETDATA_REPLY_CMD;
 
 
@@ -160,10 +160,10 @@ typedef PREPACK struct {
  * clear/disable or disable/enable, results are undefined.
  */
 typedef PREPACK struct {
-    A_UINT32              set_mask;             /* pins to set */
-    A_UINT32              clear_mask;           /* pins to clear */
-    A_UINT32              enable_mask;          /* pins to enable for output */
-    A_UINT32              disable_mask;         /* pins to disable/tristate */
+    u32 set_mask;             /* pins to set */
+    u32 clear_mask;           /* pins to clear */
+    u32 enable_mask;          /* pins to enable for output */
+    u32 disable_mask;         /* pins to disable/tristate */
 } POSTPACK WMIX_GPIO_OUTPUT_SET_CMD;
 
 /* 
@@ -172,13 +172,13 @@ typedef PREPACK struct {
  * platform-dependent header.
  */
 typedef PREPACK struct {
-    A_UINT32              gpioreg_id;           /* GPIO register ID */
-    A_UINT32              value;                /* value to write */
+    u32 gpioreg_id;           /* GPIO register ID */
+    u32 value;                /* value to write */
 } POSTPACK WMIX_GPIO_REGISTER_SET_CMD;
 
 /* Get a GPIO register.  For debug/exceptional cases. */
 typedef PREPACK struct {
-    A_UINT32              gpioreg_id;           /* GPIO register to read */
+    u32 gpioreg_id;           /* GPIO register to read */
 } POSTPACK WMIX_GPIO_REGISTER_GET_CMD;
 
 /*
@@ -187,7 +187,7 @@ typedef PREPACK struct {
  * were delivered in an earlier WMIX_GPIO_INTR_EVENT message.
  */
 typedef PREPACK struct {
-    A_UINT32              ack_mask;             /* interrupts to acknowledge */
+    u32 ack_mask;             /* interrupts to acknowledge */
 } POSTPACK WMIX_GPIO_INTR_ACK_CMD;
 
 /*
@@ -197,8 +197,8 @@ typedef PREPACK struct {
  * use of a GPIO interrupt as a Data Valid signal for other GPIO pins.
  */
 typedef PREPACK struct {
-    A_UINT32              intr_mask;            /* pending GPIO interrupts */
-    A_UINT32              input_values;         /* recent GPIO input values */
+    u32 intr_mask;            /* pending GPIO interrupts */
+    u32 input_values;         /* recent GPIO input values */
 } POSTPACK WMIX_GPIO_INTR_EVENT;
 
 /*
@@ -217,8 +217,8 @@ typedef PREPACK struct {
  * simplify Host GPIO support.
  */
 typedef PREPACK struct {
-    A_UINT32              value;
-    A_UINT32              reg_id;
+    u32 value;
+    u32 reg_id;
 } POSTPACK WMIX_GPIO_DATA_EVENT;
 
 /*
@@ -230,8 +230,8 @@ typedef PREPACK struct {
  * Heartbeat Challenge Response command
  */
 typedef PREPACK struct {
-    A_UINT32              cookie;
-    A_UINT32              source;
+    u32 cookie;
+    u32 source;
 } POSTPACK WMIX_HB_CHALLENGE_RESP_CMD;
 
 /*
@@ -249,12 +249,12 @@ typedef PREPACK struct {
  */
 
 typedef PREPACK struct {
-    A_UINT32 period; /* Time (in 30.5us ticks) between samples */
-    A_UINT32 nbins;
+    u32 period; /* Time (in 30.5us ticks) between samples */
+    u32 nbins;
 } POSTPACK WMIX_PROF_CFG_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 addr;
+    u32 addr;
 } POSTPACK WMIX_PROF_ADDR_SET_CMD;
 
 /*
@@ -264,8 +264,8 @@ typedef PREPACK struct {
  *   count set to the corresponding count
  */
 typedef PREPACK struct {
-    A_UINT32              addr;
-    A_UINT32              count;
+    u32 addr;
+    u32 count;
 } POSTPACK WMIX_PROF_COUNT_EVENT;
 
 #ifndef ATH_TARGET
diff --git a/drivers/staging/ath6kl/include/common_drv.h b/drivers/staging/ath6kl/include/common_drv.h
index 8ebb93d..b606334 100644
--- a/drivers/staging/ath6kl/include/common_drv.h
+++ b/drivers/staging/ath6kl/include/common_drv.h
@@ -29,23 +29,23 @@
 /* structure that is the state information for the default credit distribution callback
  * drivers should instantiate (zero-init as well) this structure in their driver instance
  * and pass it as a context to the HTC credit distribution functions */
-typedef struct _COMMON_CREDIT_STATE_INFO {
+struct common_credit_state_info {
     int TotalAvailableCredits;      /* total credits in the system at startup */
     int CurrentFreeCredits;         /* credits available in the pool that have not been
                                        given out to endpoints */
-    HTC_ENDPOINT_CREDIT_DIST *pLowestPriEpDist;  /* pointer to the lowest priority endpoint dist struct */
-} COMMON_CREDIT_STATE_INFO;
+    struct htc_endpoint_credit_dist *pLowestPriEpDist;  /* pointer to the lowest priority endpoint dist struct */
+};
 
-typedef struct {
-    A_INT32 (*setupTransport)(void *ar);
+struct hci_transport_callbacks {
+    s32 (*setupTransport)(void *ar);
     void (*cleanupTransport)(void *ar);
-} HCI_TRANSPORT_CALLBACKS;
+};
 
-typedef struct {
+struct hci_transport_misc_handles {
    void *netDevice;
    void *hifDevice;
    void *htcHandle;
-} HCI_TRANSPORT_MISC_HANDLES;
+};
 
 /* HTC TX packet tagging definitions */
 #define AR6K_CONTROL_PKT_TAG    HTC_TX_PACKET_TAG_USER_DEFINED
@@ -64,42 +64,42 @@ extern "C" {
 #endif
 
 /* OS-independent APIs */
-A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo);
+int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo);
 
-A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,  A_UCHAR *data, A_UINT32 length);
+int ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,  u8 *data, u32 length);
 
-A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset);
+int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset);
 
-void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
+void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType);
 
-A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    MboxIsrYieldValue,
-                               A_UINT8     HtcControlBuffers);
+int ar6000_set_htc_params(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 MboxIsrYieldValue,
+                               u8 HtcControlBuffers);
 
-A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    TargetVersion);
+int ar6000_prepare_target(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 TargetVersion);
 
-A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
-                                     A_UINT32    TargetType,
-                                     A_UINT32    Flags);
+int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice,
+                                     u32 TargetType,
+                                     u32 Flags);
 
-void ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
+void ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType);
 
-A_UINT8 *ar6000_get_cust_data_buffer(A_UINT32 TargetType);
+u8 *ar6000_get_cust_data_buffer(u32 TargetType);
 
-A_STATUS ar6000_setBTState(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setBTState(void *context, u8 *pInBuf, u32 InBufSize);
 
-A_STATUS ar6000_setDevicePowerState(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setDevicePowerState(void *context, u8 *pInBuf, u32 InBufSize);
 
-A_STATUS ar6000_setWowMode(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setWowMode(void *context, u8 *pInBuf, u32 InBufSize);
 
-A_STATUS ar6000_setHostMode(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setHostMode(void *context, u8 *pInBuf, u32 InBufSize);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/dl_list.h b/drivers/staging/ath6kl/include/dl_list.h
index 110e1d8..13b1e69 100644
--- a/drivers/staging/ath6kl/include/dl_list.h
+++ b/drivers/staging/ath6kl/include/dl_list.h
@@ -32,10 +32,10 @@
          
 /* list functions */
 /* pointers for the list */
-typedef struct _DL_LIST {
-    struct _DL_LIST *pPrev;
-    struct _DL_LIST *pNext;
-}DL_LIST, *PDL_LIST;
+struct dl_list {
+	struct dl_list *pPrev;
+	struct dl_list *pNext;
+};
 /*
  * DL_LIST_INIT , initialize doubly linked list
 */
@@ -67,7 +67,7 @@ typedef struct _DL_LIST {
  */
 #define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset)  \
 {                                                       \
-    PDL_LIST  pTemp;                                     \
+    struct dl_list *  pTemp;                                     \
     pTemp = (pStart)->pNext;                            \
     while (pTemp != (pStart)) {                         \
         (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset);   \
@@ -78,7 +78,7 @@ typedef struct _DL_LIST {
 /*
  * DL_ListInsertTail - insert pAdd to the end of the list
 */
-static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
+static INLINE struct dl_list *DL_ListInsertTail(struct dl_list *pList, struct dl_list *pAdd) {
         /* insert at tail */
     pAdd->pPrev = pList->pPrev;
     pAdd->pNext = pList;
@@ -90,7 +90,7 @@ static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
 /*
  * DL_ListInsertHead - insert pAdd into the head of the list
 */
-static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
+static INLINE struct dl_list * DL_ListInsertHead(struct dl_list * pList, struct dl_list * pAdd) {
         /* insert at head */
     pAdd->pPrev = pList;
     pAdd->pNext = pList->pNext;
@@ -103,7 +103,7 @@ static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
 /*
  * DL_ListRemove - remove pDel from list
 */
-static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) {
+static INLINE struct dl_list * DL_ListRemove(struct dl_list * pDel) {
     pDel->pNext->pPrev = pDel->pPrev;
     pDel->pPrev->pNext = pDel->pNext;
         /* point back to itself just to be safe, incase remove is called again */
@@ -115,8 +115,8 @@ static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) {
 /*
  * DL_ListRemoveItemFromHead - get a list item from the head
 */
-static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
-    PDL_LIST pItem = NULL;
+static INLINE struct dl_list * DL_ListRemoveItemFromHead(struct dl_list * pList) {
+    struct dl_list * pItem = NULL;
     if (pList->pNext != pList) {
         pItem = pList->pNext;
             /* remove the first item from head */
@@ -125,8 +125,8 @@ static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
     return pItem;
 }
 
-static INLINE PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) {
-    PDL_LIST pItem = NULL;
+static INLINE struct dl_list * DL_ListRemoveItemFromTail(struct dl_list * pList) {
+    struct dl_list * pItem = NULL;
     if (pList->pPrev != pList) {
         pItem = pList->pPrev;
             /* remove the item from tail */
@@ -136,7 +136,7 @@ static INLINE PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) {
 }
 
 /* transfer src list items to the tail of the destination list */
-static INLINE void DL_ListTransferItemsToTail(PDL_LIST pDest, PDL_LIST pSrc) {
+static INLINE void DL_ListTransferItemsToTail(struct dl_list * pDest, struct dl_list * pSrc) {
         /* only concatenate if src is not empty */
     if (!DL_LIST_IS_EMPTY(pSrc)) {
             /* cut out circular list in src and re-attach to end of dest */
diff --git a/drivers/staging/ath6kl/include/dset_api.h b/drivers/staging/ath6kl/include/dset_api.h
index 0cc121f..fe901ba 100644
--- a/drivers/staging/ath6kl/include/dset_api.h
+++ b/drivers/staging/ath6kl/include/dset_api.h
@@ -39,23 +39,23 @@ extern "C" {
 #endif
 
 /* Called to send a DataSet Open Reply back to the Target. */
-A_STATUS wmi_dset_open_reply(struct wmi_t *wmip,
-                             A_UINT32 status,
-                             A_UINT32 access_cookie,
-                             A_UINT32 size,
-                             A_UINT32 version,
-                             A_UINT32 targ_handle,
-                             A_UINT32 targ_reply_fn,
-                             A_UINT32 targ_reply_arg);
+int wmi_dset_open_reply(struct wmi_t *wmip,
+                             u32 status,
+                             u32 access_cookie,
+                             u32 size,
+                             u32 version,
+                             u32 targ_handle,
+                             u32 targ_reply_fn,
+                             u32 targ_reply_arg);
 
 /* Called to send a DataSet Data Reply back to the Target. */
-A_STATUS wmi_dset_data_reply(struct wmi_t *wmip,
-                             A_UINT32 status,
-                             A_UINT8 *host_buf,
-                             A_UINT32 length,
-                             A_UINT32 targ_buf,
-                             A_UINT32 targ_reply_fn,
-                             A_UINT32 targ_reply_arg);
+int wmi_dset_data_reply(struct wmi_t *wmip,
+                             u32 status,
+                             u8 *host_buf,
+                             u32 length,
+                             u32 targ_buf,
+                             u32 targ_reply_fn,
+                             u32 targ_reply_arg);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/gpio_api.h b/drivers/staging/ath6kl/include/gpio_api.h
index 96a1503..6b4c547 100644
--- a/drivers/staging/ath6kl/include/gpio_api.h
+++ b/drivers/staging/ath6kl/include/gpio_api.h
@@ -28,32 +28,32 @@
 /*
  * Send a command to the Target in order to change output on GPIO pins.
  */
-A_STATUS wmi_gpio_output_set(struct wmi_t *wmip,
-                             A_UINT32 set_mask,
-                             A_UINT32 clear_mask,
-                             A_UINT32 enable_mask,
-                             A_UINT32 disable_mask);
+int wmi_gpio_output_set(struct wmi_t *wmip,
+                             u32 set_mask,
+                             u32 clear_mask,
+                             u32 enable_mask,
+                             u32 disable_mask);
 
 /*
  * Send a command to the Target requesting input state of GPIO pins.
  */
-A_STATUS wmi_gpio_input_get(struct wmi_t *wmip);
+int wmi_gpio_input_get(struct wmi_t *wmip);
 
 /*
  * Send a command to the Target to change the value of a GPIO register.
  */
-A_STATUS wmi_gpio_register_set(struct wmi_t *wmip,
-                               A_UINT32 gpioreg_id,
-                               A_UINT32 value);
+int wmi_gpio_register_set(struct wmi_t *wmip,
+                               u32 gpioreg_id,
+                               u32 value);
 
 /*
  * Send a command to the Target to fetch the value of a GPIO register.
  */
-A_STATUS wmi_gpio_register_get(struct wmi_t *wmip, A_UINT32 gpioreg_id);
+int wmi_gpio_register_get(struct wmi_t *wmip, u32 gpioreg_id);
 
 /*
  * Send a command to the Target, acknowledging some GPIO interrupts.
  */
-A_STATUS wmi_gpio_intr_ack(struct wmi_t *wmip, A_UINT32 ack_mask);
+int wmi_gpio_intr_ack(struct wmi_t *wmip, u32 ack_mask);
 
 #endif /* _GPIO_API_H_ */
diff --git a/drivers/staging/ath6kl/include/hci_transport_api.h b/drivers/staging/ath6kl/include/hci_transport_api.h
index b5157ea..5e903fa 100644
--- a/drivers/staging/ath6kl/include/hci_transport_api.h
+++ b/drivers/staging/ath6kl/include/hci_transport_api.h
@@ -43,9 +43,9 @@ typedef HTC_ENDPOINT_ID HCI_TRANSPORT_PACKET_TYPE;
 #define HCI_SET_PACKET_TYPE(pP,s)  (pP)->Endpoint = (s)
 
 /* callback when an HCI packet was completely sent */
-typedef void   (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, HTC_PACKET *);
+typedef void   (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, struct htc_packet *);
 /* callback when an HCI packet is received */
-typedef void   (*HCI_TRANSPORT_RECV_PKT)(void *, HTC_PACKET *);
+typedef void   (*HCI_TRANSPORT_RECV_PKT)(void *, struct htc_packet *);
 /* Optional receive buffer re-fill callback,
  * On some OSes (like Linux) packets are allocated from a global pool and indicated up
  * to the network stack.  The driver never gets the packets back from the OS.  For these OSes
@@ -68,7 +68,7 @@ typedef void   (*HCI_TRANSPORT_RECV_REFILL)(void *, HCI_TRANSPORT_PACKET_TYPE Ty
  * NOTE*** This callback is mutually exclusive with the the refill callback above.
  *
  * */
-typedef HTC_PACKET *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length);
+typedef struct htc_packet *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length);
 
 typedef enum _HCI_SEND_FULL_ACTION {
     HCI_SEND_FULL_KEEP = 0,  /* packet that overflowed should be kept in the queue */
@@ -77,21 +77,21 @@ typedef enum _HCI_SEND_FULL_ACTION {
 
 /* callback when an HCI send queue exceeds the caller's MaxSendQueueDepth threshold,
  * the callback must return the send full action to take (either DROP or KEEP) */
-typedef HCI_SEND_FULL_ACTION  (*HCI_TRANSPORT_SEND_FULL)(void *, HTC_PACKET *);
+typedef HCI_SEND_FULL_ACTION  (*HCI_TRANSPORT_SEND_FULL)(void *, struct htc_packet *);
 
-typedef struct {
+struct hci_transport_properties {
     int    HeadRoom;      /* number of bytes in front of HCI packet for header space */
     int    TailRoom;      /* number of bytes at the end of the HCI packet for tail space */
     int    IOBlockPad;    /* I/O block padding required (always a power of 2) */
-} HCI_TRANSPORT_PROPERTIES;
+};
 
-typedef struct _HCI_TRANSPORT_CONFIG_INFO {
+struct hci_transport_config_info {
     int      ACLRecvBufferWaterMark;     /* low watermark to trigger recv refill */
     int      EventRecvBufferWaterMark;   /* low watermark to trigger recv refill */  
     int      MaxSendQueueDepth;          /* max number of packets in the single send queue */
     void     *pContext;                  /* context for all callbacks */
-    void     (*TransportFailure)(void *pContext, A_STATUS Status); /* transport failure callback */
-    A_STATUS (*TransportReady)(HCI_TRANSPORT_HANDLE, HCI_TRANSPORT_PROPERTIES *,void *pContext); /* transport is ready */
+    void     (*TransportFailure)(void *pContext, int Status); /* transport failure callback */
+    int (*TransportReady)(HCI_TRANSPORT_HANDLE, struct hci_transport_properties *,void *pContext); /* transport is ready */
     void     (*TransportRemoved)(void *pContext);                  /* transport was removed */
         /* packet processing callbacks */
     HCI_TRANSPORT_SEND_PKT_COMPLETE    pHCISendComplete;
@@ -99,7 +99,7 @@ typedef struct _HCI_TRANSPORT_CONFIG_INFO {
     HCI_TRANSPORT_RECV_REFILL          pHCIPktRecvRefill;
     HCI_TRANSPORT_RECV_ALLOC           pHCIPktRecvAlloc;
     HCI_TRANSPORT_SEND_FULL            pHCISendFull;
-} HCI_TRANSPORT_CONFIG_INFO;
+};
 
 /* ------ Function Prototypes ------ */
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -113,7 +113,7 @@ typedef struct _HCI_TRANSPORT_CONFIG_INFO {
   @example:
   @see also: HCI_TransportDetach
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Detach from the HCI transport module
@@ -134,14 +134,14 @@ void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans);
   @input:  HciTrans - HCI transport handle
            pQueue - a queue holding one or more packets
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes:  user must supply HTC packets for capturing incomming HCI packets.  The caller
            must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
            macro. Each packet in the queue must be of the same type and length 
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
+int    HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Send an HCI packet packet
@@ -150,12 +150,12 @@ A_STATUS    HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKE
            pPacket - packet to send
            Synchronous - send the packet synchronously (blocking)
   @output:
-  @return: A_OK
+  @return: 0
   @notes:  Caller must initialize packet using SET_HTC_PACKET_INFO_TX() and
            HCI_SET_PACKET_TYPE() macros to prepare the packet. 
-           If Synchronous is set to FALSE the call is fully asynchronous.  On error or completion, 
+           If Synchronous is set to false the call is fully asynchronous.  On error or completion,
            the registered send complete callback will be called.
-           If Synchronous is set to TRUE, the call will block until the packet is sent, if the
+           If Synchronous is set to true, the call will block until the packet is sent, if the
            interface cannot send the packet within a 2 second timeout, the function will return 
            the failure code : A_EBUSY.
            
@@ -166,7 +166,7 @@ A_STATUS    HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKE
   @example:
   @see also: 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
+int    HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
 
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -187,13 +187,13 @@ void        HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans);
   @function name: HCI_TransportStart
   @input:  HciTrans - hci transport handle 
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes: HCI transport communication will begin, the caller can expect the arrival
           of HCI recv packets as soon as this call returns.
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
+int    HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Enable or Disable Asynchronous Recv
@@ -201,12 +201,12 @@ A_STATUS    HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
   @input:  HciTrans - hci transport handle 
            Enable - enable or disable asynchronous recv
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes: This API must be called when HCI recv is handled synchronously
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+int    HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Receive an event packet from the HCI transport synchronously using polling
@@ -215,15 +215,15 @@ A_STATUS    HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A
            pPacket - HTC packet to hold the recv data
            MaxPollMS - maximum polling duration in Milliseconds;
   @output: 
-  @return: A_OK on success
+  @return: 0 on success
   @notes: This API should be used only during HCI device initialization, the caller must call
-          HCI_TransportEnableDisableAsyncRecv with Enable=FALSE prior to using this API. 
+          HCI_TransportEnableDisableAsyncRecv with Enable=false prior to using this API.
           This API will only capture HCI Event packets.
   @example:
   @see also: HCI_TransportEnableDisableAsyncRecv
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans, 
-                                          HTC_PACKET           *pPacket,
+int    HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
+                                          struct htc_packet           *pPacket,
                                           int                  MaxPollMS);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -232,12 +232,12 @@ A_STATUS    HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
   @input:  HciTrans - hci transport handle 
            Baud - baud rate in bps
   @output: 
-  @return: A_OK on success
+  @return: 0 on success
   @notes: This API should be used only after HCI device initialization
   @example:
   @see also: 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
+int    HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Enable/Disable HCI Transport Power Management
@@ -245,12 +245,12 @@ A_STATUS    HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Bau
   @input:  HciTrans - hci transport handle 
            Enable - 1 = Enable, 0 = Disable
   @output: 
-  @return: A_OK on success
+  @return: 0 on success
   @notes: 
   @example:
   @see also: 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/hif.h b/drivers/staging/ath6kl/include/hif.h
index 2a08267..83650d5 100644
--- a/drivers/staging/ath6kl/include/hif.h
+++ b/drivers/staging/ath6kl/include/hif.h
@@ -38,7 +38,7 @@ extern "C" {
 
 
 typedef struct htc_callbacks HTC_CALLBACKS;
-typedef struct hif_device HIF_DEVICE;
+struct hif_device;
 
 /*
  * direction - Direction of transfer (HIF_READ/HIF_WRITE).
@@ -153,7 +153,7 @@ typedef enum {
  *
  *   HIF_DEVICE_GET_MBOX_ADDR
  *   input : none
- *   output : HIF_DEVICE_MBOX_INFO
+ *   output : struct hif_device_mbox_info
  *   notes: 
  *
  *   HIF_DEVICE_GET_PENDING_EVENTS_FUNC
@@ -190,7 +190,7 @@ typedef enum {
  *   HIF_DEVICE_GET_IRQ_YIELD_PARAMS
  * 
  *   input : none
- *   output : HIF_DEVICE_IRQ_YIELD_PARAMS
+ *   output : struct hif_device_irq_yield_params
  *   note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler.
  *   The DSR callback handler will exit after a fixed number of RX packets or events are processed.  
  *   This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY. 
@@ -203,7 +203,7 @@ typedef enum {
  *   
  *   HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT
  *   input : none
- *   output : HIF_DEVICE_SCATTER_SUPPORT_INFO
+ *   output : struct hif_device_scatter_support_info
  *   note:  This query checks if the HIF layer implements the SCATTER request interface.  Scatter requests
  *   allows upper layers to submit mailbox I/O operations using a list of buffers.  This is useful for
  *   multi-message transfers that can better utilize the bus interconnect.
@@ -211,7 +211,7 @@ typedef enum {
  * 
  *   HIF_DEVICE_GET_OS_DEVICE
  *   intput : none
- *   output : HIF_DEVICE_OS_DEVICE_INFO;
+ *   output : struct hif_device_os_device_info;
  *   note: On some operating systems, the HIF layer has a parent device object for the bus.  This object
  *         may be required to register certain types of logical devices.
  * 
@@ -223,10 +223,10 @@ typedef enum {
  * 
  */
 
-typedef struct {
-    A_UINT32    ExtendedAddress;  /* extended address for larger writes */  
-    A_UINT32    ExtendedSize;
-} HIF_MBOX_PROPERTIES;
+struct hif_mbox_properties {
+    u32 ExtendedAddress;  /* extended address for larger writes */
+    u32 ExtendedSize;
+};
 
 #define HIF_MBOX_FLAG_NO_BUNDLING   (1 << 0)   /* do not allow bundling over the mailbox */
 
@@ -235,19 +235,19 @@ typedef enum _MBOX_BUF_IF_TYPE {
     MBOX_BUS_IF_SPI = 1,    
 } MBOX_BUF_IF_TYPE;
 
-typedef struct {
-    A_UINT32 MboxAddresses[4];  /* must be first element for legacy HIFs that return the address in  
+struct hif_device_mbox_info {
+    u32 MboxAddresses[4];  /* must be first element for legacy HIFs that return the address in
                                    and ARRAY of 32-bit words */
     
         /* the following describe extended mailbox properties */
-    HIF_MBOX_PROPERTIES MboxProp[4];
+    struct hif_mbox_properties MboxProp[4];
         /* if the HIF supports the GMbox extended address region it can report it
          * here, some interfaces cannot support the GMBOX address range and not set this */
-    A_UINT32 GMboxAddress;  
-    A_UINT32 GMboxSize;
-    A_UINT32 Flags;             /* flags to describe mbox behavior or usage */
+    u32 GMboxAddress;
+    u32 GMboxSize;
+    u32 Flags;             /* flags to describe mbox behavior or usage */
     MBOX_BUF_IF_TYPE MboxBusIFType;   /* mailbox bus interface type */
-} HIF_DEVICE_MBOX_INFO;
+};
 
 typedef enum {
     HIF_DEVICE_IRQ_SYNC_ONLY,   /* for HIF implementations that require the DSR to process all
@@ -265,20 +265,19 @@ typedef enum {
                             */
 } HIF_DEVICE_POWER_CHANGE_TYPE;
 
-typedef struct {
+struct hif_device_irq_yield_params {
     int     RecvPacketYieldCount; /* max number of packets to force DSR to return */
-} HIF_DEVICE_IRQ_YIELD_PARAMS;
+};
 
 
-typedef struct _HIF_SCATTER_ITEM {
-    A_UINT8     *pBuffer;             /* CPU accessible address of buffer */
+struct hif_scatter_item {
+    u8 *pBuffer;             /* CPU accessible address of buffer */
     int          Length;              /* length of transfer to/from this buffer */
     void        *pCallerContexts[2];  /* space for caller to insert a context associated with this item */
-} HIF_SCATTER_ITEM;
-
-struct _HIF_SCATTER_REQ;
+};
 
-typedef void ( *HIF_SCATTER_COMP_CB)(struct _HIF_SCATTER_REQ *);
+struct hif_scatter_req;
+typedef void ( *HIF_SCATTER_COMP_CB)(struct hif_scatter_req *);
 
 typedef enum _HIF_SCATTER_METHOD {
     HIF_SCATTER_NONE = 0,
@@ -286,84 +285,84 @@ typedef enum _HIF_SCATTER_METHOD {
     HIF_SCATTER_DMA_BOUNCE,            /* Uses SG DMA but HIF layer uses an internal bounce buffer */    
 } HIF_SCATTER_METHOD;
 
-typedef struct _HIF_SCATTER_REQ {
-    DL_LIST             ListLink;           /* link management */
-    A_UINT32            Address;            /* address for the read/write operation */
-    A_UINT32            Request;            /* request flags */
-    A_UINT32            TotalLength;        /* total length of entire transfer */
-    A_UINT32            CallerFlags;        /* caller specific flags can be stored here */
+struct hif_scatter_req {
+    struct dl_list             ListLink;           /* link management */
+    u32 Address;            /* address for the read/write operation */
+    u32 Request;            /* request flags */
+    u32 TotalLength;        /* total length of entire transfer */
+    u32 CallerFlags;        /* caller specific flags can be stored here */
     HIF_SCATTER_COMP_CB CompletionRoutine;  /* completion routine set by caller */
-    A_STATUS            CompletionStatus;   /* status of completion */
+    int            CompletionStatus;   /* status of completion */
     void                *Context;           /* caller context for this request */
     int                 ValidScatterEntries;  /* number of valid entries set by caller */
     HIF_SCATTER_METHOD  ScatterMethod;        /* scatter method handled by HIF */  
     void                *HIFPrivate[4];     /* HIF private area */
-    A_UINT8             *pScatterBounceBuffer;  /* bounce buffer for upper layers to copy to/from */
-    HIF_SCATTER_ITEM    ScatterList[1];     /* start of scatter list */
-} HIF_SCATTER_REQ;
+    u8 *pScatterBounceBuffer;  /* bounce buffer for upper layers to copy to/from */
+    struct hif_scatter_item    ScatterList[1];     /* start of scatter list */
+};
 
-typedef HIF_SCATTER_REQ * ( *HIF_ALLOCATE_SCATTER_REQUEST)(HIF_DEVICE *device);
-typedef void ( *HIF_FREE_SCATTER_REQUEST)(HIF_DEVICE *device, HIF_SCATTER_REQ *request);
-typedef A_STATUS ( *HIF_READWRITE_SCATTER)(HIF_DEVICE *device, HIF_SCATTER_REQ *request);
+typedef struct hif_scatter_req * ( *HIF_ALLOCATE_SCATTER_REQUEST)(struct hif_device *device);
+typedef void ( *HIF_FREE_SCATTER_REQUEST)(struct hif_device *device, struct hif_scatter_req *request);
+typedef int ( *HIF_READWRITE_SCATTER)(struct hif_device *device, struct hif_scatter_req *request);
 
-typedef struct _HIF_DEVICE_SCATTER_SUPPORT_INFO {
+struct hif_device_scatter_support_info {
         /* information returned from HIF layer */
     HIF_ALLOCATE_SCATTER_REQUEST    pAllocateReqFunc;
     HIF_FREE_SCATTER_REQUEST        pFreeReqFunc;
     HIF_READWRITE_SCATTER           pReadWriteScatterFunc;    
     int                             MaxScatterEntries;
     int                             MaxTransferSizePerScatterReq;
-} HIF_DEVICE_SCATTER_SUPPORT_INFO;
+};
                       
-typedef struct {
+struct hif_device_os_device_info {
     void    *pOSDevice;
-} HIF_DEVICE_OS_DEVICE_INFO;
+};
                       
 #define HIF_MAX_DEVICES                 1
 
 struct htc_callbacks {
     void      *context;     /* context to pass to the dsrhandler
                                note : rwCompletionHandler is provided the context passed to HIFReadWrite  */
-    A_STATUS (* rwCompletionHandler)(void *rwContext, A_STATUS status);
-    A_STATUS (* dsrHandler)(void *context);
+    int (* rwCompletionHandler)(void *rwContext, int status);
+    int (* dsrHandler)(void *context);
 };
 
 typedef struct osdrv_callbacks {
     void      *context;     /* context to pass for all callbacks except deviceRemovedHandler 
                                the deviceRemovedHandler is only called if the device is claimed */
-    A_STATUS (* deviceInsertedHandler)(void *context, void *hif_handle);
-    A_STATUS (* deviceRemovedHandler)(void *claimedContext, void *hif_handle);
-    A_STATUS (* deviceSuspendHandler)(void *context);
-    A_STATUS (* deviceResumeHandler)(void *context);
-    A_STATUS (* deviceWakeupHandler)(void *context);  
-    A_STATUS (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config);  
+    int (* deviceInsertedHandler)(void *context, void *hif_handle);
+    int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle);
+    int (* deviceSuspendHandler)(void *context);
+    int (* deviceResumeHandler)(void *context);
+    int (* deviceWakeupHandler)(void *context);
+    int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config);
 } OSDRV_CALLBACKS;
 
 #define HIF_OTHER_EVENTS     (1 << 0)   /* other interrupts (non-Recv) are pending, host
                                            needs to read the register table to figure out what */
 #define HIF_RECV_MSG_AVAIL   (1 << 1)   /* pending recv packet */
 
-typedef struct _HIF_PENDING_EVENTS_INFO {
-    A_UINT32 Events;
-    A_UINT32 LookAhead;
-    A_UINT32 AvailableRecvBytes;
+struct hif_pending_events_info {
+    u32 Events;
+    u32 LookAhead;
+    u32 AvailableRecvBytes;
 #ifdef THREAD_X
-    A_UINT32 Polling;
-    A_UINT32 INT_CAUSE_REG;
+    u32 Polling;
+    u32 INT_CAUSE_REG;
 #endif
-} HIF_PENDING_EVENTS_INFO;
+};
 
     /* function to get pending events , some HIF modules use special mechanisms
      * to detect packet available and other interrupts */
-typedef A_STATUS ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE              *device,
-                                             HIF_PENDING_EVENTS_INFO *pEvents,
+typedef int ( *HIF_PENDING_EVENTS_FUNC)(struct hif_device              *device,
+                                             struct hif_pending_events_info *pEvents,
                                              void                    *AsyncContext);
 
-#define HIF_MASK_RECV    TRUE
-#define HIF_UNMASK_RECV  FALSE
+#define HIF_MASK_RECV    true
+#define HIF_UNMASK_RECV  false
     /* function to mask recv events */
-typedef A_STATUS ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE  *device,
-                                                A_BOOL      Mask,
+typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(struct hif_device  *device,
+                                                bool      Mask,
                                                 void        *AsyncContext);
 
 
@@ -372,19 +371,19 @@ typedef A_STATUS ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE  *device,
  * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer
  * 
  */
-A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks);
+int HIFInit(OSDRV_CALLBACKS *callbacks);
 
 /* This API claims the HIF device and provides a context for handling removal.
  * The device removal callback is only called when the OSDRV layer claims
  * a device.  The claimed context must be non-NULL */
-void HIFClaimDevice(HIF_DEVICE *device, void *claimedContext);
+void HIFClaimDevice(struct hif_device *device, void *claimedContext);
 /* release the claimed device */
-void HIFReleaseDevice(HIF_DEVICE *device);
+void HIFReleaseDevice(struct hif_device *device);
 
 /* This API allows the HTC layer to attach to the HIF device */
-A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks);
+int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks);
 /* This API detaches the HTC layer from the HIF device */
-void     HIFDetachHTC(HIF_DEVICE *device);
+void     HIFDetachHTC(struct hif_device *device);
 
 /*
  * This API is used to provide the read/write interface over the specific bus
@@ -398,19 +397,19 @@ void     HIFDetachHTC(HIF_DEVICE *device);
  * length - Amount of data to be transmitted or received.
  * request - Characterizes the attributes of the command.
  */
-A_STATUS
-HIFReadWrite(HIF_DEVICE    *device,
-             A_UINT32       address,
-             A_UCHAR       *buffer,
-             A_UINT32       length,
-             A_UINT32       request,
+int
+HIFReadWrite(struct hif_device    *device,
+             u32 address,
+             u8       *buffer,
+             u32 length,
+             u32 request,
              void          *context);
 
 /*
  * This can be initiated from the unload driver context when the OSDRV layer has no more use for
  * the device.
  */
-void HIFShutDownDevice(HIF_DEVICE *device);
+void HIFShutDownDevice(struct hif_device *device);
 
 /*
  * This should translate to an acknowledgment to the bus driver indicating that
@@ -419,11 +418,11 @@ void HIFShutDownDevice(HIF_DEVICE *device);
  * This should prevent the bus driver from raising an interrupt unless the
  * previous one has been serviced and acknowledged using the previous API.
  */
-void HIFAckInterrupt(HIF_DEVICE *device);
+void HIFAckInterrupt(struct hif_device *device);
 
-void HIFMaskInterrupt(HIF_DEVICE *device);
+void HIFMaskInterrupt(struct hif_device *device);
 
-void HIFUnMaskInterrupt(HIF_DEVICE *device);
+void HIFUnMaskInterrupt(struct hif_device *device);
  
 #ifdef THREAD_X
 /*
@@ -441,15 +440,15 @@ int HIFIRQEventNotify(void);
 int HIFRWCompleteEventNotify(void);
 #endif
 
-A_STATUS
-HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
-                   void *config, A_UINT32 configLen);
+int
+HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode,
+                   void *config, u32 configLen);
 
 /* 
  * This API wait for the remaining MBOX messages to be drained
  * This should be moved to HTC AR6K layer
  */
-A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device);
+int hifWaitForPendingRecv(struct hif_device *device);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/htc_api.h b/drivers/staging/ath6kl/include/htc_api.h
index b007051..1bc2488 100644
--- a/drivers/staging/ath6kl/include/htc_api.h
+++ b/drivers/staging/ath6kl/include/htc_api.h
@@ -41,31 +41,31 @@ extern "C" {
 
 typedef void *HTC_HANDLE;
 
-typedef A_UINT16 HTC_SERVICE_ID;
+typedef u16 HTC_SERVICE_ID;
 
-typedef struct _HTC_INIT_INFO {
+struct htc_init_info {
     void   *pContext;           /* context for target failure notification */
-    void   (*TargetFailure)(void *Instance, A_STATUS Status);
-} HTC_INIT_INFO;
+    void   (*TargetFailure)(void *Instance, int Status);
+};
 
 /* per service connection send completion */
-typedef void   (*HTC_EP_SEND_PKT_COMPLETE)(void *,HTC_PACKET *);
+typedef void   (*HTC_EP_SEND_PKT_COMPLETE)(void *,struct htc_packet *);
 /* per service connection callback when a plurality of packets have been sent
- * The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback)
+ * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback)
  * to hold a list of completed send packets.
  * If the handler cannot fully traverse the packet queue before returning, it should
  * transfer the items of the queue into the caller's private queue using:
  *   HTC_PACKET_ENQUEUE() */
-typedef void   (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,HTC_PACKET_QUEUE *);
+typedef void   (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,struct htc_packet_queue *);
 /* per service connection pkt received */
-typedef void   (*HTC_EP_RECV_PKT)(void *,HTC_PACKET *);
+typedef void   (*HTC_EP_RECV_PKT)(void *,struct htc_packet *);
 /* per service connection callback when a plurality of packets are received
- * The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback)
+ * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback)
  * to hold a list of recv packets.
  * If the handler cannot fully traverse the packet queue before returning, it should
  * transfer the items of the queue into the caller's private queue using:
  *   HTC_PACKET_ENQUEUE() */
-typedef void   (*HTC_EP_RECV_PKT_MULTIPLE)(void *,HTC_PACKET_QUEUE *);
+typedef void   (*HTC_EP_RECV_PKT_MULTIPLE)(void *,struct htc_packet_queue *);
 
 /* Optional per service connection receive buffer re-fill callback,
  * On some OSes (like Linux) packets are allocated from a global pool and indicated up
@@ -94,7 +94,7 @@ typedef void   (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint);
  * amount of "committed" memory used to receive packets.
  *  
  * */
-typedef HTC_PACKET *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length);
+typedef struct htc_packet *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length);
 
 typedef enum _HTC_SEND_FULL_ACTION {
     HTC_SEND_FULL_KEEP = 0,  /* packet that overflowed should be kept in the queue */
@@ -114,9 +114,9 @@ typedef enum _HTC_SEND_FULL_ACTION {
  * closed loop mechanism will prevent the network stack from overunning the NIC
  * The packet to keep or drop is passed for inspection to the registered handler the handler
  * must ONLY inspect the packet, it may not free or reclaim the packet. */
-typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_PACKET *pPacket);
+typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, struct htc_packet *pPacket);
 
-typedef struct _HTC_EP_CALLBACKS {
+struct htc_ep_callbacks {
     void                     *pContext;     /* context for each callback */
     HTC_EP_SEND_PKT_COMPLETE EpTxComplete;  /* tx completion callback for connected endpoint */
     HTC_EP_RECV_PKT          EpRecv;        /* receive callback for connected endpoint */
@@ -136,39 +136,39 @@ typedef struct _HTC_EP_CALLBACKS {
                                                        when the recv queue drops below this value 
                                                        if set to 0, the refill is only called when packets 
                                                        are empty */
-} HTC_EP_CALLBACKS;
+};
 
 /* service connection information */
-typedef struct _HTC_SERVICE_CONNECT_REQ {
+struct htc_service_connect_req {
     HTC_SERVICE_ID   ServiceID;                 /* service ID to connect to */
-    A_UINT16         ConnectionFlags;           /* connection flags, see htc protocol definition */
-    A_UINT8         *pMetaData;                 /* ptr to optional service-specific meta-data */
-    A_UINT8          MetaDataLength;            /* optional meta data length */
-    HTC_EP_CALLBACKS EpCallbacks;               /* endpoint callbacks */
+    u16 ConnectionFlags;           /* connection flags, see htc protocol definition */
+    u8 *pMetaData;                 /* ptr to optional service-specific meta-data */
+    u8 MetaDataLength;            /* optional meta data length */
+    struct htc_ep_callbacks EpCallbacks;               /* endpoint callbacks */
     int              MaxSendQueueDepth;         /* maximum depth of any send queue */
-    A_UINT32         LocalConnectionFlags;      /* HTC flags for the host-side (local) connection */
+    u32 LocalConnectionFlags;      /* HTC flags for the host-side (local) connection */
     unsigned int     MaxSendMsgSize;            /* override max message size in send direction */
-} HTC_SERVICE_CONNECT_REQ;
+};
 
 #define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0)  /* enable send bundle padding for this endpoint */
 
 /* service connection response information */
-typedef struct _HTC_SERVICE_CONNECT_RESP {
-    A_UINT8         *pMetaData;         /* caller supplied buffer to optional meta-data */
-    A_UINT8         BufferLength;       /* length of caller supplied buffer */
-    A_UINT8         ActualLength;       /* actual length of meta data */
+struct htc_service_connect_resp {
+    u8 *pMetaData;         /* caller supplied buffer to optional meta-data */
+    u8 BufferLength;       /* length of caller supplied buffer */
+    u8 ActualLength;       /* actual length of meta data */
     HTC_ENDPOINT_ID Endpoint;           /* endpoint to communicate over */
     unsigned int    MaxMsgLength;       /* max length of all messages over this endpoint */
-    A_UINT8         ConnectRespCode;    /* connect response code from target */
-} HTC_SERVICE_CONNECT_RESP;
+    u8 ConnectRespCode;    /* connect response code from target */
+};
 
 /* endpoint distribution structure */
-typedef struct _HTC_ENDPOINT_CREDIT_DIST {
-    struct _HTC_ENDPOINT_CREDIT_DIST *pNext;
-    struct _HTC_ENDPOINT_CREDIT_DIST *pPrev;
+struct htc_endpoint_credit_dist {
+    struct htc_endpoint_credit_dist *pNext;
+    struct htc_endpoint_credit_dist *pPrev;
     HTC_SERVICE_ID      ServiceID;          /* Service ID (set by HTC) */
     HTC_ENDPOINT_ID     Endpoint;           /* endpoint for this distribution struct (set by HTC) */
-    A_UINT32            DistFlags;          /* distribution flags, distribution function can
+    u32 DistFlags;          /* distribution flags, distribution function can
                                                set default activity using SET_EP_ACTIVE() macro */
     int                 TxCreditsNorm;      /* credits for normal operation, anything above this
                                                indicates the endpoint is over-subscribed, this field
@@ -195,9 +195,9 @@ typedef struct _HTC_ENDPOINT_CREDIT_DIST {
                                                or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
                                                that has non-zero credits to recover
                                               */
-} HTC_ENDPOINT_CREDIT_DIST;
+};
 
-#define HTC_EP_ACTIVE                            ((A_UINT32) (1u << 31))
+#define HTC_EP_ACTIVE                            ((u32) (1u << 31))
 
 /* macro to check if an endpoint has gone active, useful for credit
  * distributions */
@@ -216,11 +216,11 @@ typedef enum _HTC_CREDIT_DIST_REASON {
 } HTC_CREDIT_DIST_REASON;
 
 typedef void (*HTC_CREDIT_DIST_CALLBACK)(void                     *Context,
-                                         HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                                         struct htc_endpoint_credit_dist *pEPList,
                                          HTC_CREDIT_DIST_REASON   Reason);
 
 typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context,
-                                         HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                                         struct htc_endpoint_credit_dist *pEPList,
                                          int                      TotalCredits);
 
     /* endpoint statistics action */
@@ -231,31 +231,31 @@ typedef enum _HTC_ENDPOINT_STAT_ACTION {
 } HTC_ENDPOINT_STAT_ACTION;
 
     /* endpoint statistics */
-typedef struct _HTC_ENDPOINT_STATS {
-    A_UINT32  TxCreditLowIndications;  /* number of times the host set the credit-low flag in a send message on
+struct htc_endpoint_stats {
+    u32 TxCreditLowIndications;  /* number of times the host set the credit-low flag in a send message on
                                         this endpoint */
-    A_UINT32  TxIssued;               /* running count of total TX packets issued */
-    A_UINT32  TxPacketsBundled;       /* running count of TX packets that were issued in bundles */
-    A_UINT32  TxBundles;              /* running count of TX bundles that were issued */
-    A_UINT32  TxDropped;              /* tx packets that were dropped */
-    A_UINT32  TxCreditRpts;           /* running count of total credit reports received for this endpoint */
-    A_UINT32  TxCreditRptsFromRx;     /* credit reports received from this endpoint's RX packets */
-    A_UINT32  TxCreditRptsFromOther;  /* credit reports received from RX packets of other endpoints */
-    A_UINT32  TxCreditRptsFromEp0;    /* credit reports received from endpoint 0 RX packets */
-    A_UINT32  TxCreditsFromRx;        /* count of credits received via Rx packets on this endpoint */
-    A_UINT32  TxCreditsFromOther;     /* count of credits received via another endpoint */
-    A_UINT32  TxCreditsFromEp0;       /* count of credits received via another endpoint */
-    A_UINT32  TxCreditsConsummed;     /* count of consummed credits */
-    A_UINT32  TxCreditsReturned;      /* count of credits returned */
-    A_UINT32  RxReceived;             /* count of RX packets received */
-    A_UINT32  RxLookAheads;           /* count of lookahead records
+    u32 TxIssued;               /* running count of total TX packets issued */
+    u32 TxPacketsBundled;       /* running count of TX packets that were issued in bundles */
+    u32 TxBundles;              /* running count of TX bundles that were issued */
+    u32 TxDropped;              /* tx packets that were dropped */
+    u32 TxCreditRpts;           /* running count of total credit reports received for this endpoint */
+    u32 TxCreditRptsFromRx;     /* credit reports received from this endpoint's RX packets */
+    u32 TxCreditRptsFromOther;  /* credit reports received from RX packets of other endpoints */
+    u32 TxCreditRptsFromEp0;    /* credit reports received from endpoint 0 RX packets */
+    u32 TxCreditsFromRx;        /* count of credits received via Rx packets on this endpoint */
+    u32 TxCreditsFromOther;     /* count of credits received via another endpoint */
+    u32 TxCreditsFromEp0;       /* count of credits received via another endpoint */
+    u32 TxCreditsConsummed;     /* count of consummed credits */
+    u32 TxCreditsReturned;      /* count of credits returned */
+    u32 RxReceived;             /* count of RX packets received */
+    u32 RxLookAheads;           /* count of lookahead records
                                          found in messages received on this endpoint */
-    A_UINT32  RxPacketsBundled;       /* count of recv packets received in a bundle */                                     
-    A_UINT32  RxBundleLookAheads;     /* count of number of bundled lookaheads */
-    A_UINT32  RxBundleIndFromHdr;     /* count of the number of bundle indications from the HTC header */
-    A_UINT32  RxAllocThreshHit;       /* count of the number of times the recv allocation threshhold was hit */
-    A_UINT32  RxAllocThreshBytes;     /* total number of bytes */
-} HTC_ENDPOINT_STATS;
+    u32 RxPacketsBundled;       /* count of recv packets received in a bundle */
+    u32 RxBundleLookAheads;     /* count of number of bundled lookaheads */
+    u32 RxBundleIndFromHdr;     /* count of the number of bundle indications from the HTC header */
+    u32 RxAllocThreshHit;       /* count of the number of times the recv allocation threshhold was hit */
+    u32 RxAllocThreshBytes;     /* total number of bytes */
+};
 
 /* ------ Function Prototypes ------ */
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -269,7 +269,7 @@ typedef struct _HTC_ENDPOINT_STATS {
   @example:
   @see also: HTCDestroy
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-HTC_HANDLE HTCCreate(void *HifDevice, HTC_INIT_INFO *pInfo);
+HTC_HANDLE HTCCreate(void *HifDevice, struct htc_init_info *pInfo);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Get the underlying HIF device handle
   @function name: HTCGetHifDevice
@@ -319,7 +319,7 @@ void        HTCSetCreditDistribution(HTC_HANDLE               HTCHandle,
   @example:
   @see also: HTCConnectService
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCWaitTarget(HTC_HANDLE HTCHandle);
+int    HTCWaitTarget(HTC_HANDLE HTCHandle);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Start target service communications
   @function name: HTCStart
@@ -334,21 +334,21 @@ A_STATUS    HTCWaitTarget(HTC_HANDLE HTCHandle);
   @example:
   @see also: HTCConnectService
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCStart(HTC_HANDLE HTCHandle);
+int    HTCStart(HTC_HANDLE HTCHandle);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Add receive packet to HTC
   @function name: HTCAddReceivePkt
   @input:  HTCHandle - HTC handle
            pPacket - HTC receive packet to add
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes:  user must supply HTC packets for capturing incomming HTC frames.  The caller
            must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
            macro.
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
+int    HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Connect to an HTC service
   @function name: HTCConnectService
@@ -361,23 +361,23 @@ A_STATUS    HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
   @example:
   @see also: HTCStart
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCConnectService(HTC_HANDLE HTCHandle,
-                              HTC_SERVICE_CONNECT_REQ  *pReq,
-                              HTC_SERVICE_CONNECT_RESP *pResp);
+int    HTCConnectService(HTC_HANDLE HTCHandle,
+                              struct htc_service_connect_req  *pReq,
+                              struct htc_service_connect_resp *pResp);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Send an HTC packet
   @function name: HTCSendPkt
   @input:  HTCHandle - HTC handle
            pPacket - packet to send
   @output:
-  @return: A_OK
+  @return: 0
   @notes:  Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro.
            This interface is fully asynchronous.  On error, HTC SendPkt will
            call the registered Endpoint callback to cleanup the packet.
   @example:
   @see also: HTCFlushEndpoint
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
+int    HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Stop HTC service communications
   @function name: HTCStop
@@ -431,7 +431,7 @@ void        HTCDumpCreditStates(HTC_HANDLE HTCHandle);
   @function name: HTCIndicateActivityChange
   @input:  HTCHandle - HTC handle
            Endpoint - endpoint in which activity has changed
-           Active - TRUE if active, FALSE if it has become inactive
+           Active - true if active, false if it has become inactive
   @output:
   @return:
   @notes:  This triggers the registered credit distribution function to
@@ -441,7 +441,7 @@ void        HTCDumpCreditStates(HTC_HANDLE HTCHandle);
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 void        HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
                                       HTC_ENDPOINT_ID Endpoint,
-                                      A_BOOL          Active);
+                                      bool          Active);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Get endpoint statistics
@@ -452,9 +452,9 @@ void        HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
   @output:
            pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR)
 
-  @return: TRUE if statistics profiling is enabled, otherwise FALSE.
+  @return: true if statistics profiling is enabled, otherwise false.
 
-  @notes:  Statistics is a compile-time option and this function may return FALSE
+  @notes:  Statistics is a compile-time option and this function may return false
            if HTC is not compiled with profiling.
 
            The caller can specify the statistic "action" to take when sampling
@@ -469,10 +469,10 @@ void        HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_BOOL       HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
+bool       HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
                                       HTC_ENDPOINT_ID          Endpoint,
                                       HTC_ENDPOINT_STAT_ACTION Action,
-                                      HTC_ENDPOINT_STATS       *pStats);
+                                      struct htc_endpoint_stats       *pStats);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Unblock HTC message reception
@@ -499,10 +499,10 @@ void HTCUnblockRecv(HTC_HANDLE HTCHandle);
   @input:  HTCHandle - HTC handle
            pPktQueue - local queue holding packets to send
   @output:
-  @return: A_OK
+  @return: 0
   @notes:  Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro.
            The queue must only contain packets directed at the same endpoint.
-           Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the TX packets in FIFO order.
+           Caller supplies a pointer to an struct htc_packet_queue structure holding the TX packets in FIFO order.
            This API will remove the packets from the pkt queue and place them into the HTC Tx Queue
            and bundle messages where possible.
            The caller may allocate the pkt queue on the stack to hold the packets.           
@@ -511,7 +511,7 @@ void HTCUnblockRecv(HTC_HANDLE HTCHandle);
   @example:
   @see also: HTCFlushEndpoint
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue);
+int    HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Add multiple receive packets to HTC
@@ -519,18 +519,18 @@ A_STATUS    HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueu
   @input:  HTCHandle - HTC handle
            pPktQueue - HTC receive packet queue holding packets to add
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes:  user must supply HTC packets for capturing incomming HTC frames.  The caller
            must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
            macro. The queue must only contain recv packets for the same endpoint.
-           Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the recv packet.
+           Caller supplies a pointer to an struct htc_packet_queue structure holding the recv packet.
            This API will remove the packets from the pkt queue and place them into internal
            recv packet list.
            The caller may allocate the pkt queue on the stack to hold the packets.           
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue);
+int    HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Check if an endpoint is marked active
@@ -538,12 +538,12 @@ A_STATUS    HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPk
   @input:  HTCHandle - HTC handle
            Endpoint - endpoint to check for active state
   @output:
-  @return: returns TRUE if Endpoint is Active
+  @return: returns true if Endpoint is Active
   @notes:  
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_BOOL      HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
+bool      HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
                                 HTC_ENDPOINT_ID Endpoint);
 
 
@@ -564,9 +564,9 @@ int         HTCGetNumRecvBuffers(HTC_HANDLE      HTCHandle,
 /* internally used functions for testing... */
 void HTCEnableRecv(HTC_HANDLE HTCHandle);
 void HTCDisableRecv(HTC_HANDLE HTCHandle);
-A_STATUS HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
-                               A_UINT32     TimeoutInMs,
-                               A_BOOL      *pbIsRecvPending);
+int HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
+                               u32 TimeoutInMs,
+                               bool      *pbIsRecvPending);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/htc_packet.h b/drivers/staging/ath6kl/include/htc_packet.h
index 15175cf..ba65c34 100644
--- a/drivers/staging/ath6kl/include/htc_packet.h
+++ b/drivers/staging/ath6kl/include/htc_packet.h
@@ -42,37 +42,37 @@ typedef enum
     ENDPOINT_MAX,
 } HTC_ENDPOINT_ID;
 
-struct _HTC_PACKET;
+struct htc_packet;
 
-typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *);
+typedef void (* HTC_PACKET_COMPLETION)(void *,struct htc_packet *);
 
-typedef A_UINT16 HTC_TX_TAG;
+typedef u16 HTC_TX_TAG;
 
-typedef struct _HTC_TX_PACKET_INFO {
+struct htc_tx_packet_info {
     HTC_TX_TAG    Tag;            /* tag used to selective flush packets */
     int           CreditsUsed;    /* number of credits used for this TX packet (HTC internal) */
-    A_UINT8       SendFlags;      /* send flags (HTC internal) */
+    u8 SendFlags;      /* send flags (HTC internal) */
     int           SeqNo;          /* internal seq no for debugging (HTC internal) */
-} HTC_TX_PACKET_INFO;
+};
 
 #define HTC_TX_PACKET_TAG_ALL          0    /* a tag of zero is reserved and used to flush ALL packets */
 #define HTC_TX_PACKET_TAG_INTERNAL     1                                /* internal tags start here */
 #define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */
 
-typedef struct _HTC_RX_PACKET_INFO {
-    A_UINT32    ExpectedHdr;        /* HTC internal use */
-    A_UINT32    HTCRxFlags;         /* HTC internal use */
-    A_UINT32    IndicationFlags;    /* indication flags set on each RX packet indication */
-} HTC_RX_PACKET_INFO;
+struct htc_rx_packet_info {
+    u32 ExpectedHdr;        /* HTC internal use */
+    u32 HTCRxFlags;         /* HTC internal use */
+    u32 IndicationFlags;    /* indication flags set on each RX packet indication */
+};
 
 #define HTC_RX_FLAGS_INDICATE_MORE_PKTS  (1 << 0)   /* more packets on this endpoint are being fetched */
 
 /* wrapper around endpoint-specific packets */
-typedef struct _HTC_PACKET {
-    DL_LIST         ListLink;       /* double link */
+struct htc_packet {
+    struct dl_list         ListLink;       /* double link */
     void            *pPktContext;   /* caller's per packet specific context */
 
-    A_UINT8         *pBufferStart;  /* the true buffer start , the caller can
+    u8 *pBufferStart;  /* the true buffer start , the caller can
                                        store the real buffer start here.  In
                                        receive callbacks, the HTC layer sets pBuffer
                                        to the start of the payload past the header. This
@@ -85,20 +85,20 @@ typedef struct _HTC_PACKET {
      * points to the start of the HTC header but when returned
      * to the caller points to the start of the payload
      */
-    A_UINT8         *pBuffer;       /* payload start (RX/TX) */
-    A_UINT32        BufferLength;   /* length of buffer */
-    A_UINT32        ActualLength;   /* actual length of payload */
+    u8 *pBuffer;       /* payload start (RX/TX) */
+    u32 BufferLength;   /* length of buffer */
+    u32 ActualLength;   /* actual length of payload */
     HTC_ENDPOINT_ID Endpoint;       /* endpoint that this packet was sent/recv'd from */
-    A_STATUS        Status;         /* completion status */
+    int        Status;         /* completion status */
     union {
-        HTC_TX_PACKET_INFO  AsTx;   /* Tx Packet specific info */
-        HTC_RX_PACKET_INFO  AsRx;   /* Rx Packet specific info */
+        struct htc_tx_packet_info  AsTx;   /* Tx Packet specific info */
+        struct htc_rx_packet_info  AsRx;   /* Rx Packet specific info */
     } PktInfo;
 
     /* the following fields are for internal HTC use */
     HTC_PACKET_COMPLETION Completion;   /* completion */
     void                  *pContext;    /* HTC private completion context */
-} HTC_PACKET;
+};
 
 
 
@@ -139,10 +139,10 @@ typedef struct _HTC_PACKET {
 }
 
 /* HTC Packet Queueing Macros */
-typedef struct _HTC_PACKET_QUEUE {
-    DL_LIST     QueueHead;
+struct htc_packet_queue {
+    struct dl_list     QueueHead;
     int         Depth;    
-} HTC_PACKET_QUEUE;
+};
  
 /* initialize queue */
 #define INIT_HTC_PACKET_QUEUE(pQ)   \
@@ -165,11 +165,11 @@ typedef struct _HTC_PACKET_QUEUE {
 /* test if a queue is empty */
 #define HTC_QUEUE_EMPTY(pQ)       ((pQ)->Depth == 0)
 /* get packet at head without removing it */
-static INLINE HTC_PACKET *HTC_GET_PKT_AT_HEAD(HTC_PACKET_QUEUE *queue)   {
+static INLINE struct htc_packet *HTC_GET_PKT_AT_HEAD(struct htc_packet_queue *queue)   {
     if (queue->Depth == 0) {
         return NULL; 
     }  
-    return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),HTC_PACKET,ListLink);
+    return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),struct htc_packet,ListLink);
 }
 /* remove a packet from a queue, where-ever it is in the queue */
 #define HTC_PACKET_REMOVE(pQ,p)     \
@@ -179,21 +179,21 @@ static INLINE HTC_PACKET *HTC_GET_PKT_AT_HEAD(HTC_PACKET_QUEUE *queue)   {
 }
 
 /* dequeue an HTC packet from the head of the queue */
-static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE(HTC_PACKET_QUEUE *queue) {
-    DL_LIST    *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead);
+static INLINE struct htc_packet *HTC_PACKET_DEQUEUE(struct htc_packet_queue *queue) {
+    struct dl_list    *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead);
     if (pItem != NULL) {
         queue->Depth--;
-        return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink);
     }
     return NULL;
 }
 
 /* dequeue an HTC packet from the tail of the queue */
-static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE_TAIL(HTC_PACKET_QUEUE *queue) {
-    DL_LIST    *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead);
+static INLINE struct htc_packet *HTC_PACKET_DEQUEUE_TAIL(struct htc_packet_queue *queue) {
+    struct dl_list    *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead);
     if (pItem != NULL) {
         queue->Depth--;
-        return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink);
     }
     return NULL;
 }
@@ -220,7 +220,7 @@ static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE_TAIL(HTC_PACKET_QUEUE *queue) {
 }
     
 #define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \
-    ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), HTC_PACKET, ListLink) 
+    ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), struct htc_packet, ListLink) 
 
 #define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END
         
diff --git a/drivers/staging/ath6kl/include/target_reg_table.h b/drivers/staging/ath6kl/include/target_reg_table.h
index 901f923..e2225d5 100644
--- a/drivers/staging/ath6kl/include/target_reg_table.h
+++ b/drivers/staging/ath6kl/include/target_reg_table.h
@@ -30,48 +30,48 @@
 
 /*** WARNING : Add to the end of the TABLE! do not change the order ****/
 typedef struct targetdef_s {
-    A_UINT32 d_RTC_BASE_ADDRESS;
-    A_UINT32 d_SYSTEM_SLEEP_OFFSET;
-    A_UINT32 d_SYSTEM_SLEEP_DISABLE_LSB;
-    A_UINT32 d_SYSTEM_SLEEP_DISABLE_MASK;
-    A_UINT32 d_CLOCK_CONTROL_OFFSET;
-    A_UINT32 d_CLOCK_CONTROL_SI0_CLK_MASK;
-    A_UINT32 d_RESET_CONTROL_OFFSET;
-    A_UINT32 d_RESET_CONTROL_SI0_RST_MASK;
-    A_UINT32 d_GPIO_BASE_ADDRESS;
-    A_UINT32 d_GPIO_PIN0_OFFSET;
-    A_UINT32 d_GPIO_PIN1_OFFSET;
-    A_UINT32 d_GPIO_PIN0_CONFIG_MASK;
-    A_UINT32 d_GPIO_PIN1_CONFIG_MASK;
-    A_UINT32 d_SI_CONFIG_BIDIR_OD_DATA_LSB;
-    A_UINT32 d_SI_CONFIG_BIDIR_OD_DATA_MASK;
-    A_UINT32 d_SI_CONFIG_I2C_LSB;
-    A_UINT32 d_SI_CONFIG_I2C_MASK;
-    A_UINT32 d_SI_CONFIG_POS_SAMPLE_LSB;
-    A_UINT32 d_SI_CONFIG_POS_SAMPLE_MASK;
-    A_UINT32 d_SI_CONFIG_INACTIVE_CLK_LSB;
-    A_UINT32 d_SI_CONFIG_INACTIVE_CLK_MASK;
-    A_UINT32 d_SI_CONFIG_INACTIVE_DATA_LSB;
-    A_UINT32 d_SI_CONFIG_INACTIVE_DATA_MASK;
-    A_UINT32 d_SI_CONFIG_DIVIDER_LSB;
-    A_UINT32 d_SI_CONFIG_DIVIDER_MASK;
-    A_UINT32 d_SI_BASE_ADDRESS;
-    A_UINT32 d_SI_CONFIG_OFFSET;
-    A_UINT32 d_SI_TX_DATA0_OFFSET;
-    A_UINT32 d_SI_TX_DATA1_OFFSET;
-    A_UINT32 d_SI_RX_DATA0_OFFSET;
-    A_UINT32 d_SI_RX_DATA1_OFFSET;
-    A_UINT32 d_SI_CS_OFFSET;
-    A_UINT32 d_SI_CS_DONE_ERR_MASK;
-    A_UINT32 d_SI_CS_DONE_INT_MASK;
-    A_UINT32 d_SI_CS_START_LSB;
-    A_UINT32 d_SI_CS_START_MASK;
-    A_UINT32 d_SI_CS_RX_CNT_LSB;
-    A_UINT32 d_SI_CS_RX_CNT_MASK;
-    A_UINT32 d_SI_CS_TX_CNT_LSB;
-    A_UINT32 d_SI_CS_TX_CNT_MASK;
-    A_UINT32 d_BOARD_DATA_SZ;
-    A_UINT32 d_BOARD_EXT_DATA_SZ;
+    u32 d_RTC_BASE_ADDRESS;
+    u32 d_SYSTEM_SLEEP_OFFSET;
+    u32 d_SYSTEM_SLEEP_DISABLE_LSB;
+    u32 d_SYSTEM_SLEEP_DISABLE_MASK;
+    u32 d_CLOCK_CONTROL_OFFSET;
+    u32 d_CLOCK_CONTROL_SI0_CLK_MASK;
+    u32 d_RESET_CONTROL_OFFSET;
+    u32 d_RESET_CONTROL_SI0_RST_MASK;
+    u32 d_GPIO_BASE_ADDRESS;
+    u32 d_GPIO_PIN0_OFFSET;
+    u32 d_GPIO_PIN1_OFFSET;
+    u32 d_GPIO_PIN0_CONFIG_MASK;
+    u32 d_GPIO_PIN1_CONFIG_MASK;
+    u32 d_SI_CONFIG_BIDIR_OD_DATA_LSB;
+    u32 d_SI_CONFIG_BIDIR_OD_DATA_MASK;
+    u32 d_SI_CONFIG_I2C_LSB;
+    u32 d_SI_CONFIG_I2C_MASK;
+    u32 d_SI_CONFIG_POS_SAMPLE_LSB;
+    u32 d_SI_CONFIG_POS_SAMPLE_MASK;
+    u32 d_SI_CONFIG_INACTIVE_CLK_LSB;
+    u32 d_SI_CONFIG_INACTIVE_CLK_MASK;
+    u32 d_SI_CONFIG_INACTIVE_DATA_LSB;
+    u32 d_SI_CONFIG_INACTIVE_DATA_MASK;
+    u32 d_SI_CONFIG_DIVIDER_LSB;
+    u32 d_SI_CONFIG_DIVIDER_MASK;
+    u32 d_SI_BASE_ADDRESS;
+    u32 d_SI_CONFIG_OFFSET;
+    u32 d_SI_TX_DATA0_OFFSET;
+    u32 d_SI_TX_DATA1_OFFSET;
+    u32 d_SI_RX_DATA0_OFFSET;
+    u32 d_SI_RX_DATA1_OFFSET;
+    u32 d_SI_CS_OFFSET;
+    u32 d_SI_CS_DONE_ERR_MASK;
+    u32 d_SI_CS_DONE_INT_MASK;
+    u32 d_SI_CS_START_LSB;
+    u32 d_SI_CS_START_MASK;
+    u32 d_SI_CS_RX_CNT_LSB;
+    u32 d_SI_CS_RX_CNT_MASK;
+    u32 d_SI_CS_TX_CNT_LSB;
+    u32 d_SI_CS_TX_CNT_MASK;
+    u32 d_BOARD_DATA_SZ;
+    u32 d_BOARD_EXT_DATA_SZ;
 } TARGET_REGISTER_TABLE;
 
 #define BOARD_DATA_SZ_MAX 2048
diff --git a/drivers/staging/ath6kl/include/wlan_api.h b/drivers/staging/ath6kl/include/wlan_api.h
index f55a645..9eea587 100644
--- a/drivers/staging/ath6kl/include/wlan_api.h
+++ b/drivers/staging/ath6kl/include/wlan_api.h
@@ -35,48 +35,48 @@ struct ieee80211_node_table;
 struct ieee80211_frame;
 
 struct ieee80211_common_ie {
-    A_UINT16    ie_chan;
-    A_UINT8     *ie_tstamp;
-    A_UINT8     *ie_ssid;
-    A_UINT8     *ie_rates;
-    A_UINT8     *ie_xrates;
-    A_UINT8     *ie_country;
-    A_UINT8     *ie_wpa;
-    A_UINT8     *ie_rsn;
-    A_UINT8     *ie_wmm;
-    A_UINT8     *ie_ath;
-    A_UINT16    ie_capInfo;
-    A_UINT16    ie_beaconInt;
-    A_UINT8     *ie_tim;
-    A_UINT8     *ie_chswitch;
-    A_UINT8     ie_erp;
-    A_UINT8     *ie_wsc;
-    A_UINT8     *ie_htcap;
-    A_UINT8     *ie_htop;
+    u16 ie_chan;
+    u8 *ie_tstamp;
+    u8 *ie_ssid;
+    u8 *ie_rates;
+    u8 *ie_xrates;
+    u8 *ie_country;
+    u8 *ie_wpa;
+    u8 *ie_rsn;
+    u8 *ie_wmm;
+    u8 *ie_ath;
+    u16 ie_capInfo;
+    u16 ie_beaconInt;
+    u8 *ie_tim;
+    u8 *ie_chswitch;
+    u8 ie_erp;
+    u8 *ie_wsc;
+    u8 *ie_htcap;
+    u8 *ie_htop;
 #ifdef WAPI_ENABLE
-    A_UINT8     *ie_wapi;
+    u8 *ie_wapi;
 #endif
 };
 
 typedef struct bss {
-    A_UINT8                      ni_macaddr[6];
-    A_UINT8                      ni_snr;
-    A_INT16                      ni_rssi;
+    u8 ni_macaddr[6];
+    u8 ni_snr;
+    s16 ni_rssi;
     struct bss                   *ni_list_next;
     struct bss                   *ni_list_prev;
     struct bss                   *ni_hash_next;
     struct bss                   *ni_hash_prev;
     struct ieee80211_common_ie   ni_cie;
-    A_UINT8                     *ni_buf;
-    A_UINT16                     ni_framelen;
+    u8 *ni_buf;
+    u16 ni_framelen;
     struct ieee80211_node_table *ni_table;
-    A_UINT32                     ni_refcnt;
+    u32 ni_refcnt;
     int                          ni_scangen;
 
-    A_UINT32                     ni_tstamp;
-    A_UINT32                     ni_actcnt;
+    u32 ni_tstamp;
+    u32 ni_actcnt;
 #ifdef OS_ROAM_MANAGEMENT
-    A_UINT32                     ni_si_gen;
+    u32 ni_si_gen;
 #endif
 } bss_t;
 
@@ -85,8 +85,8 @@ typedef void wlan_node_iter_func(void *arg, bss_t *);
 bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size);
 void wlan_node_free(bss_t *ni);
 void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
-                const A_UINT8 *macaddr);
-bss_t *wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr);
+                const u8 *macaddr);
+bss_t *wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr);
 void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni);
 void wlan_free_allnodes(struct ieee80211_node_table *nt);
 void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
@@ -96,30 +96,30 @@ void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt);
 void wlan_node_table_reset(struct ieee80211_node_table *nt);
 void wlan_node_table_cleanup(struct ieee80211_node_table *nt);
 
-A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen,
+int wlan_parse_beacon(u8 *buf, int framelen,
                            struct ieee80211_common_ie *cie);
 
-A_UINT16 wlan_ieee2freq(int chan);
-A_UINT32 wlan_freq2ieee(A_UINT16 freq);
+u16 wlan_ieee2freq(int chan);
+u32 wlan_freq2ieee(u16 freq);
 
-void wlan_set_nodeage(struct ieee80211_node_table *nt, A_UINT32 nodeAge);
+void wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge);
 
 void
 wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt);
 
 bss_t *
-wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID);
+wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, bool bIsWPA2, bool bMatchSSID);
 
 void
 wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni);
 
-bss_t *wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid);
+bss_t *wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid);
 
 bss_t *
-wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp);
+wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/include/wmi_api.h b/drivers/staging/ath6kl/include/wmi_api.h
index 4a91543..c8583e0 100644
--- a/drivers/staging/ath6kl/include/wmi_api.h
+++ b/drivers/staging/ath6kl/include/wmi_api.h
@@ -69,26 +69,26 @@ void wmi_qos_state_init(struct wmi_t *wmip);
 void wmi_shutdown(struct wmi_t *wmip);
 HTC_ENDPOINT_ID wmi_get_control_ep(struct wmi_t * wmip);
 void wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid);
-A_UINT16  wmi_get_mapped_qos_queue(struct wmi_t *, A_UINT8);
-A_STATUS wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
-A_STATUS wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_BOOL bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,A_UINT8 metaVersion, void *pTxMetaS);
-A_STATUS wmi_dot3_2_dix(void *osbuf);
+u16 wmi_get_mapped_qos_queue(struct wmi_t *, u8 );
+int wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
+int wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS);
+int wmi_dot3_2_dix(void *osbuf);
 
-A_STATUS wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf);
-A_STATUS wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode);
+int wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf);
+int wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode);
 
-A_STATUS wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
-A_STATUS wmi_syncpoint(struct wmi_t *wmip);
-A_STATUS wmi_syncpoint_reset(struct wmi_t *wmip);
-A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 layer2Priority, A_BOOL wmmEnabled);
+int wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
+int wmi_syncpoint(struct wmi_t *wmip);
+int wmi_syncpoint_reset(struct wmi_t *wmip);
+u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled);
 
-A_UINT8 wmi_determine_userPriority (A_UINT8 *pkt, A_UINT32 layer2Pri);
+u8 wmi_determine_userPriority (u8 *pkt, u32 layer2Pri);
 
-A_STATUS wmi_control_rx(struct wmi_t *wmip, void *osbuf);
+int wmi_control_rx(struct wmi_t *wmip, void *osbuf);
 void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg);
 void wmi_free_allnodes(struct wmi_t *wmip);
-bss_t *wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
-void wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
+bss_t *wmi_find_node(struct wmi_t *wmip, const u8 *macaddr);
+void wmi_free_node(struct wmi_t *wmip, const u8 *macaddr);
 
 
 typedef enum {
@@ -99,340 +99,340 @@ typedef enum {
     END_WMIFLAG                     /* end marker */
 } WMI_SYNC_FLAG;
 
-A_STATUS wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
+int wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
                       WMI_SYNC_FLAG flag);
 
-A_STATUS wmi_connect_cmd(struct wmi_t *wmip,
+int wmi_connect_cmd(struct wmi_t *wmip,
                          NETWORK_TYPE netType,
                          DOT11_AUTH_MODE dot11AuthMode,
                          AUTH_MODE authMode,
                          CRYPTO_TYPE pairwiseCrypto,
-                         A_UINT8 pairwiseCryptoLen,
+                         u8 pairwiseCryptoLen,
                          CRYPTO_TYPE groupCrypto,
-                         A_UINT8 groupCryptoLen,
+                         u8 groupCryptoLen,
                          int ssidLength,
-                         A_UCHAR *ssid,
-                         A_UINT8 *bssid,
-                         A_UINT16 channel,
-                         A_UINT32 ctrl_flags);
-
-A_STATUS wmi_reconnect_cmd(struct wmi_t *wmip,
-                           A_UINT8 *bssid,
-                           A_UINT16 channel);
-A_STATUS wmi_disconnect_cmd(struct wmi_t *wmip);
-A_STATUS wmi_getrev_cmd(struct wmi_t *wmip);
-A_STATUS wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
-                           A_BOOL forceFgScan, A_BOOL isLegacy,
-                           A_UINT32 homeDwellTime, A_UINT32 forceScanInterval,
-                           A_INT8 numChan, A_UINT16 *channelList);
-A_STATUS wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
-                            A_UINT16 fg_end_sec, A_UINT16 bg_sec,
-                            A_UINT16 minact_chdw_msec,
-                            A_UINT16 maxact_chdw_msec, A_UINT16 pas_chdw_msec,
-                            A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
-                            A_UINT32 max_dfsch_act_time,
-                            A_UINT16 maxact_scan_per_ssid);
-A_STATUS wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask);
-A_STATUS wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
-                            A_UINT8 ssidLength, A_UCHAR *ssid);
-A_STATUS wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons);
-A_STATUS wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmisstime, A_UINT16 bmissbeacons);
-A_STATUS wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
-                           A_UINT8 ieLen, A_UINT8 *ieInfo);
-A_STATUS wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode);
-A_STATUS wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
-                            A_UINT16 atim_windows, A_UINT16 timeout_value);
-A_STATUS wmi_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time,
-                   A_UINT32 ps_period, A_UINT8 sleep_period);
-A_STATUS wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
-                           A_UINT16 psPollNum, A_UINT16 dtimPolicy,
-                           A_UINT16 wakup_tx_policy, A_UINT16 num_tx_to_wakeup,
-                           A_UINT16 ps_fail_event_policy);
-A_STATUS wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout);
-A_STATUS wmi_sync_cmd(struct wmi_t *wmip, A_UINT8 syncNumber);
-A_STATUS wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
-A_STATUS wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 streamID);
-A_STATUS wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8 subType, A_UINT16 rateMask);
-A_STATUS wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_INT32 ctlRate);
-A_STATUS wmi_get_bitrate_cmd(struct wmi_t *wmip);
-A_INT8   wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate, A_INT8 *rate_idx);
-A_STATUS wmi_get_regDomain_cmd(struct wmi_t *wmip);
-A_STATUS wmi_get_channelList_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
-                                   WMI_PHY_MODE mode, A_INT8 numChan,
-                                   A_UINT16 *channelList);
-
-A_STATUS wmi_set_snr_threshold_params(struct wmi_t *wmip,
+                         u8 *ssid,
+                         u8 *bssid,
+                         u16 channel,
+                         u32 ctrl_flags);
+
+int wmi_reconnect_cmd(struct wmi_t *wmip,
+                           u8 *bssid,
+                           u16 channel);
+int wmi_disconnect_cmd(struct wmi_t *wmip);
+int wmi_getrev_cmd(struct wmi_t *wmip);
+int wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
+                           u32 forceFgScan, u32 isLegacy,
+                           u32 homeDwellTime, u32 forceScanInterval,
+                           s8 numChan, u16 *channelList);
+int wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
+                            u16 fg_end_sec, u16 bg_sec,
+                            u16 minact_chdw_msec,
+                            u16 maxact_chdw_msec, u16 pas_chdw_msec,
+                            u8 shScanRatio, u8 scanCtrlFlags,
+                            u32 max_dfsch_act_time,
+                            u16 maxact_scan_per_ssid);
+int wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask);
+int wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
+                            u8 ssidLength, u8 *ssid);
+int wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons);
+int wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmisstime, u16 bmissbeacons);
+int wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
+                           u8 ieLen, u8 *ieInfo);
+int wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode);
+int wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
+                            u16 atim_windows, u16 timeout_value);
+int wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
+                   u32 ps_period, u8 sleep_period);
+int wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
+                           u16 psPollNum, u16 dtimPolicy,
+                           u16 wakup_tx_policy, u16 num_tx_to_wakeup,
+                           u16 ps_fail_event_policy);
+int wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout);
+int wmi_sync_cmd(struct wmi_t *wmip, u8 syncNumber);
+int wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
+int wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 streamID);
+int wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask);
+int wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate);
+int wmi_get_bitrate_cmd(struct wmi_t *wmip);
+s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx);
+int wmi_get_regDomain_cmd(struct wmi_t *wmip);
+int wmi_get_channelList_cmd(struct wmi_t *wmip);
+int wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
+                                   WMI_PHY_MODE mode, s8 numChan,
+                                   u16 *channelList);
+
+int wmi_set_snr_threshold_params(struct wmi_t *wmip,
                                        WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-A_STATUS wmi_set_rssi_threshold_params(struct wmi_t *wmip,
+int wmi_set_rssi_threshold_params(struct wmi_t *wmip,
                                         WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-A_STATUS wmi_clr_rssi_snr(struct wmi_t *wmip);
-A_STATUS wmi_set_lq_threshold_params(struct wmi_t *wmip,
+int wmi_clr_rssi_snr(struct wmi_t *wmip);
+int wmi_set_lq_threshold_params(struct wmi_t *wmip,
                                       WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd);
-A_STATUS wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold);
-A_STATUS wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status, A_UINT8 preamblePolicy);
+int wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold);
+int wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy);
 
-A_STATUS wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 bitmask);
+int wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 bitmask);
 
-A_STATUS wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie,
-                                    A_UINT32 source);
+int wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie,
+                                    u32 source);
 
-A_STATUS wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
-                                     A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
-                                     A_UINT32 valid);
+int wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
+                                     u16 tsr, bool rep, u16 size,
+                                     u32 valid);
 
-A_STATUS wmi_get_stats_cmd(struct wmi_t *wmip);
+int wmi_get_stats_cmd(struct wmi_t *wmip);
 
-A_STATUS wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex,
-                        CRYPTO_TYPE keyType, A_UINT8 keyUsage,
-                        A_UINT8 keyLength,A_UINT8 *keyRSC,
-                        A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, A_UINT8 *mac,
+int wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex,
+                        CRYPTO_TYPE keyType, u8 keyUsage,
+                        u8 keyLength,u8 *keyRSC,
+                        u8 *keyMaterial, u8 key_op_ctrl, u8 *mac,
                         WMI_SYNC_FLAG sync_flag);
-A_STATUS wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk);
-A_STATUS wmi_delete_krk_cmd(struct wmi_t *wmip);
-A_STATUS wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex);
-A_STATUS wmi_set_akmp_params_cmd(struct wmi_t *wmip,
+int wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk);
+int wmi_delete_krk_cmd(struct wmi_t *wmip);
+int wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex);
+int wmi_set_akmp_params_cmd(struct wmi_t *wmip,
                                  WMI_SET_AKMP_PARAMS_CMD *akmpParams);
-A_STATUS wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
+int wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
+int wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
                                 WMI_SET_PMKID_LIST_CMD *pmkInfo);
-A_STATUS wmi_abort_scan_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM);
-A_STATUS wmi_get_txPwr_cmd(struct wmi_t *wmip);
-A_STATUS wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid);
-A_STATUS wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex);
-A_STATUS wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en);
-A_STATUS wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
-                          A_BOOL set);
-A_STATUS wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT8 ac, A_UINT16 txop,
-                                   A_UINT8 eCWmin, A_UINT8 eCWmax,
-                                   A_UINT8 aifsn);
-A_STATUS wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
-                                  A_UINT8 trafficClass, A_UINT8 maxRetries,
-                                  A_UINT8 enableNotify);
-
-void wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid);
-
-A_STATUS wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
-A_STATUS wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType);
-A_STATUS wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
-                               A_UINT8 size);
-A_STATUS wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
+int wmi_abort_scan_cmd(struct wmi_t *wmip);
+int wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM);
+int wmi_get_txPwr_cmd(struct wmi_t *wmip);
+int wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid);
+int wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex);
+int wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en);
+int wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
+                          bool set);
+int wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop,
+                                   u8 eCWmin, u8 eCWmax,
+                                   u8 aifsn);
+int wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
+                                  u8 trafficClass, u8 maxRetries,
+                                  u8 enableNotify);
+
+void wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid);
+
+int wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
+int wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType);
+int wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
+                               u8 size);
+int wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
                             WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
-                            A_UINT8 size);
-
-A_STATUS wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode);
-A_STATUS wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
-                              A_UINT8 frmType,
-                              A_UINT8 *dstMacAddr,
-                              A_UINT8 *bssid,
-                              A_UINT16 optIEDataLen,
-                              A_UINT8 *optIEData);
-
-A_STATUS wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl);
-A_STATUS wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize);
-A_STATUS wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSpLen);
-A_UINT8  convert_userPriority_to_trafficClass(A_UINT8 userPriority);
-A_UINT8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
-A_STATUS wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance);
+                            u8 size);
+
+int wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode);
+int wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
+                              u8 frmType,
+                              u8 *dstMacAddr,
+                              u8 *bssid,
+                              u16 optIEDataLen,
+                              u8 *optIEData);
+
+int wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl);
+int wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize);
+int wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSpLen);
+u8 convert_userPriority_to_trafficClass(u8 userPriority);
+u8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
+int wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance);
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-A_STATUS wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32  len);
+int wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len);
 #endif
 
-A_STATUS wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status);
-A_STATUS wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
+int wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status);
+int wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
 
-A_STATUS wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd);
+int wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
 		                                WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
                                			WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *cmd);
 
-A_STATUS wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
                    		              WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
 		                                 WMI_SET_BTCOEX_A2DP_CONFIG_CMD* cmd);
 
 
-A_STATUS wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd);
+int wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd);
 
-A_STATUS wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd);
+int wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
+int wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
 							WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd);
 
-A_STATUS wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd);
+int wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd);
 
-A_STATUS wmi_get_btcoex_stats_cmd(struct wmi_t * wmip);
+int wmi_get_btcoex_stats_cmd(struct wmi_t * wmip);
 
-A_STATUS wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 sgiMask, A_UINT8 sgiPERThreshold);
+int wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold);
 
 /*
  *  This function is used to configure the fix rates mask to the target.
  */
-A_STATUS wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask);
-A_STATUS wmi_get_ratemask_cmd(struct wmi_t *wmip);
+int wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask);
+int wmi_get_ratemask_cmd(struct wmi_t *wmip);
 
-A_STATUS wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
+int wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode);
 
-A_STATUS wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
+int wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode);
 
-A_STATUS wmi_set_qos_supp_cmd(struct wmi_t *wmip,A_UINT8 status);
-A_STATUS wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
-A_STATUS wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
-A_STATUS wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode);
+int wmi_set_qos_supp_cmd(struct wmi_t *wmip,u8 status);
+int wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
+int wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
+int wmi_set_country(struct wmi_t *wmip, u8 *countryCode);
 
-A_STATUS wmi_get_keepalive_configured(struct wmi_t *wmip);
-A_UINT8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval);
+int wmi_get_keepalive_configured(struct wmi_t *wmip);
+u8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
+int wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval);
 
-A_STATUS wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType,
-                           A_UINT8 ieLen,A_UINT8 *ieInfo);
+int wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType,
+                           u8 ieLen,u8 *ieInfo);
 
-A_STATUS wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen);
+int wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen);
 
-A_INT32 wmi_get_rate(A_INT8 rateindex);
+s32 wmi_get_rate(s8 rateindex);
 
-A_STATUS wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd);
+int wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd);
 
 /*Wake on Wireless WMI commands*/
-A_STATUS wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
-A_STATUS wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
-A_STATUS wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
-A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
-                                 WMI_ADD_WOW_PATTERN_CMD *cmd, A_UINT8* pattern, A_UINT8* mask, A_UINT8 pattern_size);
-A_STATUS wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
+int wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
+int wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
+int wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
+int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
+                                 WMI_ADD_WOW_PATTERN_CMD *cmd, u8 *pattern, u8 *mask, u8 pattern_size);
+int wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
                                  WMI_DEL_WOW_PATTERN_CMD *cmd);
-A_STATUS wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status);
+int wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status);
 
-A_STATUS
-wmi_set_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR* buffer);
+int
+wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer);
 
-A_STATUS
-wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4);
+int
+wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4);
 
-A_STATUS
-wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4);
+int
+wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4);
 
-A_STATUS
-wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable);
+int
+wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable);
 
 bss_t *
-wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID);
+wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength, bool bIsWPA2, bool bMatchSSID);
 
 
 void
 wmi_node_return (struct wmi_t *wmip, bss_t *bss);
 
 void
-wmi_set_nodeage(struct wmi_t *wmip, A_UINT32 nodeAge);
+wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge);
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-A_STATUS wmi_prof_cfg_cmd(struct wmi_t *wmip, A_UINT32 period, A_UINT32 nbins);
-A_STATUS wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr);
-A_STATUS wmi_prof_start_cmd(struct wmi_t *wmip);
-A_STATUS wmi_prof_stop_cmd(struct wmi_t *wmip);
-A_STATUS wmi_prof_count_get_cmd(struct wmi_t *wmip);
+int wmi_prof_cfg_cmd(struct wmi_t *wmip, u32 period, u32 nbins);
+int wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr);
+int wmi_prof_start_cmd(struct wmi_t *wmip);
+int wmi_prof_stop_cmd(struct wmi_t *wmip);
+int wmi_prof_count_get_cmd(struct wmi_t *wmip);
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 #ifdef OS_ROAM_MANAGEMENT
 void wmi_scan_indication (struct wmi_t *wmip);
 #endif
 
-A_STATUS
+int
 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd);
 
-bss_t   *wmi_rm_current_bss (struct wmi_t *wmip, A_UINT8 *id);
-A_STATUS wmi_add_current_bss (struct wmi_t *wmip, A_UINT8 *id, bss_t *bss);
+bss_t   *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id);
+int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss);
 
 
 /*
  * AP mode
  */
-A_STATUS
+int
 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p);
 
-A_STATUS
-wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid);
+int
+wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid);
 
-A_STATUS
-wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta);
+int
+wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta);
 
-A_STATUS
-wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy);
+int
+wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy);
 
-A_STATUS
+int
 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *a);
 
-A_UINT8
-acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl);
+u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl);
 
-A_STATUS
-wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason);
+int
+wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason);
 
-A_STATUS
-wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag);
+int
+wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag);
 
-A_STATUS
-wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period);
+int
+wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period);
 
-A_STATUS
-wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell);
+int
+wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell);
 
-A_STATUS
-wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim);
+int
+wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim);
 
-A_STATUS
-wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset);
+int
+wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset);
 
-A_STATUS
+int
 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd);
 
-A_STATUS
-wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width);
+int
+wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width);
 
-A_STATUS
-wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz);
+int
+wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz);
 
-A_STATUS
-wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray);
+int
+wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray);
 
-A_STATUS
-wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid);
+int
+wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid);
 
-A_STATUS
-wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink);
+int
+wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink);
 
-A_STATUS
-wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask);
+int
+wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask);
 
-A_STATUS 
-wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion, A_BOOL rxDot11Hdr, A_BOOL defragOnHost);
+int
+wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, bool rxDot11Hdr, bool defragOnHost);
 
-A_STATUS 
-wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode);
+int
+wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode);
 
-A_STATUS
+int
 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence);
 
-A_STATUS
-wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk);
+int
+wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk);
 
-A_UINT16
-wmi_ieee2freq (int chan);
+int
+wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd);
 
-A_UINT32
-wmi_freq2ieee (A_UINT16 freq);
+u16 wmi_ieee2freq (int chan);
+
+u32 wmi_freq2ieee (u16 freq);
 
 bss_t *
-wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength,
-                   A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp);
+wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength,
+                   u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp);
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kconfig.c b/drivers/staging/ath6kl/miscdrv/ar3kconfig.c
index 83bc5be..4f18f43 100644
--- a/drivers/staging/ath6kl/miscdrv/ar3kconfig.c
+++ b/drivers/staging/ath6kl/miscdrv/ar3kconfig.c
@@ -47,24 +47,24 @@
 #define HCI_MAX_EVT_RECV_LENGTH             257
 #define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET  5
 
-A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
+int AthPSInitialize(struct ar3k_config_info *hdev);
 
-static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig,
-                               A_UINT8          *pBuffer,
+static int SendHCICommand(struct ar3k_config_info *pConfig,
+                               u8 *pBuffer,
                                int              Length)
 {
-    HTC_PACKET  *pPacket = NULL;
-    A_STATUS    status = A_OK;
+    struct htc_packet  *pPacket = NULL;
+    int    status = 0;
        
     do {   
         
-        pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));     
+        pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));     
         if (NULL == pPacket) {
             status = A_NO_MEMORY;
             break;    
         }       
         
-        A_MEMZERO(pPacket,sizeof(HTC_PACKET));      
+        A_MEMZERO(pPacket,sizeof(struct htc_packet));      
         SET_HTC_PACKET_INFO_TX(pPacket,
                                NULL,
                                pBuffer, 
@@ -73,9 +73,9 @@ static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig,
                                AR6K_CONTROL_PKT_TAG);
         
             /* issue synchronously */                                      
-        status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,TRUE);   
+        status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true);
         
-    } while (FALSE);
+    } while (false);
    
     if (pPacket != NULL) {
         A_FREE(pPacket);
@@ -84,36 +84,36 @@ static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig,
     return status;
 }
 
-static A_STATUS RecvHCIEvent(AR3K_CONFIG_INFO *pConfig,
-                             A_UINT8          *pBuffer,
+static int RecvHCIEvent(struct ar3k_config_info *pConfig,
+                             u8 *pBuffer,
                              int              *pLength)
 {
-    A_STATUS    status = A_OK; 
-    HTC_PACKET  *pRecvPacket = NULL;
+    int    status = 0;
+    struct htc_packet  *pRecvPacket = NULL;
     
     do {
                  
-        pRecvPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));
+        pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
         if (NULL == pRecvPacket) {
             status = A_NO_MEMORY;
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
             break;    
         }     
         
-        A_MEMZERO(pRecvPacket,sizeof(HTC_PACKET)); 
+        A_MEMZERO(pRecvPacket,sizeof(struct htc_packet)); 
          
         SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
         
         status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
                                                pRecvPacket,
                                                HCI_EVENT_RESP_TIMEOUTMS);
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
 
         *pLength = pRecvPacket->ActualLength;
         
-    } while (FALSE);
+    } while (false);
        
     if (pRecvPacket != NULL) {
         A_FREE(pRecvPacket);    
@@ -122,18 +122,18 @@ static A_STATUS RecvHCIEvent(AR3K_CONFIG_INFO *pConfig,
     return status;
 } 
     
-A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
-                                           A_UINT8          *pHCICommand,
+int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
+                                           u8 *pHCICommand,
                                            int              CmdLength,
-                                           A_UINT8          **ppEventBuffer,
-                                           A_UINT8          **ppBufferToFree)
+                                           u8 **ppEventBuffer,
+                                           u8 **ppBufferToFree)
 {
-    A_STATUS    status = A_OK;   
-    A_UINT8     *pBuffer = NULL;
-    A_UINT8     *pTemp;
+    int    status = 0;
+    u8 *pBuffer = NULL;
+    u8 *pTemp;
     int         length;
-    A_BOOL      commandComplete = FALSE;
-    A_UINT8     opCodeBytes[2];
+    bool      commandComplete = false;
+    u8 opCodeBytes[2];
                                
     do {
         
@@ -141,7 +141,7 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
         length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
         length += pConfig->pHCIProps->IOBlockPad;
                                      
-        pBuffer = (A_UINT8 *)A_MALLOC(length);        
+        pBuffer = (u8 *)A_MALLOC(length);
         if (NULL == pBuffer) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
             status = A_NO_MEMORY;
@@ -153,12 +153,12 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
         opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET];
         
             /* copy HCI command */
-        A_MEMCPY(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);         
+        memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);         
             /* send command */
         status = SendHCICommand(pConfig,
                                 pBuffer + pConfig->pHCIProps->HeadRoom,
                                 CmdLength);
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status));
             AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
             break;    
@@ -167,7 +167,7 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
             /* reuse buffer to capture command complete event */
         A_MEMZERO(pBuffer,length);
         status = RecvHCIEvent(pConfig,pBuffer,&length);        
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n"));
             AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
             break;    
@@ -177,7 +177,7 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
         if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) {
             if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) &&
                 (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) {
-                commandComplete = TRUE;    
+                commandComplete = true;
             }
         }
         
@@ -200,7 +200,7 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
             pBuffer = NULL;            
         }
         
-    } while (FALSE);
+    } while (false);
 
     if (pBuffer != NULL) {
         A_FREE(pBuffer);    
@@ -209,27 +209,27 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
     return status;    
 }
 
-static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
+static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig)
 {
-    A_STATUS    status = A_OK;
-    A_UINT8     hciBaudChangeCommand[] =  {0x0c,0xfc,0x2,0,0};
-    A_UINT16    baudVal; 
-    A_UINT8     *pEvent = NULL;
-    A_UINT8     *pBufferToFree = NULL;
+    int    status = 0;
+    u8 hciBaudChangeCommand[] =  {0x0c,0xfc,0x2,0,0};
+    u16 baudVal;
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
     
     do {
         
         if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
-            baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100);
-            hciBaudChangeCommand[3] = (A_UINT8)baudVal;
-            hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8);
+            baudVal = (u16)(pConfig->AR3KBaudRate / 100);
+            hciBaudChangeCommand[3] = (u8)baudVal;
+            hciBaudChangeCommand[4] = (u8)(baudVal >> 8);
             
             status = SendHCICommandWaitCommandComplete(pConfig,
                                                        hciBaudChangeCommand,
                                                        sizeof(hciBaudChangeCommand),
                                                        &pEvent,
                                                        &pBufferToFree);          
-            if (A_FAILED(status)) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));  
                 break;    
             }
@@ -255,7 +255,7 @@ static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
             /* Tell target to change UART baud rate for AR6K */
             status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     ("AR3K Config: failed to set scale and step values: %d \n", status));
                 break;    
@@ -265,7 +265,7 @@ static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
                     ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));            
         }
                 
-    } while (FALSE);
+    } while (false);
                         
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
@@ -274,13 +274,13 @@ static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
     return status;
 }
 
-static A_STATUS AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig)
+static int AR3KExitMinBoot(struct ar3k_config_info *pConfig)
 {
-    A_STATUS  status;
-    A_CHAR    exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+    int  status;
+    char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00};
-    A_UINT8   *pEvent = NULL;
-    A_UINT8   *pBufferToFree = NULL;
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
     
     status = SendHCICommandWaitCommandComplete(pConfig,
                                                exitMinBootCmd,
@@ -288,7 +288,7 @@ static A_STATUS AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig)
                                                &pEvent,
                                                &pBufferToFree);
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("AR3K Config: MinBoot exit command event status failed: %d \n", 
@@ -310,12 +310,12 @@ static A_STATUS AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig)
     return status;                                              
 }
                                  
-static A_STATUS AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig)
+static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig)
 {
-    A_STATUS status = A_OK;
-    A_UINT8 hciResetCommand[] = {0x03,0x0c,0x0};
-    A_UINT8 *pEvent = NULL;
-    A_UINT8 *pBufferToFree = NULL;
+    int status = 0;
+    u8 hciResetCommand[] = {0x03,0x0c,0x0};
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
 
     status = SendHCICommandWaitCommandComplete( pConfig,
                                                 hciResetCommand,
@@ -323,7 +323,7 @@ static A_STATUS AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig)
                                                 &pEvent,
                                                 &pBufferToFree );
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
     }
 
@@ -334,11 +334,11 @@ static A_STATUS AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig)
     return status;
 }
 
-static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
+static int AR3KEnableTLPM(struct ar3k_config_info *pConfig)
 {
-    A_STATUS  status;
+    int  status;
     /* AR3K vendor specific command for Host Wakeup Config */
-    A_CHAR    hostWakeupConfig[] = {0x31,0xFC,0x18,
+    char hostWakeupConfig[] = {0x31,0xFC,0x18,
                                     0x02,0x00,0x00,0x00,
                                     0x01,0x00,0x00,0x00,
                                     TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00,    //idle timeout in ms
@@ -346,7 +346,7 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
                                     TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00,    //wakeup timeout in ms
                                     0x00,0x00,0x00,0x00};
     /* AR3K vendor specific command for Target Wakeup Config */
-    A_CHAR    targetWakeupConfig[] = {0x31,0xFC,0x18,
+    char targetWakeupConfig[] = {0x31,0xFC,0x18,
                                       0x04,0x00,0x00,0x00,
                                       0x01,0x00,0x00,0x00,
                                       TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00,  //idle timeout in ms
@@ -354,20 +354,20 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
                                       TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00,  //wakeup timeout in ms
                                       0x00,0x00,0x00,0x00};
     /* AR3K vendor specific command for Host Wakeup Enable */
-    A_CHAR    hostWakeupEnable[] = {0x31,0xFC,0x4,
+    char hostWakeupEnable[] = {0x31,0xFC,0x4,
                                     0x01,0x00,0x00,0x00};
     /* AR3K vendor specific command for Target Wakeup Enable */
-    A_CHAR    targetWakeupEnable[] = {0x31,0xFC,0x4,
+    char targetWakeupEnable[] = {0x31,0xFC,0x4,
                                       0x06,0x00,0x00,0x00};
     /* AR3K vendor specific command for Sleep Enable */
-    A_CHAR    sleepEnable[] = {0x4,0xFC,0x1,
+    char sleepEnable[] = {0x4,0xFC,0x1,
                                0x1};
-    A_UINT8   *pEvent = NULL;
-    A_UINT8   *pBufferToFree = NULL;
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
     
     if (0 != pConfig->IdleTimeout) {
-        A_UINT8 idle_lsb = pConfig->IdleTimeout & 0xFF;
-        A_UINT8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
+        u8 idle_lsb = pConfig->IdleTimeout & 0xFF;
+        u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
         hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
         hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
     }
@@ -384,7 +384,7 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));    
         return status;
     }
@@ -399,7 +399,7 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));    
         return status;
     }
@@ -414,7 +414,7 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));    
         return status;
     }
@@ -429,7 +429,7 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));    
         return status;
     }
@@ -444,7 +444,7 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));    
     }
     
@@ -453,9 +453,9 @@ static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
     return status;                                              
 }
 
-A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
+int AR3KConfigure(struct ar3k_config_info *pConfig)
 {
-    A_STATUS        status = A_OK; 
+    int        status = 0;
         
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
                                 
@@ -467,21 +467,21 @@ A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
         }
         
             /* disable asynchronous recv while we issue commands and receive events synchronously */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
+        if (status) {
             break;    
         }
       
         if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
             status =  AR3KExitMinBoot(pConfig);   
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }    
         }
         
        
         /* Load patching and PST file if available*/
-        if (A_OK != AthPSInitialize(pConfig)) {
+        if (0 != AthPSInitialize(pConfig)) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
         }
 
@@ -491,7 +491,7 @@ A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
  	if (pConfig->Flags & 
                 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
             status = AR3KConfigureHCIBaud(pConfig);      
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
         }     
@@ -507,13 +507,13 @@ A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
         }
                
            /* re-enable asynchronous recv */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
+        if (status) {
             break;    
         }     
     
     
-    } while (FALSE);   
+    } while (false);
     
   
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
@@ -521,10 +521,10 @@ A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
     return status;
 }
 
-A_STATUS AR3KConfigureExit(void *config)
+int AR3KConfigureExit(void *config)
 {
-    A_STATUS        status = A_OK; 
-    AR3K_CONFIG_INFO *pConfig = (AR3K_CONFIG_INFO *)config;
+    int        status = 0;
+    struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config;
         
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
                                 
@@ -536,27 +536,27 @@ A_STATUS AR3KConfigureExit(void *config)
         }
         
             /* disable asynchronous recv while we issue commands and receive events synchronously */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
+        if (status) {
             break;    
         }
       
         if (pConfig->Flags & 
                 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
             status = AR3KConfigureHCIBaud(pConfig);      
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
         }
 
            /* re-enable asynchronous recv */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
+        if (status) {
             break;    
         }     
     
     
-    } while (FALSE);   
+    } while (false);
     
   
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
index 29b8ab4..8393efe 100644
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
+++ b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
@@ -41,41 +41,41 @@
  */
 typedef struct {
 
-    PSCmdPacket *HciCmdList;
-    A_UINT32  num_packets;
-    AR3K_CONFIG_INFO *dev;
+    struct ps_cmd_packet *HciCmdList;
+    u32 num_packets;
+    struct ar3k_config_info *dev;
 }HciCommandListParam;
 
-A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
-                                           A_UINT8          *pHCICommand,
+int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
+                                           u8 *pHCICommand,
                                            int              CmdLength,
-                                           A_UINT8          **ppEventBuffer,
-                                           A_UINT8          **ppBufferToFree);
+                                           u8 **ppEventBuffer,
+                                           u8 **ppBufferToFree);
 
-A_UINT32  Rom_Version;
-A_UINT32  Build_Version;
-extern A_BOOL BDADDR;
+u32 Rom_Version;
+u32 Build_Version;
+extern bool BDADDR;
 
-A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code);
-A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig);
+int getDeviceType(struct ar3k_config_info *pConfig, u32 *code);
+int ReadVersionInfo(struct ar3k_config_info *pConfig);
 #ifndef HCI_TRANSPORT_SDIO
 
 DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent);
 DECLARE_WAIT_QUEUE_HEAD(HciEvent);
-A_UCHAR *HciEventpacket;
+u8 *HciEventpacket;
 rwlock_t syncLock;
 wait_queue_t Eventwait;
 
-int PSHciWritepacket(struct hci_dev*,A_UCHAR* Data, A_UINT32 len);
+int PSHciWritepacket(struct hci_dev*,u8* Data, u32 len);
 extern char *bdaddr;
 #endif /* HCI_TRANSPORT_SDIO */
 
-A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type);
+int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type);
 
 int PSSendOps(void *arg);
 
 #ifdef BT_PS_DEBUG
-void Hci_log(A_UCHAR * log_string,A_UCHAR *data,A_UINT32 len)
+void Hci_log(u8 * log_string,u8 *data,u32 len)
 {
     int i;
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string));
@@ -91,9 +91,9 @@ void Hci_log(A_UCHAR * log_string,A_UCHAR *data,A_UINT32 len)
 
 
 
-A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev)
+int AthPSInitialize(struct ar3k_config_info *hdev)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     if(hdev == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n"));
         return A_ERROR;
@@ -118,7 +118,7 @@ A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev)
         remove_wait_queue(&PsCompleteEvent,&wait);
         return A_ERROR;
     }
-    wait_event_interruptible(PsCompleteEvent,(PSTagMode == FALSE));
+    wait_event_interruptible(PsCompleteEvent,(PSTagMode == false));
     set_current_state(TASK_RUNNING);
     remove_wait_queue(&PsCompleteEvent,&wait);
 
@@ -133,21 +133,21 @@ int PSSendOps(void *arg)
 {
     int i;
     int status = 0;
-    PSCmdPacket *HciCmdList; /* List storing the commands */
+    struct ps_cmd_packet *HciCmdList; /* List storing the commands */
     const struct firmware* firmware;
-    A_UINT32 numCmds;
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree;
+    u32 numCmds;
+    u8 *event;
+    u8 *bufferToFree;
     struct hci_dev *device;
-    A_UCHAR *buffer;
-    A_UINT32 len;
-    A_UINT32 DevType;
-    A_UCHAR *PsFileName;
-    A_UCHAR *patchFileName;
-    A_UCHAR *path = NULL;
-    A_UCHAR *config_path = NULL;
-    A_UCHAR config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
-    AR3K_CONFIG_INFO *hdev = (AR3K_CONFIG_INFO*)arg;
+    u8 *buffer;
+    u32 len;
+    u32 DevType;
+    u8 *PsFileName;
+    u8 *patchFileName;
+    u8 *path = NULL;
+    u8 *config_path = NULL;
+    u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
+    struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg;
     struct device *firmwareDev = NULL;
     status = 0;
     HciCmdList = NULL;
@@ -157,17 +157,17 @@ int PSSendOps(void *arg)
 #else 
     device = hdev;
     firmwareDev = &device->dev;
-    AthEnableSyncCommandOp(TRUE);    
+    AthEnableSyncCommandOp(true);
 #endif /* HCI_TRANSPORT_SDIO */
     /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different.
      */
 
-    path =(A_UCHAR *)A_MALLOC(MAX_FW_PATH_LEN);
+    path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN);
     if(path == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN));
         goto complete;
     }
-    config_path = (A_UCHAR *) A_MALLOC(MAX_FW_PATH_LEN);
+    config_path = (u8 *) A_MALLOC(MAX_FW_PATH_LEN);
     if(config_path == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN));
         goto complete;
@@ -214,7 +214,7 @@ int PSSendOps(void *arg)
         status = 1;
         goto complete;
     }
-    buffer = (A_UCHAR *)A_MALLOC(firmware->size);
+    buffer = (u8 *)A_MALLOC(firmware->size);
     if(buffer != NULL) {
     /* Copy the read file to a local Dynamic buffer */
         memcpy(buffer,firmware->data,firmware->size);
@@ -248,7 +248,7 @@ int PSSendOps(void *arg)
         if(NULL == firmware || firmware->size == 0) {
             status = 0;
         } else {
-            buffer = (A_UCHAR *)A_MALLOC(firmware->size);
+            buffer = (u8 *)A_MALLOC(firmware->size);
             if(buffer != NULL) {
                 /* Copy the read file to a local Dynamic buffer */
                 memcpy(buffer,firmware->data,firmware->size);
@@ -280,8 +280,8 @@ int PSSendOps(void *arg)
     HciCmdList[0].Hcipacket,
     HciCmdList[0].packetLen,
     &event,
-    &bufferToFree) == A_OK) {
-        if(ReadPSEvent(event) == A_OK) { /* Exit if the status is success */
+    &bufferToFree) == 0) {
+        if(ReadPSEvent(event) == 0) { /* Exit if the status is success */
             if(bufferToFree != NULL) {
                 A_FREE(bufferToFree);
                 }
@@ -309,8 +309,8 @@ int PSSendOps(void *arg)
         HciCmdList[i].Hcipacket,
         HciCmdList[i].packetLen,
         &event,
-        &bufferToFree) == A_OK) {
-            if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */
+        &bufferToFree) == 0) {
+            if(ReadPSEvent(event) != 0) { /* Exit if the status is success */
                 if(bufferToFree != NULL) {
                     A_FREE(bufferToFree);
                     }
@@ -326,7 +326,7 @@ int PSSendOps(void *arg)
         }
     }
 #ifdef HCI_TRANSPORT_SDIO
-	if(BDADDR == FALSE)
+	if(BDADDR == false)
 		if(hdev->bdaddr[0] !=0x00 ||
 		   hdev->bdaddr[1] !=0x00 ||
 		   hdev->bdaddr[2] !=0x00 ||
@@ -360,7 +360,7 @@ int PSSendOps(void *arg)
         	status = 1;
         	goto complete;
     	}
-	len = min(firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1);
+	len = min_t(size_t, firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1);
 	memcpy(config_bdaddr, firmware->data, len);
 	config_bdaddr[len] = '\0';
 	write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING);
@@ -368,8 +368,8 @@ int PSSendOps(void *arg)
 	}
 complete:
 #ifndef HCI_TRANSPORT_SDIO
-    AthEnableSyncCommandOp(FALSE);    
-    PSTagMode = FALSE;
+    AthEnableSyncCommandOp(false);
+    PSTagMode = false;
     wake_up_interruptible(&PsCompleteEvent);
 #endif /* HCI_TRANSPORT_SDIO */
     if(NULL != HciCmdList) {
@@ -389,23 +389,23 @@ complete:
  *  with a HCI Command Complete event.
  *  For HCI SDIO transport, this will be internally defined. 
  */
-A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
-                                           A_UINT8          *pHCICommand,
+int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
+                                           u8 *pHCICommand,
                                            int              CmdLength,
-                                           A_UINT8          **ppEventBuffer,
-                                           A_UINT8          **ppBufferToFree)
+                                           u8 **ppEventBuffer,
+                                           u8 **ppBufferToFree)
 {
     if(CmdLength == 0) {
         return A_ERROR;
     }
     Hci_log("COM Write -->",pHCICommand,CmdLength);
-    PSAcked = FALSE;
+    PSAcked = false;
     if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) {
         /* If the controller is not available, return Error */
         return A_ERROR;
     }
     //add_timer(&psCmdTimer);
-    wait_event_interruptible(HciEvent,(PSAcked == TRUE));
+    wait_event_interruptible(HciEvent,(PSAcked == true));
     if(NULL != HciEventpacket) {
         *ppEventBuffer = HciEventpacket;
         *ppBufferToFree = HciEventpacket;
@@ -415,25 +415,25 @@ A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 #endif /* HCI_TRANSPORT_SDIO */
 
-A_STATUS ReadPSEvent(A_UCHAR* Data){
+int ReadPSEvent(u8* Data){
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3]));
                                 
     if(Data[4] == 0xFC && Data[5] == 0x00)
     {
          switch(Data[3]){
              case 0x0B:
-                     return A_OK;
+                     return 0;
                  break;
                  case 0x0C:
                     /* Change Baudrate */
-                        return A_OK;    
+                        return 0;
                  break;  
                  case 0x04:
-                     return A_OK;
+                     return 0;
                  break;  
 		case 0x1E:
 			Rom_Version = Data[9];
@@ -445,7 +445,7 @@ A_STATUS ReadPSEvent(A_UCHAR* Data){
 			Build_Version = ((Build_Version << 8) |Data[12]);
 			Build_Version = ((Build_Version << 8) |Data[11]);
 			Build_Version = ((Build_Version << 8) |Data[10]);
-			return A_OK;
+			return 0;
 		break;
 
         
@@ -481,14 +481,14 @@ int str2ba(unsigned char *str_bdaddr,unsigned char *bdaddr)
 	return 0; 
 }
 
-A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type)
+int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type)
 {
-	A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 
+	u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 
 							0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree = NULL;
-    A_STATUS result = A_ERROR;
+    u8 *event;
+    u8 *bufferToFree = NULL;
+    int result = A_ERROR;
 	int inc,outc;
 
 	if (type == BDADDR_TYPE_STRING)
@@ -499,13 +499,13 @@ A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type)
 			bdaddr_cmd[outc] = bdaddr[inc];
 	}
 
-    if(A_OK == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
+    if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
 												sizeof(bdaddr_cmd),
 												&event,&bufferToFree)) {
 
         if(event[4] == 0xFC && event[5] == 0x00){
                if(event[3] == 0x0B){
-                result = A_OK;
+                result = 0;
             }
         }
 
@@ -516,13 +516,13 @@ A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type)
     return result;
 
 }
-A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig)
+int ReadVersionInfo(struct ar3k_config_info *pConfig)
 {
-    A_UINT8   hciCommand[] =  {0x1E,0xfc,0x00};
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree = NULL;
-    A_STATUS result = A_ERROR;
-    if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
+    u8 hciCommand[] =  {0x1E,0xfc,0x00};
+    u8 *event;
+    u8 *bufferToFree = NULL;
+    int result = A_ERROR;
+    if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
 	result = ReadPSEvent(event);
 
     }
@@ -531,19 +531,19 @@ A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig)
    }
     return result;
 }
-A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code)
+int getDeviceType(struct ar3k_config_info *pConfig, u32 *code)
 {
-    A_UINT8   hciCommand[] =  {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree = NULL;
-    A_UINT32 reg;
-    A_STATUS result = A_ERROR;
+    u8 hciCommand[] =  {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
+    u8 *event;
+    u8 *bufferToFree = NULL;
+    u32 reg;
+    int result = A_ERROR;
     *code = 0;
-    hciCommand[3] = (A_UINT8)(FPGA_REGISTER & 0xFF);
-    hciCommand[4] = (A_UINT8)((FPGA_REGISTER >> 8) & 0xFF);
-    hciCommand[5] = (A_UINT8)((FPGA_REGISTER >> 16) & 0xFF);
-    hciCommand[6] = (A_UINT8)((FPGA_REGISTER >> 24) & 0xFF); 
-    if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
+    hciCommand[3] = (u8)(FPGA_REGISTER & 0xFF);
+    hciCommand[4] = (u8)((FPGA_REGISTER >> 8) & 0xFF);
+    hciCommand[5] = (u8)((FPGA_REGISTER >> 16) & 0xFF);
+    hciCommand[6] = (u8)((FPGA_REGISTER >> 24) & 0xFF);
+    if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
 
         if(event[4] == 0xFC && event[5] == 0x00){
                switch(event[3]){
@@ -553,7 +553,7 @@ A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code)
                 reg = ((reg << 8) |event[7]);
                 reg = ((reg << 8) |event[6]);
                 *code = reg;
-                result = A_OK;
+                result = 0;
 
                 break;
                 case 0x06:
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h
index 4e5b7bf..d443513 100644
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h
+++ b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h
@@ -64,12 +64,12 @@
 
 
 #ifndef HCI_TRANSPORT_SDIO
-#define AR3K_CONFIG_INFO        struct hci_dev
+#define struct ar3k_config_info        struct hci_dev
 extern wait_queue_head_t HciEvent;
 extern wait_queue_t Eventwait;
-extern A_UCHAR *HciEventpacket;
+extern u8 *HciEventpacket;
 #endif /* #ifndef HCI_TRANSPORT_SDIO */
 
-A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
-A_STATUS ReadPSEvent(A_UCHAR* Data);
+int AthPSInitialize(struct ar3k_config_info *hdev);
+int ReadPSEvent(u8* Data);
 #endif /* __AR3KPSCONFIG_H */
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c
index 8dce054..94a0939 100644
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c
+++ b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c
@@ -87,53 +87,53 @@ enum eType {
 
 typedef struct tPsTagEntry
 {
-   A_UINT32   TagId;
-   A_UINT32   TagLen;
-   A_UINT8    *TagData;
+   u32 TagId;
+   u32 TagLen;
+   u8 *TagData;
 } tPsTagEntry, *tpPsTagEntry;
 
 typedef struct tRamPatch
 {
-   A_UINT16   Len;
-   A_UINT8    * Data;
+   u16 Len;
+   u8 *Data;
 } tRamPatch, *ptRamPatch;
 
 
 
-typedef struct ST_PS_DATA_FORMAT {
+struct st_ps_data_format {
    enum eType   eDataType;
-   A_BOOL    bIsArray;
-}ST_PS_DATA_FORMAT;
+   bool    bIsArray;
+};
 
-typedef struct ST_READ_STATUS {
+struct st_read_status {
     unsigned uTagID;
     unsigned uSection;
     unsigned uLineCount;
     unsigned uCharCount;
     unsigned uByteCount;
-}ST_READ_STATUS;
+};
 
 
 /* Stores the number of PS Tags */
-static A_UINT32 Tag_Count = 0;
+static u32 Tag_Count = 0;
 
 /* Stores the number of patch commands */
-static A_UINT32 Patch_Count = 0;
-static A_UINT32 Total_tag_lenght = 0;
-A_BOOL BDADDR = FALSE;
-A_UINT32      StartTagId;
+static u32 Patch_Count = 0;
+static u32 Total_tag_lenght = 0;
+bool BDADDR = false;
+u32 StartTagId;
 
 tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE];
 tRamPatch   RamPatch[MAX_NUM_PATCH_ENTRY];
 
 
-A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat);
-char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos);
-char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos);
-static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index);
+int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat);
+char AthReadChar(u8 *buffer, u32 len,u32 *pos);
+char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos);
+static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index);
 
 /* Function to reads the next character from the input buffer */
-char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos) 
+char AthReadChar(u8 *buffer, u32 len,u32 *pos)
 {
     char Ch;
     if(buffer == NULL || *pos >=len )
@@ -146,7 +146,7 @@ char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos)
     }
 }
 /* PS parser helper function */
-unsigned int uGetInputDataFormat(char* pCharLine, ST_PS_DATA_FORMAT *pstFormat) 
+unsigned int uGetInputDataFormat(char *pCharLine, struct st_ps_data_format *pstFormat)
 {
     if(pCharLine[0] != '[') {
         pstFormat->eDataType = eHex;
@@ -286,7 +286,7 @@ unsigned int uGetInputDataFormat(char* pCharLine, ST_PS_DATA_FORMAT *pstFormat)
     }
 }
 
-unsigned int uReadDataInSection(char *pCharLine, ST_PS_DATA_FORMAT stPS_DataFormat)
+unsigned int uReadDataInSection(char *pCharLine, struct st_ps_data_format stPS_DataFormat)
 {
     char *pTokenPtr = pCharLine;
 
@@ -315,20 +315,20 @@ unsigned int uReadDataInSection(char *pCharLine, ST_PS_DATA_FORMAT stPS_DataForm
         return (0x0FFF);
     }
 }
-A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat)
+int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat)
 {
-   char     *Buffer;
-   char     *pCharLine;
-   A_UINT8    TagCount;
-   A_UINT16   ByteCount;
-   A_UINT8    ParseSection=RAM_PS_SECTION;
-   A_UINT32 pos;
+   char *Buffer;
+   char *pCharLine;
+   u8 TagCount;
+   u16 ByteCount;
+   u8 ParseSection=RAM_PS_SECTION;
+   u32 pos;
 
 
 
    int uReadCount;
-   ST_PS_DATA_FORMAT stPS_DataFormat;
-   ST_READ_STATUS   stReadStatus = {0, 0, 0,0};
+   struct st_ps_data_format stPS_DataFormat;
+   struct st_read_status   stReadStatus = {0, 0, 0,0};
    pos = 0;
    Buffer = NULL;
 
@@ -438,7 +438,7 @@ A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat
                        return A_ERROR;
                     }
                     PsTagEntry[TagCount].TagLen = ByteCount;
-                    PsTagEntry[TagCount].TagData = (A_UINT8*)A_MALLOC(ByteCount);
+                    PsTagEntry[TagCount].TagData = (u8 *)A_MALLOC(ByteCount);
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d  Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount));
                     stReadStatus.uSection = 3;
                     stReadStatus.uLineCount = 0;
@@ -472,12 +472,12 @@ A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat
                     if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) {
                        while(uReadCount > 0) {
                            PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] =
-                                                     (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4)
-                                                     | (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1]));
+                                                     (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4)
+                                                     | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1]));
 
                            PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] =
-                                                     (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4)
-                                                     | (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4]));
+                                                     (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4)
+                                                     | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4]));
 
                            stReadStatus.uCharCount += 6; // read two bytes, plus a space;
                            stReadStatus.uByteCount += 2;
@@ -549,7 +549,7 @@ A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat
    if(Buffer != NULL) {
         A_FREE(Buffer);
    }
-   return A_OK;
+   return 0;
 
 }
 
@@ -558,7 +558,7 @@ A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat
 /********************/
 
 
-A_STATUS GetNextTwoChar(A_UCHAR *srcbuffer,A_UINT32 len, A_UINT32 *pos, char * buffer)
+int GetNextTwoChar(u8 *srcbuffer,u32 len, u32 *pos, char *buffer)
 {
     unsigned char ch;
 
@@ -576,19 +576,19 @@ A_STATUS GetNextTwoChar(A_UCHAR *srcbuffer,A_UINT32 len, A_UINT32 *pos, char * b
     {
         return A_ERROR;
     }
-    return A_OK;
+    return 0;
 }
 
-A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen)
+int AthDoParsePatch(u8 *patchbuffer, u32 patchlen)
 {
 
-    char  Byte[3];
-    char   Line[MAX_BYTE_LENGTH + 1];
+    char Byte[3];
+    char Line[MAX_BYTE_LENGTH + 1];
     int    ByteCount,ByteCount_Org;
     int count;
     int i,j,k;
     int data;
-    A_UINT32 filepos;
+    u32 filepos;
     Byte[2] = '\0';
     j = 0;
     filepos = 0;
@@ -614,7 +614,7 @@ A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen)
             return A_ERROR;
         }
         RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH;
-        RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(MAX_BYTE_LENGTH);
+        RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(MAX_BYTE_LENGTH);
         Patch_Count ++;
 
 
@@ -623,7 +623,7 @@ A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen)
 
     RamPatch[Patch_Count].Len= (ByteCount & 0xFF);
     if(ByteCount != 0) {
-        RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(ByteCount);
+        RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(ByteCount);
         Patch_Count ++;
     }
     count = 0;
@@ -654,21 +654,21 @@ A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen)
 
 
     }
-    return A_OK;
+    return 0;
 }
 
 
 /********************/
-A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen)
+int AthDoParsePS(u8 *srcbuffer, u32 srclen)
 {
-    A_STATUS status;
+    int status;
     int i;
-    A_BOOL BDADDR_Present = A_ERROR;
+    bool BDADDR_Present = false;
 
     Tag_Count = 0;
 
     Total_tag_lenght = 0;
-    BDADDR = FALSE;
+    BDADDR = false;
 
 
     status = A_ERROR;
@@ -689,7 +689,7 @@ A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen)
         else{
                 for(i=0; i<Tag_Count; i++){
                         if(PsTagEntry[i].TagId == 1){
-                                BDADDR_Present = A_OK;
+                                BDADDR_Present = true;
                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is present in Patch File \r\n"));
 
                         }
@@ -713,7 +713,7 @@ A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen)
 
     return status;
 }
-char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos)
+char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos)
 {
 
     int count;
@@ -751,7 +751,7 @@ char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_U
     return buffer;
 }
 
-static void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int index){
+static void LoadHeader(u8 *HCI_PS_Command,u8 opcode,int length,int index){
 
         HCI_PS_Command[0]= 0x0B;
         HCI_PS_Command[1]= 0xFC;
@@ -764,13 +764,13 @@ static void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int ind
 
 /////////////////////////
 //
-int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets)
+int AthCreateCommandList(struct ps_cmd_packet **HciPacketList, u32 *numPackets)
 {
 
-    A_UINT8 count;
-    A_UINT32 NumcmdEntry = 0; 
+    u8 count;
+    u32 NumcmdEntry = 0;
 
-    A_UINT32 Crc = 0;
+    u32 Crc = 0;
     *numPackets = 0;
 
 
@@ -785,8 +785,8 @@ int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets)
         if(Patch_Count > 0) {
             NumcmdEntry++; /* Patch Enable Command */
         }
-           AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size  %d  \r\n",NumcmdEntry,(A_UINT32)sizeof(PSCmdPacket) * NumcmdEntry));
-        (*HciPacketList) = A_MALLOC(sizeof(PSCmdPacket) * NumcmdEntry);
+           AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size  %d  \r\n",NumcmdEntry,(u32)sizeof(struct ps_cmd_packet) * NumcmdEntry));
+        (*HciPacketList) = A_MALLOC(sizeof(struct ps_cmd_packet) * NumcmdEntry);
     if(NULL == *HciPacketList) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed  \r\n"));
         }
@@ -833,10 +833,10 @@ int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets)
 ////////////////////////
 
 /////////////
-static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index)
+static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index)
 {
-    A_UCHAR *HCI_PS_Command;
-    A_UINT32 Length;
+    u8 *HCI_PS_Command;
+    u32 Length;
     int i,j;
     
     switch(Opcode)
@@ -846,7 +846,7 @@ static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacke
 
          for(i=0;i< Param1;i++){
 
-             HCI_PS_Command = (A_UCHAR *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
+             HCI_PS_Command = (u8 *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER));
                  if(HCI_PS_Command == NULL){
                      AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
@@ -871,7 +871,7 @@ static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacke
 
          Length = 0;
          i= 0;
-         HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
+         HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
          if(HCI_PS_Command == NULL){
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
             return A_ERROR;
@@ -888,7 +888,7 @@ static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacke
     case PS_RESET:
                         Length = 0x06;
                         i=0;
-                        HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
+                        HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
                         if(HCI_PS_Command == NULL){
                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
                                 return A_ERROR;
@@ -907,9 +907,9 @@ static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacke
     case PS_WRITE:
                        for(i=0;i< Param1;i++){
                                 if(PsTagEntry[i].TagId ==1)
-                                        BDADDR = TRUE;
+                                        BDADDR = true;
 
-                                HCI_PS_Command = (A_UCHAR *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
+                                HCI_PS_Command = (u8 *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
                                 if(HCI_PS_Command == NULL){
                                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
                                         return A_ERROR;
@@ -936,7 +936,7 @@ static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacke
 
                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("VALUE of CRC:%d At index %d\r\n",Param1,*index));
 
-                        HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
+                        HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
                         if(HCI_PS_Command == NULL){
                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
                                 return A_ERROR;
@@ -953,9 +953,9 @@ static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacke
     case CHANGE_BDADDR:
     break;
     }
-    return A_OK;
+    return 0;
 }
-A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets)
+int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets)
 {
     int i;
     if(*HciPacketList == NULL) {
@@ -965,5 +965,5 @@ A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets)
         A_FREE((*HciPacketList)[i].Hcipacket);
     }  
     A_FREE(*HciPacketList);
-    return A_OK;
+    return 0;
 }
diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h
index 007b0eb..9378efc 100644
--- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h
+++ b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h
@@ -48,22 +48,14 @@
 
 /* Helper data type declaration */
 
-#ifndef A_UINT32
-#define A_UCHAR                 unsigned char
-#define A_UINT32                unsigned long
-#define A_UINT16                unsigned short
-#define A_UINT8                 unsigned char
-#define A_BOOL                  unsigned char
-#endif /* A_UINT32 */
-
 #define ATH_DEBUG_ERR          (1 << 0)
 #define ATH_DEBUG_WARN         (1 << 1)
 #define ATH_DEBUG_INFO         (1 << 2)
 
 
 
-#define FALSE   0
-#define TRUE    1
+#define false   0
+#define true    1
 
 #ifndef A_MALLOC
 #define A_MALLOC(size)  kmalloc((size),GFP_KERNEL)
@@ -97,17 +89,17 @@
 
 
 
-typedef struct PSCmdPacket
+struct ps_cmd_packet
 {
-    A_UCHAR *Hcipacket;
+    u8 *Hcipacket;
     int packetLen;
-} PSCmdPacket;
+};
 
 /* Parses a Patch information buffer and store it in global structure */
-A_STATUS AthDoParsePatch(A_UCHAR *, A_UINT32);
+int AthDoParsePatch(u8 *, u32 );
 
 /* parses a PS information buffer and stores it in a global structure */
-A_STATUS AthDoParsePS(A_UCHAR *, A_UINT32);
+int AthDoParsePS(u8 *, u32 );
 
 /* 
  *  Uses the output of Both AthDoParsePS and AthDoParsePatch APIs to form HCI command array with
@@ -120,8 +112,8 @@ A_STATUS AthDoParsePS(A_UCHAR *, A_UINT32);
  *  PS Tag Command(s)
  *
  */  
-int AthCreateCommandList(PSCmdPacket **, A_UINT32 *);
+int AthCreateCommandList(struct ps_cmd_packet **, u32 *);
 
 /* Cleanup the dynamically allicated HCI command list */
-A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets);
+int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets);
 #endif /* __AR3KPSPARSER_H */
diff --git a/drivers/staging/ath6kl/miscdrv/common_drv.c b/drivers/staging/ath6kl/miscdrv/common_drv.c
index 6754fde..a23a524 100644
--- a/drivers/staging/ath6kl/miscdrv/common_drv.c
+++ b/drivers/staging/ath6kl/miscdrv/common_drv.c
@@ -47,7 +47,7 @@
 
 static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL;
 static A_MUTEX_T                 g_ModuleListLock;
-static A_BOOL                    g_ModuleDebugInit = FALSE;
+static bool                    g_ModuleDebugInit = false;
 
 #ifdef ATH_DEBUG_MODULE
 
@@ -71,8 +71,8 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(misc,
 #define CPU_DBG_SEL_ADDRESS                      0x00000483
 #define CPU_DBG_ADDRESS                          0x00000484
 
-static A_UINT8 custDataAR6002[AR6002_CUST_DATA_SIZE];
-static A_UINT8 custDataAR6003[AR6003_CUST_DATA_SIZE];
+static u8 custDataAR6002[AR6002_CUST_DATA_SIZE];
+static u8 custDataAR6003[AR6003_CUST_DATA_SIZE];
 
 /* Compile the 4BYTE version of the window register setup routine,
  * This mitigates host interconnect issues with non-4byte aligned bus requests, some
@@ -83,18 +83,18 @@ static A_UINT8 custDataAR6003[AR6003_CUST_DATA_SIZE];
 #ifdef USE_4BYTE_REGISTER_ACCESS
 
     /* set the window address register (using 4-byte register access ). */
-A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
+int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address)
 {
-    A_STATUS status;
-    A_UINT8 addrValue[4];
-    A_INT32 i;
+    int status;
+    u8 addrValue[4];
+    s32 i;
 
         /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
          * last to initiate the access cycle */
 
     for (i = 1; i <= 3; i++) {
             /* fill the buffer with the address byte value we want to hit 4 times*/
-        addrValue[0] = ((A_UINT8 *)&Address)[i];
+        addrValue[0] = ((u8 *)&Address)[i];
         addrValue[1] = addrValue[0];
         addrValue[2] = addrValue[0];
         addrValue[3] = addrValue[0];
@@ -107,12 +107,12 @@ A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
                               4,
                               HIF_WR_SYNC_BYTE_FIX,
                               NULL);
-        if (status != A_OK) {
+        if (status) {
             break;
         }
     }
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
             Address, RegisterAddr));
         return status;
@@ -123,18 +123,18 @@ A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
          * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
     status = HIFReadWrite(hifDevice,
                           RegisterAddr,
-                          (A_UCHAR *)(&Address),
+                          (u8 *)(&Address),
                           4,
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
             Address, RegisterAddr));
         return status;
     }
 
-    return A_OK;
+    return 0;
 
 
 
@@ -144,20 +144,20 @@ A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
 #else
 
     /* set the window address register */
-A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
+int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address)
 {
-    A_STATUS status;
+    int status;
 
         /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
          * last to initiate the access cycle */
     status = HIFReadWrite(hifDevice,
                           RegisterAddr+1,  /* write upper 3 bytes */
-                          ((A_UCHAR *)(&Address))+1,
-                          sizeof(A_UINT32)-1,
+                          ((u8 *)(&Address))+1,
+                          sizeof(u32)-1,
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
              RegisterAddr, Address));
         return status;
@@ -166,18 +166,18 @@ A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
         /* write the LSB of the register, this initiates the operation */
     status = HIFReadWrite(hifDevice,
                           RegisterAddr,
-                          (A_UCHAR *)(&Address),
-                          sizeof(A_UINT8),
+                          (u8 *)(&Address),
+                          sizeof(u8),
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
             RegisterAddr, Address));
         return status;
     }
 
-    return A_OK;
+    return 0;
 }
 
 #endif
@@ -186,28 +186,28 @@ A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 Registe
  * Read from the AR6000 through its diagnostic window.
  * No cooperation from the Target is required for this.
  */
-A_STATUS
-ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
+int
+ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data)
 {
-    A_STATUS status;
+    int status;
 
         /* set window register to start read cycle */
     status = ar6000_SetAddressWindowRegister(hifDevice,
                                              WINDOW_READ_ADDR_ADDRESS,
                                              *address);
 
-    if (status != A_OK) {
+    if (status) {
         return status;
     }
 
         /* read the data */
     status = HIFReadWrite(hifDevice,
                           WINDOW_DATA_ADDRESS,
-                          (A_UCHAR *)data,
-                          sizeof(A_UINT32),
+                          (u8 *)data,
+                          sizeof(u32),
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
         return status;
     }
@@ -220,19 +220,19 @@ ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
  * Write to the AR6000 through its diagnostic window.
  * No cooperation from the Target is required for this.
  */
-A_STATUS
-ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
+int
+ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data)
 {
-    A_STATUS status;
+    int status;
 
         /* set write data */
     status = HIFReadWrite(hifDevice,
                           WINDOW_DATA_ADDRESS,
-                          (A_UCHAR *)data,
-                          sizeof(A_UINT32),
+                          (u8 *)data,
+                          sizeof(u32),
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
         return status;
     }
@@ -243,16 +243,16 @@ ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
                                            *address);
     }
 
-A_STATUS
-ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                    A_UCHAR *data, A_UINT32 length)
+int
+ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,
+                    u8 *data, u32 length)
 {
-    A_UINT32 count;
-    A_STATUS status = A_OK;
+    u32 count;
+    int status = 0;
 
     for (count = 0; count < length; count += 4, address += 4) {
         if ((status = ar6000_ReadRegDiag(hifDevice, &address,
-                                         (A_UINT32 *)&data[count])) != A_OK)
+                                         (u32 *)&data[count])) != 0)
         {
             break;
         }
@@ -261,16 +261,16 @@ ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
     return status;
 }
 
-A_STATUS
-ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                    A_UCHAR *data, A_UINT32 length)
+int
+ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address,
+                    u8 *data, u32 length)
 {
-    A_UINT32 count;
-    A_STATUS status = A_OK;
+    u32 count;
+    int status = 0;
 
     for (count = 0; count < length; count += 4, address += 4) {
         if ((status = ar6000_WriteRegDiag(hifDevice, &address,
-                                         (A_UINT32 *)&data[count])) != A_OK)
+                                         (u32 *)&data[count])) != 0)
         {
             break;
         }
@@ -279,12 +279,12 @@ ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
     return status;
 }
 
-A_STATUS
-ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
+int
+ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval)
 {
-    A_STATUS status;
-    A_UCHAR vals[4];
-    A_UCHAR register_selection[4];
+    int status;
+    u8 vals[4];
+    u8 register_selection[4];
 
     register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff);
     status = HIFReadWrite(hifDevice,
@@ -294,18 +294,18 @@ ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
                           HIF_WR_SYNC_BYTE_FIX,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel));
         return status;
     }
 
     status = HIFReadWrite(hifDevice,
                           CPU_DBG_ADDRESS,
-                          (A_UCHAR *)vals,
+                          (u8 *)vals,
                           sizeof(vals),
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n"));
         return status;
     }
@@ -316,10 +316,10 @@ ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
 }
 
 void
-ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs)
+ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs)
 {
     int i;
-    A_UINT32 val;
+    u32 val;
 
     for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) {
         val=0xffffffff;
@@ -329,13 +329,13 @@ ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs)
 }
 
 #if 0
-static A_STATUS
-_do_write_diag(HIF_DEVICE *hifDevice, A_UINT32 addr, A_UINT32 value)
+static int
+_do_write_diag(struct hif_device *hifDevice, u32 addr, u32 value)
 {
-    A_STATUS status;
+    int status;
 
     status = ar6000_WriteRegDiag(hifDevice, &addr, &value);
-    if (status != A_OK)
+    if (status)
     {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
     }
@@ -357,12 +357,12 @@ _do_write_diag(HIF_DEVICE *hifDevice, A_UINT32 addr, A_UINT32 value)
  * TBD: Might want to add special handling for AR6K_OPTION_BMI_DISABLE.
  */
 #if 0
-static A_STATUS
-_delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 TargetType)
+static int
+_delay_until_target_alive(struct hif_device *hifDevice, s32 wait_msecs, u32 TargetType)
 {
-    A_INT32 actual_wait;
-    A_INT32 i;
-    A_UINT32 address;
+    s32 actual_wait;
+    s32 i;
+    u32 address;
 
     actual_wait = 0;
 
@@ -376,19 +376,19 @@ _delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 Ta
     }
     address += 0x10;
     for (i=0; actual_wait < wait_msecs; i++) {
-        A_UINT32 data;
+        u32 data;
 
         A_MDELAY(100);
         actual_wait += 100;
 
         data = 0;
-        if (ar6000_ReadRegDiag(hifDevice, &address, &data) != A_OK) {
+        if (ar6000_ReadRegDiag(hifDevice, &address, &data) != 0) {
             return A_ERROR;
         }
 
         if (data != 0) {
             /* No need to wait longer -- we have a BMI credit */
-            return A_OK;
+            return 0;
         }
     }
     return A_ERROR; /* timed out */
@@ -399,11 +399,11 @@ _delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 Ta
 #define AR6002_RESET_CONTROL_ADDRESS 0x00004000
 #define AR6003_RESET_CONTROL_ADDRESS 0x00004000
 /* reset device */
-A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset)
+int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset)
 {
-    A_STATUS status = A_OK;
-    A_UINT32 address;
-    A_UINT32 data;
+    int status = 0;
+    u32 address;
+    u32 data;
 
     do {
 // Workaround BEGIN
@@ -428,7 +428,7 @@ A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL
 
         status = ar6000_WriteRegDiag(hifDevice, &address, &data);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -458,7 +458,7 @@ A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL
         data = 0;
         status = ar6000_ReadRegDiag(hifDevice, &address, &data);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -470,27 +470,27 @@ A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL
 #endif
 // Workaroud END
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
     }
 
-    return A_OK;
+    return 0;
 }
 
 /* This should be called in BMI phase after firmware is downloaded */
 void
-ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
+ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType)
 {
-    A_UINT32 eepHeaderAddr;
-    A_UINT8 AR6003CustDataShadow[AR6003_CUST_DATA_SIZE+4];
-    A_INT32 i;
+    u32 eepHeaderAddr;
+    u8 AR6003CustDataShadow[AR6003_CUST_DATA_SIZE+4];
+    s32 i;
 
     if (BMIReadMemory(hifDevice,
             HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_board_data),
-            (A_UCHAR *)&eepHeaderAddr,
-            4)!= A_OK)
+            (u8 *)&eepHeaderAddr,
+            4)!= 0)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadMemory for reading board data address failed \n"));
         return;
@@ -500,7 +500,7 @@ ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
         eepHeaderAddr += 36;  /* AR6003 customer data section offset is 37 */
 
         for (i=0; i<AR6003_CUST_DATA_SIZE+4; i+=4){
-            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&AR6003CustDataShadow[i])!= A_OK) {
+            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (u32 *)&AR6003CustDataShadow[i])!= 0) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
                 return ;
             }  
@@ -514,7 +514,7 @@ ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
         eepHeaderAddr += 64;  /* AR6002 customer data sectioin offset is 64 */
 
         for (i=0; i<AR6002_CUST_DATA_SIZE; i+=4){
-            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&custDataAR6002[i])!= A_OK) {
+            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (u32 *)&custDataAR6002[i])!= 0) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
                 return ;
             }  
@@ -526,8 +526,7 @@ ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
 }
 
 /* This is the function to call when need to use the cust data */
-A_UINT8 *
-ar6000_get_cust_data_buffer(A_UINT32 TargetType)
+u8 *ar6000_get_cust_data_buffer(u32 TargetType)
 {
     if (TargetType == TARGET_TYPE_AR6003)
         return custDataAR6003;
@@ -553,14 +552,14 @@ ar6000_get_cust_data_buffer(A_UINT32 TargetType)
 #endif
 
 
-void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
+void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType)
 {
-    A_UINT32 address;
-    A_UINT32 regDumpArea = 0;
-    A_STATUS status;
-    A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
-    A_UINT32 regDumpCount = 0;
-    A_UINT32 i;
+    u32 address;
+    u32 regDumpArea = 0;
+    int status;
+    u32 regDumpValues[REGISTER_DUMP_LEN_MAX];
+    u32 regDumpCount = 0;
+    u32 i;
 
     do {
 
@@ -579,7 +578,7 @@ void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
             /* read RAM location through diagnostic window */
         status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
             break;
         }
@@ -596,10 +595,10 @@ void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
             /* fetch register dump data */
         status = ar6000_ReadDataDiag(hifDevice,
                                      regDumpArea,
-                                     (A_UCHAR *)&regDumpValues[0],
-                                     regDumpCount * (sizeof(A_UINT32)));
+                                     (u8 *)&regDumpValues[0],
+                                     regDumpCount * (sizeof(u32)));
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
             break;
         }
@@ -619,26 +618,26 @@ void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
 #endif
         }
 
-    } while (FALSE);
+    } while (false);
 
 }
 
 /* set HTC/Mbox operational parameters, this can only be called when the target is in the
  * BMI phase */
-A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    MboxIsrYieldValue,
-                               A_UINT8     HtcControlBuffers)
+int ar6000_set_htc_params(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 MboxIsrYieldValue,
+                               u8 HtcControlBuffers)
 {
-    A_STATUS status;
-    A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
+    int status;
+    u32 blocksizes[HTC_MAILBOX_NUM_MAX];
 
     do {
             /* get the block sizes */
         status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     blocksizes, sizeof(blocksizes));
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n"));
             break;
         }
@@ -649,16 +648,16 @@ A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
 
         if (HtcControlBuffers != 0) {
                 /* set override for number of control buffers to use */
-            blocksizes[1] |=  ((A_UINT32)HtcControlBuffers) << 16;
+            blocksizes[1] |=  ((u32)HtcControlBuffers) << 16;
         }
 
             /* set the host interest area for the block size */
         status = BMIWriteMemory(hifDevice,
                                 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz),
-                                (A_UCHAR *)&blocksizes[1],
+                                (u8 *)&blocksizes[1],
                                 4);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n"));
             break;
         }
@@ -670,33 +669,33 @@ A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
                 /* set the host interest area for the mbox ISR yield limit */
             status = BMIWriteMemory(hifDevice,
                                     HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit),
-                                    (A_UCHAR *)&MboxIsrYieldValue,
+                                    (u8 *)&MboxIsrYieldValue,
                                     4);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n"));
                 break;
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
 
-static A_STATUS prepare_ar6002(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
+static int prepare_ar6002(struct hif_device *hifDevice, u32 TargetVersion)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     /* placeholder */
 
     return status;
 }
 
-static A_STATUS prepare_ar6003(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
+static int prepare_ar6003(struct hif_device *hifDevice, u32 TargetVersion)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     /* placeholder */
 
@@ -704,9 +703,9 @@ static A_STATUS prepare_ar6003(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
 }
 
 /* this function assumes the caller has already initialized the BMI APIs */
-A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    TargetVersion)
+int ar6000_prepare_target(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 TargetVersion)
 {
     if (TargetType == TARGET_TYPE_AR6002) {
             /* do any preparations for AR6002 devices */
@@ -715,7 +714,7 @@ A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
         return prepare_ar6003(hifDevice,TargetVersion);
     }
 
-    return A_OK;
+    return 0;
 }
 
 #if defined(CONFIG_AR6002_REV1_FORCE_HOST)
@@ -725,19 +724,19 @@ A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
  * THIS IS FOR USE ONLY WITH AR6002 REV 1.x.
  * TBDXXX: Remove this function when REV 1.x is desupported.
  */
-A_STATUS
-ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
+int
+ar6002_REV1_reset_force_host (struct hif_device *hifDevice)
 {
-    A_INT32 i;
+    s32 i;
     struct forceROM_s {
-        A_UINT32 addr;
-        A_UINT32 data;
+        u32 addr;
+        u32 data;
     };
     struct forceROM_s *ForceROM;
-    A_INT32 szForceROM;
-    A_STATUS status = A_OK;
-    A_UINT32 address;
-    A_UINT32 data;
+    s32 szForceROM;
+    int status = 0;
+    u32 address;
+    u32 data;
 
     /* Force AR6002 REV1.x to recognize Host presence.
      *
@@ -771,7 +770,7 @@ ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
 
     address = 0x004ed4b0; /* REV1 target software ID is stored here */
     status = ar6000_ReadRegDiag(hifDevice, &address, &data);
-    if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
+    if (status || (data != AR6002_VERSION_REV1)) {
         return A_ERROR; /* Not AR6002 REV1 */
     }
 
@@ -783,7 +782,7 @@ ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
     {
         if (ar6000_WriteRegDiag(hifDevice,
                                 &ForceROM[i].addr,
-                                &ForceROM[i].data) != A_OK)
+                                &ForceROM[i].data) != 0)
         {
             ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
             return A_ERROR;
@@ -792,17 +791,17 @@ ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
 
     A_MDELAY(1000);
 
-    return A_OK;
+    return 0;
 }
 
 #endif /* CONFIG_AR6002_REV1_FORCE_HOST */
 
-void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription)
+void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription)
 {
-    A_CHAR stream[60];
-    A_CHAR byteOffsetStr[10];
-    A_UINT32 i;
-    A_UINT16 offset, count, byteOffset;
+    char stream[60];
+    char byteOffsetStr[10];
+    u32 i;
+    u16 offset, count, byteOffset;
 
     A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription);
 
@@ -835,7 +834,7 @@ void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription)
 void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
 {
     int                         i;
-    ATH_DEBUG_MASK_DESCRIPTION *pDesc;
+    struct ath_debug_mask_description *pDesc;
 
     if (pInfo == NULL) {
         return;
@@ -868,7 +867,7 @@ void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
 }
 
 
-static ATH_DEBUG_MODULE_DBG_INFO *FindModule(A_CHAR *module_name)
+static ATH_DEBUG_MODULE_DBG_INFO *FindModule(char *module_name)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
 
@@ -878,7 +877,7 @@ static ATH_DEBUG_MODULE_DBG_INFO *FindModule(A_CHAR *module_name)
 
     while (pInfo != NULL) {
             /* TODO: need to use something other than strlen */
-        if (A_MEMCMP(pInfo->ModuleName,module_name,strlen(module_name)) == 0) {
+        if (memcmp(pInfo->ModuleName,module_name,strlen(module_name)) == 0) {
             break;
         }
         pInfo = pInfo->pNext;
@@ -909,7 +908,7 @@ void a_register_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
     A_MUTEX_UNLOCK(&g_ModuleListLock);
 }
 
-void a_dump_module_debug_info_by_name(A_CHAR *module_name)
+void a_dump_module_debug_info_by_name(char *module_name)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
 
@@ -917,7 +916,7 @@ void a_dump_module_debug_info_by_name(A_CHAR *module_name)
         return;
     }
 
-    if (A_MEMCMP(module_name,"all",3) == 0) {
+    if (memcmp(module_name,"all",3) == 0) {
             /* dump all */
         while (pInfo != NULL) {
             a_dump_module_debug_info(pInfo);
@@ -934,7 +933,7 @@ void a_dump_module_debug_info_by_name(A_CHAR *module_name)
 
 }
 
-A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask)
+int a_get_module_mask(char *module_name, u32 *pMask)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
 
@@ -943,10 +942,10 @@ A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask)
     }
 
     *pMask = pInfo->CurrentMask;
-    return A_OK;
+    return 0;
 }
 
-A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask)
+int a_set_module_mask(char *module_name, u32 Mask)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
 
@@ -956,7 +955,7 @@ A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask)
 
     pInfo->CurrentMask = Mask;
     A_PRINTF("Module %s,  new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask);
-    return A_OK;
+    return 0;
 }
 
 
@@ -967,7 +966,7 @@ void a_module_debug_support_init(void)
     }
     A_MUTEX_INIT(&g_ModuleListLock);
     g_pModuleInfoHead = NULL;
-    g_ModuleDebugInit = TRUE;
+    g_ModuleDebugInit = true;
     A_REGISTER_MODULE_DEBUG_INFO(misc);
 }
 
@@ -980,7 +979,7 @@ void a_module_debug_support_cleanup(void)
         return;
     }
 
-    g_ModuleDebugInit = FALSE;
+    g_ModuleDebugInit = false;
 
     A_MUTEX_LOCK(&g_ModuleListLock);
 
@@ -999,11 +998,11 @@ void a_module_debug_support_cleanup(void)
 }
 
     /* can only be called during bmi init stage */
-A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
-                                     A_UINT32    TargetType,
-                                     A_UINT32    Flags)
+int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice,
+                                     u32 TargetType,
+                                     u32 Flags)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     do {
 
@@ -1016,11 +1015,11 @@ A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
             /* set hci bridge flags */
         status = BMIWriteMemory(hifDevice,
                                 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_bridge_flags),
-                                (A_UCHAR *)&Flags,
+                                (u8 *)&Flags,
                                 4);
 
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
diff --git a/drivers/staging/ath6kl/miscdrv/credit_dist.c b/drivers/staging/ath6kl/miscdrv/credit_dist.c
index 91316e0..ae54e1f 100644
--- a/drivers/staging/ath6kl/miscdrv/credit_dist.c
+++ b/drivers/staging/ath6kl/miscdrv/credit_dist.c
@@ -41,15 +41,15 @@
 #define DATA_SVCS_USED 4
 #endif
 
-static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                                HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
+static void RedistributeCredits(struct common_credit_state_info *pCredInfo,
+                                struct htc_endpoint_credit_dist *pEPDistList);
 
-static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                        HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
+static void SeekCredits(struct common_credit_state_info *pCredInfo,
+                        struct htc_endpoint_credit_dist *pEPDistList);
 
 /* reduce an ep's credits back to a set limit */
-static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                                HTC_ENDPOINT_CREDIT_DIST  *pEpDist,
+static INLINE void ReduceCredits(struct common_credit_state_info *pCredInfo,
+                                struct htc_endpoint_credit_dist  *pEpDist,
                                 int                       Limit)
 {
     int credits;
@@ -81,12 +81,12 @@ static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
  * This function is called in the context of HTCStart() to setup initial (application-specific)
  * credit distributions */
 static void ar6000_credit_init(void                     *Context,
-                               HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                               struct htc_endpoint_credit_dist *pEPList,
                                int                      TotalCredits)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
     int                      count;
-    COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
+    struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context;
 
     pCredInfo->CurrentFreeCredits = TotalCredits;
     pCredInfo->TotalAvailableCredits = TotalCredits;
@@ -136,7 +136,7 @@ static void ar6000_credit_init(void                     *Context,
 
     if (pCredInfo->CurrentFreeCredits <= 0) {
         AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits));
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return;
     }
 
@@ -175,11 +175,11 @@ static void ar6000_credit_init(void                     *Context,
  *
  */
 static void ar6000_credit_distribute(void                     *Context,
-                                     HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
+                                     struct htc_endpoint_credit_dist *pEPDistList,
                                      HTC_CREDIT_DIST_REASON   Reason)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
-    COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
+    struct htc_endpoint_credit_dist *pCurEpDist;
+    struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context;
 
     switch (Reason) {
         case HTC_CREDIT_DIST_SEND_COMPLETE :
@@ -243,10 +243,10 @@ static void ar6000_credit_distribute(void                     *Context,
 }
 
 /* redistribute credits based on activity change */
-static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                                HTC_ENDPOINT_CREDIT_DIST *pEPDistList)
+static void RedistributeCredits(struct common_credit_state_info *pCredInfo,
+                                struct htc_endpoint_credit_dist *pEPDistList)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList;
+    struct htc_endpoint_credit_dist *pCurEpDist = pEPDistList;
 
         /* walk through the list and remove credits from inactive endpoints */
     while (pCurEpDist != NULL) {
@@ -283,10 +283,10 @@ static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
 }
 
 /* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */
-static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                        HTC_ENDPOINT_CREDIT_DIST *pEPDist)
+static void SeekCredits(struct common_credit_state_info *pCredInfo,
+                        struct htc_endpoint_credit_dist *pEPDist)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
     int                      credits = 0;
     int                      need;
 
@@ -382,7 +382,7 @@ static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
             /* return what we can get */
         credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
 
-    } while (FALSE);
+    } while (false);
 
         /* did we find some credits? */
     if (credits) {
@@ -393,11 +393,11 @@ static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
 }
 
 /* initialize and setup credit distribution */
-A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo)
+int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo)
 {
     HTC_SERVICE_ID servicepriority[5];
 
-    A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO));
+    A_MEMZERO(pCredInfo,sizeof(struct common_credit_state_info));
 
     servicepriority[0] = WMI_CONTROL_SVC;  /* highest */
     servicepriority[1] = WMI_DATA_VO_SVC;
@@ -413,6 +413,6 @@ A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO
                              servicepriority,
                              5);
 
-    return A_OK;
+    return 0;
 }
 
diff --git a/drivers/staging/ath6kl/miscdrv/miscdrv.h b/drivers/staging/ath6kl/miscdrv/miscdrv.h
index ae24b72..41be567 100644
--- a/drivers/staging/ath6kl/miscdrv/miscdrv.h
+++ b/drivers/staging/ath6kl/miscdrv/miscdrv.h
@@ -27,7 +27,7 @@
 #define HOST_INTEREST_ITEM_ADDRESS(target, item)    \
    AR6002_HOST_INTEREST_ITEM_ADDRESS(item)
 
-A_UINT32 ar6kRev2Array[][128]   = {
+u32 ar6kRev2Array[][128]   = {
                                     {0xFFFF, 0xFFFF},      // No Patches
                                };
 
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_android.c b/drivers/staging/ath6kl/os/linux/ar6000_android.c
index a588825..c96f6e9 100644
--- a/drivers/staging/ath6kl/os/linux/ar6000_android.c
+++ b/drivers/staging/ath6kl/os/linux/ar6000_android.c
@@ -25,14 +25,11 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
 #ifdef CONFIG_HAS_EARLYSUSPEND
 #include <linux/earlysuspend.h>
 #endif
 
-A_BOOL enable_mmc_host_detect_change = 0;
+bool enable_mmc_host_detect_change = false;
 static void ar6000_enable_mmchost_detect_change(int enable);
 
 
@@ -44,11 +41,6 @@ extern int bmienable;
 extern struct net_device *ar6000_devices[];
 extern char ifname[];
 
-#ifdef CONFIG_HAS_WAKELOCK
-extern struct wake_lock ar6k_wow_wake_lock;
-struct wake_lock ar6k_init_wake_lock;
-#endif
-
 const char def_ifname[] = "wlan0";
 module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
 module_param(enablelogcat, uint, 0644);
@@ -59,7 +51,7 @@ static int screen_is_off;
 static struct early_suspend ar6k_early_suspend;
 #endif
 
-static A_STATUS (*ar6000_avail_ev_p)(void *, void *);
+static int (*ar6000_avail_ev_p)(void *, void *);
 
 #if defined(CONFIG_ANDROID_LOGGER) && (!defined(CONFIG_MMC_MSM))
 int logger_write(const enum logidx index,
@@ -128,9 +120,7 @@ int logger_write(const enum logidx index,
     }
     set_fs(oldfs);
 out_free_message:
-    if (msg) {
-        kfree(msg);
-    }
+    kfree(msg);
     return ret;
 }
 #endif
@@ -163,7 +153,7 @@ int android_logger_lv(void *module, int mask)
     }
 }
 
-static int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *wbuf, size_t length)
+static int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length)
 {
     int ret = 0;
     struct file *filp = (struct file *)-ENOENT;
@@ -277,17 +267,11 @@ void android_release_firmware(const struct firmware *firmware)
     }
 }
 
-static A_STATUS ar6000_android_avail_ev(void *context, void *hif_handle)
+static int ar6000_android_avail_ev(void *context, void *hif_handle)
 {
-    A_STATUS ret;    
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock(&ar6k_init_wake_lock);
-#endif
+    int ret;
     ar6000_enable_mmchost_detect_change(0);
     ret = ar6000_avail_ev_p(context, hif_handle);
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_unlock(&ar6k_init_wake_lock);
-#endif
     return ret;
 }
 
@@ -328,9 +312,6 @@ void android_module_init(OSDRV_CALLBACKS *osdrvCallbacks)
     bmienable = 1;
     if (ifname[0] == '\0')
         strcpy(ifname, def_ifname);
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_init(&ar6k_init_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_init");
-#endif
 #ifdef CONFIG_HAS_EARLYSUSPEND
     ar6k_early_suspend.suspend = android_early_suspend;
     ar6k_early_suspend.resume  = android_late_resume;
@@ -349,28 +330,25 @@ void android_module_exit(void)
 #ifdef CONFIG_HAS_EARLYSUSPEND
     unregister_early_suspend(&ar6k_early_suspend);
 #endif
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_destroy(&ar6k_init_wake_lock);
-#endif
     ar6000_enable_mmchost_detect_change(1);
 }
 
 #ifdef CONFIG_PM
-void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
+void android_ar6k_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent)
 {
     if (
 #ifdef CONFIG_HAS_EARLYSUSPEND
         screen_is_off && 
 #endif 
             skb && ar->arConnected) {
-        A_BOOL needWake = FALSE;
+        bool needWake = false;
         if (isEvent) {
-            if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) {
-                A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb);
+            if (A_NETBUF_LEN(skb) >= sizeof(u16)) {
+                u16 cmd = *(const u16 *)A_NETBUF_DATA(skb);
                 switch (cmd) {
                 case WMI_CONNECT_EVENTID:
                 case WMI_DISCONNECT_EVENTID:
-                    needWake = TRUE;
+                    needWake = true;
                     break;
                 default:
                     /* dont wake lock the system for other event */
@@ -385,7 +363,7 @@ void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL i
                 case 0x888e: /* EAPOL */
                 case 0x88c7: /* RSN_PREAUTH */
                 case 0x88b4: /* WAPI */
-                     needWake = TRUE;
+                     needWake = true;
                      break;
                 case 0x0806: /* ARP is not important to hold wake lock */
                 default:
@@ -395,9 +373,6 @@ void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL i
         }
         if (needWake) {
             /* keep host wake up if there is any event and packate comming in*/
-#ifdef CONFIG_HAS_WAKELOCK
-            wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
-#endif
             if (wowledon) {
                 char buf[32];
                 int len = sprintf(buf, "on");
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_drv.c b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
index 126a36a..27cb02d 100644
--- a/drivers/staging/ath6kl/os/linux/ar6000_drv.c
+++ b/drivers/staging/ath6kl/os/linux/ar6000_drv.c
@@ -47,8 +47,8 @@
 #define LINUX_HACK_FUDGE_FACTOR 16
 #define BDATA_BDADDR_OFFSET     28
 
-A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 
 #ifdef DEBUG
 
@@ -60,7 +60,7 @@ A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 #define  ATH_DEBUG_HTC_RAW       ATH_DEBUG_MAKE_MODULE_MASK(5)
 #define  ATH_DEBUG_HCI_BRIDGE    ATH_DEBUG_MAKE_MODULE_MASK(6)
 
-static ATH_DEBUG_MASK_DESCRIPTION driver_debug_desc[] = {
+static struct ath_debug_mask_description driver_debug_desc[] = {
     { ATH_DEBUG_DBG_LOG      , "Target Debug Logs"},
     { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"},
     { ATH_DEBUG_WLAN_SCAN    , "WLAN scan"},
@@ -102,7 +102,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define APTC_LOWER_THROUGHPUT_THRESHOLD    2000 /* Kbps */
 
 typedef struct aptc_traffic_record {
-    A_BOOL timerScheduled;
+    bool timerScheduled;
     struct timeval samplingTS;
     unsigned long bytesReceived;
     unsigned long bytesTransmitted;
@@ -114,7 +114,7 @@ APTC_TRAFFIC_RECORD aptcTR;
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 // callbacks registered by HCI transport driver
-HCI_TRANSPORT_CALLBACKS ar6kHciTransCallbacks = { NULL };
+struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL };
 #endif
 
 unsigned int processDot11Hdr = 0;
@@ -123,7 +123,7 @@ int bmienable = BMIENABLE_DEFAULT;
 char ifname[IFNAMSIZ] = {0,};
 
 int wlaninitmode = WLAN_INIT_MODE_DEFAULT;
-unsigned int bypasswmi = 0;
+static bool bypasswmi;
 unsigned int debuglevel = 0;
 int tspecCompliance = ATHEROS_COMPLIANCE;
 unsigned int busspeedlow = 0;
@@ -165,7 +165,7 @@ unsigned int eppingtest=0;
 module_param_string(ifname, ifname, sizeof(ifname), 0644);
 module_param(wlaninitmode, int, 0644);
 module_param(bmienable, int, 0644);
-module_param(bypasswmi, uint, 0644);
+module_param(bypasswmi, bool, 0644);
 module_param(debuglevel, uint, 0644);
 module_param(tspecCompliance, int, 0644);
 module_param(onebitmode, uint, 0644);
@@ -207,7 +207,7 @@ unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX;
 #define mboxnum &_mboxnum
 
 #ifdef DEBUG
-A_UINT32 g_dbg_flags = DBG_DEFAULTS;
+u32 g_dbg_flags = DBG_DEFAULTS;
 unsigned int debugflags = 0;
 int debugdriver = 0;
 unsigned int debughtc = 0;
@@ -254,22 +254,22 @@ module_param(blocktx, int, 0644);
 #endif /* BLOCK_TX_PATH_FLAG */
 
 typedef struct user_rssi_compensation_t {
-    A_UINT16         customerID;
+    u16 customerID;
     union {
-    A_UINT16         a_enable;
-    A_UINT16         bg_enable;
-    A_UINT16         enable;
+    u16 a_enable;
+    u16 bg_enable;
+    u16 enable;
     };
-    A_INT16          bg_param_a;
-    A_INT16          bg_param_b;
-    A_INT16          a_param_a;
-    A_INT16          a_param_b;
-    A_UINT32         reserved;
+    s16 bg_param_a;
+    s16 bg_param_b;
+    s16 a_param_a;
+    s16 a_param_b;
+    u32 reserved;
 } USER_RSSI_CPENSATION;
 
 static USER_RSSI_CPENSATION rssi_compensation_param;
 
-static A_INT16 rssi_compensation_table[96];
+static s16 rssi_compensation_table[96];
 
 int reconnect_flag = 0;
 static ar6k_pal_config_t ar6k_pal_config_g;
@@ -281,7 +281,7 @@ static void ar6000_cleanup_module(void);
 int ar6000_init(struct net_device *dev);
 static int ar6000_open(struct net_device *dev);
 static int ar6000_close(struct net_device *dev);
-static void ar6000_init_control_info(AR_SOFTC_T *ar);
+static void ar6000_init_control_info(struct ar6_softc *ar);
 static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
 
 void ar6000_destroy(struct net_device *dev, unsigned int unregister);
@@ -292,7 +292,7 @@ static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev);
 
 static void disconnect_timer_handler(unsigned long ptr);
 
-void read_rssi_compensation_param(AR_SOFTC_T *ar);
+void read_rssi_compensation_param(struct ar6_softc *ar);
 
     /* for android builds we call external APIs that handle firmware download and configuration */
 #ifdef ANDROID_ENV
@@ -305,33 +305,33 @@ extern void android_module_exit(void);
 /*
  * HTC service connection handlers
  */
-static A_STATUS ar6000_avail_ev(void *context, void *hif_handle);
+static int ar6000_avail_ev(void *context, void *hif_handle);
 
-static A_STATUS ar6000_unavail_ev(void *context, void *hif_handle);
+static int ar6000_unavail_ev(void *context, void *hif_handle);
 
-A_STATUS ar6000_configure_target(AR_SOFTC_T *ar);
+int ar6000_configure_target(struct ar6_softc *ar);
 
-static void ar6000_target_failure(void *Instance, A_STATUS Status);
+static void ar6000_target_failure(void *Instance, int Status);
 
-static void ar6000_rx(void *Context, HTC_PACKET *pPacket);
+static void ar6000_rx(void *Context, struct htc_packet *pPacket);
 
 static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
 
-static void ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPackets);
+static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets);
 
-static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPacket);
+static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket);
 
 #ifdef ATH_AR6K_11N_SUPPORT
-static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, A_UINT16 num);
+static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num);
 #endif
 static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf);
 //static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf);
 
-static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length);
+static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length);
 
-static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count);
+static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count);
 
-static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar);
+static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar);
 
 static ssize_t
 ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
@@ -343,18 +343,18 @@ ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
                        struct bin_attribute *bin_attr,
                        char *buf, loff_t pos, size_t count);
 
-static A_STATUS
-ar6000_sysfs_bmi_init(AR_SOFTC_T *ar);
+static int
+ar6000_sysfs_bmi_init(struct ar6_softc *ar);
 
 /* HCI PAL callback function declarations */
-A_STATUS ar6k_setup_hci_pal(AR_SOFTC_T *ar);
-void  ar6k_cleanup_hci_pal(AR_SOFTC_T *ar);
+int ar6k_setup_hci_pal(struct ar6_softc *ar);
+void  ar6k_cleanup_hci_pal(struct ar6_softc *ar);
 
 static void
-ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar);
+ar6000_sysfs_bmi_deinit(struct ar6_softc *ar);
 
-A_STATUS
-ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode);
+int
+ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode);
 
 /*
  * Static variables
@@ -364,13 +364,13 @@ struct net_device *ar6000_devices[MAX_AR6000];
 static int is_netdev_registered;
 extern struct iw_handler_def ath_iw_handler_def;
 DECLARE_WAIT_QUEUE_HEAD(arEvent);
-static void ar6000_cookie_init(AR_SOFTC_T *ar);
-static void ar6000_cookie_cleanup(AR_SOFTC_T *ar);
-static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie);
-static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar);
+static void ar6000_cookie_init(struct ar6_softc *ar);
+static void ar6000_cookie_cleanup(struct ar6_softc *ar);
+static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie);
+static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar);
 
 #ifdef USER_KEYS
-static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl);
+static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl);
 #endif
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
@@ -402,39 +402,38 @@ static struct net_device_ops ar6000_netdev_ops = {
  */
 #define REPORT_DEBUG_LOGS_TO_APP
 
-A_STATUS
-ar6000_set_host_app_area(AR_SOFTC_T *ar)
+int
+ar6000_set_host_app_area(struct ar6_softc *ar)
 {
-    A_UINT32 address, data;
+    u32 address, data;
     struct host_app_area_s host_app_area;
 
     /* Fetch the address of the host_app_area_s instance in the host interest area */
     address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest));
-    if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) {
+    if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) {
         return A_ERROR;
     }
     address = TARG_VTOP(ar->arTargetType, data);
     host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
     if (ar6000_WriteDataDiag(ar->arHifDevice, address,
-                             (A_UCHAR *)&host_app_area,
-                             sizeof(struct host_app_area_s)) != A_OK)
+                             (u8 *)&host_app_area,
+                             sizeof(struct host_app_area_s)) != 0)
     {
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 
-A_UINT32
-dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
+u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar)
 {
-    A_UINT32 param;
-    A_UINT32 address;
-    A_STATUS status;
+    u32 param;
+    u32 address;
+    int status;
 
     address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr));
     if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
-                                      (A_UCHAR *)&param, 4)) != A_OK)
+                                      (u8 *)&param, 4)) != 0)
     {
         param = 0;
     }
@@ -447,22 +446,21 @@ dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
  * data stuctures over the diagnostic window.
  */
 void
-ar6000_dbglog_init_done(AR_SOFTC_T *ar)
+ar6000_dbglog_init_done(struct ar6_softc *ar)
 {
-    ar->dbglog_init_done = TRUE;
+    ar->dbglog_init_done = true;
 }
 
-A_UINT32
-dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
+u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit)
 {
-    A_INT32 *buffer;
-    A_UINT32 count;
-    A_UINT32 numargs;
-    A_UINT32 length;
-    A_UINT32 fraglen;
+    s32 *buffer;
+    u32 count;
+    u32 numargs;
+    u32 length;
+    u32 fraglen;
 
     count = fraglen = 0;
-    buffer = (A_INT32 *)datap;
+    buffer = (s32 *)datap;
     length = (limit >> 2);
 
     if (len <= limit) {
@@ -479,18 +477,18 @@ dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
 }
 
 void
-dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
+dbglog_parse_debug_logs(s8 *datap, u32 len)
 {
-    A_INT32 *buffer;
-    A_UINT32 count;
-    A_UINT32 timestamp;
-    A_UINT32 debugid;
-    A_UINT32 moduleid;
-    A_UINT32 numargs;
-    A_UINT32 length;
+    s32 *buffer;
+    u32 count;
+    u32 timestamp;
+    u32 debugid;
+    u32 moduleid;
+    u32 numargs;
+    u32 length;
 
     count = 0;
-    buffer = (A_INT32 *)datap;
+    buffer = (s32 *)datap;
     length = (len >> 2);
     while (count < length) {
         debugid = DBGLOG_GET_DBGID(buffer[count]);
@@ -520,14 +518,14 @@ dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
 }
 
 int
-ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
+ar6000_dbglog_get_debug_logs(struct ar6_softc *ar)
 {
-    A_UINT32 data[8]; /* Should be able to accomodate struct dbglog_buf_s */
-    A_UINT32 address;
-    A_UINT32 length;
-    A_UINT32 dropped;
-    A_UINT32 firstbuf;
-    A_UINT32 debug_hdr_ptr;
+    u32 data[8]; /* Should be able to accomodate struct dbglog_buf_s */
+    u32 address;
+    u32 length;
+    u32 dropped;
+    u32 firstbuf;
+    u32 debug_hdr_ptr;
 
     if (!ar->dbglog_init_done) return A_ERROR;
 
@@ -540,7 +538,7 @@ ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
     }
 
         /* block out others */
-    ar->dbgLogFetchInProgress = TRUE;
+    ar->dbgLogFetchInProgress = true;
 
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
@@ -552,13 +550,13 @@ ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
         address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr);
         length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */;
         A_MEMZERO(data, sizeof(data));
-        ar6000_ReadDataDiag(ar->arHifDevice, address, (A_UCHAR *)data, length);
+        ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length);
         address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */);
         firstbuf = address;
         dropped = data[1]; /* dropped */
         length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
         A_MEMZERO(data, sizeof(data));
-        ar6000_ReadDataDiag(ar->arHifDevice, address, (A_UCHAR *)&data, length);
+        ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length);
 
         do {
             address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/);
@@ -568,12 +566,12 @@ ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
                 if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
                     ar->log_cnt = 0;
                 }
-                if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
-                                    (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length))
+                if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
+                                    (u8 *)&ar->log_buffer[ar->log_cnt], length))
                 {
                     break;
                 }
-                ar6000_dbglog_event(ar, dropped, (A_INT8*)&ar->log_buffer[ar->log_cnt], length);
+                ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length);
                 ar->log_cnt += length;
             } else {
                 AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n",
@@ -583,8 +581,8 @@ ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
             address = TARG_VTOP(ar->arTargetType, data[0] /* next */);
             length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
             A_MEMZERO(data, sizeof(data));
-            if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
-                                (A_UCHAR *)&data, length))
+            if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
+                                (u8 *)&data, length))
             {
                 break;
             }
@@ -592,14 +590,14 @@ ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
         } while (address != firstbuf);
     }
 
-    ar->dbgLogFetchInProgress = FALSE;
+    ar->dbgLogFetchInProgress = false;
 
-    return A_OK;
+    return 0;
 }
 
 void
-ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
-                    A_INT8 *buffer, A_UINT32 length)
+ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
+                    s8 *buffer, u32 length)
 {
 #ifdef REPORT_DEBUG_LOGS_TO_APP
     #define MAX_WIRELESS_EVENT_SIZE 252
@@ -608,13 +606,13 @@ ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
      * There seems to be a limitation on the length of message that could be
      * transmitted to the user app via this mechanism.
      */
-    A_UINT32 send, sent;
+    u32 send, sent;
 
     sent = 0;
     send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
                                      MAX_WIRELESS_EVENT_SIZE);
     while (send) {
-        ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, (A_UINT8*)&buffer[sent], send);
+        ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, (u8 *)&buffer[sent], send);
         sent += send;
         send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
                                          MAX_WIRELESS_EVENT_SIZE);
@@ -624,7 +622,7 @@ ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
                     dropped, length));
 
     /* Interpret the debug logs */
-    dbglog_parse_debug_logs((A_INT8*)buffer, length);
+    dbglog_parse_debug_logs((s8 *)buffer, length);
 #endif /* REPORT_DEBUG_LOGS_TO_APP */
 }
 
@@ -633,7 +631,7 @@ static int __init
 ar6000_init_module(void)
 {
     static int probed = 0;
-    A_STATUS status;
+    int status;
     OSDRV_CALLBACKS osdrvCallbacks;
 
     a_module_debug_support_init();
@@ -694,7 +692,7 @@ ar6000_init_module(void)
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
     status = HIFInit(&osdrvCallbacks);
-    if(status != A_OK)
+    if (status)
         return -ENODEV;
 
     return 0;
@@ -738,12 +736,12 @@ ar6000_cleanup_module(void)
 void
 aptcTimerHandler(unsigned long arg)
 {
-    A_UINT32 numbytes;
-    A_UINT32 throughput;
-    AR_SOFTC_T *ar;
-    A_STATUS status;
+    u32 numbytes;
+    u32 throughput;
+    struct ar6_softc *ar;
+    int status;
 
-    ar = (AR_SOFTC_T *)arg;
+    ar = (struct ar6_softc *)arg;
     A_ASSERT(ar != NULL);
     A_ASSERT(!timer_pending(&aptcTimer));
 
@@ -757,12 +755,12 @@ aptcTimerHandler(unsigned long arg)
     throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
     if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
         /* Enable Sleep and delete the timer */
-        A_ASSERT(ar->arWmiReady == TRUE);
+        A_ASSERT(ar->arWmiReady == true);
         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
         AR6000_SPIN_LOCK(&ar->arLock, 0);
-        A_ASSERT(status == A_OK);
-        aptcTR.timerScheduled = FALSE;
+        A_ASSERT(status == 0);
+        aptcTR.timerScheduled = false;
     } else {
         A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
     }
@@ -773,7 +771,7 @@ aptcTimerHandler(unsigned long arg)
 
 #ifdef ATH_AR6K_11N_SUPPORT
 static void
-ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, A_UINT16 num)
+ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num)
 {
     void * osbuf;
 
@@ -804,12 +802,12 @@ ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
                       char *buf, loff_t pos, size_t count)
 {
     int index;
-    AR_SOFTC_T *ar;
-    HIF_DEVICE_OS_DEVICE_INFO   *osDevInfo;
+    struct ar6_softc *ar;
+    struct hif_device_os_device_info   *osDevInfo;
 
-    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (A_UINT32)count));
+    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count));
     for (index=0; index < MAX_AR6000; index++) {
-        ar = (AR_SOFTC_T *)ar6k_priv(ar6000_devices[index]);
+        ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
         osDevInfo = &ar->osDevInfo;
         if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
             break;
@@ -818,7 +816,7 @@ ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
 
     if (index == MAX_AR6000) return 0;
 
-    if ((BMIRawRead(ar->arHifDevice, (A_UCHAR*)buf, count, TRUE)) != A_OK) {
+    if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) {
         return 0;
     }
 
@@ -831,12 +829,12 @@ ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
                        char *buf, loff_t pos, size_t count)
 {
     int index;
-    AR_SOFTC_T *ar;
-    HIF_DEVICE_OS_DEVICE_INFO   *osDevInfo;
+    struct ar6_softc *ar;
+    struct hif_device_os_device_info   *osDevInfo;
 
-    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (A_UINT32)count));
+    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count));
     for (index=0; index < MAX_AR6000; index++) {
-        ar = (AR_SOFTC_T *)ar6k_priv(ar6000_devices[index]);
+        ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
         osDevInfo = &ar->osDevInfo;
         if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
             break;
@@ -845,28 +843,28 @@ ar6000_sysfs_bmi_write(struct file *fp, struct kobject *kobj,
 
     if (index == MAX_AR6000) return 0;
 
-    if ((BMIRawWrite(ar->arHifDevice, (A_UCHAR*)buf, count)) != A_OK) {
+    if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) {
         return 0;
     }
 
     return count;
 }
 
-static A_STATUS
-ar6000_sysfs_bmi_init(AR_SOFTC_T *ar)
+static int
+ar6000_sysfs_bmi_init(struct ar6_softc *ar)
 {
-    A_STATUS status;
+    int status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n"));
-    A_MEMZERO(&ar->osDevInfo, sizeof(HIF_DEVICE_OS_DEVICE_INFO));
+    A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info));
 
     /* Get the underlying OS device */
     status = HIFConfigureDevice(ar->arHifDevice,
                                 HIF_DEVICE_GET_OS_DEVICE,
                                 &ar->osDevInfo,
-                                sizeof(HIF_DEVICE_OS_DEVICE_INFO));
+                                sizeof(struct hif_device_os_device_info));
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n"));
         return A_ERROR;
     }
@@ -878,11 +876,11 @@ ar6000_sysfs_bmi_init(AR_SOFTC_T *ar)
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static void
-ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar)
+ar6000_sysfs_bmi_deinit(struct ar6_softc *ar)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n"));
 
@@ -890,7 +888,7 @@ ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar)
 }
 
 #define bmifn(fn) do { \
-    if ((fn) < A_OK) { \
+    if ((fn) < 0) { \
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \
         return A_ERROR; \
     } \
@@ -902,28 +900,28 @@ ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar)
 #define AR6002_MAC_ADDRESS_OFFSET     0x0A
 #define AR6003_MAC_ADDRESS_OFFSET     0x16
 static
-void calculate_crc(A_UINT32 TargetType, A_UCHAR *eeprom_data)
+void calculate_crc(u32 TargetType, u8 *eeprom_data)
 {
-    A_UINT16        *ptr_crc;
-    A_UINT16        *ptr16_eeprom;
-    A_UINT16        checksum;
-    A_UINT32        i;
-    A_UINT32        eeprom_size;
+    u16 *ptr_crc;
+    u16 *ptr16_eeprom;
+    u16 checksum;
+    u32 i;
+    u32 eeprom_size;
 
     if (TargetType == TARGET_TYPE_AR6001)
     {
         eeprom_size = 512;
-        ptr_crc = (A_UINT16 *)eeprom_data;
+        ptr_crc = (u16 *)eeprom_data;
     }
     else if (TargetType == TARGET_TYPE_AR6003)
     {
         eeprom_size = 1024;
-        ptr_crc = (A_UINT16 *)((A_UCHAR *)eeprom_data + 0x04);
+        ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
     }
     else
     {
         eeprom_size = 768;
-        ptr_crc = (A_UINT16 *)((A_UCHAR *)eeprom_data + 0x04);
+        ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
     }
 
 
@@ -932,7 +930,7 @@ void calculate_crc(A_UINT32 TargetType, A_UCHAR *eeprom_data)
 
     // Recalculate new CRC
     checksum = 0;
-    ptr16_eeprom = (A_UINT16 *)eeprom_data;
+    ptr16_eeprom = (u16 *)eeprom_data;
     for (i = 0;i < eeprom_size; i += 2)
     {
         checksum = checksum ^ (*ptr16_eeprom);
@@ -943,17 +941,17 @@ void calculate_crc(A_UINT32 TargetType, A_UCHAR *eeprom_data)
 }
 
 static void 
-ar6000_softmac_update(AR_SOFTC_T *ar, A_UCHAR *eeprom_data, size_t size)
+ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size)
 {
     const char *source = "random generated";
     const struct firmware *softmac_entry;
-    A_UCHAR *ptr_mac;
+    u8 *ptr_mac;
     switch (ar->arTargetType) {
     case TARGET_TYPE_AR6002:
-        ptr_mac = (A_UINT8 *)((A_UCHAR *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET);
+        ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET);
         break;
     case TARGET_TYPE_AR6003:
-        ptr_mac = (A_UINT8 *)((A_UCHAR *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET);
+        ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET);
         break;
     default:
 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n"));
@@ -970,7 +968,7 @@ ar6000_softmac_update(AR_SOFTC_T *ar, A_UCHAR *eeprom_data, size_t size)
     ptr_mac[5] = random32() & 0xff; 
     if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0)
     {
-        A_CHAR *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1);
+        char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1);
         if (macbuf) {            
             unsigned int softmac[6];
             memcpy(macbuf, softmac_entry->data, softmac_entry->size);
@@ -993,13 +991,13 @@ ar6000_softmac_update(AR_SOFTC_T *ar, A_UCHAR *eeprom_data, size_t size)
 }
 #endif /* SOFTMAC_FILE_USED */
 
-static A_STATUS
-ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A_BOOL compressed)
+static int
+ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed)
 {
-    A_STATUS status;
+    int status;
     const char *filename;
     const struct firmware *fw_entry;
-    A_UINT32 fw_entry_size;
+    u32 fw_entry_size;
 
     switch (file) {
         case AR6K_OTP_FILE:
@@ -1024,7 +1022,7 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
             }
             
             if (eppingtest) {
-                bypasswmi = TRUE;    
+                bypasswmi = true;
                 if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
                     filename = AR6003_REV1_EPPING_FIRMWARE_FILE;
                 } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
@@ -1034,7 +1032,7 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
                         ar->arVersion.target_ver));
                     return A_ERROR;
                 }
-                compressed = 0;
+                compressed = false;
             }
             
 #ifdef CONFIG_HOST_TCMD_SUPPORT
@@ -1047,7 +1045,7 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
                     return A_ERROR;
                 }
-                compressed = 0;
+                compressed = false;
             }
 #endif 
 #ifdef HTC_RAW_INTERFACE
@@ -1060,7 +1058,7 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
                     return A_ERROR;
                 }
-                compressed = 0;                
+                compressed = false;
             }
 #endif 
             break;
@@ -1099,7 +1097,7 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
 
 #ifdef SOFTMAC_FILE_USED
     if (file==AR6K_BOARD_DATA_FILE && fw_entry->data) {
-        ar6000_softmac_update(ar, (A_UCHAR *)fw_entry->data, fw_entry->size);
+        ar6000_softmac_update(ar, (u8 *)fw_entry->data, fw_entry->size);
     }
 #endif 
 
@@ -1108,9 +1106,9 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
 
     /* Load extended board data for AR6003 */
     if ((file==AR6K_BOARD_DATA_FILE) && (fw_entry->data)) {
-        A_UINT32 board_ext_address;
-        A_UINT32 board_ext_data_size;
-        A_UINT32 board_data_size;
+        u32 board_ext_address;
+        u32 board_ext_data_size;
+        u32 board_data_size;
 
         board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \
                                (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0));
@@ -1119,16 +1117,16 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
                           (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0));
         
         /* Determine where in Target RAM to write Board Data */
-        bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (A_UCHAR *)&board_ext_address, 4));
+        bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4));
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address));
 
         /* check whether the target has allocated memory for extended board data and file contains extended board data */
         if ((board_ext_address) && (fw_entry->size == (board_data_size + board_ext_data_size))) {
-            A_UINT32 param;
+            u32 param;
 
-            status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (A_UCHAR *)(fw_entry->data + board_data_size), board_ext_data_size);
+            status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(fw_entry->data + board_data_size), board_ext_data_size);
 
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
                 A_RELEASE_FIRMWARE(fw_entry);
                 return A_ERROR;
@@ -1136,42 +1134,42 @@ ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A
 
             /* Record the fact that extended board Data IS initialized */
             param = 1;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_initialized), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_initialized), (u8 *)&param, 4));
         }
         fw_entry_size = board_data_size;
     }
 
     if (compressed) {
-        status = BMIFastDownload(ar->arHifDevice, address, (A_UCHAR *)fw_entry->data, fw_entry_size);
+        status = BMIFastDownload(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
     } else {
-        status = BMIWriteMemory(ar->arHifDevice, address, (A_UCHAR *)fw_entry->data, fw_entry_size);
+        status = BMIWriteMemory(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
     }
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
         A_RELEASE_FIRMWARE(fw_entry);
         return A_ERROR;
     }
     A_RELEASE_FIRMWARE(fw_entry);
-    return A_OK;
+    return 0;
 }
 #endif /* INIT_MODE_DRV_ENABLED */
 
-A_STATUS
-ar6000_update_bdaddr(AR_SOFTC_T *ar)
+int
+ar6000_update_bdaddr(struct ar6_softc *ar)
 {
 
         if (setupbtdev != 0) {
-            A_UINT32 address;
+            u32 address;
 
            if (BMIReadMemory(ar->arHifDevice,
-           	HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (A_UCHAR *)&address, 4) != A_OK)
+		HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0)
            {
     	      	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n"));
            	return A_ERROR;
            }
 
-           if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (A_UCHAR *)ar->bdaddr, 6) != A_OK)
+           if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0)
            {
     	    	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n"));
            	return A_ERROR;
@@ -1181,16 +1179,16 @@ ar6000_update_bdaddr(AR_SOFTC_T *ar)
 								ar->bdaddr[4], ar->bdaddr[5]));
         }
 
-return A_OK;
+return 0;
 }
 
-A_STATUS
-ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
+int
+ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n"));
 
     if (mode == WLAN_INIT_MODE_UDEV) {
-        A_CHAR version[16];
+        char version[16];
         const struct firmware *fw_entry;
 
         /* Get config using udev through a script in user space */
@@ -1205,8 +1203,8 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 #ifdef INIT_MODE_DRV_ENABLED
     } else {
         /* The config is contained within the driver itself */
-        A_STATUS status;
-        A_UINT32 param, options, sleep, address;
+        int status;
+        u32 param, options, sleep, address;
 
         /* Temporarily disable system sleep */
         address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
@@ -1236,7 +1234,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 
         param = 0;
         if (ar->arTargetType == TARGET_TYPE_AR6002) {
-            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (A_UCHAR *)&param, 4));
+            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)&param, 4));
         }
 
         /* LPO_CAL.ENABLE = 1 if no external clk is detected */
@@ -1269,7 +1267,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
         if (ar->arTargetType == TARGET_TYPE_AR6003) {
             /* hi_ext_clk_detected = 0 */
             param = 0;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)&param, 4));
 
             /* CLOCK_CONTROL &= ~LF_CLK32 */
             address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS;
@@ -1282,22 +1280,22 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
         /* Transfer Board Data from Target EEPROM to Target RAM */
         if (ar->arTargetType == TARGET_TYPE_AR6003) {
             /* Determine where in Target RAM to write Board Data */
-            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (A_UCHAR *)&address, 4));
+            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4));
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address));
 
             /* Write EEPROM data to Target RAM */
-            if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, FALSE)) != A_OK) {
+            if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) {
                 return A_ERROR;
             }
 
             /* Record the fact that Board Data IS initialized */
             param = 1;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)&param, 4));
 
             /* Transfer One time Programmable data */
             AR6K_DATA_DOWNLOAD_ADDRESS(address, ar->arVersion.target_ver);
-            status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, TRUE);
-            if (status == A_OK) {
+            status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true);
+            if (status == 0) {
                 /* Execute the OTP code */
                 param = 0;
                 AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver);
@@ -1312,7 +1310,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 
         /* Download Target firmware */
         AR6K_DATA_DOWNLOAD_ADDRESS(address, ar->arVersion.target_ver);
-        if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, TRUE)) != A_OK) {
+        if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) {
             return A_ERROR;
         }
 
@@ -1322,12 +1320,12 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 
         /* Apply the patches */
         AR6K_PATCH_DOWNLOAD_ADDRESS(address, ar->arVersion.target_ver);
-        if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, address, FALSE)) != A_OK) {
+        if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, address, false)) != 0) {
             return A_ERROR;
         }
 
         param = address;
-        bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), (A_UCHAR *)&param, 4));
+        bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), (u8 *)&param, 4));
 
         if (ar->arTargetType == TARGET_TYPE_AR6003) {
             if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
@@ -1337,7 +1335,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
                 /* Reserve 6.5K of RAM */
                 param = 6656;
             }
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_end_RAM_reserve_sz), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_end_RAM_reserve_sz), (u8 *)&param, 4));
         }
 
         /* Restore system sleep */
@@ -1354,7 +1352,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
 #endif
             param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)&param, 4));
 
 #if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23)
             {
@@ -1369,7 +1367,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 #ifdef ATH6KL_CONFIG_GPIO_BT_RESET
 #define CONFIG_AR600x_BT_RESET_PIN	0x16
             param = CONFIG_AR600x_BT_RESET_PIN;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)&param, 4));
 #endif /* ATH6KL_CONFIG_GPIO_BT_RESET */
 
             /* Configure UART flow control polarity */
@@ -1380,7 +1378,7 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 #if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1)
             if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
                 param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2);
-                bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (A_UCHAR *)&param, 4));
+                bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)&param, 4));
             }
 #endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */
         }
@@ -1396,19 +1394,19 @@ ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
 #endif /* INIT_MODE_DRV_ENABLED */
     }
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-ar6000_configure_target(AR_SOFTC_T *ar)
+int
+ar6000_configure_target(struct ar6_softc *ar)
 {
-    A_UINT32 param;
+    u32 param;
     if (enableuartprint) {
         param = 1;
         if (BMIWriteMemory(ar->arHifDevice,
                            HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
-                           (A_UCHAR *)&param,
-                           4)!= A_OK)
+                           (u8 *)&param,
+                           4)!= 0)
         {
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n"));
              return A_ERROR;
@@ -1420,8 +1418,8 @@ ar6000_configure_target(AR_SOFTC_T *ar)
     param = HTC_PROTOCOL_VERSION;
     if (BMIWriteMemory(ar->arHifDevice,
                        HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest),
-                       (A_UCHAR *)&param,
-                       4)!= A_OK)
+                       (u8 *)&param,
+                       4)!= 0)
     {
          AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n"));
          return A_ERROR;
@@ -1435,12 +1433,12 @@ ar6000_configure_target(AR_SOFTC_T *ar)
     }
 #endif
     if (enabletimerwar) {
-        A_UINT32 param;
+        u32 param;
 
         if (BMIReadMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4)!= A_OK)
+            (u8 *)&param,
+            4)!= 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n"));
             return A_ERROR;
@@ -1450,8 +1448,8 @@ ar6000_configure_target(AR_SOFTC_T *ar)
 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n"));
             return A_ERROR;
@@ -1461,12 +1459,12 @@ ar6000_configure_target(AR_SOFTC_T *ar)
 
     /* set the firmware mode to STA/IBSS/AP */
     {
-        A_UINT32 param;
+        u32 param;
 
         if (BMIReadMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4)!= A_OK)
+            (u8 *)&param,
+            4)!= 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n"));
             return A_ERROR;
@@ -1476,8 +1474,8 @@ ar6000_configure_target(AR_SOFTC_T *ar)
 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n"));
             return A_ERROR;
@@ -1487,12 +1485,12 @@ ar6000_configure_target(AR_SOFTC_T *ar)
 
 #ifdef ATH6KL_DISABLE_TARGET_DBGLOGS
     {
-        A_UINT32 param;
+        u32 param;
 
         if (BMIReadMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4)!= A_OK)
+            (u8 *)&param,
+            4)!= 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for disabling debug logs failed\n"));
             return A_ERROR;
@@ -1502,8 +1500,8 @@ ar6000_configure_target(AR_SOFTC_T *ar)
 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for HI_OPTION_DISABLE_DBGLOG\n"));
             return A_ERROR;
@@ -1524,8 +1522,8 @@ ar6000_configure_target(AR_SOFTC_T *ar)
         param = AR6003_BOARD_EXT_DATA_ADDRESS; 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for hi_board_ext_data failed \n"));
             return A_ERROR;
@@ -1536,22 +1534,20 @@ ar6000_configure_target(AR_SOFTC_T *ar)
         /* since BMIInit is called in the driver layer, we have to set the block
          * size here for the target */
 
-    if (A_FAILED(ar6000_set_htc_params(ar->arHifDevice,
-                                       ar->arTargetType,
-                                       mbox_yield_limit,
-                                       0 /* use default number of control buffers */
-                                       ))) {
+    if (ar6000_set_htc_params(ar->arHifDevice, ar->arTargetType,
+			      mbox_yield_limit, 0)) {
+				/* use default number of control buffers */
         return A_ERROR;
     }
 
     if (setupbtdev != 0) {
-        if (A_FAILED(ar6000_set_hci_bridge_flags(ar->arHifDevice,
-                                                 ar->arTargetType,
-                                                 setupbtdev))) {
+        if (ar6000_set_hci_bridge_flags(ar->arHifDevice,
+					ar->arTargetType,
+					setupbtdev)) {
             return A_ERROR;
         }
     }
-    return A_OK;
+    return 0;
 }
 
 static void
@@ -1595,19 +1591,27 @@ init_netdev(struct net_device *dev, char *name)
 /*
  * HTC Event handlers
  */
-static A_STATUS
+static int
 ar6000_avail_ev(void *context, void *hif_handle)
 {
     int i;
     struct net_device *dev;
     void *ar_netif;
-    AR_SOFTC_T *ar;
+    struct ar6_softc *ar;
     int device_index = 0;
-    HTC_INIT_INFO  htcInfo;
+    struct htc_init_info  htcInfo;
 #ifdef ATH6K_CONFIG_CFG80211
     struct wireless_dev *wdev;
 #endif /* ATH6K_CONFIG_CFG80211 */
-    A_STATUS init_status = A_OK;
+    int init_status = 0;
+    struct hif_device_os_device_info osDevInfo;
+
+    memset(&osDevInfo, 0, sizeof(osDevInfo));
+    if (HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE,
+        &osDevInfo, sizeof(osDevInfo))) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Failed to get OS device instance\n", __func__));
+        return A_ERROR;
+    }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n"));
 
@@ -1627,14 +1631,14 @@ ar6000_avail_ev(void *context, void *hif_handle)
     device_index = i;
 
 #ifdef ATH6K_CONFIG_CFG80211
-    wdev = ar6k_cfg80211_init(NULL);
+    wdev = ar6k_cfg80211_init(osDevInfo.pOSDevice);
     if (IS_ERR(wdev)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __func__));
         return A_ERROR;
     }
     ar_netif = wdev_priv(wdev);
 #else
-    dev = alloc_etherdev(sizeof(AR_SOFTC_T));
+    dev = alloc_etherdev(sizeof(struct ar6_softc));
     if (dev == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: can't alloc etherdev\n"));
         return A_ERROR;
@@ -1648,8 +1652,8 @@ ar6000_avail_ev(void *context, void *hif_handle)
         return A_ERROR;
     }
 
-    A_MEMZERO(ar_netif, sizeof(AR_SOFTC_T));
-    ar = (AR_SOFTC_T *)ar_netif;
+    A_MEMZERO(ar_netif, sizeof(struct ar6_softc));
+    ar = (struct ar6_softc *)ar_netif;
 
 #ifdef ATH6K_CONFIG_CFG80211
     ar->wdev = wdev;
@@ -1666,18 +1670,14 @@ ar6000_avail_ev(void *context, void *hif_handle)
     SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
     wdev->netdev = dev;
     ar->arNetworkType = INFRA_NETWORK;
+    ar->smeState = SME_DISCONNECTED;
 #endif /* ATH6K_CONFIG_CFG80211 */
 
     init_netdev(dev, ifname);
 
 #ifdef SET_NETDEV_DEV
     if (ar_netif) { 
-        HIF_DEVICE_OS_DEVICE_INFO osDevInfo;
-        A_MEMZERO(&osDevInfo, sizeof(osDevInfo));
-        if ( A_SUCCESS( HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE,
-                        &osDevInfo, sizeof(osDevInfo))) ) {
-            SET_NETDEV_DEV(dev, osDevInfo.pOSDevice);
-        }
+        SET_NETDEV_DEV(dev, osDevInfo.pOSDevice);
     }
 #endif 
 
@@ -1687,10 +1687,10 @@ ar6000_avail_ev(void *context, void *hif_handle)
     ar->arDeviceIndex        = device_index;
 
     ar->arWlanPowerState     = WLAN_POWER_STATE_ON;
-    ar->arWlanOff            = FALSE;   /* We are in ON state */
+    ar->arWlanOff            = false;   /* We are in ON state */
 #ifdef CONFIG_PM
     ar->arWowState           = WLAN_WOW_STATE_NONE;
-    ar->arBTOff              = TRUE;   /* BT chip assumed to be OFF */
+    ar->arBTOff              = true;   /* BT chip assumed to be OFF */
     ar->arBTSharing          = WLAN_CONFIG_BT_SHARING; 
     ar->arWlanOffConfig      = WLAN_CONFIG_WLAN_OFF;
     ar->arSuspendConfig      = WLAN_CONFIG_PM_SUSPEND;
@@ -1699,7 +1699,7 @@ ar6000_avail_ev(void *context, void *hif_handle)
 
     A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev);
     ar->arHBChallengeResp.seqNum = 0;
-    ar->arHBChallengeResp.outstanding = FALSE;
+    ar->arHBChallengeResp.outstanding = false;
     ar->arHBChallengeResp.missCnt = 0;
     ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT;
     ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT;
@@ -1707,7 +1707,7 @@ ar6000_avail_ev(void *context, void *hif_handle)
     ar6000_init_control_info(ar);
     init_waitqueue_head(&arEvent);
     sema_init(&ar->arSem, 1);
-    ar->bIsDestroyProgress = FALSE;
+    ar->bIsDestroyProgress = false;
 
     INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue);
 
@@ -1726,7 +1726,7 @@ ar6000_avail_ev(void *context, void *hif_handle)
     {
         struct bmi_target_info targ_info;
 
-        if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) {
+        if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != 0) {
             init_status = A_ERROR;
             goto avail_ev_failed;
         }
@@ -1737,14 +1737,14 @@ ar6000_avail_ev(void *context, void *hif_handle)
             /* do any target-specific preparation that can be done through BMI */
         if (ar6000_prepare_target(ar->arHifDevice,
                                   targ_info.target_type,
-                                  targ_info.target_ver) != A_OK) {
+                                  targ_info.target_ver) != 0) {
             init_status = A_ERROR;
             goto avail_ev_failed;
         }
 
     }
 
-    if (ar6000_configure_target(ar) != A_OK) {
+    if (ar6000_configure_target(ar) != 0) {
             init_status = A_ERROR;
             goto avail_ev_failed;
     }
@@ -1799,25 +1799,27 @@ ar6000_avail_ev(void *context, void *hif_handle)
         if ((wlaninitmode == WLAN_INIT_MODE_UDEV) ||
             (wlaninitmode == WLAN_INIT_MODE_DRV))
         {
-            A_STATUS status = A_OK;
+            int status = 0;
             do {
-                if ((status = ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != A_OK)
+                if ((status = ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0)
                 {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n"));
                     break;
                 }
 #ifdef HTC_RAW_INTERFACE
-                break; /* Don't call ar6000_init for ART */
+                if (!eppingtest && bypasswmi) {
+                    break; /* Don't call ar6000_init for ART */
+                }
 #endif 
                 rtnl_lock();
-                status = (ar6000_init(dev)==0) ? A_OK : A_ERROR;
+                status = (ar6000_init(dev)==0) ? 0 : A_ERROR;
                 rtnl_unlock();
-                if (status != A_OK) {
+                if (status) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n"));
                 }
-            } while (FALSE);
+            } while (false);
 
-            if (status != A_OK) {
+            if (status) {
                 init_status = status;
                 goto avail_ev_failed;
             }
@@ -1841,7 +1843,7 @@ ar6000_avail_ev(void *context, void *hif_handle)
                     (unsigned long)ar));
 
 avail_ev_failed :
-    if (A_FAILED(init_status)) {
+    if (init_status) {
         if (bmienable) { 
             ar6000_sysfs_bmi_deinit(ar);  
         }
@@ -1850,13 +1852,13 @@ avail_ev_failed :
     return init_status;
 }
 
-static void ar6000_target_failure(void *Instance, A_STATUS Status)
+static void ar6000_target_failure(void *Instance, int Status)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
+    struct ar6_softc *ar = (struct ar6_softc *)Instance;
     WMI_TARGET_ERROR_REPORT_EVENT errEvent;
-    static A_BOOL sip = FALSE;
+    static bool sip = false;
 
-    if (Status != A_OK) {
+    if (Status != 0) {
 
         printk(KERN_ERR "ar6000_target_failure: target asserted \n");
 
@@ -1875,47 +1877,47 @@ static void ar6000_target_failure(void *Instance, A_STATUS Status)
 
         /* Report the error only once */
         if (!sip) {
-            sip = TRUE;
+            sip = true;
             errEvent.errorVal = WMI_TARGET_COM_ERR |
                                 WMI_TARGET_FATAL_ERR;
             ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
-                                     (A_UINT8 *)&errEvent,
+                                     (u8 *)&errEvent,
                                      sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
         }
     }
 }
 
-static A_STATUS
+static int
 ar6000_unavail_ev(void *context, void *hif_handle)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
         /* NULL out it's entry in the global list */
     ar6000_devices[ar->arDeviceIndex] = NULL;
     ar6000_destroy(ar->arNetDev, 1);
 
-    return A_OK;
+    return 0;
 }
 
 void
 ar6000_restart_endpoint(struct net_device *dev)
 {
-    A_STATUS status = A_OK;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    int status = 0;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     BMIInit();
     do {
-        if ( (status=ar6000_configure_target(ar))!=A_OK)
+        if ( (status=ar6000_configure_target(ar))!= 0)
             break;
-        if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != A_OK)
+        if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n"));
             break;
         }
         rtnl_lock();
-        status = (ar6000_init(dev)==0) ? A_OK : A_ERROR;
+        status = (ar6000_init(dev)==0) ? 0 : A_ERROR;
         rtnl_unlock();
 
-        if (status!=A_OK) {
+        if (status) {
             break;
         }
         if (ar->arSsidLen && ar->arWlanState == WLAN_ENABLED) {
@@ -1923,7 +1925,7 @@ ar6000_restart_endpoint(struct net_device *dev)
         }  
     } while (0);
 
-    if (status==A_OK) {
+    if (status== 0) {
         return;
     }
 
@@ -1932,27 +1934,24 @@ ar6000_restart_endpoint(struct net_device *dev)
 }
 
 void
-ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglogs)
+ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     /* Stop the transmit queues */
     netif_stop_queue(dev);
 
     /* Disable the target and the interrupts associated with it */
-    if (ar->arWmiReady == TRUE)
+    if (ar->arWmiReady == true)
     {
         if (!bypasswmi)
         {
-            if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
-            {
-                AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Disconnect\n", __func__));
-                if (!keepprofile) {
-                    AR6000_SPIN_LOCK(&ar->arLock, 0);
-                    ar6000_init_profile_info(ar);
-                    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-                }
-                wmi_disconnect_cmd(ar->arWmi);
+            bool disconnectIssued;
+ 
+            disconnectIssued = (ar->arConnected) || (ar->arConnectPending);
+            ar6000_disconnect(ar);
+            if (!keepprofile) {
+                ar6000_init_profile_info(ar);
             }
 
             A_UNTIMEOUT(&ar->disconnect_timer);
@@ -1961,9 +1960,9 @@ ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglo
                 ar6000_dbglog_get_debug_logs(ar);
             }
 
-            ar->arWmiReady  = FALSE;
+            ar->arWmiReady  = false;
             wmi_shutdown(ar->arWmi);
-            ar->arWmiEnabled = FALSE;
+            ar->arWmiEnabled = false;
             ar->arWmi = NULL;
             /* 
              * After wmi_shudown all WMI events will be dropped.
@@ -1974,14 +1973,12 @@ ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglo
              * Sometimes disconnect_event will be received when the debug logs 
              * are collected.
              */
-            if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
+            if (disconnectIssued) {
                 if(ar->arNetworkType & AP_NETWORK) {
                     ar6000_disconnect_event(ar, DISCONNECT_CMD, bcast_mac, 0, NULL, 0);
                 } else {
                     ar6000_disconnect_event(ar, DISCONNECT_CMD, ar->arBssid, 0, NULL, 0);
                 }
-                ar->arConnected = FALSE;
-                ar->arConnectPending = FALSE;
             }
 #ifdef USER_KEYS
             ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
@@ -1997,11 +1994,11 @@ ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglo
             __func__, (unsigned long) ar, (unsigned long) ar->arWmi));
 
         /* Shut down WMI if we have started it */
-        if(ar->arWmiEnabled == TRUE)
+        if(ar->arWmiEnabled == true)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__));
             wmi_shutdown(ar->arWmi);
-            ar->arWmiEnabled = FALSE;
+            ar->arWmiEnabled = false;
             ar->arWmi = NULL;
         }
     }
@@ -2014,13 +2011,13 @@ ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglo
 #else
         // FIXME: workaround to reset BT's UART baud rate to default
         if (NULL != ar->exitCallback) {
-            AR3K_CONFIG_INFO ar3kconfig;
-            A_STATUS status;
+            struct ar3k_config_info ar3kconfig;
+            int status;
 
             A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
             ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig);
             status = ar->exitCallback(&ar3kconfig);
-            if (A_OK != status) {
+            if (0 != status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate! \n"));
             }
         }
@@ -2048,14 +2045,17 @@ ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglo
          * a debug session */
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance destroy.... \n"));
         if (ar->arHifDevice != NULL) {
-            A_BOOL coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? TRUE: FALSE;
-            ar6000_reset_device(ar->arHifDevice, ar->arTargetType, TRUE, coldReset);
+            bool coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? true: false;
+            ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, coldReset);
         }
     } else {
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n"));
     }
        /* Done with cookies */
     ar6000_cookie_cleanup(ar);
+
+    /* cleanup any allocated AMSDU buffers */
+    ar6000_cleanup_amsdu_rxbufs(ar);
 }
 /*
  * We need to differentiate between the surprise and planned removal of the
@@ -2074,7 +2074,7 @@ ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglo
 void
 ar6000_destroy(struct net_device *dev, unsigned int unregister)
 {
-    AR_SOFTC_T *ar;
+    struct ar6_softc *ar;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n"));
     
@@ -2084,7 +2084,7 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
         return;
     }
 
-    ar->bIsDestroyProgress = TRUE;
+    ar->bIsDestroyProgress = true;
 
     if (down_interruptible(&ar->arSem)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __func__));
@@ -2093,7 +2093,7 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
 
     if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) {
         /* only stop endpoint if we are not stop it in suspend_ev */
-        ar6000_stop_endpoint(dev, FALSE, TRUE);
+        ar6000_stop_endpoint(dev, false, true);
     } else {
         /* clear up the platform power state before rmmod */
         plat_setup_power(1,0);
@@ -2159,18 +2159,18 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
 static void disconnect_timer_handler(unsigned long ptr)
 {
     struct net_device *dev = (struct net_device *)ptr;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     A_UNTIMEOUT(&ar->disconnect_timer);
 
     ar6000_init_profile_info(ar);
-    wmi_disconnect_cmd(ar->arWmi);
+    ar6000_disconnect(ar);
 }
 
 static void ar6000_detect_error(unsigned long ptr)
 {
     struct net_device *dev = (struct net_device *)ptr;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_TARGET_ERROR_REPORT_EVENT errEvent;
 
     AR6000_SPIN_LOCK(&ar->arLock, 0);
@@ -2188,19 +2188,19 @@ static void ar6000_detect_error(unsigned long ptr)
         errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR;
         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
-                                 (A_UINT8 *)&errEvent,
+                                 (u8 *)&errEvent,
                                  sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
         return;
     }
 
     /* Generate the sequence number for the next challenge */
     ar->arHBChallengeResp.seqNum++;
-    ar->arHBChallengeResp.outstanding = TRUE;
+    ar->arHBChallengeResp.outstanding = true;
 
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
     /* Send the challenge on the control channel */
-    if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != A_OK) {
+    if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n"));
     }
 
@@ -2209,7 +2209,7 @@ static void ar6000_detect_error(unsigned long ptr)
     A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
 }
 
-void ar6000_init_profile_info(AR_SOFTC_T *ar)
+void ar6000_init_profile_info(struct ar6_softc *ar)
 {
     ar->arSsidLen            = 0;
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
@@ -2236,13 +2236,12 @@ void ar6000_init_profile_info(AR_SOFTC_T *ar)
     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
     ar->arBssChannel = 0;
-    ar->arConnected = FALSE;
 }
 
 static void
-ar6000_init_control_info(AR_SOFTC_T *ar)
+ar6000_init_control_info(struct ar6_softc *ar)
 {
-    ar->arWmiEnabled         = FALSE;
+    ar->arWmiEnabled         = false;
     ar6000_init_profile_info(ar);
     ar->arDefTxKeyIndex      = 0;
     A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
@@ -2252,12 +2251,12 @@ ar6000_init_control_info(AR_SOFTC_T *ar)
     ar->arVersion.host_ver   = AR6K_SW_VERSION;
     ar->arRssi               = 0;
     ar->arTxPwr              = 0;
-    ar->arTxPwrSet           = FALSE;
+    ar->arTxPwrSet           = false;
     ar->arSkipScan           = 0;
     ar->arBeaconInterval     = 0;
     ar->arBitRate            = 0;
     ar->arMaxRetries         = 0;
-    ar->arWmmEnabled         = TRUE;
+    ar->arWmmEnabled         = true;
     ar->intra_bss            = 1;
     ar->scan_triggered       = 0;
     A_MEMZERO(&ar->scParams, sizeof(ar->scParams));
@@ -2266,8 +2265,8 @@ ar6000_init_control_info(AR_SOFTC_T *ar)
 
     /* Initialize the AP mode state info */
     {
-        A_UINT8 ctr;
-        A_MEMZERO((A_UINT8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t));
+        u8 ctr;
+        A_MEMZERO((u8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t));
 
         /* init the Mutexes */
         A_MUTEX_INIT(&ar->mcastpsqLock);
@@ -2281,7 +2280,7 @@ ar6000_init_control_info(AR_SOFTC_T *ar)
         ar->ap_profile_flag = 0;
         A_NETBUF_QUEUE_INIT(&ar->mcastpsq);
 
-        A_MEMCPY(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
+        memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
         ar->ap_wmode = DEF_AP_WMODE_G;
         ar->ap_dtim_period = DEF_AP_DTIM;
         ar->ap_beacon_interval = DEF_BEACON_INTERVAL;
@@ -2292,7 +2291,7 @@ static int
 ar6000_open(struct net_device *dev)
 {
     unsigned long  flags;
-    AR_SOFTC_T    *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc    *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     spin_lock_irqsave(&ar->arLock, flags);
 
@@ -2318,38 +2317,33 @@ static int
 ar6000_close(struct net_device *dev)
 {
 #ifdef ATH6K_CONFIG_CFG80211
-    AR_SOFTC_T    *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc    *ar = (struct ar6_softc *)ar6k_priv(dev);
 #endif /* ATH6K_CONFIG_CFG80211 */
     netif_stop_queue(dev);
 
 #ifdef ATH6K_CONFIG_CFG80211
-    AR6000_SPIN_LOCK(&ar->arLock, 0);
-    if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
-        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-        wmi_disconnect_cmd(ar->arWmi);
-    } else {
-        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-    }
+    ar6000_disconnect(ar);
 
-    if(ar->arWmiReady == TRUE) {
+    if(ar->arWmiReady == true) {
         if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0,
-                               0, 0, 0, 0, 0, 0, 0, 0) != A_OK) {
+                               0, 0, 0, 0, 0, 0, 0, 0) != 0) {
             return -EIO;
         }
         ar->arWlanState = WLAN_DISABLED;
     }
+	ar6k_cfg80211_scanComplete_event(ar, A_ECANCELED);
 #endif /* ATH6K_CONFIG_CFG80211 */
 
     return 0;
 }
 
 /* connect to a service */
-static A_STATUS ar6000_connectservice(AR_SOFTC_T               *ar,
-                                      HTC_SERVICE_CONNECT_REQ  *pConnect,
-                                      char                     *pDesc)
+static int ar6000_connectservice(struct ar6_softc               *ar,
+                                      struct htc_service_connect_req  *pConnect,
+                                      char *pDesc)
 {
-    A_STATUS                 status;
-    HTC_SERVICE_CONNECT_RESP response;
+    int                 status;
+    struct htc_service_connect_resp response;
 
     do {
 
@@ -2359,7 +2353,7 @@ static A_STATUS ar6000_connectservice(AR_SOFTC_T               *ar,
                                    pConnect,
                                    &response);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service status:%d \n",
                               pDesc, status));
             break;
@@ -2391,12 +2385,12 @@ static A_STATUS ar6000_connectservice(AR_SOFTC_T               *ar,
             break;
         }
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
-void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
+void ar6000_TxDataCleanup(struct ar6_softc *ar)
 {
         /* flush all the data (non-control) streams
          * we only flush packets that are tagged as data, we leave any control packets that
@@ -2416,32 +2410,148 @@ void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
 }
 
 HTC_ENDPOINT_ID
-ar6000_ac2_endpoint_id ( void * devt, A_UINT8 ac)
+ar6000_ac2_endpoint_id ( void * devt, u8 ac)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *) devt;
+    struct ar6_softc *ar = (struct ar6_softc *) devt;
     return(arAc2EndpointID(ar, ac));
 }
 
-A_UINT8
-ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep )
+u8 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep )
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *) devt;
+    struct ar6_softc *ar = (struct ar6_softc *) devt;
     return(arEndpoint2Ac(ar, ep ));
 }
 
-/* This function does one time initialization for the lifetime of the device */
-int ar6000_init(struct net_device *dev)
+/*
+ * This function applies WLAN specific configuration defined in wlan_config.h
+ */
+int ar6000_target_config_wlan_params(struct ar6_softc *ar)
 {
-    AR_SOFTC_T *ar;
-    A_STATUS    status;
-    A_INT32     timeleft;
-    A_INT16     i;
-    int         ret = 0;
+    int status = 0;
 #if defined(INIT_MODE_DRV_ENABLED) && defined(ENABLE_COEXISTENCE)
     WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD sbcb_cmd;
     WMI_SET_BTCOEX_FE_ANT_CMD sbfa_cmd;
 #endif /* INIT_MODE_DRV_ENABLED && ENABLE_COEXISTENCE */
 
+#ifdef CONFIG_HOST_TCMD_SUPPORT
+    if (ar->arTargetMode != AR6000_WLAN_MODE) {
+        return 0;
+    }
+#endif /* CONFIG_HOST_TCMD_SUPPORT */
+
+    /* 
+     * configure the device for rx dot11 header rules 0,0 are the default values
+     * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required
+     * if checksum offload is needed. Set RxMetaVersion to 2
+     */
+    if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n"));
+        status = A_ERROR;
+    }
+
+#if defined(INIT_MODE_DRV_ENABLED) && defined(ENABLE_COEXISTENCE)
+    /* Configure the type of BT collocated with WLAN */
+    memset(&sbcb_cmd, 0, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
+#ifdef CONFIG_AR600x_BT_QCOM
+    sbcb_cmd.btcoexCoLocatedBTdev = 1;
+#elif defined(CONFIG_AR600x_BT_CSR)
+    sbcb_cmd.btcoexCoLocatedBTdev = 2;
+#elif defined(CONFIG_AR600x_BT_AR3001)
+    sbcb_cmd.btcoexCoLocatedBTdev = 3;
+#else
+#error Unsupported Bluetooth Type
+#endif /* Collocated Bluetooth Type */
+
+    if ((wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set collocated BT type\n"));
+        status = A_ERROR;
+    }
+
+    /* Configure the type of BT collocated with WLAN */
+    memset(&sbfa_cmd, 0, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
+#ifdef CONFIG_AR600x_DUAL_ANTENNA
+    sbfa_cmd.btcoexFeAntType = 2;
+#elif defined(CONFIG_AR600x_SINGLE_ANTENNA)
+    sbfa_cmd.btcoexFeAntType = 1;
+#else
+#error Unsupported Front-End Antenna Configuration
+#endif /* AR600x Front-End Antenna Configuration */
+
+    if ((wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set fornt end antenna configuration\n"));
+        status = A_ERROR;
+    }
+#endif /* INIT_MODE_DRV_ENABLED && ENABLE_COEXISTENCE */
+
+#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
+    if ((wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power save fail event policy\n"));
+        status = A_ERROR;
+    }
+#endif
+
+#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
+    if ((wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set barker preamble policy\n"));
+        status = A_ERROR;
+    }
+#endif
+
+    if ((wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set keep alive interval\n"));
+        status = A_ERROR;
+    }
+
+#if WLAN_CONFIG_DISABLE_11N
+    {
+        WMI_SET_HT_CAP_CMD htCap;
+
+        memset(&htCap, 0, sizeof(WMI_SET_HT_CAP_CMD));
+        htCap.band = 0;
+        if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) {
+            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n"));
+            status = A_ERROR;
+        }
+
+        htCap.band = 1;
+        if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) {
+            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n"));
+            status = A_ERROR;
+        }
+    }
+#endif /* WLAN_CONFIG_DISABLE_11N */
+
+#ifdef ATH6K_CONFIG_OTA_MODE
+    if ((wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power mode \n"));
+        status = A_ERROR;
+    }
+#endif
+
+    if ((wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set disconnect timeout \n"));
+        status = A_ERROR;
+    }
+
+#if WLAN_CONFIG_DISABLE_TX_BURSTING  
+    if ((wmi_set_wmm_txop(ar->arWmi, WMI_TXOP_DISABLED)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set txop bursting \n"));
+        status = A_ERROR;
+    }
+#endif 
+
+    return status;
+}
+
+/* This function does one time initialization for the lifetime of the device */
+int ar6000_init(struct net_device *dev)
+{
+    struct ar6_softc *ar;
+    int    status;
+    s32 timeleft;
+    s16 i;
+    int         ret = 0;
+
     if((ar = ar6k_priv(dev)) == NULL)
     {
         return -EIO;
@@ -2465,7 +2575,7 @@ int ar6000_init(struct net_device *dev)
 
     /* Do we need to finish the BMI phase */
     if ((wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) && 
-        (BMIDone(ar->arHifDevice) != A_OK))
+        (BMIDone(ar->arHifDevice) != 0))
     {
         ret = -EIO;
         goto ar6000_init_done;
@@ -2482,7 +2592,7 @@ int ar6000_init(struct net_device *dev)
 #endif
 
         /* Indicate that WMI is enabled (although not ready yet) */
-        ar->arWmiEnabled = TRUE;
+        ar->arWmiEnabled = true;
         if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", __func__));
@@ -2495,14 +2605,14 @@ int ar6000_init(struct net_device *dev)
     }
 
     do {
-        HTC_SERVICE_CONNECT_REQ connect;
+        struct htc_service_connect_req connect;
 
             /* 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,
              */
         status = HTCWaitTarget(ar->arHtcTarget);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2533,7 +2643,7 @@ int ar6000_init(struct net_device *dev)
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI CONTROL");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2555,7 +2665,7 @@ int ar6000_init(struct net_device *dev)
              * of 0-3 */
             connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
             connect.ConnectionFlags |=
-                        ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
+                        ((u16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
         }
             /* connect to best-effort service */
         connect.ServiceID = WMI_DATA_BE_SVC;
@@ -2563,7 +2673,7 @@ int ar6000_init(struct net_device *dev)
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA BE");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2573,7 +2683,7 @@ int ar6000_init(struct net_device *dev)
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA BK");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2583,7 +2693,7 @@ int ar6000_init(struct net_device *dev)
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA VI");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2596,7 +2706,7 @@ int ar6000_init(struct net_device *dev)
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA VO");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2613,12 +2723,12 @@ int ar6000_init(struct net_device *dev)
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
         if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) {
-            HCI_TRANSPORT_MISC_HANDLES hciHandles;
+            struct hci_transport_misc_handles hciHandles;
 
             hciHandles.netDevice = ar->arNetDev;
             hciHandles.hifDevice = ar->arHifDevice;
             hciHandles.htcHandle = ar->arHtcTarget;
-            status = (A_STATUS)(ar6kHciTransCallbacks.setupTransport(&hciHandles));
+            status = (int)(ar6kHciTransCallbacks.setupTransport(&hciHandles));
         }
 #else
         if (setuphci) {
@@ -2634,9 +2744,9 @@ int ar6000_init(struct net_device *dev)
           status = ar6k_setup_hci_pal(ar);
 #endif
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         ret = -EIO;
         goto ar6000_init_done;
     }
@@ -2671,10 +2781,10 @@ int ar6000_init(struct net_device *dev)
     /* start HTC */
     status = HTCStart(ar->arHtcTarget);
 
-    if (status != A_OK) {
-        if (ar->arWmiEnabled == TRUE) {
+    if (status) {
+        if (ar->arWmiEnabled == true) {
             wmi_shutdown(ar->arWmi);
-            ar->arWmiEnabled = FALSE;
+            ar->arWmiEnabled = false;
             ar->arWmi = NULL;
         }
         ar6000_cookie_cleanup(ar);
@@ -2685,7 +2795,7 @@ int ar6000_init(struct net_device *dev)
     if (!bypasswmi) {
         /* Wait for Wmi event to be ready */
         timeleft = wait_event_interruptible_timeout(arEvent,
-            (ar->arWmiReady == TRUE), wmitimeout * HZ);
+            (ar->arWmiReady == true), wmitimeout * HZ);
 
         if (ar->arVersion.abi_ver != AR6K_ABI_VERSION) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ABI Version mismatch: Host(0x%x), Target(0x%x)\n", AR6K_ABI_VERSION, ar->arVersion.abi_ver));
@@ -2705,49 +2815,10 @@ int ar6000_init(struct net_device *dev)
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__));
 
         /* Communicate the wmi protocol verision to the target */
-        if ((ar6000_set_host_app_area(ar)) != A_OK) {
+        if ((ar6000_set_host_app_area(ar)) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n"));
         }
-
-        /* configure the device for rx dot11 header rules 0,0 are the default values
-         * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required
-         if checksum offload is needed. Set RxMetaVersion to 2*/
-        if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != A_OK) {
-            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n"));
-        }
-
-#if defined(INIT_MODE_DRV_ENABLED) && defined(ENABLE_COEXISTENCE)
-        /* Configure the type of BT collocated with WLAN */
-        A_MEMZERO(&sbcb_cmd, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
-#ifdef CONFIG_AR600x_BT_QCOM
-        sbcb_cmd.btcoexCoLocatedBTdev = 1;
-#elif defined(CONFIG_AR600x_BT_CSR)
-        sbcb_cmd.btcoexCoLocatedBTdev = 2;
-#elif defined(CONFIG_AR600x_BT_AR3001)
-        sbcb_cmd.btcoexCoLocatedBTdev = 3;
-#else
-#error Unsupported Bluetooth Type
-#endif /* Collocated Bluetooth Type */
-
-        if ((wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd)) != A_OK)
-        {
-            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set collocated BT type\n"));
-        }
-
-        /* Configure the type of BT collocated with WLAN */
-        A_MEMZERO(&sbfa_cmd, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
-#ifdef CONFIG_AR600x_DUAL_ANTENNA
-        sbfa_cmd.btcoexFeAntType = 2;
-#elif defined(CONFIG_AR600x_SINGLE_ANTENNA)
-        sbfa_cmd.btcoexFeAntType = 1;
-#else
-#error Unsupported Front-End Antenna Configuration
-#endif /* AR600x Front-End Antenna Configuration */
-
-        if ((wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd)) != A_OK) {
-            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set fornt end antenna configuration\n"));
-        }
-#endif /* INIT_MODE_DRV_ENABLED && ENABLE_COEXISTENCE */
+        ar6000_target_config_wlan_params(ar);
     }
 
     ar->arNumDataEndPts = 1;
@@ -2772,27 +2843,27 @@ ar6000_init_done:
 
 
 void
-ar6000_bitrate_rx(void *devt, A_INT32 rateKbps)
+ar6000_bitrate_rx(void *devt, s32 rateKbps)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arBitRate = rateKbps;
     wake_up(&arEvent);
 }
 
 void
-ar6000_ratemask_rx(void *devt, A_UINT32 ratemask)
+ar6000_ratemask_rx(void *devt, u32 ratemask)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arRateMask = ratemask;
     wake_up(&arEvent);
 }
 
 void
-ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
+ar6000_txPwr_rx(void *devt, u8 txPwr)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arTxPwr = txPwr;
     wake_up(&arEvent);
@@ -2800,23 +2871,22 @@ ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
 
 
 void
-ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList)
+ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
-    A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16));
+    memcpy(ar->arChannelList, chanList, numChan * sizeof (u16));
     ar->arNumChannels = numChan;
 
     wake_up(&arEvent);
 }
 
-A_UINT8
-ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo)
+u8 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *mapNo)
 {
-    AR_SOFTC_T      *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8         *datap;
+    struct ar6_softc      *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 *datap;
     ATH_MAC_HDR     *macHdr;
-    A_UINT32         i, eptMap;
+    u32 i, eptMap;
 
     (*mapNo) = 0;
     datap = A_NETBUF_DATA(skb);
@@ -2844,7 +2914,7 @@ ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * map
         A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
     }
 
-    A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
+    memcpy(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
 
     for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
         if (!ar->arTxPending[i]) {
@@ -2882,22 +2952,22 @@ static void ar6000_dump_skb(struct sk_buff *skb)
 #endif
 
 #ifdef HTC_TEST_SEND_PKTS
-static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb);
+static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb);
 #endif
 
 static int
 ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
 {
 #define AC_NOT_MAPPED   99
-    AR_SOFTC_T        *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8            ac = AC_NOT_MAPPED;
+    struct ar6_softc        *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 ac = AC_NOT_MAPPED;
     HTC_ENDPOINT_ID    eid = ENDPOINT_UNUSED;
-    A_UINT32          mapNo = 0;
+    u32 mapNo = 0;
     int               len;
     struct ar_cookie *cookie;
-    A_BOOL            checkAdHocPsMapping = FALSE,bMoreData = FALSE;
+    bool            checkAdHocPsMapping = false,bMoreData = false;
     HTC_TX_TAG        htc_tag = AR6K_DATA_PKT_TAG;
-    A_UINT8           dot11Hdr = processDot11Hdr;
+    u8 dot11Hdr = processDot11Hdr;
 #ifdef CONFIG_PM
     if (ar->arWowState != WLAN_WOW_STATE_NONE) {
         A_NETBUF_FREE(skb);
@@ -2922,7 +2992,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
 
     do {
 
-        if (ar->arWmiReady == FALSE && bypasswmi == 0) {
+        if (ar->arWmiReady == false && bypasswmi == 0) {
             break;
         }
 
@@ -2944,20 +3014,20 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
              * mcastq
              */
             if (IEEE80211_IS_MULTICAST(datap->dstMac)) {
-                A_UINT8 ctr=0;
-                A_BOOL qMcast=FALSE;
+                u8 ctr=0;
+                bool qMcast=false;
 
 
                 for (ctr=0; ctr<AP_MAX_NUM_STA; ctr++) {
                     if (STA_IS_PWR_SLEEP((&ar->sta_list[ctr]))) {
-                        qMcast = TRUE;
+                        qMcast = true;
                     }
                 }
                 if(qMcast) {
 
                     /* If this transmit is not because of a Dtim Expiry q it */
-                    if (ar->DTIMExpired == FALSE) {
-                        A_BOOL isMcastqEmpty = FALSE;
+                    if (ar->DTIMExpired == false) {
+                        bool isMcastqEmpty = false;
 
                         A_MUTEX_LOCK(&ar->mcastpsqLock);
                         isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq);
@@ -2978,7 +3048,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
                       */
                          A_MUTEX_LOCK(&ar->mcastpsqLock);
                          if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
-                             bMoreData = TRUE;
+                             bMoreData = true;
                          }
                          A_MUTEX_UNLOCK(&ar->mcastpsqLock);
                     }
@@ -2989,7 +3059,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
                     if (STA_IS_PWR_SLEEP(conn)) {
                         /* If this transmit is not because of a PsPoll q it*/
                         if (!STA_IS_PS_POLLED(conn)) {
-                            A_BOOL isPsqEmpty = FALSE;
+                            bool isPsqEmpty = false;
                             /* Queue the frames if the STA is sleeping */
                             A_MUTEX_LOCK(&conn->psqLock);
                             isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq);
@@ -3010,7 +3080,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
                           */
                              A_MUTEX_LOCK(&conn->psqLock);
                              if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) {
-                                 bMoreData = TRUE;
+                                 bMoreData = true;
                              }
                              A_MUTEX_UNLOCK(&conn->psqLock);
                          }
@@ -3026,9 +3096,9 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
 
         if (ar->arWmiEnabled) {
 #ifdef CONFIG_CHECKSUM_OFFLOAD
-        A_UINT8 csumStart=0;
-        A_UINT8 csumDest=0;
-        A_UINT8 csum=skb->ip_summed;
+        u8 csumStart=0;
+        u8 csumDest=0;
+        u8 csum=skb->ip_summed;
         if(csumOffload && (csum==CHECKSUM_PARTIAL)){
             csumStart = (skb->head + skb->csum_start - skb_network_header(skb) +
 			 sizeof(ATH_LLC_SNAP_HDR));
@@ -3048,19 +3118,19 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
                     break;
                 }
                 A_NETBUF_PUT(newbuf, len);
-                A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
+                memcpy(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
                 A_NETBUF_FREE(skb);
                 skb = newbuf;
                 /* fall through and assemble header */
             }
 
             if (dot11Hdr) {
-                if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != A_OK) {
+                if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr_add failed\n"));
                     break;
                 }
             } else {
-                if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) {
+                if (wmi_dix_2_dot3(ar->arWmi, skb) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_dot3 failed\n"));
                     break;
                 }
@@ -3072,7 +3142,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
                 metaV2.csumDest = csumDest;
                 metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/
                 if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,
-                                        WMI_META_VERSION_2,&metaV2) != A_OK) {
+                                        WMI_META_VERSION_2,&metaV2) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n"));
                     break;
                 }
@@ -3081,7 +3151,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
             else
 #endif
             {
-                if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != A_OK) {
+                if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n"));
                     break;
                 }
@@ -3091,7 +3161,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
             if ((ar->arNetworkType == ADHOC_NETWORK) &&
                 ar->arIbssPsEnable && ar->arConnected) {
                     /* flag to check adhoc mapping once we take the lock below: */
-                checkAdHocPsMapping = TRUE;
+                checkAdHocPsMapping = true;
 
             } else {
                     /* get the stream mapping */
@@ -3115,7 +3185,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
                 if (ac == HCI_TRANSPORT_STREAM_NUM) {
                         /* pass this to HCI */
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
-                    if (A_SUCCESS(hci_test_send(ar,skb))) {
+                    if (!hci_test_send(ar,skb)) {
                         return 0;
                     }
 #endif
@@ -3136,7 +3206,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
         /* did we succeed ? */
     if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) {
@@ -3173,7 +3243,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
             ar->arTotalTxDataPending++;
         }
 
-    } while (FALSE);
+    } while (false);
 
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
@@ -3211,7 +3281,7 @@ ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
 int
 ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev)
 {
-    AR_SOFTC_T        *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc        *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct ar_cookie *cookie;
     HTC_ENDPOINT_ID    eid = ENDPOINT_UNUSED;
 
@@ -3267,13 +3337,13 @@ tvsub(register struct timeval *out, register struct timeval *in)
 }
 
 void
-applyAPTCHeuristics(AR_SOFTC_T *ar)
+applyAPTCHeuristics(struct ar6_softc *ar)
 {
-    A_UINT32 duration;
-    A_UINT32 numbytes;
-    A_UINT32 throughput;
+    u32 duration;
+    u32 numbytes;
+    u32 throughput;
     struct timeval ts;
-    A_STATUS status;
+    int status;
 
     AR6000_SPIN_LOCK(&ar->arLock, 0);
 
@@ -3292,12 +3362,12 @@ applyAPTCHeuristics(AR_SOFTC_T *ar)
             throughput = ((numbytes * 8) / duration);
             if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) {
                 /* Disable Sleep and schedule a timer */
-                A_ASSERT(ar->arWmiReady == TRUE);
+                A_ASSERT(ar->arWmiReady == true);
                 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
                 status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
                 AR6000_SPIN_LOCK(&ar->arLock, 0);
                 A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
-                aptcTR.timerScheduled = TRUE;
+                aptcTR.timerScheduled = true;
             }
         }
     }
@@ -3306,11 +3376,11 @@ applyAPTCHeuristics(AR_SOFTC_T *ar)
 }
 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
 
-static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPacket)
+static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T     *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc     *ar = (struct ar6_softc *)Context;
     HTC_SEND_FULL_ACTION    action = HTC_SEND_FULL_KEEP;
-    A_BOOL                  stopNet = FALSE;
+    bool                  stopNet = false;
     HTC_ENDPOINT_ID         Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket);
 
     do {
@@ -3327,10 +3397,10 @@ static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
                 /* for endpoint ping testing drop Best Effort and Background */
             if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) {
                 action = HTC_SEND_FULL_DROP;
-                stopNet = FALSE;
+                stopNet = false;
             } else {
                     /* keep but stop the netqueues */
-                stopNet = TRUE;
+                stopNet = true;
             }
             break;
         }
@@ -3341,11 +3411,11 @@ static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
                  * the only exception to this is during testing using endpointping */
             AR6000_SPIN_LOCK(&ar->arLock, 0);
                 /* set flag to handle subsequent messages */
-            ar->arWMIControlEpFull = TRUE;
+            ar->arWMIControlEpFull = true;
             AR6000_SPIN_UNLOCK(&ar->arLock, 0);
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n"));
                 /* no need to stop the network */
-            stopNet = FALSE;
+            stopNet = false;
             break;
         }
 
@@ -3359,7 +3429,7 @@ static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
         if (ar->arNetworkType == ADHOC_NETWORK) {
             /* in adhoc mode, we cannot differentiate traffic priorities so there is no need to
              * continue, however we should stop the network */
-            stopNet = TRUE;
+            stopNet = true;
             break;
         }
         /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the highest
@@ -3371,15 +3441,15 @@ static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
                  * HTC to drop the packet that overflowed */
             action = HTC_SEND_FULL_DROP;
                 /* since we are dropping packets, no need to stop the network */
-            stopNet = FALSE;
+            stopNet = false;
             break;
         }
 
-    } while (FALSE);
+    } while (false);
 
     if (stopNet) {
         AR6000_SPIN_LOCK(&ar->arLock, 0);
-        ar->arNetQueueStopped = TRUE;
+        ar->arNetQueueStopped = true;
         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         /* one of the data endpoints queues is getting full..need to stop network stack
          * the queue will resume in ar6000_tx_complete() */
@@ -3391,18 +3461,18 @@ static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPac
 
 
 static void
-ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
+ar6000_tx_complete(void *Context, struct htc_packet_queue *pPacketQueue)
 {
-    AR_SOFTC_T     *ar = (AR_SOFTC_T *)Context;
-    A_UINT32        mapNo = 0;
-    A_STATUS        status;
+    struct ar6_softc     *ar = (struct ar6_softc *)Context;
+    u32 mapNo = 0;
+    int        status;
     struct ar_cookie * ar_cookie;
     HTC_ENDPOINT_ID   eid;
-    A_BOOL          wakeEvent = FALSE;
+    bool          wakeEvent = false;
     struct sk_buff_head  skb_queue;
-    HTC_PACKET      *pPacket;
+    struct htc_packet      *pPacket;
     struct sk_buff  *pktSkb;
-    A_BOOL          flushing = FALSE;
+    bool          flushing = false;
 
     skb_queue_head_init(&skb_queue);
 
@@ -3428,7 +3498,7 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
             /* add this to the list, use faster non-lock API */
         __skb_queue_tail(&skb_queue,pktSkb);
 
-        if (A_SUCCESS(status)) {
+        if (!status) {
             A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb));
         }
 
@@ -3447,18 +3517,18 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
         {
             if (ar->arWMIControlEpFull) {
                     /* since this packet completed, the WMI EP is no longer full */
-                ar->arWMIControlEpFull = FALSE;
+                ar->arWMIControlEpFull = false;
             }
 
             if (ar->arTxPending[eid] == 0) {
-                wakeEvent = TRUE;
+                wakeEvent = true;
             }
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             if (status == A_ECANCELED) {
                     /* a packet was flushed  */
-                flushing = TRUE;
+                flushing = true;
             }
             AR6000_STAT_INC(ar, tx_errors);
             if (status != A_NO_RESOURCE) {
@@ -3467,7 +3537,7 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
             }
         } else {
             AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n"));
-            flushing = FALSE;
+            flushing = false;
             AR6000_STAT_INC(ar, tx_packets);
             ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb);
 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
@@ -3484,7 +3554,7 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
             ar->arNodeMap[mapNo].txPending --;
 
             if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
-                A_UINT32 i;
+                u32 i;
                 for (i = ar->arNodeNum; i > 0; i --) {
                     if (!ar->arNodeMap[i - 1].txPending) {
                         A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping));
@@ -3499,7 +3569,7 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
         ar6000_free_cookie(ar, ar_cookie);
 
         if (ar->arNetQueueStopped) {
-            ar->arNetQueueStopped = FALSE;
+            ar->arNetQueueStopped = false;
         }
     }
 
@@ -3514,7 +3584,7 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
         A_NETBUF_FREE(pktSkb);
     }
 
-    if ((ar->arConnected == TRUE) || (bypasswmi)) {
+    if ((ar->arConnected == true) || bypasswmi) {
         if (!flushing) {
                 /* don't wake the queue if we are flushing, other wise it will just
                  * keep queueing packets, which will keep failing */
@@ -3529,10 +3599,10 @@ ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
 }
 
 sta_t *
-ieee80211_find_conn(AR_SOFTC_T *ar, A_UINT8 *node_addr)
+ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr)
 {
     sta_t *conn = NULL;
-    A_UINT8 i, max_conn;
+    u8 i, max_conn;
 
     switch(ar->arNetworkType) {
         case AP_NETWORK:
@@ -3553,10 +3623,10 @@ ieee80211_find_conn(AR_SOFTC_T *ar, A_UINT8 *node_addr)
     return conn;
 }
 
-sta_t *ieee80211_find_conn_for_aid(AR_SOFTC_T *ar, A_UINT8 aid)
+sta_t *ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid)
 {
     sta_t *conn = NULL;
-    A_UINT8 ctr;
+    u8 ctr;
 
     for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
         if (ar->sta_list[ctr].aid == aid) {
@@ -3572,22 +3642,22 @@ sta_t *ieee80211_find_conn_for_aid(AR_SOFTC_T *ar, A_UINT8 aid)
  */
 int pktcount;
 static void
-ar6000_rx(void *Context, HTC_PACKET *pPacket)
+ar6000_rx(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc *ar = (struct ar6_softc *)Context;
     struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
     int minHdrLen;
-    A_UINT8 containsDot11Hdr = 0;
-    A_STATUS        status = pPacket->Status;
+    u8 containsDot11Hdr = 0;
+    int        status = pPacket->Status;
     HTC_ENDPOINT_ID   ept = pPacket->Endpoint;
 
-    A_ASSERT((status != A_OK) ||
+    A_ASSERT((status) ||
              (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%lx eid=%d, skb=0x%lx, data=0x%lx, len=0x%x status:%d",
                     (unsigned long)ar, ept, (unsigned long)skb, (unsigned long)pPacket->pBuffer,
                     pPacket->ActualLength, status));
-    if (status != A_OK) {
+    if (status) {
         if (status != A_ECANCELED) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status));
         }
@@ -3597,7 +3667,7 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
          * and adaptive power throughput state */
     AR6000_SPIN_LOCK(&ar->arLock, 0);
 
-    if (A_SUCCESS(status)) {
+    if (!status) {
         AR6000_STAT_INC(ar, rx_packets);
         ar->arNetStats.rx_bytes += pPacket->ActualLength;
 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
@@ -3618,24 +3688,26 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
     skb->dev = ar->arNetDev;
-    if (status != A_OK) {
+    if (status) {
         AR6000_STAT_INC(ar, rx_errors);
         A_NETBUF_FREE(skb);
-    } else if (ar->arWmiEnabled == TRUE) {
+    } else if (ar->arWmiEnabled == true) {
         if (ept == ar->arControlEp) {
            /*
             * this is a wmi control msg
             */
 #ifdef CONFIG_PM 
-            ar6000_check_wow_status(ar, skb, TRUE);
+            ar6000_check_wow_status(ar, skb, true);
 #endif /* CONFIG_PM */
             wmi_control_rx(ar->arWmi, skb);
         } else {
                 WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
-                A_UINT8 is_amsdu, tid, is_acl_data_frame;
+                bool is_amsdu;
+                u8 tid;
+                bool is_acl_data_frame;
                 is_acl_data_frame = WMI_DATA_HDR_GET_DATA_TYPE(dhdr) == WMI_DATA_HDR_DATA_TYPE_ACL;
 #ifdef CONFIG_PM 
-                ar6000_check_wow_status(ar, NULL, FALSE);
+                ar6000_check_wow_status(ar, NULL, false);
 #endif /* CONFIG_PM */
                 /*
                  * this is a wmi data packet
@@ -3667,8 +3739,8 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                     AR6000_STAT_INC(ar, rx_length_errors);
                     A_NETBUF_FREE(skb);
                 } else {
-                    A_UINT16 seq_no;
-                    A_UINT8 meta_type;
+                    u16 seq_no;
+                    u8 meta_type;
 
 #if 0
                     /* Access RSSI values here */
@@ -3678,9 +3750,9 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                     /* Get the Power save state of the STA */
                     if (ar->arNetworkType == AP_NETWORK) {
                         sta_t *conn = NULL;
-                        A_UINT8 psState=0,prevPsState;
+                        u8 psState=0,prevPsState;
                         ATH_MAC_HDR *datap=NULL;
-                        A_UINT16 offset;
+                        u16 offset;
 
                         meta_type = WMI_DATA_HDR_GET_META(dhdr);
 
@@ -3742,7 +3814,7 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                             }
                         } else {
                             /* This frame is from a STA that is not associated*/
-                            A_ASSERT(FALSE);
+                            A_ASSERT(false);
                         }
 
                         /* Drop NULL data frames here */
@@ -3753,7 +3825,7 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                         }
                     }
 
-                    is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr);
+                    is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr) ? true : false;
                     tid = WMI_DATA_HDR_GET_UP(dhdr);
                     seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr);
                     meta_type = WMI_DATA_HDR_GET_META(dhdr);
@@ -3785,7 +3857,7 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                             break;
                     }
 
-                    A_ASSERT(status == A_OK);
+                    A_ASSERT(status == 0);
 
                     /* NWF: print the 802.11 hdr bytes */
                     if(containsDot11Hdr) {
@@ -3794,7 +3866,7 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                         status = wmi_dot3_2_dix(skb);
                     }
 
-                    if (status != A_OK) {
+                    if (status) {
                         /* Drop frames that could not be processed (lack of memory, etc.) */
                         A_NETBUF_FREE(skb);
                         goto rx_done;
@@ -3805,7 +3877,7 @@ ar6000_rx(void *Context, HTC_PACKET *pPacket)
                         *((short *)A_NETBUF_DATA(skb)) = WMI_ACL_DATA_EVENTID;
 	                /* send the data packet to PAL driver */
 			if(ar6k_pal_config_g.fpar6k_pal_recv_pkt) {
-				if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, skb) == TRUE)
+				if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, skb) == true)
 					goto rx_done;
 			}
                     }
@@ -3870,7 +3942,7 @@ ar6000_deliver_frames_to_nw_stack(void *dev, void *osbuf)
         skb->dev = dev;
         if ((skb->dev->flags & IFF_UP) == IFF_UP) {
 #ifdef CONFIG_PM 
-            ar6000_check_wow_status((AR_SOFTC_T *)ar6k_priv(dev), skb, FALSE);   
+            ar6000_check_wow_status((struct ar6_softc *)ar6k_priv(dev), skb, false);
 #endif /* CONFIG_PM */
             skb->protocol = eth_type_trans(skb, skb->dev);
         /*
@@ -3915,12 +3987,12 @@ ar6000_deliver_frames_to_bt_stack(void *dev, void *osbuf)
 static void
 ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
 {
-    AR_SOFTC_T  *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc  *ar = (struct ar6_softc *)Context;
     void        *osBuf;
     int         RxBuffers;
     int         buffersToRefill;
-    HTC_PACKET  *pPacket;
-    HTC_PACKET_QUEUE queue;
+    struct htc_packet  *pPacket;
+    struct htc_packet_queue queue;
 
     buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
                                     HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoint);
@@ -3942,7 +4014,7 @@ ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
         }
             /* the HTC packet wrapper is at the head of the reserved area
              * in the skb */
-        pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
+        pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf));
             /* set re-fill info */
         SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint);
             /* add to queue */
@@ -3957,13 +4029,13 @@ ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
 }
 
   /* clean up our amsdu buffer list */
-static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar)
+static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar)
 {
-    HTC_PACKET  *pPacket;
+    struct htc_packet  *pPacket;
     void        *osBuf;
 
         /* empty AMSDU buffer queue and free OS bufs */
-    while (TRUE) {
+    while (true) {
 
         AR6000_SPIN_LOCK(&ar->arLock, 0);
         pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue);
@@ -3975,7 +4047,7 @@ static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar)
 
         osBuf = pPacket->pPktContext;
         if (NULL == osBuf) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -3986,9 +4058,9 @@ static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar)
 
 
     /* refill the amsdu buffer list */
-static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count)
+static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count)
 {
-    HTC_PACKET  *pPacket;
+    struct htc_packet  *pPacket;
     void        *osBuf;
 
     while (Count > 0) {
@@ -3998,7 +4070,7 @@ static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count)
         }
             /* the HTC packet wrapper is at the head of the reserved area
              * in the skb */
-        pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
+        pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf));
             /* set re-fill info */
         SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_AMSDU_BUFFER_SIZE,0);
 
@@ -4018,10 +4090,10 @@ static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count)
      * keep the allocation size the same to optimize cached-slab allocations.
      *
      * */
-static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length)
+static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length)
 {
-    HTC_PACKET  *pPacket = NULL;
-    AR_SOFTC_T  *ar = (AR_SOFTC_T *)Context;
+    struct htc_packet  *pPacket = NULL;
+    struct ar6_softc  *ar = (struct ar6_softc *)Context;
     int         refillCount = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length:%d\n",Endpoint,Length));
@@ -4030,12 +4102,12 @@ static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpo
 
         if (Length <= AR6000_BUFFER_SIZE) {
                 /* shouldn't be getting called on normal sized packets */
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
         if (Length > AR6000_AMSDU_BUFFER_SIZE) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -4052,7 +4124,7 @@ static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpo
             /* set actual endpoint ID */
         pPacket->Endpoint = Endpoint;
 
-    } while (FALSE);
+    } while (false);
 
     if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) {
         ar6000_refill_amsdu_rxbufs(ar,refillCount);
@@ -4070,19 +4142,19 @@ ar6000_set_multicast_list(struct net_device *dev)
 static struct net_device_stats *
 ar6000_get_stats(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     return &ar->arNetStats;
 }
 
 static struct iw_statistics *
 ar6000_get_iwstats(struct net_device * dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     TARGET_STATS *pStats = &ar->arTargetStats;
     struct iw_statistics * pIwStats = &ar->arIwStats;
     int rtnllocked;
 
-    if (ar->bIsDestroyProgress || ar->arWmiReady == FALSE || ar->arWlanState == WLAN_DISABLED)
+    if (ar->bIsDestroyProgress || ar->arWmiReady == false || ar->arWlanState == WLAN_DISABLED)
     {
         pIwStats->status = 0;
         pIwStats->qual.qual = 0;
@@ -4132,13 +4204,13 @@ ar6000_get_iwstats(struct net_device * dev)
             break;
         }
     
-        ar->statsUpdatePending = TRUE;
+        ar->statsUpdatePending = true;
     
-        if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+        if(wmi_get_stats_cmd(ar->arWmi) != 0) {
             break;
         }
     
-        wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+        wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
         if (signal_pending(current)) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000 : WMI get stats timeout \n"));
             break;
@@ -4162,12 +4234,12 @@ err_exit:
 }
 
 void
-ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap, A_UINT32 sw_ver, A_UINT32 abi_ver)
+ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
     struct net_device *dev = ar->arNetDev;
 
-    A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
+    memcpy(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
         dev->dev_addr[0], dev->dev_addr[1],
         dev->dev_addr[2], dev->dev_addr[3],
@@ -4178,43 +4250,18 @@ ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap, A_UINT32 sw_ver,
     ar->arVersion.abi_ver = abi_ver;
 
     /* Indicate to the waiting thread that the ready event was received */
-    ar->arWmiReady = TRUE;
+    ar->arWmiReady = true;
     wake_up(&arEvent);
-
-#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
-    wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN);
-#endif
-#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
-    wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP);
-#endif
-    wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL);
-#if WLAN_CONFIG_DISABLE_11N
-    {
-        WMI_SET_HT_CAP_CMD htCap;
-
-        A_MEMZERO(&htCap, sizeof(WMI_SET_HT_CAP_CMD));
-        htCap.band = 0;
-        wmi_set_ht_cap_cmd(ar->arWmi, &htCap);
-
-        htCap.band = 1;
-        wmi_set_ht_cap_cmd(ar->arWmi, &htCap);
-    }
-#endif /* WLAN_CONFIG_DISABLE_11N */
-
-#ifdef ATH6K_CONFIG_OTA_MODE
-    wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
-#endif
-    wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT);
 }
 
 void
-add_new_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 aid, A_UINT8 *wpaie,
-            A_UINT8 ielen, A_UINT8 keymgmt, A_UINT8 ucipher, A_UINT8 auth)
+add_new_sta(struct ar6_softc *ar, u8 *mac, u16 aid, u8 *wpaie,
+            u8 ielen, u8 keymgmt, u8 ucipher, u8 auth)
 {
-    A_UINT8    free_slot=aid-1;
+    u8 free_slot=aid-1;
 
-        A_MEMCPY(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN);
-        A_MEMCPY(ar->sta_list[free_slot].wpa_ie, wpaie, ielen);
+        memcpy(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN);
+        memcpy(ar->sta_list[free_slot].wpa_ie, wpaie, ielen);
         ar->sta_list[free_slot].aid = aid;
         ar->sta_list[free_slot].keymgmt = keymgmt;
         ar->sta_list[free_slot].ucipher = ucipher;
@@ -4224,11 +4271,11 @@ add_new_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 aid, A_UINT8 *wpaie,
 }
 
 void
-ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
-                     A_UINT16 listenInterval, A_UINT16 beaconInterval,
-                     NETWORK_TYPE networkType, A_UINT8 beaconIeLen,
-                     A_UINT8 assocReqLen, A_UINT8 assocRespLen,
-                     A_UINT8 *assocInfo)
+ar6000_connect_event(struct ar6_softc *ar, u16 channel, u8 *bssid,
+                     u16 listenInterval, u16 beaconInterval,
+                     NETWORK_TYPE networkType, u8 beaconIeLen,
+                     u8 assocReqLen, u8 assocRespLen,
+                     u8 *assocInfo)
 {
     union iwreq_data wrqu;
     int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos;
@@ -4237,14 +4284,14 @@ ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
     static const char *beaconIetag = "BEACONIE=";
     char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1];
     char *pos;
-    A_UINT8 key_op_ctrl;
+    u8 key_op_ctrl;
     unsigned long flags;
     struct ieee80211req_key *ik;
     CRYPTO_TYPE keyType = NONE_CRYPT;
 
     if(ar->arNetworkType & AP_NETWORK) {
         struct net_device *dev = ar->arNetDev;
-        if(A_MEMCMP(dev->dev_addr, bssid, ATH_MAC_LEN)==0) {
+        if(memcmp(dev->dev_addr, bssid, ATH_MAC_LEN)==0) {
             ar->arACS = channel;
             ik = &ar->ap_mode_bkey;
 
@@ -4273,14 +4320,14 @@ ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
                        goto skip_key;
                 }
                 wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE,
-                                ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
+                                ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
                                 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
                                 SYNC_BOTH_WMIFLAG);
 
                 break;
             }
 skip_key:
-            ar->arConnected  = TRUE;
+            ar->arConnected  = true;
             return;
         }
 
@@ -4336,7 +4383,7 @@ skip_key:
 
         /* Send event to application */
         A_MEMZERO(&wrqu, sizeof(wrqu));
-        A_MEMCPY(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
+        memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
         wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL);
         /* In case the queue is stopped when we switch modes, this will
          * wake it up
@@ -4353,7 +4400,7 @@ skip_key:
                                 assocInfo);
 #endif /* ATH6K_CONFIG_CFG80211 */
 
-    A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid));
+    memcpy(ar->arBssid, bssid, sizeof(ar->arBssid));
     ar->arBssChannel = channel;
 
     A_PRINTF("AR6000 connected event on freq %d ", channel);
@@ -4400,9 +4447,9 @@ skip_key:
     if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
     {
         assoc_resp_ie_pos = beaconIeLen + assocReqLen +
-                            sizeof(A_UINT16)  +  /* capinfo*/
-                            sizeof(A_UINT16)  +  /* status Code */
-                            sizeof(A_UINT16)  ;  /* associd */
+                            sizeof(u16)  +  /* capinfo*/
+                            sizeof(u16)  +  /* status Code */
+                            sizeof(u16)  ;  /* associd */
         A_MEMZERO(buf, sizeof(buf));
         sprintf(buf, "%s", tag2);
         pos = buf + 12;
@@ -4429,8 +4476,8 @@ skip_key:
          * assoc Request includes capability and listen interval. Skip these.
          */
         assoc_req_ie_pos =  beaconIeLen +
-                            sizeof(A_UINT16)  +  /* capinfo*/
-                            sizeof(A_UINT16);    /* listen interval */
+                            sizeof(u16)  +  /* capinfo*/
+                            sizeof(u16);    /* listen interval */
 
         A_MEMZERO(buf, sizeof(buf));
         sprintf(buf, "%s", tag1);
@@ -4450,7 +4497,7 @@ skip_key:
 
 #ifdef USER_KEYS
     if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
-        ar->user_saved_keys.keyOk == TRUE)
+        ar->user_saved_keys.keyOk == true)
     {
         key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC;
 
@@ -4487,8 +4534,8 @@ skip_key:
 
     /* Update connect & link status atomically */
     spin_lock_irqsave(&ar->arLock, flags);
-    ar->arConnected  = TRUE;
-    ar->arConnectPending = FALSE;
+    ar->arConnected  = true;
+    ar->arConnectPending = false;
     netif_carrier_on(ar->arNetDev);
     spin_unlock_irqrestore(&ar->arLock, flags);
     /* reset the rx aggr state */
@@ -4496,7 +4543,7 @@ skip_key:
     reconnect_flag = 0;
 
     A_MEMZERO(&wrqu, sizeof(wrqu));
-    A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
+    memcpy(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
     wrqu.addr.sa_family = ARPHRD_ETHER;
     wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
     if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) {
@@ -4510,14 +4557,14 @@ skip_key:
 
 }
 
-void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num)
+void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num)
 {
     A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
     ar->arNumDataEndPts = num;
 }
 
 void
-sta_cleanup(AR_SOFTC_T *ar, A_UINT8 i)
+sta_cleanup(struct ar6_softc *ar, u8 i)
 {
     struct sk_buff *skb;
 
@@ -4540,10 +4587,9 @@ sta_cleanup(AR_SOFTC_T *ar, A_UINT8 i)
 
 }
 
-A_UINT8
-remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason)
+u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason)
 {
-    A_UINT8 i, removed=0;
+    u8 i, removed=0;
 
     if(IS_MAC_NULL(mac)) {
         return removed;
@@ -4559,7 +4605,7 @@ remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason)
         }
     } else {
         for(i=0; i < AP_MAX_NUM_STA; i++) {
-            if(A_MEMCMP(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) {
+            if(memcmp(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) {
                 A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
                 " aid=%d REASON=%d\n", mac[0], mac[1], mac[2],
                  mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason);
@@ -4574,10 +4620,10 @@ remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason)
 }
 
 void
-ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
-                        A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
+ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, u8 *bssid,
+                        u8 assocRespLen, u8 *assocInfo, u16 protocolReasonStatus)
 {
-    A_UINT8 i;
+    u8 i;
     unsigned long flags;
     union iwreq_data wrqu;
 
@@ -4607,9 +4653,11 @@ ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
         if(!IS_MAC_BCAST(bssid)) {
             /* Send event to application */
             A_MEMZERO(&wrqu, sizeof(wrqu));
-            A_MEMCPY(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
+            memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
             wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL);
         }
+
+        ar->arConnected = false;
         return;
     }
 
@@ -4654,15 +4702,14 @@ ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
      */
     if( reason == DISCONNECT_CMD)
     {
-        ar->arConnectPending = FALSE;
         if ((!ar->arUserBssFilter) && (ar->arWmiReady)) {
             wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
         }
     } else {
-        ar->arConnectPending = TRUE;
+        ar->arConnectPending = true;
         if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
             ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
-            ar->arConnected = TRUE;
+            ar->arConnected = true;
             return;
         }
     }
@@ -4684,7 +4731,7 @@ ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
              * Find the nodes based on SSID and remove it
              * NOTE :: This case will not work out for Hidden-SSID
              */
-            pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, FALSE, TRUE);
+            pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, false, true);
 
             if (pWmiSsidnode)
             {
@@ -4696,7 +4743,7 @@ ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
 
     /* Update connect & link status atomically */
     spin_lock_irqsave(&ar->arLock, flags);
-    ar->arConnected = FALSE;
+    ar->arConnected = false;
     netif_carrier_off(ar->arNetDev);
     spin_unlock_irqrestore(&ar->arLock, flags);
 
@@ -4721,7 +4768,7 @@ ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
 }
 
 void
-ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
+ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode)
 {
     A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
     ar->arRegCode = regCode;
@@ -4729,7 +4776,7 @@ ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
 
 #ifdef ATH_AR6K_11N_SUPPORT
 void
-ar6000_aggr_rcv_addba_req_evt(AR_SOFTC_T *ar, WMI_ADDBA_REQ_EVENT *evt)
+ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *evt)
 {
     if(evt->status == 0) {
         aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->win_sz);
@@ -4737,7 +4784,7 @@ ar6000_aggr_rcv_addba_req_evt(AR_SOFTC_T *ar, WMI_ADDBA_REQ_EVENT *evt)
 }
 
 void
-ar6000_aggr_rcv_addba_resp_evt(AR_SOFTC_T *ar, WMI_ADDBA_RESP_EVENT *evt)
+ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *evt)
 {
     A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt->amsdu_sz);
     if(evt->status == 0) {
@@ -4745,7 +4792,7 @@ ar6000_aggr_rcv_addba_resp_evt(AR_SOFTC_T *ar, WMI_ADDBA_RESP_EVENT *evt)
 }
 
 void
-ar6000_aggr_rcv_delba_req_evt(AR_SOFTC_T *ar, WMI_DELBA_EVENT *evt)
+ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *evt)
 {
     aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid);
 }
@@ -4760,9 +4807,9 @@ void
 ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd)
 {
     void *osbuf = NULL;
-    A_INT8 i;
-    A_UINT8 size, *buf;
-    A_STATUS ret = A_OK;
+    s8 i;
+    u8 size, *buf;
+    int ret = 0;
 
     size = cmd->evt_buf_sz + 4;
     osbuf = A_NETBUF_ALLOC(size);
@@ -4773,18 +4820,18 @@ ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd)
     }
 
     A_NETBUF_PUT(osbuf, size);
-    buf = (A_UINT8 *)A_NETBUF_DATA(osbuf);
+    buf = (u8 *)A_NETBUF_DATA(osbuf);
     /* First 2-bytes carry HCI event/ACL data type
      * the next 2 are free
      */
     *((short *)buf) = WMI_HCI_EVENT_EVENTID;
     buf += sizeof(int);
-    A_MEMCPY(buf, cmd->buf, cmd->evt_buf_sz);
+    memcpy(buf, cmd->buf, cmd->evt_buf_sz);
 
     if(ar6k_pal_config_g.fpar6k_pal_recv_pkt)
     {
       /* pass the cmd packet to PAL driver */
-      if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, osbuf) == TRUE)
+      if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, osbuf) == true)
         return;
     }
     ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf);
@@ -4802,7 +4849,7 @@ ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd)
 }
 
 void
-ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
+ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, WMI_NEIGHBOR_INFO *info)
 {
 #if WIRELESS_EXT >= 18
     struct iw_pmkid_cand *pmkcand;
@@ -4833,7 +4880,7 @@ ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
         A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand));
         pmkcand->index = i;
         pmkcand->flags = info->bssFlags;
-        A_MEMCPY(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN);
+        memcpy(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN);
         wrqu.data.length = sizeof(struct iw_pmkid_cand);
         wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand);
         A_FREE(pmkcand);
@@ -4850,7 +4897,7 @@ ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
 }
 
 void
-ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
+ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast)
 {
     static const char *tag = "MLME-MICHAELMICFAILURE.indication";
     char buf[128];
@@ -4887,7 +4934,7 @@ ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
 }
 
 void
-ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
+ar6000_scanComplete_event(struct ar6_softc *ar, int status)
 {
 
 #ifdef ATH6K_CONFIG_CFG80211
@@ -4898,7 +4945,7 @@ ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
         wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
     }
     if (ar->scan_triggered) {
-        if (status==A_OK) {
+        if (status== 0) {
             union iwreq_data wrqu;
             A_MEMZERO(&wrqu, sizeof(wrqu));
             wireless_send_event(ar->arNetDev, SIOCGIWSCAN, &wrqu, NULL);
@@ -4910,9 +4957,9 @@ ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
 }
 
 void
-ar6000_targetStats_event(AR_SOFTC_T *ar,  A_UINT8 *ptr, A_UINT32 len)
+ar6000_targetStats_event(struct ar6_softc *ar,  u8 *ptr, u32 len)
 {
-    A_UINT8 ac;
+    u8 ac;
 
     if(ar->arNetworkType == AP_NETWORK) {
         WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr;
@@ -5028,14 +5075,14 @@ ar6000_targetStats_event(AR_SOFTC_T *ar,  A_UINT8 *ptr, A_UINT32 len)
         pStats->arp_replied  += pTarget->arpStats.arp_replied;
 
         if (ar->statsUpdatePending) {
-            ar->statsUpdatePending = FALSE;
+            ar->statsUpdatePending = false;
             wake_up(&arEvent);
         }
     }
 }
 
 void
-ar6000_rssiThreshold_event(AR_SOFTC_T *ar,  WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi)
+ar6000_rssiThreshold_event(struct ar6_softc *ar,  WMI_RSSI_THRESHOLD_VAL newThreshold, s16 rssi)
 {
     USER_RSSI_THOLD userRssiThold;
 
@@ -5051,28 +5098,28 @@ ar6000_rssiThreshold_event(AR_SOFTC_T *ar,  WMI_RSSI_THRESHOLD_VAL newThreshold,
     A_PRINTF("rssi Threshold range = %d tag = %d  rssi = %d\n", newThreshold,
              userRssiThold.tag, userRssiThold.rssi);
 
-    ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
+    ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(u8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
 }
 
 
 void
-ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source)
+ar6000_hbChallengeResp_event(struct ar6_softc *ar, u32 cookie, u32 source)
 {
     if (source == APP_HB_CHALLENGE) {
         /* Report it to the app in case it wants a positive acknowledgement */
         ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID,
-                                 (A_UINT8 *)&cookie, sizeof(cookie));
+                                 (u8 *)&cookie, sizeof(cookie));
     } else {
         /* This would ignore the replys that come in after their due time */
         if (cookie == ar->arHBChallengeResp.seqNum) {
-            ar->arHBChallengeResp.outstanding = FALSE;
+            ar->arHBChallengeResp.outstanding = false;
         }
     }
 }
 
 
 void
-ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
+ar6000_reportError_event(struct ar6_softc *ar, WMI_TARGET_ERROR_VAL errorVal)
 {
 	static const char * const errString[] = {
 		[WMI_TARGET_PM_ERR_FAIL]    "WMI_TARGET_PM_ERR_FAIL",
@@ -5107,8 +5154,8 @@ ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
 
 
 void
-ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
-                 A_UINT8 statusCode, A_UINT8 *tspecSuggestion)
+ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cacIndication,
+                 u8 statusCode, u8 *tspecSuggestion)
 {
     WMM_TSPEC_IE    *tspecIe;
 
@@ -5130,8 +5177,8 @@ ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
 }
 
 void
-ar6000_channel_change_event(AR_SOFTC_T *ar, A_UINT16 oldChannel,
-                            A_UINT16 newChannel)
+ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel,
+                            u16 newChannel)
 {
     A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n",
              oldChannel, newChannel);
@@ -5144,9 +5191,9 @@ ar6000_channel_change_event(AR_SOFTC_T *ar, A_UINT16 oldChannel,
 } while(0)
 
 void
-ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
+ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl)
 {
-    A_UINT8 i;
+    u8 i;
 
     A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n",
               pTbl->numEntries, pTbl->roamMode);
@@ -5169,9 +5216,9 @@ ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
 }
 
 void
-ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
+ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
 {
-    A_UINT8 i,j;
+    u8 i,j;
 
     /*Each event now contains exactly one filter, see bug 26613*/
     A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num,                 wow_reply->num_filters);
@@ -5223,7 +5270,7 @@ ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p)
 }
 
 void
-ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
+ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p)
 {
     switch (p->roamDataType) {
         case ROAM_DATA_TIME:
@@ -5235,7 +5282,7 @@ ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
 }
 
 void
-ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
+ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *datap, int len)
 {
     struct sk_buff *skb;
     WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
@@ -5255,9 +5302,9 @@ ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
     if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
 
         A_NETBUF_PUT(skb, len);
-        A_MEMCPY(A_NETBUF_DATA(skb), datap, len);
+        memcpy(A_NETBUF_DATA(skb), datap, len);
         skb->dev = ar->arNetDev;
-        A_MEMCPY(skb_mac_header(skb), A_NETBUF_DATA(skb), 6);
+        memcpy(skb_mac_header(skb), A_NETBUF_DATA(skb), 6);
         skb->ip_summed = CHECKSUM_NONE;
         skb->pkt_type = PACKET_OTHERHOST;
         skb->protocol = __constant_htons(0x0019);
@@ -5265,13 +5312,13 @@ ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
     }
 }
 
-A_UINT32 wmiSendCmdNum;
+u32 wmiSendCmdNum;
 
-A_STATUS
+int
 ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid)
 {
-    AR_SOFTC_T       *ar = (AR_SOFTC_T *)devt;
-    A_STATUS         status = A_OK;
+    struct ar6_softc       *ar = (struct ar6_softc *)devt;
+    int         status = 0;
     struct ar_cookie *cookie = NULL;
     int i;
 #ifdef CONFIG_PM
@@ -5306,13 +5353,13 @@ ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid)
         if(logWmiRawMsgs) {
             A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum);
             for(i = 0; i < a_netbuf_to_len(osbuf); i++)
-                A_PRINTF("%x ", ((A_UINT8 *)a_netbuf_to_data(osbuf))[i]);
+                A_PRINTF("%x ", ((u8 *)a_netbuf_to_data(osbuf))[i]);
             A_PRINTF("\n");
         }
 
         wmiSendCmdNum++;
 
-    } while (FALSE);
+    } while (false);
 
     if (cookie != NULL) {
             /* got a structure to send it out on */
@@ -5337,19 +5384,19 @@ ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid)
             /* this interface is asynchronous, if there is an error, cleanup will happen in the
              * TX completion callback */
         HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
-        status = A_OK;
+        status = 0;
     }
 
-    if (status != A_OK) {
+    if (status) {
         A_NETBUF_FREE(osbuf);
     }
     return status;
 }
 
 /* indicate tx activity or inactivity on a WMI stream */
-void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active)
+void ar6000_indicate_tx_activity(void *devt, u8 TrafficClass, bool Active)
 {
-    AR_SOFTC_T  *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc  *ar = (struct ar6_softc *)devt;
     HTC_ENDPOINT_ID eid ;
     int i;
 
@@ -5407,7 +5454,7 @@ void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active
 }
 
 void
-ar6000_btcoex_config_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len)
+ar6000_btcoex_config_event(struct ar6_softc *ar,  u8 *ptr, u32 len)
 {
 
     WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr;
@@ -5421,39 +5468,39 @@ ar6000_btcoex_config_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len)
 
     switch (pBtcoexConfig->btProfileType) {
         case WMI_BTCOEX_BT_PROFILE_SCO:
-            A_MEMCPY(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd,
+            memcpy(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd,
                                         sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
             break;
         case WMI_BTCOEX_BT_PROFILE_A2DP:
-            A_MEMCPY(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd,
+            memcpy(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd,
                                         sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
             break;
         case WMI_BTCOEX_BT_PROFILE_ACLCOEX:
-            A_MEMCPY(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig,
+            memcpy(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig,
                                         sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
             break;
         case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE:
-           A_MEMCPY(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd,
+           memcpy(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd,
                                         sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
             break;
     }
     if (ar->statsUpdatePending) {
-         ar->statsUpdatePending = FALSE;
+         ar->statsUpdatePending = false;
           wake_up(&arEvent);
     }
 }
 
 void
-ar6000_btcoex_stats_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len)
+ar6000_btcoex_stats_event(struct ar6_softc *ar,  u8 *ptr, u32 len)
 {
     WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n"));
 
-    A_MEMCPY(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT));
+    memcpy(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT));
 
     if (ar->statsUpdatePending) {
-         ar->statsUpdatePending = FALSE;
+         ar->statsUpdatePending = false;
         wake_up(&arEvent);
     }
 
@@ -5463,9 +5510,9 @@ module_exit(ar6000_cleanup_module);
 
 /* Init cookie queue */
 static void
-ar6000_cookie_init(AR_SOFTC_T *ar)
+ar6000_cookie_init(struct ar6_softc *ar)
 {
-    A_UINT32    i;
+    u32 i;
 
     ar->arCookieList = NULL;
     ar->arCookieCount = 0;
@@ -5479,7 +5526,7 @@ ar6000_cookie_init(AR_SOFTC_T *ar)
 
 /* cleanup cookie queue */
 static void
-ar6000_cookie_cleanup(AR_SOFTC_T *ar)
+ar6000_cookie_cleanup(struct ar6_softc *ar)
 {
     /* It is gone .... */
     ar->arCookieList = NULL;
@@ -5488,7 +5535,7 @@ ar6000_cookie_cleanup(AR_SOFTC_T *ar)
 
 /* Init cookie queue */
 static void
-ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie)
+ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie)
 {
     /* Insert first */
     A_ASSERT(ar != NULL);
@@ -5501,7 +5548,7 @@ ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie)
 
 /* cleanup cookie queue */
 static struct ar_cookie *
-ar6000_alloc_cookie(AR_SOFTC_T  *ar)
+ar6000_alloc_cookie(struct ar6_softc  *ar)
 {
     struct ar_cookie   *cookie;
 
@@ -5522,8 +5569,8 @@ ar6000_alloc_cookie(AR_SOFTC_T  *ar)
  * the event ID and event content.
  */
 #define EVENT_ID_LEN   2
-void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
-                              A_UINT8 *datap, int len)
+void ar6000_send_event_to_app(struct ar6_softc *ar, u16 eventId,
+                              u8 *datap, int len)
 {
 
 #if (WIRELESS_EXT >= 15)
@@ -5531,7 +5578,7 @@ void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
 /* note: IWEVCUSTOM only exists in wireless extensions after version 15 */
 
     char *buf;
-    A_UINT16 size;
+    u16 size;
     union iwreq_data wrqu;
 
     size = len + EVENT_ID_LEN;
@@ -5549,10 +5596,10 @@ void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
     }
 
     A_MEMZERO(buf, size);
-    A_MEMCPY(buf, &eventId, EVENT_ID_LEN);
-    A_MEMCPY(buf+EVENT_ID_LEN, datap, len);
+    memcpy(buf, &eventId, EVENT_ID_LEN);
+    memcpy(buf+EVENT_ID_LEN, datap, len);
 
-    //AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("event ID = %d,len = %d\n",*(A_UINT16*)buf, size));
+    //AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("event ID = %d,len = %d\n",*(u16 *)buf, size));
     A_MEMZERO(&wrqu, sizeof(wrqu));
     wrqu.data.length = size;
     wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
@@ -5567,8 +5614,8 @@ void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
  * to the application. The buf which is sent to application
  * includes the event ID and event content.
  */
-void ar6000_send_generic_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
-                                      A_UINT8 *datap, int len)
+void ar6000_send_generic_event_to_app(struct ar6_softc *ar, u16 eventId,
+                                      u8 *datap, int len)
 {
 
 #if (WIRELESS_EXT >= 18)
@@ -5576,7 +5623,7 @@ void ar6000_send_generic_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
 /* IWEVGENIE exists in wireless extensions version 18 onwards */
 
     char *buf;
-    A_UINT16 size;
+    u16 size;
     union iwreq_data wrqu;
 
     size = len + EVENT_ID_LEN;
@@ -5594,8 +5641,8 @@ void ar6000_send_generic_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
     }
 
     A_MEMZERO(buf, size);
-    A_MEMCPY(buf, &eventId, EVENT_ID_LEN);
-    A_MEMCPY(buf+EVENT_ID_LEN, datap, len);
+    memcpy(buf, &eventId, EVENT_ID_LEN);
+    memcpy(buf+EVENT_ID_LEN, datap, len);
 
     A_MEMZERO(&wrqu, sizeof(wrqu));
     wrqu.data.length = size;
@@ -5616,54 +5663,52 @@ ar6000_tx_retry_err_event(void *devt)
 }
 
 void
-ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UINT8 snr)
+ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, u8 snr)
 {
     WMI_SNR_THRESHOLD_EVENT event;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     event.range = newThreshold;
     event.snr = snr;
 
-    ar6000_send_event_to_app(ar, WMI_SNR_THRESHOLD_EVENTID, (A_UINT8 *)&event,
+    ar6000_send_event_to_app(ar, WMI_SNR_THRESHOLD_EVENTID, (u8 *)&event,
                              sizeof(WMI_SNR_THRESHOLD_EVENT));
 }
 
 void
-ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT8 lq)
+ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, u8 lq)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThreshold, lq));
 }
 
 
 
-A_UINT32
-a_copy_to_user(void *to, const void *from, A_UINT32 n)
+u32 a_copy_to_user(void *to, const void *from, u32 n)
 {
     return(copy_to_user(to, from, n));
 }
 
-A_UINT32
-a_copy_from_user(void *to, const void *from, A_UINT32 n)
+u32 a_copy_from_user(void *to, const void *from, u32 n)
 {
     return(copy_from_user(to, from, n));
 }
 
 
-A_STATUS
+int
 ar6000_get_driver_cfg(struct net_device *dev,
-                        A_UINT16 cfgParam,
+                        u16 cfgParam,
                         void *result)
 {
 
-    A_STATUS    ret = 0;
+    int    ret = 0;
 
     switch(cfgParam)
     {
         case AR6000_DRIVER_CFG_GET_WLANNODECACHING:
-           *((A_UINT32 *)result) = wlanNodeCaching;
+           *((u32 *)result) = wlanNodeCaching;
            break;
         case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS:
-           *((A_UINT32 *)result) = logWmiRawMsgs;
+           *((u32 *)result) = logWmiRawMsgs;
             break;
         default:
            ret = EINVAL;
@@ -5674,19 +5719,19 @@ ar6000_get_driver_cfg(struct net_device *dev,
 }
 
 void
-ar6000_keepalive_rx(void *devt, A_UINT8 configured)
+ar6000_keepalive_rx(void *devt, u8 configured)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arKeepaliveConfigured = configured;
     wake_up(&arEvent);
 }
 
 void
-ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList,
-                        A_UINT8 *bssidList)
+ar6000_pmkid_list_event(void *devt, u8 numPMKID, WMI_PMKID *pmkidList,
+                        u8 *bssidList)
 {
-    A_UINT8 i, j;
+    u8 i, j;
 
     A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID);
 
@@ -5700,15 +5745,15 @@ ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList,
             for (j = 0; j < WMI_PMKID_LEN; j++) {
                 A_PRINTF("%2.2x", pmkidList->pmkid[j]);
             }
-        pmkidList = (WMI_PMKID *)((A_UINT8 *)pmkidList + ATH_MAC_LEN +
+        pmkidList = (WMI_PMKID *)((u8 *)pmkidList + ATH_MAC_LEN +
                                   WMI_PMKID_LEN);
     }
 }
 
-void ar6000_pspoll_event(AR_SOFTC_T *ar,A_UINT8 aid)
+void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid)
 {
     sta_t *conn=NULL;
-    A_BOOL isPsqEmpty = FALSE;
+    bool isPsqEmpty = false;
 
     conn = ieee80211_find_conn_for_aid(ar, aid);
 
@@ -5745,9 +5790,9 @@ void ar6000_pspoll_event(AR_SOFTC_T *ar,A_UINT8 aid)
     }
 }
 
-void ar6000_dtimexpiry_event(AR_SOFTC_T *ar)
+void ar6000_dtimexpiry_event(struct ar6_softc *ar)
 {
-    A_BOOL isMcastQueued = FALSE;
+    bool isMcastQueued = false;
     struct sk_buff *skb = NULL;
 
     /* If there are no associated STAs, ignore the DTIM expiry event.
@@ -5766,11 +5811,11 @@ void ar6000_dtimexpiry_event(AR_SOFTC_T *ar)
     isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq);
     A_MUTEX_UNLOCK(&ar->mcastpsqLock);
 
-    A_ASSERT(isMcastQueued == FALSE);
+    A_ASSERT(isMcastQueued == false);
 
     /* Flush the mcast psq to the target */
     /* Set the STA flag to DTIMExpired, so that the frame will go out */
-    ar->DTIMExpired = TRUE;
+    ar->DTIMExpired = true;
 
     A_MUTEX_LOCK(&ar->mcastpsqLock);
     while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
@@ -5784,37 +5829,37 @@ void ar6000_dtimexpiry_event(AR_SOFTC_T *ar)
     A_MUTEX_UNLOCK(&ar->mcastpsqLock);
 
     /* Reset the DTIMExpired flag back to 0 */
-    ar->DTIMExpired = FALSE;
+    ar->DTIMExpired = false;
 
     /* Clear the LSB of the BitMapCtl field of the TIM IE */
     wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0);
 }
 
 void
-read_rssi_compensation_param(AR_SOFTC_T *ar)
+read_rssi_compensation_param(struct ar6_softc *ar)
 {
-    A_UINT8 *cust_data_ptr;
+    u8 *cust_data_ptr;
 
 //#define RSSICOMPENSATION_PRINT
 
 #ifdef RSSICOMPENSATION_PRINT
-    A_INT16 i;
+    s16 i;
     cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType);
     for (i=0; i<16; i++) {
-        A_PRINTF("cust_data_%d = %x \n", i, *(A_UINT8 *)cust_data_ptr);
+        A_PRINTF("cust_data_%d = %x \n", i, *(u8 *)cust_data_ptr);
         cust_data_ptr += 1;
     }
 #endif
 
     cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType);
 
-    rssi_compensation_param.customerID = *(A_UINT16 *)cust_data_ptr & 0xffff;
-    rssi_compensation_param.enable = *(A_UINT16 *)(cust_data_ptr+2) & 0xffff;
-    rssi_compensation_param.bg_param_a = *(A_UINT16 *)(cust_data_ptr+4) & 0xffff;
-    rssi_compensation_param.bg_param_b = *(A_UINT16 *)(cust_data_ptr+6) & 0xffff;
-    rssi_compensation_param.a_param_a = *(A_UINT16 *)(cust_data_ptr+8) & 0xffff;
-    rssi_compensation_param.a_param_b = *(A_UINT16 *)(cust_data_ptr+10) &0xffff;
-    rssi_compensation_param.reserved = *(A_UINT32 *)(cust_data_ptr+12);
+    rssi_compensation_param.customerID = *(u16 *)cust_data_ptr & 0xffff;
+    rssi_compensation_param.enable = *(u16 *)(cust_data_ptr+2) & 0xffff;
+    rssi_compensation_param.bg_param_a = *(u16 *)(cust_data_ptr+4) & 0xffff;
+    rssi_compensation_param.bg_param_b = *(u16 *)(cust_data_ptr+6) & 0xffff;
+    rssi_compensation_param.a_param_a = *(u16 *)(cust_data_ptr+8) & 0xffff;
+    rssi_compensation_param.a_param_b = *(u16 *)(cust_data_ptr+10) &0xffff;
+    rssi_compensation_param.reserved = *(u32 *)(cust_data_ptr+12);
 
 #ifdef RSSICOMPENSATION_PRINT
     A_PRINTF("customerID = 0x%x \n", rssi_compensation_param.customerID);
@@ -5833,8 +5878,7 @@ read_rssi_compensation_param(AR_SOFTC_T *ar)
    return;
 }
 
-A_INT32
-rssi_compensation_calc_tcmd(A_UINT32 freq, A_INT32 rssi, A_UINT32 totalPkt)
+s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt)
 {
 
     if (freq > 5000)
@@ -5863,8 +5907,7 @@ rssi_compensation_calc_tcmd(A_UINT32 freq, A_INT32 rssi, A_UINT32 totalPkt)
     return rssi;
 }
 
-A_INT16
-rssi_compensation_calc(AR_SOFTC_T *ar, A_INT16 rssi)
+s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi)
 {
     if (ar->arBssChannel > 5000)
     {
@@ -5892,10 +5935,9 @@ rssi_compensation_calc(AR_SOFTC_T *ar, A_INT16 rssi)
     return rssi;
 }
 
-A_INT16
-rssi_compensation_reverse_calc(AR_SOFTC_T *ar, A_INT16 rssi, A_BOOL Above)
+s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above)
 {
-    A_INT16 i;
+    s16 i;
 
     if (ar->arBssChannel > 5000)
     {
@@ -5938,16 +5980,16 @@ rssi_compensation_reverse_calc(AR_SOFTC_T *ar, A_INT16 rssi, A_BOOL Above)
 }
 
 #ifdef WAPI_ENABLE
-void ap_wapi_rekey_event(AR_SOFTC_T *ar, A_UINT8 type, A_UINT8 *mac)
+void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac)
 {
     union iwreq_data wrqu;
-    A_CHAR buf[20];
+    char buf[20];
 
     A_MEMZERO(buf, sizeof(buf));
 
     strcpy(buf, "WAPI_REKEY");
     buf[10] = type;
-    A_MEMCPY(&buf[11], mac, ATH_MAC_LEN);
+    memcpy(&buf[11], mac, ATH_MAC_LEN);
 
     A_MEMZERO(&wrqu, sizeof(wrqu));
     wrqu.data.length = 10+1+ATH_MAC_LEN;
@@ -5958,11 +6000,11 @@ void ap_wapi_rekey_event(AR_SOFTC_T *ar, A_UINT8 type, A_UINT8 *mac)
 #endif
 
 #ifdef USER_KEYS
-static A_STATUS
+static int
 
-ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
+ar6000_reinstall_keys(struct ar6_softc *ar, u8 key_op_ctrl)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik;
     struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik;
     CRYPTO_TYPE  keyType = ar->user_saved_keys.keyType;
@@ -5975,7 +6017,7 @@ ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
         if (uik->ik_keylen) {
             status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix,
                     ar->user_saved_keys.keyType, PAIRWISE_USAGE,
-                    uik->ik_keylen, (A_UINT8 *)&uik->ik_keyrsc,
+                    uik->ik_keylen, (u8 *)&uik->ik_keyrsc,
                     uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_WMIFLAG);
         }
 
@@ -5991,7 +6033,7 @@ ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
         if (bik->ik_keylen) {
             status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix,
                     ar->user_saved_keys.keyType, GROUP_USAGE,
-                    bik->ik_keylen, (A_UINT8 *)&bik->ik_keyrsc,
+                    bik->ik_keylen, (u8 *)&bik->ik_keyrsc,
                     bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFLAG);
         }
     } else {
@@ -6010,17 +6052,17 @@ _reinstall_keys_out:
 void
 ar6000_dset_open_req(
     void *context,
-    A_UINT32 id,
-    A_UINT32 targHandle,
-    A_UINT32 targReplyFn,
-    A_UINT32 targReplyArg)
+    u32 id,
+    u32 targHandle,
+    u32 targReplyFn,
+    u32 targReplyArg)
 {
 }
 
 void
 ar6000_dset_close(
     void *context,
-    A_UINT32 access_cookie)
+    u32 access_cookie)
 {
     return;
 }
@@ -6028,12 +6070,12 @@ ar6000_dset_close(
 void
 ar6000_dset_data_req(
    void *context,
-   A_UINT32 accessCookie,
-   A_UINT32 offset,
-   A_UINT32 length,
-   A_UINT32 targBuf,
-   A_UINT32 targReplyFn,
-   A_UINT32 targReplyArg)
+   u32 accessCookie,
+   u32 offset,
+   u32 length,
+   u32 targBuf,
+   u32 targReplyFn,
+   u32 targReplyArg)
 {
 }
 
@@ -6079,7 +6121,7 @@ ar6000_ap_mode_profile_commit(struct ar6_softc *ar)
 
     A_MEMZERO(&p,sizeof(p));
     p.ssidLength = ar->arSsidLen;
-    A_MEMCPY(p.ssid,ar->arSsid,p.ssidLength);
+    memcpy(p.ssid,ar->arSsid,p.ssidLength);
     p.channel = ar->arChannelHint;
     p.networkType = ar->arNetworkType;
 
@@ -6091,26 +6133,24 @@ ar6000_ap_mode_profile_commit(struct ar6_softc *ar)
     p.groupCryptoLen = ar->arGroupCryptoLen;
     p.ctrl_flags = ar->arConnectCtrlFlags;
 
-    ar->arConnected = FALSE;
-
     wmi_ap_profile_commit(ar->arWmi, &p);
     spin_lock_irqsave(&ar->arLock, flags);
-    ar->arConnected  = TRUE;
+    ar->arConnected  = true;
     netif_carrier_on(ar->arNetDev);
     spin_unlock_irqrestore(&ar->arLock, flags);
     ar->ap_profile_flag = 0;
     return 0;
 }
 
-A_STATUS
+int
 ar6000_connect_to_ap(struct ar6_softc *ar)
 {
     /* The ssid length check prevents second "essid off" from the user,
        to be treated as a connect cmd. The second "essid off" is ignored.
     */
-    if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK)
+    if((ar->arWmiReady == true) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK)
     {
-        A_STATUS status;
+        int status;
         if((ADHOC_NETWORK != ar->arNetworkType) &&
            (NONE_AUTH==ar->arAuthMode)          &&
            (WEP_CRYPT==ar->arPairwiseCrypto)) {
@@ -6118,7 +6158,7 @@ ar6000_connect_to_ap(struct ar6_softc *ar)
         }
 
         if (!ar->arUserBssFilter) {
-            if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
+            if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
                 return -EIO;
             }
         }
@@ -6142,7 +6182,7 @@ ar6000_connect_to_ap(struct ar6_softc *ar)
         /* Set the listen interval into 1000TUs or more. This value will be indicated to Ap in the conn.
            later set it back locally at the STA to 100/1000 TUs depending on the power mode */
         if ((ar->arNetworkType == INFRA_NETWORK)) {
-            wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (A_UINT16)A_MAX_WOW_LISTEN_INTERVAL), 0);
+            wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (u16)A_MAX_WOW_LISTEN_INTERVAL), 0);
         }
         status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
                                  ar->arDot11AuthMode, ar->arAuthMode,
@@ -6151,7 +6191,7 @@ ar6000_connect_to_ap(struct ar6_softc *ar)
                                  ar->arSsidLen, ar->arSsid,
                                  ar->arReqBssid, ar->arChannelHint,
                                  ar->arConnectCtrlFlags);
-        if (status != A_OK) {
+        if (status) {
             wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB);
             if (!ar->arUserBssFilter) {
                 wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
@@ -6167,13 +6207,28 @@ ar6000_connect_to_ap(struct ar6_softc *ar)
 
         ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
         
-        ar->arConnectPending = TRUE;
+        ar->arConnectPending = true;
         return status;    
     }
     return A_ERROR;
 }
 
-A_STATUS
+int
+ar6000_disconnect(struct ar6_softc *ar)
+{
+    if ((ar->arConnected == true) || (ar->arConnectPending == true)) {
+        wmi_disconnect_cmd(ar->arWmi);
+        /* 
+         * Disconnect cmd is issued, clear connectPending.
+         * arConnected will be cleard in disconnect_event notification.
+         */
+        ar->arConnectPending = false;
+    }
+
+    return 0;
+}
+
+int
 ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie)
 {
     sta_t *conn = NULL;
@@ -6183,38 +6238,38 @@ ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie
     A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE);
 
     if(conn) {
-        A_MEMCPY(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE);
+        memcpy(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE);
     }
 
     return 0;
 }
 
-A_STATUS
-is_iwioctl_allowed(A_UINT8 mode, A_UINT16 cmd)
+int
+is_iwioctl_allowed(u8 mode, u16 cmd)
 {
     if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) {
         cmd -= SIOCSIWCOMMIT;
-        if(sioctl_filter[cmd] == 0xFF) return A_OK;
-        if(sioctl_filter[cmd] & mode) return A_OK;
+        if(sioctl_filter[cmd] == 0xFF) return 0;
+        if(sioctl_filter[cmd] & mode) return 0;
     } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) {
         cmd -= SIOCIWFIRSTPRIV;
-        if(pioctl_filter[cmd] == 0xFF) return A_OK;
-        if(pioctl_filter[cmd] & mode) return A_OK;
+        if(pioctl_filter[cmd] == 0xFF) return 0;
+        if(pioctl_filter[cmd] & mode) return 0;
     } else {
         return A_ERROR;
     }
     return A_ENOTSUP;
 }
 
-A_STATUS
-is_xioctl_allowed(A_UINT8 mode, int cmd)
+int
+is_xioctl_allowed(u8 mode, int cmd)
 {
     if(sizeof(xioctl_filter)-1 < cmd) {
         A_PRINTF("Filter for this cmd=%d not defined\n",cmd);
         return 0;
     }
-    if(xioctl_filter[cmd] == 0xFF) return A_OK;
-    if(xioctl_filter[cmd] & mode) return A_OK;
+    if(xioctl_filter[cmd] == 0xFF) return 0;
+    if(xioctl_filter[cmd] & mode) return 0;
     return A_ERROR;
 }
 
@@ -6224,9 +6279,9 @@ ap_set_wapi_key(struct ar6_softc *ar, void *ikey)
 {
     struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey;
     KEY_USAGE   keyUsage = 0;
-    A_STATUS    status;
+    int    status;
 
-    if (A_MEMCMP(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) {
+    if (memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) {
         keyUsage = GROUP_USAGE;
     } else {
         keyUsage = PAIRWISE_USAGE;
@@ -6236,11 +6291,11 @@ ap_set_wapi_key(struct ar6_softc *ar, void *ikey)
         ik->ik_keylen);
 
     status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage,
-                            ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
+                            ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
                             ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
                             SYNC_BOTH_WMIFLAG);
 
-    if (A_OK != status) {
+    if (0 != status) {
         return -EIO;
     }
     return 0;
@@ -6249,10 +6304,10 @@ ap_set_wapi_key(struct ar6_softc *ar, void *ikey)
 
 void ar6000_peer_event(
     void *context,
-    A_UINT8 eventCode,
-    A_UINT8 *macAddr)
+    u8 eventCode,
+    u8 *macAddr)
 {
-    A_UINT8 pos;
+    u8 pos;
 
     for (pos=0;pos<6;pos++)
         printk("%02x: ",*(macAddr+pos));
@@ -6261,14 +6316,14 @@ void ar6000_peer_event(
 
 #ifdef HTC_TEST_SEND_PKTS
 #define HTC_TEST_DUPLICATE 8
-static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb)
+static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb)
 {
     struct ar_cookie *cookie;
     struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE];
     struct sk_buff   *new_skb;
     int    i;
     int    pkts = 0;
-    HTC_PACKET_QUEUE pktQueue;
+    struct htc_packet_queue pktQueue;
     EPPING_HEADER    *eppingHdr;
 
     eppingHdr = A_NETBUF_DATA(dupskb);
@@ -6345,37 +6400,37 @@ static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, st
  * AP mode.
  */
 
-A_STATUS ar6000_start_ap_interface(AR_SOFTC_T *ar)
+int ar6000_start_ap_interface(struct ar6_softc *ar)
 {
-    AR_VIRTUAL_INTERFACE_T *arApDev;
+    struct ar_virtual_interface *arApDev;
 
     /* Change net_device to point to AP instance */
-    arApDev = (AR_VIRTUAL_INTERFACE_T *)ar->arApDev;
+    arApDev = (struct ar_virtual_interface *)ar->arApDev;
     ar->arNetDev = arApDev->arNetDev;
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS ar6000_stop_ap_interface(AR_SOFTC_T *ar)
+int ar6000_stop_ap_interface(struct ar6_softc *ar)
 {
-    AR_VIRTUAL_INTERFACE_T *arApDev;
+    struct ar_virtual_interface *arApDev;
 
     /* Change net_device to point to sta instance */
-    arApDev = (AR_VIRTUAL_INTERFACE_T *)ar->arApDev;
+    arApDev = (struct ar_virtual_interface *)ar->arApDev;
     if (arApDev) {
         ar->arNetDev = arApDev->arStaNetDev;
     }
 
-    return A_OK;
+    return 0;
 }
 
 
-A_STATUS ar6000_create_ap_interface(AR_SOFTC_T *ar, char *ap_ifname) 
+int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname)
 {
     struct net_device *dev;
-    AR_VIRTUAL_INTERFACE_T *arApDev;
+    struct ar_virtual_interface *arApDev;
 
-    dev = alloc_etherdev(sizeof(AR_VIRTUAL_INTERFACE_T));
+    dev = alloc_etherdev(sizeof(struct ar_virtual_interface));
     if (dev == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: can't alloc etherdev\n"));
         return A_ERROR;
@@ -6398,20 +6453,20 @@ A_STATUS ar6000_create_ap_interface(AR_SOFTC_T *ar, char *ap_ifname)
     arApNetDev = dev;
 
     /* Copy the MAC address */
-    A_MEMCPY(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN);
+    memcpy(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN);
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS ar6000_add_ap_interface(AR_SOFTC_T *ar, char *ap_ifname) 
+int ar6000_add_ap_interface(struct ar6_softc *ar, char *ap_ifname)
 {
     /* Interface already added, need not proceed further */
     if (ar->arApDev != NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_add_ap_interface: interface already present \n"));
-        return A_OK;
+        return 0;
     }
 
-    if (ar6000_create_ap_interface(ar, ap_ifname) != A_OK) {
+    if (ar6000_create_ap_interface(ar, ap_ifname) != 0) {
         return A_ERROR;
     }
 
@@ -6420,7 +6475,7 @@ A_STATUS ar6000_add_ap_interface(AR_SOFTC_T *ar, char *ap_ifname)
     return ar6000_start_ap_interface(ar);
 }
 
-A_STATUS ar6000_remove_ap_interface(AR_SOFTC_T *ar)
+int ar6000_remove_ap_interface(struct ar6_softc *ar)
 {
     if (arApNetDev) {
         ar6000_stop_ap_interface(ar);
@@ -6434,7 +6489,7 @@ A_STATUS ar6000_remove_ap_interface(AR_SOFTC_T *ar)
     arApNetDev = NULL;
 
     
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_pm.c b/drivers/staging/ath6kl/os/linux/ar6000_pm.c
index b937df9..1a90424 100644
--- a/drivers/staging/ath6kl/os/linux/ar6000_pm.c
+++ b/drivers/staging/ath6kl/os/linux/ar6000_pm.c
@@ -30,32 +30,21 @@
 #include <linux/platform_device.h>
 #include "wlan_config.h"
 
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-
 #define WOW_ENABLE_MAX_INTERVAL 0
 #define WOW_SET_SCAN_PARAMS     0
 
 extern unsigned int wmitimeout;
 extern wait_queue_head_t arEvent;
 
-#ifdef CONFIG_PM
-#ifdef CONFIG_HAS_WAKELOCK
-struct wake_lock ar6k_suspend_wake_lock;
-struct wake_lock ar6k_wow_wake_lock;
-#endif
-#endif /* CONFIG_PM */
-
 #ifdef ANDROID_ENV
-extern void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent);
+extern void android_ar6k_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent);
 #endif
 #undef ATH_MODULE_NAME
 #define ATH_MODULE_NAME pm
 #define  ATH_DEBUG_PM       ATH_DEBUG_MAKE_MODULE_MASK(0)
 
 #ifdef DEBUG
-static ATH_DEBUG_MASK_DESCRIPTION pm_debug_desc[] = {
+static struct ath_debug_mask_description pm_debug_desc[] = {
     { ATH_DEBUG_PM     , "System power management"},
 };
 
@@ -68,10 +57,10 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(pm,
 
 #endif /* DEBUG */
 
-A_STATUS ar6000_exit_cut_power_state(AR_SOFTC_T *ar);
+int ar6000_exit_cut_power_state(struct ar6_softc *ar);
 
 #ifdef CONFIG_PM
-static void ar6k_send_asleep_event_to_app(AR_SOFTC_T *ar, A_BOOL asleep)
+static void ar6k_send_asleep_event_to_app(struct ar6_softc *ar, bool asleep)
 {
     char buf[128];
     union iwreq_data wrqu;
@@ -82,17 +71,14 @@ static void ar6k_send_asleep_event_to_app(AR_SOFTC_T *ar, A_BOOL asleep)
     wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
 }
 
-static void ar6000_wow_resume(AR_SOFTC_T *ar)
+static void ar6000_wow_resume(struct ar6_softc *ar)
 {
     if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
-        A_UINT16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
-        A_UINT16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period;
-        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {TRUE, FALSE};
+        u16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
+        u16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period;
+        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {true, false};
         ar->arWowState = WLAN_WOW_STATE_NONE;
-#ifdef CONFIG_HAS_WAKELOCK
-        wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
-#endif
-        if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!=A_OK) {
+        if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!= 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n"));
         }
 #if WOW_SET_SCAN_PARAMS
@@ -113,10 +99,10 @@ static void ar6000_wow_resume(AR_SOFTC_T *ar)
 
 
 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
-        if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == A_OK) {
+        if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == 0) {
         }
 #endif
-        ar6k_send_asleep_event_to_app(ar, FALSE);
+        ar6k_send_asleep_event_to_app(ar, false);
         AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n"));
     } else {
         AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume"));
@@ -124,7 +110,7 @@ static void ar6000_wow_resume(AR_SOFTC_T *ar)
     ar->arWlanPowerState = WLAN_POWER_STATE_ON;
 }
 
-static void ar6000_wow_suspend(AR_SOFTC_T *ar)
+static void ar6000_wow_suspend(struct ar6_softc *ar)
 {
 #define WOW_LIST_ID 1
     if (ar->arNetworkType != AP_NETWORK) {
@@ -135,12 +121,12 @@ static void ar6000_wow_suspend(AR_SOFTC_T *ar)
         struct in_ifaddr **ifap = NULL;
         struct in_ifaddr *ifa = NULL;
         struct in_device *in_dev;
-        A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-        A_STATUS status;
+        u8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+        int status;
         WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } };
         WMI_DEL_WOW_PATTERN_CMD delWowCmd;
-        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE};
-        WMI_SET_WOW_MODE_CMD wowMode = {    .enable_wow = TRUE,
+        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {false, true};
+        WMI_SET_WOW_MODE_CMD wowMode = {    .enable_wow = true,
                                             .hostReqDelay = 500 };/*500 ms delay*/
 
         if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
@@ -151,7 +137,7 @@ static void ar6000_wow_suspend(AR_SOFTC_T *ar)
         ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/
 
 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
-        if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A_OK) {
+        if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == 0) {
         }
 #endif
 
@@ -169,7 +155,7 @@ static void ar6000_wow_suspend(AR_SOFTC_T *ar)
             addWowCmd.filter_size = 6; /* MAC address */
             addWowCmd.filter_offset = 0;
             status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n"));
             }
         }
@@ -186,7 +172,7 @@ static void ar6000_wow_suspend(AR_SOFTC_T *ar)
             memset(&ipCmd, 0, sizeof(ipCmd));
             ipCmd.ips[0] = ifa->ifa_local;
             status = wmi_set_ip_cmd(ar->arWmi, &ipCmd);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n"));
             }
         }
@@ -196,19 +182,19 @@ static void ar6000_wow_suspend(AR_SOFTC_T *ar)
 #endif
 
         status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n"));
         }
-        ar6k_send_asleep_event_to_app(ar, TRUE);
+        ar6k_send_asleep_event_to_app(ar, true);
 
         status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n"));
         }
 
         ar->arWowState = WLAN_WOW_STATE_SUSPENDING;
         if (ar->arTxPending[ar->arControlEp]) {
-            A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
+            u32 timeleft = wait_event_interruptible_timeout(arEvent,
             ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
             if (!timeleft || signal_pending(current)) {
                /* what can I do? wow resume at once */
@@ -225,11 +211,11 @@ static void ar6000_wow_suspend(AR_SOFTC_T *ar)
     }
 }
 
-A_STATUS ar6000_suspend_ev(void *context)
+int ar6000_suspend_ev(void *context)
 {
-    A_STATUS status = A_OK;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
-    A_INT16 pmmode = ar->arSuspendConfig;
+    int status = 0;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
+    s16 pmmode = ar->arSuspendConfig;
 wow_not_connected:
     switch (pmmode) {
     case WLAN_SUSPEND_WOW:
@@ -248,13 +234,13 @@ wow_not_connected:
     case WLAN_SUSPEND_DEEP_SLEEP:
         /* fall through */
     default:
-        status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, TRUE);
+        status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, true);
         if (ar->arWlanPowerState==WLAN_POWER_STATE_ON ||
             ar->arWlanPowerState==WLAN_POWER_STATE_WOW) {
             AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState));
         }
         AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status));
-        status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? A_OK : A_EBUSY;
+        status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? 0 : A_EBUSY;
         break;
     }
 
@@ -262,14 +248,11 @@ wow_not_connected:
     return status;
 }
 
-A_STATUS ar6000_resume_ev(void *context)
+int ar6000_resume_ev(void *context)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
-    A_UINT16 powerState = ar->arWlanPowerState;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
+    u16 powerState = ar->arWlanPowerState;
 
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock(&ar6k_suspend_wake_lock);
-#endif
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState));
     switch (powerState) {
     case WLAN_POWER_STATE_WOW:
@@ -278,7 +261,7 @@ A_STATUS ar6000_resume_ev(void *context)
     case WLAN_POWER_STATE_CUT_PWR:
         /* fall through */
     case WLAN_POWER_STATE_DEEP_SLEEP:
-        ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, TRUE);
+        ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, true);
         AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState));
         break;
     case WLAN_POWER_STATE_ON:
@@ -287,13 +270,10 @@ A_STATUS ar6000_resume_ev(void *context)
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n"));
         break;
     }
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_unlock(&ar6k_suspend_wake_lock);
-#endif
-    return A_OK;
+    return 0;
 }
 
-void ar6000_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
+void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent)
 {
     if (ar->arWowState!=WLAN_WOW_STATE_NONE) {
         if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) {
@@ -310,20 +290,20 @@ void ar6000_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent
     }
 }
 
-A_STATUS ar6000_power_change_ev(void *context, A_UINT32 config)
+int ar6000_power_change_ev(void *context, u32 config)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
-    A_STATUS status = A_OK;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config));
     switch (config) {
        case HIF_DEVICE_POWER_UP:
             ar6000_restart_endpoint(ar->arNetDev);
-            status = A_OK;
+            status = 0;
             break;
        case HIF_DEVICE_POWER_DOWN:
        case HIF_DEVICE_POWER_CUT:
-            status = A_OK;
+            status = 0;
             break;
     }
     return status;
@@ -362,10 +342,10 @@ static struct platform_driver ar6000_pm_device = {
 };
 #endif /* CONFIG_PM */
 
-A_STATUS
+int
 ar6000_setup_cut_power_state(struct ar6_softc *ar,  AR6000_WLAN_STATE state)
 {
-    A_STATUS                      status = A_OK;
+    int                      status = 0;
     HIF_DEVICE_POWER_CHANGE_TYPE  config;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState));
@@ -395,18 +375,18 @@ ar6000_setup_cut_power_state(struct ar6_softc *ar,  AR6000_WLAN_STATE state)
             if (status == A_PENDING) {
 #ifdef ANDROID_ENV
                  /* Wait for WMI ready event */
-                A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
-                            (ar->arWmiReady == TRUE), wmitimeout * HZ);
+                u32 timeleft = wait_event_interruptible_timeout(arEvent,
+                            (ar->arWmiReady == true), wmitimeout * HZ);
                 if (!timeleft || signal_pending(current)) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000 : Failed to get wmi ready \n"));
                     status = A_ERROR;
                     break;
                 }
 #endif
-                status = A_OK;
-            } else if (status == A_OK) {
+                status = 0;
+            } else if (status == 0) {
                 ar6000_restart_endpoint(ar->arNetDev);
-                status = A_OK;
+                status = 0;
             }
         } else if (state == WLAN_DISABLED) {
 
@@ -415,7 +395,7 @@ ar6000_setup_cut_power_state(struct ar6_softc *ar,  AR6000_WLAN_STATE state)
             if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) {
                 break;
             }
-            ar6000_stop_endpoint(ar->arNetDev, TRUE, FALSE);
+            ar6000_stop_endpoint(ar->arNetDev, true, false);
 
             config = HIF_DEVICE_POWER_CUT;
             status = HIFConfigureDevice(ar->arHifDevice,
@@ -432,10 +412,10 @@ ar6000_setup_cut_power_state(struct ar6_softc *ar,  AR6000_WLAN_STATE state)
     return status;
 }
 
-A_STATUS
+int
 ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState));
 #ifdef CONFIG_PM
@@ -445,7 +425,7 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
         WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode;
 
         if (state == WLAN_ENABLED) {
-            A_UINT16 fg_start_period;
+            u16 fg_start_period;
 
             /* Not in deep sleep state.. exit */
             if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) {
@@ -456,10 +436,10 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
             }
 
             fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
-            hostSleepMode.awake = TRUE;
-            hostSleepMode.asleep = FALSE;
+            hostSleepMode.awake = true;
+            hostSleepMode.asleep = false;
 
-            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != A_OK) {
+            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != 0) {
                 break;
             }
 
@@ -476,7 +456,7 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
                                         ar->scParams.shortScanRatio,
                                         ar->scParams.scanCtrlFlags,
                                         ar->scParams.max_dfsch_act_time,
-                                        ar->scParams.maxact_scan_per_ssid)) != A_OK)
+                                        ar->scParams.maxact_scan_per_ssid)) != 0)
                 {
                     break;
                 }
@@ -484,14 +464,14 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
             if (ar->arNetworkType != AP_NETWORK)
             {
                 if (ar->arSsidLen) {
-                    if (ar6000_connect_to_ap(ar) != A_OK) {
+                    if (ar6000_connect_to_ap(ar) != 0) {
                         /* no need to report error if connection failed */
                         break;
                     }
                 }
             }
         } else if (state == WLAN_DISABLED){
-            WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = FALSE };
+            WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = false };
 
             /* Already in deep sleep state.. exit */
             if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) {
@@ -505,7 +485,7 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
             {
                 /* Disconnect from the AP and disable foreground scanning */
                 AR6000_SPIN_LOCK(&ar->arLock, 0);
-                if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
+                if (ar->arConnected == true || ar->arConnectPending == true) {
                     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
                     wmi_disconnect_cmd(ar->arWmi);
                 } else {
@@ -515,12 +495,12 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
 
             ar->scan_triggered = 0;
 
-            if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != A_OK) {
+            if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 0) {
                 break;
             }
 
             /* make sure we disable wow for deep sleep */
-            if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!=A_OK)
+            if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!= 0)
             {
                 break;
             }
@@ -530,13 +510,13 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
             wmi_powermode_cmd(ar->arWmi, REC_POWER);
 #endif
 
-            hostSleepMode.awake = FALSE;
-            hostSleepMode.asleep = TRUE;
-            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!=A_OK) {
+            hostSleepMode.awake = false;
+            hostSleepMode.asleep = true;
+            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!= 0) {
                 break;
             }
             if (ar->arTxPending[ar->arControlEp]) {
-                A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
+                u32 timeleft = wait_event_interruptible_timeout(arEvent,
                                 ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
                 if (!timeleft || signal_pending(current)) {
                     status = A_ERROR;
@@ -549,22 +529,22 @@ ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
         }
     } while (0);
 
-    if (status!=A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state));
     }
 
     return status;
 }
 
-A_STATUS
-ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BOOL pmEvent)
+int
+ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool pmEvent)
 {
-    A_STATUS status = A_OK;
-    A_UINT16 powerState, oldPowerState;
+    int status = 0;
+    u16 powerState, oldPowerState;
     AR6000_WLAN_STATE oldstate = ar->arWlanState;
-    A_BOOL wlanOff = ar->arWlanOff;
+    bool wlanOff = ar->arWlanOff;
 #ifdef CONFIG_PM
-    A_BOOL btOff = ar->arBTOff;
+    bool btOff = ar->arBTOff;
 #endif /* CONFIG_PM */
 
     if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) {
@@ -598,7 +578,7 @@ ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BO
         }
 #ifdef CONFIG_PM
         else if (pmEvent && wlanOff) {
-            A_BOOL allowCutPwr = ((!ar->arBTSharing) || btOff);
+            bool allowCutPwr = ((!ar->arBTSharing) || btOff);
             if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) {
                 /* Come out of cut power */
                 ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
@@ -611,10 +591,10 @@ ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BO
         powerState = WLAN_POWER_STATE_DEEP_SLEEP;
 #ifdef CONFIG_PM
         if (pmEvent) {  /* disable due to suspend */
-            A_BOOL suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR ||
+            bool suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR ||
                                     (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
                                         ar->arWow2Config==WLAN_SUSPEND_CUT_PWR));
-            A_BOOL suspendCutIfBtOff = ((ar->arSuspendConfig ==
+            bool suspendCutIfBtOff = ((ar->arSuspendConfig ==
                                             WLAN_SUSPEND_CUT_PWR_IF_BT_OFF ||
                                         (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
                                          ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) &&
@@ -648,10 +628,10 @@ ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BO
 
     }
 
-    if (status!=A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState));
         ar->arWlanState = oldstate;
-    } else if (status == A_OK) {
+    } else if (status == 0) {
         WMI_REPORT_SLEEP_STATE_EVENT  wmiSleepEvent, *pSleepEvent = NULL;
         if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) {
             wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE;
@@ -662,7 +642,7 @@ ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BO
         }
         if (pSleepEvent) {
             AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState));
-            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)pSleepEvent,
+            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (u8 *)pSleepEvent,
                                      sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
         }
     }
@@ -670,33 +650,33 @@ ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BO
     return status;
 }
 
-A_STATUS
-ar6000_set_bt_hw_state(struct ar6_softc *ar, A_UINT32 enable)
+int
+ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 enable)
 {
 #ifdef CONFIG_PM
-    A_BOOL off = (enable == 0);
-    A_STATUS status;
+    bool off = (enable == 0);
+    int status;
     if (ar->arBTOff == off) {
-        return A_OK;
+        return 0;
     }
     ar->arBTOff = off;
-    status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, FALSE);
+    status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, false);
     return status;
 #else
-    return A_OK;
+    return 0;
 #endif
 }
 
-A_STATUS
+int
 ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
 {
-    A_STATUS status;
-    A_BOOL off = (state == WLAN_DISABLED);
+    int status;
+    bool off = (state == WLAN_DISABLED);
     if (ar->arWlanOff == off) {
-        return A_OK;
+        return 0;
     }
     ar->arWlanOff = off;
-    status = ar6000_update_wlan_pwr_state(ar, state, FALSE);
+    status = ar6000_update_wlan_pwr_state(ar, state, false);
     return status;
 }
 
@@ -704,10 +684,6 @@ void ar6000_pm_init()
 {
     A_REGISTER_MODULE_DEBUG_INFO(pm);
 #ifdef CONFIG_PM
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_init(&ar6k_suspend_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_suspend");
-    wake_lock_init(&ar6k_wow_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_wow");
-#endif
     /*
      * Register ar6000_pm_device into system.
      * We should also add platform_device into the first item of array
@@ -723,9 +699,5 @@ void ar6000_pm_exit()
 {
 #ifdef CONFIG_PM
     platform_driver_unregister(&ar6000_pm_device);
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_destroy(&ar6k_suspend_wake_lock);
-    wake_lock_destroy(&ar6k_wow_wake_lock);
-#endif
 #endif /* CONFIG_PM */
 }
diff --git a/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c b/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c
index 6b8eeea..ae7c1dd 100644
--- a/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c
+++ b/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c
@@ -26,9 +26,9 @@
 #ifdef HTC_RAW_INTERFACE
 
 static void
-ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
+ar6000_htc_raw_read_cb(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T        *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc        *ar = (struct ar6_softc *)Context;
     raw_htc_buffer    *busy;
     HTC_RAW_STREAM_ID streamID; 
     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
@@ -55,12 +55,12 @@ ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n"));
     }
 
-    A_ASSERT((pPacket->Status != A_OK) || 
+    A_ASSERT((pPacket->Status != 0) ||
              (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN)));
 
     busy->length = pPacket->ActualLength + HTC_HEADER_LEN;
     busy->currPtr = HTC_HEADER_LEN;
-    arRaw->read_buffer_available[streamID] = TRUE;
+    arRaw->read_buffer_available[streamID] = true;
     //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb:  0x%X 0x%X \n", busy->currPtr,busy->length);
     up(&arRaw->raw_htc_read_sem[streamID]);
 
@@ -70,9 +70,9 @@ ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
 }
 
 static void
-ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
+ar6000_htc_raw_write_cb(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T          *ar = (AR_SOFTC_T  *)Context;
+    struct ar6_softc          *ar = (struct ar6_softc  *)Context;
     raw_htc_buffer      *free;
     HTC_RAW_STREAM_ID   streamID;
     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
@@ -102,7 +102,7 @@ ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
     A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN));
 
     free->length = 0;
-    arRaw->write_buffer_available[streamID] = TRUE;
+    arRaw->write_buffer_available[streamID] = true;
     up(&arRaw->raw_htc_write_sem[streamID]);
 
     /* Signal the waiting process */
@@ -111,21 +111,21 @@ ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
 }
 
 /* connect to a service */
-static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T        *ar,
+static int ar6000_connect_raw_service(struct ar6_softc        *ar,
                                            HTC_RAW_STREAM_ID StreamID)
 {
-    A_STATUS                 status;
-    HTC_SERVICE_CONNECT_RESP response;
-    A_UINT8                  streamNo;
-    HTC_SERVICE_CONNECT_REQ  connect;
+    int                 status;
+    struct htc_service_connect_resp response;
+    u8 streamNo;
+    struct htc_service_connect_req  connect;
     
     do {      
         
         A_MEMZERO(&connect,sizeof(connect));
             /* pass the stream ID as meta data to the RAW streams service */
-        streamNo = (A_UINT8)StreamID;
+        streamNo = (u8)StreamID;
         connect.pMetaData = &streamNo;
-        connect.MetaDataLength = sizeof(A_UINT8);
+        connect.MetaDataLength = sizeof(u8);
             /* these fields are the same for all endpoints */
         connect.EpCallbacks.pContext = ar;
         connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb;   
@@ -147,10 +147,10 @@ static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T        *ar,
                                    &connect,
                                    &response);
         
-        if (A_FAILED(status)) {
+        if (status) {
             if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n"));
-                status = A_OK;    
+                status = 0;
             }
             break;    
         }
@@ -161,14 +161,14 @@ static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T        *ar,
         AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n", 
                         StreamID, arRawStream2EndpointID(ar,StreamID)));
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
-int ar6000_htc_raw_open(AR_SOFTC_T *ar)
+int ar6000_htc_raw_open(struct ar6_softc *ar)
 {
-    A_STATUS status;
+    int status;
     int streamID, endPt, count2;
     raw_htc_buffer *buffer;
     HTC_SERVICE_ID servicepriority;
@@ -187,7 +187,7 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
     /* wait for target */
     status = HTCWaitTarget(ar->arHtcTarget);
         
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status));
         return -ENODEV;  
     }
@@ -206,7 +206,7 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
             /* try to connect to the raw service */
         status = ar6000_connect_raw_service(ar,streamID);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -228,7 +228,7 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
                                           arRawStream2EndpointID(ar,streamID));
             
             /* Queue buffers to HTC for receive */
-            if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK)
+            if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != 0)
             {
                 BMIInit();
                 return -EIO;
@@ -241,11 +241,11 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
             memset(buffer, 0, sizeof(raw_htc_buffer));
         }
 
-        arRaw->read_buffer_available[streamID] = FALSE;
-        arRaw->write_buffer_available[streamID] = TRUE;
+        arRaw->read_buffer_available[streamID] = false;
+        arRaw->write_buffer_available[streamID] = true;
     }
     
-    if (A_FAILED(status)) {
+    if (status) {
         return -EIO;    
     }
     
@@ -262,23 +262,23 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
                              1);
 
     /* Start the HTC component */
-    if ((status = HTCStart(ar->arHtcTarget)) != A_OK) {
+    if ((status = HTCStart(ar->arHtcTarget)) != 0) {
         BMIInit();
         return -EIO;
     }
 
-    (ar)->arRawIfInit = TRUE;
+    (ar)->arRawIfInit = true;
     
     return 0;
 }
 
-int ar6000_htc_raw_close(AR_SOFTC_T *ar)
+int ar6000_htc_raw_close(struct ar6_softc *ar)
 {
     A_PRINTF("ar6000_htc_raw_close called \n");
     HTCStop(ar->arHtcTarget);
     
         /* reset the device */
-    ar6000_reset_device(ar->arHifDevice, ar->arTargetType, TRUE, FALSE);
+    ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, false);
     /* Initialize the BMI component */
     BMIInit();
 
@@ -286,7 +286,7 @@ int ar6000_htc_raw_close(AR_SOFTC_T *ar)
 }
 
 raw_htc_buffer *
-get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
+get_filled_buffer(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID)
 {
     int count;
     raw_htc_buffer *busy;
@@ -300,15 +300,15 @@ get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
         }
     }
     if (busy->length) {
-        arRaw->read_buffer_available[StreamID] = TRUE;
+        arRaw->read_buffer_available[StreamID] = true;
     } else {
-        arRaw->read_buffer_available[StreamID] = FALSE;
+        arRaw->read_buffer_available[StreamID] = false;
     }
 
     return busy;
 }
 
-ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, 
+ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, 
                             char __user *buffer, size_t length)
 {
     int readPtr;
@@ -361,14 +361,14 @@ ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
         //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl:  ep for packet:%d \n", busy->HTCPacket.Endpoint));
         HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket);
     }
-    arRaw->read_buffer_available[StreamID] = FALSE;
+    arRaw->read_buffer_available[StreamID] = false;
     up(&arRaw->raw_htc_read_sem[StreamID]);
 
     return length;
 }
 
 static raw_htc_buffer *
-get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
+get_free_buffer(struct ar6_softc *ar, HTC_ENDPOINT_ID StreamID)
 {
     int count;
     raw_htc_buffer *free;
@@ -382,15 +382,15 @@ get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
         }
     }
     if (!free->length) {
-        arRaw->write_buffer_available[StreamID] = TRUE;
+        arRaw->write_buffer_available[StreamID] = true;
     } else {
-        arRaw->write_buffer_available[StreamID] = FALSE;
+        arRaw->write_buffer_available[StreamID] = false;
     }
 
     return free;
 }
 
-ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
+ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID,
                      char __user *buffer, size_t length)
 {
     int writePtr;
@@ -447,7 +447,7 @@ ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
     
     HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);
     
-    arRaw->write_buffer_available[StreamID] = FALSE;
+    arRaw->write_buffer_available[StreamID] = false;
     up(&arRaw->raw_htc_write_sem[StreamID]);
 
     return length;
diff --git a/drivers/staging/ath6kl/os/linux/ar6k_pal.c b/drivers/staging/ath6kl/os/linux/ar6k_pal.c
index 6c98a88..1f7179a 100644
--- a/drivers/staging/ath6kl/os/linux/ar6k_pal.c
+++ b/drivers/staging/ath6kl/os/linux/ar6k_pal.c
@@ -49,7 +49,7 @@ typedef struct ar6k_hci_pal_info_s{
 #define HCI_NORMAL_MODE (1)
 #define HCI_REGISTERED (1<<1)
 	struct hci_dev *hdev;            /* BT Stack HCI dev */
-	AR_SOFTC_T *ar;
+	struct ar6_softc *ar;
 
 }ar6k_hci_pal_info_t;
 
@@ -120,9 +120,9 @@ static int btpal_send_frame(struct sk_buff *skb)
 	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
 	HCI_TRANSPORT_PACKET_TYPE type;
 	ar6k_hci_pal_info_t *pHciPalInfo;
-	A_STATUS status = A_OK;
+	int status = 0;
 	struct sk_buff *txSkb = NULL;
-	AR_SOFTC_T *ar;
+	struct ar6_softc *ar;
 
 	if (!hdev) {
 		PRIN_LOG("HCI PAL: btpal_send_frame - no device\n");
@@ -157,7 +157,7 @@ static int btpal_send_frame(struct sk_buff *skb)
 			kfree_skb(skb);
 			return 0;
 		default:
-			A_ASSERT(FALSE);
+			A_ASSERT(false);
 			kfree_skb(skb);
 			return 0;
 	} 
@@ -178,13 +178,13 @@ static int btpal_send_frame(struct sk_buff *skb)
 		{
 			PRIN_LOG("HCI command");
 
-			if (ar->arWmiReady == FALSE)
+			if (ar->arWmiReady == false)
 			{
 				PRIN_LOG("WMI not ready ");
 				break;
 			}
 
-			if (wmi_send_hci_cmd(ar->arWmi, skb->data, skb->len) != A_OK)
+			if (wmi_send_hci_cmd(ar->arWmi, skb->data, skb->len) != 0)
 			{
 				PRIN_LOG("send hci cmd error");
 				break;
@@ -195,7 +195,7 @@ static int btpal_send_frame(struct sk_buff *skb)
 			void *osbuf;
 
 			PRIN_LOG("ACL data");
-			if (ar->arWmiReady == FALSE)
+			if (ar->arWmiReady == false)
 			{
 				PRIN_LOG("WMI not ready");
 				break;
@@ -215,12 +215,12 @@ static int btpal_send_frame(struct sk_buff *skb)
 			bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
 			txSkb->dev = (void *)pHciPalInfo->hdev;
 			skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + WMI_MAX_TX_META_SZ + sizeof(WMI_DATA_HDR));
-			A_MEMCPY(txSkb->data, skb->data, skb->len);
+			memcpy(txSkb->data, skb->data, skb->len);
 			skb_put(txSkb,skb->len);
 			/* Add WMI packet type */
 			osbuf = (void *)txSkb;
 
-			if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != A_OK) {
+			if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
 				PRIN_LOG("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n");
 			} else {
 				/* Send data buffer over HTC */
@@ -229,7 +229,7 @@ static int btpal_send_frame(struct sk_buff *skb)
 			}
 			txSkb = NULL;
 		}
-	} while (FALSE);
+	} while (false);
 
 	if (txSkb != NULL) {
 		PRIN_LOG("Free skb");
@@ -260,22 +260,20 @@ static void bt_cleanup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
 		}          
 	}
 
-	if (pHciPalInfo->hdev != NULL) {
-		kfree(pHciPalInfo->hdev);
-		pHciPalInfo->hdev = NULL;
-	}
+	kfree(pHciPalInfo->hdev);
+	pHciPalInfo->hdev = NULL;
 }
 
 /*********************************************************
  * Allocate HCI device and store in PAL private info structure.
  *********************************************************/
-static A_STATUS bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
+static int bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
 {
-	A_STATUS status = A_OK;
+	int status = 0;
 	struct hci_dev *pHciDev = NULL;
 
 	if (!setupbtdev) {
-		return A_OK;    
+		return 0;
 	} 
 
 	do {
@@ -302,9 +300,9 @@ static A_STATUS bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
 		PRIN_LOG("Normal mode enabled");
 		bt_set_bit(pHciPalInfo->ulFlags, HCI_NORMAL_MODE);
 
-	} while (FALSE);
+	} while (false);
 
-	if (A_FAILED(status)) {
+	if (status) {
 		bt_cleanup_hci_pal(pHciPalInfo);    
 	}
 	return status;
@@ -315,7 +313,7 @@ static A_STATUS bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
  *********************************************/
 void ar6k_cleanup_hci_pal(void *ar_p)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar_p;
+	struct ar6_softc *ar = (struct ar6_softc *)ar_p;
 	ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)ar->hcipal_info;
 
 	if (pHciPalInfo != NULL) {
@@ -328,22 +326,22 @@ void ar6k_cleanup_hci_pal(void *ar_p)
 /****************************
  *  Register HCI device
  ****************************/
-static A_BOOL ar6k_pal_transport_ready(void *pHciPal)
+static bool ar6k_pal_transport_ready(void *pHciPal)
 {
 	ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
 
 	PRIN_LOG("HCI device transport ready");
 	if(pHciPalInfo == NULL)
-		return FALSE;
+		return false;
 
 	if (hci_register_dev(pHciPalInfo->hdev) < 0) {
 		PRIN_LOG("Can't register HCI device");
 		hci_free_dev(pHciPalInfo->hdev);
-		return FALSE;
+		return false;
 	}
 	PRIN_LOG("HCI device registered");
 	pHciPalInfo->ulFlags |= HCI_REGISTERED;
-	return TRUE;
+	return true;
 }
 
 /**************************************************
@@ -351,12 +349,12 @@ static A_BOOL ar6k_pal_transport_ready(void *pHciPal)
  * packet is received. Pass the packet to bluetooth
  * stack via hci_recv_frame.
  **************************************************/
-A_BOOL ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
+bool ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
 {
 	struct sk_buff *skb = (struct sk_buff *)osbuf;
 	ar6k_hci_pal_info_t *pHciPalInfo;
-	A_BOOL success = FALSE;
-	A_UINT8 btType = 0;
+	bool success = false;
+	u8 btType = 0;
 	pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
 
 	do {
@@ -391,8 +389,8 @@ A_BOOL ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
 			PRIN_LOG("HCI PAL: Indicated RCV of type:%d, Length:%d \n",HCI_EVENT_PKT, skb->len);
 		}
 		PRIN_LOG("hci recv success");
-		success = TRUE;
-	}while(FALSE);
+		success = true;
+	}while(false);
 	return success;
 }
 
@@ -402,12 +400,12 @@ A_BOOL ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
  * Registers a HCI device.
  * Registers packet receive callback function with ar6k 
  **********************************************************/
-A_STATUS ar6k_setup_hci_pal(void *ar_p)
+int ar6k_setup_hci_pal(void *ar_p)
 {
-	A_STATUS status = A_OK;
+	int status = 0;
 	ar6k_hci_pal_info_t *pHciPalInfo;
 	ar6k_pal_config_t ar6k_pal_config;
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar_p;
+	struct ar6_softc *ar = (struct ar6_softc *)ar_p;
 
 	do {
 
@@ -423,7 +421,7 @@ A_STATUS ar6k_setup_hci_pal(void *ar_p)
 		pHciPalInfo->ar = ar;
 
 		status = bt_setup_hci_pal(pHciPalInfo);
-		if (A_FAILED(status)) {
+		if (status) {
 			break;    
 		}
 
@@ -435,17 +433,17 @@ A_STATUS ar6k_setup_hci_pal(void *ar_p)
 		ar6k_pal_config.fpar6k_pal_recv_pkt = ar6k_pal_recv_pkt;
 		register_pal_cb(&ar6k_pal_config);
 		ar6k_pal_transport_ready(ar->hcipal_info);
-	} while (FALSE);
+	} while (false);
 
-	if (A_FAILED(status)) {
+	if (status) {
 		ar6k_cleanup_hci_pal(ar);    
 	}
 	return status;
 }
 #else  /* AR6K_ENABLE_HCI_PAL */
-A_STATUS ar6k_setup_hci_pal(void *ar_p)
+int ar6k_setup_hci_pal(void *ar_p)
 {
-	return A_OK;
+	return 0;
 }
 void ar6k_cleanup_hci_pal(void *ar_p)
 {
@@ -457,15 +455,15 @@ void ar6k_cleanup_hci_pal(void *ar_p)
  * Register init and callback function with ar6k
  * when PAL driver is a separate kernel module.
  ****************************************************/
-A_STATUS ar6k_register_hci_pal(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks);
+int ar6k_register_hci_pal(struct hci_transport_callbacks *hciTransCallbacks);
 static int __init pal_init_module(void)
 {
-	HCI_TRANSPORT_CALLBACKS hciTransCallbacks;
+	struct hci_transport_callbacks hciTransCallbacks;
 
 	hciTransCallbacks.setupTransport = ar6k_setup_hci_pal;
 	hciTransCallbacks.cleanupTransport = ar6k_cleanup_hci_pal;
 
-	if(ar6k_register_hci_pal(&hciTransCallbacks) != A_OK)
+	if(ar6k_register_hci_pal(&hciTransCallbacks) != 0)
 		return -ENODEV;
 
 	return 0;
diff --git a/drivers/staging/ath6kl/os/linux/cfg80211.c b/drivers/staging/ath6kl/os/linux/cfg80211.c
index 7269d0a..bcca394 100644
--- a/drivers/staging/ath6kl/os/linux/cfg80211.c
+++ b/drivers/staging/ath6kl/os/linux/cfg80211.c
@@ -136,7 +136,7 @@ ieee80211_supported_band ar6k_band_5ghz = {
 };
 
 static int
-ar6k_set_wpa_version(AR_SOFTC_T *ar, enum nl80211_wpa_versions wpa_version)
+ar6k_set_wpa_version(struct ar6_softc *ar, enum nl80211_wpa_versions wpa_version)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: %u\n", __func__, wpa_version));
@@ -153,11 +153,11 @@ ar6k_set_wpa_version(AR_SOFTC_T *ar, enum nl80211_wpa_versions wpa_version)
         return -ENOTSUPP;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static int
-ar6k_set_auth_type(AR_SOFTC_T *ar, enum nl80211_auth_type auth_type)
+ar6k_set_auth_type(struct ar6_softc *ar, enum nl80211_auth_type auth_type)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, auth_type));
@@ -179,15 +179,15 @@ ar6k_set_auth_type(AR_SOFTC_T *ar, enum nl80211_auth_type auth_type)
         return -ENOTSUPP;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static int
-ar6k_set_cipher(AR_SOFTC_T *ar, A_UINT32 cipher, A_BOOL ucast)
+ar6k_set_cipher(struct ar6_softc *ar, u32 cipher, bool ucast)
 {
-    A_UINT8  *ar_cipher = ucast ? &ar->arPairwiseCrypto :
+    u8 *ar_cipher = ucast ? &ar->arPairwiseCrypto :
                                 &ar->arGroupCrypto;
-    A_UINT8  *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen :
+    u8 *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen :
                                     &ar->arGroupCryptoLen;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
@@ -221,11 +221,11 @@ ar6k_set_cipher(AR_SOFTC_T *ar, A_UINT32 cipher, A_BOOL ucast)
         return -ENOTSUPP;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static void
-ar6k_set_key_mgmt(AR_SOFTC_T *ar, A_UINT32 key_mgmt)
+ar6k_set_key_mgmt(struct ar6_softc *ar, u32 key_mgmt)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, key_mgmt));
 
@@ -244,12 +244,13 @@ static int
 ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                       struct cfg80211_connect_params *sme)
 {
-    AR_SOFTC_T *ar = ar6k_priv(dev);
-    A_STATUS status;
+    struct ar6_softc *ar = ar6k_priv(dev);
+    int status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
+    ar->smeState = SME_CONNECTING;
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__));
         return -EIO;
     }
@@ -269,7 +270,7 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
         return -EINVAL;
     }
 
-    if(ar->arSkipScan == TRUE &&
+    if(ar->arSkipScan == true &&
        ((sme->channel && sme->channel->center_freq == 0) ||
         (sme->bssid && !sme->bssid[0] && !sme->bssid[1] && !sme->bssid[2] &&
          !sme->bssid[3] && !sme->bssid[4] && !sme->bssid[5])))
@@ -302,28 +303,28 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
         }
     }
 
-    if(ar->arConnected == TRUE &&
+    if(ar->arConnected == true &&
        ar->arSsidLen == sme->ssid_len &&
-       !A_MEMCMP(ar->arSsid, sme->ssid, ar->arSsidLen)) {
-        reconnect_flag = TRUE;
+       !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) {
+        reconnect_flag = true;
         status = wmi_reconnect_cmd(ar->arWmi,
                                    ar->arReqBssid,
                                    ar->arChannelHint);
 
         up(&ar->arSem);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__));
             return -EIO;
         }
         return 0;
     } else if(ar->arSsidLen == sme->ssid_len &&
-              !A_MEMCMP(ar->arSsid, sme->ssid, ar->arSsidLen)) {
-	    wmi_disconnect_cmd(ar->arWmi);
+              !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) {
+	    ar6000_disconnect(ar);
     }
 
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
     ar->arSsidLen = sme->ssid_len;
-    A_MEMCPY(ar->arSsid, sme->ssid, sme->ssid_len);
+    memcpy(ar->arSsid, sme->ssid, sme->ssid_len);
 
     if(sme->channel){
         ar->arChannelHint = sme->channel->center_freq;
@@ -331,8 +332,8 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     if(sme->bssid){
-        if(A_MEMCMP(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
-            A_MEMCPY(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid));
+        if(memcmp(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
+            memcpy(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid));
         }
     }
 
@@ -364,7 +365,7 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
         key = &ar->keys[sme->key_idx];
         key->key_len = sme->key_len;
-        A_MEMCPY(key->key, sme->key, key->key_len);
+        memcpy(key->key, sme->key, key->key_len);
         key->cipher = ar->arPairwiseCrypto;
         ar->arDefTxKeyIndex = sme->key_idx;
 
@@ -378,7 +379,7 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
     }
 
     if (!ar->arUserBssFilter) {
-        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
+        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__));
             up(&ar->arSem);
             return -EIO;
@@ -410,7 +411,7 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
         ar->arSsidLen = 0;
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Invalid request\n", __func__));
         return -ENOENT;
-    } else if (status != A_OK) {
+    } else if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_connect_cmd failed\n", __func__));
         return -EIO;
     }
@@ -422,37 +423,37 @@ ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
     }
 
     ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
-    ar->arConnectPending = TRUE;
+    ar->arConnectPending = true;
 
     return 0;
 }
 
 void
-ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
-                A_UINT8 *bssid, A_UINT16 listenInterval,
-                A_UINT16 beaconInterval,NETWORK_TYPE networkType,
-                A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
-                A_UINT8 assocRespLen, A_UINT8 *assocInfo)
+ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
+                u8 *bssid, u16 listenInterval,
+                u16 beaconInterval,NETWORK_TYPE networkType,
+                u8 beaconIeLen, u8 assocReqLen,
+                u8 assocRespLen, u8 *assocInfo)
 {
-    A_UINT16 size = 0;
-    A_UINT16 capability = 0;
+    u16 size = 0;
+    u16 capability = 0;
     struct cfg80211_bss *bss = NULL;
     struct ieee80211_mgmt *mgmt = NULL;
     struct ieee80211_channel *ibss_channel = NULL;
     s32 signal = 50 * 100;
-    A_UINT8 ie_buf_len = 0;
+    u8 ie_buf_len = 0;
     unsigned char ie_buf[256];
     unsigned char *ptr_ie_buf = ie_buf;
     unsigned char *ieeemgmtbuf = NULL;
-    A_UINT8 source_mac[ATH_MAC_LEN];
+    u8 source_mac[ATH_MAC_LEN];
 
-    A_UINT8 assocReqIeOffset = sizeof(A_UINT16)  +  /* capinfo*/
-                               sizeof(A_UINT16);    /* listen interval */
-    A_UINT8 assocRespIeOffset = sizeof(A_UINT16) +  /* capinfo*/
-                                sizeof(A_UINT16) +  /* status Code */
-                                sizeof(A_UINT16);   /* associd */
-    A_UINT8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset;
-    A_UINT8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset;
+    u8 assocReqIeOffset = sizeof(u16)  +  /* capinfo*/
+                               sizeof(u16);    /* listen interval */
+    u8 assocRespIeOffset = sizeof(u16) +  /* capinfo*/
+                                sizeof(u16) +  /* status Code */
+                                sizeof(u16);   /* associd */
+    u8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset;
+    u8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
@@ -492,7 +493,7 @@ ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
             if(ptr_ie_buf) {
                 *ptr_ie_buf++ = WLAN_EID_SSID;
                 *ptr_ie_buf++ = ar->arSsidLen;
-                A_MEMCPY(ptr_ie_buf, ar->arSsid, ar->arSsidLen);
+                memcpy(ptr_ie_buf, ar->arSsid, ar->arSsidLen);
                 ptr_ie_buf +=ar->arSsidLen;
 
                 *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS;
@@ -510,11 +511,11 @@ ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
             if(WEP_CRYPT == ar->arPairwiseCrypto) {
                 capability |= IEEE80211_CAPINFO_PRIVACY;
             }
-            A_MEMCPY(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN);
+            memcpy(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN);
             ptr_ie_buf = ie_buf;
         } else {
-            capability = *(A_UINT16 *)(&assocInfo[beaconIeLen]);
-            A_MEMCPY(source_mac, bssid, ATH_MAC_LEN);
+            capability = *(u16 *)(&assocInfo[beaconIeLen]);
+            memcpy(source_mac, bssid, ATH_MAC_LEN);
             ptr_ie_buf = assocReqIe;
             ie_buf_len = assocReqLen;
         }
@@ -533,12 +534,12 @@ ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
         A_MEMZERO(ieeemgmtbuf, size);
         mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
         mgmt->frame_control = (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
-        A_MEMCPY(mgmt->da, bcast_mac, ATH_MAC_LEN);
-        A_MEMCPY(mgmt->sa, source_mac, ATH_MAC_LEN);
-        A_MEMCPY(mgmt->bssid, bssid, ATH_MAC_LEN);
+        memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN);
+        memcpy(mgmt->sa, source_mac, ATH_MAC_LEN);
+        memcpy(mgmt->bssid, bssid, ATH_MAC_LEN);
         mgmt->u.beacon.beacon_int = beaconInterval;
         mgmt->u.beacon.capab_info = capability;
-        A_MEMCPY(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len);
+        memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len);
 
         ibss_channel = ieee80211_get_channel(ar->wdev->wiphy, (int)channel);
 
@@ -560,8 +561,9 @@ ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
         return;
     }
 
-    if (FALSE == ar->arConnected) {
+    if (false == ar->arConnected) {
         /* inform connect result to cfg80211 */
+        ar->smeState = SME_DISCONNECTED;
         cfg80211_connect_result(ar->arNetDev, bssid,
                                 assocReqIe, assocReqLen,
                                 assocRespIe, assocRespLen,
@@ -577,13 +579,13 @@ ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
 
 static int
 ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
-                        A_UINT16 reason_code)
+                        u16 reason_code)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason_code));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -604,11 +606,11 @@ ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
     }
 
     reconnect_flag = 0;
-    wmi_disconnect_cmd(ar->arWmi);
+    ar6000_disconnect(ar);
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
     ar->arSsidLen = 0;
 
-    if (ar->arSkipScan == FALSE) {
+    if (ar->arSkipScan == false) {
         A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     }
 
@@ -618,9 +620,9 @@ ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 }
 
 void
-ar6k_cfg80211_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason,
-                               A_UINT8 *bssid, A_UINT8 assocRespLen,
-                               A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
+ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
+                               u8 *bssid, u8 assocRespLen,
+                               u8 *assocInfo, u16 protocolReasonStatus)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason));
@@ -644,18 +646,28 @@ ar6k_cfg80211_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason,
         }
     }
 
-    if(FALSE == ar->arConnected) {
+    if(true == ar->arConnectPending) {
         if(NO_NETWORK_AVAIL == reason) {
             /* connect cmd failed */
-            cfg80211_connect_result(ar->arNetDev, bssid,
-                                    NULL, 0,
-                                    NULL, 0,
-                                    WLAN_STATUS_UNSPECIFIED_FAILURE,
-                                    GFP_KERNEL);
+            wmi_disconnect_cmd(ar->arWmi);
+        } else if (reason == DISCONNECT_CMD) {
+            /* connection loss due to disconnect cmd or low rssi */
+            ar->arConnectPending = false;   
+            if (ar->smeState == SME_CONNECTING) {
+                cfg80211_connect_result(ar->arNetDev, bssid,
+                                        NULL, 0,
+                                        NULL, 0,
+                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                        GFP_KERNEL);
+            } else {
+                cfg80211_disconnected(ar->arNetDev, reason, NULL, 0, GFP_KERNEL);
+            }
+            ar->smeState = SME_DISCONNECTED;
         }
     } else {
-        /* connection loss due to disconnect cmd or low rssi */
-        cfg80211_disconnected(ar->arNetDev, reason, NULL, 0, GFP_KERNEL);
+        if (reason != DISCONNECT_CMD) {
+            wmi_disconnect_cmd(ar->arWmi);
+        }
     }
 }
 
@@ -663,7 +675,7 @@ void
 ar6k_cfg80211_scan_node(void *arg, bss_t *ni)
 {
     struct wiphy *wiphy = (struct wiphy *)arg;
-    A_UINT16 size;
+    u16 size;
     unsigned char *ieeemgmtbuf = NULL;
     struct ieee80211_mgmt *mgmt;
     struct ieee80211_channel *channel;
@@ -700,10 +712,10 @@ ar6k_cfg80211_scan_node(void *arg, bss_t *ni)
        cfg80211 needs it, for time being just filling the da, sa and bssid fields alone.
     */
     mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
-    A_MEMCPY(mgmt->da, bcast_mac, ATH_MAC_LEN);
-    A_MEMCPY(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN);
-    A_MEMCPY(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN);
-    A_MEMCPY(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u),
+    memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN);
+    memcpy(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN);
+    memcpy(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN);
+    memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u),
              ni->ni_buf, ni->ni_framelen);
 
     freq    = cie->ie_chan;
@@ -724,13 +736,13 @@ static int
 ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                    struct cfg80211_scan_request *request)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     int ret = 0;
-    A_BOOL forceFgScan = FALSE;
+    u32 forceFgScan = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -743,7 +755,7 @@ ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
     if (!ar->arUserBssFilter) {
         if (wmi_bssfilter_cmd(ar->arWmi,
                              (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER),
-                             0) != A_OK) {
+                             0) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__));
             return -EIO;
         }
@@ -751,25 +763,25 @@ ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
     if(request->n_ssids &&
        request->ssids[0].ssid_len) {
-        A_UINT8 i;
+        u8 i;
 
-        if(request->n_ssids > MAX_PROBED_SSID_INDEX) {
-            request->n_ssids = MAX_PROBED_SSID_INDEX;
+        if(request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) {
+            request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
         }
 
         for (i = 0; i < request->n_ssids; i++) {
-            wmi_probedSsid_cmd(ar->arWmi, i, SPECIFIC_SSID_FLAG,
+            wmi_probedSsid_cmd(ar->arWmi, i+1, SPECIFIC_SSID_FLAG,
                                request->ssids[i].ssid_len,
                                request->ssids[i].ssid);
         }
     }
 
     if(ar->arConnected) {
-        forceFgScan = TRUE;
+        forceFgScan = 1;
     }
 
-    if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, FALSE, \
-                         0, 0, 0, NULL) != A_OK) {
+    if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, false, \
+                         0, 0, 0, NULL) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_startscan_cmd failed\n", __func__));
         ret = -EIO;
     }
@@ -780,7 +792,7 @@ ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 void
-ar6k_cfg80211_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
+ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status));
@@ -791,14 +803,14 @@ ar6k_cfg80211_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
         wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
 
         cfg80211_scan_done(ar->scan_request,
-                          (status & A_ECANCELED) ? true : false);
+            ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false);
 
         if(ar->scan_request->n_ssids &&
            ar->scan_request->ssids[0].ssid_len) {
-            A_UINT8 i;
+            u8 i;
 
             for (i = 0; i < ar->scan_request->n_ssids; i++) {
-                wmi_probedSsid_cmd(ar->arWmi, i, DISABLE_SSID_FLAG,
+                wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG,
                                    0, NULL);
             }
         }
@@ -808,18 +820,18 @@ ar6k_cfg80211_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
 
 static int
 ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
-                      A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr,
+                      u8 key_index, bool pairwise, const u8 *mac_addr,
                       struct key_params *params)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     struct ar_key *key = NULL;
-    A_UINT8 key_usage;
-    A_UINT8 key_type;
-    A_STATUS status = 0;
+    u8 key_usage;
+    u8 key_type;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s:\n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -850,9 +862,9 @@ ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
             return -EINVAL;
 
         key->key_len = params->key_len;
-        A_MEMCPY(key->key, params->key, key->key_len);
+        memcpy(key->key, params->key, key->key_len);
         key->seq_len = params->seq_len;
-        A_MEMCPY(key->seq, params->seq, key->seq_len);
+        memcpy(key->seq, params->seq, key->seq_len);
         key->cipher = params->cipher;
     }
 
@@ -889,10 +901,10 @@ ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
     ar->arDefTxKeyIndex = key_index;
     status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, key_type, key_usage,
                     key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
-                    (A_UINT8*)mac_addr, SYNC_BOTH_WMIFLAG);
+                    (u8 *)mac_addr, SYNC_BOTH_WMIFLAG);
 
 
-    if(status != A_OK) {
+    if (status) {
         return -EIO;
     }
 
@@ -901,13 +913,13 @@ ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 
 static int
 ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
-                      A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr)
+                      u8 key_index, bool pairwise, const u8 *mac_addr)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -936,17 +948,17 @@ ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 
 static int
 ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
-                      A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr,
+                      u8 key_index, bool pairwise, const u8 *mac_addr,
                       void *cookie,
                       void (*callback)(void *cookie, struct key_params*))
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     struct ar_key *key = NULL;
     struct key_params params;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -978,15 +990,16 @@ ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
 
 static int
 ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev,
-                              A_UINT8 key_index)
+                              u8 key_index, bool unicast, bool multicast)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     struct ar_key *key = NULL;
-    A_STATUS status = A_OK;
+    int status = 0;
+    u8 key_usage;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1011,11 +1024,16 @@ ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev,
 
     ar->arDefTxKeyIndex = key_index;
     key = &ar->keys[ar->arDefTxKeyIndex];
+    key_usage = GROUP_USAGE;
+    if (WEP_CRYPT == ar->arPairwiseCrypto) {
+        key_usage |= TX_USAGE;
+    }
+
     status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex,
-                            ar->arPairwiseCrypto, GROUP_USAGE | TX_USAGE,
+                            ar->arPairwiseCrypto, key_usage,
                             key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
                             NULL, SYNC_BOTH_WMIFLAG);
-    if (status != A_OK) {
+    if (status) {
         return -EIO;
     }
 
@@ -1024,13 +1042,13 @@ ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev,
 
 static int
 ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev,
-                                   A_UINT8 key_index)
+                                   u8 key_index)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1045,7 +1063,7 @@ ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 void
-ar6k_cfg80211_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
+ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
                     ("%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast));
@@ -1056,13 +1074,13 @@ ar6k_cfg80211_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
 }
 
 static int
-ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, A_UINT32 changed)
+ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)wiphy_priv(wiphy);
+    struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: changed 0x%x\n", __func__, changed));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1073,7 +1091,7 @@ ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, A_UINT32 changed)
     }
 
     if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
-        if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != A_OK){
+        if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != 0){
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_set_rts_cmd failed\n", __func__));
             return -EIO;
         }
@@ -1084,7 +1102,7 @@ ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, A_UINT32 changed)
 
 static int
 ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
-                               const A_UINT8 *peer,
+                               const u8 *peer,
                                const struct cfg80211_bitrate_mask *mask)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Setting rates: Not supported\n"));
@@ -1095,12 +1113,12 @@ ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 static int
 ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)wiphy_priv(wiphy);
-    A_UINT8 ar_dbm;
+    struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
+    u8 ar_dbm;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x, dbm %d\n", __func__, type, dbm));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1110,13 +1128,13 @@ ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting typ
         return -EIO;
     }
 
-    ar->arTxPwrSet = FALSE;
+    ar->arTxPwrSet = false;
     switch(type) {
     case NL80211_TX_POWER_AUTOMATIC:
         return 0;
     case NL80211_TX_POWER_LIMITED:
         ar->arTxPwr = ar_dbm = dbm;
-        ar->arTxPwrSet = TRUE;
+        ar->arTxPwrSet = true;
         break;
     default:
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x not supported\n", __func__, type));
@@ -1131,11 +1149,11 @@ ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting typ
 static int
 ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)wiphy_priv(wiphy);
+    struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1145,10 +1163,10 @@ ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
         return -EIO;
     }
 
-    if((ar->arConnected == TRUE)) {
+    if((ar->arConnected == true)) {
         ar->arTxPwr = 0;
 
-        if(wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
+        if(wmi_get_txPwr_cmd(ar->arWmi) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_get_txPwr_cmd failed\n", __func__));
             return -EIO;
         }
@@ -1170,12 +1188,12 @@ ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy,
                              struct net_device *dev,
                              bool pmgmt, int timeout)
 {
-    AR_SOFTC_T *ar = ar6k_priv(dev);
+    struct ar6_softc *ar = ar6k_priv(dev);
     WMI_POWER_MODE_CMD pwrMode;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: pmgmt %d, timeout %d\n", __func__, pmgmt, timeout));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1193,7 +1211,7 @@ ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy,
         pwrMode.powerMode = REC_POWER;
     }
 
-    if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != A_OK) {
+    if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_powermode_cmd failed\n", __func__));
         return -EIO;
     }
@@ -1201,7 +1219,7 @@ ar6k_cfg80211_set_power_mgmt(struct wiphy *wiphy,
     return 0;
 }
 
-static int
+static struct net_device *
 ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
             				    enum nl80211_iftype type, u32 *flags,
             				    struct vif_params *params)
@@ -1212,7 +1230,7 @@ ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
     /* Multiple virtual interface is not supported.
      * The default interface supports STA and IBSS type
      */
-    return -EOPNOTSUPP;
+    return ERR_PTR(-EOPNOTSUPP);
 }
 
 static int
@@ -1232,12 +1250,12 @@ ar6k_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
                            enum nl80211_iftype type, u32 *flags,
                            struct vif_params *params)
 {
-    AR_SOFTC_T *ar = ar6k_priv(ndev);
+    struct ar6_softc *ar = ar6k_priv(ndev);
     struct wireless_dev *wdev = ar->wdev;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type %u\n", __func__, type));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1268,12 +1286,12 @@ static int
 ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
                         struct cfg80211_ibss_params *ibss_param)
 {
-    AR_SOFTC_T *ar = ar6k_priv(dev);
-    A_STATUS status;
+    struct ar6_softc *ar = ar6k_priv(dev);
+    int status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1289,7 +1307,7 @@ ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
     }
 
     ar->arSsidLen = ibss_param->ssid_len;
-    A_MEMCPY(ar->arSsid, ibss_param->ssid, ar->arSsidLen);
+    memcpy(ar->arSsid, ibss_param->ssid, ar->arSsidLen);
 
     if(ibss_param->channel) {
         ar->arChannelHint = ibss_param->channel->center_freq;
@@ -1303,8 +1321,8 @@ ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 
     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     if(ibss_param->bssid) {
-        if(A_MEMCMP(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
-            A_MEMCPY(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid));
+        if(memcmp(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
+            memcpy(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid));
         }
     }
 
@@ -1335,6 +1353,7 @@ ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
                             ar->arSsidLen, ar->arSsid,
                             ar->arReqBssid, ar->arChannelHint,
                             ar->arConnectCtrlFlags);
+    ar->arConnectPending = true;
 
     return 0;
 }
@@ -1342,11 +1361,11 @@ ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 static int
 ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1356,7 +1375,7 @@ ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
         return -EIO;
     }
 
-    wmi_disconnect_cmd(ar->arWmi);
+    ar6000_disconnect(ar);
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
     ar->arSsidLen = 0;
 
@@ -1365,7 +1384,7 @@ ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 
 
 static const
-A_UINT32 cipher_suites[] = {
+u32 cipher_suites[] = {
     WLAN_CIPHER_SUITE_WEP40,
     WLAN_CIPHER_SUITE_WEP104,
     WLAN_CIPHER_SUITE_TKIP,
@@ -1410,7 +1429,7 @@ ar6k_cfg80211_init(struct device *dev)
     }
 
     /* create a new wiphy for use with cfg80211 */
-    wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(AR_SOFTC_T));
+    wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(struct ar6_softc));
     if(!wdev->wiphy) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("%s: Couldn't allocate wiphy device\n", __func__));
@@ -1444,7 +1463,7 @@ ar6k_cfg80211_init(struct device *dev)
 }
 
 void
-ar6k_cfg80211_deinit(AR_SOFTC_T *ar)
+ar6k_cfg80211_deinit(struct ar6_softc *ar)
 {
     struct wireless_dev *wdev = ar->wdev;
 
diff --git a/drivers/staging/ath6kl/os/linux/eeprom.c b/drivers/staging/ath6kl/os/linux/eeprom.c
index be77fb8..4cff9da 100644
--- a/drivers/staging/ath6kl/os/linux/eeprom.c
+++ b/drivers/staging/ath6kl/os/linux/eeprom.c
@@ -53,9 +53,9 @@ char *p_mac = NULL;
 // static variables
 //
 
-static A_UCHAR eeprom_data[EEPROM_SZ];
-static A_UINT32 sys_sleep_reg;
-static HIF_DEVICE *p_bmi_device;
+static u8 eeprom_data[EEPROM_SZ];
+static u32 sys_sleep_reg;
+static struct hif_device *p_bmi_device;
 
 //
 // Functions
@@ -63,7 +63,7 @@ static HIF_DEVICE *p_bmi_device;
 
 /* soft mac */
 static int
-wmic_ether_aton(const char *orig, A_UINT8 *eth)
+wmic_ether_aton(const char *orig, u8 *eth)
 {
   const char *bufp;
   int i;
@@ -103,23 +103,23 @@ wmic_ether_aton(const char *orig, A_UINT8 *eth)
 }
 
 static void
-update_mac(unsigned char* eeprom, int size, unsigned char* macaddr)
+update_mac(unsigned char *eeprom, int size, unsigned char *macaddr)
 {
 	int i;
-	A_UINT16* ptr = (A_UINT16*)(eeprom+4);
-	A_UINT16  checksum = 0;
+	u16 *ptr = (u16 *)(eeprom+4);
+	u16 checksum = 0;
 
 	memcpy(eeprom+10,macaddr,6);
 
 	*ptr = 0;
-	ptr = (A_UINT16*)eeprom;
+	ptr = (u16 *)eeprom;
 
 	for (i=0; i<size; i+=2) {
 		checksum ^= *ptr++;
 	}
 	checksum = ~checksum;
 
-	ptr = (A_UINT16*)(eeprom+4);
+	ptr = (u16 *)(eeprom+4);
 	*ptr = checksum;
 	return;
 }
@@ -127,30 +127,30 @@ update_mac(unsigned char* eeprom, int size, unsigned char* macaddr)
 
 /* Read a Target register and return its value. */
 inline void
-BMI_read_reg(A_UINT32 address, A_UINT32 *pvalue)
+BMI_read_reg(u32 address, u32 *pvalue)
 {
     BMIReadSOCRegister(p_bmi_device, address, pvalue);
 }
 
 /* Write a value to a Target register. */
 inline void
-BMI_write_reg(A_UINT32 address, A_UINT32 value)
+BMI_write_reg(u32 address, u32 value)
 {
     BMIWriteSOCRegister(p_bmi_device, address, value);
 }
 
 /* Read Target memory word and return its value. */
 inline void
-BMI_read_mem(A_UINT32 address, A_UINT32 *pvalue)
+BMI_read_mem(u32 address, u32 *pvalue)
 {
-    BMIReadMemory(p_bmi_device, address, (A_UCHAR*)(pvalue), 4);
+    BMIReadMemory(p_bmi_device, address, (u8*)(pvalue), 4);
 }
 
 /* Write a word to a Target memory. */
 inline void
-BMI_write_mem(A_UINT32 address, A_UINT8 *p_data, A_UINT32 sz)
+BMI_write_mem(u32 address, u8 *p_data, u32 sz)
 {
-    BMIWriteMemory(p_bmi_device, address, (A_UCHAR*)(p_data), sz); 
+    BMIWriteMemory(p_bmi_device, address, (u8*)(p_data), sz); 
 }
 
 /*
@@ -158,9 +158,9 @@ BMI_write_mem(A_UINT32 address, A_UINT8 *p_data, A_UINT32 sz)
  * so we can access the EEPROM.
  */
 static void
-enable_SI(HIF_DEVICE *p_device)
+enable_SI(struct hif_device *p_device)
 {
-    A_UINT32 regval;
+    u32 regval;
 
     printk("%s\n", __FUNCTION__);
 
@@ -200,7 +200,7 @@ enable_SI(HIF_DEVICE *p_device)
 static void
 disable_SI(void)
 {
-    A_UINT32 regval;
+    u32 regval;
     
     printk("%s\n", __FUNCTION__);
 
@@ -218,7 +218,7 @@ disable_SI(void)
 static void
 request_8byte_read(int offset)
 {
-    A_UINT32 regval;
+    u32 regval;
 
 //    printk("%s: request_8byte_read from offset 0x%x\n", __FUNCTION__, offset);
 
@@ -241,9 +241,9 @@ request_8byte_read(int offset)
  * writing values from Target TX_DATA registers.
  */
 static void
-request_4byte_write(int offset, A_UINT32 data)
+request_4byte_write(int offset, u32 data)
 {
-    A_UINT32 regval;
+    u32 regval;
 
     printk("%s: request_4byte_write (0x%x) to offset 0x%x\n", __FUNCTION__, data, offset);
 
@@ -266,10 +266,10 @@ request_4byte_write(int offset, A_UINT32 data)
  * Check whether or not an EEPROM request that was started
  * earlier has completed yet.
  */
-static A_BOOL
+static bool
 request_in_progress(void)
 {
-    A_UINT32 regval;
+    u32 regval;
 
     /* Wait for DONE_INT in SI_CS */
     BMI_read_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, &regval);
@@ -288,8 +288,8 @@ request_in_progress(void)
 
 static void eeprom_type_detect(void)
 {
-    A_UINT32 regval;
-    A_UINT8 i = 0;
+    u32 regval;
+    u8 i = 0;
 
     request_8byte_read(0x100);
    /* Wait for DONE_INT in SI_CS */
@@ -310,7 +310,7 @@ static void eeprom_type_detect(void)
  * and return them to the caller.
  */
 inline void
-read_8byte_results(A_UINT32 *data)
+read_8byte_results(u32 *data)
 {
     /* Read SI_RX_DATA0 and SI_RX_DATA1 */
     BMI_read_reg(SI_BASE_ADDRESS+SI_RX_DATA0_OFFSET, &data[0]);
@@ -339,7 +339,7 @@ wait_for_eeprom_completion(void)
  * waits for it to complete, and returns the result.
  */
 static void
-fetch_8bytes(int offset, A_UINT32 *data)
+fetch_8bytes(int offset, u32 *data)
 {
     request_8byte_read(offset);
     wait_for_eeprom_completion();
@@ -354,17 +354,17 @@ fetch_8bytes(int offset, A_UINT32 *data)
  * and waits for it to complete.
  */
 inline void
-commit_4bytes(int offset, A_UINT32 data)
+commit_4bytes(int offset, u32 data)
 {
     request_4byte_write(offset, data);
     wait_for_eeprom_completion();
 }
 /* ATHENV */
 #ifdef ANDROID_ENV
-void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file, char *p_mac)
+void eeprom_ar6000_transfer(struct hif_device *device, char *fake_file, char *p_mac)
 {
-    A_UINT32 first_word;
-    A_UINT32 board_data_addr;
+    u32 first_word;
+    u32 board_data_addr;
     int i;
 
     printk("%s: Enter\n", __FUNCTION__);
@@ -437,17 +437,17 @@ void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file, char *p_mac)
          * Fetch EEPROM_SZ Bytes of Board Data, 8 bytes at a time.
          */
 
-        fetch_8bytes(0, (A_UINT32 *)(&eeprom_data[0]));
+        fetch_8bytes(0, (u32 *)(&eeprom_data[0]));
 
         /* Check the first word of EEPROM for validity */
-        first_word = *((A_UINT32 *)eeprom_data);
+        first_word = *((u32 *)eeprom_data);
 
         if ((first_word == 0) || (first_word == 0xffffffff)) {
             printk("Did not find EEPROM with valid Board Data.\n");
         }
 
         for (i=8; i<EEPROM_SZ; i+=8) {
-            fetch_8bytes(i, (A_UINT32 *)(&eeprom_data[i]));
+            fetch_8bytes(i, (u32 *)(&eeprom_data[i]));
         }
     }
 
@@ -558,13 +558,13 @@ void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file, char *p_mac)
     /* soft mac */
 
     /* Write EEPROM data to Target RAM */
-    BMI_write_mem(board_data_addr, ((A_UINT8 *)eeprom_data), EEPROM_SZ);
+    BMI_write_mem(board_data_addr, ((u8 *)eeprom_data), EEPROM_SZ);
 
     /* Record the fact that Board Data IS initialized */
     {
-       A_UINT32 one = 1;
+       u32 one = 1;
        BMI_write_mem(HOST_INTEREST_ITEM_ADDRESS(hi_board_data_initialized),
-                     (A_UINT8 *)&one, sizeof(A_UINT32));
+                     (u8 *)&one, sizeof(u32));
     }
 
     disable_SI();
diff --git a/drivers/staging/ath6kl/os/linux/export_hci_transport.c b/drivers/staging/ath6kl/os/linux/export_hci_transport.c
index ffbf3d2..442a286 100644
--- a/drivers/staging/ath6kl/os/linux/export_hci_transport.c
+++ b/drivers/staging/ath6kl/os/linux/export_hci_transport.c
@@ -36,22 +36,22 @@
 #include "AR6002/hw4.0/hw/uart_reg.h"
 #include "AR6002/hw4.0/hw/rtc_wlan_reg.h"
 
-HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo);
 void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans);
-A_STATUS    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
-A_STATUS    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
+int    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
+int    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
 void        (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans);
-A_STATUS    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
-A_STATUS    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
-A_STATUS    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, 
-                                          HTC_PACKET           *pPacket,
+int    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
+int    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
+int    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans,
+                                          struct htc_packet           *pPacket,
                                           int                  MaxPollMS);
-A_STATUS    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
-A_STATUS    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+int    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
+int    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
-extern HCI_TRANSPORT_CALLBACKS ar6kHciTransCallbacks;
+extern struct hci_transport_callbacks ar6kHciTransCallbacks;
 
-A_STATUS ar6000_register_hci_transport(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks)
+int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks)
 {
     ar6kHciTransCallbacks = *hciTransCallbacks;
 
@@ -66,41 +66,41 @@ A_STATUS ar6000_register_hci_transport(HCI_TRANSPORT_CALLBACKS *hciTransCallback
     _HCI_TransportSetBaudRate = HCI_TransportSetBaudRate;
     _HCI_TransportEnablePowerMgmt = HCI_TransportEnablePowerMgmt;
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-ar6000_get_hif_dev(HIF_DEVICE *device, void *config)
+int
+ar6000_get_hif_dev(struct hif_device *device, void *config)
 {
-    A_STATUS status;
+    int status;
 
     status = HIFConfigureDevice(device,
                                 HIF_DEVICE_GET_OS_DEVICE,
-                                (HIF_DEVICE_OS_DEVICE_INFO *)config, 
-                                sizeof(HIF_DEVICE_OS_DEVICE_INFO));
+                                (struct hif_device_os_device_info *)config, 
+                                sizeof(struct hif_device_os_device_info));
     return status;
 }
 
-A_STATUS ar6000_set_uart_config(HIF_DEVICE *hifDevice, 
-                                A_UINT32 scale, 
-                                A_UINT32 step)
+int ar6000_set_uart_config(struct hif_device *hifDevice,
+                                u32 scale,
+                                u32 step)
 {
-    A_UINT32 regAddress;
-    A_UINT32 regVal;
-    A_STATUS status;
+    u32 regAddress;
+    u32 regVal;
+    int status;
 
     regAddress = WLAN_UART_BASE_ADDRESS | UART_CLKDIV_ADDRESS;
-    regVal = ((A_UINT32)scale << 16) | step;
+    regVal = ((u32)scale << 16) | step;
     /* change the HCI UART scale/step values through the diagnostic window */
     status = ar6000_WriteRegDiag(hifDevice, &regAddress, &regVal);                     
 
     return status;
 }
 
-A_STATUS ar6000_get_core_clock_config(HIF_DEVICE *hifDevice, A_UINT32 *data)
+int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data)
 {
-    A_UINT32 regAddress;
-    A_STATUS status;
+    u32 regAddress;
+    int status;
 
     regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS;
     /* read CPU clock settings*/
diff --git a/drivers/staging/ath6kl/os/linux/hci_bridge.c b/drivers/staging/ath6kl/os/linux/hci_bridge.c
index 5cdc3b8..39e5798 100644
--- a/drivers/staging/ath6kl/os/linux/hci_bridge.c
+++ b/drivers/staging/ath6kl/os/linux/hci_bridge.c
@@ -73,21 +73,21 @@ extern unsigned int hciuartscale;
 extern unsigned int hciuartstep;
 #endif /* EXPORT_HCI_BRIDGE_INTERFACE */
 
-typedef struct {
+struct ar6k_hci_bridge_info {
     void                    *pHCIDev;          /* HCI bridge device */
-    HCI_TRANSPORT_PROPERTIES HCIProps;         /* HCI bridge props */
+    struct hci_transport_properties HCIProps;         /* HCI bridge props */
     struct hci_dev          *pBtStackHCIDev;   /* BT Stack HCI dev */
-    A_BOOL                  HciNormalMode;     /* Actual HCI mode enabled (non-TEST)*/
-    A_BOOL                  HciRegistered;     /* HCI device registered with stack */
-    HTC_PACKET_QUEUE        HTCPacketStructHead;
-    A_UINT8                 *pHTCStructAlloc;
+    bool                  HciNormalMode;     /* Actual HCI mode enabled (non-TEST)*/
+    bool                  HciRegistered;     /* HCI device registered with stack */
+    struct htc_packet_queue        HTCPacketStructHead;
+    u8 *pHTCStructAlloc;
     spinlock_t              BridgeLock;
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-    HCI_TRANSPORT_MISC_HANDLES    HCITransHdl; 
+    struct hci_transport_misc_handles    HCITransHdl; 
 #else
-    AR_SOFTC_T              *ar;
+    struct ar6_softc              *ar;
 #endif /* EXPORT_HCI_BRIDGE_INTERFACE */
-} AR6K_HCI_BRIDGE_INFO;
+};
 
 #define MAX_ACL_RECV_BUFS           16
 #define MAX_EVT_RECV_BUFS           8
@@ -97,39 +97,39 @@ typedef struct {
 #define TX_PACKET_RSV_OFFSET        32
 #define NUM_HTC_PACKET_STRUCTS     ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2)
 
-#define HCI_GET_OP_CODE(p)          (((A_UINT16)((p)[1])) << 8) | ((A_UINT16)((p)[0]))
+#define HCI_GET_OP_CODE(p)          (((u16)((p)[1])) << 8) | ((u16)((p)[0]))
 
 extern unsigned int setupbtdev;
-AR3K_CONFIG_INFO      ar3kconfig;
+struct ar3k_config_info      ar3kconfig;
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-AR6K_HCI_BRIDGE_INFO *g_pHcidevInfo;
+struct ar6k_hci_bridge_info *g_pHcidevInfo;
 #endif
 
-static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo);
-static void     bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo);
-static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo);
-static A_BOOL   bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
+static void     bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
+static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
+static bool   bt_indicate_recv(struct ar6k_hci_bridge_info      *pHcidevInfo,
                                  HCI_TRANSPORT_PACKET_TYPE Type, 
                                  struct sk_buff            *skb);
-static struct sk_buff *bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length);
-static void     bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb);   
+static struct sk_buff *bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length);
+static void     bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb);   
                                
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(void *ar);
+int ar6000_setup_hci(void *ar);
 void     ar6000_cleanup_hci(void *ar);
-A_STATUS hci_test_send(void *ar, struct sk_buff *skb);
+int hci_test_send(void *ar, struct sk_buff *skb);
 #else
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar);
-void     ar6000_cleanup_hci(AR_SOFTC_T *ar);
+int ar6000_setup_hci(struct ar6_softc *ar);
+void     ar6000_cleanup_hci(struct ar6_softc *ar);
 /* HCI bridge testing */
-A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb);
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb);
 #endif /* EXPORT_HCI_BRIDGE_INTERFACE */
 
 #define LOCK_BRIDGE(dev)   spin_lock_bh(&(dev)->BridgeLock)
 #define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock)
 
-static inline void FreeBtOsBuf(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, void *osbuf)
+static inline void FreeBtOsBuf(struct ar6k_hci_bridge_info *pHcidevInfo, void *osbuf)
 {    
     if (pHcidevInfo->HciNormalMode) {
         bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf);
@@ -139,16 +139,16 @@ static inline void FreeBtOsBuf(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, void *osbuf)
     }
 }
 
-static void FreeHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, HTC_PACKET *pPacket)
+static void FreeHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo, struct htc_packet *pPacket)
 {
     LOCK_BRIDGE(pHcidevInfo);
     HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket);
     UNLOCK_BRIDGE(pHcidevInfo);  
 }
 
-static HTC_PACKET * AllocHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static struct htc_packet * AllocHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    HTC_PACKET  *pPacket = NULL;
+    struct htc_packet  *pPacket = NULL;
     LOCK_BRIDGE(pHcidevInfo);
     pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead);
     UNLOCK_BRIDGE(pHcidevInfo);  
@@ -157,14 +157,14 @@ static HTC_PACKET * AllocHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
 
 #define BLOCK_ROUND_UP_PWR2(x, align)    (((int) (x) + ((align)-1)) & ~((align)-1))
 
-static void RefillRecvBuffers(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static void RefillRecvBuffers(struct ar6k_hci_bridge_info      *pHcidevInfo, 
                               HCI_TRANSPORT_PACKET_TYPE Type, 
                               int                       NumBuffers)
 {
     int                 length, i;
     void                *osBuf = NULL;
-    HTC_PACKET_QUEUE    queue;
-    HTC_PACKET          *pPacket;
+    struct htc_packet_queue    queue;
+    struct htc_packet          *pPacket;
 
     INIT_HTC_PACKET_QUEUE(&queue);
     
@@ -215,18 +215,18 @@ static void RefillRecvBuffers(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo,
 #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
         (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \
         (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))
-static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle, 
-                                           HCI_TRANSPORT_PROPERTIES *pProps, 
+static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
+                                           struct hci_transport_properties *pProps, 
                                            void                     *pContext)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
-    A_STATUS              status;
-    A_UINT32 address, hci_uart_pwr_mgmt_params;
-//    AR3K_CONFIG_INFO      ar3kconfig;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
+    int              status;
+    u32 address, hci_uart_pwr_mgmt_params;
+//    struct ar3k_config_info      ar3kconfig;
     
     pHcidevInfo->pHCIDev = HCIHandle;
     
-    A_MEMCPY(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
+    memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
     
     AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", 
             (unsigned long)HCIHandle, 
@@ -248,7 +248,7 @@ static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
             /* start transport */
         status = HCI_TransportStart(pHcidevInfo->pHCIDev);
          
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -270,7 +270,7 @@ static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
         ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
         ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-        ar3kconfig.pHIFDevice = (HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice);
+        ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice);
 #else
         ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
 #endif
@@ -285,8 +285,8 @@ static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
         
         if ((hciuartscale != 0) || (hciuartstep != 0)) {   
                 /* user wants to tune HCI bridge UART scale/step values */
-            ar3kconfig.AR6KScale = (A_UINT16)hciuartscale;
-            ar3kconfig.AR6KStep = (A_UINT16)hciuartstep;           
+            ar3kconfig.AR6KScale = (u16)hciuartscale;
+            ar3kconfig.AR6KStep = (u16)hciuartstep;
             ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
         }
         
@@ -294,7 +294,7 @@ static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
         address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                             HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params));
         status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
-        if (A_OK == status) {
+        if (0 == status) {
             ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1);
             ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16;
             ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8;
@@ -304,28 +304,28 @@ static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
         /* configure the AR3K device */         
 		memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6);
         status = AR3KConfigure(&ar3kconfig);
-        if (A_FAILED(status)) {
+        if (status) {
             break; 
         }
 
         /* Make sure both AR6K and AR3K have power management enabled */
         if (ar3kconfig.PwrMgmtEnabled) {
-            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, TRUE);
-            if (A_FAILED(status)) {
+            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true);
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
             }
         }
         
         status = bt_register_hci(pHcidevInfo);
         
-    } while (FALSE);
+    } while (false);
 
     return status; 
 }
 
-static void ar6000_hci_transport_failure(void *pContext, A_STATUS Status)
+static void ar6000_hci_transport_failure(void *pContext, int Status)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n"));
     
@@ -336,7 +336,7 @@ static void ar6000_hci_transport_failure(void *pContext, A_STATUS Status)
 
 static void ar6000_hci_transport_removed(void *pContext)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n"));
     
@@ -347,14 +347,14 @@ static void ar6000_hci_transport_removed(void *pContext)
     pHcidevInfo->pHCIDev = NULL;
 }
 
-static void ar6000_hci_send_complete(void *pContext, HTC_PACKET *pPacket)
+static void ar6000_hci_send_complete(void *pContext, struct htc_packet *pPacket)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     void                 *osbuf = pPacket->pPktContext;
     A_ASSERT(osbuf != NULL);
     A_ASSERT(pHcidevInfo != NULL);
     
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); 
         }   
@@ -365,9 +365,9 @@ static void ar6000_hci_send_complete(void *pContext, HTC_PACKET *pPacket)
     
 }
 
-static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket)
+static void ar6000_hci_pkt_recv(void *pContext, struct htc_packet *pPacket)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     struct sk_buff       *skb;
     
     A_ASSERT(pHcidevInfo != NULL);
@@ -376,7 +376,7 @@ static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket)
           
     do {
         
-        if (A_FAILED(pPacket->Status)) {
+        if (pPacket->Status) {
             break;
         }
   
@@ -419,7 +419,7 @@ static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket)
             skb = NULL;
         } 
         
-    } while (FALSE);
+    } while (false);
     
     FreeHTCStruct(pHcidevInfo,pPacket);
     
@@ -432,7 +432,7 @@ static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket)
 
 static void  ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     int                  refillCount;
 
     if (Type == HCI_ACL_TYPE) {
@@ -447,9 +447,9 @@ static void  ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Typ
     
 }
 
-static HCI_SEND_FULL_ACTION  ar6000_hci_pkt_send_full(void *pContext, HTC_PACKET *pPacket)
+static HCI_SEND_FULL_ACTION  ar6000_hci_pkt_send_full(void *pContext, struct htc_packet *pPacket)
 {
-    AR6K_HCI_BRIDGE_INFO    *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info    *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     HCI_SEND_FULL_ACTION    action = HCI_SEND_FULL_KEEP;
     
     if (!pHcidevInfo->HciNormalMode) {
@@ -464,31 +464,31 @@ static HCI_SEND_FULL_ACTION  ar6000_hci_pkt_send_full(void *pContext, HTC_PACKET
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(void *ar)
+int ar6000_setup_hci(void *ar)
 #else
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
+int ar6000_setup_hci(struct ar6_softc *ar)
 #endif
 {
-    HCI_TRANSPORT_CONFIG_INFO config;
-    A_STATUS                  status = A_OK;
+    struct hci_transport_config_info config;
+    int                  status = 0;
     int                       i;
-    HTC_PACKET                *pPacket;
-    AR6K_HCI_BRIDGE_INFO      *pHcidevInfo;
+    struct htc_packet                *pPacket;
+    struct ar6k_hci_bridge_info      *pHcidevInfo;
         
        
     do {
         
-        pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)A_MALLOC(sizeof(AR6K_HCI_BRIDGE_INFO));
+        pHcidevInfo = (struct ar6k_hci_bridge_info *)A_MALLOC(sizeof(struct ar6k_hci_bridge_info));
         
         if (NULL == pHcidevInfo) {
             status = A_NO_MEMORY;
             break;    
         }
         
-        A_MEMZERO(pHcidevInfo, sizeof(AR6K_HCI_BRIDGE_INFO));
+        A_MEMZERO(pHcidevInfo, sizeof(struct ar6k_hci_bridge_info));
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
         g_pHcidevInfo = pHcidevInfo;
-        pHcidevInfo->HCITransHdl = *(HCI_TRANSPORT_MISC_HANDLES *)ar;
+        pHcidevInfo->HCITransHdl = *(struct hci_transport_misc_handles *)ar;
 #else
         ar->hcidev_info = pHcidevInfo;
         pHcidevInfo->ar = ar;
@@ -499,7 +499,7 @@ A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
         ar->exitCallback = AR3KConfigureExit;
     
         status = bt_setup_hci(pHcidevInfo);
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -509,19 +509,19 @@ A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
             AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n"));     
         }
         
-        pHcidevInfo->pHTCStructAlloc = (A_UINT8 *)A_MALLOC((sizeof(HTC_PACKET)) * NUM_HTC_PACKET_STRUCTS);
+        pHcidevInfo->pHTCStructAlloc = (u8 *)A_MALLOC((sizeof(struct htc_packet)) * NUM_HTC_PACKET_STRUCTS);
         
         if (NULL == pHcidevInfo->pHTCStructAlloc) {
             status = A_NO_MEMORY;
             break;    
         }
         
-        pPacket = (HTC_PACKET *)pHcidevInfo->pHTCStructAlloc;
+        pPacket = (struct htc_packet *)pHcidevInfo->pHTCStructAlloc;
         for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) {
             FreeHTCStruct(pHcidevInfo,pPacket);                
         }
         
-        A_MEMZERO(&config,sizeof(HCI_TRANSPORT_CONFIG_INFO));        
+        A_MEMZERO(&config,sizeof(struct hci_transport_config_info));        
         config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2;
         config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2;
         config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH;
@@ -544,14 +544,14 @@ A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
             status = A_ERROR;      
         }
     
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         if (pHcidevInfo != NULL) {
             if (NULL == pHcidevInfo->pHCIDev) {
                 /* GMBOX may not be present in older chips */
                 /* just return success */ 
-                status = A_OK;
+                status = 0;
             }
         }
         ar6000_cleanup_hci(ar);    
@@ -563,13 +563,13 @@ A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 void  ar6000_cleanup_hci(void *ar)
 #else
-void  ar6000_cleanup_hci(AR_SOFTC_T *ar)
+void  ar6000_cleanup_hci(struct ar6_softc *ar)
 #endif
 {
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo;
+    struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo;
 #else
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
 #endif
     
     if (pHcidevInfo != NULL) {
@@ -596,20 +596,20 @@ void  ar6000_cleanup_hci(AR_SOFTC_T *ar)
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS hci_test_send(void *ar, struct sk_buff *skb)
+int hci_test_send(void *ar, struct sk_buff *skb)
 #else
-A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb)
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb)
 #endif
 {
-    int              status = A_OK;
+    int              status = 0;
     int              length;
     EPPING_HEADER    *pHeader;
-    HTC_PACKET       *pPacket;   
+    struct htc_packet       *pPacket;   
     HTC_TX_TAG       htc_tag = AR6K_DATA_PKT_TAG;
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo;
+    struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo;
 #else
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
 #endif
             
     do {
@@ -656,18 +656,18 @@ A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb)
                                HCI_ACL_TYPE,  /* send every thing out as ACL */
                                htc_tag);
              
-        HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE);                           
+        HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false);
         pPacket = NULL;
             
-    } while (FALSE);
+    } while (false);
             
     return status;
 }
 
-void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig)
+void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info;
-    AR3K_CONFIG_INFO *config = (AR3K_CONFIG_INFO *)ar3kconfig;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
+    struct ar3k_config_info *config = (struct ar3k_config_info *)ar3kconfig;
 
     config->pHCIDev = pHcidevInfo->pHCIDev;
     config->pHCIProps = &pHcidevInfo->HCIProps;
@@ -710,9 +710,9 @@ static int bt_send_frame(struct sk_buff *skb)
 {
     struct hci_dev             *hdev = (struct hci_dev *)skb->dev;
     HCI_TRANSPORT_PACKET_TYPE  type;
-    AR6K_HCI_BRIDGE_INFO       *pHcidevInfo;
-    HTC_PACKET                 *pPacket;
-    A_STATUS                   status = A_OK;
+    struct ar6k_hci_bridge_info       *pHcidevInfo;
+    struct htc_packet                 *pPacket;
+    int                   status = 0;
     struct sk_buff             *txSkb = NULL;
     
     if (!hdev) {
@@ -725,7 +725,7 @@ static int bt_send_frame(struct sk_buff *skb)
         return -EBUSY;
     }
   
-    pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)hdev->driver_data;   
+    pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data;   
     A_ASSERT(pHcidevInfo != NULL);
       
     AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type));
@@ -747,7 +747,7 @@ static int bt_send_frame(struct sk_buff *skb)
             kfree_skb(skb);
             return 0;
         default:
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             kfree_skb(skb);
             return 0;
     } 
@@ -757,7 +757,7 @@ static int bt_send_frame(struct sk_buff *skb)
                         (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL",
                         skb->len));
         if (type == HCI_COMMAND_TYPE) {
-            A_UINT16 opcode = HCI_GET_OP_CODE(skb->data);
+            u16 opcode = HCI_GET_OP_CODE(skb->data);
             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("    HCI Command: OGF:0x%X OCF:0x%X \r\n", 
                   opcode >> 10, opcode & 0x3FF));
         }
@@ -778,7 +778,7 @@ static int bt_send_frame(struct sk_buff *skb)
         bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
         txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev;
         skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom);
-        A_MEMCPY(txSkb->data, skb->data, skb->len);
+        memcpy(txSkb->data, skb->data, skb->len);
         skb_put(txSkb,skb->len);
         
         pPacket = AllocHTCStruct(pHcidevInfo);        
@@ -802,11 +802,11 @@ static int bt_send_frame(struct sk_buff *skb)
         AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n",
                                       type, txSkb->len));
                                       
-        status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE);   
+        status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false);
         pPacket = NULL;
         txSkb = NULL;
         
-    } while (FALSE);
+    } while (false);
    
     if (txSkb != NULL) {
         kfree_skb(txSkb);    
@@ -832,11 +832,11 @@ static int bt_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
 */
 static int bt_flush(struct hci_dev *hdev)
 {
-    AR6K_HCI_BRIDGE_INFO    *pHcidevInfo; 
+    struct ar6k_hci_bridge_info    *pHcidevInfo; 
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n"));
     
-    pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)hdev->driver_data;   
+    pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data;   
     
     /* TODO??? */   
     
@@ -853,14 +853,14 @@ static void bt_destruct(struct hci_dev *hdev)
     /* nothing to do here */
 }
 
-static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    A_STATUS                    status = A_OK;
+    int                    status = 0;
     struct hci_dev              *pHciDev = NULL;
-    HIF_DEVICE_OS_DEVICE_INFO   osDevInfo;
+    struct hif_device_os_device_info   osDevInfo;
     
     if (!setupbtdev) {
-        return A_OK;    
+        return 0;
     } 
         
     do {
@@ -868,7 +868,7 @@ static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
         A_MEMZERO(&osDevInfo,sizeof(osDevInfo));
             /* get the underlying OS device */
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-        status = ar6000_get_hif_dev((HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice), 
+        status = ar6000_get_hif_dev((struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice), 
                                     &osDevInfo);
 #else
         status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice, 
@@ -877,7 +877,7 @@ static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
                                     sizeof(osDevInfo));
 #endif
                                     
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n"));
             break;
         }
@@ -902,23 +902,23 @@ static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
         pHciDev->destruct = bt_destruct;
         pHciDev->owner = THIS_MODULE; 
             /* driver is running in normal BT mode */
-        pHcidevInfo->HciNormalMode = TRUE;  
+        pHcidevInfo->HciNormalMode = true;
         
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         bt_cleanup_hci(pHcidevInfo);    
     }
     
     return status;
 }
 
-static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {   
     int   err;      
         
     if (pHcidevInfo->HciRegistered) {
-        pHcidevInfo->HciRegistered = FALSE;
+        pHcidevInfo->HciRegistered = false;
         clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags);
         clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags);
         clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags);   
@@ -929,43 +929,41 @@ static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
         }          
     }   
     
-    if (pHcidevInfo->pBtStackHCIDev != NULL) {
-        kfree(pHcidevInfo->pBtStackHCIDev);
-        pHcidevInfo->pBtStackHCIDev = NULL;
-    }  
+    kfree(pHcidevInfo->pBtStackHCIDev);
+    pHcidevInfo->pBtStackHCIDev = NULL;  
 }
 
-static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
     int       err;
-    A_STATUS  status = A_OK;
+    int  status = 0;
     
     do {          
         AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n"));
         A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL);
              /* mark that we are registered */
-        pHcidevInfo->HciRegistered = TRUE;
+        pHcidevInfo->HciRegistered = true;
         if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err));
-            pHcidevInfo->HciRegistered = FALSE;
+            pHcidevInfo->HciRegistered = false;
             status = A_ERROR;
             break;
         }
     
         AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n"));
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
-static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static bool bt_indicate_recv(struct ar6k_hci_bridge_info      *pHcidevInfo,
                                HCI_TRANSPORT_PACKET_TYPE Type, 
                                struct                    sk_buff *skb)
 {
-    A_UINT8               btType;
+    u8 btType;
     int                   len;
-    A_BOOL                success = FALSE;
+    bool                success = false;
     BT_HCI_EVENT_HEADER   *pEvent;
     
     do {
@@ -984,7 +982,7 @@ static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo,
                 break;
             default:
                 btType = 0;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
         } 
         
@@ -1015,14 +1013,14 @@ static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo,
                     ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len));
         }
             
-        success = TRUE;
+        success = true;
     
-    } while (FALSE); 
+    } while (false);
     
     return success;
 }
 
-static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length) 
+static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) 
 { 
     struct sk_buff *skb;         
         /* in normal HCI mode we need to alloc from the bt core APIs */
@@ -1033,7 +1031,7 @@ static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Le
     return skb;
 }
 
-static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb)
+static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb)
 {
     kfree_skb(skb);    
 }
@@ -1041,36 +1039,36 @@ static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *sk
 #else // { CONFIG_BLUEZ_HCI_BRIDGE
 
     /* stubs when we only want to test the HCI bridging Interface without the HT stack */
-static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    return A_OK;    
+    return 0;
 }
-static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {   
      
 }
-static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    A_ASSERT(FALSE);
+    A_ASSERT(false);
     return A_ERROR;    
 }
 
-static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static bool bt_indicate_recv(struct ar6k_hci_bridge_info      *pHcidevInfo,
                                HCI_TRANSPORT_PACKET_TYPE Type, 
                                struct                    sk_buff *skb)
 {
-    A_ASSERT(FALSE);
-    return FALSE;    
+    A_ASSERT(false);
+    return false;
 }
 
-static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length) 
+static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) 
 {
-    A_ASSERT(FALSE);
+    A_ASSERT(false);
     return NULL;
 }
-static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb)
+static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb)
 {
-    A_ASSERT(FALSE);
+    A_ASSERT(false);
 }
 
 #endif // } CONFIG_BLUEZ_HCI_BRIDGE
@@ -1080,25 +1078,25 @@ static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *sk
     /* stubs when GMBOX support is not needed */
     
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(void *ar)
+int ar6000_setup_hci(void *ar)
 #else
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
+int ar6000_setup_hci(struct ar6_softc *ar)
 #endif
 {
-    return A_OK;   
+    return 0;
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 void ar6000_cleanup_hci(void *ar)
 #else
-void ar6000_cleanup_hci(AR_SOFTC_T *ar)
+void ar6000_cleanup_hci(struct ar6_softc *ar)
 #endif
 {
     return;    
 }
 
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
-void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig)
+void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig)
 {
     return;
 }
@@ -1107,7 +1105,7 @@ void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig)
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 int hci_test_send(void *ar, struct sk_buff *skb)
 #else
-int hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb)
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb)
 #endif
 {
     return -EOPNOTSUPP;
@@ -1120,14 +1118,14 @@ int hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb)
 static int __init
 hcibridge_init_module(void)
 {
-    A_STATUS status;
-    HCI_TRANSPORT_CALLBACKS hciTransCallbacks;
+    int status;
+    struct hci_transport_callbacks hciTransCallbacks;
 
     hciTransCallbacks.setupTransport = ar6000_setup_hci;
     hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci;
 
     status = ar6000_register_hci_transport(&hciTransCallbacks);
-    if(status != A_OK)
+    if (status)
         return -ENODEV;
 
     return 0;
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
index e624883..89fd80a 100644
--- a/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
+++ b/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
@@ -104,7 +104,7 @@ struct USER_SAVEDKEYS {
     struct ieee80211req_key   ucast_ik;
     struct ieee80211req_key   bcast_ik;
     CRYPTO_TYPE               keyType;
-    A_BOOL                    keyOk;
+    bool                    keyOk;
 };
 #endif
 
@@ -121,8 +121,8 @@ struct USER_SAVEDKEYS {
 #define DBG_DEFAULTS    (DBG_ERROR|DBG_WARNING)
 
 
-A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
-A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
+int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
 #ifdef __cplusplus
 extern "C" {
@@ -362,7 +362,7 @@ typedef struct {
     int currPtr;
     int length;
     unsigned char data[HTC_RAW_BUFFER_SIZE];
-    HTC_PACKET    HTCPacket;
+    struct htc_packet    HTCPacket;
 } raw_htc_buffer;
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
@@ -380,41 +380,47 @@ enum {
 #endif /* CONFIG_HOST_TCMD_SUPPORT */
 
 struct ar_wep_key {
-    A_UINT8                 arKeyIndex;
-    A_UINT8                 arKeyLen;
-    A_UINT8                 arKey[64];
+    u8 arKeyIndex;
+    u8 arKeyLen;
+    u8 arKey[64];
 } ;
 
 #ifdef ATH6K_CONFIG_CFG80211
 struct ar_key {
-    A_UINT8     key[WLAN_MAX_KEY_LEN];
-    A_UINT8     key_len;
-    A_UINT8     seq[IW_ENCODE_SEQ_MAX_SIZE];
-    A_UINT8     seq_len;
-    A_UINT32    cipher;
+    u8 key[WLAN_MAX_KEY_LEN];
+    u8 key_len;
+    u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
+    u8 seq_len;
+    u32 cipher;
+};
+
+enum {
+    SME_DISCONNECTED,
+    SME_CONNECTING,
+    SME_CONNECTED
 };
 #endif /* ATH6K_CONFIG_CFG80211 */
 
 
 struct ar_node_mapping {
-    A_UINT8                 macAddress[6];
-    A_UINT8                 epId;
-    A_UINT8                 txPending;
+    u8 macAddress[6];
+    u8 epId;
+    u8 txPending;
 };
 
 struct ar_cookie {
     unsigned long          arc_bp[2];    /* Must be first field */
-    HTC_PACKET             HtcPkt;       /* HTC packet wrapper */
+    struct htc_packet             HtcPkt;       /* HTC packet wrapper */
     struct ar_cookie *arc_list_next;
 };
 
 struct ar_hb_chlng_resp {
     A_TIMER                 timer;
-    A_UINT32                frequency;
-    A_UINT32                seqNum;
-    A_BOOL                  outstanding;
-    A_UINT8                 missCnt;
-    A_UINT8                 missThres;
+    u32 frequency;
+    u32 seqNum;
+    bool                  outstanding;
+    u8 missCnt;
+    u8 missThres;
 };
 
 /* Per STA data, used in AP mode */
@@ -436,13 +442,13 @@ struct ar_hb_chlng_resp {
 #define STA_IS_PS_POLLED(sta) (sta->flags & (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT))
 
 typedef struct {
-    A_UINT16                flags;
-    A_UINT8                 mac[ATH_MAC_LEN];
-    A_UINT8                 aid;
-    A_UINT8                 keymgmt;
-    A_UINT8                 ucipher;
-    A_UINT8                 auth;
-    A_UINT8                 wpa_ie[IEEE80211_MAX_IE];
+    u16 flags;
+    u8 mac[ATH_MAC_LEN];
+    u8 aid;
+    u8 keymgmt;
+    u8 ucipher;
+    u8 auth;
+    u8 wpa_ie[IEEE80211_MAX_IE];
     A_NETBUF_QUEUE_T        psq;    /* power save q */
     A_MUTEX_T               psqLock;
 } sta_t;
@@ -456,173 +462,174 @@ typedef struct ar6_raw_htc {
     wait_queue_head_t       raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX];
     raw_htc_buffer          raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM];
     raw_htc_buffer          raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM];
-    A_BOOL                  write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
-    A_BOOL                  read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
+    bool                  write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
+    bool                  read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
 } AR_RAW_HTC_T;
 
-typedef struct ar6_softc {
+struct ar6_softc {
     struct net_device       *arNetDev;    /* net_device pointer */
     void                    *arWmi;
     int                     arTxPending[ENDPOINT_MAX];
     int                     arTotalTxDataPending;
-    A_UINT8                 arNumDataEndPts;
-    A_BOOL                  arWmiEnabled;
-    A_BOOL                  arWmiReady;
-    A_BOOL                  arConnected;
+    u8 arNumDataEndPts;
+    bool                  arWmiEnabled;
+    bool                  arWmiReady;
+    bool                  arConnected;
     HTC_HANDLE              arHtcTarget;
     void                    *arHifDevice;
     spinlock_t              arLock;
     struct semaphore        arSem;
     int                     arSsidLen;
     u_char                  arSsid[32];
-    A_UINT8                 arNextMode;
-    A_UINT8                 arNetworkType;
-    A_UINT8                 arDot11AuthMode;
-    A_UINT8                 arAuthMode;
-    A_UINT8                 arPairwiseCrypto;
-    A_UINT8                 arPairwiseCryptoLen;
-    A_UINT8                 arGroupCrypto;
-    A_UINT8                 arGroupCryptoLen;
-    A_UINT8                 arDefTxKeyIndex;
+    u8 arNextMode;
+    u8 arNetworkType;
+    u8 arDot11AuthMode;
+    u8 arAuthMode;
+    u8 arPairwiseCrypto;
+    u8 arPairwiseCryptoLen;
+    u8 arGroupCrypto;
+    u8 arGroupCryptoLen;
+    u8 arDefTxKeyIndex;
     struct ar_wep_key       arWepKeyList[WMI_MAX_KEY_INDEX + 1];
-    A_UINT8                 arBssid[6];
-    A_UINT8                 arReqBssid[6];
-    A_UINT16                arChannelHint;
-    A_UINT16                arBssChannel;
-    A_UINT16                arListenIntervalB;
-    A_UINT16                arListenIntervalT;
+    u8 arBssid[6];
+    u8 arReqBssid[6];
+    u16 arChannelHint;
+    u16 arBssChannel;
+    u16 arListenIntervalB;
+    u16 arListenIntervalT;
     struct ar6000_version   arVersion;
-    A_UINT32                arTargetType;
-    A_INT8                  arRssi;
-    A_UINT8                 arTxPwr;
-    A_BOOL                  arTxPwrSet;
-    A_INT32                 arBitRate;
+    u32 arTargetType;
+    s8 arRssi;
+    u8 arTxPwr;
+    bool                  arTxPwrSet;
+    s32 arBitRate;
     struct net_device_stats arNetStats;
     struct iw_statistics    arIwStats;
-    A_INT8                  arNumChannels;
-    A_UINT16                arChannelList[32];
-    A_UINT32                arRegCode;
-    A_BOOL                  statsUpdatePending;
+    s8 arNumChannels;
+    u16 arChannelList[32];
+    u32 arRegCode;
+    bool                  statsUpdatePending;
     TARGET_STATS            arTargetStats;
-    A_INT8                  arMaxRetries;
-    A_UINT8                 arPhyCapability;
+    s8 arMaxRetries;
+    u8 arPhyCapability;
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-    A_UINT8                 tcmdRxReport;
-    A_UINT32                tcmdRxTotalPkt;
-    A_INT32                 tcmdRxRssi;
-    A_UINT32                tcmdPm;
-    A_UINT32                arTargetMode;
-    A_UINT32                tcmdRxcrcErrPkt;
-    A_UINT32                tcmdRxsecErrPkt;
-    A_UINT16                tcmdRateCnt[TCMD_MAX_RATES];
-    A_UINT16                tcmdRateCntShortGuard[TCMD_MAX_RATES];
+    u8 tcmdRxReport;
+    u32 tcmdRxTotalPkt;
+    s32 tcmdRxRssi;
+    u32 tcmdPm;
+    u32 arTargetMode;
+    u32 tcmdRxcrcErrPkt;
+    u32 tcmdRxsecErrPkt;
+    u16 tcmdRateCnt[TCMD_MAX_RATES];
+    u16 tcmdRateCntShortGuard[TCMD_MAX_RATES];
 #endif
     AR6000_WLAN_STATE       arWlanState;
     struct ar_node_mapping  arNodeMap[MAX_NODE_NUM];
-    A_UINT8                 arIbssPsEnable;
-    A_UINT8                 arNodeNum;
-    A_UINT8                 arNexEpId;
+    u8 arIbssPsEnable;
+    u8 arNodeNum;
+    u8 arNexEpId;
     struct ar_cookie        *arCookieList;
-    A_UINT32                arCookieCount;
-    A_UINT32                arRateMask;
-    A_UINT8                 arSkipScan;
-    A_UINT16                arBeaconInterval;
-    A_BOOL                  arConnectPending;
-    A_BOOL                  arWmmEnabled;
+    u32 arCookieCount;
+    u32 arRateMask;
+    u8 arSkipScan;
+    u16 arBeaconInterval;
+    bool                  arConnectPending;
+    bool                  arWmmEnabled;
     struct ar_hb_chlng_resp arHBChallengeResp;
-    A_UINT8                 arKeepaliveConfigured;
-    A_UINT32                arMgmtFilter;
+    u8 arKeepaliveConfigured;
+    u32 arMgmtFilter;
     HTC_ENDPOINT_ID         arAc2EpMapping[WMM_NUM_AC];
-    A_BOOL                  arAcStreamActive[WMM_NUM_AC];
-    A_UINT8                 arAcStreamPriMap[WMM_NUM_AC];
-    A_UINT8                 arHiAcStreamActivePri;
-    A_UINT8                 arEp2AcMapping[ENDPOINT_MAX];
+    bool                  arAcStreamActive[WMM_NUM_AC];
+    u8 arAcStreamPriMap[WMM_NUM_AC];
+    u8 arHiAcStreamActivePri;
+    u8 arEp2AcMapping[ENDPOINT_MAX];
     HTC_ENDPOINT_ID         arControlEp;
 #ifdef HTC_RAW_INTERFACE
     AR_RAW_HTC_T            *arRawHtc;
 #endif
-    A_BOOL                  arNetQueueStopped;
-    A_BOOL                  arRawIfInit;
+    bool                  arNetQueueStopped;
+    bool                  arRawIfInit;
     int                     arDeviceIndex;
-    COMMON_CREDIT_STATE_INFO arCreditStateInfo;
-    A_BOOL                  arWMIControlEpFull;
-    A_BOOL                  dbgLogFetchInProgress;
-    A_UCHAR                 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE];
-    A_UINT32                log_cnt;
-    A_UINT32                dbglog_init_done;
-    A_UINT32                arConnectCtrlFlags;
+    struct common_credit_state_info arCreditStateInfo;
+    bool                  arWMIControlEpFull;
+    bool                  dbgLogFetchInProgress;
+    u8                 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE];
+    u32 log_cnt;
+    u32 dbglog_init_done;
+    u32 arConnectCtrlFlags;
 #ifdef USER_KEYS
-    A_INT32                 user_savedkeys_stat;
-    A_UINT32                user_key_ctrl;
+    s32 user_savedkeys_stat;
+    u32 user_key_ctrl;
     struct USER_SAVEDKEYS   user_saved_keys;
 #endif
     USER_RSSI_THOLD rssi_map[12];
-    A_UINT8                arUserBssFilter;
-    A_UINT16                ap_profile_flag;    /* AP mode */
+    u8 arUserBssFilter;
+    u16 ap_profile_flag;    /* AP mode */
     WMI_AP_ACL              g_acl;              /* AP mode */
     sta_t                   sta_list[AP_MAX_NUM_STA]; /* AP mode */
-    A_UINT8                 sta_list_index;     /* AP mode */
+    u8 sta_list_index;     /* AP mode */
     struct ieee80211req_key ap_mode_bkey;           /* AP mode */
     A_NETBUF_QUEUE_T        mcastpsq;    /* power save q for Mcast frames */
     A_MUTEX_T               mcastpsqLock;
-    A_BOOL                  DTIMExpired; /* flag to indicate DTIM expired */
-    A_UINT8                 intra_bss;   /* enable/disable intra bss data forward */
+    bool                  DTIMExpired; /* flag to indicate DTIM expired */
+    u8 intra_bss;   /* enable/disable intra bss data forward */
     void                    *aggr_cntxt;
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
     void                    *hcidev_info;
 #endif
     void                    *hcipal_info;
     WMI_AP_MODE_STAT        arAPStats;
-    A_UINT8                 ap_hidden_ssid;
-    A_UINT8                 ap_country_code[3];
-    A_UINT8                 ap_wmode;
-    A_UINT8                 ap_dtim_period;
-    A_UINT16                ap_beacon_interval;
-    A_UINT16                arRTS;
-    A_UINT16                arACS; /* AP mode - Auto Channel Selection */
-    HTC_PACKET_QUEUE        amsdu_rx_buffer_queue;
-    A_BOOL                  bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */
+    u8 ap_hidden_ssid;
+    u8 ap_country_code[3];
+    u8 ap_wmode;
+    u8 ap_dtim_period;
+    u16 ap_beacon_interval;
+    u16 arRTS;
+    u16 arACS; /* AP mode - Auto Channel Selection */
+    struct htc_packet_queue        amsdu_rx_buffer_queue;
+    bool                  bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */
     A_TIMER                 disconnect_timer;
-    A_UINT8		    rxMetaVersion;
+    u8 rxMetaVersion;
 #ifdef WAPI_ENABLE
-    A_UINT8                 arWapiEnable;
+    u8 arWapiEnable;
 #endif
 	WMI_BTCOEX_CONFIG_EVENT arBtcoexConfig;
 	WMI_BTCOEX_STATS_EVENT  arBtcoexStats;
-    A_INT32                 (*exitCallback)(void *config);  /* generic callback at AR6K exit */
-    HIF_DEVICE_OS_DEVICE_INFO   osDevInfo;
+    s32 (*exitCallback)(void *config);  /* generic callback at AR6K exit */
+    struct hif_device_os_device_info   osDevInfo;
 #ifdef ATH6K_CONFIG_CFG80211
     struct wireless_dev *wdev;
     struct cfg80211_scan_request    *scan_request;
     struct ar_key   keys[WMI_MAX_KEY_INDEX + 1];
+    u32 smeState;
 #endif /* ATH6K_CONFIG_CFG80211 */
-    A_UINT16                arWlanPowerState;
-    A_BOOL                  arWlanOff;
+    u16 arWlanPowerState;
+    bool                  arWlanOff;
 #ifdef CONFIG_PM
-    A_UINT16                arWowState;
-    A_BOOL                  arBTOff;
-    A_BOOL                  arBTSharing;
-    A_UINT16                arSuspendConfig;
-    A_UINT16                arWlanOffConfig;
-    A_UINT16                arWow2Config;
+    u16 arWowState;
+    bool                  arBTOff;
+    bool                  arBTSharing;
+    u16 arSuspendConfig;
+    u16 arWlanOffConfig;
+    u16 arWow2Config;
 #endif
-    A_UINT8                 scan_triggered;
+    u8 scan_triggered;
     WMI_SCAN_PARAMS_CMD     scParams;
 #define AR_MCAST_FILTER_MAC_ADDR_SIZE  4
-    A_UINT8                 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE];
-    A_UINT8                 bdaddr[6];
-    A_BOOL                  scanSpecificSsid;
+    u8 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE];
+    u8 bdaddr[6];
+    bool                  scanSpecificSsid;
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
     void                    *arApDev;
 #endif
-} AR_SOFTC_T;
+};
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-typedef struct {
+struct ar_virtual_interface {
     struct net_device       *arNetDev;    /* net_device pointer */
-    AR_SOFTC_T              *arDev;       /* ar device pointer */
+    struct ar6_softc              *arDev;       /* ar device pointer */
     struct net_device       *arStaNetDev; /* net_device pointer */
-} AR_VIRTUAL_INTERFACE_T;
+};
 #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
 #ifdef ATH6K_CONFIG_CFG80211
@@ -638,7 +645,7 @@ static inline void *ar6k_priv(struct net_device *dev)
 
     if (arApNetDev == dev) {
         /* return arDev saved in virtual interface context */
-        AR_VIRTUAL_INTERFACE_T *arVirDev;
+        struct ar_virtual_interface *arVirDev;
         arVirDev = netdev_priv(dev);
         return arVirDev->arDev;   
     } else {
@@ -672,9 +679,9 @@ static inline void *ar6k_priv(struct net_device *dev)
 #define arEndpoint2RawStreamID(ar,ep)           (ar)->arRawHtc->arEp2RawMapping[(ep)]
 
 struct ar_giwscan_param {
-    char    *current_ev;
-    char    *end_buf;
-    A_UINT32 bytes_needed;
+    char *current_ev;
+    char *end_buf;
+    u32 bytes_needed;
     struct iw_request_info *info;
 };
 
@@ -697,14 +704,14 @@ struct ar_giwscan_param {
 int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int ar6000_ioctl_dispatcher(struct net_device *dev, struct ifreq *rq, int cmd);
 void ar6000_gpio_init(void);
-void ar6000_init_profile_info(AR_SOFTC_T *ar);
-void ar6000_install_static_wep_keys(AR_SOFTC_T *ar);
+void ar6000_init_profile_info(struct ar6_softc *ar);
+void ar6000_install_static_wep_keys(struct ar6_softc *ar);
 int ar6000_init(struct net_device *dev);
-int ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar);
-void ar6000_TxDataCleanup(AR_SOFTC_T *ar);
+int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
+void ar6000_TxDataCleanup(struct ar6_softc *ar);
 int ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev);
 void ar6000_restart_endpoint(struct net_device *dev);
-void ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglogs);
+void ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs);
 
 #ifdef HTC_RAW_INTERFACE
 
@@ -712,12 +719,12 @@ void ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL get
 #define __user
 #endif
 
-int ar6000_htc_raw_open(AR_SOFTC_T *ar);
-int ar6000_htc_raw_close(AR_SOFTC_T *ar);
-ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar,
+int ar6000_htc_raw_open(struct ar6_softc *ar);
+int ar6000_htc_raw_close(struct ar6_softc *ar);
+ssize_t ar6000_htc_raw_read(struct ar6_softc *ar,
                             HTC_RAW_STREAM_ID StreamID,
                             char __user *buffer, size_t count);
-ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar,
+ssize_t ar6000_htc_raw_write(struct ar6_softc *ar,
                              HTC_RAW_STREAM_ID StreamID,
                              char __user *buffer, size_t count);
 
@@ -726,23 +733,22 @@ ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar,
 /* AP mode */
 /*TODO: These routines should be moved to a file that is common across OS */
 sta_t *
-ieee80211_find_conn(AR_SOFTC_T *ar, A_UINT8 *node_addr);
+ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr);
 
 sta_t *
-ieee80211_find_conn_for_aid(AR_SOFTC_T *ar, A_UINT8 aid);
+ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid);
 
-A_UINT8
-remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason);
+u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason);
 
 /* HCI support */
 
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar);
-void     ar6000_cleanup_hci(AR_SOFTC_T *ar);
-void     ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig);
+int ar6000_setup_hci(struct ar6_softc *ar);
+void     ar6000_cleanup_hci(struct ar6_softc *ar);
+void     ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig);
 
 /* HCI bridge testing */
-A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb);
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb);
 #endif
 
 ATH_DEBUG_DECLARE_EXTERN(htc);
@@ -752,8 +758,8 @@ ATH_DEBUG_DECLARE_EXTERN(hif);
 ATH_DEBUG_DECLARE_EXTERN(wlan);
 ATH_DEBUG_DECLARE_EXTERN(misc);
 
-extern A_UINT8 bcast_mac[];
-extern A_UINT8 null_mac[];
+extern u8 bcast_mac[];
+extern u8 null_mac[];
 
 #ifdef __cplusplus
 }
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h b/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h
index a9a29a6..39e0873 100644
--- a/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h
+++ b/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h
@@ -21,12 +21,12 @@
 //==============================================================================
 #ifndef _AR6K_PAL_H_
 #define _AR6K_PAL_H_
-#define HCI_GET_OP_CODE(p)          (((A_UINT16)((p)[1])) << 8) | ((A_UINT16)((p)[0]))
+#define HCI_GET_OP_CODE(p)          (((u16)((p)[1])) << 8) | ((u16)((p)[0]))
 
 /* transmit packet reserve offset */
 #define TX_PACKET_RSV_OFFSET        32
 /* pal specific config structure */
-typedef A_BOOL (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb);
+typedef bool (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb);
 typedef struct ar6k_pal_config_s
 {
 	ar6k_pal_recv_pkt_t fpar6k_pal_recv_pkt;
diff --git a/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h b/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h
index ea2d181..1acfb9c 100644
--- a/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h
@@ -29,37 +29,37 @@ extern "C" {
 
 struct ar6_softc;
 
-void ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap,
-                        A_UINT32 sw_ver, A_UINT32 abi_ver);
-A_STATUS ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid);
-void ar6000_connect_event(struct ar6_softc *ar, A_UINT16 channel,
-                          A_UINT8 *bssid, A_UINT16 listenInterval,
-                          A_UINT16 beaconInterval, NETWORK_TYPE networkType,
-                          A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
-                          A_UINT8 assocRespLen,A_UINT8 *assocInfo);
-void ar6000_disconnect_event(struct ar6_softc *ar, A_UINT8 reason,
-                             A_UINT8 *bssid, A_UINT8 assocRespLen,
-                             A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus);
-void ar6000_tkip_micerr_event(struct ar6_softc *ar, A_UINT8 keyid,
-                              A_BOOL ismcast);
-void ar6000_bitrate_rx(void *devt, A_INT32 rateKbps);
-void ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList);
-void ar6000_regDomain_event(struct ar6_softc *ar, A_UINT32 regCode);
-void ar6000_txPwr_rx(void *devt, A_UINT8 txPwr);
-void ar6000_keepalive_rx(void *devt, A_UINT8 configured);
+void ar6000_ready_event(void *devt, u8 *datap, u8 phyCap,
+                        u32 sw_ver, u32 abi_ver);
+int ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid);
+void ar6000_connect_event(struct ar6_softc *ar, u16 channel,
+                          u8 *bssid, u16 listenInterval,
+                          u16 beaconInterval, NETWORK_TYPE networkType,
+                          u8 beaconIeLen, u8 assocReqLen,
+                          u8 assocRespLen,u8 *assocInfo);
+void ar6000_disconnect_event(struct ar6_softc *ar, u8 reason,
+                             u8 *bssid, u8 assocRespLen,
+                             u8 *assocInfo, u16 protocolReasonStatus);
+void ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid,
+                              bool ismcast);
+void ar6000_bitrate_rx(void *devt, s32 rateKbps);
+void ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList);
+void ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode);
+void ar6000_txPwr_rx(void *devt, u8 txPwr);
+void ar6000_keepalive_rx(void *devt, u8 configured);
 void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps,
                                  WMI_NEIGHBOR_INFO *info);
-void ar6000_set_numdataendpts(struct ar6_softc *ar, A_UINT32 num);
-void ar6000_scanComplete_event(struct ar6_softc *ar, A_STATUS status);
-void ar6000_targetStats_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len);
+void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num);
+void ar6000_scanComplete_event(struct ar6_softc *ar, int status);
+void ar6000_targetStats_event(struct ar6_softc *ar,  u8 *ptr, u32 len);
 void ar6000_rssiThreshold_event(struct ar6_softc *ar,
                                 WMI_RSSI_THRESHOLD_VAL newThreshold,
-                                A_INT16 rssi);
+                                s16 rssi);
 void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal);
-void ar6000_cac_event(struct ar6_softc *ar, A_UINT8 ac, A_UINT8 cac_indication,
-                                A_UINT8 statusCode, A_UINT8 *tspecSuggestion);
-void ar6000_channel_change_event(struct ar6_softc *ar, A_UINT16 oldChannel, A_UINT16 newChannel);
-void ar6000_hbChallengeResp_event(struct ar6_softc *, A_UINT32 cookie, A_UINT32 source);
+void ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cac_indication,
+                                u8 statusCode, u8 *tspecSuggestion);
+void ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, u16 newChannel);
+void ar6000_hbChallengeResp_event(struct ar6_softc *, u32 cookie, u32 source);
 void
 ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl);
 
@@ -67,96 +67,96 @@ void
 ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p);
 
 void
-ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters,
+ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters,
                       WMI_GET_WOW_LIST_REPLY *wow_reply);
 
-void ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID,
-                             WMI_PMKID *pmkidList, A_UINT8 *bssidList);
+void ar6000_pmkid_list_event(void *devt, u8 numPMKID,
+                             WMI_PMKID *pmkidList, u8 *bssidList);
 
-void ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values);
-void ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value);
+void ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values);
+void ar6000_gpio_data_rx(u32 reg_id, u32 value);
 void ar6000_gpio_ack_rx(void);
 
-A_INT32 rssi_compensation_calc_tcmd(A_UINT32 freq, A_INT32 rssi, A_UINT32 totalPkt);
-A_INT16 rssi_compensation_calc(struct ar6_softc *ar, A_INT16 rssi);
-A_INT16 rssi_compensation_reverse_calc(struct ar6_softc *ar, A_INT16 rssi, A_BOOL Above);
+s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt);
+s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi);
+s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above);
 
 void ar6000_dbglog_init_done(struct ar6_softc *ar);
 
 #ifdef SEND_EVENT_TO_APP
-void ar6000_send_event_to_app(struct ar6_softc *ar, A_UINT16 eventId, A_UINT8 *datap, int len);
-void ar6000_send_generic_event_to_app(struct ar6_softc *ar, A_UINT16 eventId, A_UINT8 *datap, int len);
+void ar6000_send_event_to_app(struct ar6_softc *ar, u16 eventId, u8 *datap, int len);
+void ar6000_send_generic_event_to_app(struct ar6_softc *ar, u16 eventId, u8 *datap, int len);
 #endif
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-void ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len);
+void ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len);
 #endif
 
 void ar6000_tx_retry_err_event(void *devt);
 
 void ar6000_snrThresholdEvent_rx(void *devt,
                                  WMI_SNR_THRESHOLD_VAL newThreshold,
-                                 A_UINT8 snr);
+                                 u8 snr);
 
-void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, A_UINT8 lqVal);
+void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, u8 lqVal);
 
 
-void ar6000_ratemask_rx(void *devt, A_UINT32 ratemask);
+void ar6000_ratemask_rx(void *devt, u32 ratemask);
 
-A_STATUS ar6000_get_driver_cfg(struct net_device *dev,
-                                A_UINT16 cfgParam,
+int ar6000_get_driver_cfg(struct net_device *dev,
+                                u16 cfgParam,
                                 void *result);
-void ar6000_bssInfo_event_rx(struct ar6_softc *ar, A_UINT8 *data, int len);
+void ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *data, int len);
 
-void ar6000_dbglog_event(struct ar6_softc *ar, A_UINT32 dropped,
-                         A_INT8 *buffer, A_UINT32 length);
+void ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
+                         s8 *buffer, u32 length);
 
 int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
 
-void ar6000_peer_event(void *devt, A_UINT8 eventCode, A_UINT8 *bssid);
+void ar6000_peer_event(void *devt, u8 eventCode, u8 *bssid);
 
-void ar6000_indicate_tx_activity(void *devt, A_UINT8 trafficClass, A_BOOL Active);
-HTC_ENDPOINT_ID  ar6000_ac2_endpoint_id ( void * devt, A_UINT8 ac);
-A_UINT8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep );
+void ar6000_indicate_tx_activity(void *devt, u8 trafficClass, bool Active);
+HTC_ENDPOINT_ID  ar6000_ac2_endpoint_id ( void * devt, u8 ac);
+u8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep );
 
-void ar6000_btcoex_config_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len);
+void ar6000_btcoex_config_event(struct ar6_softc *ar,  u8 *ptr, u32 len);
 
-void ar6000_btcoex_stats_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len) ;
+void ar6000_btcoex_stats_event(struct ar6_softc *ar,  u8 *ptr, u32 len) ;
 
 void ar6000_dset_open_req(void *devt,
-                          A_UINT32 id,
-                          A_UINT32 targ_handle,
-                          A_UINT32 targ_reply_fn,
-                          A_UINT32 targ_reply_arg);
-void ar6000_dset_close(void *devt, A_UINT32 access_cookie);
+                          u32 id,
+                          u32 targ_handle,
+                          u32 targ_reply_fn,
+                          u32 targ_reply_arg);
+void ar6000_dset_close(void *devt, u32 access_cookie);
 void ar6000_dset_data_req(void *devt,
-                          A_UINT32 access_cookie,
-                          A_UINT32 offset,
-                          A_UINT32 length,
-                          A_UINT32 targ_buf,
-                          A_UINT32 targ_reply_fn,
-                          A_UINT32 targ_reply_arg);
+                          u32 access_cookie,
+                          u32 offset,
+                          u32 length,
+                          u32 targ_buf,
+                          u32 targ_reply_fn,
+                          u32 targ_reply_arg);
 
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
 void prof_count_rx(unsigned int addr, unsigned int count);
 #endif
 
-A_UINT32 ar6000_getnodeAge (void);
+u32 ar6000_getnodeAge (void);
 
-A_UINT32 ar6000_getclkfreq (void);
+u32 ar6000_getclkfreq (void);
 
 int ar6000_ap_mode_profile_commit(struct ar6_softc *ar);
 
 struct ieee80211req_wpaie;
-A_STATUS
+int
 ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie);
 
-A_STATUS is_iwioctl_allowed(A_UINT8 mode, A_UINT16 cmd);
+int is_iwioctl_allowed(u8 mode, u16 cmd);
 
-A_STATUS is_xioctl_allowed(A_UINT8 mode, int cmd);
+int is_xioctl_allowed(u8 mode, int cmd);
 
-void ar6000_pspoll_event(struct ar6_softc *ar,A_UINT8 aid);
+void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid);
 
 void ar6000_dtimexpiry_event(struct ar6_softc *ar);
 
@@ -167,27 +167,28 @@ void ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd);
 
 #ifdef WAPI_ENABLE
 int ap_set_wapi_key(struct ar6_softc *ar, void *ik);
-void ap_wapi_rekey_event(struct ar6_softc *ar, A_UINT8 type, A_UINT8 *mac);
+void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac);
 #endif
 
-A_STATUS ar6000_connect_to_ap(struct ar6_softc *ar);
-A_STATUS ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BOOL suspending);
-A_STATUS ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state);
-A_STATUS ar6000_set_bt_hw_state(struct ar6_softc *ar, A_UINT32 state);
+int ar6000_connect_to_ap(struct ar6_softc *ar);
+int ar6000_disconnect(struct ar6_softc *ar);
+int ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool suspending);
+int ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state);
+int ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 state);
 
 #ifdef CONFIG_PM
-A_STATUS ar6000_suspend_ev(void *context);
-A_STATUS ar6000_resume_ev(void *context);
-A_STATUS ar6000_power_change_ev(void *context, A_UINT32 config);
-void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, A_BOOL isEvent);
+int ar6000_suspend_ev(void *context);
+int ar6000_resume_ev(void *context);
+int ar6000_power_change_ev(void *context, u32 config);
+void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent);
 #endif
 
 void ar6000_pm_init(void);
 void ar6000_pm_exit(void);
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-A_STATUS ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname);
-A_STATUS ar6000_remove_ap_interface(struct ar6_softc *ar);
+int ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname);
+int ar6000_remove_ap_interface(struct ar6_softc *ar);
 #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
 #ifdef __cplusplus
diff --git a/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h b/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h
index 53bbb48..66817c2 100644
--- a/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h
@@ -531,7 +531,7 @@ typedef enum {
  *   UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN)
  *   UINT8  scanType
  *   UINT8  scanConnected
- *   A_BOOL forceFgScan
+ *   u32 forceFgScan
  * uses: WMI_START_SCAN_CMDID
  */
 
@@ -625,7 +625,7 @@ typedef enum {
  * arguments:
  * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS)
  * UINT32 keyOpCtrl
- * uses AR6000_USER_SETKEYS_INFO
+ * uses struct ar6000_user_setkeys_info
  */
 #define AR6000_XIOCTL_USER_SETKEYS                      58
 #endif /* USER_KEYS */
@@ -643,7 +643,7 @@ typedef enum {
  * arguments:
  *   UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE)
  *   UINT8 keepaliveInterval
- *   A_BOOL configured
+ *   u32 configured
  * uses: WMI_GET_KEEPALIVE_CMDID
  */
 
@@ -660,7 +660,7 @@ typedef enum {
  *         UINT32 number of bytes
  *         UINT32 activate? (0 or 1)
  *       }
- *       A_UINT32 resulting rompatch ID
+ *       u32 resulting rompatch ID
  *     }
  * uses: BMI_ROMPATCH_INSTALL
  */
@@ -710,7 +710,7 @@ typedef enum {
 #define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER    66
 /*
  * arguments:
- *      A_UINT32 filter_type;
+ *      u32 filter_type;
  */
 
 #define AR6000_XIOCTL_DBGLOG_CFG_MODULE             67
@@ -720,15 +720,15 @@ typedef enum {
 #define AR6000_XIOCTL_WMI_SET_WSC_STATUS            70
 /*
  * arguments:
- *      A_UINT32 wsc_status;
+ *      u32 wsc_status;
  *            (WSC_REG_INACTIVE or WSC_REG_ACTIVE)
  */
 
 /*
  * arguments:
  *      struct {
- *          A_UINT8 streamType;
- *          A_UINT8 status;
+ *          u8 streamType;
+ *          u8 status;
  *      }
  * uses: WMI_SET_BT_STATUS_CMDID
  */
@@ -737,9 +737,9 @@ typedef enum {
 /*
  * arguments:
  *      struct {
- *           A_UINT8 paramType;
+ *           u8 paramType;
  *           union {
- *               A_UINT8 noSCOPkts;
+ *               u8 noSCOPkts;
  *               BT_PARAMS_A2DP a2dpParams;
  *               BT_COEX_REGS regs;
  *           };
@@ -760,8 +760,8 @@ typedef enum {
 /*
  * arguments:
  *   UINT32 cmd (AR6000_XIOCTL_TARGET_INFO)
- *   A_UINT32 TargetVersion (returned)
- *   A_UINT32 TargetType    (returned)
+ *   u32 TargetVersion (returned)
+ *   u32 TargetType    (returned)
  * (See also bmi_msg.h target_ver and target_type)
  */
 
@@ -786,7 +786,7 @@ typedef enum {
  * This ioctl is used to set the connect control flags
  *
  * arguments:
- *      A_UINT32 connectCtrlFlags
+ *      u32 connectCtrlFlags
  */
 
 #define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS              82
@@ -798,7 +798,7 @@ typedef enum {
  *
  * arguments:
  *      struct {
- *          A_UINT32    akmpInfo;
+ *          u32 akmpInfo;
  *      }
  * uses: WMI_SET_AKMP_PARAMS_CMD
  */
@@ -814,7 +814,7 @@ typedef enum {
  *
  * arguments:
  *      struct {
- *          A_UINT32    numPMKID;
+ *          u32 numPMKID;
  *          WMI_PMKID   pmkidList[WMI_MAX_PMKID_CACHE];
  *      }
  * uses: WMI_SET_PMKIDLIST_CMD
@@ -850,14 +850,14 @@ typedef enum {
 #define AR6000_XIOCTL_PROF_CFG                      93
 /*
  * arguments:
- *   A_UINT32 period
- *   A_UINT32 nbins
+ *   u32 period
+ *   u32 nbins
  */
 
 #define AR6000_XIOCTL_PROF_ADDR_SET                 94
 /*
  * arguments:
- *   A_UINT32 Target address
+ *   u32 Target address
  */
 
 #define AR6000_XIOCTL_PROF_START                    95
@@ -997,91 +997,92 @@ typedef enum {
 
 #define AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM              154
 
+#define AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES     161
 
 /* used by AR6000_IOCTL_WMI_GETREV */
 struct ar6000_version {
-    A_UINT32        host_ver;
-    A_UINT32        target_ver;
-    A_UINT32        wlan_ver;
-    A_UINT32        abi_ver;
+    u32 host_ver;
+    u32 target_ver;
+    u32 wlan_ver;
+    u32 abi_ver;
 };
 
 /* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */
 struct ar6000_queuereq {
-    A_UINT8         trafficClass;
-    A_UINT16        activeTsids;
+    u8 trafficClass;
+    u16 activeTsids;
 };
 
 /* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */
 typedef struct targetStats_t {
-    A_UINT64    tx_packets;
-    A_UINT64    tx_bytes;
-    A_UINT64    tx_unicast_pkts;
-    A_UINT64    tx_unicast_bytes;
-    A_UINT64    tx_multicast_pkts;
-    A_UINT64    tx_multicast_bytes;
-    A_UINT64    tx_broadcast_pkts;
-    A_UINT64    tx_broadcast_bytes;
-    A_UINT64    tx_rts_success_cnt;
-    A_UINT64    tx_packet_per_ac[4];
-
-    A_UINT64    tx_errors;
-    A_UINT64    tx_failed_cnt;
-    A_UINT64    tx_retry_cnt;
-    A_UINT64    tx_mult_retry_cnt;
-    A_UINT64    tx_rts_fail_cnt;
-
-    A_UINT64    rx_packets;
-    A_UINT64    rx_bytes;
-    A_UINT64    rx_unicast_pkts;
-    A_UINT64    rx_unicast_bytes;
-    A_UINT64    rx_multicast_pkts;
-    A_UINT64    rx_multicast_bytes;
-    A_UINT64    rx_broadcast_pkts;
-    A_UINT64    rx_broadcast_bytes;
-    A_UINT64    rx_fragment_pkt;
-
-    A_UINT64    rx_errors;
-    A_UINT64    rx_crcerr;
-    A_UINT64    rx_key_cache_miss;
-    A_UINT64    rx_decrypt_err;
-    A_UINT64    rx_duplicate_frames;
-
-    A_UINT64    tkip_local_mic_failure;
-    A_UINT64    tkip_counter_measures_invoked;
-    A_UINT64    tkip_replays;
-    A_UINT64    tkip_format_errors;
-    A_UINT64    ccmp_format_errors;
-    A_UINT64    ccmp_replays;
-
-    A_UINT64    power_save_failure_cnt;
-
-    A_UINT64    cs_bmiss_cnt;
-    A_UINT64    cs_lowRssi_cnt;
-    A_UINT64    cs_connect_cnt;
-    A_UINT64    cs_disconnect_cnt;
-
-    A_INT32     tx_unicast_rate;
-    A_INT32     rx_unicast_rate;
-
-    A_UINT32    lq_val;
-
-    A_UINT32    wow_num_pkts_dropped;
-    A_UINT16    wow_num_events_discarded;
-
-    A_INT16     noise_floor_calibation;
-    A_INT16     cs_rssi;
-    A_INT16     cs_aveBeacon_rssi;
-    A_UINT8     cs_aveBeacon_snr;
-    A_UINT8     cs_lastRoam_msec;
-    A_UINT8     cs_snr;
-
-    A_UINT8     wow_num_host_pkt_wakeups;
-    A_UINT8     wow_num_host_event_wakeups;
-
-    A_UINT32   arp_received;
-    A_UINT32   arp_matched;
-    A_UINT32   arp_replied;
+    u64 tx_packets;
+    u64 tx_bytes;
+    u64 tx_unicast_pkts;
+    u64 tx_unicast_bytes;
+    u64 tx_multicast_pkts;
+    u64 tx_multicast_bytes;
+    u64 tx_broadcast_pkts;
+    u64 tx_broadcast_bytes;
+    u64 tx_rts_success_cnt;
+    u64 tx_packet_per_ac[4];
+
+    u64 tx_errors;
+    u64 tx_failed_cnt;
+    u64 tx_retry_cnt;
+    u64 tx_mult_retry_cnt;
+    u64 tx_rts_fail_cnt;
+
+    u64 rx_packets;
+    u64 rx_bytes;
+    u64 rx_unicast_pkts;
+    u64 rx_unicast_bytes;
+    u64 rx_multicast_pkts;
+    u64 rx_multicast_bytes;
+    u64 rx_broadcast_pkts;
+    u64 rx_broadcast_bytes;
+    u64 rx_fragment_pkt;
+
+    u64 rx_errors;
+    u64 rx_crcerr;
+    u64 rx_key_cache_miss;
+    u64 rx_decrypt_err;
+    u64 rx_duplicate_frames;
+
+    u64 tkip_local_mic_failure;
+    u64 tkip_counter_measures_invoked;
+    u64 tkip_replays;
+    u64 tkip_format_errors;
+    u64 ccmp_format_errors;
+    u64 ccmp_replays;
+
+    u64 power_save_failure_cnt;
+
+    u64 cs_bmiss_cnt;
+    u64 cs_lowRssi_cnt;
+    u64 cs_connect_cnt;
+    u64 cs_disconnect_cnt;
+
+    s32 tx_unicast_rate;
+    s32 rx_unicast_rate;
+
+    u32 lq_val;
+
+    u32 wow_num_pkts_dropped;
+    u16 wow_num_events_discarded;
+
+    s16 noise_floor_calibation;
+    s16 cs_rssi;
+    s16 cs_aveBeacon_rssi;
+    u8 cs_aveBeacon_snr;
+    u8 cs_lastRoam_msec;
+    u8 cs_snr;
+
+    u8 wow_num_host_pkt_wakeups;
+    u8 wow_num_host_event_wakeups;
+
+    u32 arp_received;
+    u32 arp_matched;
+    u32 arp_replied;
 }TARGET_STATS;
 
 typedef struct targetStats_cmd_t {
@@ -1097,70 +1098,69 @@ typedef struct targetStats_cmd_t {
 #define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL    1
 #define AR6000_USER_SETKEYS_RSC_UNCHANGED     0x00000002
 
-typedef struct {
-    A_UINT32  keyOpCtrl;  /* Bit Map of Key Mgmt Ctrl Flags */
-} AR6000_USER_SETKEYS_INFO;
-
+struct ar6000_user_setkeys_info {
+    u32 keyOpCtrl;  /* Bit Map of Key Mgmt Ctrl Flags */
+}; /* XXX: unused !? */
 
 /* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */
 struct ar6000_gpio_output_set_cmd_s {
-    A_UINT32 set_mask;
-    A_UINT32 clear_mask;
-    A_UINT32 enable_mask;
-    A_UINT32 disable_mask;
+    u32 set_mask;
+    u32 clear_mask;
+    u32 enable_mask;
+    u32 disable_mask;
 };
 
 /*
  * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET
  */
 struct ar6000_gpio_register_cmd_s {
-    A_UINT32 gpioreg_id;
-    A_UINT32 value;
+    u32 gpioreg_id;
+    u32 value;
 };
 
 /* used by AR6000_XIOCTL_GPIO_INTR_ACK */
 struct ar6000_gpio_intr_ack_cmd_s {
-    A_UINT32 ack_mask;
+    u32 ack_mask;
 };
 
 /* used by AR6000_XIOCTL_GPIO_INTR_WAIT */
 struct ar6000_gpio_intr_wait_cmd_s {
-    A_UINT32 intr_mask;
-    A_UINT32 input_values;
+    u32 intr_mask;
+    u32 input_values;
 };
 
 /* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */
 typedef struct ar6000_dbglog_module_config_s {
-    A_UINT32 valid;
-    A_UINT16 mmask;
-    A_UINT16 tsr;
-    A_BOOL   rep;
-    A_UINT16 size;
+    u32 valid;
+    u16 mmask;
+    u16 tsr;
+    u32   rep;
+    u16 size;
 } DBGLOG_MODULE_CONFIG;
 
 typedef struct user_rssi_thold_t {
-    A_INT16     tag;
-    A_INT16     rssi;
+    s16 tag;
+    s16 rssi;
 } USER_RSSI_THOLD;
 
 typedef struct user_rssi_params_t {
-    A_UINT8            weight;
-    A_UINT32           pollTime;
+    u8 weight;
+    u32 pollTime;
     USER_RSSI_THOLD    tholds[12];
 } USER_RSSI_PARAMS;
 
 typedef struct ar6000_get_btcoex_config_cmd_t{
-	A_UINT32 btProfileType;
-	A_UINT32 linkId;
+	u32 btProfileType;
+	u32 linkId;
  }AR6000_GET_BTCOEX_CONFIG_CMD;
 
 typedef struct ar6000_btcoex_config_t {
     AR6000_GET_BTCOEX_CONFIG_CMD  configCmd;
-    A_UINT32 * configEvent;
+    u32 *configEvent;
 } AR6000_BTCOEX_CONFIG;
 
 typedef struct ar6000_btcoex_stats_t {
-    A_UINT32 * statsEvent;
+    u32 *statsEvent;
  }AR6000_BTCOEX_STATS;
 /*
  * Host driver may have some config parameters. Typically, these
@@ -1183,14 +1183,14 @@ struct ar6000_diag_window_cmd_s {
 
 
 struct ar6000_traffic_activity_change {
-    A_UINT32    StreamID;   /* stream ID to indicate activity change */
-    A_UINT32    Active;     /* active (1) or inactive (0) */
+    u32 StreamID;   /* stream ID to indicate activity change */
+    u32 Active;     /* active (1) or inactive (0) */
 };
 
 /* Used with AR6000_XIOCTL_PROF_COUNT_GET */
 struct prof_count_s {
-    A_UINT32    addr;       /* bin start address */
-    A_UINT32    count;      /* hit count */
+    u32 addr;       /* bin start address */
+    u32 count;      /* hit count */
 };
 
 
@@ -1198,8 +1198,8 @@ struct prof_count_s {
 /*         AR6000_XIOCTL_MODULE_DEBUG_GET_MASK */
 /*         AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO */
 struct drv_debug_module_s {
-    A_CHAR      modulename[128];   /* name of module */
-    A_UINT32    mask;              /* new mask to set .. or .. current mask */
+    char modulename[128];   /* name of module */
+    u32 mask;              /* new mask to set .. or .. current mask */
 };
 
 
diff --git a/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h b/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h
index 9d9ecbb..8cb5632 100644
--- a/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h
@@ -44,9 +44,7 @@ typedef u_int16_t    A_UINT16;
 typedef u_int32_t    A_UINT32;
 typedef u_int64_t    A_UINT64;
 
-typedef int             A_BOOL;
 typedef char            A_CHAR;
-typedef unsigned char   A_UCHAR;
 typedef unsigned long   A_ATH_TIMER;
 
 
diff --git a/drivers/staging/ath6kl/os/linux/include/cfg80211.h b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
index b60e8ac..1a6ae97 100644
--- a/drivers/staging/ath6kl/os/linux/include/cfg80211.h
+++ b/drivers/staging/ath6kl/os/linux/include/cfg80211.h
@@ -25,21 +25,21 @@
 #define _AR6K_CFG80211_H_
 
 struct wireless_dev *ar6k_cfg80211_init(struct device *dev);
-void ar6k_cfg80211_deinit(AR_SOFTC_T *ar);
+void ar6k_cfg80211_deinit(struct ar6_softc *ar);
 
-void ar6k_cfg80211_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status);
+void ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status);
 
-void ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
-                                A_UINT8 *bssid, A_UINT16 listenInterval,
-                                A_UINT16 beaconInterval,NETWORK_TYPE networkType,
-                                A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
-                                A_UINT8 assocRespLen, A_UINT8 *assocInfo);
+void ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
+                                u8 *bssid, u16 listenInterval,
+                                u16 beaconInterval,NETWORK_TYPE networkType,
+                                u8 beaconIeLen, u8 assocReqLen,
+                                u8 assocRespLen, u8 *assocInfo);
 
-void ar6k_cfg80211_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason,
-                                    A_UINT8 *bssid, A_UINT8 assocRespLen,
-                                    A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus);
+void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
+                                    u8 *bssid, u8 assocRespLen,
+                                    u8 *assocInfo, u16 protocolReasonStatus);
 
-void ar6k_cfg80211_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast);
+void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast);
 
 #endif /* _AR6K_CFG80211_H_ */
 
diff --git a/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h b/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h
index c150680..74f9861 100644
--- a/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h
+++ b/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h
@@ -25,18 +25,18 @@
 #include "hci_transport_api.h"
 #include "common_drv.h"
 
-extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo);
 extern void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans);
-extern A_STATUS    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
-extern A_STATUS    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
+extern int    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
+extern int    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
 extern void        (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans);
-extern A_STATUS    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
-extern A_STATUS    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
-extern A_STATUS    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, 
-                                          HTC_PACKET           *pPacket,
+extern int    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
+extern int    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
+extern int    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans,
+                                          struct htc_packet           *pPacket,
                                           int                  MaxPollMS);
-extern A_STATUS    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
-extern A_STATUS    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+extern int    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
+extern int    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
 
 #define HCI_TransportAttach(HTCHandle, pInfo)   \
@@ -61,11 +61,11 @@ extern A_STATUS    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTran
             _HCI_TransportEnablePowerMgmt((HciTrans), (Enable))
 
 
-extern A_STATUS ar6000_register_hci_transport(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks);
+extern int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks);
 
-extern A_STATUS ar6000_get_hif_dev(HIF_DEVICE *device, void *config);
+extern int ar6000_get_hif_dev(struct hif_device *device, void *config);
 
-extern A_STATUS ar6000_set_uart_config(HIF_DEVICE *hifDevice, A_UINT32 scale, A_UINT32 step);
+extern int ar6000_set_uart_config(struct hif_device *hifDevice, u32 scale, u32 step);
 
 /* get core clock register settings
  * data: 0 - 40/44MHz
@@ -73,4 +73,4 @@ extern A_STATUS ar6000_set_uart_config(HIF_DEVICE *hifDevice, A_UINT32 scale, A_
  *       where (5G band/2.4G band)
  * assume 2.4G band for now
  */
-extern A_STATUS ar6000_get_core_clock_config(HIF_DEVICE *hifDevice, A_UINT32 *data);
+extern int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data);
diff --git a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
index fce6ceb..53b500c 100644
--- a/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
@@ -76,9 +76,7 @@
 #define A_CPU2BE16(x)      htons(x)
 #define A_CPU2BE32(x)      htonl(x)
 
-#define A_MEMCPY(dst, src, len)         memcpy((A_UINT8 *)(dst), (src), (len))
 #define A_MEMZERO(addr, len)            memset(addr, 0, len)
-#define A_MEMCMP(addr1, addr2, len)     memcmp((addr1), (addr2), (len))
 #define A_MALLOC(size)                  kmalloc((size), GFP_KERNEL)
 #define A_MALLOC_NOWAIT(size)           kmalloc((size), GFP_ATOMIC)
 #define A_FREE(addr)                    kfree(addr)
@@ -116,12 +114,12 @@ typedef spinlock_t                      A_MUTEX_T;
 #define A_MUTEX_INIT(mutex)             spin_lock_init(mutex)
 #define A_MUTEX_LOCK(mutex)             spin_lock_bh(mutex)
 #define A_MUTEX_UNLOCK(mutex)           spin_unlock_bh(mutex)
-#define A_IS_MUTEX_VALID(mutex)         TRUE  /* okay to return true, since A_MUTEX_DELETE does nothing */
+#define A_IS_MUTEX_VALID(mutex)         true  /* okay to return true, since A_MUTEX_DELETE does nothing */
 #define A_MUTEX_DELETE(mutex)           /* spin locks are not kernel resources so nothing to free.. */
 
 /* Get current time in ms adding a constant offset (in ms) */
 #define A_GET_MS(offset)    \
-	(jiffies + ((offset) / 1000) * HZ)
+	(((jiffies / HZ) * 1000) + (offset))
 
 /*
  * Timer Functions
@@ -247,7 +245,7 @@ typedef struct sk_buff_head A_NETBUF_QUEUE_T;
 #define A_NETBUF_QUEUE_SIZE(q)  \
     a_netbuf_queue_size(q)
 #define A_NETBUF_QUEUE_EMPTY(q) \
-    a_netbuf_queue_empty(q)
+    (a_netbuf_queue_empty(q) ? true : false)
 
 /*
  * Network buffer support
@@ -306,17 +304,17 @@ void *a_netbuf_alloc(int size);
 void *a_netbuf_alloc_raw(int size);
 void a_netbuf_free(void *bufPtr);
 void *a_netbuf_to_data(void *bufPtr);
-A_UINT32 a_netbuf_to_len(void *bufPtr);
-A_STATUS a_netbuf_push(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len);
-A_STATUS a_netbuf_put(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len);
-A_STATUS a_netbuf_pull(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len);
-A_STATUS a_netbuf_trim(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len);
-A_STATUS a_netbuf_setlen(void *bufPtr, A_INT32 len);
-A_INT32 a_netbuf_headroom(void *bufPtr);
+u32 a_netbuf_to_len(void *bufPtr);
+int a_netbuf_push(void *bufPtr, s32 len);
+int a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len);
+int a_netbuf_put(void *bufPtr, s32 len);
+int a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len);
+int a_netbuf_pull(void *bufPtr, s32 len);
+int a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len);
+int a_netbuf_trim(void *bufPtr, s32 len);
+int a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len);
+int a_netbuf_setlen(void *bufPtr, s32 len);
+s32 a_netbuf_headroom(void *bufPtr);
 void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt);
 void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt);
 void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q);
@@ -328,8 +326,8 @@ void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q);
 /*
  * Kernel v.s User space functions
  */
-A_UINT32 a_copy_to_user(void *to, const void *from, A_UINT32 n);
-A_UINT32 a_copy_from_user(void *to, const void *from, A_UINT32 n);
+u32 a_copy_to_user(void *to, const void *from, u32 n);
+u32 a_copy_from_user(void *to, const void *from, u32 n);
 
 /* In linux, WLAN Rx and Tx run in different contexts, so no need to check
  * for any commands/data queued for WLAN */
@@ -364,9 +362,7 @@ static inline void *A_ALIGN_TO_CACHE_LINE(void *ptr) {
 #define PREPACK
 #define POSTPACK                __ATTRIB_PACK
 
-#define A_MEMCPY(dst, src, len)         memcpy((dst), (src), (len))
 #define A_MEMZERO(addr, len)            memset((addr), 0, (len))
-#define A_MEMCMP(addr1, addr2, len)     memcmp((addr1), (addr2), (len))
 #define A_MALLOC(size)                  malloc(size)
 #define A_FREE(addr)                    free(addr)
 
diff --git a/drivers/staging/ath6kl/os/linux/include/wlan_config.h b/drivers/staging/ath6kl/os/linux/include/wlan_config.h
index f7d0487..2de5cef 100644
--- a/drivers/staging/ath6kl/os/linux/include/wlan_config.h
+++ b/drivers/staging/ath6kl/os/linux/include/wlan_config.h
@@ -103,6 +103,13 @@
 #define WLAN_CONFIG_PM_WOW2                 0
 
 /*
+ * This configuration item enables/disables transmit bursting 
+ * 0 - Enable tx Bursting (default)
+ * 1 - Disable tx bursting 
+ */
+#define WLAN_CONFIG_DISABLE_TX_BURSTING     0
+
+/*
  * Platform specific function to power ON/OFF AR6000 
  * and enable/disable SDIO card detection
  */
diff --git a/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h b/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h
index 77e4ec6..d172625 100644
--- a/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h
+++ b/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h
@@ -41,7 +41,7 @@
  * (0xFF) - Allow this cmd always irrespective of mode
  */
 
-A_UINT8 sioctl_filter[] = {
+u8 sioctl_filter[] = {
 (AP_NETWORK),                                   /* SIOCSIWCOMMIT   0x8B00   */
 (0xFF),                                         /* SIOCGIWNAME     0x8B01   */
 (0),                                            /* SIOCSIWNWID     0x8B02   */
@@ -96,7 +96,7 @@ A_UINT8 sioctl_filter[] = {
 
 
 
-A_UINT8 pioctl_filter[] = {
+u8 pioctl_filter[] = {
 (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK),   /* IEEE80211_IOCTL_SETPARAM             (SIOCIWFIRSTPRIV+0)     */
 (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK),   /* IEEE80211_IOCTL_SETKEY               (SIOCIWFIRSTPRIV+1)     */
 (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK),   /* IEEE80211_IOCTL_DELKEY               (SIOCIWFIRSTPRIV+2)     */
@@ -132,7 +132,7 @@ A_UINT8 pioctl_filter[] = {
 
 
 
-A_UINT8 xioctl_filter[] = {
+u8 xioctl_filter[] = {
 (0xFF),                                         /* Dummy                                           0    */
 (0xFF),                                         /* AR6000_XIOCTL_BMI_DONE                          1    */
 (0xFF),                                         /* AR6000_XIOCTL_BMI_READ_MEMORY                   2    */
@@ -288,6 +288,13 @@ A_UINT8 xioctl_filter[] = {
 (0xFF),                                         /* AR6000_XIOCTL_ADD_AP_INTERFACE                  152  */
 (0xFF),                                         /* AR6000_XIOCTL_REMOVE_AP_INTERFACE               153  */
 (0xFF),                                         /* AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM              154  */
+(INFRA_NETWORK | ADHOC_NETWORK),                /* AR6000_XIOCTL_WMI_SET_WPA_OFFLOAD_STATE         155  */
+(INFRA_NETWORK | ADHOC_NETWORK),                /* AR6000_XIOCTL_WMI_SET_PASSPHRASE                156  */
+(0xFF),
+(0xFF),
+(0xFF),
+(0xFF),
+(INFRA_NETWORK | ADHOC_NETWORK),                /* AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES     161  */
 };
 
 #endif /*_WMI_FILTER_LINUX_H_*/
diff --git a/drivers/staging/ath6kl/os/linux/ioctl.c b/drivers/staging/ath6kl/os/linux/ioctl.c
index d5f7ac0..0daa201 100644
--- a/drivers/staging/ath6kl/os/linux/ioctl.c
+++ b/drivers/staging/ath6kl/os/linux/ioctl.c
@@ -29,24 +29,23 @@
 #include "wlan_config.h"
 
 extern int enablerssicompensation;
-A_UINT32 tcmdRxFreq;
+u32 tcmdRxFreq;
 extern unsigned int wmitimeout;
 extern A_WAITQUEUE_HEAD arEvent;
 extern int tspecCompliance;
 extern int bmienable;
-extern int bypasswmi;
 extern int loghci;
 
 static int
 ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
-    if(wmi_get_roam_tbl_cmd(ar->arWmi) != A_OK) {
+    if(wmi_get_roam_tbl_cmd(ar->arWmi) != 0) {
         return -EIO;
     }
 
@@ -56,15 +55,15 @@ ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
 
     /* currently assume only roam times are required */
-    if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != A_OK) {
+    if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != 0) {
         return -EIO;
     }
 
@@ -75,11 +74,11 @@ ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_ROAM_CTRL_CMD cmd;
-    A_UINT8 size = sizeof(cmd);
+    u8 size = sizeof(cmd);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -98,7 +97,7 @@ ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
         return -EFAULT;
     }
 
-    if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != A_OK) {
+    if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != 0) {
         return -EIO;
     }
 
@@ -108,11 +107,11 @@ ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
 static int
 ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
-    A_UINT8 size = sizeof(cmd);
+    u8 size = sizeof(cmd);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -124,7 +123,7 @@ ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
         return -EFAULT;
     }
 
-    if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != A_OK) {
+    if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != 0) {
         return -EIO;
     }
 
@@ -134,14 +133,14 @@ ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
 static int
 ar6000_ioctl_set_qos_supp(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_QOS_SUPP_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -154,7 +153,7 @@ ar6000_ioctl_set_qos_supp(struct net_device *dev, struct ifreq *rq)
     ret = wmi_set_qos_supp_cmd(ar->arWmi, cmd.status);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -169,14 +168,14 @@ ar6000_ioctl_set_qos_supp(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_WMM_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -187,15 +186,15 @@ ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
     }
 
     if (cmd.status == WMI_WMM_ENABLED) {
-        ar->arWmmEnabled = TRUE;
+        ar->arWmmEnabled = true;
     } else {
-        ar->arWmmEnabled = FALSE;
+        ar->arWmmEnabled = false;
     }
 
     ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -210,14 +209,14 @@ ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_WMM_TXOP_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -230,7 +229,7 @@ ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
     ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -245,10 +244,10 @@ ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_STATUS ret = 0;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    int ret = 0;
 
-    if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == FALSE) {
+    if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -262,14 +261,14 @@ ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_country(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_AP_SET_COUNTRY_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -282,10 +281,10 @@ ar6000_ioctl_set_country(struct net_device *dev, struct ifreq *rq)
     ar->ap_profile_flag = 1; /* There is a change in profile */
 
     ret = wmi_set_country(ar->arWmi, cmd.countryCode);
-    A_MEMCPY(ar->ap_country_code, cmd.countryCode, 3);
+    memcpy(ar->ap_country_code, cmd.countryCode, 3);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -302,11 +301,11 @@ ar6000_ioctl_set_country(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWER_MODE_CMD power_mode;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -322,11 +321,11 @@ ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -344,7 +343,7 @@ ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
         cmdp = A_MALLOC(130);
         if (copy_from_user(cmdp, rq->ifr_data,
                            sizeof (*cmdp) +
-                           ((cmd.numChannels - 1) * sizeof(A_UINT16))))
+                           ((cmd.numChannels - 1) * sizeof(u16))))
         {
             kfree(cmdp);
             return -EFAULT;
@@ -362,7 +361,7 @@ ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
     if (!ret &&
         (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
                                    cmdp->numChannels, cmdp->channelList)
-         != A_OK))
+         != 0))
     {
         ret = -EIO;
     }
@@ -383,11 +382,11 @@ static int
 ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
 {
 
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -395,7 +394,7 @@ ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
         return -EFAULT;
     }
 
-    if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != A_OK ) {
+    if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != 0 ) {
         ret = -EIO;
     }
 
@@ -415,13 +414,13 @@ ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
     thold2.rssi = tmpThold.rssi;        \
 } while (0)
 
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
     USER_RSSI_PARAMS rssiParams;
-    A_INT32 i, j;
+    s32 i, j;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -431,7 +430,7 @@ ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
     cmd.weight = rssiParams.weight;
     cmd.pollTime = rssiParams.pollTime;
 
-    A_MEMCPY(ar->rssi_map, &rssiParams.tholds, sizeof(ar->rssi_map));
+    memcpy(ar->rssi_map, &rssiParams.tholds, sizeof(ar->rssi_map));
     /*
      *  only 6 elements, so use bubble sorting, in ascending order
      */
@@ -440,7 +439,7 @@ ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
             if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
                 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
             } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
-                return EFAULT;
+                return -EFAULT;
             }
         }
     }
@@ -449,7 +448,7 @@ ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
             if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
                 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
             } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
-                return EFAULT;
+                return -EFAULT;
             }
         }
     }
@@ -463,9 +462,9 @@ ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
 
     if (enablerssicompensation) {
         for (i = 0; i < 6; i++)
-            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, TRUE);
+            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, true);
         for (i = 6; i < 12; i++)
-            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, FALSE);
+            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, false);
     }
 
     cmd.thresholdAbove1_Val = ar->rssi_map[0].rssi;
@@ -481,7 +480,7 @@ ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
     cmd.thresholdBelow5_Val = ar->rssi_map[10].rssi;
     cmd.thresholdBelow6_Val = ar->rssi_map[11].rssi;
 
-    if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != A_OK ) {
+    if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != 0 ) {
         ret = -EIO;
     }
 
@@ -492,11 +491,11 @@ static int
 ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
 {
 
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -504,7 +503,7 @@ ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
         return -EFAULT;
     }
 
-    if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != A_OK ) {
+    if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != 0 ) {
         ret = -EIO;
     }
 
@@ -515,11 +514,11 @@ ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_PROBED_SSID_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -528,7 +527,7 @@ ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
     }
 
     if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
-                                  cmd.ssid) != A_OK)
+                                  cmd.ssid) != 0)
     {
         ret = -EIO;
     }
@@ -539,11 +538,11 @@ ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_ADD_BAD_AP_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -556,15 +555,15 @@ ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
         return -EIO;
     }
 
-    if (A_MEMCMP(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
+    if (memcmp(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
         /*
          * This is a delete badAP.
          */
-        if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != A_OK) {
+        if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != 0) {
             ret = -EIO;
         }
     } else {
-        if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != A_OK) {
+        if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != 0) {
             ret = -EIO;
         }
     }
@@ -575,11 +574,11 @@ ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_CREATE_PSTREAM_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -589,11 +588,11 @@ ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
     }
 
     ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
-    if (ret == A_OK)
+    if (ret == 0)
         ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -608,11 +607,11 @@ ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_DELETE_PSTREAM_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -623,7 +622,7 @@ ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
     ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -638,11 +637,11 @@ ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct ar6000_queuereq qreq;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -662,19 +661,19 @@ ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
 }
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-static A_STATUS
+static int
 ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
-                                 struct ifreq *rq, A_UINT8 *data, A_UINT32 len)
+                                 struct ifreq *rq, u8 *data, u32 len)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT32    buf[4+TCMD_MAX_RATES];
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u32 buf[4+TCMD_MAX_RATES];
     int ret = 0;
 
     if (ar->bIsDestroyProgress) {
         return -EBUSY;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -688,7 +687,7 @@ ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
     }
 
     ar->tcmdRxReport = 0;
-    if (wmi_test_cmd(ar->arWmi, data, len) != A_OK) {
+    if (wmi_test_cmd(ar->arWmi, data, len) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
@@ -703,8 +702,8 @@ ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
     buf[1] = ar->tcmdRxRssi;
     buf[2] = ar->tcmdRxcrcErrPkt;
     buf[3] = ar->tcmdRxsecErrPkt;
-    A_MEMCPY(((A_UCHAR *)buf)+(4*sizeof(A_UINT32)), ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
-    A_MEMCPY(((A_UCHAR *)buf)+(4*sizeof(A_UINT32))+(TCMD_MAX_RATES *sizeof(A_UINT16)), ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
+    memcpy(((u8 *)buf)+(4*sizeof(u32)), ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
+    memcpy(((u8 *)buf)+(4*sizeof(u32))+(TCMD_MAX_RATES *sizeof(u16)), ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
 
     if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
         ret = -EFAULT;
@@ -716,9 +715,9 @@ ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
 }
 
 void
-ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
+ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
     TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
 
     if (enablerssicompensation) {
@@ -733,8 +732,8 @@ ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
     ar->tcmdRxReport = 1;
     A_MEMZERO(ar->tcmdRateCnt,  sizeof(ar->tcmdRateCnt));
     A_MEMZERO(ar->tcmdRateCntShortGuard,  sizeof(ar->tcmdRateCntShortGuard));
-    A_MEMCPY(ar->tcmdRateCnt, rx_rep->u.report.rateCnt, sizeof(ar->tcmdRateCnt));
-    A_MEMCPY(ar->tcmdRateCntShortGuard, rx_rep->u.report.rateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
+    memcpy(ar->tcmdRateCnt, rx_rep->u.report.rateCnt, sizeof(ar->tcmdRateCnt));
+    memcpy(ar->tcmdRateCntShortGuard, rx_rep->u.report.rateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
 
     wake_up(&arEvent);
 }
@@ -743,11 +742,11 @@ ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
 static int
 ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_TARGET_ERROR_REPORT_BITMASK cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -763,11 +762,11 @@ ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_clear_target_stats(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     TARGET_STATS *pStats = &ar->arTargetStats;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
        return -EIO;
     }
     AR6000_SPIN_LOCK(&ar->arLock, 0);
@@ -779,7 +778,7 @@ ar6000_clear_target_stats(struct net_device *dev)
 static int
 ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     TARGET_STATS_CMD cmd;
     TARGET_STATS *pStats = &ar->arTargetStats;
     int ret = 0;
@@ -787,7 +786,7 @@ ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
     if (ar->bIsDestroyProgress) {
         return -EBUSY;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
@@ -801,14 +800,14 @@ ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
         return -EBUSY;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+    if(wmi_get_stats_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
         ret = -EINTR;
@@ -830,21 +829,21 @@ ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_get_ap_stats(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT32 action; /* Allocating only the desired space on the frame. Declaring is as a WMI_AP_MODE_STAT variable results in exceeding the compiler imposed limit on the maximum frame size */
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u32 action; /* Allocating only the desired space on the frame. Declaring is as a WMI_AP_MODE_STAT variable results in exceeding the compiler imposed limit on the maximum frame size */
     WMI_AP_MODE_STAT *pStats = &ar->arAPStats;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
     if (copy_from_user(&action, (char *)((unsigned int*)rq->ifr_data + 1),
-                                sizeof(A_UINT32)))
+                                sizeof(u32)))
     {
         return -EFAULT;
     }
     if (action == AP_CLEAR_STATS) {
-        A_UINT8 i;
+        u8 i;
         AR6000_SPIN_LOCK(&ar->arLock, 0);
         for(i = 0; i < AP_MAX_NUM_STA; i++) {
             pStats->sta[i].tx_bytes = 0;
@@ -864,14 +863,14 @@ ar6000_ioctl_get_ap_stats(struct net_device *dev, struct ifreq *rq)
         return -ERESTARTSYS;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+    if(wmi_get_stats_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
         ret = -EINTR;
@@ -889,11 +888,11 @@ ar6000_ioctl_get_ap_stats(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_ACCESS_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -902,7 +901,7 @@ ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
     }
 
     if (wmi_set_access_params_cmd(ar->arWmi, cmd.ac, cmd.txop, cmd.eCWmin, cmd.eCWmax,
-                                  cmd.aifsn) == A_OK)
+                                  cmd.aifsn) == 0)
     {
         ret = 0;
     } else {
@@ -915,11 +914,11 @@ ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
 static int
 ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_DISC_TIMEOUT_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -927,7 +926,7 @@ ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
         return -EFAULT;
     }
 
-    if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == A_OK)
+    if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == 0)
     {
         ret = 0;
     } else {
@@ -938,13 +937,13 @@ ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
 }
 
 static int
-ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_VOICE_PKT_SIZE_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -952,7 +951,7 @@ ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
         return -EFAULT;
     }
 
-    if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == A_OK)
+    if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == 0)
     {
         ret = 0;
     } else {
@@ -964,13 +963,13 @@ ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
 }
 
 static int
-ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_max_sp_len(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_MAX_SP_LEN_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -978,7 +977,7 @@ ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
         return -EFAULT;
     }
 
-    if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == A_OK)
+    if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == 0)
     {
         ret = 0;
     } else {
@@ -990,13 +989,13 @@ ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
 
 
 static int
-ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_BT_STATUS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1004,7 +1003,7 @@ ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
         return -EFAULT;
     }
 
-    if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == A_OK)
+    if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == 0)
     {
         ret = 0;
     } else {
@@ -1015,13 +1014,13 @@ ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
 }
 
 static int
-ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_BT_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1029,7 +1028,7 @@ ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
         return -EFAULT;
     }
 
-    if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1040,20 +1039,20 @@ ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
 }
 
 static int
-ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_FE_ANT_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1064,13 +1063,13 @@ ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char * userdata)
 }
 
 static int
-ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1078,7 +1077,7 @@ ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char * us
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1089,13 +1088,13 @@ ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char * us
 }
 
 static int
-ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  char * userdata)
+ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1103,7 +1102,7 @@ ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  cha
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_btinquiry_page_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_btinquiry_page_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1114,13 +1113,13 @@ ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  cha
 }
 
 static int
-ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_SCO_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1128,7 +1127,7 @@ ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char * userdata
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_sco_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_sco_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1140,13 +1139,13 @@ ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char * userdata
 
 static int
 ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,
-														char * userdata)
+														char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_A2DP_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1154,7 +1153,7 @@ ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_a2dp_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_a2dp_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1165,13 +1164,13 @@ ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,
 }
 
 static int
-ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1179,7 +1178,7 @@ ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char * user
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_aclcoex_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_aclcoex_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1190,13 +1189,13 @@ ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char * user
 }
 
 static int
-ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char * userdata)
+ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_DEBUG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1204,7 +1203,7 @@ ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char * userdata)
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_debug_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_debug_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1215,13 +1214,13 @@ ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char * userdata)
 }
 
 static int
-ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char *userdata)
 {
-     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
      WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD cmd;
      int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
 	return -EIO;
     }
 
@@ -1229,7 +1228,7 @@ ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char *
 	return -EFAULT;
     }
 
-    if (wmi_set_btcoex_bt_operating_status_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_bt_operating_status_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1239,11 +1238,11 @@ ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char *
 }
 
 static int
-ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char * userdata,
+ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char *userdata,
 											struct ifreq *rq)
 {
 
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     AR6000_BTCOEX_CONFIG btcoexConfig;
     WMI_BTCOEX_CONFIG_EVENT *pbtcoexConfigEv = &ar->arBtcoexConfig;
 
@@ -1252,7 +1251,7 @@ ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char * userdata,
     if (ar->bIsDestroyProgress) {
             return -EBUSY;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
             return -EIO;
     }
 	if (copy_from_user(&btcoexConfig.configCmd, userdata, sizeof(AR6000_BTCOEX_CONFIG))) {
@@ -1262,15 +1261,15 @@ ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char * userdata,
         return -ERESTARTSYS;
     }
 
-    if (wmi_get_btcoex_config_cmd(ar->arWmi, (WMI_GET_BTCOEX_CONFIG_CMD *)&btcoexConfig.configCmd) != A_OK)
+    if (wmi_get_btcoex_config_cmd(ar->arWmi, (WMI_GET_BTCOEX_CONFIG_CMD *)&btcoexConfig.configCmd) != 0)
     {
     	up(&ar->arSem);
     	return -EIO;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
        ret = -EINTR;
@@ -1284,9 +1283,9 @@ ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char * userdata,
 }
 
 static int
-ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char * userdata, struct ifreq *rq)
+ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char *userdata, struct ifreq *rq)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     AR6000_BTCOEX_STATS btcoexStats;
     WMI_BTCOEX_STATS_EVENT *pbtcoexStats = &ar->arBtcoexStats;
     int ret = 0;
@@ -1294,7 +1293,7 @@ ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char * userdata, str
     if (ar->bIsDestroyProgress) {
             return -EBUSY;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
             return -EIO;
     }
 
@@ -1306,15 +1305,15 @@ ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char * userdata, str
 		return -EFAULT;
 	}
 
-    if (wmi_get_btcoex_stats_cmd(ar->arWmi) != A_OK)
+    if (wmi_get_btcoex_stats_cmd(ar->arWmi) != 0)
     {
     	up(&ar->arSem);
     	return -EIO;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
        ret = -EINTR;
@@ -1330,20 +1329,42 @@ ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char * userdata, str
 	return(ret);
 }
 
+static int
+ar6000_xioctl_set_excess_tx_retry_thres_cmd(struct net_device * dev, char * userdata)
+{
+    struct ar6_softc     *ar     = (struct ar6_softc *)ar6k_priv(dev);
+    WMI_SET_EXCESS_TX_RETRY_THRES_CMD cmd;
+    int ret = 0;
+
+    if (ar->arWmiReady == false) {
+        return -EIO;
+    }
+
+    if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
+        return -EFAULT;
+    }
+
+    if (wmi_set_excess_tx_retry_thres_cmd(ar->arWmi, &cmd) != 0)
+    {
+        ret = -EINVAL;
+    }
+    return(ret);
+}
+
 #ifdef CONFIG_HOST_GPIO_SUPPORT
 struct ar6000_gpio_intr_wait_cmd_s  gpio_intr_results;
 /* gpio_reg_results and gpio_data_available are protected by arSem */
 static struct ar6000_gpio_register_cmd_s gpio_reg_results;
-static A_BOOL gpio_data_available; /* Requested GPIO data available */
-static A_BOOL gpio_intr_available; /* GPIO interrupt info available */
-static A_BOOL gpio_ack_received;   /* GPIO ack was received */
+static bool gpio_data_available; /* Requested GPIO data available */
+static bool gpio_intr_available; /* GPIO interrupt info available */
+static bool gpio_ack_received;   /* GPIO ack was received */
 
 /* Host-side initialization for General Purpose I/O support */
 void ar6000_gpio_init(void)
 {
-    gpio_intr_available = FALSE;
-    gpio_data_available = FALSE;
-    gpio_ack_received   = FALSE;
+    gpio_intr_available = false;
+    gpio_data_available = false;
+    gpio_ack_received   = false;
 }
 
 /*
@@ -1352,11 +1373,11 @@ void ar6000_gpio_init(void)
  * input_values shows a recent value of GPIO pins.
  */
 void
-ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values)
+ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values)
 {
     gpio_intr_results.intr_mask = intr_mask;
     gpio_intr_results.input_values = input_values;
-    *((volatile A_BOOL *)&gpio_intr_available) = TRUE;
+    *((volatile bool *)&gpio_intr_available) = true;
     wake_up(&arEvent);
 }
 
@@ -1366,11 +1387,11 @@ ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values)
  * call.
  */
 void
-ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value)
+ar6000_gpio_data_rx(u32 reg_id, u32 value)
 {
     gpio_reg_results.gpioreg_id = reg_id;
     gpio_reg_results.value = value;
-    *((volatile A_BOOL *)&gpio_data_available) = TRUE;
+    *((volatile bool *)&gpio_data_available) = true;
     wake_up(&arEvent);
 }
 
@@ -1382,75 +1403,75 @@ ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value)
 void
 ar6000_gpio_ack_rx(void)
 {
-    gpio_ack_received = TRUE;
+    gpio_ack_received = true;
     wake_up(&arEvent);
 }
 
-A_STATUS
+int
 ar6000_gpio_output_set(struct net_device *dev,
-                       A_UINT32 set_mask,
-                       A_UINT32 clear_mask,
-                       A_UINT32 enable_mask,
-                       A_UINT32 disable_mask)
+                       u32 set_mask,
+                       u32 clear_mask,
+                       u32 enable_mask,
+                       u32 disable_mask)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    gpio_ack_received = FALSE;
+    gpio_ack_received = false;
     return wmi_gpio_output_set(ar->arWmi,
                 set_mask, clear_mask, enable_mask, disable_mask);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_input_get(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    *((volatile A_BOOL *)&gpio_data_available) = FALSE;
+    *((volatile bool *)&gpio_data_available) = false;
     return wmi_gpio_input_get(ar->arWmi);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_register_set(struct net_device *dev,
-                         A_UINT32 gpioreg_id,
-                         A_UINT32 value)
+                         u32 gpioreg_id,
+                         u32 value)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    gpio_ack_received = FALSE;
+    gpio_ack_received = false;
     return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_register_get(struct net_device *dev,
-                         A_UINT32 gpioreg_id)
+                         u32 gpioreg_id)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    *((volatile A_BOOL *)&gpio_data_available) = FALSE;
+    *((volatile bool *)&gpio_data_available) = false;
     return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_intr_ack(struct net_device *dev,
-                     A_UINT32 ack_mask)
+                     u32 ack_mask)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    gpio_intr_available = FALSE;
+    gpio_intr_available = false;
     return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
 }
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
 static struct prof_count_s prof_count_results;
-static A_BOOL prof_count_available; /* Requested GPIO data available */
+static bool prof_count_available; /* Requested GPIO data available */
 
-static A_STATUS
+static int
 prof_count_get(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    *((volatile A_BOOL *)&prof_count_available) = FALSE;
+    *((volatile bool *)&prof_count_available) = false;
     return wmi_prof_count_get_cmd(ar->arWmi);
 }
 
@@ -1459,24 +1480,24 @@ prof_count_get(struct net_device *dev)
  * for a previous prof_count_get call.
  */
 void
-prof_count_rx(A_UINT32 addr, A_UINT32 count)
+prof_count_rx(u32 addr, u32 count)
 {
     prof_count_results.addr = addr;
     prof_count_results.count = count;
-    *((volatile A_BOOL *)&prof_count_available) = TRUE;
+    *((volatile bool *)&prof_count_available) = true;
     wake_up(&arEvent);
 }
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 
 
-static A_STATUS
-ar6000_create_acl_data_osbuf(struct net_device *dev, A_UINT8 *userdata, void **p_osbuf)
+static int
+ar6000_create_acl_data_osbuf(struct net_device *dev, u8 *userdata, void **p_osbuf)
 {
     void *osbuf = NULL;
-    A_UINT8 tmp_space[8];
+    u8 tmp_space[8];
     HCI_ACL_DATA_PKT *acl;
-    A_UINT8 hdr_size, *datap=NULL;
-    A_STATUS ret = A_OK;
+    u8 hdr_size, *datap=NULL;
+    int ret = 0;
 
     /* ACL is in data path. There is a need to create pool
      * mechanism for allocating and freeing NETBUFs - ToDo later.
@@ -1498,18 +1519,18 @@ ar6000_create_acl_data_osbuf(struct net_device *dev, A_UINT8 *userdata, void **p
            break;
         }
         A_NETBUF_PUT(osbuf, hdr_size + acl->data_len);
-        datap = (A_UINT8 *)A_NETBUF_DATA(osbuf);
+        datap = (u8 *)A_NETBUF_DATA(osbuf);
 
         /* Real copy to osbuf */
         acl = (HCI_ACL_DATA_PKT *)(datap);
-        A_MEMCPY(acl, tmp_space, hdr_size);
+        memcpy(acl, tmp_space, hdr_size);
         if (a_copy_from_user(acl->data, userdata + hdr_size, acl->data_len)) {
             ret = A_EFAULT;
             break;
         }
-    } while(FALSE);
+    } while(false);
 
-    if (ret == A_OK) {
+    if (ret == 0) {
         *p_osbuf = osbuf;
     } else {
         A_NETBUF_FREE(osbuf);
@@ -1520,7 +1541,7 @@ ar6000_create_acl_data_osbuf(struct net_device *dev, A_UINT8 *userdata, void **p
 
 
 int
-ar6000_ioctl_ap_setparam(AR_SOFTC_T *ar, int param, int value)
+ar6000_ioctl_ap_setparam(struct ar6_softc *ar, int param, int value)
 {
     int ret=0;
 
@@ -1600,9 +1621,9 @@ ar6000_ioctl_ap_setparam(AR_SOFTC_T *ar, int param, int value)
 }
 
 int
-ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
+ar6000_ioctl_setparam(struct ar6_softc *ar, int param, int value)
 {
-    A_BOOL profChanged = FALSE;
+    bool profChanged = false;
     int ret=0;
 
     if(ar->arNextMode == AP_NETWORK) {
@@ -1623,15 +1644,15 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
             switch (value) {
                 case WPA_MODE_WPA1:
                     ar->arAuthMode = WPA_AUTH;
-                    profChanged    = TRUE;
+                    profChanged    = true;
                     break;
                 case WPA_MODE_WPA2:
                     ar->arAuthMode = WPA2_AUTH;
-                    profChanged    = TRUE;
+                    profChanged    = true;
                     break;
                 case WPA_MODE_NONE:
                     ar->arAuthMode = NONE_AUTH;
-                    profChanged    = TRUE;
+                    profChanged    = true;
                     break;
             }
             break;
@@ -1640,10 +1661,10 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
                 case IEEE80211_AUTH_WPA_PSK:
                     if (WPA_AUTH == ar->arAuthMode) {
                         ar->arAuthMode = WPA_PSK_AUTH;
-                        profChanged    = TRUE;
+                        profChanged    = true;
                     } else if (WPA2_AUTH == ar->arAuthMode) {
                         ar->arAuthMode = WPA2_PSK_AUTH;
-                        profChanged    = TRUE;
+                        profChanged    = true;
                     } else {
                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Error -  Setting PSK "\
                             "mode when WPA param was set to %d\n",
@@ -1666,19 +1687,19 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
             switch (value) {
                 case IEEE80211_CIPHER_AES_CCM:
                     ar->arPairwiseCrypto = AES_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
                 case IEEE80211_CIPHER_TKIP:
                     ar->arPairwiseCrypto = TKIP_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
                 case IEEE80211_CIPHER_WEP:
                     ar->arPairwiseCrypto = WEP_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
                 case IEEE80211_CIPHER_NONE:
                     ar->arPairwiseCrypto = NONE_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
             }
             break;
@@ -1693,19 +1714,19 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
             switch (value) {
                 case IEEE80211_CIPHER_AES_CCM:
                     ar->arGroupCrypto = AES_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
                 case IEEE80211_CIPHER_TKIP:
                     ar->arGroupCrypto = TKIP_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
                 case IEEE80211_CIPHER_WEP:
                     ar->arGroupCrypto = WEP_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
                 case IEEE80211_CIPHER_NONE:
                     ar->arGroupCrypto = NONE_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
             }
             break;
@@ -1717,7 +1738,7 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
             }
             break;
         case IEEE80211_PARAM_COUNTERMEASURES:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 return -EIO;
             }
             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
@@ -1725,7 +1746,7 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
         default:
             break;
     }
-    if ((ar->arNextMode != AP_NETWORK) && (profChanged == TRUE)) {
+    if ((ar->arNextMode != AP_NETWORK) && (profChanged == true)) {
         /*
          * profile has changed.  Erase ssid to signal change
          */
@@ -1736,20 +1757,20 @@ ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
 }
 
 int
-ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
+ar6000_ioctl_setkey(struct ar6_softc *ar, struct ieee80211req_key *ik)
 {
     KEY_USAGE keyUsage;
-    A_STATUS status;
+    int status;
     CRYPTO_TYPE keyType = NONE_CRYPT;
 
 #ifdef USER_KEYS
-    ar->user_saved_keys.keyOk = FALSE;
+    ar->user_saved_keys.keyOk = false;
 #endif
     if ( (0 == memcmp(ik->ik_macaddr, null_mac, IEEE80211_ADDR_LEN)) ||
          (0 == memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN)) ) {
         keyUsage = GROUP_USAGE;
         if(ar->arNextMode == AP_NETWORK) {
-            A_MEMCPY(&ar->ap_mode_bkey, ik,
+            memcpy(&ar->ap_mode_bkey, ik,
                      sizeof(struct ieee80211req_key));
 #ifdef WAPI_ENABLE
             if(ar->arPairwiseCrypto == WAPI_CRYPT) {
@@ -1758,13 +1779,13 @@ ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
 #endif
         }
 #ifdef USER_KEYS
-        A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik,
+        memcpy(&ar->user_saved_keys.bcast_ik, ik,
                  sizeof(struct ieee80211req_key));
 #endif
     } else {
         keyUsage = PAIRWISE_USAGE;
 #ifdef USER_KEYS
-        A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik,
+        memcpy(&ar->user_saved_keys.ucast_ik, ik,
                  sizeof(struct ieee80211req_key));
 #endif
 #ifdef WAPI_ENABLE
@@ -1806,7 +1827,7 @@ ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
 
             A_MEMZERO(ar->arWepKeyList[index].arKey,
                             sizeof(ar->arWepKeyList[index].arKey));
-            A_MEMCPY(ar->arWepKeyList[index].arKey, ik->ik_keydata, ik->ik_keylen);
+            memcpy(ar->arWepKeyList[index].arKey, ik->ik_keydata, ik->ik_keylen);
             ar->arWepKeyList[index].arKeyLen = ik->ik_keylen;
 
             if(ik->ik_flags & IEEE80211_KEY_DEFAULT){
@@ -1823,11 +1844,11 @@ ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
         }
 
         status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
-                                ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
+                                ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
                                 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
                                 SYNC_BOTH_WMIFLAG);
 
-        if (status != A_OK) {
+        if (status) {
             return -EIO;
         }
     } else {
@@ -1835,7 +1856,7 @@ ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
     }
 
 #ifdef USER_KEYS
-    ar->user_saved_keys.keyOk = TRUE;
+    ar->user_saved_keys.keyOk = true;
 #endif
 
     return 0;
@@ -1843,14 +1864,14 @@ ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
 
 int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    HIF_DEVICE *hifDevice = ar->arHifDevice;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    struct hif_device *hifDevice = ar->arHifDevice;
     int ret = 0, param;
     unsigned int address = 0;
     unsigned int length = 0;
     unsigned char *buffer;
     char *userdata;
-    A_UINT32 connectCtrlFlags;
+    u32 connectCtrlFlags;
 
 
     WMI_SET_AKMP_PARAMS_CMD  akmpParams;
@@ -1879,13 +1900,13 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	    goto ioctl_done;
 	}
         userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
-        if(is_xioctl_allowed(ar->arNextMode, cmd) != A_OK) {
+        if(is_xioctl_allowed(ar->arNextMode, cmd) != 0) {
             A_PRINTF("xioctl: cmd=%d not allowed in this mode\n",cmd);
             ret = -EOPNOTSUPP;
             goto ioctl_done;
     }
     } else {
-        A_STATUS ret = is_iwioctl_allowed(ar->arNextMode, cmd);
+        int ret = is_iwioctl_allowed(ar->arNextMode, cmd);
         if(ret == A_ENOTSUP) {
             A_PRINTF("iwioctl: cmd=0x%x not allowed in this mode\n", cmd);
             ret = -EOPNOTSUPP;
@@ -1920,7 +1941,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             int param, value;
             int *ptr = (int *)rq->ifr_ifru.ifru_newname;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else {
                 param = *ptr++;
@@ -1932,7 +1953,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case IEEE80211_IOCTL_SETKEY:
         {
             struct ieee80211req_key keydata;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&keydata, userdata,
                             sizeof(struct ieee80211req_key))) {
@@ -1951,7 +1972,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case IEEE80211_IOCTL_SETMLME:
         {
             struct ieee80211req_mlme mlme;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&mlme, userdata,
                             sizeof(struct ieee80211req_mlme))) {
@@ -1989,12 +2010,12 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case IEEE80211_IOCTL_ADDPMKID:
         {
             struct ieee80211req_addpmkid  req;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&req, userdata, sizeof(struct ieee80211req_addpmkid))) {
                 ret = -EFAULT;
             } else {
-                A_STATUS status;
+                int status;
 
                 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
                     req.pi_bssid[0], req.pi_bssid[1], req.pi_bssid[2],
@@ -2004,7 +2025,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 status = wmi_setPmkid_cmd(ar->arWmi, req.pi_bssid, req.pi_pmkid,
                               req.pi_enable);
 
-                if (status != A_OK) {
+                if (status) {
                     ret = -EIO;
                     goto ioctl_done;
                 }
@@ -2028,7 +2049,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     ret = -EFAULT;
                     goto ioctl_done;
                 } else {
-                    wmi_test_cmd(ar->arWmi,(A_UINT8 *)&txCmd, sizeof(TCMD_CONT_TX));
+                    wmi_test_cmd(ar->arWmi,(u8 *)&txCmd, sizeof(TCMD_CONT_TX));
                 }
             }
             break;
@@ -2054,13 +2075,13 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     case TCMD_CONT_RX_FILTER:
                     case TCMD_CONT_RX_SETMAC:
                     case TCMD_CONT_RX_SET_ANT_SWITCH_TABLE:
-                         wmi_test_cmd(ar->arWmi,(A_UINT8 *)&rxCmd,
+                         wmi_test_cmd(ar->arWmi,(u8 *)&rxCmd,
                                                 sizeof(TCMD_CONT_RX));
                          tcmdRxFreq = rxCmd.u.para.freq;
                          break;
                     case TCMD_CONT_RX_REPORT:
                          ar6000_ioctl_tcmd_get_rx_report(dev, rq,
-                         (A_UINT8 *)&rxCmd, sizeof(TCMD_CONT_RX));
+                         (u8 *)&rxCmd, sizeof(TCMD_CONT_RX));
                          break;
                     default:
                          A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
@@ -2078,7 +2099,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     goto ioctl_done;
                 }
                 ar->tcmdPm = pmCmd.mode;
-                wmi_test_cmd(ar->arWmi, (A_UINT8*)&pmCmd, sizeof(TCMD_PM));
+                wmi_test_cmd(ar->arWmi, (u8 *)&pmCmd, sizeof(TCMD_PM));
             }
             break;
 #endif /* CONFIG_HOST_TCMD_SUPPORT */
@@ -2153,7 +2174,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 	    }
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Execute (address: 0x%x, param: %d)\n",
                              address, param));
-            ret = BMIExecute(hifDevice, address, (A_UINT32*)&param);
+            ret = BMIExecute(hifDevice, address, (u32 *)&param);
 	    /* return value */
 	    if (put_user(param, (unsigned int *)rq->ifr_data)) {
 		ret = -EFAULT;
@@ -2175,7 +2196,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		ret = -EFAULT;
 		break;
 	    }
-            ret = BMIReadSOCRegister(hifDevice, address, (A_UINT32*)&param);
+            ret = BMIReadSOCRegister(hifDevice, address, (u32 *)&param);
 	    /* return value */
 	    if (put_user(param, (unsigned int *)rq->ifr_data)) {
 		ret = -EFAULT;
@@ -2194,7 +2215,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 #ifdef HTC_RAW_INTERFACE
         case AR6000_XIOCTL_HTC_RAW_OPEN:
-            ret = A_OK;
+            ret = 0;
             if (!arRawIfEnabled(ar)) {
                 /* make sure block size is set in case the target was reset since last
                   * BMI phase (i.e. flashup downloads) */
@@ -2203,12 +2224,12 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                             0,  /* use default yield */
                                             0   /* use default number of HTC ctrl buffers */
                                             );
-                if (A_FAILED(ret)) {
+                if (ret) {
                     break;
                 }
                 /* Terminate the BMI phase */
                 ret = BMIDone(hifDevice);
-                if (ret == A_OK) {
+                if (ret == 0) {
                     ret = ar6000_htc_raw_open(ar);
                 }
             }
@@ -2217,7 +2238,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_HTC_RAW_CLOSE:
             if (arRawIfEnabled(ar)) {
                 ret = ar6000_htc_raw_close(ar);
-                arRawIfEnabled(ar) = FALSE;
+                arRawIfEnabled(ar) = false;
             } else {
                 ret = A_ERROR;
             }
@@ -2302,15 +2323,15 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         /* Configure Target-side profiling */
         case AR6000_XIOCTL_PROF_CFG:
         {
-            A_UINT32 period;
-            A_UINT32 nbins;
+            u32 period;
+            u32 nbins;
 	    if (get_user(period, (unsigned int *)userdata) ||
 		get_user(nbins, (unsigned int *)userdata + 1)) {
 		ret = -EFAULT;
 		break;
 	    }
 
-            if (wmi_prof_cfg_cmd(ar->arWmi, period, nbins) != A_OK) {
+            if (wmi_prof_cfg_cmd(ar->arWmi, period, nbins) != 0) {
                 ret = -EIO;
             }
 
@@ -2320,13 +2341,13 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         /* Start a profiling bucket/bin at the specified address */
         case AR6000_XIOCTL_PROF_ADDR_SET:
         {
-            A_UINT32 addr;
+            u32 addr;
 	    if (get_user(addr, (unsigned int *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
 
-            if (wmi_prof_addr_set_cmd(ar->arWmi, addr) != A_OK) {
+            if (wmi_prof_addr_set_cmd(ar->arWmi, addr) != 0) {
                 ret = -EIO;
             }
 
@@ -2348,7 +2369,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2362,9 +2383,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 goto ioctl_done;
             }
 
-            prof_count_available = FALSE;
+            prof_count_available = false;
             ret = prof_count_get(dev);
-            if (ret != A_OK) {
+            if (ret != 0) {
                 up(&ar->arSem);
                 ret = -EIO;
                 goto ioctl_done;
@@ -2399,7 +2420,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_POWER_MODE_CMD pwrModeCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&pwrModeCmd, userdata,
                                    sizeof(pwrModeCmd)))
@@ -2407,7 +2428,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
-                       != A_OK)
+                       != 0)
                 {
                     ret = -EIO;
                 }
@@ -2418,7 +2439,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&ibssPmCaps, userdata,
                                    sizeof(ibssPmCaps)))
@@ -2426,7 +2447,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
-                    ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != A_OK)
+                    ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2440,7 +2461,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_AP_PS_CMD apPsCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&apPsCmd, userdata,
                                    sizeof(apPsCmd)))
@@ -2448,7 +2469,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_apps_cmd(ar->arWmi, apPsCmd.psType, apPsCmd.idle_time,
-                    apPsCmd.ps_period, apPsCmd.sleep_period) != A_OK)
+                    apPsCmd.ps_period, apPsCmd.sleep_period) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2459,7 +2480,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_POWER_PARAMS_CMD pmParams;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&pmParams, userdata,
                                       sizeof(pmParams)))
@@ -2476,7 +2497,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 #else
                                      SEND_POWER_SAVE_FAIL_EVENT_ALWAYS
 #endif
-                                     ) != A_OK)
+                                     ) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2485,7 +2506,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_IOCTL_WMI_SETSCAN:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&ar->scParams, userdata,
                                       sizeof(ar->scParams)))
@@ -2493,9 +2514,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (CAN_SCAN_IN_CONNECT(ar->scParams.scanCtrlFlags)) {
-                    ar->arSkipScan = FALSE;
+                    ar->arSkipScan = false;
                 } else {
-                    ar->arSkipScan = TRUE;
+                    ar->arSkipScan = true;
                 }
 
                 if (wmi_scanparams_cmd(ar->arWmi, ar->scParams.fg_start_period,
@@ -2507,7 +2528,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                        ar->scParams.shortScanRatio,
                                        ar->scParams.scanCtrlFlags,
                                        ar->scParams.max_dfsch_act_time,
-                                       ar->scParams.maxact_scan_per_ssid) != A_OK)
+                                       ar->scParams.maxact_scan_per_ssid) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2518,14 +2539,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_LISTEN_INT_CMD listenCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&listenCmd, userdata,
                                       sizeof(listenCmd)))
             {
                 ret = -EFAULT;
             } else {
-                    if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != A_OK) {
+                    if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != 0) {
                         ret = -EIO;
                     } else {
                         AR6000_SPIN_LOCK(&ar->arLock, 0);
@@ -2541,14 +2562,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_BMISS_TIME_CMD bmissCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&bmissCmd, userdata,
                                       sizeof(bmissCmd)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != A_OK) {
+                if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != 0) {
                     ret = -EIO;
                 }
             }
@@ -2558,7 +2579,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_BSS_FILTER_CMD filt;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&filt, userdata,
                                    sizeof(filt)))
@@ -2566,10 +2587,10 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_bssfilter_cmd(ar->arWmi, filt.bssFilter, filt.ieMask)
-                        != A_OK) {
+                        != 0) {
                     ret = -EIO;
                 } else {
-                    ar->arUserBssFilter = param;
+                    ar->arUserBssFilter = filt.bssFilter;
                 }
             }
             break;
@@ -2587,7 +2608,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_WMI_CLR_RSSISNR:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             }
             ret = wmi_clr_rssi_snr(ar->arWmi);
@@ -2602,7 +2623,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setLpreambleCmd, userdata,
                                    sizeof(setLpreambleCmd)))
@@ -2615,7 +2636,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 #else
                            WMI_IGNORE_BARKER_IN_ERP
 #endif
-                ) != A_OK)
+                ) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2626,7 +2647,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SET_RTS:
         {
             WMI_SET_RTS_CMD rtsCmd;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&rtsCmd, userdata,
                                    sizeof(rtsCmd)))
@@ -2635,7 +2656,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             } else {
                 ar->arRTS = rtsCmd.threshold;
                 if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
-                       != A_OK)
+                       != 0)
                 {
                     ret = -EIO;
                 }
@@ -2706,9 +2727,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
         {
             WMI_SET_ASSOC_INFO_CMD cmd;
-            A_UINT8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
+            u8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
 		break;
 	    }
@@ -2729,7 +2750,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		break;
 	    }
 	    if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
-				  cmd.bufferSize, assocInfo) != A_OK) {
+				  cmd.bufferSize, assocInfo) != 0) {
 		ret = -EIO;
 		break;
 	    }
@@ -2763,12 +2784,12 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             /* If we made it to here, then the Target exists and is ready. */
 
             if (cmd == AR6000_XIOCTL_TARGET_INFO) {
-                if (copy_to_user((A_UINT32 *)rq->ifr_data, &ar->arVersion.target_ver,
+                if (copy_to_user((u32 *)rq->ifr_data, &ar->arVersion.target_ver,
                                  sizeof(ar->arVersion.target_ver)))
                 {
                     ret = -EFAULT;
                 }
-                if (copy_to_user(((A_UINT32 *)rq->ifr_data)+1, &ar->arTargetType,
+                if (copy_to_user(((u32 *)rq->ifr_data)+1, &ar->arTargetType,
                                  sizeof(ar->arTargetType)))
                 {
                     ret = -EFAULT;
@@ -2804,7 +2825,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
         {
-            A_UINT32 cookie;
+            u32 cookie;
 
             if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
                 ret = -EFAULT;
@@ -2812,7 +2833,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             }
 
             /* Send the challenge on the control channel */
-            if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != A_OK) {
+            if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != 0) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2845,7 +2866,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2869,8 +2890,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                              gpio_output_set_cmd.clear_mask,
                                              gpio_output_set_cmd.enable_mask,
                                              gpio_output_set_cmd.disable_mask);
-                if (ret != A_OK) {
-                    ret = EIO;
+                if (ret != 0) {
+                    ret = -EIO;
                 }
             }
             up(&ar->arSem);
@@ -2882,7 +2903,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2897,7 +2918,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             }
 
             ret = ar6000_gpio_input_get(dev);
-            if (ret != A_OK) {
+            if (ret != 0) {
                 up(&ar->arSem);
                 ret = -EIO;
                 goto ioctl_done;
@@ -2927,7 +2948,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2949,8 +2970,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = ar6000_gpio_register_set(dev,
                                                gpio_register_cmd.gpioreg_id,
                                                gpio_register_cmd.value);
-                if (ret != A_OK) {
-                    ret = EIO;
+                if (ret != 0) {
+                    ret = -EIO;
                 }
 
                 /* Wait for acknowledgement from Target */
@@ -2970,7 +2991,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2990,7 +3011,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
-                if (ret != A_OK) {
+                if (ret != 0) {
                     up(&ar->arSem);
                     ret = -EIO;
                     goto ioctl_done;
@@ -3020,7 +3041,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -3040,8 +3061,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
-                if (ret != A_OK) {
-                    ret = EIO;
+                if (ret != 0) {
+                    ret = -EIO;
                 }
             }
             up(&ar->arSem);
@@ -3077,7 +3098,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             /* Send the challenge on the control channel */
             if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask,
                                             config.tsr, config.rep,
-                                            config.size, config.valid) != A_OK)
+                                            config.size, config.valid) != 0)
             {
                 ret = -EIO;
                 goto ioctl_done;
@@ -3088,7 +3109,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
         {
             /* Send the challenge on the control channel */
-            if (ar6000_dbglog_get_debug_logs(ar) != A_OK)
+            if (ar6000_dbglog_get_debug_logs(ar) != 0)
             {
                 ret = -EIO;
                 goto ioctl_done;
@@ -3100,19 +3121,19 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_ADHOC_BSSID_CMD adhocBssid;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&adhocBssid, userdata,
                                       sizeof(adhocBssid)))
             {
                 ret = -EFAULT;
-            } else if (A_MEMCMP(adhocBssid.bssid, bcast_mac,
+            } else if (memcmp(adhocBssid.bssid, bcast_mac,
                                 AR6000_ETH_ADDR_LEN) == 0)
             {
                 ret = -EFAULT;
             } else {
 
-                A_MEMCPY(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
+                memcpy(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
         }
             break;
         }
@@ -3120,9 +3141,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_SET_OPT_MODE:
         {
         WMI_SET_OPT_MODE_CMD optModeCmd;
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&optModeCmd, userdata,
                                       sizeof(optModeCmd)))
@@ -3132,7 +3153,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
 
             } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
-                       != A_OK)
+                       != 0)
             {
                 ret = -EIO;
             }
@@ -3141,36 +3162,43 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
         case AR6000_XIOCTL_OPT_SEND_FRAME:
         {
-        WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
-            A_UINT8 data[MAX_OPT_DATA_LEN];
+            WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
+            u8 data[MAX_OPT_DATA_LEN];
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
-            } else if (copy_from_user(&optTxFrmCmd, userdata,
-                                      sizeof(optTxFrmCmd)))
-            {
+                break;
+            }
+
+            if (copy_from_user(&optTxFrmCmd, userdata, sizeof(optTxFrmCmd))) {
                 ret = -EFAULT;
-            } else if (copy_from_user(data,
-                                      userdata+sizeof(WMI_OPT_TX_FRAME_CMD)-1,
-                                      optTxFrmCmd.optIEDataLen))
-            {
+                break;
+            }
+
+            if (optTxFrmCmd.optIEDataLen > MAX_OPT_DATA_LEN) {
+                ret = -EINVAL;
+                break;
+            }
+
+            if (copy_from_user(data, userdata+sizeof(WMI_OPT_TX_FRAME_CMD) - 1,
+                                   optTxFrmCmd.optIEDataLen)) {
                 ret = -EFAULT;
-            } else {
-                ret = wmi_opt_tx_frame_cmd(ar->arWmi,
+                break;
+            }
+
+            ret = wmi_opt_tx_frame_cmd(ar->arWmi,
                                            optTxFrmCmd.frmType,
                                            optTxFrmCmd.dstAddr,
                                            optTxFrmCmd.bssid,
                                            optTxFrmCmd.optIEDataLen,
                                            data);
-            }
-
             break;
         }
         case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
         {
             WMI_SET_RETRY_LIMITS_CMD setRetryParams;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setRetryParams, userdata,
                                       sizeof(setRetryParams)))
@@ -3180,7 +3208,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
                                           setRetryParams.trafficClass,
                                           setRetryParams.maxRetries,
-                                          setRetryParams.enableNotify) != A_OK)
+                                          setRetryParams.enableNotify) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3195,14 +3223,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_BEACON_INT_CMD bIntvlCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&bIntvlCmd, userdata,
                        sizeof(bIntvlCmd)))
             {
                 ret = -EFAULT;
             } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
-                        != A_OK)
+                        != 0)
             {
                 ret = -EIO;
             }
@@ -3214,10 +3242,10 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case IEEE80211_IOCTL_SETAUTHALG:
         {
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
             struct ieee80211req_authalg req;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&req, userdata,
                        sizeof(struct ieee80211req_authalg)))
@@ -3267,7 +3295,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             AR6000_WLAN_STATE state;
 	    if (get_user(state, (unsigned int *)userdata))
 		ret = -EFAULT;
-	    else if (ar6000_set_wlan_state(ar, state) != A_OK)
+	    else if (ar6000_set_wlan_state(ar, state) != 0)
                 ret = -EIO;
             break;
         }
@@ -3327,7 +3355,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_START_SCAN_CMD setStartScanCmd, *cmdp;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                     ret = -EIO;
                 } else if (copy_from_user(&setStartScanCmd, userdata,
                                           sizeof(setStartScanCmd)))
@@ -3339,7 +3367,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                         if (copy_from_user(cmdp, userdata,
                                            sizeof (*cmdp) +
                                            ((setStartScanCmd.numChannels - 1) *
-                                           sizeof(A_UINT16))))
+                                           sizeof(u16))))
                         {
                             kfree(cmdp);
                             ret = -EFAULT;
@@ -3355,7 +3383,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                           cmdp->homeDwellTime,
                                           cmdp->forceScanInterval,
                                           cmdp->numChannels,
-                                          cmdp->channelList) != A_OK)
+                                          cmdp->channelList) != 0)
                     {
                         ret = -EIO;
                     }
@@ -3365,9 +3393,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SETFIXRATES:
         {
             WMI_FIX_RATES_CMD setFixRatesCmd;
-            A_STATUS returnStatus;
+            int returnStatus;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                     ret = -EIO;
                 } else if (copy_from_user(&setFixRatesCmd, userdata,
                                           sizeof(setFixRatesCmd)))
@@ -3377,7 +3405,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
                     if (returnStatus == A_EINVAL) {
                         ret = -EINVAL;
-                    } else if(returnStatus != A_OK) {
+                    } else if(returnStatus != 0) {
                         ret = -EIO;
                     } else {
                         ar->ap_profile_flag = 1; /* There is a change in profile */
@@ -3389,14 +3417,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_GETFIXRATES:
         {
             WMI_FIX_RATES_CMD getFixRatesCmd;
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
             int ret = 0;
 
             if (ar->bIsDestroyProgress) {
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -3416,7 +3444,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             } else {
                 ar->arRateMask = 0xFFFFFFFF;
 
-                if (wmi_get_ratemask_cmd(ar->arWmi) != A_OK) {
+                if (wmi_get_ratemask_cmd(ar->arWmi) != 0) {
                     up(&ar->arSem);
                     ret = -EIO;
                     goto ioctl_done;
@@ -3444,14 +3472,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_AUTH_MODE_CMD setAuthMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setAuthMode, userdata,
                                       sizeof(setAuthMode)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != A_OK)
+                if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3462,14 +3490,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_REASSOC_MODE_CMD setReassocMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setReassocMode, userdata,
                                       sizeof(setReassocMode)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != A_OK)
+                if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3478,13 +3506,13 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_DIAG_READ:
         {
-            A_UINT32 addr, data;
+            u32 addr, data;
 	    if (get_user(addr, (unsigned int *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
             addr = TARG_VTOP(ar->arTargetType, addr);
-            if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
+            if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != 0) {
                 ret = -EIO;
             }
 	    if (put_user(data, (unsigned int *)userdata + 1)) {
@@ -3495,14 +3523,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_DIAG_WRITE:
         {
-            A_UINT32 addr, data;
+            u32 addr, data;
 	    if (get_user(addr, (unsigned int *)userdata) ||
 		get_user(data, (unsigned int *)userdata + 1)) {
 		ret = -EFAULT;
 		break;
 	    }
             addr = TARG_VTOP(ar->arTargetType, addr);
-            if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
+            if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != 0) {
                 ret = -EIO;
             }
             break;
@@ -3510,14 +3538,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
         {
              WMI_SET_KEEPALIVE_CMD setKeepAlive;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&setKeepAlive, userdata,
                         sizeof(setKeepAlive))){
                  ret = -EFAULT;
              } else {
-                 if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != A_OK) {
+                 if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != 0) {
                      ret = -EIO;
                }
              }
@@ -3526,7 +3554,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SET_PARAMS:
         {
              WMI_SET_PARAMS_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
@@ -3537,7 +3565,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             {
                 ret = -EFAULT;
             } else {
-                 if (wmi_set_params_cmd(ar->arWmi, cmd.opcode, cmd.length, cmd.buffer) != A_OK) {
+                 if (wmi_set_params_cmd(ar->arWmi, cmd.opcode, cmd.length, cmd.buffer) != 0) {
                      ret = -EIO;
                }
              }
@@ -3546,7 +3574,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SET_MCAST_FILTER:
         {
              WMI_SET_MCAST_FILTER_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
@@ -3556,7 +3584,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                  if (wmi_set_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
                                                                                      cmd.multicast_mac[1],
                                                                                      cmd.multicast_mac[2],
-                                                                                     cmd.multicast_mac[3]) != A_OK) {
+                                                                                     cmd.multicast_mac[3]) != 0) {
                      ret = -EIO;
                }
              }
@@ -3565,7 +3593,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_DEL_MCAST_FILTER:
         {
              WMI_SET_MCAST_FILTER_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
@@ -3575,7 +3603,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                  if (wmi_del_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
                                                                                      cmd.multicast_mac[1],
                                                                                      cmd.multicast_mac[2],
-                                                                                     cmd.multicast_mac[3]) != A_OK) {
+                                                                                     cmd.multicast_mac[3]) != 0) {
                      ret = -EIO;
                }
              }
@@ -3584,14 +3612,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_MCAST_FILTER:
         {
              WMI_MCAST_FILTER_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
                         sizeof(cmd))){
                  ret = -EFAULT;
              } else {
-                 if (wmi_mcast_filter_cmd(ar->arWmi, cmd.enable)  != A_OK) {
+                 if (wmi_mcast_filter_cmd(ar->arWmi, cmd.enable)  != 0) {
                      ret = -EIO;
                }
              }
@@ -3599,14 +3627,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
         {
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
             WMI_GET_KEEPALIVE_CMD getKeepAlive;
             int ret = 0;
             if (ar->bIsDestroyProgress) {
                 ret =-EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                ret = -EIO;
                goto ioctl_done;
             }
@@ -3624,7 +3652,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             } else {
             getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
             ar->arKeepaliveConfigured = 0xFF;
-            if (wmi_get_keepalive_configured(ar->arWmi) != A_OK){
+            if (wmi_get_keepalive_configured(ar->arWmi) != 0){
                 up(&ar->arSem);
                 ret = -EIO;
                 goto ioctl_done;
@@ -3647,14 +3675,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SET_APPIE:
         {
             WMI_SET_APPIE_CMD appIEcmd;
-            A_UINT8           appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
-            A_UINT32            fType,ieLen;
+            u8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
+            u32 fType,ieLen;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
-	    if (get_user(fType, (A_UINT32 *)userdata)) {
+	    if (get_user(fType, (u32 *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
@@ -3662,7 +3690,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
                 ret = -EIO;
             } else {
-		if (get_user(ieLen, (A_UINT32 *)(userdata + 4))) {
+		if (get_user(ieLen, (u32 *)(userdata + 4))) {
 		    ret = -EFAULT;
 		    break;
 		}
@@ -3676,7 +3704,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     ret = -EFAULT;
                 } else {
                     if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
-                                          appIEcmd.ieLen,  appIeInfo) != A_OK)
+                                          appIEcmd.ieLen,  appIeInfo) != 0)
                     {
                         ret = -EIO;
                     }
@@ -3687,9 +3715,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
         {
             WMI_BSS_FILTER_CMD cmd;
-            A_UINT32    filterType;
+            u32 filterType;
 
-            if (copy_from_user(&filterType, userdata, sizeof(A_UINT32)))
+            if (copy_from_user(&filterType, userdata, sizeof(u32)))
             {
                 ret = -EFAULT;
                 goto ioctl_done;
@@ -3701,7 +3729,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             } else {
                 cmd.bssFilter = NONE_BSS_FILTER;
             }
-            if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != A_OK) {
+            if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != 0) {
                 ret = -EIO;
             } else {
                 ar->arUserBssFilter = cmd.bssFilter;
@@ -3714,33 +3742,33 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
         {
-            A_UINT32    wsc_status;
+            u32 wsc_status;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
-            } else if (copy_from_user(&wsc_status, userdata, sizeof(A_UINT32)))
+            } else if (copy_from_user(&wsc_status, userdata, sizeof(u32)))
             {
                 ret = -EFAULT;
                 goto ioctl_done;
             }
-            if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != A_OK) {
+            if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != 0) {
                 ret = -EIO;
             }
             break;
         }
         case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
         {
-            A_UINT32 ROM_addr;
-            A_UINT32 RAM_addr;
-            A_UINT32 nbytes;
-            A_UINT32 do_activate;
-            A_UINT32 rompatch_id;
-
-	    if (get_user(ROM_addr, (A_UINT32 *)userdata) ||
-		get_user(RAM_addr, (A_UINT32 *)userdata + 1) ||
-		get_user(nbytes, (A_UINT32 *)userdata + 2) ||
-		get_user(do_activate, (A_UINT32 *)userdata + 3)) {
+            u32 ROM_addr;
+            u32 RAM_addr;
+            u32 nbytes;
+            u32 do_activate;
+            u32 rompatch_id;
+
+	    if (get_user(ROM_addr, (u32 *)userdata) ||
+		get_user(RAM_addr, (u32 *)userdata + 1) ||
+		get_user(nbytes, (u32 *)userdata + 2) ||
+		get_user(do_activate, (u32 *)userdata + 3)) {
 		ret = -EFAULT;
 		break;
 	    }
@@ -3748,7 +3776,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                              ROM_addr, RAM_addr, nbytes));
             ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr,
                                         nbytes, do_activate, &rompatch_id);
-            if (ret == A_OK) {
+            if (ret == 0) {
 		/* return value */
 		if (put_user(rompatch_id, (unsigned int *)rq->ifr_data)) {
 		    ret = -EFAULT;
@@ -3760,9 +3788,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
         case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
         {
-            A_UINT32 rompatch_id;
+            u32 rompatch_id;
 
-	    if (get_user(rompatch_id, (A_UINT32 *)userdata)) {
+	    if (get_user(rompatch_id, (u32 *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
@@ -3774,14 +3802,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
         case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
         {
-            A_UINT32 rompatch_count;
+            u32 rompatch_count;
 
-	    if (get_user(rompatch_count, (A_UINT32 *)userdata)) {
+	    if (get_user(rompatch_count, (u32 *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Change rompatch activation count=%d\n", rompatch_count));
-            length = sizeof(A_UINT32) * rompatch_count;
+            length = sizeof(u32) * rompatch_count;
             if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
                 A_MEMZERO(buffer, length);
                 if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length))
@@ -3789,9 +3817,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     ret = -EFAULT;
                 } else {
                     if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
-                        ret = BMIrompatchActivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
+                        ret = BMIrompatchActivate(hifDevice, rompatch_count, (u32 *)buffer);
                     } else {
-                        ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
+                        ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (u32 *)buffer);
                     }
                 }
                 A_FREE(buffer);
@@ -3805,7 +3833,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_IP_CMD setIP;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setIP, userdata,
                                       sizeof(setIP)))
@@ -3813,7 +3841,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_set_ip_cmd(ar->arWmi,
-                                &setIP) != A_OK)
+                                &setIP) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3825,7 +3853,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setHostSleepMode, userdata,
                                       sizeof(setHostSleepMode)))
@@ -3833,7 +3861,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
-                                &setHostSleepMode) != A_OK)
+                                &setHostSleepMode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3844,7 +3872,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_WOW_MODE_CMD setWowMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setWowMode, userdata,
                                       sizeof(setWowMode)))
@@ -3852,7 +3880,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_set_wow_mode_cmd(ar->arWmi,
-                                &setWowMode) != A_OK)
+                                &setWowMode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3863,7 +3891,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_GET_WOW_LIST_CMD getWowList;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&getWowList, userdata,
                                       sizeof(getWowList)))
@@ -3871,7 +3899,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_get_wow_list_cmd(ar->arWmi,
-                                &getWowList) != A_OK)
+                                &getWowList) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3884,11 +3912,11 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 #define WOW_MASK_SIZE 64
 
             WMI_ADD_WOW_PATTERN_CMD cmd;
-            A_UINT8 mask_data[WOW_PATTERN_SIZE]={0};
-            A_UINT8 pattern_data[WOW_PATTERN_SIZE]={0};
+            u8 mask_data[WOW_PATTERN_SIZE]={0};
+            u8 pattern_data[WOW_PATTERN_SIZE]={0};
 
             do {
-                if (ar->arWmiReady == FALSE) {
+                if (ar->arWmiReady == false) {
                     ret = -EIO;
                     break;        
                 } 
@@ -3913,11 +3941,11 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     break;
                 }
                 if (wmi_add_wow_pattern_cmd(ar->arWmi,
-                            &cmd, pattern_data, mask_data, cmd.filter_size) != A_OK)
+                            &cmd, pattern_data, mask_data, cmd.filter_size) != 0)
                 {
                     ret = -EIO;
                 }
-            } while(FALSE);
+            } while(false);
 #undef WOW_PATTERN_SIZE
 #undef WOW_MASK_SIZE
             break;
@@ -3926,7 +3954,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_DEL_WOW_PATTERN_CMD delWowPattern;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&delWowPattern, userdata,
                                       sizeof(delWowPattern)))
@@ -3934,7 +3962,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
                 if (wmi_del_wow_pattern_cmd(ar->arWmi,
-                                &delWowPattern) != A_OK)
+                                &delWowPattern) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3948,7 +3976,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 #endif /* ATH_DEBUG_MODULE */
 #ifdef HTC_EP_STAT_PROFILING
                 {
-                    HTC_ENDPOINT_STATS stats;
+                    struct htc_endpoint_stats stats;
                     int i;
 
                     for (i = 0; i < 5; i++) {
@@ -3998,12 +4026,12 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     /* note, this is used for testing (mbox ping testing), indicate activity
                      * change using the stream ID as the traffic class */
                 ar6000_indicate_tx_activity(ar,
-                                            (A_UINT8)data.StreamID,
-                                            data.Active ? TRUE : FALSE);
+                                            (u8)data.StreamID,
+                                            data.Active ? true : false);
             }
             break;
         case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&connectCtrlFlags, userdata,
                                       sizeof(connectCtrlFlags)))
@@ -4014,20 +4042,20 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             }
             break;
         case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&akmpParams, userdata,
                                       sizeof(WMI_SET_AKMP_PARAMS_CMD)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != A_OK) {
+                if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != 0) {
                     ret = -EIO;
                 }
             }
             break;
         case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else {
                 if (copy_from_user(&pmkidInfo.numPMKID, userdata,
@@ -4043,30 +4071,30 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                     ret = -EFAULT;
                     break;
                 }
-                if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != A_OK) {
+                if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != 0) {
                     ret = -EIO;
                 }
             }
             break;
         case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else  {
-                if (wmi_get_pmkid_list_cmd(ar->arWmi) != A_OK) {
+                if (wmi_get_pmkid_list_cmd(ar->arWmi) != 0) {
                     ret = -EIO;
                 }
             }
             break;
         case AR6000_XIOCTL_WMI_ABORT_SCAN:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             }
             ret = wmi_abort_scan_cmd(ar->arWmi);
             break;
         case AR6000_XIOCTL_AP_HIDDEN_SSID:
         {
-            A_UINT8    hidden_ssid;
-            if (ar->arWmiReady == FALSE) {
+            u8 hidden_ssid;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&hidden_ssid, userdata, sizeof(hidden_ssid))) {
                 ret = -EFAULT;
@@ -4079,14 +4107,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_GET_STA_LIST:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else {
-                A_UINT8 i;
+                u8 i;
                 ap_get_sta_t temp;
                 A_MEMZERO(&temp, sizeof(temp));
                 for(i=0;i<AP_MAX_NUM_STA;i++) {
-                    A_MEMCPY(temp.sta[i].mac, ar->sta_list[i].mac, ATH_MAC_LEN);
+                    memcpy(temp.sta[i].mac, ar->sta_list[i].mac, ATH_MAC_LEN);
                     temp.sta[i].aid = ar->sta_list[i].aid;
                     temp.sta[i].keymgmt = ar->sta_list[i].keymgmt;
                     temp.sta[i].ucipher = ar->sta_list[i].ucipher;
@@ -4101,8 +4129,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_SET_NUM_STA:
         {
-            A_UINT8    num_sta;
-            if (ar->arWmiReady == FALSE) {
+            u8 num_sta;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&num_sta, userdata, sizeof(num_sta))) {
                 ret = -EFAULT;
@@ -4116,8 +4144,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_SET_ACL_POLICY:
         {
-            A_UINT8    policy;
-            if (ar->arWmiReady == FALSE) {
+            u8 policy;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&policy, userdata, sizeof(policy))) {
                 ret = -EFAULT;
@@ -4136,7 +4164,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_AP_SET_ACL_MAC:
         {
             WMI_AP_ACL_MAC_CMD    acl;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&acl, userdata, sizeof(acl))) {
                 ret = -EFAULT;
@@ -4152,7 +4180,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_GET_ACL_LIST:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_ACL *)rq->ifr_data, &ar->g_acl,
                                  sizeof(WMI_AP_ACL))) {
@@ -4168,7 +4196,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case IEEE80211_IOCTL_GETWPAIE:
         {
             struct ieee80211req_wpaie wpaie;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&wpaie, userdata, sizeof(wpaie))) {
                 ret = -EFAULT;
@@ -4181,8 +4209,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_CONN_INACT_TIME:
         {
-            A_UINT32    period;
-            if (ar->arWmiReady == FALSE) {
+            u32 period;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&period, userdata, sizeof(period))) {
                 ret = -EFAULT;
@@ -4194,7 +4222,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_AP_PROT_SCAN_TIME:
         {
             WMI_AP_PROT_SCAN_TIME_CMD  bgscan;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&bgscan, userdata, sizeof(bgscan))) {
                 ret = -EFAULT;
@@ -4211,7 +4239,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_AP_SET_DTIM:
         {
             WMI_AP_SET_DTIM_CMD  d;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&d, userdata, sizeof(d))) {
                 ret = -EFAULT;
@@ -4231,7 +4259,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_TARGET_EVENT_REPORT_CMD evtCfgCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             }
             if (copy_from_user(&evtCfgCmd, userdata,
@@ -4244,8 +4272,8 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_INTRA_BSS_COMM:
         {
-            A_UINT8    intra=0;
-            if (ar->arWmiReady == FALSE) {
+            u8 intra=0;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&intra, userdata, sizeof(intra))) {
                 ret = -EFAULT;
@@ -4276,7 +4304,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 break;
             }
 
-            if (A_FAILED(a_set_module_mask(moduleinfo.modulename, moduleinfo.mask))) {
+            if (a_set_module_mask(moduleinfo.modulename, moduleinfo.mask)) {
                 ret = -EFAULT;
             }
 
@@ -4291,7 +4319,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 break;
             }
 
-            if (A_FAILED(a_get_module_mask(moduleinfo.modulename, &moduleinfo.mask))) {
+            if (a_get_module_mask(moduleinfo.modulename, &moduleinfo.mask)) {
                 ret = -EFAULT;
                 break;
             }
@@ -4318,7 +4346,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_ADDBA_REQ_CMD cmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
@@ -4332,7 +4360,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_DELBA_REQ_CMD cmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
@@ -4346,7 +4374,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_ALLOW_AGGR_CMD cmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
@@ -4358,7 +4386,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
         case AR6000_XIOCTL_SET_HT_CAP:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&htCap, userdata,
                                       sizeof(htCap)))
@@ -4366,7 +4394,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 ret = -EFAULT;
             } else {
 
-                if (wmi_set_ht_cap_cmd(ar->arWmi, &htCap) != A_OK)
+                if (wmi_set_ht_cap_cmd(ar->arWmi, &htCap) != 0)
                 {
                     ret = -EIO;
                 }
@@ -4375,7 +4403,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_SET_HT_OP:
         {
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&htOp, userdata,
                                       sizeof(htOp)))
@@ -4383,7 +4411,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                  ret = -EFAULT;
              } else {
 
-                if (wmi_set_ht_op_cmd(ar->arWmi, htOp.sta_chan_width) != A_OK)
+                if (wmi_set_ht_op_cmd(ar->arWmi, htOp.sta_chan_width) != 0)
                 {
                      ret = -EIO;
                }
@@ -4394,12 +4422,12 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_ACL_DATA:
         {
             void *osbuf = NULL;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
-            } else if (ar6000_create_acl_data_osbuf(dev, (A_UINT8*)userdata, &osbuf) != A_OK) {
+            } else if (ar6000_create_acl_data_osbuf(dev, (u8 *)userdata, &osbuf) != 0) {
                      ret = -EIO;
             } else {
-                if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != A_OK) {
+                if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n"));
                 } else {
                     /* Send data buffer over HTC */
@@ -4411,19 +4439,19 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_HCI_CMD:
         {
             char tmp_buf[512];
-            A_INT8 i;
+            s8 i;
             WMI_HCI_CMD *cmd = (WMI_HCI_CMD *)tmp_buf;
-            A_UINT8 size;
+            u8 size;
 
             size = sizeof(cmd->cmd_buf_sz);
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(cmd, userdata, size)) {
                  ret = -EFAULT;
             } else if(copy_from_user(cmd->buf, userdata + size, cmd->cmd_buf_sz)) {
                     ret = -EFAULT;
             } else {
-                if (wmi_send_hci_cmd(ar->arWmi, cmd->buf, cmd->cmd_buf_sz) != A_OK) {
+                if (wmi_send_hci_cmd(ar->arWmi, cmd->buf, cmd->cmd_buf_sz) != 0) {
                      ret = -EIO;
                 }else if(loghci) {
                     A_PRINTF_LOG("HCI Command To PAL --> \n");
@@ -4442,14 +4470,14 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_WLAN_CONN_PRECEDENCE:
         {
             WMI_SET_BT_WLAN_CONN_PRECEDENCE cmd;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
             } else {
                 if (cmd.precedence == BT_WLAN_CONN_PRECDENCE_WLAN ||
                             cmd.precedence == BT_WLAN_CONN_PRECDENCE_PAL) {
-                    if ( wmi_set_wlan_conn_precedence_cmd(ar->arWmi, cmd.precedence) != A_OK) {
+                    if ( wmi_set_wlan_conn_precedence_cmd(ar->arWmi, cmd.precedence) != 0) {
                         ret = -EIO;
                     }
                 } else {
@@ -4467,7 +4495,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
             WMI_SET_TX_SELECT_RATES_CMD masks;
 
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&masks, userdata,
                                       sizeof(masks)))
@@ -4475,7 +4503,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                  ret = -EFAULT;
              } else {
 
-                if (wmi_set_tx_select_rates_cmd(ar->arWmi, masks.rateMasks) != A_OK)
+                if (wmi_set_tx_select_rates_cmd(ar->arWmi, masks.rateMasks) != 0)
                 {
                      ret = -EIO;
                }
@@ -4487,7 +4515,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             WMI_AP_HIDDEN_SSID_CMD ssid;
             ssid.hidden_ssid = ar->ap_hidden_ssid;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_HIDDEN_SSID_CMD *)rq->ifr_data,
                                     &ssid, sizeof(WMI_AP_HIDDEN_SSID_CMD))) {
@@ -4498,9 +4526,9 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_AP_GET_COUNTRY:
         {
             WMI_AP_SET_COUNTRY_CMD cty;
-            A_MEMCPY(cty.countryCode, ar->ap_country_code, 3);
+            memcpy(cty.countryCode, ar->ap_country_code, 3);
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_SET_COUNTRY_CMD *)rq->ifr_data,
                                     &cty, sizeof(WMI_AP_SET_COUNTRY_CMD))) {
@@ -4510,10 +4538,10 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_AP_GET_WMODE:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
-            } else if(copy_to_user((A_UINT8 *)rq->ifr_data,
-                                    &ar->ap_wmode, sizeof(A_UINT8))) {
+            } else if(copy_to_user((u8 *)rq->ifr_data,
+                                    &ar->ap_wmode, sizeof(u8))) {
                     ret = -EFAULT;
             }
             break;
@@ -4523,7 +4551,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             WMI_AP_SET_DTIM_CMD dtim;
             dtim.dtim = ar->ap_dtim_period;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_SET_DTIM_CMD *)rq->ifr_data,
                                     &dtim, sizeof(WMI_AP_SET_DTIM_CMD))) {
@@ -4536,7 +4564,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             WMI_BEACON_INT_CMD bi;
             bi.beaconInterval = ar->ap_beacon_interval;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_BEACON_INT_CMD *)rq->ifr_data,
                                     &bi, sizeof(WMI_BEACON_INT_CMD))) {
@@ -4549,7 +4577,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             WMI_SET_RTS_CMD rts;
             rts.threshold = ar->arRTS;
 	     
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_SET_RTS_CMD *)rq->ifr_data,
                                     &rts, sizeof(WMI_SET_RTS_CMD))) {
@@ -4559,11 +4587,11 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         }
         case AR6000_XIOCTL_FETCH_TARGET_REGS:
         {
-            A_UINT32 targregs[AR6003_FETCH_TARG_REGS_COUNT];
+            u32 targregs[AR6003_FETCH_TARG_REGS_COUNT];
 
             if (ar->arTargetType == TARGET_TYPE_AR6003) {
                 ar6k_FetchTargetRegs(hifDevice, targregs);
-                if (copy_to_user((A_UINT32 *)rq->ifr_data, &targregs, sizeof(targregs)))
+                if (copy_to_user((u32 *)rq->ifr_data, &targregs, sizeof(targregs)))
                 {
                     ret = -EFAULT;
                 }
@@ -4575,7 +4603,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         case AR6000_XIOCTL_AP_SET_11BG_RATESET:
         {
             WMI_AP_SET_11BG_RATESET_CMD  rate;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&rate, userdata, sizeof(rate))) {
                 ret = -EFAULT;
@@ -4595,7 +4623,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             }
             rq->ifr_ifru.ifru_ivalue = ar->arWlanState; /* return value */
 
-            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)&wmiSleepEvent,
+            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (u8 *)&wmiSleepEvent,
                                      sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
             break;
         }
@@ -4607,7 +4635,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		ret = -EFAULT;
 		break;
 	    }
-            if (ar6000_set_bt_hw_state(ar, state)!=A_OK) {
+            if (ar6000_set_bt_hw_state(ar, state)!= 0) {
                 ret = -EIO;
             }       
         }
@@ -4621,13 +4649,13 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
         {
              WMI_SET_TX_SGI_PARAM_CMD SGICmd;
 
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
              } else if (copy_from_user(&SGICmd, userdata,
                                        sizeof(SGICmd))){
                  ret = -EFAULT;
              } else{
-                     if (wmi_SGI_cmd(ar->arWmi, SGICmd.sgiMask, SGICmd.sgiPERThreshold) != A_OK) {
+                     if (wmi_SGI_cmd(ar->arWmi, SGICmd.sgiMask, SGICmd.sgiPERThreshold) != 0) {
                          ret = -EIO;
                      }
 
@@ -4642,7 +4670,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             if (copy_from_user(ap_ifname, userdata, IFNAMSIZ)) {
                 ret = -EFAULT;
             } else {
-                if (ar6000_add_ap_interface(ar, ap_ifname) != A_OK) {
+                if (ar6000_add_ap_interface(ar, ap_ifname) != 0) {
                     ret = -EIO;
                 } 
             }
@@ -4653,7 +4681,7 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
             break;
         case AR6000_XIOCTL_REMOVE_AP_INTERFACE:
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-            if (ar6000_remove_ap_interface(ar) != A_OK) {
+            if (ar6000_remove_ap_interface(ar) != 0) {
                 ret = -EIO;
             } 
 #else
@@ -4661,6 +4689,12 @@ int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 #endif
             break;
 
+        case AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES:
+        {
+            ret = ar6000_xioctl_set_excess_tx_retry_thres_cmd(dev, userdata);
+            break;
+        }
+
         default:
             ret = -EOPNOTSUPP;
     }
@@ -4672,15 +4706,15 @@ ioctl_done:
     return ret;
 }
 
-A_UINT8 mac_cmp_wild(A_UINT8 *mac, A_UINT8 *new_mac, A_UINT8 wild, A_UINT8 new_wild)
+u8 mac_cmp_wild(u8 *mac, u8 *new_mac, u8 wild, u8 new_wild)
 {
-    A_UINT8 i;
+    u8 i;
 
     for(i=0;i<ATH_MAC_LEN;i++) {
         if((wild & 1<<i) && (new_wild & 1<<i)) continue;
         if(mac[i] != new_mac[i]) return 1;
     }
-    if((A_MEMCMP(new_mac, null_mac, 6)==0) && new_wild &&
+    if((memcmp(new_mac, null_mac, 6)==0) && new_wild &&
         (wild != new_wild)) {
         return 1;
     }
@@ -4688,9 +4722,9 @@ A_UINT8 mac_cmp_wild(A_UINT8 *mac, A_UINT8 *new_mac, A_UINT8 wild, A_UINT8 new_w
     return 0;
 }
 
-A_UINT8    acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
+u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
 {
-    A_INT8    already_avail=-1, free_slot=-1, i;
+    s8 already_avail=-1, free_slot=-1, i;
 
     /* To check whether this mac is already there in our list */
     for(i=AP_ACL_SIZE-1;i>=0;i--)
@@ -4709,7 +4743,7 @@ A_UINT8    acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
         if((already_avail >= 0) || (free_slot == -1))
             return 0;
 
-        A_MEMCPY(a->acl_mac[free_slot], acl->mac, ATH_MAC_LEN);
+        memcpy(a->acl_mac[free_slot], acl->mac, ATH_MAC_LEN);
         a->index = a->index | (1 << free_slot);
         acl->index = free_slot;
         a->wildcard[free_slot] = acl->wildcard;
diff --git a/drivers/staging/ath6kl/os/linux/netbuf.c b/drivers/staging/ath6kl/os/linux/netbuf.c
index 15e5d04..a9c96b3 100644
--- a/drivers/staging/ath6kl/os/linux/netbuf.c
+++ b/drivers/staging/ath6kl/os/linux/netbuf.c
@@ -63,8 +63,8 @@ a_netbuf_alloc(int size)
 {
     struct sk_buff *skb;
     size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */
-    skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + size);
-    skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + A_GET_CACHE_LINE_BYTES());    
+    skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size);
+    skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES());    
     return ((void *)skb);
 }
 
@@ -89,8 +89,7 @@ a_netbuf_free(void *bufPtr)
     dev_kfree_skb(skb);
 }
 
-A_UINT32
-a_netbuf_to_len(void *bufPtr)
+u32 a_netbuf_to_len(void *bufPtr)
 {
     return (((struct sk_buff *)bufPtr)->len);
 }
@@ -105,98 +104,97 @@ a_netbuf_to_data(void *bufPtr)
  * Add len # of bytes to the beginning of the network buffer
  * pointed to by bufPtr
  */
-A_STATUS
-a_netbuf_push(void *bufPtr, A_INT32 len)
+int
+a_netbuf_push(void *bufPtr, s32 len)
 {
     skb_push((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Add len # of bytes to the beginning of the network buffer
  * pointed to by bufPtr and also fill with data
  */
-A_STATUS
-a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len)
+int
+a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len)
 {
     skb_push((struct sk_buff *) bufPtr, len);
-    A_MEMCPY(((struct sk_buff *)bufPtr)->data, srcPtr, len);
+    memcpy(((struct sk_buff *)bufPtr)->data, srcPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Add len # of bytes to the end of the network buffer
  * pointed to by bufPtr
  */
-A_STATUS
-a_netbuf_put(void *bufPtr, A_INT32 len)
+int
+a_netbuf_put(void *bufPtr, s32 len)
 {
     skb_put((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Add len # of bytes to the end of the network buffer
  * pointed to by bufPtr and also fill with data
  */
-A_STATUS
-a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len)
+int
+a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len)
 {
     char *start = (char*)(((struct sk_buff *)bufPtr)->data +
         ((struct sk_buff *)bufPtr)->len);
     skb_put((struct sk_buff *)bufPtr, len);
-    A_MEMCPY(start, srcPtr, len);
+    memcpy(start, srcPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 
 /*
  * Trim the network buffer pointed to by bufPtr to len # of bytes 
  */
-A_STATUS
-a_netbuf_setlen(void *bufPtr, A_INT32 len)
+int
+a_netbuf_setlen(void *bufPtr, s32 len)
 {
     skb_trim((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Chop of len # of bytes from the end of the buffer.
  */
-A_STATUS
-a_netbuf_trim(void *bufPtr, A_INT32 len)
+int
+a_netbuf_trim(void *bufPtr, s32 len)
 {
     skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Chop of len # of bytes from the end of the buffer and return the data.
  */
-A_STATUS
-a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len)
+int
+a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len)
 {
     char *start = (char*)(((struct sk_buff *)bufPtr)->data +
         (((struct sk_buff *)bufPtr)->len - len));
     
-    A_MEMCPY(dstPtr, start, len);
+    memcpy(dstPtr, start, len);
     skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
 
-    return A_OK;
+    return 0;
 }
 
 
 /*
  * Returns the number of bytes available to a a_netbuf_push()
  */
-A_INT32
-a_netbuf_headroom(void *bufPtr)
+s32 a_netbuf_headroom(void *bufPtr)
 {
     return (skb_headroom((struct sk_buff *)bufPtr));
 }
@@ -204,25 +202,25 @@ a_netbuf_headroom(void *bufPtr)
 /*
  * Removes specified number of bytes from the beginning of the buffer
  */
-A_STATUS
-a_netbuf_pull(void *bufPtr, A_INT32 len)
+int
+a_netbuf_pull(void *bufPtr, s32 len)
 {
     skb_pull((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Removes specified number of bytes from the beginning of the buffer
  * and return the data
  */
-A_STATUS
-a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len)
+int
+a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len)
 {
-    A_MEMCPY(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
+    memcpy(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
     skb_pull((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
diff --git a/drivers/staging/ath6kl/os/linux/wireless_ext.c b/drivers/staging/ath6kl/os/linux/wireless_ext.c
index bb6de0f..4b77943 100644
--- a/drivers/staging/ath6kl/os/linux/wireless_ext.c
+++ b/drivers/staging/ath6kl/os/linux/wireless_ext.c
@@ -32,7 +32,7 @@
 #define IWE_STREAM_ADD_VALUE(p1, p2, p3, p4, p5, p6) \
     iwe_stream_add_value((p1), (p2), (p3), (p4), (p5), (p6))
 
-static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
+static void ar6000_set_quality(struct iw_quality *iq, s8 rssi);
 extern unsigned int wmitimeout;
 extern A_WAITQUEUE_HEAD arEvent;
 
@@ -64,10 +64,9 @@ encode_ie(void *buf, size_t bufsize,
 }
 #endif /* WIRELESS_EXT > 14 */
 
-static A_UINT8
-get_bss_phy_capability(bss_t *bss)
+static u8 get_bss_phy_capability(bss_t *bss)
 {
-    A_UINT8 capability = 0;
+    u8 capability = 0;
     struct ieee80211_common_ie *cie = &bss->ni_cie;
 #define CHAN_IS_11A(x)              (!((x >= 2412) && (x <= 2484)))
     if (CHAN_IS_11A(cie->ie_chan)) {
@@ -94,12 +93,12 @@ ar6000_scan_node(void *arg, bss_t *ni)
     char buf[256];
 #endif
     struct ar_giwscan_param *param;
-    A_CHAR *current_ev;
-    A_CHAR *end_buf;
+    char *current_ev;
+    char *end_buf;
     struct ieee80211_common_ie  *cie;
-    A_CHAR *current_val;
-    A_INT32 j;
-    A_UINT32 rate_len, data_len = 0;
+    char *current_val;
+    s32 j;
+    u32 rate_len, data_len = 0;
 
     param = (struct ar_giwscan_param *)arg;
 
@@ -113,7 +112,7 @@ ar6000_scan_node(void *arg, bss_t *ni)
         A_MEMZERO(&iwe, sizeof(iwe));
         iwe.cmd = SIOCGIWAP;
         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-        A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
+        memcpy(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
         current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
                                           &iwe, IW_EV_ADDR_LEN);
     }
@@ -417,10 +416,10 @@ ar6000_ioctl_giwscan(struct net_device *dev,
             struct iw_request_info *info,
             struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct ar_giwscan_param param;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -429,7 +428,7 @@ ar6000_ioctl_giwscan(struct net_device *dev,
         return -EIO;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -462,12 +461,12 @@ ar6000_ioctl_siwessid(struct net_device *dev,
                      struct iw_request_info *info,
                      struct iw_point *data, char *ssid)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_STATUS status;
-    A_UINT8     arNetworkType;
-    A_UINT8 prevMode = ar->arNetworkType;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    int status;
+    u8 arNetworkType;
+    u8 prevMode = ar->arNetworkType;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -480,7 +479,7 @@ ar6000_ioctl_siwessid(struct net_device *dev,
         return -EIO;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -505,14 +504,14 @@ ar6000_ioctl_siwessid(struct net_device *dev,
 
     if (ar->arNextMode == AP_NETWORK) {
         /* SSID change for AP network - Will take effect on commit */
-        if(A_MEMCMP(ar->arSsid,ssid,32) != 0) {
+        if(memcmp(ar->arSsid,ssid,32) != 0) {
              ar->arSsidLen = data->length - 1;
-            A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
+            memcpy(ar->arSsid, ssid, ar->arSsidLen);
             ar->ap_profile_flag = 1; /* There is a change in profile */
         }
         return 0;
     } else if(ar->arNetworkType == AP_NETWORK) {
-        A_UINT8 ctr;
+        u8 ctr;
         struct sk_buff *skb;
 
         /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
@@ -532,7 +531,7 @@ ar6000_ioctl_siwessid(struct net_device *dev,
        and we cannot scan during connect.
      */
     if (data->flags) {
-        if (ar->arSkipScan == TRUE &&
+        if (ar->arSkipScan == true &&
             (ar->arChannelHint == 0 ||
              (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
               !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
@@ -576,12 +575,13 @@ ar6000_ioctl_siwessid(struct net_device *dev,
     /* Update the arNetworkType */
     ar->arNetworkType = ar->arNextMode;
 
-
     if ((prevMode != AP_NETWORK) &&
-        ((ar->arSsidLen) || ((ar->arSsidLen == 0) && ar->arConnected) || (!data->flags)))
+        ((ar->arSsidLen) || 
+        ((ar->arSsidLen == 0) && (ar->arConnected || ar->arConnectPending)) || 
+        (!data->flags)))
     {
         if ((!data->flags) ||
-            (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
+            (memcmp(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
             (ar->arSsidLen != (data->length - 1)))
         {
             /*
@@ -592,13 +592,13 @@ ar6000_ioctl_siwessid(struct net_device *dev,
              * (2) essid off has been issued
              *
              */
-            if (ar->arWmiReady == TRUE) {
+            if (ar->arWmiReady == true) {
                 reconnect_flag = 0;
                 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
-                status = wmi_disconnect_cmd(ar->arWmi);
+                ar6000_disconnect(ar);
                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
                 ar->arSsidLen = 0;
-                if (ar->arSkipScan == FALSE) {
+                if (ar->arSkipScan == false) {
                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
                 }
                 if (!data->flags) {
@@ -617,13 +617,13 @@ ar6000_ioctl_siwessid(struct net_device *dev,
              * a reconnect cmd. Issue a reconnect only we are already
              * connected.
              */
-            if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
+            if((ar->arConnected == true) && (ar->arWmiReady == true))
             {
-                reconnect_flag = TRUE;
+                reconnect_flag = true;
                 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
                                            ar->arChannelHint);
                 up(&ar->arSem);
-                if (status != A_OK) {
+                if (status) {
                     return -EIO;
                 }
                 return 0;
@@ -641,9 +641,9 @@ ar6000_ioctl_siwessid(struct net_device *dev,
     }
 
     ar->arSsidLen = data->length - 1;
-    A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
+    memcpy(ar->arSsid, ssid, ar->arSsidLen);
 
-    if (ar6000_connect_to_ap(ar)!= A_OK) {
+    if (ar6000_connect_to_ap(ar)!= 0) {
         up(&ar->arSem);
         return -EIO;
     }else{
@@ -658,9 +658,9 @@ ar6000_ioctl_giwessid(struct net_device *dev,
                      struct iw_request_info *info,
                      struct iw_point *data, char *essid)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -675,16 +675,16 @@ ar6000_ioctl_giwessid(struct net_device *dev,
 
     data->flags = 1;
     data->length = ar->arSsidLen;
-    A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
+    memcpy(essid, ar->arSsid, ar->arSsidLen);
 
     return 0;
 }
 
 
-void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
+void ar6000_install_static_wep_keys(struct ar6_softc *ar)
 {
-    A_UINT8 index;
-    A_UINT8 keyUsage;
+    u8 index;
+    u8 keyUsage;
 
     for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
         if (ar->arWepKeyList[index].arKeyLen) {
@@ -712,11 +712,11 @@ ar6000_ioctl_siwrate(struct net_device *dev,
             struct iw_request_info *info,
             struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT32  kbps;
-    A_INT8  rate_idx;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u32 kbps;
+    s8 rate_idx;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -726,15 +726,15 @@ ar6000_ioctl_siwrate(struct net_device *dev,
     } else {
         kbps = -1;                          /* -1 indicates auto rate */
     }
-    if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != A_OK)
+    if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != 0)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
         return -EINVAL;
     }
     ar->arBitRate = kbps;
-    if(ar->arWmiReady == TRUE)
+    if(ar->arWmiReady == true)
     {
-        if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) {
+        if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != 0) {
             return -EINVAL;
         }
     }
@@ -749,10 +749,10 @@ ar6000_ioctl_giwrate(struct net_device *dev,
             struct iw_request_info *info,
             struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -765,7 +765,7 @@ ar6000_ioctl_giwrate(struct net_device *dev,
         return -EIO;
     }
 
-    if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == FALSE) {
+    if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == false) {
         rrq->value = 1000 * 1000;       
         return 0;
     }
@@ -780,7 +780,7 @@ ar6000_ioctl_giwrate(struct net_device *dev,
     }
 
     ar->arBitRate = 0xFFFF;
-    if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
+    if (wmi_get_bitrate_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
@@ -792,7 +792,7 @@ ar6000_ioctl_giwrate(struct net_device *dev,
        connected - return the value stored in the device structure */
     if (!ret) {
         if (ar->arBitRate == -1) {
-            rrq->fixed = TRUE;
+            rrq->fixed = true;
             rrq->value = 0;
         } else {
             rrq->value = ar->arBitRate * 1000;
@@ -812,10 +812,10 @@ ar6000_ioctl_siwtxpow(struct net_device *dev,
              struct iw_request_info *info,
              struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8 dbM;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 dbM;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -833,12 +833,12 @@ ar6000_ioctl_siwtxpow(struct net_device *dev,
             return -EOPNOTSUPP;
         }
         ar->arTxPwr= dbM = rrq->value;
-        ar->arTxPwrSet = TRUE;
+        ar->arTxPwrSet = true;
     } else {
         ar->arTxPwr = dbM = 0;
-        ar->arTxPwrSet = FALSE;
+        ar->arTxPwrSet = false;
     }
-    if(ar->arWmiReady == TRUE)
+    if(ar->arWmiReady == true)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
         wmi_set_txPwr_cmd(ar->arWmi, dbM);
@@ -854,10 +854,10 @@ ar6000_ioctl_giwtxpow(struct net_device *dev,
             struct iw_request_info *info,
             struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -879,11 +879,11 @@ ar6000_ioctl_giwtxpow(struct net_device *dev,
         return -EBUSY;
     }
 
-    if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
+    if((ar->arWmiReady == true) && (ar->arConnected == true))
     {
         ar->arTxPwr = 0;
 
-        if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
+        if (wmi_get_txPwr_cmd(ar->arWmi) != 0) {
             up(&ar->arSem);
             return -EIO;
         }
@@ -898,8 +898,8 @@ ar6000_ioctl_giwtxpow(struct net_device *dev,
       then return value stored in the device structure */
 
     if (!ret) {
-         if (ar->arTxPwrSet == TRUE) {
-            rrq->fixed = TRUE;
+         if (ar->arTxPwrSet == true) {
+            rrq->fixed = true;
         }
         rrq->value = ar->arTxPwr;
         rrq->flags = IW_TXPOW_DBM;
@@ -924,9 +924,9 @@ ar6000_ioctl_siwretry(struct net_device *dev,
              struct iw_request_info *info,
              struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -946,10 +946,10 @@ ar6000_ioctl_siwretry(struct net_device *dev,
     if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
             return - EINVAL;
     }
-    if(ar->arWmiReady == TRUE)
+    if(ar->arWmiReady == true)
     {
         if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
-                                     rrq->value, 0) != A_OK){
+                                     rrq->value, 0) != 0){
             return -EINVAL;
         }
     }
@@ -965,9 +965,9 @@ ar6000_ioctl_giwretry(struct net_device *dev,
              struct iw_request_info *info,
              struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1006,11 +1006,11 @@ ar6000_ioctl_siwencode(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *keybuf)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int index;
-    A_INT32 auth = 0;
+    s32 auth = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1080,7 +1080,7 @@ ar6000_ioctl_siwencode(struct net_device *dev,
 
             A_MEMZERO(ar->arWepKeyList[index].arKey,
                       sizeof(ar->arWepKeyList[index].arKey));
-            A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
+            memcpy(ar->arWepKeyList[index].arKey, keybuf, erq->length);
             ar->arWepKeyList[index].arKeyLen = erq->length;
             ar->arDot11AuthMode       = auth;
         } else {
@@ -1122,11 +1122,11 @@ ar6000_ioctl_giwencode(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *key)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8 keyIndex;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 keyIndex;
     struct ar_wep_key *wk;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1158,14 +1158,14 @@ ar6000_ioctl_giwencode(struct net_device *dev,
                 erq->length = wk->arKeyLen;
             }
             if (wk->arKeyLen) {
-                A_MEMCPY(key, wk->arKey, erq->length);
+                memcpy(key, wk->arKey, erq->length);
             }
         } else {
             erq->flags &= ~IW_ENCODE_DISABLED;
             if (ar->user_saved_keys.keyOk) {
                 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen;
                 if (erq->length) {
-                    A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
+                    memcpy(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
                 }
             } else {
                 erq->length = 1;    // not really printing any key but let iwconfig know enc is on
@@ -1192,16 +1192,16 @@ ar6000_ioctl_siwgenie(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
 #ifdef WAPI_ENABLE
-    A_UINT8    *ie = erq->pointer;
-    A_UINT8    ie_type = ie[0];
-    A_UINT16   ie_length = erq->length;
-    A_UINT8    wapi_ie[128];
+    u8 *ie = erq->pointer;
+    u8 ie_type = ie[0];
+    u16 ie_length = erq->length;
+    u8 wapi_ie[128];
 #endif
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 #ifdef WAPI_ENABLE
@@ -1228,9 +1228,9 @@ ar6000_ioctl_giwgenie(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
     erq->length = 0;
@@ -1247,14 +1247,14 @@ ar6000_ioctl_siwauth(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_param *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    A_BOOL profChanged;
-    A_UINT16 param;
-    A_INT32 ret;
-    A_INT32 value;
+    bool profChanged;
+    u16 param;
+    s32 ret;
+    s32 value;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1264,7 +1264,7 @@ ar6000_ioctl_siwauth(struct net_device *dev,
 
     param = data->flags & IW_AUTH_INDEX;
     value = data->value;
-    profChanged = TRUE;
+    profChanged = true;
     ret = 0;
 
     switch (param) {
@@ -1277,7 +1277,7 @@ ar6000_ioctl_siwauth(struct net_device *dev,
                     ar->arAuthMode = WPA2_AUTH;
             } else {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_CIPHER_PAIRWISE:
@@ -1298,7 +1298,7 @@ ar6000_ioctl_siwauth(struct net_device *dev,
                 ar->arPairwiseCryptoLen = 13;
             } else {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_CIPHER_GROUP:
@@ -1319,7 +1319,7 @@ ar6000_ioctl_siwauth(struct net_device *dev,
                 ar->arGroupCryptoLen = 13;
             } else {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_KEY_MGMT:
@@ -1337,10 +1337,10 @@ ar6000_ioctl_siwauth(struct net_device *dev,
             break;
         case IW_AUTH_TKIP_COUNTERMEASURES:
             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_DROP_UNENCRYPTED:
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_80211_AUTH_ALG:
             ar->arDot11AuthMode = 0;
@@ -1355,7 +1355,7 @@ ar6000_ioctl_siwauth(struct net_device *dev,
             }
             if(ar->arDot11AuthMode == 0) {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_WPA_ENABLED:
@@ -1374,10 +1374,10 @@ ar6000_ioctl_siwauth(struct net_device *dev,
             }
             break;
         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_ROAMING_CONTROL:
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_PRIVACY_INVOKED:
             if (!value) {
@@ -1394,11 +1394,11 @@ ar6000_ioctl_siwauth(struct net_device *dev,
 #endif
         default:
            ret = -1;
-           profChanged    = FALSE;
+           profChanged    = false;
            break;
     }
 
-    if (profChanged == TRUE) {
+    if (profChanged == true) {
         /*
          * profile has changed.  Erase ssid to signal change
          */
@@ -1418,11 +1418,11 @@ ar6000_ioctl_giwauth(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_param *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT16 param;
-    A_INT32 ret;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u16 param;
+    s32 ret;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1546,29 +1546,29 @@ ar6000_ioctl_siwpmksa(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_INT32 ret;
-    A_STATUS status;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    s32 ret;
+    int status;
     struct iw_pmksa *pmksa;
 
     pmksa = (struct iw_pmksa *)extra;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
     ret = 0;
-    status = A_OK;
+    status = 0;
 
     switch (pmksa->cmd) {
         case IW_PMKSA_ADD:
-            status = wmi_setPmkid_cmd(ar->arWmi, (A_UINT8*)pmksa->bssid.sa_data, pmksa->pmkid, TRUE);
+            status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, true);
             break;
         case IW_PMKSA_REMOVE:
-            status = wmi_setPmkid_cmd(ar->arWmi, (A_UINT8*)pmksa->bssid.sa_data, pmksa->pmkid, FALSE);
+            status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, false);
             break;
         case IW_PMKSA_FLUSH:
-            if (ar->arConnected == TRUE) {
+            if (ar->arConnected == true) {
                 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
             }
             break;
@@ -1576,7 +1576,7 @@ ar6000_ioctl_siwpmksa(struct net_device *dev,
             ret=-1;
             break;
     }
-    if (status != A_OK) {
+    if (status) {
         ret = -1;
     }
 
@@ -1591,18 +1591,18 @@ static int ar6000_set_wapi_key(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
     KEY_USAGE   keyUsage = 0;
-    A_INT32     keyLen;
-    A_UINT8     *keyData;
-    A_INT32     index;
-    A_UINT32    *PN;
-    A_INT32     i;
-    A_STATUS    status;
-    A_UINT8     wapiKeyRsc[16];
+    s32 keyLen;
+    u8 *keyData;
+    s32 index;
+    u32 *PN;
+    s32 i;
+    int    status;
+    u8 wapiKeyRsc[16];
     CRYPTO_TYPE keyType = WAPI_CRYPT;
-    const A_UINT8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    const u8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
     index = erq->flags & IW_ENCODE_INDEX;
     if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
@@ -1614,13 +1614,13 @@ static int ar6000_set_wapi_key(struct net_device *dev,
     if (index < 0 || index > 4) {
         return -EIO;
     }
-    keyData = (A_UINT8 *)(ext + 1);
+    keyData = (u8 *)(ext + 1);
     keyLen = erq->length - sizeof(struct iw_encode_ext);
-    A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
+    memcpy(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
 
-    if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
+    if (memcmp(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
         keyUsage |= GROUP_USAGE;
-        PN = (A_UINT32 *)wapiKeyRsc;
+        PN = (u32 *)wapiKeyRsc;
         for (i = 0; i < 4; i++) {
             PN[i] = PN_INIT;
         }
@@ -1637,7 +1637,7 @@ static int ar6000_set_wapi_key(struct net_device *dev,
                             KEY_OP_INIT_WAPIPN,
                             NULL,
                             SYNC_BEFORE_WMIFLAG);
-    if (A_OK != status) {
+    if (0 != status) {
         return -EIO;
     }
     return 0;
@@ -1653,14 +1653,14 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_INT32 index;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    s32 index;
     struct iw_encode_ext *ext;
     KEY_USAGE keyUsage;
-    A_INT32 keyLen;
-    A_UINT8 *keyData;
-    A_UINT8 keyRsc[8];
-    A_STATUS status;
+    s32 keyLen;
+    u8 *keyData;
+    u8 keyRsc[8];
+    int status;
     CRYPTO_TYPE keyType;
 #ifdef USER_KEYS
     struct ieee80211req_key ik;
@@ -1671,7 +1671,7 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
     }
 
 #ifdef USER_KEYS
-    ar->user_saved_keys.keyOk = FALSE;
+    ar->user_saved_keys.keyOk = false;
 #endif /* USER_KEYS */
 
     index = erq->flags & IW_ENCODE_INDEX;
@@ -1721,7 +1721,7 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
         }
 
         /* key follows iw_encode_ext */
-        keyData = (A_UINT8 *)(ext + 1);
+        keyData = (u8 *)(ext + 1);
 
         switch (ext->alg) {
             case IW_ENCODE_ALG_WEP:
@@ -1737,7 +1737,7 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
                 if (!ar->arConnected) {
                     A_MEMZERO(ar->arWepKeyList[index].arKey,
                           sizeof(ar->arWepKeyList[index].arKey));
-                    A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen);
+                    memcpy(ar->arWepKeyList[index].arKey, keyData, keyLen);
                     ar->arWepKeyList[index].arKeyLen = keyLen;
 
                     return 0;
@@ -1778,7 +1778,7 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
         }
 
         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-            A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc));
+            memcpy(keyRsc, ext->rx_seq, sizeof(keyRsc));
         } else {
             A_MEMZERO(keyRsc, sizeof(keyRsc));
         }
@@ -1792,9 +1792,9 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
          status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage,
                             keyLen, keyRsc,
                             keyData, KEY_OP_INIT_VAL,
-                            (A_UINT8*)ext->addr.sa_data,
+                            (u8 *)ext->addr.sa_data,
                             SYNC_BOTH_WMIFLAG);
-         if (status != A_OK) {
+         if (status) {
             return -EIO;
          }
 
@@ -1811,7 +1811,7 @@ ar6000_ioctl_siwencodeext(struct net_device *dev,
             memcpy(&ar->user_saved_keys.ucast_ik, &ik,
                       sizeof(struct ieee80211req_key));
         }
-        ar->user_saved_keys.keyOk = TRUE;
+        ar->user_saved_keys.keyOk = true;
 #endif /* USER_KEYS */
     }
 
@@ -1827,7 +1827,7 @@ ar6000_ioctl_giwencodeext(struct net_device *dev,
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     if (ar->arWlanState == WLAN_DISABLED) {
         return -EIO;
@@ -1850,10 +1850,10 @@ static int ar6000_ioctl_siwpower(struct net_device *dev,
                  union iwreq_data *wrqu, char *extra)
 {
 #ifndef ATH6K_CONFIG_OTA_MODE
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWER_MODE power_mode;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1876,10 +1876,10 @@ static int ar6000_ioctl_giwpower(struct net_device *dev,
                  struct iw_request_info *info,
                  union iwreq_data *wrqu, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWER_MODE power_mode;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1906,10 +1906,10 @@ ar6000_ioctl_giwname(struct net_device *dev,
            struct iw_request_info *info,
            char *name, char *extra)
 {
-    A_UINT8 capability;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    u8 capability;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1961,9 +1961,9 @@ ar6000_ioctl_siwfreq(struct net_device *dev,
             struct iw_request_info *info,
             struct iw_freq *freq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2006,9 +2006,9 @@ ar6000_ioctl_giwfreq(struct net_device *dev,
                 struct iw_request_info *info,
                 struct iw_freq *freq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2026,7 +2026,7 @@ ar6000_ioctl_giwfreq(struct net_device *dev,
             return -EINVAL;
         }
     } else {
-        if (ar->arConnected != TRUE) {
+        if (ar->arConnected != true) {
             return -EINVAL;
         } else {
             freq->m = ar->arBssChannel * 100000;
@@ -2046,9 +2046,9 @@ ar6000_ioctl_siwmode(struct net_device *dev,
             struct iw_request_info *info,
             __u32 *mode, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2060,7 +2060,7 @@ ar6000_ioctl_siwmode(struct net_device *dev,
     /*
      * clear SSID during mode switch in connected state
      */
-    if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == TRUE) ){
+    if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == true) ){
         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
         ar->arSsidLen = 0;
     }
@@ -2117,9 +2117,9 @@ ar6000_ioctl_giwmode(struct net_device *dev,
             struct iw_request_info *info,
             __u32 *mode, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2177,11 +2177,11 @@ ar6000_ioctl_giwrange(struct net_device *dev,
              struct iw_request_info *info,
              struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct iw_range *range = (struct iw_range *) extra;
     int i, ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2190,7 +2190,7 @@ ar6000_ioctl_giwrange(struct net_device *dev,
         return -EBUSY;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2206,7 +2206,7 @@ ar6000_ioctl_giwrange(struct net_device *dev,
     ar->arNumChannels = -1;
     A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
 
-    if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
+    if (wmi_get_channelList_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
@@ -2300,9 +2300,9 @@ ar6000_ioctl_siwap(struct net_device *dev,
               struct iw_request_info *info,
               struct sockaddr *ap_addr, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2315,10 +2315,10 @@ ar6000_ioctl_siwap(struct net_device *dev,
         return -EIO;
     }
 
-    if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
+    if (memcmp(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
         A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     } else {
-        A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data,  sizeof(ar->arReqBssid));
+        memcpy(ar->arReqBssid, &ap_addr->sa_data,  sizeof(ar->arReqBssid));
     }
 
     return 0;
@@ -2332,9 +2332,9 @@ ar6000_ioctl_giwap(struct net_device *dev,
               struct iw_request_info *info,
               struct sockaddr *ap_addr, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2344,16 +2344,16 @@ ar6000_ioctl_giwap(struct net_device *dev,
     }
 
     if (ar->arNetworkType == AP_NETWORK) {
-        A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
+        memcpy(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
         ap_addr->sa_family = ARPHRD_ETHER;
         return 0;
     }
 
-    if (ar->arConnected != TRUE) {
+    if (ar->arConnected != true) {
         return -EINVAL;
     }
 
-    A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
+    memcpy(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
     ap_addr->sa_family = ARPHRD_ETHER;
 
     return 0;
@@ -2368,9 +2368,9 @@ ar6000_ioctl_siwmlme(struct net_device *dev,
             struct iw_request_info *info,
             struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2383,7 +2383,7 @@ ar6000_ioctl_siwmlme(struct net_device *dev,
         return -EIO;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2393,7 +2393,7 @@ ar6000_ioctl_siwmlme(struct net_device *dev,
 
     if (data->pointer && data->length == sizeof(struct iw_mlme)) {
 
-        A_UINT8 arNetworkType;
+        u8 arNetworkType;
         struct iw_mlme mlme;
 
         if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
@@ -2404,7 +2404,7 @@ ar6000_ioctl_siwmlme(struct net_device *dev,
             case IW_MLME_DEAUTH:
                 /* fall through */
             case IW_MLME_DISASSOC:
-                if ((ar->arConnected != TRUE) ||
+                if ((ar->arConnected != true) ||
                     (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) {
 
                     up(&ar->arSem);
@@ -2415,10 +2415,10 @@ ar6000_ioctl_siwmlme(struct net_device *dev,
                 ar6000_init_profile_info(ar);
                 ar->arNetworkType = arNetworkType;
                 reconnect_flag = 0;
-                wmi_disconnect_cmd(ar->arWmi);
+                ar6000_disconnect(ar);
                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
                 ar->arSsidLen = 0;
-                if (ar->arSkipScan == FALSE) {
+                if (ar->arSkipScan == false) {
                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
                 }
                 break;
@@ -2460,15 +2460,15 @@ ar6000_ioctl_siwscan(struct net_device *dev,
 #define ACT_DWELLTIME_DEFAULT   105
 #define HOME_TXDRAIN_TIME       100
 #define SCAN_INT                HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2488,13 +2488,13 @@ ar6000_ioctl_siwscan(struct net_device *dev,
     } 
 
     if (!ar->arUserBssFilter) {
-        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
+        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
             return -EIO;
         }
     }
 
     if (ar->arConnected) {
-        if  (wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+        if  (wmi_get_stats_cmd(ar->arWmi) != 0) {
             return -EIO;
         }
     }
@@ -2508,32 +2508,32 @@ ar6000_ioctl_siwscan(struct net_device *dev,
             struct iw_scan_req req;
             if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req)))
                 return -EIO;
-            if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != A_OK)
+            if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != 0)
                 return -EIO;
-            ar->scanSpecificSsid = 1;
+            ar->scanSpecificSsid = true;
         }
         else
         {
             if (ar->scanSpecificSsid) {
-                if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
+                if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != 0)
                     return -EIO;
-                 ar->scanSpecificSsid = 0;
+                 ar->scanSpecificSsid = false;
             }
         }
     }
     else
     {
         if (ar->scanSpecificSsid) {
-            if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
+            if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != 0)
                 return -EIO;
-             ar->scanSpecificSsid = 0;
+             ar->scanSpecificSsid = false;
         }
     }
 #endif
 #endif /* ANDROID_ENV */
 
-    if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
-                          0, 0, 0, NULL) != A_OK) {
+    if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, false, false, \
+                          0, 0, 0, NULL) != 0) {
         ret = -EIO;
     }
 
@@ -2565,7 +2565,7 @@ ar6000_ioctl_siwscan(struct net_device *dev,
  *     drivers for compatibility
  */
 static void
-ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
+ar6000_set_quality(struct iw_quality *iq, s8 rssi)
 {
     if (rssi < 0) {
         iq->qual = 0;
@@ -2588,14 +2588,14 @@ ar6000_ioctl_siwcommit(struct net_device *dev,
                      struct iw_request_info *info,
                      struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2615,8 +2615,6 @@ ar6000_ioctl_siwcommit(struct net_device *dev,
      * update the host driver association state for the STA|IBSS mode.
      */
     if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) {
-        ar->arConnectPending = FALSE;
-        ar->arConnected = FALSE;
         /* Stop getting pkts from upper stack */
         netif_stop_queue(ar->arNetDev);
         A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
diff --git a/drivers/staging/ath6kl/reorder/aggr_rx_internal.h b/drivers/staging/ath6kl/reorder/aggr_rx_internal.h
index 5dbf8f8..1112596 100644
--- a/drivers/staging/ath6kl/reorder/aggr_rx_internal.h
+++ b/drivers/staging/ath6kl/reorder/aggr_rx_internal.h
@@ -48,7 +48,7 @@
 #define AGGR_GET_RXTID(_p, _x)    (&(_p->RxTid[(_x)]))
 
 /* Hold q is a function of win_sz, which is negotiated per tid */
-#define HOLD_Q_SZ(_x)   (TID_WINDOW_SZ((_x))*sizeof(OSBUF_HOLD_Q))
+#define HOLD_Q_SZ(_x)   (TID_WINDOW_SZ((_x))*sizeof(struct osbuf_hold_q))
 /* AGGR_RX_TIMEOUT value is important as a (too) small value can cause frames to be 
  * delivered out of order and a (too) large value can cause undesirable latency in
  * certain situations. */
@@ -59,58 +59,59 @@ typedef enum {
     CONTIGUOUS_SEQNO = 1,
 }DELIVERY_ORDER;
 
-typedef struct {
+struct osbuf_hold_q {
     void        *osbuf;
-    A_BOOL      is_amsdu;
-    A_UINT16    seq_no;
-}OSBUF_HOLD_Q;
+    bool      is_amsdu;
+    u16 seq_no;
+};
 
 
 #if 0
-typedef struct {
-    A_UINT16    seqno_st;
-    A_UINT16    seqno_end;
-}WINDOW_SNAPSHOT;
+/* XXX: unused ? */
+struct window_snapshot {
+    u16 seqno_st;
+    u16 seqno_end;
+};
 #endif
 
-typedef struct {
-    A_BOOL              aggr;       /* is it ON or OFF */
-    A_BOOL              progress;   /* TRUE when frames have arrived after a timer start */
-    A_BOOL              timerMon;   /* TRUE if the timer started for the sake of this TID */
-    A_UINT16            win_sz;     /* negotiated window size */
-    A_UINT16            seq_next;   /* Next seq no, in current window */
-    A_UINT32            hold_q_sz;  /* Num of frames that can be held in hold q */
-    OSBUF_HOLD_Q        *hold_q;    /* Hold q for re-order */
+struct rxtid {
+    bool              aggr;       /* is it ON or OFF */
+    bool              progress;   /* true when frames have arrived after a timer start */
+    bool              timerMon;   /* true if the timer started for the sake of this TID */
+    u16 win_sz;     /* negotiated window size */
+    u16 seq_next;   /* Next seq no, in current window */
+    u32 hold_q_sz;  /* Num of frames that can be held in hold q */
+    struct osbuf_hold_q        *hold_q;    /* Hold q for re-order */
 #if 0    
-    WINDOW_SNAPSHOT     old_win;    /* Sliding window snapshot - for timeout */
+    struct window_snapshot     old_win;    /* Sliding window snapshot - for timeout */
 #endif    
     A_NETBUF_QUEUE_T    q;          /* q head for enqueuing frames for dispatch */
     A_MUTEX_T           lock;
-}RXTID;
-
-typedef struct {
-    A_UINT32    num_into_aggr;      /* hitting at the input of this module */
-    A_UINT32    num_dups;           /* duplicate */
-    A_UINT32    num_oow;            /* out of window */
-    A_UINT32    num_mpdu;           /* single payload 802.3/802.11 frame */
-    A_UINT32    num_amsdu;          /* AMSDU */
-    A_UINT32    num_delivered;      /* frames delivered to IP stack */
-    A_UINT32    num_timeouts;       /* num of timeouts, during which frames delivered */
-    A_UINT32    num_hole;           /* frame not present, when window moved over */
-    A_UINT32    num_bar;            /* num of resets of seq_num, via BAR */
-}RXTID_STATS;
-
-typedef struct {
-    A_UINT8             aggr_sz;            /* config value of aggregation size */    
-    A_UINT8             timerScheduled;
+};
+
+struct rxtid_stats {
+    u32 num_into_aggr;      /* hitting at the input of this module */
+    u32 num_dups;           /* duplicate */
+    u32 num_oow;            /* out of window */
+    u32 num_mpdu;           /* single payload 802.3/802.11 frame */
+    u32 num_amsdu;          /* AMSDU */
+    u32 num_delivered;      /* frames delivered to IP stack */
+    u32 num_timeouts;       /* num of timeouts, during which frames delivered */
+    u32 num_hole;           /* frame not present, when window moved over */
+    u32 num_bar;            /* num of resets of seq_num, via BAR */
+};
+
+struct aggr_info {
+    u8 aggr_sz;            /* config value of aggregation size */
+    u8 timerScheduled;
     A_TIMER             timer;              /* timer for returning held up pkts in re-order que */    
     void                *dev;               /* dev handle */
     RX_CALLBACK         rx_fn;              /* callback function to return frames; to upper layer */
-    RXTID               RxTid[NUM_OF_TIDS]; /* Per tid window */
+    struct rxtid               RxTid[NUM_OF_TIDS]; /* Per tid window */
     ALLOC_NETBUFS       netbuf_allocator;   /* OS netbuf alloc fn */
     A_NETBUF_QUEUE_T    freeQ;              /* pre-allocated buffers - for A_MSDU slicing */
-    RXTID_STATS         stat[NUM_OF_TIDS];  /* Tid based statistics */
+    struct rxtid_stats         stat[NUM_OF_TIDS];  /* Tid based statistics */
     PACKET_LOG          pkt_log;            /* Log info of the packets */
-}AGGR_INFO;
+};
 
 #endif /* __AGGR_RX_INTERNAL_H__ */
diff --git a/drivers/staging/ath6kl/reorder/rcv_aggr.c b/drivers/staging/ath6kl/reorder/rcv_aggr.c
index 092bb30..094b227 100644
--- a/drivers/staging/ath6kl/reorder/rcv_aggr.c
+++ b/drivers/staging/ath6kl/reorder/rcv_aggr.c
@@ -33,36 +33,36 @@
 #include "aggr_rx_internal.h"
 #include "wmi.h"
 
-extern A_STATUS
+extern int
 wmi_dot3_2_dix(void *osbuf);
 
 static void
-aggr_slice_amsdu(AGGR_INFO *p_aggr, RXTID *rxtid, void **osbuf);
+aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf);
 
 static void
 aggr_timeout(A_ATH_TIMER arg);
 
 static void
-aggr_deque_frms(AGGR_INFO *p_aggr, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 order);
+aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order);
 
 static void
-aggr_dispatch_frames(AGGR_INFO *p_aggr, A_NETBUF_QUEUE_T *q);
+aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q);
 
 static void *
-aggr_get_osbuf(AGGR_INFO *p_aggr);
+aggr_get_osbuf(struct aggr_info *p_aggr);
 
 void *
 aggr_init(ALLOC_NETBUFS netbuf_allocator)
 {
-    AGGR_INFO   *p_aggr = NULL;
-    RXTID *rxtid;
-    A_UINT8 i;
-    A_STATUS status = A_OK;
+    struct aggr_info   *p_aggr = NULL;
+    struct rxtid *rxtid;
+    u8 i;
+    int status = 0;
 
     A_PRINTF("In aggr_init..\n");
 
     do {
-        p_aggr = A_MALLOC(sizeof(AGGR_INFO));
+        p_aggr = A_MALLOC(sizeof(struct aggr_info));
         if(!p_aggr) {
             A_PRINTF("Failed to allocate memory for aggr_node\n");
             status = A_ERROR;
@@ -70,10 +70,10 @@ aggr_init(ALLOC_NETBUFS netbuf_allocator)
         }
 
         /* Init timer and data structures */
-        A_MEMZERO(p_aggr, sizeof(AGGR_INFO));
+        A_MEMZERO(p_aggr, sizeof(struct aggr_info));
         p_aggr->aggr_sz = AGGR_SZ_DEFAULT;
         A_INIT_TIMER(&p_aggr->timer, aggr_timeout, p_aggr);
-        p_aggr->timerScheduled = FALSE;
+        p_aggr->timerScheduled = false;
         A_NETBUF_QUEUE_INIT(&p_aggr->freeQ);
 
         p_aggr->netbuf_allocator = netbuf_allocator;
@@ -81,30 +81,30 @@ aggr_init(ALLOC_NETBUFS netbuf_allocator)
 
         for(i = 0; i < NUM_OF_TIDS; i++) {
             rxtid = AGGR_GET_RXTID(p_aggr, i);
-            rxtid->aggr = FALSE;
-            rxtid->progress = FALSE;
-            rxtid->timerMon = FALSE;
+            rxtid->aggr = false;
+            rxtid->progress = false;
+            rxtid->timerMon = false;
             A_NETBUF_QUEUE_INIT(&rxtid->q);
             A_MUTEX_INIT(&rxtid->lock);
         }
-    }while(FALSE);
+    }while(false);
 
     A_PRINTF("going out of aggr_init..status %s\n",
-                    (status == A_OK) ? "OK":"Error");
+                    (status == 0) ? "OK":"Error");
 
-    if(status != A_OK) {
+    if (status) {
         /* Cleanup */
         aggr_module_destroy(p_aggr);
     }
-    return ((status == A_OK) ? p_aggr : NULL);
+    return ((status == 0) ? p_aggr : NULL);
 }
 
 /* utility function to clear rx hold_q for a tid */
 static void
-aggr_delete_tid_state(AGGR_INFO *p_aggr, A_UINT8 tid)
+aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
 {
-    RXTID *rxtid;
-    RXTID_STATS *stats;
+    struct rxtid *rxtid;
+    struct rxtid_stats *stats;
 
     A_ASSERT(tid < NUM_OF_TIDS && p_aggr);
 
@@ -115,9 +115,9 @@ aggr_delete_tid_state(AGGR_INFO *p_aggr, A_UINT8 tid)
         aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO);
     }
 
-    rxtid->aggr = FALSE;
-    rxtid->progress = FALSE;
-    rxtid->timerMon = FALSE;
+    rxtid->aggr = false;
+    rxtid->progress = false;
+    rxtid->timerMon = false;
     rxtid->win_sz = 0;
     rxtid->seq_next = 0;
     rxtid->hold_q_sz = 0;
@@ -127,22 +127,22 @@ aggr_delete_tid_state(AGGR_INFO *p_aggr, A_UINT8 tid)
         rxtid->hold_q = NULL;
     }
 
-    A_MEMZERO(stats, sizeof(RXTID_STATS));
+    A_MEMZERO(stats, sizeof(struct rxtid_stats));
 }
 
 void
 aggr_module_destroy(void *cntxt)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
-    A_UINT8 i, k;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
+    u8 i, k;
     A_PRINTF("%s(): aggr = %p\n",_A_FUNCNAME_, p_aggr);
     A_ASSERT(p_aggr);
 
     if(p_aggr) {
         if(p_aggr->timerScheduled) {
             A_UNTIMEOUT(&p_aggr->timer);
-            p_aggr->timerScheduled = FALSE;
+            p_aggr->timerScheduled = false;
         }
 
         for(i = 0; i < NUM_OF_TIDS; i++) {
@@ -177,7 +177,7 @@ aggr_module_destroy(void *cntxt)
 void
 aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
 
     A_ASSERT(p_aggr && fn && dev);
 
@@ -187,10 +187,10 @@ aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn)
 
 
 void
-aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no)
+aggr_process_bar(void *cntxt, u8 tid, u16 seq_no)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID_STATS *stats;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid_stats *stats;
 
     A_ASSERT(p_aggr);
     stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
@@ -201,11 +201,11 @@ aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no)
 
 
 void
-aggr_recv_addba_req_evt(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_sz)
+aggr_recv_addba_req_evt(void *cntxt, u8 tid, u16 seq_no, u8 win_sz)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
-    RXTID_STATS *stats;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
+    struct rxtid_stats *stats;
 
     A_ASSERT(p_aggr);
     rxtid = AGGR_GET_RXTID(p_aggr, tid);
@@ -249,14 +249,14 @@ aggr_recv_addba_req_evt(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_s
         A_ASSERT(0);
     }
 
-    rxtid->aggr = TRUE;
+    rxtid->aggr = true;
 }
 
 void
-aggr_recv_delba_req_evt(void *cntxt, A_UINT8 tid)
+aggr_recv_delba_req_evt(void *cntxt, u8 tid)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
 
     A_ASSERT(p_aggr);
     A_PRINTF("%s(): tid %d\n", _A_FUNCNAME_, tid);
@@ -269,12 +269,12 @@ aggr_recv_delba_req_evt(void *cntxt, A_UINT8 tid)
 }
 
 static void
-aggr_deque_frms(AGGR_INFO *p_aggr, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 order)
+aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order)
 {
-    RXTID *rxtid;
-    OSBUF_HOLD_Q *node;
-    A_UINT16 idx, idx_end, seq_end;
-    RXTID_STATS *stats;
+    struct rxtid *rxtid;
+    struct osbuf_hold_q *node;
+    u16 idx, idx_end, seq_end;
+    struct rxtid_stats *stats;
 
     A_ASSERT(p_aggr);
     rxtid = AGGR_GET_RXTID(p_aggr, tid);
@@ -334,7 +334,7 @@ aggr_deque_frms(AGGR_INFO *p_aggr, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 order)
 }
 
 static void *
-aggr_get_osbuf(AGGR_INFO *p_aggr)
+aggr_get_osbuf(struct aggr_info *p_aggr)
 {
     void *buf = NULL;
 
@@ -356,11 +356,11 @@ aggr_get_osbuf(AGGR_INFO *p_aggr)
 
 
 static void
-aggr_slice_amsdu(AGGR_INFO *p_aggr, RXTID *rxtid, void **osbuf)
+aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf)
 {
     void *new_buf;
-    A_UINT16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
-    A_UINT8 *framep;
+    u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
+    u8 *framep;
 
     /* Frame format at this point:
      *  [DIX hdr | 802.3 | 802.3 | ... | 802.3]
@@ -397,9 +397,9 @@ aggr_slice_amsdu(AGGR_INFO *p_aggr, RXTID *rxtid, void **osbuf)
             break;
         }
 
-        A_MEMCPY(A_NETBUF_DATA(new_buf), framep, frame_8023_len);
+        memcpy(A_NETBUF_DATA(new_buf), framep, frame_8023_len);
         A_NETBUF_PUT(new_buf, frame_8023_len);
-        if (wmi_dot3_2_dix(new_buf) != A_OK) {
+        if (wmi_dot3_2_dix(new_buf) != 0) {
             A_PRINTF("dot3_2_dix err..\n");
             A_NETBUF_FREE(new_buf);
             break;
@@ -426,14 +426,14 @@ aggr_slice_amsdu(AGGR_INFO *p_aggr, RXTID *rxtid, void **osbuf)
 }
 
 void
-aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu, void **osbuf)
+aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
-    RXTID_STATS *stats;
-    A_UINT16 idx, st, cur, end;
-    A_UINT16 *log_idx;
-    OSBUF_HOLD_Q *node;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
+    struct rxtid_stats *stats;
+    u16 idx, st, cur, end;
+    u16 *log_idx;
+    struct osbuf_hold_q *node;
     PACKET_LOG *log;
 
     A_ASSERT(p_aggr);
@@ -472,7 +472,7 @@ aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu
          * be assumed that the window has moved for some valid reason.
          * Therefore, we dequeue all frames and start fresh.
          */
-        A_UINT16 extended_end;
+        u16 extended_end;
 
         extended_end = (end + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO;
 
@@ -536,17 +536,17 @@ aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu
     aggr_deque_frms(p_aggr, tid, 0, CONTIGUOUS_SEQNO);
 
     if(p_aggr->timerScheduled) {
-        rxtid->progress = TRUE;
+        rxtid->progress = true;
     }else{
         for(idx=0 ; idx<rxtid->hold_q_sz ; idx++) {
             if(rxtid->hold_q[idx].osbuf) {
                 /* there is a frame in the queue and no timer so
                  * start a timer to ensure that the frame doesn't remain
                  * stuck forever. */
-                p_aggr->timerScheduled = TRUE;
+                p_aggr->timerScheduled = true;
                 A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0);
-                rxtid->progress = FALSE;
-                rxtid->timerMon = TRUE;
+                rxtid->progress = false;
+                rxtid->timerMon = true;
                 break;
             }
         }
@@ -561,8 +561,8 @@ aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu
 void
 aggr_reset_state(void *cntxt)
 {
-    A_UINT8 tid;
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
+    u8 tid;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
 
     A_ASSERT(p_aggr);
 
@@ -575,10 +575,10 @@ aggr_reset_state(void *cntxt)
 static void
 aggr_timeout(A_ATH_TIMER arg)
 {
-    A_UINT8 i,j;
-    AGGR_INFO *p_aggr = (AGGR_INFO *)arg;
-    RXTID   *rxtid;
-    RXTID_STATS *stats;
+    u8 i,j;
+    struct aggr_info *p_aggr = (struct aggr_info *)arg;
+    struct rxtid   *rxtid;
+    struct rxtid_stats *stats;
     /*
      * If the q for which the timer was originally started has
      * not progressed then it is necessary to dequeue all the
@@ -588,9 +588,9 @@ aggr_timeout(A_ATH_TIMER arg)
         rxtid = AGGR_GET_RXTID(p_aggr, i);
         stats = AGGR_GET_RXTID_STATS(p_aggr, i);
 
-        if(rxtid->aggr == FALSE ||
-           rxtid->timerMon == FALSE ||
-           rxtid->progress == TRUE) {
+        if(rxtid->aggr == false ||
+           rxtid->timerMon == false ||
+           rxtid->progress == true) {
             continue;
         }
         // dequeue all frames in for this tid
@@ -599,25 +599,25 @@ aggr_timeout(A_ATH_TIMER arg)
         aggr_deque_frms(p_aggr, i, 0, ALL_SEQNO);
     }
 
-    p_aggr->timerScheduled = FALSE;
+    p_aggr->timerScheduled = false;
     // determine whether a new timer should be started.
     for(i = 0; i < NUM_OF_TIDS; i++) {
         rxtid = AGGR_GET_RXTID(p_aggr, i);
 
-        if(rxtid->aggr == TRUE && rxtid->hold_q) {
+        if(rxtid->aggr == true && rxtid->hold_q) {
             for(j = 0 ; j < rxtid->hold_q_sz ; j++)
             {
                 if(rxtid->hold_q[j].osbuf)
                 {
-                    p_aggr->timerScheduled = TRUE;
-                    rxtid->timerMon = TRUE;
-                    rxtid->progress = FALSE;
+                    p_aggr->timerScheduled = true;
+                    rxtid->timerMon = true;
+                    rxtid->progress = false;
                     break;
                 }
             }
 
             if(j >= rxtid->hold_q_sz) {
-                rxtid->timerMon = FALSE;
+                rxtid->timerMon = false;
             }
         }
     }
@@ -630,7 +630,7 @@ aggr_timeout(A_ATH_TIMER arg)
 }
 
 static void
-aggr_dispatch_frames(AGGR_INFO *p_aggr, A_NETBUF_QUEUE_T *q)
+aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q)
 {
     void *osbuf;
 
@@ -642,10 +642,10 @@ aggr_dispatch_frames(AGGR_INFO *p_aggr, A_NETBUF_QUEUE_T *q)
 void
 aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID   *rxtid;
-    RXTID_STATS *stats;
-    A_UINT8 i;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid   *rxtid;
+    struct rxtid_stats *stats;
+    u8 i;
 
     *log_buf = &p_aggr->pkt_log;
     A_PRINTF("\n\n================================================\n");
diff --git a/drivers/staging/ath6kl/wlan/include/ieee80211.h b/drivers/staging/ath6kl/wlan/include/ieee80211.h
index c4fd13f..532ab0e 100644
--- a/drivers/staging/ath6kl/wlan/include/ieee80211.h
+++ b/drivers/staging/ath6kl/wlan/include/ieee80211.h
@@ -68,9 +68,9 @@
 
 
 #define IEEE80211_ADDR_EQ(addr1, addr2)     \
-    (A_MEMCMP(addr1, addr2, IEEE80211_ADDR_LEN) == 0)
+    (memcmp(addr1, addr2, IEEE80211_ADDR_LEN) == 0)
 
-#define IEEE80211_ADDR_COPY(dst,src)    A_MEMCPY(dst,src,IEEE80211_ADDR_LEN)
+#define IEEE80211_ADDR_COPY(dst,src)    memcpy(dst,src,IEEE80211_ADDR_LEN)
 
 #define IEEE80211_KEYBUF_SIZE 16
 #define IEEE80211_MICBUF_SIZE (8+8)  /* space for both tx and rx */
@@ -99,24 +99,24 @@
  * generic definitions for IEEE 802.11 frames
  */
 PREPACK struct ieee80211_frame {
-    A_UINT8    i_fc[2];
-    A_UINT8    i_dur[2];
-    A_UINT8    i_addr1[IEEE80211_ADDR_LEN];
-    A_UINT8    i_addr2[IEEE80211_ADDR_LEN];
-    A_UINT8    i_addr3[IEEE80211_ADDR_LEN];
-    A_UINT8    i_seq[2];
+    u8 i_fc[2];
+    u8 i_dur[2];
+    u8 i_addr1[IEEE80211_ADDR_LEN];
+    u8 i_addr2[IEEE80211_ADDR_LEN];
+    u8 i_addr3[IEEE80211_ADDR_LEN];
+    u8 i_seq[2];
     /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
     /* see below */
 } POSTPACK;
 
 PREPACK struct ieee80211_qosframe {
-    A_UINT8 i_fc[2];
-    A_UINT8 i_dur[2];
-    A_UINT8 i_addr1[IEEE80211_ADDR_LEN];
-    A_UINT8 i_addr2[IEEE80211_ADDR_LEN];
-    A_UINT8 i_addr3[IEEE80211_ADDR_LEN];
-    A_UINT8 i_seq[2];
-    A_UINT8 i_qos[2];
+    u8 i_fc[2];
+    u8 i_dur[2];
+    u8 i_addr1[IEEE80211_ADDR_LEN];
+    u8 i_addr2[IEEE80211_ADDR_LEN];
+    u8 i_addr3[IEEE80211_ADDR_LEN];
+    u8 i_seq[2];
+    u8 i_qos[2];
 } POSTPACK;
 
 #define IEEE80211_FC0_VERSION_MASK          0x03
@@ -320,29 +320,29 @@ typedef enum {
  * WMM/802.11e Tspec Element
  */
 typedef PREPACK struct wmm_tspec_ie_t {
-    A_UINT8     elementId;
-    A_UINT8     len;
-    A_UINT8     oui[3];
-    A_UINT8     ouiType;
-    A_UINT8     ouiSubType;
-    A_UINT8     version;
-    A_UINT16    tsInfo_info;
-    A_UINT8     tsInfo_reserved;
-    A_UINT16    nominalMSDU;
-    A_UINT16    maxMSDU;
-    A_UINT32    minServiceInt;
-    A_UINT32    maxServiceInt;
-    A_UINT32    inactivityInt;
-    A_UINT32    suspensionInt;
-    A_UINT32    serviceStartTime;
-    A_UINT32    minDataRate;
-    A_UINT32    meanDataRate;
-    A_UINT32    peakDataRate;
-    A_UINT32    maxBurstSize;
-    A_UINT32    delayBound;
-    A_UINT32    minPhyRate;
-    A_UINT16    sba;
-    A_UINT16    mediumTime;
+    u8 elementId;
+    u8 len;
+    u8 oui[3];
+    u8 ouiType;
+    u8 ouiSubType;
+    u8 version;
+    u16 tsInfo_info;
+    u8 tsInfo_reserved;
+    u16 nominalMSDU;
+    u16 maxMSDU;
+    u32 minServiceInt;
+    u32 maxServiceInt;
+    u32 inactivityInt;
+    u32 suspensionInt;
+    u32 serviceStartTime;
+    u32 minDataRate;
+    u32 meanDataRate;
+    u32 peakDataRate;
+    u32 maxBurstSize;
+    u32 delayBound;
+    u32 minPhyRate;
+    u16 sba;
+    u16 mediumTime;
 } POSTPACK WMM_TSPEC_IE;
 
 
diff --git a/drivers/staging/ath6kl/wlan/include/ieee80211_node.h b/drivers/staging/ath6kl/wlan/include/ieee80211_node.h
index 683deec..1cb0167 100644
--- a/drivers/staging/ath6kl/wlan/include/ieee80211_node.h
+++ b/drivers/staging/ath6kl/wlan/include/ieee80211_node.h
@@ -55,7 +55,7 @@
 #define IEEE80211_NODE_HASHSIZE 32
 /* simple hash is enough for variation of macaddr */
 #define IEEE80211_NODE_HASH(addr)   \
-    (((const A_UINT8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \
+    (((const u8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \
         IEEE80211_NODE_HASHSIZE)
 
 /*
@@ -71,14 +71,14 @@ struct ieee80211_node_table {
     struct bss              *nt_node_last;  /* information of all nodes */
     struct bss              *nt_hash[IEEE80211_NODE_HASHSIZE];
     const char              *nt_name;   /* for debugging */
-    A_UINT32                nt_scangen; /* gen# for timeout scan */
+    u32 nt_scangen; /* gen# for timeout scan */
 #ifdef THREAD_X
     A_TIMER                 nt_inact_timer;
-    A_UINT8                 isTimerArmed;   /* is the node timer armed */
+    u8 isTimerArmed;   /* is the node timer armed */
 #endif
-    A_UINT32                nt_nodeAge; /* node aging time */
+    u32 nt_nodeAge; /* node aging time */
 #ifdef OS_ROAM_MANAGEMENT
-    A_UINT32                nt_si_gen; /* gen# for scan indication*/
+    u32 nt_si_gen; /* gen# for scan indication*/
 #endif
 };
 
diff --git a/drivers/staging/ath6kl/wlan/src/wlan_node.c b/drivers/staging/ath6kl/wlan/src/wlan_node.c
index 6ec4e48..1a3ac7d 100644
--- a/drivers/staging/ath6kl/wlan/src/wlan_node.c
+++ b/drivers/staging/ath6kl/wlan/src/wlan_node.c
@@ -40,7 +40,7 @@
 
 #ifdef ATH_DEBUG_MODULE
 
-static ATH_DEBUG_MASK_DESCRIPTION wlan_debug_desc[] = {
+static struct ath_debug_mask_description wlan_debug_desc[] = {
     { ATH_DEBUG_WLAN , "General WLAN Node Tracing"},
 };
 
@@ -58,7 +58,7 @@ static void wlan_node_timeout(A_ATH_TIMER arg);
 #endif
 
 static bss_t * _ieee80211_find_node (struct ieee80211_node_table *nt,
-                                     const A_UINT8 *macaddr);
+                                     const u8 *macaddr);
 
 bss_t *
 wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size)
@@ -111,18 +111,18 @@ wlan_node_free(bss_t *ni)
 
 void
 wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
-                const A_UINT8 *macaddr)
+                const u8 *macaddr)
 {
     int hash;
-    A_UINT32 timeoutValue = 0;
+    u32 timeoutValue = 0;
 
-    A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
+    memcpy(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
     hash = IEEE80211_NODE_HASH (macaddr);
     ieee80211_node_initref (ni);     /* mark referenced */
 
     timeoutValue = nt->nt_nodeAge;
 
-    ni->ni_tstamp = A_GET_MS (timeoutValue);
+    ni->ni_tstamp = A_GET_MS (0);
     ni->ni_actcnt = WLAN_NODE_INACT_CNT;
 
     IEEE80211_NODE_LOCK_BH(nt);
@@ -151,7 +151,7 @@ wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
 #ifdef THREAD_X
     if (!nt->isTimerArmed) {
         A_TIMEOUT_MS(&nt->nt_inact_timer, timeoutValue, 0);
-        nt->isTimerArmed = TRUE;
+        nt->isTimerArmed = true;
     }
 #endif
 
@@ -160,7 +160,7 @@ wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
 
 static bss_t *
 _ieee80211_find_node(struct ieee80211_node_table *nt,
-    const A_UINT8 *macaddr)
+    const u8 *macaddr)
 {
     bss_t *ni;
     int hash;
@@ -178,7 +178,7 @@ _ieee80211_find_node(struct ieee80211_node_table *nt,
 }
 
 bss_t *
-wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
+wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr)
 {
     bss_t *ni;
 
@@ -262,7 +262,7 @@ wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
                    void *arg)
 {
     bss_t *ni;
-    A_UINT32 gen;
+    u32 gen;
 
     gen = ++nt->nt_scangen;
 
@@ -299,7 +299,7 @@ wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt)
 
 #ifdef THREAD_X
     A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt);
-    nt->isTimerArmed = FALSE;
+    nt->isTimerArmed = false;
 #endif
     nt->nt_wmip = wmip;
     nt->nt_nodeAge = WLAN_NODE_INACT_TIMEOUT_MSEC;
@@ -316,7 +316,7 @@ wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt)
 }
 
 void
-wlan_set_nodeage(struct ieee80211_node_table *nt, A_UINT32 nodeAge)
+wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge)
 {
     nt->nt_nodeAge = nodeAge;
     return;
@@ -326,7 +326,7 @@ wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt)
 {
 #ifdef THREAD_X
     bss_t *bss, *nextBss;
-    A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
+    u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false;
 
     wmi_get_current_bssid(nt->nt_wmip, myBssid);
 
@@ -334,7 +334,7 @@ wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt)
     while (bss != NULL)
     {
         nextBss = bss->ni_list_next;
-        if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
+        if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
         {
                /*
                 * free up all but the current bss - if set
@@ -346,9 +346,9 @@ wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt)
     }
 #else
     bss_t *bss, *nextBss;
-    A_UINT8 myBssid[IEEE80211_ADDR_LEN];
-    A_UINT32 timeoutValue = 0;
-    A_UINT32 now = A_GET_MS(0);
+    u8 myBssid[IEEE80211_ADDR_LEN];
+    u32 timeoutValue = 0;
+    u32 now = A_GET_MS(0);
     timeoutValue = nt->nt_nodeAge;
 
     wmi_get_current_bssid(nt->nt_wmip, myBssid);
@@ -357,10 +357,10 @@ wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt)
     while (bss != NULL)
     {
         nextBss = bss->ni_list_next;
-        if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
+        if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
         {
 
-            if (bss->ni_tstamp <= now || --bss->ni_actcnt == 0)
+            if (((now - bss->ni_tstamp) > timeoutValue)  || --bss->ni_actcnt == 0)
             {
                /*
                 * free up all but the current bss - if set
@@ -379,8 +379,9 @@ wlan_node_timeout (A_ATH_TIMER arg)
 {
     struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg;
     bss_t *bss, *nextBss;
-    A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
-    A_UINT32 timeoutValue = 0;
+    u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false;
+    u32 timeoutValue = 0;
+    u32 now = A_GET_MS(0);
 
     timeoutValue = nt->nt_nodeAge;
 
@@ -390,10 +391,10 @@ wlan_node_timeout (A_ATH_TIMER arg)
     while (bss != NULL)
     {
         nextBss = bss->ni_list_next;
-        if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
+        if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
         {
 
-            if (bss->ni_tstamp <= A_GET_MS(0))
+            if ((now - bss->ni_tstamp) > timeoutValue)
             {
                /*
                 * free up all but the current bss - if set
@@ -406,7 +407,7 @@ wlan_node_timeout (A_ATH_TIMER arg)
                  * Re-arm timer, only when we have a bss other than
                  * current bss AND it is not aged-out.
                  */
-                reArmTimer = TRUE;
+                reArmTimer = true;
             }
         }
         bss = nextBss;
@@ -431,11 +432,11 @@ wlan_node_table_cleanup(struct ieee80211_node_table *nt)
 }
 
 bss_t *
-wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID)
+wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
 {
     bss_t   *ni = NULL;
-    A_UCHAR *pIESsid = NULL;
+    u8 *pIESsid = NULL;
 
     IEEE80211_NODE_LOCK (nt);
 
@@ -447,22 +448,22 @@ wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
             if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
 
                 //
-                // Step 2.1 : Check MatchSSID is TRUE, if so, return Matched SSID
+                // Step 2.1 : Check MatchSSID is true, if so, return Matched SSID
                 // Profile, otherwise check whether WPA2 or WPA
                 //
-                if (TRUE == bMatchSSID) {
+                if (true == bMatchSSID) {
                     ieee80211_node_incref (ni);  /* mark referenced */
                     IEEE80211_NODE_UNLOCK (nt);
                     return ni;
                 }
 
                 // Step 2 : if SSID matches, check WPA or WPA2
-                if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
+                if (true == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
                     ieee80211_node_incref (ni);  /* mark referenced */
                     IEEE80211_NODE_UNLOCK (nt);
                     return ni;
                 }
-                if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
+                if (false == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
                     ieee80211_node_incref(ni);  /* mark referenced */
                     IEEE80211_NODE_UNLOCK (nt);
                     return ni;
@@ -526,7 +527,7 @@ wlan_node_remove_core (struct ieee80211_node_table *nt, bss_t *ni)
 }
 
 bss_t *
-wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid)
+wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid)
 {
     bss_t *bss, *nextBss;
 
@@ -538,7 +539,7 @@ wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid)
     {
         nextBss = bss->ni_list_next;
 
-        if (A_MEMCMP(bssid, bss->ni_macaddr, 6) == 0)
+        if (memcmp(bssid, bss->ni_macaddr, 6) == 0)
         {
             wlan_node_remove_core (nt, bss);
             IEEE80211_NODE_UNLOCK(nt);
@@ -553,13 +554,13 @@ wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid)
 }
 
 bss_t *
-wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp)
+wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
 {
     bss_t   *ni = NULL;
     bss_t   *best_ni = NULL;
-    A_UCHAR *pIESsid = NULL;
+    u8 *pIESsid = NULL;
 
     IEEE80211_NODE_LOCK (nt);
 
diff --git a/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c b/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c
index f4926f2..9ebfecf 100644
--- a/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c
+++ b/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c
@@ -49,23 +49,23 @@
 
 /* unaligned little endian access */
 #define LE_READ_2(p)                            \
-    ((A_UINT16)                            \
-     ((((A_UINT8 *)(p))[0]      ) | (((A_UINT8 *)(p))[1] <<  8)))
+    ((u16)                            \
+     ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8)))
 
 #define LE_READ_4(p)                            \
-    ((A_UINT32)                            \
-     ((((A_UINT8 *)(p))[0]      ) | (((A_UINT8 *)(p))[1] <<  8) | \
-      (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
+    ((u32)                            \
+     ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8) | \
+      (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
 
 
 static int __inline
-iswpaoui(const A_UINT8 *frm)
+iswpaoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
 }
 
 static int __inline
-iswmmoui(const A_UINT8 *frm)
+iswmmoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
 }
@@ -73,38 +73,38 @@ iswmmoui(const A_UINT8 *frm)
 /* unused functions for now */
 #if 0
 static int __inline
-iswmmparam(const A_UINT8 *frm)
+iswmmparam(const u8 *frm)
 {
     return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
 }
 
 static int __inline
-iswmminfo(const A_UINT8 *frm)
+iswmminfo(const u8 *frm)
 {
     return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE;
 }
 #endif
 
 static int __inline
-isatherosoui(const A_UINT8 *frm)
+isatherosoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
 }
 
 static int __inline
-iswscoui(const A_UINT8 *frm)
+iswscoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
 }
 
-A_STATUS
-wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
+int
+wlan_parse_beacon(u8 *buf, int framelen, struct ieee80211_common_ie *cie)
 {
-    A_UINT8 *frm, *efrm;
-    A_UINT8 elemid_ssid = FALSE;
+    u8 *frm, *efrm;
+    u8 elemid_ssid = false;
 
     frm = buf;
-    efrm = (A_UINT8 *) (frm + framelen);
+    efrm = (u8 *) (frm + framelen);
 
     /*
      * beacon/probe response frame format
@@ -125,8 +125,8 @@ wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
     A_MEMZERO(cie, sizeof(*cie));
 
     cie->ie_tstamp = frm; frm += 8;
-    cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm);  frm += 2;
-    cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm);  frm += 2;
+    cie->ie_beaconInt = A_LE2CPU16(*(u16 *)frm);  frm += 2;
+    cie->ie_capInfo = A_LE2CPU16(*(u16 *)frm);  frm += 2;
     cie->ie_chan = 0;
 
     while (frm < efrm) {
@@ -134,7 +134,7 @@ wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
         case IEEE80211_ELEMID_SSID:
             if (!elemid_ssid) {
                 cie->ie_ssid = frm;
-                elemid_ssid = TRUE;
+                elemid_ssid = true;
             }
             break;
         case IEEE80211_ELEMID_RATES:
@@ -196,5 +196,5 @@ wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
     IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE);
     IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN);
 
-    return A_OK;
+    return 0;
 }
diff --git a/drivers/staging/ath6kl/wlan/src/wlan_utils.c b/drivers/staging/ath6kl/wlan/src/wlan_utils.c
index 1eee7ba..fd05e39 100644
--- a/drivers/staging/ath6kl/wlan/src/wlan_utils.c
+++ b/drivers/staging/ath6kl/wlan/src/wlan_utils.c
@@ -30,8 +30,7 @@
 /*
  * converts ieee channel number to frequency
  */
-A_UINT16
-wlan_ieee2freq(int chan)
+u16 wlan_ieee2freq(int chan)
 {
     if (chan == 14) {
         return 2484;
@@ -48,8 +47,7 @@ wlan_ieee2freq(int chan)
 /*
  * Converts MHz frequency to IEEE channel number.
  */
-A_UINT32
-wlan_freq2ieee(A_UINT16 freq)
+u32 wlan_freq2ieee(u16 freq)
 {
     if (freq == 2484)
         return 14;
diff --git a/drivers/staging/ath6kl/wmi/wmi.c b/drivers/staging/ath6kl/wmi/wmi.c
index 7800778..0ddaee2 100644
--- a/drivers/staging/ath6kl/wmi/wmi.c
+++ b/drivers/staging/ath6kl/wmi/wmi.c
@@ -48,7 +48,7 @@
 
 #ifdef ATH_DEBUG_MODULE
 
-static ATH_DEBUG_MASK_DESCRIPTION wmi_debug_desc[] = {
+static struct ath_debug_mask_description wmi_debug_desc[] = {
     { ATH_DEBUG_WMI , "General WMI Tracing"},
 };
 
@@ -70,134 +70,134 @@ ATH_DEBUG_INSTANTIATE_MODULE_VAR(wmi,
 #define A_DPRINTF   AR_DEBUG_PRINTF
 #endif
 
-static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
                                         int len);
 
-static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
                                         int len);
-static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
                                        int len);
-static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_sync_point(struct wmi_t *wmip);
+static int wmi_sync_point(struct wmi_t *wmip);
 
-static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
                                          int len);
-static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
                                        int len);
-static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
                                              int len);
 
-static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 #ifdef CONFIG_HOST_DSET_SUPPORT
-static A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 #endif /* CONFIG_HOST_DSET_SUPPORT */
 
 
-static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_channel_change_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
                                       int len);
-static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
                                       int len);
-static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
                                       int len);
-static A_STATUS
-wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
+static int
+wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
 
-static A_STATUS
-wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
+static int
+wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
 
-static A_STATUS
-wmi_acm_reject_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
+static int
+wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
 
 #ifdef CONFIG_HOST_GPIO_SUPPORT
-static A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-static A_STATUS
-wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif
 
-static A_STATUS
-wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS
-wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS
-wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_BOOL
-wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_INT32 rateIndex);
+static bool
+wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
 
-static A_STATUS
-wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS
-wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-A_STATUS wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
+int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
                   WMI_SYNC_FLAG syncflag);
 
-A_UINT8 ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, A_UINT32 size);
-A_UINT8 ar6000_get_lower_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, A_UINT32 size);
+u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
+u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
 
 void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
 void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-static A_STATUS wmi_send_rssi_threshold_params(struct wmi_t *wmip,
+static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-static A_STATUS wmi_send_snr_threshold_params(struct wmi_t *wmip,
+static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-static A_STATUS
-wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 
-static A_STATUS wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_dtimexpiry_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 
-static A_STATUS wmi_peer_node_event_rx (struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
                                         int len);
 #ifdef ATH_AR6K_11N_SUPPORT
-static A_STATUS wmi_addba_req_event_rx(struct wmi_t *, A_UINT8 *, int);
-static A_STATUS wmi_addba_resp_event_rx(struct wmi_t *, A_UINT8 *, int);
-static A_STATUS wmi_delba_req_event_rx(struct wmi_t *, A_UINT8 *, int);
-static A_STATUS wmi_btcoex_config_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_btcoex_stats_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
+static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
+static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
+static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif
-static A_STATUS wmi_hci_event_rx(struct wmi_t *, A_UINT8 *, int);
+static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
 
 #ifdef WAPI_ENABLE
-static A_STATUS wmi_wapi_rekey_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 #endif
 
@@ -212,7 +212,7 @@ extern unsigned int processDot11Hdr;
 #endif
 
 int wps_enable;
-static const A_INT32 wmi_rateTable[][2] = {
+static const s32 wmi_rateTable[][2] = {
   //{W/O SGI, with SGI}
     {1000, 1000},
     {2000, 2000},
@@ -244,25 +244,25 @@ static const A_INT32 wmi_rateTable[][2] = {
     {135000, 150000},
     {0, 0}};
 
-#define MODE_A_SUPPORT_RATE_START       ((A_INT32) 4)
-#define MODE_A_SUPPORT_RATE_STOP        ((A_INT32) 11)
+#define MODE_A_SUPPORT_RATE_START       ((s32) 4)
+#define MODE_A_SUPPORT_RATE_STOP        ((s32) 11)
 
 #define MODE_GONLY_SUPPORT_RATE_START   MODE_A_SUPPORT_RATE_START
 #define MODE_GONLY_SUPPORT_RATE_STOP    MODE_A_SUPPORT_RATE_STOP
 
-#define MODE_B_SUPPORT_RATE_START       ((A_INT32) 0)
-#define MODE_B_SUPPORT_RATE_STOP        ((A_INT32) 3)
+#define MODE_B_SUPPORT_RATE_START       ((s32) 0)
+#define MODE_B_SUPPORT_RATE_STOP        ((s32) 3)
 
-#define MODE_G_SUPPORT_RATE_START       ((A_INT32) 0)
-#define MODE_G_SUPPORT_RATE_STOP        ((A_INT32) 11)
+#define MODE_G_SUPPORT_RATE_START       ((s32) 0)
+#define MODE_G_SUPPORT_RATE_STOP        ((s32) 11)
 
-#define MODE_GHT20_SUPPORT_RATE_START   ((A_INT32) 0)
-#define MODE_GHT20_SUPPORT_RATE_STOP    ((A_INT32) 19)
+#define MODE_GHT20_SUPPORT_RATE_START   ((s32) 0)
+#define MODE_GHT20_SUPPORT_RATE_STOP    ((s32) 19)
 
 #define MAX_NUMBER_OF_SUPPORT_RATES     (MODE_GHT20_SUPPORT_RATE_STOP + 1)
 
 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
-const A_UINT8 up_to_ac[]= {
+const u8 up_to_ac[]= {
                 WMM_AC_BE,
                 WMM_AC_BK,
                 WMM_AC_BK,
@@ -277,27 +277,27 @@ const A_UINT8 up_to_ac[]= {
 
 /* This stuff is used when we want a simple layer-3 visibility */
 typedef PREPACK struct _iphdr {
-    A_UINT8     ip_ver_hdrlen;          /* version and hdr length */
-    A_UINT8     ip_tos;                 /* type of service */
-    A_UINT16    ip_len;                 /* total length */
-    A_UINT16    ip_id;                  /* identification */
-    A_INT16     ip_off;                 /* fragment offset field */
+    u8 ip_ver_hdrlen;          /* version and hdr length */
+    u8 ip_tos;                 /* type of service */
+    u16 ip_len;                 /* total length */
+    u16 ip_id;                  /* identification */
+    s16 ip_off;                 /* fragment offset field */
 #define IP_DF 0x4000                    /* dont fragment flag */
 #define IP_MF 0x2000                    /* more fragments flag */
 #define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
-    A_UINT8     ip_ttl;                 /* time to live */
-    A_UINT8     ip_p;                   /* protocol */
-    A_UINT16    ip_sum;                 /* checksum */
-    A_UINT8     ip_src[4];              /* source and dest address */
-    A_UINT8     ip_dst[4];
+    u8 ip_ttl;                 /* time to live */
+    u8 ip_p;                   /* protocol */
+    u16 ip_sum;                 /* checksum */
+    u8 ip_src[4];              /* source and dest address */
+    u8 ip_dst[4];
 } POSTPACK iphdr;
 
 #include "athendpack.h"
 
-static A_INT16 rssi_event_value = 0;
-static A_INT16 snr_event_value = 0;
+static s16 rssi_event_value = 0;
+static s16 snr_event_value = 0;
 
-A_BOOL is_probe_ssid = FALSE;
+bool is_probe_ssid = false;
 
 void *
 wmi_init(void *devt)
@@ -335,7 +335,7 @@ wmi_init(void *devt)
 void
 wmi_qos_state_init(struct wmi_t *wmip)
 {
-    A_UINT8 i;
+    u8 i;
 
     if (wmip == NULL) {
         return;
@@ -391,11 +391,11 @@ wmi_shutdown(struct wmi_t *wmip)
  *  Assumes the entire DIX header is contigous and that there is
  *  enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
  */
-A_STATUS
+int
 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
 {
-    A_UINT8          *datap;
-    A_UINT16         typeorlen;
+    u8 *datap;
+    u16 typeorlen;
     ATH_MAC_HDR      macHdr;
     ATH_LLC_SNAP_HDR *llcHdr;
 
@@ -409,33 +409,33 @@ wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
 
     datap = A_NETBUF_DATA(osbuf);
 
-    typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
+    typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
 
     if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
         /*
          * packet is already in 802.3 format - return success
          */
         A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
-        return (A_OK);
+        return (0);
     }
 
     /*
      * Save mac fields and length to be inserted later
      */
-    A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);
-    A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
+    memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
+    memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
     macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
                                   sizeof(ATH_LLC_SNAP_HDR));
 
     /*
      * Make room for LLC+SNAP headers
      */
-    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
         return A_NO_MEMORY;
     }
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
+    memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
 
     llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
     llcHdr->dsap      = 0xAA;
@@ -446,19 +446,19 @@ wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
     llcHdr->orgCode[2] = 0x0;
     llcHdr->etherType = typeorlen;
 
-    return (A_OK);
+    return (0);
 }
 
-A_STATUS wmi_meta_add(struct wmi_t *wmip, void *osbuf, A_UINT8 *pVersion,void *pTxMetaS)
+int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
 {
     switch(*pVersion){
 	case 0:
-    		return (A_OK);
+		return (0);
     	case WMI_META_VERSION_1:
 	        {
         	WMI_TX_META_V1     *pV1= NULL;
         	A_ASSERT(osbuf != NULL);
-        	if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != A_OK) {
+		if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
             		return A_NO_MEMORY;
         	}
 
@@ -473,44 +473,44 @@ A_STATUS wmi_meta_add(struct wmi_t *wmip, void *osbuf, A_UINT8 *pVersion,void *p
         	A_ASSERT(pVersion != NULL);
         	/* the version must be used to populate the meta field of the WMI_DATA_HDR */
         	*pVersion = WMI_META_VERSION_1;
-        	return (A_OK);
+		return (0);
     		}
 #ifdef CONFIG_CHECKSUM_OFFLOAD
 	case WMI_META_VERSION_2:
 		{
      		WMI_TX_META_V2 *pV2 ;
         	A_ASSERT(osbuf != NULL);
-        	if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != A_OK) {
+		if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
             		return A_NO_MEMORY;
         	}
          	pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
-         	A_MEMCPY(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
-         	return (A_OK);
+         	memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
+		return (0);
     		}
 #endif
 	default:
-		return (A_OK);
+		return (0);
     }
 }
 
 /* Adds a WMI data header */
-A_STATUS
-wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_BOOL bMoreData,
-                    WMI_DATA_HDR_DATA_TYPE data_type,A_UINT8 metaVersion, void *pTxMetaS)
+int
+wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
+                    WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
 {
     WMI_DATA_HDR     *dtHdr;
-//    A_UINT8 metaVersion = 0;
-    A_STATUS status;
+//    u8 metaVersion = 0;
+    int status;
 
     A_ASSERT(osbuf != NULL);
 
     /* adds the meta data field after the wmi data hdr. If metaVersion
      * is returns 0 then no meta field was added. */
-    if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != A_OK) {
+    if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
         return status;
     }
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
         return A_NO_MEMORY;
     }
 
@@ -527,19 +527,19 @@ wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_BOOL bMoreD
     WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
     //dtHdr->rssi = 0;
 
-    return (A_OK);
+    return (0);
 }
 
 
-A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 layer2Priority, A_BOOL wmmEnabled)
+u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
 {
-    A_UINT8         *datap;
-    A_UINT8         trafficClass = WMM_AC_BE;
-    A_UINT16        ipType = IP_ETHERTYPE;
+    u8 *datap;
+    u8 trafficClass = WMM_AC_BE;
+    u16 ipType = IP_ETHERTYPE;
     WMI_DATA_HDR    *dtHdr;
-    A_BOOL           streamExists = FALSE;
-    A_UINT8        userPriority;
-    A_UINT32            hdrsize, metasize;
+    u8 streamExists = 0;
+    u8 userPriority;
+    u32 hdrsize, metasize;
     ATH_LLC_SNAP_HDR    *llcHdr;
 
     WMI_CREATE_PSTREAM_CMD  cmd;
@@ -564,7 +564,7 @@ A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 la
     {
         if (processDot11Hdr)
         {
-             hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32));
+             hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
              llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
                           hdrsize);
 
@@ -580,7 +580,7 @@ A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 la
         {
             /* Extract the endpoint info from the TOS field in the IP header */
 
-            userPriority = wmi_determine_userPriority (((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
+            userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
         }
         else
         {
@@ -621,15 +621,15 @@ A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 la
     return trafficClass;
 }
 
-A_STATUS
+int
 wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
 {
-    A_UINT8          *datap;
-    A_UINT16         typeorlen;
+    u8 *datap;
+    u16 typeorlen;
     ATH_MAC_HDR      macHdr;
     ATH_LLC_SNAP_HDR *llcHdr;
     struct           ieee80211_frame *wh;
-    A_UINT32         hdrsize;
+    u32 hdrsize;
 
     A_ASSERT(osbuf != NULL);
 
@@ -641,7 +641,7 @@ wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
 
     datap = A_NETBUF_DATA(osbuf);
 
-    typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
+    typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
 
     if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
 /*
@@ -654,8 +654,8 @@ wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
     /*
      * Save mac fields and length to be inserted later
      */
-    A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);
-    A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
+    memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
+    memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
     macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
                                   sizeof(ATH_LLC_SNAP_HDR));
 
@@ -664,7 +664,7 @@ wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
     /*
      * Make room for LLC+SNAP headers
      */
-    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
         return A_NO_MEMORY;
     }
     datap = A_NETBUF_DATA(osbuf);
@@ -682,8 +682,8 @@ AddDot11Hdr:
     /* Make room for 802.11 hdr */
     if (wmip->wmi_is_wmm_enabled)
     {
-        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32));
-        if (A_NETBUF_PUSH(osbuf, hdrsize) != A_OK)
+        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
+        if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
         {
             return A_NO_MEMORY;
         }
@@ -692,8 +692,8 @@ AddDot11Hdr:
     }
     else
     {
-        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(A_UINT32));
-        if (A_NETBUF_PUSH(osbuf, hdrsize) != A_OK)
+        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
+        if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
         {
             return A_NO_MEMORY;
         }
@@ -710,18 +710,18 @@ AddDot11Hdr:
         IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
     }
 
-    return (A_OK);
+    return (0);
 }
 
-A_STATUS
+int
 wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
 {
-    A_UINT8          *datap;
+    u8 *datap;
     struct           ieee80211_frame *pwh,wh;
-    A_UINT8          type,subtype;
+    u8 type,subtype;
     ATH_LLC_SNAP_HDR *llcHdr;
     ATH_MAC_HDR      macHdr;
-    A_UINT32         hdrsize;
+    u32 hdrsize;
 
     A_ASSERT(osbuf != NULL);
     datap = A_NETBUF_DATA(osbuf);
@@ -730,11 +730,11 @@ wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
     type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
     subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 
-    A_MEMCPY((A_UINT8 *)&wh, datap, sizeof(struct ieee80211_frame));
+    memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
 
     /* strip off the 802.11 hdr*/
     if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
-        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32));
+        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
         A_NETBUF_PULL(osbuf, hdrsize);
     } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
         A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
@@ -772,44 +772,44 @@ wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
     A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY (datap, &macHdr, sizeof(ATH_MAC_HDR));
+    memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
 
-    return A_OK;
+    return 0;
 }
 
 /*
  *  performs 802.3 to DIX encapsulation for received packets.
  *  Assumes the entire 802.3 header is contigous.
  */
-A_STATUS
+int
 wmi_dot3_2_dix(void *osbuf)
 {
-    A_UINT8          *datap;
+    u8 *datap;
     ATH_MAC_HDR      macHdr;
     ATH_LLC_SNAP_HDR *llcHdr;
 
     A_ASSERT(osbuf != NULL);
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR));
+    memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
     llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
     macHdr.typeOrLen = llcHdr->etherType;
 
-    if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
+    if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
         return A_NO_MEMORY;
     }
 
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
+    memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
 
-    return (A_OK);
+    return (0);
 }
 
 /*
  * Removes a WMI data header
  */
-A_STATUS
+int
 wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
 {
     A_ASSERT(osbuf != NULL);
@@ -826,14 +826,14 @@ wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
 /*
  * WMI Extended Event received from Target.
  */
-A_STATUS
+int
 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
 {
     WMIX_CMD_HDR *cmd;
-    A_UINT16 id;
-    A_UINT8 *datap;
-    A_UINT32 len;
-    A_STATUS status = A_OK;
+    u16 id;
+    u8 *datap;
+    u32 len;
+    int status = 0;
 
     if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
@@ -844,7 +844,7 @@ wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
     cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
     id = cmd->commandId;
 
-    if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
         wmip->wmi_stats.cmd_len_err++;
         return A_ERROR;
@@ -901,16 +901,16 @@ wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
 /*
  * Control Path
  */
-A_UINT32 cmdRecvNum;
+u32 cmdRecvNum;
 
-A_STATUS
+int
 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
 {
     WMI_CMD_HDR *cmd;
-    A_UINT16 id;
-    A_UINT8 *datap;
-    A_UINT32 len, i, loggingReq;
-    A_STATUS status = A_OK;
+    u16 id;
+    u8 *datap;
+    u32 len, i, loggingReq;
+    int status = 0;
 
     A_ASSERT(osbuf != NULL);
     if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
@@ -923,7 +923,7 @@ wmi_control_rx(struct wmi_t *wmip, void *osbuf)
     cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
     id = cmd->commandId;
 
-    if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
         A_NETBUF_FREE(osbuf);
         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
         wmip->wmi_stats.cmd_len_err++;
@@ -999,7 +999,7 @@ wmi_control_rx(struct wmi_t *wmip, void *osbuf)
             */
             WMI_BSS_INFO_HDR2 bih2;
             WMI_BSS_INFO_HDR *bih;
-            A_MEMCPY(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
+            memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
 
             A_NETBUF_PUSH(osbuf, 4);
             datap = A_NETBUF_DATA(osbuf);
@@ -1011,7 +1011,7 @@ wmi_control_rx(struct wmi_t *wmip, void *osbuf)
             bih->snr = bih2.snr;
             bih->rssi = bih2.snr - 95;
             bih->ieMask = bih2.ieMask;
-            A_MEMCPY(bih->bssid, bih2.bssid, ATH_MAC_LEN);
+            memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
 
             status = wmi_bssInfo_event_rx(wmip, datap, len);
             A_WMI_SEND_GENERIC_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
@@ -1192,7 +1192,7 @@ wmi_control_rx(struct wmi_t *wmip, void *osbuf)
 }
 
 /* Send a "simple" wmi command -- one with no arguments */
-static A_STATUS
+static int
 wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
 {
     void *osbuf;
@@ -1209,7 +1209,7 @@ wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
    Enabling this command only if GPIO or profiling support is enabled.
    This is to suppress warnings on some platforms */
 #if defined(CONFIG_HOST_GPIO_SUPPORT) || defined(CONFIG_TARGET_PROFILE_SUPPORT)
-static A_STATUS
+static int
 wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
 {
     void *osbuf;
@@ -1223,8 +1223,8 @@ wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
 }
 #endif
 
-static A_STATUS
-wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
 
@@ -1232,36 +1232,36 @@ wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
         return A_EINVAL;
     }
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-    wmip->wmi_ready = TRUE;
+    wmip->wmi_ready = true;
     A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
                       ev->sw_version, ev->abi_version);
 
-    return A_OK;
+    return 0;
 }
 
 #define LE_READ_4(p)                            \
-    ((A_UINT32)                            \
-     ((((A_UINT8 *)(p))[0]      ) | (((A_UINT8 *)(p))[1] <<  8) | \
-      (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
+    ((u32)                            \
+     ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8) | \
+      (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
 
 static int __inline
-iswmmoui(const A_UINT8 *frm)
+iswmmoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
 }
 
 static int __inline
-iswmmparam(const A_UINT8 *frm)
+iswmmparam(const u8 *frm)
 {
     return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
 }
 
 
-static A_STATUS
-wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CONNECT_EVENT *ev;
-    A_UINT8 *pie,*peie;
+    u8 *pie,*peie;
 
     if (len < sizeof(WMI_CONNECT_EVENT))
     {
@@ -1275,13 +1275,13 @@ wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
         ev->bssid[0], ev->bssid[1], ev->bssid[2],
         ev->bssid[3], ev->bssid[4], ev->bssid[5]));
 
-    A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
+    memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
 
     /* initialize pointer to start of assoc rsp IEs */
     pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
-                            sizeof(A_UINT16)  +  /* capinfo*/
-                            sizeof(A_UINT16)  +  /* status Code */
-                            sizeof(A_UINT16)  ;  /* associd */
+                            sizeof(u16)  +  /* capinfo*/
+                            sizeof(u16)  +  /* status Code */
+                            sizeof(u16)  ;  /* associd */
 
     /* initialize pointer to end of assoc rsp IEs */
     peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
@@ -1295,7 +1295,7 @@ wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                 {
                     if(iswmmparam (pie))
                     {
-                        wmip->wmi_is_wmm_enabled = TRUE;
+                        wmip->wmi_is_wmm_enabled = true;
                     }
                 }
             break;
@@ -1314,11 +1314,11 @@ wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                          ev->assocReqLen, ev->assocRespLen,
                          ev->assocInfo);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_REG_DOMAIN_EVENT *ev;
 
@@ -1329,11 +1329,11 @@ wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_NEIGHBOR_REPORT_EVENT *ev;
     int numAps;
@@ -1350,11 +1350,11 @@ wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_DISCONNECT_EVENT *ev;
     wmip->wmi_traffic_class = 100;
@@ -1368,18 +1368,18 @@ wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
 
-    wmip->wmi_is_wmm_enabled = FALSE;
+    wmip->wmi_is_wmm_enabled = false;
     wmip->wmi_pair_crypto_type = NONE_CRYPT;
     wmip->wmi_grp_crypto_type = NONE_CRYPT;
 
     A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
                             ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_peer_node_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_PEER_NODE_EVENT *ev;
 
@@ -1395,11 +1395,11 @@ wmi_peer_node_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TKIP_MICERR_EVENT *ev;
 
@@ -1411,19 +1411,19 @@ wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     ev = (WMI_TKIP_MICERR_EVENT *)datap;
     A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     bss_t *bss = NULL;
     WMI_BSS_INFO_HDR *bih;
-    A_UINT8 *buf;
-    A_UINT32 nodeCachingAllowed = 1;
-    A_UCHAR cached_ssid_len = 0;
-    A_UCHAR cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
-    A_UINT8 beacon_ssid_len = 0;
+    u8 *buf;
+    u32 nodeCachingAllowed = 1;
+    u8 cached_ssid_len = 0;
+    u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
+    u8 beacon_ssid_len = 0;
 
     if (len <= sizeof(WMI_BSS_INFO_HDR)) {
         return A_EINVAL;
@@ -1434,7 +1434,7 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     if (bih->rssi > 0) {
         if (NULL == bss)
-            return A_OK;  //no node found in the table, just drop the node with incorrect RSSI
+            return 0;  //no node found in the table, just drop the node with incorrect RSSI
         else
             bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
     }
@@ -1443,14 +1443,14 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     /* What is driver config for wlan node caching? */
     if(ar6000_get_driver_cfg(wmip->wmi_devt,
                     AR6000_DRIVER_CFG_GET_WLANNODECACHING,
-                    &nodeCachingAllowed) != A_OK) {
+                    &nodeCachingAllowed) != 0) {
         wmi_node_return(wmip, bss);
         return A_EINVAL;
     }
 
     if(!nodeCachingAllowed) {
         wmi_node_return(wmip, bss);
-        return A_OK;
+        return 0;
     }
 
     buf = datap + sizeof(WMI_BSS_INFO_HDR);
@@ -1462,7 +1462,7 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
         wmi_node_return(wmip, bss);
-        return A_OK;
+        return 0;
     }
 
     if (bss != NULL) {
@@ -1475,9 +1475,9 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
         /* In case of hidden AP, beacon will not have ssid,
          * but a directed probe response will have it,
          * so cache the probe-resp-ssid if already present. */
-        if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
+        if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
         {
-            A_UCHAR *ie_ssid;
+            u8 *ie_ssid;
 
             ie_ssid = bss->ni_cie.ie_ssid;
             if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
@@ -1510,7 +1510,7 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
 
     /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
-    if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
+    if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
         (0 != cached_ssid_len) &&
         (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
     {
@@ -1529,16 +1529,16 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     /* In case of hidden AP, beacon will not have ssid,
      * but a directed probe response will have it,
      * so place the cached-ssid(probe-resp) in the bssinfo. */
-    if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
+    if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
          (0 != cached_ssid_len) &&
          (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
     {
-        A_UINT8 *ni_buf = bss->ni_buf;
+        u8 *ni_buf = bss->ni_buf;
         int buf_len = len;
 
         /* copy the first 14 bytes such as
          * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
-        A_MEMCPY(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
+        memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
 
         ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
         ni_buf += (SSID_IE_LEN_INDEX + 1);
@@ -1547,7 +1547,7 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
         buf_len -= (SSID_IE_LEN_INDEX + 1);
 
         /* copy the cached ssid */
-        A_MEMCPY(ni_buf, cached_ssid_buf, cached_ssid_len);
+        memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
         ni_buf += cached_ssid_len;
 
         buf += beacon_ssid_len;
@@ -1557,13 +1557,13 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
             buf_len -= (cached_ssid_len - beacon_ssid_len);
 
         /* now copy the rest of bytes */
-        A_MEMCPY(ni_buf, buf, buf_len);
+        memcpy(ni_buf, buf, buf_len);
     }
     else
-        A_MEMCPY(bss->ni_buf, buf, len);
+        memcpy(bss->ni_buf, buf, len);
 
     bss->ni_framelen = len;
-    if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
+    if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
         wlan_node_free(bss);
         return A_EINVAL;
     }
@@ -1575,15 +1575,15 @@ wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     bss->ni_cie.ie_chan = bih->channel;
     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     bss_t *bss;
     WMI_OPT_RX_INFO_HDR *bih;
-    A_UINT8 *buf;
+    u8 *buf;
 
     if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
         return A_EINVAL;
@@ -1614,17 +1614,17 @@ wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     bss->ni_snr        = bih->snr;
     bss->ni_cie.ie_chan = bih->channel;
     A_ASSERT(bss->ni_buf != NULL);
-    A_MEMCPY(bss->ni_buf, buf, len);
+    memcpy(bss->ni_buf, buf, len);
     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
 
-    return A_OK;
+    return 0;
 }
 
     /* This event indicates inactivity timeout of a fatpipe(pstream)
      * at the target
      */
-static A_STATUS
-wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_PSTREAM_TIMEOUT_EVENT *ev;
 
@@ -1650,15 +1650,15 @@ wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
         /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
     A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_BIT_RATE_REPLY *reply;
-    A_INT32 rate;
-    A_UINT32 sgi,index;
+    s32 rate;
+    u32 sgi,index;
     /* 54149:
      * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
      * since there is difference in the length and to avoid returning
@@ -1671,7 +1671,7 @@ wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     A_DPRINTF(DBG_WMI,
         (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
 
-    if (reply->rateIndex == (A_INT8) RATE_AUTO) {
+    if (reply->rateIndex == (s8) RATE_AUTO) {
         rate = RATE_AUTO;
     } else {
         // the SGI state is stored as the MSb of the rateIndex
@@ -1681,11 +1681,11 @@ wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     }
 
     A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_FIX_RATES_REPLY *reply;
 
@@ -1698,11 +1698,11 @@ wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CHANNEL_LIST_REPLY *reply;
 
@@ -1715,11 +1715,11 @@ wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
                           reply->channelList);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TX_PWR_REPLY *reply;
 
@@ -1731,10 +1731,10 @@ wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
 
-    return A_OK;
+    return 0;
 }
-static A_STATUS
-wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_GET_KEEPALIVE_CMD *reply;
 
@@ -1746,12 +1746,12 @@ wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_DSETOPENREQ_EVENT *dsetopenreq;
 
@@ -1767,12 +1767,12 @@ wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                         dsetopenreq->targ_reply_fn,
                         dsetopenreq->targ_reply_arg);
 
-    return A_OK;
+    return 0;
 }
 
 #ifdef CONFIG_HOST_DSET_SUPPORT
-static A_STATUS
-wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_DSETCLOSE_EVENT *dsetclose;
 
@@ -1784,11 +1784,11 @@ wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
     A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_DSETDATAREQ_EVENT *dsetdatareq;
 
@@ -1806,23 +1806,23 @@ wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                          dsetdatareq->targ_reply_fn,
                          dsetdatareq->targ_reply_arg);
 
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_HOST_DSET_SUPPORT */
 
-static A_STATUS
-wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_SCAN_COMPLETE_EVENT *ev;
 
     ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
-    if ((A_STATUS)ev->status == A_OK) {
+    if ((int)ev->status == 0) {
         wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
     }
-    A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (A_STATUS) ev->status);
-    is_probe_ssid = FALSE;
+    A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
+    is_probe_ssid = false;
 
-    return A_OK;
+    return 0;
 }
 
 /*
@@ -1832,8 +1832,8 @@ wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
  * Behavior of target after wmi error event is undefined.
  * A reset is recommended.
  */
-static A_STATUS
-wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CMD_ERROR_EVENT *ev;
 
@@ -1851,30 +1851,30 @@ wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
         break;
     }
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_RSSI_THRESHOLD_EVENT *reply;
     WMI_RSSI_THRESHOLD_VAL newThreshold;
     WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
     SQ_THRESHOLD_PARAMS *sq_thresh =
            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
-    A_UINT8 upper_rssi_threshold, lower_rssi_threshold;
-    A_INT16 rssi;
+    u8 upper_rssi_threshold, lower_rssi_threshold;
+    s16 rssi;
 
     if (len < sizeof(*reply)) {
         return A_EINVAL;
@@ -1959,19 +1959,19 @@ wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     rssi_event_value = rssi;
 
-    if (wmi_send_rssi_threshold_params(wmip, &cmd) != A_OK) {
+    if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
         A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
                   DBGARG));
     }
 
     A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TARGET_ERROR_REPORT_EVENT *reply;
 
@@ -1983,15 +1983,15 @@ wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CAC_EVENT *reply;
     WMM_TSPEC_IE *tspec_ie;
-    A_UINT16 activeTsids;
+    u16 activeTsids;
 
     if (len < sizeof(*reply)) {
         return A_EINVAL;
@@ -2008,7 +2008,7 @@ wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                 (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
     }
     else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
-        A_UINT8 i;
+        u8 i;
 
         /* following assumes that there is only one outstanding ADDTS request
            when this event is received */
@@ -2030,7 +2030,7 @@ wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
          * for delete qos stream from AP
          */
     else if (reply->cac_indication == CAC_INDICATION_DELETE) {
-        A_UINT8 tsid = 0;
+        u8 tsid = 0;
 
         tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
         tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
@@ -2053,11 +2053,11 @@ wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                 reply->cac_indication, reply->statusCode,
                 reply->tspecSuggestion);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_channel_change_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CHANNEL_CHANGE_EVENT *reply;
 
@@ -2070,11 +2070,11 @@ wmi_channel_change_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
                                reply->newChannel);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_HB_CHALLENGE_RESP_EVENT *reply;
 
@@ -2086,11 +2086,11 @@ wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TARGET_ROAM_TBL *reply;
 
@@ -2102,11 +2102,11 @@ wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TARGET_ROAM_DATA *reply;
 
@@ -2118,11 +2118,11 @@ wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
         return A_EINVAL;
@@ -2131,19 +2131,19 @@ wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_SNR_THRESHOLD_EVENT *reply;
     SQ_THRESHOLD_PARAMS *sq_thresh =
            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
     WMI_SNR_THRESHOLD_VAL newThreshold;
     WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
-    A_UINT8 upper_snr_threshold, lower_snr_threshold;
-    A_INT16 snr;
+    u8 upper_snr_threshold, lower_snr_threshold;
+    s16 snr;
 
     if (len < sizeof(*reply)) {
         return A_EINVAL;
@@ -2218,17 +2218,17 @@ wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     snr_event_value = snr;
 
-    if (wmi_send_snr_threshold_params(wmip, &cmd) != A_OK) {
+    if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
         A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
                   DBGARG));
     }
     A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_LQ_THRESHOLD_EVENT *reply;
 
@@ -2242,16 +2242,16 @@ wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                                 (WMI_LQ_THRESHOLD_VAL) reply->range,
                                 reply->lq);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
-    A_UINT16 ap_info_entry_size;
+    u16 ap_info_entry_size;
     WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
     WMI_AP_INFO_V1 *ap_info_v1;
-    A_UINT8 i;
+    u8 i;
 
     if (len < sizeof(WMI_APLIST_EVENT)) {
         return A_EINVAL;
@@ -2283,24 +2283,24 @@ wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
                    ap_info_v1->channel));
         ap_info_v1++;
     }
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
-    A_UINT32 dropped;
+    u32 dropped;
 
-    dropped = *((A_UINT32 *)datap);
+    dropped = *((u32 *)datap);
     datap += sizeof(dropped);
     len -= sizeof(dropped);
-    A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (A_INT8*)datap, len);
-    return A_OK;
+    A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
+    return 0;
 }
 
 #ifdef CONFIG_HOST_GPIO_SUPPORT
-static A_STATUS
-wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap;
 
@@ -2310,11 +2310,11 @@ wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap;
 
@@ -2324,17 +2324,17 @@ wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_GPIO_ACK_RX();
 
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
@@ -2342,11 +2342,11 @@ wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
  * Called to send a wmi command. Command specific data is already built
  * on osbuf and current osbuf->data points to it.
  */
-A_STATUS
+int
 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
                WMI_SYNC_FLAG syncflag)
 {
-    A_STATUS status;
+    int status;
 #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
     WMI_CMD_HDR         *cHdr;
     HTC_ENDPOINT_ID     eid  = wmip->wmi_endpoint_id;
@@ -2366,20 +2366,20 @@ wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
         wmi_sync_point(wmip);
     }
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
         A_NETBUF_FREE(osbuf);
         return A_NO_MEMORY;
     }
 
     cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
-    cHdr->commandId = (A_UINT16) cmdId;
+    cHdr->commandId = (u16) cmdId;
     cHdr->info1 = 0; // added for virtual interface
 
     /*
      * Only for OPT_TX_CMD, use BE endpoint.
      */
     if (IS_OPT_TX_CMD(cmdId)) {
-        if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, FALSE, FALSE,0,NULL)) != A_OK) {
+        if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
             A_NETBUF_FREE(osbuf);
             return status;
         }
@@ -2394,34 +2394,34 @@ wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
          */
         wmi_sync_point(wmip);
     }
-    return (A_OK);
+    return (0);
 #undef IS_OPT_TX_CMD
 }
 
-A_STATUS
+int
 wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
                   WMI_SYNC_FLAG syncflag)
 {
     WMIX_CMD_HDR     *cHdr;
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
         A_NETBUF_FREE(osbuf);
         return A_NO_MEMORY;
     }
 
     cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
-    cHdr->commandId = (A_UINT32) cmdId;
+    cHdr->commandId = (u32) cmdId;
 
     return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
 }
 
-A_STATUS
+int
 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
                 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
-                CRYPTO_TYPE pairwiseCrypto, A_UINT8 pairwiseCryptoLen,
-                CRYPTO_TYPE groupCrypto, A_UINT8 groupCryptoLen,
-                int ssidLength, A_UCHAR *ssid,
-                A_UINT8 *bssid, A_UINT16 channel, A_UINT32 ctrl_flags)
+                CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
+                CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
+                int ssidLength, u8 *ssid,
+                u8 *bssid, u16 channel, u32 ctrl_flags)
 {
     void *osbuf;
     WMI_CONNECT_CMD *cc;
@@ -2446,7 +2446,7 @@ wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
 
     if (ssidLength)
     {
-        A_MEMCPY(cc->ssid, ssid, ssidLength);
+        memcpy(cc->ssid, ssid, ssidLength);
     }
 
     cc->ssidLength          = ssidLength;
@@ -2461,7 +2461,7 @@ wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
     cc->ctrl_flags          = ctrl_flags;
 
     if (bssid != NULL) {
-        A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
+        memcpy(cc->bssid, bssid, ATH_MAC_LEN);
     }
 
     wmip->wmi_pair_crypto_type  = pairwiseCrypto;
@@ -2470,8 +2470,8 @@ wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
     return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel)
+int
+wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
 {
     void *osbuf;
     WMI_RECONNECT_CMD *cc;
@@ -2490,16 +2490,16 @@ wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel)
     cc->channel = channel;
 
     if (bssid != NULL) {
-        A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
+        memcpy(cc->bssid, bssid, ATH_MAC_LEN);
     }
 
     return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_disconnect_cmd(struct wmi_t *wmip)
 {
-    A_STATUS status;
+    int status;
     wmip->wmi_traffic_class = 100;
 
     /* Bug fix for 24817(elevator bug) - the disconnect command does not
@@ -2509,15 +2509,15 @@ wmi_disconnect_cmd(struct wmi_t *wmip)
     return status;
 }
 
-A_STATUS
+int
 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
-                  A_BOOL forceFgScan, A_BOOL isLegacy,
-                  A_UINT32 homeDwellTime, A_UINT32 forceScanInterval,
-                  A_INT8 numChan, A_UINT16 *channelList)
+                  u32 forceFgScan, u32 isLegacy,
+                  u32 homeDwellTime, u32 forceScanInterval,
+                  s8 numChan, u16 *channelList)
 {
     void *osbuf;
     WMI_START_SCAN_CMD *sc;
-    A_INT8 size;
+    s8 size;
 
     size = sizeof (*sc);
 
@@ -2529,7 +2529,7 @@ wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
         if (numChan > WMI_MAX_CHANNELS) {
             return A_EINVAL;
         }
-        size += sizeof(A_UINT16) * (numChan - 1);
+        size += sizeof(u16) * (numChan - 1);
     }
 
     osbuf = A_NETBUF_ALLOC(size);
@@ -2547,19 +2547,19 @@ wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
     sc->forceScanInterval = forceScanInterval;
     sc->numChannels = numChan;
     if (numChan) {
-        A_MEMCPY(sc->channelList, channelList, numChan * sizeof(A_UINT16));
+        memcpy(sc->channelList, channelList, numChan * sizeof(u16));
     }
 
     return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
-                   A_UINT16 fg_end_sec, A_UINT16 bg_sec,
-                   A_UINT16 minact_chdw_msec, A_UINT16 maxact_chdw_msec,
-                   A_UINT16 pas_chdw_msec,
-                   A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
-                   A_UINT32 max_dfsch_act_time, A_UINT16 maxact_scan_per_ssid)
+int
+wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
+                   u16 fg_end_sec, u16 bg_sec,
+                   u16 minact_chdw_msec, u16 maxact_chdw_msec,
+                   u16 pas_chdw_msec,
+                   u8 shScanRatio, u8 scanCtrlFlags,
+                   u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
 {
     void *osbuf;
     WMI_SCAN_PARAMS_CMD *sc;
@@ -2588,8 +2588,8 @@ wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask)
+int
+wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
 {
     void *osbuf;
     WMI_BSS_FILTER_CMD *cmd;
@@ -2614,9 +2614,9 @@ wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
-                   A_UINT8 ssidLength, A_UCHAR *ssid)
+int
+wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
+                   u8 ssidLength, u8 *ssid)
 {
     void *osbuf;
     WMI_PROBED_SSID_CMD *cmd;
@@ -2635,7 +2635,7 @@ wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
     }
 
     if (flag & SPECIFIC_SSID_FLAG) {
-        is_probe_ssid = TRUE;
+        is_probe_ssid = true;
     }
 
     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
@@ -2650,14 +2650,14 @@ wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
     cmd->entryIndex = index;
     cmd->flag       = flag;
     cmd->ssidLength = ssidLength;
-    A_MEMCPY(cmd->ssid, ssid, ssidLength);
+    memcpy(cmd->ssid, ssid, ssidLength);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons)
+int
+wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
 {
     void *osbuf;
     WMI_LISTEN_INT_CMD *cmd;
@@ -2678,8 +2678,8 @@ wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 lis
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons)
+int
+wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
 {
     void *osbuf;
     WMI_BMISS_TIME_CMD *cmd;
@@ -2700,13 +2700,13 @@ wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
-                     A_UINT8 ieLen, A_UINT8 *ieInfo)
+int
+wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
+                     u8 ieLen, u8 *ieInfo)
 {
     void *osbuf;
     WMI_SET_ASSOC_INFO_CMD *cmd;
-    A_UINT16 cmdLen;
+    u16 cmdLen;
 
     cmdLen = sizeof(*cmd) + ieLen - 1;
     osbuf = A_NETBUF_ALLOC(cmdLen);
@@ -2720,14 +2720,14 @@ wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
     A_MEMZERO(cmd, cmdLen);
     cmd->ieType = ieType;
     cmd->bufferSize = ieLen;
-    A_MEMCPY(cmd->assocInfo, ieInfo, ieLen);
+    memcpy(cmd->assocInfo, ieInfo, ieLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode)
+int
+wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
 {
     void *osbuf;
     WMI_POWER_MODE_CMD *cmd;
@@ -2748,9 +2748,9 @@ wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
-                   A_UINT16 atim_windows, A_UINT16 timeout_value)
+int
+wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
+                   u16 atim_windows, u16 timeout_value)
 {
     void *osbuf;
     WMI_IBSS_PM_CAPS_CMD *cmd;
@@ -2773,9 +2773,9 @@ wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time,
-                   A_UINT32 ps_period, A_UINT8 sleep_period)
+int
+wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
+                   u32 ps_period, u8 sleep_period)
 {
     void *osbuf;
     WMI_AP_PS_CMD *cmd;
@@ -2798,11 +2798,11 @@ wmi_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
-                 A_UINT16 psPollNum, A_UINT16 dtimPolicy,
-                 A_UINT16 tx_wakeup_policy, A_UINT16 num_tx_to_wakeup,
-                 A_UINT16 ps_fail_event_policy)
+int
+wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
+                 u16 psPollNum, u16 dtimPolicy,
+                 u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
+                 u16 ps_fail_event_policy)
 {
     void *osbuf;
     WMI_POWER_PARAMS_CMD *pm;
@@ -2827,8 +2827,8 @@ wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout)
+int
+wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
 {
     void *osbuf;
     WMI_DISC_TIMEOUT_CMD *cmd;
@@ -2848,10 +2848,10 @@ wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType,
-               A_UINT8 keyUsage, A_UINT8 keyLength, A_UINT8 *keyRSC,
-               A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, A_UINT8 *macAddr,
+int
+wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
+               u8 keyUsage, u8 keyLength, u8 *keyRSC,
+               u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
                WMI_SYNC_FLAG sync_flag)
 {
     void *osbuf;
@@ -2880,25 +2880,25 @@ wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType,
     cmd->keyType  = keyType;
     cmd->keyUsage = keyUsage;
     cmd->keyLength = keyLength;
-    A_MEMCPY(cmd->key, keyMaterial, keyLength);
+    memcpy(cmd->key, keyMaterial, keyLength);
 #ifdef WAPI_ENABLE
     if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
 #else
     if (NULL != keyRSC) {
 #endif // WAPI_ENABLE
-        A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
+        memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
     }
     cmd->key_op_ctrl = key_op_ctrl;
 
     if(macAddr) {
-        A_MEMCPY(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
+        memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
     }
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
 }
 
-A_STATUS
-wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk)
+int
+wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
 {
     void *osbuf;
     WMI_ADD_KRK_CMD *cmd;
@@ -2912,19 +2912,19 @@ wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk)
 
     cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
-    A_MEMCPY(cmd->krk, krk, WMI_KRK_LEN);
+    memcpy(cmd->krk, krk, WMI_KRK_LEN);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_delete_krk_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
 }
 
-A_STATUS
-wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex)
+int
+wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
 {
     void *osbuf;
     WMI_DELETE_CIPHER_KEY_CMD *cmd;
@@ -2948,9 +2948,9 @@ wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
-                 A_BOOL set)
+int
+wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
+                 bool set)
 {
     void *osbuf;
     WMI_SET_PMKID_CMD *cmd;
@@ -2959,7 +2959,7 @@ wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
         return A_EINVAL;
     }
 
-    if ((set == TRUE) && (pmkId == NULL)) {
+    if ((set == true) && (pmkId == NULL)) {
         return A_EINVAL;
     }
 
@@ -2971,9 +2971,9 @@ wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
-    A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
-    if (set == TRUE) {
-        A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
+    memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
+    if (set == true) {
+        memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
         cmd->enable = PMKID_ENABLE;
     } else {
         A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
@@ -2983,8 +2983,8 @@ wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
+int
+wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
 {
     void *osbuf;
     WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
@@ -2997,13 +2997,13 @@ wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
-    cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
+    cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_akmp_params_cmd(struct wmi_t *wmip,
                         WMI_SET_AKMP_PARAMS_CMD *akmpParams)
 {
@@ -3023,14 +3023,14 @@ wmi_set_akmp_params_cmd(struct wmi_t *wmip,
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
                        WMI_SET_PMKID_LIST_CMD *pmkInfo)
 {
     void *osbuf;
     WMI_SET_PMKID_LIST_CMD *cmd;
-    A_UINT16 cmdLen;
-    A_UINT8 i;
+    u16 cmdLen;
+    u8 i;
 
     cmdLen = sizeof(pmkInfo->numPMKID) +
              pmkInfo->numPMKID * sizeof(WMI_PMKID);
@@ -3045,7 +3045,7 @@ wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
     cmd->numPMKID = pmkInfo->numPMKID;
 
     for (i = 0; i < cmd->numPMKID; i++) {
-        A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
+        memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
                  WMI_PMKID_LEN);
     }
 
@@ -3053,13 +3053,13 @@ wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
 }
 
-A_STATUS
+int
 wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
 {
     WMI_DATA_HDR     *dtHdr;
@@ -3067,7 +3067,7 @@ wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
     A_ASSERT( eid != wmip->wmi_endpoint_id);
     A_ASSERT(osbuf != NULL);
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
         return A_NO_MEMORY;
     }
 
@@ -3081,18 +3081,18 @@ wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
 }
 
 typedef struct _WMI_DATA_SYNC_BUFS {
-    A_UINT8            trafficClass;
+    u8 trafficClass;
     void               *osbuf;
 }WMI_DATA_SYNC_BUFS;
 
-static A_STATUS
+static int
 wmi_sync_point(struct wmi_t *wmip)
 {
     void *cmd_osbuf;
     WMI_SYNC_CMD *cmd;
     WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
-    A_UINT8 i,numPriStreams=0;
-    A_STATUS status = A_OK;
+    u8 i,numPriStreams=0;
+    int status = 0;
 
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
@@ -3144,7 +3144,7 @@ wmi_sync_point(struct wmi_t *wmip)
         /* if Buffer allocation for any of the dataSync fails, then do not
          * send the Synchronize cmd on the control ep
          */
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -3155,7 +3155,7 @@ wmi_sync_point(struct wmi_t *wmip)
     status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
                           NO_SYNC_WMIFLAG);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
     }
             /* cmd buffer sent, we no longer own it */
@@ -3170,7 +3170,7 @@ wmi_sync_point(struct wmi_t *wmip)
                                                             trafficClass)
                                       );
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
             /* we don't own this buffer anymore, NULL it out of the array so it
@@ -3178,7 +3178,7 @@ wmi_sync_point(struct wmi_t *wmip)
             dataSyncBufs[i].osbuf = NULL;
         } //end for
 
-    } while(FALSE);
+    } while(false);
 
     /* free up any resources left over (possibly due to an error) */
 
@@ -3195,14 +3195,14 @@ wmi_sync_point(struct wmi_t *wmip)
     return (status);
 }
 
-A_STATUS
+int
 wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
 {
     void *osbuf;
     WMI_CREATE_PSTREAM_CMD *cmd;
-    A_UINT8 fatPipeExistsForAC=0;
-    A_INT32 minimalPHY = 0;
-    A_INT32 nominalPHY = 0;
+    u8 fatPipeExistsForAC=0;
+    s32 minimalPHY = 0;
+    s32 nominalPHY = 0;
 
     /* Validate all the parameters. */
     if( !((params->userPriority < 8) &&
@@ -3258,10 +3258,10 @@ wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
 
     cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
-    A_MEMCPY(cmd, params, sizeof(*cmd));
+    memcpy(cmd, params, sizeof(*cmd));
 
         /* this is an implicitly created Fat pipe */
-    if ((A_UINT32)params->tsid == (A_UINT32)WMI_IMPLICIT_PSTREAM) {
+    if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
         LOCK_WMI(wmip);
         fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
         wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
@@ -3291,13 +3291,13 @@ wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid)
+int
+wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
 {
     void *osbuf;
     WMI_DELETE_PSTREAM_CMD *cmd;
-    A_STATUS status;
-    A_UINT16 activeTsids=0;
+    int status;
+    u16 activeTsids=0;
 
     /* validate the parameters */
     if (trafficClass > 3) {
@@ -3355,12 +3355,12 @@ wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid)
     return status;
 }
 
-A_STATUS
-wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8 subType, A_UINT16 rateMask)
+int
+wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
 {
     void *osbuf;
     WMI_FRAME_RATES_CMD *cmd;
-    A_UINT8 frameType;
+    u8 frameType;
 
     A_DPRINTF(DBG_WMI,
         (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
@@ -3381,7 +3381,7 @@ wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8
     cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
 
-    frameType = (A_UINT8)((subType << 4) | type);
+    frameType = (u8)((subType << 4) | type);
 
     cmd->bEnableMask = bEnable;
     cmd->frameType = frameType;
@@ -3394,12 +3394,12 @@ wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8
  * used to set the bit rate.  rate is in Kbps.  If rate == -1
  * then auto selection is used.
  */
-A_STATUS
-wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_INT32 ctlRate)
+int
+wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
 {
     void *osbuf;
     WMI_BIT_RATE_CMD *cmd;
-    A_INT8 drix, mrix, crix, ret_val;
+    s8 drix, mrix, crix, ret_val;
 
     if (dataRate != -1) {
         ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
@@ -3444,47 +3444,47 @@ wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_IN
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_bitrate_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
 }
 
 /*
- * Returns TRUE iff the given rate index is legal in the current PHY mode.
+ * Returns true iff the given rate index is legal in the current PHY mode.
  */
-A_BOOL
-wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_INT32 rateIndex)
+bool
+wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
 {
     WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
-    A_BOOL isValid = TRUE;
+    bool isValid = true;
     switch(phyMode) {
         case WMI_11A_MODE:
             if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
                 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             } else {
                 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             }
             break;
 
         case WMI_11B_MODE:
             if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
-                isValid = FALSE;
+                isValid = false;
             }
             break;
 
         case WMI_11GONLY_MODE:
             if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
                 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             } else {
                 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             }
             break;
@@ -3493,52 +3493,51 @@ wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_INT32 rateIndex)
         case WMI_11AG_MODE:
             if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
                 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             } else {
                 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             }
             break;
         default:
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
     }
 
     return isValid;
 }
 
-A_INT8
-wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate, A_INT8 *rate_idx)
+s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
 {
-    A_INT8 i;
+    s8 i;
 
     for (i=0;;i++)
     {
-        if (wmi_rateTable[(A_UINT32) i][0] == 0) {
+        if (wmi_rateTable[(u32) i][0] == 0) {
             return A_EINVAL;
         }
-        if (wmi_rateTable[(A_UINT32) i][0] == rate) {
+        if (wmi_rateTable[(u32) i][0] == rate) {
             break;
         }
     }
 
-    if(wmi_is_bitrate_index_valid(wmip, (A_INT32) i) != TRUE) {
+    if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
         return A_EINVAL;
     }
 
     *rate_idx = i;
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask)
+int
+wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
 {
     void *osbuf;
     WMI_FIX_RATES_CMD *cmd;
 #if 0
-    A_INT32 rateIndex;
+    s32 rateIndex;
 /* This check does not work for AR6003 as the HT modes are enabled only when
  * the STA is connected to a HT_BSS and is not based only on channel. It is
  * safe to skip this check however because rate control will only use rates
@@ -3547,8 +3546,8 @@ wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask)
  * to be used. */
     /* Make sure all rates in the mask are valid in the current PHY mode */
     for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
-       if((1 << rateIndex) & (A_UINT32)fixRatesMask) {
-            if(wmi_is_bitrate_index_valid(wmip, rateIndex) != TRUE) {
+       if((1 << rateIndex) & (u32)fixRatesMask) {
+            if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
                 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
                 return A_EINVAL;
             }
@@ -3572,13 +3571,13 @@ wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask)
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_ratemask_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
 }
 
-A_STATUS
+int
 wmi_get_channelList_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
@@ -3594,14 +3593,14 @@ wmi_get_channelList_cmd(struct wmi_t *wmip)
  * should limit its operation to.  It should be NULL if numChan == 0.  Size of
  * array should correspond to numChan entries.
  */
-A_STATUS
-wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
-                          WMI_PHY_MODE mode, A_INT8 numChan,
-                          A_UINT16 *channelList)
+int
+wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
+                          WMI_PHY_MODE mode, s8 numChan,
+                          u16 *channelList)
 {
     void *osbuf;
     WMI_CHANNEL_PARAMS_CMD *cmd;
-    A_INT8 size;
+    s8 size;
 
     size = sizeof (*cmd);
 
@@ -3609,7 +3608,7 @@ wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
         if (numChan > WMI_MAX_CHANNELS) {
             return A_EINVAL;
         }
-        size += sizeof(A_UINT16) * (numChan - 1);
+        size += sizeof(u16) * (numChan - 1);
     }
 
     osbuf = A_NETBUF_ALLOC(size);
@@ -3626,7 +3625,7 @@ wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
     cmd->scanParam   = scanParam;
     cmd->phyMode     = mode;
     cmd->numChannels = numChan;
-    A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16));
+    memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
                          NO_SYNC_WMIFLAG));
@@ -3681,7 +3680,7 @@ wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_
 }
 }
 
-A_STATUS
+int
 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
 {
@@ -3706,15 +3705,15 @@ wmi_set_rssi_threshold_params(struct wmi_t *wmip,
     return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
 }
 
-A_STATUS
+int
 wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
 {
     void    *osbuf;
     WMI_SET_IP_CMD *cmd;
 
     /* Multicast address are not valid */
-    if((*((A_UINT8*)&ipCmd->ips[0]) >= 0xE0) ||
-       (*((A_UINT8*)&ipCmd->ips[1]) >= 0xE0)) {
+    if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
+       (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
         return A_EINVAL;
     }
 
@@ -3725,22 +3724,22 @@ wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
 
     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
     cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
-    A_MEMCPY(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
+    memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
                               WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
-    A_UINT16 activeTsids=0;
-    A_UINT8 streamExists=0;
-    A_UINT8 i;
+    u16 activeTsids=0;
+    u8 streamExists=0;
+    u8 i;
 
     if( hostModeCmd->awake == hostModeCmd->asleep) {
         return A_EINVAL;
@@ -3757,7 +3756,7 @@ wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
 
     cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
+    memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
 
     if(hostModeCmd->asleep) {
         /*
@@ -3793,12 +3792,12 @@ wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
                               WMI_SET_WOW_MODE_CMD *wowModeCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_SET_WOW_MODE_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -3812,19 +3811,19 @@ wmi_set_wow_mode_cmd(struct wmi_t *wmip,
 
     cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
+    memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
                             NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_get_wow_list_cmd(struct wmi_t *wmip,
                               WMI_GET_WOW_LIST_CMD *wowListCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_GET_WOW_LIST_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -3838,15 +3837,15 @@ wmi_get_wow_list_cmd(struct wmi_t *wmip,
 
     cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
+    memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
                             NO_SYNC_WMIFLAG));
 
 }
 
-static A_STATUS
-wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_GET_WOW_LIST_REPLY *reply;
 
@@ -3858,22 +3857,22 @@ wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
                           reply);
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
+int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
                                  WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
-                                 A_UINT8* pattern, A_UINT8* mask,
-                                 A_UINT8 pattern_size)
+                                 u8 *pattern, u8 *mask,
+                                 u8 pattern_size)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_ADD_WOW_PATTERN_CMD *cmd;
-    A_UINT8 *filter_mask = NULL;
+    u8 *filter_mask = NULL;
 
     size = sizeof (*cmd);
 
-    size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8));
+    size += ((2 * addWowCmd->filter_size)* sizeof(u8));
     osbuf = A_NETBUF_ALLOC(size);
     if (osbuf == NULL) {
         return A_NO_MEMORY;
@@ -3886,22 +3885,22 @@ A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
     cmd->filter_offset = addWowCmd->filter_offset;
     cmd->filter_size = addWowCmd->filter_size;
 
-    A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size);
+    memcpy(cmd->filter, pattern, addWowCmd->filter_size);
 
-    filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size);
-    A_MEMCPY(filter_mask, mask, addWowCmd->filter_size);
+    filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
+    memcpy(filter_mask, mask, addWowCmd->filter_size);
 
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
                               WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_DEL_WOW_PATTERN_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -3915,7 +3914,7 @@ wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
 
     cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
+    memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
                             NO_SYNC_WMIFLAG));
@@ -3953,8 +3952,8 @@ wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CM
      * event from the target which is used for the configuring the correct
      * thresholds
      */
-    snrCmd->thresholdAbove1_Val = (A_UINT8)sq_thresh->upper_threshold[0];
-    snrCmd->thresholdBelow1_Val = (A_UINT8)sq_thresh->lower_threshold[0];
+    snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
+    snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
     } else {
         /*
          * In case the user issues multiple times of snr_threshold_setting,
@@ -3967,7 +3966,7 @@ wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CM
     }
 
 }
-A_STATUS
+int
 wmi_set_snr_threshold_params(struct wmi_t *wmip,
                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
 {
@@ -3984,7 +3983,7 @@ wmi_set_snr_threshold_params(struct wmi_t *wmip,
     return (wmi_send_snr_threshold_params(wmip, snrCmd));
 }
 
-A_STATUS
+int
 wmi_clr_rssi_snr(struct wmi_t *wmip)
 {
     void    *osbuf;
@@ -3998,12 +3997,12 @@ wmi_clr_rssi_snr(struct wmi_t *wmip)
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_lq_threshold_params(struct wmi_t *wmip,
                              WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
     /* These values are in ascending order */
     if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
@@ -4027,17 +4026,17 @@ wmi_set_lq_threshold_params(struct wmi_t *wmip,
 
     cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
+    memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask)
+int
+wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
 
     size = sizeof (*cmd);
@@ -4058,8 +4057,8 @@ wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask)
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source)
+int
+wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
 {
     void *osbuf;
     WMIX_HB_CHALLENGE_RESP_CMD *cmd;
@@ -4079,10 +4078,10 @@ wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source)
                               NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
-                            A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
-                            A_UINT32 valid)
+int
+wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
+                            u16 tsr, bool rep, u16 size,
+                            u32 valid)
 {
     void *osbuf;
     WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
@@ -4105,14 +4104,14 @@ wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
                               NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_stats_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
 }
 
-A_STATUS
-wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid)
+int
+wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
 {
     void *osbuf;
     WMI_ADD_BAD_AP_CMD *cmd;
@@ -4130,13 +4129,13 @@ wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid)
 
     cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
     cmd->badApIndex = apIndex;
-    A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
+    memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
 }
 
-A_STATUS
-wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex)
+int
+wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
 {
     void *osbuf;
     WMI_DELETE_BAD_AP_CMD *cmd;
@@ -4159,14 +4158,14 @@ wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_abort_scan_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
 }
 
-A_STATUS
-wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM)
+int
+wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
 {
     void *osbuf;
     WMI_SET_TX_PWR_CMD *cmd;
@@ -4184,16 +4183,15 @@ wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM)
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_txPwr_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
 }
 
-A_UINT16
-wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass)
+u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
 {
-    A_UINT16 activeTsids=0;
+    u16 activeTsids=0;
 
     LOCK_WMI(wmip);
     activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
@@ -4202,17 +4200,17 @@ wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass)
     return activeTsids;
 }
 
-A_STATUS
+int
 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
 }
 
-A_STATUS
-wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType)
+int
+wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
 {
     void *osbuf;
-    A_UINT32 size = sizeof(A_UINT8);
+    u32 size = sizeof(u8);
     WMI_TARGET_ROAM_DATA *cmd;
 
     osbuf = A_NETBUF_ALLOC(size);      /* no payload */
@@ -4229,9 +4227,9 @@ wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
-                      A_UINT8 size)
+                      u8 size)
 {
     void *osbuf;
     WMI_SET_ROAM_CTRL_CMD *cmd;
@@ -4246,16 +4244,16 @@ wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
     cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
 
-    A_MEMCPY(cmd, p, size);
+    memcpy(cmd, p, size);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
                             WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
-                            A_UINT8 size)
+                            u8 size)
 {
     void *osbuf;
     WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
@@ -4278,7 +4276,7 @@ wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
     cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
 
-    A_MEMCPY(cmd, pCmd, size);
+    memcpy(cmd, pCmd, size);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
                          NO_SYNC_WMIFLAG));
@@ -4286,12 +4284,12 @@ wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
 
 #ifdef CONFIG_HOST_GPIO_SUPPORT
 /* Send a command to Target to change GPIO output pins. */
-A_STATUS
+int
 wmi_gpio_output_set(struct wmi_t *wmip,
-                    A_UINT32 set_mask,
-                    A_UINT32 clear_mask,
-                    A_UINT32 enable_mask,
-                    A_UINT32 disable_mask)
+                    u32 set_mask,
+                    u32 clear_mask,
+                    u32 enable_mask,
+                    u32 disable_mask)
 {
     void *osbuf;
     WMIX_GPIO_OUTPUT_SET_CMD *output_set;
@@ -4320,7 +4318,7 @@ wmi_gpio_output_set(struct wmi_t *wmip,
 }
 
 /* Send a command to the Target requesting state of the GPIO input pins */
-A_STATUS
+int
 wmi_gpio_input_get(struct wmi_t *wmip)
 {
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
@@ -4329,10 +4327,10 @@ wmi_gpio_input_get(struct wmi_t *wmip)
 }
 
 /* Send a command to the Target that changes the value of a GPIO register. */
-A_STATUS
+int
 wmi_gpio_register_set(struct wmi_t *wmip,
-                      A_UINT32 gpioreg_id,
-                      A_UINT32 value)
+                      u32 gpioreg_id,
+                      u32 value)
 {
     void *osbuf;
     WMIX_GPIO_REGISTER_SET_CMD *register_set;
@@ -4358,9 +4356,9 @@ wmi_gpio_register_set(struct wmi_t *wmip,
 }
 
 /* Send a command to the Target to fetch the value of a GPIO register. */
-A_STATUS
+int
 wmi_gpio_register_get(struct wmi_t *wmip,
-                      A_UINT32 gpioreg_id)
+                      u32 gpioreg_id)
 {
     void *osbuf;
     WMIX_GPIO_REGISTER_GET_CMD *register_get;
@@ -4384,9 +4382,9 @@ wmi_gpio_register_get(struct wmi_t *wmip,
 }
 
 /* Send a command to the Target acknowledging some GPIO interrupts. */
-A_STATUS
+int
 wmi_gpio_intr_ack(struct wmi_t *wmip,
-                  A_UINT32 ack_mask)
+                  u32 ack_mask)
 {
     void *osbuf;
     WMIX_GPIO_INTR_ACK_CMD *intr_ack;
@@ -4410,9 +4408,9 @@ wmi_gpio_intr_ack(struct wmi_t *wmip,
 }
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
-A_STATUS
-wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT8 ac,  A_UINT16 txop, A_UINT8 eCWmin,
-                          A_UINT8 eCWmax, A_UINT8 aifsn)
+int
+wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac,  u16 txop, u8 eCWmin,
+                          u8 eCWmax, u8 aifsn)
 {
     void *osbuf;
     WMI_SET_ACCESS_PARAMS_CMD *cmd;
@@ -4441,10 +4439,10 @@ wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT8 ac,  A_UINT16 txop, A_UINT
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
-                         A_UINT8 trafficClass, A_UINT8 maxRetries,
-                         A_UINT8 enableNotify)
+int
+wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
+                         u8 trafficClass, u8 maxRetries,
+                         u8 enableNotify)
 {
     void *osbuf;
     WMI_SET_RETRY_LIMITS_CMD *cmd;
@@ -4481,15 +4479,15 @@ wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
 }
 
 void
-wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid)
+wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
 {
     if (bssid != NULL) {
-        A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
+        memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
     }
 }
 
-A_STATUS
-wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode)
+int
+wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
 {
     void *osbuf;
     WMI_SET_OPT_MODE_CMD *cmd;
@@ -4509,13 +4507,13 @@ wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode)
                          SYNC_BOTH_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
-                      A_UINT8 frmType,
-                      A_UINT8 *dstMacAddr,
-                      A_UINT8 *bssid,
-                      A_UINT16 optIEDataLen,
-                      A_UINT8 *optIEData)
+                      u8 frmType,
+                      u8 *dstMacAddr,
+                      u8 *bssid,
+                      u16 optIEDataLen,
+                      u8 *optIEData)
 {
     void *osbuf;
     WMI_OPT_TX_FRAME_CMD *cmd;
@@ -4531,17 +4529,17 @@ wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
 
     cmd->frmType    = frmType;
     cmd->optIEDataLen   = optIEDataLen;
-    //cmd->optIEData     = (A_UINT8 *)((int)cmd + sizeof(*cmd));
-    A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
-    A_MEMCPY(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
-    A_MEMCPY(&cmd->optIEData[0], optIEData, optIEDataLen);
+    //cmd->optIEData     = (u8 *)((int)cmd + sizeof(*cmd));
+    memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
+    memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
+    memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl)
+int
+wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
 {
     void *osbuf;
     WMI_BEACON_INT_CMD *cmd;
@@ -4562,8 +4560,8 @@ wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl)
 }
 
 
-A_STATUS
-wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize)
+int
+wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
 {
     void *osbuf;
     WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
@@ -4584,8 +4582,8 @@ wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize)
 }
 
 
-A_STATUS
-wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen)
+int
+wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
 {
     void *osbuf;
     WMI_SET_MAX_SP_LEN_CMD *cmd;
@@ -4611,12 +4609,11 @@ wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen)
             NO_SYNC_WMIFLAG));
 }
 
-A_UINT8
-wmi_determine_userPriority(
-    A_UINT8 *pkt,
-    A_UINT32 layer2Pri)
+u8 wmi_determine_userPriority(
+    u8 *pkt,
+    u32 layer2Pri)
 {
-    A_UINT8 ipPri;
+    u8 ipPri;
     iphdr *ipHdr = (iphdr *)pkt;
 
     /* Determine IPTOS priority */
@@ -4632,27 +4629,25 @@ wmi_determine_userPriority(
     ipPri &= 0x7;
 
     if ((layer2Pri & 0x7) > ipPri)
-        return ((A_UINT8)layer2Pri & 0x7);
+        return ((u8)layer2Pri & 0x7);
     else
         return ipPri;
 }
 
-A_UINT8
-convert_userPriority_to_trafficClass(A_UINT8 userPriority)
+u8 convert_userPriority_to_trafficClass(u8 userPriority)
 {
     return  (up_to_ac[userPriority & 0x7]);
 }
 
-A_UINT8
-wmi_get_power_mode_cmd(struct wmi_t *wmip)
+u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
 {
     return wmip->wmi_powerMode;
 }
 
-A_STATUS
-wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance)
+int
+wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
 {
-    A_STATUS ret = A_OK;
+    int ret = 0;
 
 #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
 #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF  0
@@ -4682,21 +4677,21 @@ wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance)
 }
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-static A_STATUS
-wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
 
    A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
    A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len);
 
-   return A_OK;
+   return 0;
 }
 
 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
 
-A_STATUS
-wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
+int
+wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
 {
     void *osbuf;
     WMI_SET_AUTH_MODE_CMD *cmd;
@@ -4716,8 +4711,8 @@ wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
+int
+wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
 {
     void *osbuf;
     WMI_SET_REASSOC_MODE_CMD *cmd;
@@ -4737,8 +4732,8 @@ wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status, A_UINT8 preamblePolicy)
+int
+wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
 {
     void *osbuf;
     WMI_SET_LPREAMBLE_CMD *cmd;
@@ -4759,8 +4754,8 @@ wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status, A_UINT8 preamblePolicy
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold)
+int
+wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
 {
     void *osbuf;
     WMI_SET_RTS_CMD *cmd;
@@ -4780,7 +4775,7 @@ wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold)
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
 {
     void *osbuf;
@@ -4802,8 +4797,8 @@ wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
 
 }
 
-A_STATUS
-wmi_set_qos_supp_cmd(struct wmi_t *wmip, A_UINT8 status)
+int
+wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
 {
     void *osbuf;
     WMI_SET_QOS_SUPP_CMD *cmd;
@@ -4823,7 +4818,7 @@ wmi_set_qos_supp_cmd(struct wmi_t *wmip, A_UINT8 status)
 }
 
 
-A_STATUS
+int
 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
 {
     void *osbuf;
@@ -4848,8 +4843,8 @@ wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
 
 }
 
-A_STATUS
-wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode)
+int
+wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
 {
     void *osbuf;
     WMI_AP_SET_COUNTRY_CMD *cmd;
@@ -4863,7 +4858,7 @@ wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode)
 
     cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
-    A_MEMCPY(cmd->countryCode,countryCode,3);
+    memcpy(cmd->countryCode,countryCode,3);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
             NO_SYNC_WMIFLAG));
@@ -4874,8 +4869,8 @@ wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode)
    This would be beneficial for customers like Qualcomm, who might
    have different test command requirements from differnt manufacturers
  */
-A_STATUS
-wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32  len)
+int
+wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
 {
     void *osbuf;
     char *data;
@@ -4889,7 +4884,7 @@ wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32  len)
     }
     A_NETBUF_PUT(osbuf, len);
     data = A_NETBUF_DATA(osbuf);
-    A_MEMCPY(data, buf, len);
+    memcpy(data, buf, len);
 
     return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
          NO_SYNC_WMIFLAG));
@@ -4897,8 +4892,8 @@ wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32  len)
 
 #endif
 
-A_STATUS
-wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status)
+int
+wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
 {
     void *osbuf;
     WMI_SET_BT_STATUS_CMD *cmd;
@@ -4921,7 +4916,7 @@ wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status)
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
 {
     void *osbuf;
@@ -4977,13 +4972,13 @@ wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
 
     alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-    A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd));
+    memcpy(alloc_cmd, cmd, sizeof(*cmd));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
 {
 	void *osbuf;
@@ -4996,14 +4991,14 @@ wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
                          NO_SYNC_WMIFLAG));
 
 }
 
 
-A_STATUS
+int
 wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
 {
@@ -5017,14 +5012,14 @@ wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-    A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
+    memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
     A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
 {
@@ -5038,13 +5033,13 @@ wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
 {
@@ -5058,13 +5053,13 @@ wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
 {
@@ -5078,13 +5073,13 @@ wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
 {
@@ -5098,13 +5093,13 @@ wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
 {
 	void *osbuf;
@@ -5117,13 +5112,13 @@ wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
 	alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
 	return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
 							 NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
 					WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
 {
@@ -5137,13 +5132,13 @@ wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
 	alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
 	return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
 								 NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
 {
 	void *osbuf;
@@ -5156,13 +5151,13 @@ wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
 	alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
 	return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
 							 NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
 {
 
@@ -5170,7 +5165,7 @@ wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
 
 }
 
-A_STATUS
+int
 wmi_get_keepalive_configured(struct wmi_t *wmip)
 {
     void *osbuf;
@@ -5186,14 +5181,13 @@ wmi_get_keepalive_configured(struct wmi_t *wmip)
                          NO_SYNC_WMIFLAG));
 }
 
-A_UINT8
-wmi_get_keepalive_cmd(struct wmi_t *wmip)
+u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
 {
     return wmip->wmi_keepaliveInterval;
 }
 
-A_STATUS
-wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval)
+int
+wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
 {
     void *osbuf;
     WMI_SET_KEEPALIVE_CMD *cmd;
@@ -5214,8 +5208,8 @@ wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR* buffer)
+int
+wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
 {
     void *osbuf;
     WMI_SET_PARAMS_CMD *cmd;
@@ -5231,15 +5225,15 @@ wmi_set_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR*
     A_MEMZERO(cmd, sizeof(*cmd));
     cmd->opcode = opcode;
     cmd->length = length;
-    A_MEMCPY(cmd->buffer, buffer, length);
+    memcpy(cmd->buffer, buffer, length);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
 
-A_STATUS
-wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4)
+int
+wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
 {
     void *osbuf;
     WMI_SET_MCAST_FILTER_CMD *cmd;
@@ -5264,8 +5258,8 @@ wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8
 }
 
 
-A_STATUS
-wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4)
+int
+wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
 {
     void *osbuf;
     WMI_SET_MCAST_FILTER_CMD *cmd;
@@ -5289,8 +5283,8 @@ wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable)
+int
+wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
 {
     void *osbuf;
     WMI_MCAST_FILTER_CMD *cmd;
@@ -5309,13 +5303,13 @@ wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable)
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen,
-                  A_UINT8 *ieInfo)
+int
+wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
+                  u8 *ieInfo)
 {
     void *osbuf;
     WMI_SET_APPIE_CMD *cmd;
-    A_UINT16 cmdLen;
+    u16 cmdLen;
 
     cmdLen = sizeof(*cmd) + ieLen - 1;
     osbuf = A_NETBUF_ALLOC(cmdLen);
@@ -5330,16 +5324,16 @@ wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen,
 
     cmd->mgmtFrmType = mgmtFrmType;
     cmd->ieLen = ieLen;
-    A_MEMCPY(cmd->ieInfo, ieInfo, ieLen);
+    memcpy(cmd->ieInfo, ieInfo, ieLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen)
+int
+wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
 {
     void *osbuf;
-    A_UINT8 *data;
+    u8 *data;
 
     osbuf = A_NETBUF_ALLOC(dataLen);
     if (osbuf == NULL) {
@@ -5350,18 +5344,17 @@ wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen)
 
     data = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(data, cmd, dataLen);
+    memcpy(data, cmd, dataLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_INT32
-wmi_get_rate(A_INT8 rateindex)
+s32 wmi_get_rate(s8 rateindex)
 {
     if (rateindex == RATE_AUTO) {
         return 0;
     } else {
-        return(wmi_rateTable[(A_UINT32) rateindex][0]);
+        return(wmi_rateTable[(u32) rateindex][0]);
     }
 }
 
@@ -5375,14 +5368,14 @@ wmi_node_return (struct wmi_t *wmip, bss_t *bss)
 }
 
 void
-wmi_set_nodeage(struct wmi_t *wmip, A_UINT32 nodeAge)
+wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
 {
     wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
 }
 
 bss_t *
-wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID)
+wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
 {
     bss_t *node = NULL;
     node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
@@ -5406,7 +5399,7 @@ wmi_free_allnodes(struct wmi_t *wmip)
 }
 
 bss_t *
-wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
+wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
 {
     bss_t *ni=NULL;
     ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
@@ -5414,7 +5407,7 @@ wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
 }
 
 void
-wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
+wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
 {
     bss_t *ni=NULL;
 
@@ -5426,15 +5419,15 @@ wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
     return;
 }
 
-A_STATUS
+int
 wmi_dset_open_reply(struct wmi_t *wmip,
-                    A_UINT32 status,
-                    A_UINT32 access_cookie,
-                    A_UINT32 dset_size,
-                    A_UINT32 dset_version,
-                    A_UINT32 targ_handle,
-                    A_UINT32 targ_reply_fn,
-                    A_UINT32 targ_reply_arg)
+                    u32 status,
+                    u32 access_cookie,
+                    u32 dset_size,
+                    u32 dset_version,
+                    u32 targ_handle,
+                    u32 targ_reply_fn,
+                    u32 targ_reply_arg)
 {
     void *osbuf;
     WMIX_DSETOPEN_REPLY_CMD *open_reply;
@@ -5461,11 +5454,11 @@ wmi_dset_open_reply(struct wmi_t *wmip,
                              NO_SYNC_WMIFLAG));
 }
 
-static A_STATUS
-wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
+static int
+wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
 {
     WMI_PMKID_LIST_REPLY *reply;
-    A_UINT32 expected_len;
+    u32 expected_len;
 
     if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
         return A_EINVAL;
@@ -5480,12 +5473,12 @@ wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
     A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
                            reply->pmkidList, reply->bssidList[0]);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
+static int
+wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
 {
     WMI_SET_PARAMS_REPLY *reply;
 
@@ -5494,7 +5487,7 @@ wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
     }
     reply = (WMI_SET_PARAMS_REPLY *)datap;
 
-    if (A_OK == reply->status)
+    if (0 == reply->status)
     {
 
     }
@@ -5503,36 +5496,36 @@ wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
 
     }
 
-    return A_OK;
+    return 0;
 }
 
 
 
-static A_STATUS
-wmi_acm_reject_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
+static int
+wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
 {
     WMI_ACM_REJECT_EVENT *ev;
 
     ev = (WMI_ACM_REJECT_EVENT *)datap;
     wmip->wmi_traffic_class = ev->trafficClass;
     printk("ACM REJECT %d\n",wmip->wmi_traffic_class);
-    return A_OK;
+    return 0;
 }
 
 
 #ifdef CONFIG_HOST_DSET_SUPPORT
-A_STATUS
+int
 wmi_dset_data_reply(struct wmi_t *wmip,
-                    A_UINT32 status,
-                    A_UINT8 *user_buf,
-                    A_UINT32 length,
-                    A_UINT32 targ_buf,
-                    A_UINT32 targ_reply_fn,
-                    A_UINT32 targ_reply_arg)
+                    u32 status,
+                    u8 *user_buf,
+                    u32 length,
+                    u32 targ_buf,
+                    u32 targ_reply_fn,
+                    u32 targ_reply_arg)
 {
     void *osbuf;
     WMIX_DSETDATA_REPLY_CMD *data_reply;
-    A_UINT32 size;
+    u32 size;
 
     size = sizeof(*data_reply) + length;
 
@@ -5556,7 +5549,7 @@ wmi_dset_data_reply(struct wmi_t *wmip,
     data_reply->targ_reply_arg             = targ_reply_arg;
     data_reply->length                     = length;
 
-    if (status == A_OK) {
+    if (status == 0) {
         if (a_copy_from_user(data_reply->buf, user_buf, length)) {
             A_NETBUF_FREE(osbuf);
             return A_ERROR;
@@ -5568,8 +5561,8 @@ wmi_dset_data_reply(struct wmi_t *wmip,
 }
 #endif /* CONFIG_HOST_DSET_SUPPORT */
 
-A_STATUS
-wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status)
+int
+wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
 {
     void *osbuf;
     char *cmd;
@@ -5592,10 +5585,10 @@ wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status)
 }
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-A_STATUS
+int
 wmi_prof_cfg_cmd(struct wmi_t *wmip,
-                 A_UINT32 period,
-                 A_UINT32 nbins)
+                 u32 period,
+                 u32 nbins)
 {
     void *osbuf;
     WMIX_PROF_CFG_CMD *cmd;
@@ -5615,8 +5608,8 @@ wmi_prof_cfg_cmd(struct wmi_t *wmip,
     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr)
+int
+wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
 {
     void *osbuf;
     WMIX_PROF_ADDR_SET_CMD *cmd;
@@ -5635,27 +5628,27 @@ wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr)
     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_prof_start_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
 }
 
-A_STATUS
+int
 wmi_prof_stop_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
 }
 
-A_STATUS
+int
 wmi_prof_count_get_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
 }
 
 /* Called to handle WMIX_PROF_CONT_EVENTID */
-static A_STATUS
-wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
 
@@ -5665,7 +5658,7 @@ wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
 
     A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
 
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 
@@ -5677,16 +5670,16 @@ void
 wmi_scan_indication (struct wmi_t *wmip)
 {
     struct ieee80211_node_table *nt;
-    A_UINT32 gen;
-    A_UINT32 size;
-    A_UINT32 bsssize;
+    u32 gen;
+    u32 size;
+    u32 bsssize;
     bss_t *bss;
-    A_UINT32 numbss;
+    u32 numbss;
     PNDIS_802_11_BSSID_SCAN_INFO psi;
     PBYTE  pie;
     NDIS_802_11_FIXED_IEs *pFixed;
     NDIS_802_11_VARIABLE_IEs *pVar;
-    A_UINT32  RateSize;
+    u32 RateSize;
 
     struct ar6kScanIndication
     {
@@ -5888,17 +5881,16 @@ wmi_scan_indication (struct wmi_t *wmip)
 }
 #endif
 
-A_UINT8
-ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
-                           A_UINT32 size)
+u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
+                           u32 size)
 {
-    A_UINT32 index;
-    A_UINT8 threshold = (A_UINT8)sq_thresh->upper_threshold[size - 1];
+    u32 index;
+    u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
 
     /* The list is already in sorted order. Get the next lower value */
     for (index = 0; index < size; index ++) {
         if (rssi < sq_thresh->upper_threshold[index]) {
-            threshold = (A_UINT8)sq_thresh->upper_threshold[index];
+            threshold = (u8)sq_thresh->upper_threshold[index];
             break;
         }
     }
@@ -5906,29 +5898,28 @@ ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
     return threshold;
 }
 
-A_UINT8
-ar6000_get_lower_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
-                           A_UINT32 size)
+u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
+                           u32 size)
 {
-    A_UINT32 index;
-    A_UINT8 threshold = (A_UINT8)sq_thresh->lower_threshold[size - 1];
+    u32 index;
+    u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
 
     /* The list is already in sorted order. Get the next lower value */
     for (index = 0; index < size; index ++) {
         if (rssi > sq_thresh->lower_threshold[index]) {
-            threshold = (A_UINT8)sq_thresh->lower_threshold[index];
+            threshold = (u8)sq_thresh->lower_threshold[index];
             break;
         }
     }
 
     return threshold;
 }
-static A_STATUS
+static int
 wmi_send_rssi_threshold_params(struct wmi_t *wmip,
                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -5942,17 +5933,17 @@ wmi_send_rssi_threshold_params(struct wmi_t *wmip,
 
     cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
+    memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
                             NO_SYNC_WMIFLAG));
 }
-static A_STATUS
+static int
 wmi_send_snr_threshold_params(struct wmi_t *wmip,
                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -5965,13 +5956,13 @@ wmi_send_snr_threshold_params(struct wmi_t *wmip,
     A_NETBUF_PUT(osbuf, size);
     cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
+    memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
 {
     void *osbuf;
@@ -5986,86 +5977,86 @@ wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_
 
     alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-    A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd));
+    memcpy(alloc_cmd, cmd, sizeof(*cmd));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
             NO_SYNC_WMIFLAG));
 }
 
-bss_t *wmi_rm_current_bss (struct wmi_t *wmip, A_UINT8 *id)
+bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
 {
     wmi_get_current_bssid (wmip, id);
     return wlan_node_remove (&wmip->wmi_scan_table, id);
 }
 
-A_STATUS wmi_add_current_bss (struct wmi_t *wmip, A_UINT8 *id, bss_t *bss)
+int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
 {
     wlan_setup_node (&wmip->wmi_scan_table, bss, id);
-    return A_OK;
+    return 0;
 }
 
 #ifdef ATH_AR6K_11N_SUPPORT
-static A_STATUS
-wmi_addba_req_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
 
     A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_addba_resp_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
 
     A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_delba_req_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
 
     A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-wmi_btcoex_config_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+int
+wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
 	A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
 
-     return A_OK;
+     return 0;
 }
 
 
-A_STATUS
-wmi_btcoex_stats_event_rx(struct wmi_t * wmip,A_UINT8 * datap,int len)
+int
+wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
 {
 	A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
 
-     return A_OK;
+     return 0;
 
 }
 #endif
 
-static A_STATUS
-wmi_hci_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
     A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -6083,7 +6074,7 @@ wmi_hci_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
  * commit cmd will not be sent to target. Without calling this IOCTL
  * the changes will not take effect.
  */
-A_STATUS
+int
 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
 {
     void *osbuf;
@@ -6098,7 +6089,7 @@ wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
     cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cm, sizeof(*cm));
 
-    A_MEMCPY(cm,p,sizeof(*cm));
+    memcpy(cm,p,sizeof(*cm));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
 }
@@ -6109,8 +6100,8 @@ wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
  * This command will be used to enable/disable hidden ssid functioanlity of
  * beacon. If it is enabled, ssid will be NULL in beacon.
  */
-A_STATUS
-wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid)
+int
+wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
 {
     void *osbuf;
     WMI_AP_HIDDEN_SSID_CMD *hs;
@@ -6138,8 +6129,8 @@ wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid)
  * is max num of STA supported by AP). Value was already validated
  * in ioctl.c
  */
-A_STATUS
-wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta)
+int
+wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
 {
     void *osbuf;
     WMI_AP_SET_NUM_STA_CMD *ns;
@@ -6166,7 +6157,7 @@ wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta)
  * be allowed to connect with this AP. When this list is empty
  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
  */
-A_STATUS
+int
 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
 {
     void *osbuf;
@@ -6180,7 +6171,7 @@ wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
     a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(a, sizeof(*a));
-    A_MEMCPY(a,acl,sizeof(*acl));
+    memcpy(a,acl,sizeof(*acl));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
 }
@@ -6192,8 +6183,8 @@ wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
  * be allowed to connect with this AP. When this list is empty
  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
  */
-A_STATUS
-wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason)
+int
+wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
 {
     void *osbuf;
     WMI_AP_SET_MLME_CMD *mlme;
@@ -6208,14 +6199,14 @@ wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason)
     A_MEMZERO(mlme, sizeof(*mlme));
 
     mlme->cmd = cmd;
-    A_MEMCPY(mlme->mac, mac, ATH_MAC_LEN);
+    memcpy(mlme->mac, mac, ATH_MAC_LEN);
     mlme->reason = reason;
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
 }
 
-static A_STATUS
-wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_PSPOLL_EVENT *ev;
 
@@ -6225,34 +6216,34 @@ wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
     ev = (WMI_PSPOLL_EVENT *)datap;
 
     A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_dtimexpiry_event_rx(struct wmi_t *wmip, A_UINT8 *datap,int len)
+static int
+wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
 {
     A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
-    return A_OK;
+    return 0;
 }
 
 #ifdef WAPI_ENABLE
-static A_STATUS
-wmi_wapi_rekey_event_rx(struct wmi_t *wmip, A_UINT8 *datap,int len)
+static int
+wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
 {
-    A_UINT8 *ev;
+    u8 *ev;
 
     if (len < 7) {
         return A_EINVAL;
     }
-    ev = (A_UINT8 *)datap;
+    ev = (u8 *)datap;
 
     A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
-    return A_OK;
+    return 0;
 }
 #endif
 
-A_STATUS
-wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag)
+int
+wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
 {
     WMI_AP_SET_PVB_CMD *cmd;
     void *osbuf = NULL;
@@ -6272,8 +6263,8 @@ wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag)
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period)
+int
+wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
 {
     WMI_AP_CONN_INACT_CMD *cmd;
     void *osbuf = NULL;
@@ -6292,8 +6283,8 @@ wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period)
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell)
+int
+wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
 {
     WMI_AP_PROT_SCAN_TIME_CMD *cmd;
     void *osbuf = NULL;
@@ -6313,8 +6304,8 @@ wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell)
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim)
+int
+wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
 {
     WMI_AP_SET_DTIM_CMD *cmd;
     void *osbuf = NULL;
@@ -6341,8 +6332,8 @@ wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim)
  * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
  * If there is no chage in policy, the list will be intact.
  */
-A_STATUS
-wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy)
+int
+wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
 {
     void *osbuf;
     WMI_AP_ACL_POLICY_CMD *po;
@@ -6361,8 +6352,8 @@ wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy)
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset)
+int
+wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
 {
     void *osbuf;
     WMI_AP_SET_11BG_RATESET_CMD *rs;
@@ -6382,12 +6373,12 @@ wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset)
 }
 
 #ifdef ATH_AR6K_11N_SUPPORT
-A_STATUS
+int
 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
 {
     void *osbuf;
     WMI_SET_HT_CAP_CMD *htCap;
-    A_UINT8 band;
+    u8 band;
 
     osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
     if (osbuf == NULL) {
@@ -6401,14 +6392,14 @@ wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
 
     htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(htCap, sizeof(*htCap));
-    A_MEMCPY(htCap, cmd, sizeof(*htCap));
+    memcpy(htCap, cmd, sizeof(*htCap));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width)
+int
+wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
 {
     void *osbuf;
     WMI_SET_HT_OP_CMD *htInfo;
@@ -6429,8 +6420,8 @@ wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width)
 }
 #endif
 
-A_STATUS
-wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray)
+int
+wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
 {
     void *osbuf;
     WMI_SET_TX_SELECT_RATES_CMD *pData;
@@ -6443,15 +6434,15 @@ wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray)
     A_NETBUF_PUT(osbuf, sizeof(*pData));
 
     pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
-    A_MEMCPY(pData, pMaskArray, sizeof(*pData));
+    memcpy(pData, pMaskArray, sizeof(*pData));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
 
-A_STATUS
-wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz)
+int
+wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
 {
     void *osbuf;
     WMI_HCI_CMD *cmd;
@@ -6465,13 +6456,13 @@ wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz)
     cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
 
     cmd->cmd_buf_sz = sz;
-    A_MEMCPY(cmd->buf, buf, sz);
+    memcpy(cmd->buf, buf, sz);
     return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
 }
 
 #ifdef ATH_AR6K_11N_SUPPORT
-A_STATUS
-wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask)
+int
+wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
 {
     void *osbuf;
     WMI_ALLOW_AGGR_CMD *cmd;
@@ -6490,8 +6481,8 @@ wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask)
     return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid)
+int
+wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
 {
     void *osbuf;
     WMI_ADDBA_REQ_CMD *cmd;
@@ -6509,8 +6500,8 @@ wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid)
     return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink)
+int
+wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
 {
     void *osbuf;
     WMI_DELBA_REQ_CMD *cmd;
@@ -6531,9 +6522,9 @@ wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink)
 }
 #endif
 
-A_STATUS
-wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion,
-                            A_BOOL rxDot11Hdr, A_BOOL defragOnHost)
+int
+wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
+                            bool rxDot11Hdr, bool defragOnHost)
 {
     void *osbuf;
     WMI_RX_FRAME_FORMAT_CMD *cmd;
@@ -6546,8 +6537,8 @@ wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion,
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
-    cmd->dot11Hdr = (rxDot11Hdr==TRUE)? 1:0;
-    cmd->defragOnHost = (defragOnHost==TRUE)? 1:0;
+    cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
+    cmd->defragOnHost = (defragOnHost==true)? 1:0;
     cmd->metaVersion = rxMetaVersion;  /*  */
 
     /* Delete the local aggr state, on host */
@@ -6555,8 +6546,8 @@ wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion,
 }
 
 
-A_STATUS
-wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode)
+int
+wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
 {
     void *osbuf;
     WMI_SET_THIN_MODE_CMD *cmd;
@@ -6569,14 +6560,14 @@ wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode)
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
-    cmd->enable = (bThinMode==TRUE)? 1:0;
+    cmd->enable = (bThinMode==true)? 1:0;
 
     /* Delete the local aggr state, on host */
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
 }
 
 
-A_STATUS
+int
 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
 {
     void *osbuf;
@@ -6597,8 +6588,8 @@ wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE pre
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk)
+int
+wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
 {
     void *osbuf;
     WMI_SET_PMK_CMD *p;
@@ -6613,13 +6604,34 @@ wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk)
     p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(p, sizeof(*p));
 
-    A_MEMCPY(p->pmk, pmk, WMI_PMK_LEN);
+    memcpy(p->pmk, pmk, WMI_PMK_LEN);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 sgiMask, A_UINT8 sgiPERThreshold)
+int
+wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
+{
+    void *osbuf;
+    WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
+
+    osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
+    if (osbuf == NULL) {
+        return A_NO_MEMORY;
+    }
+
+    A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
+
+    p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
+    memset(p, 0, sizeof(*p));
+
+    p->threshold = cmd->threshold;
+
+    return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
+}
+
+int
+wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
 {
     void *osbuf;
     WMI_SET_TX_SGI_PARAM_CMD *cmd;
@@ -6640,10 +6652,10 @@ wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 sgiMask, A_UINT8 sgiPERThreshold)
 }
 
 bss_t *
-wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength,
-                   A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp)
+wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength,
+                   u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
 {
     bss_t *node = NULL;
     node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
@@ -6652,19 +6664,17 @@ wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
     return node;
 }
 
-A_UINT16
-wmi_ieee2freq (int chan)
+u16 wmi_ieee2freq (int chan)
 {
-    A_UINT16 freq = 0;
+    u16 freq = 0;
     freq = wlan_ieee2freq (chan);
     return freq;
 
 }
 
-A_UINT32
-wmi_freq2ieee (A_UINT16 freq)
+u32 wmi_freq2ieee (u16 freq)
 {
-    A_UINT16 chan = 0;
+    u16 chan = 0;
     chan = wlan_freq2ieee (freq);
     return chan;
 }
diff --git a/drivers/staging/ath6kl/wmi/wmi_host.h b/drivers/staging/ath6kl/wmi/wmi_host.h
index 5c7f7d3..53e4f08 100644
--- a/drivers/staging/ath6kl/wmi/wmi_host.h
+++ b/drivers/staging/ath6kl/wmi/wmi_host.h
@@ -31,8 +31,8 @@ extern "C" {
 #endif
 
 struct wmi_stats {
-    A_UINT32    cmd_len_err;
-    A_UINT32    cmd_id_err;
+    u32 cmd_len_err;
+    u32 cmd_id_err;
 };
 
 #define SSID_IE_LEN_INDEX 13
@@ -42,14 +42,14 @@ struct wmi_stats {
 #define SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
 #define SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
 typedef struct sq_threshold_params_s {
-    A_INT16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS];
-    A_INT16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS];
-    A_UINT32 upper_threshold_valid_count;
-    A_UINT32 lower_threshold_valid_count;
-    A_UINT32 polling_interval;
-    A_UINT8 weight;
-    A_UINT8  last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target.
-    A_UINT8  last_rssi_poll_event; //Not sure if it belongs to host or target
+    s16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS];
+    s16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS];
+    u32 upper_threshold_valid_count;
+    u32 lower_threshold_valid_count;
+    u32 polling_interval;
+    u8 weight;
+    u8 last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target.
+    u8 last_rssi_poll_event; //Not sure if it belongs to host or target
 } SQ_THRESHOLD_PARAMS;
 
 /*
@@ -60,17 +60,17 @@ typedef struct sq_threshold_params_s {
 #define A_NUM_BANDS            2
 
 struct wmi_t {
-    A_BOOL                          wmi_ready;
-    A_BOOL                          wmi_numQoSStream;
-    A_UINT16                        wmi_streamExistsForAC[WMM_NUM_AC];
-    A_UINT8                         wmi_fatPipeExists;
+    bool                          wmi_ready;
+    bool                          wmi_numQoSStream;
+    u16 wmi_streamExistsForAC[WMM_NUM_AC];
+    u8 wmi_fatPipeExists;
     void                           *wmi_devt;
     struct wmi_stats                wmi_stats;
     struct ieee80211_node_table     wmi_scan_table;
-    A_UINT8                         wmi_bssid[ATH_MAC_LEN];
-    A_UINT8                         wmi_powerMode;
-    A_UINT8                         wmi_phyMode;
-    A_UINT8                         wmi_keepaliveInterval;
+    u8 wmi_bssid[ATH_MAC_LEN];
+    u8 wmi_powerMode;
+    u8 wmi_phyMode;
+    u8 wmi_keepaliveInterval;
 #ifdef THREAD_X
     A_CSECT_T                       wmi_lock;
 #else 
@@ -80,9 +80,9 @@ struct wmi_t {
     SQ_THRESHOLD_PARAMS             wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_NUM_MAX];
     CRYPTO_TYPE                     wmi_pair_crypto_type;
     CRYPTO_TYPE                     wmi_grp_crypto_type;
-    A_BOOL                          wmi_is_wmm_enabled;
-    A_UINT8                         wmi_ht_allowed[A_NUM_BANDS];
-    A_UINT8                         wmi_traffic_class;
+    bool                          wmi_is_wmm_enabled;
+    u8 wmi_ht_allowed[A_NUM_BANDS];
+    u8 wmi_traffic_class;
 };
 
 #ifdef THREAD_X
diff --git a/drivers/staging/autofs/Kconfig b/drivers/staging/autofs/Kconfig
deleted file mode 100644
index 480e210..0000000
--- a/drivers/staging/autofs/Kconfig
+++ /dev/null
@@ -1,22 +0,0 @@
-config AUTOFS_FS
-	tristate "Kernel automounter support"
-	depends on BKL # unfixable, just use autofs4
-	help
-	  The automounter is a tool to automatically mount remote file systems
-	  on demand. This implementation is partially kernel-based to reduce
-	  overhead in the already-mounted case; this is unlike the BSD
-	  automounter (amd), which is a pure user space daemon.
-
-	  To use the automounter you need the user-space tools from the autofs
-	  package; you can find the location in <file:Documentation/Changes>.
-	  You also want to answer Y to "NFS file system support", below.
-
-	  If you want to use the newer version of the automounter with more
-	  features, say N here and say Y to "Kernel automounter v4 support",
-	  below.
-
-	  To compile this support as a module, choose M here: the module will be
-	  called autofs.
-
-	  If you are not a part of a fairly large, distributed network, you
-	  probably do not need an automounter, and can say N here.
diff --git a/drivers/staging/autofs/Makefile b/drivers/staging/autofs/Makefile
deleted file mode 100644
index f48781c..0000000
--- a/drivers/staging/autofs/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux autofs-filesystem routines.
-#
-
-obj-$(CONFIG_AUTOFS_FS) += autofs.o
-
-autofs-y := dirhash.o init.o inode.o root.o symlink.o waitq.o
diff --git a/drivers/staging/autofs/TODO b/drivers/staging/autofs/TODO
deleted file mode 100644
index 543803d..0000000
--- a/drivers/staging/autofs/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-autofs version 3 is on its way out of the kernel,
-It has been replaced by autofs4 several years ago.
-
-The autofs3 code uses the big kernel lock which
-is getting deprecated.
-
-Users that find autofs3 to work but not autofs4
-should talk to Ian Kent <raven@themaw.net>.
diff --git a/drivers/staging/autofs/autofs_i.h b/drivers/staging/autofs/autofs_i.h
deleted file mode 100644
index 647a143..0000000
--- a/drivers/staging/autofs/autofs_i.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *   
- * drivers/staging/autofs/autofs_i.h
- *
- *   Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ----------------------------------------------------------------------- */
-
-/* Internal header file for autofs */
-
-#include <linux/auto_fs.h>
-
-/* This is the range of ioctl() numbers we claim as ours */
-#define AUTOFS_IOC_FIRST     AUTOFS_IOC_READY
-#define AUTOFS_IOC_COUNT     32
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/dcache.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/sched.h>
-
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#ifdef DEBUG
-#define DPRINTK(D) (printk D)
-#else
-#define DPRINTK(D) ((void)0)
-#endif
-
-/*
- * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
- * kernel will keep the negative response cached for up to the time given
- * here, although the time can be shorter if the kernel throws the dcache
- * entry away.  This probably should be settable from user space.
- */
-#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ)	/* 1 minute */
-
-/* Structures associated with the root directory hash table */
-
-#define AUTOFS_HASH_SIZE 67
-
-struct autofs_dir_ent {
-	int hash;
-	char *name;
-	int len;
-	ino_t ino;
-	struct dentry *dentry;
-	/* Linked list of entries */
-	struct autofs_dir_ent *next;
-	struct autofs_dir_ent **back;
-	/* The following entries are for the expiry system */
-	unsigned long last_usage;
-	struct list_head exp;
-};
-
-struct autofs_dirhash {
-	struct autofs_dir_ent *h[AUTOFS_HASH_SIZE];
-	struct list_head expiry_head;
-};
-
-struct autofs_wait_queue {
-	wait_queue_head_t queue;
-	struct autofs_wait_queue *next;
-	autofs_wqt_t wait_queue_token;
-	/* We use the following to see what we are waiting for */
-	int hash;
-	int len;
-	char *name;
-	/* This is for status reporting upon return */
-	int status;
-	int wait_ctr;
-};
-
-struct autofs_symlink {
-	char *data;
-	int len;
-	time_t mtime;
-};
-
-#define AUTOFS_MAX_SYMLINKS 256
-
-#define AUTOFS_ROOT_INO      1
-#define AUTOFS_FIRST_SYMLINK 2
-#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS)
-
-#define AUTOFS_SYMLINK_BITMAP_LEN \
-	((AUTOFS_MAX_SYMLINKS+((sizeof(long)*1)-1))/(sizeof(long)*8))
-
-#define AUTOFS_SBI_MAGIC 0x6d4a556d
-
-struct autofs_sb_info {
-	u32 magic;
-	struct file *pipe;
-	struct pid *oz_pgrp;
-	int catatonic;
-	struct super_block *sb;
-	unsigned long exp_timeout;
-	ino_t next_dir_ino;
-	struct autofs_wait_queue *queues; /* Wait queue pointer */
-	struct autofs_dirhash dirhash; /* Root directory hash */
-	struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS];
-	unsigned long symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
-};
-
-static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb)
-{
-	return (struct autofs_sb_info *)(sb->s_fs_info);
-}
-
-/* autofs_oz_mode(): do we see the man behind the curtain?  (The
-   processes which do manipulations for us in user space sees the raw
-   filesystem without "magic".) */
-
-static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
-	return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
-}
-
-/* Hash operations */
-
-void autofs_initialize_hash(struct autofs_dirhash *);
-struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,struct qstr *);
-void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
-void autofs_hash_delete(struct autofs_dir_ent *);
-struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *);
-void autofs_hash_dputall(struct autofs_dirhash *);
-void autofs_hash_nuke(struct autofs_sb_info *);
-
-/* Expiration-handling functions */
-
-void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *);
-struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *, struct vfsmount *mnt);
-
-/* Operations structures */
-
-extern const struct inode_operations autofs_root_inode_operations;
-extern const struct inode_operations autofs_symlink_inode_operations;
-extern const struct file_operations autofs_root_operations;
-
-/* Initializing function */
-
-int autofs_fill_super(struct super_block *, void *, int);
-void autofs_kill_sb(struct super_block *sb);
-struct inode *autofs_iget(struct super_block *, unsigned long);
-
-/* Queue management functions */
-
-int autofs_wait(struct autofs_sb_info *,struct qstr *);
-int autofs_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
-void autofs_catatonic_mode(struct autofs_sb_info *);
-
-#ifdef DEBUG
-void autofs_say(const char *name, int len);
-#else
-#define autofs_say(n,l) ((void)0)
-#endif
diff --git a/drivers/staging/autofs/dirhash.c b/drivers/staging/autofs/dirhash.c
deleted file mode 100644
index a08bd73..0000000
--- a/drivers/staging/autofs/dirhash.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/dirhash.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
-
-#include "autofs_i.h"
-
-/* Functions for maintenance of expiry queue */
-
-static void autofs_init_usage(struct autofs_dirhash *dh,
-			      struct autofs_dir_ent *ent)
-{
-	list_add_tail(&ent->exp, &dh->expiry_head);
-	ent->last_usage = jiffies;
-}
-
-static void autofs_delete_usage(struct autofs_dir_ent *ent)
-{
-	list_del(&ent->exp);
-}
-
-void autofs_update_usage(struct autofs_dirhash *dh,
-			 struct autofs_dir_ent *ent)
-{
-	autofs_delete_usage(ent);   /* Unlink from current position */
-	autofs_init_usage(dh, ent);  /* Relink at queue tail */
-}
-
-struct autofs_dir_ent *autofs_expire(struct super_block *sb,
-				     struct autofs_sb_info *sbi,
-				     struct vfsmount *mnt)
-{
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	unsigned long timeout = sbi->exp_timeout;
-
-	while (1) {
-		struct path path;
-		int umount_ok;
-
-		if (list_empty(&dh->expiry_head) || sbi->catatonic)
-			return NULL;	/* No entries */
-		/* We keep the list sorted by last_usage and want old stuff */
-		ent = list_entry(dh->expiry_head.next,
-						struct autofs_dir_ent, exp);
-		if (jiffies - ent->last_usage < timeout)
-			break;
-		/* Move to end of list in case expiry isn't desirable */
-		autofs_update_usage(dh, ent);
-
-		/* Check to see that entry is expirable */
-		if (ent->ino < AUTOFS_FIRST_DIR_INO)
-			return ent; /* Symlinks are always expirable */
-
-		/* Get the dentry for the autofs subdirectory */
-		path.dentry = ent->dentry;
-
-		if (!path.dentry) {
-			/* Should only happen in catatonic mode */
-			printk(KERN_DEBUG "autofs: dentry == NULL but inode \
-				range is directory, entry %s\n", ent->name);
-			autofs_delete_usage(ent);
-			continue;
-		}
-
-		if (!path.dentry->d_inode) {
-			dput(path.dentry);
-			printk(KERN_DEBUG "autofs: negative dentry on expiry queue: %s\n",
-			       ent->name);
-			autofs_delete_usage(ent);
-			continue;
-		}
-
-		/* Make sure entry is mounted and unused; note that dentry will
-		   point to the mounted-on-top root. */
-		if (!S_ISDIR(path.dentry->d_inode->i_mode) ||
-		    !d_mountpoint(path.dentry)) {
-			DPRINTK(("autofs: not expirable \
-				(not a mounted directory): %s\n", ent->name));
-			continue;
-		}
-		path.mnt = mnt;
-		path_get(&path);
-		if (!follow_down_one(&path)) {
-			path_put(&path);
-			DPRINTK(("autofs: not expirable\
-			(not a mounted directory): %s\n", ent->name));
-			continue;
-		}
-		follow_down(&path, false);  // TODO: need to check error
-		umount_ok = may_umount(path.mnt);
-		path_put(&path);
-
-		if (umount_ok) {
-			DPRINTK(("autofs: signaling expire on %s\n",
-								ent->name));
-			return ent; /* Expirable! */
-		}
-
-		DPRINTK(("autofs: didn't expire due to may_umount: %s\n",
-								ent->name));
-	}
-	return NULL;		/* No expirable entries */
-}
-
-void autofs_initialize_hash(struct autofs_dirhash *dh)
-{
-	memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *));
-	INIT_LIST_HEAD(&dh->expiry_head);
-}
-
-struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh,
-						struct qstr *name)
-{
-	struct autofs_dir_ent *dhn;
-
-	DPRINTK(("autofs_hash_lookup: hash = 0x%08x, name = ", name->hash));
-	autofs_say(name->name, name->len);
-
-	for (dhn = dh->h[(unsigned) name->hash % AUTOFS_HASH_SIZE];
-		dhn;
-		dhn = dhn->next) {
-		if (name->hash == dhn->hash &&
-		     name->len == dhn->len &&
-		     !memcmp(name->name, dhn->name, name->len))
-			break;
-	}
-
-	return dhn;
-}
-
-void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent)
-{
-	struct autofs_dir_ent **dhnp;
-
-	DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash));
-	autofs_say(ent->name, ent->len);
-
-	autofs_init_usage(dh, ent);
-	if (ent->dentry)
-		dget(ent->dentry);
-
-	dhnp = &dh->h[(unsigned) ent->hash % AUTOFS_HASH_SIZE];
-	ent->next = *dhnp;
-	ent->back = dhnp;
-	*dhnp = ent;
-	if (ent->next)
-		ent->next->back = &(ent->next);
-}
-
-void autofs_hash_delete(struct autofs_dir_ent *ent)
-{
-	*(ent->back) = ent->next;
-	if (ent->next)
-		ent->next->back = ent->back;
-
-	autofs_delete_usage(ent);
-
-	if (ent->dentry)
-		dput(ent->dentry);
-	kfree(ent->name);
-	kfree(ent);
-}
-
-/*
- * Used by readdir().  We must validate "ptr", so we can't simply make it
- * a pointer.  Values below 0xffff are reserved; calling with any value
- * <= 0x10000 will return the first entry found.
- *
- * "last" can be NULL or the value returned by the last search *if* we
- * want the next sequential entry.
- */
-struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *dh,
-					off_t *ptr, struct autofs_dir_ent *last)
-{
-	int bucket, ecount, i;
-	struct autofs_dir_ent *ent;
-
-	bucket = (*ptr >> 16) - 1;
-	ecount = *ptr & 0xffff;
-
-	if (bucket < 0)
-		bucket = ecount = 0;
-
-	DPRINTK(("autofs_hash_enum: bucket %d, entry %d\n", bucket, ecount));
-
-	ent = last ? last->next : NULL;
-
-	if (ent) {
-		ecount++;
-	} else {
-		while  (bucket < AUTOFS_HASH_SIZE) {
-			ent = dh->h[bucket];
-			for (i = ecount ; ent && i ; i--)
-				ent = ent->next;
-
-			if (ent) {
-				ecount++; /* Point to *next* entry */
-				break;
-			}
-
-			bucket++; ecount = 0;
-		}
-	}
-
-#ifdef DEBUG
-	if (!ent)
-		printk(KERN_DEBUG "autofs_hash_enum: nothing found\n");
-	else {
-		printk(KERN_DEBUG "autofs_hash_enum: found hash %08x, name",
-								ent->hash);
-		autofs_say(ent->name, ent->len);
-	}
-#endif
-
-	*ptr = ((bucket+1) << 16) + ecount;
-	return ent;
-}
-
-/* Iterate over all the ents, and remove all dentry pointers.  Used on
-   entering catatonic mode, in order to make the filesystem unmountable. */
-void autofs_hash_dputall(struct autofs_dirhash *dh)
-{
-	int i;
-	struct autofs_dir_ent *ent;
-
-	for (i = 0 ; i < AUTOFS_HASH_SIZE ; i++) {
-		for (ent = dh->h[i] ; ent ; ent = ent->next) {
-			if (ent->dentry) {
-				dput(ent->dentry);
-				ent->dentry = NULL;
-			}
-		}
-	}
-}
-
-/* Delete everything.  This is used on filesystem destruction, so we
-   make no attempt to keep the pointers valid */
-void autofs_hash_nuke(struct autofs_sb_info *sbi)
-{
-	int i;
-	struct autofs_dir_ent *ent, *nent;
-
-	for (i = 0 ; i < AUTOFS_HASH_SIZE ; i++) {
-		for (ent = sbi->dirhash.h[i] ; ent ; ent = nent) {
-			nent = ent->next;
-			if (ent->dentry)
-				dput(ent->dentry);
-			kfree(ent->name);
-			kfree(ent);
-		}
-	}
-}
diff --git a/drivers/staging/autofs/init.c b/drivers/staging/autofs/init.c
deleted file mode 100644
index 5e4b372..0000000
--- a/drivers/staging/autofs/init.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/init.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include "autofs_i.h"
-
-static struct dentry *autofs_mount(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
-{
-	return mount_nodev(fs_type, flags, data, autofs_fill_super);
-}
-
-static struct file_system_type autofs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "autofs",
-	.mount		= autofs_mount,
-	.kill_sb	= autofs_kill_sb,
-};
-
-static int __init init_autofs_fs(void)
-{
-	return register_filesystem(&autofs_fs_type);
-}
-
-static void __exit exit_autofs_fs(void)
-{
-	unregister_filesystem(&autofs_fs_type);
-}
-
-module_init(init_autofs_fs);
-module_exit(exit_autofs_fs);
-
-#ifdef DEBUG
-void autofs_say(const char *name, int len)
-{
-	printk("(%d: ", len);
-	while ( len-- )
-		printk("%c", *name++);
-	printk(")\n");
-}
-#endif
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/autofs/inode.c b/drivers/staging/autofs/inode.c
deleted file mode 100644
index 74db190..0000000
--- a/drivers/staging/autofs/inode.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/inode.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/file.h>
-#include <linux/parser.h>
-#include <linux/bitops.h>
-#include <linux/magic.h>
-#include "autofs_i.h"
-#include <linux/module.h>
-
-void autofs_kill_sb(struct super_block *sb)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(sb);
-	unsigned int n;
-
-	/*
-	 * In the event of a failure in get_sb_nodev the superblock
-	 * info is not present so nothing else has been setup, so
-	 * just call kill_anon_super when we are called from
-	 * deactivate_super.
-	 */
-	if (!sbi)
-		goto out_kill_sb;
-
-	if (!sbi->catatonic)
-		autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
-
-	put_pid(sbi->oz_pgrp);
-
-	autofs_hash_nuke(sbi);
-	for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) {
-		if (test_bit(n, sbi->symlink_bitmap))
-			kfree(sbi->symlink[n].data);
-	}
-
-	kfree(sb->s_fs_info);
-
-out_kill_sb:
-	DPRINTK(("autofs: shutting down\n"));
-	kill_anon_super(sb);
-}
-
-static const struct super_operations autofs_sops = {
-	.statfs		= simple_statfs,
-	.show_options	= generic_show_options,
-};
-
-enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
-
-static const match_table_t autofs_tokens = {
-	{Opt_fd, "fd=%u"},
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
-	{Opt_pgrp, "pgrp=%u"},
-	{Opt_minproto, "minproto=%u"},
-	{Opt_maxproto, "maxproto=%u"},
-	{Opt_err, NULL}
-};
-
-static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
-		pid_t *pgrp, int *minproto, int *maxproto)
-{
-	char *p;
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-
-	*uid = current_uid();
-	*gid = current_gid();
-	*pgrp = task_pgrp_nr(current);
-
-	*minproto = *maxproto = AUTOFS_PROTO_VERSION;
-
-	*pipefd = -1;
-
-	if (!options)
-		return 1;
-
-	while ((p = strsep(&options, ",")) != NULL) {
-		int token;
-		if (!*p)
-			continue;
-
-		token = match_token(p, autofs_tokens, args);
-		switch (token) {
-		case Opt_fd:
-			if (match_int(&args[0], &option))
-				return 1;
-			*pipefd = option;
-			break;
-		case Opt_uid:
-			if (match_int(&args[0], &option))
-				return 1;
-			*uid = option;
-			break;
-		case Opt_gid:
-			if (match_int(&args[0], &option))
-				return 1;
-			*gid = option;
-			break;
-		case Opt_pgrp:
-			if (match_int(&args[0], &option))
-				return 1;
-			*pgrp = option;
-			break;
-		case Opt_minproto:
-			if (match_int(&args[0], &option))
-				return 1;
-			*minproto = option;
-			break;
-		case Opt_maxproto:
-			if (match_int(&args[0], &option))
-				return 1;
-			*maxproto = option;
-			break;
-		default:
-			return 1;
-		}
-	}
-	return (*pipefd < 0);
-}
-
-int autofs_fill_super(struct super_block *s, void *data, int silent)
-{
-	struct inode * root_inode;
-	struct dentry * root;
-	struct file * pipe;
-	int pipefd;
-	struct autofs_sb_info *sbi;
-	int minproto, maxproto;
-	pid_t pgid;
-
-	save_mount_options(s, data);
-
-	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
-		goto fail_unlock;
-	DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
-
-	s->s_fs_info = sbi;
-	sbi->magic = AUTOFS_SBI_MAGIC;
-	sbi->pipe = NULL;
-	sbi->catatonic = 1;
-	sbi->exp_timeout = 0;
-	autofs_initialize_hash(&sbi->dirhash);
-	sbi->queues = NULL;
-	memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN);
-	sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO;
-	s->s_blocksize = 1024;
-	s->s_blocksize_bits = 10;
-	s->s_magic = AUTOFS_SUPER_MAGIC;
-	s->s_op = &autofs_sops;
-	s->s_time_gran = 1;
-	sbi->sb = s;
-
-	root_inode = autofs_iget(s, AUTOFS_ROOT_INO);
-	if (IS_ERR(root_inode))
-		goto fail_free;
-	root = d_alloc_root(root_inode);
-	pipe = NULL;
-
-	if (!root)
-		goto fail_iput;
-
-	/* Can this call block?  - WTF cares? s is locked. */
-	if (parse_options(data, &pipefd, &root_inode->i_uid,
-				&root_inode->i_gid, &pgid, &minproto,
-				&maxproto)) {
-		printk("autofs: called with bogus options\n");
-		goto fail_dput;
-	}
-
-	/* Couldn't this be tested earlier? */
-	if (minproto > AUTOFS_PROTO_VERSION ||
-	     maxproto < AUTOFS_PROTO_VERSION) {
-		printk("autofs: kernel does not match daemon version\n");
-		goto fail_dput;
-	}
-
-	DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid));
-	sbi->oz_pgrp = find_get_pid(pgid);
-
-	if (!sbi->oz_pgrp) {
-		printk("autofs: could not find process group %d\n", pgid);
-		goto fail_dput;
-	}
-
-	pipe = fget(pipefd);
-	
-	if (!pipe) {
-		printk("autofs: could not open pipe file descriptor\n");
-		goto fail_put_pid;
-	}
-
-	if (!pipe->f_op || !pipe->f_op->write)
-		goto fail_fput;
-	sbi->pipe = pipe;
-	sbi->catatonic = 0;
-
-	/*
-	 * Success! Install the root dentry now to indicate completion.
-	 */
-	s->s_root = root;
-	return 0;
-
-fail_fput:
-	printk("autofs: pipe file descriptor does not contain proper ops\n");
-	fput(pipe);
-fail_put_pid:
-	put_pid(sbi->oz_pgrp);
-fail_dput:
-	dput(root);
-	goto fail_free;
-fail_iput:
-	printk("autofs: get root dentry failed\n");
-	iput(root_inode);
-fail_free:
-	kfree(sbi);
-	s->s_fs_info = NULL;
-fail_unlock:
-	return -EINVAL;
-}
-
-struct inode *autofs_iget(struct super_block *sb, unsigned long ino)
-{
-	unsigned int n;
-	struct autofs_sb_info *sbi = autofs_sbi(sb);
-	struct inode *inode;
-
-	inode = iget_locked(sb, ino);
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
-	if (!(inode->i_state & I_NEW))
-		return inode;
-
-	/* Initialize to the default case (stub directory) */
-
-	inode->i_op = &simple_dir_inode_operations;
-	inode->i_fop = &simple_dir_operations;
-	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
-	inode->i_nlink = 2;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-
-	if (ino == AUTOFS_ROOT_INO) {
-		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
-		inode->i_op = &autofs_root_inode_operations;
-		inode->i_fop = &autofs_root_operations;
-		goto done;
-	} 
-	
-	inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
-	inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
-	
-	if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) {
-		/* Symlink inode - should be in symlink list */
-		struct autofs_symlink *sl;
-
-		n = ino - AUTOFS_FIRST_SYMLINK;
-		if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
-			printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino);
-			goto done;
-		}
-		
-		inode->i_op = &autofs_symlink_inode_operations;
-		sl = &sbi->symlink[n];
-		inode->i_private = sl;
-		inode->i_mode = S_IFLNK | S_IRWXUGO;
-		inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
-		inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
-		inode->i_size = sl->len;
-		inode->i_nlink = 1;
-	}
-
-done:
-	unlock_new_inode(inode);
-	return inode;
-}
diff --git a/drivers/staging/autofs/root.c b/drivers/staging/autofs/root.c
deleted file mode 100644
index bf0e975..0000000
--- a/drivers/staging/autofs/root.c
+++ /dev/null
@@ -1,648 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/root.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/param.h>
-#include <linux/time.h>
-#include <linux/compat.h>
-#include <linux/smp_lock.h>
-#include "autofs_i.h"
-
-static int autofs_root_readdir(struct file *,void *,filldir_t);
-static struct dentry *autofs_root_lookup(struct inode *,struct dentry *, struct nameidata *);
-static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
-static int autofs_root_unlink(struct inode *,struct dentry *);
-static int autofs_root_rmdir(struct inode *,struct dentry *);
-static int autofs_root_mkdir(struct inode *,struct dentry *,int);
-static long autofs_root_ioctl(struct file *,unsigned int,unsigned long);
-#ifdef CONFIG_COMPAT
-static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);
-#endif
-
-const struct file_operations autofs_root_operations = {
-	.llseek		= generic_file_llseek,
-	.read		= generic_read_dir,
-	.readdir	= autofs_root_readdir,
-	.unlocked_ioctl	= autofs_root_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= autofs_root_compat_ioctl,
-#endif
-};
-
-const struct inode_operations autofs_root_inode_operations = {
-        .lookup		= autofs_root_lookup,
-        .unlink		= autofs_root_unlink,
-        .symlink	= autofs_root_symlink,
-        .mkdir		= autofs_root_mkdir,
-        .rmdir		= autofs_root_rmdir,
-};
-
-static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
-	struct autofs_dir_ent *ent = NULL;
-	struct autofs_dirhash *dirhash;
-	struct autofs_sb_info *sbi;
-	struct inode * inode = filp->f_path.dentry->d_inode;
-	off_t onr, nr;
-
-	lock_kernel();
-
-	sbi = autofs_sbi(inode->i_sb);
-	dirhash = &sbi->dirhash;
-	nr = filp->f_pos;
-
-	switch(nr)
-	{
-	case 0:
-		if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
-			goto out;
-		filp->f_pos = ++nr;
-		/* fall through */
-	case 1:
-		if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
-			goto out;
-		filp->f_pos = ++nr;
-		/* fall through */
-	default:
-		while (onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent)) {
-			if (!ent->dentry || d_mountpoint(ent->dentry)) {
-				if (filldir(dirent,ent->name,ent->len,onr,ent->ino,DT_UNKNOWN) < 0)
-					goto out;
-				filp->f_pos = nr;
-			}
-		}
-		break;
-	}
-
-out:
-	unlock_kernel();
-	return 0;
-}
-
-static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, struct autofs_sb_info *sbi)
-{
-	struct inode * inode;
-	struct autofs_dir_ent *ent;
-	int status = 0;
-
-	if (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) {
-		do {
-			if (status && dentry->d_inode) {
-				if (status != -ENOENT)
-					printk("autofs warning: lookup failure on positive dentry, status = %d, name = %s\n", status, dentry->d_name.name);
-				return 0; /* Try to get the kernel to invalidate this dentry */
-			}
-
-			/* Turn this into a real negative dentry? */
-			if (status == -ENOENT) {
-				dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
-				dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-				return 1;
-			} else if (status) {
-				/* Return a negative dentry, but leave it "pending" */
-				return 1;
-			}
-			status = autofs_wait(sbi, &dentry->d_name);
-		} while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)));
-	}
-
-	/* Abuse this field as a pointer to the directory entry, used to
-	   find the expire list pointers */
-	dentry->d_time = (unsigned long) ent;
-	
-	if (!dentry->d_inode) {
-		inode = autofs_iget(sb, ent->ino);
-		if (IS_ERR(inode)) {
-			/* Failed, but leave pending for next time */
-			return 1;
-		}
-		dentry->d_inode = inode;
-	}
-
-	/* If this is a directory that isn't a mount point, bitch at the
-	   daemon and fix it in user space */
-	if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
-		return !autofs_wait(sbi, &dentry->d_name);
-	}
-
-	/* We don't update the usages for the autofs daemon itself, this
-	   is necessary for recursive autofs mounts */
-	if (!autofs_oz_mode(sbi)) {
-		autofs_update_usage(&sbi->dirhash,ent);
-	}
-
-	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-	return 1;
-}
-
-
-/*
- * Revalidate is called on every cache lookup.  Some of those
- * cache lookups may actually happen while the dentry is not
- * yet completely filled in, and revalidate has to delay such
- * lookups..
- */
-static int autofs_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-	struct inode * dir;
-	struct autofs_sb_info *sbi;
-	struct autofs_dir_ent *ent;
-	int res;
-
-	if (nd->flags & LOOKUP_RCU)
-		return -ECHILD;
-
-	lock_kernel();
-	dir = dentry->d_parent->d_inode;
-	sbi = autofs_sbi(dir->i_sb);
-
-	/* Pending dentry */
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
-		if (autofs_oz_mode(sbi))
-			res = 1;
-		else
-			res = try_to_fill_dentry(dentry, dir->i_sb, sbi);
-		unlock_kernel();
-		return res;
-	}
-
-	/* Negative dentry.. invalidate if "old" */
-	if (!dentry->d_inode) {
-		unlock_kernel();
-		return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT);
-	}
-		
-	/* Check for a non-mountpoint directory */
-	if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
-		if (autofs_oz_mode(sbi))
-			res = 1;
-		else
-			res = try_to_fill_dentry(dentry, dir->i_sb, sbi);
-		unlock_kernel();
-		return res;
-	}
-
-	/* Update the usage list */
-	if (!autofs_oz_mode(sbi)) {
-		ent = (struct autofs_dir_ent *) dentry->d_time;
-		if (ent)
-			autofs_update_usage(&sbi->dirhash,ent);
-	}
-	unlock_kernel();
-	return 1;
-}
-
-static const struct dentry_operations autofs_dentry_operations = {
-	.d_revalidate	= autofs_revalidate,
-};
-
-static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-	struct autofs_sb_info *sbi;
-	int oz_mode;
-
-	DPRINTK(("autofs_root_lookup: name = "));
-	lock_kernel();
-	autofs_say(dentry->d_name.name,dentry->d_name.len);
-
-	if (dentry->d_name.len > NAME_MAX) {
-		unlock_kernel();
-		return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
-	}
-
-	sbi = autofs_sbi(dir->i_sb);
-
-	oz_mode = autofs_oz_mode(sbi);
-	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, "
-				"oz_mode = %d\n", task_pid_nr(current),
-				task_pgrp_nr(current), sbi->catatonic,
-				oz_mode));
-
-	/*
-	 * Mark the dentry incomplete, but add it. This is needed so
-	 * that the VFS layer knows about the dentry, and we can count
-	 * on catching any lookups through the revalidate.
-	 *
-	 * Let all the hard work be done by the revalidate function that
-	 * needs to be able to do this anyway..
-	 *
-	 * We need to do this before we release the directory semaphore.
-	 */
-	d_set_d_op(dentry, &autofs_dentry_operations);
-	dentry->d_flags |= DCACHE_AUTOFS_PENDING;
-	d_add(dentry, NULL);
-
-	mutex_unlock(&dir->i_mutex);
-	autofs_revalidate(dentry, nd);
-	mutex_lock(&dir->i_mutex);
-
-	/*
-	 * If we are still pending, check if we had to handle
-	 * a signal. If so we can force a restart..
-	 */
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
-		/* See if we were interrupted */
-		if (signal_pending(current)) {
-			sigset_t *sigset = &current->pending.signal;
-			if (sigismember (sigset, SIGKILL) ||
-			    sigismember (sigset, SIGQUIT) ||
-			    sigismember (sigset, SIGINT)) {
-				unlock_kernel();
-				return ERR_PTR(-ERESTARTNOINTR);
-			}
-		}
-	}
-	unlock_kernel();
-
-	/*
-	 * If this dentry is unhashed, then we shouldn't honour this
-	 * lookup even if the dentry is positive.  Returning ENOENT here
-	 * doesn't do the right thing for all system calls, but it should
-	 * be OK for the operations we permit from an autofs.
-	 */
-	if (dentry->d_inode && d_unhashed(dentry))
-		return ERR_PTR(-ENOENT);
-
-	return NULL;
-}
-
-static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	unsigned int n;
-	int slsize;
-	struct autofs_symlink *sl;
-	struct inode *inode;
-
-	DPRINTK(("autofs_root_symlink: %s <- ", symname));
-	autofs_say(dentry->d_name.name,dentry->d_name.len);
-
-	lock_kernel();
-	if (!autofs_oz_mode(sbi)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	if (autofs_hash_lookup(dh, &dentry->d_name)) {
-		unlock_kernel();
-		return -EEXIST;
-	}
-
-	n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
-	if (n >= AUTOFS_MAX_SYMLINKS) {
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	set_bit(n,sbi->symlink_bitmap);
-	sl = &sbi->symlink[n];
-	sl->len = strlen(symname);
-	sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
-	if (!sl->data) {
-		clear_bit(n,sbi->symlink_bitmap);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if (!ent) {
-		kfree(sl->data);
-		clear_bit(n,sbi->symlink_bitmap);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
-	if (!ent->name) {
-		kfree(sl->data);
-		kfree(ent);
-		clear_bit(n,sbi->symlink_bitmap);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	memcpy(sl->data,symname,slsize);
-	sl->mtime = get_seconds();
-
-	ent->ino = AUTOFS_FIRST_SYMLINK + n;
-	ent->hash = dentry->d_name.hash;
-	memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len));
-	ent->dentry = NULL;	/* We don't keep the dentry for symlinks */
-
-	autofs_hash_insert(dh,ent);
-
-	inode = autofs_iget(dir->i_sb, ent->ino);
-	if (IS_ERR(inode))
-		return PTR_ERR(inode);
-
-	d_instantiate(dentry, inode);
-	unlock_kernel();
-	return 0;
-}
-
-/*
- * NOTE!
- *
- * Normal filesystems would do a "d_delete()" to tell the VFS dcache
- * that the file no longer exists. However, doing that means that the
- * VFS layer can turn the dentry into a negative dentry, which we
- * obviously do not want (we're dropping the entry not because it
- * doesn't exist, but because it has timed out).
- *
- * Also see autofs_root_rmdir()..
- */
-static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	unsigned int n;
-
-	/* This allows root to remove symlinks */
-	lock_kernel();
-	if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if (!ent) {
-		unlock_kernel();
-		return -ENOENT;
-	}
-
-	n = ent->ino - AUTOFS_FIRST_SYMLINK;
-	if (n >= AUTOFS_MAX_SYMLINKS) {
-		unlock_kernel();
-		return -EISDIR;	/* It's a directory, dummy */
-	}
-	if (!test_bit(n,sbi->symlink_bitmap)) {
-		unlock_kernel();
-		return -EINVAL;	/* Nonexistent symlink?  Shouldn't happen */
-	}
-	
-	dentry->d_time = (unsigned long)(struct autofs_dirhash *)NULL;
-	autofs_hash_delete(ent);
-	clear_bit(n,sbi->symlink_bitmap);
-	kfree(sbi->symlink[n].data);
-	d_drop(dentry);
-	
-	unlock_kernel();
-	return 0;
-}
-
-static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-
-	lock_kernel();
-	if (!autofs_oz_mode(sbi)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if (!ent) {
-		unlock_kernel();
-		return -ENOENT;
-	}
-
-	if ((unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO) {
-		unlock_kernel();
-		return -ENOTDIR; /* Not a directory */
-	}
-
-	if (ent->dentry != dentry) {
-		printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name);
-	}
-
-	dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL;
-	autofs_hash_delete(ent);
-	drop_nlink(dir);
-	d_drop(dentry);
-	unlock_kernel();
-
-	return 0;
-}
-
-static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	struct inode *inode;
-	ino_t ino;
-
-	lock_kernel();
-	if (!autofs_oz_mode(sbi)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if (ent) {
-		unlock_kernel();
-		return -EEXIST;
-	}
-
-	if (sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO) {
-		printk("autofs: Out of inode numbers -- what the heck did you do??\n");
-		unlock_kernel();
-		return -ENOSPC;
-	}
-	ino = sbi->next_dir_ino++;
-
-	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if (!ent) {
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
-	if (!ent->name) {
-		kfree(ent);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent->hash = dentry->d_name.hash;
-	memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len));
-	ent->ino = ino;
-	ent->dentry = dentry;
-	autofs_hash_insert(dh,ent);
-
-	inc_nlink(dir);
-
-	inode = autofs_iget(dir->i_sb, ino);
-	if (IS_ERR(inode)) {
-		drop_nlink(dir);
-		return PTR_ERR(inode);
-	}
-
-	d_instantiate(dentry, inode);
-	unlock_kernel();
-
-	return 0;
-}
-
-/* Get/set timeout ioctl() operation */
-#ifdef CONFIG_COMPAT
-static inline int autofs_compat_get_set_timeout(struct autofs_sb_info *sbi,
-					 unsigned int __user *p)
-{
-	unsigned long ntimeout;
-
-	if (get_user(ntimeout, p) ||
-	    put_user(sbi->exp_timeout / HZ, p))
-		return -EFAULT;
-
-	if (ntimeout > UINT_MAX/HZ)
-		sbi->exp_timeout = 0;
-	else
-		sbi->exp_timeout = ntimeout * HZ;
-
-	return 0;
-}
-#endif
-
-static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
-					 unsigned long __user *p)
-{
-	unsigned long ntimeout;
-
-	if (get_user(ntimeout, p) ||
-	    put_user(sbi->exp_timeout / HZ, p))
-		return -EFAULT;
-
-	if (ntimeout > ULONG_MAX/HZ)
-		sbi->exp_timeout = 0;
-	else
-		sbi->exp_timeout = ntimeout * HZ;
-
-	return 0;
-}
-
-/* Return protocol version */
-static inline int autofs_get_protover(int __user *p)
-{
-	return put_user(AUTOFS_PROTO_VERSION, p);
-}
-
-/* Perform an expiry operation */
-static inline int autofs_expire_run(struct super_block *sb,
-				    struct autofs_sb_info *sbi,
-				    struct vfsmount *mnt,
-				    struct autofs_packet_expire __user *pkt_p)
-{
-	struct autofs_dir_ent *ent;
-	struct autofs_packet_expire pkt;
-
-	memset(&pkt,0,sizeof pkt);
-
-	pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
-	pkt.hdr.type = autofs_ptype_expire;
-
-	if (!sbi->exp_timeout || !(ent = autofs_expire(sb,sbi,mnt)))
-		return -EAGAIN;
-
-	pkt.len = ent->len;
-	memcpy(pkt.name, ent->name, pkt.len);
-	pkt.name[pkt.len] = '\0';
-
-	if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
-		return -EFAULT;
-
-	return 0;
-}
-
-/*
- * ioctl()'s on the root directory is the chief method for the daemon to
- * generate kernel reactions
- */
-static int autofs_do_root_ioctl(struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
-	void __user *argp = (void __user *)arg;
-
-	DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,task_pgrp_nr(current)));
-
-	if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
-	     _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
-		return -ENOTTY;
-	
-	if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	
-	switch(cmd) {
-	case AUTOFS_IOC_READY:	/* Wait queue: go ahead and retry */
-		return autofs_wait_release(sbi,(autofs_wqt_t)arg,0);
-	case AUTOFS_IOC_FAIL:	/* Wait queue: fail with ENOENT */
-		return autofs_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT);
-	case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
-		autofs_catatonic_mode(sbi);
-		return 0;
-	case AUTOFS_IOC_PROTOVER: /* Get protocol version */
-		return autofs_get_protover(argp);
-#ifdef CONFIG_COMPAT
-	case AUTOFS_IOC_SETTIMEOUT32:
-		return autofs_compat_get_set_timeout(sbi, argp);
-#endif
-	case AUTOFS_IOC_SETTIMEOUT:
-		return autofs_get_set_timeout(sbi, argp);
-	case AUTOFS_IOC_EXPIRE:
-		return autofs_expire_run(inode->i_sb, sbi, filp->f_path.mnt,
-					 argp);
-	default:
-		return -ENOSYS;
-	}
-
-}
-
-static long autofs_root_ioctl(struct file *filp,
-			     unsigned int cmd, unsigned long arg)
-{
-	int ret;
-
-	lock_kernel();
-	ret = autofs_do_root_ioctl(filp->f_path.dentry->d_inode,
-				   filp, cmd, arg);
-	unlock_kernel();
-
-	return ret;
-}
-
-#ifdef CONFIG_COMPAT
-static long autofs_root_compat_ioctl(struct file *filp,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	int ret;
-
-	lock_kernel();
-	if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
-		ret = autofs_do_root_ioctl(inode, filp, cmd, arg);
-	else
-		ret = autofs_do_root_ioctl(inode, filp, cmd,
-			(unsigned long)compat_ptr(arg));
-	unlock_kernel();
-
-	return ret;
-}
-#endif
diff --git a/drivers/staging/autofs/symlink.c b/drivers/staging/autofs/symlink.c
deleted file mode 100644
index ff2c65c..0000000
--- a/drivers/staging/autofs/symlink.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/symlink.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
-
-#include "autofs_i.h"
-
-/* Nothing to release.. */
-static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	char *s=((struct autofs_symlink *)dentry->d_inode->i_private)->data;
-	nd_set_link(nd, s);
-	return NULL;
-}
-
-const struct inode_operations autofs_symlink_inode_operations = {
-	.readlink	= generic_readlink,
-	.follow_link	= autofs_follow_link
-};
diff --git a/drivers/staging/autofs/waitq.c b/drivers/staging/autofs/waitq.c
deleted file mode 100644
index d3c8cc9..0000000
--- a/drivers/staging/autofs/waitq.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/waitq.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * This file is part of the Linux kernel and is made available under
- * the terms of the GNU General Public License, version 2, or at your
- * option, any later version, incorporated herein by reference.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/signal.h>
-#include <linux/file.h>
-#include "autofs_i.h"
-
-/* We make this a static variable rather than a part of the superblock; it
-   is better if we don't reassign numbers easily even across filesystems */
-static autofs_wqt_t autofs_next_wait_queue = 1;
-
-/* These are the signals we allow interrupting a pending mount */
-#define SHUTDOWN_SIGS	(sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT))
-
-void autofs_catatonic_mode(struct autofs_sb_info *sbi)
-{
-	struct autofs_wait_queue *wq, *nwq;
-
-	DPRINTK(("autofs: entering catatonic mode\n"));
-
-	sbi->catatonic = 1;
-	wq = sbi->queues;
-	sbi->queues = NULL;	/* Erase all wait queues */
-	while ( wq ) {
-		nwq = wq->next;
-		wq->status = -ENOENT; /* Magic is gone - report failure */
-		kfree(wq->name);
-		wq->name = NULL;
-		wake_up(&wq->queue);
-		wq = nwq;
-	}
-	fput(sbi->pipe);	/* Close the pipe */
-	sbi->pipe = NULL;
-	autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
-}
-
-static int autofs_write(struct file *file, const void *addr, int bytes)
-{
-	unsigned long sigpipe, flags;
-	mm_segment_t fs;
-	const char *data = (const char *)addr;
-	ssize_t wr = 0;
-
-	/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
-
-	sigpipe = sigismember(&current->pending.signal, SIGPIPE);
-
-	/* Save pointer to user space and point back to kernel space */
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	while (bytes &&
-	       (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {
-		data += wr;
-		bytes -= wr;
-	}
-
-	set_fs(fs);
-
-	/* Keep the currently executing process from receiving a
-	   SIGPIPE unless it was already supposed to get one */
-	if (wr == -EPIPE && !sigpipe) {
-		spin_lock_irqsave(&current->sighand->siglock, flags);
-		sigdelset(&current->pending.signal, SIGPIPE);
-		recalc_sigpending();
-		spin_unlock_irqrestore(&current->sighand->siglock, flags);
-	}
-
-	return (bytes > 0);
-}
-	
-static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_queue *wq)
-{
-	struct autofs_packet_missing pkt;
-
-	DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token));
-	autofs_say(wq->name,wq->len);
-
-	memset(&pkt,0,sizeof pkt); /* For security reasons */
-
-	pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
-	pkt.hdr.type = autofs_ptype_missing;
-	pkt.wait_queue_token = wq->wait_queue_token;
-	pkt.len = wq->len;
-        memcpy(pkt.name, wq->name, pkt.len);
-	pkt.name[pkt.len] = '\0';
-
-	if ( autofs_write(sbi->pipe,&pkt,sizeof(struct autofs_packet_missing)) )
-		autofs_catatonic_mode(sbi);
-}
-
-int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name)
-{
-	struct autofs_wait_queue *wq;
-	int status;
-
-	/* In catatonic mode, we don't wait for nobody */
-	if ( sbi->catatonic )
-		return -ENOENT;
-	
-	/* We shouldn't be able to get here, but just in case */
-	if ( name->len > NAME_MAX )
-		return -ENOENT;
-
-	for ( wq = sbi->queues ; wq ; wq = wq->next ) {
-		if ( wq->hash == name->hash &&
-		     wq->len == name->len &&
-		     wq->name && !memcmp(wq->name,name->name,name->len) )
-			break;
-	}
-	
-	if ( !wq ) {
-		/* Create a new wait queue */
-		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
-		if ( !wq )
-			return -ENOMEM;
-
-		wq->name = kmalloc(name->len,GFP_KERNEL);
-		if ( !wq->name ) {
-			kfree(wq);
-			return -ENOMEM;
-		}
-		wq->wait_queue_token = autofs_next_wait_queue++;
-		init_waitqueue_head(&wq->queue);
-		wq->hash = name->hash;
-		wq->len = name->len;
-		wq->status = -EINTR; /* Status return if interrupted */
-		memcpy(wq->name, name->name, name->len);
-		wq->next = sbi->queues;
-		sbi->queues = wq;
-
-		/* autofs_notify_daemon() may block */
-		wq->wait_ctr = 2;
-		autofs_notify_daemon(sbi,wq);
-	} else
-		wq->wait_ctr++;
-
-	/* wq->name is NULL if and only if the lock is already released */
-
-	if ( sbi->catatonic ) {
-		/* We might have slept, so check again for catatonic mode */
-		wq->status = -ENOENT;
-		kfree(wq->name);
-		wq->name = NULL;
-	}
-
-	if ( wq->name ) {
-		/* Block all but "shutdown" signals while waiting */
-		sigset_t sigmask;
-
-		siginitsetinv(&sigmask, SHUTDOWN_SIGS);
-		sigprocmask(SIG_BLOCK, &sigmask, &sigmask);
-
-		interruptible_sleep_on(&wq->queue);
-
-		sigprocmask(SIG_SETMASK, &sigmask, NULL);
-	} else {
-		DPRINTK(("autofs_wait: skipped sleeping\n"));
-	}
-
-	status = wq->status;
-
-	if ( ! --wq->wait_ctr )	/* Are we the last process to need status? */
-		kfree(wq);
-
-	return status;
-}
-
-
-int autofs_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_token, int status)
-{
-	struct autofs_wait_queue *wq, **wql;
-
-	for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) {
-		if ( wq->wait_queue_token == wait_queue_token )
-			break;
-	}
-	if ( !wq )
-		return -EINVAL;
-
-	*wql = wq->next;	/* Unlink from chain */
-	kfree(wq->name);
-	wq->name = NULL;	/* Do not wait on this queue */
-
-	wq->status = status;
-
-	if ( ! --wq->wait_ctr )	/* Is anyone still waiting for this guy? */
-		kfree(wq);
-	else
-		wake_up(&wq->queue);
-
-	return 0;
-}
-
diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
index 31674ea..867dbf1 100644
--- a/drivers/staging/bcm/Bcmchar.c
+++ b/drivers/staging/bcm/Bcmchar.c
@@ -15,21 +15,20 @@
 
 static int bcm_char_open(struct inode *inode, struct file * filp)
 {
-	PMINI_ADAPTER 		Adapter = NULL;
-    PPER_TARANG_DATA 	pTarang = NULL;
+	PMINI_ADAPTER       Adapter = NULL;
+	PPER_TARANG_DATA    pTarang = NULL;
 
 	Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    pTarang = (PPER_TARANG_DATA)kmalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL);
-    if (!pTarang)
-        return -ENOMEM;
+	pTarang = kzalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL);
+	if (!pTarang)
+		return -ENOMEM;
 
-	memset (pTarang, 0, sizeof(PER_TARANG_DATA));
-    pTarang->Adapter = Adapter;
-	pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB) ;
+	pTarang->Adapter = Adapter;
+	pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB);
 
 	down(&Adapter->RxAppControlQueuelock);
-    pTarang->next = Adapter->pTarangs;
-    Adapter->pTarangs = pTarang;
+	pTarang->next = Adapter->pTarangs;
+	Adapter->pTarangs = pTarang;
 	up(&Adapter->RxAppControlQueuelock);
 
 	/* Store the Adapter structure */
@@ -41,118 +40,117 @@ static int bcm_char_open(struct inode *inode, struct file * filp)
 	nonseekable_open(inode, filp);
 	return 0;
 }
+
 static int bcm_char_release(struct inode *inode, struct file *filp)
 {
-    PPER_TARANG_DATA pTarang, tmp, ptmp;
-	PMINI_ADAPTER Adapter=NULL;
-    struct sk_buff * pkt, * npkt;
+	PPER_TARANG_DATA pTarang, tmp, ptmp;
+	PMINI_ADAPTER Adapter = NULL;
+	struct sk_buff *pkt, *npkt;
 
-    pTarang = (PPER_TARANG_DATA)filp->private_data;
+	pTarang = (PPER_TARANG_DATA)filp->private_data;
 
-    if(pTarang == NULL)
-	{
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ptarang is null\n");
-	return 0;
+	if (pTarang == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"ptarang is null\n");
+		return 0;
 	}
 
 	Adapter = pTarang->Adapter;
 
-    down( &Adapter->RxAppControlQueuelock);
+	down(&Adapter->RxAppControlQueuelock);
 
-    tmp = Adapter->pTarangs;
-    for ( ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next )
-	{
-        if ( tmp == pTarang )
+	tmp = Adapter->pTarangs;
+	for (ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next) {
+		if (tmp == pTarang)
 			break;
 	}
 
-    if ( tmp )
-	{
-        if ( !ptmp )
-            Adapter->pTarangs = tmp->next;
-        else
-            ptmp->next = tmp->next;
+	if (tmp) {
+		if (!ptmp)
+			Adapter->pTarangs = tmp->next;
+		else
+			ptmp->next = tmp->next;
+	} else {
+		up(&Adapter->RxAppControlQueuelock);
+		return 0;
 	}
 
-    else
-	{
-    	up( &Adapter->RxAppControlQueuelock);
-	return 0;
+	pkt = pTarang->RxAppControlHead;
+	while (pkt) {
+		npkt = pkt->next;
+		kfree_skb(pkt);
+		pkt = npkt;
 	}
 
-    pkt = pTarang->RxAppControlHead;
-    while ( pkt )
-	{
-        npkt = pkt->next;
-        kfree_skb(pkt);
-        pkt = npkt;
-	}
-
-    up( &Adapter->RxAppControlQueuelock);
+	up(&Adapter->RxAppControlQueuelock);
 
-    /*Stop Queuing the control response Packets*/
-    atomic_dec(&Adapter->ApplicationRunning);
+	/*Stop Queuing the control response Packets*/
+	atomic_dec(&Adapter->ApplicationRunning);
 
-    kfree(pTarang);
+	kfree(pTarang);
 
 	/* remove this filp from the asynchronously notified filp's */
-    filp->private_data = NULL;
-    return 0;
+	filp->private_data = NULL;
+	return 0;
 }
 
-static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
+static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
+			     loff_t *f_pos)
 {
 	PPER_TARANG_DATA pTarang = filp->private_data;
 	PMINI_ADAPTER	Adapter = pTarang->Adapter;
-	struct sk_buff* Packet = NULL;
+	struct sk_buff *Packet = NULL;
 	ssize_t         PktLen = 0;
-	int 		wait_ret_val=0;
+	int             wait_ret_val = 0;
+	unsigned long ret = 0;
 
 	wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue,
-		(pTarang->RxAppControlHead || Adapter->device_removed));
-	if((wait_ret_val == -ERESTARTSYS))
-	{
-   		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Exiting as i've been asked to exit!!!\n");
+						(pTarang->RxAppControlHead ||
+						 Adapter->device_removed));
+	if ((wait_ret_val == -ERESTARTSYS)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"Exiting as i've been asked to exit!!!\n");
 		return wait_ret_val;
 	}
 
-	if(Adapter->device_removed)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device Removed... Killing the Apps...\n");
+	if (Adapter->device_removed) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"Device Removed... Killing the Apps...\n");
 		return -ENODEV;
 	}
 
-	if(FALSE == Adapter->fw_download_done)
+	if (FALSE == Adapter->fw_download_done)
 		return -EACCES;
 
-    down( &Adapter->RxAppControlQueuelock);
+	down(&Adapter->RxAppControlQueuelock);
 
-	if(pTarang->RxAppControlHead)
-	{
+	if (pTarang->RxAppControlHead) {
 		Packet = pTarang->RxAppControlHead;
-		DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail);
+		DEQUEUEPACKET(pTarang->RxAppControlHead,
+			      pTarang->RxAppControlTail);
 		pTarang->AppCtrlQueueLen--;
 	}
 
-    up(&Adapter->RxAppControlQueuelock);
+	up(&Adapter->RxAppControlQueuelock);
 
-	if(Packet)
-	{
+	if (Packet) {
 		PktLen = Packet->len;
-		if(copy_to_user(buf, Packet->data, min_t(size_t, PktLen, size)))
-		{
+		ret = copy_to_user(buf, Packet->data,
+				   min_t(size_t, PktLen, size));
+		if (ret) {
 			dev_kfree_skb(Packet);
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nReturning from copy to user failure \n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+					"Returning from copy to user failure\n");
 			return -EFAULT;
 		}
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
 				"Read %zd Bytes From Adapter packet = %p by process %d!\n",
 				PktLen, Packet, current->pid);
 		dev_kfree_skb(Packet);
 	}
 
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<====\n");
-    return PktLen;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<\n");
+	return PktLen;
 }
 
 static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
@@ -2024,6 +2022,12 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 				if(Status)
 				{
 					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space");
+					Status = -EFAULT;
+					break;
+				}
+
+				if (IoBuffer.InputLength != sizeof(unsigned long)) {
+					Status = -EINVAL;
 					break;
 				}
 
@@ -2031,6 +2035,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 				if(Status)
 				{
 					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space");
+					Status = -EFAULT;
 					break;
 				}
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
@@ -2093,7 +2098,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
 }
 
 
-static struct file_operations bcm_fops = {
+static const struct file_operations bcm_fops = {
 	.owner    = THIS_MODULE,
 	.open     = bcm_char_open,
 	.release  = bcm_char_release,
@@ -2107,32 +2112,32 @@ extern struct class *bcm_class;
 int register_control_device_interface(PMINI_ADAPTER Adapter)
 {
 
-	if(Adapter->major>0)
+	if (Adapter->major > 0)
 		return Adapter->major;
 
 	Adapter->major = register_chrdev(0, DEV_NAME, &bcm_fops);
-	if(Adapter->major < 0) {
+	if (Adapter->major < 0) {
 		pr_err(DRV_NAME ": could not created character device\n");
 		return Adapter->major;
 	}
 
-	Adapter->pstCreatedClassDevice = device_create (bcm_class, NULL,
-							MKDEV(Adapter->major, 0), Adapter,
-							DEV_NAME);
+	Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL,
+						       MKDEV(Adapter->major, 0),
+						       Adapter, DEV_NAME);
 
-	if(IS_ERR(Adapter->pstCreatedClassDevice)) {
+	if (IS_ERR(Adapter->pstCreatedClassDevice)) {
 		pr_err(DRV_NAME ": class device create failed\n");
 		unregister_chrdev(Adapter->major, DEV_NAME);
 		return PTR_ERR(Adapter->pstCreatedClassDevice);
 	}
-			
+
 	return 0;
 }
 
 void unregister_control_device_interface(PMINI_ADAPTER Adapter)
 {
-	if(Adapter->major > 0) {
-		device_destroy (bcm_class, MKDEV(Adapter->major, 0));
+	if (Adapter->major > 0) {
+		device_destroy(bcm_class, MKDEV(Adapter->major, 0));
 		unregister_chrdev(Adapter->major, DEV_NAME);
 	}
 }
diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c
index a6ce239..133e146 100644
--- a/drivers/staging/bcm/Bcmnet.c
+++ b/drivers/staging/bcm/Bcmnet.c
@@ -8,7 +8,7 @@ static INT bcm_open(struct net_device *dev)
 
 	if (Adapter->fw_download_done == FALSE) {
 		pr_notice(PFX "%s: link up failed (download in progress)\n",
- 			  dev->name);
+			  dev->name);
 		return -EBUSY;
 	}
 
@@ -50,7 +50,7 @@ static u16 bcm_select_queue(struct net_device *dev, struct sk_buff *skb)
 * Description - This is the main transmit function for our virtual
 *		interface(eth0). It handles the ARP packets. It
 *		clones this packet and then Queue it to a suitable
-* 		Queue. Then calls the transmit_packet().
+*		Queue. Then calls the transmit_packet().
 *
 * Parameter   -	 skb - Pointer to the socket buffer structure
 *		 dev - Pointer to the virtual net device structure
@@ -110,13 +110,13 @@ static netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev)
 Register other driver entry points with the kernel
 */
 static const struct net_device_ops bcmNetDevOps = {
-    .ndo_open		= bcm_open,
-    .ndo_stop 		= bcm_close,
-    .ndo_start_xmit	= bcm_transmit,
-    .ndo_change_mtu	= eth_change_mtu,
-    .ndo_set_mac_address = eth_mac_addr,
-    .ndo_validate_addr	= eth_validate_addr,
-    .ndo_select_queue	= bcm_select_queue,
+	.ndo_open		= bcm_open,
+	.ndo_stop		= bcm_close,
+	.ndo_start_xmit	        = bcm_transmit,
+	.ndo_change_mtu	        = eth_change_mtu,
+	.ndo_set_mac_address    = eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_select_queue	= bcm_select_queue,
 };
 
 static struct device_type wimax_type = {
@@ -138,7 +138,8 @@ static int bcm_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 	return 0;
 }
 
-static void bcm_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void bcm_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
 {
 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
 	PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter;
@@ -160,14 +161,14 @@ static u32 bcm_get_link(struct net_device *dev)
 	return Adapter->LinkUpStatus;
 }
 
-static u32 bcm_get_msglevel (struct net_device *dev)
+static u32 bcm_get_msglevel(struct net_device *dev)
 {
 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
 
 	return Adapter->msg_enable;
 }
 
-static void bcm_set_msglevel (struct net_device *dev, u32 level)
+static void bcm_set_msglevel(struct net_device *dev, u32 level)
 {
 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
 
@@ -177,7 +178,7 @@ static void bcm_set_msglevel (struct net_device *dev, u32 level)
 static const struct ethtool_ops bcm_ethtool_ops = {
 	.get_settings	= bcm_get_settings,
 	.get_drvinfo	= bcm_get_drvinfo,
-	.get_link 	= bcm_get_link,
+	.get_link	= bcm_get_link,
 	.get_msglevel	= bcm_get_msglevel,
 	.set_msglevel	= bcm_set_msglevel,
 };
@@ -206,7 +207,7 @@ int register_networkdev(PMINI_ADAPTER Adapter)
 	if (result != STATUS_SUCCESS) {
 		dev_err(&udev->dev,
 			PFX "Error in Reading the mac Address: %d", result);
- 		return -EIO;
+		return -EIO;
 	}
 
 	result = register_netdev(net);
@@ -233,6 +234,6 @@ void unregister_networkdev(PMINI_ADAPTER Adapter)
 	if (netif_msg_probe(Adapter))
 		dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n",
 			 net->name, xdev->bus->bus_name, xdev->devpath);
- 
+
 	unregister_netdev(Adapter->dev);
 }
diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c
index 5ac4582..9be184f 100644
--- a/drivers/staging/bcm/CmHost.c
+++ b/drivers/staging/bcm/CmHost.c
@@ -1,6 +1,6 @@
 /************************************************************
 *			CMHOST.C
-*	This file contains the routines for handling Connnection
+*	This file contains the routines for handling Connection
 *	Management.
 ************************************************************/
 
@@ -974,11 +974,7 @@ static VOID CopyToAdapter( register PMINI_ADAPTER Adapter,		/**<Pointer to the A
 			!(psfLocalSet->u8RequesttransmissionPolicy &
 				MASK_DISABLE_HEADER_SUPPRESSION);
 
-	if(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication)
-	{
-		kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication);
-		Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = NULL;
-	}
+	kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication);
 	Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = pstAddIndication;
 
 	//Re Sort the SF list in PackInfo according to Traffic Priority
@@ -1971,10 +1967,7 @@ INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter)
 
 INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter)
 {
-	if(Adapter->caDsxReqResp)
-	{
-		kfree(Adapter->caDsxReqResp);
-	}
+	kfree(Adapter->caDsxReqResp);
 	return 0;
 
 }
diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c
index f585aae..d624f35 100644
--- a/drivers/staging/bcm/Misc.c
+++ b/drivers/staging/bcm/Misc.c
@@ -498,13 +498,12 @@ VOID LinkMessage(PMINI_ADAPTER Adapter)
 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
 	if(Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup)
 	{
-		pstLinkRequest=kmalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
+		pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
 		if(!pstLinkRequest)
 		{
 			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
 			return;
 		}
-		memset(pstLinkRequest,0,sizeof(LINK_REQUEST));
 		//sync up request...
 		Adapter->LinkStatus = WAIT_FOR_SYNC;// current link status
 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
@@ -516,13 +515,12 @@ VOID LinkMessage(PMINI_ADAPTER Adapter)
 	}
 	else if(Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp)
 	{
-		pstLinkRequest=kmalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
+		pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
 		if(!pstLinkRequest)
 		{
 			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
 			return;
 		}
-		memset(pstLinkRequest,0,sizeof(LINK_REQUEST));
 		//LINK_UP_REQUEST
 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
 		pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD;
diff --git a/drivers/staging/brcm80211/Kconfig b/drivers/staging/brcm80211/Kconfig
index 57d2d1b..b6f8635 100644
--- a/drivers/staging/brcm80211/Kconfig
+++ b/drivers/staging/brcm80211/Kconfig
@@ -2,13 +2,7 @@ menuconfig BRCM80211
 	tristate "Broadcom IEEE802.11n WLAN drivers"
 	depends on WLAN
 
-choice
-	prompt "Broadcom IEEE802.11n driver style"
-	depends on BRCM80211
-	help
-	Select the appropriate driver style from the list below.
-
-config BRCM80211_PCI
+config BRCMSMAC
 	bool "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
 	depends on PCI
 	depends on BRCM80211 && MAC80211
@@ -16,7 +10,7 @@ config BRCM80211_PCI
 	---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 brcm80211.ko.
+	  be called brcmsmac.ko.
 
 config BRCMFMAC
 	bool "Broadcom IEEE802.11n embedded FullMAC WLAN driver"
@@ -30,4 +24,10 @@ config BRCMFMAC
 	  Broadcom IEEE802.11n FullMAC chipsets.  This driver uses the kernel's
 	  wireless extensions subsystem.  If you choose to build a module,
 	  it'll be called brcmfmac.ko.
-endchoice
+
+config BRCMDBG
+	bool "Broadcom driver debug functions"
+	default n
+	depends on BRCM80211
+	---help---
+	  Selecting this enables additional code for debug purposes.
diff --git a/drivers/staging/brcm80211/Makefile b/drivers/staging/brcm80211/Makefile
index 1953ebe..c064cdf 100644
--- a/drivers/staging/brcm80211/Makefile
+++ b/drivers/staging/brcm80211/Makefile
@@ -15,62 +15,9 @@
 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-ccflags-y :=					\
-	-DBCMDBG				\
-	-DWLC_HIGH				\
-	-DSTA					\
-	-DWME					\
-	-DWL11N					\
-	-DDBAND					\
-	-DBCMDMA32				\
-	-DBCMNVRAMR				\
-	-Idrivers/staging/brcm80211/sys		\
-	-Idrivers/staging/brcm80211/phy		\
-	-Idrivers/staging/brcm80211/util	\
-	-Idrivers/staging/brcm80211/include
+# common flags
+subdir-ccflags-y					:= -DBCMDMA32
+subdir-ccflags-$(CONFIG_BRCMDBG)	+= -DBCMDBG -DBCMDBG_ASSERT
 
-PCI_CFLAGS := -DWLC_LOW
-
-BRCM80211_OFILES := \
-	util/siutils.o \
-	util/aiutils.o \
-	util/bcmotp.o \
-	util/bcmsrom.o \
-	util/bcmutils.o \
-	util/bcmwifi.o \
-	util/hndpmu.o \
-	util/linux_osl.o \
-	sys/wlc_alloc.o \
-	sys/wlc_antsel.o \
-	sys/wlc_channel.o \
-	sys/wlc_event.o \
-	sys/wlc_mac80211.o \
-	sys/wlc_rate.o \
-	sys/wlc_stf.o \
-	sys/wl_mac80211.o \
-	sys/wlc_ampdu.o
-
-PCIFILES := \
-	phy/wlc_phy_cmn.o \
-	phy/wlc_phy_lcn.o \
-	phy/wlc_phy_n.o \
-	phy/wlc_phytbl_lcn.o \
-	phy/wlc_phytbl_n.o \
-	sys/wlc_bmac.o \
-	sys/wlc_phy_shim.o \
-	sys/wl_ucode_loader.o \
-	util/hnddma.o \
-	util/nicpci.o \
-	util/nvram/nvram_ro.o \
-	util/qmath.o
-
-MODULEPFX := brcm80211
-
-# PCI driver
-ifeq ($(CONFIG_BRCM80211_PCI),y)
-obj-m	+= $(MODULEPFX).o
-ccflags-y += $(PCI_CFLAGS)
-$(MODULEPFX)-objs	= $(BRCM80211_OFILES) $(PCIFILES)
-endif
-
-obj-$(CONFIG_BRCMFMAC)    += brcmfmac/
+obj-$(CONFIG_BRCMFMAC)	+= brcmfmac/
+obj-$(CONFIG_BRCMSMAC)	+= brcmsmac/
diff --git a/drivers/staging/brcm80211/brcmfmac/Kconfig b/drivers/staging/brcm80211/brcmfmac/Kconfig
deleted file mode 100644
index e9f3037..0000000
--- a/drivers/staging/brcm80211/brcmfmac/Kconfig
+++ /dev/null
@@ -1,15 +0,0 @@
-menuconfig BRCMFMAC
-	tristate "Broadcom fullmac wireless cards support"
-	depends on MMC
-	depends on CFG80211
-	select FW_LOADER
-	select WIRELESS_EXT
-	select WEXT_PRIV
-	---help---
-	  This module adds support for wireless adapters based on
-	  Broadcom fullmac chipsets.
-	  This driver uses the kernel's wireless extensions subsystem.
-	  If you choose to build a module, it'll be called brcmfmac.ko. Say M if
-	  unsure.
-
-
diff --git a/drivers/staging/brcm80211/brcmfmac/Makefile b/drivers/staging/brcm80211/brcmfmac/Makefile
index 76f2d8b..ac5a7d4 100644
--- a/drivers/staging/brcm80211/brcmfmac/Makefile
+++ b/drivers/staging/brcm80211/brcmfmac/Makefile
@@ -17,13 +17,11 @@
 
 ccflags-y :=			\
 	-DARP_OFFLOAD_SUPPORT	\
-	-DBCMDBG		\
 	-DBCMLXSDMMC		\
 	-DBCMPLATFORM_BUS	\
 	-DBCMSDIO		\
 	-DBDC			\
 	-DBRCM_FULLMAC		\
-	-DDHD_DEBUG		\
 	-DDHD_FIRSTREAD=64	\
 	-DDHD_SCHED		\
 	-DDHD_SDALIGN=64	\
@@ -32,16 +30,34 @@ ccflags-y :=			\
 	-DMMC_SDIO_ABORT	\
 	-DPKT_FILTER_SUPPORT	\
 	-DSHOW_EVENTS		\
-	-DTOE			\
-	-Idrivers/staging/brcm80211/brcmfmac		\
+	-DTOE
+
+ccflags-$(CONFIG_BRCMDBG)	+= -DDHD_DEBUG
+
+ccflags-y += \
+	-Idrivers/staging/brcm80211/brcmfmac	\
 	-Idrivers/staging/brcm80211/include		\
 	-Idrivers/staging/brcm80211/util
 
-DHDOFILES = dhd_linux.o ../util/linux_osl.o ../util/bcmutils.o dhd_common.o dhd_custom_gpio.o	\
-	wl_iw.o wl_cfg80211.o ../util/siutils.o ../util/sbutils.o ../util/aiutils.o ../util/hndpmu.o ../util/bcmwifi.o dhd_sdio.o	\
-	dhd_linux_sched.o dhd_cdc.o bcmsdh_sdmmc.o bcmsdh.o bcmsdh_linux.o	\
-	bcmsdh_sdmmc_linux.o
+DHDOFILES = \
+	wl_cfg80211.o \
+	wl_iw.o \
+	dhd_cdc.o \
+	dhd_common.o \
+	dhd_custom_gpio.o \
+	dhd_sdio.o	\
+	dhd_linux.o \
+	dhd_linux_sched.o \
+	bcmsdh.o \
+	bcmsdh_linux.o	\
+	bcmsdh_sdmmc.o \
+	bcmsdh_sdmmc_linux.o \
+	aiutils.o \
+	siutils.o \
+	sbutils.o \
+	bcmutils.o \
+	bcmwifi.o \
+	hndpmu.o
 
 obj-m += brcmfmac.o
 brcmfmac-objs += $(DHDOFILES)
-
diff --git a/drivers/staging/brcm80211/brcmfmac/aiutils.c b/drivers/staging/brcm80211/brcmfmac/aiutils.c
new file mode 100644
index 0000000..e648086
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/aiutils.c
@@ -0,0 +1 @@
+#include "../util/aiutils.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmcdc.h b/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
new file mode 100644
index 0000000..ed4c4a5
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/if_ether.h>
+
+typedef struct cdc_ioctl {
+	u32 cmd;		/* ioctl command value */
+	u32 len;		/* lower 16: output buflen; upper 16:
+				 input buflen (excludes header) */
+	u32 flags;		/* flag defns given below */
+	u32 status;		/* status code returned from the device */
+} cdc_ioctl_t;
+
+/* Max valid buffer size that can be sent to the dongle */
+#define CDC_MAX_MSG_SIZE	(ETH_FRAME_LEN+ETH_FCS_LEN)
+
+/* len field is divided into input and output buffer lengths */
+#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF	/* maximum or expected
+						 response length, */
+					   /* excluding IOCTL header */
+#define CDCL_IOC_OUTLEN_SHIFT  0
+#define CDCL_IOC_INLEN_MASK    0xFFFF0000	/* input buffer length,
+						 excluding IOCTL header */
+#define CDCL_IOC_INLEN_SHIFT   16
+
+/* CDC flag definitions */
+#define CDCF_IOC_ERROR		0x01	/* 0=success, 1=ioctl cmd failed */
+#define CDCF_IOC_SET		0x02	/* 0=get, 1=set cmd */
+#define CDCF_IOC_IF_MASK	0xF000	/* I/F index */
+#define CDCF_IOC_IF_SHIFT	12
+#define CDCF_IOC_ID_MASK	0xFFFF0000	/* used to uniquely id an ioctl
+						 req/resp pairing */
+#define CDCF_IOC_ID_SHIFT	16	/* # of bits of shift for ID Mask */
+
+#define CDC_IOC_IF_IDX(flags)	\
+	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
+#define CDC_IOC_ID(flags)	\
+	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+
+#define CDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
+#define CDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
+	((idx) << CDCF_IOC_IF_SHIFT)))
+
+/*
+ * BDC header
+ *
+ *   The BDC header is used on data packets to convey priority across USB.
+ */
+
+#define	BDC_HEADER_LEN		4
+
+#define BDC_PROTO_VER		1	/* Protocol version */
+
+#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
+#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
+
+#define BDC_FLAG__UNUSED	0x03	/* Unassigned */
+#define BDC_FLAG_SUM_GOOD	0x04	/* Dongle has verified good
+					 RX checksums */
+#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums */
+
+#define BDC_PRIORITY_MASK	0x7
+
+#define BDC_FLAG2_FC_FLAG	0x10	/* flag to indicate if pkt contains */
+						/* FLOW CONTROL info only */
+#define BDC_PRIORITY_FC_SHIFT	4	/* flow control info shift */
+
+#define BDC_FLAG2_IF_MASK	0x0f	/* APSTA: interface on which the
+					 packet was received */
+#define BDC_FLAG2_IF_SHIFT	0
+
+#define BDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
+	((idx) << BDC_FLAG2_IF_SHIFT)))
+
+struct bdc_header {
+	u8 flags;		/* Flags */
+	u8 priority;		/* 802.1d Priority 0:2 bits, 4:7 flow
+				 control info for usb */
+	u8 flags2;
+	u8 rssi;
+};
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h b/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
new file mode 100644
index 0000000..53c3291
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_sdio_api_h_
+#define	_sdio_api_h_
+
+#define SDIOH_API_RC_SUCCESS                          (0x00)
+#define SDIOH_API_RC_FAIL	                      (0x01)
+#define SDIOH_API_SUCCESS(status) (status == 0)
+
+#define SDIOH_READ              0	/* Read request */
+#define SDIOH_WRITE             1	/* Write request */
+
+#define SDIOH_DATA_FIX          0	/* Fixed addressing */
+#define SDIOH_DATA_INC          1	/* Incremental addressing */
+
+#define SDIOH_CMD_TYPE_NORMAL   0	/* Normal command */
+#define SDIOH_CMD_TYPE_APPEND   1	/* Append command */
+#define SDIOH_CMD_TYPE_CUTTHRU  2	/* Cut-through command */
+
+#define SDIOH_DATA_PIO          0	/* PIO mode */
+#define SDIOH_DATA_DMA          1	/* DMA mode */
+
+typedef int SDIOH_API_RC;
+
+/* SDio Host structure */
+typedef struct sdioh_info sdioh_info_t;
+
+/* callback function, taking one arg */
+typedef void (*sdioh_cb_fn_t) (void *);
+
+/* attach, return handler on success, NULL if failed.
+ *  The handler shall be provided by all subsequent calls. No local cache
+ *  cfghdl points to the starting address of pci device mapped memory
+ */
+extern sdioh_info_t *sdioh_attach(void *cfghdl, uint irq);
+extern SDIOH_API_RC sdioh_detach(sdioh_info_t *si);
+extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si,
+					     sdioh_cb_fn_t fn, void *argh);
+extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
+
+/* query whether SD interrupt is enabled or not */
+extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
+
+/* enable or disable SD interrupt */
+extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
+
+#if defined(DHD_DEBUG)
+extern bool sdioh_interrupt_pending(sdioh_info_t *si);
+#endif
+
+extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
+extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
+
+/* read or write one byte using cmd52 */
+extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc,
+				       uint addr, u8 *byte);
+
+/* read or write 2/4 bytes using cmd53 */
+extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type,
+				       uint rw, uint fnc, uint addr,
+				       u32 *word, uint nbyte);
+
+/* read or write any buffer using cmd53 */
+extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma,
+					 uint fix_inc, uint rw, uint fnc_num,
+					 u32 addr, uint regwidth,
+					 u32 buflen, u8 *buffer,
+					 struct sk_buff *pkt);
+
+/* get cis data */
+extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, u8 *cis,
+				   u32 length);
+
+extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, u32 addr,
+				   u8 *data);
+extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, u32 addr,
+				    u8 *data);
+
+/* query number of io functions */
+extern uint sdioh_query_iofnum(sdioh_info_t *si);
+
+/* handle iovars */
+extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
+			  void *params, int plen, void *arg, int len, bool set);
+
+/* Issue abort to the specified function and clear controller as needed */
+extern int sdioh_abort(sdioh_info_t *si, uint fnc);
+
+/* Start and Stop SDIO without re-enumerating the SD card. */
+extern int sdioh_start(sdioh_info_t *si, int stage);
+extern int sdioh_stop(sdioh_info_t *si);
+
+/* Reset and re-initialize the device */
+extern int sdioh_sdio_reset(sdioh_info_t *si);
+
+/* Helper function */
+void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
+
+#endif				/* _sdio_api_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
index acf43a3..473f57d 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
@@ -19,8 +19,6 @@
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
-#include <bcmendian.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <hndsoc.h>
 #include <siutils.h>
@@ -39,7 +37,6 @@ struct bcmsdh_info {
 	bool init_success;	/* underlying driver successfully attached */
 	void *sdioh;		/* handler for sdioh */
 	u32 vendevid;	/* Target Vendor and Device ID on SD bus */
-	struct osl_info *osh;
 	bool regfail;		/* Save status of last
 				 reg_read/reg_write call */
 	u32 sbwad;		/* Save backplane window address */
@@ -56,8 +53,7 @@ void bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable)
 }
 #endif
 
-bcmsdh_info_t *bcmsdh_attach(struct osl_info *osh, void *cfghdl,
-				void **regsva, uint irq)
+bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq)
 {
 	bcmsdh_info_t *bcmsdh;
 
@@ -70,13 +66,12 @@ bcmsdh_info_t *bcmsdh_attach(struct osl_info *osh, void *cfghdl,
 	/* save the handler locally */
 	l_bcmsdh = bcmsdh;
 
-	bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq);
+	bcmsdh->sdioh = sdioh_attach(cfghdl, irq);
 	if (!bcmsdh->sdioh) {
-		bcmsdh_detach(osh, bcmsdh);
+		bcmsdh_detach(bcmsdh);
 		return NULL;
 	}
 
-	bcmsdh->osh = osh;
 	bcmsdh->init_success = true;
 
 	*regsva = (u32 *) SI_ENUM_BASE;
@@ -86,13 +81,13 @@ bcmsdh_info_t *bcmsdh_attach(struct osl_info *osh, void *cfghdl,
 	return bcmsdh;
 }
 
-int bcmsdh_detach(struct osl_info *osh, void *sdh)
+int bcmsdh_detach(void *sdh)
 {
 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
 
 	if (bcmsdh != NULL) {
 		if (bcmsdh->sdioh) {
-			sdioh_detach(osh, bcmsdh->sdioh);
+			sdioh_detach(bcmsdh->sdioh);
 			bcmsdh->sdioh = NULL;
 		}
 		kfree(bcmsdh);
@@ -324,7 +319,7 @@ int bcmsdh_cis_read(void *sdh, uint func, u8 * cis, uint length)
 			BCMSDH_ERROR(("%s: out of memory\n", __func__));
 			return BCME_NOMEM;
 		}
-		bcopy(cis, tmp_buf, length);
+		memcpy(tmp_buf, cis, length);
 		for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
 		     tmp_ptr++) {
 			ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
index d24b5e7..e3556ff 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
@@ -24,15 +24,14 @@
 #include <linux/pci.h>
 #include <linux/completion.h>
 
-#include <osl.h>
 #include <pcicfg.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
+#include <bcmutils.h>
 
 #if defined(OOB_INTR_ONLY)
 #include <linux/irq.h>
 extern void dhdsdio_isr(void *args);
-#include <bcmutils.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 #endif				/* defined(OOB_INTR_ONLY) */
@@ -56,7 +55,6 @@ struct bcmsdh_hc {
 #else
 	struct pci_dev *dev;	/* pci device handle */
 #endif				/* BCMPLATFORM_BUS */
-	struct osl_info *osh;
 	void *regs;		/* SDIO Host Controller address */
 	bcmsdh_info_t *sdh;	/* SDIO Host Controller handle */
 	void *ch;
@@ -114,7 +112,7 @@ bool bcmsdh_chipmatch(u16 vendor, u16 device)
 #ifdef BCMSDIOH_SPI
 	/* This is the PciSpiHost. */
 	if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) {
-		printf("Found PCI SPI Host Controller\n");
+		WL_NONE("Found PCI SPI Host Controller\n");
 		return true;
 	}
 #endif				/* BCMSDIOH_SPI */
@@ -142,7 +140,6 @@ static
 #endif				/* BCMLXSDMMC */
 int bcmsdh_probe(struct device *dev)
 {
-	struct osl_info *osh = NULL;
 	bcmsdh_hc_t *sdhc = NULL;
 	unsigned long regs = 0;
 	bcmsdh_info_t *sdh = NULL;
@@ -177,28 +174,21 @@ int bcmsdh_probe(struct device *dev)
 	}
 #endif				/* defined(OOB_INTR_ONLY) */
 	/* allocate SDIO Host Controller state info */
-	osh = osl_attach(dev, PCI_BUS);
-	if (!osh) {
-		SDLX_MSG(("%s: osl_attach failed\n", __func__));
-		goto err;
-	}
 	sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
 	if (!sdhc) {
 		SDLX_MSG(("%s: out of memory\n", __func__));
 		goto err;
 	}
-	sdhc->osh = osh;
-
 	sdhc->dev = (void *)dev;
 
 #ifdef BCMLXSDMMC
-	sdh = bcmsdh_attach(osh, (void *)0, (void **)&regs, irq);
+	sdh = bcmsdh_attach((void *)0, (void **)&regs, irq);
 	if (!sdh) {
 		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
 		goto err;
 	}
 #else
-	sdh = bcmsdh_attach(osh, (void *)r->start, (void **)&regs, irq);
+	sdh = bcmsdh_attach((void *)r->start, (void **)&regs, irq);
 	if (!sdh) {
 		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
 		goto err;
@@ -220,7 +210,7 @@ int bcmsdh_probe(struct device *dev)
 
 	/* try to attach to the target device */
 	sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
-				0, 0, 0, 0, (void *)regs, NULL, sdh);
+				  0, 0, 0, 0, (void *)regs, sdh);
 	if (!sdhc->ch) {
 		SDLX_MSG(("%s: device attach failed\n", __func__));
 		goto err;
@@ -232,11 +222,10 @@ int bcmsdh_probe(struct device *dev)
 err:
 	if (sdhc) {
 		if (sdhc->sdh)
-			bcmsdh_detach(sdhc->osh, sdhc->sdh);
+			bcmsdh_detach(sdhc->sdh);
 		kfree(sdhc);
 	}
-	if (osh)
-		osl_detach(osh);
+
 	return -ENODEV;
 }
 
@@ -246,11 +235,10 @@ static
 int bcmsdh_remove(struct device *dev)
 {
 	bcmsdh_hc_t *sdhc, *prev;
-	struct osl_info *osh;
 
 	sdhc = sdhcinfo;
 	drvinfo.detach(sdhc->ch);
-	bcmsdh_detach(sdhc->osh, sdhc->sdh);
+	bcmsdh_detach(sdhc->sdh);
 	/* find the SDIO Host Controller state for this pdev
 		 and take it out from the list */
 	for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
@@ -269,9 +257,7 @@ int bcmsdh_remove(struct device *dev)
 	}
 
 	/* release SDIO Host Controller info */
-	osh = sdhc->osh;
 	kfree(sdhc);
-	osl_detach(osh);
 
 #if !defined(BCMLXSDMMC)
 	dev_set_drvdata(dev, NULL);
@@ -328,8 +314,6 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
 		return IRQ_HANDLED;
 	}
 
-	WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
-
 	dhdsdio_isr((void *)dhdp->bus);
 
 	return IRQ_HANDLED;
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index d399b5c..65313fa 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -17,8 +17,6 @@
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
-#include <bcmendian.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <sdio.h>		/* SDIO Device and Protocol Specs */
 #include <sdioh.h>		/* SDIO Host Controller Specification */
@@ -112,7 +110,7 @@ static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd)
 /*
  *	Public entry points & extern's
  */
-extern sdioh_info_t *sdioh_attach(struct osl_info *osh, void *bar0, uint irq)
+sdioh_info_t *sdioh_attach(void *bar0, uint irq)
 {
 	sdioh_info_t *sd;
 	int err_ret;
@@ -129,7 +127,6 @@ extern sdioh_info_t *sdioh_attach(struct osl_info *osh, void *bar0, uint irq)
 		sd_err(("sdioh_attach: out of memory\n"));
 		return NULL;
 	}
-	sd->osh = osh;
 	if (sdioh_sdmmc_osinit(sd) != 0) {
 		sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
 		kfree(sd);
@@ -175,7 +172,7 @@ extern sdioh_info_t *sdioh_attach(struct osl_info *osh, void *bar0, uint irq)
 	return sd;
 }
 
-extern SDIOH_API_RC sdioh_detach(struct osl_info *osh, sdioh_info_t *sd)
+extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
 {
 	sd_trace(("%s\n", __func__));
 
@@ -441,7 +438,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 		val_size = sizeof(int);
 
 	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
+		memcpy(&int_val, params, sizeof(int_val));
 
 	bool_val = (int_val != 0) ? true : false;
 
@@ -449,7 +446,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 	switch (actionid) {
 	case IOV_GVAL(IOV_MSGLEVEL):
 		int_val = (s32) sd_msglevel;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_MSGLEVEL):
@@ -458,7 +455,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_BLOCKMODE):
 		int_val = (s32) si->sd_blockmode;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_BLOCKMODE):
@@ -472,7 +469,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 			break;
 		}
 		int_val = (s32) si->client_block_size[int_val];
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_BLOCKSIZE):
@@ -514,12 +511,12 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_RXCHAIN):
 		int_val = false;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_DMA):
 		int_val = (s32) si->sd_use_dma;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_DMA):
@@ -528,7 +525,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_USEINTS):
 		int_val = (s32) si->use_client_ints;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_USEINTS):
@@ -542,7 +539,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_DIVISOR):
 		int_val = (u32) sd_divisor;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_DIVISOR):
@@ -551,7 +548,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_POWER):
 		int_val = (u32) sd_power;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_POWER):
@@ -560,7 +557,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_CLOCK):
 		int_val = (u32) sd_clock;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_CLOCK):
@@ -569,7 +566,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_SDMODE):
 		int_val = (u32) sd_sdmode;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDMODE):
@@ -578,7 +575,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_HISPEED):
 		int_val = (u32) sd_hiok;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_HISPEED):
@@ -587,12 +584,12 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 
 	case IOV_GVAL(IOV_NUMINTS):
 		int_val = (s32) si->intrcount;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_NUMLOCALINTS):
 		int_val = (s32) 0;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_HOSTREG):
@@ -621,7 +618,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 				int_val = 32;	/* sdioh_sdmmc_rreg(si,
 						 sd_ptr->offset); */
 
-			bcopy(&int_val, arg, sizeof(int_val));
+			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
 
@@ -657,7 +654,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
 			}
 
 			int_val = (int)data;
-			bcopy(&int_val, arg, sizeof(int_val));
+			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
 
@@ -735,7 +732,7 @@ static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, u32 regaddr)
 	}
 
 	/* Only the lower 17-bits are valid */
-	scratch = ltoh32(scratch);
+	scratch = le32_to_cpu(scratch);
 	scratch &= 0x0001FFFF;
 	return scratch;
 }
@@ -1039,7 +1036,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
 	if (pkt == NULL) {
 		sd_data(("%s: Creating new %s Packet, len=%d\n",
 			 __func__, write ? "TX" : "RX", buflen_u));
-		mypkt = pkt_buf_get_skb(sd->osh, buflen_u);
+		mypkt = pkt_buf_get_skb(buflen_u);
 		if (!mypkt) {
 			sd_err(("%s: pkt_buf_get_skb failed: len %d\n",
 				__func__, buflen_u));
@@ -1048,16 +1045,16 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
 
 		/* For a write, copy the buffer data into the packet. */
 		if (write)
-			bcopy(buffer, mypkt->data, buflen_u);
+			memcpy(mypkt->data, buffer, buflen_u);
 
 		Status =
 		    sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
 
 		/* For a read, copy the packet data back to the buffer. */
 		if (!write)
-			bcopy(mypkt->data, buffer, buflen_u);
+			memcpy(buffer, mypkt->data, buflen_u);
 
-		pkt_buf_free_skb(sd->osh, mypkt, write ? true : false);
+		pkt_buf_free_skb(mypkt);
 	} else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
 		/* Case 2: We have a packet, but it is unaligned. */
 
@@ -1066,7 +1063,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
 
 		sd_data(("%s: Creating aligned %s Packet, len=%d\n",
 			 __func__, write ? "TX" : "RX", pkt->len));
-		mypkt = pkt_buf_get_skb(sd->osh, pkt->len);
+		mypkt = pkt_buf_get_skb(pkt->len);
 		if (!mypkt) {
 			sd_err(("%s: pkt_buf_get_skb failed: len %d\n",
 				__func__, pkt->len));
@@ -1075,16 +1072,16 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write,
 
 		/* For a write, copy the buffer data into the packet. */
 		if (write)
-			bcopy(pkt->data, mypkt->data, pkt->len);
+			memcpy(mypkt->data, pkt->data, pkt->len);
 
 		Status =
 		    sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
 
 		/* For a read, copy the packet data back to the buffer. */
 		if (!write)
-			bcopy(mypkt->data, pkt->data, mypkt->len);
+			memcpy(pkt->data, mypkt->data, mypkt->len);
 
-		pkt_buf_free_skb(sd->osh, mypkt, write ? true : false);
+		pkt_buf_free_skb(mypkt);
 	} else {		/* case 3: We have a packet and
 				 it is aligned. */
 		sd_data(("%s: Aligned %s Packet, direct DMA\n",
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
new file mode 100644
index 0000000..3ef42b3
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __BCMSDH_SDMMC_H__
+#define __BCMSDH_SDMMC_H__
+
+#ifdef BCMDBG
+#define sd_err(x)	\
+	do { \
+		if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_trace(x)	\
+	do { \
+		if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_info(x)	\
+	do { \
+		if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_debug(x)	\
+	do { \
+		if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_data(x)	\
+	do { \
+		if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_ctrl(x)	\
+	do { \
+		if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#else
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#endif
+
+/* Allocate/init/free per-OS private data */
+extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
+extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
+
+#define BLOCK_SIZE_64 64
+#define BLOCK_SIZE_512 512
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
+
+/* internal return code */
+#define SUCCESS	0
+#define ERROR	1
+
+/* private bus modes */
+#define SDIOH_MODE_SD4		2
+#define CLIENT_INTR 		0x100	/* Get rid of this! */
+
+struct sdioh_info {
+	struct osl_info *osh;		/* osh handler */
+	bool client_intr_enabled;	/* interrupt connnected flag */
+	bool intr_handler_valid;	/* client driver interrupt handler valid */
+	sdioh_cb_fn_t intr_handler;	/* registered interrupt handler */
+	void *intr_handler_arg;	/* argument to call interrupt handler */
+	u16 intmask;		/* Current active interrupts */
+	void *sdos_info;	/* Pointer to per-OS private data */
+
+	uint irq;		/* Client irq */
+	int intrcount;		/* Client interrupts */
+	bool sd_use_dma;	/* DMA on CMD53 */
+	bool sd_blockmode;	/* sd_blockmode == false => 64 Byte Cmd 53s. */
+	/*  Must be on for sd_multiblock to be effective */
+	bool use_client_ints;	/* If this is false, make sure to restore */
+	int sd_mode;		/* SD1/SD4/SPI */
+	int client_block_size[SDIOD_MAX_IOFUNCS];	/* Blocksize */
+	u8 num_funcs;	/* Supported funcs on client */
+	u32 com_cis_ptr;
+	u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+	uint max_dma_len;
+	uint max_dma_descriptors;	/* DMA Descriptors supported by this controller. */
+	/*	SDDMA_DESCRIPTOR	SGList[32]; *//* Scatter/Gather DMA List */
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmsdh_sdmmc.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/* OS-independent interrupt handler */
+extern bool check_client_intr(sdioh_info_t *sd);
+
+/* Core interrupt enable/disable of device interrupts */
+extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
+extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
+
+/**************************************************************
+ * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
+ */
+
+/* Register mapping routines */
+extern u32 *sdioh_sdmmc_reg_map(s32 addr, int size);
+extern void sdioh_sdmmc_reg_unmap(s32 addr, int size);
+
+/* Interrupt (de)registration routines */
+extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
+extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
+
+typedef struct _BCMSDH_SDMMC_INSTANCE {
+	sdioh_info_t *sd;
+	struct sdio_func *func[SDIOD_MAX_IOFUNCS];
+	u32 host_claimed;
+} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
+
+#endif				/* __BCMSDH_SDMMC_H__ */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
index ceaa474..d738d4d 100644
--- a/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
@@ -17,7 +17,6 @@
 #include <linux/sched.h>	/* request_irq() */
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <sdio.h>		/* SDIO Specs */
 #include <bcmsdbus.h>		/* bcmsdh to/from specific controller APIs */
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmutils.c b/drivers/staging/brcm80211/brcmfmac/bcmutils.c
new file mode 100644
index 0000000..8e1296a
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmutils.c
@@ -0,0 +1 @@
+#include "../util/bcmutils.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/bcmwifi.c b/drivers/staging/brcm80211/brcmfmac/bcmwifi.c
new file mode 100644
index 0000000..9fe988c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/bcmwifi.c
@@ -0,0 +1 @@
+#include "../util/bcmwifi.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd.h b/drivers/staging/brcm80211/brcmfmac/dhd.h
index 69c6a02..60cf782 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd.h
@@ -33,9 +33,6 @@
 #include <linux/ethtool.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
-#if defined(CONFIG_HAS_WAKELOCK)
-#include <linux/wakelock.h>
-#endif			/* defined (CONFIG_HAS_WAKELOCK) */
 /* The kernel threading is sdio-specific */
 
 #include <wlioctl.h>
@@ -52,32 +49,9 @@ enum dhd_bus_state {
 	DHD_BUS_DATA		/* Ready for frame transfers */
 };
 
-enum dhd_bus_wake_state {
-	WAKE_LOCK_OFF,
-	WAKE_LOCK_PRIV,
-	WAKE_LOCK_DPC,
-	WAKE_LOCK_IOCTL,
-	WAKE_LOCK_DOWNLOAD,
-	WAKE_LOCK_TMOUT,
-	WAKE_LOCK_WATCHDOG,
-	WAKE_LOCK_LINK_DOWN_TMOUT,
-	WAKE_LOCK_PNO_FIND_TMOUT,
-	WAKE_LOCK_SOFTAP_SET,
-	WAKE_LOCK_SOFTAP_STOP,
-	WAKE_LOCK_SOFTAP_START,
-	WAKE_LOCK_MAX
-};
-enum dhd_prealloc_index {
-	DHD_PREALLOC_PROT = 0,
-	DHD_PREALLOC_RXBUF,
-	DHD_PREALLOC_DATABUF,
-	DHD_PREALLOC_OSL_BUF
-};
-
 /* Common structure for module and instance linkage */
 typedef struct dhd_pub {
 	/* Linkage ponters */
-	struct osl_info *osh;		/* OSL handle */
 	struct dhd_bus *bus;	/* Bus module handle */
 	struct dhd_prot *prot;	/* Protocol module handle */
 	struct dhd_info *info;	/* Info module handle */
@@ -95,8 +69,8 @@ typedef struct dhd_pub {
 	/* Dongle media info */
 	bool iswl;		/* Dongle-resident driver is wl */
 	unsigned long drv_version;	/* Version of dongle-resident driver */
-	struct ether_addr mac;	/* MAC address obtained from dongle */
-	dngl_stats_t dstats;	/* Stats for dongle-based data */
+	u8 mac[ETH_ALEN];			/* MAC address obtained from dongle */
+	dngl_stats_t dstats;		/* Stats for dongle-based data */
 
 	/* Additional stats for the bus level */
 	unsigned long tx_packets;	/* Data packets sent to dongle */
@@ -145,9 +119,6 @@ typedef struct dhd_pub {
 	u8 country_code[WLC_CNTRY_BUF_SZ];
 	char eventmask[WL_EVENTING_MASK_LEN];
 
-#if defined(CONFIG_HAS_WAKELOCK)
-	struct wake_lock wakelock[WAKE_LOCK_MAX];
-#endif		/*  defined (CONFIG_HAS_WAKELOCK) */
 } dhd_pub_t;
 
 #if defined(CONFIG_PM_SLEEP)
@@ -230,41 +201,6 @@ static inline void MUTEX_UNLOCK_WL_SCAN_SET(void)
 {
 }
 
-static inline void WAKE_LOCK_INIT(dhd_pub_t *dhdp, int index, char *y)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock_init(&dhdp->wakelock[index], WAKE_LOCK_SUSPEND, y);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_LOCK(dhd_pub_t *dhdp, int index)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock(&dhdp->wakelock[index]);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_UNLOCK(dhd_pub_t *dhdp, int index)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_unlock(&dhdp->wakelock[index]);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_LOCK_TIMEOUT(dhd_pub_t *dhdp, int index, long time)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock_timeout(&dhdp->wakelock[index], time);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_LOCK_DESTROY(dhd_pub_t *dhdp, int index)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock_destroy(&dhdp->wakelock[index]);
-#endif /* defined (CONFIG_HAS_WAKELOCK) */
-}
-
 typedef struct dhd_if_event {
 	u8 ifidx;
 	u8 action;
@@ -276,16 +212,12 @@ typedef struct dhd_if_event {
  * Exported from dhd OS modules (dhd_linux/dhd_ndis)
  */
 
-/* To allow osl_attach/detach calls from os-independent modules */
-struct osl_info *dhd_osl_attach(void *pdev, uint bustype);
-void dhd_osl_detach(struct osl_info *osh);
-
 /* Indication from bus module regarding presence/insertion of dongle.
  * Return dhd_pub_t pointer, used as handle to OS module in later calls.
  * Returned structure should have bus and prot pointers filled in.
  * bus_hdrlen specifies required headroom for bus module header.
  */
-extern dhd_pub_t *dhd_attach(struct osl_info *osh, struct dhd_bus *bus,
+extern dhd_pub_t *dhd_attach(struct dhd_bus *bus,
 				uint bus_hdrlen);
 extern int dhd_net_attach(dhd_pub_t *dhdp, int idx);
 
@@ -364,7 +296,6 @@ extern int dhd_ifname2idx(struct dhd_info *dhd, char *name);
 extern u8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx);
 extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata,
 			 wl_event_msg_t *, void **data_ptr);
-extern void wl_event_to_host_order(wl_event_msg_t *evt);
 
 extern void dhd_common_init(void);
 
@@ -389,14 +320,12 @@ extern int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag);
 extern uint dhd_bus_status(dhd_pub_t *dhdp);
 extern int dhd_bus_start(dhd_pub_t *dhdp);
 
-extern void print_buf(void *pbuf, int len, int bytes_per_line);
-
-typedef enum cust_gpio_modes {
+enum cust_gpio_modes {
 	WLAN_RESET_ON,
 	WLAN_RESET_OFF,
 	WLAN_POWER_ON,
 	WLAN_POWER_OFF
-} cust_gpio_modes_t;
+};
 /*
  * Insmod parameters for debug/test
  */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
index cd0d540..065f1ae 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
@@ -27,7 +27,7 @@ extern void dhd_bus_unregister(void);
 
 /* Download firmware image and nvram image */
 extern bool dhd_bus_download_firmware(struct dhd_bus *bus,
-	      struct osl_info *osh, char *fw_path, char *nv_path);
+				      char *fw_path, char *nv_path);
 
 /* Stop bus module: clear pending frames, disable data flow */
 extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
index b7b527f..39a4d00 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
@@ -17,11 +17,9 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
-#include <osl.h>
 
 #include <bcmutils.h>
 #include <bcmcdc.h>
-#include <bcmendian.h>
 
 #include <dngl_stats.h>
 #include <dhd.h>
@@ -65,7 +63,7 @@ typedef struct dhd_prot {
 static int dhdcdc_msg(dhd_pub_t *dhd)
 {
 	dhd_prot_t *prot = dhd->prot;
-	int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
+	int len = le32_to_cpu(prot->msg.len) + sizeof(cdc_ioctl_t);
 
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -93,7 +91,7 @@ static int dhdcdc_cmplt(dhd_pub_t *dhd, u32 id, u32 len)
 				  len + sizeof(cdc_ioctl_t));
 		if (ret < 0)
 			break;
-	} while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
+	} while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
 
 	return ret;
 }
@@ -124,11 +122,11 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 
 	memset(msg, 0, sizeof(cdc_ioctl_t));
 
-	msg->cmd = htol32(cmd);
-	msg->len = htol32(len);
+	msg->cmd = cpu_to_le32(cmd);
+	msg->len = cpu_to_le32(len);
 	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
 	CDC_SET_IF_IDX(msg, ifidx);
-	msg->flags = htol32(msg->flags);
+	msg->flags = cpu_to_le32(msg->flags);
 
 	if (buf)
 		memcpy(prot->buf, buf, len);
@@ -146,7 +144,7 @@ retry:
 	if (ret < 0)
 		goto done;
 
-	flags = ltoh32(msg->flags);
+	flags = le32_to_cpu(msg->flags);
 	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
 
 	if ((id < prot->reqid) && (++retries < RETRIES))
@@ -170,7 +168,7 @@ retry:
 
 	/* Check the ERROR flag */
 	if (flags & CDCF_IOC_ERROR) {
-		ret = ltoh32(msg->status);
+		ret = le32_to_cpu(msg->status);
 		/* Cache error from dongle */
 		dhd->dongle_error = ret;
 	}
@@ -191,11 +189,11 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 
 	memset(msg, 0, sizeof(cdc_ioctl_t));
 
-	msg->cmd = htol32(cmd);
-	msg->len = htol32(len);
+	msg->cmd = cpu_to_le32(cmd);
+	msg->len = cpu_to_le32(len);
 	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
 	CDC_SET_IF_IDX(msg, ifidx);
-	msg->flags = htol32(msg->flags);
+	msg->flags = cpu_to_le32(msg->flags);
 
 	if (buf)
 		memcpy(prot->buf, buf, len);
@@ -208,7 +206,7 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 	if (ret < 0)
 		goto done;
 
-	flags = ltoh32(msg->flags);
+	flags = le32_to_cpu(msg->flags);
 	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
 
 	if (id != prot->reqid) {
@@ -220,7 +218,7 @@ int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len)
 
 	/* Check the ERROR flag */
 	if (flags & CDCF_IOC_ERROR) {
-		ret = ltoh32(msg->status);
+		ret = le32_to_cpu(msg->status);
 		/* Cache error from dongle */
 		dhd->dongle_error = ret;
 	}
@@ -276,8 +274,8 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
 		ret = 0;
 	else {
 		cdc_ioctl_t *msg = &prot->msg;
-		ioc->needed = ltoh32(msg->len);	/* len == needed when set/query
-						 fails from dongle */
+		/* len == needed when set/query fails from dongle */
+		ioc->needed = le32_to_cpu(msg->len);
 	}
 
 	/* Intercept the wme_dp ioctl here */
@@ -286,8 +284,8 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc, void *buf, int len)
 
 		slen = strlen("wme_dp") + 1;
 		if (len >= (int)(slen + sizeof(int)))
-			bcopy(((char *)buf + slen), &val, sizeof(int));
-		dhd->wme_dp = (u8) ltoh32(val);
+			memcpy(&val, (char *)buf + slen, sizeof(int));
+		dhd->wme_dp = (u8) le32_to_cpu(val);
 	}
 
 	prot->pending = false;
@@ -345,26 +343,6 @@ void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, struct sk_buff *pktbuf)
 	BDC_SET_IF_IDX(h, ifidx);
 }
 
-bool dhd_proto_fcinfo(dhd_pub_t *dhd, struct sk_buff *pktbuf, u8 * fcbits)
-{
-#ifdef BDC
-	struct bdc_header *h;
-
-	if (pktbuf->len < BDC_HEADER_LEN) {
-		DHD_ERROR(("%s: rx data too short (%d < %d)\n",
-			   __func__, pktbuf->len, BDC_HEADER_LEN));
-		return BCME_ERROR;
-	}
-
-	h = (struct bdc_header *)(pktbuf->data);
-
-	*fcbits = h->priority >> BDC_PRIORITY_FC_SHIFT;
-	if ((h->flags2 & BDC_FLAG2_FC_FLAG) == BDC_FLAG2_FC_FLAG)
-		return true;
-#endif
-	return false;
-}
-
 int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, struct sk_buff *pktbuf)
 {
 #ifdef BDC
@@ -437,8 +415,7 @@ int dhd_prot_attach(dhd_pub_t *dhd)
 	return 0;
 
 fail:
-	if (cdc != NULL)
-		kfree(cdc);
+	kfree(cdc);
 	return BCME_NOMEM;
 }
 
@@ -477,7 +454,7 @@ int dhd_prot_init(dhd_pub_t *dhd)
 		dhd_os_proto_unblock(dhd);
 		return ret;
 	}
-	memcpy(dhd->mac.octet, buf, ETH_ALEN);
+	memcpy(dhd->mac, buf, ETH_ALEN);
 
 	dhd_os_proto_unblock(dhd);
 
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_common.c b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
index 3dbf72e..aa171f6 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_common.c
@@ -17,9 +17,7 @@
 #include <linux/string.h>
 #include <bcmdefs.h>
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <bcmutils.h>
-#include <bcmendian.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhd_bus.h>
@@ -37,11 +35,6 @@ u32 dhd_conn_event;
 u32 dhd_conn_status;
 u32 dhd_conn_reason;
 
-#define htod32(i) i
-#define htod16(i) i
-#define dtoh32(i) i
-#define dtoh16(i) i
-
 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
 			    uint len);
 extern void dhd_ind_scan_confirm(void *h, bool status);
@@ -57,8 +50,8 @@ void dhd_iscan_unlock(void);
 #error DHD_SDALIGN is not a power of 2!
 #endif
 
-#ifdef DHD_DEBUG
 #define EPI_VERSION_STR         "4.218.248.5"
+#ifdef DHD_DEBUG
 const char dhd_version[] =
 "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " __DATE__
 " at " __TIME__;
@@ -214,7 +207,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 		goto exit;
 
 	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
+		memcpy(&int_val, params, sizeof(int_val));
 
 	switch (actionid) {
 	case IOV_GVAL(IOV_VERSION):
@@ -224,7 +217,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_MSGLEVEL):
 		int_val = (s32) dhd_msg_level;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_MSGLEVEL):
@@ -239,12 +232,12 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_BCMERROR):
 		int_val = (s32) dhd_pub->bcmerror;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_WDTICK):
 		int_val = (s32) dhd_watchdog_ms;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_WDTICK):
@@ -262,7 +255,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 #ifdef DHD_DEBUG
 	case IOV_GVAL(IOV_DCONSOLE_POLL):
 		int_val = (s32) dhd_console_ms;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_DCONSOLE_POLL):
@@ -290,7 +283,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_IOCTLTIMEOUT):{
 			int_val = (s32) dhd_os_get_ioctl_resp_timeout();
-			bcopy(&int_val, arg, sizeof(int_val));
+			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
 
@@ -312,21 +305,6 @@ exit:
 	return bcmerror;
 }
 
-/* Store the status of a connection attempt for later retrieval by an iovar */
-void dhd_store_conn_status(u32 event, u32 status, u32 reason)
-{
-	/* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID
-	 * because an encryption/rsn mismatch results in both events, and
-	 * the important information is in the WLC_E_PRUNE.
-	 */
-	if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL &&
-	      dhd_conn_event == WLC_E_PRUNE)) {
-		dhd_conn_event = event;
-		dhd_conn_status = status;
-		dhd_conn_reason = reason;
-	}
-}
-
 bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
 		  int prec)
 {
@@ -368,7 +346,7 @@ bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
 			ASSERT(p);
 		}
 
-		pkt_buf_free_skb(dhdp->osh, p, true);
+		pkt_buf_free_skb(p);
 	}
 
 	/* Enqueue */
@@ -592,14 +570,14 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 		WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
 	};
 	uint event_type, flags, auth_type, datalen;
-	event_type = ntoh32(event->event_type);
-	flags = ntoh16(event->flags);
-	status = ntoh32(event->status);
-	reason = ntoh32(event->reason);
-	auth_type = ntoh32(event->auth_type);
-	datalen = ntoh32(event->datalen);
+	event_type = be32_to_cpu(event->event_type);
+	flags = be16_to_cpu(event->flags);
+	status = be32_to_cpu(event->status);
+	reason = be32_to_cpu(event->reason);
+	auth_type = be32_to_cpu(event->auth_type);
+	datalen = be32_to_cpu(event->datalen);
 	/* debug dump of event messages */
-	sprintf(eabuf, "%pM", event->addr.octet);
+	sprintf(eabuf, "%pM", event->addr);
 
 	event_name = "UNKNOWN";
 	for (i = 0; i < ARRAY_SIZE(event_names); i++) {
@@ -653,9 +631,9 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 
 	case WLC_E_AUTH:
 	case WLC_E_AUTH_IND:
-		if (auth_type == DOT11_OPEN_SYSTEM)
+		if (auth_type == WLAN_AUTH_OPEN)
 			auth_str = "Open System";
-		else if (auth_type == DOT11_SHARED_KEY)
+		else if (auth_type == WLAN_AUTH_SHARED_KEY)
 			auth_str = "Shared Key";
 		else {
 			sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
@@ -754,34 +732,35 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 			memcpy(&hdr, buf, MSGTRACE_HDRLEN);
 
 			if (hdr.version != MSGTRACE_VERSION) {
-				printf
+				DHD_ERROR(
 				    ("\nMACEVENT: %s [unsupported version --> "
 				     "dhd version:%d dongle version:%d]\n",
-				     event_name, MSGTRACE_VERSION, hdr.version);
+				     event_name, MSGTRACE_VERSION, hdr.version)
+				);
 				/* Reset datalen to avoid display below */
 				datalen = 0;
 				break;
 			}
 
 			/* There are 2 bytes available at the end of data */
-			buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0';
+			buf[MSGTRACE_HDRLEN + be16_to_cpu(hdr.len)] = '\0';
 
-			if (ntoh32(hdr.discarded_bytes)
-			    || ntoh32(hdr.discarded_printf)) {
-				printf
+			if (be32_to_cpu(hdr.discarded_bytes)
+			    || be32_to_cpu(hdr.discarded_printf)) {
+				DHD_ERROR(
 				    ("\nWLC_E_TRACE: [Discarded traces in dongle -->"
 				     "discarded_bytes %d discarded_printf %d]\n",
-				     ntoh32(hdr.discarded_bytes),
-				     ntoh32(hdr.discarded_printf));
+				     be32_to_cpu(hdr.discarded_bytes),
+				     be32_to_cpu(hdr.discarded_printf)));
 			}
 
-			nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1;
+			nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
 			if (nblost > 0) {
-				printf
+				DHD_ERROR(
 				    ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
-				     ntoh32(hdr.seqnum), nblost);
+				     be32_to_cpu(hdr.seqnum), nblost));
 			}
-			seqnum_prev = ntoh32(hdr.seqnum);
+			seqnum_prev = be32_to_cpu(hdr.seqnum);
 
 			/* Display the trace buffer. Advance from \n to \n to
 			 * avoid display big
@@ -790,10 +769,10 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 			p = (char *)&buf[MSGTRACE_HDRLEN];
 			while ((s = strstr(p, "\n")) != NULL) {
 				*s = '\0';
-				printf("%s\n", p);
+				printk(KERN_DEBUG"%s\n", p);
 				p = s + 1;
 			}
-			printf("%s\n", p);
+			printk(KERN_DEBUG "%s\n", p);
 
 			/* Reset datalen to avoid display below */
 			datalen = 0;
@@ -802,7 +781,7 @@ static void wl_show_host_event(wl_event_msg_t *event, void *event_data)
 
 	case WLC_E_RSSI:
 		DHD_EVENT(("MACEVENT: %s %d\n", event_name,
-			   ntoh32(*((int *)event_data))));
+			   be32_to_cpu(*((int *)event_data))));
 		break;
 
 	default:
@@ -840,7 +819,7 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
 	}
 
 	/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
-	if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) !=
+	if (get_unaligned_be16(&pvt_data->bcm_hdr.usr_subtype) !=
 	    BCMILCP_BCM_SUBTYPE_EVENT) {
 		DHD_ERROR(("%s: mismatched subtype, bailing\n", __func__));
 		return BCME_ERROR;
@@ -852,10 +831,10 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
 	/* memcpy since BRCM event pkt may be unaligned. */
 	memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
 
-	type = ntoh32_ua((void *)&event->event_type);
-	flags = ntoh16_ua((void *)&event->flags);
-	status = ntoh32_ua((void *)&event->status);
-	evlen = ntoh32_ua((void *)&event->datalen) + sizeof(bcm_event_t);
+	type = get_unaligned_be32(&event->event_type);
+	flags = get_unaligned_be16(&event->flags);
+	status = get_unaligned_be32(&event->status);
+	evlen = get_unaligned_be32(&event->datalen) + sizeof(bcm_event_t);
 
 	switch (type) {
 	case WLC_E_IF:
@@ -868,7 +847,7 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
 				if (ifevent->action == WLC_E_IF_ADD)
 					dhd_add_if(dhd, ifevent->ifidx,
 						   NULL, event->ifname,
-						   pvt_data->eth.ether_dhost,
+						   pvt_data->eth.h_dest,
 						   ifevent->flags,
 						   ifevent->bssidx);
 				else
@@ -909,10 +888,10 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
 		if (type == WLC_E_NDIS_LINK) {
 			u32 temp;
 
-			temp = ntoh32_ua((void *)&event->event_type);
+			temp = get_unaligned_be32(&event->event_type);
 			DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
 
-			temp = ntoh32(WLC_E_NDIS_LINK);
+			temp = be32_to_cpu(WLC_E_NDIS_LINK);
 			memcpy((void *)(&pvt_data->event.event_type), &temp,
 			       sizeof(pvt_data->event.event_type));
 		}
@@ -926,42 +905,6 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata,
 	return BCME_OK;
 }
 
-void wl_event_to_host_order(wl_event_msg_t *evt)
-{
-	/* Event struct members passed from dongle to host are stored
-	 * in network
-	 * byte order. Convert all members to host-order.
-	 */
-	evt->event_type = ntoh32(evt->event_type);
-	evt->flags = ntoh16(evt->flags);
-	evt->status = ntoh32(evt->status);
-	evt->reason = ntoh32(evt->reason);
-	evt->auth_type = ntoh32(evt->auth_type);
-	evt->datalen = ntoh32(evt->datalen);
-	evt->version = ntoh16(evt->version);
-}
-
-void print_buf(void *pbuf, int len, int bytes_per_line)
-{
-	int i, j = 0;
-	unsigned char *buf = pbuf;
-
-	if (bytes_per_line == 0)
-		bytes_per_line = len;
-
-	for (i = 0; i < len; i++) {
-		printf("%2.2x", *buf++);
-		j++;
-		if (j == bytes_per_line) {
-			printf("\n");
-			j = 0;
-		} else {
-			printf(":");
-		}
-	}
-	printf("\n");
-}
-
 /* Convert user's input in hex pattern to byte-size mask */
 static int wl_pattern_atoh(char *src, char *dst)
 {
@@ -1025,10 +968,10 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
 	pkt_filterp = (wl_pkt_filter_enable_t *) (buf + str_len + 1);
 
 	/* Parse packet filter id. */
-	enable_parm.id = htod32(simple_strtoul(argv[i], NULL, 0));
+	enable_parm.id = simple_strtoul(argv[i], NULL, 0);
 
 	/* Parse enable/disable value. */
-	enable_parm.enable = htod32(enable);
+	enable_parm.enable = enable;
 
 	buf_len += sizeof(enable_parm);
 	memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
@@ -1053,8 +996,7 @@ dhd_pktfilter_offload_enable(dhd_pub_t *dhd, char *arg, int enable,
 			   __func__, arg, rc));
 
 fail:
-	if (arg_org)
-		kfree(arg_org);
+	kfree(arg_org);
 }
 
 void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
@@ -1113,7 +1055,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
 
 	/* Parse packet filter id. */
-	pkt_filter.id = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Polarity not provided\n"));
@@ -1121,7 +1063,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	}
 
 	/* Parse filter polarity. */
-	pkt_filter.negate_match = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Filter type not provided\n"));
@@ -1129,7 +1071,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	}
 
 	/* Parse filter type. */
-	pkt_filter.type = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Offset not provided\n"));
@@ -1137,7 +1079,7 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 	}
 
 	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Bitmask not provided\n"));
@@ -1146,8 +1088,8 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 
 	/* Parse pattern filter mask. */
 	mask_size =
-	    htod32(wl_pattern_atoh
-		   (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern));
+	    wl_pattern_atoh
+		   (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Pattern not provided\n"));
@@ -1156,9 +1098,9 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 
 	/* Parse pattern filter pattern. */
 	pattern_size =
-	    htod32(wl_pattern_atoh(argv[i],
+	    wl_pattern_atoh(argv[i],
 				   (char *)&pkt_filterp->u.pattern.
-				   mask_and_pattern[mask_size]));
+				   mask_and_pattern[mask_size]);
 
 	if (mask_size != pattern_size) {
 		DHD_ERROR(("Mask and pattern not the same size\n"));
@@ -1189,11 +1131,9 @@ void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
 			   __func__, arg));
 
 fail:
-	if (arg_org)
-		kfree(arg_org);
+	kfree(arg_org);
 
-	if (buf)
-		kfree(buf);
+	kfree(buf);
 }
 
 void dhd_arp_offload_set(dhd_pub_t *dhd, int arp_mode)
@@ -1242,7 +1182,7 @@ int dhd_preinit_ioctls(dhd_pub_t *dhd)
 	int scan_unassoc_time = 40;
 #ifdef GET_CUSTOM_MAC_ENABLE
 	int ret = 0;
-	struct ether_addr ea_addr;
+	u8 ea_addr[ETH_ALEN];
 #endif				/* GET_CUSTOM_MAC_ENABLE */
 
 	dhd_os_proto_block(dhd);
@@ -1254,9 +1194,9 @@ int dhd_preinit_ioctls(dhd_pub_t *dhd)
 	 ** firmware but unique per board mac address maybe provided by
 	 ** customer code
 	 */
-	ret = dhd_custom_get_mac_address(ea_addr.octet);
+	ret = dhd_custom_get_mac_address(ea_addr);
 	if (!ret) {
-		bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETH_ALEN,
+		bcm_mkiovar("cur_etheraddr", (void *)ea_addr, ETH_ALEN,
 			    buf, sizeof(buf));
 		ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
 		if (ret < 0) {
@@ -1478,8 +1418,7 @@ int dhd_iscan_print_cache(iscan_buf_t *iscan_skip)
 				   bi->BSSID.octet[2], bi->BSSID.octet[3],
 				   bi->BSSID.octet[4], bi->BSSID.octet[5]));
 
-			bi = (wl_bss_info_t *)((unsigned long)bi +
-						dtoh32(bi->length));
+			bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
 		}
 		iscan_cur = iscan_cur->next;
 		l++;
@@ -1543,18 +1482,16 @@ int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
 					bi->BSSID.octet[5]));
 
 					bi_new = bi;
-					bi = (wl_bss_info_t *)((unsigned long)bi +
-								dtoh32
-								(bi->length));
+					bi = (wl_bss_info_t *)((unsigned long)
+							       bi + bi->length);
 /*
 			if(bi && bi_new) {
-				bcopy(bi, bi_new, results->buflen -
-				dtoh32(bi_new->length));
-				results->buflen -= dtoh32(bi_new->length);
+				memcpy(bi_new, bi, results->buflen -
+				bi_new->length);
+				results->buflen -= bi_new->length;
 			}
 */
-					results->buflen -=
-					    dtoh32(bi_new->length);
+					results->buflen -= bi_new->length;
 					results->count--;
 
 					for (j = i; j < results->count; j++) {
@@ -1570,16 +1507,13 @@ int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
 
 							bi_next =
 							    (wl_bss_info_t *)((unsigned long)bi +
-								 dtoh32
-								 (bi->length));
-							bcopy(bi, bi_new,
-							      dtoh32
-							      (bi->length));
+								 bi->length);
+							memcpy(bi_new, bi,
+							      bi->length);
 							bi_new =
 							    (wl_bss_info_t *)((unsigned long)bi_new +
-								 dtoh32
-								 (bi_new->
-								  length));
+								 bi_new->
+								  length);
 							bi = bi_next;
 						}
 					}
@@ -1594,7 +1528,7 @@ int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip)
 					break;
 				}
 				bi = (wl_bss_info_t *)((unsigned long)bi +
-							dtoh32(bi->length));
+							bi->length);
 			}
 		}
 		iscan_cur = iscan_cur->next;
@@ -1648,7 +1582,7 @@ int dhd_iscan_remove_duplicates(void *dhdp, iscan_buf_t *iscan_cur)
 
 		dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
 
-		bi = (wl_bss_info_t *)((unsigned long)bi + dtoh32(bi->length));
+		bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
 	}
 
 done:
@@ -1677,15 +1611,15 @@ int dhd_iscan_request(void *dhdp, u16 action)
 	params.params.bss_type = DOT11_BSSTYPE_ANY;
 	params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
 
-	params.params.nprobes = htod32(-1);
-	params.params.active_time = htod32(-1);
-	params.params.passive_time = htod32(-1);
-	params.params.home_time = htod32(-1);
-	params.params.channel_num = htod32(0);
+	params.params.nprobes = -1;
+	params.params.active_time = -1;
+	params.params.passive_time = -1;
+	params.params.home_time = -1;
+	params.params.channel_num = 0;
 
-	params.version = htod32(ISCAN_REQ_VERSION);
-	params.action = htod16(action);
-	params.scan_duration = htod16(0);
+	params.version = ISCAN_REQ_VERSION;
+	params.action = action;
+	params.scan_duration = 0;
 
 	bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf,
 		    WLC_IOCTL_SMLEN);
@@ -1722,16 +1656,16 @@ static int dhd_iscan_get_partial_result(void *dhdp, uint *scan_count)
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+	list.results.buflen = WLC_IW_ISCAN_MAXLEN;
 	bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
 		    iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
 	rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf,
 			  WLC_IW_ISCAN_MAXLEN);
 
-	results->buflen = dtoh32(results->buflen);
-	results->version = dtoh32(results->version);
-	*scan_count = results->count = dtoh32(results->count);
-	status = dtoh32(list_buf->status);
+	results->buflen = results->buflen;
+	results->version = results->version;
+	*scan_count = results->count = results->count;
+	status = list_buf->status;
 
 	dhd_iscan_unlock();
 
@@ -1854,12 +1788,12 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t *ssids_local, int nssid, unsigned char sc
 	memset(&pfn_element, 0, sizeof(pfn_element));
 
 	/* set pfn parameters */
-	pfn_param.version = htod32(PFN_VERSION);
-	pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
+	pfn_param.version = PFN_VERSION;
+	pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
 
 	/* set up pno scan fr */
 	if (scan_fr != 0)
-		pfn_param.scan_freq = htod32(scan_fr);
+		pfn_param.scan_freq = scan_fr;
 
 	bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf,
 		    sizeof(iovbuf));
@@ -1868,11 +1802,11 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t *ssids_local, int nssid, unsigned char sc
 	/* set all pfn ssid */
 	for (i = 0; i < nssid; i++) {
 
-		pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
-		pfn_element.auth = (DOT11_OPEN_SYSTEM);
-		pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
-		pfn_element.wsec = htod32(0);
-		pfn_element.infra = htod32(1);
+		pfn_element.bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
+		pfn_element.auth = WLAN_AUTH_OPEN;
+		pfn_element.wpa_auth = WPA_AUTH_PFN_ANY;
+		pfn_element.wsec = 0;
+		pfn_element.infra = 1;
 
 		memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID,
 		       ssids_local[i].SSID_len);
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
index c3f18bb..cbfa1c1 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
@@ -15,7 +15,6 @@
  */
 
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <bcmutils.h>
 
 #include <dngl_stats.h>
@@ -149,9 +148,8 @@ int dhd_custom_get_mac_address(unsigned char *buf)
 #ifdef EXAMPLE_GET_MAC
 	/* EXAMPLE code */
 	{
-		struct ether_addr ea_example = {
-			{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF} };
-		bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+		u8 ea_example[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xFF};
+		memcpy(buf, ea_example, ETH_ALEN);
 	}
 #endif				/* EXAMPLE_GET_MAC */
 
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
index cd2578a..0817f13 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
@@ -21,31 +21,31 @@
 
 #define DHD_ERROR(args)	       \
 	do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
-		printf args; } while (0)
+		printk args; } while (0)
 #define DHD_TRACE(args)		do {if (dhd_msg_level & DHD_TRACE_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_INFO(args)		do {if (dhd_msg_level & DHD_INFO_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_DATA(args)		do {if (dhd_msg_level & DHD_DATA_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_CTL(args)		do {if (dhd_msg_level & DHD_CTL_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_TIMER(args)		do {if (dhd_msg_level & DHD_TIMER_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_HDRS(args)		do {if (dhd_msg_level & DHD_HDRS_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_BYTES(args)		do {if (dhd_msg_level & DHD_BYTES_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_INTR(args)		do {if (dhd_msg_level & DHD_INTR_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_GLOM(args)		do {if (dhd_msg_level & DHD_GLOM_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_EVENT(args)		do {if (dhd_msg_level & DHD_EVENT_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_BTA(args)		do {if (dhd_msg_level & DHD_BTA_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_ISCAN(args)		do {if (dhd_msg_level & DHD_ISCAN_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 
 #define DHD_ERROR_ON()		(dhd_msg_level & DHD_ERROR_VAL)
 #define DHD_TRACE_ON()		(dhd_msg_level & DHD_TRACE_VAL)
@@ -63,7 +63,7 @@
 
 #else	/* (defined BCMDBG) || (defined DHD_DEBUG) */
 
-#define DHD_ERROR(args)  do {if (net_ratelimit()) printf args; } while (0)
+#define DHD_ERROR(args)  do {if (net_ratelimit()) printk args; } while (0)
 #define DHD_TRACE(args)
 #define DHD_INFO(args)
 #define DHD_DATA(args)
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
index db45083..02c6d44 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
@@ -32,11 +32,8 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
-#include <bcmendian.h>
 
-#include <proto/ethernet.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhd_bus.h>
@@ -45,7 +42,8 @@
 
 #include <wl_cfg80211.h>
 
-#define EPI_VERSION_STR         "4.218.248.5"
+#define EPI_VERSION_STR		"4.218.248.5"
+#define ETH_P_BRCM			0x886c
 
 #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
 #include <linux/wifi_tiwlan.h>
@@ -149,7 +147,7 @@ static struct platform_driver wifi_device = {
 	.suspend = wifi_suspend,
 	.resume = wifi_resume,
 	.driver = {
-		   .name = "bcm4329_wlan",
+		   .name = KBUILD_MODNAME,
 		   }
 };
 
@@ -247,7 +245,7 @@ typedef struct dhd_info {
 	struct semaphore sysioc_sem;
 	bool set_multicast;
 	bool set_macaddress;
-	struct ether_addr macvalue;
+	u8 macvalue[ETH_ALEN];
 	wait_queue_head_t ctrl_wait;
 	atomic_t pend_8021x_cnt;
 
@@ -387,12 +385,6 @@ module_param(dhd_pktgen_len, uint, 0);
 #define DHD_COMPILED
 #endif
 
-static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR
-#ifdef DHD_DEBUG
-"\nCompiled in " " on " __DATE__ " at " __TIME__
-#endif
-;
-
 #if defined(CONFIG_WIRELESS_EXT)
 struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
 #endif				/* defined(CONFIG_WIRELESS_EXT) */
@@ -719,7 +711,7 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	strcpy(bufp, "mcast_list");
 	bufp += strlen("mcast_list") + 1;
 
-	cnt = htol32(cnt);
+	cnt = cpu_to_le32(cnt);
 	memcpy(bufp, &cnt, sizeof(cnt));
 	bufp += sizeof(cnt);
 
@@ -758,7 +750,7 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 			   dhd_ifname(&dhd->pub, ifidx)));
 		return;
 	}
-	allmulti = htol32(allmulti);
+	allmulti = cpu_to_le32(allmulti);
 
 	if (!bcm_mkiovar
 	    ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
@@ -778,7 +770,8 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
 		DHD_ERROR(("%s: set allmulti %d failed\n",
-			   dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
+			   dhd_ifname(&dhd->pub, ifidx),
+			   le32_to_cpu(allmulti)));
 	}
 
 	kfree(buf);
@@ -787,7 +780,7 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 		 driver does */
 
 	allmulti = (dev->flags & IFF_PROMISC) ? true : false;
-	allmulti = htol32(allmulti);
+	allmulti = cpu_to_le32(allmulti);
 
 	memset(&ioc, 0, sizeof(ioc));
 	ioc.cmd = WLC_SET_PROMISC;
@@ -798,12 +791,13 @@ static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
 	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
 		DHD_ERROR(("%s: set promisc %d failed\n",
-			   dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
+			   dhd_ifname(&dhd->pub, ifidx),
+			   le32_to_cpu(allmulti)));
 	}
 }
 
 static int
-_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr)
+_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
 {
 	char buf[32];
 	wl_ioctl_t ioc;
@@ -976,7 +970,7 @@ static int _dhd_sysioc_thread(void *data)
 				if (dhd->set_macaddress) {
 					dhd->set_macaddress = false;
 					_dhd_set_mac_address(dhd, i,
-							     &dhd->macvalue);
+							     dhd->macvalue);
 				}
 			}
 		}
@@ -1030,11 +1024,11 @@ int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
 	/* Update multicast statistic */
 	if (pktbuf->len >= ETH_ALEN) {
 		u8 *pktdata = (u8 *) (pktbuf->data);
-		struct ether_header *eh = (struct ether_header *)pktdata;
+		struct ethhdr *eh = (struct ethhdr *)pktdata;
 
-		if (is_multicast_ether_addr(eh->ether_dhost))
+		if (is_multicast_ether_addr(eh->h_dest))
 			dhdp->tx_multicast++;
-		if (ntoh16(eh->ether_type) == ETH_P_PAE)
+		if (ntohs(eh->h_proto) == ETH_P_PAE)
 			atomic_inc(&dhd->pend_8021x_cnt);
 	}
 
@@ -1045,7 +1039,6 @@ int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
 #ifdef BCMDBUS
 	ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
 #else
-	WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
 	ret = dhd_bus_txdata(dhdp->bus, pktbuf);
 #endif				/* BCMDBUS */
 
@@ -1053,30 +1046,20 @@ int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf)
 }
 
 static inline void *
-osl_pkt_frmnative(struct osl_info *osh, struct sk_buff *skb)
+osl_pkt_frmnative(struct sk_buff *skb)
 {
-	struct sk_buff *nskb;
-
-	for (nskb = skb; nskb; nskb = nskb->next)
-		osh->pktalloced++;
-
 	return (void *)skb;
 }
 #define PKTFRMNATIVE(osh, skb)	\
-	osl_pkt_frmnative((osh), (struct sk_buff *)(skb))
+	osl_pkt_frmnative((struct sk_buff *)(skb))
 
 static inline struct sk_buff *
-osl_pkt_tonative(struct osl_info *osh, void *pkt)
+osl_pkt_tonative(void *pkt)
 {
-	struct sk_buff *nskb;
-
-	for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next)
-		osh->pktalloced--;
-
 	return (struct sk_buff *)pkt;
 }
 #define PKTTONATIVE(osh, pkt)	\
-	osl_pkt_tonative((osh), (pkt))
+	osl_pkt_tonative((pkt))
 
 static int dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
@@ -1215,7 +1198,7 @@ void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, struct sk_buff *pktbuf,
 		skb_pull(skb, ETH_HLEN);
 
 		/* Process special event packets and then discard them */
-		if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM)
+		if (ntohs(skb->protocol) == ETH_P_BRCM)
 			dhd_wl_host_event(dhd, &ifidx,
 					  skb_mac_header(skb),
 					  &event, &data);
@@ -1254,13 +1237,13 @@ void dhd_txcomplete(dhd_pub_t *dhdp, struct sk_buff *txp, bool success)
 {
 	uint ifidx;
 	dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
-	struct ether_header *eh;
+	struct ethhdr *eh;
 	u16 type;
 
 	dhd_prot_hdrpull(dhdp, &ifidx, txp);
 
-	eh = (struct ether_header *)(txp->data);
-	type = ntoh16(eh->ether_type);
+	eh = (struct ethhdr *)(txp->data);
+	type = ntohs(eh->h_proto);
 
 	if (type == ETH_P_PAE)
 		atomic_dec(&dhd->pend_8021x_cnt);
@@ -1304,7 +1287,6 @@ static struct net_device_stats *dhd_get_stats(struct net_device *net)
 static int dhd_watchdog_thread(void *data)
 {
 	dhd_info_t *dhd = (dhd_info_t *) data;
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_WATCHDOG, "dhd_watchdog_thread");
 
 	/* This thread doesn't need any user-level access,
 	 * so get rid of all our resources
@@ -1325,18 +1307,14 @@ static int dhd_watchdog_thread(void *data)
 			break;
 		if (down_interruptible(&dhd->watchdog_sem) == 0) {
 			if (dhd->pub.dongle_reset == false) {
-				WAKE_LOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
 				/* Call the bus module watchdog */
 				dhd_bus_watchdog(&dhd->pub);
-				WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
 			}
 			/* Count the tick for reference */
 			dhd->pub.tickcnt++;
 		} else
 			break;
 	}
-
-	WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG);
 	return 0;
 }
 
@@ -1370,7 +1348,6 @@ static int dhd_dpc_thread(void *data)
 {
 	dhd_info_t *dhd = (dhd_info_t *) data;
 
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_DPC, "dhd_dpc_thread");
 	/* This thread doesn't need any user-level access,
 	 * so get rid of all our resources
 	 */
@@ -1393,21 +1370,15 @@ static int dhd_dpc_thread(void *data)
 			/* Call bus dpc unless it indicated down
 				 (then clean stop) */
 			if (dhd->pub.busstate != DHD_BUS_DOWN) {
-				WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC);
 				if (dhd_bus_dpc(dhd->pub.bus)) {
 					up(&dhd->dpc_sem);
-					WAKE_LOCK_TIMEOUT(&dhd->pub,
-							  WAKE_LOCK_TMOUT, 25);
 				}
-				WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_DPC);
 			} else {
 				dhd_bus_stop(dhd->pub.bus, true);
 			}
 		} else
 			break;
 	}
-
-	WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_DPC);
 	return 0;
 }
 
@@ -1797,22 +1768,16 @@ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
 	if (is_set_key_cmd)
 		dhd_wait_pend8021x(net);
 
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_IOCTL, "dhd_ioctl_entry");
-	WAKE_LOCK(&dhd->pub, WAKE_LOCK_IOCTL);
-
 	bcmerror =
 	    dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
 
-	WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_IOCTL);
-	WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_IOCTL);
 done:
 	if (!bcmerror && buf && ioc.buf) {
 		if (copy_to_user(ioc.buf, buf, buflen))
 			bcmerror = -EFAULT;
 	}
 
-	if (buf)
-		kfree(buf);
+	kfree(buf);
 
 	if (bcmerror > 0)
 		bcmerror = 0;
@@ -1866,7 +1831,7 @@ static int dhd_open(struct net_device *net)
 		}
 		atomic_set(&dhd->pend_8021x_cnt, 0);
 
-		memcpy(net->dev_addr, dhd->pub.mac.octet, ETH_ALEN);
+		memcpy(net->dev_addr, dhd->pub.mac, ETH_ALEN);
 
 #ifdef TOE
 		/* Get current TOE mode from dongle */
@@ -1891,16 +1856,6 @@ static int dhd_open(struct net_device *net)
 	return ret;
 }
 
-struct osl_info *dhd_osl_attach(void *pdev, uint bustype)
-{
-	return osl_attach(pdev, bustype);
-}
-
-void dhd_osl_detach(struct osl_info *osh)
-{
-	osl_detach(osh);
-}
-
 int
 dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
 	   u8 *mac_addr, u32 flags, u8 bssidx)
@@ -1954,8 +1909,7 @@ void dhd_del_if(dhd_info_t *dhd, int ifidx)
 	up(&dhd->sysioc_sem);
 }
 
-dhd_pub_t *dhd_attach(struct osl_info *osh, struct dhd_bus *bus,
-			uint bus_hdrlen)
+dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
 {
 	dhd_info_t *dhd = NULL;
 	struct net_device *net;
@@ -1976,19 +1930,16 @@ dhd_pub_t *dhd_attach(struct osl_info *osh, struct dhd_bus *bus,
 	}
 
 	/* Allocate primary dhd_info */
-	dhd = kmalloc(sizeof(dhd_info_t), GFP_ATOMIC);
+	dhd = kzalloc(sizeof(dhd_info_t), GFP_ATOMIC);
 	if (!dhd) {
 		DHD_ERROR(("%s: OOM - alloc dhd_info\n", __func__));
 		goto fail;
 	}
 
-	memset(dhd, 0, sizeof(dhd_info_t));
-
 	/*
 	 * Save the dhd_info into the priv
 	 */
 	memcpy(netdev_priv(net), &dhd, sizeof(dhd));
-	dhd->pub.osh = osh;
 
 	/* Set network interface name if it was provided as module parameter */
 	if (iface_name[0]) {
@@ -2115,11 +2066,6 @@ dhd_pub_t *dhd_attach(struct osl_info *osh, struct dhd_bus *bus,
 #endif	/* defined(CONFIG_PM_SLEEP) */
 	/* && defined(DHD_GPL) */
 	/* Init lock suspend to prevent kernel going to suspend */
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_TMOUT, "dhd_wake_lock");
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_LINK_DOWN_TMOUT,
-		       "dhd_wake_lock_link_dw_event");
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_PNO_FIND_TMOUT,
-		       "dhd_wake_lock_link_pno_find_event");
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
 	dhd->early_suspend.suspend = dhd_early_suspend;
@@ -2153,20 +2099,13 @@ int dhd_bus_start(dhd_pub_t *dhdp)
 
 	/* try to download image and nvram to the dongle */
 	if (dhd->pub.busstate == DHD_BUS_DOWN) {
-		WAKE_LOCK_INIT(dhdp, WAKE_LOCK_DOWNLOAD, "dhd_bus_start");
-		WAKE_LOCK(dhdp, WAKE_LOCK_DOWNLOAD);
-		if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
+		if (!(dhd_bus_download_firmware(dhd->pub.bus,
 						fw_path, nv_path))) {
 			DHD_ERROR(("%s: dhdsdio_probe_download failed. "
 				"firmware = %s nvram = %s\n",
 				__func__, fw_path, nv_path));
-			WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
 			return -1;
 		}
-
-		WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
-		WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
 	}
 
 	/* Start the watchdog timer */
@@ -2203,7 +2142,7 @@ int dhd_bus_start(dhd_pub_t *dhdp)
 	bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
 		    sizeof(iovbuf));
 	dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
-	bcopy(iovbuf, dhdp->eventmask, WL_EVENTING_MASK_LEN);
+	memcpy(dhdp->eventmask, iovbuf, WL_EVENTING_MASK_LEN);
 
 	setbit(dhdp->eventmask, WLC_E_SET_SSID);
 	setbit(dhdp->eventmask, WLC_E_PRUNE);
@@ -2299,7 +2238,7 @@ int dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
 	 */
 	if (ifidx != 0) {
 		/* for virtual interfaces use the primary MAC  */
-		memcpy(temp_addr, dhd->pub.mac.octet, ETH_ALEN);
+		memcpy(temp_addr, dhd->pub.mac, ETH_ALEN);
 
 	}
 
@@ -2335,7 +2274,7 @@ int dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
 		goto fail;
 	}
 
-	printf("%s: Broadcom Dongle Host Driver\n", net->name);
+	DHD_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
 
 	return 0;
 
@@ -2432,9 +2371,6 @@ void dhd_detach(dhd_pub_t *dhdp)
 			unregister_pm_notifier(&dhd_sleep_pm_notifier);
 #endif	/* defined(CONFIG_PM_SLEEP) */
 			/* && defined(DHD_GPL) */
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT);
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT);
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_PNO_FIND_TMOUT);
 			free_netdev(ifp->net);
 			kfree(ifp);
 			kfree(dhd);
@@ -2483,7 +2419,7 @@ static int __init dhd_module_init(void)
 	error = wifi_add_dev();
 	if (error) {
 		DHD_ERROR(("%s: platform_driver_register failed\n", __func__));
-		goto faild;
+		goto failed;
 	}
 
 	/* Waiting callback after platform_driver_register is done or
@@ -2493,21 +2429,19 @@ static int __init dhd_module_init(void)
 			__func__);
 		/* remove device */
 		wifi_del_dev();
-		goto faild;
+		goto failed;
 	}
 #endif	/* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
 
 	error = dhd_bus_register();
 
-	if (!error)
-		printf("\n%s\n", dhd_version);
-	else {
+	if (error) {
 		DHD_ERROR(("%s: sdio_register_driver failed\n", __func__));
-		goto faild;
+		goto failed;
 	}
 	return error;
 
-faild:
+failed:
 	/* turn off power and exit */
 	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
 	return -EINVAL;
@@ -2790,7 +2724,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata,
 /* send up locally generated event */
 void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
 {
-	switch (ntoh32(event->event_type)) {
+	switch (be32_to_cpu(event->event_type)) {
 	default:
 		break;
 	}
@@ -2975,7 +2909,7 @@ int write_to_file(dhd_pub_t *dhd, u8 *buf, int size)
 	/* open file to write */
 	fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
 	if (!fp) {
-		printf("%s: open file error\n", __func__);
+		DHD_ERROR(("%s: open file error\n", __func__));
 		ret = -1;
 		goto exit;
 	}
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
index a5309e2..030d5ff 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
@@ -46,9 +46,6 @@ extern int dhd_prot_init(dhd_pub_t *dhdp);
 /* Stop protocol: sync w/dongle state. */
 extern void dhd_prot_stop(dhd_pub_t *dhdp);
 
-extern bool dhd_proto_fcinfo(dhd_pub_t *dhd, struct sk_buff *pktbuf,
-			     u8 *fcbits);
-
 /* Add any protocol-specific data header.
  * Caller must reserve prot_hdrlen prepend space.
  */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
index 3edce44..1066270 100644
--- a/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <bcmdefs.h>
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <bcmsdh.h>
 
 #ifdef BCMEMBEDIMAGE
@@ -26,7 +25,6 @@
 
 #include <bcmdefs.h>
 #include <bcmutils.h>
-#include <bcmendian.h>
 #include <bcmdevs.h>
 
 #include <siutils.h>
@@ -44,8 +42,6 @@
 #include <sbsdpcmdev.h>
 #include <bcmsdpcm.h>
 
-#include <proto/ethernet.h>
-#include <proto/802.1d.h>
 #include <proto/802.11.h>
 
 #include <dngl_stats.h>
@@ -61,9 +57,9 @@
 #define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
 #endif
 
-#define QLEN		256	/* bulk rx and tx queue lengths */
-#define FCHI		(QLEN - 10)
-#define FCLOW		(FCHI / 2)
+#define TXQLEN		2048	/* bulk tx queue length */
+#define TXHI		(TXQLEN - 256)	/* turn on flow control above TXHI */
+#define TXLOW		(TXHI - 256)	/* turn off flow control below TXLOW */
 #define PRIOMASK	7
 
 #define TXRETRIES	2	/* # of retries for tx frames */
@@ -144,7 +140,15 @@
  * bufpool was present for gspi bus.
  */
 #define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
-							pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+							pkt_buf_free_skb(pkt);
+
+/*
+ * Conversion of 802.1D priority to precedence level
+ */
+#define PRIO2PREC(prio) \
+	(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
+	((prio^2)) : (prio))
+
 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
 			    uint len);
@@ -329,7 +333,6 @@ uint dhd_txminmax;
 #define DONGLE_MIN_MEMSIZE (128 * 1024)
 int dhd_dongle_memsize;
 
-static bool dhd_doflow;
 static bool dhd_alignctl;
 
 static bool sd1idle;
@@ -357,7 +360,7 @@ extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
 #endif	/* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
-#define PKTALIGN(_osh, _p, _len, _align)				\
+#define PKTALIGN(_p, _len, _align)				\
 	do {								\
 		uint datalign;						\
 		datalign = (unsigned long)((_p)->data);			\
@@ -386,7 +389,7 @@ static bool dhd_readahead;
 do { \
 	retryvar = 0; \
 	do { \
-		regvar = R_REG(bus->dhd->osh, regaddr); \
+		regvar = R_REG(regaddr); \
 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
 	if (retryvar) { \
 		bus->regfails += (retryvar-1); \
@@ -402,7 +405,7 @@ do { \
 do { \
 	retryvar = 0; \
 	do { \
-		W_REG(bus->dhd->osh, regaddr, regval); \
+		W_REG(regaddr, regval); \
 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
 	if (retryvar) { \
 		bus->regfails += (retryvar-1); \
@@ -431,16 +434,15 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus);
 #endif				/* DHD_DEBUG  */
 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
 
-static void dhdsdio_release(dhd_bus_t *bus, struct osl_info *osh);
-static void dhdsdio_release_malloc(dhd_bus_t *bus, struct osl_info *osh);
+static void dhdsdio_release(dhd_bus_t *bus);
+static void dhdsdio_release_malloc(dhd_bus_t *bus);
 static void dhdsdio_disconnect(void *ptr);
 static bool dhdsdio_chipmatch(u16 chipid);
-static bool dhdsdio_probe_attach(dhd_bus_t *bus, struct osl_info *osh,
-				 void *sdh, void *regsva, u16 devid);
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, struct osl_info *osh,
-				 void *sdh);
-static bool dhdsdio_probe_init(dhd_bus_t *bus, struct osl_info *osh, void *sdh);
-static void dhdsdio_release_dongle(dhd_bus_t *bus, struct osl_info * osh);
+static bool dhdsdio_probe_attach(dhd_bus_t *bus, void *sdh,
+				 void *regsva, u16 devid);
+static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh);
+static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh);
+static void dhdsdio_release_dongle(dhd_bus_t *bus);
 
 static uint process_nvram_vars(char *varbuf, uint len);
 
@@ -454,8 +456,7 @@ static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, u32 addr, uint fn,
 			       struct sk_buff *pkt, bcmsdh_cmplt_fn_t complete,
 			       void *handle);
 
-static bool dhdsdio_download_firmware(struct dhd_bus *bus, struct osl_info *osh,
-				      void *sdh);
+static bool dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh);
 static int _dhdsdio_download_firmware(struct dhd_bus *bus);
 
 static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
@@ -908,7 +909,6 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 			 bool free_pkt)
 {
 	int ret;
-	struct osl_info *osh;
 	u8 *frame;
 	u16 len, pad = 0;
 	u32 swheader;
@@ -920,7 +920,6 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 	DHD_TRACE(("%s: Enter\n", __func__));
 
 	sdh = bus->sdh;
-	osh = bus->dhd->osh;
 
 	if (bus->dhd->dongle_reset) {
 		ret = BCME_NOTREADY;
@@ -936,7 +935,7 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 			DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
 				  __func__, skb_headroom(pkt), pad));
 			bus->dhd->tx_realloc++;
-			new = pkt_buf_get_skb(osh, (pkt->len + DHD_SDALIGN));
+			new = pkt_buf_get_skb(pkt->len + DHD_SDALIGN);
 			if (!new) {
 				DHD_ERROR(("%s: couldn't allocate new %d-byte "
 					"packet\n",
@@ -945,10 +944,10 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 				goto done;
 			}
 
-			PKTALIGN(osh, new, pkt->len, DHD_SDALIGN);
-			bcopy(pkt->data, new->data, pkt->len);
+			PKTALIGN(new, pkt->len, DHD_SDALIGN);
+			memcpy(new->data, pkt->data, pkt->len);
 			if (free_pkt)
-				pkt_buf_free_skb(osh, pkt, true);
+				pkt_buf_free_skb(pkt);
 			/* free the pkt if canned one is not used */
 			free_pkt = true;
 			pkt = new;
@@ -967,16 +966,17 @@ static int dhdsdio_txpkt(dhd_bus_t *bus, struct sk_buff *pkt, uint chan,
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
 	len = (u16) (pkt->len);
-	*(u16 *) frame = htol16(len);
-	*(((u16 *) frame) + 1) = htol16(~len);
+	*(u16 *) frame = cpu_to_le16(len);
+	*(((u16 *) frame) + 1) = cpu_to_le16(~len);
 
 	/* Software tag: channel, sequence number, data offset */
 	swheader =
 	    ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
 	    (((pad +
 	       SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
-	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+
+	put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 #ifdef DHD_DEBUG
 	tx_packets[pkt->priority]++;
@@ -1061,7 +1061,7 @@ done:
 	dhd_os_sdlock(bus->dhd);
 
 	if (free_pkt)
-		pkt_buf_free_skb(osh, pkt, true);
+		pkt_buf_free_skb(pkt);
 
 	return ret;
 }
@@ -1069,12 +1069,10 @@ done:
 int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
 {
 	int ret = BCME_ERROR;
-	struct osl_info *osh;
 	uint datalen, prec;
 
 	DHD_TRACE(("%s: Enter\n", __func__));
 
-	osh = bus->dhd->osh;
 	datalen = pkt->len;
 
 #ifdef SDTEST
@@ -1112,7 +1110,7 @@ int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
 		if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == false) {
 			skb_pull(pkt, SDPCM_HDRLEN);
 			dhd_txcomplete(bus->dhd, pkt, false);
-			pkt_buf_free_skb(osh, pkt, true);
+			pkt_buf_free_skb(pkt);
 			DHD_ERROR(("%s: out of bus->txq !!!\n", __func__));
 			ret = BCME_NORESOURCE;
 		} else {
@@ -1120,7 +1118,7 @@ int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
 		}
 		dhd_os_sdunlock_txq(bus->dhd);
 
-		if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow)
+		if (pktq_len(&bus->txq) >= TXHI)
 			dhd_txflowcontrol(bus->dhd, 0, ON);
 
 #ifdef DHD_DEBUG
@@ -1218,8 +1216,8 @@ static uint dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
 	}
 
 	/* Deflow-control stack if needed */
-	if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
-	    dhd->txoff && (pktq_len(&bus->txq) < FCLOW))
+	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
+	    dhd->txoff && (pktq_len(&bus->txq) < TXLOW))
 		dhd_txflowcontrol(dhd, 0, OFF);
 
 	return cnt;
@@ -1282,8 +1280,8 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 	dhdsdio_clkctl(bus, CLK_AVAIL, false);
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
-	*(u16 *) frame = htol16((u16) msglen);
-	*(((u16 *) frame) + 1) = htol16(~msglen);
+	*(u16 *) frame = cpu_to_le16((u16) msglen);
+	*(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
 
 	/* Software tag: channel, sequence number, data offset */
 	swheader =
@@ -1291,8 +1289,8 @@ int dhd_bus_txctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 	     SDPCM_CHANNEL_MASK)
 	    | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
 			     SDPCM_DOFFSET_MASK);
-	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
-	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+	put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 	if (!DATAOK(bus)) {
 		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
@@ -1396,7 +1394,7 @@ int dhd_bus_rxctl(struct dhd_bus *bus, unsigned char *msg, uint msglen)
 
 	dhd_os_sdlock(bus->dhd);
 	rxlen = bus->rxlen;
-	bcopy(bus->rxctl, msg, min(msglen, rxlen));
+	memcpy(msg, bus->rxctl, min(msglen, rxlen));
 	bus->rxlen = 0;
 	dhd_os_sdunlock(bus->dhd);
 
@@ -1659,7 +1657,7 @@ static int dhdsdio_pktgen_get(dhd_bus_t *bus, u8 *arg)
 	pktgen.mode = bus->pktgen_mode;
 	pktgen.stop = bus->pktgen_stop;
 
-	bcopy(&pktgen, arg, sizeof(pktgen));
+	memcpy(arg, &pktgen, sizeof(pktgen));
 
 	return 0;
 }
@@ -1669,7 +1667,7 @@ static int dhdsdio_pktgen_set(dhd_bus_t *bus, u8 *arg)
 	dhd_pktgen_t pktgen;
 	uint oldcnt, oldmode;
 
-	bcopy(arg, &pktgen, sizeof(pktgen));
+	memcpy(&pktgen, arg, sizeof(pktgen));
 	if (pktgen.version != DHD_PKTGEN_VERSION)
 		return BCME_BADARG;
 
@@ -1769,7 +1767,7 @@ static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
 	if (rv < 0)
 		return rv;
 
-	addr = ltoh32(addr);
+	addr = le32_to_cpu(addr);
 
 	DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
 
@@ -1790,13 +1788,13 @@ static int dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
 		return rv;
 
 	/* Endianness */
-	sh->flags = ltoh32(sh->flags);
-	sh->trap_addr = ltoh32(sh->trap_addr);
-	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
-	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
-	sh->assert_line = ltoh32(sh->assert_line);
-	sh->console_addr = ltoh32(sh->console_addr);
-	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
+	sh->flags = le32_to_cpu(sh->flags);
+	sh->trap_addr = le32_to_cpu(sh->trap_addr);
+	sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
+	sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
+	sh->assert_line = le32_to_cpu(sh->assert_line);
+	sh->console_addr = le32_to_cpu(sh->console_addr);
+	sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
 
 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
 		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
@@ -1932,10 +1930,8 @@ static int dhdsdio_checkdied(dhd_bus_t *bus, u8 *data, uint size)
 #endif				/* DHD_DEBUG */
 
 done:
-	if (mbuffer)
-		kfree(mbuffer);
-	if (str)
-		kfree(str);
+	kfree(mbuffer);
+	kfree(str);
 
 	return bcmerror;
 }
@@ -1952,34 +1948,33 @@ static int dhdsdio_mem_dump(dhd_bus_t *bus)
 	size = bus->ramsize;
 	buf = kmalloc(size, GFP_ATOMIC);
 	if (!buf) {
-		printf("%s: Out of memory (%d bytes)\n", __func__, size);
+		DHD_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
 		return -1;
 	}
 
 	/* Read mem content */
-	printf("Dump dongle memory");
+	printk(KERN_DEBUG "Dump dongle memory");
 	databuf = buf;
 	while (size) {
 		read_size = min(MEMBLOCK, size);
 		ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
 		if (ret) {
-			printf("%s: Error membytes %d\n", __func__, ret);
-			if (buf)
-				kfree(buf);
+			DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
+			kfree(buf);
 			return -1;
 		}
-		printf(".");
+		printk(".");
 
 		/* Decrement size and increment start address */
 		size -= read_size;
 		start += read_size;
 		databuf += read_size;
 	}
-	printf("Done\n");
+	printk(KERN_DEBUG "Done\n");
 
 	/* free buf before return !!! */
 	if (write_to_file(bus->dhd, buf, bus->ramsize)) {
-		printf("%s: Error writing to files\n", __func__);
+		DHD_ERROR(("%s: Error writing to files\n", __func__));
 		return -1;
 	}
 
@@ -2009,13 +2004,13 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
 
 	/* Allocate console buffer (one time only) */
 	if (c->buf == NULL) {
-		c->bufsize = ltoh32(c->log.buf_size);
+		c->bufsize = le32_to_cpu(c->log.buf_size);
 		c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
 		if (c->buf == NULL)
 			return BCME_NOMEM;
 	}
 
-	idx = ltoh32(c->log.idx);
+	idx = le32_to_cpu(c->log.idx);
 
 	/* Protect against corrupt value */
 	if (idx > c->bufsize)
@@ -2027,7 +2022,7 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
 		return BCME_OK;
 
 	/* Read the console buffer */
-	addr = ltoh32(c->log.buf);
+	addr = le32_to_cpu(c->log.buf);
 	rv = dhdsdio_membytes(bus, false, addr, c->buf, c->bufsize);
 	if (rv < 0)
 		return rv;
@@ -2057,7 +2052,7 @@ static int dhdsdio_readconsole(dhd_bus_t *bus)
 			if (line[n - 1] == '\r')
 				n--;
 			line[n] = 0;
-			printf("CONSOLE: %s\n", line);
+			printk(KERN_DEBUG "CONSOLE: %s\n", line);
 		}
 	}
 break2:
@@ -2083,8 +2078,7 @@ int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
 	}
 
 	/* Free the old ones and replace with passed variables */
-	if (bus->vars)
-		kfree(bus->vars);
+	kfree(bus->vars);
 
 	bus->vars = kmalloc(len, GFP_ATOMIC);
 	bus->varsz = bus->vars ? len : 0;
@@ -2095,7 +2089,7 @@ int dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
 
 	/* Copy the passed variables, which should include the
 		 terminating double-null */
-	bcopy(arg, bus->vars, bus->varsz);
+	memcpy(bus->vars, arg, bus->varsz);
 err:
 	return bcmerror;
 }
@@ -2118,7 +2112,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		goto exit;
 
 	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
+		memcpy(&int_val, params, sizeof(int_val));
 
 	bool_val = (int_val != 0) ? true : false;
 
@@ -2138,7 +2132,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			bcmerror = dhdsdio_bussleep(bus, bool_val);
 		} else {
 			int_val = (s32) bus->sleeping;
-			bcopy(&int_val, arg, val_size);
+			memcpy(arg, &int_val, val_size);
 		}
 		goto exit;
 	}
@@ -2152,7 +2146,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 	switch (actionid) {
 	case IOV_GVAL(IOV_INTR):
 		int_val = (s32) bus->intr;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_INTR):
@@ -2173,7 +2167,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_POLLRATE):
 		int_val = (s32) bus->pollrate;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_POLLRATE):
@@ -2183,7 +2177,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_IDLETIME):
 		int_val = bus->idletime;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_IDLETIME):
@@ -2195,7 +2189,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_IDLECLOCK):
 		int_val = (s32) bus->idleclock;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_IDLECLOCK):
@@ -2204,7 +2198,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_SD1IDLE):
 		int_val = (s32) sd1idle;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SD1IDLE):
@@ -2223,8 +2217,8 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			ASSERT(plen >= 2 * sizeof(int));
 
 			address = (u32) int_val;
-			bcopy((char *)params + sizeof(int_val), &int_val,
-			      sizeof(int_val));
+			memcpy(&int_val, (char *)params + sizeof(int_val),
+			       sizeof(int_val));
 			size = (uint) int_val;
 
 			/* Do some validation */
@@ -2267,17 +2261,17 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_MEMSIZE):
 		int_val = (s32) bus->ramsize;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_SDIOD_DRIVE):
 		int_val = (s32) dhd_sdiod_drive_strength;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDIOD_DRIVE):
 		dhd_sdiod_drive_strength = int_val;
-		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh,
+		si_sdiod_drive_strength_init(bus->sih,
 					     dhd_sdiod_drive_strength);
 		break;
 
@@ -2291,7 +2285,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_READAHEAD):
 		int_val = (s32) dhd_readahead;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_READAHEAD):
@@ -2302,7 +2296,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_SDRXCHAIN):
 		int_val = (s32) bus->use_rxchain;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDRXCHAIN):
@@ -2313,7 +2307,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 		break;
 	case IOV_GVAL(IOV_ALIGNCTL):
 		int_val = (s32) dhd_alignctl;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_ALIGNCTL):
@@ -2322,13 +2316,13 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_SDALIGN):
 		int_val = DHD_SDALIGN;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 #ifdef DHD_DEBUG
 	case IOV_GVAL(IOV_VARS):
 		if (bus->varsz < (uint) len)
-			bcopy(bus->vars, arg, bus->varsz);
+			memcpy(arg, bus->vars, bus->varsz);
 		else
 			bcmerror = BCME_BUFTOOSHORT;
 		break;
@@ -2347,7 +2341,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
 			if (bcmsdh_regfail(bus->sdh))
 				bcmerror = BCME_SDIO_ERROR;
-			bcopy(&int_val, arg, sizeof(s32));
+			memcpy(arg, &int_val, sizeof(s32));
 			break;
 		}
 
@@ -2373,14 +2367,14 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			sdreg_t sdreg;
 			u32 addr, size;
 
-			bcopy(params, &sdreg, sizeof(sdreg));
+			memcpy(&sdreg, params, sizeof(sdreg));
 
 			addr = SI_ENUM_BASE + sdreg.offset;
 			size = sdreg.func;
 			int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
 			if (bcmsdh_regfail(bus->sdh))
 				bcmerror = BCME_SDIO_ERROR;
-			bcopy(&int_val, arg, sizeof(s32));
+			memcpy(arg, &int_val, sizeof(s32));
 			break;
 		}
 
@@ -2389,7 +2383,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			sdreg_t sdreg;
 			u32 addr, size;
 
-			bcopy(params, &sdreg, sizeof(sdreg));
+			memcpy(&sdreg, params, sizeof(sdreg));
 
 			addr = SI_ENUM_BASE + sdreg.offset;
 			size = sdreg.func;
@@ -2420,7 +2414,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_FORCEEVEN):
 		int_val = (s32) forcealign;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_FORCEEVEN):
@@ -2429,7 +2423,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_TXBOUND):
 		int_val = (s32) dhd_txbound;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_TXBOUND):
@@ -2438,7 +2432,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_RXBOUND):
 		int_val = (s32) dhd_rxbound;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_RXBOUND):
@@ -2447,7 +2441,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 	case IOV_GVAL(IOV_TXMINMAX):
 		int_val = (s32) dhd_txminmax;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_TXMINMAX):
@@ -2458,7 +2452,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 #ifdef SDTEST
 	case IOV_GVAL(IOV_EXTLOOP):
 		int_val = (s32) bus->ext_loop;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_EXTLOOP):
@@ -2480,9 +2474,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 			__func__, bool_val, bus->dhd->dongle_reset,
 			bus->dhd->busstate));
 
-		ASSERT(bus->dhd->osh);
-		/* ASSERT(bus->cl_devid); */
-
 		dhd_bus_devreset(bus->dhd, (u8) bool_val);
 
 		break;
@@ -2492,7 +2483,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, u32 actionid,
 
 		/* Get its status */
 		int_val = (bool) bus->dhd->dongle_reset;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 
 		break;
 
@@ -2532,12 +2523,11 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
 	varaddr = (bus->ramsize - 4) - varsize;
 
 	if (bus->vars) {
-		vbuffer = kmalloc(varsize, GFP_ATOMIC);
+		vbuffer = kzalloc(varsize, GFP_ATOMIC);
 		if (!vbuffer)
 			return BCME_NOMEM;
 
-		memset(vbuffer, 0, varsize);
-		bcopy(bus->vars, vbuffer, bus->varsz);
+		memcpy(vbuffer, bus->vars, bus->varsz);
 
 		/* Write the vars list */
 		bcmerror =
@@ -2590,7 +2580,7 @@ static int dhdsdio_write_vars(dhd_bus_t *bus)
 	} else {
 		varsizew = varsize / 4;
 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
-		varsizew = htol32(varsizew);
+		varsizew = cpu_to_le32(varsizew);
 	}
 
 	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
@@ -2828,7 +2818,6 @@ exit:
 
 void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
 {
-	struct osl_info *osh = bus->dhd->osh;
 	u32 local_hostintmask;
 	u8 saveclk;
 	uint retries;
@@ -2878,14 +2867,14 @@ void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
 	dhdsdio_clkctl(bus, CLK_SDONLY, false);
 
 	/* Clear the data packet queues */
-	pktq_flush(osh, &bus->txq, true);
+	pktq_flush(&bus->txq, true);
 
 	/* Clear any held glomming stuff */
 	if (bus->glomd)
-		pkt_buf_free_skb(osh, bus->glomd, false);
+		pkt_buf_free_skb(bus->glomd);
 
 	if (bus->glom)
-		pkt_buf_free_skb(osh, bus->glom, false);
+		pkt_buf_free_skb(bus->glom);
 
 	bus->glom = bus->glomd = NULL;
 
@@ -3100,13 +3089,13 @@ dhdsdio_read_control(dhd_bus_t *bus, u8 *hdr, uint len, uint doff)
 	ASSERT(bus->rxctl >= bus->rxbuf);
 
 	/* Copy the already-read portion over */
-	bcopy(hdr, bus->rxctl, firstread);
+	memcpy(bus->rxctl, hdr, firstread);
 	if (len <= firstread)
 		goto gotpkt;
 
 	/* Copy the full data pkt in gSPI case and process ioctl. */
 	if (bus->bus == SPI_BUS) {
-		bcopy(hdr, bus->rxctl, len);
+		memcpy(bus->rxctl, hdr, len);
 		goto gotpkt;
 	}
 
@@ -3184,7 +3173,6 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 
 	u16 sublen, check;
 	struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
-	struct osl_info *osh = bus->dhd->osh;
 
 	int errcode;
 	u8 chan, seq, doff, sfdoff;
@@ -3214,7 +3202,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 
 		for (totlen = num = 0; dlen; num++) {
 			/* Get (and move past) next length */
-			sublen = ltoh16_ua(dptr);
+			sublen = get_unaligned_le16(dptr);
 			dlen -= sizeof(u16);
 			dptr += sizeof(u16);
 			if ((sublen < SDPCM_HDRLEN) ||
@@ -3240,7 +3228,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			}
 
 			/* Allocate/chain packet for next subframe */
-			pnext = pkt_buf_get_skb(osh, sublen + DHD_SDALIGN);
+			pnext = pkt_buf_get_skb(sublen + DHD_SDALIGN);
 			if (pnext == NULL) {
 				DHD_ERROR(("%s: pkt_buf_get_skb failed, num %d len %d\n",
 					   __func__, num, sublen));
@@ -3257,7 +3245,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			}
 
 			/* Adhere to start alignment requirements */
-			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
+			PKTALIGN(pnext, sublen, DHD_SDALIGN);
 		}
 
 		/* If all allocations succeeded, save packet chain
@@ -3276,13 +3264,13 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			pfirst = pnext = NULL;
 		} else {
 			if (pfirst)
-				pkt_buf_free_skb(osh, pfirst, false);
+				pkt_buf_free_skb(pfirst);
 			bus->glom = NULL;
 			num = 0;
 		}
 
 		/* Done with descriptor packet */
-		pkt_buf_free_skb(osh, bus->glomd, false);
+		pkt_buf_free_skb(bus->glomd);
 		bus->glomd = NULL;
 		bus->nextlen = 0;
 
@@ -3303,7 +3291,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 		}
 
 		pfirst = bus->glom;
-		dlen = (u16) pkttotlen(osh, pfirst);
+		dlen = (u16) pkttotlen(pfirst);
 
 		/* Do an SDIO read for the superframe.  Configurable iovar to
 		 * read directly into the chained packet, or allocate a large
@@ -3323,7 +3311,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 						      F2SYNC, bus->dataptr,
 						      dlen, NULL, NULL, NULL);
 			sublen =
-			    (u16) pktfrombuf(osh, pfirst, 0, dlen,
+			    (u16) pktfrombuf(pfirst, 0, dlen,
 						bus->dataptr);
 			if (sublen != dlen) {
 				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
@@ -3351,7 +3339,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 				bus->glomerr = 0;
 				dhdsdio_rxfail(bus, true, false);
 				dhd_os_sdlock_rxq(bus->dhd);
-				pkt_buf_free_skb(osh, bus->glom, false);
+				pkt_buf_free_skb(bus->glom);
 				dhd_os_sdunlock_rxq(bus->dhd);
 				bus->rxglomfail++;
 				bus->glom = NULL;
@@ -3367,8 +3355,8 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 
 		/* Validate the superframe header */
 		dptr = (u8 *) (pfirst->data);
-		sublen = ltoh16_ua(dptr);
-		check = ltoh16_ua(dptr + sizeof(u16));
+		sublen = get_unaligned_le16(dptr);
+		check = get_unaligned_le16(dptr + sizeof(u16));
 
 		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -3437,8 +3425,8 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 		     num++, pnext = pnext->next) {
 			dptr = (u8 *) (pnext->data);
 			dlen = (u16) (pnext->len);
-			sublen = ltoh16_ua(dptr);
-			check = ltoh16_ua(dptr + sizeof(u16));
+			sublen = get_unaligned_le16(dptr);
+			check = get_unaligned_le16(dptr + sizeof(u16));
 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
 #ifdef DHD_DEBUG
@@ -3480,7 +3468,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 				bus->glomerr = 0;
 				dhdsdio_rxfail(bus, true, false);
 				dhd_os_sdlock_rxq(bus->dhd);
-				pkt_buf_free_skb(osh, bus->glom, false);
+				pkt_buf_free_skb(bus->glom);
 				dhd_os_sdunlock_rxq(bus->dhd);
 				bus->rxglomfail++;
 				bus->glom = NULL;
@@ -3500,7 +3488,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			pfirst->next = NULL;
 
 			dptr = (u8 *) (pfirst->data);
-			sublen = ltoh16_ua(dptr);
+			sublen = get_unaligned_le16(dptr);
 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -3528,7 +3516,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 			skb_pull(pfirst, doff);
 
 			if (pfirst->len == 0) {
-				pkt_buf_free_skb(bus->dhd->osh, pfirst, false);
+				pkt_buf_free_skb(pfirst);
 				if (plast) {
 					plast->next = pnext;
 				} else {
@@ -3541,7 +3529,7 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 				DHD_ERROR(("%s: rx protocol error\n",
 					   __func__));
 				bus->dhd->rx_errors++;
-				pkt_buf_free_skb(osh, pfirst, false);
+				pkt_buf_free_skb(pfirst);
 				if (plast) {
 					plast->next = pnext;
 				} else {
@@ -3585,7 +3573,6 @@ static u8 dhdsdio_rxglom(dhd_bus_t *bus, u8 rxseq)
 /* Return true if there may be more frames to read */
 static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 {
-	struct osl_info *osh = bus->dhd->osh;
 	bcmsdh_info_t *sdh = bus->sdh;
 
 	u16 len, check;	/* Extracted hardware header fields */
@@ -3680,7 +3667,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			 */
 			/* Allocate a packet buffer */
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt = pkt_buf_get_skb(osh, rdlen + DHD_SDALIGN);
+			pkt = pkt_buf_get_skb(rdlen + DHD_SDALIGN);
 			if (!pkt) {
 				if (bus->bus == SPI_BUS) {
 					bus->usebufpool = false;
@@ -3738,7 +3725,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 					bus->usebufpool = true;
 
 				ASSERT(!(pkt->prev));
-				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
+				PKTALIGN(pkt, rdlen, DHD_SDALIGN);
 				rxbuf = (u8 *) (pkt->data);
 				/* Read the entire frame */
 				sdret =
@@ -3753,7 +3740,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 				if (sdret < 0) {
 					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
 						__func__, rdlen, sdret));
-					pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+					pkt_buf_free_skb(pkt);
 					bus->dhd->rx_errors++;
 					dhd_os_sdunlock_rxq(bus->dhd);
 					/* Force retry w/normal header read.
@@ -3770,11 +3757,11 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 			dhd_os_sdunlock_rxq(bus->dhd);
 
 			/* Now check the header */
-			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
+			memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
 
 			/* Extract hardware header fields */
-			len = ltoh16_ua(bus->rxhdr);
-			check = ltoh16_ua(bus->rxhdr + sizeof(u16));
+			len = get_unaligned_le16(bus->rxhdr);
+			check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
 
 			/* All zeros means readahead info was bad */
 			if (!(len | check)) {
@@ -3901,8 +3888,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 							     doff);
 					if (bus->usebufpool) {
 						dhd_os_sdlock_rxq(bus->dhd);
-						pkt_buf_free_skb(bus->dhd->osh, pkt,
-							false);
+						pkt_buf_free_skb(pkt);
 						dhd_os_sdunlock_rxq(bus->dhd);
 					}
 					continue;
@@ -3965,8 +3951,8 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 #endif
 
 		/* Extract hardware header fields */
-		len = ltoh16_ua(bus->rxhdr);
-		check = ltoh16_ua(bus->rxhdr + sizeof(u16));
+		len = get_unaligned_le16(bus->rxhdr);
+		check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
 
 		/* All zeros means no more frames */
 		if (!(len | check)) {
@@ -4091,7 +4077,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 		}
 
 		dhd_os_sdlock_rxq(bus->dhd);
-		pkt = pkt_buf_get_skb(osh, (rdlen + firstread + DHD_SDALIGN));
+		pkt = pkt_buf_get_skb(rdlen + firstread + DHD_SDALIGN);
 		if (!pkt) {
 			/* Give up on data, request rtx of events */
 			DHD_ERROR(("%s: pkt_buf_get_skb failed: rdlen %d chan %d\n",
@@ -4108,7 +4094,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 		/* Leave room for what we already read, and align remainder */
 		ASSERT(firstread < pkt->len);
 		skb_pull(pkt, firstread);
-		PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
+		PKTALIGN(pkt, rdlen, DHD_SDALIGN);
 
 		/* Read the remaining frame data */
 		sdret =
@@ -4127,7 +4113,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 				       ? "data" : "test")),
 				   sdret));
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+			pkt_buf_free_skb(pkt);
 			dhd_os_sdunlock_rxq(bus->dhd);
 			bus->dhd->rx_errors++;
 			dhdsdio_rxfail(bus, true, RETRYCHAN(chan));
@@ -4136,7 +4122,7 @@ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 
 		/* Copy the already-read portion */
 		skb_push(pkt, firstread);
-		bcopy(bus->rxhdr, pkt->data, firstread);
+		memcpy(pkt->data, bus->rxhdr, firstread);
 
 #ifdef DHD_DEBUG
 		if (DHD_BYTES_ON() && DHD_DATA_ON())
@@ -4180,13 +4166,13 @@ deliver:
 
 		if (pkt->len == 0) {
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+			pkt_buf_free_skb(pkt);
 			dhd_os_sdunlock_rxq(bus->dhd);
 			continue;
 		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
 			DHD_ERROR(("%s: rx protocol error\n", __func__));
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+			pkt_buf_free_skb(pkt);
 			dhd_os_sdunlock_rxq(bus->dhd);
 			bus->dhd->rx_errors++;
 			continue;
@@ -4501,7 +4487,7 @@ clkwait:
 		if (ret == 0)
 			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
-		printf("Return_dpc value is : %d\n", ret);
+		DHD_INFO(("Return_dpc value is : %d\n", ret));
 		bus->ctrl_frame_stat = false;
 		dhd_wait_event_wakeup(bus->dhd);
 	}
@@ -4635,13 +4621,12 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 	u8 *data;
 	uint pktcount;
 	uint fillbyte;
-	struct osl_info *osh = bus->dhd->osh;
 	u16 len;
 
 	/* Display current count if appropriate */
 	if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
 		bus->pktgen_ptick = 0;
-		printf("%s: send attempts %d rcvd %d\n",
+		printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
 		       __func__, bus->pktgen_sent, bus->pktgen_rcvd);
 	}
 
@@ -4663,14 +4648,14 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 
 		/* Allocate an appropriate-sized packet */
 		len = bus->pktgen_len;
-		pkt = pkt_buf_get_skb(osh,
+		pkt = pkt_buf_get_skb(
 			(len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
 			true);
 		if (!pkt) {
 			DHD_ERROR(("%s: pkt_buf_get_skb failed!\n", __func__));
 			break;
 		}
-		PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
+		PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
 			 DHD_SDALIGN);
 		data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
 
@@ -4694,7 +4679,7 @@ static void dhdsdio_pktgen(dhd_bus_t *bus)
 		default:
 			DHD_ERROR(("Unrecognized pktgen mode %d\n",
 				   bus->pktgen_mode));
-			pkt_buf_free_skb(osh, pkt, true);
+			pkt_buf_free_skb(pkt, true);
 			bus->pktgen_count = 0;
 			return;
 		}
@@ -4740,16 +4725,15 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
 {
 	struct sk_buff *pkt;
 	u8 *data;
-	struct osl_info *osh = bus->dhd->osh;
 
 	/* Allocate the packet */
-	pkt = pkt_buf_get_skb(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN,
+	pkt = pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN,
 			true);
 	if (!pkt) {
 		DHD_ERROR(("%s: pkt_buf_get_skb failed!\n", __func__));
 		return;
 	}
-	PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
+	PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
 	data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
 
 	/* Fill in the test header */
@@ -4765,7 +4749,6 @@ static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start)
 
 static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 {
-	struct osl_info *osh = bus->dhd->osh;
 	u8 *data;
 	uint pktlen;
 
@@ -4779,7 +4762,7 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 	if (pktlen < SDPCM_TEST_HDRLEN) {
 		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n",
 			   pktlen));
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		return;
 	}
 
@@ -4797,7 +4780,7 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, "
 				"pktlen %d seq %d" " cmd %d extra %d len %d\n",
 				pktlen, seq, cmd, extra, len));
-			pkt_buf_free_skb(osh, pkt, false);
+			pkt_buf_free_skb(pkt, false);
 			return;
 		}
 	}
@@ -4812,14 +4795,14 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 			bus->pktgen_sent++;
 		} else {
 			bus->pktgen_fail++;
-			pkt_buf_free_skb(osh, pkt, false);
+			pkt_buf_free_skb(pkt, false);
 		}
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_ECHORSP:
 		if (bus->ext_loop) {
-			pkt_buf_free_skb(osh, pkt, false);
+			pkt_buf_free_skb(pkt, false);
 			bus->pktgen_rcvd++;
 			break;
 		}
@@ -4832,12 +4815,12 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 				break;
 			}
 		}
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_DISCARD:
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		bus->pktgen_rcvd++;
 		break;
 
@@ -4847,7 +4830,7 @@ static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, "
 			"pktlen %d seq %d" " cmd %d extra %d len %d\n",
 			pktlen, seq, cmd, extra, len));
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		break;
 	}
 
@@ -4987,7 +4970,7 @@ extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
 
 	/* Zero cbuf_index */
 	addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf_idx);
-	val = htol32(0);
+	val = cpu_to_le32(0);
 	rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
 	if (rv < 0)
 		goto done;
@@ -5000,7 +4983,7 @@ extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
 
 	/* Write length into vcons_in */
 	addr = bus->console_addr + offsetof(hndrte_cons_t, vcons_in);
-	val = htol32(msglen);
+	val = cpu_to_le32(msglen);
 	rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
 	if (rv < 0)
 		goto done;
@@ -5008,7 +4991,7 @@ extern int dhd_bus_console_in(dhd_pub_t *dhdp, unsigned char *msg, uint msglen)
 	/* Bump dongle by sending an empty event pkt.
 	 * sdpcm_sendup (RX) checks for virtual console input.
 	 */
-	pkt = pkt_buf_get_skb(bus->dhd->osh, 4 + SDPCM_RESERVE);
+	pkt = pkt_buf_get_skb(4 + SDPCM_RESERVE);
 	if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
 		dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
 
@@ -5066,7 +5049,7 @@ static bool dhdsdio_chipmatch(u16 chipid)
 
 static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 			   u16 slot, u16 func, uint bustype, void *regsva,
-			   struct osl_info *osh, void *sdh)
+			   void *sdh)
 {
 	int ret;
 	dhd_bus_t *bus;
@@ -5085,7 +5068,6 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 	sd1idle = true;
 	dhd_readahead = true;
 	retrydata = false;
-	dhd_doflow = false;
 	dhd_dongle_memsize = 0;
 	dhd_txminmax = DHD_TXMINMAX;
 
@@ -5143,15 +5125,6 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 		return NULL;
 	}
 
-	if (osh == NULL) {
-		/* Ask the OS interface part for an OSL handle */
-		osh = dhd_osl_attach(sdh, DHD_BUS);
-		if (!osh) {
-			DHD_ERROR(("%s: osl_attach failed!\n", __func__));
-			return NULL;
-		}
-	}
-
 	/* Allocate private bus interface state */
 	bus = kzalloc(sizeof(dhd_bus_t), GFP_ATOMIC);
 	if (!bus) {
@@ -5166,25 +5139,25 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 					 else use locally malloced rxbuf */
 
 	/* attempt to attach to the dongle */
-	if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
+	if (!(dhdsdio_probe_attach(bus, sdh, regsva, devid))) {
 		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __func__));
 		goto fail;
 	}
 
 	/* Attach to the dhd/OS/network interface */
-	bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE);
+	bus->dhd = dhd_attach(bus, SDPCM_RESERVE);
 	if (!bus->dhd) {
 		DHD_ERROR(("%s: dhd_attach failed\n", __func__));
 		goto fail;
 	}
 
 	/* Allocate buffers */
-	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
+	if (!(dhdsdio_probe_malloc(bus, sdh))) {
 		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __func__));
 		goto fail;
 	}
 
-	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
+	if (!(dhdsdio_probe_init(bus, sdh))) {
 		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __func__));
 		goto fail;
 	}
@@ -5220,13 +5193,12 @@ static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 	return bus;
 
 fail:
-	dhdsdio_release(bus, osh);
+	dhdsdio_release(bus);
 	return NULL;
 }
 
 static bool
-dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
-			void *regsva, u16 devid)
+dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
 {
 	u8 clkctl = 0;
 	int err = 0;
@@ -5238,7 +5210,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
 		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __func__));
 
 #ifdef DHD_DEBUG
-	printf("F1 signature read @0x18000000=0x%4x\n",
+	printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
 	       bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
 
 #endif				/* DHD_DEBUG */
@@ -5279,13 +5251,12 @@ dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
 		udelay(65);
 
 		for (fn = 0; fn <= numfn; fn++) {
-			cis[fn] = kmalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
+			cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
 			if (!cis[fn]) {
 				DHD_INFO(("dhdsdio_probe: fn %d cis malloc "
 					"failed\n", fn));
 				break;
 			}
-			memset(cis[fn], 0, SBSDIO_CIS_SIZE_LIMIT);
 
 			err = bcmsdh_cis_read(sdh, fn, cis[fn],
 						SBSDIO_CIS_SIZE_LIMIT);
@@ -5311,7 +5282,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
 #endif				/* DHD_DEBUG */
 
 	/* si_attach() will provide an SI handle and scan the backplane */
-	bus->sih = si_attach((uint) devid, osh, regsva, DHD_BUS, sdh,
+	bus->sih = si_attach((uint) devid, regsva, DHD_BUS, sdh,
 				   &bus->vars, &bus->varsz);
 	if (!(bus->sih)) {
 		DHD_ERROR(("%s: si_attach failed!\n", __func__));
@@ -5326,7 +5297,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
 		goto fail;
 	}
 
-	si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
+	si_sdiod_drive_strength_init(bus->sih, dhd_sdiod_drive_strength);
 
 	/* Get info on the ARM and SOCRAM cores... */
 	if (!DHD_NOPMU(bus)) {
@@ -5364,9 +5335,9 @@ dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
 	bus->sdpcmrev = si_corerev(bus->sih);
 
 	/* Set core control so an SDIO reset does a backplane reset */
-	OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
+	OR_REG(&bus->regs->corecontrol, CC_BPRESEN);
 
-	pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
+	pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
 
 	/* Locate an appropriately-aligned portion of hdrbuf */
 	bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], DHD_SDALIGN);
@@ -5383,8 +5354,7 @@ fail:
 	return false;
 }
 
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, struct osl_info *osh,
-				 void *sdh)
+static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -5425,7 +5395,7 @@ fail:
 	return false;
 }
 
-static bool dhdsdio_probe_init(dhd_bus_t *bus, struct osl_info *osh, void *sdh)
+static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh)
 {
 	s32 fnum;
 
@@ -5502,20 +5472,19 @@ static bool dhdsdio_probe_init(dhd_bus_t *bus, struct osl_info *osh, void *sdh)
 }
 
 bool
-dhd_bus_download_firmware(struct dhd_bus *bus, struct osl_info *osh,
-			  char *fw_path, char *nv_path)
+dhd_bus_download_firmware(struct dhd_bus *bus, char *fw_path, char *nv_path)
 {
 	bool ret;
 	bus->fw_path = fw_path;
 	bus->nv_path = nv_path;
 
-	ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
+	ret = dhdsdio_download_firmware(bus, bus->sdh);
 
 	return ret;
 }
 
 static bool
-dhdsdio_download_firmware(struct dhd_bus *bus, struct osl_info *osh, void *sdh)
+dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh)
 {
 	bool ret;
 
@@ -5530,37 +5499,32 @@ dhdsdio_download_firmware(struct dhd_bus *bus, struct osl_info *osh, void *sdh)
 }
 
 /* Detach and free everything */
-static void dhdsdio_release(dhd_bus_t *bus, struct osl_info *osh)
+static void dhdsdio_release(dhd_bus_t *bus)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
 	if (bus) {
-		ASSERT(osh);
-
 		/* De-register interrupt handler */
 		bcmsdh_intr_disable(bus->sdh);
 		bcmsdh_intr_dereg(bus->sdh);
 
 		if (bus->dhd) {
 
-			dhdsdio_release_dongle(bus, osh);
+			dhdsdio_release_dongle(bus);
 
 			dhd_detach(bus->dhd);
 			bus->dhd = NULL;
 		}
 
-		dhdsdio_release_malloc(bus, osh);
+		dhdsdio_release_malloc(bus);
 
 		kfree(bus);
 	}
 
-	if (osh)
-		dhd_osl_detach(osh);
-
 	DHD_TRACE(("%s: Disconnected\n", __func__));
 }
 
-static void dhdsdio_release_malloc(dhd_bus_t *bus, struct osl_info *osh)
+static void dhdsdio_release_malloc(dhd_bus_t *bus)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -5573,13 +5537,11 @@ static void dhdsdio_release_malloc(dhd_bus_t *bus, struct osl_info *osh)
 		bus->rxlen = 0;
 	}
 
-	if (bus->databuf) {
-		kfree(bus->databuf);
-		bus->databuf = NULL;
-	}
+	kfree(bus->databuf);
+	bus->databuf = NULL;
 }
 
-static void dhdsdio_release_dongle(dhd_bus_t *bus, struct osl_info *osh)
+static void dhdsdio_release_dongle(dhd_bus_t *bus)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -5609,7 +5571,7 @@ static void dhdsdio_disconnect(void *ptr)
 
 	if (bus) {
 		ASSERT(bus->dhd);
-		dhdsdio_release(bus, bus->dhd->osh);
+		dhdsdio_release(bus);
 	}
 
 	DHD_TRACE(("%s: Disconnected\n", __func__));
@@ -5679,6 +5641,10 @@ static int dhdsdio_download_code_array(struct dhd_bus *bus)
 		unsigned char *ularray;
 
 		ularray = kmalloc(bus->ramsize, GFP_ATOMIC);
+		if (!ularray) {
+			bcmerror = BCME_NOMEM;
+			goto err;
+		}
 		/* Upload image to verify downloaded contents. */
 		offset = 0;
 		memset(ularray, 0xaa, bus->ramsize);
@@ -5690,7 +5656,7 @@ static int dhdsdio_download_code_array(struct dhd_bus *bus)
 				DHD_ERROR(("%s: error %d on reading %d membytes"
 					" at 0x%08x\n",
 					__func__, bcmerror, MEMBLOCK, offset));
-				goto err;
+				goto free;
 			}
 
 			offset += MEMBLOCK;
@@ -5704,7 +5670,7 @@ static int dhdsdio_download_code_array(struct dhd_bus *bus)
 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
 				__func__, bcmerror,
 				sizeof(dlarray) - offset, offset));
-				goto err;
+				goto free;
 			}
 		}
 
@@ -5712,11 +5678,11 @@ static int dhdsdio_download_code_array(struct dhd_bus *bus)
 			DHD_ERROR(("%s: Downloaded image is corrupted.\n",
 				   __func__));
 			ASSERT(0);
-			goto err;
+			goto free;
 		} else
 			DHD_ERROR(("%s: Download/Upload/Compare succeeded.\n",
 				__func__));
-
+free:
 		kfree(ularray);
 	}
 #endif				/* DHD_DEBUG */
@@ -5764,8 +5730,7 @@ static int dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path)
 	}
 
 err:
-	if (memblock)
-		kfree(memblock);
+	kfree(memblock);
 
 	if (image)
 		dhd_os_close_image(image);
@@ -5904,8 +5869,7 @@ static int dhdsdio_download_nvram(struct dhd_bus *bus)
 	}
 
 err:
-	if (memblock)
-		kfree(memblock);
+	kfree(memblock);
 
 	if (image)
 		dhd_os_close_image(image);
@@ -6051,7 +6015,7 @@ int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag)
 
 			/* Clean tx/rx buffer pointers,
 			 detach from the dongle */
-			dhdsdio_release_dongle(bus, bus->dhd->osh);
+			dhdsdio_release_dongle(bus);
 
 			bus->dhd->dongle_reset = true;
 			bus->dhd->up = false;
@@ -6071,14 +6035,13 @@ int dhd_bus_devreset(dhd_pub_t *dhdp, u8 flag)
 			bcmsdh_reset(bus->sdh);
 
 			/* Attempt to re-attach & download */
-			if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
+			if (dhdsdio_probe_attach(bus, bus->sdh,
 						 (u32 *) SI_ENUM_BASE,
 						 bus->cl_devid)) {
 				/* Attempt to download binary to the dongle */
 				if (dhdsdio_probe_init
-				    (bus, bus->dhd->osh, bus->sdh)
+				    (bus, bus->sdh)
 				    && dhdsdio_download_firmware(bus,
-								 bus->dhd->osh,
 								 bus->sdh)) {
 
 					/* Re-init bus, enable F2 transfer */
diff --git a/drivers/staging/brcm80211/brcmfmac/dhdioctl.h b/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
new file mode 100644
index 0000000..f0ba535
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _dhdioctl_h_
+#define	_dhdioctl_h_
+
+/* Linux network driver ioctl encoding */
+typedef struct dhd_ioctl {
+	uint cmd;		/* common ioctl definition */
+	void *buf;		/* pointer to user buffer */
+	uint len;		/* length of user buffer */
+	bool set;		/* get or set request (optional) */
+	uint used;		/* bytes read or written (optional) */
+	uint needed;		/* bytes needed (optional) */
+	uint driver;		/* to identify target driver */
+} dhd_ioctl_t;
+
+/* per-driver magic numbers */
+#define DHD_IOCTL_MAGIC		0x00444944
+
+/* bump this number if you change the ioctl interface */
+#define DHD_IOCTL_VERSION	1
+
+#define	DHD_IOCTL_MAXLEN	8192	/* max length ioctl buffer required */
+#define	DHD_IOCTL_SMLEN	256	/* "small" length ioctl buffer required */
+
+/* common ioctl definitions */
+#define DHD_GET_MAGIC				0
+#define DHD_GET_VERSION				1
+#define DHD_GET_VAR				2
+#define DHD_SET_VAR				3
+
+/* message levels */
+#define DHD_ERROR_VAL	0x0001
+#define DHD_TRACE_VAL	0x0002
+#define DHD_INFO_VAL	0x0004
+#define DHD_DATA_VAL	0x0008
+#define DHD_CTL_VAL	0x0010
+#define DHD_TIMER_VAL	0x0020
+#define DHD_HDRS_VAL	0x0040
+#define DHD_BYTES_VAL	0x0080
+#define DHD_INTR_VAL	0x0100
+#define DHD_LOG_VAL	0x0200
+#define DHD_GLOM_VAL	0x0400
+#define DHD_EVENT_VAL	0x0800
+#define DHD_BTA_VAL	0x1000
+#define DHD_ISCAN_VAL 0x2000
+
+#ifdef SDTEST
+/* For pktgen iovar */
+typedef struct dhd_pktgen {
+	uint version;		/* To allow structure change tracking */
+	uint freq;		/* Max ticks between tx/rx attempts */
+	uint count;		/* Test packets to send/rcv each attempt */
+	uint print;		/* Print counts every <print> attempts */
+	uint total;		/* Total packets (or bursts) */
+	uint minlen;		/* Minimum length of packets to send */
+	uint maxlen;		/* Maximum length of packets to send */
+	uint numsent;		/* Count of test packets sent */
+	uint numrcvd;		/* Count of test packets received */
+	uint numfail;		/* Count of test send failures */
+	uint mode;		/* Test mode (type of test packets) */
+	uint stop;		/* Stop after this many tx failures */
+} dhd_pktgen_t;
+
+/* Version in case structure changes */
+#define DHD_PKTGEN_VERSION 2
+
+/* Type of test packets to use */
+#define DHD_PKTGEN_ECHO		1	/* Send echo requests */
+#define DHD_PKTGEN_SEND		2	/* Send discard packets */
+#define DHD_PKTGEN_RXBURST	3	/* Request dongle send N packets */
+#define DHD_PKTGEN_RECV		4	/* Continuous rx from continuous
+					 tx dongle */
+#endif				/* SDTEST */
+
+/* Enter idle immediately (no timeout) */
+#define DHD_IDLE_IMMEDIATE	(-1)
+
+/* Values for idleclock iovar: other values are the sd_divisor to use
+	 when idle */
+#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change
+				 when idle */
+#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped
+				 (and use SD1 mode) */
+
+#endif				/* _dhdioctl_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/hndpmu.c b/drivers/staging/brcm80211/brcmfmac/hndpmu.c
new file mode 100644
index 0000000..e841da6
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/hndpmu.c
@@ -0,0 +1 @@
+#include "../util/hndpmu.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h b/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
new file mode 100644
index 0000000..28f092c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_hndrte_armtrap_h
+#define	_hndrte_armtrap_h
+
+/* ARM trap handling */
+
+/* Trap types defined by ARM (see arminc.h) */
+
+/* Trap locations in lo memory */
+#define	TRAP_STRIDE	4
+#define FIRST_TRAP	TR_RST
+#define LAST_TRAP	(TR_FIQ * TRAP_STRIDE)
+
+#if defined(__ARM_ARCH_4T__)
+#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
+#elif defined(__ARM_ARCH_7M__)
+#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
+#endif				/* __ARM_ARCH_7M__ */
+
+/* The trap structure is defined here as offsets for assembly */
+#define	TR_TYPE		0x00
+#define	TR_EPC		0x04
+#define	TR_CPSR		0x08
+#define	TR_SPSR		0x0c
+#define	TR_REGS		0x10
+#define	TR_REG(n)	(TR_REGS + (n) * 4)
+#define	TR_SP		TR_REG(13)
+#define	TR_LR		TR_REG(14)
+#define	TR_PC		TR_REG(15)
+
+#define	TRAP_T_SIZE	80
+
+#ifndef	_LANGUAGE_ASSEMBLY
+
+typedef struct _trap_struct {
+	u32 type;
+	u32 epc;
+	u32 cpsr;
+	u32 spsr;
+	u32 r0;
+	u32 r1;
+	u32 r2;
+	u32 r3;
+	u32 r4;
+	u32 r5;
+	u32 r6;
+	u32 r7;
+	u32 r8;
+	u32 r9;
+	u32 r10;
+	u32 r11;
+	u32 r12;
+	u32 r13;
+	u32 r14;
+	u32 pc;
+} trap_t;
+
+#endif				/* !_LANGUAGE_ASSEMBLY */
+
+#endif				/* _hndrte_armtrap_h */
diff --git a/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h b/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
new file mode 100644
index 0000000..4df3eec
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _hndrte_cons_h
+#define _hndrte_cons_h
+
+#define CBUF_LEN	(128)
+
+#define LOG_BUF_LEN	1024
+
+typedef struct {
+	u32 buf;		/* Can't be pointer on (64-bit) hosts */
+	uint buf_size;
+	uint idx;
+	char *_buf_compat;	/* Redundant pointer for backward compat. */
+} hndrte_log_t;
+
+typedef struct {
+	/* Virtual UART
+	 * When there is no UART (e.g. Quickturn),
+	 * the host should write a complete
+	 * input line directly into cbuf and then write
+	 * the length into vcons_in.
+	 * This may also be used when there is a real UART
+	 * (at risk of conflicting with
+	 * the real UART).  vcons_out is currently unused.
+	 */
+	volatile uint vcons_in;
+	volatile uint vcons_out;
+
+	/* Output (logging) buffer
+	 * Console output is written to a ring buffer log_buf at index log_idx.
+	 * The host may read the output when it sees log_idx advance.
+	 * Output will be lost if the output wraps around faster than the host
+	 * polls.
+	 */
+	hndrte_log_t log;
+
+	/* Console input line buffer
+	 * Characters are read one at a time into cbuf
+	 * until <CR> is received, then
+	 * the buffer is processed as a command line.
+	 * Also used for virtual UART.
+	 */
+	uint cbuf_idx;
+	char cbuf[CBUF_LEN];
+} hndrte_cons_t;
+
+#endif /* _hndrte_cons_h */
+
diff --git a/drivers/staging/brcm80211/brcmfmac/msgtrace.h b/drivers/staging/brcm80211/brcmfmac/msgtrace.h
new file mode 100644
index 0000000..d654671
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/msgtrace.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_MSGTRACE_H
+#define	_MSGTRACE_H
+
+#define MSGTRACE_VERSION 1
+
+/* Message trace header */
+typedef struct msgtrace_hdr {
+	u8 version;
+	u8 spare;
+	u16 len;		/* Len of the trace */
+	u32 seqnum;		/* Sequence number of message. Useful
+				 * if the messsage has been lost
+				 * because of DMA error or a bus reset
+				 * (ex: SDIO Func2)
+				 */
+	u32 discarded_bytes;	/* Number of discarded bytes because of
+				 trace overflow  */
+	u32 discarded_printf;	/* Number of discarded printf
+				 because of trace overflow */
+} __attribute__((packed)) msgtrace_hdr_t;
+
+#define MSGTRACE_HDRLEN		sizeof(msgtrace_hdr_t)
+
+/* The hbus driver generates traces when sending a trace message.
+ * This causes endless traces.
+ * This flag must be set to true in any hbus traces.
+ * The flag is reset in the function msgtrace_put.
+ * This prevents endless traces but generates hasardous
+ * lost of traces only in bus device code.
+ * It is recommendat to set this flag in macro SD_TRACE
+ * but not in SD_ERROR for avoiding missing
+ * hbus error traces. hbus error trace should not generates endless traces.
+ */
+extern bool msgtrace_hbus_trace;
+
+typedef void (*msgtrace_func_send_t) (void *hdl1, void *hdl2, u8 *hdr,
+				      u16 hdrlen, u8 *buf,
+				      u16 buflen);
+
+extern void msgtrace_sent(void);
+extern void msgtrace_put(char *buf, int count);
+extern void msgtrace_init(void *hdl1, void *hdl2,
+			  msgtrace_func_send_t func_send);
+
+#endif				/* _MSGTRACE_H */
diff --git a/drivers/staging/brcm80211/brcmfmac/sbutils.c b/drivers/staging/brcm80211/brcmfmac/sbutils.c
new file mode 100644
index 0000000..64496b8
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/sbutils.c
@@ -0,0 +1 @@
+#include "../util/sbutils.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/sdioh.h b/drivers/staging/brcm80211/brcmfmac/sdioh.h
new file mode 100644
index 0000000..f96aaf9
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/sdioh.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_SDIOH_H
+#define	_SDIOH_H
+
+#define SD_SysAddr			0x000
+#define SD_BlockSize			0x004
+#define SD_BlockCount 			0x006
+#define SD_Arg0				0x008
+#define SD_Arg1 			0x00A
+#define SD_TransferMode			0x00C
+#define SD_Command 			0x00E
+#define SD_Response0			0x010
+#define SD_Response1 			0x012
+#define SD_Response2			0x014
+#define SD_Response3 			0x016
+#define SD_Response4			0x018
+#define SD_Response5 			0x01A
+#define SD_Response6			0x01C
+#define SD_Response7 			0x01E
+#define SD_BufferDataPort0		0x020
+#define SD_BufferDataPort1 		0x022
+#define SD_PresentState			0x024
+#define SD_HostCntrl			0x028
+#define SD_PwrCntrl			0x029
+#define SD_BlockGapCntrl 		0x02A
+#define SD_WakeupCntrl 			0x02B
+#define SD_ClockCntrl			0x02C
+#define SD_TimeoutCntrl 		0x02E
+#define SD_SoftwareReset		0x02F
+#define SD_IntrStatus			0x030
+#define SD_ErrorIntrStatus 		0x032
+#define SD_IntrStatusEnable		0x034
+#define SD_ErrorIntrStatusEnable 	0x036
+#define SD_IntrSignalEnable		0x038
+#define SD_ErrorIntrSignalEnable 	0x03A
+#define SD_CMD12ErrorStatus		0x03C
+#define SD_Capabilities			0x040
+#define SD_Capabilities_Reserved	0x044
+#define SD_MaxCurCap			0x048
+#define SD_MaxCurCap_Reserved		0x04C
+#define SD_ADMA_SysAddr			0x58
+#define SD_SlotInterruptStatus		0x0FC
+#define SD_HostControllerVersion 	0x0FE
+
+/* SD specific registers in PCI config space */
+#define SD_SlotInfo	0x40
+
+#endif				/* _SDIOH_H */
diff --git a/drivers/staging/brcm80211/brcmfmac/sdiovar.h b/drivers/staging/brcm80211/brcmfmac/sdiovar.h
new file mode 100644
index 0000000..d1cfa5f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/sdiovar.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _sdiovar_h_
+#define _sdiovar_h_
+
+typedef struct sdreg {
+	int func;
+	int offset;
+	int value;
+} sdreg_t;
+
+/* Common msglevel constants */
+#define SDH_ERROR_VAL		0x0001	/* Error */
+#define SDH_TRACE_VAL		0x0002	/* Trace */
+#define SDH_INFO_VAL		0x0004	/* Info */
+#define SDH_DEBUG_VAL		0x0008	/* Debug */
+#define SDH_DATA_VAL		0x0010	/* Data */
+#define SDH_CTRL_VAL		0x0020	/* Control Regs */
+#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
+#define SDH_DMA_VAL		0x0080	/* DMA */
+
+#define NUM_PREV_TRANSACTIONS	16
+
+#endif				/* _sdiovar_h_ */
diff --git a/drivers/staging/brcm80211/brcmfmac/siutils.c b/drivers/staging/brcm80211/brcmfmac/siutils.c
new file mode 100644
index 0000000..f428e99
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmfmac/siutils.c
@@ -0,0 +1 @@
+#include "../util/siutils.c"
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
index 991463f..555b056 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
@@ -16,11 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
-#include <osl.h>
 
 #include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
 
 #include <asm/uaccess.h>
 
@@ -44,6 +41,7 @@
 
 static struct sdio_func *cfg80211_sdio_func;
 static struct wl_dev *wl_cfg80211_dev;
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
 
 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
 
@@ -87,8 +85,8 @@ static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 				      s32 dbm);
 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-					    struct net_device *dev,
-					    u8 key_idx);
+					  struct net_device *dev, u8 key_idx,
+					  bool unicast, bool multicast);
 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 				 u8 key_idx, bool pairwise, const u8 *mac_addr,
 				 struct key_params *params);
@@ -555,24 +553,24 @@ static const u32 __wl_cipher_suites[] = {
 
 static void swap_key_from_BE(struct wl_wsec_key *key)
 {
-	key->index = htod32(key->index);
-	key->len = htod32(key->len);
-	key->algo = htod32(key->algo);
-	key->flags = htod32(key->flags);
-	key->rxiv.hi = htod32(key->rxiv.hi);
-	key->rxiv.lo = htod16(key->rxiv.lo);
-	key->iv_initialized = htod32(key->iv_initialized);
+	key->index = cpu_to_le32(key->index);
+	key->len = cpu_to_le32(key->len);
+	key->algo = cpu_to_le32(key->algo);
+	key->flags = cpu_to_le32(key->flags);
+	key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+	key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+	key->iv_initialized = cpu_to_le32(key->iv_initialized);
 }
 
 static void swap_key_to_BE(struct wl_wsec_key *key)
 {
-	key->index = dtoh32(key->index);
-	key->len = dtoh32(key->len);
-	key->algo = dtoh32(key->algo);
-	key->flags = dtoh32(key->flags);
-	key->rxiv.hi = dtoh32(key->rxiv.hi);
-	key->rxiv.lo = dtoh16(key->rxiv.lo);
-	key->iv_initialized = dtoh32(key->iv_initialized);
+	key->index = le32_to_cpu(key->index);
+	key->len = le32_to_cpu(key->len);
+	key->algo = le32_to_cpu(key->algo);
+	key->flags = le32_to_cpu(key->flags);
+	key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
+	key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
+	key->iv_initialized = le32_to_cpu(key->iv_initialized);
 }
 
 static s32
@@ -626,8 +624,8 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 	default:
 		return -EINVAL;
 	}
-	infra = htod32(infra);
-	ap = htod32(ap);
+	infra = cpu_to_le32(infra);
+	ap = cpu_to_le32(ap);
 	wdev = ndev->ieee80211_ptr;
 	wdev->iftype = type;
 	WL_DBG("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra);
@@ -648,7 +646,7 @@ wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
 
 static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
 {
-	memcpy(&params->bssid, &ether_bcast, ETH_ALEN);
+	memcpy(params->bssid, ether_bcast, ETH_ALEN);
 	params->bss_type = DOT11_BSSTYPE_ANY;
 	params->scan_type = 0;
 	params->nprobes = -1;
@@ -657,10 +655,10 @@ static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
 	params->home_time = -1;
 	params->channel_num = 0;
 
-	params->nprobes = htod32(params->nprobes);
-	params->active_time = htod32(params->active_time);
-	params->passive_time = htod32(params->passive_time);
-	params->home_time = htod32(params->home_time);
+	params->nprobes = cpu_to_le32(params->nprobes);
+	params->active_time = cpu_to_le32(params->active_time);
+	params->passive_time = cpu_to_le32(params->passive_time);
+	params->home_time = cpu_to_le32(params->home_time);
 	if (ssid && ssid->SSID_len)
 		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
 
@@ -673,7 +671,7 @@ wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
 	s32 iolen;
 
 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(unlikely(!iolen));
+	BUG_ON(!iolen);
 
 	return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
 }
@@ -685,7 +683,7 @@ wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
 	s32 iolen;
 
 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(unlikely(!iolen));
+	BUG_ON(!iolen);
 
 	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
 }
@@ -703,14 +701,13 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
 	params = kzalloc(params_size, GFP_KERNEL);
 	if (unlikely(!params))
 		return -ENOMEM;
-	memset(params, 0, params_size);
-	BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
+	BUG_ON(params_size >= WLC_IOCTL_SMLEN);
 
 	wl_iscan_prep(&params->params, ssid);
 
-	params->version = htod32(ISCAN_REQ_VERSION);
-	params->action = htod16(action);
-	params->scan_duration = htod16(0);
+	params->version = cpu_to_le32(ISCAN_REQ_VERSION);
+	params->action = cpu_to_le16(action);
+	params->scan_duration = cpu_to_le16(0);
 
 	/* params_size += offsetof(wl_iscan_params_t, params); */
 	err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
@@ -813,7 +810,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 			    min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
 		if (sr->ssid.SSID_len) {
 			memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
-			sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
+			sr->ssid.SSID_len = cpu_to_le32(sr->ssid.SSID_len);
 			WL_DBG("Specific scan ssid=\"%s\" len=%d\n",
 			       sr->ssid.SSID, sr->ssid.SSID_len);
 			spec_scan = true;
@@ -873,9 +870,9 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
 	u32 len;
 	s32 err = 0;
 
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
-	BUG_ON(unlikely(!len));
+	BUG_ON(!len);
 
 	err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
 	if (unlikely(err)) {
@@ -899,12 +896,12 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
 	len =
 	    bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
 			sizeof(var.buf));
-	BUG_ON(unlikely(!len));
+	BUG_ON(!len);
 	err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 	}
-	*retval = dtoh32(var.val);
+	*retval = le32_to_cpu(var.val);
 
 	return err;
 }
@@ -938,7 +935,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
 	s32 err = 0;
 	u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
 
-	retry = htod32(retry);
+	retry = cpu_to_le32(retry);
 	err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
 	if (unlikely(err)) {
 		WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
@@ -1041,7 +1038,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 	memset(&join_params, 0, sizeof(join_params));
 	memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
 	       params->ssid_len);
-	join_params.ssid.SSID_len = htod32(params->ssid_len);
+	join_params.ssid.SSID_len = cpu_to_le32(params->ssid_len);
 	if (params->bssid)
 		memcpy(&join_params.params.bssid, params->bssid,
 		       ETH_ALEN);
@@ -1371,12 +1368,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 
 	join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
 	memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+	join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
 	wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
-	memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
+	memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
 
 	wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
-	WL_DBG("join_param_size %d\n", join_params_size);
+	WL_DBG("join_param_size %zu\n", join_params_size);
 
 	if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
 		WL_DBG("ssid \"%s\", len (%d)\n",
@@ -1407,7 +1404,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 	if (likely(act)) {
 		scbval.val = reason_code;
 		memcpy(&scbval.ea, &wl->bssid, ETH_ALEN);
-		scbval.val = htod32(scbval.val);
+		scbval.val = cpu_to_le32(scbval.val);
 		err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
 				sizeof(scb_val_t));
 		if (unlikely(err)) {
@@ -1449,7 +1446,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 	}
 	/* Make sure radio is off or on as far as software is concerned */
 	disable = WL_RADIO_SW_DISABLE << 16;
-	disable = htod32(disable);
+	disable = cpu_to_le32(disable);
 	err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_RADIO error (%d)\n", err);
@@ -1493,7 +1490,7 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
 
 static s32
 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
-			       u8 key_idx)
+			       u8 key_idx, bool unicast, bool multicast)
 {
 	u32 index;
 	s32 wsec;
@@ -1507,11 +1504,11 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		return err;
 	}
-	wsec = dtoh32(wsec);
+	wsec = le32_to_cpu(wsec);
 	if (wsec & WEP_ENABLED) {
 		/* Just select a new current key */
 		index = (u32) key_idx;
-		index = htod32(index);
+		index = cpu_to_le32(index);
 		err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
 				sizeof(index));
 		if (unlikely(err)) {
@@ -1684,7 +1681,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	val = 1;		/* assume shared key. otherwise 0 */
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
@@ -1740,7 +1737,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	val = 0;		/* assume open key. otherwise 1 */
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
@@ -1768,7 +1765,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 	key.index = key_idx;
 	swap_key_to_BE(&key);
 	memset(&params, 0, sizeof(params));
-	params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
+	params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
 	memcpy(params.key, key.data, params.key_len);
 
 	err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
@@ -1776,7 +1773,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		return err;
 	}
-	wsec = dtoh32(wsec);
+	wsec = le32_to_cpu(wsec);
 	switch (wsec) {
 	case WEP_ENABLED:
 		sec = wl_read_prof(wl, WL_PROF_SEC);
@@ -1836,7 +1833,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 	if (err) {
 		WL_ERR("Could not get rate (%d)\n", err);
 	} else {
-		rate = dtoh32(rate);
+		rate = le32_to_cpu(rate);
 		sinfo->filled |= STATION_INFO_TX_BITRATE;
 		sinfo->txrate.legacy = rate * 5;
 		WL_DBG("Rate %d Mbps\n", rate / 2);
@@ -1850,7 +1847,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 			WL_ERR("Could not get rssi (%d)\n", err);
 			return err;
 		}
-		rssi = dtoh32(scb_val.val);
+		rssi = le32_to_cpu(scb_val.val);
 		sinfo->filled |= STATION_INFO_SIGNAL;
 		sinfo->signal = rssi;
 		WL_DBG("RSSI %d dBm\n", rssi);
@@ -1868,7 +1865,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 
 	CHECK_SYS_UP();
 	pm = enabled ? PM_FAST : PM_OFF;
-	pm = htod32(pm);
+	pm = cpu_to_le32(pm);
 	WL_DBG("power save %s\n", (pm ? "enabled" : "disabled"));
 	err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
 	if (unlikely(err)) {
@@ -1931,7 +1928,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 		return err;
 	}
 
-	rateset.count = dtoh32(rateset.count);
+	rateset.count = le32_to_cpu(rateset.count);
 
 	legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
 	if (!legacy)
@@ -1980,8 +1977,6 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
 	struct net_device *ndev = wl_to_ndev(wl);
 	s32 err = 0;
 
-	CHECK_SYS_UP();
-
 	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
 	wl_term_iscan(wl);
 	if (wl->scan_request) {
@@ -2005,8 +2000,8 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
 	WL_DBG("No of elements %d\n", pmk_list->pmkids.npmkid);
 	for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
 		WL_DBG("PMKID[%d]: %pM =\n", i,
-		       &pmk_list->pmkids.pmkid[i].BSSID);
-		for (j = 0; j < WPA2_PMKID_LEN; j++) {
+			&pmk_list->pmkids.pmkid[i].BSSID);
+		for (j = 0; j < WLAN_PMKID_LEN; j++) {
 			WL_DBG("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
 		}
 	}
@@ -2035,7 +2030,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
 		memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
 		       ETH_ALEN);
 		memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
-		       WPA2_PMKID_LEN);
+		       WLAN_PMKID_LEN);
 		if (i == wl->pmk_list->pmkids.npmkid)
 			wl->pmk_list->pmkids.npmkid++;
 	} else {
@@ -2043,7 +2038,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
 	}
 	WL_DBG("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
 	       &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID);
-	for (i = 0; i < WPA2_PMKID_LEN; i++) {
+	for (i = 0; i < WLAN_PMKID_LEN; i++) {
 		WL_DBG("%02x\n",
 		       wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
 		       PMKID[i]);
@@ -2065,11 +2060,11 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 
 	CHECK_SYS_UP();
 	memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
-	memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+	memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
 
 	WL_DBG("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
 	       &pmkid.pmkid[0].BSSID);
-	for (i = 0; i < WPA2_PMKID_LEN; i++) {
+	for (i = 0; i < WLAN_PMKID_LEN; i++) {
 		WL_DBG("%02x\n", pmkid.pmkid[0].PMKID[i]);
 	}
 
@@ -2088,7 +2083,7 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 			       ETH_ALEN);
 			memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
 			       &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
-			       WPA2_PMKID_LEN);
+			       WLAN_PMKID_LEN);
 		}
 		wl->pmk_list->pmkids.npmkid--;
 	} else {
@@ -2264,7 +2259,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 	u32 freq;
 	s32 err = 0;
 
-	if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
+	if (unlikely(le32_to_cpu(bi->length) > WL_BSS_INFO_MAX)) {
 		WL_DBG("Beacon is larger than buffer. Discarding\n");
 		return err;
 	}
@@ -2313,7 +2308,9 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 	notif_bss_info->frame_len =
 	    offsetof(struct ieee80211_mgmt,
 		     u.beacon.variable) + wl_get_ielen(wl);
-	freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+	freq = ieee80211_channel_to_frequency(notif_bss_info->channel,
+					      band->band);
+
 	channel = ieee80211_get_channel(wiphy, freq);
 
 	WL_DBG("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
@@ -2337,8 +2334,8 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 
 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
+	u32 event = be32_to_cpu(e->event_type);
+	u16 flags = be16_to_cpu(e->flags);
 
 	if (event == WLC_E_LINK) {
 		if (flags & WLC_EVENT_MSG_LINK) {
@@ -2356,8 +2353,8 @@ static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
 
 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
+	u32 event = be32_to_cpu(e->event_type);
+	u16 flags = be16_to_cpu(e->flags);
 
 	if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
 		return true;
@@ -2371,8 +2368,8 @@ static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
 
 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-	u32 event = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
+	u32 event = be32_to_cpu(e->event_type);
+	u32 status = be32_to_cpu(e->status);
 
 	if (event == WLC_E_SET_SSID || event == WLC_E_LINK) {
 		if (status == WLC_E_STATUS_NO_NETWORKS)
@@ -2436,7 +2433,7 @@ wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
 	u32 buflen;
 
 	buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
-	BUG_ON(unlikely(!buflen));
+	BUG_ON(!buflen);
 
 	return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
 }
@@ -2450,7 +2447,7 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
 	s32 err = 0;
 
 	len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
-	BUG_ON(unlikely(!len));
+	BUG_ON(!len);
 	err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
 			WL_IOCTL_LEN_MAX);
 	if (unlikely(err)) {
@@ -2537,10 +2534,10 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
 		join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
 		join_params->params.chanspec_list[0] |= chanspec;
 		join_params->params.chanspec_list[0] =
-		htodchanspec(join_params->params.chanspec_list[0]);
+		cpu_to_le16(join_params->params.chanspec_list[0]);
 
 		join_params->params.chanspec_num =
-			htod32(join_params->params.chanspec_num);
+			cpu_to_le32(join_params->params.chanspec_num);
 
 		WL_DBG("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
 		       join_params->params.chanspec_list[0], ch, chanspec);
@@ -2571,7 +2568,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl)
 	rtnl_lock();
 	if (unlikely(!bss)) {
 		WL_DBG("Could not find the AP\n");
-		*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+		*(u32 *) wl->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
 		err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
 				wl->extra_buf, WL_EXTRA_BUF_MAX);
 		if (unlikely(err)) {
@@ -2682,7 +2679,7 @@ static s32
 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
 		     const wl_event_msg_t *e, void *data)
 {
-	u16 flags = ntoh16(e->flags);
+	u16 flags = be16_to_cpu(e->flags);
 	enum nl80211_key_type key_type;
 
 	rtnl_lock();
@@ -2723,7 +2720,7 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 		WL_ERR("scan busy (%d)\n", err);
 		goto scan_done_out;
 	}
-	channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+	channel_inform.scan_channel = le32_to_cpu(channel_inform.scan_channel);
 	if (unlikely(channel_inform.scan_channel)) {
 
 		WL_DBG("channel_inform.scan_channel (%d)\n",
@@ -2732,16 +2729,16 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 	wl->bss_list = wl->scan_results;
 	bss_list = wl->bss_list;
 	memset(bss_list, 0, len);
-	bss_list->buflen = htod32(len);
+	bss_list->buflen = cpu_to_le32(len);
 	err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
 	if (unlikely(err)) {
 		WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
 		err = -EINVAL;
 		goto scan_done_out;
 	}
-	bss_list->buflen = dtoh32(bss_list->buflen);
-	bss_list->version = dtoh32(bss_list->version);
-	bss_list->count = dtoh32(bss_list->count);
+	bss_list->buflen = le32_to_cpu(bss_list->buflen);
+	bss_list->version = le32_to_cpu(bss_list->version);
+	bss_list->count = le32_to_cpu(bss_list->count);
 
 	err = wl_inform_bss(wl);
 	if (err)
@@ -2950,7 +2947,7 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
+	list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
 	err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
 				WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
 				WL_ISCAN_BUF_MAX);
@@ -2958,12 +2955,12 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
 		WL_ERR("error (%d)\n", err);
 		return err;
 	}
-	results->buflen = dtoh32(results->buflen);
-	results->version = dtoh32(results->version);
-	results->count = dtoh32(results->count);
+	results->buflen = le32_to_cpu(results->buflen);
+	results->version = le32_to_cpu(results->version);
+	results->count = le32_to_cpu(results->count);
 	WL_DBG("results->count = %d\n", results->count);
 	WL_DBG("results->buflen = %d\n", results->buflen);
-	*status = dtoh32(list_buf->status);
+	*status = le32_to_cpu(list_buf->status);
 	*bss_list = results;
 
 	return err;
@@ -3274,7 +3271,7 @@ static s32 wl_event_handler(void *data)
 void
 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
 {
-	u32 event_type = ntoh32(e->event_type);
+	u32 event_type = be32_to_cpu(e->event_type);
 	struct wl_priv *wl = ndev_to_wl(ndev);
 #if (WL_DBG_LEVEL > 0)
 	s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
@@ -3393,8 +3390,8 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
 		WL_ERR("invalid type (%d)\n", iftype);
 		return err;
 	}
-	infra = htod32(infra);
-	ap = htod32(ap);
+	infra = cpu_to_le32(infra);
+	ap = cpu_to_le32(ap);
 	WL_DBG("%s ap (%d), infra (%d)\n", ndev->name, ap, infra);
 	err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
 	if (unlikely(err)) {
@@ -3656,26 +3653,28 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
 	pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
 
 	/* Parse packet filter id. */
-	pkt_filter.id = htod32(100);
+	pkt_filter.id = cpu_to_le32(100);
 
 	/* Parse filter polarity. */
-	pkt_filter.negate_match = htod32(0);
+	pkt_filter.negate_match = cpu_to_le32(0);
 
 	/* Parse filter type. */
-	pkt_filter.type = htod32(0);
+	pkt_filter.type = cpu_to_le32(0);
 
 	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = htod32(0);
+	pkt_filter.u.pattern.offset = cpu_to_le32(0);
 
 	/* Parse pattern filter mask. */
-	mask_size = htod32(wl_pattern_atoh("0xff",
-					   (char *)pkt_filterp->u.pattern.
-					   mask_and_pattern));
+	mask_size = cpu_to_le32(wl_pattern_atoh("0xff",
+						(char *)pkt_filterp->u.pattern.
+						mask_and_pattern));
 
 	/* Parse pattern filter pattern. */
-	pattern_size = htod32(wl_pattern_atoh("0x00",
-					      (char *)&pkt_filterp->u.pattern.
-					      mask_and_pattern[mask_size]));
+	pattern_size = cpu_to_le32(wl_pattern_atoh("0x00",
+						   (char *)&pkt_filterp->u.
+						   pattern.
+						   mask_and_pattern
+						   [mask_size]));
 
 	if (mask_size != pattern_size) {
 		WL_ERR("Mask and pattern not the same size\n");
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
index 482691b..5112160 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
@@ -20,7 +20,6 @@
 #include <linux/wireless.h>
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
-#include <proto/ethernet.h>
 #include <wlioctl.h>
 
 struct wl_conf;
@@ -29,23 +28,6 @@ struct wl_priv;
 struct wl_security;
 struct wl_ibss;
 
-#if defined(IL_BIGENDIAN)
-#include <bcmendian.h>
-#define htod32(i) (bcmswap32(i))
-#define htod16(i) (bcmswap16(i))
-#define dtoh32(i) (bcmswap32(i))
-#define dtoh16(i) (bcmswap16(i))
-#define htodchanspec(i) htod16(i)
-#define dtohchanspec(i) dtoh16(i)
-#else
-#define htod32(i) i
-#define htod16(i) i
-#define dtoh32(i) i
-#define dtoh16(i) i
-#define htodchanspec(i) i
-#define dtohchanspec(i) i
-#endif
-
 #define WL_DBG_NONE	0
 #define WL_DBG_DBG 	(1 << 2)
 #define WL_DBG_INFO	(1 << 1)
@@ -316,7 +298,7 @@ struct wl_priv {
 						 cfg80211 layer */
 	struct wl_ie ie;	/* information element object for
 					 internal purpose */
-	struct ether_addr bssid;	/* bssid of currently engaged network */
+	u8 bssid[ETH_ALEN];	/* bssid of currently engaged network */
 	struct semaphore event_sync;	/* for synchronization of main event
 					 thread */
 	struct wl_profile *profile;	/* holding dongle profile */
@@ -366,7 +348,8 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list,
 {
 	return bss = bss ?
 		(struct wl_bss_info *)((unsigned long)bss +
-				       dtoh32(bss->length)) : list->bss_info;
+				       le32_to_cpu(bss->length)) :
+		list->bss_info;
 }
 
 #define for_each_bss(list, bss, __i)	\
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.c b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
index db6e68e..b49957f 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_iw.c
+++ b/drivers/staging/brcm80211/brcmfmac/wl_iw.c
@@ -18,12 +18,9 @@
 #include <linux/semaphore.h>
 #include <bcmdefs.h>
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <wlioctl.h>
 
 #include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
 
 #include <linux/if_arp.h>
 #include <asm/uaccess.h>
@@ -31,11 +28,10 @@
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhdioctl.h>
-
+#include <linux/ieee80211.h>
 typedef const struct si_pub si_t;
 #include <wlioctl.h>
 
-#include <proto/ethernet.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 
@@ -72,23 +68,6 @@ uint wl_msg_level = WL_ERROR_VAL;
 
 #define MAX_WLIW_IOCTL_LEN 1024
 
-#if defined(IL_BIGENDIAN)
-#include <bcmendian.h>
-#define htod32(i) (bcmswap32(i))
-#define htod16(i) (bcmswap16(i))
-#define dtoh32(i) (bcmswap32(i))
-#define dtoh16(i) (bcmswap16(i))
-#define htodchanspec(i) htod16(i)
-#define dtohchanspec(i) dtoh16(i)
-#else
-#define htod32(i) i
-#define htod16(i) i
-#define dtoh32(i) i
-#define dtoh16(i) i
-#define htodchanspec(i) i
-#define dtohchanspec(i) i
-#endif
-
 #ifdef CONFIG_WIRELESS_EXT
 
 extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
@@ -137,6 +116,9 @@ typedef struct iscan_info {
 	int iscan_ex_param_size;
 } iscan_info_t;
 iscan_info_t *g_iscan;
+
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+
 static void wl_iw_timerfunc(unsigned long data);
 static void wl_iw_set_event_mask(struct net_device *dev);
 static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, u16 action);
@@ -158,24 +140,24 @@ wl_iw_get_scan_prep(wl_scan_results_t *list,
 
 static void swap_key_from_BE(wl_wsec_key_t *key)
 {
-	key->index = htod32(key->index);
-	key->len = htod32(key->len);
-	key->algo = htod32(key->algo);
-	key->flags = htod32(key->flags);
-	key->rxiv.hi = htod32(key->rxiv.hi);
-	key->rxiv.lo = htod16(key->rxiv.lo);
-	key->iv_initialized = htod32(key->iv_initialized);
+	key->index = cpu_to_le32(key->index);
+	key->len = cpu_to_le32(key->len);
+	key->algo = cpu_to_le32(key->algo);
+	key->flags = cpu_to_le32(key->flags);
+	key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+	key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+	key->iv_initialized = cpu_to_le32(key->iv_initialized);
 }
 
 static void swap_key_to_BE(wl_wsec_key_t *key)
 {
-	key->index = dtoh32(key->index);
-	key->len = dtoh32(key->len);
-	key->algo = dtoh32(key->algo);
-	key->flags = dtoh32(key->flags);
-	key->rxiv.hi = dtoh32(key->rxiv.hi);
-	key->rxiv.lo = dtoh16(key->rxiv.lo);
-	key->iv_initialized = dtoh32(key->iv_initialized);
+	key->index = le32_to_cpu(key->index);
+	key->len = le32_to_cpu(key->len);
+	key->algo = le32_to_cpu(key->algo);
+	key->flags = le32_to_cpu(key->flags);
+	key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
+	key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
+	key->iv_initialized = le32_to_cpu(key->iv_initialized);
 }
 
 static int dev_wlc_ioctl(struct net_device *dev, int cmd, void *arg, int len)
@@ -223,7 +205,7 @@ static int dev_wlc_intvar_set(struct net_device *dev, char *name, int val)
 	char buf[WLC_IOCTL_SMLEN];
 	uint len;
 
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
 	ASSERT(len);
 
@@ -288,7 +270,7 @@ dev_wlc_bufvar_get(struct net_device *dev, char *name, char *buf, int buflen)
 	    dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf,
 			  MAX_WLIW_IOCTL_LEN);
 	if (!error)
-		bcopy(ioctlbuf, buf, buflen);
+		memcpy(buf, ioctlbuf, buflen);
 
 	return error;
 }
@@ -310,7 +292,7 @@ static int dev_wlc_intvar_get(struct net_device *dev, char *name, int *retval)
 	ASSERT(len);
 	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
 
-	*retval = dtoh32(var.val);
+	*retval = le32_to_cpu(var.val);
 
 	return error;
 }
@@ -340,7 +322,7 @@ wl_iw_config_commit(struct net_device *dev,
 	if (error)
 		return error;
 
-	ssid.SSID_len = dtoh32(ssid.SSID_len);
+	ssid.SSID_len = le32_to_cpu(ssid.SSID_len);
 
 	if (!ssid.SSID_len)
 		return 0;
@@ -392,7 +374,7 @@ wl_iw_set_freq(struct net_device *dev,
 
 		chan = wf_mhz2channel(fwrq->m, sf);
 	}
-	chan = htod32(chan);
+	chan = cpu_to_le32(chan);
 
 	error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan));
 	if (error)
@@ -415,8 +397,8 @@ wl_iw_get_freq(struct net_device *dev,
 	if (error)
 		return error;
 
-	fwrq->m = dtoh32(ci.hw_channel);
-	fwrq->e = dtoh32(0);
+	fwrq->m = le32_to_cpu(ci.hw_channel);
+	fwrq->e = le32_to_cpu(0);
 	return 0;
 }
 
@@ -441,8 +423,8 @@ wl_iw_set_mode(struct net_device *dev,
 	default:
 		return -EINVAL;
 	}
-	infra = htod32(infra);
-	ap = htod32(ap);
+	infra = cpu_to_le32(infra);
+	ap = cpu_to_le32(ap);
 
 	error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra));
 	if (error)
@@ -471,8 +453,8 @@ wl_iw_get_mode(struct net_device *dev,
 	if (error)
 		return error;
 
-	infra = dtoh32(infra);
-	ap = dtoh32(ap);
+	infra = le32_to_cpu(infra);
+	ap = le32_to_cpu(ap);
 	*uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
 
 	return 0;
@@ -488,7 +470,7 @@ wl_iw_get_range(struct net_device *dev,
 	wl_rateset_t rateset;
 	s8 *channels;
 	int error, i, k;
-	uint sf, ch;
+	uint ch;
 
 	int phytype;
 	int bw_cap = 0, sgi_tx = 0, nmode = 0;
@@ -517,23 +499,24 @@ wl_iw_get_range(struct net_device *dev,
 
 	range->min_nwid = range->max_nwid = 0;
 
-	list->count = htod32(MAXCHANNEL);
+	list->count = cpu_to_le32(MAXCHANNEL);
 	error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels,
 				(MAXCHANNEL + 1) * 4);
 	if (error) {
 		kfree(channels);
 		return error;
 	}
-	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
-		range->freq[i].i = dtoh32(list->element[i]);
-
-		ch = dtoh32(list->element[i]);
-		if (ch <= CH_MAX_2G_CHANNEL)
-			sf = WF_CHAN_FACTOR_2_4_G;
-		else
-			sf = WF_CHAN_FACTOR_5_G;
+	for (i = 0; i < le32_to_cpu(list->count) && i < IW_MAX_FREQUENCIES;
+	     i++) {
+		range->freq[i].i = le32_to_cpu(list->element[i]);
 
-		range->freq[i].m = wf_channel2mhz(ch, sf);
+		ch = le32_to_cpu(list->element[i]);
+		if (ch <= CH_MAX_2G_CHANNEL) {
+			range->freq[i].m = ieee80211_dsss_chan_to_freq(ch);
+		} else {
+			range->freq[i].m = ieee80211_ofdm_chan_to_freq(
+						WF_CHAN_FACTOR_5_G/2, ch);
+		}
 		range->freq[i].e = 6;
 	}
 	range->num_frequency = range->num_channels = i;
@@ -555,7 +538,7 @@ wl_iw_get_range(struct net_device *dev,
 		kfree(channels);
 		return error;
 	}
-	rateset.count = dtoh32(rateset.count);
+	rateset.count = le32_to_cpu(rateset.count);
 	range->num_bitrates = rateset.count;
 	for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
 		range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
@@ -567,7 +550,7 @@ wl_iw_get_range(struct net_device *dev,
 		dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
 		dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci,
 			      sizeof(channel_info_t));
-		ci.hw_channel = dtoh32(ci.hw_channel);
+		ci.hw_channel = le32_to_cpu(ci.hw_channel);
 
 		if (bw_cap == 0 || (bw_cap == 2 && ci.hw_channel <= 14)) {
 			if (sgi_tx == 0)
@@ -593,7 +576,7 @@ wl_iw_get_range(struct net_device *dev,
 		kfree(channels);
 		return error;
 	}
-	i = dtoh32(i);
+	i = le32_to_cpu(i);
 	if (i == WLC_PHY_TYPE_A)
 		range->throughput = 24000000;
 	else
@@ -606,14 +589,14 @@ wl_iw_get_range(struct net_device *dev,
 
 	range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
 	range->num_encoding_sizes = 4;
-	range->encoding_size[0] = WEP1_KEY_SIZE;
-	range->encoding_size[1] = WEP128_KEY_SIZE;
+	range->encoding_size[0] = WLAN_KEY_LEN_WEP40;
+	range->encoding_size[1] = WLAN_KEY_LEN_WEP104;
 #if WIRELESS_EXT > 17
-	range->encoding_size[2] = TKIP_KEY_SIZE;
+	range->encoding_size[2] = WLAN_KEY_LEN_TKIP;
 #else
 	range->encoding_size[2] = 0;
 #endif
-	range->encoding_size[3] = AES_KEY_SIZE;
+	range->encoding_size[3] = WLAN_KEY_LEN_AES_CMAC;
 
 	range->min_pmp = 0;
 	range->max_pmp = 0;
@@ -690,7 +673,7 @@ wl_iw_set_spy(struct net_device *dev,
 
 	iw->spy_num = min_t(int, ARRAY_SIZE(iw->spy_addr), dwrq->length);
 	for (i = 0; i < iw->spy_num; i++)
-		memcpy(&iw->spy_addr[i], addr[i].sa_data, ETH_ALEN);
+		memcpy(iw->spy_addr[i], addr[i].sa_data, ETH_ALEN);
 	memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
 
 	return 0;
@@ -712,7 +695,7 @@ wl_iw_get_spy(struct net_device *dev,
 
 	dwrq->length = iw->spy_num;
 	for (i = 0; i < iw->spy_num; i++) {
-		memcpy(addr[i].sa_data, &iw->spy_addr[i], ETH_ALEN);
+		memcpy(addr[i].sa_data, iw->spy_addr[i], ETH_ALEN);
 		addr[i].sa_family = AF_UNIX;
 		memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
 		iw->spy_qual[i].updated = 0;
@@ -745,10 +728,10 @@ wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params,
 		join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
 		join_params->params.chanspec_list[0] |= chanspec;
 		join_params->params.chanspec_list[0] =
-		    htodchanspec(join_params->params.chanspec_list[0]);
+		    cpu_to_le16(join_params->params.chanspec_list[0]);
 
 		join_params->params.chanspec_num =
-		    htod32(join_params->params.chanspec_num);
+		    cpu_to_le32(join_params->params.chanspec_num);
 
 		WL_TRACE("%s  join_params->params.chanspec_list[0]= %X\n",
 			 __func__, join_params->params.chanspec_list[0]);
@@ -784,7 +767,7 @@ wl_iw_set_wap(struct net_device *dev,
 	join_params_size = sizeof(join_params.ssid);
 
 	memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
+	join_params.ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
 	memcpy(&join_params.params.bssid, awrq->sa_data, ETH_ALEN);
 
 	WL_TRACE("%s  target_channel=%d\n",
@@ -840,15 +823,15 @@ wl_iw_mlme(struct net_device *dev,
 	}
 
 	scbval.val = mlme->reason_code;
-	bcopy(&mlme->addr.sa_data, &scbval.ea, ETH_ALEN);
+	memcpy(&scbval.ea, &mlme->addr.sa_data, ETH_ALEN);
 
 	if (mlme->cmd == IW_MLME_DISASSOC) {
-		scbval.val = htod32(scbval.val);
+		scbval.val = cpu_to_le32(scbval.val);
 		error =
 		    dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval,
 				  sizeof(scb_val_t));
 	} else if (mlme->cmd == IW_MLME_DEAUTH) {
-		scbval.val = htod32(scbval.val);
+		scbval.val = cpu_to_le32(scbval.val);
 		error =
 		    dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
 				  &scbval, sizeof(scb_val_t));
@@ -879,20 +862,19 @@ wl_iw_get_aplist(struct net_device *dev,
 	if (!extra)
 		return -EINVAL;
 
-	list = kmalloc(buflen, GFP_KERNEL);
+	list = kzalloc(buflen, GFP_KERNEL);
 	if (!list)
 		return -ENOMEM;
-	memset(list, 0, buflen);
-	list->buflen = htod32(buflen);
+	list->buflen = cpu_to_le32(buflen);
 	error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen);
 	if (error) {
 		WL_ERROR("%d: Scan results error %d\n", __LINE__, error);
 		kfree(list);
 		return error;
 	}
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
+	list->buflen = le32_to_cpu(list->buflen);
+	list->version = le32_to_cpu(list->version);
+	list->count = le32_to_cpu(list->count);
 	if (list->version != WL_BSS_INFO_VERSION) {
 		WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
 			 __func__, list->version);
@@ -903,18 +885,18 @@ wl_iw_get_aplist(struct net_device *dev,
 	for (i = 0, dwrq->length = 0;
 	     i < list->count && dwrq->length < IW_MAX_AP; i++) {
 		bi = bi ? (wl_bss_info_t *) ((unsigned long)bi +
-					     dtoh32(bi->length)) : list->
+					     le32_to_cpu(bi->length)) : list->
 		    bss_info;
-		ASSERT(((unsigned long)bi + dtoh32(bi->length)) <=
+		ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
 		       ((unsigned long)list + buflen));
 
-		if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+		if (!(le16_to_cpu(bi->capability) & WLAN_CAPABILITY_ESS))
 			continue;
 
 		memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETH_ALEN);
 		addr[dwrq->length].sa_family = ARPHRD_ETHER;
-		qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
-		qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+		qual[dwrq->length].qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
+		qual[dwrq->length].level = 0x100 + le16_to_cpu(bi->RSSI);
 		qual[dwrq->length].noise = 0x100 + bi->phy_noise;
 
 #if WIRELESS_EXT > 18
@@ -975,20 +957,22 @@ wl_iw_iscan_get_aplist(struct net_device *dev,
 		for (i = 0, dwrq->length = 0;
 		     i < list->count && dwrq->length < IW_MAX_AP; i++) {
 			bi = bi ? (wl_bss_info_t *) ((unsigned long)bi +
-						     dtoh32(bi->length)) :
+						     le32_to_cpu(bi->length)) :
 			    list->bss_info;
-			ASSERT(((unsigned long)bi + dtoh32(bi->length)) <=
+			ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
 			       ((unsigned long)list + WLC_IW_ISCAN_MAXLEN));
 
-			if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+			if (!(le16_to_cpu(bi->capability) &
+			      WLAN_CAPABILITY_ESS))
 				continue;
 
 			memcpy(addr[dwrq->length].sa_data, &bi->BSSID,
 			       ETH_ALEN);
 			addr[dwrq->length].sa_family = ARPHRD_ETHER;
 			qual[dwrq->length].qual =
-			    rssi_to_qual(dtoh16(bi->RSSI));
-			qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+			    rssi_to_qual(le16_to_cpu(bi->RSSI));
+			qual[dwrq->length].level = 0x100 +
+							le16_to_cpu(bi->RSSI);
 			qual[dwrq->length].noise = 0x100 + bi->phy_noise;
 
 #if WIRELESS_EXT > 18
@@ -1015,7 +999,7 @@ static int wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
 {
 	int err = 0;
 
-	memcpy(&params->bssid, &ether_bcast, ETH_ALEN);
+	memcpy(params->bssid, ether_bcast, ETH_ALEN);
 	params->bss_type = DOT11_BSSTYPE_ANY;
 	params->scan_type = 0;
 	params->nprobes = -1;
@@ -1024,10 +1008,10 @@ static int wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid)
 	params->home_time = -1;
 	params->channel_num = 0;
 
-	params->nprobes = htod32(params->nprobes);
-	params->active_time = htod32(params->active_time);
-	params->passive_time = htod32(params->passive_time);
-	params->home_time = htod32(params->home_time);
+	params->nprobes = cpu_to_le32(params->nprobes);
+	params->active_time = cpu_to_le32(params->active_time);
+	params->passive_time = cpu_to_le32(params->passive_time);
+	params->home_time = cpu_to_le32(params->home_time);
 	if (ssid && ssid->SSID_len)
 		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
 
@@ -1038,9 +1022,9 @@ static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, u16 action)
 {
 	int err = 0;
 
-	iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
-	iscan->iscan_ex_params_p->action = htod16(action);
-	iscan->iscan_ex_params_p->scan_duration = htod16(0);
+	iscan->iscan_ex_params_p->version = cpu_to_le32(ISCAN_REQ_VERSION);
+	iscan->iscan_ex_params_p->action = cpu_to_le16(action);
+	iscan->iscan_ex_params_p->scan_duration = cpu_to_le16(0);
 
 	WL_SCAN("%s : nprobes=%d\n",
 		__func__, iscan->iscan_ex_params_p->params.nprobes);
@@ -1077,7 +1061,7 @@ static void wl_iw_set_event_mask(struct net_device *dev)
 	char iovbuf[WL_EVENTING_MASK_LEN + 12];
 
 	dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
-	bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
 	setbit(eventmask, WLC_E_SCAN_COMPLETE);
 	dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
 			    iovbuf, sizeof(iovbuf));
@@ -1124,19 +1108,19 @@ static u32 wl_iw_iscan_get(iscan_info_t *iscan)
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+	list.results.buflen = cpu_to_le32(WLC_IW_ISCAN_MAXLEN);
 	res = dev_iw_iovar_getbuf(iscan->dev,
 				  "iscanresults",
 				  &list,
 				  WL_ISCAN_RESULTS_FIXED_SIZE,
 				  buf->iscan_buf, WLC_IW_ISCAN_MAXLEN);
 	if (res == 0) {
-		results->buflen = dtoh32(results->buflen);
-		results->version = dtoh32(results->version);
-		results->count = dtoh32(results->count);
+		results->buflen = le32_to_cpu(results->buflen);
+		results->version = le32_to_cpu(results->version);
+		results->count = le32_to_cpu(results->count);
 		WL_TRACE("results->count = %d\n", results->count);
 		WL_TRACE("results->buflen = %d\n", results->buflen);
-		status = dtoh32(list_buf->status);
+		status = le32_to_cpu(list_buf->status);
 	} else {
 		WL_ERROR("%s returns error %d\n", __func__, res);
 		status = WL_SCAN_RESULTS_NO_MEM;
@@ -1283,7 +1267,7 @@ wl_iw_set_scan(struct net_device *dev,
 				memcpy(g_specific_ssid.SSID, req->essid,
 				       g_specific_ssid.SSID_len);
 				g_specific_ssid.SSID_len =
-				    htod32(g_specific_ssid.SSID_len);
+				    cpu_to_le32(g_specific_ssid.SSID_len);
 				g_scan_specified_ssid = 1;
 				WL_TRACE("### Specific scan ssid=%s len=%d\n",
 					 g_specific_ssid.SSID,
@@ -1367,7 +1351,7 @@ wl_iw_iscan_set_scan(struct net_device *dev,
 	if (g_scan_specified_ssid) {
 		WL_TRACE("%s Specific SCAN already running ignoring BC scan\n",
 			 __func__);
-		return EBUSY;
+		return -EBUSY;
 	}
 
 	memset(&ssid, 0, sizeof(ssid));
@@ -1379,7 +1363,7 @@ wl_iw_iscan_set_scan(struct net_device *dev,
 			ssid.SSID_len = min_t(size_t, sizeof(ssid.SSID),
 						req->essid_len);
 			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
-			ssid.SSID_len = htod32(ssid.SSID_len);
+			ssid.SSID_len = cpu_to_le32(ssid.SSID_len);
 		} else {
 			g_scan_specified_ssid = 0;
 
@@ -1505,7 +1489,7 @@ wl_iw_get_scan_prep(wl_scan_results_t *list,
 		}
 
 		bi = bi ? (wl_bss_info_t *)((unsigned long)bi +
-					     dtoh32(bi->length)) : list->
+					     le32_to_cpu(bi->length)) : list->
 		    bss_info;
 
 		WL_TRACE("%s : %s\n", __func__, bi->SSID);
@@ -1516,14 +1500,15 @@ wl_iw_get_scan_prep(wl_scan_results_t *list,
 		event =
 		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 					 IW_EV_ADDR_LEN);
-		iwe.u.data.length = dtoh32(bi->SSID_len);
+		iwe.u.data.length = le32_to_cpu(bi->SSID_len);
 		iwe.cmd = SIOCGIWESSID;
 		iwe.u.data.flags = 1;
 		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
 
-		if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+		if (le16_to_cpu(bi->capability) & (WLAN_CAPABILITY_ESS |
+		    WLAN_CAPABILITY_IBSS)) {
 			iwe.cmd = SIOCGIWMODE;
-			if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+			if (le16_to_cpu(bi->capability) & WLAN_CAPABILITY_ESS)
 				iwe.u.mode = IW_MODE_INFRA;
 			else
 				iwe.u.mode = IW_MODE_ADHOC;
@@ -1533,19 +1518,23 @@ wl_iw_get_scan_prep(wl_scan_results_t *list,
 		}
 
 		iwe.cmd = SIOCGIWFREQ;
-		iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
-					      CHSPEC_CHANNEL(bi->chanspec) <=
-					      CH_MAX_2G_CHANNEL ?
-					      WF_CHAN_FACTOR_2_4_G :
-					      WF_CHAN_FACTOR_5_G);
+
+		if (CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL)
+			iwe.u.freq.m = ieee80211_dsss_chan_to_freq(
+						CHSPEC_CHANNEL(bi->chanspec));
+		else
+			iwe.u.freq.m = ieee80211_ofdm_chan_to_freq(
+						WF_CHAN_FACTOR_5_G/2,
+						CHSPEC_CHANNEL(bi->chanspec));
+
 		iwe.u.freq.e = 6;
 		event =
 		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 					 IW_EV_FREQ_LEN);
 
 		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
-		iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+		iwe.u.qual.qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
+		iwe.u.qual.level = 0x100 + le16_to_cpu(bi->RSSI);
 		iwe.u.qual.noise = 0x100 + bi->phy_noise;
 		event =
 		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
@@ -1554,7 +1543,7 @@ wl_iw_get_scan_prep(wl_scan_results_t *list,
 		wl_iw_handle_scanresults_ies(&event, end, info, bi);
 
 		iwe.cmd = SIOCGIWENCODE;
-		if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+		if (le16_to_cpu(bi->capability) & WLAN_CAPABILITY_PRIVACY)
 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
@@ -1621,7 +1610,7 @@ wl_iw_get_scan(struct net_device *dev,
 	error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci));
 	if (error)
 		return error;
-	ci.scan_channel = dtoh32(ci.scan_channel);
+	ci.scan_channel = le32_to_cpu(ci.scan_channel);
 	if (ci.scan_channel)
 		return -EAGAIN;
 
@@ -1636,7 +1625,7 @@ wl_iw_get_scan(struct net_device *dev,
 	}
 
 	memset(list, 0, len);
-	list->buflen = htod32(len);
+	list->buflen = cpu_to_le32(len);
 	error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len);
 	if (error) {
 		WL_ERROR("%s: %s : Scan_results ERROR %d\n",
@@ -1648,9 +1637,9 @@ wl_iw_get_scan(struct net_device *dev,
 		}
 		return 0;
 	}
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
+	list->buflen = le32_to_cpu(list->buflen);
+	list->version = le32_to_cpu(list->version);
+	list->count = le32_to_cpu(list->count);
 
 	if (list->version != WL_BSS_INFO_VERSION) {
 		WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
@@ -1770,9 +1759,9 @@ wl_iw_iscan_get_scan(struct net_device *dev,
 		for (ii = 0; ii < list->count && apcnt < IW_MAX_AP;
 		     apcnt++, ii++) {
 			bi = bi ? (wl_bss_info_t *)((unsigned long)bi +
-						     dtoh32(bi->length)) :
+						     le32_to_cpu(bi->length)) :
 			    list->bss_info;
-			ASSERT(((unsigned long)bi + dtoh32(bi->length)) <=
+			ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
 			       ((unsigned long)list + WLC_IW_ISCAN_MAXLEN));
 
 			if (event + ETH_ALEN + bi->SSID_len +
@@ -1787,17 +1776,18 @@ wl_iw_iscan_get_scan(struct net_device *dev,
 			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 						 IW_EV_ADDR_LEN);
 
-			iwe.u.data.length = dtoh32(bi->SSID_len);
+			iwe.u.data.length = le32_to_cpu(bi->SSID_len);
 			iwe.cmd = SIOCGIWESSID;
 			iwe.u.data.flags = 1;
 			event =
 			    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
 						 bi->SSID);
 
-			if (dtoh16(bi->capability) &
-			    (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+			if (le16_to_cpu(bi->capability) &
+			    (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
 				iwe.cmd = SIOCGIWMODE;
-				if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+				if (le16_to_cpu(bi->capability) &
+				    WLAN_CAPABILITY_ESS)
 					iwe.u.mode = IW_MODE_INFRA;
 				else
 					iwe.u.mode = IW_MODE_ADHOC;
@@ -1810,20 +1800,23 @@ wl_iw_iscan_get_scan(struct net_device *dev,
 			channel =
 			    (bi->ctl_ch ==
 			     0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
-			iwe.u.freq.m =
-			    wf_channel2mhz(channel,
-					   channel <=
-					   CH_MAX_2G_CHANNEL ?
-					   WF_CHAN_FACTOR_2_4_G :
-					   WF_CHAN_FACTOR_5_G);
+
+			if (channel <= CH_MAX_2G_CHANNEL)
+				iwe.u.freq.m =
+					ieee80211_dsss_chan_to_freq(channel);
+			else
+				iwe.u.freq.m = ieee80211_ofdm_chan_to_freq(
+							WF_CHAN_FACTOR_5_G/2,
+							channel);
+
 			iwe.u.freq.e = 6;
 			event =
 			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 						 IW_EV_FREQ_LEN);
 
 			iwe.cmd = IWEVQUAL;
-			iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
-			iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+			iwe.u.qual.qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
+			iwe.u.qual.level = 0x100 + le16_to_cpu(bi->RSSI);
 			iwe.u.qual.noise = 0x100 + bi->phy_noise;
 			event =
 			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
@@ -1832,7 +1825,8 @@ wl_iw_iscan_get_scan(struct net_device *dev,
 			wl_iw_handle_scanresults_ies(&event, end, info, bi);
 
 			iwe.cmd = SIOCGIWENCODE;
-			if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+			if (le16_to_cpu(bi->capability) &
+			    WLAN_CAPABILITY_PRIVACY)
 				iwe.u.data.flags =
 				    IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 			else
@@ -1912,14 +1906,14 @@ wl_iw_set_essid(struct net_device *dev,
 	} else {
 		g_ssid.SSID_len = 0;
 	}
-	g_ssid.SSID_len = htod32(g_ssid.SSID_len);
+	g_ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
 
 	memset(&join_params, 0, sizeof(join_params));
 	join_params_size = sizeof(join_params.ssid);
 
 	memcpy(&join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
-	memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
+	join_params.ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
+	memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
 
 	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params,
 			     &join_params_size);
@@ -1955,7 +1949,7 @@ wl_iw_get_essid(struct net_device *dev,
 		return error;
 	}
 
-	ssid.SSID_len = dtoh32(ssid.SSID_len);
+	ssid.SSID_len = le32_to_cpu(ssid.SSID_len);
 
 	memcpy(extra, ssid.SSID, ssid.SSID_len);
 
@@ -2017,7 +2011,7 @@ wl_iw_set_rate(struct net_device *dev,
 	if (error)
 		return error;
 
-	rateset.count = dtoh32(rateset.count);
+	rateset.count = le32_to_cpu(rateset.count);
 
 	if (vwrq->value < 0)
 		rate = rateset.rates[rateset.count - 1] & 0x7f;
@@ -2042,7 +2036,7 @@ wl_iw_set_rate(struct net_device *dev,
 		for (i = 0; i < rateset.count; i++)
 			if ((rateset.rates[i] & 0x7f) > rate)
 				break;
-		rateset.count = htod32(i);
+		rateset.count = cpu_to_le32(i);
 
 		error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset,
 					sizeof(rateset));
@@ -2064,7 +2058,7 @@ wl_iw_get_rate(struct net_device *dev,
 	error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
 	if (error)
 		return error;
-	rate = dtoh32(rate);
+	rate = le32_to_cpu(rate);
 	vwrq->value = rate * 500000;
 
 	return 0;
@@ -2164,7 +2158,7 @@ wl_iw_set_txpow(struct net_device *dev,
 	disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
 	disable += WL_RADIO_SW_DISABLE << 16;
 
-	disable = htod32(disable);
+	disable = cpu_to_le32(disable);
 	error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable));
 	if (error)
 		return error;
@@ -2206,7 +2200,7 @@ wl_iw_get_txpow(struct net_device *dev,
 	if (error)
 		return error;
 
-	disable = dtoh32(disable);
+	disable = le32_to_cpu(disable);
 	result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
 	vwrq->value = (s32) bcm_qdbm_to_mw(result);
 	vwrq->fixed = 0;
@@ -2241,7 +2235,7 @@ wl_iw_set_retry(struct net_device *dev,
 		if ((vwrq->flags & IW_RETRY_MAX)
 		    || !(vwrq->flags & IW_RETRY_MIN)) {
 #endif
-			lrl = htod32(vwrq->value);
+			lrl = cpu_to_le32(vwrq->value);
 			error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl,
 						sizeof(lrl));
 			if (error)
@@ -2256,7 +2250,7 @@ wl_iw_set_retry(struct net_device *dev,
 		if ((vwrq->flags & IW_RETRY_MIN)
 		    || !(vwrq->flags & IW_RETRY_MAX)) {
 #endif
-			srl = htod32(vwrq->value);
+			srl = cpu_to_le32(vwrq->value);
 			error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl,
 						sizeof(srl));
 			if (error)
@@ -2288,8 +2282,8 @@ wl_iw_get_retry(struct net_device *dev,
 	if (error)
 		return error;
 
-	lrl = dtoh32(lrl);
-	srl = dtoh32(srl);
+	lrl = le32_to_cpu(lrl);
+	srl = le32_to_cpu(srl);
 
 	if (vwrq->flags & IW_RETRY_MAX) {
 		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
@@ -2320,12 +2314,12 @@ wl_iw_set_encode(struct net_device *dev,
 	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
 		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS;
 		     key.index++) {
-			val = htod32(key.index);
+			val = cpu_to_le32(key.index);
 			error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val,
 						sizeof(val));
 			if (error)
 				return error;
-			val = dtoh32(val);
+			val = le32_to_cpu(val);
 			if (val)
 				break;
 		}
@@ -2338,7 +2332,7 @@ wl_iw_set_encode(struct net_device *dev,
 	}
 
 	if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
-		val = htod32(key.index);
+		val = cpu_to_le32(key.index);
 		error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val,
 					sizeof(val));
 		if (error)
@@ -2353,16 +2347,16 @@ wl_iw_set_encode(struct net_device *dev,
 
 		key.flags = WL_PRIMARY_KEY;
 		switch (key.len) {
-		case WEP1_KEY_SIZE:
+		case WLAN_KEY_LEN_WEP40:
 			key.algo = CRYPTO_ALGO_WEP1;
 			break;
-		case WEP128_KEY_SIZE:
+		case WLAN_KEY_LEN_WEP104:
 			key.algo = CRYPTO_ALGO_WEP128;
 			break;
-		case TKIP_KEY_SIZE:
+		case WLAN_KEY_LEN_TKIP:
 			key.algo = CRYPTO_ALGO_TKIP;
 			break;
-		case AES_KEY_SIZE:
+		case WLAN_KEY_LEN_AES_CMAC:
 			key.algo = CRYPTO_ALGO_AES_CCM;
 			break;
 		default:
@@ -2389,7 +2383,7 @@ wl_iw_set_encode(struct net_device *dev,
 		return error;
 
 	val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
 	if (error)
 		return error;
@@ -2417,7 +2411,7 @@ wl_iw_get_encode(struct net_device *dev,
 						sizeof(val));
 			if (error)
 				return error;
-			val = dtoh32(val);
+			val = le32_to_cpu(val);
 			if (val)
 				break;
 		}
@@ -2437,9 +2431,9 @@ wl_iw_get_encode(struct net_device *dev,
 
 	swap_key_to_BE(&key);
 
-	wsec = dtoh32(wsec);
-	auth = dtoh32(auth);
-	dwrq->length = min_t(u16, DOT11_MAX_KEY_SIZE, key.len);
+	wsec = le32_to_cpu(wsec);
+	auth = le32_to_cpu(auth);
+	dwrq->length = min_t(u16, WLAN_MAX_KEY_LEN, key.len);
 
 	dwrq->flags = key.index + 1;
 	if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)))
@@ -2465,7 +2459,7 @@ wl_iw_set_power(struct net_device *dev,
 
 	pm = vwrq->disabled ? PM_OFF : PM_MAX;
 
-	pm = htod32(pm);
+	pm = cpu_to_le32(pm);
 	error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
 	if (error)
 		return error;
@@ -2486,7 +2480,7 @@ wl_iw_get_power(struct net_device *dev,
 	if (error)
 		return error;
 
-	pm = dtoh32(pm);
+	pm = le32_to_cpu(pm);
 	vwrq->disabled = pm ? 0 : 1;
 	vwrq->flags = IW_POWER_ALL_R;
 
@@ -2545,14 +2539,13 @@ wl_iw_set_encodeext(struct net_device *dev,
 	key.len = iwe->key_len;
 
 	if (!is_multicast_ether_addr(iwe->addr.sa_data))
-		bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea,
-		      ETH_ALEN);
+		memcpy(&key.ea, &iwe->addr.sa_data, ETH_ALEN);
 
 	if (key.len == 0) {
 		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
 			WL_WSEC("Changing the the primary Key to %d\n",
 				key.index);
-			key.index = htod32(key.index);
+			key.index = cpu_to_le32(key.index);
 			error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
 					      &key.index, sizeof(key.index));
 			if (error)
@@ -2571,13 +2564,13 @@ wl_iw_set_encodeext(struct net_device *dev,
 			key.flags = WL_PRIMARY_KEY;
 		}
 
-		bcopy((void *)iwe->key, key.data, iwe->key_len);
+		memcpy(key.data, iwe->key, iwe->key_len);
 
 		if (iwe->alg == IW_ENCODE_ALG_TKIP) {
 			u8 keybuf[8];
-			bcopy(&key.data[24], keybuf, sizeof(keybuf));
-			bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
-			bcopy(keybuf, &key.data[16], sizeof(keybuf));
+			memcpy(keybuf, &key.data[24], sizeof(keybuf));
+			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+			memcpy(&key.data[16], keybuf, sizeof(keybuf));
 		}
 
 		if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
@@ -2594,7 +2587,7 @@ wl_iw_set_encodeext(struct net_device *dev,
 			key.algo = CRYPTO_ALGO_OFF;
 			break;
 		case IW_ENCODE_ALG_WEP:
-			if (iwe->key_len == WEP1_KEY_SIZE)
+			if (iwe->key_len == WLAN_KEY_LEN_WEP40)
 				key.algo = CRYPTO_ALGO_WEP1;
 			else
 				key.algo = CRYPTO_ALGO_WEP128;
@@ -2651,14 +2644,16 @@ wl_iw_set_pmksa(struct net_device *dev,
 			uint j;
 			pmkidptr = &pmkid;
 
-			bcopy(&iwpmksa->bssid.sa_data[0],
-			      &pmkidptr->pmkid[0].BSSID, ETH_ALEN);
-			bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID,
-			      WPA2_PMKID_LEN);
+			memcpy(&pmkidptr->pmkid[0].BSSID,
+			       &iwpmksa->bssid.sa_data[0],
+			       ETH_ALEN);
+			memcpy(&pmkidptr->pmkid[0].PMKID,
+			       &iwpmksa->pmkid[0],
+			       WLAN_PMKID_LEN);
 
-			WL_WSEC("wl_iw_set_pmksa:IW_PMKSA_REMOVE:PMKID: %pM = ",
-				&pmkidptr->pmkid[0].BSSID);
-			for (j = 0; j < WPA2_PMKID_LEN; j++)
+			WL_WSEC("wl_iw_set_pmksa:IW_PMKSA_REMOVE:PMKID: "
+				"%pM = ", &pmkidptr->pmkid[0].BSSID);
+			for (j = 0; j < WLAN_PMKID_LEN; j++)
 				WL_WSEC("%02x ", pmkidptr->pmkid[0].PMKID[j]);
 			WL_WSEC("\n");
 		}
@@ -2673,12 +2668,12 @@ wl_iw_set_pmksa(struct net_device *dev,
 		    && (i < pmkid_list.pmkids.npmkid)) {
 			memset(&pmkid_list.pmkids.pmkid[i], 0, sizeof(pmkid_t));
 			for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
-				bcopy(&pmkid_list.pmkids.pmkid[i + 1].BSSID,
-				      &pmkid_list.pmkids.pmkid[i].BSSID,
-				      ETH_ALEN);
-				bcopy(&pmkid_list.pmkids.pmkid[i + 1].PMKID,
-				      &pmkid_list.pmkids.pmkid[i].PMKID,
-				      WPA2_PMKID_LEN);
+				memcpy(&pmkid_list.pmkids.pmkid[i].BSSID,
+				       &pmkid_list.pmkids.pmkid[i + 1].BSSID,
+				       ETH_ALEN);
+				memcpy(&pmkid_list.pmkids.pmkid[i].PMKID,
+				       &pmkid_list.pmkids.pmkid[i + 1].PMKID,
+				       WLAN_PMKID_LEN);
 			}
 			pmkid_list.pmkids.npmkid--;
 		} else
@@ -2692,12 +2687,12 @@ wl_iw_set_pmksa(struct net_device *dev,
 			     &pmkid_list.pmkids.pmkid[i].BSSID, ETH_ALEN))
 				break;
 		if (i < MAXPMKID) {
-			bcopy(&iwpmksa->bssid.sa_data[0],
-			      &pmkid_list.pmkids.pmkid[i].BSSID,
-			      ETH_ALEN);
-			bcopy(&iwpmksa->pmkid[0],
-			      &pmkid_list.pmkids.pmkid[i].PMKID,
-			      WPA2_PMKID_LEN);
+			memcpy(&pmkid_list.pmkids.pmkid[i].BSSID,
+			       &iwpmksa->bssid.sa_data[0],
+			       ETH_ALEN);
+			memcpy(&pmkid_list.pmkids.pmkid[i].PMKID,
+			       &iwpmksa->pmkid[0],
+			       WLAN_PMKID_LEN);
 			if (i == pmkid_list.pmkids.npmkid)
 				pmkid_list.pmkids.npmkid++;
 		} else
@@ -2708,7 +2703,7 @@ wl_iw_set_pmksa(struct net_device *dev,
 			k = pmkid_list.pmkids.npmkid;
 			WL_WSEC("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %pM = ",
 				&pmkid_list.pmkids.pmkid[k].BSSID);
-			for (j = 0; j < WPA2_PMKID_LEN; j++)
+			for (j = 0; j < WLAN_PMKID_LEN; j++)
 				WL_WSEC("%02x ",
 					pmkid_list.pmkids.pmkid[k].PMKID[j]);
 			WL_WSEC("\n");
@@ -2720,7 +2715,7 @@ wl_iw_set_pmksa(struct net_device *dev,
 		uint j;
 		WL_WSEC("PMKID[%d]: %pM = ",
 			i, &pmkid_list.pmkids.pmkid[i].BSSID);
-		for (j = 0; j < WPA2_PMKID_LEN; j++)
+		for (j = 0; j < WLAN_PMKID_LEN; j++)
 			WL_WSEC("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]);
 		WL_WSEC("\n");
 	}
@@ -3342,9 +3337,9 @@ wl_iw_conn_status_str(u32 event_type, u32 status, u32 reason,
 static bool
 wl_iw_check_conn_fail(wl_event_msg_t *e, char *stringBuf, uint buflen)
 {
-	u32 event = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
-	u32 reason = ntoh32(e->reason);
+	u32 event = be32_to_cpu(e->event_type);
+	u32 status = be32_to_cpu(e->status);
+	u32 reason = be32_to_cpu(e->reason);
 
 	if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
 		return true;
@@ -3363,10 +3358,10 @@ void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
 	union iwreq_data wrqu;
 	char extra[IW_CUSTOM_MAX + 1];
 	int cmd = 0;
-	u32 event_type = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
-	u32 datalen = ntoh32(e->datalen);
-	u32 status = ntoh32(e->status);
+	u32 event_type = be32_to_cpu(e->event_type);
+	u16 flags = be16_to_cpu(e->flags);
+	u32 datalen = be32_to_cpu(e->datalen);
+	u32 status = be32_to_cpu(e->status);
 	wl_iw_t *iw;
 	u32 toto;
 	memset(&wrqu, 0, sizeof(wrqu));
@@ -3409,8 +3404,6 @@ void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
 		if (!(flags & WLC_EVENT_MSG_LINK)) {
 			memset(wrqu.addr.sa_data, 0, ETH_ALEN);
 			memset(&extra, 0, ETH_ALEN);
-			WAKE_LOCK_TIMEOUT(iw->pub, WAKE_LOCK_LINK_DOWN_TMOUT,
-					  20 * HZ);
 		} else {
 			memcpy(wrqu.addr.sa_data, &e->addr, ETH_ALEN);
 			WL_TRACE("Link UP\n");
@@ -3436,10 +3429,10 @@ void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
 			wrqu.data.length = sizeof(status) + 1;
 			extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
 			memcpy(&extra[1], &status, sizeof(status));
-			printf("wl_iw_event status %d PacketId %d\n", status,
-			       toto);
-			printf("WLC_E_ACTION_FRAME_COMPLETE len %d\n",
-			       wrqu.data.length);
+			WL_TRACE("wl_iw_event status %d PacketId %d\n", status,
+				 toto);
+			WL_TRACE("WLC_E_ACTION_FRAME_COMPLETE len %d\n",
+				 wrqu.data.length);
 		}
 		break;
 #endif				/* WIRELESS_EXT > 14 */
@@ -3471,9 +3464,8 @@ void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
 
 				cmd = IWEVPMKIDCAND;
 				pmkcandlist = data;
-				count =
-				    ntoh32_ua((u8 *) &
-					      pmkcandlist->npmkid_cand);
+				count = get_unaligned_be32(&pmkcandlist->
+							   npmkid_cand);
 				ASSERT(count >= 0);
 				wrqu.data.length = sizeof(struct iw_pmkid_cand);
 				pmkidcand = pmkcandlist->pmkid_cand;
@@ -3483,9 +3475,9 @@ void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
 					if (pmkidcand->preauth)
 						iwpmkidcand->flags |=
 						    IW_PMKID_CAND_PREAUTH;
-					bcopy(&pmkidcand->BSSID,
-					      &iwpmkidcand->bssid.sa_data,
-					      ETH_ALEN);
+					memcpy(&iwpmkidcand->bssid.sa_data,
+					       &pmkidcand->BSSID,
+					       ETH_ALEN);
 #ifndef SANDGATE2G
 					wireless_send_event(dev, cmd, &wrqu,
 							    extra);
@@ -3523,8 +3515,6 @@ void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void *data)
 			WL_ERROR("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n",
 				 __func__, PNO_EVENT_UP,
 				 ssid->SSID, ssid->SSID_len);
-			WAKE_LOCK_TIMEOUT(iw->pub, WAKE_LOCK_PNO_FIND_TMOUT,
-					  20 * HZ);
 			cmd = IWEVCUSTOM;
 			memset(&wrqu, 0, sizeof(wrqu));
 			strcpy(extra, PNO_EVENT_UP);
@@ -3562,7 +3552,7 @@ int
 wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
 {
 	int res = 0;
-	wl_cnt_t cnt;
+	struct wl_cnt cnt;
 	int phy_noise;
 	int rssi;
 	scb_val_t scb_val;
@@ -3573,7 +3563,7 @@ wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
 	if (res)
 		goto done;
 
-	phy_noise = dtoh32(phy_noise);
+	phy_noise = le32_to_cpu(phy_noise);
 	WL_TRACE("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise);
 
 	memset(&scb_val, 0, sizeof(scb_val_t));
@@ -3581,7 +3571,7 @@ wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
 	if (res)
 		goto done;
 
-	rssi = dtoh32(scb_val.val);
+	rssi = le32_to_cpu(scb_val.val);
 	WL_TRACE("wl_iw_get_wireless_stats rssi=%d\n", rssi);
 	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
 		wstats->qual.qual = 0;
@@ -3605,47 +3595,50 @@ wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
 #endif
 
 #if WIRELESS_EXT > 11
-	WL_TRACE("wl_iw_get_wireless_stats counters=%zu\n", sizeof(wl_cnt_t));
+	WL_TRACE("wl_iw_get_wireless_stats counters=%zu\n",
+		 sizeof(struct wl_cnt));
 
-	memset(&cnt, 0, sizeof(wl_cnt_t));
+	memset(&cnt, 0, sizeof(struct wl_cnt));
 	res =
-	    dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
+	    dev_wlc_bufvar_get(dev, "counters", (char *)&cnt,
+			       sizeof(struct wl_cnt));
 	if (res) {
 		WL_ERROR("wl_iw_get_wireless_stats counters failed error=%d\n",
 			 res);
 		goto done;
 	}
 
-	cnt.version = dtoh16(cnt.version);
+	cnt.version = le16_to_cpu(cnt.version);
 	if (cnt.version != WL_CNT_T_VERSION) {
-		WL_TRACE("\tIncorrect version of counters struct: expected %d; got %d\n",
+		WL_TRACE("\tIncorrect counter version: expected %d; got %d\n",
 			 WL_CNT_T_VERSION, cnt.version);
 		goto done;
 	}
 
 	wstats->discard.nwid = 0;
-	wstats->discard.code = dtoh32(cnt.rxundec);
-	wstats->discard.fragment = dtoh32(cnt.rxfragerr);
-	wstats->discard.retries = dtoh32(cnt.txfail);
-	wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
+	wstats->discard.code = le32_to_cpu(cnt.rxundec);
+	wstats->discard.fragment = le32_to_cpu(cnt.rxfragerr);
+	wstats->discard.retries = le32_to_cpu(cnt.txfail);
+	wstats->discard.misc = le32_to_cpu(cnt.rxrunt) +
+		le32_to_cpu(cnt.rxgiant);
 	wstats->miss.beacon = 0;
 
 	WL_TRACE("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
-		 dtoh32(cnt.txframe), dtoh32(cnt.txbyte));
+		 le32_to_cpu(cnt.txframe), le32_to_cpu(cnt.txbyte));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n",
-		  dtoh32(cnt.rxfrmtoolong));
+		  le32_to_cpu(cnt.rxfrmtoolong));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxbadplcp=%d\n",
-		  dtoh32(cnt.rxbadplcp));
+		  le32_to_cpu(cnt.rxbadplcp));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxundec=%d\n",
-		  dtoh32(cnt.rxundec));
+		  le32_to_cpu(cnt.rxundec));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxfragerr=%d\n",
-		  dtoh32(cnt.rxfragerr));
+		  le32_to_cpu(cnt.rxfragerr));
 	WL_TRACE("wl_iw_get_wireless_stats counters txfail=%d\n",
-		  dtoh32(cnt.txfail));
+		  le32_to_cpu(cnt.txfail));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxrunt=%d\n",
-		  dtoh32(cnt.rxrunt));
+		  le32_to_cpu(cnt.rxrunt));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxgiant=%d\n",
-		  dtoh32(cnt.rxgiant));
+		  le32_to_cpu(cnt.rxgiant));
 #endif				/* WIRELESS_EXT > 11 */
 
 done:
@@ -3673,11 +3666,10 @@ int wl_iw_attach(struct net_device *dev, void *dhdp)
 	params_size =
 	    (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
 #endif
-	iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
+	iscan = kzalloc(sizeof(iscan_info_t), GFP_KERNEL);
 
 	if (!iscan)
 		return -ENOMEM;
-	memset(iscan, 0, sizeof(iscan_info_t));
 
 	iscan->iscan_ex_params_p = kmalloc(params_size, GFP_KERNEL);
 	if (!iscan->iscan_ex_params_p)
@@ -3711,11 +3703,10 @@ int wl_iw_attach(struct net_device *dev, void *dhdp)
 	priv_dev = dev;
 	MUTEX_LOCK_SOFTAP_SET_INIT(iw->pub);
 #endif
-	g_scan = kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
+	g_scan = kzalloc(G_SCAN_RESULTS, GFP_KERNEL);
 	if (!g_scan)
 		return -ENOMEM;
 
-	memset(g_scan, 0, G_SCAN_RESULTS);
 	g_scan_specified_ssid = 0;
 
 	return 0;
diff --git a/drivers/staging/brcm80211/brcmfmac/wl_iw.h b/drivers/staging/brcm80211/brcmfmac/wl_iw.h
index c8637c5..fe06174 100644
--- a/drivers/staging/brcm80211/brcmfmac/wl_iw.h
+++ b/drivers/staging/brcm80211/brcmfmac/wl_iw.h
@@ -19,7 +19,6 @@
 
 #include <linux/wireless.h>
 
-#include <proto/ethernet.h>
 #include <wlioctl.h>
 
 #define WL_SCAN_PARAMS_SSID_MAX	10
@@ -92,7 +91,7 @@ typedef struct wl_iw {
 	u32 gwsec;
 	bool privacy_invoked;
 
-	struct ether_addr spy_addr[IW_MAX_SPY];
+	u8 spy_addr[IW_MAX_SPY][ETH_ALEN];
 	struct iw_quality spy_qual[IW_MAX_SPY];
 	void *wlinfo;
 	dhd_pub_t *pub;
@@ -140,10 +139,4 @@ extern int dhd_dev_get_pno_status(struct net_device *dev);
 #define PNO_TLV_TYPE_TIME		'T'
 #define  PNO_EVENT_UP			"PNO_EVENT"
 
-typedef struct cmd_tlv {
-	char prefix;
-	char version;
-	char subver;
-	char reserved;
-} cmd_tlv_t;
 #endif				/* _wl_iw_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/Makefile b/drivers/staging/brcm80211/brcmsmac/Makefile
new file mode 100644
index 0000000..c4aafe5
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/Makefile
@@ -0,0 +1,63 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver
+#
+# 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.
+
+ccflags-y :=				\
+	-DWLC_HIGH				\
+	-DWLC_LOW				\
+	-DSTA					\
+	-DWME					\
+	-DWL11N					\
+	-DDBAND					\
+	-DBCMNVRAMR				\
+	-Idrivers/staging/brcm80211/brcmsmac \
+	-Idrivers/staging/brcm80211/brcmsmac/phy \
+	-Idrivers/staging/brcm80211/util \
+	-Idrivers/staging/brcm80211/include
+
+BRCMSMAC_OFILES := \
+	wl_mac80211.o \
+	wl_ucode_loader.o \
+	wlc_alloc.o \
+	wlc_ampdu.o \
+	wlc_antsel.o \
+	wlc_bmac.o \
+	wlc_channel.o \
+	wlc_main.o \
+	wlc_phy_shim.o \
+	wlc_rate.o \
+	wlc_stf.o \
+	phy/wlc_phy_cmn.o \
+	phy/wlc_phy_lcn.o \
+	phy/wlc_phy_n.o \
+	phy/wlc_phytbl_lcn.o \
+	phy/wlc_phytbl_n.o \
+	../util/aiutils.o \
+	../util/siutils.o \
+	../util/bcmutils.o \
+	../util/bcmwifi.o \
+	../util/bcmotp.o \
+	../util/bcmsrom.o \
+	../util/hnddma.o \
+	../util/hndpmu.o \
+	../util/nicpci.o \
+	../util/qmath.o \
+	../util/nvram/nvram_ro.o
+
+MODULEPFX := brcmsmac
+
+obj-m	+= $(MODULEPFX).o
+$(MODULEPFX)-objs	= $(BRCMSMAC_OFILES)
diff --git a/drivers/staging/brcm80211/brcmsmac/d11.h b/drivers/staging/brcm80211/brcmsmac/d11.h
new file mode 100644
index 0000000..a9d182f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/d11.h
@@ -0,0 +1,1771 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_D11_H
+#define	_D11_H
+
+#ifndef WL_RSSI_ANT_MAX
+#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
+#elif WL_RSSI_ANT_MAX != 4
+#error "WL_RSSI_ANT_MAX does not match"
+#endif
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef	PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif
+
+#define	BCN_TMPL_LEN		512	/* length of the BCN template area */
+
+/* RX FIFO numbers */
+#define	RX_FIFO			0	/* data and ctl frames */
+#define	RX_TXSTATUS_FIFO	3	/* RX fifo for tx status packages */
+
+/* TX FIFO numbers using WME Access Classes */
+#define	TX_AC_BK_FIFO		0	/* Access Category Background TX FIFO */
+#define	TX_AC_BE_FIFO		1	/* Access Category Best-Effort TX FIFO */
+#define	TX_AC_VI_FIFO		2	/* Access Class Video TX FIFO */
+#define	TX_AC_VO_FIFO		3	/* Access Class Voice TX FIFO */
+#define	TX_BCMC_FIFO		4	/* Broadcast/Multicast TX FIFO */
+#define	TX_ATIM_FIFO		5	/* TX fifo for ATIM window info */
+
+/* Addr is byte address used by SW; offset is word offset used by uCode */
+
+/* Per AC TX limit settings */
+#define M_AC_TXLMT_BASE_ADDR         (0x180 * 2)
+#define M_AC_TXLMT_ADDR(_ac)         (M_AC_TXLMT_BASE_ADDR + (2 * (_ac)))
+
+/* Legacy TX FIFO numbers */
+#define	TX_DATA_FIFO		TX_AC_BE_FIFO
+#define	TX_CTL_FIFO		TX_AC_VO_FIFO
+
+typedef volatile struct {
+	u32 intstatus;
+	u32 intmask;
+} intctrlregs_t;
+
+/* PIO structure,
+ *  support two PIO format: 2 bytes access and 4 bytes access
+ *  basic FIFO register set is per channel(transmit or receive)
+ *  a pair of channels is defined for convenience
+ */
+/* 2byte-wide pio register set per channel(xmt or rcv) */
+typedef volatile struct {
+	u16 fifocontrol;
+	u16 fifodata;
+	u16 fifofree;	/* only valid in xmt channel, not in rcv channel */
+	u16 PAD;
+} pio2regs_t;
+
+/* a pair of pio channels(tx and rx) */
+typedef volatile struct {
+	pio2regs_t tx;
+	pio2regs_t rx;
+} pio2regp_t;
+
+/* 4byte-wide pio register set per channel(xmt or rcv) */
+typedef volatile struct {
+	u32 fifocontrol;
+	u32 fifodata;
+} pio4regs_t;
+
+/* a pair of pio channels(tx and rx) */
+typedef volatile struct {
+	pio4regs_t tx;
+	pio4regs_t rx;
+} pio4regp_t;
+
+/* read: 32-bit register that can be read as 32-bit or as 2 16-bit
+ * write: only low 16b-it half can be written
+ */
+typedef volatile union {
+	u32 pmqhostdata;	/* read only! */
+	struct {
+		u16 pmqctrlstatus;	/* read/write */
+		u16 PAD;
+	} w;
+} pmqreg_t;
+
+typedef volatile struct {
+	dma64regs_t dmaxmt;	/* dma tx */
+	pio4regs_t piotx;	/* pio tx */
+	dma64regs_t dmarcv;	/* dma rx */
+	pio4regs_t piorx;	/* pio rx */
+} fifo64_t;
+
+/*
+ * Host Interface Registers
+ * - primed from hnd_cores/dot11mac/systemC/registers/ihr.h
+ * - but definitely not complete
+ */
+typedef volatile struct _d11regs {
+	/* Device Control ("semi-standard host registers") */
+	u32 PAD[3];		/* 0x0 - 0x8 */
+	u32 biststatus;	/* 0xC */
+	u32 biststatus2;	/* 0x10 */
+	u32 PAD;		/* 0x14 */
+	u32 gptimer;		/* 0x18 */
+	u32 usectimer;	/* 0x1c *//* for corerev >= 26 */
+
+	/* Interrupt Control *//* 0x20 */
+	intctrlregs_t intctrlregs[8];
+
+	u32 PAD[40];		/* 0x60 - 0xFC */
+
+	u32 intrcvlazy[4];	/* 0x100 - 0x10C */
+
+	u32 PAD[4];		/* 0x110 - 0x11c */
+
+	u32 maccontrol;	/* 0x120 */
+	u32 maccommand;	/* 0x124 */
+	u32 macintstatus;	/* 0x128 */
+	u32 macintmask;	/* 0x12C */
+
+	/* Transmit Template Access */
+	u32 tplatewrptr;	/* 0x130 */
+	u32 tplatewrdata;	/* 0x134 */
+	u32 PAD[2];		/* 0x138 - 0x13C */
+
+	/* PMQ registers */
+	pmqreg_t pmqreg;	/* 0x140 */
+	u32 pmqpatl;		/* 0x144 */
+	u32 pmqpath;		/* 0x148 */
+	u32 PAD;		/* 0x14C */
+
+	u32 chnstatus;	/* 0x150 */
+	u32 psmdebug;	/* 0x154 */
+	u32 phydebug;	/* 0x158 */
+	u32 machwcap;	/* 0x15C */
+
+	/* Extended Internal Objects */
+	u32 objaddr;		/* 0x160 */
+	u32 objdata;		/* 0x164 */
+	u32 PAD[2];		/* 0x168 - 0x16c */
+
+	u32 frmtxstatus;	/* 0x170 */
+	u32 frmtxstatus2;	/* 0x174 */
+	u32 PAD[2];		/* 0x178 - 0x17c */
+
+	/* TSF host access */
+	u32 tsf_timerlow;	/* 0x180 */
+	u32 tsf_timerhigh;	/* 0x184 */
+	u32 tsf_cfprep;	/* 0x188 */
+	u32 tsf_cfpstart;	/* 0x18c */
+	u32 tsf_cfpmaxdur32;	/* 0x190 */
+	u32 PAD[3];		/* 0x194 - 0x19c */
+
+	u32 maccontrol1;	/* 0x1a0 */
+	u32 machwcap1;	/* 0x1a4 */
+	u32 PAD[14];		/* 0x1a8 - 0x1dc */
+
+	/* Clock control and hardware workarounds*/
+	u32 clk_ctl_st;	/* 0x1e0 */
+	u32 hw_war;
+	u32 d11_phypllctl;	/* the phypll request/avail bits are
+				 * moved to clk_ctl_st
+				 */
+	u32 PAD[5];		/* 0x1ec - 0x1fc */
+
+	/* 0x200-0x37F dma/pio registers */
+	fifo64_t fifo64regs[6];
+
+	/* FIFO diagnostic port access */
+	dma32diag_t dmafifo;	/* 0x380 - 0x38C */
+
+	u32 aggfifocnt;	/* 0x390 */
+	u32 aggfifodata;	/* 0x394 */
+	u32 PAD[16];		/* 0x398 - 0x3d4 */
+	u16 radioregaddr;	/* 0x3d8 */
+	u16 radioregdata;	/* 0x3da */
+
+	/*
+	 * time delay between the change on rf disable input and
+	 * radio shutdown
+	 */
+	u32 rfdisabledly;	/* 0x3DC */
+
+	/* PHY register access */
+	u16 phyversion;	/* 0x3e0 - 0x0 */
+	u16 phybbconfig;	/* 0x3e2 - 0x1 */
+	u16 phyadcbias;	/* 0x3e4 - 0x2  Bphy only */
+	u16 phyanacore;	/* 0x3e6 - 0x3  pwwrdwn on aphy */
+	u16 phyrxstatus0;	/* 0x3e8 - 0x4 */
+	u16 phyrxstatus1;	/* 0x3ea - 0x5 */
+	u16 phycrsth;	/* 0x3ec - 0x6 */
+	u16 phytxerror;	/* 0x3ee - 0x7 */
+	u16 phychannel;	/* 0x3f0 - 0x8 */
+	u16 PAD[1];		/* 0x3f2 - 0x9 */
+	u16 phytest;		/* 0x3f4 - 0xa */
+	u16 phy4waddr;	/* 0x3f6 - 0xb */
+	u16 phy4wdatahi;	/* 0x3f8 - 0xc */
+	u16 phy4wdatalo;	/* 0x3fa - 0xd */
+	u16 phyregaddr;	/* 0x3fc - 0xe */
+	u16 phyregdata;	/* 0x3fe - 0xf */
+
+	/* IHR *//* 0x400 - 0x7FE */
+
+	/* RXE Block */
+	u16 PAD[3];		/* 0x400 - 0x406 */
+	u16 rcv_fifo_ctl;	/* 0x406 */
+	u16 PAD;		/* 0x408 - 0x40a */
+	u16 rcv_frm_cnt;	/* 0x40a */
+	u16 PAD[4];		/* 0x40a - 0x414 */
+	u16 rssi;		/* 0x414 */
+	u16 PAD[5];		/* 0x414 - 0x420 */
+	u16 rcm_ctl;		/* 0x420 */
+	u16 rcm_mat_data;	/* 0x422 */
+	u16 rcm_mat_mask;	/* 0x424 */
+	u16 rcm_mat_dly;	/* 0x426 */
+	u16 rcm_cond_mask_l;	/* 0x428 */
+	u16 rcm_cond_mask_h;	/* 0x42A */
+	u16 rcm_cond_dly;	/* 0x42C */
+	u16 PAD[1];		/* 0x42E */
+	u16 ext_ihr_addr;	/* 0x430 */
+	u16 ext_ihr_data;	/* 0x432 */
+	u16 rxe_phyrs_2;	/* 0x434 */
+	u16 rxe_phyrs_3;	/* 0x436 */
+	u16 phy_mode;	/* 0x438 */
+	u16 rcmta_ctl;	/* 0x43a */
+	u16 rcmta_size;	/* 0x43c */
+	u16 rcmta_addr0;	/* 0x43e */
+	u16 rcmta_addr1;	/* 0x440 */
+	u16 rcmta_addr2;	/* 0x442 */
+	u16 PAD[30];		/* 0x444 - 0x480 */
+
+	/* PSM Block *//* 0x480 - 0x500 */
+
+	u16 PAD;		/* 0x480 */
+	u16 psm_maccontrol_h;	/* 0x482 */
+	u16 psm_macintstatus_l;	/* 0x484 */
+	u16 psm_macintstatus_h;	/* 0x486 */
+	u16 psm_macintmask_l;	/* 0x488 */
+	u16 psm_macintmask_h;	/* 0x48A */
+	u16 PAD;		/* 0x48C */
+	u16 psm_maccommand;	/* 0x48E */
+	u16 psm_brc;		/* 0x490 */
+	u16 psm_phy_hdr_param;	/* 0x492 */
+	u16 psm_postcard;	/* 0x494 */
+	u16 psm_pcard_loc_l;	/* 0x496 */
+	u16 psm_pcard_loc_h;	/* 0x498 */
+	u16 psm_gpio_in;	/* 0x49A */
+	u16 psm_gpio_out;	/* 0x49C */
+	u16 psm_gpio_oe;	/* 0x49E */
+
+	u16 psm_bred_0;	/* 0x4A0 */
+	u16 psm_bred_1;	/* 0x4A2 */
+	u16 psm_bred_2;	/* 0x4A4 */
+	u16 psm_bred_3;	/* 0x4A6 */
+	u16 psm_brcl_0;	/* 0x4A8 */
+	u16 psm_brcl_1;	/* 0x4AA */
+	u16 psm_brcl_2;	/* 0x4AC */
+	u16 psm_brcl_3;	/* 0x4AE */
+	u16 psm_brpo_0;	/* 0x4B0 */
+	u16 psm_brpo_1;	/* 0x4B2 */
+	u16 psm_brpo_2;	/* 0x4B4 */
+	u16 psm_brpo_3;	/* 0x4B6 */
+	u16 psm_brwk_0;	/* 0x4B8 */
+	u16 psm_brwk_1;	/* 0x4BA */
+	u16 psm_brwk_2;	/* 0x4BC */
+	u16 psm_brwk_3;	/* 0x4BE */
+
+	u16 psm_base_0;	/* 0x4C0 */
+	u16 psm_base_1;	/* 0x4C2 */
+	u16 psm_base_2;	/* 0x4C4 */
+	u16 psm_base_3;	/* 0x4C6 */
+	u16 psm_base_4;	/* 0x4C8 */
+	u16 psm_base_5;	/* 0x4CA */
+	u16 psm_base_6;	/* 0x4CC */
+	u16 psm_pc_reg_0;	/* 0x4CE */
+	u16 psm_pc_reg_1;	/* 0x4D0 */
+	u16 psm_pc_reg_2;	/* 0x4D2 */
+	u16 psm_pc_reg_3;	/* 0x4D4 */
+	u16 PAD[0xD];	/* 0x4D6 - 0x4DE */
+	u16 psm_corectlsts;	/* 0x4f0 *//* Corerev >= 13 */
+	u16 PAD[0x7];	/* 0x4f2 - 0x4fE */
+
+	/* TXE0 Block *//* 0x500 - 0x580 */
+	u16 txe_ctl;		/* 0x500 */
+	u16 txe_aux;		/* 0x502 */
+	u16 txe_ts_loc;	/* 0x504 */
+	u16 txe_time_out;	/* 0x506 */
+	u16 txe_wm_0;	/* 0x508 */
+	u16 txe_wm_1;	/* 0x50A */
+	u16 txe_phyctl;	/* 0x50C */
+	u16 txe_status;	/* 0x50E */
+	u16 txe_mmplcp0;	/* 0x510 */
+	u16 txe_mmplcp1;	/* 0x512 */
+	u16 txe_phyctl1;	/* 0x514 */
+
+	u16 PAD[0x05];	/* 0x510 - 0x51E */
+
+	/* Transmit control */
+	u16 xmtfifodef;	/* 0x520 */
+	u16 xmtfifo_frame_cnt;	/* 0x522 *//* Corerev >= 16 */
+	u16 xmtfifo_byte_cnt;	/* 0x524 *//* Corerev >= 16 */
+	u16 xmtfifo_head;	/* 0x526 *//* Corerev >= 16 */
+	u16 xmtfifo_rd_ptr;	/* 0x528 *//* Corerev >= 16 */
+	u16 xmtfifo_wr_ptr;	/* 0x52A *//* Corerev >= 16 */
+	u16 xmtfifodef1;	/* 0x52C *//* Corerev >= 16 */
+
+	u16 PAD[0x09];	/* 0x52E - 0x53E */
+
+	u16 xmtfifocmd;	/* 0x540 */
+	u16 xmtfifoflush;	/* 0x542 */
+	u16 xmtfifothresh;	/* 0x544 */
+	u16 xmtfifordy;	/* 0x546 */
+	u16 xmtfifoprirdy;	/* 0x548 */
+	u16 xmtfiforqpri;	/* 0x54A */
+	u16 xmttplatetxptr;	/* 0x54C */
+	u16 PAD;		/* 0x54E */
+	u16 xmttplateptr;	/* 0x550 */
+	u16 smpl_clct_strptr;	/* 0x552 *//* Corerev >= 22 */
+	u16 smpl_clct_stpptr;	/* 0x554 *//* Corerev >= 22 */
+	u16 smpl_clct_curptr;	/* 0x556 *//* Corerev >= 22 */
+	u16 PAD[0x04];	/* 0x558 - 0x55E */
+	u16 xmttplatedatalo;	/* 0x560 */
+	u16 xmttplatedatahi;	/* 0x562 */
+
+	u16 PAD[2];		/* 0x564 - 0x566 */
+
+	u16 xmtsel;		/* 0x568 */
+	u16 xmttxcnt;	/* 0x56A */
+	u16 xmttxshmaddr;	/* 0x56C */
+
+	u16 PAD[0x09];	/* 0x56E - 0x57E */
+
+	/* TXE1 Block */
+	u16 PAD[0x40];	/* 0x580 - 0x5FE */
+
+	/* TSF Block */
+	u16 PAD[0X02];	/* 0x600 - 0x602 */
+	u16 tsf_cfpstrt_l;	/* 0x604 */
+	u16 tsf_cfpstrt_h;	/* 0x606 */
+	u16 PAD[0X05];	/* 0x608 - 0x610 */
+	u16 tsf_cfppretbtt;	/* 0x612 */
+	u16 PAD[0XD];	/* 0x614 - 0x62C */
+	u16 tsf_clk_frac_l;	/* 0x62E */
+	u16 tsf_clk_frac_h;	/* 0x630 */
+	u16 PAD[0X14];	/* 0x632 - 0x658 */
+	u16 tsf_random;	/* 0x65A */
+	u16 PAD[0x05];	/* 0x65C - 0x664 */
+	/* GPTimer 2 registers */
+	u16 tsf_gpt2_stat;	/* 0x666 */
+	u16 tsf_gpt2_ctr_l;	/* 0x668 */
+	u16 tsf_gpt2_ctr_h;	/* 0x66A */
+	u16 tsf_gpt2_val_l;	/* 0x66C */
+	u16 tsf_gpt2_val_h;	/* 0x66E */
+	u16 tsf_gptall_stat;	/* 0x670 */
+	u16 PAD[0x07];	/* 0x672 - 0x67E */
+
+	/* IFS Block */
+	u16 ifs_sifs_rx_tx_tx;	/* 0x680 */
+	u16 ifs_sifs_nav_tx;	/* 0x682 */
+	u16 ifs_slot;	/* 0x684 */
+	u16 PAD;		/* 0x686 */
+	u16 ifs_ctl;		/* 0x688 */
+	u16 PAD[0x3];	/* 0x68a - 0x68F */
+	u16 ifsstat;		/* 0x690 */
+	u16 ifsmedbusyctl;	/* 0x692 */
+	u16 iftxdur;		/* 0x694 */
+	u16 PAD[0x3];	/* 0x696 - 0x69b */
+	/* EDCF support in dot11macs */
+	u16 ifs_aifsn;	/* 0x69c */
+	u16 ifs_ctl1;	/* 0x69e */
+
+	/* slow clock registers */
+	u16 scc_ctl;		/* 0x6a0 */
+	u16 scc_timer_l;	/* 0x6a2 */
+	u16 scc_timer_h;	/* 0x6a4 */
+	u16 scc_frac;	/* 0x6a6 */
+	u16 scc_fastpwrup_dly;	/* 0x6a8 */
+	u16 scc_per;		/* 0x6aa */
+	u16 scc_per_frac;	/* 0x6ac */
+	u16 scc_cal_timer_l;	/* 0x6ae */
+	u16 scc_cal_timer_h;	/* 0x6b0 */
+	u16 PAD;		/* 0x6b2 */
+
+	u16 PAD[0x26];
+
+	/* NAV Block */
+	u16 nav_ctl;		/* 0x700 */
+	u16 navstat;		/* 0x702 */
+	u16 PAD[0x3e];	/* 0x702 - 0x77E */
+
+	/* WEP/PMQ Block *//* 0x780 - 0x7FE */
+	u16 PAD[0x20];	/* 0x780 - 0x7BE */
+
+	u16 wepctl;		/* 0x7C0 */
+	u16 wepivloc;	/* 0x7C2 */
+	u16 wepivkey;	/* 0x7C4 */
+	u16 wepwkey;		/* 0x7C6 */
+
+	u16 PAD[4];		/* 0x7C8 - 0x7CE */
+	u16 pcmctl;		/* 0X7D0 */
+	u16 pcmstat;		/* 0X7D2 */
+	u16 PAD[6];		/* 0x7D4 - 0x7DE */
+
+	u16 pmqctl;		/* 0x7E0 */
+	u16 pmqstatus;	/* 0x7E2 */
+	u16 pmqpat0;		/* 0x7E4 */
+	u16 pmqpat1;		/* 0x7E6 */
+	u16 pmqpat2;		/* 0x7E8 */
+
+	u16 pmqdat;		/* 0x7EA */
+	u16 pmqdator;	/* 0x7EC */
+	u16 pmqhst;		/* 0x7EE */
+	u16 pmqpath0;	/* 0x7F0 */
+	u16 pmqpath1;	/* 0x7F2 */
+	u16 pmqpath2;	/* 0x7F4 */
+	u16 pmqdath;		/* 0x7F6 */
+
+	u16 PAD[0x04];	/* 0x7F8 - 0x7FE */
+
+	/* SHM *//* 0x800 - 0xEFE */
+	u16 PAD[0x380];	/* 0x800 - 0xEFE */
+
+	/* SB configuration registers: 0xF00 */
+	sbconfig_t sbconfig;	/* sb config regs occupy top 256 bytes */
+} d11regs_t;
+
+#define	PIHR_BASE	0x0400	/* byte address of packed IHR region */
+
+/* biststatus */
+#define	BT_DONE		(1U << 31)	/* bist done */
+#define	BT_B2S		(1 << 30)	/* bist2 ram summary bit */
+
+/* intstatus and intmask */
+#define	I_PC		(1 << 10)	/* pci descriptor error */
+#define	I_PD		(1 << 11)	/* pci data error */
+#define	I_DE		(1 << 12)	/* descriptor protocol error */
+#define	I_RU		(1 << 13)	/* receive descriptor underflow */
+#define	I_RO		(1 << 14)	/* receive fifo overflow */
+#define	I_XU		(1 << 15)	/* transmit fifo underflow */
+#define	I_RI		(1 << 16)	/* receive interrupt */
+#define	I_XI		(1 << 24)	/* transmit interrupt */
+
+/* interrupt receive lazy */
+#define	IRL_TO_MASK		0x00ffffff	/* timeout */
+#define	IRL_FC_MASK		0xff000000	/* frame count */
+#define	IRL_FC_SHIFT		24	/* frame count */
+
+/* maccontrol register */
+#define	MCTL_GMODE		(1U << 31)
+#define	MCTL_DISCARD_PMQ	(1 << 30)
+#define	MCTL_WAKE		(1 << 26)
+#define	MCTL_HPS		(1 << 25)
+#define	MCTL_PROMISC		(1 << 24)
+#define	MCTL_KEEPBADFCS		(1 << 23)
+#define	MCTL_KEEPCONTROL	(1 << 22)
+#define	MCTL_PHYLOCK		(1 << 21)
+#define	MCTL_BCNS_PROMISC	(1 << 20)
+#define	MCTL_LOCK_RADIO		(1 << 19)
+#define	MCTL_AP			(1 << 18)
+#define	MCTL_INFRA		(1 << 17)
+#define	MCTL_BIGEND		(1 << 16)
+#define	MCTL_GPOUT_SEL_MASK	(3 << 14)
+#define	MCTL_GPOUT_SEL_SHIFT	14
+#define	MCTL_EN_PSMDBG		(1 << 13)
+#define	MCTL_IHR_EN		(1 << 10)
+#define	MCTL_SHM_UPPER		(1 <<  9)
+#define	MCTL_SHM_EN		(1 <<  8)
+#define	MCTL_PSM_JMP_0		(1 <<  2)
+#define	MCTL_PSM_RUN		(1 <<  1)
+#define	MCTL_EN_MAC		(1 <<  0)
+
+/* maccommand register */
+#define	MCMD_BCN0VLD		(1 <<  0)
+#define	MCMD_BCN1VLD		(1 <<  1)
+#define	MCMD_DIRFRMQVAL		(1 <<  2)
+#define	MCMD_CCA		(1 <<  3)
+#define	MCMD_BG_NOISE		(1 <<  4)
+#define	MCMD_SKIP_SHMINIT	(1 <<  5)	/* only used for simulation */
+#define MCMD_SAMPLECOLL		MCMD_SKIP_SHMINIT	/* reuse for sample collect */
+
+/* macintstatus/macintmask */
+#define	MI_MACSSPNDD		(1 <<  0)	/* MAC has gracefully suspended */
+#define	MI_BCNTPL		(1 <<  1)	/* beacon template available */
+#define	MI_TBTT			(1 <<  2)	/* TBTT indication */
+#define	MI_BCNSUCCESS		(1 <<  3)	/* beacon successfully tx'd */
+#define	MI_BCNCANCLD		(1 <<  4)	/* beacon canceled (IBSS) */
+#define	MI_ATIMWINEND		(1 <<  5)	/* end of ATIM-window (IBSS) */
+#define	MI_PMQ			(1 <<  6)	/* PMQ entries available */
+#define	MI_NSPECGEN_0		(1 <<  7)	/* non-specific gen-stat bits that are set by PSM */
+#define	MI_NSPECGEN_1		(1 <<  8)	/* non-specific gen-stat bits that are set by PSM */
+#define	MI_MACTXERR		(1 <<  9)	/* MAC level Tx error */
+#define	MI_NSPECGEN_3		(1 << 10)	/* non-specific gen-stat bits that are set by PSM */
+#define	MI_PHYTXERR		(1 << 11)	/* PHY Tx error */
+#define	MI_PME			(1 << 12)	/* Power Management Event */
+#define	MI_GP0			(1 << 13)	/* General-purpose timer0 */
+#define	MI_GP1			(1 << 14)	/* General-purpose timer1 */
+#define	MI_DMAINT		(1 << 15)	/* (ORed) DMA-interrupts */
+#define	MI_TXSTOP		(1 << 16)	/* MAC has completed a TX FIFO Suspend/Flush */
+#define	MI_CCA			(1 << 17)	/* MAC has completed a CCA measurement */
+#define	MI_BG_NOISE		(1 << 18)	/* MAC has collected background noise samples */
+#define	MI_DTIM_TBTT		(1 << 19)	/* MBSS DTIM TBTT indication */
+#define MI_PRQ			(1 << 20)	/* Probe response queue needs attention */
+#define	MI_PWRUP		(1 << 21)	/* Radio/PHY has been powered back up. */
+#define	MI_RESERVED3		(1 << 22)
+#define	MI_RESERVED2		(1 << 23)
+#define MI_RESERVED1		(1 << 25)
+/* MAC detected change on RF Disable input*/
+#define MI_RFDISABLE		(1 << 28)
+#define	MI_TFS			(1 << 29)	/* MAC has completed a TX */
+#define	MI_PHYCHANGED		(1 << 30)	/* A phy status change wrt G mode */
+#define	MI_TO			(1U << 31)	/* general purpose timeout */
+
+/* Mac capabilities registers */
+/* machwcap */
+#define	MCAP_TKIPMIC		0x80000000	/* TKIP MIC hardware present */
+
+/* pmqhost data */
+#define	PMQH_DATA_MASK		0xffff0000	/* data entry of head pmq entry */
+#define	PMQH_BSSCFG		0x00100000	/* PM entry for BSS config */
+#define	PMQH_PMOFF		0x00010000	/* PM Mode OFF: power save off */
+#define	PMQH_PMON		0x00020000	/* PM Mode ON: power save on */
+#define	PMQH_DASAT		0x00040000	/* Dis-associated or De-authenticated */
+#define	PMQH_ATIMFAIL		0x00080000	/* ATIM not acknowledged */
+#define	PMQH_DEL_ENTRY		0x00000001	/* delete head entry */
+#define	PMQH_DEL_MULT		0x00000002	/* delete head entry to cur read pointer -1 */
+#define	PMQH_OFLO		0x00000004	/* pmq overflow indication */
+#define	PMQH_NOT_EMPTY		0x00000008	/* entries are present in pmq */
+
+/* phydebug */
+#define	PDBG_CRS		(1 << 0)	/* phy is asserting carrier sense */
+#define	PDBG_TXA		(1 << 1)	/* phy is taking xmit byte from mac this cycle */
+#define	PDBG_TXF		(1 << 2)	/* mac is instructing the phy to transmit a frame */
+#define	PDBG_TXE		(1 << 3)	/* phy is signalling a transmit Error to the mac */
+#define	PDBG_RXF		(1 << 4)	/* phy detected the end of a valid frame preamble */
+#define	PDBG_RXS		(1 << 5)	/* phy detected the end of a valid PLCP header */
+#define	PDBG_RXFRG		(1 << 6)	/* rx start not asserted */
+#define	PDBG_RXV		(1 << 7)	/* mac is taking receive byte from phy this cycle */
+#define	PDBG_RFD		(1 << 16)	/* RF portion of the radio is disabled */
+
+/* objaddr register */
+#define	OBJADDR_SEL_MASK	0x000F0000
+#define	OBJADDR_UCM_SEL		0x00000000
+#define	OBJADDR_SHM_SEL		0x00010000
+#define	OBJADDR_SCR_SEL		0x00020000
+#define	OBJADDR_IHR_SEL		0x00030000
+#define	OBJADDR_RCMTA_SEL	0x00040000
+#define	OBJADDR_SRCHM_SEL	0x00060000
+#define	OBJADDR_WINC		0x01000000
+#define	OBJADDR_RINC		0x02000000
+#define	OBJADDR_AUTO_INC	0x03000000
+
+#define	WEP_PCMADDR		0x07d4
+#define	WEP_PCMDATA		0x07d6
+
+/* frmtxstatus */
+#define	TXS_V			(1 << 0)	/* valid bit */
+#define	TXS_STATUS_MASK		0xffff
+#define	TXS_FID_MASK		0xffff0000
+#define	TXS_FID_SHIFT		16
+
+/* frmtxstatus2 */
+#define	TXS_SEQ_MASK		0xffff
+#define	TXS_PTX_MASK		0xff0000
+#define	TXS_PTX_SHIFT		16
+#define	TXS_MU_MASK		0x01000000
+#define	TXS_MU_SHIFT		24
+
+/* clk_ctl_st */
+#define CCS_ERSRC_REQ_D11PLL	0x00000100	/* d11 core pll request */
+#define CCS_ERSRC_REQ_PHYPLL	0x00000200	/* PHY pll request */
+#define CCS_ERSRC_AVAIL_D11PLL	0x01000000	/* d11 core pll available */
+#define CCS_ERSRC_AVAIL_PHYPLL	0x02000000	/* PHY pll available */
+
+/* HT Cloclk Ctrl and Clock Avail for 4313 */
+#define CCS_ERSRC_REQ_HT    0x00000010	/* HT avail request */
+#define CCS_ERSRC_AVAIL_HT  0x00020000	/* HT clock available */
+
+/* tsf_cfprep register */
+#define	CFPREP_CBI_MASK		0xffffffc0
+#define	CFPREP_CBI_SHIFT	6
+#define	CFPREP_CFPP		0x00000001
+
+/* tx fifo sizes values are in terms of 256 byte blocks */
+#define TXFIFOCMD_RESET_MASK	(1 << 15)	/* reset */
+#define TXFIFOCMD_FIFOSEL_SHIFT	8	/* fifo */
+#define TXFIFO_FIFOTOP_SHIFT	8	/* fifo start */
+
+#define TXFIFO_START_BLK16	 65	/* Base address + 32 * 512 B/P */
+#define TXFIFO_START_BLK	 6	/* Base address + 6 * 256 B */
+#define TXFIFO_SIZE_UNIT	256	/* one unit corresponds to 256 bytes */
+#define MBSS16_TEMPLMEM_MINBLKS	65	/* one unit corresponds to 256 bytes */
+
+/* phy versions, PhyVersion:Revision field */
+#define	PV_AV_MASK		0xf000	/* analog block version */
+#define	PV_AV_SHIFT		12	/* analog block version bitfield offset */
+#define	PV_PT_MASK		0x0f00	/* phy type */
+#define	PV_PT_SHIFT		8	/* phy type bitfield offset */
+#define	PV_PV_MASK		0x000f	/* phy version */
+#define	PHY_TYPE(v)		((v & PV_PT_MASK) >> PV_PT_SHIFT)
+
+/* phy types, PhyVersion:PhyType field */
+#define	PHY_TYPE_N		4	/* N-Phy value */
+#define	PHY_TYPE_SSN		6	/* SSLPN-Phy value */
+#define	PHY_TYPE_LCN		8	/* LCN-Phy value */
+#define	PHY_TYPE_LCNXN		9	/* LCNXN-Phy value */
+#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
+
+/* analog types, PhyVersion:AnalogType field */
+#define	ANA_11N_013		5
+
+/* 802.11a PLCP header def */
+typedef struct ofdm_phy_hdr ofdm_phy_hdr_t;
+struct ofdm_phy_hdr {
+	u8 rlpt[3];		/* rate, length, parity, tail */
+	u16 service;
+	u8 pad;
+} __attribute__((packed));
+
+#define	D11A_PHY_HDR_GRATE(phdr)	((phdr)->rlpt[0] & 0x0f)
+#define	D11A_PHY_HDR_GRES(phdr)		(((phdr)->rlpt[0] >> 4) & 0x01)
+#define	D11A_PHY_HDR_GLENGTH(phdr)	(((u32 *)((phdr)->rlpt) >> 5) & 0x0fff)
+#define	D11A_PHY_HDR_GPARITY(phdr)	(((phdr)->rlpt[3] >> 1) & 0x01)
+#define	D11A_PHY_HDR_GTAIL(phdr)	(((phdr)->rlpt[3] >> 2) & 0x3f)
+
+/* rate encoded per 802.11a-1999 sec 17.3.4.1 */
+#define	D11A_PHY_HDR_SRATE(phdr, rate)		\
+	((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf))
+/* set reserved field to zero */
+#define	D11A_PHY_HDR_SRES(phdr)		((phdr)->rlpt[0] &= 0xef)
+/* length is number of octets in PSDU */
+#define	D11A_PHY_HDR_SLENGTH(phdr, length)	\
+	(*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \
+	(((length) & 0x0fff) << 5))
+/* set the tail to all zeros */
+#define	D11A_PHY_HDR_STAIL(phdr)	((phdr)->rlpt[3] &= 0x03)
+
+#define	D11A_PHY_HDR_LEN_L	3	/* low-rate part of PLCP header */
+#define	D11A_PHY_HDR_LEN_R	2	/* high-rate part of PLCP header */
+
+#define	D11A_PHY_TX_DELAY	(2)	/* 2.1 usec */
+
+#define	D11A_PHY_HDR_TIME	(4)	/* low-rate part of PLCP header */
+#define	D11A_PHY_PRE_TIME	(16)
+#define	D11A_PHY_PREHDR_TIME	(D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME)
+
+/* 802.11b PLCP header def */
+typedef struct cck_phy_hdr cck_phy_hdr_t;
+struct cck_phy_hdr {
+	u8 signal;
+	u8 service;
+	u16 length;
+	u16 crc;
+} __attribute__((packed));
+
+#define	D11B_PHY_HDR_LEN	6
+
+#define	D11B_PHY_TX_DELAY	(3)	/* 3.4 usec */
+
+#define	D11B_PHY_LHDR_TIME	(D11B_PHY_HDR_LEN << 3)
+#define	D11B_PHY_LPRE_TIME	(144)
+#define	D11B_PHY_LPREHDR_TIME	(D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME)
+
+#define	D11B_PHY_SHDR_TIME	(D11B_PHY_LHDR_TIME >> 1)
+#define	D11B_PHY_SPRE_TIME	(D11B_PHY_LPRE_TIME >> 1)
+#define	D11B_PHY_SPREHDR_TIME	(D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME)
+
+#define	D11B_PLCP_SIGNAL_LOCKED	(1 << 2)
+#define	D11B_PLCP_SIGNAL_LE	(1 << 7)
+
+#define MIMO_PLCP_MCS_MASK	0x7f	/* mcs index */
+#define MIMO_PLCP_40MHZ		0x80	/* 40 Hz frame */
+#define MIMO_PLCP_AMPDU		0x08	/* ampdu */
+
+#define WLC_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8))
+#define WLC_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8))
+#define WLC_SET_MIMO_PLCP_LEN(plcp, len) \
+	do { \
+		plcp[1] = len & 0xff; \
+		plcp[2] = ((len >> 8) & 0xff); \
+	} while (0);
+
+#define WLC_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU)
+#define WLC_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
+#define WLC_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
+
+/* The dot11a PLCP header is 5 bytes.  To simplify the software (so that we
+ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has
+ * padding added in the ucode.
+ */
+#define	D11_PHY_HDR_LEN	6
+
+/* TX DMA buffer header */
+typedef struct d11txh d11txh_t;
+struct d11txh {
+	u16 MacTxControlLow;	/* 0x0 */
+	u16 MacTxControlHigh;	/* 0x1 */
+	u16 MacFrameControl;	/* 0x2 */
+	u16 TxFesTimeNormal;	/* 0x3 */
+	u16 PhyTxControlWord;	/* 0x4 */
+	u16 PhyTxControlWord_1;	/* 0x5 */
+	u16 PhyTxControlWord_1_Fbr;	/* 0x6 */
+	u16 PhyTxControlWord_1_Rts;	/* 0x7 */
+	u16 PhyTxControlWord_1_FbrRts;	/* 0x8 */
+	u16 MainRates;	/* 0x9 */
+	u16 XtraFrameTypes;	/* 0xa */
+	u8 IV[16];		/* 0x0b - 0x12 */
+	u8 TxFrameRA[6];	/* 0x13 - 0x15 */
+	u16 TxFesTimeFallback;	/* 0x16 */
+	u8 RTSPLCPFallback[6];	/* 0x17 - 0x19 */
+	u16 RTSDurFallback;	/* 0x1a */
+	u8 FragPLCPFallback[6];	/* 0x1b - 1d */
+	u16 FragDurFallback;	/* 0x1e */
+	u16 MModeLen;	/* 0x1f */
+	u16 MModeFbrLen;	/* 0x20 */
+	u16 TstampLow;	/* 0x21 */
+	u16 TstampHigh;	/* 0x22 */
+	u16 ABI_MimoAntSel;	/* 0x23 */
+	u16 PreloadSize;	/* 0x24 */
+	u16 AmpduSeqCtl;	/* 0x25 */
+	u16 TxFrameID;	/* 0x26 */
+	u16 TxStatus;	/* 0x27 */
+	u16 MaxNMpdus;	/* 0x28 */
+	u16 MaxABytes_MRT;	/* 0x29 */
+	u16 MaxABytes_FBR;	/* 0x2a */
+	u16 MinMBytes;	/* 0x2b */
+	u8 RTSPhyHeader[D11_PHY_HDR_LEN];	/* 0x2c - 0x2e */
+	struct ieee80211_rts rts_frame;	/* 0x2f - 0x36 */
+	u16 PAD;		/* 0x37 */
+} __attribute__((packed));
+
+#define	D11_TXH_LEN		112	/* bytes */
+
+/* Frame Types */
+#define FT_CCK	0
+#define FT_OFDM	1
+#define FT_HT	2
+#define FT_N	3
+
+/* Position of MPDU inside A-MPDU; indicated with bits 10:9 of MacTxControlLow */
+#define TXC_AMPDU_SHIFT		9	/* shift for ampdu settings */
+#define TXC_AMPDU_NONE		0	/* Regular MPDU, not an A-MPDU */
+#define TXC_AMPDU_FIRST		1	/* first MPDU of an A-MPDU */
+#define TXC_AMPDU_MIDDLE	2	/* intermediate MPDU of an A-MPDU */
+#define TXC_AMPDU_LAST		3	/* last (or single) MPDU of an A-MPDU */
+
+/* MacTxControlLow */
+#define TXC_AMIC		0x8000
+#define	TXC_SENDCTS		0x0800
+#define TXC_AMPDU_MASK		0x0600
+#define TXC_BW_40		0x0100
+#define TXC_FREQBAND_5G		0x0080
+#define	TXC_DFCS		0x0040
+#define	TXC_IGNOREPMQ		0x0020
+#define	TXC_HWSEQ		0x0010
+#define	TXC_STARTMSDU		0x0008
+#define	TXC_SENDRTS		0x0004
+#define	TXC_LONGFRAME		0x0002
+#define	TXC_IMMEDACK		0x0001
+
+/* MacTxControlHigh */
+#define TXC_PREAMBLE_RTS_FB_SHORT	0x8000	/* RTS fallback preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_MAIN_SHORT	0x4000	/* RTS main rate preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_DATA_FB_SHORT	0x2000	/* Main fallback rate preamble type
+						 * 1 = SHORT for OFDM/GF for MIMO
+						 * 0 = LONG for CCK/MM for MIMO
+						 */
+/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */
+#define	TXC_AMPDU_FBR		0x1000	/* use fallback rate for this AMPDU */
+#define	TXC_SECKEY_MASK		0x0FF0
+#define	TXC_SECKEY_SHIFT	4
+#define	TXC_ALT_TXPWR		0x0008	/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+#define	TXC_SECTYPE_MASK	0x0007
+#define	TXC_SECTYPE_SHIFT	0
+
+/* Null delimiter for Fallback rate */
+#define AMPDU_FBR_NULL_DELIM  5	/* Location of Null delimiter count for AMPDU */
+
+/* PhyTxControl for Mimophy */
+#define	PHY_TXC_PWR_MASK	0xFC00
+#define	PHY_TXC_PWR_SHIFT	10
+#define	PHY_TXC_ANT_MASK	0x03C0	/* bit 6, 7, 8, 9 */
+#define	PHY_TXC_ANT_SHIFT	6
+#define	PHY_TXC_ANT_0_1		0x00C0	/* auto, last rx */
+#define	PHY_TXC_LCNPHY_ANT_LAST	0x0000
+#define	PHY_TXC_ANT_3		0x0200	/* virtual antenna 3 */
+#define	PHY_TXC_ANT_2		0x0100	/* virtual antenna 2 */
+#define	PHY_TXC_ANT_1		0x0080	/* virtual antenna 1 */
+#define	PHY_TXC_ANT_0		0x0040	/* virtual antenna 0 */
+#define	PHY_TXC_SHORT_HDR	0x0010
+
+#define	PHY_TXC_OLD_ANT_0	0x0000
+#define	PHY_TXC_OLD_ANT_1	0x0100
+#define	PHY_TXC_OLD_ANT_LAST	0x0300
+
+/* PhyTxControl_1 for Mimophy */
+#define PHY_TXC1_BW_MASK		0x0007
+#define PHY_TXC1_BW_10MHZ		0
+#define PHY_TXC1_BW_10MHZ_UP		1
+#define PHY_TXC1_BW_20MHZ		2
+#define PHY_TXC1_BW_20MHZ_UP		3
+#define PHY_TXC1_BW_40MHZ		4
+#define PHY_TXC1_BW_40MHZ_DUP		5
+#define PHY_TXC1_MODE_SHIFT		3
+#define PHY_TXC1_MODE_MASK		0x0038
+#define PHY_TXC1_MODE_SISO		0
+#define PHY_TXC1_MODE_CDD		1
+#define PHY_TXC1_MODE_STBC		2
+#define PHY_TXC1_MODE_SDM		3
+
+/* PhyTxControl for HTphy that are different from Mimophy */
+#define	PHY_TXC_HTANT_MASK		0x3fC0	/* bit 6, 7, 8, 9, 10, 11, 12, 13 */
+
+/* XtraFrameTypes */
+#define XFTS_RTS_FT_SHIFT	2
+#define XFTS_FBRRTS_FT_SHIFT	4
+#define XFTS_CHANNEL_SHIFT	8
+
+/* Antenna diversity bit in ant_wr_settle */
+#define	PHY_AWS_ANTDIV		0x2000
+
+/* IFS ctl */
+#define IFS_USEEDCF	(1 << 2)
+
+/* IFS ctl1 */
+#define IFS_CTL1_EDCRS	(1 << 3)
+#define IFS_CTL1_EDCRS_20L (1 << 4)
+#define IFS_CTL1_EDCRS_40 (1 << 5)
+
+/* ABI_MimoAntSel */
+#define ABI_MAS_ADDR_BMP_IDX_MASK	0x0f00
+#define ABI_MAS_ADDR_BMP_IDX_SHIFT	8
+#define ABI_MAS_FBR_ANT_PTN_MASK	0x00f0
+#define ABI_MAS_FBR_ANT_PTN_SHIFT	4
+#define ABI_MAS_MRT_ANT_PTN_MASK	0x000f
+
+/* tx status packet */
+typedef struct tx_status tx_status_t;
+struct tx_status {
+	u16 framelen;
+	u16 PAD;
+	u16 frameid;
+	u16 status;
+	u16 lasttxtime;
+	u16 sequence;
+	u16 phyerr;
+	u16 ackphyrxsh;
+} __attribute__((packed));
+
+#define	TXSTATUS_LEN	16
+
+/* status field bit definitions */
+#define	TX_STATUS_FRM_RTX_MASK	0xF000
+#define	TX_STATUS_FRM_RTX_SHIFT	12
+#define	TX_STATUS_RTS_RTX_MASK	0x0F00
+#define	TX_STATUS_RTS_RTX_SHIFT	8
+#define TX_STATUS_MASK		0x00FE
+#define	TX_STATUS_PMINDCTD	(1 << 7)	/* PM mode indicated to AP */
+#define	TX_STATUS_INTERMEDIATE	(1 << 6)	/* intermediate or 1st ampdu pkg */
+#define	TX_STATUS_AMPDU		(1 << 5)	/* AMPDU status */
+#define TX_STATUS_SUPR_MASK	0x1C	/* suppress status bits (4:2) */
+#define TX_STATUS_SUPR_SHIFT	2
+#define	TX_STATUS_ACK_RCV	(1 << 1)	/* ACK received */
+#define	TX_STATUS_VALID		(1 << 0)	/* Tx status valid */
+#define	TX_STATUS_NO_ACK	0
+
+/* suppress status reason codes */
+#define	TX_STATUS_SUPR_PMQ	(1 << 2)	/* PMQ entry */
+#define	TX_STATUS_SUPR_FLUSH	(2 << 2)	/* flush request */
+#define	TX_STATUS_SUPR_FRAG	(3 << 2)	/* previous frag failure */
+#define	TX_STATUS_SUPR_TBTT	(3 << 2)	/* SHARED: Probe response supr for TBTT */
+#define	TX_STATUS_SUPR_BADCH	(4 << 2)	/* channel mismatch */
+#define	TX_STATUS_SUPR_EXPTIME	(5 << 2)	/* lifetime expiry */
+#define	TX_STATUS_SUPR_UF	(6 << 2)	/* underflow */
+
+/* Unexpected tx status for rate update */
+#define TX_STATUS_UNEXP(status) \
+	((((status) & TX_STATUS_INTERMEDIATE) != 0) && \
+	 TX_STATUS_UNEXP_AMPDU(status))
+
+/* Unexpected tx status for A-MPDU rate update */
+#define TX_STATUS_UNEXP_AMPDU(status) \
+	((((status) & TX_STATUS_SUPR_MASK) != 0) && \
+	 (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME))
+
+#define TX_STATUS_BA_BMAP03_MASK	0xF000	/* ba bitmap 0:3 in 1st pkg */
+#define TX_STATUS_BA_BMAP03_SHIFT	12	/* ba bitmap 0:3 in 1st pkg */
+#define TX_STATUS_BA_BMAP47_MASK	0x001E	/* ba bitmap 4:7 in 2nd pkg */
+#define TX_STATUS_BA_BMAP47_SHIFT	3	/* ba bitmap 4:7 in 2nd pkg */
+
+/* RXE (Receive Engine) */
+
+/* RCM_CTL */
+#define	RCM_INC_MASK_H		0x0080
+#define	RCM_INC_MASK_L		0x0040
+#define	RCM_INC_DATA		0x0020
+#define	RCM_INDEX_MASK		0x001F
+#define	RCM_SIZE		15
+
+#define	RCM_MAC_OFFSET		0	/* current MAC address */
+#define	RCM_BSSID_OFFSET	3	/* current BSSID address */
+#define	RCM_F_BSSID_0_OFFSET	6	/* foreign BSS CFP tracking */
+#define	RCM_F_BSSID_1_OFFSET	9	/* foreign BSS CFP tracking */
+#define	RCM_F_BSSID_2_OFFSET	12	/* foreign BSS CFP tracking */
+
+#define RCM_WEP_TA0_OFFSET	16
+#define RCM_WEP_TA1_OFFSET	19
+#define RCM_WEP_TA2_OFFSET	22
+#define RCM_WEP_TA3_OFFSET	25
+
+/* PSM Block */
+
+/* psm_phy_hdr_param bits */
+#define MAC_PHY_RESET		1
+#define MAC_PHY_CLOCK_EN	2
+#define MAC_PHY_FORCE_CLK	4
+
+/* WEP Block */
+
+/* WEP_WKEY */
+#define	WKEY_START		(1 << 8)
+#define	WKEY_SEL_MASK		0x1F
+
+/* WEP data formats */
+
+/* the number of RCMTA entries */
+#define RCMTA_SIZE 50
+
+#define M_ADDR_BMP_BLK		(0x37e * 2)
+#define M_ADDR_BMP_BLK_SZ	12
+
+#define ADDR_BMP_RA		(1 << 0)	/* Receiver Address (RA) */
+#define ADDR_BMP_TA		(1 << 1)	/* Transmitter Address (TA) */
+#define ADDR_BMP_BSSID		(1 << 2)	/* BSSID */
+#define ADDR_BMP_AP		(1 << 3)	/* Infra-BSS Access Point (AP) */
+#define ADDR_BMP_STA		(1 << 4)	/* Infra-BSS Station (STA) */
+#define ADDR_BMP_RESERVED1	(1 << 5)
+#define ADDR_BMP_RESERVED2	(1 << 6)
+#define ADDR_BMP_RESERVED3	(1 << 7)
+#define ADDR_BMP_BSS_IDX_MASK	(3 << 8)	/* BSS control block index */
+#define ADDR_BMP_BSS_IDX_SHIFT	8
+
+#define	WSEC_MAX_RCMTA_KEYS	54
+
+/* max keys in M_TKMICKEYS_BLK */
+#define	WSEC_MAX_TKMIC_ENGINE_KEYS		12	/* 8 + 4 default */
+
+/* max RXE match registers */
+#define WSEC_MAX_RXE_KEYS	4
+
+/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */
+/* SKL (Security Key Lookup) */
+#define	SKL_ALGO_MASK		0x0007
+#define	SKL_ALGO_SHIFT		0
+#define	SKL_KEYID_MASK		0x0008
+#define	SKL_KEYID_SHIFT		3
+#define	SKL_INDEX_MASK		0x03F0
+#define	SKL_INDEX_SHIFT		4
+#define	SKL_GRP_ALGO_MASK	0x1c00
+#define	SKL_GRP_ALGO_SHIFT	10
+
+/* additional bits defined for IBSS group key support */
+#define	SKL_IBSS_INDEX_MASK	0x01F0
+#define	SKL_IBSS_INDEX_SHIFT	4
+#define	SKL_IBSS_KEYID1_MASK	0x0600
+#define	SKL_IBSS_KEYID1_SHIFT	9
+#define	SKL_IBSS_KEYID2_MASK	0x1800
+#define	SKL_IBSS_KEYID2_SHIFT	11
+#define	SKL_IBSS_KEYALGO_MASK	0xE000
+#define	SKL_IBSS_KEYALGO_SHIFT	13
+
+#define	WSEC_MODE_OFF		0
+#define	WSEC_MODE_HW		1
+#define	WSEC_MODE_SW		2
+
+#define	WSEC_ALGO_OFF		0
+#define	WSEC_ALGO_WEP1		1
+#define	WSEC_ALGO_TKIP		2
+#define	WSEC_ALGO_AES		3
+#define	WSEC_ALGO_WEP128	4
+#define	WSEC_ALGO_AES_LEGACY	5
+#define	WSEC_ALGO_NALG		6
+
+#define	AES_MODE_NONE		0
+#define	AES_MODE_CCM		1
+
+/* WEP_CTL (Rev 0) */
+#define	WECR0_KEYREG_SHIFT	0
+#define	WECR0_KEYREG_MASK	0x7
+#define	WECR0_DECRYPT		(1 << 3)
+#define	WECR0_IVINLINE		(1 << 4)
+#define	WECR0_WEPALG_SHIFT	5
+#define	WECR0_WEPALG_MASK	(0x7 << 5)
+#define	WECR0_WKEYSEL_SHIFT	8
+#define	WECR0_WKEYSEL_MASK	(0x7 << 8)
+#define	WECR0_WKEYSTART		(1 << 11)
+#define	WECR0_WEPINIT		(1 << 14)
+#define	WECR0_ICVERR		(1 << 15)
+
+/* Frame template map byte offsets */
+#define	T_ACTS_TPL_BASE		(0)
+#define	T_NULL_TPL_BASE		(0xc * 2)
+#define	T_QNULL_TPL_BASE	(0x1c * 2)
+#define	T_RR_TPL_BASE		(0x2c * 2)
+#define	T_BCN0_TPL_BASE		(0x34 * 2)
+#define	T_PRS_TPL_BASE		(0x134 * 2)
+#define	T_BCN1_TPL_BASE		(0x234 * 2)
+#define T_TX_FIFO_TXRAM_BASE	(T_ACTS_TPL_BASE + (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
+
+#define T_BA_TPL_BASE		T_QNULL_TPL_BASE	/* template area for BA */
+
+#define T_RAM_ACCESS_SZ		4	/* template ram is 4 byte access only */
+
+/* Shared Mem byte offsets */
+
+/* Location where the ucode expects the corerev */
+#define	M_MACHW_VER		(0x00b * 2)
+
+/* Location where the ucode expects the MAC capabilities */
+#define	M_MACHW_CAP_L		(0x060 * 2)
+#define	M_MACHW_CAP_H	(0x061 * 2)
+
+/* WME shared memory */
+#define M_EDCF_STATUS_OFF	(0x007 * 2)
+#define M_TXF_CUR_INDEX		(0x018 * 2)
+#define M_EDCF_QINFO		(0x120 * 2)
+
+/* PS-mode related parameters */
+#define	M_DOT11_SLOT		(0x008 * 2)
+#define	M_DOT11_DTIMPERIOD	(0x009 * 2)
+#define	M_NOSLPZNATDTIM		(0x026 * 2)
+
+/* Beacon-related parameters */
+#define	M_BCN0_FRM_BYTESZ	(0x00c * 2)	/* Bcn 0 template length */
+#define	M_BCN1_FRM_BYTESZ	(0x00d * 2)	/* Bcn 1 template length */
+#define	M_BCN_TXTSF_OFFSET	(0x00e * 2)
+#define	M_TIMBPOS_INBEACON	(0x00f * 2)
+#define	M_SFRMTXCNTFBRTHSD	(0x022 * 2)
+#define	M_LFRMTXCNTFBRTHSD	(0x023 * 2)
+#define	M_BCN_PCTLWD		(0x02a * 2)
+#define M_BCN_LI		(0x05b * 2)	/* beacon listen interval */
+
+/* MAX Rx Frame len */
+#define M_MAXRXFRM_LEN		(0x010 * 2)
+
+/* ACK/CTS related params */
+#define	M_RSP_PCTLWD		(0x011 * 2)
+
+/* Hardware Power Control */
+#define M_TXPWR_N		(0x012 * 2)
+#define M_TXPWR_TARGET		(0x013 * 2)
+#define M_TXPWR_MAX		(0x014 * 2)
+#define M_TXPWR_CUR		(0x019 * 2)
+
+/* Rx-related parameters */
+#define	M_RX_PAD_DATA_OFFSET	(0x01a * 2)
+
+/* WEP Shared mem data */
+#define	M_SEC_DEFIVLOC		(0x01e * 2)
+#define	M_SEC_VALNUMSOFTMCHTA	(0x01f * 2)
+#define	M_PHYVER		(0x028 * 2)
+#define	M_PHYTYPE		(0x029 * 2)
+#define	M_SECRXKEYS_PTR		(0x02b * 2)
+#define	M_TKMICKEYS_PTR		(0x059 * 2)
+#define	M_SECKINDXALGO_BLK	(0x2ea * 2)
+#define M_SECKINDXALGO_BLK_SZ	54
+#define	M_SECPSMRXTAMCH_BLK	(0x2fa * 2)
+#define	M_TKIP_TSC_TTAK		(0x18c * 2)
+#define	D11_MAX_KEY_SIZE	16
+
+#define	M_MAX_ANTCNT		(0x02e * 2)	/* antenna swap threshold */
+
+/* Probe response related parameters */
+#define	M_SSIDLEN		(0x024 * 2)
+#define	M_PRB_RESP_FRM_LEN	(0x025 * 2)
+#define	M_PRS_MAXTIME		(0x03a * 2)
+#define	M_SSID			(0xb0 * 2)
+#define	M_CTXPRS_BLK		(0xc0 * 2)
+#define	C_CTX_PCTLWD_POS	(0x4 * 2)
+
+/* Delta between OFDM and CCK power in CCK power boost mode */
+#define M_OFDM_OFFSET		(0x027 * 2)
+
+/* TSSI for last 4 11b/g CCK packets transmitted */
+#define	M_B_TSSI_0		(0x02c * 2)
+#define	M_B_TSSI_1		(0x02d * 2)
+
+/* Host flags to turn on ucode options */
+#define	M_HOST_FLAGS1		(0x02f * 2)
+#define	M_HOST_FLAGS2		(0x030 * 2)
+#define	M_HOST_FLAGS3		(0x031 * 2)
+#define	M_HOST_FLAGS4		(0x03c * 2)
+#define	M_HOST_FLAGS5		(0x06a * 2)
+#define	M_HOST_FLAGS_SZ		16
+
+#define M_RADAR_REG		(0x033 * 2)
+
+/* TSSI for last 4 11a OFDM packets transmitted */
+#define	M_A_TSSI_0		(0x034 * 2)
+#define	M_A_TSSI_1		(0x035 * 2)
+
+/* noise interference measurement */
+#define M_NOISE_IF_COUNT	(0x034 * 2)
+#define M_NOISE_IF_TIMEOUT	(0x035 * 2)
+
+#define	M_RF_RX_SP_REG1		(0x036 * 2)
+
+/* TSSI for last 4 11g OFDM packets transmitted */
+#define	M_G_TSSI_0		(0x038 * 2)
+#define	M_G_TSSI_1		(0x039 * 2)
+
+/* Background noise measure */
+#define	M_JSSI_0		(0x44 * 2)
+#define	M_JSSI_1		(0x45 * 2)
+#define	M_JSSI_AUX		(0x46 * 2)
+
+#define	M_CUR_2050_RADIOCODE	(0x47 * 2)
+
+/* TX fifo sizes */
+#define M_FIFOSIZE0		(0x4c * 2)
+#define M_FIFOSIZE1		(0x4d * 2)
+#define M_FIFOSIZE2		(0x4e * 2)
+#define M_FIFOSIZE3		(0x4f * 2)
+#define D11_MAX_TX_FRMS		32	/* max frames allowed in tx fifo */
+
+/* Current channel number plus upper bits */
+#define M_CURCHANNEL		(0x50 * 2)
+#define D11_CURCHANNEL_5G	0x0100;
+#define D11_CURCHANNEL_40	0x0200;
+#define D11_CURCHANNEL_MAX	0x00FF;
+
+/* last posted frameid on the bcmc fifo */
+#define M_BCMC_FID		(0x54 * 2)
+#define INVALIDFID		0xffff
+
+/* extended beacon phyctl bytes for 11N */
+#define	M_BCN_PCTL1WD		(0x058 * 2)
+
+/* idle busy ratio to duty_cycle requirement  */
+#define M_TX_IDLE_BUSY_RATIO_X_16_CCK  (0x52 * 2)
+#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2)
+
+/* CW RSSI for LCNPHY */
+#define M_LCN_RSSI_0 		0x1332
+#define M_LCN_RSSI_1 		0x1338
+#define M_LCN_RSSI_2 		0x133e
+#define M_LCN_RSSI_3 		0x1344
+
+/* SNR for LCNPHY */
+#define M_LCN_SNR_A_0 	0x1334
+#define M_LCN_SNR_B_0 	0x1336
+
+#define M_LCN_SNR_A_1 	0x133a
+#define M_LCN_SNR_B_1 	0x133c
+
+#define M_LCN_SNR_A_2 	0x1340
+#define M_LCN_SNR_B_2 	0x1342
+
+#define M_LCN_SNR_A_3 	0x1346
+#define M_LCN_SNR_B_3 	0x1348
+
+#define M_LCN_LAST_RESET 	(81*2)
+#define M_LCN_LAST_LOC	(63*2)
+#define M_LCNPHY_RESET_STATUS (4902)
+#define M_LCNPHY_DSC_TIME	(0x98d*2)
+#define M_LCNPHY_RESET_CNT_DSC (0x98b*2)
+#define M_LCNPHY_RESET_CNT	(0x98c*2)
+
+/* Rate table offsets */
+#define	M_RT_DIRMAP_A		(0xe0 * 2)
+#define	M_RT_BBRSMAP_A		(0xf0 * 2)
+#define	M_RT_DIRMAP_B		(0x100 * 2)
+#define	M_RT_BBRSMAP_B		(0x110 * 2)
+
+/* Rate table entry offsets */
+#define	M_RT_PRS_PLCP_POS	10
+#define	M_RT_PRS_DUR_POS	16
+#define	M_RT_OFDM_PCTL1_POS	18
+
+#define M_20IN40_IQ			(0x380 * 2)
+
+/* SHM locations where ucode stores the current power index */
+#define M_CURR_IDX1		(0x384 * 2)
+#define M_CURR_IDX2		(0x387 * 2)
+
+#define M_BSCALE_ANT0	(0x5e * 2)
+#define M_BSCALE_ANT1	(0x5f * 2)
+
+/* Antenna Diversity Testing */
+#define M_MIMO_ANTSEL_RXDFLT	(0x63 * 2)
+#define M_ANTSEL_CLKDIV	(0x61 * 2)
+#define M_MIMO_ANTSEL_TXDFLT	(0x64 * 2)
+
+#define M_MIMO_MAXSYM	(0x5d * 2)
+#define MIMO_MAXSYM_DEF		0x8000	/* 32k */
+#define MIMO_MAXSYM_MAX		0xffff	/* 64k */
+
+#define M_WATCHDOG_8TU		(0x1e * 2)
+#define WATCHDOG_8TU_DEF	5
+#define WATCHDOG_8TU_MAX	10
+
+/* Manufacturing Test Variables */
+#define M_PKTENG_CTRL		(0x6c * 2)	/* PER test mode */
+#define M_PKTENG_IFS		(0x6d * 2)	/* IFS for TX mode */
+#define M_PKTENG_FRMCNT_LO		(0x6e * 2)	/* Lower word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_HI		(0x6f * 2)	/* Upper word of tx frmcnt/rx lostcnt */
+
+/* Index variation in vbat ripple */
+#define M_LCN_PWR_IDX_MAX	(0x67 * 2)	/* highest index read by ucode */
+#define M_LCN_PWR_IDX_MIN	(0x66 * 2)	/* lowest index read by ucode */
+
+/* M_PKTENG_CTRL bit definitions */
+#define M_PKTENG_MODE_TX		0x0001
+#define M_PKTENG_MODE_TX_RIFS	        0x0004
+#define M_PKTENG_MODE_TX_CTS            0x0008
+#define M_PKTENG_MODE_RX		0x0002
+#define M_PKTENG_MODE_RX_WITH_ACK	0x0402
+#define M_PKTENG_MODE_MASK		0x0003
+#define M_PKTENG_FRMCNT_VLD		0x0100	/* TX frames indicated in the frmcnt reg */
+
+/* Sample Collect parameters (bitmap and type) */
+#define M_SMPL_COL_BMP		(0x37d * 2)	/* Trigger bitmap for sample collect */
+#define M_SMPL_COL_CTL		(0x3b2 * 2)	/* Sample collect type */
+
+#define ANTSEL_CLKDIV_4MHZ	6
+#define MIMO_ANTSEL_BUSY	0x4000	/* bit 14 (busy) */
+#define MIMO_ANTSEL_SEL		0x8000	/* bit 15 write the value */
+#define MIMO_ANTSEL_WAIT	50	/* 50us wait */
+#define MIMO_ANTSEL_OVERRIDE	0x8000	/* flag */
+
+typedef struct shm_acparams shm_acparams_t;
+struct shm_acparams {
+	u16 txop;
+	u16 cwmin;
+	u16 cwmax;
+	u16 cwcur;
+	u16 aifs;
+	u16 bslots;
+	u16 reggap;
+	u16 status;
+	u16 rsvd[8];
+} __attribute__((packed));
+#define M_EDCF_QLEN	(16 * 2)
+
+#define WME_STATUS_NEWAC	(1 << 8)
+
+/* M_HOST_FLAGS */
+#define MHFMAX		5	/* Number of valid hostflag half-word (u16) */
+#define MHF1		0	/* Hostflag 1 index */
+#define MHF2		1	/* Hostflag 2 index */
+#define MHF3		2	/* Hostflag 3 index */
+#define MHF4		3	/* Hostflag 4 index */
+#define MHF5		4	/* Hostflag 5 index */
+
+/* Flags in M_HOST_FLAGS */
+#define	MHF1_ANTDIV		0x0001	/* Enable ucode antenna diversity help */
+#define	MHF1_EDCF		0x0100	/* Enable EDCF access control */
+#define MHF1_IQSWAP_WAR		0x0200
+#define	MHF1_FORCEFASTCLK	0x0400	/* Disable Slow clock request, for corerev < 11 */
+
+/* Flags in M_HOST_FLAGS2 */
+#define MHF2_PCISLOWCLKWAR	0x0008	/* PR16165WAR : Enable ucode PCI slow clock WAR */
+#define MHF2_TXBCMC_NOW		0x0040	/* Flush BCMC FIFO immediately */
+#define MHF2_HWPWRCTL		0x0080	/* Enable ucode/hw power control */
+#define MHF2_NPHY40MHZ_WAR	0x0800
+
+/* Flags in M_HOST_FLAGS3 */
+#define MHF3_ANTSEL_EN		0x0001	/* enabled mimo antenna selection */
+#define MHF3_ANTSEL_MODE	0x0002	/* antenna selection mode: 0: 2x3, 1: 2x4 */
+#define MHF3_RESERVED1		0x0004
+#define MHF3_RESERVED2		0x0008
+#define MHF3_NPHY_MLADV_WAR	0x0010
+
+/* Flags in M_HOST_FLAGS4 */
+#define MHF4_BPHY_TXCORE0	0x0080	/* force bphy Tx on core 0 (board level WAR) */
+#define MHF4_EXTPA_ENABLE  	0x4000	/* for 4313A0 FEM boards */
+
+/* Flags in M_HOST_FLAGS5 */
+#define MHF5_4313_GPIOCTRL	0x0001
+#define MHF5_RESERVED1		0x0002
+#define MHF5_RESERVED2		0x0004
+/* Radio power setting for ucode */
+#define	M_RADIO_PWR		(0x32 * 2)
+
+/* phy noise recorded by ucode right after tx */
+#define	M_PHY_NOISE		(0x037 * 2)
+#define	PHY_NOISE_MASK		0x00ff
+
+/* Receive Frame Data Header for 802.11b DCF-only frames */
+typedef struct d11rxhdr d11rxhdr_t;
+struct d11rxhdr {
+	u16 RxFrameSize;	/* Actual byte length of the frame data received */
+	u16 PAD;
+	u16 PhyRxStatus_0;	/* PhyRxStatus 15:0 */
+	u16 PhyRxStatus_1;	/* PhyRxStatus 31:16 */
+	u16 PhyRxStatus_2;	/* PhyRxStatus 47:32 */
+	u16 PhyRxStatus_3;	/* PhyRxStatus 63:48 */
+	u16 PhyRxStatus_4;	/* PhyRxStatus 79:64 */
+	u16 PhyRxStatus_5;	/* PhyRxStatus 95:80 */
+	u16 RxStatus1;	/* MAC Rx Status */
+	u16 RxStatus2;	/* extended MAC Rx status */
+	u16 RxTSFTime;	/* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
+	u16 RxChan;		/* gain code, channel radio code, and phy type */
+} __attribute__((packed));
+
+#define	RXHDR_LEN		24	/* sizeof d11rxhdr_t */
+#define	FRAMELEN(h)		((h)->RxFrameSize)
+
+typedef struct wlc_d11rxhdr wlc_d11rxhdr_t;
+struct wlc_d11rxhdr {
+	d11rxhdr_t rxhdr;
+	u32 tsf_l;		/* TSF_L reading */
+	s8 rssi;		/* computed instanteneous rssi in BMAC */
+	s8 rxpwr0;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
+	s8 rxpwr1;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
+	s8 do_rssi_ma;	/* do per-pkt sampling for per-antenna ma in HIGH */
+	s8 rxpwr[WL_RSSI_ANT_MAX];	/* rssi for supported antennas */
+} __attribute__((packed));
+
+/* PhyRxStatus_0: */
+#define	PRXS0_FT_MASK		0x0003	/* NPHY only: CCK, OFDM, preN, N */
+#define	PRXS0_CLIP_MASK		0x000C	/* NPHY only: clip count adjustment steps by AGC */
+#define	PRXS0_CLIP_SHIFT	2
+#define	PRXS0_UNSRATE		0x0010	/* PHY received a frame with unsupported rate */
+#define	PRXS0_RXANT_UPSUBBAND	0x0020	/* GPHY: rx ant, NPHY: upper sideband */
+#define	PRXS0_LCRS		0x0040	/* CCK frame only: lost crs during cck frame reception */
+#define	PRXS0_SHORTH		0x0080	/* Short Preamble */
+#define	PRXS0_PLCPFV		0x0100	/* PLCP violation */
+#define	PRXS0_PLCPHCF		0x0200	/* PLCP header integrity check failed */
+#define	PRXS0_GAIN_CTL		0x4000	/* legacy PHY gain control */
+#define PRXS0_ANTSEL_MASK	0xF000	/* NPHY: Antennas used for received frame, bitmask */
+#define PRXS0_ANTSEL_SHIFT	0x12
+
+/* subfield PRXS0_FT_MASK */
+#define	PRXS0_CCK		0x0000
+#define	PRXS0_OFDM		0x0001	/* valid only for G phy, use rxh->RxChan for A phy */
+#define	PRXS0_PREN		0x0002
+#define	PRXS0_STDN		0x0003
+
+/* subfield PRXS0_ANTSEL_MASK */
+#define PRXS0_ANTSEL_0		0x0	/* antenna 0 is used */
+#define PRXS0_ANTSEL_1		0x2	/* antenna 1 is used */
+#define PRXS0_ANTSEL_2		0x4	/* antenna 2 is used */
+#define PRXS0_ANTSEL_3		0x8	/* antenna 3 is used */
+
+/* PhyRxStatus_1: */
+#define	PRXS1_JSSI_MASK		0x00FF
+#define	PRXS1_JSSI_SHIFT	0
+#define	PRXS1_SQ_MASK		0xFF00
+#define	PRXS1_SQ_SHIFT		8
+
+/* nphy PhyRxStatus_1: */
+#define PRXS1_nphy_PWR0_MASK	0x00FF
+#define PRXS1_nphy_PWR1_MASK	0xFF00
+
+/* HTPHY Rx Status defines */
+/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */
+#define PRXS0_BAND	        0x0400	/* 0 = 2.4G, 1 = 5G */
+#define PRXS0_RSVD	        0x0800	/* reserved; set to 0 */
+#define PRXS0_UNUSED	        0xF000	/* unused and not defined; set to 0 */
+
+/* htphy PhyRxStatus_1: */
+#define PRXS1_HTPHY_CORE_MASK	0x000F	/* core enables for {3..0}, 0=disabled, 1=enabled */
+#define PRXS1_HTPHY_ANTCFG_MASK	0x00F0	/* antenna configation */
+#define PRXS1_HTPHY_MMPLCPLenL_MASK	0xFF00	/* Mixmode PLCP Length low byte mask */
+
+/* htphy PhyRxStatus_2: */
+#define PRXS2_HTPHY_MMPLCPLenH_MASK	0x000F	/* Mixmode PLCP Length high byte maskw */
+#define PRXS2_HTPHY_MMPLCH_RATE_MASK	0x00F0	/* Mixmode PLCP rate mask */
+#define PRXS2_HTPHY_RXPWR_ANT0	0xFF00	/* Rx power on core 0 */
+
+/* htphy PhyRxStatus_3: */
+#define PRXS3_HTPHY_RXPWR_ANT1	0x00FF	/* Rx power on core 1 */
+#define PRXS3_HTPHY_RXPWR_ANT2	0xFF00	/* Rx power on core 2 */
+
+/* htphy PhyRxStatus_4: */
+#define PRXS4_HTPHY_RXPWR_ANT3	0x00FF	/* Rx power on core 3 */
+#define PRXS4_HTPHY_CFO		0xFF00	/* Coarse frequency offset */
+
+/* htphy PhyRxStatus_5: */
+#define PRXS5_HTPHY_FFO	        0x00FF	/* Fine frequency offset */
+#define PRXS5_HTPHY_AR	        0xFF00	/* Advance Retard */
+
+#define HTPHY_MMPLCPLen(rxs)	((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
+	(((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8))
+/* Get Rx power on core 0 */
+#define HTPHY_RXPWR_ANT0(rxs)	((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
+/* Get Rx power on core 1 */
+#define HTPHY_RXPWR_ANT1(rxs)	(((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
+/* Get Rx power on core 2 */
+#define HTPHY_RXPWR_ANT2(rxs)	((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
+
+/* ucode RxStatus1: */
+#define	RXS_BCNSENT		0x8000
+#define	RXS_SECKINDX_MASK	0x07e0
+#define	RXS_SECKINDX_SHIFT	5
+#define	RXS_DECERR		(1 << 4)
+#define	RXS_DECATMPT		(1 << 3)
+#define	RXS_PBPRES		(1 << 2)	/* PAD bytes to make IP data 4 bytes aligned */
+#define	RXS_RESPFRAMETX		(1 << 1)
+#define	RXS_FCSERR		(1 << 0)
+
+/* ucode RxStatus2: */
+#define RXS_AMSDU_MASK		1
+#define	RXS_AGGTYPE_MASK	0x6
+#define	RXS_AGGTYPE_SHIFT	1
+#define	RXS_PHYRXST_VALID	(1 << 8)
+#define RXS_RXANT_MASK		0x3
+#define RXS_RXANT_SHIFT		12
+
+/* RxChan */
+#define RXS_CHAN_40		0x1000
+#define RXS_CHAN_5G		0x0800
+#define	RXS_CHAN_ID_MASK	0x07f8
+#define	RXS_CHAN_ID_SHIFT	3
+#define	RXS_CHAN_PHYTYPE_MASK	0x0007
+#define	RXS_CHAN_PHYTYPE_SHIFT	0
+
+/* Index of attenuations used during ucode power control. */
+#define M_PWRIND_BLKS	(0x184 * 2)
+#define M_PWRIND_MAP0	(M_PWRIND_BLKS + 0x0)
+#define M_PWRIND_MAP1	(M_PWRIND_BLKS + 0x2)
+#define M_PWRIND_MAP2	(M_PWRIND_BLKS + 0x4)
+#define M_PWRIND_MAP3	(M_PWRIND_BLKS + 0x6)
+/* M_PWRIND_MAP(core) macro */
+#define M_PWRIND_MAP(core)  (M_PWRIND_BLKS + ((core)<<1))
+
+/* PSM SHM variable offsets */
+#define	M_PSM_SOFT_REGS	0x0
+#define	M_BOM_REV_MAJOR	(M_PSM_SOFT_REGS + 0x0)
+#define	M_BOM_REV_MINOR	(M_PSM_SOFT_REGS + 0x2)
+#define	M_UCODE_DBGST	(M_PSM_SOFT_REGS + 0x40)	/* ucode debug status code */
+#define	M_UCODE_MACSTAT	(M_PSM_SOFT_REGS + 0xE0)	/* macstat counters */
+
+#define M_AGING_THRSH	(0x3e * 2)	/* max time waiting for medium before tx */
+#define	M_MBURST_SIZE	(0x40 * 2)	/* max frames in a frameburst */
+#define	M_MBURST_TXOP	(0x41 * 2)	/* max frameburst TXOP in unit of us */
+#define M_SYNTHPU_DLY	(0x4a * 2)	/* pre-wakeup for synthpu, default: 500 */
+#define	M_PRETBTT	(0x4b * 2)
+
+#define M_ALT_TXPWR_IDX		(M_PSM_SOFT_REGS + (0x3b * 2))	/* offset to the target txpwr */
+#define M_PHY_TX_FLT_PTR	(M_PSM_SOFT_REGS + (0x3d * 2))
+#define M_CTS_DURATION		(M_PSM_SOFT_REGS + (0x5c * 2))
+#define M_LP_RCCAL_OVR		(M_PSM_SOFT_REGS + (0x6b * 2))
+
+/* PKTENG Rx Stats Block */
+#define M_RXSTATS_BLK_PTR	(M_PSM_SOFT_REGS + (0x65 * 2))
+
+/* ucode debug status codes */
+#define	DBGST_INACTIVE		0	/* not valid really */
+#define	DBGST_INIT		1	/* after zeroing SHM, before suspending at init */
+#define	DBGST_ACTIVE		2	/* "normal" state */
+#define	DBGST_SUSPENDED		3	/* suspended */
+#define	DBGST_ASLEEP		4	/* asleep (PS mode) */
+
+/* Scratch Reg defs */
+typedef enum {
+	S_RSV0 = 0,
+	S_RSV1,
+	S_RSV2,
+
+	/* scratch registers for Dot11-contants */
+	S_DOT11_CWMIN,		/* CW-minimum                                   0x03 */
+	S_DOT11_CWMAX,		/* CW-maximum                                   0x04 */
+	S_DOT11_CWCUR,		/* CW-current                                   0x05 */
+	S_DOT11_SRC_LMT,	/* short retry count limit                      0x06 */
+	S_DOT11_LRC_LMT,	/* long retry count limit                       0x07 */
+	S_DOT11_DTIMCOUNT,	/* DTIM-count                                   0x08 */
+
+	/* Tx-side scratch registers */
+	S_SEQ_NUM,		/* hardware sequence number reg                 0x09 */
+	S_SEQ_NUM_FRAG,		/* seq-num for frags (Set at the start os MSDU  0x0A */
+	S_FRMRETX_CNT,		/* frame retx count                             0x0B */
+	S_SSRC,			/* Station short retry count                    0x0C */
+	S_SLRC,			/* Station long retry count                     0x0D */
+	S_EXP_RSP,		/* Expected response frame                      0x0E */
+	S_OLD_BREM,		/* Remaining backoff ctr                        0x0F */
+	S_OLD_CWWIN,		/* saved-off CW-cur                             0x10 */
+	S_TXECTL,		/* TXE-Ctl word constructed in scr-pad          0x11 */
+	S_CTXTST,		/* frm type-subtype as read from Tx-descr       0x12 */
+
+	/* Rx-side scratch registers */
+	S_RXTST,		/* Type and subtype in Rxframe                  0x13 */
+
+	/* Global state register */
+	S_STREG,		/* state storage actual bit maps below          0x14 */
+
+	S_TXPWR_SUM,		/* Tx power control: accumulator                0x15 */
+	S_TXPWR_ITER,		/* Tx power control: iteration                  0x16 */
+	S_RX_FRMTYPE,		/* Rate and PHY type for frames                 0x17 */
+	S_THIS_AGG,		/* Size of this AGG (A-MSDU)                    0x18 */
+
+	S_KEYINDX,		/*                                              0x19 */
+	S_RXFRMLEN,		/* Receive MPDU length in bytes                 0x1A */
+
+	/* Receive TSF time stored in SCR */
+	S_RXTSFTMRVAL_WD3,	/* TSF value at the start of rx                 0x1B */
+	S_RXTSFTMRVAL_WD2,	/* TSF value at the start of rx                 0x1C */
+	S_RXTSFTMRVAL_WD1,	/* TSF value at the start of rx                 0x1D */
+	S_RXTSFTMRVAL_WD0,	/* TSF value at the start of rx                 0x1E */
+	S_RXSSN,		/* Received start seq number for A-MPDU BA      0x1F */
+	S_RXQOSFLD,		/* Rx-QoS field (if present)                    0x20 */
+
+	/* Scratch pad regs used in microcode as temp storage */
+	S_TMP0,			/* stmp0                                        0x21 */
+	S_TMP1,			/* stmp1                                        0x22 */
+	S_TMP2,			/* stmp2                                        0x23 */
+	S_TMP3,			/* stmp3                                        0x24 */
+	S_TMP4,			/* stmp4                                        0x25 */
+	S_TMP5,			/* stmp5                                        0x26 */
+	S_PRQPENALTY_CTR,	/* Probe response queue penalty counter         0x27 */
+	S_ANTCNT,		/* unsuccessful attempts on current ant.        0x28 */
+	S_SYMBOL,		/* flag for possible symbol ctl frames          0x29 */
+	S_RXTP,			/* rx frame type                                0x2A */
+	S_STREG2,		/* extra state storage                          0x2B */
+	S_STREG3,		/* even more extra state storage                0x2C */
+	S_STREG4,		/* ...                                          0x2D */
+	S_STREG5,		/* remember to initialize it to zero            0x2E */
+
+	S_ADJPWR_IDX,
+	S_CUR_PTR,		/* Temp pointer for A-MPDU re-Tx SHM table      0x32 */
+	S_REVID4,		/* 0x33 */
+	S_INDX,			/* 0x34 */
+	S_ADDR0,		/* 0x35 */
+	S_ADDR1,		/* 0x36 */
+	S_ADDR2,		/* 0x37 */
+	S_ADDR3,		/* 0x38 */
+	S_ADDR4,		/* 0x39 */
+	S_ADDR5,		/* 0x3A */
+	S_TMP6,			/* 0x3B */
+	S_KEYINDX_BU,		/* Backup for Key index                         0x3C */
+	S_MFGTEST_TMP0,		/* Temp register used for RX test calculations  0x3D */
+	S_RXESN,		/* Received end sequence number for A-MPDU BA   0x3E */
+	S_STREG6,		/* 0x3F */
+} ePsmScratchPadRegDefinitions;
+
+#define S_BEACON_INDX	S_OLD_BREM
+#define S_PRS_INDX	S_OLD_CWWIN
+#define S_PHYTYPE	S_SSRC
+#define S_PHYVER	S_SLRC
+
+/* IHR SLOW_CTRL values */
+#define SLOW_CTRL_PDE		(1 << 0)
+#define SLOW_CTRL_FD		(1 << 8)
+
+/* ucode mac statistic counters in shared memory */
+typedef struct macstat {
+	u16 txallfrm;	/* 0x80 */
+	u16 txrtsfrm;	/* 0x82 */
+	u16 txctsfrm;	/* 0x84 */
+	u16 txackfrm;	/* 0x86 */
+	u16 txdnlfrm;	/* 0x88 */
+	u16 txbcnfrm;	/* 0x8a */
+	u16 txfunfl[8];	/* 0x8c - 0x9b */
+	u16 txtplunfl;	/* 0x9c */
+	u16 txphyerr;	/* 0x9e */
+	u16 pktengrxducast;	/* 0xa0 */
+	u16 pktengrxdmcast;	/* 0xa2 */
+	u16 rxfrmtoolong;	/* 0xa4 */
+	u16 rxfrmtooshrt;	/* 0xa6 */
+	u16 rxinvmachdr;	/* 0xa8 */
+	u16 rxbadfcs;	/* 0xaa */
+	u16 rxbadplcp;	/* 0xac */
+	u16 rxcrsglitch;	/* 0xae */
+	u16 rxstrt;		/* 0xb0 */
+	u16 rxdfrmucastmbss;	/* 0xb2 */
+	u16 rxmfrmucastmbss;	/* 0xb4 */
+	u16 rxcfrmucast;	/* 0xb6 */
+	u16 rxrtsucast;	/* 0xb8 */
+	u16 rxctsucast;	/* 0xba */
+	u16 rxackucast;	/* 0xbc */
+	u16 rxdfrmocast;	/* 0xbe */
+	u16 rxmfrmocast;	/* 0xc0 */
+	u16 rxcfrmocast;	/* 0xc2 */
+	u16 rxrtsocast;	/* 0xc4 */
+	u16 rxctsocast;	/* 0xc6 */
+	u16 rxdfrmmcast;	/* 0xc8 */
+	u16 rxmfrmmcast;	/* 0xca */
+	u16 rxcfrmmcast;	/* 0xcc */
+	u16 rxbeaconmbss;	/* 0xce */
+	u16 rxdfrmucastobss;	/* 0xd0 */
+	u16 rxbeaconobss;	/* 0xd2 */
+	u16 rxrsptmout;	/* 0xd4 */
+	u16 bcntxcancl;	/* 0xd6 */
+	u16 PAD;
+	u16 rxf0ovfl;	/* 0xda */
+	u16 rxf1ovfl;	/* 0xdc */
+	u16 rxf2ovfl;	/* 0xde */
+	u16 txsfovfl;	/* 0xe0 */
+	u16 pmqovfl;		/* 0xe2 */
+	u16 rxcgprqfrm;	/* 0xe4 */
+	u16 rxcgprsqovfl;	/* 0xe6 */
+	u16 txcgprsfail;	/* 0xe8 */
+	u16 txcgprssuc;	/* 0xea */
+	u16 prs_timeout;	/* 0xec */
+	u16 rxnack;
+	u16 frmscons;
+	u16 txnack;
+	u16 txglitch_nack;
+	u16 txburst;		/* 0xf6 # tx bursts */
+	u16 bphy_rxcrsglitch;	/* bphy rx crs glitch */
+	u16 phywatchdog;	/* 0xfa # of phy watchdog events */
+	u16 PAD;
+	u16 bphy_badplcp;	/* bphy bad plcp */
+} macstat_t;
+
+/* dot11 core-specific control flags */
+#define	SICF_PCLKE		0x0004	/* PHY clock enable */
+#define	SICF_PRST		0x0008	/* PHY reset */
+#define	SICF_MPCLKE		0x0010	/* MAC PHY clockcontrol enable */
+#define	SICF_FREF		0x0020	/* PLL FreqRefSelect */
+/* NOTE: the following bw bits only apply when the core is attached
+ * to a NPHY
+ */
+#define	SICF_BWMASK		0x00c0	/* phy clock mask (b6 & b7) */
+#define	SICF_BW40		0x0080	/* 40MHz BW (160MHz phyclk) */
+#define	SICF_BW20		0x0040	/* 20MHz BW (80MHz phyclk) */
+#define	SICF_BW10		0x0000	/* 10MHz BW (40MHz phyclk) */
+#define	SICF_GMODE		0x2000	/* gmode enable */
+
+/* dot11 core-specific status flags */
+#define	SISF_2G_PHY		0x0001	/* 2.4G capable phy */
+#define	SISF_5G_PHY		0x0002	/* 5G capable phy */
+#define	SISF_FCLKA		0x0004	/* FastClkAvailable */
+#define	SISF_DB_PHY		0x0008	/* Dualband phy */
+
+/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg, radio and LPPHY regs are separated === */
+
+#define	BPHY_REG_OFT_BASE	0x0
+/* offsets for indirect access to bphy registers */
+#define	BPHY_BB_CONFIG		0x01
+#define	BPHY_ADCBIAS		0x02
+#define	BPHY_ANACORE		0x03
+#define	BPHY_PHYCRSTH		0x06
+#define	BPHY_TEST		0x0a
+#define	BPHY_PA_TX_TO		0x10
+#define	BPHY_SYNTH_DC_TO	0x11
+#define	BPHY_PA_TX_TIME_UP	0x12
+#define	BPHY_RX_FLTR_TIME_UP	0x13
+#define	BPHY_TX_POWER_OVERRIDE	0x14
+#define	BPHY_RF_OVERRIDE	0x15
+#define	BPHY_RF_TR_LOOKUP1	0x16
+#define	BPHY_RF_TR_LOOKUP2	0x17
+#define	BPHY_COEFFS		0x18
+#define	BPHY_PLL_OUT		0x19
+#define	BPHY_REFRESH_MAIN	0x1a
+#define	BPHY_REFRESH_TO0	0x1b
+#define	BPHY_REFRESH_TO1	0x1c
+#define	BPHY_RSSI_TRESH		0x20
+#define	BPHY_IQ_TRESH_HH	0x21
+#define	BPHY_IQ_TRESH_H		0x22
+#define	BPHY_IQ_TRESH_L		0x23
+#define	BPHY_IQ_TRESH_LL	0x24
+#define	BPHY_GAIN		0x25
+#define	BPHY_LNA_GAIN_RANGE	0x26
+#define	BPHY_JSSI		0x27
+#define	BPHY_TSSI_CTL		0x28
+#define	BPHY_TSSI		0x29
+#define	BPHY_TR_LOSS_CTL	0x2a
+#define	BPHY_LO_LEAKAGE		0x2b
+#define	BPHY_LO_RSSI_ACC	0x2c
+#define	BPHY_LO_IQMAG_ACC	0x2d
+#define	BPHY_TX_DC_OFF1		0x2e
+#define	BPHY_TX_DC_OFF2		0x2f
+#define	BPHY_PEAK_CNT_THRESH	0x30
+#define	BPHY_FREQ_OFFSET	0x31
+#define	BPHY_DIVERSITY_CTL	0x32
+#define	BPHY_PEAK_ENERGY_LO	0x33
+#define	BPHY_PEAK_ENERGY_HI	0x34
+#define	BPHY_SYNC_CTL		0x35
+#define	BPHY_TX_PWR_CTRL	0x36
+#define BPHY_TX_EST_PWR 	0x37
+#define	BPHY_STEP		0x38
+#define	BPHY_WARMUP		0x39
+#define	BPHY_LMS_CFF_READ	0x3a
+#define	BPHY_LMS_COEFF_I	0x3b
+#define	BPHY_LMS_COEFF_Q	0x3c
+#define	BPHY_SIG_POW		0x3d
+#define	BPHY_RFDC_CANCEL_CTL	0x3e
+#define	BPHY_HDR_TYPE		0x40
+#define	BPHY_SFD_TO		0x41
+#define	BPHY_SFD_CTL		0x42
+#define	BPHY_DEBUG		0x43
+#define	BPHY_RX_DELAY_COMP	0x44
+#define	BPHY_CRS_DROP_TO	0x45
+#define	BPHY_SHORT_SFD_NZEROS	0x46
+#define	BPHY_DSSS_COEFF1	0x48
+#define	BPHY_DSSS_COEFF2	0x49
+#define	BPHY_CCK_COEFF1		0x4a
+#define	BPHY_CCK_COEFF2		0x4b
+#define	BPHY_TR_CORR		0x4c
+#define	BPHY_ANGLE_SCALE	0x4d
+#define	BPHY_TX_PWR_BASE_IDX	0x4e
+#define	BPHY_OPTIONAL_MODES2	0x4f
+#define	BPHY_CCK_LMS_STEP	0x50
+#define	BPHY_BYPASS		0x51
+#define	BPHY_CCK_DELAY_LONG	0x52
+#define	BPHY_CCK_DELAY_SHORT	0x53
+#define	BPHY_PPROC_CHAN_DELAY	0x54
+#define	BPHY_DDFS_ENABLE	0x58
+#define	BPHY_PHASE_SCALE	0x59
+#define	BPHY_FREQ_CONTROL	0x5a
+#define	BPHY_LNA_GAIN_RANGE_10	0x5b
+#define	BPHY_LNA_GAIN_RANGE_32	0x5c
+#define	BPHY_OPTIONAL_MODES	0x5d
+#define	BPHY_RX_STATUS2		0x5e
+#define	BPHY_RX_STATUS3		0x5f
+#define	BPHY_DAC_CONTROL	0x60
+#define	BPHY_ANA11G_FILT_CTRL	0x62
+#define	BPHY_REFRESH_CTRL	0x64
+#define	BPHY_RF_OVERRIDE2	0x65
+#define	BPHY_SPUR_CANCEL_CTRL	0x66
+#define	BPHY_FINE_DIGIGAIN_CTRL	0x67
+#define	BPHY_RSSI_LUT		0x88
+#define	BPHY_RSSI_LUT_END	0xa7
+#define	BPHY_TSSI_LUT		0xa8
+#define	BPHY_TSSI_LUT_END	0xc7
+#define	BPHY_TSSI2PWR_LUT	0x380
+#define	BPHY_TSSI2PWR_LUT_END	0x39f
+#define	BPHY_LOCOMP_LUT		0x3a0
+#define	BPHY_LOCOMP_LUT_END	0x3bf
+#define	BPHY_TXGAIN_LUT		0x3c0
+#define	BPHY_TXGAIN_LUT_END	0x3ff
+
+/* Bits in BB_CONFIG: */
+#define	PHY_BBC_ANT_MASK	0x0180
+#define	PHY_BBC_ANT_SHIFT	7
+#define	BB_DARWIN		0x1000
+#define BBCFG_RESETCCA		0x4000
+#define BBCFG_RESETRX		0x8000
+
+/* Bits in phytest(0x0a): */
+#define	TST_DDFS		0x2000
+#define	TST_TXFILT1		0x0800
+#define	TST_UNSCRAM		0x0400
+#define	TST_CARR_SUPP		0x0200
+#define	TST_DC_COMP_LOOP	0x0100
+#define	TST_LOOPBACK		0x0080
+#define	TST_TXFILT0		0x0040
+#define	TST_TXTEST_ENABLE	0x0020
+#define	TST_TXTEST_RATE		0x0018
+#define	TST_TXTEST_PHASE	0x0007
+
+/* phytest txTestRate values */
+#define	TST_TXTEST_RATE_1MBPS	0
+#define	TST_TXTEST_RATE_2MBPS	1
+#define	TST_TXTEST_RATE_5_5MBPS	2
+#define	TST_TXTEST_RATE_11MBPS	3
+#define	TST_TXTEST_RATE_SHIFT	3
+
+#define SHM_BYT_CNT	0x2	/* IHR location */
+#define MAX_BYT_CNT	0x600	/* Maximum frame len */
+
+#endif				/* _D11_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h b/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h
new file mode 100644
index 0000000..51a2238
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef phy_version_h_
+#define phy_version_h_
+
+#define	PHY_MAJOR_VERSION		1
+
+#define	PHY_MINOR_VERSION		82
+
+#define	PHY_RC_NUMBER		8
+
+#define	PHY_INCREMENTAL_NUMBER	0
+
+#define	PHY_BUILD_NUMBER		0
+
+#define	PHY_VERSION			{ 1, 82, 8, 0 }
+
+#define	PHY_VERSION_NUM		0x01520800
+
+#define	PHY_VERSION_STR		"1.82.8.0"
+
+#endif				/* phy_version_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
new file mode 100644
index 0000000..8f75af2
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
@@ -0,0 +1,3431 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlc_cfg.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <bcmdefs.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <bcmnvram.h>
+#include <sbchipc.h>
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+
+#include <wlc_phy_int.h>
+#include <wlc_phyreg_n.h>
+#include <wlc_phy_radio.h>
+#include <wlc_phy_lcn.h>
+
+u32 phyhal_msg_level = PHYHAL_ERROR;
+
+typedef struct _chan_info_basic {
+	u16 chan;
+	u16 freq;
+} chan_info_basic_t;
+
+static chan_info_basic_t chan_info_all[] = {
+
+	{1, 2412},
+	{2, 2417},
+	{3, 2422},
+	{4, 2427},
+	{5, 2432},
+	{6, 2437},
+	{7, 2442},
+	{8, 2447},
+	{9, 2452},
+	{10, 2457},
+	{11, 2462},
+	{12, 2467},
+	{13, 2472},
+	{14, 2484},
+
+	{34, 5170},
+	{38, 5190},
+	{42, 5210},
+	{46, 5230},
+
+	{36, 5180},
+	{40, 5200},
+	{44, 5220},
+	{48, 5240},
+	{52, 5260},
+	{56, 5280},
+	{60, 5300},
+	{64, 5320},
+
+	{100, 5500},
+	{104, 5520},
+	{108, 5540},
+	{112, 5560},
+	{116, 5580},
+	{120, 5600},
+	{124, 5620},
+	{128, 5640},
+	{132, 5660},
+	{136, 5680},
+	{140, 5700},
+
+	{149, 5745},
+	{153, 5765},
+	{157, 5785},
+	{161, 5805},
+	{165, 5825},
+
+	{184, 4920},
+	{188, 4940},
+	{192, 4960},
+	{196, 4980},
+	{200, 5000},
+	{204, 5020},
+	{208, 5040},
+	{212, 5060},
+	{216, 50800}
+};
+
+u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
+	0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
+	0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
+	0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
+	0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
+	0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
+	0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
+	0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
+	0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
+	0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
+	0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
+	0x0507, 0x0fea, 0xe4f2, 0xf6e6
+};
+
+const u8 ofdm_rate_lookup[] = {
+
+	WLC_RATE_48M,
+	WLC_RATE_24M,
+	WLC_RATE_12M,
+	WLC_RATE_6M,
+	WLC_RATE_54M,
+	WLC_RATE_36M,
+	WLC_RATE_18M,
+	WLC_RATE_9M
+};
+
+#define PHY_WREG_LIMIT	24
+
+static void wlc_set_phy_uninitted(phy_info_t *pi);
+static u32 wlc_phy_get_radio_ver(phy_info_t *pi);
+static void wlc_phy_timercb_phycal(void *arg);
+
+static bool wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr,
+				   s8 *pwr_ant);
+
+static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay);
+static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm);
+static void wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason,
+					 u8 ch);
+
+static void wlc_phy_txpower_reg_limit_calc(phy_info_t *pi,
+					   struct txpwr_limits *tp, chanspec_t);
+static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi);
+
+static s8 wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan,
+					     u32 band, u8 rate);
+static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band);
+static s8 wlc_phy_env_measure_vbat(phy_info_t *pi);
+static s8 wlc_phy_env_measure_temperature(phy_info_t *pi);
+
+char *phy_getvar(phy_info_t *pi, const char *name)
+{
+	char *vars = pi->vars;
+	char *s;
+	int len;
+
+	ASSERT(pi->vars != (char *)&pi->vars);
+
+	if (!name)
+		return NULL;
+
+	len = strlen(name);
+	if (len == 0)
+		return NULL;
+
+	for (s = vars; s && *s;) {
+		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
+			return &s[len + 1];
+
+		while (*s++)
+			;
+	}
+
+	return nvram_get(name);
+}
+
+int phy_getintvar(phy_info_t *pi, const char *name)
+{
+	char *val;
+
+	val = PHY_GETVAR(pi, name);
+	if (val == NULL)
+		return 0;
+
+	return simple_strtoul(val, NULL, 0);
+}
+
+void wlc_phyreg_enter(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
+}
+
+void wlc_phyreg_exit(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
+}
+
+void wlc_radioreg_enter(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
+
+	udelay(10);
+}
+
+void wlc_radioreg_exit(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	volatile u16 dummy;
+
+	dummy = R_REG(&pi->regs->phyversion);
+	pi->phy_wreg = 0;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
+}
+
+u16 read_radio_reg(phy_info_t *pi, u16 addr)
+{
+	u16 data;
+
+	if ((addr == RADIO_IDCODE))
+		return 0xffff;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return NORADIO_IDCODE & 0xffff;
+
+	switch (pi->pubpi.phy_type) {
+	case PHY_TYPE_N:
+		CASECHECK(PHYTYPE, PHY_TYPE_N);
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			addr |= RADIO_2057_READ_OFF;
+		else
+			addr |= RADIO_2055_READ_OFF;
+		break;
+
+	case PHY_TYPE_LCN:
+		CASECHECK(PHYTYPE, PHY_TYPE_LCN);
+		addr |= RADIO_2064_READ_OFF;
+		break;
+
+	default:
+		ASSERT(VALID_PHYTYPE(pi->pubpi.phy_type));
+	}
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+		W_REG(&pi->regs->radioregaddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		data = R_REG(&pi->regs->radioregdata);
+	} else {
+		W_REG(&pi->regs->phy4waddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->phy4waddr);
+#endif
+
+#ifdef __ARM_ARCH_4T__
+		__asm__(" .align 4 ");
+		__asm__(" nop ");
+		data = R_REG(&pi->regs->phy4wdatalo);
+#else
+		data = R_REG(&pi->regs->phy4wdatalo);
+#endif
+
+	}
+	pi->phy_wreg = 0;
+
+	return data;
+}
+
+void write_radio_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+
+		W_REG(&pi->regs->radioregaddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		W_REG(&pi->regs->radioregdata, val);
+	} else {
+		W_REG(&pi->regs->phy4waddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->phy4waddr);
+#endif
+		W_REG(&pi->regs->phy4wdatalo, val);
+	}
+
+	if (pi->sh->bustype == PCI_BUS) {
+		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+			(void)R_REG(&pi->regs->maccontrol);
+			pi->phy_wreg = 0;
+		}
+	}
+}
+
+static u32 read_radio_id(phy_info_t *pi)
+{
+	u32 id;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return NORADIO_IDCODE;
+
+	if (D11REV_GE(pi->sh->corerev, 24)) {
+		u32 b0, b1, b2;
+
+		W_REG(&pi->regs->radioregaddr, 0);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		b0 = (u32) R_REG(&pi->regs->radioregdata);
+		W_REG(&pi->regs->radioregaddr, 1);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		b1 = (u32) R_REG(&pi->regs->radioregdata);
+		W_REG(&pi->regs->radioregaddr, 2);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		b2 = (u32) R_REG(&pi->regs->radioregdata);
+
+		id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
+								      & 0xf);
+	} else {
+		W_REG(&pi->regs->phy4waddr, RADIO_IDCODE);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->phy4waddr);
+#endif
+		id = (u32) R_REG(&pi->regs->phy4wdatalo);
+		id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
+	}
+	pi->phy_wreg = 0;
+	return id;
+}
+
+void and_radio_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & val));
+}
+
+void or_radio_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval | val));
+}
+
+void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval ^ mask));
+}
+
+void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
+}
+
+void write_phy_channel_reg(phy_info_t *pi, uint val)
+{
+	W_REG(&pi->regs->phychannel, val);
+}
+
+#if defined(BCMDBG)
+static bool wlc_phy_war41476(phy_info_t *pi)
+{
+	u32 mc = R_REG(&pi->regs->maccontrol);
+
+	return ((mc & MCTL_EN_MAC) == 0)
+	    || ((mc & MCTL_PHYLOCK) == MCTL_PHYLOCK);
+}
+#endif
+
+u16 read_phy_reg(phy_info_t *pi, u16 addr)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	pi->phy_wreg = 0;
+	return R_REG(&regs->phyregdata);
+}
+
+void write_phy_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+#ifdef __mips__
+	W_REG(&regs->phyregaddr, addr);
+	(void)R_REG(&regs->phyregaddr);
+	W_REG(&regs->phyregdata, val);
+	if (addr == 0x72)
+		(void)R_REG(&regs->phyregdata);
+#else
+	W_REG((u32 *)(&regs->phyregaddr),
+	      addr | (val << 16));
+	if (pi->sh->bustype == PCI_BUS) {
+		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+			pi->phy_wreg = 0;
+			(void)R_REG(&regs->phyversion);
+		}
+	}
+#endif
+}
+
+void and_phy_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) & val));
+	pi->phy_wreg = 0;
+}
+
+void or_phy_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) | val));
+	pi->phy_wreg = 0;
+}
+
+void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	W_REG(&regs->phyregdata,
+	      ((R_REG(&regs->phyregdata) & ~mask) | (val & mask)));
+	pi->phy_wreg = 0;
+}
+
+static void WLBANDINITFN(wlc_set_phy_uninitted) (phy_info_t *pi)
+{
+	int i, j;
+
+	pi->initialized = false;
+
+	pi->tx_vos = 0xffff;
+	pi->nrssi_table_delta = 0x7fffffff;
+	pi->rc_cal = 0xffff;
+	pi->mintxbias = 0xffff;
+	pi->txpwridx = -1;
+	if (ISNPHY(pi)) {
+		pi->phy_spuravoid = SPURAVOID_DISABLE;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7))
+			pi->phy_spuravoid = SPURAVOID_AUTO;
+
+		pi->nphy_papd_skip = 0;
+		pi->nphy_papd_epsilon_offset[0] = 0xf588;
+		pi->nphy_papd_epsilon_offset[1] = 0xf588;
+		pi->nphy_txpwr_idx[0] = 128;
+		pi->nphy_txpwr_idx[1] = 128;
+		pi->nphy_txpwrindex[0].index_internal = 40;
+		pi->nphy_txpwrindex[1].index_internal = 40;
+		pi->phy_pabias = 0;
+	} else {
+		pi->phy_spuravoid = SPURAVOID_AUTO;
+	}
+	pi->radiopwr = 0xffff;
+	for (i = 0; i < STATIC_NUM_RF; i++) {
+		for (j = 0; j < STATIC_NUM_BB; j++) {
+			pi->stats_11b_txpower[i][j] = -1;
+		}
+	}
+}
+
+shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp)
+{
+	shared_phy_t *sh;
+
+	sh = kzalloc(sizeof(shared_phy_t), GFP_ATOMIC);
+	if (sh == NULL) {
+		return NULL;
+	}
+
+	sh->sih = shp->sih;
+	sh->physhim = shp->physhim;
+	sh->unit = shp->unit;
+	sh->corerev = shp->corerev;
+
+	sh->vid = shp->vid;
+	sh->did = shp->did;
+	sh->chip = shp->chip;
+	sh->chiprev = shp->chiprev;
+	sh->chippkg = shp->chippkg;
+	sh->sromrev = shp->sromrev;
+	sh->boardtype = shp->boardtype;
+	sh->boardrev = shp->boardrev;
+	sh->boardvendor = shp->boardvendor;
+	sh->boardflags = shp->boardflags;
+	sh->boardflags2 = shp->boardflags2;
+	sh->bustype = shp->bustype;
+	sh->buscorerev = shp->buscorerev;
+
+	sh->fast_timer = PHY_SW_TIMER_FAST;
+	sh->slow_timer = PHY_SW_TIMER_SLOW;
+	sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
+
+	sh->rssi_mode = RSSI_ANT_MERGE_MAX;
+
+	return sh;
+}
+
+void wlc_phy_shared_detach(shared_phy_t *phy_sh)
+{
+	if (phy_sh) {
+		if (phy_sh->phy_head) {
+			ASSERT(!phy_sh->phy_head);
+		}
+		kfree(phy_sh);
+	}
+}
+
+wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype, char *vars)
+{
+	phy_info_t *pi;
+	u32 sflags = 0;
+	uint phyversion;
+	int i;
+
+	if (D11REV_IS(sh->corerev, 4))
+		sflags = SISF_2G_PHY | SISF_5G_PHY;
+	else
+		sflags = si_core_sflags(sh->sih, 0, 0);
+
+	if (BAND_5G(bandtype)) {
+		if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
+			return NULL;
+		}
+	}
+
+	pi = sh->phy_head;
+	if ((sflags & SISF_DB_PHY) && pi) {
+
+		wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+		pi->refcnt++;
+		return &pi->pubpi_ro;
+	}
+
+	pi = kzalloc(sizeof(phy_info_t), GFP_ATOMIC);
+	if (pi == NULL) {
+		return NULL;
+	}
+	pi->regs = (d11regs_t *) regs;
+	pi->sh = sh;
+	pi->phy_init_por = true;
+	pi->phy_wreg_limit = PHY_WREG_LIMIT;
+
+	pi->vars = vars;
+
+	pi->txpwr_percent = 100;
+
+	pi->do_initcal = true;
+
+	pi->phycal_tempdelta = 0;
+
+	if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
+
+		pi->pubpi.coreflags = SICF_GMODE;
+	}
+
+	wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+	phyversion = R_REG(&pi->regs->phyversion);
+
+	pi->pubpi.phy_type = PHY_TYPE(phyversion);
+	pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
+
+	if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
+		pi->pubpi.phy_type = PHY_TYPE_N;
+		pi->pubpi.phy_rev += LCNXN_BASEREV;
+	}
+	pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
+	pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
+
+	if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
+		goto err;
+	}
+	if (BAND_5G(bandtype)) {
+		if (!ISNPHY(pi)) {
+			goto err;
+		}
+	} else {
+		if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+			goto err;
+		}
+	}
+
+	if (ISSIM_ENAB(pi->sh->sih)) {
+		pi->pubpi.radioid = NORADIO_ID;
+		pi->pubpi.radiorev = 5;
+	} else {
+		u32 idcode;
+
+		wlc_phy_anacore((wlc_phy_t *) pi, ON);
+
+		idcode = wlc_phy_get_radio_ver(pi);
+		pi->pubpi.radioid =
+		    (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
+		pi->pubpi.radiorev =
+		    (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
+		pi->pubpi.radiover =
+		    (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
+		if (!VALID_RADIO(pi, pi->pubpi.radioid)) {
+			goto err;
+		}
+
+		wlc_phy_switch_radio((wlc_phy_t *) pi, OFF);
+	}
+
+	wlc_set_phy_uninitted(pi);
+
+	pi->bw = WL_CHANSPEC_BW_20;
+	pi->radio_chanspec =
+	    BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
+
+	pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+	pi->rxiq_antsel = ANT_RX_DIV_DEF;
+
+	pi->watchdog_override = true;
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+
+	pi->nphy_saved_noisevars.bufcount = 0;
+
+	if (ISNPHY(pi))
+		pi->min_txpower = PHY_TXPWR_MIN_NPHY;
+	else
+		pi->min_txpower = PHY_TXPWR_MIN;
+
+	pi->sh->phyrxchain = 0x3;
+
+	pi->rx2tx_biasentry = -1;
+
+	pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+	pi->phy_txcore_enable_temp =
+	    PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
+	pi->phy_tempsense_offset = 0;
+	pi->phy_txcore_heatedup = false;
+
+	pi->nphy_lastcal_temp = -50;
+
+	pi->phynoise_polling = true;
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		pi->phynoise_polling = false;
+
+	for (i = 0; i < TXP_NUM_RATES; i++) {
+		pi->txpwr_limit[i] = WLC_TXPWR_MAX;
+		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
+		pi->tx_user_target[i] = WLC_TXPWR_MAX;
+	}
+
+	pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
+
+	pi->user_txpwr_at_rfport = false;
+
+	if (ISNPHY(pi)) {
+
+		pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
+							  wlc_phy_timercb_phycal,
+							  pi, "phycal");
+		if (!pi->phycal_timer) {
+			goto err;
+		}
+
+		if (!wlc_phy_attach_nphy(pi))
+			goto err;
+
+	} else if (ISLCNPHY(pi)) {
+		if (!wlc_phy_attach_lcnphy(pi))
+			goto err;
+
+	} else {
+
+	}
+
+	pi->refcnt++;
+	pi->next = pi->sh->phy_head;
+	sh->phy_head = pi;
+
+	pi->vars = (char *)&pi->vars;
+
+	memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(wlc_phy_t));
+
+	return &pi->pubpi_ro;
+
+ err:
+	kfree(pi);
+	return NULL;
+}
+
+void wlc_phy_detach(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (pih) {
+		if (--pi->refcnt) {
+			return;
+		}
+
+		if (pi->phycal_timer) {
+			wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
+			pi->phycal_timer = NULL;
+		}
+
+		if (pi->sh->phy_head == pi)
+			pi->sh->phy_head = pi->next;
+		else if (pi->sh->phy_head->next == pi)
+			pi->sh->phy_head->next = NULL;
+		else
+			ASSERT(0);
+
+		if (pi->pi_fptr.detach)
+			(pi->pi_fptr.detach) (pi);
+
+		kfree(pi);
+	}
+}
+
+bool
+wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype, u16 *phyrev,
+		       u16 *radioid, u16 *radiover)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	*phytype = (u16) pi->pubpi.phy_type;
+	*phyrev = (u16) pi->pubpi.phy_rev;
+	*radioid = pi->pubpi.radioid;
+	*radiover = pi->pubpi.radiorev;
+
+	return true;
+}
+
+bool wlc_phy_get_encore(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	return pi->pubpi.abgphy_encore;
+}
+
+u32 wlc_phy_get_coreflags(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	return pi->pubpi.coreflags;
+}
+
+static void wlc_phy_timercb_phycal(void *arg)
+{
+	phy_info_t *pi = (phy_info_t *) arg;
+	uint delay = 5;
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		if (!pi->sh->up) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+			return;
+		}
+
+		if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
+
+			delay = 1000;
+			wlc_phy_cal_perical_mphase_restart(pi);
+		} else
+			wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
+		wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+		return;
+	}
+
+}
+
+void wlc_phy_anacore(wlc_phy_t *pih, bool on)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (ISNPHY(pi)) {
+		if (on) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0xa6, 0x0d);
+				write_phy_reg(pi, 0x8f, 0x0);
+				write_phy_reg(pi, 0xa7, 0x0d);
+				write_phy_reg(pi, 0xa5, 0x0);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x0);
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0x8f, 0x07ff);
+				write_phy_reg(pi, 0xa6, 0x0fd);
+				write_phy_reg(pi, 0xa5, 0x07ff);
+				write_phy_reg(pi, 0xa7, 0x0fd);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x7fff);
+			}
+		}
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x43b,
+				    ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+		} else {
+			or_phy_reg(pi, 0x43c,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+			or_phy_reg(pi, 0x43b,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+		}
+	}
+}
+
+u32 wlc_phy_clk_bwbits(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	u32 phy_bw_clkbits = 0;
+
+	if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
+		switch (pi->bw) {
+		case WL_CHANSPEC_BW_10:
+			phy_bw_clkbits = SICF_BW10;
+			break;
+		case WL_CHANSPEC_BW_20:
+			phy_bw_clkbits = SICF_BW20;
+			break;
+		case WL_CHANSPEC_BW_40:
+			phy_bw_clkbits = SICF_BW40;
+			break;
+		default:
+			ASSERT(0);
+			break;
+		}
+	}
+
+	return phy_bw_clkbits;
+}
+
+void WLBANDINITFN(wlc_phy_por_inform) (wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->phy_init_por = true;
+}
+
+void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->edcrs_threshold_lock = lock;
+
+	write_phy_reg(pi, 0x22c, 0x46b);
+	write_phy_reg(pi, 0x22d, 0x46b);
+	write_phy_reg(pi, 0x22e, 0x3c0);
+	write_phy_reg(pi, 0x22f, 0x3c0);
+}
+
+void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->do_initcal = initcal;
+}
+
+void wlc_phy_hw_clk_state_upd(wlc_phy_t *pih, bool newstate)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->clk = newstate;
+}
+
+void wlc_phy_hw_state_upd(wlc_phy_t *pih, bool newstate)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->up = newstate;
+}
+
+void WLBANDINITFN(wlc_phy_init) (wlc_phy_t *pih, chanspec_t chanspec)
+{
+	u32 mc;
+	initfn_t phy_init = NULL;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (pi->init_in_progress)
+		return;
+
+	pi->init_in_progress = true;
+
+	pi->radio_chanspec = chanspec;
+
+	mc = R_REG(&pi->regs->maccontrol);
+	if ((mc & MCTL_EN_MAC) != 0) {
+		ASSERT((const char *)
+		       "wlc_phy_init: Called with the MAC running!" == NULL);
+	}
+
+	ASSERT(pi != NULL);
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+	}
+
+	if (D11REV_GE(pi->sh->corerev, 5))
+		ASSERT(si_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA);
+
+	phy_init = pi->pi_fptr.init;
+
+	if (phy_init == NULL) {
+		ASSERT(phy_init != NULL);
+		return;
+	}
+
+	wlc_phy_anacore(pih, ON);
+
+	if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim,
+				  CHSPEC_BW(pi->radio_chanspec));
+
+	pi->nphy_gain_boost = true;
+
+	wlc_phy_switch_radio((wlc_phy_t *) pi, ON);
+
+	(*phy_init) (pi);
+
+	pi->phy_init_por = false;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlc_phy_do_dummy_tx(pi, true, OFF);
+
+	if (!(ISNPHY(pi)))
+		wlc_phy_txpower_update_shm(pi);
+
+	wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi, pi->sh->rx_antdiv);
+
+	pi->init_in_progress = false;
+}
+
+void wlc_phy_cal_init(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	initfn_t cal_init = NULL;
+
+	ASSERT((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) == 0);
+
+	if (!pi->initialized) {
+		cal_init = pi->pi_fptr.calinit;
+		if (cal_init)
+			(*cal_init) (pi);
+
+		pi->initialized = true;
+	}
+}
+
+int wlc_phy_down(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	int callbacks = 0;
+
+	ASSERT(pi->phytest_on == false);
+
+	if (pi->phycal_timer
+	    && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
+		callbacks++;
+
+	pi->nphy_iqcal_chanspec_2G = 0;
+	pi->nphy_iqcal_chanspec_5G = 0;
+
+	return callbacks;
+}
+
+static u32 wlc_phy_get_radio_ver(phy_info_t *pi)
+{
+	u32 ver;
+
+	ver = read_radio_id(pi);
+
+	return ver;
+}
+
+void
+wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	pi->tbl_data_hi = tblDataHi;
+	pi->tbl_data_lo = tblDataLo;
+
+	if ((pi->sh->chip == BCM43224_CHIP_ID ||
+	     pi->sh->chip == BCM43421_CHIP_ID) &&
+	    (pi->sh->chiprev == 1)) {
+		pi->tbl_addr = tblAddr;
+		pi->tbl_save_id = tbl_id;
+		pi->tbl_save_offset = tbl_offset;
+	}
+}
+
+void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val)
+{
+	ASSERT((width == 8) || (width == 16) || (width == 32));
+
+	if ((pi->sh->chip == BCM43224_CHIP_ID ||
+	     pi->sh->chip == BCM43421_CHIP_ID) &&
+	    (pi->sh->chiprev == 1) &&
+	    (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+		read_phy_reg(pi, pi->tbl_data_lo);
+
+		write_phy_reg(pi, pi->tbl_addr,
+			      (pi->tbl_save_id << 10) | pi->tbl_save_offset);
+		pi->tbl_save_offset++;
+	}
+
+	if (width == 32) {
+
+		write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	} else {
+
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	}
+}
+
+void
+wlc_phy_write_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
+		    u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
+	const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
+	const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
+
+	ASSERT((tbl_width == 8) || (tbl_width == 16) || (tbl_width == 32));
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID ||
+		     pi->sh->chip == BCM43421_CHIP_ID) &&
+		    (pi->sh->chiprev == 1) &&
+		    (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+			read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+
+			write_phy_reg(pi, tblDataHi,
+				      (u16) (ptbl_32b[idx] >> 16));
+			write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
+		} else if (tbl_width == 16) {
+
+			write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
+		} else {
+
+			write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
+		}
+	}
+}
+
+void
+wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
+	u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
+	u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
+
+	ASSERT((tbl_width == 8) || (tbl_width == 16) || (tbl_width == 32));
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID ||
+		     pi->sh->chip == BCM43421_CHIP_ID) &&
+		    (pi->sh->chiprev == 1)) {
+			(void)read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+
+			ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
+			ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
+		} else if (tbl_width == 16) {
+
+			ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
+		} else {
+
+			ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
+		}
+	}
+}
+
+uint
+wlc_phy_init_radio_regs_allbands(phy_info_t *pi, radio_20xx_regs_t *radioregs)
+{
+	uint i = 0;
+
+	do {
+		if (radioregs[i].do_init) {
+			write_radio_reg(pi, radioregs[i].address,
+					(u16) radioregs[i].init);
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+uint
+wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
+			u16 core_offset)
+{
+	uint i = 0;
+	uint count = 0;
+
+	do {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (radioregs[i].do_init_a) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_a);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					WLC_PHY_WAR_PR51571(pi);
+			}
+		} else {
+			if (radioregs[i].do_init_g) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_g);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					WLC_PHY_WAR_PR51571(pi);
+			}
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on)
+{
+#define	DUMMY_PKT_LEN	20
+	d11regs_t *regs = pi->regs;
+	int i, count;
+	u8 ofdmpkt[DUMMY_PKT_LEN] = {
+		0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u8 cckpkt[DUMMY_PKT_LEN] = {
+		0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u32 *dummypkt;
+
+	ASSERT((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) == 0);
+
+	dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
+	wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
+				      dummypkt);
+
+	W_REG(&regs->xmtsel, 0);
+
+	if (D11REV_GE(pi->sh->corerev, 11))
+		W_REG(&regs->wepctl, 0x100);
+	else
+		W_REG(&regs->wepctl, 0);
+
+	W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
+	if (ISNPHY(pi) || ISLCNPHY(pi)) {
+		ASSERT(ofdm);
+		W_REG(&regs->txe_phyctl1, 0x1A02);
+	}
+
+	W_REG(&regs->txe_wm_0, 0);
+	W_REG(&regs->txe_wm_1, 0);
+
+	W_REG(&regs->xmttplatetxptr, 0);
+	W_REG(&regs->xmttxcnt, DUMMY_PKT_LEN);
+
+	W_REG(&regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
+
+	W_REG(&regs->txe_ctl, 0);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, OFF);
+	}
+
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		W_REG(&regs->txe_aux, 0xD0);
+	else
+		W_REG(&regs->txe_aux, ((1 << 5) | (1 << 4)));
+
+	(void)R_REG(&regs->txe_aux);
+
+	i = 0;
+	count = ofdm ? 30 : 250;
+
+	if (ISSIM_ENAB(pi->sh->sih)) {
+		count *= 100;
+	}
+
+	while ((i++ < count)
+	       && (R_REG(&regs->txe_status) & (1 << 7))) {
+		udelay(10);
+	}
+
+	i = 0;
+
+	while ((i++ < 10)
+	       && ((R_REG(&regs->txe_status) & (1 << 10)) == 0)) {
+		udelay(10);
+	}
+
+	i = 0;
+
+	while ((i++ < 10) && ((R_REG(&regs->ifsstat) & (1 << 8))))
+		udelay(10);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, ON);
+	}
+}
+
+void wlc_phy_hold_upd(wlc_phy_t *pih, mbool id, bool set)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	ASSERT(id);
+
+	if (set) {
+		mboolset(pi->measure_hold, id);
+	} else {
+		mboolclr(pi->measure_hold, id);
+	}
+
+	return;
+}
+
+void wlc_phy_mute_upd(wlc_phy_t *pih, bool mute, mbool flags)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (mute) {
+		mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	} else {
+		mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	}
+
+	if (!mute && (flags & PHY_MUTE_FOR_PREISM))
+		pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
+	return;
+}
+
+void wlc_phy_clear_tssi(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (ISNPHY(pi)) {
+		return;
+	} else {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
+	}
+}
+
+static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi)
+{
+	return false;
+}
+
+void wlc_phy_switch_radio(wlc_phy_t *pih, bool on)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	{
+		uint mc;
+
+		mc = R_REG(&pi->regs->maccontrol);
+	}
+
+	if (ISNPHY(pi)) {
+		wlc_phy_switch_radio_nphy(pi, on);
+
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x44c,
+				    ~((0x1 << 8) |
+				      (0x1 << 9) |
+				      (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
+			and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
+			and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
+		} else {
+			and_phy_reg(pi, 0x44d,
+				    ~((0x1 << 10) |
+				      (0x1 << 11) |
+				      (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
+			or_phy_reg(pi, 0x44c,
+				   (0x1 << 8) |
+				   (0x1 << 9) |
+				   (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
+
+			and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
+			and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
+			or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
+			and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
+			or_phy_reg(pi, 0x4f9, (0x1 << 3));
+		}
+	}
+}
+
+u16 wlc_phy_bw_state_get(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->bw;
+}
+
+void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->bw = bw;
+}
+
+void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	pi->radio_chanspec = newch;
+
+}
+
+chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->radio_chanspec;
+}
+
+void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 m_cur_channel;
+	chansetfn_t chanspec_set = NULL;
+
+	ASSERT(!wf_chspec_malformed(chanspec));
+
+	m_cur_channel = CHSPEC_CHANNEL(chanspec);
+	if (CHSPEC_IS5G(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_5G;
+	if (CHSPEC_IS40(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_40;
+	wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
+
+	chanspec_set = pi->pi_fptr.chanset;
+	if (chanspec_set)
+		(*chanspec_set) (pi, chanspec);
+
+}
+
+int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
+{
+	int range = -1;
+
+	if (freq < 2500)
+		range = WL_CHAN_FREQ_RANGE_2G;
+	else if (freq <= 5320)
+		range = WL_CHAN_FREQ_RANGE_5GL;
+	else if (freq <= 5700)
+		range = WL_CHAN_FREQ_RANGE_5GM;
+	else
+		range = WL_CHAN_FREQ_RANGE_5GH;
+
+	return range;
+}
+
+int wlc_phy_chanspec_bandrange_get(phy_info_t *pi, chanspec_t chanspec)
+{
+	int range = -1;
+	uint channel = CHSPEC_CHANNEL(chanspec);
+	uint freq = wlc_phy_channel2freq(channel);
+
+	if (ISNPHY(pi)) {
+		range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
+	} else if (ISLCNPHY(pi)) {
+		range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
+	} else
+		ASSERT(0);
+
+	return range;
+}
+
+void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi, bool wide_filter)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->channel_14_wide_filter = wide_filter;
+
+}
+
+int wlc_phy_channel2freq(uint channel)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
+		if (chan_info_all[i].chan == channel)
+			return chan_info_all[i].freq;
+	return 0;
+}
+
+void
+wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band, chanvec_t *channels)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint i;
+	uint channel;
+
+	ASSERT((band == WLC_BAND_2G) || (band == WLC_BAND_5G));
+
+	memset(channels, 0, sizeof(chanvec_t));
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
+		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
+			setbit(channels->vec, channel);
+	}
+}
+
+chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint i;
+	uint channel;
+	chanspec_t chspec;
+
+	ASSERT((band == WLC_BAND_2G) || (band == WLC_BAND_5G));
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if (ISNPHY(pi) && IS40MHZ(pi)) {
+			uint j;
+
+			for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
+				if (chan_info_all[j].chan ==
+				    channel + CH_10MHZ_APART)
+					break;
+			}
+
+			if (j == ARRAY_SIZE(chan_info_all))
+				continue;
+
+			channel = UPPER_20_SB(channel);
+			chspec =
+			    channel | WL_CHANSPEC_BW_40 |
+			    WL_CHANSPEC_CTL_SB_LOWER;
+			if (band == WLC_BAND_2G)
+				chspec |= WL_CHANSPEC_BAND_2G;
+			else
+				chspec |= WL_CHANSPEC_BAND_5G;
+		} else
+			chspec = CH20MHZ_CHSPEC(channel);
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
+		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
+			return chspec;
+	}
+
+	ASSERT(0);
+
+	return (chanspec_t) INVCHANSPEC;
+}
+
+int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	ASSERT(qdbm != NULL);
+	*qdbm = pi->tx_user_target[0];
+	if (override != NULL)
+		*override = pi->txpwroverride;
+	return 0;
+}
+
+void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr)
+{
+	bool mac_enabled = false;
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_CCK],
+	       &txpwr->cck[0], WLC_NUM_RATES_CCK);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM],
+	       &txpwr->ofdm[0], WLC_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
+	       &txpwr->ofdm_cdd[0], WLC_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO],
+	       &txpwr->ofdm_40_siso[0], WLC_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD],
+	       &txpwr->ofdm_40_cdd[0], WLC_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
+	       &txpwr->mcs_20_siso[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
+	       &txpwr->mcs_20_cdd[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
+	       &txpwr->mcs_20_stbc[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
+	       &txpwr->mcs_20_mimo[0], WLC_NUM_RATES_MCS_2_STREAM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
+	       &txpwr->mcs_40_siso[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
+	       &txpwr->mcs_40_cdd[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
+	       &txpwr->mcs_40_stbc[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
+	       &txpwr->mcs_40_mimo[0], WLC_NUM_RATES_MCS_2_STREAM);
+
+	if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
+		mac_enabled = true;
+
+	if (mac_enabled)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+
+	if (mac_enabled)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	int i;
+
+	if (qdbm > 127)
+		return 5;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->tx_user_target[i] = (u8) qdbm;
+
+	pi->txpwroverride = false;
+
+	if (pi->sh->up) {
+		if (!SCAN_INPROG_PHY(pi)) {
+			bool suspend;
+
+			suspend =
+			    (0 ==
+			     (R_REG(&pi->regs->maccontrol) &
+			      MCTL_EN_MAC));
+
+			if (!suspend)
+				wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+			wlc_phy_txpower_recalc_target(pi);
+			wlc_phy_cal_txpower_recalc_sw(pi);
+
+			if (!suspend)
+				wlapi_enable_mac(pi->sh->physhim);
+		}
+	}
+	return 0;
+}
+
+void
+wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint channel, u8 *min_pwr,
+			  u8 *max_pwr, int txp_rate_idx)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint i;
+
+	*min_pwr = pi->min_txpower * WLC_TXPWR_DB_FACTOR;
+
+	if (ISNPHY(pi)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
+						   (u8) txp_rate_idx);
+
+	} else if ((channel <= CH_MAX_2G_CHANNEL)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+	} else {
+
+		*max_pwr = WLC_TXPWR_MAX;
+
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_OFDM;
+
+		for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+			if (channel == chan_info_all[i].chan) {
+				break;
+			}
+		}
+		ASSERT(i < ARRAY_SIZE(chan_info_all));
+
+		if (pi->hwtxpwr) {
+			*max_pwr = pi->hwtxpwr[i];
+		} else {
+
+			if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+			if ((i >= FIRST_HIGH_5G_CHAN)
+			    && (i <= LAST_HIGH_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+			if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		}
+	}
+}
+
+void
+wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan, u8 *max_txpwr,
+				  u8 *min_txpwr)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 max_num_rate;
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+
+	pactrl = 0;
+
+	max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
+	    ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
+
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
+					  rate);
+
+		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+		tx_pwr_max = max(tx_pwr_max, maxtxpwr);
+		tx_pwr_min = min(tx_pwr_min, maxtxpwr);
+	}
+	*max_txpwr = tx_pwr_max;
+	*min_txpwr = tx_pwr_min;
+}
+
+void
+wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint bandunit, s32 *max_pwr,
+				s32 *min_pwr, u32 *step_pwr)
+{
+	return;
+}
+
+u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->tx_power_min;
+}
+
+u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->tx_power_max;
+}
+
+void wlc_phy_txpower_recalc_target(phy_info_t *pi)
+{
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+	uint target_chan;
+	u8 tx_pwr_target[TXP_NUM_RATES];
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 tx_pwr_max_rate_ind = 0;
+	u8 max_num_rate;
+	u8 start_rate = 0;
+	chanspec_t chspec;
+	u32 band = CHSPEC2WLC_BAND(pi->radio_chanspec);
+	initfn_t txpwr_recalc_fn = NULL;
+
+	chspec = pi->radio_chanspec;
+	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
+		target_chan = CHSPEC_CHANNEL(chspec);
+	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
+		target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
+	else
+		target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
+
+	pactrl = 0;
+	if (ISLCNPHY(pi)) {
+		u32 offset_mcs, i;
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			offset_mcs = pi->mcs40_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+				    pi->tx_srom_max_2g -
+				    ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		} else {
+			offset_mcs = pi->mcs20_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+				    pi->tx_srom_max_2g -
+				    ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+	}
+#if WL11N
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+			((ISLCNPHY(pi)) ?
+			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
+#else
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
+#endif
+
+	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
+
+	for (rate = start_rate; rate < max_num_rate; rate++) {
+
+		tx_pwr_target[rate] = pi->tx_user_target[rate];
+
+		if (pi->user_txpwr_at_rfport) {
+			tx_pwr_target[rate] +=
+			    wlc_user_txpwr_antport_to_rfport(pi, target_chan,
+							     band, rate);
+		}
+
+		{
+
+			wlc_phy_txpower_sromlimit((wlc_phy_t *) pi, target_chan,
+						  &mintxpwr, &maxtxpwr, rate);
+
+			maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
+
+			maxtxpwr =
+			    (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+			maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+			maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
+
+			if (pi->txpwr_percent <= 100)
+				maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
+
+			tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
+		}
+
+		tx_pwr_target[rate] =
+		    min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
+
+		if (tx_pwr_target[rate] > tx_pwr_max)
+			tx_pwr_max_rate_ind = rate;
+
+		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
+		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
+	}
+
+	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
+	pi->tx_power_max = tx_pwr_max;
+	pi->tx_power_min = tx_pwr_min;
+	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		pi->tx_power_target[rate] = tx_pwr_target[rate];
+
+		if (!pi->hwpwrctrl || ISNPHY(pi)) {
+			pi->tx_power_offset[rate] =
+			    pi->tx_power_max - pi->tx_power_target[rate];
+		} else {
+			pi->tx_power_offset[rate] =
+			    pi->tx_power_target[rate] - pi->tx_power_min;
+		}
+	}
+
+	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
+	if (txpwr_recalc_fn)
+		(*txpwr_recalc_fn) (pi);
+}
+
+void
+wlc_phy_txpower_reg_limit_calc(phy_info_t *pi, struct txpwr_limits *txpwr,
+			       chanspec_t chanspec)
+{
+	u8 tmp_txpwr_limit[2 * WLC_NUM_RATES_OFDM];
+	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
+	int rate_start_index = 0, rate1, rate2, k;
+
+	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
+
+	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
+
+	if (ISNPHY(pi)) {
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->mcs_20_siso;
+				txpwr_ptr2 = txpwr->ofdm;
+				rate_start_index = WL_TX_POWER_OFDM_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->mcs_20_cdd;
+				txpwr_ptr2 = txpwr->ofdm_cdd;
+				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->mcs_40_siso;
+				txpwr_ptr2 = txpwr->ofdm_40_siso;
+				rate_start_index =
+				    WL_TX_POWER_OFDM40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->mcs_40_cdd;
+				txpwr_ptr2 = txpwr->ofdm_40_cdd;
+				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
+				break;
+			}
+
+			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
+				    txpwr_ptr1[rate2];
+			}
+			wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
+							WLC_NUM_RATES_OFDM - 1,
+							WLC_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_OFDM; rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+				    min(txpwr_ptr2[rate2],
+					tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->ofdm;
+				txpwr_ptr2 = txpwr->mcs_20_siso;
+				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->ofdm_cdd;
+				txpwr_ptr2 = txpwr->mcs_20_cdd;
+				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->ofdm_40_siso;
+				txpwr_ptr2 = txpwr->mcs_40_siso;
+				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->ofdm_40_cdd;
+				txpwr_ptr2 = txpwr->mcs_40_cdd;
+				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
+				break;
+			}
+			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
+				    txpwr_ptr1[rate2];
+			}
+			wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
+							WLC_NUM_RATES_OFDM - 1,
+							WLC_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+				    min(txpwr_ptr2[rate2],
+					tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_stbc;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_stbc;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_mimo;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_mimo;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_MCS_2_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
+
+		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
+		    min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
+			pi->txpwr_limit[WL_TX_POWER_MCS_32]);
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
+		    pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
+	}
+}
+
+void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->txpwr_percent = txpwr_percent;
+}
+
+void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->sh->machwcap = machwcap;
+}
+
+void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 rxc;
+	rxc = 0;
+
+	if (start_end == ON) {
+		if (!ISNPHY(pi))
+			return;
+
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			W_REG(&pi->regs->phyregaddr, 0xa0);
+			(void)R_REG(&pi->regs->phyregaddr);
+			rxc = R_REG(&pi->regs->phyregdata);
+			W_REG(&pi->regs->phyregdata,
+			      (0x1 << 15) | rxc);
+		}
+	} else {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			W_REG(&pi->regs->phyregaddr, 0xa0);
+			(void)R_REG(&pi->regs->phyregaddr);
+			W_REG(&pi->regs->phyregdata, rxc);
+		}
+
+		wlc_phy_por_inform(ppi);
+	}
+}
+
+void
+wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr,
+			  chanspec_t chanspec)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
+
+	if (ISLCNPHY(pi)) {
+		int i, j;
+		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
+		     j < WLC_NUM_RATES_MCS_1_STREAM; i++, j++) {
+			if (txpwr->mcs_20_siso[j])
+				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
+			else
+				pi->txpwr_limit[i] = txpwr->ofdm[j];
+		}
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->ofdm_rateset_war = war;
+}
+
+void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->bf_preempt_4306 = bf_preempt;
+}
+
+void wlc_phy_txpower_update_shm(phy_info_t *pi)
+{
+	int j;
+	if (ISNPHY(pi)) {
+		ASSERT(0);
+		return;
+	}
+
+	if (!pi->sh->clk)
+		return;
+
+	if (pi->hwpwrctrl) {
+		u16 offset;
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
+				     1 << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
+				     pi->tx_power_min << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
+				     pi->hwpwr_txcur);
+
+		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
+			const u8 ucode_ofdm_rates[] = {
+				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+			};
+			offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
+							    ucode_ofdm_rates[j -
+									     TXP_FIRST_OFDM]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
+					     pi->tx_power_offset[j]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
+					     -(pi->tx_power_offset[j] / 2));
+		}
+
+		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
+			       MHF2_HWPWRCTL, WLC_BAND_ALL);
+	} else {
+		int i;
+
+		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
+			pi->tx_power_offset[i] =
+			    (u8) roundup(pi->tx_power_offset[i], 8);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
+				     (u16) ((pi->
+						tx_power_offset[TXP_FIRST_OFDM]
+						+ 7) >> 3));
+	}
+}
+
+bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	if (ISNPHY(pi)) {
+		return pi->nphy_txpwrctrl;
+	} else {
+		return pi->hwpwrctrl;
+	}
+}
+
+void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	bool cur_hwpwrctrl = pi->hwpwrctrl;
+	bool suspend;
+
+	if (!pi->hwpwrctrl_capable) {
+		return;
+	}
+
+	pi->hwpwrctrl = hwpwrctrl;
+	pi->nphy_txpwrctrl = hwpwrctrl;
+	pi->txpwrctrl = hwpwrctrl;
+
+	if (ISNPHY(pi)) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+			wlc_phy_txpwr_fixpower_nphy(pi);
+		} else {
+
+			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+				    pi->saved_txpwr_idx);
+		}
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	} else if (hwpwrctrl != cur_hwpwrctrl) {
+
+		return;
+	}
+}
+
+void wlc_phy_txpower_ipa_upd(phy_info_t *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
+		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
+	} else {
+		pi->ipa2g_on = false;
+		pi->ipa5g_on = false;
+	}
+}
+
+static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi);
+
+static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi)
+{
+	s16 tx0_status, tx1_status;
+	u16 estPower1, estPower2;
+	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
+	u32 est_pwr;
+
+	estPower1 = read_phy_reg(pi, 0x118);
+	estPower2 = read_phy_reg(pi, 0x119);
+
+	if ((estPower1 & (0x1 << 8))
+	    == (0x1 << 8)) {
+		pwr0 = (u8) (estPower1 & (0xff << 0))
+		    >> 0;
+	} else {
+		pwr0 = 0x80;
+	}
+
+	if ((estPower2 & (0x1 << 8))
+	    == (0x1 << 8)) {
+		pwr1 = (u8) (estPower2 & (0xff << 0))
+		    >> 0;
+	} else {
+		pwr1 = 0x80;
+	}
+
+	tx0_status = read_phy_reg(pi, 0x1ed);
+	tx1_status = read_phy_reg(pi, 0x1ee);
+
+	if ((tx0_status & (0x1 << 15))
+	    == (0x1 << 15)) {
+		adj_pwr0 = (u8) (tx0_status & (0xff << 0))
+		    >> 0;
+	} else {
+		adj_pwr0 = 0x80;
+	}
+	if ((tx1_status & (0x1 << 15))
+	    == (0x1 << 15)) {
+		adj_pwr1 = (u8) (tx1_status & (0xff << 0))
+		    >> 0;
+	} else {
+		adj_pwr1 = 0x80;
+	}
+
+	est_pwr =
+	    (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
+	return est_pwr;
+}
+
+void
+wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power, uint channel)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint rate, num_rates;
+	u8 min_pwr, max_pwr;
+
+#if WL_TX_POWER_RATES != TXP_NUM_RATES
+#error "tx_power_t struct out of sync with this fn"
+#endif
+
+	if (ISNPHY(pi)) {
+		power->rf_cores = 2;
+		power->flags |= (WL_TX_POWER_F_MIMO);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+			power->flags |=
+			    (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
+	} else if (ISLCNPHY(pi)) {
+		power->rf_cores = 1;
+		power->flags |= (WL_TX_POWER_F_SISO);
+		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
+			power->flags |= WL_TX_POWER_F_ENABLED;
+		if (pi->hwpwrctrl)
+			power->flags |= WL_TX_POWER_F_HW;
+	}
+
+	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+		     ((ISLCNPHY(pi)) ?
+		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
+
+	for (rate = 0; rate < num_rates; rate++) {
+		power->user_limit[rate] = pi->tx_user_target[rate];
+		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
+					  rate);
+		power->board_limit[rate] = (u8) max_pwr;
+		power->target[rate] = pi->tx_power_target[rate];
+	}
+
+	if (ISNPHY(pi)) {
+		u32 est_pout;
+
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_phyreg_enter((wlc_phy_t *) pi);
+		est_pout = wlc_phy_txpower_est_power_nphy(pi);
+		wlc_phyreg_exit((wlc_phy_t *) pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		power->est_Pout[0] = (est_pout >> 8) & 0xff;
+		power->est_Pout[1] = est_pout & 0xff;
+
+		power->est_Pout_act[0] = est_pout >> 24;
+		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
+
+		if (power->est_Pout[0] == 0x80)
+			power->est_Pout[0] = 0;
+		if (power->est_Pout[1] == 0x80)
+			power->est_Pout[1] = 0;
+
+		if (power->est_Pout_act[0] == 0x80)
+			power->est_Pout_act[0] = 0;
+		if (power->est_Pout_act[1] == 0x80)
+			power->est_Pout_act[1] = 0;
+
+		power->est_Pout_cck = 0;
+
+		power->tx_power_max[0] = pi->tx_power_max;
+		power->tx_power_max[1] = pi->tx_power_max;
+
+		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
+		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
+	} else if (!pi->hwpwrctrl) {
+	} else if (pi->sh->up) {
+
+		wlc_phyreg_enter(ppi);
+		if (ISLCNPHY(pi)) {
+
+			power->tx_power_max[0] = pi->tx_power_max;
+			power->tx_power_max[1] = pi->tx_power_max;
+
+			power->tx_power_max_rate_ind[0] =
+			    pi->tx_power_max_rate_ind;
+			power->tx_power_max_rate_ind[1] =
+			    pi->tx_power_max_rate_ind;
+
+			if (wlc_phy_tpc_isenabled_lcnphy(pi))
+				power->flags |=
+				    (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+			else
+				power->flags &=
+				    ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+
+			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
+					    (s8 *) &power->est_Pout_cck);
+		}
+		wlc_phyreg_exit(ppi);
+	}
+}
+
+void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->antsel_type = antsel_type;
+}
+
+bool wlc_phy_test_ison(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->phytest_on;
+}
+
+bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	bool ret = true;
+
+	wlc_phyreg_enter(ppi);
+
+	if (ISNPHY(pi)) {
+
+		ret = false;
+	} else if (ISLCNPHY(pi)) {
+		u16 crsctrl = read_phy_reg(pi, 0x410);
+		u16 div = crsctrl & (0x1 << 1);
+		*pval = (div | ((crsctrl & (0x1 << 0)) ^ (div >> 1)));
+	}
+
+	wlc_phyreg_exit(ppi);
+
+	return ret;
+}
+
+void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	bool suspend;
+
+	pi->sh->rx_antdiv = val;
+
+	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
+		if (val > ANT_RX_DIV_FORCE_1)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
+				       MHF1_ANTDIV, WLC_BAND_ALL);
+		else
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
+				       WLC_BAND_ALL);
+	}
+
+	if (ISNPHY(pi)) {
+
+		return;
+	}
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (ISLCNPHY(pi)) {
+		if (val > ANT_RX_DIV_FORCE_1) {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
+			mod_phy_reg(pi, 0x410,
+				    (0x1 << 0),
+				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
+		} else {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
+			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
+		}
+	} else {
+		ASSERT(0);
+	}
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return;
+}
+
+static bool
+wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr, s8 *pwr_ant)
+{
+	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
+	u8 i;
+
+	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
+	ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
+	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
+		else
+
+			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
+	}
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
+		pwr_ant[i] = cmplx_pwr_dbm[i];
+	}
+	pi->nphy_noise_index =
+	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+	return true;
+}
+
+static void
+wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason, u8 ch)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	bool sampling_in_progress = (pi->phynoise_state != 0);
+	bool wait_for_intr = true;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		return;
+	}
+
+	switch (reason) {
+	case PHY_NOISE_SAMPLE_MON:
+
+		pi->phynoise_chan_watchdog = ch;
+		pi->phynoise_state |= PHY_NOISE_STATE_MON;
+
+		break;
+
+	case PHY_NOISE_SAMPLE_EXTERNAL:
+
+		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
+		break;
+
+	default:
+		ASSERT(0);
+		break;
+	}
+
+	if (sampling_in_progress)
+		return;
+
+	pi->phynoise_now = pi->sh->now;
+
+	if (pi->phy_fixed_noise) {
+		if (ISNPHY(pi)) {
+			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
+			    PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
+			    PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+		} else {
+
+			noise_dbm = PHY_NOISE_FIXED_VAL;
+		}
+
+		wait_for_intr = false;
+		goto done;
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			OR_REG(&pi->regs->maccommand,
+			       MCMD_BG_NOISE);
+		} else {
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_lcnphy_deaf_mode(pi, (bool) 0);
+			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
+			wlc_lcnphy_deaf_mode(pi, (bool) 1);
+			wlapi_enable_mac(pi->sh->physhim);
+			wait_for_intr = false;
+		}
+	} else if (ISNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			OR_REG(&pi->regs->maccommand,
+			       MCMD_BG_NOISE);
+		} else {
+			phy_iq_est_t est[PHY_CORE_MAX];
+			u32 cmplx_pwr[PHY_CORE_MAX];
+			s8 noise_dbm_ant[PHY_CORE_MAX];
+			u16 log_num_samps, num_samps, classif_state = 0;
+			u8 wait_time = 32;
+			u8 wait_crs = 0;
+			u8 i;
+
+			memset((u8 *) est, 0, sizeof(est));
+			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+			num_samps = 1 << log_num_samps;
+
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, 3, 0);
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
+					       wait_crs);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+			wlapi_enable_mac(pi->sh->physhim);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++)
+				cmplx_pwr[i] =
+				    (est[i].i_pwr +
+				     est[i].q_pwr) >> log_num_samps;
+
+			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+				pi->nphy_noise_win[i][pi->nphy_noise_index] =
+				    noise_dbm_ant[i];
+
+				if (noise_dbm_ant[i] > noise_dbm)
+					noise_dbm = noise_dbm_ant[i];
+			}
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			wait_for_intr = false;
+		}
+	}
+
+ done:
+
+	if (!wait_for_intr)
+		wlc_phy_noise_cb(pi, ch, noise_dbm);
+
+}
+
+void wlc_phy_noise_sample_request_external(wlc_phy_t *pih)
+{
+	u8 channel;
+
+	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
+
+	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
+}
+
+static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm)
+{
+	if (!pi->phynoise_state)
+		return;
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
+		if (pi->phynoise_chan_watchdog == channel) {
+			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
+			    noise_dbm;
+			pi->sh->phy_noise_index =
+			    MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
+		}
+		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
+	}
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
+		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
+	}
+
+}
+
+static s8 wlc_phy_noise_read_shmem(phy_info_t *pi)
+{
+	u32 cmplx_pwr[PHY_CORE_MAX];
+	s8 noise_dbm_ant[PHY_CORE_MAX];
+	u16 lo, hi;
+	u32 cmplx_pwr_tot = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	u8 idx, core;
+
+	ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
+	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
+		hi = wlapi_bmac_read_shm(pi->sh->physhim,
+					 M_PWRIND_MAP(idx + 1));
+		cmplx_pwr[core] = (hi << 16) + lo;
+		cmplx_pwr_tot += cmplx_pwr[core];
+		if (cmplx_pwr[core] == 0) {
+			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
+		} else
+			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
+	}
+
+	if (cmplx_pwr_tot != 0)
+		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		pi->nphy_noise_win[core][pi->nphy_noise_index] =
+		    noise_dbm_ant[core];
+
+		if (noise_dbm_ant[core] > noise_dbm)
+			noise_dbm = noise_dbm_ant[core];
+	}
+	pi->nphy_noise_index =
+	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+
+	return noise_dbm;
+
+}
+
+void wlc_phy_noise_sample_intr(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	u16 jssi_aux;
+	u8 channel = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+
+	if (ISLCNPHY(pi)) {
+		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
+		u16 lo, hi;
+		s32 pwr_offset_dB, gain_dB;
+		u16 status_0, status_1;
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
+		cmplx_pwr0 = (hi << 16) + lo;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
+		cmplx_pwr1 = (hi << 16) + lo;
+		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
+
+		status_0 = 0x44;
+		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
+		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
+		    && ((status_1 & 0xc000) == 0x4000)) {
+
+			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
+					   pi->pubpi.phy_corenum);
+			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
+			if (pwr_offset_dB > 127)
+				pwr_offset_dB -= 256;
+
+			noise_dbm += (s8) (pwr_offset_dB - 30);
+
+			gain_dB = (status_0 & 0x1ff);
+			noise_dbm -= (s8) (gain_dB);
+		} else {
+			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
+		}
+	} else if (ISNPHY(pi)) {
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		noise_dbm = wlc_phy_noise_read_shmem(pi);
+	} else {
+		ASSERT(0);
+	}
+
+	wlc_phy_noise_cb(pi, channel, noise_dbm);
+
+}
+
+s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	9,
+	10,
+	8,
+	8,
+	7,
+	7,
+	1,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	1,
+	1,
+	0,
+	0,
+	0,
+	0
+};
+
+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
+{
+	u8 shift_ct, lsb, msb, secondmsb, i;
+	u32 tmp;
+
+	for (i = 0; i < core; i++) {
+		tmp = cmplx_pwr[i];
+		shift_ct = msb = secondmsb = 0;
+		while (tmp != 0) {
+			tmp = tmp >> 1;
+			shift_ct++;
+			lsb = (u8) (tmp & 1);
+			if (lsb == 1)
+				msb = shift_ct;
+		}
+		secondmsb = (u8) ((cmplx_pwr[i] >> (msb - 1)) & 1);
+		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
+	}
+}
+
+void BCMFASTPATH wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx)
+{
+	wlc_d11rxhdr_t *wlc_rxhdr = (wlc_d11rxhdr_t *) ctx;
+	d11rxhdr_t *rxh = &wlc_rxhdr->rxhdr;
+	int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
+	uint radioid = pih->radioid;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		rssi = WLC_RSSI_INVALID;
+		goto end;
+	}
+
+	if ((pi->sh->corerev >= 11)
+	    && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
+		rssi = WLC_RSSI_INVALID;
+		goto end;
+	}
+
+	if (ISLCNPHY(pi)) {
+		u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
+		phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+		if (rssi > 127)
+			rssi -= 256;
+
+		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
+		if ((rssi > -46) && (gidx > 18))
+			rssi = rssi + 7;
+
+		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
+
+		rssi = rssi + 2;
+
+	}
+
+	if (ISLCNPHY(pi)) {
+
+		if (rssi > 127)
+			rssi -= 256;
+	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
+		   || radioid == BCM2057_ID) {
+		ASSERT(ISNPHY(pi));
+		rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
+	} else {
+		ASSERT((const char *)"Unknown radio" == NULL);
+	}
+
+ end:
+	wlc_rxhdr->rssi = (s8) rssi;
+}
+
+void wlc_phy_freqtrack_start(wlc_phy_t *pih)
+{
+	return;
+}
+
+void wlc_phy_freqtrack_end(wlc_phy_t *pih)
+{
+	return;
+}
+
+void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag)
+{
+	phy_info_t *pi;
+	pi = (phy_info_t *) ppi;
+
+	if (ISLCNPHY(pi))
+		wlc_lcnphy_deaf_mode(pi, true);
+	else if (ISNPHY(pi))
+		wlc_nphy_deaf_mode(pi, true);
+	else {
+		ASSERT(0);
+	}
+}
+
+void wlc_phy_watchdog(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	bool delay_phy_cal = false;
+	pi->sh->now++;
+
+	if (!pi->watchdog_override)
+		return;
+
+	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
+		wlc_phy_noise_sample_request((wlc_phy_t *) pi,
+					     PHY_NOISE_SAMPLE_MON,
+					     CHSPEC_CHANNEL(pi->
+							    radio_chanspec));
+	}
+
+	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
+		pi->phynoise_state = 0;
+	}
+
+	if ((!pi->phycal_txpower) ||
+	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
+
+		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
+			pi->phycal_txpower = pi->sh->now;
+		}
+	}
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+	     || ASSOC_INPROG_PHY(pi)))
+		return;
+
+	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
+
+		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
+		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
+		    ((pi->sh->now - pi->nphy_perical_last) >=
+		     pi->sh->glacial_timer))
+			wlc_phy_cal_perical((wlc_phy_t *) pi,
+					    PHY_PERICAL_WATCHDOG);
+
+		wlc_phy_txpwr_papd_cal_nphy(pi);
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (pi->phy_forcecal ||
+		    ((pi->sh->now - pi->phy_lastcal) >=
+		     pi->sh->glacial_timer)) {
+			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
+				wlc_lcnphy_calib_modes(pi,
+						       LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+			if (!
+			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+			     || ASSOC_INPROG_PHY(pi)
+			     || pi->carrier_suppr_disable
+			     || pi->disable_percal))
+				wlc_lcnphy_calib_modes(pi,
+						       PHY_PERICAL_WATCHDOG);
+		}
+	}
+}
+
+void wlc_phy_BSSinit(wlc_phy_t *pih, bool bonlyap, int rssi)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	uint i;
+	uint k;
+
+	for (i = 0; i < MA_WINDOW_SZ; i++) {
+		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
+	}
+	if (ISLCNPHY(pi)) {
+		for (i = 0; i < MA_WINDOW_SZ; i++)
+			pi->sh->phy_noise_window[i] =
+			    PHY_NOISE_FIXED_VAL_LCNPHY;
+	}
+	pi->sh->phy_noise_index = 0;
+
+	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
+		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
+			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
+	}
+	pi->nphy_noise_index = 0;
+}
+
+void
+wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
+{
+	*eps_imag = (epsilon >> 13);
+	if (*eps_imag > 0xfff)
+		*eps_imag -= 0x2000;
+
+	*eps_real = (epsilon & 0x1fff);
+	if (*eps_real > 0xfff)
+		*eps_real -= 0x2000;
+}
+
+static const fixed AtanTbl[] = {
+	2949120,
+	1740967,
+	919879,
+	466945,
+	234379,
+	117304,
+	58666,
+	29335,
+	14668,
+	7334,
+	3667,
+	1833,
+	917,
+	458,
+	229,
+	115,
+	57,
+	29
+};
+
+void wlc_phy_cordic(fixed theta, cs32 *val)
+{
+	fixed angle, valtmp;
+	unsigned iter;
+	int signx = 1;
+	int signtheta;
+
+	val[0].i = CORDIC_AG;
+	val[0].q = 0;
+	angle = 0;
+
+	signtheta = (theta < 0) ? -1 : 1;
+	theta =
+	    ((theta + FIXED(180) * signtheta) % FIXED(360)) -
+	    FIXED(180) * signtheta;
+
+	if (FLOAT(theta) > 90) {
+		theta -= FIXED(180);
+		signx = -1;
+	} else if (FLOAT(theta) < -90) {
+		theta += FIXED(180);
+		signx = -1;
+	}
+
+	for (iter = 0; iter < CORDIC_NI; iter++) {
+		if (theta > angle) {
+			valtmp = val[0].i - (val[0].q >> iter);
+			val[0].q = (val[0].i >> iter) + val[0].q;
+			val[0].i = valtmp;
+			angle += AtanTbl[iter];
+		} else {
+			valtmp = val[0].i + (val[0].q >> iter);
+			val[0].q = -(val[0].i >> iter) + val[0].q;
+			val[0].i = valtmp;
+			angle -= AtanTbl[iter];
+		}
+	}
+
+	val[0].i = val[0].i * signx;
+	val[0].q = val[0].q * signx;
+}
+
+void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi)
+{
+	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay)
+{
+
+	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
+	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
+		return;
+
+	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+}
+
+void wlc_phy_cal_perical(wlc_phy_t *pih, u8 reason)
+{
+	s16 nphy_currtemp = 0;
+	s16 delta_temp = 0;
+	bool do_periodic_cal = true;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (!ISNPHY(pi))
+		return;
+
+	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
+	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
+		return;
+
+	switch (reason) {
+	case PHY_PERICAL_DRIVERUP:
+		break;
+
+	case PHY_PERICAL_PHYINIT:
+		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+			if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+				wlc_phy_cal_perical_mphase_reset(pi);
+			}
+			wlc_phy_cal_perical_mphase_schedule(pi,
+							    PHY_PERICAL_INIT_DELAY);
+		}
+		break;
+
+	case PHY_PERICAL_JOIN_BSS:
+	case PHY_PERICAL_START_IBSS:
+	case PHY_PERICAL_UP_BSS:
+		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
+		    PHY_PERICAL_MPHASE_PENDING(pi)) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+		}
+
+		pi->first_cal_after_assoc = true;
+
+		pi->cal_type_override = PHY_PERICAL_FULL;
+
+		if (pi->phycal_tempdelta) {
+			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
+		}
+		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
+		break;
+
+	case PHY_PERICAL_WATCHDOG:
+		if (pi->phycal_tempdelta) {
+			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+			delta_temp =
+			    (nphy_currtemp > pi->nphy_lastcal_temp) ?
+			    nphy_currtemp - pi->nphy_lastcal_temp :
+			    pi->nphy_lastcal_temp - nphy_currtemp;
+
+			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
+			    (pi->nphy_txiqlocal_chanspec ==
+			     pi->radio_chanspec)) {
+				do_periodic_cal = false;
+			} else {
+				pi->nphy_lastcal_temp = nphy_currtemp;
+			}
+		}
+
+		if (do_periodic_cal) {
+
+			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+
+				if (!PHY_PERICAL_MPHASE_PENDING(pi))
+					wlc_phy_cal_perical_mphase_schedule(pi,
+									    PHY_PERICAL_WDOG_DELAY);
+			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
+				wlc_phy_cal_perical_nphy_run(pi,
+							     PHY_PERICAL_AUTO);
+			else {
+				ASSERT(0);
+			}
+		}
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+}
+
+void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi)
+{
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+u8 wlc_phy_nbits(s32 value)
+{
+	s32 abs_val;
+	u8 nbits = 0;
+
+	abs_val = ABS(value);
+	while ((abs_val >> nbits) > 0)
+		nbits++;
+
+	return nbits;
+}
+
+u32 wlc_phy_sqrt_int(u32 value)
+{
+	u32 root = 0, shift = 0;
+
+	for (shift = 0; shift < 32; shift += 2) {
+		if (((0x40000000 >> shift) + root) <= value) {
+			value -= ((0x40000000 >> shift) + root);
+			root = (root >> 1) | (0x40000000 >> shift);
+		} else {
+			root = root >> 1;
+		}
+	}
+
+	if (root < value)
+		++root;
+
+	return root;
+}
+
+void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain, u8 rxchain)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->sh->hw_phytxchain = txchain;
+	pi->sh->hw_phyrxchain = rxchain;
+	pi->sh->phytxchain = txchain;
+	pi->sh->phyrxchain = rxchain;
+	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain, u8 rxchain)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->sh->phytxchain = txchain;
+
+	if (ISNPHY(pi)) {
+		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
+	}
+	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain, u8 *rxchain)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	*txchain = pi->sh->phytxchain;
+	*rxchain = pi->sh->phyrxchain;
+}
+
+u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih)
+{
+	s16 nphy_currtemp;
+	u8 active_bitmap;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
+
+	if (!pi->watchdog_override)
+		return active_bitmap;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		if (!pi->phy_txcore_heatedup) {
+			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
+				active_bitmap &= 0xFD;
+				pi->phy_txcore_heatedup = true;
+			}
+		} else {
+			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
+				active_bitmap |= 0x2;
+				pi->phy_txcore_heatedup = false;
+			}
+		}
+	}
+
+	return active_bitmap;
+}
+
+s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	u8 siso_mcs_id, cdd_mcs_id;
+
+	siso_mcs_id =
+	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
+	    TXP_FIRST_MCS_20_SISO;
+	cdd_mcs_id =
+	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
+	    TXP_FIRST_MCS_20_CDD;
+
+	if (pi->tx_power_target[siso_mcs_id] >
+	    (pi->tx_power_target[cdd_mcs_id] + 12))
+		return PHY_TXC1_MODE_SISO;
+	else
+		return PHY_TXC1_MODE_CDD;
+}
+
+const u8 *wlc_phy_get_ofdm_rate_lookup(void)
+{
+	return ofdm_rate_lookup;
+}
+
+void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode)
+{
+	if ((pi->sh->chip == BCM4313_CHIP_ID) &&
+	    (pi->sh->boardflags & BFL_FEM)) {
+		if (mode) {
+			u16 txant = 0;
+			txant = wlapi_bmac_get_txant(pi->sh->physhim);
+			if (txant == 1) {
+				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
+
+			}
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
+				   0x0);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioout), 0x40, 0x40);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioouten), 0x40,
+				   0x40);
+		} else {
+			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
+
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioout), 0x40, 0x00);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
+				   0x40);
+		}
+	}
+}
+
+static s8
+wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan, u32 band,
+				 u8 rate)
+{
+	s8 offset = 0;
+
+	if (!pi->user_txpwr_at_rfport)
+		return offset;
+	return offset;
+}
+
+static s8 wlc_phy_env_measure_vbat(phy_info_t *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_vbatsense(pi, 0);
+	else
+		return 0;
+}
+
+static s8 wlc_phy_env_measure_temperature(phy_info_t *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_tempsense_degree(pi, 0);
+	else
+		return 0;
+}
+
+static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band)
+{
+	u8 i;
+	s8 temp, vbat;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
+
+	vbat = wlc_phy_env_measure_vbat(pi);
+	temp = wlc_phy_env_measure_temperature(pi);
+
+}
+
+void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool ldpc)
+{
+	return;
+}
+
+void
+wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset, s8 *ofdmoffset)
+{
+	*cckoffset = 0;
+	*ofdmoffset = 0;
+}
+
+u32 wlc_phy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, roundup, rbit;
+
+	ASSERT(divisor);
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+	rbit = divisor & 1;
+	roundup = (divisor >> 1) + rbit;
+
+	while (precision--) {
+		quotient <<= 1;
+		if (remainder >= roundup) {
+			quotient++;
+			remainder = ((remainder - roundup) << 1) + rbit;
+		} else {
+			remainder <<= 1;
+		}
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
+}
+
+s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi, chanspec_t chanspec)
+{
+
+	return rssi;
+}
+
+bool wlc_phy_txpower_ipa_ison(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	if (ISNPHY(pi))
+		return wlc_phy_n_txpower_ipa_ison(pi);
+	else
+		return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h
new file mode 100644
index 0000000..bf962d5
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_phy_h_
+#define _wlc_phy_h_
+
+#include <wlioctl.h>
+#include <siutils.h>
+#include <d11.h>
+#include <wlc_phy_shim.h>
+
+#define	IDCODE_VER_MASK		0x0000000f
+#define	IDCODE_VER_SHIFT	0
+#define	IDCODE_MFG_MASK		0x00000fff
+#define	IDCODE_MFG_SHIFT	0
+#define	IDCODE_ID_MASK		0x0ffff000
+#define	IDCODE_ID_SHIFT		12
+#define	IDCODE_REV_MASK		0xf0000000
+#define	IDCODE_REV_SHIFT	28
+
+#define	NORADIO_ID		0xe4f5
+#define	NORADIO_IDCODE		0x4e4f5246
+
+#define BCM2055_ID		0x2055
+#define BCM2055_IDCODE		0x02055000
+#define BCM2055A0_IDCODE	0x1205517f
+
+#define BCM2056_ID		0x2056
+#define BCM2056_IDCODE		0x02056000
+#define BCM2056A0_IDCODE	0x1205617f
+
+#define BCM2057_ID		0x2057
+#define BCM2057_IDCODE		0x02057000
+#define BCM2057A0_IDCODE	0x1205717f
+
+#define BCM2064_ID		0x2064
+#define BCM2064_IDCODE		0x02064000
+#define BCM2064A0_IDCODE	0x0206417f
+
+#define PHY_TPC_HW_OFF		false
+#define PHY_TPC_HW_ON		true
+
+#define PHY_PERICAL_DRIVERUP	1
+#define PHY_PERICAL_WATCHDOG	2
+#define PHY_PERICAL_PHYINIT	3
+#define PHY_PERICAL_JOIN_BSS	4
+#define PHY_PERICAL_START_IBSS	5
+#define PHY_PERICAL_UP_BSS	6
+#define PHY_PERICAL_CHAN	7
+#define PHY_FULLCAL	8
+
+#define PHY_PERICAL_DISABLE	0
+#define PHY_PERICAL_SPHASE	1
+#define PHY_PERICAL_MPHASE	2
+#define PHY_PERICAL_MANUAL	3
+
+#define PHY_HOLD_FOR_ASSOC	1
+#define PHY_HOLD_FOR_SCAN	2
+#define PHY_HOLD_FOR_RM		4
+#define PHY_HOLD_FOR_PLT	8
+#define PHY_HOLD_FOR_MUTE	16
+#define PHY_HOLD_FOR_NOT_ASSOC 0x20
+
+#define PHY_MUTE_FOR_PREISM	1
+#define PHY_MUTE_ALL		0xffffffff
+
+#define PHY_NOISE_FIXED_VAL 		(-95)
+#define PHY_NOISE_FIXED_VAL_NPHY       	(-92)
+#define PHY_NOISE_FIXED_VAL_LCNPHY     	(-92)
+
+#define PHY_MODE_CAL		0x0002
+#define PHY_MODE_NOISEM		0x0004
+
+#define WLC_TXPWR_DB_FACTOR	4
+
+#define WLC_NUM_RATES_CCK           4
+#define WLC_NUM_RATES_OFDM          8
+#define WLC_NUM_RATES_MCS_1_STREAM  8
+#define WLC_NUM_RATES_MCS_2_STREAM  8
+#define WLC_NUM_RATES_MCS_3_STREAM  8
+#define WLC_NUM_RATES_MCS_4_STREAM  8
+typedef struct txpwr_limits {
+	u8 cck[WLC_NUM_RATES_CCK];
+	u8 ofdm[WLC_NUM_RATES_OFDM];
+
+	u8 ofdm_cdd[WLC_NUM_RATES_OFDM];
+
+	u8 ofdm_40_siso[WLC_NUM_RATES_OFDM];
+	u8 ofdm_40_cdd[WLC_NUM_RATES_OFDM];
+
+	u8 mcs_20_siso[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_cdd[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_stbc[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_mimo[WLC_NUM_RATES_MCS_2_STREAM];
+
+	u8 mcs_40_siso[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_cdd[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_stbc[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_mimo[WLC_NUM_RATES_MCS_2_STREAM];
+	u8 mcs32;
+} txpwr_limits_t;
+
+typedef struct {
+	u8 vec[MAXCHANNEL / NBBY];
+} chanvec_t;
+
+struct rpc_info;
+typedef struct shared_phy shared_phy_t;
+
+struct phy_pub;
+
+typedef struct phy_pub wlc_phy_t;
+
+typedef struct shared_phy_params {
+	si_t *sih;
+	void *physhim;
+	uint unit;
+	uint corerev;
+	uint bustype;
+	uint buscorerev;
+	char *vars;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	uint boardvendor;
+	u32 boardflags;
+	u32 boardflags2;
+} shared_phy_params_t;
+
+
+extern shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp);
+extern void wlc_phy_shared_detach(shared_phy_t *phy_sh);
+extern wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype,
+				 char *vars);
+extern void wlc_phy_detach(wlc_phy_t *ppi);
+
+extern bool wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype,
+				   u16 *phyrev, u16 *radioid,
+				   u16 *radiover);
+extern bool wlc_phy_get_encore(wlc_phy_t *pih);
+extern u32 wlc_phy_get_coreflags(wlc_phy_t *pih);
+
+extern void wlc_phy_hw_clk_state_upd(wlc_phy_t *ppi, bool newstate);
+extern void wlc_phy_hw_state_upd(wlc_phy_t *ppi, bool newstate);
+extern void wlc_phy_init(wlc_phy_t *ppi, chanspec_t chanspec);
+extern void wlc_phy_watchdog(wlc_phy_t *ppi);
+extern int wlc_phy_down(wlc_phy_t *ppi);
+extern u32 wlc_phy_clk_bwbits(wlc_phy_t *pih);
+extern void wlc_phy_cal_init(wlc_phy_t *ppi);
+extern void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init);
+
+extern void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec);
+extern chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi);
+extern void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch);
+extern u16 wlc_phy_bw_state_get(wlc_phy_t *ppi);
+extern void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw);
+
+extern void wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx);
+extern void wlc_phy_por_inform(wlc_phy_t *ppi);
+extern void wlc_phy_noise_sample_intr(wlc_phy_t *ppi);
+extern bool wlc_phy_bist_check_phy(wlc_phy_t *ppi);
+
+extern void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag);
+
+extern void wlc_phy_switch_radio(wlc_phy_t *ppi, bool on);
+extern void wlc_phy_anacore(wlc_phy_t *ppi, bool on);
+
+
+extern void wlc_phy_BSSinit(wlc_phy_t *ppi, bool bonlyap, int rssi);
+
+extern void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi,
+						 bool wide_filter);
+extern void wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band,
+					  chanvec_t *channels);
+extern chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band);
+
+extern void wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint chan,
+				      u8 *_min_, u8 *_max_, int rate);
+extern void wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan,
+					      u8 *_max_, u8 *_min_);
+extern void wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint band, s32 *,
+					    s32 *, u32 *);
+extern void wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *,
+				      chanspec_t chanspec);
+extern int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override);
+extern int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override);
+extern void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *);
+extern bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi);
+extern void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl);
+extern u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi);
+extern u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi);
+extern bool wlc_phy_txpower_ipa_ison(wlc_phy_t *pih);
+
+extern void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain,
+				   u8 rxchain);
+extern void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain,
+				  u8 rxchain);
+extern void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain,
+				  u8 *rxchain);
+extern u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih);
+extern s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec);
+extern void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool val);
+
+extern void wlc_phy_cal_perical(wlc_phy_t *ppi, u8 reason);
+extern void wlc_phy_noise_sample_request_external(wlc_phy_t *ppi);
+extern void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock);
+extern void wlc_phy_cal_papd_recal(wlc_phy_t *ppi);
+
+extern void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val);
+extern bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval);
+extern void wlc_phy_clear_tssi(wlc_phy_t *ppi);
+extern void wlc_phy_hold_upd(wlc_phy_t *ppi, mbool id, bool val);
+extern void wlc_phy_mute_upd(wlc_phy_t *ppi, bool val, mbool flags);
+
+extern void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type);
+
+extern void wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power,
+					uint channel);
+
+extern void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal);
+extern bool wlc_phy_test_ison(wlc_phy_t *ppi);
+extern void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent);
+extern void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war);
+extern void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt);
+extern void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap);
+
+extern void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end);
+
+extern void wlc_phy_freqtrack_start(wlc_phy_t *ppi);
+extern void wlc_phy_freqtrack_end(wlc_phy_t *ppi);
+
+extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
+
+extern s8 wlc_phy_get_tx_power_offset_by_mcs(wlc_phy_t *ppi,
+					       u8 mcs_offset);
+extern s8 wlc_phy_get_tx_power_offset(wlc_phy_t *ppi, u8 tbl_offset);
+#endif				/* _wlc_phy_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h
new file mode 100644
index 0000000..6e12a95
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_phy_int_h_
+#define _wlc_phy_int_h_
+
+#include <linux/kernel.h>
+#include <bcmdefs.h>
+#include <bcmutils.h>
+
+#include <bcmsrom_fmt.h>
+#include <wlc_phy_hal.h>
+
+#define PHYHAL_ERROR	0x0001
+#define PHYHAL_TRACE	0x0002
+#define PHYHAL_INFORM	0x0004
+
+extern u32 phyhal_msg_level;
+
+#define PHY_INFORM_ON()		(phyhal_msg_level & PHYHAL_INFORM)
+#define PHY_THERMAL_ON()	(phyhal_msg_level & PHYHAL_THERMAL)
+#define PHY_CAL_ON()		(phyhal_msg_level & PHYHAL_CAL)
+
+#ifdef BOARD_TYPE
+#define BOARDTYPE(_type) BOARD_TYPE
+#else
+#define BOARDTYPE(_type) _type
+#endif
+
+#define LCNXN_BASEREV		16
+
+struct wlc_hw_info;
+typedef struct phy_info phy_info_t;
+typedef void (*initfn_t) (phy_info_t *);
+typedef void (*chansetfn_t) (phy_info_t *, chanspec_t);
+typedef int (*longtrnfn_t) (phy_info_t *, int);
+typedef void (*txiqccgetfn_t) (phy_info_t *, u16 *, u16 *);
+typedef void (*txiqccsetfn_t) (phy_info_t *, u16, u16);
+typedef u16(*txloccgetfn_t) (phy_info_t *);
+typedef void (*radioloftgetfn_t) (phy_info_t *, u8 *, u8 *, u8 *,
+				  u8 *);
+typedef s32(*rxsigpwrfn_t) (phy_info_t *, s32);
+typedef void (*detachfn_t) (phy_info_t *);
+
+#undef ISNPHY
+#undef ISLCNPHY
+#define ISNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
+#define ISLCNPHY(pi)  	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
+
+#define ISPHY_11N_CAP(pi)	(ISNPHY(pi) || ISLCNPHY(pi))
+
+#define IS20MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_20)
+#define IS40MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_40)
+
+#define PHY_GET_RFATTN(rfgain)	((rfgain) & 0x0f)
+#define PHY_GET_PADMIX(rfgain)	(((rfgain) & 0x10) >> 4)
+#define PHY_GET_RFGAINID(rfattn, padmix, width)	((rfattn) + ((padmix)*(width)))
+#define PHY_SAT(x, n)		((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \
+				((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x)))
+#define PHY_SHIFT_ROUND(x, n)	((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n))
+#define PHY_HW_ROUND(x, s)		((x >> s) + ((x >> (s-1)) & (s != 0)))
+
+#define CH_5G_GROUP	3
+#define A_LOW_CHANS	0
+#define A_MID_CHANS	1
+#define A_HIGH_CHANS	2
+#define CH_2G_GROUP	1
+#define G_ALL_CHANS	0
+
+#define FIRST_REF5_CHANNUM	149
+#define LAST_REF5_CHANNUM	165
+#define	FIRST_5G_CHAN		14
+#define	LAST_5G_CHAN		50
+#define	FIRST_MID_5G_CHAN	14
+#define	LAST_MID_5G_CHAN	35
+#define	FIRST_HIGH_5G_CHAN	36
+#define	LAST_HIGH_5G_CHAN	41
+#define	FIRST_LOW_5G_CHAN	42
+#define	LAST_LOW_5G_CHAN	50
+
+#define BASE_LOW_5G_CHAN	4900
+#define BASE_MID_5G_CHAN	5100
+#define BASE_HIGH_5G_CHAN	5500
+
+#define CHAN5G_FREQ(chan)  (5000 + chan*5)
+#define CHAN2G_FREQ(chan)  (2407 + chan*5)
+
+#define TXP_FIRST_CCK		0
+#define TXP_LAST_CCK		3
+#define TXP_FIRST_OFDM		4
+#define TXP_LAST_OFDM		11
+#define TXP_FIRST_OFDM_20_CDD	12
+#define TXP_LAST_OFDM_20_CDD	19
+#define TXP_FIRST_MCS_20_SISO	20
+#define TXP_LAST_MCS_20_SISO	27
+#define TXP_FIRST_MCS_20_CDD	28
+#define TXP_LAST_MCS_20_CDD	35
+#define TXP_FIRST_MCS_20_STBC	36
+#define TXP_LAST_MCS_20_STBC	43
+#define TXP_FIRST_MCS_20_SDM	44
+#define TXP_LAST_MCS_20_SDM	51
+#define TXP_FIRST_OFDM_40_SISO	52
+#define TXP_LAST_OFDM_40_SISO	59
+#define TXP_FIRST_OFDM_40_CDD	60
+#define TXP_LAST_OFDM_40_CDD	67
+#define TXP_FIRST_MCS_40_SISO	68
+#define TXP_LAST_MCS_40_SISO	75
+#define TXP_FIRST_MCS_40_CDD	76
+#define TXP_LAST_MCS_40_CDD	83
+#define TXP_FIRST_MCS_40_STBC	84
+#define TXP_LAST_MCS_40_STBC	91
+#define TXP_FIRST_MCS_40_SDM	92
+#define TXP_LAST_MCS_40_SDM	99
+#define TXP_MCS_32	        100
+#define TXP_NUM_RATES		101
+#define ADJ_PWR_TBL_LEN		84
+
+#define TXP_FIRST_SISO_MCS_20	20
+#define TXP_LAST_SISO_MCS_20	27
+
+#define PHY_CORE_NUM_1	1
+#define PHY_CORE_NUM_2	2
+#define PHY_CORE_NUM_3	3
+#define PHY_CORE_NUM_4	4
+#define PHY_CORE_MAX	PHY_CORE_NUM_4
+#define PHY_CORE_0	0
+#define PHY_CORE_1	1
+#define PHY_CORE_2	2
+#define PHY_CORE_3	3
+
+#define MA_WINDOW_SZ		8
+
+#define PHY_NOISE_SAMPLE_MON		1
+#define PHY_NOISE_SAMPLE_EXTERNAL	2
+#define PHY_NOISE_WINDOW_SZ	16
+#define PHY_NOISE_GLITCH_INIT_MA 10
+#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10
+#define PHY_NOISE_STATE_MON		0x1
+#define PHY_NOISE_STATE_EXTERNAL	0x2
+#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY	10
+#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE	9
+
+#define PHY_NOISE_OFFSETFACT_4322  (-103)
+#define PHY_NOISE_MA_WINDOW_SZ	2
+
+#define	PHY_RSSI_TABLE_SIZE	64
+#define RSSI_ANT_MERGE_MAX	0
+#define RSSI_ANT_MERGE_MIN	1
+#define RSSI_ANT_MERGE_AVG	2
+
+#define	PHY_TSSI_TABLE_SIZE	64
+#define	APHY_TSSI_TABLE_SIZE	256
+#define	TX_GAIN_TABLE_LENGTH	64
+#define	DEFAULT_11A_TXP_IDX	24
+#define NUM_TSSI_FRAMES        4
+#define	NULL_TSSI		0x7f
+#define	NULL_TSSI_W		0x7f7f
+
+#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64
+
+#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9
+
+#define PHY_TXPWR_MIN		10
+#define PHY_TXPWR_MIN_NPHY	8
+#define RADIOPWR_OVERRIDE_DEF	(-1)
+
+#define PWRTBL_NUM_COEFF	3
+
+#define SPURAVOID_DISABLE	0
+#define SPURAVOID_AUTO		1
+#define SPURAVOID_FORCEON	2
+#define SPURAVOID_FORCEON2	3
+
+#define PHY_SW_TIMER_FAST		15
+#define PHY_SW_TIMER_SLOW		60
+#define PHY_SW_TIMER_GLACIAL	120
+
+#define PHY_PERICAL_AUTO	0
+#define PHY_PERICAL_FULL	1
+#define PHY_PERICAL_PARTIAL	2
+
+#define PHY_PERICAL_NODELAY	0
+#define PHY_PERICAL_INIT_DELAY	5
+#define PHY_PERICAL_ASSOC_DELAY	5
+#define PHY_PERICAL_WDOG_DELAY	5
+
+#define MPHASE_TXCAL_NUMCMDS	2
+#define PHY_PERICAL_MPHASE_PENDING(pi)	(pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
+
+enum {
+	MPHASE_CAL_STATE_IDLE = 0,
+	MPHASE_CAL_STATE_INIT = 1,
+	MPHASE_CAL_STATE_TXPHASE0,
+	MPHASE_CAL_STATE_TXPHASE1,
+	MPHASE_CAL_STATE_TXPHASE2,
+	MPHASE_CAL_STATE_TXPHASE3,
+	MPHASE_CAL_STATE_TXPHASE4,
+	MPHASE_CAL_STATE_TXPHASE5,
+	MPHASE_CAL_STATE_PAPDCAL,
+	MPHASE_CAL_STATE_RXCAL,
+	MPHASE_CAL_STATE_RSSICAL,
+	MPHASE_CAL_STATE_IDLETSSI
+};
+
+typedef enum {
+	CAL_FULL,
+	CAL_RECAL,
+	CAL_CURRECAL,
+	CAL_DIGCAL,
+	CAL_GCTRL,
+	CAL_SOFT,
+	CAL_DIGLO
+} phy_cal_mode_t;
+
+#define RDR_NTIERS  1
+#define RDR_TIER_SIZE 64
+#define RDR_LIST_SIZE (512/3)
+#define RDR_EPOCH_SIZE 40
+#define RDR_NANTENNAS 2
+#define RDR_NTIER_SIZE  RDR_LIST_SIZE
+#define RDR_LP_BUFFER_SIZE 64
+#define LP_LEN_HIS_SIZE 10
+
+#define STATIC_NUM_RF 32
+#define STATIC_NUM_BB 9
+
+#define BB_MULT_MASK		0x0000ffff
+#define BB_MULT_VALID_MASK	0x80000000
+
+#define CORDIC_AG	39797
+#define	CORDIC_NI	18
+#define	FIXED(X)	((s32)((X) << 16))
+#define	FLOAT(X)	(((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
+
+#define PHY_CHAIN_TX_DISABLE_TEMP	115
+#define PHY_HYSTERESIS_DELTATEMP	5
+
+#define PHY_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
+
+#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
+	mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
+	(value) << phy_type##_##reg_name##_##field##_##SHIFT);
+#define READ_PHY_REG(pi, phy_type, reg_name, field) \
+	((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
+	>> phy_type##_##reg_name##_##field##_##SHIFT)
+
+#define	VALID_PHYTYPE(phytype)	(((uint)phytype == PHY_TYPE_N) || \
+				((uint)phytype == PHY_TYPE_LCN))
+
+#define VALID_N_RADIO(radioid)	((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
+				(radioid == BCM2057_ID))
+#define VALID_LCN_RADIO(radioid)	(radioid == BCM2064_ID)
+
+#define	VALID_RADIO(pi, radioid)	(\
+	(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
+	(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+
+#define SCAN_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
+#define RM_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
+#define PLT_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
+#define ASSOC_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
+#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
+#define PHY_MUTED(pi)		(mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
+#define PUB_NOT_ASSOC(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
+
+#if defined(EXT_CBALL)
+#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
+#else
+#define NORADIO_ENAB(pub) 0
+#endif
+
+#define PHY_LTRN_LIST_LEN	64
+extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
+
+typedef struct _phy_table_info {
+	uint table;
+	int q;
+	uint max;
+} phy_table_info_t;
+
+typedef struct phytbl_info {
+	const void *tbl_ptr;
+	u32 tbl_len;
+	u32 tbl_id;
+	u32 tbl_offset;
+	u32 tbl_width;
+} phytbl_info_t;
+
+typedef struct {
+	u8 curr_home_channel;
+	u16 crsminpwrthld_40_stored;
+	u16 crsminpwrthld_20L_stored;
+	u16 crsminpwrthld_20U_stored;
+	u16 init_gain_code_core1_stored;
+	u16 init_gain_code_core2_stored;
+	u16 init_gain_codeb_core1_stored;
+	u16 init_gain_codeb_core2_stored;
+	u16 init_gain_table_stored[4];
+
+	u16 clip1_hi_gain_code_core1_stored;
+	u16 clip1_hi_gain_code_core2_stored;
+	u16 clip1_hi_gain_codeb_core1_stored;
+	u16 clip1_hi_gain_codeb_core2_stored;
+	u16 nb_clip_thresh_core1_stored;
+	u16 nb_clip_thresh_core2_stored;
+	u16 init_ofdmlna2gainchange_stored[4];
+	u16 init_ccklna2gainchange_stored[4];
+	u16 clip1_lo_gain_code_core1_stored;
+	u16 clip1_lo_gain_code_core2_stored;
+	u16 clip1_lo_gain_codeb_core1_stored;
+	u16 clip1_lo_gain_codeb_core2_stored;
+	u16 w1_clip_thresh_core1_stored;
+	u16 w1_clip_thresh_core2_stored;
+	u16 radio_2056_core1_rssi_gain_stored;
+	u16 radio_2056_core2_rssi_gain_stored;
+	u16 energy_drop_timeout_len_stored;
+
+	u16 ed_crs40_assertthld0_stored;
+	u16 ed_crs40_assertthld1_stored;
+	u16 ed_crs40_deassertthld0_stored;
+	u16 ed_crs40_deassertthld1_stored;
+	u16 ed_crs20L_assertthld0_stored;
+	u16 ed_crs20L_assertthld1_stored;
+	u16 ed_crs20L_deassertthld0_stored;
+	u16 ed_crs20L_deassertthld1_stored;
+	u16 ed_crs20U_assertthld0_stored;
+	u16 ed_crs20U_assertthld1_stored;
+	u16 ed_crs20U_deassertthld0_stored;
+	u16 ed_crs20U_deassertthld1_stored;
+
+	u16 badplcp_ma;
+	u16 badplcp_ma_previous;
+	u16 badplcp_ma_total;
+	u16 badplcp_ma_list[MA_WINDOW_SZ];
+	int badplcp_ma_index;
+	s16 pre_badplcp_cnt;
+	s16 bphy_pre_badplcp_cnt;
+
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u16 init_gain_rfseq[4];
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+
+	s16 crsminpwr_index;
+
+	u16 radio_2057_core1_rssi_wb1a_gc_stored;
+	u16 radio_2057_core2_rssi_wb1a_gc_stored;
+	u16 radio_2057_core1_rssi_wb1g_gc_stored;
+	u16 radio_2057_core2_rssi_wb1g_gc_stored;
+	u16 radio_2057_core1_rssi_wb2_gc_stored;
+	u16 radio_2057_core2_rssi_wb2_gc_stored;
+	u16 radio_2057_core1_rssi_nb_gc_stored;
+	u16 radio_2057_core2_rssi_nb_gc_stored;
+
+} interference_info_t;
+
+typedef struct {
+	u16 rc_cal_ovr;
+	u16 phycrsth1;
+	u16 phycrsth2;
+	u16 init_n1p1_gain;
+	u16 p1_p2_gain;
+	u16 n1_n2_gain;
+	u16 n1_p1_gain;
+	u16 div_search_gain;
+	u16 div_p1_p2_gain;
+	u16 div_search_gn_change;
+	u16 table_7_2;
+	u16 table_7_3;
+	u16 cckshbits_gnref;
+	u16 clip_thresh;
+	u16 clip2_thresh;
+	u16 clip3_thresh;
+	u16 clip_p2_thresh;
+	u16 clip_pwdn_thresh;
+	u16 clip_n1p1_thresh;
+	u16 clip_n1_pwdn_thresh;
+	u16 bbconfig;
+	u16 cthr_sthr_shdin;
+	u16 energy;
+	u16 clip_p1_p2_thresh;
+	u16 threshold;
+	u16 reg15;
+	u16 reg16;
+	u16 reg17;
+	u16 div_srch_idx;
+	u16 div_srch_p1_p2;
+	u16 div_srch_gn_back;
+	u16 ant_dwell;
+	u16 ant_wr_settle;
+} aci_save_gphy_t;
+
+typedef struct _lo_complex_t {
+	s8 i;
+	s8 q;
+} lo_complex_abgphy_info_t;
+
+typedef struct _nphy_iq_comp {
+	s16 a0;
+	s16 b0;
+	s16 a1;
+	s16 b1;
+} nphy_iq_comp_t;
+
+typedef struct _nphy_txpwrindex {
+	s8 index;
+	s8 index_internal;
+	s8 index_internal_save;
+	u16 AfectrlOverride;
+	u16 AfeCtrlDacGain;
+	u16 rad_gain;
+	u8 bbmult;
+	u16 iqcomp_a;
+	u16 iqcomp_b;
+	u16 locomp;
+} phy_txpwrindex_t;
+
+typedef struct {
+
+	u16 txcal_coeffs_2G[8];
+	u16 txcal_radio_regs_2G[8];
+	nphy_iq_comp_t rxcal_coeffs_2G;
+
+	u16 txcal_coeffs_5G[8];
+	u16 txcal_radio_regs_5G[8];
+	nphy_iq_comp_t rxcal_coeffs_5G;
+} txiqcal_cache_t;
+
+typedef struct _nphy_pwrctrl {
+	s8 max_pwr_2g;
+	s8 idle_targ_2g;
+	s16 pwrdet_2g_a1;
+	s16 pwrdet_2g_b0;
+	s16 pwrdet_2g_b1;
+	s8 max_pwr_5gm;
+	s8 idle_targ_5gm;
+	s8 max_pwr_5gh;
+	s8 max_pwr_5gl;
+	s16 pwrdet_5gm_a1;
+	s16 pwrdet_5gm_b0;
+	s16 pwrdet_5gm_b1;
+	s16 pwrdet_5gl_a1;
+	s16 pwrdet_5gl_b0;
+	s16 pwrdet_5gl_b1;
+	s16 pwrdet_5gh_a1;
+	s16 pwrdet_5gh_b0;
+	s16 pwrdet_5gh_b1;
+	s8 idle_targ_5gl;
+	s8 idle_targ_5gh;
+	s8 idle_tssi_2g;
+	s8 idle_tssi_5g;
+	s8 idle_tssi;
+	s16 a1;
+	s16 b0;
+	s16 b1;
+} phy_pwrctrl_t;
+
+typedef struct _nphy_txgains {
+	u16 txlpf[2];
+	u16 txgm[2];
+	u16 pga[2];
+	u16 pad[2];
+	u16 ipa[2];
+} nphy_txgains_t;
+
+#define PHY_NOISEVAR_BUFSIZE 10
+
+typedef struct _nphy_noisevar_buf {
+	int bufcount;
+	int tone_id[PHY_NOISEVAR_BUFSIZE];
+	u32 noise_vars[PHY_NOISEVAR_BUFSIZE];
+	u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE];
+} phy_noisevar_buf_t;
+
+typedef struct {
+	u16 rssical_radio_regs_2G[2];
+	u16 rssical_phyregs_2G[12];
+
+	u16 rssical_radio_regs_5G[2];
+	u16 rssical_phyregs_5G[12];
+} rssical_cache_t;
+
+typedef struct {
+
+	u16 txiqlocal_a;
+	u16 txiqlocal_b;
+	u16 txiqlocal_didq;
+	u8 txiqlocal_ei0;
+	u8 txiqlocal_eq0;
+	u8 txiqlocal_fi0;
+	u8 txiqlocal_fq0;
+
+	u16 txiqlocal_bestcoeffs[11];
+	u16 txiqlocal_bestcoeffs_valid;
+
+	u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY];
+	u16 analog_gain_ref;
+	u16 lut_begin;
+	u16 lut_end;
+	u16 lut_step;
+	u16 rxcompdbm;
+	u16 papdctrl;
+	u16 sslpnCalibClkEnCtrl;
+
+	u16 rxiqcal_coeff_a0;
+	u16 rxiqcal_coeff_b0;
+} lcnphy_cal_results_t;
+
+struct shared_phy {
+	struct phy_info *phy_head;
+	uint unit;
+	si_t *sih;
+	void *physhim;
+	uint corerev;
+	u32 machwcap;
+	bool up;
+	bool clk;
+	uint now;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	uint boardvendor;
+	u32 boardflags;
+	u32 boardflags2;
+	uint bustype;
+	uint buscorerev;
+	uint fast_timer;
+	uint slow_timer;
+	uint glacial_timer;
+	u8 rx_antdiv;
+	s8 phy_noise_window[MA_WINDOW_SZ];
+	uint phy_noise_index;
+	u8 hw_phytxchain;
+	u8 hw_phyrxchain;
+	u8 phytxchain;
+	u8 phyrxchain;
+	u8 rssi_mode;
+	bool _rifs_phy;
+};
+
+struct phy_pub {
+	uint phy_type;
+	uint phy_rev;
+	u8 phy_corenum;
+	u16 radioid;
+	u8 radiorev;
+	u8 radiover;
+
+	uint coreflags;
+	uint ana_rev;
+	bool abgphy_encore;
+};
+
+struct phy_info_nphy;
+typedef struct phy_info_nphy phy_info_nphy_t;
+
+struct phy_info_lcnphy;
+typedef struct phy_info_lcnphy phy_info_lcnphy_t;
+
+struct phy_func_ptr {
+	initfn_t init;
+	initfn_t calinit;
+	chansetfn_t chanset;
+	initfn_t txpwrrecalc;
+	longtrnfn_t longtrn;
+	txiqccgetfn_t txiqccget;
+	txiqccsetfn_t txiqccset;
+	txloccgetfn_t txloccget;
+	radioloftgetfn_t radioloftget;
+	initfn_t carrsuppr;
+	rxsigpwrfn_t rxsigpwr;
+	detachfn_t detach;
+};
+typedef struct phy_func_ptr phy_func_ptr_t;
+
+struct phy_info {
+	wlc_phy_t pubpi_ro;
+	shared_phy_t *sh;
+	phy_func_ptr_t pi_fptr;
+	void *pi_ptr;
+
+	union {
+		phy_info_lcnphy_t *pi_lcnphy;
+	} u;
+	bool user_txpwr_at_rfport;
+
+	d11regs_t *regs;
+	struct phy_info *next;
+	char *vars;
+	wlc_phy_t pubpi;
+
+	bool do_initcal;
+	bool phytest_on;
+	bool ofdm_rateset_war;
+	bool bf_preempt_4306;
+	chanspec_t radio_chanspec;
+	u8 antsel_type;
+	u16 bw;
+	u8 txpwr_percent;
+	bool phy_init_por;
+
+	bool init_in_progress;
+	bool initialized;
+	bool sbtml_gm;
+	uint refcnt;
+	bool watchdog_override;
+	u8 phynoise_state;
+	uint phynoise_now;
+	int phynoise_chan_watchdog;
+	bool phynoise_polling;
+	bool disable_percal;
+	mbool measure_hold;
+
+	s16 txpa_2g[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_low[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_mid[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_hi[PWRTBL_NUM_COEFF];
+
+	u8 tx_srom_max_2g;
+	u8 tx_srom_max_5g_low;
+	u8 tx_srom_max_5g_mid;
+	u8 tx_srom_max_5g_hi;
+	u8 tx_srom_max_rate_2g[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES];
+	u8 tx_user_target[TXP_NUM_RATES];
+	s8 tx_power_offset[TXP_NUM_RATES];
+	u8 tx_power_target[TXP_NUM_RATES];
+
+	srom_fem_t srom_fem2g;
+	srom_fem_t srom_fem5g;
+
+	u8 tx_power_max;
+	u8 tx_power_max_rate_ind;
+	bool hwpwrctrl;
+	u8 nphy_txpwrctrl;
+	s8 nphy_txrx_chain;
+	bool phy_5g_pwrgain;
+
+	u16 phy_wreg;
+	u16 phy_wreg_limit;
+
+	s8 n_preamble_override;
+	u8 antswitch;
+	u8 aa2g, aa5g;
+
+	s8 idle_tssi[CH_5G_GROUP];
+	s8 target_idle_tssi;
+	s8 txpwr_est_Pout;
+	u8 tx_power_min;
+	u8 txpwr_limit[TXP_NUM_RATES];
+	u8 txpwr_env_limit[TXP_NUM_RATES];
+	u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN];
+
+	bool channel_14_wide_filter;
+
+	bool txpwroverride;
+	bool txpwridx_override_aphy;
+	s16 radiopwr_override;
+	u16 hwpwr_txcur;
+	u8 saved_txpwr_idx;
+
+	bool edcrs_threshold_lock;
+
+	u32 tr_R_gain_val;
+	u32 tr_T_gain_val;
+
+	s16 ofdm_analog_filt_bw_override;
+	s16 cck_analog_filt_bw_override;
+	s16 ofdm_rccal_override;
+	s16 cck_rccal_override;
+	u16 extlna_type;
+
+	uint interference_mode_crs_time;
+	u16 crsglitch_prev;
+	bool interference_mode_crs;
+
+	u32 phy_tx_tone_freq;
+	uint phy_lastcal;
+	bool phy_forcecal;
+	bool phy_fixed_noise;
+	u32 xtalfreq;
+	u8 pdiv;
+	s8 carrier_suppr_disable;
+
+	bool phy_bphy_evm;
+	bool phy_bphy_rfcs;
+	s8 phy_scraminit;
+	u8 phy_gpiosel;
+
+	s16 phy_txcore_disable_temp;
+	s16 phy_txcore_enable_temp;
+	s8 phy_tempsense_offset;
+	bool phy_txcore_heatedup;
+
+	u16 radiopwr;
+	u16 bb_atten;
+	u16 txctl1;
+
+	u16 mintxbias;
+	u16 mintxmag;
+	lo_complex_abgphy_info_t gphy_locomp_iq[STATIC_NUM_RF][STATIC_NUM_BB];
+	s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
+	u16 gain_table[TX_GAIN_TABLE_LENGTH];
+	bool loopback_gain;
+	s16 max_lpback_gain_hdB;
+	s16 trsw_rx_gain_hdB;
+	u8 power_vec[8];
+
+	u16 rc_cal;
+	int nrssi_table_delta;
+	int nrssi_slope_scale;
+	int nrssi_slope_offset;
+	int min_rssi;
+	int max_rssi;
+
+	s8 txpwridx;
+	u8 min_txpower;
+
+	u8 a_band_high_disable;
+
+	u16 tx_vos;
+	u16 global_tx_bb_dc_bias_loft;
+
+	int rf_max;
+	int bb_max;
+	int rf_list_size;
+	int bb_list_size;
+	u16 *rf_attn_list;
+	u16 *bb_attn_list;
+	u16 padmix_mask;
+	u16 padmix_reg;
+	u16 *txmag_list;
+	uint txmag_len;
+	bool txmag_enable;
+
+	s8 *a_tssi_to_dbm;
+	s8 *m_tssi_to_dbm;
+	s8 *l_tssi_to_dbm;
+	s8 *h_tssi_to_dbm;
+	u8 *hwtxpwr;
+
+	u16 freqtrack_saved_regs[2];
+	int cur_interference_mode;
+	bool hwpwrctrl_capable;
+	bool temppwrctrl_capable;
+
+	uint phycal_nslope;
+	uint phycal_noffset;
+	uint phycal_mlo;
+	uint phycal_txpower;
+
+	u8 phy_aa2g;
+
+	bool nphy_tableloaded;
+	s8 nphy_rssisel;
+	u32 nphy_bb_mult_save;
+	u16 nphy_txiqlocal_bestc[11];
+	bool nphy_txiqlocal_coeffsvalid;
+	phy_txpwrindex_t nphy_txpwrindex[PHY_CORE_NUM_2];
+	phy_pwrctrl_t nphy_pwrctrl_info[PHY_CORE_NUM_2];
+	u16 cck2gpo;
+	u32 ofdm2gpo;
+	u32 ofdm5gpo;
+	u32 ofdm5glpo;
+	u32 ofdm5ghpo;
+	u8 bw402gpo;
+	u8 bw405gpo;
+	u8 bw405glpo;
+	u8 bw405ghpo;
+	u8 cdd2gpo;
+	u8 cdd5gpo;
+	u8 cdd5glpo;
+	u8 cdd5ghpo;
+	u8 stbc2gpo;
+	u8 stbc5gpo;
+	u8 stbc5glpo;
+	u8 stbc5ghpo;
+	u8 bwdup2gpo;
+	u8 bwdup5gpo;
+	u8 bwdup5glpo;
+	u8 bwdup5ghpo;
+	u16 mcs2gpo[8];
+	u16 mcs5gpo[8];
+	u16 mcs5glpo[8];
+	u16 mcs5ghpo[8];
+	u32 nphy_rxcalparams;
+
+	u8 phy_spuravoid;
+	bool phy_isspuravoid;
+
+	u8 phy_pabias;
+	u8 nphy_papd_skip;
+	u8 nphy_tssi_slope;
+
+	s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
+	u8 nphy_noise_index;
+
+	u8 nphy_txpid2g[PHY_CORE_NUM_2];
+	u8 nphy_txpid5g[PHY_CORE_NUM_2];
+	u8 nphy_txpid5gl[PHY_CORE_NUM_2];
+	u8 nphy_txpid5gh[PHY_CORE_NUM_2];
+
+	bool nphy_gain_boost;
+	bool nphy_elna_gain_config;
+	u16 old_bphy_test;
+	u16 old_bphy_testcontrol;
+
+	bool phyhang_avoid;
+
+	bool rssical_nphy;
+	u8 nphy_perical;
+	uint nphy_perical_last;
+	u8 cal_type_override;
+	u8 mphase_cal_phase_id;
+	u8 mphase_txcal_cmdidx;
+	u8 mphase_txcal_numcmds;
+	u16 mphase_txcal_bestcoeffs[11];
+	chanspec_t nphy_txiqlocal_chanspec;
+	chanspec_t nphy_iqcal_chanspec_2G;
+	chanspec_t nphy_iqcal_chanspec_5G;
+	chanspec_t nphy_rssical_chanspec_2G;
+	chanspec_t nphy_rssical_chanspec_5G;
+	struct wlapi_timer *phycal_timer;
+	bool use_int_tx_iqlo_cal_nphy;
+	bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
+	s16 nphy_lastcal_temp;
+
+	txiqcal_cache_t calibration_cache;
+	rssical_cache_t rssical_cache;
+
+	u8 nphy_txpwr_idx[2];
+	u8 nphy_papd_cal_type;
+	uint nphy_papd_last_cal;
+	u16 nphy_papd_tx_gain_at_last_cal[2];
+	u8 nphy_papd_cal_gain_index[2];
+	s16 nphy_papd_epsilon_offset[2];
+	bool nphy_papd_recal_enable;
+	u32 nphy_papd_recal_counter;
+	bool nphy_force_papd_cal;
+	bool nphy_papdcomp;
+	bool ipa2g_on;
+	bool ipa5g_on;
+
+	u16 classifier_state;
+	u16 clip_state[2];
+	uint nphy_deaf_count;
+	u8 rxiq_samps;
+	u8 rxiq_antsel;
+
+	u16 rfctrlIntc1_save;
+	u16 rfctrlIntc2_save;
+	bool first_cal_after_assoc;
+	u16 tx_rx_cal_radio_saveregs[22];
+	u16 tx_rx_cal_phy_saveregs[15];
+
+	u8 nphy_cal_orig_pwr_idx[2];
+	u8 nphy_txcal_pwr_idx[2];
+	u8 nphy_rxcal_pwr_idx[2];
+	u16 nphy_cal_orig_tx_gain[2];
+	nphy_txgains_t nphy_cal_target_gain;
+	u16 nphy_txcal_bbmult;
+	u16 nphy_gmval;
+
+	u16 nphy_saved_bbconf;
+
+	bool nphy_gband_spurwar_en;
+	bool nphy_gband_spurwar2_en;
+	bool nphy_aband_spurwar_en;
+	u16 nphy_rccal_value;
+	u16 nphy_crsminpwr[3];
+	phy_noisevar_buf_t nphy_saved_noisevars;
+	bool nphy_anarxlpf_adjusted;
+	bool nphy_crsminpwr_adjusted;
+	bool nphy_noisevars_adjusted;
+
+	bool nphy_rxcal_active;
+	u16 radar_percal_mask;
+	bool dfs_lp_buffer_nphy;
+
+	u16 nphy_fineclockgatecontrol;
+
+	s8 rx2tx_biasentry;
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+	s16 noise_crsminpwr_index;
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u8 aci_noise_curr_channel;
+	u16 init_gain_rfseq[4];
+
+	bool radio_is_on;
+
+	bool nphy_sample_play_lpf_bw_ctl_ovr;
+
+	u16 tbl_data_hi;
+	u16 tbl_data_lo;
+	u16 tbl_addr;
+
+	uint tbl_save_id;
+	uint tbl_save_offset;
+
+	u8 txpwrctrl;
+	s8 txpwrindex[PHY_CORE_MAX];
+
+	u8 phycal_tempdelta;
+	u32 mcs20_po;
+	u32 mcs40_po;
+};
+
+typedef s32 fixed;
+
+typedef struct _cs32 {
+	fixed q;
+	fixed i;
+} cs32;
+
+typedef struct radio_regs {
+	u16 address;
+	u32 init_a;
+	u32 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+} radio_regs_t;
+
+typedef struct radio_20xx_regs {
+	u16 address;
+	u8 init;
+	u8 do_init;
+} radio_20xx_regs_t;
+
+typedef struct lcnphy_radio_regs {
+	u16 address;
+	u8 init_a;
+	u8 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+} lcnphy_radio_regs_t;
+
+extern lcnphy_radio_regs_t lcnphy_radio_regs_2064[];
+extern lcnphy_radio_regs_t lcnphy_radio_regs_2066[];
+extern radio_regs_t regs_2055[], regs_SYN_2056[], regs_TX_2056[],
+    regs_RX_2056[];
+extern radio_regs_t regs_SYN_2056_A1[], regs_TX_2056_A1[], regs_RX_2056_A1[];
+extern radio_regs_t regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
+    regs_RX_2056_rev5[];
+extern radio_regs_t regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
+    regs_RX_2056_rev6[];
+extern radio_regs_t regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
+    regs_RX_2056_rev7[];
+extern radio_regs_t regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
+    regs_RX_2056_rev8[];
+extern radio_20xx_regs_t regs_2057_rev4[], regs_2057_rev5[], regs_2057_rev5v1[];
+extern radio_20xx_regs_t regs_2057_rev7[], regs_2057_rev8[];
+
+extern char *phy_getvar(phy_info_t *pi, const char *name);
+extern int phy_getintvar(phy_info_t *pi, const char *name);
+#define PHY_GETVAR(pi, name)	phy_getvar(pi, name)
+#define PHY_GETINTVAR(pi, name)	phy_getintvar(pi, name)
+
+extern u16 read_phy_reg(phy_info_t *pi, u16 addr);
+extern void write_phy_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void and_phy_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void or_phy_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val);
+
+extern u16 read_radio_reg(phy_info_t *pi, u16 addr);
+extern void or_radio_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void and_radio_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask,
+			  u16 val);
+extern void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask);
+
+extern void write_radio_reg(phy_info_t *pi, u16 addr, u16 val);
+
+extern void wlc_phyreg_enter(wlc_phy_t *pih);
+extern void wlc_phyreg_exit(wlc_phy_t *pih);
+extern void wlc_radioreg_enter(wlc_phy_t *pih);
+extern void wlc_radioreg_exit(wlc_phy_t *pih);
+
+extern void wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
+			       u16 tblAddr, u16 tblDataHi,
+			       u16 tblDatalo);
+extern void wlc_phy_write_table(phy_info_t *pi,
+				const phytbl_info_t *ptbl_info, u16 tblAddr,
+				u16 tblDataHi, u16 tblDatalo);
+extern void wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
+			       u16 tblAddr, u16 tblDataHi,
+			       u16 tblDataLo);
+extern void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val);
+
+extern void write_phy_channel_reg(phy_info_t *pi, uint val);
+extern void wlc_phy_txpower_update_shm(phy_info_t *pi);
+
+extern void wlc_phy_cordic(fixed theta, cs32 *val);
+extern u8 wlc_phy_nbits(s32 value);
+extern u32 wlc_phy_sqrt_int(u32 value);
+extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
+
+extern uint wlc_phy_init_radio_regs_allbands(phy_info_t *pi,
+					     radio_20xx_regs_t *radioregs);
+extern uint wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
+				    u16 core_offset);
+
+extern void wlc_phy_txpower_ipa_upd(phy_info_t *pi);
+
+extern void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on);
+extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real,
+					s32 *eps_imag);
+
+extern void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi);
+extern void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi);
+
+extern bool wlc_phy_attach_nphy(phy_info_t *pi);
+extern bool wlc_phy_attach_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_detach_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_init_nphy(phy_info_t *pi);
+extern void wlc_phy_init_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_cal_init_nphy(phy_info_t *pi);
+extern void wlc_phy_cal_init_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec);
+extern void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec);
+extern void wlc_phy_chanspec_set_fixup_lcnphy(phy_info_t *pi,
+					      chanspec_t chanspec);
+extern int wlc_phy_channel2freq(uint channel);
+extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
+extern int wlc_phy_chanspec_bandrange_get(phy_info_t *, chanspec_t);
+
+extern void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode);
+extern s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi);
+
+extern void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi);
+extern void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi);
+extern void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi);
+
+extern void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index);
+extern void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable);
+extern void wlc_lcnphy_stop_tx_tone(phy_info_t *pi);
+extern void wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz,
+				     u16 max_val, bool iqcalmode);
+
+extern void wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan,
+					       u8 *max_pwr, u8 rate_id);
+extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+					    u8 rate_mcs_end,
+					    u8 rate_ofdm_start);
+extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power,
+					    u8 rate_ofdm_start,
+					    u8 rate_ofdm_end,
+					    u8 rate_mcs_start);
+
+extern u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode);
+extern s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode);
+extern s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode);
+extern s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode);
+extern void wlc_phy_carrier_suppress_lcnphy(phy_info_t *pi);
+extern void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel);
+extern void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode);
+extern void wlc_2064_vco_cal(phy_info_t *pi);
+
+extern void wlc_phy_txpower_recalc_target(phy_info_t *pi);
+extern u32 wlc_phy_qdiv_roundup(u32 dividend, u32 divisor,
+				   u8 precision);
+
+#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL	0x18
+#define LCNPHY_TX_POWER_TABLE_SIZE	128
+#define LCNPHY_MAX_TX_POWER_INDEX	(LCNPHY_TX_POWER_TABLE_SIZE - 1)
+#define LCNPHY_TBL_ID_TXPWRCTL 	0x07
+#define LCNPHY_TX_PWR_CTRL_OFF	0
+#define LCNPHY_TX_PWR_CTRL_SW		(0x1 << 15)
+#define LCNPHY_TX_PWR_CTRL_HW         ((0x1 << 15) | \
+					(0x1 << 14) | \
+					(0x1 << 13))
+
+#define LCNPHY_TX_PWR_CTRL_TEMPBASED	0xE001
+
+extern void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti);
+extern void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti);
+extern void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b);
+extern void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq);
+extern void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b);
+extern u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi);
+extern void wlc_lcnphy_get_radio_loft(phy_info_t *pi, u8 *ei0,
+				      u8 *eq0, u8 *fi0, u8 *fq0);
+extern void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode);
+extern void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode);
+extern bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi);
+extern void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi);
+extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
+extern void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr,
+				s8 *cck_pwr);
+extern void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi);
+
+extern s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index);
+
+#define NPHY_MAX_HPVGA1_INDEX		10
+#define NPHY_DEF_HPVGA1_INDEXLIMIT	7
+
+typedef struct _phy_iq_est {
+	s32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+} phy_iq_est_t;
+
+extern void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable);
+extern void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode);
+
+#define wlc_phy_write_table_nphy(pi, pti)	wlc_phy_write_table(pi, pti, 0x72, \
+	0x74, 0x73)
+#define wlc_phy_read_table_nphy(pi, pti)	wlc_phy_read_table(pi, pti, 0x72, \
+	0x74, 0x73)
+#define wlc_nphy_table_addr(pi, id, off)	wlc_phy_table_addr((pi), (id), (off), \
+	0x72, 0x74, 0x73)
+#define wlc_nphy_table_data_write(pi, w, v)	wlc_phy_table_data_write((pi), (w), (v))
+
+extern void wlc_phy_table_read_nphy(phy_info_t *pi, u32, u32 l, u32 o,
+				    u32 w, void *d);
+extern void wlc_phy_table_write_nphy(phy_info_t *pi, u32, u32, u32,
+				     u32, const void *);
+
+#define	PHY_IPA(pi) \
+	((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
+	 (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
+
+#define WLC_PHY_WAR_PR51571(pi) \
+	if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
+		(void)R_REG(&(pi)->regs->maccontrol)
+
+extern void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype);
+extern void wlc_phy_aci_reset_nphy(phy_info_t *pi);
+extern void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en);
+
+extern u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint chan);
+extern void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on);
+
+extern void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi);
+
+extern void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd);
+extern s16 wlc_phy_tempsense_nphy(phy_info_t *pi);
+
+extern u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val);
+
+extern void wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est,
+				   u16 num_samps, u8 wait_time,
+				   u8 wait_for_crs);
+
+extern void wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write,
+				      nphy_iq_comp_t *comp);
+extern void wlc_phy_aci_and_noise_reduction_nphy(phy_info_t *pi);
+
+extern void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask);
+extern u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih);
+
+extern void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type);
+extern void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi);
+extern void wlc_phy_txpwr_apply_nphy(phy_info_t *pi);
+extern void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi);
+extern u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi);
+
+extern nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi);
+extern int wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+				   bool full, bool m);
+extern int wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+				 u8 type, bool d);
+extern void wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask,
+				     s8 txpwrindex, bool res);
+extern void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core, u8 rssi_type);
+extern int wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type,
+				  s32 *rssi_buf, u8 nsamps);
+extern void wlc_phy_rssi_cal_nphy(phy_info_t *pi);
+extern int wlc_phy_aci_scan_nphy(phy_info_t *pi);
+extern void wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower,
+					bool debug);
+extern int wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+				u8 mode, u8, bool);
+extern void wlc_phy_stopplayback_nphy(phy_info_t *pi);
+extern void wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf,
+				     u8 num_samps);
+extern void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi);
+
+extern int wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh);
+
+#define NPHY_TESTPATTERN_BPHY_EVM   0
+#define NPHY_TESTPATTERN_BPHY_RFCS  1
+
+extern void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs);
+
+void wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset,
+				s8 *ofdmoffset);
+extern s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi,
+				    chanspec_t chanspec);
+
+extern bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pih);
+#endif				/* _wlc_phy_int_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c
new file mode 100644
index 0000000..a5a7bb8
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c
@@ -0,0 +1,5325 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <wlc_cfg.h>
+#include <qmath.h>
+#include <linux/pci.h>
+#include <siutils.h>
+#include <hndpmu.h>
+
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+
+#include <wlc_phy_radio.h>
+#include <wlc_phy_int.h>
+#include <wlc_phy_lcn.h>
+#include <wlc_phytbl_lcn.h>
+
+#define PLL_2064_NDIV		90
+#define PLL_2064_LOW_END_VCO 	3000
+#define PLL_2064_LOW_END_KVCO 	27
+#define PLL_2064_HIGH_END_VCO	4200
+#define PLL_2064_HIGH_END_KVCO	68
+#define PLL_2064_LOOP_BW_DOUBLER	200
+#define PLL_2064_D30_DOUBLER		10500
+#define PLL_2064_LOOP_BW	260
+#define PLL_2064_D30		8000
+#define PLL_2064_CAL_REF_TO	8
+#define PLL_2064_MHZ		1000000
+#define PLL_2064_OPEN_LOOP_DELAY	5
+
+#define TEMPSENSE 			1
+#define VBATSENSE           2
+
+#define NOISE_IF_UPD_CHK_INTERVAL	1
+#define NOISE_IF_UPD_RST_INTERVAL	60
+#define NOISE_IF_UPD_THRESHOLD_CNT	1
+#define NOISE_IF_UPD_TRHRESHOLD	50
+#define NOISE_IF_UPD_TIMEOUT		1000
+#define NOISE_IF_OFF			0
+#define NOISE_IF_CHK			1
+#define NOISE_IF_ON			2
+
+#define PAPD_BLANKING_PROFILE 		3
+#define PAPD2LUT			0
+#define PAPD_CORR_NORM 			0
+#define PAPD_BLANKING_THRESHOLD 	0
+#define PAPD_STOP_AFTER_LAST_UPDATE	0
+
+#define LCN_TARGET_PWR  60
+
+#define LCN_VBAT_OFFSET_433X 34649679
+#define LCN_VBAT_SLOPE_433X  8258032
+
+#define LCN_VBAT_SCALE_NOM  53
+#define LCN_VBAT_SCALE_DEN  432
+
+#define LCN_TEMPSENSE_OFFSET  80812
+#define LCN_TEMPSENSE_DEN  2647
+
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define wlc_lcnphy_enable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, true)
+#define wlc_lcnphy_disable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, false)
+
+#define wlc_lcnphy_iqcal_active(pi)	\
+	(read_phy_reg((pi), 0x451) & \
+	((0x1 << 15) | (0x1 << 14)))
+
+#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
+	(pi->temppwrctrl_capable)
+#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
+	(pi->hwpwrctrl_capable)
+
+#define SWCTRL_BT_TX		0x18
+#define SWCTRL_OVR_DISABLE	0x40
+
+#define	AFE_CLK_INIT_MODE_TXRX2X	1
+#define	AFE_CLK_INIT_MODE_PAPD		0
+
+#define LCNPHY_TBL_ID_IQLOCAL			0x00
+
+#define LCNPHY_TBL_ID_RFSEQ         0x08
+#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
+#define LCNPHY_TBL_ID_SW_CTRL			0x0f
+#define LCNPHY_TBL_ID_GAIN_TBL		0x12
+#define LCNPHY_TBL_ID_SPUR			0x14
+#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
+#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
+
+#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 	832
+#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 	128
+#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 	192
+#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
+#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
+#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
+
+#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
+
+#define LCNPHY_TX_PWR_CTRL_START_NPT		1
+#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
+
+#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
+
+#define LCNPHY_ACI_DETECT_START      1
+#define LCNPHY_ACI_DETECT_PROGRESS   2
+#define LCNPHY_ACI_DETECT_STOP       3
+
+#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
+#define LCNPHY_ACI_GLITCH_TRSH 2000
+#define	LCNPHY_ACI_TMOUT 250
+#define LCNPHY_ACI_DETECT_TIMEOUT  2
+#define LCNPHY_ACI_START_DELAY 0
+
+#define wlc_lcnphy_tx_gain_override_enabled(pi) \
+	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
+
+#define wlc_lcnphy_total_tx_frames(pi) \
+	wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + offsetof(macstat_t, txallfrm))
+
+typedef struct {
+	u16 gm_gain;
+	u16 pga_gain;
+	u16 pad_gain;
+	u16 dac_gain;
+} lcnphy_txgains_t;
+
+typedef enum {
+	LCNPHY_CAL_FULL,
+	LCNPHY_CAL_RECAL,
+	LCNPHY_CAL_CURRECAL,
+	LCNPHY_CAL_DIGCAL,
+	LCNPHY_CAL_GCTRL
+} lcnphy_cal_mode_t;
+
+typedef struct {
+	lcnphy_txgains_t gains;
+	bool useindex;
+	u8 index;
+} lcnphy_txcalgains_t;
+
+typedef struct {
+	u8 chan;
+	s16 a;
+	s16 b;
+} lcnphy_rx_iqcomp_t;
+
+typedef struct {
+	s16 re;
+	s16 im;
+} lcnphy_spb_tone_t;
+
+typedef struct {
+	u16 re;
+	u16 im;
+} lcnphy_unsign16_struct;
+
+typedef struct {
+	u32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+} lcnphy_iq_est_t;
+
+typedef struct {
+	u16 ptcentreTs20;
+	u16 ptcentreFactor;
+} lcnphy_sfo_cfg_t;
+
+typedef enum {
+	LCNPHY_PAPD_CAL_CW,
+	LCNPHY_PAPD_CAL_OFDM
+} lcnphy_papd_cal_type_t;
+
+typedef u16 iqcal_gain_params_lcnphy[9];
+
+static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
+	{0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
+	tbl_iqcal_gainparams_lcnphy_2G,
+};
+
+static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
+	sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
+	    sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
+};
+
+static const lcnphy_sfo_cfg_t lcnphy_sfo_cfg[] = {
+	{965, 1087},
+	{967, 1085},
+	{969, 1082},
+	{971, 1080},
+	{973, 1078},
+	{975, 1076},
+	{977, 1073},
+	{979, 1071},
+	{981, 1069},
+	{983, 1067},
+	{985, 1065},
+	{987, 1063},
+	{989, 1060},
+	{994, 1055}
+};
+
+static const
+u16 lcnphy_iqcal_loft_gainladder[] = {
+	((2 << 8) | 0),
+	((3 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((16 << 8) | 1),
+	((16 << 8) | 2),
+	((16 << 8) | 3),
+	((16 << 8) | 4),
+	((16 << 8) | 5),
+	((16 << 8) | 6),
+	((16 << 8) | 7),
+	((23 << 8) | 7),
+	((32 << 8) | 7),
+	((45 << 8) | 7),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+u16 lcnphy_iqcal_ir_gainladder[] = {
+	((1 << 8) | 0),
+	((2 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((23 << 8) | 0),
+	((32 << 8) | 0),
+	((45 << 8) | 0),
+	((64 << 8) | 0),
+	((64 << 8) | 1),
+	((64 << 8) | 2),
+	((64 << 8) | 3),
+	((64 << 8) | 4),
+	((64 << 8) | 5),
+	((64 << 8) | 6),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+lcnphy_spb_tone_t lcnphy_spb_tone_3750[] = {
+	{88, 0},
+	{73, 49},
+	{34, 81},
+	{-17, 86},
+	{-62, 62},
+	{-86, 17},
+	{-81, -34},
+	{-49, -73},
+	{0, -88},
+	{49, -73},
+	{81, -34},
+	{86, 17},
+	{62, 62},
+	{17, 86},
+	{-34, 81},
+	{-73, 49},
+	{-88, 0},
+	{-73, -49},
+	{-34, -81},
+	{17, -86},
+	{62, -62},
+	{86, -17},
+	{81, 34},
+	{49, 73},
+	{0, 88},
+	{-49, 73},
+	{-81, 34},
+	{-86, -17},
+	{-62, -62},
+	{-17, -86},
+	{34, -81},
+	{73, -49},
+};
+
+static const
+u16 iqlo_loopback_rf_regs[20] = {
+	RADIO_2064_REG036,
+	RADIO_2064_REG11A,
+	RADIO_2064_REG03A,
+	RADIO_2064_REG025,
+	RADIO_2064_REG028,
+	RADIO_2064_REG005,
+	RADIO_2064_REG112,
+	RADIO_2064_REG0FF,
+	RADIO_2064_REG11F,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG007,
+	RADIO_2064_REG0FC,
+	RADIO_2064_REG0FD,
+	RADIO_2064_REG012,
+	RADIO_2064_REG057,
+	RADIO_2064_REG059,
+	RADIO_2064_REG05C,
+	RADIO_2064_REG078,
+	RADIO_2064_REG092,
+};
+
+static const
+u16 tempsense_phy_regs[14] = {
+	0x503,
+	0x4a4,
+	0x4d0,
+	0x4d9,
+	0x4da,
+	0x4a6,
+	0x938,
+	0x939,
+	0x4d8,
+	0x4d0,
+	0x4d7,
+	0x4a5,
+	0x40d,
+	0x4a2,
+};
+
+static const
+u16 rxiq_cal_rf_reg[11] = {
+	RADIO_2064_REG098,
+	RADIO_2064_REG116,
+	RADIO_2064_REG12C,
+	RADIO_2064_REG06A,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG01B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG01D,
+	RADIO_2064_REG114,
+	RADIO_2064_REG02E,
+	RADIO_2064_REG12A,
+};
+
+static const
+lcnphy_rx_iqcomp_t lcnphy_rx_iqcomp_table_rev0[] = {
+	{1, 0, 0},
+	{2, 0, 0},
+	{3, 0, 0},
+	{4, 0, 0},
+	{5, 0, 0},
+	{6, 0, 0},
+	{7, 0, 0},
+	{8, 0, 0},
+	{9, 0, 0},
+	{10, 0, 0},
+	{11, 0, 0},
+	{12, 0, 0},
+	{13, 0, 0},
+	{14, 0, 0},
+	{34, 0, 0},
+	{38, 0, 0},
+	{42, 0, 0},
+	{46, 0, 0},
+	{36, 0, 0},
+	{40, 0, 0},
+	{44, 0, 0},
+	{48, 0, 0},
+	{52, 0, 0},
+	{56, 0, 0},
+	{60, 0, 0},
+	{64, 0, 0},
+	{100, 0, 0},
+	{104, 0, 0},
+	{108, 0, 0},
+	{112, 0, 0},
+	{116, 0, 0},
+	{120, 0, 0},
+	{124, 0, 0},
+	{128, 0, 0},
+	{132, 0, 0},
+	{136, 0, 0},
+	{140, 0, 0},
+	{149, 0, 0},
+	{153, 0, 0},
+	{157, 0, 0},
+	{161, 0, 0},
+	{165, 0, 0},
+	{184, 0, 0},
+	{188, 0, 0},
+	{192, 0, 0},
+	{196, 0, 0},
+	{200, 0, 0},
+	{204, 0, 0},
+	{208, 0, 0},
+	{212, 0, 0},
+	{216, 0, 0},
+};
+
+static const u32 lcnphy_23bitgaincode_table[] = {
+	0x200100,
+	0x200200,
+	0x200004,
+	0x200014,
+	0x200024,
+	0x200034,
+	0x200134,
+	0x200234,
+	0x200334,
+	0x200434,
+	0x200037,
+	0x200137,
+	0x200237,
+	0x200337,
+	0x200437,
+	0x000035,
+	0x000135,
+	0x000235,
+	0x000037,
+	0x000137,
+	0x000237,
+	0x000337,
+	0x00013f,
+	0x00023f,
+	0x00033f,
+	0x00034f,
+	0x00044f,
+	0x00144f,
+	0x00244f,
+	0x00254f,
+	0x00354f,
+	0x00454f,
+	0x00464f,
+	0x01464f,
+	0x02464f,
+	0x03464f,
+	0x04464f,
+};
+
+static const s8 lcnphy_gain_table[] = {
+	-16,
+	-13,
+	10,
+	7,
+	4,
+	0,
+	3,
+	6,
+	9,
+	12,
+	15,
+	18,
+	21,
+	24,
+	27,
+	30,
+	33,
+	36,
+	39,
+	42,
+	45,
+	48,
+	50,
+	53,
+	56,
+	59,
+	62,
+	65,
+	68,
+	71,
+	74,
+	77,
+	80,
+	83,
+	86,
+	89,
+	92,
+};
+
+static const s8 lcnphy_gain_index_offset_for_rssi[] = {
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	8,
+	7,
+	7,
+	6,
+	7,
+	7,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	3,
+	3,
+	3,
+	3,
+	3,
+	3,
+	4,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	-1,
+	-2,
+	-2,
+	-2
+};
+
+extern const u8 spur_tbl_rev0[];
+extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev1;
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[];
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
+
+typedef struct _chan_info_2064_lcnphy {
+	uint chan;
+	uint freq;
+	u8 logen_buftune;
+	u8 logen_rccr_tx;
+	u8 txrf_mix_tune_ctrl;
+	u8 pa_input_tune_g;
+	u8 logen_rccr_rx;
+	u8 pa_rxrf_lna1_freq_tune;
+	u8 pa_rxrf_lna2_freq_tune;
+	u8 rxrf_rxrf_spare1;
+} chan_info_2064_lcnphy_t;
+
+static chan_info_2064_lcnphy_t chan_info_2064_lcnphy[] = {
+	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+};
+
+lcnphy_radio_regs_t lcnphy_radio_regs_2064[] = {
+	{0x00, 0, 0, 0, 0},
+	{0x01, 0x64, 0x64, 0, 0},
+	{0x02, 0x20, 0x20, 0, 0},
+	{0x03, 0x66, 0x66, 0, 0},
+	{0x04, 0xf8, 0xf8, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x10, 0x10, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0x37, 0x37, 0, 0},
+	{0x0B, 0x6, 0x6, 0, 0},
+	{0x0C, 0x55, 0x55, 0, 0},
+	{0x0D, 0x8b, 0x8b, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0x5, 0x5, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0xe, 0xe, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0xb, 0xb, 0, 0},
+	{0x14, 0x2, 0x2, 0, 0},
+	{0x15, 0x12, 0x12, 0, 0},
+	{0x16, 0x12, 0x12, 0, 0},
+	{0x17, 0xc, 0xc, 0, 0},
+	{0x18, 0xc, 0xc, 0, 0},
+	{0x19, 0xc, 0xc, 0, 0},
+	{0x1A, 0x8, 0x8, 0, 0},
+	{0x1B, 0x2, 0x2, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0x1, 0x1, 0, 0},
+	{0x1E, 0x12, 0x12, 0, 0},
+	{0x1F, 0x6e, 0x6e, 0, 0},
+	{0x20, 0x2, 0x2, 0, 0},
+	{0x21, 0x23, 0x23, 0, 0},
+	{0x22, 0x8, 0x8, 0, 0},
+	{0x23, 0, 0, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0x33, 0x33, 0, 0},
+	{0x27, 0x55, 0x55, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x30, 0x30, 0, 0},
+	{0x2A, 0xb, 0xb, 0, 0},
+	{0x2B, 0x1b, 0x1b, 0, 0},
+	{0x2C, 0x3, 0x3, 0, 0},
+	{0x2D, 0x1b, 0x1b, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x20, 0x20, 0, 0},
+	{0x30, 0xa, 0xa, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0x62, 0x62, 0, 0},
+	{0x33, 0x19, 0x19, 0, 0},
+	{0x34, 0x33, 0x33, 0, 0},
+	{0x35, 0x77, 0x77, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x70, 0x70, 0, 0},
+	{0x38, 0x3, 0x3, 0, 0},
+	{0x39, 0xf, 0xf, 0, 0},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0xcf, 0xcf, 0, 0},
+	{0x3C, 0x1a, 0x1a, 0, 0},
+	{0x3D, 0x6, 0x6, 0, 0},
+	{0x3E, 0x42, 0x42, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0xfb, 0xfb, 0, 0},
+	{0x41, 0x9a, 0x9a, 0, 0},
+	{0x42, 0x7a, 0x7a, 0, 0},
+	{0x43, 0x29, 0x29, 0, 0},
+	{0x44, 0, 0, 0, 0},
+	{0x45, 0x8, 0x8, 0, 0},
+	{0x46, 0xce, 0xce, 0, 0},
+	{0x47, 0x27, 0x27, 0, 0},
+	{0x48, 0x62, 0x62, 0, 0},
+	{0x49, 0x6, 0x6, 0, 0},
+	{0x4A, 0x58, 0x58, 0, 0},
+	{0x4B, 0xf7, 0xf7, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0xb3, 0xb3, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0, 0, 0, 0},
+	{0x51, 0x9, 0x9, 0, 0},
+	{0x52, 0x5, 0x5, 0, 0},
+	{0x53, 0x17, 0x17, 0, 0},
+	{0x54, 0x38, 0x38, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0xb, 0xb, 0, 0},
+	{0x58, 0, 0, 0, 0},
+	{0x59, 0, 0, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0, 0, 0, 0},
+	{0x5C, 0, 0, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x88, 0x88, 0, 0},
+	{0x5F, 0xcc, 0xcc, 0, 0},
+	{0x60, 0x74, 0x74, 0, 0},
+	{0x61, 0x74, 0x74, 0, 0},
+	{0x62, 0x74, 0x74, 0, 0},
+	{0x63, 0x44, 0x44, 0, 0},
+	{0x64, 0x77, 0x77, 0, 0},
+	{0x65, 0x44, 0x44, 0, 0},
+	{0x66, 0x77, 0x77, 0, 0},
+	{0x67, 0x55, 0x55, 0, 0},
+	{0x68, 0x77, 0x77, 0, 0},
+	{0x69, 0x77, 0x77, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0x7f, 0x7f, 0, 0},
+	{0x6C, 0x8, 0x8, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0x88, 0x88, 0, 0},
+	{0x6F, 0x66, 0x66, 0, 0},
+	{0x70, 0x66, 0x66, 0, 0},
+	{0x71, 0x28, 0x28, 0, 0},
+	{0x72, 0x55, 0x55, 0, 0},
+	{0x73, 0x4, 0x4, 0, 0},
+	{0x74, 0, 0, 0, 0},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0, 0, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0xd6, 0xd6, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0xb4, 0xb4, 0, 0},
+	{0x84, 0x1, 0x1, 0, 0},
+	{0x85, 0x20, 0x20, 0, 0},
+	{0x86, 0x5, 0x5, 0, 0},
+	{0x87, 0xff, 0xff, 0, 0},
+	{0x88, 0x7, 0x7, 0, 0},
+	{0x89, 0x77, 0x77, 0, 0},
+	{0x8A, 0x77, 0x77, 0, 0},
+	{0x8B, 0x77, 0x77, 0, 0},
+	{0x8C, 0x77, 0x77, 0, 0},
+	{0x8D, 0x8, 0x8, 0, 0},
+	{0x8E, 0xa, 0xa, 0, 0},
+	{0x8F, 0x8, 0x8, 0, 0},
+	{0x90, 0x18, 0x18, 0, 0},
+	{0x91, 0x5, 0x5, 0, 0},
+	{0x92, 0x1f, 0x1f, 0, 0},
+	{0x93, 0x10, 0x10, 0, 0},
+	{0x94, 0x3, 0x3, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0xaa, 0xaa, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0x23, 0x23, 0, 0},
+	{0x9A, 0x7, 0x7, 0, 0},
+	{0x9B, 0xf, 0xf, 0, 0},
+	{0x9C, 0x10, 0x10, 0, 0},
+	{0x9D, 0x3, 0x3, 0, 0},
+	{0x9E, 0x4, 0x4, 0, 0},
+	{0x9F, 0x20, 0x20, 0, 0},
+	{0xA0, 0, 0, 0, 0},
+	{0xA1, 0, 0, 0, 0},
+	{0xA2, 0, 0, 0, 0},
+	{0xA3, 0, 0, 0, 0},
+	{0xA4, 0x1, 0x1, 0, 0},
+	{0xA5, 0x77, 0x77, 0, 0},
+	{0xA6, 0x77, 0x77, 0, 0},
+	{0xA7, 0x77, 0x77, 0, 0},
+	{0xA8, 0x77, 0x77, 0, 0},
+	{0xA9, 0x8c, 0x8c, 0, 0},
+	{0xAA, 0x88, 0x88, 0, 0},
+	{0xAB, 0x78, 0x78, 0, 0},
+	{0xAC, 0x57, 0x57, 0, 0},
+	{0xAD, 0x88, 0x88, 0, 0},
+	{0xAE, 0, 0, 0, 0},
+	{0xAF, 0x8, 0x8, 0, 0},
+	{0xB0, 0x88, 0x88, 0, 0},
+	{0xB1, 0, 0, 0, 0},
+	{0xB2, 0x1b, 0x1b, 0, 0},
+	{0xB3, 0x3, 0x3, 0, 0},
+	{0xB4, 0x24, 0x24, 0, 0},
+	{0xB5, 0x3, 0x3, 0, 0},
+	{0xB6, 0x1b, 0x1b, 0, 0},
+	{0xB7, 0x24, 0x24, 0, 0},
+	{0xB8, 0x3, 0x3, 0, 0},
+	{0xB9, 0, 0, 0, 0},
+	{0xBA, 0xaa, 0xaa, 0, 0},
+	{0xBB, 0, 0, 0, 0},
+	{0xBC, 0x4, 0x4, 0, 0},
+	{0xBD, 0, 0, 0, 0},
+	{0xBE, 0x8, 0x8, 0, 0},
+	{0xBF, 0x11, 0x11, 0, 0},
+	{0xC0, 0, 0, 0, 0},
+	{0xC1, 0, 0, 0, 0},
+	{0xC2, 0x62, 0x62, 0, 0},
+	{0xC3, 0x1e, 0x1e, 0, 0},
+	{0xC4, 0x33, 0x33, 0, 0},
+	{0xC5, 0x37, 0x37, 0, 0},
+	{0xC6, 0, 0, 0, 0},
+	{0xC7, 0x70, 0x70, 0, 0},
+	{0xC8, 0x1e, 0x1e, 0, 0},
+	{0xC9, 0x6, 0x6, 0, 0},
+	{0xCA, 0x4, 0x4, 0, 0},
+	{0xCB, 0x2f, 0x2f, 0, 0},
+	{0xCC, 0xf, 0xf, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0xff, 0xff, 0, 0},
+	{0xCF, 0x8, 0x8, 0, 0},
+	{0xD0, 0x3f, 0x3f, 0, 0},
+	{0xD1, 0x3f, 0x3f, 0, 0},
+	{0xD2, 0x3f, 0x3f, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0xcc, 0xcc, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0x8, 0x8, 0, 0},
+	{0xD9, 0x8, 0x8, 0, 0},
+	{0xDA, 0x8, 0x8, 0, 0},
+	{0xDB, 0x11, 0x11, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x87, 0x87, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0x8, 0x8, 0, 0},
+	{0xE0, 0x8, 0x8, 0, 0},
+	{0xE1, 0x8, 0x8, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xE3, 0, 0, 0, 0},
+	{0xE4, 0, 0, 0, 0},
+	{0xE5, 0xf5, 0xf5, 0, 0},
+	{0xE6, 0x30, 0x30, 0, 0},
+	{0xE7, 0x1, 0x1, 0, 0},
+	{0xE8, 0, 0, 0, 0},
+	{0xE9, 0xff, 0xff, 0, 0},
+	{0xEA, 0, 0, 0, 0},
+	{0xEB, 0, 0, 0, 0},
+	{0xEC, 0x22, 0x22, 0, 0},
+	{0xED, 0, 0, 0, 0},
+	{0xEE, 0, 0, 0, 0},
+	{0xEF, 0, 0, 0, 0},
+	{0xF0, 0x3, 0x3, 0, 0},
+	{0xF1, 0x1, 0x1, 0, 0},
+	{0xF2, 0, 0, 0, 0},
+	{0xF3, 0, 0, 0, 0},
+	{0xF4, 0, 0, 0, 0},
+	{0xF5, 0, 0, 0, 0},
+	{0xF6, 0, 0, 0, 0},
+	{0xF7, 0x6, 0x6, 0, 0},
+	{0xF8, 0, 0, 0, 0},
+	{0xF9, 0, 0, 0, 0},
+	{0xFA, 0x40, 0x40, 0, 0},
+	{0xFB, 0, 0, 0, 0},
+	{0xFC, 0x1, 0x1, 0, 0},
+	{0xFD, 0x80, 0x80, 0, 0},
+	{0xFE, 0x2, 0x2, 0, 0},
+	{0xFF, 0x10, 0x10, 0, 0},
+	{0x100, 0x2, 0x2, 0, 0},
+	{0x101, 0x1e, 0x1e, 0, 0},
+	{0x102, 0x1e, 0x1e, 0, 0},
+	{0x103, 0, 0, 0, 0},
+	{0x104, 0x1f, 0x1f, 0, 0},
+	{0x105, 0, 0x8, 0, 1},
+	{0x106, 0x2a, 0x2a, 0, 0},
+	{0x107, 0xf, 0xf, 0, 0},
+	{0x108, 0, 0, 0, 0},
+	{0x109, 0, 0, 0, 0},
+	{0x10A, 0, 0, 0, 0},
+	{0x10B, 0, 0, 0, 0},
+	{0x10C, 0, 0, 0, 0},
+	{0x10D, 0, 0, 0, 0},
+	{0x10E, 0, 0, 0, 0},
+	{0x10F, 0, 0, 0, 0},
+	{0x110, 0, 0, 0, 0},
+	{0x111, 0, 0, 0, 0},
+	{0x112, 0, 0, 0, 0},
+	{0x113, 0, 0, 0, 0},
+	{0x114, 0, 0, 0, 0},
+	{0x115, 0, 0, 0, 0},
+	{0x116, 0, 0, 0, 0},
+	{0x117, 0, 0, 0, 0},
+	{0x118, 0, 0, 0, 0},
+	{0x119, 0, 0, 0, 0},
+	{0x11A, 0, 0, 0, 0},
+	{0x11B, 0, 0, 0, 0},
+	{0x11C, 0x1, 0x1, 0, 0},
+	{0x11D, 0, 0, 0, 0},
+	{0x11E, 0, 0, 0, 0},
+	{0x11F, 0, 0, 0, 0},
+	{0x120, 0, 0, 0, 0},
+	{0x121, 0, 0, 0, 0},
+	{0x122, 0x80, 0x80, 0, 0},
+	{0x123, 0, 0, 0, 0},
+	{0x124, 0xf8, 0xf8, 0, 0},
+	{0x125, 0, 0, 0, 0},
+	{0x126, 0, 0, 0, 0},
+	{0x127, 0, 0, 0, 0},
+	{0x128, 0, 0, 0, 0},
+	{0x129, 0, 0, 0, 0},
+	{0x12A, 0, 0, 0, 0},
+	{0x12B, 0, 0, 0, 0},
+	{0x12C, 0, 0, 0, 0},
+	{0x12D, 0, 0, 0, 0},
+	{0x12E, 0, 0, 0, 0},
+	{0x12F, 0, 0, 0, 0},
+	{0x130, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+#define LCNPHY_NUM_DIG_FILT_COEFFS 16
+#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
+
+u16
+    LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
+    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
+	 128, 64,},
+	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
+	 167, 93,},
+	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
+	 128, 64,},
+	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
+	 256, 185, 256,},
+	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
+	 256, 273, 256,},
+	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
+	 256, 352, 256,},
+	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
+	 128, 233, 128,},
+	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
+	 1881, 256,},
+	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
+	 1881, 256,},
+	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
+	 384, 288,},
+	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
+	 128, 384, 288,},
+	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+};
+
+#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
+u16
+    LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
+    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
+	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
+	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
+	 750, 0xFE2B, 212, 0xFFCE, 212,},
+	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+	 0xFEF2, 128, 0xFFE2, 128}
+};
+
+#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
+	mod_phy_reg(pi, 0x4a4, \
+		(0x1ff << 0), \
+		(u16)(idx) << 0)
+
+#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
+	mod_phy_reg(pi, 0x4a5, \
+		(0x7 << 8), \
+		(u16)(npt) << 8)
+
+#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
+	(read_phy_reg((pi), 0x4a4) & \
+			((0x1 << 15) | \
+			(0x1 << 14) | \
+			(0x1 << 13)))
+
+#define wlc_lcnphy_get_tx_pwr_npt(pi) \
+	((read_phy_reg(pi, 0x4a5) & \
+		(0x7 << 8)) >> \
+		8)
+
+#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
+	(read_phy_reg(pi, 0x473) & 0x1ff)
+
+#define wlc_lcnphy_get_target_tx_pwr(pi) \
+	((read_phy_reg(pi, 0x4a7) & \
+		(0xff << 0)) >> \
+		0)
+
+#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
+	mod_phy_reg(pi, 0x4a7, \
+		(0xff << 0), \
+		(u16)(target) << 0)
+
+#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
+#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
+
+#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
+#define FIXED_TXPWR 78
+#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
+
+static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
+				      u8 precision);
+static void wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
+						   u16 ext_lna, u16 trsw,
+						   u16 biq2, u16 biq1,
+						   u16 tia, u16 lna2,
+						   u16 lna1);
+static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi);
+static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain);
+static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx);
+static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0);
+static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi);
+static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains);
+static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable);
+static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi);
+static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable);
+static void wlc_lcnphy_set_tx_gain(phy_info_t *pi,
+				   lcnphy_txgains_t *target_gains);
+static bool wlc_lcnphy_rx_iq_est(phy_info_t *pi, u16 num_samps,
+				 u8 wait_time, lcnphy_iq_est_t *iq_est);
+static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps);
+static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi);
+static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode);
+extern void wlc_lcnphy_tx_pwr_ctrl_init(wlc_phy_t *ppi);
+static void wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi,
+						    u8 channel);
+
+static void wlc_lcnphy_load_tx_gain_table(phy_info_t *pi,
+					  const lcnphy_tx_gain_tbl_entry *g);
+
+static void wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo,
+				u16 thresh, s16 *ptr, int mode);
+static int wlc_lcnphy_calc_floor(s16 coeff, int type);
+static void wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi,
+					u16 *values_to_save);
+static void wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi,
+						u16 *values_to_save);
+static void wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x,
+			      s16 coeff_y);
+static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type);
+static void wlc_lcnphy_a1(phy_info_t *pi, int cal_type,
+			  int num_levels, int step_size_lg2);
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi);
+
+static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi,
+					   chanspec_t chanspec);
+static void wlc_lcnphy_agc_temp_init(phy_info_t *pi);
+static void wlc_lcnphy_temp_adj(phy_info_t *pi);
+static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi);
+static void wlc_lcnphy_baseband_init(phy_info_t *pi);
+static void wlc_lcnphy_radio_init(phy_info_t *pi);
+static void wlc_lcnphy_rc_cal(phy_info_t *pi);
+static void wlc_lcnphy_rcal(phy_info_t *pi);
+static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable);
+static int wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm,
+					 s16 filt_type);
+static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b);
+
+void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti)
+{
+	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti)
+{
+	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+static void
+wlc_lcnphy_common_read_table(phy_info_t *pi, u32 tbl_id,
+			     const void *tbl_ptr, u32 tbl_len,
+			     u32 tbl_width, u32 tbl_offset)
+{
+	phytbl_info_t tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_read_table(pi, &tab);
+}
+
+static void
+wlc_lcnphy_common_write_table(phy_info_t *pi, u32 tbl_id,
+			      const void *tbl_ptr, u32 tbl_len,
+			      u32 tbl_width, u32 tbl_offset)
+{
+
+	phytbl_info_t tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static u32
+wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, roundup, rbit;
+
+	ASSERT(divisor);
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+	rbit = divisor & 1;
+	roundup = (divisor >> 1) + rbit;
+
+	while (precision--) {
+		quotient <<= 1;
+		if (remainder >= roundup) {
+			quotient++;
+			remainder = ((remainder - roundup) << 1) + rbit;
+		} else {
+			remainder <<= 1;
+		}
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
+}
+
+static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
+{
+	int k;
+	k = 0;
+	if (type == 0) {
+		if (coeff_x < 0) {
+			k = (coeff_x - 1) / 2;
+		} else {
+			k = coeff_x / 2;
+		}
+	}
+	if (type == 1) {
+		if ((coeff_x + 1) < 0)
+			k = (coeff_x) / 2;
+		else
+			k = (coeff_x + 1) / 2;
+	}
+	return k;
+}
+
+s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi)
+{
+	s8 index;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (txpwrctrl_off(pi))
+		index = pi_lcn->lcnphy_current_index;
+	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		index =
+		    (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
+			    / 2);
+	else
+		index = pi_lcn->lcnphy_current_index;
+	return index;
+}
+
+static u32 wlc_lcnphy_measure_digital_power(phy_info_t *pi, u16 nsamples)
+{
+	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
+
+	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
+		return 0;
+	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
+}
+
+void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel)
+{
+	u16 afectrlovr, afectrlovrval;
+	afectrlovr = read_phy_reg(pi, 0x43b);
+	afectrlovrval = read_phy_reg(pi, 0x43c);
+	if (channel != 0) {
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
+
+		write_phy_reg(pi, 0x44b, 0xffff);
+		wlc_lcnphy_tx_pu(pi, 1);
+
+		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
+
+		or_phy_reg(pi, 0x6da, 0x0080);
+
+		or_phy_reg(pi, 0x00a, 0x228);
+	} else {
+		and_phy_reg(pi, 0x00a, ~(0x228));
+
+		and_phy_reg(pi, 0x6da, 0xFF7F);
+		write_phy_reg(pi, 0x43b, afectrlovr);
+		write_phy_reg(pi, 0x43c, afectrlovrval);
+	}
+}
+
+static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi)
+{
+	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
+
+	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
+	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
+}
+
+static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable)
+{
+	if (enable) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
+
+		write_phy_reg(pi, 0x44a, 0x084);
+		write_phy_reg(pi, 0x44a, 0x080);
+		write_phy_reg(pi, 0x6d3, 0x2222);
+		write_phy_reg(pi, 0x6d3, 0x2220);
+	} else {
+		write_phy_reg(pi, 0x942, 0x0);
+		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
+	}
+	wlapi_switch_macfreq(pi->sh->physhim, enable);
+}
+
+void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+
+	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
+
+	wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!NORADIO_ENAB(pi->pubpi)) {
+		wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+		udelay(1000);
+	}
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+
+	write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
+	write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
+	}
+
+	wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
+
+}
+
+static void wlc_lcnphy_set_dac_gain(phy_info_t *pi, u16 dac_gain)
+{
+	u16 dac_ctrl;
+
+	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
+	dac_ctrl = dac_ctrl & 0xc7f;
+	dac_ctrl = dac_ctrl | (dac_gain << 7);
+	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
+
+}
+
+static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable)
+{
+	u16 bit = bEnable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
+}
+
+static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi)
+{
+	u16 pa_gain;
+
+	pa_gain = (read_phy_reg(pi, 0x4fb) &
+		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
+	    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
+
+	return pa_gain;
+}
+
+static void
+wlc_lcnphy_set_tx_gain(phy_info_t *pi, lcnphy_txgains_t *target_gains)
+{
+	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	mod_phy_reg(pi, 0x4b5,
+		    (0xffff << 0),
+		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
+		    0);
+	mod_phy_reg(pi, 0x4fb,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	mod_phy_reg(pi, 0x4fc,
+		    (0xffff << 0),
+		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
+		    0);
+	mod_phy_reg(pi, 0x4fd,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+}
+
+static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0)
+{
+	u16 m0m1 = (u16) m0 << 8;
+	phytbl_info_t tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi)
+{
+	u32 data_buf[64];
+	phytbl_info_t tab;
+
+	memset(data_buf, 0, sizeof(data_buf));
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = data_buf;
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		tab.tbl_len = 30;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_len = 64;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+typedef enum {
+	LCNPHY_TSSI_PRE_PA,
+	LCNPHY_TSSI_POST_PA,
+	LCNPHY_TSSI_EXT
+} lcnphy_tssi_mode_t;
+
+static void wlc_lcnphy_set_tssi_mux(phy_info_t *pi, lcnphy_tssi_mode_t pos)
+{
+	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
+
+	if (LCNPHY_TSSI_POST_PA == pos) {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	} else {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	}
+	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
+
+	if (LCNPHY_TSSI_EXT == pos) {
+		write_radio_reg(pi, RADIO_2064_REG07F, 1);
+		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
+		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
+	}
+}
+
+static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(phy_info_t *pi)
+{
+	u16 N1, N2, N3, N4, N5, N6, N;
+	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
+	      >> 0);
+	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
+		   >> 12);
+	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
+	      >> 0);
+	N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
+		   >> 8);
+	N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
+	      >> 0);
+	N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
+		   >> 8);
+	N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
+	if (N < 1600)
+		N = 1600;
+	return N;
+}
+
+static void wlc_lcnphy_pwrctrl_rssiparams(phy_info_t *pi)
+{
+	u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	auxpga_vmid =
+	    (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
+	auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
+	auxpga_gain_temp = 2;
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x4db,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x4dc,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40a,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40b,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_phy_reg(pi, 0x40c,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
+}
+
+static void wlc_lcnphy_tssi_setup(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u32 rfseq, ind;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &ind;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 0;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	tab.tbl_offset = 704;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
+
+	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
+
+	wlc_lcnphy_clear_tx_power_offsets(pi);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
+
+	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
+		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+	} else {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xc);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+	} else {
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+	else
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		mod_phy_reg(pi, 0x4d7,
+			    (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
+	}
+
+	rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &rfseq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
+
+	wlc_lcnphy_pwrctrl_rssiparams(pi);
+}
+
+void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi)
+{
+	u16 tx_cnt, tx_total, npt;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	tx_total = wlc_lcnphy_total_tx_frames(pi);
+	tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
+	npt = wlc_lcnphy_get_tx_pwr_npt(pi);
+
+	if (tx_cnt > (1 << npt)) {
+
+		pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
+
+		pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+		pi_lcn->lcnphy_tssi_npt = npt;
+
+	}
+}
+
+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
+{
+	s32 a, b, p;
+
+	a = 32768 + (a1 * tssi);
+	b = (1024 * b0) + (64 * b1 * tssi);
+	p = ((2 * b) + a) / (2 * a);
+
+	return p;
+}
+
+static void wlc_lcnphy_txpower_reset_npt(phy_info_t *pi)
+{
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
+	pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
+}
+
+void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u32 rate_table[WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM +
+			  WLC_NUM_RATES_MCS_1_STREAM];
+	uint i, j;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
+
+		if (i == WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM)
+			j = TXP_FIRST_MCS_20_SISO;
+
+		rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = ARRAY_SIZE(rate_table);
+	tab.tbl_ptr = rate_table;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
+		wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
+
+		wlc_lcnphy_txpower_reset_npt(pi);
+	}
+}
+
+static void wlc_lcnphy_set_tx_pwr_soft_ctrl(phy_info_t *pi, s8 index)
+{
+	u32 cck_offset[4] = { 22, 22, 22, 22 };
+	u32 ofdm_offset, reg_offset_cck;
+	int i;
+	u16 index2;
+	phytbl_info_t tab;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return;
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
+
+	or_phy_reg(pi, 0x6da, 0x0040);
+
+	reg_offset_cck = 0;
+	for (i = 0; i < 4; i++)
+		cck_offset[i] -= reg_offset_cck;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 4;
+	tab.tbl_ptr = cck_offset;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+	ofdm_offset = 0;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &ofdm_offset;
+	for (i = 836; i < 862; i++) {
+		tab.tbl_offset = i;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
+
+	index2 = (u16) (index * 2);
+	mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
+
+}
+
+static s8 wlc_lcnphy_tempcompensated_txpwrctrl(phy_info_t *pi)
+{
+	s8 index, delta_brd, delta_temp, new_index, tempcorrx;
+	s16 manp, meas_temp, temp_diff;
+	bool neg = 0;
+	u16 temp;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return pi_lcn->lcnphy_current_index;
+
+	index = FIXED_TXPWR;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return index;
+
+	if (pi_lcn->lcnphy_tempsense_slope == 0) {
+		return index;
+	}
+	temp = (u16) wlc_lcnphy_tempsense(pi, 0);
+	meas_temp = LCNPHY_TEMPSENSE(temp);
+
+	if (pi->tx_power_min != 0) {
+		delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
+	} else {
+		delta_brd = 0;
+	}
+
+	manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
+	temp_diff = manp - meas_temp;
+	if (temp_diff < 0) {
+
+		neg = 1;
+
+		temp_diff = -temp_diff;
+	}
+
+	delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
+						    (u32) (pi_lcn->
+							      lcnphy_tempsense_slope
+							      * 10), 0);
+	if (neg)
+		delta_temp = -delta_temp;
+
+	if (pi_lcn->lcnphy_tempsense_option == 3
+	    && LCNREV_IS(pi->pubpi.phy_rev, 0))
+		delta_temp = 0;
+	if (pi_lcn->lcnphy_tempcorrx > 31)
+		tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
+	else
+		tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		tempcorrx = 4;
+	new_index =
+	    index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
+	new_index += tempcorrx;
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		index = 127;
+	if (new_index < 0 || new_index > 126) {
+		return index;
+	}
+	return new_index;
+}
+
+static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(phy_info_t *pi, u16 mode)
+{
+
+	u16 current_mode = mode;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_HW)
+		current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
+		current_mode = LCNPHY_TX_PWR_CTRL_HW;
+	return current_mode;
+}
+
+void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode)
+{
+	u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	ASSERT((LCNPHY_TX_PWR_CTRL_OFF == mode) ||
+	       (LCNPHY_TX_PWR_CTRL_SW == mode) ||
+	       (LCNPHY_TX_PWR_CTRL_HW == mode) ||
+	       (LCNPHY_TX_PWR_CTRL_TEMPBASED == mode));
+
+	mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
+	old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 6),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
+
+	if (old_mode != mode) {
+		if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
+
+			wlc_lcnphy_tx_pwr_update_npt(pi);
+
+			wlc_lcnphy_clear_tx_power_offsets(pi);
+		}
+		if (LCNPHY_TX_PWR_CTRL_HW == mode) {
+
+			wlc_lcnphy_txpower_recalc_target(pi);
+
+			wlc_lcnphy_set_start_tx_pwr_idx(pi,
+							pi_lcn->
+							lcnphy_tssi_idx);
+			wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
+			mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
+
+			pi_lcn->lcnphy_tssi_tx_cnt =
+			    wlc_lcnphy_total_tx_frames(pi);
+
+			wlc_lcnphy_disable_tx_gain_override(pi);
+			pi_lcn->lcnphy_tx_power_idx_override = -1;
+		} else
+			wlc_lcnphy_enable_tx_gain_override(pi);
+
+		mod_phy_reg(pi, 0x4a4,
+			    ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
+		if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
+			index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+			wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
+			pi_lcn->lcnphy_current_index = (s8)
+			    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+		}
+	}
+}
+
+static bool wlc_lcnphy_iqcal_wait(phy_info_t *pi)
+{
+	uint delay_count = 0;
+
+	while (wlc_lcnphy_iqcal_active(pi)) {
+		udelay(100);
+		delay_count++;
+
+		if (delay_count > (10 * 500))
+			break;
+	}
+
+	return (0 == wlc_lcnphy_iqcal_active(pi));
+}
+
+static void
+wlc_lcnphy_tx_iqlo_cal(phy_info_t *pi,
+		       lcnphy_txgains_t *target_gains,
+		       lcnphy_cal_mode_t cal_mode, bool keep_tone)
+{
+
+	lcnphy_txgains_t cal_gains, temp_gains;
+	u16 hash;
+	u8 band_idx;
+	int j;
+	u16 ncorr_override[5];
+	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+	};
+
+	u16 commands_fullcal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+
+	u16 commands_recal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+
+	u16 command_nums_fullcal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+
+	u16 command_nums_recal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+	u16 *command_nums = command_nums_fullcal;
+
+	u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
+	u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
+	u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
+	bool tx_gain_override_old;
+	lcnphy_txgains_t old_gains;
+	uint i, n_cal_cmds = 0, n_cal_start = 0;
+	u16 *values_to_save;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+	if (NULL == values_to_save) {
+		return;
+	}
+
+	save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+	save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	or_phy_reg(pi, 0x6da, 0x40);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	switch (cal_mode) {
+	case LCNPHY_CAL_FULL:
+		start_coeffs = syst_coeffs;
+		cal_cmds = commands_fullcal;
+		n_cal_cmds = ARRAY_SIZE(commands_fullcal);
+		break;
+
+	case LCNPHY_CAL_RECAL:
+		ASSERT(pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid);
+
+		start_coeffs = syst_coeffs;
+
+		cal_cmds = commands_recal;
+		n_cal_cmds = ARRAY_SIZE(commands_recal);
+		command_nums = command_nums_recal;
+		break;
+	default:
+		ASSERT(false);
+	}
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      start_coeffs, 11, 16, 64);
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+	mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
+
+	tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
+
+	mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
+
+	mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	if (tx_gain_override_old)
+		wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	if (!target_gains) {
+		if (!tx_gain_override_old)
+			wlc_lcnphy_set_tx_pwr_by_index(pi,
+						       pi_lcn->lcnphy_tssi_idx);
+		wlc_lcnphy_get_tx_gain(pi, &temp_gains);
+		target_gains = &temp_gains;
+	}
+
+	hash = (target_gains->gm_gain << 8) |
+	    (target_gains->pga_gain << 4) | (target_gains->pad_gain);
+
+	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	cal_gains = *target_gains;
+	memset(ncorr_override, 0, sizeof(ncorr_override));
+	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
+		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
+			cal_gains.gm_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+			cal_gains.pga_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+			cal_gains.pad_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+			memcpy(ncorr_override,
+			       &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
+			       sizeof(ncorr_override));
+			break;
+		}
+	}
+
+	wlc_lcnphy_set_tx_gain(pi, &cal_gains);
+
+	write_phy_reg(pi, 0x453, 0xaa9);
+	write_phy_reg(pi, 0x93d, 0xc0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      (const void *)
+				      lcnphy_iqcal_loft_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
+				      16, 0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      (const void *)lcnphy_iqcal_ir_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
+				      32);
+
+	if (pi->phy_tx_tone_freq) {
+
+		wlc_lcnphy_stop_tx_tone(pi);
+		udelay(5);
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	} else {
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	}
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+
+	for (i = n_cal_start; i < n_cal_cmds; i++) {
+		u16 zero_diq = 0;
+		u16 best_coeffs[11];
+		u16 command_num;
+
+		cal_type = (cal_cmds[i] & 0x0f00) >> 8;
+
+		command_num = command_nums[i];
+		if (ncorr_override[cal_type])
+			command_num =
+			    ncorr_override[cal_type] << 8 | (command_num &
+							     0xff);
+
+		write_phy_reg(pi, 0x452, command_num);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+
+			wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						     &diq_start, 1, 16, 69);
+
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &zero_diq, 1, 16, 69);
+		}
+
+		write_phy_reg(pi, 0x451, cal_cmds[i]);
+
+		if (!wlc_lcnphy_iqcal_wait(pi)) {
+
+			goto cleanup;
+		}
+
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     best_coeffs,
+					     ARRAY_SIZE(best_coeffs), 16, 96);
+		wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					      best_coeffs,
+					      ARRAY_SIZE(best_coeffs), 16, 64);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &diq_start, 1, 16, 69);
+		}
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     pi_lcn->lcnphy_cal_results.
+					     txiqlocal_bestcoeffs,
+					     ARRAY_SIZE(pi_lcn->
+						       lcnphy_cal_results.
+						       txiqlocal_bestcoeffs),
+					     16, 96);
+	}
+
+	wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				     pi_lcn->lcnphy_cal_results.
+				     txiqlocal_bestcoeffs,
+				     ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
+					       txiqlocal_bestcoeffs), 16, 96);
+	pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[0], 4, 16, 80);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[5], 2, 16, 85);
+
+ cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
+	kfree(values_to_save);
+
+	if (!keep_tone)
+		wlc_lcnphy_stop_tx_tone(pi);
+
+	write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
+
+	write_phy_reg(pi, 0x453, 0);
+
+	if (tx_gain_override_old)
+		wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
+
+	write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
+	write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
+
+}
+
+static void wlc_lcnphy_idle_tssi_est(wlc_phy_t *ppi)
+{
+	bool suspend, tx_gain_override_old;
+	lcnphy_txgains_t old_gains;
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
+	    idleTssi0_regvalue_2C;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
+	u16 SAVE_jtag_bb_afe_switch =
+	    read_radio_reg(pi, RADIO_2064_REG007) & 1;
+	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
+	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
+	idleTssi = read_phy_reg(pi, 0x4ab);
+	suspend =
+	    (0 ==
+	     (R_REG(&((phy_info_t *) pi)->regs->maccontrol) &
+	      MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
+	wlc_lcnphy_tssi_setup(pi);
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+		    >> 0);
+
+	idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
+			>> 0);
+
+	if (idleTssi0_2C >= 256)
+		idleTssi0_OB = idleTssi0_2C - 256;
+	else
+		idleTssi0_OB = idleTssi0_2C + 256;
+
+	idleTssi0_regvalue_OB = idleTssi0_OB;
+	if (idleTssi0_regvalue_OB >= 256)
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
+	else
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
+
+	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
+	mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static void wlc_lcnphy_vbat_temp_sense_setup(phy_info_t *pi, u8 mode)
+{
+	bool suspend;
+	u16 save_txpwrCtrlEn;
+	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+	u16 auxpga_vmid;
+	phytbl_info_t tab;
+	u32 val;
+	u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
+	    save_reg112;
+	u16 values_to_save[14];
+	s8 index;
+	int i;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	udelay(999);
+
+	save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
+	save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
+	save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
+	save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
+	save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
+	save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
+
+	for (i = 0; i < 14; i++)
+		values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+	index = pi_lcn->lcnphy_current_index;
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xC);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+	if (mode == TEMPSENSE) {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
+
+		auxpga_vmidcourse = 8;
+		auxpga_vmidfine = 0x4;
+		auxpga_gain = 2;
+		mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
+	} else {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
+
+		auxpga_vmidcourse = 7;
+		auxpga_vmidfine = 0xa;
+		auxpga_gain = 2;
+	}
+	auxpga_vmid =
+	    (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
+
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
+
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	if (!tempsense_done(pi))
+		udelay(10);
+
+	write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
+	write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
+	write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
+	write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
+	write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
+	write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
+	for (i = 0; i < 14; i++)
+		write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
+
+	write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+	udelay(999);
+}
+
+void WLBANDINITFN(wlc_lcnphy_tx_pwr_ctrl_init) (wlc_phy_t *ppi)
+{
+	lcnphy_txgains_t tx_gains;
+	u8 bbmult;
+	phytbl_info_t tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	bool suspend;
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		wlc_lcnphy_set_bbmult(pi, 0x30);
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+		return;
+	}
+
+	if (!pi->hwpwrctrl_capable) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			tx_gains.gm_gain = 4;
+			tx_gains.pga_gain = 12;
+			tx_gains.pad_gain = 12;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		} else {
+			tx_gains.gm_gain = 7;
+			tx_gains.pga_gain = 15;
+			tx_gains.pad_gain = 14;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		}
+		wlc_lcnphy_set_tx_gain(pi, &tx_gains);
+		wlc_lcnphy_set_bbmult(pi, bbmult);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	} else {
+
+		wlc_lcnphy_idle_tssi_est(ppi);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
+
+		write_phy_reg(pi, 0x4a8, 10);
+
+		wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	}
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi)
+{
+	u16 m0m1;
+	phytbl_info_t tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return (u8) ((m0m1 & 0xff00) >> 8);
+}
+
+static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain)
+{
+	mod_phy_reg(pi, 0x4fb,
+		    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
+	mod_phy_reg(pi, 0x4fd,
+		    LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
+}
+
+void
+wlc_lcnphy_get_radio_loft(phy_info_t *pi,
+			  u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
+{
+	*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
+	*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
+	*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
+	*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
+}
+
+static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains)
+{
+	u16 dac_gain;
+
+	dac_gain = read_phy_reg(pi, 0x439) >> 0;
+	gains->dac_gain = (dac_gain & 0x380) >> 7;
+
+	{
+		u16 rfgain0, rfgain1;
+
+		rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
+		rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
+
+		gains->gm_gain = rfgain0 & 0xff;
+		gains->pga_gain = (rfgain0 >> 8) & 0xff;
+		gains->pad_gain = rfgain1 & 0xff;
+	}
+}
+
+void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b)
+{
+	phytbl_info_t tab;
+	u16 iqcc[2];
+
+	iqcc[0] = a;
+	iqcc[1] = b;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_offset = 80;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq)
+{
+	phytbl_info_t tab;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index)
+{
+	phytbl_info_t tab;
+	u16 a, b;
+	u8 bb_mult;
+	u32 bbmultiqcomp, txgain, locoeffs, rfpower;
+	lcnphy_txgains_t gains;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	ASSERT(index <= LCNPHY_MAX_TX_POWER_INDEX);
+
+	pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
+	pi_lcn->lcnphy_current_index = (u8) index;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+	tab.tbl_ptr = &bbmultiqcomp;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &txgain;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	gains.gm_gain = (u16) (txgain & 0xff);
+	gains.pga_gain = (u16) (txgain >> 8) & 0xff;
+	gains.pad_gain = (u16) (txgain >> 16) & 0xff;
+	gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
+	wlc_lcnphy_set_tx_gain(pi, &gains);
+	wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
+
+	bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
+	wlc_lcnphy_set_bbmult(pi, bb_mult);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
+		b = (u16) (bbmultiqcomp & 0x3ff);
+		wlc_lcnphy_set_tx_iqcc(pi, a, b);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
+		tab.tbl_ptr = &locoeffs;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		tab.tbl_ptr = &rfpower;
+		wlc_lcnphy_read_table(pi, &tab);
+		mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
+
+	}
+}
+
+static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx)
+{
+
+	mod_phy_reg(pi, 0x44d,
+		    (0x1 << 1) |
+		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
+
+	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
+}
+
+static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi)
+{
+	u32 j;
+	phytbl_info_t tab;
+	u32 temp_offset[128];
+	tab.tbl_ptr = temp_offset;
+	tab.tbl_len = 128;
+	tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
+	tab.tbl_width = 32;
+	tab.tbl_offset = 0;
+
+	memset(temp_offset, 0, sizeof(temp_offset));
+	for (j = 1; j < 128; j += 2)
+		temp_offset[j] = 0x80000;
+
+	wlc_lcnphy_write_table(pi, &tab);
+	return;
+}
+
+static void
+wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
+				       u16 trsw,
+				       u16 ext_lna,
+				       u16 biq2,
+				       u16 biq1,
+				       u16 tia, u16 lna2, u16 lna1)
+{
+	u16 gain0_15, gain16_19;
+
+	gain16_19 = biq2 & 0xf;
+	gain0_15 = ((biq1 & 0xf) << 12) |
+	    ((tia & 0xf) << 8) |
+	    ((lna2 & 0x3) << 6) |
+	    ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
+
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	} else {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	}
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+
+}
+
+static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable)
+{
+	u16 ebit = enable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
+		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
+		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
+	}
+}
+
+void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable)
+{
+	if (!bEnable) {
+
+		and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
+
+		and_phy_reg(pi, 0x44c,
+			    ~(u16) ((0x1 << 3) |
+				       (0x1 << 5) |
+				       (0x1 << 12) |
+				       (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x44d,
+			    ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
+
+		and_phy_reg(pi, 0x4f9,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x4fa,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+	} else {
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+		mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+		wlc_lcnphy_set_trsw_override(pi, true, false);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
+		} else {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		}
+	}
+}
+
+static void
+wlc_lcnphy_run_samples(phy_info_t *pi,
+		       u16 num_samps,
+		       u16 num_loops, u16 wait, bool iqcalmode)
+{
+
+	or_phy_reg(pi, 0x6da, 0x8080);
+
+	mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
+	if (num_loops != 0xffff)
+		num_loops--;
+	mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
+
+	mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
+
+	if (iqcalmode) {
+
+		and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
+		or_phy_reg(pi, 0x453, (0x1 << 15));
+	} else {
+		write_phy_reg(pi, 0x63f, 1);
+		wlc_lcnphy_tx_pu(pi, 1);
+	}
+
+	or_radio_reg(pi, RADIO_2064_REG112, 0x6);
+}
+
+void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode)
+{
+
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+	}
+
+	if (phybw40 == 0) {
+		mod_phy_reg((pi), 0x410,
+			    (0x1 << 6) |
+			    (0x1 << 5),
+			    ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
+			    6 | (!mode) << 5);
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
+	}
+}
+
+void
+wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz, u16 max_val,
+			 bool iqcalmode)
+{
+	u8 phy_bw;
+	u16 num_samps, t, k;
+	u32 bw;
+	fixed theta = 0, rot = 0;
+	cs32 tone_samp;
+	u32 data_buf[64];
+	u16 i_samp, q_samp;
+	phytbl_info_t tab;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = f_kHz;
+
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	phy_bw = 40;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x2);
+		write_phy_reg(pi, 0x93b, 0x0);
+		write_phy_reg(pi, 0x93c, 0x0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+	}
+
+	if (f_kHz) {
+		k = 1;
+		do {
+			bw = phy_bw * 1000 * k;
+			num_samps = bw / ABS(f_kHz);
+			ASSERT(num_samps <= ARRAY_SIZE(data_buf));
+			k++;
+		} while ((num_samps * (u32) (ABS(f_kHz))) != bw);
+	} else
+		num_samps = 2;
+
+	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		wlc_phy_cordic(theta, &tone_samp);
+
+		theta += rot;
+
+		i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
+		q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
+		data_buf[t] = (i_samp << 10) | q_samp;
+	}
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
+
+	tab.tbl_ptr = data_buf;
+	tab.tbl_len = num_samps;
+	tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
+	tab.tbl_offset = 0;
+	tab.tbl_width = 32;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
+}
+
+void wlc_lcnphy_stop_tx_tone(phy_info_t *pi)
+{
+	s16 playback_status;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = 0;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, 0x2017);
+		write_phy_reg(pi, 0x93c, 0x27c5);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+	}
+
+	playback_status = read_phy_reg(pi, 0x644);
+	if (playback_status & (0x1 << 0)) {
+		wlc_lcnphy_tx_pu(pi, 0);
+		mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
+	} else if (playback_status & (0x1 << 1))
+		mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
+
+	and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
+
+	wlc_lcnphy_deaf_mode(pi, false);
+}
+
+static void wlc_lcnphy_clear_trsw_override(phy_info_t *pi)
+{
+
+	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+}
+
+void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b)
+{
+	u16 iqcc[2];
+	phytbl_info_t tab;
+
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_id = 0;
+	tab.tbl_offset = 80;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	*a = iqcc[0];
+	*b = iqcc[1];
+}
+
+u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u16 didq;
+
+	tab.tbl_id = 0;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return didq;
+}
+
+static void wlc_lcnphy_txpwrtbl_iqlo_cal(phy_info_t *pi)
+{
+
+	lcnphy_txgains_t target_gains, old_gains;
+	u8 save_bb_mult;
+	u16 a, b, didq, save_pa_gain = 0;
+	uint idx, SAVE_txpwrindex = 0xFF;
+	u32 val;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	phytbl_info_t tab;
+	u8 ei0, eq0, fi0, fq0;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+	save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	save_bb_mult = wlc_lcnphy_get_bbmult(pi);
+
+	if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
+		SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	target_gains.gm_gain = 7;
+	target_gains.pga_gain = 0;
+	target_gains.pad_gain = 21;
+	target_gains.dac_gain = 0;
+	wlc_lcnphy_set_tx_gain(pi, &target_gains);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
+
+		wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+				       (pi_lcn->
+					lcnphy_recal ? LCNPHY_CAL_RECAL :
+					LCNPHY_CAL_FULL), false);
+	} else {
+
+		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+	}
+
+	wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
+	if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			target_gains.gm_gain = 255;
+			target_gains.pga_gain = 255;
+			target_gains.pad_gain = 0xf0;
+			target_gains.dac_gain = 0;
+		} else {
+			target_gains.gm_gain = 7;
+			target_gains.pga_gain = 45;
+			target_gains.pad_gain = 186;
+			target_gains.dac_gain = 0;
+		}
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 1)
+		    || pi_lcn->lcnphy_hw_iqcal_en) {
+
+			target_gains.pga_gain = 0;
+			target_gains.pad_gain = 30;
+			wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+			wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+					       LCNPHY_CAL_FULL, false);
+		} else {
+
+			wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+		}
+
+	}
+
+	wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+
+	didq = wlc_lcnphy_get_tx_locc(pi);
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &val;
+
+	tab.tbl_len = 1;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+
+	for (idx = 0; idx < 128; idx++) {
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
+
+		wlc_lcnphy_read_table(pi, &tab);
+		val = (val & 0xfff00000) |
+		    ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = didq;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
+	pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
+	pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
+	pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
+
+	wlc_lcnphy_set_bbmult(pi, save_bb_mult);
+	wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+
+	if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+	else
+		wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
+}
+
+s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s16 avg = 0;
+	bool suspend = 0;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (s16) (tempsenseval1 - 512);
+	else
+		avg = (s16) tempsenseval1;
+
+	if (tempsenseval2 > 255)
+		avg += (s16) (tempsenseval2 - 512);
+	else
+		avg += (s16) tempsenseval2;
+
+	avg /= 2;
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return avg;
+}
+
+u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s32 avg = 0;
+	bool suspend = 0;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (int)(tempsenseval1 - 512);
+	else
+		avg = (int)tempsenseval1;
+
+	if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg - tempsenseval2 + 512);
+		else
+			avg = (int)(avg - tempsenseval2);
+	} else {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg + tempsenseval2 - 512);
+		else
+			avg = (int)(avg + tempsenseval2);
+		avg = avg / 2;
+	}
+	if (avg < 0)
+		avg = avg + 512;
+
+	if (pi_lcn->lcnphy_tempsense_option == 2)
+		avg = tempsenseval1;
+
+	if (mode)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (u16) avg;
+}
+
+s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode)
+{
+	s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
+	degree =
+	    ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
+	    / LCN_TEMPSENSE_DEN;
+	return (s8) degree;
+}
+
+s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode)
+{
+	u16 vbatsenseval;
+	s32 avg = 0;
+	bool suspend = 0;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
+	}
+
+	vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
+
+	if (vbatsenseval > 255)
+		avg = (s32) (vbatsenseval - 512);
+	else
+		avg = (s32) vbatsenseval;
+
+	avg =
+	    (avg * LCN_VBAT_SCALE_NOM +
+	     (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
+
+	if (mode == 1) {
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (s8) avg;
+}
+
+static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode)
+{
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
+
+	if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
+	    (mode == AFE_CLK_INIT_MODE_TXRX2X))
+		write_phy_reg(pi, 0x6d0, 0x7);
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+}
+
+static bool
+wlc_lcnphy_rx_iq_est(phy_info_t *pi,
+		     u16 num_samps,
+		     u8 wait_time, lcnphy_iq_est_t *iq_est)
+{
+	int wait_count = 0;
+	bool result = true;
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
+
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
+
+	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
+
+	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
+
+		if (wait_count > (10 * 500)) {
+			result = false;
+			goto cleanup;
+		}
+		udelay(100);
+		wait_count++;
+	}
+
+	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
+	    (u32) read_phy_reg(pi, 0x484);
+	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
+	    (u32) read_phy_reg(pi, 0x486);
+	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
+	    (u32) read_phy_reg(pi, 0x488);
+
+ cleanup:
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
+
+	return result;
+}
+
+static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps)
+{
+#define LCNPHY_MIN_RXIQ_PWR 2
+	bool result;
+	u16 a0_new, b0_new;
+	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
+	s32 a, b, temp;
+	s16 iq_nbits, qq_nbits, arsh, brsh;
+	s32 iq;
+	u32 ii, qq;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
+	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
+	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
+
+	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
+
+	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
+	if (!result)
+		goto cleanup;
+
+	iq = (s32) iq_est.iq_prod;
+	ii = iq_est.i_pwr;
+	qq = iq_est.q_pwr;
+
+	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
+		result = false;
+		goto cleanup;
+	}
+
+	iq_nbits = wlc_phy_nbits(iq);
+	qq_nbits = wlc_phy_nbits(qq);
+
+	arsh = 10 - (30 - iq_nbits);
+	if (arsh >= 0) {
+		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+		temp = (s32) (ii >> arsh);
+		if (temp == 0) {
+			return false;
+		}
+	} else {
+		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+		temp = (s32) (ii << -arsh);
+		if (temp == 0) {
+			return false;
+		}
+	}
+	a /= temp;
+	brsh = qq_nbits - 31 + 20;
+	if (brsh >= 0) {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii >> brsh);
+		if (temp == 0) {
+			return false;
+		}
+	} else {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii << -brsh);
+		if (temp == 0) {
+			return false;
+		}
+	}
+	b /= temp;
+	b -= a * a;
+	b = (s32) wlc_phy_sqrt_int((u32) b);
+	b -= (1 << 10);
+	a0_new = (u16) (a & 0x3ff);
+	b0_new = (u16) (b & 0x3ff);
+ cleanup:
+
+	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
+
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
+
+	return result;
+}
+
+static bool
+wlc_lcnphy_rx_iq_cal(phy_info_t *pi, const lcnphy_rx_iqcomp_t *iqcomp,
+		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
+		     int tx_gain_idx)
+{
+	lcnphy_txgains_t old_gains;
+	u16 tx_pwr_ctrl;
+	u8 tx_gain_index_old = 0;
+	bool result = false, tx_gain_override_old = false;
+	u16 i, Core1TxControl_old, RFOverride0_old,
+	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
+	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
+	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
+	int tia_gain;
+	u32 received_power, rx_pwr_threshold;
+	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
+	u16 values_to_save[11];
+	s16 *ptr;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+	if (NULL == ptr) {
+		return false;
+	}
+	if (module == 2) {
+		ASSERT(iqcomp_sz);
+
+		while (iqcomp_sz--) {
+			if (iqcomp[iqcomp_sz].chan ==
+			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
+
+				wlc_lcnphy_set_rx_iq_comp(pi,
+							  (u16)
+							  iqcomp[iqcomp_sz].a,
+							  (u16)
+							  iqcomp[iqcomp_sz].b);
+				result = true;
+				break;
+			}
+		}
+		ASSERT(result);
+		goto cal_done;
+	}
+
+	if (module == 1) {
+
+		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+		for (i = 0; i < 11; i++) {
+			values_to_save[i] =
+			    read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+		}
+		Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+		or_phy_reg(pi, 0x631, 0x0015);
+
+		RFOverride0_old = read_phy_reg(pi, 0x44c);
+		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+		rfoverride2_old = read_phy_reg(pi, 0x4b0);
+		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+		rfoverride3_old = read_phy_reg(pi, 0x4f9);
+		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+		rfoverride4_old = read_phy_reg(pi, 0x938);
+		rfoverride4val_old = read_phy_reg(pi, 0x939);
+		afectrlovr_old = read_phy_reg(pi, 0x43b);
+		afectrlovrval_old = read_phy_reg(pi, 0x43c);
+		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+		if (tx_gain_override_old) {
+			wlc_lcnphy_get_tx_gain(pi, &old_gains);
+			tx_gain_index_old = pi_lcn->lcnphy_current_index;
+		}
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+
+		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+		write_phy_reg(pi, 0x6da, 0xffff);
+		or_phy_reg(pi, 0x6db, 0x3);
+		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+		wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+		tia_gain = 8;
+		rx_pwr_threshold = 950;
+		while (tia_gain > 0) {
+			tia_gain -= 1;
+			wlc_lcnphy_set_rx_gain_by_distribution(pi,
+							       0, 0, 2, 2,
+							       (u16)
+							       tia_gain, 1, 0);
+			udelay(500);
+
+			received_power =
+			    wlc_lcnphy_measure_digital_power(pi, 2000);
+			if (received_power < rx_pwr_threshold)
+				break;
+		}
+		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+
+		wlc_lcnphy_stop_tx_tone(pi);
+
+		write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x4b0, rfoverride2_old);
+		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+		write_phy_reg(pi, 0x4f9, rfoverride3_old);
+		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+		write_phy_reg(pi, 0x938, rfoverride4_old);
+		write_phy_reg(pi, 0x939, rfoverride4val_old);
+		write_phy_reg(pi, 0x43b, afectrlovr_old);
+		write_phy_reg(pi, 0x43c, afectrlovrval_old);
+		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+
+		wlc_lcnphy_clear_trsw_override(pi);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+
+		for (i = 0; i < 11; i++) {
+			write_radio_reg(pi, rxiq_cal_rf_reg[i],
+					values_to_save[i]);
+		}
+
+		if (tx_gain_override_old) {
+			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+		} else
+			wlc_lcnphy_disable_tx_gain_override(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+
+		wlc_lcnphy_rx_gain_override_enable(pi, false);
+	}
+
+ cal_done:
+	kfree(ptr);
+	return result;
+}
+
+static void wlc_lcnphy_temp_adj(phy_info_t *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+}
+
+static void wlc_lcnphy_glacial_timer_based_cal(phy_info_t *pi)
+{
+	bool suspend;
+	s8 index;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_deaf_mode(pi, true);
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	index = pi_lcn->lcnphy_current_index;
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+}
+
+static void wlc_lcnphy_periodic_cal(phy_info_t *pi)
+{
+	bool suspend, full_cal;
+	const lcnphy_rx_iqcomp_t *rx_iqcomp;
+	int rx_iqcomp_sz;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	phytbl_info_t tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	full_cal =
+	    (pi_lcn->lcnphy_full_cal_channel !=
+	     CHSPEC_CHANNEL(pi->radio_chanspec));
+	pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+	index = pi_lcn->lcnphy_current_index;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend) {
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
+	rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
+	else
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		wlc_lcnphy_idle_tssi_est((wlc_phy_t *) pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+	}
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode)
+{
+	u16 temp_new;
+	int temp1, temp2, temp_diff;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	switch (mode) {
+	case PHY_PERICAL_CHAN:
+
+		break;
+	case PHY_FULLCAL:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_PHYINIT:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_WATCHDOG:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+			temp_new = wlc_lcnphy_tempsense(pi, 0);
+			temp1 = LCNPHY_TEMPSENSE(temp_new);
+			temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
+			temp_diff = temp1 - temp2;
+			if ((pi_lcn->lcnphy_cal_counter > 90) ||
+			    (temp_diff > 60) || (temp_diff < -60)) {
+				wlc_lcnphy_glacial_timer_based_cal(pi);
+				wlc_2064_vco_cal(pi);
+				pi_lcn->lcnphy_cal_temper = temp_new;
+				pi_lcn->lcnphy_cal_counter = 0;
+			} else
+				pi_lcn->lcnphy_cal_counter++;
+		}
+		break;
+	case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+			wlc_lcnphy_tx_power_adjustment((wlc_phy_t *) pi);
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+}
+
+void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr, s8 *cck_pwr)
+{
+	s8 cck_offset;
+	u16 status;
+	status = (read_phy_reg(pi, 0x4ab));
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    (status  & (0x1 << 15))) {
+		*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+				     >> 0) >> 1);
+
+		if (wlc_phy_tpc_isenabled_lcnphy(pi))
+			cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
+		else
+			cck_offset = 0;
+
+		*cck_pwr = *ofdm_pwr + cck_offset;
+	} else {
+		*cck_pwr = 0;
+		*ofdm_pwr = 0;
+	}
+}
+
+void WLBANDINITFN(wlc_phy_cal_init_lcnphy) (phy_info_t *pi)
+{
+	return;
+
+}
+
+static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi, chanspec_t chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if (channel == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+	}
+	pi_lcn->lcnphy_bandedge_corr = 2;
+	if (channel == 1)
+		pi_lcn->lcnphy_bandedge_corr = 4;
+
+	if (channel == 1 || channel == 2 || channel == 3 ||
+	    channel == 4 || channel == 9 ||
+	    channel == 10 || channel == 11 || channel == 12) {
+		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
+		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
+		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
+
+		si_pmu_pllupd(pi->sh->sih);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+		pi_lcn->lcnphy_spurmod = 0;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
+
+		write_phy_reg(pi, 0x425, 0x5907);
+	} else {
+		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
+		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
+		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
+
+		si_pmu_pllupd(pi->sh->sih);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+
+		pi_lcn->lcnphy_spurmod = 0;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
+
+		write_phy_reg(pi, 0x425, 0x590a);
+	}
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+}
+
+void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi)
+{
+	s8 index;
+	u16 index2;
+	phy_info_t *pi = (phy_info_t *) ppi;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
+		index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+		index2 = (u16) (index * 2);
+		mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+		pi_lcn->lcnphy_current_index = (s8)
+		    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+	}
+}
+
+static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b)
+{
+	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
+
+}
+
+void WLBANDINITFN(wlc_phy_init_lcnphy) (phy_info_t *pi)
+{
+	u8 phybw40;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	pi_lcn->lcnphy_cal_counter = 0;
+	pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
+
+	or_phy_reg(pi, 0x44a, 0x80);
+	and_phy_reg(pi, 0x44a, 0x7f);
+
+	wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
+
+	write_phy_reg(pi, 0x60a, 160);
+
+	write_phy_reg(pi, 0x46a, 25);
+
+	wlc_lcnphy_baseband_init(pi);
+
+	wlc_lcnphy_radio_init(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_lcnphy_tx_pwr_ctrl_init((wlc_phy_t *) pi);
+
+	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
+
+	si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
+
+	si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
+
+	wlc_lcnphy_agc_temp_init(pi);
+
+	wlc_lcnphy_temp_adj(pi);
+
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+	udelay(100);
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
+	wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi, u16 *values_to_save)
+{
+	u16 vmid;
+	int i;
+	for (i = 0; i < 20; i++) {
+		values_to_save[i] =
+		    read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
+	}
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+	mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
+	mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
+	else
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
+
+	or_radio_reg(pi, RADIO_2064_REG036, 0x01);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
+	udelay(20);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 1);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xF);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG005, 0x8);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x80);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+	or_radio_reg(pi, RADIO_2064_REG113, 0x10);
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG007, 0x1);
+	udelay(20);
+
+	vmid = 0x2A6;
+	mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
+	write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	udelay(20);
+	write_radio_reg(pi, RADIO_2064_REG012, 0x02);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x06);
+	write_radio_reg(pi, RADIO_2064_REG036, 0x11);
+	write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
+	write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
+	write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
+	write_radio_reg(pi, RADIO_2064_REG092, 0x15);
+}
+
+static void
+wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo, u16 thresh,
+		    s16 *ptr, int mode)
+{
+	u32 curval1, curval2, stpptr, curptr, strptr, val;
+	u16 sslpnCalibClkEnCtrl, timer;
+	u16 old_sslpnCalibClkEnCtrl;
+	s16 imag, real;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	timer = 0;
+	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	curval1 = R_REG(&pi->regs->psm_corectlsts);
+	ptr[130] = 0;
+	W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
+
+	W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
+	W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
+	udelay(20);
+	curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
+	W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
+
+	write_phy_reg(pi, 0x555, 0x0);
+	write_phy_reg(pi, 0x5a6, 0x5);
+
+	write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
+	write_phy_reg(pi, 0x5cf, 3);
+	write_phy_reg(pi, 0x5a5, 0x3);
+	write_phy_reg(pi, 0x583, 0x0);
+	write_phy_reg(pi, 0x584, 0x0);
+	write_phy_reg(pi, 0x585, 0x0fff);
+	write_phy_reg(pi, 0x586, 0x0000);
+
+	write_phy_reg(pi, 0x580, 0x4501);
+
+	sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+	write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
+	stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
+	curptr = R_REG(&pi->regs->smpl_clct_curptr);
+	do {
+		udelay(10);
+		curptr = R_REG(&pi->regs->smpl_clct_curptr);
+		timer++;
+	} while ((curptr != stpptr) && (timer < 500));
+
+	W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
+	strptr = 0x7E00;
+	W_REG(&pi->regs->tplatewrptr, strptr);
+	while (strptr < 0x8000) {
+		val = R_REG(&pi->regs->tplatewrdata);
+		imag = ((val >> 16) & 0x3ff);
+		real = ((val) & 0x3ff);
+		if (imag > 511) {
+			imag -= 1024;
+		}
+		if (real > 511) {
+			real -= 1024;
+		}
+		if (pi_lcn->lcnphy_iqcal_swp_dis)
+			ptr[(strptr - 0x7E00) / 4] = real;
+		else
+			ptr[(strptr - 0x7E00) / 4] = imag;
+		if (clip_detect_algo) {
+			if (imag > thresh || imag < -thresh) {
+				strptr = 0x8000;
+				ptr[130] = 1;
+			}
+		}
+		strptr += 4;
+	}
+
+	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+	W_REG(&pi->regs->psm_phy_hdr_param, curval2);
+	W_REG(&pi->regs->psm_corectlsts, curval1);
+}
+
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi)
+{
+	lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
+
+	wlc_lcnphy_set_cc(pi, 0, 0, 0);
+	wlc_lcnphy_set_cc(pi, 2, 0, 0);
+	wlc_lcnphy_set_cc(pi, 3, 0, 0);
+	wlc_lcnphy_set_cc(pi, 4, 0, 0);
+
+	wlc_lcnphy_a1(pi, 4, 0, 0);
+	wlc_lcnphy_a1(pi, 3, 0, 0);
+	wlc_lcnphy_a1(pi, 2, 3, 2);
+	wlc_lcnphy_a1(pi, 0, 5, 8);
+	wlc_lcnphy_a1(pi, 2, 2, 1);
+	wlc_lcnphy_a1(pi, 0, 4, 3);
+
+	iqcc0 = wlc_lcnphy_get_cc(pi, 0);
+	locc2 = wlc_lcnphy_get_cc(pi, 2);
+	locc3 = wlc_lcnphy_get_cc(pi, 3);
+	locc4 = wlc_lcnphy_get_cc(pi, 4);
+}
+
+static void
+wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x, s16 coeff_y)
+{
+	u16 di0dq0;
+	u16 x, y, data_rf;
+	int k;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
+		break;
+	case 2:
+		di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
+		wlc_lcnphy_set_tx_locc(pi, di0dq0);
+		break;
+	case 3:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG089, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
+		break;
+	case 4:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
+		break;
+	}
+}
+
+static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type)
+{
+	u16 a, b, didq;
+	u8 di0, dq0, ei, eq, fi, fq;
+	lcnphy_unsign16_struct cc;
+	cc.re = 0;
+	cc.im = 0;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+		cc.re = a;
+		cc.im = b;
+		break;
+	case 2:
+		didq = wlc_lcnphy_get_tx_locc(pi);
+		di0 = (((didq & 0xff00) << 16) >> 24);
+		dq0 = (((didq & 0x00ff) << 24) >> 24);
+		cc.re = (u16) di0;
+		cc.im = (u16) dq0;
+		break;
+	case 3:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) ei;
+		cc.im = (u16) eq;
+		break;
+	case 4:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) fi;
+		cc.im = (u16) fq;
+		break;
+	}
+	return cc;
+}
+
+static void
+wlc_lcnphy_a1(phy_info_t *pi, int cal_type, int num_levels, int step_size_lg2)
+{
+	const lcnphy_spb_tone_t *phy_c1;
+	lcnphy_spb_tone_t phy_c2;
+	lcnphy_unsign16_struct phy_c3;
+	int phy_c4, phy_c5, k, l, j, phy_c6;
+	u16 phy_c7, phy_c8, phy_c9;
+	s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
+	s16 *ptr, phy_c17;
+	s32 phy_c18, phy_c19;
+	u32 phy_c20, phy_c21;
+	bool phy_c22, phy_c23, phy_c24, phy_c25;
+	u16 phy_c26, phy_c27;
+	u16 phy_c28, phy_c29, phy_c30;
+	u16 phy_c31;
+	u16 *phy_c32;
+	phy_c21 = 0;
+	phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
+	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+	if (NULL == ptr) {
+		return;
+	}
+
+	phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+	if (NULL == phy_c32) {
+		kfree(ptr);
+		return;
+	}
+	phy_c26 = read_phy_reg(pi, 0x6da);
+	phy_c27 = read_phy_reg(pi, 0x6db);
+	phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
+	write_phy_reg(pi, 0x93d, 0xC0);
+
+	wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
+	write_phy_reg(pi, 0x6da, 0xffff);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
+	udelay(500);
+	phy_c28 = read_phy_reg(pi, 0x938);
+	phy_c29 = read_phy_reg(pi, 0x4d7);
+	phy_c30 = read_phy_reg(pi, 0x4d8);
+	or_phy_reg(pi, 0x938, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 3);
+	mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
+	or_phy_reg(pi, 0x4d8, 1 << 0);
+	or_phy_reg(pi, 0x4d8, 1 << 1);
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
+	phy_c1 = &lcnphy_spb_tone_3750[0];
+	phy_c4 = 32;
+
+	if (num_levels == 0) {
+		if (cal_type != 0) {
+			num_levels = 4;
+		} else {
+			num_levels = 9;
+		}
+	}
+	if (step_size_lg2 == 0) {
+		if (cal_type != 0) {
+			step_size_lg2 = 3;
+		} else {
+			step_size_lg2 = 8;
+		}
+	}
+
+	phy_c7 = (1 << step_size_lg2);
+	phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
+	phy_c15 = (s16) phy_c3.re;
+	phy_c16 = (s16) phy_c3.im;
+	if (cal_type == 2) {
+		if (phy_c3.re > 127)
+			phy_c15 = phy_c3.re - 256;
+		if (phy_c3.im > 127)
+			phy_c16 = phy_c3.im - 256;
+	}
+	wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+	udelay(20);
+	for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
+		phy_c23 = 1;
+		phy_c22 = 0;
+		switch (cal_type) {
+		case 0:
+			phy_c10 = 511;
+			break;
+		case 2:
+			phy_c10 = 127;
+			break;
+		case 3:
+			phy_c10 = 15;
+			break;
+		case 4:
+			phy_c10 = 15;
+			break;
+		}
+
+		phy_c9 = read_phy_reg(pi, 0x93d);
+		phy_c9 = 2 * phy_c9;
+		phy_c24 = 0;
+		phy_c5 = 7;
+		phy_c25 = 1;
+		while (1) {
+			write_radio_reg(pi, RADIO_2064_REG026,
+					(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
+			udelay(50);
+			phy_c22 = 0;
+			ptr[130] = 0;
+			wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
+			if (ptr[130] == 1)
+				phy_c22 = 1;
+			if (phy_c22)
+				phy_c5 -= 1;
+			if ((phy_c22 != phy_c24) && (!phy_c25))
+				break;
+			if (!phy_c22)
+				phy_c5 += 1;
+			if (phy_c5 <= 0 || phy_c5 >= 7)
+				break;
+			phy_c24 = phy_c22;
+			phy_c25 = 0;
+		}
+
+		if (phy_c5 < 0)
+			phy_c5 = 0;
+		else if (phy_c5 > 7)
+			phy_c5 = 7;
+
+		for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
+			for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
+				phy_c11 = phy_c15 + k;
+				phy_c12 = phy_c16 + l;
+
+				if (phy_c11 < -phy_c10)
+					phy_c11 = -phy_c10;
+				else if (phy_c11 > phy_c10)
+					phy_c11 = phy_c10;
+				if (phy_c12 < -phy_c10)
+					phy_c12 = -phy_c10;
+				else if (phy_c12 > phy_c10)
+					phy_c12 = phy_c10;
+				wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
+						  phy_c12);
+				udelay(20);
+				wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
+
+				phy_c18 = 0;
+				phy_c19 = 0;
+				for (j = 0; j < 128; j++) {
+					if (cal_type != 0) {
+						phy_c6 = j % phy_c4;
+					} else {
+						phy_c6 = (2 * j) % phy_c4;
+					}
+					phy_c2.re = phy_c1[phy_c6].re;
+					phy_c2.im = phy_c1[phy_c6].im;
+					phy_c17 = ptr[j];
+					phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
+					phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
+				}
+
+				phy_c18 = phy_c18 >> 10;
+				phy_c19 = phy_c19 >> 10;
+				phy_c20 =
+				    ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
+
+				if (phy_c23 || phy_c20 < phy_c21) {
+					phy_c21 = phy_c20;
+					phy_c13 = phy_c11;
+					phy_c14 = phy_c12;
+				}
+				phy_c23 = 0;
+			}
+		}
+		phy_c23 = 1;
+		phy_c15 = phy_c13;
+		phy_c16 = phy_c14;
+		phy_c7 = phy_c7 >> 1;
+		wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+		udelay(20);
+	}
+	goto cleanup;
+ cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
+	wlc_lcnphy_stop_tx_tone(pi);
+	write_phy_reg(pi, 0x6da, phy_c26);
+	write_phy_reg(pi, 0x6db, phy_c27);
+	write_phy_reg(pi, 0x938, phy_c28);
+	write_phy_reg(pi, 0x4d7, phy_c29);
+	write_phy_reg(pi, 0x4d8, phy_c30);
+	write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
+
+	kfree(phy_c32);
+	kfree(ptr);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi, u16 *values_to_save)
+{
+	int i;
+
+	and_phy_reg(pi, 0x44c, 0x0 >> 11);
+
+	and_phy_reg(pi, 0x43b, 0xC);
+
+	for (i = 0; i < 20; i++) {
+		write_radio_reg(pi, iqlo_loopback_rf_regs[i],
+				values_to_save[i]);
+	}
+}
+
+static void
+WLBANDINITFN(wlc_lcnphy_load_tx_gain_table) (phy_info_t *pi,
+					     const lcnphy_tx_gain_tbl_entry *
+					     gain_table) {
+	u32 j;
+	phytbl_info_t tab;
+	u32 val;
+	u16 pa_gain;
+	u16 gm_gain;
+
+	if (CHSPEC_IS5G(pi->radio_chanspec))
+		pa_gain = 0x70;
+	else
+		pa_gain = 0x70;
+
+	if (pi->sh->boardflags & BFL_FEM)
+		pa_gain = 0x10;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+
+	for (j = 0; j < 128; j++) {
+		gm_gain = gain_table[j].gm;
+		val = (((u32) pa_gain << 24) |
+		       (gain_table[j].pad << 16) |
+		       (gain_table[j].pga << 8) | gm_gain);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void wlc_lcnphy_load_rfpower(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u32 val, bbmult, rfgain;
+	u8 index;
+	u8 scale_factor = 1;
+	s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	for (index = 0; index < 128; index++) {
+		tab.tbl_ptr = &bbmult;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+		bbmult = bbmult >> 20;
+
+		tab.tbl_ptr = &rfgain;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
+		qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
+
+		if (qQ1 < qQ2) {
+			temp2 = qm_shr16(temp2, qQ2 - qQ1);
+			qQ = qQ1;
+		} else {
+			temp1 = qm_shr16(temp1, qQ1 - qQ2);
+			qQ = qQ2;
+		}
+		temp = qm_sub16(temp1, temp2);
+
+		if (qQ >= 4)
+			shift = qQ - 4;
+		else
+			shift = 4 - qQ;
+
+		val = (((index << shift) + (5 * temp) +
+			(1 << (scale_factor + shift - 3))) >> (scale_factor +
+							       shift - 2));
+
+		tab.tbl_ptr = &val;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void WLBANDINITFN(wlc_lcnphy_tbl_init) (phy_info_t *pi)
+{
+	uint idx;
+	u8 phybw40;
+	phytbl_info_t tab;
+	u32 val;
+
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
+		wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
+	}
+
+	if (pi->sh->boardflags & BFL_FEM_BT) {
+		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+		tab.tbl_width = 16;
+		tab.tbl_ptr = &val;
+		tab.tbl_len = 1;
+		val = 100;
+		tab.tbl_offset = 4;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &val;
+	tab.tbl_len = 1;
+
+	val = 114;
+	tab.tbl_offset = 0;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 130;
+	tab.tbl_offset = 1;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 6;
+	tab.tbl_offset = 8;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->sh->boardflags & BFL_FEM)
+			wlc_lcnphy_load_tx_gain_table(pi,
+						      dot11lcnphy_2GHz_extPA_gaintable_rev0);
+		else
+			wlc_lcnphy_load_tx_gain_table(pi,
+						      dot11lcnphy_2GHz_gaintable_rev0);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			for (idx = 0;
+			     idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+			     idx++)
+				if (pi->sh->boardflags & BFL_EXTLNA)
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
+							       [idx]);
+				else
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_2G_rev2
+							       [idx]);
+		} else {
+			for (idx = 0;
+			     idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+			     idx++)
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
+							       [idx]);
+				else
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_5G_rev2
+							       [idx]);
+		}
+	}
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && !(pi->sh->boardflags & BFL_FEM_BT))
+		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
+	else if (pi->sh->boardflags & BFL_FEM_BT) {
+		if (pi->sh->boardrev < 0x1250)
+			wlc_lcnphy_write_table(pi,
+					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
+		else
+			wlc_lcnphy_write_table(pi,
+					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
+	} else
+		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
+
+	wlc_lcnphy_load_rfpower(pi);
+
+	wlc_lcnphy_clear_papd_comptable(pi);
+}
+
+static void WLBANDINITFN(wlc_lcnphy_rev0_baseband_init) (phy_info_t *pi)
+{
+	u16 afectrl1;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
+
+	write_phy_reg(pi, 0x43b, 0x0);
+	write_phy_reg(pi, 0x43c, 0x0);
+	write_phy_reg(pi, 0x44c, 0x0);
+	write_phy_reg(pi, 0x4e6, 0x0);
+	write_phy_reg(pi, 0x4f9, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x938, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x44e, 0);
+
+	or_phy_reg(pi, 0x567, 0x03);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!(pi->sh->boardflags & BFL_FEM))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
+
+	if (0) {
+		afectrl1 = 0;
+		afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
+				     (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
+								      lcnphy_rssi_gs
+								      << 10));
+		write_phy_reg(pi, 0x43e, afectrl1);
+	}
+
+	mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
+	if (pi->sh->boardflags & BFL_FEM) {
+		mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
+
+		write_phy_reg(pi, 0x910, 0x1);
+	}
+
+	mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
+	mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
+	mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
+
+}
+
+static void WLBANDINITFN(wlc_lcnphy_rev2_baseband_init) (phy_info_t *pi)
+{
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
+
+		mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
+	}
+}
+
+static void wlc_lcnphy_agc_temp_init(phy_info_t *pi)
+{
+	s16 temp;
+	phytbl_info_t tab;
+	u32 tableBuffer[2];
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	temp = (s16) read_phy_reg(pi, 0x4df);
+	pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
+
+	if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
+		pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
+
+	pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
+
+	if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
+		pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = 17;
+	tab.tbl_offset = 59;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	if (tableBuffer[0] > 63)
+		tableBuffer[0] -= 128;
+	pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
+
+	if (tableBuffer[1] > 63)
+		tableBuffer[1] -= 128;
+	pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
+
+	temp = (s16) (read_phy_reg(pi, 0x434)
+			& (0xff << 0));
+	if (temp > 127)
+		temp -= 256;
+	pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
+
+	pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
+					  & (0xff << 8))
+	    >> 8;
+	pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
+					   & (0xff << 0))
+	    >> 0;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
+	tab.tbl_offset = 28;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
+	pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
+
+}
+
+static void WLBANDINITFN(wlc_lcnphy_bu_tweaks) (phy_info_t *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	or_phy_reg(pi, 0x805, 0x1);
+
+	mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
+
+	mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
+
+	write_phy_reg(pi, 0x414, 0x1e10);
+	write_phy_reg(pi, 0x415, 0x0640);
+
+	mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+	mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
+
+	mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
+
+	if (!(pi->sh->boardrev < 0x1204))
+		mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
+
+	write_phy_reg(pi, 0x7d6, 0x0902);
+	mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
+
+	mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
+
+		mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
+
+		mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
+
+		mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+		mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
+		mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
+		mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
+
+		mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+		mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
+
+	}
+}
+
+static void WLBANDINITFN(wlc_lcnphy_baseband_init) (phy_info_t *pi)
+{
+
+	wlc_lcnphy_tbl_init(pi);
+	wlc_lcnphy_rev0_baseband_init(pi);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		wlc_lcnphy_rev2_baseband_init(pi);
+	wlc_lcnphy_bu_tweaks(pi);
+}
+
+static void WLBANDINITFN(wlc_radio_2064_init) (phy_info_t *pi)
+{
+	u32 i;
+	lcnphy_radio_regs_t *lcnphyregs = NULL;
+
+	lcnphyregs = lcnphy_radio_regs_2064;
+
+	for (i = 0; lcnphyregs[i].address != 0xffff; i++)
+		if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_a);
+		else if (lcnphyregs[i].do_init_g)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_g);
+
+	write_radio_reg(pi, RADIO_2064_REG032, 0x62);
+	write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+
+	write_radio_reg(pi, RADIO_2064_REG090, 0x10);
+
+	write_radio_reg(pi, RADIO_2064_REG010, 0x00);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+
+		write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
+		write_radio_reg(pi, RADIO_2064_REG061, 0x72);
+		write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
+	write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
+
+	write_phy_reg(pi, 0x4ea, 0x4688);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
+
+	mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
+
+	wlc_lcnphy_set_tx_locc(pi, 0);
+
+	wlc_lcnphy_rcal(pi);
+
+	wlc_lcnphy_rc_cal(pi);
+}
+
+static void WLBANDINITFN(wlc_lcnphy_radio_init) (phy_info_t *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	wlc_radio_2064_init(pi);
+}
+
+static void wlc_lcnphy_rcal(phy_info_t *pi)
+{
+	u8 rcal_value;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	or_radio_reg(pi, RADIO_2064_REG004, 0x40);
+	or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+
+	or_radio_reg(pi, RADIO_2064_REG078, 0x80);
+	or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+
+	or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+
+	or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
+	mdelay(5);
+	SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+
+	if (wlc_radio_2064_rcal_done(pi)) {
+		rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
+		rcal_value = rcal_value & 0x1f;
+	}
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
+}
+
+static void wlc_lcnphy_rc_cal(phy_info_t *pi)
+{
+	u8 dflt_rc_cal_val;
+	u16 flt_val;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	dflt_rc_cal_val = 7;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		dflt_rc_cal_val = 11;
+	flt_val =
+	    (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
+	    (dflt_rc_cal_val);
+	write_phy_reg(pi, 0x933, flt_val);
+	write_phy_reg(pi, 0x934, flt_val);
+	write_phy_reg(pi, 0x935, flt_val);
+	write_phy_reg(pi, 0x936, flt_val);
+	write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+
+	return;
+}
+
+static bool wlc_phy_txpwr_srom_read_lcnphy(phy_info_t *pi)
+{
+	s8 txpwr = 0;
+	int i;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 cckpo = 0;
+		u32 offset_ofdm, offset_mcs;
+
+		pi_lcn->lcnphy_tr_isolation_mid =
+		    (u8) PHY_GETINTVAR(pi, "triso2g");
+
+		pi_lcn->lcnphy_rx_power_offset =
+		    (u8) PHY_GETINTVAR(pi, "rxpo2g");
+
+		pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
+		pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
+		pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
+
+		pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
+		pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
+		pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
+
+		{
+			pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
+			pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
+			pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
+
+			pi_lcn->lcnphy_rssi_vf_hightemp =
+			    pi_lcn->lcnphy_rssi_vf;
+			pi_lcn->lcnphy_rssi_vc_hightemp =
+			    pi_lcn->lcnphy_rssi_vc;
+			pi_lcn->lcnphy_rssi_gs_hightemp =
+			    pi_lcn->lcnphy_rssi_gs;
+		}
+
+		txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+		pi->tx_srom_max_2g = txpwr;
+
+		for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
+			pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
+			pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
+		}
+
+		cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+		if (cckpo) {
+			uint max_pwr_chan = txpwr;
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
+				    ((cckpo & 0xf) * 2);
+				cckpo >>= 4;
+			}
+
+			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
+				    ((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+		} else {
+			u8 opo = 0;
+
+			opo = (u8) PHY_GETINTVAR(pi, "opo");
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr;
+			}
+
+			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr -
+				    ((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+			offset_mcs =
+			    ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
+			    (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+			pi_lcn->lcnphy_mcs20_po = offset_mcs;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i] =
+				    txpwr - ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+
+		pi_lcn->lcnphy_rawtempsense =
+		    (u16) PHY_GETINTVAR(pi, "rawtempsense");
+		pi_lcn->lcnphy_measPower =
+		    (u8) PHY_GETINTVAR(pi, "measpower");
+		pi_lcn->lcnphy_tempsense_slope =
+		    (u8) PHY_GETINTVAR(pi, "tempsense_slope");
+		pi_lcn->lcnphy_hw_iqcal_en =
+		    (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
+		pi_lcn->lcnphy_iqcal_swp_dis =
+		    (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
+		pi_lcn->lcnphy_tempcorrx =
+		    (u8) PHY_GETINTVAR(pi, "tempcorrx");
+		pi_lcn->lcnphy_tempsense_option =
+		    (u8) PHY_GETINTVAR(pi, "tempsense_option");
+		pi_lcn->lcnphy_freqoffset_corr =
+		    (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
+		if ((u8) getintvar(pi->vars, "aa2g") > 1)
+			wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi,
+					      (u8) getintvar(pi->vars,
+								"aa2g"));
+	}
+	pi_lcn->lcnphy_cck_dig_filt_type = -1;
+	if (PHY_GETVAR(pi, "cckdigfilttype")) {
+		s16 temp;
+		temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
+		if (temp >= 0) {
+			pi_lcn->lcnphy_cck_dig_filt_type = temp;
+		}
+	}
+
+	return true;
+}
+
+void wlc_2064_vco_cal(phy_info_t *pi)
+{
+	u8 calnrst;
+
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
+	calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
+	udelay(300);
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
+}
+
+static void
+wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi, u8 channel)
+{
+	uint i;
+	const chan_info_2064_lcnphy_t *ci;
+	u8 rfpll_doubler = 0;
+	u8 pll_pwrup, pll_pwrup_ovr;
+	fixed qFxtal, qFref, qFvco, qFcal;
+	u8 d15, d16, f16, e44, e45;
+	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
+	u16 loop_bw, d30, setCount;
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+	ci = &chan_info_2064_lcnphy[0];
+	rfpll_doubler = 1;
+
+	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
+
+	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
+	if (!rfpll_doubler) {
+		loop_bw = PLL_2064_LOOP_BW;
+		d30 = PLL_2064_D30;
+	} else {
+		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+		d30 = PLL_2064_D30_DOUBLER;
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
+			if (chan_info_2064_lcnphy[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
+			return;
+		}
+
+		ci = &chan_info_2064_lcnphy[i];
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
+
+	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
+
+	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
+		      (ci->logen_rccr_rx) << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
+		      (ci->pa_rxrf_lna2_freq_tune) << 4);
+
+	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
+
+	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
+	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
+
+	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
+
+	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
+	e44 = 0;
+	e45 = 0;
+
+	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+	if (pi->xtalfreq > 26000000)
+		e44 = 1;
+	if (pi->xtalfreq > 52000000)
+		e45 = 1;
+	if (e44 == 0)
+		fcal_div = 1;
+	else if (e45 == 0)
+		fcal_div = 2;
+	else
+		fcal_div = 4;
+	fvco3 = (ci->freq * 3);
+	fref3 = 2 * fpfd;
+
+	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
+	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
+	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
+	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
+
+	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
+
+	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
+	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
+	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
+
+	d16 = (qFcal * 8 / (d15 + 1)) - 1;
+	write_radio_reg(pi, RADIO_2064_REG051, d16);
+
+	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
+	setCount = f16 * 3 * (ci->freq) / 32 - 1;
+	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
+		      (u8) (setCount >> 8));
+
+	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
+	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
+
+	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
+
+	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
+	while (div_frac >= fref3) {
+		div_int++;
+		div_frac -= fref3;
+	}
+	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
+
+	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
+		      (u8) (div_int >> 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
+		      (u8) (div_int << 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
+		      (u8) (div_frac >> 16));
+	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
+	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
+
+	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
+
+	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
+	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
+	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
+
+	{
+		u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
+		u16 c29, c38, c30, g30, d28;
+		c29 = loop_bw;
+		d29 = 200;
+		c38 = 1250;
+		h29 = d29 / c29;
+		h23 = 1;
+		c28 = 30;
+		d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
+			(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
+		       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
+		    + PLL_2064_LOW_END_KVCO;
+		h28_ten = (d28 * 10) / c28;
+		c30 = 2640;
+		e30 = (d30 - 680) / 490;
+		g30 = 680 + (e30 * 490);
+		h30_ten = (g30 * 10) / c30;
+		cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
+		mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
+	}
+	if (channel >= 1 && channel <= 5)
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
+	else
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
+	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
+
+	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
+	udelay(1);
+
+	wlc_2064_vco_cal(pi);
+
+	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
+	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		write_radio_reg(pi, RADIO_2064_REG038, 3);
+		write_radio_reg(pi, RADIO_2064_REG091, 7);
+	}
+}
+
+bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi)
+{
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return 0;
+	else
+		return (LCNPHY_TX_PWR_CTRL_HW ==
+			wlc_lcnphy_get_tx_pwr_ctrl((pi)));
+}
+
+void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi)
+{
+	u16 pwr_ctrl;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+	} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+		wlc_lcnphy_txpower_recalc_target(pi);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
+	} else
+		return;
+}
+
+void wlc_phy_detach_lcnphy(phy_info_t *pi)
+{
+	kfree(pi->u.pi_lcnphy);
+}
+
+bool wlc_phy_attach_lcnphy(phy_info_t *pi)
+{
+	phy_info_lcnphy_t *pi_lcn;
+
+	pi->u.pi_lcnphy = kzalloc(sizeof(phy_info_lcnphy_t), GFP_ATOMIC);
+	if (pi->u.pi_lcnphy == NULL) {
+		return false;
+	}
+
+	pi_lcn = pi->u.pi_lcnphy;
+
+	if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
+		pi->hwpwrctrl = true;
+		pi->hwpwrctrl_capable = true;
+	}
+
+	pi->xtalfreq = si_alp_clock(pi->sh->sih);
+	ASSERT(0 == (pi->xtalfreq % 1000));
+
+	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
+
+	pi->pi_fptr.init = wlc_phy_init_lcnphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
+	pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
+	pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
+	pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
+	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
+	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
+
+	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
+		return false;
+
+	if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
+		if (pi_lcn->lcnphy_tempsense_option == 3) {
+			pi->hwpwrctrl = true;
+			pi->hwpwrctrl_capable = true;
+			pi->temppwrctrl_capable = false;
+		} else {
+			pi->hwpwrctrl = false;
+			pi->hwpwrctrl_capable = false;
+			pi->temppwrctrl_capable = true;
+		}
+	}
+
+	return true;
+}
+
+static void wlc_lcnphy_set_rx_gain(phy_info_t *pi, u32 gain)
+{
+	u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
+
+	trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
+	ext_lna = (u16) (gain >> 29) & 0x01;
+	lna1 = (u16) (gain >> 0) & 0x0f;
+	lna2 = (u16) (gain >> 4) & 0x0f;
+	tia = (u16) (gain >> 8) & 0xf;
+	biq0 = (u16) (gain >> 12) & 0xf;
+	biq1 = (u16) (gain >> 16) & 0xf;
+
+	gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
+			     ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
+			     ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
+	gain16_19 = biq1;
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+		mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
+	}
+	wlc_lcnphy_rx_gain_override_enable(pi, true);
+}
+
+static u32 wlc_lcnphy_get_receive_power(phy_info_t *pi, s32 *gain_index)
+{
+	u32 received_power = 0;
+	s32 max_index = 0;
+	u32 gain_code = 0;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	max_index = 36;
+	if (*gain_index >= 0)
+		gain_code = lcnphy_23bitgaincode_table[*gain_index];
+
+	if (-1 == *gain_index) {
+		*gain_index = 0;
+		while ((*gain_index <= (s32) max_index)
+		       && (received_power < 700)) {
+			wlc_lcnphy_set_rx_gain(pi,
+					       lcnphy_23bitgaincode_table
+					       [*gain_index]);
+			received_power =
+			    wlc_lcnphy_measure_digital_power(pi,
+							     pi_lcn->
+							     lcnphy_noise_samples);
+			(*gain_index)++;
+		}
+		(*gain_index)--;
+	} else {
+		wlc_lcnphy_set_rx_gain(pi, gain_code);
+		received_power =
+		    wlc_lcnphy_measure_digital_power(pi,
+						     pi_lcn->
+						     lcnphy_noise_samples);
+	}
+
+	return received_power;
+}
+
+s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index)
+{
+	s32 gain = 0;
+	s32 nominal_power_db;
+	s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
+	    input_power_db;
+	s32 received_power, temperature;
+	uint freq;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
+
+	gain = lcnphy_gain_table[gain_index];
+
+	nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
+
+	{
+		u32 power = (received_power * 16);
+		u32 msb1, msb2, val1, val2, diff1, diff2;
+		msb1 = ffs(power) - 1;
+		msb2 = msb1 + 1;
+		val1 = 1 << msb1;
+		val2 = 1 << msb2;
+		diff1 = (power - val1);
+		diff2 = (val2 - power);
+		if (diff1 < diff2)
+			log_val = msb1;
+		else
+			log_val = msb2;
+	}
+
+	log_val = log_val * 3;
+
+	gain_mismatch = (nominal_power_db / 2) - (log_val);
+
+	desired_gain = gain + gain_mismatch;
+
+	input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
+
+	if (input_power_offset_db > 127)
+		input_power_offset_db -= 256;
+
+	input_power_db = input_power_offset_db - desired_gain;
+
+	input_power_db =
+	    input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
+
+	freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
+	if ((freq > 2427) && (freq <= 2467))
+		input_power_db = input_power_db - 1;
+
+	temperature = pi_lcn->lcnphy_lastsensed_temperature;
+
+	if ((temperature - 15) < -30) {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
+		    7;
+	} else if ((temperature - 15) < 4) {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
+		    3;
+	} else {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12);
+	}
+
+	wlc_lcnphy_rx_gain_override_enable(pi, 0);
+
+	return input_power_db;
+}
+
+static int
+wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm, s16 filt_type)
+{
+	s16 filt_index = -1;
+	int j;
+
+	u16 addr[] = {
+		0x910,
+		0x91e,
+		0x91f,
+		0x924,
+		0x925,
+		0x926,
+		0x920,
+		0x921,
+		0x927,
+		0x928,
+		0x929,
+		0x922,
+		0x923,
+		0x930,
+		0x931,
+		0x932
+	};
+
+	u16 addr_ofdm[] = {
+		0x90f,
+		0x900,
+		0x901,
+		0x906,
+		0x907,
+		0x908,
+		0x902,
+		0x903,
+		0x909,
+		0x90a,
+		0x90b,
+		0x904,
+		0x905,
+		0x90c,
+		0x90d,
+		0x90e
+	};
+
+	if (!is_ofdm) {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index == -1) {
+			ASSERT(false);
+		} else {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, addr[j],
+					      LCNPHY_txdigfiltcoeffs_cck
+					      [filt_index][j + 1]);
+			}
+		}
+	} else {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index == -1) {
+			ASSERT(false);
+		} else {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, addr_ofdm[j],
+					      LCNPHY_txdigfiltcoeffs_ofdm
+					      [filt_index][j + 1]);
+			}
+		}
+	}
+
+	return (filt_index != -1) ? 0 : -1;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h
new file mode 100644
index 0000000..b7bfc72
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_phy_lcn_h_
+#define _wlc_phy_lcn_h_
+
+struct phy_info_lcnphy {
+	int lcnphy_txrf_sp_9_override;
+	u8 lcnphy_full_cal_channel;
+	u8 lcnphy_cal_counter;
+	u16 lcnphy_cal_temper;
+	bool lcnphy_recal;
+
+	u8 lcnphy_rc_cap;
+	u32 lcnphy_mcs20_po;
+
+	u8 lcnphy_tr_isolation_mid;
+	u8 lcnphy_tr_isolation_low;
+	u8 lcnphy_tr_isolation_hi;
+
+	u8 lcnphy_bx_arch;
+	u8 lcnphy_rx_power_offset;
+	u8 lcnphy_rssi_vf;
+	u8 lcnphy_rssi_vc;
+	u8 lcnphy_rssi_gs;
+	u8 lcnphy_tssi_val;
+	u8 lcnphy_rssi_vf_lowtemp;
+	u8 lcnphy_rssi_vc_lowtemp;
+	u8 lcnphy_rssi_gs_lowtemp;
+
+	u8 lcnphy_rssi_vf_hightemp;
+	u8 lcnphy_rssi_vc_hightemp;
+	u8 lcnphy_rssi_gs_hightemp;
+
+	s16 lcnphy_pa0b0;
+	s16 lcnphy_pa0b1;
+	s16 lcnphy_pa0b2;
+
+	u16 lcnphy_rawtempsense;
+	u8 lcnphy_measPower;
+	u8 lcnphy_tempsense_slope;
+	u8 lcnphy_freqoffset_corr;
+	u8 lcnphy_tempsense_option;
+	u8 lcnphy_tempcorrx;
+	bool lcnphy_iqcal_swp_dis;
+	bool lcnphy_hw_iqcal_en;
+	uint lcnphy_bandedge_corr;
+	bool lcnphy_spurmod;
+	u16 lcnphy_tssi_tx_cnt;
+	u16 lcnphy_tssi_idx;
+	u16 lcnphy_tssi_npt;
+
+	u16 lcnphy_target_tx_freq;
+	s8 lcnphy_tx_power_idx_override;
+	u16 lcnphy_noise_samples;
+
+	u32 lcnphy_papdRxGnIdx;
+	u32 lcnphy_papd_rxGnCtrl_init;
+
+	u32 lcnphy_gain_idx_14_lowword;
+	u32 lcnphy_gain_idx_14_hiword;
+	u32 lcnphy_gain_idx_27_lowword;
+	u32 lcnphy_gain_idx_27_hiword;
+	s16 lcnphy_ofdmgainidxtableoffset;
+	s16 lcnphy_dsssgainidxtableoffset;
+	u32 lcnphy_tr_R_gain_val;
+	u32 lcnphy_tr_T_gain_val;
+	s8 lcnphy_input_pwr_offset_db;
+	u16 lcnphy_Med_Low_Gain_db;
+	u16 lcnphy_Very_Low_Gain_db;
+	s8 lcnphy_lastsensed_temperature;
+	s8 lcnphy_pkteng_rssi_slope;
+	u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
+	u8 lcnphy_volt_winner;
+	u8 lcnphy_volt_low;
+	u8 lcnphy_54_48_36_24mbps_backoff;
+	u8 lcnphy_11n_backoff;
+	u8 lcnphy_lowerofdm;
+	u8 lcnphy_cck;
+	u8 lcnphy_psat_2pt3_detected;
+	s32 lcnphy_lowest_Re_div_Im;
+	s8 lcnphy_final_papd_cal_idx;
+	u16 lcnphy_extstxctrl4;
+	u16 lcnphy_extstxctrl0;
+	u16 lcnphy_extstxctrl1;
+	s16 lcnphy_cck_dig_filt_type;
+	s16 lcnphy_ofdm_dig_filt_type;
+	lcnphy_cal_results_t lcnphy_cal_results;
+
+	u8 lcnphy_psat_pwr;
+	u8 lcnphy_psat_indx;
+	s32 lcnphy_min_phase;
+	u8 lcnphy_final_idx;
+	u8 lcnphy_start_idx;
+	u8 lcnphy_current_index;
+	u16 lcnphy_logen_buf_1;
+	u16 lcnphy_local_ovr_2;
+	u16 lcnphy_local_oval_6;
+	u16 lcnphy_local_oval_5;
+	u16 lcnphy_logen_mixer_1;
+
+	u8 lcnphy_aci_stat;
+	uint lcnphy_aci_start_time;
+	s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
+};
+#endif				/* _wlc_phy_lcn_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
new file mode 100644
index 0000000..7947c60
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
@@ -0,0 +1,29234 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <bcmdefs.h>
+#include <wlc_cfg.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <siutils.h>
+#include <sbchipc.h>
+#include <hndpmu.h>
+
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+
+#include <wlc_phy_radio.h>
+#include <wlc_phy_int.h>
+#include <wlc_phyreg_n.h>
+#include <wlc_phytbl_n.h>
+
+#define	READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
+#define	WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
+#define	WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
+
+#define	READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
+	radio_type##_##jspace##1##_##reg_name));
+#define	WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
+	radio_type##_##jspace##1##_##reg_name), value);
+#define	READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
+	radio_type##_##reg_name##_##jspace##1));
+#define	WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
+	radio_type##_##reg_name##_##jspace##1), value);
+
+#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
+#define NPHY_ACI_CHANNEL_DELTA 5
+#define NPHY_ACI_CHANNEL_SKIP 4
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5
+#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4
+#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_NOASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH  400
+
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56
+
+#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16
+
+#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8
+
+#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5)
+
+#define NPHY_RSSICAL_MAXREAD 31
+
+#define NPHY_RSSICAL_NPOLL 8
+#define NPHY_RSSICAL_MAXD  (1<<20)
+#define NPHY_MIN_RXIQ_PWR 2
+
+#define NPHY_RSSICAL_W1_TARGET 25
+#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET
+#define NPHY_RSSICAL_NB_TARGET 0
+
+#define NPHY_RSSICAL_W1_TARGET_REV3 29
+#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3
+
+#define NPHY_CALSANITY_RSSI_NB_MAX_POS  9
+#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
+#define NPHY_CALSANITY_RSSI_W1_MAX_POS  12
+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W2_MAX_POS  NPHY_CALSANITY_RSSI_W1_MAX_POS
+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
+#define NPHY_RSSI_NB_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
+#define NPHY_RSSI_W1_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG))
+#define NPHY_RSSI_W2_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG))
+
+#define NPHY_IQCAL_NUMGAINS 9
+#define NPHY_N_GCTL 0x66
+
+#define NPHY_PAPD_EPS_TBL_SIZE 64
+#define NPHY_PAPD_SCL_TBL_SIZE 64
+#define NPHY_NUM_DIG_FILT_COEFFS 15
+
+#define NPHY_PAPD_COMP_OFF 0
+#define NPHY_PAPD_COMP_ON  1
+
+#define NPHY_SROM_TEMPSHIFT		32
+#define NPHY_SROM_MAXTEMPOFFSET		16
+#define NPHY_SROM_MINTEMPOFFSET		-16
+
+#define NPHY_CAL_MAXTEMPDELTA		64
+
+#define NPHY_NOISEVAR_TBLLEN40 256
+#define NPHY_NOISEVAR_TBLLEN20 128
+
+#define NPHY_ANARXLPFBW_REDUCTIONFACT 7
+
+#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
+
+typedef struct _nphy_iqcal_params {
+	u16 txlpf;
+	u16 txgm;
+	u16 pga;
+	u16 pad;
+	u16 ipa;
+	u16 cal_gain;
+	u16 ncorr[5];
+} nphy_iqcal_params_t;
+
+typedef struct _nphy_txiqcal_ladder {
+	u8 percent;
+	u8 g_env;
+} nphy_txiqcal_ladder_t;
+
+typedef struct {
+	nphy_txgains_t gains;
+	bool useindex;
+	u8 index;
+} nphy_ipa_txcalgains_t;
+
+typedef struct nphy_papd_restore_state_t {
+	u16 fbmix[2];
+	u16 vga_master[2];
+	u16 intpa_master[2];
+	u16 afectrl[2];
+	u16 afeoverride[2];
+	u16 pwrup[2];
+	u16 atten[2];
+	u16 mm;
+} nphy_papd_restore_state;
+
+typedef struct _nphy_ipa_txrxgain {
+	u16 hpvga;
+	u16 lpf_biq1;
+	u16 lpf_biq0;
+	u16 lna2;
+	u16 lna1;
+	s8 txpwrindex;
+} nphy_ipa_txrxgain_t;
+
+#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
+{0, 0, 0, 0, 0, 50},
+{0, 0, 0, 0, 0, -1},
+{0, 0, 0, 3, 0, -1},
+{0, 0, 3, 3, 0, -1},
+{0, 2, 3, 3, 0, -1}
+};
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
+{0, 0, 0, 0, 0, 70},
+{0, 0, 0, 0, 0, 20},
+{0, 0, 0, 3, 0, 20},
+{0, 0, 3, 3, 0, 20},
+{0, 2, 3, 3, 0, 20}
+};
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { {0, 0, 0, 0, 0, 100},
+{0, 0, 0, 0, 0, 50},
+{0, 0, 0, 0, 0, -1},
+{0, 0, 0, 3, 0, -1},
+{0, 0, 3, 3, 0, -1},
+{0, 0, 5, 3, 0, -1}
+};
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { {0, 0, 0, 0, 0, 10},
+{0, 0, 0, 1, 0, 10},
+{0, 0, 1, 2, 0, 10},
+{0, 0, 1, 3, 0, 10},
+{0, 0, 4, 3, 0, 10},
+{0, 0, 6, 3, 0, 10}
+};
+
+#define NPHY_RXCAL_TONEAMP 181
+#define NPHY_RXCAL_TONEFREQ_40MHz 4000
+#define NPHY_RXCAL_TONEFREQ_20MHz 2000
+
+enum {
+	NPHY_RXCAL_GAIN_INIT = 0,
+	NPHY_RXCAL_GAIN_UP,
+	NPHY_RXCAL_GAIN_DOWN
+};
+
+#define wlc_phy_get_papd_nphy(pi) \
+	(read_phy_reg((pi), 0x1e7) & \
+			((0x1 << 15) | \
+			(0x1 << 14) | \
+			(0x1 << 13)))
+
+#define TXFILT_SHAPING_OFDM20   0
+#define TXFILT_SHAPING_OFDM40   1
+#define TXFILT_SHAPING_CCK      2
+#define TXFILT_DEFAULT_OFDM20   3
+#define TXFILT_DEFAULT_OFDM40   4
+
+u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
+	{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
+	 230, -44, 230, 201, -191, 201},
+	{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
+	 26, 34, -32, 34},
+	{-360, 164, -376, 164, -1533, 576, 308, -314, 308,
+	 121, -73, 121, 91, 124, 91},
+	{-295, 200, -363, 142, -1391, 826, 151, 301, 151,
+	 151, 301, 151, 602, -752, 602},
+	{-92, 58, -96, 49, -104, 44, 17, 35, 17,
+	 12, 25, 12, 13, 27, 13},
+	{-375, 136, -399, 209, -1479, 949, 130, 260, 130,
+	 230, -44, 230, 201, -191, 201},
+	{0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97,
+	 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a}
+};
+
+typedef struct _chan_info_nphy_2055 {
+	u16 chan;
+	u16 freq;
+	uint unknown;
+	u8 RF_pll_ref;
+	u8 RF_rf_pll_mod1;
+	u8 RF_rf_pll_mod0;
+	u8 RF_vco_cap_tail;
+	u8 RF_vco_cal1;
+	u8 RF_vco_cal2;
+	u8 RF_pll_lf_c1;
+	u8 RF_pll_lf_r1;
+	u8 RF_pll_lf_c2;
+	u8 RF_lgbuf_cen_buf;
+	u8 RF_lgen_tune1;
+	u8 RF_lgen_tune2;
+	u8 RF_core1_lgbuf_a_tune;
+	u8 RF_core1_lgbuf_g_tune;
+	u8 RF_core1_rxrf_reg1;
+	u8 RF_core1_tx_pga_pad_tn;
+	u8 RF_core1_tx_mx_bgtrim;
+	u8 RF_core2_lgbuf_a_tune;
+	u8 RF_core2_lgbuf_g_tune;
+	u8 RF_core2_rxrf_reg1;
+	u8 RF_core2_tx_pga_pad_tn;
+	u8 RF_core2_tx_mx_bgtrim;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_2055_t;
+
+typedef struct _chan_info_nphy_radio205x {
+	u16 chan;
+	u16 freq;
+	u8 RF_SYN_pll_vcocal1;
+	u8 RF_SYN_pll_vcocal2;
+	u8 RF_SYN_pll_refdiv;
+	u8 RF_SYN_pll_mmd2;
+	u8 RF_SYN_pll_mmd1;
+	u8 RF_SYN_pll_loopfilter1;
+	u8 RF_SYN_pll_loopfilter2;
+	u8 RF_SYN_pll_loopfilter3;
+	u8 RF_SYN_pll_loopfilter4;
+	u8 RF_SYN_pll_loopfilter5;
+	u8 RF_SYN_reserved_addr27;
+	u8 RF_SYN_reserved_addr28;
+	u8 RF_SYN_reserved_addr29;
+	u8 RF_SYN_logen_VCOBUF1;
+	u8 RF_SYN_logen_MIXER2;
+	u8 RF_SYN_logen_BUF3;
+	u8 RF_SYN_logen_BUF4;
+	u8 RF_RX0_lnaa_tune;
+	u8 RF_RX0_lnag_tune;
+	u8 RF_TX0_intpaa_boost_tune;
+	u8 RF_TX0_intpag_boost_tune;
+	u8 RF_TX0_pada_boost_tune;
+	u8 RF_TX0_padg_boost_tune;
+	u8 RF_TX0_pgaa_boost_tune;
+	u8 RF_TX0_pgag_boost_tune;
+	u8 RF_TX0_mixa_boost_tune;
+	u8 RF_TX0_mixg_boost_tune;
+	u8 RF_RX1_lnaa_tune;
+	u8 RF_RX1_lnag_tune;
+	u8 RF_TX1_intpaa_boost_tune;
+	u8 RF_TX1_intpag_boost_tune;
+	u8 RF_TX1_pada_boost_tune;
+	u8 RF_TX1_padg_boost_tune;
+	u8 RF_TX1_pgaa_boost_tune;
+	u8 RF_TX1_pgag_boost_tune;
+	u8 RF_TX1_mixa_boost_tune;
+	u8 RF_TX1_mixg_boost_tune;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_radio205x_t;
+
+typedef struct _chan_info_nphy_radio2057 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_mx5g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_logen_indbuf5g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_pga_boost_tune_core0;
+	u8 RF_txmix5g_boost_tune_core0;
+	u8 RF_pad5g_tune_misc_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_lna5g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_pga_boost_tune_core1;
+	u8 RF_txmix5g_boost_tune_core1;
+	u8 RF_pad5g_tune_misc_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u8 RF_lna5g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_radio2057_t;
+
+typedef struct _chan_info_nphy_radio2057_rev5 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_radio2057_rev5_t;
+
+typedef struct nphy_sfo_cfg {
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} nphy_sfo_cfg_t;
+
+static chan_info_nphy_2055_t chan_info_nphy_2055[] = {
+	{
+	 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216},
+	{
+	 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215},
+	{
+	 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214},
+	{
+	 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213},
+	{
+	 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212},
+	{
+	 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211},
+	{
+	 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F},
+	{
+	 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E},
+	{
+	 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D},
+	{
+	 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C},
+	{
+	 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B},
+	{
+	 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A},
+	{
+	 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209},
+	{
+	 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208},
+	{
+	 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207},
+	{
+	 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206},
+	{
+	 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205},
+	{
+	 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204},
+	{
+	 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203},
+	{
+	 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202},
+	{
+	 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201},
+	{
+	 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200},
+	{
+	 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C,
+	 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF},
+	{
+	 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD},
+	{
+	 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC},
+	{
+	 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB},
+	{
+	 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA},
+	{
+	 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9},
+	{
+	 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8},
+	{
+	 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7},
+	{
+	 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6},
+	{
+	 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5},
+	{
+	 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4},
+	{
+	 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3},
+	{
+	 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2},
+	{
+	 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1},
+	{
+	 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0},
+	{
+	 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0},
+	{
+	 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF},
+	{
+	 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE},
+	{
+	 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED},
+	{
+	 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC},
+	{
+	 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB},
+	{
+	 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA},
+	{
+	 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9},
+	{
+	 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8},
+	{
+	 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7},
+	{
+	 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6},
+	{
+	 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5},
+	{
+	 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5},
+	{
+	 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4},
+	{
+	 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3},
+	{
+	 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2},
+	{
+	 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1},
+	{
+	 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0},
+	{
+	 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF},
+	{
+	 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE},
+	{
+	 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD},
+	{
+	 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD},
+	{
+	 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC},
+	{
+	 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB},
+	{
+	 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA},
+	{
+	 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9},
+	{
+	 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8},
+	{
+	 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7},
+	{
+	 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7},
+	{
+	 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6},
+	{
+	 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5},
+	{
+	 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4},
+	{
+	 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3},
+	{
+	 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2},
+	{
+	 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2},
+	{
+	 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1},
+	{
+	 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0},
+	{
+	 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF},
+	{
+	 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE},
+	{
+	 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE},
+	{
+	 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD},
+	{
+	 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC},
+	{
+	 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA},
+	{
+	 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA},
+	{
+	 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9},
+	{
+	 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9},
+	{
+	 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9},
+	{
+	 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8},
+	{
+	 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7},
+	{
+	 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7},
+	{
+	 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6},
+	{
+	 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5},
+	{
+	 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5},
+	{
+	 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4},
+	{
+	 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3},
+	{
+	 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3},
+	{
+	 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2},
+	{
+	 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2},
+	{
+	 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1},
+	{
+	 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0},
+	{
+	 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF},
+	{
+	 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF},
+	{
+	 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE},
+	{
+	 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD},
+	{
+	 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC},
+	{
+	 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D,
+	 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443},
+	{
+	 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441},
+	{
+	 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F},
+	{
+	 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D},
+	{
+	 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C,
+	 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A},
+	{
+	 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B,
+	 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438},
+	{
+	 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A,
+	 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436},
+	{
+	 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A,
+	 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434},
+	{
+	 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09,
+	 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431},
+	{
+	 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08,
+	 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F},
+	{
+	 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08,
+	 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D},
+	{
+	 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08,
+	 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B},
+	{
+	 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07,
+	 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429},
+	{
+	 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07,
+	 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev3_2056[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev4_2056_A1[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev5_2056v5[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v6[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev5n6_2056v7[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v8[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v11[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio2057_t chan_info_nphyrev7_2057_rev4[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216,
+	 },
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215,
+	 },
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214,
+	 },
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213,
+	 },
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212,
+	 },
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211,
+	 },
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f,
+	 },
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e,
+	 },
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d,
+	 },
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c,
+	 },
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b,
+	 },
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a,
+	 },
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209,
+	 },
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208,
+	 },
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207,
+	 },
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206,
+	 },
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205,
+	 },
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204,
+	 },
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203,
+	 },
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202,
+	 },
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201,
+	 },
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200,
+	 },
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff,
+	 },
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd,
+	 },
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc,
+	 },
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb,
+	 },
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa,
+	 },
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9,
+	 },
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8,
+	 },
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7,
+	 },
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6,
+	 },
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5,
+	 },
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4,
+	 },
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3,
+	 },
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2,
+	 },
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1,
+	 },
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0,
+	 },
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0,
+	 },
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef,
+	 },
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee,
+	 },
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed,
+	 },
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec,
+	 },
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb,
+	 },
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea,
+	 },
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9,
+	 },
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8,
+	 },
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7,
+	 },
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6,
+	 },
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5,
+	 },
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5,
+	 },
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4,
+	 },
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3,
+	 },
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2,
+	 },
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1,
+	 },
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0,
+	 },
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df,
+	 },
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de,
+	 },
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd,
+	 },
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd,
+	 },
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc,
+	 },
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db,
+	 },
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da,
+	 },
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9,
+	 },
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8,
+	 },
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7,
+	 },
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7,
+	 },
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6,
+	 },
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5,
+	 },
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4,
+	 },
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3,
+	 },
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2,
+	 },
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2,
+	 },
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1,
+	 },
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0,
+	 },
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf,
+	 },
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce,
+	 },
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce,
+	 },
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd,
+	 },
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc,
+	 },
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9,
+	 },
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8,
+	 },
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6,
+	 },
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4,
+	 },
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2,
+	 },
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2,
+	 },
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1,
+	 },
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0,
+	 },
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf,
+	 },
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf,
+	 },
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be,
+	 },
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd,
+	 },
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443,
+	 },
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441,
+	 },
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f,
+	 },
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d,
+	 },
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a,
+	 },
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438,
+	 },
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436,
+	 },
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434,
+	 },
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431,
+	 },
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f,
+	 },
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d,
+	 },
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b,
+	 },
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429,
+	 },
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11,
+	 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev8_2057_rev5[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev9_2057_rev5v1[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev7[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216},
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev8[] = {
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+radio_regs_t regs_2055[] = {
+	{0x02, 0x80, 0x80, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0x27, 0x27, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x27, 0x27, 0, 0},
+	{0x07, 0x7f, 0x7f, 1, 1},
+	{0x08, 0x7, 0x7, 1, 1},
+	{0x09, 0x7f, 0x7f, 1, 1},
+	{0x0A, 0x7, 0x7, 1, 1},
+	{0x0B, 0x15, 0x15, 0, 0},
+	{0x0C, 0x15, 0x15, 0, 0},
+	{0x0D, 0x4f, 0x4f, 1, 1},
+	{0x0E, 0x5, 0x5, 1, 1},
+	{0x0F, 0x4f, 0x4f, 1, 1},
+	{0x10, 0x5, 0x5, 1, 1},
+	{0x11, 0xd0, 0xd0, 0, 0},
+	{0x12, 0x2, 0x2, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0x40, 0x40, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0xc0, 0xc0, 0, 0},
+	{0x1E, 0xff, 0xff, 0, 0},
+	{0x1F, 0xc0, 0xc0, 0, 0},
+	{0x20, 0xff, 0xff, 0, 0},
+	{0x21, 0xc0, 0xc0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x2c, 0x2c, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0xa4, 0xa4, 0, 0},
+	{0x2E, 0x38, 0x38, 0, 0},
+	{0x2F, 0, 0, 0, 0},
+	{0x30, 0x4, 0x4, 1, 1},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0xa, 0xa, 0, 0},
+	{0x33, 0x87, 0x87, 0, 0},
+	{0x34, 0x9, 0x9, 0, 0},
+	{0x35, 0x70, 0x70, 0, 0},
+	{0x36, 0x11, 0x11, 0, 0},
+	{0x37, 0x18, 0x18, 1, 1},
+	{0x38, 0x6, 0x6, 0, 0},
+	{0x39, 0x4, 0x4, 1, 1},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0x9e, 0x9e, 0, 0},
+	{0x3C, 0x9, 0x9, 0, 0},
+	{0x3D, 0xc8, 0xc8, 1, 1},
+	{0x3E, 0x88, 0x88, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0, 0, 0, 0},
+	{0x42, 0x1, 0x1, 0, 0},
+	{0x43, 0x2, 0x2, 0, 0},
+	{0x44, 0x96, 0x96, 0, 0},
+	{0x45, 0x3e, 0x3e, 0, 0},
+	{0x46, 0x3e, 0x3e, 0, 0},
+	{0x47, 0x13, 0x13, 0, 0},
+	{0x48, 0x2, 0x2, 0, 0},
+	{0x49, 0x15, 0x15, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0, 0, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0, 0, 0, 0},
+	{0x50, 0x8, 0x8, 0, 0},
+	{0x51, 0x8, 0x8, 0, 0},
+	{0x52, 0x6, 0x6, 0, 0},
+	{0x53, 0x84, 0x84, 1, 1},
+	{0x54, 0xc3, 0xc3, 0, 0},
+	{0x55, 0x8f, 0x8f, 0, 0},
+	{0x56, 0xff, 0xff, 0, 0},
+	{0x57, 0xff, 0xff, 0, 0},
+	{0x58, 0x88, 0x88, 0, 0},
+	{0x59, 0x88, 0x88, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0xcc, 0xcc, 0, 0},
+	{0x5C, 0x6, 0x6, 0, 0},
+	{0x5D, 0x80, 0x80, 0, 0},
+	{0x5E, 0x80, 0x80, 0, 0},
+	{0x5F, 0xf8, 0xf8, 0, 0},
+	{0x60, 0x88, 0x88, 0, 0},
+	{0x61, 0x88, 0x88, 0, 0},
+	{0x62, 0x88, 0x8, 1, 1},
+	{0x63, 0x88, 0x88, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0x1, 0x1, 1, 1},
+	{0x66, 0x8a, 0x8a, 0, 0},
+	{0x67, 0x8, 0x8, 0, 0},
+	{0x68, 0x83, 0x83, 0, 0},
+	{0x69, 0x6, 0x6, 0, 0},
+	{0x6A, 0xa0, 0xa0, 0, 0},
+	{0x6B, 0xa, 0xa, 0, 0},
+	{0x6C, 0x87, 0x87, 1, 1},
+	{0x6D, 0x2a, 0x2a, 0, 0},
+	{0x6E, 0x2a, 0x2a, 0, 0},
+	{0x6F, 0x2a, 0x2a, 0, 0},
+	{0x70, 0x2a, 0x2a, 0, 0},
+	{0x71, 0x18, 0x18, 0, 0},
+	{0x72, 0x6a, 0x6a, 1, 1},
+	{0x73, 0xab, 0xab, 1, 1},
+	{0x74, 0x13, 0x13, 1, 1},
+	{0x75, 0xc1, 0xc1, 1, 1},
+	{0x76, 0xaa, 0xaa, 1, 1},
+	{0x77, 0x87, 0x87, 1, 1},
+	{0x78, 0, 0, 0, 0},
+	{0x79, 0x6, 0x6, 0, 0},
+	{0x7A, 0x7, 0x7, 0, 0},
+	{0x7B, 0x7, 0x7, 0, 0},
+	{0x7C, 0x15, 0x15, 0, 0},
+	{0x7D, 0x55, 0x55, 0, 0},
+	{0x7E, 0x97, 0x97, 1, 1},
+	{0x7F, 0x8, 0x8, 0, 0},
+	{0x80, 0x14, 0x14, 1, 1},
+	{0x81, 0x33, 0x33, 0, 0},
+	{0x82, 0x88, 0x88, 0, 0},
+	{0x83, 0x6, 0x6, 0, 0},
+	{0x84, 0x3, 0x3, 1, 1},
+	{0x85, 0xa, 0xa, 0, 0},
+	{0x86, 0x3, 0x3, 1, 1},
+	{0x87, 0x2a, 0x2a, 0, 0},
+	{0x88, 0xa4, 0xa4, 0, 0},
+	{0x89, 0x18, 0x18, 0, 0},
+	{0x8A, 0x28, 0x28, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0x4a, 0x4a, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0xf8, 0xf8, 0, 0},
+	{0x8F, 0x88, 0x88, 0, 0},
+	{0x90, 0x88, 0x88, 0, 0},
+	{0x91, 0x88, 0x8, 1, 1},
+	{0x92, 0x88, 0x88, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0x1, 0x1, 1, 1},
+	{0x95, 0x8a, 0x8a, 0, 0},
+	{0x96, 0x8, 0x8, 0, 0},
+	{0x97, 0x83, 0x83, 0, 0},
+	{0x98, 0x6, 0x6, 0, 0},
+	{0x99, 0xa0, 0xa0, 0, 0},
+	{0x9A, 0xa, 0xa, 0, 0},
+	{0x9B, 0x87, 0x87, 1, 1},
+	{0x9C, 0x2a, 0x2a, 0, 0},
+	{0x9D, 0x2a, 0x2a, 0, 0},
+	{0x9E, 0x2a, 0x2a, 0, 0},
+	{0x9F, 0x2a, 0x2a, 0, 0},
+	{0xA0, 0x18, 0x18, 0, 0},
+	{0xA1, 0x6a, 0x6a, 1, 1},
+	{0xA2, 0xab, 0xab, 1, 1},
+	{0xA3, 0x13, 0x13, 1, 1},
+	{0xA4, 0xc1, 0xc1, 1, 1},
+	{0xA5, 0xaa, 0xaa, 1, 1},
+	{0xA6, 0x87, 0x87, 1, 1},
+	{0xA7, 0, 0, 0, 0},
+	{0xA8, 0x6, 0x6, 0, 0},
+	{0xA9, 0x7, 0x7, 0, 0},
+	{0xAA, 0x7, 0x7, 0, 0},
+	{0xAB, 0x15, 0x15, 0, 0},
+	{0xAC, 0x55, 0x55, 0, 0},
+	{0xAD, 0x97, 0x97, 1, 1},
+	{0xAE, 0x8, 0x8, 0, 0},
+	{0xAF, 0x14, 0x14, 1, 1},
+	{0xB0, 0x33, 0x33, 0, 0},
+	{0xB1, 0x88, 0x88, 0, 0},
+	{0xB2, 0x6, 0x6, 0, 0},
+	{0xB3, 0x3, 0x3, 1, 1},
+	{0xB4, 0xa, 0xa, 0, 0},
+	{0xB5, 0x3, 0x3, 1, 1},
+	{0xB6, 0x2a, 0x2a, 0, 0},
+	{0xB7, 0xa4, 0xa4, 0, 0},
+	{0xB8, 0x18, 0x18, 0, 0},
+	{0xB9, 0x28, 0x28, 0, 0},
+	{0xBA, 0, 0, 0, 0},
+	{0xBB, 0x4a, 0x4a, 0, 0},
+	{0xBC, 0, 0, 0, 0},
+	{0xBD, 0x71, 0x71, 0, 0},
+	{0xBE, 0x72, 0x72, 0, 0},
+	{0xBF, 0x73, 0x73, 0, 0},
+	{0xC0, 0x74, 0x74, 0, 0},
+	{0xC1, 0x75, 0x75, 0, 0},
+	{0xC2, 0x76, 0x76, 0, 0},
+	{0xC3, 0x77, 0x77, 0, 0},
+	{0xC4, 0x78, 0x78, 0, 0},
+	{0xC5, 0x79, 0x79, 0, 0},
+	{0xC6, 0x7a, 0x7a, 0, 0},
+	{0xC7, 0, 0, 0, 0},
+	{0xC8, 0, 0, 0, 0},
+	{0xC9, 0, 0, 0, 0},
+	{0xCA, 0, 0, 0, 0},
+	{0xCB, 0, 0, 0, 0},
+	{0xCC, 0, 0, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0x6, 0x6, 0, 0},
+	{0xCF, 0, 0, 0, 0},
+	{0xD0, 0, 0, 0, 0},
+	{0xD1, 0x18, 0x18, 0, 0},
+	{0xD2, 0x88, 0x88, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0, 0, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0, 0, 0, 0},
+	{0xD9, 0, 0, 0, 0},
+	{0xDA, 0x6, 0x6, 0, 0},
+	{0xDB, 0, 0, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x18, 0x18, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0, 0, 0, 0},
+	{0xE0, 0, 0, 0, 0},
+	{0xE1, 0, 0, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_SYN_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x74, 0x74, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x99, 0x99, 0, 0},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x99, 0x99, 0, 0},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x66, 0x66, 0, 0},
+	{0x50, 0x66, 0x66, 0, 0},
+	{0x51, 0x57, 0x57, 0, 0},
+	{0x52, 0x57, 0x57, 0, 0},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x23, 0x23, 0, 0},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0x2, 0x2, 0, 0},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x72, 0x72, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x2f, 0x2f, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_TX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_RX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_SYN_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_TX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_RX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_SYN_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x6, 0x6, 1, 1},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x3f, 0x3f, 1, 1},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0x6, 0x6, 1, 1},
+	{0x4C, 0x6, 0x6, 1, 1},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x2b, 0x2b, 1, 1},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_TX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_RX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_20xx_regs_t regs_2057_rev4[] = {
+	{0x00, 0x84, 0},
+	{0x01, 0, 0},
+	{0x02, 0x60, 0},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 1},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0xf7, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x4, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x26, 1},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 1},
+	{0x3D, 0xff, 1},
+	{0x3E, 0xff, 1},
+	{0x3F, 0xff, 1},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x75, 0},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0xa8, 0},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x30, 0},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0x19, 0},
+	{0x64, 0x62, 0},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0xc8, 0},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x1e, 0},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x1e, 0},
+	{0x7C, 0x62, 0},
+	{0x7D, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x9c, 0},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 1},
+	{0x8B, 0x10, 1},
+	{0x8C, 0xf0, 1},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0xe1, 0},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 1},
+	{0xA5, 0x6d, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 1},
+	{0xA9, 0xc, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 1},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x75, 0},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0xa8, 0},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x30, 0},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0x19, 0},
+	{0xE9, 0x62, 0},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0xc8, 0},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x1e, 0},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x1e, 0},
+	{0x101, 0x62, 0},
+	{0x102, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x9c, 0},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 1},
+	{0x110, 0x10, 1},
+	{0x111, 0xf0, 1},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0xe1, 0},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 1},
+	{0x12A, 0x6d, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 1},
+	{0x12E, 0xc, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 1},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x152, 0, 0},
+	{0x153, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0x2, 1},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0xFFFF, 0, 0},
+};
+
+radio_20xx_regs_t regs_2057_rev5[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+radio_20xx_regs_t regs_2057_rev5v1[] = {
+	{0x00, 0x15, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+radio_20xx_regs_t regs_2057_rev7[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0x13, 1},
+	{0x65, 0, 0},
+	{0x66, 0xee, 1},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0x14, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0x13, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0xee, 1},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0x14, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+radio_20xx_regs_t regs_2057_rev8[] = {
+	{0x00, 0x8, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0xf, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0xf, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 };
+
+static s32 nphy_lnagain_est0[] = { -315, 40370 };
+static s32 nphy_lnagain_est1[] = { -224, 23242 };
+
+static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
+	{
+	 {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
+	 {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
+	 {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
+	 {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
+	 {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
+	 {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
+	 {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
+	 {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
+	 {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
+	 },
+	{
+	 {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
+	 {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
+	 {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
+	 }
+};
+
+static const u32 nphy_tpc_txgain[] = {
+	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
+	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
+	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
+	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
+	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
+	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
+	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
+	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
+	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
+	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
+	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
+	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
+	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
+	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
+	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
+	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
+	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
+	0x03902942, 0x03902844, 0x03902842, 0x03902744,
+	0x03902742, 0x03902644, 0x03902642, 0x03902544,
+	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
+	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
+	0x03802842, 0x03802744, 0x03802742, 0x03802644,
+	0x03802642, 0x03802544, 0x03802542, 0x03802444,
+	0x03802442, 0x03802344, 0x03802342, 0x03802244,
+	0x03802242, 0x03802144, 0x03802142, 0x03802044,
+	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
+	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
+	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
+	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
+	0x03801842, 0x03801744, 0x03801742, 0x03801644,
+	0x03801642, 0x03801544, 0x03801542, 0x03801444,
+	0x03801442, 0x03801344, 0x03801342, 0x00002b00
+};
+
+static const u16 nphy_tpc_loscale[] = {
+	256, 256, 271, 271, 287, 256, 256, 271,
+	271, 287, 287, 304, 304, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 406, 406, 430,
+	430, 455, 455, 482, 482, 511, 511, 541,
+	541, 573, 573, 607, 607, 643, 643, 681,
+	681, 722, 722, 764, 764, 810, 810, 858,
+	858, 908, 908, 962, 962, 1019, 1019, 256
+};
+
+static u32 nphy_tpc_txgain_ipa[] = {
+	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
+	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
+	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
+	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
+	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
+	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
+	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
+	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
+	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
+	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
+	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
+	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
+	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
+	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
+	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
+	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
+	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
+	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
+	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
+	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
+	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
+	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
+	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
+	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
+	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
+	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
+	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
+	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
+	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
+	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
+	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
+	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev5[] = {
+	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
+	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
+	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
+	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
+	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
+	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
+	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
+	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
+	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
+	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
+	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
+	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
+	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
+	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
+	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
+	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
+	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
+	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
+	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
+	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
+	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
+	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
+	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
+	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
+	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
+	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
+	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
+	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
+	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
+	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
+	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
+	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev6[] = {
+	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
+	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
+	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
+	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
+	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
+	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
+	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
+	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
+	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
+	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
+	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
+	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
+	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
+	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
+	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
+	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
+	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
+	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
+	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
+	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
+	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
+	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
+	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
+	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
+	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
+	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
+	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
+	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
+	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
+	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
+	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
+	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = {
+	0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039,
+	0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032,
+	0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d,
+	0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c,
+	0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d,
+	0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a,
+	0x70570028, 0x704f002a, 0x7047002c, 0x7047002a,
+	0x70470028, 0x70470026, 0x70470024, 0x70470022,
+	0x7047001f, 0x70370027, 0x70370024, 0x70370022,
+	0x70370020, 0x7037001f, 0x7037001d, 0x7037001b,
+	0x7037001a, 0x70370018, 0x70370017, 0x7027001e,
+	0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022,
+	0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b,
+	0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015,
+	0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011,
+	0x70170019, 0x70170018, 0x70170016, 0x70170015,
+	0x70170014, 0x70170013, 0x70170012, 0x70170010,
+	0x70170010, 0x7017000f, 0x700f001d, 0x700f001b,
+	0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015,
+	0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011,
+	0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e,
+	0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b,
+	0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009,
+	0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007,
+	0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006,
+	0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004,
+	0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004,
+	0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003,
+	0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002,
+	0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = {
+	0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039,
+	0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032,
+	0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d,
+	0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c,
+	0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d,
+	0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a,
+	0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a,
+	0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022,
+	0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022,
+	0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b,
+	0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e,
+	0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022,
+	0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b,
+	0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015,
+	0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011,
+	0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015,
+	0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010,
+	0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b,
+	0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015,
+	0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011,
+	0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e,
+	0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b,
+	0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009,
+	0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007,
+	0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006,
+	0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004,
+	0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004,
+	0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003,
+	0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002,
+	0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_5g[] = {
+	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
+	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
+	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
+	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
+	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
+	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
+	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
+	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
+	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
+	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
+	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
+	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
+	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
+	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
+	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
+	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
+	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
+	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
+	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
+	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
+	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
+	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
+	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
+	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
+	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
+	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
+	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
+	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
+	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
+	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
+	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
+	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057[] = {
+	0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039,
+	0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035,
+	0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033,
+	0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a,
+	0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039,
+	0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038,
+	0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038,
+	0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037,
+	0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036,
+	0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037,
+	0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036,
+	0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035,
+	0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033,
+	0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034,
+	0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032,
+	0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028,
+	0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020,
+	0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019,
+	0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014,
+	0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010,
+	0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d,
+	0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a,
+	0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008,
+	0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006,
+	0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005,
+	0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004,
+	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = {
+	0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a,
+	0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a,
+	0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028,
+	0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e,
+	0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e,
+	0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e,
+	0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d,
+	0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d,
+	0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c,
+	0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b,
+	0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b,
+	0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a,
+	0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029,
+	0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029,
+	0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027,
+	0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020,
+	0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019,
+	0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014,
+	0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f,
+	0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c,
+	0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a,
+	0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008,
+	0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006,
+	0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005,
+	0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004,
+	0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003,
+	0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001,
+	0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_2g[] = {
+	-114, -108, -98, -91, -84, -78, -70, -62,
+	-54, -46, -39, -31, -23, -15, -8, 0
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_5g[] = {
+	-100, -95, -89, -83, -77, -70, -63, -56,
+	-48, -41, -33, -25, -19, -12, -6, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = {
+	-159, -113, -86, -72, -62, -54, -48, -43,
+	-39, -35, -31, -28, -25, -23, -20, -18,
+	-17, -15, -13, -11, -10, -8, -7, -6,
+	-5, -4, -3, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = {
+	-109, -109, -82, -68, -58, -50, -44, -39,
+	-35, -31, -28, -26, -23, -21, -19, -17,
+	-16, -14, -13, -11, -10, -9, -8, -7,
+	-5, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = {
+	-122, -122, -95, -80, -69, -61, -54, -49,
+	-43, -39, -35, -32, -28, -26, -23, -21,
+	-18, -16, -15, -13, -11, -10, -8, -7,
+	-6, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057[] = {
+	-107, -101, -92, -85, -78, -71, -62, -55,
+	-47, -39, -32, -24, -19, -12, -6, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = {
+	-110, -104, -95, -88, -81, -74, -66, -58,
+	-50, -44, -36, -28, -23, -15, -8, 0
+};
+
+static u8 pad_gain_codes_used_2057rev5[] = {
+	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
+	10, 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+
+static u8 pad_gain_codes_used_2057rev7[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+	5, 4, 3, 2, 1
+};
+
+static u8 pad_all_gain_codes_2057[] = {
+	31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
+	21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
+	11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
+	1, 0
+};
+
+static u8 pga_all_gain_codes_2057[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static u32 nphy_papd_scaltbl[] = {
+	0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038,
+	0x0887003c, 0x081f003f, 0x07a20043, 0x07340047,
+	0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059,
+	0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070,
+	0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d,
+	0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2,
+	0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0,
+	0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a,
+	0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162,
+	0x015d0177, 0x0149018e, 0x013701a5, 0x012601be,
+	0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232,
+	0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3,
+	0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a,
+	0x008b03af, 0x008303e7, 0x007c0422, 0x00750461,
+	0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583,
+	0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1
+};
+
+static u32 nphy_tpc_txgain_rev3[] = {
+	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
+	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
+	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
+	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
+	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
+	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
+	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
+	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
+	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
+	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
+	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
+	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
+	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
+	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
+	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
+	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
+	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
+	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
+	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
+	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
+	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
+	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
+	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
+	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
+	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
+	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
+	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
+	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
+	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
+	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
+	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
+	0x1041003c, 0x1041003b, 0x10410039, 0x10410037
+};
+
+static u32 nphy_tpc_txgain_HiPwrEPA[] = {
+	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev3[] = {
+	0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d,
+	0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b,
+	0x8091003b, 0x8089003a, 0x8081003a, 0x80790039,
+	0x80710039, 0x8069003a, 0x8061003b, 0x8059003d,
+	0x8051003f, 0x80490042, 0x8049003e, 0x8049003b,
+	0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b,
+	0x80390038, 0x80390035, 0x8031003a, 0x80310036,
+	0x80310033, 0x8029003a, 0x80290037, 0x80290034,
+	0x80290031, 0x80210039, 0x80210036, 0x80210033,
+	0x80210030, 0x8019003c, 0x80190039, 0x80190036,
+	0x80190033, 0x80190030, 0x8019002d, 0x8019002b,
+	0x80190028, 0x8011003a, 0x80110036, 0x80110033,
+	0x80110030, 0x8011002e, 0x8011002b, 0x80110029,
+	0x80110027, 0x80110024, 0x80110022, 0x80110020,
+	0x8011001f, 0x8011001d, 0x8009003a, 0x80090037,
+	0x80090034, 0x80090031, 0x8009002e, 0x8009002c,
+	0x80090029, 0x80090027, 0x80090025, 0x80090023,
+	0x80090021, 0x8009001f, 0x8009001d, 0x8009011d,
+	0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d,
+	0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev5[] = {
+	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
+	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
+	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
+	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
+	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
+	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
+	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
+	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
+	0x10290031, 0x10210039, 0x10210036, 0x10210033,
+	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
+	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
+	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
+	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
+	0x10110027, 0x10110024, 0x10110022, 0x10110020,
+	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
+	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
+	0x10090029, 0x10090027, 0x10090025, 0x10090023,
+	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
+	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
+	0x10090015, 0x10090013, 0x10090012, 0x10090011,
+	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
+	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
+	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
+	0x10090008, 0x10090008, 0x10090007, 0x10090007,
+	0x10090007, 0x10090006, 0x10090006, 0x10090005,
+	0x10090005, 0x10090005, 0x10090005, 0x10090004,
+	0x10090004, 0x10090004, 0x10090004, 0x10090003,
+	0x10090003, 0x10090003, 0x10090003, 0x10090003,
+	0x10090003, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090001, 0x10090001,
+	0x10090001, 0x10090001, 0x10090001, 0x10090001
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev3[] = {
+	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
+	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
+	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
+	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
+	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
+	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
+	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
+	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
+	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
+	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
+	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
+	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
+	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
+	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
+	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
+	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
+	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
+	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
+	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
+	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
+	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
+	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
+	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
+	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
+	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
+	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
+	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
+	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
+	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
+	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
+	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
+	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev4[] = {
+	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
+	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
+	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
+	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
+	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
+	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
+	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
+	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
+	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
+	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
+	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
+	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
+	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
+	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
+	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
+	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
+	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
+	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
+	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
+	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
+	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
+	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
+	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
+	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
+	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
+	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
+	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
+	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
+	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
+	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
+	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
+	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev5[] = {
+	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
+	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
+	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
+	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
+	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
+	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
+	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
+	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
+	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
+	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
+	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
+	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
+	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
+	0x09620039, 0x09620037, 0x09620035, 0x09620033,
+	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
+	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
+	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
+	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
+	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
+	0x06620039, 0x06620037, 0x06620035, 0x06620033,
+	0x05620046, 0x05620044, 0x05620042, 0x05620040,
+	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
+	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
+	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
+	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
+	0x03620038, 0x03620037, 0x03620035, 0x03620033,
+	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
+	0x02620046, 0x02620044, 0x02620043, 0x02620042,
+	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
+	0x01620043, 0x01620042, 0x01620041, 0x01620040,
+	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
+	0x0062003b, 0x00620039, 0x00620037, 0x00620035
+};
+
+static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
+	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
+static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
+	0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
+	0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
+
+static bool wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
+				   chan_info_nphy_radio2057_t **t0,
+				   chan_info_nphy_radio205x_t **t1,
+				   chan_info_nphy_radio2057_rev5_t **t2,
+				   chan_info_nphy_2055_t **t3);
+static void wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chans,
+					const nphy_sfo_cfg_t *c);
+
+static void wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi,
+					    u16 reduction_factr);
+static void wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *,
+					     u32 *buf);
+static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr);
+static void wlc_phy_txlpfbw_nphy(phy_info_t *pi);
+static void wlc_phy_spurwar_nphy(phy_info_t *pi);
+
+static void wlc_phy_radio_preinit_2055(phy_info_t *pi);
+static void wlc_phy_radio_init_2055(phy_info_t *pi);
+static void wlc_phy_radio_postinit_2055(phy_info_t *pi);
+static void wlc_phy_radio_preinit_205x(phy_info_t *pi);
+static void wlc_phy_radio_init_2056(phy_info_t *pi);
+static void wlc_phy_radio_postinit_2056(phy_info_t *pi);
+static void wlc_phy_radio_init_2057(phy_info_t *pi);
+static void wlc_phy_radio_postinit_2057(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi);
+static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi);
+
+static void wlc_phy_restore_rssical_nphy(phy_info_t *pi);
+static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi);
+static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi);
+static int wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t tg,
+				      u8 type, bool d);
+static void wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rxcore,
+					     u16 *rg, u8 type);
+static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble);
+static void wlc_phy_savecal_nphy(phy_info_t *pi);
+static void wlc_phy_restorecal_nphy(phy_info_t *pi);
+static void wlc_phy_resetcca_nphy(phy_info_t *pi);
+
+static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi);
+static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi);
+static void wlc_phy_precal_txgain_nphy(phy_info_t *pi);
+static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core);
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi);
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi);
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi);
+static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi);
+static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1);
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi);
+
+static void wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32,
+			    u32 e);
+static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core);
+static void wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *,
+			    phy_cal_mode_t, u8);
+static void wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi,
+					  nphy_papd_restore_state *state);
+static void wlc_phy_papd_cal_setup_nphy(phy_info_t *pi,
+					nphy_papd_restore_state *state, u8);
+
+static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals);
+
+static void wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *evts,
+				   u8 *dlys, u8 len);
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset);
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off,
+				  u8 override_id);
+
+static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type);
+static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi);
+
+static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi);
+static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
+					    u16 *pwr_offset,
+					    u8 tmp_max_pwr, u8 rate_start,
+					    u8 rate_end);
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi);
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi);
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi);
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi);
+
+static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi);
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core);
+static void wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0,
+					   u8 idx1);
+static void wlc_phy_a4(phy_info_t *pi, bool full_cal);
+
+static u16 wlc_phy_radio205x_rcal(phy_info_t *pi);
+
+static u16 wlc_phy_radio2057_rccal(phy_info_t *pi);
+
+static u16 wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz,
+					    u16 max_val,
+					    u8 dac_test_mode);
+static void wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
+					 u16 num_samps);
+static void wlc_phy_runsamples_nphy(phy_info_t *pi, u16 n, u16 lps,
+				    u16 wait, u8 iq, u8 dac_test_mode,
+				    bool modify_bbmult);
+
+bool wlc_phy_bist_check_phy(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	u32 phybist0, phybist1, phybist2, phybist3, phybist4;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16))
+		return true;
+
+	phybist0 = read_phy_reg(pi, 0x0e);
+	phybist1 = read_phy_reg(pi, 0x0f);
+	phybist2 = read_phy_reg(pi, 0xea);
+	phybist3 = read_phy_reg(pi, 0xeb);
+	phybist4 = read_phy_reg(pi, 0x156);
+
+	if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
+	    (phybist3 == 0) && (phybist4 == 0)) {
+		return true;
+	}
+
+	return false;
+}
+
+static void WLBANDINITFN(wlc_phy_bphy_init_nphy) (phy_info_t *pi)
+{
+	u16 addr, val;
+
+	ASSERT(ISNPHY(pi));
+
+	val = 0x1e1f;
+	for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT);
+	     addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) {
+		write_phy_reg(pi, addr, val);
+		if (addr == (NPHY_TO_BPHY_OFF + 0x97))
+			val = 0x3e3f;
+		else
+			val -= 0x0202;
+	}
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
+
+	} else {
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
+	}
+}
+
+void
+wlc_phy_table_write_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
+			 u32 width, const void *data)
+{
+	mimophytbl_info_t tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_write_table_nphy(pi, &tbl);
+}
+
+void
+wlc_phy_table_read_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
+			u32 width, void *data)
+{
+	mimophytbl_info_t tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_read_table_nphy(pi, &tbl);
+}
+
+static void WLBANDINITFN(wlc_phy_static_table_download_nphy) (phy_info_t *pi)
+{
+	uint idx;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev16[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev7[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev3[idx]);
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0[idx]);
+	}
+}
+
+static void WLBANDINITFN(wlc_phy_tbl_init_nphy) (phy_info_t *pi)
+{
+	uint idx = 0;
+	u8 antswctrllut;
+
+	if (pi->phy_init_por)
+		wlc_phy_static_table_download_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+		    pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
+
+		switch (antswctrllut) {
+		case 0:
+
+			break;
+
+		case 1:
+
+			if (pi->aa2g == 7) {
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_ANTSWCTRLLUT,
+							 2, 0x21, 8,
+							 &ant_sw_ctrl_tbl_rev8_2o3
+							 [0]);
+			} else {
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_ANTSWCTRLLUT,
+							 2, 0x21, 8,
+							 &ant_sw_ctrl_tbl_rev8
+							 [0]);
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8[2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8[4]);
+			break;
+
+		case 2:
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x1, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [0]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x5, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x9, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [4]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x21, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [0]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [4]);
+			break;
+
+		default:
+
+			ASSERT(0);
+			break;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
+
+			if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
+				antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+				    pi->srom_fem2g.antswctrllut : pi->
+				    srom_fem5g.antswctrllut;
+				switch (antswctrllut) {
+				case 0:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile
+								 [idx]);
+					break;
+				case 1:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile1
+								 [idx]);
+					break;
+				case 2:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile2
+								 [idx]);
+					break;
+				case 3:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile3
+								 [idx]);
+					break;
+				default:
+
+					ASSERT(0);
+					break;
+				}
+			} else {
+				wlc_phy_write_table_nphy(pi,
+							 &mimophytbl_info_rev3_volatile
+							 [idx]);
+			}
+		}
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0_volatile
+						 [idx]);
+		}
+	}
+}
+
+static void
+wlc_phy_write_txmacreg_nphy(phy_info_t *pi, u16 holdoff, u16 delay)
+{
+	write_phy_reg(pi, 0x77, holdoff);
+	write_phy_reg(pi, 0xb4, delay);
+}
+
+void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs)
+{
+	u16 holdoff, delay;
+
+	if (rifs) {
+
+		holdoff = 0x10;
+		delay = 0x258;
+	} else {
+
+		holdoff = 0x15;
+		delay = 0x320;
+	}
+
+	wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
+
+	if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
+		pi->sh->_rifs_phy = rifs;
+	}
+}
+
+bool wlc_phy_attach_nphy(phy_info_t *pi)
+{
+	uint i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
+		pi->phyhang_avoid = true;
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		pi->nphy_gband_spurwar_en = true;
+
+		if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
+			pi->nphy_aband_spurwar_en = true;
+		}
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
+			pi->nphy_gband_spurwar2_en = true;
+		}
+	}
+
+	pi->n_preamble_override = AUTO;
+	if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4))
+		pi->n_preamble_override = WLC_N_PREAMBLE_MIXEDMODE;
+
+	pi->nphy_txrx_chain = AUTO;
+	pi->phy_scraminit = AUTO;
+
+	pi->nphy_rxcalparams = 0x010100B5;
+
+	pi->nphy_perical = PHY_PERICAL_MPHASE;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS;
+
+	pi->nphy_gain_boost = true;
+	pi->nphy_elna_gain_config = false;
+	pi->radio_is_on = false;
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_txpwrindex[i].index = AUTO;
+	}
+
+	wlc_phy_txpwrctrl_config_nphy(pi);
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+		pi->hwpwrctrl_capable = true;
+
+	pi->pi_fptr.init = wlc_phy_init_nphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_nphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy;
+
+	if (!wlc_phy_txpwr_srom_read_nphy(pi))
+		return false;
+
+	return true;
+}
+
+static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+		pi->phy_5g_pwrgain = true;
+		return;
+	}
+
+	pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
+	pi->phy_5g_pwrgain = false;
+
+	if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
+	    NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+	else if ((pi->sh->sromrev >= 4)
+		 && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
+		pi->phy_5g_pwrgain = true;
+}
+
+void WLBANDINITFN(wlc_phy_init_nphy) (phy_info_t *pi)
+{
+	u16 val;
+	u16 clip1_ths[2];
+	nphy_txgains_t target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool do_nphy_cal = false;
+	uint core;
+	uint origidx, intr_val;
+	d11regs_t *regs;
+	u32 d11_clk_ctl_st;
+
+	core = 0;
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+	}
+
+	if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
+	    ((pi->sh->chippkg == BCM4717_PKG_ID) ||
+	     (pi->sh->chippkg == BCM4718_PKG_ID))) {
+		if ((pi->sh->boardflags & BFL_EXTLNA) &&
+		    (CHSPEC_IS2G(pi->radio_chanspec))) {
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, chipcontrol), 0x40,
+				   0x40);
+		}
+	}
+
+	if ((!PHY_IPA(pi)) && (pi->sh->chip == BCM5357_CHIP_ID)) {
+		si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
+				   CCTRL5357_EXTPA);
+	}
+
+	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
+	    CHSPEC_IS40(pi->radio_chanspec)) {
+
+		regs = (d11regs_t *) si_switch_core(pi->sh->sih, D11_CORE_ID,
+						    &origidx, &intr_val);
+		ASSERT(regs != NULL);
+
+		d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
+		AND_REG(&regs->clk_ctl_st,
+			~(CCS_FORCEHT | CCS_HTAREQ));
+
+		W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+
+		si_restore_core(pi->sh->sih, origidx, intr_val);
+	}
+
+	pi->use_int_tx_iqlo_cal_nphy =
+	    (PHY_IPA(pi) ||
+	     (NREV_GE(pi->pubpi.phy_rev, 7) ||
+	      (NREV_GE(pi->pubpi.phy_rev, 5)
+	       && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
+
+	pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
+
+	pi->nphy_deaf_count = 0;
+
+	wlc_phy_tbl_init_nphy(pi);
+
+	pi->nphy_crsminpwr_adjusted = false;
+	pi->nphy_noisevars_adjusted = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xe7, 0);
+		write_phy_reg(pi, 0xec, 0);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_phy_reg(pi, 0x342, 0);
+			write_phy_reg(pi, 0x343, 0);
+			write_phy_reg(pi, 0x346, 0);
+			write_phy_reg(pi, 0x347, 0);
+		}
+		write_phy_reg(pi, 0xe5, 0);
+		write_phy_reg(pi, 0xe6, 0);
+	} else {
+		write_phy_reg(pi, 0xec, 0);
+	}
+
+	write_phy_reg(pi, 0x91, 0);
+	write_phy_reg(pi, 0x92, 0);
+	if (NREV_LT(pi->pubpi.phy_rev, 6)) {
+		write_phy_reg(pi, 0x93, 0);
+		write_phy_reg(pi, 0x94, 0);
+	}
+
+	and_phy_reg(pi, 0xa1, ~3);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0x8f, 0);
+		write_phy_reg(pi, 0xa5, 0);
+	} else {
+		write_phy_reg(pi, 0xa5, 0);
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+	else if (NREV_LT(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+	write_phy_reg(pi, 0x203, 32);
+	write_phy_reg(pi, 0x201, 32);
+
+	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
+		write_phy_reg(pi, 0x20d, 160);
+	else
+		write_phy_reg(pi, 0x20d, 184);
+
+	write_phy_reg(pi, 0x13a, 200);
+
+	write_phy_reg(pi, 0x70, 80);
+
+	write_phy_reg(pi, 0x1ff, 48);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 8)) {
+		wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
+	}
+
+	wlc_phy_stf_chain_upd_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0x180, 0xaa8);
+		write_phy_reg(pi, 0x181, 0x9a4);
+	}
+
+	if (PHY_IPA(pi)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 0), (1) << 0);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7),
+				    (pi->nphy_papd_epsilon_offset[core]) << 7);
+
+		}
+
+		wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
+		}
+	}
+
+	wlc_phy_workarounds_nphy(pi);
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
+
+	wlc_phy_pa_override_nphy(pi, OFF);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	wlc_phy_pa_override_nphy(pi, ON);
+
+	wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_phy_bphy_init_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_txpwr_fixpower_nphy(pi);
+
+	wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u32 *tx_pwrctrl_tbl = NULL;
+		u16 idx;
+		s16 pga_gn = 0;
+		s16 pad_gn = 0;
+		s32 rfpwr_offset = 0;
+
+		if (PHY_IPA(pi)) {
+			tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if NREV_IS
+					(pi->pubpi.phy_rev, 3) {
+					tx_pwrctrl_tbl =
+					    nphy_tpc_5GHz_txgain_rev3;
+				} else if NREV_IS
+					(pi->pubpi.phy_rev, 4) {
+					tx_pwrctrl_tbl =
+					    (pi->srom_fem5g.extpagain == 3) ?
+					    nphy_tpc_5GHz_txgain_HiPwrEPA :
+					    nphy_tpc_5GHz_txgain_rev4;
+				} else {
+					tx_pwrctrl_tbl =
+					    nphy_tpc_5GHz_txgain_rev5;
+				}
+
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (pi->pubpi.radiorev == 5) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_epa_2057rev5;
+					} else if (pi->pubpi.radiorev == 3) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_epa_2057rev3;
+					}
+
+				} else {
+					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3)) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_HiPwrEPA;
+					} else {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_rev3;
+					}
+				}
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+
+		pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if ((pi->pubpi.radiorev == 3) ||
+					    (pi->pubpi.radiorev == 4) ||
+					    (pi->pubpi.radiorev == 6)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev3n4
+						    [pad_gn];
+					} else if (pi->pubpi.radiorev == 5) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev5
+						    [pad_gn];
+					} else if ((pi->pubpi.radiorev == 7)
+						   || (pi->pubpi.radiorev ==
+						       8)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev7
+						    [pad_gn];
+					} else {
+						ASSERT(0);
+					}
+
+				} else {
+					if ((pi->pubpi.radiorev == 3) ||
+					    (pi->pubpi.radiorev == 4) ||
+					    (pi->pubpi.radiorev == 6)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_pgagain_dlt_5g_2057
+						    [pga_gn];
+					} else if ((pi->pubpi.radiorev == 7)
+						   || (pi->pubpi.radiorev ==
+						       8)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_pgagain_dlt_5g_2057rev7
+						    [pga_gn];
+					} else {
+						ASSERT(0);
+					}
+				}
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE1TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE2TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+			}
+		} else {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					rfpwr_offset = (s16)
+					    nphy_papd_pga_gain_delta_ipa_2g
+					    [pga_gn];
+				} else {
+					rfpwr_offset = (s16)
+					    nphy_papd_pga_gain_delta_ipa_5g
+					    [pga_gn];
+				}
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE1TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE2TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+			}
+
+		}
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+	}
+
+	if (pi->sh->phyrxchain != 0x3) {
+		wlc_phy_rxcore_setstate_nphy((wlc_phy_t *) pi,
+					     pi->sh->phyrxchain);
+	}
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if (!NORADIO_ENAB(pi->pubpi)) {
+		bool do_rssi_cal = false;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			    (pi->nphy_rssical_chanspec_2G == 0) :
+			    (pi->nphy_rssical_chanspec_5G == 0);
+
+			if (do_rssi_cal) {
+				wlc_phy_rssi_cal_nphy(pi);
+			} else {
+				wlc_phy_restore_rssical_nphy(pi);
+			}
+		} else {
+			wlc_phy_rssi_cal_nphy(pi);
+		}
+
+		if (!SCAN_RM_IN_PROGRESS(pi)) {
+			do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			    (pi->nphy_iqcal_chanspec_2G == 0) :
+			    (pi->nphy_iqcal_chanspec_5G == 0);
+		}
+
+		if (!pi->do_initcal)
+			do_nphy_cal = false;
+
+		if (do_nphy_cal) {
+
+			target_gain = wlc_phy_get_tx_gain_nphy(pi);
+
+			if (pi->antsel_type == ANTSEL_2x3)
+				wlc_phy_antsel_init((wlc_phy_t *) pi, true);
+
+			if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
+				wlc_phy_rssi_cal_nphy(pi);
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					pi->nphy_cal_orig_pwr_idx[0] =
+					    pi->nphy_txpwrindex[PHY_CORE_0].
+					    index_internal;
+					pi->nphy_cal_orig_pwr_idx[1] =
+					    pi->nphy_txpwrindex[PHY_CORE_1].
+					    index_internal;
+
+					wlc_phy_precal_txgain_nphy(pi);
+					target_gain =
+					    wlc_phy_get_tx_gain_nphy(pi);
+				}
+
+				if (wlc_phy_cal_txiqlo_nphy
+				    (pi, target_gain, true, false) == BCME_OK) {
+					if (wlc_phy_cal_rxiq_nphy
+					    (pi, target_gain, 2,
+					     false) == BCME_OK) {
+						wlc_phy_savecal_nphy(pi);
+
+					}
+				}
+			} else if (pi->mphase_cal_phase_id ==
+				   MPHASE_CAL_STATE_IDLE) {
+
+				wlc_phy_cal_perical((wlc_phy_t *) pi,
+						    PHY_PERICAL_PHYINIT);
+			}
+		} else {
+			wlc_phy_restorecal_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+
+		write_phy_reg(pi, 0x70, 50);
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	wlc_phy_spurwar_nphy(pi);
+
+}
+
+static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble)
+{
+	bool gf_preamble = false;
+	u16 val;
+
+	if (preamble == WLC_N_PREAMBLE_GF) {
+		gf_preamble = true;
+	}
+
+	val = read_phy_reg(pi, 0xed);
+
+	val |= RX_GF_MM_AUTO;
+	val &= ~RX_GF_OR_MM;
+	if (gf_preamble)
+		val |= RX_GF_OR_MM;
+
+	write_phy_reg(pi, 0xed, val);
+}
+
+static void wlc_phy_resetcca_nphy(phy_info_t *pi)
+{
+	u16 val;
+
+	ASSERT(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	udelay(1);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+}
+
+void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en)
+{
+	u16 rfctrlintc_override_val;
+
+	if (!en) {
+
+		pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
+		pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			rfctrlintc_override_val = 0x1480;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			rfctrlintc_override_val =
+			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+		} else {
+			rfctrlintc_override_val =
+			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		}
+
+		write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+		write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	} else {
+
+		write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
+		write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
+	}
+
+}
+
+void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi)
+{
+
+	u16 txrx_chain =
+	    (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
+	bool CoreActv_override = false;
+
+	if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN0) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
+			and_phy_reg(pi, 0xa0, ~0x20);
+		}
+	} else if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN1) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
+			or_phy_reg(pi, 0xa0, 0x20);
+		}
+	}
+
+	mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+
+	if (CoreActv_override) {
+
+		pi->nphy_perical = PHY_PERICAL_DISABLE;
+		or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	} else {
+		pi->nphy_perical = PHY_PERICAL_MPHASE;
+		and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+	}
+}
+
+void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask)
+{
+	u16 regval;
+	u16 tbl_buf[16];
+	uint i;
+	phy_info_t *pi = (phy_info_t *) pih;
+	u16 tbl_opcode;
+	bool suspend;
+
+	pi->sh->phyrxchain = rxcore_bitmask;
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	regval = read_phy_reg(pi, 0xa2);
+	regval &= ~(0xf << 4);
+	regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
+	write_phy_reg(pi, 0xa2, regval);
+
+	if ((rxcore_bitmask & 0x3) != 0x3) {
+
+		write_phy_reg(pi, 0x20e, 1);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry == -1) {
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							ARRAY_SIZE(tbl_buf), 80,
+							16, tbl_buf);
+
+				for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
+					if (tbl_buf[i] ==
+					    NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+
+						pi->rx2tx_biasentry = (u8) i;
+						tbl_opcode =
+						    NPHY_REV3_RFSEQ_CMD_NOP;
+						wlc_phy_table_write_nphy(pi,
+									 NPHY_TBL_ID_RFSEQ,
+									 1, i,
+									 16,
+									 &tbl_opcode);
+						break;
+					} else if (tbl_buf[i] ==
+						   NPHY_REV3_RFSEQ_CMD_END) {
+						break;
+					}
+				}
+			}
+		}
+	} else {
+
+		write_phy_reg(pi, 0x20e, 30);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry != -1) {
+				tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1, pi->rx2tx_biasentry,
+							 16, &tbl_opcode);
+				pi->rx2tx_biasentry = -1;
+			}
+		}
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih)
+{
+	u16 regval, rxen_bits;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	regval = read_phy_reg(pi, 0xa2);
+	rxen_bits = (regval >> 4) & 0xf;
+
+	return (u8) rxen_bits;
+}
+
+bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pi)
+{
+	return PHY_IPA(pi);
+}
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi)
+{
+	u8 idx, idx2, i, delta_ind;
+
+	for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
+		pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
+	}
+
+	for (i = 0; i < 4; i++) {
+		idx2 = 0;
+
+		delta_ind = 0;
+
+		switch (i) {
+		case 0:
+
+			if (CHSPEC_IS40(pi->radio_chanspec)
+			    && NPHY_IS_SROM_REINTERPRET) {
+				idx = TXP_FIRST_MCS_40_SISO;
+			} else {
+				idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+				    TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
+				delta_ind = 1;
+			}
+			break;
+
+		case 1:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
+			break;
+
+		case 2:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
+			break;
+
+		case 3:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
+			break;
+		}
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		idx = idx + delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		idx = idx + 1 - delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+	}
+}
+
+void wlc_phy_cal_init_nphy(phy_info_t *pi)
+{
+}
+
+static void wlc_phy_war_force_trsw_to_R_cliplo_nphy(phy_info_t *pi, u8 core)
+{
+	if (core == PHY_CORE_0) {
+		write_phy_reg(pi, 0x38, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x37, 0x0060);
+		} else {
+			write_phy_reg(pi, 0x37, 0x1080);
+		}
+	} else if (core == PHY_CORE_1) {
+		write_phy_reg(pi, 0x2ae, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x2ad, 0x0060);
+		} else {
+			write_phy_reg(pi, 0x2ad, 0x1080);
+		}
+	}
+}
+
+static void wlc_phy_war_txchain_upd_nphy(phy_info_t *pi, u8 txchain)
+{
+	u8 txchain0, txchain1;
+
+	txchain0 = txchain & 0x1;
+	txchain1 = (txchain & 0x2) >> 1;
+	if (!txchain0) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+	}
+
+	if (!txchain1) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+	}
+}
+
+static void wlc_phy_workarounds_nphy(phy_info_t *pi)
+{
+	u8 rfseq_rx2tx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_EXT_PA
+	};
+	u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
+	u8 rfseq_tx2rx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_EXT_PA,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS
+	};
+	u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
+	u8 rfseq_tx2rx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+	u8 rfseq_rx2tx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
+
+	u8 rfseq_rx2tx_events_rev3_ipa[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+	u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
+
+	s16 alpha0, alpha1, alpha2;
+	s16 beta0, beta1, beta2;
+	u32 leg_data_weights, ht_data_weights, nss1_data_weights,
+	    stbc_data_weights;
+	u8 chan_freq_range = 0;
+	u16 dac_control = 0x0002;
+	u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
+	u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
+	u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 *aux_adc_vmid;
+	u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
+	u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 *aux_adc_gain;
+	u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
+	u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
+	s32 min_nvar_val = 0x18d;
+	s32 min_nvar_offset_6mbps = 20;
+	u8 pdetrange;
+	u8 triso;
+	u16 regval;
+	u16 afectrl_adc_ctrl1_rev7 = 0x20;
+	u16 afectrl_adc_ctrl2_rev7 = 0x0;
+	u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
+	u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 ipalvlshift_3p3_war_en = 0;
+	u16 rccal_bcap_val, rccal_scap_val;
+	u16 rccal_tx20_11b_bcap = 0;
+	u16 rccal_tx20_11b_scap = 0;
+	u16 rccal_tx20_11n_bcap = 0;
+	u16 rccal_tx20_11n_scap = 0;
+	u16 rccal_tx40_11n_bcap = 0;
+	u16 rccal_tx40_11n_scap = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11b = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11n = 0;
+	u16 rx2tx_lpf_rc_lut_tx40_11n = 0;
+	u16 tx_lpf_bw_ofdm_20mhz = 0;
+	u16 tx_lpf_bw_ofdm_40mhz = 0;
+	u16 tx_lpf_bw_11b = 0;
+	u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt;
+	u16 txgm_idac_bleed = 0;
+	bool rccal_ovrd = false;
+	u16 freq;
+	int coreNum;
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (!ISSIM_ENAB(pi->sh->sih)) {
+		or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+			mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
+
+			mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
+			mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
+			mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
+			mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
+			mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
+			mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
+			mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
+			mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
+			mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
+			mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
+			mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
+			mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
+			mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
+			mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
+			mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
+			mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
+		}
+
+		if (NREV_LE(pi->pubpi.phy_rev, 8)) {
+			write_phy_reg(pi, 0x23f, 0x1b0);
+			write_phy_reg(pi, 0x240, 0x1b0);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+					 &dac_control);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+					 &dac_control);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					1, 0, 32, &leg_data_weights);
+		leg_data_weights = leg_data_weights & 0xffffff;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 0, 32, &leg_data_weights);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 2, 0x15e, 16,
+					 rfseq_rx2tx_dacbufpu_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
+					 rfseq_rx2tx_dacbufpu_rev7);
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3_ipa,
+					       rfseq_rx2tx_dlys_rev3_ipa,
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa) /
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa
+						[0]));
+		}
+
+		mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
+		mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
+
+		tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
+		tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
+		tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
+
+		if (PHY_IPA(pi)) {
+
+			if (((pi->pubpi.radiorev == 5)
+			     && (CHSPEC_IS40(pi->radio_chanspec) == 1))
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+
+				rccal_bcap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_BCAP_VAL);
+				rccal_scap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_SCAP_VAL);
+
+				rccal_tx20_11b_bcap = rccal_bcap_val;
+				rccal_tx20_11b_scap = rccal_scap_val;
+
+				if ((pi->pubpi.radiorev == 5) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
+
+					rccal_tx20_11n_bcap = rccal_bcap_val;
+					rccal_tx20_11n_scap = rccal_scap_val;
+					rccal_tx40_11n_bcap = 0xc;
+					rccal_tx40_11n_scap = 0xc;
+
+					rccal_ovrd = true;
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					tx_lpf_bw_ofdm_20mhz = 4;
+					tx_lpf_bw_11b = 1;
+
+					if (CHSPEC_IS2G(pi->radio_chanspec)) {
+						rccal_tx20_11n_bcap = 0xc;
+						rccal_tx20_11n_scap = 0xc;
+						rccal_tx40_11n_bcap = 0xa;
+						rccal_tx40_11n_scap = 0xa;
+					} else {
+						rccal_tx20_11n_bcap = 0x14;
+						rccal_tx20_11n_scap = 0x14;
+						rccal_tx40_11n_bcap = 0xf;
+						rccal_tx40_11n_scap = 0xf;
+					}
+
+					rccal_ovrd = true;
+				}
+			}
+
+		} else {
+
+			if (pi->pubpi.radiorev == 5) {
+
+				tx_lpf_bw_ofdm_20mhz = 1;
+				tx_lpf_bw_ofdm_40mhz = 3;
+
+				rccal_bcap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_BCAP_VAL);
+				rccal_scap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_SCAP_VAL);
+
+				rccal_tx20_11b_bcap = rccal_bcap_val;
+				rccal_tx20_11b_scap = rccal_scap_val;
+
+				rccal_tx20_11n_bcap = 0x13;
+				rccal_tx20_11n_scap = 0x11;
+				rccal_tx40_11n_bcap = 0x13;
+				rccal_tx40_11n_scap = 0x11;
+
+				rccal_ovrd = true;
+			}
+		}
+
+		if (rccal_ovrd) {
+
+			rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
+			    (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
+			rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
+			    (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
+			rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
+			    (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x152 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11b);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x153 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x154 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x155 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x156 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x157 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x158 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x159 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+			}
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		}
+
+		if (!NORADIO_ENAB(pi->pubpi)) {
+			write_phy_reg(pi, 0x32f, 0x3);
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		}
+
+		if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
+		    (pi->pubpi.radiorev == 6)) {
+			if ((pi->sh->sromrev >= 8)
+			    && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
+				ipalvlshift_3p3_war_en = 1;
+
+			if (ipalvlshift_3p3_war_en) {
+				write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG,
+						0x5);
+				write_radio_reg(pi, RADIO_2057_GPAIO_SEL1,
+						0x30);
+				write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
+				or_radio_reg(pi,
+					     RADIO_2057_RXTXBIAS_CONFIG_CORE0,
+					     0x1);
+				or_radio_reg(pi,
+					     RADIO_2057_RXTXBIAS_CONFIG_CORE1,
+					     0x1);
+
+				ipa2g_mainbias = 0x1f;
+
+				ipa2g_casconv = 0x6f;
+
+				ipa2g_biasfilt = 0xaa;
+			} else {
+
+				ipa2g_mainbias = 0x2b;
+
+				ipa2g_casconv = 0x7f;
+
+				ipa2g_biasfilt = 0xee;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum, IPA2G_IMAIN,
+							 ipa2g_mainbias);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum, IPA2G_CASCONV,
+							 ipa2g_casconv);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 IPA2G_BIAS_FILTER,
+							 ipa2g_biasfilt);
+				}
+			}
+		}
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((pi->pubpi.radiorev == 3)
+				    || (pi->pubpi.radiorev == 4)
+				    || (pi->pubpi.radiorev == 6)) {
+
+					txgm_idac_bleed = 0x7f;
+				}
+
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					if (txgm_idac_bleed != 0)
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 TXGM_IDAC_BLEED,
+								 txgm_idac_bleed);
+				}
+
+				if (pi->pubpi.radiorev == 5) {
+
+					for (coreNum = 0; coreNum <= 1;
+					     coreNum++) {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_CASCONV,
+								 0x13);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_IMAIN,
+								 0x1f);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_BIAS_FILTER,
+								 0xee);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 PAD2G_IDACS,
+								 0x8a);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 PAD_BIAS_FILTER_BWS,
+								 0x3e);
+					}
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					if (CHSPEC_IS40(pi->radio_chanspec) ==
+					    0) {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 0,
+								 IPA2G_IMAIN,
+								 0x14);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 1,
+								 IPA2G_IMAIN,
+								 0x12);
+					} else {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 0,
+								 IPA2G_IMAIN,
+								 0x16);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 1,
+								 IPA2G_IMAIN,
+								 0x16);
+					}
+				}
+
+			} else {
+				freq =
+				    CHAN5G_FREQ(CHSPEC_CHANNEL
+						(pi->radio_chanspec));
+				if (((freq >= 5180) && (freq <= 5230))
+				    || ((freq >= 5745) && (freq <= 5805))) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 0, IPA5G_BIAS_FILTER,
+							 0xff);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 1, IPA5G_BIAS_FILTER,
+							 0xff);
+				}
+			}
+		} else {
+
+			if (pi->pubpi.radiorev != 5) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 TXMIX2G_TUNE_BOOST_PU,
+							 0x61);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 TXGM_IDAC_BLEED, 0x70);
+				}
+			}
+		}
+
+		if (pi->pubpi.radiorev == 4) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x05, 16,
+						 &afectrl_adc_ctrl1_rev7);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x15, 16,
+						 &afectrl_adc_ctrl1_rev7);
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_VCM_CAL_MASTER, 0x0);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_SET_VCM_I, 0x3f);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_SET_VCM_Q, 0x3f);
+			}
+		} else {
+			mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+
+			mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
+			mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x05, 16,
+						 &afectrl_adc_ctrl2_rev7);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x15, 16,
+						 &afectrl_adc_ctrl2_rev7);
+
+			mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
+		}
+
+		write_phy_reg(pi, 0x6a, 0x2);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
+					 &min_nvar_offset_6mbps);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
+					 &rfseq_pktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
+					 &rfseq_pktgn_lpf_h_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
+					 &rfseq_htpktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
+					 &rfseq_cckpktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
+					 &rfseq_tx2rx_lpf_h_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
+					 &rfseq_rx2tx_lpf_h_hpc_rev7);
+
+		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		} else {
+			min_nvar_val = noise_var_tbl_rev7[3];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+
+			min_nvar_val = noise_var_tbl_rev7[127];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		}
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		pdetrange =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    pdetrange : pi->srom_fem2g.pdetrange;
+
+		if (pdetrange == 0) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x70;
+				aux_adc_vmid_rev7_core1[3] = 0x70;
+				aux_adc_gain_rev7[3] = 2;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x80;
+				aux_adc_vmid_rev7_core1[3] = 0x80;
+				aux_adc_gain_rev7[3] = 3;
+			}
+		} else if (pdetrange == 1) {
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x7c;
+				aux_adc_vmid_rev7_core1[3] = 0x7c;
+				aux_adc_gain_rev7[3] = 2;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x8c;
+				aux_adc_vmid_rev7_core1[3] = 0x8c;
+				aux_adc_gain_rev7[3] = 1;
+			}
+		} else if (pdetrange == 2) {
+			if (pi->pubpi.radioid == BCM2057_ID) {
+				if ((pi->pubpi.radiorev == 5)
+				    || (pi->pubpi.radiorev == 7)
+				    || (pi->pubpi.radiorev == 8)) {
+					if (chan_freq_range ==
+					    WL_CHAN_FREQ_RANGE_2G) {
+						aux_adc_vmid_rev7_core0[3] =
+						    0x8c;
+						aux_adc_vmid_rev7_core1[3] =
+						    0x8c;
+						aux_adc_gain_rev7[3] = 0;
+					} else {
+						aux_adc_vmid_rev7_core0[3] =
+						    0x96;
+						aux_adc_vmid_rev7_core1[3] =
+						    0x96;
+						aux_adc_gain_rev7[3] = 0;
+					}
+				}
+			}
+
+		} else if (pdetrange == 3) {
+			if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x89;
+				aux_adc_vmid_rev7_core1[3] = 0x89;
+				aux_adc_gain_rev7[3] = 0;
+			}
+
+		} else if (pdetrange == 5) {
+
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x80;
+				aux_adc_vmid_rev7_core1[3] = 0x80;
+				aux_adc_gain_rev7[3] = 3;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x70;
+				aux_adc_vmid_rev7_core1[3] = 0x70;
+				aux_adc_gain_rev7[3] = 2;
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
+					 &aux_adc_vmid_rev7_core0);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
+					 &aux_adc_vmid_rev7_core1);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
+					 &aux_adc_gain_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
+					 &aux_adc_gain_rev7);
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		write_phy_reg(pi, 0x23f, 0x1f8);
+		write_phy_reg(pi, 0x240, 0x1f8);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					1, 0, 32, &leg_data_weights);
+		leg_data_weights = leg_data_weights & 0xffffff;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 0, 32, &leg_data_weights);
+
+		alpha0 = 293;
+		alpha1 = 435;
+		alpha2 = 261;
+		beta0 = 366;
+		beta1 = 205;
+		beta2 = 32;
+		write_phy_reg(pi, 0x145, alpha0);
+		write_phy_reg(pi, 0x146, alpha1);
+		write_phy_reg(pi, 0x147, alpha2);
+		write_phy_reg(pi, 0x148, beta0);
+		write_phy_reg(pi, 0x149, beta1);
+		write_phy_reg(pi, 0x14a, beta2);
+
+		write_phy_reg(pi, 0x38, 0xC);
+		write_phy_reg(pi, 0x2ae, 0xC);
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
+				       rfseq_tx2rx_events_rev3,
+				       rfseq_tx2rx_dlys_rev3,
+				       sizeof(rfseq_tx2rx_events_rev3) /
+				       sizeof(rfseq_tx2rx_events_rev3[0]));
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3_ipa,
+					       rfseq_rx2tx_dlys_rev3_ipa,
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa) /
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa
+						[0]));
+		}
+
+		if ((pi->sh->hw_phyrxchain != 0x3) &&
+		    (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
+
+			if (PHY_IPA(pi)) {
+				rfseq_rx2tx_dlys_rev3[5] = 59;
+				rfseq_rx2tx_dlys_rev3[6] = 1;
+				rfseq_rx2tx_events_rev3[7] =
+				    NPHY_REV3_RFSEQ_CMD_END;
+			}
+
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3,
+					       rfseq_rx2tx_dlys_rev3,
+					       sizeof(rfseq_rx2tx_events_rev3) /
+					       sizeof(rfseq_rx2tx_events_rev3
+						      [0]));
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6a, 0x2);
+		} else {
+			write_phy_reg(pi, 0x6a, 0x9c40);
+		}
+
+		mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
+
+		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		} else {
+			min_nvar_val = noise_var_tbl_rev3[3];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+
+			min_nvar_val = noise_var_tbl_rev3[127];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		}
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+					 &dac_control);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+					 &dac_control);
+
+		pdetrange =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    pdetrange : pi->srom_fem2g.pdetrange;
+
+		if (pdetrange == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+				aux_adc_vmid = aux_adc_vmid_rev4;
+				aux_adc_gain = aux_adc_gain_rev4;
+			} else {
+				aux_adc_vmid = aux_adc_vmid_rev3;
+				aux_adc_gain = aux_adc_gain_rev3;
+			}
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				switch (chan_freq_range) {
+				case WL_CHAN_FREQ_RANGE_5GL:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				case WL_CHAN_FREQ_RANGE_5GM:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				case WL_CHAN_FREQ_RANGE_5GH:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				default:
+					break;
+				}
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, aux_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, aux_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, aux_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, aux_adc_gain);
+		} else if (pdetrange == 1) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, sk_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, sk_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, sk_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, sk_adc_gain);
+		} else if (pdetrange == 2) {
+
+			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
+			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				chan_freq_range =
+				    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+				if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+					bcm_adc_vmid[3] = 0x8e;
+					bcm_adc_gain[3] = 0x03;
+				} else {
+					bcm_adc_vmid[3] = 0x94;
+					bcm_adc_gain[3] = 0x03;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				bcm_adc_vmid[3] = 0x84;
+				bcm_adc_gain[3] = 0x02;
+			}
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, bcm_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, bcm_adc_gain);
+		} else if (pdetrange == 3) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if ((NREV_GE(pi->pubpi.phy_rev, 4))
+			    && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
+
+				u16 auxadc_vmid[] = {
+					0xa2, 0xb4, 0xb4, 0x270 };
+				u16 auxadc_gain[] = {
+					0x02, 0x02, 0x02, 0x00 };
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x08, 16, auxadc_vmid);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x18, 16, auxadc_vmid);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x0c, 16, auxadc_gain);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x1c, 16, auxadc_gain);
+			}
+		} else if ((pdetrange == 4) || (pdetrange == 5)) {
+			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
+			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
+			u16 Vmid[2], Av[2];
+
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
+				Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
+				Av[0] = (pdetrange == 4) ? 2 : 0;
+				Av[1] = (pdetrange == 4) ? 2 : 0;
+			} else {
+				Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
+				Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
+				Av[0] = (pdetrange == 4) ? 2 : 0;
+				Av[1] = (pdetrange == 4) ? 2 : 0;
+			}
+
+			bcm_adc_vmid[3] = Vmid[0];
+			bcm_adc_gain[3] = Av[0];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, bcm_adc_gain);
+
+			bcm_adc_vmid[3] = Vmid[1];
+			bcm_adc_gain[3] = Av[1];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, bcm_adc_gain);
+		} else {
+			ASSERT(0);
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0),
+				0x6);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1),
+				0x6);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0),
+				0x7);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1),
+				0x7);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0),
+				0x88);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1),
+				0x88);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1),
+				0x0);
+
+		triso =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    triso : pi->srom_fem2g.triso;
+		if (triso == 7) {
+			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+		}
+
+		wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
+
+		if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
+		     (CHSPEC_IS5G(pi->radio_chanspec))) ||
+		    (((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
+		      (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
+		     (CHSPEC_IS2G(pi->radio_chanspec)))) {
+			nss1_data_weights = 0x00088888;
+			ht_data_weights = 0x00088888;
+			stbc_data_weights = 0x00088888;
+		} else {
+			nss1_data_weights = 0x88888888;
+			ht_data_weights = 0x88888888;
+			stbc_data_weights = 0x88888888;
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 1, 32, &nss1_data_weights);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 2, 32, &ht_data_weights);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 3, 32, &stbc_data_weights);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_GMBB_IDAC |
+						RADIO_2056_TX0, 0x70);
+				write_radio_reg(pi,
+						RADIO_2056_TX_GMBB_IDAC |
+						RADIO_2056_TX1, 0x70);
+			}
+		}
+
+		if (!pi->edcrs_threshold_lock) {
+			write_phy_reg(pi, 0x224, 0x3eb);
+			write_phy_reg(pi, 0x225, 0x3eb);
+			write_phy_reg(pi, 0x226, 0x341);
+			write_phy_reg(pi, 0x227, 0x341);
+			write_phy_reg(pi, 0x228, 0x42b);
+			write_phy_reg(pi, 0x229, 0x42b);
+			write_phy_reg(pi, 0x22a, 0x381);
+			write_phy_reg(pi, 0x22b, 0x381);
+			write_phy_reg(pi, 0x22c, 0x42b);
+			write_phy_reg(pi, 0x22d, 0x42b);
+			write_phy_reg(pi, 0x22e, 0x381);
+			write_phy_reg(pi, 0x22f, 0x381);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+
+			if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
+				wlapi_bmac_mhf(pi->sh->physhim, MHF4,
+					       MHF4_BPHY_TXCORE0,
+					       MHF4_BPHY_TXCORE0, WLC_BAND_ALL);
+			}
+		}
+	} else {
+
+		if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
+		    (pi->sh->boardtype == 0x8b)) {
+			uint i;
+			u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
+			for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
+				rfseq_rx2tx_dlys[i] = war_dlys[i];
+		}
+
+		if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
+		} else {
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
+		}
+
+		regval = 0x000a;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+			regval = 0xcdaa;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			regval = 0x0000;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
+
+			regval = 0x7aab;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
+
+			regval = 0x0800;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
+		}
+
+		write_phy_reg(pi, 0xf8, 0x02d8);
+		write_phy_reg(pi, 0xf9, 0x0301);
+		write_phy_reg(pi, 0xfa, 0x02d8);
+		write_phy_reg(pi, 0xfb, 0x0301);
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
+				       rfseq_rx2tx_dlys,
+				       sizeof(rfseq_rx2tx_events) /
+				       sizeof(rfseq_rx2tx_events[0]));
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
+				       rfseq_tx2rx_dlys,
+				       sizeof(rfseq_tx2rx_events) /
+				       sizeof(rfseq_tx2rx_events[0]));
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
+				wlapi_bmac_mhf(pi->sh->physhim, MHF3,
+					       MHF3_NPHY_MLADV_WAR,
+					       MHF3_NPHY_MLADV_WAR,
+					       WLC_BAND_ALL);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			write_phy_reg(pi, 0x1e3, 0x0);
+			write_phy_reg(pi, 0x1e4, 0x0);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
+
+		alpha0 = 293;
+		alpha1 = 435;
+		alpha2 = 261;
+		beta0 = 366;
+		beta1 = 205;
+		beta2 = 32;
+		write_phy_reg(pi, 0x145, alpha0);
+		write_phy_reg(pi, 0x146, alpha1);
+		write_phy_reg(pi, 0x147, alpha2);
+		write_phy_reg(pi, 0x148, beta0);
+		write_phy_reg(pi, 0x149, beta1);
+		write_phy_reg(pi, 0x14a, beta2);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+			mod_phy_reg(pi, 0x142, (0xf << 12), 0);
+
+			write_phy_reg(pi, 0x192, 0xb5);
+			write_phy_reg(pi, 0x193, 0xa4);
+			write_phy_reg(pi, 0x194, 0x0);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_phy_reg(pi, 0x221,
+				    NPHY_FORCESIG_DECODEGATEDCLKS,
+				    NPHY_FORCESIG_DECODEGATEDCLKS);
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi)
+{
+	u16 w1th, hpf_code, currband;
+	int ctr;
+	u8 rfseq_updategainu_events[] = {
+		NPHY_RFSEQ_CMD_RX_GAIN,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_SET_HPF_BW
+	};
+	u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
+	s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
+	s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
+	s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
+	s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
+	s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
+	s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
+	s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
+	s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
+	s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
+	s8 *lna1_gain_db = NULL;
+	s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
+	s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
+	s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
+	s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
+	s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
+	s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
+	s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
+	s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
+	s8 *lna2_gain_db = NULL;
+	s8 tiaG_gain_db[] = {
+		0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
+	s8 tiaA_gain_db[] = {
+		0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
+	s8 tiaA_gain_db_rev4[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 tiaA_gain_db_rev5[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 tiaA_gain_db_rev6[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 *tia_gain_db;
+	s8 tiaG_gainbits[] = {
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+	s8 tiaA_gainbits[] = {
+		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
+	s8 tiaA_gainbits_rev4[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 tiaA_gainbits_rev5[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 tiaA_gainbits_rev6[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 *tia_gainbits;
+	s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
+	s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
+	u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
+	u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
+	u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
+	u16 rfseqG_init_gain_rev5_elna[] = {
+		0x013f, 0x013f, 0x013f, 0x013f };
+	u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
+	u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
+	u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
+	u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
+	u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
+	u16 rfseqA_init_gain_rev4_elna[] = {
+		0x314f, 0x314f, 0x314f, 0x314f };
+	u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
+	u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
+	u16 *rfseq_init_gain;
+	u16 initG_gaincode = 0x627e;
+	u16 initG_gaincode_rev4 = 0x527e;
+	u16 initG_gaincode_rev5 = 0x427e;
+	u16 initG_gaincode_rev5_elna = 0x027e;
+	u16 initG_gaincode_rev6 = 0x527e;
+	u16 initG_gaincode_rev6_224B0 = 0x427e;
+	u16 initG_gaincode_rev6_elna = 0x127e;
+	u16 initA_gaincode = 0x52de;
+	u16 initA_gaincode_rev4 = 0x629e;
+	u16 initA_gaincode_rev4_elna = 0x329e;
+	u16 initA_gaincode_rev5 = 0x729e;
+	u16 initA_gaincode_rev6 = 0x729e;
+	u16 init_gaincode;
+	u16 clip1hiG_gaincode = 0x107e;
+	u16 clip1hiG_gaincode_rev4 = 0x007e;
+	u16 clip1hiG_gaincode_rev5 = 0x1076;
+	u16 clip1hiG_gaincode_rev6 = 0x007e;
+	u16 clip1hiA_gaincode = 0x00de;
+	u16 clip1hiA_gaincode_rev4 = 0x029e;
+	u16 clip1hiA_gaincode_rev5 = 0x029e;
+	u16 clip1hiA_gaincode_rev6 = 0x029e;
+	u16 clip1hi_gaincode;
+	u16 clip1mdG_gaincode = 0x0066;
+	u16 clip1mdA_gaincode = 0x00ca;
+	u16 clip1mdA_gaincode_rev4 = 0x1084;
+	u16 clip1mdA_gaincode_rev5 = 0x2084;
+	u16 clip1mdA_gaincode_rev6 = 0x2084;
+	u16 clip1md_gaincode = 0;
+	u16 clip1loG_gaincode = 0x0074;
+	u16 clip1loG_gaincode_rev5[] = {
+		0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
+	};
+	u16 clip1loG_gaincode_rev6[] = {
+		0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
+	};
+	u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
+	u16 clip1loA_gaincode = 0x00cc;
+	u16 clip1loA_gaincode_rev4 = 0x0086;
+	u16 clip1loA_gaincode_rev5 = 0x2086;
+	u16 clip1loA_gaincode_rev6 = 0x2086;
+	u16 clip1lo_gaincode;
+	u8 crsminG_th = 0x18;
+	u8 crsminG_th_rev5 = 0x18;
+	u8 crsminG_th_rev6 = 0x18;
+	u8 crsminA_th = 0x1e;
+	u8 crsminA_th_rev4 = 0x24;
+	u8 crsminA_th_rev5 = 0x24;
+	u8 crsminA_th_rev6 = 0x24;
+	u8 crsmin_th;
+	u8 crsminlG_th = 0x18;
+	u8 crsminlG_th_rev5 = 0x18;
+	u8 crsminlG_th_rev6 = 0x18;
+	u8 crsminlA_th = 0x1e;
+	u8 crsminlA_th_rev4 = 0x24;
+	u8 crsminlA_th_rev5 = 0x24;
+	u8 crsminlA_th_rev6 = 0x24;
+	u8 crsminl_th = 0;
+	u8 crsminuG_th = 0x18;
+	u8 crsminuG_th_rev5 = 0x18;
+	u8 crsminuG_th_rev6 = 0x18;
+	u8 crsminuA_th = 0x1e;
+	u8 crsminuA_th_rev4 = 0x24;
+	u8 crsminuA_th_rev5 = 0x24;
+	u8 crsminuA_th_rev6 = 0x24;
+	u8 crsminuA_th_rev6_224B0 = 0x2d;
+	u8 crsminu_th;
+	u16 nbclipG_th = 0x20d;
+	u16 nbclipG_th_rev4 = 0x1a1;
+	u16 nbclipG_th_rev5 = 0x1d0;
+	u16 nbclipG_th_rev6 = 0x1d0;
+	u16 nbclipA_th = 0x1a1;
+	u16 nbclipA_th_rev4 = 0x107;
+	u16 nbclipA_th_rev5 = 0x0a9;
+	u16 nbclipA_th_rev6 = 0x0f0;
+	u16 nbclip_th = 0;
+	u8 w1clipG_th = 5;
+	u8 w1clipG_th_rev5 = 9;
+	u8 w1clipG_th_rev6 = 5;
+	u8 w1clipA_th = 25, w1clip_th;
+	u8 rssi_gain_default = 0x50;
+	u8 rssiG_gain_rev6_224B0 = 0x50;
+	u8 rssiA_gain_rev5 = 0x90;
+	u8 rssiA_gain_rev6 = 0x90;
+	u8 rssi_gain;
+	u16 regval[21];
+	u8 triso;
+
+	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
+	    pi->srom_fem2g.triso;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (pi->pubpi.radiorev == 5) {
+
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
+		} else if (pi->pubpi.radiorev == 7) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
+
+		} else if ((pi->pubpi.radiorev == 3)
+			   || (pi->pubpi.radiorev == 8)) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			if (pi->pubpi.radiorev == 8) {
+				mod_phy_reg(pi, 0x283,
+					    (0xff << 0), (0x44 << 0));
+				mod_phy_reg(pi, 0x280,
+					    (0xff << 0), (0x44 << 0));
+			}
+		} else {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		currband =
+		    read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+		if (currband == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				if (pi->pubpi.radiorev == 11) {
+					lna1_gain_db = lna1G_gain_db_rev6_224B0;
+					lna2_gain_db = lna2G_gain_db_rev6_224B0;
+					rfseq_init_gain =
+					    rfseqG_init_gain_rev6_224B0;
+					init_gaincode =
+					    initG_gaincode_rev6_224B0;
+					clip1hi_gaincode =
+					    clip1hiG_gaincode_rev6;
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev6_224B0;
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssiG_gain_rev6_224B0;
+				} else {
+					lna1_gain_db = lna1G_gain_db_rev6;
+					lna2_gain_db = lna2G_gain_db_rev6;
+					if (pi->sh->boardflags & BFL_EXTLNA) {
+
+						rfseq_init_gain =
+						    rfseqG_init_gain_rev6_elna;
+						init_gaincode =
+						    initG_gaincode_rev6_elna;
+					} else {
+						rfseq_init_gain =
+						    rfseqG_init_gain_rev6;
+						init_gaincode =
+						    initG_gaincode_rev6;
+					}
+					clip1hi_gaincode =
+					    clip1hiG_gaincode_rev6;
+					switch (triso) {
+					case 0:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[0];
+						break;
+					case 1:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[1];
+						break;
+					case 2:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[2];
+						break;
+					case 3:
+					default:
+
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[3];
+						break;
+					case 4:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[4];
+						break;
+					case 5:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[5];
+						break;
+					case 6:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[6];
+						break;
+					case 7:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[7];
+						break;
+					}
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssi_gain_default;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1G_gain_db_rev5;
+				lna2_gain_db = lna2G_gain_db_rev5;
+				if (pi->sh->boardflags & BFL_EXTLNA) {
+
+					rfseq_init_gain =
+					    rfseqG_init_gain_rev5_elna;
+					init_gaincode =
+					    initG_gaincode_rev5_elna;
+				} else {
+					rfseq_init_gain = rfseqG_init_gain_rev5;
+					init_gaincode = initG_gaincode_rev5;
+				}
+				clip1hi_gaincode = clip1hiG_gaincode_rev5;
+				switch (triso) {
+				case 0:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[0];
+					break;
+				case 1:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[1];
+					break;
+				case 2:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[2];
+					break;
+				case 3:
+
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[3];
+					break;
+				case 4:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[4];
+					break;
+				case 5:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[5];
+					break;
+				case 6:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[6];
+					break;
+				case 7:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[7];
+					break;
+				default:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[3];
+					break;
+				}
+				nbclip_th = nbclipG_th_rev5;
+				w1clip_th = w1clipG_th_rev5;
+				crsmin_th = crsminG_th_rev5;
+				crsminl_th = crsminlG_th_rev5;
+				crsminu_th = crsminuG_th_rev5;
+				rssi_gain = rssi_gain_default;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1G_gain_db_rev4;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain_rev4;
+				init_gaincode = initG_gaincode_rev4;
+				clip1hi_gaincode = clip1hiG_gaincode_rev4;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th_rev4;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1G_gain_db;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain;
+				init_gaincode = initG_gaincode;
+				clip1hi_gaincode = clip1hiG_gaincode;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			}
+			tia_gain_db = tiaG_gain_db;
+			tia_gainbits = tiaG_gainbits;
+			clip1md_gaincode = clip1mdG_gaincode;
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				lna1_gain_db = lna1A_gain_db_rev6;
+				lna2_gain_db = lna2A_gain_db_rev6;
+				tia_gain_db = tiaA_gain_db_rev6;
+				tia_gainbits = tiaA_gainbits_rev6;
+				rfseq_init_gain = rfseqA_init_gain_rev6;
+				init_gaincode = initA_gaincode_rev6;
+				clip1hi_gaincode = clip1hiA_gaincode_rev6;
+				clip1md_gaincode = clip1mdA_gaincode_rev6;
+				clip1lo_gaincode = clip1loA_gaincode_rev6;
+				crsmin_th = crsminA_th_rev6;
+				crsminl_th = crsminlA_th_rev6;
+				if ((pi->pubpi.radiorev == 11) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
+					crsminu_th = crsminuA_th_rev6_224B0;
+				} else {
+					crsminu_th = crsminuA_th_rev6;
+				}
+				nbclip_th = nbclipA_th_rev6;
+				rssi_gain = rssiA_gain_rev6;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1A_gain_db_rev5;
+				lna2_gain_db = lna2A_gain_db_rev5;
+				tia_gain_db = tiaA_gain_db_rev5;
+				tia_gainbits = tiaA_gainbits_rev5;
+				rfseq_init_gain = rfseqA_init_gain_rev5;
+				init_gaincode = initA_gaincode_rev5;
+				clip1hi_gaincode = clip1hiA_gaincode_rev5;
+				clip1md_gaincode = clip1mdA_gaincode_rev5;
+				clip1lo_gaincode = clip1loA_gaincode_rev5;
+				crsmin_th = crsminA_th_rev5;
+				crsminl_th = crsminlA_th_rev5;
+				crsminu_th = crsminuA_th_rev5;
+				nbclip_th = nbclipA_th_rev5;
+				rssi_gain = rssiA_gain_rev5;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1A_gain_db_rev4;
+				lna2_gain_db = lna2A_gain_db_rev4;
+				tia_gain_db = tiaA_gain_db_rev4;
+				tia_gainbits = tiaA_gainbits_rev4;
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
+
+					rfseq_init_gain =
+					    rfseqA_init_gain_rev4_elna;
+					init_gaincode =
+					    initA_gaincode_rev4_elna;
+				} else {
+					rfseq_init_gain = rfseqA_init_gain_rev4;
+					init_gaincode = initA_gaincode_rev4;
+				}
+				clip1hi_gaincode = clip1hiA_gaincode_rev4;
+				clip1md_gaincode = clip1mdA_gaincode_rev4;
+				clip1lo_gaincode = clip1loA_gaincode_rev4;
+				crsmin_th = crsminA_th_rev4;
+				crsminl_th = crsminlA_th_rev4;
+				crsminu_th = crsminuA_th_rev4;
+				nbclip_th = nbclipA_th_rev4;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1A_gain_db;
+				lna2_gain_db = lna2A_gain_db;
+				tia_gain_db = tiaA_gain_db;
+				tia_gainbits = tiaA_gainbits;
+				rfseq_init_gain = rfseqA_init_gain;
+				init_gaincode = initA_gaincode;
+				clip1hi_gaincode = clip1hiA_gaincode;
+				clip1md_gaincode = clip1mdA_gaincode;
+				clip1lo_gaincode = clip1loA_gaincode;
+				crsmin_th = crsminA_th;
+				crsminl_th = crsminlA_th;
+				crsminu_th = crsminuA_th;
+				nbclip_th = nbclipA_th;
+				rssi_gain = rssi_gain_default;
+			}
+			w1clip_th = w1clipA_th;
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
+				0xf0);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
+				0xf0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
+				rssi_gain);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
+				rssi_gain);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
+				0xFF);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
+				0xFF);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
+					 8, lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
+					 8, lna1_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+					 8, lna2_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+					 8, lna2_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
+					 8, tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
+					 8, tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
+					 8, tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
+					 8, tia_gainbits);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
+					 8, &lpf_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
+					 8, &lpf_gainbits);
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x24, clip1md_gaincode);
+		write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+
+		mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
+		mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		write_phy_reg(pi, 0x2b, nbclip_th);
+		write_phy_reg(pi, 0x41, nbclip_th);
+
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+	} else {
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		write_phy_reg(pi, 0x2b, 0x84);
+		write_phy_reg(pi, 0x41, 0x84);
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6b, 0x2b);
+			write_phy_reg(pi, 0x6c, 0x2b);
+			write_phy_reg(pi, 0x6d, 0x9);
+			write_phy_reg(pi, 0x6e, 0x9);
+		}
+
+		w1th = NPHY_RSSICAL_W1_TARGET - 4;
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
+
+			mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
+		}
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+		if (pi->nphy_gain_boost)
+			if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
+			    (CHSPEC_IS40(pi->radio_chanspec)))
+				hpf_code = 4;
+			else
+				hpf_code = 5;
+		else if (CHSPEC_IS40(pi->radio_chanspec))
+			hpf_code = 6;
+		else
+			hpf_code = 7;
+
+		mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
+		mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
+
+		for (ctr = 0; ctr < 4; ctr++) {
+			regval[ctr] = (hpf_code << 8) | 0x7c;
+		}
+		wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+		if (pi->nphy_elna_gain_config) {
+			regval[0] = 0;
+			regval[1] = 1;
+			regval[2] = 1;
+			regval[3] = 1;
+			wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+
+			for (ctr = 0; ctr < 4; ctr++) {
+				regval[ctr] = (hpf_code << 8) | 0x74;
+			}
+			wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			for (ctr = 0; ctr < 21; ctr++) {
+				regval[ctr] = 3 * ctr;
+			}
+			wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+
+			for (ctr = 0; ctr < 21; ctr++) {
+				regval[ctr] = (u16) ctr;
+			}
+			wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
+		}
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
+				       rfseq_updategainu_events,
+				       rfseq_updategainu_dlys,
+				       sizeof(rfseq_updategainu_events) /
+				       sizeof(rfseq_updategainu_events[0]));
+
+		mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_phy_reg(pi,
+				    (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
+				    0x7f, 0x4);
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi)
+{
+	s8 lna1_gain_db[] = { 8, 13, 17, 22 };
+	s8 lna2_gain_db[] = { -2, 7, 11, 15 };
+	s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
+	s8 tia_gainbits[] = {
+		0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+	mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
+	mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
+				 lna1_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
+				 lna1_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
+				 lna2_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
+				 lna2_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+				 tia_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+				 tia_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+				 tia_gainbits);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+				 tia_gainbits);
+
+	write_phy_reg(pi, 0x37, 0x74);
+	write_phy_reg(pi, 0x2ad, 0x74);
+	write_phy_reg(pi, 0x38, 0x18);
+	write_phy_reg(pi, 0x2ae, 0x18);
+
+	write_phy_reg(pi, 0x2b, 0xe8);
+	write_phy_reg(pi, 0x41, 0xe8);
+
+	if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
+	} else {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi)
+{
+	u16 currband;
+	s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
+	s8 *lna1_gain_db = NULL;
+	s8 *lna1_gain_db_2 = NULL;
+	s8 *lna2_gain_db = NULL;
+	s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
+	s8 *tia_gain_db;
+	s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
+	s8 *tia_gainbits;
+	u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
+	u16 *rfseq_init_gain;
+	u16 init_gaincode;
+	u16 clip1hi_gaincode;
+	u16 clip1md_gaincode = 0;
+	u16 clip1md_gaincode_B;
+	u16 clip1lo_gaincode;
+	u16 clip1lo_gaincode_B;
+	u8 crsminl_th = 0;
+	u8 crsminu_th;
+	u16 nbclip_th = 0;
+	u8 w1clip_th;
+	u16 freq;
+	s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
+	u8 chg_nbclip_th = 0;
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (currband == 0) {
+
+		lna1_gain_db = lna1G_gain_db_rev7;
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+					 lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+					 lna1_gain_db);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+		}
+
+		mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
+			mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+		}
+	} else {
+
+		init_gaincode = 0x9e;
+		clip1hi_gaincode = 0x9e;
+		clip1md_gaincode_B = 0x24;
+		clip1lo_gaincode = 0x8a;
+		clip1lo_gaincode_B = 8;
+		rfseq_init_gain = rfseqA_init_gain_rev7;
+
+		tia_gain_db = tiaA_gain_db_rev7;
+		tia_gainbits = tiaA_gainbits_rev7;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			w1clip_th = 25;
+			clip1md_gaincode = 0x82;
+
+			if ((freq <= 5080) || (freq == 5825)) {
+
+				s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					11, 17, 22, 25 };
+				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x3e;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else if ((freq >= 5500) && (freq <= 5700)) {
+
+				s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					12, 18, 22, 26 };
+				s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
+
+				crsminu_th = 0x45;
+				clip1md_gaincode_B = 0x14;
+				nbclip_th = 0xff;
+				chg_nbclip_th = 1;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else {
+
+				s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					12, 18, 22, 26 };
+				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x41;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			}
+
+			if (freq <= 4920) {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5700)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 0;
+			}
+		} else {
+
+			crsminu_th = 0x3a;
+			crsminl_th = 0x3a;
+			w1clip_th = 20;
+
+			if ((freq >= 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5550)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 3;
+			}
+		}
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x36, clip1md_gaincode_B);
+		write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+		write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
+		write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+					 tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+					 tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+					 tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+					 tia_gainbits);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		if (chg_nbclip_th == 1) {
+			write_phy_reg(pi, 0x2b, nbclip_th);
+			write_phy_reg(pi, 0x41, nbclip_th);
+		}
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 0), (nvar_baseline_offset0 << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 6), (nvar_baseline_offset1 << 6));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+						 lna1_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+						 lna1_gain_db_2);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+						 8, lna2_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+						 8, lna2_gain_db);
+
+			write_phy_reg(pi, 0x24, clip1md_gaincode);
+			write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+		} else {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		}
+
+	}
+
+}
+
+static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi)
+{
+	uint core;
+	int ctr;
+	s16 gain_delta[2];
+	u8 curr_channel;
+	u16 minmax_gain[2];
+	u16 regval[4];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->nphy_gain_boost) {
+		if ((CHSPEC_IS2G(pi->radio_chanspec))) {
+
+			gain_delta[0] = 6;
+			gain_delta[1] = 6;
+		} else {
+
+			curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+			gain_delta[0] =
+			    (s16)
+			    PHY_HW_ROUND(((nphy_lnagain_est0[0] *
+					   curr_channel) +
+					  nphy_lnagain_est0[1]), 13);
+			gain_delta[1] =
+			    (s16)
+			    PHY_HW_ROUND(((nphy_lnagain_est1[0] *
+					   curr_channel) +
+					  nphy_lnagain_est1[1]), 13);
+		}
+	} else {
+
+		gain_delta[0] = 0;
+		gain_delta[1] = 0;
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (pi->nphy_elna_gain_config) {
+
+			regval[0] = nphy_def_lnagains[2] + gain_delta[core];
+			regval[1] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[2] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[3] = nphy_def_lnagains[3] + gain_delta[core];
+		} else {
+			for (ctr = 0; ctr < 4; ctr++) {
+				regval[ctr] =
+				    nphy_def_lnagains[ctr] + gain_delta[core];
+			}
+		}
+		wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
+
+		minmax_gain[core] =
+		    (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
+	}
+
+	mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
+	mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on)
+{
+	if (on) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (!pi->radio_is_on) {
+				wlc_phy_radio_preinit_205x(pi);
+				wlc_phy_radio_init_2057(pi);
+				wlc_phy_radio_postinit_2057(pi);
+			}
+
+			wlc_phy_chanspec_set((wlc_phy_t *) pi,
+					     pi->radio_chanspec);
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio_preinit_205x(pi);
+			wlc_phy_radio_init_2056(pi);
+			wlc_phy_radio_postinit_2056(pi);
+
+			wlc_phy_chanspec_set((wlc_phy_t *) pi,
+					     pi->radio_chanspec);
+		} else {
+			wlc_phy_radio_preinit_2055(pi);
+			wlc_phy_radio_init_2055(pi);
+			wlc_phy_radio_postinit_2055(pi);
+		}
+
+		pi->radio_is_on = true;
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX0, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX1, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+
+			pi->radio_is_on = false;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			pi->radio_is_on = false;
+		}
+
+	}
+}
+
+static void wlc_phy_radio_preinit_2055(phy_info_t *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+}
+
+static void wlc_phy_radio_init_2055(phy_info_t *pi)
+{
+	wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+}
+
+static void wlc_phy_radio_postinit_2055(phy_info_t *pi)
+{
+
+	and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
+		      ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
+
+	if (((pi->sh->sromrev >= 4)
+	     && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
+	    || ((pi->sh->sromrev < 4))) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
+		and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
+	write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
+
+	and_radio_reg(pi, RADIO_2055_CAL_MISC,
+		      ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
+
+	or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
+
+	udelay(1000);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+
+	SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		   RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+
+	ASSERT((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		RADIO_2055_RCAL_DONE) == RADIO_2055_RCAL_DONE);
+
+	and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
+		      ~(RADIO_2055_CAL_LPO_ENABLE));
+
+	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+
+	mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	if (pi->nphy_gain_boost) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+		and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+	} else {
+		or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+		or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+	}
+
+	udelay(2);
+}
+
+static void wlc_phy_radio_preinit_205x(phy_info_t *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+	and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU);
+
+}
+
+static void wlc_phy_radio_init_2056(phy_info_t *pi)
+{
+	radio_regs_t *regs_SYN_2056_ptr = NULL;
+	radio_regs_t *regs_TX_2056_ptr = NULL;
+	radio_regs_t *regs_RX_2056_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		regs_SYN_2056_ptr = regs_SYN_2056;
+		regs_TX_2056_ptr = regs_TX_2056;
+		regs_RX_2056_ptr = regs_RX_2056;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+		regs_TX_2056_ptr = regs_TX_2056_A1;
+		regs_RX_2056_ptr = regs_RX_2056_A1;
+	} else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			regs_TX_2056_ptr = regs_TX_2056_rev5;
+			regs_RX_2056_ptr = regs_RX_2056_rev5;
+			break;
+
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			regs_TX_2056_ptr = regs_TX_2056_rev6;
+			regs_RX_2056_ptr = regs_RX_2056_rev6;
+			break;
+
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			regs_TX_2056_ptr = regs_TX_2056_rev7;
+			regs_RX_2056_ptr = regs_RX_2056_rev7;
+			break;
+
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			regs_TX_2056_ptr = regs_TX_2056_rev8;
+			regs_RX_2056_ptr = regs_RX_2056_rev8;
+			break;
+
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			regs_TX_2056_ptr = regs_TX_2056_rev11;
+			regs_RX_2056_ptr = regs_RX_2056_rev11;
+			break;
+
+		default:
+			ASSERT(0);
+			break;
+		}
+	}
+
+	wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1);
+}
+
+static void wlc_phy_radio_postinit_2056(phy_info_t *pi)
+{
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb);
+
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2);
+	udelay(1000);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
+
+	if ((pi->sh->boardflags2 & BFL2_LEGACY)
+	    || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
+
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
+	} else {
+
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
+	}
+
+	mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+	}
+}
+
+static void wlc_phy_radio_init_2057(phy_info_t *pi)
+{
+	radio_20xx_regs_t *regs_2057_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+		regs_2057_ptr = regs_2057_rev4;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+		   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+
+			if (pi->pubpi.radiover == 0x0) {
+
+				regs_2057_ptr = regs_2057_rev5;
+
+			} else if (pi->pubpi.radiover == 0x1) {
+
+				regs_2057_ptr = regs_2057_rev5v1;
+			} else {
+				ASSERT(0);
+				break;
+			}
+
+		case 7:
+
+			regs_2057_ptr = regs_2057_rev7;
+			break;
+
+		case 8:
+
+			regs_2057_ptr = regs_2057_rev8;
+			break;
+
+		default:
+			ASSERT(0);
+			break;
+		}
+	} else {
+		ASSERT(0);
+	}
+
+	wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+}
+
+static void wlc_phy_radio_postinit_2057(phy_info_t *pi)
+{
+
+	mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+
+	if (pi->sh->chip == !BCM6362_CHIP_ID) {
+
+		mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x2, 0x2);
+	}
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
+	mdelay(2);
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+		wlc_phy_radio2057_rccal(pi);
+	}
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+}
+
+static bool
+wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
+		       chan_info_nphy_radio2057_t **t0,
+		       chan_info_nphy_radio205x_t **t1,
+		       chan_info_nphy_radio2057_rev5_t **t2,
+		       chan_info_nphy_2055_t **t3)
+{
+	uint i;
+	chan_info_nphy_radio2057_t *chan_info_tbl_p_0 = NULL;
+	chan_info_nphy_radio205x_t *chan_info_tbl_p_1 = NULL;
+	chan_info_nphy_radio2057_rev5_t *chan_info_tbl_p_2 = NULL;
+	u32 tbl_len = 0;
+
+	int freq = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+			   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+			switch (pi->pubpi.radiorev) {
+
+			case 5:
+
+				if (pi->pubpi.radiover == 0x0) {
+
+					chan_info_tbl_p_2 =
+					    chan_info_nphyrev8_2057_rev5;
+					tbl_len =
+					    ARRAY_SIZE
+					    (chan_info_nphyrev8_2057_rev5);
+
+				} else if (pi->pubpi.radiover == 0x1) {
+
+					chan_info_tbl_p_2 =
+					    chan_info_nphyrev9_2057_rev5v1;
+					tbl_len =
+					    ARRAY_SIZE
+					    (chan_info_nphyrev9_2057_rev5v1);
+
+				}
+				break;
+
+			case 7:
+				chan_info_tbl_p_0 =
+				    chan_info_nphyrev8_2057_rev7;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
+				break;
+
+			case 8:
+				chan_info_tbl_p_0 =
+				    chan_info_nphyrev8_2057_rev8;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+				break;
+
+			default:
+				if (NORADIO_ENAB(pi->pubpi)) {
+					goto fail;
+				}
+				break;
+			}
+		} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+		} else {
+			goto fail;
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (pi->pubpi.radiorev == 5) {
+
+				if (chan_info_tbl_p_2[i].chan == channel)
+					break;
+			} else {
+
+				if (chan_info_tbl_p_0[i].chan == channel)
+					break;
+			}
+		}
+
+		if (i >= tbl_len) {
+			ASSERT(i < tbl_len);
+			goto fail;
+		}
+		if (pi->pubpi.radiorev == 5) {
+			*t2 = &chan_info_tbl_p_2[i];
+			freq = chan_info_tbl_p_2[i].freq;
+		} else {
+			*t0 = &chan_info_tbl_p_0[i];
+			freq = chan_info_tbl_p_0[i].freq;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev3_2056;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)
+			   || NREV_IS(pi->pubpi.phy_rev, 6)) {
+			switch (pi->pubpi.radiorev) {
+			case 5:
+				chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5);
+				break;
+			case 6:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6);
+				break;
+			case 7:
+			case 9:
+				chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
+				break;
+			case 8:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8);
+				break;
+			case 11:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
+				break;
+			default:
+				if (NORADIO_ENAB(pi->pubpi)) {
+					goto fail;
+				}
+				break;
+			}
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (chan_info_tbl_p_1[i].chan == channel)
+				break;
+		}
+
+		if (i >= tbl_len) {
+			ASSERT(i < tbl_len);
+			goto fail;
+		}
+		*t1 = &chan_info_tbl_p_1[i];
+		freq = chan_info_tbl_p_1[i].freq;
+
+	} else {
+		for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++)
+			if (chan_info_nphy_2055[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
+			ASSERT(i < ARRAY_SIZE(chan_info_nphy_2055));
+			goto fail;
+		}
+		*t3 = &chan_info_nphy_2055[i];
+		freq = chan_info_nphy_2055[i].freq;
+	}
+
+	*f = freq;
+	return true;
+
+ fail:
+	*f = WL_CHAN_FREQ_RANGE_2G;
+	return false;
+}
+
+u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint channel)
+{
+	int freq;
+	chan_info_nphy_radio2057_t *t0 = NULL;
+	chan_info_nphy_radio205x_t *t1 = NULL;
+	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
+	chan_info_nphy_2055_t *t3 = NULL;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if (channel == 0)
+		channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+	wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
+		return WL_CHAN_FREQ_RANGE_5GL;
+	} else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
+		return WL_CHAN_FREQ_RANGE_5GM;
+	} else {
+		return WL_CHAN_FREQ_RANGE_5GH;
+	}
+}
+
+static void
+wlc_phy_chanspec_radio2055_setup(phy_info_t *pi, chan_info_nphy_2055_t *ci)
+{
+
+	write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2);
+	write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE,
+			ci->RF_core1_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE,
+			ci->RF_core1_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1);
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN,
+			ci->RF_core1_tx_pga_pad_tn);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM,
+			ci->RF_core1_tx_mx_bgtrim);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE,
+			ci->RF_core2_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE,
+			ci->RF_core2_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN,
+			ci->RF_core2_tx_pga_pad_tn);
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM,
+			ci->RF_core2_tx_mx_bgtrim);
+
+	udelay(50);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65);
+
+	udelay(300);
+}
+
+static void
+wlc_phy_chanspec_radio2056_setup(phy_info_t *pi,
+				 const chan_info_nphy_radio205x_t *ci)
+{
+	radio_regs_t *regs_SYN_2056_ptr = NULL;
+
+	write_radio_reg(pi,
+			RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN,
+			ci->RF_SYN_pll_refdiv);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter3);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter4);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter5);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr27);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr28);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr29);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_VCOBUF1);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_MIXER2);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF3);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF4);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixg_boost_tune);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixg_boost_tune);
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3))
+		regs_SYN_2056_ptr = regs_SYN_2056;
+	else if (NREV_IS(pi->pubpi.phy_rev, 4))
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+	else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			break;
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			break;
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			break;
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			break;
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			break;
+		}
+	}
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
+	} else {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+
+			if ((pi->sh->chip == BCM4716_CHIP_ID) ||
+			    (pi->sh->chip == BCM47162_CHIP_ID)) {
+
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_LOOPFILTER4 |
+						RADIO_2056_SYN, 0x14);
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_CP2 |
+						RADIO_2056_SYN, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_LOOPFILTER4 |
+						RADIO_2056_SYN, 0xb);
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_CP2 |
+						RADIO_2056_SYN, 0x14);
+			}
+		}
+	}
+
+	if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) &&
+	    (CHSPEC_IS2G(pi->radio_chanspec))) {
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+				0xb);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN,
+				0x20);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_APLL_WAR) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 |
+					RADIO_2056_SYN, 0x5);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+					RADIO_2056_SYN, 0xc);
+		}
+	}
+
+	if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 pag_boost_tune;
+		u16 padg_boost_tune;
+		u16 pgag_boost_tune;
+		u16 mixg_boost_tune;
+		u16 bias, cascbias;
+		uint core;
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_IDAC, 0xcc);
+
+				if ((pi->sh->chip == BCM4716_CHIP_ID) ||
+				    (pi->sh->chip ==
+				     BCM47162_CHIP_ID)) {
+					bias = 0x40;
+					cascbias = 0x45;
+					pag_boost_tune = 0x5;
+					pgag_boost_tune = 0x33;
+					padg_boost_tune = 0x77;
+					mixg_boost_tune = 0x55;
+				} else {
+					bias = 0x25;
+					cascbias = 0x20;
+
+					if ((pi->sh->chip ==
+					     BCM43224_CHIP_ID)
+					    || (pi->sh->chip ==
+						BCM43225_CHIP_ID)
+					    || (pi->sh->chip ==
+						BCM43421_CHIP_ID)) {
+						if (pi->sh->chippkg ==
+						    BCM43224_FAB_SMIC) {
+							bias = 0x2a;
+							cascbias = 0x38;
+						}
+					}
+
+					pag_boost_tune = 0x4;
+					pgag_boost_tune = 0x03;
+					padg_boost_tune = 0x77;
+					mixg_boost_tune = 0x65;
+				}
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, cascbias);
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_BOOST_TUNE,
+						 pag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PGAG_BOOST_TUNE,
+						 pgag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_BOOST_TUNE,
+						 padg_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 MIXG_BOOST_TUNE,
+						 mixg_boost_tune);
+			} else {
+
+				bias = IS40MHZ(pi) ? 0x40 : 0x20;
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, 0x30);
+			}
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1,
+					 0xee);
+		}
+	}
+
+	if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6)
+	    && CHSPEC_IS5G(pi->radio_chanspec)) {
+		u16 paa_boost_tune;
+		u16 pada_boost_tune;
+		u16 pgaa_boost_tune;
+		u16 mixa_boost_tune;
+		u16 freq, pabias, cascbias;
+		uint core;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+
+		if (freq < 5150) {
+
+			paa_boost_tune = 0xa;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xf;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5340) {
+
+			paa_boost_tune = 0x8;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xfb;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5650) {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xb;
+			mixa_boost_tune = 0xf;
+		} else {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			if (freq != 5825) {
+				pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
+			} else {
+				pgaa_boost_tune = 6;
+			}
+			mixa_boost_tune = 0xf;
+		}
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_BOOST_TUNE, paa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_BOOST_TUNE, pada_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PGAA_BOOST_TUNE, pgaa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 MIXA_BOOST_TUNE, mixa_boost_tune);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 TXSPARE1, 0x30);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PA_SPARE2, 0xee);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_CASCBIAS, 0x3);
+
+			cascbias = 0x30;
+
+			if ((pi->sh->chip == BCM43224_CHIP_ID) ||
+			    (pi->sh->chip == BCM43225_CHIP_ID) ||
+			    (pi->sh->chip == BCM43421_CHIP_ID)) {
+				if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
+					cascbias = 0x35;
+				}
+			}
+
+			pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IAUX_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IMAIN_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_CASCBIAS, cascbias);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04,
+			      (1 << 2));
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39);
+	}
+
+	udelay(300);
+}
+
+#define MAX_205x_RCAL_WAITLOOPS 10000
+
+static u16 wlc_phy_radio205x_rcal(phy_info_t *pi)
+{
+	u16 rcal_reg = 0;
+	int i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->pubpi.radiorev == 5) {
+
+			and_phy_reg(pi, 0x342, ~(0x1 << 1));
+
+			udelay(10);
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x1);
+		}
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
+
+		udelay(10);
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
+			if (rcal_reg & 0x1) {
+				break;
+			}
+			udelay(100);
+		}
+
+		ASSERT(i < MAX_205x_RCAL_WAITLOOPS);
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
+
+		rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
+		if (pi->pubpi.radiorev == 5) {
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x0);
+		}
+
+		if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+			mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
+				      rcal_reg);
+			mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
+				      rcal_reg << 2);
+		}
+
+	} else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		u16 savereg;
+
+		savereg =
+		    read_radio_reg(pi,
+				   RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg | 0x7);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x9);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi,
+						  RADIO_2056_SYN_RCAL_CODE_OUT |
+						  RADIO_2056_SYN);
+			if (rcal_reg & 0x80) {
+				break;
+			}
+			udelay(100);
+		}
+
+		ASSERT(i < MAX_205x_RCAL_WAITLOOPS);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+
+		rcal_reg =
+		    read_radio_reg(pi,
+				   RADIO_2056_SYN_RCAL_CODE_OUT |
+				   RADIO_2056_SYN);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x0);
+
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg);
+
+		return rcal_reg & 0x1f;
+	}
+	return rcal_reg & 0x3e;
+}
+
+static void
+wlc_phy_chanspec_radio2057_setup(phy_info_t *pi,
+				 const chan_info_nphy_radio2057_t *ci,
+				 const chan_info_nphy_radio2057_rev5_t *ci2)
+{
+	int coreNum;
+	u16 txmix2g_tune_boost_pu = 0;
+	u16 pad2g_tune_pus = 0;
+
+	if (pi->pubpi.radiorev == 5) {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci2->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci2->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci2->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci2->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci2->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci2->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC,
+				ci2->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1);
+		write_radio_reg(pi,
+				RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci2->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci2->RF_logen_indbuf2g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci2->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci2->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci2->RF_lna2g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci2->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci2->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci2->RF_lna2g_tune_core1);
+
+	} else {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1);
+		write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE,
+				ci->RF_logen_mx5g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci->RF_logen_indbuf2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE,
+				ci->RF_logen_indbuf5g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0,
+				ci->RF_pga_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0,
+				ci->RF_txmix5g_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0,
+				ci->RF_pad5g_tune_misc_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci->RF_lna2g_tune_core0);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0,
+				ci->RF_lna5g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1,
+				ci->RF_pga_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1,
+				ci->RF_txmix5g_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1,
+				ci->RF_pad5g_tune_misc_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci->RF_lna2g_tune_core1);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1,
+				ci->RF_lna5g_tune_core1);
+	}
+
+	if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x3f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+	} else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) ||
+		   (pi->pubpi.radiorev == 8)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1b);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0xa);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0xa);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (PHY_IPA(pi)) {
+			if (pi->pubpi.radiorev == 3) {
+				txmix2g_tune_boost_pu = 0x6b;
+			}
+
+			if (pi->pubpi.radiorev == 5)
+				pad2g_tune_pus = 0x73;
+
+		} else {
+			if (pi->pubpi.radiorev != 5) {
+				pad2g_tune_pus = 0x3;
+
+				txmix2g_tune_boost_pu = 0x61;
+			}
+		}
+
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			if (txmix2g_tune_boost_pu != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 TXMIX2G_TUNE_BOOST_PU,
+						 txmix2g_tune_boost_pu);
+
+			if (pad2g_tune_pus != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 PAD2G_TUNE_PUS,
+						 pad2g_tune_pus);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+static u16 wlc_phy_radio2057_rccal(phy_info_t *pi)
+{
+	u16 rccal_valid;
+	int i;
+	bool chip43226_6362A0;
+
+	chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
+			    || (pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6));
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	ASSERT(rccal_valid & 0x2);
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	ASSERT(rccal_valid & 0x2);
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	ASSERT(rccal_valid & 0x2);
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	return rccal_valid;
+}
+
+static void
+wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi, u16 reduction_factr)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						((pi->nphy_rccal_value +
+						  reduction_factr) | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						(pi->nphy_rccal_value | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = false;
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *tone_id_buf,
+				 u32 *noise_var_buf)
+{
+	int i;
+	u32 offset;
+	int tone_id;
+	int tbllen =
+	    CHSPEC_IS40(pi->
+			radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
+	    NPHY_NOISEVAR_TBLLEN20;
+
+	if (pi->nphy_noisevars_adjusted) {
+		for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
+			tone_id = pi->nphy_saved_noisevars.tone_id[i];
+			offset = (tone_id >= 0) ?
+			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32,
+						 (void *)&pi->
+						 nphy_saved_noisevars.
+						 min_noise_vars[i]);
+		}
+
+		pi->nphy_saved_noisevars.bufcount = 0;
+		pi->nphy_noisevars_adjusted = false;
+	}
+
+	if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
+		pi->nphy_saved_noisevars.bufcount = 0;
+
+		for (i = 0; i < ntones; i++) {
+			tone_id = tone_id_buf[i];
+			offset = (tone_id >= 0) ?
+			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
+			pi->nphy_saved_noisevars.tone_id[i] = tone_id;
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						offset, 32,
+						&pi->nphy_saved_noisevars.
+						min_noise_vars[i]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32,
+						 (void *)&noise_var_buf[i]);
+			pi->nphy_saved_noisevars.bufcount++;
+		}
+
+		pi->nphy_noisevars_adjusted = true;
+	}
+}
+
+static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr)
+{
+	u16 regval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				pi->nphy_crsminpwr[0] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				pi->nphy_crsminpwr[1] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				pi->nphy_crsminpwr[2] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[0];
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[1];
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[2];
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = false;
+			}
+		}
+	}
+}
+
+static void wlc_phy_txlpfbw_nphy(phy_info_t *pi)
+{
+	u8 tx_lpf_bw = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			tx_lpf_bw = 3;
+		} else {
+			tx_lpf_bw = 1;
+		}
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				tx_lpf_bw = 5;
+			} else {
+				tx_lpf_bw = 4;
+			}
+		}
+		write_phy_reg(pi, 0xe8,
+			      (tx_lpf_bw << 0) |
+			      (tx_lpf_bw << 3) |
+			      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+
+		if (PHY_IPA(pi)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				tx_lpf_bw = 4;
+			} else {
+				tx_lpf_bw = 1;
+			}
+
+			write_phy_reg(pi, 0xe9,
+				      (tx_lpf_bw << 0) |
+				      (tx_lpf_bw << 3) |
+				      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+		}
+	}
+}
+
+static void wlc_phy_spurwar_nphy(phy_info_t *pi)
+{
+	u16 cur_channel = 0;
+	int nphy_adj_tone_id_buf[] = { 57, 58 };
+	u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
+	bool isAdjustNoiseVar = false;
+	uint numTonesAdjust = 0;
+	u32 tempval = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+		if (pi->nphy_gband_spurwar_en) {
+
+			wlc_phy_adjust_rx_analpfbw_nphy(pi,
+							NPHY_ANARXLPFBW_REDUCTIONFACT);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((cur_channel == 11)
+				    && CHSPEC_IS40(pi->radio_chanspec)) {
+
+					wlc_phy_adjust_min_noisevar_nphy(pi, 2,
+									 nphy_adj_tone_id_buf,
+									 nphy_adj_noise_var_buf);
+				} else {
+
+					wlc_phy_adjust_min_noisevar_nphy(pi, 0,
+									 NULL,
+									 NULL);
+				}
+			}
+			wlc_phy_adjust_crsminpwr_nphy(pi,
+						      NPHY_ADJUSTED_MINCRSPOWER);
+		}
+
+		if ((pi->nphy_gband_spurwar2_en)
+		    && CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				switch (cur_channel) {
+				case 3:
+					nphy_adj_tone_id_buf[0] = 57;
+					nphy_adj_tone_id_buf[1] = 58;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 4:
+					nphy_adj_tone_id_buf[0] = 41;
+					nphy_adj_tone_id_buf[1] = 42;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 5:
+					nphy_adj_tone_id_buf[0] = 25;
+					nphy_adj_tone_id_buf[1] = 26;
+					nphy_adj_noise_var_buf[0] = 0x24f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 6:
+					nphy_adj_tone_id_buf[0] = 9;
+					nphy_adj_tone_id_buf[1] = 10;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 7:
+					nphy_adj_tone_id_buf[0] = 121;
+					nphy_adj_tone_id_buf[1] = 122;
+					nphy_adj_noise_var_buf[0] = 0x18f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 8:
+					nphy_adj_tone_id_buf[0] = 105;
+					nphy_adj_tone_id_buf[1] = 106;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 9:
+					nphy_adj_tone_id_buf[0] = 89;
+					nphy_adj_tone_id_buf[1] = 90;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 10:
+					nphy_adj_tone_id_buf[0] = 73;
+					nphy_adj_tone_id_buf[1] = 74;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				default:
+					isAdjustNoiseVar = false;
+					break;
+				}
+			}
+
+			if (isAdjustNoiseVar) {
+				numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
+				    sizeof(nphy_adj_tone_id_buf[0]);
+
+				wlc_phy_adjust_min_noisevar_nphy(pi,
+								 numTonesAdjust,
+								 nphy_adj_tone_id_buf,
+								 nphy_adj_noise_var_buf);
+
+				tempval = 0;
+
+			} else {
+
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if ((pi->nphy_aband_spurwar_en) &&
+		    (CHSPEC_IS5G(pi->radio_chanspec))) {
+			switch (cur_channel) {
+			case 54:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x25f;
+				break;
+			case 38:
+			case 102:
+			case 118:
+				if ((pi->sh->chip == BCM4716_CHIP_ID) &&
+				    (pi->sh->chippkg == BCM4717_PKG_ID)) {
+					nphy_adj_tone_id_buf[0] = 32;
+					nphy_adj_noise_var_buf[0] = 0x21f;
+				} else {
+					nphy_adj_tone_id_buf[0] = 0;
+					nphy_adj_noise_var_buf[0] = 0x0;
+				}
+				break;
+			case 134:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x21f;
+				break;
+			case 151:
+				nphy_adj_tone_id_buf[0] = 16;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			case 153:
+			case 161:
+				nphy_adj_tone_id_buf[0] = 48;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			default:
+				nphy_adj_tone_id_buf[0] = 0;
+				nphy_adj_noise_var_buf[0] = 0x0;
+				break;
+			}
+
+			if (nphy_adj_tone_id_buf[0]
+			    && nphy_adj_noise_var_buf[0]) {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 1,
+								 nphy_adj_tone_id_buf,
+								 nphy_adj_noise_var_buf);
+			} else {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+}
+
+static void
+wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chanspec,
+			    const nphy_sfo_cfg_t *ci)
+{
+	u16 val;
+
+	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (CHSPEC_IS5G(chanspec) && !val) {
+
+		val = R_REG(&pi->regs->psm_phy_hdr_param);
+		W_REG(&pi->regs->psm_phy_hdr_param,
+		      (val | MAC_PHY_FORCE_CLK));
+
+		or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			   (BBCFG_RESETCCA | BBCFG_RESETRX));
+
+		W_REG(&pi->regs->psm_phy_hdr_param, val);
+
+		or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
+	} else if (!CHSPEC_IS5G(chanspec) && val) {
+
+		and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
+
+		val = R_REG(&pi->regs->psm_phy_hdr_param);
+		W_REG(&pi->regs->psm_phy_hdr_param,
+		      (val | MAC_PHY_FORCE_CLK));
+
+		and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			    (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
+
+		W_REG(&pi->regs->psm_phy_hdr_param, val);
+	}
+
+	write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
+	write_phy_reg(pi, 0x1cf, ci->PHY_BW2);
+	write_phy_reg(pi, 0x1d0, ci->PHY_BW3);
+
+	write_phy_reg(pi, 0x1d1, ci->PHY_BW4);
+	write_phy_reg(pi, 0x1d2, ci->PHY_BW5);
+	write_phy_reg(pi, 0x1d3, ci->PHY_BW6);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en,
+					NPHY_ClassifierCtrl_ofdm_en);
+
+		if (CHSPEC_IS2G(chanspec))
+			and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
+	}
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		wlc_phy_txpwr_fixpower_nphy(pi);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+	}
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)
+	    && (pi->phy_spuravoid != SPURAVOID_DISABLE)) {
+		u8 spuravoid = 0;
+
+		val = CHSPEC_CHANNEL(chanspec);
+		if (!CHSPEC_IS40(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if ((val == 13) || (val == 14) || (val == 153)) {
+					spuravoid = 1;
+				}
+			} else {
+
+				if (((val >= 5) && (val <= 8)) || (val == 13)
+				    || (val == 14)) {
+					spuravoid = 1;
+				}
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if (val == 54) {
+					spuravoid = 1;
+				}
+			} else {
+
+				if (pi->nphy_aband_spurwar_en &&
+				    ((val == 38) || (val == 102)
+				     || (val == 118))) {
+					if ((pi->sh->chip ==
+					     BCM4716_CHIP_ID)
+					    && (pi->sh->chippkg ==
+						BCM4717_PKG_ID)) {
+						spuravoid = 0;
+					} else {
+						spuravoid = 1;
+					}
+				}
+			}
+		}
+
+		if (pi->phy_spuravoid == SPURAVOID_FORCEON)
+			spuravoid = 1;
+
+		if ((pi->sh->chip == BCM4716_CHIP_ID) ||
+		    (pi->sh->chip == BCM47162_CHIP_ID)) {
+			si_pmu_spuravoid(pi->sh->sih, spuravoid);
+		} else {
+			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
+			si_pmu_spuravoid(pi->sh->sih, spuravoid);
+			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
+		}
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID) ||
+		    (pi->sh->chip == BCM43225_CHIP_ID) ||
+		    (pi->sh->chip == BCM43421_CHIP_ID)) {
+
+			if (spuravoid == 1) {
+
+				W_REG(&pi->regs->tsf_clk_frac_l,
+				      0x5341);
+				W_REG(&pi->regs->tsf_clk_frac_h,
+				      0x8);
+			} else {
+
+				W_REG(&pi->regs->tsf_clk_frac_l,
+				      0x8889);
+				W_REG(&pi->regs->tsf_clk_frac_h,
+				      0x8);
+			}
+		}
+
+		if (!((pi->sh->chip == BCM4716_CHIP_ID) ||
+		      (pi->sh->chip == BCM47162_CHIP_ID))) {
+			wlapi_bmac_core_phypll_reset(pi->sh->physhim);
+		}
+
+		mod_phy_reg(pi, 0x01, (0x1 << 15),
+			    ((spuravoid > 0) ? (0x1 << 15) : 0));
+
+		wlc_phy_resetcca_nphy(pi);
+
+		pi->phy_isspuravoid = (spuravoid > 0);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7))
+		write_phy_reg(pi, 0x17e, 0x3830);
+
+	wlc_phy_spurwar_nphy(pi);
+}
+
+void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec)
+{
+	int freq;
+	chan_info_nphy_radio2057_t *t0 = NULL;
+	chan_info_nphy_radio205x_t *t1 = NULL;
+	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
+	chan_info_nphy_2055_t *t3 = NULL;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		return;
+	}
+
+	if (!wlc_phy_chan2freq_nphy
+	    (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
+		return;
+
+	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
+
+	if (CHSPEC_BW(chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec));
+
+	if (CHSPEC_IS40(chanspec)) {
+		if (CHSPEC_SB_UPPER(chanspec)) {
+			or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
+			}
+		} else {
+			and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				and_phy_reg(pi, 0x310,
+					    (~PRIM_SEL_UP20 & 0xffff));
+			}
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+			}
+
+			wlc_phy_chanspec_radio2057_setup(pi, t0, t2);
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+						    (pi->pubpi.radiorev ==
+						     5) ? (const nphy_sfo_cfg_t
+							   *)&(t2->
+							       PHY_BW1a)
+						    : (const nphy_sfo_cfg_t *)
+						    &(t0->PHY_BW1a));
+
+		} else {
+
+			mod_radio_reg(pi,
+				      RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN,
+				      0x4,
+				      (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0));
+			wlc_phy_chanspec_radio2056_setup(pi, t1);
+
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+						    (const nphy_sfo_cfg_t *)
+						    &(t1->PHY_BW1a));
+		}
+
+	} else {
+
+		mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70,
+			      (CHSPEC_IS5G(chanspec) ? (0x02 << 4)
+			       : (0x05 << 4)));
+
+		wlc_phy_chanspec_radio2055_setup(pi, t3);
+		wlc_phy_chanspec_nphy_setup(pi, chanspec,
+					    (const nphy_sfo_cfg_t *)&(t3->
+								      PHY_BW1a));
+	}
+
+}
+
+static void wlc_phy_savecal_nphy(phy_info_t *pi)
+{
+	void *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_2G[4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[6] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[7] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+	} else {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_5G[4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[6] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[7] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			txcal_radio_regs[2 * coreNum] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_FINE_I);
+			txcal_radio_regs[2 * coreNum + 1] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_FINE_Q);
+
+			txcal_radio_regs[2 * coreNum + 4] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_COARSE_I);
+			txcal_radio_regs[2 * coreNum + 5] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_COARSE_Q);
+		}
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_restorecal_nphy(phy_info_t *pi)
+{
+	u16 *loft_comp;
+	u16 txcal_coeffs_bphy[4];
+	u16 *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_iqcal_chanspec_2G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
+	} else {
+		if (pi->nphy_iqcal_chanspec_5G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
+				 (void *)tbl_ptr);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		txcal_coeffs_bphy[0] = tbl_ptr[0];
+		txcal_coeffs_bphy[1] = tbl_ptr[1];
+		txcal_coeffs_bphy[2] = tbl_ptr[2];
+		txcal_coeffs_bphy[3] = tbl_ptr[3];
+	} else {
+		txcal_coeffs_bphy[0] = 0;
+		txcal_coeffs_bphy[1] = 0;
+		txcal_coeffs_bphy[2] = 0;
+		txcal_coeffs_bphy[3] = 0;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
+				 txcal_coeffs_bphy);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		wlc_phy_tx_iq_war_nphy(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_I,
+					 txcal_radio_regs[2 * coreNum]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_Q,
+					 txcal_radio_regs[2 * coreNum + 1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_I,
+					 txcal_radio_regs[2 * coreNum + 4]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_Q,
+					 txcal_radio_regs[2 * coreNum + 5]);
+		}
+	}
+}
+
+void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 mask = 0xfc00;
+	u32 mc = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		return;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188;
+
+		if (lut_init == false)
+			return;
+
+		if (pi->srom_fem2g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x02, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x03, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x08, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x0C, 16, &v3);
+		} else {
+			ASSERT(0);
+		}
+
+		if (pi->srom_fem5g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x12, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x13, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x18, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x1C, 16, &v3);
+		} else {
+			ASSERT(0);
+		}
+	} else {
+
+		write_phy_reg(pi, 0xc8, 0x0);
+		write_phy_reg(pi, 0xc9, 0x0);
+
+		si_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
+
+		mc = R_REG(&pi->regs->maccontrol);
+		mc &= ~MCTL_GPOUT_SEL_MASK;
+		W_REG(&pi->regs->maccontrol, mc);
+
+		OR_REG(&pi->regs->psm_gpio_oe, mask);
+
+		AND_REG(&pi->regs->psm_gpio_out, ~mask);
+
+		if (lut_init) {
+			write_phy_reg(pi, 0xf8, 0x02d8);
+			write_phy_reg(pi, 0xf9, 0x0301);
+			write_phy_reg(pi, 0xfa, 0x02d8);
+			write_phy_reg(pi, 0xfb, 0x0301);
+		}
+	}
+}
+
+u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val)
+{
+	u16 curr_ctl, new_ctl;
+	bool suspended = false;
+
+	if (D11REV_IS(pi->sh->corerev, 16)) {
+		suspended =
+		    (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
+		    false : true;
+		if (!suspended)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0);
+
+	new_ctl = (curr_ctl & (~mask)) | (val & mask);
+
+	mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl);
+
+	if (D11REV_IS(pi->sh->corerev, 16) && !suspended)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return new_ctl;
+}
+
+static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals)
+{
+
+	if (write == 0) {
+		vals[0] = read_phy_reg(pi, 0x2c);
+		vals[1] = read_phy_reg(pi, 0x42);
+	} else {
+		write_phy_reg(pi, 0x2c, vals[0]);
+		write_phy_reg(pi, 0x42, vals[1]);
+	}
+}
+
+void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd)
+{
+	u16 trigger_mask, status_mask;
+	u16 orig_RfseqCoreActv;
+
+	switch (cmd) {
+	case NPHY_RFSEQ_RX2TX:
+		trigger_mask = NPHY_RfseqTrigger_rx2tx;
+		status_mask = NPHY_RfseqStatus_rx2tx;
+		break;
+	case NPHY_RFSEQ_TX2RX:
+		trigger_mask = NPHY_RfseqTrigger_tx2rx;
+		status_mask = NPHY_RfseqStatus_tx2rx;
+		break;
+	case NPHY_RFSEQ_RESET2RX:
+		trigger_mask = NPHY_RfseqTrigger_reset2rx;
+		status_mask = NPHY_RfseqStatus_reset2rx;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINH:
+		trigger_mask = NPHY_RfseqTrigger_updategainh;
+		status_mask = NPHY_RfseqStatus_updategainh;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINL:
+		trigger_mask = NPHY_RfseqTrigger_updategainl;
+		status_mask = NPHY_RfseqStatus_updategainl;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINU:
+		trigger_mask = NPHY_RfseqTrigger_updategainu;
+		status_mask = NPHY_RfseqStatus_updategainu;
+		break;
+	default:
+		return;
+	}
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1,
+		   (NPHY_RfseqMode_CoreActv_override |
+		    NPHY_RfseqMode_Trigger_override));
+	or_phy_reg(pi, 0xa3, trigger_mask);
+	SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000);
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+
+	ASSERT((read_phy_reg(pi, 0xa4) & status_mask) == 0);
+}
+
+static void
+wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *events, u8 *dlys,
+		       u8 len)
+{
+	u32 t1_offset, t2_offset;
+	u8 ctr;
+	u8 end_event =
+	    NREV_GE(pi->pubpi.phy_rev,
+		    3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
+	u8 end_dly = 1;
+
+	ASSERT(len <= 16);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	t1_offset = cmd << 4;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
+				 events);
+	t2_offset = t1_offset + 0x080;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
+				 dlys);
+
+	for (ctr = len; ctr < 16; ctr++) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t1_offset + ctr, 8, &end_event);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t2_offset + ctr, 8, &end_dly);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset)
+{
+	u16 lpf_bw_ctl_val = 0;
+	u16 rx2tx_lpf_rc_lut_offset = 0;
+
+	if (offset == 0) {
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			rx2tx_lpf_rc_lut_offset = 0x159;
+		} else {
+			rx2tx_lpf_rc_lut_offset = 0x154;
+		}
+	} else {
+		rx2tx_lpf_rc_lut_offset = offset;
+	}
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+				(u32) rx2tx_lpf_rc_lut_offset, 16,
+				&lpf_bw_ctl_val);
+
+	lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
+
+	return lpf_bw_ctl_val;
+}
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off, u8 override_id)
+{
+	u8 core_num;
+	u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
+	u8 val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+			if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
+
+				switch (field) {
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 7):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 7);
+					val_shift = 7;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0xf8 :
+					    0xfa;
+					val_mask = (0x7 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7b :
+					    0x7e;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 12):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7c :
+					    0x7f;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x3 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+					    0x349;
+					val_mask = (0xff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+					    0x349;
+					val_mask = (0xf << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
+
+				switch (field) {
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 2):
+
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 7):
+
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x7 << 8);
+					val_shift = 8;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 14);
+					val_shift = 14;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 13);
+					val_shift = 13;
+					break;
+				case (0x1 << 9):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 12);
+					val_shift = 12;
+					break;
+				case (0x1 << 8):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 11);
+					val_shift = 11;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
+
+				switch (field) {
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff) {
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+					}
+				}
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_nphy(phy_info_t *pi, u16 field, u16 value,
+			     u8 core_mask, u8 off)
+{
+	u8 core_num;
+	u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
+	    0, val_mask = 0;
+	u8 shift = 0, val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 2):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 1);
+				val_shift = 1;
+				break;
+			case (0x1 << 3):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 2);
+				val_shift = 2;
+				break;
+			case (0x1 << 4):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 4);
+				val_shift = 4;
+				break;
+			case (0x1 << 5):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 5);
+				val_shift = 5;
+				break;
+			case (0x1 << 6):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 7):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 7);
+				val_shift = 7;
+				break;
+			case (0x1 << 8):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 8);
+				val_shift = 8;
+				break;
+			case (0x1 << 11):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 13);
+				val_shift = 13;
+				break;
+
+			case (0x1 << 9):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 0);
+				val_shift = 0;
+				break;
+
+			case (0x1 << 10):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 4);
+				val_shift = 4;
+				break;
+
+			case (0x1 << 12):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7b : 0x7e;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 13):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7c : 0x7f;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 14):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x3 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 0):
+				en_addr = (core_num == 0) ? 0xe5 : 0xe6;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x1 << 15);
+				val_shift = 15;
+				break;
+			default:
+				addr = 0xffff;
+				break;
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff) {
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+					}
+				}
+			}
+		}
+	} else {
+
+		if (off) {
+			and_phy_reg(pi, 0xec, ~field);
+			value = 0x0;
+		} else {
+			or_phy_reg(pi, 0xec, field);
+		}
+
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+			case (0x1 << 9):
+			case (0x1 << 12):
+			case (0x1 << 13):
+			case (0x1 << 14):
+				addr = 0x78;
+
+				core_mask = 0x1;
+				break;
+			case (0x1 << 2):
+			case (0x1 << 3):
+			case (0x1 << 4):
+			case (0x1 << 5):
+			case (0x1 << 6):
+			case (0x1 << 7):
+			case (0x1 << 8):
+				addr = (core_num == 0) ? 0x7a : 0x7d;
+				break;
+			case (0x1 << 10):
+				addr = (core_num == 0) ? 0x7b : 0x7e;
+				break;
+			case (0x1 << 11):
+				addr = (core_num == 0) ? 0x7c : 0x7f;
+				break;
+			default:
+				addr = 0xffff;
+			}
+
+			switch (field) {
+			case (0x1 << 1):
+				mask = (0x7 << 3);
+				shift = 3;
+				break;
+			case (0x1 << 9):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 12):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 13):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 14):
+				mask = (0xf << 12);
+				shift = 12;
+				break;
+			case (0x1 << 2):
+				mask = (0x1 << 0);
+				shift = 0;
+				break;
+			case (0x1 << 3):
+				mask = (0x1 << 1);
+				shift = 1;
+				break;
+			case (0x1 << 4):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 5):
+				mask = (0x3 << 4);
+				shift = 4;
+				break;
+			case (0x1 << 6):
+				mask = (0x3 << 6);
+				shift = 6;
+				break;
+			case (0x1 << 7):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 8):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 10):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			case (0x1 << 11):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			default:
+				mask = 0x0;
+				shift = 0x0;
+				break;
+			}
+
+			if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
+				mod_phy_reg(pi, addr, mask, (value << shift));
+			}
+		}
+
+		or_phy_reg(pi, 0xec, (0x1 << 0));
+		or_phy_reg(pi, 0x78, (0x1 << 0));
+		udelay(1);
+		and_phy_reg(pi, 0xec, ~(0x1 << 0));
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_1tomany_nphy(phy_info_t *pi, u16 cmd, u16 value,
+				     u8 core_mask, u8 off)
+{
+	u16 rfmxgain = 0, lpfgain = 0;
+	u16 tgain = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		switch (cmd) {
+		case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rxgain:
+			rfmxgain = value & 0x000ff;
+			lpfgain = value & 0x0ff00;
+			lpfgain = lpfgain >> 8;
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+							  rfmxgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
+							  lpfgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_txgain:
+			tgain = value & 0x7fff;
+			lpfgain = value & 0x8000;
+			lpfgain = lpfgain >> 14;
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+							  tgain, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
+							  lpfgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		}
+	}
+}
+
+static void
+wlc_phy_scale_offset_rssi_nphy(phy_info_t *pi, u16 scale, s8 offset,
+			       u8 coresel, u8 rail, u8 rssi_type)
+{
+	u16 valuetostuff;
+
+	offset = (offset > NPHY_RSSICAL_MAXREAD) ?
+	    NPHY_RSSICAL_MAXREAD : offset;
+	offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
+	    -NPHY_RSSICAL_MAXREAD - 1 : offset;
+
+	valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1a6, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1ac, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1b2, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1b8, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1a4, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1aa, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1b0, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1b6, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1a5, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1ab, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1b1, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1b7, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1a7, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1ad, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1b3, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1b9, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1a8, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1ae, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1b4, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1ba, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+		write_phy_reg(pi, 0x1a9, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+		write_phy_reg(pi, 0x1b5, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+		write_phy_reg(pi, 0x1af, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+		write_phy_reg(pi, 0x1bb, valuetostuff);
+	}
+}
+
+void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core_code, u8 rssi_type)
+{
+	u16 mask, val;
+	u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val,
+	    startseq;
+	u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val,
+	    rfctrlovr_trigger_val;
+	u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask;
+	u16 rfctrlcmd_val, rfctrlovr_val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			mod_phy_reg(pi, 0x8f, (0x1 << 9), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 9), 0);
+
+			mod_phy_reg(pi, 0xa6, (0x3 << 8), 0);
+			mod_phy_reg(pi, 0xa7, (0x3 << 8), 0);
+
+			mod_phy_reg(pi, 0xe5, (0x1 << 5), 0);
+			mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
+
+			mask = (0x1 << 2) |
+			    (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
+			mod_phy_reg(pi, 0xf9, mask, 0);
+			mod_phy_reg(pi, 0xfb, mask, 0);
+
+		} else {
+			for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+				if (core_code == RADIO_MIMO_CORESEL_CORE1
+				    && core == PHY_CORE_1)
+					continue;
+				else if (core_code == RADIO_MIMO_CORESEL_CORE2
+					 && core == PHY_CORE_0)
+					continue;
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ?
+					    0x8f : 0xa5, (0x1 << 9), 1 << 9);
+
+				if (rssi_type == NPHY_RSSI_SEL_W1 ||
+				    rssi_type == NPHY_RSSI_SEL_W2 ||
+				    rssi_type == NPHY_RSSI_SEL_NB) {
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xa6 : 0xa7,
+						    (0x3 << 8), 0);
+
+					mask = (0x1 << 2) |
+					    (0x1 << 3) |
+					    (0x1 << 4) | (0x1 << 5);
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, 0);
+
+					if (rssi_type == NPHY_RSSI_SEL_W1) {
+						if (CHSPEC_IS5G
+						    (pi->radio_chanspec)) {
+							mask = (0x1 << 2);
+							val = 1 << 2;
+						} else {
+							mask = (0x1 << 3);
+							val = 1 << 3;
+						}
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_W2) {
+						mask = (0x1 << 4);
+						val = 1 << 4;
+					} else {
+						mask = (0x1 << 5);
+						val = 1 << 5;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, val);
+
+					mask = (0x1 << 5);
+					val = 1 << 5;
+					mod_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xe5 : 0xe6, mask, val);
+				} else {
+					if (rssi_type == NPHY_RSSI_SEL_TBD) {
+
+						mask = (0x3 << 8);
+						val = 1 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 1 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_IQ) {
+
+						mask = (0x3 << 8);
+						val = 2 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 2 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else {
+
+						mask = (0x3 << 8);
+						val = 3 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 3 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+
+						if (PHY_IPA(pi)) {
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     7)) {
+
+								write_radio_reg
+								    (pi,
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2057_TX0_TX_SSI_MUX
+								      :
+								      RADIO_2057_TX1_TX_SSI_MUX),
+								     (CHSPEC_IS5G
+								      (pi->
+								       radio_chanspec)
+								      ? 0xc :
+								      0xe));
+							} else {
+								write_radio_reg
+								    (pi,
+								     RADIO_2056_TX_TX_SSI_MUX
+								     |
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2056_TX0
+								      :
+								      RADIO_2056_TX1),
+								     (CHSPEC_IS5G
+								      (pi->
+								       radio_chanspec)
+								      ? 0xc :
+								      0xe));
+							}
+						} else {
+
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     7)) {
+								write_radio_reg
+								    (pi,
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2057_TX0_TX_SSI_MUX
+								      :
+								      RADIO_2057_TX1_TX_SSI_MUX),
+								     0x11);
+
+								if (pi->pubpi.
+								    radioid ==
+								    BCM2057_ID)
+									write_radio_reg
+									    (pi,
+									     RADIO_2057_IQTEST_SEL_PU,
+									     0x1);
+
+							} else {
+								write_radio_reg
+								    (pi,
+								     RADIO_2056_TX_TX_SSI_MUX
+								     |
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2056_TX0
+								      :
+								      RADIO_2056_TX1),
+								     0x11);
+							}
+						}
+
+						afectrlovr_rssi_val = 1 << 9;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x8f
+							    : 0xa5, (0x1 << 9),
+							    afectrlovr_rssi_val);
+					}
+				}
+			}
+		}
+	} else {
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+
+			val = 0x0;
+		} else if (rssi_type == NPHY_RSSI_SEL_TBD) {
+
+			val = 0x1;
+		} else if (rssi_type == NPHY_RSSI_SEL_IQ) {
+
+			val = 0x2;
+		} else {
+
+			val = 0x3;
+		}
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (val << 12) | (val << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			if (rssi_type == NPHY_RSSI_SEL_W1) {
+				val = 0x1;
+			}
+			if (rssi_type == NPHY_RSSI_SEL_W2) {
+				val = 0x2;
+			}
+			if (rssi_type == NPHY_RSSI_SEL_NB) {
+				val = 0x3;
+			}
+			mask = (0x3 << 4);
+			val = (val << 4);
+			mod_phy_reg(pi, 0x7a, mask, val);
+			mod_phy_reg(pi, 0x7d, mask, val);
+		}
+
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			afectrlovr_rssi_val = 0;
+			rfctrlcmd_rxen_val = 0;
+			rfctrlcmd_coresel_val = 0;
+			rfctrlovr_rssi_val = 0;
+			rfctrlovr_rxen_val = 0;
+			rfctrlovr_coresel_val = 0;
+			rfctrlovr_trigger_val = 0;
+			startseq = 0;
+		} else {
+			afectrlovr_rssi_val = 1;
+			rfctrlcmd_rxen_val = 1;
+			rfctrlcmd_coresel_val = core_code;
+			rfctrlovr_rssi_val = 1;
+			rfctrlovr_rxen_val = 1;
+			rfctrlovr_coresel_val = 1;
+			rfctrlovr_trigger_val = 1;
+			startseq = 1;
+		}
+
+		afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13));
+		afectrlovr_rssi_val = (afectrlovr_rssi_val <<
+				       12) | (afectrlovr_rssi_val << 13);
+		mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask,
+			    afectrlovr_rssi_val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
+			rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
+			    (rfctrlcmd_coresel_val << 3);
+
+			rfctrlovr_mask = ((0x1 << 5) |
+					  (0x1 << 12) |
+					  (0x1 << 1) | (0x1 << 0));
+			rfctrlovr_val = (rfctrlovr_rssi_val <<
+					 5) |
+			    (rfctrlovr_rxen_val << 12) |
+			    (rfctrlovr_coresel_val << 1) |
+			    (rfctrlovr_trigger_val << 0);
+
+			mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
+			mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
+
+			mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0));
+			udelay(20);
+
+			mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+		}
+	}
+}
+
+int
+wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type, s32 *rssi_buf,
+		       u8 nsamps)
+{
+	s16 rssi0, rssi1;
+	u16 afectrlCore1_save = 0;
+	u16 afectrlCore2_save = 0;
+	u16 afectrlOverride1_save = 0;
+	u16 afectrlOverride2_save = 0;
+	u16 rfctrlOverrideAux0_save = 0;
+	u16 rfctrlOverrideAux1_save = 0;
+	u16 rfctrlMiscReg1_save = 0;
+	u16 rfctrlMiscReg2_save = 0;
+	u16 rfctrlcmd_save = 0;
+	u16 rfctrloverride_save = 0;
+	u16 rfctrlrssiothers1_save = 0;
+	u16 rfctrlrssiothers2_save = 0;
+	s8 tmp_buf[4];
+	u8 ctr = 0, samp = 0;
+	s32 rssi_out_val;
+	u16 gpiosel_orig;
+
+	afectrlCore1_save = read_phy_reg(pi, 0xa6);
+	afectrlCore2_save = read_phy_reg(pi, 0xa7);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+		rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+		afectrlOverride1_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+		rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	} else {
+		afectrlOverride1_save = read_phy_reg(pi, 0xa5);
+		rfctrlcmd_save = read_phy_reg(pi, 0x78);
+		rfctrloverride_save = read_phy_reg(pi, 0xec);
+		rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a);
+		rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	gpiosel_orig = read_phy_reg(pi, 0xca);
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0xca, 5);
+	}
+
+	for (ctr = 0; ctr < 4; ctr++) {
+		rssi_buf[ctr] = 0;
+	}
+
+	for (samp = 0; samp < nsamps; samp++) {
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			rssi0 = read_phy_reg(pi, 0x1c9);
+			rssi1 = read_phy_reg(pi, 0x1ca);
+		} else {
+			rssi0 = read_phy_reg(pi, 0x219);
+			rssi1 = read_phy_reg(pi, 0x21a);
+		}
+
+		ctr = 0;
+		tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
+
+		for (ctr = 0; ctr < 4; ctr++) {
+			rssi_buf[ctr] += tmp_buf[ctr];
+		}
+
+	}
+
+	rssi_out_val = rssi_buf[3] & 0xff;
+	rssi_out_val |= (rssi_buf[2] & 0xff) << 8;
+	rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
+	rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0xca, gpiosel_orig);
+	}
+
+	write_phy_reg(pi, 0xa6, afectrlCore1_save);
+	write_phy_reg(pi, 0xa7, afectrlCore2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save);
+		write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride1_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save);
+		write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save);
+	} else {
+		write_phy_reg(pi, 0xa5, afectrlOverride1_save);
+		write_phy_reg(pi, 0x78, rfctrlcmd_save);
+		write_phy_reg(pi, 0xec, rfctrloverride_save);
+		write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save);
+		write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save);
+	}
+
+	return rssi_out_val;
+}
+
+s16 wlc_phy_tempsense_nphy(phy_info_t *pi)
+{
+	u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save;
+	u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save;
+	u16 pwrdet_rxtx_core1_save;
+	u16 pwrdet_rxtx_core2_save;
+	u16 afectrlCore1_save;
+	u16 afectrlCore2_save;
+	u16 afectrlOverride_save;
+	u16 afectrlOverride2_save;
+	u16 pd_pll_ts_save;
+	u16 gpioSel_save;
+	s32 radio_temp[4];
+	s32 radio_temp2[4];
+	u16 syn_tempprocsense_save;
+	s16 offset = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save;
+		u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save;
+		u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH;
+		s32 auxADC_Vl;
+		u16 RfctrlOverride5_save, RfctrlOverride6_save;
+		u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save;
+		u16 RSSIMultCoef0QPowerDet_save;
+		u16 tempsense_Rcal;
+
+		syn_tempprocsense_save =
+		    read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae);
+		RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+		RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					&auxADC_Vmid_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					&auxADC_Av_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					&auxADC_rssi_ctrlL_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					&auxADC_rssi_ctrlH_save);
+
+		write_phy_reg(pi, 0x1ae, 0x0);
+
+		auxADC_rssi_ctrlL = 0x0;
+		auxADC_rssi_ctrlH = 0x20;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH);
+
+		tempsense_Rcal = syn_tempprocsense_save & 0x1c;
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		mod_phy_reg(pi, 0xa6, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7));
+		mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7));
+
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+		udelay(5);
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa6, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa6, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6));
+		mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6));
+
+		auxADC_Vmid = 0xA3;
+		auxADC_Av = 0x0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x03);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+
+		auxADC_Av = 0x7;
+		if (radio_temp[1] + radio_temp2[1] < -30) {
+			auxADC_Vmid = 0x45;
+			auxADC_Vl = 263;
+		} else if (radio_temp[1] + radio_temp2[1] < -9) {
+			auxADC_Vmid = 0x200;
+			auxADC_Vl = 467;
+		} else if (radio_temp[1] + radio_temp2[1] < 11) {
+			auxADC_Vmid = 0x266;
+			auxADC_Vl = 634;
+		} else {
+			auxADC_Vmid = 0x2D5;
+			auxADC_Vl = 816;
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save);
+		write_phy_reg(pi, 0x346, RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, RfctrlOverride6_save);
+		write_phy_reg(pi, 0x344, RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, RfctrlMiscReg5_save);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH_save);
+
+		if (pi->sh->chip == BCM5357_CHIP_ID) {
+			radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
+					 + 88 * (auxADC_Vl) - 27111 +
+					 128) / 256;
+		} else if (pi->sh->chip == BCM43236_CHIP_ID) {
+			radio_temp[0] = (198 * (radio_temp[1] + radio_temp2[1])
+					 + 91 * (auxADC_Vl) - 27243 +
+					 128) / 256;
+		} else {
+			radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
+					 + 82 * (auxADC_Vl) - 28861 +
+					 128) / 256;
+		}
+
+		offset = (s16) pi->phy_tempsense_offset;
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		syn_tempprocsense_save =
+		    read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		} else {
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
+		}
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
+		} else {
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+		}
+
+		radio_temp[0] =
+		    (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+
+		offset = (s16) pi->phy_tempsense_offset;
+	} else {
+
+		pwrdet_rxtx_core1_save =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pwrdet_rxtx_core2_save =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+		core1_txrf_iqcal1_save =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		core1_txrf_iqcal2_save =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		core2_txrf_iqcal1_save =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		core2_txrf_iqcal2_save =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		radio_temp[0] = (radio_temp[0] + radio_temp2[0]);
+		radio_temp[1] = (radio_temp[1] + radio_temp2[1]);
+		radio_temp[2] = (radio_temp[2] + radio_temp2[2]);
+		radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
+
+		radio_temp[0] =
+		    (radio_temp[0] + radio_temp[1] + radio_temp[2] +
+		     radio_temp[3]);
+
+		radio_temp[0] =
+		    (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
+
+		radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
+
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pwrdet_rxtx_core1_save);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pwrdet_rxtx_core2_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				core1_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				core2_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				core1_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				core2_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride_save);
+	}
+
+	return (s16) radio_temp[0] + offset;
+}
+
+static void
+wlc_phy_set_rssi_2055_vcm(phy_info_t *pi, u8 rssi_type, u8 *vcm_buf)
+{
+	u8 core;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (rssi_type == NPHY_RSSI_SEL_NB) {
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			}
+		} else {
+
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			}
+		}
+	}
+}
+
+void wlc_phy_rssi_cal_nphy(phy_info_t *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		wlc_phy_rssi_cal_nphy_rev3(pi);
+	} else {
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type)
+{
+	s32 target_code;
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 rssi_ctrl_state[2], pd_state[2];
+	u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
+	u16 rfctrlintc_override_val;
+	u16 clip_off[] = { 0xffff, 0xffff };
+	u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
+	u8 vcm, min_vcm, vcm_tmp[4];
+	u8 vcm_final[4] = { 0, 0, 0, 0 };
+	u8 result_idx, ctr;
+	s32 poll_results[4][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_miniq[4][2] = {
+		{0, 0},
+		{0, 0},
+		{0, 0},
+		{0, 0}
+	};
+	s32 min_d, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+
+	switch (rssi_type) {
+	case NPHY_RSSI_SEL_NB:
+		target_code = NPHY_RSSICAL_NB_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W1:
+		target_code = NPHY_RSSICAL_W1_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W2:
+		target_code = NPHY_RSSICAL_W2_TARGET;
+		break;
+	default:
+		return;
+		break;
+	}
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
+	rfctrlintc_override_val =
+	    CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
+
+	rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
+	rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
+	write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
+
+	rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
+	rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
+	write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
+
+	pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
+	    RADIO_2055_WBRSSI_G2_PD;
+	pd_state[0] =
+	    read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
+	pd_state[1] =
+	    read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
+	rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
+	    RADIO_2055_WBRSSI_G2_SEL;
+	rssi_ctrl_state[0] =
+	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
+	rssi_ctrl_state[1] =
+	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_I, rssi_type);
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_Q, rssi_type);
+
+	for (vcm = 0; vcm < 4; vcm++) {
+
+		vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
+		if (rssi_type != NPHY_RSSI_SEL_W2) {
+			wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
+		}
+
+		wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
+				       NPHY_RSSICAL_NPOLL);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1)
+		    || (rssi_type == NPHY_RSSI_SEL_W2)) {
+			for (ctr = 0; ctr < 2; ctr++) {
+				poll_miniq[vcm][ctr] =
+				    min(poll_results[vcm][ctr * 2 + 0],
+					poll_results[vcm][ctr * 2 + 1]);
+			}
+		}
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		min_d = NPHY_RSSICAL_MAXD;
+		min_vcm = 0;
+		min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
+		for (vcm = 0; vcm < 4; vcm++) {
+			curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
+				      poll_results[vcm][result_idx] :
+				      poll_miniq[vcm][result_idx / 2]) -
+				     (target_code * NPHY_RSSICAL_NPOLL));
+			if (curr_d < min_d) {
+				min_d = curr_d;
+				min_vcm = vcm;
+			}
+			if (poll_results[vcm][result_idx] < min_poll) {
+				min_poll = poll_results[vcm][result_idx];
+			}
+		}
+		vcm_final[result_idx] = min_vcm;
+		poll_results_min[result_idx] = min_poll;
+	}
+
+	if (rssi_type != NPHY_RSSI_SEL_W2) {
+		wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		fine_digital_offset[result_idx] =
+		    (target_code * NPHY_RSSICAL_NPOLL) -
+		    poll_results[vcm_final[result_idx]][result_idx];
+		if (fine_digital_offset[result_idx] < 0) {
+			fine_digital_offset[result_idx] =
+			    ABS(fine_digital_offset[result_idx]);
+			fine_digital_offset[result_idx] +=
+			    (NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+			fine_digital_offset[result_idx] =
+			    -fine_digital_offset[result_idx];
+		} else {
+			fine_digital_offset[result_idx] +=
+			    (NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+		}
+
+		if (poll_results_min[result_idx] ==
+		    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+			fine_digital_offset[result_idx] =
+			    (target_code - NPHY_RSSICAL_MAXREAD - 1);
+		}
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+					       (s8)
+					       fine_digital_offset[result_idx],
+					       (result_idx / 2 ==
+						0) ? RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       (result_idx % 2 ==
+						0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
+					       rssi_type);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
+	if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_NB);
+	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W1);
+	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	} else {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	}
+	if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_NB);
+	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W1);
+	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	} else {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
+
+	write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
+	write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+
+	wlc_phy_resetcca_nphy(pi);
+}
+
+int BCMFASTPATH
+wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh)
+{
+	d11rxhdr_t *rxh = &wlc_rxh->rxhdr;
+	s16 rxpwr, rxpwr0, rxpwr1;
+	s16 phyRx0_l, phyRx2_l;
+
+	rxpwr = 0;
+	rxpwr0 = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
+	rxpwr1 = (le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
+
+	if (rxpwr0 > 127)
+		rxpwr0 -= 256;
+	if (rxpwr1 > 127)
+		rxpwr1 -= 256;
+
+	phyRx0_l = le16_to_cpu(rxh->PhyRxStatus_0) & 0x00ff;
+	phyRx2_l = le16_to_cpu(rxh->PhyRxStatus_2) & 0x00ff;
+	if (phyRx2_l > 127)
+		phyRx2_l -= 256;
+
+	if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
+		rxpwr0 = rxpwr1;
+		rxpwr1 = phyRx2_l;
+	}
+
+	wlc_rxh->rxpwr[0] = (s8) rxpwr0;
+	wlc_rxh->rxpwr[1] = (s8) rxpwr1;
+	wlc_rxh->do_rssi_ma = 0;
+
+	if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
+		rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
+		rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
+		rxpwr = (rxpwr0 + rxpwr1) >> 1;
+	else
+		ASSERT(0);
+
+	return rxpwr;
+}
+
+static void
+wlc_phy_rfctrlintc_override_nphy(phy_info_t *pi, u8 field, u16 value,
+				 u8 core_code)
+{
+	u16 mask;
+	u16 val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (core_code == RADIO_MIMO_CORESEL_CORE1
+			    && core == PHY_CORE_1)
+				continue;
+			else if (core_code == RADIO_MIMO_CORESEL_CORE2
+				 && core == PHY_CORE_0)
+				continue;
+
+			if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+				mask = (0x1 << 10);
+				val = 1 << 10;
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					    0x92, mask, val);
+			}
+
+			if (field == NPHY_RfctrlIntc_override_OFF) {
+
+				write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					      0x92, 0);
+
+				wlc_phy_force_rfseq_nphy(pi,
+							 NPHY_RFSEQ_RESET2RX);
+			} else if (field == NPHY_RfctrlIntc_override_TRSW) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 6) | (0x1 << 7);
+
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 10));
+
+					and_phy_reg(pi, 0x2ff, (u16)
+						    ~(0x3 << 14));
+					or_phy_reg(pi, 0x2ff, (0x1 << 13));
+					or_phy_reg(pi, 0x2ff, (0x1 << 0));
+				} else {
+
+					mask = (0x1 << 6) |
+					    (0x1 << 7) |
+					    (0x1 << 8) | (0x1 << 9);
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					mask = (0x1 << 0);
+					val = 1 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+
+					mask = (core == PHY_CORE_0) ? (0x1 << 0)
+					    : (0x1 << 1);
+					val = 1 << ((core == PHY_CORE_0) ?
+						    0 : 1);
+					mod_phy_reg(pi, 0x78, mask, val);
+
+					SPINWAIT(((read_phy_reg(pi, 0x78) & val)
+						  != 0), 10000);
+					ASSERT((read_phy_reg(pi, 0x78) & val) ==
+					       0);
+
+					mask = (0x1 << 0);
+					val = 0 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_PA) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 4) | (0x1 << 5);
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						val = value << 5;
+					} else {
+						val = value << 4;
+					}
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 12));
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 5);
+						val = value << 5;
+					} else {
+						mask = (0x1 << 4);
+						val = value << 4;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 0);
+						val = value << 0;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 2);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 2);
+						val = value << 2;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 0);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 0);
+						val = value << 0;
+					} else {
+						mask = (0x1 << 2);
+						val = value << 2;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field ==
+				   NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 1);
+						val = value << 1;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 3);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 3);
+						val = value << 3;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 1);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 1);
+						val = value << 1;
+					} else {
+						mask = (0x1 << 3);
+						val = value << 3;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			}
+		}
+	} else {
+		return;
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi)
+{
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 clip_off[] = { 0xffff, 0xffff };
+	s32 target_code;
+	u8 vcm, min_vcm;
+	u8 vcm_final = 0;
+	u8 result_idx;
+	s32 poll_results[8][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_result_core[4] = { 0, 0, 0, 0 };
+	s32 min_d = NPHY_RSSICAL_MAXD, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+	u8 vcm_level_max;
+	u8 core;
+	u8 wb_cnt;
+	u8 rssi_type;
+	u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save;
+	u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save;
+	u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save;
+	u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save;
+	u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save;
+	u16 NPHY_RfctrlCmd_save;
+	u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save;
+	u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save;
+	u8 rxcore_state;
+	u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save;
+	u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save;
+	u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
+	u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
+
+	NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
+	    NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
+	    NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
+	    NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91);
+	NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92);
+	NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f);
+	NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5);
+	NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6);
+	NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7);
+	NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7);
+	NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342);
+		NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343);
+		NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+	}
+	NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+	NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78);
+	NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+	NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340);
+		NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341);
+		NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+	}
+	NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a);
+	NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d);
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
+						     0, 0, 0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rx_pu,
+						     1, 0, 0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0);
+	}
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
+							  0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
+		}
+
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
+							  0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
+		}
+	}
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
+
+	vcm_level_max = 8;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_I, NPHY_RSSI_SEL_NB);
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
+
+		for (vcm = 0; vcm < vcm_level_max; vcm++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, (core == PHY_CORE_0) ?
+					      RADIO_2057_NB_MASTER_CORE0 :
+					      RADIO_2057_NB_MASTER_CORE1,
+					      RADIO_2057_VCM_MASK, vcm);
+			} else {
+
+				mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+					      ((core ==
+						PHY_CORE_0) ? RADIO_2056_RX0 :
+					       RADIO_2056_RX1),
+					      RADIO_2056_VCM_MASK,
+					      vcm << RADIO_2056_RSSI_VCM_SHIFT);
+			}
+
+			wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
+					       &poll_results[vcm][0],
+					       NPHY_RSSICAL_NPOLL);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
+
+				min_d = NPHY_RSSICAL_MAXD;
+				min_vcm = 0;
+				min_poll =
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
+				    1;
+				for (vcm = 0; vcm < vcm_level_max; vcm++) {
+					curr_d = poll_results[vcm][result_idx] *
+					    poll_results[vcm][result_idx] +
+					    poll_results[vcm][result_idx + 1] *
+					    poll_results[vcm][result_idx + 1];
+					if (curr_d < min_d) {
+						min_d = curr_d;
+						min_vcm = vcm;
+					}
+					if (poll_results[vcm][result_idx] <
+					    min_poll) {
+						min_poll =
+						    poll_results[vcm]
+						    [result_idx];
+					}
+				}
+				vcm_final = min_vcm;
+				poll_results_min[result_idx] = min_poll;
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, (core == PHY_CORE_0) ?
+				      RADIO_2057_NB_MASTER_CORE0 :
+				      RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK, vcm_final);
+		} else {
+			mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+				      ((core ==
+					PHY_CORE_0) ? RADIO_2056_RX0 :
+				       RADIO_2056_RX1), RADIO_2056_VCM_MASK,
+				      vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if (core == result_idx / 2) {
+				fine_digital_offset[result_idx] =
+				    (NPHY_RSSICAL_NB_TARGET *
+				     NPHY_RSSICAL_NPOLL) -
+				    poll_results[vcm_final][result_idx];
+				if (fine_digital_offset[result_idx] < 0) {
+					fine_digital_offset[result_idx] =
+					    ABS(fine_digital_offset
+						[result_idx]);
+					fine_digital_offset[result_idx] +=
+					    (NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+					    NPHY_RSSICAL_NPOLL;
+					fine_digital_offset[result_idx] =
+					    -fine_digital_offset[result_idx];
+				} else {
+					fine_digital_offset[result_idx] +=
+					    (NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+					    NPHY_RSSICAL_NPOLL;
+				}
+
+				if (poll_results_min[result_idx] ==
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+					fine_digital_offset[result_idx] =
+					    (NPHY_RSSICAL_NB_TARGET -
+					     NPHY_RSSICAL_MAXREAD - 1);
+				}
+
+				wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+							       (s8)
+							       fine_digital_offset
+							       [result_idx],
+							       (result_idx /
+								2 ==
+								0) ?
+							       RADIO_MIMO_CORESEL_CORE1
+							       :
+							       RADIO_MIMO_CORESEL_CORE2,
+							       (result_idx %
+								2 ==
+								0) ? NPHY_RAIL_I
+							       : NPHY_RAIL_Q,
+							       NPHY_RSSI_SEL_NB);
+			}
+		}
+
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) {
+			if (wb_cnt == 0) {
+				rssi_type = NPHY_RSSI_SEL_W1;
+				target_code = NPHY_RSSICAL_W1_TARGET_REV3;
+			} else {
+				rssi_type = NPHY_RSSI_SEL_W2;
+				target_code = NPHY_RSSICAL_W2_TARGET_REV3;
+			}
+
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_I, rssi_type);
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_Q, rssi_type);
+
+			wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core,
+					       NPHY_RSSICAL_NPOLL);
+
+			for (result_idx = 0; result_idx < 4; result_idx++) {
+				if (core == result_idx / 2) {
+					fine_digital_offset[result_idx] =
+					    (target_code * NPHY_RSSICAL_NPOLL) -
+					    poll_result_core[result_idx];
+					if (fine_digital_offset[result_idx] < 0) {
+						fine_digital_offset[result_idx]
+						    =
+						    ABS(fine_digital_offset
+							[result_idx]);
+						fine_digital_offset[result_idx]
+						    += (NPHY_RSSICAL_NPOLL / 2);
+						fine_digital_offset[result_idx]
+						    /= NPHY_RSSICAL_NPOLL;
+						fine_digital_offset[result_idx]
+						    =
+						    -fine_digital_offset
+						    [result_idx];
+					} else {
+						fine_digital_offset[result_idx]
+						    += (NPHY_RSSICAL_NPOLL / 2);
+						fine_digital_offset[result_idx]
+						    /= NPHY_RSSICAL_NPOLL;
+					}
+
+					wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+								       (s8)
+								       fine_digital_offset
+								       [core *
+									2],
+								       (core ==
+									PHY_CORE_0)
+								       ?
+								       RADIO_MIMO_CORESEL_CORE1
+								       :
+								       RADIO_MIMO_CORESEL_CORE2,
+								       (result_idx
+									% 2 ==
+									0) ?
+								       NPHY_RAIL_I
+								       :
+								       NPHY_RAIL_Q,
+								       rssi_type);
+				}
+			}
+
+		}
+	}
+
+	write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save);
+	write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 0);
+
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+
+	write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save);
+	write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save);
+	write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save);
+	write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save);
+	write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save);
+	write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save);
+		write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save);
+		write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save);
+	}
+	write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save);
+	write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save);
+	write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save);
+	write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save);
+	write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save);
+		write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save);
+		write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save);
+	}
+	write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save);
+	write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_2G[0] =
+		    read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_2G[1] =
+		    read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_2G[2] =
+		    read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_2G[3] =
+		    read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_2G[4] =
+		    read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_2G[5] =
+		    read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_2G[6] =
+		    read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_2G[7] =
+		    read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_2G[8] =
+		    read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_2G[9] =
+		    read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_2G[10] =
+		    read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_2G[11] =
+		    read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_5G[0] =
+		    read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_5G[1] =
+		    read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_5G[2] =
+		    read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_5G[3] =
+		    read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_5G[4] =
+		    read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_5G[5] =
+		    read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_5G[6] =
+		    read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_5G[7] =
+		    read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_5G[8] =
+		    read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_5G[9] =
+		    read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_5G[10] =
+		    read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_5G[11] =
+		    read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
+	}
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+}
+
+static void wlc_phy_restore_rssical_nphy(phy_info_t *pi)
+{
+	ASSERT(NREV_GE(pi->pubpi.phy_rev, 3));
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_rssical_chanspec_2G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_2G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_2G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_2G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_2G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_2G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_2G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_2G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_2G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_2G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_2G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_2G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_2G[11]);
+
+	} else {
+		if (pi->nphy_rssical_chanspec_5G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_5G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_5G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_5G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_5G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_5G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_5G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_5G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_5G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_5G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_5G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_5G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_5G[11]);
+	}
+}
+
+static u16
+wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+			      u8 dac_test_mode)
+{
+	u8 phy_bw, is_phybw40;
+	u16 num_samps, t, spur;
+	fixed theta = 0, rot = 0;
+	u32 tbl_len;
+	cs32 *tone_buf = NULL;
+
+	is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+	phy_bw = (is_phybw40 == 1) ? 40 : 20;
+	tbl_len = (phy_bw << 3);
+
+	if (dac_test_mode == 1) {
+		spur = read_phy_reg(pi, 0x01);
+		spur = (spur >> 15) & 1;
+		phy_bw = (spur == 1) ? 82 : 80;
+		phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw;
+
+		tbl_len = (phy_bw << 1);
+	}
+
+	tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
+	if (tone_buf == NULL) {
+		return 0;
+	}
+
+	num_samps = (u16) tbl_len;
+	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		wlc_phy_cordic(theta, &tone_buf[t]);
+
+		theta += rot;
+
+		tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val);
+		tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val);
+	}
+
+	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
+
+	kfree(tone_buf);
+
+	return num_samps;
+}
+
+int
+wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+		     u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
+{
+	u16 num_samps;
+	u16 loops = 0xffff;
+	u16 wait = 0;
+
+	num_samps =
+		wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
+	if (num_samps == 0) {
+		return BCME_ERROR;
+	}
+
+	wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
+				dac_test_mode, modify_bbmult);
+
+	return BCME_OK;
+}
+
+static void
+wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
+			     u16 num_samps)
+{
+	u16 t;
+	u32 *data_buf = NULL;
+
+	data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
+	if (data_buf == NULL) {
+		return;
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	for (t = 0; t < num_samps; t++) {
+		data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
+		    (((unsigned int)tone_buf[t].q) & 0x3ff);
+	}
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+				 data_buf);
+
+	kfree(data_buf);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_runsamples_nphy(phy_info_t *pi, u16 num_samps, u16 loops,
+			u16 wait, u8 iqmode, u8 dac_test_mode,
+			bool modify_bbmult)
+{
+	u16 bb_mult;
+	u8 phy_bw, sample_cmd;
+	u16 orig_RfseqCoreActv;
+	u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3,
+	    lpf_bw_ctl_miscreg4;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phy_bw = 20;
+	if (CHSPEC_IS40(pi->radio_chanspec))
+		phy_bw = 40;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7);
+		lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
+		if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+			    (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+			    (0x7 << 8);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
+
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+			    (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+			    (0x7 << 8);
+		}
+	}
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) {
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					&bb_mult);
+		pi->nphy_bb_mult_save =
+		    BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
+	}
+
+	if (modify_bbmult) {
+		bb_mult = (phy_bw == 20) ? 100 : 71;
+		bb_mult = (bb_mult << 8) + bb_mult;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	write_phy_reg(pi, 0xc6, num_samps - 1);
+
+	if (loops != 0xffff) {
+		write_phy_reg(pi, 0xc4, loops - 1);
+	} else {
+		write_phy_reg(pi, 0xc4, loops);
+	}
+	write_phy_reg(pi, 0xc5, wait);
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	if (iqmode) {
+
+		and_phy_reg(pi, 0xc2, 0x7FFF);
+
+		or_phy_reg(pi, 0xc2, 0x8000);
+	} else {
+
+		sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1;
+		write_phy_reg(pi, 0xc3, sample_cmd);
+	}
+
+	SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000);
+
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+}
+
+void wlc_phy_stopplayback_nphy(phy_info_t *pi)
+{
+	u16 playback_status;
+	u16 bb_mult;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	playback_status = read_phy_reg(pi, 0xc7);
+	if (playback_status & 0x1) {
+		or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
+	} else if (playback_status & 0x2) {
+
+		and_phy_reg(pi, 0xc2,
+			    (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
+	}
+
+	and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) {
+
+		bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+
+		pi->nphy_bb_mult_save = 0;
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
+		if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  0, 0, 1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi)
+{
+	u16 base_idx[2], curr_gain[2];
+	u8 core_no;
+	nphy_txgains_t target_gain;
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+					curr_gain);
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x0007;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x00F8) >> 3);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x7000) >> 12);
+				target_gain.txlpf[core_no] =
+				    ((curr_gain[core_no] & 0x8000) >> 15);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x000F;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x00F0) >> 4);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x7000) >> 12);
+			} else {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x0003;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x000C) >> 2);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0070) >> 4);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x0380) >> 7);
+			}
+		}
+	} else {
+		base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f;
+		base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				if (PHY_IPA(pi)) {
+					tx_pwrctrl_tbl =
+					    wlc_phy_get_ipa_gaintbl_nphy(pi);
+				} else {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						if NREV_IS
+							(pi->pubpi.phy_rev, 3) {
+							tx_pwrctrl_tbl =
+							    nphy_tpc_5GHz_txgain_rev3;
+						} else if NREV_IS
+							(pi->pubpi.phy_rev, 4) {
+							tx_pwrctrl_tbl =
+							    (pi->srom_fem5g.
+							     extpagain ==
+							     3) ?
+							    nphy_tpc_5GHz_txgain_HiPwrEPA
+							    :
+							    nphy_tpc_5GHz_txgain_rev4;
+						} else {
+							tx_pwrctrl_tbl =
+							    nphy_tpc_5GHz_txgain_rev5;
+						}
+					} else {
+						if (NREV_GE
+						    (pi->pubpi.phy_rev, 7)) {
+							if (pi->pubpi.
+							    radiorev == 3) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_epa_2057rev3;
+							} else if (pi->pubpi.
+								   radiorev ==
+								   5) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_epa_2057rev5;
+							}
+
+						} else {
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     5)
+							    && (pi->srom_fem2g.
+								extpagain ==
+								3)) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_HiPwrEPA;
+							} else {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_rev3;
+							}
+						}
+					}
+				}
+				if NREV_GE
+					(pi->pubpi.phy_rev, 7) {
+					target_gain.ipa[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 16) & 0x7;
+					target_gain.pad[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 19) & 0x1f;
+					target_gain.pga[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 28) & 0x7;
+					target_gain.txlpf[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 31) & 0x1;
+				} else {
+					target_gain.ipa[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 16) & 0xf;
+					target_gain.pad[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 20) & 0xf;
+					target_gain.pga[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 28) & 0x7;
+				}
+			} else {
+				target_gain.ipa[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
+				    0x3;
+				target_gain.pad[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
+				    0x3;
+				target_gain.pga[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
+				    0x7;
+				target_gain.txgm[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
+				    0x7;
+			}
+		}
+	}
+
+	return target_gain;
+}
+
+static void
+wlc_phy_iqcal_gainparams_nphy(phy_info_t *pi, u16 core_no,
+			      nphy_txgains_t target_gain,
+			      nphy_iqcal_params_t *params)
+{
+	u8 k;
+	int idx;
+	u16 gain_index;
+	u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			params->txlpf = target_gain.txlpf[core_no];
+		}
+		params->txgm = target_gain.txgm[core_no];
+		params->pga = target_gain.pga[core_no];
+		params->pad = target_gain.pad[core_no];
+		params->ipa = target_gain.ipa[core_no];
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			params->cal_gain =
+			    ((params->txlpf << 15) | (params->
+						      txgm << 12) | (params->
+								     pga << 8) |
+			     (params->pad << 3) | (params->ipa));
+		} else {
+			params->cal_gain =
+			    ((params->txgm << 12) | (params->
+						     pga << 8) | (params->
+								  pad << 4) |
+			     (params->ipa));
+		}
+		params->ncorr[0] = 0x79;
+		params->ncorr[1] = 0x79;
+		params->ncorr[2] = 0x79;
+		params->ncorr[3] = 0x79;
+		params->ncorr[4] = 0x79;
+	} else {
+
+		gain_index = ((target_gain.pad[core_no] << 0) |
+			      (target_gain.pga[core_no] << 4) | (target_gain.
+								 txgm[core_no]
+								 << 8));
+
+		idx = -1;
+		for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
+			if (tbl_iqcal_gainparams_nphy[band_idx][k][0] ==
+			    gain_index) {
+				idx = k;
+				break;
+			}
+		}
+
+		ASSERT(idx != -1);
+
+		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
+		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
+		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
+		params->cal_gain = ((params->txgm << 7) | (params->pga << 4) |
+				    (params->pad << 2));
+		params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4];
+		params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5];
+		params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6];
+		params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7];
+	}
+}
+
+static void wlc_phy_txcal_radio_setup_nphy(phy_info_t *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core <= 1; core++) {
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TX_SSI_MASTER);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    IQCAL_VCM_HG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    IQCAL_IDAC);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TX_SSI_MUX);
+
+			if (pi->pubpi.radiorev != 5)
+				pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+				    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						    TSSIA);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TSSI_MISC1);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x0a);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX, 0x4);
+					if (!
+					    (pi->
+					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x21);
+					}
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x06);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX,
+							 0x06);
+					if (!
+					    (pi->
+					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x31);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x21);
+					}
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			}
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+			    (core ==
+			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_SSI_MASTER |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_IQCAL_VCM_HG |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_IQCAL_IDAC |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_VCM | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_AMP_DET |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_SSI_MUX |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+			    read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			    read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC1 |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC2 |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC3 |
+					   jtag_core);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x0a);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+
+				if (PHY_IPA(pi)) {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x4);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x1);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x2f);
+				}
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIG | jtag_core,
+						0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x06);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIA | jtag_core,
+						0x00);
+
+				if (PHY_IPA(pi)) {
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x06);
+					if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+
+						write_radio_reg(pi,
+								RADIO_2056_TX_TSSIG
+								| jtag_core,
+								0x11);
+					} else {
+
+						write_radio_reg(pi,
+								RADIO_2056_TX_TSSIG
+								| jtag_core,
+								0x1);
+					}
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIG |
+							jtag_core, 0x20);
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			}
+		}
+	} else {
+
+		pi->tx_rx_cal_radio_saveregs[0] =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[1] =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[2] =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[3] =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[4] =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pi->tx_rx_cal_radio_saveregs[5] =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+
+		if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
+		    0) {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		} else {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20);
+		} else {
+
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf);
+		}
+	}
+}
+
+static void wlc_phy_txcal_radio_cleanup_nphy(phy_info_t *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core <= 1; core++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TX_SSI_MASTER,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  0]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  2]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  3]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  5]);
+
+			if (pi->pubpi.radiorev != 5)
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIA,
+						 pi->
+						 tx_rx_cal_radio_saveregs[(core
+									   *
+									   11) +
+									  6]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  7]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  8]);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+			    (core ==
+			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_VCM_HG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 1]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_IDAC | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 2]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_AMP_DET | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 4]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MUX | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 5]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 6]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 7]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC1 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 8]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC2 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 9]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC3 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 10]);
+		}
+	} else {
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[0]);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[1]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[2]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[3]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pi->tx_rx_cal_radio_saveregs[4]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pi->tx_rx_cal_radio_saveregs[5]);
+	}
+}
+
+static void wlc_phy_txcal_physetup_nphy(phy_info_t *pi)
+{
+	u16 val, mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 8) | (0x3 << 10));
+		val = (0x2 << 8);
+		val |= (0x2 << 10);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0x8f);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0x8f, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0xa5, val);
+
+		pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01);
+		mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[5] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[6] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
+
+		if (!(pi->use_int_tx_iqlo_cal_nphy)) {
+
+			wlc_phy_rfctrlintc_override_nphy(pi,
+							 NPHY_RfctrlIntc_override_PA,
+							 1,
+							 RADIO_MIMO_CORESEL_CORE1
+							 |
+							 RADIO_MIMO_CORESEL_CORE2);
+		} else {
+
+			wlc_phy_rfctrlintc_override_nphy(pi,
+							 NPHY_RfctrlIntc_override_PA,
+							 0,
+							 RADIO_MIMO_CORESEL_CORE1
+							 |
+							 RADIO_MIMO_CORESEL_CORE2);
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+
+		pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+		pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      1 << 4);
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						      1, 0);
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						      1, 0);
+				} else {
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+						      1, 0);
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+						      1, 0);
+				}
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(pi,
+								  (0x1 << 3), 0,
+								  0x3, 0,
+								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (0x2 << 12);
+		val |= (0x2 << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 12) | (0x1 << 13));
+		write_phy_reg(pi, 0xa5, val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[4] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92);
+		val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		write_phy_reg(pi, 0x91, val);
+		write_phy_reg(pi, 0x92, val);
+	}
+}
+
+static void wlc_phy_txcal_phycleanup_nphy(phy_info_t *pi)
+{
+	u16 mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]);
+		write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]);
+		write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &pi->tx_rx_cal_phy_saveregs[5]);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &pi->tx_rx_cal_phy_saveregs[6]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]);
+
+		write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+		write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
+							  1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		wlc_phy_resetcca_nphy(pi);
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						      1, 1);
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						      1, 1);
+				} else {
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+						      1, 1);
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+						      1, 1);
+				}
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      0);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(pi,
+								  (0x1 << 3), 0,
+								  0x3, 1,
+								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		mask = ((0x3 << 12) | (0x3 << 14));
+		mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]);
+		mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &pi->tx_rx_cal_phy_saveregs[3]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &pi->tx_rx_cal_phy_saveregs[4]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]);
+	}
+}
+
+#define NPHY_CAL_TSSISAMPS	64
+#define NPHY_TEST_TONE_FREQ_40MHz 4000
+#define NPHY_TEST_TONE_FREQ_20MHz 2500
+
+void
+wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf, u8 num_samps)
+{
+	u16 tssi_reg;
+	s32 temp, pwrindex[2];
+	s32 idle_tssi[2];
+	s32 rssi_buf[4];
+	s32 tssival[2];
+	u8 tssi_type;
+
+	tssi_reg = read_phy_reg(pi, 0x1e9);
+
+	temp = (s32) (tssi_reg & 0x3f);
+	idle_tssi[0] = (temp <= 31) ? temp : (temp - 64);
+
+	temp = (s32) ((tssi_reg >> 8) & 0x3f);
+	idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
+
+	tssi_type =
+	    CHSPEC_IS5G(pi->radio_chanspec) ?
+	    (u8)NPHY_RSSI_SEL_TSSI_5G:(u8)NPHY_RSSI_SEL_TSSI_2G;
+
+	wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
+
+	tssival[0] = rssi_buf[0] / ((s32) num_samps);
+	tssival[1] = rssi_buf[2] / ((s32) num_samps);
+
+	pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
+	pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
+
+	if (pwrindex[0] < 0) {
+		pwrindex[0] = 0;
+	} else if (pwrindex[0] > 63) {
+		pwrindex[0] = 63;
+	}
+
+	if (pwrindex[1] < 0) {
+		pwrindex[1] = 0;
+	} else if (pwrindex[1] > 63) {
+		pwrindex[1] = 63;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
+				(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1,
+				(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
+}
+
+static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi)
+{
+	u16 txcal_gain[2];
+
+	pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
+	pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				txcal_gain);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
+	} else {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 txcal_gain);
+}
+
+static void wlc_phy_precal_txgain_nphy(phy_info_t *pi)
+{
+	bool save_bbmult = false;
+	u8 txcal_index_2057_rev5n7 = 0;
+	u8 txcal_index_2057_rev3n4n6 = 10;
+
+	if (pi->use_int_tx_iqlo_cal_nphy) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				pi->nphy_txcal_pwr_idx[0] =
+				    txcal_index_2057_rev3n4n6;
+				pi->nphy_txcal_pwr_idx[1] =
+				    txcal_index_2057_rev3n4n6;
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 txcal_index_2057_rev3n4n6,
+							 false);
+			} else {
+
+				pi->nphy_txcal_pwr_idx[0] =
+				    txcal_index_2057_rev5n7;
+				pi->nphy_txcal_pwr_idx[1] =
+				    txcal_index_2057_rev5n7;
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 txcal_index_2057_rev5n7,
+							 false);
+			}
+			save_bbmult = true;
+
+		} else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
+			if (pi->sh->hw_phytxchain != 3) {
+				pi->nphy_txcal_pwr_idx[1] =
+				    pi->nphy_txcal_pwr_idx[0];
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 pi->
+							 nphy_txcal_pwr_idx[0],
+							 true);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					pi->nphy_txcal_pwr_idx[0] = 80;
+					pi->nphy_txcal_pwr_idx[1] = 80;
+					wlc_phy_txpwr_index_nphy(pi, 3, 80,
+								 false);
+					save_bbmult = true;
+				}
+			} else {
+
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					wlc_phy_cal_txgainctrl_nphy(pi, 14,
+								    false);
+				}
+			} else {
+
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+		}
+
+	} else {
+		wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
+	}
+
+	if (save_bbmult) {
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+					&pi->nphy_txcal_bbmult);
+	}
+}
+
+void
+wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower, bool debug)
+{
+	int gainctrl_loopidx;
+	uint core;
+	u16 m0m1, curr_m0m1;
+	s32 delta_power;
+	s32 txpwrindex;
+	s32 qdBm_power[2];
+	u16 orig_BBConfig;
+	u16 phy_saveregs[4];
+	u32 freq_test;
+	u16 ampl_test = 250;
+	uint stepsize;
+	bool phyhang_avoid_state = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		stepsize = 2;
+	} else {
+
+		stepsize = 1;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		freq_test = 5000;
+	} else {
+		freq_test = 2500;
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phyhang_avoid_state = pi->phyhang_avoid;
+	pi->phyhang_avoid = false;
+
+	phy_saveregs[0] = read_phy_reg(pi, 0x91);
+	phy_saveregs[1] = read_phy_reg(pi, 0x92);
+	phy_saveregs[2] = read_phy_reg(pi, 0xe7);
+	phy_saveregs[3] = read_phy_reg(pi, 0xec);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (!debug) {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+	} else {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x7, RADIO_MIMO_CORESEL_CORE2);
+	}
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
+
+		for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
+		     gainctrl_loopidx++) {
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			if (core == PHY_CORE_0) {
+				curr_m0m1 = m0m1 & 0xff00;
+			} else {
+				curr_m0m1 = m0m1 & 0x00ff;
+			}
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+
+			udelay(50);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+
+			delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+
+			txpwrindex -= stepsize * delta_power;
+			if (txpwrindex < 0) {
+				txpwrindex = 0;
+			} else if (txpwrindex > 127) {
+				txpwrindex = 127;
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (NREV_IS(pi->pubpi.phy_rev, 4) &&
+				    (pi->srom_fem5g.extpagain == 3)) {
+					if (txpwrindex < 30) {
+						txpwrindex = 30;
+					}
+				}
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+				    (pi->srom_fem2g.extpagain == 3)) {
+					if (txpwrindex < 50) {
+						txpwrindex = 50;
+					}
+				}
+			}
+
+			wlc_phy_txpwr_index_nphy(pi, (1 << core),
+						 (u8) txpwrindex, true);
+		}
+
+		pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+
+		if (debug) {
+			u16 radio_gain;
+			u16 dbg_m0m1;
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+
+			udelay(100);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
+						&radio_gain);
+
+			mdelay(4000);
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	write_phy_reg(pi, 0x91, phy_saveregs[0]);
+	write_phy_reg(pi, 0x92, phy_saveregs[1]);
+	write_phy_reg(pi, 0xe7, phy_saveregs[2]);
+	write_phy_reg(pi, 0xec, phy_saveregs[3]);
+
+	pi->phyhang_avoid = phyhang_avoid_state;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core)
+{
+	int index;
+	u32 bbmult_scale;
+	u16 bbmult;
+	u16 tblentry;
+
+	nphy_txiqcal_ladder_t ladder_lo[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+		{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
+	};
+
+	nphy_txiqcal_ladder_t ladder_iq[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
+		{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
+	};
+
+	bbmult = (core == PHY_CORE_0) ?
+	    ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
+						     nphy_txcal_bbmult & 0xff);
+
+	for (index = 0; index < 18; index++) {
+		bbmult_scale = ladder_lo[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+		    ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
+					 &tblentry);
+
+		bbmult_scale = ladder_iq[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+		    ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
+					 16, &tblentry);
+	}
+}
+
+void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype)
+{
+	nphy_txgains_t target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool fullcal = true;
+	bool restore_tx_gain = false;
+	bool mphase;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		wlc_phy_cal_perical_mphase_reset(pi);
+		return;
+	}
+
+	if (PHY_MUTED(pi))
+		return;
+
+	ASSERT(pi->nphy_perical != PHY_PERICAL_DISABLE);
+
+	if (caltype == PHY_PERICAL_AUTO)
+		fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec);
+	else if (caltype == PHY_PERICAL_PARTIAL)
+		fullcal = false;
+
+	if (pi->cal_type_override != PHY_PERICAL_AUTO) {
+		fullcal =
+		    (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
+	}
+
+	if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
+		if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
+			wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phyreg_enter((wlc_phy_t *) pi);
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
+	    (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
+		pi->nphy_cal_orig_pwr_idx[0] =
+		    (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
+		pi->nphy_cal_orig_pwr_idx[1] =
+		    (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
+
+		if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
+						0x110, 16,
+						pi->nphy_cal_orig_tx_gain);
+		} else {
+			pi->nphy_cal_orig_tx_gain[0] = 0;
+			pi->nphy_cal_orig_tx_gain[1] = 0;
+		}
+	}
+	target_gain = wlc_phy_get_tx_gain_nphy(pi);
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	if (pi->antsel_type == ANTSEL_2x3)
+		wlc_phy_antsel_init((wlc_phy_t *) pi, true);
+
+	mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE);
+	if (!mphase) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_precal_txgain_nphy(pi);
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			restore_tx_gain = true;
+
+			target_gain = pi->nphy_cal_target_gain;
+		}
+		if (BCME_OK ==
+		    wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
+			if (PHY_IPA(pi))
+				wlc_phy_a4(pi, true);
+
+			wlc_phyreg_exit((wlc_phy_t *) pi);
+			wlapi_enable_mac(pi->sh->physhim);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION,
+					     10000);
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_phyreg_enter((wlc_phy_t *) pi);
+
+			if (BCME_OK == wlc_phy_cal_rxiq_nphy(pi, target_gain,
+							     (pi->
+							      first_cal_after_assoc
+							      || (pi->
+								  cal_type_override
+								  ==
+								  PHY_PERICAL_FULL))
+							     ? 2 : 0, false)) {
+				wlc_phy_savecal_nphy(pi);
+
+				wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+				pi->nphy_perical_last = pi->sh->now;
+			}
+		}
+		if (caltype != PHY_PERICAL_AUTO) {
+			wlc_phy_rssi_cal_nphy(pi);
+		}
+
+		if (pi->first_cal_after_assoc
+		    || (pi->cal_type_override == PHY_PERICAL_FULL)) {
+			pi->first_cal_after_assoc = false;
+			wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+			wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio205x_vcocal_nphy(pi);
+		}
+	} else {
+		ASSERT(pi->nphy_perical >= PHY_PERICAL_MPHASE);
+
+		switch (pi->mphase_cal_phase_id) {
+		case MPHASE_CAL_STATE_INIT:
+			pi->nphy_perical_last = pi->sh->now;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				wlc_phy_precal_txgain_nphy(pi);
+			}
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_TXPHASE0:
+		case MPHASE_CAL_STATE_TXPHASE1:
+		case MPHASE_CAL_STATE_TXPHASE2:
+		case MPHASE_CAL_STATE_TXPHASE3:
+		case MPHASE_CAL_STATE_TXPHASE4:
+		case MPHASE_CAL_STATE_TXPHASE5:
+			if ((pi->radar_percal_mask & 0x10) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (wlc_phy_cal_txiqlo_nphy
+			    (pi, pi->nphy_cal_target_gain, fullcal,
+			     true) != BCME_OK) {
+
+				wlc_phy_cal_perical_mphase_reset(pi);
+				break;
+			}
+
+			if (NREV_LE(pi->pubpi.phy_rev, 2) &&
+			    (pi->mphase_cal_phase_id ==
+			     MPHASE_CAL_STATE_TXPHASE4)) {
+				pi->mphase_cal_phase_id += 2;
+			} else {
+				pi->mphase_cal_phase_id++;
+			}
+			break;
+
+		case MPHASE_CAL_STATE_PAPDCAL:
+			if ((pi->radar_percal_mask & 0x2) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (PHY_IPA(pi)) {
+				wlc_phy_a4(pi, true);
+			}
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RXCAL:
+			if ((pi->radar_percal_mask & 0x1) != 0)
+				pi->nphy_rxcal_active = true;
+			if (wlc_phy_cal_rxiq_nphy(pi, target_gain,
+						  (pi->first_cal_after_assoc ||
+						   (pi->cal_type_override ==
+						    PHY_PERICAL_FULL)) ? 2 : 0,
+						  false) == BCME_OK) {
+				wlc_phy_savecal_nphy(pi);
+			}
+
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RSSICAL:
+			if ((pi->radar_percal_mask & 0x4) != 0)
+				pi->nphy_rxcal_active = true;
+			wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+			wlc_phy_rssi_cal_nphy(pi);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				wlc_phy_radio205x_vcocal_nphy(pi);
+			}
+			restore_tx_gain = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->mphase_cal_phase_id++;
+			} else {
+				wlc_phy_cal_perical_mphase_reset(pi);
+			}
+
+			break;
+
+		case MPHASE_CAL_STATE_IDLETSSI:
+			if ((pi->radar_percal_mask & 0x8) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->first_cal_after_assoc = false;
+				wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+				wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+			}
+
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+
+		default:
+			ASSERT(0);
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (restore_tx_gain) {
+			if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) {
+
+				wlc_phy_txpwr_index_nphy(pi, 1,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [0], false);
+				wlc_phy_txpwr_index_nphy(pi, 2,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [1], false);
+
+				pi->nphy_txpwrindex[0].index = -1;
+				pi->nphy_txpwrindex[1].index = -1;
+			} else {
+				wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+							 (s8) (pi->
+								 nphy_txpwrindex
+								 [0].
+								 index_internal),
+							 false);
+				wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+							 (s8) (pi->
+								 nphy_txpwrindex
+								 [1].
+								 index_internal),
+							 false);
+			}
+		}
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+	wlc_phyreg_exit((wlc_phy_t *) pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+int
+wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+			bool fullcal, bool mphase)
+{
+	u16 val;
+	u16 tbl_buf[11];
+	u8 cal_cnt;
+	u16 cal_cmd;
+	u8 num_cals, max_cal_cmds;
+	u16 core_no, cal_type;
+	u16 diq_start = 0;
+	u8 phy_bw;
+	u16 max_val;
+	u16 tone_freq;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	nphy_iqcal_params_t cal_params[2];
+	u32 tbl_len;
+	void *tbl_ptr;
+	bool ladder_updated[2];
+	u8 mphase_cal_lastphase = 0;
+	int bcmerror = BCME_OK;
+	bool phyhang_avoid_state = false;
+
+	u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
+		0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
+		    0x1902,
+		0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
+		    0x6407
+	};
+
+	u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
+		0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
+		    0x3200,
+		0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
+		    0x6407
+	};
+
+	u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
+		0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
+		    0x1202,
+		0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
+		    0x4707
+	};
+
+	u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
+		0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
+		    0x2300,
+		0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
+		    0x4707
+	};
+
+	u16 tbl_tx_iqlo_cal_startcoefs[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		    0x0000
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
+		0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
+		0x9123, 0x9264, 0x9086, 0x9245, 0x9056
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_recal[] = {
+		0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
+		0x9101, 0x9253, 0x9053, 0x9234, 0x9034
+	};
+
+	u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
+		0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
+		0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
+		0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
+	};
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		phy_bw = 40;
+	} else {
+		phy_bw = 20;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	wlc_phy_txcal_radio_setup_nphy(pi);
+
+	wlc_phy_txcal_physetup_nphy(pi);
+
+	ladder_updated[0] = ladder_updated[1] = false;
+	if (!(NREV_GE(pi->pubpi.phy_rev, 6) ||
+	      (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi)
+	       && (CHSPEC_IS2G(pi->radio_chanspec))))) {
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0,
+					 16, tbl_ptr);
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32,
+					 16, tbl_ptr);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0xc2, 0x8ad9);
+	} else {
+		write_phy_reg(pi, 0xc2, 0x8aa9);
+	}
+
+	max_val = 250;
+	tone_freq = (phy_bw == 20) ? 2500 : 5000;
+
+	if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+		wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false);
+		bcmerror = BCME_OK;
+	} else {
+		bcmerror =
+		    wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
+	}
+
+	if (bcmerror == BCME_OK) {
+
+		if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+			tbl_ptr = pi->mphase_txcal_bestcoeffs;
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+		} else {
+			if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
+
+				tbl_ptr = pi->nphy_txiqlocal_bestc;
+				tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+				if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+					tbl_len -= 2;
+				}
+			} else {
+
+				fullcal = true;
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					tbl_ptr =
+					    tbl_tx_iqlo_cal_startcoefs_nphyrev3;
+					tbl_len =
+					    ARRAY_SIZE
+					    (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
+				} else {
+					tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
+					tbl_len =
+					    ARRAY_SIZE
+					    (tbl_tx_iqlo_cal_startcoefs);
+				}
+			}
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64,
+					 16, tbl_ptr);
+
+		if (fullcal) {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
+		} else {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
+		}
+
+		if (mphase) {
+			cal_cnt = pi->mphase_txcal_cmdidx;
+			if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
+				num_cals = cal_cnt + pi->mphase_txcal_numcmds;
+			} else {
+				num_cals = max_cal_cmds;
+			}
+		} else {
+			cal_cnt = 0;
+			num_cals = max_cal_cmds;
+		}
+
+		for (; cal_cnt < num_cals; cal_cnt++) {
+
+			if (fullcal) {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				    tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
+				    [cal_cnt] :
+				    tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
+			} else {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				    tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
+				    : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
+			}
+
+			core_no = ((cal_cmd & 0x3000) >> 12);
+			cal_type = ((cal_cmd & 0x0F00) >> 8);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6) ||
+			    (NREV_IS(pi->pubpi.phy_rev, 5) &&
+			     PHY_IPA(pi)
+			     && (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				if (!ladder_updated[core_no]) {
+					wlc_phy_update_txcal_ladder_nphy(pi,
+									 core_no);
+					ladder_updated[core_no] = true;
+				}
+			}
+
+			val =
+			    (cal_params[core_no].
+			     ncorr[cal_type] << 8) | NPHY_N_GCTL;
+			write_phy_reg(pi, 0xc1, val);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+							1, 69 + core_no, 16,
+							tbl_buf);
+
+				diq_start = tbl_buf[0];
+
+				tbl_buf[0] = 0;
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_IQLOCAL, 1,
+							 69 + core_no, 16,
+							 tbl_buf);
+			}
+
+			write_phy_reg(pi, 0xc0, cal_cmd);
+
+			SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0),
+				 20000);
+			ASSERT((read_phy_reg(pi, 0xc0) & 0xc000) == 0);
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						 tbl_len, 64, 16, tbl_buf);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				tbl_buf[0] = diq_start;
+
+			}
+
+		}
+
+		if (mphase) {
+			pi->mphase_txcal_cmdidx = num_cals;
+			if (pi->mphase_txcal_cmdidx >= max_cal_cmds)
+				pi->mphase_txcal_cmdidx = 0;
+		}
+
+		mphase_cal_lastphase =
+		    (NREV_LE(pi->pubpi.phy_rev, 2)) ?
+		    MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
+
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, tbl_buf);
+
+			if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+				tbl_buf[0] = 0;
+				tbl_buf[1] = 0;
+				tbl_buf[2] = 0;
+				tbl_buf[3] = 0;
+
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16, tbl_buf);
+
+			tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->nphy_txiqlocal_bestc);
+
+			pi->nphy_txiqlocal_coeffsvalid = true;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+		} else {
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->mphase_txcal_bestcoeffs);
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+
+		write_phy_reg(pi, 0xc2, 0x0000);
+
+	}
+
+	wlc_phy_txcal_phycleanup_nphy(pi);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_txcal_radio_cleanup_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase))
+			wlc_phy_tx_iq_war_nphy(pi);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		pi->phyhang_avoid = phyhang_avoid_state;
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi)
+{
+	u16 tbl_buf[7];
+
+	ASSERT(NREV_LT(pi->pubpi.phy_rev, 2));
+
+	if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) &&
+	    (pi->nphy_txiqlocal_coeffsvalid)) {
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+					ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf);
+
+		if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) ||
+		    (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) ||
+		    (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) ||
+		    (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, pi->nphy_txiqlocal_bestc);
+
+			tbl_buf[0] = 0;
+			tbl_buf[1] = 0;
+			tbl_buf[2] = 0;
+			tbl_buf[3] = 0;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+		}
+	}
+}
+
+static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi)
+{
+	nphy_iq_comp_t tx_comp;
+
+	wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
+
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
+}
+
+void
+wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write, nphy_iq_comp_t *pcomp)
+{
+	if (write) {
+		write_phy_reg(pi, 0x9a, pcomp->a0);
+		write_phy_reg(pi, 0x9b, pcomp->b0);
+		write_phy_reg(pi, 0x9c, pcomp->a1);
+		write_phy_reg(pi, 0x9d, pcomp->b1);
+	} else {
+		pcomp->a0 = read_phy_reg(pi, 0x9a);
+		pcomp->b0 = read_phy_reg(pi, 0x9b);
+		pcomp->a1 = read_phy_reg(pi, 0x9c);
+		pcomp->b1 = read_phy_reg(pi, 0x9d);
+	}
+}
+
+void
+wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est, u16 num_samps,
+		       u8 wait_time, u8 wait_for_crs)
+{
+	u8 core;
+
+	write_phy_reg(pi, 0x12b, num_samps);
+	mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0));
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode,
+		    (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0);
+
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart);
+
+	SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0),
+		 10000);
+	ASSERT((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0);
+
+	if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
+		ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			est[core].i_pwr =
+			    (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
+			    | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
+			est[core].q_pwr =
+			    (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
+			    | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
+			est[core].iq_prod =
+			    (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
+			    read_phy_reg(pi, NPHY_IqestIqAccLo(core));
+		}
+	}
+}
+
+#define CAL_RETRY_CNT 2
+static void wlc_phy_calc_rx_iq_comp_nphy(phy_info_t *pi, u8 core_mask)
+{
+	u8 curr_core;
+	phy_iq_est_t est[PHY_CORE_MAX];
+	nphy_iq_comp_t old_comp, new_comp;
+	s32 iq = 0;
+	u32 ii = 0, qq = 0;
+	s16 iq_nbits, qq_nbits, brsh, arsh;
+	s32 a, b, temp;
+	int bcmerror = BCME_OK;
+	uint cal_retry = 0;
+
+	if (core_mask == 0x0)
+		return;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp);
+	new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+
+ cal_try:
+	wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
+
+	new_comp = old_comp;
+
+	for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) {
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else {
+			continue;
+		}
+
+		if ((ii + qq) < NPHY_MIN_RXIQ_PWR) {
+			bcmerror = BCME_ERROR;
+			break;
+		}
+
+		iq_nbits = wlc_phy_nbits(iq);
+		qq_nbits = wlc_phy_nbits(qq);
+
+		arsh = 10 - (30 - iq_nbits);
+		if (arsh >= 0) {
+			a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+			temp = (s32) (ii >> arsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		} else {
+			a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+			temp = (s32) (ii << -arsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		}
+
+		a /= temp;
+
+		brsh = qq_nbits - 31 + 20;
+		if (brsh >= 0) {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii >> brsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		} else {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii << -brsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		}
+		b /= temp;
+		b -= a * a;
+		b = (s32) wlc_phy_sqrt_int((u32) b);
+		b -= (1 << 10);
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a0 = (s16) a & 0x3ff;
+				new_comp.b0 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a0 = (s16) b & 0x3ff;
+				new_comp.b0 = (s16) a & 0x3ff;
+			}
+		}
+		if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a1 = (s16) a & 0x3ff;
+				new_comp.b1 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a1 = (s16) b & 0x3ff;
+				new_comp.b1 = (s16) a & 0x3ff;
+			}
+		}
+	}
+
+	if (bcmerror != BCME_OK) {
+		printk("%s: Failed, cnt = %d\n", __func__, cal_retry);
+
+		if (cal_retry < CAL_RETRY_CNT) {
+			cal_retry++;
+			goto cal_try;
+		}
+
+		new_comp = old_comp;
+	} else if (cal_retry > 0) {
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+}
+
+static void wlc_phy_rxcal_radio_setup_nphy(phy_info_t *pi, u8 rx_core)
+{
+	u16 offtune_val;
+	u16 bias_g = 0;
+	u16 bias_a = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+						0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+						0x7f);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+						0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+						0x7f);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			pi->tx_rx_cal_radio_saveregs[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_RXIQCAL_TXMUX |
+					   RADIO_2056_TX1);
+			pi->tx_rx_cal_radio_saveregs[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RXIQCAL_RXMUX |
+					   RADIO_2056_RX0);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+				    read_radio_reg(pi,
+						   RADIO_2056_RX_RXSPARE2 |
+						   RADIO_2056_RX0);
+				pi->tx_rx_cal_radio_saveregs[3] =
+				    read_radio_reg(pi,
+						   RADIO_2056_TX_TXSPARE2 |
+						   RADIO_2056_TX1);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_MASTER
+							   | RADIO_2056_RX0);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX1, bias_a);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX0, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_TUNE
+							   | RADIO_2056_RX0);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_MASTER
+							   | RADIO_2056_RX0);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX1, bias_g);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX0, bias_g);
+
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_TUNE
+							   | RADIO_2056_RX0);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x6);
+			}
+
+		} else {
+			pi->tx_rx_cal_radio_saveregs[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_RXIQCAL_TXMUX |
+					   RADIO_2056_TX0);
+			pi->tx_rx_cal_radio_saveregs[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RXIQCAL_RXMUX |
+					   RADIO_2056_RX1);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+				    read_radio_reg(pi,
+						   RADIO_2056_RX_RXSPARE2 |
+						   RADIO_2056_RX1);
+				pi->tx_rx_cal_radio_saveregs[3] =
+				    read_radio_reg(pi,
+						   RADIO_2056_TX_TXSPARE2 |
+						   RADIO_2056_TX0);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_MASTER
+							   | RADIO_2056_RX1);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX0, bias_a);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX1, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_TUNE
+							   | RADIO_2056_RX1);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_MASTER
+							   | RADIO_2056_RX1);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX0, bias_g);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX1, bias_g);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_TUNE
+							   | RADIO_2056_RX1);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x6);
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_radio_cleanup_nphy(phy_info_t *pi, u8 rx_core)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX1,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX0,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX1,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			}
+
+		} else {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX0,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX1,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX0,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_physetup_nphy(phy_info_t *pi, u8 rx_core)
+{
+	u8 tx_core;
+	u16 rx_antval, tx_antval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		tx_core = rx_core;
+	} else {
+		tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
+	}
+
+	pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
+	pi->tx_rx_cal_phy_saveregs[1] =
+	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
+	pi->tx_rx_cal_phy_saveregs[2] =
+	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
+	pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
+	pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
+	pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
+	pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d);
+	pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7);
+	pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342);
+		pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343);
+		pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346);
+		pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347);
+	}
+
+	pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+	pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12);
+
+	} else {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+		mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4);
+		mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8);
+	}
+
+	mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0);
+	mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		    (0x1 << 2), (0x1 << 2));
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1), 0);
+		mod_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+			    0x8f : 0xa5,
+			    (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1));
+	}
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  2, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0);
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, rx_core + 1);
+	} else {
+
+		if (rx_core == PHY_CORE_0) {
+			rx_antval = 0x1;
+			tx_antval = 0x8;
+		} else {
+			rx_antval = 0x4;
+			tx_antval = 0x2;
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 rx_antval, rx_core + 1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 tx_antval, tx_core + 1);
+	}
+}
+
+static void wlc_phy_rxcal_phycleanup_nphy(phy_info_t *pi, u8 rx_core)
+{
+
+	write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7,
+		      pi->tx_rx_cal_phy_saveregs[1]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		      pi->tx_rx_cal_phy_saveregs[2]);
+	write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]);
+	write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]);
+
+	write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]);
+	write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]);
+	write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]);
+	write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]);
+		write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]);
+		write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]);
+		write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]);
+	}
+
+	write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+	write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rx_core,
+				 u16 *rxgain, u8 cal_type)
+{
+
+	u16 num_samps;
+	phy_iq_est_t est[PHY_CORE_MAX];
+	u8 tx_core;
+	nphy_iq_comp_t save_comp, zero_comp;
+	u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
+	    10000;
+	s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
+	bool gainctrl_done = false;
+	u8 mix_tia_gain = 3;
+	s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
+	s8 curr_gaintbl_index = 3;
+	u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
+	nphy_ipa_txrxgain_t *nphy_rxcal_gaintbl;
+	u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
+	int fine_gain_idx;
+	s8 txpwrindex;
+	u16 nphy_rxcal_txgain[2];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		tx_core = rx_core;
+	} else {
+		tx_core = 1 - rx_core;
+	}
+
+	num_samps = 1024;
+	desired_log2_pwr = (cal_type == 0) ? 13 : 13;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp);
+	zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mix_tia_gain = 3;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+			mix_tia_gain = 4;
+		} else {
+			mix_tia_gain = 6;
+		}
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
+		} else {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
+		}
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
+		} else {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
+		}
+	}
+
+	do {
+
+		hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
+		    0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
+		lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
+		lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
+		lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
+		lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
+		txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_1tomany_nphy(pi,
+							     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+							     ((lpf_biq1 << 12) |
+							      (lpf_biq0 << 8) |
+							      (mix_tia_gain <<
+							       4) | (lna2 << 2)
+							      | lna1), 0x3, 0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+						     ((hpvga << 12) |
+						      (lpf_biq1 << 10) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+		}
+
+		pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
+
+		if (txpwrindex == -1) {
+			nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval;
+			nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+						 2, 0x110, 16,
+						 nphy_rxcal_txgain);
+		} else {
+			wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex,
+						 false);
+		}
+
+		wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ?
+				     NPHY_RXCAL_TONEFREQ_40MHz :
+				     NPHY_RXCAL_TONEFREQ_20MHz,
+				     NPHY_RXCAL_TONEAMP, 0, cal_type, false);
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+		i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps;
+		q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps;
+		curr_pwr = i_pwr + q_pwr;
+
+		switch (gainctrl_dirn) {
+		case NPHY_RXCAL_GAIN_INIT:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_UP;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_UP:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_done = true;
+				optim_pwr = prev_pwr;
+				optim_gaintbl_index = prev_gaintbl_index;
+			} else {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_DOWN:
+			if (curr_pwr > thresh_pwr) {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_done = true;
+				optim_pwr = curr_pwr;
+				optim_gaintbl_index = curr_gaintbl_index;
+			}
+			break;
+
+		default:
+			ASSERT(0);
+		}
+
+		if ((curr_gaintbl_index < 0) ||
+		    (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) {
+			gainctrl_done = true;
+			optim_pwr = curr_pwr;
+			optim_gaintbl_index = prev_gaintbl_index;
+		} else {
+			prev_pwr = curr_pwr;
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+	} while (!gainctrl_done);
+
+	hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga;
+	lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1;
+	lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0;
+	lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2;
+	lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1;
+	txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex;
+
+	actual_log2_pwr = wlc_phy_nbits(optim_pwr);
+	delta_pwr = desired_log2_pwr - actual_log2_pwr;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		fine_gain_idx = (int)lpf_biq1 + delta_pwr;
+
+		if (fine_gain_idx + (int)lpf_biq0 > 10) {
+			lpf_biq1 = 10 - lpf_biq0;
+		} else {
+			lpf_biq1 = (u16) max(fine_gain_idx, 0);
+		}
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+						     ((lpf_biq1 << 12) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+	} else {
+		hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+					     ((hpvga << 12) | (lpf_biq1 << 10) |
+					      (lpf_biq0 << 8) | (mix_tia_gain <<
+								 4) | (lna2 <<
+								       2) |
+					      lna1), 0x3, 0);
+
+	}
+
+	if (rxgain != NULL) {
+		*rxgain++ = lna1;
+		*rxgain++ = lna2;
+		*rxgain++ = mix_tia_gain;
+		*rxgain++ = lpf_biq0;
+		*rxgain++ = lpf_biq1;
+		*rxgain = hpvga;
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy(phy_info_t *pi, u8 rx_core, u16 *rxgain,
+			    u8 cal_type)
+{
+	wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type);
+}
+
+static u8
+wlc_phy_rc_sweep_nphy(phy_info_t *pi, u8 core_idx, u8 loopback_type)
+{
+	u32 target_bws[2] = { 9500, 21000 };
+	u32 ref_tones[2] = { 3000, 6000 };
+	u32 target_bw, ref_tone;
+
+	u32 target_pwr_ratios[2] = { 28606, 18468 };
+	u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0;
+
+	u16 start_rccal_ovr_val = 128;
+	u16 txlpf_rccal_lpc_ovr_val = 128;
+	u16 rxlpf_rccal_hpc_ovr_val = 159;
+
+	u16 orig_txlpf_rccal_lpc_ovr_val;
+	u16 orig_rxlpf_rccal_hpc_ovr_val;
+	u16 radio_addr_offset_rx;
+	u16 radio_addr_offset_tx;
+	u16 orig_dcBypass;
+	u16 orig_RxStrnFilt40Num[6];
+	u16 orig_RxStrnFilt40Den[4];
+	u16 orig_rfctrloverride[2];
+	u16 orig_rfctrlauxreg[2];
+	u16 orig_rfctrlrssiothers;
+	u16 tx_lpf_bw = 4;
+
+	u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 };
+	u16 lpf_hpc = 7, hpvga_hpc = 7;
+
+	s8 rccal_stepsize;
+	u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0;
+	u32 ref_iq_vals = 0, target_iq_vals = 0;
+	u16 num_samps, log_num_samps = 10;
+	phy_iq_est_t est[PHY_CORE_MAX];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		return 0;
+	}
+
+	num_samps = (1 << log_num_samps);
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		target_bw = target_bws[1];
+		target_pwr_ratio = target_pwr_ratios[1];
+		ref_tone = ref_tones[1];
+		rx_lpf_bw = rx_lpf_bws[1];
+	} else {
+		target_bw = target_bws[0];
+		target_pwr_ratio = target_pwr_ratios[0];
+		ref_tone = ref_tones[0];
+		rx_lpf_bw = rx_lpf_bws[0];
+	}
+
+	if (core_idx == 0) {
+		radio_addr_offset_rx = RADIO_2056_RX0;
+		radio_addr_offset_tx =
+		    (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+	} else {
+		radio_addr_offset_rx = RADIO_2056_RX1;
+		radio_addr_offset_tx =
+		    (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
+	}
+
+	orig_txlpf_rccal_lpc_ovr_val =
+	    read_radio_reg(pi,
+			   (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
+	orig_rxlpf_rccal_hpc_ovr_val =
+	    read_radio_reg(pi,
+			   (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+			    radio_addr_offset_rx));
+
+	orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
+
+	orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267);
+	orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268);
+	orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269);
+	orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a);
+	orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b);
+	orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c);
+	orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d);
+	orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e);
+	orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f);
+	orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270);
+
+	orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7);
+	orig_rfctrloverride[1] = read_phy_reg(pi, 0xec);
+	orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8);
+	orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa);
+	orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			txlpf_rccal_lpc_ovr_val);
+
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8));
+
+	write_phy_reg(pi, 0x267, 0x02d4);
+	write_phy_reg(pi, 0x268, 0x0000);
+	write_phy_reg(pi, 0x269, 0x0000);
+	write_phy_reg(pi, 0x26a, 0x0000);
+	write_phy_reg(pi, 0x26b, 0x0000);
+	write_phy_reg(pi, 0x26c, 0x02d4);
+	write_phy_reg(pi, 0x26d, 0x0000);
+	write_phy_reg(pi, 0x26e, 0x0000);
+	write_phy_reg(pi, 0x26f, 0x0000);
+	write_phy_reg(pi, 0x270, 0x0000);
+
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8));
+	or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10));
+
+	mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8,
+		    (0x7 << 10), (tx_lpf_bw << 10));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 0), (hpvga_hpc << 0));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 4), (lpf_hpc << 4));
+	mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d,
+		    (0x7 << 8), (rx_lpf_bw << 8));
+
+	rccal_stepsize = 16;
+	rccal_val = start_rccal_ovr_val + rccal_stepsize;
+
+	while (rccal_stepsize >= 0) {
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 radio_addr_offset_rx), rccal_val);
+
+		if (rccal_stepsize == 16) {
+
+			wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+			if (core_idx == 0) {
+				ref_iq_vals =
+				    max_t(u32, (est[0].i_pwr +
+					 est[0].q_pwr) >> (log_num_samps + 1),
+					1);
+			} else {
+				ref_iq_vals =
+				    max_t(u32, (est[1].i_pwr +
+					 est[1].q_pwr) >> (log_num_samps + 1),
+					1);
+			}
+
+			wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+		}
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+		if (core_idx == 0) {
+			target_iq_vals =
+			    (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
+							      1);
+		} else {
+			target_iq_vals =
+			    (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
+							      1);
+		}
+		pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
+
+		if (rccal_stepsize == 0) {
+			rccal_stepsize--;
+		} else if (rccal_stepsize == 1) {
+			last_rccal_val = rccal_val;
+			rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
+			last_pwr_ratio = pwr_ratio;
+			rccal_stepsize--;
+		} else {
+			rccal_stepsize = (rccal_stepsize >> 1);
+			rccal_val += ((pwr_ratio > target_pwr_ratio) ?
+				      rccal_stepsize : (-rccal_stepsize));
+		}
+
+		if (rccal_stepsize == -1) {
+			best_rccal_val =
+			    (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
+			     ABS((int)pwr_ratio -
+				 (int)target_pwr_ratio)) ? last_rccal_val :
+			    rccal_val;
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				if ((best_rccal_val > 140)
+				    || (best_rccal_val < 135)) {
+					best_rccal_val = 138;
+				}
+			} else {
+				if ((best_rccal_val > 142)
+				    || (best_rccal_val < 137)) {
+					best_rccal_val = 140;
+				}
+			}
+
+			write_radio_reg(pi,
+					(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+					 radio_addr_offset_rx), best_rccal_val);
+		}
+	}
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			orig_txlpf_rccal_lpc_ovr_val);
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			orig_rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8));
+
+	write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]);
+	write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]);
+	write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]);
+	write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]);
+	write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]);
+	write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]);
+	write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]);
+	write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]);
+	write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]);
+	write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]);
+
+	write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]);
+	write_phy_reg(pi, 0xec, orig_rfctrloverride[1]);
+	write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]);
+	write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]);
+	write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers);
+
+	pi->nphy_anarxlpf_adjusted = false;
+
+	return best_rccal_val - 0x80;
+}
+
+#define WAIT_FOR_SCOPE	4000
+static int
+wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t target_gain,
+			   u8 cal_type, bool debug)
+{
+	u16 orig_BBConfig;
+	u8 core_no, rx_core;
+	u8 best_rccal[2];
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	nphy_iqcal_params_t cal_params[2];
+	u8 rxcore_state;
+	s8 rxlpf_rccal_hpc, txlpf_rccal_lpc;
+	s8 txlpf_idac;
+	bool phyhang_avoid_state = false;
+	bool skip_rxiqcal = false;
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
+
+	for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+
+		skip_rxiqcal =
+		    ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
+
+		wlc_phy_rxcal_physetup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_radio_setup_nphy(pi, rx_core);
+
+		if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) {
+
+			wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
+
+			wlc_phy_tx_tone_nphy(pi,
+					     (CHSPEC_IS40(pi->radio_chanspec)) ?
+					     NPHY_RXCAL_TONEFREQ_40MHz :
+					     NPHY_RXCAL_TONEFREQ_20MHz,
+					     NPHY_RXCAL_TONEAMP, 0, cal_type,
+					     false);
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1);
+			wlc_phy_stopplayback_nphy(pi);
+		}
+
+		if (((cal_type == 1) || (cal_type == 2))
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+			if (rx_core == PHY_CORE_1) {
+
+				if (rxcore_state == 1) {
+					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
+								      *) pi, 3);
+				}
+
+				wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
+							    1);
+
+				best_rccal[rx_core] =
+				    wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
+				pi->nphy_rccal_value = best_rccal[rx_core];
+
+				if (rxcore_state == 1) {
+					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
+								      *) pi,
+								     rxcore_state);
+				}
+			}
+		}
+
+		wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_phycleanup_nphy(pi, rx_core);
+		wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	}
+
+	if ((cal_type == 1) || (cal_type == 2)) {
+
+		best_rccal[0] = best_rccal[1];
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 RADIO_2056_RX0), (best_rccal[0] | 0x80));
+
+		for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+			rxlpf_rccal_hpc =
+			    (((int)best_rccal[rx_core] - 12) >> 1) + 10;
+			txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
+
+			if (PHY_IPA(pi)) {
+				txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
+				txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
+						 TXLPF_IDAC_4, txlpf_idac);
+			}
+
+			rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
+			txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
+
+			write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_RX0 :
+					      RADIO_2056_RX1)),
+					(rxlpf_rccal_hpc | 0x80));
+
+			write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_TX0 :
+					      RADIO_2056_TX1)),
+					(txlpf_rccal_lpc | 0x80));
+		}
+	}
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	wlc_phy_resetcca_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+						     0, 0x3, 1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+	}
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		pi->phyhang_avoid = phyhang_avoid_state;
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return BCME_OK;
+}
+
+static int
+wlc_phy_cal_rxiq_nphy_rev2(phy_info_t *pi, nphy_txgains_t target_gain,
+			   bool debug)
+{
+	phy_iq_est_t est[PHY_CORE_MAX];
+	u8 core_num, rx_core, tx_core;
+	u16 lna_vals[] = { 0x3, 0x3, 0x1 };
+	u16 hpf1_vals[] = { 0x7, 0x2, 0x0 };
+	u16 hpf2_vals[] = { 0x2, 0x0, 0x0 };
+	s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna;
+	s16 desired_log2_pwr, actual_log2_pwr, hpf_change;
+	u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride;
+	u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx;
+	u16 num_samps;
+	u32 i_pwr, q_pwr, tot_pwr[3];
+	u8 gain_pass, use_hpf_num;
+	u16 mask, val1, val2;
+	u16 core_no;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	nphy_iqcal_params_t cal_params[2];
+	u8 phy_bw;
+	int bcmerror = BCME_OK;
+	bool first_playtone = true;
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		wlc_phy_reapply_txcal_coeffs_nphy(pi);
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	num_samps = 1024;
+	desired_log2_pwr = 13;
+
+	for (core_num = 0; core_num < 2; core_num++) {
+
+		rx_core = core_num;
+		tx_core = 1 - core_num;
+
+		orig_RfseqCoreActv = read_phy_reg(pi, 0xa2);
+		orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						0xa6 : 0xa7);
+		orig_AfectrlOverride = read_phy_reg(pi, 0xa5);
+		orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+		orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			   ((0x1 << 1) | (0x1 << 2)));
+		or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
+
+		if (((pi->nphy_rxcalparams) & 0xff000000)) {
+
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
+				       0x110));
+		} else {
+
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
+				       0x120));
+		}
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
+			      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
+			       0x114));
+
+		mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK;
+		if (rx_core == PHY_CORE_0) {
+			val1 = RADIO_2055_COUPLE_RX_MASK;
+			val2 = RADIO_2055_COUPLE_TX_MASK;
+		} else {
+			val1 = RADIO_2055_COUPLE_TX_MASK;
+			val2 = RADIO_2055_COUPLE_RX_MASK;
+		}
+
+		if ((pi->nphy_rxcalparams & 0x10000)) {
+			mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask,
+				      val1);
+			mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask,
+				      val2);
+		}
+
+		for (gain_pass = 0; gain_pass < 4; gain_pass++) {
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			if (gain_pass < 3) {
+				curr_lna = lna_vals[gain_pass];
+				curr_hpf1 = hpf1_vals[gain_pass];
+				curr_hpf2 = hpf2_vals[gain_pass];
+			} else {
+
+				if (tot_pwr[1] > 10000) {
+					curr_lna = lna_vals[2];
+					curr_hpf1 = hpf1_vals[2];
+					curr_hpf2 = hpf2_vals[2];
+					use_hpf_num = 1;
+					curr_hpf = curr_hpf1;
+					actual_log2_pwr =
+					    wlc_phy_nbits(tot_pwr[2]);
+				} else {
+					if (tot_pwr[0] > 10000) {
+						curr_lna = lna_vals[1];
+						curr_hpf1 = hpf1_vals[1];
+						curr_hpf2 = hpf2_vals[1];
+						use_hpf_num = 1;
+						curr_hpf = curr_hpf1;
+						actual_log2_pwr =
+						    wlc_phy_nbits(tot_pwr[1]);
+					} else {
+						curr_lna = lna_vals[0];
+						curr_hpf1 = hpf1_vals[0];
+						curr_hpf2 = hpf2_vals[0];
+						use_hpf_num = 2;
+						curr_hpf = curr_hpf2;
+						actual_log2_pwr =
+						    wlc_phy_nbits(tot_pwr[0]);
+					}
+				}
+
+				hpf_change = desired_log2_pwr - actual_log2_pwr;
+				curr_hpf += hpf_change;
+				curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
+				if (use_hpf_num == 1) {
+					curr_hpf1 = curr_hpf;
+				} else {
+					curr_hpf2 = curr_hpf;
+				}
+			}
+
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
+						     ((curr_hpf2 << 8) |
+						      (curr_hpf1 << 4) |
+						      (curr_lna << 2)), 0x3, 0);
+			wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+			wlc_phy_stopplayback_nphy(pi);
+
+			if (first_playtone) {
+				bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
+								(u16) (pi->
+									  nphy_rxcalparams
+									  &
+									  0xffff),
+								0, 0, true);
+				first_playtone = false;
+			} else {
+				phy_bw =
+				    (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
+				wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
+							0, 0, 0, true);
+			}
+
+			if (bcmerror == BCME_OK) {
+				if (gain_pass < 3) {
+
+					wlc_phy_rx_iq_est_nphy(pi, est,
+							       num_samps, 32,
+							       0);
+					i_pwr =
+					    (est[rx_core].i_pwr +
+					     num_samps / 2) / num_samps;
+					q_pwr =
+					    (est[rx_core].q_pwr +
+					     num_samps / 2) / num_samps;
+					tot_pwr[gain_pass] = i_pwr + q_pwr;
+				} else {
+
+					wlc_phy_calc_rx_iq_comp_nphy(pi,
+								     (1 <<
+								      rx_core));
+				}
+
+				wlc_phy_stopplayback_nphy(pi);
+			}
+
+			if (bcmerror != BCME_OK)
+				break;
+		}
+
+		and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask);
+		and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask);
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcTx);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcRx);
+		write_phy_reg(pi, 0xa5, orig_AfectrlOverride);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 :
+			      0xa7, orig_AfectrlCore);
+		write_phy_reg(pi, 0xa2, orig_RfseqCoreActv);
+
+		if (bcmerror != BCME_OK)
+			break;
+	}
+
+	wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+int
+wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+		      u8 cal_type, bool debug)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		cal_type = 0;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
+						  debug);
+	} else {
+		return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
+	}
+}
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi)
+{
+	int j, type = 2;
+	u16 addr_offset = 0x2c5;
+
+	for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+		write_phy_reg(pi, addr_offset + j,
+			      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+	}
+}
+
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi)
+{
+	int j, type;
+	u16 addr_offset[] = { 0x186, 0x195,
+		0x2c5
+	};
+
+	for (type = 0; type < 3; type++) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, addr_offset[type] + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+		}
+	}
+
+	if (IS40MHZ(pi)) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+		}
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, 0x186 + j,
+					      NPHY_IPA_REV4_txdigi_filtcoeffs[5]
+					      [j]);
+			}
+		}
+
+		if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, 0x2c5 + j,
+					      NPHY_IPA_REV4_txdigi_filtcoeffs[6]
+					      [j]);
+			}
+		}
+	}
+}
+
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi)
+{
+	int j;
+
+	if (IS40MHZ(pi)) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x195 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
+		}
+	} else {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+		}
+	}
+}
+
+static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi)
+{
+	u16 m0m1;
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	return m0m1;
+}
+
+static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1)
+{
+	u16 m0m1 = (u16) ((m0 << 8) | m1);
+
+	wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
+	wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
+}
+
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi)
+{
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev4n6;
+			} else if (pi->pubpi.radiorev == 3) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev3;
+			} else if (pi->pubpi.radiorev == 5) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev5;
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev7;
+			} else {
+				ASSERT(0);
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+			if (pi->sh->chip == BCM47162_CHIP_ID) {
+
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+		} else {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
+		}
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_5g_2057rev7;
+			} else {
+				ASSERT(0);
+			}
+
+		} else {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
+		}
+	}
+
+	return tx_pwrctrl_tbl;
+}
+
+static void
+wlc_phy_papd_cal_setup_nphy(phy_info_t *pi, nphy_papd_restore_state *state,
+			    u8 core)
+{
+	s32 tone_freq;
+	u8 off_core;
+	u16 mixgain = 0;
+
+	off_core = core ^ 0x1;
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+				mixgain = (core == 0) ? 0x20 : 0x00;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				mixgain = 0x00;
+
+			} else if ((pi->pubpi.radiorev <= 4)
+				   || (pi->pubpi.radiorev == 6)) {
+
+				mixgain = 0x00;
+			} else {
+				ASSERT(0);
+			}
+
+		} else {
+			if ((pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				mixgain = 0x50;
+			} else if ((pi->pubpi.radiorev == 3)
+				   || (pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				mixgain = 0x0;
+			} else {
+				ASSERT(0);
+			}
+		}
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+						  mixgain, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+						     1, (1 << core), 0);
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+						     0, (1 << off_core), 0);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+						  0, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+		state->afectrl[off_core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
+		state->afeoverride[off_core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5), (0x1 << 2), (0x1 << 2));
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
+			    (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
+				 0x8f), (0x1 << 2), (0x1 << 2));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->pwrup[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_2G_PWRUP);
+			state->atten[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_2G_ATTEN);
+			state->pwrup[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_2G_PWRUP);
+			state->atten[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_2G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_2G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			} else if (pi->pubpi.radiorev == 5) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 (core == 0) ? 0xf7 : 0xf2);
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			} else {
+				ASSERT(0);
+			}
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_ATTEN, 0xff);
+
+		} else {
+			state->pwrup[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_5G_PWRUP);
+			state->atten[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_5G_ATTEN);
+			state->pwrup[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_5G_PWRUP);
+			state->atten[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_5G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_5G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf4);
+
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf0);
+			}
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_ATTEN, 0xff);
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5),
+			    (0x1 << 0) |
+			    (0x1 << 1) |
+			    (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+
+		state->vga_master[core] =
+		    READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
+		WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->fbmix[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+					    TXFBMIX_G);
+			state->intpa_master[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+					    INTPAG_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAG_MASTER, 0x04);
+		} else {
+			state->fbmix[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+					    TXFBMIX_A);
+			state->intpa_master[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+					    INTPAA_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_MASTER, 0x04);
+
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+	}
+}
+
+static void
+wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi, nphy_papd_restore_state *state)
+{
+	u8 core;
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 state->atten[core]);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN,
+						 state->atten[core]);
+			}
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  0, 0x3, 1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		}
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
+							  1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
+					 state->vga_master[core]);
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_G, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_MASTER,
+						 state->intpa_master[core]);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_A, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAA_MASTER,
+						 state->intpa_master[core]);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
+	}
+}
+
+static void
+wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32 start,
+		u32 end)
+{
+	u32 *buf, *src, *dst, sz;
+
+	sz = end - start + 1;
+	ASSERT(end > start);
+	ASSERT(end < NPHY_PAPD_EPS_TBL_SIZE);
+
+	buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
+	if (NULL == buf) {
+		return;
+	}
+
+	src = buf;
+	dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
+
+	wlc_phy_table_read_nphy(pi,
+				(core ==
+				 PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1),
+				NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
+
+	do {
+		u32 phy_a1, phy_a2;
+		s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
+
+		phy_a1 = end - min(end, (winsz >> 1));
+		phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
+		phy_a3 = phy_a2 - phy_a1 + 1;
+		phy_a6 = 0;
+		phy_a7 = 0;
+
+		do {
+			wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
+						    &phy_a5);
+			phy_a6 += phy_a4;
+			phy_a7 += phy_a5;
+		} while (phy_a2-- != phy_a1);
+
+		phy_a6 /= phy_a3;
+		phy_a7 /= phy_a3;
+		dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
+	} while (end-- != start);
+
+	wlc_phy_table_write_nphy(pi,
+				 (core ==
+				  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
+
+	kfree(buf);
+}
+
+static void
+wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *txgains,
+		phy_cal_mode_t cal_mode, u8 core)
+{
+	u16 phy_a1, phy_a2, phy_a3;
+	u16 phy_a4, phy_a5;
+	bool phy_a6;
+	u8 phy_a7, m[2];
+	u32 phy_a8 = 0;
+	nphy_txgains_t phy_a9;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3))
+		return;
+
+	phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
+
+	ASSERT((cal_mode == CAL_FULL) || (cal_mode == CAL_GCTRL)
+	       || (cal_mode == CAL_SOFT));
+	phy_a6 = ((cal_mode == CAL_GCTRL)
+		  || (cal_mode == CAL_SOFT)) ? true : false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (phy_a9.pga[core] << 8) |
+				  (txgains->gains.pad[core] << 3) |
+				  (phy_a9.ipa[core]));
+		} else {
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (txgains->gains.pga[core] << 8) |
+				  (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_txgain,
+						     phy_a5, (1 << core), 0);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+
+				m[core] = IS40MHZ(pi) ? 60 : 79;
+			} else {
+
+				m[core] = IS40MHZ(pi) ? 45 : 64;
+			}
+
+		} else {
+			m[core] = IS40MHZ(pi) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->sh->chip == BCM6362_CHIP_ID) {
+				phy_a1 = 35;
+				phy_a3 = 35;
+			} else if ((pi->pubpi.radiorev == 4)
+				   || (pi->pubpi.radiorev == 6)) {
+				phy_a1 = 30;
+				phy_a3 = 30;
+			} else {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			}
+		} else {
+			if ((pi->pubpi.radiorev == 5)
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			} else {
+				phy_a1 = 35;
+				phy_a3 = 35;
+			}
+		}
+
+		if (cal_mode == CAL_GCTRL) {
+			if ((pi->pubpi.radiorev == 5)
+			    && (CHSPEC_IS2G(pi->radio_chanspec))) {
+				phy_a1 = 55;
+			} else if (((pi->pubpi.radiorev == 7) &&
+				    (CHSPEC_IS2G(pi->radio_chanspec))) ||
+				   ((pi->pubpi.radiorev == 8) &&
+				    (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				phy_a1 = 60;
+			} else {
+				phy_a1 = 63;
+			}
+
+		} else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
+
+			phy_a1 = 35;
+			phy_a3 = 35;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		write_phy_reg(pi, 0x2a1, 0x80);
+		write_phy_reg(pi, 0x2a2, 0x100);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 4), (11) << 4);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 8), (11) << 8);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 0), (0x3) << 0);
+
+		write_phy_reg(pi, 0x2e5, 0x20);
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  1, ((core == 0) ? 1 : 2), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, ((core == 0) ? 2 : 1), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				wlc_phy_a1_nphy(pi, core, 5, 0, 35);
+			}
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_txgain,
+						     phy_a5, (1 << core), 1);
+
+	} else {
+
+		if (txgains) {
+			if (txgains->useindex) {
+				phy_a4 = 15 - ((txgains->index) >> 3);
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+						phy_a5 = 0x00f7 | (phy_a4 << 8);
+
+						if (pi->sh->chip ==
+						    BCM47162_CHIP_ID) {
+							phy_a5 =
+							    0x10f7 | (phy_a4 <<
+								      8);
+						}
+					} else
+					    if (NREV_IS(pi->pubpi.phy_rev, 5))
+						phy_a5 = 0x10f7 | (phy_a4 << 8);
+					else
+						phy_a5 = 0x50f7 | (phy_a4 << 8);
+				} else {
+					phy_a5 = 0x70f7 | (phy_a4 << 8);
+				}
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     phy_a5,
+							     (1 << core), 0);
+			} else {
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     0x5bf7,
+							     (1 << core), 0);
+			}
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			m[core] = IS40MHZ(pi) ? 45 : 64;
+		} else {
+			m[core] = IS40MHZ(pi) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (cal_mode == CAL_FULL) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_SOFT) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_GCTRL) {
+			phy_a1 = 63;
+			phy_a3 = 25;
+		} else {
+
+			phy_a1 = 25;
+			phy_a3 = 25;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (1) << 13);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (0) << 13);
+
+			write_phy_reg(pi, 0x2a1, 0x20);
+			write_phy_reg(pi, 0x2a2, 0x60);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 4), (9) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 8), (9) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 0), (0x2) << 0);
+
+			write_phy_reg(pi, 0x2e5, 0x20);
+		} else {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (1) << 11);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (0) << 11);
+
+			write_phy_reg(pi, 0x2a1, 0x80);
+			write_phy_reg(pi, 0x2a2, 0x600);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 4), (0) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 8), (0) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 0), (0x3) << 0);
+
+			mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
+
+		}
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			wlc_phy_a1_nphy(pi, core, 5, 0, 40);
+		}
+	}
+}
+
+static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core)
+{
+	int phy_a1;
+	int phy_a2;
+	bool phy_a3;
+	nphy_ipa_txcalgains_t phy_a4;
+	bool phy_a5 = false;
+	bool phy_a6 = true;
+	s32 phy_a7, phy_a8;
+	u32 phy_a9;
+	int phy_a10;
+	bool phy_a11 = false;
+	int phy_a12;
+	u8 phy_a13 = 0;
+	u8 phy_a14;
+	u8 *phy_a15 = NULL;
+
+	phy_a4.useindex = true;
+	phy_a12 = start_gain;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a2 = 20;
+		phy_a1 = 1;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+
+				phy_a15 = pad_gain_codes_used_2057rev5;
+				phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
+				    sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				phy_a15 = pad_gain_codes_used_2057rev7;
+				phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
+				    sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
+
+			} else {
+
+				phy_a15 = pad_all_gain_codes_2057;
+				phy_a13 = sizeof(pad_all_gain_codes_2057) /
+				    sizeof(pad_all_gain_codes_2057[0]) - 1;
+			}
+
+		} else {
+
+			phy_a15 = pga_all_gain_codes_2057;
+			phy_a13 = sizeof(pga_all_gain_codes_2057) /
+			    sizeof(pga_all_gain_codes_2057[0]) - 1;
+		}
+
+		phy_a14 = 0;
+
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_a4.gains.pad[core] =
+				    (u16) phy_a15[phy_a12];
+			} else {
+				phy_a4.gains.pga[core] =
+				    (u16) phy_a15[phy_a12];
+			}
+
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+				  (phy_a8 == 4095) || (phy_a8 == -4096));
+
+			if (!phy_a6 && (phy_a3 != phy_a5)) {
+				if (!phy_a3) {
+					phy_a12 -= (u8) phy_a1;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			if (phy_a3)
+				phy_a12 += (u8) phy_a1;
+			else
+				phy_a12 -= (u8) phy_a1;
+
+			if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
+				if (phy_a12 < phy_a14) {
+					phy_a12 = phy_a14;
+				} else {
+					phy_a12 = phy_a13;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			phy_a6 = false;
+			phy_a5 = phy_a3;
+		}
+
+	} else {
+		phy_a2 = 10;
+		phy_a1 = 8;
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			phy_a4.index = (u8) phy_a12;
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
+
+			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
+				  (phy_a8 == 4095) || (phy_a8 == -4096));
+
+			if (!phy_a6 && (phy_a3 != phy_a5)) {
+				if (!phy_a3) {
+					phy_a12 -= (u8) phy_a1;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			if (phy_a3)
+				phy_a12 += (u8) phy_a1;
+			else
+				phy_a12 -= (u8) phy_a1;
+
+			if ((phy_a12 < 0) || (phy_a12 > 127)) {
+				if (phy_a12 < 0) {
+					phy_a12 = 0;
+				} else {
+					phy_a12 = 127;
+				}
+				phy_a11 = true;
+				break;
+			}
+
+			phy_a6 = false;
+			phy_a5 = phy_a3;
+		}
+
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		return (u8) phy_a15[phy_a12];
+	} else {
+		return (u8) phy_a12;
+	}
+
+}
+
+static void wlc_phy_a4(phy_info_t *pi, bool full_cal)
+{
+	nphy_ipa_txcalgains_t phy_b1[2];
+	nphy_papd_restore_state phy_b2;
+	bool phy_b3;
+	u8 phy_b4;
+	u8 phy_b5;
+	s16 phy_b6, phy_b7, phy_b8;
+	u16 phy_b9;
+	s16 phy_b10, phy_b11, phy_b12;
+
+	phy_b11 = 0;
+	phy_b12 = 0;
+	phy_b7 = 0;
+	phy_b8 = 0;
+	phy_b6 = 0;
+
+	if (pi->nphy_papd_skip == 1)
+		return;
+
+	phy_b3 =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!phy_b3) {
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	pi->nphy_force_papd_cal = false;
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
+		pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
+		    wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
+
+	pi->nphy_papd_last_cal = pi->sh->now;
+	pi->nphy_papd_recal_counter++;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	phy_b4 = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
+				 nphy_papd_scaltbl);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
+				 nphy_papd_scaltbl);
+
+	phy_b9 = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		s32 i, val = 0;
+		for (i = 0; i < 64; i++) {
+			wlc_phy_table_write_nphy(pi,
+						 ((phy_b5 ==
+						   PHY_CORE_0) ?
+						  NPHY_TBL_ID_EPSILONTBL0 :
+						  NPHY_TBL_ID_EPSILONTBL1), 1,
+						 i, 32, &val);
+		}
+	}
+
+	wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
+
+	phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+				if ((pi->pubpi.radiorev == 3)
+				    || (pi->pubpi.radiorev == 4)
+				    || (pi->pubpi.radiorev == 6)) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    23;
+
+				} else if (pi->pubpi.radiorev == 5) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    0;
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    wlc_phy_a3_nphy(pi,
+							    pi->
+							    nphy_papd_cal_gain_index
+							    [phy_b5], phy_b5);
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    0;
+					pi->nphy_papd_cal_gain_index[phy_b5] =
+					    wlc_phy_a3_nphy(pi,
+							    pi->
+							    nphy_papd_cal_gain_index
+							    [phy_b5], phy_b5);
+
+				} else {
+					ASSERT(0);
+				}
+
+				phy_b1[phy_b5].gains.pad[phy_b5] =
+				    pi->nphy_papd_cal_gain_index[phy_b5];
+
+			} else {
+				pi->nphy_papd_cal_gain_index[phy_b5] = 0;
+				pi->nphy_papd_cal_gain_index[phy_b5] =
+				    wlc_phy_a3_nphy(pi,
+						    pi->
+						    nphy_papd_cal_gain_index
+						    [phy_b5], phy_b5);
+				phy_b1[phy_b5].gains.pga[phy_b5] =
+				    pi->nphy_papd_cal_gain_index[phy_b5];
+			}
+		} else {
+			phy_b1[phy_b5].useindex = true;
+			phy_b1[phy_b5].index = 16;
+			phy_b1[phy_b5].index =
+			    wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5);
+
+			pi->nphy_papd_cal_gain_index[phy_b5] =
+			    15 - ((phy_b1[phy_b5].index) >> 3);
+		}
+
+		switch (pi->nphy_papd_cal_type) {
+		case 0:
+			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
+			break;
+		case 1:
+			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
+			break;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
+		}
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
+	}
+
+	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
+		int eps_offset = 0;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev == 3) {
+					eps_offset = -2;
+				} else if (pi->pubpi.radiorev == 5) {
+					eps_offset = 3;
+				} else {
+					eps_offset = -1;
+				}
+			} else {
+				eps_offset = 2;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
+				phy_b10 = 0;
+				if ((pi->pubpi.radiorev == 3) ||
+				    (pi->pubpi.radiorev == 4) ||
+				    (pi->pubpi.radiorev == 6)) {
+					phy_b12 =
+					    -
+					    (nphy_papd_padgain_dlt_2g_2057rev3n4
+					     [phy_b8]
+					     + 1) / 2;
+					phy_b10 = -1;
+				} else if (pi->pubpi.radiorev == 5) {
+					phy_b12 =
+					    -(nphy_papd_padgain_dlt_2g_2057rev5
+					      [phy_b8]
+					      + 1) / 2;
+				} else if ((pi->pubpi.radiorev == 7) ||
+					   (pi->pubpi.radiorev == 8)) {
+					phy_b12 =
+					    -(nphy_papd_padgain_dlt_2g_2057rev7
+					      [phy_b8]
+					      + 1) / 2;
+				} else {
+					ASSERT(0);
+				}
+			} else {
+				phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
+				if ((pi->pubpi.radiorev == 3) ||
+				    (pi->pubpi.radiorev == 4) ||
+				    (pi->pubpi.radiorev == 6)) {
+					phy_b11 =
+					    -(nphy_papd_pgagain_dlt_5g_2057
+					      [phy_b7]
+					      + 1) / 2;
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+					phy_b11 =
+					    -(nphy_papd_pgagain_dlt_5g_2057rev7
+					      [phy_b7]
+					      + 1) / 2;
+				} else {
+					ASSERT(0);
+				}
+
+				phy_b10 = -9;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b6 =
+				    -60 + 27 + eps_offset + phy_b12 + phy_b10;
+			} else {
+				phy_b6 =
+				    -60 + 27 + eps_offset + phy_b11 + phy_b10;
+			}
+
+			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7), (phy_b6) << 7);
+
+			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+		} else {
+			if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+				eps_offset = 4;
+			} else {
+				eps_offset = 2;
+			}
+
+			phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_b11 =
+				    -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] +
+				      1) / 2;
+				phy_b10 = 0;
+			} else {
+				phy_b11 =
+				    -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] +
+				      1) / 2;
+				phy_b10 = -9;
+			}
+
+			phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
+
+			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7), (phy_b6) << 7);
+
+			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
+		}
+	}
+
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 11), (0) << 11);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 11), (0) << 11);
+
+	}
+	pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
+
+	write_phy_reg(pi, 0x01, phy_b9);
+
+	wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
+	if (phy_b4 == PHY_TPC_HW_OFF) {
+		wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+					 (s8) (pi->nphy_txpwrindex[0].
+						 index_internal), false);
+		wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+					 (s8) (pi->nphy_txpwrindex[1].
+						 index_internal), false);
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!phy_b3) {
+		wlapi_enable_mac(pi->sh->physhim);
+	}
+}
+
+void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi)
+{
+	uint core;
+	u32 txgain;
+	u16 rad_gain, dac_gain, bbmult, m1m2;
+	u8 txpi[2], chan_freq_range;
+	s32 rfpwr_offset;
+
+	ASSERT(pi->nphy_txpwrctrl == PHY_TPC_HW_OFF);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->sh->sromrev < 4) {
+		txpi[0] = txpi[1] = 72;
+	} else {
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		switch (chan_freq_range) {
+		case WL_CHAN_FREQ_RANGE_2G:
+			txpi[0] = pi->nphy_txpid2g[0];
+			txpi[1] = pi->nphy_txpid2g[1];
+			break;
+		case WL_CHAN_FREQ_RANGE_5GL:
+			txpi[0] = pi->nphy_txpid5gl[0];
+			txpi[1] = pi->nphy_txpid5gl[1];
+			break;
+		case WL_CHAN_FREQ_RANGE_5GM:
+			txpi[0] = pi->nphy_txpid5g[0];
+			txpi[1] = pi->nphy_txpid5g[1];
+			break;
+		case WL_CHAN_FREQ_RANGE_5GH:
+			txpi[0] = pi->nphy_txpid5gh[0];
+			txpi[1] = pi->nphy_txpid5gh[1];
+			break;
+		default:
+			txpi[0] = txpi[1] = 91;
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		txpi[0] = txpi[1] = 30;
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		txpi[0] = txpi[1] = 40;
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		if ((txpi[0] < 40) || (txpi[0] > 100) ||
+		    (txpi[1] < 40) || (txpi[1] > 100))
+			txpi[0] = txpi[1] = 91;
+	}
+
+	pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0];
+	pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1];
+	pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0];
+	pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1];
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (PHY_IPA(pi)) {
+				u32 *tx_gaintbl =
+				    wlc_phy_get_ipa_gaintbl_nphy(pi);
+				txgain = tx_gaintbl[txpi[core]];
+			} else {
+				if (CHSPEC_IS5G(pi->radio_chanspec)) {
+					if NREV_IS
+						(pi->pubpi.phy_rev, 3) {
+						txgain =
+						    nphy_tpc_5GHz_txgain_rev3
+						    [txpi[core]];
+					} else if NREV_IS
+						(pi->pubpi.phy_rev, 4) {
+						txgain =
+						    (pi->srom_fem5g.extpagain ==
+						     3) ?
+						    nphy_tpc_5GHz_txgain_HiPwrEPA
+						    [txpi[core]] :
+						    nphy_tpc_5GHz_txgain_rev4
+						    [txpi[core]];
+					} else {
+						txgain =
+						    nphy_tpc_5GHz_txgain_rev5
+						    [txpi[core]];
+					}
+				} else {
+					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3)) {
+						txgain =
+						    nphy_tpc_txgain_HiPwrEPA
+						    [txpi[core]];
+					} else {
+						txgain =
+						    nphy_tpc_txgain_rev3[txpi
+									 [core]];
+					}
+				}
+			}
+		} else {
+			txgain = nphy_tpc_txgain[txpi[core]];
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
+		} else {
+			rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1);
+		} else {
+			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
+		}
+		bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+					 0xa5), (0x1 << 8), (0x1 << 8));
+		} else {
+			mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
+		}
+		write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
+
+		wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+					 &rad_gain);
+
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+		m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+		m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+		wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_CORE1TXPWRCTL :
+						 NPHY_TBL_ID_CORE2TXPWRCTL), 1,
+						576 + txpi[core], 32,
+						&rfpwr_offset);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1ff << 4),
+				    ((s16) rfpwr_offset) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (1) << 2);
+
+		}
+	}
+
+	and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0)));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset,
+				u8 tmp_max_pwr, u8 rate_start,
+				u8 rate_end)
+{
+	u8 rate;
+	u8 word_num, nibble_num;
+	u8 tmp_nibble;
+
+	for (rate = rate_start; rate <= rate_end; rate++) {
+		word_num = (rate - rate_start) >> 2;
+		nibble_num = (rate - rate_start) & 0x3;
+		tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf;
+
+		srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble;
+	}
+}
+
+static void
+wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
+			    u8 rate_start, u8 rate_end)
+{
+	u8 rate;
+
+	for (rate = rate_start; rate <= rate_end; rate++) {
+		srom_max[rate] -= 2 * pwr_offset;
+	}
+}
+
+void
+wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+				u8 rate_mcs_end, u8 rate_ofdm_start)
+{
+	u8 rate1, rate2;
+
+	rate2 = rate_ofdm_start;
+	for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) {
+		power[rate1] = power[rate2];
+		rate2 += (rate1 == rate_mcs_start) ? 2 : 1;
+	}
+	power[rate_mcs_end] = power[rate_mcs_end - 1];
+}
+
+void
+wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
+				u8 rate_ofdm_end, u8 rate_mcs_start)
+{
+	u8 rate1, rate2;
+
+	for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start;
+	     rate1 <= rate_ofdm_end; rate1++, rate2++) {
+		power[rate1] = power[rate2];
+		if (rate1 == rate_ofdm_start)
+			power[++rate1] = power[rate2];
+	}
+}
+
+void wlc_phy_txpwr_apply_nphy(phy_info_t *pi)
+{
+	uint rate1, rate2, band_num;
+	u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0;
+	u8 tmp_max_pwr = 0;
+	u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
+	u8 *tx_srom_max_rate = NULL;
+
+	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
+		switch (band_num) {
+		case 0:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g,
+					  pi->nphy_pwrctrl_info[1].max_pwr_2g);
+
+			pwr_offsets1[0] = pi->cck2gpo;
+			wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g,
+							pwr_offsets1,
+							tmp_max_pwr,
+							TXP_FIRST_CCK,
+							TXP_LAST_CCK);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm2gpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs2gpo;
+
+			tmp_cddpo = pi->cdd2gpo;
+			tmp_stbcpo = pi->stbc2gpo;
+			tmp_bw40po = pi->bw402gpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_2g;
+			break;
+		case 1:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gm);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm5gpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5gpo;
+
+			tmp_cddpo = pi->cdd5gpo;
+			tmp_stbcpo = pi->stbc5gpo;
+			tmp_bw40po = pi->bw405gpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid;
+			break;
+		case 2:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gl);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm5glpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5glpo;
+
+			tmp_cddpo = pi->cdd5glpo;
+			tmp_stbcpo = pi->stbc5glpo;
+			tmp_bw40po = pi->bw405glpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_low;
+			break;
+		case 3:
+
+			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh,
+					  pi->nphy_pwrctrl_info[1].max_pwr_5gh);
+
+			pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
+			pwr_offsets1[1] =
+			    (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
+
+			pwr_offsets2 = pi->mcs5ghpo;
+
+			tmp_cddpo = pi->cdd5ghpo;
+			tmp_stbcpo = pi->stbc5ghpo;
+			tmp_bw40po = pi->bw405ghpo;
+
+			tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi;
+			break;
+		}
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1,
+						tmp_max_pwr, TXP_FIRST_OFDM,
+						TXP_LAST_OFDM);
+
+		wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate,
+						TXP_FIRST_MCS_20_SISO,
+						TXP_LAST_MCS_20_SISO,
+						TXP_FIRST_OFDM);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
+						tmp_max_pwr,
+						TXP_FIRST_MCS_20_CDD,
+						TXP_LAST_MCS_20_CDD);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
+						    TXP_FIRST_MCS_20_CDD,
+						    TXP_LAST_MCS_20_CDD);
+		}
+
+		wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+						TXP_FIRST_OFDM_20_CDD,
+						TXP_LAST_OFDM_20_CDD,
+						TXP_FIRST_MCS_20_CDD);
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
+						tmp_max_pwr,
+						TXP_FIRST_MCS_20_STBC,
+						TXP_LAST_MCS_20_STBC);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_stbcpo,
+						    TXP_FIRST_MCS_20_STBC,
+						    TXP_LAST_MCS_20_STBC);
+		}
+
+		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+						&pwr_offsets2[2], tmp_max_pwr,
+						TXP_FIRST_MCS_20_SDM,
+						TXP_LAST_MCS_20_SDM);
+
+		if (NPHY_IS_SROM_REINTERPRET) {
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_SISO,
+							TXP_LAST_MCS_40_SISO);
+
+			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+							TXP_FIRST_OFDM_40_SISO,
+							TXP_LAST_OFDM_40_SISO,
+							TXP_FIRST_MCS_40_SISO);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_CDD,
+							TXP_LAST_MCS_40_CDD);
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
+						    TXP_FIRST_MCS_40_CDD,
+						    TXP_LAST_MCS_40_CDD);
+
+			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
+							TXP_FIRST_OFDM_40_CDD,
+							TXP_LAST_OFDM_40_CDD,
+							TXP_FIRST_MCS_40_CDD);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[4],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_STBC,
+							TXP_LAST_MCS_40_STBC);
+
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_stbcpo,
+						    TXP_FIRST_MCS_40_STBC,
+						    TXP_LAST_MCS_40_STBC);
+
+			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
+							&pwr_offsets2[6],
+							tmp_max_pwr,
+							TXP_FIRST_MCS_40_SDM,
+							TXP_LAST_MCS_40_SDM);
+		} else {
+
+			for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
+			     TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM;
+			     rate1++, rate2++)
+				tx_srom_max_rate[rate1] =
+				    tx_srom_max_rate[rate2];
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
+						    tmp_bw40po,
+						    TXP_FIRST_OFDM_40_SISO,
+						    TXP_LAST_MCS_40_SDM);
+		}
+
+		tx_srom_max_rate[TXP_MCS_32] =
+		    tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
+	}
+
+	return;
+}
+
+static void wlc_phy_txpwr_srom_read_ppr_nphy(phy_info_t *pi)
+{
+	u16 bw40po, cddpo, stbcpo, bwduppo;
+	uint band_num;
+
+	if (pi->sh->sromrev >= 9) {
+
+		return;
+	}
+
+	bw40po = (u16) PHY_GETINTVAR(pi, "bw40po");
+	pi->bw402gpo = bw40po & 0xf;
+	pi->bw405gpo = (bw40po & 0xf0) >> 4;
+	pi->bw405glpo = (bw40po & 0xf00) >> 8;
+	pi->bw405ghpo = (bw40po & 0xf000) >> 12;
+
+	cddpo = (u16) PHY_GETINTVAR(pi, "cddpo");
+	pi->cdd2gpo = cddpo & 0xf;
+	pi->cdd5gpo = (cddpo & 0xf0) >> 4;
+	pi->cdd5glpo = (cddpo & 0xf00) >> 8;
+	pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
+
+	stbcpo = (u16) PHY_GETINTVAR(pi, "stbcpo");
+	pi->stbc2gpo = stbcpo & 0xf;
+	pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
+	pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
+	pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
+
+	bwduppo = (u16) PHY_GETINTVAR(pi, "bwduppo");
+	pi->bwdup2gpo = bwduppo & 0xf;
+	pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
+	pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
+	pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
+
+	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
+		switch (band_num) {
+		case 0:
+
+			pi->nphy_txpid2g[PHY_CORE_0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid2ga0");
+			pi->nphy_txpid2g[PHY_CORE_1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid2ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
+			    (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
+			    (s8) PHY_GETINTVAR(pi, "maxp2ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw0a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw0a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw1a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw1a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw2a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa2gw2a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
+			    (s8) PHY_GETINTVAR(pi, "itt2ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
+			    (s8) PHY_GETINTVAR(pi, "itt2ga1");
+
+			pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+
+			pi->ofdm2gpo = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+
+			pi->mcs2gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+			pi->mcs2gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs2gpo1");
+			pi->mcs2gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs2gpo2");
+			pi->mcs2gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs2gpo3");
+			pi->mcs2gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs2gpo4");
+			pi->mcs2gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs2gpo5");
+			pi->mcs2gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs2gpo6");
+			pi->mcs2gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs2gpo7");
+			break;
+		case 1:
+
+			pi->nphy_txpid5g[PHY_CORE_0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5ga0");
+			pi->nphy_txpid5g[PHY_CORE_1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
+			    (s8) PHY_GETINTVAR(pi, "maxp5ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
+			    (s8) PHY_GETINTVAR(pi, "maxp5ga1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw0a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw0a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw1a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw1a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw2a0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5gw2a1");
+			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
+			    (s8) PHY_GETINTVAR(pi, "itt5ga0");
+			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
+			    (s8) PHY_GETINTVAR(pi, "itt5ga1");
+
+			pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo");
+
+			pi->mcs5gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs5gpo0");
+			pi->mcs5gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs5gpo1");
+			pi->mcs5gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs5gpo2");
+			pi->mcs5gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs5gpo3");
+			pi->mcs5gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs5gpo4");
+			pi->mcs5gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs5gpo5");
+			pi->mcs5gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs5gpo6");
+			pi->mcs5gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs5gpo7");
+			break;
+		case 2:
+
+			pi->nphy_txpid5gl[0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gla0");
+			pi->nphy_txpid5gl[1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gla1");
+			pi->nphy_pwrctrl_info[0].max_pwr_5gl =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gla0");
+			pi->nphy_pwrctrl_info[1].max_pwr_5gl =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gla1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw0a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw0a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw1a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw1a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw2a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5glw2a1");
+			pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
+			pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
+
+			pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo");
+
+			pi->mcs5glpo[0] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo0");
+			pi->mcs5glpo[1] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo1");
+			pi->mcs5glpo[2] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo2");
+			pi->mcs5glpo[3] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo3");
+			pi->mcs5glpo[4] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo4");
+			pi->mcs5glpo[5] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo5");
+			pi->mcs5glpo[6] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo6");
+			pi->mcs5glpo[7] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5glpo7");
+			break;
+		case 3:
+
+			pi->nphy_txpid5gh[0] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gha0");
+			pi->nphy_txpid5gh[1] =
+			    (u8) PHY_GETINTVAR(pi, "txpid5gha1");
+			pi->nphy_pwrctrl_info[0].max_pwr_5gh =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gha0");
+			pi->nphy_pwrctrl_info[1].max_pwr_5gh =
+			    (s8) PHY_GETINTVAR(pi, "maxp5gha1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a1");
+			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a0");
+			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
+			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a1");
+			pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
+			pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
+
+			pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo");
+
+			pi->mcs5ghpo[0] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo0");
+			pi->mcs5ghpo[1] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo1");
+			pi->mcs5ghpo[2] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo2");
+			pi->mcs5ghpo[3] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo3");
+			pi->mcs5ghpo[4] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo4");
+			pi->mcs5ghpo[5] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo5");
+			pi->mcs5ghpo[6] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo6");
+			pi->mcs5ghpo[7] =
+			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo7");
+			break;
+		}
+	}
+
+	wlc_phy_txpwr_apply_nphy(pi);
+}
+
+static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi)
+{
+
+	pi->antswitch = (u8) PHY_GETINTVAR(pi, "antswitch");
+	pi->aa2g = (u8) PHY_GETINTVAR(pi, "aa2g");
+	pi->aa5g = (u8) PHY_GETINTVAR(pi, "aa5g");
+
+	pi->srom_fem2g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos2g");
+	pi->srom_fem2g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain2g");
+	pi->srom_fem2g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange2g");
+	pi->srom_fem2g.triso = (u8) PHY_GETINTVAR(pi, "triso2g");
+	pi->srom_fem2g.antswctrllut = (u8) PHY_GETINTVAR(pi, "antswctl2g");
+
+	pi->srom_fem5g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos5g");
+	pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g");
+	pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g");
+	pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g");
+	if (PHY_GETVAR(pi, "antswctl5g")) {
+
+		pi->srom_fem5g.antswctrllut =
+		    (u8) PHY_GETINTVAR(pi, "antswctl5g");
+	} else {
+
+		pi->srom_fem5g.antswctrllut =
+		    (u8) PHY_GETINTVAR(pi, "antswctl2g");
+	}
+
+	wlc_phy_txpower_ipa_upd(pi);
+
+	pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh");
+	if (pi->phy_txcore_disable_temp == 0) {
+		pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+	}
+
+	pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset");
+	if (pi->phy_tempsense_offset != 0) {
+		if (pi->phy_tempsense_offset >
+		    (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) {
+			pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
+		} else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
+						    NPHY_SROM_MINTEMPOFFSET)) {
+			pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
+		} else {
+			pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
+		}
+	}
+
+	pi->phy_txcore_enable_temp =
+	    pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
+
+	pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta");
+	if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) {
+		pi->phycal_tempdelta = 0;
+	}
+
+	wlc_phy_txpwr_srom_read_ppr_nphy(pi);
+
+	return true;
+}
+
+void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi)
+{
+	u8 tx_pwr_ctrl_state;
+	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)R_REG(&pi->regs->maccontrol);
+		udelay(1);
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+}
+
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi)
+{
+	u32 idx;
+	u16 iqloCalbuf[7];
+	u32 iqcomp, locomp, curr_locomp;
+	s8 locomp_i, locomp_q;
+	s8 curr_locomp_i, curr_locomp_q;
+	u32 tbl_id, tbl_len, tbl_offset;
+	u32 regval[128];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
+
+	tbl_len = 128;
+	tbl_offset = 320;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+		iqcomp =
+		    (tbl_id ==
+		     26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
+		    (iqloCalbuf[1] & 0x3ff)
+		    : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
+		    (iqloCalbuf[3] & 0x3ff);
+
+		for (idx = 0; idx < tbl_len; idx++) {
+			regval[idx] = iqcomp;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	tbl_offset = 448;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+		locomp =
+		    (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
+		locomp_i = (s8) ((locomp >> 8) & 0xff);
+		locomp_q = (s8) ((locomp) & 0xff);
+		for (idx = 0; idx < tbl_len; idx++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				curr_locomp_i = locomp_i;
+				curr_locomp_q = locomp_q;
+			} else {
+				curr_locomp_i = (s8) ((locomp_i *
+							 nphy_tpc_loscale[idx] +
+							 128) >> 8);
+				curr_locomp_q =
+				    (s8) ((locomp_q * nphy_tpc_loscale[idx] +
+					     128) >> 8);
+			}
+			curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
+			curr_locomp |= (u32) (curr_locomp_q & 0xff);
+			regval[idx] = curr_locomp;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_ipa_internal_tssi_setup_nphy(phy_info_t *pi)
+{
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x5);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MUX, 0xe);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0);
+
+				if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIG, 0x1);
+				} else {
+
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIG, 0x31);
+				}
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x9);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MUX, 0xc);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0);
+
+				if (pi->pubpi.radiorev != 5) {
+					if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x1);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+					}
+				}
+			}
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 0x3);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 0x0);
+		}
+	} else {
+		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
+				(CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
+				0x80);
+		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
+		WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
+					 0x3);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
+					 0x8);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
+					 0x0);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
+					 0x0);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MASTER, 0x5);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIA, 0x0);
+				if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIG, 0x31);
+				} else {
+					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
+							 core, TSSIG, 0x11);
+				}
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MUX, 0xe);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MASTER, 0x9);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TSSIA, 0x31);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TSSIG, 0x0);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 TX_SSI_MUX, 0xc);
+			}
+		}
+	}
+}
+
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi)
+{
+	s32 rssi_buf[4];
+	s32 int_val;
+
+	if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
+
+		return;
+
+	if (PHY_IPA(pi)) {
+		wlc_phy_ipa_internal_tssi_setup_nphy(pi);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
+	}
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
+
+	udelay(20);
+	int_val =
+	    wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
+				   1);
+	wlc_phy_stopplayback_nphy(pi);
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+		    (u8) ((int_val >> 24) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+		    (u8) ((int_val >> 24) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+		    (u8) ((int_val >> 8) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+		    (u8) ((int_val >> 8) & 0xff);
+	} else {
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
+		    (u8) ((int_val >> 24) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
+		    (u8) ((int_val >> 8) & 0xff);
+
+		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
+		    (u8) ((int_val >> 16) & 0xff);
+		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
+		    (u8) ((int_val) & 0xff);
+	}
+
+}
+
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi)
+{
+	u32 idx;
+	s16 a1[2], b0[2], b1[2];
+	s8 target_pwr_qtrdbm[2];
+	s32 num, den, pwr_est;
+	u8 chan_freq_range;
+	u8 idle_tssi[2];
+	u32 tbl_id, tbl_len, tbl_offset;
+	u32 regval[64];
+	u8 core;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)R_REG(&pi->regs->maccontrol);
+		udelay(1);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	or_phy_reg(pi, 0x122, (0x1 << 0));
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
+	} else {
+
+		or_phy_reg(pi, 0x1e7, (0x1 << 15));
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+
+	if (pi->sh->sromrev < 4) {
+		idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+		idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+		target_pwr_qtrdbm[0] = 13 * 4;
+		target_pwr_qtrdbm[1] = 13 * 4;
+		a1[0] = -424;
+		a1[1] = -424;
+		b0[0] = 5612;
+		b0[1] = 5612;
+		b1[1] = -1393;
+		b1[0] = -1393;
+	} else {
+
+		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
+		switch (chan_freq_range) {
+		case WL_CHAN_FREQ_RANGE_2G:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_2g;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_2g;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GL:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_5gl;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_5gl;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GM:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_5gm;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_5gm;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
+			break;
+		case WL_CHAN_FREQ_RANGE_5GH:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
+			target_pwr_qtrdbm[0] =
+			    pi->nphy_pwrctrl_info[0].max_pwr_5gh;
+			target_pwr_qtrdbm[1] =
+			    pi->nphy_pwrctrl_info[1].max_pwr_5gh;
+			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
+			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
+			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
+			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
+			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
+			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
+			break;
+		default:
+			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
+			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
+			target_pwr_qtrdbm[0] = 13 * 4;
+			target_pwr_qtrdbm[1] = 13 * 4;
+			a1[0] = -424;
+			a1[1] = -424;
+			b0[0] = 5612;
+			b0[1] = 5612;
+			b1[1] = -1393;
+			b1[0] = -1393;
+			break;
+		}
+	}
+
+	target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
+	target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->srom_fem2g.tssipos) {
+			or_phy_reg(pi, 0x1e9, (0x1 << 14));
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			for (core = 0; core <= 1; core++) {
+				if (PHY_IPA(pi)) {
+
+					if (CHSPEC_IS2G(pi->radio_chanspec)) {
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TX_SSI_MUX,
+								 0xe);
+					} else {
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TX_SSI_MUX,
+								 0xc);
+					}
+				} else {
+				}
+			}
+		} else {
+			if (PHY_IPA(pi)) {
+
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX0,
+						(CHSPEC_IS5G
+						 (pi->
+						  radio_chanspec)) ? 0xc : 0xe);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX1,
+						(CHSPEC_IS5G
+						 (pi->
+						  radio_chanspec)) ? 0xc : 0xe);
+			} else {
+
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX0, 0x11);
+				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
+						RADIO_2056_TX1, 0x11);
+			}
+		}
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
+		(void)R_REG(&pi->regs->maccontrol);
+		udelay(1);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+	} else {
+		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, 0x222, (0xff << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
+	} else if (NREV_GT(pi->pubpi.phy_rev, 1)) {
+		mod_phy_reg(pi, 0x222, (0xff << 0),
+			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
+	}
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
+
+	write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
+
+	write_phy_reg(pi, 0x1e9,
+		      (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
+
+	write_phy_reg(pi, 0x1ea,
+		      (target_pwr_qtrdbm[0] << 0) |
+		      (target_pwr_qtrdbm[1] << 8));
+
+	tbl_len = 64;
+	tbl_offset = 0;
+	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
+	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
+
+		for (idx = 0; idx < tbl_len; idx++) {
+			num =
+			    8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
+			den = 32768 + a1[tbl_id - 26] * idx;
+			pwr_est = max(((4 * num + den / 2) / den), -8);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+				if (idx <=
+				    (uint) (31 - idle_tssi[tbl_id - 26] + 1))
+					pwr_est =
+					    max(pwr_est,
+						target_pwr_qtrdbm[tbl_id - 26] +
+						1);
+			}
+			regval[idx] = (u32) pwr_est;
+		}
+		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
+					 regval);
+	}
+
+	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
+				 pi->adj_pwr_tbl_nphy);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
+				 pi->adj_pwr_tbl_nphy);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi)
+{
+	return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
+					     (0x1 << 14) | (0x1 << 13));
+}
+
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core)
+{
+	u16 tmp;
+	tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
+
+	tmp = (tmp & (0x7f << 8)) >> 8;
+	return (u8) tmp;
+}
+
+static void
+wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0, u8 idx1)
+{
+	mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
+
+	if (NREV_GT(pi->pubpi.phy_rev, 1))
+		mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
+}
+
+u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi)
+{
+	u16 tmp;
+	u16 pwr_idx[2];
+
+	if (wlc_phy_txpwr_ison_nphy(pi)) {
+		pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0);
+		pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1);
+
+		tmp = (pwr_idx[0] << 8) | pwr_idx[1];
+	} else {
+		tmp =
+		    ((pi->nphy_txpwrindex[PHY_CORE_0].
+		      index_internal & 0xff) << 8) | (pi->
+						      nphy_txpwrindex
+						      [PHY_CORE_1].
+						      index_internal & 0xff);
+	}
+
+	return tmp;
+}
+
+void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi)
+{
+	if (PHY_IPA(pi)
+	    && (pi->nphy_force_papd_cal
+		|| (wlc_phy_txpwr_ison_nphy(pi)
+		    &&
+		    (((u32)
+		      ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
+			  pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
+		     || ((u32)
+			 ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
+			     pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) {
+		wlc_phy_a4(pi, true);
+	}
+}
+
+void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type)
+{
+	u16 mask = 0, val = 0, ishw = 0;
+	u8 ctr;
+	uint core;
+	u32 tbl_offset;
+	u32 tbl_len;
+	u16 regval[84];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	switch (ctrl_type) {
+	case PHY_TPC_HW_OFF:
+	case PHY_TPC_HW_ON:
+		pi->nphy_txpwrctrl = ctrl_type;
+		break;
+	default:
+		break;
+	}
+
+	if (ctrl_type == PHY_TPC_HW_OFF) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			if (wlc_phy_txpwr_ison_nphy(pi)) {
+				for (core = 0; core < pi->pubpi.phy_corenum;
+				     core++)
+					pi->nphy_txpwr_idx[core] =
+					    wlc_phy_txpwr_idx_cur_get_nphy(pi,
+									   (u8)
+									   core);
+			}
+
+		}
+
+		tbl_len = 84;
+		tbl_offset = 64;
+		for (ctr = 0; ctr < tbl_len; ctr++) {
+			regval[ctr] = 0;
+		}
+		wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
+					 regval);
+		wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
+					 regval);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			and_phy_reg(pi, 0x1e7,
+				    (u16) (~((0x1 << 15) |
+						(0x1 << 14) | (0x1 << 13))));
+		} else {
+			and_phy_reg(pi, 0x1e7,
+				    (u16) (~((0x1 << 14) | (0x1 << 13))));
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			or_phy_reg(pi, 0x8f, (0x1 << 8));
+			or_phy_reg(pi, 0xa5, (0x1 << 8));
+		} else {
+			or_phy_reg(pi, 0xa5, (0x1 << 14));
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x53);
+		else if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
+				       MHF1_IQSWAP_WAR, WLC_BAND_ALL);
+
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64,
+					 8, pi->adj_pwr_tbl_nphy);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64,
+					 8, pi->adj_pwr_tbl_nphy);
+
+		ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0;
+		mask = (0x1 << 14) | (0x1 << 13);
+		val = (ishw << 14) | (ishw << 13);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			mask |= (0x1 << 15);
+			val |= (ishw << 15);
+		}
+
+		mod_phy_reg(pi, 0x1e7, mask, val);
+
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32);
+				mod_phy_reg(pi, 0x222, (0xff << 0), 0x32);
+			} else {
+				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64);
+				if (NREV_GT(pi->pubpi.phy_rev, 1))
+					mod_phy_reg(pi, 0x222,
+						    (0xff << 0), 0x64);
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if ((pi->nphy_txpwr_idx[0] != 128)
+			    && (pi->nphy_txpwr_idx[1] != 128)) {
+				wlc_phy_txpwr_idx_cur_set_nphy(pi,
+							       pi->
+							       nphy_txpwr_idx
+							       [0],
+							       pi->
+							       nphy_txpwr_idx
+							       [1]);
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			and_phy_reg(pi, 0x8f, ~(0x1 << 8));
+			and_phy_reg(pi, 0xa5, ~(0x1 << 8));
+		} else {
+			and_phy_reg(pi, 0xa5, ~(0x1 << 14));
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+		else if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
+				       0x0, WLC_BAND_ALL);
+
+		if (PHY_IPA(pi)) {
+			mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 2), (0) << 2);
+
+		}
+
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void
+wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask, s8 txpwrindex,
+			 bool restore_cals)
+{
+	u8 core, txpwrctl_tbl;
+	u16 tx_ind0, iq_ind0, lo_ind0;
+	u16 m1m2;
+	u32 txgain;
+	u16 rad_gain, dac_gain;
+	u8 bbmult;
+	u32 iqcomp;
+	u16 iqcomp_a, iqcomp_b;
+	u32 locomp;
+	u16 tmpval;
+	u8 tx_pwr_ctrl_state;
+	s32 rfpwr_offset;
+	u16 regval[2];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	tx_ind0 = 192;
+	iq_ind0 = 320;
+	lo_ind0 = 448;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((core_mask & (1 << core)) == 0) {
+			continue;
+		}
+
+		txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
+
+		if (txpwrindex < 0) {
+			if (pi->nphy_txpwrindex[core].index < 0) {
+
+				continue;
+			}
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				mod_phy_reg(pi, 0x8f,
+					    (0x1 << 8),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+				mod_phy_reg(pi, 0xa5, (0x1 << 8),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+			} else {
+				mod_phy_reg(pi, 0xa5,
+					    (0x1 << 14),
+					    pi->nphy_txpwrindex[core].
+					    AfectrlOverride);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xaa : 0xab,
+				      pi->nphy_txpwrindex[core].AfeCtrlDacGain);
+
+			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+						 &pi->nphy_txpwrindex[core].
+						 rad_gain);
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+			m1m2 |= ((core == PHY_CORE_0) ?
+				 (pi->nphy_txpwrindex[core].bbmult << 8) :
+				 (pi->nphy_txpwrindex[core].bbmult << 0));
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+			if (restore_cals) {
+
+				wlc_phy_table_write_nphy(pi, 15, 2,
+							 (80 + 2 * core), 16,
+							 (void *)&pi->
+							 nphy_txpwrindex[core].
+							 iqcomp_a);
+
+				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
+							 16,
+							 &pi->
+							 nphy_txpwrindex[core].
+							 locomp);
+				wlc_phy_table_write_nphy(pi, 15, 1, (93 + core),
+							 16,
+							 (void *)&pi->
+							 nphy_txpwrindex[core].
+							 locomp);
+			}
+
+			wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+
+			pi->nphy_txpwrindex[core].index_internal =
+			    pi->nphy_txpwrindex[core].index_internal_save;
+		} else {
+
+			if (pi->nphy_txpwrindex[core].index < 0) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					mod_phy_reg(pi, 0x8f,
+						    (0x1 << 8),
+						    pi->nphy_txpwrindex[core].
+						    AfectrlOverride);
+					mod_phy_reg(pi, 0xa5, (0x1 << 8),
+						    pi->nphy_txpwrindex[core].
+						    AfectrlOverride);
+				} else {
+					pi->nphy_txpwrindex[core].
+					    AfectrlOverride =
+					    read_phy_reg(pi, 0xa5);
+				}
+
+				pi->nphy_txpwrindex[core].AfeCtrlDacGain =
+				    read_phy_reg(pi,
+						 (core ==
+						  PHY_CORE_0) ? 0xaa : 0xab);
+
+				wlc_phy_table_read_nphy(pi, 7, 1,
+							(0x110 + core), 16,
+							&pi->
+							nphy_txpwrindex[core].
+							rad_gain);
+
+				wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+							&tmpval);
+				tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
+				tmpval &= 0xff;
+				pi->nphy_txpwrindex[core].bbmult =
+				    (u8) tmpval;
+
+				wlc_phy_table_read_nphy(pi, 15, 2,
+							(80 + 2 * core), 16,
+							(void *)&pi->
+							nphy_txpwrindex[core].
+							iqcomp_a);
+
+				wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
+							16,
+							(void *)&pi->
+							nphy_txpwrindex[core].
+							locomp);
+
+				pi->nphy_txpwrindex[core].index_internal_save =
+				    pi->nphy_txpwrindex[core].index_internal;
+			}
+
+			tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+			wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+			if (NREV_IS(pi->pubpi.phy_rev, 1))
+				wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(tx_ind0 + txpwrindex), 32,
+						&txgain);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				rad_gain =
+				    (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
+			} else {
+				rad_gain =
+				    (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
+			}
+			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
+			bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+						 0xa5), (0x1 << 8), (0x1 << 8));
+			} else {
+				mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
+			}
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xaa : 0xab, dac_gain);
+
+			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
+						 &rad_gain);
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
+			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
+			m1m2 |=
+			    ((core ==
+			      PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(iq_ind0 + txpwrindex), 32,
+						&iqcomp);
+			iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1);
+			iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1);
+
+			if (restore_cals) {
+				regval[0] = (u16) iqcomp_a;
+				regval[1] = (u16) iqcomp_b;
+				wlc_phy_table_write_nphy(pi, 15, 2,
+							 (80 + 2 * core), 16,
+							 regval);
+			}
+
+			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
+						(lo_ind0 + txpwrindex), 32,
+						&locomp);
+			if (restore_cals) {
+				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
+							 16, &locomp);
+			}
+
+			if (NREV_IS(pi->pubpi.phy_rev, 1))
+				wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+			if (PHY_IPA(pi)) {
+				wlc_phy_table_read_nphy(pi,
+							(core ==
+							 PHY_CORE_0 ?
+							 NPHY_TBL_ID_CORE1TXPWRCTL
+							 :
+							 NPHY_TBL_ID_CORE2TXPWRCTL),
+							1, 576 + txpwrindex, 32,
+							&rfpwr_offset);
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+					    0x29b, (0x1ff << 4),
+					    ((s16) rfpwr_offset) << 4);
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+					    0x29b, (0x1 << 2), (1) << 2);
+
+			}
+
+			wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+		}
+
+		pi->nphy_txpwrindex[core].index = txpwrindex;
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void
+wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan, u8 *max_pwr,
+				   u8 txp_rate_idx)
+{
+	u8 chan_freq_range;
+
+	chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan);
+	switch (chan_freq_range) {
+	case WL_CHAN_FREQ_RANGE_2G:
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GM:
+		*max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GL:
+		*max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		break;
+	case WL_CHAN_FREQ_RANGE_5GH:
+		*max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+		break;
+	default:
+		ASSERT(0);
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+		break;
+	}
+
+	return;
+}
+
+void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable)
+{
+	u16 clip_off[] = { 0xffff, 0xffff };
+
+	ASSERT(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+
+	if (enable) {
+		if (pi->nphy_deaf_count == 0) {
+			pi->classifier_state =
+			    wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+			wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
+			wlc_phy_clip_det_nphy(pi, 1, clip_off);
+		}
+
+		pi->nphy_deaf_count++;
+
+		wlc_phy_resetcca_nphy(pi);
+
+	} else {
+		ASSERT(pi->nphy_deaf_count > 0);
+
+		pi->nphy_deaf_count--;
+
+		if (pi->nphy_deaf_count == 0) {
+			wlc_phy_classifier_nphy(pi, (0x7 << 0),
+						pi->classifier_state);
+			wlc_phy_clip_det_nphy(pi, 1, pi->clip_state);
+		}
+	}
+}
+
+void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode)
+{
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (mode) {
+		if (pi->nphy_deaf_count == 0)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+	} else {
+		if (pi->nphy_deaf_count > 0)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+	wlapi_enable_mac(pi->sh->physhim);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h
new file mode 100644
index 0000000..72176ae
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_radio.h
@@ -0,0 +1,1533 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_BCM20XX_H
+#define	_BCM20XX_H
+
+#define	RADIO_IDCODE			0x01
+
+#define RADIO_DEFAULT_CORE		0
+
+#define	RXC0_RSSI_RST			0x80
+#define	RXC0_MODE_RSSI			0x40
+#define	RXC0_MODE_OFF			0x20
+#define	RXC0_MODE_CM			0x10
+#define	RXC0_LAN_LOAD			0x08
+#define	RXC0_OFF_ADJ_MASK		0x07
+
+#define	TXC0_MODE_TXLPF			0x04
+#define	TXC0_PA_TSSI_EN			0x02
+#define	TXC0_TSSI_EN			0x01
+
+#define	TXC1_PA_GAIN_MASK		0x60
+#define	TXC1_PA_GAIN_3DB		0x40
+#define	TXC1_PA_GAIN_2DB		0x20
+#define	TXC1_TX_MIX_GAIN		0x10
+#define	TXC1_OFF_I_MASK			0x0c
+#define	TXC1_OFF_Q_MASK			0x03
+
+#define	RADIO_2055_READ_OFF		0x100
+#define	RADIO_2057_READ_OFF		0x200
+
+#define RADIO_2055_GEN_SPARE		0x00
+#define RADIO_2055_SP_PIN_PD		0x02
+#define RADIO_2055_SP_RSSI_CORE1	0x03
+#define RADIO_2055_SP_PD_MISC_CORE1	0x04
+#define RADIO_2055_SP_RSSI_CORE2	0x05
+#define RADIO_2055_SP_PD_MISC_CORE2	0x06
+#define RADIO_2055_SP_RX_GC1_CORE1	0x07
+#define RADIO_2055_SP_RX_GC2_CORE1	0x08
+#define RADIO_2055_SP_RX_GC1_CORE2	0x09
+#define RADIO_2055_SP_RX_GC2_CORE2	0x0a
+#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b
+#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c
+#define RADIO_2055_SP_TX_GC1_CORE1	0x0d
+#define RADIO_2055_SP_TX_GC2_CORE1	0x0e
+#define RADIO_2055_SP_TX_GC1_CORE2	0x0f
+#define RADIO_2055_SP_TX_GC2_CORE2	0x10
+#define RADIO_2055_MASTER_CNTRL1	0x11
+#define RADIO_2055_MASTER_CNTRL2	0x12
+#define RADIO_2055_PD_LGEN		0x13
+#define RADIO_2055_PD_PLL_TS		0x14
+#define RADIO_2055_PD_CORE1_LGBUF	0x15
+#define RADIO_2055_PD_CORE1_TX		0x16
+#define RADIO_2055_PD_CORE1_RXTX	0x17
+#define RADIO_2055_PD_CORE1_RSSI_MISC	0x18
+#define RADIO_2055_PD_CORE2_LGBUF	0x19
+#define RADIO_2055_PD_CORE2_TX		0x1a
+#define RADIO_2055_PD_CORE2_RXTX	0x1b
+#define RADIO_2055_PD_CORE2_RSSI_MISC	0x1c
+#define RADIO_2055_PWRDET_LGEN		0x1d
+#define RADIO_2055_PWRDET_LGBUF_CORE1	0x1e
+#define RADIO_2055_PWRDET_RXTX_CORE1	0x1f
+#define RADIO_2055_PWRDET_LGBUF_CORE2	0x20
+#define RADIO_2055_PWRDET_RXTX_CORE2	0x21
+#define RADIO_2055_RRCCAL_CNTRL_SPARE	0x22
+#define RADIO_2055_RRCCAL_N_OPT_SEL	0x23
+#define RADIO_2055_CAL_MISC		0x24
+#define RADIO_2055_CAL_COUNTER_OUT	0x25
+#define RADIO_2055_CAL_COUNTER_OUT2	0x26
+#define RADIO_2055_CAL_CVAR_CNTRL	0x27
+#define RADIO_2055_CAL_RVAR_CNTRL	0x28
+#define RADIO_2055_CAL_LPO_CNTRL	0x29
+#define RADIO_2055_CAL_TS		0x2a
+#define RADIO_2055_CAL_RCCAL_READ_TS	0x2b
+#define RADIO_2055_CAL_RCAL_READ_TS	0x2c
+#define RADIO_2055_PAD_DRIVER		0x2d
+#define RADIO_2055_XO_CNTRL1		0x2e
+#define RADIO_2055_XO_CNTRL2		0x2f
+#define RADIO_2055_XO_REGULATOR		0x30
+#define RADIO_2055_XO_MISC		0x31
+#define RADIO_2055_PLL_LF_C1		0x32
+#define RADIO_2055_PLL_CAL_VTH		0x33
+#define RADIO_2055_PLL_LF_C2		0x34
+#define RADIO_2055_PLL_REF		0x35
+#define RADIO_2055_PLL_LF_R1		0x36
+#define RADIO_2055_PLL_PFD_CP		0x37
+#define RADIO_2055_PLL_IDAC_CPOPAMP	0x38
+#define RADIO_2055_PLL_CP_REGULATOR	0x39
+#define RADIO_2055_PLL_RCAL		0x3a
+#define RADIO_2055_RF_PLL_MOD0		0x3b
+#define RADIO_2055_RF_PLL_MOD1		0x3c
+#define RADIO_2055_RF_MMD_IDAC1		0x3d
+#define RADIO_2055_RF_MMD_IDAC0		0x3e
+#define RADIO_2055_RF_MMD_SPARE		0x3f
+#define RADIO_2055_VCO_CAL1		0x40
+#define RADIO_2055_VCO_CAL2		0x41
+#define RADIO_2055_VCO_CAL3		0x42
+#define RADIO_2055_VCO_CAL4		0x43
+#define RADIO_2055_VCO_CAL5		0x44
+#define RADIO_2055_VCO_CAL6		0x45
+#define RADIO_2055_VCO_CAL7		0x46
+#define RADIO_2055_VCO_CAL8		0x47
+#define RADIO_2055_VCO_CAL9		0x48
+#define RADIO_2055_VCO_CAL10		0x49
+#define RADIO_2055_VCO_CAL11		0x4a
+#define RADIO_2055_VCO_CAL12		0x4b
+#define RADIO_2055_VCO_CAL13		0x4c
+#define RADIO_2055_VCO_CAL14		0x4d
+#define RADIO_2055_VCO_CAL15		0x4e
+#define RADIO_2055_VCO_CAL16		0x4f
+#define RADIO_2055_VCO_KVCO		0x50
+#define RADIO_2055_VCO_CAP_TAIL		0x51
+#define RADIO_2055_VCO_IDAC_VCO		0x52
+#define RADIO_2055_VCO_REGULATOR	0x53
+#define RADIO_2055_PLL_RF_VTH		0x54
+#define RADIO_2055_LGBUF_CEN_BUF	0x55
+#define RADIO_2055_LGEN_TUNE1		0x56
+#define RADIO_2055_LGEN_TUNE2		0x57
+#define RADIO_2055_LGEN_IDAC1		0x58
+#define RADIO_2055_LGEN_IDAC2		0x59
+#define RADIO_2055_LGEN_BIAS_CNT	0x5a
+#define RADIO_2055_LGEN_BIAS_IDAC	0x5b
+#define RADIO_2055_LGEN_RCAL		0x5c
+#define RADIO_2055_LGEN_DIV		0x5d
+#define RADIO_2055_LGEN_SPARE2		0x5e
+#define RADIO_2055_CORE1_LGBUF_A_TUNE	0x5f
+#define RADIO_2055_CORE1_LGBUF_G_TUNE	0x60
+#define RADIO_2055_CORE1_LGBUF_DIV	0x61
+#define RADIO_2055_CORE1_LGBUF_A_IDAC	0x62
+#define RADIO_2055_CORE1_LGBUF_G_IDAC	0x63
+#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64
+#define RADIO_2055_CORE1_LGBUF_SPARE	0x65
+#define RADIO_2055_CORE1_RXRF_SPC1	0x66
+#define RADIO_2055_CORE1_RXRF_REG1	0x67
+#define RADIO_2055_CORE1_RXRF_REG2	0x68
+#define RADIO_2055_CORE1_RXRF_RCAL	0x69
+#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a
+#define RADIO_2055_CORE1_RXBB_LPF	0x6b
+#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c
+#define RADIO_2055_CORE1_RXBB_VGA1_IDAC	0x6d
+#define RADIO_2055_CORE1_RXBB_VGA2_IDAC	0x6e
+#define RADIO_2055_CORE1_RXBB_VGA3_IDAC	0x6f
+#define RADIO_2055_CORE1_RXBB_BUFO_CTRL	0x70
+#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75
+#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76
+#define RADIO_2055_CORE1_RXBB_REGULATOR	0x77
+#define RADIO_2055_CORE1_RXBB_SPARE1	0x78
+#define RADIO_2055_CORE1_RXTXBB_RCAL	0x79
+#define RADIO_2055_CORE1_TXRF_SGM_PGA	0x7a
+#define RADIO_2055_CORE1_TXRF_SGM_PAD	0x7b
+#define RADIO_2055_CORE1_TXRF_CNTR_PGA1	0x7c
+#define RADIO_2055_CORE1_TXRF_CNTR_PAD1	0x7d
+#define RADIO_2055_CORE1_TX_RFPGA_IDAC	0x7e
+#define RADIO_2055_CORE1_TX_PGA_PAD_TN	0x7f
+#define RADIO_2055_CORE1_TX_PAD_IDAC1	0x80
+#define RADIO_2055_CORE1_TX_PAD_IDAC2	0x81
+#define RADIO_2055_CORE1_TX_MX_BGTRIM	0x82
+#define RADIO_2055_CORE1_TXRF_RCAL	0x83
+#define RADIO_2055_CORE1_TXRF_PAD_TSSI1	0x84
+#define RADIO_2055_CORE1_TXRF_PAD_TSSI2	0x85
+#define RADIO_2055_CORE1_TX_RF_SPARE	0x86
+#define RADIO_2055_CORE1_TXRF_IQCAL1	0x87
+#define RADIO_2055_CORE1_TXRF_IQCAL2	0x88
+#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89
+#define RADIO_2055_CORE1_TXBB_LPF1	0x8a
+#define RADIO_2055_CORE1_TX_VOS_CNCL	0x8b
+#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c
+#define RADIO_2055_CORE1_TX_BB_MXGM	0x8d
+#define RADIO_2055_CORE2_LGBUF_A_TUNE	0x8e
+#define RADIO_2055_CORE2_LGBUF_G_TUNE	0x8f
+#define RADIO_2055_CORE2_LGBUF_DIV	0x90
+#define RADIO_2055_CORE2_LGBUF_A_IDAC	0x91
+#define RADIO_2055_CORE2_LGBUF_G_IDAC	0x92
+#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93
+#define RADIO_2055_CORE2_LGBUF_SPARE	0x94
+#define RADIO_2055_CORE2_RXRF_SPC1	0x95
+#define RADIO_2055_CORE2_RXRF_REG1	0x96
+#define RADIO_2055_CORE2_RXRF_REG2	0x97
+#define RADIO_2055_CORE2_RXRF_RCAL	0x98
+#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99
+#define RADIO_2055_CORE2_RXBB_LPF	0x9a
+#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b
+#define RADIO_2055_CORE2_RXBB_VGA1_IDAC	0x9c
+#define RADIO_2055_CORE2_RXBB_VGA2_IDAC	0x9d
+#define RADIO_2055_CORE2_RXBB_VGA3_IDAC	0x9e
+#define RADIO_2055_CORE2_RXBB_BUFO_CTRL	0x9f
+#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4
+#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5
+#define RADIO_2055_CORE2_RXBB_REGULATOR	0xa6
+#define RADIO_2055_CORE2_RXBB_SPARE1	0xa7
+#define RADIO_2055_CORE2_RXTXBB_RCAL	0xa8
+#define RADIO_2055_CORE2_TXRF_SGM_PGA	0xa9
+#define RADIO_2055_CORE2_TXRF_SGM_PAD	0xaa
+#define RADIO_2055_CORE2_TXRF_CNTR_PGA1	0xab
+#define RADIO_2055_CORE2_TXRF_CNTR_PAD1	0xac
+#define RADIO_2055_CORE2_TX_RFPGA_IDAC	0xad
+#define RADIO_2055_CORE2_TX_PGA_PAD_TN	0xae
+#define RADIO_2055_CORE2_TX_PAD_IDAC1	0xaf
+#define RADIO_2055_CORE2_TX_PAD_IDAC2	0xb0
+#define RADIO_2055_CORE2_TX_MX_BGTRIM	0xb1
+#define RADIO_2055_CORE2_TXRF_RCAL	0xb2
+#define RADIO_2055_CORE2_TXRF_PAD_TSSI1	0xb3
+#define RADIO_2055_CORE2_TXRF_PAD_TSSI2	0xb4
+#define RADIO_2055_CORE2_TX_RF_SPARE	0xb5
+#define RADIO_2055_CORE2_TXRF_IQCAL1	0xb6
+#define RADIO_2055_CORE2_TXRF_IQCAL2	0xb7
+#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8
+#define RADIO_2055_CORE2_TXBB_LPF1	0xb9
+#define RADIO_2055_CORE2_TX_VOS_CNCL	0xba
+#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb
+#define RADIO_2055_CORE2_TX_BB_MXGM	0xbc
+#define RADIO_2055_PRG_GC_HPVGA23_21	0xbd
+#define RADIO_2055_PRG_GC_HPVGA23_22	0xbe
+#define RADIO_2055_PRG_GC_HPVGA23_23	0xbf
+#define RADIO_2055_PRG_GC_HPVGA23_24	0xc0
+#define RADIO_2055_PRG_GC_HPVGA23_25	0xc1
+#define RADIO_2055_PRG_GC_HPVGA23_26	0xc2
+#define RADIO_2055_PRG_GC_HPVGA23_27	0xc3
+#define RADIO_2055_PRG_GC_HPVGA23_28	0xc4
+#define RADIO_2055_PRG_GC_HPVGA23_29	0xc5
+#define RADIO_2055_PRG_GC_HPVGA23_30	0xc6
+#define RADIO_2055_CORE1_LNA_GAINBST	0xcd
+#define RADIO_2055_CORE1_B0_NBRSSI_VCM	0xd2
+#define RADIO_2055_CORE1_GEN_SPARE2		0xd6
+#define RADIO_2055_CORE2_LNA_GAINBST	0xd9
+#define RADIO_2055_CORE2_B0_NBRSSI_VCM	0xde
+#define RADIO_2055_CORE2_GEN_SPARE2		0xe2
+
+#define RADIO_2055_GAINBST_GAIN_DB	6
+#define RADIO_2055_GAINBST_CODE		0x6
+
+#define RADIO_2055_JTAGCTRL_MASK	0x04
+#define RADIO_2055_JTAGSYNC_MASK	0x08
+#define RADIO_2055_RRCAL_START		0x40
+#define RADIO_2055_RRCAL_RST_N		0x01
+#define RADIO_2055_CAL_LPO_ENABLE	0x80
+#define RADIO_2055_RCAL_DONE		0x80
+#define RADIO_2055_NBRSSI_VCM_I_MASK	0x03
+#define RADIO_2055_NBRSSI_VCM_I_SHIFT	0x00
+#define RADIO_2055_NBRSSI_VCM_Q_MASK	0x03
+#define RADIO_2055_NBRSSI_VCM_Q_SHIFT	0x00
+#define RADIO_2055_WBRSSI_VCM_IQ_MASK	0x0c
+#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT	0x02
+#define RADIO_2055_NBRSSI_PD		0x01
+#define RADIO_2055_WBRSSI_G1_PD		0x04
+#define RADIO_2055_WBRSSI_G2_PD		0x02
+#define RADIO_2055_NBRSSI_SEL		0x01
+#define RADIO_2055_WBRSSI_G1_SEL	0x04
+#define RADIO_2055_WBRSSI_G2_SEL	0x02
+#define RADIO_2055_COUPLE_RX_MASK	0x01
+#define RADIO_2055_COUPLE_TX_MASK	0x02
+#define RADIO_2055_GAINBST_DISABLE	0x02
+#define RADIO_2055_GAINBST_VAL_MASK	0x07
+#define RADIO_2055_RXMX_GC_MASK		0x0c
+
+#define RADIO_MIMO_CORESEL_OFF		0x0
+#define RADIO_MIMO_CORESEL_CORE1	0x1
+#define RADIO_MIMO_CORESEL_CORE2	0x2
+#define RADIO_MIMO_CORESEL_CORE3	0x3
+#define RADIO_MIMO_CORESEL_CORE4	0x4
+#define RADIO_MIMO_CORESEL_ALLRX	0x5
+#define RADIO_MIMO_CORESEL_ALLTX	0x6
+#define RADIO_MIMO_CORESEL_ALLRXTX	0x7
+
+#define	RADIO_2064_READ_OFF		0x200
+
+#define RADIO_2064_REG000               0x0
+#define RADIO_2064_REG001               0x1
+#define RADIO_2064_REG002               0x2
+#define RADIO_2064_REG003               0x3
+#define RADIO_2064_REG004               0x4
+#define RADIO_2064_REG005               0x5
+#define RADIO_2064_REG006               0x6
+#define RADIO_2064_REG007               0x7
+#define RADIO_2064_REG008               0x8
+#define RADIO_2064_REG009               0x9
+#define RADIO_2064_REG00A               0xa
+#define RADIO_2064_REG00B               0xb
+#define RADIO_2064_REG00C               0xc
+#define RADIO_2064_REG00D               0xd
+#define RADIO_2064_REG00E               0xe
+#define RADIO_2064_REG00F               0xf
+#define RADIO_2064_REG010               0x10
+#define RADIO_2064_REG011               0x11
+#define RADIO_2064_REG012               0x12
+#define RADIO_2064_REG013               0x13
+#define RADIO_2064_REG014               0x14
+#define RADIO_2064_REG015               0x15
+#define RADIO_2064_REG016               0x16
+#define RADIO_2064_REG017               0x17
+#define RADIO_2064_REG018               0x18
+#define RADIO_2064_REG019               0x19
+#define RADIO_2064_REG01A               0x1a
+#define RADIO_2064_REG01B               0x1b
+#define RADIO_2064_REG01C               0x1c
+#define RADIO_2064_REG01D               0x1d
+#define RADIO_2064_REG01E               0x1e
+#define RADIO_2064_REG01F               0x1f
+#define RADIO_2064_REG020               0x20
+#define RADIO_2064_REG021               0x21
+#define RADIO_2064_REG022               0x22
+#define RADIO_2064_REG023               0x23
+#define RADIO_2064_REG024               0x24
+#define RADIO_2064_REG025               0x25
+#define RADIO_2064_REG026               0x26
+#define RADIO_2064_REG027               0x27
+#define RADIO_2064_REG028               0x28
+#define RADIO_2064_REG029               0x29
+#define RADIO_2064_REG02A               0x2a
+#define RADIO_2064_REG02B               0x2b
+#define RADIO_2064_REG02C               0x2c
+#define RADIO_2064_REG02D               0x2d
+#define RADIO_2064_REG02E               0x2e
+#define RADIO_2064_REG02F               0x2f
+#define RADIO_2064_REG030               0x30
+#define RADIO_2064_REG031               0x31
+#define RADIO_2064_REG032               0x32
+#define RADIO_2064_REG033               0x33
+#define RADIO_2064_REG034               0x34
+#define RADIO_2064_REG035               0x35
+#define RADIO_2064_REG036               0x36
+#define RADIO_2064_REG037               0x37
+#define RADIO_2064_REG038               0x38
+#define RADIO_2064_REG039               0x39
+#define RADIO_2064_REG03A               0x3a
+#define RADIO_2064_REG03B               0x3b
+#define RADIO_2064_REG03C               0x3c
+#define RADIO_2064_REG03D               0x3d
+#define RADIO_2064_REG03E               0x3e
+#define RADIO_2064_REG03F               0x3f
+#define RADIO_2064_REG040               0x40
+#define RADIO_2064_REG041               0x41
+#define RADIO_2064_REG042               0x42
+#define RADIO_2064_REG043               0x43
+#define RADIO_2064_REG044               0x44
+#define RADIO_2064_REG045               0x45
+#define RADIO_2064_REG046               0x46
+#define RADIO_2064_REG047               0x47
+#define RADIO_2064_REG048               0x48
+#define RADIO_2064_REG049               0x49
+#define RADIO_2064_REG04A               0x4a
+#define RADIO_2064_REG04B               0x4b
+#define RADIO_2064_REG04C               0x4c
+#define RADIO_2064_REG04D               0x4d
+#define RADIO_2064_REG04E               0x4e
+#define RADIO_2064_REG04F               0x4f
+#define RADIO_2064_REG050               0x50
+#define RADIO_2064_REG051               0x51
+#define RADIO_2064_REG052               0x52
+#define RADIO_2064_REG053               0x53
+#define RADIO_2064_REG054               0x54
+#define RADIO_2064_REG055               0x55
+#define RADIO_2064_REG056               0x56
+#define RADIO_2064_REG057               0x57
+#define RADIO_2064_REG058               0x58
+#define RADIO_2064_REG059               0x59
+#define RADIO_2064_REG05A               0x5a
+#define RADIO_2064_REG05B               0x5b
+#define RADIO_2064_REG05C               0x5c
+#define RADIO_2064_REG05D               0x5d
+#define RADIO_2064_REG05E               0x5e
+#define RADIO_2064_REG05F               0x5f
+#define RADIO_2064_REG060               0x60
+#define RADIO_2064_REG061               0x61
+#define RADIO_2064_REG062               0x62
+#define RADIO_2064_REG063               0x63
+#define RADIO_2064_REG064               0x64
+#define RADIO_2064_REG065               0x65
+#define RADIO_2064_REG066               0x66
+#define RADIO_2064_REG067               0x67
+#define RADIO_2064_REG068               0x68
+#define RADIO_2064_REG069               0x69
+#define RADIO_2064_REG06A               0x6a
+#define RADIO_2064_REG06B               0x6b
+#define RADIO_2064_REG06C               0x6c
+#define RADIO_2064_REG06D               0x6d
+#define RADIO_2064_REG06E               0x6e
+#define RADIO_2064_REG06F               0x6f
+#define RADIO_2064_REG070               0x70
+#define RADIO_2064_REG071               0x71
+#define RADIO_2064_REG072               0x72
+#define RADIO_2064_REG073               0x73
+#define RADIO_2064_REG074               0x74
+#define RADIO_2064_REG075               0x75
+#define RADIO_2064_REG076               0x76
+#define RADIO_2064_REG077               0x77
+#define RADIO_2064_REG078               0x78
+#define RADIO_2064_REG079               0x79
+#define RADIO_2064_REG07A               0x7a
+#define RADIO_2064_REG07B               0x7b
+#define RADIO_2064_REG07C               0x7c
+#define RADIO_2064_REG07D               0x7d
+#define RADIO_2064_REG07E               0x7e
+#define RADIO_2064_REG07F               0x7f
+#define RADIO_2064_REG080               0x80
+#define RADIO_2064_REG081               0x81
+#define RADIO_2064_REG082               0x82
+#define RADIO_2064_REG083               0x83
+#define RADIO_2064_REG084               0x84
+#define RADIO_2064_REG085               0x85
+#define RADIO_2064_REG086               0x86
+#define RADIO_2064_REG087               0x87
+#define RADIO_2064_REG088               0x88
+#define RADIO_2064_REG089               0x89
+#define RADIO_2064_REG08A               0x8a
+#define RADIO_2064_REG08B               0x8b
+#define RADIO_2064_REG08C               0x8c
+#define RADIO_2064_REG08D               0x8d
+#define RADIO_2064_REG08E               0x8e
+#define RADIO_2064_REG08F               0x8f
+#define RADIO_2064_REG090               0x90
+#define RADIO_2064_REG091               0x91
+#define RADIO_2064_REG092               0x92
+#define RADIO_2064_REG093               0x93
+#define RADIO_2064_REG094               0x94
+#define RADIO_2064_REG095               0x95
+#define RADIO_2064_REG096               0x96
+#define RADIO_2064_REG097               0x97
+#define RADIO_2064_REG098               0x98
+#define RADIO_2064_REG099               0x99
+#define RADIO_2064_REG09A               0x9a
+#define RADIO_2064_REG09B               0x9b
+#define RADIO_2064_REG09C               0x9c
+#define RADIO_2064_REG09D               0x9d
+#define RADIO_2064_REG09E               0x9e
+#define RADIO_2064_REG09F               0x9f
+#define RADIO_2064_REG0A0               0xa0
+#define RADIO_2064_REG0A1               0xa1
+#define RADIO_2064_REG0A2               0xa2
+#define RADIO_2064_REG0A3               0xa3
+#define RADIO_2064_REG0A4               0xa4
+#define RADIO_2064_REG0A5               0xa5
+#define RADIO_2064_REG0A6               0xa6
+#define RADIO_2064_REG0A7               0xa7
+#define RADIO_2064_REG0A8               0xa8
+#define RADIO_2064_REG0A9               0xa9
+#define RADIO_2064_REG0AA               0xaa
+#define RADIO_2064_REG0AB               0xab
+#define RADIO_2064_REG0AC               0xac
+#define RADIO_2064_REG0AD               0xad
+#define RADIO_2064_REG0AE               0xae
+#define RADIO_2064_REG0AF               0xaf
+#define RADIO_2064_REG0B0               0xb0
+#define RADIO_2064_REG0B1               0xb1
+#define RADIO_2064_REG0B2               0xb2
+#define RADIO_2064_REG0B3               0xb3
+#define RADIO_2064_REG0B4               0xb4
+#define RADIO_2064_REG0B5               0xb5
+#define RADIO_2064_REG0B6               0xb6
+#define RADIO_2064_REG0B7               0xb7
+#define RADIO_2064_REG0B8               0xb8
+#define RADIO_2064_REG0B9               0xb9
+#define RADIO_2064_REG0BA               0xba
+#define RADIO_2064_REG0BB               0xbb
+#define RADIO_2064_REG0BC               0xbc
+#define RADIO_2064_REG0BD               0xbd
+#define RADIO_2064_REG0BE               0xbe
+#define RADIO_2064_REG0BF               0xbf
+#define RADIO_2064_REG0C0               0xc0
+#define RADIO_2064_REG0C1               0xc1
+#define RADIO_2064_REG0C2               0xc2
+#define RADIO_2064_REG0C3               0xc3
+#define RADIO_2064_REG0C4               0xc4
+#define RADIO_2064_REG0C5               0xc5
+#define RADIO_2064_REG0C6               0xc6
+#define RADIO_2064_REG0C7               0xc7
+#define RADIO_2064_REG0C8               0xc8
+#define RADIO_2064_REG0C9               0xc9
+#define RADIO_2064_REG0CA               0xca
+#define RADIO_2064_REG0CB               0xcb
+#define RADIO_2064_REG0CC               0xcc
+#define RADIO_2064_REG0CD               0xcd
+#define RADIO_2064_REG0CE               0xce
+#define RADIO_2064_REG0CF               0xcf
+#define RADIO_2064_REG0D0               0xd0
+#define RADIO_2064_REG0D1               0xd1
+#define RADIO_2064_REG0D2               0xd2
+#define RADIO_2064_REG0D3               0xd3
+#define RADIO_2064_REG0D4               0xd4
+#define RADIO_2064_REG0D5               0xd5
+#define RADIO_2064_REG0D6               0xd6
+#define RADIO_2064_REG0D7               0xd7
+#define RADIO_2064_REG0D8               0xd8
+#define RADIO_2064_REG0D9               0xd9
+#define RADIO_2064_REG0DA               0xda
+#define RADIO_2064_REG0DB               0xdb
+#define RADIO_2064_REG0DC               0xdc
+#define RADIO_2064_REG0DD               0xdd
+#define RADIO_2064_REG0DE               0xde
+#define RADIO_2064_REG0DF               0xdf
+#define RADIO_2064_REG0E0               0xe0
+#define RADIO_2064_REG0E1               0xe1
+#define RADIO_2064_REG0E2               0xe2
+#define RADIO_2064_REG0E3               0xe3
+#define RADIO_2064_REG0E4               0xe4
+#define RADIO_2064_REG0E5               0xe5
+#define RADIO_2064_REG0E6               0xe6
+#define RADIO_2064_REG0E7               0xe7
+#define RADIO_2064_REG0E8               0xe8
+#define RADIO_2064_REG0E9               0xe9
+#define RADIO_2064_REG0EA               0xea
+#define RADIO_2064_REG0EB               0xeb
+#define RADIO_2064_REG0EC               0xec
+#define RADIO_2064_REG0ED               0xed
+#define RADIO_2064_REG0EE               0xee
+#define RADIO_2064_REG0EF               0xef
+#define RADIO_2064_REG0F0               0xf0
+#define RADIO_2064_REG0F1               0xf1
+#define RADIO_2064_REG0F2               0xf2
+#define RADIO_2064_REG0F3               0xf3
+#define RADIO_2064_REG0F4               0xf4
+#define RADIO_2064_REG0F5               0xf5
+#define RADIO_2064_REG0F6               0xf6
+#define RADIO_2064_REG0F7               0xf7
+#define RADIO_2064_REG0F8               0xf8
+#define RADIO_2064_REG0F9               0xf9
+#define RADIO_2064_REG0FA               0xfa
+#define RADIO_2064_REG0FB               0xfb
+#define RADIO_2064_REG0FC               0xfc
+#define RADIO_2064_REG0FD               0xfd
+#define RADIO_2064_REG0FE               0xfe
+#define RADIO_2064_REG0FF               0xff
+#define RADIO_2064_REG100               0x100
+#define RADIO_2064_REG101               0x101
+#define RADIO_2064_REG102               0x102
+#define RADIO_2064_REG103               0x103
+#define RADIO_2064_REG104               0x104
+#define RADIO_2064_REG105               0x105
+#define RADIO_2064_REG106               0x106
+#define RADIO_2064_REG107               0x107
+#define RADIO_2064_REG108               0x108
+#define RADIO_2064_REG109               0x109
+#define RADIO_2064_REG10A               0x10a
+#define RADIO_2064_REG10B               0x10b
+#define RADIO_2064_REG10C               0x10c
+#define RADIO_2064_REG10D               0x10d
+#define RADIO_2064_REG10E               0x10e
+#define RADIO_2064_REG10F               0x10f
+#define RADIO_2064_REG110               0x110
+#define RADIO_2064_REG111               0x111
+#define RADIO_2064_REG112               0x112
+#define RADIO_2064_REG113               0x113
+#define RADIO_2064_REG114               0x114
+#define RADIO_2064_REG115               0x115
+#define RADIO_2064_REG116               0x116
+#define RADIO_2064_REG117               0x117
+#define RADIO_2064_REG118               0x118
+#define RADIO_2064_REG119               0x119
+#define RADIO_2064_REG11A               0x11a
+#define RADIO_2064_REG11B               0x11b
+#define RADIO_2064_REG11C               0x11c
+#define RADIO_2064_REG11D               0x11d
+#define RADIO_2064_REG11E               0x11e
+#define RADIO_2064_REG11F               0x11f
+#define RADIO_2064_REG120               0x120
+#define RADIO_2064_REG121               0x121
+#define RADIO_2064_REG122               0x122
+#define RADIO_2064_REG123               0x123
+#define RADIO_2064_REG124               0x124
+#define RADIO_2064_REG125               0x125
+#define RADIO_2064_REG126               0x126
+#define RADIO_2064_REG127               0x127
+#define RADIO_2064_REG128               0x128
+#define RADIO_2064_REG129               0x129
+#define RADIO_2064_REG12A               0x12a
+#define RADIO_2064_REG12B               0x12b
+#define RADIO_2064_REG12C               0x12c
+#define RADIO_2064_REG12D               0x12d
+#define RADIO_2064_REG12E               0x12e
+#define RADIO_2064_REG12F               0x12f
+#define RADIO_2064_REG130               0x130
+
+#define RADIO_2056_SYN                           (0x0 << 12)
+#define RADIO_2056_TX0                           (0x2 << 12)
+#define RADIO_2056_TX1                           (0x3 << 12)
+#define RADIO_2056_RX0                           (0x6 << 12)
+#define RADIO_2056_RX1                           (0x7 << 12)
+#define RADIO_2056_ALLTX                         (0xe << 12)
+#define RADIO_2056_ALLRX                         (0xf << 12)
+
+#define RADIO_2056_SYN_RESERVED_ADDR0            0x0
+#define RADIO_2056_SYN_IDCODE                    0x1
+#define RADIO_2056_SYN_RESERVED_ADDR2            0x2
+#define RADIO_2056_SYN_RESERVED_ADDR3            0x3
+#define RADIO_2056_SYN_RESERVED_ADDR4            0x4
+#define RADIO_2056_SYN_RESERVED_ADDR5            0x5
+#define RADIO_2056_SYN_RESERVED_ADDR6            0x6
+#define RADIO_2056_SYN_RESERVED_ADDR7            0x7
+#define RADIO_2056_SYN_COM_CTRL                  0x8
+#define RADIO_2056_SYN_COM_PU                    0x9
+#define RADIO_2056_SYN_COM_OVR                   0xa
+#define RADIO_2056_SYN_COM_RESET                 0xb
+#define RADIO_2056_SYN_COM_RCAL                  0xc
+#define RADIO_2056_SYN_COM_RC_RXLPF              0xd
+#define RADIO_2056_SYN_COM_RC_TXLPF              0xe
+#define RADIO_2056_SYN_COM_RC_RXHPF              0xf
+#define RADIO_2056_SYN_RESERVED_ADDR16           0x10
+#define RADIO_2056_SYN_RESERVED_ADDR17           0x11
+#define RADIO_2056_SYN_RESERVED_ADDR18           0x12
+#define RADIO_2056_SYN_RESERVED_ADDR19           0x13
+#define RADIO_2056_SYN_RESERVED_ADDR20           0x14
+#define RADIO_2056_SYN_RESERVED_ADDR21           0x15
+#define RADIO_2056_SYN_RESERVED_ADDR22           0x16
+#define RADIO_2056_SYN_RESERVED_ADDR23           0x17
+#define RADIO_2056_SYN_RESERVED_ADDR24           0x18
+#define RADIO_2056_SYN_RESERVED_ADDR25           0x19
+#define RADIO_2056_SYN_RESERVED_ADDR26           0x1a
+#define RADIO_2056_SYN_RESERVED_ADDR27           0x1b
+#define RADIO_2056_SYN_RESERVED_ADDR28           0x1c
+#define RADIO_2056_SYN_RESERVED_ADDR29           0x1d
+#define RADIO_2056_SYN_RESERVED_ADDR30           0x1e
+#define RADIO_2056_SYN_RESERVED_ADDR31           0x1f
+#define RADIO_2056_SYN_GPIO_MASTER1              0x20
+#define RADIO_2056_SYN_GPIO_MASTER2              0x21
+#define RADIO_2056_SYN_TOPBIAS_MASTER            0x22
+#define RADIO_2056_SYN_TOPBIAS_RCAL              0x23
+#define RADIO_2056_SYN_AFEREG                    0x24
+#define RADIO_2056_SYN_TEMPPROCSENSE             0x25
+#define RADIO_2056_SYN_TEMPPROCSENSEIDAC         0x26
+#define RADIO_2056_SYN_TEMPPROCSENSERCAL         0x27
+#define RADIO_2056_SYN_LPO                       0x28
+#define RADIO_2056_SYN_VDDCAL_MASTER             0x29
+#define RADIO_2056_SYN_VDDCAL_IDAC               0x2a
+#define RADIO_2056_SYN_VDDCAL_STATUS             0x2b
+#define RADIO_2056_SYN_RCAL_MASTER               0x2c
+#define RADIO_2056_SYN_RCAL_CODE_OUT             0x2d
+#define RADIO_2056_SYN_RCCAL_CTRL0               0x2e
+#define RADIO_2056_SYN_RCCAL_CTRL1               0x2f
+#define RADIO_2056_SYN_RCCAL_CTRL2               0x30
+#define RADIO_2056_SYN_RCCAL_CTRL3               0x31
+#define RADIO_2056_SYN_RCCAL_CTRL4               0x32
+#define RADIO_2056_SYN_RCCAL_CTRL5               0x33
+#define RADIO_2056_SYN_RCCAL_CTRL6               0x34
+#define RADIO_2056_SYN_RCCAL_CTRL7               0x35
+#define RADIO_2056_SYN_RCCAL_CTRL8               0x36
+#define RADIO_2056_SYN_RCCAL_CTRL9               0x37
+#define RADIO_2056_SYN_RCCAL_CTRL10              0x38
+#define RADIO_2056_SYN_RCCAL_CTRL11              0x39
+#define RADIO_2056_SYN_ZCAL_SPARE1               0x3a
+#define RADIO_2056_SYN_ZCAL_SPARE2               0x3b
+#define RADIO_2056_SYN_PLL_MAST1                 0x3c
+#define RADIO_2056_SYN_PLL_MAST2                 0x3d
+#define RADIO_2056_SYN_PLL_MAST3                 0x3e
+#define RADIO_2056_SYN_PLL_BIAS_RESET            0x3f
+#define RADIO_2056_SYN_PLL_XTAL0                 0x40
+#define RADIO_2056_SYN_PLL_XTAL1                 0x41
+#define RADIO_2056_SYN_PLL_XTAL3                 0x42
+#define RADIO_2056_SYN_PLL_XTAL4                 0x43
+#define RADIO_2056_SYN_PLL_XTAL5                 0x44
+#define RADIO_2056_SYN_PLL_XTAL6                 0x45
+#define RADIO_2056_SYN_PLL_REFDIV                0x46
+#define RADIO_2056_SYN_PLL_PFD                   0x47
+#define RADIO_2056_SYN_PLL_CP1                   0x48
+#define RADIO_2056_SYN_PLL_CP2                   0x49
+#define RADIO_2056_SYN_PLL_CP3                   0x4a
+#define RADIO_2056_SYN_PLL_LOOPFILTER1           0x4b
+#define RADIO_2056_SYN_PLL_LOOPFILTER2           0x4c
+#define RADIO_2056_SYN_PLL_LOOPFILTER3           0x4d
+#define RADIO_2056_SYN_PLL_LOOPFILTER4           0x4e
+#define RADIO_2056_SYN_PLL_LOOPFILTER5           0x4f
+#define RADIO_2056_SYN_PLL_MMD1                  0x50
+#define RADIO_2056_SYN_PLL_MMD2                  0x51
+#define RADIO_2056_SYN_PLL_VCO1                  0x52
+#define RADIO_2056_SYN_PLL_VCO2                  0x53
+#define RADIO_2056_SYN_PLL_MONITOR1              0x54
+#define RADIO_2056_SYN_PLL_MONITOR2              0x55
+#define RADIO_2056_SYN_PLL_VCOCAL1               0x56
+#define RADIO_2056_SYN_PLL_VCOCAL2               0x57
+#define RADIO_2056_SYN_PLL_VCOCAL4               0x58
+#define RADIO_2056_SYN_PLL_VCOCAL5               0x59
+#define RADIO_2056_SYN_PLL_VCOCAL6               0x5a
+#define RADIO_2056_SYN_PLL_VCOCAL7               0x5b
+#define RADIO_2056_SYN_PLL_VCOCAL8               0x5c
+#define RADIO_2056_SYN_PLL_VCOCAL9               0x5d
+#define RADIO_2056_SYN_PLL_VCOCAL10              0x5e
+#define RADIO_2056_SYN_PLL_VCOCAL11              0x5f
+#define RADIO_2056_SYN_PLL_VCOCAL12              0x60
+#define RADIO_2056_SYN_PLL_VCOCAL13              0x61
+#define RADIO_2056_SYN_PLL_VREG                  0x62
+#define RADIO_2056_SYN_PLL_STATUS1               0x63
+#define RADIO_2056_SYN_PLL_STATUS2               0x64
+#define RADIO_2056_SYN_PLL_STATUS3               0x65
+#define RADIO_2056_SYN_LOGEN_PU0                 0x66
+#define RADIO_2056_SYN_LOGEN_PU1                 0x67
+#define RADIO_2056_SYN_LOGEN_PU2                 0x68
+#define RADIO_2056_SYN_LOGEN_PU3                 0x69
+#define RADIO_2056_SYN_LOGEN_PU5                 0x6a
+#define RADIO_2056_SYN_LOGEN_PU6                 0x6b
+#define RADIO_2056_SYN_LOGEN_PU7                 0x6c
+#define RADIO_2056_SYN_LOGEN_PU8                 0x6d
+#define RADIO_2056_SYN_LOGEN_BIAS_RESET          0x6e
+#define RADIO_2056_SYN_LOGEN_RCCR1               0x6f
+#define RADIO_2056_SYN_LOGEN_VCOBUF1             0x70
+#define RADIO_2056_SYN_LOGEN_MIXER1              0x71
+#define RADIO_2056_SYN_LOGEN_MIXER2              0x72
+#define RADIO_2056_SYN_LOGEN_BUF1                0x73
+#define RADIO_2056_SYN_LOGENBUF2                 0x74
+#define RADIO_2056_SYN_LOGEN_BUF3                0x75
+#define RADIO_2056_SYN_LOGEN_BUF4                0x76
+#define RADIO_2056_SYN_LOGEN_DIV1                0x77
+#define RADIO_2056_SYN_LOGEN_DIV2                0x78
+#define RADIO_2056_SYN_LOGEN_DIV3                0x79
+#define RADIO_2056_SYN_LOGEN_ACL1                0x7a
+#define RADIO_2056_SYN_LOGEN_ACL2                0x7b
+#define RADIO_2056_SYN_LOGEN_ACL3                0x7c
+#define RADIO_2056_SYN_LOGEN_ACL4                0x7d
+#define RADIO_2056_SYN_LOGEN_ACL5                0x7e
+#define RADIO_2056_SYN_LOGEN_ACL6                0x7f
+#define RADIO_2056_SYN_LOGEN_ACLOUT              0x80
+#define RADIO_2056_SYN_LOGEN_ACLCAL1             0x81
+#define RADIO_2056_SYN_LOGEN_ACLCAL2             0x82
+#define RADIO_2056_SYN_LOGEN_ACLCAL3             0x83
+#define RADIO_2056_SYN_CALEN                     0x84
+#define RADIO_2056_SYN_LOGEN_PEAKDET1            0x85
+#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR        0x86
+#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR     0x87
+#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR     0x88
+#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR     0x89
+#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR     0x8a
+#define RADIO_2056_SYN_LOGEN_VCOBUF2             0x8b
+#define RADIO_2056_SYN_LOGEN_MIXER3              0x8c
+#define RADIO_2056_SYN_LOGEN_BUF5                0x8d
+#define RADIO_2056_SYN_LOGEN_BUF6                0x8e
+#define RADIO_2056_SYN_LOGEN_CBUFRX1             0x8f
+#define RADIO_2056_SYN_LOGEN_CBUFRX2             0x90
+#define RADIO_2056_SYN_LOGEN_CBUFRX3             0x91
+#define RADIO_2056_SYN_LOGEN_CBUFRX4             0x92
+#define RADIO_2056_SYN_LOGEN_CBUFTX1             0x93
+#define RADIO_2056_SYN_LOGEN_CBUFTX2             0x94
+#define RADIO_2056_SYN_LOGEN_CBUFTX3             0x95
+#define RADIO_2056_SYN_LOGEN_CBUFTX4             0x96
+#define RADIO_2056_SYN_LOGEN_CMOSRX1             0x97
+#define RADIO_2056_SYN_LOGEN_CMOSRX2             0x98
+#define RADIO_2056_SYN_LOGEN_CMOSRX3             0x99
+#define RADIO_2056_SYN_LOGEN_CMOSRX4             0x9a
+#define RADIO_2056_SYN_LOGEN_CMOSTX1             0x9b
+#define RADIO_2056_SYN_LOGEN_CMOSTX2             0x9c
+#define RADIO_2056_SYN_LOGEN_CMOSTX3             0x9d
+#define RADIO_2056_SYN_LOGEN_CMOSTX4             0x9e
+#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL      0x9f
+#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL       0xa0
+#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL         0xa1
+#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL         0xa2
+#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL      0xa3
+#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL      0xa4
+#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL      0xa5
+#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL      0xa6
+#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL      0xa7
+#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL      0xa8
+#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL      0xa9
+#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL      0xaa
+#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL      0xab
+#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL      0xac
+#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL      0xad
+#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL      0xae
+#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL      0xaf
+#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL      0xb0
+#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL      0xb1
+#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL      0xb2
+#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT         0xb3
+#define RADIO_2056_SYN_LOGEN_CORE_CALVALID       0xb4
+#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID    0xb5
+#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID       0xb6
+
+#define RADIO_2056_TX_RESERVED_ADDR0             0x0
+#define RADIO_2056_TX_IDCODE                     0x1
+#define RADIO_2056_TX_RESERVED_ADDR2             0x2
+#define RADIO_2056_TX_RESERVED_ADDR3             0x3
+#define RADIO_2056_TX_RESERVED_ADDR4             0x4
+#define RADIO_2056_TX_RESERVED_ADDR5             0x5
+#define RADIO_2056_TX_RESERVED_ADDR6             0x6
+#define RADIO_2056_TX_RESERVED_ADDR7             0x7
+#define RADIO_2056_TX_COM_CTRL                   0x8
+#define RADIO_2056_TX_COM_PU                     0x9
+#define RADIO_2056_TX_COM_OVR                    0xa
+#define RADIO_2056_TX_COM_RESET                  0xb
+#define RADIO_2056_TX_COM_RCAL                   0xc
+#define RADIO_2056_TX_COM_RC_RXLPF               0xd
+#define RADIO_2056_TX_COM_RC_TXLPF               0xe
+#define RADIO_2056_TX_COM_RC_RXHPF               0xf
+#define RADIO_2056_TX_RESERVED_ADDR16            0x10
+#define RADIO_2056_TX_RESERVED_ADDR17            0x11
+#define RADIO_2056_TX_RESERVED_ADDR18            0x12
+#define RADIO_2056_TX_RESERVED_ADDR19            0x13
+#define RADIO_2056_TX_RESERVED_ADDR20            0x14
+#define RADIO_2056_TX_RESERVED_ADDR21            0x15
+#define RADIO_2056_TX_RESERVED_ADDR22            0x16
+#define RADIO_2056_TX_RESERVED_ADDR23            0x17
+#define RADIO_2056_TX_RESERVED_ADDR24            0x18
+#define RADIO_2056_TX_RESERVED_ADDR25            0x19
+#define RADIO_2056_TX_RESERVED_ADDR26            0x1a
+#define RADIO_2056_TX_RESERVED_ADDR27            0x1b
+#define RADIO_2056_TX_RESERVED_ADDR28            0x1c
+#define RADIO_2056_TX_RESERVED_ADDR29            0x1d
+#define RADIO_2056_TX_RESERVED_ADDR30            0x1e
+#define RADIO_2056_TX_RESERVED_ADDR31            0x1f
+#define RADIO_2056_TX_IQCAL_GAIN_BW              0x20
+#define RADIO_2056_TX_LOFT_FINE_I                0x21
+#define RADIO_2056_TX_LOFT_FINE_Q                0x22
+#define RADIO_2056_TX_LOFT_COARSE_I              0x23
+#define RADIO_2056_TX_LOFT_COARSE_Q              0x24
+#define RADIO_2056_TX_TX_COM_MASTER1             0x25
+#define RADIO_2056_TX_TX_COM_MASTER2             0x26
+#define RADIO_2056_TX_RXIQCAL_TXMUX              0x27
+#define RADIO_2056_TX_TX_SSI_MASTER              0x28
+#define RADIO_2056_TX_IQCAL_VCM_HG               0x29
+#define RADIO_2056_TX_IQCAL_IDAC                 0x2a
+#define RADIO_2056_TX_TSSI_VCM                   0x2b
+#define RADIO_2056_TX_TX_AMP_DET                 0x2c
+#define RADIO_2056_TX_TX_SSI_MUX                 0x2d
+#define RADIO_2056_TX_TSSIA                      0x2e
+#define RADIO_2056_TX_TSSIG                      0x2f
+#define RADIO_2056_TX_TSSI_MISC1                 0x30
+#define RADIO_2056_TX_TSSI_MISC2                 0x31
+#define RADIO_2056_TX_TSSI_MISC3                 0x32
+#define RADIO_2056_TX_PA_SPARE1                  0x33
+#define RADIO_2056_TX_PA_SPARE2                  0x34
+#define RADIO_2056_TX_INTPAA_MASTER              0x35
+#define RADIO_2056_TX_INTPAA_GAIN                0x36
+#define RADIO_2056_TX_INTPAA_BOOST_TUNE          0x37
+#define RADIO_2056_TX_INTPAA_IAUX_STAT           0x38
+#define RADIO_2056_TX_INTPAA_IAUX_DYN            0x39
+#define RADIO_2056_TX_INTPAA_IMAIN_STAT          0x3a
+#define RADIO_2056_TX_INTPAA_IMAIN_DYN           0x3b
+#define RADIO_2056_TX_INTPAA_CASCBIAS            0x3c
+#define RADIO_2056_TX_INTPAA_PASLOPE             0x3d
+#define RADIO_2056_TX_INTPAA_PA_MISC             0x3e
+#define RADIO_2056_TX_INTPAG_MASTER              0x3f
+#define RADIO_2056_TX_INTPAG_GAIN                0x40
+#define RADIO_2056_TX_INTPAG_BOOST_TUNE          0x41
+#define RADIO_2056_TX_INTPAG_IAUX_STAT           0x42
+#define RADIO_2056_TX_INTPAG_IAUX_DYN            0x43
+#define RADIO_2056_TX_INTPAG_IMAIN_STAT          0x44
+#define RADIO_2056_TX_INTPAG_IMAIN_DYN           0x45
+#define RADIO_2056_TX_INTPAG_CASCBIAS            0x46
+#define RADIO_2056_TX_INTPAG_PASLOPE             0x47
+#define RADIO_2056_TX_INTPAG_PA_MISC             0x48
+#define RADIO_2056_TX_PADA_MASTER                0x49
+#define RADIO_2056_TX_PADA_IDAC                  0x4a
+#define RADIO_2056_TX_PADA_CASCBIAS              0x4b
+#define RADIO_2056_TX_PADA_GAIN                  0x4c
+#define RADIO_2056_TX_PADA_BOOST_TUNE            0x4d
+#define RADIO_2056_TX_PADA_SLOPE                 0x4e
+#define RADIO_2056_TX_PADG_MASTER                0x4f
+#define RADIO_2056_TX_PADG_IDAC                  0x50
+#define RADIO_2056_TX_PADG_CASCBIAS              0x51
+#define RADIO_2056_TX_PADG_GAIN                  0x52
+#define RADIO_2056_TX_PADG_BOOST_TUNE            0x53
+#define RADIO_2056_TX_PADG_SLOPE                 0x54
+#define RADIO_2056_TX_PGAA_MASTER                0x55
+#define RADIO_2056_TX_PGAA_IDAC                  0x56
+#define RADIO_2056_TX_PGAA_GAIN                  0x57
+#define RADIO_2056_TX_PGAA_BOOST_TUNE            0x58
+#define RADIO_2056_TX_PGAA_SLOPE                 0x59
+#define RADIO_2056_TX_PGAA_MISC                  0x5a
+#define RADIO_2056_TX_PGAG_MASTER                0x5b
+#define RADIO_2056_TX_PGAG_IDAC                  0x5c
+#define RADIO_2056_TX_PGAG_GAIN                  0x5d
+#define RADIO_2056_TX_PGAG_BOOST_TUNE            0x5e
+#define RADIO_2056_TX_PGAG_SLOPE                 0x5f
+#define RADIO_2056_TX_PGAG_MISC                  0x60
+#define RADIO_2056_TX_MIXA_MASTER                0x61
+#define RADIO_2056_TX_MIXA_BOOST_TUNE            0x62
+#define RADIO_2056_TX_MIXG                       0x63
+#define RADIO_2056_TX_MIXG_BOOST_TUNE            0x64
+#define RADIO_2056_TX_BB_GM_MASTER               0x65
+#define RADIO_2056_TX_GMBB_GM                    0x66
+#define RADIO_2056_TX_GMBB_IDAC                  0x67
+#define RADIO_2056_TX_TXLPF_MASTER               0x68
+#define RADIO_2056_TX_TXLPF_RCCAL                0x69
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF0           0x6a
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF1           0x6b
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF2           0x6c
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF3           0x6d
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF4           0x6e
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF5           0x6f
+#define RADIO_2056_TX_TXLPF_RCCAL_OFF6           0x70
+#define RADIO_2056_TX_TXLPF_BW                   0x71
+#define RADIO_2056_TX_TXLPF_GAIN                 0x72
+#define RADIO_2056_TX_TXLPF_IDAC                 0x73
+#define RADIO_2056_TX_TXLPF_IDAC_0               0x74
+#define RADIO_2056_TX_TXLPF_IDAC_1               0x75
+#define RADIO_2056_TX_TXLPF_IDAC_2               0x76
+#define RADIO_2056_TX_TXLPF_IDAC_3               0x77
+#define RADIO_2056_TX_TXLPF_IDAC_4               0x78
+#define RADIO_2056_TX_TXLPF_IDAC_5               0x79
+#define RADIO_2056_TX_TXLPF_IDAC_6               0x7a
+#define RADIO_2056_TX_TXLPF_OPAMP_IDAC           0x7b
+#define RADIO_2056_TX_TXLPF_MISC                 0x7c
+#define RADIO_2056_TX_TXSPARE1                   0x7d
+#define RADIO_2056_TX_TXSPARE2                   0x7e
+#define RADIO_2056_TX_TXSPARE3                   0x7f
+#define RADIO_2056_TX_TXSPARE4                   0x80
+#define RADIO_2056_TX_TXSPARE5                   0x81
+#define RADIO_2056_TX_TXSPARE6                   0x82
+#define RADIO_2056_TX_TXSPARE7                   0x83
+#define RADIO_2056_TX_TXSPARE8                   0x84
+#define RADIO_2056_TX_TXSPARE9                   0x85
+#define RADIO_2056_TX_TXSPARE10                  0x86
+#define RADIO_2056_TX_TXSPARE11                  0x87
+#define RADIO_2056_TX_TXSPARE12                  0x88
+#define RADIO_2056_TX_TXSPARE13                  0x89
+#define RADIO_2056_TX_TXSPARE14                  0x8a
+#define RADIO_2056_TX_TXSPARE15                  0x8b
+#define RADIO_2056_TX_TXSPARE16                  0x8c
+#define RADIO_2056_TX_STATUS_INTPA_GAIN          0x8d
+#define RADIO_2056_TX_STATUS_PAD_GAIN            0x8e
+#define RADIO_2056_TX_STATUS_PGA_GAIN            0x8f
+#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN       0x90
+#define RADIO_2056_TX_STATUS_TXLPF_BW            0x91
+#define RADIO_2056_TX_STATUS_TXLPF_RC            0x92
+#define RADIO_2056_TX_GMBB_IDAC0                 0x93
+#define RADIO_2056_TX_GMBB_IDAC1                 0x94
+#define RADIO_2056_TX_GMBB_IDAC2                 0x95
+#define RADIO_2056_TX_GMBB_IDAC3                 0x96
+#define RADIO_2056_TX_GMBB_IDAC4                 0x97
+#define RADIO_2056_TX_GMBB_IDAC5                 0x98
+#define RADIO_2056_TX_GMBB_IDAC6                 0x99
+#define RADIO_2056_TX_GMBB_IDAC7                 0x9a
+
+#define RADIO_2056_RX_RESERVED_ADDR0             0x0
+#define RADIO_2056_RX_IDCODE                     0x1
+#define RADIO_2056_RX_RESERVED_ADDR2             0x2
+#define RADIO_2056_RX_RESERVED_ADDR3             0x3
+#define RADIO_2056_RX_RESERVED_ADDR4             0x4
+#define RADIO_2056_RX_RESERVED_ADDR5             0x5
+#define RADIO_2056_RX_RESERVED_ADDR6             0x6
+#define RADIO_2056_RX_RESERVED_ADDR7             0x7
+#define RADIO_2056_RX_COM_CTRL                   0x8
+#define RADIO_2056_RX_COM_PU                     0x9
+#define RADIO_2056_RX_COM_OVR                    0xa
+#define RADIO_2056_RX_COM_RESET                  0xb
+#define RADIO_2056_RX_COM_RCAL                   0xc
+#define RADIO_2056_RX_COM_RC_RXLPF               0xd
+#define RADIO_2056_RX_COM_RC_TXLPF               0xe
+#define RADIO_2056_RX_COM_RC_RXHPF               0xf
+#define RADIO_2056_RX_RESERVED_ADDR16            0x10
+#define RADIO_2056_RX_RESERVED_ADDR17            0x11
+#define RADIO_2056_RX_RESERVED_ADDR18            0x12
+#define RADIO_2056_RX_RESERVED_ADDR19            0x13
+#define RADIO_2056_RX_RESERVED_ADDR20            0x14
+#define RADIO_2056_RX_RESERVED_ADDR21            0x15
+#define RADIO_2056_RX_RESERVED_ADDR22            0x16
+#define RADIO_2056_RX_RESERVED_ADDR23            0x17
+#define RADIO_2056_RX_RESERVED_ADDR24            0x18
+#define RADIO_2056_RX_RESERVED_ADDR25            0x19
+#define RADIO_2056_RX_RESERVED_ADDR26            0x1a
+#define RADIO_2056_RX_RESERVED_ADDR27            0x1b
+#define RADIO_2056_RX_RESERVED_ADDR28            0x1c
+#define RADIO_2056_RX_RESERVED_ADDR29            0x1d
+#define RADIO_2056_RX_RESERVED_ADDR30            0x1e
+#define RADIO_2056_RX_RESERVED_ADDR31            0x1f
+#define RADIO_2056_RX_RXIQCAL_RXMUX              0x20
+#define RADIO_2056_RX_RSSI_PU                    0x21
+#define RADIO_2056_RX_RSSI_SEL                   0x22
+#define RADIO_2056_RX_RSSI_GAIN                  0x23
+#define RADIO_2056_RX_RSSI_NB_IDAC               0x24
+#define RADIO_2056_RX_RSSI_WB2I_IDAC_1           0x25
+#define RADIO_2056_RX_RSSI_WB2I_IDAC_2           0x26
+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1           0x27
+#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2           0x28
+#define RADIO_2056_RX_RSSI_POLE                  0x29
+#define RADIO_2056_RX_RSSI_WB1_IDAC              0x2a
+#define RADIO_2056_RX_RSSI_MISC                  0x2b
+#define RADIO_2056_RX_LNAA_MASTER                0x2c
+#define RADIO_2056_RX_LNAA_TUNE                  0x2d
+#define RADIO_2056_RX_LNAA_GAIN                  0x2e
+#define RADIO_2056_RX_LNA_A_SLOPE                0x2f
+#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC        0x30
+#define RADIO_2056_RX_LNAA2_IDAC                 0x31
+#define RADIO_2056_RX_LNA1A_MISC                 0x32
+#define RADIO_2056_RX_LNAG_MASTER                0x33
+#define RADIO_2056_RX_LNAG_TUNE                  0x34
+#define RADIO_2056_RX_LNAG_GAIN                  0x35
+#define RADIO_2056_RX_LNA_G_SLOPE                0x36
+#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC        0x37
+#define RADIO_2056_RX_LNAG2_IDAC                 0x38
+#define RADIO_2056_RX_LNA1G_MISC                 0x39
+#define RADIO_2056_RX_MIXA_MASTER                0x3a
+#define RADIO_2056_RX_MIXA_VCM                   0x3b
+#define RADIO_2056_RX_MIXA_CTRLPTAT              0x3c
+#define RADIO_2056_RX_MIXA_LOB_BIAS              0x3d
+#define RADIO_2056_RX_MIXA_CORE_IDAC             0x3e
+#define RADIO_2056_RX_MIXA_CMFB_IDAC             0x3f
+#define RADIO_2056_RX_MIXA_BIAS_AUX              0x40
+#define RADIO_2056_RX_MIXA_BIAS_MAIN             0x41
+#define RADIO_2056_RX_MIXA_BIAS_MISC             0x42
+#define RADIO_2056_RX_MIXA_MAST_BIAS             0x43
+#define RADIO_2056_RX_MIXG_MASTER                0x44
+#define RADIO_2056_RX_MIXG_VCM                   0x45
+#define RADIO_2056_RX_MIXG_CTRLPTAT              0x46
+#define RADIO_2056_RX_MIXG_LOB_BIAS              0x47
+#define RADIO_2056_RX_MIXG_CORE_IDAC             0x48
+#define RADIO_2056_RX_MIXG_CMFB_IDAC             0x49
+#define RADIO_2056_RX_MIXG_BIAS_AUX              0x4a
+#define RADIO_2056_RX_MIXG_BIAS_MAIN             0x4b
+#define RADIO_2056_RX_MIXG_BIAS_MISC             0x4c
+#define RADIO_2056_RX_MIXG_MAST_BIAS             0x4d
+#define RADIO_2056_RX_TIA_MASTER                 0x4e
+#define RADIO_2056_RX_TIA_IOPAMP                 0x4f
+#define RADIO_2056_RX_TIA_QOPAMP                 0x50
+#define RADIO_2056_RX_TIA_IMISC                  0x51
+#define RADIO_2056_RX_TIA_QMISC                  0x52
+#define RADIO_2056_RX_TIA_GAIN                   0x53
+#define RADIO_2056_RX_TIA_SPARE1                 0x54
+#define RADIO_2056_RX_TIA_SPARE2                 0x55
+#define RADIO_2056_RX_BB_LPF_MASTER              0x56
+#define RADIO_2056_RX_AACI_MASTER                0x57
+#define RADIO_2056_RX_RXLPF_IDAC                 0x58
+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ       0x59
+#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ      0x5a
+#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL        0x5b
+#define RADIO_2056_RX_RXLPF_OUTVCM               0x5c
+#define RADIO_2056_RX_RXLPF_INVCM_BODY           0x5d
+#define RADIO_2056_RX_RXLPF_CC_OP                0x5e
+#define RADIO_2056_RX_RXLPF_GAIN                 0x5f
+#define RADIO_2056_RX_RXLPF_Q_BW                 0x60
+#define RADIO_2056_RX_RXLPF_HP_CORNER_BW         0x61
+#define RADIO_2056_RX_RXLPF_RCCAL_HPC            0x62
+#define RADIO_2056_RX_RXHPF_OFF0                 0x63
+#define RADIO_2056_RX_RXHPF_OFF1                 0x64
+#define RADIO_2056_RX_RXHPF_OFF2                 0x65
+#define RADIO_2056_RX_RXHPF_OFF3                 0x66
+#define RADIO_2056_RX_RXHPF_OFF4                 0x67
+#define RADIO_2056_RX_RXHPF_OFF5                 0x68
+#define RADIO_2056_RX_RXHPF_OFF6                 0x69
+#define RADIO_2056_RX_RXHPF_OFF7                 0x6a
+#define RADIO_2056_RX_RXLPF_RCCAL_LPC            0x6b
+#define RADIO_2056_RX_RXLPF_OFF_0                0x6c
+#define RADIO_2056_RX_RXLPF_OFF_1                0x6d
+#define RADIO_2056_RX_RXLPF_OFF_2                0x6e
+#define RADIO_2056_RX_RXLPF_OFF_3                0x6f
+#define RADIO_2056_RX_RXLPF_OFF_4                0x70
+#define RADIO_2056_RX_UNUSED                     0x71
+#define RADIO_2056_RX_VGA_MASTER                 0x72
+#define RADIO_2056_RX_VGA_BIAS                   0x73
+#define RADIO_2056_RX_VGA_BIAS_DCCANCEL          0x74
+#define RADIO_2056_RX_VGA_GAIN                   0x75
+#define RADIO_2056_RX_VGA_HP_CORNER_BW           0x76
+#define RADIO_2056_RX_VGABUF_BIAS                0x77
+#define RADIO_2056_RX_VGABUF_GAIN_BW             0x78
+#define RADIO_2056_RX_TXFBMIX_A                  0x79
+#define RADIO_2056_RX_TXFBMIX_G                  0x7a
+#define RADIO_2056_RX_RXSPARE1                   0x7b
+#define RADIO_2056_RX_RXSPARE2                   0x7c
+#define RADIO_2056_RX_RXSPARE3                   0x7d
+#define RADIO_2056_RX_RXSPARE4                   0x7e
+#define RADIO_2056_RX_RXSPARE5                   0x7f
+#define RADIO_2056_RX_RXSPARE6                   0x80
+#define RADIO_2056_RX_RXSPARE7                   0x81
+#define RADIO_2056_RX_RXSPARE8                   0x82
+#define RADIO_2056_RX_RXSPARE9                   0x83
+#define RADIO_2056_RX_RXSPARE10                  0x84
+#define RADIO_2056_RX_RXSPARE11                  0x85
+#define RADIO_2056_RX_RXSPARE12                  0x86
+#define RADIO_2056_RX_RXSPARE13                  0x87
+#define RADIO_2056_RX_RXSPARE14                  0x88
+#define RADIO_2056_RX_RXSPARE15                  0x89
+#define RADIO_2056_RX_RXSPARE16                  0x8a
+#define RADIO_2056_RX_STATUS_LNAA_GAIN           0x8b
+#define RADIO_2056_RX_STATUS_LNAG_GAIN           0x8c
+#define RADIO_2056_RX_STATUS_MIXTIA_GAIN         0x8d
+#define RADIO_2056_RX_STATUS_RXLPF_GAIN          0x8e
+#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN        0x8f
+#define RADIO_2056_RX_STATUS_RXLPF_Q             0x90
+#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW        0x91
+#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC       0x92
+#define RADIO_2056_RX_STATUS_RXLPF_RC            0x93
+#define RADIO_2056_RX_STATUS_HPC_RC              0x94
+
+#define RADIO_2056_LNA1_A_PU		0x01
+#define RADIO_2056_LNA2_A_PU		0x02
+#define RADIO_2056_LNA1_G_PU		0x01
+#define RADIO_2056_LNA2_G_PU		0x02
+#define RADIO_2056_MIXA_PU_I		0x01
+#define RADIO_2056_MIXA_PU_Q		0x02
+#define RADIO_2056_MIXA_PU_GM		0x10
+#define RADIO_2056_MIXG_PU_I		0x01
+#define RADIO_2056_MIXG_PU_Q		0x02
+#define RADIO_2056_MIXG_PU_GM		0x10
+#define RADIO_2056_TIA_PU			0x01
+#define RADIO_2056_BB_LPF_PU		0x20
+#define RADIO_2056_W1_PU			0x02
+#define RADIO_2056_W2_PU			0x04
+#define RADIO_2056_NB_PU			0x08
+#define RADIO_2056_RSSI_W1_SEL		0x02
+#define RADIO_2056_RSSI_W2_SEL		0x04
+#define RADIO_2056_RSSI_NB_SEL		0x08
+#define RADIO_2056_VCM_MASK			0x1c
+#define RADIO_2056_RSSI_VCM_SHIFT	0x02
+
+#define RADIO_2057_DACBUF_VINCM_CORE0            0x0
+#define RADIO_2057_IDCODE                        0x1
+#define RADIO_2057_RCCAL_MASTER                  0x2
+#define RADIO_2057_RCCAL_CAP_SIZE                0x3
+#define RADIO_2057_RCAL_CONFIG                   0x4
+#define RADIO_2057_GPAIO_CONFIG                  0x5
+#define RADIO_2057_GPAIO_SEL1                    0x6
+#define RADIO_2057_GPAIO_SEL0                    0x7
+#define RADIO_2057_CLPO_CONFIG                   0x8
+#define RADIO_2057_BANDGAP_CONFIG                0x9
+#define RADIO_2057_BANDGAP_RCAL_TRIM             0xa
+#define RADIO_2057_AFEREG_CONFIG                 0xb
+#define RADIO_2057_TEMPSENSE_CONFIG              0xc
+#define RADIO_2057_XTAL_CONFIG1                  0xd
+#define RADIO_2057_XTAL_ICORE_SIZE               0xe
+#define RADIO_2057_XTAL_BUF_SIZE                 0xf
+#define RADIO_2057_XTAL_PULLCAP_SIZE             0x10
+#define RADIO_2057_RFPLL_MASTER                  0x11
+#define RADIO_2057_VCOMONITOR_VTH_L              0x12
+#define RADIO_2057_VCOMONITOR_VTH_H              0x13
+#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14
+#define RADIO_2057_VCO_VARCSIZE_IDAC             0x15
+#define RADIO_2057_VCOCAL_COUNTVAL0              0x16
+#define RADIO_2057_VCOCAL_COUNTVAL1              0x17
+#define RADIO_2057_VCOCAL_INTCLK_COUNT           0x18
+#define RADIO_2057_VCOCAL_MASTER                 0x19
+#define RADIO_2057_VCOCAL_NUMCAPCHANGE           0x1a
+#define RADIO_2057_VCOCAL_WINSIZE                0x1b
+#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH    0x1c
+#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP  0x1d
+#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP   0x1e
+#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP  0x1f
+#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1      0x20
+#define RADIO_2057_VCO_FORCECAP0                 0x21
+#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22
+#define RADIO_2057_RFPLL_PFD_RESET_PW            0x23
+#define RADIO_2057_RFPLL_LOOPFILTER_R2           0x24
+#define RADIO_2057_RFPLL_LOOPFILTER_R1           0x25
+#define RADIO_2057_RFPLL_LOOPFILTER_C3           0x26
+#define RADIO_2057_RFPLL_LOOPFILTER_C2           0x27
+#define RADIO_2057_RFPLL_LOOPFILTER_C1           0x28
+#define RADIO_2057_CP_KPD_IDAC                   0x29
+#define RADIO_2057_RFPLL_IDACS                   0x2a
+#define RADIO_2057_RFPLL_MISC_EN                 0x2b
+#define RADIO_2057_RFPLL_MMD0                    0x2c
+#define RADIO_2057_RFPLL_MMD1                    0x2d
+#define RADIO_2057_RFPLL_MISC_CAL_RESETN         0x2e
+#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES  0x2f
+#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE     0x30
+#define RADIO_2057_VCOCAL_READCAP0               0x31
+#define RADIO_2057_VCOCAL_READCAP1               0x32
+#define RADIO_2057_VCOCAL_STATUS                 0x33
+#define RADIO_2057_LOGEN_PUS                     0x34
+#define RADIO_2057_LOGEN_PTAT_RESETS             0x35
+#define RADIO_2057_VCOBUF_IDACS                  0x36
+#define RADIO_2057_VCOBUF_TUNE                   0x37
+#define RADIO_2057_CMOSBUF_TX2GQ_IDACS           0x38
+#define RADIO_2057_CMOSBUF_TX2GI_IDACS           0x39
+#define RADIO_2057_CMOSBUF_TX5GQ_IDACS           0x3a
+#define RADIO_2057_CMOSBUF_TX5GI_IDACS           0x3b
+#define RADIO_2057_CMOSBUF_RX2GQ_IDACS           0x3c
+#define RADIO_2057_CMOSBUF_RX2GI_IDACS           0x3d
+#define RADIO_2057_CMOSBUF_RX5GQ_IDACS           0x3e
+#define RADIO_2057_CMOSBUF_RX5GI_IDACS           0x3f
+#define RADIO_2057_LOGEN_MX2G_IDACS              0x40
+#define RADIO_2057_LOGEN_MX2G_TUNE               0x41
+#define RADIO_2057_LOGEN_MX5G_IDACS              0x42
+#define RADIO_2057_LOGEN_MX5G_TUNE               0x43
+#define RADIO_2057_LOGEN_MX5G_RCCR               0x44
+#define RADIO_2057_LOGEN_INDBUF2G_IDAC           0x45
+#define RADIO_2057_LOGEN_INDBUF2G_IBOOST         0x46
+#define RADIO_2057_LOGEN_INDBUF2G_TUNE           0x47
+#define RADIO_2057_LOGEN_INDBUF5G_IDAC           0x48
+#define RADIO_2057_LOGEN_INDBUF5G_IBOOST         0x49
+#define RADIO_2057_LOGEN_INDBUF5G_TUNE           0x4a
+#define RADIO_2057_CMOSBUF_TX_RCCR               0x4b
+#define RADIO_2057_CMOSBUF_RX_RCCR               0x4c
+#define RADIO_2057_LOGEN_SEL_PKDET               0x4d
+#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT          0x4e
+#define RADIO_2057_RXTXBIAS_CONFIG_CORE0         0x4f
+#define RADIO_2057_TXGM_TXRF_PUS_CORE0           0x50
+#define RADIO_2057_TXGM_IDAC_BLEED_CORE0         0x51
+#define RADIO_2057_TXGM_GAIN_CORE0               0x56
+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0        0x57
+#define RADIO_2057_PAD2G_PTATS_CORE0             0x58
+#define RADIO_2057_PAD2G_IDACS_CORE0             0x59
+#define RADIO_2057_PAD2G_BOOST_PU_CORE0          0x5a
+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0        0x5b
+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0   0x5c
+#define RADIO_2057_TXMIX2G_LODC_CORE0            0x5d
+#define RADIO_2057_PAD2G_TUNE_PUS_CORE0          0x5e
+#define RADIO_2057_IPA2G_GAIN_CORE0              0x5f
+#define RADIO_2057_TSSI2G_SPARE1_CORE0           0x60
+#define RADIO_2057_TSSI2G_SPARE2_CORE0           0x61
+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0  0x62
+#define RADIO_2057_IPA2G_IMAIN_CORE0             0x63
+#define RADIO_2057_IPA2G_CASCONV_CORE0           0x64
+#define RADIO_2057_IPA2G_CASCOFFV_CORE0          0x65
+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0       0x66
+#define RADIO_2057_TX5G_PKDET_CORE0              0x69
+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0      0x6a
+#define RADIO_2057_PAD5G_PTATS1_CORE0            0x6b
+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0      0x6c
+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0     0x6d
+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0       0x6e
+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f
+#define RADIO_2057_PGA_BOOST_TUNE_CORE0          0x70
+#define RADIO_2057_PGA_GAIN_CORE0                0x71
+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72
+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0      0x73
+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0     0x74
+#define RADIO_2057_IPA5G_IAUX_CORE0              0x75
+#define RADIO_2057_IPA5G_GAIN_CORE0              0x76
+#define RADIO_2057_TSSI5G_SPARE1_CORE0           0x77
+#define RADIO_2057_TSSI5G_SPARE2_CORE0           0x78
+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0       0x79
+#define RADIO_2057_IPA5G_PTAT_CORE0              0x7a
+#define RADIO_2057_IPA5G_IMAIN_CORE0             0x7b
+#define RADIO_2057_IPA5G_CASCONV_CORE0           0x7c
+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0       0x7d
+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0     0x80
+#define RADIO_2057_TR2G_CONFIG1_CORE0_NU         0x81
+#define RADIO_2057_TR2G_CONFIG2_CORE0_NU         0x82
+#define RADIO_2057_LNA5G_RFEN_CORE0              0x83
+#define RADIO_2057_TR5G_CONFIG2_CORE0_NU         0x84
+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0      0x85
+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86
+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0  0x87
+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0   0x88
+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0      0x89
+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0      0x8a
+#define RADIO_2057_LNA2_IAUX_PTAT_CORE0          0x8b
+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0      0x8c
+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d
+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0        0x8e
+#define RADIO_2057_TIA_CONFIG_CORE0              0x8f
+#define RADIO_2057_TIA_IQGAIN_CORE0              0x90
+#define RADIO_2057_TIA_IBIAS2_CORE0              0x91
+#define RADIO_2057_TIA_IBIAS1_CORE0              0x92
+#define RADIO_2057_TIA_SPARE_Q_CORE0             0x93
+#define RADIO_2057_TIA_SPARE_I_CORE0             0x94
+#define RADIO_2057_RXMIX2G_PUS_CORE0             0x95
+#define RADIO_2057_RXMIX2G_VCMREFS_CORE0         0x96
+#define RADIO_2057_RXMIX2G_LODC_QI_CORE0         0x97
+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0       0x98
+#define RADIO_2057_LNA2G_GAIN_CORE0              0x99
+#define RADIO_2057_LNA2G_TUNE_CORE0              0x9a
+#define RADIO_2057_RXMIX5G_PUS_CORE0             0x9b
+#define RADIO_2057_RXMIX5G_VCMREFS_CORE0         0x9c
+#define RADIO_2057_RXMIX5G_LODC_QI_CORE0         0x9d
+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0       0x9e
+#define RADIO_2057_LNA5G_GAIN_CORE0              0x9f
+#define RADIO_2057_LNA5G_TUNE_CORE0              0xa0
+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0    0xa1
+#define RADIO_2057_RXBB_BIAS_MASTER_CORE0        0xa2
+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0       0xa3
+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4
+#define RADIO_2057_TXBUF_VINCM_CORE0             0xa5
+#define RADIO_2057_TXBUF_IDACS_CORE0             0xa6
+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0       0xa7
+#define RADIO_2057_RXBB_CC_CORE0                 0xa8
+#define RADIO_2057_RXBB_SPARE3_CORE0             0xa9
+#define RADIO_2057_RXBB_RCCAL_HPC_CORE0          0xaa
+#define RADIO_2057_LPF_IDACS_CORE0               0xab
+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0  0xac
+#define RADIO_2057_TXBUF_GAIN_CORE0              0xad
+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0   0xae
+#define RADIO_2057_RXBUF_DEGEN_CORE0             0xaf
+#define RADIO_2057_RXBB_SPARE2_CORE0             0xb0
+#define RADIO_2057_RXBB_SPARE1_CORE0             0xb1
+#define RADIO_2057_RSSI_MASTER_CORE0             0xb2
+#define RADIO_2057_W2_MASTER_CORE0               0xb3
+#define RADIO_2057_NB_MASTER_CORE0               0xb4
+#define RADIO_2057_W2_IDACS0_Q_CORE0             0xb5
+#define RADIO_2057_W2_IDACS1_Q_CORE0             0xb6
+#define RADIO_2057_W2_IDACS0_I_CORE0             0xb7
+#define RADIO_2057_W2_IDACS1_I_CORE0             0xb8
+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0  0xb9
+#define RADIO_2057_NB_IDACS_Q_CORE0              0xba
+#define RADIO_2057_NB_IDACS_I_CORE0              0xbb
+#define RADIO_2057_BACKUP4_CORE0                 0xc1
+#define RADIO_2057_BACKUP3_CORE0                 0xc2
+#define RADIO_2057_BACKUP2_CORE0                 0xc3
+#define RADIO_2057_BACKUP1_CORE0                 0xc4
+#define RADIO_2057_SPARE16_CORE0                 0xc5
+#define RADIO_2057_SPARE15_CORE0                 0xc6
+#define RADIO_2057_SPARE14_CORE0                 0xc7
+#define RADIO_2057_SPARE13_CORE0                 0xc8
+#define RADIO_2057_SPARE12_CORE0                 0xc9
+#define RADIO_2057_SPARE11_CORE0                 0xca
+#define RADIO_2057_TX2G_BIAS_RESETS_CORE0        0xcb
+#define RADIO_2057_TX5G_BIAS_RESETS_CORE0        0xcc
+#define RADIO_2057_IQTEST_SEL_PU                 0xcd
+#define RADIO_2057_XTAL_CONFIG2                  0xce
+#define RADIO_2057_BUFS_MISC_LPFBW_CORE0         0xcf
+#define RADIO_2057_TXLPF_RCCAL_CORE0             0xd0
+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1
+#define RADIO_2057_LPF_GAIN_CORE0                0xd2
+#define RADIO_2057_DACBUF_IDACS_BW_CORE0         0xd3
+#define RADIO_2057_RXTXBIAS_CONFIG_CORE1         0xd4
+#define RADIO_2057_TXGM_TXRF_PUS_CORE1           0xd5
+#define RADIO_2057_TXGM_IDAC_BLEED_CORE1         0xd6
+#define RADIO_2057_TXGM_GAIN_CORE1               0xdb
+#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1        0xdc
+#define RADIO_2057_PAD2G_PTATS_CORE1             0xdd
+#define RADIO_2057_PAD2G_IDACS_CORE1             0xde
+#define RADIO_2057_PAD2G_BOOST_PU_CORE1          0xdf
+#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1        0xe0
+#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1   0xe1
+#define RADIO_2057_TXMIX2G_LODC_CORE1            0xe2
+#define RADIO_2057_PAD2G_TUNE_PUS_CORE1          0xe3
+#define RADIO_2057_IPA2G_GAIN_CORE1              0xe4
+#define RADIO_2057_TSSI2G_SPARE1_CORE1           0xe5
+#define RADIO_2057_TSSI2G_SPARE2_CORE1           0xe6
+#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1  0xe7
+#define RADIO_2057_IPA2G_IMAIN_CORE1             0xe8
+#define RADIO_2057_IPA2G_CASCONV_CORE1           0xe9
+#define RADIO_2057_IPA2G_CASCOFFV_CORE1          0xea
+#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1       0xeb
+#define RADIO_2057_TX5G_PKDET_CORE1              0xee
+#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1      0xef
+#define RADIO_2057_PAD5G_PTATS1_CORE1            0xf0
+#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1      0xf1
+#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1     0xf2
+#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1       0xf3
+#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4
+#define RADIO_2057_PGA_BOOST_TUNE_CORE1          0xf5
+#define RADIO_2057_PGA_GAIN_CORE1                0xf6
+#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7
+#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1      0xf8
+#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1     0xf9
+#define RADIO_2057_IPA5G_IAUX_CORE1              0xfa
+#define RADIO_2057_IPA5G_GAIN_CORE1              0xfb
+#define RADIO_2057_TSSI5G_SPARE1_CORE1           0xfc
+#define RADIO_2057_TSSI5G_SPARE2_CORE1           0xfd
+#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1       0xfe
+#define RADIO_2057_IPA5G_PTAT_CORE1              0xff
+#define RADIO_2057_IPA5G_IMAIN_CORE1             0x100
+#define RADIO_2057_IPA5G_CASCONV_CORE1           0x101
+#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1       0x102
+#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1     0x105
+#define RADIO_2057_TR2G_CONFIG1_CORE1_NU         0x106
+#define RADIO_2057_TR2G_CONFIG2_CORE1_NU         0x107
+#define RADIO_2057_LNA5G_RFEN_CORE1              0x108
+#define RADIO_2057_TR5G_CONFIG2_CORE1_NU         0x109
+#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1      0x10a
+#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
+#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1  0x10c
+#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1   0x10d
+#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1      0x10e
+#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1      0x10f
+#define RADIO_2057_LNA2_IAUX_PTAT_CORE1          0x110
+#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1      0x111
+#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
+#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1        0x113
+#define RADIO_2057_TIA_CONFIG_CORE1              0x114
+#define RADIO_2057_TIA_IQGAIN_CORE1              0x115
+#define RADIO_2057_TIA_IBIAS2_CORE1              0x116
+#define RADIO_2057_TIA_IBIAS1_CORE1              0x117
+#define RADIO_2057_TIA_SPARE_Q_CORE1             0x118
+#define RADIO_2057_TIA_SPARE_I_CORE1             0x119
+#define RADIO_2057_RXMIX2G_PUS_CORE1             0x11a
+#define RADIO_2057_RXMIX2G_VCMREFS_CORE1         0x11b
+#define RADIO_2057_RXMIX2G_LODC_QI_CORE1         0x11c
+#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1       0x11d
+#define RADIO_2057_LNA2G_GAIN_CORE1              0x11e
+#define RADIO_2057_LNA2G_TUNE_CORE1              0x11f
+#define RADIO_2057_RXMIX5G_PUS_CORE1             0x120
+#define RADIO_2057_RXMIX5G_VCMREFS_CORE1         0x121
+#define RADIO_2057_RXMIX5G_LODC_QI_CORE1         0x122
+#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1       0x123
+#define RADIO_2057_LNA5G_GAIN_CORE1              0x124
+#define RADIO_2057_LNA5G_TUNE_CORE1              0x125
+#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1    0x126
+#define RADIO_2057_RXBB_BIAS_MASTER_CORE1        0x127
+#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1       0x128
+#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
+#define RADIO_2057_TXBUF_VINCM_CORE1             0x12a
+#define RADIO_2057_TXBUF_IDACS_CORE1             0x12b
+#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1       0x12c
+#define RADIO_2057_RXBB_CC_CORE1                 0x12d
+#define RADIO_2057_RXBB_SPARE3_CORE1             0x12e
+#define RADIO_2057_RXBB_RCCAL_HPC_CORE1          0x12f
+#define RADIO_2057_LPF_IDACS_CORE1               0x130
+#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1  0x131
+#define RADIO_2057_TXBUF_GAIN_CORE1              0x132
+#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1   0x133
+#define RADIO_2057_RXBUF_DEGEN_CORE1             0x134
+#define RADIO_2057_RXBB_SPARE2_CORE1             0x135
+#define RADIO_2057_RXBB_SPARE1_CORE1             0x136
+#define RADIO_2057_RSSI_MASTER_CORE1             0x137
+#define RADIO_2057_W2_MASTER_CORE1               0x138
+#define RADIO_2057_NB_MASTER_CORE1               0x139
+#define RADIO_2057_W2_IDACS0_Q_CORE1             0x13a
+#define RADIO_2057_W2_IDACS1_Q_CORE1             0x13b
+#define RADIO_2057_W2_IDACS0_I_CORE1             0x13c
+#define RADIO_2057_W2_IDACS1_I_CORE1             0x13d
+#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1  0x13e
+#define RADIO_2057_NB_IDACS_Q_CORE1              0x13f
+#define RADIO_2057_NB_IDACS_I_CORE1              0x140
+#define RADIO_2057_BACKUP4_CORE1                 0x146
+#define RADIO_2057_BACKUP3_CORE1                 0x147
+#define RADIO_2057_BACKUP2_CORE1                 0x148
+#define RADIO_2057_BACKUP1_CORE1                 0x149
+#define RADIO_2057_SPARE16_CORE1                 0x14a
+#define RADIO_2057_SPARE15_CORE1                 0x14b
+#define RADIO_2057_SPARE14_CORE1                 0x14c
+#define RADIO_2057_SPARE13_CORE1                 0x14d
+#define RADIO_2057_SPARE12_CORE1                 0x14e
+#define RADIO_2057_SPARE11_CORE1                 0x14f
+#define RADIO_2057_TX2G_BIAS_RESETS_CORE1        0x150
+#define RADIO_2057_TX5G_BIAS_RESETS_CORE1        0x151
+#define RADIO_2057_SPARE8_CORE1                  0x152
+#define RADIO_2057_SPARE7_CORE1                  0x153
+#define RADIO_2057_BUFS_MISC_LPFBW_CORE1         0x154
+#define RADIO_2057_TXLPF_RCCAL_CORE1             0x155
+#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
+#define RADIO_2057_LPF_GAIN_CORE1                0x157
+#define RADIO_2057_DACBUF_IDACS_BW_CORE1         0x158
+#define RADIO_2057_DACBUF_VINCM_CORE1            0x159
+#define RADIO_2057_RCCAL_START_R1_Q1_P1          0x15a
+#define RADIO_2057_RCCAL_X1                      0x15b
+#define RADIO_2057_RCCAL_TRC0                    0x15c
+#define RADIO_2057_RCCAL_TRC1                    0x15d
+#define RADIO_2057_RCCAL_DONE_OSCCAP             0x15e
+#define RADIO_2057_RCCAL_N0_0                    0x15f
+#define RADIO_2057_RCCAL_N0_1                    0x160
+#define RADIO_2057_RCCAL_N1_0                    0x161
+#define RADIO_2057_RCCAL_N1_1                    0x162
+#define RADIO_2057_RCAL_STATUS                   0x163
+#define RADIO_2057_XTALPUOVR_PINCTRL             0x164
+#define RADIO_2057_OVR_REG0                      0x165
+#define RADIO_2057_OVR_REG1                      0x166
+#define RADIO_2057_OVR_REG2                      0x167
+#define RADIO_2057_OVR_REG3                      0x168
+#define RADIO_2057_OVR_REG4                      0x169
+#define RADIO_2057_RCCAL_SCAP_VAL                0x16a
+#define RADIO_2057_RCCAL_BCAP_VAL                0x16b
+#define RADIO_2057_RCCAL_HPC_VAL                 0x16c
+#define RADIO_2057_RCCAL_OVERRIDES               0x16d
+#define RADIO_2057_TX0_IQCAL_GAIN_BW             0x170
+#define RADIO_2057_TX0_LOFT_FINE_I               0x171
+#define RADIO_2057_TX0_LOFT_FINE_Q               0x172
+#define RADIO_2057_TX0_LOFT_COARSE_I             0x173
+#define RADIO_2057_TX0_LOFT_COARSE_Q             0x174
+#define RADIO_2057_TX0_TX_SSI_MASTER             0x175
+#define RADIO_2057_TX0_IQCAL_VCM_HG              0x176
+#define RADIO_2057_TX0_IQCAL_IDAC                0x177
+#define RADIO_2057_TX0_TSSI_VCM                  0x178
+#define RADIO_2057_TX0_TX_SSI_MUX                0x179
+#define RADIO_2057_TX0_TSSIA                     0x17a
+#define RADIO_2057_TX0_TSSIG                     0x17b
+#define RADIO_2057_TX0_TSSI_MISC1                0x17c
+#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN       0x17d
+#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP       0x17e
+#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN       0x17f
+#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP       0x180
+#define RADIO_2057_TX1_IQCAL_GAIN_BW             0x190
+#define RADIO_2057_TX1_LOFT_FINE_I               0x191
+#define RADIO_2057_TX1_LOFT_FINE_Q               0x192
+#define RADIO_2057_TX1_LOFT_COARSE_I             0x193
+#define RADIO_2057_TX1_LOFT_COARSE_Q             0x194
+#define RADIO_2057_TX1_TX_SSI_MASTER             0x195
+#define RADIO_2057_TX1_IQCAL_VCM_HG              0x196
+#define RADIO_2057_TX1_IQCAL_IDAC                0x197
+#define RADIO_2057_TX1_TSSI_VCM                  0x198
+#define RADIO_2057_TX1_TX_SSI_MUX                0x199
+#define RADIO_2057_TX1_TSSIA                     0x19a
+#define RADIO_2057_TX1_TSSIG                     0x19b
+#define RADIO_2057_TX1_TSSI_MISC1                0x19c
+#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN       0x19d
+#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP       0x19e
+#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN       0x19f
+#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP       0x1a0
+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0      0x1a1
+#define RADIO_2057_AFE_SET_VCM_I_CORE0           0x1a2
+#define RADIO_2057_AFE_SET_VCM_Q_CORE0           0x1a3
+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0    0x1a4
+#define RADIO_2057_AFE_STATUS_VCM_I_CORE0        0x1a5
+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0        0x1a6
+#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1      0x1a7
+#define RADIO_2057_AFE_SET_VCM_I_CORE1           0x1a8
+#define RADIO_2057_AFE_SET_VCM_Q_CORE1           0x1a9
+#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1    0x1aa
+#define RADIO_2057_AFE_STATUS_VCM_I_CORE1        0x1ab
+#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1        0x1ac
+
+#define RADIO_2057v7_DACBUF_VINCM_CORE0          0x1ad
+#define RADIO_2057v7_RCCAL_MASTER                0x1ae
+#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU       0x1af
+#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU       0x1b0
+#define RADIO_2057v7_LOGEN_PUS1                  0x1b1
+#define RADIO_2057v7_OVR_REG5                    0x1b2
+#define RADIO_2057v7_OVR_REG6                    0x1b3
+#define RADIO_2057v7_OVR_REG7                    0x1b4
+#define RADIO_2057v7_OVR_REG8                    0x1b5
+#define RADIO_2057v7_OVR_REG9                    0x1b6
+#define RADIO_2057v7_OVR_REG10                   0x1b7
+#define RADIO_2057v7_OVR_REG11                   0x1b8
+#define RADIO_2057v7_OVR_REG12                   0x1b9
+#define RADIO_2057v7_OVR_REG13                   0x1ba
+#define RADIO_2057v7_OVR_REG14                   0x1bb
+#define RADIO_2057v7_OVR_REG15                   0x1bc
+#define RADIO_2057v7_OVR_REG16                   0x1bd
+#define RADIO_2057v7_OVR_REG1                    0x1be
+#define RADIO_2057v7_OVR_REG18                   0x1bf
+#define RADIO_2057v7_OVR_REG19                   0x1c0
+#define RADIO_2057v7_OVR_REG20                   0x1c1
+#define RADIO_2057v7_OVR_REG21                   0x1c2
+#define RADIO_2057v7_OVR_REG2                    0x1c3
+#define RADIO_2057v7_OVR_REG23                   0x1c4
+#define RADIO_2057v7_OVR_REG24                   0x1c5
+#define RADIO_2057v7_OVR_REG25                   0x1c6
+#define RADIO_2057v7_OVR_REG26                   0x1c7
+#define RADIO_2057v7_OVR_REG27                   0x1c8
+#define RADIO_2057v7_OVR_REG28                   0x1c9
+#define RADIO_2057v7_IQTEST_SEL_PU2              0x1ca
+
+#define RADIO_2057_VCM_MASK			 0x7
+
+#endif				/* _BCM20XX_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h
new file mode 100644
index 0000000..211bc3a
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phyreg_n.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define NPHY_TBL_ID_GAIN1		0
+#define NPHY_TBL_ID_GAIN2		1
+#define NPHY_TBL_ID_GAINBITS1		2
+#define NPHY_TBL_ID_GAINBITS2		3
+#define NPHY_TBL_ID_GAINLIMIT		4
+#define NPHY_TBL_ID_WRSSIGainLimit	5
+#define NPHY_TBL_ID_RFSEQ		7
+#define NPHY_TBL_ID_AFECTRL		8
+#define NPHY_TBL_ID_ANTSWCTRLLUT	9
+#define NPHY_TBL_ID_IQLOCAL		15
+#define NPHY_TBL_ID_NOISEVAR		16
+#define NPHY_TBL_ID_SAMPLEPLAY		17
+#define NPHY_TBL_ID_CORE1TXPWRCTL	26
+#define NPHY_TBL_ID_CORE2TXPWRCTL	27
+#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL	30
+
+#define NPHY_TBL_ID_EPSILONTBL0   31
+#define NPHY_TBL_ID_SCALARTBL0    32
+#define NPHY_TBL_ID_EPSILONTBL1   33
+#define NPHY_TBL_ID_SCALARTBL1    34
+
+#define	NPHY_TO_BPHY_OFF	0xc00
+
+#define NPHY_BandControl_currentBand			0x0001
+#define RFCC_CHIP0_PU			0x0400
+#define RFCC_POR_FORCE			0x0040
+#define RFCC_OE_POR_FORCE		0x0080
+#define NPHY_RfctrlIntc_override_OFF			0
+#define NPHY_RfctrlIntc_override_TRSW			1
+#define NPHY_RfctrlIntc_override_PA				2
+#define NPHY_RfctrlIntc_override_EXT_LNA_PU		3
+#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN	4
+#define RIFS_ENABLE			0x80
+#define BPHY_BAND_SEL_UP20		0x10
+#define NPHY_MLenable			0x02
+
+#define NPHY_RfseqMode_CoreActv_override 0x0001
+#define NPHY_RfseqMode_Trigger_override	0x0002
+#define NPHY_RfseqCoreActv_TxRxChain0	(0x11)
+#define NPHY_RfseqCoreActv_TxRxChain1	(0x22)
+
+#define NPHY_RfseqTrigger_rx2tx		0x0001
+#define NPHY_RfseqTrigger_tx2rx		0x0002
+#define NPHY_RfseqTrigger_updategainh	0x0004
+#define NPHY_RfseqTrigger_updategainl	0x0008
+#define NPHY_RfseqTrigger_updategainu	0x0010
+#define NPHY_RfseqTrigger_reset2rx	0x0020
+#define NPHY_RfseqStatus_rx2tx		0x0001
+#define NPHY_RfseqStatus_tx2rx		0x0002
+#define NPHY_RfseqStatus_updategainh	0x0004
+#define NPHY_RfseqStatus_updategainl	0x0008
+#define NPHY_RfseqStatus_updategainu	0x0010
+#define NPHY_RfseqStatus_reset2rx	0x0020
+#define NPHY_ClassifierCtrl_cck_en	0x1
+#define NPHY_ClassifierCtrl_ofdm_en	0x2
+#define NPHY_ClassifierCtrl_waited_en	0x4
+#define NPHY_IQFlip_ADC1		0x0001
+#define NPHY_IQFlip_ADC2		0x0010
+#define NPHY_sampleCmd_STOP		0x0002
+
+#define RX_GF_OR_MM			0x0004
+#define RX_GF_MM_AUTO			0x0100
+
+#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN	0x8000
+
+#define NPHY_IqestCmd_iqstart		0x1
+#define NPHY_IqestCmd_iqMode		0x2
+
+#define NPHY_TxPwrCtrlCmd_pwrIndex_init		0x40
+#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7	0x19
+
+#define PRIM_SEL_UP20		0x8000
+
+#define NPHY_RFSEQ_RX2TX		0x0
+#define NPHY_RFSEQ_TX2RX		0x1
+#define NPHY_RFSEQ_RESET2RX		0x2
+#define NPHY_RFSEQ_UPDATEGAINH		0x3
+#define NPHY_RFSEQ_UPDATEGAINL		0x4
+#define NPHY_RFSEQ_UPDATEGAINU		0x5
+
+#define NPHY_RFSEQ_CMD_NOP		0x0
+#define NPHY_RFSEQ_CMD_RXG_FBW		0x1
+#define NPHY_RFSEQ_CMD_TR_SWITCH	0x2
+#define NPHY_RFSEQ_CMD_EXT_PA		0x3
+#define NPHY_RFSEQ_CMD_RXPD_TXPD	0x4
+#define NPHY_RFSEQ_CMD_TX_GAIN		0x5
+#define NPHY_RFSEQ_CMD_RX_GAIN		0x6
+#define NPHY_RFSEQ_CMD_SET_HPF_BW	0x7
+#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS	0x8
+#define NPHY_RFSEQ_CMD_END		0xf
+
+#define NPHY_REV3_RFSEQ_CMD_NOP		0x0
+#define NPHY_REV3_RFSEQ_CMD_RXG_FBW	0x1
+#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH	0x2
+#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU	0x3
+#define NPHY_REV3_RFSEQ_CMD_EXT_PA	0x4
+#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD	0x5
+#define NPHY_REV3_RFSEQ_CMD_TX_GAIN	0x6
+#define NPHY_REV3_RFSEQ_CMD_RX_GAIN	0x7
+#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS	0x8
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC	0x9
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC	0xa
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC	0xb
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC	0xc
+#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC	0xd
+#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC	0xe
+#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS	0xf
+#define NPHY_REV3_RFSEQ_CMD_END		0x1f
+
+#define NPHY_RSSI_SEL_W1 		0x0
+#define NPHY_RSSI_SEL_W2 		0x1
+#define NPHY_RSSI_SEL_NB 		0x2
+#define NPHY_RSSI_SEL_IQ 		0x3
+#define NPHY_RSSI_SEL_TSSI_2G 		0x4
+#define NPHY_RSSI_SEL_TSSI_5G 		0x5
+#define NPHY_RSSI_SEL_TBD 		0x6
+
+#define NPHY_RAIL_I			0x0
+#define NPHY_RAIL_Q			0x1
+
+#define NPHY_FORCESIG_DECODEGATEDCLKS	0x8
+
+#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
+#define NPHY_REV7_RfctrlOverride_cmd_rx_pu   0x1
+#define NPHY_REV7_RfctrlOverride_cmd_tx_pu   0x2
+#define NPHY_REV7_RfctrlOverride_cmd_rxgain  0x3
+#define NPHY_REV7_RfctrlOverride_cmd_txgain  0x4
+
+#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
+#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK  0x0ff00
+#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
+
+#define NPHY_REV7_TXGAINCODE_TGAIN_MASK     0x7fff
+#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK   0x8000
+#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
+
+#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
+#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
+#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
+
+#define NPHY_IqestIqAccLo(core)  ((core == 0) ? 0x12c : 0x134)
+
+#define NPHY_IqestIqAccHi(core)  ((core == 0) ? 0x12d : 0x135)
+
+#define NPHY_IqestipwrAccLo(core)  ((core == 0) ? 0x12e : 0x136)
+
+#define NPHY_IqestipwrAccHi(core)  ((core == 0) ? 0x12f : 0x137)
+
+#define NPHY_IqestqpwrAccLo(core)  ((core == 0) ? 0x130 : 0x138)
+
+#define NPHY_IqestqpwrAccHi(core)  ((core == 0) ? 0x131 : 0x139)
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c
new file mode 100644
index 0000000..81c59b0
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.c
@@ -0,0 +1,3639 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <sbhnddma.h>
+#include <wlc_phy_int.h>
+#include <wlc_phytbl_lcn.h>
+
+const u32 dot11lcn_gain_tbl_rev0[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000004,
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x000000cd,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x000000d3,
+	0x00000113,
+	0x00000513,
+	0x00000913,
+	0x00000953,
+	0x00000d53,
+	0x00001153,
+	0x00001193,
+	0x00005193,
+	0x00009193,
+	0x0000d193,
+	0x00011193,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000004,
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x000000cd,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x000000d3,
+	0x00000113,
+	0x00000513,
+	0x00000913,
+	0x00000953,
+	0x00000d53,
+	0x00001153,
+	0x00005153,
+	0x00009153,
+	0x0000d153,
+	0x00011153,
+	0x00015153,
+	0x00019153,
+	0x0001d153,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 dot11lcn_gain_tbl_rev1[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000D,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x000000d1,
+	0x00000053,
+	0x00000093,
+	0x000000d3,
+	0x000000d7,
+	0x00000117,
+	0x00000517,
+	0x00000917,
+	0x00000957,
+	0x00000d57,
+	0x00001157,
+	0x00001197,
+	0x00005197,
+	0x00009197,
+	0x0000d197,
+	0x00011197,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000D,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x00000011,
+	0x00000051,
+	0x00000091,
+	0x000000d1,
+	0x00000053,
+	0x00000093,
+	0x000000d3,
+	0x000000d7,
+	0x00000117,
+	0x00000517,
+	0x00000917,
+	0x00000957,
+	0x00000d57,
+	0x00001157,
+	0x00005157,
+	0x00009157,
+	0x0000d157,
+	0x00011157,
+	0x00015157,
+	0x00019157,
+	0x0001d157,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
+	0x0401,
+	0x0402,
+	0x0403,
+	0x0404,
+	0x0405,
+	0x0406,
+	0x0407,
+	0x0408,
+	0x0409,
+	0x040a,
+	0x058b,
+	0x058c,
+	0x058d,
+	0x058e,
+	0x058f,
+	0x0090,
+	0x0091,
+	0x0092,
+	0x0193,
+	0x0194,
+	0x0195,
+	0x0196,
+	0x0197,
+	0x0198,
+	0x0199,
+	0x019a,
+	0x019b,
+	0x019c,
+	0x019d,
+	0x019e,
+	0x019f,
+	0x01a0,
+	0x01a1,
+	0x01a2,
+	0x01a3,
+	0x01a4,
+	0x01a5,
+	0x0000,
+};
+
+const u32 dot11lcn_gain_idx_tbl_rev0[] = {
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x20000000,
+	0x00000000,
+	0x30000000,
+	0x00000000,
+	0x40000000,
+	0x00000000,
+	0x50000000,
+	0x00000000,
+	0x60000000,
+	0x00000000,
+	0x70000000,
+	0x00000000,
+	0x80000000,
+	0x00000000,
+	0x90000000,
+	0x00000008,
+	0xa0000000,
+	0x00000008,
+	0xb0000000,
+	0x00000008,
+	0xc0000000,
+	0x00000008,
+	0xd0000000,
+	0x00000008,
+	0xe0000000,
+	0x00000008,
+	0xf0000000,
+	0x00000008,
+	0x00000000,
+	0x00000009,
+	0x10000000,
+	0x00000009,
+	0x20000000,
+	0x00000019,
+	0x30000000,
+	0x00000019,
+	0x40000000,
+	0x00000019,
+	0x50000000,
+	0x00000019,
+	0x60000000,
+	0x00000019,
+	0x70000000,
+	0x00000019,
+	0x80000000,
+	0x00000019,
+	0x90000000,
+	0x00000019,
+	0xa0000000,
+	0x00000019,
+	0xb0000000,
+	0x00000019,
+	0xc0000000,
+	0x00000019,
+	0xd0000000,
+	0x00000019,
+	0xe0000000,
+	0x00000019,
+	0xf0000000,
+	0x00000019,
+	0x00000000,
+	0x0000001a,
+	0x10000000,
+	0x0000001a,
+	0x20000000,
+	0x0000001a,
+	0x30000000,
+	0x0000001a,
+	0x40000000,
+	0x0000001a,
+	0x50000000,
+	0x00000002,
+	0x60000000,
+	0x00000002,
+	0x70000000,
+	0x00000002,
+	0x80000000,
+	0x00000002,
+	0x90000000,
+	0x00000002,
+	0xa0000000,
+	0x00000002,
+	0xb0000000,
+	0x00000002,
+	0xc0000000,
+	0x0000000a,
+	0xd0000000,
+	0x0000000a,
+	0xe0000000,
+	0x0000000a,
+	0xf0000000,
+	0x0000000a,
+	0x00000000,
+	0x0000000b,
+	0x10000000,
+	0x0000000b,
+	0x20000000,
+	0x0000000b,
+	0x30000000,
+	0x0000000b,
+	0x40000000,
+	0x0000000b,
+	0x50000000,
+	0x0000001b,
+	0x60000000,
+	0x0000001b,
+	0x70000000,
+	0x0000001b,
+	0x80000000,
+	0x0000001b,
+	0x90000000,
+	0x0000001b,
+	0xa0000000,
+	0x0000001b,
+	0xb0000000,
+	0x0000001b,
+	0xc0000000,
+	0x0000001b,
+	0xd0000000,
+	0x0000001b,
+	0xe0000000,
+	0x0000001b,
+	0xf0000000,
+	0x0000001b,
+	0x00000000,
+	0x0000001c,
+	0x10000000,
+	0x0000001c,
+	0x20000000,
+	0x0000001c,
+	0x30000000,
+	0x0000001c,
+	0x40000000,
+	0x0000001c,
+	0x50000000,
+	0x0000001c,
+	0x60000000,
+	0x0000001c,
+	0x70000000,
+	0x0000001c,
+	0x80000000,
+	0x0000001c,
+	0x90000000,
+	0x0000001c,
+};
+
+const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0001,
+	0x0080,
+	0x0081,
+	0x0100,
+	0x0101,
+	0x0180,
+	0x0181,
+	0x0182,
+	0x0183,
+	0x0184,
+	0x0185,
+	0x0186,
+	0x0187,
+	0x0188,
+	0x0285,
+	0x0289,
+	0x028a,
+	0x028b,
+	0x028c,
+	0x028d,
+	0x028e,
+	0x028f,
+	0x0290,
+	0x0291,
+	0x0292,
+	0x0293,
+	0x0294,
+	0x0295,
+	0x0296,
+	0x0297,
+	0x0298,
+	0x0299,
+	0x029a,
+	0x0000
+};
+
+const u8 dot11lcn_gain_val_tbl_2G[] = {
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x00,
+	0x0c,
+	0x03,
+	0xeb,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+const u32 dot11lcn_gain_idx_tbl_2G[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x10000000,
+	0x00000008,
+	0x00000000,
+	0x00000010,
+	0x10000000,
+	0x00000010,
+	0x00000000,
+	0x00000018,
+	0x10000000,
+	0x00000018,
+	0x20000000,
+	0x00000018,
+	0x30000000,
+	0x00000018,
+	0x40000000,
+	0x00000018,
+	0x50000000,
+	0x00000018,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x50000000,
+	0x00000028,
+	0x90000000,
+	0x00000028,
+	0xa0000000,
+	0x00000028,
+	0xb0000000,
+	0x00000028,
+	0xc0000000,
+	0x00000028,
+	0xd0000000,
+	0x00000028,
+	0xe0000000,
+	0x00000028,
+	0xf0000000,
+	0x00000028,
+	0x00000000,
+	0x00000029,
+	0x10000000,
+	0x00000029,
+	0x20000000,
+	0x00000029,
+	0x30000000,
+	0x00000029,
+	0x40000000,
+	0x00000029,
+	0x50000000,
+	0x00000029,
+	0x60000000,
+	0x00000029,
+	0x70000000,
+	0x00000029,
+	0x80000000,
+	0x00000029,
+	0x90000000,
+	0x00000029,
+	0xa0000000,
+	0x00000029,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x00000000,
+	0x00000008,
+	0x10000000,
+	0x00000008,
+	0x00000000,
+	0x00000010,
+	0x10000000,
+	0x00000010,
+	0x00000000,
+	0x00000018,
+	0x10000000,
+	0x00000018,
+	0x20000000,
+	0x00000018,
+	0x30000000,
+	0x00000018,
+	0x40000000,
+	0x00000018,
+	0x50000000,
+	0x00000018,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x50000000,
+	0x00000028,
+	0x90000000,
+	0x00000028,
+	0xa0000000,
+	0x00000028,
+	0xb0000000,
+	0x00000028,
+	0xc0000000,
+	0x00000028,
+	0xd0000000,
+	0x00000028,
+	0xe0000000,
+	0x00000028,
+	0xf0000000,
+	0x00000028,
+	0x00000000,
+	0x00000029,
+	0x10000000,
+	0x00000029,
+	0x20000000,
+	0x00000029,
+	0x30000000,
+	0x00000029,
+	0x40000000,
+	0x00000029,
+	0x50000000,
+	0x00000029,
+	0x60000000,
+	0x00000029,
+	0x70000000,
+	0x00000029,
+	0x80000000,
+	0x00000029,
+	0x90000000,
+	0x00000029,
+	0xa0000000,
+	0x00000029,
+	0xb0000000,
+	0x00000029,
+	0xc0000000,
+	0x00000029,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_gain_tbl_2G[] = {
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x0000004d,
+	0x0000008d,
+	0x00000049,
+	0x00000089,
+	0x000000c9,
+	0x0000004b,
+	0x0000008b,
+	0x000000cb,
+	0x000000cf,
+	0x0000010f,
+	0x0000050f,
+	0x0000090f,
+	0x0000094f,
+	0x00000d4f,
+	0x0000114f,
+	0x0000118f,
+	0x0000518f,
+	0x0000918f,
+	0x0000d18f,
+	0x0001118f,
+	0x0001518f,
+	0x0001918f,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_gain_tbl_extlna_2G[] = {
+	0x00000000,
+	0x00000004,
+	0x00000008,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x00000003,
+	0x00000007,
+	0x0000000b,
+	0x0000000f,
+	0x0000004f,
+	0x0000008f,
+	0x000000cf,
+	0x0000010f,
+	0x0000014f,
+	0x0000018f,
+	0x0000058f,
+	0x0000098f,
+	0x00000d8f,
+	0x00008000,
+	0x00008004,
+	0x00008008,
+	0x00008001,
+	0x00008005,
+	0x00008009,
+	0x0000800d,
+	0x00008003,
+	0x00008007,
+	0x0000800b,
+	0x0000800f,
+	0x0000804f,
+	0x0000808f,
+	0x000080cf,
+	0x0000810f,
+	0x0000814f,
+	0x0000818f,
+	0x0000858f,
+	0x0000898f,
+	0x00008d8f,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0400,
+	0x0401,
+	0x0402,
+	0x0403,
+	0x0404,
+	0x0483,
+	0x0484,
+	0x0485,
+	0x0486,
+	0x0583,
+	0x0584,
+	0x0585,
+	0x0587,
+	0x0588,
+	0x0589,
+	0x058a,
+	0x0687,
+	0x0688,
+	0x0689,
+	0x068a,
+	0x068b,
+	0x068c,
+	0x068d,
+	0x068e,
+	0x068f,
+	0x0690,
+	0x0691,
+	0x0692,
+	0x0693,
+	0x0000
+};
+
+const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x02,
+	0x08,
+	0x0e,
+	0x13,
+	0x1b,
+	0xfc,
+	0x00,
+	0x0f,
+	0x03,
+	0xeb,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x00000000,
+	0x00000040,
+	0x10000000,
+	0x00000040,
+	0x20000000,
+	0x00000040,
+	0x30000000,
+	0x00000040,
+	0x40000000,
+	0x00000040,
+	0x30000000,
+	0x00000048,
+	0x40000000,
+	0x00000048,
+	0x50000000,
+	0x00000048,
+	0x60000000,
+	0x00000048,
+	0x30000000,
+	0x00000058,
+	0x40000000,
+	0x00000058,
+	0x50000000,
+	0x00000058,
+	0x70000000,
+	0x00000058,
+	0x80000000,
+	0x00000058,
+	0x90000000,
+	0x00000058,
+	0xa0000000,
+	0x00000058,
+	0x70000000,
+	0x00000068,
+	0x80000000,
+	0x00000068,
+	0x90000000,
+	0x00000068,
+	0xa0000000,
+	0x00000068,
+	0xb0000000,
+	0x00000068,
+	0xc0000000,
+	0x00000068,
+	0xd0000000,
+	0x00000068,
+	0xe0000000,
+	0x00000068,
+	0xf0000000,
+	0x00000068,
+	0x00000000,
+	0x00000069,
+	0x10000000,
+	0x00000069,
+	0x20000000,
+	0x00000069,
+	0x30000000,
+	0x00000069,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x40000000,
+	0x00000041,
+	0x50000000,
+	0x00000041,
+	0x60000000,
+	0x00000041,
+	0x70000000,
+	0x00000041,
+	0x80000000,
+	0x00000041,
+	0x70000000,
+	0x00000049,
+	0x80000000,
+	0x00000049,
+	0x90000000,
+	0x00000049,
+	0xa0000000,
+	0x00000049,
+	0x70000000,
+	0x00000059,
+	0x80000000,
+	0x00000059,
+	0x90000000,
+	0x00000059,
+	0xb0000000,
+	0x00000059,
+	0xc0000000,
+	0x00000059,
+	0xd0000000,
+	0x00000059,
+	0xe0000000,
+	0x00000059,
+	0xb0000000,
+	0x00000069,
+	0xc0000000,
+	0x00000069,
+	0xd0000000,
+	0x00000069,
+	0xe0000000,
+	0x00000069,
+	0xf0000000,
+	0x00000069,
+	0x00000000,
+	0x0000006a,
+	0x10000000,
+	0x0000006a,
+	0x20000000,
+	0x0000006a,
+	0x30000000,
+	0x0000006a,
+	0x40000000,
+	0x0000006a,
+	0x50000000,
+	0x0000006a,
+	0x60000000,
+	0x0000006a,
+	0x70000000,
+	0x0000006a,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0001,
+	0x0002,
+	0x0003,
+	0x0004,
+	0x0083,
+	0x0084,
+	0x0085,
+	0x0086,
+	0x0087,
+	0x0186,
+	0x0187,
+	0x0188,
+	0x0189,
+	0x018a,
+	0x018b,
+	0x018c,
+	0x018d,
+	0x018e,
+	0x018f,
+	0x0190,
+	0x0191,
+	0x0192,
+	0x0193,
+	0x0194,
+	0x0195,
+	0x0196,
+	0x0197,
+	0x0198,
+	0x0199,
+	0x019a,
+	0x019b,
+	0x019c,
+	0x019d,
+	0x0000
+};
+
+const u32 dot11lcn_gain_val_tbl_5G[] = {
+	0xf7,
+	0xfd,
+	0x00,
+	0x04,
+	0x04,
+	0x04,
+	0xf7,
+	0xfd,
+	0x00,
+	0x04,
+	0x04,
+	0x04,
+	0xf6,
+	0x00,
+	0x0c,
+	0x03,
+	0xeb,
+	0xfe,
+	0x06,
+	0x0a,
+	0x10,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00
+};
+
+const u32 dot11lcn_gain_idx_tbl_5G[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x10000000,
+	0x00000000,
+	0x20000000,
+	0x00000000,
+	0x30000000,
+	0x00000000,
+	0x40000000,
+	0x00000000,
+	0x30000000,
+	0x00000008,
+	0x40000000,
+	0x00000008,
+	0x50000000,
+	0x00000008,
+	0x60000000,
+	0x00000008,
+	0x70000000,
+	0x00000008,
+	0x60000000,
+	0x00000018,
+	0x70000000,
+	0x00000018,
+	0x80000000,
+	0x00000018,
+	0x90000000,
+	0x00000018,
+	0xa0000000,
+	0x00000018,
+	0xb0000000,
+	0x00000018,
+	0xc0000000,
+	0x00000018,
+	0xd0000000,
+	0x00000018,
+	0xe0000000,
+	0x00000018,
+	0xf0000000,
+	0x00000018,
+	0x00000000,
+	0x00000019,
+	0x10000000,
+	0x00000019,
+	0x20000000,
+	0x00000019,
+	0x30000000,
+	0x00000019,
+	0x40000000,
+	0x00000019,
+	0x50000000,
+	0x00000019,
+	0x60000000,
+	0x00000019,
+	0x70000000,
+	0x00000019,
+	0x80000000,
+	0x00000019,
+	0x90000000,
+	0x00000019,
+	0xa0000000,
+	0x00000019,
+	0xb0000000,
+	0x00000019,
+	0xc0000000,
+	0x00000019,
+	0xd0000000,
+	0x00000019,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const u32 dot11lcn_gain_tbl_5G[] = {
+	0x00000000,
+	0x00000040,
+	0x00000080,
+	0x00000001,
+	0x00000005,
+	0x00000009,
+	0x0000000d,
+	0x00000011,
+	0x00000015,
+	0x00000055,
+	0x00000095,
+	0x00000017,
+	0x0000001b,
+	0x0000005b,
+	0x0000009b,
+	0x000000db,
+	0x0000011b,
+	0x0000015b,
+	0x0000019b,
+	0x0000059b,
+	0x0000099b,
+	0x00000d9b,
+	0x0000119b,
+	0x0000519b,
+	0x0000919b,
+	0x0000d19b,
+	0x0001119b,
+	0x0001519b,
+	0x0001919b,
+	0x0001d19b,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev0[] = {
+	{&dot11lcn_gain_tbl_rev0,
+	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
+	 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
+	,
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[] = {
+	{&dot11lcn_gain_tbl_rev1,
+	 sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18,
+	 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
+	,
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_2G_rev2[] = {
+	{&dot11lcn_gain_tbl_2G,
+	 sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_2G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_2G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_2G,
+	 sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_2G,
+	 sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]),
+	 17, 0, 8}
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_5G_rev2[] = {
+	{&dot11lcn_gain_tbl_5G,
+	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_5G,
+	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
+	 17, 0, 8}
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = {
+	{&dot11lcn_gain_tbl_extlna_2G,
+	 sizeof(dot11lcn_gain_tbl_extlna_2G) /
+	 sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_extlna_2G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_extlna_2G,
+	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G) /
+	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_extlna_2G,
+	 sizeof(dot11lcn_gain_val_tbl_extlna_2G) /
+	 sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8}
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = {
+	{&dot11lcn_gain_tbl_5G,
+	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
+	 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
+	,
+	{&dot11lcn_gain_idx_tbl_5G,
+	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
+	 13, 0, 32}
+	,
+	{&dot11lcn_gain_val_tbl_5G,
+	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
+	 17, 0, 8}
+};
+
+const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
+    sizeof(dot11lcnphytbl_rx_gain_info_rev0) /
+    sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]);
+
+const u32 dot11lcnphytbl_rx_gain_info_sz_rev1 =
+    sizeof(dot11lcnphytbl_rx_gain_info_rev1) /
+    sizeof(dot11lcnphytbl_rx_gain_info_rev1[0]);
+
+const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
+    sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) /
+    sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]);
+
+const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
+    sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) /
+    sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]);
+
+const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+	0x014d,
+};
+
+const u16 dot11lcn_noise_scale_tbl_rev0[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
+	0x000141f8,
+	0x000021f8,
+	0x000021fb,
+	0x000041fb,
+	0x0001fe4b,
+	0x0000217b,
+	0x00002133,
+	0x000040eb,
+	0x0001fea3,
+	0x0000024b,
+};
+
+const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
+	0x00100001,
+	0x00200010,
+	0x00300001,
+	0x00400010,
+	0x00500022,
+	0x00600122,
+	0x00700222,
+	0x00800322,
+	0x00900422,
+	0x00a00522,
+	0x00b00622,
+	0x00c00722,
+	0x00d00822,
+	0x00f00922,
+	0x00100a22,
+	0x00200b22,
+	0x00300c22,
+	0x00400d22,
+	0x00500e22,
+	0x00600f22,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x0007,
+	0x0005,
+	0x0006,
+	0x0004,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+	0x000b,
+	0x000b,
+	0x000a,
+	0x000a,
+
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0005,
+	0x0002,
+	0x0000,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+	0x0007,
+	0x0007,
+	0x0002,
+	0x0002,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+	0x0002,
+	0x0008,
+	0x0004,
+	0x0001,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+	0x000a,
+	0x0009,
+	0x0006,
+	0x0005,
+};
+
+const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+	0x0004,
+	0x0004,
+	0x0002,
+	0x0002,
+};
+
+const u8 dot11lcn_nf_table_rev0[] = {
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+	0x5f,
+	0x36,
+	0x29,
+	0x1f,
+};
+
+const u8 dot11lcn_gain_val_tbl_rev0[] = {
+	0x09,
+	0x0f,
+	0x14,
+	0x18,
+	0xfe,
+	0x07,
+	0x0b,
+	0x0f,
+	0xfb,
+	0xfe,
+	0x01,
+	0x05,
+	0x08,
+	0x0b,
+	0x0e,
+	0x11,
+	0x14,
+	0x17,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0x06,
+	0x09,
+	0x0c,
+	0x0f,
+	0x12,
+	0x15,
+	0x18,
+	0x1b,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x03,
+	0xeb,
+	0x00,
+	0x00,
+};
+
+const u8 dot11lcn_spur_tbl_rev0[] = {
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x02,
+	0x03,
+	0x01,
+	0x03,
+	0x02,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x02,
+	0x03,
+	0x01,
+	0x03,
+	0x02,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+	0x01,
+};
+
+const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
+	0x001a,
+	0x0034,
+	0x004e,
+	0x0068,
+	0x009c,
+	0x00d0,
+	0x00ea,
+	0x0104,
+	0x0034,
+	0x0068,
+	0x009c,
+	0x00d0,
+	0x0138,
+	0x01a0,
+	0x01d4,
+	0x0208,
+	0x004e,
+	0x009c,
+	0x00ea,
+	0x0138,
+	0x01d4,
+	0x0270,
+	0x02be,
+	0x030c,
+	0x0068,
+	0x00d0,
+	0x0138,
+	0x01a0,
+	0x0270,
+	0x0340,
+	0x03a8,
+	0x0410,
+	0x0018,
+	0x009c,
+	0x00d0,
+	0x0104,
+	0x00ea,
+	0x0138,
+	0x0186,
+	0x00d0,
+	0x0104,
+	0x0104,
+	0x0138,
+	0x016c,
+	0x016c,
+	0x01a0,
+	0x0138,
+	0x0186,
+	0x0186,
+	0x01d4,
+	0x0222,
+	0x0222,
+	0x0270,
+	0x0104,
+	0x0138,
+	0x016c,
+	0x0138,
+	0x016c,
+	0x01a0,
+	0x01d4,
+	0x01a0,
+	0x01d4,
+	0x0208,
+	0x0208,
+	0x023c,
+	0x0186,
+	0x01d4,
+	0x0222,
+	0x01d4,
+	0x0222,
+	0x0270,
+	0x02be,
+	0x0270,
+	0x02be,
+	0x030c,
+	0x030c,
+	0x035a,
+	0x0036,
+	0x006c,
+	0x00a2,
+	0x00d8,
+	0x0144,
+	0x01b0,
+	0x01e6,
+	0x021c,
+	0x006c,
+	0x00d8,
+	0x0144,
+	0x01b0,
+	0x0288,
+	0x0360,
+	0x03cc,
+	0x0438,
+	0x00a2,
+	0x0144,
+	0x01e6,
+	0x0288,
+	0x03cc,
+	0x0510,
+	0x05b2,
+	0x0654,
+	0x00d8,
+	0x01b0,
+	0x0288,
+	0x0360,
+	0x0510,
+	0x06c0,
+	0x0798,
+	0x0870,
+	0x0018,
+	0x0144,
+	0x01b0,
+	0x021c,
+	0x01e6,
+	0x0288,
+	0x032a,
+	0x01b0,
+	0x021c,
+	0x021c,
+	0x0288,
+	0x02f4,
+	0x02f4,
+	0x0360,
+	0x0288,
+	0x032a,
+	0x032a,
+	0x03cc,
+	0x046e,
+	0x046e,
+	0x0510,
+	0x021c,
+	0x0288,
+	0x02f4,
+	0x0288,
+	0x02f4,
+	0x0360,
+	0x03cc,
+	0x0360,
+	0x03cc,
+	0x0438,
+	0x0438,
+	0x04a4,
+	0x032a,
+	0x03cc,
+	0x046e,
+	0x03cc,
+	0x046e,
+	0x0510,
+	0x05b2,
+	0x0510,
+	0x05b2,
+	0x0654,
+	0x0654,
+	0x06f6,
+};
+
+const u16 dot11lcn_iq_local_tbl_rev0[] = {
+	0x0200,
+	0x0300,
+	0x0400,
+	0x0600,
+	0x0800,
+	0x0b00,
+	0x1000,
+	0x1001,
+	0x1002,
+	0x1003,
+	0x1004,
+	0x1005,
+	0x1006,
+	0x1007,
+	0x1707,
+	0x2007,
+	0x2d07,
+	0x4007,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0200,
+	0x0300,
+	0x0400,
+	0x0600,
+	0x0800,
+	0x0b00,
+	0x1000,
+	0x1001,
+	0x1002,
+	0x1003,
+	0x1004,
+	0x1005,
+	0x1006,
+	0x1007,
+	0x1707,
+	0x2007,
+	0x2d07,
+	0x4007,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x4000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+	0x00080000,
+};
+
+const dot11lcnphytbl_info_t dot11lcnphytbl_info_rev0[] = {
+	{&dot11lcn_min_sig_sq_tbl_rev0,
+	 sizeof(dot11lcn_min_sig_sq_tbl_rev0) /
+	 sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16}
+	,
+	{&dot11lcn_noise_scale_tbl_rev0,
+	 sizeof(dot11lcn_noise_scale_tbl_rev0) /
+	 sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16}
+	,
+	{&dot11lcn_fltr_ctrl_tbl_rev0,
+	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0) /
+	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32}
+	,
+	{&dot11lcn_ps_ctrl_tbl_rev0,
+	 sizeof(dot11lcn_ps_ctrl_tbl_rev0) /
+	 sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32}
+	,
+	{&dot11lcn_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
+	,
+	{&dot11lcn_aux_gain_idx_tbl_rev0,
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
+	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
+	,
+	{&dot11lcn_sw_ctrl_tbl_rev0,
+	 sizeof(dot11lcn_sw_ctrl_tbl_rev0) /
+	 sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16}
+	,
+	{&dot11lcn_nf_table_rev0,
+	 sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16,
+	 0, 8}
+	,
+	{&dot11lcn_gain_val_tbl_rev0,
+	 sizeof(dot11lcn_gain_val_tbl_rev0) /
+	 sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8}
+	,
+	{&dot11lcn_gain_tbl_rev0,
+	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
+	 0, 32}
+	,
+	{&dot11lcn_spur_tbl_rev0,
+	 sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20,
+	 0, 8}
+	,
+	{&dot11lcn_unsup_mcs_tbl_rev0,
+	 sizeof(dot11lcn_unsup_mcs_tbl_rev0) /
+	 sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16}
+	,
+	{&dot11lcn_iq_local_tbl_rev0,
+	 sizeof(dot11lcn_iq_local_tbl_rev0) /
+	 sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16}
+	,
+	{&dot11lcn_papd_compdelta_tbl_rev0,
+	 sizeof(dot11lcn_papd_compdelta_tbl_rev0) /
+	 sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32}
+	,
+};
+
+const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313 = {
+	&dot11lcn_sw_ctrl_tbl_4313_rev0,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
+};
+
+const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa = {
+	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
+};
+
+const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
+	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
+};
+
+const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
+	&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
+	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
+};
+
+const u32 dot11lcnphytbl_info_sz_rev0 =
+    sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]);
+
+const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
+	{3, 0, 31, 0, 72,}
+	,
+	{3, 0, 31, 0, 70,}
+	,
+	{3, 0, 31, 0, 68,}
+	,
+	{3, 0, 30, 0, 67,}
+	,
+	{3, 0, 29, 0, 68,}
+	,
+	{3, 0, 28, 0, 68,}
+	,
+	{3, 0, 27, 0, 69,}
+	,
+	{3, 0, 26, 0, 70,}
+	,
+	{3, 0, 25, 0, 70,}
+	,
+	{3, 0, 24, 0, 71,}
+	,
+	{3, 0, 23, 0, 72,}
+	,
+	{3, 0, 23, 0, 70,}
+	,
+	{3, 0, 22, 0, 71,}
+	,
+	{3, 0, 21, 0, 72,}
+	,
+	{3, 0, 21, 0, 70,}
+	,
+	{3, 0, 21, 0, 68,}
+	,
+	{3, 0, 21, 0, 66,}
+	,
+	{3, 0, 21, 0, 64,}
+	,
+	{3, 0, 21, 0, 63,}
+	,
+	{3, 0, 20, 0, 64,}
+	,
+	{3, 0, 19, 0, 65,}
+	,
+	{3, 0, 19, 0, 64,}
+	,
+	{3, 0, 18, 0, 65,}
+	,
+	{3, 0, 18, 0, 64,}
+	,
+	{3, 0, 17, 0, 65,}
+	,
+	{3, 0, 17, 0, 64,}
+	,
+	{3, 0, 16, 0, 65,}
+	,
+	{3, 0, 16, 0, 64,}
+	,
+	{3, 0, 16, 0, 62,}
+	,
+	{3, 0, 16, 0, 60,}
+	,
+	{3, 0, 16, 0, 58,}
+	,
+	{3, 0, 15, 0, 61,}
+	,
+	{3, 0, 15, 0, 59,}
+	,
+	{3, 0, 14, 0, 61,}
+	,
+	{3, 0, 14, 0, 60,}
+	,
+	{3, 0, 14, 0, 58,}
+	,
+	{3, 0, 13, 0, 60,}
+	,
+	{3, 0, 13, 0, 59,}
+	,
+	{3, 0, 12, 0, 62,}
+	,
+	{3, 0, 12, 0, 60,}
+	,
+	{3, 0, 12, 0, 58,}
+	,
+	{3, 0, 11, 0, 62,}
+	,
+	{3, 0, 11, 0, 60,}
+	,
+	{3, 0, 11, 0, 59,}
+	,
+	{3, 0, 11, 0, 57,}
+	,
+	{3, 0, 10, 0, 61,}
+	,
+	{3, 0, 10, 0, 59,}
+	,
+	{3, 0, 10, 0, 57,}
+	,
+	{3, 0, 9, 0, 62,}
+	,
+	{3, 0, 9, 0, 60,}
+	,
+	{3, 0, 9, 0, 58,}
+	,
+	{3, 0, 9, 0, 57,}
+	,
+	{3, 0, 8, 0, 62,}
+	,
+	{3, 0, 8, 0, 60,}
+	,
+	{3, 0, 8, 0, 58,}
+	,
+	{3, 0, 8, 0, 57,}
+	,
+	{3, 0, 8, 0, 55,}
+	,
+	{3, 0, 7, 0, 61,}
+	,
+	{3, 0, 7, 0, 60,}
+	,
+	{3, 0, 7, 0, 58,}
+	,
+	{3, 0, 7, 0, 56,}
+	,
+	{3, 0, 7, 0, 55,}
+	,
+	{3, 0, 6, 0, 62,}
+	,
+	{3, 0, 6, 0, 60,}
+	,
+	{3, 0, 6, 0, 58,}
+	,
+	{3, 0, 6, 0, 57,}
+	,
+	{3, 0, 6, 0, 55,}
+	,
+	{3, 0, 6, 0, 54,}
+	,
+	{3, 0, 6, 0, 52,}
+	,
+	{3, 0, 5, 0, 61,}
+	,
+	{3, 0, 5, 0, 59,}
+	,
+	{3, 0, 5, 0, 57,}
+	,
+	{3, 0, 5, 0, 56,}
+	,
+	{3, 0, 5, 0, 54,}
+	,
+	{3, 0, 5, 0, 53,}
+	,
+	{3, 0, 5, 0, 51,}
+	,
+	{3, 0, 4, 0, 62,}
+	,
+	{3, 0, 4, 0, 60,}
+	,
+	{3, 0, 4, 0, 58,}
+	,
+	{3, 0, 4, 0, 57,}
+	,
+	{3, 0, 4, 0, 55,}
+	,
+	{3, 0, 4, 0, 54,}
+	,
+	{3, 0, 4, 0, 52,}
+	,
+	{3, 0, 4, 0, 51,}
+	,
+	{3, 0, 4, 0, 49,}
+	,
+	{3, 0, 4, 0, 48,}
+	,
+	{3, 0, 4, 0, 46,}
+	,
+	{3, 0, 3, 0, 60,}
+	,
+	{3, 0, 3, 0, 58,}
+	,
+	{3, 0, 3, 0, 57,}
+	,
+	{3, 0, 3, 0, 55,}
+	,
+	{3, 0, 3, 0, 54,}
+	,
+	{3, 0, 3, 0, 52,}
+	,
+	{3, 0, 3, 0, 51,}
+	,
+	{3, 0, 3, 0, 49,}
+	,
+	{3, 0, 3, 0, 48,}
+	,
+	{3, 0, 3, 0, 46,}
+	,
+	{3, 0, 3, 0, 45,}
+	,
+	{3, 0, 3, 0, 44,}
+	,
+	{3, 0, 3, 0, 43,}
+	,
+	{3, 0, 3, 0, 41,}
+	,
+	{3, 0, 2, 0, 61,}
+	,
+	{3, 0, 2, 0, 59,}
+	,
+	{3, 0, 2, 0, 57,}
+	,
+	{3, 0, 2, 0, 56,}
+	,
+	{3, 0, 2, 0, 54,}
+	,
+	{3, 0, 2, 0, 53,}
+	,
+	{3, 0, 2, 0, 51,}
+	,
+	{3, 0, 2, 0, 50,}
+	,
+	{3, 0, 2, 0, 48,}
+	,
+	{3, 0, 2, 0, 47,}
+	,
+	{3, 0, 2, 0, 46,}
+	,
+	{3, 0, 2, 0, 44,}
+	,
+	{3, 0, 2, 0, 43,}
+	,
+	{3, 0, 2, 0, 42,}
+	,
+	{3, 0, 2, 0, 41,}
+	,
+	{3, 0, 2, 0, 39,}
+	,
+	{3, 0, 2, 0, 38,}
+	,
+	{3, 0, 2, 0, 37,}
+	,
+	{3, 0, 2, 0, 36,}
+	,
+	{3, 0, 2, 0, 35,}
+	,
+	{3, 0, 2, 0, 34,}
+	,
+	{3, 0, 2, 0, 33,}
+	,
+	{3, 0, 2, 0, 32,}
+	,
+	{3, 0, 1, 0, 63,}
+	,
+	{3, 0, 1, 0, 61,}
+	,
+	{3, 0, 1, 0, 59,}
+	,
+	{3, 0, 1, 0, 57,}
+	,
+};
+
+const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
+	{7, 0, 31, 0, 72,}
+	,
+	{7, 0, 31, 0, 70,}
+	,
+	{7, 0, 31, 0, 68,}
+	,
+	{7, 0, 30, 0, 67,}
+	,
+	{7, 0, 29, 0, 68,}
+	,
+	{7, 0, 28, 0, 68,}
+	,
+	{7, 0, 27, 0, 69,}
+	,
+	{7, 0, 26, 0, 70,}
+	,
+	{7, 0, 25, 0, 70,}
+	,
+	{7, 0, 24, 0, 71,}
+	,
+	{7, 0, 23, 0, 72,}
+	,
+	{7, 0, 23, 0, 70,}
+	,
+	{7, 0, 22, 0, 71,}
+	,
+	{7, 0, 21, 0, 72,}
+	,
+	{7, 0, 21, 0, 70,}
+	,
+	{7, 0, 21, 0, 68,}
+	,
+	{7, 0, 21, 0, 66,}
+	,
+	{7, 0, 21, 0, 64,}
+	,
+	{7, 0, 21, 0, 63,}
+	,
+	{7, 0, 20, 0, 64,}
+	,
+	{7, 0, 19, 0, 65,}
+	,
+	{7, 0, 19, 0, 64,}
+	,
+	{7, 0, 18, 0, 65,}
+	,
+	{7, 0, 18, 0, 64,}
+	,
+	{7, 0, 17, 0, 65,}
+	,
+	{7, 0, 17, 0, 64,}
+	,
+	{7, 0, 16, 0, 65,}
+	,
+	{7, 0, 16, 0, 64,}
+	,
+	{7, 0, 16, 0, 62,}
+	,
+	{7, 0, 16, 0, 60,}
+	,
+	{7, 0, 16, 0, 58,}
+	,
+	{7, 0, 15, 0, 61,}
+	,
+	{7, 0, 15, 0, 59,}
+	,
+	{7, 0, 14, 0, 61,}
+	,
+	{7, 0, 14, 0, 60,}
+	,
+	{7, 0, 14, 0, 58,}
+	,
+	{7, 0, 13, 0, 60,}
+	,
+	{7, 0, 13, 0, 59,}
+	,
+	{7, 0, 12, 0, 62,}
+	,
+	{7, 0, 12, 0, 60,}
+	,
+	{7, 0, 12, 0, 58,}
+	,
+	{7, 0, 11, 0, 62,}
+	,
+	{7, 0, 11, 0, 60,}
+	,
+	{7, 0, 11, 0, 59,}
+	,
+	{7, 0, 11, 0, 57,}
+	,
+	{7, 0, 10, 0, 61,}
+	,
+	{7, 0, 10, 0, 59,}
+	,
+	{7, 0, 10, 0, 57,}
+	,
+	{7, 0, 9, 0, 62,}
+	,
+	{7, 0, 9, 0, 60,}
+	,
+	{7, 0, 9, 0, 58,}
+	,
+	{7, 0, 9, 0, 57,}
+	,
+	{7, 0, 8, 0, 62,}
+	,
+	{7, 0, 8, 0, 60,}
+	,
+	{7, 0, 8, 0, 58,}
+	,
+	{7, 0, 8, 0, 57,}
+	,
+	{7, 0, 8, 0, 55,}
+	,
+	{7, 0, 7, 0, 61,}
+	,
+	{7, 0, 7, 0, 60,}
+	,
+	{7, 0, 7, 0, 58,}
+	,
+	{7, 0, 7, 0, 56,}
+	,
+	{7, 0, 7, 0, 55,}
+	,
+	{7, 0, 6, 0, 62,}
+	,
+	{7, 0, 6, 0, 60,}
+	,
+	{7, 0, 6, 0, 58,}
+	,
+	{7, 0, 6, 0, 57,}
+	,
+	{7, 0, 6, 0, 55,}
+	,
+	{7, 0, 6, 0, 54,}
+	,
+	{7, 0, 6, 0, 52,}
+	,
+	{7, 0, 5, 0, 61,}
+	,
+	{7, 0, 5, 0, 59,}
+	,
+	{7, 0, 5, 0, 57,}
+	,
+	{7, 0, 5, 0, 56,}
+	,
+	{7, 0, 5, 0, 54,}
+	,
+	{7, 0, 5, 0, 53,}
+	,
+	{7, 0, 5, 0, 51,}
+	,
+	{7, 0, 4, 0, 62,}
+	,
+	{7, 0, 4, 0, 60,}
+	,
+	{7, 0, 4, 0, 58,}
+	,
+	{7, 0, 4, 0, 57,}
+	,
+	{7, 0, 4, 0, 55,}
+	,
+	{7, 0, 4, 0, 54,}
+	,
+	{7, 0, 4, 0, 52,}
+	,
+	{7, 0, 4, 0, 51,}
+	,
+	{7, 0, 4, 0, 49,}
+	,
+	{7, 0, 4, 0, 48,}
+	,
+	{7, 0, 4, 0, 46,}
+	,
+	{7, 0, 3, 0, 60,}
+	,
+	{7, 0, 3, 0, 58,}
+	,
+	{7, 0, 3, 0, 57,}
+	,
+	{7, 0, 3, 0, 55,}
+	,
+	{7, 0, 3, 0, 54,}
+	,
+	{7, 0, 3, 0, 52,}
+	,
+	{7, 0, 3, 0, 51,}
+	,
+	{7, 0, 3, 0, 49,}
+	,
+	{7, 0, 3, 0, 48,}
+	,
+	{7, 0, 3, 0, 46,}
+	,
+	{7, 0, 3, 0, 45,}
+	,
+	{7, 0, 3, 0, 44,}
+	,
+	{7, 0, 3, 0, 43,}
+	,
+	{7, 0, 3, 0, 41,}
+	,
+	{7, 0, 2, 0, 61,}
+	,
+	{7, 0, 2, 0, 59,}
+	,
+	{7, 0, 2, 0, 57,}
+	,
+	{7, 0, 2, 0, 56,}
+	,
+	{7, 0, 2, 0, 54,}
+	,
+	{7, 0, 2, 0, 53,}
+	,
+	{7, 0, 2, 0, 51,}
+	,
+	{7, 0, 2, 0, 50,}
+	,
+	{7, 0, 2, 0, 48,}
+	,
+	{7, 0, 2, 0, 47,}
+	,
+	{7, 0, 2, 0, 46,}
+	,
+	{7, 0, 2, 0, 44,}
+	,
+	{7, 0, 2, 0, 43,}
+	,
+	{7, 0, 2, 0, 42,}
+	,
+	{7, 0, 2, 0, 41,}
+	,
+	{7, 0, 2, 0, 39,}
+	,
+	{7, 0, 2, 0, 38,}
+	,
+	{7, 0, 2, 0, 37,}
+	,
+	{7, 0, 2, 0, 36,}
+	,
+	{7, 0, 2, 0, 35,}
+	,
+	{7, 0, 2, 0, 34,}
+	,
+	{7, 0, 2, 0, 33,}
+	,
+	{7, 0, 2, 0, 32,}
+	,
+	{7, 0, 1, 0, 63,}
+	,
+	{7, 0, 1, 0, 61,}
+	,
+	{7, 0, 1, 0, 59,}
+	,
+	{7, 0, 1, 0, 57,}
+	,
+};
+
+const lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
+	{255, 255, 0xf0, 0, 152,}
+	,
+	{255, 255, 0xf0, 0, 147,}
+	,
+	{255, 255, 0xf0, 0, 143,}
+	,
+	{255, 255, 0xf0, 0, 139,}
+	,
+	{255, 255, 0xf0, 0, 135,}
+	,
+	{255, 255, 0xf0, 0, 131,}
+	,
+	{255, 255, 0xf0, 0, 128,}
+	,
+	{255, 255, 0xf0, 0, 124,}
+	,
+	{255, 255, 0xf0, 0, 121,}
+	,
+	{255, 255, 0xf0, 0, 117,}
+	,
+	{255, 255, 0xf0, 0, 114,}
+	,
+	{255, 255, 0xf0, 0, 111,}
+	,
+	{255, 255, 0xf0, 0, 107,}
+	,
+	{255, 255, 0xf0, 0, 104,}
+	,
+	{255, 255, 0xf0, 0, 101,}
+	,
+	{255, 255, 0xf0, 0, 99,}
+	,
+	{255, 255, 0xf0, 0, 96,}
+	,
+	{255, 255, 0xf0, 0, 93,}
+	,
+	{255, 255, 0xf0, 0, 90,}
+	,
+	{255, 255, 0xf0, 0, 88,}
+	,
+	{255, 255, 0xf0, 0, 85,}
+	,
+	{255, 255, 0xf0, 0, 83,}
+	,
+	{255, 255, 0xf0, 0, 81,}
+	,
+	{255, 255, 0xf0, 0, 78,}
+	,
+	{255, 255, 0xf0, 0, 76,}
+	,
+	{255, 255, 0xf0, 0, 74,}
+	,
+	{255, 255, 0xf0, 0, 72,}
+	,
+	{255, 255, 0xf0, 0, 70,}
+	,
+	{255, 255, 0xf0, 0, 68,}
+	,
+	{255, 255, 0xf0, 0, 66,}
+	,
+	{255, 255, 0xf0, 0, 64,}
+	,
+	{255, 248, 0xf0, 0, 64,}
+	,
+	{255, 241, 0xf0, 0, 64,}
+	,
+	{255, 251, 0xe0, 0, 64,}
+	,
+	{255, 244, 0xe0, 0, 64,}
+	,
+	{255, 254, 0xd0, 0, 64,}
+	,
+	{255, 246, 0xd0, 0, 64,}
+	,
+	{255, 239, 0xd0, 0, 64,}
+	,
+	{255, 249, 0xc0, 0, 64,}
+	,
+	{255, 242, 0xc0, 0, 64,}
+	,
+	{255, 255, 0xb0, 0, 64,}
+	,
+	{255, 248, 0xb0, 0, 64,}
+	,
+	{255, 241, 0xb0, 0, 64,}
+	,
+	{255, 254, 0xa0, 0, 64,}
+	,
+	{255, 246, 0xa0, 0, 64,}
+	,
+	{255, 239, 0xa0, 0, 64,}
+	,
+	{255, 255, 0x90, 0, 64,}
+	,
+	{255, 248, 0x90, 0, 64,}
+	,
+	{255, 241, 0x90, 0, 64,}
+	,
+	{255, 234, 0x90, 0, 64,}
+	,
+	{255, 255, 0x80, 0, 64,}
+	,
+	{255, 248, 0x80, 0, 64,}
+	,
+	{255, 241, 0x80, 0, 64,}
+	,
+	{255, 234, 0x80, 0, 64,}
+	,
+	{255, 255, 0x70, 0, 64,}
+	,
+	{255, 248, 0x70, 0, 64,}
+	,
+	{255, 241, 0x70, 0, 64,}
+	,
+	{255, 234, 0x70, 0, 64,}
+	,
+	{255, 227, 0x70, 0, 64,}
+	,
+	{255, 221, 0x70, 0, 64,}
+	,
+	{255, 215, 0x70, 0, 64,}
+	,
+	{255, 208, 0x70, 0, 64,}
+	,
+	{255, 203, 0x70, 0, 64,}
+	,
+	{255, 197, 0x70, 0, 64,}
+	,
+	{255, 255, 0x60, 0, 64,}
+	,
+	{255, 248, 0x60, 0, 64,}
+	,
+	{255, 241, 0x60, 0, 64,}
+	,
+	{255, 234, 0x60, 0, 64,}
+	,
+	{255, 227, 0x60, 0, 64,}
+	,
+	{255, 221, 0x60, 0, 64,}
+	,
+	{255, 255, 0x50, 0, 64,}
+	,
+	{255, 248, 0x50, 0, 64,}
+	,
+	{255, 241, 0x50, 0, 64,}
+	,
+	{255, 234, 0x50, 0, 64,}
+	,
+	{255, 227, 0x50, 0, 64,}
+	,
+	{255, 221, 0x50, 0, 64,}
+	,
+	{255, 215, 0x50, 0, 64,}
+	,
+	{255, 208, 0x50, 0, 64,}
+	,
+	{255, 255, 0x40, 0, 64,}
+	,
+	{255, 248, 0x40, 0, 64,}
+	,
+	{255, 241, 0x40, 0, 64,}
+	,
+	{255, 234, 0x40, 0, 64,}
+	,
+	{255, 227, 0x40, 0, 64,}
+	,
+	{255, 221, 0x40, 0, 64,}
+	,
+	{255, 215, 0x40, 0, 64,}
+	,
+	{255, 208, 0x40, 0, 64,}
+	,
+	{255, 203, 0x40, 0, 64,}
+	,
+	{255, 197, 0x40, 0, 64,}
+	,
+	{255, 255, 0x30, 0, 64,}
+	,
+	{255, 248, 0x30, 0, 64,}
+	,
+	{255, 241, 0x30, 0, 64,}
+	,
+	{255, 234, 0x30, 0, 64,}
+	,
+	{255, 227, 0x30, 0, 64,}
+	,
+	{255, 221, 0x30, 0, 64,}
+	,
+	{255, 215, 0x30, 0, 64,}
+	,
+	{255, 208, 0x30, 0, 64,}
+	,
+	{255, 203, 0x30, 0, 64,}
+	,
+	{255, 197, 0x30, 0, 64,}
+	,
+	{255, 191, 0x30, 0, 64,}
+	,
+	{255, 186, 0x30, 0, 64,}
+	,
+	{255, 181, 0x30, 0, 64,}
+	,
+	{255, 175, 0x30, 0, 64,}
+	,
+	{255, 255, 0x20, 0, 64,}
+	,
+	{255, 248, 0x20, 0, 64,}
+	,
+	{255, 241, 0x20, 0, 64,}
+	,
+	{255, 234, 0x20, 0, 64,}
+	,
+	{255, 227, 0x20, 0, 64,}
+	,
+	{255, 221, 0x20, 0, 64,}
+	,
+	{255, 215, 0x20, 0, 64,}
+	,
+	{255, 208, 0x20, 0, 64,}
+	,
+	{255, 203, 0x20, 0, 64,}
+	,
+	{255, 197, 0x20, 0, 64,}
+	,
+	{255, 191, 0x20, 0, 64,}
+	,
+	{255, 186, 0x20, 0, 64,}
+	,
+	{255, 181, 0x20, 0, 64,}
+	,
+	{255, 175, 0x20, 0, 64,}
+	,
+	{255, 170, 0x20, 0, 64,}
+	,
+	{255, 166, 0x20, 0, 64,}
+	,
+	{255, 161, 0x20, 0, 64,}
+	,
+	{255, 156, 0x20, 0, 64,}
+	,
+	{255, 152, 0x20, 0, 64,}
+	,
+	{255, 148, 0x20, 0, 64,}
+	,
+	{255, 143, 0x20, 0, 64,}
+	,
+	{255, 139, 0x20, 0, 64,}
+	,
+	{255, 135, 0x20, 0, 64,}
+	,
+	{255, 132, 0x20, 0, 64,}
+	,
+	{255, 255, 0x10, 0, 64,}
+	,
+	{255, 248, 0x10, 0, 64,}
+	,
+};
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h
new file mode 100644
index 0000000..5a64a98
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_lcn.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+typedef phytbl_info_t dot11lcnphytbl_info_t;
+
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev0[];
+extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313;
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa;
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
+
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_info_rev0[];
+extern const u32 dot11lcnphytbl_info_sz_rev0;
+
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_2G_rev2[];
+extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_5G_rev2[];
+extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
+
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
+
+typedef struct {
+	unsigned char gm;
+	unsigned char pga;
+	unsigned char pad;
+	unsigned char dac;
+	unsigned char bb_mult;
+} lcnphy_tx_gain_tbl_entry;
+
+extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
+extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
+
+extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c
new file mode 100644
index 0000000..742df99
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.c
@@ -0,0 +1,10632 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+
+#include <sbhnddma.h>
+#include <wlc_phy_int.h>
+#include <wlc_phytbl_n.h>
+
+const u32 frame_struct_rev0[] = {
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x09804506,
+	0x00100030,
+	0x09804507,
+	0x00100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100004,
+	0x01000a0d,
+	0x00100024,
+	0x0980450e,
+	0x00100034,
+	0x0980450f,
+	0x00100034,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x01800504,
+	0x00100030,
+	0x11808505,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x11808504,
+	0x00100030,
+	0x3981ca05,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x10008a04,
+	0x00100000,
+	0x3981ca05,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100008,
+	0x01000a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x1180850c,
+	0x00100038,
+	0x3981ca0d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x10008a0c,
+	0x00100008,
+	0x3981ca0d,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x02001405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x0200140d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x0b004a06,
+	0x01900060,
+	0x5b02ca04,
+	0x00100060,
+	0x3b01d405,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x5802d404,
+	0x00100000,
+	0x3b01d405,
+	0x00100060,
+	0x0b004a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x5002940c,
+	0x00100010,
+	0x3201940d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x0b004a0e,
+	0x01900070,
+	0x5b02ca0c,
+	0x00100070,
+	0x3b01d40d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x5802d40c,
+	0x00100010,
+	0x3b01d40d,
+	0x00100070,
+	0x0b004a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x000f4800,
+	0x62031405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x53028a07,
+	0x01900060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x000f4808,
+	0x6203140d,
+	0x00100048,
+	0x53028a0e,
+	0x01900068,
+	0x53028a0f,
+	0x01900068,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100004,
+	0x11008a0d,
+	0x00100024,
+	0x1980c50e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x0180c506,
+	0x00100030,
+	0x0180c506,
+	0x00100030,
+	0x2180c50c,
+	0x00100030,
+	0x49820a0d,
+	0x0016a130,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x2000ca0c,
+	0x00100000,
+	0x49820a0d,
+	0x0016a130,
+	0x1980c50e,
+	0x00100030,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100008,
+	0x0200140d,
+	0x00100048,
+	0x0b004a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x03004a06,
+	0x01900060,
+	0x03004a06,
+	0x01900060,
+	0x6b030a0c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x6b03140c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x0b004a0e,
+	0x01900060,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x53028a0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u8 frame_lut_rev0[] = {
+	0x02,
+	0x04,
+	0x14,
+	0x14,
+	0x03,
+	0x05,
+	0x16,
+	0x16,
+	0x0a,
+	0x0c,
+	0x1c,
+	0x1c,
+	0x0b,
+	0x0d,
+	0x1e,
+	0x1e,
+	0x06,
+	0x08,
+	0x18,
+	0x18,
+	0x07,
+	0x09,
+	0x1a,
+	0x1a,
+	0x0e,
+	0x10,
+	0x20,
+	0x28,
+	0x0f,
+	0x11,
+	0x22,
+	0x2a,
+};
+
+const u32 tmap_tbl_rev0[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdtrn_tbl_rev0[] = {
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0xfa58fa58,
+	0xf895043b,
+	0xff4c09c0,
+	0xfbc6ffa8,
+	0xfb84f384,
+	0x0798f6f9,
+	0x05760122,
+	0x058409f6,
+	0x0b500000,
+	0x05b7f542,
+	0x08860432,
+	0x06ddfee7,
+	0xfb84f384,
+	0xf9d90664,
+	0xf7e8025c,
+	0x00fff7bd,
+	0x05a805a8,
+	0xf7bd00ff,
+	0x025cf7e8,
+	0x0664f9d9,
+	0xf384fb84,
+	0xfee706dd,
+	0x04320886,
+	0xf54205b7,
+	0x00000b50,
+	0x09f60584,
+	0x01220576,
+	0xf6f90798,
+	0xf384fb84,
+	0xffa8fbc6,
+	0x09c0ff4c,
+	0x043bf895,
+	0x02d402d4,
+	0x07de0270,
+	0xfc96079c,
+	0xf90afe94,
+	0xfe00ff2c,
+	0x02d4065d,
+	0x092a0096,
+	0x0014fbb8,
+	0xfd2cfd2c,
+	0x076afb3c,
+	0x0096f752,
+	0xf991fd87,
+	0xfb2c0200,
+	0xfeb8f960,
+	0x08e0fc96,
+	0x049802a8,
+	0xfd2cfd2c,
+	0x02a80498,
+	0xfc9608e0,
+	0xf960feb8,
+	0x0200fb2c,
+	0xfd87f991,
+	0xf7520096,
+	0xfb3c076a,
+	0xfd2cfd2c,
+	0xfbb80014,
+	0x0096092a,
+	0x065d02d4,
+	0xff2cfe00,
+	0xfe94f90a,
+	0x079cfc96,
+	0x027007de,
+	0x02d402d4,
+	0x027007de,
+	0x079cfc96,
+	0xfe94f90a,
+	0xff2cfe00,
+	0x065d02d4,
+	0x0096092a,
+	0xfbb80014,
+	0xfd2cfd2c,
+	0xfb3c076a,
+	0xf7520096,
+	0xfd87f991,
+	0x0200fb2c,
+	0xf960feb8,
+	0xfc9608e0,
+	0x02a80498,
+	0xfd2cfd2c,
+	0x049802a8,
+	0x08e0fc96,
+	0xfeb8f960,
+	0xfb2c0200,
+	0xf991fd87,
+	0x0096f752,
+	0x076afb3c,
+	0xfd2cfd2c,
+	0x0014fbb8,
+	0x092a0096,
+	0x02d4065d,
+	0xfe00ff2c,
+	0xf90afe94,
+	0xfc96079c,
+	0x07de0270,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x061c061c,
+	0xff30009d,
+	0xffb21141,
+	0xfd87fb54,
+	0xf65dfe59,
+	0x02eef99e,
+	0x0166f03c,
+	0xfff809b6,
+	0x000008a4,
+	0x000af42b,
+	0x00eff577,
+	0xfa840bf2,
+	0xfc02ff51,
+	0x08260f67,
+	0xfff0036f,
+	0x0842f9c3,
+	0x00000000,
+	0x063df7be,
+	0xfc910010,
+	0xf099f7da,
+	0x00af03fe,
+	0xf40e057c,
+	0x0a89ff11,
+	0x0bd5fff6,
+	0xf75c0000,
+	0xf64a0008,
+	0x0fc4fe9a,
+	0x0662fd12,
+	0x01a709a3,
+	0x04ac0279,
+	0xeebf004e,
+	0xff6300d0,
+	0xf9e4f9e4,
+	0x00d0ff63,
+	0x004eeebf,
+	0x027904ac,
+	0x09a301a7,
+	0xfd120662,
+	0xfe9a0fc4,
+	0x0008f64a,
+	0x0000f75c,
+	0xfff60bd5,
+	0xff110a89,
+	0x057cf40e,
+	0x03fe00af,
+	0xf7daf099,
+	0x0010fc91,
+	0xf7be063d,
+	0x00000000,
+	0xf9c30842,
+	0x036ffff0,
+	0x0f670826,
+	0xff51fc02,
+	0x0bf2fa84,
+	0xf57700ef,
+	0xf42b000a,
+	0x08a40000,
+	0x09b6fff8,
+	0xf03c0166,
+	0xf99e02ee,
+	0xfe59f65d,
+	0xfb54fd87,
+	0x1141ffb2,
+	0x009dff30,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0xfa58fa58,
+	0xf8f0fe00,
+	0x0448073d,
+	0xfdc9fe46,
+	0xf9910258,
+	0x089d0407,
+	0xfd5cf71a,
+	0x02affde0,
+	0x083e0496,
+	0xff5a0740,
+	0xff7afd97,
+	0x00fe01f1,
+	0x0009082e,
+	0xfa94ff75,
+	0xfecdf8ea,
+	0xffb0f693,
+	0xfd2cfa58,
+	0x0433ff16,
+	0xfba405dd,
+	0xfa610341,
+	0x06a606cb,
+	0x0039fd2d,
+	0x0677fa97,
+	0x01fa05e0,
+	0xf896003e,
+	0x075a068b,
+	0x012cfc3e,
+	0xfa23f98d,
+	0xfc7cfd43,
+	0xff90fc0d,
+	0x01c10982,
+	0x00c601d6,
+	0xfd2cfd2c,
+	0x01d600c6,
+	0x098201c1,
+	0xfc0dff90,
+	0xfd43fc7c,
+	0xf98dfa23,
+	0xfc3e012c,
+	0x068b075a,
+	0x003ef896,
+	0x05e001fa,
+	0xfa970677,
+	0xfd2d0039,
+	0x06cb06a6,
+	0x0341fa61,
+	0x05ddfba4,
+	0xff160433,
+	0xfa58fd2c,
+	0xf693ffb0,
+	0xf8eafecd,
+	0xff75fa94,
+	0x082e0009,
+	0x01f100fe,
+	0xfd97ff7a,
+	0x0740ff5a,
+	0x0496083e,
+	0xfde002af,
+	0xf71afd5c,
+	0x0407089d,
+	0x0258f991,
+	0xfe46fdc9,
+	0x073d0448,
+	0xfe00f8f0,
+	0xfd2cfd2c,
+	0xfce00500,
+	0xfc09fddc,
+	0xfe680157,
+	0x04c70571,
+	0xfc3aff21,
+	0xfcd70228,
+	0x056d0277,
+	0x0200fe00,
+	0x0022f927,
+	0xfe3c032b,
+	0xfc44ff3c,
+	0x03e9fbdb,
+	0x04570313,
+	0x04c9ff5c,
+	0x000d03b8,
+	0xfa580000,
+	0xfbe900d2,
+	0xf9d0fe0b,
+	0x0125fdf9,
+	0x042501bf,
+	0x0328fa2b,
+	0xffa902f0,
+	0xfa250157,
+	0x0200fe00,
+	0x03740438,
+	0xff0405fd,
+	0x030cfe52,
+	0x0037fb39,
+	0xff6904c5,
+	0x04f8fd23,
+	0xfd31fc1b,
+	0xfd2cfd2c,
+	0xfc1bfd31,
+	0xfd2304f8,
+	0x04c5ff69,
+	0xfb390037,
+	0xfe52030c,
+	0x05fdff04,
+	0x04380374,
+	0xfe000200,
+	0x0157fa25,
+	0x02f0ffa9,
+	0xfa2b0328,
+	0x01bf0425,
+	0xfdf90125,
+	0xfe0bf9d0,
+	0x00d2fbe9,
+	0x0000fa58,
+	0x03b8000d,
+	0xff5c04c9,
+	0x03130457,
+	0xfbdb03e9,
+	0xff3cfc44,
+	0x032bfe3c,
+	0xf9270022,
+	0xfe000200,
+	0x0277056d,
+	0x0228fcd7,
+	0xff21fc3a,
+	0x057104c7,
+	0x0157fe68,
+	0xfddcfc09,
+	0x0500fce0,
+	0xfd2cfd2c,
+	0x0500fce0,
+	0xfddcfc09,
+	0x0157fe68,
+	0x057104c7,
+	0xff21fc3a,
+	0x0228fcd7,
+	0x0277056d,
+	0xfe000200,
+	0xf9270022,
+	0x032bfe3c,
+	0xff3cfc44,
+	0xfbdb03e9,
+	0x03130457,
+	0xff5c04c9,
+	0x03b8000d,
+	0x0000fa58,
+	0x00d2fbe9,
+	0xfe0bf9d0,
+	0xfdf90125,
+	0x01bf0425,
+	0xfa2b0328,
+	0x02f0ffa9,
+	0x0157fa25,
+	0xfe000200,
+	0x04380374,
+	0x05fdff04,
+	0xfe52030c,
+	0xfb390037,
+	0x04c5ff69,
+	0xfd2304f8,
+	0xfc1bfd31,
+	0xfd2cfd2c,
+	0xfd31fc1b,
+	0x04f8fd23,
+	0xff6904c5,
+	0x0037fb39,
+	0x030cfe52,
+	0xff0405fd,
+	0x03740438,
+	0x0200fe00,
+	0xfa250157,
+	0xffa902f0,
+	0x0328fa2b,
+	0x042501bf,
+	0x0125fdf9,
+	0xf9d0fe0b,
+	0xfbe900d2,
+	0xfa580000,
+	0x000d03b8,
+	0x04c9ff5c,
+	0x04570313,
+	0x03e9fbdb,
+	0xfc44ff3c,
+	0xfe3c032b,
+	0x0022f927,
+	0x0200fe00,
+	0x056d0277,
+	0xfcd70228,
+	0xfc3aff21,
+	0x04c70571,
+	0xfe680157,
+	0xfc09fddc,
+	0xfce00500,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+};
+
+const u32 intlv_tbl_rev0[] = {
+	0x00802070,
+	0x0671188d,
+	0x0a60192c,
+	0x0a300e46,
+	0x00c1188d,
+	0x080024d2,
+	0x00000070,
+};
+
+const u16 pilot_tbl_rev0[] = {
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0xff0a,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xff0a,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xf83f,
+	0xfa1f,
+	0xfa97,
+	0xfab5,
+	0xf2bd,
+	0xf0bf,
+	0xffff,
+	0xffff,
+	0xf017,
+	0xf815,
+	0xf215,
+	0xf095,
+	0xf035,
+	0xf01d,
+	0xffff,
+	0xffff,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xf01f,
+	0xf817,
+	0xfa15,
+	0xf295,
+	0xf0b5,
+	0xf03d,
+	0xffff,
+	0xffff,
+	0xf82a,
+	0xfa0a,
+	0xfa82,
+	0xfaa0,
+	0xf2a8,
+	0xf0aa,
+	0xffff,
+	0xffff,
+	0xf002,
+	0xf800,
+	0xf200,
+	0xf080,
+	0xf020,
+	0xf008,
+	0xffff,
+	0xffff,
+	0xf00a,
+	0xf802,
+	0xfa00,
+	0xf280,
+	0xf0a0,
+	0xf028,
+	0xffff,
+	0xffff,
+};
+
+const u32 pltlut_tbl_rev0[] = {
+	0x76540123,
+	0x62407351,
+	0x76543201,
+	0x76540213,
+	0x76540123,
+	0x76430521,
+};
+
+const u32 tdi_tbl20_ant0_rev0[] = {
+	0x00091226,
+	0x000a1429,
+	0x000b56ad,
+	0x000c58b0,
+	0x000d5ab3,
+	0x000e9cb6,
+	0x000f9eba,
+	0x0000c13d,
+	0x00020301,
+	0x00030504,
+	0x00040708,
+	0x0005090b,
+	0x00064b8e,
+	0x00095291,
+	0x000a5494,
+	0x000b9718,
+	0x000c9927,
+	0x000d9b2a,
+	0x000edd2e,
+	0x000fdf31,
+	0x000101b4,
+	0x000243b7,
+	0x000345bb,
+	0x000447be,
+	0x00058982,
+	0x00068c05,
+	0x00099309,
+	0x000a950c,
+	0x000bd78f,
+	0x000cd992,
+	0x000ddb96,
+	0x000f1d99,
+	0x00005fa8,
+	0x0001422c,
+	0x0002842f,
+	0x00038632,
+	0x00048835,
+	0x0005ca38,
+	0x0006ccbc,
+	0x0009d3bf,
+	0x000b1603,
+	0x000c1806,
+	0x000d1a0a,
+	0x000e1c0d,
+	0x000f5e10,
+	0x00008093,
+	0x00018297,
+	0x0002c49a,
+	0x0003c680,
+	0x0004c880,
+	0x00060b00,
+	0x00070d00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl20_ant1_rev0[] = {
+	0x00014b26,
+	0x00028d29,
+	0x000393ad,
+	0x00049630,
+	0x0005d833,
+	0x0006da36,
+	0x00099c3a,
+	0x000a9e3d,
+	0x000bc081,
+	0x000cc284,
+	0x000dc488,
+	0x000f068b,
+	0x0000488e,
+	0x00018b91,
+	0x0002d214,
+	0x0003d418,
+	0x0004d6a7,
+	0x000618aa,
+	0x00071aae,
+	0x0009dcb1,
+	0x000b1eb4,
+	0x000c0137,
+	0x000d033b,
+	0x000e053e,
+	0x000f4702,
+	0x00008905,
+	0x00020c09,
+	0x0003128c,
+	0x0004148f,
+	0x00051712,
+	0x00065916,
+	0x00091b19,
+	0x000a1d28,
+	0x000b5f2c,
+	0x000c41af,
+	0x000d43b2,
+	0x000e85b5,
+	0x000f87b8,
+	0x0000c9bc,
+	0x00024cbf,
+	0x00035303,
+	0x00045506,
+	0x0005978a,
+	0x0006998d,
+	0x00095b90,
+	0x000a5d93,
+	0x000b9f97,
+	0x000c821a,
+	0x000d8400,
+	0x000ec600,
+	0x000fc800,
+	0x00010a00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant0_rev0[] = {
+	0x0011a346,
+	0x00136ccf,
+	0x0014f5d9,
+	0x001641e2,
+	0x0017cb6b,
+	0x00195475,
+	0x001b2383,
+	0x001cad0c,
+	0x001e7616,
+	0x0000821f,
+	0x00020ba8,
+	0x0003d4b2,
+	0x00056447,
+	0x00072dd0,
+	0x0008b6da,
+	0x000a02e3,
+	0x000b8c6c,
+	0x000d15f6,
+	0x0011e484,
+	0x0013ae0d,
+	0x00153717,
+	0x00168320,
+	0x00180ca9,
+	0x00199633,
+	0x001b6548,
+	0x001ceed1,
+	0x001eb7db,
+	0x0000c3e4,
+	0x00024d6d,
+	0x000416f7,
+	0x0005a585,
+	0x00076f0f,
+	0x0008f818,
+	0x000a4421,
+	0x000bcdab,
+	0x000d9734,
+	0x00122649,
+	0x0013efd2,
+	0x001578dc,
+	0x0016c4e5,
+	0x00184e6e,
+	0x001a17f8,
+	0x001ba686,
+	0x001d3010,
+	0x001ef999,
+	0x00010522,
+	0x00028eac,
+	0x00045835,
+	0x0005e74a,
+	0x0007b0d3,
+	0x00093a5d,
+	0x000a85e6,
+	0x000c0f6f,
+	0x000dd8f9,
+	0x00126787,
+	0x00143111,
+	0x0015ba9a,
+	0x00170623,
+	0x00188fad,
+	0x001a5936,
+	0x001be84b,
+	0x001db1d4,
+	0x001f3b5e,
+	0x000146e7,
+	0x00031070,
+	0x000499fa,
+	0x00062888,
+	0x0007f212,
+	0x00097b9b,
+	0x000ac7a4,
+	0x000c50ae,
+	0x000e1a37,
+	0x0012a94c,
+	0x001472d5,
+	0x0015fc5f,
+	0x00174868,
+	0x0018d171,
+	0x001a9afb,
+	0x001c2989,
+	0x001df313,
+	0x001f7c9c,
+	0x000188a5,
+	0x000351af,
+	0x0004db38,
+	0x0006aa4d,
+	0x000833d7,
+	0x0009bd60,
+	0x000b0969,
+	0x000c9273,
+	0x000e5bfc,
+	0x00132a8a,
+	0x0014b414,
+	0x00163d9d,
+	0x001789a6,
+	0x001912b0,
+	0x001adc39,
+	0x001c6bce,
+	0x001e34d8,
+	0x001fbe61,
+	0x0001ca6a,
+	0x00039374,
+	0x00051cfd,
+	0x0006ec0b,
+	0x00087515,
+	0x0009fe9e,
+	0x000b4aa7,
+	0x000cd3b1,
+	0x000e9d3a,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant1_rev0[] = {
+	0x001edb36,
+	0x000129ca,
+	0x0002b353,
+	0x00047cdd,
+	0x0005c8e6,
+	0x000791ef,
+	0x00091bf9,
+	0x000aaa07,
+	0x000c3391,
+	0x000dfd1a,
+	0x00120923,
+	0x0013d22d,
+	0x00155c37,
+	0x0016eacb,
+	0x00187454,
+	0x001a3dde,
+	0x001b89e7,
+	0x001d12f0,
+	0x001f1cfa,
+	0x00016b88,
+	0x00033492,
+	0x0004be1b,
+	0x00060a24,
+	0x0007d32e,
+	0x00095d38,
+	0x000aec4c,
+	0x000c7555,
+	0x000e3edf,
+	0x00124ae8,
+	0x001413f1,
+	0x0015a37b,
+	0x00172c89,
+	0x0018b593,
+	0x001a419c,
+	0x001bcb25,
+	0x001d942f,
+	0x001f63b9,
+	0x0001ad4d,
+	0x00037657,
+	0x0004c260,
+	0x00068be9,
+	0x000814f3,
+	0x0009a47c,
+	0x000b2d8a,
+	0x000cb694,
+	0x000e429d,
+	0x00128c26,
+	0x001455b0,
+	0x0015e4ba,
+	0x00176e4e,
+	0x0018f758,
+	0x001a8361,
+	0x001c0cea,
+	0x001dd674,
+	0x001fa57d,
+	0x0001ee8b,
+	0x0003b795,
+	0x0005039e,
+	0x0006cd27,
+	0x000856b1,
+	0x0009e5c6,
+	0x000b6f4f,
+	0x000cf859,
+	0x000e8462,
+	0x00130deb,
+	0x00149775,
+	0x00162603,
+	0x0017af8c,
+	0x00193896,
+	0x001ac49f,
+	0x001c4e28,
+	0x001e17b2,
+	0x0000a6c7,
+	0x00023050,
+	0x0003f9da,
+	0x00054563,
+	0x00070eec,
+	0x00089876,
+	0x000a2704,
+	0x000bb08d,
+	0x000d3a17,
+	0x001185a0,
+	0x00134f29,
+	0x0014d8b3,
+	0x001667c8,
+	0x0017f151,
+	0x00197adb,
+	0x001b0664,
+	0x001c8fed,
+	0x001e5977,
+	0x0000e805,
+	0x0002718f,
+	0x00043b18,
+	0x000586a1,
+	0x0007502b,
+	0x0008d9b4,
+	0x000a68c9,
+	0x000bf252,
+	0x000dbbdc,
+	0x0011c7e5,
+	0x001390ee,
+	0x00151a78,
+	0x0016a906,
+	0x00183290,
+	0x0019bc19,
+	0x001b4822,
+	0x001cd12c,
+	0x001e9ab5,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 bdi_tbl_rev0[] = {
+	0x0070,
+	0x0126,
+	0x012c,
+	0x0246,
+	0x048d,
+	0x04d2,
+};
+
+const u32 chanest_tbl_rev0[] = {
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+};
+
+const u8 mcs_tbl_rev0[] = {
+	0x00,
+	0x08,
+	0x0a,
+	0x10,
+	0x12,
+	0x19,
+	0x1a,
+	0x1c,
+	0x40,
+	0x48,
+	0x4a,
+	0x50,
+	0x52,
+	0x59,
+	0x5a,
+	0x5c,
+	0x80,
+	0x88,
+	0x8a,
+	0x90,
+	0x92,
+	0x99,
+	0x9a,
+	0x9c,
+	0xc0,
+	0xc8,
+	0xca,
+	0xd0,
+	0xd2,
+	0xd9,
+	0xda,
+	0xdc,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x01,
+	0x02,
+	0x04,
+	0x08,
+	0x09,
+	0x0a,
+	0x0c,
+	0x10,
+	0x11,
+	0x12,
+	0x14,
+	0x18,
+	0x19,
+	0x1a,
+	0x1c,
+	0x20,
+	0x21,
+	0x22,
+	0x24,
+	0x40,
+	0x41,
+	0x42,
+	0x44,
+	0x48,
+	0x49,
+	0x4a,
+	0x4c,
+	0x50,
+	0x51,
+	0x52,
+	0x54,
+	0x58,
+	0x59,
+	0x5a,
+	0x5c,
+	0x60,
+	0x61,
+	0x62,
+	0x64,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u32 noise_var_tbl0_rev0[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+const u32 noise_var_tbl1_rev0[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+const u8 est_pwr_lut_core0_rev0[] = {
+	0x50,
+	0x4f,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3b,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x34,
+	0x33,
+	0x32,
+	0x31,
+	0x30,
+	0x2f,
+	0x2e,
+	0x2d,
+	0x2c,
+	0x2b,
+	0x2a,
+	0x29,
+	0x28,
+	0x27,
+	0x26,
+	0x25,
+	0x24,
+	0x23,
+	0x22,
+	0x21,
+	0x20,
+	0x1f,
+	0x1e,
+	0x1d,
+	0x1c,
+	0x1b,
+	0x1a,
+	0x19,
+	0x18,
+	0x17,
+	0x16,
+	0x15,
+	0x14,
+	0x13,
+	0x12,
+	0x11,
+};
+
+const u8 est_pwr_lut_core1_rev0[] = {
+	0x50,
+	0x4f,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3b,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x34,
+	0x33,
+	0x32,
+	0x31,
+	0x30,
+	0x2f,
+	0x2e,
+	0x2d,
+	0x2c,
+	0x2b,
+	0x2a,
+	0x29,
+	0x28,
+	0x27,
+	0x26,
+	0x25,
+	0x24,
+	0x23,
+	0x22,
+	0x21,
+	0x20,
+	0x1f,
+	0x1e,
+	0x1d,
+	0x1c,
+	0x1b,
+	0x1a,
+	0x19,
+	0x18,
+	0x17,
+	0x16,
+	0x15,
+	0x14,
+	0x13,
+	0x12,
+	0x11,
+};
+
+const u8 adj_pwr_lut_core0_rev0[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u8 adj_pwr_lut_core1_rev0[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u32 gainctrl_lut_core0_rev0[] = {
+	0x03cc2b44,
+	0x03cc2b42,
+	0x03cc2b40,
+	0x03cc2b3e,
+	0x03cc2b3d,
+	0x03cc2b3b,
+	0x03c82b44,
+	0x03c82b42,
+	0x03c82b40,
+	0x03c82b3e,
+	0x03c82b3d,
+	0x03c82b3b,
+	0x03c82b39,
+	0x03c82b38,
+	0x03c82b36,
+	0x03c82b34,
+	0x03c42b44,
+	0x03c42b42,
+	0x03c42b40,
+	0x03c42b3e,
+	0x03c42b3d,
+	0x03c42b3b,
+	0x03c42b39,
+	0x03c42b38,
+	0x03c42b36,
+	0x03c42b34,
+	0x03c42b33,
+	0x03c42b32,
+	0x03c42b30,
+	0x03c42b2f,
+	0x03c42b2d,
+	0x03c02b44,
+	0x03c02b42,
+	0x03c02b40,
+	0x03c02b3e,
+	0x03c02b3d,
+	0x03c02b3b,
+	0x03c02b39,
+	0x03c02b38,
+	0x03c02b36,
+	0x03c02b34,
+	0x03b02b44,
+	0x03b02b42,
+	0x03b02b40,
+	0x03b02b3e,
+	0x03b02b3d,
+	0x03b02b3b,
+	0x03b02b39,
+	0x03b02b38,
+	0x03b02b36,
+	0x03b02b34,
+	0x03b02b33,
+	0x03b02b32,
+	0x03b02b30,
+	0x03b02b2f,
+	0x03b02b2d,
+	0x03a02b44,
+	0x03a02b42,
+	0x03a02b40,
+	0x03a02b3e,
+	0x03a02b3d,
+	0x03a02b3b,
+	0x03a02b39,
+	0x03a02b38,
+	0x03a02b36,
+	0x03a02b34,
+	0x03902b44,
+	0x03902b42,
+	0x03902b40,
+	0x03902b3e,
+	0x03902b3d,
+	0x03902b3b,
+	0x03902b39,
+	0x03902b38,
+	0x03902b36,
+	0x03902b34,
+	0x03902b33,
+	0x03902b32,
+	0x03902b30,
+	0x03802b44,
+	0x03802b42,
+	0x03802b40,
+	0x03802b3e,
+	0x03802b3d,
+	0x03802b3b,
+	0x03802b39,
+	0x03802b38,
+	0x03802b36,
+	0x03802b34,
+	0x03802b33,
+	0x03802b32,
+	0x03802b30,
+	0x03802b2f,
+	0x03802b2d,
+	0x03802b2c,
+	0x03802b2b,
+	0x03802b2a,
+	0x03802b29,
+	0x03802b27,
+	0x03802b26,
+	0x03802b25,
+	0x03802b24,
+	0x03802b23,
+	0x03802b22,
+	0x03802b21,
+	0x03802b20,
+	0x03802b1f,
+	0x03802b1e,
+	0x03802b1e,
+	0x03802b1d,
+	0x03802b1c,
+	0x03802b1b,
+	0x03802b1a,
+	0x03802b1a,
+	0x03802b19,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x00002b00,
+};
+
+const u32 gainctrl_lut_core1_rev0[] = {
+	0x03cc2b44,
+	0x03cc2b42,
+	0x03cc2b40,
+	0x03cc2b3e,
+	0x03cc2b3d,
+	0x03cc2b3b,
+	0x03c82b44,
+	0x03c82b42,
+	0x03c82b40,
+	0x03c82b3e,
+	0x03c82b3d,
+	0x03c82b3b,
+	0x03c82b39,
+	0x03c82b38,
+	0x03c82b36,
+	0x03c82b34,
+	0x03c42b44,
+	0x03c42b42,
+	0x03c42b40,
+	0x03c42b3e,
+	0x03c42b3d,
+	0x03c42b3b,
+	0x03c42b39,
+	0x03c42b38,
+	0x03c42b36,
+	0x03c42b34,
+	0x03c42b33,
+	0x03c42b32,
+	0x03c42b30,
+	0x03c42b2f,
+	0x03c42b2d,
+	0x03c02b44,
+	0x03c02b42,
+	0x03c02b40,
+	0x03c02b3e,
+	0x03c02b3d,
+	0x03c02b3b,
+	0x03c02b39,
+	0x03c02b38,
+	0x03c02b36,
+	0x03c02b34,
+	0x03b02b44,
+	0x03b02b42,
+	0x03b02b40,
+	0x03b02b3e,
+	0x03b02b3d,
+	0x03b02b3b,
+	0x03b02b39,
+	0x03b02b38,
+	0x03b02b36,
+	0x03b02b34,
+	0x03b02b33,
+	0x03b02b32,
+	0x03b02b30,
+	0x03b02b2f,
+	0x03b02b2d,
+	0x03a02b44,
+	0x03a02b42,
+	0x03a02b40,
+	0x03a02b3e,
+	0x03a02b3d,
+	0x03a02b3b,
+	0x03a02b39,
+	0x03a02b38,
+	0x03a02b36,
+	0x03a02b34,
+	0x03902b44,
+	0x03902b42,
+	0x03902b40,
+	0x03902b3e,
+	0x03902b3d,
+	0x03902b3b,
+	0x03902b39,
+	0x03902b38,
+	0x03902b36,
+	0x03902b34,
+	0x03902b33,
+	0x03902b32,
+	0x03902b30,
+	0x03802b44,
+	0x03802b42,
+	0x03802b40,
+	0x03802b3e,
+	0x03802b3d,
+	0x03802b3b,
+	0x03802b39,
+	0x03802b38,
+	0x03802b36,
+	0x03802b34,
+	0x03802b33,
+	0x03802b32,
+	0x03802b30,
+	0x03802b2f,
+	0x03802b2d,
+	0x03802b2c,
+	0x03802b2b,
+	0x03802b2a,
+	0x03802b29,
+	0x03802b27,
+	0x03802b26,
+	0x03802b25,
+	0x03802b24,
+	0x03802b23,
+	0x03802b22,
+	0x03802b21,
+	0x03802b20,
+	0x03802b1f,
+	0x03802b1e,
+	0x03802b1e,
+	0x03802b1d,
+	0x03802b1c,
+	0x03802b1b,
+	0x03802b1a,
+	0x03802b1a,
+	0x03802b19,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x03802b18,
+	0x00002b00,
+};
+
+const u32 iq_lut_core0_rev0[] = {
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+};
+
+const u32 iq_lut_core1_rev0[] = {
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+	0x0000007f,
+};
+
+const u16 loft_lut_core0_rev0[] = {
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+};
+
+const u16 loft_lut_core1_rev0[] = {
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+	0x0000,
+	0x0101,
+	0x0002,
+	0x0103,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev0_volatile[] = {
+	{&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0,
+	 16}
+	,
+	{&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]),
+	 20, 0, 32}
+	,
+	{&gainctrl_lut_core0_rev0,
+	 sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev0,
+	 sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]),
+	 27, 192, 32}
+	,
+
+	{&est_pwr_lut_core0_rev0,
+	 sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev0,
+	 sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev0,
+	 sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev0,
+	 sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27,
+	 64, 8}
+	,
+	{&iq_lut_core0_rev0,
+	 sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev0,
+	 sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev0,
+	 sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev0,
+	 sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448,
+	 16}
+	,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev0[] = {
+	{&frame_struct_rev0,
+	 sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32}
+	,
+	{&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]),
+	 24, 0, 8}
+	,
+	{&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12,
+	 0, 32}
+	,
+	{&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]),
+	 14, 0, 32}
+	,
+	{&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]),
+	 13, 0, 32}
+	,
+	{&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]),
+	 11, 0, 16}
+	,
+	{&tdi_tbl20_ant0_rev0,
+	 sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128,
+	 32}
+	,
+	{&tdi_tbl20_ant1_rev0,
+	 sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256,
+	 32}
+	,
+	{&tdi_tbl40_ant0_rev0,
+	 sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640,
+	 32}
+	,
+	{&tdi_tbl40_ant1_rev0,
+	 sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768,
+	 32}
+	,
+	{&chanest_tbl_rev0,
+	 sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32}
+	,
+	{&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8}
+	,
+	{&noise_var_tbl0_rev0,
+	 sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0,
+	 32}
+	,
+	{&noise_var_tbl1_rev0,
+	 sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128,
+	 32}
+	,
+};
+
+const u32 mimophytbl_info_sz_rev0 =
+    sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]);
+const u32 mimophytbl_info_sz_rev0_volatile =
+    sizeof(mimophytbl_info_rev0_volatile) /
+    sizeof(mimophytbl_info_rev0_volatile[0]);
+
+const u16 ant_swctrl_tbl_rev3[] = {
+	0x0082,
+	0x0082,
+	0x0211,
+	0x0222,
+	0x0328,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0144,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0188,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0082,
+	0x0082,
+	0x0211,
+	0x0222,
+	0x0328,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0144,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0188,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 ant_swctrl_tbl_rev3_1[] = {
+	0x0022,
+	0x0022,
+	0x0011,
+	0x0022,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0011,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0022,
+	0x0011,
+	0x0022,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0011,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0022,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 ant_swctrl_tbl_rev3_2[] = {
+	0x0088,
+	0x0088,
+	0x0044,
+	0x0088,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0044,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0088,
+	0x0044,
+	0x0088,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0044,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0088,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 ant_swctrl_tbl_rev3_3[] = {
+	0x022,
+	0x022,
+	0x011,
+	0x022,
+	0x000,
+	0x000,
+	0x000,
+	0x000,
+	0x011,
+	0x000,
+	0x000,
+	0x000,
+	0x022,
+	0x000,
+	0x000,
+	0x3cc,
+	0x022,
+	0x022,
+	0x011,
+	0x022,
+	0x000,
+	0x000,
+	0x000,
+	0x000,
+	0x011,
+	0x000,
+	0x000,
+	0x000,
+	0x022,
+	0x000,
+	0x000,
+	0x3cc
+};
+
+const u32 frame_struct_rev3[] = {
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x09804506,
+	0x00100030,
+	0x09804507,
+	0x00100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100004,
+	0x01000a0d,
+	0x00100024,
+	0x0980450e,
+	0x00100034,
+	0x0980450f,
+	0x00100034,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x01800504,
+	0x00100030,
+	0x11808505,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000a04,
+	0x00100000,
+	0x11008a05,
+	0x00100020,
+	0x21810506,
+	0x00100030,
+	0x21810506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x1980c506,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x11808504,
+	0x00100030,
+	0x3981ca05,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x10008a04,
+	0x00100000,
+	0x3981ca05,
+	0x00100030,
+	0x1980c506,
+	0x00100030,
+	0x29814507,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a0c,
+	0x00100008,
+	0x01000a0d,
+	0x00100028,
+	0x1980c50e,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x1180850c,
+	0x00100038,
+	0x3981ca0d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x10008a0c,
+	0x00100008,
+	0x3981ca0d,
+	0x00100038,
+	0x1980c50e,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x02001405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x13008a06,
+	0x01900060,
+	0x13008a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x0200140d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x0b004a06,
+	0x01900060,
+	0x0b004a06,
+	0x01900060,
+	0x5b02ca04,
+	0x00100060,
+	0x3b01d405,
+	0x00100060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x5802d404,
+	0x00100000,
+	0x3b01d405,
+	0x00100060,
+	0x0b004a06,
+	0x01900060,
+	0x23010a07,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x5002940c,
+	0x00100010,
+	0x3201940d,
+	0x00100050,
+	0x0b004a0e,
+	0x01900070,
+	0x0b004a0e,
+	0x01900070,
+	0x5b02ca0c,
+	0x00100070,
+	0x3b01d40d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x5802d40c,
+	0x00100010,
+	0x3b01d40d,
+	0x00100070,
+	0x0b004a0e,
+	0x01900070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x000f4800,
+	0x62031405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x53028a07,
+	0x01900060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x000f4808,
+	0x6203140d,
+	0x00100048,
+	0x53028a0e,
+	0x01900068,
+	0x53028a0f,
+	0x01900068,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100004,
+	0x11008a0d,
+	0x00100024,
+	0x1980c50e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x2181050e,
+	0x00100034,
+	0x0180050c,
+	0x00100038,
+	0x1180850d,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000a0c,
+	0x00100008,
+	0x11008a0d,
+	0x00100028,
+	0x2181050e,
+	0x00100038,
+	0x2181050e,
+	0x00100038,
+	0x1181850d,
+	0x00100038,
+	0x2981450f,
+	0x01100038,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x08004a04,
+	0x00100000,
+	0x01000a05,
+	0x00100020,
+	0x0180c506,
+	0x00100030,
+	0x0180c506,
+	0x00100030,
+	0x2180c50c,
+	0x00100030,
+	0x49820a0d,
+	0x0016a130,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x2000ca0c,
+	0x00100000,
+	0x49820a0d,
+	0x0016a130,
+	0x1980c50e,
+	0x00100030,
+	0x41824a0d,
+	0x0016a130,
+	0x2981450f,
+	0x01100030,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100008,
+	0x0200140d,
+	0x00100048,
+	0x0b004a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x13008a0e,
+	0x01900068,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x13008a0e,
+	0x01900070,
+	0x13008a0e,
+	0x01900070,
+	0x1b014a0d,
+	0x00100070,
+	0x23010a0f,
+	0x01500070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x50029404,
+	0x00100000,
+	0x32019405,
+	0x00100040,
+	0x03004a06,
+	0x01900060,
+	0x03004a06,
+	0x01900060,
+	0x6b030a0c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x6b03140c,
+	0x00100060,
+	0x4b02140d,
+	0x0016a160,
+	0x0b004a0e,
+	0x01900060,
+	0x4302540d,
+	0x0016a160,
+	0x23010a0f,
+	0x01500060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x53028a06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x43020a04,
+	0x00100060,
+	0x1b00ca05,
+	0x00100060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x53028a0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x43020a0c,
+	0x00100070,
+	0x1b00ca0d,
+	0x00100070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x40021404,
+	0x00100000,
+	0x1a00d405,
+	0x00100040,
+	0x5b02ca06,
+	0x01900060,
+	0x5b02ca06,
+	0x01900060,
+	0x53028a07,
+	0x0190c060,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x4002140c,
+	0x00100010,
+	0x1a00d40d,
+	0x00100050,
+	0x5b02ca0e,
+	0x01900070,
+	0x5b02ca0e,
+	0x01900070,
+	0x53028a0f,
+	0x0190c070,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 pilot_tbl_rev3[] = {
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0xff08,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0x80d5,
+	0xff0a,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xff82,
+	0xffa0,
+	0xff28,
+	0xff0a,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xffff,
+	0xf83f,
+	0xfa1f,
+	0xfa97,
+	0xfab5,
+	0xf2bd,
+	0xf0bf,
+	0xffff,
+	0xffff,
+	0xf017,
+	0xf815,
+	0xf215,
+	0xf095,
+	0xf035,
+	0xf01d,
+	0xffff,
+	0xffff,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xff08,
+	0xff02,
+	0xff80,
+	0xff20,
+	0xf01f,
+	0xf817,
+	0xfa15,
+	0xf295,
+	0xf0b5,
+	0xf03d,
+	0xffff,
+	0xffff,
+	0xf82a,
+	0xfa0a,
+	0xfa82,
+	0xfaa0,
+	0xf2a8,
+	0xf0aa,
+	0xffff,
+	0xffff,
+	0xf002,
+	0xf800,
+	0xf200,
+	0xf080,
+	0xf020,
+	0xf008,
+	0xffff,
+	0xffff,
+	0xf00a,
+	0xf802,
+	0xfa00,
+	0xf280,
+	0xf0a0,
+	0xf028,
+	0xffff,
+	0xffff,
+};
+
+const u32 tmap_tbl_rev3[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 intlv_tbl_rev3[] = {
+	0x00802070,
+	0x0671188d,
+	0x0a60192c,
+	0x0a300e46,
+	0x00c1188d,
+	0x080024d2,
+	0x00000070,
+};
+
+const u32 tdtrn_tbl_rev3[] = {
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x061c061c,
+	0x0050ee68,
+	0xf592fe36,
+	0xfe5212f6,
+	0x00000c38,
+	0xfe5212f6,
+	0xf592fe36,
+	0x0050ee68,
+	0x061c061c,
+	0xee680050,
+	0xfe36f592,
+	0x12f6fe52,
+	0x0c380000,
+	0x12f6fe52,
+	0xfe36f592,
+	0xee680050,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0x05e305e3,
+	0x004def0c,
+	0xf5f3fe47,
+	0xfe611246,
+	0x00000bc7,
+	0xfe611246,
+	0xf5f3fe47,
+	0x004def0c,
+	0x05e305e3,
+	0xef0c004d,
+	0xfe47f5f3,
+	0x1246fe61,
+	0x0bc70000,
+	0x1246fe61,
+	0xfe47f5f3,
+	0xef0c004d,
+	0xfa58fa58,
+	0xf895043b,
+	0xff4c09c0,
+	0xfbc6ffa8,
+	0xfb84f384,
+	0x0798f6f9,
+	0x05760122,
+	0x058409f6,
+	0x0b500000,
+	0x05b7f542,
+	0x08860432,
+	0x06ddfee7,
+	0xfb84f384,
+	0xf9d90664,
+	0xf7e8025c,
+	0x00fff7bd,
+	0x05a805a8,
+	0xf7bd00ff,
+	0x025cf7e8,
+	0x0664f9d9,
+	0xf384fb84,
+	0xfee706dd,
+	0x04320886,
+	0xf54205b7,
+	0x00000b50,
+	0x09f60584,
+	0x01220576,
+	0xf6f90798,
+	0xf384fb84,
+	0xffa8fbc6,
+	0x09c0ff4c,
+	0x043bf895,
+	0x02d402d4,
+	0x07de0270,
+	0xfc96079c,
+	0xf90afe94,
+	0xfe00ff2c,
+	0x02d4065d,
+	0x092a0096,
+	0x0014fbb8,
+	0xfd2cfd2c,
+	0x076afb3c,
+	0x0096f752,
+	0xf991fd87,
+	0xfb2c0200,
+	0xfeb8f960,
+	0x08e0fc96,
+	0x049802a8,
+	0xfd2cfd2c,
+	0x02a80498,
+	0xfc9608e0,
+	0xf960feb8,
+	0x0200fb2c,
+	0xfd87f991,
+	0xf7520096,
+	0xfb3c076a,
+	0xfd2cfd2c,
+	0xfbb80014,
+	0x0096092a,
+	0x065d02d4,
+	0xff2cfe00,
+	0xfe94f90a,
+	0x079cfc96,
+	0x027007de,
+	0x02d402d4,
+	0x027007de,
+	0x079cfc96,
+	0xfe94f90a,
+	0xff2cfe00,
+	0x065d02d4,
+	0x0096092a,
+	0xfbb80014,
+	0xfd2cfd2c,
+	0xfb3c076a,
+	0xf7520096,
+	0xfd87f991,
+	0x0200fb2c,
+	0xf960feb8,
+	0xfc9608e0,
+	0x02a80498,
+	0xfd2cfd2c,
+	0x049802a8,
+	0x08e0fc96,
+	0xfeb8f960,
+	0xfb2c0200,
+	0xf991fd87,
+	0x0096f752,
+	0x076afb3c,
+	0xfd2cfd2c,
+	0x0014fbb8,
+	0x092a0096,
+	0x02d4065d,
+	0xfe00ff2c,
+	0xf90afe94,
+	0xfc96079c,
+	0x07de0270,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x062a0000,
+	0xfefa0759,
+	0x08b80908,
+	0xf396fc2d,
+	0xf9d6045c,
+	0xfc4ef608,
+	0xf748f596,
+	0x07b207bf,
+	0x062a062a,
+	0xf84ef841,
+	0xf748f596,
+	0x03b209f8,
+	0xf9d6045c,
+	0x0c6a03d3,
+	0x08b80908,
+	0x0106f8a7,
+	0x062a0000,
+	0xfefaf8a7,
+	0x08b8f6f8,
+	0xf39603d3,
+	0xf9d6fba4,
+	0xfc4e09f8,
+	0xf7480a6a,
+	0x07b2f841,
+	0x062af9d6,
+	0xf84e07bf,
+	0xf7480a6a,
+	0x03b2f608,
+	0xf9d6fba4,
+	0x0c6afc2d,
+	0x08b8f6f8,
+	0x01060759,
+	0x061c061c,
+	0xff30009d,
+	0xffb21141,
+	0xfd87fb54,
+	0xf65dfe59,
+	0x02eef99e,
+	0x0166f03c,
+	0xfff809b6,
+	0x000008a4,
+	0x000af42b,
+	0x00eff577,
+	0xfa840bf2,
+	0xfc02ff51,
+	0x08260f67,
+	0xfff0036f,
+	0x0842f9c3,
+	0x00000000,
+	0x063df7be,
+	0xfc910010,
+	0xf099f7da,
+	0x00af03fe,
+	0xf40e057c,
+	0x0a89ff11,
+	0x0bd5fff6,
+	0xf75c0000,
+	0xf64a0008,
+	0x0fc4fe9a,
+	0x0662fd12,
+	0x01a709a3,
+	0x04ac0279,
+	0xeebf004e,
+	0xff6300d0,
+	0xf9e4f9e4,
+	0x00d0ff63,
+	0x004eeebf,
+	0x027904ac,
+	0x09a301a7,
+	0xfd120662,
+	0xfe9a0fc4,
+	0x0008f64a,
+	0x0000f75c,
+	0xfff60bd5,
+	0xff110a89,
+	0x057cf40e,
+	0x03fe00af,
+	0xf7daf099,
+	0x0010fc91,
+	0xf7be063d,
+	0x00000000,
+	0xf9c30842,
+	0x036ffff0,
+	0x0f670826,
+	0xff51fc02,
+	0x0bf2fa84,
+	0xf57700ef,
+	0xf42b000a,
+	0x08a40000,
+	0x09b6fff8,
+	0xf03c0166,
+	0xf99e02ee,
+	0xfe59f65d,
+	0xfb54fd87,
+	0x1141ffb2,
+	0x009dff30,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0x05e30000,
+	0xff060705,
+	0x085408a0,
+	0xf425fc59,
+	0xfa1d042a,
+	0xfc78f67a,
+	0xf7acf60e,
+	0x075a0766,
+	0x05e305e3,
+	0xf8a6f89a,
+	0xf7acf60e,
+	0x03880986,
+	0xfa1d042a,
+	0x0bdb03a7,
+	0x085408a0,
+	0x00faf8fb,
+	0x05e30000,
+	0xff06f8fb,
+	0x0854f760,
+	0xf42503a7,
+	0xfa1dfbd6,
+	0xfc780986,
+	0xf7ac09f2,
+	0x075af89a,
+	0x05e3fa1d,
+	0xf8a60766,
+	0xf7ac09f2,
+	0x0388f67a,
+	0xfa1dfbd6,
+	0x0bdbfc59,
+	0x0854f760,
+	0x00fa0705,
+	0xfa58fa58,
+	0xf8f0fe00,
+	0x0448073d,
+	0xfdc9fe46,
+	0xf9910258,
+	0x089d0407,
+	0xfd5cf71a,
+	0x02affde0,
+	0x083e0496,
+	0xff5a0740,
+	0xff7afd97,
+	0x00fe01f1,
+	0x0009082e,
+	0xfa94ff75,
+	0xfecdf8ea,
+	0xffb0f693,
+	0xfd2cfa58,
+	0x0433ff16,
+	0xfba405dd,
+	0xfa610341,
+	0x06a606cb,
+	0x0039fd2d,
+	0x0677fa97,
+	0x01fa05e0,
+	0xf896003e,
+	0x075a068b,
+	0x012cfc3e,
+	0xfa23f98d,
+	0xfc7cfd43,
+	0xff90fc0d,
+	0x01c10982,
+	0x00c601d6,
+	0xfd2cfd2c,
+	0x01d600c6,
+	0x098201c1,
+	0xfc0dff90,
+	0xfd43fc7c,
+	0xf98dfa23,
+	0xfc3e012c,
+	0x068b075a,
+	0x003ef896,
+	0x05e001fa,
+	0xfa970677,
+	0xfd2d0039,
+	0x06cb06a6,
+	0x0341fa61,
+	0x05ddfba4,
+	0xff160433,
+	0xfa58fd2c,
+	0xf693ffb0,
+	0xf8eafecd,
+	0xff75fa94,
+	0x082e0009,
+	0x01f100fe,
+	0xfd97ff7a,
+	0x0740ff5a,
+	0x0496083e,
+	0xfde002af,
+	0xf71afd5c,
+	0x0407089d,
+	0x0258f991,
+	0xfe46fdc9,
+	0x073d0448,
+	0xfe00f8f0,
+	0xfd2cfd2c,
+	0xfce00500,
+	0xfc09fddc,
+	0xfe680157,
+	0x04c70571,
+	0xfc3aff21,
+	0xfcd70228,
+	0x056d0277,
+	0x0200fe00,
+	0x0022f927,
+	0xfe3c032b,
+	0xfc44ff3c,
+	0x03e9fbdb,
+	0x04570313,
+	0x04c9ff5c,
+	0x000d03b8,
+	0xfa580000,
+	0xfbe900d2,
+	0xf9d0fe0b,
+	0x0125fdf9,
+	0x042501bf,
+	0x0328fa2b,
+	0xffa902f0,
+	0xfa250157,
+	0x0200fe00,
+	0x03740438,
+	0xff0405fd,
+	0x030cfe52,
+	0x0037fb39,
+	0xff6904c5,
+	0x04f8fd23,
+	0xfd31fc1b,
+	0xfd2cfd2c,
+	0xfc1bfd31,
+	0xfd2304f8,
+	0x04c5ff69,
+	0xfb390037,
+	0xfe52030c,
+	0x05fdff04,
+	0x04380374,
+	0xfe000200,
+	0x0157fa25,
+	0x02f0ffa9,
+	0xfa2b0328,
+	0x01bf0425,
+	0xfdf90125,
+	0xfe0bf9d0,
+	0x00d2fbe9,
+	0x0000fa58,
+	0x03b8000d,
+	0xff5c04c9,
+	0x03130457,
+	0xfbdb03e9,
+	0xff3cfc44,
+	0x032bfe3c,
+	0xf9270022,
+	0xfe000200,
+	0x0277056d,
+	0x0228fcd7,
+	0xff21fc3a,
+	0x057104c7,
+	0x0157fe68,
+	0xfddcfc09,
+	0x0500fce0,
+	0xfd2cfd2c,
+	0x0500fce0,
+	0xfddcfc09,
+	0x0157fe68,
+	0x057104c7,
+	0xff21fc3a,
+	0x0228fcd7,
+	0x0277056d,
+	0xfe000200,
+	0xf9270022,
+	0x032bfe3c,
+	0xff3cfc44,
+	0xfbdb03e9,
+	0x03130457,
+	0xff5c04c9,
+	0x03b8000d,
+	0x0000fa58,
+	0x00d2fbe9,
+	0xfe0bf9d0,
+	0xfdf90125,
+	0x01bf0425,
+	0xfa2b0328,
+	0x02f0ffa9,
+	0x0157fa25,
+	0xfe000200,
+	0x04380374,
+	0x05fdff04,
+	0xfe52030c,
+	0xfb390037,
+	0x04c5ff69,
+	0xfd2304f8,
+	0xfc1bfd31,
+	0xfd2cfd2c,
+	0xfd31fc1b,
+	0x04f8fd23,
+	0xff6904c5,
+	0x0037fb39,
+	0x030cfe52,
+	0xff0405fd,
+	0x03740438,
+	0x0200fe00,
+	0xfa250157,
+	0xffa902f0,
+	0x0328fa2b,
+	0x042501bf,
+	0x0125fdf9,
+	0xf9d0fe0b,
+	0xfbe900d2,
+	0xfa580000,
+	0x000d03b8,
+	0x04c9ff5c,
+	0x04570313,
+	0x03e9fbdb,
+	0xfc44ff3c,
+	0xfe3c032b,
+	0x0022f927,
+	0x0200fe00,
+	0x056d0277,
+	0xfcd70228,
+	0xfc3aff21,
+	0x04c70571,
+	0xfe680157,
+	0xfc09fddc,
+	0xfce00500,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+	0x05a80000,
+	0xff1006be,
+	0x0800084a,
+	0xf49cfc7e,
+	0xfa580400,
+	0xfc9cf6da,
+	0xf800f672,
+	0x0710071c,
+	0x05a805a8,
+	0xf8f0f8e4,
+	0xf800f672,
+	0x03640926,
+	0xfa580400,
+	0x0b640382,
+	0x0800084a,
+	0x00f0f942,
+	0x05a80000,
+	0xff10f942,
+	0x0800f7b6,
+	0xf49c0382,
+	0xfa58fc00,
+	0xfc9c0926,
+	0xf800098e,
+	0x0710f8e4,
+	0x05a8fa58,
+	0xf8f0071c,
+	0xf800098e,
+	0x0364f6da,
+	0xfa58fc00,
+	0x0b64fc7e,
+	0x0800f7b6,
+	0x00f006be,
+};
+
+const u32 noise_var_tbl_rev3[] = {
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+	0x02110211,
+	0x0000014d,
+};
+
+const u16 mcs_tbl_rev3[] = {
+	0x0000,
+	0x0008,
+	0x000a,
+	0x0010,
+	0x0012,
+	0x0019,
+	0x001a,
+	0x001c,
+	0x0080,
+	0x0088,
+	0x008a,
+	0x0090,
+	0x0092,
+	0x0099,
+	0x009a,
+	0x009c,
+	0x0100,
+	0x0108,
+	0x010a,
+	0x0110,
+	0x0112,
+	0x0119,
+	0x011a,
+	0x011c,
+	0x0180,
+	0x0188,
+	0x018a,
+	0x0190,
+	0x0192,
+	0x0199,
+	0x019a,
+	0x019c,
+	0x0000,
+	0x0098,
+	0x00a0,
+	0x00a8,
+	0x009a,
+	0x00a2,
+	0x00aa,
+	0x0120,
+	0x0128,
+	0x0128,
+	0x0130,
+	0x0138,
+	0x0138,
+	0x0140,
+	0x0122,
+	0x012a,
+	0x012a,
+	0x0132,
+	0x013a,
+	0x013a,
+	0x0142,
+	0x01a8,
+	0x01b0,
+	0x01b8,
+	0x01b0,
+	0x01b8,
+	0x01c0,
+	0x01c8,
+	0x01c0,
+	0x01c8,
+	0x01d0,
+	0x01d0,
+	0x01d8,
+	0x01aa,
+	0x01b2,
+	0x01ba,
+	0x01b2,
+	0x01ba,
+	0x01c2,
+	0x01ca,
+	0x01c2,
+	0x01ca,
+	0x01d2,
+	0x01d2,
+	0x01da,
+	0x0001,
+	0x0002,
+	0x0004,
+	0x0009,
+	0x000c,
+	0x0011,
+	0x0014,
+	0x0018,
+	0x0020,
+	0x0021,
+	0x0022,
+	0x0024,
+	0x0081,
+	0x0082,
+	0x0084,
+	0x0089,
+	0x008c,
+	0x0091,
+	0x0094,
+	0x0098,
+	0x00a0,
+	0x00a1,
+	0x00a2,
+	0x00a4,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+	0x0007,
+};
+
+const u32 tdi_tbl20_ant0_rev3[] = {
+	0x00091226,
+	0x000a1429,
+	0x000b56ad,
+	0x000c58b0,
+	0x000d5ab3,
+	0x000e9cb6,
+	0x000f9eba,
+	0x0000c13d,
+	0x00020301,
+	0x00030504,
+	0x00040708,
+	0x0005090b,
+	0x00064b8e,
+	0x00095291,
+	0x000a5494,
+	0x000b9718,
+	0x000c9927,
+	0x000d9b2a,
+	0x000edd2e,
+	0x000fdf31,
+	0x000101b4,
+	0x000243b7,
+	0x000345bb,
+	0x000447be,
+	0x00058982,
+	0x00068c05,
+	0x00099309,
+	0x000a950c,
+	0x000bd78f,
+	0x000cd992,
+	0x000ddb96,
+	0x000f1d99,
+	0x00005fa8,
+	0x0001422c,
+	0x0002842f,
+	0x00038632,
+	0x00048835,
+	0x0005ca38,
+	0x0006ccbc,
+	0x0009d3bf,
+	0x000b1603,
+	0x000c1806,
+	0x000d1a0a,
+	0x000e1c0d,
+	0x000f5e10,
+	0x00008093,
+	0x00018297,
+	0x0002c49a,
+	0x0003c680,
+	0x0004c880,
+	0x00060b00,
+	0x00070d00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl20_ant1_rev3[] = {
+	0x00014b26,
+	0x00028d29,
+	0x000393ad,
+	0x00049630,
+	0x0005d833,
+	0x0006da36,
+	0x00099c3a,
+	0x000a9e3d,
+	0x000bc081,
+	0x000cc284,
+	0x000dc488,
+	0x000f068b,
+	0x0000488e,
+	0x00018b91,
+	0x0002d214,
+	0x0003d418,
+	0x0004d6a7,
+	0x000618aa,
+	0x00071aae,
+	0x0009dcb1,
+	0x000b1eb4,
+	0x000c0137,
+	0x000d033b,
+	0x000e053e,
+	0x000f4702,
+	0x00008905,
+	0x00020c09,
+	0x0003128c,
+	0x0004148f,
+	0x00051712,
+	0x00065916,
+	0x00091b19,
+	0x000a1d28,
+	0x000b5f2c,
+	0x000c41af,
+	0x000d43b2,
+	0x000e85b5,
+	0x000f87b8,
+	0x0000c9bc,
+	0x00024cbf,
+	0x00035303,
+	0x00045506,
+	0x0005978a,
+	0x0006998d,
+	0x00095b90,
+	0x000a5d93,
+	0x000b9f97,
+	0x000c821a,
+	0x000d8400,
+	0x000ec600,
+	0x000fc800,
+	0x00010a00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant0_rev3[] = {
+	0x0011a346,
+	0x00136ccf,
+	0x0014f5d9,
+	0x001641e2,
+	0x0017cb6b,
+	0x00195475,
+	0x001b2383,
+	0x001cad0c,
+	0x001e7616,
+	0x0000821f,
+	0x00020ba8,
+	0x0003d4b2,
+	0x00056447,
+	0x00072dd0,
+	0x0008b6da,
+	0x000a02e3,
+	0x000b8c6c,
+	0x000d15f6,
+	0x0011e484,
+	0x0013ae0d,
+	0x00153717,
+	0x00168320,
+	0x00180ca9,
+	0x00199633,
+	0x001b6548,
+	0x001ceed1,
+	0x001eb7db,
+	0x0000c3e4,
+	0x00024d6d,
+	0x000416f7,
+	0x0005a585,
+	0x00076f0f,
+	0x0008f818,
+	0x000a4421,
+	0x000bcdab,
+	0x000d9734,
+	0x00122649,
+	0x0013efd2,
+	0x001578dc,
+	0x0016c4e5,
+	0x00184e6e,
+	0x001a17f8,
+	0x001ba686,
+	0x001d3010,
+	0x001ef999,
+	0x00010522,
+	0x00028eac,
+	0x00045835,
+	0x0005e74a,
+	0x0007b0d3,
+	0x00093a5d,
+	0x000a85e6,
+	0x000c0f6f,
+	0x000dd8f9,
+	0x00126787,
+	0x00143111,
+	0x0015ba9a,
+	0x00170623,
+	0x00188fad,
+	0x001a5936,
+	0x001be84b,
+	0x001db1d4,
+	0x001f3b5e,
+	0x000146e7,
+	0x00031070,
+	0x000499fa,
+	0x00062888,
+	0x0007f212,
+	0x00097b9b,
+	0x000ac7a4,
+	0x000c50ae,
+	0x000e1a37,
+	0x0012a94c,
+	0x001472d5,
+	0x0015fc5f,
+	0x00174868,
+	0x0018d171,
+	0x001a9afb,
+	0x001c2989,
+	0x001df313,
+	0x001f7c9c,
+	0x000188a5,
+	0x000351af,
+	0x0004db38,
+	0x0006aa4d,
+	0x000833d7,
+	0x0009bd60,
+	0x000b0969,
+	0x000c9273,
+	0x000e5bfc,
+	0x00132a8a,
+	0x0014b414,
+	0x00163d9d,
+	0x001789a6,
+	0x001912b0,
+	0x001adc39,
+	0x001c6bce,
+	0x001e34d8,
+	0x001fbe61,
+	0x0001ca6a,
+	0x00039374,
+	0x00051cfd,
+	0x0006ec0b,
+	0x00087515,
+	0x0009fe9e,
+	0x000b4aa7,
+	0x000cd3b1,
+	0x000e9d3a,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 tdi_tbl40_ant1_rev3[] = {
+	0x001edb36,
+	0x000129ca,
+	0x0002b353,
+	0x00047cdd,
+	0x0005c8e6,
+	0x000791ef,
+	0x00091bf9,
+	0x000aaa07,
+	0x000c3391,
+	0x000dfd1a,
+	0x00120923,
+	0x0013d22d,
+	0x00155c37,
+	0x0016eacb,
+	0x00187454,
+	0x001a3dde,
+	0x001b89e7,
+	0x001d12f0,
+	0x001f1cfa,
+	0x00016b88,
+	0x00033492,
+	0x0004be1b,
+	0x00060a24,
+	0x0007d32e,
+	0x00095d38,
+	0x000aec4c,
+	0x000c7555,
+	0x000e3edf,
+	0x00124ae8,
+	0x001413f1,
+	0x0015a37b,
+	0x00172c89,
+	0x0018b593,
+	0x001a419c,
+	0x001bcb25,
+	0x001d942f,
+	0x001f63b9,
+	0x0001ad4d,
+	0x00037657,
+	0x0004c260,
+	0x00068be9,
+	0x000814f3,
+	0x0009a47c,
+	0x000b2d8a,
+	0x000cb694,
+	0x000e429d,
+	0x00128c26,
+	0x001455b0,
+	0x0015e4ba,
+	0x00176e4e,
+	0x0018f758,
+	0x001a8361,
+	0x001c0cea,
+	0x001dd674,
+	0x001fa57d,
+	0x0001ee8b,
+	0x0003b795,
+	0x0005039e,
+	0x0006cd27,
+	0x000856b1,
+	0x0009e5c6,
+	0x000b6f4f,
+	0x000cf859,
+	0x000e8462,
+	0x00130deb,
+	0x00149775,
+	0x00162603,
+	0x0017af8c,
+	0x00193896,
+	0x001ac49f,
+	0x001c4e28,
+	0x001e17b2,
+	0x0000a6c7,
+	0x00023050,
+	0x0003f9da,
+	0x00054563,
+	0x00070eec,
+	0x00089876,
+	0x000a2704,
+	0x000bb08d,
+	0x000d3a17,
+	0x001185a0,
+	0x00134f29,
+	0x0014d8b3,
+	0x001667c8,
+	0x0017f151,
+	0x00197adb,
+	0x001b0664,
+	0x001c8fed,
+	0x001e5977,
+	0x0000e805,
+	0x0002718f,
+	0x00043b18,
+	0x000586a1,
+	0x0007502b,
+	0x0008d9b4,
+	0x000a68c9,
+	0x000bf252,
+	0x000dbbdc,
+	0x0011c7e5,
+	0x001390ee,
+	0x00151a78,
+	0x0016a906,
+	0x00183290,
+	0x0019bc19,
+	0x001b4822,
+	0x001cd12c,
+	0x001e9ab5,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 pltlut_tbl_rev3[] = {
+	0x76540213,
+	0x62407351,
+	0x76543210,
+	0x76540213,
+	0x76540213,
+	0x76430521,
+};
+
+const u32 chanest_tbl_rev3[] = {
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x44444444,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+	0x10101010,
+};
+
+const u8 frame_lut_rev3[] = {
+	0x02,
+	0x04,
+	0x14,
+	0x14,
+	0x03,
+	0x05,
+	0x16,
+	0x16,
+	0x0a,
+	0x0c,
+	0x1c,
+	0x1c,
+	0x0b,
+	0x0d,
+	0x1e,
+	0x1e,
+	0x06,
+	0x08,
+	0x18,
+	0x18,
+	0x07,
+	0x09,
+	0x1a,
+	0x1a,
+	0x0e,
+	0x10,
+	0x20,
+	0x28,
+	0x0f,
+	0x11,
+	0x22,
+	0x2a,
+};
+
+const u8 est_pwr_lut_core0_rev3[] = {
+	0x55,
+	0x54,
+	0x54,
+	0x53,
+	0x52,
+	0x52,
+	0x51,
+	0x51,
+	0x50,
+	0x4f,
+	0x4f,
+	0x4e,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x33,
+	0x32,
+	0x31,
+	0x2f,
+	0x2e,
+	0x2c,
+	0x2b,
+	0x29,
+	0x27,
+	0x25,
+	0x23,
+	0x21,
+	0x1f,
+	0x1d,
+	0x1a,
+	0x18,
+	0x15,
+	0x12,
+	0x0e,
+	0x0b,
+	0x07,
+	0x02,
+	0xfd,
+};
+
+const u8 est_pwr_lut_core1_rev3[] = {
+	0x55,
+	0x54,
+	0x54,
+	0x53,
+	0x52,
+	0x52,
+	0x51,
+	0x51,
+	0x50,
+	0x4f,
+	0x4f,
+	0x4e,
+	0x4e,
+	0x4d,
+	0x4c,
+	0x4c,
+	0x4b,
+	0x4a,
+	0x49,
+	0x49,
+	0x48,
+	0x47,
+	0x46,
+	0x46,
+	0x45,
+	0x44,
+	0x43,
+	0x42,
+	0x41,
+	0x40,
+	0x40,
+	0x3f,
+	0x3e,
+	0x3d,
+	0x3c,
+	0x3a,
+	0x39,
+	0x38,
+	0x37,
+	0x36,
+	0x35,
+	0x33,
+	0x32,
+	0x31,
+	0x2f,
+	0x2e,
+	0x2c,
+	0x2b,
+	0x29,
+	0x27,
+	0x25,
+	0x23,
+	0x21,
+	0x1f,
+	0x1d,
+	0x1a,
+	0x18,
+	0x15,
+	0x12,
+	0x0e,
+	0x0b,
+	0x07,
+	0x02,
+	0xfd,
+};
+
+const u8 adj_pwr_lut_core0_rev3[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u8 adj_pwr_lut_core1_rev3[] = {
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+	0x00,
+};
+
+const u32 gainctrl_lut_core0_rev3[] = {
+	0x5bf70044,
+	0x5bf70042,
+	0x5bf70040,
+	0x5bf7003e,
+	0x5bf7003c,
+	0x5bf7003b,
+	0x5bf70039,
+	0x5bf70037,
+	0x5bf70036,
+	0x5bf70034,
+	0x5bf70033,
+	0x5bf70031,
+	0x5bf70030,
+	0x5ba70044,
+	0x5ba70042,
+	0x5ba70040,
+	0x5ba7003e,
+	0x5ba7003c,
+	0x5ba7003b,
+	0x5ba70039,
+	0x5ba70037,
+	0x5ba70036,
+	0x5ba70034,
+	0x5ba70033,
+	0x5b770044,
+	0x5b770042,
+	0x5b770040,
+	0x5b77003e,
+	0x5b77003c,
+	0x5b77003b,
+	0x5b770039,
+	0x5b770037,
+	0x5b770036,
+	0x5b770034,
+	0x5b770033,
+	0x5b770031,
+	0x5b770030,
+	0x5b77002f,
+	0x5b77002d,
+	0x5b77002c,
+	0x5b470044,
+	0x5b470042,
+	0x5b470040,
+	0x5b47003e,
+	0x5b47003c,
+	0x5b47003b,
+	0x5b470039,
+	0x5b470037,
+	0x5b470036,
+	0x5b470034,
+	0x5b470033,
+	0x5b470031,
+	0x5b470030,
+	0x5b47002f,
+	0x5b47002d,
+	0x5b47002c,
+	0x5b47002b,
+	0x5b47002a,
+	0x5b270044,
+	0x5b270042,
+	0x5b270040,
+	0x5b27003e,
+	0x5b27003c,
+	0x5b27003b,
+	0x5b270039,
+	0x5b270037,
+	0x5b270036,
+	0x5b270034,
+	0x5b270033,
+	0x5b270031,
+	0x5b270030,
+	0x5b27002f,
+	0x5b170044,
+	0x5b170042,
+	0x5b170040,
+	0x5b17003e,
+	0x5b17003c,
+	0x5b17003b,
+	0x5b170039,
+	0x5b170037,
+	0x5b170036,
+	0x5b170034,
+	0x5b170033,
+	0x5b170031,
+	0x5b170030,
+	0x5b17002f,
+	0x5b17002d,
+	0x5b17002c,
+	0x5b17002b,
+	0x5b17002a,
+	0x5b170028,
+	0x5b170027,
+	0x5b170026,
+	0x5b170025,
+	0x5b170024,
+	0x5b170023,
+	0x5b070044,
+	0x5b070042,
+	0x5b070040,
+	0x5b07003e,
+	0x5b07003c,
+	0x5b07003b,
+	0x5b070039,
+	0x5b070037,
+	0x5b070036,
+	0x5b070034,
+	0x5b070033,
+	0x5b070031,
+	0x5b070030,
+	0x5b07002f,
+	0x5b07002d,
+	0x5b07002c,
+	0x5b07002b,
+	0x5b07002a,
+	0x5b070028,
+	0x5b070027,
+	0x5b070026,
+	0x5b070025,
+	0x5b070024,
+	0x5b070023,
+	0x5b070022,
+	0x5b070021,
+	0x5b070020,
+	0x5b07001f,
+	0x5b07001e,
+	0x5b07001d,
+	0x5b07001d,
+	0x5b07001c,
+};
+
+const u32 gainctrl_lut_core1_rev3[] = {
+	0x5bf70044,
+	0x5bf70042,
+	0x5bf70040,
+	0x5bf7003e,
+	0x5bf7003c,
+	0x5bf7003b,
+	0x5bf70039,
+	0x5bf70037,
+	0x5bf70036,
+	0x5bf70034,
+	0x5bf70033,
+	0x5bf70031,
+	0x5bf70030,
+	0x5ba70044,
+	0x5ba70042,
+	0x5ba70040,
+	0x5ba7003e,
+	0x5ba7003c,
+	0x5ba7003b,
+	0x5ba70039,
+	0x5ba70037,
+	0x5ba70036,
+	0x5ba70034,
+	0x5ba70033,
+	0x5b770044,
+	0x5b770042,
+	0x5b770040,
+	0x5b77003e,
+	0x5b77003c,
+	0x5b77003b,
+	0x5b770039,
+	0x5b770037,
+	0x5b770036,
+	0x5b770034,
+	0x5b770033,
+	0x5b770031,
+	0x5b770030,
+	0x5b77002f,
+	0x5b77002d,
+	0x5b77002c,
+	0x5b470044,
+	0x5b470042,
+	0x5b470040,
+	0x5b47003e,
+	0x5b47003c,
+	0x5b47003b,
+	0x5b470039,
+	0x5b470037,
+	0x5b470036,
+	0x5b470034,
+	0x5b470033,
+	0x5b470031,
+	0x5b470030,
+	0x5b47002f,
+	0x5b47002d,
+	0x5b47002c,
+	0x5b47002b,
+	0x5b47002a,
+	0x5b270044,
+	0x5b270042,
+	0x5b270040,
+	0x5b27003e,
+	0x5b27003c,
+	0x5b27003b,
+	0x5b270039,
+	0x5b270037,
+	0x5b270036,
+	0x5b270034,
+	0x5b270033,
+	0x5b270031,
+	0x5b270030,
+	0x5b27002f,
+	0x5b170044,
+	0x5b170042,
+	0x5b170040,
+	0x5b17003e,
+	0x5b17003c,
+	0x5b17003b,
+	0x5b170039,
+	0x5b170037,
+	0x5b170036,
+	0x5b170034,
+	0x5b170033,
+	0x5b170031,
+	0x5b170030,
+	0x5b17002f,
+	0x5b17002d,
+	0x5b17002c,
+	0x5b17002b,
+	0x5b17002a,
+	0x5b170028,
+	0x5b170027,
+	0x5b170026,
+	0x5b170025,
+	0x5b170024,
+	0x5b170023,
+	0x5b070044,
+	0x5b070042,
+	0x5b070040,
+	0x5b07003e,
+	0x5b07003c,
+	0x5b07003b,
+	0x5b070039,
+	0x5b070037,
+	0x5b070036,
+	0x5b070034,
+	0x5b070033,
+	0x5b070031,
+	0x5b070030,
+	0x5b07002f,
+	0x5b07002d,
+	0x5b07002c,
+	0x5b07002b,
+	0x5b07002a,
+	0x5b070028,
+	0x5b070027,
+	0x5b070026,
+	0x5b070025,
+	0x5b070024,
+	0x5b070023,
+	0x5b070022,
+	0x5b070021,
+	0x5b070020,
+	0x5b07001f,
+	0x5b07001e,
+	0x5b07001d,
+	0x5b07001d,
+	0x5b07001c,
+};
+
+const u32 iq_lut_core0_rev3[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 iq_lut_core1_rev3[] = {
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u16 loft_lut_core0_rev3[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 loft_lut_core1_rev3[] = {
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+	0x0000,
+};
+
+const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+};
+
+const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x0036,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x002a,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x001e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x000e,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01fc,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01ee,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+	0x01d6,
+};
+
+const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
+	0x00000000,
+	0x00001fa0,
+	0x00019f78,
+	0x0001df7e,
+	0x03fa9f86,
+	0x03fd1f90,
+	0x03fe5f8a,
+	0x03fb1f94,
+	0x03fd9fa0,
+	0x00009f98,
+	0x03fd1fac,
+	0x03ff9fa2,
+	0x03fe9fae,
+	0x00001fae,
+	0x03fddfb4,
+	0x03ff1fb8,
+	0x03ff9fbc,
+	0x03ffdfbe,
+	0x03fe9fc2,
+	0x03fedfc6,
+	0x03fedfc6,
+	0x03ff9fc8,
+	0x03ff5fc6,
+	0x03fedfc2,
+	0x03ff9fc0,
+	0x03ff5fac,
+	0x03ff5fac,
+	0x03ff9fa2,
+	0x03ff9fa6,
+	0x03ff9faa,
+	0x03ff5fb0,
+	0x03ff5fb4,
+	0x03ff1fca,
+	0x03ff5fce,
+	0x03fcdfdc,
+	0x03fb4006,
+	0x00000030,
+	0x03ff808a,
+	0x03ff80da,
+	0x0000016c,
+	0x03ff8318,
+	0x03ff063a,
+	0x03fd8bd6,
+	0x00014ffe,
+	0x00034ffe,
+	0x00034ffe,
+	0x0003cffe,
+	0x00040ffe,
+	0x00040ffe,
+	0x0003cffe,
+	0x0003cffe,
+	0x00020ffe,
+	0x03fe0ffe,
+	0x03fdcffe,
+	0x03f94ffe,
+	0x03f54ffe,
+	0x03f44ffe,
+	0x03ef8ffe,
+	0x03ee0ffe,
+	0x03ebcffe,
+	0x03e8cffe,
+	0x03e74ffe,
+	0x03e4cffe,
+	0x03e38ffe,
+};
+
+const u32 papd_cal_scalars_tbl_core0_rev3[] = {
+	0x05af005a,
+	0x0571005e,
+	0x05040066,
+	0x04bd006c,
+	0x047d0072,
+	0x04430078,
+	0x03f70081,
+	0x03cb0087,
+	0x03870091,
+	0x035e0098,
+	0x032e00a1,
+	0x030300aa,
+	0x02d800b4,
+	0x02ae00bf,
+	0x028900ca,
+	0x026400d6,
+	0x024100e3,
+	0x022200f0,
+	0x020200ff,
+	0x01e5010e,
+	0x01ca011e,
+	0x01b0012f,
+	0x01990140,
+	0x01830153,
+	0x016c0168,
+	0x0158017d,
+	0x01450193,
+	0x013301ab,
+	0x012101c5,
+	0x011101e0,
+	0x010201fc,
+	0x00f4021a,
+	0x00e6011d,
+	0x00d9012e,
+	0x00cd0140,
+	0x00c20153,
+	0x00b70167,
+	0x00ac017c,
+	0x00a30193,
+	0x009a01ab,
+	0x009101c4,
+	0x008901df,
+	0x008101fb,
+	0x007a0219,
+	0x00730239,
+	0x006d025b,
+	0x0067027e,
+	0x006102a4,
+	0x005c02cc,
+	0x005602f6,
+	0x00520323,
+	0x004d0353,
+	0x00490385,
+	0x004503bb,
+	0x004103f3,
+	0x003d042f,
+	0x003a046f,
+	0x003704b2,
+	0x003404f9,
+	0x00310545,
+	0x002e0596,
+	0x002b05f5,
+	0x00290640,
+	0x002606a4,
+};
+
+const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
+	0x00000000,
+	0x00001fa0,
+	0x00019f78,
+	0x0001df7e,
+	0x03fa9f86,
+	0x03fd1f90,
+	0x03fe5f8a,
+	0x03fb1f94,
+	0x03fd9fa0,
+	0x00009f98,
+	0x03fd1fac,
+	0x03ff9fa2,
+	0x03fe9fae,
+	0x00001fae,
+	0x03fddfb4,
+	0x03ff1fb8,
+	0x03ff9fbc,
+	0x03ffdfbe,
+	0x03fe9fc2,
+	0x03fedfc6,
+	0x03fedfc6,
+	0x03ff9fc8,
+	0x03ff5fc6,
+	0x03fedfc2,
+	0x03ff9fc0,
+	0x03ff5fac,
+	0x03ff5fac,
+	0x03ff9fa2,
+	0x03ff9fa6,
+	0x03ff9faa,
+	0x03ff5fb0,
+	0x03ff5fb4,
+	0x03ff1fca,
+	0x03ff5fce,
+	0x03fcdfdc,
+	0x03fb4006,
+	0x00000030,
+	0x03ff808a,
+	0x03ff80da,
+	0x0000016c,
+	0x03ff8318,
+	0x03ff063a,
+	0x03fd8bd6,
+	0x00014ffe,
+	0x00034ffe,
+	0x00034ffe,
+	0x0003cffe,
+	0x00040ffe,
+	0x00040ffe,
+	0x0003cffe,
+	0x0003cffe,
+	0x00020ffe,
+	0x03fe0ffe,
+	0x03fdcffe,
+	0x03f94ffe,
+	0x03f54ffe,
+	0x03f44ffe,
+	0x03ef8ffe,
+	0x03ee0ffe,
+	0x03ebcffe,
+	0x03e8cffe,
+	0x03e74ffe,
+	0x03e4cffe,
+	0x03e38ffe,
+};
+
+const u32 papd_cal_scalars_tbl_core1_rev3[] = {
+	0x05af005a,
+	0x0571005e,
+	0x05040066,
+	0x04bd006c,
+	0x047d0072,
+	0x04430078,
+	0x03f70081,
+	0x03cb0087,
+	0x03870091,
+	0x035e0098,
+	0x032e00a1,
+	0x030300aa,
+	0x02d800b4,
+	0x02ae00bf,
+	0x028900ca,
+	0x026400d6,
+	0x024100e3,
+	0x022200f0,
+	0x020200ff,
+	0x01e5010e,
+	0x01ca011e,
+	0x01b0012f,
+	0x01990140,
+	0x01830153,
+	0x016c0168,
+	0x0158017d,
+	0x01450193,
+	0x013301ab,
+	0x012101c5,
+	0x011101e0,
+	0x010201fc,
+	0x00f4021a,
+	0x00e6011d,
+	0x00d9012e,
+	0x00cd0140,
+	0x00c20153,
+	0x00b70167,
+	0x00ac017c,
+	0x00a30193,
+	0x009a01ab,
+	0x009101c4,
+	0x008901df,
+	0x008101fb,
+	0x007a0219,
+	0x00730239,
+	0x006d025b,
+	0x0067027e,
+	0x006102a4,
+	0x005c02cc,
+	0x005602f6,
+	0x00520323,
+	0x004d0353,
+	0x00490385,
+	0x004503bb,
+	0x004103f3,
+	0x003d042f,
+	0x003a046f,
+	0x003704b2,
+	0x003404f9,
+	0x00310545,
+	0x002e0596,
+	0x002b05f5,
+	0x00290640,
+	0x002606a4,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev3_volatile[] = {
+	{&ant_swctrl_tbl_rev3,
+	 sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16}
+	,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev3_volatile1[] = {
+	{&ant_swctrl_tbl_rev3_1,
+	 sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0,
+	 16}
+	,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev3_volatile2[] = {
+	{&ant_swctrl_tbl_rev3_2,
+	 sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0,
+	 16}
+	,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev3_volatile3[] = {
+	{&ant_swctrl_tbl_rev3_3,
+	 sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0,
+	 16}
+	,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev3[] = {
+	{&frame_struct_rev3,
+	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
+	,
+	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
+	 11, 0, 16}
+	,
+	{&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12,
+	 0, 32}
+	,
+	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
+	 13, 0, 32}
+	,
+	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
+	 14, 0, 32}
+	,
+	{&noise_var_tbl_rev3,
+	 sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32}
+	,
+	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
+	 16}
+	,
+	{&tdi_tbl20_ant0_rev3,
+	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
+	 32}
+	,
+	{&tdi_tbl20_ant1_rev3,
+	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
+	 32}
+	,
+	{&tdi_tbl40_ant0_rev3,
+	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
+	 32}
+	,
+	{&tdi_tbl40_ant1_rev3,
+	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
+	 32}
+	,
+	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
+	 20, 0, 32}
+	,
+	{&chanest_tbl_rev3,
+	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
+	,
+	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
+	 24, 0, 8}
+	,
+	{&est_pwr_lut_core0_rev3,
+	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev3,
+	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev3,
+	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev3,
+	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
+	 64, 8}
+	,
+	{&gainctrl_lut_core0_rev3,
+	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev3,
+	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
+	 27, 192, 32}
+	,
+	{&iq_lut_core0_rev3,
+	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev3,
+	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev3,
+	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev3,
+	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
+	 16}
+};
+
+const u32 mimophytbl_info_sz_rev3 =
+    sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]);
+const u32 mimophytbl_info_sz_rev3_volatile =
+    sizeof(mimophytbl_info_rev3_volatile) /
+    sizeof(mimophytbl_info_rev3_volatile[0]);
+const u32 mimophytbl_info_sz_rev3_volatile1 =
+    sizeof(mimophytbl_info_rev3_volatile1) /
+    sizeof(mimophytbl_info_rev3_volatile1[0]);
+const u32 mimophytbl_info_sz_rev3_volatile2 =
+    sizeof(mimophytbl_info_rev3_volatile2) /
+    sizeof(mimophytbl_info_rev3_volatile2[0]);
+const u32 mimophytbl_info_sz_rev3_volatile3 =
+    sizeof(mimophytbl_info_rev3_volatile3) /
+    sizeof(mimophytbl_info_rev3_volatile3[0]);
+
+const u32 tmap_tbl_rev7[] = {
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00011111,
+	0x11110000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00088aaa,
+	0xaaaa0000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xaaa8aaa0,
+	0x8aaa8aaa,
+	0xaa8a8a8a,
+	0x000aaa88,
+	0x8aaa0000,
+	0xaaa8a888,
+	0x8aa88a8a,
+	0x8a88a888,
+	0x08080a00,
+	0x0a08080a,
+	0x080a0a08,
+	0x00080808,
+	0x080a0000,
+	0x080a0808,
+	0x080a0808,
+	0x0a0a0a08,
+	0xa0a0a0a0,
+	0x80a0a080,
+	0x8080a0a0,
+	0x00008080,
+	0x80a00000,
+	0x80a080a0,
+	0xa080a0a0,
+	0x8080a0a0,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x99999000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x22000000,
+	0x2222b222,
+	0x22222222,
+	0x222222b2,
+	0xb2222220,
+	0x22222222,
+	0x22d22222,
+	0x00000222,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x33000000,
+	0x3333b333,
+	0x33333333,
+	0x333333b3,
+	0xb3333330,
+	0x33333333,
+	0x33d33333,
+	0x00000333,
+	0x22000000,
+	0x2222a222,
+	0x22222222,
+	0x222222a2,
+	0xa2222220,
+	0x22222222,
+	0x22c22222,
+	0x00000222,
+	0x99b99b00,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb99,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x22222200,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0x22222222,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x11111111,
+	0xf1111111,
+	0x11111111,
+	0x11f11111,
+	0x01111111,
+	0xbb9bb900,
+	0xb9b9bb99,
+	0xb99bbbbb,
+	0xbbbb9b9b,
+	0xb9bb99bb,
+	0xb99999b9,
+	0xb9b9b99b,
+	0x00000bbb,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88aa,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x0a888aaa,
+	0xaa000000,
+	0xa8a8aa88,
+	0xa88aaaaa,
+	0xaaaa8a8a,
+	0xa8aa88a0,
+	0xa88888a8,
+	0xa8a8a88a,
+	0x00000aaa,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0xbbbbbb00,
+	0x999bbbbb,
+	0x9bb99b9b,
+	0xb9b9b9bb,
+	0xb9b99bbb,
+	0xb9b9b9bb,
+	0xb9bb9b99,
+	0x00000999,
+	0x8a000000,
+	0xaa88a888,
+	0xa88888aa,
+	0xa88a8a88,
+	0xa88aa88a,
+	0x88a8aaaa,
+	0xa8aa8aaa,
+	0x0888a88a,
+	0x0b0b0b00,
+	0x090b0b0b,
+	0x0b090b0b,
+	0x0909090b,
+	0x09090b0b,
+	0x09090b0b,
+	0x09090b09,
+	0x00000909,
+	0x0a000000,
+	0x0a080808,
+	0x080a080a,
+	0x080a0a08,
+	0x080a080a,
+	0x0808080a,
+	0x0a0a0a08,
+	0x0808080a,
+	0xb0b0b000,
+	0x9090b0b0,
+	0x90b09090,
+	0xb0b0b090,
+	0xb0b090b0,
+	0x90b0b0b0,
+	0xb0b09090,
+	0x00000090,
+	0x80000000,
+	0xa080a080,
+	0xa08080a0,
+	0xa0808080,
+	0xa080a080,
+	0x80a0a0a0,
+	0xa0a080a0,
+	0x00a0a0a0,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x11000000,
+	0x1111f111,
+	0x11111111,
+	0x111111f1,
+	0xf1111110,
+	0x11111111,
+	0x11f11111,
+	0x00000111,
+	0x33000000,
+	0x3333f333,
+	0x33333333,
+	0x333333f3,
+	0xf3333330,
+	0x33333333,
+	0x33f33333,
+	0x00000333,
+	0x22000000,
+	0x2222f222,
+	0x22222222,
+	0x222222f2,
+	0xf2222220,
+	0x22222222,
+	0x22f22222,
+	0x00000222,
+	0x99000000,
+	0x9b9b99bb,
+	0x9bb99999,
+	0x9999b9b9,
+	0x9b99bb90,
+	0x9bbbbb9b,
+	0x9b9b9bb9,
+	0x00000999,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88888000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00aaa888,
+	0x88a88a00,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x000aa888,
+	0x88880000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa88,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x08aaa888,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x11000000,
+	0x1111a111,
+	0x11111111,
+	0x111111a1,
+	0xa1111110,
+	0x11111111,
+	0x11c11111,
+	0x00000111,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x88000000,
+	0x8a8a88aa,
+	0x8aa88888,
+	0x8888a8a8,
+	0x8a88aa80,
+	0x8aaaaa8a,
+	0x8a8a8aa8,
+	0x00000888,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+};
+
+const u32 noise_var_tbl_rev7[] = {
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+	0x020c020c,
+	0x0000014d,
+};
+
+const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
+	0x00000000,
+	0x00000000,
+	0x00016023,
+	0x00006028,
+	0x00034036,
+	0x0003402e,
+	0x0007203c,
+	0x0006e037,
+	0x00070030,
+	0x0009401f,
+	0x0009a00f,
+	0x000b600d,
+	0x000c8007,
+	0x000ce007,
+	0x00101fff,
+	0x00121ff9,
+	0x0012e004,
+	0x0014dffc,
+	0x0016dff6,
+	0x0018dfe9,
+	0x001b3fe5,
+	0x001c5fd0,
+	0x001ddfc2,
+	0x001f1fb6,
+	0x00207fa4,
+	0x00219f8f,
+	0x0022ff7d,
+	0x00247f6c,
+	0x0024df5b,
+	0x00267f4b,
+	0x0027df3b,
+	0x0029bf3b,
+	0x002b5f2f,
+	0x002d3f2e,
+	0x002f5f2a,
+	0x002fff15,
+	0x00315f0b,
+	0x0032defa,
+	0x0033beeb,
+	0x0034fed9,
+	0x00353ec5,
+	0x00361eb0,
+	0x00363e9b,
+	0x0036be87,
+	0x0036be70,
+	0x0038fe67,
+	0x0044beb2,
+	0x00513ef3,
+	0x00595f11,
+	0x00669f3d,
+	0x0078dfdf,
+	0x00a143aa,
+	0x01642fff,
+	0x0162afff,
+	0x01620fff,
+	0x0160cfff,
+	0x015f0fff,
+	0x015dafff,
+	0x015bcfff,
+	0x015bcfff,
+	0x015b4fff,
+	0x015acfff,
+	0x01590fff,
+	0x0156cfff,
+};
+
+const u32 papd_cal_scalars_tbl_core0_rev7[] = {
+	0x0b5e002d,
+	0x0ae2002f,
+	0x0a3b0032,
+	0x09a70035,
+	0x09220038,
+	0x08ab003b,
+	0x081f003f,
+	0x07a20043,
+	0x07340047,
+	0x06d2004b,
+	0x067a004f,
+	0x06170054,
+	0x05bf0059,
+	0x0571005e,
+	0x051e0064,
+	0x04d3006a,
+	0x04910070,
+	0x044c0077,
+	0x040f007e,
+	0x03d90085,
+	0x03a1008d,
+	0x036f0095,
+	0x033d009e,
+	0x030b00a8,
+	0x02e000b2,
+	0x02b900bc,
+	0x029200c7,
+	0x026d00d3,
+	0x024900e0,
+	0x022900ed,
+	0x020a00fb,
+	0x01ec010a,
+	0x01d20119,
+	0x01b7012a,
+	0x019e013c,
+	0x0188014e,
+	0x01720162,
+	0x015d0177,
+	0x0149018e,
+	0x013701a5,
+	0x012601be,
+	0x011501d8,
+	0x010601f4,
+	0x00f70212,
+	0x00e90231,
+	0x00dc0253,
+	0x00d00276,
+	0x00c4029b,
+	0x00b902c3,
+	0x00af02ed,
+	0x00a50319,
+	0x009c0348,
+	0x0093037a,
+	0x008b03af,
+	0x008303e6,
+	0x007c0422,
+	0x00750460,
+	0x006e04a3,
+	0x006804e9,
+	0x00620533,
+	0x005d0582,
+	0x005805d6,
+	0x0053062e,
+	0x004e068c,
+};
+
+const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
+	0x00000000,
+	0x00000000,
+	0x00016023,
+	0x00006028,
+	0x00034036,
+	0x0003402e,
+	0x0007203c,
+	0x0006e037,
+	0x00070030,
+	0x0009401f,
+	0x0009a00f,
+	0x000b600d,
+	0x000c8007,
+	0x000ce007,
+	0x00101fff,
+	0x00121ff9,
+	0x0012e004,
+	0x0014dffc,
+	0x0016dff6,
+	0x0018dfe9,
+	0x001b3fe5,
+	0x001c5fd0,
+	0x001ddfc2,
+	0x001f1fb6,
+	0x00207fa4,
+	0x00219f8f,
+	0x0022ff7d,
+	0x00247f6c,
+	0x0024df5b,
+	0x00267f4b,
+	0x0027df3b,
+	0x0029bf3b,
+	0x002b5f2f,
+	0x002d3f2e,
+	0x002f5f2a,
+	0x002fff15,
+	0x00315f0b,
+	0x0032defa,
+	0x0033beeb,
+	0x0034fed9,
+	0x00353ec5,
+	0x00361eb0,
+	0x00363e9b,
+	0x0036be87,
+	0x0036be70,
+	0x0038fe67,
+	0x0044beb2,
+	0x00513ef3,
+	0x00595f11,
+	0x00669f3d,
+	0x0078dfdf,
+	0x00a143aa,
+	0x01642fff,
+	0x0162afff,
+	0x01620fff,
+	0x0160cfff,
+	0x015f0fff,
+	0x015dafff,
+	0x015bcfff,
+	0x015bcfff,
+	0x015b4fff,
+	0x015acfff,
+	0x01590fff,
+	0x0156cfff,
+};
+
+const u32 papd_cal_scalars_tbl_core1_rev7[] = {
+	0x0b5e002d,
+	0x0ae2002f,
+	0x0a3b0032,
+	0x09a70035,
+	0x09220038,
+	0x08ab003b,
+	0x081f003f,
+	0x07a20043,
+	0x07340047,
+	0x06d2004b,
+	0x067a004f,
+	0x06170054,
+	0x05bf0059,
+	0x0571005e,
+	0x051e0064,
+	0x04d3006a,
+	0x04910070,
+	0x044c0077,
+	0x040f007e,
+	0x03d90085,
+	0x03a1008d,
+	0x036f0095,
+	0x033d009e,
+	0x030b00a8,
+	0x02e000b2,
+	0x02b900bc,
+	0x029200c7,
+	0x026d00d3,
+	0x024900e0,
+	0x022900ed,
+	0x020a00fb,
+	0x01ec010a,
+	0x01d20119,
+	0x01b7012a,
+	0x019e013c,
+	0x0188014e,
+	0x01720162,
+	0x015d0177,
+	0x0149018e,
+	0x013701a5,
+	0x012601be,
+	0x011501d8,
+	0x010601f4,
+	0x00f70212,
+	0x00e90231,
+	0x00dc0253,
+	0x00d00276,
+	0x00c4029b,
+	0x00b902c3,
+	0x00af02ed,
+	0x00a50319,
+	0x009c0348,
+	0x0093037a,
+	0x008b03af,
+	0x008303e6,
+	0x007c0422,
+	0x00750460,
+	0x006e04a3,
+	0x006804e9,
+	0x00620533,
+	0x005d0582,
+	0x005805d6,
+	0x0053062e,
+	0x004e068c,
+};
+
+const mimophytbl_info_t mimophytbl_info_rev7[] = {
+	{&frame_struct_rev3,
+	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
+	,
+	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
+	 11, 0, 16}
+	,
+	{&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12,
+	 0, 32}
+	,
+	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
+	 13, 0, 32}
+	,
+	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
+	 14, 0, 32}
+	,
+	{&noise_var_tbl_rev7,
+	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
+	,
+	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
+	 16}
+	,
+	{&tdi_tbl20_ant0_rev3,
+	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
+	 32}
+	,
+	{&tdi_tbl20_ant1_rev3,
+	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
+	 32}
+	,
+	{&tdi_tbl40_ant0_rev3,
+	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
+	 32}
+	,
+	{&tdi_tbl40_ant1_rev3,
+	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
+	 32}
+	,
+	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
+	 20, 0, 32}
+	,
+	{&chanest_tbl_rev3,
+	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
+	,
+	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
+	 24, 0, 8}
+	,
+	{&est_pwr_lut_core0_rev3,
+	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev3,
+	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev3,
+	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev3,
+	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
+	 64, 8}
+	,
+	{&gainctrl_lut_core0_rev3,
+	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev3,
+	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
+	 27, 192, 32}
+	,
+	{&iq_lut_core0_rev3,
+	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev3,
+	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev3,
+	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev3,
+	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
+	 16}
+	,
+	{&papd_comp_rfpwr_tbl_core0_rev3,
+	 sizeof(papd_comp_rfpwr_tbl_core0_rev3) /
+	 sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16}
+	,
+	{&papd_comp_rfpwr_tbl_core1_rev3,
+	 sizeof(papd_comp_rfpwr_tbl_core1_rev3) /
+	 sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16}
+	,
+	{&papd_comp_epsilon_tbl_core0_rev7,
+	 sizeof(papd_comp_epsilon_tbl_core0_rev7) /
+	 sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32}
+	,
+	{&papd_cal_scalars_tbl_core0_rev7,
+	 sizeof(papd_cal_scalars_tbl_core0_rev7) /
+	 sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32}
+	,
+	{&papd_comp_epsilon_tbl_core1_rev7,
+	 sizeof(papd_comp_epsilon_tbl_core1_rev7) /
+	 sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32}
+	,
+	{&papd_cal_scalars_tbl_core1_rev7,
+	 sizeof(papd_cal_scalars_tbl_core1_rev7) /
+	 sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32}
+	,
+};
+
+const u32 mimophytbl_info_sz_rev7 =
+    sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]);
+
+const mimophytbl_info_t mimophytbl_info_rev16[] = {
+	{&noise_var_tbl_rev7,
+	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
+	,
+	{&est_pwr_lut_core0_rev3,
+	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
+	 0, 8}
+	,
+	{&est_pwr_lut_core1_rev3,
+	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
+	 0, 8}
+	,
+	{&adj_pwr_lut_core0_rev3,
+	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
+	 64, 8}
+	,
+	{&adj_pwr_lut_core1_rev3,
+	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
+	 64, 8}
+	,
+	{&gainctrl_lut_core0_rev3,
+	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
+	 26, 192, 32}
+	,
+	{&gainctrl_lut_core1_rev3,
+	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
+	 27, 192, 32}
+	,
+	{&iq_lut_core0_rev3,
+	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
+	,
+	{&iq_lut_core1_rev3,
+	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
+	,
+	{&loft_lut_core0_rev3,
+	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
+	 16}
+	,
+	{&loft_lut_core1_rev3,
+	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
+	 16}
+	,
+};
+
+const u32 mimophytbl_info_sz_rev16 =
+    sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]);
diff --git a/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h
new file mode 100644
index 0000000..396122f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/phy/wlc_phytbl_n.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define ANT_SWCTRL_TBL_REV3_IDX (0)
+
+typedef phytbl_info_t mimophytbl_info_t;
+
+extern const mimophytbl_info_t mimophytbl_info_rev0[],
+    mimophytbl_info_rev0_volatile[];
+extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile;
+
+extern const mimophytbl_info_t mimophytbl_info_rev3[],
+    mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[],
+    mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[];
+extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile,
+    mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2,
+    mimophytbl_info_sz_rev3_volatile3;
+
+extern const u32 noise_var_tbl_rev3[];
+
+extern const mimophytbl_info_t mimophytbl_info_rev7[];
+extern const u32 mimophytbl_info_sz_rev7;
+extern const u32 noise_var_tbl_rev7[];
+
+extern const mimophytbl_info_t mimophytbl_info_rev16[];
+extern const u32 mimophytbl_info_sz_rev16;
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_dbg.h b/drivers/staging/brcm80211/brcmsmac/wl_dbg.h
new file mode 100644
index 0000000..54af257
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wl_dbg.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wl_dbg_h_
+#define _wl_dbg_h_
+
+/* wl_msg_level is a bit vector with defs in wlioctl.h */
+extern u32 wl_msg_level;
+
+#define WL_NONE(fmt, args...) no_printk(fmt, ##args)
+
+#define WL_PRINT(level, fmt, args...)		\
+do {						\
+	if (wl_msg_level & level)		\
+		printk(fmt, ##args);		\
+} while (0)
+
+#ifdef BCMDBG
+
+#define	WL_ERROR(fmt, args...)	WL_PRINT(WL_ERROR_VAL, fmt, ##args)
+#define	WL_TRACE(fmt, args...)	WL_PRINT(WL_TRACE_VAL, fmt, ##args)
+#define WL_AMPDU(fmt, args...)	WL_PRINT(WL_AMPDU_VAL, fmt, ##args)
+#define WL_FFPLD(fmt, args...)	WL_PRINT(WL_FFPLD_VAL, fmt, ##args)
+
+#define WL_ERROR_ON()		(wl_msg_level & WL_ERROR_VAL)
+
+/* Extra message control for AMPDU debugging */
+#define   WL_AMPDU_UPDN_VAL	0x00000001	/* Config up/down related  */
+#define   WL_AMPDU_ERR_VAL	0x00000002	/* Calls to beaocn update  */
+#define   WL_AMPDU_TX_VAL	0x00000004	/* Transmit data path */
+#define   WL_AMPDU_RX_VAL	0x00000008	/* Receive data path  */
+#define   WL_AMPDU_CTL_VAL	0x00000010	/* TSF-related items  */
+#define   WL_AMPDU_HW_VAL       0x00000020	/* AMPDU_HW */
+#define   WL_AMPDU_HWTXS_VAL    0x00000040	/* AMPDU_HWTXS */
+#define   WL_AMPDU_HWDBG_VAL    0x00000080	/* AMPDU_DBG */
+
+extern u32 wl_ampdu_dbg;
+
+#define WL_AMPDU_PRINT(level, fmt, args...)	\
+do {						\
+	if (wl_ampdu_dbg & level) {		\
+		WL_AMPDU(fmt, ##args);		\
+	}					\
+} while (0)
+
+#define WL_AMPDU_UPDN(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_UPDN_VAL, fmt, ##args)
+#define WL_AMPDU_RX(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_RX_VAL, fmt, ##args)
+#define WL_AMPDU_ERR(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_ERR_VAL, fmt, ##args)
+#define WL_AMPDU_TX(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_TX_VAL, fmt, ##args)
+#define WL_AMPDU_CTL(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_CTL_VAL, fmt, ##args)
+#define WL_AMPDU_HW(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_HW_VAL, fmt, ##args)
+#define WL_AMPDU_HWTXS(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_HWTXS_VAL, fmt, ##args)
+#define WL_AMPDU_HWDBG(fmt, args...)			\
+	WL_AMPDU_PRINT(WL_AMPDU_HWDBG_VAL, fmt, ##args)
+#define WL_AMPDU_ERR_ON() (wl_ampdu_dbg & WL_AMPDU_ERR_VAL)
+#define WL_AMPDU_HW_ON() (wl_ampdu_dbg & WL_AMPDU_HW_VAL)
+#define WL_AMPDU_HWTXS_ON() (wl_ampdu_dbg & WL_AMPDU_HWTXS_VAL)
+
+#else				/* BCMDBG */
+
+#define	WL_ERROR(fmt, args...)		no_printk(fmt, ##args)
+#define	WL_TRACE(fmt, args...)		no_printk(fmt, ##args)
+#define WL_AMPDU(fmt, args...)		no_printk(fmt, ##args)
+#define WL_FFPLD(fmt, args...)		no_printk(fmt, ##args)
+
+#define WL_ERROR_ON()		0
+
+#define WL_AMPDU_UPDN(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_RX(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_ERR(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_TX(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_CTL(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_HW(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_HWTXS(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_HWDBG(fmt, args...)	no_printk(fmt, ##args)
+#define WL_AMPDU_ERR_ON()       0
+#define WL_AMPDU_HW_ON()        0
+#define WL_AMPDU_HWTXS_ON()     0
+
+#endif				/* BCMDBG */
+
+#endif				/* _wl_dbg_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_export.h b/drivers/staging/brcm80211/brcmsmac/wl_export.h
new file mode 100644
index 0000000..9ff760f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wl_export.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wl_export_h_
+#define _wl_export_h_
+
+/* misc callbacks */
+struct wl_info;
+struct wl_if;
+struct wlc_if;
+extern void wl_init(struct wl_info *wl);
+extern uint wl_reset(struct wl_info *wl);
+extern void wl_intrson(struct wl_info *wl);
+extern u32 wl_intrsoff(struct wl_info *wl);
+extern void wl_intrsrestore(struct wl_info *wl, u32 macintmask);
+extern int wl_up(struct wl_info *wl);
+extern void wl_down(struct wl_info *wl);
+extern void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
+			     int prio);
+extern bool wl_alloc_dma_resources(struct wl_info *wl, uint dmaddrwidth);
+extern bool wl_rfkill_set_hw_state(struct wl_info *wl);
+
+/* timer functions */
+struct wl_timer;
+extern struct wl_timer *wl_init_timer(struct wl_info *wl,
+				      void (*fn) (void *arg), void *arg,
+				      const char *name);
+extern void wl_free_timer(struct wl_info *wl, struct wl_timer *timer);
+extern void wl_add_timer(struct wl_info *wl, struct wl_timer *timer, uint ms,
+			 int periodic);
+extern bool wl_del_timer(struct wl_info *wl, struct wl_timer *timer);
+
+#endif				/* _wl_export_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
new file mode 100644
index 0000000..774b4e9
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.c
@@ -0,0 +1,1954 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define __UNDEF_NO_VERSION__
+
+#include <linux/kernel.h>
+#include <linux/etherdevice.h>
+#include <linux/types.h>
+#include <linux/pci_ids.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/firmware.h>
+#include <net/mac80211.h>
+
+#include <proto/802.11.h>
+#include <bcmdefs.h>
+#include <bcmwifi.h>
+#include <bcmutils.h>
+#include <pcicfg.h>
+#include <wlioctl.h>
+#include <sbhnddma.h>
+
+#include "phy/wlc_phy_int.h"
+#include "d11.h"
+#include "wlc_types.h"
+#include "wlc_cfg.h"
+#include "phy/phy_version.h"
+#include "wlc_key.h"
+#include "wlc_channel.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wl_dbg.h"
+#include "wl_export.h"
+#include "wl_ucode.h"
+#include "wl_mac80211.h"
+
+static void wl_timer(unsigned long data);
+static void _wl_timer(struct wl_timer *t);
+
+
+static int ieee_hw_init(struct ieee80211_hw *hw);
+static int ieee_hw_rate_init(struct ieee80211_hw *hw);
+
+static int wl_linux_watchdog(void *ctx);
+
+/* Flags we support */
+#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
+	FIF_ALLMULTI | \
+	FIF_FCSFAIL | \
+	FIF_PLCPFAIL | \
+	FIF_CONTROL | \
+	FIF_OTHER_BSS | \
+	FIF_BCN_PRBRESP_PROMISC)
+
+static int wl_found;
+
+#define WL_DEV_IF(dev)		((struct wl_if *)netdev_priv(dev))
+#define	WL_INFO(dev)		((struct wl_info *)(WL_DEV_IF(dev)->wl))
+static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev);
+static void wl_release_fw(struct wl_info *wl);
+
+/* local prototypes */
+static void wl_dpc(unsigned long data);
+static irqreturn_t wl_isr(int irq, void *dev_id);
+
+static int __devinit wl_pci_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent);
+static void wl_remove(struct pci_dev *pdev);
+static void wl_free(struct wl_info *wl);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* recognized PCI IDs */
+static struct pci_device_id wl_id_table[] = {
+	{PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43225 2G */
+	{PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43224 DUAL */
+	{PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 4313 DUAL */
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, wl_id_table);
+
+#ifdef BCMDBG
+static int msglevel = 0xdeadbeef;
+module_param(msglevel, int, 0);
+static int phymsglevel = 0xdeadbeef;
+module_param(phymsglevel, int, 0);
+#endif				/* BCMDBG */
+
+#define HW_TO_WL(hw)	 (hw->priv)
+#define WL_TO_HW(wl)	  (wl->pub->ieee_hw)
+
+/* MAC80211 callback functions */
+static int wl_ops_start(struct ieee80211_hw *hw);
+static void wl_ops_stop(struct ieee80211_hw *hw);
+static int wl_ops_add_interface(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif);
+static void wl_ops_remove_interface(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif);
+static int wl_ops_config(struct ieee80211_hw *hw, u32 changed);
+static void wl_ops_bss_info_changed(struct ieee80211_hw *hw,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_bss_conf *info,
+				    u32 changed);
+static void wl_ops_configure_filter(struct ieee80211_hw *hw,
+				    unsigned int changed_flags,
+				    unsigned int *total_flags, u64 multicast);
+static int wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
+			  bool set);
+static void wl_ops_sw_scan_start(struct ieee80211_hw *hw);
+static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw);
+static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
+static int wl_ops_get_stats(struct ieee80211_hw *hw,
+			    struct ieee80211_low_level_stats *stats);
+static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
+static void wl_ops_sta_notify(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif,
+			      enum sta_notify_cmd cmd,
+			      struct ieee80211_sta *sta);
+static int wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			  const struct ieee80211_tx_queue_params *params);
+static u64 wl_ops_get_tsf(struct ieee80211_hw *hw);
+static int wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		      struct ieee80211_sta *sta);
+static int wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			 struct ieee80211_sta *sta);
+static int wl_ops_ampdu_action(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size);
+static void wl_ops_rfkill_poll(struct ieee80211_hw *hw);
+
+static void wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct wl_info *wl = hw->priv;
+
+	WL_LOCK(wl);
+	if (!wl->pub->up) {
+		WL_ERROR("ops->tx called while down\n");
+		kfree_skb(skb);
+		goto done;
+	}
+	wlc_sendpkt_mac80211(wl->wlc, skb, hw);
+ done:
+	WL_UNLOCK(wl);
+}
+
+static int wl_ops_start(struct ieee80211_hw *hw)
+{
+	struct wl_info *wl = hw->priv;
+	bool blocked;
+	/*
+	  struct ieee80211_channel *curchan = hw->conf.channel;
+	  WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
+	*/
+
+	ieee80211_wake_queues(hw);
+	WL_LOCK(wl);
+	blocked = wl_rfkill_set_hw_state(wl);
+	WL_UNLOCK(wl);
+	if (!blocked)
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+
+	return 0;
+}
+
+static void wl_ops_stop(struct ieee80211_hw *hw)
+{
+#ifdef BRCMDBG
+	struct wl_info *wl = hw->priv;
+	ASSERT(wl);
+#endif /*BRCMDBG*/
+	ieee80211_stop_queues(hw);
+}
+
+static int
+wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct wl_info *wl;
+	int err;
+
+	/* Just STA for now */
+	if (vif->type != NL80211_IFTYPE_AP &&
+	    vif->type != NL80211_IFTYPE_MESH_POINT &&
+	    vif->type != NL80211_IFTYPE_STATION &&
+	    vif->type != NL80211_IFTYPE_WDS &&
+	    vif->type != NL80211_IFTYPE_ADHOC) {
+		WL_ERROR("%s: Attempt to add type %d, only STA for now\n",
+			 __func__, vif->type);
+		return -EOPNOTSUPP;
+	}
+
+	wl = HW_TO_WL(hw);
+	WL_LOCK(wl);
+	err = wl_up(wl);
+	WL_UNLOCK(wl);
+
+	if (err != 0) {
+		WL_ERROR("%s: wl_up() returned %d\n", __func__, err);
+	}
+	return err;
+}
+
+static void
+wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct wl_info *wl;
+
+	wl = HW_TO_WL(hw);
+
+	/* put driver in down state */
+	WL_LOCK(wl);
+	wl_down(wl);
+	WL_UNLOCK(wl);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+static int
+ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
+		 enum nl80211_channel_type type)
+{
+	struct wl_info *wl = HW_TO_WL(hw);
+	int err = 0;
+
+	switch (type) {
+	case NL80211_CHAN_HT20:
+	case NL80211_CHAN_NO_HT:
+		err = wlc_set(wl->wlc, WLC_SET_CHANNEL, chan->hw_value);
+		break;
+	case NL80211_CHAN_HT40MINUS:
+	case NL80211_CHAN_HT40PLUS:
+		WL_ERROR("%s: Need to implement 40 Mhz Channels!\n", __func__);
+		err = 1;
+		break;
+	}
+
+	if (err)
+		return -EIO;
+	return err;
+}
+
+static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct ieee80211_conf *conf = &hw->conf;
+	struct wl_info *wl = HW_TO_WL(hw);
+	int err = 0;
+	int new_int;
+
+	WL_LOCK(wl);
+	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+		if (wlc_iovar_setint
+		    (wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
+			WL_ERROR("%s: Error setting listen_interval\n",
+				 __func__);
+			err = -EIO;
+			goto config_out;
+		}
+		wlc_iovar_getint(wl->wlc, "bcn_li_bcn", &new_int);
+		ASSERT(new_int == conf->listen_interval);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
+		WL_ERROR("%s: change monitor mode: %s (implement)\n", __func__,
+			 conf->flags & IEEE80211_CONF_MONITOR ?
+				"true" : "false");
+	if (changed & IEEE80211_CONF_CHANGE_PS)
+		WL_ERROR("%s: change power-save mode: %s (implement)\n",
+			 __func__, conf->flags & IEEE80211_CONF_PS ?
+				"true" : "false");
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		if (wlc_iovar_setint
+		    (wl->wlc, "qtxpower", conf->power_level * 4)) {
+			WL_ERROR("%s: Error setting power_level\n", __func__);
+			err = -EIO;
+			goto config_out;
+		}
+		wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
+		if (new_int != (conf->power_level * 4))
+			WL_ERROR("%s: Power level req != actual, %d %d\n",
+				 __func__, conf->power_level * 4, new_int);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		err = ieee_set_channel(hw, conf->channel, conf->channel_type);
+	}
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+		if (wlc_set
+		    (wl->wlc, WLC_SET_SRL,
+		     conf->short_frame_max_tx_count) < 0) {
+			WL_ERROR("%s: Error setting srl\n", __func__);
+			err = -EIO;
+			goto config_out;
+		}
+		if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
+		    < 0) {
+			WL_ERROR("%s: Error setting lrl\n", __func__);
+			err = -EIO;
+			goto config_out;
+		}
+	}
+
+ config_out:
+	WL_UNLOCK(wl);
+	return err;
+}
+
+static void
+wl_ops_bss_info_changed(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			struct ieee80211_bss_conf *info, u32 changed)
+{
+	struct wl_info *wl = HW_TO_WL(hw);
+	int val;
+
+	if (changed & BSS_CHANGED_ASSOC) {
+		/* association status changed (associated/disassociated)
+		 * also implies a change in the AID.
+		 */
+		WL_ERROR("%s: %s: %sassociated\n", KBUILD_MODNAME, __func__,
+			 info->assoc ? "" : "dis");
+		wlc_associate_upd(wl->wlc, info->assoc);
+	}
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		/* CTS protection changed */
+		WL_ERROR("%s: use_cts_prot: %s (implement)\n", __func__,
+			info->use_cts_prot ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		/* preamble changed */
+		WL_ERROR("%s: short preamble: %s (implement)\n", __func__,
+			info->use_short_preamble ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		/* slot timing changed */
+		if (info->use_short_slot)
+			val = 1;
+		else
+			val = 0;
+		WL_LOCK(wl);
+		wlc_set(wl->wlc, WLC_SET_SHORTSLOT_OVERRIDE, val);
+		WL_UNLOCK(wl);
+	}
+
+	if (changed & BSS_CHANGED_HT) {
+		/* 802.11n parameters changed */
+		u16 mode = info->ht_operation_mode;
+		WL_NONE("%s: HT mode: 0x%04X\n", __func__, mode);
+		wlc_protection_upd(wl->wlc, WLC_PROT_N_CFG,
+			mode & IEEE80211_HT_OP_MODE_PROTECTION);
+		wlc_protection_upd(wl->wlc, WLC_PROT_N_NONGF,
+			mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+		wlc_protection_upd(wl->wlc, WLC_PROT_N_OBSS,
+			mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT);
+	}
+	if (changed & BSS_CHANGED_BASIC_RATES) {
+		/* Basic rateset changed */
+		WL_ERROR("%s: Need to change Basic Rates: 0x%x (implement)\n",
+			 __func__, (u32) info->basic_rates);
+	}
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		/* Beacon interval changed */
+		WL_NONE("%s: Beacon Interval: %d\n",
+			__func__, info->beacon_int);
+		wlc_set(wl->wlc, WLC_SET_BCNPRD, info->beacon_int);
+	}
+	if (changed & BSS_CHANGED_BSSID) {
+		/* BSSID changed, for whatever reason (IBSS and managed mode) */
+		WL_NONE("%s: new BSSID: aid %d  bss:%pM\n", __func__,
+			info->aid, info->bssid);
+		WL_LOCK(wl);
+		wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
+				  info->bssid);
+		WL_UNLOCK(wl);
+	}
+	if (changed & BSS_CHANGED_BEACON) {
+		/* Beacon data changed, retrieve new beacon (beaconing modes) */
+		WL_ERROR("%s: beacon changed\n", __func__);
+	}
+	if (changed & BSS_CHANGED_BEACON_ENABLED) {
+		/* Beaconing should be enabled/disabled (beaconing modes) */
+		WL_ERROR("%s: Beacon enabled: %s\n", __func__,
+			 info->enable_beacon ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_CQM) {
+		/* Connection quality monitor config changed */
+		WL_ERROR("%s: cqm change: threshold %d, hys %d (implement)\n",
+			__func__, info->cqm_rssi_thold, info->cqm_rssi_hyst);
+	}
+	if (changed & BSS_CHANGED_IBSS) {
+		/* IBSS join status changed */
+		WL_ERROR("%s: IBSS joined: %s (implement)\n", __func__,
+			info->ibss_joined ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_ARP_FILTER) {
+		/* Hardware ARP filter address list or state changed */
+		WL_ERROR("%s: arp filtering: enabled %s, count %d (implement)\n",
+			__func__, info->arp_filter_enabled ? "true" : "false",
+			info->arp_addr_cnt);
+	}
+	if (changed & BSS_CHANGED_QOS) {
+		/*
+		 * QoS for this association was enabled/disabled.
+		 * Note that it is only ever disabled for station mode.
+		 */
+		WL_ERROR("%s: qos enabled: %s (implement)\n", __func__,
+			info->qos ? "true" : "false");
+	}
+	if (changed & BSS_CHANGED_IDLE) {
+		/* Idle changed for this BSS/interface */
+		WL_ERROR("%s: BSS idle: %s (implement)\n", __func__,
+			info->idle ? "true" : "false");
+	}
+	return;
+}
+
+static void
+wl_ops_configure_filter(struct ieee80211_hw *hw,
+			unsigned int changed_flags,
+			unsigned int *total_flags, u64 multicast)
+{
+	struct wl_info *wl = hw->priv;
+
+	changed_flags &= MAC_FILTERS;
+	*total_flags &= MAC_FILTERS;
+	if (changed_flags & FIF_PROMISC_IN_BSS)
+		WL_ERROR("FIF_PROMISC_IN_BSS\n");
+	if (changed_flags & FIF_ALLMULTI)
+		WL_ERROR("FIF_ALLMULTI\n");
+	if (changed_flags & FIF_FCSFAIL)
+		WL_ERROR("FIF_FCSFAIL\n");
+	if (changed_flags & FIF_PLCPFAIL)
+		WL_ERROR("FIF_PLCPFAIL\n");
+	if (changed_flags & FIF_CONTROL)
+		WL_ERROR("FIF_CONTROL\n");
+	if (changed_flags & FIF_OTHER_BSS)
+		WL_ERROR("FIF_OTHER_BSS\n");
+	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+		WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
+		WL_LOCK(wl);
+		if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
+			wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
+			wlc_mac_bcn_promisc_change(wl->wlc, 1);
+		} else {
+			wlc_mac_bcn_promisc_change(wl->wlc, 0);
+			wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
+		}
+		WL_UNLOCK(wl);
+	}
+	return;
+}
+
+static int
+wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
+{
+	WL_NONE("%s: Enter\n", __func__);
+	return 0;
+}
+
+static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
+{
+	struct wl_info *wl = hw->priv;
+	WL_NONE("Scan Start\n");
+	WL_LOCK(wl);
+	wlc_scan_start(wl->wlc);
+	WL_UNLOCK(wl);
+	return;
+}
+
+static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
+{
+	struct wl_info *wl = hw->priv;
+	WL_NONE("Scan Complete\n");
+	WL_LOCK(wl);
+	wlc_scan_stop(wl->wlc);
+	WL_UNLOCK(wl);
+	return;
+}
+
+static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
+{
+	WL_ERROR("%s: Enter\n", __func__);
+	return;
+}
+
+static int
+wl_ops_get_stats(struct ieee80211_hw *hw,
+		 struct ieee80211_low_level_stats *stats)
+{
+	struct wl_info *wl = hw->priv;
+	struct wl_cnt *cnt;
+
+	WL_LOCK(wl);
+	cnt = wl->pub->_cnt;
+	stats->dot11ACKFailureCount = cnt->txnoack;
+	stats->dot11RTSFailureCount = cnt->txnocts;
+	stats->dot11FCSErrorCount = cnt->rxcrc;
+	stats->dot11RTSSuccessCount = cnt->txrts;
+	WL_UNLOCK(wl);
+	return 0;
+}
+
+static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+	struct wl_info *wl = hw->priv;
+
+	WL_LOCK(wl);
+	wlc_iovar_setint(wl->wlc, "rtsthresh", value & 0xFFFF);
+	WL_UNLOCK(wl);
+	return 0;
+}
+
+static void
+wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
+{
+	WL_NONE("%s: Enter\n", __func__);
+	switch (cmd) {
+	default:
+		WL_ERROR("%s: Unknown cmd = %d\n", __func__, cmd);
+		break;
+	}
+	return;
+}
+
+static int
+wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
+	       const struct ieee80211_tx_queue_params *params)
+{
+	struct wl_info *wl = hw->priv;
+
+	WL_NONE("%s: Enter (WME config)\n", __func__);
+	WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
+		 params->txop, params->cw_min, params->cw_max, params->aifs);
+
+	WL_LOCK(wl);
+	wlc_wme_setparams(wl->wlc, queue, (void *)params, true);
+	WL_UNLOCK(wl);
+
+	return 0;
+}
+
+static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
+{
+	WL_ERROR("%s: Enter\n", __func__);
+	return 0;
+}
+
+static int
+wl_ops_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+	       struct ieee80211_sta *sta)
+{
+	struct scb *scb;
+
+	int i;
+	struct wl_info *wl = hw->priv;
+
+	/* Init the scb */
+	scb = (struct scb *)sta->drv_priv;
+	memset(scb, 0, sizeof(struct scb));
+	for (i = 0; i < NUMPRIO; i++)
+		scb->seqctl[i] = 0xFFFF;
+	scb->seqctl_nonqos = 0xFFFF;
+	scb->magic = SCB_MAGIC;
+
+	wl->pub->global_scb = scb;
+	wl->pub->global_ampdu = &(scb->scb_ampdu);
+	wl->pub->global_ampdu->scb = scb;
+	wl->pub->global_ampdu->max_pdu = 16;
+	pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
+		  AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
+
+	sta->ht_cap.ht_supported = true;
+	sta->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
+	sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
+	    IEEE80211_HT_CAP_SGI_20 |
+	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
+
+	/* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
+	return 0;
+}
+
+static int
+wl_ops_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+		  struct ieee80211_sta *sta)
+{
+	WL_NONE("%s: Enter\n", __func__);
+	return 0;
+}
+
+static int
+wl_ops_ampdu_action(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    enum ieee80211_ampdu_mlme_action action,
+		    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+		    u8 buf_size)
+{
+#if defined(BCMDBG)
+	struct scb *scb = (struct scb *)sta->drv_priv;
+#endif
+	struct wl_info *wl = hw->priv;
+	int status;
+
+	ASSERT(scb->magic == SCB_MAGIC);
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__);
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__);
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		WL_LOCK(wl);
+		status = wlc_aggregatable(wl->wlc, tid);
+		WL_UNLOCK(wl);
+		if (!status) {
+			/* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
+			return -1;
+		}
+		/* XXX: Use the starting sequence number provided ... */
+		*ssn = 0;
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+
+	case IEEE80211_AMPDU_TX_STOP:
+		WL_LOCK(wl);
+		wlc_ampdu_flush(wl->wlc, sta, tid);
+		WL_UNLOCK(wl);
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/* Not sure what to do here */
+		/* Power save wakeup */
+		WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
+			__func__);
+		break;
+	default:
+		WL_ERROR("%s: Invalid command, ignoring\n", __func__);
+	}
+
+	return 0;
+}
+
+static void wl_ops_rfkill_poll(struct ieee80211_hw *hw)
+{
+	struct wl_info *wl = HW_TO_WL(hw);
+	bool blocked;
+
+	WL_LOCK(wl);
+	blocked = wlc_check_radio_disabled(wl->wlc);
+	WL_UNLOCK(wl);
+
+	WL_NONE("wl: rfkill_poll: %d\n", blocked);
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+}
+
+static const struct ieee80211_ops wl_ops = {
+	.tx = wl_ops_tx,
+	.start = wl_ops_start,
+	.stop = wl_ops_stop,
+	.add_interface = wl_ops_add_interface,
+	.remove_interface = wl_ops_remove_interface,
+	.config = wl_ops_config,
+	.bss_info_changed = wl_ops_bss_info_changed,
+	.configure_filter = wl_ops_configure_filter,
+	.set_tim = wl_ops_set_tim,
+	.sw_scan_start = wl_ops_sw_scan_start,
+	.sw_scan_complete = wl_ops_sw_scan_complete,
+	.set_tsf = wl_ops_set_tsf,
+	.get_stats = wl_ops_get_stats,
+	.set_rts_threshold = wl_ops_set_rts_threshold,
+	.sta_notify = wl_ops_sta_notify,
+	.conf_tx = wl_ops_conf_tx,
+	.get_tsf = wl_ops_get_tsf,
+	.sta_add = wl_ops_sta_add,
+	.sta_remove = wl_ops_sta_remove,
+	.ampdu_action = wl_ops_ampdu_action,
+	.rfkill_poll = wl_ops_rfkill_poll,
+};
+
+/*
+ * is called in wl_pci_probe() context, therefore no locking required.
+ */
+static int wl_set_hint(struct wl_info *wl, char *abbrev)
+{
+	WL_NONE("%s: Sending country code %c%c to MAC80211\n",
+		 __func__, abbrev[0], abbrev[1]);
+	return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
+}
+
+/**
+ * attach to the WL device.
+ *
+ * Attach to the WL device identified by vendor and device parameters.
+ * regs is a host accessible memory address pointing to WL device registers.
+ *
+ * wl_attach is not defined as static because in the case where no bus
+ * is defined, wl_attach will never be called, and thus, gcc will issue
+ * a warning that this function is defined but not used if we declare
+ * it as static.
+ *
+ *
+ * is called in wl_pci_probe() context, therefore no locking required.
+ */
+static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
+			    uint bustype, void *btparam, uint irq)
+{
+	struct wl_info *wl;
+	int unit, err;
+
+	unsigned long base_addr;
+	struct ieee80211_hw *hw;
+	u8 perm[ETH_ALEN];
+
+	unit = wl_found;
+	err = 0;
+
+	if (unit < 0) {
+		WL_ERROR("wl%d: unit number overflow, exiting\n", unit);
+		return NULL;
+	}
+
+	/* allocate private info */
+	hw = pci_get_drvdata(btparam);	/* btparam == pdev */
+	wl = hw->priv;
+	ASSERT(wl);
+
+	atomic_set(&wl->callbacks, 0);
+
+	/* setup the bottom half handler */
+	tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl);
+
+
+
+	base_addr = regs;
+
+	if (bustype == PCI_BUS) {
+		wl->piomode = false;
+	} else if (bustype == RPC_BUS) {
+		/* Do nothing */
+	} else {
+		bustype = PCI_BUS;
+		WL_TRACE("force to PCI\n");
+	}
+	wl->bcm_bustype = bustype;
+
+	wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
+	if (wl->regsva == NULL) {
+		WL_ERROR("wl%d: ioremap() failed\n", unit);
+		goto fail;
+	}
+	spin_lock_init(&wl->lock);
+	spin_lock_init(&wl->isr_lock);
+
+	/* prepare ucode */
+	if (wl_request_fw(wl, (struct pci_dev *)btparam) < 0) {
+		WL_ERROR("%s: Failed to find firmware usually in %s\n",
+			 KBUILD_MODNAME, "/lib/firmware/brcm");
+		wl_release_fw(wl);
+		wl_remove((struct pci_dev *)btparam);
+		goto fail1;
+	}
+
+	/* common load-time initialization */
+	wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode,
+			     wl->regsva, wl->bcm_bustype, btparam, &err);
+	wl_release_fw(wl);
+	if (!wl->wlc) {
+		WL_ERROR("%s: wlc_attach() failed with code %d\n",
+			 KBUILD_MODNAME, err);
+		goto fail;
+	}
+	wl->pub = wlc_pub(wl->wlc);
+
+	wl->pub->ieee_hw = hw;
+	ASSERT(wl->pub->ieee_hw);
+	ASSERT(wl->pub->ieee_hw->priv == wl);
+
+
+	if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
+		WL_ERROR("wl%d: Error setting MPC variable to 0\n", unit);
+	}
+
+	/* register our interrupt handler */
+	if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
+		WL_ERROR("wl%d: request_irq() failed\n", unit);
+		goto fail;
+	}
+	wl->irq = irq;
+
+	/* register module */
+	wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog,
+			    NULL);
+
+	if (ieee_hw_init(hw)) {
+		WL_ERROR("wl%d: %s: ieee_hw_init failed!\n", unit, __func__);
+		goto fail;
+	}
+
+	memcpy(perm, &wl->pub->cur_etheraddr, ETH_ALEN);
+	ASSERT(is_valid_ether_addr(perm));
+	SET_IEEE80211_PERM_ADDR(hw, perm);
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		WL_ERROR("%s: ieee80211_register_hw failed, status %d\n",
+			 __func__, err);
+	}
+
+	if (wl->pub->srom_ccode[0])
+		err = wl_set_hint(wl, wl->pub->srom_ccode);
+	else
+		err = wl_set_hint(wl, "US");
+	if (err) {
+		WL_ERROR("%s: regulatory_hint failed, status %d\n",
+			 __func__, err);
+	}
+
+	wl_found++;
+	return wl;
+
+fail:
+	wl_free(wl);
+fail1:
+	return NULL;
+}
+
+
+
+#define CHAN2GHZ(channel, freqency, chflags)  { \
+	.band = IEEE80211_BAND_2GHZ, \
+	.center_freq = (freqency), \
+	.hw_value = (channel), \
+	.flags = chflags, \
+	.max_antenna_gain = 0, \
+	.max_power = 19, \
+}
+
+static struct ieee80211_channel wl_2ghz_chantable[] = {
+	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN2GHZ(5, 2432, 0),
+	CHAN2GHZ(6, 2437, 0),
+	CHAN2GHZ(7, 2442, 0),
+	CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(12, 2467,
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(13, 2472,
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN2GHZ(14, 2484,
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+#define CHAN5GHZ(channel, chflags)  { \
+	.band = IEEE80211_BAND_5GHZ, \
+	.center_freq = 5000 + 5*(channel), \
+	.hw_value = (channel), \
+	.flags = chflags, \
+	.max_antenna_gain = 0, \
+	.max_power = 21, \
+}
+
+static struct ieee80211_channel wl_5ghz_nphy_chantable[] = {
+	/* UNII-1 */
+	CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
+	/* UNII-2 */
+	CHAN5GHZ(52,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(56,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(60,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(64,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	/* MID */
+	CHAN5GHZ(100,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(104,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(108,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(112,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(116,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(120,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(124,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(128,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(132,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(136,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(140,
+		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
+		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
+		 IEEE80211_CHAN_NO_HT40MINUS),
+	/* UNII-3 */
+	CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
+	CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
+	CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
+};
+
+#define RATE(rate100m, _flags) { \
+	.bitrate = (rate100m), \
+	.flags = (_flags), \
+	.hw_value = (rate100m / 5), \
+}
+
+static struct ieee80211_rate wl_legacy_ratetable[] = {
+	RATE(10, 0),
+	RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
+	RATE(60, 0),
+	RATE(90, 0),
+	RATE(120, 0),
+	RATE(180, 0),
+	RATE(240, 0),
+	RATE(360, 0),
+	RATE(480, 0),
+	RATE(540, 0),
+};
+
+static struct ieee80211_supported_band wl_band_2GHz_nphy = {
+	.band = IEEE80211_BAND_2GHZ,
+	.channels = wl_2ghz_chantable,
+	.n_channels = ARRAY_SIZE(wl_2ghz_chantable),
+	.bitrates = wl_legacy_ratetable,
+	.n_bitrates = ARRAY_SIZE(wl_legacy_ratetable),
+	.ht_cap = {
+		   /* from include/linux/ieee80211.h */
+		   .cap = IEEE80211_HT_CAP_GRN_FLD |
+		   IEEE80211_HT_CAP_SGI_20 |
+		   IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
+		   .ht_supported = true,
+		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+		   .mcs = {
+			   /* placeholders for now */
+			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+			   .rx_highest = 500,
+			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+		   }
+};
+
+static struct ieee80211_supported_band wl_band_5GHz_nphy = {
+	.band = IEEE80211_BAND_5GHZ,
+	.channels = wl_5ghz_nphy_chantable,
+	.n_channels = ARRAY_SIZE(wl_5ghz_nphy_chantable),
+	.bitrates = wl_legacy_ratetable + 4,
+	.n_bitrates = ARRAY_SIZE(wl_legacy_ratetable) - 4,
+	.ht_cap = {
+		   /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
+		   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,	/* No 40 mhz yet */
+		   .ht_supported = true,
+		   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
+		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
+		   .mcs = {
+			   /* placeholders for now */
+			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
+			   .rx_highest = 500,
+			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
+		   }
+};
+
+/*
+ * is called in wl_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_rate_init(struct ieee80211_hw *hw)
+{
+	struct wl_info *wl = HW_TO_WL(hw);
+	int has_5g;
+	char phy_list[4];
+
+	has_5g = 0;
+
+	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+	hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+
+	if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
+		WL_ERROR("Phy list failed\n");
+	}
+	WL_NONE("%s: phylist = %c\n", __func__, phy_list[0]);
+
+	if (phy_list[0] == 'n' || phy_list[0] == 'c') {
+		if (phy_list[0] == 'c') {
+			/* Single stream */
+			wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
+			wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
+		}
+		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
+	} else {
+		BUG();
+		return -1;
+	}
+
+	/* Assume all bands use the same phy.  True for 11n devices. */
+	if (NBANDS_PUB(wl->pub) > 1) {
+		has_5g++;
+		if (phy_list[0] == 'n' || phy_list[0] == 'c') {
+			hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			    &wl_band_5GHz_nphy;
+		} else {
+			return -1;
+		}
+	}
+
+	WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g);
+
+	return 0;
+}
+
+/*
+ * is called in wl_pci_probe() context, therefore no locking required.
+ */
+static int ieee_hw_init(struct ieee80211_hw *hw)
+{
+	hw->flags = IEEE80211_HW_SIGNAL_DBM
+	    /* | IEEE80211_HW_CONNECTION_MONITOR  What is this? */
+	    | IEEE80211_HW_REPORTS_TX_ACK_STATUS
+	    | IEEE80211_HW_AMPDU_AGGREGATION;
+
+	hw->extra_tx_headroom = wlc_get_header_len();
+	/* FIXME: should get this from wlc->machwcap */
+	hw->queues = 4;
+	/* FIXME: this doesn't seem to be used properly in minstrel_ht.
+	 * mac80211/status.c:ieee80211_tx_status() checks this value,
+	 * but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
+	 * appears to always set 3 rates
+	 */
+	hw->max_rates = 2;	/* Primary rate and 1 fallback rate */
+
+	hw->channel_change_time = 7 * 1000;	/* channel change time is dependant on chip and band  */
+	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+	hw->rate_control_algorithm = "minstrel_ht";
+
+	hw->sta_data_size = sizeof(struct scb);
+	return ieee_hw_rate_init(hw);
+}
+
+/**
+ * determines if a device is a WL device, and if so, attaches it.
+ *
+ * This function determines if a device pointed to by pdev is a WL device,
+ * and if so, performs a wl_attach() on it.
+ *
+ * Perimeter lock is initialized in the course of this function.
+ */
+static int __devinit
+wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int rc;
+	struct wl_info *wl;
+	struct ieee80211_hw *hw;
+	u32 val;
+
+	ASSERT(pdev);
+
+	WL_TRACE("%s: bus %d slot %d func %d irq %d\n",
+		 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+		 PCI_FUNC(pdev->devfn), pdev->irq);
+
+	if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
+	    (((pdev->device & 0xff00) != 0x4300) &&
+	     ((pdev->device & 0xff00) != 0x4700) &&
+	     ((pdev->device < 43000) || (pdev->device > 43999))))
+		return -ENODEV;
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		WL_ERROR("%s: Cannot enable device %d-%d_%d\n",
+			 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+			 PCI_FUNC(pdev->devfn));
+		return -ENODEV;
+	}
+	pci_set_master(pdev);
+
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+	hw = ieee80211_alloc_hw(sizeof(struct wl_info), &wl_ops);
+	if (!hw) {
+		WL_ERROR("%s: ieee80211_alloc_hw failed\n", __func__);
+		rc = -ENOMEM;
+		goto err_1;
+	}
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	pci_set_drvdata(pdev, hw);
+
+	memset(hw->priv, 0, sizeof(*wl));
+
+	wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0),
+		       PCI_BUS, pdev, pdev->irq);
+
+	if (!wl) {
+		WL_ERROR("%s: %s: wl_attach failed!\n",
+			 KBUILD_MODNAME, __func__);
+		return -ENODEV;
+	}
+	return 0;
+ err_1:
+	WL_ERROR("%s: err_1: Major hoarkage\n", __func__);
+	return 0;
+}
+
+static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct wl_info *wl;
+	struct ieee80211_hw *hw;
+
+	WL_TRACE("wl: wl_suspend\n");
+
+	hw = pci_get_drvdata(pdev);
+	wl = HW_TO_WL(hw);
+	if (!wl) {
+		WL_ERROR("wl: wl_suspend: pci_get_drvdata failed\n");
+		return -ENODEV;
+	}
+
+	/* only need to flag hw is down for proper resume */
+	WL_LOCK(wl);
+	wl->pub->hw_up = false;
+	WL_UNLOCK(wl);
+
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	return pci_set_power_state(pdev, PCI_D3hot);
+}
+
+static int wl_resume(struct pci_dev *pdev)
+{
+	struct wl_info *wl;
+	struct ieee80211_hw *hw;
+	int err = 0;
+	u32 val;
+
+	WL_TRACE("wl: wl_resume\n");
+	hw = pci_get_drvdata(pdev);
+	wl = HW_TO_WL(hw);
+	if (!wl) {
+		WL_ERROR("wl: wl_resume: pci_get_drvdata failed\n");
+		return -ENODEV;
+	}
+
+	err = pci_set_power_state(pdev, PCI_D0);
+	if (err)
+		return err;
+
+	pci_restore_state(pdev);
+
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+
+	pci_set_master(pdev);
+
+	pci_read_config_dword(pdev, 0x40, &val);
+	if ((val & 0x0000ff00) != 0)
+		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
+
+	/*
+	*  done. driver will be put in up state
+	*  in wl_ops_add_interface() call.
+	*/
+	return err;
+}
+
+/*
+* called from both kernel as from wl_*()
+* precondition: perimeter lock is not acquired.
+*/
+static void wl_remove(struct pci_dev *pdev)
+{
+	struct wl_info *wl;
+	struct ieee80211_hw *hw;
+	int status;
+
+	hw = pci_get_drvdata(pdev);
+	wl = HW_TO_WL(hw);
+	if (!wl) {
+		WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
+		return;
+	}
+
+	WL_LOCK(wl);
+	status = wlc_chipmatch(pdev->vendor, pdev->device);
+	WL_UNLOCK(wl);
+	if (!status) {
+		WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
+		return;
+	}
+	if (wl->wlc) {
+		wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+		wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+		ieee80211_unregister_hw(hw);
+		WL_LOCK(wl);
+		wl_down(wl);
+		WL_UNLOCK(wl);
+		WL_NONE("%s: Down\n", __func__);
+	}
+	pci_disable_device(pdev);
+
+	wl_free(wl);
+
+	pci_set_drvdata(pdev, NULL);
+	ieee80211_free_hw(hw);
+}
+
+static struct pci_driver wl_pci_driver = {
+	.name     = KBUILD_MODNAME,
+	.probe    = wl_pci_probe,
+	.suspend  = wl_suspend,
+	.resume   = wl_resume,
+	.remove   = __devexit_p(wl_remove),
+	.id_table = wl_id_table,
+};
+
+/**
+ * This is the main entry point for the WL driver.
+ *
+ * This function determines if a device pointed to by pdev is a WL device,
+ * and if so, performs a wl_attach() on it.
+ *
+ */
+static int __init wl_module_init(void)
+{
+	int error = -ENODEV;
+
+#ifdef BCMDBG
+	if (msglevel != 0xdeadbeef)
+		wl_msg_level = msglevel;
+	else {
+		char *var = getvar(NULL, "wl_msglevel");
+		if (var) {
+			unsigned long value;
+
+			(void)strict_strtoul(var, 0, &value);
+			wl_msg_level = value;
+		}
+	}
+	if (phymsglevel != 0xdeadbeef)
+		phyhal_msg_level = phymsglevel;
+	else {
+		char *var = getvar(NULL, "phy_msglevel");
+		if (var) {
+			unsigned long value;
+
+			(void)strict_strtoul(var, 0, &value);
+			phyhal_msg_level = value;
+		}
+	}
+#endif				/* BCMDBG */
+
+	error = pci_register_driver(&wl_pci_driver);
+	if (!error)
+		return 0;
+
+
+
+	return error;
+}
+
+/**
+ * This function unloads the WL driver from the system.
+ *
+ * This function unconditionally unloads the WL driver module from the
+ * system.
+ *
+ */
+static void __exit wl_module_exit(void)
+{
+	pci_unregister_driver(&wl_pci_driver);
+
+}
+
+module_init(wl_module_init);
+module_exit(wl_module_exit);
+
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void wl_free(struct wl_info *wl)
+{
+	struct wl_timer *t, *next;
+
+	ASSERT(wl);
+	/* free ucode data */
+	if (wl->fw.fw_cnt)
+		wl_ucode_data_free();
+	if (wl->irq)
+		free_irq(wl->irq, wl);
+
+	/* kill dpc */
+	tasklet_kill(&wl->tasklet);
+
+	if (wl->pub) {
+		wlc_module_unregister(wl->pub, "linux", wl);
+	}
+
+	/* free common resources */
+	if (wl->wlc) {
+		wlc_detach(wl->wlc);
+		wl->wlc = NULL;
+		wl->pub = NULL;
+	}
+
+	/* virtual interface deletion is deferred so we cannot spinwait */
+
+	/* wait for all pending callbacks to complete */
+	while (atomic_read(&wl->callbacks) > 0)
+		schedule();
+
+	/* free timers */
+	for (t = wl->timers; t; t = next) {
+		next = t->next;
+#ifdef BCMDBG
+		kfree(t->name);
+#endif
+		kfree(t);
+	}
+
+	/*
+	 * unregister_netdev() calls get_stats() which may read chip registers
+	 * so we cannot unmap the chip registers until after calling unregister_netdev() .
+	 */
+	if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
+	    wl->bcm_bustype != JTAG_BUS) {
+		iounmap((void *)wl->regsva);
+	}
+	wl->regsva = NULL;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
+		      int prio)
+{
+	WL_ERROR("Shouldn't be here %s\n", __func__);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void wl_init(struct wl_info *wl)
+{
+	WL_TRACE("wl%d: wl_init\n", wl->pub->unit);
+
+	wl_reset(wl);
+
+	wlc_init(wl->wlc);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+uint wl_reset(struct wl_info *wl)
+{
+	WL_TRACE("wl%d: wl_reset\n", wl->pub->unit);
+
+	wlc_reset(wl->wlc);
+
+	/* dpc will not be rescheduled */
+	wl->resched = 0;
+
+	return 0;
+}
+
+/*
+ * These are interrupt on/off entry points. Disable interrupts
+ * during interrupt state transition.
+ */
+void BCMFASTPATH wl_intrson(struct wl_info *wl)
+{
+	unsigned long flags;
+
+	INT_LOCK(wl, flags);
+	wlc_intrson(wl->wlc);
+	INT_UNLOCK(wl, flags);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+bool wl_alloc_dma_resources(struct wl_info *wl, uint addrwidth)
+{
+	return true;
+}
+
+u32 BCMFASTPATH wl_intrsoff(struct wl_info *wl)
+{
+	unsigned long flags;
+	u32 status;
+
+	INT_LOCK(wl, flags);
+	status = wlc_intrsoff(wl->wlc);
+	INT_UNLOCK(wl, flags);
+	return status;
+}
+
+void wl_intrsrestore(struct wl_info *wl, u32 macintmask)
+{
+	unsigned long flags;
+
+	INT_LOCK(wl, flags);
+	wlc_intrsrestore(wl->wlc, macintmask);
+	INT_UNLOCK(wl, flags);
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+int wl_up(struct wl_info *wl)
+{
+	int error = 0;
+
+	if (wl->pub->up)
+		return 0;
+
+	error = wlc_up(wl->wlc);
+
+	return error;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void wl_down(struct wl_info *wl)
+{
+	uint callbacks, ret_val = 0;
+
+	/* call common down function */
+	ret_val = wlc_down(wl->wlc);
+	callbacks = atomic_read(&wl->callbacks) - ret_val;
+
+	/* wait for down callbacks to complete */
+	WL_UNLOCK(wl);
+
+	/* For HIGH_only driver, it's important to actually schedule other work,
+	 * not just spin wait since everything runs at schedule level
+	 */
+	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
+
+	WL_LOCK(wl);
+}
+
+static irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
+{
+	struct wl_info *wl;
+	bool ours, wantdpc;
+	unsigned long flags;
+
+	wl = (struct wl_info *) dev_id;
+
+	WL_ISRLOCK(wl, flags);
+
+	/* call common first level interrupt handler */
+	ours = wlc_isr(wl->wlc, &wantdpc);
+	if (ours) {
+		/* if more to do... */
+		if (wantdpc) {
+
+			/* ...and call the second level interrupt handler */
+			/* schedule dpc */
+			ASSERT(wl->resched == false);
+			tasklet_schedule(&wl->tasklet);
+		}
+	}
+
+	WL_ISRUNLOCK(wl, flags);
+
+	return IRQ_RETVAL(ours);
+}
+
+static void BCMFASTPATH wl_dpc(unsigned long data)
+{
+	struct wl_info *wl;
+
+	wl = (struct wl_info *) data;
+
+	WL_LOCK(wl);
+
+	/* call the common second level interrupt handler */
+	if (wl->pub->up) {
+		if (wl->resched) {
+			unsigned long flags;
+
+			INT_LOCK(wl, flags);
+			wlc_intrsupd(wl->wlc);
+			INT_UNLOCK(wl, flags);
+		}
+
+		wl->resched = wlc_dpc(wl->wlc, true);
+	}
+
+	/* wlc_dpc() may bring the driver down */
+	if (!wl->pub->up)
+		goto done;
+
+	/* re-schedule dpc */
+	if (wl->resched)
+		tasklet_schedule(&wl->tasklet);
+	else {
+		/* re-enable interrupts */
+		wl_intrson(wl);
+	}
+
+ done:
+	WL_UNLOCK(wl);
+}
+
+/*
+ * is called by the kernel from software irq context
+ */
+static void wl_timer(unsigned long data)
+{
+	_wl_timer((struct wl_timer *) data);
+}
+
+/*
+* precondition: perimeter lock is not acquired
+ */
+static void _wl_timer(struct wl_timer *t)
+{
+	WL_LOCK(t->wl);
+
+	if (t->set) {
+		if (t->periodic) {
+			t->timer.expires = jiffies + t->ms * HZ / 1000;
+			atomic_inc(&t->wl->callbacks);
+			add_timer(&t->timer);
+			t->set = true;
+		} else
+			t->set = false;
+
+		t->fn(t->arg);
+	}
+
+	atomic_dec(&t->wl->callbacks);
+
+	WL_UNLOCK(t->wl);
+}
+
+/*
+ * Adds a timer to the list. Caller supplies a timer function.
+ * Is called from wlc.
+ *
+ * precondition: perimeter lock has been acquired
+ */
+struct wl_timer *wl_init_timer(struct wl_info *wl, void (*fn) (void *arg),
+			       void *arg, const char *name)
+{
+	struct wl_timer *t;
+
+	t = kzalloc(sizeof(struct wl_timer), GFP_ATOMIC);
+	if (!t) {
+		WL_ERROR("wl%d: wl_init_timer: out of memory\n", wl->pub->unit);
+		return 0;
+	}
+
+	init_timer(&t->timer);
+	t->timer.data = (unsigned long) t;
+	t->timer.function = wl_timer;
+	t->wl = wl;
+	t->fn = fn;
+	t->arg = arg;
+	t->next = wl->timers;
+	wl->timers = t;
+
+#ifdef BCMDBG
+	t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC);
+	if (t->name)
+		strcpy(t->name, name);
+#endif
+
+	return t;
+}
+
+/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
+ * as well as it's easier to make it periodic
+ *
+ * precondition: perimeter lock has been acquired
+ */
+void wl_add_timer(struct wl_info *wl, struct wl_timer *t, uint ms, int periodic)
+{
+#ifdef BCMDBG
+	if (t->set) {
+		WL_ERROR("%s: Already set. Name: %s, per %d\n",
+			 __func__, t->name, periodic);
+	}
+#endif
+	ASSERT(!t->set);
+
+	t->ms = ms;
+	t->periodic = (bool) periodic;
+	t->set = true;
+	t->timer.expires = jiffies + ms * HZ / 1000;
+
+	atomic_inc(&wl->callbacks);
+	add_timer(&t->timer);
+}
+
+/*
+ * return true if timer successfully deleted, false if still pending
+ *
+ * precondition: perimeter lock has been acquired
+ */
+bool wl_del_timer(struct wl_info *wl, struct wl_timer *t)
+{
+	if (t->set) {
+		t->set = false;
+		if (!del_timer(&t->timer)) {
+			return false;
+		}
+		atomic_dec(&wl->callbacks);
+	}
+
+	return true;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+void wl_free_timer(struct wl_info *wl, struct wl_timer *t)
+{
+	struct wl_timer *tmp;
+
+	/* delete the timer in case it is active */
+	wl_del_timer(wl, t);
+
+	if (wl->timers == t) {
+		wl->timers = wl->timers->next;
+#ifdef BCMDBG
+		kfree(t->name);
+#endif
+		kfree(t);
+		return;
+
+	}
+
+	tmp = wl->timers;
+	while (tmp) {
+		if (tmp->next == t) {
+			tmp->next = t->next;
+#ifdef BCMDBG
+			kfree(t->name);
+#endif
+			kfree(t);
+			return;
+		}
+		tmp = tmp->next;
+	}
+
+}
+
+/*
+ * runs in software irq context
+ *
+ * precondition: perimeter lock is not acquired
+ */
+static int wl_linux_watchdog(void *ctx)
+{
+	struct wl_info *wl = (struct wl_info *) ctx;
+	struct wl_cnt *cnt;
+	struct net_device_stats *stats = NULL;
+	uint id;
+	/* refresh stats */
+	if (wl->pub->up) {
+		ASSERT(wl->stats_id < 2);
+
+		cnt = wl->pub->_cnt;
+		id = 1 - wl->stats_id;
+		stats = &wl->stats_watchdog[id];
+		stats->rx_packets = cnt->rxframe;
+		stats->tx_packets = cnt->txframe;
+		stats->rx_bytes = cnt->rxbyte;
+		stats->tx_bytes = cnt->txbyte;
+		stats->rx_errors = cnt->rxerror;
+		stats->tx_errors = cnt->txerror;
+		stats->collisions = 0;
+
+		stats->rx_length_errors = 0;
+		stats->rx_over_errors = cnt->rxoflo;
+		stats->rx_crc_errors = cnt->rxcrc;
+		stats->rx_frame_errors = 0;
+		stats->rx_fifo_errors = cnt->rxoflo;
+		stats->rx_missed_errors = 0;
+
+		stats->tx_fifo_errors = cnt->txuflo;
+
+		wl->stats_id = id;
+	}
+
+	return 0;
+}
+
+struct wl_fw_hdr {
+	u32 offset;
+	u32 len;
+	u32 idx;
+};
+
+char *wl_firmwares[WL_MAX_FW] = {
+	"brcm/bcm43xx",
+	NULL
+};
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
+{
+	int i, entry;
+	const u8 *pdata;
+	struct wl_fw_hdr *hdr;
+	for (i = 0; i < wl->fw.fw_cnt; i++) {
+		hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
+		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
+		     entry++, hdr++) {
+			if (hdr->idx == idx) {
+				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
+				*pbuf = kmalloc(hdr->len, GFP_ATOMIC);
+				if (*pbuf == NULL) {
+					WL_ERROR("fail to alloc %d bytes\n",
+						 hdr->len);
+					goto fail;
+				}
+				memcpy(*pbuf, pdata, hdr->len);
+				return 0;
+			}
+		}
+	}
+	WL_ERROR("ERROR: ucode buf tag:%d can not be found!\n", idx);
+	*pbuf = NULL;
+fail:
+	return BCME_NOTFOUND;
+}
+
+/*
+ * Precondition: Since this function is called in wl_pci_probe() context,
+ * no locking is required.
+ */
+int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx)
+{
+	int i, entry;
+	const u8 *pdata;
+	struct wl_fw_hdr *hdr;
+	for (i = 0; i < wl->fw.fw_cnt; i++) {
+		hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
+		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
+		     entry++, hdr++) {
+			if (hdr->idx == idx) {
+				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
+				ASSERT(hdr->len == 4);
+				*data = *((u32 *) pdata);
+				return 0;
+			}
+		}
+	}
+	WL_ERROR("ERROR: ucode tag:%d can not be found!\n", idx);
+	return -1;
+}
+
+/*
+ * Precondition: Since this function is called in wl_pci_probe() context,
+ * no locking is required.
+ */
+static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
+{
+	int status;
+	struct device *device = &pdev->dev;
+	char fw_name[100];
+	int i;
+
+	memset((void *)&wl->fw, 0, sizeof(struct wl_firmware));
+	for (i = 0; i < WL_MAX_FW; i++) {
+		if (wl_firmwares[i] == NULL)
+			break;
+		sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
+			UCODE_LOADER_API_VER);
+		WL_NONE("request fw %s\n", fw_name);
+		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+		if (status) {
+			WL_ERROR("%s: fail to load firmware %s\n",
+				 KBUILD_MODNAME, fw_name);
+			return status;
+		}
+		WL_NONE("request fw %s\n", fw_name);
+		sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
+			UCODE_LOADER_API_VER);
+		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+		if (status) {
+			WL_ERROR("%s: fail to load firmware %s\n",
+				 KBUILD_MODNAME, fw_name);
+			return status;
+		}
+		wl->fw.hdr_num_entries[i] =
+		    wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
+		WL_NONE("request fw %s find: %d entries\n",
+			fw_name, wl->fw.hdr_num_entries[i]);
+	}
+	wl->fw.fw_cnt = i;
+	return wl_ucode_data_init(wl);
+}
+
+/*
+ * precondition: can both be called locked and unlocked
+ */
+void wl_ucode_free_buf(void *p)
+{
+	kfree(p);
+}
+
+/*
+ * Precondition: Since this function is called in wl_pci_probe() context,
+ * no locking is required.
+ */
+static void wl_release_fw(struct wl_info *wl)
+{
+	int i;
+	for (i = 0; i < WL_MAX_FW; i++) {
+		release_firmware(wl->fw.fw_bin[i]);
+		release_firmware(wl->fw.fw_hdr[i]);
+	}
+}
+
+
+/*
+ * checks validity of all firmware images loaded from user space
+ *
+ * Precondition: Since this function is called in wl_pci_probe() context,
+ * no locking is required.
+ */
+int wl_check_firmwares(struct wl_info *wl)
+{
+	int i;
+	int entry;
+	int rc = 0;
+	const struct firmware *fw;
+	const struct firmware *fw_hdr;
+	struct wl_fw_hdr *ucode_hdr;
+	for (i = 0; i < WL_MAX_FW && rc == 0; i++) {
+		fw =  wl->fw.fw_bin[i];
+		fw_hdr = wl->fw.fw_hdr[i];
+		if (fw == NULL && fw_hdr == NULL) {
+			break;
+		} else if (fw == NULL || fw_hdr == NULL) {
+			WL_ERROR("%s: invalid bin/hdr fw\n", __func__);
+			rc = -EBADF;
+		} else if (fw_hdr->size % sizeof(struct wl_fw_hdr)) {
+			WL_ERROR("%s: non integral fw hdr file size %zu/%zu\n",
+				 __func__, fw_hdr->size,
+				 sizeof(struct wl_fw_hdr));
+			rc = -EBADF;
+		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
+			WL_ERROR("%s: out of bounds fw file size %zu\n",
+				 __func__, fw->size);
+			rc = -EBADF;
+		} else {
+			/* check if ucode section overruns firmware image */
+			ucode_hdr = (struct wl_fw_hdr *)fw_hdr->data;
+			for (entry = 0; entry < wl->fw.hdr_num_entries[i] &&
+			     !rc; entry++, ucode_hdr++) {
+				if (ucode_hdr->offset + ucode_hdr->len >
+				    fw->size) {
+					WL_ERROR("%s: conflicting bin/hdr\n",
+						 __func__);
+					rc = -EBADF;
+				}
+			}
+		}
+	}
+	if (rc == 0 && wl->fw.fw_cnt != i) {
+		WL_ERROR("%s: invalid fw_cnt=%d\n", __func__, wl->fw.fw_cnt);
+		rc = -EBADF;
+	}
+	return rc;
+}
+
+/*
+ * precondition: perimeter lock has been acquired
+ */
+bool wl_rfkill_set_hw_state(struct wl_info *wl)
+{
+	bool blocked = wlc_check_radio_disabled(wl->wlc);
+
+	WL_NONE("%s: update hw state: blocked=%s\n", __func__,
+		blocked ? "true" : "false");
+	WL_UNLOCK(wl);
+	wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked);
+	if (blocked)
+		wiphy_rfkill_start_polling(wl->pub->ieee_hw->wiphy);
+	WL_LOCK(wl);
+	return blocked;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
new file mode 100644
index 0000000..f3198cc
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wl_mac80211.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wl_mac80211_h_
+#define _wl_mac80211_h_
+
+/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
+ * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
+ * submitted to workqueue instead of being on kernel timer
+ */
+struct wl_timer {
+	struct timer_list timer;
+	struct wl_info *wl;
+	void (*fn) (void *);
+	void *arg;		/* argument to fn */
+	uint ms;
+	bool periodic;
+	bool set;
+	struct wl_timer *next;
+#ifdef BCMDBG
+	char *name;		/* Description of the timer */
+#endif
+};
+
+struct wl_if {
+	uint subunit;		/* WDS/BSS unit */
+	struct pci_dev *pci_dev;
+};
+
+#define WL_MAX_FW		4
+struct wl_firmware {
+	u32 fw_cnt;
+	const struct firmware *fw_bin[WL_MAX_FW];
+	const struct firmware *fw_hdr[WL_MAX_FW];
+	u32 hdr_num_entries[WL_MAX_FW];
+};
+
+struct wl_info {
+	struct wlc_pub *pub;		/* pointer to public wlc state */
+	void *wlc;		/* pointer to private common os-independent data */
+	u32 magic;
+
+	int irq;
+
+	spinlock_t lock;	/* per-device perimeter lock */
+	spinlock_t isr_lock;	/* per-device ISR synchronization lock */
+	uint bcm_bustype;	/* bus type */
+	bool piomode;		/* set from insmod argument */
+	void *regsva;		/* opaque chip registers virtual address */
+	atomic_t callbacks;	/* # outstanding callback functions */
+	struct wl_timer *timers;	/* timer cleanup queue */
+	struct tasklet_struct tasklet;	/* dpc tasklet */
+	bool resched;		/* dpc needs to be and is rescheduled */
+#ifdef LINUXSTA_PS
+	u32 pci_psstate[16];	/* pci ps-state save/restore */
+#endif
+	/* RPC, handle, lock, txq, workitem */
+	uint stats_id;		/* the current set of stats */
+	/* ping-pong stats counters updated by Linux watchdog */
+	struct net_device_stats stats_watchdog[2];
+	struct wl_firmware fw;
+};
+
+#define WL_LOCK(wl)	spin_lock_bh(&(wl)->lock)
+#define WL_UNLOCK(wl)	spin_unlock_bh(&(wl)->lock)
+
+/* locking from inside wl_isr */
+#define WL_ISRLOCK(wl, flags) do {spin_lock(&(wl)->isr_lock); (void)(flags); } while (0)
+#define WL_ISRUNLOCK(wl, flags) do {spin_unlock(&(wl)->isr_lock); (void)(flags); } while (0)
+
+/* locking under WL_LOCK() to synchronize with wl_isr */
+#define INT_LOCK(wl, flags)	spin_lock_irqsave(&(wl)->isr_lock, flags)
+#define INT_UNLOCK(wl, flags)	spin_unlock_irqrestore(&(wl)->isr_lock, flags)
+
+#endif				/* _wl_mac80211_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_ucode.h b/drivers/staging/brcm80211/brcmsmac/wl_ucode.h
new file mode 100644
index 0000000..6933fda
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wl_ucode.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define MIN_FW_SIZE 40000	/* minimum firmware file size in bytes */
+#define MAX_FW_SIZE 150000
+
+#define UCODE_LOADER_API_VER 0
+
+struct d11init {
+	u16 addr;
+	u16 size;
+	u32 value;
+};
+
+extern struct d11init *d11lcn0bsinitvals24;
+extern struct d11init *d11lcn0initvals24;
+extern struct d11init *d11lcn1bsinitvals24;
+extern struct d11init *d11lcn1initvals24;
+extern struct d11init *d11lcn2bsinitvals24;
+extern struct d11init *d11lcn2initvals24;
+extern struct d11init *d11n0absinitvals16;
+extern struct d11init *d11n0bsinitvals16;
+extern struct d11init *d11n0initvals16;
+extern u32 *bcm43xx_16_mimo;
+extern u32 bcm43xx_16_mimosz;
+extern u32 *bcm43xx_24_lcn;
+extern u32 bcm43xx_24_lcnsz;
+
+extern int wl_ucode_data_init(struct wl_info *wl);
+extern void wl_ucode_data_free(void);
+
+extern int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, unsigned int idx);
+extern int wl_ucode_init_uint(struct wl_info *wl, unsigned *data,
+			      unsigned int idx);
+extern void wl_ucode_free_buf(void *);
+extern int  wl_check_firmwares(struct wl_info *wl);
diff --git a/drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c b/drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c
new file mode 100644
index 0000000..cc00dd1
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wl_ucode_loader.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/types.h>
+#include <bcmdefs.h>
+#include <wl_ucode.h>
+
+enum {
+	D11UCODE_NAMETAG_START = 0,
+	D11LCN0BSINITVALS24,
+	D11LCN0INITVALS24,
+	D11LCN1BSINITVALS24,
+	D11LCN1INITVALS24,
+	D11LCN2BSINITVALS24,
+	D11LCN2INITVALS24,
+	D11N0ABSINITVALS16,
+	D11N0BSINITVALS16,
+	D11N0INITVALS16,
+	D11UCODE_OVERSIGHT16_MIMO,
+	D11UCODE_OVERSIGHT16_MIMOSZ,
+	D11UCODE_OVERSIGHT24_LCN,
+	D11UCODE_OVERSIGHT24_LCNSZ,
+	D11UCODE_OVERSIGHT_BOMMAJOR,
+	D11UCODE_OVERSIGHT_BOMMINOR
+};
+
+struct d11init *d11lcn0bsinitvals24;
+struct d11init *d11lcn0initvals24;
+struct d11init *d11lcn1bsinitvals24;
+struct d11init *d11lcn1initvals24;
+struct d11init *d11lcn2bsinitvals24;
+struct d11init *d11lcn2initvals24;
+struct d11init *d11n0absinitvals16;
+struct d11init *d11n0bsinitvals16;
+struct d11init *d11n0initvals16;
+u32 *bcm43xx_16_mimo;
+u32 bcm43xx_16_mimosz;
+u32 *bcm43xx_24_lcn;
+u32 bcm43xx_24_lcnsz;
+u32 *bcm43xx_bommajor;
+u32 *bcm43xx_bomminor;
+
+int wl_ucode_data_init(struct wl_info *wl)
+{
+	int rc;
+	rc = wl_check_firmwares(wl);
+
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn0bsinitvals24,
+					     D11LCN0BSINITVALS24);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn0initvals24,
+					     D11LCN0INITVALS24);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn1bsinitvals24,
+					     D11LCN1BSINITVALS24);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn1initvals24,
+					     D11LCN1INITVALS24);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn2bsinitvals24,
+					     D11LCN2BSINITVALS24);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11lcn2initvals24,
+					     D11LCN2INITVALS24);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11n0absinitvals16,
+					     D11N0ABSINITVALS16);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11n0bsinitvals16,
+					     D11N0BSINITVALS16);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&d11n0initvals16,
+					     D11N0INITVALS16);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_16_mimo,
+					     D11UCODE_OVERSIGHT16_MIMO);
+	rc = rc < 0 ? rc : wl_ucode_init_uint(wl, &bcm43xx_16_mimosz,
+					      D11UCODE_OVERSIGHT16_MIMOSZ);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_24_lcn,
+					     D11UCODE_OVERSIGHT24_LCN);
+	rc = rc < 0 ? rc : wl_ucode_init_uint(wl, &bcm43xx_24_lcnsz,
+					      D11UCODE_OVERSIGHT24_LCNSZ);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_bommajor,
+					     D11UCODE_OVERSIGHT_BOMMAJOR);
+	rc = rc < 0 ? rc : wl_ucode_init_buf(wl, (void **)&bcm43xx_bomminor,
+					     D11UCODE_OVERSIGHT_BOMMINOR);
+	return rc;
+}
+
+void wl_ucode_data_free(void)
+{
+	wl_ucode_free_buf((void *)d11lcn0bsinitvals24);
+	wl_ucode_free_buf((void *)d11lcn0initvals24);
+	wl_ucode_free_buf((void *)d11lcn1bsinitvals24);
+	wl_ucode_free_buf((void *)d11lcn1initvals24);
+	wl_ucode_free_buf((void *)d11lcn2bsinitvals24);
+	wl_ucode_free_buf((void *)d11lcn2initvals24);
+	wl_ucode_free_buf((void *)d11n0absinitvals16);
+	wl_ucode_free_buf((void *)d11n0bsinitvals16);
+	wl_ucode_free_buf((void *)d11n0initvals16);
+	wl_ucode_free_buf((void *)bcm43xx_16_mimo);
+	wl_ucode_free_buf((void *)bcm43xx_24_lcn);
+	wl_ucode_free_buf((void *)bcm43xx_bommajor);
+	wl_ucode_free_buf((void *)bcm43xx_bomminor);
+
+	return;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_alloc.c b/drivers/staging/brcm80211/brcmsmac/wlc_alloc.c
new file mode 100644
index 0000000..e928fa1
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_alloc.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <wlioctl.h>
+#include <sbhnddma.h>
+
+#include "d11.h"
+#include "wlc_types.h"
+#include "wlc_cfg.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_key.h"
+#include "wlc_alloc.h"
+#include "wl_dbg.h"
+#include "wlc_rate.h"
+#include "wlc_bsscfg.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+
+static struct wlc_bsscfg *wlc_bsscfg_malloc(uint unit);
+static void wlc_bsscfg_mfree(struct wlc_bsscfg *cfg);
+static struct wlc_pub *wlc_pub_malloc(uint unit,
+				      uint *err, uint devid);
+static void wlc_pub_mfree(struct wlc_pub *pub);
+static void wlc_tunables_init(wlc_tunables_t *tunables, uint devid);
+
+void *wlc_calloc(uint unit, uint size)
+{
+	void *item;
+
+	item = kzalloc(size, GFP_ATOMIC);
+	if (item == NULL)
+		WL_ERROR("wl%d: %s: out of memory\n", unit, __func__);
+	return item;
+}
+
+void wlc_tunables_init(wlc_tunables_t *tunables, uint devid)
+{
+	tunables->ntxd = NTXD;
+	tunables->nrxd = NRXD;
+	tunables->rxbufsz = RXBUFSZ;
+	tunables->nrxbufpost = NRXBUFPOST;
+	tunables->maxscb = MAXSCB;
+	tunables->ampdunummpdu = AMPDU_NUM_MPDU;
+	tunables->maxpktcb = MAXPKTCB;
+	tunables->maxucodebss = WLC_MAX_UCODE_BSS;
+	tunables->maxucodebss4 = WLC_MAX_UCODE_BSS4;
+	tunables->maxbss = MAXBSS;
+	tunables->datahiwat = WLC_DATAHIWAT;
+	tunables->ampdudatahiwat = WLC_AMPDUDATAHIWAT;
+	tunables->rxbnd = RXBND;
+	tunables->txsbnd = TXSBND;
+}
+
+static struct wlc_pub *wlc_pub_malloc(uint unit, uint *err, uint devid)
+{
+	struct wlc_pub *pub;
+
+	pub = wlc_calloc(unit, sizeof(struct wlc_pub));
+	if (pub == NULL) {
+		*err = 1001;
+		goto fail;
+	}
+
+	pub->tunables = wlc_calloc(unit,
+		sizeof(wlc_tunables_t));
+	if (pub->tunables == NULL) {
+		*err = 1028;
+		goto fail;
+	}
+
+	/* need to init the tunables now */
+	wlc_tunables_init(pub->tunables, devid);
+
+	pub->_cnt = wlc_calloc(unit, sizeof(struct wl_cnt));
+	if (pub->_cnt == NULL)
+		goto fail;
+
+	pub->multicast = (u8 *)wlc_calloc(unit,
+		(ETH_ALEN * MAXMULTILIST));
+	if (pub->multicast == NULL) {
+		*err = 1003;
+		goto fail;
+	}
+
+	return pub;
+
+ fail:
+	wlc_pub_mfree(pub);
+	return NULL;
+}
+
+static void wlc_pub_mfree(struct wlc_pub *pub)
+{
+	if (pub == NULL)
+		return;
+
+	kfree(pub->multicast);
+	kfree(pub->_cnt);
+	kfree(pub->tunables);
+	kfree(pub);
+}
+
+static struct wlc_bsscfg *wlc_bsscfg_malloc(uint unit)
+{
+	struct wlc_bsscfg *cfg;
+
+	cfg = (struct wlc_bsscfg *) wlc_calloc(unit, sizeof(struct wlc_bsscfg));
+	if (cfg == NULL)
+		goto fail;
+
+	cfg->current_bss = (wlc_bss_info_t *)wlc_calloc(unit,
+		sizeof(wlc_bss_info_t));
+	if (cfg->current_bss == NULL)
+		goto fail;
+
+	return cfg;
+
+ fail:
+	wlc_bsscfg_mfree(cfg);
+	return NULL;
+}
+
+static void wlc_bsscfg_mfree(struct wlc_bsscfg *cfg)
+{
+	if (cfg == NULL)
+		return;
+
+	kfree(cfg->maclist);
+	kfree(cfg->current_bss);
+	kfree(cfg);
+}
+
+void wlc_bsscfg_ID_assign(struct wlc_info *wlc, struct wlc_bsscfg *bsscfg)
+{
+	bsscfg->ID = wlc->next_bsscfg_ID;
+	wlc->next_bsscfg_ID++;
+}
+
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+struct wlc_info *wlc_attach_malloc(uint unit, uint *err, uint devid)
+{
+	struct wlc_info *wlc;
+
+	wlc = (struct wlc_info *) wlc_calloc(unit, sizeof(struct wlc_info));
+	if (wlc == NULL) {
+		*err = 1002;
+		goto fail;
+	}
+
+	wlc->hwrxoff = WL_HWRXOFF;
+
+	/* allocate struct wlc_pub state structure */
+	wlc->pub = wlc_pub_malloc(unit, err, devid);
+	if (wlc->pub == NULL) {
+		*err = 1003;
+		goto fail;
+	}
+	wlc->pub->wlc = wlc;
+
+	/* allocate struct wlc_hw_info state structure */
+
+	wlc->hw = (struct wlc_hw_info *)wlc_calloc(unit,
+			sizeof(struct wlc_hw_info));
+	if (wlc->hw == NULL) {
+		*err = 1005;
+		goto fail;
+	}
+	wlc->hw->wlc = wlc;
+
+	wlc->hw->bandstate[0] = wlc_calloc(unit,
+		(sizeof(struct wlc_hwband) * MAXBANDS));
+	if (wlc->hw->bandstate[0] == NULL) {
+		*err = 1006;
+		goto fail;
+	} else {
+		int i;
+
+		for (i = 1; i < MAXBANDS; i++) {
+			wlc->hw->bandstate[i] = (struct wlc_hwband *)
+			    ((unsigned long)wlc->hw->bandstate[0] +
+			     (sizeof(struct wlc_hwband) * i));
+		}
+	}
+
+	wlc->modulecb = wlc_calloc(unit,
+		sizeof(struct modulecb) * WLC_MAXMODULES);
+	if (wlc->modulecb == NULL) {
+		*err = 1009;
+		goto fail;
+	}
+
+	wlc->default_bss = (wlc_bss_info_t *)wlc_calloc(unit,
+		sizeof(wlc_bss_info_t));
+	if (wlc->default_bss == NULL) {
+		*err = 1010;
+		goto fail;
+	}
+
+	wlc->cfg = wlc_bsscfg_malloc(unit);
+	if (wlc->cfg == NULL) {
+		*err = 1011;
+		goto fail;
+	}
+	wlc_bsscfg_ID_assign(wlc, wlc->cfg);
+
+	wlc->pkt_callback = wlc_calloc(unit,
+		(sizeof(struct pkt_cb) * (wlc->pub->tunables->maxpktcb + 1)));
+	if (wlc->pkt_callback == NULL) {
+		*err = 1013;
+		goto fail;
+	}
+
+	wlc->wsec_def_keys[0] = (wsec_key_t *)wlc_calloc(unit,
+		(sizeof(wsec_key_t) * WLC_DEFAULT_KEYS));
+	if (wlc->wsec_def_keys[0] == NULL) {
+		*err = 1015;
+		goto fail;
+	} else {
+		int i;
+		for (i = 1; i < WLC_DEFAULT_KEYS; i++) {
+			wlc->wsec_def_keys[i] = (wsec_key_t *)
+			    ((unsigned long)wlc->wsec_def_keys[0] +
+			     (sizeof(wsec_key_t) * i));
+		}
+	}
+
+	wlc->protection = wlc_calloc(unit,
+		sizeof(struct wlc_protection));
+	if (wlc->protection == NULL) {
+		*err = 1016;
+		goto fail;
+	}
+
+	wlc->stf = wlc_calloc(unit, sizeof(struct wlc_stf));
+	if (wlc->stf == NULL) {
+		*err = 1017;
+		goto fail;
+	}
+
+	wlc->bandstate[0] = (struct wlcband *)wlc_calloc(unit,
+				(sizeof(struct wlcband)*MAXBANDS));
+	if (wlc->bandstate[0] == NULL) {
+		*err = 1025;
+		goto fail;
+	} else {
+		int i;
+
+		for (i = 1; i < MAXBANDS; i++) {
+			wlc->bandstate[i] =
+			    (struct wlcband *) ((unsigned long)wlc->bandstate[0]
+			    + (sizeof(struct wlcband)*i));
+		}
+	}
+
+	wlc->corestate = (struct wlccore *)wlc_calloc(unit,
+						      sizeof(struct wlccore));
+	if (wlc->corestate == NULL) {
+		*err = 1026;
+		goto fail;
+	}
+
+	wlc->corestate->macstat_snapshot =
+		(macstat_t *)wlc_calloc(unit, sizeof(macstat_t));
+	if (wlc->corestate->macstat_snapshot == NULL) {
+		*err = 1027;
+		goto fail;
+	}
+
+	return wlc;
+
+ fail:
+	wlc_detach_mfree(wlc);
+	return NULL;
+}
+
+void wlc_detach_mfree(struct wlc_info *wlc)
+{
+	if (wlc == NULL)
+		return;
+
+	wlc_bsscfg_mfree(wlc->cfg);
+	wlc_pub_mfree(wlc->pub);
+	kfree(wlc->modulecb);
+	kfree(wlc->default_bss);
+	kfree(wlc->pkt_callback);
+	kfree(wlc->wsec_def_keys[0]);
+	kfree(wlc->protection);
+	kfree(wlc->stf);
+	kfree(wlc->bandstate[0]);
+	kfree(wlc->corestate->macstat_snapshot);
+	kfree(wlc->corestate);
+	kfree(wlc->hw->bandstate[0]);
+	kfree(wlc->hw);
+
+	/* free the wlc */
+	kfree(wlc);
+	wlc = NULL;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_alloc.h b/drivers/staging/brcm80211/brcmsmac/wlc_alloc.h
new file mode 100644
index 0000000..1fb7430
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_alloc.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+extern void *wlc_calloc(uint unit, uint size);
+
+extern struct wlc_info *wlc_attach_malloc(uint unit, uint *err, uint devid);
+extern void wlc_detach_mfree(struct wlc_info *wlc);
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
new file mode 100644
index 0000000..c6cdcd9
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
@@ -0,0 +1,1421 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <net/mac80211.h>
+
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <wlioctl.h>
+#include <sbhnddma.h>
+#include <hnddma.h>
+#include <d11.h>
+
+#include "wlc_types.h"
+#include "wlc_cfg.h"
+#include "wlc_rate.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_key.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_antsel.h"
+#include "wl_export.h"
+#include "wl_dbg.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+#include "wlc_ampdu.h"
+
+/*
+ *	Disable AMPDU statistics counters for now
+ */
+#define WLCNTINCR(a)
+#define WLCNTADD(a, b)
+
+#define AMPDU_MAX_MPDU		32	/* max number of mpdus in an ampdu */
+#define AMPDU_NUM_MPDU_LEGACY	16	/* max number of mpdus in an ampdu to a legacy */
+#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
+#define AMPDU_TX_BA_DEF_WSIZE	64	/* default Tx ba window size (in pdu) */
+#define AMPDU_RX_BA_DEF_WSIZE   64	/* max Rx ba window size (in pdu) */
+#define AMPDU_RX_BA_MAX_WSIZE   64	/* default Rx ba window size (in pdu) */
+#define	AMPDU_MAX_DUR		5	/* max dur of tx ampdu (in msec) */
+#define AMPDU_DEF_RETRY_LIMIT	5	/* default tx retry limit */
+#define AMPDU_DEF_RR_RETRY_LIMIT	2	/* default tx retry limit at reg rate */
+#define AMPDU_DEF_TXPKT_WEIGHT	2	/* default weight of ampdu in txfifo */
+#define AMPDU_DEF_FFPLD_RSVD	2048	/* default ffpld reserved bytes */
+#define AMPDU_INI_FREE		10	/* # of inis to be freed on detach */
+#define	AMPDU_SCB_MAX_RELEASE	20	/* max # of mpdus released at a time */
+
+#define NUM_FFPLD_FIFO 4	/* number of fifo concerned by pre-loading */
+#define FFPLD_TX_MAX_UNFL   200	/* default value of the average number of ampdu
+				 * without underflows
+				 */
+#define FFPLD_MPDU_SIZE 1800	/* estimate of maximum mpdu size */
+#define FFPLD_MAX_MCS 23	/* we don't deal with mcs 32 */
+#define FFPLD_PLD_INCR 1000	/* increments in bytes */
+#define FFPLD_MAX_AMPDU_CNT 5000	/* maximum number of ampdu we
+					 * accumulate between resets.
+					 */
+
+#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
+
+/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
+#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
+	AMPDU_DELIMITER_LEN + 3\
+	+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
+
+#ifdef BCMDBG
+u32 wl_ampdu_dbg =
+    WL_AMPDU_UPDN_VAL |
+    WL_AMPDU_ERR_VAL |
+    WL_AMPDU_TX_VAL |
+    WL_AMPDU_RX_VAL |
+    WL_AMPDU_CTL_VAL |
+    WL_AMPDU_HW_VAL | WL_AMPDU_HWTXS_VAL | WL_AMPDU_HWDBG_VAL;
+#endif
+
+/* structure to hold tx fifo information and pre-loading state
+ * counters specific to tx underflows of ampdus
+ * some counters might be redundant with the ones in wlc or ampdu structures.
+ * This allows to maintain a specific state independantly of
+ * how often and/or when the wlc counters are updated.
+ */
+typedef struct wlc_fifo_info {
+	u16 ampdu_pld_size;	/* number of bytes to be pre-loaded */
+	u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];	/* per-mcs max # of mpdus in an ampdu */
+	u16 prev_txfunfl;	/* num of underflows last read from the HW macstats counter */
+	u32 accum_txfunfl;	/* num of underflows since we modified pld params */
+	u32 accum_txampdu;	/* num of tx ampdu since we modified pld params  */
+	u32 prev_txampdu;	/* previous reading of tx ampdu */
+	u32 dmaxferrate;	/* estimated dma avg xfer rate in kbits/sec */
+} wlc_fifo_info_t;
+
+/* AMPDU module specific state */
+struct ampdu_info {
+	struct wlc_info *wlc;	/* pointer to main wlc structure */
+	int scb_handle;		/* scb cubby handle to retrieve data from scb */
+	u8 ini_enable[AMPDU_MAX_SCB_TID];	/* per-tid initiator enable/disable of ampdu */
+	u8 ba_tx_wsize;	/* Tx ba window size (in pdu) */
+	u8 ba_rx_wsize;	/* Rx ba window size (in pdu) */
+	u8 retry_limit;	/* mpdu transmit retry limit */
+	u8 rr_retry_limit;	/* mpdu transmit retry limit at regular rate */
+	u8 retry_limit_tid[AMPDU_MAX_SCB_TID];	/* per-tid mpdu transmit retry limit */
+	/* per-tid mpdu transmit retry limit at regular rate */
+	u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
+	u8 mpdu_density;	/* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
+	s8 max_pdu;		/* max pdus allowed in ampdu */
+	u8 dur;		/* max duration of an ampdu (in msec) */
+	u8 txpkt_weight;	/* weight of ampdu in txfifo; reduces rate lag */
+	u8 rx_factor;	/* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
+	u32 ffpld_rsvd;	/* number of bytes to reserve for preload */
+	u32 max_txlen[MCS_TABLE_SIZE][2][2];	/* max size of ampdu per mcs, bw and sgi */
+	void *ini_free[AMPDU_INI_FREE];	/* array of ini's to be freed on detach */
+	bool mfbr;		/* enable multiple fallback rate */
+	u32 tx_max_funl;	/* underflows should be kept such that
+				 * (tx_max_funfl*underflows) < tx frames
+				 */
+	wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO];	/* table of fifo infos  */
+
+};
+
+#define AMPDU_CLEANUPFLAG_RX   (0x1)
+#define AMPDU_CLEANUPFLAG_TX   (0x2)
+
+#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
+#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
+
+static void wlc_ffpld_init(struct ampdu_info *ampdu);
+static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
+static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
+
+static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
+						   scb_ampdu_t *scb_ampdu,
+						   u8 tid, bool override);
+static void ampdu_cleanup_tid_ini(struct ampdu_info *ampdu,
+				  scb_ampdu_t *scb_ampdu,
+				  u8 tid, bool force);
+static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
+static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
+static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
+
+#define wlc_ampdu_txflowcontrol(a, b, c)	do {} while (0)
+
+static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
+					  struct scb *scb,
+					  struct sk_buff *p, tx_status_t *txs,
+					  u32 frmtxstatus, u32 frmtxstatus2);
+static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
+static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
+
+struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
+{
+	struct ampdu_info *ampdu;
+	int i;
+
+	/* some code depends on packed structures */
+	ASSERT(DOT11_MAXNUMFRAGS == NBITS(u16));
+	ASSERT(ISPOWEROF2(AMPDU_TX_BA_MAX_WSIZE));
+	ASSERT(ISPOWEROF2(AMPDU_RX_BA_MAX_WSIZE));
+	ASSERT(wlc->pub->tunables->ampdunummpdu <= AMPDU_MAX_MPDU);
+	ASSERT(wlc->pub->tunables->ampdunummpdu > 0);
+
+	ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
+	if (!ampdu) {
+		WL_ERROR("wl%d: wlc_ampdu_attach: out of mem\n",
+			 wlc->pub->unit);
+		return NULL;
+	}
+	ampdu->wlc = wlc;
+
+	for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
+		ampdu->ini_enable[i] = true;
+	/* Disable ampdu for VO by default */
+	ampdu->ini_enable[PRIO_8021D_VO] = false;
+	ampdu->ini_enable[PRIO_8021D_NC] = false;
+
+	/* Disable ampdu for BK by default since not enough fifo space */
+	ampdu->ini_enable[PRIO_8021D_NONE] = false;
+	ampdu->ini_enable[PRIO_8021D_BK] = false;
+
+	ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
+	ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
+	ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
+	ampdu->max_pdu = AUTO;
+	ampdu->dur = AMPDU_MAX_DUR;
+	ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
+
+	ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
+	/* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
+	if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
+		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
+	else
+		ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
+	ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
+	ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
+
+	for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
+		ampdu->retry_limit_tid[i] = ampdu->retry_limit;
+		ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
+	}
+
+	ampdu_update_max_txlen(ampdu, ampdu->dur);
+	ampdu->mfbr = false;
+	/* try to set ampdu to the default value */
+	wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
+
+	ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
+	wlc_ffpld_init(ampdu);
+
+	return ampdu;
+}
+
+void wlc_ampdu_detach(struct ampdu_info *ampdu)
+{
+	int i;
+
+	if (!ampdu)
+		return;
+
+	/* free all ini's which were to be freed on callbacks which were never called */
+	for (i = 0; i < AMPDU_INI_FREE; i++) {
+		kfree(ampdu->ini_free[i]);
+	}
+
+	wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
+	kfree(ampdu);
+}
+
+void scb_ampdu_cleanup(struct ampdu_info *ampdu, struct scb *scb)
+{
+	scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	u8 tid;
+
+	WL_AMPDU_UPDN("scb_ampdu_cleanup: enter\n");
+	ASSERT(scb_ampdu);
+
+	for (tid = 0; tid < AMPDU_MAX_SCB_TID; tid++) {
+		ampdu_cleanup_tid_ini(ampdu, scb_ampdu, tid, false);
+	}
+}
+
+/* reset the ampdu state machine so that it can gracefully handle packets that were
+ * freed from the dma and tx queues during reinit
+ */
+void wlc_ampdu_reset(struct ampdu_info *ampdu)
+{
+	WL_NONE("%s: Entering\n", __func__);
+}
+
+static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
+{
+	scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	int i;
+
+	scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
+
+	/* go back to legacy size if some preloading is occuring */
+	for (i = 0; i < NUM_FFPLD_FIFO; i++) {
+		if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
+			scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
+	}
+
+	/* apply user override */
+	if (ampdu->max_pdu != AUTO)
+		scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
+
+	scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
+
+	if (scb_ampdu->max_rxlen)
+		scb_ampdu->release =
+		    min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
+
+	scb_ampdu->release = min(scb_ampdu->release,
+				 ampdu->fifo_tb[TX_AC_BE_FIFO].
+				 mcs2ampdu_table[FFPLD_MAX_MCS]);
+
+	ASSERT(scb_ampdu->release);
+}
+
+void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
+{
+	scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
+}
+
+static void wlc_ffpld_init(struct ampdu_info *ampdu)
+{
+	int i, j;
+	wlc_fifo_info_t *fifo;
+
+	for (j = 0; j < NUM_FFPLD_FIFO; j++) {
+		fifo = (ampdu->fifo_tb + j);
+		fifo->ampdu_pld_size = 0;
+		for (i = 0; i <= FFPLD_MAX_MCS; i++)
+			fifo->mcs2ampdu_table[i] = 255;
+		fifo->dmaxferrate = 0;
+		fifo->accum_txampdu = 0;
+		fifo->prev_txfunfl = 0;
+		fifo->accum_txfunfl = 0;
+
+	}
+}
+
+/* evaluate the dma transfer rate using the tx underflows as feedback.
+ * If necessary, increase tx fifo preloading. If not enough,
+ * decrease maximum ampdu size for each mcs till underflows stop
+ * Return 1 if pre-loading not active, -1 if not an underflow event,
+ * 0 if pre-loading module took care of the event.
+ */
+static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
+{
+	struct ampdu_info *ampdu = wlc->ampdu;
+	u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
+	u32 txunfl_ratio;
+	u8 max_mpdu;
+	u32 current_ampdu_cnt = 0;
+	u16 max_pld_size;
+	u32 new_txunfl;
+	wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
+	uint xmtfifo_sz;
+	u16 cur_txunfl;
+
+	/* return if we got here for a different reason than underflows */
+	cur_txunfl =
+	    wlc_read_shm(wlc,
+			 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
+	new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
+	if (new_txunfl == 0) {
+		WL_FFPLD("check_txunfl : TX status FRAG set but no tx underflows\n");
+		return -1;
+	}
+	fifo->prev_txfunfl = cur_txunfl;
+
+	if (!ampdu->tx_max_funl)
+		return 1;
+
+	/* check if fifo is big enough */
+	if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
+		WL_FFPLD("check_txunfl : get xmtfifo_sz failed\n");
+		return -1;
+	}
+
+	if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
+		return 1;
+
+	max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
+	fifo->accum_txfunfl += new_txunfl;
+
+	/* we need to wait for at least 10 underflows */
+	if (fifo->accum_txfunfl < 10)
+		return 0;
+
+	WL_FFPLD("ampdu_count %d  tx_underflows %d\n",
+		 current_ampdu_cnt, fifo->accum_txfunfl);
+
+	/*
+	   compute the current ratio of tx unfl per ampdu.
+	   When the current ampdu count becomes too
+	   big while the ratio remains small, we reset
+	   the current count in order to not
+	   introduce too big of a latency in detecting a
+	   large amount of tx underflows later.
+	 */
+
+	txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
+
+	if (txunfl_ratio > ampdu->tx_max_funl) {
+		if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
+			fifo->accum_txfunfl = 0;
+		}
+		return 0;
+	}
+	max_mpdu =
+	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
+
+	/* In case max value max_pdu is already lower than
+	   the fifo depth, there is nothing more we can do.
+	 */
+
+	if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
+		WL_FFPLD(("tx fifo pld : max ampdu fits in fifo\n)"));
+		fifo->accum_txfunfl = 0;
+		return 0;
+	}
+
+	if (fifo->ampdu_pld_size < max_pld_size) {
+
+		/* increment by TX_FIFO_PLD_INC bytes */
+		fifo->ampdu_pld_size += FFPLD_PLD_INCR;
+		if (fifo->ampdu_pld_size > max_pld_size)
+			fifo->ampdu_pld_size = max_pld_size;
+
+		/* update scb release size */
+		scb_ampdu_update_config_all(ampdu);
+
+		/*
+		   compute a new dma xfer rate for max_mpdu @ max mcs.
+		   This is the minimum dma rate that
+		   can acheive no unferflow condition for the current mpdu size.
+		 */
+		/* note : we divide/multiply by 100 to avoid integer overflows */
+		fifo->dmaxferrate =
+		    (((phy_rate / 100) *
+		      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+		     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+
+		WL_FFPLD("DMA estimated transfer rate %d; pre-load size %d\n",
+			 fifo->dmaxferrate, fifo->ampdu_pld_size);
+	} else {
+
+		/* decrease ampdu size */
+		if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
+			if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
+				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
+				    AMPDU_NUM_MPDU_LEGACY - 1;
+			else
+				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
+
+			/* recompute the table */
+			wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
+
+			/* update scb release size */
+			scb_ampdu_update_config_all(ampdu);
+		}
+	}
+	fifo->accum_txfunfl = 0;
+	return 0;
+}
+
+static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
+{
+	int i;
+	u32 phy_rate, dma_rate, tmp;
+	u8 max_mpdu;
+	wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
+
+	/* recompute the dma rate */
+	/* note : we divide/multiply by 100 to avoid integer overflows */
+	max_mpdu =
+	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
+	phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
+	dma_rate =
+	    (((phy_rate / 100) *
+	      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
+	     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
+	fifo->dmaxferrate = dma_rate;
+
+	/* fill up the mcs2ampdu table; do not recalc the last mcs */
+	dma_rate = dma_rate >> 7;
+	for (i = 0; i < FFPLD_MAX_MCS; i++) {
+		/* shifting to keep it within integer range */
+		phy_rate = MCS_RATE(i, true, false) >> 7;
+		if (phy_rate > dma_rate) {
+			tmp = ((fifo->ampdu_pld_size * phy_rate) /
+			       ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
+			tmp = min_t(u32, tmp, 255);
+			fifo->mcs2ampdu_table[i] = (u8) tmp;
+		}
+	}
+}
+
+static void BCMFASTPATH
+wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
+	      uint prec)
+{
+	scb_ampdu_t *scb_ampdu;
+	scb_ampdu_tid_ini_t *ini;
+	u8 tid = (u8) (p->priority);
+
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+
+	/* initialize initiator on first packet; sends addba req */
+	ini = SCB_AMPDU_INI(scb_ampdu, tid);
+	if (ini->magic != INI_MAGIC) {
+		ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
+	}
+	return;
+}
+
+int BCMFASTPATH
+wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
+	      struct sk_buff **pdu, int prec)
+{
+	struct wlc_info *wlc;
+	struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
+	u8 tid, ndelim;
+	int err = 0;
+	u8 preamble_type = WLC_GF_PREAMBLE;
+	u8 fbr_preamble_type = WLC_GF_PREAMBLE;
+	u8 rts_preamble_type = WLC_LONG_PREAMBLE;
+	u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
+
+	bool rr = true, fbr = false;
+	uint i, count = 0, fifo, seg_cnt = 0;
+	u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
+	u32 ampdu_len, maxlen = 0;
+	d11txh_t *txh = NULL;
+	u8 *plcp;
+	struct ieee80211_hdr *h;
+	struct scb *scb;
+	scb_ampdu_t *scb_ampdu;
+	scb_ampdu_tid_ini_t *ini;
+	u8 mcs = 0;
+	bool use_rts = false, use_cts = false;
+	ratespec_t rspec = 0, rspec_fallback = 0;
+	ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+	struct ieee80211_rts *rts;
+	u8 rr_retry_limit;
+	wlc_fifo_info_t *f;
+	bool fbr_iscck;
+	struct ieee80211_tx_info *tx_info;
+	u16 qlen;
+
+	wlc = ampdu->wlc;
+	p = *pdu;
+
+	ASSERT(p);
+
+	tid = (u8) (p->priority);
+	ASSERT(tid < AMPDU_MAX_SCB_TID);
+
+	f = ampdu->fifo_tb + prio2fifo[tid];
+
+	scb = wlc->pub->global_scb;
+	ASSERT(scb->magic == SCB_MAGIC);
+
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	ASSERT(scb_ampdu);
+	ini = &scb_ampdu->ini[tid];
+
+	/* Let pressure continue to build ... */
+	qlen = pktq_plen(&qi->q, prec);
+	if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
+		return BCME_BUSY;
+	}
+
+	wlc_ampdu_agg(ampdu, scb, p, tid);
+
+	if (wlc->block_datafifo) {
+		WL_ERROR("%s: Fifo blocked\n", __func__);
+		return BCME_BUSY;
+	}
+	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
+	ampdu_len = 0;
+	dma_len = 0;
+	while (p) {
+		struct ieee80211_tx_rate *txrate;
+
+		tx_info = IEEE80211_SKB_CB(p);
+		txrate = tx_info->status.rates;
+
+		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+			err = wlc_prep_pdu(wlc, p, &fifo);
+		} else {
+			WL_ERROR("%s: AMPDU flag is off!\n", __func__);
+			*pdu = NULL;
+			err = 0;
+			break;
+		}
+
+		if (err) {
+			if (err == BCME_BUSY) {
+				WL_ERROR("wl%d: wlc_sendampdu: prep_xdu retry; seq 0x%x\n",
+					 wlc->pub->unit, seq);
+				WLCNTINCR(ampdu->cnt->sduretry);
+				*pdu = p;
+				break;
+			}
+
+			/* error in the packet; reject it */
+			WL_AMPDU_ERR("wl%d: wlc_sendampdu: prep_xdu rejected; seq 0x%x\n",
+				     wlc->pub->unit, seq);
+			WLCNTINCR(ampdu->cnt->sdurejected);
+
+			*pdu = NULL;
+			break;
+		}
+
+		/* pkt is good to be aggregated */
+		ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+		txh = (d11txh_t *) p->data;
+		plcp = (u8 *) (txh + 1);
+		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
+		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
+		index = TX_SEQ_TO_INDEX(seq);
+
+		/* check mcl fields and test whether it can be agg'd */
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		mcl &= ~TXC_AMPDU_MASK;
+		fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
+		ASSERT(!fbr_iscck);
+		txh->PreloadSize = 0;	/* always default to 0 */
+
+		/*  Handle retry limits */
+		if (txrate[0].count <= rr_retry_limit) {
+			txrate[0].count++;
+			rr = true;
+			fbr = false;
+			ASSERT(!fbr);
+		} else {
+			fbr = true;
+			rr = false;
+			txrate[1].count++;
+		}
+
+		/* extract the length info */
+		len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
+		    : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+
+		/* retrieve null delimiter count */
+		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+		seg_cnt += 1;
+
+		WL_AMPDU_TX("wl%d: wlc_sendampdu: mpdu %d plcp_len %d\n",
+			    wlc->pub->unit, count, len);
+
+		/*
+		 * aggregateable mpdu. For ucode/hw agg,
+		 * test whether need to break or change the epoch
+		 */
+		if (count == 0) {
+			mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
+			/* refill the bits since might be a retx mpdu */
+			mcl |= TXC_STARTMSDU;
+			rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+			if (ieee80211_is_rts(rts->frame_control)) {
+				mcl |= TXC_SENDRTS;
+				use_rts = true;
+			}
+			if (ieee80211_is_cts(rts->frame_control)) {
+				mcl |= TXC_SENDCTS;
+				use_cts = true;
+			}
+		} else {
+			mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
+			mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
+		}
+
+		len = roundup(len, 4);
+		ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
+
+		dma_len += (u16) pkttotlen(p);
+
+		WL_AMPDU_TX("wl%d: wlc_sendampdu: ampdu_len %d seg_cnt %d null delim %d\n",
+			    wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
+
+		txh->MacTxControlLow = cpu_to_le16(mcl);
+
+		/* this packet is added */
+		pkt[count++] = p;
+
+		/* patch the first MPDU */
+		if (count == 1) {
+			u8 plcp0, plcp3, is40, sgi;
+			struct ieee80211_sta *sta;
+
+			sta = tx_info->control.sta;
+
+			if (rr) {
+				plcp0 = plcp[0];
+				plcp3 = plcp[3];
+			} else {
+				plcp0 = txh->FragPLCPFallback[0];
+				plcp3 = txh->FragPLCPFallback[3];
+
+			}
+			is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
+			sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
+			mcs = plcp0 & ~MIMO_PLCP_40MHZ;
+			ASSERT(mcs < MCS_TABLE_SIZE);
+			maxlen =
+			    min(scb_ampdu->max_rxlen,
+				ampdu->max_txlen[mcs][is40][sgi]);
+
+			WL_NONE("sendampdu: sgi %d, is40 %d, mcs %d\n",
+				sgi, is40, mcs);
+
+			maxlen = 64 * 1024;	/* XXX Fix me to honor real max_rxlen */
+
+			if (is40)
+				mimo_ctlchbw =
+				    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
+				    ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
+
+			/* rebuild the rspec and rspec_fallback */
+			rspec = RSPEC_MIMORATE;
+			rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
+			if (plcp[0] & MIMO_PLCP_40MHZ)
+				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
+
+			if (fbr_iscck)	/* CCK */
+				rspec_fallback =
+				    CCK_RSPEC(CCK_PHY2MAC_RATE
+					      (txh->FragPLCPFallback[0]));
+			else {	/* MIMO */
+				rspec_fallback = RSPEC_MIMORATE;
+				rspec_fallback |=
+				    txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
+				if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
+					rspec_fallback |=
+					    (PHY_TXC1_BW_40MHZ <<
+					     RSPEC_BW_SHIFT);
+			}
+
+			if (use_rts || use_cts) {
+				rts_rspec =
+				    wlc_rspec_to_rts_rspec(wlc, rspec, false,
+							   mimo_ctlchbw);
+				rts_rspec_fallback =
+				    wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
+							   false, mimo_ctlchbw);
+			}
+		}
+
+		/* if (first mpdu for host agg) */
+		/* test whether to add more */
+		if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
+		    (count == f->mcs2ampdu_table[mcs])) {
+			WL_AMPDU_ERR("wl%d: PR 37644: stopping ampdu at %d for mcs %d\n",
+				     wlc->pub->unit, count, mcs);
+			break;
+		}
+
+		if (count == scb_ampdu->max_pdu) {
+			WL_NONE("Stop taking from q, reached %d deep\n",
+				scb_ampdu->max_pdu);
+			break;
+		}
+
+		/* check to see if the next pkt is a candidate for aggregation */
+		p = pktq_ppeek(&qi->q, prec);
+		tx_info = IEEE80211_SKB_CB(p);	/* tx_info must be checked with current p */
+
+		if (p) {
+			if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+			    ((u8) (p->priority) == tid)) {
+
+				plen =
+				    pkttotlen(p) + AMPDU_MAX_MPDU_OVERHEAD;
+				plen = max(scb_ampdu->min_len, plen);
+
+				if ((plen + ampdu_len) > maxlen) {
+					p = NULL;
+					WL_ERROR("%s: Bogus plen #1\n",
+						 __func__);
+					ASSERT(3 == 4);
+					continue;
+				}
+
+				/* check if there are enough descriptors available */
+				if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
+					WL_ERROR("%s: No fifo space   !!!!!!\n",
+						 __func__);
+					p = NULL;
+					continue;
+				}
+				p = pktq_pdeq(&qi->q, prec);
+				ASSERT(p);
+			} else {
+				p = NULL;
+			}
+		}
+	}			/* end while(p) */
+
+	ini->tx_in_transit += count;
+
+	if (count) {
+		WLCNTADD(ampdu->cnt->txmpdu, count);
+
+		/* patch up the last txh */
+		txh = (d11txh_t *) pkt[count - 1]->data;
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		mcl &= ~TXC_AMPDU_MASK;
+		mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
+		txh->MacTxControlLow = cpu_to_le16(mcl);
+
+		/* remove the null delimiter after last mpdu */
+		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
+		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
+		ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
+
+		/* remove the pad len from last mpdu */
+		fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
+		len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
+		    : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
+		ampdu_len -= roundup(len, 4) - len;
+
+		/* patch up the first txh & plcp */
+		txh = (d11txh_t *) pkt[0]->data;
+		plcp = (u8 *) (txh + 1);
+
+		WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
+		/* mark plcp to indicate ampdu */
+		WLC_SET_MIMO_PLCP_AMPDU(plcp);
+
+		/* reset the mixed mode header durations */
+		if (txh->MModeLen) {
+			u16 mmodelen =
+			    wlc_calc_lsig_len(wlc, rspec, ampdu_len);
+			txh->MModeLen = cpu_to_le16(mmodelen);
+			preamble_type = WLC_MM_PREAMBLE;
+		}
+		if (txh->MModeFbrLen) {
+			u16 mmfbrlen =
+			    wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
+			txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
+			fbr_preamble_type = WLC_MM_PREAMBLE;
+		}
+
+		/* set the preload length */
+		if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
+			dma_len = min(dma_len, f->ampdu_pld_size);
+			txh->PreloadSize = cpu_to_le16(dma_len);
+		} else
+			txh->PreloadSize = 0;
+
+		mch = le16_to_cpu(txh->MacTxControlHigh);
+
+		/* update RTS dur fields */
+		if (use_rts || use_cts) {
+			u16 durid;
+			rts = (struct ieee80211_rts *)&txh->rts_frame;
+			if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
+			    TXC_PREAMBLE_RTS_MAIN_SHORT)
+				rts_preamble_type = WLC_SHORT_PREAMBLE;
+
+			if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
+			    TXC_PREAMBLE_RTS_FB_SHORT)
+				rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
+
+			durid =
+			    wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
+						   rspec, rts_preamble_type,
+						   preamble_type, ampdu_len,
+						   true);
+			rts->duration = cpu_to_le16(durid);
+			durid = wlc_compute_rtscts_dur(wlc, use_cts,
+						       rts_rspec_fallback,
+						       rspec_fallback,
+						       rts_fbr_preamble_type,
+						       fbr_preamble_type,
+						       ampdu_len, true);
+			txh->RTSDurFallback = cpu_to_le16(durid);
+			/* set TxFesTimeNormal */
+			txh->TxFesTimeNormal = rts->duration;
+			/* set fallback rate version of TxFesTimeNormal */
+			txh->TxFesTimeFallback = txh->RTSDurFallback;
+		}
+
+		/* set flag and plcp for fallback rate */
+		if (fbr) {
+			WLCNTADD(ampdu->cnt->txfbr_mpdu, count);
+			WLCNTINCR(ampdu->cnt->txfbr_ampdu);
+			mch |= TXC_AMPDU_FBR;
+			txh->MacTxControlHigh = cpu_to_le16(mch);
+			WLC_SET_MIMO_PLCP_AMPDU(plcp);
+			WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
+		}
+
+		WL_AMPDU_TX("wl%d: wlc_sendampdu: count %d ampdu_len %d\n",
+			    wlc->pub->unit, count, ampdu_len);
+
+		/* inform rate_sel if it this is a rate probe pkt */
+		frameid = le16_to_cpu(txh->TxFrameID);
+		if (frameid & TXFID_RATE_PROBE_MASK) {
+			WL_ERROR("%s: XXX what to do with TXFID_RATE_PROBE_MASK!?\n",
+				 __func__);
+		}
+		for (i = 0; i < count; i++)
+			wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
+				   ampdu->txpkt_weight);
+
+	}
+	/* endif (count) */
+	return err;
+}
+
+void BCMFASTPATH
+wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+		     struct sk_buff *p, tx_status_t *txs)
+{
+	scb_ampdu_t *scb_ampdu;
+	struct wlc_info *wlc = ampdu->wlc;
+	scb_ampdu_tid_ini_t *ini;
+	u32 s1 = 0, s2 = 0;
+	struct ieee80211_tx_info *tx_info;
+
+	tx_info = IEEE80211_SKB_CB(p);
+	ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+	ASSERT(txs->status & TX_STATUS_AMPDU);
+
+	/* BMAC_NOTE: For the split driver, second level txstatus comes later
+	 * So if the ACK was received then wait for the second level else just
+	 * call the first one
+	 */
+	if (txs->status & TX_STATUS_ACK_RCV) {
+		u8 status_delay = 0;
+
+		/* wait till the next 8 bytes of txstatus is available */
+		while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
+			udelay(1);
+			status_delay++;
+			if (status_delay > 10) {
+				ASSERT(status_delay <= 10);
+				return;
+			}
+		}
+
+		ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
+		ASSERT(s1 & TX_STATUS_AMPDU);
+		s2 = R_REG(&wlc->regs->frmtxstatus2);
+	}
+
+	if (likely(scb)) {
+		ASSERT(scb->magic == SCB_MAGIC);
+		scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+		ASSERT(scb_ampdu);
+		ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
+		ASSERT(ini->scb == scb);
+		wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
+	} else {
+		/* loop through all pkts and free */
+		u8 queue = txs->frameid & TXFID_QUEUE_MASK;
+		d11txh_t *txh;
+		u16 mcl;
+		while (p) {
+			tx_info = IEEE80211_SKB_CB(p);
+			txh = (d11txh_t *) p->data;
+			mcl = le16_to_cpu(txh->MacTxControlLow);
+			ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+			pkt_buf_free_skb(p);
+			/* break out if last packet of ampdu */
+			if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+			    TXC_AMPDU_LAST)
+				break;
+			p = GETNEXTTXP(wlc, queue);
+			ASSERT(p != NULL);
+		}
+		wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
+	}
+	wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
+}
+
+void
+rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
+	    tx_status_t *txs, u8 mcs)
+{
+	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
+	int i;
+
+	/* clear the rest of the rates */
+	for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+		txrate[i].idx = -1;
+		txrate[i].count = 0;
+	}
+}
+
+#define SHORTNAME "AMPDU status"
+
+static void BCMFASTPATH
+wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
+			      struct sk_buff *p, tx_status_t *txs,
+			      u32 s1, u32 s2)
+{
+	scb_ampdu_t *scb_ampdu;
+	struct wlc_info *wlc = ampdu->wlc;
+	scb_ampdu_tid_ini_t *ini;
+	u8 bitmap[8], queue, tid;
+	d11txh_t *txh;
+	u8 *plcp;
+	struct ieee80211_hdr *h;
+	u16 seq, start_seq = 0, bindex, index, mcl;
+	u8 mcs = 0;
+	bool ba_recd = false, ack_recd = false;
+	u8 suc_mpdu = 0, tot_mpdu = 0;
+	uint supr_status;
+	bool update_rate = true, retry = true, tx_error = false;
+	u16 mimoantsel = 0;
+	u8 antselid = 0;
+	u8 retry_limit, rr_retry_limit;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
+
+#ifdef BCMDBG
+	u8 hole[AMPDU_MAX_MPDU];
+	memset(hole, 0, sizeof(hole));
+#endif
+
+	ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+	ASSERT(txs->status & TX_STATUS_AMPDU);
+
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	ASSERT(scb_ampdu);
+
+	tid = (u8) (p->priority);
+
+	ini = SCB_AMPDU_INI(scb_ampdu, tid);
+	retry_limit = ampdu->retry_limit_tid[tid];
+	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
+
+	ASSERT(ini->scb == scb);
+
+	memset(bitmap, 0, sizeof(bitmap));
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	ASSERT(queue < AC_COUNT);
+
+	supr_status = txs->status & TX_STATUS_SUPR_MASK;
+
+	if (txs->status & TX_STATUS_ACK_RCV) {
+		if (TX_STATUS_SUPR_UF == supr_status) {
+			update_rate = false;
+		}
+
+		ASSERT(txs->status & TX_STATUS_INTERMEDIATE);
+		start_seq = txs->sequence >> SEQNUM_SHIFT;
+		bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
+		    TX_STATUS_BA_BMAP03_SHIFT;
+
+		ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
+		ASSERT(s1 & TX_STATUS_AMPDU);
+
+		bitmap[0] |=
+		    (s1 & TX_STATUS_BA_BMAP47_MASK) <<
+		    TX_STATUS_BA_BMAP47_SHIFT;
+		bitmap[1] = (s1 >> 8) & 0xff;
+		bitmap[2] = (s1 >> 16) & 0xff;
+		bitmap[3] = (s1 >> 24) & 0xff;
+
+		bitmap[4] = s2 & 0xff;
+		bitmap[5] = (s2 >> 8) & 0xff;
+		bitmap[6] = (s2 >> 16) & 0xff;
+		bitmap[7] = (s2 >> 24) & 0xff;
+
+		ba_recd = true;
+	} else {
+		WLCNTINCR(ampdu->cnt->noba);
+		if (supr_status) {
+			update_rate = false;
+			if (supr_status == TX_STATUS_SUPR_BADCH) {
+				WL_ERROR("%s: Pkt tx suppressed, illegal channel possibly %d\n",
+					 __func__,
+					 CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+			} else {
+				if (supr_status == TX_STATUS_SUPR_FRAG)
+					WL_NONE("%s: AMPDU frag err\n",
+						__func__);
+				else
+					WL_ERROR("%s: wlc_ampdu_dotxstatus: supr_status 0x%x\n",
+						 __func__, supr_status);
+			}
+			/* no need to retry for badch; will fail again */
+			if (supr_status == TX_STATUS_SUPR_BADCH ||
+			    supr_status == TX_STATUS_SUPR_EXPTIME) {
+				retry = false;
+				wlc->pub->_cnt->txchanrej++;
+			} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
+
+				wlc->pub->_cnt->txexptime++;
+
+				/* TX underflow : try tuning pre-loading or ampdu size */
+			} else if (supr_status == TX_STATUS_SUPR_FRAG) {
+				/* if there were underflows, but pre-loading is not active,
+				   notify rate adaptation.
+				 */
+				if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
+				    > 0) {
+					tx_error = true;
+				}
+			}
+		} else if (txs->phyerr) {
+			update_rate = false;
+			wlc->pub->_cnt->txphyerr++;
+			WL_ERROR("wl%d: wlc_ampdu_dotxstatus: tx phy error (0x%x)\n",
+				 wlc->pub->unit, txs->phyerr);
+
+			if (WL_ERROR_ON()) {
+				prpkt("txpkt (AMPDU)", p);
+				wlc_print_txdesc((d11txh_t *) p->data);
+			}
+			wlc_print_txstatus(txs);
+		}
+	}
+
+	/* loop through all pkts and retry if not acked */
+	while (p) {
+		tx_info = IEEE80211_SKB_CB(p);
+		ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
+		txh = (d11txh_t *) p->data;
+		mcl = le16_to_cpu(txh->MacTxControlLow);
+		plcp = (u8 *) (txh + 1);
+		h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
+		seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
+
+		if (tot_mpdu == 0) {
+			mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
+			mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
+		}
+
+		index = TX_SEQ_TO_INDEX(seq);
+		ack_recd = false;
+		if (ba_recd) {
+			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
+
+			WL_AMPDU_TX("%s: tid %d seq is %d, start_seq is %d, bindex is %d set %d, index %d\n",
+				    __func__, tid, seq, start_seq, bindex,
+				    isset(bitmap, bindex), index);
+
+			/* if acked then clear bit and free packet */
+			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
+			    && isset(bitmap, bindex)) {
+				ini->tx_in_transit--;
+				ini->txretry[index] = 0;
+
+				/* ampdu_ack_len: number of acked aggregated frames */
+				/* ampdu_ack_map: block ack bit map for the aggregation */
+				/* ampdu_len: number of aggregated frames */
+				rate_status(wlc, tx_info, txs, mcs);
+				tx_info->flags |= IEEE80211_TX_STAT_ACK;
+				tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+
+				/* XXX TODO: Make these accurate. */
+				tx_info->status.ampdu_ack_len =
+				    (txs->
+				     status & TX_STATUS_FRM_RTX_MASK) >>
+				    TX_STATUS_FRM_RTX_SHIFT;
+				tx_info->status.ampdu_len =
+				    (txs->
+				     status & TX_STATUS_FRM_RTX_MASK) >>
+				    TX_STATUS_FRM_RTX_SHIFT;
+
+				skb_pull(p, D11_PHY_HDR_LEN);
+				skb_pull(p, D11_TXH_LEN);
+
+				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
+							    p);
+				ack_recd = true;
+				suc_mpdu++;
+			}
+		}
+		/* either retransmit or send bar if ack not recd */
+		if (!ack_recd) {
+			struct ieee80211_tx_rate *txrate =
+			    tx_info->status.rates;
+			if (retry && (txrate[0].count < (int)retry_limit)) {
+				ini->txretry[index]++;
+				ini->tx_in_transit--;
+				/* Use high prededence for retransmit to give some punch */
+				/* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
+				wlc_txq_enq(wlc, scb, p,
+					    WLC_PRIO_TO_HI_PREC(tid));
+			} else {
+				/* Retry timeout */
+				ini->tx_in_transit--;
+				ieee80211_tx_info_clear_status(tx_info);
+				tx_info->flags |=
+				    IEEE80211_TX_STAT_AMPDU_NO_BACK;
+				skb_pull(p, D11_PHY_HDR_LEN);
+				skb_pull(p, D11_TXH_LEN);
+				WL_ERROR("%s: BA Timeout, seq %d, in_transit %d\n",
+					 SHORTNAME, seq, ini->tx_in_transit);
+				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
+							    p);
+			}
+		}
+		tot_mpdu++;
+
+		/* break out if last packet of ampdu */
+		if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
+		    TXC_AMPDU_LAST)
+			break;
+
+		p = GETNEXTTXP(wlc, queue);
+		if (p == NULL) {
+			ASSERT(p);
+			break;
+		}
+	}
+	wlc_send_q(wlc, wlc->active_queue);
+
+	/* update rate state */
+	antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
+
+	wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
+}
+
+static void
+ampdu_cleanup_tid_ini(struct ampdu_info *ampdu, scb_ampdu_t *scb_ampdu, u8 tid,
+		      bool force)
+{
+	scb_ampdu_tid_ini_t *ini;
+	ini = SCB_AMPDU_INI(scb_ampdu, tid);
+	if (!ini)
+		return;
+
+	WL_AMPDU_CTL("wl%d: ampdu_cleanup_tid_ini: tid %d\n",
+		     ampdu->wlc->pub->unit, tid);
+
+	if (ini->tx_in_transit && !force)
+		return;
+
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, ini->scb);
+	ASSERT(ini == &scb_ampdu->ini[ini->tid]);
+
+	/* free all buffered tx packets */
+	pktq_pflush(&scb_ampdu->txq, ini->tid, true, NULL, 0);
+}
+
+/* initialize the initiator code for tid */
+static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
+						   scb_ampdu_t *scb_ampdu,
+						   u8 tid, bool override)
+{
+	scb_ampdu_tid_ini_t *ini;
+
+	ASSERT(scb_ampdu);
+	ASSERT(scb_ampdu->scb);
+	ASSERT(SCB_AMPDU(scb_ampdu->scb));
+	ASSERT(tid < AMPDU_MAX_SCB_TID);
+
+	/* check for per-tid control of ampdu */
+	if (!ampdu->ini_enable[tid]) {
+		WL_ERROR("%s: Rejecting tid %d\n", __func__, tid);
+		return NULL;
+	}
+
+	ini = SCB_AMPDU_INI(scb_ampdu, tid);
+	ini->tid = tid;
+	ini->scb = scb_ampdu->scb;
+	ini->magic = INI_MAGIC;
+	WLCNTINCR(ampdu->cnt->txaddbareq);
+
+	return ini;
+}
+
+static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
+{
+	struct wlc_info *wlc = ampdu->wlc;
+
+	wlc->pub->_ampdu = false;
+
+	if (on) {
+		if (!N_ENAB(wlc->pub)) {
+			WL_AMPDU_ERR("wl%d: driver not nmode enabled\n",
+				     wlc->pub->unit);
+			return BCME_UNSUPPORTED;
+		}
+		if (!wlc_ampdu_cap(ampdu)) {
+			WL_AMPDU_ERR("wl%d: device not ampdu capable\n",
+				     wlc->pub->unit);
+			return BCME_UNSUPPORTED;
+		}
+		wlc->pub->_ampdu = on;
+	}
+
+	return 0;
+}
+
+static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
+{
+	if (WLC_PHY_11N_CAP(ampdu->wlc->band))
+		return true;
+	else
+		return false;
+}
+
+static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
+{
+	u32 rate, mcs;
+
+	for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
+		/* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
+		/* 20MHz, No SGI */
+		rate = MCS_RATE(mcs, false, false);
+		ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
+		/* 40 MHz, No SGI */
+		rate = MCS_RATE(mcs, true, false);
+		ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
+		/* 20MHz, SGI */
+		rate = MCS_RATE(mcs, false, true);
+		ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
+		/* 40 MHz, SGI */
+		rate = MCS_RATE(mcs, true, true);
+		ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
+	}
+}
+
+u8 BCMFASTPATH
+wlc_ampdu_null_delim_cnt(struct ampdu_info *ampdu, struct scb *scb,
+			 ratespec_t rspec, int phylen)
+{
+	scb_ampdu_t *scb_ampdu;
+	int bytes, cnt, tmp;
+	u8 tx_density;
+
+	ASSERT(scb);
+	ASSERT(SCB_AMPDU(scb));
+
+	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
+	ASSERT(scb_ampdu);
+
+	if (scb_ampdu->mpdu_density == 0)
+		return 0;
+
+	/* RSPEC2RATE is in kbps units ==> ~RSPEC2RATE/2^13 is in bytes/usec
+	   density x is in 2^(x-4) usec
+	   ==> # of bytes needed for req density = rate/2^(17-x)
+	   ==> # of null delimiters = ceil(ceil(rate/2^(17-x)) - phylen)/4)
+	 */
+
+	tx_density = scb_ampdu->mpdu_density;
+
+	ASSERT(tx_density <= AMPDU_MAX_MPDU_DENSITY);
+	tmp = 1 << (17 - tx_density);
+	bytes = CEIL(RSPEC2RATE(rspec), tmp);
+
+	if (bytes > phylen) {
+		cnt = CEIL(bytes - phylen, AMPDU_DELIMITER_LEN);
+		ASSERT(cnt <= 255);
+		return (u8) cnt;
+	} else
+		return 0;
+}
+
+void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
+{
+	char template[T_RAM_ACCESS_SZ * 2];
+
+	/* driver needs to write the ta in the template; ta is at offset 16 */
+	memset(template, 0, sizeof(template));
+	memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
+	wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
+			       template);
+}
+
+bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
+{
+	return wlc->ampdu->ini_enable[tid];
+}
+
+void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
+{
+	struct wlc_info *wlc = ampdu->wlc;
+
+	/* Extend ucode internal watchdog timer to match larger received frames */
+	if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
+	    IEEE80211_HT_MAX_AMPDU_64K) {
+		wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
+		wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
+	} else {
+		wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
+		wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
+	}
+}
+
+struct cb_del_ampdu_pars {
+	struct ieee80211_sta *sta;
+	u16 tid;
+};
+
+/*
+ * callback function that helps flushing ampdu packets from a priority queue
+ */
+static bool cb_del_ampdu_pkt(void *p, int arg_a)
+{
+	struct sk_buff *mpdu = (struct sk_buff *)p;
+	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
+	struct cb_del_ampdu_pars *ampdu_pars =
+				 (struct cb_del_ampdu_pars *)arg_a;
+	bool rc;
+
+	rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
+	rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
+		    tx_info->control.sta == ampdu_pars->sta);
+	rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
+	return rc;
+}
+
+/*
+ * callback function that helps invalidating ampdu packets in a DMA queue
+ */
+static void dma_cb_fn_ampdu(void *txi, void *arg_a)
+{
+	struct ieee80211_sta *sta = arg_a;
+	struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
+
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+	    (tx_info->control.sta == sta || sta == NULL))
+		tx_info->control.sta = NULL;
+}
+
+/*
+ * When a remote party is no longer available for ampdu communication, any
+ * pending tx ampdu packets in the driver have to be flushed.
+ */
+void wlc_ampdu_flush(struct wlc_info *wlc,
+		     struct ieee80211_sta *sta, u16 tid)
+{
+	struct wlc_txq_info *qi = wlc->active_queue;
+	struct pktq *pq = &qi->q;
+	int prec;
+	struct cb_del_ampdu_pars ampdu_pars;
+
+	ampdu_pars.sta = sta;
+	ampdu_pars.tid = tid;
+	for (prec = 0; prec < pq->num_prec; prec++) {
+		pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
+			    (int)&ampdu_pars);
+	}
+	wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h
new file mode 100644
index 0000000..17e9ebc
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_ampdu_h_
+#define _wlc_ampdu_h_
+
+extern struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc);
+extern void wlc_ampdu_detach(struct ampdu_info *ampdu);
+extern int wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
+			 struct sk_buff **aggp, int prec);
+extern void wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
+				 struct sk_buff *p, tx_status_t *txs);
+extern void wlc_ampdu_reset(struct ampdu_info *ampdu);
+extern void wlc_ampdu_macaddr_upd(struct wlc_info *wlc);
+extern void wlc_ampdu_shm_upd(struct ampdu_info *ampdu);
+extern u8 wlc_ampdu_null_delim_cnt(struct ampdu_info *ampdu, struct scb *scb,
+				      ratespec_t rspec, int phylen);
+
+#endif				/* _wlc_ampdu_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_antsel.c b/drivers/staging/brcm80211/brcmsmac/wlc_antsel.c
new file mode 100644
index 0000000..85a73a9
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_antsel.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlc_cfg.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+#include <wlioctl.h>
+
+#include "d11.h"
+#include "wlc_rate.h"
+#include "wlc_key.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wl_dbg.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_bmac.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+#include "wl_export.h"
+#include "wlc_phy_shim.h"
+#include "wlc_antsel.h"
+
+/* useful macros */
+#define WLC_ANTSEL_11N_0(ant)	((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
+#define WLC_ANTSEL_11N_1(ant)	(((ant) & ANT_SELCFG_MASK) & 0xf)
+#define WLC_ANTIDX_11N(ant)	(((WLC_ANTSEL_11N_0(ant)) << 2) + (WLC_ANTSEL_11N_1(ant)))
+#define WLC_ANT_ISAUTO_11N(ant)	(((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
+#define WLC_ANTSEL_11N(ant)	((ant) & ANT_SELCFG_MASK)
+
+/* antenna switch */
+/* defines for no boardlevel antenna diversity */
+#define ANT_SELCFG_DEF_2x2	0x01	/* default antenna configuration */
+
+/* 2x3 antdiv defines and tables for GPIO communication */
+#define ANT_SELCFG_NUM_2x3	3
+#define ANT_SELCFG_DEF_2x3	0x01	/* default antenna configuration */
+
+/* 2x4 antdiv rev4 defines and tables for GPIO communication */
+#define ANT_SELCFG_NUM_2x4	4
+#define ANT_SELCFG_DEF_2x4	0x02	/* default antenna configuration */
+
+/* static functions */
+static int wlc_antsel_cfgupd(struct antsel_info *asi, wlc_antselcfg_t *antsel);
+static u8 wlc_antsel_id2antcfg(struct antsel_info *asi, u8 id);
+static u16 wlc_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
+static void wlc_antsel_init_cfg(struct antsel_info *asi,
+				wlc_antselcfg_t *antsel,
+				bool auto_sel);
+
+const u16 mimo_2x4_div_antselpat_tbl[] = {
+	0, 0, 0x9, 0xa,		/* ant0: 0 ant1: 2,3 */
+	0, 0, 0x5, 0x6,		/* ant0: 1 ant1: 2,3 */
+	0, 0, 0, 0,		/* n.a.              */
+	0, 0, 0, 0		/* n.a.              */
+};
+
+const u8 mimo_2x4_div_antselid_tbl[16] = {
+	0, 0, 0, 0, 0, 2, 3, 0,
+	0, 0, 1, 0, 0, 0, 0, 0	/* pat to antselid */
+};
+
+const u16 mimo_2x3_div_antselpat_tbl[] = {
+	16, 0, 1, 16,		/* ant0: 0 ant1: 1,2 */
+	16, 16, 16, 16,		/* n.a.              */
+	16, 2, 16, 16,		/* ant0: 2 ant1: 1   */
+	16, 16, 16, 16		/* n.a.              */
+};
+
+const u8 mimo_2x3_div_antselid_tbl[16] = {
+	0, 1, 2, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0	/* pat to antselid */
+};
+
+struct antsel_info *wlc_antsel_attach(struct wlc_info *wlc)
+{
+	struct antsel_info *asi;
+
+	asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
+	if (!asi) {
+		WL_ERROR("wl%d: wlc_antsel_attach: out of mem\n",
+			 wlc->pub->unit);
+		return NULL;
+	}
+
+	asi->wlc = wlc;
+	asi->pub = wlc->pub;
+	asi->antsel_type = ANTSEL_NA;
+	asi->antsel_avail = false;
+	asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
+
+	if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
+		switch (asi->antsel_antswitch) {
+		case ANTSWITCH_TYPE_1:
+		case ANTSWITCH_TYPE_2:
+		case ANTSWITCH_TYPE_3:
+			/* 4321/2 board with 2x3 switch logic */
+			asi->antsel_type = ANTSEL_2x3;
+			/* Antenna selection availability */
+			if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
+			    ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
+				asi->antsel_avail = true;
+			} else
+			    if (((u16) getintvar(asi->pub->vars, "aa2g") ==
+				 3)
+				|| ((u16) getintvar(asi->pub->vars, "aa5g")
+				    == 3)) {
+				asi->antsel_avail = false;
+			} else {
+				asi->antsel_avail = false;
+				WL_ERROR("wlc_antsel_attach: 2o3 board cfg invalid\n");
+				ASSERT(0);
+			}
+			break;
+		default:
+			break;
+		}
+	} else if ((asi->pub->sromrev == 4) &&
+		   ((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
+		   ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
+		/* hack to match old 4321CB2 cards with 2of3 antenna switch */
+		asi->antsel_type = ANTSEL_2x3;
+		asi->antsel_avail = true;
+	} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
+		asi->antsel_type = ANTSEL_2x4;
+		asi->antsel_avail = true;
+	}
+
+	/* Set the antenna selection type for the low driver */
+	wlc_bmac_antsel_type_set(wlc->hw, asi->antsel_type);
+
+	/* Init (auto/manual) antenna selection */
+	wlc_antsel_init_cfg(asi, &asi->antcfg_11n, true);
+	wlc_antsel_init_cfg(asi, &asi->antcfg_cur, true);
+
+	return asi;
+}
+
+void wlc_antsel_detach(struct antsel_info *asi)
+{
+	kfree(asi);
+}
+
+void wlc_antsel_init(struct antsel_info *asi)
+{
+	if ((asi->antsel_type == ANTSEL_2x3) ||
+	    (asi->antsel_type == ANTSEL_2x4))
+		wlc_antsel_cfgupd(asi, &asi->antcfg_11n);
+}
+
+/* boardlevel antenna selection: init antenna selection structure */
+static void
+wlc_antsel_init_cfg(struct antsel_info *asi, wlc_antselcfg_t *antsel,
+		    bool auto_sel)
+{
+	if (asi->antsel_type == ANTSEL_2x3) {
+		u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
+		    ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
+		antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
+
+	} else if (asi->antsel_type == ANTSEL_2x4) {
+
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
+		antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
+
+	} else {		/* no antenna selection available */
+
+		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
+		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
+		antsel->num_antcfg = 0;
+	}
+}
+
+void BCMFASTPATH
+wlc_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
+		      u8 antselid, u8 fbantselid, u8 *antcfg,
+		      u8 *fbantcfg)
+{
+	u8 ant;
+
+	/* if use default, assign it and return */
+	if (usedef) {
+		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
+		*fbantcfg = *antcfg;
+		return;
+	}
+
+	if (!sel) {
+		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+		*fbantcfg = *antcfg;
+
+	} else {
+		ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+		if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
+			*antcfg = wlc_antsel_id2antcfg(asi, antselid);
+			*fbantcfg = wlc_antsel_id2antcfg(asi, fbantselid);
+		} else {
+			*antcfg =
+			    asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
+			*fbantcfg = *antcfg;
+		}
+	}
+	return;
+}
+
+/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
+u8 wlc_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
+{
+	u8 antselid = 0;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
+		return antselid;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
+		return antselid;
+	}
+
+	return antselid;
+}
+
+/* boardlevel antenna selection: convert id to ant_cfg */
+static u8 wlc_antsel_id2antcfg(struct antsel_info *asi, u8 id)
+{
+	u8 antcfg = ANT_SELCFG_DEF_2x2;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
+		return antcfg;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
+		return antcfg;
+	}
+
+	return antcfg;
+}
+
+/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */
+static u16 wlc_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
+{
+	u8 idx = WLC_ANTIDX_11N(WLC_ANTSEL_11N(ant_cfg));
+	u16 mimo_antsel = 0;
+
+	if (asi->antsel_type == ANTSEL_2x4) {
+		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
+		mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
+		return mimo_antsel;
+
+	} else if (asi->antsel_type == ANTSEL_2x3) {
+		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
+		mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
+		return mimo_antsel;
+	}
+
+	return mimo_antsel;
+}
+
+/* boardlevel antenna selection: ucode interface control */
+static int wlc_antsel_cfgupd(struct antsel_info *asi, wlc_antselcfg_t *antsel)
+{
+	struct wlc_info *wlc = asi->wlc;
+	u8 ant_cfg;
+	u16 mimo_antsel;
+
+	ASSERT(asi->antsel_type != ANTSEL_NA);
+
+	/* 1) Update TX antconfig for all frames that are not unicast data
+	 *    (aka default TX)
+	 */
+	ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
+	mimo_antsel = wlc_antsel_antcfg2antsel(asi, ant_cfg);
+	wlc_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
+	/* Update driver stats for currently selected default tx/rx antenna config */
+	asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
+
+	/* 2) Update RX antconfig for all frames that are not unicast data
+	 *    (aka default RX)
+	 */
+	ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
+	mimo_antsel = wlc_antsel_antcfg2antsel(asi, ant_cfg);
+	wlc_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
+	/* Update driver stats for currently selected default tx/rx antenna config */
+	asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
+
+	return 0;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_antsel.h b/drivers/staging/brcm80211/brcmsmac/wlc_antsel.h
new file mode 100644
index 0000000..2470c73
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_antsel.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_antsel_h_
+#define _wlc_antsel_h_
+
+extern struct antsel_info *wlc_antsel_attach(struct wlc_info *wlc);
+extern void wlc_antsel_detach(struct antsel_info *asi);
+extern void wlc_antsel_init(struct antsel_info *asi);
+extern void wlc_antsel_antcfg_get(struct antsel_info *asi, bool usedef,
+				  bool sel,
+				  u8 id, u8 fbid, u8 *antcfg,
+				  u8 *fbantcfg);
+extern u8 wlc_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
+
+#endif /* _wlc_antsel_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
new file mode 100644
index 0000000..5a96dc3
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
@@ -0,0 +1,3745 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <proto/802.11.h>
+#include <bcmdefs.h>
+#include <bcmdevs.h>
+#include <bcmwifi.h>
+#include <siutils.h>
+#include <bcmsrom.h>
+#include <bcmotp.h>
+#include <bcmutils.h>
+#include <wlioctl.h>
+#include <sbconfig.h>
+#include <sbchipc.h>
+#include <pcicfg.h>
+#include <sbhnddma.h>
+#include <hnddma.h>
+#include <hndpmu.h>
+
+#include "wlc_types.h"
+#include "d11.h"
+#include "wlc_cfg.h"
+#include "wlc_rate.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_key.h"
+#include "wlc_phy_shim.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+#include "wl_export.h"
+#include "wl_ucode.h"
+#include "wlc_antsel.h"
+#include "pcie_core.h"
+#include "wlc_alloc.h"
+#include "wl_dbg.h"
+#include "wlc_bmac.h"
+
+#define	TIMER_INTERVAL_WATCHDOG_BMAC	1000	/* watchdog timer, in unit of ms */
+
+#define	SYNTHPU_DLY_APHY_US	3700	/* a phy synthpu_dly time in us */
+#define	SYNTHPU_DLY_BPHY_US	1050	/* b/g phy synthpu_dly time in us, default */
+#define	SYNTHPU_DLY_NPHY_US	2048	/* n phy REV3 synthpu_dly time in us, default */
+#define	SYNTHPU_DLY_LPPHY_US	300	/* lpphy synthpu_dly time in us */
+
+#define	SYNTHPU_DLY_PHY_US_QT	100	/* QT synthpu_dly time in us */
+
+#ifndef BMAC_DUP_TO_REMOVE
+#define WLC_RM_WAIT_TX_SUSPEND		4	/* Wait Tx Suspend */
+
+#define	ANTCNT			10	/* vanilla M_MAX_ANTCNT value */
+
+#endif				/* BMAC_DUP_TO_REMOVE */
+
+#define DMAREG(wlc_hw, direction, fifonum) \
+	((direction == DMA_TX) ? \
+		(void *)&(wlc_hw->regs->fifo64regs[fifonum].dmaxmt) : \
+		(void *)&(wlc_hw->regs->fifo64regs[fifonum].dmarcv))
+
+/*
+ * The following table lists the buffer memory allocated to xmt fifos in HW.
+ * the size is in units of 256bytes(one block), total size is HW dependent
+ * ucode has default fifo partition, sw can overwrite if necessary
+ *
+ * This is documented in twiki under the topic UcodeTxFifo. Please ensure
+ * the twiki is updated before making changes.
+ */
+
+#define XMTFIFOTBL_STARTREV	20	/* Starting corerev for the fifo size table */
+
+static u16 xmtfifo_sz[][NFIFO] = {
+	{20, 192, 192, 21, 17, 5},	/* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{9, 58, 22, 14, 14, 5},	/* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
+	{20, 192, 192, 21, 17, 5},	/* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{20, 192, 192, 21, 17, 5},	/* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
+	{9, 58, 22, 14, 14, 5},	/* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
+};
+
+static void wlc_clkctl_clk(struct wlc_hw_info *wlc, uint mode);
+static void wlc_coreinit(struct wlc_info *wlc);
+
+/* used by wlc_wakeucode_init() */
+static void wlc_write_inits(struct wlc_hw_info *wlc_hw,
+			    const struct d11init *inits);
+static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
+			    const uint nbytes);
+static void wlc_ucode_download(struct wlc_hw_info *wlc);
+static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw);
+
+/* used by wlc_dpc() */
+static bool wlc_bmac_dotxstatus(struct wlc_hw_info *wlc, tx_status_t *txs,
+				u32 s2);
+static bool wlc_bmac_txstatus(struct wlc_hw_info *wlc, bool bound, bool *fatal);
+static bool wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound);
+
+/* used by wlc_down() */
+static void wlc_flushqueues(struct wlc_info *wlc);
+
+static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs);
+static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw);
+static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw);
+static bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw,
+				       uint tx_fifo);
+static void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo);
+static void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo);
+
+/* Low Level Prototypes */
+static int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw);
+static void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw);
+static void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want);
+static u16 wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset,
+				   u32 sel);
+static void wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset,
+				  u16 v, u32 sel);
+static void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk);
+static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme);
+static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw);
+static void wlc_ucode_bsinit(struct wlc_hw_info *wlc_hw);
+static bool wlc_validboardtype(struct wlc_hw_info *wlc);
+static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw);
+static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw);
+static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw);
+static void wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init);
+static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw);
+static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool want, mbool flags);
+static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw);
+static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw);
+static u32 wlc_wlintrsoff(struct wlc_info *wlc);
+static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask);
+static void wlc_gpio_init(struct wlc_info *wlc);
+static void wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn,
+				      int len);
+static void wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn,
+				      int len);
+static void wlc_bmac_bsinit(struct wlc_info *wlc, chanspec_t chanspec);
+static u32 wlc_setband_inact(struct wlc_info *wlc, uint bandunit);
+static void wlc_bmac_setband(struct wlc_hw_info *wlc_hw, uint bandunit,
+			     chanspec_t chanspec);
+static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
+					bool shortslot);
+static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw);
+static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw,
+					     u8 rate);
+
+/* === Low Level functions === */
+
+void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot)
+{
+	wlc_hw->shortslot = shortslot;
+
+	if (BAND_2G(wlc_bmac_bandtype(wlc_hw)) && wlc_hw->up) {
+		wlc_suspend_mac_and_wait(wlc_hw->wlc);
+		wlc_bmac_update_slot_timing(wlc_hw, shortslot);
+		wlc_enable_mac(wlc_hw->wlc);
+	}
+}
+
+/*
+ * Update the slot timing for standard 11b/g (20us slots)
+ * or shortslot 11g (9us slots)
+ * The PSM needs to be suspended for this call.
+ */
+static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
+					bool shortslot)
+{
+	d11regs_t *regs;
+
+	regs = wlc_hw->regs;
+
+	if (shortslot) {
+		/* 11g short slot: 11a timing */
+		W_REG(&regs->ifs_slot, 0x0207);	/* APHY_SLOT_TIME */
+		wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
+	} else {
+		/* 11g long slot: 11b timing */
+		W_REG(&regs->ifs_slot, 0x0212);	/* BPHY_SLOT_TIME */
+		wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
+	}
+}
+
+static void WLBANDINITFN(wlc_ucode_bsinit) (struct wlc_hw_info *wlc_hw)
+{
+	/* init microcode host flags */
+	wlc_write_mhf(wlc_hw, wlc_hw->band->mhfs);
+
+	/* do band-specific ucode IHR, SHM, and SCR inits */
+	if (D11REV_IS(wlc_hw->corerev, 23)) {
+		if (WLCISNPHY(wlc_hw->band)) {
+			wlc_write_inits(wlc_hw, d11n0bsinitvals16);
+		} else {
+			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
+				 __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	} else {
+		if (D11REV_IS(wlc_hw->corerev, 24)) {
+			if (WLCISLCNPHY(wlc_hw->band)) {
+				wlc_write_inits(wlc_hw, d11lcn0bsinitvals24);
+			} else
+				WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
+					 __func__, wlc_hw->unit,
+					 wlc_hw->corerev);
+		} else {
+			WL_ERROR("%s: wl%d: unsupported corerev %d\n",
+				 __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	}
+}
+
+/* switch to new band but leave it inactive */
+static u32 WLBANDINITFN(wlc_setband_inact) (struct wlc_info *wlc, uint bandunit)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	u32 macintmask;
+
+	WL_TRACE("wl%d: wlc_setband_inact\n", wlc_hw->unit);
+
+	ASSERT(bandunit != wlc_hw->band->bandunit);
+	ASSERT(si_iscoreup(wlc_hw->sih));
+	ASSERT((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) ==
+	       0);
+
+	/* disable interrupts */
+	macintmask = wl_intrsoff(wlc->wl);
+
+	/* radio off */
+	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+	ASSERT(wlc_hw->clk);
+
+	wlc_bmac_core_phy_clk(wlc_hw, OFF);
+
+	wlc_setxband(wlc_hw, bandunit);
+
+	return macintmask;
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+static bool BCMFASTPATH
+wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound)
+{
+	struct sk_buff *p;
+	struct sk_buff *head = NULL;
+	struct sk_buff *tail = NULL;
+	uint n = 0;
+	uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
+	u32 tsf_h, tsf_l;
+	wlc_d11rxhdr_t *wlc_rxhdr = NULL;
+
+	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
+	/* gather received frames */
+	while ((p = dma_rx(wlc_hw->di[fifo]))) {
+
+		if (!tail)
+			head = tail = p;
+		else {
+			tail->prev = p;
+			tail = p;
+		}
+
+		/* !give others some time to run! */
+		if (++n >= bound_limit)
+			break;
+	}
+
+	/* get the TSF REG reading */
+	wlc_bmac_read_tsf(wlc_hw, &tsf_l, &tsf_h);
+
+	/* post more rbufs */
+	dma_rxfill(wlc_hw->di[fifo]);
+
+	/* process each frame */
+	while ((p = head) != NULL) {
+		head = head->prev;
+		p->prev = NULL;
+
+		/* record the tsf_l in wlc_rxd11hdr */
+		wlc_rxhdr = (wlc_d11rxhdr_t *) p->data;
+		wlc_rxhdr->tsf_l = cpu_to_le32(tsf_l);
+
+		/* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
+		wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
+
+		wlc_recv(wlc_hw->wlc, p);
+	}
+
+	return n >= bound_limit;
+}
+
+/* second-level interrupt processing
+ *   Return true if another dpc needs to be re-scheduled. false otherwise.
+ *   Param 'bounded' indicates if applicable loops should be bounded.
+ */
+bool BCMFASTPATH wlc_dpc(struct wlc_info *wlc, bool bounded)
+{
+	u32 macintstatus;
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	bool fatal = false;
+
+	if (DEVICEREMOVED(wlc)) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
+		wl_down(wlc->wl);
+		return false;
+	}
+
+	/* grab and clear the saved software intstatus bits */
+	macintstatus = wlc->macintstatus;
+	wlc->macintstatus = 0;
+
+	WL_TRACE("wl%d: wlc_dpc: macintstatus 0x%x\n",
+		 wlc_hw->unit, macintstatus);
+
+	if (macintstatus & MI_PRQ) {
+		/* Process probe request FIFO */
+		ASSERT(0 && "PRQ Interrupt in non-MBSS");
+	}
+
+	/* BCN template is available */
+	/* ZZZ: Use AP_ACTIVE ? */
+	if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub) || wlc->aps_associated)
+	    && (macintstatus & MI_BCNTPL)) {
+		wlc_update_beacon(wlc);
+	}
+
+	/* PMQ entry addition */
+	if (macintstatus & MI_PMQ) {
+	}
+
+	/* tx status */
+	if (macintstatus & MI_TFS) {
+		if (wlc_bmac_txstatus(wlc->hw, bounded, &fatal))
+			wlc->macintstatus |= MI_TFS;
+		if (fatal) {
+			WL_ERROR("MI_TFS: fatal\n");
+			goto fatal;
+		}
+	}
+
+	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+		wlc_tbtt(wlc, regs);
+
+	/* ATIM window end */
+	if (macintstatus & MI_ATIMWINEND) {
+		WL_TRACE("wlc_isr: end of ATIM window\n");
+
+		OR_REG(&regs->maccommand, wlc->qvalid);
+		wlc->qvalid = 0;
+	}
+
+	/* phy tx error */
+	if (macintstatus & MI_PHYTXERR) {
+		wlc->pub->_cnt->txphyerr++;
+	}
+
+	/* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
+	if (macintstatus & MI_DMAINT) {
+		if (wlc_bmac_recv(wlc_hw, RX_FIFO, bounded)) {
+			wlc->macintstatus |= MI_DMAINT;
+		}
+	}
+
+	/* TX FIFO suspend/flush completion */
+	if (macintstatus & MI_TXSTOP) {
+		if (wlc_bmac_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO)) {
+			/*      WL_ERROR("dpc: fifo_suspend_comlete\n"); */
+		}
+	}
+
+	/* noise sample collected */
+	if (macintstatus & MI_BG_NOISE) {
+		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
+	}
+
+	if (macintstatus & MI_GP0) {
+		WL_ERROR("wl%d: PSM microcode watchdog fired at %d (seconds). Resetting.\n",
+			 wlc_hw->unit, wlc_hw->now);
+
+		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
+					__func__, wlc_hw->sih->chip,
+					wlc_hw->sih->chiprev);
+
+		wlc->pub->_cnt->psmwds++;
+
+		/* big hammer */
+		wl_init(wlc->wl);
+	}
+
+	/* gptimer timeout */
+	if (macintstatus & MI_TO) {
+		W_REG(&regs->gptimer, 0);
+	}
+
+	if (macintstatus & MI_RFDISABLE) {
+		WL_TRACE("wl%d: BMAC Detected a change on the RF Disable Input\n", wlc_hw->unit);
+
+		wlc->pub->_cnt->rfdisable++;
+		wl_rfkill_set_hw_state(wlc->wl);
+	}
+
+	/* send any enq'd tx packets. Just makes sure to jump start tx */
+	if (!pktq_empty(&wlc->active_queue->q))
+		wlc_send_q(wlc, wlc->active_queue);
+
+	ASSERT(wlc_ps_check(wlc));
+
+	/* make sure the bound indication and the implementation are in sync */
+	ASSERT(bounded == true || wlc->macintstatus == 0);
+
+	/* it isn't done and needs to be resched if macintstatus is non-zero */
+	return wlc->macintstatus != 0;
+
+ fatal:
+	wl_init(wlc->wl);
+	return wlc->macintstatus != 0;
+}
+
+/* common low-level watchdog code */
+void wlc_bmac_watchdog(void *arg)
+{
+	struct wlc_info *wlc = (struct wlc_info *) arg;
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+
+	WL_TRACE("wl%d: wlc_bmac_watchdog\n", wlc_hw->unit);
+
+	if (!wlc_hw->up)
+		return;
+
+	/* increment second count */
+	wlc_hw->now++;
+
+	/* Check for FIFO error interrupts */
+	wlc_bmac_fifoerrors(wlc_hw);
+
+	/* make sure RX dma has buffers */
+	dma_rxfill(wlc->hw->di[RX_FIFO]);
+
+	wlc_phy_watchdog(wlc_hw->band->pi);
+}
+
+void
+wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
+		      bool mute, struct txpwr_limits *txpwr)
+{
+	uint bandunit;
+
+	WL_TRACE("wl%d: wlc_bmac_set_chanspec 0x%x\n",
+		 wlc_hw->unit, chanspec);
+
+	wlc_hw->chanspec = chanspec;
+
+	/* Switch bands if necessary */
+	if (NBANDS_HW(wlc_hw) > 1) {
+		bandunit = CHSPEC_WLCBANDUNIT(chanspec);
+		if (wlc_hw->band->bandunit != bandunit) {
+			/* wlc_bmac_setband disables other bandunit,
+			 *  use light band switch if not up yet
+			 */
+			if (wlc_hw->up) {
+				wlc_phy_chanspec_radio_set(wlc_hw->
+							   bandstate[bandunit]->
+							   pi, chanspec);
+				wlc_bmac_setband(wlc_hw, bandunit, chanspec);
+			} else {
+				wlc_setxband(wlc_hw, bandunit);
+			}
+		}
+	}
+
+	wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
+
+	if (!wlc_hw->up) {
+		if (wlc_hw->clk)
+			wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
+						  chanspec);
+		wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+	} else {
+		wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
+		wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
+
+		/* Update muting of the channel */
+		wlc_bmac_mute(wlc_hw, mute, 0);
+	}
+}
+
+int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw, wlc_bmac_state_t *state)
+{
+	state->machwcap = wlc_hw->machwcap;
+
+	return 0;
+}
+
+static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme)
+{
+	uint i;
+	char name[8];
+	/* ucode host flag 2 needed for pio mode, independent of band and fifo */
+	u16 pio_mhf2 = 0;
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	uint unit = wlc_hw->unit;
+	wlc_tunables_t *tune = wlc->pub->tunables;
+
+	/* name and offsets for dma_attach */
+	snprintf(name, sizeof(name), "wl%d", unit);
+
+	if (wlc_hw->di[0] == 0) {	/* Init FIFOs */
+		uint addrwidth;
+		int dma_attach_err = 0;
+		/* Find out the DMA addressing capability and let OS know
+		 * All the channels within one DMA core have 'common-minimum' same
+		 * capability
+		 */
+		addrwidth =
+		    dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
+
+		if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
+			WL_ERROR("wl%d: wlc_attach: alloc_dma_resources failed\n",
+				 unit);
+			return false;
+		}
+
+		/*
+		 * FIFO 0
+		 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
+		 * RX: RX_FIFO (RX data packets)
+		 */
+		ASSERT(TX_AC_BK_FIFO == 0);
+		ASSERT(RX_FIFO == 0);
+		wlc_hw->di[0] = dma_attach(name, wlc_hw->sih,
+					   (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
+					    NULL), DMAREG(wlc_hw, DMA_RX, 0),
+					   (wme ? tune->ntxd : 0), tune->nrxd,
+					   tune->rxbufsz, -1, tune->nrxbufpost,
+					   WL_HWRXOFF, &wl_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[0]);
+
+		/*
+		 * FIFO 1
+		 * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
+		 *   (legacy) TX_DATA_FIFO (TX data packets)
+		 * RX: UNUSED
+		 */
+		ASSERT(TX_AC_BE_FIFO == 1);
+		ASSERT(TX_DATA_FIFO == 1);
+		wlc_hw->di[1] = dma_attach(name, wlc_hw->sih,
+					   DMAREG(wlc_hw, DMA_TX, 1), NULL,
+					   tune->ntxd, 0, 0, -1, 0, 0,
+					   &wl_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[1]);
+
+		/*
+		 * FIFO 2
+		 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
+		 * RX: UNUSED
+		 */
+		ASSERT(TX_AC_VI_FIFO == 2);
+		wlc_hw->di[2] = dma_attach(name, wlc_hw->sih,
+					   DMAREG(wlc_hw, DMA_TX, 2), NULL,
+					   tune->ntxd, 0, 0, -1, 0, 0,
+					   &wl_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[2]);
+		/*
+		 * FIFO 3
+		 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
+		 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
+		 */
+		ASSERT(TX_AC_VO_FIFO == 3);
+		ASSERT(TX_CTL_FIFO == 3);
+		wlc_hw->di[3] = dma_attach(name, wlc_hw->sih,
+					   DMAREG(wlc_hw, DMA_TX, 3),
+					   NULL, tune->ntxd, 0, 0, -1,
+					   0, 0, &wl_msg_level);
+		dma_attach_err |= (NULL == wlc_hw->di[3]);
+/* Cleaner to leave this as if with AP defined */
+
+		if (dma_attach_err) {
+			WL_ERROR("wl%d: wlc_attach: dma_attach failed\n", unit);
+			return false;
+		}
+
+		/* get pointer to dma engine tx flow control variable */
+		for (i = 0; i < NFIFO; i++)
+			if (wlc_hw->di[i])
+				wlc_hw->txavail[i] =
+				    (uint *) dma_getvar(wlc_hw->di[i],
+							"&txavail");
+	}
+
+	/* initial ucode host flags */
+	wlc_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
+
+	return true;
+}
+
+static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw)
+{
+	uint j;
+
+	for (j = 0; j < NFIFO; j++) {
+		if (wlc_hw->di[j]) {
+			dma_detach(wlc_hw->di[j]);
+			wlc_hw->di[j] = NULL;
+		}
+	}
+}
+
+/* low level attach
+ *    run backplane attach, init nvram
+ *    run phy attach
+ *    initialize software state for each core and band
+ *    put the whole chip in reset(driver down state), no clock
+ */
+int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device, uint unit,
+		    bool piomode, void *regsva, uint bustype, void *btparam)
+{
+	struct wlc_hw_info *wlc_hw;
+	d11regs_t *regs;
+	char *macaddr = NULL;
+	char *vars;
+	uint err = 0;
+	uint j;
+	bool wme = false;
+	shared_phy_params_t sha_params;
+
+	WL_TRACE("wl%d: wlc_bmac_attach: vendor 0x%x device 0x%x\n",
+		 unit, vendor, device);
+
+	ASSERT(sizeof(wlc_d11rxhdr_t) <= WL_HWRXOFF);
+
+	wme = true;
+
+	wlc_hw = wlc->hw;
+	wlc_hw->wlc = wlc;
+	wlc_hw->unit = unit;
+	wlc_hw->band = wlc_hw->bandstate[0];
+	wlc_hw->_piomode = piomode;
+
+	/* populate struct wlc_hw_info with default values  */
+	wlc_bmac_info_init(wlc_hw);
+
+	/*
+	 * Do the hardware portion of the attach.
+	 * Also initialize software state that depends on the particular hardware
+	 * we are running.
+	 */
+	wlc_hw->sih = si_attach((uint) device, regsva, bustype, btparam,
+				&wlc_hw->vars, &wlc_hw->vars_size);
+	if (wlc_hw->sih == NULL) {
+		WL_ERROR("wl%d: wlc_bmac_attach: si_attach failed\n", unit);
+		err = 11;
+		goto fail;
+	}
+	vars = wlc_hw->vars;
+
+	/*
+	 * Get vendid/devid nvram overwrites, which could be different
+	 * than those the BIOS recognizes for devices on PCMCIA_BUS,
+	 * SDIO_BUS, and SROMless devices on PCI_BUS.
+	 */
+#ifdef BCMBUSTYPE
+	bustype = BCMBUSTYPE;
+#endif
+	if (bustype != SI_BUS) {
+		char *var;
+
+		var = getvar(vars, "vendid");
+		if (var) {
+			vendor = (u16) simple_strtoul(var, NULL, 0);
+			WL_ERROR("Overriding vendor id = 0x%x\n", vendor);
+		}
+		var = getvar(vars, "devid");
+		if (var) {
+			u16 devid = (u16) simple_strtoul(var, NULL, 0);
+			if (devid != 0xffff) {
+				device = devid;
+				WL_ERROR("Overriding device id = 0x%x\n",
+					 device);
+			}
+		}
+
+		/* verify again the device is supported */
+		if (!wlc_chipmatch(vendor, device)) {
+			WL_ERROR("wl%d: wlc_bmac_attach: Unsupported vendor/device (0x%x/0x%x)\n",
+				 unit, vendor, device);
+			err = 12;
+			goto fail;
+		}
+	}
+
+	wlc_hw->vendorid = vendor;
+	wlc_hw->deviceid = device;
+
+	/* set bar0 window to point at D11 core */
+	wlc_hw->regs = (d11regs_t *) si_setcore(wlc_hw->sih, D11_CORE_ID, 0);
+	wlc_hw->corerev = si_corerev(wlc_hw->sih);
+
+	regs = wlc_hw->regs;
+
+	wlc->regs = wlc_hw->regs;
+
+	/* validate chip, chiprev and corerev */
+	if (!wlc_isgoodchip(wlc_hw)) {
+		err = 13;
+		goto fail;
+	}
+
+	/* initialize power control registers */
+	si_clkctl_init(wlc_hw->sih);
+
+	/* request fastclock and force fastclock for the rest of attach
+	 * bring the d11 core out of reset.
+	 *   For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
+	 *   But it will be called again inside wlc_corereset, after d11 is out of reset.
+	 */
+	wlc_clkctl_clk(wlc_hw, CLK_FAST);
+	wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
+
+	if (!wlc_bmac_validate_chip_access(wlc_hw)) {
+		WL_ERROR("wl%d: wlc_bmac_attach: validate_chip_access failed\n",
+			 unit);
+		err = 14;
+		goto fail;
+	}
+
+	/* get the board rev, used just below */
+	j = getintvar(vars, "boardrev");
+	/* promote srom boardrev of 0xFF to 1 */
+	if (j == BOARDREV_PROMOTABLE)
+		j = BOARDREV_PROMOTED;
+	wlc_hw->boardrev = (u16) j;
+	if (!wlc_validboardtype(wlc_hw)) {
+		WL_ERROR("wl%d: wlc_bmac_attach: Unsupported Broadcom board type (0x%x)" " or revision level (0x%x)\n",
+			 unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
+		err = 15;
+		goto fail;
+	}
+	wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
+	wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
+	wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
+
+	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+		wlc_bmac_pllreq(wlc_hw, true, WLC_PLLREQ_SHARED);
+
+	if ((wlc_hw->sih->bustype == PCI_BUS)
+	    && (si_pci_war16165(wlc_hw->sih)))
+		wlc->war16165 = true;
+
+	/* check device id(srom, nvram etc.) to set bands */
+	if (wlc_hw->deviceid == BCM43224_D11N_ID) {
+		/* Dualband boards */
+		wlc_hw->_nbands = 2;
+	} else
+		wlc_hw->_nbands = 1;
+
+	if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
+		wlc_hw->_nbands = 1;
+
+	/* BMAC_NOTE: remove init of pub values when wlc_attach() unconditionally does the
+	 * init of these values
+	 */
+	wlc->vendorid = wlc_hw->vendorid;
+	wlc->deviceid = wlc_hw->deviceid;
+	wlc->pub->sih = wlc_hw->sih;
+	wlc->pub->corerev = wlc_hw->corerev;
+	wlc->pub->sromrev = wlc_hw->sromrev;
+	wlc->pub->boardrev = wlc_hw->boardrev;
+	wlc->pub->boardflags = wlc_hw->boardflags;
+	wlc->pub->boardflags2 = wlc_hw->boardflags2;
+	wlc->pub->_nbands = wlc_hw->_nbands;
+
+	wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
+
+	if (wlc_hw->physhim == NULL) {
+		WL_ERROR("wl%d: wlc_bmac_attach: wlc_phy_shim_attach failed\n",
+			 unit);
+		err = 25;
+		goto fail;
+	}
+
+	/* pass all the parameters to wlc_phy_shared_attach in one struct */
+	sha_params.sih = wlc_hw->sih;
+	sha_params.physhim = wlc_hw->physhim;
+	sha_params.unit = unit;
+	sha_params.corerev = wlc_hw->corerev;
+	sha_params.vars = vars;
+	sha_params.vid = wlc_hw->vendorid;
+	sha_params.did = wlc_hw->deviceid;
+	sha_params.chip = wlc_hw->sih->chip;
+	sha_params.chiprev = wlc_hw->sih->chiprev;
+	sha_params.chippkg = wlc_hw->sih->chippkg;
+	sha_params.sromrev = wlc_hw->sromrev;
+	sha_params.boardtype = wlc_hw->sih->boardtype;
+	sha_params.boardrev = wlc_hw->boardrev;
+	sha_params.boardvendor = wlc_hw->sih->boardvendor;
+	sha_params.boardflags = wlc_hw->boardflags;
+	sha_params.boardflags2 = wlc_hw->boardflags2;
+	sha_params.bustype = wlc_hw->sih->bustype;
+	sha_params.buscorerev = wlc_hw->sih->buscorerev;
+
+	/* alloc and save pointer to shared phy state area */
+	wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
+	if (!wlc_hw->phy_sh) {
+		err = 16;
+		goto fail;
+	}
+
+	/* initialize software state for each core and band */
+	for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
+		/*
+		 * band0 is always 2.4Ghz
+		 * band1, if present, is 5Ghz
+		 */
+
+		/* So if this is a single band 11a card, use band 1 */
+		if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
+			j = BAND_5G_INDEX;
+
+		wlc_setxband(wlc_hw, j);
+
+		wlc_hw->band->bandunit = j;
+		wlc_hw->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
+		wlc->band->bandunit = j;
+		wlc->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
+		wlc->core->coreidx = si_coreidx(wlc_hw->sih);
+
+		wlc_hw->machwcap = R_REG(&regs->machwcap);
+		wlc_hw->machwcap_backup = wlc_hw->machwcap;
+
+		/* init tx fifo size */
+		ASSERT((wlc_hw->corerev - XMTFIFOTBL_STARTREV) <
+		       ARRAY_SIZE(xmtfifo_sz));
+		wlc_hw->xmtfifo_sz =
+		    xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
+
+		/* Get a phy for this band */
+		wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
+			(void *)regs, wlc_bmac_bandtype(wlc_hw), vars);
+		if (wlc_hw->band->pi == NULL) {
+			WL_ERROR("wl%d: wlc_bmac_attach: wlc_phy_attach failed\n",
+				 unit);
+			err = 17;
+			goto fail;
+		}
+
+		wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
+
+		wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
+				       &wlc_hw->band->phyrev,
+				       &wlc_hw->band->radioid,
+				       &wlc_hw->band->radiorev);
+		wlc_hw->band->abgphy_encore =
+		    wlc_phy_get_encore(wlc_hw->band->pi);
+		wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
+		wlc_hw->band->core_flags =
+		    wlc_phy_get_coreflags(wlc_hw->band->pi);
+
+		/* verify good phy_type & supported phy revision */
+		if (WLCISNPHY(wlc_hw->band)) {
+			if (NCONF_HAS(wlc_hw->band->phyrev))
+				goto good_phy;
+			else
+				goto bad_phy;
+		} else if (WLCISLCNPHY(wlc_hw->band)) {
+			if (LCNCONF_HAS(wlc_hw->band->phyrev))
+				goto good_phy;
+			else
+				goto bad_phy;
+		} else {
+ bad_phy:
+			WL_ERROR("wl%d: wlc_bmac_attach: unsupported phy type/rev (%d/%d)\n",
+				 unit,
+				 wlc_hw->band->phytype, wlc_hw->band->phyrev);
+			err = 18;
+			goto fail;
+		}
+
+ good_phy:
+		/* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
+		 * high level attach. However we can not make that change until all low level access
+		 * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
+		 * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
+		 * low only init when all fns updated.
+		 */
+		wlc->band->pi = wlc_hw->band->pi;
+		wlc->band->phytype = wlc_hw->band->phytype;
+		wlc->band->phyrev = wlc_hw->band->phyrev;
+		wlc->band->radioid = wlc_hw->band->radioid;
+		wlc->band->radiorev = wlc_hw->band->radiorev;
+
+		/* default contention windows size limits */
+		wlc_hw->band->CWmin = APHY_CWMIN;
+		wlc_hw->band->CWmax = PHY_CWMAX;
+
+		if (!wlc_bmac_attach_dmapio(wlc, j, wme)) {
+			err = 19;
+			goto fail;
+		}
+	}
+
+	/* disable core to match driver "down" state */
+	wlc_coredisable(wlc_hw);
+
+	/* Match driver "down" state */
+	if (wlc_hw->sih->bustype == PCI_BUS)
+		si_pci_down(wlc_hw->sih);
+
+	/* register sb interrupt callback functions */
+	si_register_intr_callback(wlc_hw->sih, (void *)wlc_wlintrsoff,
+				  (void *)wlc_wlintrsrestore, NULL, wlc);
+
+	/* turn off pll and xtal to match driver "down" state */
+	wlc_bmac_xtal(wlc_hw, OFF);
+
+	/* *********************************************************************
+	 * The hardware is in the DOWN state at this point. D11 core
+	 * or cores are in reset with clocks off, and the board PLLs
+	 * are off if possible.
+	 *
+	 * Beyond this point, wlc->sbclk == false and chip registers
+	 * should not be touched.
+	 *********************************************************************
+	 */
+
+	/* init etheraddr state variables */
+	macaddr = wlc_get_macaddr(wlc_hw);
+	if (macaddr == NULL) {
+		WL_ERROR("wl%d: wlc_bmac_attach: macaddr not found\n", unit);
+		err = 21;
+		goto fail;
+	}
+	bcm_ether_atoe(macaddr, wlc_hw->etheraddr);
+	if (is_broadcast_ether_addr(wlc_hw->etheraddr) ||
+	    is_zero_ether_addr(wlc_hw->etheraddr)) {
+		WL_ERROR("wl%d: wlc_bmac_attach: bad macaddr %s\n",
+			 unit, macaddr);
+		err = 22;
+		goto fail;
+	}
+
+	WL_TRACE("%s:: deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
+		 __func__, wlc_hw->deviceid, wlc_hw->_nbands,
+		 wlc_hw->sih->boardtype, macaddr);
+
+	return err;
+
+ fail:
+	WL_ERROR("wl%d: wlc_bmac_attach: failed with err %d\n", unit, err);
+	return err;
+}
+
+/*
+ * Initialize wlc_info default values ...
+ * may get overrides later in this function
+ *  BMAC_NOTES, move low out and resolve the dangling ones
+ */
+static void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw)
+{
+	struct wlc_info *wlc = wlc_hw->wlc;
+
+	/* set default sw macintmask value */
+	wlc->defmacintmask = DEF_MACINTMASK;
+
+	/* various 802.11g modes */
+	wlc_hw->shortslot = false;
+
+	wlc_hw->SFBL = RETRY_SHORT_FB;
+	wlc_hw->LFBL = RETRY_LONG_FB;
+
+	/* default mac retry limits */
+	wlc_hw->SRL = RETRY_SHORT_DEF;
+	wlc_hw->LRL = RETRY_LONG_DEF;
+	wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
+}
+
+/*
+ * low level detach
+ */
+int wlc_bmac_detach(struct wlc_info *wlc)
+{
+	uint i;
+	struct wlc_hwband *band;
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	int callbacks;
+
+	callbacks = 0;
+
+	if (wlc_hw->sih) {
+		/* detach interrupt sync mechanism since interrupt is disabled and per-port
+		 * interrupt object may has been freed. this must be done before sb core switch
+		 */
+		si_deregister_intr_callback(wlc_hw->sih);
+
+		if (wlc_hw->sih->bustype == PCI_BUS)
+			si_pci_sleep(wlc_hw->sih);
+	}
+
+	wlc_bmac_detach_dmapio(wlc_hw);
+
+	band = wlc_hw->band;
+	for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
+		if (band->pi) {
+			/* Detach this band's phy */
+			wlc_phy_detach(band->pi);
+			band->pi = NULL;
+		}
+		band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
+	}
+
+	/* Free shared phy state */
+	wlc_phy_shared_detach(wlc_hw->phy_sh);
+
+	wlc_phy_shim_detach(wlc_hw->physhim);
+
+	/* free vars */
+	kfree(wlc_hw->vars);
+	wlc_hw->vars = NULL;
+
+	if (wlc_hw->sih) {
+		si_detach(wlc_hw->sih);
+		wlc_hw->sih = NULL;
+	}
+
+	return callbacks;
+
+}
+
+void wlc_bmac_reset(struct wlc_hw_info *wlc_hw)
+{
+	WL_TRACE("wl%d: wlc_bmac_reset\n", wlc_hw->unit);
+
+	wlc_hw->wlc->pub->_cnt->reset++;
+
+	/* reset the core */
+	if (!DEVICEREMOVED(wlc_hw->wlc))
+		wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
+
+	/* purge the dma rings */
+	wlc_flushqueues(wlc_hw->wlc);
+
+	wlc_reset_bmac_done(wlc_hw->wlc);
+}
+
+void
+wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
+			  bool mute) {
+	u32 macintmask;
+	bool fastclk;
+	struct wlc_info *wlc = wlc_hw->wlc;
+
+	WL_TRACE("wl%d: wlc_bmac_init\n", wlc_hw->unit);
+
+	/* request FAST clock if not on */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		wlc_clkctl_clk(wlc_hw, CLK_FAST);
+
+	/* disable interrupts */
+	macintmask = wl_intrsoff(wlc->wl);
+
+	/* set up the specified band and chanspec */
+	wlc_setxband(wlc_hw, CHSPEC_WLCBANDUNIT(chanspec));
+	wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
+
+	/* do one-time phy inits and calibration */
+	wlc_phy_cal_init(wlc_hw->band->pi);
+
+	/* core-specific initialization */
+	wlc_coreinit(wlc);
+
+	/* suspend the tx fifos and mute the phy for preism cac time */
+	if (mute)
+		wlc_bmac_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
+
+	/* band-specific inits */
+	wlc_bmac_bsinit(wlc, chanspec);
+
+	/* restore macintmask */
+	wl_intrsrestore(wlc->wl, macintmask);
+
+	/* seed wake_override with WLC_WAKE_OVERRIDE_MACSUSPEND since the mac is suspended
+	 * and wlc_enable_mac() will clear this override bit.
+	 */
+	mboolset(wlc_hw->wake_override, WLC_WAKE_OVERRIDE_MACSUSPEND);
+
+	/*
+	 * initialize mac_suspend_depth to 1 to match ucode initial suspended state
+	 */
+	wlc_hw->mac_suspend_depth = 1;
+
+	/* restore the clk */
+	if (!fastclk)
+		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw)
+{
+	uint coremask;
+
+	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
+
+	ASSERT(wlc_hw->wlc->pub->hw_up && wlc_hw->wlc->macintmask == 0);
+
+	/*
+	 * Enable pll and xtal, initialize the power control registers,
+	 * and force fastclock for the remainder of wlc_up().
+	 */
+	wlc_bmac_xtal(wlc_hw, ON);
+	si_clkctl_init(wlc_hw->sih);
+	wlc_clkctl_clk(wlc_hw, CLK_FAST);
+
+	/*
+	 * Configure pci/pcmcia here instead of in wlc_attach()
+	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
+	 */
+	coremask = (1 << wlc_hw->wlc->core->coreidx);
+
+	if (wlc_hw->sih->bustype == PCI_BUS)
+		si_pci_setup(wlc_hw->sih, coremask);
+
+	ASSERT(si_coreid(wlc_hw->sih) == D11_CORE_ID);
+
+	/*
+	 * Need to read the hwradio status here to cover the case where the system
+	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
+	 */
+	if (wlc_bmac_radio_read_hwdisabled(wlc_hw)) {
+		/* put SB PCI in down state again */
+		if (wlc_hw->sih->bustype == PCI_BUS)
+			si_pci_down(wlc_hw->sih);
+		wlc_bmac_xtal(wlc_hw, OFF);
+		return BCME_RADIOOFF;
+	}
+
+	if (wlc_hw->sih->bustype == PCI_BUS)
+		si_pci_up(wlc_hw->sih);
+
+	/* reset the d11 core */
+	wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
+
+	return 0;
+}
+
+int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw)
+{
+	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
+
+	wlc_hw->up = true;
+	wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
+
+	/* FULLY enable dynamic power control and d11 core interrupt */
+	wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+	ASSERT(wlc_hw->wlc->macintmask == 0);
+	wl_intrson(wlc_hw->wlc->wl);
+	return 0;
+}
+
+int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw)
+{
+	bool dev_gone;
+	uint callbacks = 0;
+
+	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
+
+	if (!wlc_hw->up)
+		return callbacks;
+
+	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
+
+	/* disable interrupts */
+	if (dev_gone)
+		wlc_hw->wlc->macintmask = 0;
+	else {
+		/* now disable interrupts */
+		wl_intrsoff(wlc_hw->wlc->wl);
+
+		/* ensure we're running on the pll clock again */
+		wlc_clkctl_clk(wlc_hw, CLK_FAST);
+	}
+	/* down phy at the last of this stage */
+	callbacks += wlc_phy_down(wlc_hw->band->pi);
+
+	return callbacks;
+}
+
+int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw)
+{
+	uint callbacks = 0;
+	bool dev_gone;
+
+	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
+
+	if (!wlc_hw->up)
+		return callbacks;
+
+	wlc_hw->up = false;
+	wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
+
+	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
+
+	if (dev_gone) {
+		wlc_hw->sbclk = false;
+		wlc_hw->clk = false;
+		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+
+		/* reclaim any posted packets */
+		wlc_flushqueues(wlc_hw->wlc);
+	} else {
+
+		/* Reset and disable the core */
+		if (si_iscoreup(wlc_hw->sih)) {
+			if (R_REG(&wlc_hw->regs->maccontrol) &
+			    MCTL_EN_MAC)
+				wlc_suspend_mac_and_wait(wlc_hw->wlc);
+			callbacks += wl_reset(wlc_hw->wlc->wl);
+			wlc_coredisable(wlc_hw);
+		}
+
+		/* turn off primary xtal and pll */
+		if (!wlc_hw->noreset) {
+			if (wlc_hw->sih->bustype == PCI_BUS)
+				si_pci_down(wlc_hw->sih);
+			wlc_bmac_xtal(wlc_hw, OFF);
+		}
+	}
+
+	return callbacks;
+}
+
+void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw)
+{
+	/* delay before first read of ucode state */
+	udelay(40);
+
+	/* wait until ucode is no longer asleep */
+	SPINWAIT((wlc_bmac_read_shm(wlc_hw, M_UCODE_DBGST) ==
+		  DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
+
+	ASSERT(wlc_bmac_read_shm(wlc_hw, M_UCODE_DBGST) != DBGST_ASLEEP);
+}
+
+void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw, u8 *ea)
+{
+	memcpy(ea, wlc_hw->etheraddr, ETH_ALEN);
+}
+
+static int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw)
+{
+	return wlc_hw->band->bandtype;
+}
+
+/* control chip clock to save power, enable dynamic clock or force fast clock */
+static void wlc_clkctl_clk(struct wlc_hw_info *wlc_hw, uint mode)
+{
+	if (PMUCTL_ENAB(wlc_hw->sih)) {
+		/* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
+		 *  but mac core will still run on ALP(not HT) when it enters powersave mode,
+		 *      which means the FCA bit may not be set.
+		 *      should wakeup mac if driver wants it to run on HT.
+		 */
+
+		if (wlc_hw->clk) {
+			if (mode == CLK_FAST) {
+				OR_REG(&wlc_hw->regs->clk_ctl_st,
+				       CCS_FORCEHT);
+
+				udelay(64);
+
+				SPINWAIT(((R_REG
+					   (&wlc_hw->regs->
+					    clk_ctl_st) & CCS_HTAVAIL) == 0),
+					 PMU_MAX_TRANSITION_DLY);
+				ASSERT(R_REG
+				       (&wlc_hw->regs->
+					clk_ctl_st) & CCS_HTAVAIL);
+			} else {
+				if ((wlc_hw->sih->pmurev == 0) &&
+				    (R_REG
+				     (&wlc_hw->regs->
+				      clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
+					SPINWAIT(((R_REG
+						   (&wlc_hw->regs->
+						    clk_ctl_st) & CCS_HTAVAIL)
+						  == 0),
+						 PMU_MAX_TRANSITION_DLY);
+				AND_REG(&wlc_hw->regs->clk_ctl_st,
+					~CCS_FORCEHT);
+			}
+		}
+		wlc_hw->forcefastclk = (mode == CLK_FAST);
+	} else {
+
+		/* old chips w/o PMU, force HT through cc,
+		 * then use FCA to verify mac is running fast clock
+		 */
+
+		wlc_hw->forcefastclk = si_clkctl_cc(wlc_hw->sih, mode);
+
+		/* check fast clock is available (if core is not in reset) */
+		if (wlc_hw->forcefastclk && wlc_hw->clk)
+			ASSERT(si_core_sflags(wlc_hw->sih, 0, 0) & SISF_FCLKA);
+
+		/* keep the ucode wake bit on if forcefastclk is on
+		 * since we do not want ucode to put us back to slow clock
+		 * when it dozes for PM mode.
+		 * Code below matches the wake override bit with current forcefastclk state
+		 * Only setting bit in wake_override instead of waking ucode immediately
+		 * since old code (wlc.c 1.4499) had this behavior. Older code set
+		 * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
+		 * (protected by an up check) was executed just below.
+		 */
+		if (wlc_hw->forcefastclk)
+			mboolset(wlc_hw->wake_override,
+				 WLC_WAKE_OVERRIDE_FORCEFAST);
+		else
+			mboolclr(wlc_hw->wake_override,
+				 WLC_WAKE_OVERRIDE_FORCEFAST);
+	}
+}
+
+/* set initial host flags value */
+static void
+wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+
+	memset(mhfs, 0, MHFMAX * sizeof(u16));
+
+	mhfs[MHF2] |= mhf2_init;
+
+	/* prohibit use of slowclock on multifunction boards */
+	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
+		mhfs[MHF1] |= MHF1_FORCEFASTCLK;
+
+	if (WLCISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
+		mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
+		mhfs[MHF1] |= MHF1_IQSWAP_WAR;
+	}
+}
+
+/* set or clear ucode host flag bits
+ * it has an optimization for no-change write
+ * it only writes through shared memory when the core has clock;
+ * pre-CLK changes should use wlc_write_mhf to get around the optimization
+ *
+ *
+ * bands values are: WLC_BAND_AUTO <--- Current band only
+ *                   WLC_BAND_5G   <--- 5G band only
+ *                   WLC_BAND_2G   <--- 2G band only
+ *                   WLC_BAND_ALL  <--- All bands
+ */
+void
+wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask, u16 val,
+	     int bands)
+{
+	u16 save;
+	u16 addr[MHFMAX] = {
+		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+		M_HOST_FLAGS5
+	};
+	struct wlc_hwband *band;
+
+	ASSERT((val & ~mask) == 0);
+	ASSERT(idx < MHFMAX);
+	ASSERT(ARRAY_SIZE(addr) == MHFMAX);
+
+	switch (bands) {
+		/* Current band only or all bands,
+		 * then set the band to current band
+		 */
+	case WLC_BAND_AUTO:
+	case WLC_BAND_ALL:
+		band = wlc_hw->band;
+		break;
+	case WLC_BAND_5G:
+		band = wlc_hw->bandstate[BAND_5G_INDEX];
+		break;
+	case WLC_BAND_2G:
+		band = wlc_hw->bandstate[BAND_2G_INDEX];
+		break;
+	default:
+		ASSERT(0);
+		band = NULL;
+	}
+
+	if (band) {
+		save = band->mhfs[idx];
+		band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
+
+		/* optimization: only write through if changed, and
+		 * changed band is the current band
+		 */
+		if (wlc_hw->clk && (band->mhfs[idx] != save)
+		    && (band == wlc_hw->band))
+			wlc_bmac_write_shm(wlc_hw, addr[idx],
+					   (u16) band->mhfs[idx]);
+	}
+
+	if (bands == WLC_BAND_ALL) {
+		wlc_hw->bandstate[0]->mhfs[idx] =
+		    (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
+		wlc_hw->bandstate[1]->mhfs[idx] =
+		    (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
+	}
+}
+
+u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands)
+{
+	struct wlc_hwband *band;
+	ASSERT(idx < MHFMAX);
+
+	switch (bands) {
+	case WLC_BAND_AUTO:
+		band = wlc_hw->band;
+		break;
+	case WLC_BAND_5G:
+		band = wlc_hw->bandstate[BAND_5G_INDEX];
+		break;
+	case WLC_BAND_2G:
+		band = wlc_hw->bandstate[BAND_2G_INDEX];
+		break;
+	default:
+		ASSERT(0);
+		band = NULL;
+	}
+
+	if (!band)
+		return 0;
+
+	return band->mhfs[idx];
+}
+
+static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs)
+{
+	u8 idx;
+	u16 addr[] = {
+		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
+		M_HOST_FLAGS5
+	};
+
+	ASSERT(ARRAY_SIZE(addr) == MHFMAX);
+
+	for (idx = 0; idx < MHFMAX; idx++) {
+		wlc_bmac_write_shm(wlc_hw, addr[idx], mhfs[idx]);
+	}
+}
+
+/* set the maccontrol register to desired reset state and
+ * initialize the sw cache of the register
+ */
+static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw)
+{
+	/* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
+	wlc_hw->maccontrol = 0;
+	wlc_hw->suspended_fifos = 0;
+	wlc_hw->wake_override = 0;
+	wlc_hw->mute_override = 0;
+	wlc_bmac_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
+}
+
+/* set or clear maccontrol bits */
+void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val)
+{
+	u32 maccontrol;
+	u32 new_maccontrol;
+
+	ASSERT((val & ~mask) == 0);
+
+	maccontrol = wlc_hw->maccontrol;
+	new_maccontrol = (maccontrol & ~mask) | val;
+
+	/* if the new maccontrol value is the same as the old, nothing to do */
+	if (new_maccontrol == maccontrol)
+		return;
+
+	/* something changed, cache the new value */
+	wlc_hw->maccontrol = new_maccontrol;
+
+	/* write the new values with overrides applied */
+	wlc_mctrl_write(wlc_hw);
+}
+
+/* write the software state of maccontrol and overrides to the maccontrol register */
+static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw)
+{
+	u32 maccontrol = wlc_hw->maccontrol;
+
+	/* OR in the wake bit if overridden */
+	if (wlc_hw->wake_override)
+		maccontrol |= MCTL_WAKE;
+
+	/* set AP and INFRA bits for mute if needed */
+	if (wlc_hw->mute_override) {
+		maccontrol &= ~(MCTL_AP);
+		maccontrol |= MCTL_INFRA;
+	}
+
+	W_REG(&wlc_hw->regs->maccontrol, maccontrol);
+}
+
+void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw, u32 override_bit)
+{
+	ASSERT((wlc_hw->wake_override & override_bit) == 0);
+
+	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
+		mboolset(wlc_hw->wake_override, override_bit);
+		return;
+	}
+
+	mboolset(wlc_hw->wake_override, override_bit);
+
+	wlc_mctrl_write(wlc_hw);
+	wlc_bmac_wait_for_wake(wlc_hw);
+
+	return;
+}
+
+void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw, u32 override_bit)
+{
+	ASSERT(wlc_hw->wake_override & override_bit);
+
+	mboolclr(wlc_hw->wake_override, override_bit);
+
+	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
+		return;
+
+	wlc_mctrl_write(wlc_hw);
+
+	return;
+}
+
+/* When driver needs ucode to stop beaconing, it has to make sure that
+ * MCTL_AP is clear and MCTL_INFRA is set
+ * Mode           MCTL_AP        MCTL_INFRA
+ * AP                1              1
+ * STA               0              1 <--- This will ensure no beacons
+ * IBSS              0              0
+ */
+static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw)
+{
+	wlc_hw->mute_override = 1;
+
+	/* if maccontrol already has AP == 0 and INFRA == 1 without this
+	 * override, then there is no change to write
+	 */
+	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+		return;
+
+	wlc_mctrl_write(wlc_hw);
+
+	return;
+}
+
+/* Clear the override on AP and INFRA bits */
+static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw)
+{
+	if (wlc_hw->mute_override == 0)
+		return;
+
+	wlc_hw->mute_override = 0;
+
+	/* if maccontrol already has AP == 0 and INFRA == 1 without this
+	 * override, then there is no change to write
+	 */
+	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
+		return;
+
+	wlc_mctrl_write(wlc_hw);
+}
+
+/*
+ * Write a MAC address to the rcmta structure
+ */
+void
+wlc_bmac_set_rcmta(struct wlc_hw_info *wlc_hw, int idx,
+		   const u8 *addr)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	volatile u16 *objdata16 = (volatile u16 *)&regs->objdata;
+	u32 mac_hm;
+	u16 mac_l;
+
+	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
+
+	mac_hm =
+	    (addr[3] << 24) | (addr[2] << 16) |
+	    (addr[1] << 8) | addr[0];
+	mac_l = (addr[5] << 8) | addr[4];
+
+	W_REG(&regs->objaddr, (OBJADDR_RCMTA_SEL | (idx * 2)));
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, mac_hm);
+	W_REG(&regs->objaddr, (OBJADDR_RCMTA_SEL | ((idx * 2) + 1)));
+	(void)R_REG(&regs->objaddr);
+	W_REG(objdata16, mac_l);
+}
+
+/*
+ * Write a MAC address to the given match reg offset in the RXE match engine.
+ */
+void
+wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw, int match_reg_offset,
+		       const u8 *addr)
+{
+	d11regs_t *regs;
+	u16 mac_l;
+	u16 mac_m;
+	u16 mac_h;
+
+	WL_TRACE("wl%d: wlc_bmac_set_addrmatch\n", wlc_hw->unit);
+
+	ASSERT(match_reg_offset < RCM_SIZE);
+
+	regs = wlc_hw->regs;
+	mac_l = addr[0] | (addr[1] << 8);
+	mac_m = addr[2] | (addr[3] << 8);
+	mac_h = addr[4] | (addr[5] << 8);
+
+	/* enter the MAC addr into the RXE match registers */
+	W_REG(&regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
+	W_REG(&regs->rcm_mat_data, mac_l);
+	W_REG(&regs->rcm_mat_data, mac_m);
+	W_REG(&regs->rcm_mat_data, mac_h);
+
+}
+
+void
+wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset, int len,
+			    void *buf)
+{
+	d11regs_t *regs;
+	u32 word;
+	bool be_bit;
+#ifdef IL_BIGENDIAN
+	volatile u16 *dptr = NULL;
+#endif				/* IL_BIGENDIAN */
+	WL_TRACE("wl%d: wlc_bmac_write_template_ram\n", wlc_hw->unit);
+
+	regs = wlc_hw->regs;
+
+	ASSERT(IS_ALIGNED(offset, sizeof(u32)));
+	ASSERT(IS_ALIGNED(len, sizeof(u32)));
+	ASSERT((offset & ~0xffff) == 0);
+
+	W_REG(&regs->tplatewrptr, offset);
+
+	/* if MCTL_BIGEND bit set in mac control register,
+	 * the chip swaps data in fifo, as well as data in
+	 * template ram
+	 */
+	be_bit = (R_REG(&regs->maccontrol) & MCTL_BIGEND) != 0;
+
+	while (len > 0) {
+		memcpy(&word, buf, sizeof(u32));
+
+		if (be_bit)
+			word = cpu_to_be32(word);
+		else
+			word = cpu_to_le32(word);
+
+		W_REG(&regs->tplatewrdata, word);
+
+		buf = (u8 *) buf + sizeof(u32);
+		len -= sizeof(u32);
+	}
+}
+
+void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin)
+{
+	wlc_hw->band->CWmin = newmin;
+
+	W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
+	(void)R_REG(&wlc_hw->regs->objaddr);
+	W_REG(&wlc_hw->regs->objdata, newmin);
+}
+
+void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax)
+{
+	wlc_hw->band->CWmax = newmax;
+
+	W_REG(&wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
+	(void)R_REG(&wlc_hw->regs->objaddr);
+	W_REG(&wlc_hw->regs->objdata, newmax);
+}
+
+void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw)
+{
+	bool fastclk;
+
+	/* request FAST clock if not on */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		wlc_clkctl_clk(wlc_hw, CLK_FAST);
+
+	wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
+
+	ASSERT(wlc_hw->clk);
+
+	wlc_bmac_phy_reset(wlc_hw);
+	wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
+
+	/* restore the clk */
+	if (!fastclk)
+		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+static void
+wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn, int len)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	wlc_bmac_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
+				    bcn);
+	/* write beacon length to SCR */
+	ASSERT(len < 65536);
+	wlc_bmac_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
+	/* mark beacon0 valid */
+	OR_REG(&regs->maccommand, MCMD_BCN0VLD);
+}
+
+static void
+wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn, int len)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	wlc_bmac_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
+				    bcn);
+	/* write beacon length to SCR */
+	ASSERT(len < 65536);
+	wlc_bmac_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
+	/* mark beacon1 valid */
+	OR_REG(&regs->maccommand, MCMD_BCN1VLD);
+}
+
+/* mac is assumed to be suspended at this point */
+void
+wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw, void *bcn, int len,
+			       bool both)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	if (both) {
+		wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
+		wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
+	} else {
+		/* bcn 0 */
+		if (!(R_REG(&regs->maccommand) & MCMD_BCN0VLD))
+			wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
+		/* bcn 1 */
+		else if (!
+			 (R_REG(&regs->maccommand) & MCMD_BCN1VLD))
+			wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
+		else		/* one template should always have been available */
+			ASSERT(0);
+	}
+}
+
+static void WLBANDINITFN(wlc_bmac_upd_synthpu) (struct wlc_hw_info *wlc_hw)
+{
+	u16 v;
+	struct wlc_info *wlc = wlc_hw->wlc;
+	/* update SYNTHPU_DLY */
+
+	if (WLCISLCNPHY(wlc->band)) {
+		v = SYNTHPU_DLY_LPPHY_US;
+	} else if (WLCISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
+		v = SYNTHPU_DLY_NPHY_US;
+	} else {
+		v = SYNTHPU_DLY_BPHY_US;
+	}
+
+	wlc_bmac_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
+}
+
+/* band-specific init */
+static void
+WLBANDINITFN(wlc_bmac_bsinit) (struct wlc_info *wlc, chanspec_t chanspec)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+
+	WL_TRACE("wl%d: wlc_bmac_bsinit: bandunit %d\n",
+		 wlc_hw->unit, wlc_hw->band->bandunit);
+
+	/* sanity check */
+	if (PHY_TYPE(R_REG(&wlc_hw->regs->phyversion)) !=
+	    PHY_TYPE_LCNXN)
+		ASSERT((uint)
+		       PHY_TYPE(R_REG(&wlc_hw->regs->phyversion))
+		       == wlc_hw->band->phytype);
+
+	wlc_ucode_bsinit(wlc_hw);
+
+	wlc_phy_init(wlc_hw->band->pi, chanspec);
+
+	wlc_ucode_txant_set(wlc_hw);
+
+	/* cwmin is band-specific, update hardware with value for current band */
+	wlc_bmac_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
+	wlc_bmac_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
+
+	wlc_bmac_update_slot_timing(wlc_hw,
+				    BAND_5G(wlc_hw->band->
+					    bandtype) ? true : wlc_hw->
+				    shortslot);
+
+	/* write phytype and phyvers */
+	wlc_bmac_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
+	wlc_bmac_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
+
+	/* initialize the txphyctl1 rate table since shmem is shared between bands */
+	wlc_upd_ofdm_pctl1_table(wlc_hw);
+
+	wlc_bmac_upd_synthpu(wlc_hw);
+}
+
+static void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk)
+{
+	WL_TRACE("wl%d: wlc_bmac_core_phy_clk: clk %d\n", wlc_hw->unit, clk);
+
+	wlc_hw->phyclk = clk;
+
+	if (OFF == clk) {	/* clear gmode bit, put phy into reset */
+
+		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
+			       (SICF_PRST | SICF_FGC));
+		udelay(1);
+		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
+		udelay(1);
+
+	} else {		/* take phy out of reset */
+
+		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
+		udelay(1);
+		si_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
+		udelay(1);
+
+	}
+}
+
+/* Perform a soft reset of the PHY PLL */
+void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw)
+{
+	WL_TRACE("wl%d: wlc_bmac_core_phypll_reset\n", wlc_hw->unit);
+
+	si_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
+	udelay(1);
+	si_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
+	udelay(1);
+	si_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
+	udelay(1);
+	si_corereg(wlc_hw->sih, SI_CC_IDX,
+		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
+	udelay(1);
+}
+
+/* light way to turn on phy clock without reset for NPHY only
+ *  refer to wlc_bmac_core_phy_clk for full version
+ */
+void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk)
+{
+	/* support(necessary for NPHY and HYPHY) only */
+	if (!WLCISNPHY(wlc_hw->band))
+		return;
+
+	if (ON == clk)
+		si_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
+	else
+		si_core_cflags(wlc_hw->sih, SICF_FGC, 0);
+
+}
+
+void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk)
+{
+	if (ON == clk)
+		si_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
+	else
+		si_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
+}
+
+void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw)
+{
+	wlc_phy_t *pih = wlc_hw->band->pi;
+	u32 phy_bw_clkbits;
+	bool phy_in_reset = false;
+
+	WL_TRACE("wl%d: wlc_bmac_phy_reset\n", wlc_hw->unit);
+
+	if (pih == NULL)
+		return;
+
+	phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
+
+	/* Specfic reset sequence required for NPHY rev 3 and 4 */
+	if (WLCISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
+	    NREV_LE(wlc_hw->band->phyrev, 4)) {
+		/* Set the PHY bandwidth */
+		si_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
+
+		udelay(1);
+
+		/* Perform a soft reset of the PHY PLL */
+		wlc_bmac_core_phypll_reset(wlc_hw);
+
+		/* reset the PHY */
+		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
+			       (SICF_PRST | SICF_PCLKE));
+		phy_in_reset = true;
+	} else {
+
+		si_core_cflags(wlc_hw->sih,
+			       (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
+			       (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
+	}
+
+	udelay(2);
+	wlc_bmac_core_phy_clk(wlc_hw, ON);
+
+	if (pih)
+		wlc_phy_anacore(pih, ON);
+}
+
+/* switch to and initialize new band */
+static void
+WLBANDINITFN(wlc_bmac_setband) (struct wlc_hw_info *wlc_hw, uint bandunit,
+				chanspec_t chanspec) {
+	struct wlc_info *wlc = wlc_hw->wlc;
+	u32 macintmask;
+
+	ASSERT(NBANDS_HW(wlc_hw) > 1);
+	ASSERT(bandunit != wlc_hw->band->bandunit);
+
+	/* Enable the d11 core before accessing it */
+	if (!si_iscoreup(wlc_hw->sih)) {
+		si_core_reset(wlc_hw->sih, 0, 0);
+		ASSERT(si_iscoreup(wlc_hw->sih));
+		wlc_mctrl_reset(wlc_hw);
+	}
+
+	macintmask = wlc_setband_inact(wlc, bandunit);
+
+	if (!wlc_hw->up)
+		return;
+
+	wlc_bmac_core_phy_clk(wlc_hw, ON);
+
+	/* band-specific initializations */
+	wlc_bmac_bsinit(wlc, chanspec);
+
+	/*
+	 * If there are any pending software interrupt bits,
+	 * then replace these with a harmless nonzero value
+	 * so wlc_dpc() will re-enable interrupts when done.
+	 */
+	if (wlc->macintstatus)
+		wlc->macintstatus = MI_DMAINT;
+
+	/* restore macintmask */
+	wl_intrsrestore(wlc->wl, macintmask);
+
+	/* ucode should still be suspended.. */
+	ASSERT((R_REG(&wlc_hw->regs->maccontrol) & MCTL_EN_MAC) ==
+	       0);
+}
+
+/* low-level band switch utility routine */
+void WLBANDINITFN(wlc_setxband) (struct wlc_hw_info *wlc_hw, uint bandunit)
+{
+	WL_TRACE("wl%d: wlc_setxband: bandunit %d\n", wlc_hw->unit, bandunit);
+
+	wlc_hw->band = wlc_hw->bandstate[bandunit];
+
+	/* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
+	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
+
+	/* set gmode core flag */
+	if (wlc_hw->sbclk && !wlc_hw->noreset) {
+		si_core_cflags(wlc_hw->sih, SICF_GMODE,
+			       ((bandunit == 0) ? SICF_GMODE : 0));
+	}
+}
+
+static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw)
+{
+
+	/* reject unsupported corerev */
+	if (!VALID_COREREV(wlc_hw->corerev)) {
+		WL_ERROR("unsupported core rev %d\n", wlc_hw->corerev);
+		return false;
+	}
+
+	return true;
+}
+
+static bool wlc_validboardtype(struct wlc_hw_info *wlc_hw)
+{
+	bool goodboard = true;
+	uint boardrev = wlc_hw->boardrev;
+
+	if (boardrev == 0)
+		goodboard = false;
+	else if (boardrev > 0xff) {
+		uint brt = (boardrev & 0xf000) >> 12;
+		uint b0 = (boardrev & 0xf00) >> 8;
+		uint b1 = (boardrev & 0xf0) >> 4;
+		uint b2 = boardrev & 0xf;
+
+		if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
+		    || (b2 > 9))
+			goodboard = false;
+	}
+
+	if (wlc_hw->sih->boardvendor != VENDOR_BROADCOM)
+		return goodboard;
+
+	return goodboard;
+}
+
+static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw)
+{
+	const char *varname = "macaddr";
+	char *macaddr;
+
+	/* If macaddr exists, use it (Sromrev4, CIS, ...). */
+	macaddr = getvar(wlc_hw->vars, varname);
+	if (macaddr != NULL)
+		return macaddr;
+
+	if (NBANDS_HW(wlc_hw) > 1)
+		varname = "et1macaddr";
+	else
+		varname = "il0macaddr";
+
+	macaddr = getvar(wlc_hw->vars, varname);
+	if (macaddr == NULL) {
+		WL_ERROR("wl%d: wlc_get_macaddr: macaddr getvar(%s) not found\n",
+			 wlc_hw->unit, varname);
+	}
+
+	return macaddr;
+}
+
+/*
+ * Return true if radio is disabled, otherwise false.
+ * hw radio disable signal is an external pin, users activate it asynchronously
+ * this function could be called when driver is down and w/o clock
+ * it operates on different registers depending on corerev and boardflag.
+ */
+bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw)
+{
+	bool v, clk, xtal;
+	u32 resetbits = 0, flags = 0;
+
+	xtal = wlc_hw->sbclk;
+	if (!xtal)
+		wlc_bmac_xtal(wlc_hw, ON);
+
+	/* may need to take core out of reset first */
+	clk = wlc_hw->clk;
+	if (!clk) {
+		/*
+		 * mac no longer enables phyclk automatically when driver
+		 * accesses phyreg throughput mac. This can be skipped since
+		 * only mac reg is accessed below
+		 */
+		flags |= SICF_PCLKE;
+
+		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
+		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+		    (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
+		    (wlc_hw->sih->chip == BCM43421_CHIP_ID))
+			wlc_hw->regs =
+			    (d11regs_t *) si_setcore(wlc_hw->sih, D11_CORE_ID,
+						     0);
+		si_core_reset(wlc_hw->sih, flags, resetbits);
+		wlc_mctrl_reset(wlc_hw);
+	}
+
+	v = ((R_REG(&wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
+
+	/* put core back into reset */
+	if (!clk)
+		si_core_disable(wlc_hw->sih, 0);
+
+	if (!xtal)
+		wlc_bmac_xtal(wlc_hw, OFF);
+
+	return v;
+}
+
+/* Initialize just the hardware when coming out of POR or S3/S5 system states */
+void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw)
+{
+	if (wlc_hw->wlc->pub->hw_up)
+		return;
+
+	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
+
+	/*
+	 * Enable pll and xtal, initialize the power control registers,
+	 * and force fastclock for the remainder of wlc_up().
+	 */
+	wlc_bmac_xtal(wlc_hw, ON);
+	si_clkctl_init(wlc_hw->sih);
+	wlc_clkctl_clk(wlc_hw, CLK_FAST);
+
+	if (wlc_hw->sih->bustype == PCI_BUS) {
+		si_pci_fixcfg(wlc_hw->sih);
+
+		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
+		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+		    (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
+		    (wlc_hw->sih->chip == BCM43421_CHIP_ID))
+			wlc_hw->regs =
+			    (d11regs_t *) si_setcore(wlc_hw->sih, D11_CORE_ID,
+						     0);
+	}
+
+	/* Inform phy that a POR reset has occurred so it does a complete phy init */
+	wlc_phy_por_inform(wlc_hw->band->pi);
+
+	wlc_hw->ucode_loaded = false;
+	wlc_hw->wlc->pub->hw_up = true;
+
+	if ((wlc_hw->boardflags & BFL_FEM)
+	    && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+		if (!
+		    (wlc_hw->boardrev >= 0x1250
+		     && (wlc_hw->boardflags & BFL_FEM_BT)))
+			si_epa_4313war(wlc_hw->sih);
+	}
+}
+
+static bool wlc_dma_rxreset(struct wlc_hw_info *wlc_hw, uint fifo)
+{
+	struct hnddma_pub *di = wlc_hw->di[fifo];
+	return dma_rxreset(di);
+}
+
+/* d11 core reset
+ *   ensure fask clock during reset
+ *   reset dma
+ *   reset d11(out of reset)
+ *   reset phy(out of reset)
+ *   clear software macintstatus for fresh new start
+ * one testing hack wlc_hw->noreset will bypass the d11/phy reset
+ */
+void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags)
+{
+	d11regs_t *regs;
+	uint i;
+	bool fastclk;
+	u32 resetbits = 0;
+
+	if (flags == WLC_USE_COREFLAGS)
+		flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
+
+	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
+
+	regs = wlc_hw->regs;
+
+	/* request FAST clock if not on  */
+	fastclk = wlc_hw->forcefastclk;
+	if (!fastclk)
+		wlc_clkctl_clk(wlc_hw, CLK_FAST);
+
+	/* reset the dma engines except first time thru */
+	if (si_iscoreup(wlc_hw->sih)) {
+		for (i = 0; i < NFIFO; i++)
+			if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) {
+				WL_ERROR("wl%d: %s: dma_txreset[%d]: cannot stop dma\n",
+					 wlc_hw->unit, __func__, i);
+			}
+
+		if ((wlc_hw->di[RX_FIFO])
+		    && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) {
+			WL_ERROR("wl%d: %s: dma_rxreset[%d]: cannot stop dma\n",
+				 wlc_hw->unit, __func__, RX_FIFO);
+		}
+	}
+	/* if noreset, just stop the psm and return */
+	if (wlc_hw->noreset) {
+		wlc_hw->wlc->macintstatus = 0;	/* skip wl_dpc after down */
+		wlc_bmac_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
+		return;
+	}
+
+	/*
+	 * mac no longer enables phyclk automatically when driver accesses
+	 * phyreg throughput mac, AND phy_reset is skipped at early stage when
+	 * band->pi is invalid. need to enable PHY CLK
+	 */
+	flags |= SICF_PCLKE;
+
+	/* reset the core
+	 * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
+	 *  is cleared by the core_reset. have to re-request it.
+	 *  This adds some delay and we can optimize it by also requesting fastclk through
+	 *  chipcommon during this period if necessary. But that has to work coordinate
+	 *  with other driver like mips/arm since they may touch chipcommon as well.
+	 */
+	wlc_hw->clk = false;
+	si_core_reset(wlc_hw->sih, flags, resetbits);
+	wlc_hw->clk = true;
+	if (wlc_hw->band && wlc_hw->band->pi)
+		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
+
+	wlc_mctrl_reset(wlc_hw);
+
+	if (PMUCTL_ENAB(wlc_hw->sih))
+		wlc_clkctl_clk(wlc_hw, CLK_FAST);
+
+	wlc_bmac_phy_reset(wlc_hw);
+
+	/* turn on PHY_PLL */
+	wlc_bmac_core_phypll_ctl(wlc_hw, true);
+
+	/* clear sw intstatus */
+	wlc_hw->wlc->macintstatus = 0;
+
+	/* restore the clk setting */
+	if (!fastclk)
+		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
+}
+
+/* txfifo sizes needs to be modified(increased) since the newer cores
+ * have more memory.
+ */
+static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	u16 fifo_nu;
+	u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
+	u16 txfifo_def, txfifo_def1;
+	u16 txfifo_cmd;
+
+	/* tx fifos start at TXFIFO_START_BLK from the Base address */
+	txfifo_startblk = TXFIFO_START_BLK;
+
+	/* sequence of operations:  reset fifo, set fifo size, reset fifo */
+	for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
+
+		txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
+		txfifo_def = (txfifo_startblk & 0xff) |
+		    (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
+		txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
+		    ((((txfifo_endblk -
+			1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
+		txfifo_cmd =
+		    TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
+
+		W_REG(&regs->xmtfifocmd, txfifo_cmd);
+		W_REG(&regs->xmtfifodef, txfifo_def);
+		W_REG(&regs->xmtfifodef1, txfifo_def1);
+
+		W_REG(&regs->xmtfifocmd, txfifo_cmd);
+
+		txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
+	}
+	/*
+	 * need to propagate to shm location to be in sync since ucode/hw won't
+	 * do this
+	 */
+	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE0,
+			   wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
+	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE1,
+			   wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
+	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE2,
+			   ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
+			    xmtfifo_sz[TX_AC_BK_FIFO]));
+	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE3,
+			   ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
+			    xmtfifo_sz[TX_BCMC_FIFO]));
+}
+
+/* d11 core init
+ *   reset PSM
+ *   download ucode/PCM
+ *   let ucode run to suspended
+ *   download ucode inits
+ *   config other core registers
+ *   init dma
+ */
+static void wlc_coreinit(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	d11regs_t *regs;
+	u32 sflags;
+	uint bcnint_us;
+	uint i = 0;
+	bool fifosz_fixup = false;
+	int err = 0;
+	u16 buf[NFIFO];
+
+	regs = wlc_hw->regs;
+
+	WL_TRACE("wl%d: wlc_coreinit\n", wlc_hw->unit);
+
+	/* reset PSM */
+	wlc_bmac_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
+
+	wlc_ucode_download(wlc_hw);
+	/*
+	 * FIFOSZ fixup. driver wants to controls the fifo allocation.
+	 */
+	fifosz_fixup = true;
+
+	/* let the PSM run to the suspended state, set mode to BSS STA */
+	W_REG(&regs->macintstatus, -1);
+	wlc_bmac_mctrl(wlc_hw, ~0,
+		       (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
+
+	/* wait for ucode to self-suspend after auto-init */
+	SPINWAIT(((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0),
+		 1000 * 1000);
+	if ((R_REG(&regs->macintstatus) & MI_MACSSPNDD) == 0)
+		WL_ERROR("wl%d: wlc_coreinit: ucode did not self-suspend!\n",
+			 wlc_hw->unit);
+
+	wlc_gpio_init(wlc);
+
+	sflags = si_core_sflags(wlc_hw->sih, 0, 0);
+
+	if (D11REV_IS(wlc_hw->corerev, 23)) {
+		if (WLCISNPHY(wlc_hw->band))
+			wlc_write_inits(wlc_hw, d11n0initvals16);
+		else
+			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
+				 __func__, wlc_hw->unit, wlc_hw->corerev);
+	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
+		if (WLCISLCNPHY(wlc_hw->band)) {
+			wlc_write_inits(wlc_hw, d11lcn0initvals24);
+		} else {
+			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
+				 __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	} else {
+		WL_ERROR("%s: wl%d: unsupported corerev %d\n",
+			 __func__, wlc_hw->unit, wlc_hw->corerev);
+	}
+
+	/* For old ucode, txfifo sizes needs to be modified(increased) */
+	if (fifosz_fixup == true) {
+		wlc_corerev_fifofixup(wlc_hw);
+	}
+
+	/* check txfifo allocations match between ucode and driver */
+	buf[TX_AC_BE_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE0);
+	if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
+		i = TX_AC_BE_FIFO;
+		err = -1;
+	}
+	buf[TX_AC_VI_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE1);
+	if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
+		i = TX_AC_VI_FIFO;
+		err = -1;
+	}
+	buf[TX_AC_BK_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE2);
+	buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
+	buf[TX_AC_BK_FIFO] &= 0xff;
+	if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
+		i = TX_AC_BK_FIFO;
+		err = -1;
+	}
+	if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
+		i = TX_AC_VO_FIFO;
+		err = -1;
+	}
+	buf[TX_BCMC_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE3);
+	buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
+	buf[TX_BCMC_FIFO] &= 0xff;
+	if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
+		i = TX_BCMC_FIFO;
+		err = -1;
+	}
+	if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
+		i = TX_ATIM_FIFO;
+		err = -1;
+	}
+	if (err != 0) {
+		WL_ERROR("wlc_coreinit: txfifo mismatch: ucode size %d driver size %d index %d\n",
+			 buf[i], wlc_hw->xmtfifo_sz[i], i);
+		ASSERT(0);
+	}
+
+	/* make sure we can still talk to the mac */
+	ASSERT(R_REG(&regs->maccontrol) != 0xffffffff);
+
+	/* band-specific inits done by wlc_bsinit() */
+
+	/* Set up frame burst size and antenna swap threshold init values */
+	wlc_bmac_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
+	wlc_bmac_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
+
+	/* enable one rx interrupt per received frame */
+	W_REG(&regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
+
+	/* set the station mode (BSS STA) */
+	wlc_bmac_mctrl(wlc_hw,
+		       (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
+		       (MCTL_INFRA | MCTL_DISCARD_PMQ));
+
+	/* set up Beacon interval */
+	bcnint_us = 0x8000 << 10;
+	W_REG(&regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
+	W_REG(&regs->tsf_cfpstart, bcnint_us);
+	W_REG(&regs->macintstatus, MI_GP1);
+
+	/* write interrupt mask */
+	W_REG(&regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
+
+	/* allow the MAC to control the PHY clock (dynamic on/off) */
+	wlc_bmac_macphyclk_set(wlc_hw, ON);
+
+	/* program dynamic clock control fast powerup delay register */
+	wlc->fastpwrup_dly = si_clkctl_fast_pwrup_delay(wlc_hw->sih);
+	W_REG(&regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
+
+	/* tell the ucode the corerev */
+	wlc_bmac_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
+
+	/* tell the ucode MAC capabilities */
+	wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_L,
+			   (u16) (wlc_hw->machwcap & 0xffff));
+	wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_H,
+			   (u16) ((wlc_hw->
+				      machwcap >> 16) & 0xffff));
+
+	/* write retry limits to SCR, this done after PSM init */
+	W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, wlc_hw->SRL);
+	W_REG(&regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, wlc_hw->LRL);
+
+	/* write rate fallback retry limits */
+	wlc_bmac_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
+	wlc_bmac_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
+
+	AND_REG(&regs->ifs_ctl, 0x0FFF);
+	W_REG(&regs->ifs_aifsn, EDCF_AIFSN_MIN);
+
+	/* dma initializations */
+	wlc->txpend16165war = 0;
+
+	/* init the tx dma engines */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc_hw->di[i])
+			dma_txinit(wlc_hw->di[i]);
+	}
+
+	/* init the rx dma engine(s) and post receive buffers */
+	dma_rxinit(wlc_hw->di[RX_FIFO]);
+	dma_rxfill(wlc_hw->di[RX_FIFO]);
+}
+
+/* This function is used for changing the tsf frac register
+ * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
+ * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
+ * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
+ * HTPHY Formula is 2^26/freq(MHz) e.g.
+ * For spuron2 - 126MHz -> 2^26/126 = 532610.0
+ *  - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
+ * For spuron: 123MHz -> 2^26/123    = 545600.5
+ *  - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
+ * For spur off: 120MHz -> 2^26/120    = 559240.5
+ *  - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
+ */
+
+void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode)
+{
+	d11regs_t *regs;
+	regs = wlc_hw->regs;
+
+	if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
+	    (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
+		if (spurmode == WL_SPURAVOID_ON2) {	/* 126Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x2082);
+			W_REG(&regs->tsf_clk_frac_h, 0x8);
+		} else if (spurmode == WL_SPURAVOID_ON1) {	/* 123Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x5341);
+			W_REG(&regs->tsf_clk_frac_h, 0x8);
+		} else {	/* 120Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x8889);
+			W_REG(&regs->tsf_clk_frac_h, 0x8);
+		}
+	} else if (WLCISLCNPHY(wlc_hw->band)) {
+		if (spurmode == WL_SPURAVOID_ON1) {	/* 82Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0x7CE0);
+			W_REG(&regs->tsf_clk_frac_h, 0xC);
+		} else {	/* 80Mhz */
+			W_REG(&regs->tsf_clk_frac_l, 0xCCCD);
+			W_REG(&regs->tsf_clk_frac_h, 0xC);
+		}
+	}
+}
+
+/* Initialize GPIOs that are controlled by D11 core */
+static void wlc_gpio_init(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	d11regs_t *regs;
+	u32 gc, gm;
+
+	regs = wlc_hw->regs;
+
+	/* use GPIO select 0 to get all gpio signals from the gpio out reg */
+	wlc_bmac_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
+
+	/*
+	 * Common GPIO setup:
+	 *      G0 = LED 0 = WLAN Activity
+	 *      G1 = LED 1 = WLAN 2.4 GHz Radio State
+	 *      G2 = LED 2 = WLAN 5 GHz Radio State
+	 *      G4 = radio disable input (HI enabled, LO disabled)
+	 */
+
+	gc = gm = 0;
+
+	/* Allocate GPIOs for mimo antenna diversity feature */
+	if (wlc_hw->antsel_type == ANTSEL_2x3) {
+		/* Enable antenna diversity, use 2x3 mode */
+		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+			     MHF3_ANTSEL_EN, WLC_BAND_ALL);
+		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
+			     MHF3_ANTSEL_MODE, WLC_BAND_ALL);
+
+		/* init superswitch control */
+		wlc_phy_antsel_init(wlc_hw->band->pi, false);
+
+	} else if (wlc_hw->antsel_type == ANTSEL_2x4) {
+		ASSERT((gm & BOARD_GPIO_12) == 0);
+		gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
+		/*
+		 * The board itself is powered by these GPIOs
+		 * (when not sending pattern) so set them high
+		 */
+		OR_REG(&regs->psm_gpio_oe,
+		       (BOARD_GPIO_12 | BOARD_GPIO_13));
+		OR_REG(&regs->psm_gpio_out,
+		       (BOARD_GPIO_12 | BOARD_GPIO_13));
+
+		/* Enable antenna diversity, use 2x4 mode */
+		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
+			     MHF3_ANTSEL_EN, WLC_BAND_ALL);
+		wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
+			     WLC_BAND_ALL);
+
+		/* Configure the desired clock to be 4Mhz */
+		wlc_bmac_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
+				   ANTSEL_CLKDIV_4MHZ);
+	}
+
+	/* gpio 9 controls the PA.  ucode is responsible for wiggling out and oe */
+	if (wlc_hw->boardflags & BFL_PACTRL)
+		gm |= gc |= BOARD_GPIO_PACTRL;
+
+	/* apply to gpiocontrol register */
+	si_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
+}
+
+static void wlc_ucode_download(struct wlc_hw_info *wlc_hw)
+{
+	struct wlc_info *wlc;
+	wlc = wlc_hw->wlc;
+
+	if (wlc_hw->ucode_loaded)
+		return;
+
+	if (D11REV_IS(wlc_hw->corerev, 23)) {
+		if (WLCISNPHY(wlc_hw->band)) {
+			wlc_ucode_write(wlc_hw, bcm43xx_16_mimo,
+					bcm43xx_16_mimosz);
+			wlc_hw->ucode_loaded = true;
+		} else
+			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
+				 __func__, wlc_hw->unit, wlc_hw->corerev);
+	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
+		if (WLCISLCNPHY(wlc_hw->band)) {
+			wlc_ucode_write(wlc_hw, bcm43xx_24_lcn,
+					bcm43xx_24_lcnsz);
+			wlc_hw->ucode_loaded = true;
+		} else {
+			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
+				 __func__, wlc_hw->unit, wlc_hw->corerev);
+		}
+	}
+}
+
+static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
+			      const uint nbytes) {
+	d11regs_t *regs = wlc_hw->regs;
+	uint i;
+	uint count;
+
+	WL_TRACE("wl%d: wlc_ucode_write\n", wlc_hw->unit);
+
+	ASSERT(IS_ALIGNED(nbytes, sizeof(u32)));
+
+	count = (nbytes / sizeof(u32));
+
+	W_REG(&regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
+	(void)R_REG(&regs->objaddr);
+	for (i = 0; i < count; i++)
+		W_REG(&regs->objdata, ucode[i]);
+}
+
+static void wlc_write_inits(struct wlc_hw_info *wlc_hw,
+			    const struct d11init *inits)
+{
+	int i;
+	volatile u8 *base;
+
+	WL_TRACE("wl%d: wlc_write_inits\n", wlc_hw->unit);
+
+	base = (volatile u8 *)wlc_hw->regs;
+
+	for (i = 0; inits[i].addr != 0xffff; i++) {
+		ASSERT((inits[i].size == 2) || (inits[i].size == 4));
+
+		if (inits[i].size == 2)
+			W_REG((u16 *)(base + inits[i].addr),
+			      inits[i].value);
+		else if (inits[i].size == 4)
+			W_REG((u32 *)(base + inits[i].addr),
+			      inits[i].value);
+	}
+}
+
+static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw)
+{
+	u16 phyctl;
+	u16 phytxant = wlc_hw->bmac_phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* set the Probe Response frame phy control word */
+	phyctl = wlc_bmac_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
+	phyctl = (phyctl & ~mask) | phytxant;
+	wlc_bmac_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
+
+	/* set the Response (ACK/CTS) frame phy control word */
+	phyctl = wlc_bmac_read_shm(wlc_hw, M_RSP_PCTLWD);
+	phyctl = (phyctl & ~mask) | phytxant;
+	wlc_bmac_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
+}
+
+void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant)
+{
+	/* update sw state */
+	wlc_hw->bmac_phytxant = phytxant;
+
+	/* push to ucode if up */
+	if (!wlc_hw->up)
+		return;
+	wlc_ucode_txant_set(wlc_hw);
+
+}
+
+u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw)
+{
+	return (u16) wlc_hw->wlc->stf->txant;
+}
+
+void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw, u8 antsel_type)
+{
+	wlc_hw->antsel_type = antsel_type;
+
+	/* Update the antsel type for phy module to use */
+	wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
+}
+
+void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw)
+{
+	bool fatal = false;
+	uint unit;
+	uint intstatus, idx;
+	d11regs_t *regs = wlc_hw->regs;
+
+	unit = wlc_hw->unit;
+
+	for (idx = 0; idx < NFIFO; idx++) {
+		/* read intstatus register and ignore any non-error bits */
+		intstatus =
+		    R_REG(&regs->intctrlregs[idx].intstatus) & I_ERRORS;
+		if (!intstatus)
+			continue;
+
+		WL_TRACE("wl%d: wlc_bmac_fifoerrors: intstatus%d 0x%x\n",
+			 unit, idx, intstatus);
+
+		if (intstatus & I_RO) {
+			WL_ERROR("wl%d: fifo %d: receive fifo overflow\n",
+				 unit, idx);
+			wlc_hw->wlc->pub->_cnt->rxoflo++;
+			fatal = true;
+		}
+
+		if (intstatus & I_PC) {
+			WL_ERROR("wl%d: fifo %d: descriptor error\n",
+				 unit, idx);
+			wlc_hw->wlc->pub->_cnt->dmade++;
+			fatal = true;
+		}
+
+		if (intstatus & I_PD) {
+			WL_ERROR("wl%d: fifo %d: data error\n", unit, idx);
+			wlc_hw->wlc->pub->_cnt->dmada++;
+			fatal = true;
+		}
+
+		if (intstatus & I_DE) {
+			WL_ERROR("wl%d: fifo %d: descriptor protocol error\n",
+				 unit, idx);
+			wlc_hw->wlc->pub->_cnt->dmape++;
+			fatal = true;
+		}
+
+		if (intstatus & I_RU) {
+			WL_ERROR("wl%d: fifo %d: receive descriptor underflow\n",
+				 idx, unit);
+			wlc_hw->wlc->pub->_cnt->rxuflo[idx]++;
+		}
+
+		if (intstatus & I_XU) {
+			WL_ERROR("wl%d: fifo %d: transmit fifo underflow\n",
+				 idx, unit);
+			wlc_hw->wlc->pub->_cnt->txuflo++;
+			fatal = true;
+		}
+
+		if (fatal) {
+			wlc_fatal_error(wlc_hw->wlc);	/* big hammer */
+			break;
+		} else
+			W_REG(&regs->intctrlregs[idx].intstatus,
+			      intstatus);
+	}
+}
+
+void wlc_intrson(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	ASSERT(wlc->defmacintmask);
+	wlc->macintmask = wlc->defmacintmask;
+	W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+/* callback for siutils.c, which has only wlc handler, no wl
+ * they both check up, not only because there is no need to off/restore d11 interrupt
+ *  but also because per-port code may require sync with valid interrupt.
+ */
+
+static u32 wlc_wlintrsoff(struct wlc_info *wlc)
+{
+	if (!wlc->hw->up)
+		return 0;
+
+	return wl_intrsoff(wlc->wl);
+}
+
+static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask)
+{
+	if (!wlc->hw->up)
+		return;
+
+	wl_intrsrestore(wlc->wl, macintmask);
+}
+
+u32 wlc_intrsoff(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	u32 macintmask;
+
+	if (!wlc_hw->clk)
+		return 0;
+
+	macintmask = wlc->macintmask;	/* isr can still happen */
+
+	W_REG(&wlc_hw->regs->macintmask, 0);
+	(void)R_REG(&wlc_hw->regs->macintmask);	/* sync readback */
+	udelay(1);		/* ensure int line is no longer driven */
+	wlc->macintmask = 0;
+
+	/* return previous macintmask; resolve race between us and our isr */
+	return wlc->macintstatus ? 0 : macintmask;
+}
+
+void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	if (!wlc_hw->clk)
+		return;
+
+	wlc->macintmask = macintmask;
+	W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
+}
+
+static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, mbool flags)
+{
+	u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+	if (on) {
+		/* suspend tx fifos */
+		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
+		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
+		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
+		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
+
+		/* zero the address match register so we do not send ACKs */
+		wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+				       null_ether_addr);
+	} else {
+		/* resume tx fifos */
+		if (!wlc_hw->wlc->tx_suspended) {
+			wlc_bmac_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
+		}
+		wlc_bmac_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
+		wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
+		wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
+
+		/* Restore address */
+		wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
+				       wlc_hw->etheraddr);
+	}
+
+	wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
+
+	if (on)
+		wlc_ucode_mute_override_set(wlc_hw);
+	else
+		wlc_ucode_mute_override_clear(wlc_hw);
+}
+
+int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo, uint *blocks)
+{
+	if (fifo >= NFIFO)
+		return BCME_RANGE;
+
+	*blocks = wlc_hw->xmtfifo_sz[fifo];
+
+	return 0;
+}
+
+/* wlc_bmac_tx_fifo_suspended:
+ * Check the MAC's tx suspend status for a tx fifo.
+ *
+ * When the MAC acknowledges a tx suspend, it indicates that no more
+ * packets will be transmitted out the radio. This is independent of
+ * DMA channel suspension---the DMA may have finished suspending, or may still
+ * be pulling data into a tx fifo, by the time the MAC acks the suspend
+ * request.
+ */
+static bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw, uint tx_fifo)
+{
+	/* check that a suspend has been requested and is no longer pending */
+
+	/*
+	 * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
+	 * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
+	 * chnstatus register.
+	 * The tx fifo suspend completion is independent of the DMA suspend completion and
+	 *   may be acked before or after the DMA is suspended.
+	 */
+	if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
+	    (R_REG(&wlc_hw->regs->chnstatus) &
+	     (1 << tx_fifo)) == 0)
+		return true;
+
+	return false;
+}
+
+static void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo)
+{
+	u8 fifo = 1 << tx_fifo;
+
+	/* Two clients of this code, 11h Quiet period and scanning. */
+
+	/* only suspend if not already suspended */
+	if ((wlc_hw->suspended_fifos & fifo) == fifo)
+		return;
+
+	/* force the core awake only if not already */
+	if (wlc_hw->suspended_fifos == 0)
+		wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_TXFIFO);
+
+	wlc_hw->suspended_fifos |= fifo;
+
+	if (wlc_hw->di[tx_fifo]) {
+		/* Suspending AMPDU transmissions in the middle can cause underflow
+		 * which may result in mismatch between ucode and driver
+		 * so suspend the mac before suspending the FIFO
+		 */
+		if (WLC_PHY_11N_CAP(wlc_hw->band))
+			wlc_suspend_mac_and_wait(wlc_hw->wlc);
+
+		dma_txsuspend(wlc_hw->di[tx_fifo]);
+
+		if (WLC_PHY_11N_CAP(wlc_hw->band))
+			wlc_enable_mac(wlc_hw->wlc);
+	}
+}
+
+static void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo)
+{
+	/* BMAC_NOTE: WLC_TX_FIFO_ENAB is done in wlc_dpc() for DMA case but need to be done
+	 * here for PIO otherwise the watchdog will catch the inconsistency and fire
+	 */
+	/* Two clients of this code, 11h Quiet period and scanning. */
+	if (wlc_hw->di[tx_fifo])
+		dma_txresume(wlc_hw->di[tx_fifo]);
+
+	/* allow core to sleep again */
+	if (wlc_hw->suspended_fifos == 0)
+		return;
+	else {
+		wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
+		if (wlc_hw->suspended_fifos == 0)
+			wlc_ucode_wake_override_clear(wlc_hw,
+						      WLC_WAKE_OVERRIDE_TXFIFO);
+	}
+}
+
+/*
+ * Read and clear macintmask and macintstatus and intstatus registers.
+ * This routine should be called with interrupts off
+ * Return:
+ *   -1 if DEVICEREMOVED(wlc) evaluates to true;
+ *   0 if the interrupt is not for us, or we are in some special cases;
+ *   device interrupt status bits otherwise.
+ */
+static inline u32 wlc_intstatus(struct wlc_info *wlc, bool in_isr)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	u32 macintstatus;
+
+	/* macintstatus includes a DMA interrupt summary bit */
+	macintstatus = R_REG(&regs->macintstatus);
+
+	WL_TRACE("wl%d: macintstatus: 0x%x\n", wlc_hw->unit, macintstatus);
+
+	/* detect cardbus removed, in power down(suspend) and in reset */
+	if (DEVICEREMOVED(wlc))
+		return -1;
+
+	/* DEVICEREMOVED succeeds even when the core is still resetting,
+	 * handle that case here.
+	 */
+	if (macintstatus == 0xffffffff)
+		return 0;
+
+	/* defer unsolicited interrupts */
+	macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
+
+	/* if not for us */
+	if (macintstatus == 0)
+		return 0;
+
+	/* interrupts are already turned off for CFE build
+	 * Caution: For CFE Turning off the interrupts again has some undesired
+	 * consequences
+	 */
+	/* turn off the interrupts */
+	W_REG(&regs->macintmask, 0);
+	(void)R_REG(&regs->macintmask);	/* sync readback */
+	wlc->macintmask = 0;
+
+	/* clear device interrupts */
+	W_REG(&regs->macintstatus, macintstatus);
+
+	/* MI_DMAINT is indication of non-zero intstatus */
+	if (macintstatus & MI_DMAINT) {
+		/*
+		 * only fifo interrupt enabled is I_RI in
+		 * RX_FIFO. If MI_DMAINT is set, assume it
+		 * is set and clear the interrupt.
+		 */
+		W_REG(&regs->intctrlregs[RX_FIFO].intstatus,
+		      DEF_RXINTMASK);
+	}
+
+	return macintstatus;
+}
+
+/* Update wlc->macintstatus and wlc->intstatus[]. */
+/* Return true if they are updated successfully. false otherwise */
+bool wlc_intrsupd(struct wlc_info *wlc)
+{
+	u32 macintstatus;
+
+	ASSERT(wlc->macintstatus != 0);
+
+	/* read and clear macintstatus and intstatus registers */
+	macintstatus = wlc_intstatus(wlc, false);
+
+	/* device is removed */
+	if (macintstatus == 0xffffffff)
+		return false;
+
+	/* update interrupt status in software */
+	wlc->macintstatus |= macintstatus;
+
+	return true;
+}
+
+/*
+ * First-level interrupt processing.
+ * Return true if this was our interrupt, false otherwise.
+ * *wantdpc will be set to true if further wlc_dpc() processing is required,
+ * false otherwise.
+ */
+bool BCMFASTPATH wlc_isr(struct wlc_info *wlc, bool *wantdpc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	u32 macintstatus;
+
+	*wantdpc = false;
+
+	if (!wlc_hw->up || !wlc->macintmask)
+		return false;
+
+	/* read and clear macintstatus and intstatus registers */
+	macintstatus = wlc_intstatus(wlc, true);
+
+	if (macintstatus == 0xffffffff)
+		WL_ERROR("DEVICEREMOVED detected in the ISR code path\n");
+
+	/* it is not for us */
+	if (macintstatus == 0)
+		return false;
+
+	*wantdpc = true;
+
+	/* save interrupt status bits */
+	ASSERT(wlc->macintstatus == 0);
+	wlc->macintstatus = macintstatus;
+
+	return true;
+
+}
+
+static bool BCMFASTPATH
+wlc_bmac_dotxstatus(struct wlc_hw_info *wlc_hw, tx_status_t *txs, u32 s2)
+{
+	/* discard intermediate indications for ucode with one legitimate case:
+	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
+	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
+	 *   transmission count)
+	 */
+	if (!(txs->status & TX_STATUS_AMPDU)
+	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
+		return false;
+	}
+
+	return wlc_dotxstatus(wlc_hw->wlc, txs, s2);
+}
+
+/* process tx completion events in BMAC
+ * Return true if more tx status need to be processed. false otherwise.
+ */
+static bool BCMFASTPATH
+wlc_bmac_txstatus(struct wlc_hw_info *wlc_hw, bool bound, bool *fatal)
+{
+	bool morepending = false;
+	struct wlc_info *wlc = wlc_hw->wlc;
+	d11regs_t *regs;
+	tx_status_t txstatus, *txs;
+	u32 s1, s2;
+	uint n = 0;
+	/*
+	 * Param 'max_tx_num' indicates max. # tx status to process before
+	 * break out.
+	 */
+	uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
+
+	WL_TRACE("wl%d: wlc_bmac_txstatus\n", wlc_hw->unit);
+
+	txs = &txstatus;
+	regs = wlc_hw->regs;
+	while (!(*fatal)
+	       && (s1 = R_REG(&regs->frmtxstatus)) & TXS_V) {
+
+		if (s1 == 0xffffffff) {
+			WL_ERROR("wl%d: %s: dead chip\n",
+				wlc_hw->unit, __func__);
+			ASSERT(s1 != 0xffffffff);
+			return morepending;
+		}
+
+			s2 = R_REG(&regs->frmtxstatus2);
+
+		txs->status = s1 & TXS_STATUS_MASK;
+		txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
+		txs->sequence = s2 & TXS_SEQ_MASK;
+		txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
+		txs->lasttxtime = 0;
+
+		*fatal = wlc_bmac_dotxstatus(wlc_hw, txs, s2);
+
+		/* !give others some time to run! */
+		if (++n >= max_tx_num)
+			break;
+	}
+
+	if (*fatal)
+		return 0;
+
+	if (n >= max_tx_num)
+		morepending = true;
+
+	if (!pktq_empty(&wlc->active_queue->q))
+		wlc_send_q(wlc, wlc->active_queue);
+
+	return morepending;
+}
+
+void wlc_suspend_mac_and_wait(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	u32 mc, mi;
+
+	WL_TRACE("wl%d: wlc_suspend_mac_and_wait: bandunit %d\n",
+		 wlc_hw->unit, wlc_hw->band->bandunit);
+
+	/*
+	 * Track overlapping suspend requests
+	 */
+	wlc_hw->mac_suspend_depth++;
+	if (wlc_hw->mac_suspend_depth > 1)
+		return;
+
+	/* force the core awake */
+	wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
+
+	mc = R_REG(&regs->maccontrol);
+
+	if (mc == 0xffffffff) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
+		wl_down(wlc->wl);
+		return;
+	}
+	ASSERT(!(mc & MCTL_PSM_JMP_0));
+	ASSERT(mc & MCTL_PSM_RUN);
+	ASSERT(mc & MCTL_EN_MAC);
+
+	mi = R_REG(&regs->macintstatus);
+	if (mi == 0xffffffff) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
+		wl_down(wlc->wl);
+		return;
+	}
+	ASSERT(!(mi & MI_MACSSPNDD));
+
+	wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, 0);
+
+	SPINWAIT(!(R_REG(&regs->macintstatus) & MI_MACSSPNDD),
+		 WLC_MAX_MAC_SUSPEND);
+
+	if (!(R_REG(&regs->macintstatus) & MI_MACSSPNDD)) {
+		WL_ERROR("wl%d: wlc_suspend_mac_and_wait: waited %d uS and MI_MACSSPNDD is still not on.\n",
+			 wlc_hw->unit, WLC_MAX_MAC_SUSPEND);
+		WL_ERROR("wl%d: psmdebug 0x%08x, phydebug 0x%08x, psm_brc 0x%04x\n",
+			 wlc_hw->unit,
+			 R_REG(&regs->psmdebug),
+			 R_REG(&regs->phydebug),
+			 R_REG(&regs->psm_brc));
+	}
+
+	mc = R_REG(&regs->maccontrol);
+	if (mc == 0xffffffff) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
+		wl_down(wlc->wl);
+		return;
+	}
+	ASSERT(!(mc & MCTL_PSM_JMP_0));
+	ASSERT(mc & MCTL_PSM_RUN);
+	ASSERT(!(mc & MCTL_EN_MAC));
+}
+
+void wlc_enable_mac(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	d11regs_t *regs = wlc_hw->regs;
+	u32 mc, mi;
+
+	WL_TRACE("wl%d: wlc_enable_mac: bandunit %d\n",
+		 wlc_hw->unit, wlc->band->bandunit);
+
+	/*
+	 * Track overlapping suspend requests
+	 */
+	ASSERT(wlc_hw->mac_suspend_depth > 0);
+	wlc_hw->mac_suspend_depth--;
+	if (wlc_hw->mac_suspend_depth > 0)
+		return;
+
+	mc = R_REG(&regs->maccontrol);
+	ASSERT(!(mc & MCTL_PSM_JMP_0));
+	ASSERT(!(mc & MCTL_EN_MAC));
+	ASSERT(mc & MCTL_PSM_RUN);
+
+	wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
+	W_REG(&regs->macintstatus, MI_MACSSPNDD);
+
+	mc = R_REG(&regs->maccontrol);
+	ASSERT(!(mc & MCTL_PSM_JMP_0));
+	ASSERT(mc & MCTL_EN_MAC);
+	ASSERT(mc & MCTL_PSM_RUN);
+
+	mi = R_REG(&regs->macintstatus);
+	ASSERT(!(mi & MI_MACSSPNDD));
+
+	wlc_ucode_wake_override_clear(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
+}
+
+static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw)
+{
+	u8 rate;
+	u8 rates[8] = {
+		WLC_RATE_6M, WLC_RATE_9M, WLC_RATE_12M, WLC_RATE_18M,
+		WLC_RATE_24M, WLC_RATE_36M, WLC_RATE_48M, WLC_RATE_54M
+	};
+	u16 entry_ptr;
+	u16 pctl1;
+	uint i;
+
+	if (!WLC_PHY_11N_CAP(wlc_hw->band))
+		return;
+
+	/* walk the phy rate table and update the entries */
+	for (i = 0; i < ARRAY_SIZE(rates); i++) {
+		rate = rates[i];
+
+		entry_ptr = wlc_bmac_ofdm_ratetable_offset(wlc_hw, rate);
+
+		/* read the SHM Rate Table entry OFDM PCTL1 values */
+		pctl1 =
+		    wlc_bmac_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
+
+		/* modify the value */
+		pctl1 &= ~PHY_TXC1_MODE_MASK;
+		pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
+
+		/* Update the SHM Rate Table entry OFDM PCTL1 values */
+		wlc_bmac_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
+				   pctl1);
+	}
+}
+
+static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw, u8 rate)
+{
+	uint i;
+	u8 plcp_rate = 0;
+	struct plcp_signal_rate_lookup {
+		u8 rate;
+		u8 signal_rate;
+	};
+	/* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
+	const struct plcp_signal_rate_lookup rate_lookup[] = {
+		{WLC_RATE_6M, 0xB},
+		{WLC_RATE_9M, 0xF},
+		{WLC_RATE_12M, 0xA},
+		{WLC_RATE_18M, 0xE},
+		{WLC_RATE_24M, 0x9},
+		{WLC_RATE_36M, 0xD},
+		{WLC_RATE_48M, 0x8},
+		{WLC_RATE_54M, 0xC}
+	};
+
+	for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
+		if (rate == rate_lookup[i].rate) {
+			plcp_rate = rate_lookup[i].signal_rate;
+			break;
+		}
+	}
+
+	/* Find the SHM pointer to the rate table entry by looking in the
+	 * Direct-map Table
+	 */
+	return 2 * wlc_bmac_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
+}
+
+void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode)
+{
+	wlc_hw->hw_stf_ss_opmode = stf_mode;
+
+	if (wlc_hw->clk)
+		wlc_upd_ofdm_pctl1_table(wlc_hw);
+}
+
+void BCMFASTPATH
+wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
+		  u32 *tsf_h_ptr)
+{
+	d11regs_t *regs = wlc_hw->regs;
+
+	/* read the tsf timer low, then high to get an atomic read */
+	*tsf_l_ptr = R_REG(&regs->tsf_timerlow);
+	*tsf_h_ptr = R_REG(&regs->tsf_timerhigh);
+
+	return;
+}
+
+static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw)
+{
+	d11regs_t *regs;
+	u32 w, val;
+
+	WL_TRACE("wl%d: validate_chip_access\n", wlc_hw->unit);
+
+	regs = wlc_hw->regs;
+
+	/* Validate dchip register access */
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	w = R_REG(&regs->objdata);
+
+	/* Can we write and read back a 32bit register? */
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, (u32) 0xaa5555aa);
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	val = R_REG(&regs->objdata);
+	if (val != (u32) 0xaa5555aa) {
+		WL_ERROR("wl%d: validate_chip_access: SHM = 0x%x, expected 0xaa5555aa\n",
+			 wlc_hw->unit, val);
+		return false;
+	}
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, (u32) 0x55aaaa55);
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	val = R_REG(&regs->objdata);
+	if (val != (u32) 0x55aaaa55) {
+		WL_ERROR("wl%d: validate_chip_access: SHM = 0x%x, expected 0x55aaaa55\n",
+			 wlc_hw->unit, val);
+		return false;
+	}
+
+	W_REG(&regs->objaddr, OBJADDR_SHM_SEL | 0);
+	(void)R_REG(&regs->objaddr);
+	W_REG(&regs->objdata, w);
+
+	/* clear CFPStart */
+	W_REG(&regs->tsf_cfpstart, 0);
+
+	w = R_REG(&regs->maccontrol);
+	if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
+	    (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
+		WL_ERROR("wl%d: validate_chip_access: maccontrol = 0x%x, expected 0x%x or 0x%x\n",
+			 wlc_hw->unit, w,
+			 (MCTL_IHR_EN | MCTL_WAKE),
+			 (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
+		return false;
+	}
+
+	return true;
+}
+
+#define PHYPLL_WAIT_US	100000
+
+void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on)
+{
+	d11regs_t *regs;
+	u32 tmp;
+
+	WL_TRACE("wl%d: wlc_bmac_core_phypll_ctl\n", wlc_hw->unit);
+
+	tmp = 0;
+	regs = wlc_hw->regs;
+
+	if (on) {
+		if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
+			OR_REG(&regs->clk_ctl_st,
+			       (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
+				CCS_ERSRC_REQ_PHYPLL));
+			SPINWAIT((R_REG(&regs->clk_ctl_st) &
+				  (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
+				 PHYPLL_WAIT_US);
+
+			tmp = R_REG(&regs->clk_ctl_st);
+			if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
+			    (CCS_ERSRC_AVAIL_HT)) {
+				WL_ERROR("%s: turn on PHY PLL failed\n",
+					 __func__);
+				ASSERT(0);
+			}
+		} else {
+			OR_REG(&regs->clk_ctl_st,
+			       (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
+			SPINWAIT((R_REG(&regs->clk_ctl_st) &
+				  (CCS_ERSRC_AVAIL_D11PLL |
+				   CCS_ERSRC_AVAIL_PHYPLL)) !=
+				 (CCS_ERSRC_AVAIL_D11PLL |
+				  CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
+
+			tmp = R_REG(&regs->clk_ctl_st);
+			if ((tmp &
+			     (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
+			    !=
+			    (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) {
+				WL_ERROR("%s: turn on PHY PLL failed\n",
+					 __func__);
+				ASSERT(0);
+			}
+		}
+	} else {
+		/* Since the PLL may be shared, other cores can still be requesting it;
+		 * so we'll deassert the request but not wait for status to comply.
+		 */
+		AND_REG(&regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
+		tmp = R_REG(&regs->clk_ctl_st);
+	}
+}
+
+void wlc_coredisable(struct wlc_hw_info *wlc_hw)
+{
+	bool dev_gone;
+
+	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
+
+	ASSERT(!wlc_hw->up);
+
+	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
+
+	if (dev_gone)
+		return;
+
+	if (wlc_hw->noreset)
+		return;
+
+	/* radio off */
+	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
+
+	/* turn off analog core */
+	wlc_phy_anacore(wlc_hw->band->pi, OFF);
+
+	/* turn off PHYPLL to save power */
+	wlc_bmac_core_phypll_ctl(wlc_hw, false);
+
+	/* No need to set wlc->pub->radio_active = OFF
+	 * because this function needs down capability and
+	 * radio_active is designed for BCMNODOWN.
+	 */
+
+	/* remove gpio controls */
+	if (wlc_hw->ucode_dbgsel)
+		si_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
+
+	wlc_hw->clk = false;
+	si_core_disable(wlc_hw->sih, 0);
+	wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+}
+
+/* power both the pll and external oscillator on/off */
+static void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want)
+{
+	WL_TRACE("wl%d: wlc_bmac_xtal: want %d\n", wlc_hw->unit, want);
+
+	/* dont power down if plldown is false or we must poll hw radio disable */
+	if (!want && wlc_hw->pllreq)
+		return;
+
+	if (wlc_hw->sih)
+		si_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
+
+	wlc_hw->sbclk = want;
+	if (!wlc_hw->sbclk) {
+		wlc_hw->clk = false;
+		if (wlc_hw->band && wlc_hw->band->pi)
+			wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
+	}
+}
+
+static void wlc_flushqueues(struct wlc_info *wlc)
+{
+	struct wlc_hw_info *wlc_hw = wlc->hw;
+	uint i;
+
+	wlc->txpend16165war = 0;
+
+	/* free any posted tx packets */
+	for (i = 0; i < NFIFO; i++)
+		if (wlc_hw->di[i]) {
+			dma_txreclaim(wlc_hw->di[i], HNDDMA_RANGE_ALL);
+			TXPKTPENDCLR(wlc, i);
+			WL_TRACE("wlc_flushqueues: pktpend fifo %d cleared\n",
+				 i);
+		}
+
+	/* free any posted rx packets */
+	dma_rxreclaim(wlc_hw->di[RX_FIFO]);
+}
+
+u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset)
+{
+	return wlc_bmac_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
+}
+
+void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v)
+{
+	wlc_bmac_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
+}
+
+/* Set a range of shared memory to a value.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+void wlc_bmac_set_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v, int len)
+{
+	int i;
+
+	/* offset and len need to be even */
+	ASSERT((offset & 1) == 0);
+	ASSERT((len & 1) == 0);
+
+	if (len <= 0)
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		wlc_bmac_write_objmem(wlc_hw, offset + i, v, OBJADDR_SHM_SEL);
+	}
+}
+
+static u16
+wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset, u32 sel)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
+	volatile u16 *objdata_hi = objdata_lo + 1;
+	u16 v;
+
+	ASSERT((offset & 1) == 0);
+
+	W_REG(&regs->objaddr, sel | (offset >> 2));
+	(void)R_REG(&regs->objaddr);
+	if (offset & 2) {
+		v = R_REG(objdata_hi);
+	} else {
+		v = R_REG(objdata_lo);
+	}
+
+	return v;
+}
+
+static void
+wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset, u16 v, u32 sel)
+{
+	d11regs_t *regs = wlc_hw->regs;
+	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
+	volatile u16 *objdata_hi = objdata_lo + 1;
+
+	ASSERT((offset & 1) == 0);
+
+	W_REG(&regs->objaddr, sel | (offset >> 2));
+	(void)R_REG(&regs->objaddr);
+	if (offset & 2) {
+		W_REG(objdata_hi, v);
+	} else {
+		W_REG(objdata_lo, v);
+	}
+}
+
+/* Copy a buffer to shared memory of specified type .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw, uint offset, const void *buf,
+		       int len, u32 sel)
+{
+	u16 v;
+	const u8 *p = (const u8 *)buf;
+	int i;
+
+	/* offset and len need to be even */
+	ASSERT((offset & 1) == 0);
+	ASSERT((len & 1) == 0);
+
+	if (len <= 0)
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		v = p[i] | (p[i + 1] << 8);
+		wlc_bmac_write_objmem(wlc_hw, offset + i, v, sel);
+	}
+}
+
+/* Copy a piece of shared memory of specified type to a buffer .
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ * 'sel' selects the type of memory
+ */
+void
+wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset, void *buf,
+			 int len, u32 sel)
+{
+	u16 v;
+	u8 *p = (u8 *) buf;
+	int i;
+
+	/* offset and len need to be even */
+	ASSERT((offset & 1) == 0);
+	ASSERT((len & 1) == 0);
+
+	if (len <= 0)
+		return;
+
+	for (i = 0; i < len; i += 2) {
+		v = wlc_bmac_read_objmem(wlc_hw, offset + i, sel);
+		p[i] = v & 0xFF;
+		p[i + 1] = (v >> 8) & 0xFF;
+	}
+}
+
+void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf, uint *len)
+{
+	WL_TRACE("wlc_bmac_copyfrom_vars, nvram vars totlen=%d\n",
+		 wlc_hw->vars_size);
+
+	*buf = wlc_hw->vars;
+	*len = wlc_hw->vars_size;
+}
+
+void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL, u16 LRL)
+{
+	wlc_hw->SRL = SRL;
+	wlc_hw->LRL = LRL;
+
+	/* write retry limit to SCR, shouldn't need to suspend */
+	if (wlc_hw->up) {
+		W_REG(&wlc_hw->regs->objaddr,
+		      OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
+		(void)R_REG(&wlc_hw->regs->objaddr);
+		W_REG(&wlc_hw->regs->objdata, wlc_hw->SRL);
+		W_REG(&wlc_hw->regs->objaddr,
+		      OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
+		(void)R_REG(&wlc_hw->regs->objaddr);
+		W_REG(&wlc_hw->regs->objdata, wlc_hw->LRL);
+	}
+}
+
+void wlc_bmac_set_noreset(struct wlc_hw_info *wlc_hw, bool noreset_flag)
+{
+	wlc_hw->noreset = noreset_flag;
+}
+
+void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set, mbool req_bit)
+{
+	ASSERT(req_bit);
+
+	if (set) {
+		if (mboolisset(wlc_hw->pllreq, req_bit))
+			return;
+
+		mboolset(wlc_hw->pllreq, req_bit);
+
+		if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
+			if (!wlc_hw->sbclk) {
+				wlc_bmac_xtal(wlc_hw, ON);
+			}
+		}
+	} else {
+		if (!mboolisset(wlc_hw->pllreq, req_bit))
+			return;
+
+		mboolclr(wlc_hw->pllreq, req_bit);
+
+		if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
+			if (wlc_hw->sbclk) {
+				wlc_bmac_xtal(wlc_hw, OFF);
+			}
+		}
+	}
+
+	return;
+}
+
+/* this will be true for all ai chips */
+bool wlc_bmac_taclear(struct wlc_hw_info *wlc_hw, bool ta_ok)
+{
+	return true;
+}
+
+u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate)
+{
+	u16 table_ptr;
+	u8 phy_rate, index;
+
+	/* get the phy specific rate encoding for the PLCP SIGNAL field */
+	/* XXX4321 fixup needed ? */
+	if (IS_OFDM(rate))
+		table_ptr = M_RT_DIRMAP_A;
+	else
+		table_ptr = M_RT_DIRMAP_B;
+
+	/* for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & RATE_MASK;
+	index = phy_rate & 0xf;
+
+	/* Find the SHM pointer to the rate table entry by looking in the
+	 * Direct-map Table
+	 */
+	return 2 * wlc_bmac_read_shm(wlc_hw, table_ptr + (index * 2));
+}
+
+void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail)
+{
+	wlc_hw->antsel_avail = antsel_avail;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
new file mode 100644
index 0000000..9c2c658
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef _wlc_bmac_h_
+#define _wlc_bmac_h_
+
+/* XXXXX this interface is under wlc.c by design
+ * http://hwnbu-twiki.broadcom.com/bin/view/Mwgroup/WlBmacDesign
+ *
+ *        high driver files(e.g. wlc_ampdu.c etc)
+ *             wlc.h/wlc.c
+ *         wlc_bmac.h/wlc_bmac.c
+ *
+ *  So don't include this in files other than wlc.c, wlc_bmac* wl_rte.c(dongle port) and wl_phy.c
+ *  create wrappers in wlc.c if needed
+ */
+
+/* dup state between BMAC(struct wlc_hw_info) and HIGH(struct wlc_info)
+   driver */
+typedef struct wlc_bmac_state {
+	u32 machwcap;	/* mac hw capibility */
+	u32 preamble_ovr;	/* preamble override */
+} wlc_bmac_state_t;
+
+enum {
+	IOV_BMAC_DIAG,
+	IOV_BMAC_SBGPIOTIMERVAL,
+	IOV_BMAC_SBGPIOOUT,
+	IOV_BMAC_CCGPIOCTRL,	/* CC GPIOCTRL REG */
+	IOV_BMAC_CCGPIOOUT,	/* CC GPIOOUT REG */
+	IOV_BMAC_CCGPIOOUTEN,	/* CC GPIOOUTEN REG */
+	IOV_BMAC_CCGPIOIN,	/* CC GPIOIN REG */
+	IOV_BMAC_WPSGPIO,	/* WPS push button GPIO pin */
+	IOV_BMAC_OTPDUMP,
+	IOV_BMAC_OTPSTAT,
+	IOV_BMAC_PCIEASPM,	/* obfuscation clkreq/aspm control */
+	IOV_BMAC_PCIEADVCORRMASK,	/* advanced correctable error mask */
+	IOV_BMAC_PCIECLKREQ,	/* PCIE 1.1 clockreq enab support */
+	IOV_BMAC_PCIELCREG,	/* PCIE LCREG */
+	IOV_BMAC_SBGPIOTIMERMASK,
+	IOV_BMAC_RFDISABLEDLY,
+	IOV_BMAC_PCIEREG,	/* PCIE REG */
+	IOV_BMAC_PCICFGREG,	/* PCI Config register */
+	IOV_BMAC_PCIESERDESREG,	/* PCIE SERDES REG (dev, 0}offset) */
+	IOV_BMAC_PCIEGPIOOUT,	/* PCIEOUT REG */
+	IOV_BMAC_PCIEGPIOOUTEN,	/* PCIEOUTEN REG */
+	IOV_BMAC_PCIECLKREQENCTRL,	/* clkreqenctrl REG (PCIE REV > 6.0 */
+	IOV_BMAC_DMALPBK,
+	IOV_BMAC_CCREG,
+	IOV_BMAC_COREREG,
+	IOV_BMAC_SDCIS,
+	IOV_BMAC_SDIO_DRIVE,
+	IOV_BMAC_OTPW,
+	IOV_BMAC_NVOTPW,
+	IOV_BMAC_SROM,
+	IOV_BMAC_SRCRC,
+	IOV_BMAC_CIS_SOURCE,
+	IOV_BMAC_CISVAR,
+	IOV_BMAC_OTPLOCK,
+	IOV_BMAC_OTP_CHIPID,
+	IOV_BMAC_CUSTOMVAR1,
+	IOV_BMAC_BOARDFLAGS,
+	IOV_BMAC_BOARDFLAGS2,
+	IOV_BMAC_WPSLED,
+	IOV_BMAC_NVRAM_SOURCE,
+	IOV_BMAC_OTP_RAW_READ,
+	IOV_BMAC_LAST
+};
+
+extern int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device,
+			   uint unit, bool piomode, void *regsva, uint bustype,
+			   void *btparam);
+extern int wlc_bmac_detach(struct wlc_info *wlc);
+extern void wlc_bmac_watchdog(void *arg);
+
+/* up/down, reset, clk */
+extern void wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw,
+				   uint offset, const void *buf, int len,
+				   u32 sel);
+extern void wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset,
+				     void *buf, int len, u32 sel);
+#define wlc_bmac_copyfrom_shm(wlc_hw, offset, buf, len)                 \
+	wlc_bmac_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
+#define wlc_bmac_copyto_shm(wlc_hw, offset, buf, len)                   \
+	wlc_bmac_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
+
+extern void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on);
+extern void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk);
+extern void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk);
+extern void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags);
+extern void wlc_bmac_reset(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
+			  bool mute);
+extern int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw);
+extern int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw);
+extern int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw);
+extern int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode);
+
+/* chanspec, ucode interface */
+extern void wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw,
+				  chanspec_t chanspec,
+				  bool mute, struct txpwr_limits *txpwr);
+
+extern int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo,
+				   uint *blocks);
+extern void wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask,
+			 u16 val, int bands);
+extern void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val);
+extern u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands);
+extern void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant);
+extern u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw,
+				     u8 antsel_type);
+extern int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw,
+			      wlc_bmac_state_t *state);
+extern void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v);
+extern u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset);
+extern void wlc_bmac_set_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v,
+			     int len);
+extern void wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset,
+					int len, void *buf);
+extern void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf,
+				   uint *len);
+
+extern void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw,
+				  u8 *ea);
+
+extern bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot);
+extern void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode);
+
+extern void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw);
+
+extern void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw,
+					u32 override_bit);
+extern void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw,
+					  u32 override_bit);
+
+extern void wlc_bmac_set_rcmta(struct wlc_hw_info *wlc_hw, int idx,
+			       const u8 *addr);
+extern void wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw,
+				   int match_reg_offset,
+				   const u8 *addr);
+extern void wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw,
+					   void *bcn, int len, bool both);
+
+extern void wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
+			      u32 *tsf_h_ptr);
+extern void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin);
+extern void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax);
+extern void wlc_bmac_set_noreset(struct wlc_hw_info *wlc, bool noreset_flag);
+
+extern void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL,
+				    u16 LRL);
+
+extern void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw);
+
+
+/* API for BMAC driver (e.g. wlc_phy.c etc) */
+
+extern void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw);
+extern void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set,
+			    mbool req_bit);
+extern bool wlc_bmac_taclear(struct wlc_hw_info *wlc_hw, bool ta_ok);
+extern void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw);
+extern u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate);
+extern void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail);
+
+#endif /* _wlc_bmac_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h b/drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h
new file mode 100644
index 0000000..bbcff4f
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_bsscfg.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLC_BSSCFG_H_
+#define _WLC_BSSCFG_H_
+
+/* Check if a particular BSS config is AP or STA */
+#define BSSCFG_AP(cfg)		(0)
+#define BSSCFG_STA(cfg)		(1)
+
+#define BSSCFG_IBSS(cfg)	(!(cfg)->BSS)
+
+#define NTXRATE			64	/* # tx MPDUs rate is reported for */
+#define MAXMACLIST		64	/* max # source MAC matches */
+#define BCN_TEMPLATE_COUNT 	2
+
+/* Iterator for "associated" STA bss configs:
+   (struct wlc_info *wlc, int idx, struct wlc_bsscfg *cfg) */
+#define FOREACH_AS_STA(wlc, idx, cfg) \
+	for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) \
+		if ((cfg = (wlc)->bsscfg[idx]) && BSSCFG_STA(cfg) && cfg->associated)
+
+/* As above for all non-NULL BSS configs */
+#define FOREACH_BSS(wlc, idx, cfg) \
+	for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) \
+		if ((cfg = (wlc)->bsscfg[idx]))
+
+/* BSS configuration state */
+struct wlc_bsscfg {
+	struct wlc_info *wlc;	/* wlc to which this bsscfg belongs to. */
+	bool up;		/* is this configuration up operational */
+	bool enable;		/* is this configuration enabled */
+	bool associated;	/* is BSS in ASSOCIATED state */
+	bool BSS;		/* infraustructure or adhac */
+	bool dtim_programmed;
+
+	u8 SSID_len;		/* the length of SSID */
+	u8 SSID[IEEE80211_MAX_SSID_LEN]; /* SSID string */
+	struct scb *bcmc_scb[MAXBANDS];	/* one bcmc_scb per band */
+	s8 _idx;		/* the index of this bsscfg,
+				 * assigned at wlc_bsscfg_alloc()
+				 */
+	/* MAC filter */
+	uint nmac;		/* # of entries on maclist array */
+	int macmode;		/* allow/deny stations on maclist array */
+	struct ether_addr *maclist;	/* list of source MAC addrs to match */
+
+	/* security */
+	u32 wsec;		/* wireless security bitvec */
+	s16 auth;		/* 802.11 authentication: Open, Shared Key, WPA */
+	s16 openshared;	/* try Open auth first, then Shared Key */
+	bool wsec_restrict;	/* drop unencrypted packets if wsec is enabled */
+	bool eap_restrict;	/* restrict data until 802.1X auth succeeds */
+	u16 WPA_auth;	/* WPA: authenticated key management */
+	bool wpa2_preauth;	/* default is true, wpa_cap sets value */
+	bool wsec_portopen;	/* indicates keys are plumbed */
+	wsec_iv_t wpa_none_txiv;	/* global txiv for WPA_NONE, tkip and aes */
+	int wsec_index;		/* 0-3: default tx key, -1: not set */
+	wsec_key_t *bss_def_keys[WLC_DEFAULT_KEYS];	/* default key storage */
+
+	/* TKIP countermeasures */
+	bool tkip_countermeasures;	/* flags TKIP no-assoc period */
+	u32 tk_cm_dt;	/* detect timer */
+	u32 tk_cm_bt;	/* blocking timer */
+	u32 tk_cm_bt_tmstmp;	/* Timestamp when TKIP BT is activated */
+	bool tk_cm_activate;	/* activate countermeasures after EAPOL-Key sent */
+
+	u8 BSSID[ETH_ALEN];	/* BSSID (associated) */
+	u8 cur_etheraddr[ETH_ALEN];	/* h/w address */
+	u16 bcmc_fid;	/* the last BCMC FID queued to TX_BCMC_FIFO */
+	u16 bcmc_fid_shm;	/* the last BCMC FID written to shared mem */
+
+	u32 flags;		/* WLC_BSSCFG flags; see below */
+
+	u8 *bcn;		/* AP beacon */
+	uint bcn_len;		/* AP beacon length */
+	bool ar_disassoc;	/* disassociated in associated recreation */
+
+	int auth_atmptd;	/* auth type (open/shared) attempted */
+
+	pmkid_cand_t pmkid_cand[MAXPMKID];	/* PMKID candidate list */
+	uint npmkid_cand;	/* num PMKID candidates */
+	pmkid_t pmkid[MAXPMKID];	/* PMKID cache */
+	uint npmkid;		/* num cached PMKIDs */
+
+	wlc_bss_info_t *current_bss;	/* BSS parms in ASSOCIATED state */
+
+	/* PM states */
+	bool PMawakebcn;	/* bcn recvd during current waking state */
+	bool PMpending;		/* waiting for tx status with PM indicated set */
+	bool priorPMstate;	/* Detecting PM state transitions */
+	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
+
+	/* BSSID entry in RCMTA, use the wsec key management infrastructure to
+	 * manage the RCMTA entries.
+	 */
+	wsec_key_t *rcmta;
+
+	/* 'unique' ID of this bsscfg, assigned at bsscfg allocation */
+	u16 ID;
+
+	uint txrspecidx;	/* index into tx rate circular buffer */
+	ratespec_t txrspec[NTXRATE][2];	/* circular buffer of prev MPDUs tx rates */
+};
+
+#define WLC_BSSCFG_11N_DISABLE	0x1000	/* Do not advertise .11n IEs for this BSS */
+#define WLC_BSSCFG_HW_BCN	0x20	/* The BSS is generating beacons in HW */
+
+#define HWBCN_ENAB(cfg)		(((cfg)->flags & WLC_BSSCFG_HW_BCN) != 0)
+#define HWPRB_ENAB(cfg)		(((cfg)->flags & WLC_BSSCFG_HW_PRB) != 0)
+
+extern void wlc_bsscfg_ID_assign(struct wlc_info *wlc,
+				 struct wlc_bsscfg *bsscfg);
+
+/* Extend N_ENAB to per-BSS */
+#define BSS_N_ENAB(wlc, cfg) \
+	(N_ENAB((wlc)->pub) && !((cfg)->flags & WLC_BSSCFG_11N_DISABLE))
+
+#define MBSS_BCN_ENAB(cfg)       0
+#define MBSS_PRB_ENAB(cfg)       0
+#define SOFTBCN_ENAB(pub)    (0)
+#define SOFTPRB_ENAB(pub)    (0)
+#define wlc_bsscfg_tx_check(a) do { } while (0);
+
+#endif				/* _WLC_BSSCFG_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_cfg.h b/drivers/staging/brcm80211/brcmsmac/wlc_cfg.h
new file mode 100644
index 0000000..85fbd06
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_cfg.h
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_cfg_h_
+#define _wlc_cfg_h_
+
+#define NBANDS(wlc) ((wlc)->pub->_nbands)
+#define NBANDS_PUB(pub) ((pub)->_nbands)
+#define NBANDS_HW(hw) ((hw)->_nbands)
+
+#define IS_SINGLEBAND_5G(device)	0
+
+/* **** Core type/rev defaults **** */
+#define D11_DEFAULT	0x0fffffb0	/* Supported  D11 revs: 4, 5, 7-27
+					 * also need to update wlc.h MAXCOREREV
+					 */
+
+#define NPHY_DEFAULT	0x000001ff	/* Supported nphy revs:
+					 *      0       4321a0
+					 *      1       4321a1
+					 *      2       4321b0/b1/c0/c1
+					 *      3       4322a0
+					 *      4       4322a1
+					 *      5       4716a0
+					 *      6       43222a0, 43224a0
+					 *      7       43226a0
+					 *      8       5357a0, 43236a0
+					 */
+
+#define LCNPHY_DEFAULT	0x00000007	/* Supported lcnphy revs:
+					 *      0       4313a0, 4336a0, 4330a0
+					 *      1
+					 *      2       4330a0
+					 */
+
+#define SSLPNPHY_DEFAULT 0x0000000f	/* Supported sslpnphy revs:
+					 *      0       4329a0/k0
+					 *      1       4329b0/4329C0
+					 *      2       4319a0
+					 *      3       5356a0
+					 */
+
+
+/* For undefined values, use defaults */
+#ifndef D11CONF
+#define D11CONF	D11_DEFAULT
+#endif
+#ifndef NCONF
+#define NCONF	NPHY_DEFAULT
+#endif
+#ifndef LCNCONF
+#define LCNCONF	LCNPHY_DEFAULT
+#endif
+
+#ifndef SSLPNCONF
+#define SSLPNCONF	SSLPNPHY_DEFAULT
+#endif
+
+/********************************************************************
+ * Phy/Core Configuration.  Defines macros to to check core phy/rev *
+ * compile-time configuration.  Defines default core support.       *
+ * ******************************************************************
+ */
+
+/* Basic macros to check a configuration bitmask */
+
+#define CONF_HAS(config, val)	((config) & (1 << (val)))
+#define CONF_MSK(config, mask)	((config) & (mask))
+#define MSK_RANGE(low, hi)	((1 << ((hi)+1)) - (1 << (low)))
+#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
+
+#define CONF_IS(config, val)	((config) == (1 << (val)))
+#define CONF_GE(config, val)	((config) & (0-(1 << (val))))
+#define CONF_GT(config, val)	((config) & (0-2*(1 << (val))))
+#define CONF_LT(config, val)	((config) & ((1 << (val))-1))
+#define CONF_LE(config, val)	((config) & (2*(1 << (val))-1))
+
+/* Wrappers for some of the above, specific to config constants */
+
+#define NCONF_HAS(val)	CONF_HAS(NCONF, val)
+#define NCONF_MSK(mask)	CONF_MSK(NCONF, mask)
+#define NCONF_IS(val)	CONF_IS(NCONF, val)
+#define NCONF_GE(val)	CONF_GE(NCONF, val)
+#define NCONF_GT(val)	CONF_GT(NCONF, val)
+#define NCONF_LT(val)	CONF_LT(NCONF, val)
+#define NCONF_LE(val)	CONF_LE(NCONF, val)
+
+#define LCNCONF_HAS(val)	CONF_HAS(LCNCONF, val)
+#define LCNCONF_MSK(mask)	CONF_MSK(LCNCONF, mask)
+#define LCNCONF_IS(val)		CONF_IS(LCNCONF, val)
+#define LCNCONF_GE(val)		CONF_GE(LCNCONF, val)
+#define LCNCONF_GT(val)		CONF_GT(LCNCONF, val)
+#define LCNCONF_LT(val)		CONF_LT(LCNCONF, val)
+#define LCNCONF_LE(val)		CONF_LE(LCNCONF, val)
+
+#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
+#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
+#define D11CONF_IS(val)	CONF_IS(D11CONF, val)
+#define D11CONF_GE(val)	CONF_GE(D11CONF, val)
+#define D11CONF_GT(val)	CONF_GT(D11CONF, val)
+#define D11CONF_LT(val)	CONF_LT(D11CONF, val)
+#define D11CONF_LE(val)	CONF_LE(D11CONF, val)
+
+#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
+#define PHYCONF_IS(val)	CONF_IS(PHYTYPE, val)
+
+#define NREV_IS(var, val)	(NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
+#define NREV_GE(var, val)	(NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
+#define NREV_GT(var, val)	(NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
+#define NREV_LT(var, val)	(NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
+#define NREV_LE(var, val)	(NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
+
+#define LCNREV_IS(var, val)	(LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
+#define LCNREV_GE(var, val)	(LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
+#define LCNREV_GT(var, val)	(LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
+#define LCNREV_LT(var, val)	(LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
+#define LCNREV_LE(var, val)	(LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
+
+#define D11REV_IS(var, val)	(D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
+#define D11REV_GE(var, val)	(D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
+#define D11REV_GT(var, val)	(D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
+#define D11REV_LT(var, val)	(D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
+#define D11REV_LE(var, val)	(D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
+
+#define PHYTYPE_IS(var, val)	(PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
+
+/* Finally, early-exit from switch case if anyone wants it... */
+
+#define CASECHECK(config, val)	if (!(CONF_HAS(config, val))) break
+#define CASEMSK(config, mask)	if (!(CONF_MSK(config, mask))) break
+
+#if (D11CONF ^ (D11CONF & D11_DEFAULT))
+#error "Unsupported MAC revision configured"
+#endif
+#if (NCONF ^ (NCONF & NPHY_DEFAULT))
+#error "Unsupported NPHY revision configured"
+#endif
+#if (LCNCONF ^ (LCNCONF & LCNPHY_DEFAULT))
+#error "Unsupported LPPHY revision configured"
+#endif
+
+/* *** Consistency checks *** */
+#if !D11CONF
+#error "No MAC revisions configured!"
+#endif
+
+#if !NCONF && !LCNCONF && !SSLPNCONF
+#error "No PHY configured!"
+#endif
+
+/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
+
+#define _PHYCONF_N (1 << PHY_TYPE_N)
+
+#if LCNCONF
+#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
+#else
+#define _PHYCONF_LCN 0
+#endif				/* LCNCONF */
+
+#if SSLPNCONF
+#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
+#else
+#define _PHYCONF_SSLPN 0
+#endif				/* SSLPNCONF */
+
+#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
+
+/* Utility macro to identify 802.11n (HT) capable PHYs */
+#define PHYTYPE_11N_CAP(phytype) \
+	(PHYTYPE_IS(phytype, PHY_TYPE_N) ||	\
+	 PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
+	 PHYTYPE_IS(phytype, PHY_TYPE_SSN))
+
+/* Last but not least: shorter wlc-specific var checks */
+#define WLCISNPHY(band)		PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
+#define WLCISLCNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
+#define WLCISSSLPNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
+
+#define WLC_PHY_11N_CAP(band)	PHYTYPE_11N_CAP((band)->phytype)
+
+/**********************************************************************
+ * ------------- End of Core phy/rev configuration. ----------------- *
+ * ********************************************************************
+ */
+
+/*************************************************
+ * Defaults for tunables (e.g. sizing constants)
+ *
+ * For each new tunable, add a member to the end
+ * of wlc_tunables_t in wlc_pub.h to enable
+ * runtime checks of tunable values. (Directly
+ * using the macros in code invalidates ROM code)
+ *
+ * ***********************************************
+ */
+#ifndef NTXD
+#define NTXD		256	/* Max # of entries in Tx FIFO based on 4kb page size */
+#endif				/* NTXD */
+#ifndef NRXD
+#define NRXD		256	/* Max # of entries in Rx FIFO based on 4kb page size */
+#endif				/* NRXD */
+
+#ifndef NRXBUFPOST
+#define	NRXBUFPOST	32	/* try to keep this # rbufs posted to the chip */
+#endif				/* NRXBUFPOST */
+
+#ifndef MAXSCB			/* station control blocks in cache */
+#define MAXSCB		32	/* Maximum SCBs in cache for STA */
+#endif				/* MAXSCB */
+
+#ifndef AMPDU_NUM_MPDU
+#define AMPDU_NUM_MPDU		16	/* max allowed number of mpdus in an ampdu (2 streams) */
+#endif				/* AMPDU_NUM_MPDU */
+
+#ifndef AMPDU_NUM_MPDU_3STREAMS
+#define AMPDU_NUM_MPDU_3STREAMS	32	/* max allowed number of mpdus in an ampdu for 3+ streams */
+#endif				/* AMPDU_NUM_MPDU_3STREAMS */
+
+/* Count of packet callback structures. either of following
+ * 1. Set to the number of SCBs since a STA
+ * can queue up a rate callback for each IBSS STA it knows about, and an AP can
+ * queue up an "are you there?" Null Data callback for each associated STA
+ * 2. controlled by tunable config file
+ */
+#ifndef MAXPKTCB
+#define MAXPKTCB	MAXSCB	/* Max number of packet callbacks */
+#endif				/* MAXPKTCB */
+
+#ifndef CTFPOOLSZ
+#define CTFPOOLSZ       128
+#endif				/* CTFPOOLSZ */
+
+/* NetBSD also needs to keep track of this */
+#define WLC_MAX_UCODE_BSS	(16)	/* Number of BSS handled in ucode bcn/prb */
+#define WLC_MAX_UCODE_BSS4	(4)	/* Number of BSS handled in sw bcn/prb */
+#ifndef WLC_MAXBSSCFG
+#define WLC_MAXBSSCFG		(1)	/* max # BSS configs */
+#endif				/* WLC_MAXBSSCFG */
+
+#ifndef MAXBSS
+#define MAXBSS		64	/* max # available networks */
+#endif				/* MAXBSS */
+
+#ifndef WLC_DATAHIWAT
+#define WLC_DATAHIWAT		50	/* data msg txq hiwat mark */
+#endif				/* WLC_DATAHIWAT */
+
+#ifndef WLC_AMPDUDATAHIWAT
+#define WLC_AMPDUDATAHIWAT 255
+#endif				/* WLC_AMPDUDATAHIWAT */
+
+/* bounded rx loops */
+#ifndef RXBND
+#define RXBND		8	/* max # frames to process in wlc_recv() */
+#endif				/* RXBND */
+#ifndef TXSBND
+#define TXSBND		8	/* max # tx status to process in wlc_txstatus() */
+#endif				/* TXSBND */
+
+#define BAND_5G(bt)	((bt) == WLC_BAND_5G)
+#define BAND_2G(bt)	((bt) == WLC_BAND_2G)
+
+#define WLBANDINITDATA(_data)	_data
+#define WLBANDINITFN(_fn)	_fn
+
+#endif				/* _wlc_cfg_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_channel.c b/drivers/staging/brcm80211/brcmsmac/wlc_channel.c
new file mode 100644
index 0000000..96161c0
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_channel.c
@@ -0,0 +1,1582 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <sbhnddma.h>
+#include <wlioctl.h>
+
+#include "wlc_types.h"
+#include "d11.h"
+#include "wlc_cfg.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_key.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_bmac.h"
+#include "wlc_rate.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+#include "wlc_stf.h"
+#include "wl_dbg.h"
+
+#define	VALID_CHANNEL20_DB(wlc, val) wlc_valid_channel20_db((wlc)->cmi, val)
+#define	VALID_CHANNEL20_IN_BAND(wlc, bandunit, val) \
+	wlc_valid_channel20_in_band((wlc)->cmi, bandunit, val)
+#define	VALID_CHANNEL20(wlc, val) wlc_valid_channel20((wlc)->cmi, val)
+
+typedef struct wlc_cm_band {
+	u8 locale_flags;	/* locale_info_t flags */
+	chanvec_t valid_channels;	/* List of valid channels in the country */
+	const chanvec_t *restricted_channels;	/* List of restricted use channels */
+	const chanvec_t *radar_channels;	/* List of radar sensitive channels */
+	u8 PAD[8];
+} wlc_cm_band_t;
+
+struct wlc_cm_info {
+	struct wlc_pub *pub;
+	struct wlc_info *wlc;
+	char srom_ccode[WLC_CNTRY_BUF_SZ];	/* Country Code in SROM */
+	uint srom_regrev;	/* Regulatory Rev for the SROM ccode */
+	const country_info_t *country;	/* current country def */
+	char ccode[WLC_CNTRY_BUF_SZ];	/* current internal Country Code */
+	uint regrev;		/* current Regulatory Revision */
+	char country_abbrev[WLC_CNTRY_BUF_SZ];	/* current advertised ccode */
+	wlc_cm_band_t bandstate[MAXBANDS];	/* per-band state (one per phy/radio) */
+	/* quiet channels currently for radar sensitivity or 11h support */
+	chanvec_t quiet_channels;	/* channels on which we cannot transmit */
+};
+
+static int wlc_channels_init(wlc_cm_info_t *wlc_cm,
+			     const country_info_t *country);
+static void wlc_set_country_common(wlc_cm_info_t *wlc_cm,
+				   const char *country_abbrev,
+				   const char *ccode, uint regrev,
+				   const country_info_t *country);
+static int wlc_set_countrycode(wlc_cm_info_t *wlc_cm, const char *ccode);
+static int wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
+				   const char *country_abbrev,
+				   const char *ccode, int regrev);
+static int wlc_country_aggregate_map(wlc_cm_info_t *wlc_cm, const char *ccode,
+				     char *mapped_ccode, uint *mapped_regrev);
+static const country_info_t *wlc_country_lookup_direct(const char *ccode,
+						       uint regrev);
+static const country_info_t *wlc_countrycode_map(wlc_cm_info_t *wlc_cm,
+						 const char *ccode,
+						 char *mapped_ccode,
+						 uint *mapped_regrev);
+static void wlc_channels_commit(wlc_cm_info_t *wlc_cm);
+static void wlc_quiet_channels_reset(wlc_cm_info_t *wlc_cm);
+static bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
+static bool wlc_valid_channel20_db(wlc_cm_info_t *wlc_cm, uint val);
+static bool wlc_valid_channel20_in_band(wlc_cm_info_t *wlc_cm, uint bandunit,
+					uint val);
+static bool wlc_valid_channel20(wlc_cm_info_t *wlc_cm, uint val);
+static const country_info_t *wlc_country_lookup(struct wlc_info *wlc,
+						const char *ccode);
+static void wlc_locale_get_channels(const locale_info_t *locale,
+				    chanvec_t *valid_channels);
+static const locale_info_t *wlc_get_locale_2g(u8 locale_idx);
+static const locale_info_t *wlc_get_locale_5g(u8 locale_idx);
+static bool wlc_japan(struct wlc_info *wlc);
+static bool wlc_japan_ccode(const char *ccode);
+static void wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm_info_t *
+								 wlc_cm,
+								 struct
+								 txpwr_limits
+								 *txpwr,
+								 u8
+								 local_constraint_qdbm);
+void wlc_locale_add_channels(chanvec_t *target, const chanvec_t *channels);
+static const locale_mimo_info_t *wlc_get_mimo_2g(u8 locale_idx);
+static const locale_mimo_info_t *wlc_get_mimo_5g(u8 locale_idx);
+
+/* QDB() macro takes a dB value and converts to a quarter dB value */
+#ifdef QDB
+#undef QDB
+#endif
+#define QDB(n) ((n) * WLC_TXPWR_DB_FACTOR)
+
+/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
+
+/*
+ * Some common channel sets
+ */
+
+/* No channels */
+static const chanvec_t chanvec_none = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* All 2.4 GHz HW channels */
+const chanvec_t chanvec_all_2G = {
+	{0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* All 5 GHz HW channels */
+const chanvec_t chanvec_all_5G = {
+	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
+	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
+	 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
+	 0x11, 0x11, 0x11, 0x01}
+};
+
+/*
+ * Radar channel sets
+ */
+
+/* No radar */
+#define radar_set_none chanvec_none
+
+static const chanvec_t radar_set1 = {	/* Channels 52 - 64, 100 - 140 */
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,	/* 52 - 60 */
+	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,	/* 64, 100 - 124 */
+	 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 128 - 140 */
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/*
+ * Restricted channel sets
+ */
+
+#define restricted_set_none chanvec_none
+
+/* Channels 34, 38, 42, 46 */
+static const chanvec_t restricted_set_japan_legacy = {
+	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channels 12, 13 */
+static const chanvec_t restricted_set_2g_short = {
+	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channel 165 */
+static const chanvec_t restricted_chan_165 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channels 36 - 48 & 149 - 165 */
+static const chanvec_t restricted_low_hi = {
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Channels 12 - 14 */
+static const chanvec_t restricted_set_12_13_14 = {
+	{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+#define  LOCALE_CHAN_01_11	 (1<<0)
+#define  LOCALE_CHAN_12_13	 (1<<1)
+#define  LOCALE_CHAN_14		 (1<<2)
+#define  LOCALE_SET_5G_LOW_JP1   (1<<3)	/* 34-48, step 2 */
+#define  LOCALE_SET_5G_LOW_JP2   (1<<4)	/* 34-46, step 4 */
+#define  LOCALE_SET_5G_LOW1      (1<<5)	/* 36-48, step 4 */
+#define  LOCALE_SET_5G_LOW2      (1<<6)	/* 52 */
+#define  LOCALE_SET_5G_LOW3      (1<<7)	/* 56-64, step 4 */
+#define  LOCALE_SET_5G_MID1      (1<<8)	/* 100-116, step 4 */
+#define  LOCALE_SET_5G_MID2	 (1<<9)	/* 120-124, step 4 */
+#define  LOCALE_SET_5G_MID3      (1<<10)	/* 128 */
+#define  LOCALE_SET_5G_HIGH1     (1<<11)	/* 132-140, step 4 */
+#define  LOCALE_SET_5G_HIGH2     (1<<12)	/* 149-161, step 4 */
+#define  LOCALE_SET_5G_HIGH3     (1<<13)	/* 165 */
+#define  LOCALE_CHAN_52_140_ALL  (1<<14)
+#define  LOCALE_SET_5G_HIGH4     (1<<15)	/* 184-216 */
+
+#define  LOCALE_CHAN_36_64       (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
+#define  LOCALE_CHAN_52_64       (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
+#define  LOCALE_CHAN_100_124	 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
+#define  LOCALE_CHAN_100_140     \
+	(LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
+#define  LOCALE_CHAN_149_165     (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
+#define  LOCALE_CHAN_184_216     LOCALE_SET_5G_HIGH4
+
+#define  LOCALE_CHAN_01_14	(LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14)
+
+#define  LOCALE_RADAR_SET_NONE		  0
+#define  LOCALE_RADAR_SET_1		  1
+
+#define  LOCALE_RESTRICTED_NONE		  0
+#define  LOCALE_RESTRICTED_SET_2G_SHORT   1
+#define  LOCALE_RESTRICTED_CHAN_165       2
+#define  LOCALE_CHAN_ALL_5G		  3
+#define  LOCALE_RESTRICTED_JAPAN_LEGACY   4
+#define  LOCALE_RESTRICTED_11D_2G	  5
+#define  LOCALE_RESTRICTED_11D_5G	  6
+#define  LOCALE_RESTRICTED_LOW_HI	  7
+#define  LOCALE_RESTRICTED_12_13_14	  8
+
+/* global memory to provide working buffer for expanded locale */
+
+static const chanvec_t *g_table_radar_set[] = {
+	&chanvec_none,
+	&radar_set1
+};
+
+static const chanvec_t *g_table_restricted_chan[] = {
+	&chanvec_none,		/* restricted_set_none */
+	&restricted_set_2g_short,
+	&restricted_chan_165,
+	&chanvec_all_5G,
+	&restricted_set_japan_legacy,
+	&chanvec_all_2G,	/* restricted_set_11d_2G */
+	&chanvec_all_5G,	/* restricted_set_11d_5G */
+	&restricted_low_hi,
+	&restricted_set_12_13_14
+};
+
+static const chanvec_t locale_2g_01_11 = {
+	{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_2g_12_13 = {
+	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_2g_14 = {
+	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW_JP1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW_JP2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_LOW3 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_MID1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_MID2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_MID3 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH1 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH2 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH3 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_52_140_ALL = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
+	 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+	 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static const chanvec_t locale_5g_HIGH4 = {
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+	 0x11, 0x11, 0x11, 0x11}
+};
+
+static const chanvec_t *g_table_locale_base[] = {
+	&locale_2g_01_11,
+	&locale_2g_12_13,
+	&locale_2g_14,
+	&locale_5g_LOW_JP1,
+	&locale_5g_LOW_JP2,
+	&locale_5g_LOW1,
+	&locale_5g_LOW2,
+	&locale_5g_LOW3,
+	&locale_5g_MID1,
+	&locale_5g_MID2,
+	&locale_5g_MID3,
+	&locale_5g_HIGH1,
+	&locale_5g_HIGH2,
+	&locale_5g_HIGH3,
+	&locale_5g_52_140_ALL,
+	&locale_5g_HIGH4
+};
+
+void wlc_locale_add_channels(chanvec_t *target, const chanvec_t *channels)
+{
+	u8 i;
+	for (i = 0; i < sizeof(chanvec_t); i++) {
+		target->vec[i] |= channels->vec[i];
+	}
+}
+
+static void wlc_locale_get_channels(const locale_info_t *locale,
+				    chanvec_t *channels)
+{
+	u8 i;
+
+	memset(channels, 0, sizeof(chanvec_t));
+
+	for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
+		if (locale->valid_channels & (1 << i)) {
+			wlc_locale_add_channels(channels,
+						g_table_locale_base[i]);
+		}
+	}
+}
+
+/*
+ * Locale Definitions - 2.4 GHz
+ */
+static const locale_info_t locale_i = {	/* locale i. channel 1 - 13 */
+	LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
+	LOCALE_RADAR_SET_NONE,
+	LOCALE_RESTRICTED_SET_2G_SHORT,
+	{QDB(19), QDB(19), QDB(19),
+	 QDB(19), QDB(19), QDB(19)},
+	{20, 20, 20, 0},
+	WLC_EIRP
+};
+
+/*
+ * Locale Definitions - 5 GHz
+ */
+static const locale_info_t locale_11 = {
+	/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
+	LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
+	LOCALE_RADAR_SET_1,
+	LOCALE_RESTRICTED_NONE,
+	{QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
+	{23, 23, 23, 30, 30},
+	WLC_EIRP | WLC_DFS_EU
+};
+
+#define LOCALE_2G_IDX_i			0
+static const locale_info_t *g_locale_2g_table[] = {
+	&locale_i
+};
+
+#define LOCALE_5G_IDX_11	0
+static const locale_info_t *g_locale_5g_table[] = {
+	&locale_11
+};
+
+/*
+ * MIMO Locale Definitions - 2.4 GHz
+ */
+static const locale_mimo_info_t locale_bn = {
+	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13)},
+	{0, 0, QDB(13), QDB(13), QDB(13),
+	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
+	 QDB(13), 0, 0},
+	0
+};
+
+/* locale mimo 2g indexes */
+#define LOCALE_MIMO_IDX_bn			0
+
+static const locale_mimo_info_t *g_mimo_2g_table[] = {
+	&locale_bn
+};
+
+/*
+ * MIMO Locale Definitions - 5 GHz
+ */
+static const locale_mimo_info_t locale_11n = {
+	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
+	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
+	0
+};
+
+#define LOCALE_MIMO_IDX_11n			0
+static const locale_mimo_info_t *g_mimo_5g_table[] = {
+	&locale_11n
+};
+
+#ifdef LC
+#undef LC
+#endif
+#define LC(id)	LOCALE_MIMO_IDX_ ## id
+
+#ifdef LC_2G
+#undef LC_2G
+#endif
+#define LC_2G(id)	LOCALE_2G_IDX_ ## id
+
+#ifdef LC_5G
+#undef LC_5G
+#endif
+#define LC_5G(id)	LOCALE_5G_IDX_ ## id
+
+#define LOCALES(band2, band5, mimo2, mimo5)     {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
+
+static const struct {
+	char abbrev[WLC_CNTRY_BUF_SZ];	/* country abbreviation */
+	country_info_t country;
+} cntry_locales[] = {
+	{
+	"X2", LOCALES(i, 11, bn, 11n)},	/* Worldwide RoW 2 */
+};
+
+#ifdef SUPPORT_40MHZ
+/* 20MHz channel info for 40MHz pairing support */
+struct chan20_info {
+	u8 sb;
+	u8 adj_sbs;
+};
+
+/* indicates adjacent channels that are allowed for a 40 Mhz channel and
+ * those that permitted by the HT
+ */
+struct chan20_info chan20_info[] = {
+	/* 11b/11g */
+/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
+/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 11 */ {12, (CH_LOWER_SB)},
+/* 12 */ {13, (CH_LOWER_SB)},
+/* 13 */ {14, (CH_LOWER_SB)},
+
+/* 11a japan high */
+/* 14 */ {34, (CH_UPPER_SB)},
+/* 15 */ {38, (CH_LOWER_SB)},
+/* 16 */ {42, (CH_LOWER_SB)},
+/* 17 */ {46, (CH_LOWER_SB)},
+
+/* 11a usa low */
+/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
+
+/* 11a Europe */
+/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 36 */ {140, (CH_LOWER_SB)},
+
+/* 11a usa high, ref5 only */
+/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
+/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
+/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
+/* 41 */ {165, (CH_LOWER_SB)},
+
+/* 11a japan */
+/* 42 */ {184, (CH_UPPER_SB)},
+/* 43 */ {188, (CH_LOWER_SB)},
+/* 44 */ {192, (CH_UPPER_SB)},
+/* 45 */ {196, (CH_LOWER_SB)},
+/* 46 */ {200, (CH_UPPER_SB)},
+/* 47 */ {204, (CH_LOWER_SB)},
+/* 48 */ {208, (CH_UPPER_SB)},
+/* 49 */ {212, (CH_LOWER_SB)},
+/* 50 */ {216, (CH_LOWER_SB)}
+};
+#endif				/* SUPPORT_40MHZ */
+
+static const locale_info_t *wlc_get_locale_2g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) {
+		WL_ERROR("%s: locale 2g index size out of range %d\n",
+			 __func__, locale_idx);
+		ASSERT(locale_idx < ARRAY_SIZE(g_locale_2g_table));
+		return NULL;
+	}
+	return g_locale_2g_table[locale_idx];
+}
+
+static const locale_info_t *wlc_get_locale_5g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) {
+		WL_ERROR("%s: locale 5g index size out of range %d\n",
+			 __func__, locale_idx);
+		ASSERT(locale_idx < ARRAY_SIZE(g_locale_5g_table));
+		return NULL;
+	}
+	return g_locale_5g_table[locale_idx];
+}
+
+const locale_mimo_info_t *wlc_get_mimo_2g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) {
+		WL_ERROR("%s: mimo 2g index size out of range %d\n",
+			 __func__, locale_idx);
+		return NULL;
+	}
+	return g_mimo_2g_table[locale_idx];
+}
+
+const locale_mimo_info_t *wlc_get_mimo_5g(u8 locale_idx)
+{
+	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) {
+		WL_ERROR("%s: mimo 5g index size out of range %d\n",
+			 __func__, locale_idx);
+		return NULL;
+	}
+	return g_mimo_5g_table[locale_idx];
+}
+
+wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc)
+{
+	wlc_cm_info_t *wlc_cm;
+	char country_abbrev[WLC_CNTRY_BUF_SZ];
+	const country_info_t *country;
+	struct wlc_pub *pub = wlc->pub;
+	char *ccode;
+
+	WL_TRACE("wl%d: wlc_channel_mgr_attach\n", wlc->pub->unit);
+
+	wlc_cm = kzalloc(sizeof(wlc_cm_info_t), GFP_ATOMIC);
+	if (wlc_cm == NULL) {
+		WL_ERROR("wl%d: %s: out of memory", pub->unit, __func__);
+		return NULL;
+	}
+	wlc_cm->pub = pub;
+	wlc_cm->wlc = wlc;
+	wlc->cmi = wlc_cm;
+
+	/* store the country code for passing up as a regulatory hint */
+	ccode = getvar(wlc->pub->vars, "ccode");
+	if (ccode) {
+		strncpy(wlc->pub->srom_ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
+		WL_NONE("%s: SROM country code is %c%c\n",
+			__func__,
+			wlc->pub->srom_ccode[0], wlc->pub->srom_ccode[1]);
+	}
+
+	/* internal country information which must match regulatory constraints in firmware */
+	memset(country_abbrev, 0, WLC_CNTRY_BUF_SZ);
+	strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
+	country = wlc_country_lookup(wlc, country_abbrev);
+
+	ASSERT(country != NULL);
+
+	/* save default country for exiting 11d regulatory mode */
+	strncpy(wlc->country_default, country_abbrev, WLC_CNTRY_BUF_SZ - 1);
+
+	/* initialize autocountry_default to driver default */
+	strncpy(wlc->autocountry_default, "X2", WLC_CNTRY_BUF_SZ - 1);
+
+	wlc_set_countrycode(wlc_cm, country_abbrev);
+
+	return wlc_cm;
+}
+
+void wlc_channel_mgr_detach(wlc_cm_info_t *wlc_cm)
+{
+	kfree(wlc_cm);
+}
+
+u8 wlc_channel_locale_flags_in_band(wlc_cm_info_t *wlc_cm, uint bandunit)
+{
+	return wlc_cm->bandstate[bandunit].locale_flags;
+}
+
+/* set the driver's current country and regulatory information using a country code
+ * as the source. Lookup built in country information found with the country code.
+ */
+static int wlc_set_countrycode(wlc_cm_info_t *wlc_cm, const char *ccode)
+{
+	char country_abbrev[WLC_CNTRY_BUF_SZ];
+	strncpy(country_abbrev, ccode, WLC_CNTRY_BUF_SZ);
+	return wlc_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
+}
+
+static int
+wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
+			const char *country_abbrev,
+			const char *ccode, int regrev)
+{
+	const country_info_t *country;
+	char mapped_ccode[WLC_CNTRY_BUF_SZ];
+	uint mapped_regrev;
+
+	WL_NONE("%s: (country_abbrev \"%s\", ccode \"%s\", regrev %d) SPROM \"%s\"/%u\n",
+		__func__, country_abbrev, ccode, regrev,
+		wlc_cm->srom_ccode, wlc_cm->srom_regrev);
+
+	/* if regrev is -1, lookup the mapped country code,
+	 * otherwise use the ccode and regrev directly
+	 */
+	if (regrev == -1) {
+		/* map the country code to a built-in country code, regrev, and country_info */
+		country =
+		    wlc_countrycode_map(wlc_cm, ccode, mapped_ccode,
+					&mapped_regrev);
+	} else {
+		/* find the matching built-in country definition */
+		ASSERT(0);
+		country = wlc_country_lookup_direct(ccode, regrev);
+		strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
+		mapped_regrev = regrev;
+	}
+
+	if (country == NULL)
+		return BCME_BADARG;
+
+	/* set the driver state for the country */
+	wlc_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
+			       mapped_regrev, country);
+
+	return 0;
+}
+
+/* set the driver's current country and regulatory information using a country code
+ * as the source. Look up built in country information found with the country code.
+ */
+static void
+wlc_set_country_common(wlc_cm_info_t *wlc_cm,
+		       const char *country_abbrev,
+		       const char *ccode, uint regrev,
+		       const country_info_t *country)
+{
+	const locale_mimo_info_t *li_mimo;
+	const locale_info_t *locale;
+	struct wlc_info *wlc = wlc_cm->wlc;
+	char prev_country_abbrev[WLC_CNTRY_BUF_SZ];
+
+	ASSERT(country != NULL);
+
+	/* save current country state */
+	wlc_cm->country = country;
+
+	memset(&prev_country_abbrev, 0, WLC_CNTRY_BUF_SZ);
+	strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
+		WLC_CNTRY_BUF_SZ - 1);
+
+	strncpy(wlc_cm->country_abbrev, country_abbrev, WLC_CNTRY_BUF_SZ - 1);
+	strncpy(wlc_cm->ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
+	wlc_cm->regrev = regrev;
+
+	/* disable/restore nmode based on country regulations */
+	li_mimo = wlc_get_mimo_2g(country->locale_mimo_2G);
+	if (li_mimo && (li_mimo->flags & WLC_NO_MIMO)) {
+		wlc_set_nmode(wlc, OFF);
+		wlc->stf->no_cddstbc = true;
+	} else {
+		wlc->stf->no_cddstbc = false;
+		if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
+			wlc_set_nmode(wlc, wlc->protection->nmode_user);
+	}
+
+	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+	/* set or restore gmode as required by regulatory */
+	locale = wlc_get_locale_2g(country->locale_2G);
+	if (locale && (locale->flags & WLC_NO_OFDM)) {
+		wlc_set_gmode(wlc, GMODE_LEGACY_B, false);
+	} else {
+		wlc_set_gmode(wlc, wlc->protection->gmode_user, false);
+	}
+
+	wlc_channels_init(wlc_cm, country);
+
+	return;
+}
+
+/* Lookup a country info structure from a null terminated country code
+ * The lookup is case sensitive.
+ */
+static const country_info_t *wlc_country_lookup(struct wlc_info *wlc,
+					 const char *ccode)
+{
+	const country_info_t *country;
+	char mapped_ccode[WLC_CNTRY_BUF_SZ];
+	uint mapped_regrev;
+
+	/* map the country code to a built-in country code, regrev, and country_info struct */
+	country =
+	    wlc_countrycode_map(wlc->cmi, ccode, mapped_ccode, &mapped_regrev);
+
+	return country;
+}
+
+static const country_info_t *wlc_countrycode_map(wlc_cm_info_t *wlc_cm,
+						 const char *ccode,
+						 char *mapped_ccode,
+						 uint *mapped_regrev)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	const country_info_t *country;
+	uint srom_regrev = wlc_cm->srom_regrev;
+	const char *srom_ccode = wlc_cm->srom_ccode;
+	int mapped;
+
+	/* check for currently supported ccode size */
+	if (strlen(ccode) > (WLC_CNTRY_BUF_SZ - 1)) {
+		WL_ERROR("wl%d: %s: ccode \"%s\" too long for match\n",
+			 wlc->pub->unit, __func__, ccode);
+		return NULL;
+	}
+
+	/* default mapping is the given ccode and regrev 0 */
+	strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
+	*mapped_regrev = 0;
+
+	/* If the desired country code matches the srom country code,
+	 * then the mapped country is the srom regulatory rev.
+	 * Otherwise look for an aggregate mapping.
+	 */
+	if (!strcmp(srom_ccode, ccode)) {
+		*mapped_regrev = srom_regrev;
+		mapped = 0;
+		WL_ERROR("srom_code == ccode %s\n", __func__);
+		ASSERT(0);
+	} else {
+		mapped =
+		    wlc_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
+					      mapped_regrev);
+	}
+
+	/* find the matching built-in country definition */
+	country = wlc_country_lookup_direct(mapped_ccode, *mapped_regrev);
+
+	/* if there is not an exact rev match, default to rev zero */
+	if (country == NULL && *mapped_regrev != 0) {
+		*mapped_regrev = 0;
+		ASSERT(0);
+		country =
+		    wlc_country_lookup_direct(mapped_ccode, *mapped_regrev);
+	}
+
+	return country;
+}
+
+static int
+wlc_country_aggregate_map(wlc_cm_info_t *wlc_cm, const char *ccode,
+			  char *mapped_ccode, uint *mapped_regrev)
+{
+	return false;
+}
+
+/* Lookup a country info structure from a null terminated country
+ * abbreviation and regrev directly with no translation.
+ */
+static const country_info_t *wlc_country_lookup_direct(const char *ccode,
+						       uint regrev)
+{
+	uint size, i;
+
+	/* Should just return 0 for single locale driver. */
+	/* Keep it this way in case we add more locales. (for now anyway) */
+
+	/* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */
+	if (regrev > 0)
+		return NULL;
+
+	/* find matched table entry from country code */
+	size = ARRAY_SIZE(cntry_locales);
+	for (i = 0; i < size; i++) {
+		if (strcmp(ccode, cntry_locales[i].abbrev) == 0) {
+			return &cntry_locales[i].country;
+		}
+	}
+
+	WL_ERROR("%s: Returning NULL\n", __func__);
+	ASSERT(0);
+	return NULL;
+}
+
+static int
+wlc_channels_init(wlc_cm_info_t *wlc_cm, const country_info_t *country)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	uint i, j;
+	struct wlcband *band;
+	const locale_info_t *li;
+	chanvec_t sup_chan;
+	const locale_mimo_info_t *li_mimo;
+
+	band = wlc->band;
+	for (i = 0; i < NBANDS(wlc);
+	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
+
+		li = BAND_5G(band->bandtype) ?
+		    wlc_get_locale_5g(country->locale_5G) :
+		    wlc_get_locale_2g(country->locale_2G);
+		ASSERT(li);
+		wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
+		li_mimo = BAND_5G(band->bandtype) ?
+		    wlc_get_mimo_5g(country->locale_mimo_5G) :
+		    wlc_get_mimo_2g(country->locale_mimo_2G);
+		ASSERT(li_mimo);
+
+		/* merge the mimo non-mimo locale flags */
+		wlc_cm->bandstate[band->bandunit].locale_flags |=
+		    li_mimo->flags;
+
+		wlc_cm->bandstate[band->bandunit].restricted_channels =
+		    g_table_restricted_chan[li->restricted_channels];
+		wlc_cm->bandstate[band->bandunit].radar_channels =
+		    g_table_radar_set[li->radar_channels];
+
+		/* set the channel availability,
+		 * masking out the channels that may not be supported on this phy
+		 */
+		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
+					      &sup_chan);
+		wlc_locale_get_channels(li,
+					&wlc_cm->bandstate[band->bandunit].
+					valid_channels);
+		for (j = 0; j < sizeof(chanvec_t); j++)
+			wlc_cm->bandstate[band->bandunit].valid_channels.
+			    vec[j] &= sup_chan.vec[j];
+	}
+
+	wlc_quiet_channels_reset(wlc_cm);
+	wlc_channels_commit(wlc_cm);
+
+	return 0;
+}
+
+/* Update the radio state (enable/disable) and tx power targets
+ * based on a new set of channel/regulatory information
+ */
+static void wlc_channels_commit(wlc_cm_info_t *wlc_cm)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	uint chan;
+	struct txpwr_limits txpwr;
+
+	/* search for the existence of any valid channel */
+	for (chan = 0; chan < MAXCHANNEL; chan++) {
+		if (VALID_CHANNEL20_DB(wlc, chan)) {
+			break;
+		}
+	}
+	if (chan == MAXCHANNEL)
+		chan = INVCHANNEL;
+
+	/* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */
+	if (chan == INVCHANNEL) {
+		/* country/locale with no valid channels, set the radio disable bit */
+		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+		WL_ERROR("wl%d: %s: no valid channel for \"%s\" nbands %d bandlocked %d\n",
+			 wlc->pub->unit, __func__,
+			 wlc_cm->country_abbrev, NBANDS(wlc), wlc->bandlocked);
+	} else
+	    if (mboolisset(wlc->pub->radio_disabled,
+		WL_RADIO_COUNTRY_DISABLE)) {
+		/* country/locale with valid channel, clear the radio disable bit */
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
+	}
+
+	/* Now that the country abbreviation is set, if the radio supports 2G, then
+	 * set channel 14 restrictions based on the new locale.
+	 */
+	if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) {
+		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
+						     wlc_japan(wlc) ? true :
+						     false);
+	}
+
+	if (wlc->pub->up && chan != INVCHANNEL) {
+		wlc_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
+		wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm,
+								     &txpwr,
+								     WLC_TXPWR_MAX);
+		wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
+	}
+}
+
+/* reset the quiet channels vector to the union of the restricted and radar channel sets */
+static void wlc_quiet_channels_reset(wlc_cm_info_t *wlc_cm)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	uint i, j;
+	struct wlcband *band;
+	const chanvec_t *chanvec;
+
+	memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t));
+
+	band = wlc->band;
+	for (i = 0; i < NBANDS(wlc);
+	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
+
+		/* initialize quiet channels for restricted channels */
+		chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
+		for (j = 0; j < sizeof(chanvec_t); j++)
+			wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
+
+	}
+}
+
+static bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
+{
+	return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ?
+		(isset
+		 (wlc_cm->quiet_channels.vec,
+		  LOWER_20_SB(CHSPEC_CHANNEL(chspec)))
+		 || isset(wlc_cm->quiet_channels.vec,
+			  UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->
+									quiet_channels.
+									vec,
+									CHSPEC_CHANNEL
+									(chspec));
+}
+
+/* Is the channel valid for the current locale? (but don't consider channels not
+ *   available due to bandlocking)
+ */
+static bool wlc_valid_channel20_db(wlc_cm_info_t *wlc_cm, uint val)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+
+	return VALID_CHANNEL20(wlc, val) ||
+		(!wlc->bandlocked
+		 && VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
+}
+
+/* Is the channel valid for the current locale and specified band? */
+static bool
+wlc_valid_channel20_in_band(wlc_cm_info_t *wlc_cm, uint bandunit, uint val)
+{
+	return ((val < MAXCHANNEL)
+		&& isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
+}
+
+/* Is the channel valid for the current locale and current band? */
+static bool wlc_valid_channel20(wlc_cm_info_t *wlc_cm, uint val)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+
+	return ((val < MAXCHANNEL) &&
+		isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
+		      val));
+}
+
+static void
+wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm_info_t *wlc_cm,
+						     struct txpwr_limits *txpwr,
+						     u8
+						     local_constraint_qdbm)
+{
+	int j;
+
+	/* CCK Rates */
+	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) {
+		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
+	}
+
+	/* 20 MHz Legacy OFDM SISO */
+	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) {
+		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
+	}
+
+	/* 20 MHz Legacy OFDM CDD */
+	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
+		txpwr->ofdm_cdd[j] =
+		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 40 MHz Legacy OFDM SISO */
+	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
+		txpwr->ofdm_40_siso[j] =
+		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
+	}
+
+	/* 40 MHz Legacy OFDM CDD */
+	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
+		txpwr->ofdm_40_cdd[j] =
+		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 0-7 SISO */
+	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_20_siso[j] =
+		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 0-7 CDD */
+	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_20_cdd[j] =
+		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 0-7 STBC */
+	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_20_stbc[j] =
+		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
+	}
+
+	/* 20MHz MCS 8-15 MIMO */
+	for (j = 0; j < WLC_NUM_RATES_MCS_2_STREAM; j++)
+		txpwr->mcs_20_mimo[j] =
+		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 0-7 SISO */
+	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_40_siso[j] =
+		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
+	}
+
+	/* 40MHz MCS 0-7 CDD */
+	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_40_cdd[j] =
+		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
+	}
+
+	/* 40MHz MCS 0-7 STBC */
+	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
+		txpwr->mcs_40_stbc[j] =
+		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
+	}
+
+	/* 40MHz MCS 8-15 MIMO */
+	for (j = 0; j < WLC_NUM_RATES_MCS_2_STREAM; j++)
+		txpwr->mcs_40_mimo[j] =
+		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
+
+	/* 40MHz MCS 32 */
+	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
+
+}
+
+void
+wlc_channel_set_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chanspec,
+			 u8 local_constraint_qdbm)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	struct txpwr_limits txpwr;
+
+	wlc_channel_reg_limits(wlc_cm, chanspec, &txpwr);
+
+	wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
+							     local_constraint_qdbm);
+
+	wlc_bmac_set_chanspec(wlc->hw, chanspec,
+			      (wlc_quiet_chanspec(wlc_cm, chanspec) != 0),
+			      &txpwr);
+}
+
+#ifdef POWER_DBG
+static void wlc_phy_txpower_limits_dump(txpwr_limits_t *txpwr)
+{
+	int i;
+	char buf[80];
+	char fraction[4][4] = { "   ", ".25", ".5 ", ".75" };
+
+	sprintf(buf, "CCK                ");
+	for (i = 0; i < WLC_NUM_RATES_CCK; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->cck[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->cck[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz OFDM SISO   ");
+	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz OFDM CDD    ");
+	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm_cdd[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm_cdd[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz OFDM SISO   ");
+	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm_40_siso[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm_40_siso[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz OFDM CDD    ");
+	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->ofdm_40_cdd[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->ofdm_40_cdd[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS0-7 SISO ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_siso[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_siso[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS0-7 CDD  ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_cdd[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_cdd[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS0-7 STBC ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_stbc[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_stbc[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "20 MHz MCS8-15 SDM ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_20_mimo[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_20_mimo[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS0-7 SISO ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_siso[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_siso[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS0-7 CDD  ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_cdd[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_cdd[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS0-7 STBC ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_stbc[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_stbc[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	sprintf(buf, "40 MHz MCS8-15 SDM ");
+	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
+		sprintf(buf[strlen(buf)], " %2d%s",
+			txpwr->mcs_40_mimo[i] / WLC_TXPWR_DB_FACTOR,
+			fraction[txpwr->mcs_40_mimo[i] % WLC_TXPWR_DB_FACTOR]);
+	}
+	printk(KERN_DEBUG "%s\n", buf);
+
+	printk(KERN_DEBUG "MCS32               %2d%s\n",
+	       txpwr->mcs32 / WLC_TXPWR_DB_FACTOR,
+	       fraction[txpwr->mcs32 % WLC_TXPWR_DB_FACTOR]);
+}
+#endif				/* POWER_DBG */
+
+void
+wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm, chanspec_t chanspec,
+		       txpwr_limits_t *txpwr)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	uint i;
+	uint chan;
+	int maxpwr;
+	int delta;
+	const country_info_t *country;
+	struct wlcband *band;
+	const locale_info_t *li;
+	int conducted_max;
+	int conducted_ofdm_max;
+	const locale_mimo_info_t *li_mimo;
+	int maxpwr20, maxpwr40;
+	int maxpwr_idx;
+	uint j;
+
+	memset(txpwr, 0, sizeof(txpwr_limits_t));
+
+	if (!wlc_valid_chanspec_db(wlc_cm, chanspec)) {
+		country = wlc_country_lookup(wlc, wlc->autocountry_default);
+		if (country == NULL)
+			return;
+	} else {
+		country = wlc_cm->country;
+	}
+
+	chan = CHSPEC_CHANNEL(chanspec);
+	band = wlc->bandstate[CHSPEC_WLCBANDUNIT(chanspec)];
+	li = BAND_5G(band->bandtype) ?
+	    wlc_get_locale_5g(country->locale_5G) :
+	    wlc_get_locale_2g(country->locale_2G);
+
+	li_mimo = BAND_5G(band->bandtype) ?
+	    wlc_get_mimo_5g(country->locale_mimo_5G) :
+	    wlc_get_mimo_2g(country->locale_mimo_2G);
+
+	if (li->flags & WLC_EIRP) {
+		delta = band->antgain;
+	} else {
+		delta = 0;
+		if (band->antgain > QDB(6))
+			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
+	}
+
+	if (li == &locale_i) {
+		conducted_max = QDB(22);
+		conducted_ofdm_max = QDB(22);
+	}
+
+	/* CCK txpwr limits for 2.4G band */
+	if (BAND_2G(band->bandtype)) {
+		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
+
+		maxpwr = maxpwr - delta;
+		maxpwr = max(maxpwr, 0);
+		maxpwr = min(maxpwr, conducted_max);
+
+		for (i = 0; i < WLC_NUM_RATES_CCK; i++)
+			txpwr->cck[i] = (u8) maxpwr;
+	}
+
+	/* OFDM txpwr limits for 2.4G or 5G bands */
+	if (BAND_2G(band->bandtype)) {
+		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
+
+	} else {
+		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
+	}
+
+	maxpwr = maxpwr - delta;
+	maxpwr = max(maxpwr, 0);
+	maxpwr = min(maxpwr, conducted_ofdm_max);
+
+	/* Keep OFDM lmit below CCK limit */
+	if (BAND_2G(band->bandtype))
+		maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
+
+	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
+		txpwr->ofdm[i] = (u8) maxpwr;
+	}
+
+	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
+		/* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless
+		 * overriden by the locale specific code. We set this value to 0 as a
+		 * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value
+		 * to the 40 MHz value if it wasn't explicitly set.
+		 */
+		txpwr->ofdm_40_siso[i] = 0;
+
+		txpwr->ofdm_cdd[i] = (u8) maxpwr;
+
+		txpwr->ofdm_40_cdd[i] = 0;
+	}
+
+	/* MIMO/HT specific limits */
+	if (li_mimo->flags & WLC_EIRP) {
+		delta = band->antgain;
+	} else {
+		delta = 0;
+		if (band->antgain > QDB(6))
+			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
+	}
+
+	if (BAND_2G(band->bandtype))
+		maxpwr_idx = (chan - 1);
+	else
+		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
+
+	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
+	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
+
+	maxpwr20 = maxpwr20 - delta;
+	maxpwr20 = max(maxpwr20, 0);
+	maxpwr40 = maxpwr40 - delta;
+	maxpwr40 = max(maxpwr40, 0);
+
+	/* Fill in the MCS 0-7 (SISO) rates */
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+
+		/* 20 MHz has the same power as the corresponding OFDM rate unless
+		 * overriden by the locale specific code.
+		 */
+		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
+		txpwr->mcs_40_siso[i] = 0;
+	}
+
+	/* Fill in the MCS 0-7 CDD rates */
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
+		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
+	}
+
+	/* These locales have SISO expressed in the table and override CDD later */
+	if (li_mimo == &locale_bn) {
+		if (li_mimo == &locale_bn) {
+			maxpwr20 = QDB(16);
+			maxpwr40 = 0;
+
+			if (chan >= 3 && chan <= 11) {
+				maxpwr40 = QDB(16);
+			}
+		}
+
+		for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
+			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
+		}
+	}
+
+	/* Fill in the MCS 0-7 STBC rates */
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		txpwr->mcs_20_stbc[i] = 0;
+		txpwr->mcs_40_stbc[i] = 0;
+	}
+
+	/* Fill in the MCS 8-15 SDM rates */
+	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
+		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
+		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
+	}
+
+	/* Fill in MCS32 */
+	txpwr->mcs32 = (u8) maxpwr40;
+
+	for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) {
+		if (txpwr->ofdm_40_cdd[i] == 0)
+			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
+		if (i == 0) {
+			i = i + 1;
+			if (txpwr->ofdm_40_cdd[i] == 0)
+				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
+		}
+	}
+
+	/* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't
+	 * provided explicitly.
+	 */
+
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		if (txpwr->mcs_40_siso[i] == 0)
+			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
+	}
+
+	for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) {
+		if (txpwr->ofdm_40_siso[i] == 0)
+			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
+		if (i == 0) {
+			i = i + 1;
+			if (txpwr->ofdm_40_siso[i] == 0)
+				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
+		}
+	}
+
+	/* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't
+	 * provided explicitly.
+	 */
+	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
+		if (txpwr->mcs_20_stbc[i] == 0)
+			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
+
+		if (txpwr->mcs_40_stbc[i] == 0)
+			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
+	}
+
+#ifdef POWER_DBG
+	wlc_phy_txpower_limits_dump(txpwr);
+#endif
+	return;
+}
+
+/* Returns true if currently set country is Japan or variant */
+static bool wlc_japan(struct wlc_info *wlc)
+{
+	return wlc_japan_ccode(wlc->cmi->country_abbrev);
+}
+
+/* JP, J1 - J10 are Japan ccodes */
+static bool wlc_japan_ccode(const char *ccode)
+{
+	return (ccode[0] == 'J' &&
+		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
+}
+
+/*
+ * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands
+ * are valid 20MZH channels in this locale and they are also a legal HT combination
+ */
+static bool
+wlc_valid_chanspec_ext(wlc_cm_info_t *wlc_cm, chanspec_t chspec, bool dualband)
+{
+	struct wlc_info *wlc = wlc_cm->wlc;
+	u8 channel = CHSPEC_CHANNEL(chspec);
+
+	/* check the chanspec */
+	if (wf_chspec_malformed(chspec)) {
+		WL_ERROR("wl%d: malformed chanspec 0x%x\n",
+			 wlc->pub->unit, chspec);
+		ASSERT(0);
+		return false;
+	}
+
+	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
+	    CHSPEC_WLCBANDUNIT(chspec))
+		return false;
+
+	/* Check a 20Mhz channel */
+	if (CHSPEC_IS20(chspec)) {
+		if (dualband)
+			return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
+		else
+			return VALID_CHANNEL20(wlc_cm->wlc, channel);
+	}
+#ifdef SUPPORT_40MHZ
+	/* We know we are now checking a 40MHZ channel, so we should only be here
+	 * for NPHYS
+	 */
+	if (WLCISNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band)) {
+		u8 upper_sideband = 0, idx;
+		u8 num_ch20_entries =
+		    sizeof(chan20_info) / sizeof(struct chan20_info);
+
+		if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_WLCBANDUNIT(chspec)))
+			return false;
+
+		if (dualband) {
+			if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
+			    !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
+				return false;
+		} else {
+			if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
+			    !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
+				return false;
+		}
+
+		/* find the lower sideband info in the sideband array */
+		for (idx = 0; idx < num_ch20_entries; idx++) {
+			if (chan20_info[idx].sb == LOWER_20_SB(channel))
+				upper_sideband = chan20_info[idx].adj_sbs;
+		}
+		/* check that the lower sideband allows an upper sideband */
+		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
+		    (CH_UPPER_SB | CH_EWA_VALID))
+			return true;
+		return false;
+	}
+#endif				/* 40 MHZ */
+
+	return false;
+}
+
+bool wlc_valid_chanspec_db(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
+{
+	return wlc_valid_chanspec_ext(wlc_cm, chspec, true);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_channel.h b/drivers/staging/brcm80211/brcmsmac/wlc_channel.h
new file mode 100644
index 0000000..b8dec5b
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_channel.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLC_CHANNEL_H_
+#define _WLC_CHANNEL_H_
+
+#define WLC_TXPWR_DB_FACTOR 4	/* conversion for phy txpwr cacluations that use .25 dB units */
+
+struct wlc_info;
+
+/* maxpwr mapping to 5GHz band channels:
+ * maxpwr[0] - channels [34-48]
+ * maxpwr[1] - channels [52-60]
+ * maxpwr[2] - channels [62-64]
+ * maxpwr[3] - channels [100-140]
+ * maxpwr[4] - channels [149-165]
+ */
+#define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
+
+/* power level in group of 2.4GHz band channels:
+ * maxpwr[0] - CCK  channels [1]
+ * maxpwr[1] - CCK  channels [2-10]
+ * maxpwr[2] - CCK  channels [11-14]
+ * maxpwr[3] - OFDM channels [1]
+ * maxpwr[4] - OFDM channels [2-10]
+ * maxpwr[5] - OFDM channels [11-14]
+ */
+
+/* macro to get 2.4 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))	/* cck index */
+#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))	/* ofdm index */
+
+/* macro to get 5 GHz channel group index for tx power */
+#define CHANNEL_POWER_IDX_5G(c) \
+	(((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4))))
+
+#define WLC_MAXPWR_TBL_SIZE		6	/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
+#define WLC_MAXPWR_MIMO_TBL_SIZE	14	/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
+
+/* locale channel and power info. */
+typedef struct {
+	u32 valid_channels;
+	u8 radar_channels;	/* List of radar sensitive channels */
+	u8 restricted_channels;	/* List of channels used only if APs are detected */
+	s8 maxpwr[WLC_MAXPWR_TBL_SIZE];	/* Max tx pwr in qdBm for each sub-band */
+	s8 pub_maxpwr[BAND_5G_PWR_LVLS];	/* Country IE advertised max tx pwr in dBm
+						 * per sub-band
+						 */
+	u8 flags;
+} locale_info_t;
+
+/* bits for locale_info flags */
+#define WLC_PEAK_CONDUCTED	0x00	/* Peak for locals */
+#define WLC_EIRP		0x01	/* Flag for EIRP */
+#define WLC_DFS_TPC		0x02	/* Flag for DFS TPC */
+#define WLC_NO_OFDM		0x04	/* Flag for No OFDM */
+#define WLC_NO_40MHZ		0x08	/* Flag for No MIMO 40MHz */
+#define WLC_NO_MIMO		0x10	/* Flag for No MIMO, 20 or 40 MHz */
+#define WLC_RADAR_TYPE_EU       0x20	/* Flag for EU */
+#define WLC_DFS_FCC             WLC_DFS_TPC	/* Flag for DFS FCC */
+#define WLC_DFS_EU              (WLC_DFS_TPC | WLC_RADAR_TYPE_EU)	/* Flag for DFS EU */
+
+#define ISDFS_EU(fl)		(((fl) & WLC_DFS_EU) == WLC_DFS_EU)
+
+/* locale per-channel tx power limits for MIMO frames
+ * maxpwr arrays are index by channel for 2.4 GHz limits, and
+ * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
+ */
+typedef struct {
+	s8 maxpwr20[WLC_MAXPWR_MIMO_TBL_SIZE];	/* tx 20 MHz power limits, qdBm units */
+	s8 maxpwr40[WLC_MAXPWR_MIMO_TBL_SIZE];	/* tx 40 MHz power limits, qdBm units */
+	u8 flags;
+} locale_mimo_info_t;
+
+extern const chanvec_t chanvec_all_2G;
+extern const chanvec_t chanvec_all_5G;
+
+/*
+ * Country names and abbreviations with locale defined from ISO 3166
+ */
+struct country_info {
+	const u8 locale_2G;	/* 2.4G band locale */
+	const u8 locale_5G;	/* 5G band locale */
+	const u8 locale_mimo_2G;	/* 2.4G mimo info */
+	const u8 locale_mimo_5G;	/* 5G mimo info */
+};
+
+typedef struct country_info country_info_t;
+
+typedef struct wlc_cm_info wlc_cm_info_t;
+
+extern wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc);
+extern void wlc_channel_mgr_detach(wlc_cm_info_t *wlc_cm);
+
+extern u8 wlc_channel_locale_flags_in_band(wlc_cm_info_t *wlc_cm,
+					   uint bandunit);
+
+extern bool wlc_valid_chanspec_db(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
+
+extern void wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm,
+				   chanspec_t chanspec,
+				   struct txpwr_limits *txpwr);
+extern void wlc_channel_set_chanspec(wlc_cm_info_t *wlc_cm,
+				     chanspec_t chanspec,
+				     u8 local_constraint_qdbm);
+
+#endif				/* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_key.h b/drivers/staging/brcm80211/brcmsmac/wlc_key.h
new file mode 100644
index 0000000..50a4e38
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_key.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_key_h_
+#define _wlc_key_h_
+
+struct scb;
+struct wlc_info;
+struct wlc_bsscfg;
+/* Maximum # of keys that wl driver supports in S/W.
+ * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS.
+ */
+#define WSEC_MAX_KEYS		54	/* Max # of keys (50 + 4 default keys) */
+#define WLC_DEFAULT_KEYS	4	/* Default # of keys */
+
+#define WSEC_MAX_WOWL_KEYS 5	/* Max keys in WOWL mode (1 + 4 default keys) */
+
+#define WPA2_GTK_MAX	3
+
+/*
+* Max # of keys currently supported:
+*
+*     s/w keys if WSEC_SW(wlc->wsec).
+*     h/w keys otherwise.
+*/
+#define WLC_MAX_WSEC_KEYS(wlc) WSEC_MAX_KEYS
+
+/* number of 802.11 default (non-paired, group keys) */
+#define WSEC_MAX_DEFAULT_KEYS	4	/* # of default keys */
+
+/* Max # of hardware keys supported */
+#define WLC_MAX_WSEC_HW_KEYS(wlc) WSEC_MAX_RCMTA_KEYS
+
+/* Max # of hardware TKIP MIC keys supported */
+#define WLC_MAX_TKMIC_HW_KEYS(wlc) (WSEC_MAX_TKMIC_ENGINE_KEYS)
+
+#define WSEC_HW_TKMIC_KEY(wlc, key, bsscfg) \
+	((((wlc)->machwcap & MCAP_TKIPMIC)) && \
+	 (key) && ((key)->algo == CRYPTO_ALGO_TKIP) && \
+	 !WSEC_SOFTKEY(wlc, key, bsscfg) && \
+	WSEC_KEY_INDEX(wlc, key) >= WLC_DEFAULT_KEYS && \
+	(WSEC_KEY_INDEX(wlc, key) < WSEC_MAX_TKMIC_ENGINE_KEYS))
+
+/* index of key in key table */
+#define WSEC_KEY_INDEX(wlc, key)	((key)->idx)
+
+#define WSEC_SOFTKEY(wlc, key, bsscfg) (WLC_SW_KEYS(wlc, bsscfg) || \
+	WSEC_KEY_INDEX(wlc, key) >= WLC_MAX_WSEC_HW_KEYS(wlc))
+
+/* get a key, non-NULL only if key allocated and not clear */
+#define WSEC_KEY(wlc, i)	(((wlc)->wsec_keys[i] && (wlc)->wsec_keys[i]->len) ? \
+	(wlc)->wsec_keys[i] : NULL)
+
+#define WSEC_SCB_KEY_VALID(scb)	(((scb)->key && (scb)->key->len) ? true : false)
+
+/* default key */
+#define WSEC_BSS_DEFAULT_KEY(bsscfg) (((bsscfg)->wsec_index == -1) ? \
+	(struct wsec_key *)NULL:(bsscfg)->bss_def_keys[(bsscfg)->wsec_index])
+
+/* Macros for key management in IBSS mode */
+#define WSEC_IBSS_MAX_PEERS	16	/* Max # of IBSS Peers */
+#define WSEC_IBSS_RCMTA_INDEX(idx) \
+	(((idx - WSEC_MAX_DEFAULT_KEYS) % WSEC_IBSS_MAX_PEERS) + WSEC_MAX_DEFAULT_KEYS)
+
+/* contiguous # key slots for infrastructure mode STA */
+#define WSEC_BSS_STA_KEY_GROUP_SIZE	5
+
+typedef struct wsec_iv {
+	u32 hi;		/* upper 32 bits of IV */
+	u16 lo;		/* lower 16 bits of IV */
+} wsec_iv_t;
+
+#define WLC_NUMRXIVS	16	/* # rx IVs (one per 802.11e TID) */
+
+typedef struct wsec_key {
+	u8 ea[ETH_ALEN];	/* per station */
+	u8 idx;		/* key index in wsec_keys array */
+	u8 id;		/* key ID [0-3] */
+	u8 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
+	u8 rcmta;		/* rcmta entry index, same as idx by default */
+	u16 flags;		/* misc flags */
+	u8 algo_hw;		/* cache for hw register */
+	u8 aes_mode;		/* cache for hw register */
+	s8 iv_len;		/* IV length */
+	s8 icv_len;		/* ICV length */
+	u32 len;		/* key length..don't move this var */
+	/* data is 4byte aligned */
+	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
+	wsec_iv_t rxiv[WLC_NUMRXIVS];	/* Rx IV (one per TID) */
+	wsec_iv_t txiv;		/* Tx IV */
+
+} wsec_key_t;
+
+#define broken_roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+
+/* For use with wsec_key_t.flags */
+
+#define WSEC_BS_UPDATE		(1 << 0)	/* Indicates hw needs key update on BS switch */
+#define WSEC_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
+#define WSEC_TKIP_ERROR		(1 << 2)	/* Provoke deliberate MIC error */
+#define WSEC_REPLAY_ERROR	(1 << 3)	/* Provoke deliberate replay */
+#define WSEC_IBSS_PEER_GROUP_KEY	(1 << 7)	/* Flag: group key for a IBSS PEER */
+#define WSEC_ICV_ERROR		(1 << 8)	/* Provoke deliberate ICV error */
+
+#define wlc_key_insert(a, b, c, d, e, f, g, h, i, j) (BCME_ERROR)
+#define wlc_key_update(a, b, c) do {} while (0)
+#define wlc_key_remove(a, b, c) do {} while (0)
+#define wlc_key_remove_all(a, b) do {} while (0)
+#define wlc_key_delete(a, b, c) do {} while (0)
+#define wlc_scb_key_delete(a, b) do {} while (0)
+#define wlc_key_lookup(a, b, c, d, e) (NULL)
+#define wlc_key_hw_init_all(a) do {} while (0)
+#define wlc_key_hw_init(a, b, c)  do {} while (0)
+#define wlc_key_hw_wowl_init(a, b, c, d) do {} while (0)
+#define wlc_key_sw_wowl_update(a, b, c, d, e) do {} while (0)
+#define wlc_key_sw_wowl_create(a, b, c) (BCME_ERROR)
+#define wlc_key_iv_update(a, b, c, d, e) do {(void)e; } while (0)
+#define wlc_key_iv_init(a, b, c) do {} while (0)
+#define wlc_key_set_error(a, b, c) (BCME_ERROR)
+#define wlc_key_dump_hw(a, b) (BCME_ERROR)
+#define wlc_key_dump_sw(a, b) (BCME_ERROR)
+#define wlc_key_defkeyflag(a) (0)
+#define wlc_rcmta_add_bssid(a, b) do {} while (0)
+#define wlc_rcmta_del_bssid(a, b) do {} while (0)
+#define wlc_key_scb_delete(a, b) do {} while (0)
+
+#endif				/* _wlc_key_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
new file mode 100644
index 0000000..639b5d7
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
@@ -0,0 +1,8499 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/ctype.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include <bcmdefs.h>
+#include <bcmdevs.h>
+#include <bcmutils.h>
+#include <bcmwifi.h>
+#include <siutils.h>
+#include <pcicfg.h>
+#include <bcmsrom.h>
+#include <wlioctl.h>
+#include <sbhnddma.h>
+#include <hnddma.h>
+#include <hndpmu.h>
+
+#include "d11.h"
+#include "wlc_types.h"
+#include "wlc_cfg.h"
+#include "wlc_rate.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_key.h"
+#include "wlc_bsscfg.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+#include "wlc_bmac.h"
+#include "wlc_phy_hal.h"
+#include "wlc_phy_shim.h"
+#include "wlc_antsel.h"
+#include "wlc_stf.h"
+#include "wlc_ampdu.h"
+#include "wl_export.h"
+#include "wlc_alloc.h"
+#include "wl_dbg.h"
+
+/*
+ *	Disable statistics counting for WME
+ */
+#define WLCNTSET(a, b)
+#define WLCNTINCR(a)
+#define WLCNTADD(a, b)
+
+/*
+ * WPA(2) definitions
+ */
+#define RSN_CAP_4_REPLAY_CNTRS		2
+#define RSN_CAP_16_REPLAY_CNTRS		3
+
+#define WPA_CAP_4_REPLAY_CNTRS		RSN_CAP_4_REPLAY_CNTRS
+#define WPA_CAP_16_REPLAY_CNTRS		RSN_CAP_16_REPLAY_CNTRS
+
+/*
+ * Indication for txflowcontrol that all priority bits in
+ * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
+ */
+#define ALLPRIO		-1
+
+/*
+ * buffer length needed for wlc_format_ssid
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN	((4 * IEEE80211_MAX_SSID_LEN) + 1)
+
+#define	TIMER_INTERVAL_WATCHDOG	1000	/* watchdog timer, in unit of ms */
+#define	TIMER_INTERVAL_RADIOCHK	800	/* radio monitor timer, in unit of ms */
+
+#ifndef WLC_MPC_MAX_DELAYCNT
+#define	WLC_MPC_MAX_DELAYCNT	10	/* Max MPC timeout, in unit of watchdog */
+#endif
+#define	WLC_MPC_MIN_DELAYCNT	1	/* Min MPC timeout, in unit of watchdog */
+#define	WLC_MPC_THRESHOLD	3	/* MPC count threshold level */
+
+#define	BEACON_INTERVAL_DEFAULT	100	/* beacon interval, in unit of 1024TU */
+#define	DTIM_INTERVAL_DEFAULT	3	/* DTIM interval, in unit of beacon interval */
+
+/* Scale down delays to accommodate QT slow speed */
+#define	BEACON_INTERVAL_DEF_QT	20	/* beacon interval, in unit of 1024TU */
+#define	DTIM_INTERVAL_DEF_QT	1	/* DTIM interval, in unit of beacon interval */
+
+#define	TBTT_ALIGN_LEEWAY_US	100	/* min leeway before first TBTT in us */
+
+/*
+ * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft
+ * watchdog) it is not a wall clock and won't increment when driver is in "down" state
+ * this low resolution driver tick can be used for maintenance tasks such as phy
+ * calibration and scb update
+ */
+
+/* watchdog trigger mode: OSL timer or TBTT */
+#define WLC_WATCHDOG_TBTT(wlc) \
+	(wlc->stas_associated > 0 && wlc->PM != PM_OFF && wlc->pub->align_wd_tbtt)
+
+/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */
+#define BCMCFID(wlc, fid) wlc_bmac_write_shm((wlc)->hw, M_BCMC_FID, (fid))
+
+#define WLC_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \
+				(!AP_ENAB(wlc->pub)) && (wlc->war16165))
+
+/* debug/trace */
+uint wl_msg_level =
+#if defined(BCMDBG)
+    WL_ERROR_VAL;
+#else
+    0;
+#endif				/* BCMDBG */
+
+/* Find basic rate for a given rate */
+#define WLC_BASIC_RATE(wlc, rspec)	(IS_MCS(rspec) ? \
+			(wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \
+			(wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
+
+#define FRAMETYPE(r, mimoframe)	(IS_MCS(r) ? mimoframe	: (IS_CCK(r) ? FT_CCK : FT_OFDM))
+
+#define RFDISABLE_DEFAULT	10000000	/* rfdisable delay timer 500 ms, runs of ALP clock */
+
+#define WLC_TEMPSENSE_PERIOD		10	/* 10 second timeout */
+
+#define SCAN_IN_PROGRESS(x)	0
+
+#define EPI_VERSION_NUM		0x054b0b00
+
+#ifdef BCMDBG
+/* pointer to most recently allocated wl/wlc */
+static struct wlc_info *wlc_info_dbg = (struct wlc_info *) (NULL);
+#endif
+
+/* IOVar table */
+
+/* Parameter IDs, for use only internally to wlc -- in the wlc_iovars
+ * table and by the wlc_doiovar() function.  No ordering is imposed:
+ * the table is keyed by name, and the function uses a switch.
+ */
+enum {
+	IOV_MPC = 1,
+	IOV_RTSTHRESH,
+	IOV_QTXPOWER,
+	IOV_BCN_LI_BCN,		/* Beacon listen interval in # of beacons */
+	IOV_LAST		/* In case of a need to check max ID number */
+};
+
+const bcm_iovar_t wlc_iovars[] = {
+	{"mpc", IOV_MPC, (0), IOVT_BOOL, 0},
+	{"rtsthresh", IOV_RTSTHRESH, (IOVF_WHL), IOVT_UINT16, 0},
+	{"qtxpower", IOV_QTXPOWER, (IOVF_WHL), IOVT_UINT32, 0},
+	{"bcn_li_bcn", IOV_BCN_LI_BCN, (0), IOVT_UINT8, 0},
+	{NULL, 0, 0, 0, 0}
+};
+
+const u8 prio2fifo[NUMPRIO] = {
+	TX_AC_BE_FIFO,		/* 0    BE      AC_BE   Best Effort */
+	TX_AC_BK_FIFO,		/* 1    BK      AC_BK   Background */
+	TX_AC_BK_FIFO,		/* 2    --      AC_BK   Background */
+	TX_AC_BE_FIFO,		/* 3    EE      AC_BE   Best Effort */
+	TX_AC_VI_FIFO,		/* 4    CL      AC_VI   Video */
+	TX_AC_VI_FIFO,		/* 5    VI      AC_VI   Video */
+	TX_AC_VO_FIFO,		/* 6    VO      AC_VO   Voice */
+	TX_AC_VO_FIFO		/* 7    NC      AC_VO   Voice */
+};
+
+/* precedences numbers for wlc queues. These are twice as may levels as
+ * 802.1D priorities.
+ * Odd numbers are used for HI priority traffic at same precedence levels
+ * These constants are used ONLY by wlc_prio2prec_map.  Do not use them elsewhere.
+ */
+#define	_WLC_PREC_NONE		0	/* None = - */
+#define	_WLC_PREC_BK		2	/* BK - Background */
+#define	_WLC_PREC_BE		4	/* BE - Best-effort */
+#define	_WLC_PREC_EE		6	/* EE - Excellent-effort */
+#define	_WLC_PREC_CL		8	/* CL - Controlled Load */
+#define	_WLC_PREC_VI		10	/* Vi - Video */
+#define	_WLC_PREC_VO		12	/* Vo - Voice */
+#define	_WLC_PREC_NC		14	/* NC - Network Control */
+
+/* 802.1D Priority to precedence queue mapping */
+const u8 wlc_prio2prec_map[] = {
+	_WLC_PREC_BE,		/* 0 BE - Best-effort */
+	_WLC_PREC_BK,		/* 1 BK - Background */
+	_WLC_PREC_NONE,		/* 2 None = - */
+	_WLC_PREC_EE,		/* 3 EE - Excellent-effort */
+	_WLC_PREC_CL,		/* 4 CL - Controlled Load */
+	_WLC_PREC_VI,		/* 5 Vi - Video */
+	_WLC_PREC_VO,		/* 6 Vo - Voice */
+	_WLC_PREC_NC,		/* 7 NC - Network Control */
+};
+
+/* Sanity check for tx_prec_map and fifo synchup
+ * Either there are some packets pending for the fifo, else if fifo is empty then
+ * all the corresponding precmap bits should be set
+ */
+#define WLC_TX_FIFO_CHECK(wlc, fifo) (TXPKTPENDGET((wlc), (fifo)) ||	\
+	(TXPKTPENDGET((wlc), (fifo)) == 0 && \
+	((wlc)->tx_prec_map & (wlc)->fifo2prec_map[(fifo)]) == \
+	(wlc)->fifo2prec_map[(fifo)]))
+
+/* TX FIFO number to WME/802.1E Access Category */
+const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
+
+/* WME/802.1E Access Category to TX FIFO number */
+static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
+
+static bool in_send_q = false;
+
+/* Shared memory location index for various AC params */
+#define wme_shmemacindex(ac)	wme_ac2fifo[ac]
+
+#ifdef BCMDBG
+static const char *fifo_names[] = {
+	"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
+#else
+static const char fifo_names[6][0];
+#endif
+
+static const u8 acbitmap2maxprio[] = {
+	PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
+	PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
+	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
+	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
+};
+
+/* currently the best mechanism for determining SIFS is the band in use */
+#define SIFS(band) ((band)->bandtype == WLC_BAND_5G ? APHY_SIFS_TIME : BPHY_SIFS_TIME);
+
+/* value for # replay counters currently supported */
+#define WLC_REPLAY_CNTRS_VALUE	WPA_CAP_16_REPLAY_CNTRS
+
+/* local prototypes */
+static u16 BCMFASTPATH wlc_d11hdrs_mac80211(struct wlc_info *wlc,
+					       struct ieee80211_hw *hw,
+					       struct sk_buff *p,
+					       struct scb *scb, uint frag,
+					       uint nfrags, uint queue,
+					       uint next_frag_len,
+					       wsec_key_t *key,
+					       ratespec_t rspec_override);
+
+static void wlc_ctrupd_cache(u16 cur_stat, u16 *macstat_snapshot, u32 *macstat);
+static void wlc_bss_default_init(struct wlc_info *wlc);
+static void wlc_ucode_mac_upd(struct wlc_info *wlc);
+static ratespec_t mac80211_wlc_set_nrate(struct wlc_info *wlc,
+					 struct wlcband *cur_band, u32 int_val);
+static void wlc_tx_prec_map_init(struct wlc_info *wlc);
+static void wlc_watchdog(void *arg);
+static void wlc_watchdog_by_timer(void *arg);
+static u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate);
+static int wlc_set_rateset(struct wlc_info *wlc, wlc_rateset_t *rs_arg);
+static int wlc_iovar_rangecheck(struct wlc_info *wlc, u32 val,
+				const bcm_iovar_t *vi);
+static u8 wlc_local_constraint_qdbm(struct wlc_info *wlc);
+
+/* send and receive */
+static struct wlc_txq_info *wlc_txq_alloc(struct wlc_info *wlc);
+static void wlc_txq_free(struct wlc_info *wlc,
+			 struct wlc_txq_info *qi);
+static void wlc_txflowcontrol_signal(struct wlc_info *wlc,
+				     struct wlc_txq_info *qi,
+				     bool on, int prio);
+static void wlc_txflowcontrol_reset(struct wlc_info *wlc);
+static u16 wlc_compute_airtime(struct wlc_info *wlc, ratespec_t rspec,
+				  uint length);
+static void wlc_compute_cck_plcp(ratespec_t rate, uint length, u8 *plcp);
+static void wlc_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
+static void wlc_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
+static u16 wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate,
+				    u8 preamble_type, uint next_frag_len);
+static void wlc_recvctl(struct wlc_info *wlc,
+			d11rxhdr_t *rxh, struct sk_buff *p);
+static uint wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t rate,
+			       u8 preamble_type, uint dur);
+static uint wlc_calc_ack_time(struct wlc_info *wlc, ratespec_t rate,
+			      u8 preamble_type);
+static uint wlc_calc_cts_time(struct wlc_info *wlc, ratespec_t rate,
+			      u8 preamble_type);
+/* interrupt, up/down, band */
+static void wlc_setband(struct wlc_info *wlc, uint bandunit);
+static chanspec_t wlc_init_chanspec(struct wlc_info *wlc);
+static void wlc_bandinit_ordered(struct wlc_info *wlc, chanspec_t chanspec);
+static void wlc_bsinit(struct wlc_info *wlc);
+static int wlc_duty_cycle_set(struct wlc_info *wlc, int duty_cycle, bool isOFDM,
+			      bool writeToShm);
+static void wlc_radio_hwdisable_upd(struct wlc_info *wlc);
+static bool wlc_radio_monitor_start(struct wlc_info *wlc);
+static void wlc_radio_timer(void *arg);
+static void wlc_radio_enable(struct wlc_info *wlc);
+static void wlc_radio_upd(struct wlc_info *wlc);
+
+/* scan, association, BSS */
+static uint wlc_calc_ba_time(struct wlc_info *wlc, ratespec_t rate,
+			     u8 preamble_type);
+static void wlc_update_mimo_band_bwcap(struct wlc_info *wlc, u8 bwcap);
+static void wlc_ht_update_sgi_rx(struct wlc_info *wlc, int val);
+static void wlc_ht_update_ldpc(struct wlc_info *wlc, s8 val);
+static void wlc_war16165(struct wlc_info *wlc, bool tx);
+
+static void wlc_wme_retries_write(struct wlc_info *wlc);
+static bool wlc_attach_stf_ant_init(struct wlc_info *wlc);
+static uint wlc_attach_module(struct wlc_info *wlc);
+static void wlc_detach_module(struct wlc_info *wlc);
+static void wlc_timers_deinit(struct wlc_info *wlc);
+static void wlc_down_led_upd(struct wlc_info *wlc);
+static uint wlc_down_del_timer(struct wlc_info *wlc);
+static void wlc_ofdm_rateset_war(struct wlc_info *wlc);
+static int _wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
+		      struct wlc_if *wlcif);
+
+#if defined(BCMDBG)
+void wlc_get_rcmta(struct wlc_info *wlc, int idx, u8 *addr)
+{
+	d11regs_t *regs = wlc->regs;
+	u32 v32;
+
+	WL_TRACE("wl%d: %s\n", WLCWLUNIT(wlc), __func__);
+
+	W_REG(&regs->objaddr, (OBJADDR_RCMTA_SEL | (idx * 2)));
+	(void)R_REG(&regs->objaddr);
+	v32 = R_REG(&regs->objdata);
+	addr[0] = (u8) v32;
+	addr[1] = (u8) (v32 >> 8);
+	addr[2] = (u8) (v32 >> 16);
+	addr[3] = (u8) (v32 >> 24);
+	W_REG(&regs->objaddr, (OBJADDR_RCMTA_SEL | ((idx * 2) + 1)));
+	(void)R_REG(&regs->objaddr);
+	v32 = R_REG(&regs->objdata);
+	addr[4] = (u8) v32;
+	addr[5] = (u8) (v32 >> 8);
+}
+#endif				/* defined(BCMDBG) */
+
+/* keep the chip awake if needed */
+bool wlc_stay_awake(struct wlc_info *wlc)
+{
+	return true;
+}
+
+/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful
+ */
+bool wlc_ps_allowed(struct wlc_info *wlc)
+{
+	int idx;
+	struct wlc_bsscfg *cfg;
+
+	/* disallow PS when one of the following global conditions meets */
+	if (!wlc->pub->associated || !wlc->PMenabled || wlc->PM_override)
+		return false;
+
+	/* disallow PS when one of these meets when not scanning */
+	if (!wlc->PMblocked) {
+		if (AP_ACTIVE(wlc) || wlc->monitor)
+			return false;
+	}
+
+	FOREACH_AS_STA(wlc, idx, cfg) {
+		/* disallow PS when one of the following bsscfg specific conditions meets */
+		if (!cfg->BSS || !WLC_PORTOPEN(cfg))
+			return false;
+
+		if (!cfg->dtim_programmed)
+			return false;
+	}
+
+	return true;
+}
+
+void wlc_reset(struct wlc_info *wlc)
+{
+	WL_TRACE("wl%d: wlc_reset\n", wlc->pub->unit);
+
+	wlc->check_for_unaligned_tbtt = false;
+
+	/* slurp up hw mac counters before core reset */
+	wlc_statsupd(wlc);
+
+	/* reset our snapshot of macstat counters */
+	memset((char *)wlc->core->macstat_snapshot, 0,
+		sizeof(macstat_t));
+
+	wlc_bmac_reset(wlc->hw);
+	wlc_ampdu_reset(wlc->ampdu);
+	wlc->txretried = 0;
+
+}
+
+void wlc_fatal_error(struct wlc_info *wlc)
+{
+	WL_ERROR("wl%d: fatal error, reinitializing\n", wlc->pub->unit);
+	wl_init(wlc->wl);
+}
+
+/* Return the channel the driver should initialize during wlc_init.
+ * the channel may have to be changed from the currently configured channel
+ * if other configurations are in conflict (bandlocked, 11n mode disabled,
+ * invalid channel for current country, etc.)
+ */
+static chanspec_t wlc_init_chanspec(struct wlc_info *wlc)
+{
+	chanspec_t chanspec =
+	    1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
+	    WL_CHANSPEC_BAND_2G;
+
+	/* make sure the channel is on the supported band if we are band-restricted */
+	if (wlc->bandlocked || NBANDS(wlc) == 1) {
+		ASSERT(CHSPEC_WLCBANDUNIT(chanspec) == wlc->band->bandunit);
+	}
+	ASSERT(wlc_valid_chanspec_db(wlc->cmi, chanspec));
+	return chanspec;
+}
+
+struct scb global_scb;
+
+static void wlc_init_scb(struct wlc_info *wlc, struct scb *scb)
+{
+	int i;
+	scb->flags = SCB_WMECAP | SCB_HTCAP;
+	for (i = 0; i < NUMPRIO; i++)
+		scb->seqnum[i] = 0;
+}
+
+void wlc_init(struct wlc_info *wlc)
+{
+	d11regs_t *regs;
+	chanspec_t chanspec;
+	int i;
+	struct wlc_bsscfg *bsscfg;
+	bool mute = false;
+
+	WL_TRACE("wl%d: wlc_init\n", wlc->pub->unit);
+
+	regs = wlc->regs;
+
+	/* This will happen if a big-hammer was executed. In that case, we want to go back
+	 * to the channel that we were on and not new channel
+	 */
+	if (wlc->pub->associated)
+		chanspec = wlc->home_chanspec;
+	else
+		chanspec = wlc_init_chanspec(wlc);
+
+	wlc_bmac_init(wlc->hw, chanspec, mute);
+
+	wlc->seckeys = wlc_bmac_read_shm(wlc->hw, M_SECRXKEYS_PTR) * 2;
+	if (wlc->machwcap & MCAP_TKIPMIC)
+		wlc->tkmickeys =
+		    wlc_bmac_read_shm(wlc->hw, M_TKMICKEYS_PTR) * 2;
+
+	/* update beacon listen interval */
+	wlc_bcn_li_upd(wlc);
+	wlc->bcn_wait_prd =
+	    (u8) (wlc_bmac_read_shm(wlc->hw, M_NOSLPZNATDTIM) >> 10);
+	ASSERT(wlc->bcn_wait_prd > 0);
+
+	/* the world is new again, so is our reported rate */
+	wlc_reprate_init(wlc);
+
+	/* write ethernet address to core */
+	FOREACH_BSS(wlc, i, bsscfg) {
+		wlc_set_mac(bsscfg);
+		wlc_set_bssid(bsscfg);
+	}
+
+	/* Update tsf_cfprep if associated and up */
+	if (wlc->pub->associated) {
+		FOREACH_BSS(wlc, i, bsscfg) {
+			if (bsscfg->up) {
+				u32 bi;
+
+				/* get beacon period and convert to uS */
+				bi = bsscfg->current_bss->beacon_period << 10;
+				/*
+				 * update since init path would reset
+				 * to default value
+				 */
+				W_REG(&regs->tsf_cfprep,
+				      (bi << CFPREP_CBI_SHIFT));
+
+				/* Update maccontrol PM related bits */
+				wlc_set_ps_ctrl(wlc);
+
+				break;
+			}
+		}
+	}
+
+	wlc_key_hw_init_all(wlc);
+
+	wlc_bandinit_ordered(wlc, chanspec);
+
+	wlc_init_scb(wlc, &global_scb);
+
+	/* init probe response timeout */
+	wlc_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
+
+	/* init max burst txop (framebursting) */
+	wlc_write_shm(wlc, M_MBURST_TXOP,
+		      (wlc->
+		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
+
+	/* initialize maximum allowed duty cycle */
+	wlc_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
+	wlc_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
+
+	/* Update some shared memory locations related to max AMPDU size allowed to received */
+	wlc_ampdu_shm_upd(wlc->ampdu);
+
+	/* band-specific inits */
+	wlc_bsinit(wlc);
+
+	/* Enable EDCF mode (while the MAC is suspended) */
+	if (EDCF_ENAB(wlc->pub)) {
+		OR_REG(&regs->ifs_ctl, IFS_USEEDCF);
+		wlc_edcf_setparams(wlc->cfg, false);
+	}
+
+	/* Init precedence maps for empty FIFOs */
+	wlc_tx_prec_map_init(wlc);
+
+	/* read the ucode version if we have not yet done so */
+	if (wlc->ucode_rev == 0) {
+		wlc->ucode_rev =
+		    wlc_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
+		wlc->ucode_rev |= wlc_read_shm(wlc, M_BOM_REV_MINOR);
+	}
+
+	/* ..now really unleash hell (allow the MAC out of suspend) */
+	wlc_enable_mac(wlc);
+
+	/* clear tx flow control */
+	wlc_txflowcontrol_reset(wlc);
+
+	/* clear tx data fifo suspends */
+	wlc->tx_suspended = false;
+
+	/* enable the RF Disable Delay timer */
+	W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
+
+	/* initialize mpc delay */
+	wlc->mpc_delay_off = wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
+
+	/*
+	 * Initialize WME parameters; if they haven't been set by some other
+	 * mechanism (IOVar, etc) then read them from the hardware.
+	 */
+	if (WLC_WME_RETRY_SHORT_GET(wlc, 0) == 0) {	/* Uninitialized; read from HW */
+		int ac;
+
+		ASSERT(wlc->clk);
+		for (ac = 0; ac < AC_COUNT; ac++) {
+			wlc->wme_retries[ac] =
+			    wlc_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
+		}
+	}
+}
+
+void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc)
+{
+	wlc->bcnmisc_monitor = promisc;
+	wlc_mac_bcn_promisc(wlc);
+}
+
+void wlc_mac_bcn_promisc(struct wlc_info *wlc)
+{
+	if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
+	    wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
+		wlc_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
+	else
+		wlc_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
+}
+
+/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
+void wlc_mac_promisc(struct wlc_info *wlc)
+{
+	u32 promisc_bits = 0;
+
+	/* promiscuous mode just sets MCTL_PROMISC
+	 * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit
+	 * since all BSS data traffic is directed at the AP
+	 */
+	if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub) && !wlc->wet)
+		promisc_bits |= MCTL_PROMISC;
+
+	/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
+	 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
+	 * handled in wlc_mac_bcn_promisc()
+	 */
+	if (MONITOR_ENAB(wlc))
+		promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
+
+	wlc_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
+}
+
+/* check if hps and wake states of sw and hw are in sync */
+bool wlc_ps_check(struct wlc_info *wlc)
+{
+	bool res = true;
+	bool hps, wake;
+	bool wake_ok;
+
+	if (!AP_ACTIVE(wlc)) {
+		u32 tmp;
+		tmp = R_REG(&wlc->regs->maccontrol);
+
+		/*
+		 * If deviceremoved is detected, then don't take any action as
+		 * this can be called in any context. Assume that caller will
+		 * take care of the condition. This is just to avoid assert
+		 */
+		if (tmp == 0xffffffff) {
+			WL_ERROR("wl%d: %s: dead chip\n",
+				 wlc->pub->unit, __func__);
+			return DEVICEREMOVED(wlc);
+		}
+
+		hps = PS_ALLOWED(wlc);
+
+		if (hps != ((tmp & MCTL_HPS) != 0)) {
+			int idx;
+			struct wlc_bsscfg *cfg;
+			WL_ERROR("wl%d: hps not sync, sw %d, maccontrol 0x%x\n",
+				 wlc->pub->unit, hps, tmp);
+			FOREACH_BSS(wlc, idx, cfg) {
+				if (!BSSCFG_STA(cfg))
+					continue;
+			}
+
+			res = false;
+		}
+		/* For a monolithic build the wake check can be exact since it looks at wake
+		 * override bits. The MCTL_WAKE bit should match the 'wake' value.
+		 */
+		wake = STAY_AWAKE(wlc) || wlc->hw->wake_override;
+		wake_ok = (wake == ((tmp & MCTL_WAKE) != 0));
+		if (hps && !wake_ok) {
+			WL_ERROR("wl%d: wake not sync, sw %d maccontrol 0x%x\n",
+				 wlc->pub->unit, wake, tmp);
+			res = false;
+		}
+	}
+	ASSERT(res);
+	return res;
+}
+
+/* push sw hps and wake state through hardware */
+void wlc_set_ps_ctrl(struct wlc_info *wlc)
+{
+	u32 v1, v2;
+	bool hps, wake;
+	bool awake_before;
+
+	hps = PS_ALLOWED(wlc);
+	wake = hps ? (STAY_AWAKE(wlc)) : true;
+
+	WL_TRACE("wl%d: wlc_set_ps_ctrl: hps %d wake %d\n",
+		 wlc->pub->unit, hps, wake);
+
+	v1 = R_REG(&wlc->regs->maccontrol);
+	v2 = 0;
+	if (hps)
+		v2 |= MCTL_HPS;
+	if (wake)
+		v2 |= MCTL_WAKE;
+
+	wlc_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
+
+	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
+
+	if (wake && !awake_before)
+		wlc_bmac_wait_for_wake(wlc->hw);
+
+}
+
+/*
+ * Write this BSS config's MAC address to core.
+ * Updates RXE match engine.
+ */
+int wlc_set_mac(struct wlc_bsscfg *cfg)
+{
+	int err = 0;
+	struct wlc_info *wlc = cfg->wlc;
+
+	if (cfg == wlc->cfg) {
+		/* enter the MAC addr into the RXE match registers */
+		wlc_set_addrmatch(wlc, RCM_MAC_OFFSET, cfg->cur_etheraddr);
+	}
+
+	wlc_ampdu_macaddr_upd(wlc);
+
+	return err;
+}
+
+/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
+ * Updates RXE match engine.
+ */
+void wlc_set_bssid(struct wlc_bsscfg *cfg)
+{
+	struct wlc_info *wlc = cfg->wlc;
+
+	/* if primary config, we need to update BSSID in RXE match registers */
+	if (cfg == wlc->cfg) {
+		wlc_set_addrmatch(wlc, RCM_BSSID_OFFSET, cfg->BSSID);
+	}
+#ifdef SUPPORT_HWKEYS
+	else if (BSSCFG_STA(cfg) && cfg->BSS) {
+		wlc_rcmta_add_bssid(wlc, cfg);
+	}
+#endif
+}
+
+/*
+ * Suspend the the MAC and update the slot timing
+ * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
+ */
+void wlc_switch_shortslot(struct wlc_info *wlc, bool shortslot)
+{
+	int idx;
+	struct wlc_bsscfg *cfg;
+
+	ASSERT(wlc->band->gmode);
+
+	/* use the override if it is set */
+	if (wlc->shortslot_override != WLC_SHORTSLOT_AUTO)
+		shortslot = (wlc->shortslot_override == WLC_SHORTSLOT_ON);
+
+	if (wlc->shortslot == shortslot)
+		return;
+
+	wlc->shortslot = shortslot;
+
+	/* update the capability based on current shortslot mode */
+	FOREACH_BSS(wlc, idx, cfg) {
+		if (!cfg->associated)
+			continue;
+		cfg->current_bss->capability &=
+					~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+		if (wlc->shortslot)
+			cfg->current_bss->capability |=
+					WLAN_CAPABILITY_SHORT_SLOT_TIME;
+	}
+
+	wlc_bmac_set_shortslot(wlc->hw, shortslot);
+}
+
+static u8 wlc_local_constraint_qdbm(struct wlc_info *wlc)
+{
+	u8 local;
+	s16 local_max;
+
+	local = WLC_TXPWR_MAX;
+	if (wlc->pub->associated &&
+	    (wf_chspec_ctlchan(wlc->chanspec) ==
+	     wf_chspec_ctlchan(wlc->home_chanspec))) {
+
+		/* get the local power constraint if we are on the AP's
+		 * channel [802.11h, 7.3.2.13]
+		 */
+		/* Clamp the value between 0 and WLC_TXPWR_MAX w/o overflowing the target */
+		local_max =
+		    (wlc->txpwr_local_max -
+		     wlc->txpwr_local_constraint) * WLC_TXPWR_DB_FACTOR;
+		if (local_max > 0 && local_max < WLC_TXPWR_MAX)
+			return (u8) local_max;
+		if (local_max < 0)
+			return 0;
+	}
+
+	return local;
+}
+
+/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */
+void wlc_set_home_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
+{
+	if (wlc->home_chanspec != chanspec) {
+		int idx;
+		struct wlc_bsscfg *cfg;
+
+		wlc->home_chanspec = chanspec;
+
+		FOREACH_BSS(wlc, idx, cfg) {
+			if (!cfg->associated)
+				continue;
+
+			cfg->current_bss->chanspec = chanspec;
+		}
+
+	}
+}
+
+static void wlc_set_phy_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
+{
+	/* Save our copy of the chanspec */
+	wlc->chanspec = chanspec;
+
+	/* Set the chanspec and power limits for this locale after computing
+	 * any 11h local tx power constraints.
+	 */
+	wlc_channel_set_chanspec(wlc->cmi, chanspec,
+				 wlc_local_constraint_qdbm(wlc));
+
+	if (wlc->stf->ss_algosel_auto)
+		wlc_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
+					    chanspec);
+
+	wlc_stf_ss_update(wlc, wlc->band);
+
+}
+
+void wlc_set_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
+{
+	uint bandunit;
+	bool switchband = false;
+	chanspec_t old_chanspec = wlc->chanspec;
+
+	if (!wlc_valid_chanspec_db(wlc->cmi, chanspec)) {
+		WL_ERROR("wl%d: %s: Bad channel %d\n",
+			 wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
+		ASSERT(wlc_valid_chanspec_db(wlc->cmi, chanspec));
+		return;
+	}
+
+	/* Switch bands if necessary */
+	if (NBANDS(wlc) > 1) {
+		bandunit = CHSPEC_WLCBANDUNIT(chanspec);
+		if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
+			switchband = true;
+			if (wlc->bandlocked) {
+				WL_ERROR("wl%d: %s: chspec %d band is locked!\n",
+					 wlc->pub->unit, __func__,
+					 CHSPEC_CHANNEL(chanspec));
+				return;
+			}
+			/* BMAC_NOTE: should the setband call come after the wlc_bmac_chanspec() ?
+			 * if the setband updates (wlc_bsinit) use low level calls to inspect and
+			 * set state, the state inspected may be from the wrong band, or the
+			 * following wlc_bmac_set_chanspec() may undo the work.
+			 */
+			wlc_setband(wlc, bandunit);
+		}
+	}
+
+	ASSERT(N_ENAB(wlc->pub) || !CHSPEC_IS40(chanspec));
+
+	/* sync up phy/radio chanspec */
+	wlc_set_phy_chanspec(wlc, chanspec);
+
+	/* init antenna selection */
+	if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
+		wlc_antsel_init(wlc->asi);
+
+		/* Fix the hardware rateset based on bw.
+		 * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
+		 */
+		wlc_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
+					  wlc->band->
+					  mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
+					  : 0);
+	}
+
+	/* update some mac configuration since chanspec changed */
+	wlc_ucode_mac_upd(wlc);
+}
+
+#if defined(BCMDBG)
+static int wlc_get_current_txpwr(struct wlc_info *wlc, void *pwr, uint len)
+{
+	txpwr_limits_t txpwr;
+	tx_power_t power;
+	tx_power_legacy_t *old_power = NULL;
+	int r, c;
+	uint qdbm;
+	bool override;
+
+	if (len == sizeof(tx_power_legacy_t))
+		old_power = (tx_power_legacy_t *) pwr;
+	else if (len < sizeof(tx_power_t))
+		return BCME_BUFTOOSHORT;
+
+	memset(&power, 0, sizeof(tx_power_t));
+
+	power.chanspec = WLC_BAND_PI_RADIO_CHANSPEC;
+	if (wlc->pub->associated)
+		power.local_chanspec = wlc->home_chanspec;
+
+	/* Return the user target tx power limits for the various rates.  Note  wlc_phy.c's
+	 * public interface only implements getting and setting a single value for all of
+	 * rates, so we need to fill the array ourselves.
+	 */
+	wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
+	for (r = 0; r < WL_TX_POWER_RATES; r++) {
+		power.user_limit[r] = (u8) qdbm;
+	}
+
+	power.local_max = wlc->txpwr_local_max * WLC_TXPWR_DB_FACTOR;
+	power.local_constraint =
+	    wlc->txpwr_local_constraint * WLC_TXPWR_DB_FACTOR;
+
+	power.antgain[0] = wlc->bandstate[BAND_2G_INDEX]->antgain;
+	power.antgain[1] = wlc->bandstate[BAND_5G_INDEX]->antgain;
+
+	wlc_channel_reg_limits(wlc->cmi, power.chanspec, &txpwr);
+
+#if WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK
+#error "WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK"
+#endif
+
+	/* CCK tx power limits */
+	for (c = 0, r = WL_TX_POWER_CCK_FIRST; c < WL_TX_POWER_CCK_NUM;
+	     c++, r++)
+		power.reg_limit[r] = txpwr.cck[c];
+
+#if WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM
+#error "WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM"
+#endif
+
+	/* 20 MHz OFDM SISO tx power limits */
+	for (c = 0, r = WL_TX_POWER_OFDM_FIRST; c < WL_TX_POWER_OFDM_NUM;
+	     c++, r++)
+		power.reg_limit[r] = txpwr.ofdm[c];
+
+	if (WLC_PHY_11N_CAP(wlc->band)) {
+
+		/* 20 MHz OFDM CDD tx power limits */
+		for (c = 0, r = WL_TX_POWER_OFDM20_CDD_FIRST;
+		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
+			power.reg_limit[r] = txpwr.ofdm_cdd[c];
+
+		/* 40 MHz OFDM SISO tx power limits */
+		for (c = 0, r = WL_TX_POWER_OFDM40_SISO_FIRST;
+		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
+			power.reg_limit[r] = txpwr.ofdm_40_siso[c];
+
+		/* 40 MHz OFDM CDD tx power limits */
+		for (c = 0, r = WL_TX_POWER_OFDM40_CDD_FIRST;
+		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
+			power.reg_limit[r] = txpwr.ofdm_40_cdd[c];
+
+#if WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM
+#error "WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM"
+#endif
+
+		/* 20MHz MCS0-7 SISO tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS20_SISO_FIRST;
+		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_20_siso[c];
+
+		/* 20MHz MCS0-7 CDD tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS20_CDD_FIRST;
+		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_20_cdd[c];
+
+		/* 20MHz MCS0-7 STBC tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS20_STBC_FIRST;
+		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_20_stbc[c];
+
+		/* 40MHz MCS0-7 SISO tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS40_SISO_FIRST;
+		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_40_siso[c];
+
+		/* 40MHz MCS0-7 CDD tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS40_CDD_FIRST;
+		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_40_cdd[c];
+
+		/* 40MHz MCS0-7 STBC tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS40_STBC_FIRST;
+		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_40_stbc[c];
+
+#if WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM
+#error "WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM"
+#endif
+
+		/* 20MHz MCS8-15 SDM tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS20_SDM_FIRST;
+		     c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_20_mimo[c];
+
+		/* 40MHz MCS8-15 SDM tx power limits */
+		for (c = 0, r = WL_TX_POWER_MCS40_SDM_FIRST;
+		     c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
+			power.reg_limit[r] = txpwr.mcs_40_mimo[c];
+
+		/* MCS 32 */
+		power.reg_limit[WL_TX_POWER_MCS_32] = txpwr.mcs32;
+	}
+
+	wlc_phy_txpower_get_current(wlc->band->pi, &power,
+				    CHSPEC_CHANNEL(power.chanspec));
+
+	/* copy the tx_power_t struct to the return buffer,
+	 * or convert to a tx_power_legacy_t struct
+	 */
+	if (!old_power) {
+		memcpy(pwr, &power, sizeof(tx_power_t));
+	} else {
+		int band_idx = CHSPEC_IS2G(power.chanspec) ? 0 : 1;
+
+		memset(old_power, 0, sizeof(tx_power_legacy_t));
+
+		old_power->txpwr_local_max = power.local_max;
+		old_power->txpwr_local_constraint = power.local_constraint;
+		if (CHSPEC_IS2G(power.chanspec)) {
+			old_power->txpwr_chan_reg_max = txpwr.cck[0];
+			old_power->txpwr_est_Pout[band_idx] =
+			    power.est_Pout_cck;
+			old_power->txpwr_est_Pout_gofdm = power.est_Pout[0];
+		} else {
+			old_power->txpwr_chan_reg_max = txpwr.ofdm[0];
+			old_power->txpwr_est_Pout[band_idx] = power.est_Pout[0];
+		}
+		old_power->txpwr_antgain[0] = power.antgain[0];
+		old_power->txpwr_antgain[1] = power.antgain[1];
+
+		for (r = 0; r < NUM_PWRCTRL_RATES; r++) {
+			old_power->txpwr_band_max[r] = power.user_limit[r];
+			old_power->txpwr_limit[r] = power.reg_limit[r];
+			old_power->txpwr_target[band_idx][r] = power.target[r];
+			if (CHSPEC_IS2G(power.chanspec))
+				old_power->txpwr_bphy_cck_max[r] =
+				    power.board_limit[r];
+			else
+				old_power->txpwr_aphy_max[r] =
+				    power.board_limit[r];
+		}
+	}
+
+	return 0;
+}
+#endif				/* defined(BCMDBG) */
+
+static u32 wlc_watchdog_backup_bi(struct wlc_info *wlc)
+{
+	u32 bi;
+	bi = 2 * wlc->cfg->current_bss->dtim_period *
+	    wlc->cfg->current_bss->beacon_period;
+	if (wlc->bcn_li_dtim)
+		bi *= wlc->bcn_li_dtim;
+	else if (wlc->bcn_li_bcn)
+		/* recalculate bi based on bcn_li_bcn */
+		bi = 2 * wlc->bcn_li_bcn * wlc->cfg->current_bss->beacon_period;
+
+	if (bi < 2 * TIMER_INTERVAL_WATCHDOG)
+		bi = 2 * TIMER_INTERVAL_WATCHDOG;
+	return bi;
+}
+
+/* Change to run the watchdog either from a periodic timer or from tbtt handler.
+ * Call watchdog from tbtt handler if tbtt is true, watchdog timer otherwise.
+ */
+void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt)
+{
+	/* make sure changing watchdog driver is allowed */
+	if (!wlc->pub->up || !wlc->pub->align_wd_tbtt)
+		return;
+	if (!tbtt && wlc->WDarmed) {
+		wl_del_timer(wlc->wl, wlc->wdtimer);
+		wlc->WDarmed = false;
+	}
+
+	/* stop watchdog timer and use tbtt interrupt to drive watchdog */
+	if (tbtt && wlc->WDarmed) {
+		wl_del_timer(wlc->wl, wlc->wdtimer);
+		wlc->WDarmed = false;
+		wlc->WDlast = OSL_SYSUPTIME();
+	}
+	/* arm watchdog timer and drive the watchdog there */
+	else if (!tbtt && !wlc->WDarmed) {
+		wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
+			     true);
+		wlc->WDarmed = true;
+	}
+	if (tbtt && !wlc->WDarmed) {
+		wl_add_timer(wlc->wl, wlc->wdtimer, wlc_watchdog_backup_bi(wlc),
+			     true);
+		wlc->WDarmed = true;
+	}
+}
+
+ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc, wlc_rateset_t *rs)
+{
+	ratespec_t lowest_basic_rspec;
+	uint i;
+
+	/* Use the lowest basic rate */
+	lowest_basic_rspec = rs->rates[0] & RATE_MASK;
+	for (i = 0; i < rs->count; i++) {
+		if (rs->rates[i] & WLC_RATE_FLAG) {
+			lowest_basic_rspec = rs->rates[i] & RATE_MASK;
+			break;
+		}
+	}
+#if NCONF
+	/* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */
+	if (IS_OFDM(lowest_basic_rspec)) {
+		lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
+	}
+#endif
+
+	return lowest_basic_rspec;
+}
+
+/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant
+ * setting as per this table:
+ *  ratespec     CCK		ant = wlc->stf->txant
+ *  		OFDM		ant = 3
+ */
+void wlc_beacon_phytxctl_txant_upd(struct wlc_info *wlc, ratespec_t bcn_rspec)
+{
+	u16 phyctl;
+	u16 phytxant = wlc->stf->phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* for non-siso rates or default setting, use the available chains */
+	if (WLC_PHY_11N_CAP(wlc->band)) {
+		phytxant = wlc_stf_phytxchain_sel(wlc, bcn_rspec);
+	}
+
+	phyctl = wlc_read_shm(wlc, M_BCN_PCTLWD);
+	phyctl = (phyctl & ~mask) | phytxant;
+	wlc_write_shm(wlc, M_BCN_PCTLWD, phyctl);
+}
+
+/* centralized protection config change function to simplify debugging, no consistency checking
+ * this should be called only on changes to avoid overhead in periodic function
+*/
+void wlc_protection_upd(struct wlc_info *wlc, uint idx, int val)
+{
+	WL_TRACE("wlc_protection_upd: idx %d, val %d\n", idx, val);
+
+	switch (idx) {
+	case WLC_PROT_G_SPEC:
+		wlc->protection->_g = (bool) val;
+		break;
+	case WLC_PROT_G_OVR:
+		wlc->protection->g_override = (s8) val;
+		break;
+	case WLC_PROT_G_USER:
+		wlc->protection->gmode_user = (u8) val;
+		break;
+	case WLC_PROT_OVERLAP:
+		wlc->protection->overlap = (s8) val;
+		break;
+	case WLC_PROT_N_USER:
+		wlc->protection->nmode_user = (s8) val;
+		break;
+	case WLC_PROT_N_CFG:
+		wlc->protection->n_cfg = (s8) val;
+		break;
+	case WLC_PROT_N_CFG_OVR:
+		wlc->protection->n_cfg_override = (s8) val;
+		break;
+	case WLC_PROT_N_NONGF:
+		wlc->protection->nongf = (bool) val;
+		break;
+	case WLC_PROT_N_NONGF_OVR:
+		wlc->protection->nongf_override = (s8) val;
+		break;
+	case WLC_PROT_N_PAM_OVR:
+		wlc->protection->n_pam_override = (s8) val;
+		break;
+	case WLC_PROT_N_OBSS:
+		wlc->protection->n_obss = (bool) val;
+		break;
+
+	default:
+		ASSERT(0);
+		break;
+	}
+
+}
+
+static void wlc_ht_update_sgi_rx(struct wlc_info *wlc, int val)
+{
+	wlc->ht_cap.cap_info &= ~(IEEE80211_HT_CAP_SGI_20 |
+					IEEE80211_HT_CAP_SGI_40);
+	wlc->ht_cap.cap_info |= (val & WLC_N_SGI_20) ?
+					IEEE80211_HT_CAP_SGI_20 : 0;
+	wlc->ht_cap.cap_info |= (val & WLC_N_SGI_40) ?
+					IEEE80211_HT_CAP_SGI_40 : 0;
+
+	if (wlc->pub->up) {
+		wlc_update_beacon(wlc);
+		wlc_update_probe_resp(wlc, true);
+	}
+}
+
+static void wlc_ht_update_ldpc(struct wlc_info *wlc, s8 val)
+{
+	wlc->stf->ldpc = val;
+
+	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_LDPC_CODING;
+	if (wlc->stf->ldpc != OFF)
+		wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
+
+	if (wlc->pub->up) {
+		wlc_update_beacon(wlc);
+		wlc_update_probe_resp(wlc, true);
+		wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
+	}
+}
+
+/*
+ * ucode, hwmac update
+ *    Channel dependent updates for ucode and hw
+ */
+static void wlc_ucode_mac_upd(struct wlc_info *wlc)
+{
+	/* enable or disable any active IBSSs depending on whether or not
+	 * we are on the home channel
+	 */
+	if (wlc->home_chanspec == WLC_BAND_PI_RADIO_CHANSPEC) {
+		if (wlc->pub->associated) {
+			/* BMAC_NOTE: This is something that should be fixed in ucode inits.
+			 * I think that the ucode inits set up the bcn templates and shm values
+			 * with a bogus beacon. This should not be done in the inits. If ucode needs
+			 * to set up a beacon for testing, the test routines should write it down,
+			 * not expect the inits to populate a bogus beacon.
+			 */
+			if (WLC_PHY_11N_CAP(wlc->band)) {
+				wlc_write_shm(wlc, M_BCN_TXTSF_OFFSET,
+					      wlc->band->bcntsfoff);
+			}
+		}
+	} else {
+		/* disable an active IBSS if we are not on the home channel */
+	}
+
+	/* update the various promisc bits */
+	wlc_mac_bcn_promisc(wlc);
+	wlc_mac_promisc(wlc);
+}
+
+static void wlc_bandinit_ordered(struct wlc_info *wlc, chanspec_t chanspec)
+{
+	wlc_rateset_t default_rateset;
+	uint parkband;
+	uint i, band_order[2];
+
+	WL_TRACE("wl%d: wlc_bandinit_ordered\n", wlc->pub->unit);
+	/*
+	 * We might have been bandlocked during down and the chip power-cycled (hibernate).
+	 * figure out the right band to park on
+	 */
+	if (wlc->bandlocked || NBANDS(wlc) == 1) {
+		ASSERT(CHSPEC_WLCBANDUNIT(chanspec) == wlc->band->bandunit);
+
+		parkband = wlc->band->bandunit;	/* updated in wlc_bandlock() */
+		band_order[0] = band_order[1] = parkband;
+	} else {
+		/* park on the band of the specified chanspec */
+		parkband = CHSPEC_WLCBANDUNIT(chanspec);
+
+		/* order so that parkband initialize last */
+		band_order[0] = parkband ^ 1;
+		band_order[1] = parkband;
+	}
+
+	/* make each band operational, software state init */
+	for (i = 0; i < NBANDS(wlc); i++) {
+		uint j = band_order[i];
+
+		wlc->band = wlc->bandstate[j];
+
+		wlc_default_rateset(wlc, &default_rateset);
+
+		/* fill in hw_rate */
+		wlc_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
+				   false, WLC_RATES_CCK_OFDM, RATE_MASK,
+				   (bool) N_ENAB(wlc->pub));
+
+		/* init basic rate lookup */
+		wlc_rate_lookup_init(wlc, &default_rateset);
+	}
+
+	/* sync up phy/radio chanspec */
+	wlc_set_phy_chanspec(wlc, chanspec);
+}
+
+/* band-specific init */
+static void WLBANDINITFN(wlc_bsinit) (struct wlc_info *wlc)
+{
+	WL_TRACE("wl%d: wlc_bsinit: bandunit %d\n",
+		 wlc->pub->unit, wlc->band->bandunit);
+
+	/* write ucode ACK/CTS rate table */
+	wlc_set_ratetable(wlc);
+
+	/* update some band specific mac configuration */
+	wlc_ucode_mac_upd(wlc);
+
+	/* init antenna selection */
+	wlc_antsel_init(wlc->asi);
+
+}
+
+/* switch to and initialize new band */
+static void WLBANDINITFN(wlc_setband) (struct wlc_info *wlc, uint bandunit)
+{
+	int idx;
+	struct wlc_bsscfg *cfg;
+
+	ASSERT(NBANDS(wlc) > 1);
+	ASSERT(!wlc->bandlocked);
+	ASSERT(bandunit != wlc->band->bandunit || wlc->bandinit_pending);
+
+	wlc->band = wlc->bandstate[bandunit];
+
+	if (!wlc->pub->up)
+		return;
+
+	/* wait for at least one beacon before entering sleeping state */
+	wlc->PMawakebcn = true;
+	FOREACH_AS_STA(wlc, idx, cfg)
+	    cfg->PMawakebcn = true;
+	wlc_set_ps_ctrl(wlc);
+
+	/* band-specific initializations */
+	wlc_bsinit(wlc);
+}
+
+/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */
+void wlc_wme_initparams_sta(struct wlc_info *wlc, wme_param_ie_t *pe)
+{
+	static const wme_param_ie_t stadef = {
+		WME_OUI,
+		WME_TYPE,
+		WME_SUBTYPE_PARAM_IE,
+		WME_VER,
+		0,
+		0,
+		{
+		 {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
+		  cpu_to_le16(EDCF_AC_BE_TXOP_STA)},
+		 {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
+		  cpu_to_le16(EDCF_AC_BK_TXOP_STA)},
+		 {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
+		  cpu_to_le16(EDCF_AC_VI_TXOP_STA)},
+		 {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
+		  cpu_to_le16(EDCF_AC_VO_TXOP_STA)}
+		 }
+	};
+
+	ASSERT(sizeof(*pe) == WME_PARAM_IE_LEN);
+	memcpy(pe, &stadef, sizeof(*pe));
+}
+
+void wlc_wme_setparams(struct wlc_info *wlc, u16 aci, void *arg, bool suspend)
+{
+	int i;
+	shm_acparams_t acp_shm;
+	u16 *shm_entry;
+	struct ieee80211_tx_queue_params *params = arg;
+
+	ASSERT(wlc);
+
+	/* Only apply params if the core is out of reset and has clocks */
+	if (!wlc->clk) {
+		WL_ERROR("wl%d: %s : no-clock\n", wlc->pub->unit, __func__);
+		return;
+	}
+
+	/*
+	 * AP uses AC params from wme_param_ie_ap.
+	 * AP advertises AC params from wme_param_ie.
+	 * STA uses AC params from wme_param_ie.
+	 */
+
+	wlc->wme_admctl = 0;
+
+	do {
+		memset((char *)&acp_shm, 0, sizeof(shm_acparams_t));
+		/* find out which ac this set of params applies to */
+		ASSERT(aci < AC_COUNT);
+		/* set the admission control policy for this AC */
+		/* wlc->wme_admctl |= 1 << aci; *//* should be set ??  seems like off by default */
+
+		/* fill in shm ac params struct */
+		acp_shm.txop = le16_to_cpu(params->txop);
+		/* convert from units of 32us to us for ucode */
+		wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
+		    EDCF_TXOP2USEC(acp_shm.txop);
+		acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
+
+		if (aci == AC_VI && acp_shm.txop == 0
+		    && acp_shm.aifs < EDCF_AIFSN_MAX)
+			acp_shm.aifs++;
+
+		if (acp_shm.aifs < EDCF_AIFSN_MIN
+		    || acp_shm.aifs > EDCF_AIFSN_MAX) {
+			WL_ERROR("wl%d: wlc_edcf_setparams: bad aifs %d\n",
+				 wlc->pub->unit, acp_shm.aifs);
+			continue;
+		}
+
+		acp_shm.cwmin = params->cw_min;
+		acp_shm.cwmax = params->cw_max;
+		acp_shm.cwcur = acp_shm.cwmin;
+		acp_shm.bslots =
+		    R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
+		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
+		/* Indicate the new params to the ucode */
+		acp_shm.status = wlc_read_shm(wlc, (M_EDCF_QINFO +
+						    wme_shmemacindex(aci) *
+						    M_EDCF_QLEN +
+						    M_EDCF_STATUS_OFF));
+		acp_shm.status |= WME_STATUS_NEWAC;
+
+		/* Fill in shm acparam table */
+		shm_entry = (u16 *) &acp_shm;
+		for (i = 0; i < (int)sizeof(shm_acparams_t); i += 2)
+			wlc_write_shm(wlc,
+				      M_EDCF_QINFO +
+				      wme_shmemacindex(aci) * M_EDCF_QLEN + i,
+				      *shm_entry++);
+
+	} while (0);
+
+	if (suspend)
+		wlc_suspend_mac_and_wait(wlc);
+
+	if (suspend)
+		wlc_enable_mac(wlc);
+
+}
+
+void wlc_edcf_setparams(struct wlc_bsscfg *cfg, bool suspend)
+{
+	struct wlc_info *wlc = cfg->wlc;
+	uint aci, i, j;
+	edcf_acparam_t *edcf_acp;
+	shm_acparams_t acp_shm;
+	u16 *shm_entry;
+
+	ASSERT(cfg);
+	ASSERT(wlc);
+
+	/* Only apply params if the core is out of reset and has clocks */
+	if (!wlc->clk)
+		return;
+
+	/*
+	 * AP uses AC params from wme_param_ie_ap.
+	 * AP advertises AC params from wme_param_ie.
+	 * STA uses AC params from wme_param_ie.
+	 */
+
+	edcf_acp = (edcf_acparam_t *) &wlc->wme_param_ie.acparam[0];
+
+	wlc->wme_admctl = 0;
+
+	for (i = 0; i < AC_COUNT; i++, edcf_acp++) {
+		memset((char *)&acp_shm, 0, sizeof(shm_acparams_t));
+		/* find out which ac this set of params applies to */
+		aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
+		ASSERT(aci < AC_COUNT);
+		/* set the admission control policy for this AC */
+		if (edcf_acp->ACI & EDCF_ACM_MASK) {
+			wlc->wme_admctl |= 1 << aci;
+		}
+
+		/* fill in shm ac params struct */
+		acp_shm.txop = le16_to_cpu(edcf_acp->TXOP);
+		/* convert from units of 32us to us for ucode */
+		wlc->edcf_txop[aci] = acp_shm.txop =
+		    EDCF_TXOP2USEC(acp_shm.txop);
+		acp_shm.aifs = (edcf_acp->ACI & EDCF_AIFSN_MASK);
+
+		if (aci == AC_VI && acp_shm.txop == 0
+		    && acp_shm.aifs < EDCF_AIFSN_MAX)
+			acp_shm.aifs++;
+
+		if (acp_shm.aifs < EDCF_AIFSN_MIN
+		    || acp_shm.aifs > EDCF_AIFSN_MAX) {
+			WL_ERROR("wl%d: wlc_edcf_setparams: bad aifs %d\n",
+				 wlc->pub->unit, acp_shm.aifs);
+			continue;
+		}
+
+		/* CWmin = 2^(ECWmin) - 1 */
+		acp_shm.cwmin = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
+		/* CWmax = 2^(ECWmax) - 1 */
+		acp_shm.cwmax = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
+					    >> EDCF_ECWMAX_SHIFT);
+		acp_shm.cwcur = acp_shm.cwmin;
+		acp_shm.bslots =
+		    R_REG(&wlc->regs->tsf_random) & acp_shm.cwcur;
+		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
+		/* Indicate the new params to the ucode */
+		acp_shm.status = wlc_read_shm(wlc, (M_EDCF_QINFO +
+						    wme_shmemacindex(aci) *
+						    M_EDCF_QLEN +
+						    M_EDCF_STATUS_OFF));
+		acp_shm.status |= WME_STATUS_NEWAC;
+
+		/* Fill in shm acparam table */
+		shm_entry = (u16 *) &acp_shm;
+		for (j = 0; j < (int)sizeof(shm_acparams_t); j += 2)
+			wlc_write_shm(wlc,
+				      M_EDCF_QINFO +
+				      wme_shmemacindex(aci) * M_EDCF_QLEN + j,
+				      *shm_entry++);
+	}
+
+	if (suspend)
+		wlc_suspend_mac_and_wait(wlc);
+
+	if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
+		wlc_update_beacon(wlc);
+		wlc_update_probe_resp(wlc, false);
+	}
+
+	if (suspend)
+		wlc_enable_mac(wlc);
+
+}
+
+bool wlc_timers_init(struct wlc_info *wlc, int unit)
+{
+	wlc->wdtimer = wl_init_timer(wlc->wl, wlc_watchdog_by_timer,
+		wlc, "watchdog");
+	if (!wlc->wdtimer) {
+		WL_ERROR("wl%d:  wl_init_timer for wdtimer failed\n", unit);
+		goto fail;
+	}
+
+	wlc->radio_timer = wl_init_timer(wlc->wl, wlc_radio_timer,
+		wlc, "radio");
+	if (!wlc->radio_timer) {
+		WL_ERROR("wl%d:  wl_init_timer for radio_timer failed\n", unit);
+		goto fail;
+	}
+
+	return true;
+
+ fail:
+	return false;
+}
+
+/*
+ * Initialize wlc_info default values ...
+ * may get overrides later in this function
+ */
+void wlc_info_init(struct wlc_info *wlc, int unit)
+{
+	int i;
+	/* Assume the device is there until proven otherwise */
+	wlc->device_present = true;
+
+	/* set default power output percentage to 100 percent */
+	wlc->txpwr_percent = 100;
+
+	/* Save our copy of the chanspec */
+	wlc->chanspec = CH20MHZ_CHSPEC(1);
+
+	/* initialize CCK preamble mode to unassociated state */
+	wlc->shortpreamble = false;
+
+	wlc->legacy_probe = true;
+
+	/* various 802.11g modes */
+	wlc->shortslot = false;
+	wlc->shortslot_override = WLC_SHORTSLOT_AUTO;
+
+	wlc->barker_overlap_control = true;
+	wlc->barker_preamble = WLC_BARKER_SHORT_ALLOWED;
+	wlc->txburst_limit_override = AUTO;
+
+	wlc_protection_upd(wlc, WLC_PROT_G_OVR, WLC_PROTECTION_AUTO);
+	wlc_protection_upd(wlc, WLC_PROT_G_SPEC, false);
+
+	wlc_protection_upd(wlc, WLC_PROT_N_CFG_OVR, WLC_PROTECTION_AUTO);
+	wlc_protection_upd(wlc, WLC_PROT_N_CFG, WLC_N_PROTECTION_OFF);
+	wlc_protection_upd(wlc, WLC_PROT_N_NONGF_OVR, WLC_PROTECTION_AUTO);
+	wlc_protection_upd(wlc, WLC_PROT_N_NONGF, false);
+	wlc_protection_upd(wlc, WLC_PROT_N_PAM_OVR, AUTO);
+
+	wlc_protection_upd(wlc, WLC_PROT_OVERLAP, WLC_PROTECTION_CTL_OVERLAP);
+
+	/* 802.11g draft 4.0 NonERP elt advertisement */
+	wlc->include_legacy_erp = true;
+
+	wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
+	wlc->stf->txant = ANT_TX_DEF;
+
+	wlc->prb_resp_timeout = WLC_PRB_RESP_TIMEOUT;
+
+	wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
+	for (i = 0; i < NFIFO; i++)
+		wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
+	wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
+
+	/* default rate fallback retry limits */
+	wlc->SFBL = RETRY_SHORT_FB;
+	wlc->LFBL = RETRY_LONG_FB;
+
+	/* default mac retry limits */
+	wlc->SRL = RETRY_SHORT_DEF;
+	wlc->LRL = RETRY_LONG_DEF;
+
+	/* init PM state */
+	wlc->PM = PM_OFF;	/* User's setting of PM mode through IOCTL */
+	wlc->PM_override = false;	/* Prevents from going to PM if our AP is 'ill' */
+	wlc->PMenabled = false;	/* Current PM state */
+	wlc->PMpending = false;	/* Tracks whether STA indicated PM in the last attempt */
+	wlc->PMblocked = false;	/* To allow blocking going into PM during RM and scans */
+
+	/* In WMM Auto mode, PM is allowed if association is a UAPSD association */
+	wlc->WME_PM_blocked = false;
+
+	/* Init wme queuing method */
+	wlc->wme_prec_queuing = false;
+
+	/* Overrides for the core to stay awake under zillion conditions Look for STAY_AWAKE */
+	wlc->wake = false;
+	/* Are we waiting for a response to PS-Poll that we sent */
+	wlc->PSpoll = false;
+
+	/* APSD defaults */
+	wlc->wme_apsd = true;
+	wlc->apsd_sta_usp = false;
+	wlc->apsd_trigger_timeout = 0;	/* disable the trigger timer */
+	wlc->apsd_trigger_ac = AC_BITMAP_ALL;
+
+	/* Set flag to indicate that hw keys should be used when available. */
+	wlc->wsec_swkeys = false;
+
+	/* init the 4 static WEP default keys */
+	for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
+		wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
+		wlc->wsec_keys[i]->idx = (u8) i;
+	}
+
+	wlc->_regulatory_domain = false;	/* 802.11d */
+
+	/* WME QoS mode is Auto by default */
+	wlc->pub->_wme = AUTO;
+
+#ifdef BCMSDIODEV_ENABLED
+	wlc->pub->_priofc = true;	/* enable priority flow control for sdio dongle */
+#endif
+
+	wlc->pub->_ampdu = AMPDU_AGG_HOST;
+	wlc->pub->bcmerror = 0;
+	wlc->ibss_allowed = true;
+	wlc->ibss_coalesce_allowed = true;
+	wlc->pub->_coex = ON;
+
+	/* initialize mpc delay */
+	wlc->mpc_delay_off = wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
+
+	wlc->pr80838_war = true;
+}
+
+static bool wlc_state_bmac_sync(struct wlc_info *wlc)
+{
+	wlc_bmac_state_t state_bmac;
+
+	if (wlc_bmac_state_get(wlc->hw, &state_bmac) != 0)
+		return false;
+
+	wlc->machwcap = state_bmac.machwcap;
+	wlc_protection_upd(wlc, WLC_PROT_N_PAM_OVR,
+			   (s8) state_bmac.preamble_ovr);
+
+	return true;
+}
+
+static uint wlc_attach_module(struct wlc_info *wlc)
+{
+	uint err = 0;
+	uint unit;
+	unit = wlc->pub->unit;
+
+	wlc->asi = wlc_antsel_attach(wlc);
+	if (wlc->asi == NULL) {
+		WL_ERROR("wl%d: wlc_attach: wlc_antsel_attach failed\n", unit);
+		err = 44;
+		goto fail;
+	}
+
+	wlc->ampdu = wlc_ampdu_attach(wlc);
+	if (wlc->ampdu == NULL) {
+		WL_ERROR("wl%d: wlc_attach: wlc_ampdu_attach failed\n", unit);
+		err = 50;
+		goto fail;
+	}
+
+	if ((wlc_stf_attach(wlc) != 0)) {
+		WL_ERROR("wl%d: wlc_attach: wlc_stf_attach failed\n", unit);
+		err = 68;
+		goto fail;
+	}
+ fail:
+	return err;
+}
+
+struct wlc_pub *wlc_pub(void *wlc)
+{
+	return ((struct wlc_info *) wlc)->pub;
+}
+
+#define CHIP_SUPPORTS_11N(wlc) 	1
+
+/*
+ * The common driver entry routine. Error codes should be unique
+ */
+void *wlc_attach(void *wl, u16 vendor, u16 device, uint unit, bool piomode,
+		 void *regsva, uint bustype, void *btparam, uint *perr)
+{
+	struct wlc_info *wlc;
+	uint err = 0;
+	uint j;
+	struct wlc_pub *pub;
+	struct wlc_txq_info *qi;
+	uint n_disabled;
+
+	WL_NONE("wl%d: %s: vendor 0x%x device 0x%x\n",
+		unit, __func__, vendor, device);
+
+	ASSERT(WSEC_MAX_RCMTA_KEYS <= WSEC_MAX_KEYS);
+	ASSERT(WSEC_MAX_DEFAULT_KEYS == WLC_DEFAULT_KEYS);
+
+	/* some code depends on packed structures */
+	ASSERT(sizeof(struct ethhdr) == ETH_HLEN);
+	ASSERT(sizeof(d11regs_t) == SI_CORE_SIZE);
+	ASSERT(sizeof(ofdm_phy_hdr_t) == D11_PHY_HDR_LEN);
+	ASSERT(sizeof(cck_phy_hdr_t) == D11_PHY_HDR_LEN);
+	ASSERT(sizeof(d11txh_t) == D11_TXH_LEN);
+	ASSERT(sizeof(d11rxhdr_t) == RXHDR_LEN);
+	ASSERT(sizeof(struct ieee80211_hdr) == DOT11_A4_HDR_LEN);
+	ASSERT(sizeof(struct ieee80211_rts) == DOT11_RTS_LEN);
+	ASSERT(sizeof(tx_status_t) == TXSTATUS_LEN);
+	ASSERT(sizeof(struct ieee80211_ht_cap) == HT_CAP_IE_LEN);
+#ifdef BRCM_FULLMAC
+	ASSERT(offsetof(wl_scan_params_t, channel_list) ==
+	       WL_SCAN_PARAMS_FIXED_SIZE);
+#endif
+	ASSERT(IS_ALIGNED(offsetof(wsec_key_t, data), sizeof(u32)));
+	ASSERT(ISPOWEROF2(MA_WINDOW_SZ));
+
+	ASSERT(sizeof(wlc_d11rxhdr_t) <= WL_HWRXOFF);
+
+	/*
+	 * Number of replay counters value used in WPA IE must match # rxivs
+	 * supported in wsec_key_t struct. See 802.11i/D3.0 sect. 7.3.2.17
+	 * 'RSN Information Element' figure 8 for this mapping.
+	 */
+	ASSERT((WPA_CAP_16_REPLAY_CNTRS == WLC_REPLAY_CNTRS_VALUE
+		&& 16 == WLC_NUMRXIVS)
+	       || (WPA_CAP_4_REPLAY_CNTRS == WLC_REPLAY_CNTRS_VALUE
+		   && 4 == WLC_NUMRXIVS));
+
+	/* allocate struct wlc_info state and its substructures */
+	wlc = (struct wlc_info *) wlc_attach_malloc(unit, &err, device);
+	if (wlc == NULL)
+		goto fail;
+	pub = wlc->pub;
+
+#if defined(BCMDBG)
+	wlc_info_dbg = wlc;
+#endif
+
+	wlc->band = wlc->bandstate[0];
+	wlc->core = wlc->corestate;
+	wlc->wl = wl;
+	pub->unit = unit;
+	wlc->btparam = btparam;
+	pub->_piomode = piomode;
+	wlc->bandinit_pending = false;
+	/* By default restrict TKIP associations from 11n STA's */
+	wlc->ht_wsec_restriction = WLC_HT_TKIP_RESTRICT;
+
+	/* populate struct wlc_info with default values  */
+	wlc_info_init(wlc, unit);
+
+	/* update sta/ap related parameters */
+	wlc_ap_upd(wlc);
+
+	/* 11n_disable nvram */
+	n_disabled = getintvar(pub->vars, "11n_disable");
+
+	/* register a module (to handle iovars) */
+	wlc_module_register(wlc->pub, wlc_iovars, "wlc_iovars", wlc,
+			    wlc_doiovar, NULL, NULL);
+
+	/*
+	 * low level attach steps(all hw accesses go
+	 * inside, no more in rest of the attach)
+	 */
+	err = wlc_bmac_attach(wlc, vendor, device, unit, piomode, regsva,
+			      bustype, btparam);
+	if (err)
+		goto fail;
+
+	/* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split,
+	 * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver
+	 */
+	if (!wlc_state_bmac_sync(wlc)) {
+		err = 20;
+		goto fail;
+	}
+
+	pub->phy_11ncapable = WLC_PHY_11N_CAP(wlc->band);
+
+	/* propagate *vars* from BMAC driver to high driver */
+	wlc_bmac_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
+
+
+	/* set maximum allowed duty cycle */
+	wlc->tx_duty_cycle_ofdm =
+	    (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
+	wlc->tx_duty_cycle_cck =
+	    (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
+
+	wlc_stf_phy_chain_calc(wlc);
+
+	/* txchain 1: txant 0, txchain 2: txant 1 */
+	if (WLCISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+		wlc->stf->txant = wlc->stf->hw_txchain - 1;
+
+	/* push to BMAC driver */
+	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
+			       wlc->stf->hw_rxchain);
+
+	/* pull up some info resulting from the low attach */
+	{
+		int i;
+		for (i = 0; i < NFIFO; i++)
+			wlc->core->txavail[i] = wlc->hw->txavail[i];
+	}
+
+	wlc_bmac_hw_etheraddr(wlc->hw, wlc->perm_etheraddr);
+
+	memcpy(&pub->cur_etheraddr, &wlc->perm_etheraddr, ETH_ALEN);
+
+	for (j = 0; j < NBANDS(wlc); j++) {
+		/* Use band 1 for single band 11a */
+		if (IS_SINGLEBAND_5G(wlc->deviceid))
+			j = BAND_5G_INDEX;
+
+		wlc->band = wlc->bandstate[j];
+
+		if (!wlc_attach_stf_ant_init(wlc)) {
+			err = 24;
+			goto fail;
+		}
+
+		/* default contention windows size limits */
+		wlc->band->CWmin = APHY_CWMIN;
+		wlc->band->CWmax = PHY_CWMAX;
+
+		/* init gmode value */
+		if (BAND_2G(wlc->band->bandtype)) {
+			wlc->band->gmode = GMODE_AUTO;
+			wlc_protection_upd(wlc, WLC_PROT_G_USER,
+					   wlc->band->gmode);
+		}
+
+		/* init _n_enab supported mode */
+		if (WLC_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
+			if (n_disabled & WLFEATURE_DISABLE_11N) {
+				pub->_n_enab = OFF;
+				wlc_protection_upd(wlc, WLC_PROT_N_USER, OFF);
+			} else {
+				pub->_n_enab = SUPPORT_11N;
+				wlc_protection_upd(wlc, WLC_PROT_N_USER,
+						   ((pub->_n_enab ==
+						     SUPPORT_11N) ? WL_11N_2x2 :
+						    WL_11N_3x3));
+			}
+		}
+
+		/* init per-band default rateset, depend on band->gmode */
+		wlc_default_rateset(wlc, &wlc->band->defrateset);
+
+		/* fill in hw_rateset (used early by WLC_SET_RATESET) */
+		wlc_rateset_filter(&wlc->band->defrateset,
+				   &wlc->band->hw_rateset, false,
+				   WLC_RATES_CCK_OFDM, RATE_MASK,
+				   (bool) N_ENAB(wlc->pub));
+	}
+
+	/* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */
+	wlc_stf_phy_txant_upd(wlc);
+
+	/* attach each modules */
+	err = wlc_attach_module(wlc);
+	if (err != 0)
+		goto fail;
+
+	if (!wlc_timers_init(wlc, unit)) {
+		WL_ERROR("wl%d: %s: wlc_init_timer failed\n", unit, __func__);
+		err = 32;
+		goto fail;
+	}
+
+	/* depend on rateset, gmode */
+	wlc->cmi = wlc_channel_mgr_attach(wlc);
+	if (!wlc->cmi) {
+		WL_ERROR("wl%d: %s: wlc_channel_mgr_attach failed\n",
+			 unit, __func__);
+		err = 33;
+		goto fail;
+	}
+
+	/* init default when all parameters are ready, i.e. ->rateset */
+	wlc_bss_default_init(wlc);
+
+	/*
+	 * Complete the wlc default state initializations..
+	 */
+
+	/* allocate our initial queue */
+	qi = wlc_txq_alloc(wlc);
+	if (qi == NULL) {
+		WL_ERROR("wl%d: %s: failed to malloc tx queue\n",
+			 unit, __func__);
+		err = 100;
+		goto fail;
+	}
+	wlc->active_queue = qi;
+
+	wlc->bsscfg[0] = wlc->cfg;
+	wlc->cfg->_idx = 0;
+	wlc->cfg->wlc = wlc;
+	pub->txmaxpkts = MAXTXPKTS;
+
+	pub->_cnt->version = WL_CNT_T_VERSION;
+	pub->_cnt->length = sizeof(struct wl_cnt);
+
+	WLCNTSET(pub->_wme_cnt->version, WL_WME_CNT_VERSION);
+	WLCNTSET(pub->_wme_cnt->length, sizeof(wl_wme_cnt_t));
+
+	wlc_wme_initparams_sta(wlc, &wlc->wme_param_ie);
+
+	wlc->mimoft = FT_HT;
+	wlc->ht_cap.cap_info = HT_CAP;
+	if (HT_ENAB(wlc->pub))
+		wlc->stf->ldpc = AUTO;
+
+	wlc->mimo_40txbw = AUTO;
+	wlc->ofdm_40txbw = AUTO;
+	wlc->cck_40txbw = AUTO;
+	wlc_update_mimo_band_bwcap(wlc, WLC_N_BW_20IN2G_40IN5G);
+
+	/* Enable setting the RIFS Mode bit by default in HT Info IE */
+	wlc->rifs_advert = AUTO;
+
+	/* Set default values of SGI */
+	if (WLC_SGI_CAP_PHY(wlc)) {
+		wlc_ht_update_sgi_rx(wlc, (WLC_N_SGI_20 | WLC_N_SGI_40));
+		wlc->sgi_tx = AUTO;
+	} else if (WLCISSSLPNPHY(wlc->band)) {
+		wlc_ht_update_sgi_rx(wlc, (WLC_N_SGI_20 | WLC_N_SGI_40));
+		wlc->sgi_tx = AUTO;
+	} else {
+		wlc_ht_update_sgi_rx(wlc, 0);
+		wlc->sgi_tx = OFF;
+	}
+
+	/* *******nvram 11n config overrides Start ********* */
+
+	/* apply the sgi override from nvram conf */
+	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
+		wlc->sgi_tx = OFF;
+
+	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
+		wlc_ht_update_sgi_rx(wlc, 0);
+
+	/* apply the stbc override from nvram conf */
+	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
+		wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
+		wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
+		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
+	}
+	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
+		wlc_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
+
+	/* apply the GF override from nvram conf */
+	if (n_disabled & WLFEATURE_DISABLE_11N_GF)
+		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_GRN_FLD;
+
+	/* initialize radio_mpc_disable according to wlc->mpc */
+	wlc_radio_mpc_upd(wlc);
+
+	if ((wlc->pub->sih->chip) == BCM43235_CHIP_ID) {
+		if ((getintvar(wlc->pub->vars, "aa2g") == 7) ||
+		    (getintvar(wlc->pub->vars, "aa5g") == 7)) {
+			wlc_bmac_antsel_set(wlc->hw, 1);
+		}
+	} else {
+		wlc_bmac_antsel_set(wlc->hw, wlc->asi->antsel_avail);
+	}
+
+	if (perr)
+		*perr = 0;
+
+	return (void *)wlc;
+
+ fail:
+	WL_ERROR("wl%d: %s: failed with err %d\n", unit, __func__, err);
+	if (wlc)
+		wlc_detach(wlc);
+
+	if (perr)
+		*perr = err;
+	return NULL;
+}
+
+static void wlc_attach_antgain_init(struct wlc_info *wlc)
+{
+	uint unit;
+	unit = wlc->pub->unit;
+
+	if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
+		/* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
+		wlc->band->antgain = 8;
+	} else if (wlc->band->antgain == -1) {
+		WL_ERROR("wl%d: %s: Invalid antennas available in srom, using 2dB\n",
+			 unit, __func__);
+		wlc->band->antgain = 8;
+	} else {
+		s8 gain, fract;
+		/* Older sroms specified gain in whole dbm only.  In order
+		 * be able to specify qdbm granularity and remain backward compatible
+		 * the whole dbms are now encoded in only low 6 bits and remaining qdbms
+		 * are encoded in the hi 2 bits. 6 bit signed number ranges from
+		 * -32 - 31. Examples: 0x1 = 1 db,
+		 * 0xc1 = 1.75 db (1 + 3 quarters),
+		 * 0x3f = -1 (-1 + 0 quarters),
+		 * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm.
+		 * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm.
+		 */
+		gain = wlc->band->antgain & 0x3f;
+		gain <<= 2;	/* Sign extend */
+		gain >>= 2;
+		fract = (wlc->band->antgain & 0xc0) >> 6;
+		wlc->band->antgain = 4 * gain + fract;
+	}
+}
+
+static bool wlc_attach_stf_ant_init(struct wlc_info *wlc)
+{
+	int aa;
+	uint unit;
+	char *vars;
+	int bandtype;
+
+	unit = wlc->pub->unit;
+	vars = wlc->pub->vars;
+	bandtype = wlc->band->bandtype;
+
+	/* get antennas available */
+	aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
+	if (aa == 0)
+		aa = (s8) getintvar(vars,
+				      (BAND_5G(bandtype) ? "aa1" : "aa0"));
+	if ((aa < 1) || (aa > 15)) {
+		WL_ERROR("wl%d: %s: Invalid antennas available in srom (0x%x), using 3\n",
+			 unit, __func__, aa);
+		aa = 3;
+	}
+
+	/* reset the defaults if we have a single antenna */
+	if (aa == 1) {
+		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
+		wlc->stf->txant = ANT_TX_FORCE_0;
+	} else if (aa == 2) {
+		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
+		wlc->stf->txant = ANT_TX_FORCE_1;
+	} else {
+	}
+
+	/* Compute Antenna Gain */
+	wlc->band->antgain =
+	    (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
+	wlc_attach_antgain_init(wlc);
+
+	return true;
+}
+
+
+static void wlc_timers_deinit(struct wlc_info *wlc)
+{
+	/* free timer state */
+	if (wlc->wdtimer) {
+		wl_free_timer(wlc->wl, wlc->wdtimer);
+		wlc->wdtimer = NULL;
+	}
+	if (wlc->radio_timer) {
+		wl_free_timer(wlc->wl, wlc->radio_timer);
+		wlc->radio_timer = NULL;
+	}
+}
+
+static void wlc_detach_module(struct wlc_info *wlc)
+{
+	if (wlc->asi) {
+		wlc_antsel_detach(wlc->asi);
+		wlc->asi = NULL;
+	}
+
+	if (wlc->ampdu) {
+		wlc_ampdu_detach(wlc->ampdu);
+		wlc->ampdu = NULL;
+	}
+
+	wlc_stf_detach(wlc);
+}
+
+/*
+ * Return a count of the number of driver callbacks still pending.
+ *
+ * General policy is that wlc_detach can only dealloc/free software states. It can NOT
+ *  touch hardware registers since the d11core may be in reset and clock may not be available.
+ *    One exception is sb register access, which is possible if crystal is turned on
+ * After "down" state, driver should avoid software timer with the exception of radio_monitor.
+ */
+uint wlc_detach(struct wlc_info *wlc)
+{
+	uint i;
+	uint callbacks = 0;
+
+	if (wlc == NULL)
+		return 0;
+
+	WL_TRACE("wl%d: %s\n", wlc->pub->unit, __func__);
+
+	ASSERT(!wlc->pub->up);
+
+	callbacks += wlc_bmac_detach(wlc);
+
+	/* delete software timers */
+	if (!wlc_radio_monitor_stop(wlc))
+		callbacks++;
+
+	wlc_channel_mgr_detach(wlc->cmi);
+
+	wlc_timers_deinit(wlc);
+
+	wlc_detach_module(wlc);
+
+	/* free other state */
+
+
+#ifdef BCMDBG
+	kfree(wlc->country_ie_override);
+	wlc->country_ie_override = NULL;
+#endif				/* BCMDBG */
+
+	{
+		/* free dumpcb list */
+		struct dumpcb_s *prev, *ptr;
+		prev = ptr = wlc->dumpcb_head;
+		while (ptr) {
+			ptr = prev->next;
+			kfree(prev);
+			prev = ptr;
+		}
+		wlc->dumpcb_head = NULL;
+	}
+
+	/* Detach from iovar manager */
+	wlc_module_unregister(wlc->pub, "wlc_iovars", wlc);
+
+	while (wlc->tx_queues != NULL)
+		wlc_txq_free(wlc, wlc->tx_queues);
+
+	/*
+	 * consistency check: wlc_module_register/wlc_module_unregister calls
+	 * should match therefore nothing should be left here.
+	 */
+	for (i = 0; i < WLC_MAXMODULES; i++)
+		ASSERT(wlc->modulecb[i].name[0] == '\0');
+
+	wlc_detach_mfree(wlc);
+	return callbacks;
+}
+
+/* update state that depends on the current value of "ap" */
+void wlc_ap_upd(struct wlc_info *wlc)
+{
+	if (AP_ENAB(wlc->pub))
+		wlc->PLCPHdr_override = WLC_PLCP_AUTO;	/* AP: short not allowed, but not enforced */
+	else
+		wlc->PLCPHdr_override = WLC_PLCP_SHORT;	/* STA-BSS; short capable */
+
+	/* disable vlan_mode on AP since some legacy STAs cannot rx tagged pkts */
+	wlc->vlan_mode = AP_ENAB(wlc->pub) ? OFF : AUTO;
+
+	/* fixup mpc */
+	wlc->mpc = true;
+}
+
+/* read hwdisable state and propagate to wlc flag */
+static void wlc_radio_hwdisable_upd(struct wlc_info *wlc)
+{
+	if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
+		return;
+
+	if (wlc_bmac_radio_read_hwdisabled(wlc->hw)) {
+		mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+	} else {
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
+	}
+}
+
+/* return true if Minimum Power Consumption should be entered, false otherwise */
+bool wlc_is_non_delay_mpc(struct wlc_info *wlc)
+{
+	return false;
+}
+
+bool wlc_ismpc(struct wlc_info *wlc)
+{
+	return (wlc->mpc_delay_off == 0) && (wlc_is_non_delay_mpc(wlc));
+}
+
+void wlc_radio_mpc_upd(struct wlc_info *wlc)
+{
+	bool mpc_radio, radio_state;
+
+	/*
+	 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
+	 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
+	 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
+	 * the radio is going down.
+	 */
+	if (!wlc->mpc) {
+		if (!wlc->pub->radio_disabled)
+			return;
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+		wlc_radio_upd(wlc);
+		if (!wlc->pub->radio_disabled)
+			wlc_radio_monitor_stop(wlc);
+		return;
+	}
+
+	/*
+	 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled
+	 * to go ON, always call radio_upd synchronously
+	 * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog)
+	 */
+	radio_state =
+	    (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
+	     ON);
+	mpc_radio = (wlc_ismpc(wlc) == true) ? OFF : ON;
+
+	if (radio_state == ON && mpc_radio == OFF)
+		wlc->mpc_delay_off = wlc->mpc_dlycnt;
+	else if (radio_state == OFF && mpc_radio == ON) {
+		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
+		wlc_radio_upd(wlc);
+		if (wlc->mpc_offcnt < WLC_MPC_THRESHOLD) {
+			wlc->mpc_dlycnt = WLC_MPC_MAX_DELAYCNT;
+		} else
+			wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
+		wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
+	}
+	/* Below logic is meant to capture the transition from mpc off to mpc on for reasons
+	 * other than wlc->mpc_delay_off keeping the mpc off. In that case reset
+	 * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
+	 */
+	if ((wlc->prev_non_delay_mpc == false) &&
+	    (wlc_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) {
+		wlc->mpc_delay_off = wlc->mpc_dlycnt;
+	}
+	wlc->prev_non_delay_mpc = wlc_is_non_delay_mpc(wlc);
+}
+
+/*
+ * centralized radio disable/enable function,
+ * invoke radio enable/disable after updating hwradio status
+ */
+static void wlc_radio_upd(struct wlc_info *wlc)
+{
+	if (wlc->pub->radio_disabled) {
+		wlc_radio_disable(wlc);
+	} else {
+		wlc_radio_enable(wlc);
+	}
+}
+
+/* maintain LED behavior in down state */
+static void wlc_down_led_upd(struct wlc_info *wlc)
+{
+	ASSERT(!wlc->pub->up);
+
+	/* maintain LEDs while in down state, turn on sbclk if not available yet */
+	/* turn on sbclk if necessary */
+	if (!AP_ENAB(wlc->pub)) {
+		wlc_pllreq(wlc, true, WLC_PLLREQ_FLIP);
+
+		wlc_pllreq(wlc, false, WLC_PLLREQ_FLIP);
+	}
+}
+
+/* update hwradio status and return it */
+bool wlc_check_radio_disabled(struct wlc_info *wlc)
+{
+	wlc_radio_hwdisable_upd(wlc);
+
+	return mboolisset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE) ? true : false;
+}
+
+void wlc_radio_disable(struct wlc_info *wlc)
+{
+	if (!wlc->pub->up) {
+		wlc_down_led_upd(wlc);
+		return;
+	}
+
+	wlc_radio_monitor_start(wlc);
+	wl_down(wlc->wl);
+}
+
+static void wlc_radio_enable(struct wlc_info *wlc)
+{
+	if (wlc->pub->up)
+		return;
+
+	if (DEVICEREMOVED(wlc))
+		return;
+
+	if (!wlc->down_override) {	/* imposed by wl down/out ioctl */
+		wl_up(wlc->wl);
+	}
+}
+
+/* periodical query hw radio button while driver is "down" */
+static void wlc_radio_timer(void *arg)
+{
+	struct wlc_info *wlc = (struct wlc_info *) arg;
+
+	if (DEVICEREMOVED(wlc)) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc->pub->unit, __func__);
+		wl_down(wlc->wl);
+		return;
+	}
+
+	/* cap mpc off count */
+	if (wlc->mpc_offcnt < WLC_MPC_MAX_DELAYCNT)
+		wlc->mpc_offcnt++;
+
+	/* validate all the reasons driver could be down and running this radio_timer */
+	ASSERT(wlc->pub->radio_disabled || wlc->down_override);
+	wlc_radio_hwdisable_upd(wlc);
+	wlc_radio_upd(wlc);
+}
+
+static bool wlc_radio_monitor_start(struct wlc_info *wlc)
+{
+	/* Don't start the timer if HWRADIO feature is disabled */
+	if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
+		return true;
+
+	wlc->radio_monitor = true;
+	wlc_pllreq(wlc, true, WLC_PLLREQ_RADIO_MON);
+	wl_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
+	return true;
+}
+
+bool wlc_radio_monitor_stop(struct wlc_info *wlc)
+{
+	if (!wlc->radio_monitor)
+		return true;
+
+	ASSERT((wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO) !=
+	       WL_SWFL_NOHWRADIO);
+
+	wlc->radio_monitor = false;
+	wlc_pllreq(wlc, false, WLC_PLLREQ_RADIO_MON);
+	return wl_del_timer(wlc->wl, wlc->radio_timer);
+}
+
+/* bring the driver down, but don't reset hardware */
+void wlc_out(struct wlc_info *wlc)
+{
+	wlc_bmac_set_noreset(wlc->hw, true);
+	wlc_radio_upd(wlc);
+	wl_down(wlc->wl);
+	wlc_bmac_set_noreset(wlc->hw, false);
+
+	/* core clk is true in BMAC driver due to noreset, need to mirror it in HIGH */
+	wlc->clk = true;
+
+	/* This will make sure that when 'up' is done
+	 * after 'out' it'll restore hardware (especially gpios)
+	 */
+	wlc->pub->hw_up = false;
+}
+
+#if defined(BCMDBG)
+/* Verify the sanity of wlc->tx_prec_map. This can be done only by making sure that
+ * if there is no packet pending for the FIFO, then the corresponding prec bits should be set
+ * in prec_map. Of course, ignore this rule when block_datafifo is set
+ */
+static bool wlc_tx_prec_map_verify(struct wlc_info *wlc)
+{
+	/* For non-WME, both fifos have overlapping prec_map. So it's an error only if both
+	 * fail the check.
+	 */
+	if (!EDCF_ENAB(wlc->pub)) {
+		if (!(WLC_TX_FIFO_CHECK(wlc, TX_DATA_FIFO) ||
+		      WLC_TX_FIFO_CHECK(wlc, TX_CTL_FIFO)))
+			return false;
+		else
+			return true;
+	}
+
+	return WLC_TX_FIFO_CHECK(wlc, TX_AC_BK_FIFO)
+		&& WLC_TX_FIFO_CHECK(wlc, TX_AC_BE_FIFO)
+		&& WLC_TX_FIFO_CHECK(wlc, TX_AC_VI_FIFO)
+		&& WLC_TX_FIFO_CHECK(wlc, TX_AC_VO_FIFO);
+}
+#endif				/* BCMDBG */
+
+static void wlc_watchdog_by_timer(void *arg)
+{
+	struct wlc_info *wlc = (struct wlc_info *) arg;
+	wlc_watchdog(arg);
+	if (WLC_WATCHDOG_TBTT(wlc)) {
+		/* set to normal osl watchdog period */
+		wl_del_timer(wlc->wl, wlc->wdtimer);
+		wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
+			     true);
+	}
+}
+
+/* common watchdog code */
+static void wlc_watchdog(void *arg)
+{
+	struct wlc_info *wlc = (struct wlc_info *) arg;
+	int i;
+	struct wlc_bsscfg *cfg;
+
+	WL_TRACE("wl%d: wlc_watchdog\n", wlc->pub->unit);
+
+	if (!wlc->pub->up)
+		return;
+
+	if (DEVICEREMOVED(wlc)) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc->pub->unit, __func__);
+		wl_down(wlc->wl);
+		return;
+	}
+
+	/* increment second count */
+	wlc->pub->now++;
+
+	/* delay radio disable */
+	if (wlc->mpc_delay_off) {
+		if (--wlc->mpc_delay_off == 0) {
+			mboolset(wlc->pub->radio_disabled,
+				 WL_RADIO_MPC_DISABLE);
+			if (wlc->mpc && wlc_ismpc(wlc))
+				wlc->mpc_offcnt = 0;
+			wlc->mpc_laston_ts = OSL_SYSUPTIME();
+		}
+	}
+
+	/* mpc sync */
+	wlc_radio_mpc_upd(wlc);
+	/* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
+	wlc_radio_hwdisable_upd(wlc);
+	wlc_radio_upd(wlc);
+	/* if ismpc, driver should be in down state if up/down is allowed */
+	if (wlc->mpc && wlc_ismpc(wlc))
+		ASSERT(!wlc->pub->up);
+	/* if radio is disable, driver may be down, quit here */
+	if (wlc->pub->radio_disabled)
+		return;
+
+	wlc_bmac_watchdog(wlc);
+
+	/* occasionally sample mac stat counters to detect 16-bit counter wrap */
+	if ((wlc->pub->now % SW_TIMER_MAC_STAT_UPD) == 0)
+		wlc_statsupd(wlc);
+
+	/* Manage TKIP countermeasures timers */
+	FOREACH_BSS(wlc, i, cfg) {
+		if (cfg->tk_cm_dt) {
+			cfg->tk_cm_dt--;
+		}
+		if (cfg->tk_cm_bt) {
+			cfg->tk_cm_bt--;
+		}
+	}
+
+	/* Call any registered watchdog handlers */
+	for (i = 0; i < WLC_MAXMODULES; i++) {
+		if (wlc->modulecb[i].watchdog_fn)
+			wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl);
+	}
+
+	if (WLCISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
+	    ((wlc->pub->now - wlc->tempsense_lasttime) >=
+	     WLC_TEMPSENSE_PERIOD)) {
+		wlc->tempsense_lasttime = wlc->pub->now;
+		wlc_tempsense_upd(wlc);
+	}
+	/* BMAC_NOTE: for HIGH_ONLY driver, this seems being called after RPC bus failed */
+	ASSERT(wlc_bmac_taclear(wlc->hw, true));
+
+	/* Verify that tx_prec_map and fifos are in sync to avoid lock ups */
+	ASSERT(wlc_tx_prec_map_verify(wlc));
+
+	ASSERT(wlc_ps_check(wlc));
+}
+
+/* make interface operational */
+int wlc_up(struct wlc_info *wlc)
+{
+	WL_TRACE("wl%d: %s:\n", wlc->pub->unit, __func__);
+
+	/* HW is turned off so don't try to access it */
+	if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
+		return BCME_RADIOOFF;
+
+	if (!wlc->pub->hw_up) {
+		wlc_bmac_hw_up(wlc->hw);
+		wlc->pub->hw_up = true;
+	}
+
+	if ((wlc->pub->boardflags & BFL_FEM)
+	    && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
+		if (wlc->pub->boardrev >= 0x1250
+		    && (wlc->pub->boardflags & BFL_FEM_BT)) {
+			wlc_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
+				MHF5_4313_GPIOCTRL, WLC_BAND_ALL);
+		} else {
+			wlc_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE, MHF4_EXTPA_ENABLE,
+				WLC_BAND_ALL);
+		}
+	}
+
+	/*
+	 * Need to read the hwradio status here to cover the case where the system
+	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
+	 * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS)
+	 * don't call radio_update to avoid looping wlc_up.
+	 *
+	 * wlc_bmac_up_prep() returns either 0 or BCME_RADIOOFF only
+	 */
+	if (!wlc->pub->radio_disabled) {
+		int status = wlc_bmac_up_prep(wlc->hw);
+		if (status == BCME_RADIOOFF) {
+			if (!mboolisset
+			    (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
+				int idx;
+				struct wlc_bsscfg *bsscfg;
+				mboolset(wlc->pub->radio_disabled,
+					 WL_RADIO_HW_DISABLE);
+
+				FOREACH_BSS(wlc, idx, bsscfg) {
+					if (!BSSCFG_STA(bsscfg)
+					    || !bsscfg->enable || !bsscfg->BSS)
+						continue;
+					WL_ERROR("wl%d.%d: wlc_up: rfdisable -> " "wlc_bsscfg_disable()\n",
+						 wlc->pub->unit, idx);
+				}
+			}
+		} else
+			ASSERT(!status);
+	}
+
+	if (wlc->pub->radio_disabled) {
+		wlc_radio_monitor_start(wlc);
+		return 0;
+	}
+
+	/* wlc_bmac_up_prep has done wlc_corereset(). so clk is on, set it */
+	wlc->clk = true;
+
+	wlc_radio_monitor_stop(wlc);
+
+	/* Set EDCF hostflags */
+	if (EDCF_ENAB(wlc->pub)) {
+		wlc_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, WLC_BAND_ALL);
+	} else {
+		wlc_mhf(wlc, MHF1, MHF1_EDCF, 0, WLC_BAND_ALL);
+	}
+
+	if (WLC_WAR16165(wlc))
+		wlc_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
+			WLC_BAND_ALL);
+
+	wl_init(wlc->wl);
+	wlc->pub->up = true;
+
+	if (wlc->bandinit_pending) {
+		wlc_suspend_mac_and_wait(wlc);
+		wlc_set_chanspec(wlc, wlc->default_bss->chanspec);
+		wlc->bandinit_pending = false;
+		wlc_enable_mac(wlc);
+	}
+
+	wlc_bmac_up_finish(wlc->hw);
+
+	/* other software states up after ISR is running */
+	/* start APs that were to be brought up but are not up  yet */
+	/* if (AP_ENAB(wlc->pub)) wlc_restart_ap(wlc->ap); */
+
+	/* Program the TX wme params with the current settings */
+	wlc_wme_retries_write(wlc);
+
+	/* start one second watchdog timer */
+	ASSERT(!wlc->WDarmed);
+	wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
+	wlc->WDarmed = true;
+
+	/* ensure antenna config is up to date */
+	wlc_stf_phy_txant_upd(wlc);
+	/* ensure LDPC config is in sync */
+	wlc_ht_update_ldpc(wlc, wlc->stf->ldpc);
+
+	return 0;
+}
+
+/* Initialize the base precedence map for dequeueing from txq based on WME settings */
+static void wlc_tx_prec_map_init(struct wlc_info *wlc)
+{
+	wlc->tx_prec_map = WLC_PREC_BMP_ALL;
+	memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
+
+	/* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences
+	 * if either is full.
+	 */
+	if (!EDCF_ENAB(wlc->pub)) {
+		wlc->fifo2prec_map[TX_DATA_FIFO] = WLC_PREC_BMP_ALL;
+		wlc->fifo2prec_map[TX_CTL_FIFO] = WLC_PREC_BMP_ALL;
+	} else {
+		wlc->fifo2prec_map[TX_AC_BK_FIFO] = WLC_PREC_BMP_AC_BK;
+		wlc->fifo2prec_map[TX_AC_BE_FIFO] = WLC_PREC_BMP_AC_BE;
+		wlc->fifo2prec_map[TX_AC_VI_FIFO] = WLC_PREC_BMP_AC_VI;
+		wlc->fifo2prec_map[TX_AC_VO_FIFO] = WLC_PREC_BMP_AC_VO;
+	}
+}
+
+static uint wlc_down_del_timer(struct wlc_info *wlc)
+{
+	uint callbacks = 0;
+
+	return callbacks;
+}
+
+/*
+ * Mark the interface nonoperational, stop the software mechanisms,
+ * disable the hardware, free any transient buffer state.
+ * Return a count of the number of driver callbacks still pending.
+ */
+uint wlc_down(struct wlc_info *wlc)
+{
+
+	uint callbacks = 0;
+	int i;
+	bool dev_gone = false;
+	struct wlc_txq_info *qi;
+
+	WL_TRACE("wl%d: %s:\n", wlc->pub->unit, __func__);
+
+	/* check if we are already in the going down path */
+	if (wlc->going_down) {
+		WL_ERROR("wl%d: %s: Driver going down so return\n",
+			 wlc->pub->unit, __func__);
+		return 0;
+	}
+	if (!wlc->pub->up)
+		return callbacks;
+
+	/* in between, mpc could try to bring down again.. */
+	wlc->going_down = true;
+
+	callbacks += wlc_bmac_down_prep(wlc->hw);
+
+	dev_gone = DEVICEREMOVED(wlc);
+
+	/* Call any registered down handlers */
+	for (i = 0; i < WLC_MAXMODULES; i++) {
+		if (wlc->modulecb[i].down_fn)
+			callbacks +=
+			    wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
+	}
+
+	/* cancel the watchdog timer */
+	if (wlc->WDarmed) {
+		if (!wl_del_timer(wlc->wl, wlc->wdtimer))
+			callbacks++;
+		wlc->WDarmed = false;
+	}
+	/* cancel all other timers */
+	callbacks += wlc_down_del_timer(wlc);
+
+	/* interrupt must have been blocked */
+	ASSERT((wlc->macintmask == 0) || !wlc->pub->up);
+
+	wlc->pub->up = false;
+
+	wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
+
+	/* clear txq flow control */
+	wlc_txflowcontrol_reset(wlc);
+
+	/* flush tx queues */
+	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
+		pktq_flush(&qi->q, true, NULL, 0);
+		ASSERT(pktq_empty(&qi->q));
+	}
+
+	callbacks += wlc_bmac_down_finish(wlc->hw);
+
+	/* wlc_bmac_down_finish has done wlc_coredisable(). so clk is off */
+	wlc->clk = false;
+
+#ifdef BCMDBG
+	/* Since all the packets should have been freed,
+	 * all callbacks should have been called
+	 */
+	for (i = 1; i <= wlc->pub->tunables->maxpktcb; i++)
+		ASSERT(wlc->pkt_callback[i].fn == NULL);
+#endif
+	wlc->going_down = false;
+	return callbacks;
+}
+
+/* Set the current gmode configuration */
+int wlc_set_gmode(struct wlc_info *wlc, u8 gmode, bool config)
+{
+	int ret = 0;
+	uint i;
+	wlc_rateset_t rs;
+	/* Default to 54g Auto */
+	s8 shortslot = WLC_SHORTSLOT_AUTO;	/* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
+	bool shortslot_restrict = false;	/* Restrict association to stations that support shortslot
+						 */
+	bool ignore_bcns = true;	/* Ignore legacy beacons on the same channel */
+	bool ofdm_basic = false;	/* Make 6, 12, and 24 basic rates */
+	int preamble = WLC_PLCP_LONG;	/* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
+	bool preamble_restrict = false;	/* Restrict association to stations that support short
+					 * preambles
+					 */
+	struct wlcband *band;
+
+	/* if N-support is enabled, allow Gmode set as long as requested
+	 * Gmode is not GMODE_LEGACY_B
+	 */
+	if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
+		return BCME_UNSUPPORTED;
+
+	/* verify that we are dealing with 2G band and grab the band pointer */
+	if (wlc->band->bandtype == WLC_BAND_2G)
+		band = wlc->band;
+	else if ((NBANDS(wlc) > 1) &&
+		 (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == WLC_BAND_2G))
+		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+	else
+		return BCME_BADBAND;
+
+	/* Legacy or bust when no OFDM is supported by regulatory */
+	if ((wlc_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
+	     WLC_NO_OFDM) && (gmode != GMODE_LEGACY_B))
+		return BCME_RANGE;
+
+	/* update configuration value */
+	if (config == true)
+		wlc_protection_upd(wlc, WLC_PROT_G_USER, gmode);
+
+	/* Clear supported rates filter */
+	memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t));
+
+	/* Clear rateset override */
+	memset(&rs, 0, sizeof(wlc_rateset_t));
+
+	switch (gmode) {
+	case GMODE_LEGACY_B:
+		shortslot = WLC_SHORTSLOT_OFF;
+		wlc_rateset_copy(&gphy_legacy_rates, &rs);
+
+		break;
+
+	case GMODE_LRS:
+		if (AP_ENAB(wlc->pub))
+			wlc_rateset_copy(&cck_rates, &wlc->sup_rates_override);
+		break;
+
+	case GMODE_AUTO:
+		/* Accept defaults */
+		break;
+
+	case GMODE_ONLY:
+		ofdm_basic = true;
+		preamble = WLC_PLCP_SHORT;
+		preamble_restrict = true;
+		break;
+
+	case GMODE_PERFORMANCE:
+		if (AP_ENAB(wlc->pub))	/* Put all rates into the Supported Rates element */
+			wlc_rateset_copy(&cck_ofdm_rates,
+					 &wlc->sup_rates_override);
+
+		shortslot = WLC_SHORTSLOT_ON;
+		shortslot_restrict = true;
+		ofdm_basic = true;
+		preamble = WLC_PLCP_SHORT;
+		preamble_restrict = true;
+		break;
+
+	default:
+		/* Error */
+		WL_ERROR("wl%d: %s: invalid gmode %d\n",
+			 wlc->pub->unit, __func__, gmode);
+		return BCME_UNSUPPORTED;
+	}
+
+	/*
+	 * If we are switching to gmode == GMODE_LEGACY_B,
+	 * clean up rate info that may refer to OFDM rates.
+	 */
+	if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
+		band->gmode = gmode;
+		if (band->rspec_override && !IS_CCK(band->rspec_override)) {
+			band->rspec_override = 0;
+			wlc_reprate_init(wlc);
+		}
+		if (band->mrspec_override && !IS_CCK(band->mrspec_override)) {
+			band->mrspec_override = 0;
+		}
+	}
+
+	band->gmode = gmode;
+
+	wlc->ignore_bcns = ignore_bcns;
+
+	wlc->shortslot_override = shortslot;
+
+	if (AP_ENAB(wlc->pub)) {
+		/* wlc->ap->shortslot_restrict = shortslot_restrict; */
+		wlc->PLCPHdr_override =
+		    (preamble !=
+		     WLC_PLCP_LONG) ? WLC_PLCP_SHORT : WLC_PLCP_AUTO;
+	}
+
+	if ((AP_ENAB(wlc->pub) && preamble != WLC_PLCP_LONG)
+	    || preamble == WLC_PLCP_SHORT)
+		wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+	else
+		wlc->default_bss->capability &= ~WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+	/* Update shortslot capability bit for AP and IBSS */
+	if ((AP_ENAB(wlc->pub) && shortslot == WLC_SHORTSLOT_AUTO) ||
+	    shortslot == WLC_SHORTSLOT_ON)
+		wlc->default_bss->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+	else
+		wlc->default_bss->capability &=
+					~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+
+	/* Use the default 11g rateset */
+	if (!rs.count)
+		wlc_rateset_copy(&cck_ofdm_rates, &rs);
+
+	if (ofdm_basic) {
+		for (i = 0; i < rs.count; i++) {
+			if (rs.rates[i] == WLC_RATE_6M
+			    || rs.rates[i] == WLC_RATE_12M
+			    || rs.rates[i] == WLC_RATE_24M)
+				rs.rates[i] |= WLC_RATE_FLAG;
+		}
+	}
+
+	/* Set default bss rateset */
+	wlc->default_bss->rateset.count = rs.count;
+	memcpy(wlc->default_bss->rateset.rates, rs.rates, 
+	       sizeof(wlc->default_bss->rateset.rates));
+
+	return ret;
+}
+
+static int wlc_nmode_validate(struct wlc_info *wlc, s32 nmode)
+{
+	int err = 0;
+
+	switch (nmode) {
+
+	case OFF:
+		break;
+
+	case AUTO:
+	case WL_11N_2x2:
+	case WL_11N_3x3:
+		if (!(WLC_PHY_11N_CAP(wlc->band)))
+			err = BCME_BADBAND;
+		break;
+
+	default:
+		err = BCME_RANGE;
+		break;
+	}
+
+	return err;
+}
+
+int wlc_set_nmode(struct wlc_info *wlc, s32 nmode)
+{
+	uint i;
+	int err;
+
+	err = wlc_nmode_validate(wlc, nmode);
+	ASSERT(err == 0);
+	if (err)
+		return err;
+
+	switch (nmode) {
+	case OFF:
+		wlc->pub->_n_enab = OFF;
+		wlc->default_bss->flags &= ~WLC_BSS_HT;
+		/* delete the mcs rates from the default and hw ratesets */
+		wlc_rateset_mcs_clear(&wlc->default_bss->rateset);
+		for (i = 0; i < NBANDS(wlc); i++) {
+			memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
+			       MCSSET_LEN);
+			if (IS_MCS(wlc->band->rspec_override)) {
+				wlc->bandstate[i]->rspec_override = 0;
+				wlc_reprate_init(wlc);
+			}
+			if (IS_MCS(wlc->band->mrspec_override))
+				wlc->bandstate[i]->mrspec_override = 0;
+		}
+		break;
+
+	case AUTO:
+		if (wlc->stf->txstreams == WL_11N_3x3)
+			nmode = WL_11N_3x3;
+		else
+			nmode = WL_11N_2x2;
+	case WL_11N_2x2:
+	case WL_11N_3x3:
+		ASSERT(WLC_PHY_11N_CAP(wlc->band));
+		/* force GMODE_AUTO if NMODE is ON */
+		wlc_set_gmode(wlc, GMODE_AUTO, true);
+		if (nmode == WL_11N_3x3)
+			wlc->pub->_n_enab = SUPPORT_HT;
+		else
+			wlc->pub->_n_enab = SUPPORT_11N;
+		wlc->default_bss->flags |= WLC_BSS_HT;
+		/* add the mcs rates to the default and hw ratesets */
+		wlc_rateset_mcs_build(&wlc->default_bss->rateset,
+				      wlc->stf->txstreams);
+		for (i = 0; i < NBANDS(wlc); i++)
+			memcpy(wlc->bandstate[i]->hw_rateset.mcs,
+			       wlc->default_bss->rateset.mcs, MCSSET_LEN);
+		break;
+
+	default:
+		ASSERT(0);
+		break;
+	}
+
+	return err;
+}
+
+static int wlc_set_rateset(struct wlc_info *wlc, wlc_rateset_t *rs_arg)
+{
+	wlc_rateset_t rs, new;
+	uint bandunit;
+
+	memcpy(&rs, rs_arg, sizeof(wlc_rateset_t));
+
+	/* check for bad count value */
+	if ((rs.count == 0) || (rs.count > WLC_NUMRATES))
+		return BCME_BADRATESET;
+
+	/* try the current band */
+	bandunit = wlc->band->bandunit;
+	memcpy(&new, &rs, sizeof(wlc_rateset_t));
+	if (wlc_rate_hwrs_filter_sort_validate
+	    (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
+	     wlc->stf->txstreams))
+		goto good;
+
+	/* try the other band */
+	if (IS_MBAND_UNLOCKED(wlc)) {
+		bandunit = OTHERBANDUNIT(wlc);
+		memcpy(&new, &rs, sizeof(wlc_rateset_t));
+		if (wlc_rate_hwrs_filter_sort_validate(&new,
+						       &wlc->
+						       bandstate[bandunit]->
+						       hw_rateset, true,
+						       wlc->stf->txstreams))
+			goto good;
+	}
+
+	return BCME_ERROR;
+
+ good:
+	/* apply new rateset */
+	memcpy(&wlc->default_bss->rateset, &new, sizeof(wlc_rateset_t));
+	memcpy(&wlc->bandstate[bandunit]->defrateset, &new,
+	       sizeof(wlc_rateset_t));
+	return 0;
+}
+
+/* simplified integer set interface for common ioctl handler */
+int wlc_set(struct wlc_info *wlc, int cmd, int arg)
+{
+	return wlc_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
+}
+
+/* simplified integer get interface for common ioctl handler */
+int wlc_get(struct wlc_info *wlc, int cmd, int *arg)
+{
+	return wlc_ioctl(wlc, cmd, arg, sizeof(int), NULL);
+}
+
+static void wlc_ofdm_rateset_war(struct wlc_info *wlc)
+{
+	u8 r;
+	bool war = false;
+
+	if (wlc->cfg->associated)
+		r = wlc->cfg->current_bss->rateset.rates[0];
+	else
+		r = wlc->default_bss->rateset.rates[0];
+
+	wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
+
+	return;
+}
+
+int
+wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
+	  struct wlc_if *wlcif)
+{
+	return _wlc_ioctl(wlc, cmd, arg, len, wlcif);
+}
+
+/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
+static int
+_wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
+	   struct wlc_if *wlcif)
+{
+	int val, *pval;
+	bool bool_val;
+	int bcmerror;
+	d11regs_t *regs;
+	uint i;
+	struct scb *nextscb;
+	bool ta_ok;
+	uint band;
+	rw_reg_t *r;
+	struct wlc_bsscfg *bsscfg;
+	wlc_bss_info_t *current_bss;
+
+	/* update bsscfg pointer */
+	bsscfg = NULL;		/* XXX: Hack bsscfg to be size one and use this globally */
+	current_bss = NULL;
+
+	/* initialize the following to get rid of compiler warning */
+	nextscb = NULL;
+	ta_ok = false;
+	band = 0;
+	r = NULL;
+
+	/* If the device is turned off, then it's not "removed" */
+	if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
+		WL_ERROR("wl%d: %s: dead chip\n", wlc->pub->unit, __func__);
+		wl_down(wlc->wl);
+		return BCME_ERROR;
+	}
+
+	ASSERT(!(wlc->pub->hw_off && wlc->pub->up));
+
+	/* default argument is generic integer */
+	pval = arg ? (int *)arg:NULL;
+
+	/* This will prevent the misaligned access */
+	if (pval && (u32) len >= sizeof(val))
+		memcpy(&val, pval, sizeof(val));
+	else
+		val = 0;
+
+	/* bool conversion to avoid duplication below */
+	bool_val = val != 0;
+
+	if (cmd != WLC_SET_CHANNEL)
+		WL_NONE("WLC_IOCTL: cmd %d val 0x%x (%d) len %d\n",
+			cmd, (uint)val, val, len);
+
+	bcmerror = 0;
+	regs = wlc->regs;
+
+	/* A few commands don't need any arguments; all the others do. */
+	switch (cmd) {
+	case WLC_UP:
+	case WLC_OUT:
+	case WLC_DOWN:
+	case WLC_DISASSOC:
+	case WLC_RESTART:
+	case WLC_REBOOT:
+	case WLC_START_CHANNEL_QA:
+	case WLC_INIT:
+		break;
+
+	default:
+		if ((arg == NULL) || (len <= 0)) {
+			WL_ERROR("wl%d: %s: Command %d needs arguments\n",
+				 wlc->pub->unit, __func__, cmd);
+			bcmerror = BCME_BADARG;
+			goto done;
+		}
+	}
+
+	switch (cmd) {
+
+#if defined(BCMDBG)
+	case WLC_GET_MSGLEVEL:
+		*pval = wl_msg_level;
+		break;
+
+	case WLC_SET_MSGLEVEL:
+		wl_msg_level = val;
+		break;
+#endif
+
+	case WLC_GET_INSTANCE:
+		*pval = wlc->pub->unit;
+		break;
+
+	case WLC_GET_CHANNEL:{
+			channel_info_t *ci = (channel_info_t *) arg;
+
+			ASSERT(len > (int)sizeof(ci));
+
+			ci->hw_channel =
+			    CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC);
+			ci->target_channel =
+			    CHSPEC_CHANNEL(wlc->default_bss->chanspec);
+			ci->scan_channel = 0;
+
+			break;
+		}
+
+	case WLC_SET_CHANNEL:{
+			chanspec_t chspec = CH20MHZ_CHSPEC(val);
+
+			if (val < 0 || val > MAXCHANNEL) {
+				bcmerror = BCME_OUTOFRANGECHAN;
+				break;
+			}
+
+			if (!wlc_valid_chanspec_db(wlc->cmi, chspec)) {
+				bcmerror = BCME_BADCHAN;
+				break;
+			}
+
+			if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
+				if (wlc->band->bandunit !=
+				    CHSPEC_WLCBANDUNIT(chspec))
+					wlc->bandinit_pending = true;
+				else
+					wlc->bandinit_pending = false;
+			}
+
+			wlc->default_bss->chanspec = chspec;
+			/* wlc_BSSinit() will sanitize the rateset before using it.. */
+			if (wlc->pub->up &&
+			    (WLC_BAND_PI_RADIO_CHANSPEC != chspec)) {
+				wlc_set_home_chanspec(wlc, chspec);
+				wlc_suspend_mac_and_wait(wlc);
+				wlc_set_chanspec(wlc, chspec);
+				wlc_enable_mac(wlc);
+			}
+			break;
+		}
+
+#if defined(BCMDBG)
+	case WLC_GET_UCFLAGS:
+		if (!wlc->pub->up) {
+			bcmerror = BCME_NOTUP;
+			break;
+		}
+
+		/* optional band is stored in the second integer of incoming buffer */
+		band =
+		    (len <
+		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
+
+		/* bcmerror checking */
+		bcmerror = wlc_iocregchk(wlc, band);
+		if (bcmerror)
+			break;
+
+		if (val >= MHFMAX) {
+			bcmerror = BCME_RANGE;
+			break;
+		}
+
+		*pval = wlc_bmac_mhf_get(wlc->hw, (u8) val, WLC_BAND_AUTO);
+		break;
+
+	case WLC_SET_UCFLAGS:
+		if (!wlc->pub->up) {
+			bcmerror = BCME_NOTUP;
+			break;
+		}
+
+		/* optional band is stored in the second integer of incoming buffer */
+		band =
+		    (len <
+		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
+
+		/* bcmerror checking */
+		bcmerror = wlc_iocregchk(wlc, band);
+		if (bcmerror)
+			break;
+
+		i = (u16) val;
+		if (i >= MHFMAX) {
+			bcmerror = BCME_RANGE;
+			break;
+		}
+
+		wlc_mhf(wlc, (u8) i, 0xffff, (u16) (val >> NBITS(u16)),
+			WLC_BAND_AUTO);
+		break;
+
+	case WLC_GET_SHMEM:
+		ta_ok = true;
+
+		/* optional band is stored in the second integer of incoming buffer */
+		band =
+		    (len <
+		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
+
+		/* bcmerror checking */
+		bcmerror = wlc_iocregchk(wlc, band);
+		if (bcmerror)
+			break;
+
+		if (val & 1) {
+			bcmerror = BCME_BADADDR;
+			break;
+		}
+
+		*pval = wlc_read_shm(wlc, (u16) val);
+		break;
+
+	case WLC_SET_SHMEM:
+		ta_ok = true;
+
+		/* optional band is stored in the second integer of incoming buffer */
+		band =
+		    (len <
+		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
+
+		/* bcmerror checking */
+		bcmerror = wlc_iocregchk(wlc, band);
+		if (bcmerror)
+			break;
+
+		if (val & 1) {
+			bcmerror = BCME_BADADDR;
+			break;
+		}
+
+		wlc_write_shm(wlc, (u16) val,
+			      (u16) (val >> NBITS(u16)));
+		break;
+
+	case WLC_R_REG:	/* MAC registers */
+		ta_ok = true;
+		r = (rw_reg_t *) arg;
+		band = WLC_BAND_AUTO;
+
+		if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
+			bcmerror = BCME_BUFTOOSHORT;
+			break;
+		}
+
+		if (len >= (int)sizeof(rw_reg_t))
+			band = r->band;
+
+		/* bcmerror checking */
+		bcmerror = wlc_iocregchk(wlc, band);
+		if (bcmerror)
+			break;
+
+		if ((r->byteoff + r->size) > sizeof(d11regs_t)) {
+			bcmerror = BCME_BADADDR;
+			break;
+		}
+		if (r->size == sizeof(u32))
+			r->val =
+			    R_REG((u32 *)((unsigned char *)(unsigned long)regs +
+					      r->byteoff));
+		else if (r->size == sizeof(u16))
+			r->val =
+			    R_REG((u16 *)((unsigned char *)(unsigned long)regs +
+					      r->byteoff));
+		else
+			bcmerror = BCME_BADADDR;
+		break;
+
+	case WLC_W_REG:
+		ta_ok = true;
+		r = (rw_reg_t *) arg;
+		band = WLC_BAND_AUTO;
+
+		if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
+			bcmerror = BCME_BUFTOOSHORT;
+			break;
+		}
+
+		if (len >= (int)sizeof(rw_reg_t))
+			band = r->band;
+
+		/* bcmerror checking */
+		bcmerror = wlc_iocregchk(wlc, band);
+		if (bcmerror)
+			break;
+
+		if (r->byteoff + r->size > sizeof(d11regs_t)) {
+			bcmerror = BCME_BADADDR;
+			break;
+		}
+		if (r->size == sizeof(u32))
+			W_REG((u32 *)((unsigned char *)(unsigned long) regs +
+					  r->byteoff), r->val);
+		else if (r->size == sizeof(u16))
+			W_REG((u16 *)((unsigned char *)(unsigned long) regs +
+					  r->byteoff), r->val);
+		else
+			bcmerror = BCME_BADADDR;
+		break;
+#endif				/* BCMDBG */
+
+	case WLC_GET_TXANT:
+		*pval = wlc->stf->txant;
+		break;
+
+	case WLC_SET_TXANT:
+		bcmerror = wlc_stf_ant_txant_validate(wlc, (s8) val);
+		if (bcmerror < 0)
+			break;
+
+		wlc->stf->txant = (s8) val;
+
+		/* if down, we are done */
+		if (!wlc->pub->up)
+			break;
+
+		wlc_suspend_mac_and_wait(wlc);
+
+		wlc_stf_phy_txant_upd(wlc);
+		wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
+
+		wlc_enable_mac(wlc);
+
+		break;
+
+	case WLC_GET_ANTDIV:{
+			u8 phy_antdiv;
+
+			/* return configured value if core is down */
+			if (!wlc->pub->up) {
+				*pval = wlc->stf->ant_rx_ovr;
+
+			} else {
+				if (wlc_phy_ant_rxdiv_get
+				    (wlc->band->pi, &phy_antdiv))
+					*pval = (int)phy_antdiv;
+				else
+					*pval = (int)wlc->stf->ant_rx_ovr;
+			}
+
+			break;
+		}
+	case WLC_SET_ANTDIV:
+		/* values are -1=driver default, 0=force0, 1=force1, 2=start1, 3=start0 */
+		if ((val < -1) || (val > 3)) {
+			bcmerror = BCME_RANGE;
+			break;
+		}
+
+		if (val == -1)
+			val = ANT_RX_DIV_DEF;
+
+		wlc->stf->ant_rx_ovr = (u8) val;
+		wlc_phy_ant_rxdiv_set(wlc->band->pi, (u8) val);
+		break;
+
+	case WLC_GET_RX_ANT:{	/* get latest used rx antenna */
+			u16 rxstatus;
+
+			if (!wlc->pub->up) {
+				bcmerror = BCME_NOTUP;
+				break;
+			}
+
+			rxstatus = R_REG(&wlc->regs->phyrxstatus0);
+			if (rxstatus == 0xdead || rxstatus == (u16) -1) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+			*pval = (rxstatus & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
+			break;
+		}
+
+#if defined(BCMDBG)
+	case WLC_GET_UCANTDIV:
+		if (!wlc->clk) {
+			bcmerror = BCME_NOCLK;
+			break;
+		}
+
+		*pval =
+		    (wlc_bmac_mhf_get(wlc->hw, MHF1, WLC_BAND_AUTO) &
+		     MHF1_ANTDIV);
+		break;
+
+	case WLC_SET_UCANTDIV:{
+			if (!wlc->pub->up) {
+				bcmerror = BCME_NOTUP;
+				break;
+			}
+
+			/* if multiband, band must be locked */
+			if (IS_MBAND_UNLOCKED(wlc)) {
+				bcmerror = BCME_NOTBANDLOCKED;
+				break;
+			}
+
+			wlc_mhf(wlc, MHF1, MHF1_ANTDIV,
+				(val ? MHF1_ANTDIV : 0), WLC_BAND_AUTO);
+			break;
+		}
+#endif				/* defined(BCMDBG) */
+
+	case WLC_GET_SRL:
+		*pval = wlc->SRL;
+		break;
+
+	case WLC_SET_SRL:
+		if (val >= 1 && val <= RETRY_SHORT_MAX) {
+			int ac;
+			wlc->SRL = (u16) val;
+
+			wlc_bmac_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+
+			for (ac = 0; ac < AC_COUNT; ac++) {
+				WLC_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
+			}
+			wlc_wme_retries_write(wlc);
+		} else
+			bcmerror = BCME_RANGE;
+		break;
+
+	case WLC_GET_LRL:
+		*pval = wlc->LRL;
+		break;
+
+	case WLC_SET_LRL:
+		if (val >= 1 && val <= 255) {
+			int ac;
+			wlc->LRL = (u16) val;
+
+			wlc_bmac_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
+
+			for (ac = 0; ac < AC_COUNT; ac++) {
+				WLC_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
+			}
+			wlc_wme_retries_write(wlc);
+		} else
+			bcmerror = BCME_RANGE;
+		break;
+
+	case WLC_GET_CWMIN:
+		*pval = wlc->band->CWmin;
+		break;
+
+	case WLC_SET_CWMIN:
+		if (!wlc->clk) {
+			bcmerror = BCME_NOCLK;
+			break;
+		}
+
+		if (val >= 1 && val <= 255) {
+			wlc_set_cwmin(wlc, (u16) val);
+		} else
+			bcmerror = BCME_RANGE;
+		break;
+
+	case WLC_GET_CWMAX:
+		*pval = wlc->band->CWmax;
+		break;
+
+	case WLC_SET_CWMAX:
+		if (!wlc->clk) {
+			bcmerror = BCME_NOCLK;
+			break;
+		}
+
+		if (val >= 255 && val <= 2047) {
+			wlc_set_cwmax(wlc, (u16) val);
+		} else
+			bcmerror = BCME_RANGE;
+		break;
+
+	case WLC_GET_RADIO:	/* use mask if don't want to expose some internal bits */
+		*pval = wlc->pub->radio_disabled;
+		break;
+
+	case WLC_SET_RADIO:{	/* 32 bits input, higher 16 bits are mask, lower 16 bits are value to
+				 * set
+				 */
+			u16 radiomask, radioval;
+			uint validbits =
+			    WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE;
+			mbool new = 0;
+
+			radiomask = (val & 0xffff0000) >> 16;
+			radioval = val & 0x0000ffff;
+
+			if ((radiomask == 0) || (radiomask & ~validbits)
+			    || (radioval & ~validbits)
+			    || ((radioval & ~radiomask) != 0)) {
+				WL_ERROR("SET_RADIO with wrong bits 0x%x\n",
+					 val);
+				bcmerror = BCME_RANGE;
+				break;
+			}
+
+			new =
+			    (wlc->pub->radio_disabled & ~radiomask) | radioval;
+			wlc->pub->radio_disabled = new;
+
+			wlc_radio_hwdisable_upd(wlc);
+			wlc_radio_upd(wlc);
+			break;
+		}
+
+	case WLC_GET_PHYTYPE:
+		*pval = WLC_PHYTYPE(wlc->band->phytype);
+		break;
+
+#if defined(BCMDBG)
+	case WLC_GET_KEY:
+		if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc))) {
+			wl_wsec_key_t key;
+
+			wsec_key_t *src_key = wlc->wsec_keys[val];
+
+			if (len < (int)sizeof(key)) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+
+			memset((char *)&key, 0, sizeof(key));
+			if (src_key) {
+				key.index = src_key->id;
+				key.len = src_key->len;
+				memcpy(key.data, src_key->data, key.len);
+				key.algo = src_key->algo;
+				if (WSEC_SOFTKEY(wlc, src_key, bsscfg))
+					key.flags |= WL_SOFT_KEY;
+				if (src_key->flags & WSEC_PRIMARY_KEY)
+					key.flags |= WL_PRIMARY_KEY;
+
+				memcpy(key.ea, src_key->ea, ETH_ALEN);
+			}
+
+			memcpy(arg, &key, sizeof(key));
+		} else
+			bcmerror = BCME_BADKEYIDX;
+		break;
+#endif				/* defined(BCMDBG) */
+
+	case WLC_SET_KEY:
+		bcmerror =
+		    wlc_iovar_op(wlc, "wsec_key", NULL, 0, arg, len, IOV_SET,
+				 wlcif);
+		break;
+
+	case WLC_GET_KEY_SEQ:{
+			wsec_key_t *key;
+
+			if (len < DOT11_WPA_KEY_RSC_LEN) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+
+			/* Return the key's tx iv as an EAPOL sequence counter.
+			 * This will be used to supply the RSC value to a supplicant.
+			 * The format is 8 bytes, with least significant in seq[0].
+			 */
+
+			key = WSEC_KEY(wlc, val);
+			if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc)) &&
+				(key != NULL)) {
+				u8 seq[DOT11_WPA_KEY_RSC_LEN];
+				u16 lo;
+				u32 hi;
+				/* group keys in WPA-NONE (IBSS only, AES and TKIP) use a global TXIV */
+				if ((bsscfg->WPA_auth & WPA_AUTH_NONE) &&
+				    is_zero_ether_addr(key->ea)) {
+					lo = bsscfg->wpa_none_txiv.lo;
+					hi = bsscfg->wpa_none_txiv.hi;
+				} else {
+					lo = key->txiv.lo;
+					hi = key->txiv.hi;
+				}
+
+				/* format the buffer, low to high */
+				seq[0] = lo & 0xff;
+				seq[1] = (lo >> 8) & 0xff;
+				seq[2] = hi & 0xff;
+				seq[3] = (hi >> 8) & 0xff;
+				seq[4] = (hi >> 16) & 0xff;
+				seq[5] = (hi >> 24) & 0xff;
+				seq[6] = 0;
+				seq[7] = 0;
+
+				memcpy(arg, seq, sizeof(seq));
+			} else {
+				bcmerror = BCME_BADKEYIDX;
+			}
+			break;
+		}
+
+	case WLC_GET_CURR_RATESET:{
+			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
+			wlc_rateset_t *rs;
+
+			if (bsscfg->associated)
+				rs = &current_bss->rateset;
+			else
+				rs = &wlc->default_bss->rateset;
+
+			if (len < (int)(rs->count + sizeof(rs->count))) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+
+			/* Copy only legacy rateset section */
+			ret_rs->count = rs->count;
+			memcpy(&ret_rs->rates, &rs->rates, rs->count);
+			break;
+		}
+
+	case WLC_GET_RATESET:{
+			wlc_rateset_t rs;
+			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
+
+			memset(&rs, 0, sizeof(wlc_rateset_t));
+			wlc_default_rateset(wlc, (wlc_rateset_t *) &rs);
+
+			if (len < (int)(rs.count + sizeof(rs.count))) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+
+			/* Copy only legacy rateset section */
+			ret_rs->count = rs.count;
+			memcpy(&ret_rs->rates, &rs.rates, rs.count);
+			break;
+		}
+
+	case WLC_SET_RATESET:{
+			wlc_rateset_t rs;
+			wl_rateset_t *in_rs = (wl_rateset_t *) arg;
+
+			if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+
+			if (in_rs->count > WLC_NUMRATES) {
+				bcmerror = BCME_BUFTOOLONG;
+				break;
+			}
+
+			memset(&rs, 0, sizeof(wlc_rateset_t));
+
+			/* Copy only legacy rateset section */
+			rs.count = in_rs->count;
+			memcpy(&rs.rates, &in_rs->rates, rs.count);
+
+			/* merge rateset coming in with the current mcsset */
+			if (N_ENAB(wlc->pub)) {
+				if (bsscfg->associated)
+					memcpy(rs.mcs,
+					       &current_bss->rateset.mcs[0],
+					       MCSSET_LEN);
+				else
+					memcpy(rs.mcs,
+					       &wlc->default_bss->rateset.mcs[0],
+					       MCSSET_LEN);
+			}
+
+			bcmerror = wlc_set_rateset(wlc, &rs);
+
+			if (!bcmerror)
+				wlc_ofdm_rateset_war(wlc);
+
+			break;
+		}
+
+	case WLC_GET_BCNPRD:
+		if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
+			*pval = current_bss->beacon_period;
+		else
+			*pval = wlc->default_bss->beacon_period;
+		break;
+
+	case WLC_SET_BCNPRD:
+		/* range [1, 0xffff] */
+		if (val >= DOT11_MIN_BEACON_PERIOD
+		    && val <= DOT11_MAX_BEACON_PERIOD) {
+			wlc->default_bss->beacon_period = (u16) val;
+		} else
+			bcmerror = BCME_RANGE;
+		break;
+
+	case WLC_GET_DTIMPRD:
+		if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
+			*pval = current_bss->dtim_period;
+		else
+			*pval = wlc->default_bss->dtim_period;
+		break;
+
+	case WLC_SET_DTIMPRD:
+		/* range [1, 0xff] */
+		if (val >= DOT11_MIN_DTIM_PERIOD
+		    && val <= DOT11_MAX_DTIM_PERIOD) {
+			wlc->default_bss->dtim_period = (u8) val;
+		} else
+			bcmerror = BCME_RANGE;
+		break;
+
+#ifdef SUPPORT_PS
+	case WLC_GET_PM:
+		*pval = wlc->PM;
+		break;
+
+	case WLC_SET_PM:
+		if ((val >= PM_OFF) && (val <= PM_MAX)) {
+			wlc->PM = (u8) val;
+			if (wlc->pub->up) {
+			}
+			/* Change watchdog driver to align watchdog with tbtt if possible */
+			wlc_watchdog_upd(wlc, PS_ALLOWED(wlc));
+		} else
+			bcmerror = BCME_ERROR;
+		break;
+#endif				/* SUPPORT_PS */
+
+#ifdef SUPPORT_PS
+#ifdef BCMDBG
+	case WLC_GET_WAKE:
+		if (AP_ENAB(wlc->pub)) {
+			bcmerror = BCME_NOTSTA;
+			break;
+		}
+		*pval = wlc->wake;
+		break;
+
+	case WLC_SET_WAKE:
+		if (AP_ENAB(wlc->pub)) {
+			bcmerror = BCME_NOTSTA;
+			break;
+		}
+
+		wlc->wake = val ? true : false;
+
+		/* if down, we're done */
+		if (!wlc->pub->up)
+			break;
+
+		/* apply to the mac */
+		wlc_set_ps_ctrl(wlc);
+		break;
+#endif				/* BCMDBG */
+#endif				/* SUPPORT_PS */
+
+	case WLC_GET_REVINFO:
+		bcmerror = wlc_get_revision_info(wlc, arg, (uint) len);
+		break;
+
+	case WLC_GET_AP:
+		*pval = (int)AP_ENAB(wlc->pub);
+		break;
+
+	case WLC_GET_ATIM:
+		if (bsscfg->associated)
+			*pval = (int)current_bss->atim_window;
+		else
+			*pval = (int)wlc->default_bss->atim_window;
+		break;
+
+	case WLC_SET_ATIM:
+		wlc->default_bss->atim_window = (u32) val;
+		break;
+
+	case WLC_GET_PKTCNTS:{
+			get_pktcnt_t *pktcnt = (get_pktcnt_t *) pval;
+			wlc_statsupd(wlc);
+			pktcnt->rx_good_pkt = wlc->pub->_cnt->rxframe;
+			pktcnt->rx_bad_pkt = wlc->pub->_cnt->rxerror;
+			pktcnt->tx_good_pkt =
+			    wlc->pub->_cnt->txfrmsnt;
+			pktcnt->tx_bad_pkt =
+			    wlc->pub->_cnt->txerror +
+			    wlc->pub->_cnt->txfail;
+			if (len >= (int)sizeof(get_pktcnt_t)) {
+				/* Be backward compatible - only if buffer is large enough  */
+				pktcnt->rx_ocast_good_pkt =
+				    wlc->pub->_cnt->rxmfrmocast;
+			}
+			break;
+		}
+
+#ifdef SUPPORT_HWKEY
+	case WLC_GET_WSEC:
+		bcmerror =
+		    wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_GET,
+				 wlcif);
+		break;
+
+	case WLC_SET_WSEC:
+		bcmerror =
+		    wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_SET,
+				 wlcif);
+		break;
+
+	case WLC_GET_WPA_AUTH:
+		*pval = (int)bsscfg->WPA_auth;
+		break;
+
+	case WLC_SET_WPA_AUTH:
+		/* change of WPA_Auth modifies the PS_ALLOWED state */
+		if (BSSCFG_STA(bsscfg)) {
+			bsscfg->WPA_auth = (u16) val;
+		} else
+			bsscfg->WPA_auth = (u16) val;
+		break;
+#endif				/* SUPPORT_HWKEY */
+
+	case WLC_GET_BANDLIST:
+		/* count of number of bands, followed by each band type */
+		*pval++ = NBANDS(wlc);
+		*pval++ = wlc->band->bandtype;
+		if (NBANDS(wlc) > 1)
+			*pval++ = wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype;
+		break;
+
+	case WLC_GET_BAND:
+		*pval = wlc->bandlocked ? wlc->band->bandtype : WLC_BAND_AUTO;
+		break;
+
+	case WLC_GET_PHYLIST:
+		{
+			unsigned char *cp = arg;
+			if (len < 3) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+
+			if (WLCISNPHY(wlc->band)) {
+				*cp++ = 'n';
+			} else if (WLCISLCNPHY(wlc->band)) {
+				*cp++ = 'c';
+			} else if (WLCISSSLPNPHY(wlc->band)) {
+				*cp++ = 's';
+			}
+			*cp = '\0';
+			break;
+		}
+
+	case WLC_GET_SHORTSLOT:
+		*pval = wlc->shortslot;
+		break;
+
+	case WLC_GET_SHORTSLOT_OVERRIDE:
+		*pval = wlc->shortslot_override;
+		break;
+
+	case WLC_SET_SHORTSLOT_OVERRIDE:
+		if ((val != WLC_SHORTSLOT_AUTO) &&
+		    (val != WLC_SHORTSLOT_OFF) && (val != WLC_SHORTSLOT_ON)) {
+			bcmerror = BCME_RANGE;
+			break;
+		}
+
+		wlc->shortslot_override = (s8) val;
+
+		/* shortslot is an 11g feature, so no more work if we are
+		 * currently on the 5G band
+		 */
+		if (BAND_5G(wlc->band->bandtype))
+			break;
+
+		if (wlc->pub->up && wlc->pub->associated) {
+			/* let watchdog or beacon processing update shortslot */
+		} else if (wlc->pub->up) {
+			/* unassociated shortslot is off */
+			wlc_switch_shortslot(wlc, false);
+		} else {
+			/* driver is down, so just update the wlc_info value */
+			if (wlc->shortslot_override == WLC_SHORTSLOT_AUTO) {
+				wlc->shortslot = false;
+			} else {
+				wlc->shortslot =
+				    (wlc->shortslot_override ==
+				     WLC_SHORTSLOT_ON);
+			}
+		}
+
+		break;
+
+	case WLC_GET_LEGACY_ERP:
+		*pval = wlc->include_legacy_erp;
+		break;
+
+	case WLC_SET_LEGACY_ERP:
+		if (wlc->include_legacy_erp == bool_val)
+			break;
+
+		wlc->include_legacy_erp = bool_val;
+
+		if (AP_ENAB(wlc->pub) && wlc->clk) {
+			wlc_update_beacon(wlc);
+			wlc_update_probe_resp(wlc, true);
+		}
+		break;
+
+	case WLC_GET_GMODE:
+		if (wlc->band->bandtype == WLC_BAND_2G)
+			*pval = wlc->band->gmode;
+		else if (NBANDS(wlc) > 1)
+			*pval = wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode;
+		break;
+
+	case WLC_SET_GMODE:
+		if (!wlc->pub->associated)
+			bcmerror = wlc_set_gmode(wlc, (u8) val, true);
+		else {
+			bcmerror = BCME_ASSOCIATED;
+			break;
+		}
+		break;
+
+	case WLC_GET_GMODE_PROTECTION:
+		*pval = wlc->protection->_g;
+		break;
+
+	case WLC_GET_PROTECTION_CONTROL:
+		*pval = wlc->protection->overlap;
+		break;
+
+	case WLC_SET_PROTECTION_CONTROL:
+		if ((val != WLC_PROTECTION_CTL_OFF) &&
+		    (val != WLC_PROTECTION_CTL_LOCAL) &&
+		    (val != WLC_PROTECTION_CTL_OVERLAP)) {
+			bcmerror = BCME_RANGE;
+			break;
+		}
+
+		wlc_protection_upd(wlc, WLC_PROT_OVERLAP, (s8) val);
+
+		/* Current g_protection will sync up to the specified control alg in watchdog
+		 * if the driver is up and associated.
+		 * If the driver is down or not associated, the control setting has no effect.
+		 */
+		break;
+
+	case WLC_GET_GMODE_PROTECTION_OVERRIDE:
+		*pval = wlc->protection->g_override;
+		break;
+
+	case WLC_SET_GMODE_PROTECTION_OVERRIDE:
+		if ((val != WLC_PROTECTION_AUTO) &&
+		    (val != WLC_PROTECTION_OFF) && (val != WLC_PROTECTION_ON)) {
+			bcmerror = BCME_RANGE;
+			break;
+		}
+
+		wlc_protection_upd(wlc, WLC_PROT_G_OVR, (s8) val);
+
+		break;
+
+	case WLC_SET_SUP_RATESET_OVERRIDE:{
+			wlc_rateset_t rs, new;
+
+			/* copyin */
+			if (len < (int)sizeof(wlc_rateset_t)) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+			memcpy(&rs, arg, sizeof(wlc_rateset_t));
+
+			/* check for bad count value */
+			if (rs.count > WLC_NUMRATES) {
+				bcmerror = BCME_BADRATESET;	/* invalid rateset */
+				break;
+			}
+
+			/* this command is only appropriate for gmode operation */
+			if (!(wlc->band->gmode ||
+			      ((NBANDS(wlc) > 1)
+			       && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
+				bcmerror = BCME_BADBAND;	/* gmode only command when not in gmode */
+				break;
+			}
+
+			/* check for an empty rateset to clear the override */
+			if (rs.count == 0) {
+				memset(&wlc->sup_rates_override, 0,
+				      sizeof(wlc_rateset_t));
+				break;
+			}
+
+			/* validate rateset by comparing pre and post sorted against 11g hw rates */
+			wlc_rateset_filter(&rs, &new, false, WLC_RATES_CCK_OFDM,
+					   RATE_MASK, BSS_N_ENAB(wlc, bsscfg));
+			wlc_rate_hwrs_filter_sort_validate(&new,
+							   &cck_ofdm_rates,
+							   false,
+							   wlc->stf->txstreams);
+			if (rs.count != new.count) {
+				bcmerror = BCME_BADRATESET;	/* invalid rateset */
+				break;
+			}
+
+			/* apply new rateset to the override */
+			memcpy(&wlc->sup_rates_override, &new,
+			      sizeof(wlc_rateset_t));
+
+			/* update bcn and probe resp if needed */
+			if (wlc->pub->up && AP_ENAB(wlc->pub)
+			    && wlc->pub->associated) {
+				wlc_update_beacon(wlc);
+				wlc_update_probe_resp(wlc, true);
+			}
+			break;
+		}
+
+	case WLC_GET_SUP_RATESET_OVERRIDE:
+		/* this command is only appropriate for gmode operation */
+		if (!(wlc->band->gmode ||
+		      ((NBANDS(wlc) > 1)
+		       && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
+			bcmerror = BCME_BADBAND;	/* gmode only command when not in gmode */
+			break;
+		}
+		if (len < (int)sizeof(wlc_rateset_t)) {
+			bcmerror = BCME_BUFTOOSHORT;
+			break;
+		}
+		memcpy(arg, &wlc->sup_rates_override, sizeof(wlc_rateset_t));
+
+		break;
+
+	case WLC_GET_PRB_RESP_TIMEOUT:
+		*pval = wlc->prb_resp_timeout;
+		break;
+
+	case WLC_SET_PRB_RESP_TIMEOUT:
+		if (wlc->pub->up) {
+			bcmerror = BCME_NOTDOWN;
+			break;
+		}
+		if (val < 0 || val >= 0xFFFF) {
+			bcmerror = BCME_RANGE;	/* bad value */
+			break;
+		}
+		wlc->prb_resp_timeout = (u16) val;
+		break;
+
+	case WLC_GET_KEY_PRIMARY:{
+			wsec_key_t *key;
+
+			/* treat the 'val' parm as the key id */
+			key = WSEC_BSS_DEFAULT_KEY(bsscfg);
+			if (key != NULL) {
+				*pval = key->id == val ? true : false;
+			} else {
+				bcmerror = BCME_BADKEYIDX;
+			}
+			break;
+		}
+
+	case WLC_SET_KEY_PRIMARY:{
+			wsec_key_t *key, *old_key;
+
+			bcmerror = BCME_BADKEYIDX;
+
+			/* treat the 'val' parm as the key id */
+			for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
+				key = bsscfg->bss_def_keys[i];
+				if (key != NULL && key->id == val) {
+					old_key = WSEC_BSS_DEFAULT_KEY(bsscfg);
+					if (old_key != NULL)
+						old_key->flags &=
+						    ~WSEC_PRIMARY_KEY;
+					key->flags |= WSEC_PRIMARY_KEY;
+					bsscfg->wsec_index = i;
+					bcmerror = BCME_OK;
+				}
+			}
+			break;
+		}
+
+#ifdef BCMDBG
+	case WLC_INIT:
+		wl_init(wlc->wl);
+		break;
+#endif
+
+	case WLC_SET_VAR:
+	case WLC_GET_VAR:{
+			char *name;
+			/* validate the name value */
+			name = (char *)arg;
+			for (i = 0; i < (uint) len && *name != '\0';
+			     i++, name++)
+				;
+
+			if (i == (uint) len) {
+				bcmerror = BCME_BUFTOOSHORT;
+				break;
+			}
+			i++;	/* include the null in the string length */
+
+			if (cmd == WLC_GET_VAR) {
+				bcmerror =
+				    wlc_iovar_op(wlc, arg,
+						 (void *)((s8 *) arg + i),
+						 len - i, arg, len, IOV_GET,
+						 wlcif);
+			} else
+				bcmerror =
+				    wlc_iovar_op(wlc, arg, NULL, 0,
+						 (void *)((s8 *) arg + i),
+						 len - i, IOV_SET, wlcif);
+
+			break;
+		}
+
+	case WLC_SET_WSEC_PMK:
+		bcmerror = BCME_UNSUPPORTED;
+		break;
+
+#if defined(BCMDBG)
+	case WLC_CURRENT_PWR:
+		if (!wlc->pub->up)
+			bcmerror = BCME_NOTUP;
+		else
+			bcmerror = wlc_get_current_txpwr(wlc, arg, len);
+		break;
+#endif
+
+	case WLC_LAST:
+		WL_ERROR("%s: WLC_LAST\n", __func__);
+	}
+ done:
+
+	if (bcmerror) {
+		if (VALID_BCMERROR(bcmerror))
+			wlc->pub->bcmerror = bcmerror;
+		else {
+			bcmerror = 0;
+		}
+
+	}
+	/* BMAC_NOTE: for HIGH_ONLY driver, this seems being called after RPC bus failed */
+	/* In hw_off condition, IOCTLs that reach here are deemed safe but taclear would
+	 * certainly result in getting -1 for register reads. So skip ta_clear altogether
+	 */
+	if (!(wlc->pub->hw_off))
+		ASSERT(wlc_bmac_taclear(wlc->hw, ta_ok) || !ta_ok);
+
+	return bcmerror;
+}
+
+#if defined(BCMDBG)
+/* consolidated register access ioctl error checking */
+int wlc_iocregchk(struct wlc_info *wlc, uint band)
+{
+	/* if band is specified, it must be the current band */
+	if ((band != WLC_BAND_AUTO) && (band != (uint) wlc->band->bandtype))
+		return BCME_BADBAND;
+
+	/* if multiband and band is not specified, band must be locked */
+	if ((band == WLC_BAND_AUTO) && IS_MBAND_UNLOCKED(wlc))
+		return BCME_NOTBANDLOCKED;
+
+	/* must have core clocks */
+	if (!wlc->clk)
+		return BCME_NOCLK;
+
+	return 0;
+}
+#endif				/* defined(BCMDBG) */
+
+#if defined(BCMDBG)
+/* For some ioctls, make sure that the pi pointer matches the current phy */
+int wlc_iocpichk(struct wlc_info *wlc, uint phytype)
+{
+	if (wlc->band->phytype != phytype)
+		return BCME_BADBAND;
+	return 0;
+}
+#endif
+
+/* Look up the given var name in the given table */
+static const bcm_iovar_t *wlc_iovar_lookup(const bcm_iovar_t *table,
+					   const char *name)
+{
+	const bcm_iovar_t *vi;
+	const char *lookup_name;
+
+	/* skip any ':' delimited option prefixes */
+	lookup_name = strrchr(name, ':');
+	if (lookup_name != NULL)
+		lookup_name++;
+	else
+		lookup_name = name;
+
+	ASSERT(table != NULL);
+
+	for (vi = table; vi->name; vi++) {
+		if (!strcmp(vi->name, lookup_name))
+			return vi;
+	}
+	/* ran to end of table */
+
+	return NULL;		/* var name not found */
+}
+
+/* simplified integer get interface for common WLC_GET_VAR ioctl handler */
+int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg)
+{
+	return wlc_iovar_op(wlc, name, NULL, 0, arg, sizeof(s32), IOV_GET,
+			    NULL);
+}
+
+/* simplified integer set interface for common WLC_SET_VAR ioctl handler */
+int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg)
+{
+	return wlc_iovar_op(wlc, name, NULL, 0, (void *)&arg, sizeof(arg),
+			    IOV_SET, NULL);
+}
+
+/* simplified s8 get interface for common WLC_GET_VAR ioctl handler */
+int wlc_iovar_gets8(struct wlc_info *wlc, const char *name, s8 *arg)
+{
+	int iovar_int;
+	int err;
+
+	err =
+	    wlc_iovar_op(wlc, name, NULL, 0, &iovar_int, sizeof(iovar_int),
+			 IOV_GET, NULL);
+	if (!err)
+		*arg = (s8) iovar_int;
+
+	return err;
+}
+
+/*
+ * register iovar table, watchdog and down handlers.
+ * calling function must keep 'iovars' until wlc_module_unregister is called.
+ * 'iovar' must have the last entry's name field being NULL as terminator.
+ */
+int wlc_module_register(struct wlc_pub *pub, const bcm_iovar_t *iovars,
+			const char *name, void *hdl, iovar_fn_t i_fn,
+			watchdog_fn_t w_fn, down_fn_t d_fn)
+{
+	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
+	int i;
+
+	ASSERT(name != NULL);
+	ASSERT(i_fn != NULL || w_fn != NULL || d_fn != NULL);
+
+	/* find an empty entry and just add, no duplication check! */
+	for (i = 0; i < WLC_MAXMODULES; i++) {
+		if (wlc->modulecb[i].name[0] == '\0') {
+			strncpy(wlc->modulecb[i].name, name,
+				sizeof(wlc->modulecb[i].name) - 1);
+			wlc->modulecb[i].iovars = iovars;
+			wlc->modulecb[i].hdl = hdl;
+			wlc->modulecb[i].iovar_fn = i_fn;
+			wlc->modulecb[i].watchdog_fn = w_fn;
+			wlc->modulecb[i].down_fn = d_fn;
+			return 0;
+		}
+	}
+
+	/* it is time to increase the capacity */
+	ASSERT(i < WLC_MAXMODULES);
+	return BCME_NORESOURCE;
+}
+
+/* unregister module callbacks */
+int wlc_module_unregister(struct wlc_pub *pub, const char *name, void *hdl)
+{
+	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
+	int i;
+
+	if (wlc == NULL)
+		return BCME_NOTFOUND;
+
+	ASSERT(name != NULL);
+
+	for (i = 0; i < WLC_MAXMODULES; i++) {
+		if (!strcmp(wlc->modulecb[i].name, name) &&
+		    (wlc->modulecb[i].hdl == hdl)) {
+			memset(&wlc->modulecb[i], 0, sizeof(struct modulecb));
+			return 0;
+		}
+	}
+
+	/* table not found! */
+	return BCME_NOTFOUND;
+}
+
+/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */
+static void wlc_wme_retries_write(struct wlc_info *wlc)
+{
+	int ac;
+
+	/* Need clock to do this */
+	if (!wlc->clk)
+		return;
+
+	for (ac = 0; ac < AC_COUNT; ac++) {
+		wlc_write_shm(wlc, M_AC_TXLMT_ADDR(ac), wlc->wme_retries[ac]);
+	}
+}
+
+/* Get or set an iovar.  The params/p_len pair specifies any additional
+ * qualifying parameters (e.g. an "element index") for a get, while the
+ * arg/len pair is the buffer for the value to be set or retrieved.
+ * Operation (get/set) is specified by the last argument.
+ * interface context provided by wlcif
+ *
+ * All pointers may point into the same buffer.
+ */
+int
+wlc_iovar_op(struct wlc_info *wlc, const char *name,
+	     void *params, int p_len, void *arg, int len,
+	     bool set, struct wlc_if *wlcif)
+{
+	int err = 0;
+	int val_size;
+	const bcm_iovar_t *vi = NULL;
+	u32 actionid;
+	int i;
+
+	ASSERT(name != NULL);
+
+	ASSERT(len >= 0);
+
+	/* Get MUST have return space */
+	ASSERT(set || (arg && len));
+
+	ASSERT(!(wlc->pub->hw_off && wlc->pub->up));
+
+	/* Set does NOT take qualifiers */
+	ASSERT(!set || (!params && !p_len));
+
+	if (!set && (len == sizeof(int)) &&
+	    !(IS_ALIGNED((unsigned long)(arg), (uint) sizeof(int)))) {
+		WL_ERROR("wl%d: %s unaligned get ptr for %s\n",
+			 wlc->pub->unit, __func__, name);
+		ASSERT(0);
+	}
+
+	/* find the given iovar name */
+	for (i = 0; i < WLC_MAXMODULES; i++) {
+		if (!wlc->modulecb[i].iovars)
+			continue;
+		vi = wlc_iovar_lookup(wlc->modulecb[i].iovars, name);
+		if (vi)
+			break;
+	}
+	/* iovar name not found */
+	if (i >= WLC_MAXMODULES) {
+		err = BCME_UNSUPPORTED;
+		goto exit;
+	}
+
+	/* set up 'params' pointer in case this is a set command so that
+	 * the convenience int and bool code can be common to set and get
+	 */
+	if (params == NULL) {
+		params = arg;
+		p_len = len;
+	}
+
+	if (vi->type == IOVT_VOID)
+		val_size = 0;
+	else if (vi->type == IOVT_BUFFER)
+		val_size = len;
+	else
+		/* all other types are integer sized */
+		val_size = sizeof(int);
+
+	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
+
+	/* Do the actual parameter implementation */
+	err = wlc->modulecb[i].iovar_fn(wlc->modulecb[i].hdl, vi, actionid,
+					name, params, p_len, arg, len, val_size,
+					wlcif);
+
+ exit:
+	return err;
+}
+
+int
+wlc_iovar_check(struct wlc_pub *pub, const bcm_iovar_t *vi, void *arg, int len,
+		bool set)
+{
+	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
+	int err = 0;
+	s32 int_val = 0;
+
+	/* check generic condition flags */
+	if (set) {
+		if (((vi->flags & IOVF_SET_DOWN) && wlc->pub->up) ||
+		    ((vi->flags & IOVF_SET_UP) && !wlc->pub->up)) {
+			err = (wlc->pub->up ? BCME_NOTDOWN : BCME_NOTUP);
+		} else if ((vi->flags & IOVF_SET_BAND)
+			   && IS_MBAND_UNLOCKED(wlc)) {
+			err = BCME_NOTBANDLOCKED;
+		} else if ((vi->flags & IOVF_SET_CLK) && !wlc->clk) {
+			err = BCME_NOCLK;
+		}
+	} else {
+		if (((vi->flags & IOVF_GET_DOWN) && wlc->pub->up) ||
+		    ((vi->flags & IOVF_GET_UP) && !wlc->pub->up)) {
+			err = (wlc->pub->up ? BCME_NOTDOWN : BCME_NOTUP);
+		} else if ((vi->flags & IOVF_GET_BAND)
+			   && IS_MBAND_UNLOCKED(wlc)) {
+			err = BCME_NOTBANDLOCKED;
+		} else if ((vi->flags & IOVF_GET_CLK) && !wlc->clk) {
+			err = BCME_NOCLK;
+		}
+	}
+
+	if (err)
+		goto exit;
+
+	/* length check on io buf */
+	err = bcm_iovar_lencheck(vi, arg, len, set);
+	if (err)
+		goto exit;
+
+	/* On set, check value ranges for integer types */
+	if (set) {
+		switch (vi->type) {
+		case IOVT_BOOL:
+		case IOVT_INT8:
+		case IOVT_INT16:
+		case IOVT_INT32:
+		case IOVT_UINT8:
+		case IOVT_UINT16:
+		case IOVT_UINT32:
+			memcpy(&int_val, arg, sizeof(int));
+			err = wlc_iovar_rangecheck(wlc, int_val, vi);
+			break;
+		}
+	}
+ exit:
+	return err;
+}
+
+/* handler for iovar table wlc_iovars */
+/*
+ * IMPLEMENTATION NOTE: In order to avoid checking for get/set in each
+ * iovar case, the switch statement maps the iovar id into separate get
+ * and set values.  If you add a new iovar to the switch you MUST use
+ * IOV_GVAL and/or IOV_SVAL in the case labels to avoid conflict with
+ * another case.
+ * Please use params for additional qualifying parameters.
+ */
+int
+wlc_doiovar(void *hdl, const bcm_iovar_t *vi, u32 actionid,
+	    const char *name, void *params, uint p_len, void *arg, int len,
+	    int val_size, struct wlc_if *wlcif)
+{
+	struct wlc_info *wlc = hdl;
+	struct wlc_bsscfg *bsscfg;
+	int err = 0;
+	s32 int_val = 0;
+	s32 int_val2 = 0;
+	s32 *ret_int_ptr;
+	bool bool_val;
+	bool bool_val2;
+	wlc_bss_info_t *current_bss;
+
+	WL_TRACE("wl%d: %s\n", wlc->pub->unit, __func__);
+
+	bsscfg = NULL;
+	current_bss = NULL;
+
+	err = wlc_iovar_check(wlc->pub, vi, arg, len, IOV_ISSET(actionid));
+	if (err != 0)
+		return err;
+
+	/* convenience int and bool vals for first 8 bytes of buffer */
+	if (p_len >= (int)sizeof(int_val))
+		memcpy(&int_val, params, sizeof(int_val));
+
+	if (p_len >= (int)sizeof(int_val) * 2)
+		memcpy(&int_val2,
+		       (void *)((unsigned long)params + sizeof(int_val)),
+		       sizeof(int_val));
+
+	/* convenience int ptr for 4-byte gets (requires int aligned arg) */
+	ret_int_ptr = (s32 *) arg;
+
+	bool_val = (int_val != 0) ? true : false;
+	bool_val2 = (int_val2 != 0) ? true : false;
+
+	WL_TRACE("wl%d: %s: id %d\n",
+		 wlc->pub->unit, __func__, IOV_ID(actionid));
+	/* Do the actual parameter implementation */
+	switch (actionid) {
+	case IOV_SVAL(IOV_RTSTHRESH):
+		wlc->RTSThresh = int_val;
+		break;
+
+	case IOV_GVAL(IOV_QTXPOWER):{
+			uint qdbm;
+			bool override;
+
+			err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
+				&override);
+			if (err != BCME_OK)
+				return err;
+
+			/* Return qdbm units */
+			*ret_int_ptr =
+			    qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
+			break;
+		}
+
+		/* As long as override is false, this only sets the *user* targets.
+		   User can twiddle this all he wants with no harm.
+		   wlc_phy_txpower_set() explicitly sets override to false if
+		   not internal or test.
+		 */
+	case IOV_SVAL(IOV_QTXPOWER):{
+			u8 qdbm;
+			bool override;
+
+			/* Remove override bit and clip to max qdbm value */
+			qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
+			/* Extract override setting */
+			override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
+			err =
+			    wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
+			break;
+		}
+
+	case IOV_GVAL(IOV_MPC):
+		*ret_int_ptr = (s32) wlc->mpc;
+		break;
+
+	case IOV_SVAL(IOV_MPC):
+		wlc->mpc = bool_val;
+		wlc_radio_mpc_upd(wlc);
+
+		break;
+
+	case IOV_GVAL(IOV_BCN_LI_BCN):
+		*ret_int_ptr = wlc->bcn_li_bcn;
+		break;
+
+	case IOV_SVAL(IOV_BCN_LI_BCN):
+		wlc->bcn_li_bcn = (u8) int_val;
+		if (wlc->pub->up)
+			wlc_bcn_li_upd(wlc);
+		break;
+
+	default:
+		WL_ERROR("wl%d: %s: unsupported\n", wlc->pub->unit, __func__);
+		err = BCME_UNSUPPORTED;
+		break;
+	}
+
+	goto exit;		/* avoid unused label warning */
+
+ exit:
+	return err;
+}
+
+static int
+wlc_iovar_rangecheck(struct wlc_info *wlc, u32 val, const bcm_iovar_t *vi)
+{
+	int err = 0;
+	u32 min_val = 0;
+	u32 max_val = 0;
+
+	/* Only ranged integers are checked */
+	switch (vi->type) {
+	case IOVT_INT32:
+		max_val |= 0x7fffffff;
+		/* fall through */
+	case IOVT_INT16:
+		max_val |= 0x00007fff;
+		/* fall through */
+	case IOVT_INT8:
+		max_val |= 0x0000007f;
+		min_val = ~max_val;
+		if (vi->flags & IOVF_NTRL)
+			min_val = 1;
+		else if (vi->flags & IOVF_WHL)
+			min_val = 0;
+		/* Signed values are checked against max_val and min_val */
+		if ((s32) val < (s32) min_val
+		    || (s32) val > (s32) max_val)
+			err = BCME_RANGE;
+		break;
+
+	case IOVT_UINT32:
+		max_val |= 0xffffffff;
+		/* fall through */
+	case IOVT_UINT16:
+		max_val |= 0x0000ffff;
+		/* fall through */
+	case IOVT_UINT8:
+		max_val |= 0x000000ff;
+		if (vi->flags & IOVF_NTRL)
+			min_val = 1;
+		if ((val < min_val) || (val > max_val))
+			err = BCME_RANGE;
+		break;
+	}
+
+	return err;
+}
+
+#ifdef BCMDBG
+static const char *supr_reason[] = {
+	"None", "PMQ Entry", "Flush request",
+	"Previous frag failure", "Channel mismatch",
+	"Lifetime Expiry", "Underflow"
+};
+
+static void wlc_print_txs_status(u16 s)
+{
+	printk(KERN_DEBUG "[15:12]  %d  frame attempts\n",
+	       (s & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT);
+	printk(KERN_DEBUG " [11:8]  %d  rts attempts\n",
+	       (s & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT);
+	printk(KERN_DEBUG "    [7]  %d  PM mode indicated\n",
+	       ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
+	printk(KERN_DEBUG "    [6]  %d  intermediate status\n",
+	       ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
+	printk(KERN_DEBUG "    [5]  %d  AMPDU\n",
+	       (s & TX_STATUS_AMPDU) ? 1 : 0);
+	printk(KERN_DEBUG "  [4:2]  %d  Frame Suppressed Reason (%s)\n",
+	       ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
+	       supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
+	printk(KERN_DEBUG "    [1]  %d  acked\n",
+	       ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
+}
+#endif				/* BCMDBG */
+
+void wlc_print_txstatus(tx_status_t *txs)
+{
+#if defined(BCMDBG)
+	u16 s = txs->status;
+	u16 ackphyrxsh = txs->ackphyrxsh;
+
+	printk(KERN_DEBUG "\ntxpkt (MPDU) Complete\n");
+
+	printk(KERN_DEBUG "FrameID: %04x   ", txs->frameid);
+	printk(KERN_DEBUG "TxStatus: %04x", s);
+	printk(KERN_DEBUG "\n");
+
+	wlc_print_txs_status(s);
+
+	printk(KERN_DEBUG "LastTxTime: %04x ", txs->lasttxtime);
+	printk(KERN_DEBUG "Seq: %04x ", txs->sequence);
+	printk(KERN_DEBUG "PHYTxStatus: %04x ", txs->phyerr);
+	printk(KERN_DEBUG "RxAckRSSI: %04x ",
+	       (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
+	printk(KERN_DEBUG "RxAckSQ: %04x",
+	       (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
+	printk(KERN_DEBUG "\n");
+#endif				/* defined(BCMDBG) */
+}
+
+static void
+wlc_ctrupd_cache(u16 cur_stat, u16 *macstat_snapshot, u32 *macstat)
+{
+	u16 v;
+	u16 delta;
+
+	v = le16_to_cpu(cur_stat);
+	delta = (u16)(v - *macstat_snapshot);
+
+	if (delta != 0) {
+		*macstat += delta;
+		*macstat_snapshot = v;
+	}
+}
+
+#define MACSTATUPD(name) \
+	wlc_ctrupd_cache(macstats.name, &wlc->core->macstat_snapshot->name, &wlc->pub->_cnt->name)
+
+void wlc_statsupd(struct wlc_info *wlc)
+{
+	int i;
+	macstat_t macstats;
+#ifdef BCMDBG
+	u16 delta;
+	u16 rxf0ovfl;
+	u16 txfunfl[NFIFO];
+#endif				/* BCMDBG */
+
+	/* if driver down, make no sense to update stats */
+	if (!wlc->pub->up)
+		return;
+
+#ifdef BCMDBG
+	/* save last rx fifo 0 overflow count */
+	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
+
+	/* save last tx fifo  underflow count */
+	for (i = 0; i < NFIFO; i++)
+		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
+#endif				/* BCMDBG */
+
+	/* Read mac stats from contiguous shared memory */
+	wlc_bmac_copyfrom_shm(wlc->hw, M_UCODE_MACSTAT,
+			      &macstats, sizeof(macstat_t));
+
+	/* update mac stats */
+	MACSTATUPD(txallfrm);
+	MACSTATUPD(txrtsfrm);
+	MACSTATUPD(txctsfrm);
+	MACSTATUPD(txackfrm);
+	MACSTATUPD(txdnlfrm);
+	MACSTATUPD(txbcnfrm);
+	for (i = 0; i < NFIFO; i++)
+		MACSTATUPD(txfunfl[i]);
+	MACSTATUPD(txtplunfl);
+	MACSTATUPD(txphyerr);
+	MACSTATUPD(rxfrmtoolong);
+	MACSTATUPD(rxfrmtooshrt);
+	MACSTATUPD(rxinvmachdr);
+	MACSTATUPD(rxbadfcs);
+	MACSTATUPD(rxbadplcp);
+	MACSTATUPD(rxcrsglitch);
+	MACSTATUPD(rxstrt);
+	MACSTATUPD(rxdfrmucastmbss);
+	MACSTATUPD(rxmfrmucastmbss);
+	MACSTATUPD(rxcfrmucast);
+	MACSTATUPD(rxrtsucast);
+	MACSTATUPD(rxctsucast);
+	MACSTATUPD(rxackucast);
+	MACSTATUPD(rxdfrmocast);
+	MACSTATUPD(rxmfrmocast);
+	MACSTATUPD(rxcfrmocast);
+	MACSTATUPD(rxrtsocast);
+	MACSTATUPD(rxctsocast);
+	MACSTATUPD(rxdfrmmcast);
+	MACSTATUPD(rxmfrmmcast);
+	MACSTATUPD(rxcfrmmcast);
+	MACSTATUPD(rxbeaconmbss);
+	MACSTATUPD(rxdfrmucastobss);
+	MACSTATUPD(rxbeaconobss);
+	MACSTATUPD(rxrsptmout);
+	MACSTATUPD(bcntxcancl);
+	MACSTATUPD(rxf0ovfl);
+	MACSTATUPD(rxf1ovfl);
+	MACSTATUPD(rxf2ovfl);
+	MACSTATUPD(txsfovfl);
+	MACSTATUPD(pmqovfl);
+	MACSTATUPD(rxcgprqfrm);
+	MACSTATUPD(rxcgprsqovfl);
+	MACSTATUPD(txcgprsfail);
+	MACSTATUPD(txcgprssuc);
+	MACSTATUPD(prs_timeout);
+	MACSTATUPD(rxnack);
+	MACSTATUPD(frmscons);
+	MACSTATUPD(txnack);
+	MACSTATUPD(txglitch_nack);
+	MACSTATUPD(txburst);
+	MACSTATUPD(phywatchdog);
+	MACSTATUPD(pktengrxducast);
+	MACSTATUPD(pktengrxdmcast);
+
+#ifdef BCMDBG
+	/* check for rx fifo 0 overflow */
+	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
+	if (delta)
+		WL_ERROR("wl%d: %u rx fifo 0 overflows!\n",
+			 wlc->pub->unit, delta);
+
+	/* check for tx fifo underflows */
+	for (i = 0; i < NFIFO; i++) {
+		delta =
+		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
+			      txfunfl[i]);
+		if (delta)
+			WL_ERROR("wl%d: %u tx fifo %d underflows!\n",
+				 wlc->pub->unit, delta, i);
+	}
+#endif				/* BCMDBG */
+
+	/* dot11 counter update */
+
+	WLCNTSET(wlc->pub->_cnt->txrts,
+		 (wlc->pub->_cnt->rxctsucast -
+		  wlc->pub->_cnt->d11cnt_txrts_off));
+	WLCNTSET(wlc->pub->_cnt->rxcrc,
+		 (wlc->pub->_cnt->rxbadfcs - wlc->pub->_cnt->d11cnt_rxcrc_off));
+	WLCNTSET(wlc->pub->_cnt->txnocts,
+		 ((wlc->pub->_cnt->txrtsfrm - wlc->pub->_cnt->rxctsucast) -
+		  wlc->pub->_cnt->d11cnt_txnocts_off));
+
+	/* merge counters from dma module */
+	for (i = 0; i < NFIFO; i++) {
+		if (wlc->hw->di[i]) {
+			WLCNTADD(wlc->pub->_cnt->txnobuf,
+				 (wlc->hw->di[i])->txnobuf);
+			WLCNTADD(wlc->pub->_cnt->rxnobuf,
+				 (wlc->hw->di[i])->rxnobuf);
+			WLCNTADD(wlc->pub->_cnt->rxgiant,
+				 (wlc->hw->di[i])->rxgiants);
+			dma_counterreset(wlc->hw->di[i]);
+		}
+	}
+
+	/*
+	 * Aggregate transmit and receive errors that probably resulted
+	 * in the loss of a frame are computed on the fly.
+	 */
+	WLCNTSET(wlc->pub->_cnt->txerror,
+		 wlc->pub->_cnt->txnobuf + wlc->pub->_cnt->txnoassoc +
+		 wlc->pub->_cnt->txuflo + wlc->pub->_cnt->txrunt +
+		 wlc->pub->_cnt->dmade + wlc->pub->_cnt->dmada +
+		 wlc->pub->_cnt->dmape);
+	WLCNTSET(wlc->pub->_cnt->rxerror,
+		 wlc->pub->_cnt->rxoflo + wlc->pub->_cnt->rxnobuf +
+		 wlc->pub->_cnt->rxfragerr + wlc->pub->_cnt->rxrunt +
+		 wlc->pub->_cnt->rxgiant + wlc->pub->_cnt->rxnoscb +
+		 wlc->pub->_cnt->rxbadsrcmac);
+	for (i = 0; i < NFIFO; i++)
+		wlc->pub->_cnt->rxerror += wlc->pub->_cnt->rxuflo[i];
+}
+
+bool wlc_chipmatch(u16 vendor, u16 device)
+{
+	if (vendor != VENDOR_BROADCOM) {
+		WL_ERROR("wlc_chipmatch: unknown vendor id %04x\n", vendor);
+		return false;
+	}
+
+	if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
+		return true;
+
+	if (device == BCM4313_D11N2G_ID)
+		return true;
+	if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
+		return true;
+
+	WL_ERROR("wlc_chipmatch: unknown device id %04x\n", device);
+	return false;
+}
+
+#if defined(BCMDBG)
+void wlc_print_txdesc(d11txh_t *txh)
+{
+	u16 mtcl = le16_to_cpu(txh->MacTxControlLow);
+	u16 mtch = le16_to_cpu(txh->MacTxControlHigh);
+	u16 mfc = le16_to_cpu(txh->MacFrameControl);
+	u16 tfest = le16_to_cpu(txh->TxFesTimeNormal);
+	u16 ptcw = le16_to_cpu(txh->PhyTxControlWord);
+	u16 ptcw_1 = le16_to_cpu(txh->PhyTxControlWord_1);
+	u16 ptcw_1_Fbr = le16_to_cpu(txh->PhyTxControlWord_1_Fbr);
+	u16 ptcw_1_Rts = le16_to_cpu(txh->PhyTxControlWord_1_Rts);
+	u16 ptcw_1_FbrRts = le16_to_cpu(txh->PhyTxControlWord_1_FbrRts);
+	u16 mainrates = le16_to_cpu(txh->MainRates);
+	u16 xtraft = le16_to_cpu(txh->XtraFrameTypes);
+	u8 *iv = txh->IV;
+	u8 *ra = txh->TxFrameRA;
+	u16 tfestfb = le16_to_cpu(txh->TxFesTimeFallback);
+	u8 *rtspfb = txh->RTSPLCPFallback;
+	u16 rtsdfb = le16_to_cpu(txh->RTSDurFallback);
+	u8 *fragpfb = txh->FragPLCPFallback;
+	u16 fragdfb = le16_to_cpu(txh->FragDurFallback);
+	u16 mmodelen = le16_to_cpu(txh->MModeLen);
+	u16 mmodefbrlen = le16_to_cpu(txh->MModeFbrLen);
+	u16 tfid = le16_to_cpu(txh->TxFrameID);
+	u16 txs = le16_to_cpu(txh->TxStatus);
+	u16 mnmpdu = le16_to_cpu(txh->MaxNMpdus);
+	u16 mabyte = le16_to_cpu(txh->MaxABytes_MRT);
+	u16 mabyte_f = le16_to_cpu(txh->MaxABytes_FBR);
+	u16 mmbyte = le16_to_cpu(txh->MinMBytes);
+
+	u8 *rtsph = txh->RTSPhyHeader;
+	struct ieee80211_rts rts = txh->rts_frame;
+	char hexbuf[256];
+
+	/* add plcp header along with txh descriptor */
+	prhex("Raw TxDesc + plcp header", (unsigned char *) txh, sizeof(d11txh_t) + 48);
+
+	printk(KERN_DEBUG "TxCtlLow: %04x ", mtcl);
+	printk(KERN_DEBUG "TxCtlHigh: %04x ", mtch);
+	printk(KERN_DEBUG "FC: %04x ", mfc);
+	printk(KERN_DEBUG "FES Time: %04x\n", tfest);
+	printk(KERN_DEBUG "PhyCtl: %04x%s ", ptcw,
+	       (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
+	printk(KERN_DEBUG "PhyCtl_1: %04x ", ptcw_1);
+	printk(KERN_DEBUG "PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
+	printk(KERN_DEBUG "PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
+	printk(KERN_DEBUG "PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
+	printk(KERN_DEBUG "MainRates: %04x ", mainrates);
+	printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
+	printk(KERN_DEBUG "\n");
+
+	bcm_format_hex(hexbuf, iv, sizeof(txh->IV));
+	printk(KERN_DEBUG "SecIV:       %s\n", hexbuf);
+	bcm_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
+	printk(KERN_DEBUG "RA:          %s\n", hexbuf);
+
+	printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
+	bcm_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
+	printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+	printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
+	bcm_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
+	printk(KERN_DEBUG "PLCP: %s ", hexbuf);
+	printk(KERN_DEBUG "DUR: %04x", fragdfb);
+	printk(KERN_DEBUG "\n");
+
+	printk(KERN_DEBUG "MModeLen: %04x ", mmodelen);
+	printk(KERN_DEBUG "MModeFbrLen: %04x\n", mmodefbrlen);
+
+	printk(KERN_DEBUG "FrameID:     %04x\n", tfid);
+	printk(KERN_DEBUG "TxStatus:    %04x\n", txs);
+
+	printk(KERN_DEBUG "MaxNumMpdu:  %04x\n", mnmpdu);
+	printk(KERN_DEBUG "MaxAggbyte:  %04x\n", mabyte);
+	printk(KERN_DEBUG "MaxAggbyte_fb:  %04x\n", mabyte_f);
+	printk(KERN_DEBUG "MinByte:     %04x\n", mmbyte);
+
+	bcm_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
+	printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+	bcm_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
+	printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
+	printk(KERN_DEBUG "\n");
+}
+#endif				/* defined(BCMDBG) */
+
+#if defined(BCMDBG)
+void wlc_print_rxh(d11rxhdr_t *rxh)
+{
+	u16 len = rxh->RxFrameSize;
+	u16 phystatus_0 = rxh->PhyRxStatus_0;
+	u16 phystatus_1 = rxh->PhyRxStatus_1;
+	u16 phystatus_2 = rxh->PhyRxStatus_2;
+	u16 phystatus_3 = rxh->PhyRxStatus_3;
+	u16 macstatus1 = rxh->RxStatus1;
+	u16 macstatus2 = rxh->RxStatus2;
+	char flagstr[64];
+	char lenbuf[20];
+	static const bcm_bit_desc_t macstat_flags[] = {
+		{RXS_FCSERR, "FCSErr"},
+		{RXS_RESPFRAMETX, "Reply"},
+		{RXS_PBPRES, "PADDING"},
+		{RXS_DECATMPT, "DeCr"},
+		{RXS_DECERR, "DeCrErr"},
+		{RXS_BCNSENT, "Bcn"},
+		{0, NULL}
+	};
+
+	prhex("Raw RxDesc", (unsigned char *) rxh, sizeof(d11rxhdr_t));
+
+	bcm_format_flags(macstat_flags, macstatus1, flagstr, 64);
+
+	snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
+
+	printk(KERN_DEBUG "RxFrameSize:     %6s (%d)%s\n", lenbuf, len,
+	       (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
+	printk(KERN_DEBUG "RxPHYStatus:     %04x %04x %04x %04x\n",
+	       phystatus_0, phystatus_1, phystatus_2, phystatus_3);
+	printk(KERN_DEBUG "RxMACStatus:     %x %s\n", macstatus1, flagstr);
+	printk(KERN_DEBUG "RXMACaggtype:    %x\n",
+	       (macstatus2 & RXS_AGGTYPE_MASK));
+	printk(KERN_DEBUG "RxTSFTime:       %04x\n", rxh->RxTSFTime);
+}
+#endif				/* defined(BCMDBG) */
+
+#if defined(BCMDBG)
+int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len)
+{
+	uint i, c;
+	char *p = buf;
+	char *endp = buf + SSID_FMT_BUF_LEN;
+
+	if (ssid_len > IEEE80211_MAX_SSID_LEN)
+		ssid_len = IEEE80211_MAX_SSID_LEN;
+
+	for (i = 0; i < ssid_len; i++) {
+		c = (uint) ssid[i];
+		if (c == '\\') {
+			*p++ = '\\';
+			*p++ = '\\';
+		} else if (isprint((unsigned char) c)) {
+			*p++ = (char)c;
+		} else {
+			p += snprintf(p, (endp - p), "\\x%02X", c);
+		}
+	}
+	*p = '\0';
+	ASSERT(p < endp);
+
+	return (int)(p - buf);
+}
+#endif				/* defined(BCMDBG) */
+
+static u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate)
+{
+	return wlc_bmac_rate_shm_offset(wlc->hw, rate);
+}
+
+/* Callback for device removed */
+
+/*
+ * Attempts to queue a packet onto a multiple-precedence queue,
+ * if necessary evicting a lower precedence packet from the queue.
+ *
+ * 'prec' is the precedence number that has already been mapped
+ * from the packet priority.
+ *
+ * Returns true if packet consumed (queued), false if not.
+ */
+bool BCMFASTPATH
+wlc_prec_enq(struct wlc_info *wlc, struct pktq *q, void *pkt, int prec)
+{
+	return wlc_prec_enq_head(wlc, q, pkt, prec, false);
+}
+
+bool BCMFASTPATH
+wlc_prec_enq_head(struct wlc_info *wlc, struct pktq *q, struct sk_buff *pkt,
+		  int prec, bool head)
+{
+	struct sk_buff *p;
+	int eprec = -1;		/* precedence to evict from */
+
+	/* Determine precedence from which to evict packet, if any */
+	if (pktq_pfull(q, prec))
+		eprec = prec;
+	else if (pktq_full(q)) {
+		p = pktq_peek_tail(q, &eprec);
+		ASSERT(p != NULL);
+		if (eprec > prec) {
+			WL_ERROR("%s: Failing: eprec %d > prec %d\n",
+				 __func__, eprec, prec);
+			return false;
+		}
+	}
+
+	/* Evict if needed */
+	if (eprec >= 0) {
+		bool discard_oldest;
+
+		/* Detect queueing to unconfigured precedence */
+		ASSERT(!pktq_pempty(q, eprec));
+
+		discard_oldest = AC_BITMAP_TST(wlc->wme_dp, eprec);
+
+		/* Refuse newer packet unless configured to discard oldest */
+		if (eprec == prec && !discard_oldest) {
+			WL_ERROR("%s: No where to go, prec == %d\n",
+				 __func__, prec);
+			return false;
+		}
+
+		/* Evict packet according to discard policy */
+		p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q,
+									  eprec);
+		ASSERT(p != NULL);
+
+		/* Increment wme stats */
+		if (WME_ENAB(wlc->pub)) {
+			WLCNTINCR(wlc->pub->_wme_cnt->
+				  tx_failed[WME_PRIO2AC(p->priority)].packets);
+			WLCNTADD(wlc->pub->_wme_cnt->
+				 tx_failed[WME_PRIO2AC(p->priority)].bytes,
+				 pkttotlen(p));
+		}
+		pkt_buf_free_skb(p);
+		wlc->pub->_cnt->txnobuf++;
+	}
+
+	/* Enqueue */
+	if (head)
+		p = pktq_penq_head(q, prec, pkt);
+	else
+		p = pktq_penq(q, prec, pkt);
+	ASSERT(p != NULL);
+
+	return true;
+}
+
+void BCMFASTPATH wlc_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
+			     uint prec)
+{
+	struct wlc_info *wlc = (struct wlc_info *) ctx;
+	struct wlc_txq_info *qi = wlc->active_queue;	/* Check me */
+	struct pktq *q = &qi->q;
+	int prio;
+
+	prio = sdu->priority;
+
+	ASSERT(pktq_max(q) >= wlc->pub->tunables->datahiwat);
+
+	if (!wlc_prec_enq(wlc, q, sdu, prec)) {
+		if (!EDCF_ENAB(wlc->pub)
+		    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
+			WL_ERROR("wl%d: wlc_txq_enq: txq overflow\n",
+				 wlc->pub->unit);
+
+		/*
+		 * XXX we might hit this condtion in case
+		 * packet flooding from mac80211 stack
+		 */
+		pkt_buf_free_skb(sdu);
+		wlc->pub->_cnt->txnobuf++;
+	}
+
+	/* Check if flow control needs to be turned on after enqueuing the packet
+	 *   Don't turn on flow control if EDCF is enabled. Driver would make the decision on what
+	 *   to drop instead of relying on stack to make the right decision
+	 */
+	if (!EDCF_ENAB(wlc->pub)
+	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
+		if (pktq_len(q) >= wlc->pub->tunables->datahiwat) {
+			wlc_txflowcontrol(wlc, qi, ON, ALLPRIO);
+		}
+	} else if (wlc->pub->_priofc) {
+		if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
+		    wlc->pub->tunables->datahiwat) {
+			wlc_txflowcontrol(wlc, qi, ON, prio);
+		}
+	}
+}
+
+bool BCMFASTPATH
+wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu,
+		     struct ieee80211_hw *hw)
+{
+	u8 prio;
+	uint fifo;
+	void *pkt;
+	struct scb *scb = &global_scb;
+	struct ieee80211_hdr *d11_header = (struct ieee80211_hdr *)(sdu->data);
+
+	ASSERT(sdu);
+
+	/* 802.11 standard requires management traffic to go at highest priority */
+	prio = ieee80211_is_data(d11_header->frame_control) ? sdu->priority :
+		MAXPRIO;
+	fifo = prio2fifo[prio];
+
+	ASSERT((uint) skb_headroom(sdu) >= TXOFF);
+	ASSERT(!(sdu->next));
+	ASSERT(!(sdu->prev));
+	ASSERT(fifo < NFIFO);
+
+	pkt = sdu;
+	if (unlikely
+	    (wlc_d11hdrs_mac80211(wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0)))
+		return -EINVAL;
+	wlc_txq_enq(wlc, scb, pkt, WLC_PRIO_TO_PREC(prio));
+	wlc_send_q(wlc, wlc->active_queue);
+
+	wlc->pub->_cnt->ieee_tx++;
+	return 0;
+}
+
+void BCMFASTPATH wlc_send_q(struct wlc_info *wlc, struct wlc_txq_info *qi)
+{
+	struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
+	int prec;
+	u16 prec_map;
+	int err = 0, i, count;
+	uint fifo;
+	struct pktq *q = &qi->q;
+	struct ieee80211_tx_info *tx_info;
+
+	/* only do work for the active queue */
+	if (qi != wlc->active_queue)
+		return;
+
+	if (in_send_q)
+		return;
+	else
+		in_send_q = true;
+
+	prec_map = wlc->tx_prec_map;
+
+	/* Send all the enq'd pkts that we can.
+	 * Dequeue packets with precedence with empty HW fifo only
+	 */
+	while (prec_map && (pkt[0] = pktq_mdeq(q, prec_map, &prec))) {
+		tx_info = IEEE80211_SKB_CB(pkt[0]);
+		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+			err = wlc_sendampdu(wlc->ampdu, qi, pkt, prec);
+		} else {
+			count = 1;
+			err = wlc_prep_pdu(wlc, pkt[0], &fifo);
+			if (!err) {
+				for (i = 0; i < count; i++) {
+					wlc_txfifo(wlc, fifo, pkt[i], true, 1);
+				}
+			}
+		}
+
+		if (err == BCME_BUSY) {
+			pktq_penq_head(q, prec, pkt[0]);
+			/* If send failed due to any other reason than a change in
+			 * HW FIFO condition, quit. Otherwise, read the new prec_map!
+			 */
+			if (prec_map == wlc->tx_prec_map)
+				break;
+			prec_map = wlc->tx_prec_map;
+		}
+	}
+
+	/* Check if flow control needs to be turned off after sending the packet */
+	if (!EDCF_ENAB(wlc->pub)
+	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
+		if (wlc_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
+		    && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) {
+			wlc_txflowcontrol(wlc, qi, OFF, ALLPRIO);
+		}
+	} else if (wlc->pub->_priofc) {
+		int prio;
+		for (prio = MAXPRIO; prio >= 0; prio--) {
+			if (wlc_txflowcontrol_prio_isset(wlc, qi, prio) &&
+			    (pktq_plen(q, wlc_prio2prec_map[prio]) <
+			     wlc->pub->tunables->datahiwat / 2)) {
+				wlc_txflowcontrol(wlc, qi, OFF, prio);
+			}
+		}
+	}
+	in_send_q = false;
+}
+
+/*
+ * bcmc_fid_generate:
+ * Generate frame ID for a BCMC packet.  The frag field is not used
+ * for MC frames so is used as part of the sequence number.
+ */
+static inline u16
+bcmc_fid_generate(struct wlc_info *wlc, struct wlc_bsscfg *bsscfg,
+		  d11txh_t *txh)
+{
+	u16 frameid;
+
+	frameid = le16_to_cpu(txh->TxFrameID) & ~(TXFID_SEQ_MASK |
+						  TXFID_QUEUE_MASK);
+	frameid |=
+	    (((wlc->
+	       mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+	    TX_BCMC_FIFO;
+
+	return frameid;
+}
+
+void BCMFASTPATH
+wlc_txfifo(struct wlc_info *wlc, uint fifo, struct sk_buff *p, bool commit,
+	   s8 txpktpend)
+{
+	u16 frameid = INVALIDFID;
+	d11txh_t *txh;
+
+	ASSERT(fifo < NFIFO);
+	txh = (d11txh_t *) (p->data);
+
+	/* When a BC/MC frame is being committed to the BCMC fifo via DMA (NOT PIO), update
+	 * ucode or BSS info as appropriate.
+	 */
+	if (fifo == TX_BCMC_FIFO) {
+		frameid = le16_to_cpu(txh->TxFrameID);
+
+	}
+
+	if (WLC_WAR16165(wlc))
+		wlc_war16165(wlc, true);
+
+
+	/* Bump up pending count for if not using rpc. If rpc is used, this will be handled
+	 * in wlc_bmac_txfifo()
+	 */
+	if (commit) {
+		TXPKTPENDINC(wlc, fifo, txpktpend);
+		WL_TRACE("wlc_txfifo, pktpend inc %d to %d\n",
+			 txpktpend, TXPKTPENDGET(wlc, fifo));
+	}
+
+	/* Commit BCMC sequence number in the SHM frame ID location */
+	if (frameid != INVALIDFID)
+		BCMCFID(wlc, frameid);
+
+	if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) {
+		WL_ERROR("wlc_txfifo: fatal, toss frames !!!\n");
+	}
+}
+
+static u16
+wlc_compute_airtime(struct wlc_info *wlc, ratespec_t rspec, uint length)
+{
+	u16 usec = 0;
+	uint mac_rate = RSPEC2RATE(rspec);
+	uint nsyms;
+
+	if (IS_MCS(rspec)) {
+		/* not supported yet */
+		ASSERT(0);
+	} else if (IS_OFDM(rspec)) {
+		/* nsyms = Ceiling(Nbits / (Nbits/sym))
+		 *
+		 * Nbits = length * 8
+		 * Nbits/sym = Mbps * 4 = mac_rate * 2
+		 */
+		nsyms = CEIL((length * 8), (mac_rate * 2));
+
+		/* usec = symbols * usec/symbol */
+		usec = (u16) (nsyms * APHY_SYMBOL_TIME);
+		return usec;
+	} else {
+		switch (mac_rate) {
+		case WLC_RATE_1M:
+			usec = length << 3;
+			break;
+		case WLC_RATE_2M:
+			usec = length << 2;
+			break;
+		case WLC_RATE_5M5:
+			usec = (length << 4) / 11;
+			break;
+		case WLC_RATE_11M:
+			usec = (length << 3) / 11;
+			break;
+		default:
+			WL_ERROR("wl%d: wlc_compute_airtime: unsupported rspec 0x%x\n",
+				 wlc->pub->unit, rspec);
+			ASSERT((const char *)"Bad phy_rate" == NULL);
+			break;
+		}
+	}
+
+	return usec;
+}
+
+void BCMFASTPATH
+wlc_compute_plcp(struct wlc_info *wlc, ratespec_t rspec, uint length, u8 *plcp)
+{
+	if (IS_MCS(rspec)) {
+		wlc_compute_mimo_plcp(rspec, length, plcp);
+	} else if (IS_OFDM(rspec)) {
+		wlc_compute_ofdm_plcp(rspec, length, plcp);
+	} else {
+		wlc_compute_cck_plcp(rspec, length, plcp);
+	}
+	return;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void wlc_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp)
+{
+	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
+	ASSERT(IS_MCS(rspec));
+	plcp[0] = mcs;
+	if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
+		plcp[0] |= MIMO_PLCP_40MHZ;
+	WLC_SET_MIMO_PLCP_LEN(plcp, length);
+	plcp[3] = RSPEC_MIMOPLCP3(rspec);	/* rspec already holds this byte */
+	plcp[3] |= 0x7;		/* set smoothing, not sounding ppdu & reserved */
+	plcp[4] = 0;		/* number of extension spatial streams bit 0 & 1 */
+	plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void BCMFASTPATH
+wlc_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp)
+{
+	u8 rate_signal;
+	u32 tmp = 0;
+	int rate = RSPEC2RATE(rspec);
+
+	ASSERT(IS_OFDM(rspec));
+
+	/* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */
+	rate_signal = rate_info[rate] & RATE_MASK;
+	ASSERT(rate_signal != 0);
+
+	memset(plcp, 0, D11_PHY_HDR_LEN);
+	D11A_PHY_HDR_SRATE((ofdm_phy_hdr_t *) plcp, rate_signal);
+
+	tmp = (length & 0xfff) << 5;
+	plcp[2] |= (tmp >> 16) & 0xff;
+	plcp[1] |= (tmp >> 8) & 0xff;
+	plcp[0] |= tmp & 0xff;
+
+	return;
+}
+
+/*
+ * Compute PLCP, but only requires actual rate and length of pkt.
+ * Rate is given in the driver standard multiple of 500 kbps.
+ * le is set for 11 Mbps rate if necessary.
+ * Broken out for PRQ.
+ */
+
+static void wlc_cck_plcp_set(int rate_500, uint length, u8 *plcp)
+{
+	u16 usec = 0;
+	u8 le = 0;
+
+	switch (rate_500) {
+	case WLC_RATE_1M:
+		usec = length << 3;
+		break;
+	case WLC_RATE_2M:
+		usec = length << 2;
+		break;
+	case WLC_RATE_5M5:
+		usec = (length << 4) / 11;
+		if ((length << 4) - (usec * 11) > 0)
+			usec++;
+		break;
+	case WLC_RATE_11M:
+		usec = (length << 3) / 11;
+		if ((length << 3) - (usec * 11) > 0) {
+			usec++;
+			if ((usec * 11) - (length << 3) >= 8)
+				le = D11B_PLCP_SIGNAL_LE;
+		}
+		break;
+
+	default:
+		WL_ERROR("wlc_cck_plcp_set: unsupported rate %d\n", rate_500);
+		rate_500 = WLC_RATE_1M;
+		usec = length << 3;
+		break;
+	}
+	/* PLCP signal byte */
+	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
+	/* PLCP service byte */
+	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
+	/* PLCP length u16, little endian */
+	plcp[2] = usec & 0xff;
+	plcp[3] = (usec >> 8) & 0xff;
+	/* PLCP CRC16 */
+	plcp[4] = 0;
+	plcp[5] = 0;
+}
+
+/* Rate: 802.11 rate code, length: PSDU length in octets */
+static void wlc_compute_cck_plcp(ratespec_t rspec, uint length, u8 *plcp)
+{
+	int rate = RSPEC2RATE(rspec);
+
+	ASSERT(IS_CCK(rspec));
+
+	wlc_cck_plcp_set(rate, length, plcp);
+}
+
+/* wlc_compute_frame_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for MPDU
+ * DUR for a single frame = 1 SIFS + 1 ACK
+ * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
+ *
+ * rate			MPDU rate in unit of 500kbps
+ * next_frag_len	next MPDU length in bytes
+ * preamble_type	use short/GF or long/MM PLCP header
+ */
+static u16 BCMFASTPATH
+wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate, u8 preamble_type,
+		      uint next_frag_len)
+{
+	u16 dur, sifs;
+
+	sifs = SIFS(wlc->band);
+
+	dur = sifs;
+	dur += (u16) wlc_calc_ack_time(wlc, rate, preamble_type);
+
+	if (next_frag_len) {
+		/* Double the current DUR to get 2 SIFS + 2 ACKs */
+		dur *= 2;
+		/* add another SIFS and the frag time */
+		dur += sifs;
+		dur +=
+		    (u16) wlc_calc_frame_time(wlc, rate, preamble_type,
+						 next_frag_len);
+	}
+	return dur;
+}
+
+/* wlc_compute_rtscts_dur()
+ *
+ * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
+ * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
+ * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
+ *
+ * cts			cts-to-self or rts/cts
+ * rts_rate		rts or cts rate in unit of 500kbps
+ * rate			next MPDU rate in unit of 500kbps
+ * frame_len		next MPDU frame length in bytes
+ */
+u16 BCMFASTPATH
+wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only, ratespec_t rts_rate,
+		       ratespec_t frame_rate, u8 rts_preamble_type,
+		       u8 frame_preamble_type, uint frame_len, bool ba)
+{
+	u16 dur, sifs;
+
+	sifs = SIFS(wlc->band);
+
+	if (!cts_only) {	/* RTS/CTS */
+		dur = 3 * sifs;
+		dur +=
+		    (u16) wlc_calc_cts_time(wlc, rts_rate,
+					       rts_preamble_type);
+	} else {		/* CTS-TO-SELF */
+		dur = 2 * sifs;
+	}
+
+	dur +=
+	    (u16) wlc_calc_frame_time(wlc, frame_rate, frame_preamble_type,
+					 frame_len);
+	if (ba)
+		dur +=
+		    (u16) wlc_calc_ba_time(wlc, frame_rate,
+					      WLC_SHORT_PREAMBLE);
+	else
+		dur +=
+		    (u16) wlc_calc_ack_time(wlc, frame_rate,
+					       frame_preamble_type);
+	return dur;
+}
+
+static bool wlc_phy_rspec_check(struct wlc_info *wlc, u16 bw, ratespec_t rspec)
+{
+	if (IS_MCS(rspec)) {
+		uint mcs = rspec & RSPEC_RATE_MASK;
+
+		if (mcs < 8) {
+			ASSERT(RSPEC_STF(rspec) < PHY_TXC1_MODE_SDM);
+		} else if ((mcs >= 8) && (mcs <= 23)) {
+			ASSERT(RSPEC_STF(rspec) == PHY_TXC1_MODE_SDM);
+		} else if (mcs == 32) {
+			ASSERT(RSPEC_STF(rspec) < PHY_TXC1_MODE_SDM);
+			ASSERT(bw == PHY_TXC1_BW_40MHZ_DUP);
+		}
+	} else if (IS_OFDM(rspec)) {
+		ASSERT(RSPEC_STF(rspec) < PHY_TXC1_MODE_STBC);
+	} else {
+		ASSERT(IS_CCK(rspec));
+
+		ASSERT((bw == PHY_TXC1_BW_20MHZ)
+		       || (bw == PHY_TXC1_BW_20MHZ_UP));
+		ASSERT(RSPEC_STF(rspec) == PHY_TXC1_MODE_SISO);
+	}
+
+	return true;
+}
+
+u16 BCMFASTPATH wlc_phytxctl1_calc(struct wlc_info *wlc, ratespec_t rspec)
+{
+	u16 phyctl1 = 0;
+	u16 bw;
+
+	if (WLCISLCNPHY(wlc->band)) {
+		bw = PHY_TXC1_BW_20MHZ;
+	} else {
+		bw = RSPEC_GET_BW(rspec);
+		/* 10Mhz is not supported yet */
+		if (bw < PHY_TXC1_BW_20MHZ) {
+			WL_ERROR("wlc_phytxctl1_calc: bw %d is not supported yet, set to 20L\n",
+				 bw);
+			bw = PHY_TXC1_BW_20MHZ;
+		}
+
+		wlc_phy_rspec_check(wlc, bw, rspec);
+	}
+
+	if (IS_MCS(rspec)) {
+		uint mcs = rspec & RSPEC_RATE_MASK;
+
+		/* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
+		phyctl1 = RSPEC_PHYTXBYTE2(rspec);
+		/* set the upper byte of phyctl1 */
+		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
+	} else if (IS_CCK(rspec) && !WLCISLCNPHY(wlc->band)
+		   && !WLCISSSLPNPHY(wlc->band)) {
+		/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
+		/* Eventually MIMOPHY would also be converted to this format */
+		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+		phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
+	} else {		/* legacy OFDM/CCK */
+		s16 phycfg;
+		/* get the phyctl byte from rate phycfg table */
+		phycfg = wlc_rate_legacy_phyctl(RSPEC2RATE(rspec));
+		if (phycfg == -1) {
+			WL_ERROR("wlc_phytxctl1_calc: wrong legacy OFDM/CCK rate\n");
+			ASSERT(0);
+			phycfg = 0;
+		}
+		/* set the upper byte of phyctl1 */
+		phyctl1 =
+		    (bw | (phycfg << 8) |
+		     (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
+	}
+
+#ifdef BCMDBG
+	/* phy clock must support 40Mhz if tx descriptor uses it */
+	if ((phyctl1 & PHY_TXC1_BW_MASK) >= PHY_TXC1_BW_40MHZ) {
+		ASSERT(CHSPEC_WLC_BW(wlc->chanspec) == WLC_40_MHZ);
+		ASSERT(wlc->chanspec == wlc_phy_chanspec_get(wlc->band->pi));
+	}
+#endif				/* BCMDBG */
+	return phyctl1;
+}
+
+ratespec_t BCMFASTPATH
+wlc_rspec_to_rts_rspec(struct wlc_info *wlc, ratespec_t rspec, bool use_rspec,
+		       u16 mimo_ctlchbw)
+{
+	ratespec_t rts_rspec = 0;
+
+	if (use_rspec) {
+		/* use frame rate as rts rate */
+		rts_rspec = rspec;
+
+	} else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) {
+		/* Use 11Mbps as the g protection RTS target rate and fallback.
+		 * Use the WLC_BASIC_RATE() lookup to find the best basic rate under the
+		 * target in case 11 Mbps is not Basic.
+		 * 6 and 9 Mbps are not usually selected by rate selection, but even
+		 * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust.
+		 */
+		rts_rspec = WLC_BASIC_RATE(wlc, WLC_RATE_11M);
+	} else {
+		/* calculate RTS rate and fallback rate based on the frame rate
+		 * RTS must be sent at a basic rate since it is a
+		 * control frame, sec 9.6 of 802.11 spec
+		 */
+		rts_rspec = WLC_BASIC_RATE(wlc, rspec);
+	}
+
+	if (WLC_PHY_11N_CAP(wlc->band)) {
+		/* set rts txbw to correct side band */
+		rts_rspec &= ~RSPEC_BW_MASK;
+
+		/* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel
+		 * (DUP), otherwise send RTS on control channel
+		 */
+		if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
+			rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
+		else
+			rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+		/* pick siso/cdd as default for ofdm */
+		if (IS_OFDM(rts_rspec)) {
+			rts_rspec &= ~RSPEC_STF_MASK;
+			rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
+		}
+	}
+	return rts_rspec;
+}
+
+/*
+ * Add d11txh_t, cck_phy_hdr_t.
+ *
+ * 'p' data must start with 802.11 MAC header
+ * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
+ *
+ * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
+ *
+ */
+static u16 BCMFASTPATH
+wlc_d11hdrs_mac80211(struct wlc_info *wlc, struct ieee80211_hw *hw,
+		     struct sk_buff *p, struct scb *scb, uint frag,
+		     uint nfrags, uint queue, uint next_frag_len,
+		     wsec_key_t *key, ratespec_t rspec_override)
+{
+	struct ieee80211_hdr *h;
+	d11txh_t *txh;
+	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
+	int len, phylen, rts_phylen;
+	u16 mch, phyctl, xfts, mainrates;
+	u16 seq = 0, mcl = 0, status = 0, frameid = 0;
+	ratespec_t rspec[2] = { WLC_RATE_1M, WLC_RATE_1M }, rts_rspec[2] = {
+	WLC_RATE_1M, WLC_RATE_1M};
+	bool use_rts = false;
+	bool use_cts = false;
+	bool use_rifs = false;
+	bool short_preamble[2] = { false, false };
+	u8 preamble_type[2] = { WLC_LONG_PREAMBLE, WLC_LONG_PREAMBLE };
+	u8 rts_preamble_type[2] = { WLC_LONG_PREAMBLE, WLC_LONG_PREAMBLE };
+	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
+	struct ieee80211_rts *rts = NULL;
+	bool qos;
+	uint ac;
+	u32 rate_val[2];
+	bool hwtkmic = false;
+	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
+#define ANTCFG_NONE 0xFF
+	u8 antcfg = ANTCFG_NONE;
+	u8 fbantcfg = ANTCFG_NONE;
+	uint phyctl1_stf = 0;
+	u16 durid = 0;
+	struct ieee80211_tx_rate *txrate[2];
+	int k;
+	struct ieee80211_tx_info *tx_info;
+	bool is_mcs[2];
+	u16 mimo_txbw;
+	u8 mimo_preamble_type;
+
+	ASSERT(queue < NFIFO);
+
+	/* locate 802.11 MAC header */
+	h = (struct ieee80211_hdr *)(p->data);
+	qos = ieee80211_is_data_qos(h->frame_control);
+
+	/* compute length of frame in bytes for use in PLCP computations */
+	len = pkttotlen(p);
+	phylen = len + FCS_LEN;
+
+	/* If WEP enabled, add room in phylen for the additional bytes of
+	 * ICV which MAC generates.  We do NOT add the additional bytes to
+	 * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
+	 * in this case
+	 */
+	if (key) {
+		phylen += key->icv_len;
+	}
+
+	/* Get tx_info */
+	tx_info = IEEE80211_SKB_CB(p);
+	ASSERT(tx_info);
+
+	/* add PLCP */
+	plcp = skb_push(p, D11_PHY_HDR_LEN);
+
+	/* add Broadcom tx descriptor header */
+	txh = (d11txh_t *) skb_push(p, D11_TXH_LEN);
+	memset(txh, 0, D11_TXH_LEN);
+
+	/* setup frameid */
+	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+		/* non-AP STA should never use BCMC queue */
+		ASSERT(queue != TX_BCMC_FIFO);
+		if (queue == TX_BCMC_FIFO) {
+			WL_ERROR("wl%d: %s: ASSERT queue == TX_BCMC!\n",
+				 WLCWLUNIT(wlc), __func__);
+			frameid = bcmc_fid_generate(wlc, NULL, txh);
+		} else {
+			/* Increment the counter for first fragment */
+			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
+				SCB_SEQNUM(scb, p->priority)++;
+			}
+
+			/* extract fragment number from frame first */
+			seq = le16_to_cpu(seq) & FRAGNUM_MASK;
+			seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
+			h->seq_ctrl = cpu_to_le16(seq);
+
+			frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
+			    (queue & TXFID_QUEUE_MASK);
+		}
+	}
+	frameid |= queue & TXFID_QUEUE_MASK;
+
+	/* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
+	if (SCB_PS(scb) || ieee80211_is_beacon(h->frame_control))
+		mcl |= TXC_IGNOREPMQ;
+
+	ASSERT(hw->max_rates <= IEEE80211_TX_MAX_RATES);
+	ASSERT(hw->max_rates == 2);
+
+	txrate[0] = tx_info->control.rates;
+	txrate[1] = txrate[0] + 1;
+
+	ASSERT(txrate[0]->idx >= 0);
+	/* if rate control algorithm didn't give us a fallback rate, use the primary rate */
+	if (txrate[1]->idx < 0) {
+		txrate[1] = txrate[0];
+	}
+
+	for (k = 0; k < hw->max_rates; k++) {
+		is_mcs[k] =
+		    txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
+		if (!is_mcs[k]) {
+			ASSERT(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU));
+			if ((txrate[k]->idx >= 0)
+			    && (txrate[k]->idx <
+				hw->wiphy->bands[tx_info->band]->n_bitrates)) {
+				rate_val[k] =
+				    hw->wiphy->bands[tx_info->band]->
+				    bitrates[txrate[k]->idx].hw_value;
+				short_preamble[k] =
+				    txrate[k]->
+				    flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
+				    true : false;
+			} else {
+				ASSERT((txrate[k]->idx >= 0) &&
+				       (txrate[k]->idx <
+					hw->wiphy->bands[tx_info->band]->
+					n_bitrates));
+				rate_val[k] = WLC_RATE_1M;
+			}
+		} else {
+			rate_val[k] = txrate[k]->idx;
+		}
+		/* Currently only support same setting for primay and fallback rates.
+		 * Unify flags for each rate into a single value for the frame
+		 */
+		use_rts |=
+		    txrate[k]->
+		    flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
+		use_cts |=
+		    txrate[k]->
+		    flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
+
+		if (is_mcs[k])
+			rate_val[k] |= NRATE_MCS_INUSE;
+
+		rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
+
+		/* (1) RATE: determine and validate primary rate and fallback rates */
+		if (!RSPEC_ACTIVE(rspec[k])) {
+			ASSERT(RSPEC_ACTIVE(rspec[k]));
+			rspec[k] = WLC_RATE_1M;
+		} else {
+			if (!is_multicast_ether_addr(h->addr1)) {
+				/* set tx antenna config */
+				wlc_antsel_antcfg_get(wlc->asi, false, false, 0,
+						      0, &antcfg, &fbantcfg);
+			}
+		}
+	}
+
+	phyctl1_stf = wlc->stf->ss_opmode;
+
+	if (N_ENAB(wlc->pub)) {
+		for (k = 0; k < hw->max_rates; k++) {
+			/* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */
+			if (((IS_MCS(rspec[k]) &&
+			      IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
+			     IS_OFDM(rspec[k]))
+			    && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
+				|| !(rspec[k] & RSPEC_OVERRIDE))) {
+				rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
+
+				/* For SISO MCS use STBC if possible */
+				if (IS_MCS(rspec[k])
+				    && WLC_STF_SS_STBC_TX(wlc, scb)) {
+					u8 stc;
+
+					ASSERT(WLC_STBC_CAP_PHY(wlc));
+					stc = 1;	/* Nss for single stream is always 1 */
+					rspec[k] |=
+					    (PHY_TXC1_MODE_STBC <<
+					     RSPEC_STF_SHIFT) | (stc <<
+								 RSPEC_STC_SHIFT);
+				} else
+					rspec[k] |=
+					    (phyctl1_stf << RSPEC_STF_SHIFT);
+			}
+
+			/* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */
+			if (CHSPEC_WLC_BW(wlc->chanspec) == WLC_40_MHZ) {
+				/* default txbw is 20in40 SB */
+				mimo_ctlchbw = mimo_txbw =
+				    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
+				    ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
+
+				if (IS_MCS(rspec[k])) {
+					/* mcs 32 must be 40b/w DUP */
+					if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
+						mimo_txbw =
+						    PHY_TXC1_BW_40MHZ_DUP;
+						/* use override */
+					} else if (wlc->mimo_40txbw != AUTO)
+						mimo_txbw = wlc->mimo_40txbw;
+					/* else check if dst is using 40 Mhz */
+					else if (scb->flags & SCB_IS40)
+						mimo_txbw = PHY_TXC1_BW_40MHZ;
+				} else if (IS_OFDM(rspec[k])) {
+					if (wlc->ofdm_40txbw != AUTO)
+						mimo_txbw = wlc->ofdm_40txbw;
+				} else {
+					ASSERT(IS_CCK(rspec[k]));
+					if (wlc->cck_40txbw != AUTO)
+						mimo_txbw = wlc->cck_40txbw;
+				}
+			} else {
+				/* mcs32 is 40 b/w only.
+				 * This is possible for probe packets on a STA during SCAN
+				 */
+				if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
+					/* mcs 0 */
+					rspec[k] = RSPEC_MIMORATE;
+				}
+				mimo_txbw = PHY_TXC1_BW_20MHZ;
+			}
+
+			/* Set channel width */
+			rspec[k] &= ~RSPEC_BW_MASK;
+			if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
+				rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
+			else
+				rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
+
+			/* Set Short GI */
+#ifdef NOSGIYET
+			if (IS_MCS(rspec[k])
+			    && (txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
+				rspec[k] |= RSPEC_SHORT_GI;
+			else if (!(txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
+				rspec[k] &= ~RSPEC_SHORT_GI;
+#else
+			rspec[k] &= ~RSPEC_SHORT_GI;
+#endif
+
+			mimo_preamble_type = WLC_MM_PREAMBLE;
+			if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
+				mimo_preamble_type = WLC_GF_PREAMBLE;
+
+			if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
+			    && (!IS_MCS(rspec[k]))) {
+				WL_ERROR("wl%d: %s: IEEE80211_TX_RC_MCS != IS_MCS(rspec)\n",
+					 WLCWLUNIT(wlc), __func__);
+				ASSERT(0 && "Rate mismatch");
+			}
+
+			if (IS_MCS(rspec[k])) {
+				preamble_type[k] = mimo_preamble_type;
+
+				/* if SGI is selected, then forced mm for single stream */
+				if ((rspec[k] & RSPEC_SHORT_GI)
+				    && IS_SINGLE_STREAM(rspec[k] &
+							RSPEC_RATE_MASK)) {
+					preamble_type[k] = WLC_MM_PREAMBLE;
+				}
+			}
+
+			/* mimo bw field MUST now be valid in the rspec (it affects duration calculations) */
+			ASSERT(VALID_RATE_DBG(wlc, rspec[0]));
+
+			/* should be better conditionalized */
+			if (!IS_MCS(rspec[0])
+			    && (tx_info->control.rates[0].
+				flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
+				preamble_type[k] = WLC_SHORT_PREAMBLE;
+
+			ASSERT(!IS_MCS(rspec[0])
+			       || WLC_IS_MIMO_PREAMBLE(preamble_type[k]));
+		}
+	} else {
+		for (k = 0; k < hw->max_rates; k++) {
+			/* Set ctrlchbw as 20Mhz */
+			ASSERT(!IS_MCS(rspec[k]));
+			rspec[k] &= ~RSPEC_BW_MASK;
+			rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
+
+			/* for nphy, stf of ofdm frames must follow policies */
+			if (WLCISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
+				rspec[k] &= ~RSPEC_STF_MASK;
+				rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
+			}
+		}
+	}
+
+	/* Reset these for use with AMPDU's */
+	txrate[0]->count = 0;
+	txrate[1]->count = 0;
+
+	/* (2) PROTECTION, may change rspec */
+	if ((ieee80211_is_data(h->frame_control) ||
+	    ieee80211_is_mgmt(h->frame_control)) &&
+	    (phylen > wlc->RTSThresh) && !is_multicast_ether_addr(h->addr1))
+		use_rts = true;
+
+	/* (3) PLCP: determine PLCP header and MAC duration, fill d11txh_t */
+	wlc_compute_plcp(wlc, rspec[0], phylen, plcp);
+	wlc_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
+	memcpy(&txh->FragPLCPFallback,
+	       plcp_fallback, sizeof(txh->FragPLCPFallback));
+
+	/* Length field now put in CCK FBR CRC field */
+	if (IS_CCK(rspec[1])) {
+		txh->FragPLCPFallback[4] = phylen & 0xff;
+		txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
+	}
+
+	/* MIMO-RATE: need validation ?? */
+	mainrates =
+	    IS_OFDM(rspec[0]) ? D11A_PHY_HDR_GRATE((ofdm_phy_hdr_t *) plcp) :
+	    plcp[0];
+
+	/* DUR field for main rate */
+	if (!ieee80211_is_pspoll(h->frame_control) &&
+	    !is_multicast_ether_addr(h->addr1) && !use_rifs) {
+		durid =
+		    wlc_compute_frame_dur(wlc, rspec[0], preamble_type[0],
+					  next_frag_len);
+		h->duration_id = cpu_to_le16(durid);
+	} else if (use_rifs) {
+		/* NAV protect to end of next max packet size */
+		durid =
+		    (u16) wlc_calc_frame_time(wlc, rspec[0],
+						 preamble_type[0],
+						 DOT11_MAX_FRAG_LEN);
+		durid += RIFS_11N_TIME;
+		h->duration_id = cpu_to_le16(durid);
+	}
+
+	/* DUR field for fallback rate */
+	if (ieee80211_is_pspoll(h->frame_control))
+		txh->FragDurFallback = h->duration_id;
+	else if (is_multicast_ether_addr(h->addr1) || use_rifs)
+		txh->FragDurFallback = 0;
+	else {
+		durid = wlc_compute_frame_dur(wlc, rspec[1],
+					      preamble_type[1], next_frag_len);
+		txh->FragDurFallback = cpu_to_le16(durid);
+	}
+
+	/* (4) MAC-HDR: MacTxControlLow */
+	if (frag == 0)
+		mcl |= TXC_STARTMSDU;
+
+	if (!is_multicast_ether_addr(h->addr1))
+		mcl |= TXC_IMMEDACK;
+
+	if (BAND_5G(wlc->band->bandtype))
+		mcl |= TXC_FREQBAND_5G;
+
+	if (CHSPEC_IS40(WLC_BAND_PI_RADIO_CHANSPEC))
+		mcl |= TXC_BW_40;
+
+	/* set AMIC bit if using hardware TKIP MIC */
+	if (hwtkmic)
+		mcl |= TXC_AMIC;
+
+	txh->MacTxControlLow = cpu_to_le16(mcl);
+
+	/* MacTxControlHigh */
+	mch = 0;
+
+	/* Set fallback rate preamble type */
+	if ((preamble_type[1] == WLC_SHORT_PREAMBLE) ||
+	    (preamble_type[1] == WLC_GF_PREAMBLE)) {
+		ASSERT((preamble_type[1] == WLC_GF_PREAMBLE) ||
+		       (!IS_MCS(rspec[1])));
+		if (RSPEC2RATE(rspec[1]) != WLC_RATE_1M)
+			mch |= TXC_PREAMBLE_DATA_FB_SHORT;
+	}
+
+	/* MacFrameControl */
+	memcpy(&txh->MacFrameControl, &h->frame_control, sizeof(u16));
+	txh->TxFesTimeNormal = cpu_to_le16(0);
+
+	txh->TxFesTimeFallback = cpu_to_le16(0);
+
+	/* TxFrameRA */
+	memcpy(&txh->TxFrameRA, &h->addr1, ETH_ALEN);
+
+	/* TxFrameID */
+	txh->TxFrameID = cpu_to_le16(frameid);
+
+	/* TxStatus, Note the case of recreating the first frag of a suppressed frame
+	 * then we may need to reset the retry cnt's via the status reg
+	 */
+	txh->TxStatus = cpu_to_le16(status);
+
+	/* extra fields for ucode AMPDU aggregation, the new fields are added to
+	 * the END of previous structure so that it's compatible in driver.
+	 */
+	txh->MaxNMpdus = cpu_to_le16(0);
+	txh->MaxABytes_MRT = cpu_to_le16(0);
+	txh->MaxABytes_FBR = cpu_to_le16(0);
+	txh->MinMBytes = cpu_to_le16(0);
+
+	/* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration, furnish d11txh_t */
+	/* RTS PLCP header and RTS frame */
+	if (use_rts || use_cts) {
+		if (use_rts && use_cts)
+			use_cts = false;
+
+		for (k = 0; k < 2; k++) {
+			rts_rspec[k] = wlc_rspec_to_rts_rspec(wlc, rspec[k],
+							      false,
+							      mimo_ctlchbw);
+		}
+
+		if (!IS_OFDM(rts_rspec[0]) &&
+		    !((RSPEC2RATE(rts_rspec[0]) == WLC_RATE_1M) ||
+		      (wlc->PLCPHdr_override == WLC_PLCP_LONG))) {
+			rts_preamble_type[0] = WLC_SHORT_PREAMBLE;
+			mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
+		}
+
+		if (!IS_OFDM(rts_rspec[1]) &&
+		    !((RSPEC2RATE(rts_rspec[1]) == WLC_RATE_1M) ||
+		      (wlc->PLCPHdr_override == WLC_PLCP_LONG))) {
+			rts_preamble_type[1] = WLC_SHORT_PREAMBLE;
+			mch |= TXC_PREAMBLE_RTS_FB_SHORT;
+		}
+
+		/* RTS/CTS additions to MacTxControlLow */
+		if (use_cts) {
+			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDCTS);
+		} else {
+			txh->MacTxControlLow |= cpu_to_le16(TXC_SENDRTS);
+			txh->MacTxControlLow |= cpu_to_le16(TXC_LONGFRAME);
+		}
+
+		/* RTS PLCP header */
+		ASSERT(IS_ALIGNED((unsigned long)txh->RTSPhyHeader, sizeof(u16)));
+		rts_plcp = txh->RTSPhyHeader;
+		if (use_cts)
+			rts_phylen = DOT11_CTS_LEN + FCS_LEN;
+		else
+			rts_phylen = DOT11_RTS_LEN + FCS_LEN;
+
+		wlc_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
+
+		/* fallback rate version of RTS PLCP header */
+		wlc_compute_plcp(wlc, rts_rspec[1], rts_phylen,
+				 rts_plcp_fallback);
+		memcpy(&txh->RTSPLCPFallback, rts_plcp_fallback,
+		       sizeof(txh->RTSPLCPFallback));
+
+		/* RTS frame fields... */
+		rts = (struct ieee80211_rts *)&txh->rts_frame;
+
+		durid = wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
+					       rspec[0], rts_preamble_type[0],
+					       preamble_type[0], phylen, false);
+		rts->duration = cpu_to_le16(durid);
+		/* fallback rate version of RTS DUR field */
+		durid = wlc_compute_rtscts_dur(wlc, use_cts,
+					       rts_rspec[1], rspec[1],
+					       rts_preamble_type[1],
+					       preamble_type[1], phylen, false);
+		txh->RTSDurFallback = cpu_to_le16(durid);
+
+		if (use_cts) {
+			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+							 IEEE80211_STYPE_CTS);
+
+			memcpy(&rts->ra, &h->addr2, ETH_ALEN);
+		} else {
+			rts->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+							 IEEE80211_STYPE_RTS);
+
+			memcpy(&rts->ra, &h->addr1, 2 * ETH_ALEN);
+		}
+
+		/* mainrate
+		 *    low 8 bits: main frag rate/mcs,
+		 *    high 8 bits: rts/cts rate/mcs
+		 */
+		mainrates |= (IS_OFDM(rts_rspec[0]) ?
+			      D11A_PHY_HDR_GRATE((ofdm_phy_hdr_t *) rts_plcp) :
+			      rts_plcp[0]) << 8;
+	} else {
+		memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
+		memset((char *)&txh->rts_frame, 0,
+			sizeof(struct ieee80211_rts));
+		memset((char *)txh->RTSPLCPFallback, 0,
+		      sizeof(txh->RTSPLCPFallback));
+		txh->RTSDurFallback = 0;
+	}
+
+#ifdef SUPPORT_40MHZ
+	/* add null delimiter count */
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) {
+		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
+		    wlc_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
+	}
+#endif
+
+	/* Now that RTS/RTS FB preamble types are updated, write the final value */
+	txh->MacTxControlHigh = cpu_to_le16(mch);
+
+	/* MainRates (both the rts and frag plcp rates have been calculated now) */
+	txh->MainRates = cpu_to_le16(mainrates);
+
+	/* XtraFrameTypes */
+	xfts = FRAMETYPE(rspec[1], wlc->mimoft);
+	xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
+	xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
+	xfts |=
+	    CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
+	txh->XtraFrameTypes = cpu_to_le16(xfts);
+
+	/* PhyTxControlWord */
+	phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
+	if ((preamble_type[0] == WLC_SHORT_PREAMBLE) ||
+	    (preamble_type[0] == WLC_GF_PREAMBLE)) {
+		ASSERT((preamble_type[0] == WLC_GF_PREAMBLE)
+		       || !IS_MCS(rspec[0]));
+		if (RSPEC2RATE(rspec[0]) != WLC_RATE_1M)
+			phyctl |= PHY_TXC_SHORT_HDR;
+		wlc->pub->_cnt->txprshort++;
+	}
+
+	/* phytxant is properly bit shifted */
+	phyctl |= wlc_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
+	txh->PhyTxControlWord = cpu_to_le16(phyctl);
+
+	/* PhyTxControlWord_1 */
+	if (WLC_PHY_11N_CAP(wlc->band)) {
+		u16 phyctl1 = 0;
+
+		phyctl1 = wlc_phytxctl1_calc(wlc, rspec[0]);
+		txh->PhyTxControlWord_1 = cpu_to_le16(phyctl1);
+		phyctl1 = wlc_phytxctl1_calc(wlc, rspec[1]);
+		txh->PhyTxControlWord_1_Fbr = cpu_to_le16(phyctl1);
+
+		if (use_rts || use_cts) {
+			phyctl1 = wlc_phytxctl1_calc(wlc, rts_rspec[0]);
+			txh->PhyTxControlWord_1_Rts = cpu_to_le16(phyctl1);
+			phyctl1 = wlc_phytxctl1_calc(wlc, rts_rspec[1]);
+			txh->PhyTxControlWord_1_FbrRts = cpu_to_le16(phyctl1);
+		}
+
+		/*
+		 * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set,
+		 * fill in non-zero MModeLen and/or MModeFbrLen
+		 *  it will be unnecessary if they are separated
+		 */
+		if (IS_MCS(rspec[0]) && (preamble_type[0] == WLC_MM_PREAMBLE)) {
+			u16 mmodelen =
+			    wlc_calc_lsig_len(wlc, rspec[0], phylen);
+			txh->MModeLen = cpu_to_le16(mmodelen);
+		}
+
+		if (IS_MCS(rspec[1]) && (preamble_type[1] == WLC_MM_PREAMBLE)) {
+			u16 mmodefbrlen =
+			    wlc_calc_lsig_len(wlc, rspec[1], phylen);
+			txh->MModeFbrLen = cpu_to_le16(mmodefbrlen);
+		}
+	}
+
+	if (IS_MCS(rspec[0]))
+		ASSERT(IS_MCS(rspec[1]));
+
+	ASSERT(!IS_MCS(rspec[0]) ||
+	       ((preamble_type[0] == WLC_MM_PREAMBLE) == (txh->MModeLen != 0)));
+	ASSERT(!IS_MCS(rspec[1]) ||
+	       ((preamble_type[1] == WLC_MM_PREAMBLE) ==
+		(txh->MModeFbrLen != 0)));
+
+	ac = wme_fifo2ac[queue];
+	if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
+		uint frag_dur, dur, dur_fallback;
+
+		ASSERT(!is_multicast_ether_addr(h->addr1));
+
+		/* WME: Update TXOP threshold */
+		if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) {
+			frag_dur =
+			    wlc_calc_frame_time(wlc, rspec[0], preamble_type[0],
+						phylen);
+
+			if (rts) {
+				/* 1 RTS or CTS-to-self frame */
+				dur =
+				    wlc_calc_cts_time(wlc, rts_rspec[0],
+						      rts_preamble_type[0]);
+				dur_fallback =
+				    wlc_calc_cts_time(wlc, rts_rspec[1],
+						      rts_preamble_type[1]);
+				/* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
+				dur += le16_to_cpu(rts->duration);
+				dur_fallback +=
+					le16_to_cpu(txh->RTSDurFallback);
+			} else if (use_rifs) {
+				dur = frag_dur;
+				dur_fallback = 0;
+			} else {
+				/* frame + SIFS + ACK */
+				dur = frag_dur;
+				dur +=
+				    wlc_compute_frame_dur(wlc, rspec[0],
+							  preamble_type[0], 0);
+
+				dur_fallback =
+				    wlc_calc_frame_time(wlc, rspec[1],
+							preamble_type[1],
+							phylen);
+				dur_fallback +=
+				    wlc_compute_frame_dur(wlc, rspec[1],
+							  preamble_type[1], 0);
+			}
+			/* NEED to set TxFesTimeNormal (hard) */
+			txh->TxFesTimeNormal = cpu_to_le16((u16) dur);
+			/* NEED to set fallback rate version of TxFesTimeNormal (hard) */
+			txh->TxFesTimeFallback =
+				cpu_to_le16((u16) dur_fallback);
+
+			/* update txop byte threshold (txop minus intraframe overhead) */
+			if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
+				{
+					uint newfragthresh;
+
+					newfragthresh =
+					    wlc_calc_frame_len(wlc, rspec[0],
+							       preamble_type[0],
+							       (wlc->
+								edcf_txop[ac] -
+								(dur -
+								 frag_dur)));
+					/* range bound the fragthreshold */
+					if (newfragthresh < DOT11_MIN_FRAG_LEN)
+						newfragthresh =
+						    DOT11_MIN_FRAG_LEN;
+					else if (newfragthresh >
+						 wlc->usr_fragthresh)
+						newfragthresh =
+						    wlc->usr_fragthresh;
+					/* update the fragthresh and do txc update */
+					if (wlc->fragthresh[queue] !=
+					    (u16) newfragthresh) {
+						wlc->fragthresh[queue] =
+						    (u16) newfragthresh;
+					}
+				}
+			} else
+				WL_ERROR("wl%d: %s txop invalid for rate %d\n",
+					 wlc->pub->unit, fifo_names[queue],
+					 RSPEC2RATE(rspec[0]));
+
+			if (dur > wlc->edcf_txop[ac])
+				WL_ERROR("wl%d: %s: %s txop exceeded phylen %d/%d dur %d/%d\n",
+					 wlc->pub->unit, __func__,
+					 fifo_names[queue],
+					 phylen, wlc->fragthresh[queue],
+					 dur, wlc->edcf_txop[ac]);
+		}
+	}
+
+	return 0;
+}
+
+void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs)
+{
+	struct wlc_bsscfg *cfg = wlc->cfg;
+
+	wlc->pub->_cnt->tbtt++;
+
+	if (BSSCFG_STA(cfg)) {
+		/* run watchdog here if the watchdog timer is not armed */
+		if (WLC_WATCHDOG_TBTT(wlc)) {
+			u32 cur, delta;
+			if (wlc->WDarmed) {
+				wl_del_timer(wlc->wl, wlc->wdtimer);
+				wlc->WDarmed = false;
+			}
+
+			cur = OSL_SYSUPTIME();
+			delta = cur > wlc->WDlast ? cur - wlc->WDlast :
+			    (u32) ~0 - wlc->WDlast + cur + 1;
+			if (delta >= TIMER_INTERVAL_WATCHDOG) {
+				wlc_watchdog((void *)wlc);
+				wlc->WDlast = cur;
+			}
+
+			wl_add_timer(wlc->wl, wlc->wdtimer,
+				     wlc_watchdog_backup_bi(wlc), true);
+			wlc->WDarmed = true;
+		}
+	}
+
+	if (!cfg->BSS) {
+		/* DirFrmQ is now valid...defer setting until end of ATIM window */
+		wlc->qvalid |= MCMD_DIRFRMQVAL;
+	}
+}
+
+/* GP timer is a freerunning 32 bit counter, decrements at 1 us rate */
+void wlc_hwtimer_gptimer_set(struct wlc_info *wlc, uint us)
+{
+	W_REG(&wlc->regs->gptimer, us);
+}
+
+void wlc_hwtimer_gptimer_abort(struct wlc_info *wlc)
+{
+	W_REG(&wlc->regs->gptimer, 0);
+}
+
+static void wlc_hwtimer_gptimer_cb(struct wlc_info *wlc)
+{
+	/* when interrupt is generated, the counter is loaded with last value
+	 * written and continue to decrement. So it has to be cleaned first
+	 */
+	W_REG(&wlc->regs->gptimer, 0);
+}
+
+/*
+ * This fn has all the high level dpc processing from wlc_dpc.
+ * POLICY: no macinstatus change, no bounding loop.
+ *         All dpc bounding should be handled in BMAC dpc, like txstatus and rxint
+ */
+void wlc_high_dpc(struct wlc_info *wlc, u32 macintstatus)
+{
+	d11regs_t *regs = wlc->regs;
+#ifdef BCMDBG
+	char flagstr[128];
+	static const bcm_bit_desc_t int_flags[] = {
+		{MI_MACSSPNDD, "MACSSPNDD"},
+		{MI_BCNTPL, "BCNTPL"},
+		{MI_TBTT, "TBTT"},
+		{MI_BCNSUCCESS, "BCNSUCCESS"},
+		{MI_BCNCANCLD, "BCNCANCLD"},
+		{MI_ATIMWINEND, "ATIMWINEND"},
+		{MI_PMQ, "PMQ"},
+		{MI_NSPECGEN_0, "NSPECGEN_0"},
+		{MI_NSPECGEN_1, "NSPECGEN_1"},
+		{MI_MACTXERR, "MACTXERR"},
+		{MI_NSPECGEN_3, "NSPECGEN_3"},
+		{MI_PHYTXERR, "PHYTXERR"},
+		{MI_PME, "PME"},
+		{MI_GP0, "GP0"},
+		{MI_GP1, "GP1"},
+		{MI_DMAINT, "DMAINT"},
+		{MI_TXSTOP, "TXSTOP"},
+		{MI_CCA, "CCA"},
+		{MI_BG_NOISE, "BG_NOISE"},
+		{MI_DTIM_TBTT, "DTIM_TBTT"},
+		{MI_PRQ, "PRQ"},
+		{MI_PWRUP, "PWRUP"},
+		{MI_RFDISABLE, "RFDISABLE"},
+		{MI_TFS, "TFS"},
+		{MI_PHYCHANGED, "PHYCHANGED"},
+		{MI_TO, "TO"},
+		{0, NULL}
+	};
+
+	if (macintstatus & ~(MI_TBTT | MI_TXSTOP)) {
+		bcm_format_flags(int_flags, macintstatus, flagstr,
+				 sizeof(flagstr));
+		WL_TRACE("wl%d: macintstatus 0x%x %s\n",
+			 wlc->pub->unit, macintstatus, flagstr);
+	}
+#endif				/* BCMDBG */
+
+	if (macintstatus & MI_PRQ) {
+		/* Process probe request FIFO */
+		ASSERT(0 && "PRQ Interrupt in non-MBSS");
+	}
+
+	/* TBTT indication */
+	/* ucode only gives either TBTT or DTIM_TBTT, not both */
+	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
+		wlc_tbtt(wlc, regs);
+
+	if (macintstatus & MI_GP0) {
+		WL_ERROR("wl%d: PSM microcode watchdog fired at %d (seconds). Resetting.\n",
+			 wlc->pub->unit, wlc->pub->now);
+
+		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
+					__func__, wlc->pub->sih->chip,
+					wlc->pub->sih->chiprev);
+
+		wlc->pub->_cnt->psmwds++;
+
+		/* big hammer */
+		wl_init(wlc->wl);
+	}
+
+	/* gptimer timeout */
+	if (macintstatus & MI_TO) {
+		wlc_hwtimer_gptimer_cb(wlc);
+	}
+
+	if (macintstatus & MI_RFDISABLE) {
+		WL_ERROR("wl%d: MAC Detected a change on the RF Disable Input 0x%x\n",
+			 wlc->pub->unit,
+			 R_REG(&regs->phydebug) & PDBG_RFD);
+		/* delay the cleanup to wl_down in IBSS case */
+		if ((R_REG(&regs->phydebug) & PDBG_RFD)) {
+			int idx;
+			struct wlc_bsscfg *bsscfg;
+			FOREACH_BSS(wlc, idx, bsscfg) {
+				if (!BSSCFG_STA(bsscfg) || !bsscfg->enable
+				    || !bsscfg->BSS)
+					continue;
+				WL_ERROR("wl%d: wlc_dpc: rfdisable -> wlc_bsscfg_disable()\n",
+					 wlc->pub->unit);
+			}
+		}
+	}
+
+	/* send any enq'd tx packets. Just makes sure to jump start tx */
+	if (!pktq_empty(&wlc->active_queue->q))
+		wlc_send_q(wlc, wlc->active_queue);
+
+	ASSERT(wlc_ps_check(wlc));
+}
+
+static void wlc_war16165(struct wlc_info *wlc, bool tx)
+{
+	if (tx) {
+		/* the post-increment is used in STAY_AWAKE macro */
+		if (wlc->txpend16165war++ == 0)
+			wlc_set_ps_ctrl(wlc);
+	} else {
+		wlc->txpend16165war--;
+		if (wlc->txpend16165war == 0)
+			wlc_set_ps_ctrl(wlc);
+	}
+}
+
+/* process an individual tx_status_t */
+/* WLC_HIGH_API */
+bool BCMFASTPATH
+wlc_dotxstatus(struct wlc_info *wlc, tx_status_t *txs, u32 frm_tx2)
+{
+	struct sk_buff *p;
+	uint queue;
+	d11txh_t *txh;
+	struct scb *scb = NULL;
+	bool free_pdu;
+	int tx_rts, tx_frame_count, tx_rts_count;
+	uint totlen, supr_status;
+	bool lastframe;
+	struct ieee80211_hdr *h;
+	u16 mcl;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_tx_rate *txrate;
+	int i;
+
+	(void)(frm_tx2);	/* Compiler reference to avoid unused variable warning */
+
+	/* discard intermediate indications for ucode with one legitimate case:
+	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
+	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
+	 *   transmission count)
+	 */
+	if (!(txs->status & TX_STATUS_AMPDU)
+	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
+		WLCNTADD(wlc->pub->_cnt->txnoack,
+			 ((txs->
+			   status & TX_STATUS_FRM_RTX_MASK) >>
+			  TX_STATUS_FRM_RTX_SHIFT));
+		WL_ERROR("%s: INTERMEDIATE but not AMPDU\n", __func__);
+		return false;
+	}
+
+	queue = txs->frameid & TXFID_QUEUE_MASK;
+	ASSERT(queue < NFIFO);
+	if (queue >= NFIFO) {
+		p = NULL;
+		goto fatal;
+	}
+
+	p = GETNEXTTXP(wlc, queue);
+	if (WLC_WAR16165(wlc))
+		wlc_war16165(wlc, false);
+	if (p == NULL)
+		goto fatal;
+
+	txh = (d11txh_t *) (p->data);
+	mcl = le16_to_cpu(txh->MacTxControlLow);
+
+	if (txs->phyerr) {
+		if (WL_ERROR_ON()) {
+			WL_ERROR("phyerr 0x%x, rate 0x%x\n",
+				 txs->phyerr, txh->MainRates);
+			wlc_print_txdesc(txh);
+		}
+		wlc_print_txstatus(txs);
+	}
+
+	ASSERT(txs->frameid == cpu_to_le16(txh->TxFrameID));
+	if (txs->frameid != cpu_to_le16(txh->TxFrameID))
+		goto fatal;
+
+	tx_info = IEEE80211_SKB_CB(p);
+	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+
+	if (tx_info->control.sta)
+		scb = (struct scb *)tx_info->control.sta->drv_priv;
+
+	if (N_ENAB(wlc->pub)) {
+		u8 *plcp = (u8 *) (txh + 1);
+		if (PLCP3_ISSGI(plcp[3]))
+			wlc->pub->_cnt->txmpdu_sgi++;
+		if (PLCP3_ISSTBC(plcp[3]))
+			wlc->pub->_cnt->txmpdu_stbc++;
+	}
+
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+		ASSERT((mcl & TXC_AMPDU_MASK) != TXC_AMPDU_NONE);
+		wlc_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
+		return false;
+	}
+
+	supr_status = txs->status & TX_STATUS_SUPR_MASK;
+	if (supr_status == TX_STATUS_SUPR_BADCH)
+		WL_NONE("%s: Pkt tx suppressed, possibly channel %d\n",
+			__func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
+
+	tx_rts = cpu_to_le16(txh->MacTxControlLow) & TXC_SENDRTS;
+	tx_frame_count =
+	    (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
+	tx_rts_count =
+	    (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
+
+	lastframe = !ieee80211_has_morefrags(h->frame_control);
+
+	if (!lastframe) {
+		WL_ERROR("Not last frame!\n");
+	} else {
+		u16 sfbl, lfbl;
+		ieee80211_tx_info_clear_status(tx_info);
+		if (queue < AC_COUNT) {
+			sfbl = WLC_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
+			lfbl = WLC_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
+		} else {
+			sfbl = wlc->SFBL;
+			lfbl = wlc->LFBL;
+		}
+
+		txrate = tx_info->status.rates;
+		/* FIXME: this should use a combination of sfbl, lfbl depending on frame length and RTS setting */
+		if ((tx_frame_count > sfbl) && (txrate[1].idx >= 0)) {
+			/* rate selection requested a fallback rate and we used it */
+			txrate->count = lfbl;
+			txrate[1].count = tx_frame_count - lfbl;
+		} else {
+			/* rate selection did not request fallback rate, or we didn't need it */
+			txrate->count = tx_frame_count;
+			/* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */
+			txrate[1].idx = -1;
+			txrate[1].count = 0;
+		}
+
+		/* clear the rest of the rates */
+		for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
+			txrate[i].idx = -1;
+			txrate[i].count = 0;
+		}
+
+		if (txs->status & TX_STATUS_ACK_RCV)
+			tx_info->flags |= IEEE80211_TX_STAT_ACK;
+	}
+
+	totlen = pkttotlen(p);
+	free_pdu = true;
+
+	wlc_txfifo_complete(wlc, queue, 1);
+
+	if (lastframe) {
+		p->next = NULL;
+		p->prev = NULL;
+		wlc->txretried = 0;
+		/* remove PLCP & Broadcom tx descriptor header */
+		skb_pull(p, D11_PHY_HDR_LEN);
+		skb_pull(p, D11_TXH_LEN);
+		ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
+		wlc->pub->_cnt->ieee_tx_status++;
+	} else {
+		WL_ERROR("%s: Not last frame => not calling tx_status\n",
+			 __func__);
+	}
+
+	return false;
+
+ fatal:
+	ASSERT(0);
+	if (p)
+		pkt_buf_free_skb(p);
+
+	return true;
+
+}
+
+void BCMFASTPATH
+wlc_txfifo_complete(struct wlc_info *wlc, uint fifo, s8 txpktpend)
+{
+	TXPKTPENDDEC(wlc, fifo, txpktpend);
+	WL_TRACE("wlc_txfifo_complete, pktpend dec %d to %d\n",
+		 txpktpend, TXPKTPENDGET(wlc, fifo));
+
+	/* There is more room; mark precedences related to this FIFO sendable */
+	WLC_TX_FIFO_ENAB(wlc, fifo);
+	ASSERT(TXPKTPENDGET(wlc, fifo) >= 0);
+
+	if (!TXPKTPENDTOT(wlc)) {
+		if (wlc->block_datafifo & DATA_BLOCK_TX_SUPR)
+			wlc_bsscfg_tx_check(wlc);
+	}
+
+	/* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
+	if (AP_ENAB(wlc->pub) &&
+	    wlc->bcmcfifo_drain && !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) {
+		wlc->bcmcfifo_drain = false;
+		wlc_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, WLC_BAND_AUTO);
+	}
+
+	/* figure out which bsscfg is being worked on... */
+}
+
+/* Given the beacon interval in kus, and a 64 bit TSF in us,
+ * return the offset (in us) of the TSF from the last TBTT
+ */
+u32 wlc_calc_tbtt_offset(u32 bp, u32 tsf_h, u32 tsf_l)
+{
+	u32 k, btklo, btkhi, offset;
+
+	/* TBTT is always an even multiple of the beacon_interval,
+	 * so the TBTT less than or equal to the beacon timestamp is
+	 * the beacon timestamp minus the beacon timestamp modulo
+	 * the beacon interval.
+	 *
+	 * TBTT = BT - (BT % BIu)
+	 *      = (BTk - (BTk % BP)) * 2^10
+	 *
+	 * BT = beacon timestamp (usec, 64bits)
+	 * BTk = beacon timestamp (Kusec, 54bits)
+	 * BP = beacon interval (Kusec, 16bits)
+	 * BIu = BP * 2^10 = beacon interval (usec, 26bits)
+	 *
+	 * To keep the calculations in u32s, the modulo operation
+	 * on the high part of BT needs to be done in parts using the
+	 * relations:
+	 * X*Y mod Z = ((X mod Z) * (Y mod Z)) mod Z
+	 * and
+	 * (X + Y) mod Z = ((X mod Z) + (Y mod Z)) mod Z
+	 *
+	 * So, if BTk[n] = u16 n [0,3] of BTk.
+	 * BTk % BP = SUM((BTk[n] * 2^16n) % BP , 0<=n<4) % BP
+	 * and the SUM term can be broken down:
+	 * (BTk[n] *     2^16n)    % BP
+	 * (BTk[n] * (2^16n % BP)) % BP
+	 *
+	 * Create a set of power of 2 mod BP constants:
+	 * K[n] = 2^(16n) % BP
+	 *      = (K[n-1] * 2^16) % BP
+	 * K[2] = 2^32 % BP = ((2^16 % BP) * 2^16) % BP
+	 *
+	 * BTk % BP = BTk[0-1] % BP +
+	 *            (BTk[2] * K[2]) % BP +
+	 *            (BTk[3] * K[3]) % BP
+	 *
+	 * Since K[n] < 2^16 and BTk[n] is < 2^16, then BTk[n] * K[n] < 2^32
+	 */
+
+	/* BTk = BT >> 10, btklo = BTk[0-3], bkthi = BTk[4-6] */
+	btklo = (tsf_h << 22) | (tsf_l >> 10);
+	btkhi = tsf_h >> 10;
+
+	/* offset = BTk % BP */
+	offset = btklo % bp;
+
+	/* K[2] = ((2^16 % BP) * 2^16) % BP */
+	k = (u32) (1 << 16) % bp;
+	k = (u32) (k * 1 << 16) % (u32) bp;
+
+	/* offset += (BTk[2] * K[2]) % BP */
+	offset += ((btkhi & 0xffff) * k) % bp;
+
+	/* BTk[3] */
+	btkhi = btkhi >> 16;
+
+	/* k[3] = (K[2] * 2^16) % BP */
+	k = (k << 16) % bp;
+
+	/* offset += (BTk[3] * K[3]) % BP */
+	offset += ((btkhi & 0xffff) * k) % bp;
+
+	offset = offset % bp;
+
+	/* convert offset from kus to us by shifting up 10 bits and
+	 * add in the low 10 bits of tsf that we ignored
+	 */
+	offset = (offset << 10) + (tsf_l & 0x3FF);
+
+	return offset;
+}
+
+/* Update beacon listen interval in shared memory */
+void wlc_bcn_li_upd(struct wlc_info *wlc)
+{
+	if (AP_ENAB(wlc->pub))
+		return;
+
+	/* wake up every DTIM is the default */
+	if (wlc->bcn_li_dtim == 1)
+		wlc_write_shm(wlc, M_BCN_LI, 0);
+	else
+		wlc_write_shm(wlc, M_BCN_LI,
+			      (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
+}
+
+static void
+prep_mac80211_status(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p,
+		     struct ieee80211_rx_status *rx_status)
+{
+	u32 tsf_l, tsf_h;
+	wlc_d11rxhdr_t *wlc_rxh = (wlc_d11rxhdr_t *) rxh;
+	int preamble;
+	int channel;
+	ratespec_t rspec;
+	unsigned char *plcp;
+
+#if 0
+	/* Clearly, this is bogus -- reading the TSF now is wrong */
+	wlc_read_tsf(wlc, &tsf_l, &tsf_h);	/* mactime */
+	rx_status->mactime = tsf_h;
+	rx_status->mactime <<= 32;
+	rx_status->mactime |= tsf_l;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU; /* clearly wrong */
+#endif
+
+	channel = WLC_CHAN_CHANNEL(rxh->RxChan);
+
+	if (channel > 14) {
+		rx_status->band = IEEE80211_BAND_5GHZ;
+		rx_status->freq = ieee80211_ofdm_chan_to_freq(
+					WF_CHAN_FACTOR_5_G/2, channel);
+
+	} else {
+		rx_status->band = IEEE80211_BAND_2GHZ;
+		rx_status->freq = ieee80211_dsss_chan_to_freq(channel);
+	}
+
+	rx_status->signal = wlc_rxh->rssi;	/* signal */
+
+	/* noise */
+	/* qual */
+	rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;	/* ant */
+
+	plcp = p->data;
+
+	rspec = wlc_compute_rspec(rxh, plcp);
+	if (IS_MCS(rspec)) {
+		rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
+		rx_status->flag |= RX_FLAG_HT;
+		if (RSPEC_IS40MHZ(rspec))
+			rx_status->flag |= RX_FLAG_40MHZ;
+	} else {
+		switch (RSPEC2RATE(rspec)) {
+		case WLC_RATE_1M:
+			rx_status->rate_idx = 0;
+			break;
+		case WLC_RATE_2M:
+			rx_status->rate_idx = 1;
+			break;
+		case WLC_RATE_5M5:
+			rx_status->rate_idx = 2;
+			break;
+		case WLC_RATE_11M:
+			rx_status->rate_idx = 3;
+			break;
+		case WLC_RATE_6M:
+			rx_status->rate_idx = 4;
+			break;
+		case WLC_RATE_9M:
+			rx_status->rate_idx = 5;
+			break;
+		case WLC_RATE_12M:
+			rx_status->rate_idx = 6;
+			break;
+		case WLC_RATE_18M:
+			rx_status->rate_idx = 7;
+			break;
+		case WLC_RATE_24M:
+			rx_status->rate_idx = 8;
+			break;
+		case WLC_RATE_36M:
+			rx_status->rate_idx = 9;
+			break;
+		case WLC_RATE_48M:
+			rx_status->rate_idx = 10;
+			break;
+		case WLC_RATE_54M:
+			rx_status->rate_idx = 11;
+			break;
+		default:
+			WL_ERROR("%s: Unknown rate\n", __func__);
+		}
+
+		/* Determine short preamble and rate_idx */
+		preamble = 0;
+		if (IS_CCK(rspec)) {
+			if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
+				WL_ERROR("Short CCK\n");
+			rx_status->flag |= RX_FLAG_SHORTPRE;
+		} else if (IS_OFDM(rspec)) {
+			rx_status->flag |= RX_FLAG_SHORTPRE;
+		} else {
+			WL_ERROR("%s: Unknown modulation\n", __func__);
+		}
+	}
+
+	if (PLCP3_ISSGI(plcp[3]))
+		rx_status->flag |= RX_FLAG_SHORT_GI;
+
+	if (rxh->RxStatus1 & RXS_DECERR) {
+		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+		WL_ERROR("%s:  RX_FLAG_FAILED_PLCP_CRC\n", __func__);
+	}
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		WL_ERROR("%s:  RX_FLAG_FAILED_FCS_CRC\n", __func__);
+	}
+}
+
+static void
+wlc_recvctl(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p)
+{
+	int len_mpdu;
+	struct ieee80211_rx_status rx_status;
+#if defined(BCMDBG)
+	struct sk_buff *skb = p;
+#endif				/* BCMDBG */
+	/* Todo:
+	 * Cache plcp for first MPDU of AMPD and use chacched version for INTERMEDIATE.
+	 * Test for INTERMEDIATE  like so:
+	 * if (!(plcp[0] | plcp[1] | plcp[2]))
+	 */
+
+	memset(&rx_status, 0, sizeof(rx_status));
+	prep_mac80211_status(wlc, rxh, p, &rx_status);
+
+	/* mac header+body length, exclude CRC and plcp header */
+	len_mpdu = p->len - D11_PHY_HDR_LEN - FCS_LEN;
+	skb_pull(p, D11_PHY_HDR_LEN);
+	__skb_trim(p, len_mpdu);
+
+	ASSERT(!(p->next));
+	ASSERT(!(p->prev));
+
+	ASSERT(IS_ALIGNED((unsigned long)skb->data, 2));
+
+	memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
+	ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
+
+	wlc->pub->_cnt->ieee_rx++;
+	return;
+}
+
+void wlc_bss_list_free(struct wlc_info *wlc, struct wlc_bss_list *bss_list)
+{
+	uint index;
+
+	if (!bss_list) {
+		WL_ERROR("%s: Attempting to free NULL list\n", __func__);
+		return;
+	}
+	/* inspect all BSS descriptor */
+	for (index = 0; index < bss_list->count; index++) {
+		kfree(bss_list->ptrs[index]);
+		bss_list->ptrs[index] = NULL;
+	}
+	bss_list->count = 0;
+}
+
+/* Process received frames */
+/*
+ * Return true if more frames need to be processed. false otherwise.
+ * Param 'bound' indicates max. # frames to process before break out.
+ */
+/* WLC_HIGH_API */
+void BCMFASTPATH wlc_recv(struct wlc_info *wlc, struct sk_buff *p)
+{
+	d11rxhdr_t *rxh;
+	struct ieee80211_hdr *h;
+	uint len;
+	bool is_amsdu;
+
+	WL_TRACE("wl%d: wlc_recv\n", wlc->pub->unit);
+
+	/* frame starts with rxhdr */
+	rxh = (d11rxhdr_t *) (p->data);
+
+	/* strip off rxhdr */
+	skb_pull(p, wlc->hwrxoff);
+
+	/* fixup rx header endianness */
+	rxh->RxFrameSize = le16_to_cpu(rxh->RxFrameSize);
+	rxh->PhyRxStatus_0 = le16_to_cpu(rxh->PhyRxStatus_0);
+	rxh->PhyRxStatus_1 = le16_to_cpu(rxh->PhyRxStatus_1);
+	rxh->PhyRxStatus_2 = le16_to_cpu(rxh->PhyRxStatus_2);
+	rxh->PhyRxStatus_3 = le16_to_cpu(rxh->PhyRxStatus_3);
+	rxh->PhyRxStatus_4 = le16_to_cpu(rxh->PhyRxStatus_4);
+	rxh->PhyRxStatus_5 = le16_to_cpu(rxh->PhyRxStatus_5);
+	rxh->RxStatus1 = le16_to_cpu(rxh->RxStatus1);
+	rxh->RxStatus2 = le16_to_cpu(rxh->RxStatus2);
+	rxh->RxTSFTime = le16_to_cpu(rxh->RxTSFTime);
+	rxh->RxChan = le16_to_cpu(rxh->RxChan);
+
+	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
+	if (rxh->RxStatus1 & RXS_PBPRES) {
+		if (p->len < 2) {
+			wlc->pub->_cnt->rxrunt++;
+			WL_ERROR("wl%d: wlc_recv: rcvd runt of len %d\n",
+				 wlc->pub->unit, p->len);
+			goto toss;
+		}
+		skb_pull(p, 2);
+	}
+
+	h = (struct ieee80211_hdr *)(p->data + D11_PHY_HDR_LEN);
+	len = p->len;
+
+	if (rxh->RxStatus1 & RXS_FCSERR) {
+		if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
+			WL_ERROR("FCSERR while scanning******* - tossing\n");
+			goto toss;
+		} else {
+			WL_ERROR("RCSERR!!!\n");
+			goto toss;
+		}
+	}
+
+	/* check received pkt has at least frame control field */
+	if (len < D11_PHY_HDR_LEN + sizeof(h->frame_control)) {
+		wlc->pub->_cnt->rxrunt++;
+		goto toss;
+	}
+
+	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
+
+	/* explicitly test bad src address to avoid sending bad deauth */
+	if (!is_amsdu) {
+		/* CTS and ACK CTL frames are w/o a2 */
+
+		if (ieee80211_is_data(h->frame_control) ||
+		    ieee80211_is_mgmt(h->frame_control)) {
+			if ((is_zero_ether_addr(h->addr2) ||
+			     is_multicast_ether_addr(h->addr2))) {
+				WL_ERROR("wl%d: %s: dropping a frame with "
+					 "invalid src mac address, a2: %pM\n",
+					 wlc->pub->unit, __func__, h->addr2);
+				wlc->pub->_cnt->rxbadsrcmac++;
+				goto toss;
+			}
+			wlc->pub->_cnt->rxfrag++;
+		}
+	}
+
+	/* due to sheer numbers, toss out probe reqs for now */
+	if (ieee80211_is_probe_req(h->frame_control))
+		goto toss;
+
+	if (is_amsdu) {
+		WL_ERROR("%s: is_amsdu causing toss\n", __func__);
+		goto toss;
+	}
+
+	wlc_recvctl(wlc, rxh, p);
+	return;
+
+ toss:
+	pkt_buf_free_skb(p);
+}
+
+/* calculate frame duration for Mixed-mode L-SIG spoofing, return
+ * number of bytes goes in the length field
+ *
+ * Formula given by HT PHY Spec v 1.13
+ *   len = 3(nsyms + nstream + 3) - 3
+ */
+u16 BCMFASTPATH
+wlc_calc_lsig_len(struct wlc_info *wlc, ratespec_t ratespec, uint mac_len)
+{
+	uint nsyms, len = 0, kNdps;
+
+	WL_TRACE("wl%d: wlc_calc_lsig_len: rate %d, len%d\n",
+		 wlc->pub->unit, RSPEC2RATE(ratespec), mac_len);
+
+	if (IS_MCS(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		/* MCS_TXS(mcs) returns num tx streams - 1 */
+		int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
+
+		ASSERT(WLC_PHY_11N_CAP(wlc->band));
+		/* the payload duration calculation matches that of regular ofdm */
+		/* 1000Ndbps = kbps * 4 */
+		kNdps =
+		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
+			     RSPEC_ISSGI(ratespec)) * 4;
+
+		if (RSPEC_STC(ratespec) == 0)
+			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		nsyms += (tot_streams + 3);	/* (+3) account for HT-SIG(2) and HT-STF(1) */
+		/* 3 bytes/symbol @ legacy 6Mbps rate */
+		len = (3 * nsyms) - 3;	/* (-3) excluding service bits and tail bits */
+	}
+
+	return (u16) len;
+}
+
+/* calculate frame duration of a given rate and length, return time in usec unit */
+uint BCMFASTPATH
+wlc_calc_frame_time(struct wlc_info *wlc, ratespec_t ratespec, u8 preamble_type,
+		    uint mac_len)
+{
+	uint nsyms, dur = 0, Ndps, kNdps;
+	uint rate = RSPEC2RATE(ratespec);
+
+	if (rate == 0) {
+		ASSERT(0);
+		WL_ERROR("wl%d: WAR: using rate of 1 mbps\n", wlc->pub->unit);
+		rate = WLC_RATE_1M;
+	}
+
+	WL_TRACE("wl%d: wlc_calc_frame_time: rspec 0x%x, preamble_type %d, len%d\n",
+		 wlc->pub->unit, ratespec, preamble_type, mac_len);
+
+	if (IS_MCS(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
+		ASSERT(WLC_PHY_11N_CAP(wlc->band));
+		ASSERT(WLC_IS_MIMO_PREAMBLE(preamble_type));
+
+		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		if (preamble_type == WLC_MM_PREAMBLE)
+			dur += PREN_MM_EXT;
+		/* 1000Ndbps = kbps * 4 */
+		kNdps =
+		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
+			     RSPEC_ISSGI(ratespec)) * 4;
+
+		if (RSPEC_STC(ratespec) == 0)
+			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+			nsyms =
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, kNdps);
+		else
+			/* STBC needs to have even number of symbols */
+			nsyms =
+			    2 *
+			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
+				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
+
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (BAND_2G(wlc->band->bandtype))
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else if (IS_OFDM(rate)) {
+		dur = APHY_PREAMBLE_TIME;
+		dur += APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
+		nsyms =
+		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
+			 Ndps);
+		dur += APHY_SYMBOL_TIME * nsyms;
+		if (BAND_2G(wlc->band->bandtype))
+			dur += DOT11_OFDM_SIGNAL_EXTENSION;
+	} else {
+		/* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */
+		mac_len = mac_len * 8 * 2;
+		/* calc ceiling of bits/rate = microseconds of air time */
+		dur = (mac_len + rate - 1) / rate;
+		if (preamble_type & WLC_SHORT_PREAMBLE)
+			dur += BPHY_PLCP_SHORT_TIME;
+		else
+			dur += BPHY_PLCP_TIME;
+	}
+	return dur;
+}
+
+/* The opposite of wlc_calc_frame_time */
+static uint
+wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t ratespec, u8 preamble_type,
+		   uint dur)
+{
+	uint nsyms, mac_len, Ndps, kNdps;
+	uint rate = RSPEC2RATE(ratespec);
+
+	WL_TRACE("wl%d: wlc_calc_frame_len: rspec 0x%x, preamble_type %d, dur %d\n",
+		 wlc->pub->unit, ratespec, preamble_type, dur);
+
+	if (IS_MCS(ratespec)) {
+		uint mcs = ratespec & RSPEC_RATE_MASK;
+		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
+		ASSERT(WLC_PHY_11N_CAP(wlc->band));
+		dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
+		/* payload calculation matches that of regular ofdm */
+		if (BAND_2G(wlc->band->bandtype))
+			dur -= DOT11_OFDM_SIGNAL_EXTENSION;
+		/* kNdbps = kbps * 4 */
+		kNdps =
+		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
+			     RSPEC_ISSGI(ratespec)) * 4;
+		nsyms = dur / APHY_SYMBOL_TIME;
+		mac_len =
+		    ((nsyms * kNdps) -
+		     ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
+	} else if (IS_OFDM(ratespec)) {
+		dur -= APHY_PREAMBLE_TIME;
+		dur -= APHY_SIGNAL_TIME;
+		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
+		Ndps = rate * 2;
+		nsyms = dur / APHY_SYMBOL_TIME;
+		mac_len =
+		    ((nsyms * Ndps) -
+		     (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
+	} else {
+		if (preamble_type & WLC_SHORT_PREAMBLE)
+			dur -= BPHY_PLCP_SHORT_TIME;
+		else
+			dur -= BPHY_PLCP_TIME;
+		mac_len = dur * rate;
+		/* divide out factor of 2 in rate (1/2 mbps) */
+		mac_len = mac_len / 8 / 2;
+	}
+	return mac_len;
+}
+
+static uint
+wlc_calc_ba_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
+{
+	WL_TRACE("wl%d: wlc_calc_ba_time: rspec 0x%x, preamble_type %d\n",
+		 wlc->pub->unit, rspec, preamble_type);
+	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
+	 * or equal to the rate of the immediately previous frame in the FES
+	 */
+	rspec = WLC_BASIC_RATE(wlc, rspec);
+	ASSERT(VALID_RATE_DBG(wlc, rspec));
+
+	/* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
+	return wlc_calc_frame_time(wlc, rspec, preamble_type,
+				   (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
+				    FCS_LEN));
+}
+
+static uint BCMFASTPATH
+wlc_calc_ack_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
+{
+	uint dur = 0;
+
+	WL_TRACE("wl%d: wlc_calc_ack_time: rspec 0x%x, preamble_type %d\n",
+		 wlc->pub->unit, rspec, preamble_type);
+	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
+	 * or equal to the rate of the immediately previous frame in the FES
+	 */
+	rspec = WLC_BASIC_RATE(wlc, rspec);
+	ASSERT(VALID_RATE_DBG(wlc, rspec));
+
+	/* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
+	dur =
+	    wlc_calc_frame_time(wlc, rspec, preamble_type,
+				(DOT11_ACK_LEN + FCS_LEN));
+	return dur;
+}
+
+static uint
+wlc_calc_cts_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
+{
+	WL_TRACE("wl%d: wlc_calc_cts_time: ratespec 0x%x, preamble_type %d\n",
+		 wlc->pub->unit, rspec, preamble_type);
+	return wlc_calc_ack_time(wlc, rspec, preamble_type);
+}
+
+/* derive wlc->band->basic_rate[] table from 'rateset' */
+void wlc_rate_lookup_init(struct wlc_info *wlc, wlc_rateset_t *rateset)
+{
+	u8 rate;
+	u8 mandatory;
+	u8 cck_basic = 0;
+	u8 ofdm_basic = 0;
+	u8 *br = wlc->band->basic_rate;
+	uint i;
+
+	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
+	memset(br, 0, WLC_MAXRATE + 1);
+
+	/* For each basic rate in the rates list, make an entry in the
+	 * best basic lookup.
+	 */
+	for (i = 0; i < rateset->count; i++) {
+		/* only make an entry for a basic rate */
+		if (!(rateset->rates[i] & WLC_RATE_FLAG))
+			continue;
+
+		/* mask off basic bit */
+		rate = (rateset->rates[i] & RATE_MASK);
+
+		if (rate > WLC_MAXRATE) {
+			WL_ERROR("wlc_rate_lookup_init: invalid rate 0x%X in rate set\n",
+				 rateset->rates[i]);
+			continue;
+		}
+
+		br[rate] = rate;
+	}
+
+	/* The rate lookup table now has non-zero entries for each
+	 * basic rate, equal to the basic rate: br[basicN] = basicN
+	 *
+	 * To look up the best basic rate corresponding to any
+	 * particular rate, code can use the basic_rate table
+	 * like this
+	 *
+	 * basic_rate = wlc->band->basic_rate[tx_rate]
+	 *
+	 * Make sure there is a best basic rate entry for
+	 * every rate by walking up the table from low rates
+	 * to high, filling in holes in the lookup table
+	 */
+
+	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
+		rate = wlc->band->hw_rateset.rates[i];
+		ASSERT(rate <= WLC_MAXRATE);
+
+		if (br[rate] != 0) {
+			/* This rate is a basic rate.
+			 * Keep track of the best basic rate so far by
+			 * modulation type.
+			 */
+			if (IS_OFDM(rate))
+				ofdm_basic = rate;
+			else
+				cck_basic = rate;
+
+			continue;
+		}
+
+		/* This rate is not a basic rate so figure out the
+		 * best basic rate less than this rate and fill in
+		 * the hole in the table
+		 */
+
+		br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
+
+		if (br[rate] != 0)
+			continue;
+
+		if (IS_OFDM(rate)) {
+			/* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */
+			if (rate >= WLC_RATE_24M)
+				mandatory = WLC_RATE_24M;
+			else if (rate >= WLC_RATE_12M)
+				mandatory = WLC_RATE_12M;
+			else
+				mandatory = WLC_RATE_6M;
+		} else {
+			/* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */
+			mandatory = rate;
+		}
+
+		br[rate] = mandatory;
+	}
+}
+
+static void wlc_write_rate_shm(struct wlc_info *wlc, u8 rate, u8 basic_rate)
+{
+	u8 phy_rate, index;
+	u8 basic_phy_rate, basic_index;
+	u16 dir_table, basic_table;
+	u16 basic_ptr;
+
+	/* Shared memory address for the table we are reading */
+	dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
+
+	/* Shared memory address for the table we are writing */
+	basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
+
+	/*
+	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
+	 * the index into the rate table.
+	 */
+	phy_rate = rate_info[rate] & RATE_MASK;
+	basic_phy_rate = rate_info[basic_rate] & RATE_MASK;
+	index = phy_rate & 0xf;
+	basic_index = basic_phy_rate & 0xf;
+
+	/* Find the SHM pointer to the ACK rate entry by looking in the
+	 * Direct-map Table
+	 */
+	basic_ptr = wlc_read_shm(wlc, (dir_table + basic_index * 2));
+
+	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
+	 * to the correct basic rate for the given incoming rate
+	 */
+	wlc_write_shm(wlc, (basic_table + index * 2), basic_ptr);
+}
+
+static const wlc_rateset_t *wlc_rateset_get_hwrs(struct wlc_info *wlc)
+{
+	const wlc_rateset_t *rs_dflt;
+
+	if (WLC_PHY_11N_CAP(wlc->band)) {
+		if (BAND_5G(wlc->band->bandtype))
+			rs_dflt = &ofdm_mimo_rates;
+		else
+			rs_dflt = &cck_ofdm_mimo_rates;
+	} else if (wlc->band->gmode)
+		rs_dflt = &cck_ofdm_rates;
+	else
+		rs_dflt = &cck_rates;
+
+	return rs_dflt;
+}
+
+void wlc_set_ratetable(struct wlc_info *wlc)
+{
+	const wlc_rateset_t *rs_dflt;
+	wlc_rateset_t rs;
+	u8 rate, basic_rate;
+	uint i;
+
+	rs_dflt = wlc_rateset_get_hwrs(wlc);
+	ASSERT(rs_dflt != NULL);
+
+	wlc_rateset_copy(rs_dflt, &rs);
+	wlc_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/* walk the phy rate table and update SHM basic rate lookup table */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & RATE_MASK;
+
+		/* for a given rate WLC_BASIC_RATE returns the rate at
+		 * which a response ACK/CTS should be sent.
+		 */
+		basic_rate = WLC_BASIC_RATE(wlc, rate);
+		if (basic_rate == 0) {
+			/* This should only happen if we are using a
+			 * restricted rateset.
+			 */
+			basic_rate = rs.rates[0] & RATE_MASK;
+		}
+
+		wlc_write_rate_shm(wlc, rate, basic_rate);
+	}
+}
+
+/*
+ * Return true if the specified rate is supported by the specified band.
+ * WLC_BAND_AUTO indicates the current band.
+ */
+bool wlc_valid_rate(struct wlc_info *wlc, ratespec_t rspec, int band,
+		    bool verbose)
+{
+	wlc_rateset_t *hw_rateset;
+	uint i;
+
+	if ((band == WLC_BAND_AUTO) || (band == wlc->band->bandtype)) {
+		hw_rateset = &wlc->band->hw_rateset;
+	} else if (NBANDS(wlc) > 1) {
+		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
+	} else {
+		/* other band specified and we are a single band device */
+		return false;
+	}
+
+	/* check if this is a mimo rate */
+	if (IS_MCS(rspec)) {
+		if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
+			goto error;
+
+		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
+	}
+
+	for (i = 0; i < hw_rateset->count; i++)
+		if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
+			return true;
+ error:
+	if (verbose) {
+		WL_ERROR("wl%d: wlc_valid_rate: rate spec 0x%x not in hw_rateset\n",
+			 wlc->pub->unit, rspec);
+	}
+
+	return false;
+}
+
+static void wlc_update_mimo_band_bwcap(struct wlc_info *wlc, u8 bwcap)
+{
+	uint i;
+	struct wlcband *band;
+
+	for (i = 0; i < NBANDS(wlc); i++) {
+		if (IS_SINGLEBAND_5G(wlc->deviceid))
+			i = BAND_5G_INDEX;
+		band = wlc->bandstate[i];
+		if (band->bandtype == WLC_BAND_5G) {
+			if ((bwcap == WLC_N_BW_40ALL)
+			    || (bwcap == WLC_N_BW_20IN2G_40IN5G))
+				band->mimo_cap_40 = true;
+			else
+				band->mimo_cap_40 = false;
+		} else {
+			ASSERT(band->bandtype == WLC_BAND_2G);
+			if (bwcap == WLC_N_BW_40ALL)
+				band->mimo_cap_40 = true;
+			else
+				band->mimo_cap_40 = false;
+		}
+	}
+
+	wlc->mimo_band_bwcap = bwcap;
+}
+
+void wlc_mod_prb_rsp_rate_table(struct wlc_info *wlc, uint frame_len)
+{
+	const wlc_rateset_t *rs_dflt;
+	wlc_rateset_t rs;
+	u8 rate;
+	u16 entry_ptr;
+	u8 plcp[D11_PHY_HDR_LEN];
+	u16 dur, sifs;
+	uint i;
+
+	sifs = SIFS(wlc->band);
+
+	rs_dflt = wlc_rateset_get_hwrs(wlc);
+	ASSERT(rs_dflt != NULL);
+
+	wlc_rateset_copy(rs_dflt, &rs);
+	wlc_rateset_mcs_upd(&rs, wlc->stf->txstreams);
+
+	/* walk the phy rate table and update MAC core SHM basic rate table entries */
+	for (i = 0; i < rs.count; i++) {
+		rate = rs.rates[i] & RATE_MASK;
+
+		entry_ptr = wlc_rate_shm_offset(wlc, rate);
+
+		/* Calculate the Probe Response PLCP for the given rate */
+		wlc_compute_plcp(wlc, rate, frame_len, plcp);
+
+		/* Calculate the duration of the Probe Response frame plus SIFS for the MAC */
+		dur =
+		    (u16) wlc_calc_frame_time(wlc, rate, WLC_LONG_PREAMBLE,
+						 frame_len);
+		dur += sifs;
+
+		/* Update the SHM Rate Table entry Probe Response values */
+		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
+			      (u16) (plcp[0] + (plcp[1] << 8)));
+		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
+			      (u16) (plcp[2] + (plcp[3] << 8)));
+		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
+	}
+}
+
+u16
+wlc_compute_bcntsfoff(struct wlc_info *wlc, ratespec_t rspec,
+		      bool short_preamble, bool phydelay)
+{
+	uint bcntsfoff = 0;
+
+	if (IS_MCS(rspec)) {
+		WL_ERROR("wl%d: recd beacon with mcs rate; rspec 0x%x\n",
+			 wlc->pub->unit, rspec);
+	} else if (IS_OFDM(rspec)) {
+		/* tx delay from MAC through phy to air (2.1 usec) +
+		 * phy header time (preamble + PLCP SIGNAL == 20 usec) +
+		 * PLCP SERVICE + MAC header time (SERVICE + FC + DUR + A1 + A2 + A3 + SEQ == 26
+		 * bytes at beacon rate)
+		 */
+		bcntsfoff += phydelay ? D11A_PHY_TX_DELAY : 0;
+		bcntsfoff += APHY_PREAMBLE_TIME + APHY_SIGNAL_TIME;
+		bcntsfoff +=
+		    wlc_compute_airtime(wlc, rspec,
+					APHY_SERVICE_NBITS / 8 +
+					DOT11_MAC_HDR_LEN);
+	} else {
+		/* tx delay from MAC through phy to air (3.4 usec) +
+		 * phy header time (long preamble + PLCP == 192 usec) +
+		 * MAC header time (FC + DUR + A1 + A2 + A3 + SEQ == 24 bytes at beacon rate)
+		 */
+		bcntsfoff += phydelay ? D11B_PHY_TX_DELAY : 0;
+		bcntsfoff +=
+		    short_preamble ? D11B_PHY_SPREHDR_TIME :
+		    D11B_PHY_LPREHDR_TIME;
+		bcntsfoff += wlc_compute_airtime(wlc, rspec, DOT11_MAC_HDR_LEN);
+	}
+	return (u16) (bcntsfoff);
+}
+
+/*	Max buffering needed for beacon template/prb resp template is 142 bytes.
+ *
+ *	PLCP header is 6 bytes.
+ *	802.11 A3 header is 24 bytes.
+ *	Max beacon frame body template length is 112 bytes.
+ *	Max probe resp frame body template length is 110 bytes.
+ *
+ *      *len on input contains the max length of the packet available.
+ *
+ *	The *len value is set to the number of bytes in buf used, and starts with the PLCP
+ *	and included up to, but not including, the 4 byte FCS.
+ */
+static void
+wlc_bcn_prb_template(struct wlc_info *wlc, u16 type, ratespec_t bcn_rspec,
+		     struct wlc_bsscfg *cfg, u16 *buf, int *len)
+{
+	static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+	cck_phy_hdr_t *plcp;
+	struct ieee80211_mgmt *h;
+	int hdr_len, body_len;
+
+	ASSERT(*len >= 142);
+	ASSERT(type == IEEE80211_STYPE_BEACON ||
+	       type == IEEE80211_STYPE_PROBE_RESP);
+
+	if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
+		hdr_len = DOT11_MAC_HDR_LEN;
+	else
+		hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
+	body_len = *len - hdr_len;	/* calc buffer size provided for frame body */
+
+	*len = hdr_len + body_len;	/* return actual size */
+
+	/* format PHY and MAC headers */
+	memset((char *)buf, 0, hdr_len);
+
+	plcp = (cck_phy_hdr_t *) buf;
+
+	/* PLCP for Probe Response frames are filled in from core's rate table */
+	if (type == IEEE80211_STYPE_BEACON && !MBSS_BCN_ENAB(cfg)) {
+		/* fill in PLCP */
+		wlc_compute_plcp(wlc, bcn_rspec,
+				 (DOT11_MAC_HDR_LEN + body_len + FCS_LEN),
+				 (u8 *) plcp);
+
+	}
+	/* "Regular" and 16 MBSS but not for 4 MBSS */
+	/* Update the phytxctl for the beacon based on the rspec */
+	if (!SOFTBCN_ENAB(cfg))
+		wlc_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
+
+	if (MBSS_BCN_ENAB(cfg) && type == IEEE80211_STYPE_BEACON)
+		h = (struct ieee80211_mgmt *)&plcp[0];
+	else
+		h = (struct ieee80211_mgmt *)&plcp[1];
+
+	/* fill in 802.11 header */
+	h->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | type);
+
+	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
+	/* A1 filled in by MAC for prb resp, broadcast for bcn */
+	if (type == IEEE80211_STYPE_BEACON)
+		memcpy(&h->da, &ether_bcast, ETH_ALEN);
+	memcpy(&h->sa, &cfg->cur_etheraddr, ETH_ALEN);
+	memcpy(&h->bssid, &cfg->BSSID, ETH_ALEN);
+
+	/* SEQ filled in by MAC */
+
+	return;
+}
+
+int wlc_get_header_len()
+{
+	return TXOFF;
+}
+
+/* Update a beacon for a particular BSS
+ * For MBSS, this updates the software template and sets "latest" to the index of the
+ * template updated.
+ * Otherwise, it updates the hardware template.
+ */
+void wlc_bss_update_beacon(struct wlc_info *wlc, struct wlc_bsscfg *cfg)
+{
+	int len = BCN_TMPL_LEN;
+
+	/* Clear the soft intmask */
+	wlc->defmacintmask &= ~MI_BCNTPL;
+
+	if (!cfg->up) {		/* Only allow updates on an UP bss */
+		return;
+	}
+
+	/* Optimize:  Some of if/else could be combined */
+	if (!MBSS_BCN_ENAB(cfg) && HWBCN_ENAB(cfg)) {
+		/* Hardware beaconing for this config */
+		u16 bcn[BCN_TMPL_LEN / 2];
+		u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
+		d11regs_t *regs = wlc->regs;
+
+		/* Check if both templates are in use, if so sched. an interrupt
+		 *      that will call back into this routine
+		 */
+		if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
+			/* clear any previous status */
+			W_REG(&regs->macintstatus, MI_BCNTPL);
+		}
+		/* Check that after scheduling the interrupt both of the
+		 *      templates are still busy. if not clear the int. & remask
+		 */
+		if ((R_REG(&regs->maccommand) & both_valid) == both_valid) {
+			wlc->defmacintmask |= MI_BCNTPL;
+			return;
+		}
+
+		wlc->bcn_rspec =
+		    wlc_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
+		ASSERT(wlc_valid_rate
+		       (wlc, wlc->bcn_rspec,
+			CHSPEC_IS2G(cfg->current_bss->
+				    chanspec) ? WLC_BAND_2G : WLC_BAND_5G,
+			true));
+
+		/* update the template and ucode shm */
+		wlc_bcn_prb_template(wlc, IEEE80211_STYPE_BEACON,
+				     wlc->bcn_rspec, cfg, bcn, &len);
+		wlc_write_hw_bcntemplates(wlc, bcn, len, false);
+	}
+}
+
+/*
+ * Update all beacons for the system.
+ */
+void wlc_update_beacon(struct wlc_info *wlc)
+{
+	int idx;
+	struct wlc_bsscfg *bsscfg;
+
+	/* update AP or IBSS beacons */
+	FOREACH_BSS(wlc, idx, bsscfg) {
+		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
+			wlc_bss_update_beacon(wlc, bsscfg);
+	}
+}
+
+/* Write ssid into shared memory */
+void wlc_shm_ssid_upd(struct wlc_info *wlc, struct wlc_bsscfg *cfg)
+{
+	u8 *ssidptr = cfg->SSID;
+	u16 base = M_SSID;
+	u8 ssidbuf[IEEE80211_MAX_SSID_LEN];
+
+	/* padding the ssid with zero and copy it into shm */
+	memset(ssidbuf, 0, IEEE80211_MAX_SSID_LEN);
+	memcpy(ssidbuf, ssidptr, cfg->SSID_len);
+
+	wlc_copyto_shm(wlc, base, ssidbuf, IEEE80211_MAX_SSID_LEN);
+
+	if (!MBSS_BCN_ENAB(cfg))
+		wlc_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
+}
+
+void wlc_update_probe_resp(struct wlc_info *wlc, bool suspend)
+{
+	int idx;
+	struct wlc_bsscfg *bsscfg;
+
+	/* update AP or IBSS probe responses */
+	FOREACH_BSS(wlc, idx, bsscfg) {
+		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
+			wlc_bss_update_probe_resp(wlc, bsscfg, suspend);
+	}
+}
+
+void
+wlc_bss_update_probe_resp(struct wlc_info *wlc, struct wlc_bsscfg *cfg,
+			  bool suspend)
+{
+	u16 prb_resp[BCN_TMPL_LEN / 2];
+	int len = BCN_TMPL_LEN;
+
+	/* write the probe response to hardware, or save in the config structure */
+	if (!MBSS_PRB_ENAB(cfg)) {
+
+		/* create the probe response template */
+		wlc_bcn_prb_template(wlc, IEEE80211_STYPE_PROBE_RESP, 0, cfg,
+				     prb_resp, &len);
+
+		if (suspend)
+			wlc_suspend_mac_and_wait(wlc);
+
+		/* write the probe response into the template region */
+		wlc_bmac_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
+					    (len + 3) & ~3, prb_resp);
+
+		/* write the length of the probe response frame (+PLCP/-FCS) */
+		wlc_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
+
+		/* write the SSID and SSID length */
+		wlc_shm_ssid_upd(wlc, cfg);
+
+		/*
+		 * Write PLCP headers and durations for probe response frames at all rates.
+		 * Use the actual frame length covered by the PLCP header for the call to
+		 * wlc_mod_prb_rsp_rate_table() by subtracting the PLCP len and adding the FCS.
+		 */
+		len += (-D11_PHY_HDR_LEN + FCS_LEN);
+		wlc_mod_prb_rsp_rate_table(wlc, (u16) len);
+
+		if (suspend)
+			wlc_enable_mac(wlc);
+	} else {		/* Generating probe resp in sw; update local template */
+		ASSERT(0 && "No software probe response support without MBSS");
+	}
+}
+
+/* prepares pdu for transmission. returns BCM error codes */
+int wlc_prep_pdu(struct wlc_info *wlc, struct sk_buff *pdu, uint *fifop)
+{
+	uint fifo;
+	d11txh_t *txh;
+	struct ieee80211_hdr *h;
+	struct scb *scb;
+
+	ASSERT(pdu);
+	txh = (d11txh_t *) (pdu->data);
+	ASSERT(txh);
+	h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
+	ASSERT(h);
+
+	/* get the pkt queue info. This was put at wlc_sendctl or wlc_send for PDU */
+	fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
+
+	scb = NULL;
+
+	*fifop = fifo;
+
+	/* return if insufficient dma resources */
+	if (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
+		/* Mark precedences related to this FIFO, unsendable */
+		WLC_TX_FIFO_CLEAR(wlc, fifo);
+		return BCME_BUSY;
+	}
+
+	if (!ieee80211_is_data(txh->MacFrameControl))
+		wlc->pub->_cnt->txctl++;
+
+	return 0;
+}
+
+/* init tx reported rate mechanism */
+void wlc_reprate_init(struct wlc_info *wlc)
+{
+	int i;
+	struct wlc_bsscfg *bsscfg;
+
+	FOREACH_BSS(wlc, i, bsscfg) {
+		wlc_bsscfg_reprate_init(bsscfg);
+	}
+}
+
+/* per bsscfg init tx reported rate mechanism */
+void wlc_bsscfg_reprate_init(struct wlc_bsscfg *bsscfg)
+{
+	bsscfg->txrspecidx = 0;
+	memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
+}
+
+/* Retrieve a consolidated set of revision information,
+ * typically for the WLC_GET_REVINFO ioctl
+ */
+int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len)
+{
+	wlc_rev_info_t *rinfo = (wlc_rev_info_t *) buf;
+
+	if (len < WL_REV_INFO_LEGACY_LENGTH)
+		return BCME_BUFTOOSHORT;
+
+	rinfo->vendorid = wlc->vendorid;
+	rinfo->deviceid = wlc->deviceid;
+	rinfo->radiorev = (wlc->band->radiorev << IDCODE_REV_SHIFT) |
+	    (wlc->band->radioid << IDCODE_ID_SHIFT);
+	rinfo->chiprev = wlc->pub->sih->chiprev;
+	rinfo->corerev = wlc->pub->corerev;
+	rinfo->boardid = wlc->pub->sih->boardtype;
+	rinfo->boardvendor = wlc->pub->sih->boardvendor;
+	rinfo->boardrev = wlc->pub->boardrev;
+	rinfo->ucoderev = wlc->ucode_rev;
+	rinfo->driverrev = EPI_VERSION_NUM;
+	rinfo->bus = wlc->pub->sih->bustype;
+	rinfo->chipnum = wlc->pub->sih->chip;
+
+	if (len >= (offsetof(wlc_rev_info_t, chippkg))) {
+		rinfo->phytype = wlc->band->phytype;
+		rinfo->phyrev = wlc->band->phyrev;
+		rinfo->anarev = 0;	/* obsolete stuff, suppress */
+	}
+
+	if (len >= sizeof(*rinfo)) {
+		rinfo->chippkg = wlc->pub->sih->chippkg;
+	}
+
+	return BCME_OK;
+}
+
+void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs)
+{
+	wlc_rateset_default(rs, NULL, wlc->band->phytype, wlc->band->bandtype,
+			    false, RATE_MASK_FULL, (bool) N_ENAB(wlc->pub),
+			    CHSPEC_WLC_BW(wlc->default_bss->chanspec),
+			    wlc->stf->txstreams);
+}
+
+static void wlc_bss_default_init(struct wlc_info *wlc)
+{
+	chanspec_t chanspec;
+	struct wlcband *band;
+	wlc_bss_info_t *bi = wlc->default_bss;
+
+	/* init default and target BSS with some sane initial values */
+	memset((char *)(bi), 0, sizeof(wlc_bss_info_t));
+	bi->beacon_period = ISSIM_ENAB(wlc->pub->sih) ? BEACON_INTERVAL_DEF_QT :
+	    BEACON_INTERVAL_DEFAULT;
+	bi->dtim_period = ISSIM_ENAB(wlc->pub->sih) ? DTIM_INTERVAL_DEF_QT :
+	    DTIM_INTERVAL_DEFAULT;
+
+	/* fill the default channel as the first valid channel
+	 * starting from the 2G channels
+	 */
+	chanspec = CH20MHZ_CHSPEC(1);
+	ASSERT(chanspec != INVCHANSPEC);
+
+	wlc->home_chanspec = bi->chanspec = chanspec;
+
+	/* find the band of our default channel */
+	band = wlc->band;
+	if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_WLCBANDUNIT(chanspec))
+		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
+
+	/* init bss rates to the band specific default rate set */
+	wlc_rateset_default(&bi->rateset, NULL, band->phytype, band->bandtype,
+			    false, RATE_MASK_FULL, (bool) N_ENAB(wlc->pub),
+			    CHSPEC_WLC_BW(chanspec), wlc->stf->txstreams);
+
+	if (N_ENAB(wlc->pub))
+		bi->flags |= WLC_BSS_HT;
+}
+
+void
+wlc_uint64_sub(u32 *a_high, u32 *a_low, u32 b_high, u32 b_low)
+{
+	if (b_low > *a_low) {
+		/* low half needs a carry */
+		b_high += 1;
+	}
+	*a_low -= b_low;
+	*a_high -= b_high;
+}
+
+static ratespec_t
+mac80211_wlc_set_nrate(struct wlc_info *wlc, struct wlcband *cur_band,
+		       u32 int_val)
+{
+	u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
+	u8 rate = int_val & NRATE_RATE_MASK;
+	ratespec_t rspec;
+	bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
+	bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
+	bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
+				  == NRATE_OVERRIDE_MCS_ONLY);
+	int bcmerror = 0;
+
+	if (!ismcs) {
+		return (ratespec_t) rate;
+	}
+
+	/* validate the combination of rate/mcs/stf is allowed */
+	if (N_ENAB(wlc->pub) && ismcs) {
+		/* mcs only allowed when nmode */
+		if (stf > PHY_TXC1_MODE_SDM) {
+			WL_ERROR("wl%d: %s: Invalid stf\n",
+				 WLCWLUNIT(wlc), __func__);
+			bcmerror = BCME_RANGE;
+			goto done;
+		}
+
+		/* mcs 32 is a special case, DUP mode 40 only */
+		if (rate == 32) {
+			if (!CHSPEC_IS40(wlc->home_chanspec) ||
+			    ((stf != PHY_TXC1_MODE_SISO)
+			     && (stf != PHY_TXC1_MODE_CDD))) {
+				WL_ERROR("wl%d: %s: Invalid mcs 32\n",
+					 WLCWLUNIT(wlc), __func__);
+				bcmerror = BCME_RANGE;
+				goto done;
+			}
+			/* mcs > 7 must use stf SDM */
+		} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
+			/* mcs > 7 must use stf SDM */
+			if (stf != PHY_TXC1_MODE_SDM) {
+				WL_TRACE("wl%d: %s: enabling SDM mode for mcs %d\n",
+					 WLCWLUNIT(wlc), __func__, rate);
+				stf = PHY_TXC1_MODE_SDM;
+			}
+		} else {
+			/* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */
+			if ((stf > PHY_TXC1_MODE_STBC) ||
+			    (!WLC_STBC_CAP_PHY(wlc)
+			     && (stf == PHY_TXC1_MODE_STBC))) {
+				WL_ERROR("wl%d: %s: Invalid STBC\n",
+					 WLCWLUNIT(wlc), __func__);
+				bcmerror = BCME_RANGE;
+				goto done;
+			}
+		}
+	} else if (IS_OFDM(rate)) {
+		if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
+			WL_ERROR("wl%d: %s: Invalid OFDM\n",
+				 WLCWLUNIT(wlc), __func__);
+			bcmerror = BCME_RANGE;
+			goto done;
+		}
+	} else if (IS_CCK(rate)) {
+		if ((cur_band->bandtype != WLC_BAND_2G)
+		    || (stf != PHY_TXC1_MODE_SISO)) {
+			WL_ERROR("wl%d: %s: Invalid CCK\n",
+				 WLCWLUNIT(wlc), __func__);
+			bcmerror = BCME_RANGE;
+			goto done;
+		}
+	} else {
+		WL_ERROR("wl%d: %s: Unknown rate type\n",
+			 WLCWLUNIT(wlc), __func__);
+		bcmerror = BCME_RANGE;
+		goto done;
+	}
+	/* make sure multiple antennae are available for non-siso rates */
+	if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
+		WL_ERROR("wl%d: %s: SISO antenna but !SISO request\n",
+			 WLCWLUNIT(wlc), __func__);
+		bcmerror = BCME_RANGE;
+		goto done;
+	}
+
+	rspec = rate;
+	if (ismcs) {
+		rspec |= RSPEC_MIMORATE;
+		/* For STBC populate the STC field of the ratespec */
+		if (stf == PHY_TXC1_MODE_STBC) {
+			u8 stc;
+			stc = 1;	/* Nss for single stream is always 1 */
+			rspec |= (stc << RSPEC_STC_SHIFT);
+		}
+	}
+
+	rspec |= (stf << RSPEC_STF_SHIFT);
+
+	if (override_mcs_only)
+		rspec |= RSPEC_OVERRIDE_MCS_ONLY;
+
+	if (issgi)
+		rspec |= RSPEC_SHORT_GI;
+
+	if ((rate != 0)
+	    && !wlc_valid_rate(wlc, rspec, cur_band->bandtype, true)) {
+		return rate;
+	}
+
+	return rspec;
+ done:
+	WL_ERROR("Hoark\n");
+	return rate;
+}
+
+/* formula:  IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
+static int
+wlc_duty_cycle_set(struct wlc_info *wlc, int duty_cycle, bool isOFDM,
+		   bool writeToShm)
+{
+	int idle_busy_ratio_x_16 = 0;
+	uint offset =
+	    isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
+	    M_TX_IDLE_BUSY_RATIO_X_16_CCK;
+	if (duty_cycle > 100 || duty_cycle < 0) {
+		WL_ERROR("wl%d:  duty cycle value off limit\n", wlc->pub->unit);
+		return BCME_RANGE;
+	}
+	if (duty_cycle)
+		idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
+	/* Only write to shared memory  when wl is up */
+	if (writeToShm)
+		wlc_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
+
+	if (isOFDM)
+		wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
+	else
+		wlc->tx_duty_cycle_cck = (u16) duty_cycle;
+
+	return BCME_OK;
+}
+
+/* Read a single u16 from shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+u16 wlc_read_shm(struct wlc_info *wlc, uint offset)
+{
+	return wlc_bmac_read_shm(wlc->hw, offset);
+}
+
+/* Write a single u16 to shared memory.
+ * SHM 'offset' needs to be an even address
+ */
+void wlc_write_shm(struct wlc_info *wlc, uint offset, u16 v)
+{
+	wlc_bmac_write_shm(wlc->hw, offset, v);
+}
+
+/* Set a range of shared memory to a value.
+ * SHM 'offset' needs to be an even address and
+ * Range length 'len' must be an even number of bytes
+ */
+void wlc_set_shm(struct wlc_info *wlc, uint offset, u16 v, int len)
+{
+	/* offset and len need to be even */
+	ASSERT((offset & 1) == 0);
+	ASSERT((len & 1) == 0);
+
+	if (len <= 0)
+		return;
+
+	wlc_bmac_set_shm(wlc->hw, offset, v, len);
+}
+
+/* Copy a buffer to shared memory.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+void wlc_copyto_shm(struct wlc_info *wlc, uint offset, const void *buf, int len)
+{
+	/* offset and len need to be even */
+	ASSERT((offset & 1) == 0);
+	ASSERT((len & 1) == 0);
+
+	if (len <= 0)
+		return;
+	wlc_bmac_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+
+}
+
+/* Copy from shared memory to a buffer.
+ * SHM 'offset' needs to be an even address and
+ * Buffer length 'len' must be an even number of bytes
+ */
+void wlc_copyfrom_shm(struct wlc_info *wlc, uint offset, void *buf, int len)
+{
+	/* offset and len need to be even */
+	ASSERT((offset & 1) == 0);
+	ASSERT((len & 1) == 0);
+
+	if (len <= 0)
+		return;
+
+	wlc_bmac_copyfrom_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
+}
+
+/* wrapper BMAC functions to for HIGH driver access */
+void wlc_mctrl(struct wlc_info *wlc, u32 mask, u32 val)
+{
+	wlc_bmac_mctrl(wlc->hw, mask, val);
+}
+
+void wlc_corereset(struct wlc_info *wlc, u32 flags)
+{
+	wlc_bmac_corereset(wlc->hw, flags);
+}
+
+void wlc_mhf(struct wlc_info *wlc, u8 idx, u16 mask, u16 val, int bands)
+{
+	wlc_bmac_mhf(wlc->hw, idx, mask, val, bands);
+}
+
+u16 wlc_mhf_get(struct wlc_info *wlc, u8 idx, int bands)
+{
+	return wlc_bmac_mhf_get(wlc->hw, idx, bands);
+}
+
+int wlc_xmtfifo_sz_get(struct wlc_info *wlc, uint fifo, uint *blocks)
+{
+	return wlc_bmac_xmtfifo_sz_get(wlc->hw, fifo, blocks);
+}
+
+void wlc_write_template_ram(struct wlc_info *wlc, int offset, int len,
+			    void *buf)
+{
+	wlc_bmac_write_template_ram(wlc->hw, offset, len, buf);
+}
+
+void wlc_write_hw_bcntemplates(struct wlc_info *wlc, void *bcn, int len,
+			       bool both)
+{
+	wlc_bmac_write_hw_bcntemplates(wlc->hw, bcn, len, both);
+}
+
+void
+wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
+		  const u8 *addr)
+{
+	wlc_bmac_set_addrmatch(wlc->hw, match_reg_offset, addr);
+	if (match_reg_offset == RCM_BSSID_OFFSET)
+		memcpy(wlc->cfg->BSSID, addr, ETH_ALEN);
+}
+
+void wlc_set_rcmta(struct wlc_info *wlc, int idx, const u8 *addr)
+{
+	wlc_bmac_set_rcmta(wlc->hw, idx, addr);
+}
+
+void wlc_read_tsf(struct wlc_info *wlc, u32 *tsf_l_ptr, u32 *tsf_h_ptr)
+{
+	wlc_bmac_read_tsf(wlc->hw, tsf_l_ptr, tsf_h_ptr);
+}
+
+void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin)
+{
+	wlc->band->CWmin = newmin;
+	wlc_bmac_set_cwmin(wlc->hw, newmin);
+}
+
+void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax)
+{
+	wlc->band->CWmax = newmax;
+	wlc_bmac_set_cwmax(wlc->hw, newmax);
+}
+
+void wlc_fifoerrors(struct wlc_info *wlc)
+{
+
+	wlc_bmac_fifoerrors(wlc->hw);
+}
+
+/* Search mem rw utilities */
+
+void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit)
+{
+	wlc_bmac_pllreq(wlc->hw, set, req_bit);
+}
+
+void wlc_reset_bmac_done(struct wlc_info *wlc)
+{
+}
+
+void wlc_ht_mimops_cap_update(struct wlc_info *wlc, u8 mimops_mode)
+{
+	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_SM_PS;
+	wlc->ht_cap.cap_info |= (mimops_mode << IEEE80211_HT_CAP_SM_PS_SHIFT);
+
+	if (AP_ENAB(wlc->pub) && wlc->clk) {
+		wlc_update_beacon(wlc);
+		wlc_update_probe_resp(wlc, true);
+	}
+}
+
+/* check for the particular priority flow control bit being set */
+bool
+wlc_txflowcontrol_prio_isset(struct wlc_info *wlc, struct wlc_txq_info *q,
+			     int prio)
+{
+	uint prio_mask;
+
+	if (prio == ALLPRIO) {
+		prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
+	} else {
+		ASSERT(prio >= 0 && prio <= MAXPRIO);
+		prio_mask = NBITVAL(prio);
+	}
+
+	return (q->stopped & prio_mask) == prio_mask;
+}
+
+/* propogate the flow control to all interfaces using the given tx queue */
+void wlc_txflowcontrol(struct wlc_info *wlc, struct wlc_txq_info *qi,
+		       bool on, int prio)
+{
+	uint prio_bits;
+	uint cur_bits;
+
+	WL_TRACE("%s: flow control kicks in\n", __func__);
+
+	if (prio == ALLPRIO) {
+		prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
+	} else {
+		ASSERT(prio >= 0 && prio <= MAXPRIO);
+		prio_bits = NBITVAL(prio);
+	}
+
+	cur_bits = qi->stopped & prio_bits;
+
+	/* Check for the case of no change and return early
+	 * Otherwise update the bit and continue
+	 */
+	if (on) {
+		if (cur_bits == prio_bits) {
+			return;
+		}
+		mboolset(qi->stopped, prio_bits);
+	} else {
+		if (cur_bits == 0) {
+			return;
+		}
+		mboolclr(qi->stopped, prio_bits);
+	}
+
+	/* If there is a flow control override we will not change the external
+	 * flow control state.
+	 */
+	if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) {
+		return;
+	}
+
+	wlc_txflowcontrol_signal(wlc, qi, on, prio);
+}
+
+void
+wlc_txflowcontrol_override(struct wlc_info *wlc, struct wlc_txq_info *qi,
+			   bool on, uint override)
+{
+	uint prev_override;
+
+	ASSERT(override != 0);
+	ASSERT((override & TXQ_STOP_FOR_PRIOFC_MASK) == 0);
+
+	prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
+
+	/* Update the flow control bits and do an early return if there is
+	 * no change in the external flow control state.
+	 */
+	if (on) {
+		mboolset(qi->stopped, override);
+		/* if there was a previous override bit on, then setting this
+		 * makes no difference.
+		 */
+		if (prev_override) {
+			return;
+		}
+
+		wlc_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
+	} else {
+		mboolclr(qi->stopped, override);
+		/* clearing an override bit will only make a difference for
+		 * flow control if it was the only bit set. For any other
+		 * override setting, just return
+		 */
+		if (prev_override != override) {
+			return;
+		}
+
+		if (qi->stopped == 0) {
+			wlc_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
+		} else {
+			int prio;
+
+			for (prio = MAXPRIO; prio >= 0; prio--) {
+				if (!mboolisset(qi->stopped, NBITVAL(prio)))
+					wlc_txflowcontrol_signal(wlc, qi, OFF,
+								 prio);
+			}
+		}
+	}
+}
+
+static void wlc_txflowcontrol_reset(struct wlc_info *wlc)
+{
+	struct wlc_txq_info *qi;
+
+	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
+		if (qi->stopped) {
+			wlc_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
+			qi->stopped = 0;
+		}
+	}
+}
+
+static void
+wlc_txflowcontrol_signal(struct wlc_info *wlc, struct wlc_txq_info *qi, bool on,
+			 int prio)
+{
+	struct wlc_if *wlcif;
+
+	for (wlcif = wlc->wlcif_list; wlcif != NULL; wlcif = wlcif->next) {
+		if (wlcif->qi == qi && wlcif->flags & WLC_IF_LINKED)
+			wl_txflowcontrol(wlc->wl, wlcif->wlif, on, prio);
+	}
+}
+
+static struct wlc_txq_info *wlc_txq_alloc(struct wlc_info *wlc)
+{
+	struct wlc_txq_info *qi, *p;
+
+	qi = wlc_calloc(wlc->pub->unit, sizeof(struct wlc_txq_info));
+	if (qi != NULL) {
+		/*
+		 * Have enough room for control packets along with HI watermark
+		 * Also, add room to txq for total psq packets if all the SCBs
+		 * leave PS mode. The watermark for flowcontrol to OS packets
+		 * will remain the same
+		 */
+		pktq_init(&qi->q, WLC_PREC_COUNT,
+			  (2 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT
+			  + wlc->pub->psq_pkts_total);
+
+		/* add this queue to the the global list */
+		p = wlc->tx_queues;
+		if (p == NULL) {
+			wlc->tx_queues = qi;
+		} else {
+			while (p->next != NULL)
+				p = p->next;
+			p->next = qi;
+		}
+	}
+	return qi;
+}
+
+static void wlc_txq_free(struct wlc_info *wlc, struct wlc_txq_info *qi)
+{
+	struct wlc_txq_info *p;
+
+	if (qi == NULL)
+		return;
+
+	/* remove the queue from the linked list */
+	p = wlc->tx_queues;
+	if (p == qi)
+		wlc->tx_queues = p->next;
+	else {
+		while (p != NULL && p->next != qi)
+			p = p->next;
+		ASSERT(p->next == qi);
+		if (p != NULL)
+			p->next = p->next->next;
+	}
+
+	kfree(qi);
+}
+
+/*
+ * Flag 'scan in progress' to withold dynamic phy calibration
+ */
+void wlc_scan_start(struct wlc_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
+}
+
+void wlc_scan_stop(struct wlc_info *wlc)
+{
+	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
+}
+
+void wlc_associate_upd(struct wlc_info *wlc, bool state)
+{
+	wlc->pub->associated = state;
+	wlc->cfg->associated = state;
+}
+
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
+ */
+void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn))
+{
+	struct hnddma_pub *dmah;
+	int i;
+	for (i = 0; i < NFIFO; i++) {
+		dmah = hw->di[i];
+		if (dmah != NULL)
+			dma_walk_packets(dmah, dma_callback_fn, sta);
+	}
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.h b/drivers/staging/brcm80211/brcmsmac/wlc_main.h
new file mode 100644
index 0000000..960f82c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.h
@@ -0,0 +1,970 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_h_
+#define _wlc_h_
+
+#define MA_WINDOW_SZ		8	/* moving average window size */
+#define	WL_HWRXOFF		38	/* chip rx buffer offset */
+#define	INVCHANNEL		255	/* invalid channel */
+#define	MAXCOREREV		28	/* max # supported core revisions (0 .. MAXCOREREV - 1) */
+#define WLC_MAXMODULES		22	/* max #  wlc_module_register() calls */
+
+#define WLC_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
+
+/* Maximum wait time for a MAC suspend */
+#define	WLC_MAX_MAC_SUSPEND	83000	/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
+
+/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable
+ */
+#define WLC_PRB_RESP_TIMEOUT	0	/* Disable probe response timeout */
+
+/* transmit buffer max headroom for protocol headers */
+#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
+
+/* For managing scan result lists */
+struct wlc_bss_list {
+	uint count;
+	bool beacon;		/* set for beacon, cleared for probe response */
+	wlc_bss_info_t *ptrs[MAXBSS];
+};
+
+#define	SW_TIMER_MAC_STAT_UPD		30	/* periodic MAC stats update */
+
+/* Double check that unsupported cores are not enabled */
+#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
+#error "Configuration for D11CONF includes unsupported versions."
+#endif				/* Bad versions */
+
+#define	VALID_COREREV(corerev)	CONF_HAS(D11CONF, corerev)
+
+/* values for shortslot_override */
+#define WLC_SHORTSLOT_AUTO	-1	/* Driver will manage Shortslot setting */
+#define WLC_SHORTSLOT_OFF	0	/* Turn off short slot */
+#define WLC_SHORTSLOT_ON	1	/* Turn on short slot */
+
+/* value for short/long and mixmode/greenfield preamble */
+
+#define WLC_LONG_PREAMBLE	(0)
+#define WLC_SHORT_PREAMBLE	(1 << 0)
+#define WLC_GF_PREAMBLE		(1 << 1)
+#define WLC_MM_PREAMBLE		(1 << 2)
+#define WLC_IS_MIMO_PREAMBLE(_pre) (((_pre) == WLC_GF_PREAMBLE) || ((_pre) == WLC_MM_PREAMBLE))
+
+/* values for barker_preamble */
+#define WLC_BARKER_SHORT_ALLOWED	0	/* Short pre-amble allowed */
+
+/* A fifo is full. Clear precedences related to that FIFO */
+#define WLC_TX_FIFO_CLEAR(wlc, fifo) ((wlc)->tx_prec_map &= ~(wlc)->fifo2prec_map[fifo])
+
+/* Fifo is NOT full. Enable precedences for that FIFO */
+#define WLC_TX_FIFO_ENAB(wlc, fifo)  ((wlc)->tx_prec_map |= (wlc)->fifo2prec_map[fifo])
+
+/* TxFrameID */
+/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
+/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
+#define TXFID_QUEUE_MASK	0x0007	/* Bits 0-2 */
+#define TXFID_SEQ_MASK		0x7FE0	/* Bits 5-15 */
+#define TXFID_SEQ_SHIFT		5	/* Number of bit shifts */
+#define	TXFID_RATE_PROBE_MASK	0x8000	/* Bit 15 for rate probe */
+#define TXFID_RATE_MASK		0x0018	/* Mask for bits 3 and 4 */
+#define TXFID_RATE_SHIFT	3	/* Shift 3 bits for rate mask */
+
+/* promote boardrev */
+#define BOARDREV_PROMOTABLE	0xFF	/* from */
+#define BOARDREV_PROMOTED	1	/* to */
+
+/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true
+ */
+#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
+#define WLC_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \
+	((bsscfg)->wsec & WSEC_SWFLAG)))
+
+#define WLC_PORTOPEN(cfg) \
+	(((cfg)->WPA_auth != WPA_AUTH_DISABLED && WSEC_ENABLED((cfg)->wsec)) ? \
+	(cfg)->wsec_portopen : true)
+
+#define PS_ALLOWED(wlc)	wlc_ps_allowed(wlc)
+#define STAY_AWAKE(wlc) wlc_stay_awake(wlc)
+
+#define DATA_BLOCK_TX_SUPR	(1 << 4)
+
+/* 802.1D Priority to TX FIFO number for wme */
+extern const u8 prio2fifo[];
+
+/* Ucode MCTL_WAKE override bits */
+#define WLC_WAKE_OVERRIDE_CLKCTL	0x01
+#define WLC_WAKE_OVERRIDE_PHYREG	0x02
+#define WLC_WAKE_OVERRIDE_MACSUSPEND	0x04
+#define WLC_WAKE_OVERRIDE_TXFIFO	0x08
+#define WLC_WAKE_OVERRIDE_FORCEFAST	0x10
+
+/* stuff pulled in from wlc.c */
+
+/* Interrupt bit error summary.  Don't include I_RU: we refill DMA at other
+ * times; and if we run out, constant I_RU interrupts may cause lockup.  We
+ * will still get error counts from rx0ovfl.
+ */
+#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RO | I_XU)
+/* default software intmasks */
+#define	DEF_RXINTMASK	(I_RI)	/* enable rx int on rxfifo only */
+#define	DEF_MACINTMASK	(MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
+			 MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
+			 MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
+
+#define	RETRY_SHORT_DEF			7	/* Default Short retry Limit */
+#define	RETRY_SHORT_MAX			255	/* Maximum Short retry Limit */
+#define	RETRY_LONG_DEF			4	/* Default Long retry count */
+#define	RETRY_SHORT_FB			3	/* Short retry count for fallback rate */
+#define	RETRY_LONG_FB			2	/* Long retry count for fallback rate */
+
+#define	MAXTXPKTS		6	/* max # pkts pending */
+
+/* frameburst */
+#define	MAXTXFRAMEBURST		8	/* vanilla xpress mode: max frames/burst */
+#define	MAXFRAMEBURST_TXOP	10000	/* Frameburst TXOP in usec */
+
+/* Per-AC retry limit register definitions; uses bcmdefs.h bitfield macros */
+#define EDCF_SHORT_S            0
+#define EDCF_SFB_S              4
+#define EDCF_LONG_S             8
+#define EDCF_LFB_S              12
+#define EDCF_SHORT_M            BITFIELD_MASK(4)
+#define EDCF_SFB_M              BITFIELD_MASK(4)
+#define EDCF_LONG_M             BITFIELD_MASK(4)
+#define EDCF_LFB_M              BITFIELD_MASK(4)
+
+#define WLC_WME_RETRY_SHORT_GET(wlc, ac)    GFIELD(wlc->wme_retries[ac], EDCF_SHORT)
+#define WLC_WME_RETRY_SFB_GET(wlc, ac)      GFIELD(wlc->wme_retries[ac], EDCF_SFB)
+#define WLC_WME_RETRY_LONG_GET(wlc, ac)     GFIELD(wlc->wme_retries[ac], EDCF_LONG)
+#define WLC_WME_RETRY_LFB_GET(wlc, ac)      GFIELD(wlc->wme_retries[ac], EDCF_LFB)
+
+#define WLC_WME_RETRY_SHORT_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SHORT, val))
+#define WLC_WME_RETRY_SFB_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SFB, val))
+#define WLC_WME_RETRY_LONG_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LONG, val))
+#define WLC_WME_RETRY_LFB_SET(wlc, ac, val) \
+	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LFB, val))
+
+/* PLL requests */
+#define WLC_PLLREQ_SHARED	0x1	/* pll is shared on old chips */
+#define WLC_PLLREQ_RADIO_MON	0x2	/* hold pll for radio monitor register checking */
+#define WLC_PLLREQ_FLIP		0x4	/* hold/release pll for some short operation */
+
+/* Do we support this rate? */
+#define VALID_RATE_DBG(wlc, rspec) wlc_valid_rate(wlc, rspec, WLC_BAND_AUTO, true)
+
+/*
+ * Macros to check if AP or STA is active.
+ * AP Active means more than just configured: driver and BSS are "up";
+ * that is, we are beaconing/responding as an AP (aps_associated).
+ * STA Active similarly means the driver is up and a configured STA BSS
+ * is up: either associated (stas_associated) or trying.
+ *
+ * Macro definitions vary as per AP/STA ifdefs, allowing references to
+ * ifdef'd structure fields and constant values (0) for optimization.
+ * Make sure to enclose blocks of code such that any routines they
+ * reference can also be unused and optimized out by the linker.
+ */
+/* NOTE: References structure fields defined in wlc.h */
+#define AP_ACTIVE(wlc)	(0)
+
+/*
+ * Detect Card removed.
+ * Even checking an sbconfig register read will not false trigger when the core is in reset.
+ * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy
+ * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern
+ * (some platforms return all 0).
+ * If clocks are present, call the sb routine which will figure out if the device is removed.
+ */
+#define DEVICEREMOVED(wlc)      \
+	((wlc->hw->clk) ?   \
+	((R_REG(&wlc->hw->regs->maccontrol) & \
+	(MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN) : \
+	(si_deviceremoved(wlc->hw->sih)))
+
+#define WLCWLUNIT(wlc)		((wlc)->pub->unit)
+
+struct wlc_protection {
+	bool _g;		/* use g spec protection, driver internal */
+	s8 g_override;	/* override for use of g spec protection */
+	u8 gmode_user;	/* user config gmode, operating band->gmode is different */
+	s8 overlap;		/* Overlap BSS/IBSS protection for both 11g and 11n */
+	s8 nmode_user;	/* user config nmode, operating pub->nmode is different */
+	s8 n_cfg;		/* use OFDM protection on MIMO frames */
+	s8 n_cfg_override;	/* override for use of N protection */
+	bool nongf;		/* non-GF present protection */
+	s8 nongf_override;	/* override for use of GF protection */
+	s8 n_pam_override;	/* override for preamble: MM or GF */
+	bool n_obss;		/* indicated OBSS Non-HT STA present */
+
+	uint longpre_detect_timeout;	/* #sec until long preamble bcns gone */
+	uint barker_detect_timeout;	/* #sec until bcns signaling Barker long preamble */
+	/* only is gone */
+	uint ofdm_ibss_timeout;	/* #sec until ofdm IBSS beacons gone */
+	uint ofdm_ovlp_timeout;	/* #sec until ofdm overlapping BSS bcns gone */
+	uint nonerp_ibss_timeout;	/* #sec until nonerp IBSS beacons gone */
+	uint nonerp_ovlp_timeout;	/* #sec until nonerp overlapping BSS bcns gone */
+	uint g_ibss_timeout;	/* #sec until bcns signaling Use_Protection gone */
+	uint n_ibss_timeout;	/* #sec until bcns signaling Use_OFDM_Protection gone */
+	uint ht20in40_ovlp_timeout;	/* #sec until 20MHz overlapping OPMODE gone */
+	uint ht20in40_ibss_timeout;	/* #sec until 20MHz-only HT station bcns gone */
+	uint non_gf_ibss_timeout;	/* #sec until non-GF bcns gone */
+};
+
+/* anything affects the single/dual streams/antenna operation */
+struct wlc_stf {
+	u8 hw_txchain;	/* HW txchain bitmap cfg */
+	u8 txchain;		/* txchain bitmap being used */
+	u8 txstreams;	/* number of txchains being used */
+
+	u8 hw_rxchain;	/* HW rxchain bitmap cfg */
+	u8 rxchain;		/* rxchain bitmap being used */
+	u8 rxstreams;	/* number of rxchains being used */
+
+	u8 ant_rx_ovr;	/* rx antenna override */
+	s8 txant;		/* userTx antenna setting */
+	u16 phytxant;	/* phyTx antenna setting in txheader */
+
+	u8 ss_opmode;	/* singlestream Operational mode, 0:siso; 1:cdd */
+	bool ss_algosel_auto;	/* if true, use wlc->stf->ss_algo_channel; */
+	/* else use wlc->band->stf->ss_mode_band; */
+	u16 ss_algo_channel;	/* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */
+	u8 no_cddstbc;	/* stf override, 1: no CDD (or STBC) allowed */
+
+	u8 rxchain_restore_delay;	/* delay time to restore default rxchain */
+
+	s8 ldpc;		/* AUTO/ON/OFF ldpc cap supported */
+	u8 txcore[MAX_STREAMS_SUPPORTED + 1];	/* bitmap of selected core for each Nsts */
+	s8 spatial_policy;
+};
+
+#define WLC_STF_SS_STBC_TX(wlc, scb) \
+	(((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) || \
+	 (SCB_STBC_CAP((scb)) &&					\
+	  (wlc)->band->band_stf_stbc_tx == AUTO &&			\
+	  isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
+
+#define WLC_STBC_CAP_PHY(wlc) (WLCISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3))
+
+#define WLC_SGI_CAP_PHY(wlc) ((WLCISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3)) || \
+	WLCISLCNPHY(wlc->band))
+
+#define WLC_CHAN_PHYTYPE(x)     (((x) & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT)
+#define WLC_CHAN_CHANNEL(x)     (((x) & RXS_CHAN_ID_MASK) >> RXS_CHAN_ID_SHIFT)
+#define WLC_RX_CHANNEL(rxh)	(WLC_CHAN_CHANNEL((rxh)->RxChan))
+
+/* wlc_bss_info flag bit values */
+#define WLC_BSS_HT		0x0020	/* BSS is HT (MIMO) capable */
+
+/* Flags used in wlc_txq_info.stopped */
+#define TXQ_STOP_FOR_PRIOFC_MASK	0x000000FF	/* per prio flow control bits */
+#define TXQ_STOP_FOR_PKT_DRAIN		0x00000100	/* stop txq enqueue for packet drain */
+#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL	0x00000200	/* stop txq enqueue for ampdu flow control */
+
+#define WLC_HT_WEP_RESTRICT	0x01	/* restrict HT with WEP */
+#define WLC_HT_TKIP_RESTRICT	0x02	/* restrict HT with TKIP */
+
+/*
+ * core state (mac)
+ */
+struct wlccore {
+	uint coreidx;		/* # sb enumerated core */
+
+	/* fifo */
+	uint *txavail[NFIFO];	/* # tx descriptors available */
+	s16 txpktpend[NFIFO];	/* tx admission control */
+
+	macstat_t *macstat_snapshot;	/* mac hw prev read values */
+};
+
+/*
+ * band state (phy+ana+radio)
+ */
+struct wlcband {
+	int bandtype;		/* WLC_BAND_2G, WLC_BAND_5G */
+	uint bandunit;		/* bandstate[] index */
+
+	u16 phytype;		/* phytype */
+	u16 phyrev;
+	u16 radioid;
+	u16 radiorev;
+	wlc_phy_t *pi;		/* pointer to phy specific information */
+	bool abgphy_encore;
+
+	u8 gmode;		/* currently active gmode (see wlioctl.h) */
+
+	struct scb *hwrs_scb;	/* permanent scb for hw rateset */
+
+	wlc_rateset_t defrateset;	/* band-specific copy of default_bss.rateset */
+
+	ratespec_t rspec_override;	/* 802.11 rate override */
+	ratespec_t mrspec_override;	/* multicast rate override */
+	u8 band_stf_ss_mode;	/* Configured STF type, 0:siso; 1:cdd */
+	s8 band_stf_stbc_tx;	/* STBC TX 0:off; 1:force on; -1:auto */
+	wlc_rateset_t hw_rateset;	/* rates supported by chip (phy-specific) */
+	u8 basic_rate[WLC_MAXRATE + 1];	/* basic rates indexed by rate */
+	bool mimo_cap_40;	/* 40 MHz cap enabled on this band */
+	s8 antgain;		/* antenna gain from srom */
+
+	u16 CWmin;		/* The minimum size of contention window, in unit of aSlotTime */
+	u16 CWmax;		/* The maximum size of contention window, in unit of aSlotTime */
+	u16 bcntsfoff;	/* beacon tsf offset */
+};
+
+/* tx completion callback takes 3 args */
+typedef void (*pkcb_fn_t) (struct wlc_info *wlc, uint txstatus, void *arg);
+
+struct pkt_cb {
+	pkcb_fn_t fn;		/* function to call when tx frame completes */
+	void *arg;		/* void arg for fn */
+	u8 nextidx;		/* index of next call back if threading */
+	bool entered;		/* recursion check */
+};
+
+/* module control blocks */
+struct modulecb {
+	char name[32];		/* module name : NULL indicates empty array member */
+	const bcm_iovar_t *iovars;	/* iovar table */
+	void *hdl;		/* handle passed when handler 'doiovar' is called */
+	watchdog_fn_t watchdog_fn;	/* watchdog handler */
+	iovar_fn_t iovar_fn;	/* iovar handler */
+	down_fn_t down_fn;	/* down handler. Note: the int returned
+				 * by the down function is a count of the
+				 * number of timers that could not be
+				 * freed.
+				 */
+};
+
+/* dump control blocks */
+struct dumpcb_s {
+	const char *name;	/* dump name */
+	dump_fn_t dump_fn;	/* 'wl dump' handler */
+	void *dump_fn_arg;
+	struct dumpcb_s *next;
+};
+
+/* virtual interface */
+struct wlc_if {
+	struct wlc_if *next;
+	u8 type;		/* WLC_IFTYPE_BSS or WLC_IFTYPE_WDS */
+	u8 index;		/* assigned in wl_add_if(), index of the wlif if any,
+				 * not necessarily corresponding to bsscfg._idx or
+				 * AID2PVBMAP(scb).
+				 */
+	u8 flags;		/* flags for the interface */
+	struct wl_if *wlif;		/* pointer to wlif */
+	struct wlc_txq_info *qi;	/* pointer to associated tx queue */
+	union {
+		struct scb *scb;	/* pointer to scb if WLC_IFTYPE_WDS */
+		struct wlc_bsscfg *bsscfg;	/* pointer to bsscfg if WLC_IFTYPE_BSS */
+	} u;
+};
+
+/* flags for the interface */
+#define WLC_IF_LINKED		0x02	/* this interface is linked to a wl_if */
+
+struct wlc_hwband {
+	int bandtype;		/* WLC_BAND_2G, WLC_BAND_5G */
+	uint bandunit;		/* bandstate[] index */
+	u16 mhfs[MHFMAX];	/* MHF array shadow */
+	u8 bandhw_stf_ss_mode;	/* HW configured STF type, 0:siso; 1:cdd */
+	u16 CWmin;
+	u16 CWmax;
+	u32 core_flags;
+
+	u16 phytype;		/* phytype */
+	u16 phyrev;
+	u16 radioid;
+	u16 radiorev;
+	wlc_phy_t *pi;		/* pointer to phy specific information */
+	bool abgphy_encore;
+};
+
+struct wlc_hw_info {
+	bool _piomode;		/* true if pio mode */
+	struct wlc_info *wlc;
+
+	/* fifo */
+	struct hnddma_pub *di[NFIFO];	/* hnddma handles, per fifo */
+
+	uint unit;		/* device instance number */
+
+	/* version info */
+	u16 vendorid;	/* PCI vendor id */
+	u16 deviceid;	/* PCI device id */
+	uint corerev;		/* core revision */
+	u8 sromrev;		/* version # of the srom */
+	u16 boardrev;	/* version # of particular board */
+	u32 boardflags;	/* Board specific flags from srom */
+	u32 boardflags2;	/* More board flags if sromrev >= 4 */
+	u32 machwcap;	/* MAC capabilities */
+	u32 machwcap_backup;	/* backup of machwcap */
+	u16 ucode_dbgsel;	/* dbgsel for ucode debug(config gpio) */
+
+	si_t *sih;		/* SB handle (cookie for siutils calls) */
+	char *vars;		/* "environment" name=value */
+	uint vars_size;		/* size of vars, free vars on detach */
+	d11regs_t *regs;	/* pointer to device registers */
+	void *physhim;		/* phy shim layer handler */
+	void *phy_sh;		/* pointer to shared phy state */
+	struct wlc_hwband *band;/* pointer to active per-band state */
+	struct wlc_hwband *bandstate[MAXBANDS];/* band state per phy/radio */
+	u16 bmac_phytxant;	/* cache of high phytxant state */
+	bool shortslot;		/* currently using 11g ShortSlot timing */
+	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
+	u16 LRL;		/* 802.11 dot11LongRetryLimit */
+	u16 SFBL;		/* Short Frame Rate Fallback Limit */
+	u16 LFBL;		/* Long Frame Rate Fallback Limit */
+
+	bool up;		/* d11 hardware up and running */
+	uint now;		/* # elapsed seconds */
+	uint _nbands;		/* # bands supported */
+	chanspec_t chanspec;	/* bmac chanspec shadow */
+
+	uint *txavail[NFIFO];	/* # tx descriptors available */
+	u16 *xmtfifo_sz;	/* fifo size in 256B for each xmt fifo */
+
+	mbool pllreq;		/* pll requests to keep PLL on */
+
+	u8 suspended_fifos;	/* Which TX fifo to remain awake for */
+	u32 maccontrol;	/* Cached value of maccontrol */
+	uint mac_suspend_depth;	/* current depth of mac_suspend levels */
+	u32 wake_override;	/* Various conditions to force MAC to WAKE mode */
+	u32 mute_override;	/* Prevent ucode from sending beacons */
+	u8 etheraddr[ETH_ALEN];	/* currently configured ethernet address */
+	u32 led_gpio_mask;	/* LED GPIO Mask */
+	bool noreset;		/* true= do not reset hw, used by WLC_OUT */
+	bool forcefastclk;	/* true if the h/w is forcing the use of fast clk */
+	bool clk;		/* core is out of reset and has clock */
+	bool sbclk;		/* sb has clock */
+	struct bmac_pmq *bmac_pmq; /*  bmac PM states derived from ucode PMQ */
+	bool phyclk;		/* phy is out of reset and has clock */
+	bool dma_lpbk;		/* core is in DMA loopback */
+
+	bool ucode_loaded;	/* true after ucode downloaded */
+
+
+	u8 hw_stf_ss_opmode;	/* STF single stream operation mode */
+	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
+				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+				 */
+	u32 antsel_avail;	/*
+				 * put struct antsel_info here if more info is
+				 * needed
+				 */
+};
+
+/* TX Queue information
+ *
+ * Each flow of traffic out of the device has a TX Queue with independent
+ * flow control. Several interfaces may be associated with a single TX Queue
+ * if they belong to the same flow of traffic from the device. For multi-channel
+ * operation there are independent TX Queues for each channel.
+ */
+struct wlc_txq_info {
+	struct wlc_txq_info *next;
+	struct pktq q;
+	uint stopped;		/* tx flow control bits */
+};
+
+/*
+ * Principal common (os-independent) software data structure.
+ */
+struct wlc_info {
+	struct wlc_pub *pub;		/* pointer to wlc public state */
+	struct wl_info *wl;	/* pointer to os-specific private state */
+	d11regs_t *regs;	/* pointer to device registers */
+
+	struct wlc_hw_info *hw;	/* HW related state used primarily by BMAC */
+
+	/* clock */
+	int clkreq_override;	/* setting for clkreq for PCIE : Auto, 0, 1 */
+	u16 fastpwrup_dly;	/* time in us needed to bring up d11 fast clock */
+
+	/* interrupt */
+	u32 macintstatus;	/* bit channel between isr and dpc */
+	u32 macintmask;	/* sw runtime master macintmask value */
+	u32 defmacintmask;	/* default "on" macintmask value */
+
+	/* up and down */
+	bool device_present;	/* (removable) device is present */
+
+	bool clk;		/* core is out of reset and has clock */
+
+	/* multiband */
+	struct wlccore *core;	/* pointer to active io core */
+	struct wlcband *band;	/* pointer to active per-band state */
+	struct wlccore *corestate;	/* per-core state (one per hw core) */
+	/* per-band state (one per phy/radio): */
+	struct wlcband *bandstate[MAXBANDS];
+
+	bool war16165;		/* PCI slow clock 16165 war flag */
+
+	bool tx_suspended;	/* data fifos need to remain suspended */
+
+	uint txpend16165war;
+
+	/* packet queue */
+	uint qvalid;		/* DirFrmQValid and BcMcFrmQValid */
+
+	/* Regulatory power limits */
+	s8 txpwr_local_max;	/* regulatory local txpwr max */
+	u8 txpwr_local_constraint;	/* local power contraint in dB */
+
+
+	struct ampdu_info *ampdu;	/* ampdu module handler */
+	struct antsel_info *asi;	/* antsel module handler */
+	wlc_cm_info_t *cmi;	/* channel manager module handler */
+
+	void *btparam;		/* bus type specific cookie */
+
+	uint vars_size;		/* size of vars, free vars on detach */
+
+	u16 vendorid;	/* PCI vendor id */
+	u16 deviceid;	/* PCI device id */
+	uint ucode_rev;		/* microcode revision */
+
+	u32 machwcap;	/* MAC capabilities, BMAC shadow */
+
+	u8 perm_etheraddr[ETH_ALEN];	/* original sprom local ethernet address */
+
+	bool bandlocked;	/* disable auto multi-band switching */
+	bool bandinit_pending;	/* track band init in auto band */
+
+	bool radio_monitor;	/* radio timer is running */
+	bool down_override;	/* true=down */
+	bool going_down;	/* down path intermediate variable */
+
+	bool mpc;		/* enable minimum power consumption */
+	u8 mpc_dlycnt;	/* # of watchdog cnt before turn disable radio */
+	u8 mpc_offcnt;	/* # of watchdog cnt that radio is disabled */
+	u8 mpc_delay_off;	/* delay radio disable by # of watchdog cnt */
+	u8 prev_non_delay_mpc;	/* prev state wlc_is_non_delay_mpc */
+
+	/* timer */
+	struct wl_timer *wdtimer;	/* timer for watchdog routine */
+	uint fast_timer;	/* Periodic timeout for 'fast' timer */
+	uint slow_timer;	/* Periodic timeout for 'slow' timer */
+	uint glacial_timer;	/* Periodic timeout for 'glacial' timer */
+	uint phycal_mlo;	/* last time measurelow calibration was done */
+	uint phycal_txpower;	/* last time txpower calibration was done */
+
+	struct wl_timer *radio_timer;	/* timer for hw radio button monitor routine */
+	struct wl_timer *pspoll_timer;	/* periodic pspoll timer */
+
+	/* promiscuous */
+	bool monitor;		/* monitor (MPDU sniffing) mode */
+	bool bcnmisc_ibss;	/* bcns promisc mode override for IBSS */
+	bool bcnmisc_scan;	/* bcns promisc mode override for scan */
+	bool bcnmisc_monitor;	/* bcns promisc mode override for monitor */
+
+	u8 bcn_wait_prd;	/* max waiting period (for beacon) in 1024TU */
+
+	/* driver feature */
+	bool _rifs;		/* enable per-packet rifs */
+	s32 rifs_advert;	/* RIFS mode advertisement */
+	s8 sgi_tx;		/* sgi tx */
+	bool wet;		/* true if wireless ethernet bridging mode */
+
+	/* AP-STA synchronization, power save */
+	bool check_for_unaligned_tbtt;	/* check unaligned tbtt flag */
+	bool PM_override;	/* no power-save flag, override PM(user input) */
+	bool PMenabled;		/* current power-management state (CAM or PS) */
+	bool PMpending;		/* waiting for tx status with PM indicated set */
+	bool PMblocked;		/* block any PSPolling in PS mode, used to buffer
+				 * AP traffic, also used to indicate in progress
+				 * of scan, rm, etc. off home channel activity.
+				 */
+	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
+	u8 PM;		/* power-management mode (CAM, PS or FASTPS) */
+	bool PMawakebcn;	/* bcn recvd during current waking state */
+
+	bool WME_PM_blocked;	/* Can STA go to PM when in WME Auto mode */
+	bool wake;		/* host-specified PS-mode sleep state */
+	u8 pspoll_prd;	/* pspoll interval in milliseconds */
+	u8 bcn_li_bcn;	/* beacon listen interval in # beacons */
+	u8 bcn_li_dtim;	/* beacon listen interval in # dtims */
+
+	bool WDarmed;		/* watchdog timer is armed */
+	u32 WDlast;		/* last time wlc_watchdog() was called */
+
+	/* WME */
+	ac_bitmap_t wme_dp;	/* Discard (oldest first) policy per AC */
+	bool wme_apsd;		/* enable Advanced Power Save Delivery */
+	ac_bitmap_t wme_admctl;	/* bit i set if AC i under admission control */
+	u16 edcf_txop[AC_COUNT];	/* current txop for each ac */
+	wme_param_ie_t wme_param_ie;	/* WME parameter info element, which on STA
+					 * contains parameters in use locally, and on
+					 * AP contains parameters advertised to STA
+					 * in beacons and assoc responses.
+					 */
+	bool wme_prec_queuing;	/* enable/disable non-wme STA prec queuing */
+	u16 wme_retries[AC_COUNT];	/* per-AC retry limits */
+
+	int vlan_mode;		/* OK to use 802.1Q Tags (ON, OFF, AUTO) */
+	u16 tx_prec_map;	/* Precedence map based on HW FIFO space */
+	u16 fifo2prec_map[NFIFO];	/* pointer to fifo2_prec map based on WME */
+
+	/*
+	 * BSS Configurations set of BSS configurations, idx 0 is default and
+	 * always valid
+	 */
+	struct wlc_bsscfg *bsscfg[WLC_MAXBSSCFG];
+	struct wlc_bsscfg *cfg;	/* the primary bsscfg (can be AP or STA) */
+	u8 stas_associated;	/* count of ASSOCIATED STA bsscfgs */
+	u8 aps_associated;	/* count of UP AP bsscfgs */
+	u8 block_datafifo;	/* prohibit posting frames to data fifos */
+	bool bcmcfifo_drain;	/* TX_BCMC_FIFO is set to drain */
+
+	/* tx queue */
+	struct wlc_txq_info *tx_queues;	/* common TX Queue list */
+
+	/* security */
+	wsec_key_t *wsec_keys[WSEC_MAX_KEYS];	/* dynamic key storage */
+	wsec_key_t *wsec_def_keys[WLC_DEFAULT_KEYS];	/* default key storage */
+	bool wsec_swkeys;	/* indicates that all keys should be
+				 * treated as sw keys (used for debugging)
+				 */
+	struct modulecb *modulecb;
+	struct dumpcb_s *dumpcb_head;
+
+	u8 mimoft;		/* SIGN or 11N */
+	u8 mimo_band_bwcap;	/* bw cap per band type */
+	s8 txburst_limit_override;	/* tx burst limit override */
+	u16 txburst_limit;	/* tx burst limit value */
+	s8 cck_40txbw;	/* 11N, cck tx b/w override when in 40MHZ mode */
+	s8 ofdm_40txbw;	/* 11N, ofdm tx b/w override when in 40MHZ mode */
+	s8 mimo_40txbw;	/* 11N, mimo tx b/w override when in 40MHZ mode */
+	/* HT CAP IE being advertised by this node: */
+	struct ieee80211_ht_cap ht_cap;
+
+	uint seckeys;		/* 54 key table shm address */
+	uint tkmickeys;		/* 12 TKIP MIC key table shm address */
+
+	wlc_bss_info_t *default_bss;	/* configured BSS parameters */
+
+	u16 AID;		/* association ID */
+	u16 counter;		/* per-sdu monotonically increasing counter */
+	u16 mc_fid_counter;	/* BC/MC FIFO frame ID counter */
+
+	bool ibss_allowed;	/* false, all IBSS will be ignored during a scan
+				 * and the driver will not allow the creation of
+				 * an IBSS network
+				 */
+	bool ibss_coalesce_allowed;
+
+	char country_default[WLC_CNTRY_BUF_SZ];	/* saved country for leaving 802.11d
+						 * auto-country mode
+						 */
+	char autocountry_default[WLC_CNTRY_BUF_SZ];	/* initial country for 802.11d
+							 * auto-country mode
+							 */
+#ifdef BCMDBG
+	bcm_tlv_t *country_ie_override;	/* debug override of announced Country IE */
+#endif
+
+	u16 prb_resp_timeout;	/* do not send prb resp if request older than this,
+					 * 0 = disable
+					 */
+
+	wlc_rateset_t sup_rates_override;	/* use only these rates in 11g supported rates if
+						 * specifed
+						 */
+
+	chanspec_t home_chanspec;	/* shared home chanspec */
+
+	/* PHY parameters */
+	chanspec_t chanspec;	/* target operational channel */
+	u16 usr_fragthresh;	/* user configured fragmentation threshold */
+	u16 fragthresh[NFIFO];	/* per-fifo fragmentation thresholds */
+	u16 RTSThresh;	/* 802.11 dot11RTSThreshold */
+	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
+	u16 LRL;		/* 802.11 dot11LongRetryLimit */
+	u16 SFBL;		/* Short Frame Rate Fallback Limit */
+	u16 LFBL;		/* Long Frame Rate Fallback Limit */
+
+	/* network config */
+	bool shortpreamble;	/* currently operating with CCK ShortPreambles */
+	bool shortslot;		/* currently using 11g ShortSlot timing */
+	s8 barker_preamble;	/* current Barker Preamble Mode */
+	s8 shortslot_override;	/* 11g ShortSlot override */
+	bool include_legacy_erp;	/* include Legacy ERP info elt ID 47 as well as g ID 42 */
+	bool barker_overlap_control;	/* true: be aware of overlapping BSSs for barker */
+	bool ignore_bcns;	/* override: ignore non shortslot bcns in a 11g network */
+	bool legacy_probe;	/* restricts probe requests to CCK rates */
+
+	struct wlc_protection *protection;
+	s8 PLCPHdr_override;	/* 802.11b Preamble Type override */
+
+	struct wlc_stf *stf;
+
+	struct pkt_cb *pkt_callback;	/* tx completion callback handlers */
+
+	u32 txretried;	/* tx retried number in one msdu */
+
+	ratespec_t bcn_rspec;	/* save bcn ratespec purpose */
+
+	bool apsd_sta_usp;	/* Unscheduled Service Period in progress on STA */
+	struct wl_timer *apsd_trigger_timer;	/* timer for wme apsd trigger frames */
+	u32 apsd_trigger_timeout;	/* timeout value for apsd_trigger_timer (in ms)
+					 * 0 == disable
+					 */
+	ac_bitmap_t apsd_trigger_ac;	/* Permissible Access Category in which APSD Null
+					 * Trigger frames can be send
+					 */
+	u8 htphy_membership;	/* HT PHY membership */
+
+	bool _regulatory_domain;	/* 802.11d enabled? */
+
+	u8 mimops_PM;
+
+	u8 txpwr_percent;	/* power output percentage */
+
+	u8 ht_wsec_restriction;	/* the restriction of HT with TKIP or WEP */
+
+	uint tempsense_lasttime;
+
+	u16 tx_duty_cycle_ofdm;	/* maximum allowed duty cycle for OFDM */
+	u16 tx_duty_cycle_cck;	/* maximum allowed duty cycle for CCK */
+
+	u16 next_bsscfg_ID;
+
+	struct wlc_if *wlcif_list;	/* linked list of wlc_if structs */
+	struct wlc_txq_info *active_queue; /* txq for the currently active
+					    * transmit context
+					    */
+	u32 mpc_dur;		/* total time (ms) in mpc mode except for the
+				 * portion since radio is turned off last time
+				 */
+	u32 mpc_laston_ts;	/* timestamp (ms) when radio is turned off last
+				 * time
+				 */
+	bool pr80838_war;
+	uint hwrxoff;
+};
+
+/* antsel module specific state */
+struct antsel_info {
+	struct wlc_info *wlc;	/* pointer to main wlc structure */
+	struct wlc_pub *pub;		/* pointer to public fn */
+	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
+				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
+				 */
+	u8 antsel_antswitch;	/* board level antenna switch type */
+	bool antsel_avail;	/* Ant selection availability (SROM based) */
+	wlc_antselcfg_t antcfg_11n;	/* antenna configuration */
+	wlc_antselcfg_t antcfg_cur;	/* current antenna config (auto) */
+};
+
+#define	CHANNEL_BANDUNIT(wlc, ch) (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
+#define	OTHERBANDUNIT(wlc)	((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
+
+#define IS_MBAND_UNLOCKED(wlc) \
+	((NBANDS(wlc) > 1) && !(wlc)->bandlocked)
+
+#define WLC_BAND_PI_RADIO_CHANSPEC wlc_phy_chanspec_get(wlc->band->pi)
+
+/* sum the individual fifo tx pending packet counts */
+#define	TXPKTPENDTOT(wlc) ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \
+	(wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3])
+#define TXPKTPENDGET(wlc, fifo)		((wlc)->core->txpktpend[(fifo)])
+#define TXPKTPENDINC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] += (val))
+#define TXPKTPENDDEC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] -= (val))
+#define TXPKTPENDCLR(wlc, fifo)		((wlc)->core->txpktpend[(fifo)] = 0)
+#define TXAVAIL(wlc, fifo)		(*(wlc)->core->txavail[(fifo)])
+#define GETNEXTTXP(wlc, _queue)								\
+		dma_getnexttxp((wlc)->hw->di[(_queue)], HNDDMA_RANGE_TRANSMITTED)
+
+#define WLC_IS_MATCH_SSID(wlc, ssid1, ssid2, len1, len2) \
+	((len1 == len2) && !memcmp(ssid1, ssid2, len1))
+
+extern void wlc_high_dpc(struct wlc_info *wlc, u32 macintstatus);
+extern void wlc_fatal_error(struct wlc_info *wlc);
+extern void wlc_bmac_rpc_watchdog(struct wlc_info *wlc);
+extern void wlc_recv(struct wlc_info *wlc, struct sk_buff *p);
+extern bool wlc_dotxstatus(struct wlc_info *wlc, tx_status_t *txs, u32 frm_tx2);
+extern void wlc_txfifo(struct wlc_info *wlc, uint fifo, struct sk_buff *p,
+		       bool commit, s8 txpktpend);
+extern void wlc_txfifo_complete(struct wlc_info *wlc, uint fifo, s8 txpktpend);
+extern void wlc_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
+			uint prec);
+extern void wlc_info_init(struct wlc_info *wlc, int unit);
+extern void wlc_print_txstatus(tx_status_t *txs);
+extern int wlc_xmtfifo_sz_get(struct wlc_info *wlc, uint fifo, uint *blocks);
+extern void wlc_write_template_ram(struct wlc_info *wlc, int offset, int len,
+				   void *buf);
+extern void wlc_write_hw_bcntemplates(struct wlc_info *wlc, void *bcn, int len,
+				      bool both);
+#if defined(BCMDBG)
+extern void wlc_get_rcmta(struct wlc_info *wlc, int idx,
+			  u8 *addr);
+#endif
+extern void wlc_set_rcmta(struct wlc_info *wlc, int idx,
+			  const u8 *addr);
+extern void wlc_read_tsf(struct wlc_info *wlc, u32 *tsf_l_ptr,
+			 u32 *tsf_h_ptr);
+extern void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin);
+extern void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax);
+extern void wlc_fifoerrors(struct wlc_info *wlc);
+extern void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit);
+extern void wlc_reset_bmac_done(struct wlc_info *wlc);
+extern void wlc_hwtimer_gptimer_set(struct wlc_info *wlc, uint us);
+extern void wlc_hwtimer_gptimer_abort(struct wlc_info *wlc);
+
+#if defined(BCMDBG)
+extern void wlc_print_rxh(d11rxhdr_t *rxh);
+extern void wlc_print_hdrs(struct wlc_info *wlc, const char *prefix, u8 *frame,
+			   d11txh_t *txh, d11rxhdr_t *rxh, uint len);
+extern void wlc_print_txdesc(d11txh_t *txh);
+#else
+#define wlc_print_txdesc(a)
+#endif
+#if defined(BCMDBG)
+extern void wlc_print_dot11_mac_hdr(u8 *buf, int len);
+#endif
+
+extern void wlc_setxband(struct wlc_hw_info *wlc_hw, uint bandunit);
+extern void wlc_coredisable(struct wlc_hw_info *wlc_hw);
+
+extern bool wlc_valid_rate(struct wlc_info *wlc, ratespec_t rate, int band,
+			   bool verbose);
+extern void wlc_ap_upd(struct wlc_info *wlc);
+
+/* helper functions */
+extern void wlc_shm_ssid_upd(struct wlc_info *wlc, struct wlc_bsscfg *cfg);
+extern int wlc_set_gmode(struct wlc_info *wlc, u8 gmode, bool config);
+
+extern void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc);
+extern void wlc_mac_bcn_promisc(struct wlc_info *wlc);
+extern void wlc_mac_promisc(struct wlc_info *wlc);
+extern void wlc_txflowcontrol(struct wlc_info *wlc, struct wlc_txq_info *qi,
+			      bool on, int prio);
+extern void wlc_txflowcontrol_override(struct wlc_info *wlc,
+				       struct wlc_txq_info *qi,
+				       bool on, uint override);
+extern bool wlc_txflowcontrol_prio_isset(struct wlc_info *wlc,
+					 struct wlc_txq_info *qi, int prio);
+extern void wlc_send_q(struct wlc_info *wlc, struct wlc_txq_info *qi);
+extern int wlc_prep_pdu(struct wlc_info *wlc, struct sk_buff *pdu, uint *fifo);
+
+extern u16 wlc_calc_lsig_len(struct wlc_info *wlc, ratespec_t ratespec,
+				uint mac_len);
+extern ratespec_t wlc_rspec_to_rts_rspec(struct wlc_info *wlc, ratespec_t rspec,
+					 bool use_rspec, u16 mimo_ctlchbw);
+extern u16 wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only,
+				     ratespec_t rts_rate, ratespec_t frame_rate,
+				     u8 rts_preamble_type,
+				     u8 frame_preamble_type, uint frame_len,
+				     bool ba);
+
+extern void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs);
+extern void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn));
+
+#if defined(BCMDBG)
+extern void wlc_dump_ie(struct wlc_info *wlc, bcm_tlv_t *ie,
+			struct bcmstrbuf *b);
+#endif
+
+extern bool wlc_ps_check(struct wlc_info *wlc);
+extern void wlc_reprate_init(struct wlc_info *wlc);
+extern void wlc_bsscfg_reprate_init(struct wlc_bsscfg *bsscfg);
+extern void wlc_uint64_sub(u32 *a_high, u32 *a_low, u32 b_high,
+			   u32 b_low);
+extern u32 wlc_calc_tbtt_offset(u32 bi, u32 tsf_h, u32 tsf_l);
+
+/* Shared memory access */
+extern void wlc_write_shm(struct wlc_info *wlc, uint offset, u16 v);
+extern u16 wlc_read_shm(struct wlc_info *wlc, uint offset);
+extern void wlc_set_shm(struct wlc_info *wlc, uint offset, u16 v, int len);
+extern void wlc_copyto_shm(struct wlc_info *wlc, uint offset, const void *buf,
+			   int len);
+extern void wlc_copyfrom_shm(struct wlc_info *wlc, uint offset, void *buf,
+			     int len);
+
+extern void wlc_update_beacon(struct wlc_info *wlc);
+extern void wlc_bss_update_beacon(struct wlc_info *wlc,
+				  struct wlc_bsscfg *bsscfg);
+
+extern void wlc_update_probe_resp(struct wlc_info *wlc, bool suspend);
+extern void wlc_bss_update_probe_resp(struct wlc_info *wlc,
+				      struct wlc_bsscfg *cfg, bool suspend);
+
+extern bool wlc_ismpc(struct wlc_info *wlc);
+extern bool wlc_is_non_delay_mpc(struct wlc_info *wlc);
+extern void wlc_radio_mpc_upd(struct wlc_info *wlc);
+extern bool wlc_prec_enq(struct wlc_info *wlc, struct pktq *q, void *pkt,
+			 int prec);
+extern bool wlc_prec_enq_head(struct wlc_info *wlc, struct pktq *q,
+			      struct sk_buff *pkt, int prec, bool head);
+extern u16 wlc_phytxctl1_calc(struct wlc_info *wlc, ratespec_t rspec);
+extern void wlc_compute_plcp(struct wlc_info *wlc, ratespec_t rate, uint length,
+			     u8 *plcp);
+extern uint wlc_calc_frame_time(struct wlc_info *wlc, ratespec_t ratespec,
+				u8 preamble_type, uint mac_len);
+
+extern void wlc_set_chanspec(struct wlc_info *wlc, chanspec_t chanspec);
+
+extern bool wlc_timers_init(struct wlc_info *wlc, int unit);
+
+extern const bcm_iovar_t wlc_iovars[];
+
+extern int wlc_doiovar(void *hdl, const bcm_iovar_t *vi, u32 actionid,
+		       const char *name, void *params, uint p_len, void *arg,
+		       int len, int val_size, struct wlc_if *wlcif);
+
+#if defined(BCMDBG)
+extern void wlc_print_ies(struct wlc_info *wlc, u8 *ies, uint ies_len);
+#endif
+
+extern int wlc_set_nmode(struct wlc_info *wlc, s32 nmode);
+extern void wlc_ht_mimops_cap_update(struct wlc_info *wlc, u8 mimops_mode);
+extern void wlc_mimops_action_ht_send(struct wlc_info *wlc,
+				      struct wlc_bsscfg *bsscfg,
+				      u8 mimops_mode);
+
+extern void wlc_switch_shortslot(struct wlc_info *wlc, bool shortslot);
+extern void wlc_set_bssid(struct wlc_bsscfg *cfg);
+extern void wlc_edcf_setparams(struct wlc_bsscfg *cfg, bool suspend);
+
+extern void wlc_set_ratetable(struct wlc_info *wlc);
+extern int wlc_set_mac(struct wlc_bsscfg *cfg);
+extern void wlc_beacon_phytxctl_txant_upd(struct wlc_info *wlc,
+					  ratespec_t bcn_rate);
+extern void wlc_mod_prb_rsp_rate_table(struct wlc_info *wlc, uint frame_len);
+extern ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc,
+					 wlc_rateset_t *rs);
+extern u16 wlc_compute_bcntsfoff(struct wlc_info *wlc, ratespec_t rspec,
+				    bool short_preamble, bool phydelay);
+extern void wlc_radio_disable(struct wlc_info *wlc);
+extern void wlc_bcn_li_upd(struct wlc_info *wlc);
+
+extern int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len);
+extern void wlc_out(struct wlc_info *wlc);
+extern void wlc_set_home_chanspec(struct wlc_info *wlc, chanspec_t chanspec);
+extern void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt);
+extern bool wlc_ps_allowed(struct wlc_info *wlc);
+extern bool wlc_stay_awake(struct wlc_info *wlc);
+extern void wlc_wme_initparams_sta(struct wlc_info *wlc, wme_param_ie_t *pe);
+
+extern void wlc_bss_list_free(struct wlc_info *wlc,
+			      struct wlc_bss_list *bss_list);
+extern void wlc_ht_mimops_cap_update(struct wlc_info *wlc, u8 mimops_mode);
+#endif				/* _wlc_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c b/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c
new file mode 100644
index 0000000..96d3600
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
+ *   WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
+ *   On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
+ *   access to wlc_hw pointer.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include <proto/802.11.h>
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <bcmwifi.h>
+#include <siutils.h>
+#include <wlioctl.h>
+#include <sbconfig.h>
+#include <sbchipc.h>
+#include <pcicfg.h>
+#include <sbhnddma.h>
+#include <hnddma.h>
+#include <hndpmu.h>
+
+#include "wlc_types.h"
+#include "wl_dbg.h"
+#include "wlc_cfg.h"
+#include "d11.h"
+#include "wlc_rate.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_channel.h"
+#include "bcmsrom.h"
+#include "wlc_key.h"
+#include "wlc_bmac.h"
+#include "wlc_phy_hal.h"
+#include "wl_export.h"
+#include "wlc_main.h"
+#include "wlc_phy_shim.h"
+
+/* PHY SHIM module specific state */
+struct wlc_phy_shim_info {
+	struct wlc_hw_info *wlc_hw;	/* pointer to main wlc_hw structure */
+	void *wlc;		/* pointer to main wlc structure */
+	void *wl;		/* pointer to os-specific private state */
+};
+
+wlc_phy_shim_info_t *wlc_phy_shim_attach(struct wlc_hw_info *wlc_hw,
+						       void *wl, void *wlc) {
+	wlc_phy_shim_info_t *physhim = NULL;
+
+	physhim = kzalloc(sizeof(wlc_phy_shim_info_t), GFP_ATOMIC);
+	if (!physhim) {
+		WL_ERROR("wl%d: wlc_phy_shim_attach: out of mem\n",
+			 wlc_hw->unit);
+		return NULL;
+	}
+	physhim->wlc_hw = wlc_hw;
+	physhim->wlc = wlc;
+	physhim->wl = wl;
+
+	return physhim;
+}
+
+void wlc_phy_shim_detach(wlc_phy_shim_info_t *physhim)
+{
+	kfree(physhim);
+}
+
+struct wlapi_timer *wlapi_init_timer(wlc_phy_shim_info_t *physhim,
+				     void (*fn) (void *arg), void *arg,
+				     const char *name)
+{
+	return (struct wlapi_timer *)wl_init_timer(physhim->wl, fn, arg, name);
+}
+
+void wlapi_free_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t)
+{
+	wl_free_timer(physhim->wl, (struct wl_timer *)t);
+}
+
+void
+wlapi_add_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t, uint ms,
+		int periodic)
+{
+	wl_add_timer(physhim->wl, (struct wl_timer *)t, ms, periodic);
+}
+
+bool wlapi_del_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t)
+{
+	return wl_del_timer(physhim->wl, (struct wl_timer *)t);
+}
+
+void wlapi_intrson(wlc_phy_shim_info_t *physhim)
+{
+	wl_intrson(physhim->wl);
+}
+
+u32 wlapi_intrsoff(wlc_phy_shim_info_t *physhim)
+{
+	return wl_intrsoff(physhim->wl);
+}
+
+void wlapi_intrsrestore(wlc_phy_shim_info_t *physhim, u32 macintmask)
+{
+	wl_intrsrestore(physhim->wl, macintmask);
+}
+
+void wlapi_bmac_write_shm(wlc_phy_shim_info_t *physhim, uint offset, u16 v)
+{
+	wlc_bmac_write_shm(physhim->wlc_hw, offset, v);
+}
+
+u16 wlapi_bmac_read_shm(wlc_phy_shim_info_t *physhim, uint offset)
+{
+	return wlc_bmac_read_shm(physhim->wlc_hw, offset);
+}
+
+void
+wlapi_bmac_mhf(wlc_phy_shim_info_t *physhim, u8 idx, u16 mask,
+	       u16 val, int bands)
+{
+	wlc_bmac_mhf(physhim->wlc_hw, idx, mask, val, bands);
+}
+
+void wlapi_bmac_corereset(wlc_phy_shim_info_t *physhim, u32 flags)
+{
+	wlc_bmac_corereset(physhim->wlc_hw, flags);
+}
+
+void wlapi_suspend_mac_and_wait(wlc_phy_shim_info_t *physhim)
+{
+	wlc_suspend_mac_and_wait(physhim->wlc);
+}
+
+void wlapi_switch_macfreq(wlc_phy_shim_info_t *physhim, u8 spurmode)
+{
+	wlc_bmac_switch_macfreq(physhim->wlc_hw, spurmode);
+}
+
+void wlapi_enable_mac(wlc_phy_shim_info_t *physhim)
+{
+	wlc_enable_mac(physhim->wlc);
+}
+
+void wlapi_bmac_mctrl(wlc_phy_shim_info_t *physhim, u32 mask, u32 val)
+{
+	wlc_bmac_mctrl(physhim->wlc_hw, mask, val);
+}
+
+void wlapi_bmac_phy_reset(wlc_phy_shim_info_t *physhim)
+{
+	wlc_bmac_phy_reset(physhim->wlc_hw);
+}
+
+void wlapi_bmac_bw_set(wlc_phy_shim_info_t *physhim, u16 bw)
+{
+	wlc_bmac_bw_set(physhim->wlc_hw, bw);
+}
+
+u16 wlapi_bmac_get_txant(wlc_phy_shim_info_t *physhim)
+{
+	return wlc_bmac_get_txant(physhim->wlc_hw);
+}
+
+void wlapi_bmac_phyclk_fgc(wlc_phy_shim_info_t *physhim, bool clk)
+{
+	wlc_bmac_phyclk_fgc(physhim->wlc_hw, clk);
+}
+
+void wlapi_bmac_macphyclk_set(wlc_phy_shim_info_t *physhim, bool clk)
+{
+	wlc_bmac_macphyclk_set(physhim->wlc_hw, clk);
+}
+
+void wlapi_bmac_core_phypll_ctl(wlc_phy_shim_info_t *physhim, bool on)
+{
+	wlc_bmac_core_phypll_ctl(physhim->wlc_hw, on);
+}
+
+void wlapi_bmac_core_phypll_reset(wlc_phy_shim_info_t *physhim)
+{
+	wlc_bmac_core_phypll_reset(physhim->wlc_hw);
+}
+
+void wlapi_bmac_ucode_wake_override_phyreg_set(wlc_phy_shim_info_t *physhim)
+{
+	wlc_ucode_wake_override_set(physhim->wlc_hw, WLC_WAKE_OVERRIDE_PHYREG);
+}
+
+void wlapi_bmac_ucode_wake_override_phyreg_clear(wlc_phy_shim_info_t *physhim)
+{
+	wlc_ucode_wake_override_clear(physhim->wlc_hw,
+				      WLC_WAKE_OVERRIDE_PHYREG);
+}
+
+void
+wlapi_bmac_write_template_ram(wlc_phy_shim_info_t *physhim, int offset,
+			      int len, void *buf)
+{
+	wlc_bmac_write_template_ram(physhim->wlc_hw, offset, len, buf);
+}
+
+u16 wlapi_bmac_rate_shm_offset(wlc_phy_shim_info_t *physhim, u8 rate)
+{
+	return wlc_bmac_rate_shm_offset(physhim->wlc_hw, rate);
+}
+
+void wlapi_ucode_sample_init(wlc_phy_shim_info_t *physhim)
+{
+}
+
+void
+wlapi_copyfrom_objmem(wlc_phy_shim_info_t *physhim, uint offset, void *buf,
+		      int len, u32 sel)
+{
+	wlc_bmac_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
+}
+
+void
+wlapi_copyto_objmem(wlc_phy_shim_info_t *physhim, uint offset, const void *buf,
+		    int l, u32 sel)
+{
+	wlc_bmac_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h b/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h
new file mode 100644
index 0000000..c151a5d
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_phy_shim.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_phy_shim_h_
+#define _wlc_phy_shim_h_
+
+#define RADAR_TYPE_NONE		0	/* Radar type None */
+#define RADAR_TYPE_ETSI_1	1	/* ETSI 1 Radar type */
+#define RADAR_TYPE_ETSI_2	2	/* ETSI 2 Radar type */
+#define RADAR_TYPE_ETSI_3	3	/* ETSI 3 Radar type */
+#define RADAR_TYPE_ITU_E	4	/* ITU E Radar type */
+#define RADAR_TYPE_ITU_K	5	/* ITU K Radar type */
+#define RADAR_TYPE_UNCLASSIFIED	6	/* Unclassified Radar type  */
+#define RADAR_TYPE_BIN5		7	/* long pulse radar type */
+#define RADAR_TYPE_STG2 	8	/* staggered-2 radar */
+#define RADAR_TYPE_STG3 	9	/* staggered-3 radar */
+#define RADAR_TYPE_FRA		10	/* French radar */
+
+/* French radar pulse widths */
+#define FRA_T1_20MHZ	52770
+#define FRA_T2_20MHZ	61538
+#define FRA_T3_20MHZ	66002
+#define FRA_T1_40MHZ	105541
+#define FRA_T2_40MHZ	123077
+#define FRA_T3_40MHZ	132004
+#define FRA_ERR_20MHZ	60
+#define FRA_ERR_40MHZ	120
+
+#define ANTSEL_NA		0	/* No boardlevel selection available */
+#define ANTSEL_2x4		1	/* 2x4 boardlevel selection available */
+#define ANTSEL_2x3		2	/* 2x3 CB2 boardlevel selection available */
+
+/* Rx Antenna diversity control values */
+#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
+#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
+#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
+#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
+#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
+#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
+
+/* Forward declarations */
+struct wlc_hw_info;
+typedef struct wlc_phy_shim_info wlc_phy_shim_info_t;
+
+extern wlc_phy_shim_info_t *wlc_phy_shim_attach(struct wlc_hw_info *wlc_hw,
+						void *wl, void *wlc);
+extern void wlc_phy_shim_detach(wlc_phy_shim_info_t *physhim);
+
+/* PHY to WL utility functions */
+struct wlapi_timer;
+extern struct wlapi_timer *wlapi_init_timer(wlc_phy_shim_info_t *physhim,
+					    void (*fn) (void *arg), void *arg,
+					    const char *name);
+extern void wlapi_free_timer(wlc_phy_shim_info_t *physhim,
+			     struct wlapi_timer *t);
+extern void wlapi_add_timer(wlc_phy_shim_info_t *physhim,
+			    struct wlapi_timer *t, uint ms, int periodic);
+extern bool wlapi_del_timer(wlc_phy_shim_info_t *physhim,
+			    struct wlapi_timer *t);
+extern void wlapi_intrson(wlc_phy_shim_info_t *physhim);
+extern u32 wlapi_intrsoff(wlc_phy_shim_info_t *physhim);
+extern void wlapi_intrsrestore(wlc_phy_shim_info_t *physhim,
+			       u32 macintmask);
+
+extern void wlapi_bmac_write_shm(wlc_phy_shim_info_t *physhim, uint offset,
+				 u16 v);
+extern u16 wlapi_bmac_read_shm(wlc_phy_shim_info_t *physhim, uint offset);
+extern void wlapi_bmac_mhf(wlc_phy_shim_info_t *physhim, u8 idx,
+			   u16 mask, u16 val, int bands);
+extern void wlapi_bmac_corereset(wlc_phy_shim_info_t *physhim, u32 flags);
+extern void wlapi_suspend_mac_and_wait(wlc_phy_shim_info_t *physhim);
+extern void wlapi_switch_macfreq(wlc_phy_shim_info_t *physhim, u8 spurmode);
+extern void wlapi_enable_mac(wlc_phy_shim_info_t *physhim);
+extern void wlapi_bmac_mctrl(wlc_phy_shim_info_t *physhim, u32 mask,
+			     u32 val);
+extern void wlapi_bmac_phy_reset(wlc_phy_shim_info_t *physhim);
+extern void wlapi_bmac_bw_set(wlc_phy_shim_info_t *physhim, u16 bw);
+extern void wlapi_bmac_phyclk_fgc(wlc_phy_shim_info_t *physhim, bool clk);
+extern void wlapi_bmac_macphyclk_set(wlc_phy_shim_info_t *physhim, bool clk);
+extern void wlapi_bmac_core_phypll_ctl(wlc_phy_shim_info_t *physhim, bool on);
+extern void wlapi_bmac_core_phypll_reset(wlc_phy_shim_info_t *physhim);
+extern void wlapi_bmac_ucode_wake_override_phyreg_set(wlc_phy_shim_info_t *
+						      physhim);
+extern void wlapi_bmac_ucode_wake_override_phyreg_clear(wlc_phy_shim_info_t *
+							physhim);
+extern void wlapi_bmac_write_template_ram(wlc_phy_shim_info_t *physhim, int o,
+					  int len, void *buf);
+extern u16 wlapi_bmac_rate_shm_offset(wlc_phy_shim_info_t *physhim,
+					 u8 rate);
+extern void wlapi_ucode_sample_init(wlc_phy_shim_info_t *physhim);
+extern void wlapi_copyfrom_objmem(wlc_phy_shim_info_t *physhim, uint,
+				  void *buf, int, u32 sel);
+extern void wlapi_copyto_objmem(wlc_phy_shim_info_t *physhim, uint,
+				const void *buf, int, u32);
+
+extern void wlapi_high_update_phy_mode(wlc_phy_shim_info_t *physhim,
+				       u32 phy_mode);
+extern u16 wlapi_bmac_get_txant(wlc_phy_shim_info_t *physhim);
+#endif				/* _wlc_phy_shim_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_pub.h b/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
new file mode 100644
index 0000000..b956c23
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_pub.h
@@ -0,0 +1,610 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_pub_h_
+#define _wlc_pub_h_
+
+#define	WLC_NUMRATES	16	/* max # of rates in a rateset */
+#define	MAXMULTILIST	32	/* max # multicast addresses */
+#define	D11_PHY_HDR_LEN	6	/* Phy header length - 6 bytes */
+
+/* phy types */
+#define	PHY_TYPE_A	0	/* Phy type A */
+#define	PHY_TYPE_G	2	/* Phy type G */
+#define	PHY_TYPE_N	4	/* Phy type N */
+#define	PHY_TYPE_LP	5	/* Phy type Low Power A/B/G */
+#define	PHY_TYPE_SSN	6	/* Phy type Single Stream N */
+#define	PHY_TYPE_LCN	8	/* Phy type Single Stream N */
+#define	PHY_TYPE_LCNXN	9	/* Phy type 2-stream N */
+#define	PHY_TYPE_HT	7	/* Phy type 3-Stream N */
+
+/* bw */
+#define WLC_10_MHZ	10	/* 10Mhz nphy channel bandwidth */
+#define WLC_20_MHZ	20	/* 20Mhz nphy channel bandwidth */
+#define WLC_40_MHZ	40	/* 40Mhz nphy channel bandwidth */
+
+#define CHSPEC_WLC_BW(chanspec)	(CHSPEC_IS40(chanspec) ? WLC_40_MHZ : \
+				 CHSPEC_IS20(chanspec) ? WLC_20_MHZ : \
+							 WLC_10_MHZ)
+
+#define	WLC_RSSI_MINVAL		-200	/* Low value, e.g. for forcing roam */
+#define	WLC_RSSI_NO_SIGNAL	-91	/* NDIS RSSI link quality cutoffs */
+#define	WLC_RSSI_VERY_LOW	-80	/* Very low quality cutoffs */
+#define	WLC_RSSI_LOW		-70	/* Low quality cutoffs */
+#define	WLC_RSSI_GOOD		-68	/* Good quality cutoffs */
+#define	WLC_RSSI_VERY_GOOD	-58	/* Very good quality cutoffs */
+#define	WLC_RSSI_EXCELLENT	-57	/* Excellent quality cutoffs */
+
+#define WLC_PHYTYPE(_x) (_x)	/* macro to perform WLC PHY -> D11 PHY TYPE, currently 1:1 */
+
+#define MA_WINDOW_SZ		8	/* moving average window size */
+
+#define WLC_SNR_INVALID		0	/* invalid SNR value */
+
+/* a large TX Power as an init value to factor out of min() calculations,
+ * keep low enough to fit in an s8, units are .25 dBm
+ */
+#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
+
+/* legacy rx Antenna diversity for SISO rates */
+#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
+#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
+#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
+#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
+#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
+#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
+
+/* legacy rx Antenna diversity for SISO rates */
+#define ANT_TX_FORCE_0		0	/* Tx on antenna 0, "legacy term Main" */
+#define ANT_TX_FORCE_1		1	/* Tx on antenna 1, "legacy term Aux" */
+#define ANT_TX_LAST_RX		3	/* Tx on phy's last good Rx antenna */
+#define ANT_TX_DEF			3	/* driver's default tx antenna setting */
+
+#define TXCORE_POLICY_ALL	0x1	/* use all available core for transmit */
+
+/* Tx Chain values */
+#define TXCHAIN_DEF		0x1	/* def bitmap of txchain */
+#define TXCHAIN_DEF_NPHY	0x3	/* default bitmap of tx chains for nphy */
+#define TXCHAIN_DEF_HTPHY	0x7	/* default bitmap of tx chains for nphy */
+#define RXCHAIN_DEF		0x1	/* def bitmap of rxchain */
+#define RXCHAIN_DEF_NPHY	0x3	/* default bitmap of rx chains for nphy */
+#define RXCHAIN_DEF_HTPHY	0x7	/* default bitmap of rx chains for nphy */
+#define ANTSWITCH_NONE		0	/* no antenna switch */
+#define ANTSWITCH_TYPE_1	1	/* antenna switch on 4321CB2, 2of3 */
+#define ANTSWITCH_TYPE_2	2	/* antenna switch on 4321MPCI, 2of3 */
+#define ANTSWITCH_TYPE_3	3	/* antenna switch on 4322, 2of3 */
+
+#define RXBUFSZ		PKTBUFSZ
+#ifndef AIDMAPSZ
+#define AIDMAPSZ	(roundup(MAXSCB, NBBY)/NBBY)	/* aid bitmap size in bytes */
+#endif				/* AIDMAPSZ */
+
+typedef struct wlc_tunables {
+	int ntxd;		/* size of tx descriptor table */
+	int nrxd;		/* size of rx descriptor table */
+	int rxbufsz;		/* size of rx buffers to post */
+	int nrxbufpost;		/* # of rx buffers to post */
+	int maxscb;		/* # of SCBs supported */
+	int ampdunummpdu;	/* max number of mpdu in an ampdu */
+	int maxpktcb;		/* max # of packet callbacks */
+	int maxucodebss;	/* max # of BSS handled in ucode bcn/prb */
+	int maxucodebss4;	/* max # of BSS handled in sw bcn/prb */
+	int maxbss;		/* max # of bss info elements in scan list */
+	int datahiwat;		/* data msg txq hiwat mark */
+	int ampdudatahiwat;	/* AMPDU msg txq hiwat mark */
+	int rxbnd;		/* max # of rx bufs to process before deferring to dpc */
+	int txsbnd;		/* max # tx status to process in wlc_txstatus() */
+	int memreserved;	/* memory reserved for BMAC's USB dma rx */
+} wlc_tunables_t;
+
+typedef struct wlc_rateset {
+	uint count;		/* number of rates in rates[] */
+	u8 rates[WLC_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
+	u8 htphy_membership;	/* HT PHY Membership */
+	u8 mcs[MCSSET_LEN];	/* supported mcs index bit map */
+} wlc_rateset_t;
+
+struct rsn_parms {
+	u8 flags;		/* misc booleans (e.g., supported) */
+	u8 multicast;	/* multicast cipher */
+	u8 ucount;		/* count of unicast ciphers */
+	u8 unicast[4];	/* unicast ciphers */
+	u8 acount;		/* count of auth modes */
+	u8 auth[4];		/* Authentication modes */
+	u8 PAD[4];		/* padding for future growth */
+};
+
+/*
+ * buffer length needed for wlc_format_ssid
+ * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
+ */
+#define SSID_FMT_BUF_LEN	((4 * IEEE80211_MAX_SSID_LEN) + 1)
+
+#define RSN_FLAGS_SUPPORTED		0x1	/* Flag for rsn_params */
+#define RSN_FLAGS_PREAUTH		0x2	/* Flag for WPA2 rsn_params */
+
+/* All the HT-specific default advertised capabilities (including AMPDU)
+ * should be grouped here at one place
+ */
+#define AMPDU_DEF_MPDU_DENSITY	6	/* default mpdu density (110 ==> 4us) */
+
+/* defaults for the HT (MIMO) bss */
+#define HT_CAP	(IEEE80211_HT_CAP_SM_PS |\
+	IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_GRN_FLD |\
+	IEEE80211_HT_CAP_MAX_AMSDU | IEEE80211_HT_CAP_DSSSCCK40)
+
+/* wlc internal bss_info, wl external one is in wlioctl.h */
+typedef struct wlc_bss_info {
+	u8 BSSID[ETH_ALEN];	/* network BSSID */
+	u16 flags;		/* flags for internal attributes */
+	u8 SSID_len;		/* the length of SSID */
+	u8 SSID[32];		/* SSID string */
+	s16 RSSI;		/* receive signal strength (in dBm) */
+	s16 SNR;		/* receive signal SNR in dB */
+	u16 beacon_period;	/* units are Kusec */
+	u16 atim_window;	/* units are Kusec */
+	chanspec_t chanspec;	/* Channel num, bw, ctrl_sb and band */
+	s8 infra;		/* 0=IBSS, 1=infrastructure, 2=unknown */
+	wlc_rateset_t rateset;	/* supported rates */
+	u8 dtim_period;	/* DTIM period */
+	s8 phy_noise;		/* noise right after tx (in dBm) */
+	u16 capability;	/* Capability information */
+	u8 wme_qosinfo;	/* QoS Info from WME IE; valid if WLC_BSS_WME flag set */
+	struct rsn_parms wpa;
+	struct rsn_parms wpa2;
+	u16 qbss_load_aac;	/* qbss load available admission capacity */
+	/* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */
+	u8 qbss_load_chan_free;	/* indicates how free the channel is */
+	u8 mcipher;		/* multicast cipher */
+	u8 wpacfg;		/* wpa config index */
+} wlc_bss_info_t;
+
+/* forward declarations */
+struct wlc_if;
+
+/* wlc_ioctl error codes */
+#define WLC_ENOIOCTL	1	/* No such Ioctl */
+#define WLC_EINVAL	2	/* Invalid value */
+#define WLC_ETOOSMALL	3	/* Value too small */
+#define WLC_ETOOBIG	4	/* Value too big */
+#define WLC_ERANGE	5	/* Out of range */
+#define WLC_EDOWN	6	/* Down */
+#define WLC_EUP		7	/* Up */
+#define WLC_ENOMEM	8	/* No Memory */
+#define WLC_EBUSY	9	/* Busy */
+
+/* IOVar flags for common error checks */
+#define IOVF_MFG	(1<<3)	/* flag for mfgtest iovars */
+#define IOVF_WHL	(1<<4)	/* value must be whole (0-max) */
+#define IOVF_NTRL	(1<<5)	/* value must be natural (1-max) */
+
+#define IOVF_SET_UP	(1<<6)	/* set requires driver be up */
+#define IOVF_SET_DOWN	(1<<7)	/* set requires driver be down */
+#define IOVF_SET_CLK	(1<<8)	/* set requires core clock */
+#define IOVF_SET_BAND	(1<<9)	/* set requires fixed band */
+
+#define IOVF_GET_UP	(1<<10)	/* get requires driver be up */
+#define IOVF_GET_DOWN	(1<<11)	/* get requires driver be down */
+#define IOVF_GET_CLK	(1<<12)	/* get requires core clock */
+#define IOVF_GET_BAND	(1<<13)	/* get requires fixed band */
+#define IOVF_OPEN_ALLOW	(1<<14)	/* set allowed iovar for opensrc */
+
+/* watchdog down and dump callback function proto's */
+typedef int (*watchdog_fn_t) (void *handle);
+typedef int (*down_fn_t) (void *handle);
+typedef int (*dump_fn_t) (void *handle, struct bcmstrbuf *b);
+
+/* IOVar handler
+ *
+ * handle - a pointer value registered with the function
+ * vi - iovar_info that was looked up
+ * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid.
+ * name - the actual iovar name
+ * params/plen - parameters and length for a get, input only.
+ * arg/len - buffer and length for value to be set or retrieved, input or output.
+ * vsize - value size, valid for integer type only.
+ * wlcif - interface context (wlc_if pointer)
+ *
+ * All pointers may point into the same buffer.
+ */
+typedef int (*iovar_fn_t) (void *handle, const bcm_iovar_t *vi,
+			   u32 actionid, const char *name, void *params,
+			   uint plen, void *arg, int alen, int vsize,
+			   struct wlc_if *wlcif);
+
+#define MAC80211_PROMISC_BCNS	(1 << 0)
+#define MAC80211_SCAN		(1 << 1)
+
+/*
+ * Public portion of "common" os-independent state structure.
+ * The wlc handle points at this.
+ */
+struct wlc_pub {
+	void *wlc;
+
+	struct ieee80211_hw *ieee_hw;
+	struct scb *global_scb;
+	scb_ampdu_t *global_ampdu;
+	uint mac80211_state;
+	uint unit;		/* device instance number */
+	uint corerev;		/* core revision */
+	si_t *sih;		/* SB handle (cookie for siutils calls) */
+	char *vars;		/* "environment" name=value */
+	bool up;		/* interface up and running */
+	bool hw_off;		/* HW is off */
+	wlc_tunables_t *tunables;	/* tunables: ntxd, nrxd, maxscb, etc. */
+	bool hw_up;		/* one time hw up/down(from boot or hibernation) */
+	bool _piomode;		/* true if pio mode *//* BMAC_NOTE: NEED In both */
+	uint _nbands;		/* # bands supported */
+	uint now;		/* # elapsed seconds */
+
+	bool promisc;		/* promiscuous destination address */
+	bool delayed_down;	/* down delayed */
+	bool _ap;		/* AP mode enabled */
+	bool _apsta;		/* simultaneous AP/STA mode enabled */
+	bool _assoc_recreate;	/* association recreation on up transitions */
+	int _wme;		/* WME QoS mode */
+	u8 _mbss;		/* MBSS mode on */
+	bool allmulti;		/* enable all multicasts */
+	bool associated;	/* true:part of [I]BSS, false: not */
+	/* (union of stas_associated, aps_associated) */
+	bool phytest_on;	/* whether a PHY test is running */
+	bool bf_preempt_4306;	/* True to enable 'darwin' mode */
+	bool _ampdu;		/* ampdu enabled or not */
+	bool _cac;		/* 802.11e CAC enabled */
+	u8 _n_enab;		/* bitmap of 11N + HT support */
+	bool _n_reqd;		/* N support required for clients */
+
+	s8 _coex;		/* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */
+	bool _priofc;		/* Priority-based flowcontrol */
+
+	u8 cur_etheraddr[ETH_ALEN];	/* our local ethernet address */
+
+	u8 *multicast;	/* ptr to list of multicast addresses */
+	uint nmulticast;	/* # enabled multicast addresses */
+
+	u32 wlfeatureflag;	/* Flags to control sw features from registry */
+	int psq_pkts_total;	/* total num of ps pkts */
+
+	u16 txmaxpkts;	/* max number of large pkts allowed to be pending */
+
+	/* s/w decryption counters */
+	u32 swdecrypt;	/* s/w decrypt attempts */
+
+	int bcmerror;		/* last bcm error */
+
+	mbool radio_disabled;	/* bit vector for radio disabled reasons */
+	bool radio_active;	/* radio on/off state */
+	u16 roam_time_thresh;	/* Max. # secs. of not hearing beacons
+					 * before roaming.
+					 */
+	bool align_wd_tbtt;	/* Align watchdog with tbtt indication
+				 * handling. This flag is cleared by default
+				 * and is set by per port code explicitly and
+				 * you need to make sure the OSL_SYSUPTIME()
+				 * is implemented properly in osl of that port
+				 * when it enables this Power Save feature.
+				 */
+
+	u16 boardrev;	/* version # of particular board */
+	u8 sromrev;		/* version # of the srom */
+	char srom_ccode[WLC_CNTRY_BUF_SZ];	/* Country Code in SROM */
+	u32 boardflags;	/* Board specific flags from srom */
+	u32 boardflags2;	/* More board flags if sromrev >= 4 */
+	bool tempsense_disable;	/* disable periodic tempsense check */
+
+	bool _lmac;		/* lmac module included and enabled */
+	bool _lmacproto;	/* lmac protocol module included and enabled */
+	bool phy_11ncapable;	/* the PHY/HW is capable of 802.11N */
+	bool _ampdumac;		/* mac assist ampdu enabled or not */
+
+	struct wl_cnt *_cnt;	/* low-level counters in driver */
+};
+
+/* wl_monitor rx status per packet */
+typedef struct wl_rxsts {
+	uint pkterror;		/* error flags per pkt */
+	uint phytype;		/* 802.11 A/B/G ... */
+	uint channel;		/* channel */
+	uint datarate;		/* rate in 500kbps */
+	uint antenna;		/* antenna pkts received on */
+	uint pktlength;		/* pkt length minus bcm phy hdr */
+	u32 mactime;		/* time stamp from mac, count per 1us */
+	uint sq;		/* signal quality */
+	s32 signal;		/* in dbm */
+	s32 noise;		/* in dbm */
+	uint preamble;		/* Unknown, short, long */
+	uint encoding;		/* Unknown, CCK, PBCC, OFDM */
+	uint nfrmtype;		/* special 802.11n frames(AMPDU, AMSDU) */
+	struct wl_if *wlif;	/* wl interface */
+} wl_rxsts_t;
+
+/* status per error RX pkt */
+#define WL_RXS_CRC_ERROR		0x00000001	/* CRC Error in packet */
+#define WL_RXS_RUNT_ERROR		0x00000002	/* Runt packet */
+#define WL_RXS_ALIGN_ERROR		0x00000004	/* Misaligned packet */
+#define WL_RXS_OVERSIZE_ERROR		0x00000008	/* packet bigger than RX_LENGTH (usually 1518) */
+#define WL_RXS_WEP_ICV_ERROR		0x00000010	/* Integrity Check Value error */
+#define WL_RXS_WEP_ENCRYPTED		0x00000020	/* Encrypted with WEP */
+#define WL_RXS_PLCP_SHORT		0x00000040	/* Short PLCP error */
+#define WL_RXS_DECRYPT_ERR		0x00000080	/* Decryption error */
+#define WL_RXS_OTHER_ERR		0x80000000	/* Other errors */
+
+/* phy type */
+#define WL_RXS_PHY_A			0x00000000	/* A phy type */
+#define WL_RXS_PHY_B			0x00000001	/* B phy type */
+#define WL_RXS_PHY_G			0x00000002	/* G phy type */
+#define WL_RXS_PHY_N			0x00000004	/* N phy type */
+
+/* encoding */
+#define WL_RXS_ENCODING_CCK		0x00000000	/* CCK encoding */
+#define WL_RXS_ENCODING_OFDM		0x00000001	/* OFDM encoding */
+
+/* preamble */
+#define WL_RXS_UNUSED_STUB		0x0	/* stub to match with wlc_ethereal.h */
+#define WL_RXS_PREAMBLE_SHORT		0x00000001	/* Short preamble */
+#define WL_RXS_PREAMBLE_LONG		0x00000002	/* Long preamble */
+#define WL_RXS_PREAMBLE_MIMO_MM		0x00000003	/* MIMO mixed mode preamble */
+#define WL_RXS_PREAMBLE_MIMO_GF		0x00000004	/* MIMO green field preamble */
+
+#define WL_RXS_NFRM_AMPDU_FIRST		0x00000001	/* first MPDU in A-MPDU */
+#define WL_RXS_NFRM_AMPDU_SUB		0x00000002	/* subsequent MPDU(s) in A-MPDU */
+#define WL_RXS_NFRM_AMSDU_FIRST		0x00000004	/* first MSDU in A-MSDU */
+#define WL_RXS_NFRM_AMSDU_SUB		0x00000008	/* subsequent MSDU(s) in A-MSDU */
+
+/* forward declare and use the struct notation so we don't have to
+ * have it defined if not necessary.
+ */
+struct wlc_info;
+struct wlc_hw_info;
+struct wlc_bsscfg;
+struct wlc_if;
+
+/***********************************************
+ * Feature-related macros to optimize out code *
+ * *********************************************
+ */
+
+/* AP Support (versus STA) */
+#define	AP_ENAB(pub)	(0)
+
+/* Macro to check if APSTA mode enabled */
+#define APSTA_ENAB(pub)	(0)
+
+/* Some useful combinations */
+#define STA_ONLY(pub)	(!AP_ENAB(pub))
+#define AP_ONLY(pub)	(AP_ENAB(pub) && !APSTA_ENAB(pub))
+
+#define ENAB_1x1	0x01
+#define ENAB_2x2	0x02
+#define ENAB_3x3	0x04
+#define ENAB_4x4	0x08
+#define SUPPORT_11N	(ENAB_1x1|ENAB_2x2)
+#define SUPPORT_HT	(ENAB_1x1|ENAB_2x2|ENAB_3x3)
+/* WL11N Support */
+#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \
+	(defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0)))
+#define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N)
+#define N_REQD(pub) ((pub)->_n_reqd)
+#else
+#define N_ENAB(pub)	0
+#define N_REQD(pub)	0
+#endif
+
+#if (defined(HTCONF) && (HTCONF != 0))
+#define HT_ENAB(pub) (((pub)->_n_enab & SUPPORT_HT) == SUPPORT_HT)
+#else
+#define HT_ENAB(pub) 0
+#endif
+
+#define AMPDU_AGG_HOST	1
+#define AMPDU_ENAB(pub) ((pub)->_ampdu)
+
+#define EDCF_ENAB(pub) (WME_ENAB(pub))
+#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
+
+#define MONITOR_ENAB(wlc)	((wlc)->monitor)
+
+#define PROMISC_ENAB(wlc)	((wlc)->promisc)
+
+#define	WLC_PREC_COUNT		16	/* Max precedence level implemented */
+
+/* pri is priority encoded in the packet. This maps the Packet priority to
+ * enqueue precedence as defined in wlc_prec_map
+ */
+extern const u8 wlc_prio2prec_map[];
+#define WLC_PRIO_TO_PREC(pri)	wlc_prio2prec_map[(pri) & 7]
+
+/* This maps priority to one precedence higher - Used by PS-Poll response packets to
+ * simulate enqueue-at-head operation, but still maintain the order on the queue
+ */
+#define WLC_PRIO_TO_HI_PREC(pri)	min(WLC_PRIO_TO_PREC(pri) + 1, WLC_PREC_COUNT - 1)
+
+extern const u8 wme_fifo2ac[];
+#define WME_PRIO2AC(prio)	wme_fifo2ac[prio2fifo[(prio)]]
+
+/* Mask to describe all precedence levels */
+#define WLC_PREC_BMP_ALL		MAXBITVAL(WLC_PREC_COUNT)
+
+/* Define a bitmap of precedences comprised by each AC */
+#define WLC_PREC_BMP_AC_BE	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BE)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BE)) |	\
+				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_EE)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
+#define WLC_PREC_BMP_AC_BK	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BK)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BK)) |	\
+				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NONE)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
+#define WLC_PREC_BMP_AC_VI	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_CL)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_CL)) |	\
+				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VI)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
+#define WLC_PREC_BMP_AC_VO	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VO)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VO)) |	\
+				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NC)) |	\
+				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
+
+/* WME Support */
+#define WME_ENAB(pub) ((pub)->_wme != OFF)
+#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
+
+#define WLC_USE_COREFLAGS	0xffffffff	/* invalid core flags, use the saved coreflags */
+
+
+/* network protection config */
+#define	WLC_PROT_G_SPEC		1	/* SPEC g protection */
+#define	WLC_PROT_G_OVR		2	/* SPEC g prot override */
+#define	WLC_PROT_G_USER		3	/* gmode specified by user */
+#define	WLC_PROT_OVERLAP	4	/* overlap */
+#define	WLC_PROT_N_USER		10	/* nmode specified by user */
+#define	WLC_PROT_N_CFG		11	/* n protection */
+#define	WLC_PROT_N_CFG_OVR	12	/* n protection override */
+#define	WLC_PROT_N_NONGF	13	/* non-GF protection */
+#define	WLC_PROT_N_NONGF_OVR	14	/* non-GF protection override */
+#define	WLC_PROT_N_PAM_OVR	15	/* n preamble override */
+#define	WLC_PROT_N_OBSS		16	/* non-HT OBSS present */
+
+/* common functions for every port */
+extern void *wlc_attach(void *wl, u16 vendor, u16 device, uint unit,
+			bool piomode, void *regsva, uint bustype, void *btparam,
+			uint *perr);
+extern uint wlc_detach(struct wlc_info *wlc);
+extern int wlc_up(struct wlc_info *wlc);
+extern uint wlc_down(struct wlc_info *wlc);
+
+extern int wlc_set(struct wlc_info *wlc, int cmd, int arg);
+extern int wlc_get(struct wlc_info *wlc, int cmd, int *arg);
+extern int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg);
+extern int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg);
+extern bool wlc_chipmatch(u16 vendor, u16 device);
+extern void wlc_init(struct wlc_info *wlc);
+extern void wlc_reset(struct wlc_info *wlc);
+
+extern void wlc_intrson(struct wlc_info *wlc);
+extern u32 wlc_intrsoff(struct wlc_info *wlc);
+extern void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask);
+extern bool wlc_intrsupd(struct wlc_info *wlc);
+extern bool wlc_isr(struct wlc_info *wlc, bool *wantdpc);
+extern bool wlc_dpc(struct wlc_info *wlc, bool bounded);
+extern bool wlc_send80211_raw(struct wlc_info *wlc, struct wlc_if *wlcif,
+			      void *p, uint ac);
+extern bool wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu,
+				 struct ieee80211_hw *hw);
+extern int wlc_iovar_op(struct wlc_info *wlc, const char *name, void *params,
+			int p_len, void *arg, int len, bool set,
+			struct wlc_if *wlcif);
+extern int wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
+		     struct wlc_if *wlcif);
+/* helper functions */
+extern void wlc_statsupd(struct wlc_info *wlc);
+extern void wlc_protection_upd(struct wlc_info *wlc, uint idx, int val);
+extern int wlc_get_header_len(void);
+extern void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc);
+extern void wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
+			      const u8 *addr);
+extern void wlc_wme_setparams(struct wlc_info *wlc, u16 aci, void *arg,
+			      bool suspend);
+
+extern struct wlc_pub *wlc_pub(void *wlc);
+
+/* common functions for every port */
+extern int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw);
+extern int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw);
+extern int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw);
+extern int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw);
+
+extern u32 wlc_reg_read(struct wlc_info *wlc, void *r, uint size);
+extern void wlc_reg_write(struct wlc_info *wlc, void *r, u32 v, uint size);
+extern void wlc_corereset(struct wlc_info *wlc, u32 flags);
+extern void wlc_mhf(struct wlc_info *wlc, u8 idx, u16 mask, u16 val,
+		    int bands);
+extern u16 wlc_mhf_get(struct wlc_info *wlc, u8 idx, int bands);
+extern u32 wlc_delta_txfunfl(struct wlc_info *wlc, int fifo);
+extern void wlc_rate_lookup_init(struct wlc_info *wlc, wlc_rateset_t *rateset);
+extern void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs);
+
+struct ieee80211_sta;
+extern void wlc_ampdu_flush(struct wlc_info *wlc, struct ieee80211_sta *sta,
+			    u16 tid);
+
+/* wlc_phy.c helper functions */
+extern void wlc_set_ps_ctrl(struct wlc_info *wlc);
+extern void wlc_mctrl(struct wlc_info *wlc, u32 mask, u32 val);
+extern void wlc_scb_ratesel_init_all(struct wlc_info *wlc);
+
+/* ioctl */
+extern int wlc_iovar_gets8(struct wlc_info *wlc, const char *name,
+			     s8 *arg);
+extern int wlc_iovar_check(struct wlc_pub *pub, const bcm_iovar_t *vi,
+			   void *arg,
+			   int len, bool set);
+
+extern int wlc_module_register(struct wlc_pub *pub, const bcm_iovar_t *iovars,
+			       const char *name, void *hdl, iovar_fn_t iovar_fn,
+			       watchdog_fn_t watchdog_fn, down_fn_t down_fn);
+extern int wlc_module_unregister(struct wlc_pub *pub, const char *name,
+				 void *hdl);
+extern void wlc_suspend_mac_and_wait(struct wlc_info *wlc);
+extern void wlc_enable_mac(struct wlc_info *wlc);
+extern void wlc_associate_upd(struct wlc_info *wlc, bool state);
+extern void wlc_scan_start(struct wlc_info *wlc);
+extern void wlc_scan_stop(struct wlc_info *wlc);
+
+static inline int wlc_iovar_getuint(struct wlc_info *wlc, const char *name,
+				    uint *arg)
+{
+	return wlc_iovar_getint(wlc, name, (int *)arg);
+}
+
+static inline int wlc_iovar_getu8(struct wlc_info *wlc, const char *name,
+				     u8 *arg)
+{
+	return wlc_iovar_gets8(wlc, name, (s8 *) arg);
+}
+
+static inline int wlc_iovar_setuint(struct wlc_info *wlc, const char *name,
+				    uint arg)
+{
+	return wlc_iovar_setint(wlc, name, (int)arg);
+}
+
+#if defined(BCMDBG)
+extern int wlc_iocregchk(struct wlc_info *wlc, uint band);
+#endif
+#if defined(BCMDBG)
+extern int wlc_iocpichk(struct wlc_info *wlc, uint phytype);
+#endif
+
+/* helper functions */
+extern bool wlc_check_radio_disabled(struct wlc_info *wlc);
+extern bool wlc_radio_monitor_stop(struct wlc_info *wlc);
+
+#if defined(BCMDBG)
+extern int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len);
+#endif
+
+#define	MAXBANDS		2	/* Maximum #of bands */
+/* bandstate array indices */
+#define BAND_2G_INDEX		0	/* wlc->bandstate[x] index */
+#define BAND_5G_INDEX		1	/* wlc->bandstate[x] index */
+
+#define BAND_2G_NAME		"2.4G"
+#define BAND_5G_NAME		"5G"
+
+/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */
+#define WLC_RPCTX_PARAMS		32
+
+#endif				/* _wlc_pub_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_rate.c b/drivers/staging/brcm80211/brcmsmac/wlc_rate.c
new file mode 100644
index 0000000..0cfa360
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_rate.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <proto/802.11.h>
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <wlioctl.h>
+#include <sbhnddma.h>
+
+#include "wlc_types.h"
+#include "d11.h"
+#include "wl_dbg.h"
+#include "wlc_cfg.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_rate.h"
+
+/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
+const u8 rate_info[WLC_MAXRATE + 1] = {
+	/*  0     1     2     3     4     5     6     7     8     9 */
+/*   0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
+/*  20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
+/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
+/*  50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*  90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
+/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
+};
+
+/* rates are in units of Kbps */
+const mcs_info_t mcs_table[MCS_TABLE_SIZE] = {
+	/* MCS  0: SS 1, MOD: BPSK,  CR 1/2 */
+	{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
+	 WLC_RATE_6M},
+	/* MCS  1: SS 1, MOD: QPSK,  CR 1/2 */
+	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
+	 WLC_RATE_12M},
+	/* MCS  2: SS 1, MOD: QPSK,  CR 3/4 */
+	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
+	 WLC_RATE_18M},
+	/* MCS  3: SS 1, MOD: 16QAM, CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
+	 WLC_RATE_24M},
+	/* MCS  4: SS 1, MOD: 16QAM, CR 3/4 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
+	 WLC_RATE_36M},
+	/* MCS  5: SS 1, MOD: 64QAM, CR 2/3 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
+	 WLC_RATE_48M},
+	/* MCS  6: SS 1, MOD: 64QAM, CR 3/4 */
+	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
+	 WLC_RATE_54M},
+	/* MCS  7: SS 1, MOD: 64QAM, CR 5/6 */
+	{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
+	 WLC_RATE_54M},
+	/* MCS  8: SS 2, MOD: BPSK,  CR 1/2 */
+	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
+	 WLC_RATE_6M},
+	/* MCS  9: SS 2, MOD: QPSK,  CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
+	 WLC_RATE_12M},
+	/* MCS 10: SS 2, MOD: QPSK,  CR 3/4 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
+	 WLC_RATE_18M},
+	/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
+	 WLC_RATE_24M},
+	/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
+	 WLC_RATE_36M},
+	/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
+	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
+	 WLC_RATE_48M},
+	/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
+	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
+	 WLC_RATE_54M},
+	/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
+	{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
+	 WLC_RATE_54M},
+	/* MCS 16: SS 3, MOD: BPSK,  CR 1/2 */
+	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
+	 WLC_RATE_6M},
+	/* MCS 17: SS 3, MOD: QPSK,  CR 1/2 */
+	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
+	 WLC_RATE_12M},
+	/* MCS 18: SS 3, MOD: QPSK,  CR 3/4 */
+	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
+	 WLC_RATE_18M},
+	/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
+	 WLC_RATE_24M},
+	/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
+	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
+	 WLC_RATE_36M},
+	/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
+	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
+	 WLC_RATE_48M},
+	/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
+	{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
+	 WLC_RATE_54M},
+	/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
+	{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
+	 WLC_RATE_54M},
+	/* MCS 24: SS 4, MOD: BPSK,  CR 1/2 */
+	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
+	 WLC_RATE_6M},
+	/* MCS 25: SS 4, MOD: QPSK,  CR 1/2 */
+	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
+	 WLC_RATE_12M},
+	/* MCS 26: SS 4, MOD: QPSK,  CR 3/4 */
+	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
+	 WLC_RATE_18M},
+	/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
+	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
+	 WLC_RATE_24M},
+	/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
+	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
+	 WLC_RATE_36M},
+	/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
+	{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
+	 WLC_RATE_48M},
+	/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
+	{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
+	 WLC_RATE_54M},
+	/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
+	{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
+	 WLC_RATE_54M},
+	/* MCS 32: SS 1, MOD: BPSK,  CR 1/2 */
+	{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, WLC_RATE_6M},
+};
+
+/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
+ *   Number of spatial streams: always 1
+ *   other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
+ */
+typedef struct legacy_phycfg {
+	u32 rate_ofdm;	/* ofdm mac rate */
+	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
+} legacy_phycfg_t;
+
+#define LEGACY_PHYCFG_TABLE_SIZE	12	/* Number of legacy_rate_cfg entries in the table */
+
+/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
+/* Eventually MIMOPHY would also be converted to this format */
+/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
+static const legacy_phycfg_t legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
+	{WLC_RATE_1M, 0x00},	/* CCK  1Mbps,  data rate  0 */
+	{WLC_RATE_2M, 0x08},	/* CCK  2Mbps,  data rate  1 */
+	{WLC_RATE_5M5, 0x10},	/* CCK  5.5Mbps,  data rate  2 */
+	{WLC_RATE_11M, 0x18},	/* CCK  11Mbps,  data rate   3 */
+	{WLC_RATE_6M, 0x00},	/* OFDM  6Mbps,  code rate 1/2, BPSK,   1 spatial stream */
+	{WLC_RATE_9M, 0x02},	/* OFDM  9Mbps,  code rate 3/4, BPSK,   1 spatial stream */
+	{WLC_RATE_12M, 0x08},	/* OFDM  12Mbps, code rate 1/2, QPSK,   1 spatial stream */
+	{WLC_RATE_18M, 0x0A},	/* OFDM  18Mbps, code rate 3/4, QPSK,   1 spatial stream */
+	{WLC_RATE_24M, 0x10},	/* OFDM  24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
+	{WLC_RATE_36M, 0x12},	/* OFDM  36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
+	{WLC_RATE_48M, 0x19},	/* OFDM  48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
+	{WLC_RATE_54M, 0x1A},	/* OFDM  54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
+};
+
+/* Hardware rates (also encodes default basic rates) */
+
+const wlc_rateset_t cck_ofdm_mimo_rates = {
+	12,
+	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
+	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t ofdm_mimo_rates = {
+	8,
+	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+/* Default ratesets that include MCS32 for 40BW channels */
+const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
+	12,
+	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
+	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t ofdm_40bw_mimo_rates = {
+	8,
+	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t cck_ofdm_rates = {
+	12,
+	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
+	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
+	 0x6c},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t gphy_legacy_rates = {
+	4,
+	{			/*    1b,   2b,   5.5b,  11b Mbps */
+	 0x82, 0x84, 0x8b, 0x96},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t ofdm_rates = {
+	8,
+	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
+	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+const wlc_rateset_t cck_rates = {
+	4,
+	{			/*    1b,   2b,   5.5,  11 Mbps */
+	 0x82, 0x84, 0x0b, 0x16},
+	0x00,
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00}
+};
+
+static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate);
+
+/* check if rateset is valid.
+ * if check_brate is true, rateset without a basic rate is considered NOT valid.
+ */
+static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate)
+{
+	uint idx;
+
+	if (!rs->count)
+		return false;
+
+	if (!check_brate)
+		return true;
+
+	/* error if no basic rates */
+	for (idx = 0; idx < rs->count; idx++) {
+		if (rs->rates[idx] & WLC_RATE_FLAG)
+			return true;
+	}
+	return false;
+}
+
+void wlc_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
+{
+	int i;
+	for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
+		rs->mcs[i] = 0;
+}
+
+/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
+ * and check if resulting rateset is valid.
+*/
+bool
+wlc_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
+				   const wlc_rateset_t *hw_rs,
+				   bool check_brate, u8 txstreams)
+{
+	u8 rateset[WLC_MAXRATE + 1];
+	u8 r;
+	uint count;
+	uint i;
+
+	memset(rateset, 0, sizeof(rateset));
+	count = rs->count;
+
+	for (i = 0; i < count; i++) {
+		/* mask off "basic rate" bit, WLC_RATE_FLAG */
+		r = (int)rs->rates[i] & RATE_MASK;
+		if ((r > WLC_MAXRATE) || (rate_info[r] == 0)) {
+			continue;
+		}
+		rateset[r] = rs->rates[i];	/* preserve basic bit! */
+	}
+
+	/* fill out the rates in order, looking at only supported rates */
+	count = 0;
+	for (i = 0; i < hw_rs->count; i++) {
+		r = hw_rs->rates[i] & RATE_MASK;
+		ASSERT(r <= WLC_MAXRATE);
+		if (rateset[r])
+			rs->rates[count++] = rateset[r];
+	}
+
+	rs->count = count;
+
+	/* only set the mcs rate bit if the equivalent hw mcs bit is set */
+	for (i = 0; i < MCSSET_LEN; i++)
+		rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
+
+	if (wlc_rateset_valid(rs, check_brate))
+		return true;
+	else
+		return false;
+}
+
+/* caluclate the rate of a rx'd frame and return it as a ratespec */
+ratespec_t BCMFASTPATH wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp)
+{
+	int phy_type;
+	ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
+
+	phy_type =
+	    ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
+
+	if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
+	    (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
+		switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
+		case PRXS0_CCK:
+			rspec =
+			    CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
+			break;
+		case PRXS0_OFDM:
+			rspec =
+			    OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->
+					      rlpt[0]);
+			break;
+		case PRXS0_PREN:
+			rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
+			if (plcp[0] & MIMO_PLCP_40MHZ) {
+				/* indicate rspec is for 40 MHz mode */
+				rspec &= ~RSPEC_BW_MASK;
+				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
+			}
+			break;
+		case PRXS0_STDN:
+			/* fallthru */
+		default:
+			/* not supported */
+			ASSERT(0);
+			break;
+		}
+		if (PLCP3_ISSGI(plcp[3]))
+			rspec |= RSPEC_SHORT_GI;
+	} else
+	    if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
+		rspec = OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->rlpt[0]);
+	else
+		rspec = CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
+
+	return rspec;
+}
+
+/* copy rateset src to dst as-is (no masking or sorting) */
+void wlc_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
+{
+	memcpy(dst, src, sizeof(wlc_rateset_t));
+}
+
+/*
+ * Copy and selectively filter one rateset to another.
+ * 'basic_only' means only copy basic rates.
+ * 'rates' indicates cck (11b) and ofdm rates combinations.
+ *    - 0: cck and ofdm
+ *    - 1: cck only
+ *    - 2: ofdm only
+ * 'xmask' is the copy mask (typically 0x7f or 0xff).
+ */
+void
+wlc_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
+		   u8 rates, uint xmask, bool mcsallow)
+{
+	uint i;
+	uint r;
+	uint count;
+
+	count = 0;
+	for (i = 0; i < src->count; i++) {
+		r = src->rates[i];
+		if (basic_only && !(r & WLC_RATE_FLAG))
+			continue;
+		if ((rates == WLC_RATES_CCK) && IS_OFDM((r & RATE_MASK)))
+			continue;
+		if ((rates == WLC_RATES_OFDM) && IS_CCK((r & RATE_MASK)))
+			continue;
+		dst->rates[count++] = r & xmask;
+	}
+	dst->count = count;
+	dst->htphy_membership = src->htphy_membership;
+
+	if (mcsallow && rates != WLC_RATES_CCK)
+		memcpy(&dst->mcs[0], &src->mcs[0], MCSSET_LEN);
+	else
+		wlc_rateset_mcs_clear(dst);
+}
+
+/* select rateset for a given phy_type and bandtype and filter it, sort it
+ * and fill rs_tgt with result
+ */
+void
+wlc_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
+		    uint phy_type, int bandtype, bool cck_only, uint rate_mask,
+		    bool mcsallow, u8 bw, u8 txstreams)
+{
+	const wlc_rateset_t *rs_dflt;
+	wlc_rateset_t rs_sel;
+	if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
+	    (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
+		if (BAND_5G(bandtype)) {
+			rs_dflt = (bw == WLC_20_MHZ ?
+				   &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
+		} else {
+			rs_dflt = (bw == WLC_20_MHZ ?
+				   &cck_ofdm_mimo_rates :
+				   &cck_ofdm_40bw_mimo_rates);
+		}
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
+		rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
+		rs_dflt = &ofdm_rates;
+	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
+		rs_dflt = &cck_ofdm_rates;
+	} else {
+		ASSERT(0);	/* should not happen */
+		rs_dflt = &cck_rates;	/* force cck */
+	}
+
+	/* if hw rateset is not supplied, assign selected rateset to it */
+	if (!rs_hw)
+		rs_hw = rs_dflt;
+
+	wlc_rateset_copy(rs_dflt, &rs_sel);
+	wlc_rateset_mcs_upd(&rs_sel, txstreams);
+	wlc_rateset_filter(&rs_sel, rs_tgt, false,
+			   cck_only ? WLC_RATES_CCK : WLC_RATES_CCK_OFDM,
+			   rate_mask, mcsallow);
+	wlc_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
+					   mcsallow ? txstreams : 1);
+}
+
+s16 BCMFASTPATH wlc_rate_legacy_phyctl(uint rate)
+{
+	uint i;
+	for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
+		if (rate == legacy_phycfg_table[i].rate_ofdm)
+			return legacy_phycfg_table[i].tx_phy_ctl3;
+
+	return -1;
+}
+
+void wlc_rateset_mcs_clear(wlc_rateset_t *rateset)
+{
+	uint i;
+	for (i = 0; i < MCSSET_LEN; i++)
+		rateset->mcs[i] = 0;
+}
+
+void wlc_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
+{
+	memcpy(&rateset->mcs[0], &cck_ofdm_mimo_rates.mcs[0], MCSSET_LEN);
+	wlc_rateset_mcs_upd(rateset, txstreams);
+}
+
+/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
+void wlc_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
+{
+	if (bw == WLC_40_MHZ)
+		setbit(rateset->mcs, 32);
+	else
+		clrbit(rateset->mcs, 32);
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_rate.h b/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
new file mode 100644
index 0000000..25ba2a4
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_rate.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLC_RATE_H_
+#define _WLC_RATE_H_
+
+extern const u8 rate_info[];
+extern const struct wlc_rateset cck_ofdm_mimo_rates;
+extern const struct wlc_rateset ofdm_mimo_rates;
+extern const struct wlc_rateset cck_ofdm_rates;
+extern const struct wlc_rateset ofdm_rates;
+extern const struct wlc_rateset cck_rates;
+extern const struct wlc_rateset gphy_legacy_rates;
+extern const struct wlc_rateset wlc_lrs_rates;
+extern const struct wlc_rateset rate_limit_1_2;
+
+typedef struct mcs_info {
+	u32 phy_rate_20;	/* phy rate in kbps [20Mhz] */
+	u32 phy_rate_40;	/* phy rate in kbps [40Mhz] */
+	u32 phy_rate_20_sgi;	/* phy rate in kbps [20Mhz] with SGI */
+	u32 phy_rate_40_sgi;	/* phy rate in kbps [40Mhz] with SGI */
+	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
+	u8 leg_ofdm;		/* matching legacy ofdm rate in 500bkps */
+} mcs_info_t;
+
+#define WLC_MAXMCS	32	/* max valid mcs index */
+#define MCS_TABLE_SIZE	33	/* Number of mcs entries in the table */
+extern const mcs_info_t mcs_table[];
+
+#define MCS_INVALID	0xFF
+#define MCS_CR_MASK	0x07	/* Code Rate bit mask */
+#define MCS_MOD_MASK	0x38	/* Modulation bit shift */
+#define MCS_MOD_SHIFT	3	/* MOdulation bit shift */
+#define MCS_TXS_MASK	0xc0	/* num tx streams - 1 bit mask */
+#define MCS_TXS_SHIFT	6	/* num tx streams - 1 bit shift */
+#define MCS_CR(_mcs)	(mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK)
+#define MCS_MOD(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT)
+#define MCS_TXS(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT)
+#define MCS_RATE(_mcs, _is40, _sgi)	(_sgi ? \
+	(_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \
+	(_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
+#define VALID_MCS(_mcs)	((_mcs < MCS_TABLE_SIZE))
+
+#define	WLC_RATE_FLAG	0x80	/* Rate flag: basic or ofdm */
+
+/* Macros to use the rate_info table */
+#define	RATE_MASK	0x7f	/* Rate value mask w/o basic rate flag */
+#define	RATE_MASK_FULL	0xff	/* Rate value mask with basic rate flag */
+
+#define WLC_RATE_500K_TO_BPS(rate)	((rate) * 500000)	/* convert 500kbps to bps */
+
+/* rate spec : holds rate and mode specific information required to generate a tx frame. */
+/* Legacy CCK and OFDM information is held in the same manner as was done in the past    */
+/* (in the lower byte) the upper 3 bytes primarily hold MIMO specific information        */
+typedef u32 ratespec_t;
+
+/* rate spec bit fields */
+#define RSPEC_RATE_MASK		0x0000007F	/* Either 500Kbps units or MIMO MCS idx */
+#define RSPEC_MIMORATE		0x08000000	/* mimo MCS is stored in RSPEC_RATE_MASK */
+#define RSPEC_BW_MASK		0x00000700	/* mimo bw mask */
+#define RSPEC_BW_SHIFT		8	/* mimo bw shift */
+#define RSPEC_STF_MASK		0x00003800	/* mimo Space/Time/Frequency mode mask */
+#define RSPEC_STF_SHIFT		11	/* mimo Space/Time/Frequency mode shift */
+#define RSPEC_CT_MASK		0x0000C000	/* mimo coding type mask */
+#define RSPEC_CT_SHIFT		14	/* mimo coding type shift */
+#define RSPEC_STC_MASK		0x00300000	/* mimo num STC streams per PLCP defn. */
+#define RSPEC_STC_SHIFT		20	/* mimo num STC streams per PLCP defn. */
+#define RSPEC_LDPC_CODING	0x00400000	/* mimo bit indicates adv coding in use */
+#define RSPEC_SHORT_GI		0x00800000	/* mimo bit indicates short GI in use */
+#define RSPEC_OVERRIDE		0x80000000	/* bit indicates override both rate & mode */
+#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000	/* bit indicates override rate only */
+
+#define WLC_HTPHY		127	/* HT PHY Membership */
+
+#define RSPEC_ACTIVE(rspec)	(rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE))
+#define RSPEC2RATE(rspec)      	((rspec & RSPEC_MIMORATE) ? \
+	MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \
+	(rspec & RSPEC_RATE_MASK))
+/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
+#define RSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
+		MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \
+		(rspec & RSPEC_RATE_MASK))
+#define CRSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
+		MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\
+		(rspec & RSPEC_RATE_MASK))
+
+#define RSPEC2KBPS(rspec)	(IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500)
+#define RSPEC_PHYTXBYTE2(rspec)	((rspec & 0xff00) >> 8)
+#define RSPEC_GET_BW(rspec)	((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT)
+#define RSPEC_IS40MHZ(rspec)	((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \
+				PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \
+				RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP))
+#define RSPEC_ISSGI(rspec)	((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI)
+#define RSPEC_MIMOPLCP3(rspec)	((rspec & 0xf00000) >> 16)
+#define PLCP3_ISSGI(plcp)	(plcp & (RSPEC_SHORT_GI >> 16))
+#define RSPEC_STC(rspec)	((rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT)
+#define RSPEC_STF(rspec)	((rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT)
+#define PLCP3_ISSTBC(plcp)	((plcp & (RSPEC_STC_MASK) >> 16) == 0x10)
+#define PLCP3_STC_MASK          0x30
+#define PLCP3_STC_SHIFT         4
+
+/* Rate info table; takes a legacy rate or ratespec_t */
+#define	IS_MCS(r)     	(r & RSPEC_MIMORATE)
+#define	IS_OFDM(r)     	(!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & WLC_RATE_FLAG))
+#define	IS_CCK(r)	(!IS_MCS(r) && (((r) & RATE_MASK) == WLC_RATE_1M || \
+			 ((r) & RATE_MASK) == WLC_RATE_2M || \
+			 ((r) & RATE_MASK) == WLC_RATE_5M5 || ((r) & RATE_MASK) == WLC_RATE_11M))
+#define IS_SINGLE_STREAM(mcs)	(((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32))
+#define CCK_RSPEC(cck)		((cck) & RSPEC_RATE_MASK)
+#define OFDM_RSPEC(ofdm)	(((ofdm) & RSPEC_RATE_MASK) |\
+	(PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT))
+#define LEGACY_RSPEC(rate)	(IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate))
+
+#define MCS_RSPEC(mcs)		(((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \
+	(IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \
+	(PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT)))
+
+/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */
+extern const u8 ofdm_rate_lookup[];
+#define OFDM_PHY2MAC_RATE(rlpt)		(ofdm_rate_lookup[rlpt & 0x7])
+#define CCK_PHY2MAC_RATE(signal)	(signal/5)
+
+/* Rates specified in wlc_rateset_filter() */
+#define WLC_RATES_CCK_OFDM	0
+#define WLC_RATES_CCK		1
+#define WLC_RATES_OFDM		2
+
+/* use the stuct form instead of typedef to fix dependency problems */
+struct wlc_rateset;
+
+/* sanitize, and sort a rateset with the basic bit(s) preserved, validate rateset */
+extern bool wlc_rate_hwrs_filter_sort_validate(struct wlc_rateset *rs,
+					       const struct wlc_rateset *hw_rs,
+					       bool check_brate,
+					       u8 txstreams);
+/* copy rateset src to dst as-is (no masking or sorting) */
+extern void wlc_rateset_copy(const struct wlc_rateset *src,
+			     struct wlc_rateset *dst);
+
+/* would be nice to have these documented ... */
+extern ratespec_t wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp);
+
+extern void wlc_rateset_filter(struct wlc_rateset *src, struct wlc_rateset *dst,
+			       bool basic_only, u8 rates, uint xmask,
+			       bool mcsallow);
+extern void wlc_rateset_default(struct wlc_rateset *rs_tgt,
+				const struct wlc_rateset *rs_hw, uint phy_type,
+				int bandtype, bool cck_only, uint rate_mask,
+				bool mcsallow, u8 bw, u8 txstreams);
+extern s16 wlc_rate_legacy_phyctl(uint rate);
+
+extern void wlc_rateset_mcs_upd(struct wlc_rateset *rs, u8 txstreams);
+extern void wlc_rateset_mcs_clear(struct wlc_rateset *rateset);
+extern void wlc_rateset_mcs_build(struct wlc_rateset *rateset, u8 txstreams);
+extern void wlc_rateset_bw_mcs_filter(struct wlc_rateset *rateset, u8 bw);
+
+#endif				/* _WLC_RATE_H_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_scb.h b/drivers/staging/brcm80211/brcmsmac/wlc_scb.h
new file mode 100644
index 0000000..7326006
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_scb.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_scb_h_
+#define _wlc_scb_h_
+
+extern bool wlc_aggregatable(struct wlc_info *wlc, u8 tid);
+
+#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
+/* structure to store per-tid state for the ampdu initiator */
+typedef struct scb_ampdu_tid_ini {
+	u32 magic;
+	u8 tx_in_transit;	/* number of pending mpdus in transit in driver */
+	u8 tid;		/* initiator tid for easy lookup */
+	u8 txretry[AMPDU_TX_BA_MAX_WSIZE];	/* tx retry count; indexed by seq modulo */
+	struct scb *scb;	/* backptr for easy lookup */
+} scb_ampdu_tid_ini_t;
+
+#define AMPDU_MAX_SCB_TID	NUMPRIO
+
+typedef struct scb_ampdu {
+	struct scb *scb;	/* back pointer for easy reference */
+	u8 mpdu_density;	/* mpdu density */
+	u8 max_pdu;		/* max pdus allowed in ampdu */
+	u8 release;		/* # of mpdus released at a time */
+	u16 min_len;		/* min mpdu len to support the density */
+	u32 max_rxlen;	/* max ampdu rcv length; 8k, 16k, 32k, 64k */
+	struct pktq txq;	/* sdu transmit queue pending aggregation */
+
+	/* This could easily be a ini[] pointer and we keep this info in wl itself instead
+	 * of having mac80211 hold it for us.  Also could be made dynamic per tid instead of
+	 * static.
+	 */
+	scb_ampdu_tid_ini_t ini[AMPDU_MAX_SCB_TID];	/* initiator info - per tid (NUMPRIO) */
+} scb_ampdu_t;
+
+#define SCB_MAGIC 	0xbeefcafe
+#define INI_MAGIC 	0xabcd1234
+
+/* station control block - one per remote MAC address */
+struct scb {
+	u32 magic;
+	u32 flags;		/* various bit flags as defined below */
+	u32 flags2;		/* various bit flags2 as defined below */
+	u8 state;		/* current state bitfield of auth/assoc process */
+	u8 ea[ETH_ALEN];	/* station address */
+	void *fragbuf[NUMPRIO];	/* defragmentation buffer per prio */
+	uint fragresid[NUMPRIO];	/* #bytes unused in frag buffer per prio */
+
+	u16 seqctl[NUMPRIO];	/* seqctl of last received frame (for dups) */
+	u16 seqctl_nonqos;	/* seqctl of last received frame (for dups) for
+				 * non-QoS data and management
+				 */
+	u16 seqnum[NUMPRIO];	/* WME: driver maintained sw seqnum per priority */
+
+	scb_ampdu_t scb_ampdu;	/* AMPDU state including per tid info */
+};
+
+/* scb flags */
+#define SCB_WMECAP		0x0040	/* may ONLY be set if WME_ENAB(wlc) */
+#define SCB_HTCAP		0x10000	/* HT (MIMO) capable device */
+#define SCB_IS40		0x80000	/* 40MHz capable */
+#define SCB_STBCCAP		0x40000000	/* STBC Capable */
+#define SCB_WME(a)		((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
+#define SCB_SEQNUM(scb, prio)	((scb)->seqnum[(prio)])
+#define SCB_PS(a)		NULL
+#define SCB_STBC_CAP(a)		((a)->flags & SCB_STBCCAP)
+#define SCB_AMPDU(a)		true
+#endif				/* _wlc_scb_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_stf.c b/drivers/staging/brcm80211/brcmsmac/wlc_stf.c
new file mode 100644
index 0000000..098fd59
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_stf.c
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <proto/802.11.h>
+
+#include <bcmdefs.h>
+#include <bcmutils.h>
+#include <siutils.h>
+#include <wlioctl.h>
+#include <bcmwifi.h>
+#include <sbhnddma.h>
+
+#include "wlc_types.h"
+#include "d11.h"
+#include "wl_dbg.h"
+#include "wlc_cfg.h"
+#include "wlc_rate.h"
+#include "wlc_scb.h"
+#include "wlc_pub.h"
+#include "wlc_key.h"
+#include "phy/wlc_phy_hal.h"
+#include "wlc_channel.h"
+#include "wlc_main.h"
+#include "wl_export.h"
+#include "wlc_bmac.h"
+#include "wlc_stf.h"
+
+#define MIN_SPATIAL_EXPANSION	0
+#define MAX_SPATIAL_EXPANSION	1
+
+#define WLC_STF_SS_STBC_RX(wlc) (WLCISNPHY(wlc->band) && \
+	NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
+
+static bool wlc_stf_stbc_tx_set(struct wlc_info *wlc, s32 int_val);
+static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 val);
+static int wlc_stf_spatial_policy_set(struct wlc_info *wlc, int val);
+static void wlc_stf_stbc_rx_ht_update(struct wlc_info *wlc, int val);
+
+static void _wlc_stf_phy_txant_upd(struct wlc_info *wlc);
+static u16 _wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec);
+
+#define NSTS_1	1
+#define NSTS_2	2
+#define NSTS_3	3
+#define NSTS_4	4
+const u8 txcore_default[5] = {
+	(0),			/* bitmap of the core enabled */
+	(0x01),			/* For Nsts = 1, enable core 1 */
+	(0x03),			/* For Nsts = 2, enable core 1 & 2 */
+	(0x07),			/* For Nsts = 3, enable core 1, 2 & 3 */
+	(0x0f)			/* For Nsts = 4, enable all cores */
+};
+
+static void wlc_stf_stbc_rx_ht_update(struct wlc_info *wlc, int val)
+{
+	ASSERT((val == HT_CAP_RX_STBC_NO)
+	       || (val == HT_CAP_RX_STBC_ONE_STREAM));
+
+	/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
+	if (WLC_STF_SS_STBC_RX(wlc)) {
+		if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
+			return;
+	}
+
+	wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_RX_STBC;
+	wlc->ht_cap.cap_info |= (val << IEEE80211_HT_CAP_RX_STBC_SHIFT);
+
+	if (wlc->pub->up) {
+		wlc_update_beacon(wlc);
+		wlc_update_probe_resp(wlc, true);
+	}
+}
+
+/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */
+void wlc_tempsense_upd(struct wlc_info *wlc)
+{
+	wlc_phy_t *pi = wlc->band->pi;
+	uint active_chains, txchain;
+
+	/* Check if the chip is too hot. Disable one Tx chain, if it is */
+	/* high 4 bits are for Rx chain, low 4 bits are  for Tx chain */
+	active_chains = wlc_phy_stf_chain_active_get(pi);
+	txchain = active_chains & 0xf;
+
+	if (wlc->stf->txchain == wlc->stf->hw_txchain) {
+		if (txchain && (txchain < wlc->stf->hw_txchain)) {
+			/* turn off 1 tx chain */
+			wlc_stf_txchain_set(wlc, txchain, true);
+		}
+	} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
+		if (txchain == wlc->stf->hw_txchain) {
+			/* turn back on txchain */
+			wlc_stf_txchain_set(wlc, txchain, true);
+		}
+	}
+}
+
+void
+wlc_stf_ss_algo_channel_get(struct wlc_info *wlc, u16 *ss_algo_channel,
+			    chanspec_t chanspec)
+{
+	tx_power_t power;
+	u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
+
+	/* Clear previous settings */
+	*ss_algo_channel = 0;
+
+	if (!wlc->pub->up) {
+		*ss_algo_channel = (u16) -1;
+		return;
+	}
+
+	wlc_phy_txpower_get_current(wlc->band->pi, &power,
+				    CHSPEC_CHANNEL(chanspec));
+
+	siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
+	cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
+	stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
+	    WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
+
+	/* criteria to choose stf mode */
+
+	/* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs
+	 * on both chains
+	 */
+	if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
+		setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
+	else
+		setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
+
+	/* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check
+	 * so cannot be default mode of operation. One of SISO, CDD have to be set
+	 */
+	if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
+		setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
+}
+
+static bool wlc_stf_stbc_tx_set(struct wlc_info *wlc, s32 int_val)
+{
+	if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) {
+		return false;
+	}
+
+	if ((int_val == ON) && (wlc->stf->txstreams == 1))
+		return false;
+
+	if ((int_val == OFF) || (wlc->stf->txstreams == 1)
+	    || !WLC_STBC_CAP_PHY(wlc))
+		wlc->ht_cap.cap_info &= ~IEEE80211_HT_CAP_TX_STBC;
+	else
+		wlc->ht_cap.cap_info |= IEEE80211_HT_CAP_TX_STBC;
+
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
+
+	return true;
+}
+
+bool wlc_stf_stbc_rx_set(struct wlc_info *wlc, s32 int_val)
+{
+	if ((int_val != HT_CAP_RX_STBC_NO)
+	    && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) {
+		return false;
+	}
+
+	if (WLC_STF_SS_STBC_RX(wlc)) {
+		if ((int_val != HT_CAP_RX_STBC_NO)
+		    && (wlc->stf->rxstreams == 1))
+			return false;
+	}
+
+	wlc_stf_stbc_rx_ht_update(wlc, int_val);
+	return true;
+}
+
+static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 core_mask)
+{
+	WL_TRACE("wl%d: %s: Nsts %d core_mask %x\n",
+		 wlc->pub->unit, __func__, Nsts, core_mask);
+
+	ASSERT((Nsts > 0) && (Nsts <= MAX_STREAMS_SUPPORTED));
+
+	if (WLC_BITSCNT(core_mask) > wlc->stf->txstreams) {
+		core_mask = 0;
+	}
+
+	if ((WLC_BITSCNT(core_mask) == wlc->stf->txstreams) &&
+	    ((core_mask & ~wlc->stf->txchain)
+	     || !(core_mask & wlc->stf->txchain))) {
+		core_mask = wlc->stf->txchain;
+	}
+
+	ASSERT(!core_mask || Nsts <= WLC_BITSCNT(core_mask));
+
+	wlc->stf->txcore[Nsts] = core_mask;
+	/* Nsts = 1..4, txcore index = 1..4 */
+	if (Nsts == 1) {
+		/* Needs to update beacon and ucode generated response
+		 * frames when 1 stream core map changed
+		 */
+		wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
+		wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant);
+		if (wlc->clk) {
+			wlc_suspend_mac_and_wait(wlc);
+			wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
+			wlc_enable_mac(wlc);
+		}
+	}
+
+	return BCME_OK;
+}
+
+static int wlc_stf_spatial_policy_set(struct wlc_info *wlc, int val)
+{
+	int i;
+	u8 core_mask = 0;
+
+	WL_TRACE("wl%d: %s: val %x\n", wlc->pub->unit, __func__, val);
+
+	wlc->stf->spatial_policy = (s8) val;
+	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
+		core_mask = (val == MAX_SPATIAL_EXPANSION) ?
+		    wlc->stf->txchain : txcore_default[i];
+		wlc_stf_txcore_set(wlc, (u8) i, core_mask);
+	}
+	return BCME_OK;
+}
+
+int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force)
+{
+	u8 txchain = (u8) int_val;
+	u8 txstreams;
+	uint i;
+
+	if (wlc->stf->txchain == txchain)
+		return BCME_OK;
+
+	if ((txchain & ~wlc->stf->hw_txchain)
+	    || !(txchain & wlc->stf->hw_txchain))
+		return BCME_RANGE;
+
+	/* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */
+	txstreams = (u8) WLC_BITSCNT(txchain);
+	if (txstreams > MAX_STREAMS_SUPPORTED)
+		return BCME_RANGE;
+
+	if (txstreams == 1) {
+		for (i = 0; i < NBANDS(wlc); i++)
+			if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
+			     PHY_TXC1_MODE_SISO)
+			    || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
+				PHY_TXC1_MODE_SISO)) {
+				if (!force)
+					return BCME_ERROR;
+
+				/* over-write the override rspec */
+				if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
+				    != PHY_TXC1_MODE_SISO) {
+					wlc->bandstate[i]->rspec_override = 0;
+					WL_ERROR("%s(): temp sense override non-SISO rspec_override\n",
+						 __func__);
+				}
+				if (RSPEC_STF
+				    (wlc->bandstate[i]->mrspec_override) !=
+				    PHY_TXC1_MODE_SISO) {
+					wlc->bandstate[i]->mrspec_override = 0;
+					WL_ERROR("%s(): temp sense override non-SISO mrspec_override\n",
+						 __func__);
+				}
+			}
+	}
+
+	wlc->stf->txchain = txchain;
+	wlc->stf->txstreams = txstreams;
+	wlc_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
+	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+	wlc->stf->txant =
+	    (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
+	_wlc_stf_phy_txant_upd(wlc);
+
+	wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
+			      wlc->stf->rxchain);
+
+	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
+		wlc_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
+
+	return BCME_OK;
+}
+
+/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
+int wlc_stf_ss_update(struct wlc_info *wlc, struct wlcband *band)
+{
+	int ret_code = 0;
+	u8 prev_stf_ss;
+	u8 upd_stf_ss;
+
+	prev_stf_ss = wlc->stf->ss_opmode;
+
+	/* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
+	if (WLC_STBC_CAP_PHY(wlc) &&
+	    wlc->stf->ss_algosel_auto
+	    && (wlc->stf->ss_algo_channel != (u16) -1)) {
+		ASSERT(isset(&wlc->stf->ss_algo_channel, PHY_TXC1_MODE_CDD)
+		       || isset(&wlc->stf->ss_algo_channel,
+				PHY_TXC1_MODE_SISO));
+		upd_stf_ss = (wlc->stf->no_cddstbc || (wlc->stf->txstreams == 1)
+			      || isset(&wlc->stf->ss_algo_channel,
+				       PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
+		    : PHY_TXC1_MODE_CDD;
+	} else {
+		if (wlc->band != band)
+			return ret_code;
+		upd_stf_ss = (wlc->stf->no_cddstbc
+			      || (wlc->stf->txstreams ==
+				  1)) ? PHY_TXC1_MODE_SISO : band->
+		    band_stf_ss_mode;
+	}
+	if (prev_stf_ss != upd_stf_ss) {
+		wlc->stf->ss_opmode = upd_stf_ss;
+		wlc_bmac_band_stf_ss_set(wlc->hw, upd_stf_ss);
+	}
+
+	return ret_code;
+}
+
+int wlc_stf_attach(struct wlc_info *wlc)
+{
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
+
+	if (WLCISNPHY(wlc->band) &&
+	    (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
+		wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
+		    PHY_TXC1_MODE_CDD;
+	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
+	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
+
+	wlc_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
+	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
+	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
+
+	if (WLC_STBC_CAP_PHY(wlc)) {
+		wlc->stf->ss_algosel_auto = true;
+		wlc->stf->ss_algo_channel = (u16) -1;	/* Init the default value */
+	}
+	return 0;
+}
+
+void wlc_stf_detach(struct wlc_info *wlc)
+{
+}
+
+int wlc_stf_ant_txant_validate(struct wlc_info *wlc, s8 val)
+{
+	int bcmerror = BCME_OK;
+
+	/* when there is only 1 tx_streams, don't allow to change the txant */
+	if (WLCISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
+		return ((val == wlc->stf->txant) ? bcmerror : BCME_RANGE);
+
+	switch (val) {
+	case -1:
+		val = ANT_TX_DEF;
+		break;
+	case 0:
+		val = ANT_TX_FORCE_0;
+		break;
+	case 1:
+		val = ANT_TX_FORCE_1;
+		break;
+	case 3:
+		val = ANT_TX_LAST_RX;
+		break;
+	default:
+		bcmerror = BCME_RANGE;
+		break;
+	}
+
+	if (bcmerror == BCME_OK)
+		wlc->stf->txant = (s8) val;
+
+	return bcmerror;
+
+}
+
+/*
+ * Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain
+ *  change
+ *
+ * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
+ *   achieve various tx/rx antenna selection schemes
+ *
+ * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx)
+ * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and
+ *    do tx-antenna selection for SISO transmissions
+ * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and
+ *    do tx-antenna selection for SISO transmissions
+ * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active
+*/
+static void _wlc_stf_phy_txant_upd(struct wlc_info *wlc)
+{
+	s8 txant;
+
+	txant = (s8) wlc->stf->txant;
+	ASSERT(txant == ANT_TX_FORCE_0 || txant == ANT_TX_FORCE_1
+	       || txant == ANT_TX_LAST_RX);
+
+	if (WLC_PHY_11N_CAP(wlc->band)) {
+		if (txant == ANT_TX_FORCE_0) {
+			wlc->stf->phytxant = PHY_TXC_ANT_0;
+		} else if (txant == ANT_TX_FORCE_1) {
+			wlc->stf->phytxant = PHY_TXC_ANT_1;
+
+			if (WLCISNPHY(wlc->band) &&
+			    NREV_GE(wlc->band->phyrev, 3)
+			    && NREV_LT(wlc->band->phyrev, 7)) {
+				wlc->stf->phytxant = PHY_TXC_ANT_2;
+			}
+		} else {
+			if (WLCISLCNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band))
+				wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
+			else {
+				/* keep this assert to catch out of sync wlc->stf->txcore */
+				ASSERT(wlc->stf->txchain > 0);
+				wlc->stf->phytxant =
+				    wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+			}
+		}
+	} else {
+		if (txant == ANT_TX_FORCE_0)
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
+		else if (txant == ANT_TX_FORCE_1)
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
+		else
+			wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
+	}
+
+	wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant);
+}
+
+void wlc_stf_phy_txant_upd(struct wlc_info *wlc)
+{
+	_wlc_stf_phy_txant_upd(wlc);
+}
+
+void wlc_stf_phy_chain_calc(struct wlc_info *wlc)
+{
+	/* get available rx/tx chains */
+	wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
+	wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
+
+	/* these parameter are intended to be used for all PHY types */
+	if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
+		if (WLCISNPHY(wlc->band)) {
+			wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
+		} else {
+			wlc->stf->hw_txchain = TXCHAIN_DEF;
+		}
+	}
+
+	wlc->stf->txchain = wlc->stf->hw_txchain;
+	wlc->stf->txstreams = (u8) WLC_BITSCNT(wlc->stf->hw_txchain);
+
+	if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
+		if (WLCISNPHY(wlc->band)) {
+			wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
+		} else {
+			wlc->stf->hw_rxchain = RXCHAIN_DEF;
+		}
+	}
+
+	wlc->stf->rxchain = wlc->stf->hw_rxchain;
+	wlc->stf->rxstreams = (u8) WLC_BITSCNT(wlc->stf->hw_rxchain);
+
+	/* initialize the txcore table */
+	memcpy(wlc->stf->txcore, txcore_default, sizeof(wlc->stf->txcore));
+
+	/* default spatial_policy */
+	wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
+	wlc_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
+}
+
+static u16 _wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec)
+{
+	u16 phytxant = wlc->stf->phytxant;
+
+	if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
+		ASSERT(wlc->stf->txstreams > 1);
+		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+	} else if (wlc->stf->txant == ANT_TX_DEF)
+		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
+	phytxant &= PHY_TXC_ANT_MASK;
+	return phytxant;
+}
+
+u16 wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec)
+{
+	return _wlc_stf_phytxchain_sel(wlc, rspec);
+}
+
+u16 wlc_stf_d11hdrs_phyctl_txant(struct wlc_info *wlc, ratespec_t rspec)
+{
+	u16 phytxant = wlc->stf->phytxant;
+	u16 mask = PHY_TXC_ANT_MASK;
+
+	/* for non-siso rates or default setting, use the available chains */
+	if (WLCISNPHY(wlc->band)) {
+		ASSERT(wlc->stf->txchain != 0);
+		phytxant = _wlc_stf_phytxchain_sel(wlc, rspec);
+		mask = PHY_TXC_HTANT_MASK;
+	}
+	phytxant |= phytxant & mask;
+	return phytxant;
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_stf.h b/drivers/staging/brcm80211/brcmsmac/wlc_stf.h
new file mode 100644
index 0000000..2b1180b
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_stf.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_stf_h_
+#define _wlc_stf_h_
+
+extern int wlc_stf_attach(struct wlc_info *wlc);
+extern void wlc_stf_detach(struct wlc_info *wlc);
+
+extern void wlc_tempsense_upd(struct wlc_info *wlc);
+extern void wlc_stf_ss_algo_channel_get(struct wlc_info *wlc,
+					u16 *ss_algo_channel,
+					chanspec_t chanspec);
+extern int wlc_stf_ss_update(struct wlc_info *wlc, struct wlcband *band);
+extern void wlc_stf_phy_txant_upd(struct wlc_info *wlc);
+extern int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force);
+extern bool wlc_stf_stbc_rx_set(struct wlc_info *wlc, s32 int_val);
+
+extern int wlc_stf_ant_txant_validate(struct wlc_info *wlc, s8 val);
+extern void wlc_stf_phy_txant_upd(struct wlc_info *wlc);
+extern void wlc_stf_phy_chain_calc(struct wlc_info *wlc);
+extern u16 wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec);
+extern u16 wlc_stf_d11hdrs_phyctl_txant(struct wlc_info *wlc, ratespec_t rspec);
+
+#endif				/* _wlc_stf_h_ */
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_types.h b/drivers/staging/brcm80211/brcmsmac/wlc_types.h
new file mode 100644
index 0000000..df6e04c
--- /dev/null
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_types.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _wlc_types_h_
+#define _wlc_types_h_
+
+/* forward declarations */
+
+struct wlc_info;
+struct wlc_hw_info;
+struct wlc_if;
+struct wl_if;
+struct ampdu_info;
+struct antsel_info;
+struct bmac_pmq;
+
+struct d11init;
+
+#ifndef _hnddma_pub_
+#define _hnddma_pub_
+struct hnddma_pub;
+#endif				/* _hnddma_pub_ */
+
+#endif				/* _wlc_types_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmcdc.h b/drivers/staging/brcm80211/include/bcmcdc.h
deleted file mode 100644
index 10c1ddc..0000000
--- a/drivers/staging/brcm80211/include/bcmcdc.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <proto/ethernet.h>
-
-typedef struct cdc_ioctl {
-	u32 cmd;		/* ioctl command value */
-	u32 len;		/* lower 16: output buflen; upper 16:
-				 input buflen (excludes header) */
-	u32 flags;		/* flag defns given below */
-	u32 status;		/* status code returned from the device */
-} cdc_ioctl_t;
-
-/* Max valid buffer size that can be sent to the dongle */
-#define CDC_MAX_MSG_SIZE   ETHER_MAX_LEN
-
-/* len field is divided into input and output buffer lengths */
-#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF	/* maximum or expected
-						 response length, */
-					   /* excluding IOCTL header */
-#define CDCL_IOC_OUTLEN_SHIFT  0
-#define CDCL_IOC_INLEN_MASK    0xFFFF0000	/* input buffer length,
-						 excluding IOCTL header */
-#define CDCL_IOC_INLEN_SHIFT   16
-
-/* CDC flag definitions */
-#define CDCF_IOC_ERROR		0x01	/* 0=success, 1=ioctl cmd failed */
-#define CDCF_IOC_SET		0x02	/* 0=get, 1=set cmd */
-#define CDCF_IOC_IF_MASK	0xF000	/* I/F index */
-#define CDCF_IOC_IF_SHIFT	12
-#define CDCF_IOC_ID_MASK	0xFFFF0000	/* used to uniquely id an ioctl
-						 req/resp pairing */
-#define CDCF_IOC_ID_SHIFT	16	/* # of bits of shift for ID Mask */
-
-#define CDC_IOC_IF_IDX(flags)	\
-	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
-#define CDC_IOC_ID(flags)	\
-	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
-
-#define CDC_GET_IF_IDX(hdr) \
-	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
-#define CDC_SET_IF_IDX(hdr, idx) \
-	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
-	((idx) << CDCF_IOC_IF_SHIFT)))
-
-/*
- * BDC header
- *
- *   The BDC header is used on data packets to convey priority across USB.
- */
-
-#define	BDC_HEADER_LEN		4
-
-#define BDC_PROTO_VER		1	/* Protocol version */
-
-#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
-#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
-
-#define BDC_FLAG__UNUSED	0x03	/* Unassigned */
-#define BDC_FLAG_SUM_GOOD	0x04	/* Dongle has verified good
-					 RX checksums */
-#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums */
-
-#define BDC_PRIORITY_MASK	0x7
-
-#define BDC_FLAG2_FC_FLAG	0x10	/* flag to indicate if pkt contains */
-						/* FLOW CONTROL info only */
-#define BDC_PRIORITY_FC_SHIFT	4	/* flow control info shift */
-
-#define BDC_FLAG2_IF_MASK	0x0f	/* APSTA: interface on which the
-					 packet was received */
-#define BDC_FLAG2_IF_SHIFT	0
-
-#define BDC_GET_IF_IDX(hdr) \
-	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
-#define BDC_SET_IF_IDX(hdr, idx) \
-	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
-	((idx) << BDC_FLAG2_IF_SHIFT)))
-
-struct bdc_header {
-	u8 flags;		/* Flags */
-	u8 priority;		/* 802.1d Priority 0:2 bits, 4:7 flow
-				 control info for usb */
-	u8 flags2;
-	u8 rssi;
-};
diff --git a/drivers/staging/brcm80211/include/bcmdefs.h b/drivers/staging/brcm80211/include/bcmdefs.h
index 74601fc..22a389e 100644
--- a/drivers/staging/brcm80211/include/bcmdefs.h
+++ b/drivers/staging/brcm80211/include/bcmdefs.h
@@ -138,10 +138,25 @@ typedef struct {
 		(((val) & (~(field ## _M << field ## _S))) | \
 		 ((unsigned)(bits) << field ## _S))
 
+/*
+ * Priority definitions according 802.1D
+ */
+#define	PRIO_8021D_NONE		2
+#define	PRIO_8021D_BK		1
+#define	PRIO_8021D_BE		0
+#define	PRIO_8021D_EE		3
+#define	PRIO_8021D_CL		4
+#define	PRIO_8021D_VI		5
+#define	PRIO_8021D_VO		6
+#define	PRIO_8021D_NC		7
+#define	MAXPRIO			7
+#define NUMPRIO			(MAXPRIO + 1)
+
 /* Max. nvram variable table size */
 #define	MAXSZ_NVRAM_VARS	4096
 
 /* handle forward declaration */
 struct wl_info;
+struct wlc_bsscfg;
 
 #endif				/* _bcmdefs_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmendian.h b/drivers/staging/brcm80211/include/bcmendian.h
deleted file mode 100644
index 4123aef..0000000
--- a/drivers/staging/brcm80211/include/bcmendian.h
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _BCMENDIAN_H_
-#define _BCMENDIAN_H_
-
-/* Reverse the bytes in a 16-bit value */
-#define BCMSWAP16(val) \
-	((u16)((((u16)(val) & (u16)0x00ffU) << 8) | \
-		  (((u16)(val) & (u16)0xff00U) >> 8)))
-
-/* Reverse the bytes in a 32-bit value */
-#define BCMSWAP32(val) \
-	((u32)((((u32)(val) & (u32)0x000000ffU) << 24) | \
-		  (((u32)(val) & (u32)0x0000ff00U) <<  8) | \
-		  (((u32)(val) & (u32)0x00ff0000U) >>  8) | \
-		  (((u32)(val) & (u32)0xff000000U) >> 24)))
-
-/* Reverse the two 16-bit halves of a 32-bit value */
-#define BCMSWAP32BY16(val) \
-	((u32)((((u32)(val) & (u32)0x0000ffffU) << 16) | \
-		  (((u32)(val) & (u32)0xffff0000U) >> 16)))
-
-/* Byte swapping macros
- *    Host <=> Network (Big Endian) for 16- and 32-bit values
- *    Host <=> Little-Endian for 16- and 32-bit values
- */
-#ifndef hton16
-#ifndef IL_BIGENDIAN
-#define HTON16(i) BCMSWAP16(i)
-#define	hton16(i) bcmswap16(i)
-#define	HTON32(i) BCMSWAP32(i)
-#define	hton32(i) bcmswap32(i)
-#define	NTOH16(i) BCMSWAP16(i)
-#define	ntoh16(i) bcmswap16(i)
-#define	NTOH32(i) BCMSWAP32(i)
-#define	ntoh32(i) bcmswap32(i)
-#define LTOH16(i) (i)
-#define ltoh16(i) (i)
-#define LTOH32(i) (i)
-#define ltoh32(i) (i)
-#define HTOL16(i) (i)
-#define htol16(i) (i)
-#define HTOL32(i) (i)
-#define htol32(i) (i)
-#else				/* IL_BIGENDIAN */
-#define HTON16(i) (i)
-#define	hton16(i) (i)
-#define	HTON32(i) (i)
-#define	hton32(i) (i)
-#define	NTOH16(i) (i)
-#define	ntoh16(i) (i)
-#define	NTOH32(i) (i)
-#define	ntoh32(i) (i)
-#define	LTOH16(i) BCMSWAP16(i)
-#define	ltoh16(i) bcmswap16(i)
-#define	LTOH32(i) BCMSWAP32(i)
-#define	ltoh32(i) bcmswap32(i)
-#define HTOL16(i) BCMSWAP16(i)
-#define htol16(i) bcmswap16(i)
-#define HTOL32(i) BCMSWAP32(i)
-#define htol32(i) bcmswap32(i)
-#endif				/* IL_BIGENDIAN */
-#endif				/* hton16 */
-
-#ifndef IL_BIGENDIAN
-#define ltoh16_buf(buf, i)
-#define htol16_buf(buf, i)
-#else
-#define ltoh16_buf(buf, i) bcmswap16_buf((u16 *)(buf), (i))
-#define htol16_buf(buf, i) bcmswap16_buf((u16 *)(buf), (i))
-#endif				/* IL_BIGENDIAN */
-
-/* Unaligned loads and stores in host byte order */
-#ifndef IL_BIGENDIAN
-#define load32_ua(a)		ltoh32_ua(a)
-#define store32_ua(a, v)	htol32_ua_store(v, a)
-#define load16_ua(a)		ltoh16_ua(a)
-#define store16_ua(a, v)	htol16_ua_store(v, a)
-#else
-#define load32_ua(a)		ntoh32_ua(a)
-#define store32_ua(a, v)	hton32_ua_store(v, a)
-#define load16_ua(a)		ntoh16_ua(a)
-#define store16_ua(a, v)	hton16_ua_store(v, a)
-#endif				/* IL_BIGENDIAN */
-
-#define _LTOH16_UA(cp)	((cp)[0] | ((cp)[1] << 8))
-#define _LTOH32_UA(cp)	((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24))
-#define _NTOH16_UA(cp)	(((cp)[0] << 8) | (cp)[1])
-#define _NTOH32_UA(cp)	(((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3])
-
-#define ltoh_ua(ptr) \
-	(sizeof(*(ptr)) == sizeof(u8) ? *(const u8 *)(ptr) : \
-	 sizeof(*(ptr)) == sizeof(u16) ? _LTOH16_UA((const u8 *)(ptr)) : \
-	 sizeof(*(ptr)) == sizeof(u32) ? _LTOH32_UA((const u8 *)(ptr)) : \
-	 *(u8 *)0)
-
-#define ntoh_ua(ptr) \
-	(sizeof(*(ptr)) == sizeof(u8) ? *(const u8 *)(ptr) : \
-	 sizeof(*(ptr)) == sizeof(u16) ? _NTOH16_UA((const u8 *)(ptr)) : \
-	 sizeof(*(ptr)) == sizeof(u32) ? _NTOH32_UA((const u8 *)(ptr)) : \
-	 *(u8 *)0)
-
-#ifdef __GNUC__
-
-/* GNU macro versions avoid referencing the argument multiple times, while also
- * avoiding the -fno-inline used in ROM builds.
- */
-
-#define bcmswap16(val) ({ \
-	u16 _val = (val); \
-	BCMSWAP16(_val); \
-})
-
-#define bcmswap32(val) ({ \
-	u32 _val = (val); \
-	BCMSWAP32(_val); \
-})
-
-#define bcmswap32by16(val) ({ \
-	u32 _val = (val); \
-	BCMSWAP32BY16(_val); \
-})
-
-#define bcmswap16_buf(buf, len) ({ \
-	u16 *_buf = (u16 *)(buf); \
-	uint _wds = (len) / 2; \
-	while (_wds--) { \
-		*_buf = bcmswap16(*_buf); \
-		_buf++; \
-	} \
-})
-
-#define htol16_ua_store(val, bytes) ({ \
-	u16 _val = (val); \
-	u8 *_bytes = (u8 *)(bytes); \
-	_bytes[0] = _val & 0xff; \
-	_bytes[1] = _val >> 8; \
-})
-
-#define htol32_ua_store(val, bytes) ({ \
-	u32 _val = (val); \
-	u8 *_bytes = (u8 *)(bytes); \
-	_bytes[0] = _val & 0xff; \
-	_bytes[1] = (_val >> 8) & 0xff; \
-	_bytes[2] = (_val >> 16) & 0xff; \
-	_bytes[3] = _val >> 24; \
-})
-
-#define hton16_ua_store(val, bytes) ({ \
-	u16 _val = (val); \
-	u8 *_bytes = (u8 *)(bytes); \
-	_bytes[0] = _val >> 8; \
-	_bytes[1] = _val & 0xff; \
-})
-
-#define hton32_ua_store(val, bytes) ({ \
-	u32 _val = (val); \
-	u8 *_bytes = (u8 *)(bytes); \
-	_bytes[0] = _val >> 24; \
-	_bytes[1] = (_val >> 16) & 0xff; \
-	_bytes[2] = (_val >> 8) & 0xff; \
-	_bytes[3] = _val & 0xff; \
-})
-
-#define ltoh16_ua(bytes) ({ \
-	const u8 *_bytes = (const u8 *)(bytes); \
-	_LTOH16_UA(_bytes); \
-})
-
-#define ltoh32_ua(bytes) ({ \
-	const u8 *_bytes = (const u8 *)(bytes); \
-	_LTOH32_UA(_bytes); \
-})
-
-#define ntoh16_ua(bytes) ({ \
-	const u8 *_bytes = (const u8 *)(bytes); \
-	_NTOH16_UA(_bytes); \
-})
-
-#define ntoh32_ua(bytes) ({ \
-	const u8 *_bytes = (const u8 *)(bytes); \
-	_NTOH32_UA(_bytes); \
-})
-
-#else				/* !__GNUC__ */
-
-/* Inline versions avoid referencing the argument multiple times */
-static inline u16 bcmswap16(u16 val)
-{
-	return BCMSWAP16(val);
-}
-
-static inline u32 bcmswap32(u32 val)
-{
-	return BCMSWAP32(val);
-}
-
-static inline u32 bcmswap32by16(u32 val)
-{
-	return BCMSWAP32BY16(val);
-}
-
-/* Reverse pairs of bytes in a buffer (not for high-performance use) */
-/* buf	- start of buffer of shorts to swap */
-/* len  - byte length of buffer */
-static inline void bcmswap16_buf(u16 *buf, uint len)
-{
-	len = len / 2;
-
-	while (len--) {
-		*buf = bcmswap16(*buf);
-		buf++;
-	}
-}
-
-/*
- * Store 16-bit value to unaligned little-endian byte array.
- */
-static inline void htol16_ua_store(u16 val, u8 *bytes)
-{
-	bytes[0] = val & 0xff;
-	bytes[1] = val >> 8;
-}
-
-/*
- * Store 32-bit value to unaligned little-endian byte array.
- */
-static inline void htol32_ua_store(u32 val, u8 *bytes)
-{
-	bytes[0] = val & 0xff;
-	bytes[1] = (val >> 8) & 0xff;
-	bytes[2] = (val >> 16) & 0xff;
-	bytes[3] = val >> 24;
-}
-
-/*
- * Store 16-bit value to unaligned network-(big-)endian byte array.
- */
-static inline void hton16_ua_store(u16 val, u8 *bytes)
-{
-	bytes[0] = val >> 8;
-	bytes[1] = val & 0xff;
-}
-
-/*
- * Store 32-bit value to unaligned network-(big-)endian byte array.
- */
-static inline void hton32_ua_store(u32 val, u8 *bytes)
-{
-	bytes[0] = val >> 24;
-	bytes[1] = (val >> 16) & 0xff;
-	bytes[2] = (val >> 8) & 0xff;
-	bytes[3] = val & 0xff;
-}
-
-/*
- * Load 16-bit value from unaligned little-endian byte array.
- */
-static inline u16 ltoh16_ua(const void *bytes)
-{
-	return _LTOH16_UA((const u8 *)bytes);
-}
-
-/*
- * Load 32-bit value from unaligned little-endian byte array.
- */
-static inline u32 ltoh32_ua(const void *bytes)
-{
-	return _LTOH32_UA((const u8 *)bytes);
-}
-
-/*
- * Load 16-bit value from unaligned big-(network-)endian byte array.
- */
-static inline u16 ntoh16_ua(const void *bytes)
-{
-	return _NTOH16_UA((const u8 *)bytes);
-}
-
-/*
- * Load 32-bit value from unaligned big-(network-)endian byte array.
- */
-static inline u32 ntoh32_ua(const void *bytes)
-{
-	return _NTOH32_UA((const u8 *)bytes);
-}
-
-#endif				/* !__GNUC__ */
-#endif				/* !_BCMENDIAN_H_ */
diff --git a/drivers/staging/brcm80211/include/bcmnvram.h b/drivers/staging/brcm80211/include/bcmnvram.h
index 63e31a4..e194131 100644
--- a/drivers/staging/brcm80211/include/bcmnvram.h
+++ b/drivers/staging/brcm80211/include/bcmnvram.h
@@ -29,12 +29,6 @@ struct nvram_header {
 	u32 config_ncdl;	/* ncdl values for memc */
 };
 
-struct nvram_tuple {
-	char *name;
-	char *value;
-	struct nvram_tuple *next;
-};
-
 /*
  * Get default value for an NVRAM variable
  */
diff --git a/drivers/staging/brcm80211/include/bcmsdbus.h b/drivers/staging/brcm80211/include/bcmsdbus.h
deleted file mode 100644
index 89059dd..0000000
--- a/drivers/staging/brcm80211/include/bcmsdbus.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_sdio_api_h_
-#define	_sdio_api_h_
-
-#define SDIOH_API_RC_SUCCESS                          (0x00)
-#define SDIOH_API_RC_FAIL	                      (0x01)
-#define SDIOH_API_SUCCESS(status) (status == 0)
-
-#define SDIOH_READ              0	/* Read request */
-#define SDIOH_WRITE             1	/* Write request */
-
-#define SDIOH_DATA_FIX          0	/* Fixed addressing */
-#define SDIOH_DATA_INC          1	/* Incremental addressing */
-
-#define SDIOH_CMD_TYPE_NORMAL   0	/* Normal command */
-#define SDIOH_CMD_TYPE_APPEND   1	/* Append command */
-#define SDIOH_CMD_TYPE_CUTTHRU  2	/* Cut-through command */
-
-#define SDIOH_DATA_PIO          0	/* PIO mode */
-#define SDIOH_DATA_DMA          1	/* DMA mode */
-
-typedef int SDIOH_API_RC;
-
-/* SDio Host structure */
-typedef struct sdioh_info sdioh_info_t;
-
-/* callback function, taking one arg */
-typedef void (*sdioh_cb_fn_t) (void *);
-
-/* attach, return handler on success, NULL if failed.
- *  The handler shall be provided by all subsequent calls. No local cache
- *  cfghdl points to the starting address of pci device mapped memory
- */
-extern sdioh_info_t *sdioh_attach(struct osl_info *osh, void *cfghdl, uint irq);
-extern SDIOH_API_RC sdioh_detach(struct osl_info *osh, sdioh_info_t *si);
-extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si,
-					     sdioh_cb_fn_t fn, void *argh);
-extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
-
-/* query whether SD interrupt is enabled or not */
-extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
-
-/* enable or disable SD interrupt */
-extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
-
-#if defined(BCMDBG)
-extern bool sdioh_interrupt_pending(sdioh_info_t *si);
-#endif
-
-extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
-extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
-
-/* read or write one byte using cmd52 */
-extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc,
-				       uint addr, u8 *byte);
-
-/* read or write 2/4 bytes using cmd53 */
-extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type,
-				       uint rw, uint fnc, uint addr,
-				       u32 *word, uint nbyte);
-
-/* read or write any buffer using cmd53 */
-extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma,
-					 uint fix_inc, uint rw, uint fnc_num,
-					 u32 addr, uint regwidth,
-					 u32 buflen, u8 *buffer,
-					 struct sk_buff *pkt);
-
-/* get cis data */
-extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, u8 *cis,
-				   u32 length);
-
-extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, u32 addr,
-				   u8 *data);
-extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, u32 addr,
-				    u8 *data);
-
-/* query number of io functions */
-extern uint sdioh_query_iofnum(sdioh_info_t *si);
-
-/* handle iovars */
-extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
-			  void *params, int plen, void *arg, int len, bool set);
-
-/* Issue abort to the specified function and clear controller as needed */
-extern int sdioh_abort(sdioh_info_t *si, uint fnc);
-
-/* Start and Stop SDIO without re-enumerating the SD card. */
-extern int sdioh_start(sdioh_info_t *si, int stage);
-extern int sdioh_stop(sdioh_info_t *si);
-
-/* Reset and re-initialize the device */
-extern int sdioh_sdio_reset(sdioh_info_t *si);
-
-/* Helper function */
-void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
-
-#endif				/* _sdio_api_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmsdh.h b/drivers/staging/brcm80211/include/bcmsdh.h
index 0e1f799..3b57dc1 100644
--- a/drivers/staging/brcm80211/include/bcmsdh.h
+++ b/drivers/staging/brcm80211/include/bcmsdh.h
@@ -17,13 +17,22 @@
 #ifndef	_bcmsdh_h_
 #define	_bcmsdh_h_
 
+#include <linux/skbuff.h>
 #define BCMSDH_ERROR_VAL	0x0001	/* Error */
 #define BCMSDH_INFO_VAL		0x0002	/* Info */
 extern const uint bcmsdh_msglevel;
 
 #ifdef BCMDBG
-#define BCMSDH_ERROR(x)	do { if ((bcmsdh_msglevel & BCMSDH_ERROR_VAL) && net_ratelimit()) printf x; } while (0)
-#define BCMSDH_INFO(x)	do { if ((bcmsdh_msglevel & BCMSDH_INFO_VAL) && net_ratelimit()) printf x; } while (0)
+#define BCMSDH_ERROR(x) \
+	do { \
+		if ((bcmsdh_msglevel & BCMSDH_ERROR_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define BCMSDH_INFO(x)	\
+	do { \
+		if ((bcmsdh_msglevel & BCMSDH_INFO_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
 #else				/* BCMDBG */
 #define BCMSDH_ERROR(x)
 #define BCMSDH_INFO(x)
@@ -40,11 +49,10 @@ typedef void (*bcmsdh_cb_fn_t) (void *);
  *    implementation may maintain a single "default" handle (e.g. the first or
  *    most recent one) to enable single-instance implementations to pass NULL.
  */
-extern bcmsdh_info_t *bcmsdh_attach(struct osl_info *osh, void *cfghdl,
-				    void **regsva, uint irq);
+extern bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq);
 
 /* Detach - freeup resources allocated in attach */
-extern int bcmsdh_detach(struct osl_info *osh, void *sdh);
+extern int bcmsdh_detach(void *sdh);
 
 /* Query if SD device interrupts are enabled */
 extern bool bcmsdh_intr_query(void *sdh);
@@ -57,7 +65,7 @@ extern int bcmsdh_intr_disable(void *sdh);
 extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh);
 extern int bcmsdh_intr_dereg(void *sdh);
 
-#if defined(BCMDBG)
+#if defined(DHD_DEBUG)
 /* Query pending interrupt status from the host controller */
 extern bool bcmsdh_intr_pending(void *sdh);
 #endif
@@ -174,8 +182,7 @@ extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
 typedef struct {
 	/* attach to device */
 	void *(*attach) (u16 vend_id, u16 dev_id, u16 bus, u16 slot,
-			 u16 func, uint bustype, void *regsva,
-			 struct osl_info *osh, void *param);
+			 u16 func, uint bustype, void *regsva, void *param);
 	/* detach from device */
 	void (*detach) (void *ch);
 } bcmsdh_driver_t;
diff --git a/drivers/staging/brcm80211/include/bcmsdh_sdmmc.h b/drivers/staging/brcm80211/include/bcmsdh_sdmmc.h
deleted file mode 100644
index 4d671dd..0000000
--- a/drivers/staging/brcm80211/include/bcmsdh_sdmmc.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef __BCMSDH_SDMMC_H__
-#define __BCMSDH_SDMMC_H__
-
-#ifdef BCMDBG
-#define sd_err(x)	do { if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) printf x; } while (0)
-#define sd_trace(x)	do { if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) printf x; } while (0)
-#define sd_info(x)	do { if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) printf x; } while (0)
-#define sd_debug(x)	do { if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) printf x; } while (0)
-#define sd_data(x)	do { if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) printf x; } while (0)
-#define sd_ctrl(x)	do { if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) printf x; } while (0)
-#else
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#endif
-
-/* Allocate/init/free per-OS private data */
-extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
-extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
-
-#define BLOCK_SIZE_64 64
-#define BLOCK_SIZE_512 512
-#define BLOCK_SIZE_4318 64
-#define BLOCK_SIZE_4328 512
-
-/* internal return code */
-#define SUCCESS	0
-#define ERROR	1
-
-/* private bus modes */
-#define SDIOH_MODE_SD4		2
-#define CLIENT_INTR 		0x100	/* Get rid of this! */
-
-struct sdioh_info {
-	struct osl_info *osh;		/* osh handler */
-	bool client_intr_enabled;	/* interrupt connnected flag */
-	bool intr_handler_valid;	/* client driver interrupt handler valid */
-	sdioh_cb_fn_t intr_handler;	/* registered interrupt handler */
-	void *intr_handler_arg;	/* argument to call interrupt handler */
-	u16 intmask;		/* Current active interrupts */
-	void *sdos_info;	/* Pointer to per-OS private data */
-
-	uint irq;		/* Client irq */
-	int intrcount;		/* Client interrupts */
-	bool sd_use_dma;	/* DMA on CMD53 */
-	bool sd_blockmode;	/* sd_blockmode == false => 64 Byte Cmd 53s. */
-	/*  Must be on for sd_multiblock to be effective */
-	bool use_client_ints;	/* If this is false, make sure to restore */
-	int sd_mode;		/* SD1/SD4/SPI */
-	int client_block_size[SDIOD_MAX_IOFUNCS];	/* Blocksize */
-	u8 num_funcs;	/* Supported funcs on client */
-	u32 com_cis_ptr;
-	u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
-	uint max_dma_len;
-	uint max_dma_descriptors;	/* DMA Descriptors supported by this controller. */
-	/*	SDDMA_DESCRIPTOR	SGList[32]; *//* Scatter/Gather DMA List */
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmsdh_sdmmc.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/* OS-independent interrupt handler */
-extern bool check_client_intr(sdioh_info_t *sd);
-
-/* Core interrupt enable/disable of device interrupts */
-extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
-extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
-
-/**************************************************************
- * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
- */
-
-/* Register mapping routines */
-extern u32 *sdioh_sdmmc_reg_map(struct osl_info *osh, s32 addr, int size);
-extern void sdioh_sdmmc_reg_unmap(struct osl_info *osh, s32 addr, int size);
-
-/* Interrupt (de)registration routines */
-extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
-extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
-
-typedef struct _BCMSDH_SDMMC_INSTANCE {
-	sdioh_info_t *sd;
-	struct sdio_func *func[SDIOD_MAX_IOFUNCS];
-	u32 host_claimed;
-} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
-
-#endif				/* __BCMSDH_SDMMC_H__ */
diff --git a/drivers/staging/brcm80211/include/bcmsrom.h b/drivers/staging/brcm80211/include/bcmsrom.h
index cdcef74..b2dc895 100644
--- a/drivers/staging/brcm80211/include/bcmsrom.h
+++ b/drivers/staging/brcm80211/include/bcmsrom.h
@@ -21,14 +21,14 @@
 
 /* Prototypes */
 extern int srom_var_init(si_t *sih, uint bus, void *curmap,
-			 struct osl_info *osh, char **vars, uint *count);
+			 char **vars, uint *count);
 
-extern int srom_read(si_t *sih, uint bus, void *curmap, struct osl_info *osh,
+extern int srom_read(si_t *sih, uint bus, void *curmap,
 		     uint byteoff, uint nbytes, u16 *buf, bool check_crc);
 
 /* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP
  *   and extract from it into name=value pairs
  */
-extern int srom_parsecis(struct osl_info *osh, u8 **pcis, uint ciscnt,
+extern int srom_parsecis(u8 **pcis, uint ciscnt,
 			 char **vars, uint *count);
 #endif				/* _bcmsrom_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmsrom_tbl.h b/drivers/staging/brcm80211/include/bcmsrom_tbl.h
deleted file mode 100644
index 22ae7c1..0000000
--- a/drivers/staging/brcm80211/include/bcmsrom_tbl.h
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_bcmsrom_tbl_h_
-#define	_bcmsrom_tbl_h_
-
-#include "sbpcmcia.h"
-#include "wlioctl.h"
-
-typedef struct {
-	const char *name;
-	u32 revmask;
-	u32 flags;
-	u16 off;
-	u16 mask;
-} sromvar_t;
-
-#define SRFL_MORE	1	/* value continues as described by the next entry */
-#define	SRFL_NOFFS	2	/* value bits can't be all one's */
-#define	SRFL_PRHEX	4	/* value is in hexdecimal format */
-#define	SRFL_PRSIGN	8	/* value is in signed decimal format */
-#define	SRFL_CCODE	0x10	/* value is in country code format */
-#define	SRFL_ETHADDR	0x20	/* value is an Ethernet address */
-#define SRFL_LEDDC	0x40	/* value is an LED duty cycle */
-#define SRFL_NOVAR	0x80	/* do not generate a nvram param, entry is for mfgc */
-
-/* Assumptions:
- * - Ethernet address spans across 3 consective words
- *
- * Table rules:
- * - Add multiple entries next to each other if a value spans across multiple words
- *   (even multiple fields in the same word) with each entry except the last having
- *   it's SRFL_MORE bit set.
- * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
- *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
- * - The last entry's name field must be NULL to indicate the end of the table. Other
- *   entries must have non-NULL name.
- */
-
-static const sromvar_t pci_sromvars[] = {
-	{"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
-	{"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
-	{"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
-	{"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
-	{"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
-	{"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
-	{"", 0, 0, SROM_BFL2, 0xffff},
-	{"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
-	{"", 0, 0, SROM3_BFL2, 0xffff},
-	{"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
-	{"", 0, 0, SROM4_BFL1, 0xffff},
-	{"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
-	{"", 0, 0, SROM5_BFL1, 0xffff},
-	{"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
-	{"", 0, 0, SROM8_BFL1, 0xffff},
-	{"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
-	{"", 0, 0, SROM4_BFL3, 0xffff},
-	{"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
-	{"", 0, 0, SROM5_BFL3, 0xffff},
-	{"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
-	{"", 0, 0, SROM8_BFL3, 0xffff},
-	{"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
-	{"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
-	{"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
-	{"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
-	{"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
-	{"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
-	{"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
-	{"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
-	{"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
-	{"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
-	{"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
-	{"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
-	{"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
-	{"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
-	{"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
-	{"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
-	{"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
-	{"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
-	{"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
-	{"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
-	{"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
-	{"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
-	{"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
-	{"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
-	{"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
-	{"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
-	{"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
-	{"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
-	{"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
-	{"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
-	{"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
-	{"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
-	{"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
-	{"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
-	{"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
-	{"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
-	{"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
-	{"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
-	{"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
-	{"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
-	{"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
-	{"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
-	{"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
-	{"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
-	{"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
-	{"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
-	{"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
-	{"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
-	{"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
-	{"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
-	{"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
-	{"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
-	{"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
-	{"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
-	{"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
-	{"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
-	{"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
-	{"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
-	{"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
-	{"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
-	{"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
-	{"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
-	{"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
-	{"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
-	{"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
-	{"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
-	{"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
-	{"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
-	{"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
-	{"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
-	{"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
-	{"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
-	{"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
-	{"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
-	{"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
-	{"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
-	{"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
-	{"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
-	{"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
-	{"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
-	{"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
-	{"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
-	{"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
-	{"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
-	{"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
-	{"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
-	{"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
-	{"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
-	{"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
-	{"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
-	{"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
-	{"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
-	{"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
-	{"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
-	{"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
-	{"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
-	{"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
-	{"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
-	{"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
-	{"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
-	{"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
-	{"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
-	{"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
-	{"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
-	{"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
-	{"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
-	{"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
-	{"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
-	{"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
-	{"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
-	{"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
-	{"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
-	{"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
-	{"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
-	{"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
-	{"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
-	{"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
-	{"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
-	{"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
-	{"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
-	{"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
-	{"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
-	{"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
-	{"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
-	{"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
-	{"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
-	{"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
-	{"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
-	{"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
-	{"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
-	{"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
-	{"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
-	{"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
-	{"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
-	{"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
-	{"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
-	{"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
-	{"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
-	{"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
-	{"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
-	{"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
-	{"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
-	{"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
-
-	{"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
-	{"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
-	{"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
-	{"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
-	{"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
-	{"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
-	{"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
-	{"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
-	{"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
-	{"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
-	{"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
-	{"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
-	{"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
-	{"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
-	{"rawtempsense", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
-	{"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
-	{"tempsense_slope", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
-	 0x00ff},
-	{"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
-	{"tempsense_option", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
-	 0x0300},
-	{"freqoffset_corr", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
-	 0x000f},
-	{"iqcal_swp_dis", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
-	{"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
-	{"phycal_tempdelta", 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
-
-	{"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
-	{"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
-	{"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
-	{"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
-	{"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
-	{"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
-	{"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
-	{"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
-	{"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
-	{"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
-	{"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
-	{"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
-	{"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
-	{"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
-	{"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
-	{"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
-	{"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
-	{"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
-	{"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
-	{"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
-	{"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
-	{"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
-	{"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
-	{"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
-	{"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
-	{"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
-	{"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
-	{"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
-	{"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
-	{"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
-	{"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
-	{"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
-	{"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
-	{"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
-	{"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
-	{"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
-	{"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
-	{"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
-	{"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
-	{"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
-	{"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
-	{"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
-	{"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
-	{"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
-	{"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
-	{"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
-	{"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
-	{"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
-	{"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
-	{"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
-	{"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
-	{"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
-	{"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
-	{"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
-	{"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
-	{"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
-	{"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
-	{"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
-	{"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
-	{"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
-	{"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
-	{"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
-	{"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
-	{"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
-	{"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
-	{"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
-	{"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
-	{"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
-	{"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
-	{"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
-	{"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
-	{"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
-	{"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
-	{"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
-	{"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
-	{"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
-	{"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
-	{"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
-	{"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
-	{"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
-	{"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
-	{"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
-	{"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
-	{"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
-
-	/* power per rate from sromrev 9 */
-	{"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
-	{"cckbw20ul2gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
-	{"legofdmbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
-	{"legofdmbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
-	{"legofdmbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
-	{"legofdmbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20,
-	 0xffff},
-	{"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
-	{"legofdmbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
-	{"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
-	{"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
-	{"mcsbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw405glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
-	{"mcsbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw405gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
-	{"mcsbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
-	{"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
-	{"mcsbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL,
-	 0xffff},
-	{"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
-	{"mcsbw405ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
-	{"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
-	{"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
-	{"legofdm40duppo", 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
-
-	{NULL, 0, 0, 0, 0}
-};
-
-static const sromvar_t perpath_pci_sromvars[] = {
-	{"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
-	{"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
-	{"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
-	{"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
-	{"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
-	{"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
-	{"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
-	{"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
-	{"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
-	{"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
-	{"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
-	{"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
-	{"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
-	{"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
-	{"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
-	{"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
-	{"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
-	{"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
-	{"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
-	{"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
-	{"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
-	{"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
-	{"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
-	{"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
-	{"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
-	{"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
-	{"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
-	{"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
-	{"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
-	{"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
-	{"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
-	{"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
-	{"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
-	{"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
-	{"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
-	{"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
-	{"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
-	{"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
-	{"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
-	{"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
-	{NULL, 0, 0, 0, 0}
-};
-
-#if !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP))
-#define	PHY_TYPE_N		4	/* N-Phy value */
-#define	PHY_TYPE_LP		5	/* LP-Phy value */
-#endif				/* !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */
-#if !defined(PHY_TYPE_NULL)
-#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
-#endif				/* !defined(PHY_TYPE_NULL) */
-
-typedef struct {
-	u16 phy_type;
-	u16 bandrange;
-	u16 chain;
-	const char *vars;
-} pavars_t;
-
-static const pavars_t pavars[] = {
-	/* NPHY */
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0,
-	 "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1,
-	 "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0,
-	 "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1,
-	 "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
-	/* LPPHY */
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"},
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"},
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"},
-	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"},
-	{PHY_TYPE_NULL, 0, 0, ""}
-};
-
-typedef struct {
-	u16 phy_type;
-	u16 bandrange;
-	const char *vars;
-} povars_t;
-
-static const povars_t povars[] = {
-	/* NPHY */
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,
-	 "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
-	 "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL,
-	 "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
-	 "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM,
-	 "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
-	 "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
-	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH,
-	 "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
-	 "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
-	{PHY_TYPE_NULL, 0, ""}
-};
-
-typedef struct {
-	u8 tag;		/* Broadcom subtag name */
-	u8 len;		/* Length field of the tuple, note that it includes the
-				 * subtag name (1 byte): 1 + tuple content length
-				 */
-	const char *params;
-} cis_tuple_t;
-
-#define OTP_RAW		(0xff - 1)	/* Reserved tuple number for wrvar Raw input */
-#define OTP_VERS_1	(0xff - 2)	/* CISTPL_VERS_1 */
-#define OTP_MANFID	(0xff - 3)	/* CISTPL_MANFID */
-#define OTP_RAW1	(0xff - 4)	/* Like RAW, but comes first */
-
-static const cis_tuple_t cis_hnbuvars[] = {
-	{OTP_RAW1, 0, ""},	/* special case */
-	{OTP_VERS_1, 0, "smanf sproductname"},	/* special case (non BRCM tuple) */
-	{OTP_MANFID, 4, "2manfid 2prodid"},	/* special case (non BRCM tuple) */
-	{HNBU_SROMREV, 2, "1sromrev"},
-	/* NOTE: subdevid is also written to boardtype.
-	 *       Need to write HNBU_BOARDTYPE to change it if it is different.
-	 */
-	{HNBU_CHIPID, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
-	{HNBU_BOARDREV, 3, "2boardrev"},
-	{HNBU_PAPARMS, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
-	{HNBU_AA, 3, "1aa2g 1aa5g"},
-	{HNBU_AA, 3, "1aa0 1aa1"},	/* backward compatibility */
-	{HNBU_AG, 5, "1ag0 1ag1 1ag2 1ag3"},
-	{HNBU_BOARDFLAGS, 9, "4boardflags 4boardflags2"},
-	{HNBU_LEDS, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"},
-	{HNBU_CCODE, 4, "2ccode 1cctl"},
-	{HNBU_CCKPO, 3, "2cckpo"},
-	{HNBU_OFDMPO, 5, "4ofdmpo"},
-	{HNBU_RDLID, 3, "2rdlid"},
-	{HNBU_RSSISMBXA2G, 3, "0rssismf2g 0rssismc2g 0rssisav2g 0bxa2g"},	/* special case */
-	{HNBU_RSSISMBXA5G, 3, "0rssismf5g 0rssismc5g 0rssisav5g 0bxa5g"},	/* special case */
-	{HNBU_XTALFREQ, 5, "4xtalfreq"},
-	{HNBU_TRI2G, 2, "1tri2g"},
-	{HNBU_TRI5G, 4, "1tri5gl 1tri5g 1tri5gh"},
-	{HNBU_RXPO2G, 2, "1rxpo2g"},
-	{HNBU_RXPO5G, 2, "1rxpo5g"},
-	{HNBU_BOARDNUM, 3, "2boardnum"},
-	{HNBU_MACADDR, 7, "6macaddr"},	/* special case */
-	{HNBU_RDLSN, 3, "2rdlsn"},
-	{HNBU_BOARDTYPE, 3, "2boardtype"},
-	{HNBU_LEDDC, 3, "2leddc"},
-	{HNBU_RDLRNDIS, 2, "1rdlndis"},
-	{HNBU_CHAINSWITCH, 5, "1txchain 1rxchain 2antswitch"},
-	{HNBU_REGREV, 2, "1regrev"},
-	{HNBU_FEM, 5, "0antswctl2g, 0triso2g, 0pdetrange2g, 0extpagain2g, 0tssipos2g" "0antswctl5g, 0triso5g, 0pdetrange5g, 0extpagain5g, 0tssipos5g"},	/* special case */
-	{HNBU_PAPARMS_C0, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
-	 "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 "
-	 "2pa5gw1a0 2pa5gw2a0 2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 "
-	 "2pa5ghw1a0 2pa5ghw2a0"},
-	{HNBU_PAPARMS_C1, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
-	 "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 "
-	 "2pa5gw1a1 2pa5gw2a1 2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 "
-	 "2pa5ghw1a1 2pa5ghw2a1"},
-	{HNBU_PO_CCKOFDM, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
-	 "4ofdm5ghpo"},
-	{HNBU_PO_MCS2G, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
-	 "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
-	{HNBU_PO_MCS5GM, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
-	 "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
-	{HNBU_PO_MCS5GLH, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
-	 "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
-	 "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
-	 "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
-	{HNBU_CCKFILTTYPE, 2, "1cckdigfilttype"},
-	{HNBU_PO_CDD, 3, "2cddpo"},
-	{HNBU_PO_STBC, 3, "2stbcpo"},
-	{HNBU_PO_40M, 3, "2bw40po"},
-	{HNBU_PO_40MDUP, 3, "2bwduppo"},
-	{HNBU_RDLRWU, 2, "1rdlrwu"},
-	{HNBU_WPS, 3, "1wpsgpio 1wpsled"},
-	{HNBU_USBFS, 2, "1usbfs"},
-	{HNBU_CUSTOM1, 5, "4customvar1"},
-	{OTP_RAW, 0, ""},	/* special case */
-	{HNBU_OFDMPO5G, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
-	{HNBU_USBEPNUM, 3, "2usbepnum"},
-	{0xFF, 0, ""}
-};
-
-#endif				/* _bcmsrom_tbl_h_ */
diff --git a/drivers/staging/brcm80211/include/bcmutils.h b/drivers/staging/brcm80211/include/bcmutils.h
index a8f76d8..fc2a2a9 100644
--- a/drivers/staging/brcm80211/include/bcmutils.h
+++ b/drivers/staging/brcm80211/include/bcmutils.h
@@ -54,12 +54,12 @@
 #define PKTQ_MAX_PREC           16	/* Maximum precedence levels */
 #endif
 
-	typedef struct pktq_prec {
+	struct pktq_prec {
 		struct sk_buff *head;	/* first packet to dequeue */
 		struct sk_buff *tail;	/* last packet to dequeue */
 		u16 len;		/* number of queued packets */
 		u16 max;		/* maximum number of queued packets */
-	} pktq_prec_t;
+	};
 
 /* multi-priority pkt queue */
 	struct pktq {
@@ -71,28 +71,11 @@
 		struct pktq_prec q[PKTQ_MAX_PREC];
 	};
 
-/* simple, non-priority pkt queue */
-	struct spktq {
-		u16 num_prec;	/* number of precedences in use (always 1) */
-		u16 hi_prec;	/* rapid dequeue hint (>= highest non-empty prec) */
-		u16 max;	/* total max packets */
-		u16 len;	/* total number of packets */
-		/* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */
-		struct pktq_prec q[1];
-	};
-
 #define PKTQ_PREC_ITER(pq, prec)        for (prec = (pq)->num_prec - 1; prec >= 0; prec--)
 
 /* fn(pkt, arg).  return true if pkt belongs to if */
 	typedef bool(*ifpkt_cb_t) (void *, int);
 
-/* forward definition of ether_addr structure used by some function prototypes */
-
-	struct ether_addr;
-
-	extern int ether_isbcast(const void *ea);
-	extern int ether_isnulladdr(const void *ea);
-
 /* operations on a specific precedence in packet queue */
 
 #define pktq_psetmax(pq, prec, _max)    ((pq)->q[prec].max = (_max))
@@ -111,12 +94,16 @@ extern struct sk_buff *pktq_penq_head(struct pktq *pq, int prec,
 extern struct sk_buff *pktq_pdeq(struct pktq *pq, int prec);
 extern struct sk_buff *pktq_pdeq_tail(struct pktq *pq, int prec);
 
+/* packet primitives */
+extern struct sk_buff *pkt_buf_get_skb(uint len);
+extern void pkt_buf_free_skb(struct sk_buff *skb);
+
 /* Empty the queue at particular precedence level */
 #ifdef BRCM_FULLMAC
-	extern void pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec,
+	extern void pktq_pflush(struct pktq *pq, int prec,
 		bool dir);
 #else
-	extern void pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec,
+	extern void pktq_pflush(struct pktq *pq, int prec,
 		bool dir, ifpkt_cb_t fn, int arg);
 #endif /* BRCM_FULLMAC */
 
@@ -144,20 +131,20 @@ extern struct sk_buff *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
 /* prec_out may be NULL if caller is not interested in return value */
 	extern struct sk_buff *pktq_peek_tail(struct pktq *pq, int *prec_out);
 #ifdef BRCM_FULLMAC
-	extern void pktq_flush(struct osl_info *osh, struct pktq *pq, bool dir);
+	extern void pktq_flush(struct pktq *pq, bool dir);
 #else
-	extern void pktq_flush(struct osl_info *osh, struct pktq *pq, bool dir,
+	extern void pktq_flush(struct pktq *pq, bool dir,
 		ifpkt_cb_t fn, int arg);
 #endif
 
 /* externs */
 /* packet */
-	extern uint pktfrombuf(struct osl_info *osh, struct sk_buff *p,
+	extern uint pktfrombuf(struct sk_buff *p,
 			       uint offset, int len, unsigned char *buf);
-	extern uint pkttotlen(struct osl_info *osh, struct sk_buff *p);
+	extern uint pkttotlen(struct sk_buff *p);
 
 /* ethernet address */
-	extern int bcm_ether_atoe(char *p, struct ether_addr *ea);
+	extern int bcm_ether_atoe(char *p, u8 *ea);
 
 /* ip address */
 	struct ipv4_addr;
@@ -167,9 +154,11 @@ extern struct sk_buff *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
 	extern char *getvar(char *vars, const char *name);
 	extern int getintvar(char *vars, const char *name);
 #ifdef BCMDBG
-	extern void prpkt(const char *msg, struct osl_info *osh,
-			  struct sk_buff *p0);
+	extern void prpkt(const char *msg, struct sk_buff *p0);
+#else
+#define prpkt(a, b)
 #endif				/* BCMDBG */
+
 #define bcm_perf_enable()
 #define bcmstats(fmt)
 #define	bcmlog(fmt, a1, a2)
@@ -369,12 +358,142 @@ extern struct sk_buff *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
 #define REG_MAP(pa, size)       (void *)(0)
 #endif
 
-/* Register operations */
-#define AND_REG(osh, r, v)	W_REG(osh, (r), R_REG(osh, r) & (v))
-#define OR_REG(osh, r, v)	W_REG(osh, (r), R_REG(osh, r) | (v))
+extern u32 g_assert_type;
+
+#if defined(BCMDBG_ASSERT)
+#define ASSERT(exp) \
+	  do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
+extern void osl_assert(char *exp, char *file, int line);
+#else
+#define ASSERT(exp)	do {} while (0)
+#endif  /* defined(BCMDBG_ASSERT) */
+
+/* register access macros */
+#if defined(BCMSDIO)
+#ifdef BRCM_FULLMAC
+#include <bcmsdh.h>
+#endif
+#define OSL_WRITE_REG(r, v) \
+		(bcmsdh_reg_write(NULL, (unsigned long)(r), sizeof(*(r)), (v)))
+#define OSL_READ_REG(r) \
+		(bcmsdh_reg_read(NULL, (unsigned long)(r), sizeof(*(r))))
+#endif
+
+#if defined(BCMSDIO)
+#define SELECT_BUS_WRITE(mmap_op, bus_op) bus_op
+#define SELECT_BUS_READ(mmap_op, bus_op) bus_op
+#else
+#define SELECT_BUS_WRITE(mmap_op, bus_op) mmap_op
+#define SELECT_BUS_READ(mmap_op, bus_op) mmap_op
+#endif
+
+/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
+#define	PKTBUFSZ	2048
 
-#define SET_REG(osh, r, mask, val) \
-		W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val)))
+#define OSL_SYSUPTIME()		((u32)jiffies * (1000 / HZ))
+#ifdef BRCM_FULLMAC
+#include <linux/kernel.h>	/* for vsn/printf's */
+#include <linux/string.h>	/* for mem*, str* */
+#endif
+/* bcopy's: Linux kernel doesn't provide these (anymore) */
+#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
+
+/* register access macros */
+#ifndef IL_BIGENDIAN
+#ifndef __mips__
+#define R_REG(r) (\
+	SELECT_BUS_READ(sizeof(*(r)) == sizeof(u8) ? \
+	readb((volatile u8*)(r)) : \
+	sizeof(*(r)) == sizeof(u16) ? readw((volatile u16*)(r)) : \
+	readl((volatile u32*)(r)), OSL_READ_REG(r)) \
+)
+#else				/* __mips__ */
+#define R_REG(r) (\
+	SELECT_BUS_READ( \
+		({ \
+			__typeof(*(r)) __osl_v; \
+			__asm__ __volatile__("sync"); \
+			switch (sizeof(*(r))) { \
+			case sizeof(u8): \
+				__osl_v = readb((volatile u8*)(r)); \
+				break; \
+			case sizeof(u16): \
+				__osl_v = readw((volatile u16*)(r)); \
+				break; \
+			case sizeof(u32): \
+				__osl_v = \
+				readl((volatile u32*)(r)); \
+				break; \
+			} \
+			__asm__ __volatile__("sync"); \
+			__osl_v; \
+		}), \
+		({ \
+			__typeof(*(r)) __osl_v; \
+			__asm__ __volatile__("sync"); \
+			__osl_v = OSL_READ_REG(r); \
+			__asm__ __volatile__("sync"); \
+			__osl_v; \
+		})) \
+)
+#endif				/* __mips__ */
+
+#define W_REG(r, v) do { \
+	SELECT_BUS_WRITE( \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8): \
+			writeb((u8)(v), (volatile u8*)(r)); break; \
+		case sizeof(u16): \
+			writew((u16)(v), (volatile u16*)(r)); break; \
+		case sizeof(u32): \
+			writel((u32)(v), (volatile u32*)(r)); break; \
+		}, \
+		(OSL_WRITE_REG(r, v))); \
+	} while (0)
+#else				/* IL_BIGENDIAN */
+#define R_REG(r) (\
+	SELECT_BUS_READ( \
+		({ \
+			__typeof(*(r)) __osl_v; \
+			switch (sizeof(*(r))) { \
+			case sizeof(u8): \
+				__osl_v = \
+				readb((volatile u8*)((r)^3)); \
+				break; \
+			case sizeof(u16): \
+				__osl_v = \
+				readw((volatile u16*)((r)^2)); \
+				break; \
+			case sizeof(u32): \
+				__osl_v = readl((volatile u32*)(r)); \
+				break; \
+			} \
+			__osl_v; \
+		}), \
+		OSL_READ_REG(r)) \
+)
+#define W_REG(r, v) do { \
+	SELECT_BUS_WRITE( \
+		switch (sizeof(*(r))) { \
+		case sizeof(u8):	\
+			writeb((u8)(v), \
+			(volatile u8*)((r)^3)); break; \
+		case sizeof(u16):	\
+			writew((u16)(v), \
+			(volatile u16*)((r)^2)); break; \
+		case sizeof(u32):	\
+			writel((u32)(v), \
+			(volatile u32*)(r)); break; \
+		}, \
+		(OSL_WRITE_REG(r, v))); \
+	} while (0)
+#endif				/* IL_BIGENDIAN */
+
+#define AND_REG(r, v)	W_REG((r), R_REG(r) & (v))
+#define OR_REG(r, v)	W_REG((r), R_REG(r) | (v))
+
+#define SET_REG(r, mask, val) \
+		W_REG((r), ((R_REG(r) & ~(mask)) | (val)))
 
 #ifndef setbit
 #ifndef NBBY			/* the BSD family defines NBBY */
@@ -498,19 +617,9 @@ extern struct sk_buff *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out);
 	extern u16 bcm_qdbm_to_mw(u8 qdbm);
 	extern u8 bcm_mw_to_qdbm(u16 mw);
 
-/* generic datastruct to help dump routines */
-	struct fielddesc {
-		const char *nameandfmt;
-		u32 offset;
-		u32 len;
-	};
-
 	extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
 	extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...);
 
-	typedef u32(*bcmutl_rdreg_rtn) (void *arg0, uint arg1,
-					   u32 offset);
-
 	extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf,
 				uint len);
 	extern uint bcm_bitcount(u8 *bitmap, uint bytelength);
diff --git a/drivers/staging/brcm80211/include/bcmwifi.h b/drivers/staging/brcm80211/include/bcmwifi.h
index 4067fba..4a0f976 100644
--- a/drivers/staging/brcm80211/include/bcmwifi.h
+++ b/drivers/staging/brcm80211/include/bcmwifi.h
@@ -144,13 +144,6 @@ extern bool wf_chspec_malformed(chanspec_t chanspec);
 extern u8 wf_chspec_ctlchan(chanspec_t chspec);
 
 /*
- * This function returns the chanspec that control traffic is being sent on, for legacy
- * channels this is just the chanspec, for 40MHZ channels it is the upper or lowre 20MHZ
- * sideband depending on the chanspec selected
- */
-extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
-
-/*
  * Return the channel number for a given frequency and base frequency.
  * The returned channel number is relative to the given base frequency.
  * If the given base frequency is zero, a base frequency of 5 GHz is assumed for
@@ -171,22 +164,4 @@ extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec);
  */
 extern int wf_mhz2channel(uint freq, uint start_factor);
 
-/*
- * Return the center frequency in MHz of the given channel and base frequency.
- * The channel number is interpreted relative to the given base frequency.
- *
- * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_5_G are defined for
- * 2.4 GHz and 5 GHz bands.
- * The channel range of [1, 14] is only checked for a start_factor of
- * WF_CHAN_FACTOR_2_4_G (4814).
- * Odd start_factors produce channels on .5 MHz boundaries, in which case
- * the answer is rounded down to an integral MHz.
- * -1 is returned for an out of range channel.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-extern int wf_channel2mhz(uint channel, uint start_factor);
-
 #endif				/* _bcmwifi_h_ */
diff --git a/drivers/staging/brcm80211/include/d11.h b/drivers/staging/brcm80211/include/d11.h
deleted file mode 100644
index be2d497..0000000
--- a/drivers/staging/brcm80211/include/d11.h
+++ /dev/null
@@ -1,1771 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_D11_H
-#define	_D11_H
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-#ifndef WL_RSSI_ANT_MAX
-#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
-#elif WL_RSSI_ANT_MAX != 4
-#error "WL_RSSI_ANT_MAX does not match"
-#endif
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef	PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-#define	BCN_TMPL_LEN		512	/* length of the BCN template area */
-
-/* RX FIFO numbers */
-#define	RX_FIFO			0	/* data and ctl frames */
-#define	RX_TXSTATUS_FIFO	3	/* RX fifo for tx status packages */
-
-/* TX FIFO numbers using WME Access Classes */
-#define	TX_AC_BK_FIFO		0	/* Access Category Background TX FIFO */
-#define	TX_AC_BE_FIFO		1	/* Access Category Best-Effort TX FIFO */
-#define	TX_AC_VI_FIFO		2	/* Access Class Video TX FIFO */
-#define	TX_AC_VO_FIFO		3	/* Access Class Voice TX FIFO */
-#define	TX_BCMC_FIFO		4	/* Broadcast/Multicast TX FIFO */
-#define	TX_ATIM_FIFO		5	/* TX fifo for ATIM window info */
-
-/* Addr is byte address used by SW; offset is word offset used by uCode */
-
-/* Per AC TX limit settings */
-#define M_AC_TXLMT_BASE_ADDR         (0x180 * 2)
-#define M_AC_TXLMT_ADDR(_ac)         (M_AC_TXLMT_BASE_ADDR + (2 * (_ac)))
-
-/* Legacy TX FIFO numbers */
-#define	TX_DATA_FIFO		TX_AC_BE_FIFO
-#define	TX_CTL_FIFO		TX_AC_VO_FIFO
-
-typedef volatile struct {
-	u32 intstatus;
-	u32 intmask;
-} intctrlregs_t;
-
-/* read: 32-bit register that can be read as 32-bit or as 2 16-bit
- * write: only low 16b-it half can be written
- */
-typedef volatile union {
-	u32 pmqhostdata;	/* read only! */
-	struct {
-		u16 pmqctrlstatus;	/* read/write */
-		u16 PAD;
-	} w;
-} pmqreg_t;
-
-/* pio register set 2/4 bytes union for d11 fifo */
-typedef volatile union {
-	pio2regp_t b2;		/* < corerev 8 */
-	pio4regp_t b4;		/* >= corerev 8 */
-} u_pioreg_t;
-
-/* dma/pio corerev < 11 */
-typedef volatile struct {
-	dma32regp_t dmaregs[8];	/* 0x200 - 0x2fc */
-	u_pioreg_t pioregs[8];	/* 0x300 */
-} fifo32_t;
-
-/* dma/pio corerev >= 11 */
-typedef volatile struct {
-	dma64regs_t dmaxmt;	/* dma tx */
-	pio4regs_t piotx;	/* pio tx */
-	dma64regs_t dmarcv;	/* dma rx */
-	pio4regs_t piorx;	/* pio rx */
-} fifo64_t;
-
-/*
- * Host Interface Registers
- * - primed from hnd_cores/dot11mac/systemC/registers/ihr.h
- * - but definitely not complete
- */
-typedef volatile struct _d11regs {
-	/* Device Control ("semi-standard host registers") */
-	u32 PAD[3];		/* 0x0 - 0x8 */
-	u32 biststatus;	/* 0xC */
-	u32 biststatus2;	/* 0x10 */
-	u32 PAD;		/* 0x14 */
-	u32 gptimer;		/* 0x18 *//* for corerev >= 3 */
-	u32 usectimer;	/* 0x1c *//* for corerev >= 26 */
-
-	/* Interrupt Control *//* 0x20 */
-	intctrlregs_t intctrlregs[8];
-
-	u32 PAD[40];		/* 0x60 - 0xFC */
-
-	/* tx fifos 6-7 and rx fifos 1-3 removed in corerev 5 */
-	u32 intrcvlazy[4];	/* 0x100 - 0x10C */
-
-	u32 PAD[4];		/* 0x110 - 0x11c */
-
-	u32 maccontrol;	/* 0x120 */
-	u32 maccommand;	/* 0x124 */
-	u32 macintstatus;	/* 0x128 */
-	u32 macintmask;	/* 0x12C */
-
-	/* Transmit Template Access */
-	u32 tplatewrptr;	/* 0x130 */
-	u32 tplatewrdata;	/* 0x134 */
-	u32 PAD[2];		/* 0x138 - 0x13C */
-
-	/* PMQ registers */
-	pmqreg_t pmqreg;	/* 0x140 */
-	u32 pmqpatl;		/* 0x144 */
-	u32 pmqpath;		/* 0x148 */
-	u32 PAD;		/* 0x14C */
-
-	u32 chnstatus;	/* 0x150 */
-	u32 psmdebug;	/* 0x154 *//* for corerev >= 3 */
-	u32 phydebug;	/* 0x158 *//* for corerev >= 3 */
-	u32 machwcap;	/* 0x15C *//* Corerev >= 13 */
-
-	/* Extended Internal Objects */
-	u32 objaddr;		/* 0x160 */
-	u32 objdata;		/* 0x164 */
-	u32 PAD[2];		/* 0x168 - 0x16c */
-
-	/* New txstatus registers on corerev >= 5 */
-	u32 frmtxstatus;	/* 0x170 */
-	u32 frmtxstatus2;	/* 0x174 */
-	u32 PAD[2];		/* 0x178 - 0x17c */
-
-	/* New TSF host access on corerev >= 3 */
-
-	u32 tsf_timerlow;	/* 0x180 */
-	u32 tsf_timerhigh;	/* 0x184 */
-	u32 tsf_cfprep;	/* 0x188 */
-	u32 tsf_cfpstart;	/* 0x18c */
-	u32 tsf_cfpmaxdur32;	/* 0x190 */
-	u32 PAD[3];		/* 0x194 - 0x19c */
-
-	u32 maccontrol1;	/* 0x1a0 */
-	u32 machwcap1;	/* 0x1a4 */
-	u32 PAD[14];		/* 0x1a8 - 0x1dc */
-
-	/* Clock control and hardware workarounds (corerev >= 13) */
-	u32 clk_ctl_st;	/* 0x1e0 */
-	u32 hw_war;
-	u32 d11_phypllctl;	/* 0x1e8 (corerev == 16), the phypll request/avail bits are
-				 *   moved to clk_ctl_st for corerev >= 17
-				 */
-	u32 PAD[5];		/* 0x1ec - 0x1fc */
-
-	/* 0x200-0x37F dma/pio registers */
-	volatile union {
-		fifo32_t f32regs;	/* tx fifos 6-7 and rx fifos 1-3 (corerev < 5) */
-		fifo64_t f64regs[6];	/* on corerev >= 11 */
-	} fifo;
-
-	/* FIFO diagnostic port access */
-	dma32diag_t dmafifo;	/* 0x380 - 0x38C */
-
-	u32 aggfifocnt;	/* 0x390 */
-	u32 aggfifodata;	/* 0x394 */
-	u32 PAD[16];		/* 0x398 - 0x3d4 */
-	u16 radioregaddr;	/* 0x3d8 */
-	u16 radioregdata;	/* 0x3da */
-
-	/* time delay between the change on rf disable input and radio shutdown corerev 10 */
-	u32 rfdisabledly;	/* 0x3DC */
-
-	/* PHY register access */
-	u16 phyversion;	/* 0x3e0 - 0x0 */
-	u16 phybbconfig;	/* 0x3e2 - 0x1 */
-	u16 phyadcbias;	/* 0x3e4 - 0x2  Bphy only */
-	u16 phyanacore;	/* 0x3e6 - 0x3  pwwrdwn on aphy */
-	u16 phyrxstatus0;	/* 0x3e8 - 0x4 */
-	u16 phyrxstatus1;	/* 0x3ea - 0x5 */
-	u16 phycrsth;	/* 0x3ec - 0x6 */
-	u16 phytxerror;	/* 0x3ee - 0x7 */
-	u16 phychannel;	/* 0x3f0 - 0x8 */
-	u16 PAD[1];		/* 0x3f2 - 0x9 */
-	u16 phytest;		/* 0x3f4 - 0xa */
-	u16 phy4waddr;	/* 0x3f6 - 0xb */
-	u16 phy4wdatahi;	/* 0x3f8 - 0xc */
-	u16 phy4wdatalo;	/* 0x3fa - 0xd */
-	u16 phyregaddr;	/* 0x3fc - 0xe */
-	u16 phyregdata;	/* 0x3fe - 0xf */
-
-	/* IHR *//* 0x400 - 0x7FE */
-
-	/* RXE Block */
-	u16 PAD[3];		/* 0x400 - 0x406 */
-	u16 rcv_fifo_ctl;	/* 0x406 */
-	u16 PAD;		/* 0x408 - 0x40a */
-	u16 rcv_frm_cnt;	/* 0x40a */
-	u16 PAD[4];		/* 0x40a - 0x414 */
-	u16 rssi;		/* 0x414 */
-	u16 PAD[5];		/* 0x414 - 0x420 */
-	u16 rcm_ctl;		/* 0x420 */
-	u16 rcm_mat_data;	/* 0x422 */
-	u16 rcm_mat_mask;	/* 0x424 */
-	u16 rcm_mat_dly;	/* 0x426 */
-	u16 rcm_cond_mask_l;	/* 0x428 */
-	u16 rcm_cond_mask_h;	/* 0x42A */
-	u16 rcm_cond_dly;	/* 0x42C */
-	u16 PAD[1];		/* 0x42E */
-	u16 ext_ihr_addr;	/* 0x430 */
-	u16 ext_ihr_data;	/* 0x432 */
-	u16 rxe_phyrs_2;	/* 0x434 */
-	u16 rxe_phyrs_3;	/* 0x436 */
-	u16 phy_mode;	/* 0x438 */
-	u16 rcmta_ctl;	/* 0x43a */
-	u16 rcmta_size;	/* 0x43c */
-	u16 rcmta_addr0;	/* 0x43e */
-	u16 rcmta_addr1;	/* 0x440 */
-	u16 rcmta_addr2;	/* 0x442 */
-	u16 PAD[30];		/* 0x444 - 0x480 */
-
-	/* PSM Block *//* 0x480 - 0x500 */
-
-	u16 PAD;		/* 0x480 */
-	u16 psm_maccontrol_h;	/* 0x482 */
-	u16 psm_macintstatus_l;	/* 0x484 */
-	u16 psm_macintstatus_h;	/* 0x486 */
-	u16 psm_macintmask_l;	/* 0x488 */
-	u16 psm_macintmask_h;	/* 0x48A */
-	u16 PAD;		/* 0x48C */
-	u16 psm_maccommand;	/* 0x48E */
-	u16 psm_brc;		/* 0x490 */
-	u16 psm_phy_hdr_param;	/* 0x492 */
-	u16 psm_postcard;	/* 0x494 */
-	u16 psm_pcard_loc_l;	/* 0x496 */
-	u16 psm_pcard_loc_h;	/* 0x498 */
-	u16 psm_gpio_in;	/* 0x49A */
-	u16 psm_gpio_out;	/* 0x49C */
-	u16 psm_gpio_oe;	/* 0x49E */
-
-	u16 psm_bred_0;	/* 0x4A0 */
-	u16 psm_bred_1;	/* 0x4A2 */
-	u16 psm_bred_2;	/* 0x4A4 */
-	u16 psm_bred_3;	/* 0x4A6 */
-	u16 psm_brcl_0;	/* 0x4A8 */
-	u16 psm_brcl_1;	/* 0x4AA */
-	u16 psm_brcl_2;	/* 0x4AC */
-	u16 psm_brcl_3;	/* 0x4AE */
-	u16 psm_brpo_0;	/* 0x4B0 */
-	u16 psm_brpo_1;	/* 0x4B2 */
-	u16 psm_brpo_2;	/* 0x4B4 */
-	u16 psm_brpo_3;	/* 0x4B6 */
-	u16 psm_brwk_0;	/* 0x4B8 */
-	u16 psm_brwk_1;	/* 0x4BA */
-	u16 psm_brwk_2;	/* 0x4BC */
-	u16 psm_brwk_3;	/* 0x4BE */
-
-	u16 psm_base_0;	/* 0x4C0 */
-	u16 psm_base_1;	/* 0x4C2 */
-	u16 psm_base_2;	/* 0x4C4 */
-	u16 psm_base_3;	/* 0x4C6 */
-	u16 psm_base_4;	/* 0x4C8 */
-	u16 psm_base_5;	/* 0x4CA */
-	u16 psm_base_6;	/* 0x4CC */
-	u16 psm_pc_reg_0;	/* 0x4CE */
-	u16 psm_pc_reg_1;	/* 0x4D0 */
-	u16 psm_pc_reg_2;	/* 0x4D2 */
-	u16 psm_pc_reg_3;	/* 0x4D4 */
-	u16 PAD[0xD];	/* 0x4D6 - 0x4DE */
-	u16 psm_corectlsts;	/* 0x4f0 *//* Corerev >= 13 */
-	u16 PAD[0x7];	/* 0x4f2 - 0x4fE */
-
-	/* TXE0 Block *//* 0x500 - 0x580 */
-	u16 txe_ctl;		/* 0x500 */
-	u16 txe_aux;		/* 0x502 */
-	u16 txe_ts_loc;	/* 0x504 */
-	u16 txe_time_out;	/* 0x506 */
-	u16 txe_wm_0;	/* 0x508 */
-	u16 txe_wm_1;	/* 0x50A */
-	u16 txe_phyctl;	/* 0x50C */
-	u16 txe_status;	/* 0x50E */
-	u16 txe_mmplcp0;	/* 0x510 */
-	u16 txe_mmplcp1;	/* 0x512 */
-	u16 txe_phyctl1;	/* 0x514 */
-
-	u16 PAD[0x05];	/* 0x510 - 0x51E */
-
-	/* Transmit control */
-	u16 xmtfifodef;	/* 0x520 */
-	u16 xmtfifo_frame_cnt;	/* 0x522 *//* Corerev >= 16 */
-	u16 xmtfifo_byte_cnt;	/* 0x524 *//* Corerev >= 16 */
-	u16 xmtfifo_head;	/* 0x526 *//* Corerev >= 16 */
-	u16 xmtfifo_rd_ptr;	/* 0x528 *//* Corerev >= 16 */
-	u16 xmtfifo_wr_ptr;	/* 0x52A *//* Corerev >= 16 */
-	u16 xmtfifodef1;	/* 0x52C *//* Corerev >= 16 */
-
-	u16 PAD[0x09];	/* 0x52E - 0x53E */
-
-	u16 xmtfifocmd;	/* 0x540 */
-	u16 xmtfifoflush;	/* 0x542 */
-	u16 xmtfifothresh;	/* 0x544 */
-	u16 xmtfifordy;	/* 0x546 */
-	u16 xmtfifoprirdy;	/* 0x548 */
-	u16 xmtfiforqpri;	/* 0x54A */
-	u16 xmttplatetxptr;	/* 0x54C */
-	u16 PAD;		/* 0x54E */
-	u16 xmttplateptr;	/* 0x550 */
-	u16 smpl_clct_strptr;	/* 0x552 *//* Corerev >= 22 */
-	u16 smpl_clct_stpptr;	/* 0x554 *//* Corerev >= 22 */
-	u16 smpl_clct_curptr;	/* 0x556 *//* Corerev >= 22 */
-	u16 PAD[0x04];	/* 0x558 - 0x55E */
-	u16 xmttplatedatalo;	/* 0x560 */
-	u16 xmttplatedatahi;	/* 0x562 */
-
-	u16 PAD[2];		/* 0x564 - 0x566 */
-
-	u16 xmtsel;		/* 0x568 */
-	u16 xmttxcnt;	/* 0x56A */
-	u16 xmttxshmaddr;	/* 0x56C */
-
-	u16 PAD[0x09];	/* 0x56E - 0x57E */
-
-	/* TXE1 Block */
-	u16 PAD[0x40];	/* 0x580 - 0x5FE */
-
-	/* TSF Block */
-	u16 PAD[0X02];	/* 0x600 - 0x602 */
-	u16 tsf_cfpstrt_l;	/* 0x604 */
-	u16 tsf_cfpstrt_h;	/* 0x606 */
-	u16 PAD[0X05];	/* 0x608 - 0x610 */
-	u16 tsf_cfppretbtt;	/* 0x612 */
-	u16 PAD[0XD];	/* 0x614 - 0x62C */
-	u16 tsf_clk_frac_l;	/* 0x62E */
-	u16 tsf_clk_frac_h;	/* 0x630 */
-	u16 PAD[0X14];	/* 0x632 - 0x658 */
-	u16 tsf_random;	/* 0x65A */
-	u16 PAD[0x05];	/* 0x65C - 0x664 */
-	/* GPTimer 2 registers are corerev >= 3 */
-	u16 tsf_gpt2_stat;	/* 0x666 */
-	u16 tsf_gpt2_ctr_l;	/* 0x668 */
-	u16 tsf_gpt2_ctr_h;	/* 0x66A */
-	u16 tsf_gpt2_val_l;	/* 0x66C */
-	u16 tsf_gpt2_val_h;	/* 0x66E */
-	u16 tsf_gptall_stat;	/* 0x670 */
-	u16 PAD[0x07];	/* 0x672 - 0x67E */
-
-	/* IFS Block */
-	u16 ifs_sifs_rx_tx_tx;	/* 0x680 */
-	u16 ifs_sifs_nav_tx;	/* 0x682 */
-	u16 ifs_slot;	/* 0x684 */
-	u16 PAD;		/* 0x686 */
-	u16 ifs_ctl;		/* 0x688 */
-	u16 PAD[0x3];	/* 0x68a - 0x68F */
-	u16 ifsstat;		/* 0x690 */
-	u16 ifsmedbusyctl;	/* 0x692 */
-	u16 iftxdur;		/* 0x694 */
-	u16 PAD[0x3];	/* 0x696 - 0x69b */
-	/* EDCF support in dot11macs with corerevs >= 16 */
-	u16 ifs_aifsn;	/* 0x69c */
-	u16 ifs_ctl1;	/* 0x69e */
-
-	/* New slow clock registers on corerev >= 5 */
-	u16 scc_ctl;		/* 0x6a0 */
-	u16 scc_timer_l;	/* 0x6a2 */
-	u16 scc_timer_h;	/* 0x6a4 */
-	u16 scc_frac;	/* 0x6a6 */
-	u16 scc_fastpwrup_dly;	/* 0x6a8 */
-	u16 scc_per;		/* 0x6aa */
-	u16 scc_per_frac;	/* 0x6ac */
-	u16 scc_cal_timer_l;	/* 0x6ae */
-	u16 scc_cal_timer_h;	/* 0x6b0 */
-	u16 PAD;		/* 0x6b2 */
-
-	u16 PAD[0x26];
-
-	/* NAV Block */
-	u16 nav_ctl;		/* 0x700 */
-	u16 navstat;		/* 0x702 */
-	u16 PAD[0x3e];	/* 0x702 - 0x77E */
-
-	/* WEP/PMQ Block *//* 0x780 - 0x7FE */
-	u16 PAD[0x20];	/* 0x780 - 0x7BE */
-
-	u16 wepctl;		/* 0x7C0 */
-	u16 wepivloc;	/* 0x7C2 */
-	u16 wepivkey;	/* 0x7C4 */
-	u16 wepwkey;		/* 0x7C6 */
-
-	u16 PAD[4];		/* 0x7C8 - 0x7CE */
-	u16 pcmctl;		/* 0X7D0 */
-	u16 pcmstat;		/* 0X7D2 */
-	u16 PAD[6];		/* 0x7D4 - 0x7DE */
-
-	u16 pmqctl;		/* 0x7E0 */
-	u16 pmqstatus;	/* 0x7E2 */
-	u16 pmqpat0;		/* 0x7E4 */
-	u16 pmqpat1;		/* 0x7E6 */
-	u16 pmqpat2;		/* 0x7E8 */
-
-	u16 pmqdat;		/* 0x7EA */
-	u16 pmqdator;	/* 0x7EC */
-	u16 pmqhst;		/* 0x7EE */
-	u16 pmqpath0;	/* 0x7F0 */
-	u16 pmqpath1;	/* 0x7F2 */
-	u16 pmqpath2;	/* 0x7F4 */
-	u16 pmqdath;		/* 0x7F6 */
-
-	u16 PAD[0x04];	/* 0x7F8 - 0x7FE */
-
-	/* SHM *//* 0x800 - 0xEFE */
-	u16 PAD[0x380];	/* 0x800 - 0xEFE */
-
-	/* SB configuration registers: 0xF00 */
-	sbconfig_t sbconfig;	/* sb config regs occupy top 256 bytes */
-} d11regs_t;
-
-#define	PIHR_BASE	0x0400	/* byte address of packed IHR region */
-
-/* biststatus */
-#define	BT_DONE		(1U << 31)	/* bist done */
-#define	BT_B2S		(1 << 30)	/* bist2 ram summary bit */
-
-/* intstatus and intmask */
-#define	I_PC		(1 << 10)	/* pci descriptor error */
-#define	I_PD		(1 << 11)	/* pci data error */
-#define	I_DE		(1 << 12)	/* descriptor protocol error */
-#define	I_RU		(1 << 13)	/* receive descriptor underflow */
-#define	I_RO		(1 << 14)	/* receive fifo overflow */
-#define	I_XU		(1 << 15)	/* transmit fifo underflow */
-#define	I_RI		(1 << 16)	/* receive interrupt */
-#define	I_XI		(1 << 24)	/* transmit interrupt */
-
-/* interrupt receive lazy */
-#define	IRL_TO_MASK		0x00ffffff	/* timeout */
-#define	IRL_FC_MASK		0xff000000	/* frame count */
-#define	IRL_FC_SHIFT		24	/* frame count */
-
-/* maccontrol register */
-#define	MCTL_GMODE		(1U << 31)
-#define	MCTL_DISCARD_PMQ	(1 << 30)
-#define	MCTL_WAKE		(1 << 26)
-#define	MCTL_HPS		(1 << 25)
-#define	MCTL_PROMISC		(1 << 24)
-#define	MCTL_KEEPBADFCS		(1 << 23)
-#define	MCTL_KEEPCONTROL	(1 << 22)
-#define	MCTL_PHYLOCK		(1 << 21)
-#define	MCTL_BCNS_PROMISC	(1 << 20)
-#define	MCTL_LOCK_RADIO		(1 << 19)
-#define	MCTL_AP			(1 << 18)
-#define	MCTL_INFRA		(1 << 17)
-#define	MCTL_BIGEND		(1 << 16)
-#define	MCTL_GPOUT_SEL_MASK	(3 << 14)
-#define	MCTL_GPOUT_SEL_SHIFT	14
-#define	MCTL_EN_PSMDBG		(1 << 13)
-#define	MCTL_IHR_EN		(1 << 10)
-#define	MCTL_SHM_UPPER		(1 <<  9)
-#define	MCTL_SHM_EN		(1 <<  8)
-#define	MCTL_PSM_JMP_0		(1 <<  2)
-#define	MCTL_PSM_RUN		(1 <<  1)
-#define	MCTL_EN_MAC		(1 <<  0)
-
-/* maccommand register */
-#define	MCMD_BCN0VLD		(1 <<  0)
-#define	MCMD_BCN1VLD		(1 <<  1)
-#define	MCMD_DIRFRMQVAL		(1 <<  2)
-#define	MCMD_CCA		(1 <<  3)
-#define	MCMD_BG_NOISE		(1 <<  4)
-#define	MCMD_SKIP_SHMINIT	(1 <<  5)	/* only used for simulation */
-#define MCMD_SAMPLECOLL		MCMD_SKIP_SHMINIT	/* reuse for sample collect */
-
-/* macintstatus/macintmask */
-#define	MI_MACSSPNDD		(1 <<  0)	/* MAC has gracefully suspended */
-#define	MI_BCNTPL		(1 <<  1)	/* beacon template available */
-#define	MI_TBTT			(1 <<  2)	/* TBTT indication */
-#define	MI_BCNSUCCESS		(1 <<  3)	/* beacon successfully tx'd */
-#define	MI_BCNCANCLD		(1 <<  4)	/* beacon canceled (IBSS) */
-#define	MI_ATIMWINEND		(1 <<  5)	/* end of ATIM-window (IBSS) */
-#define	MI_PMQ			(1 <<  6)	/* PMQ entries available */
-#define	MI_NSPECGEN_0		(1 <<  7)	/* non-specific gen-stat bits that are set by PSM */
-#define	MI_NSPECGEN_1		(1 <<  8)	/* non-specific gen-stat bits that are set by PSM */
-#define	MI_MACTXERR		(1 <<  9)	/* MAC level Tx error */
-#define	MI_NSPECGEN_3		(1 << 10)	/* non-specific gen-stat bits that are set by PSM */
-#define	MI_PHYTXERR		(1 << 11)	/* PHY Tx error */
-#define	MI_PME			(1 << 12)	/* Power Management Event */
-#define	MI_GP0			(1 << 13)	/* General-purpose timer0 */
-#define	MI_GP1			(1 << 14)	/* General-purpose timer1 */
-#define	MI_DMAINT		(1 << 15)	/* (ORed) DMA-interrupts */
-#define	MI_TXSTOP		(1 << 16)	/* MAC has completed a TX FIFO Suspend/Flush */
-#define	MI_CCA			(1 << 17)	/* MAC has completed a CCA measurement */
-#define	MI_BG_NOISE		(1 << 18)	/* MAC has collected background noise samples */
-#define	MI_DTIM_TBTT		(1 << 19)	/* MBSS DTIM TBTT indication */
-#define MI_PRQ			(1 << 20)	/* Probe response queue needs attention */
-#define	MI_PWRUP		(1 << 21)	/* Radio/PHY has been powered back up. */
-#define	MI_RESERVED3		(1 << 22)
-#define	MI_RESERVED2		(1 << 23)
-#define MI_RESERVED1		(1 << 25)
-#define MI_RFDISABLE		(1 << 28)	/* MAC detected a change on RF Disable input
-						 * (corerev >= 10)
-						 */
-#define	MI_TFS			(1 << 29)	/* MAC has completed a TX (corerev >= 5) */
-#define	MI_PHYCHANGED		(1 << 30)	/* A phy status change wrt G mode */
-#define	MI_TO			(1U << 31)	/* general purpose timeout (corerev >= 3) */
-
-/* Mac capabilities registers */
-/* machwcap */
-#define	MCAP_TKIPMIC		0x80000000	/* TKIP MIC hardware present */
-
-/* pmqhost data */
-#define	PMQH_DATA_MASK		0xffff0000	/* data entry of head pmq entry */
-#define	PMQH_BSSCFG		0x00100000	/* PM entry for BSS config */
-#define	PMQH_PMOFF		0x00010000	/* PM Mode OFF: power save off */
-#define	PMQH_PMON		0x00020000	/* PM Mode ON: power save on */
-#define	PMQH_DASAT		0x00040000	/* Dis-associated or De-authenticated */
-#define	PMQH_ATIMFAIL		0x00080000	/* ATIM not acknowledged */
-#define	PMQH_DEL_ENTRY		0x00000001	/* delete head entry */
-#define	PMQH_DEL_MULT		0x00000002	/* delete head entry to cur read pointer -1 */
-#define	PMQH_OFLO		0x00000004	/* pmq overflow indication */
-#define	PMQH_NOT_EMPTY		0x00000008	/* entries are present in pmq */
-
-/* phydebug (corerev >= 3) */
-#define	PDBG_CRS		(1 << 0)	/* phy is asserting carrier sense */
-#define	PDBG_TXA		(1 << 1)	/* phy is taking xmit byte from mac this cycle */
-#define	PDBG_TXF		(1 << 2)	/* mac is instructing the phy to transmit a frame */
-#define	PDBG_TXE		(1 << 3)	/* phy is signalling a transmit Error to the mac */
-#define	PDBG_RXF		(1 << 4)	/* phy detected the end of a valid frame preamble */
-#define	PDBG_RXS		(1 << 5)	/* phy detected the end of a valid PLCP header */
-#define	PDBG_RXFRG		(1 << 6)	/* rx start not asserted */
-#define	PDBG_RXV		(1 << 7)	/* mac is taking receive byte from phy this cycle */
-#define	PDBG_RFD		(1 << 16)	/* RF portion of the radio is disabled */
-
-/* objaddr register */
-#define	OBJADDR_SEL_MASK	0x000F0000
-#define	OBJADDR_UCM_SEL		0x00000000
-#define	OBJADDR_SHM_SEL		0x00010000
-#define	OBJADDR_SCR_SEL		0x00020000
-#define	OBJADDR_IHR_SEL		0x00030000
-#define	OBJADDR_RCMTA_SEL	0x00040000
-#define	OBJADDR_SRCHM_SEL	0x00060000
-#define	OBJADDR_WINC		0x01000000
-#define	OBJADDR_RINC		0x02000000
-#define	OBJADDR_AUTO_INC	0x03000000
-
-#define	WEP_PCMADDR		0x07d4
-#define	WEP_PCMDATA		0x07d6
-
-/* frmtxstatus */
-#define	TXS_V			(1 << 0)	/* valid bit */
-#define	TXS_STATUS_MASK		0xffff
-/* sw mask to map txstatus for corerevs <= 4 to be the same as for corerev > 4 */
-#define	TXS_COMPAT_MASK		0x3
-#define	TXS_COMPAT_SHIFT	1
-#define	TXS_FID_MASK		0xffff0000
-#define	TXS_FID_SHIFT		16
-
-/* frmtxstatus2 */
-#define	TXS_SEQ_MASK		0xffff
-#define	TXS_PTX_MASK		0xff0000
-#define	TXS_PTX_SHIFT		16
-#define	TXS_MU_MASK		0x01000000
-#define	TXS_MU_SHIFT		24
-
-/* clk_ctl_st, corerev >= 17 */
-#define CCS_ERSRC_REQ_D11PLL	0x00000100	/* d11 core pll request */
-#define CCS_ERSRC_REQ_PHYPLL	0x00000200	/* PHY pll request */
-#define CCS_ERSRC_AVAIL_D11PLL	0x01000000	/* d11 core pll available */
-#define CCS_ERSRC_AVAIL_PHYPLL	0x02000000	/* PHY pll available */
-
-/* HT Cloclk Ctrl and Clock Avail for 4313 */
-#define CCS_ERSRC_REQ_HT    0x00000010	/* HT avail request */
-#define CCS_ERSRC_AVAIL_HT  0x00020000	/* HT clock available */
-
-/* d11_pwrctl, corerev16 only */
-#define D11_PHYPLL_AVAIL_REQ	0x000010000	/* request PHY PLL resource */
-#define D11_PHYPLL_AVAIL_STS	0x001000000	/* PHY PLL is available */
-
-/* tsf_cfprep register */
-#define	CFPREP_CBI_MASK		0xffffffc0
-#define	CFPREP_CBI_SHIFT	6
-#define	CFPREP_CFPP		0x00000001
-
-/* tx fifo sizes for corerev >= 9 */
-/* tx fifo sizes values are in terms of 256 byte blocks */
-#define TXFIFOCMD_RESET_MASK	(1 << 15)	/* reset */
-#define TXFIFOCMD_FIFOSEL_SHIFT	8	/* fifo */
-#define TXFIFO_FIFOTOP_SHIFT	8	/* fifo start */
-
-#define TXFIFO_START_BLK16	 65	/* Base address + 32 * 512 B/P */
-#define TXFIFO_START_BLK	 6	/* Base address + 6 * 256 B */
-#define TXFIFO_SIZE_UNIT	256	/* one unit corresponds to 256 bytes */
-#define MBSS16_TEMPLMEM_MINBLKS	65	/* one unit corresponds to 256 bytes */
-
-/* phy versions, PhyVersion:Revision field */
-#define	PV_AV_MASK		0xf000	/* analog block version */
-#define	PV_AV_SHIFT		12	/* analog block version bitfield offset */
-#define	PV_PT_MASK		0x0f00	/* phy type */
-#define	PV_PT_SHIFT		8	/* phy type bitfield offset */
-#define	PV_PV_MASK		0x000f	/* phy version */
-#define	PHY_TYPE(v)		((v & PV_PT_MASK) >> PV_PT_SHIFT)
-
-/* phy types, PhyVersion:PhyType field */
-#define	PHY_TYPE_N		4	/* N-Phy value */
-#define	PHY_TYPE_SSN		6	/* SSLPN-Phy value */
-#define	PHY_TYPE_LCN		8	/* LCN-Phy value */
-#define	PHY_TYPE_LCNXN		9	/* LCNXN-Phy value */
-#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
-
-/* analog types, PhyVersion:AnalogType field */
-#define	ANA_11N_013		5
-
-/* 802.11a PLCP header def */
-typedef struct ofdm_phy_hdr ofdm_phy_hdr_t;
-BWL_PRE_PACKED_STRUCT struct ofdm_phy_hdr {
-	u8 rlpt[3];		/* rate, length, parity, tail */
-	u16 service;
-	u8 pad;
-} BWL_POST_PACKED_STRUCT;
-
-#define	D11A_PHY_HDR_GRATE(phdr)	((phdr)->rlpt[0] & 0x0f)
-#define	D11A_PHY_HDR_GRES(phdr)		(((phdr)->rlpt[0] >> 4) & 0x01)
-#define	D11A_PHY_HDR_GLENGTH(phdr)	(((u32 *)((phdr)->rlpt) >> 5) & 0x0fff)
-#define	D11A_PHY_HDR_GPARITY(phdr)	(((phdr)->rlpt[3] >> 1) & 0x01)
-#define	D11A_PHY_HDR_GTAIL(phdr)	(((phdr)->rlpt[3] >> 2) & 0x3f)
-
-/* rate encoded per 802.11a-1999 sec 17.3.4.1 */
-#define	D11A_PHY_HDR_SRATE(phdr, rate)		\
-	((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf))
-/* set reserved field to zero */
-#define	D11A_PHY_HDR_SRES(phdr)		((phdr)->rlpt[0] &= 0xef)
-/* length is number of octets in PSDU */
-#define	D11A_PHY_HDR_SLENGTH(phdr, length)	\
-	(*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \
-	(((length) & 0x0fff) << 5))
-/* set the tail to all zeros */
-#define	D11A_PHY_HDR_STAIL(phdr)	((phdr)->rlpt[3] &= 0x03)
-
-#define	D11A_PHY_HDR_LEN_L	3	/* low-rate part of PLCP header */
-#define	D11A_PHY_HDR_LEN_R	2	/* high-rate part of PLCP header */
-
-#define	D11A_PHY_TX_DELAY	(2)	/* 2.1 usec */
-
-#define	D11A_PHY_HDR_TIME	(4)	/* low-rate part of PLCP header */
-#define	D11A_PHY_PRE_TIME	(16)
-#define	D11A_PHY_PREHDR_TIME	(D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME)
-
-/* 802.11b PLCP header def */
-typedef struct cck_phy_hdr cck_phy_hdr_t;
-BWL_PRE_PACKED_STRUCT struct cck_phy_hdr {
-	u8 signal;
-	u8 service;
-	u16 length;
-	u16 crc;
-} BWL_POST_PACKED_STRUCT;
-
-#define	D11B_PHY_HDR_LEN	6
-
-#define	D11B_PHY_TX_DELAY	(3)	/* 3.4 usec */
-
-#define	D11B_PHY_LHDR_TIME	(D11B_PHY_HDR_LEN << 3)
-#define	D11B_PHY_LPRE_TIME	(144)
-#define	D11B_PHY_LPREHDR_TIME	(D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME)
-
-#define	D11B_PHY_SHDR_TIME	(D11B_PHY_LHDR_TIME >> 1)
-#define	D11B_PHY_SPRE_TIME	(D11B_PHY_LPRE_TIME >> 1)
-#define	D11B_PHY_SPREHDR_TIME	(D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME)
-
-#define	D11B_PLCP_SIGNAL_LOCKED	(1 << 2)
-#define	D11B_PLCP_SIGNAL_LE	(1 << 7)
-
-#define MIMO_PLCP_MCS_MASK	0x7f	/* mcs index */
-#define MIMO_PLCP_40MHZ		0x80	/* 40 Hz frame */
-#define MIMO_PLCP_AMPDU		0x08	/* ampdu */
-
-#define WLC_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8))
-#define WLC_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8))
-#define WLC_SET_MIMO_PLCP_LEN(plcp, len) \
-	do { \
-		plcp[1] = len & 0xff; \
-		plcp[2] = ((len >> 8) & 0xff); \
-	} while (0);
-
-#define WLC_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU)
-#define WLC_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
-#define WLC_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
-
-/* The dot11a PLCP header is 5 bytes.  To simplify the software (so that we
- * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has
- * padding added in the ucode.
- */
-#define	D11_PHY_HDR_LEN	6
-
-/* TX DMA buffer header */
-typedef struct d11txh d11txh_t;
-BWL_PRE_PACKED_STRUCT struct d11txh {
-	u16 MacTxControlLow;	/* 0x0 */
-	u16 MacTxControlHigh;	/* 0x1 */
-	u16 MacFrameControl;	/* 0x2 */
-	u16 TxFesTimeNormal;	/* 0x3 */
-	u16 PhyTxControlWord;	/* 0x4 */
-	u16 PhyTxControlWord_1;	/* 0x5 */
-	u16 PhyTxControlWord_1_Fbr;	/* 0x6 */
-	u16 PhyTxControlWord_1_Rts;	/* 0x7 */
-	u16 PhyTxControlWord_1_FbrRts;	/* 0x8 */
-	u16 MainRates;	/* 0x9 */
-	u16 XtraFrameTypes;	/* 0xa */
-	u8 IV[16];		/* 0x0b - 0x12 */
-	u8 TxFrameRA[6];	/* 0x13 - 0x15 */
-	u16 TxFesTimeFallback;	/* 0x16 */
-	u8 RTSPLCPFallback[6];	/* 0x17 - 0x19 */
-	u16 RTSDurFallback;	/* 0x1a */
-	u8 FragPLCPFallback[6];	/* 0x1b - 1d */
-	u16 FragDurFallback;	/* 0x1e */
-	u16 MModeLen;	/* 0x1f */
-	u16 MModeFbrLen;	/* 0x20 */
-	u16 TstampLow;	/* 0x21 */
-	u16 TstampHigh;	/* 0x22 */
-	u16 ABI_MimoAntSel;	/* 0x23 */
-	u16 PreloadSize;	/* 0x24 */
-	u16 AmpduSeqCtl;	/* 0x25 */
-	u16 TxFrameID;	/* 0x26 */
-	u16 TxStatus;	/* 0x27 */
-	u16 MaxNMpdus;	/* 0x28 corerev >=16 */
-	u16 MaxABytes_MRT;	/* 0x29 corerev >=16 */
-	u16 MaxABytes_FBR;	/* 0x2a corerev >=16 */
-	u16 MinMBytes;	/* 0x2b corerev >=16 */
-	u8 RTSPhyHeader[D11_PHY_HDR_LEN];	/* 0x2c - 0x2e */
-	struct dot11_rts_frame rts_frame;	/* 0x2f - 0x36 */
-	u16 PAD;		/* 0x37 */
-} BWL_POST_PACKED_STRUCT;
-
-#define	D11_TXH_LEN		112	/* bytes */
-
-/* Frame Types */
-#define FT_CCK	0
-#define FT_OFDM	1
-#define FT_HT	2
-#define FT_N	3
-
-/* Position of MPDU inside A-MPDU; indicated with bits 10:9 of MacTxControlLow */
-#define TXC_AMPDU_SHIFT		9	/* shift for ampdu settings */
-#define TXC_AMPDU_NONE		0	/* Regular MPDU, not an A-MPDU */
-#define TXC_AMPDU_FIRST		1	/* first MPDU of an A-MPDU */
-#define TXC_AMPDU_MIDDLE	2	/* intermediate MPDU of an A-MPDU */
-#define TXC_AMPDU_LAST		3	/* last (or single) MPDU of an A-MPDU */
-
-/* MacTxControlLow */
-#define TXC_AMIC		0x8000
-#define	TXC_SENDCTS		0x0800
-#define TXC_AMPDU_MASK		0x0600
-#define TXC_BW_40		0x0100
-#define TXC_FREQBAND_5G		0x0080
-#define	TXC_DFCS		0x0040
-#define	TXC_IGNOREPMQ		0x0020
-#define	TXC_HWSEQ		0x0010
-#define	TXC_STARTMSDU		0x0008
-#define	TXC_SENDRTS		0x0004
-#define	TXC_LONGFRAME		0x0002
-#define	TXC_IMMEDACK		0x0001
-
-/* MacTxControlHigh */
-#define TXC_PREAMBLE_RTS_FB_SHORT	0x8000	/* RTS fallback preamble type 1 = SHORT 0 = LONG */
-#define TXC_PREAMBLE_RTS_MAIN_SHORT	0x4000	/* RTS main rate preamble type 1 = SHORT 0 = LONG */
-#define TXC_PREAMBLE_DATA_FB_SHORT	0x2000	/* Main fallback rate preamble type
-						 * 1 = SHORT for OFDM/GF for MIMO
-						 * 0 = LONG for CCK/MM for MIMO
-						 */
-/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */
-#define	TXC_AMPDU_FBR		0x1000	/* use fallback rate for this AMPDU */
-#define	TXC_SECKEY_MASK		0x0FF0
-#define	TXC_SECKEY_SHIFT	4
-#define	TXC_ALT_TXPWR		0x0008	/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
-#define	TXC_SECTYPE_MASK	0x0007
-#define	TXC_SECTYPE_SHIFT	0
-
-/* Null delimiter for Fallback rate */
-#define AMPDU_FBR_NULL_DELIM  5	/* Location of Null delimiter count for AMPDU */
-
-/* PhyTxControl for Mimophy */
-#define	PHY_TXC_PWR_MASK	0xFC00
-#define	PHY_TXC_PWR_SHIFT	10
-#define	PHY_TXC_ANT_MASK	0x03C0	/* bit 6, 7, 8, 9 */
-#define	PHY_TXC_ANT_SHIFT	6
-#define	PHY_TXC_ANT_0_1		0x00C0	/* auto, last rx */
-#define	PHY_TXC_LCNPHY_ANT_LAST	0x0000
-#define	PHY_TXC_ANT_3		0x0200	/* virtual antenna 3 */
-#define	PHY_TXC_ANT_2		0x0100	/* virtual antenna 2 */
-#define	PHY_TXC_ANT_1		0x0080	/* virtual antenna 1 */
-#define	PHY_TXC_ANT_0		0x0040	/* virtual antenna 0 */
-#define	PHY_TXC_SHORT_HDR	0x0010
-
-#define	PHY_TXC_OLD_ANT_0	0x0000
-#define	PHY_TXC_OLD_ANT_1	0x0100
-#define	PHY_TXC_OLD_ANT_LAST	0x0300
-
-/* PhyTxControl_1 for Mimophy */
-#define PHY_TXC1_BW_MASK		0x0007
-#define PHY_TXC1_BW_10MHZ		0
-#define PHY_TXC1_BW_10MHZ_UP		1
-#define PHY_TXC1_BW_20MHZ		2
-#define PHY_TXC1_BW_20MHZ_UP		3
-#define PHY_TXC1_BW_40MHZ		4
-#define PHY_TXC1_BW_40MHZ_DUP		5
-#define PHY_TXC1_MODE_SHIFT		3
-#define PHY_TXC1_MODE_MASK		0x0038
-#define PHY_TXC1_MODE_SISO		0
-#define PHY_TXC1_MODE_CDD		1
-#define PHY_TXC1_MODE_STBC		2
-#define PHY_TXC1_MODE_SDM		3
-
-/* PhyTxControl for HTphy that are different from Mimophy */
-#define	PHY_TXC_HTANT_MASK		0x3fC0	/* bit 6, 7, 8, 9, 10, 11, 12, 13 */
-
-/* XtraFrameTypes */
-#define XFTS_RTS_FT_SHIFT	2
-#define XFTS_FBRRTS_FT_SHIFT	4
-#define XFTS_CHANNEL_SHIFT	8
-
-/* Antenna diversity bit in ant_wr_settle */
-#define	PHY_AWS_ANTDIV		0x2000
-
-/* IFS ctl */
-#define IFS_USEEDCF	(1 << 2)
-
-/* IFS ctl1 */
-#define IFS_CTL1_EDCRS	(1 << 3)
-#define IFS_CTL1_EDCRS_20L (1 << 4)
-#define IFS_CTL1_EDCRS_40 (1 << 5)
-
-/* ABI_MimoAntSel */
-#define ABI_MAS_ADDR_BMP_IDX_MASK	0x0f00
-#define ABI_MAS_ADDR_BMP_IDX_SHIFT	8
-#define ABI_MAS_FBR_ANT_PTN_MASK	0x00f0
-#define ABI_MAS_FBR_ANT_PTN_SHIFT	4
-#define ABI_MAS_MRT_ANT_PTN_MASK	0x000f
-
-/* tx status packet */
-typedef struct tx_status tx_status_t;
-BWL_PRE_PACKED_STRUCT struct tx_status {
-	u16 framelen;
-	u16 PAD;
-	u16 frameid;
-	u16 status;
-	u16 lasttxtime;
-	u16 sequence;
-	u16 phyerr;
-	u16 ackphyrxsh;
-} BWL_POST_PACKED_STRUCT;
-
-#define	TXSTATUS_LEN	16
-
-/* status field bit definitions */
-#define	TX_STATUS_FRM_RTX_MASK	0xF000
-#define	TX_STATUS_FRM_RTX_SHIFT	12
-#define	TX_STATUS_RTS_RTX_MASK	0x0F00
-#define	TX_STATUS_RTS_RTX_SHIFT	8
-#define TX_STATUS_MASK		0x00FE
-#define	TX_STATUS_PMINDCTD	(1 << 7)	/* PM mode indicated to AP */
-#define	TX_STATUS_INTERMEDIATE	(1 << 6)	/* intermediate or 1st ampdu pkg */
-#define	TX_STATUS_AMPDU		(1 << 5)	/* AMPDU status */
-#define TX_STATUS_SUPR_MASK	0x1C	/* suppress status bits (4:2) */
-#define TX_STATUS_SUPR_SHIFT	2
-#define	TX_STATUS_ACK_RCV	(1 << 1)	/* ACK received */
-#define	TX_STATUS_VALID		(1 << 0)	/* Tx status valid (corerev >= 5) */
-#define	TX_STATUS_NO_ACK	0
-
-/* suppress status reason codes */
-#define	TX_STATUS_SUPR_PMQ	(1 << 2)	/* PMQ entry */
-#define	TX_STATUS_SUPR_FLUSH	(2 << 2)	/* flush request */
-#define	TX_STATUS_SUPR_FRAG	(3 << 2)	/* previous frag failure */
-#define	TX_STATUS_SUPR_TBTT	(3 << 2)	/* SHARED: Probe response supr for TBTT */
-#define	TX_STATUS_SUPR_BADCH	(4 << 2)	/* channel mismatch */
-#define	TX_STATUS_SUPR_EXPTIME	(5 << 2)	/* lifetime expiry */
-#define	TX_STATUS_SUPR_UF	(6 << 2)	/* underflow */
-
-/* Unexpected tx status for rate update */
-#define TX_STATUS_UNEXP(status) \
-	((((status) & TX_STATUS_INTERMEDIATE) != 0) && \
-	 TX_STATUS_UNEXP_AMPDU(status))
-
-/* Unexpected tx status for A-MPDU rate update */
-#define TX_STATUS_UNEXP_AMPDU(status) \
-	((((status) & TX_STATUS_SUPR_MASK) != 0) && \
-	 (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME))
-
-#define TX_STATUS_BA_BMAP03_MASK	0xF000	/* ba bitmap 0:3 in 1st pkg */
-#define TX_STATUS_BA_BMAP03_SHIFT	12	/* ba bitmap 0:3 in 1st pkg */
-#define TX_STATUS_BA_BMAP47_MASK	0x001E	/* ba bitmap 4:7 in 2nd pkg */
-#define TX_STATUS_BA_BMAP47_SHIFT	3	/* ba bitmap 4:7 in 2nd pkg */
-
-/* RXE (Receive Engine) */
-
-/* RCM_CTL */
-#define	RCM_INC_MASK_H		0x0080
-#define	RCM_INC_MASK_L		0x0040
-#define	RCM_INC_DATA		0x0020
-#define	RCM_INDEX_MASK		0x001F
-#define	RCM_SIZE		15
-
-#define	RCM_MAC_OFFSET		0	/* current MAC address */
-#define	RCM_BSSID_OFFSET	3	/* current BSSID address */
-#define	RCM_F_BSSID_0_OFFSET	6	/* foreign BSS CFP tracking */
-#define	RCM_F_BSSID_1_OFFSET	9	/* foreign BSS CFP tracking */
-#define	RCM_F_BSSID_2_OFFSET	12	/* foreign BSS CFP tracking */
-
-#define RCM_WEP_TA0_OFFSET	16
-#define RCM_WEP_TA1_OFFSET	19
-#define RCM_WEP_TA2_OFFSET	22
-#define RCM_WEP_TA3_OFFSET	25
-
-/* PSM Block */
-
-/* psm_phy_hdr_param bits */
-#define MAC_PHY_RESET		1
-#define MAC_PHY_CLOCK_EN	2
-#define MAC_PHY_FORCE_CLK	4
-
-/* WEP Block */
-
-/* WEP_WKEY */
-#define	WKEY_START		(1 << 8)
-#define	WKEY_SEL_MASK		0x1F
-
-/* WEP data formats */
-
-/* the number of RCMTA entries */
-#define RCMTA_SIZE 50
-
-#define M_ADDR_BMP_BLK		(0x37e * 2)
-#define M_ADDR_BMP_BLK_SZ	12
-
-#define ADDR_BMP_RA		(1 << 0)	/* Receiver Address (RA) */
-#define ADDR_BMP_TA		(1 << 1)	/* Transmitter Address (TA) */
-#define ADDR_BMP_BSSID		(1 << 2)	/* BSSID */
-#define ADDR_BMP_AP		(1 << 3)	/* Infra-BSS Access Point (AP) */
-#define ADDR_BMP_STA		(1 << 4)	/* Infra-BSS Station (STA) */
-#define ADDR_BMP_RESERVED1	(1 << 5)
-#define ADDR_BMP_RESERVED2	(1 << 6)
-#define ADDR_BMP_RESERVED3	(1 << 7)
-#define ADDR_BMP_BSS_IDX_MASK	(3 << 8)	/* BSS control block index */
-#define ADDR_BMP_BSS_IDX_SHIFT	8
-
-#define	WSEC_MAX_RCMTA_KEYS	54
-
-/* max keys in M_TKMICKEYS_BLK */
-#define	WSEC_MAX_TKMIC_ENGINE_KEYS		12	/* 8 + 4 default */
-
-/* max RXE match registers */
-#define WSEC_MAX_RXE_KEYS	4
-
-/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */
-/* SKL (Security Key Lookup) */
-#define	SKL_ALGO_MASK		0x0007
-#define	SKL_ALGO_SHIFT		0
-#define	SKL_KEYID_MASK		0x0008
-#define	SKL_KEYID_SHIFT		3
-#define	SKL_INDEX_MASK		0x03F0
-#define	SKL_INDEX_SHIFT		4
-#define	SKL_GRP_ALGO_MASK	0x1c00
-#define	SKL_GRP_ALGO_SHIFT	10
-
-/* additional bits defined for IBSS group key support */
-#define	SKL_IBSS_INDEX_MASK	0x01F0
-#define	SKL_IBSS_INDEX_SHIFT	4
-#define	SKL_IBSS_KEYID1_MASK	0x0600
-#define	SKL_IBSS_KEYID1_SHIFT	9
-#define	SKL_IBSS_KEYID2_MASK	0x1800
-#define	SKL_IBSS_KEYID2_SHIFT	11
-#define	SKL_IBSS_KEYALGO_MASK	0xE000
-#define	SKL_IBSS_KEYALGO_SHIFT	13
-
-#define	WSEC_MODE_OFF		0
-#define	WSEC_MODE_HW		1
-#define	WSEC_MODE_SW		2
-
-#define	WSEC_ALGO_OFF		0
-#define	WSEC_ALGO_WEP1		1
-#define	WSEC_ALGO_TKIP		2
-#define	WSEC_ALGO_AES		3
-#define	WSEC_ALGO_WEP128	4
-#define	WSEC_ALGO_AES_LEGACY	5
-#define	WSEC_ALGO_NALG		6
-
-#define	AES_MODE_NONE		0
-#define	AES_MODE_CCM		1
-
-/* WEP_CTL (Rev 0) */
-#define	WECR0_KEYREG_SHIFT	0
-#define	WECR0_KEYREG_MASK	0x7
-#define	WECR0_DECRYPT		(1 << 3)
-#define	WECR0_IVINLINE		(1 << 4)
-#define	WECR0_WEPALG_SHIFT	5
-#define	WECR0_WEPALG_MASK	(0x7 << 5)
-#define	WECR0_WKEYSEL_SHIFT	8
-#define	WECR0_WKEYSEL_MASK	(0x7 << 8)
-#define	WECR0_WKEYSTART		(1 << 11)
-#define	WECR0_WEPINIT		(1 << 14)
-#define	WECR0_ICVERR		(1 << 15)
-
-/* Frame template map byte offsets */
-#define	T_ACTS_TPL_BASE		(0)
-#define	T_NULL_TPL_BASE		(0xc * 2)
-#define	T_QNULL_TPL_BASE	(0x1c * 2)
-#define	T_RR_TPL_BASE		(0x2c * 2)
-#define	T_BCN0_TPL_BASE		(0x34 * 2)
-#define	T_PRS_TPL_BASE		(0x134 * 2)
-#define	T_BCN1_TPL_BASE		(0x234 * 2)
-#define T_TX_FIFO_TXRAM_BASE	(T_ACTS_TPL_BASE + (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
-
-#define T_BA_TPL_BASE		T_QNULL_TPL_BASE	/* template area for BA */
-
-#define T_RAM_ACCESS_SZ		4	/* template ram is 4 byte access only */
-
-/* Shared Mem byte offsets */
-
-/* Location where the ucode expects the corerev */
-#define	M_MACHW_VER		(0x00b * 2)
-
-/* Location where the ucode expects the MAC capabilities */
-#define	M_MACHW_CAP_L		(0x060 * 2)
-#define	M_MACHW_CAP_H	(0x061 * 2)
-
-/* WME shared memory */
-#define M_EDCF_STATUS_OFF	(0x007 * 2)
-#define M_TXF_CUR_INDEX		(0x018 * 2)
-#define M_EDCF_QINFO		(0x120 * 2)
-
-/* PS-mode related parameters */
-#define	M_DOT11_SLOT		(0x008 * 2)
-#define	M_DOT11_DTIMPERIOD	(0x009 * 2)
-#define	M_NOSLPZNATDTIM		(0x026 * 2)
-
-/* Beacon-related parameters */
-#define	M_BCN0_FRM_BYTESZ	(0x00c * 2)	/* Bcn 0 template length */
-#define	M_BCN1_FRM_BYTESZ	(0x00d * 2)	/* Bcn 1 template length */
-#define	M_BCN_TXTSF_OFFSET	(0x00e * 2)
-#define	M_TIMBPOS_INBEACON	(0x00f * 2)
-#define	M_SFRMTXCNTFBRTHSD	(0x022 * 2)
-#define	M_LFRMTXCNTFBRTHSD	(0x023 * 2)
-#define	M_BCN_PCTLWD		(0x02a * 2)
-#define M_BCN_LI		(0x05b * 2)	/* beacon listen interval */
-
-/* MAX Rx Frame len */
-#define M_MAXRXFRM_LEN		(0x010 * 2)
-
-/* ACK/CTS related params */
-#define	M_RSP_PCTLWD		(0x011 * 2)
-
-/* Hardware Power Control */
-#define M_TXPWR_N		(0x012 * 2)
-#define M_TXPWR_TARGET		(0x013 * 2)
-#define M_TXPWR_MAX		(0x014 * 2)
-#define M_TXPWR_CUR		(0x019 * 2)
-
-/* Rx-related parameters */
-#define	M_RX_PAD_DATA_OFFSET	(0x01a * 2)
-
-/* WEP Shared mem data */
-#define	M_SEC_DEFIVLOC		(0x01e * 2)
-#define	M_SEC_VALNUMSOFTMCHTA	(0x01f * 2)
-#define	M_PHYVER		(0x028 * 2)
-#define	M_PHYTYPE		(0x029 * 2)
-#define	M_SECRXKEYS_PTR		(0x02b * 2)
-#define	M_TKMICKEYS_PTR		(0x059 * 2)
-#define	M_SECKINDXALGO_BLK	(0x2ea * 2)
-#define M_SECKINDXALGO_BLK_SZ	54
-#define	M_SECPSMRXTAMCH_BLK	(0x2fa * 2)
-#define	M_TKIP_TSC_TTAK		(0x18c * 2)
-#define	D11_MAX_KEY_SIZE	16
-
-#define	M_MAX_ANTCNT		(0x02e * 2)	/* antenna swap threshold */
-
-/* Probe response related parameters */
-#define	M_SSIDLEN		(0x024 * 2)
-#define	M_PRB_RESP_FRM_LEN	(0x025 * 2)
-#define	M_PRS_MAXTIME		(0x03a * 2)
-#define	M_SSID			(0xb0 * 2)
-#define	M_CTXPRS_BLK		(0xc0 * 2)
-#define	C_CTX_PCTLWD_POS	(0x4 * 2)
-
-/* Delta between OFDM and CCK power in CCK power boost mode */
-#define M_OFDM_OFFSET		(0x027 * 2)
-
-/* TSSI for last 4 11b/g CCK packets transmitted */
-#define	M_B_TSSI_0		(0x02c * 2)
-#define	M_B_TSSI_1		(0x02d * 2)
-
-/* Host flags to turn on ucode options */
-#define	M_HOST_FLAGS1		(0x02f * 2)
-#define	M_HOST_FLAGS2		(0x030 * 2)
-#define	M_HOST_FLAGS3		(0x031 * 2)
-#define	M_HOST_FLAGS4		(0x03c * 2)
-#define	M_HOST_FLAGS5		(0x06a * 2)
-#define	M_HOST_FLAGS_SZ		16
-
-#define M_RADAR_REG		(0x033 * 2)
-
-/* TSSI for last 4 11a OFDM packets transmitted */
-#define	M_A_TSSI_0		(0x034 * 2)
-#define	M_A_TSSI_1		(0x035 * 2)
-
-/* noise interference measurement */
-#define M_NOISE_IF_COUNT	(0x034 * 2)
-#define M_NOISE_IF_TIMEOUT	(0x035 * 2)
-
-#define	M_RF_RX_SP_REG1		(0x036 * 2)
-
-/* TSSI for last 4 11g OFDM packets transmitted */
-#define	M_G_TSSI_0		(0x038 * 2)
-#define	M_G_TSSI_1		(0x039 * 2)
-
-/* Background noise measure */
-#define	M_JSSI_0		(0x44 * 2)
-#define	M_JSSI_1		(0x45 * 2)
-#define	M_JSSI_AUX		(0x46 * 2)
-
-#define	M_CUR_2050_RADIOCODE	(0x47 * 2)
-
-/* TX fifo sizes */
-#define M_FIFOSIZE0		(0x4c * 2)
-#define M_FIFOSIZE1		(0x4d * 2)
-#define M_FIFOSIZE2		(0x4e * 2)
-#define M_FIFOSIZE3		(0x4f * 2)
-#define D11_MAX_TX_FRMS		32	/* max frames allowed in tx fifo */
-
-/* Current channel number plus upper bits */
-#define M_CURCHANNEL		(0x50 * 2)
-#define D11_CURCHANNEL_5G	0x0100;
-#define D11_CURCHANNEL_40	0x0200;
-#define D11_CURCHANNEL_MAX	0x00FF;
-
-/* last posted frameid on the bcmc fifo */
-#define M_BCMC_FID		(0x54 * 2)
-#define INVALIDFID		0xffff
-
-/* extended beacon phyctl bytes for 11N */
-#define	M_BCN_PCTL1WD		(0x058 * 2)
-
-/* idle busy ratio to duty_cycle requirement  */
-#define M_TX_IDLE_BUSY_RATIO_X_16_CCK  (0x52 * 2)
-#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2)
-
-/* CW RSSI for LCNPHY */
-#define M_LCN_RSSI_0 		0x1332
-#define M_LCN_RSSI_1 		0x1338
-#define M_LCN_RSSI_2 		0x133e
-#define M_LCN_RSSI_3 		0x1344
-
-/* SNR for LCNPHY */
-#define M_LCN_SNR_A_0 	0x1334
-#define M_LCN_SNR_B_0 	0x1336
-
-#define M_LCN_SNR_A_1 	0x133a
-#define M_LCN_SNR_B_1 	0x133c
-
-#define M_LCN_SNR_A_2 	0x1340
-#define M_LCN_SNR_B_2 	0x1342
-
-#define M_LCN_SNR_A_3 	0x1346
-#define M_LCN_SNR_B_3 	0x1348
-
-#define M_LCN_LAST_RESET 	(81*2)
-#define M_LCN_LAST_LOC	(63*2)
-#define M_LCNPHY_RESET_STATUS (4902)
-#define M_LCNPHY_DSC_TIME	(0x98d*2)
-#define M_LCNPHY_RESET_CNT_DSC (0x98b*2)
-#define M_LCNPHY_RESET_CNT	(0x98c*2)
-
-/* Rate table offsets */
-#define	M_RT_DIRMAP_A		(0xe0 * 2)
-#define	M_RT_BBRSMAP_A		(0xf0 * 2)
-#define	M_RT_DIRMAP_B		(0x100 * 2)
-#define	M_RT_BBRSMAP_B		(0x110 * 2)
-
-/* Rate table entry offsets */
-#define	M_RT_PRS_PLCP_POS	10
-#define	M_RT_PRS_DUR_POS	16
-#define	M_RT_OFDM_PCTL1_POS	18
-
-#define M_20IN40_IQ			(0x380 * 2)
-
-/* SHM locations where ucode stores the current power index */
-#define M_CURR_IDX1		(0x384 * 2)
-#define M_CURR_IDX2		(0x387 * 2)
-
-#define M_BSCALE_ANT0	(0x5e * 2)
-#define M_BSCALE_ANT1	(0x5f * 2)
-
-/* Antenna Diversity Testing */
-#define M_MIMO_ANTSEL_RXDFLT	(0x63 * 2)
-#define M_ANTSEL_CLKDIV	(0x61 * 2)
-#define M_MIMO_ANTSEL_TXDFLT	(0x64 * 2)
-
-#define M_MIMO_MAXSYM	(0x5d * 2)
-#define MIMO_MAXSYM_DEF		0x8000	/* 32k */
-#define MIMO_MAXSYM_MAX		0xffff	/* 64k */
-
-#define M_WATCHDOG_8TU		(0x1e * 2)
-#define WATCHDOG_8TU_DEF	5
-#define WATCHDOG_8TU_MAX	10
-
-/* Manufacturing Test Variables */
-#define M_PKTENG_CTRL		(0x6c * 2)	/* PER test mode */
-#define M_PKTENG_IFS		(0x6d * 2)	/* IFS for TX mode */
-#define M_PKTENG_FRMCNT_LO		(0x6e * 2)	/* Lower word of tx frmcnt/rx lostcnt */
-#define M_PKTENG_FRMCNT_HI		(0x6f * 2)	/* Upper word of tx frmcnt/rx lostcnt */
-
-/* Index variation in vbat ripple */
-#define M_LCN_PWR_IDX_MAX	(0x67 * 2)	/* highest index read by ucode */
-#define M_LCN_PWR_IDX_MIN	(0x66 * 2)	/* lowest index read by ucode */
-
-/* M_PKTENG_CTRL bit definitions */
-#define M_PKTENG_MODE_TX		0x0001
-#define M_PKTENG_MODE_TX_RIFS	        0x0004
-#define M_PKTENG_MODE_TX_CTS            0x0008
-#define M_PKTENG_MODE_RX		0x0002
-#define M_PKTENG_MODE_RX_WITH_ACK	0x0402
-#define M_PKTENG_MODE_MASK		0x0003
-#define M_PKTENG_FRMCNT_VLD		0x0100	/* TX frames indicated in the frmcnt reg */
-
-/* Sample Collect parameters (bitmap and type) */
-#define M_SMPL_COL_BMP		(0x37d * 2)	/* Trigger bitmap for sample collect */
-#define M_SMPL_COL_CTL		(0x3b2 * 2)	/* Sample collect type */
-
-#define ANTSEL_CLKDIV_4MHZ	6
-#define MIMO_ANTSEL_BUSY	0x4000	/* bit 14 (busy) */
-#define MIMO_ANTSEL_SEL		0x8000	/* bit 15 write the value */
-#define MIMO_ANTSEL_WAIT	50	/* 50us wait */
-#define MIMO_ANTSEL_OVERRIDE	0x8000	/* flag */
-
-typedef struct shm_acparams shm_acparams_t;
-BWL_PRE_PACKED_STRUCT struct shm_acparams {
-	u16 txop;
-	u16 cwmin;
-	u16 cwmax;
-	u16 cwcur;
-	u16 aifs;
-	u16 bslots;
-	u16 reggap;
-	u16 status;
-	u16 rsvd[8];
-} BWL_POST_PACKED_STRUCT;
-#define M_EDCF_QLEN	(16 * 2)
-
-#define WME_STATUS_NEWAC	(1 << 8)
-
-/* M_HOST_FLAGS */
-#define MHFMAX		5	/* Number of valid hostflag half-word (u16) */
-#define MHF1		0	/* Hostflag 1 index */
-#define MHF2		1	/* Hostflag 2 index */
-#define MHF3		2	/* Hostflag 3 index */
-#define MHF4		3	/* Hostflag 4 index */
-#define MHF5		4	/* Hostflag 5 index */
-
-/* Flags in M_HOST_FLAGS */
-#define	MHF1_ANTDIV		0x0001	/* Enable ucode antenna diversity help */
-#define	MHF1_EDCF		0x0100	/* Enable EDCF access control */
-#define MHF1_IQSWAP_WAR		0x0200
-#define	MHF1_FORCEFASTCLK	0x0400	/* Disable Slow clock request, for corerev < 11 */
-
-/* Flags in M_HOST_FLAGS2 */
-#define MHF2_PCISLOWCLKWAR	0x0008	/* PR16165WAR : Enable ucode PCI slow clock WAR */
-#define MHF2_TXBCMC_NOW		0x0040	/* Flush BCMC FIFO immediately */
-#define MHF2_HWPWRCTL		0x0080	/* Enable ucode/hw power control */
-#define MHF2_NPHY40MHZ_WAR	0x0800
-
-/* Flags in M_HOST_FLAGS3 */
-#define MHF3_ANTSEL_EN		0x0001	/* enabled mimo antenna selection */
-#define MHF3_ANTSEL_MODE	0x0002	/* antenna selection mode: 0: 2x3, 1: 2x4 */
-#define MHF3_RESERVED1		0x0004
-#define MHF3_RESERVED2		0x0008
-#define MHF3_NPHY_MLADV_WAR	0x0010
-
-/* Flags in M_HOST_FLAGS4 */
-#define MHF4_BPHY_TXCORE0	0x0080	/* force bphy Tx on core 0 (board level WAR) */
-#define MHF4_EXTPA_ENABLE  	0x4000	/* for 4313A0 FEM boards */
-
-/* Flags in M_HOST_FLAGS5 */
-#define MHF5_4313_GPIOCTRL	0x0001
-#define MHF5_RESERVED1		0x0002
-#define MHF5_RESERVED2		0x0004
-/* Radio power setting for ucode */
-#define	M_RADIO_PWR		(0x32 * 2)
-
-/* phy noise recorded by ucode right after tx */
-#define	M_PHY_NOISE		(0x037 * 2)
-#define	PHY_NOISE_MASK		0x00ff
-
-/* Receive Frame Data Header for 802.11b DCF-only frames */
-typedef struct d11rxhdr d11rxhdr_t;
-BWL_PRE_PACKED_STRUCT struct d11rxhdr {
-	u16 RxFrameSize;	/* Actual byte length of the frame data received */
-	u16 PAD;
-	u16 PhyRxStatus_0;	/* PhyRxStatus 15:0 */
-	u16 PhyRxStatus_1;	/* PhyRxStatus 31:16 */
-	u16 PhyRxStatus_2;	/* PhyRxStatus 47:32 */
-	u16 PhyRxStatus_3;	/* PhyRxStatus 63:48 */
-	u16 PhyRxStatus_4;	/* PhyRxStatus 79:64 */
-	u16 PhyRxStatus_5;	/* PhyRxStatus 95:80 */
-	u16 RxStatus1;	/* MAC Rx Status */
-	u16 RxStatus2;	/* extended MAC Rx status */
-	u16 RxTSFTime;	/* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
-	u16 RxChan;		/* gain code, channel radio code, and phy type */
-} BWL_POST_PACKED_STRUCT;
-
-#define	RXHDR_LEN		24	/* sizeof d11rxhdr_t */
-#define	FRAMELEN(h)		((h)->RxFrameSize)
-
-typedef struct wlc_d11rxhdr wlc_d11rxhdr_t;
-BWL_PRE_PACKED_STRUCT struct wlc_d11rxhdr {
-	d11rxhdr_t rxhdr;
-	u32 tsf_l;		/* TSF_L reading */
-	s8 rssi;		/* computed instanteneous rssi in BMAC */
-	s8 rxpwr0;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
-	s8 rxpwr1;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
-	s8 do_rssi_ma;	/* do per-pkt sampling for per-antenna ma in HIGH */
-	s8 rxpwr[WL_RSSI_ANT_MAX];	/* rssi for supported antennas */
-} BWL_POST_PACKED_STRUCT;
-
-/* PhyRxStatus_0: */
-#define	PRXS0_FT_MASK		0x0003	/* NPHY only: CCK, OFDM, preN, N */
-#define	PRXS0_CLIP_MASK		0x000C	/* NPHY only: clip count adjustment steps by AGC */
-#define	PRXS0_CLIP_SHIFT	2
-#define	PRXS0_UNSRATE		0x0010	/* PHY received a frame with unsupported rate */
-#define	PRXS0_RXANT_UPSUBBAND	0x0020	/* GPHY: rx ant, NPHY: upper sideband */
-#define	PRXS0_LCRS		0x0040	/* CCK frame only: lost crs during cck frame reception */
-#define	PRXS0_SHORTH		0x0080	/* Short Preamble */
-#define	PRXS0_PLCPFV		0x0100	/* PLCP violation */
-#define	PRXS0_PLCPHCF		0x0200	/* PLCP header integrity check failed */
-#define	PRXS0_GAIN_CTL		0x4000	/* legacy PHY gain control */
-#define PRXS0_ANTSEL_MASK	0xF000	/* NPHY: Antennas used for received frame, bitmask */
-#define PRXS0_ANTSEL_SHIFT	0x12
-
-/* subfield PRXS0_FT_MASK */
-#define	PRXS0_CCK		0x0000
-#define	PRXS0_OFDM		0x0001	/* valid only for G phy, use rxh->RxChan for A phy */
-#define	PRXS0_PREN		0x0002
-#define	PRXS0_STDN		0x0003
-
-/* subfield PRXS0_ANTSEL_MASK */
-#define PRXS0_ANTSEL_0		0x0	/* antenna 0 is used */
-#define PRXS0_ANTSEL_1		0x2	/* antenna 1 is used */
-#define PRXS0_ANTSEL_2		0x4	/* antenna 2 is used */
-#define PRXS0_ANTSEL_3		0x8	/* antenna 3 is used */
-
-/* PhyRxStatus_1: */
-#define	PRXS1_JSSI_MASK		0x00FF
-#define	PRXS1_JSSI_SHIFT	0
-#define	PRXS1_SQ_MASK		0xFF00
-#define	PRXS1_SQ_SHIFT		8
-
-/* nphy PhyRxStatus_1: */
-#define PRXS1_nphy_PWR0_MASK	0x00FF
-#define PRXS1_nphy_PWR1_MASK	0xFF00
-
-/* HTPHY Rx Status defines */
-/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */
-#define PRXS0_BAND	        0x0400	/* 0 = 2.4G, 1 = 5G */
-#define PRXS0_RSVD	        0x0800	/* reserved; set to 0 */
-#define PRXS0_UNUSED	        0xF000	/* unused and not defined; set to 0 */
-
-/* htphy PhyRxStatus_1: */
-#define PRXS1_HTPHY_CORE_MASK	0x000F	/* core enables for {3..0}, 0=disabled, 1=enabled */
-#define PRXS1_HTPHY_ANTCFG_MASK	0x00F0	/* antenna configation */
-#define PRXS1_HTPHY_MMPLCPLenL_MASK	0xFF00	/* Mixmode PLCP Length low byte mask */
-
-/* htphy PhyRxStatus_2: */
-#define PRXS2_HTPHY_MMPLCPLenH_MASK	0x000F	/* Mixmode PLCP Length high byte maskw */
-#define PRXS2_HTPHY_MMPLCH_RATE_MASK	0x00F0	/* Mixmode PLCP rate mask */
-#define PRXS2_HTPHY_RXPWR_ANT0	0xFF00	/* Rx power on core 0 */
-
-/* htphy PhyRxStatus_3: */
-#define PRXS3_HTPHY_RXPWR_ANT1	0x00FF	/* Rx power on core 1 */
-#define PRXS3_HTPHY_RXPWR_ANT2	0xFF00	/* Rx power on core 2 */
-
-/* htphy PhyRxStatus_4: */
-#define PRXS4_HTPHY_RXPWR_ANT3	0x00FF	/* Rx power on core 3 */
-#define PRXS4_HTPHY_CFO		0xFF00	/* Coarse frequency offset */
-
-/* htphy PhyRxStatus_5: */
-#define PRXS5_HTPHY_FFO	        0x00FF	/* Fine frequency offset */
-#define PRXS5_HTPHY_AR	        0xFF00	/* Advance Retard */
-
-#define HTPHY_MMPLCPLen(rxs)	((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
-	(((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8))
-/* Get Rx power on core 0 */
-#define HTPHY_RXPWR_ANT0(rxs)	((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
-/* Get Rx power on core 1 */
-#define HTPHY_RXPWR_ANT1(rxs)	(((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
-/* Get Rx power on core 2 */
-#define HTPHY_RXPWR_ANT2(rxs)	((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
-
-/* ucode RxStatus1: */
-#define	RXS_BCNSENT		0x8000
-#define	RXS_SECKINDX_MASK	0x07e0
-#define	RXS_SECKINDX_SHIFT	5
-#define	RXS_DECERR		(1 << 4)
-#define	RXS_DECATMPT		(1 << 3)
-#define	RXS_PBPRES		(1 << 2)	/* PAD bytes to make IP data 4 bytes aligned */
-#define	RXS_RESPFRAMETX		(1 << 1)
-#define	RXS_FCSERR		(1 << 0)
-
-/* ucode RxStatus2: */
-#define RXS_AMSDU_MASK		1
-#define	RXS_AGGTYPE_MASK	0x6
-#define	RXS_AGGTYPE_SHIFT	1
-#define	RXS_PHYRXST_VALID	(1 << 8)
-#define RXS_RXANT_MASK		0x3
-#define RXS_RXANT_SHIFT		12
-
-/* RxChan */
-#define RXS_CHAN_40		0x1000
-#define RXS_CHAN_5G		0x0800
-#define	RXS_CHAN_ID_MASK	0x07f8
-#define	RXS_CHAN_ID_SHIFT	3
-#define	RXS_CHAN_PHYTYPE_MASK	0x0007
-#define	RXS_CHAN_PHYTYPE_SHIFT	0
-
-/* Index of attenuations used during ucode power control. */
-#define M_PWRIND_BLKS	(0x184 * 2)
-#define M_PWRIND_MAP0	(M_PWRIND_BLKS + 0x0)
-#define M_PWRIND_MAP1	(M_PWRIND_BLKS + 0x2)
-#define M_PWRIND_MAP2	(M_PWRIND_BLKS + 0x4)
-#define M_PWRIND_MAP3	(M_PWRIND_BLKS + 0x6)
-/* M_PWRIND_MAP(core) macro */
-#define M_PWRIND_MAP(core)  (M_PWRIND_BLKS + ((core)<<1))
-
-/* PSM SHM variable offsets */
-#define	M_PSM_SOFT_REGS	0x0
-#define	M_BOM_REV_MAJOR	(M_PSM_SOFT_REGS + 0x0)
-#define	M_BOM_REV_MINOR	(M_PSM_SOFT_REGS + 0x2)
-#define	M_UCODE_DBGST	(M_PSM_SOFT_REGS + 0x40)	/* ucode debug status code */
-#define	M_UCODE_MACSTAT	(M_PSM_SOFT_REGS + 0xE0)	/* macstat counters */
-
-#define M_AGING_THRSH	(0x3e * 2)	/* max time waiting for medium before tx */
-#define	M_MBURST_SIZE	(0x40 * 2)	/* max frames in a frameburst */
-#define	M_MBURST_TXOP	(0x41 * 2)	/* max frameburst TXOP in unit of us */
-#define M_SYNTHPU_DLY	(0x4a * 2)	/* pre-wakeup for synthpu, default: 500 */
-#define	M_PRETBTT	(0x4b * 2)
-
-#define M_ALT_TXPWR_IDX		(M_PSM_SOFT_REGS + (0x3b * 2))	/* offset to the target txpwr */
-#define M_PHY_TX_FLT_PTR	(M_PSM_SOFT_REGS + (0x3d * 2))
-#define M_CTS_DURATION		(M_PSM_SOFT_REGS + (0x5c * 2))
-#define M_LP_RCCAL_OVR		(M_PSM_SOFT_REGS + (0x6b * 2))
-
-/* PKTENG Rx Stats Block */
-#define M_RXSTATS_BLK_PTR	(M_PSM_SOFT_REGS + (0x65 * 2))
-
-/* ucode debug status codes */
-#define	DBGST_INACTIVE		0	/* not valid really */
-#define	DBGST_INIT		1	/* after zeroing SHM, before suspending at init */
-#define	DBGST_ACTIVE		2	/* "normal" state */
-#define	DBGST_SUSPENDED		3	/* suspended */
-#define	DBGST_ASLEEP		4	/* asleep (PS mode) */
-
-/* Scratch Reg defs */
-typedef enum {
-	S_RSV0 = 0,
-	S_RSV1,
-	S_RSV2,
-
-	/* scratch registers for Dot11-contants */
-	S_DOT11_CWMIN,		/* CW-minimum                                   0x03 */
-	S_DOT11_CWMAX,		/* CW-maximum                                   0x04 */
-	S_DOT11_CWCUR,		/* CW-current                                   0x05 */
-	S_DOT11_SRC_LMT,	/* short retry count limit                      0x06 */
-	S_DOT11_LRC_LMT,	/* long retry count limit                       0x07 */
-	S_DOT11_DTIMCOUNT,	/* DTIM-count                                   0x08 */
-
-	/* Tx-side scratch registers */
-	S_SEQ_NUM,		/* hardware sequence number reg                 0x09 */
-	S_SEQ_NUM_FRAG,		/* seq-num for frags (Set at the start os MSDU  0x0A */
-	S_FRMRETX_CNT,		/* frame retx count                             0x0B */
-	S_SSRC,			/* Station short retry count                    0x0C */
-	S_SLRC,			/* Station long retry count                     0x0D */
-	S_EXP_RSP,		/* Expected response frame                      0x0E */
-	S_OLD_BREM,		/* Remaining backoff ctr                        0x0F */
-	S_OLD_CWWIN,		/* saved-off CW-cur                             0x10 */
-	S_TXECTL,		/* TXE-Ctl word constructed in scr-pad          0x11 */
-	S_CTXTST,		/* frm type-subtype as read from Tx-descr       0x12 */
-
-	/* Rx-side scratch registers */
-	S_RXTST,		/* Type and subtype in Rxframe                  0x13 */
-
-	/* Global state register */
-	S_STREG,		/* state storage actual bit maps below          0x14 */
-
-	S_TXPWR_SUM,		/* Tx power control: accumulator                0x15 */
-	S_TXPWR_ITER,		/* Tx power control: iteration                  0x16 */
-	S_RX_FRMTYPE,		/* Rate and PHY type for frames                 0x17 */
-	S_THIS_AGG,		/* Size of this AGG (A-MSDU)                    0x18 */
-
-	S_KEYINDX,		/*                                              0x19 */
-	S_RXFRMLEN,		/* Receive MPDU length in bytes                 0x1A */
-
-	/* Receive TSF time stored in SCR */
-	S_RXTSFTMRVAL_WD3,	/* TSF value at the start of rx                 0x1B */
-	S_RXTSFTMRVAL_WD2,	/* TSF value at the start of rx                 0x1C */
-	S_RXTSFTMRVAL_WD1,	/* TSF value at the start of rx                 0x1D */
-	S_RXTSFTMRVAL_WD0,	/* TSF value at the start of rx                 0x1E */
-	S_RXSSN,		/* Received start seq number for A-MPDU BA      0x1F */
-	S_RXQOSFLD,		/* Rx-QoS field (if present)                    0x20 */
-
-	/* Scratch pad regs used in microcode as temp storage */
-	S_TMP0,			/* stmp0                                        0x21 */
-	S_TMP1,			/* stmp1                                        0x22 */
-	S_TMP2,			/* stmp2                                        0x23 */
-	S_TMP3,			/* stmp3                                        0x24 */
-	S_TMP4,			/* stmp4                                        0x25 */
-	S_TMP5,			/* stmp5                                        0x26 */
-	S_PRQPENALTY_CTR,	/* Probe response queue penalty counter         0x27 */
-	S_ANTCNT,		/* unsuccessful attempts on current ant.        0x28 */
-	S_SYMBOL,		/* flag for possible symbol ctl frames          0x29 */
-	S_RXTP,			/* rx frame type                                0x2A */
-	S_STREG2,		/* extra state storage                          0x2B */
-	S_STREG3,		/* even more extra state storage                0x2C */
-	S_STREG4,		/* ...                                          0x2D */
-	S_STREG5,		/* remember to initialize it to zero            0x2E */
-
-	S_ADJPWR_IDX,
-	S_CUR_PTR,		/* Temp pointer for A-MPDU re-Tx SHM table      0x32 */
-	S_REVID4,		/* 0x33 */
-	S_INDX,			/* 0x34 */
-	S_ADDR0,		/* 0x35 */
-	S_ADDR1,		/* 0x36 */
-	S_ADDR2,		/* 0x37 */
-	S_ADDR3,		/* 0x38 */
-	S_ADDR4,		/* 0x39 */
-	S_ADDR5,		/* 0x3A */
-	S_TMP6,			/* 0x3B */
-	S_KEYINDX_BU,		/* Backup for Key index                         0x3C */
-	S_MFGTEST_TMP0,		/* Temp register used for RX test calculations  0x3D */
-	S_RXESN,		/* Received end sequence number for A-MPDU BA   0x3E */
-	S_STREG6,		/* 0x3F */
-} ePsmScratchPadRegDefinitions;
-
-#define S_BEACON_INDX	S_OLD_BREM
-#define S_PRS_INDX	S_OLD_CWWIN
-#define S_PHYTYPE	S_SSRC
-#define S_PHYVER	S_SLRC
-
-/* IHR SLOW_CTRL values */
-#define SLOW_CTRL_PDE		(1 << 0)
-#define SLOW_CTRL_FD		(1 << 8)
-
-/* ucode mac statistic counters in shared memory */
-typedef struct macstat {
-	u16 txallfrm;	/* 0x80 */
-	u16 txrtsfrm;	/* 0x82 */
-	u16 txctsfrm;	/* 0x84 */
-	u16 txackfrm;	/* 0x86 */
-	u16 txdnlfrm;	/* 0x88 */
-	u16 txbcnfrm;	/* 0x8a */
-	u16 txfunfl[8];	/* 0x8c - 0x9b */
-	u16 txtplunfl;	/* 0x9c */
-	u16 txphyerr;	/* 0x9e */
-	u16 pktengrxducast;	/* 0xa0 */
-	u16 pktengrxdmcast;	/* 0xa2 */
-	u16 rxfrmtoolong;	/* 0xa4 */
-	u16 rxfrmtooshrt;	/* 0xa6 */
-	u16 rxinvmachdr;	/* 0xa8 */
-	u16 rxbadfcs;	/* 0xaa */
-	u16 rxbadplcp;	/* 0xac */
-	u16 rxcrsglitch;	/* 0xae */
-	u16 rxstrt;		/* 0xb0 */
-	u16 rxdfrmucastmbss;	/* 0xb2 */
-	u16 rxmfrmucastmbss;	/* 0xb4 */
-	u16 rxcfrmucast;	/* 0xb6 */
-	u16 rxrtsucast;	/* 0xb8 */
-	u16 rxctsucast;	/* 0xba */
-	u16 rxackucast;	/* 0xbc */
-	u16 rxdfrmocast;	/* 0xbe */
-	u16 rxmfrmocast;	/* 0xc0 */
-	u16 rxcfrmocast;	/* 0xc2 */
-	u16 rxrtsocast;	/* 0xc4 */
-	u16 rxctsocast;	/* 0xc6 */
-	u16 rxdfrmmcast;	/* 0xc8 */
-	u16 rxmfrmmcast;	/* 0xca */
-	u16 rxcfrmmcast;	/* 0xcc */
-	u16 rxbeaconmbss;	/* 0xce */
-	u16 rxdfrmucastobss;	/* 0xd0 */
-	u16 rxbeaconobss;	/* 0xd2 */
-	u16 rxrsptmout;	/* 0xd4 */
-	u16 bcntxcancl;	/* 0xd6 */
-	u16 PAD;
-	u16 rxf0ovfl;	/* 0xda */
-	u16 rxf1ovfl;	/* 0xdc */
-	u16 rxf2ovfl;	/* 0xde */
-	u16 txsfovfl;	/* 0xe0 */
-	u16 pmqovfl;		/* 0xe2 */
-	u16 rxcgprqfrm;	/* 0xe4 */
-	u16 rxcgprsqovfl;	/* 0xe6 */
-	u16 txcgprsfail;	/* 0xe8 */
-	u16 txcgprssuc;	/* 0xea */
-	u16 prs_timeout;	/* 0xec */
-	u16 rxnack;
-	u16 frmscons;
-	u16 txnack;
-	u16 txglitch_nack;
-	u16 txburst;		/* 0xf6 # tx bursts */
-	u16 bphy_rxcrsglitch;	/* bphy rx crs glitch */
-	u16 phywatchdog;	/* 0xfa # of phy watchdog events */
-	u16 PAD;
-	u16 bphy_badplcp;	/* bphy bad plcp */
-} macstat_t;
-
-/* dot11 core-specific control flags */
-#define	SICF_PCLKE		0x0004	/* PHY clock enable */
-#define	SICF_PRST		0x0008	/* PHY reset */
-#define	SICF_MPCLKE		0x0010	/* MAC PHY clockcontrol enable */
-#define	SICF_FREF		0x0020	/* PLL FreqRefSelect (corerev >= 5) */
-/* NOTE: the following bw bits only apply when the core is attached
- * to a NPHY (and corerev >= 11 which it will always be for NPHYs).
- */
-#define	SICF_BWMASK		0x00c0	/* phy clock mask (b6 & b7) */
-#define	SICF_BW40		0x0080	/* 40MHz BW (160MHz phyclk) */
-#define	SICF_BW20		0x0040	/* 20MHz BW (80MHz phyclk) */
-#define	SICF_BW10		0x0000	/* 10MHz BW (40MHz phyclk) */
-#define	SICF_GMODE		0x2000	/* gmode enable */
-
-/* dot11 core-specific status flags */
-#define	SISF_2G_PHY		0x0001	/* 2.4G capable phy (corerev >= 5) */
-#define	SISF_5G_PHY		0x0002	/* 5G capable phy (corerev >= 5) */
-#define	SISF_FCLKA		0x0004	/* FastClkAvailable (corerev >= 5) */
-#define	SISF_DB_PHY		0x0008	/* Dualband phy (corerev >= 11) */
-
-/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg, radio and LPPHY regs are separated === */
-
-#define	BPHY_REG_OFT_BASE	0x0
-/* offsets for indirect access to bphy registers */
-#define	BPHY_BB_CONFIG		0x01
-#define	BPHY_ADCBIAS		0x02
-#define	BPHY_ANACORE		0x03
-#define	BPHY_PHYCRSTH		0x06
-#define	BPHY_TEST		0x0a
-#define	BPHY_PA_TX_TO		0x10
-#define	BPHY_SYNTH_DC_TO	0x11
-#define	BPHY_PA_TX_TIME_UP	0x12
-#define	BPHY_RX_FLTR_TIME_UP	0x13
-#define	BPHY_TX_POWER_OVERRIDE	0x14
-#define	BPHY_RF_OVERRIDE	0x15
-#define	BPHY_RF_TR_LOOKUP1	0x16
-#define	BPHY_RF_TR_LOOKUP2	0x17
-#define	BPHY_COEFFS		0x18
-#define	BPHY_PLL_OUT		0x19
-#define	BPHY_REFRESH_MAIN	0x1a
-#define	BPHY_REFRESH_TO0	0x1b
-#define	BPHY_REFRESH_TO1	0x1c
-#define	BPHY_RSSI_TRESH		0x20
-#define	BPHY_IQ_TRESH_HH	0x21
-#define	BPHY_IQ_TRESH_H		0x22
-#define	BPHY_IQ_TRESH_L		0x23
-#define	BPHY_IQ_TRESH_LL	0x24
-#define	BPHY_GAIN		0x25
-#define	BPHY_LNA_GAIN_RANGE	0x26
-#define	BPHY_JSSI		0x27
-#define	BPHY_TSSI_CTL		0x28
-#define	BPHY_TSSI		0x29
-#define	BPHY_TR_LOSS_CTL	0x2a
-#define	BPHY_LO_LEAKAGE		0x2b
-#define	BPHY_LO_RSSI_ACC	0x2c
-#define	BPHY_LO_IQMAG_ACC	0x2d
-#define	BPHY_TX_DC_OFF1		0x2e
-#define	BPHY_TX_DC_OFF2		0x2f
-#define	BPHY_PEAK_CNT_THRESH	0x30
-#define	BPHY_FREQ_OFFSET	0x31
-#define	BPHY_DIVERSITY_CTL	0x32
-#define	BPHY_PEAK_ENERGY_LO	0x33
-#define	BPHY_PEAK_ENERGY_HI	0x34
-#define	BPHY_SYNC_CTL		0x35
-#define	BPHY_TX_PWR_CTRL	0x36
-#define BPHY_TX_EST_PWR 	0x37
-#define	BPHY_STEP		0x38
-#define	BPHY_WARMUP		0x39
-#define	BPHY_LMS_CFF_READ	0x3a
-#define	BPHY_LMS_COEFF_I	0x3b
-#define	BPHY_LMS_COEFF_Q	0x3c
-#define	BPHY_SIG_POW		0x3d
-#define	BPHY_RFDC_CANCEL_CTL	0x3e
-#define	BPHY_HDR_TYPE		0x40
-#define	BPHY_SFD_TO		0x41
-#define	BPHY_SFD_CTL		0x42
-#define	BPHY_DEBUG		0x43
-#define	BPHY_RX_DELAY_COMP	0x44
-#define	BPHY_CRS_DROP_TO	0x45
-#define	BPHY_SHORT_SFD_NZEROS	0x46
-#define	BPHY_DSSS_COEFF1	0x48
-#define	BPHY_DSSS_COEFF2	0x49
-#define	BPHY_CCK_COEFF1		0x4a
-#define	BPHY_CCK_COEFF2		0x4b
-#define	BPHY_TR_CORR		0x4c
-#define	BPHY_ANGLE_SCALE	0x4d
-#define	BPHY_TX_PWR_BASE_IDX	0x4e
-#define	BPHY_OPTIONAL_MODES2	0x4f
-#define	BPHY_CCK_LMS_STEP	0x50
-#define	BPHY_BYPASS		0x51
-#define	BPHY_CCK_DELAY_LONG	0x52
-#define	BPHY_CCK_DELAY_SHORT	0x53
-#define	BPHY_PPROC_CHAN_DELAY	0x54
-#define	BPHY_DDFS_ENABLE	0x58
-#define	BPHY_PHASE_SCALE	0x59
-#define	BPHY_FREQ_CONTROL	0x5a
-#define	BPHY_LNA_GAIN_RANGE_10	0x5b
-#define	BPHY_LNA_GAIN_RANGE_32	0x5c
-#define	BPHY_OPTIONAL_MODES	0x5d
-#define	BPHY_RX_STATUS2		0x5e
-#define	BPHY_RX_STATUS3		0x5f
-#define	BPHY_DAC_CONTROL	0x60
-#define	BPHY_ANA11G_FILT_CTRL	0x62
-#define	BPHY_REFRESH_CTRL	0x64
-#define	BPHY_RF_OVERRIDE2	0x65
-#define	BPHY_SPUR_CANCEL_CTRL	0x66
-#define	BPHY_FINE_DIGIGAIN_CTRL	0x67
-#define	BPHY_RSSI_LUT		0x88
-#define	BPHY_RSSI_LUT_END	0xa7
-#define	BPHY_TSSI_LUT		0xa8
-#define	BPHY_TSSI_LUT_END	0xc7
-#define	BPHY_TSSI2PWR_LUT	0x380
-#define	BPHY_TSSI2PWR_LUT_END	0x39f
-#define	BPHY_LOCOMP_LUT		0x3a0
-#define	BPHY_LOCOMP_LUT_END	0x3bf
-#define	BPHY_TXGAIN_LUT		0x3c0
-#define	BPHY_TXGAIN_LUT_END	0x3ff
-
-/* Bits in BB_CONFIG: */
-#define	PHY_BBC_ANT_MASK	0x0180
-#define	PHY_BBC_ANT_SHIFT	7
-#define	BB_DARWIN		0x1000
-#define BBCFG_RESETCCA		0x4000
-#define BBCFG_RESETRX		0x8000
-
-/* Bits in phytest(0x0a): */
-#define	TST_DDFS		0x2000
-#define	TST_TXFILT1		0x0800
-#define	TST_UNSCRAM		0x0400
-#define	TST_CARR_SUPP		0x0200
-#define	TST_DC_COMP_LOOP	0x0100
-#define	TST_LOOPBACK		0x0080
-#define	TST_TXFILT0		0x0040
-#define	TST_TXTEST_ENABLE	0x0020
-#define	TST_TXTEST_RATE		0x0018
-#define	TST_TXTEST_PHASE	0x0007
-
-/* phytest txTestRate values */
-#define	TST_TXTEST_RATE_1MBPS	0
-#define	TST_TXTEST_RATE_2MBPS	1
-#define	TST_TXTEST_RATE_5_5MBPS	2
-#define	TST_TXTEST_RATE_11MBPS	3
-#define	TST_TXTEST_RATE_SHIFT	3
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#define SHM_BYT_CNT	0x2	/* IHR location */
-#define MAX_BYT_CNT	0x600	/* Maximum frame len */
-
-#endif				/* _D11_H */
diff --git a/drivers/staging/brcm80211/include/dhdioctl.h b/drivers/staging/brcm80211/include/dhdioctl.h
deleted file mode 100644
index 4d06e50..0000000
--- a/drivers/staging/brcm80211/include/dhdioctl.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _dhdioctl_h_
-#define	_dhdioctl_h_
-
-/* require default structure packing */
-#define BWL_DEFAULT_PACKING
-#include <packed_section_start.h>
-
-/* Linux network driver ioctl encoding */
-typedef struct dhd_ioctl {
-	uint cmd;		/* common ioctl definition */
-	void *buf;		/* pointer to user buffer */
-	uint len;		/* length of user buffer */
-	bool set;		/* get or set request (optional) */
-	uint used;		/* bytes read or written (optional) */
-	uint needed;		/* bytes needed (optional) */
-	uint driver;		/* to identify target driver */
-} dhd_ioctl_t;
-
-/* per-driver magic numbers */
-#define DHD_IOCTL_MAGIC		0x00444944
-
-/* bump this number if you change the ioctl interface */
-#define DHD_IOCTL_VERSION	1
-
-#define	DHD_IOCTL_MAXLEN	8192	/* max length ioctl buffer required */
-#define	DHD_IOCTL_SMLEN	256	/* "small" length ioctl buffer required */
-
-/* common ioctl definitions */
-#define DHD_GET_MAGIC				0
-#define DHD_GET_VERSION				1
-#define DHD_GET_VAR				2
-#define DHD_SET_VAR				3
-
-/* message levels */
-#define DHD_ERROR_VAL	0x0001
-#define DHD_TRACE_VAL	0x0002
-#define DHD_INFO_VAL	0x0004
-#define DHD_DATA_VAL	0x0008
-#define DHD_CTL_VAL	0x0010
-#define DHD_TIMER_VAL	0x0020
-#define DHD_HDRS_VAL	0x0040
-#define DHD_BYTES_VAL	0x0080
-#define DHD_INTR_VAL	0x0100
-#define DHD_LOG_VAL	0x0200
-#define DHD_GLOM_VAL	0x0400
-#define DHD_EVENT_VAL	0x0800
-#define DHD_BTA_VAL	0x1000
-#define DHD_ISCAN_VAL 0x2000
-
-#ifdef SDTEST
-/* For pktgen iovar */
-typedef struct dhd_pktgen {
-	uint version;		/* To allow structure change tracking */
-	uint freq;		/* Max ticks between tx/rx attempts */
-	uint count;		/* Test packets to send/rcv each attempt */
-	uint print;		/* Print counts every <print> attempts */
-	uint total;		/* Total packets (or bursts) */
-	uint minlen;		/* Minimum length of packets to send */
-	uint maxlen;		/* Maximum length of packets to send */
-	uint numsent;		/* Count of test packets sent */
-	uint numrcvd;		/* Count of test packets received */
-	uint numfail;		/* Count of test send failures */
-	uint mode;		/* Test mode (type of test packets) */
-	uint stop;		/* Stop after this many tx failures */
-} dhd_pktgen_t;
-
-/* Version in case structure changes */
-#define DHD_PKTGEN_VERSION 2
-
-/* Type of test packets to use */
-#define DHD_PKTGEN_ECHO		1	/* Send echo requests */
-#define DHD_PKTGEN_SEND		2	/* Send discard packets */
-#define DHD_PKTGEN_RXBURST	3	/* Request dongle send N packets */
-#define DHD_PKTGEN_RECV		4	/* Continuous rx from continuous
-					 tx dongle */
-#endif				/* SDTEST */
-
-/* Enter idle immediately (no timeout) */
-#define DHD_IDLE_IMMEDIATE	(-1)
-
-/* Values for idleclock iovar: other values are the sd_divisor to use
-	 when idle */
-#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change
-				 when idle */
-#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped
-				 (and use SD1 mode) */
-
-/* require default structure packing */
-#include <packed_section_end.h>
-
-#endif				/* _dhdioctl_h_ */
diff --git a/drivers/staging/brcm80211/include/hnddma.h b/drivers/staging/brcm80211/include/hnddma.h
index 4c5462b..5d079e7 100644
--- a/drivers/staging/brcm80211/include/hnddma.h
+++ b/drivers/staging/brcm80211/include/hnddma.h
@@ -22,6 +22,11 @@
 struct hnddma_pub;
 #endif				/* _hnddma_pub_ */
 
+/* map/unmap direction */
+#define	DMA_TX	1		/* TX direction for DMA */
+#define	DMA_RX	2		/* RX direction for DMA */
+#define BUS_SWAP32(v)		(v)
+
 /* range param for dma_getnexttxp() and dma_txreclaim */
 typedef enum txd_range {
 	HNDDMA_RANGE_ALL = 1,
@@ -143,52 +148,11 @@ struct hnddma_pub {
 	uint txnobuf;		/* tx out of dma descriptors */
 };
 
-extern struct hnddma_pub *dma_attach(struct osl_info *osh, char *name,
-			    si_t *sih,
+extern struct hnddma_pub *dma_attach(char *name, si_t *sih,
 			    void *dmaregstx, void *dmaregsrx, uint ntxd,
 			    uint nrxd, uint rxbufsize, int rxextheadroom,
 			    uint nrxpost, uint rxoffset, uint *msg_level);
-#ifdef BCMDMA32
-
-#define dma_detach(di)			((di)->di_fn->detach(di))
-#define dma_txreset(di)			((di)->di_fn->txreset(di))
-#define dma_rxreset(di)			((di)->di_fn->rxreset(di))
-#define dma_rxidle(di)			((di)->di_fn->rxidle(di))
-#define dma_txinit(di)                  ((di)->di_fn->txinit(di))
-#define dma_txenabled(di)               ((di)->di_fn->txenabled(di))
-#define dma_rxinit(di)                  ((di)->di_fn->rxinit(di))
-#define dma_txsuspend(di)               ((di)->di_fn->txsuspend(di))
-#define dma_txresume(di)                ((di)->di_fn->txresume(di))
-#define dma_txsuspended(di)             ((di)->di_fn->txsuspended(di))
-#define dma_txsuspendedidle(di)         ((di)->di_fn->txsuspendedidle(di))
-#define dma_txfast(di, p, commit)	((di)->di_fn->txfast(di, p, commit))
-#define dma_fifoloopbackenable(di)      ((di)->di_fn->fifoloopbackenable(di))
-#define dma_txstopped(di)               ((di)->di_fn->txstopped(di))
-#define dma_rxstopped(di)               ((di)->di_fn->rxstopped(di))
-#define dma_rxenable(di)                ((di)->di_fn->rxenable(di))
-#define dma_rxenabled(di)               ((di)->di_fn->rxenabled(di))
-#define dma_rx(di)                      ((di)->di_fn->rx(di))
-#define dma_rxfill(di)                  ((di)->di_fn->rxfill(di))
-#define dma_txreclaim(di, range)	((di)->di_fn->txreclaim(di, range))
-#define dma_rxreclaim(di)               ((di)->di_fn->rxreclaim(di))
-#define dma_getvar(di, name)		((di)->di_fn->d_getvar(di, name))
-#define dma_getnexttxp(di, range)	((di)->di_fn->getnexttxp(di, range))
-#define dma_getnextrxp(di, forceall)    ((di)->di_fn->getnextrxp(di, forceall))
-#define dma_peeknexttxp(di)             ((di)->di_fn->peeknexttxp(di))
-#define dma_peeknextrxp(di)             ((di)->di_fn->peeknextrxp(di))
-#define dma_rxparam_get(di, off, bufs)	((di)->di_fn->rxparam_get(di, off, bufs))
-
-#define dma_txblock(di)                 ((di)->di_fn->txblock(di))
-#define dma_txunblock(di)               ((di)->di_fn->txunblock(di))
-#define dma_txactive(di)                ((di)->di_fn->txactive(di))
-#define dma_rxactive(di)                ((di)->di_fn->rxactive(di))
-#define dma_txrotate(di)                ((di)->di_fn->txrotate(di))
-#define dma_counterreset(di)            ((di)->di_fn->counterreset(di))
-#define dma_ctrlflags(di, mask, flags)  ((di)->di_fn->ctrlflags((di), (mask), (flags)))
-#define dma_txpending(di)		((di)->di_fn->txpending(di))
-#define dma_txcommitted(di)		((di)->di_fn->txcommitted(di))
-
-#else				/* BCMDMA32 */
+
 extern const di_fcn_t dma64proc;
 
 #define dma_detach(di)			(dma64proc.detach(di))
@@ -231,7 +195,6 @@ extern const di_fcn_t dma64proc;
 #define dma_txpending(di)		(dma64proc.txpending(di))
 #define dma_txcommitted(di)		(dma64proc.txcommitted(di))
 
-#endif				/* BCMDMA32 */
 
 /* return addresswidth allowed
  * This needs to be done after SB attach but before dma attach.
@@ -239,8 +202,6 @@ extern const di_fcn_t dma64proc;
  * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
  */
 extern uint dma_addrwidth(si_t *sih, void *dmaregs);
-
-/* pio helpers */
-extern void dma_txpioloopback(struct osl_info *osh, dma32regs_t *);
-
+void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a);
 #endif				/* _hnddma_h_ */
diff --git a/drivers/staging/brcm80211/include/hndpmu.h b/drivers/staging/brcm80211/include/hndpmu.h
index a0110e4..3eea1f9 100644
--- a/drivers/staging/brcm80211/include/hndpmu.h
+++ b/drivers/staging/brcm80211/include/hndpmu.h
@@ -28,44 +28,41 @@
 #define SET_LDO_VOLTAGE_LNLDO1	9
 #define SET_LDO_VOLTAGE_LNLDO2_SEL	10
 
-extern void si_pmu_init(si_t *sih, struct osl_info *osh);
-extern void si_pmu_chip_init(si_t *sih, struct osl_info *osh);
-extern void si_pmu_pll_init(si_t *sih, struct osl_info *osh, u32 xtalfreq);
-extern void si_pmu_res_init(si_t *sih, struct osl_info *osh);
-extern void si_pmu_swreg_init(si_t *sih, struct osl_info *osh);
+extern void si_pmu_init(si_t *sih);
+extern void si_pmu_chip_init(si_t *sih);
+extern void si_pmu_pll_init(si_t *sih, u32 xtalfreq);
+extern void si_pmu_res_init(si_t *sih);
+extern void si_pmu_swreg_init(si_t *sih);
 
-extern u32 si_pmu_force_ilp(si_t *sih, struct osl_info *osh, bool force);
+extern u32 si_pmu_force_ilp(si_t *sih, bool force);
 
-extern u32 si_pmu_si_clock(si_t *sih, struct osl_info *osh);
-extern u32 si_pmu_cpu_clock(si_t *sih, struct osl_info *osh);
-extern u32 si_pmu_mem_clock(si_t *sih, struct osl_info *osh);
-extern u32 si_pmu_alp_clock(si_t *sih, struct osl_info *osh);
-extern u32 si_pmu_ilp_clock(si_t *sih, struct osl_info *osh);
+extern u32 si_pmu_si_clock(si_t *sih);
+extern u32 si_pmu_cpu_clock(si_t *sih);
+extern u32 si_pmu_mem_clock(si_t *sih);
+extern u32 si_pmu_alp_clock(si_t *sih);
+extern u32 si_pmu_ilp_clock(si_t *sih);
 
-extern void si_pmu_set_switcher_voltage(si_t *sih, struct osl_info *osh,
+extern void si_pmu_set_switcher_voltage(si_t *sih,
 					u8 bb_voltage, u8 rf_voltage);
-extern void si_pmu_set_ldo_voltage(si_t *sih, struct osl_info *osh, u8 ldo,
-				   u8 voltage);
-extern u16 si_pmu_fast_pwrup_delay(si_t *sih, struct osl_info *osh);
-extern void si_pmu_rcal(si_t *sih, struct osl_info *osh);
+extern void si_pmu_set_ldo_voltage(si_t *sih, u8 ldo, u8 voltage);
+extern u16 si_pmu_fast_pwrup_delay(si_t *sih);
+extern void si_pmu_rcal(si_t *sih);
 extern void si_pmu_pllupd(si_t *sih);
-extern void si_pmu_spuravoid(si_t *sih, struct osl_info *osh, u8 spuravoid);
+extern void si_pmu_spuravoid(si_t *sih, u8 spuravoid);
 
-extern bool si_pmu_is_otp_powered(si_t *sih, struct osl_info *osh);
-extern u32 si_pmu_measure_alpclk(si_t *sih, struct osl_info *osh);
+extern bool si_pmu_is_otp_powered(si_t *sih);
+extern u32 si_pmu_measure_alpclk(si_t *sih);
 
 extern u32 si_pmu_chipcontrol(si_t *sih, uint reg, u32 mask, u32 val);
 extern u32 si_pmu_regcontrol(si_t *sih, uint reg, u32 mask, u32 val);
 extern u32 si_pmu_pllcontrol(si_t *sih, uint reg, u32 mask, u32 val);
 extern void si_pmu_pllupd(si_t *sih);
-extern void si_pmu_sprom_enable(si_t *sih, struct osl_info *osh, bool enable);
+extern void si_pmu_sprom_enable(si_t *sih, bool enable);
 
 extern void si_pmu_radio_enable(si_t *sih, bool enable);
-extern u32 si_pmu_waitforclk_on_backplane(si_t *sih, struct osl_info *osh,
-					     u32 clk, u32 delay);
+extern u32 si_pmu_waitforclk_on_backplane(si_t *sih, u32 clk, u32 delay);
 
-extern void si_pmu_otp_power(si_t *sih, struct osl_info *osh, bool on);
-extern void si_sdiod_drive_strength_init(si_t *sih, struct osl_info *osh,
-					 u32 drivestrength);
+extern void si_pmu_otp_power(si_t *sih, bool on);
+extern void si_sdiod_drive_strength_init(si_t *sih, u32 drivestrength);
 
 #endif				/* _hndpmu_h_ */
diff --git a/drivers/staging/brcm80211/include/hndrte_armtrap.h b/drivers/staging/brcm80211/include/hndrte_armtrap.h
deleted file mode 100644
index 28f092c..0000000
--- a/drivers/staging/brcm80211/include/hndrte_armtrap.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_hndrte_armtrap_h
-#define	_hndrte_armtrap_h
-
-/* ARM trap handling */
-
-/* Trap types defined by ARM (see arminc.h) */
-
-/* Trap locations in lo memory */
-#define	TRAP_STRIDE	4
-#define FIRST_TRAP	TR_RST
-#define LAST_TRAP	(TR_FIQ * TRAP_STRIDE)
-
-#if defined(__ARM_ARCH_4T__)
-#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
-#elif defined(__ARM_ARCH_7M__)
-#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
-#endif				/* __ARM_ARCH_7M__ */
-
-/* The trap structure is defined here as offsets for assembly */
-#define	TR_TYPE		0x00
-#define	TR_EPC		0x04
-#define	TR_CPSR		0x08
-#define	TR_SPSR		0x0c
-#define	TR_REGS		0x10
-#define	TR_REG(n)	(TR_REGS + (n) * 4)
-#define	TR_SP		TR_REG(13)
-#define	TR_LR		TR_REG(14)
-#define	TR_PC		TR_REG(15)
-
-#define	TRAP_T_SIZE	80
-
-#ifndef	_LANGUAGE_ASSEMBLY
-
-typedef struct _trap_struct {
-	u32 type;
-	u32 epc;
-	u32 cpsr;
-	u32 spsr;
-	u32 r0;
-	u32 r1;
-	u32 r2;
-	u32 r3;
-	u32 r4;
-	u32 r5;
-	u32 r6;
-	u32 r7;
-	u32 r8;
-	u32 r9;
-	u32 r10;
-	u32 r11;
-	u32 r12;
-	u32 r13;
-	u32 r14;
-	u32 pc;
-} trap_t;
-
-#endif				/* !_LANGUAGE_ASSEMBLY */
-
-#endif				/* _hndrte_armtrap_h */
diff --git a/drivers/staging/brcm80211/include/hndrte_cons.h b/drivers/staging/brcm80211/include/hndrte_cons.h
deleted file mode 100644
index 5caa53f..0000000
--- a/drivers/staging/brcm80211/include/hndrte_cons.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define CBUF_LEN	(128)
-
-#define LOG_BUF_LEN	1024
-
-typedef struct {
-	u32 buf;		/* Can't be pointer on (64-bit) hosts */
-	uint buf_size;
-	uint idx;
-	char *_buf_compat;	/* Redundant pointer for backward compat. */
-} hndrte_log_t;
-
-typedef struct {
-	/* Virtual UART
-	 * When there is no UART (e.g. Quickturn),
-	 * the host should write a complete
-	 * input line directly into cbuf and then write
-	 * the length into vcons_in.
-	 * This may also be used when there is a real UART
-	 * (at risk of conflicting with
-	 * the real UART).  vcons_out is currently unused.
-	 */
-	volatile uint vcons_in;
-	volatile uint vcons_out;
-
-	/* Output (logging) buffer
-	 * Console output is written to a ring buffer log_buf at index log_idx.
-	 * The host may read the output when it sees log_idx advance.
-	 * Output will be lost if the output wraps around faster than the host
-	 * polls.
-	 */
-	hndrte_log_t log;
-
-	/* Console input line buffer
-	 * Characters are read one at a time into cbuf
-	 * until <CR> is received, then
-	 * the buffer is processed as a command line.
-	 * Also used for virtual UART.
-	 */
-	uint cbuf_idx;
-	char cbuf[CBUF_LEN];
-} hndrte_cons_t;
diff --git a/drivers/staging/brcm80211/include/msgtrace.h b/drivers/staging/brcm80211/include/msgtrace.h
deleted file mode 100644
index 9d9e53d..0000000
--- a/drivers/staging/brcm80211/include/msgtrace.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_MSGTRACE_H
-#define	_MSGTRACE_H
-
-/* This marks the start of a packed structure section. */
-#include <packed_section_start.h>
-
-#define MSGTRACE_VERSION 1
-
-/* Message trace header */
-typedef BWL_PRE_PACKED_STRUCT struct msgtrace_hdr {
-	u8 version;
-	u8 spare;
-	u16 len;		/* Len of the trace */
-	u32 seqnum;		/* Sequence number of message. Useful
-				 * if the messsage has been lost
-				 * because of DMA error or a bus reset
-				 * (ex: SDIO Func2)
-				 */
-	u32 discarded_bytes;	/* Number of discarded bytes because of
-				 trace overflow  */
-	u32 discarded_printf;	/* Number of discarded printf
-				 because of trace overflow */
-} BWL_POST_PACKED_STRUCT msgtrace_hdr_t;
-
-#define MSGTRACE_HDRLEN		sizeof(msgtrace_hdr_t)
-
-/* The hbus driver generates traces when sending a trace message.
- * This causes endless traces.
- * This flag must be set to true in any hbus traces.
- * The flag is reset in the function msgtrace_put.
- * This prevents endless traces but generates hasardous
- * lost of traces only in bus device code.
- * It is recommendat to set this flag in macro SD_TRACE
- * but not in SD_ERROR for avoiding missing
- * hbus error traces. hbus error trace should not generates endless traces.
- */
-extern bool msgtrace_hbus_trace;
-
-typedef void (*msgtrace_func_send_t) (void *hdl1, void *hdl2, u8 *hdr,
-				      u16 hdrlen, u8 *buf,
-				      u16 buflen);
-
-extern void msgtrace_sent(void);
-extern void msgtrace_put(char *buf, int count);
-extern void msgtrace_init(void *hdl1, void *hdl2,
-			  msgtrace_func_send_t func_send);
-
-/* This marks the end of a packed structure section. */
-#include <packed_section_end.h>
-
-#endif				/* _MSGTRACE_H */
diff --git a/drivers/staging/brcm80211/include/nicpci.h b/drivers/staging/brcm80211/include/nicpci.h
index 928818d..30321eb 100644
--- a/drivers/staging/brcm80211/include/nicpci.h
+++ b/drivers/staging/brcm80211/include/nicpci.h
@@ -45,17 +45,17 @@
 #else
 struct sbpcieregs;
 
-extern u8 pcicore_find_pci_capability(struct osl_info *osh, u8 req_cap_id,
+extern u8 pcicore_find_pci_capability(void *dev, u8 req_cap_id,
 					 unsigned char *buf, u32 *buflen);
-extern uint pcie_readreg(struct osl_info *osh, struct sbpcieregs *pcieregs,
+extern uint pcie_readreg(struct sbpcieregs *pcieregs,
 			 uint addrtype, uint offset);
-extern uint pcie_writereg(struct osl_info *osh, struct sbpcieregs *pcieregs,
+extern uint pcie_writereg(struct sbpcieregs *pcieregs,
 			  uint addrtype, uint offset, uint val);
 
 extern u8 pcie_clkreq(void *pch, u32 mask, u32 val);
 extern u32 pcie_lcreg(void *pch, u32 mask, u32 val);
 
-extern void *pcicore_init(si_t *sih, struct osl_info *osh, void *regs);
+extern void *pcicore_init(si_t *sih, void *pdev, void *regs);
 extern void pcicore_deinit(void *pch);
 extern void pcicore_attach(void *pch, char *pvars, int state);
 extern void pcicore_hwup(void *pch);
@@ -70,7 +70,7 @@ extern u32 pcicore_pcieserdesreg(void *pch, u32 mdioslave, u32 offset,
 extern u32 pcicore_pciereg(void *pch, u32 offset, u32 mask,
 			      u32 val, uint type);
 
-extern bool pcicore_pmecap_fast(struct osl_info *osh);
+extern bool pcicore_pmecap_fast(void *pch);
 extern void pcicore_pmeen(void *pch);
 extern void pcicore_pmeclr(void *pch);
 extern bool pcicore_pmestat(void *pch);
diff --git a/drivers/staging/brcm80211/include/osl.h b/drivers/staging/brcm80211/include/osl.h
deleted file mode 100644
index b282356..0000000
--- a/drivers/staging/brcm80211/include/osl.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _osl_h_
-#define _osl_h_
-
-/* osl handle type forward declaration */
-struct osl_info {
-	uint pktalloced;	/* Number of allocated packet buffers */
-	bool mmbus;		/* Bus supports memory-mapped registers */
-	uint magic;
-	void *pdev;
-	uint bustype;
-};
-
-typedef struct osl_dmainfo osldma_t;
-
-
-extern struct osl_info *osl_attach(void *pdev, uint bustype);
-extern void osl_detach(struct osl_info *osh);
-
-extern u32 g_assert_type;
-
-#if defined(BCMDBG_ASSERT)
-#define ASSERT(exp) \
-	  do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0)
-extern void osl_assert(char *exp, char *file, int line);
-#else
-#define ASSERT(exp)	do {} while (0)
-#endif  /* defined(BCMDBG_ASSERT) */
-
-/* PCI device bus # and slot # */
-#define OSL_PCI_BUS(osh)	osl_pci_bus(osh)
-#define OSL_PCI_SLOT(osh)	osl_pci_slot(osh)
-extern uint osl_pci_bus(struct osl_info *osh);
-extern uint osl_pci_slot(struct osl_info *osh);
-
-#define BUS_SWAP32(v)		(v)
-
-extern void *osl_dma_alloc_consistent(struct osl_info *osh, uint size,
-				      u16 align, uint *tot, unsigned long *pap);
-
-#ifdef BRCM_FULLMAC
-#define	DMA_ALLOC_CONSISTENT(osh, size, pap, dmah, alignbits) \
-	osl_dma_alloc_consistent((osh), (size), (0), (tot), (pap))
-#else
-#define	DMA_ALLOC_CONSISTENT(osh, size, align, tot, pap, dmah) \
-	osl_dma_alloc_consistent((osh), (size), (align), (tot), (pap))
-#endif /* BRCM_FULLMAC */
-
-#define	DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \
-	osl_dma_free_consistent((osh), (void *)(va), (size), (pa))
-extern void osl_dma_free_consistent(struct osl_info *osh, void *va,
-				    uint size, unsigned long pa);
-
-/* map/unmap direction */
-#define	DMA_TX	1		/* TX direction for DMA */
-#define	DMA_RX	2		/* RX direction for DMA */
-
-/* map/unmap shared (dma-able) memory */
-#define	DMA_MAP(osh, va, size, direction, p, dmah) \
-	osl_dma_map((osh), (va), (size), (direction))
-#define	DMA_UNMAP(osh, pa, size, direction, p, dmah) \
-	osl_dma_unmap((osh), (pa), (size), (direction))
-extern uint osl_dma_map(struct osl_info *osh, void *va, uint size,
-			int direction);
-extern void osl_dma_unmap(struct osl_info *osh, uint pa, uint size,
-			  int direction);
-
-/* register access macros */
-#if defined(BCMSDIO)
-#ifdef BRCM_FULLMAC
-#include <bcmsdh.h>
-#endif
-#define OSL_WRITE_REG(osh, r, v) \
-		(bcmsdh_reg_write(NULL, (unsigned long)(r), sizeof(*(r)), (v)))
-#define OSL_READ_REG(osh, r) \
-		(bcmsdh_reg_read(NULL, (unsigned long)(r), sizeof(*(r))))
-#endif
-
-#if defined(BCMSDIO)
-#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) \
-	if ((osh)->mmbus) \
-		mmap_op else bus_op
-#define SELECT_BUS_READ(osh, mmap_op, bus_op) \
-	((osh)->mmbus) ?  mmap_op : bus_op
-#else
-#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) mmap_op
-#define SELECT_BUS_READ(osh, mmap_op, bus_op) mmap_op
-#endif
-
-/* the largest reasonable packet buffer driver uses for ethernet MTU in bytes */
-#define	PKTBUFSZ	2048
-
-#define OSL_SYSUPTIME()		((u32)jiffies * (1000 / HZ))
-#define	printf(fmt, args...)	printk(fmt , ## args)
-#ifdef BRCM_FULLMAC
-#include <linux/kernel.h>	/* for vsn/printf's */
-#include <linux/string.h>	/* for mem*, str* */
-#endif
-/* bcopy's: Linux kernel doesn't provide these (anymore) */
-#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
-
-/* register access macros */
-#ifndef IL_BIGENDIAN
-#ifndef __mips__
-#define R_REG(osh, r) (\
-	SELECT_BUS_READ(osh, sizeof(*(r)) == sizeof(u8) ? \
-	readb((volatile u8*)(r)) : \
-	sizeof(*(r)) == sizeof(u16) ? readw((volatile u16*)(r)) : \
-	readl((volatile u32*)(r)), OSL_READ_REG(osh, r)) \
-)
-#else				/* __mips__ */
-#define R_REG(osh, r) (\
-	SELECT_BUS_READ(osh, \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			__asm__ __volatile__("sync"); \
-			switch (sizeof(*(r))) { \
-			case sizeof(u8): \
-				__osl_v = readb((volatile u8*)(r)); \
-				break; \
-			case sizeof(u16): \
-				__osl_v = readw((volatile u16*)(r)); \
-				break; \
-			case sizeof(u32): \
-				__osl_v = \
-				readl((volatile u32*)(r)); \
-				break; \
-			} \
-			__asm__ __volatile__("sync"); \
-			__osl_v; \
-		}), \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			__asm__ __volatile__("sync"); \
-			__osl_v = OSL_READ_REG(osh, r); \
-			__asm__ __volatile__("sync"); \
-			__osl_v; \
-		})) \
-)
-#endif				/* __mips__ */
-
-#define W_REG(osh, r, v) do { \
-	SELECT_BUS_WRITE(osh,  \
-		switch (sizeof(*(r))) { \
-		case sizeof(u8): \
-			writeb((u8)(v), (volatile u8*)(r)); break; \
-		case sizeof(u16): \
-			writew((u16)(v), (volatile u16*)(r)); break; \
-		case sizeof(u32): \
-			writel((u32)(v), (volatile u32*)(r)); break; \
-		}, \
-		(OSL_WRITE_REG(osh, r, v))); \
-	} while (0)
-#else				/* IL_BIGENDIAN */
-#define R_REG(osh, r) (\
-	SELECT_BUS_READ(osh, \
-		({ \
-			__typeof(*(r)) __osl_v; \
-			switch (sizeof(*(r))) { \
-			case sizeof(u8): \
-				__osl_v = \
-				readb((volatile u8*)((r)^3)); \
-				break; \
-			case sizeof(u16): \
-				__osl_v = \
-				readw((volatile u16*)((r)^2)); \
-				break; \
-			case sizeof(u32): \
-				__osl_v = readl((volatile u32*)(r)); \
-				break; \
-			} \
-			__osl_v; \
-		}), \
-		OSL_READ_REG(osh, r)) \
-)
-#define W_REG(osh, r, v) do { \
-	SELECT_BUS_WRITE(osh,  \
-		switch (sizeof(*(r))) { \
-		case sizeof(u8):	\
-			writeb((u8)(v), \
-			(volatile u8*)((r)^3)); break; \
-		case sizeof(u16):	\
-			writew((u16)(v), \
-			(volatile u16*)((r)^2)); break; \
-		case sizeof(u32):	\
-			writel((u32)(v), \
-			(volatile u32*)(r)); break; \
-		}, \
-		(OSL_WRITE_REG(osh, r, v))); \
-	} while (0)
-#endif				/* IL_BIGENDIAN */
-
-#define	bcopy(src, dst, len)	memcpy((dst), (src), (len))
-
-/* packet primitives */
-extern struct sk_buff *pkt_buf_get_skb(struct osl_info *osh, uint len);
-extern void pkt_buf_free_skb(struct osl_info *osh, struct sk_buff *skb, bool send);
-
-#endif /* _osl_h_ */
diff --git a/drivers/staging/brcm80211/include/packed_section_end.h b/drivers/staging/brcm80211/include/packed_section_end.h
deleted file mode 100644
index 04c7d43..0000000
--- a/drivers/staging/brcm80211/include/packed_section_end.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
- * and undefined in packed_section_end.h. If it is NOT defined at this
- * point, then there is a missing include of packed_section_start.h.
- */
-#ifdef BWL_PACKED_SECTION
-#undef BWL_PACKED_SECTION
-#else
-#error "BWL_PACKED_SECTION is NOT defined!"
-#endif
-
-/* Compiler-specific directives for structure packing are declared in
- * packed_section_start.h. This marks the end of the structure packing section,
- * so, undef them here.
- */
-#undef	BWL_PRE_PACKED_STRUCT
-#undef	BWL_POST_PACKED_STRUCT
diff --git a/drivers/staging/brcm80211/include/packed_section_start.h b/drivers/staging/brcm80211/include/packed_section_start.h
deleted file mode 100644
index 60e862a..0000000
--- a/drivers/staging/brcm80211/include/packed_section_start.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h
- * and undefined in packed_section_end.h. If it is already defined at this
- * point, then there is a missing include of packed_section_end.h.
- */
-#ifdef BWL_PACKED_SECTION
-#error "BWL_PACKED_SECTION is already defined!"
-#else
-#define BWL_PACKED_SECTION
-#endif
-
-/* Declare compiler-specific directives for structure packing. */
-#if defined(__GNUC__)
-#define	BWL_PRE_PACKED_STRUCT
-#define	BWL_POST_PACKED_STRUCT	__attribute__((packed))
-#elif defined(__CC_ARM)
-#define	BWL_PRE_PACKED_STRUCT	__packed
-#define	BWL_POST_PACKED_STRUCT
-#else
-#error "Unknown compiler!"
-#endif
diff --git a/drivers/staging/brcm80211/include/pci_core.h b/drivers/staging/brcm80211/include/pci_core.h
deleted file mode 100644
index 9153dcb..0000000
--- a/drivers/staging/brcm80211/include/pci_core.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_PCI_CORE_H_
-#define	_PCI_CORE_H_
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif
-
-/* Sonics side: PCI core and host control registers */
-struct sbpciregs {
-	u32 control;		/* PCI control */
-	u32 PAD[3];
-	u32 arbcontrol;	/* PCI arbiter control */
-	u32 clkrun;		/* Clkrun Control (>=rev11) */
-	u32 PAD[2];
-	u32 intstatus;	/* Interrupt status */
-	u32 intmask;		/* Interrupt mask */
-	u32 sbtopcimailbox;	/* Sonics to PCI mailbox */
-	u32 PAD[9];
-	u32 bcastaddr;	/* Sonics broadcast address */
-	u32 bcastdata;	/* Sonics broadcast data */
-	u32 PAD[2];
-	u32 gpioin;		/* ro: gpio input (>=rev2) */
-	u32 gpioout;		/* rw: gpio output (>=rev2) */
-	u32 gpioouten;	/* rw: gpio output enable (>= rev2) */
-	u32 gpiocontrol;	/* rw: gpio control (>= rev2) */
-	u32 PAD[36];
-	u32 sbtopci0;	/* Sonics to PCI translation 0 */
-	u32 sbtopci1;	/* Sonics to PCI translation 1 */
-	u32 sbtopci2;	/* Sonics to PCI translation 2 */
-	u32 PAD[189];
-	u32 pcicfg[4][64];	/* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
-	u16 sprom[36];	/* SPROM shadow Area */
-	u32 PAD[46];
-};
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-/* PCI control */
-#define PCI_RST_OE	0x01	/* When set, drives PCI_RESET out to pin */
-#define PCI_RST		0x02	/* Value driven out to pin */
-#define PCI_CLK_OE	0x04	/* When set, drives clock as gated by PCI_CLK out to pin */
-#define PCI_CLK		0x08	/* Gate for clock driven out to pin */
-
-/* PCI arbiter control */
-#define PCI_INT_ARB	0x01	/* When set, use an internal arbiter */
-#define PCI_EXT_ARB	0x02	/* When set, use an external arbiter */
-/* ParkID - for PCI corerev >= 8 */
-#define PCI_PARKID_MASK		0x1c	/* Selects which agent is parked on an idle bus */
-#define PCI_PARKID_SHIFT	2
-#define PCI_PARKID_EXT0		0	/* External master 0 */
-#define PCI_PARKID_EXT1		1	/* External master 1 */
-#define PCI_PARKID_EXT2		2	/* External master 2 */
-#define PCI_PARKID_EXT3		3	/* External master 3 (rev >= 11) */
-#define PCI_PARKID_INT		3	/* Internal master (rev < 11) */
-#define PCI11_PARKID_INT	4	/* Internal master (rev >= 11) */
-#define PCI_PARKID_LAST		4	/* Last active master (rev < 11) */
-#define PCI11_PARKID_LAST	5	/* Last active master (rev >= 11) */
-
-#define PCI_CLKRUN_DSBL	0x8000	/* Bit 15 forceClkrun */
-
-/* Interrupt status/mask */
-#define PCI_INTA	0x01	/* PCI INTA# is asserted */
-#define PCI_INTB	0x02	/* PCI INTB# is asserted */
-#define PCI_SERR	0x04	/* PCI SERR# has been asserted (write one to clear) */
-#define PCI_PERR	0x08	/* PCI PERR# has been asserted (write one to clear) */
-#define PCI_PME		0x10	/* PCI PME# is asserted */
-
-/* (General) PCI/SB mailbox interrupts, two bits per pci function */
-#define	MAILBOX_F0_0	0x100	/* function 0, int 0 */
-#define	MAILBOX_F0_1	0x200	/* function 0, int 1 */
-#define	MAILBOX_F1_0	0x400	/* function 1, int 0 */
-#define	MAILBOX_F1_1	0x800	/* function 1, int 1 */
-#define	MAILBOX_F2_0	0x1000	/* function 2, int 0 */
-#define	MAILBOX_F2_1	0x2000	/* function 2, int 1 */
-#define	MAILBOX_F3_0	0x4000	/* function 3, int 0 */
-#define	MAILBOX_F3_1	0x8000	/* function 3, int 1 */
-
-/* Sonics broadcast address */
-#define BCAST_ADDR_MASK	0xff	/* Broadcast register address */
-
-/* Sonics to PCI translation types */
-#define SBTOPCI0_MASK	0xfc000000
-#define SBTOPCI1_MASK	0xfc000000
-#define SBTOPCI2_MASK	0xc0000000
-#define SBTOPCI_MEM	0
-#define SBTOPCI_IO	1
-#define SBTOPCI_CFG0	2
-#define SBTOPCI_CFG1	3
-#define	SBTOPCI_PREF	0x4	/* prefetch enable */
-#define	SBTOPCI_BURST	0x8	/* burst enable */
-#define	SBTOPCI_RC_MASK		0x30	/* read command (>= rev11) */
-#define	SBTOPCI_RC_READ		0x00	/* memory read */
-#define	SBTOPCI_RC_READLINE	0x10	/* memory read line */
-#define	SBTOPCI_RC_READMULTI	0x20	/* memory read multiple */
-
-/* PCI core index in SROM shadow area */
-#define SRSH_PI_OFFSET	0	/* first word */
-#define SRSH_PI_MASK	0xf000	/* bit 15:12 */
-#define SRSH_PI_SHIFT	12	/* bit 15:12 */
-
-#endif				/* _PCI_CORE_H_ */
diff --git a/drivers/staging/brcm80211/include/pcicfg.h b/drivers/staging/brcm80211/include/pcicfg.h
index 3a19e1d..675554a 100644
--- a/drivers/staging/brcm80211/include/pcicfg.h
+++ b/drivers/staging/brcm80211/include/pcicfg.h
@@ -388,7 +388,7 @@ typedef struct _pciconfig_cap_msi {
 	u32 msgaddr;
 } pciconfig_cap_msi;
 
-/* Data structure to define the Power managment facility
+/* Data structure to define the Power management facility
  * Valid for PCI and PCIE configurations
  */
 typedef struct _pciconfig_cap_pwrmgmt {
@@ -465,8 +465,8 @@ typedef struct _pcie_enhanced_caphdr {
 #define bar0_window	dev_dep[0x80 - 0x40]
 #define bar1_window	dev_dep[0x84 - 0x40]
 #define sprom_control	dev_dep[0x88 - 0x40]
-#define	PCI_BAR0_WIN		0x80	/* backplane addres space accessed by BAR0 */
-#define	PCI_BAR1_WIN		0x84	/* backplane addres space accessed by BAR1 */
+#define	PCI_BAR0_WIN		0x80	/* backplane address space accessed by BAR0 */
+#define	PCI_BAR1_WIN		0x84	/* backplane address space accessed by BAR1 */
 #define	PCI_SPROM_CONTROL	0x88	/* sprom property control */
 #define	PCI_BAR1_CONTROL	0x8c	/* BAR1 region burst control */
 #define	PCI_INT_STATUS		0x90	/* PCI and other cores interrupts */
@@ -475,7 +475,7 @@ typedef struct _pcie_enhanced_caphdr {
 #define PCI_BACKPLANE_ADDR	0xa0	/* address an arbitrary location on the system backplane */
 #define PCI_BACKPLANE_DATA	0xa4	/* data at the location specified by above address */
 #define	PCI_CLK_CTL_ST		0xa8	/* pci config space clock control/status (>=rev14) */
-#define	PCI_BAR0_WIN2		0xac	/* backplane addres space accessed by second 4KB of BAR0 */
+#define	PCI_BAR0_WIN2		0xac	/* backplane address space accessed by second 4KB of BAR0 */
 #define	PCI_GPIO_IN		0xb0	/* pci config space gpio input (>=rev3) */
 #define	PCI_GPIO_OUT		0xb4	/* pci config space gpio output (>=rev3) */
 #define	PCI_GPIO_OUTEN		0xb8	/* pci config space gpio output enable (>=rev3) */
diff --git a/drivers/staging/brcm80211/include/proto/802.11.h b/drivers/staging/brcm80211/include/proto/802.11.h
index ffde19c..374125d 100644
--- a/drivers/staging/brcm80211/include/proto/802.11.h
+++ b/drivers/staging/brcm80211/include/proto/802.11.h
@@ -17,20 +17,16 @@
 #ifndef _802_11_H_
 #define _802_11_H_
 
-#include <proto/wpa.h>
-#include <packed_section_start.h>
+#include <linux/if_ether.h>
 
 #define DOT11_A3_HDR_LEN		24
 #define DOT11_A4_HDR_LEN		30
 #define DOT11_MAC_HDR_LEN		DOT11_A3_HDR_LEN
-#define DOT11_FCS_LEN			4
 #define DOT11_ICV_AES_LEN		8
 #define DOT11_QOS_LEN			2
 
 #define DOT11_IV_MAX_LEN		8
 
-#define DOT11_MAX_SSID_LEN		32
-
 #define DOT11_DEFAULT_RTS_LEN		2347
 
 #define DOT11_MIN_FRAG_LEN		256
@@ -45,23 +41,6 @@
 
 #define DOT11_OUI_LEN			3
 
-BWL_PRE_PACKED_STRUCT struct dot11_header {
-	u16 fc;
-	u16 durid;
-	struct ether_addr a1;
-	struct ether_addr a2;
-	struct ether_addr a3;
-	u16 seq;
-	struct ether_addr a4;
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
-	u16 fc;
-	u16 durid;
-	struct ether_addr ra;
-	struct ether_addr ta;
-} BWL_POST_PACKED_STRUCT;
-
 #define	DOT11_RTS_LEN		16
 #define	DOT11_CTS_LEN		10
 #define	DOT11_ACK_LEN		10
@@ -69,23 +48,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_rts_frame {
 #define DOT11_BA_BITMAP_LEN		128
 #define DOT11_BA_LEN		4
 
-BWL_PRE_PACKED_STRUCT struct dot11_management_header {
-	u16 fc;
-	u16 durid;
-	struct ether_addr da;
-	struct ether_addr sa;
-	struct ether_addr bssid;
-	u16 seq;
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_MGMT_HDR_LEN	24
-
-BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb {
-	u32 timestamp[2];
-	u16 beacon_interval;
-	u16 capability;
-} BWL_POST_PACKED_STRUCT;
-#define	DOT11_BCN_PRB_LEN	12
-
 #define WME_OUI			"\x00\x50\xf2"
 #define WME_VER			1
 #define WME_TYPE		2
@@ -102,14 +64,14 @@ typedef u8 ac_bitmap_t;
 #define AC_BITMAP_ALL		0xf
 #define AC_BITMAP_TST(ab, ac)	(((ab) & (1 << (ac))) != 0)
 
-BWL_PRE_PACKED_STRUCT struct edcf_acparam {
+struct edcf_acparam {
 	u8 ACI;
 	u8 ECW;
 	u16 TXOP;
-} BWL_POST_PACKED_STRUCT;
+} __attribute__((packed));
 typedef struct edcf_acparam edcf_acparam_t;
 
-BWL_PRE_PACKED_STRUCT struct wme_param_ie {
+struct wme_param_ie {
 	u8 oui[3];
 	u8 type;
 	u8 subtype;
@@ -117,7 +79,7 @@ BWL_PRE_PACKED_STRUCT struct wme_param_ie {
 	u8 qosinfo;
 	u8 rsvd;
 	edcf_acparam_t acparam[AC_COUNT];
-} BWL_POST_PACKED_STRUCT;
+} __attribute__((packed));
 typedef struct wme_param_ie wme_param_ie_t;
 #define WME_PARAM_IE_LEN            24
 
@@ -150,60 +112,14 @@ typedef struct wme_param_ie wme_param_ie_t;
 
 #define EDCF_AC_VO_TXOP_AP           0x002f
 
-#define DOT11_OPEN_SYSTEM	0
-#define DOT11_SHARED_KEY	1
-
-#define FC_TYPE_MASK		0xC
-#define FC_TYPE_SHIFT		2
-#define FC_SUBTYPE_MASK		0xF0
-#define FC_SUBTYPE_SHIFT	4
-#define FC_MOREFRAG		0x400
-
 #define SEQNUM_SHIFT		4
 #define SEQNUM_MAX		0x1000
 #define FRAGNUM_MASK		0xF
 
-#define FC_TYPE_MNG		0
-#define FC_TYPE_CTL		1
-#define FC_TYPE_DATA		2
-
-#define FC_SUBTYPE_PROBE_REQ		4
-#define FC_SUBTYPE_PROBE_RESP		5
-#define FC_SUBTYPE_BEACON		8
-#define FC_SUBTYPE_PS_POLL		10
-#define FC_SUBTYPE_RTS			11
-#define FC_SUBTYPE_CTS			12
-
-#define FC_SUBTYPE_ANY_QOS(s)		(((s) & 8) != 0)
-
-#define FC_KIND_MASK		(FC_TYPE_MASK | FC_SUBTYPE_MASK)
-
-#define FC_KIND(t, s)	(((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT))
-
-#define FC_SUBTYPE(fc)	(((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT)
-#define FC_TYPE(fc)	(((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT)
-
-#define FC_PROBE_REQ	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ)
-#define FC_PROBE_RESP	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP)
-#define FC_BEACON	FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON)
-#define FC_PS_POLL	FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL)
-#define FC_RTS		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS)
-#define FC_CTS		FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS)
-
-#define TLV_LEN_OFF		1
-#define TLV_HDR_LEN		2
-#define TLV_BODY_OFF		2
-
 #define DOT11_MNG_RSN_ID			48
 #define DOT11_MNG_WPA_ID			221
 #define DOT11_MNG_VS_ID				221
 
-#define DOT11_CAP_ESS				0x0001
-#define DOT11_CAP_IBSS				0x0002
-#define DOT11_CAP_PRIVACY			0x0010
-#define DOT11_CAP_SHORT				0x0020
-#define DOT11_CAP_SHORTSLOT			0x0400
-
 #define DOT11_BSSTYPE_INFRASTRUCTURE		0
 #define DOT11_BSSTYPE_ANY			2
 #define DOT11_SCANTYPE_ACTIVE			0
@@ -253,43 +169,12 @@ typedef struct d11cnt {
 
 #define MCSSET_LEN	16
 
-BWL_PRE_PACKED_STRUCT struct ht_cap_ie {
-	u16 cap;
-	u8 params;
-	u8 supp_mcs[MCSSET_LEN];
-	u16 ext_htcap;
-	u32 txbf_cap;
-	u8 as_cap;
-} BWL_POST_PACKED_STRUCT;
-typedef struct ht_cap_ie ht_cap_ie_t;
-
 #define HT_CAP_IE_LEN		26
 
-#define HT_CAP_LDPC_CODING	0x0001
-#define HT_CAP_40MHZ		0x0002
-#define HT_CAP_MIMO_PS_MASK	0x000C
-#define HT_CAP_MIMO_PS_SHIFT	0x0002
-#define HT_CAP_MIMO_PS_OFF	0x0003
-#define HT_CAP_MIMO_PS_ON	0x0000
-#define HT_CAP_GF		0x0010
-#define HT_CAP_SHORT_GI_20	0x0020
-#define HT_CAP_SHORT_GI_40	0x0040
-#define HT_CAP_TX_STBC		0x0080
-#define HT_CAP_RX_STBC_MASK	0x0300
-#define HT_CAP_RX_STBC_SHIFT	8
-#define HT_CAP_MAX_AMSDU	0x0800
-#define HT_CAP_DSSS_CCK	0x1000
-#define HT_CAP_40MHZ_INTOLERANT 0x4000
-
 #define HT_CAP_RX_STBC_NO		0x0
 #define HT_CAP_RX_STBC_ONE_STREAM	0x1
 
-#define HT_PARAMS_RX_FACTOR_MASK	0x03
-
-#define AMPDU_MAX_MPDU_DENSITY	7
-#define AMPDU_RX_FACTOR_16K	1
-#define AMPDU_RX_FACTOR_32K	2
-#define AMPDU_RX_FACTOR_64K	3
+#define AMPDU_MAX_MPDU_DENSITY	IEEE80211_HT_MPDU_DENSITY_16
 
 #define AMPDU_DELIMITER_LEN	4
 
@@ -308,15 +193,8 @@ typedef struct ht_cap_ie ht_cap_ie_t;
 #define RSN_AKM_PSK		2
 
 #define DOT11_MAX_DEFAULT_KEYS	4
-#define DOT11_MAX_KEY_SIZE	32
 #define DOT11_WPA_KEY_RSC_LEN   8
 
-#define WEP1_KEY_SIZE		5
-#define WEP128_KEY_SIZE		13
-#define TKIP_KEY_SIZE		32
-#define AES_KEY_SIZE		16
-
 #define BRCM_OUI		"\x00\x10\x18"
-#include <packed_section_end.h>
 
 #endif				/* _802_11_H_ */
diff --git a/drivers/staging/brcm80211/include/proto/802.1d.h b/drivers/staging/brcm80211/include/proto/802.1d.h
deleted file mode 100644
index 9802d87..0000000
--- a/drivers/staging/brcm80211/include/proto/802.1d.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _802_1_D_
-#define _802_1_D_
-
-#define	PRIO_8021D_NONE		2
-#define	PRIO_8021D_BK		1
-#define	PRIO_8021D_BE		0
-#define	PRIO_8021D_EE		3
-#define	PRIO_8021D_CL		4
-#define	PRIO_8021D_VI		5
-#define	PRIO_8021D_VO		6
-#define	PRIO_8021D_NC		7
-#define	MAXPRIO			7
-#define NUMPRIO			(MAXPRIO + 1)
-
-#define ALLPRIO		-1
-
-#define PRIO2PREC(prio) \
-	(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
-	((prio^2)) : (prio))
-
-#endif				/* _802_1_D_ */
diff --git a/drivers/staging/brcm80211/include/proto/bcmeth.h b/drivers/staging/brcm80211/include/proto/bcmeth.h
index f7d3d8d..e98ee65 100644
--- a/drivers/staging/brcm80211/include/proto/bcmeth.h
+++ b/drivers/staging/brcm80211/include/proto/bcmeth.h
@@ -17,8 +17,6 @@
 #ifndef _BCMETH_H_
 #define _BCMETH_H_
 
-#include <packed_section_start.h>
-
 #define	BCMILCP_SUBTYPE_RATE		1
 #define	BCMILCP_SUBTYPE_LINK		2
 #define	BCMILCP_SUBTYPE_CSA		3
@@ -35,14 +33,12 @@
 #define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH	8
 #define BCMILCP_BCM_SUBTYPEHDR_VERSION		0
 
-typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr {
+typedef  struct bcmeth_hdr {
 	u16 subtype;
 	u16 length;
 	u8 version;
 	u8 oui[3];
 	u16 usr_subtype;
-} BWL_POST_PACKED_STRUCT bcmeth_hdr_t;
-
-#include <packed_section_end.h>
+} __attribute__((packed)) bcmeth_hdr_t;
 
 #endif				/* _BCMETH_H_ */
diff --git a/drivers/staging/brcm80211/include/proto/bcmevent.h b/drivers/staging/brcm80211/include/proto/bcmevent.h
index 865d157..1b60789 100644
--- a/drivers/staging/brcm80211/include/proto/bcmevent.h
+++ b/drivers/staging/brcm80211/include/proto/bcmevent.h
@@ -17,7 +17,7 @@
 #ifndef _BCMEVENT_H_
 #define _BCMEVENT_H_
 
-#include <packed_section_start.h>
+#include <linux/if_ether.h>
 
 #define BCM_EVENT_MSG_VERSION		1
 #define BCM_MSG_IFNAME_MAX		16
@@ -26,7 +26,7 @@
 #define WLC_EVENT_MSG_FLUSHTXQ		0x02
 #define WLC_EVENT_MSG_GROUP		0x04
 
-typedef BWL_PRE_PACKED_STRUCT struct {
+typedef struct {
 	u16 version;
 	u16 flags;
 	u32 event_type;
@@ -34,16 +34,16 @@ typedef BWL_PRE_PACKED_STRUCT struct {
 	u32 reason;
 	u32 auth_type;
 	u32 datalen;
-	struct ether_addr addr;
+	u8 addr[ETH_ALEN];
 	char ifname[BCM_MSG_IFNAME_MAX];
-} BWL_POST_PACKED_STRUCT wl_event_msg_t;
+} __attribute__((packed)) wl_event_msg_t;
 
 #ifdef BRCM_FULLMAC
-typedef BWL_PRE_PACKED_STRUCT struct bcm_event {
-	struct ether_header eth;
+typedef struct bcm_event {
+	struct ethhdr eth;
 	bcmeth_hdr_t		bcm_hdr;
 	wl_event_msg_t		event;
-} BWL_POST_PACKED_STRUCT bcm_event_t;
+} __attribute__((packed)) bcm_event_t;
 #endif
 #define BCM_MSG_LEN	(sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - \
 	sizeof(struct ether_header))
@@ -191,14 +191,6 @@ extern const int bcmevent_names_size;
 #define WLC_E_SUP_SEND_FAIL		13
 #define WLC_E_SUP_DEAUTH		14
 
-typedef struct wl_event_data_if {
-	u8 ifidx;
-	u8 opcode;
-	u8 reserved;
-	u8 bssidx;
-	u8 role;
-} wl_event_data_if_t;
-
 #define WLC_E_IF_ADD		1
 #define WLC_E_IF_DEL		2
 #define WLC_E_IF_CHANGE		3
@@ -212,6 +204,4 @@ typedef struct wl_event_data_if {
 #define WLC_E_LINK_ASSOC_REC	3
 #define WLC_E_LINK_BSSCFG_DIS	4
 
-#include <packed_section_end.h>
-
 #endif				/* _BCMEVENT_H_ */
diff --git a/drivers/staging/brcm80211/include/proto/ethernet.h b/drivers/staging/brcm80211/include/proto/ethernet.h
deleted file mode 100644
index 567407d..0000000
--- a/drivers/staging/brcm80211/include/proto/ethernet.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _NET_ETHERNET_H_
-#define _NET_ETHERNET_H_
-
-#include <linux/if_ether.h>
-
-#include <packed_section_start.h>
-
-#define	ETHER_TYPE_LEN		2
-#define	ETHER_CRC_LEN		4
-#define	ETHER_MIN_LEN		64
-#define	ETHER_MIN_DATA		46
-#define	ETHER_MAX_LEN		1518
-#define	ETHER_MAX_DATA		1500
-
-#define	ETHER_TYPE_BRCM		0x886c
-
-#define ETHER_DEST_OFFSET	(0 * ETH_ALEN)
-#define ETHER_SRC_OFFSET	(1 * ETH_ALEN)
-#define ETHER_TYPE_OFFSET	(2 * ETH_ALEN)
-
-#define	ETHER_IS_VALID_LEN(foo)	\
-	((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
-
-#define ETHER_FILL_MCAST_ADDR_FROM_IP(ea, mgrp_ip) {		\
-		((u8 *)ea)[0] = 0x01;			\
-		((u8 *)ea)[1] = 0x00;			\
-		((u8 *)ea)[2] = 0x5e;			\
-		((u8 *)ea)[3] = ((mgrp_ip) >> 16) & 0x7f;	\
-		((u8 *)ea)[4] = ((mgrp_ip) >>  8) & 0xff;	\
-		((u8 *)ea)[5] = ((mgrp_ip) >>  0) & 0xff;	\
-}
-
-BWL_PRE_PACKED_STRUCT struct ether_header {
-	u8 ether_dhost[ETH_ALEN];
-	u8 ether_shost[ETH_ALEN];
-	u16 ether_type;
-} BWL_POST_PACKED_STRUCT;
-
-BWL_PRE_PACKED_STRUCT struct ether_addr {
-	u8 octet[ETH_ALEN];
-} BWL_POST_PACKED_STRUCT;
-
-#define ETHER_SET_UNICAST(ea)	(((u8 *)(ea))[0] = (((u8 *)(ea))[0] & ~1))
-
-static const struct ether_addr ether_bcast = { {255, 255, 255, 255, 255, 255} };
-
-#define ETHER_MOVE_HDR(d, s) \
-do { \
-	struct ether_header t; \
-	t = *(struct ether_header *)(s); \
-	*(struct ether_header *)(d) = t; \
-} while (0)
-
-#include <packed_section_end.h>
-
-#endif				/* _NET_ETHERNET_H_ */
diff --git a/drivers/staging/brcm80211/include/proto/wpa.h b/drivers/staging/brcm80211/include/proto/wpa.h
deleted file mode 100644
index 10c2fb6..0000000
--- a/drivers/staging/brcm80211/include/proto/wpa.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _proto_wpa_h_
-#define _proto_wpa_h_
-
-#include <proto/ethernet.h>
-
-#define WPA2_PMKID_LEN	16
-#define RSN_CAP_1_REPLAY_CNTR		0
-#define RSN_CAP_2_REPLAY_CNTRS		1
-#define RSN_CAP_4_REPLAY_CNTRS		2
-#define RSN_CAP_16_REPLAY_CNTRS		3
-
-#define WPA_CAP_4_REPLAY_CNTRS		RSN_CAP_4_REPLAY_CNTRS
-#define WPA_CAP_16_REPLAY_CNTRS		RSN_CAP_16_REPLAY_CNTRS
-#define WPA_CAP_REPLAY_CNTR_SHIFT	RSN_CAP_PTK_REPLAY_CNTR_SHIFT
-#define WPA_CAP_REPLAY_CNTR_MASK	RSN_CAP_PTK_REPLAY_CNTR_MASK
-
-#endif				/* _proto_wpa_h_ */
diff --git a/drivers/staging/brcm80211/include/rpc_osl.h b/drivers/staging/brcm80211/include/rpc_osl.h
deleted file mode 100644
index c59d9ed..0000000
--- a/drivers/staging/brcm80211/include/rpc_osl.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _rpcosl_h_
-#define _rpcosl_h_
-
-typedef struct rpc_osl rpc_osl_t;
-extern rpc_osl_t *rpc_osl_attach(struct osl_info *osh);
-extern void rpc_osl_detach(rpc_osl_t *rpc_osh);
-
-#define RPC_OSL_LOCK(rpc_osh) rpc_osl_lock((rpc_osh))
-#define RPC_OSL_UNLOCK(rpc_osh) rpc_osl_unlock((rpc_osh))
-#define RPC_OSL_WAIT(rpc_osh, to, ptimedout)	rpc_osl_wait((rpc_osh), (to), (ptimedout))
-#define RPC_OSL_WAKE(rpc_osh)			rpc_osl_wake((rpc_osh))
-extern void rpc_osl_lock(rpc_osl_t *rpc_osh);
-extern void rpc_osl_unlock(rpc_osl_t *rpc_osh);
-extern int rpc_osl_wait(rpc_osl_t *rpc_osh, uint ms, bool *ptimedout);
-extern void rpc_osl_wake(rpc_osl_t *rpc_osh);
-
-#endif				/* _rpcosl_h_ */
diff --git a/drivers/staging/brcm80211/include/sbhnddma.h b/drivers/staging/brcm80211/include/sbhnddma.h
index 09e6d33..08cb7f6 100644
--- a/drivers/staging/brcm80211/include/sbhnddma.h
+++ b/drivers/staging/brcm80211/include/sbhnddma.h
@@ -190,7 +190,7 @@ typedef volatile struct {
 } dma64dd_t;
 
 /*
- * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical addresss.
+ * Each descriptor ring must be 8kB aligned, and fit within a contiguous 8kB physical address.
  */
 #define D64RINGALIGN_BITS	13
 #define	D64MAXRINGSZ		(1 << D64RINGALIGN_BITS)
@@ -303,7 +303,7 @@ typedef volatile struct {
 
 #define D64_RX_FRM_STS_LEN	0x0000ffff	/* frame length mask */
 #define D64_RX_FRM_STS_OVFL	0x00800000	/* RxOverFlow */
-#define D64_RX_FRM_STS_DSCRCNT	0x0f000000	/* no. of descriptors used - 1, d11corerev >= 22 */
+#define D64_RX_FRM_STS_DSCRCNT	0x0f000000  /* no. of descriptors used - 1 */
 #define D64_RX_FRM_STS_DATATYPE	0xf0000000	/* core-dependent data type */
 
 /* receive frame status */
diff --git a/drivers/staging/brcm80211/include/sbhndpio.h b/drivers/staging/brcm80211/include/sbhndpio.h
deleted file mode 100644
index 9eabdb5..0000000
--- a/drivers/staging/brcm80211/include/sbhndpio.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_sbhndpio_h_
-#define	_sbhndpio_h_
-
-/* PIO structure,
- *  support two PIO format: 2 bytes access and 4 bytes access
- *  basic FIFO register set is per channel(transmit or receive)
- *  a pair of channels is defined for convenience
- */
-
-/* 2byte-wide pio register set per channel(xmt or rcv) */
-typedef volatile struct {
-	u16 fifocontrol;
-	u16 fifodata;
-	u16 fifofree;	/* only valid in xmt channel, not in rcv channel */
-	u16 PAD;
-} pio2regs_t;
-
-/* a pair of pio channels(tx and rx) */
-typedef volatile struct {
-	pio2regs_t tx;
-	pio2regs_t rx;
-} pio2regp_t;
-
-/* 4byte-wide pio register set per channel(xmt or rcv) */
-typedef volatile struct {
-	u32 fifocontrol;
-	u32 fifodata;
-} pio4regs_t;
-
-/* a pair of pio channels(tx and rx) */
-typedef volatile struct {
-	pio4regs_t tx;
-	pio4regs_t rx;
-} pio4regp_t;
-
-#endif				/* _sbhndpio_h_ */
diff --git a/drivers/staging/brcm80211/include/sbpcmcia.h b/drivers/staging/brcm80211/include/sbpcmcia.h
deleted file mode 100644
index 6b9923f5..0000000
--- a/drivers/staging/brcm80211/include/sbpcmcia.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SBPCMCIA_H
-#define	_SBPCMCIA_H
-
-/* All the addresses that are offsets in attribute space are divided
- * by two to account for the fact that odd bytes are invalid in
- * attribute space and our read/write routines make the space appear
- * as if they didn't exist. Still we want to show the original numbers
- * as documented in the hnd_pcmcia core manual.
- */
-
-/* PCMCIA Function Configuration Registers */
-#define	PCMCIA_FCR		(0x700 / 2)
-
-#define	FCR0_OFF		0
-#define	FCR1_OFF		(0x40 / 2)
-#define	FCR2_OFF		(0x80 / 2)
-#define	FCR3_OFF		(0xc0 / 2)
-
-#define	PCMCIA_FCR0		(0x700 / 2)
-#define	PCMCIA_FCR1		(0x740 / 2)
-#define	PCMCIA_FCR2		(0x780 / 2)
-#define	PCMCIA_FCR3		(0x7c0 / 2)
-
-/* Standard PCMCIA FCR registers */
-
-#define	PCMCIA_COR		0
-
-#define	COR_RST			0x80
-#define	COR_LEV			0x40
-#define	COR_IRQEN		0x04
-#define	COR_BLREN		0x01
-#define	COR_FUNEN		0x01
-
-#define	PCICIA_FCSR		(2 / 2)
-#define	PCICIA_PRR		(4 / 2)
-#define	PCICIA_SCR		(6 / 2)
-#define	PCICIA_ESR		(8 / 2)
-
-#define PCM_MEMOFF		0x0000
-#define F0_MEMOFF		0x1000
-#define F1_MEMOFF		0x2000
-#define F2_MEMOFF		0x3000
-#define F3_MEMOFF		0x4000
-
-/* Memory base in the function fcr's */
-#define MEM_ADDR0		(0x728 / 2)
-#define MEM_ADDR1		(0x72a / 2)
-#define MEM_ADDR2		(0x72c / 2)
-
-/* PCMCIA base plus Srom access in fcr0: */
-#define PCMCIA_ADDR0		(0x072e / 2)
-#define PCMCIA_ADDR1		(0x0730 / 2)
-#define PCMCIA_ADDR2		(0x0732 / 2)
-
-#define MEM_SEG			(0x0734 / 2)
-#define SROM_CS			(0x0736 / 2)
-#define SROM_DATAL		(0x0738 / 2)
-#define SROM_DATAH		(0x073a / 2)
-#define SROM_ADDRL		(0x073c / 2)
-#define SROM_ADDRH		(0x073e / 2)
-#define	SROM_INFO2		(0x0772 / 2)	/* Corerev >= 2 && <= 5 */
-#define	SROM_INFO		(0x07be / 2)	/* Corerev >= 6 */
-
-/*  Values for srom_cs: */
-#define SROM_IDLE		0
-#define SROM_WRITE		1
-#define SROM_READ		2
-#define SROM_WEN		4
-#define SROM_WDS		7
-#define SROM_DONE		8
-
-/* Fields in srom_info: */
-#define	SRI_SZ_MASK		0x03
-#define	SRI_BLANK		0x04
-#define	SRI_OTP			0x80
-
-#if !defined(ESTA_POSTMOGRIFY_REMOVAL)
-/* CIS stuff */
-
-/* The CIS stops where the FCRs start */
-#define	CIS_SIZE		PCMCIA_FCR
-
-/* CIS tuple length field max */
-#define CIS_TUPLE_LEN_MAX	0xff
-
-/* Standard tuples we know about */
-
-#define CISTPL_NULL			0x00
-#define	CISTPL_VERS_1		0x15	/* CIS ver, manf, dev & ver strings */
-#define	CISTPL_MANFID		0x20	/* Manufacturer and device id */
-#define CISTPL_FUNCID		0x21	/* Function identification */
-#define	CISTPL_FUNCE		0x22	/* Function extensions */
-#define	CISTPL_CFTABLE		0x1b	/* Config table entry */
-#define	CISTPL_END		0xff	/* End of the CIS tuple chain */
-
-/* Function identifier provides context for the function extentions tuple */
-#define CISTPL_FID_SDIO		0x0c	/* Extensions defined by SDIO spec */
-
-/* Function extensions for LANs (assumed for extensions other than SDIO) */
-#define	LAN_TECH		1	/* Technology type */
-#define	LAN_SPEED		2	/* Raw bit rate */
-#define	LAN_MEDIA		3	/* Transmission media */
-#define	LAN_NID			4	/* Node identification (aka MAC addr) */
-#define	LAN_CONN		5	/* Connector standard */
-
-/* CFTable */
-#define CFTABLE_REGWIN_2K	0x08	/* 2k reg windows size */
-#define CFTABLE_REGWIN_4K	0x10	/* 4k reg windows size */
-#define CFTABLE_REGWIN_8K	0x20	/* 8k reg windows size */
-
-/* Vendor unique tuples are 0x80-0x8f. Within Broadcom we'll
- * take one for HNBU, and use "extensions" (a la FUNCE) within it.
- */
-
-#define	CISTPL_BRCM_HNBU	0x80
-
-/* Subtypes of BRCM_HNBU: */
-
-#define HNBU_SROMREV		0x00	/* A byte with sromrev, 1 if not present */
-#define HNBU_CHIPID		0x01	/* Two 16bit values: PCI vendor & device id */
-#define HNBU_BOARDREV		0x02	/* One byte board revision */
-#define HNBU_PAPARMS		0x03	/* PA parameters: 8 (sromrev == 1)
-					 * or 9 (sromrev > 1) bytes
-					 */
-#define HNBU_OEM		0x04	/* Eight bytes OEM data (sromrev == 1) */
-#define HNBU_CC			0x05	/* Default country code (sromrev == 1) */
-#define	HNBU_AA			0x06	/* Antennas available */
-#define	HNBU_AG			0x07	/* Antenna gain */
-#define HNBU_BOARDFLAGS		0x08	/* board flags (2 or 4 bytes) */
-#define HNBU_LEDS		0x09	/* LED set */
-#define HNBU_CCODE		0x0a	/* Country code (2 bytes ascii + 1 byte cctl)
-					 * in rev 2
-					 */
-#define HNBU_CCKPO		0x0b	/* 2 byte cck power offsets in rev 3 */
-#define HNBU_OFDMPO		0x0c	/* 4 byte 11g ofdm power offsets in rev 3 */
-#define HNBU_GPIOTIMER		0x0d	/* 2 bytes with on/off values in rev 3 */
-#define HNBU_PAPARMS5G		0x0e	/* 5G PA params */
-#define HNBU_ANT5G		0x0f	/* 4328 5G antennas available/gain */
-#define HNBU_RDLID		0x10	/* 2 byte USB remote downloader (RDL) product Id */
-#define HNBU_RSSISMBXA2G	0x11	/* 4328 2G RSSI mid pt sel & board switch arch,
-					 * 2 bytes, rev 3.
-					 */
-#define HNBU_RSSISMBXA5G	0x12	/* 4328 5G RSSI mid pt sel & board switch arch,
-					 * 2 bytes, rev 3.
-					 */
-#define HNBU_XTALFREQ		0x13	/* 4 byte Crystal frequency in kilohertz */
-#define HNBU_TRI2G		0x14	/* 4328 2G TR isolation, 1 byte */
-#define HNBU_TRI5G		0x15	/* 4328 5G TR isolation, 3 bytes */
-#define HNBU_RXPO2G		0x16	/* 4328 2G RX power offset, 1 byte */
-#define HNBU_RXPO5G		0x17	/* 4328 5G RX power offset, 1 byte */
-#define HNBU_BOARDNUM		0x18	/* board serial number, independent of mac addr */
-#define HNBU_MACADDR		0x19	/* mac addr override for the standard CIS LAN_NID */
-#define HNBU_RDLSN		0x1a	/* 2 bytes; serial # advertised in USB descriptor */
-#define HNBU_BOARDTYPE		0x1b	/* 2 bytes; boardtype */
-#define HNBU_LEDDC		0x1c	/* 2 bytes; LED duty cycle */
-#define HNBU_HNBUCIS		0x1d	/* what follows is proprietary HNBU CIS format */
-#define HNBU_PAPARMS_SSLPNPHY	0x1e	/* SSLPNPHY PA params */
-#define HNBU_RSSISMBXA2G_SSLPNPHY 0x1f	/* SSLPNPHY RSSI mid pt sel & board switch arch */
-#define HNBU_RDLRNDIS		0x20	/* 1 byte; 1 = RDL advertises RNDIS config */
-#define HNBU_CHAINSWITCH	0x21	/* 2 byte; txchain, rxchain */
-#define HNBU_REGREV		0x22	/* 1 byte; */
-#define HNBU_FEM		0x23	/* 2 or 4 byte: 11n frontend specification */
-#define HNBU_PAPARMS_C0		0x24	/* 8 or 30 bytes: 11n pa paramater for chain 0 */
-#define HNBU_PAPARMS_C1		0x25	/* 8 or 30 bytes: 11n pa paramater for chain 1 */
-#define HNBU_PAPARMS_C2		0x26	/* 8 or 30 bytes: 11n pa paramater for chain 2 */
-#define HNBU_PAPARMS_C3		0x27	/* 8 or 30 bytes: 11n pa paramater for chain 3 */
-#define HNBU_PO_CCKOFDM		0x28	/* 6 or 18 bytes: cck2g/ofdm2g/ofdm5g power offset */
-#define HNBU_PO_MCS2G		0x29	/* 8 bytes: mcs2g power offset */
-#define HNBU_PO_MCS5GM		0x2a	/* 8 bytes: mcs5g mid band power offset */
-#define HNBU_PO_MCS5GLH		0x2b	/* 16 bytes: mcs5g low-high band power offset */
-#define HNBU_PO_CDD		0x2c	/* 2 bytes: cdd2g/5g power offset */
-#define HNBU_PO_STBC		0x2d	/* 2 bytes: stbc2g/5g power offset */
-#define HNBU_PO_40M		0x2e	/* 2 bytes: 40Mhz channel 2g/5g power offset */
-#define HNBU_PO_40MDUP		0x2f	/* 2 bytes: 40Mhz channel dup 2g/5g power offset */
-
-#define HNBU_RDLRWU		0x30	/* 1 byte; 1 = RDL advertises Remote Wake-up */
-#define HNBU_WPS		0x31	/* 1 byte; GPIO pin for WPS button */
-#define HNBU_USBFS		0x32	/* 1 byte; 1 = USB advertises FS mode only */
-#define HNBU_BRMIN		0x33	/* 4 byte bootloader min resource mask */
-#define HNBU_BRMAX		0x34	/* 4 byte bootloader max resource mask */
-#define HNBU_PATCH		0x35	/* bootloader patch addr(2b) & data(4b) pair */
-#define HNBU_CCKFILTTYPE	0x36	/* CCK digital filter selection options */
-#define HNBU_OFDMPO5G		0x37	/* 4 * 3 = 12 byte 11a ofdm power offsets in rev 3 */
-
-#define HNBU_USBEPNUM		0x40	/* USB endpoint numbers */
-#define HNBU_SROM3SWRGN		0x80	/* 78 bytes; srom rev 3 s/w region without crc8
-					 * plus extra info appended.
-					 */
-#define HNBU_RESERVED		0x81	/* Reserved for non-BRCM post-mfg additions */
-#define HNBU_CUSTOM1		0x82	/* 4 byte; For non-BRCM post-mfg additions */
-#define HNBU_CUSTOM2		0x83	/* Reserved; For non-BRCM post-mfg additions */
-#endif				/* !defined(ESTA_POSTMOGRIFY_REMOVAL) */
-
-/* sbtmstatelow */
-#define SBTML_INT_ACK		0x40000	/* ack the sb interrupt */
-#define SBTML_INT_EN		0x20000	/* enable sb interrupt */
-
-/* sbtmstatehigh */
-#define SBTMH_INT_STATUS	0x40000	/* sb interrupt status */
-
-#endif				/* _SBPCMCIA_H */
diff --git a/drivers/staging/brcm80211/include/sbsdio.h b/drivers/staging/brcm80211/include/sbsdio.h
index 6afdbbe..c7facd3 100644
--- a/drivers/staging/brcm80211/include/sbsdio.h
+++ b/drivers/staging/brcm80211/include/sbsdio.h
@@ -144,7 +144,7 @@
 						 */
 
 #define SBSDIO_BYTEMODE_DATALEN_MAX	64	/* sdio byte mode: maximum length of one
-						 * data comamnd
+						 * data command
 						 */
 
 #define SBSDIO_CORE_ADDR_MASK		0x1FFFF	/* sdio core function one address mask */
diff --git a/drivers/staging/brcm80211/include/sbsocram.h b/drivers/staging/brcm80211/include/sbsocram.h
deleted file mode 100644
index 0cfe985..0000000
--- a/drivers/staging/brcm80211/include/sbsocram.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SBSOCRAM_H
-#define	_SBSOCRAM_H
-
-#ifndef _LANGUAGE_ASSEMBLY
-
-/* cpp contortions to concatenate w/arg prescan */
-#ifndef PAD
-#define	_PADLINE(line)	pad ## line
-#define	_XSTR(line)	_PADLINE(line)
-#define	PAD		_XSTR(__LINE__)
-#endif				/* PAD */
-
-/* Memcsocram core registers */
-typedef volatile struct sbsocramregs {
-	u32 coreinfo;
-	u32 bwalloc;
-	u32 extracoreinfo;
-	u32 biststat;
-	u32 bankidx;
-	u32 standbyctrl;
-
-	u32 errlogstatus;	/* rev 6 */
-	u32 errlogaddr;	/* rev 6 */
-	/* used for patching rev 3 & 5 */
-	u32 cambankidx;
-	u32 cambankstandbyctrl;
-	u32 cambankpatchctrl;
-	u32 cambankpatchtblbaseaddr;
-	u32 cambankcmdreg;
-	u32 cambankdatareg;
-	u32 cambankmaskreg;
-	u32 PAD[1];
-	u32 bankinfo;	/* corev 8 */
-	u32 PAD[15];
-	u32 extmemconfig;
-	u32 extmemparitycsr;
-	u32 extmemparityerrdata;
-	u32 extmemparityerrcnt;
-	u32 extmemwrctrlandsize;
-	u32 PAD[84];
-	u32 workaround;
-	u32 pwrctl;		/* corerev >= 2 */
-} sbsocramregs_t;
-
-#endif				/* _LANGUAGE_ASSEMBLY */
-
-/* Register offsets */
-#define	SR_COREINFO		0x00
-#define	SR_BWALLOC		0x04
-#define	SR_BISTSTAT		0x0c
-#define	SR_BANKINDEX		0x10
-#define	SR_BANKSTBYCTL		0x14
-#define SR_PWRCTL		0x1e8
-
-/* Coreinfo register */
-#define	SRCI_PT_MASK		0x00070000	/* corerev >= 6; port type[18:16] */
-#define	SRCI_PT_SHIFT		16
-/* port types : SRCI_PT_<processorPT>_<backplanePT> */
-#define SRCI_PT_OCP_OCP		0
-#define SRCI_PT_AXI_OCP		1
-#define SRCI_PT_ARM7AHB_OCP	2
-#define SRCI_PT_CM3AHB_OCP	3
-#define SRCI_PT_AXI_AXI		4
-#define SRCI_PT_AHB_AXI		5
-/* corerev >= 3 */
-#define SRCI_LSS_MASK		0x00f00000
-#define SRCI_LSS_SHIFT		20
-#define SRCI_LRS_MASK		0x0f000000
-#define SRCI_LRS_SHIFT		24
-
-/* In corerev 0, the memory size is 2 to the power of the
- * base plus 16 plus to the contents of the memsize field plus 1.
- */
-#define	SRCI_MS0_MASK		0xf
-#define SR_MS0_BASE		16
-
-/*
- * In corerev 1 the bank size is 2 ^ the bank size field plus 14,
- * the memory size is number of banks times bank size.
- * The same applies to rom size.
- */
-#define	SRCI_ROMNB_MASK		0xf000
-#define	SRCI_ROMNB_SHIFT	12
-#define	SRCI_ROMBSZ_MASK	0xf00
-#define	SRCI_ROMBSZ_SHIFT	8
-#define	SRCI_SRNB_MASK		0xf0
-#define	SRCI_SRNB_SHIFT		4
-#define	SRCI_SRBSZ_MASK		0xf
-#define	SRCI_SRBSZ_SHIFT	0
-
-#define SR_BSZ_BASE		14
-
-/* Standby control register */
-#define	SRSC_SBYOVR_MASK	0x80000000
-#define	SRSC_SBYOVR_SHIFT	31
-#define	SRSC_SBYOVRVAL_MASK	0x60000000
-#define	SRSC_SBYOVRVAL_SHIFT	29
-#define	SRSC_SBYEN_MASK		0x01000000	/* rev >= 3 */
-#define	SRSC_SBYEN_SHIFT	24
-
-/* Power control register */
-#define SRPC_PMU_STBYDIS_MASK	0x00000010	/* rev >= 3 */
-#define SRPC_PMU_STBYDIS_SHIFT	4
-#define SRPC_STBYOVRVAL_MASK	0x00000008
-#define SRPC_STBYOVRVAL_SHIFT	3
-#define SRPC_STBYOVR_MASK	0x00000007
-#define SRPC_STBYOVR_SHIFT	0
-
-/* Extra core capability register */
-#define SRECC_NUM_BANKS_MASK   0x000000F0
-#define SRECC_NUM_BANKS_SHIFT  4
-#define SRECC_BANKSIZE_MASK    0x0000000F
-#define SRECC_BANKSIZE_SHIFT   0
-
-#define SRECC_BANKSIZE(value)	 (1 << (value))
-
-/* CAM bank patch control */
-#define SRCBPC_PATCHENABLE 0x80000000
-
-#define SRP_ADDRESS   0x0001FFFC
-#define SRP_VALID     0x8000
-
-/* CAM bank command reg */
-#define SRCMD_WRITE  0x00020000
-#define SRCMD_READ   0x00010000
-#define SRCMD_DONE   0x80000000
-
-#define SRCMD_DONE_DLY	1000
-
-/* bankidx and bankinfo reg defines corerev >= 8 */
-#define SOCRAM_BANKINFO_SZMASK		0x3f
-#define SOCRAM_BANKIDX_ROM_MASK		0x100
-
-#define SOCRAM_BANKIDX_MEMTYPE_SHIFT	8
-/* socram bankinfo memtype */
-#define SOCRAM_MEMTYPE_RAM		0
-#define SOCRAM_MEMTYPE_R0M		1
-#define SOCRAM_MEMTYPE_DEVRAM		2
-
-#define	SOCRAM_BANKINFO_REG		0x40
-#define	SOCRAM_BANKIDX_REG		0x10
-#define	SOCRAM_BANKINFO_STDBY_MASK	0x400
-#define	SOCRAM_BANKINFO_STDBY_TIMER	0x800
-
-/* bankinfo rev >= 10 */
-#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT	13
-#define SOCRAM_BANKINFO_DEVRAMSEL_MASK	0x2000
-#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT	14
-#define SOCRAM_BANKINFO_DEVRAMPRO_MASK	0x4000
-
-/* extracoreinfo register */
-#define SOCRAM_DEVRAMBANK_MASK		0xF000
-#define SOCRAM_DEVRAMBANK_SHIFT		12
-
-/* bank info to calculate bank size */
-#define	SOCRAM_BANKINFO_SZBASE		8192
-#define SOCRAM_BANKSIZE_SHIFT		13	/* SOCRAM_BANKINFO_SZBASE */
-
-#endif				/* _SBSOCRAM_H */
diff --git a/drivers/staging/brcm80211/include/sdioh.h b/drivers/staging/brcm80211/include/sdioh.h
deleted file mode 100644
index f96aaf9..0000000
--- a/drivers/staging/brcm80211/include/sdioh.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SDIOH_H
-#define	_SDIOH_H
-
-#define SD_SysAddr			0x000
-#define SD_BlockSize			0x004
-#define SD_BlockCount 			0x006
-#define SD_Arg0				0x008
-#define SD_Arg1 			0x00A
-#define SD_TransferMode			0x00C
-#define SD_Command 			0x00E
-#define SD_Response0			0x010
-#define SD_Response1 			0x012
-#define SD_Response2			0x014
-#define SD_Response3 			0x016
-#define SD_Response4			0x018
-#define SD_Response5 			0x01A
-#define SD_Response6			0x01C
-#define SD_Response7 			0x01E
-#define SD_BufferDataPort0		0x020
-#define SD_BufferDataPort1 		0x022
-#define SD_PresentState			0x024
-#define SD_HostCntrl			0x028
-#define SD_PwrCntrl			0x029
-#define SD_BlockGapCntrl 		0x02A
-#define SD_WakeupCntrl 			0x02B
-#define SD_ClockCntrl			0x02C
-#define SD_TimeoutCntrl 		0x02E
-#define SD_SoftwareReset		0x02F
-#define SD_IntrStatus			0x030
-#define SD_ErrorIntrStatus 		0x032
-#define SD_IntrStatusEnable		0x034
-#define SD_ErrorIntrStatusEnable 	0x036
-#define SD_IntrSignalEnable		0x038
-#define SD_ErrorIntrSignalEnable 	0x03A
-#define SD_CMD12ErrorStatus		0x03C
-#define SD_Capabilities			0x040
-#define SD_Capabilities_Reserved	0x044
-#define SD_MaxCurCap			0x048
-#define SD_MaxCurCap_Reserved		0x04C
-#define SD_ADMA_SysAddr			0x58
-#define SD_SlotInterruptStatus		0x0FC
-#define SD_HostControllerVersion 	0x0FE
-
-/* SD specific registers in PCI config space */
-#define SD_SlotInfo	0x40
-
-#endif				/* _SDIOH_H */
diff --git a/drivers/staging/brcm80211/include/sdiovar.h b/drivers/staging/brcm80211/include/sdiovar.h
deleted file mode 100644
index 7686fde..0000000
--- a/drivers/staging/brcm80211/include/sdiovar.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _sdiovar_h_
-#define _sdiovar_h_
-
-/* require default structure packing */
-#define BWL_DEFAULT_PACKING
-#include <packed_section_start.h>
-
-typedef struct sdreg {
-	int func;
-	int offset;
-	int value;
-} sdreg_t;
-
-/* Common msglevel constants */
-#define SDH_ERROR_VAL		0x0001	/* Error */
-#define SDH_TRACE_VAL		0x0002	/* Trace */
-#define SDH_INFO_VAL		0x0004	/* Info */
-#define SDH_DEBUG_VAL		0x0008	/* Debug */
-#define SDH_DATA_VAL		0x0010	/* Data */
-#define SDH_CTRL_VAL		0x0020	/* Control Regs */
-#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
-#define SDH_DMA_VAL		0x0080	/* DMA */
-
-#define NUM_PREV_TRANSACTIONS	16
-
-#include <packed_section_end.h>
-
-#endif				/* _sdiovar_h_ */
diff --git a/drivers/staging/brcm80211/include/siutils.h b/drivers/staging/brcm80211/include/siutils.h
index a935092..101e9a4 100644
--- a/drivers/staging/brcm80211/include/siutils.h
+++ b/drivers/staging/brcm80211/include/siutils.h
@@ -118,8 +118,8 @@ typedef void (*gpio_handler_t) (u32 stat, void *arg);
 #define GPIO_CTRL_EPA_EN_MASK 0x40
 
 /* === exported functions === */
-extern si_t *si_attach(uint pcidev, struct osl_info *osh, void *regs,
-		       uint bustype, void *sdh, char **vars, uint *varsz);
+extern si_t *si_attach(uint pcidev, void *regs, uint bustype,
+		       void *sdh, char **vars, uint *varsz);
 
 extern void si_detach(si_t *sih);
 extern bool si_pci_war16165(si_t *sih);
@@ -128,7 +128,6 @@ extern uint si_coreid(si_t *sih);
 extern uint si_flag(si_t *sih);
 extern uint si_coreidx(si_t *sih);
 extern uint si_corerev(si_t *sih);
-struct osl_info *si_osh(si_t *sih);
 extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask,
 		uint val);
 extern void si_write_wrapperreg(si_t *sih, u32 offset, u32 val);
@@ -173,10 +172,6 @@ extern void si_sdio_init(si_t *sih);
 #define si_eci_init(sih) (0)
 #define si_eci_notify_bt(sih, type, val)  (0)
 #define si_seci(sih) 0
-static inline void *si_seci_init(si_t *sih, u8 use_seci)
-{
-	return NULL;
-}
 
 /* OTP status */
 extern bool si_is_otp_disabled(si_t *sih);
@@ -192,7 +187,7 @@ extern void si_sprom_init(si_t *sih);
 #define	SI_ERROR(args)
 
 #ifdef BCMDBG
-#define	SI_MSG(args)	printf args
+#define	SI_MSG(args)	printk args
 #else
 #define	SI_MSG(args)
 #endif				/* BCMDBG */
@@ -216,9 +211,8 @@ typedef struct gpioh_item {
 
 /* misc si info needed by some of the routines */
 typedef struct si_info {
-	struct si_pub pub;	/* back plane public state (must be first field) */
-	struct osl_info *osh;		/* osl os handle */
-	void *sdh;		/* bcmsdh handle */
+	struct si_pub pub;	/* back plane public state (must be first) */
+	void *pbus;		/* handle to bus (pci/sdio/..) */
 	uint dev_coreid;	/* the core provides driver functions */
 	void *intr_arg;		/* interrupt callback function arg */
 	si_intrsoff_t intrsoff_fn;	/* turns chip interrupts off */
@@ -255,7 +249,7 @@ typedef struct si_info {
 	u32 oob_router;	/* oob router registers for axi */
 } si_info_t;
 
-#define	SI_INFO(sih)	(si_info_t *)sih
+#define	SI_INFO(sih)	((si_info_t *)(sih))
 
 #define	GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \
 		IS_ALIGNED((x), SI_CORE_SIZE))
@@ -275,7 +269,7 @@ typedef struct si_info {
 
 /*
  * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts
- * before after core switching to avoid invalid register accesss inside ISR.
+ * before after core switching to avoid invalid register access inside ISR.
  */
 #define INTR_OFF(si, intr_val) \
 	if ((si)->intrsoff_fn && (si)->coreid[(si)->curidx] == (si)->dev_coreid) {	\
@@ -334,9 +328,9 @@ extern void si_epa_4313war(si_t *sih);
 char *si_getnvramflvar(si_t *sih, const char *name);
 
 /* AMBA Interconnect exported externs */
-extern si_t *ai_attach(uint pcidev, struct osl_info *osh, void *regs,
-		       uint bustype, void *sdh, char **vars, uint *varsz);
-extern si_t *ai_kattach(struct osl_info *osh);
+extern si_t *ai_attach(uint pcidev, void *regs, uint bustype,
+		       void *sdh, char **vars, uint *varsz);
+extern si_t *ai_kattach(void);
 extern void ai_scan(si_t *sih, void *regs, uint devid);
 
 extern uint ai_flag(si_t *sih);
diff --git a/drivers/staging/brcm80211/include/spid.h b/drivers/staging/brcm80211/include/spid.h
deleted file mode 100644
index e0abb84..0000000
--- a/drivers/staging/brcm80211/include/spid.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_SPI_H
-#define	_SPI_H
-
-/*
- * Brcm SPI Device Register Map.
- *
- */
-
-typedef volatile struct {
-	u8 config;		/* 0x00, len, endian, clock, speed, polarity, wakeup */
-	u8 response_delay;	/* 0x01, read response delay in bytes (corerev < 3) */
-	u8 status_enable;	/* 0x02, status-enable, intr with status, response_delay
-				 * function selection, command/data error check
-				 */
-	u8 reset_bp;		/* 0x03, reset on wlan/bt backplane reset (corerev >= 1) */
-	u16 intr_reg;	/* 0x04, Intr status register */
-	u16 intr_en_reg;	/* 0x06, Intr mask register */
-	u32 status_reg;	/* 0x08, RO, Status bits of last spi transfer */
-	u16 f1_info_reg;	/* 0x0c, RO, enabled, ready for data transfer, blocksize */
-	u16 f2_info_reg;	/* 0x0e, RO, enabled, ready for data transfer, blocksize */
-	u16 f3_info_reg;	/* 0x10, RO, enabled, ready for data transfer, blocksize */
-	u32 test_read;	/* 0x14, RO 0xfeedbead signature */
-	u32 test_rw;		/* 0x18, RW */
-	u8 resp_delay_f0;	/* 0x1c, read resp delay bytes for F0 (corerev >= 3) */
-	u8 resp_delay_f1;	/* 0x1d, read resp delay bytes for F1 (corerev >= 3) */
-	u8 resp_delay_f2;	/* 0x1e, read resp delay bytes for F2 (corerev >= 3) */
-	u8 resp_delay_f3;	/* 0x1f, read resp delay bytes for F3 (corerev >= 3) */
-} spi_regs_t;
-
-/* SPI device register offsets */
-#define SPID_CONFIG			0x00
-#define SPID_RESPONSE_DELAY		0x01
-#define SPID_STATUS_ENABLE		0x02
-#define SPID_RESET_BP			0x03	/* (corerev >= 1) */
-#define SPID_INTR_REG			0x04	/* 16 bits - Interrupt status */
-#define SPID_INTR_EN_REG		0x06	/* 16 bits - Interrupt mask */
-#define SPID_STATUS_REG			0x08	/* 32 bits */
-#define SPID_F1_INFO_REG		0x0C	/* 16 bits */
-#define SPID_F2_INFO_REG		0x0E	/* 16 bits */
-#define SPID_F3_INFO_REG		0x10	/* 16 bits */
-#define SPID_TEST_READ			0x14	/* 32 bits */
-#define SPID_TEST_RW			0x18	/* 32 bits */
-#define SPID_RESP_DELAY_F0		0x1c	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F1		0x1d	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F2		0x1e	/* 8 bits (corerev >= 3) */
-#define SPID_RESP_DELAY_F3		0x1f	/* 8 bits (corerev >= 3) */
-
-/* Bit masks for SPID_CONFIG device register */
-#define WORD_LENGTH_32	0x1	/* 0/1 16/32 bit word length */
-#define ENDIAN_BIG	0x2	/* 0/1 Little/Big Endian */
-#define CLOCK_PHASE	0x4	/* 0/1 clock phase delay */
-#define CLOCK_POLARITY	0x8	/* 0/1 Idle state clock polarity is low/high */
-#define HIGH_SPEED_MODE	0x10	/* 1/0 High Speed mode / Normal mode */
-#define INTR_POLARITY	0x20	/* 1/0 Interrupt active polarity is high/low */
-#define WAKE_UP		0x80	/* 0/1 Wake-up command from Host to WLAN */
-
-/* Bit mask for SPID_RESPONSE_DELAY device register */
-#define RESPONSE_DELAY_MASK	0xFF	/* Configurable rd response delay in multiples of 8 bits */
-
-/* Bit mask for SPID_STATUS_ENABLE device register */
-#define STATUS_ENABLE		0x1	/* 1/0 Status sent/not sent to host after read/write */
-#define INTR_WITH_STATUS	0x2	/* 0/1 Do-not / do-interrupt if status is sent */
-#define RESP_DELAY_ALL		0x4	/* Applicability of resp delay to F1 or all func's read */
-#define DWORD_PKT_LEN_EN	0x8	/* Packet len denoted in dwords instead of bytes */
-#define CMD_ERR_CHK_EN		0x20	/* Command error check enable */
-#define DATA_ERR_CHK_EN		0x40	/* Data error check enable */
-
-/* Bit mask for SPID_RESET_BP device register */
-#define RESET_ON_WLAN_BP_RESET	0x4	/* enable reset for WLAN backplane */
-#define RESET_ON_BT_BP_RESET	0x8	/* enable reset for BT backplane */
-#define RESET_SPI		0x80	/* reset the above enabled logic */
-
-/* Bit mask for SPID_INTR_REG device register */
-#define DATA_UNAVAILABLE	0x0001	/* Requested data not available; Clear by writing a "1" */
-#define F2_F3_FIFO_RD_UNDERFLOW	0x0002
-#define F2_F3_FIFO_WR_OVERFLOW	0x0004
-#define COMMAND_ERROR		0x0008	/* Cleared by writing 1 */
-#define DATA_ERROR		0x0010	/* Cleared by writing 1 */
-#define F2_PACKET_AVAILABLE	0x0020
-#define F3_PACKET_AVAILABLE	0x0040
-#define F1_OVERFLOW		0x0080	/* Due to last write. Bkplane has pending write requests */
-#define MISC_INTR0		0x0100
-#define MISC_INTR1		0x0200
-#define MISC_INTR2		0x0400
-#define MISC_INTR3		0x0800
-#define MISC_INTR4		0x1000
-#define F1_INTR			0x2000
-#define F2_INTR			0x4000
-#define F3_INTR			0x8000
-
-/* Bit mask for 32bit SPID_STATUS_REG device register */
-#define STATUS_DATA_NOT_AVAILABLE	0x00000001
-#define STATUS_UNDERFLOW		0x00000002
-#define STATUS_OVERFLOW			0x00000004
-#define STATUS_F2_INTR			0x00000008
-#define STATUS_F3_INTR			0x00000010
-#define STATUS_F2_RX_READY		0x00000020
-#define STATUS_F3_RX_READY		0x00000040
-#define STATUS_HOST_CMD_DATA_ERR	0x00000080
-#define STATUS_F2_PKT_AVAILABLE		0x00000100
-#define STATUS_F2_PKT_LEN_MASK		0x000FFE00
-#define STATUS_F2_PKT_LEN_SHIFT		9
-#define STATUS_F3_PKT_AVAILABLE		0x00100000
-#define STATUS_F3_PKT_LEN_MASK		0xFFE00000
-#define STATUS_F3_PKT_LEN_SHIFT		21
-
-/* Bit mask for 16 bits SPID_F1_INFO_REG device register */
-#define F1_ENABLED 			0x0001
-#define F1_RDY_FOR_DATA_TRANSFER	0x0002
-#define F1_MAX_PKT_SIZE			0x01FC
-
-/* Bit mask for 16 bits SPID_F2_INFO_REG device register */
-#define F2_ENABLED 			0x0001
-#define F2_RDY_FOR_DATA_TRANSFER	0x0002
-#define F2_MAX_PKT_SIZE			0x3FFC
-
-/* Bit mask for 16 bits SPID_F3_INFO_REG device register */
-#define F3_ENABLED 			0x0001
-#define F3_RDY_FOR_DATA_TRANSFER	0x0002
-#define F3_MAX_PKT_SIZE			0x3FFC
-
-/* Bit mask for 32 bits SPID_TEST_READ device register read in 16bit LE mode */
-#define TEST_RO_DATA_32BIT_LE		0xFEEDBEAD
-
-/* Maximum number of I/O funcs */
-#define SPI_MAX_IOFUNCS		4
-
-#define SPI_MAX_PKT_LEN		(2048*4)
-
-/* Misc defines */
-#define SPI_FUNC_0		0
-#define SPI_FUNC_1		1
-#define SPI_FUNC_2		2
-#define SPI_FUNC_3		3
-
-#define WAIT_F2RXFIFORDY	100
-#define WAIT_F2RXFIFORDY_DELAY	20
-
-#endif				/* _SPI_H */
diff --git a/drivers/staging/brcm80211/include/wlioctl.h b/drivers/staging/brcm80211/include/wlioctl.h
index 9be793c..5e2b11b 100644
--- a/drivers/staging/brcm80211/include/wlioctl.h
+++ b/drivers/staging/brcm80211/include/wlioctl.h
@@ -17,7 +17,7 @@
 #ifndef _wlioctl_h_
 #define	_wlioctl_h_
 
-#include <proto/ethernet.h>
+#include <linux/ieee80211.h>
 #ifdef BRCM_FULLMAC
 #include <proto/bcmeth.h>
 #endif
@@ -29,10 +29,6 @@
 #define INTF_NAME_SIZ	16
 #endif
 
-/* require default structure packing */
-#define BWL_DEFAULT_PACKING
-#include <packed_section_start.h>
-
 #ifdef BRCM_FULLMAC
 
 #define	WL_BSS_INFO_VERSION	108	/* current ver of wl_bss_info struct */
@@ -46,7 +42,7 @@ typedef struct wl_bss_info {
 	u32 length;		/* byte length of data in this record,
 				 * starting at version and including IEs
 				 */
-	struct ether_addr BSSID;
+	u8 BSSID[ETH_ALEN];
 	u16 beacon_period;	/* units are Kusec */
 	u16 capability;	/* Capability information */
 	u8 SSID_len;
@@ -128,7 +124,7 @@ typedef struct wl_extdscan_params {
 
 typedef struct wl_scan_params {
 	wlc_ssid_t ssid;	/* default: {0, ""} */
-	struct ether_addr bssid;	/* default: bcast */
+	u8 bssid[ETH_ALEN];	/* default: bcast */
 	s8 bss_type;		/* default: any,
 				 * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT
 				 */
@@ -234,8 +230,8 @@ typedef struct wl_iscan_results {
 
 typedef struct wl_probe_params {
 	wlc_ssid_t ssid;
-	struct ether_addr bssid;
-	struct ether_addr mac;
+	u8 bssid[ETH_ALEN];
+	u8 mac[ETH_ALEN];
 } wl_probe_params_t;
 #endif /* BRCM_FULLMAC */
 
@@ -262,7 +258,7 @@ typedef struct wl_u32_list {
 
 /* used for association with a specific BSSID and chanspec list */
 typedef struct wl_assoc_params {
-	struct ether_addr bssid;	/* 00:00:00:00:00:00: broadcast scan */
+	u8 bssid[ETH_ALEN];	/* 00:00:00:00:00:00: broadcast scan */
 	s32 chanspec_num;	/* 0: all available channels,
 				 * otherwise count of chanspecs in chanspec_list
 				 */
@@ -478,7 +474,7 @@ typedef struct wl_rm_rep {
 typedef struct wl_wsec_key {
 	u32 index;		/* key index */
 	u32 len;		/* key length */
-	u8 data[DOT11_MAX_KEY_SIZE];	/* key data */
+	u8 data[WLAN_MAX_KEY_LEN];	/* key data */
 	u32 pad_1[18];
 	u32 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
 	u32 flags;		/* misc flags */
@@ -492,7 +488,7 @@ typedef struct wl_wsec_key {
 		u16 lo;	/* lower 16 bits of IV */
 	} rxiv;
 	u32 pad_5[2];
-	struct ether_addr ea;	/* per station */
+	u8 ea[ETH_ALEN];	/* per station */
 } wl_wsec_key_t;
 
 #define WSEC_MIN_PSK_LEN	8
@@ -534,8 +530,8 @@ typedef struct {
 #define	MAXPMKID		16
 
 typedef struct _pmkid {
-	struct ether_addr BSSID;
-	u8 PMKID[WPA2_PMKID_LEN];
+	u8 BSSID[ETH_ALEN];
+	u8 PMKID[WLAN_PMKID_LEN];
 } pmkid_t;
 
 typedef struct _pmkid_list {
@@ -544,7 +540,7 @@ typedef struct _pmkid_list {
 } pmkid_list_t;
 
 typedef struct _pmkid_cand {
-	struct ether_addr BSSID;
+	u8 BSSID[ETH_ALEN];
 	u8 preauth;
 } pmkid_cand_t;
 
@@ -572,7 +568,7 @@ typedef struct {
 /* Used to get specific STA parameters */
 typedef struct {
 	u32 val;
-	struct ether_addr ea;
+	u8 ea[ETH_ALEN];
 } scb_val_t;
 #endif /* BRCM_FULLMAC */
 
@@ -586,7 +582,7 @@ typedef struct channel_info {
 /* For ioctls that take a list of MAC addresses */
 struct maclist {
 	uint count;		/* number of MAC addresses */
-	struct ether_addr ea[1];	/* variable length array of MAC addresses */
+	u8 ea[1][ETH_ALEN];	/* variable length array of MAC addresses */
 };
 
 /* get pkt count struct passed through ioctl */
@@ -1266,7 +1262,7 @@ struct tsinfo_arg {
 
 #define	WL_CNT_T_VERSION	7	/* current version of wl_cnt_t struct */
 
-typedef struct {
+struct wl_cnt {
 	u16 version;		/* see definition of WL_CNT_T_VERSION */
 	u16 length;		/* length of entire structure */
 
@@ -1496,7 +1492,7 @@ typedef struct {
 	u32 rxmpdu_sgi;	/* count for sgi received */
 	u32 txmpdu_stbc;	/* count for stbc transmit */
 	u32 rxmpdu_stbc;	/* count for stbc received */
-} wl_cnt_t;
+};
 
 #define	WL_DELTA_STATS_T_VERSION	1	/* current version of wl_delta_stats_t struct */
 
@@ -1614,7 +1610,7 @@ struct ampdu_tid_control {
 
 /* structure for identifying ea/tid for sending addba/delba */
 struct ampdu_ea_tid {
-	struct ether_addr ea;	/* Station address */
+	u8 ea[ETH_ALEN];	/* Station address */
 	u8 tid;		/* tid */
 };
 /* structure for identifying retry/tid for retry_limit_tid/rr_retry_limit_tid */
@@ -1668,9 +1664,6 @@ typedef struct wl_pkt_filter_enable {
 
 #define	WLC_RSSI_INVALID	 0	/* invalid RSSI value */
 
-/* require default structure packing */
-#include <packed_section_end.h>
-
 /* n-mode support capability */
 /* 2x2 includes both 1x1 & 2x2 devices
  * reserved #define 2 for future when we want to separate 1x1 & 2x2 and
diff --git a/drivers/staging/brcm80211/phy/phy_version.h b/drivers/staging/brcm80211/phy/phy_version.h
deleted file mode 100644
index 51a2238..0000000
--- a/drivers/staging/brcm80211/phy/phy_version.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef phy_version_h_
-#define phy_version_h_
-
-#define	PHY_MAJOR_VERSION		1
-
-#define	PHY_MINOR_VERSION		82
-
-#define	PHY_RC_NUMBER		8
-
-#define	PHY_INCREMENTAL_NUMBER	0
-
-#define	PHY_BUILD_NUMBER		0
-
-#define	PHY_VERSION			{ 1, 82, 8, 0 }
-
-#define	PHY_VERSION_NUM		0x01520800
-
-#define	PHY_VERSION_STR		"1.82.8.0"
-
-#endif				/* phy_version_h_ */
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_cmn.c b/drivers/staging/brcm80211/phy/wlc_phy_cmn.c
deleted file mode 100644
index 3bed37c..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_cmn.c
+++ /dev/null
@@ -1,3461 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <wlc_cfg.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <bcmendian.h>
-#include <bcmnvram.h>
-#include <sbchipc.h>
-#include <bcmdevs.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-
-#include <wlc_phy_int.h>
-#include <wlc_phyreg_n.h>
-#include <wlc_phy_radio.h>
-#include <wlc_phy_lcn.h>
-
-u32 phyhal_msg_level = PHYHAL_ERROR;
-
-typedef struct _chan_info_basic {
-	u16 chan;
-	u16 freq;
-} chan_info_basic_t;
-
-static chan_info_basic_t chan_info_all[] = {
-
-	{1, 2412},
-	{2, 2417},
-	{3, 2422},
-	{4, 2427},
-	{5, 2432},
-	{6, 2437},
-	{7, 2442},
-	{8, 2447},
-	{9, 2452},
-	{10, 2457},
-	{11, 2462},
-	{12, 2467},
-	{13, 2472},
-	{14, 2484},
-
-	{34, 5170},
-	{38, 5190},
-	{42, 5210},
-	{46, 5230},
-
-	{36, 5180},
-	{40, 5200},
-	{44, 5220},
-	{48, 5240},
-	{52, 5260},
-	{56, 5280},
-	{60, 5300},
-	{64, 5320},
-
-	{100, 5500},
-	{104, 5520},
-	{108, 5540},
-	{112, 5560},
-	{116, 5580},
-	{120, 5600},
-	{124, 5620},
-	{128, 5640},
-	{132, 5660},
-	{136, 5680},
-	{140, 5700},
-
-	{149, 5745},
-	{153, 5765},
-	{157, 5785},
-	{161, 5805},
-	{165, 5825},
-
-	{184, 4920},
-	{188, 4940},
-	{192, 4960},
-	{196, 4980},
-	{200, 5000},
-	{204, 5020},
-	{208, 5040},
-	{212, 5060},
-	{216, 50800}
-};
-
-u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
-	0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
-	0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
-	0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
-	0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
-	0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
-	0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
-	0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
-	0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
-	0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
-	0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
-	0x0507, 0x0fea, 0xe4f2, 0xf6e6
-};
-
-const u8 ofdm_rate_lookup[] = {
-
-	WLC_RATE_48M,
-	WLC_RATE_24M,
-	WLC_RATE_12M,
-	WLC_RATE_6M,
-	WLC_RATE_54M,
-	WLC_RATE_36M,
-	WLC_RATE_18M,
-	WLC_RATE_9M
-};
-
-#define PHY_WREG_LIMIT	24
-
-static void wlc_set_phy_uninitted(phy_info_t *pi);
-static u32 wlc_phy_get_radio_ver(phy_info_t *pi);
-static void wlc_phy_timercb_phycal(void *arg);
-
-static bool wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr,
-				   s8 *pwr_ant);
-
-static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay);
-static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm);
-static void wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason,
-					 u8 ch);
-
-static void wlc_phy_txpower_reg_limit_calc(phy_info_t *pi,
-					   struct txpwr_limits *tp, chanspec_t);
-static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi);
-
-static s8 wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan,
-					     u32 band, u8 rate);
-static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band);
-static s8 wlc_phy_env_measure_vbat(phy_info_t *pi);
-static s8 wlc_phy_env_measure_temperature(phy_info_t *pi);
-
-char *phy_getvar(phy_info_t *pi, const char *name)
-{
-	char *vars = pi->vars;
-	char *s;
-	int len;
-
-	ASSERT(pi->vars != (char *)&pi->vars);
-
-	if (!name)
-		return NULL;
-
-	len = strlen(name);
-	if (len == 0)
-		return NULL;
-
-	for (s = vars; s && *s;) {
-		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
-			return &s[len + 1];
-
-		while (*s++)
-			;
-	}
-
-	return nvram_get(name);
-}
-
-int phy_getintvar(phy_info_t *pi, const char *name)
-{
-	char *val;
-
-	val = PHY_GETVAR(pi, name);
-	if (val == NULL)
-		return 0;
-
-	return simple_strtoul(val, NULL, 0);
-}
-
-void wlc_phyreg_enter(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
-}
-
-void wlc_phyreg_exit(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
-}
-
-void wlc_radioreg_enter(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
-
-	udelay(10);
-}
-
-void wlc_radioreg_exit(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	volatile u16 dummy;
-
-	dummy = R_REG(pi->sh->osh, &pi->regs->phyversion);
-	pi->phy_wreg = 0;
-	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
-}
-
-u16 read_radio_reg(phy_info_t *pi, u16 addr)
-{
-	u16 data;
-
-	if ((addr == RADIO_IDCODE))
-		return 0xffff;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return NORADIO_IDCODE & 0xffff;
-
-	switch (pi->pubpi.phy_type) {
-	case PHY_TYPE_N:
-		CASECHECK(PHYTYPE, PHY_TYPE_N);
-		if (NREV_GE(pi->pubpi.phy_rev, 7))
-			addr |= RADIO_2057_READ_OFF;
-		else
-			addr |= RADIO_2055_READ_OFF;
-		break;
-
-	case PHY_TYPE_LCN:
-		CASECHECK(PHYTYPE, PHY_TYPE_LCN);
-		addr |= RADIO_2064_READ_OFF;
-		break;
-
-	default:
-		ASSERT(VALID_PHYTYPE(pi->pubpi.phy_type));
-	}
-
-	if ((D11REV_GE(pi->sh->corerev, 24)) ||
-	    (D11REV_IS(pi->sh->corerev, 22)
-	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
-		W_REG(pi->sh->osh, &pi->regs->radioregaddr, addr);
-#ifdef __mips__
-		(void)R_REG(pi->sh->osh, &pi->regs->radioregaddr);
-#endif
-		data = R_REG(pi->sh->osh, &pi->regs->radioregdata);
-	} else {
-		W_REG(pi->sh->osh, &pi->regs->phy4waddr, addr);
-#ifdef __mips__
-		(void)R_REG(pi->sh->osh, &pi->regs->phy4waddr);
-#endif
-
-#ifdef __ARM_ARCH_4T__
-		__asm__(" .align 4 ");
-		__asm__(" nop ");
-		data = R_REG(pi->sh->osh, &pi->regs->phy4wdatalo);
-#else
-		data = R_REG(pi->sh->osh, &pi->regs->phy4wdatalo);
-#endif
-
-	}
-	pi->phy_wreg = 0;
-
-	return data;
-}
-
-void write_radio_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	struct osl_info *osh;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	osh = pi->sh->osh;
-
-	if ((D11REV_GE(pi->sh->corerev, 24)) ||
-	    (D11REV_IS(pi->sh->corerev, 22)
-	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
-
-		W_REG(osh, &pi->regs->radioregaddr, addr);
-#ifdef __mips__
-		(void)R_REG(osh, &pi->regs->radioregaddr);
-#endif
-		W_REG(osh, &pi->regs->radioregdata, val);
-	} else {
-		W_REG(osh, &pi->regs->phy4waddr, addr);
-#ifdef __mips__
-		(void)R_REG(osh, &pi->regs->phy4waddr);
-#endif
-		W_REG(osh, &pi->regs->phy4wdatalo, val);
-	}
-
-	if (pi->sh->bustype == PCI_BUS) {
-		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
-			(void)R_REG(osh, &pi->regs->maccontrol);
-			pi->phy_wreg = 0;
-		}
-	}
-}
-
-static u32 read_radio_id(phy_info_t *pi)
-{
-	u32 id;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return NORADIO_IDCODE;
-
-	if (D11REV_GE(pi->sh->corerev, 24)) {
-		u32 b0, b1, b2;
-
-		W_REG(pi->sh->osh, &pi->regs->radioregaddr, 0);
-#ifdef __mips__
-		(void)R_REG(pi->sh->osh, &pi->regs->radioregaddr);
-#endif
-		b0 = (u32) R_REG(pi->sh->osh, &pi->regs->radioregdata);
-		W_REG(pi->sh->osh, &pi->regs->radioregaddr, 1);
-#ifdef __mips__
-		(void)R_REG(pi->sh->osh, &pi->regs->radioregaddr);
-#endif
-		b1 = (u32) R_REG(pi->sh->osh, &pi->regs->radioregdata);
-		W_REG(pi->sh->osh, &pi->regs->radioregaddr, 2);
-#ifdef __mips__
-		(void)R_REG(pi->sh->osh, &pi->regs->radioregaddr);
-#endif
-		b2 = (u32) R_REG(pi->sh->osh, &pi->regs->radioregdata);
-
-		id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
-								      & 0xf);
-	} else {
-		W_REG(pi->sh->osh, &pi->regs->phy4waddr, RADIO_IDCODE);
-#ifdef __mips__
-		(void)R_REG(pi->sh->osh, &pi->regs->phy4waddr);
-#endif
-		id = (u32) R_REG(pi->sh->osh, &pi->regs->phy4wdatalo);
-		id |= (u32) R_REG(pi->sh->osh, &pi->regs->phy4wdatahi) << 16;
-	}
-	pi->phy_wreg = 0;
-	return id;
-}
-
-void and_radio_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval & val));
-}
-
-void or_radio_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval | val));
-}
-
-void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval ^ mask));
-}
-
-void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
-{
-	u16 rval;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	rval = read_radio_reg(pi, addr);
-	write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
-}
-
-void write_phy_channel_reg(phy_info_t *pi, uint val)
-{
-	W_REG(pi->sh->osh, &pi->regs->phychannel, val);
-}
-
-#if defined(BCMDBG)
-static bool wlc_phy_war41476(phy_info_t *pi)
-{
-	u32 mc = R_REG(pi->sh->osh, &pi->regs->maccontrol);
-
-	return ((mc & MCTL_EN_MAC) == 0)
-	    || ((mc & MCTL_PHYLOCK) == MCTL_PHYLOCK);
-}
-#endif
-
-u16 read_phy_reg(phy_info_t *pi, u16 addr)
-{
-	struct osl_info *osh;
-	d11regs_t *regs;
-
-	osh = pi->sh->osh;
-	regs = pi->regs;
-
-	W_REG(osh, &regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(osh, &regs->phyregaddr);
-#endif
-
-	ASSERT(!
-	       (D11REV_IS(pi->sh->corerev, 11)
-		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
-
-	pi->phy_wreg = 0;
-	return R_REG(osh, &regs->phyregdata);
-}
-
-void write_phy_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	struct osl_info *osh;
-	d11regs_t *regs;
-
-	osh = pi->sh->osh;
-	regs = pi->regs;
-
-#ifdef __mips__
-	W_REG(osh, &regs->phyregaddr, addr);
-	(void)R_REG(osh, &regs->phyregaddr);
-	W_REG(osh, &regs->phyregdata, val);
-	if (addr == 0x72)
-		(void)R_REG(osh, &regs->phyregdata);
-#else
-	W_REG(osh, (volatile u32 *)(&regs->phyregaddr),
-	      addr | (val << 16));
-	if (pi->sh->bustype == PCI_BUS) {
-		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
-			pi->phy_wreg = 0;
-			(void)R_REG(osh, &regs->phyversion);
-		}
-	}
-#endif
-}
-
-void and_phy_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	struct osl_info *osh;
-	d11regs_t *regs;
-
-	osh = pi->sh->osh;
-	regs = pi->regs;
-
-	W_REG(osh, &regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(osh, &regs->phyregaddr);
-#endif
-
-	ASSERT(!
-	       (D11REV_IS(pi->sh->corerev, 11)
-		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
-
-	W_REG(osh, &regs->phyregdata, (R_REG(osh, &regs->phyregdata) & val));
-	pi->phy_wreg = 0;
-}
-
-void or_phy_reg(phy_info_t *pi, u16 addr, u16 val)
-{
-	struct osl_info *osh;
-	d11regs_t *regs;
-
-	osh = pi->sh->osh;
-	regs = pi->regs;
-
-	W_REG(osh, &regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(osh, &regs->phyregaddr);
-#endif
-
-	ASSERT(!
-	       (D11REV_IS(pi->sh->corerev, 11)
-		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
-
-	W_REG(osh, &regs->phyregdata, (R_REG(osh, &regs->phyregdata) | val));
-	pi->phy_wreg = 0;
-}
-
-void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
-{
-	struct osl_info *osh;
-	d11regs_t *regs;
-
-	osh = pi->sh->osh;
-	regs = pi->regs;
-
-	W_REG(osh, &regs->phyregaddr, addr);
-#ifdef __mips__
-	(void)R_REG(osh, &regs->phyregaddr);
-#endif
-
-	ASSERT(!
-	       (D11REV_IS(pi->sh->corerev, 11)
-		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
-
-	W_REG(osh, &regs->phyregdata,
-	      ((R_REG(osh, &regs->phyregdata) & ~mask) | (val & mask)));
-	pi->phy_wreg = 0;
-}
-
-static void WLBANDINITFN(wlc_set_phy_uninitted) (phy_info_t *pi)
-{
-	int i, j;
-
-	pi->initialized = false;
-
-	pi->tx_vos = 0xffff;
-	pi->nrssi_table_delta = 0x7fffffff;
-	pi->rc_cal = 0xffff;
-	pi->mintxbias = 0xffff;
-	pi->txpwridx = -1;
-	if (ISNPHY(pi)) {
-		pi->phy_spuravoid = SPURAVOID_DISABLE;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)
-		    && NREV_LT(pi->pubpi.phy_rev, 7))
-			pi->phy_spuravoid = SPURAVOID_AUTO;
-
-		pi->nphy_papd_skip = 0;
-		pi->nphy_papd_epsilon_offset[0] = 0xf588;
-		pi->nphy_papd_epsilon_offset[1] = 0xf588;
-		pi->nphy_txpwr_idx[0] = 128;
-		pi->nphy_txpwr_idx[1] = 128;
-		pi->nphy_txpwrindex[0].index_internal = 40;
-		pi->nphy_txpwrindex[1].index_internal = 40;
-		pi->phy_pabias = 0;
-	} else {
-		pi->phy_spuravoid = SPURAVOID_AUTO;
-	}
-	pi->radiopwr = 0xffff;
-	for (i = 0; i < STATIC_NUM_RF; i++) {
-		for (j = 0; j < STATIC_NUM_BB; j++) {
-			pi->stats_11b_txpower[i][j] = -1;
-		}
-	}
-}
-
-shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp)
-{
-	shared_phy_t *sh;
-
-	sh = kzalloc(sizeof(shared_phy_t), GFP_ATOMIC);
-	if (sh == NULL) {
-		return NULL;
-	}
-
-	sh->osh = shp->osh;
-	sh->sih = shp->sih;
-	sh->physhim = shp->physhim;
-	sh->unit = shp->unit;
-	sh->corerev = shp->corerev;
-
-	sh->vid = shp->vid;
-	sh->did = shp->did;
-	sh->chip = shp->chip;
-	sh->chiprev = shp->chiprev;
-	sh->chippkg = shp->chippkg;
-	sh->sromrev = shp->sromrev;
-	sh->boardtype = shp->boardtype;
-	sh->boardrev = shp->boardrev;
-	sh->boardvendor = shp->boardvendor;
-	sh->boardflags = shp->boardflags;
-	sh->boardflags2 = shp->boardflags2;
-	sh->bustype = shp->bustype;
-	sh->buscorerev = shp->buscorerev;
-
-	sh->fast_timer = PHY_SW_TIMER_FAST;
-	sh->slow_timer = PHY_SW_TIMER_SLOW;
-	sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
-
-	sh->rssi_mode = RSSI_ANT_MERGE_MAX;
-
-	return sh;
-}
-
-void wlc_phy_shared_detach(shared_phy_t *phy_sh)
-{
-	struct osl_info *osh;
-
-	if (phy_sh) {
-		osh = phy_sh->osh;
-
-		if (phy_sh->phy_head) {
-			ASSERT(!phy_sh->phy_head);
-		}
-		kfree(phy_sh);
-	}
-}
-
-wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype, char *vars)
-{
-	phy_info_t *pi;
-	u32 sflags = 0;
-	uint phyversion;
-	int i;
-	struct osl_info *osh;
-
-	osh = sh->osh;
-
-	if (D11REV_IS(sh->corerev, 4))
-		sflags = SISF_2G_PHY | SISF_5G_PHY;
-	else
-		sflags = si_core_sflags(sh->sih, 0, 0);
-
-	if (BAND_5G(bandtype)) {
-		if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
-			return NULL;
-		}
-	}
-
-	pi = sh->phy_head;
-	if ((sflags & SISF_DB_PHY) && pi) {
-
-		wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
-		pi->refcnt++;
-		return &pi->pubpi_ro;
-	}
-
-	pi = kzalloc(sizeof(phy_info_t), GFP_ATOMIC);
-	if (pi == NULL) {
-		return NULL;
-	}
-	pi->regs = (d11regs_t *) regs;
-	pi->sh = sh;
-	pi->phy_init_por = true;
-	pi->phy_wreg_limit = PHY_WREG_LIMIT;
-
-	pi->vars = vars;
-
-	pi->txpwr_percent = 100;
-
-	pi->do_initcal = true;
-
-	pi->phycal_tempdelta = 0;
-
-	if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
-
-		pi->pubpi.coreflags = SICF_GMODE;
-	}
-
-	wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
-	phyversion = R_REG(osh, &pi->regs->phyversion);
-
-	pi->pubpi.phy_type = PHY_TYPE(phyversion);
-	pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
-
-	if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
-		pi->pubpi.phy_type = PHY_TYPE_N;
-		pi->pubpi.phy_rev += LCNXN_BASEREV;
-	}
-	pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
-	pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
-
-	if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
-		goto err;
-	}
-	if (BAND_5G(bandtype)) {
-		if (!ISNPHY(pi)) {
-			goto err;
-		}
-	} else {
-		if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
-			goto err;
-		}
-	}
-
-	if (ISSIM_ENAB(pi->sh->sih)) {
-		pi->pubpi.radioid = NORADIO_ID;
-		pi->pubpi.radiorev = 5;
-	} else {
-		u32 idcode;
-
-		wlc_phy_anacore((wlc_phy_t *) pi, ON);
-
-		idcode = wlc_phy_get_radio_ver(pi);
-		pi->pubpi.radioid =
-		    (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
-		pi->pubpi.radiorev =
-		    (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
-		pi->pubpi.radiover =
-		    (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
-		if (!VALID_RADIO(pi, pi->pubpi.radioid)) {
-			goto err;
-		}
-
-		wlc_phy_switch_radio((wlc_phy_t *) pi, OFF);
-	}
-
-	wlc_set_phy_uninitted(pi);
-
-	pi->bw = WL_CHANSPEC_BW_20;
-	pi->radio_chanspec =
-	    BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
-
-	pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
-	pi->rxiq_antsel = ANT_RX_DIV_DEF;
-
-	pi->watchdog_override = true;
-
-	pi->cal_type_override = PHY_PERICAL_AUTO;
-
-	pi->nphy_saved_noisevars.bufcount = 0;
-
-	if (ISNPHY(pi))
-		pi->min_txpower = PHY_TXPWR_MIN_NPHY;
-	else
-		pi->min_txpower = PHY_TXPWR_MIN;
-
-	pi->sh->phyrxchain = 0x3;
-
-	pi->rx2tx_biasentry = -1;
-
-	pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
-	pi->phy_txcore_enable_temp =
-	    PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
-	pi->phy_tempsense_offset = 0;
-	pi->phy_txcore_heatedup = false;
-
-	pi->nphy_lastcal_temp = -50;
-
-	pi->phynoise_polling = true;
-	if (ISNPHY(pi) || ISLCNPHY(pi))
-		pi->phynoise_polling = false;
-
-	for (i = 0; i < TXP_NUM_RATES; i++) {
-		pi->txpwr_limit[i] = WLC_TXPWR_MAX;
-		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
-		pi->tx_user_target[i] = WLC_TXPWR_MAX;
-	}
-
-	pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
-
-	pi->user_txpwr_at_rfport = false;
-
-	if (ISNPHY(pi)) {
-
-		pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
-							  wlc_phy_timercb_phycal,
-							  pi, "phycal");
-		if (!pi->phycal_timer) {
-			goto err;
-		}
-
-		if (!wlc_phy_attach_nphy(pi))
-			goto err;
-
-	} else if (ISLCNPHY(pi)) {
-		if (!wlc_phy_attach_lcnphy(pi))
-			goto err;
-
-	} else {
-
-	}
-
-	pi->refcnt++;
-	pi->next = pi->sh->phy_head;
-	sh->phy_head = pi;
-
-	pi->vars = (char *)&pi->vars;
-
-	bcopy(&pi->pubpi, &pi->pubpi_ro, sizeof(wlc_phy_t));
-
-	return &pi->pubpi_ro;
-
- err:
-	if (pi)
-		kfree(pi);
-	return NULL;
-}
-
-void wlc_phy_detach(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (pih) {
-		if (--pi->refcnt) {
-			return;
-		}
-
-		if (pi->phycal_timer) {
-			wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
-			pi->phycal_timer = NULL;
-		}
-
-		if (pi->sh->phy_head == pi)
-			pi->sh->phy_head = pi->next;
-		else if (pi->sh->phy_head->next == pi)
-			pi->sh->phy_head->next = NULL;
-		else
-			ASSERT(0);
-
-		if (pi->pi_fptr.detach)
-			(pi->pi_fptr.detach) (pi);
-
-		kfree(pi);
-	}
-}
-
-bool
-wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype, u16 *phyrev,
-		       u16 *radioid, u16 *radiover)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	*phytype = (u16) pi->pubpi.phy_type;
-	*phyrev = (u16) pi->pubpi.phy_rev;
-	*radioid = pi->pubpi.radioid;
-	*radiover = pi->pubpi.radiorev;
-
-	return true;
-}
-
-bool wlc_phy_get_encore(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	return pi->pubpi.abgphy_encore;
-}
-
-u32 wlc_phy_get_coreflags(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	return pi->pubpi.coreflags;
-}
-
-static void wlc_phy_timercb_phycal(void *arg)
-{
-	phy_info_t *pi = (phy_info_t *) arg;
-	uint delay = 5;
-
-	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
-		if (!pi->sh->up) {
-			wlc_phy_cal_perical_mphase_reset(pi);
-			return;
-		}
-
-		if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
-
-			delay = 1000;
-			wlc_phy_cal_perical_mphase_restart(pi);
-		} else
-			wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
-		wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
-		return;
-	}
-
-}
-
-void wlc_phy_anacore(wlc_phy_t *pih, bool on)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (ISNPHY(pi)) {
-		if (on) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				write_phy_reg(pi, 0xa6, 0x0d);
-				write_phy_reg(pi, 0x8f, 0x0);
-				write_phy_reg(pi, 0xa7, 0x0d);
-				write_phy_reg(pi, 0xa5, 0x0);
-			} else {
-				write_phy_reg(pi, 0xa5, 0x0);
-			}
-		} else {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				write_phy_reg(pi, 0x8f, 0x07ff);
-				write_phy_reg(pi, 0xa6, 0x0fd);
-				write_phy_reg(pi, 0xa5, 0x07ff);
-				write_phy_reg(pi, 0xa7, 0x0fd);
-			} else {
-				write_phy_reg(pi, 0xa5, 0x7fff);
-			}
-		}
-	} else if (ISLCNPHY(pi)) {
-		if (on) {
-			and_phy_reg(pi, 0x43b,
-				    ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-		} else {
-			or_phy_reg(pi, 0x43c,
-				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-			or_phy_reg(pi, 0x43b,
-				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-		}
-	}
-}
-
-u32 wlc_phy_clk_bwbits(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	u32 phy_bw_clkbits = 0;
-
-	if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
-		switch (pi->bw) {
-		case WL_CHANSPEC_BW_10:
-			phy_bw_clkbits = SICF_BW10;
-			break;
-		case WL_CHANSPEC_BW_20:
-			phy_bw_clkbits = SICF_BW20;
-			break;
-		case WL_CHANSPEC_BW_40:
-			phy_bw_clkbits = SICF_BW40;
-			break;
-		default:
-			ASSERT(0);
-			break;
-		}
-	}
-
-	return phy_bw_clkbits;
-}
-
-void WLBANDINITFN(wlc_phy_por_inform) (wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->phy_init_por = true;
-}
-
-void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->edcrs_threshold_lock = lock;
-
-	write_phy_reg(pi, 0x22c, 0x46b);
-	write_phy_reg(pi, 0x22d, 0x46b);
-	write_phy_reg(pi, 0x22e, 0x3c0);
-	write_phy_reg(pi, 0x22f, 0x3c0);
-}
-
-void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->do_initcal = initcal;
-}
-
-void wlc_phy_hw_clk_state_upd(wlc_phy_t *pih, bool newstate)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (!pi || !pi->sh)
-		return;
-
-	pi->sh->clk = newstate;
-}
-
-void wlc_phy_hw_state_upd(wlc_phy_t *pih, bool newstate)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (!pi || !pi->sh)
-		return;
-
-	pi->sh->up = newstate;
-}
-
-void WLBANDINITFN(wlc_phy_init) (wlc_phy_t *pih, chanspec_t chanspec)
-{
-	u32 mc;
-	initfn_t phy_init = NULL;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (pi->init_in_progress)
-		return;
-
-	pi->init_in_progress = true;
-
-	pi->radio_chanspec = chanspec;
-
-	mc = R_REG(pi->sh->osh, &pi->regs->maccontrol);
-	if ((mc & MCTL_EN_MAC) != 0) {
-		ASSERT((const char *)
-		       "wlc_phy_init: Called with the MAC running!" == NULL);
-	}
-
-	ASSERT(pi != NULL);
-
-	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
-		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
-	}
-
-	if (D11REV_GE(pi->sh->corerev, 5))
-		ASSERT(si_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA);
-
-	phy_init = pi->pi_fptr.init;
-
-	if (phy_init == NULL) {
-		ASSERT(phy_init != NULL);
-		return;
-	}
-
-	wlc_phy_anacore(pih, ON);
-
-	if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
-		wlapi_bmac_bw_set(pi->sh->physhim,
-				  CHSPEC_BW(pi->radio_chanspec));
-
-	pi->nphy_gain_boost = true;
-
-	wlc_phy_switch_radio((wlc_phy_t *) pi, ON);
-
-	(*phy_init) (pi);
-
-	pi->phy_init_por = false;
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlc_phy_do_dummy_tx(pi, true, OFF);
-
-	if (!(ISNPHY(pi)))
-		wlc_phy_txpower_update_shm(pi);
-
-	wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi, pi->sh->rx_antdiv);
-
-	pi->init_in_progress = false;
-}
-
-void wlc_phy_cal_init(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	initfn_t cal_init = NULL;
-
-	ASSERT((R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC) == 0);
-
-	if (!pi->initialized) {
-		cal_init = pi->pi_fptr.calinit;
-		if (cal_init)
-			(*cal_init) (pi);
-
-		pi->initialized = true;
-	}
-}
-
-int wlc_phy_down(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	int callbacks = 0;
-
-	ASSERT(pi->phytest_on == false);
-
-	if (pi->phycal_timer
-	    && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
-		callbacks++;
-
-	pi->nphy_iqcal_chanspec_2G = 0;
-	pi->nphy_iqcal_chanspec_5G = 0;
-
-	return callbacks;
-}
-
-static u32 wlc_phy_get_radio_ver(phy_info_t *pi)
-{
-	u32 ver;
-
-	ver = read_radio_id(pi);
-
-	return ver;
-}
-
-void
-wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
-		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
-{
-	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
-
-	pi->tbl_data_hi = tblDataHi;
-	pi->tbl_data_lo = tblDataLo;
-
-	if ((pi->sh->chip == BCM43224_CHIP_ID ||
-	     pi->sh->chip == BCM43421_CHIP_ID) &&
-	    (pi->sh->chiprev == 1)) {
-		pi->tbl_addr = tblAddr;
-		pi->tbl_save_id = tbl_id;
-		pi->tbl_save_offset = tbl_offset;
-	}
-}
-
-void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val)
-{
-	ASSERT((width == 8) || (width == 16) || (width == 32));
-
-	if ((pi->sh->chip == BCM43224_CHIP_ID ||
-	     pi->sh->chip == BCM43421_CHIP_ID) &&
-	    (pi->sh->chiprev == 1) &&
-	    (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
-		read_phy_reg(pi, pi->tbl_data_lo);
-
-		write_phy_reg(pi, pi->tbl_addr,
-			      (pi->tbl_save_id << 10) | pi->tbl_save_offset);
-		pi->tbl_save_offset++;
-	}
-
-	if (width == 32) {
-
-		write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
-		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
-	} else {
-
-		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
-	}
-}
-
-void
-wlc_phy_write_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
-		    u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
-{
-	uint idx;
-	uint tbl_id = ptbl_info->tbl_id;
-	uint tbl_offset = ptbl_info->tbl_offset;
-	uint tbl_width = ptbl_info->tbl_width;
-	const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
-	const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
-	const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
-
-	ASSERT((tbl_width == 8) || (tbl_width == 16) || (tbl_width == 32));
-
-	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
-
-	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
-
-		if ((pi->sh->chip == BCM43224_CHIP_ID ||
-		     pi->sh->chip == BCM43421_CHIP_ID) &&
-		    (pi->sh->chiprev == 1) &&
-		    (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
-			read_phy_reg(pi, tblDataLo);
-
-			write_phy_reg(pi, tblAddr,
-				      (tbl_id << 10) | (tbl_offset + idx));
-		}
-
-		if (tbl_width == 32) {
-
-			write_phy_reg(pi, tblDataHi,
-				      (u16) (ptbl_32b[idx] >> 16));
-			write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
-		} else if (tbl_width == 16) {
-
-			write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
-		} else {
-
-			write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
-		}
-	}
-}
-
-void
-wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
-		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
-{
-	uint idx;
-	uint tbl_id = ptbl_info->tbl_id;
-	uint tbl_offset = ptbl_info->tbl_offset;
-	uint tbl_width = ptbl_info->tbl_width;
-	u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
-	u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
-	u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
-
-	ASSERT((tbl_width == 8) || (tbl_width == 16) || (tbl_width == 32));
-
-	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
-
-	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
-
-		if ((pi->sh->chip == BCM43224_CHIP_ID ||
-		     pi->sh->chip == BCM43421_CHIP_ID) &&
-		    (pi->sh->chiprev == 1)) {
-			(void)read_phy_reg(pi, tblDataLo);
-
-			write_phy_reg(pi, tblAddr,
-				      (tbl_id << 10) | (tbl_offset + idx));
-		}
-
-		if (tbl_width == 32) {
-
-			ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
-			ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
-		} else if (tbl_width == 16) {
-
-			ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
-		} else {
-
-			ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
-		}
-	}
-}
-
-uint
-wlc_phy_init_radio_regs_allbands(phy_info_t *pi, radio_20xx_regs_t *radioregs)
-{
-	uint i = 0;
-
-	do {
-		if (radioregs[i].do_init) {
-			write_radio_reg(pi, radioregs[i].address,
-					(u16) radioregs[i].init);
-		}
-
-		i++;
-	} while (radioregs[i].address != 0xffff);
-
-	return i;
-}
-
-uint
-wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
-			u16 core_offset)
-{
-	uint i = 0;
-	uint count = 0;
-
-	do {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			if (radioregs[i].do_init_a) {
-				write_radio_reg(pi,
-						radioregs[i].
-						address | core_offset,
-						(u16) radioregs[i].init_a);
-				if (ISNPHY(pi) && (++count % 4 == 0))
-					WLC_PHY_WAR_PR51571(pi);
-			}
-		} else {
-			if (radioregs[i].do_init_g) {
-				write_radio_reg(pi,
-						radioregs[i].
-						address | core_offset,
-						(u16) radioregs[i].init_g);
-				if (ISNPHY(pi) && (++count % 4 == 0))
-					WLC_PHY_WAR_PR51571(pi);
-			}
-		}
-
-		i++;
-	} while (radioregs[i].address != 0xffff);
-
-	return i;
-}
-
-void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on)
-{
-#define	DUMMY_PKT_LEN	20
-	d11regs_t *regs = pi->regs;
-	int i, count;
-	u8 ofdmpkt[DUMMY_PKT_LEN] = {
-		0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
-	};
-	u8 cckpkt[DUMMY_PKT_LEN] = {
-		0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
-		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
-	};
-	u32 *dummypkt;
-
-	ASSERT((R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC) == 0);
-
-	dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
-	wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
-				      dummypkt);
-
-	W_REG(pi->sh->osh, &regs->xmtsel, 0);
-
-	if (D11REV_GE(pi->sh->corerev, 11))
-		W_REG(pi->sh->osh, &regs->wepctl, 0x100);
-	else
-		W_REG(pi->sh->osh, &regs->wepctl, 0);
-
-	W_REG(pi->sh->osh, &regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
-	if (ISNPHY(pi) || ISLCNPHY(pi)) {
-		ASSERT(ofdm);
-		W_REG(pi->sh->osh, &regs->txe_phyctl1, 0x1A02);
-	}
-
-	W_REG(pi->sh->osh, &regs->txe_wm_0, 0);
-	W_REG(pi->sh->osh, &regs->txe_wm_1, 0);
-
-	W_REG(pi->sh->osh, &regs->xmttplatetxptr, 0);
-	W_REG(pi->sh->osh, &regs->xmttxcnt, DUMMY_PKT_LEN);
-
-	W_REG(pi->sh->osh, &regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
-
-	W_REG(pi->sh->osh, &regs->txe_ctl, 0);
-
-	if (!pa_on) {
-		if (ISNPHY(pi))
-			wlc_phy_pa_override_nphy(pi, OFF);
-	}
-
-	if (ISNPHY(pi) || ISLCNPHY(pi))
-		W_REG(pi->sh->osh, &regs->txe_aux, 0xD0);
-	else
-		W_REG(pi->sh->osh, &regs->txe_aux, ((1 << 5) | (1 << 4)));
-
-	(void)R_REG(pi->sh->osh, &regs->txe_aux);
-
-	i = 0;
-	count = ofdm ? 30 : 250;
-
-	if (ISSIM_ENAB(pi->sh->sih)) {
-		count *= 100;
-	}
-
-	while ((i++ < count)
-	       && (R_REG(pi->sh->osh, &regs->txe_status) & (1 << 7))) {
-		udelay(10);
-	}
-
-	i = 0;
-
-	while ((i++ < 10)
-	       && ((R_REG(pi->sh->osh, &regs->txe_status) & (1 << 10)) == 0)) {
-		udelay(10);
-	}
-
-	i = 0;
-
-	while ((i++ < 10) && ((R_REG(pi->sh->osh, &regs->ifsstat) & (1 << 8)))) {
-		udelay(10);
-	}
-	if (!pa_on) {
-		if (ISNPHY(pi))
-			wlc_phy_pa_override_nphy(pi, ON);
-	}
-}
-
-void wlc_phy_hold_upd(wlc_phy_t *pih, mbool id, bool set)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	ASSERT(id);
-
-	if (set) {
-		mboolset(pi->measure_hold, id);
-	} else {
-		mboolclr(pi->measure_hold, id);
-	}
-
-	return;
-}
-
-void wlc_phy_mute_upd(wlc_phy_t *pih, bool mute, mbool flags)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (mute) {
-		mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
-	} else {
-		mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
-	}
-
-	if (!mute && (flags & PHY_MUTE_FOR_PREISM))
-		pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
-	return;
-}
-
-void wlc_phy_clear_tssi(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (ISNPHY(pi)) {
-		return;
-	} else {
-		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
-	}
-}
-
-static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi)
-{
-	return false;
-}
-
-void wlc_phy_switch_radio(wlc_phy_t *pih, bool on)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	{
-		uint mc;
-
-		mc = R_REG(pi->sh->osh, &pi->regs->maccontrol);
-	}
-
-	if (ISNPHY(pi)) {
-		wlc_phy_switch_radio_nphy(pi, on);
-
-	} else if (ISLCNPHY(pi)) {
-		if (on) {
-			and_phy_reg(pi, 0x44c,
-				    ~((0x1 << 8) |
-				      (0x1 << 9) |
-				      (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
-			and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
-			and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
-		} else {
-			and_phy_reg(pi, 0x44d,
-				    ~((0x1 << 10) |
-				      (0x1 << 11) |
-				      (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
-			or_phy_reg(pi, 0x44c,
-				   (0x1 << 8) |
-				   (0x1 << 9) |
-				   (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
-
-			and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
-			and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
-			or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
-			and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
-			or_phy_reg(pi, 0x4f9, (0x1 << 3));
-		}
-	}
-}
-
-u16 wlc_phy_bw_state_get(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->bw;
-}
-
-void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->bw = bw;
-}
-
-void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	pi->radio_chanspec = newch;
-
-}
-
-chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->radio_chanspec;
-}
-
-void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 m_cur_channel;
-	chansetfn_t chanspec_set = NULL;
-
-	ASSERT(!wf_chspec_malformed(chanspec));
-
-	m_cur_channel = CHSPEC_CHANNEL(chanspec);
-	if (CHSPEC_IS5G(chanspec))
-		m_cur_channel |= D11_CURCHANNEL_5G;
-	if (CHSPEC_IS40(chanspec))
-		m_cur_channel |= D11_CURCHANNEL_40;
-	wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
-
-	chanspec_set = pi->pi_fptr.chanset;
-	if (chanspec_set)
-		(*chanspec_set) (pi, chanspec);
-
-}
-
-int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
-{
-	int range = -1;
-
-	if (freq < 2500)
-		range = WL_CHAN_FREQ_RANGE_2G;
-	else if (freq <= 5320)
-		range = WL_CHAN_FREQ_RANGE_5GL;
-	else if (freq <= 5700)
-		range = WL_CHAN_FREQ_RANGE_5GM;
-	else
-		range = WL_CHAN_FREQ_RANGE_5GH;
-
-	return range;
-}
-
-int wlc_phy_chanspec_bandrange_get(phy_info_t *pi, chanspec_t chanspec)
-{
-	int range = -1;
-	uint channel = CHSPEC_CHANNEL(chanspec);
-	uint freq = wlc_phy_channel2freq(channel);
-
-	if (ISNPHY(pi)) {
-		range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
-	} else if (ISLCNPHY(pi)) {
-		range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
-	} else
-		ASSERT(0);
-
-	return range;
-}
-
-void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi, bool wide_filter)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->channel_14_wide_filter = wide_filter;
-
-}
-
-int wlc_phy_channel2freq(uint channel)
-{
-	uint i;
-
-	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
-		if (chan_info_all[i].chan == channel)
-			return chan_info_all[i].freq;
-	return 0;
-}
-
-void
-wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band, chanvec_t *channels)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint i;
-	uint channel;
-
-	ASSERT((band == WLC_BAND_2G) || (band == WLC_BAND_5G));
-
-	memset(channels, 0, sizeof(chanvec_t));
-
-	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
-		channel = chan_info_all[i].chan;
-
-		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
-		    && (channel <= LAST_REF5_CHANNUM))
-			continue;
-
-		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
-		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
-			setbit(channels->vec, channel);
-	}
-}
-
-chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint i;
-	uint channel;
-	chanspec_t chspec;
-
-	ASSERT((band == WLC_BAND_2G) || (band == WLC_BAND_5G));
-
-	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
-		channel = chan_info_all[i].chan;
-
-		if (ISNPHY(pi) && IS40MHZ(pi)) {
-			uint j;
-
-			for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
-				if (chan_info_all[j].chan ==
-				    channel + CH_10MHZ_APART)
-					break;
-			}
-
-			if (j == ARRAY_SIZE(chan_info_all))
-				continue;
-
-			channel = UPPER_20_SB(channel);
-			chspec =
-			    channel | WL_CHANSPEC_BW_40 |
-			    WL_CHANSPEC_CTL_SB_LOWER;
-			if (band == WLC_BAND_2G)
-				chspec |= WL_CHANSPEC_BAND_2G;
-			else
-				chspec |= WL_CHANSPEC_BAND_5G;
-		} else
-			chspec = CH20MHZ_CHSPEC(channel);
-
-		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
-		    && (channel <= LAST_REF5_CHANNUM))
-			continue;
-
-		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
-		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
-			return chspec;
-	}
-
-	ASSERT(0);
-
-	return (chanspec_t) INVCHANSPEC;
-}
-
-int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	ASSERT(qdbm != NULL);
-	*qdbm = pi->tx_user_target[0];
-	if (override != NULL)
-		*override = pi->txpwroverride;
-	return 0;
-}
-
-void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr)
-{
-	bool mac_enabled = false;
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	bcopy(&txpwr->cck[0], &pi->tx_user_target[TXP_FIRST_CCK],
-	      WLC_NUM_RATES_CCK);
-
-	bcopy(&txpwr->ofdm[0], &pi->tx_user_target[TXP_FIRST_OFDM],
-	      WLC_NUM_RATES_OFDM);
-	bcopy(&txpwr->ofdm_cdd[0], &pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
-	      WLC_NUM_RATES_OFDM);
-
-	bcopy(&txpwr->ofdm_40_siso[0],
-	      &pi->tx_user_target[TXP_FIRST_OFDM_40_SISO], WLC_NUM_RATES_OFDM);
-	bcopy(&txpwr->ofdm_40_cdd[0],
-	      &pi->tx_user_target[TXP_FIRST_OFDM_40_CDD], WLC_NUM_RATES_OFDM);
-
-	bcopy(&txpwr->mcs_20_siso[0],
-	      &pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
-	      WLC_NUM_RATES_MCS_1_STREAM);
-	bcopy(&txpwr->mcs_20_cdd[0], &pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
-	      WLC_NUM_RATES_MCS_1_STREAM);
-	bcopy(&txpwr->mcs_20_stbc[0],
-	      &pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
-	      WLC_NUM_RATES_MCS_1_STREAM);
-	bcopy(&txpwr->mcs_20_mimo[0], &pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
-	      WLC_NUM_RATES_MCS_2_STREAM);
-
-	bcopy(&txpwr->mcs_40_siso[0],
-	      &pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
-	      WLC_NUM_RATES_MCS_1_STREAM);
-	bcopy(&txpwr->mcs_40_cdd[0], &pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
-	      WLC_NUM_RATES_MCS_1_STREAM);
-	bcopy(&txpwr->mcs_40_stbc[0],
-	      &pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
-	      WLC_NUM_RATES_MCS_1_STREAM);
-	bcopy(&txpwr->mcs_40_mimo[0], &pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
-	      WLC_NUM_RATES_MCS_2_STREAM);
-
-	if (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC)
-		mac_enabled = true;
-
-	if (mac_enabled)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	wlc_phy_txpower_recalc_target(pi);
-	wlc_phy_cal_txpower_recalc_sw(pi);
-
-	if (mac_enabled)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	int i;
-
-	if (qdbm > 127)
-		return 5;
-
-	for (i = 0; i < TXP_NUM_RATES; i++)
-		pi->tx_user_target[i] = (u8) qdbm;
-
-	pi->txpwroverride = false;
-
-	if (pi->sh->up) {
-		if (!SCAN_INPROG_PHY(pi)) {
-			bool suspend;
-
-			suspend =
-			    (0 ==
-			     (R_REG(pi->sh->osh, &pi->regs->maccontrol) &
-			      MCTL_EN_MAC));
-
-			if (!suspend)
-				wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-			wlc_phy_txpower_recalc_target(pi);
-			wlc_phy_cal_txpower_recalc_sw(pi);
-
-			if (!suspend)
-				wlapi_enable_mac(pi->sh->physhim);
-		}
-	}
-	return 0;
-}
-
-void
-wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint channel, u8 *min_pwr,
-			  u8 *max_pwr, int txp_rate_idx)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint i;
-
-	*min_pwr = pi->min_txpower * WLC_TXPWR_DB_FACTOR;
-
-	if (ISNPHY(pi)) {
-		if (txp_rate_idx < 0)
-			txp_rate_idx = TXP_FIRST_CCK;
-		wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
-						   (u8) txp_rate_idx);
-
-	} else if ((channel <= CH_MAX_2G_CHANNEL)) {
-		if (txp_rate_idx < 0)
-			txp_rate_idx = TXP_FIRST_CCK;
-		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
-	} else {
-
-		*max_pwr = WLC_TXPWR_MAX;
-
-		if (txp_rate_idx < 0)
-			txp_rate_idx = TXP_FIRST_OFDM;
-
-		for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
-			if (channel == chan_info_all[i].chan) {
-				break;
-			}
-		}
-		ASSERT(i < ARRAY_SIZE(chan_info_all));
-
-		if (pi->hwtxpwr) {
-			*max_pwr = pi->hwtxpwr[i];
-		} else {
-
-			if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
-				*max_pwr =
-				    pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
-			if ((i >= FIRST_HIGH_5G_CHAN)
-			    && (i <= LAST_HIGH_5G_CHAN))
-				*max_pwr =
-				    pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
-			if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
-				*max_pwr =
-				    pi->tx_srom_max_rate_5g_low[txp_rate_idx];
-		}
-	}
-}
-
-void
-wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan, u8 *max_txpwr,
-				  u8 *min_txpwr)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u8 tx_pwr_max = 0;
-	u8 tx_pwr_min = 255;
-	u8 max_num_rate;
-	u8 maxtxpwr, mintxpwr, rate, pactrl;
-
-	pactrl = 0;
-
-	max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
-	    ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
-
-	for (rate = 0; rate < max_num_rate; rate++) {
-
-		wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
-					  rate);
-
-		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
-
-		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
-
-		tx_pwr_max = max(tx_pwr_max, maxtxpwr);
-		tx_pwr_min = min(tx_pwr_min, maxtxpwr);
-	}
-	*max_txpwr = tx_pwr_max;
-	*min_txpwr = tx_pwr_min;
-}
-
-void
-wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint bandunit, s32 *max_pwr,
-				s32 *min_pwr, u32 *step_pwr)
-{
-	return;
-}
-
-u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->tx_power_min;
-}
-
-u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->tx_power_max;
-}
-
-void wlc_phy_txpower_recalc_target(phy_info_t *pi)
-{
-	u8 maxtxpwr, mintxpwr, rate, pactrl;
-	uint target_chan;
-	u8 tx_pwr_target[TXP_NUM_RATES];
-	u8 tx_pwr_max = 0;
-	u8 tx_pwr_min = 255;
-	u8 tx_pwr_max_rate_ind = 0;
-	u8 max_num_rate;
-	u8 start_rate = 0;
-	chanspec_t chspec;
-	u32 band = CHSPEC2WLC_BAND(pi->radio_chanspec);
-	initfn_t txpwr_recalc_fn = NULL;
-
-	chspec = pi->radio_chanspec;
-	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
-		target_chan = CHSPEC_CHANNEL(chspec);
-	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
-		target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
-	else
-		target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
-
-	pactrl = 0;
-	if (ISLCNPHY(pi)) {
-		u32 offset_mcs, i;
-
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			offset_mcs = pi->mcs40_po;
-			for (i = TXP_FIRST_SISO_MCS_20;
-			     i <= TXP_LAST_SISO_MCS_20; i++) {
-				pi->tx_srom_max_rate_2g[i - 8] =
-				    pi->tx_srom_max_2g -
-				    ((offset_mcs & 0xf) * 2);
-				offset_mcs >>= 4;
-			}
-		} else {
-			offset_mcs = pi->mcs20_po;
-			for (i = TXP_FIRST_SISO_MCS_20;
-			     i <= TXP_LAST_SISO_MCS_20; i++) {
-				pi->tx_srom_max_rate_2g[i - 8] =
-				    pi->tx_srom_max_2g -
-				    ((offset_mcs & 0xf) * 2);
-				offset_mcs >>= 4;
-			}
-		}
-	}
-#if WL11N
-	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
-			((ISLCNPHY(pi)) ?
-			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
-#else
-	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
-#endif
-
-	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
-
-	for (rate = start_rate; rate < max_num_rate; rate++) {
-
-		tx_pwr_target[rate] = pi->tx_user_target[rate];
-
-		if (pi->user_txpwr_at_rfport) {
-			tx_pwr_target[rate] +=
-			    wlc_user_txpwr_antport_to_rfport(pi, target_chan,
-							     band, rate);
-		}
-
-		{
-
-			wlc_phy_txpower_sromlimit((wlc_phy_t *) pi, target_chan,
-						  &mintxpwr, &maxtxpwr, rate);
-
-			maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
-
-			maxtxpwr =
-			    (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
-
-			maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
-
-			maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
-
-			if (pi->txpwr_percent <= 100)
-				maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
-
-			tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
-		}
-
-		tx_pwr_target[rate] =
-		    min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
-
-		if (tx_pwr_target[rate] > tx_pwr_max)
-			tx_pwr_max_rate_ind = rate;
-
-		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
-		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
-	}
-
-	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
-	pi->tx_power_max = tx_pwr_max;
-	pi->tx_power_min = tx_pwr_min;
-	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
-	for (rate = 0; rate < max_num_rate; rate++) {
-
-		pi->tx_power_target[rate] = tx_pwr_target[rate];
-
-		if (!pi->hwpwrctrl || ISNPHY(pi)) {
-			pi->tx_power_offset[rate] =
-			    pi->tx_power_max - pi->tx_power_target[rate];
-		} else {
-			pi->tx_power_offset[rate] =
-			    pi->tx_power_target[rate] - pi->tx_power_min;
-		}
-	}
-
-	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
-	if (txpwr_recalc_fn)
-		(*txpwr_recalc_fn) (pi);
-}
-
-void
-wlc_phy_txpower_reg_limit_calc(phy_info_t *pi, struct txpwr_limits *txpwr,
-			       chanspec_t chanspec)
-{
-	u8 tmp_txpwr_limit[2 * WLC_NUM_RATES_OFDM];
-	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
-	int rate_start_index = 0, rate1, rate2, k;
-
-	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
-	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
-		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
-
-	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
-	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
-		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
-
-	if (ISNPHY(pi)) {
-
-		for (k = 0; k < 4; k++) {
-			switch (k) {
-			case 0:
-
-				txpwr_ptr1 = txpwr->mcs_20_siso;
-				txpwr_ptr2 = txpwr->ofdm;
-				rate_start_index = WL_TX_POWER_OFDM_FIRST;
-				break;
-			case 1:
-
-				txpwr_ptr1 = txpwr->mcs_20_cdd;
-				txpwr_ptr2 = txpwr->ofdm_cdd;
-				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
-				break;
-			case 2:
-
-				txpwr_ptr1 = txpwr->mcs_40_siso;
-				txpwr_ptr2 = txpwr->ofdm_40_siso;
-				rate_start_index =
-				    WL_TX_POWER_OFDM40_SISO_FIRST;
-				break;
-			case 3:
-
-				txpwr_ptr1 = txpwr->mcs_40_cdd;
-				txpwr_ptr2 = txpwr->ofdm_40_cdd;
-				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
-				break;
-			}
-
-			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
-				tmp_txpwr_limit[rate2] = 0;
-				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
-				    txpwr_ptr1[rate2];
-			}
-			wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
-							WLC_NUM_RATES_OFDM - 1,
-							WLC_NUM_RATES_OFDM);
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_OFDM; rate1++, rate2++)
-				pi->txpwr_limit[rate1] =
-				    min(txpwr_ptr2[rate2],
-					tmp_txpwr_limit[rate2]);
-		}
-
-		for (k = 0; k < 4; k++) {
-			switch (k) {
-			case 0:
-
-				txpwr_ptr1 = txpwr->ofdm;
-				txpwr_ptr2 = txpwr->mcs_20_siso;
-				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
-				break;
-			case 1:
-
-				txpwr_ptr1 = txpwr->ofdm_cdd;
-				txpwr_ptr2 = txpwr->mcs_20_cdd;
-				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
-				break;
-			case 2:
-
-				txpwr_ptr1 = txpwr->ofdm_40_siso;
-				txpwr_ptr2 = txpwr->mcs_40_siso;
-				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
-				break;
-			case 3:
-
-				txpwr_ptr1 = txpwr->ofdm_40_cdd;
-				txpwr_ptr2 = txpwr->mcs_40_cdd;
-				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
-				break;
-			}
-			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
-				tmp_txpwr_limit[rate2] = 0;
-				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
-				    txpwr_ptr1[rate2];
-			}
-			wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
-							WLC_NUM_RATES_OFDM - 1,
-							WLC_NUM_RATES_OFDM);
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
-			     rate1++, rate2++)
-				pi->txpwr_limit[rate1] =
-				    min(txpwr_ptr2[rate2],
-					tmp_txpwr_limit[rate2]);
-		}
-
-		for (k = 0; k < 2; k++) {
-			switch (k) {
-			case 0:
-
-				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
-				txpwr_ptr1 = txpwr->mcs_20_stbc;
-				break;
-			case 1:
-
-				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
-				txpwr_ptr1 = txpwr->mcs_40_stbc;
-				break;
-			}
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
-			     rate1++, rate2++)
-				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
-		}
-
-		for (k = 0; k < 2; k++) {
-			switch (k) {
-			case 0:
-
-				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
-				txpwr_ptr1 = txpwr->mcs_20_mimo;
-				break;
-			case 1:
-
-				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
-				txpwr_ptr1 = txpwr->mcs_40_mimo;
-				break;
-			}
-			for (rate1 = rate_start_index, rate2 = 0;
-			     rate2 < WLC_NUM_RATES_MCS_2_STREAM;
-			     rate1++, rate2++)
-				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
-		}
-
-		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
-
-		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
-		    min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
-			pi->txpwr_limit[WL_TX_POWER_MCS_32]);
-		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
-		    pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
-	}
-}
-
-void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->txpwr_percent = txpwr_percent;
-}
-
-void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->sh->machwcap = machwcap;
-}
-
-void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 rxc;
-	rxc = 0;
-
-	if (start_end == ON) {
-		if (!ISNPHY(pi))
-			return;
-
-		if (NREV_IS(pi->pubpi.phy_rev, 3)
-		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
-			W_REG(pi->sh->osh, &pi->regs->phyregaddr, 0xa0);
-			(void)R_REG(pi->sh->osh, &pi->regs->phyregaddr);
-			rxc = R_REG(pi->sh->osh, &pi->regs->phyregdata);
-			W_REG(pi->sh->osh, &pi->regs->phyregdata,
-			      (0x1 << 15) | rxc);
-		}
-	} else {
-		if (NREV_IS(pi->pubpi.phy_rev, 3)
-		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
-			W_REG(pi->sh->osh, &pi->regs->phyregaddr, 0xa0);
-			(void)R_REG(pi->sh->osh, &pi->regs->phyregaddr);
-			W_REG(pi->sh->osh, &pi->regs->phyregdata, rxc);
-		}
-
-		wlc_phy_por_inform(ppi);
-	}
-}
-
-void
-wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr,
-			  chanspec_t chanspec)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
-
-	if (ISLCNPHY(pi)) {
-		int i, j;
-		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
-		     j < WLC_NUM_RATES_MCS_1_STREAM; i++, j++) {
-			if (txpwr->mcs_20_siso[j])
-				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
-			else
-				pi->txpwr_limit[i] = txpwr->ofdm[j];
-		}
-	}
-
-	wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	wlc_phy_txpower_recalc_target(pi);
-	wlc_phy_cal_txpower_recalc_sw(pi);
-	wlapi_enable_mac(pi->sh->physhim);
-}
-
-void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->ofdm_rateset_war = war;
-}
-
-void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->bf_preempt_4306 = bf_preempt;
-}
-
-void wlc_phy_txpower_update_shm(phy_info_t *pi)
-{
-	int j;
-	if (ISNPHY(pi)) {
-		ASSERT(0);
-		return;
-	}
-
-	if (!pi->sh->clk)
-		return;
-
-	if (pi->hwpwrctrl) {
-		u16 offset;
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
-				     1 << NUM_TSSI_FRAMES);
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
-				     pi->tx_power_min << NUM_TSSI_FRAMES);
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
-				     pi->hwpwr_txcur);
-
-		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
-			const u8 ucode_ofdm_rates[] = {
-				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
-			};
-			offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
-							    ucode_ofdm_rates[j -
-									     TXP_FIRST_OFDM]);
-			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
-					     pi->tx_power_offset[j]);
-			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
-					     -(pi->tx_power_offset[j] / 2));
-		}
-
-		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
-			       MHF2_HWPWRCTL, WLC_BAND_ALL);
-	} else {
-		int i;
-
-		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
-			pi->tx_power_offset[i] =
-			    (u8) roundup(pi->tx_power_offset[i], 8);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
-				     (u16) ((pi->
-						tx_power_offset[TXP_FIRST_OFDM]
-						+ 7) >> 3));
-	}
-}
-
-bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	if (ISNPHY(pi)) {
-		return pi->nphy_txpwrctrl;
-	} else {
-		return pi->hwpwrctrl;
-	}
-}
-
-void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	bool cur_hwpwrctrl = pi->hwpwrctrl;
-	bool suspend;
-
-	if (!pi->hwpwrctrl_capable) {
-		return;
-	}
-
-	pi->hwpwrctrl = hwpwrctrl;
-	pi->nphy_txpwrctrl = hwpwrctrl;
-	pi->txpwrctrl = hwpwrctrl;
-
-	if (ISNPHY(pi)) {
-		suspend =
-		    (0 ==
-		     (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
-		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
-			wlc_phy_txpwr_fixpower_nphy(pi);
-		} else {
-
-			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
-				    pi->saved_txpwr_idx);
-		}
-
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	} else if (hwpwrctrl != cur_hwpwrctrl) {
-
-		return;
-	}
-}
-
-void wlc_phy_txpower_ipa_upd(phy_info_t *pi)
-{
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
-		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
-	} else {
-		pi->ipa2g_on = false;
-		pi->ipa5g_on = false;
-	}
-}
-
-static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi);
-
-static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi)
-{
-	s16 tx0_status, tx1_status;
-	u16 estPower1, estPower2;
-	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
-	u32 est_pwr;
-
-	estPower1 = read_phy_reg(pi, 0x118);
-	estPower2 = read_phy_reg(pi, 0x119);
-
-	if ((estPower1 & (0x1 << 8))
-	    == (0x1 << 8)) {
-		pwr0 = (u8) (estPower1 & (0xff << 0))
-		    >> 0;
-	} else {
-		pwr0 = 0x80;
-	}
-
-	if ((estPower2 & (0x1 << 8))
-	    == (0x1 << 8)) {
-		pwr1 = (u8) (estPower2 & (0xff << 0))
-		    >> 0;
-	} else {
-		pwr1 = 0x80;
-	}
-
-	tx0_status = read_phy_reg(pi, 0x1ed);
-	tx1_status = read_phy_reg(pi, 0x1ee);
-
-	if ((tx0_status & (0x1 << 15))
-	    == (0x1 << 15)) {
-		adj_pwr0 = (u8) (tx0_status & (0xff << 0))
-		    >> 0;
-	} else {
-		adj_pwr0 = 0x80;
-	}
-	if ((tx1_status & (0x1 << 15))
-	    == (0x1 << 15)) {
-		adj_pwr1 = (u8) (tx1_status & (0xff << 0))
-		    >> 0;
-	} else {
-		adj_pwr1 = 0x80;
-	}
-
-	est_pwr =
-	    (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
-	return est_pwr;
-}
-
-void
-wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power, uint channel)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	uint rate, num_rates;
-	u8 min_pwr, max_pwr;
-
-#if WL_TX_POWER_RATES != TXP_NUM_RATES
-#error "tx_power_t struct out of sync with this fn"
-#endif
-
-	if (ISNPHY(pi)) {
-		power->rf_cores = 2;
-		power->flags |= (WL_TX_POWER_F_MIMO);
-		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
-			power->flags |=
-			    (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
-	} else if (ISLCNPHY(pi)) {
-		power->rf_cores = 1;
-		power->flags |= (WL_TX_POWER_F_SISO);
-		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
-			power->flags |= WL_TX_POWER_F_ENABLED;
-		if (pi->hwpwrctrl)
-			power->flags |= WL_TX_POWER_F_HW;
-	}
-
-	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
-		     ((ISLCNPHY(pi)) ?
-		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
-
-	for (rate = 0; rate < num_rates; rate++) {
-		power->user_limit[rate] = pi->tx_user_target[rate];
-		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
-					  rate);
-		power->board_limit[rate] = (u8) max_pwr;
-		power->target[rate] = pi->tx_power_target[rate];
-	}
-
-	if (ISNPHY(pi)) {
-		u32 est_pout;
-
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_phyreg_enter((wlc_phy_t *) pi);
-		est_pout = wlc_phy_txpower_est_power_nphy(pi);
-		wlc_phyreg_exit((wlc_phy_t *) pi);
-		wlapi_enable_mac(pi->sh->physhim);
-
-		power->est_Pout[0] = (est_pout >> 8) & 0xff;
-		power->est_Pout[1] = est_pout & 0xff;
-
-		power->est_Pout_act[0] = est_pout >> 24;
-		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
-
-		if (power->est_Pout[0] == 0x80)
-			power->est_Pout[0] = 0;
-		if (power->est_Pout[1] == 0x80)
-			power->est_Pout[1] = 0;
-
-		if (power->est_Pout_act[0] == 0x80)
-			power->est_Pout_act[0] = 0;
-		if (power->est_Pout_act[1] == 0x80)
-			power->est_Pout_act[1] = 0;
-
-		power->est_Pout_cck = 0;
-
-		power->tx_power_max[0] = pi->tx_power_max;
-		power->tx_power_max[1] = pi->tx_power_max;
-
-		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
-		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
-	} else if (!pi->hwpwrctrl) {
-	} else if (pi->sh->up) {
-
-		wlc_phyreg_enter(ppi);
-		if (ISLCNPHY(pi)) {
-
-			power->tx_power_max[0] = pi->tx_power_max;
-			power->tx_power_max[1] = pi->tx_power_max;
-
-			power->tx_power_max_rate_ind[0] =
-			    pi->tx_power_max_rate_ind;
-			power->tx_power_max_rate_ind[1] =
-			    pi->tx_power_max_rate_ind;
-
-			if (wlc_phy_tpc_isenabled_lcnphy(pi))
-				power->flags |=
-				    (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
-			else
-				power->flags &=
-				    ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
-
-			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
-					    (s8 *) &power->est_Pout_cck);
-		}
-		wlc_phyreg_exit(ppi);
-	}
-}
-
-void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	pi->antsel_type = antsel_type;
-}
-
-bool wlc_phy_test_ison(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	return pi->phytest_on;
-}
-
-bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	bool ret = true;
-
-	wlc_phyreg_enter(ppi);
-
-	if (ISNPHY(pi)) {
-
-		ret = false;
-	} else if (ISLCNPHY(pi)) {
-		u16 crsctrl = read_phy_reg(pi, 0x410);
-		u16 div = crsctrl & (0x1 << 1);
-		*pval = (div | ((crsctrl & (0x1 << 0)) ^ (div >> 1)));
-	}
-
-	wlc_phyreg_exit(ppi);
-
-	return ret;
-}
-
-void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	bool suspend;
-
-	pi->sh->rx_antdiv = val;
-
-	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
-		if (val > ANT_RX_DIV_FORCE_1)
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
-				       MHF1_ANTDIV, WLC_BAND_ALL);
-		else
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
-				       WLC_BAND_ALL);
-	}
-
-	if (ISNPHY(pi)) {
-
-		return;
-	}
-
-	if (!pi->sh->clk)
-		return;
-
-	suspend =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (ISLCNPHY(pi)) {
-		if (val > ANT_RX_DIV_FORCE_1) {
-			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
-			mod_phy_reg(pi, 0x410,
-				    (0x1 << 0),
-				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
-		} else {
-			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
-			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
-		}
-	} else {
-		ASSERT(0);
-	}
-
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-
-	return;
-}
-
-static bool
-wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr, s8 *pwr_ant)
-{
-	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
-	u8 i;
-
-	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
-	ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
-	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
-
-	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-		if (NREV_GE(pi->pubpi.phy_rev, 3))
-			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
-		else
-
-			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
-	}
-
-	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
-		pwr_ant[i] = cmplx_pwr_dbm[i];
-	}
-	pi->nphy_noise_index =
-	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
-	return true;
-}
-
-static void
-wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason, u8 ch)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-	bool sampling_in_progress = (pi->phynoise_state != 0);
-	bool wait_for_intr = true;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		return;
-	}
-
-	switch (reason) {
-	case PHY_NOISE_SAMPLE_MON:
-
-		pi->phynoise_chan_watchdog = ch;
-		pi->phynoise_state |= PHY_NOISE_STATE_MON;
-
-		break;
-
-	case PHY_NOISE_SAMPLE_EXTERNAL:
-
-		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
-		break;
-
-	default:
-		ASSERT(0);
-		break;
-	}
-
-	if (sampling_in_progress)
-		return;
-
-	pi->phynoise_now = pi->sh->now;
-
-	if (pi->phy_fixed_noise) {
-		if (ISNPHY(pi)) {
-			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
-			    PHY_NOISE_FIXED_VAL_NPHY;
-			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
-			    PHY_NOISE_FIXED_VAL_NPHY;
-			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
-							   PHY_NOISE_WINDOW_SZ);
-
-			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-		} else {
-
-			noise_dbm = PHY_NOISE_FIXED_VAL;
-		}
-
-		wait_for_intr = false;
-		goto done;
-	}
-
-	if (ISLCNPHY(pi)) {
-		if (!pi->phynoise_polling
-		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
-			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
-
-			OR_REG(pi->sh->osh, &pi->regs->maccommand,
-			       MCMD_BG_NOISE);
-		} else {
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-			wlc_lcnphy_deaf_mode(pi, (bool) 0);
-			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
-			wlc_lcnphy_deaf_mode(pi, (bool) 1);
-			wlapi_enable_mac(pi->sh->physhim);
-			wait_for_intr = false;
-		}
-	} else if (ISNPHY(pi)) {
-		if (!pi->phynoise_polling
-		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
-
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
-
-			OR_REG(pi->sh->osh, &pi->regs->maccommand,
-			       MCMD_BG_NOISE);
-		} else {
-			phy_iq_est_t est[PHY_CORE_MAX];
-			u32 cmplx_pwr[PHY_CORE_MAX];
-			s8 noise_dbm_ant[PHY_CORE_MAX];
-			u16 log_num_samps, num_samps, classif_state = 0;
-			u8 wait_time = 32;
-			u8 wait_crs = 0;
-			u8 i;
-
-			memset((u8 *) est, 0, sizeof(est));
-			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
-			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
-
-			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
-			num_samps = 1 << log_num_samps;
-
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
-			wlc_phy_classifier_nphy(pi, 3, 0);
-			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
-					       wait_crs);
-			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
-			wlapi_enable_mac(pi->sh->physhim);
-
-			for (i = 0; i < pi->pubpi.phy_corenum; i++)
-				cmplx_pwr[i] =
-				    (est[i].i_pwr +
-				     est[i].q_pwr) >> log_num_samps;
-
-			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
-
-			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-				pi->nphy_noise_win[i][pi->nphy_noise_index] =
-				    noise_dbm_ant[i];
-
-				if (noise_dbm_ant[i] > noise_dbm)
-					noise_dbm = noise_dbm_ant[i];
-			}
-			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
-							   PHY_NOISE_WINDOW_SZ);
-
-			wait_for_intr = false;
-		}
-	}
-
- done:
-
-	if (!wait_for_intr)
-		wlc_phy_noise_cb(pi, ch, noise_dbm);
-
-}
-
-void wlc_phy_noise_sample_request_external(wlc_phy_t *pih)
-{
-	u8 channel;
-
-	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
-
-	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
-}
-
-static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm)
-{
-	if (!pi->phynoise_state)
-		return;
-
-	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
-		if (pi->phynoise_chan_watchdog == channel) {
-			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
-			    noise_dbm;
-			pi->sh->phy_noise_index =
-			    MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
-		}
-		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
-	}
-
-	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
-		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
-	}
-
-}
-
-static s8 wlc_phy_noise_read_shmem(phy_info_t *pi)
-{
-	u32 cmplx_pwr[PHY_CORE_MAX];
-	s8 noise_dbm_ant[PHY_CORE_MAX];
-	u16 lo, hi;
-	u32 cmplx_pwr_tot = 0;
-	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-	u8 idx, core;
-
-	ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
-	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
-	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
-
-	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
-		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
-		hi = wlapi_bmac_read_shm(pi->sh->physhim,
-					 M_PWRIND_MAP(idx + 1));
-		cmplx_pwr[core] = (hi << 16) + lo;
-		cmplx_pwr_tot += cmplx_pwr[core];
-		if (cmplx_pwr[core] == 0) {
-			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
-		} else
-			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
-	}
-
-	if (cmplx_pwr_tot != 0)
-		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		pi->nphy_noise_win[core][pi->nphy_noise_index] =
-		    noise_dbm_ant[core];
-
-		if (noise_dbm_ant[core] > noise_dbm)
-			noise_dbm = noise_dbm_ant[core];
-	}
-	pi->nphy_noise_index =
-	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
-
-	return noise_dbm;
-
-}
-
-void wlc_phy_noise_sample_intr(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	u16 jssi_aux;
-	u8 channel = 0;
-	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
-
-	if (ISLCNPHY(pi)) {
-		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
-		u16 lo, hi;
-		s32 pwr_offset_dB, gain_dB;
-		u16 status_0, status_1;
-
-		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
-		channel = jssi_aux & D11_CURCHANNEL_MAX;
-
-		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
-		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
-		cmplx_pwr0 = (hi << 16) + lo;
-
-		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
-		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
-		cmplx_pwr1 = (hi << 16) + lo;
-		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
-
-		status_0 = 0x44;
-		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
-		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
-		    && ((status_1 & 0xc000) == 0x4000)) {
-
-			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
-					   pi->pubpi.phy_corenum);
-			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
-			if (pwr_offset_dB > 127)
-				pwr_offset_dB -= 256;
-
-			noise_dbm += (s8) (pwr_offset_dB - 30);
-
-			gain_dB = (status_0 & 0x1ff);
-			noise_dbm -= (s8) (gain_dB);
-		} else {
-			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
-		}
-	} else if (ISNPHY(pi)) {
-
-		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
-		channel = jssi_aux & D11_CURCHANNEL_MAX;
-
-		noise_dbm = wlc_phy_noise_read_shmem(pi);
-	} else {
-		ASSERT(0);
-	}
-
-	wlc_phy_noise_cb(pi, channel, noise_dbm);
-
-}
-
-s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
-	8,
-	8,
-	8,
-	8,
-	8,
-	8,
-	8,
-	9,
-	10,
-	8,
-	8,
-	7,
-	7,
-	1,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	1,
-	1,
-	0,
-	0,
-	0,
-	0
-};
-
-void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
-{
-	u8 shift_ct, lsb, msb, secondmsb, i;
-	u32 tmp;
-
-	for (i = 0; i < core; i++) {
-		tmp = cmplx_pwr[i];
-		shift_ct = msb = secondmsb = 0;
-		while (tmp != 0) {
-			tmp = tmp >> 1;
-			shift_ct++;
-			lsb = (u8) (tmp & 1);
-			if (lsb == 1)
-				msb = shift_ct;
-		}
-		secondmsb = (u8) ((cmplx_pwr[i] >> (msb - 1)) & 1);
-		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
-	}
-}
-
-void BCMFASTPATH wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx)
-{
-	wlc_d11rxhdr_t *wlc_rxhdr = (wlc_d11rxhdr_t *) ctx;
-	d11rxhdr_t *rxh = &wlc_rxhdr->rxhdr;
-	int rssi = ltoh16(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
-	uint radioid = pih->radioid;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		rssi = WLC_RSSI_INVALID;
-		goto end;
-	}
-
-	if ((pi->sh->corerev >= 11)
-	    && !(ltoh16(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
-		rssi = WLC_RSSI_INVALID;
-		goto end;
-	}
-
-	if (ISLCNPHY(pi)) {
-		u8 gidx = (ltoh16(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
-		phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-		if (rssi > 127)
-			rssi -= 256;
-
-		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
-		if ((rssi > -46) && (gidx > 18))
-			rssi = rssi + 7;
-
-		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
-
-		rssi = rssi + 2;
-
-	}
-
-	if (ISLCNPHY(pi)) {
-
-		if (rssi > 127)
-			rssi -= 256;
-	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
-		   || radioid == BCM2057_ID) {
-		ASSERT(ISNPHY(pi));
-		rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
-	} else {
-		ASSERT((const char *)"Unknown radio" == NULL);
-	}
-
- end:
-	wlc_rxhdr->rssi = (s8) rssi;
-}
-
-void wlc_phy_freqtrack_start(wlc_phy_t *pih)
-{
-	return;
-}
-
-void wlc_phy_freqtrack_end(wlc_phy_t *pih)
-{
-	return;
-}
-
-void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag)
-{
-	phy_info_t *pi;
-	pi = (phy_info_t *) ppi;
-
-	if (ISLCNPHY(pi))
-		wlc_lcnphy_deaf_mode(pi, true);
-	else if (ISNPHY(pi))
-		wlc_nphy_deaf_mode(pi, true);
-	else {
-		ASSERT(0);
-	}
-}
-
-void wlc_phy_watchdog(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	bool delay_phy_cal = false;
-	pi->sh->now++;
-
-	if (!pi->watchdog_override)
-		return;
-
-	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
-		wlc_phy_noise_sample_request((wlc_phy_t *) pi,
-					     PHY_NOISE_SAMPLE_MON,
-					     CHSPEC_CHANNEL(pi->
-							    radio_chanspec));
-	}
-
-	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
-		pi->phynoise_state = 0;
-	}
-
-	if ((!pi->phycal_txpower) ||
-	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
-
-		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
-			pi->phycal_txpower = pi->sh->now;
-		}
-	}
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
-	     || ASSOC_INPROG_PHY(pi)))
-		return;
-
-	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
-
-		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
-		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
-		    ((pi->sh->now - pi->nphy_perical_last) >=
-		     pi->sh->glacial_timer))
-			wlc_phy_cal_perical((wlc_phy_t *) pi,
-					    PHY_PERICAL_WATCHDOG);
-
-		wlc_phy_txpwr_papd_cal_nphy(pi);
-	}
-
-	if (ISLCNPHY(pi)) {
-		if (pi->phy_forcecal ||
-		    ((pi->sh->now - pi->phy_lastcal) >=
-		     pi->sh->glacial_timer)) {
-			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
-				wlc_lcnphy_calib_modes(pi,
-						       LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
-			if (!
-			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
-			     || ASSOC_INPROG_PHY(pi)
-			     || pi->carrier_suppr_disable
-			     || pi->disable_percal))
-				wlc_lcnphy_calib_modes(pi,
-						       PHY_PERICAL_WATCHDOG);
-		}
-	}
-}
-
-void wlc_phy_BSSinit(wlc_phy_t *pih, bool bonlyap, int rssi)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	uint i;
-	uint k;
-
-	for (i = 0; i < MA_WINDOW_SZ; i++) {
-		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
-	}
-	if (ISLCNPHY(pi)) {
-		for (i = 0; i < MA_WINDOW_SZ; i++)
-			pi->sh->phy_noise_window[i] =
-			    PHY_NOISE_FIXED_VAL_LCNPHY;
-	}
-	pi->sh->phy_noise_index = 0;
-
-	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
-		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
-			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
-	}
-	pi->nphy_noise_index = 0;
-}
-
-void
-wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
-{
-	*eps_imag = (epsilon >> 13);
-	if (*eps_imag > 0xfff)
-		*eps_imag -= 0x2000;
-
-	*eps_real = (epsilon & 0x1fff);
-	if (*eps_real > 0xfff)
-		*eps_real -= 0x2000;
-}
-
-static const fixed AtanTbl[] = {
-	2949120,
-	1740967,
-	919879,
-	466945,
-	234379,
-	117304,
-	58666,
-	29335,
-	14668,
-	7334,
-	3667,
-	1833,
-	917,
-	458,
-	229,
-	115,
-	57,
-	29
-};
-
-void wlc_phy_cordic(fixed theta, cs32 *val)
-{
-	fixed angle, valtmp;
-	unsigned iter;
-	int signx = 1;
-	int signtheta;
-
-	val[0].i = CORDIC_AG;
-	val[0].q = 0;
-	angle = 0;
-
-	signtheta = (theta < 0) ? -1 : 1;
-	theta =
-	    ((theta + FIXED(180) * signtheta) % FIXED(360)) -
-	    FIXED(180) * signtheta;
-
-	if (FLOAT(theta) > 90) {
-		theta -= FIXED(180);
-		signx = -1;
-	} else if (FLOAT(theta) < -90) {
-		theta += FIXED(180);
-		signx = -1;
-	}
-
-	for (iter = 0; iter < CORDIC_NI; iter++) {
-		if (theta > angle) {
-			valtmp = val[0].i - (val[0].q >> iter);
-			val[0].q = (val[0].i >> iter) + val[0].q;
-			val[0].i = valtmp;
-			angle += AtanTbl[iter];
-		} else {
-			valtmp = val[0].i + (val[0].q >> iter);
-			val[0].q = -(val[0].i >> iter) + val[0].q;
-			val[0].i = valtmp;
-			angle -= AtanTbl[iter];
-		}
-	}
-
-	val[0].i = val[0].i * signx;
-	val[0].q = val[0].q * signx;
-}
-
-void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi)
-{
-	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
-
-	pi->cal_type_override = PHY_PERICAL_AUTO;
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
-	pi->mphase_txcal_cmdidx = 0;
-}
-
-static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay)
-{
-
-	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
-	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
-		return;
-
-	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
-
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
-	wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
-}
-
-void wlc_phy_cal_perical(wlc_phy_t *pih, u8 reason)
-{
-	s16 nphy_currtemp = 0;
-	s16 delta_temp = 0;
-	bool do_periodic_cal = true;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	if (!ISNPHY(pi))
-		return;
-
-	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
-	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
-		return;
-
-	switch (reason) {
-	case PHY_PERICAL_DRIVERUP:
-		break;
-
-	case PHY_PERICAL_PHYINIT:
-		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
-			if (PHY_PERICAL_MPHASE_PENDING(pi)) {
-				wlc_phy_cal_perical_mphase_reset(pi);
-			}
-			wlc_phy_cal_perical_mphase_schedule(pi,
-							    PHY_PERICAL_INIT_DELAY);
-		}
-		break;
-
-	case PHY_PERICAL_JOIN_BSS:
-	case PHY_PERICAL_START_IBSS:
-	case PHY_PERICAL_UP_BSS:
-		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
-		    PHY_PERICAL_MPHASE_PENDING(pi)) {
-			wlc_phy_cal_perical_mphase_reset(pi);
-		}
-
-		pi->first_cal_after_assoc = true;
-
-		pi->cal_type_override = PHY_PERICAL_FULL;
-
-		if (pi->phycal_tempdelta) {
-			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
-		}
-		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
-		break;
-
-	case PHY_PERICAL_WATCHDOG:
-		if (pi->phycal_tempdelta) {
-			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
-			delta_temp =
-			    (nphy_currtemp > pi->nphy_lastcal_temp) ?
-			    nphy_currtemp - pi->nphy_lastcal_temp :
-			    pi->nphy_lastcal_temp - nphy_currtemp;
-
-			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
-			    (pi->nphy_txiqlocal_chanspec ==
-			     pi->radio_chanspec)) {
-				do_periodic_cal = false;
-			} else {
-				pi->nphy_lastcal_temp = nphy_currtemp;
-			}
-		}
-
-		if (do_periodic_cal) {
-
-			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
-
-				if (!PHY_PERICAL_MPHASE_PENDING(pi))
-					wlc_phy_cal_perical_mphase_schedule(pi,
-									    PHY_PERICAL_WDOG_DELAY);
-			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
-				wlc_phy_cal_perical_nphy_run(pi,
-							     PHY_PERICAL_AUTO);
-			else {
-				ASSERT(0);
-			}
-		}
-		break;
-	default:
-		ASSERT(0);
-		break;
-	}
-}
-
-void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi)
-{
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
-	pi->mphase_txcal_cmdidx = 0;
-}
-
-u8 wlc_phy_nbits(s32 value)
-{
-	s32 abs_val;
-	u8 nbits = 0;
-
-	abs_val = ABS(value);
-	while ((abs_val >> nbits) > 0)
-		nbits++;
-
-	return nbits;
-}
-
-u32 wlc_phy_sqrt_int(u32 value)
-{
-	u32 root = 0, shift = 0;
-
-	for (shift = 0; shift < 32; shift += 2) {
-		if (((0x40000000 >> shift) + root) <= value) {
-			value -= ((0x40000000 >> shift) + root);
-			root = (root >> 1) | (0x40000000 >> shift);
-		} else {
-			root = root >> 1;
-		}
-	}
-
-	if (root < value)
-		++root;
-
-	return root;
-}
-
-void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain, u8 rxchain)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->sh->hw_phytxchain = txchain;
-	pi->sh->hw_phyrxchain = rxchain;
-	pi->sh->phytxchain = txchain;
-	pi->sh->phyrxchain = rxchain;
-	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
-}
-
-void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain, u8 rxchain)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	pi->sh->phytxchain = txchain;
-
-	if (ISNPHY(pi)) {
-		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
-	}
-	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
-}
-
-void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain, u8 *rxchain)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	*txchain = pi->sh->phytxchain;
-	*rxchain = pi->sh->phyrxchain;
-}
-
-u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih)
-{
-	s16 nphy_currtemp;
-	u8 active_bitmap;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
-
-	if (!pi->watchdog_override)
-		return active_bitmap;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
-		wlapi_enable_mac(pi->sh->physhim);
-
-		if (!pi->phy_txcore_heatedup) {
-			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
-				active_bitmap &= 0xFD;
-				pi->phy_txcore_heatedup = true;
-			}
-		} else {
-			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
-				active_bitmap |= 0x2;
-				pi->phy_txcore_heatedup = false;
-			}
-		}
-	}
-
-	return active_bitmap;
-}
-
-s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	u8 siso_mcs_id, cdd_mcs_id;
-
-	siso_mcs_id =
-	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
-	    TXP_FIRST_MCS_20_SISO;
-	cdd_mcs_id =
-	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
-	    TXP_FIRST_MCS_20_CDD;
-
-	if (pi->tx_power_target[siso_mcs_id] >
-	    (pi->tx_power_target[cdd_mcs_id] + 12))
-		return PHY_TXC1_MODE_SISO;
-	else
-		return PHY_TXC1_MODE_CDD;
-}
-
-const u8 *wlc_phy_get_ofdm_rate_lookup(void)
-{
-	return ofdm_rate_lookup;
-}
-
-void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode)
-{
-	if ((pi->sh->chip == BCM4313_CHIP_ID) &&
-	    (pi->sh->boardflags & BFL_FEM)) {
-		if (mode) {
-			u16 txant = 0;
-			txant = wlapi_bmac_get_txant(pi->sh->physhim);
-			if (txant == 1) {
-				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
-
-				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
-
-			}
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
-				   0x0);
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioout), 0x40, 0x40);
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioouten), 0x40,
-				   0x40);
-		} else {
-			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
-
-			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
-
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioout), 0x40, 0x00);
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
-				   0x40);
-		}
-	}
-}
-
-static s8
-wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan, u32 band,
-				 u8 rate)
-{
-	s8 offset = 0;
-
-	if (!pi->user_txpwr_at_rfport)
-		return offset;
-	return offset;
-}
-
-static s8 wlc_phy_env_measure_vbat(phy_info_t *pi)
-{
-	if (ISLCNPHY(pi))
-		return wlc_lcnphy_vbatsense(pi, 0);
-	else
-		return 0;
-}
-
-static s8 wlc_phy_env_measure_temperature(phy_info_t *pi)
-{
-	if (ISLCNPHY(pi))
-		return wlc_lcnphy_tempsense_degree(pi, 0);
-	else
-		return 0;
-}
-
-static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band)
-{
-	u8 i;
-	s8 temp, vbat;
-
-	for (i = 0; i < TXP_NUM_RATES; i++)
-		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
-
-	vbat = wlc_phy_env_measure_vbat(pi);
-	temp = wlc_phy_env_measure_temperature(pi);
-
-}
-
-void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool ldpc)
-{
-	return;
-}
-
-void
-wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset, s8 *ofdmoffset)
-{
-	*cckoffset = 0;
-	*ofdmoffset = 0;
-}
-
-u32 wlc_phy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
-{
-	u32 quotient, remainder, roundup, rbit;
-
-	ASSERT(divisor);
-
-	quotient = dividend / divisor;
-	remainder = dividend % divisor;
-	rbit = divisor & 1;
-	roundup = (divisor >> 1) + rbit;
-
-	while (precision--) {
-		quotient <<= 1;
-		if (remainder >= roundup) {
-			quotient++;
-			remainder = ((remainder - roundup) << 1) + rbit;
-		} else {
-			remainder <<= 1;
-		}
-	}
-
-	if (remainder >= roundup)
-		quotient++;
-
-	return quotient;
-}
-
-s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi, chanspec_t chanspec)
-{
-
-	return rssi;
-}
-
-bool wlc_phy_txpower_ipa_ison(wlc_phy_t *ppi)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	if (ISNPHY(pi))
-		return wlc_phy_n_txpower_ipa_ison(pi);
-	else
-		return 0;
-}
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_hal.h b/drivers/staging/brcm80211/phy/wlc_phy_hal.h
deleted file mode 100644
index 514e15e..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_hal.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_h_
-#define _wlc_phy_h_
-
-#include <wlioctl.h>
-#include <siutils.h>
-#include <d11.h>
-#include <wlc_phy_shim.h>
-
-#define	IDCODE_VER_MASK		0x0000000f
-#define	IDCODE_VER_SHIFT	0
-#define	IDCODE_MFG_MASK		0x00000fff
-#define	IDCODE_MFG_SHIFT	0
-#define	IDCODE_ID_MASK		0x0ffff000
-#define	IDCODE_ID_SHIFT		12
-#define	IDCODE_REV_MASK		0xf0000000
-#define	IDCODE_REV_SHIFT	28
-
-#define	NORADIO_ID		0xe4f5
-#define	NORADIO_IDCODE		0x4e4f5246
-
-#define BCM2055_ID		0x2055
-#define BCM2055_IDCODE		0x02055000
-#define BCM2055A0_IDCODE	0x1205517f
-
-#define BCM2056_ID		0x2056
-#define BCM2056_IDCODE		0x02056000
-#define BCM2056A0_IDCODE	0x1205617f
-
-#define BCM2057_ID		0x2057
-#define BCM2057_IDCODE		0x02057000
-#define BCM2057A0_IDCODE	0x1205717f
-
-#define BCM2064_ID		0x2064
-#define BCM2064_IDCODE		0x02064000
-#define BCM2064A0_IDCODE	0x0206417f
-
-#define PHY_TPC_HW_OFF		false
-#define PHY_TPC_HW_ON		true
-
-#define PHY_PERICAL_DRIVERUP	1
-#define PHY_PERICAL_WATCHDOG	2
-#define PHY_PERICAL_PHYINIT	3
-#define PHY_PERICAL_JOIN_BSS	4
-#define PHY_PERICAL_START_IBSS	5
-#define PHY_PERICAL_UP_BSS	6
-#define PHY_PERICAL_CHAN	7
-#define PHY_FULLCAL	8
-
-#define PHY_PERICAL_DISABLE	0
-#define PHY_PERICAL_SPHASE	1
-#define PHY_PERICAL_MPHASE	2
-#define PHY_PERICAL_MANUAL	3
-
-#define PHY_HOLD_FOR_ASSOC	1
-#define PHY_HOLD_FOR_SCAN	2
-#define PHY_HOLD_FOR_RM		4
-#define PHY_HOLD_FOR_PLT	8
-#define PHY_HOLD_FOR_MUTE	16
-#define PHY_HOLD_FOR_NOT_ASSOC 0x20
-
-#define PHY_MUTE_FOR_PREISM	1
-#define PHY_MUTE_ALL		0xffffffff
-
-#define PHY_NOISE_FIXED_VAL 		(-95)
-#define PHY_NOISE_FIXED_VAL_NPHY       	(-92)
-#define PHY_NOISE_FIXED_VAL_LCNPHY     	(-92)
-
-#define PHY_MODE_CAL		0x0002
-#define PHY_MODE_NOISEM		0x0004
-
-#define WLC_TXPWR_DB_FACTOR	4
-
-#define WLC_NUM_RATES_CCK           4
-#define WLC_NUM_RATES_OFDM          8
-#define WLC_NUM_RATES_MCS_1_STREAM  8
-#define WLC_NUM_RATES_MCS_2_STREAM  8
-#define WLC_NUM_RATES_MCS_3_STREAM  8
-#define WLC_NUM_RATES_MCS_4_STREAM  8
-typedef struct txpwr_limits {
-	u8 cck[WLC_NUM_RATES_CCK];
-	u8 ofdm[WLC_NUM_RATES_OFDM];
-
-	u8 ofdm_cdd[WLC_NUM_RATES_OFDM];
-
-	u8 ofdm_40_siso[WLC_NUM_RATES_OFDM];
-	u8 ofdm_40_cdd[WLC_NUM_RATES_OFDM];
-
-	u8 mcs_20_siso[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_20_cdd[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_20_stbc[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_20_mimo[WLC_NUM_RATES_MCS_2_STREAM];
-
-	u8 mcs_40_siso[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_40_cdd[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_40_stbc[WLC_NUM_RATES_MCS_1_STREAM];
-	u8 mcs_40_mimo[WLC_NUM_RATES_MCS_2_STREAM];
-	u8 mcs32;
-} txpwr_limits_t;
-
-typedef struct {
-	u8 vec[MAXCHANNEL / NBBY];
-} chanvec_t;
-
-struct rpc_info;
-typedef struct shared_phy shared_phy_t;
-
-struct phy_pub;
-
-typedef struct phy_pub wlc_phy_t;
-
-typedef struct shared_phy_params {
-	void *osh;
-	si_t *sih;
-	void *physhim;
-	uint unit;
-	uint corerev;
-	uint bustype;
-	uint buscorerev;
-	char *vars;
-	u16 vid;
-	u16 did;
-	uint chip;
-	uint chiprev;
-	uint chippkg;
-	uint sromrev;
-	uint boardtype;
-	uint boardrev;
-	uint boardvendor;
-	u32 boardflags;
-	u32 boardflags2;
-} shared_phy_params_t;
-
-
-extern shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp);
-extern void wlc_phy_shared_detach(shared_phy_t *phy_sh);
-extern wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype,
-				 char *vars);
-extern void wlc_phy_detach(wlc_phy_t *ppi);
-
-extern bool wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype,
-				   u16 *phyrev, u16 *radioid,
-				   u16 *radiover);
-extern bool wlc_phy_get_encore(wlc_phy_t *pih);
-extern u32 wlc_phy_get_coreflags(wlc_phy_t *pih);
-
-extern void wlc_phy_hw_clk_state_upd(wlc_phy_t *ppi, bool newstate);
-extern void wlc_phy_hw_state_upd(wlc_phy_t *ppi, bool newstate);
-extern void wlc_phy_init(wlc_phy_t *ppi, chanspec_t chanspec);
-extern void wlc_phy_watchdog(wlc_phy_t *ppi);
-extern int wlc_phy_down(wlc_phy_t *ppi);
-extern u32 wlc_phy_clk_bwbits(wlc_phy_t *pih);
-extern void wlc_phy_cal_init(wlc_phy_t *ppi);
-extern void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init);
-
-extern void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec);
-extern chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi);
-extern void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch);
-extern u16 wlc_phy_bw_state_get(wlc_phy_t *ppi);
-extern void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw);
-
-extern void wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx);
-extern void wlc_phy_por_inform(wlc_phy_t *ppi);
-extern void wlc_phy_noise_sample_intr(wlc_phy_t *ppi);
-extern bool wlc_phy_bist_check_phy(wlc_phy_t *ppi);
-
-extern void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag);
-
-extern void wlc_phy_switch_radio(wlc_phy_t *ppi, bool on);
-extern void wlc_phy_anacore(wlc_phy_t *ppi, bool on);
-
-
-extern void wlc_phy_BSSinit(wlc_phy_t *ppi, bool bonlyap, int rssi);
-
-extern void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi,
-						 bool wide_filter);
-extern void wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band,
-					  chanvec_t *channels);
-extern chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band);
-
-extern void wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint chan,
-				      u8 *_min_, u8 *_max_, int rate);
-extern void wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan,
-					      u8 *_max_, u8 *_min_);
-extern void wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint band, s32 *,
-					    s32 *, u32 *);
-extern void wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *,
-				      chanspec_t chanspec);
-extern int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override);
-extern int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override);
-extern void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *);
-extern bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi);
-extern void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl);
-extern u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi);
-extern u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi);
-extern bool wlc_phy_txpower_ipa_ison(wlc_phy_t *pih);
-
-extern void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain,
-				   u8 rxchain);
-extern void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain,
-				  u8 rxchain);
-extern void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain,
-				  u8 *rxchain);
-extern u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih);
-extern s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec);
-extern void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool val);
-
-extern void wlc_phy_cal_perical(wlc_phy_t *ppi, u8 reason);
-extern void wlc_phy_noise_sample_request_external(wlc_phy_t *ppi);
-extern void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock);
-extern void wlc_phy_cal_papd_recal(wlc_phy_t *ppi);
-
-extern void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val);
-extern bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval);
-extern void wlc_phy_clear_tssi(wlc_phy_t *ppi);
-extern void wlc_phy_hold_upd(wlc_phy_t *ppi, mbool id, bool val);
-extern void wlc_phy_mute_upd(wlc_phy_t *ppi, bool val, mbool flags);
-
-extern void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type);
-
-extern void wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power,
-					uint channel);
-
-extern void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal);
-extern bool wlc_phy_test_ison(wlc_phy_t *ppi);
-extern void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent);
-extern void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war);
-extern void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt);
-extern void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap);
-
-extern void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end);
-
-extern void wlc_phy_freqtrack_start(wlc_phy_t *ppi);
-extern void wlc_phy_freqtrack_end(wlc_phy_t *ppi);
-
-extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
-
-extern s8 wlc_phy_get_tx_power_offset_by_mcs(wlc_phy_t *ppi,
-					       u8 mcs_offset);
-extern s8 wlc_phy_get_tx_power_offset(wlc_phy_t *ppi, u8 tbl_offset);
-#endif				/* _wlc_phy_h_ */
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_int.h b/drivers/staging/brcm80211/phy/wlc_phy_int.h
deleted file mode 100644
index 72eee91..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_int.h
+++ /dev/null
@@ -1,1229 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_int_h_
-#define _wlc_phy_int_h_
-
-#include <linux/kernel.h>
-#include <bcmdefs.h>
-#include <bcmutils.h>
-
-#include <bcmsrom_fmt.h>
-#include <wlc_phy_hal.h>
-
-#define PHYHAL_ERROR	0x0001
-#define PHYHAL_TRACE	0x0002
-#define PHYHAL_INFORM	0x0004
-
-extern u32 phyhal_msg_level;
-
-#define PHY_INFORM_ON()		(phyhal_msg_level & PHYHAL_INFORM)
-#define PHY_THERMAL_ON()	(phyhal_msg_level & PHYHAL_THERMAL)
-#define PHY_CAL_ON()		(phyhal_msg_level & PHYHAL_CAL)
-
-#ifdef BOARD_TYPE
-#define BOARDTYPE(_type) BOARD_TYPE
-#else
-#define BOARDTYPE(_type) _type
-#endif
-
-#define LCNXN_BASEREV		16
-
-struct wlc_hw_info;
-typedef struct phy_info phy_info_t;
-typedef void (*initfn_t) (phy_info_t *);
-typedef void (*chansetfn_t) (phy_info_t *, chanspec_t);
-typedef int (*longtrnfn_t) (phy_info_t *, int);
-typedef void (*txiqccgetfn_t) (phy_info_t *, u16 *, u16 *);
-typedef void (*txiqccsetfn_t) (phy_info_t *, u16, u16);
-typedef u16(*txloccgetfn_t) (phy_info_t *);
-typedef void (*radioloftgetfn_t) (phy_info_t *, u8 *, u8 *, u8 *,
-				  u8 *);
-typedef s32(*rxsigpwrfn_t) (phy_info_t *, s32);
-typedef void (*detachfn_t) (phy_info_t *);
-
-#undef ISNPHY
-#undef ISLCNPHY
-#define ISNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
-#define ISLCNPHY(pi)  	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
-
-#define ISPHY_11N_CAP(pi)	(ISNPHY(pi) || ISLCNPHY(pi))
-
-#define IS20MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_20)
-#define IS40MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_40)
-
-#define PHY_GET_RFATTN(rfgain)	((rfgain) & 0x0f)
-#define PHY_GET_PADMIX(rfgain)	(((rfgain) & 0x10) >> 4)
-#define PHY_GET_RFGAINID(rfattn, padmix, width)	((rfattn) + ((padmix)*(width)))
-#define PHY_SAT(x, n)		((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \
-				((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x)))
-#define PHY_SHIFT_ROUND(x, n)	((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n))
-#define PHY_HW_ROUND(x, s)		((x >> s) + ((x >> (s-1)) & (s != 0)))
-
-#define CH_5G_GROUP	3
-#define A_LOW_CHANS	0
-#define A_MID_CHANS	1
-#define A_HIGH_CHANS	2
-#define CH_2G_GROUP	1
-#define G_ALL_CHANS	0
-
-#define FIRST_REF5_CHANNUM	149
-#define LAST_REF5_CHANNUM	165
-#define	FIRST_5G_CHAN		14
-#define	LAST_5G_CHAN		50
-#define	FIRST_MID_5G_CHAN	14
-#define	LAST_MID_5G_CHAN	35
-#define	FIRST_HIGH_5G_CHAN	36
-#define	LAST_HIGH_5G_CHAN	41
-#define	FIRST_LOW_5G_CHAN	42
-#define	LAST_LOW_5G_CHAN	50
-
-#define BASE_LOW_5G_CHAN	4900
-#define BASE_MID_5G_CHAN	5100
-#define BASE_HIGH_5G_CHAN	5500
-
-#define CHAN5G_FREQ(chan)  (5000 + chan*5)
-#define CHAN2G_FREQ(chan)  (2407 + chan*5)
-
-#define TXP_FIRST_CCK		0
-#define TXP_LAST_CCK		3
-#define TXP_FIRST_OFDM		4
-#define TXP_LAST_OFDM		11
-#define TXP_FIRST_OFDM_20_CDD	12
-#define TXP_LAST_OFDM_20_CDD	19
-#define TXP_FIRST_MCS_20_SISO	20
-#define TXP_LAST_MCS_20_SISO	27
-#define TXP_FIRST_MCS_20_CDD	28
-#define TXP_LAST_MCS_20_CDD	35
-#define TXP_FIRST_MCS_20_STBC	36
-#define TXP_LAST_MCS_20_STBC	43
-#define TXP_FIRST_MCS_20_SDM	44
-#define TXP_LAST_MCS_20_SDM	51
-#define TXP_FIRST_OFDM_40_SISO	52
-#define TXP_LAST_OFDM_40_SISO	59
-#define TXP_FIRST_OFDM_40_CDD	60
-#define TXP_LAST_OFDM_40_CDD	67
-#define TXP_FIRST_MCS_40_SISO	68
-#define TXP_LAST_MCS_40_SISO	75
-#define TXP_FIRST_MCS_40_CDD	76
-#define TXP_LAST_MCS_40_CDD	83
-#define TXP_FIRST_MCS_40_STBC	84
-#define TXP_LAST_MCS_40_STBC	91
-#define TXP_FIRST_MCS_40_SDM	92
-#define TXP_LAST_MCS_40_SDM	99
-#define TXP_MCS_32	        100
-#define TXP_NUM_RATES		101
-#define ADJ_PWR_TBL_LEN		84
-
-#define TXP_FIRST_SISO_MCS_20	20
-#define TXP_LAST_SISO_MCS_20	27
-
-#define PHY_CORE_NUM_1	1
-#define PHY_CORE_NUM_2	2
-#define PHY_CORE_NUM_3	3
-#define PHY_CORE_NUM_4	4
-#define PHY_CORE_MAX	PHY_CORE_NUM_4
-#define PHY_CORE_0	0
-#define PHY_CORE_1	1
-#define PHY_CORE_2	2
-#define PHY_CORE_3	3
-
-#define MA_WINDOW_SZ		8
-
-#define PHY_NOISE_SAMPLE_MON		1
-#define PHY_NOISE_SAMPLE_EXTERNAL	2
-#define PHY_NOISE_WINDOW_SZ	16
-#define PHY_NOISE_GLITCH_INIT_MA 10
-#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10
-#define PHY_NOISE_STATE_MON		0x1
-#define PHY_NOISE_STATE_EXTERNAL	0x2
-#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY	10
-#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE	9
-
-#define PHY_NOISE_OFFSETFACT_4322  (-103)
-#define PHY_NOISE_MA_WINDOW_SZ	2
-
-#define	PHY_RSSI_TABLE_SIZE	64
-#define RSSI_ANT_MERGE_MAX	0
-#define RSSI_ANT_MERGE_MIN	1
-#define RSSI_ANT_MERGE_AVG	2
-
-#define	PHY_TSSI_TABLE_SIZE	64
-#define	APHY_TSSI_TABLE_SIZE	256
-#define	TX_GAIN_TABLE_LENGTH	64
-#define	DEFAULT_11A_TXP_IDX	24
-#define NUM_TSSI_FRAMES        4
-#define	NULL_TSSI		0x7f
-#define	NULL_TSSI_W		0x7f7f
-
-#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64
-
-#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9
-
-#define PHY_TXPWR_MIN		10
-#define PHY_TXPWR_MIN_NPHY	8
-#define RADIOPWR_OVERRIDE_DEF	(-1)
-
-#define PWRTBL_NUM_COEFF	3
-
-#define SPURAVOID_DISABLE	0
-#define SPURAVOID_AUTO		1
-#define SPURAVOID_FORCEON	2
-#define SPURAVOID_FORCEON2	3
-
-#define PHY_SW_TIMER_FAST		15
-#define PHY_SW_TIMER_SLOW		60
-#define PHY_SW_TIMER_GLACIAL	120
-
-#define PHY_PERICAL_AUTO	0
-#define PHY_PERICAL_FULL	1
-#define PHY_PERICAL_PARTIAL	2
-
-#define PHY_PERICAL_NODELAY	0
-#define PHY_PERICAL_INIT_DELAY	5
-#define PHY_PERICAL_ASSOC_DELAY	5
-#define PHY_PERICAL_WDOG_DELAY	5
-
-#define MPHASE_TXCAL_NUMCMDS	2
-#define PHY_PERICAL_MPHASE_PENDING(pi)	(pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
-
-enum {
-	MPHASE_CAL_STATE_IDLE = 0,
-	MPHASE_CAL_STATE_INIT = 1,
-	MPHASE_CAL_STATE_TXPHASE0,
-	MPHASE_CAL_STATE_TXPHASE1,
-	MPHASE_CAL_STATE_TXPHASE2,
-	MPHASE_CAL_STATE_TXPHASE3,
-	MPHASE_CAL_STATE_TXPHASE4,
-	MPHASE_CAL_STATE_TXPHASE5,
-	MPHASE_CAL_STATE_PAPDCAL,
-	MPHASE_CAL_STATE_RXCAL,
-	MPHASE_CAL_STATE_RSSICAL,
-	MPHASE_CAL_STATE_IDLETSSI
-};
-
-typedef enum {
-	CAL_FULL,
-	CAL_RECAL,
-	CAL_CURRECAL,
-	CAL_DIGCAL,
-	CAL_GCTRL,
-	CAL_SOFT,
-	CAL_DIGLO
-} phy_cal_mode_t;
-
-#define RDR_NTIERS  1
-#define RDR_TIER_SIZE 64
-#define RDR_LIST_SIZE (512/3)
-#define RDR_EPOCH_SIZE 40
-#define RDR_NANTENNAS 2
-#define RDR_NTIER_SIZE  RDR_LIST_SIZE
-#define RDR_LP_BUFFER_SIZE 64
-#define LP_LEN_HIS_SIZE 10
-
-#define STATIC_NUM_RF 32
-#define STATIC_NUM_BB 9
-
-#define BB_MULT_MASK		0x0000ffff
-#define BB_MULT_VALID_MASK	0x80000000
-
-#define CORDIC_AG	39797
-#define	CORDIC_NI	18
-#define	FIXED(X)	((s32)((X) << 16))
-#define	FLOAT(X)	(((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
-
-#define PHY_CHAIN_TX_DISABLE_TEMP	115
-#define PHY_HYSTERESIS_DELTATEMP	5
-
-#define PHY_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
-
-#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
-	mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
-	(value) << phy_type##_##reg_name##_##field##_##SHIFT);
-#define READ_PHY_REG(pi, phy_type, reg_name, field) \
-	((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
-	>> phy_type##_##reg_name##_##field##_##SHIFT)
-
-#define	VALID_PHYTYPE(phytype)	(((uint)phytype == PHY_TYPE_N) || \
-				((uint)phytype == PHY_TYPE_LCN))
-
-#define VALID_N_RADIO(radioid)	((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
-				(radioid == BCM2057_ID))
-#define VALID_LCN_RADIO(radioid)	(radioid == BCM2064_ID)
-
-#define	VALID_RADIO(pi, radioid)	(\
-	(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
-	(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
-
-#define SCAN_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
-#define RM_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
-#define PLT_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
-#define ASSOC_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
-#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
-#define PHY_MUTED(pi)		(mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
-#define PUB_NOT_ASSOC(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
-
-#if defined(EXT_CBALL)
-#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
-#else
-#define NORADIO_ENAB(pub) 0
-#endif
-
-#define PHY_LTRN_LIST_LEN	64
-extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
-
-typedef struct _phy_table_info {
-	uint table;
-	int q;
-	uint max;
-} phy_table_info_t;
-
-typedef struct phytbl_info {
-	const void *tbl_ptr;
-	u32 tbl_len;
-	u32 tbl_id;
-	u32 tbl_offset;
-	u32 tbl_width;
-} phytbl_info_t;
-
-typedef struct {
-	u8 curr_home_channel;
-	u16 crsminpwrthld_40_stored;
-	u16 crsminpwrthld_20L_stored;
-	u16 crsminpwrthld_20U_stored;
-	u16 init_gain_code_core1_stored;
-	u16 init_gain_code_core2_stored;
-	u16 init_gain_codeb_core1_stored;
-	u16 init_gain_codeb_core2_stored;
-	u16 init_gain_table_stored[4];
-
-	u16 clip1_hi_gain_code_core1_stored;
-	u16 clip1_hi_gain_code_core2_stored;
-	u16 clip1_hi_gain_codeb_core1_stored;
-	u16 clip1_hi_gain_codeb_core2_stored;
-	u16 nb_clip_thresh_core1_stored;
-	u16 nb_clip_thresh_core2_stored;
-	u16 init_ofdmlna2gainchange_stored[4];
-	u16 init_ccklna2gainchange_stored[4];
-	u16 clip1_lo_gain_code_core1_stored;
-	u16 clip1_lo_gain_code_core2_stored;
-	u16 clip1_lo_gain_codeb_core1_stored;
-	u16 clip1_lo_gain_codeb_core2_stored;
-	u16 w1_clip_thresh_core1_stored;
-	u16 w1_clip_thresh_core2_stored;
-	u16 radio_2056_core1_rssi_gain_stored;
-	u16 radio_2056_core2_rssi_gain_stored;
-	u16 energy_drop_timeout_len_stored;
-
-	u16 ed_crs40_assertthld0_stored;
-	u16 ed_crs40_assertthld1_stored;
-	u16 ed_crs40_deassertthld0_stored;
-	u16 ed_crs40_deassertthld1_stored;
-	u16 ed_crs20L_assertthld0_stored;
-	u16 ed_crs20L_assertthld1_stored;
-	u16 ed_crs20L_deassertthld0_stored;
-	u16 ed_crs20L_deassertthld1_stored;
-	u16 ed_crs20U_assertthld0_stored;
-	u16 ed_crs20U_assertthld1_stored;
-	u16 ed_crs20U_deassertthld0_stored;
-	u16 ed_crs20U_deassertthld1_stored;
-
-	u16 badplcp_ma;
-	u16 badplcp_ma_previous;
-	u16 badplcp_ma_total;
-	u16 badplcp_ma_list[MA_WINDOW_SZ];
-	int badplcp_ma_index;
-	s16 pre_badplcp_cnt;
-	s16 bphy_pre_badplcp_cnt;
-
-	u16 init_gain_core1;
-	u16 init_gain_core2;
-	u16 init_gainb_core1;
-	u16 init_gainb_core2;
-	u16 init_gain_rfseq[4];
-
-	u16 crsminpwr0;
-	u16 crsminpwrl0;
-	u16 crsminpwru0;
-
-	s16 crsminpwr_index;
-
-	u16 radio_2057_core1_rssi_wb1a_gc_stored;
-	u16 radio_2057_core2_rssi_wb1a_gc_stored;
-	u16 radio_2057_core1_rssi_wb1g_gc_stored;
-	u16 radio_2057_core2_rssi_wb1g_gc_stored;
-	u16 radio_2057_core1_rssi_wb2_gc_stored;
-	u16 radio_2057_core2_rssi_wb2_gc_stored;
-	u16 radio_2057_core1_rssi_nb_gc_stored;
-	u16 radio_2057_core2_rssi_nb_gc_stored;
-
-} interference_info_t;
-
-typedef struct {
-	u16 rc_cal_ovr;
-	u16 phycrsth1;
-	u16 phycrsth2;
-	u16 init_n1p1_gain;
-	u16 p1_p2_gain;
-	u16 n1_n2_gain;
-	u16 n1_p1_gain;
-	u16 div_search_gain;
-	u16 div_p1_p2_gain;
-	u16 div_search_gn_change;
-	u16 table_7_2;
-	u16 table_7_3;
-	u16 cckshbits_gnref;
-	u16 clip_thresh;
-	u16 clip2_thresh;
-	u16 clip3_thresh;
-	u16 clip_p2_thresh;
-	u16 clip_pwdn_thresh;
-	u16 clip_n1p1_thresh;
-	u16 clip_n1_pwdn_thresh;
-	u16 bbconfig;
-	u16 cthr_sthr_shdin;
-	u16 energy;
-	u16 clip_p1_p2_thresh;
-	u16 threshold;
-	u16 reg15;
-	u16 reg16;
-	u16 reg17;
-	u16 div_srch_idx;
-	u16 div_srch_p1_p2;
-	u16 div_srch_gn_back;
-	u16 ant_dwell;
-	u16 ant_wr_settle;
-} aci_save_gphy_t;
-
-typedef struct _lo_complex_t {
-	s8 i;
-	s8 q;
-} lo_complex_abgphy_info_t;
-
-typedef struct _nphy_iq_comp {
-	s16 a0;
-	s16 b0;
-	s16 a1;
-	s16 b1;
-} nphy_iq_comp_t;
-
-typedef struct _nphy_txpwrindex {
-	s8 index;
-	s8 index_internal;
-	s8 index_internal_save;
-	u16 AfectrlOverride;
-	u16 AfeCtrlDacGain;
-	u16 rad_gain;
-	u8 bbmult;
-	u16 iqcomp_a;
-	u16 iqcomp_b;
-	u16 locomp;
-} phy_txpwrindex_t;
-
-typedef struct {
-
-	u16 txcal_coeffs_2G[8];
-	u16 txcal_radio_regs_2G[8];
-	nphy_iq_comp_t rxcal_coeffs_2G;
-
-	u16 txcal_coeffs_5G[8];
-	u16 txcal_radio_regs_5G[8];
-	nphy_iq_comp_t rxcal_coeffs_5G;
-} txiqcal_cache_t;
-
-typedef struct _nphy_pwrctrl {
-	s8 max_pwr_2g;
-	s8 idle_targ_2g;
-	s16 pwrdet_2g_a1;
-	s16 pwrdet_2g_b0;
-	s16 pwrdet_2g_b1;
-	s8 max_pwr_5gm;
-	s8 idle_targ_5gm;
-	s8 max_pwr_5gh;
-	s8 max_pwr_5gl;
-	s16 pwrdet_5gm_a1;
-	s16 pwrdet_5gm_b0;
-	s16 pwrdet_5gm_b1;
-	s16 pwrdet_5gl_a1;
-	s16 pwrdet_5gl_b0;
-	s16 pwrdet_5gl_b1;
-	s16 pwrdet_5gh_a1;
-	s16 pwrdet_5gh_b0;
-	s16 pwrdet_5gh_b1;
-	s8 idle_targ_5gl;
-	s8 idle_targ_5gh;
-	s8 idle_tssi_2g;
-	s8 idle_tssi_5g;
-	s8 idle_tssi;
-	s16 a1;
-	s16 b0;
-	s16 b1;
-} phy_pwrctrl_t;
-
-typedef struct _nphy_txgains {
-	u16 txlpf[2];
-	u16 txgm[2];
-	u16 pga[2];
-	u16 pad[2];
-	u16 ipa[2];
-} nphy_txgains_t;
-
-#define PHY_NOISEVAR_BUFSIZE 10
-
-typedef struct _nphy_noisevar_buf {
-	int bufcount;
-	int tone_id[PHY_NOISEVAR_BUFSIZE];
-	u32 noise_vars[PHY_NOISEVAR_BUFSIZE];
-	u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE];
-} phy_noisevar_buf_t;
-
-typedef struct {
-	u16 rssical_radio_regs_2G[2];
-	u16 rssical_phyregs_2G[12];
-
-	u16 rssical_radio_regs_5G[2];
-	u16 rssical_phyregs_5G[12];
-} rssical_cache_t;
-
-typedef struct {
-
-	u16 txiqlocal_a;
-	u16 txiqlocal_b;
-	u16 txiqlocal_didq;
-	u8 txiqlocal_ei0;
-	u8 txiqlocal_eq0;
-	u8 txiqlocal_fi0;
-	u8 txiqlocal_fq0;
-
-	u16 txiqlocal_bestcoeffs[11];
-	u16 txiqlocal_bestcoeffs_valid;
-
-	u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY];
-	u16 analog_gain_ref;
-	u16 lut_begin;
-	u16 lut_end;
-	u16 lut_step;
-	u16 rxcompdbm;
-	u16 papdctrl;
-	u16 sslpnCalibClkEnCtrl;
-
-	u16 rxiqcal_coeff_a0;
-	u16 rxiqcal_coeff_b0;
-} lcnphy_cal_results_t;
-
-struct shared_phy {
-	struct phy_info *phy_head;
-	uint unit;
-	struct osl_info *osh;
-	si_t *sih;
-	void *physhim;
-	uint corerev;
-	u32 machwcap;
-	bool up;
-	bool clk;
-	uint now;
-	u16 vid;
-	u16 did;
-	uint chip;
-	uint chiprev;
-	uint chippkg;
-	uint sromrev;
-	uint boardtype;
-	uint boardrev;
-	uint boardvendor;
-	u32 boardflags;
-	u32 boardflags2;
-	uint bustype;
-	uint buscorerev;
-	uint fast_timer;
-	uint slow_timer;
-	uint glacial_timer;
-	u8 rx_antdiv;
-	s8 phy_noise_window[MA_WINDOW_SZ];
-	uint phy_noise_index;
-	u8 hw_phytxchain;
-	u8 hw_phyrxchain;
-	u8 phytxchain;
-	u8 phyrxchain;
-	u8 rssi_mode;
-	bool _rifs_phy;
-};
-
-struct phy_pub {
-	uint phy_type;
-	uint phy_rev;
-	u8 phy_corenum;
-	u16 radioid;
-	u8 radiorev;
-	u8 radiover;
-
-	uint coreflags;
-	uint ana_rev;
-	bool abgphy_encore;
-};
-
-struct phy_info_nphy;
-typedef struct phy_info_nphy phy_info_nphy_t;
-
-struct phy_info_lcnphy;
-typedef struct phy_info_lcnphy phy_info_lcnphy_t;
-
-struct phy_func_ptr {
-	initfn_t init;
-	initfn_t calinit;
-	chansetfn_t chanset;
-	initfn_t txpwrrecalc;
-	longtrnfn_t longtrn;
-	txiqccgetfn_t txiqccget;
-	txiqccsetfn_t txiqccset;
-	txloccgetfn_t txloccget;
-	radioloftgetfn_t radioloftget;
-	initfn_t carrsuppr;
-	rxsigpwrfn_t rxsigpwr;
-	detachfn_t detach;
-};
-typedef struct phy_func_ptr phy_func_ptr_t;
-
-struct phy_info {
-	wlc_phy_t pubpi_ro;
-	shared_phy_t *sh;
-	phy_func_ptr_t pi_fptr;
-	void *pi_ptr;
-
-	union {
-		phy_info_lcnphy_t *pi_lcnphy;
-	} u;
-	bool user_txpwr_at_rfport;
-
-	d11regs_t *regs;
-	struct phy_info *next;
-	char *vars;
-	wlc_phy_t pubpi;
-
-	bool do_initcal;
-	bool phytest_on;
-	bool ofdm_rateset_war;
-	bool bf_preempt_4306;
-	chanspec_t radio_chanspec;
-	u8 antsel_type;
-	u16 bw;
-	u8 txpwr_percent;
-	bool phy_init_por;
-
-	bool init_in_progress;
-	bool initialized;
-	bool sbtml_gm;
-	uint refcnt;
-	bool watchdog_override;
-	u8 phynoise_state;
-	uint phynoise_now;
-	int phynoise_chan_watchdog;
-	bool phynoise_polling;
-	bool disable_percal;
-	mbool measure_hold;
-
-	s16 txpa_2g[PWRTBL_NUM_COEFF];
-	s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
-	s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF];
-	s16 txpa_5g_low[PWRTBL_NUM_COEFF];
-	s16 txpa_5g_mid[PWRTBL_NUM_COEFF];
-	s16 txpa_5g_hi[PWRTBL_NUM_COEFF];
-
-	u8 tx_srom_max_2g;
-	u8 tx_srom_max_5g_low;
-	u8 tx_srom_max_5g_mid;
-	u8 tx_srom_max_5g_hi;
-	u8 tx_srom_max_rate_2g[TXP_NUM_RATES];
-	u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES];
-	u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES];
-	u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES];
-	u8 tx_user_target[TXP_NUM_RATES];
-	s8 tx_power_offset[TXP_NUM_RATES];
-	u8 tx_power_target[TXP_NUM_RATES];
-
-	srom_fem_t srom_fem2g;
-	srom_fem_t srom_fem5g;
-
-	u8 tx_power_max;
-	u8 tx_power_max_rate_ind;
-	bool hwpwrctrl;
-	u8 nphy_txpwrctrl;
-	s8 nphy_txrx_chain;
-	bool phy_5g_pwrgain;
-
-	u16 phy_wreg;
-	u16 phy_wreg_limit;
-
-	s8 n_preamble_override;
-	u8 antswitch;
-	u8 aa2g, aa5g;
-
-	s8 idle_tssi[CH_5G_GROUP];
-	s8 target_idle_tssi;
-	s8 txpwr_est_Pout;
-	u8 tx_power_min;
-	u8 txpwr_limit[TXP_NUM_RATES];
-	u8 txpwr_env_limit[TXP_NUM_RATES];
-	u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN];
-
-	bool channel_14_wide_filter;
-
-	bool txpwroverride;
-	bool txpwridx_override_aphy;
-	s16 radiopwr_override;
-	u16 hwpwr_txcur;
-	u8 saved_txpwr_idx;
-
-	bool edcrs_threshold_lock;
-
-	u32 tr_R_gain_val;
-	u32 tr_T_gain_val;
-
-	s16 ofdm_analog_filt_bw_override;
-	s16 cck_analog_filt_bw_override;
-	s16 ofdm_rccal_override;
-	s16 cck_rccal_override;
-	u16 extlna_type;
-
-	uint interference_mode_crs_time;
-	u16 crsglitch_prev;
-	bool interference_mode_crs;
-
-	u32 phy_tx_tone_freq;
-	uint phy_lastcal;
-	bool phy_forcecal;
-	bool phy_fixed_noise;
-	u32 xtalfreq;
-	u8 pdiv;
-	s8 carrier_suppr_disable;
-
-	bool phy_bphy_evm;
-	bool phy_bphy_rfcs;
-	s8 phy_scraminit;
-	u8 phy_gpiosel;
-
-	s16 phy_txcore_disable_temp;
-	s16 phy_txcore_enable_temp;
-	s8 phy_tempsense_offset;
-	bool phy_txcore_heatedup;
-
-	u16 radiopwr;
-	u16 bb_atten;
-	u16 txctl1;
-
-	u16 mintxbias;
-	u16 mintxmag;
-	lo_complex_abgphy_info_t gphy_locomp_iq[STATIC_NUM_RF][STATIC_NUM_BB];
-	s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
-	u16 gain_table[TX_GAIN_TABLE_LENGTH];
-	bool loopback_gain;
-	s16 max_lpback_gain_hdB;
-	s16 trsw_rx_gain_hdB;
-	u8 power_vec[8];
-
-	u16 rc_cal;
-	int nrssi_table_delta;
-	int nrssi_slope_scale;
-	int nrssi_slope_offset;
-	int min_rssi;
-	int max_rssi;
-
-	s8 txpwridx;
-	u8 min_txpower;
-
-	u8 a_band_high_disable;
-
-	u16 tx_vos;
-	u16 global_tx_bb_dc_bias_loft;
-
-	int rf_max;
-	int bb_max;
-	int rf_list_size;
-	int bb_list_size;
-	u16 *rf_attn_list;
-	u16 *bb_attn_list;
-	u16 padmix_mask;
-	u16 padmix_reg;
-	u16 *txmag_list;
-	uint txmag_len;
-	bool txmag_enable;
-
-	s8 *a_tssi_to_dbm;
-	s8 *m_tssi_to_dbm;
-	s8 *l_tssi_to_dbm;
-	s8 *h_tssi_to_dbm;
-	u8 *hwtxpwr;
-
-	u16 freqtrack_saved_regs[2];
-	int cur_interference_mode;
-	bool hwpwrctrl_capable;
-	bool temppwrctrl_capable;
-
-	uint phycal_nslope;
-	uint phycal_noffset;
-	uint phycal_mlo;
-	uint phycal_txpower;
-
-	u8 phy_aa2g;
-
-	bool nphy_tableloaded;
-	s8 nphy_rssisel;
-	u32 nphy_bb_mult_save;
-	u16 nphy_txiqlocal_bestc[11];
-	bool nphy_txiqlocal_coeffsvalid;
-	phy_txpwrindex_t nphy_txpwrindex[PHY_CORE_NUM_2];
-	phy_pwrctrl_t nphy_pwrctrl_info[PHY_CORE_NUM_2];
-	u16 cck2gpo;
-	u32 ofdm2gpo;
-	u32 ofdm5gpo;
-	u32 ofdm5glpo;
-	u32 ofdm5ghpo;
-	u8 bw402gpo;
-	u8 bw405gpo;
-	u8 bw405glpo;
-	u8 bw405ghpo;
-	u8 cdd2gpo;
-	u8 cdd5gpo;
-	u8 cdd5glpo;
-	u8 cdd5ghpo;
-	u8 stbc2gpo;
-	u8 stbc5gpo;
-	u8 stbc5glpo;
-	u8 stbc5ghpo;
-	u8 bwdup2gpo;
-	u8 bwdup5gpo;
-	u8 bwdup5glpo;
-	u8 bwdup5ghpo;
-	u16 mcs2gpo[8];
-	u16 mcs5gpo[8];
-	u16 mcs5glpo[8];
-	u16 mcs5ghpo[8];
-	u32 nphy_rxcalparams;
-
-	u8 phy_spuravoid;
-	bool phy_isspuravoid;
-
-	u8 phy_pabias;
-	u8 nphy_papd_skip;
-	u8 nphy_tssi_slope;
-
-	s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
-	u8 nphy_noise_index;
-
-	u8 nphy_txpid2g[PHY_CORE_NUM_2];
-	u8 nphy_txpid5g[PHY_CORE_NUM_2];
-	u8 nphy_txpid5gl[PHY_CORE_NUM_2];
-	u8 nphy_txpid5gh[PHY_CORE_NUM_2];
-
-	bool nphy_gain_boost;
-	bool nphy_elna_gain_config;
-	u16 old_bphy_test;
-	u16 old_bphy_testcontrol;
-
-	bool phyhang_avoid;
-
-	bool rssical_nphy;
-	u8 nphy_perical;
-	uint nphy_perical_last;
-	u8 cal_type_override;
-	u8 mphase_cal_phase_id;
-	u8 mphase_txcal_cmdidx;
-	u8 mphase_txcal_numcmds;
-	u16 mphase_txcal_bestcoeffs[11];
-	chanspec_t nphy_txiqlocal_chanspec;
-	chanspec_t nphy_iqcal_chanspec_2G;
-	chanspec_t nphy_iqcal_chanspec_5G;
-	chanspec_t nphy_rssical_chanspec_2G;
-	chanspec_t nphy_rssical_chanspec_5G;
-	struct wlapi_timer *phycal_timer;
-	bool use_int_tx_iqlo_cal_nphy;
-	bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
-	s16 nphy_lastcal_temp;
-
-	txiqcal_cache_t calibration_cache;
-	rssical_cache_t rssical_cache;
-
-	u8 nphy_txpwr_idx[2];
-	u8 nphy_papd_cal_type;
-	uint nphy_papd_last_cal;
-	u16 nphy_papd_tx_gain_at_last_cal[2];
-	u8 nphy_papd_cal_gain_index[2];
-	s16 nphy_papd_epsilon_offset[2];
-	bool nphy_papd_recal_enable;
-	u32 nphy_papd_recal_counter;
-	bool nphy_force_papd_cal;
-	bool nphy_papdcomp;
-	bool ipa2g_on;
-	bool ipa5g_on;
-
-	u16 classifier_state;
-	u16 clip_state[2];
-	uint nphy_deaf_count;
-	u8 rxiq_samps;
-	u8 rxiq_antsel;
-
-	u16 rfctrlIntc1_save;
-	u16 rfctrlIntc2_save;
-	bool first_cal_after_assoc;
-	u16 tx_rx_cal_radio_saveregs[22];
-	u16 tx_rx_cal_phy_saveregs[15];
-
-	u8 nphy_cal_orig_pwr_idx[2];
-	u8 nphy_txcal_pwr_idx[2];
-	u8 nphy_rxcal_pwr_idx[2];
-	u16 nphy_cal_orig_tx_gain[2];
-	nphy_txgains_t nphy_cal_target_gain;
-	u16 nphy_txcal_bbmult;
-	u16 nphy_gmval;
-
-	u16 nphy_saved_bbconf;
-
-	bool nphy_gband_spurwar_en;
-	bool nphy_gband_spurwar2_en;
-	bool nphy_aband_spurwar_en;
-	u16 nphy_rccal_value;
-	u16 nphy_crsminpwr[3];
-	phy_noisevar_buf_t nphy_saved_noisevars;
-	bool nphy_anarxlpf_adjusted;
-	bool nphy_crsminpwr_adjusted;
-	bool nphy_noisevars_adjusted;
-
-	bool nphy_rxcal_active;
-	u16 radar_percal_mask;
-	bool dfs_lp_buffer_nphy;
-
-	u16 nphy_fineclockgatecontrol;
-
-	s8 rx2tx_biasentry;
-
-	u16 crsminpwr0;
-	u16 crsminpwrl0;
-	u16 crsminpwru0;
-	s16 noise_crsminpwr_index;
-	u16 init_gain_core1;
-	u16 init_gain_core2;
-	u16 init_gainb_core1;
-	u16 init_gainb_core2;
-	u8 aci_noise_curr_channel;
-	u16 init_gain_rfseq[4];
-
-	bool radio_is_on;
-
-	bool nphy_sample_play_lpf_bw_ctl_ovr;
-
-	u16 tbl_data_hi;
-	u16 tbl_data_lo;
-	u16 tbl_addr;
-
-	uint tbl_save_id;
-	uint tbl_save_offset;
-
-	u8 txpwrctrl;
-	s8 txpwrindex[PHY_CORE_MAX];
-
-	u8 phycal_tempdelta;
-	u32 mcs20_po;
-	u32 mcs40_po;
-};
-
-typedef s32 fixed;
-
-typedef struct _cs32 {
-	fixed q;
-	fixed i;
-} cs32;
-
-typedef struct radio_regs {
-	u16 address;
-	u32 init_a;
-	u32 init_g;
-	u8 do_init_a;
-	u8 do_init_g;
-} radio_regs_t;
-
-typedef struct radio_20xx_regs {
-	u16 address;
-	u8 init;
-	u8 do_init;
-} radio_20xx_regs_t;
-
-typedef struct lcnphy_radio_regs {
-	u16 address;
-	u8 init_a;
-	u8 init_g;
-	u8 do_init_a;
-	u8 do_init_g;
-} lcnphy_radio_regs_t;
-
-extern lcnphy_radio_regs_t lcnphy_radio_regs_2064[];
-extern lcnphy_radio_regs_t lcnphy_radio_regs_2066[];
-extern radio_regs_t regs_2055[], regs_SYN_2056[], regs_TX_2056[],
-    regs_RX_2056[];
-extern radio_regs_t regs_SYN_2056_A1[], regs_TX_2056_A1[], regs_RX_2056_A1[];
-extern radio_regs_t regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
-    regs_RX_2056_rev5[];
-extern radio_regs_t regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
-    regs_RX_2056_rev6[];
-extern radio_regs_t regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
-    regs_RX_2056_rev7[];
-extern radio_regs_t regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
-    regs_RX_2056_rev8[];
-extern radio_20xx_regs_t regs_2057_rev4[], regs_2057_rev5[], regs_2057_rev5v1[];
-extern radio_20xx_regs_t regs_2057_rev7[], regs_2057_rev8[];
-
-extern char *phy_getvar(phy_info_t *pi, const char *name);
-extern int phy_getintvar(phy_info_t *pi, const char *name);
-#define PHY_GETVAR(pi, name)	phy_getvar(pi, name)
-#define PHY_GETINTVAR(pi, name)	phy_getintvar(pi, name)
-
-extern u16 read_phy_reg(phy_info_t *pi, u16 addr);
-extern void write_phy_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void and_phy_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void or_phy_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val);
-
-extern u16 read_radio_reg(phy_info_t *pi, u16 addr);
-extern void or_radio_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void and_radio_reg(phy_info_t *pi, u16 addr, u16 val);
-extern void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask,
-			  u16 val);
-extern void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask);
-
-extern void write_radio_reg(phy_info_t *pi, u16 addr, u16 val);
-
-extern void wlc_phyreg_enter(wlc_phy_t *pih);
-extern void wlc_phyreg_exit(wlc_phy_t *pih);
-extern void wlc_radioreg_enter(wlc_phy_t *pih);
-extern void wlc_radioreg_exit(wlc_phy_t *pih);
-
-extern void wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
-			       u16 tblAddr, u16 tblDataHi,
-			       u16 tblDatalo);
-extern void wlc_phy_write_table(phy_info_t *pi,
-				const phytbl_info_t *ptbl_info, u16 tblAddr,
-				u16 tblDataHi, u16 tblDatalo);
-extern void wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
-			       u16 tblAddr, u16 tblDataHi,
-			       u16 tblDataLo);
-extern void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val);
-
-extern void write_phy_channel_reg(phy_info_t *pi, uint val);
-extern void wlc_phy_txpower_update_shm(phy_info_t *pi);
-
-extern void wlc_phy_cordic(fixed theta, cs32 *val);
-extern u8 wlc_phy_nbits(s32 value);
-extern u32 wlc_phy_sqrt_int(u32 value);
-extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
-
-extern uint wlc_phy_init_radio_regs_allbands(phy_info_t *pi,
-					     radio_20xx_regs_t *radioregs);
-extern uint wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
-				    u16 core_offset);
-
-extern void wlc_phy_txpower_ipa_upd(phy_info_t *pi);
-
-extern void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on);
-extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real,
-					s32 *eps_imag);
-
-extern void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi);
-extern void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi);
-
-extern bool wlc_phy_attach_nphy(phy_info_t *pi);
-extern bool wlc_phy_attach_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_detach_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_init_nphy(phy_info_t *pi);
-extern void wlc_phy_init_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_cal_init_nphy(phy_info_t *pi);
-extern void wlc_phy_cal_init_lcnphy(phy_info_t *pi);
-
-extern void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec);
-extern void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec);
-extern void wlc_phy_chanspec_set_fixup_lcnphy(phy_info_t *pi,
-					      chanspec_t chanspec);
-extern int wlc_phy_channel2freq(uint channel);
-extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
-extern int wlc_phy_chanspec_bandrange_get(phy_info_t *, chanspec_t);
-
-extern void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode);
-extern s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi);
-
-extern void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi);
-extern void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi);
-extern void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi);
-
-extern void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index);
-extern void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable);
-extern void wlc_lcnphy_stop_tx_tone(phy_info_t *pi);
-extern void wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz,
-				     u16 max_val, bool iqcalmode);
-
-extern void wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan,
-					       u8 *max_pwr, u8 rate_id);
-extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
-					    u8 rate_mcs_end,
-					    u8 rate_ofdm_start);
-extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power,
-					    u8 rate_ofdm_start,
-					    u8 rate_ofdm_end,
-					    u8 rate_mcs_start);
-
-extern u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode);
-extern s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode);
-extern s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode);
-extern s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode);
-extern void wlc_phy_carrier_suppress_lcnphy(phy_info_t *pi);
-extern void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel);
-extern void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode);
-extern void wlc_2064_vco_cal(phy_info_t *pi);
-
-extern void wlc_phy_txpower_recalc_target(phy_info_t *pi);
-extern u32 wlc_phy_qdiv_roundup(u32 dividend, u32 divisor,
-				   u8 precision);
-
-#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL	0x18
-#define LCNPHY_TX_POWER_TABLE_SIZE	128
-#define LCNPHY_MAX_TX_POWER_INDEX	(LCNPHY_TX_POWER_TABLE_SIZE - 1)
-#define LCNPHY_TBL_ID_TXPWRCTL 	0x07
-#define LCNPHY_TX_PWR_CTRL_OFF	0
-#define LCNPHY_TX_PWR_CTRL_SW		(0x1 << 15)
-#define LCNPHY_TX_PWR_CTRL_HW         ((0x1 << 15) | \
-					(0x1 << 14) | \
-					(0x1 << 13))
-
-#define LCNPHY_TX_PWR_CTRL_TEMPBASED	0xE001
-
-extern void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti);
-extern void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti);
-extern void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b);
-extern void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq);
-extern void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b);
-extern u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi);
-extern void wlc_lcnphy_get_radio_loft(phy_info_t *pi, u8 *ei0,
-				      u8 *eq0, u8 *fi0, u8 *fq0);
-extern void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode);
-extern void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode);
-extern bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi);
-extern void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi);
-extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
-extern void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr,
-				s8 *cck_pwr);
-extern void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi);
-
-extern s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index);
-
-#define NPHY_MAX_HPVGA1_INDEX		10
-#define NPHY_DEF_HPVGA1_INDEXLIMIT	7
-
-typedef struct _phy_iq_est {
-	s32 iq_prod;
-	u32 i_pwr;
-	u32 q_pwr;
-} phy_iq_est_t;
-
-extern void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable);
-extern void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode);
-
-#define wlc_phy_write_table_nphy(pi, pti)	wlc_phy_write_table(pi, pti, 0x72, \
-	0x74, 0x73)
-#define wlc_phy_read_table_nphy(pi, pti)	wlc_phy_read_table(pi, pti, 0x72, \
-	0x74, 0x73)
-#define wlc_nphy_table_addr(pi, id, off)	wlc_phy_table_addr((pi), (id), (off), \
-	0x72, 0x74, 0x73)
-#define wlc_nphy_table_data_write(pi, w, v)	wlc_phy_table_data_write((pi), (w), (v))
-
-extern void wlc_phy_table_read_nphy(phy_info_t *pi, u32, u32 l, u32 o,
-				    u32 w, void *d);
-extern void wlc_phy_table_write_nphy(phy_info_t *pi, u32, u32, u32,
-				     u32, const void *);
-
-#define	PHY_IPA(pi) \
-	((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
-	 (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
-
-#define WLC_PHY_WAR_PR51571(pi) \
-	if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
-		(void)R_REG((pi)->sh->osh, &(pi)->regs->maccontrol)
-
-extern void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype);
-extern void wlc_phy_aci_reset_nphy(phy_info_t *pi);
-extern void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en);
-
-extern u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint chan);
-extern void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on);
-
-extern void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi);
-
-extern void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd);
-extern s16 wlc_phy_tempsense_nphy(phy_info_t *pi);
-
-extern u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val);
-
-extern void wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est,
-				   u16 num_samps, u8 wait_time,
-				   u8 wait_for_crs);
-
-extern void wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write,
-				      nphy_iq_comp_t *comp);
-extern void wlc_phy_aci_and_noise_reduction_nphy(phy_info_t *pi);
-
-extern void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask);
-extern u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih);
-
-extern void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type);
-extern void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi);
-extern void wlc_phy_txpwr_apply_nphy(phy_info_t *pi);
-extern void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi);
-extern u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi);
-
-extern nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi);
-extern int wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-				   bool full, bool m);
-extern int wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-				 u8 type, bool d);
-extern void wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask,
-				     s8 txpwrindex, bool res);
-extern void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core, u8 rssi_type);
-extern int wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type,
-				  s32 *rssi_buf, u8 nsamps);
-extern void wlc_phy_rssi_cal_nphy(phy_info_t *pi);
-extern int wlc_phy_aci_scan_nphy(phy_info_t *pi);
-extern void wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower,
-					bool debug);
-extern int wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
-				u8 mode, u8, bool);
-extern void wlc_phy_stopplayback_nphy(phy_info_t *pi);
-extern void wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf,
-				     u8 num_samps);
-extern void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi);
-
-extern int wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh);
-
-#define NPHY_TESTPATTERN_BPHY_EVM   0
-#define NPHY_TESTPATTERN_BPHY_RFCS  1
-
-extern void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs);
-
-void wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset,
-				s8 *ofdmoffset);
-extern s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi,
-				    chanspec_t chanspec);
-
-extern bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pih);
-#endif				/* _wlc_phy_int_h_ */
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_lcn.c b/drivers/staging/brcm80211/phy/wlc_phy_lcn.c
deleted file mode 100644
index 3ac2b49..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_lcn.c
+++ /dev/null
@@ -1,5325 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <wlc_cfg.h>
-#include <qmath.h>
-#include <osl.h>
-#include <linux/pci.h>
-#include <siutils.h>
-#include <hndpmu.h>
-
-#include <bcmdevs.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-
-#include <wlc_phy_radio.h>
-#include <wlc_phy_int.h>
-#include <wlc_phy_lcn.h>
-#include <wlc_phytbl_lcn.h>
-
-#define PLL_2064_NDIV		90
-#define PLL_2064_LOW_END_VCO 	3000
-#define PLL_2064_LOW_END_KVCO 	27
-#define PLL_2064_HIGH_END_VCO	4200
-#define PLL_2064_HIGH_END_KVCO	68
-#define PLL_2064_LOOP_BW_DOUBLER	200
-#define PLL_2064_D30_DOUBLER		10500
-#define PLL_2064_LOOP_BW	260
-#define PLL_2064_D30		8000
-#define PLL_2064_CAL_REF_TO	8
-#define PLL_2064_MHZ		1000000
-#define PLL_2064_OPEN_LOOP_DELAY	5
-
-#define TEMPSENSE 			1
-#define VBATSENSE           2
-
-#define NOISE_IF_UPD_CHK_INTERVAL	1
-#define NOISE_IF_UPD_RST_INTERVAL	60
-#define NOISE_IF_UPD_THRESHOLD_CNT	1
-#define NOISE_IF_UPD_TRHRESHOLD	50
-#define NOISE_IF_UPD_TIMEOUT		1000
-#define NOISE_IF_OFF			0
-#define NOISE_IF_CHK			1
-#define NOISE_IF_ON			2
-
-#define PAPD_BLANKING_PROFILE 		3
-#define PAPD2LUT			0
-#define PAPD_CORR_NORM 			0
-#define PAPD_BLANKING_THRESHOLD 	0
-#define PAPD_STOP_AFTER_LAST_UPDATE	0
-
-#define LCN_TARGET_PWR  60
-
-#define LCN_VBAT_OFFSET_433X 34649679
-#define LCN_VBAT_SLOPE_433X  8258032
-
-#define LCN_VBAT_SCALE_NOM  53
-#define LCN_VBAT_SCALE_DEN  432
-
-#define LCN_TEMPSENSE_OFFSET  80812
-#define LCN_TEMPSENSE_DEN  2647
-
-#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
-	(0 + 8)
-#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
-	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
-
-#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
-	(0 + 8)
-#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
-	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
-
-#define wlc_lcnphy_enable_tx_gain_override(pi) \
-	wlc_lcnphy_set_tx_gain_override(pi, true)
-#define wlc_lcnphy_disable_tx_gain_override(pi) \
-	wlc_lcnphy_set_tx_gain_override(pi, false)
-
-#define wlc_lcnphy_iqcal_active(pi)	\
-	(read_phy_reg((pi), 0x451) & \
-	((0x1 << 15) | (0x1 << 14)))
-
-#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
-#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
-	(pi->temppwrctrl_capable)
-#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
-	(pi->hwpwrctrl_capable)
-
-#define SWCTRL_BT_TX		0x18
-#define SWCTRL_OVR_DISABLE	0x40
-
-#define	AFE_CLK_INIT_MODE_TXRX2X	1
-#define	AFE_CLK_INIT_MODE_PAPD		0
-
-#define LCNPHY_TBL_ID_IQLOCAL			0x00
-
-#define LCNPHY_TBL_ID_RFSEQ         0x08
-#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
-#define LCNPHY_TBL_ID_SW_CTRL			0x0f
-#define LCNPHY_TBL_ID_GAIN_TBL		0x12
-#define LCNPHY_TBL_ID_SPUR			0x14
-#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
-#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
-
-#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 	832
-#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 	128
-#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 	192
-#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
-#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
-#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
-
-#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
-
-#define LCNPHY_TX_PWR_CTRL_START_NPT		1
-#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
-
-#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
-
-#define LCNPHY_ACI_DETECT_START      1
-#define LCNPHY_ACI_DETECT_PROGRESS   2
-#define LCNPHY_ACI_DETECT_STOP       3
-
-#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
-#define LCNPHY_ACI_GLITCH_TRSH 2000
-#define	LCNPHY_ACI_TMOUT 250
-#define LCNPHY_ACI_DETECT_TIMEOUT  2
-#define LCNPHY_ACI_START_DELAY 0
-
-#define wlc_lcnphy_tx_gain_override_enabled(pi) \
-	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
-
-#define wlc_lcnphy_total_tx_frames(pi) \
-	wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + offsetof(macstat_t, txallfrm))
-
-typedef struct {
-	u16 gm_gain;
-	u16 pga_gain;
-	u16 pad_gain;
-	u16 dac_gain;
-} lcnphy_txgains_t;
-
-typedef enum {
-	LCNPHY_CAL_FULL,
-	LCNPHY_CAL_RECAL,
-	LCNPHY_CAL_CURRECAL,
-	LCNPHY_CAL_DIGCAL,
-	LCNPHY_CAL_GCTRL
-} lcnphy_cal_mode_t;
-
-typedef struct {
-	lcnphy_txgains_t gains;
-	bool useindex;
-	u8 index;
-} lcnphy_txcalgains_t;
-
-typedef struct {
-	u8 chan;
-	s16 a;
-	s16 b;
-} lcnphy_rx_iqcomp_t;
-
-typedef struct {
-	s16 re;
-	s16 im;
-} lcnphy_spb_tone_t;
-
-typedef struct {
-	u16 re;
-	u16 im;
-} lcnphy_unsign16_struct;
-
-typedef struct {
-	u32 iq_prod;
-	u32 i_pwr;
-	u32 q_pwr;
-} lcnphy_iq_est_t;
-
-typedef struct {
-	u16 ptcentreTs20;
-	u16 ptcentreFactor;
-} lcnphy_sfo_cfg_t;
-
-typedef enum {
-	LCNPHY_PAPD_CAL_CW,
-	LCNPHY_PAPD_CAL_OFDM
-} lcnphy_papd_cal_type_t;
-
-typedef u16 iqcal_gain_params_lcnphy[9];
-
-static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
-	{0, 0, 0, 0, 0, 0, 0, 0, 0},
-};
-
-static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
-	tbl_iqcal_gainparams_lcnphy_2G,
-};
-
-static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
-	sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
-	    sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
-};
-
-static const lcnphy_sfo_cfg_t lcnphy_sfo_cfg[] = {
-	{965, 1087},
-	{967, 1085},
-	{969, 1082},
-	{971, 1080},
-	{973, 1078},
-	{975, 1076},
-	{977, 1073},
-	{979, 1071},
-	{981, 1069},
-	{983, 1067},
-	{985, 1065},
-	{987, 1063},
-	{989, 1060},
-	{994, 1055}
-};
-
-static const
-u16 lcnphy_iqcal_loft_gainladder[] = {
-	((2 << 8) | 0),
-	((3 << 8) | 0),
-	((4 << 8) | 0),
-	((6 << 8) | 0),
-	((8 << 8) | 0),
-	((11 << 8) | 0),
-	((16 << 8) | 0),
-	((16 << 8) | 1),
-	((16 << 8) | 2),
-	((16 << 8) | 3),
-	((16 << 8) | 4),
-	((16 << 8) | 5),
-	((16 << 8) | 6),
-	((16 << 8) | 7),
-	((23 << 8) | 7),
-	((32 << 8) | 7),
-	((45 << 8) | 7),
-	((64 << 8) | 7),
-	((91 << 8) | 7),
-	((128 << 8) | 7)
-};
-
-static const
-u16 lcnphy_iqcal_ir_gainladder[] = {
-	((1 << 8) | 0),
-	((2 << 8) | 0),
-	((4 << 8) | 0),
-	((6 << 8) | 0),
-	((8 << 8) | 0),
-	((11 << 8) | 0),
-	((16 << 8) | 0),
-	((23 << 8) | 0),
-	((32 << 8) | 0),
-	((45 << 8) | 0),
-	((64 << 8) | 0),
-	((64 << 8) | 1),
-	((64 << 8) | 2),
-	((64 << 8) | 3),
-	((64 << 8) | 4),
-	((64 << 8) | 5),
-	((64 << 8) | 6),
-	((64 << 8) | 7),
-	((91 << 8) | 7),
-	((128 << 8) | 7)
-};
-
-static const
-lcnphy_spb_tone_t lcnphy_spb_tone_3750[] = {
-	{88, 0},
-	{73, 49},
-	{34, 81},
-	{-17, 86},
-	{-62, 62},
-	{-86, 17},
-	{-81, -34},
-	{-49, -73},
-	{0, -88},
-	{49, -73},
-	{81, -34},
-	{86, 17},
-	{62, 62},
-	{17, 86},
-	{-34, 81},
-	{-73, 49},
-	{-88, 0},
-	{-73, -49},
-	{-34, -81},
-	{17, -86},
-	{62, -62},
-	{86, -17},
-	{81, 34},
-	{49, 73},
-	{0, 88},
-	{-49, 73},
-	{-81, 34},
-	{-86, -17},
-	{-62, -62},
-	{-17, -86},
-	{34, -81},
-	{73, -49},
-};
-
-static const
-u16 iqlo_loopback_rf_regs[20] = {
-	RADIO_2064_REG036,
-	RADIO_2064_REG11A,
-	RADIO_2064_REG03A,
-	RADIO_2064_REG025,
-	RADIO_2064_REG028,
-	RADIO_2064_REG005,
-	RADIO_2064_REG112,
-	RADIO_2064_REG0FF,
-	RADIO_2064_REG11F,
-	RADIO_2064_REG00B,
-	RADIO_2064_REG113,
-	RADIO_2064_REG007,
-	RADIO_2064_REG0FC,
-	RADIO_2064_REG0FD,
-	RADIO_2064_REG012,
-	RADIO_2064_REG057,
-	RADIO_2064_REG059,
-	RADIO_2064_REG05C,
-	RADIO_2064_REG078,
-	RADIO_2064_REG092,
-};
-
-static const
-u16 tempsense_phy_regs[14] = {
-	0x503,
-	0x4a4,
-	0x4d0,
-	0x4d9,
-	0x4da,
-	0x4a6,
-	0x938,
-	0x939,
-	0x4d8,
-	0x4d0,
-	0x4d7,
-	0x4a5,
-	0x40d,
-	0x4a2,
-};
-
-static const
-u16 rxiq_cal_rf_reg[11] = {
-	RADIO_2064_REG098,
-	RADIO_2064_REG116,
-	RADIO_2064_REG12C,
-	RADIO_2064_REG06A,
-	RADIO_2064_REG00B,
-	RADIO_2064_REG01B,
-	RADIO_2064_REG113,
-	RADIO_2064_REG01D,
-	RADIO_2064_REG114,
-	RADIO_2064_REG02E,
-	RADIO_2064_REG12A,
-};
-
-static const
-lcnphy_rx_iqcomp_t lcnphy_rx_iqcomp_table_rev0[] = {
-	{1, 0, 0},
-	{2, 0, 0},
-	{3, 0, 0},
-	{4, 0, 0},
-	{5, 0, 0},
-	{6, 0, 0},
-	{7, 0, 0},
-	{8, 0, 0},
-	{9, 0, 0},
-	{10, 0, 0},
-	{11, 0, 0},
-	{12, 0, 0},
-	{13, 0, 0},
-	{14, 0, 0},
-	{34, 0, 0},
-	{38, 0, 0},
-	{42, 0, 0},
-	{46, 0, 0},
-	{36, 0, 0},
-	{40, 0, 0},
-	{44, 0, 0},
-	{48, 0, 0},
-	{52, 0, 0},
-	{56, 0, 0},
-	{60, 0, 0},
-	{64, 0, 0},
-	{100, 0, 0},
-	{104, 0, 0},
-	{108, 0, 0},
-	{112, 0, 0},
-	{116, 0, 0},
-	{120, 0, 0},
-	{124, 0, 0},
-	{128, 0, 0},
-	{132, 0, 0},
-	{136, 0, 0},
-	{140, 0, 0},
-	{149, 0, 0},
-	{153, 0, 0},
-	{157, 0, 0},
-	{161, 0, 0},
-	{165, 0, 0},
-	{184, 0, 0},
-	{188, 0, 0},
-	{192, 0, 0},
-	{196, 0, 0},
-	{200, 0, 0},
-	{204, 0, 0},
-	{208, 0, 0},
-	{212, 0, 0},
-	{216, 0, 0},
-};
-
-static const u32 lcnphy_23bitgaincode_table[] = {
-	0x200100,
-	0x200200,
-	0x200004,
-	0x200014,
-	0x200024,
-	0x200034,
-	0x200134,
-	0x200234,
-	0x200334,
-	0x200434,
-	0x200037,
-	0x200137,
-	0x200237,
-	0x200337,
-	0x200437,
-	0x000035,
-	0x000135,
-	0x000235,
-	0x000037,
-	0x000137,
-	0x000237,
-	0x000337,
-	0x00013f,
-	0x00023f,
-	0x00033f,
-	0x00034f,
-	0x00044f,
-	0x00144f,
-	0x00244f,
-	0x00254f,
-	0x00354f,
-	0x00454f,
-	0x00464f,
-	0x01464f,
-	0x02464f,
-	0x03464f,
-	0x04464f,
-};
-
-static const s8 lcnphy_gain_table[] = {
-	-16,
-	-13,
-	10,
-	7,
-	4,
-	0,
-	3,
-	6,
-	9,
-	12,
-	15,
-	18,
-	21,
-	24,
-	27,
-	30,
-	33,
-	36,
-	39,
-	42,
-	45,
-	48,
-	50,
-	53,
-	56,
-	59,
-	62,
-	65,
-	68,
-	71,
-	74,
-	77,
-	80,
-	83,
-	86,
-	89,
-	92,
-};
-
-static const s8 lcnphy_gain_index_offset_for_rssi[] = {
-	7,
-	7,
-	7,
-	7,
-	7,
-	7,
-	7,
-	8,
-	7,
-	7,
-	6,
-	7,
-	7,
-	4,
-	4,
-	4,
-	4,
-	4,
-	4,
-	4,
-	4,
-	3,
-	3,
-	3,
-	3,
-	3,
-	3,
-	4,
-	2,
-	2,
-	2,
-	2,
-	2,
-	2,
-	-1,
-	-2,
-	-2,
-	-2
-};
-
-extern const u8 spur_tbl_rev0[];
-extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev1;
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[];
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
-
-typedef struct _chan_info_2064_lcnphy {
-	uint chan;
-	uint freq;
-	u8 logen_buftune;
-	u8 logen_rccr_tx;
-	u8 txrf_mix_tune_ctrl;
-	u8 pa_input_tune_g;
-	u8 logen_rccr_rx;
-	u8 pa_rxrf_lna1_freq_tune;
-	u8 pa_rxrf_lna2_freq_tune;
-	u8 rxrf_rxrf_spare1;
-} chan_info_2064_lcnphy_t;
-
-static chan_info_2064_lcnphy_t chan_info_2064_lcnphy[] = {
-	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
-};
-
-lcnphy_radio_regs_t lcnphy_radio_regs_2064[] = {
-	{0x00, 0, 0, 0, 0},
-	{0x01, 0x64, 0x64, 0, 0},
-	{0x02, 0x20, 0x20, 0, 0},
-	{0x03, 0x66, 0x66, 0, 0},
-	{0x04, 0xf8, 0xf8, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0x10, 0x10, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0x37, 0x37, 0, 0},
-	{0x0B, 0x6, 0x6, 0, 0},
-	{0x0C, 0x55, 0x55, 0, 0},
-	{0x0D, 0x8b, 0x8b, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0x5, 0x5, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0xe, 0xe, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0xb, 0xb, 0, 0},
-	{0x14, 0x2, 0x2, 0, 0},
-	{0x15, 0x12, 0x12, 0, 0},
-	{0x16, 0x12, 0x12, 0, 0},
-	{0x17, 0xc, 0xc, 0, 0},
-	{0x18, 0xc, 0xc, 0, 0},
-	{0x19, 0xc, 0xc, 0, 0},
-	{0x1A, 0x8, 0x8, 0, 0},
-	{0x1B, 0x2, 0x2, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0x1, 0x1, 0, 0},
-	{0x1E, 0x12, 0x12, 0, 0},
-	{0x1F, 0x6e, 0x6e, 0, 0},
-	{0x20, 0x2, 0x2, 0, 0},
-	{0x21, 0x23, 0x23, 0, 0},
-	{0x22, 0x8, 0x8, 0, 0},
-	{0x23, 0, 0, 0, 0},
-	{0x24, 0, 0, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0x33, 0x33, 0, 0},
-	{0x27, 0x55, 0x55, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x30, 0x30, 0, 0},
-	{0x2A, 0xb, 0xb, 0, 0},
-	{0x2B, 0x1b, 0x1b, 0, 0},
-	{0x2C, 0x3, 0x3, 0, 0},
-	{0x2D, 0x1b, 0x1b, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x20, 0x20, 0, 0},
-	{0x30, 0xa, 0xa, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0x62, 0x62, 0, 0},
-	{0x33, 0x19, 0x19, 0, 0},
-	{0x34, 0x33, 0x33, 0, 0},
-	{0x35, 0x77, 0x77, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x70, 0x70, 0, 0},
-	{0x38, 0x3, 0x3, 0, 0},
-	{0x39, 0xf, 0xf, 0, 0},
-	{0x3A, 0x6, 0x6, 0, 0},
-	{0x3B, 0xcf, 0xcf, 0, 0},
-	{0x3C, 0x1a, 0x1a, 0, 0},
-	{0x3D, 0x6, 0x6, 0, 0},
-	{0x3E, 0x42, 0x42, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0xfb, 0xfb, 0, 0},
-	{0x41, 0x9a, 0x9a, 0, 0},
-	{0x42, 0x7a, 0x7a, 0, 0},
-	{0x43, 0x29, 0x29, 0, 0},
-	{0x44, 0, 0, 0, 0},
-	{0x45, 0x8, 0x8, 0, 0},
-	{0x46, 0xce, 0xce, 0, 0},
-	{0x47, 0x27, 0x27, 0, 0},
-	{0x48, 0x62, 0x62, 0, 0},
-	{0x49, 0x6, 0x6, 0, 0},
-	{0x4A, 0x58, 0x58, 0, 0},
-	{0x4B, 0xf7, 0xf7, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0xb3, 0xb3, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0, 0, 0, 0},
-	{0x51, 0x9, 0x9, 0, 0},
-	{0x52, 0x5, 0x5, 0, 0},
-	{0x53, 0x17, 0x17, 0, 0},
-	{0x54, 0x38, 0x38, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0xb, 0xb, 0, 0},
-	{0x58, 0, 0, 0, 0},
-	{0x59, 0, 0, 0, 0},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0, 0, 0, 0},
-	{0x5C, 0, 0, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x88, 0x88, 0, 0},
-	{0x5F, 0xcc, 0xcc, 0, 0},
-	{0x60, 0x74, 0x74, 0, 0},
-	{0x61, 0x74, 0x74, 0, 0},
-	{0x62, 0x74, 0x74, 0, 0},
-	{0x63, 0x44, 0x44, 0, 0},
-	{0x64, 0x77, 0x77, 0, 0},
-	{0x65, 0x44, 0x44, 0, 0},
-	{0x66, 0x77, 0x77, 0, 0},
-	{0x67, 0x55, 0x55, 0, 0},
-	{0x68, 0x77, 0x77, 0, 0},
-	{0x69, 0x77, 0x77, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0x7f, 0x7f, 0, 0},
-	{0x6C, 0x8, 0x8, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0x88, 0x88, 0, 0},
-	{0x6F, 0x66, 0x66, 0, 0},
-	{0x70, 0x66, 0x66, 0, 0},
-	{0x71, 0x28, 0x28, 0, 0},
-	{0x72, 0x55, 0x55, 0, 0},
-	{0x73, 0x4, 0x4, 0, 0},
-	{0x74, 0, 0, 0, 0},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0, 0, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0xd6, 0xd6, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0xb4, 0xb4, 0, 0},
-	{0x84, 0x1, 0x1, 0, 0},
-	{0x85, 0x20, 0x20, 0, 0},
-	{0x86, 0x5, 0x5, 0, 0},
-	{0x87, 0xff, 0xff, 0, 0},
-	{0x88, 0x7, 0x7, 0, 0},
-	{0x89, 0x77, 0x77, 0, 0},
-	{0x8A, 0x77, 0x77, 0, 0},
-	{0x8B, 0x77, 0x77, 0, 0},
-	{0x8C, 0x77, 0x77, 0, 0},
-	{0x8D, 0x8, 0x8, 0, 0},
-	{0x8E, 0xa, 0xa, 0, 0},
-	{0x8F, 0x8, 0x8, 0, 0},
-	{0x90, 0x18, 0x18, 0, 0},
-	{0x91, 0x5, 0x5, 0, 0},
-	{0x92, 0x1f, 0x1f, 0, 0},
-	{0x93, 0x10, 0x10, 0, 0},
-	{0x94, 0x3, 0x3, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0xaa, 0xaa, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0x23, 0x23, 0, 0},
-	{0x9A, 0x7, 0x7, 0, 0},
-	{0x9B, 0xf, 0xf, 0, 0},
-	{0x9C, 0x10, 0x10, 0, 0},
-	{0x9D, 0x3, 0x3, 0, 0},
-	{0x9E, 0x4, 0x4, 0, 0},
-	{0x9F, 0x20, 0x20, 0, 0},
-	{0xA0, 0, 0, 0, 0},
-	{0xA1, 0, 0, 0, 0},
-	{0xA2, 0, 0, 0, 0},
-	{0xA3, 0, 0, 0, 0},
-	{0xA4, 0x1, 0x1, 0, 0},
-	{0xA5, 0x77, 0x77, 0, 0},
-	{0xA6, 0x77, 0x77, 0, 0},
-	{0xA7, 0x77, 0x77, 0, 0},
-	{0xA8, 0x77, 0x77, 0, 0},
-	{0xA9, 0x8c, 0x8c, 0, 0},
-	{0xAA, 0x88, 0x88, 0, 0},
-	{0xAB, 0x78, 0x78, 0, 0},
-	{0xAC, 0x57, 0x57, 0, 0},
-	{0xAD, 0x88, 0x88, 0, 0},
-	{0xAE, 0, 0, 0, 0},
-	{0xAF, 0x8, 0x8, 0, 0},
-	{0xB0, 0x88, 0x88, 0, 0},
-	{0xB1, 0, 0, 0, 0},
-	{0xB2, 0x1b, 0x1b, 0, 0},
-	{0xB3, 0x3, 0x3, 0, 0},
-	{0xB4, 0x24, 0x24, 0, 0},
-	{0xB5, 0x3, 0x3, 0, 0},
-	{0xB6, 0x1b, 0x1b, 0, 0},
-	{0xB7, 0x24, 0x24, 0, 0},
-	{0xB8, 0x3, 0x3, 0, 0},
-	{0xB9, 0, 0, 0, 0},
-	{0xBA, 0xaa, 0xaa, 0, 0},
-	{0xBB, 0, 0, 0, 0},
-	{0xBC, 0x4, 0x4, 0, 0},
-	{0xBD, 0, 0, 0, 0},
-	{0xBE, 0x8, 0x8, 0, 0},
-	{0xBF, 0x11, 0x11, 0, 0},
-	{0xC0, 0, 0, 0, 0},
-	{0xC1, 0, 0, 0, 0},
-	{0xC2, 0x62, 0x62, 0, 0},
-	{0xC3, 0x1e, 0x1e, 0, 0},
-	{0xC4, 0x33, 0x33, 0, 0},
-	{0xC5, 0x37, 0x37, 0, 0},
-	{0xC6, 0, 0, 0, 0},
-	{0xC7, 0x70, 0x70, 0, 0},
-	{0xC8, 0x1e, 0x1e, 0, 0},
-	{0xC9, 0x6, 0x6, 0, 0},
-	{0xCA, 0x4, 0x4, 0, 0},
-	{0xCB, 0x2f, 0x2f, 0, 0},
-	{0xCC, 0xf, 0xf, 0, 0},
-	{0xCD, 0, 0, 0, 0},
-	{0xCE, 0xff, 0xff, 0, 0},
-	{0xCF, 0x8, 0x8, 0, 0},
-	{0xD0, 0x3f, 0x3f, 0, 0},
-	{0xD1, 0x3f, 0x3f, 0, 0},
-	{0xD2, 0x3f, 0x3f, 0, 0},
-	{0xD3, 0, 0, 0, 0},
-	{0xD4, 0, 0, 0, 0},
-	{0xD5, 0, 0, 0, 0},
-	{0xD6, 0xcc, 0xcc, 0, 0},
-	{0xD7, 0, 0, 0, 0},
-	{0xD8, 0x8, 0x8, 0, 0},
-	{0xD9, 0x8, 0x8, 0, 0},
-	{0xDA, 0x8, 0x8, 0, 0},
-	{0xDB, 0x11, 0x11, 0, 0},
-	{0xDC, 0, 0, 0, 0},
-	{0xDD, 0x87, 0x87, 0, 0},
-	{0xDE, 0x88, 0x88, 0, 0},
-	{0xDF, 0x8, 0x8, 0, 0},
-	{0xE0, 0x8, 0x8, 0, 0},
-	{0xE1, 0x8, 0x8, 0, 0},
-	{0xE2, 0, 0, 0, 0},
-	{0xE3, 0, 0, 0, 0},
-	{0xE4, 0, 0, 0, 0},
-	{0xE5, 0xf5, 0xf5, 0, 0},
-	{0xE6, 0x30, 0x30, 0, 0},
-	{0xE7, 0x1, 0x1, 0, 0},
-	{0xE8, 0, 0, 0, 0},
-	{0xE9, 0xff, 0xff, 0, 0},
-	{0xEA, 0, 0, 0, 0},
-	{0xEB, 0, 0, 0, 0},
-	{0xEC, 0x22, 0x22, 0, 0},
-	{0xED, 0, 0, 0, 0},
-	{0xEE, 0, 0, 0, 0},
-	{0xEF, 0, 0, 0, 0},
-	{0xF0, 0x3, 0x3, 0, 0},
-	{0xF1, 0x1, 0x1, 0, 0},
-	{0xF2, 0, 0, 0, 0},
-	{0xF3, 0, 0, 0, 0},
-	{0xF4, 0, 0, 0, 0},
-	{0xF5, 0, 0, 0, 0},
-	{0xF6, 0, 0, 0, 0},
-	{0xF7, 0x6, 0x6, 0, 0},
-	{0xF8, 0, 0, 0, 0},
-	{0xF9, 0, 0, 0, 0},
-	{0xFA, 0x40, 0x40, 0, 0},
-	{0xFB, 0, 0, 0, 0},
-	{0xFC, 0x1, 0x1, 0, 0},
-	{0xFD, 0x80, 0x80, 0, 0},
-	{0xFE, 0x2, 0x2, 0, 0},
-	{0xFF, 0x10, 0x10, 0, 0},
-	{0x100, 0x2, 0x2, 0, 0},
-	{0x101, 0x1e, 0x1e, 0, 0},
-	{0x102, 0x1e, 0x1e, 0, 0},
-	{0x103, 0, 0, 0, 0},
-	{0x104, 0x1f, 0x1f, 0, 0},
-	{0x105, 0, 0x8, 0, 1},
-	{0x106, 0x2a, 0x2a, 0, 0},
-	{0x107, 0xf, 0xf, 0, 0},
-	{0x108, 0, 0, 0, 0},
-	{0x109, 0, 0, 0, 0},
-	{0x10A, 0, 0, 0, 0},
-	{0x10B, 0, 0, 0, 0},
-	{0x10C, 0, 0, 0, 0},
-	{0x10D, 0, 0, 0, 0},
-	{0x10E, 0, 0, 0, 0},
-	{0x10F, 0, 0, 0, 0},
-	{0x110, 0, 0, 0, 0},
-	{0x111, 0, 0, 0, 0},
-	{0x112, 0, 0, 0, 0},
-	{0x113, 0, 0, 0, 0},
-	{0x114, 0, 0, 0, 0},
-	{0x115, 0, 0, 0, 0},
-	{0x116, 0, 0, 0, 0},
-	{0x117, 0, 0, 0, 0},
-	{0x118, 0, 0, 0, 0},
-	{0x119, 0, 0, 0, 0},
-	{0x11A, 0, 0, 0, 0},
-	{0x11B, 0, 0, 0, 0},
-	{0x11C, 0x1, 0x1, 0, 0},
-	{0x11D, 0, 0, 0, 0},
-	{0x11E, 0, 0, 0, 0},
-	{0x11F, 0, 0, 0, 0},
-	{0x120, 0, 0, 0, 0},
-	{0x121, 0, 0, 0, 0},
-	{0x122, 0x80, 0x80, 0, 0},
-	{0x123, 0, 0, 0, 0},
-	{0x124, 0xf8, 0xf8, 0, 0},
-	{0x125, 0, 0, 0, 0},
-	{0x126, 0, 0, 0, 0},
-	{0x127, 0, 0, 0, 0},
-	{0x128, 0, 0, 0, 0},
-	{0x129, 0, 0, 0, 0},
-	{0x12A, 0, 0, 0, 0},
-	{0x12B, 0, 0, 0, 0},
-	{0x12C, 0, 0, 0, 0},
-	{0x12D, 0, 0, 0, 0},
-	{0x12E, 0, 0, 0, 0},
-	{0x12F, 0, 0, 0, 0},
-	{0x130, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-#define LCNPHY_NUM_DIG_FILT_COEFFS 16
-#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
-
-u16
-    LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
-    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
-	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
-	 128, 64,},
-	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
-	 167, 93,},
-	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
-	 128, 64,},
-	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
-	 170, 340, 170,},
-	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
-	 256, 185, 256,},
-	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
-	 256, 273, 256,},
-	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
-	 256, 352, 256,},
-	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
-	 128, 233, 128,},
-	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
-	 1881, 256,},
-	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
-	 1881, 256,},
-	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
-	 384, 288,},
-	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
-	 128, 384, 288,},
-	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
-	 170, 340, 170,},
-};
-
-#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
-u16
-    LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
-    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
-	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
-	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
-	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
-	 750, 0xFE2B, 212, 0xFFCE, 212,},
-	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
-	 0xFEF2, 128, 0xFFE2, 128}
-};
-
-#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
-	mod_phy_reg(pi, 0x4a4, \
-		(0x1ff << 0), \
-		(u16)(idx) << 0)
-
-#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
-	mod_phy_reg(pi, 0x4a5, \
-		(0x7 << 8), \
-		(u16)(npt) << 8)
-
-#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
-	(read_phy_reg((pi), 0x4a4) & \
-			((0x1 << 15) | \
-			(0x1 << 14) | \
-			(0x1 << 13)))
-
-#define wlc_lcnphy_get_tx_pwr_npt(pi) \
-	((read_phy_reg(pi, 0x4a5) & \
-		(0x7 << 8)) >> \
-		8)
-
-#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
-	(read_phy_reg(pi, 0x473) & 0x1ff)
-
-#define wlc_lcnphy_get_target_tx_pwr(pi) \
-	((read_phy_reg(pi, 0x4a7) & \
-		(0xff << 0)) >> \
-		0)
-
-#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
-	mod_phy_reg(pi, 0x4a7, \
-		(0xff << 0), \
-		(u16)(target) << 0)
-
-#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
-#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
-
-#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
-#define FIXED_TXPWR 78
-#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
-
-static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
-				      u8 precision);
-static void wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
-						   u16 ext_lna, u16 trsw,
-						   u16 biq2, u16 biq1,
-						   u16 tia, u16 lna2,
-						   u16 lna1);
-static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi);
-static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain);
-static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx);
-static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0);
-static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi);
-static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains);
-static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable);
-static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi);
-static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable);
-static void wlc_lcnphy_set_tx_gain(phy_info_t *pi,
-				   lcnphy_txgains_t *target_gains);
-static bool wlc_lcnphy_rx_iq_est(phy_info_t *pi, u16 num_samps,
-				 u8 wait_time, lcnphy_iq_est_t *iq_est);
-static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps);
-static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi);
-static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode);
-extern void wlc_lcnphy_tx_pwr_ctrl_init(wlc_phy_t *ppi);
-static void wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi,
-						    u8 channel);
-
-static void wlc_lcnphy_load_tx_gain_table(phy_info_t *pi,
-					  const lcnphy_tx_gain_tbl_entry *g);
-
-static void wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo,
-				u16 thresh, s16 *ptr, int mode);
-static int wlc_lcnphy_calc_floor(s16 coeff, int type);
-static void wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi,
-					u16 *values_to_save);
-static void wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi,
-						u16 *values_to_save);
-static void wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x,
-			      s16 coeff_y);
-static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type);
-static void wlc_lcnphy_a1(phy_info_t *pi, int cal_type,
-			  int num_levels, int step_size_lg2);
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi);
-
-static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi,
-					   chanspec_t chanspec);
-static void wlc_lcnphy_agc_temp_init(phy_info_t *pi);
-static void wlc_lcnphy_temp_adj(phy_info_t *pi);
-static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi);
-static void wlc_lcnphy_baseband_init(phy_info_t *pi);
-static void wlc_lcnphy_radio_init(phy_info_t *pi);
-static void wlc_lcnphy_rc_cal(phy_info_t *pi);
-static void wlc_lcnphy_rcal(phy_info_t *pi);
-static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable);
-static int wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm,
-					 s16 filt_type);
-static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b);
-
-void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti)
-{
-	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
-}
-
-void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti)
-{
-	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
-}
-
-static void
-wlc_lcnphy_common_read_table(phy_info_t *pi, u32 tbl_id,
-			     const void *tbl_ptr, u32 tbl_len,
-			     u32 tbl_width, u32 tbl_offset)
-{
-	phytbl_info_t tab;
-	tab.tbl_id = tbl_id;
-	tab.tbl_ptr = tbl_ptr;
-	tab.tbl_len = tbl_len;
-	tab.tbl_width = tbl_width;
-	tab.tbl_offset = tbl_offset;
-	wlc_lcnphy_read_table(pi, &tab);
-}
-
-static void
-wlc_lcnphy_common_write_table(phy_info_t *pi, u32 tbl_id,
-			      const void *tbl_ptr, u32 tbl_len,
-			      u32 tbl_width, u32 tbl_offset)
-{
-
-	phytbl_info_t tab;
-	tab.tbl_id = tbl_id;
-	tab.tbl_ptr = tbl_ptr;
-	tab.tbl_len = tbl_len;
-	tab.tbl_width = tbl_width;
-	tab.tbl_offset = tbl_offset;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-static u32
-wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
-{
-	u32 quotient, remainder, roundup, rbit;
-
-	ASSERT(divisor);
-
-	quotient = dividend / divisor;
-	remainder = dividend % divisor;
-	rbit = divisor & 1;
-	roundup = (divisor >> 1) + rbit;
-
-	while (precision--) {
-		quotient <<= 1;
-		if (remainder >= roundup) {
-			quotient++;
-			remainder = ((remainder - roundup) << 1) + rbit;
-		} else {
-			remainder <<= 1;
-		}
-	}
-
-	if (remainder >= roundup)
-		quotient++;
-
-	return quotient;
-}
-
-static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
-{
-	int k;
-	k = 0;
-	if (type == 0) {
-		if (coeff_x < 0) {
-			k = (coeff_x - 1) / 2;
-		} else {
-			k = coeff_x / 2;
-		}
-	}
-	if (type == 1) {
-		if ((coeff_x + 1) < 0)
-			k = (coeff_x) / 2;
-		else
-			k = (coeff_x + 1) / 2;
-	}
-	return k;
-}
-
-s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi)
-{
-	s8 index;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (txpwrctrl_off(pi))
-		index = pi_lcn->lcnphy_current_index;
-	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
-		index =
-		    (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
-			    / 2);
-	else
-		index = pi_lcn->lcnphy_current_index;
-	return index;
-}
-
-static u32 wlc_lcnphy_measure_digital_power(phy_info_t *pi, u16 nsamples)
-{
-	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
-
-	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
-		return 0;
-	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
-}
-
-void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel)
-{
-	u16 afectrlovr, afectrlovrval;
-	afectrlovr = read_phy_reg(pi, 0x43b);
-	afectrlovrval = read_phy_reg(pi, 0x43c);
-	if (channel != 0) {
-		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
-
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
-
-		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
-
-		write_phy_reg(pi, 0x44b, 0xffff);
-		wlc_lcnphy_tx_pu(pi, 1);
-
-		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
-
-		or_phy_reg(pi, 0x6da, 0x0080);
-
-		or_phy_reg(pi, 0x00a, 0x228);
-	} else {
-		and_phy_reg(pi, 0x00a, ~(0x228));
-
-		and_phy_reg(pi, 0x6da, 0xFF7F);
-		write_phy_reg(pi, 0x43b, afectrlovr);
-		write_phy_reg(pi, 0x43c, afectrlovrval);
-	}
-}
-
-static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi)
-{
-	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
-
-	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
-	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
-
-	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
-	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
-
-	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
-	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
-
-	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
-	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
-}
-
-static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable)
-{
-	if (enable) {
-		write_phy_reg(pi, 0x942, 0x7);
-		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
-		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
-
-		write_phy_reg(pi, 0x44a, 0x084);
-		write_phy_reg(pi, 0x44a, 0x080);
-		write_phy_reg(pi, 0x6d3, 0x2222);
-		write_phy_reg(pi, 0x6d3, 0x2220);
-	} else {
-		write_phy_reg(pi, 0x942, 0x0);
-		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
-		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
-	}
-	wlapi_switch_macfreq(pi->sh->physhim, enable);
-}
-
-void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec)
-{
-	u8 channel = CHSPEC_CHANNEL(chanspec);
-
-	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
-
-	wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-
-	if (!NORADIO_ENAB(pi->pubpi)) {
-		wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
-		udelay(1000);
-	}
-
-	wlc_lcnphy_toggle_afe_pwdn(pi);
-
-	write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
-	write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
-
-	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
-		wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
-	} else {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
-		wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
-	}
-
-	wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
-
-	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-
-}
-
-static void wlc_lcnphy_set_dac_gain(phy_info_t *pi, u16 dac_gain)
-{
-	u16 dac_ctrl;
-
-	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
-	dac_ctrl = dac_ctrl & 0xc7f;
-	dac_ctrl = dac_ctrl | (dac_gain << 7);
-	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
-
-}
-
-static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable)
-{
-	u16 bit = bEnable ? 1 : 0;
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
-}
-
-static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi)
-{
-	u16 pa_gain;
-
-	pa_gain = (read_phy_reg(pi, 0x4fb) &
-		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
-	    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
-
-	return pa_gain;
-}
-
-static void
-wlc_lcnphy_set_tx_gain(phy_info_t *pi, lcnphy_txgains_t *target_gains)
-{
-	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
-
-	mod_phy_reg(pi, 0x4b5,
-		    (0xffff << 0),
-		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
-		    0);
-	mod_phy_reg(pi, 0x4fb,
-		    (0x7fff << 0),
-		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
-
-	mod_phy_reg(pi, 0x4fc,
-		    (0xffff << 0),
-		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
-		    0);
-	mod_phy_reg(pi, 0x4fd,
-		    (0x7fff << 0),
-		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
-
-	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
-
-	wlc_lcnphy_enable_tx_gain_override(pi);
-}
-
-static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0)
-{
-	u16 m0m1 = (u16) m0 << 8;
-	phytbl_info_t tab;
-
-	tab.tbl_ptr = &m0m1;
-	tab.tbl_len = 1;
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_offset = 87;
-	tab.tbl_width = 16;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi)
-{
-	u32 data_buf[64];
-	phytbl_info_t tab;
-
-	memset(data_buf, 0, sizeof(data_buf));
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = data_buf;
-
-	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-
-		tab.tbl_len = 30;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	tab.tbl_len = 64;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-typedef enum {
-	LCNPHY_TSSI_PRE_PA,
-	LCNPHY_TSSI_POST_PA,
-	LCNPHY_TSSI_EXT
-} lcnphy_tssi_mode_t;
-
-static void wlc_lcnphy_set_tssi_mux(phy_info_t *pi, lcnphy_tssi_mode_t pos)
-{
-	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
-
-	if (LCNPHY_TSSI_POST_PA == pos) {
-		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
-
-		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
-
-		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
-		} else {
-			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-		}
-	} else {
-		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
-
-		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
-
-		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
-		} else {
-			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
-			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-		}
-	}
-	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
-
-	if (LCNPHY_TSSI_EXT == pos) {
-		write_radio_reg(pi, RADIO_2064_REG07F, 1);
-		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
-		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
-		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
-	}
-}
-
-static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(phy_info_t *pi)
-{
-	u16 N1, N2, N3, N4, N5, N6, N;
-	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
-	      >> 0);
-	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
-		   >> 12);
-	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
-	      >> 0);
-	N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
-		   >> 8);
-	N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
-	      >> 0);
-	N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
-		   >> 8);
-	N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
-	if (N < 1600)
-		N = 1600;
-	return N;
-}
-
-static void wlc_lcnphy_pwrctrl_rssiparams(phy_info_t *pi)
-{
-	u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	auxpga_vmid =
-	    (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
-	auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
-	auxpga_gain_temp = 2;
-
-	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
-
-	mod_phy_reg(pi, 0x4db,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
-
-	mod_phy_reg(pi, 0x4dc,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
-
-	mod_phy_reg(pi, 0x40a,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
-
-	mod_phy_reg(pi, 0x40b,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
-
-	mod_phy_reg(pi, 0x40c,
-		    (0x3ff << 0) |
-		    (0x7 << 12),
-		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
-
-	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-}
-
-static void wlc_lcnphy_tssi_setup(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u32 rfseq, ind;
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = &ind;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 0;
-	for (ind = 0; ind < 128; ind++) {
-		wlc_lcnphy_write_table(pi, &tab);
-		tab.tbl_offset++;
-	}
-	tab.tbl_offset = 704;
-	for (ind = 0; ind < 128; ind++) {
-		wlc_lcnphy_write_table(pi, &tab);
-		tab.tbl_offset++;
-	}
-	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
-
-	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
-
-	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
-
-	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
-
-	mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
-
-	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
-
-	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
-
-	mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
-
-	mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
-
-	wlc_lcnphy_clear_tx_power_offsets(pi);
-
-	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
-
-	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
-
-	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
-		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
-	} else {
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
-		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
-	}
-
-	write_radio_reg(pi, RADIO_2064_REG025, 0xc);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
-	} else {
-		if (CHSPEC_IS2G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
-		else
-			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
-	}
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
-	else
-		mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
-
-	mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
-
-	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
-
-	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-		mod_phy_reg(pi, 0x4d7,
-			    (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
-	}
-
-	rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
-	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &rfseq;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 6;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
-
-	mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
-
-	wlc_lcnphy_pwrctrl_rssiparams(pi);
-}
-
-void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi)
-{
-	u16 tx_cnt, tx_total, npt;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	tx_total = wlc_lcnphy_total_tx_frames(pi);
-	tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
-	npt = wlc_lcnphy_get_tx_pwr_npt(pi);
-
-	if (tx_cnt > (1 << npt)) {
-
-		pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
-
-		pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
-		pi_lcn->lcnphy_tssi_npt = npt;
-
-	}
-}
-
-s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
-{
-	s32 a, b, p;
-
-	a = 32768 + (a1 * tssi);
-	b = (1024 * b0) + (64 * b1 * tssi);
-	p = ((2 * b) + a) / (2 * a);
-
-	return p;
-}
-
-static void wlc_lcnphy_txpower_reset_npt(phy_info_t *pi)
-{
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		return;
-
-	pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
-	pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
-}
-
-void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u32 rate_table[WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM +
-			  WLC_NUM_RATES_MCS_1_STREAM];
-	uint i, j;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		return;
-
-	for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
-
-		if (i == WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM)
-			j = TXP_FIRST_MCS_20_SISO;
-
-		rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
-	}
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = ARRAY_SIZE(rate_table);
-	tab.tbl_ptr = rate_table;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
-		wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
-
-		wlc_lcnphy_txpower_reset_npt(pi);
-	}
-}
-
-static void wlc_lcnphy_set_tx_pwr_soft_ctrl(phy_info_t *pi, s8 index)
-{
-	u32 cck_offset[4] = { 22, 22, 22, 22 };
-	u32 ofdm_offset, reg_offset_cck;
-	int i;
-	u16 index2;
-	phytbl_info_t tab;
-
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
-		return;
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
-
-	or_phy_reg(pi, 0x6da, 0x0040);
-
-	reg_offset_cck = 0;
-	for (i = 0; i < 4; i++)
-		cck_offset[i] -= reg_offset_cck;
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 4;
-	tab.tbl_ptr = cck_offset;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-	wlc_lcnphy_write_table(pi, &tab);
-	ofdm_offset = 0;
-	tab.tbl_len = 1;
-	tab.tbl_ptr = &ofdm_offset;
-	for (i = 836; i < 862; i++) {
-		tab.tbl_offset = i;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
-
-	mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
-
-	index2 = (u16) (index * 2);
-	mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
-
-	mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
-
-}
-
-static s8 wlc_lcnphy_tempcompensated_txpwrctrl(phy_info_t *pi)
-{
-	s8 index, delta_brd, delta_temp, new_index, tempcorrx;
-	s16 manp, meas_temp, temp_diff;
-	bool neg = 0;
-	u16 temp;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
-		return pi_lcn->lcnphy_current_index;
-
-	index = FIXED_TXPWR;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return index;
-
-	if (pi_lcn->lcnphy_tempsense_slope == 0) {
-		return index;
-	}
-	temp = (u16) wlc_lcnphy_tempsense(pi, 0);
-	meas_temp = LCNPHY_TEMPSENSE(temp);
-
-	if (pi->tx_power_min != 0) {
-		delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
-	} else {
-		delta_brd = 0;
-	}
-
-	manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
-	temp_diff = manp - meas_temp;
-	if (temp_diff < 0) {
-
-		neg = 1;
-
-		temp_diff = -temp_diff;
-	}
-
-	delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
-						    (u32) (pi_lcn->
-							      lcnphy_tempsense_slope
-							      * 10), 0);
-	if (neg)
-		delta_temp = -delta_temp;
-
-	if (pi_lcn->lcnphy_tempsense_option == 3
-	    && LCNREV_IS(pi->pubpi.phy_rev, 0))
-		delta_temp = 0;
-	if (pi_lcn->lcnphy_tempcorrx > 31)
-		tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
-	else
-		tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		tempcorrx = 4;
-	new_index =
-	    index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
-	new_index += tempcorrx;
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		index = 127;
-	if (new_index < 0 || new_index > 126) {
-		return index;
-	}
-	return new_index;
-}
-
-static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(phy_info_t *pi, u16 mode)
-{
-
-	u16 current_mode = mode;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
-	    mode == LCNPHY_TX_PWR_CTRL_HW)
-		current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
-	    mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
-		current_mode = LCNPHY_TX_PWR_CTRL_HW;
-	return current_mode;
-}
-
-void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode)
-{
-	u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	s8 index;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	ASSERT((LCNPHY_TX_PWR_CTRL_OFF == mode) ||
-	       (LCNPHY_TX_PWR_CTRL_SW == mode) ||
-	       (LCNPHY_TX_PWR_CTRL_HW == mode) ||
-	       (LCNPHY_TX_PWR_CTRL_TEMPBASED == mode));
-
-	mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
-	old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 6),
-		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
-
-	mod_phy_reg(pi, 0x6a3, (0x1 << 4),
-		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
-
-	if (old_mode != mode) {
-		if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
-
-			wlc_lcnphy_tx_pwr_update_npt(pi);
-
-			wlc_lcnphy_clear_tx_power_offsets(pi);
-		}
-		if (LCNPHY_TX_PWR_CTRL_HW == mode) {
-
-			wlc_lcnphy_txpower_recalc_target(pi);
-
-			wlc_lcnphy_set_start_tx_pwr_idx(pi,
-							pi_lcn->
-							lcnphy_tssi_idx);
-			wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
-			mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
-
-			pi_lcn->lcnphy_tssi_tx_cnt =
-			    wlc_lcnphy_total_tx_frames(pi);
-
-			wlc_lcnphy_disable_tx_gain_override(pi);
-			pi_lcn->lcnphy_tx_power_idx_override = -1;
-		} else
-			wlc_lcnphy_enable_tx_gain_override(pi);
-
-		mod_phy_reg(pi, 0x4a4,
-			    ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
-		if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
-			index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
-			wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
-			pi_lcn->lcnphy_current_index = (s8)
-			    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
-		}
-	}
-}
-
-static bool wlc_lcnphy_iqcal_wait(phy_info_t *pi)
-{
-	uint delay_count = 0;
-
-	while (wlc_lcnphy_iqcal_active(pi)) {
-		udelay(100);
-		delay_count++;
-
-		if (delay_count > (10 * 500))
-			break;
-	}
-
-	return (0 == wlc_lcnphy_iqcal_active(pi));
-}
-
-static void
-wlc_lcnphy_tx_iqlo_cal(phy_info_t *pi,
-		       lcnphy_txgains_t *target_gains,
-		       lcnphy_cal_mode_t cal_mode, bool keep_tone)
-{
-
-	lcnphy_txgains_t cal_gains, temp_gains;
-	u16 hash;
-	u8 band_idx;
-	int j;
-	u16 ncorr_override[5];
-	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000
-	};
-
-	u16 commands_fullcal[] = {
-		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
-
-	u16 commands_recal[] = {
-		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
-
-	u16 command_nums_fullcal[] = {
-		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
-
-	u16 command_nums_recal[] = {
-		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
-	u16 *command_nums = command_nums_fullcal;
-
-	u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
-	u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
-	u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
-	bool tx_gain_override_old;
-	lcnphy_txgains_t old_gains;
-	uint i, n_cal_cmds = 0, n_cal_start = 0;
-	u16 *values_to_save;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
-	if (NULL == values_to_save) {
-		return;
-	}
-
-	save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-	save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-
-	or_phy_reg(pi, 0x6da, 0x40);
-	or_phy_reg(pi, 0x6db, 0x3);
-
-	switch (cal_mode) {
-	case LCNPHY_CAL_FULL:
-		start_coeffs = syst_coeffs;
-		cal_cmds = commands_fullcal;
-		n_cal_cmds = ARRAY_SIZE(commands_fullcal);
-		break;
-
-	case LCNPHY_CAL_RECAL:
-		ASSERT(pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid);
-
-		start_coeffs = syst_coeffs;
-
-		cal_cmds = commands_recal;
-		n_cal_cmds = ARRAY_SIZE(commands_recal);
-		command_nums = command_nums_recal;
-		break;
-	default:
-		ASSERT(false);
-	}
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      start_coeffs, 11, 16, 64);
-
-	write_phy_reg(pi, 0x6da, 0xffff);
-	mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
-
-	tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
-
-	mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
-
-	mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
-
-	wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
-
-	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-	if (tx_gain_override_old)
-		wlc_lcnphy_get_tx_gain(pi, &old_gains);
-
-	if (!target_gains) {
-		if (!tx_gain_override_old)
-			wlc_lcnphy_set_tx_pwr_by_index(pi,
-						       pi_lcn->lcnphy_tssi_idx);
-		wlc_lcnphy_get_tx_gain(pi, &temp_gains);
-		target_gains = &temp_gains;
-	}
-
-	hash = (target_gains->gm_gain << 8) |
-	    (target_gains->pga_gain << 4) | (target_gains->pad_gain);
-
-	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
-
-	cal_gains = *target_gains;
-	memset(ncorr_override, 0, sizeof(ncorr_override));
-	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
-		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
-			cal_gains.gm_gain =
-			    tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
-			cal_gains.pga_gain =
-			    tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
-			cal_gains.pad_gain =
-			    tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
-			bcopy(&tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
-			      ncorr_override, sizeof(ncorr_override));
-			break;
-		}
-	}
-
-	wlc_lcnphy_set_tx_gain(pi, &cal_gains);
-
-	write_phy_reg(pi, 0x453, 0xaa9);
-	write_phy_reg(pi, 0x93d, 0xc0);
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      (const void *)
-				      lcnphy_iqcal_loft_gainladder,
-				      ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
-				      16, 0);
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      (const void *)lcnphy_iqcal_ir_gainladder,
-				      ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
-				      32);
-
-	if (pi->phy_tx_tone_freq) {
-
-		wlc_lcnphy_stop_tx_tone(pi);
-		udelay(5);
-		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
-	} else {
-		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
-	}
-
-	write_phy_reg(pi, 0x6da, 0xffff);
-
-	for (i = n_cal_start; i < n_cal_cmds; i++) {
-		u16 zero_diq = 0;
-		u16 best_coeffs[11];
-		u16 command_num;
-
-		cal_type = (cal_cmds[i] & 0x0f00) >> 8;
-
-		command_num = command_nums[i];
-		if (ncorr_override[cal_type])
-			command_num =
-			    ncorr_override[cal_type] << 8 | (command_num &
-							     0xff);
-
-		write_phy_reg(pi, 0x452, command_num);
-
-		if ((cal_type == 3) || (cal_type == 4)) {
-
-			wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-						     &diq_start, 1, 16, 69);
-
-			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-						      &zero_diq, 1, 16, 69);
-		}
-
-		write_phy_reg(pi, 0x451, cal_cmds[i]);
-
-		if (!wlc_lcnphy_iqcal_wait(pi)) {
-
-			goto cleanup;
-		}
-
-		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-					     best_coeffs,
-					     ARRAY_SIZE(best_coeffs), 16, 96);
-		wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-					      best_coeffs,
-					      ARRAY_SIZE(best_coeffs), 16, 64);
-
-		if ((cal_type == 3) || (cal_type == 4)) {
-			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-						      &diq_start, 1, 16, 69);
-		}
-		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-					     pi_lcn->lcnphy_cal_results.
-					     txiqlocal_bestcoeffs,
-					     ARRAY_SIZE(pi_lcn->
-						       lcnphy_cal_results.
-						       txiqlocal_bestcoeffs),
-					     16, 96);
-	}
-
-	wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				     pi_lcn->lcnphy_cal_results.
-				     txiqlocal_bestcoeffs,
-				     ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
-					       txiqlocal_bestcoeffs), 16, 96);
-	pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      &pi_lcn->lcnphy_cal_results.
-				      txiqlocal_bestcoeffs[0], 4, 16, 80);
-
-	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
-				      &pi_lcn->lcnphy_cal_results.
-				      txiqlocal_bestcoeffs[5], 2, 16, 85);
-
- cleanup:
-	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
-	kfree(values_to_save);
-
-	if (!keep_tone)
-		wlc_lcnphy_stop_tx_tone(pi);
-
-	write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
-
-	write_phy_reg(pi, 0x453, 0);
-
-	if (tx_gain_override_old)
-		wlc_lcnphy_set_tx_gain(pi, &old_gains);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
-
-	write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
-	write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
-
-}
-
-static void wlc_lcnphy_idle_tssi_est(wlc_phy_t *ppi)
-{
-	bool suspend, tx_gain_override_old;
-	lcnphy_txgains_t old_gains;
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
-	    idleTssi0_regvalue_2C;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
-	u16 SAVE_jtag_bb_afe_switch =
-	    read_radio_reg(pi, RADIO_2064_REG007) & 1;
-	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
-	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
-	idleTssi = read_phy_reg(pi, 0x4ab);
-	suspend =
-	    (0 ==
-	     (R_REG(pi->sh->osh, &((phy_info_t *) pi)->regs->maccontrol) &
-	      MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-	wlc_lcnphy_get_tx_gain(pi, &old_gains);
-
-	wlc_lcnphy_enable_tx_gain_override(pi);
-	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
-	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
-	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
-	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
-	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
-	wlc_lcnphy_tssi_setup(pi);
-	wlc_phy_do_dummy_tx(pi, true, OFF);
-	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
-		    >> 0);
-
-	idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
-			>> 0);
-
-	if (idleTssi0_2C >= 256)
-		idleTssi0_OB = idleTssi0_2C - 256;
-	else
-		idleTssi0_OB = idleTssi0_2C + 256;
-
-	idleTssi0_regvalue_OB = idleTssi0_OB;
-	if (idleTssi0_regvalue_OB >= 256)
-		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
-	else
-		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
-	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
-
-	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
-	wlc_lcnphy_set_tx_gain(pi, &old_gains);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
-
-	write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
-	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
-	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
-	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
-	mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-static void wlc_lcnphy_vbat_temp_sense_setup(phy_info_t *pi, u8 mode)
-{
-	bool suspend;
-	u16 save_txpwrCtrlEn;
-	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
-	u16 auxpga_vmid;
-	phytbl_info_t tab;
-	u32 val;
-	u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
-	    save_reg112;
-	u16 values_to_save[14];
-	s8 index;
-	int i;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	udelay(999);
-
-	save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
-	save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
-	save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
-	save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
-	save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
-	save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
-
-	for (i = 0; i < 14; i++)
-		values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
-	suspend =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-	index = pi_lcn->lcnphy_current_index;
-	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
-	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
-	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
-	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
-	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
-
-	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
-
-	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
-
-	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
-
-	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
-
-	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
-
-	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
-
-	mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
-
-	mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
-
-	mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
-
-	mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
-
-	mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
-
-	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
-
-	write_radio_reg(pi, RADIO_2064_REG025, 0xC);
-
-	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
-
-	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
-
-	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
-
-	val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
-	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-	tab.tbl_width = 16;
-	tab.tbl_len = 1;
-	tab.tbl_ptr = &val;
-	tab.tbl_offset = 6;
-	wlc_lcnphy_write_table(pi, &tab);
-	if (mode == TEMPSENSE) {
-		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
-
-		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
-
-		auxpga_vmidcourse = 8;
-		auxpga_vmidfine = 0x4;
-		auxpga_gain = 2;
-		mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
-	} else {
-		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
-
-		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
-
-		auxpga_vmidcourse = 7;
-		auxpga_vmidfine = 0xa;
-		auxpga_gain = 2;
-	}
-	auxpga_vmid =
-	    (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
-	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
-
-	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
-
-	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
-
-	mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
-
-	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
-
-	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
-
-	wlc_phy_do_dummy_tx(pi, true, OFF);
-	if (!tempsense_done(pi))
-		udelay(10);
-
-	write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
-	write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
-	write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
-	write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
-	write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
-	write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
-	for (i = 0; i < 14; i++)
-		write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
-	wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
-
-	write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-	udelay(999);
-}
-
-void WLBANDINITFN(wlc_lcnphy_tx_pwr_ctrl_init) (wlc_phy_t *ppi)
-{
-	lcnphy_txgains_t tx_gains;
-	u8 bbmult;
-	phytbl_info_t tab;
-	s32 a1, b0, b1;
-	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
-	bool suspend;
-	phy_info_t *pi = (phy_info_t *) ppi;
-
-	suspend =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		wlc_lcnphy_set_bbmult(pi, 0x30);
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-		return;
-	}
-
-	if (!pi->hwpwrctrl_capable) {
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			tx_gains.gm_gain = 4;
-			tx_gains.pga_gain = 12;
-			tx_gains.pad_gain = 12;
-			tx_gains.dac_gain = 0;
-
-			bbmult = 150;
-		} else {
-			tx_gains.gm_gain = 7;
-			tx_gains.pga_gain = 15;
-			tx_gains.pad_gain = 14;
-			tx_gains.dac_gain = 0;
-
-			bbmult = 150;
-		}
-		wlc_lcnphy_set_tx_gain(pi, &tx_gains);
-		wlc_lcnphy_set_bbmult(pi, bbmult);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
-	} else {
-
-		wlc_lcnphy_idle_tssi_est(ppi);
-
-		wlc_lcnphy_clear_tx_power_offsets(pi);
-
-		b0 = pi->txpa_2g[0];
-		b1 = pi->txpa_2g[1];
-		a1 = pi->txpa_2g[2];
-		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
-		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
-
-		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-		tab.tbl_width = 32;
-		tab.tbl_ptr = &pwr;
-		tab.tbl_len = 1;
-		tab.tbl_offset = 0;
-		for (tssi = 0; tssi < 128; tssi++) {
-			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
-
-			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
-			wlc_lcnphy_write_table(pi, &tab);
-			tab.tbl_offset++;
-		}
-
-		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
-
-		write_phy_reg(pi, 0x4a8, 10);
-
-		wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
-
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
-	}
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi)
-{
-	u16 m0m1;
-	phytbl_info_t tab;
-
-	tab.tbl_ptr = &m0m1;
-	tab.tbl_len = 1;
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_offset = 87;
-	tab.tbl_width = 16;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	return (u8) ((m0m1 & 0xff00) >> 8);
-}
-
-static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain)
-{
-	mod_phy_reg(pi, 0x4fb,
-		    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
-		    gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
-	mod_phy_reg(pi, 0x4fd,
-		    LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
-		    gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
-}
-
-void
-wlc_lcnphy_get_radio_loft(phy_info_t *pi,
-			  u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
-{
-	*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
-	*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
-	*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
-	*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
-}
-
-static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains)
-{
-	u16 dac_gain;
-
-	dac_gain = read_phy_reg(pi, 0x439) >> 0;
-	gains->dac_gain = (dac_gain & 0x380) >> 7;
-
-	{
-		u16 rfgain0, rfgain1;
-
-		rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
-		rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
-
-		gains->gm_gain = rfgain0 & 0xff;
-		gains->pga_gain = (rfgain0 >> 8) & 0xff;
-		gains->pad_gain = rfgain1 & 0xff;
-	}
-}
-
-void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b)
-{
-	phytbl_info_t tab;
-	u16 iqcc[2];
-
-	iqcc[0] = a;
-	iqcc[1] = b;
-
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = iqcc;
-	tab.tbl_len = 2;
-	tab.tbl_offset = 80;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq)
-{
-	phytbl_info_t tab;
-
-	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &didq;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 85;
-	wlc_lcnphy_write_table(pi, &tab);
-}
-
-void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index)
-{
-	phytbl_info_t tab;
-	u16 a, b;
-	u8 bb_mult;
-	u32 bbmultiqcomp, txgain, locoeffs, rfpower;
-	lcnphy_txgains_t gains;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	ASSERT(index <= LCNPHY_MAX_TX_POWER_INDEX);
-
-	pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
-	pi_lcn->lcnphy_current_index = (u8) index;
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 1;
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
-	tab.tbl_ptr = &bbmultiqcomp;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = &txgain;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	gains.gm_gain = (u16) (txgain & 0xff);
-	gains.pga_gain = (u16) (txgain >> 8) & 0xff;
-	gains.pad_gain = (u16) (txgain >> 16) & 0xff;
-	gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
-	wlc_lcnphy_set_tx_gain(pi, &gains);
-	wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
-
-	bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
-	wlc_lcnphy_set_bbmult(pi, bb_mult);
-
-	wlc_lcnphy_enable_tx_gain_override(pi);
-
-	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-
-		a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
-		b = (u16) (bbmultiqcomp & 0x3ff);
-		wlc_lcnphy_set_tx_iqcc(pi, a, b);
-
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
-		tab.tbl_ptr = &locoeffs;
-		wlc_lcnphy_read_table(pi, &tab);
-
-		wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
-
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
-		tab.tbl_ptr = &rfpower;
-		wlc_lcnphy_read_table(pi, &tab);
-		mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
-
-	}
-}
-
-static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx)
-{
-
-	mod_phy_reg(pi, 0x44d,
-		    (0x1 << 1) |
-		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
-
-	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
-}
-
-static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi)
-{
-	u32 j;
-	phytbl_info_t tab;
-	u32 temp_offset[128];
-	tab.tbl_ptr = temp_offset;
-	tab.tbl_len = 128;
-	tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
-	tab.tbl_width = 32;
-	tab.tbl_offset = 0;
-
-	memset(temp_offset, 0, sizeof(temp_offset));
-	for (j = 1; j < 128; j += 2)
-		temp_offset[j] = 0x80000;
-
-	wlc_lcnphy_write_table(pi, &tab);
-	return;
-}
-
-static void
-wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
-				       u16 trsw,
-				       u16 ext_lna,
-				       u16 biq2,
-				       u16 biq1,
-				       u16 tia, u16 lna2, u16 lna1)
-{
-	u16 gain0_15, gain16_19;
-
-	gain16_19 = biq2 & 0xf;
-	gain0_15 = ((biq1 & 0xf) << 12) |
-	    ((tia & 0xf) << 8) |
-	    ((lna2 & 0x3) << 6) |
-	    ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
-
-	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
-	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
-	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-
-	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
-		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
-	} else {
-		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
-
-		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
-
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
-	}
-
-	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-
-}
-
-static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable)
-{
-	u16 ebit = enable ? 1 : 0;
-
-	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
-
-	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
-		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
-		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
-	} else {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
-	}
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
-		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
-	}
-}
-
-void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable)
-{
-	if (!bEnable) {
-
-		and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
-
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
-
-		and_phy_reg(pi, 0x44c,
-			    ~(u16) ((0x1 << 3) |
-				       (0x1 << 5) |
-				       (0x1 << 12) |
-				       (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-
-		and_phy_reg(pi, 0x44d,
-			    ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
-		mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
-
-		mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
-
-		and_phy_reg(pi, 0x4f9,
-			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-
-		and_phy_reg(pi, 0x4fa,
-			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
-	} else {
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
-		mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
-
-		mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
-		mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
-
-		wlc_lcnphy_set_trsw_override(pi, true, false);
-
-		mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
-		mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
-			mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
-			mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
-		} else {
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
-			mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
-
-			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
-			mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
-
-			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
-		}
-	}
-}
-
-static void
-wlc_lcnphy_run_samples(phy_info_t *pi,
-		       u16 num_samps,
-		       u16 num_loops, u16 wait, bool iqcalmode)
-{
-
-	or_phy_reg(pi, 0x6da, 0x8080);
-
-	mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
-	if (num_loops != 0xffff)
-		num_loops--;
-	mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
-
-	mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
-
-	if (iqcalmode) {
-
-		and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
-		or_phy_reg(pi, 0x453, (0x1 << 15));
-	} else {
-		write_phy_reg(pi, 0x63f, 1);
-		wlc_lcnphy_tx_pu(pi, 1);
-	}
-
-	or_radio_reg(pi, RADIO_2064_REG112, 0x6);
-}
-
-void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode)
-{
-
-	u8 phybw40;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
-	} else {
-		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
-		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
-	}
-
-	if (phybw40 == 0) {
-		mod_phy_reg((pi), 0x410,
-			    (0x1 << 6) |
-			    (0x1 << 5),
-			    ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
-			    6 | (!mode) << 5);
-		mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
-	}
-}
-
-void
-wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz, u16 max_val,
-			 bool iqcalmode)
-{
-	u8 phy_bw;
-	u16 num_samps, t, k;
-	u32 bw;
-	fixed theta = 0, rot = 0;
-	cs32 tone_samp;
-	u32 data_buf[64];
-	u16 i_samp, q_samp;
-	phytbl_info_t tab;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	pi->phy_tx_tone_freq = f_kHz;
-
-	wlc_lcnphy_deaf_mode(pi, true);
-
-	phy_bw = 40;
-	if (pi_lcn->lcnphy_spurmod) {
-		write_phy_reg(pi, 0x942, 0x2);
-		write_phy_reg(pi, 0x93b, 0x0);
-		write_phy_reg(pi, 0x93c, 0x0);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
-	}
-
-	if (f_kHz) {
-		k = 1;
-		do {
-			bw = phy_bw * 1000 * k;
-			num_samps = bw / ABS(f_kHz);
-			ASSERT(num_samps <= ARRAY_SIZE(data_buf));
-			k++;
-		} while ((num_samps * (u32) (ABS(f_kHz))) != bw);
-	} else
-		num_samps = 2;
-
-	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
-	theta = 0;
-
-	for (t = 0; t < num_samps; t++) {
-
-		wlc_phy_cordic(theta, &tone_samp);
-
-		theta += rot;
-
-		i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
-		q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
-		data_buf[t] = (i_samp << 10) | q_samp;
-	}
-
-	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
-
-	tab.tbl_ptr = data_buf;
-	tab.tbl_len = num_samps;
-	tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
-	tab.tbl_offset = 0;
-	tab.tbl_width = 32;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
-}
-
-void wlc_lcnphy_stop_tx_tone(phy_info_t *pi)
-{
-	s16 playback_status;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	pi->phy_tx_tone_freq = 0;
-	if (pi_lcn->lcnphy_spurmod) {
-		write_phy_reg(pi, 0x942, 0x7);
-		write_phy_reg(pi, 0x93b, 0x2017);
-		write_phy_reg(pi, 0x93c, 0x27c5);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
-	}
-
-	playback_status = read_phy_reg(pi, 0x644);
-	if (playback_status & (0x1 << 0)) {
-		wlc_lcnphy_tx_pu(pi, 0);
-		mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
-	} else if (playback_status & (0x1 << 1))
-		mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
-
-	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
-
-	and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
-
-	wlc_lcnphy_deaf_mode(pi, false);
-}
-
-static void wlc_lcnphy_clear_trsw_override(phy_info_t *pi)
-{
-
-	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
-}
-
-void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b)
-{
-	u16 iqcc[2];
-	phytbl_info_t tab;
-
-	tab.tbl_ptr = iqcc;
-	tab.tbl_len = 2;
-	tab.tbl_id = 0;
-	tab.tbl_offset = 80;
-	tab.tbl_width = 16;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	*a = iqcc[0];
-	*b = iqcc[1];
-}
-
-u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u16 didq;
-
-	tab.tbl_id = 0;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &didq;
-	tab.tbl_len = 1;
-	tab.tbl_offset = 85;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	return didq;
-}
-
-static void wlc_lcnphy_txpwrtbl_iqlo_cal(phy_info_t *pi)
-{
-
-	lcnphy_txgains_t target_gains, old_gains;
-	u8 save_bb_mult;
-	u16 a, b, didq, save_pa_gain = 0;
-	uint idx, SAVE_txpwrindex = 0xFF;
-	u32 val;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	phytbl_info_t tab;
-	u8 ei0, eq0, fi0, fq0;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	wlc_lcnphy_get_tx_gain(pi, &old_gains);
-	save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
-
-	save_bb_mult = wlc_lcnphy_get_bbmult(pi);
-
-	if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
-		SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-	target_gains.gm_gain = 7;
-	target_gains.pga_gain = 0;
-	target_gains.pad_gain = 21;
-	target_gains.dac_gain = 0;
-	wlc_lcnphy_set_tx_gain(pi, &target_gains);
-	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
-
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
-
-		wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
-				       (pi_lcn->
-					lcnphy_recal ? LCNPHY_CAL_RECAL :
-					LCNPHY_CAL_FULL), false);
-	} else {
-
-		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
-	}
-
-	wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
-	if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			target_gains.gm_gain = 255;
-			target_gains.pga_gain = 255;
-			target_gains.pad_gain = 0xf0;
-			target_gains.dac_gain = 0;
-		} else {
-			target_gains.gm_gain = 7;
-			target_gains.pga_gain = 45;
-			target_gains.pad_gain = 186;
-			target_gains.dac_gain = 0;
-		}
-
-		if (LCNREV_IS(pi->pubpi.phy_rev, 1)
-		    || pi_lcn->lcnphy_hw_iqcal_en) {
-
-			target_gains.pga_gain = 0;
-			target_gains.pad_gain = 30;
-			wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
-			wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
-					       LCNPHY_CAL_FULL, false);
-		} else {
-
-			wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
-		}
-
-	}
-
-	wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
-
-	didq = wlc_lcnphy_get_tx_locc(pi);
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_ptr = &val;
-
-	tab.tbl_len = 1;
-	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
-
-	for (idx = 0; idx < 128; idx++) {
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
-
-		wlc_lcnphy_read_table(pi, &tab);
-		val = (val & 0xfff00000) |
-		    ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
-		wlc_lcnphy_write_table(pi, &tab);
-
-		val = didq;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
-	pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
-	pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
-	pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
-	pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
-	pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
-	pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
-
-	wlc_lcnphy_set_bbmult(pi, save_bb_mult);
-	wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
-	wlc_lcnphy_set_tx_gain(pi, &old_gains);
-
-	if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
-	else
-		wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
-}
-
-s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode)
-{
-	u16 tempsenseval1, tempsenseval2;
-	s16 avg = 0;
-	bool suspend = 0;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return -1;
-
-	if (mode == 1) {
-		suspend =
-		    (0 ==
-		     (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
-	}
-	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
-	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
-
-	if (tempsenseval1 > 255)
-		avg = (s16) (tempsenseval1 - 512);
-	else
-		avg = (s16) tempsenseval1;
-
-	if (tempsenseval2 > 255)
-		avg += (s16) (tempsenseval2 - 512);
-	else
-		avg += (s16) tempsenseval2;
-
-	avg /= 2;
-
-	if (mode == 1) {
-
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
-		udelay(100);
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	}
-	return avg;
-}
-
-u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode)
-{
-	u16 tempsenseval1, tempsenseval2;
-	s32 avg = 0;
-	bool suspend = 0;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return -1;
-
-	if (mode == 1) {
-		suspend =
-		    (0 ==
-		     (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
-	}
-	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
-	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
-
-	if (tempsenseval1 > 255)
-		avg = (int)(tempsenseval1 - 512);
-	else
-		avg = (int)tempsenseval1;
-
-	if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
-		if (tempsenseval2 > 255)
-			avg = (int)(avg - tempsenseval2 + 512);
-		else
-			avg = (int)(avg - tempsenseval2);
-	} else {
-		if (tempsenseval2 > 255)
-			avg = (int)(avg + tempsenseval2 - 512);
-		else
-			avg = (int)(avg + tempsenseval2);
-		avg = avg / 2;
-	}
-	if (avg < 0)
-		avg = avg + 512;
-
-	if (pi_lcn->lcnphy_tempsense_option == 2)
-		avg = tempsenseval1;
-
-	if (mode)
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
-
-	if (mode == 1) {
-
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
-		udelay(100);
-		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	}
-	return (u16) avg;
-}
-
-s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode)
-{
-	s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
-	degree =
-	    ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
-	    / LCN_TEMPSENSE_DEN;
-	return (s8) degree;
-}
-
-s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode)
-{
-	u16 vbatsenseval;
-	s32 avg = 0;
-	bool suspend = 0;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return -1;
-
-	if (mode == 1) {
-		suspend =
-		    (0 ==
-		     (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-		if (!suspend)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-		wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
-	}
-
-	vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
-
-	if (vbatsenseval > 255)
-		avg = (s32) (vbatsenseval - 512);
-	else
-		avg = (s32) vbatsenseval;
-
-	avg =
-	    (avg * LCN_VBAT_SCALE_NOM +
-	     (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
-
-	if (mode == 1) {
-		if (!suspend)
-			wlapi_enable_mac(pi->sh->physhim);
-	}
-	return (s8) avg;
-}
-
-static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode)
-{
-	u8 phybw40;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
-
-	if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
-	    (mode == AFE_CLK_INIT_MODE_TXRX2X))
-		write_phy_reg(pi, 0x6d0, 0x7);
-
-	wlc_lcnphy_toggle_afe_pwdn(pi);
-}
-
-static bool
-wlc_lcnphy_rx_iq_est(phy_info_t *pi,
-		     u16 num_samps,
-		     u8 wait_time, lcnphy_iq_est_t *iq_est)
-{
-	int wait_count = 0;
-	bool result = true;
-	u8 phybw40;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
-
-	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
-
-	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
-
-	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
-
-	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
-
-	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
-
-	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
-
-		if (wait_count > (10 * 500)) {
-			result = false;
-			goto cleanup;
-		}
-		udelay(100);
-		wait_count++;
-	}
-
-	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
-	    (u32) read_phy_reg(pi, 0x484);
-	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
-	    (u32) read_phy_reg(pi, 0x486);
-	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
-	    (u32) read_phy_reg(pi, 0x488);
-
- cleanup:
-	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
-
-	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
-
-	return result;
-}
-
-static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps)
-{
-#define LCNPHY_MIN_RXIQ_PWR 2
-	bool result;
-	u16 a0_new, b0_new;
-	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
-	s32 a, b, temp;
-	s16 iq_nbits, qq_nbits, arsh, brsh;
-	s32 iq;
-	u32 ii, qq;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
-	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
-	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
-
-	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
-
-	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
-
-	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
-	if (!result)
-		goto cleanup;
-
-	iq = (s32) iq_est.iq_prod;
-	ii = iq_est.i_pwr;
-	qq = iq_est.q_pwr;
-
-	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
-		result = false;
-		goto cleanup;
-	}
-
-	iq_nbits = wlc_phy_nbits(iq);
-	qq_nbits = wlc_phy_nbits(qq);
-
-	arsh = 10 - (30 - iq_nbits);
-	if (arsh >= 0) {
-		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
-		temp = (s32) (ii >> arsh);
-		if (temp == 0) {
-			return false;
-		}
-	} else {
-		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
-		temp = (s32) (ii << -arsh);
-		if (temp == 0) {
-			return false;
-		}
-	}
-	a /= temp;
-	brsh = qq_nbits - 31 + 20;
-	if (brsh >= 0) {
-		b = (qq << (31 - qq_nbits));
-		temp = (s32) (ii >> brsh);
-		if (temp == 0) {
-			return false;
-		}
-	} else {
-		b = (qq << (31 - qq_nbits));
-		temp = (s32) (ii << -brsh);
-		if (temp == 0) {
-			return false;
-		}
-	}
-	b /= temp;
-	b -= a * a;
-	b = (s32) wlc_phy_sqrt_int((u32) b);
-	b -= (1 << 10);
-	a0_new = (u16) (a & 0x3ff);
-	b0_new = (u16) (b & 0x3ff);
- cleanup:
-
-	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
-
-	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
-
-	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
-
-	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
-	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
-
-	return result;
-}
-
-static bool
-wlc_lcnphy_rx_iq_cal(phy_info_t *pi, const lcnphy_rx_iqcomp_t *iqcomp,
-		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
-		     int tx_gain_idx)
-{
-	lcnphy_txgains_t old_gains;
-	u16 tx_pwr_ctrl;
-	u8 tx_gain_index_old = 0;
-	bool result = false, tx_gain_override_old = false;
-	u16 i, Core1TxControl_old, RFOverride0_old,
-	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
-	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
-	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-	int tia_gain;
-	u32 received_power, rx_pwr_threshold;
-	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
-	u16 values_to_save[11];
-	s16 *ptr;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
-	if (NULL == ptr) {
-		return false;
-	}
-	if (module == 2) {
-		ASSERT(iqcomp_sz);
-
-		while (iqcomp_sz--) {
-			if (iqcomp[iqcomp_sz].chan ==
-			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
-
-				wlc_lcnphy_set_rx_iq_comp(pi,
-							  (u16)
-							  iqcomp[iqcomp_sz].a,
-							  (u16)
-							  iqcomp[iqcomp_sz].b);
-				result = true;
-				break;
-			}
-		}
-		ASSERT(result);
-		goto cal_done;
-	}
-
-	if (module == 1) {
-
-		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-		for (i = 0; i < 11; i++) {
-			values_to_save[i] =
-			    read_radio_reg(pi, rxiq_cal_rf_reg[i]);
-		}
-		Core1TxControl_old = read_phy_reg(pi, 0x631);
-
-		or_phy_reg(pi, 0x631, 0x0015);
-
-		RFOverride0_old = read_phy_reg(pi, 0x44c);
-		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
-		rfoverride2_old = read_phy_reg(pi, 0x4b0);
-		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
-		rfoverride3_old = read_phy_reg(pi, 0x4f9);
-		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
-		rfoverride4_old = read_phy_reg(pi, 0x938);
-		rfoverride4val_old = read_phy_reg(pi, 0x939);
-		afectrlovr_old = read_phy_reg(pi, 0x43b);
-		afectrlovrval_old = read_phy_reg(pi, 0x43c);
-		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
-		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-		if (tx_gain_override_old) {
-			wlc_lcnphy_get_tx_gain(pi, &old_gains);
-			tx_gain_index_old = pi_lcn->lcnphy_current_index;
-		}
-
-		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
-
-		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
-		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
-		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
-		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
-		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
-		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
-		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
-		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
-		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
-		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
-		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
-		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
-		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
-		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
-		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
-		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
-		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
-		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
-		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
-
-		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
-		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
-		write_phy_reg(pi, 0x6da, 0xffff);
-		or_phy_reg(pi, 0x6db, 0x3);
-		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-		wlc_lcnphy_rx_gain_override_enable(pi, true);
-
-		tia_gain = 8;
-		rx_pwr_threshold = 950;
-		while (tia_gain > 0) {
-			tia_gain -= 1;
-			wlc_lcnphy_set_rx_gain_by_distribution(pi,
-							       0, 0, 2, 2,
-							       (u16)
-							       tia_gain, 1, 0);
-			udelay(500);
-
-			received_power =
-			    wlc_lcnphy_measure_digital_power(pi, 2000);
-			if (received_power < rx_pwr_threshold)
-				break;
-		}
-		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
-
-		wlc_lcnphy_stop_tx_tone(pi);
-
-		write_phy_reg(pi, 0x631, Core1TxControl_old);
-
-		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
-		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
-		write_phy_reg(pi, 0x4b0, rfoverride2_old);
-		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
-		write_phy_reg(pi, 0x4f9, rfoverride3_old);
-		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
-		write_phy_reg(pi, 0x938, rfoverride4_old);
-		write_phy_reg(pi, 0x939, rfoverride4val_old);
-		write_phy_reg(pi, 0x43b, afectrlovr_old);
-		write_phy_reg(pi, 0x43c, afectrlovrval_old);
-		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
-
-		wlc_lcnphy_clear_trsw_override(pi);
-
-		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
-
-		for (i = 0; i < 11; i++) {
-			write_radio_reg(pi, rxiq_cal_rf_reg[i],
-					values_to_save[i]);
-		}
-
-		if (tx_gain_override_old) {
-			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
-		} else
-			wlc_lcnphy_disable_tx_gain_override(pi);
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-
-		wlc_lcnphy_rx_gain_override_enable(pi, false);
-	}
-
- cal_done:
-	kfree(ptr);
-	return result;
-}
-
-static void wlc_lcnphy_temp_adj(phy_info_t *pi)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-}
-
-static void wlc_lcnphy_glacial_timer_based_cal(phy_info_t *pi)
-{
-	bool suspend;
-	s8 index;
-	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	suspend =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	wlc_lcnphy_deaf_mode(pi, true);
-	pi->phy_lastcal = pi->sh->now;
-	pi->phy_forcecal = false;
-	index = pi_lcn->lcnphy_current_index;
-
-	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
-
-	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
-	wlc_lcnphy_deaf_mode(pi, false);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-
-}
-
-static void wlc_lcnphy_periodic_cal(phy_info_t *pi)
-{
-	bool suspend, full_cal;
-	const lcnphy_rx_iqcomp_t *rx_iqcomp;
-	int rx_iqcomp_sz;
-	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	s8 index;
-	phytbl_info_t tab;
-	s32 a1, b0, b1;
-	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	pi->phy_lastcal = pi->sh->now;
-	pi->phy_forcecal = false;
-	full_cal =
-	    (pi_lcn->lcnphy_full_cal_channel !=
-	     CHSPEC_CHANNEL(pi->radio_chanspec));
-	pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-	index = pi_lcn->lcnphy_current_index;
-
-	suspend =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend) {
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	}
-	wlc_lcnphy_deaf_mode(pi, true);
-
-	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
-
-	rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
-	rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
-	else
-		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
-
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
-
-		wlc_lcnphy_idle_tssi_est((wlc_phy_t *) pi);
-
-		b0 = pi->txpa_2g[0];
-		b1 = pi->txpa_2g[1];
-		a1 = pi->txpa_2g[2];
-		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
-		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
-
-		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-		tab.tbl_width = 32;
-		tab.tbl_ptr = &pwr;
-		tab.tbl_len = 1;
-		tab.tbl_offset = 0;
-		for (tssi = 0; tssi < 128; tssi++) {
-			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
-			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
-			wlc_lcnphy_write_table(pi, &tab);
-			tab.tbl_offset++;
-		}
-	}
-
-	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
-	wlc_lcnphy_deaf_mode(pi, false);
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode)
-{
-	u16 temp_new;
-	int temp1, temp2, temp_diff;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	switch (mode) {
-	case PHY_PERICAL_CHAN:
-
-		break;
-	case PHY_FULLCAL:
-		wlc_lcnphy_periodic_cal(pi);
-		break;
-	case PHY_PERICAL_PHYINIT:
-		wlc_lcnphy_periodic_cal(pi);
-		break;
-	case PHY_PERICAL_WATCHDOG:
-		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-			temp_new = wlc_lcnphy_tempsense(pi, 0);
-			temp1 = LCNPHY_TEMPSENSE(temp_new);
-			temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
-			temp_diff = temp1 - temp2;
-			if ((pi_lcn->lcnphy_cal_counter > 90) ||
-			    (temp_diff > 60) || (temp_diff < -60)) {
-				wlc_lcnphy_glacial_timer_based_cal(pi);
-				wlc_2064_vco_cal(pi);
-				pi_lcn->lcnphy_cal_temper = temp_new;
-				pi_lcn->lcnphy_cal_counter = 0;
-			} else
-				pi_lcn->lcnphy_cal_counter++;
-		}
-		break;
-	case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
-		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-			wlc_lcnphy_tx_power_adjustment((wlc_phy_t *) pi);
-		break;
-	default:
-		ASSERT(0);
-		break;
-	}
-}
-
-void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr, s8 *cck_pwr)
-{
-	s8 cck_offset;
-	u16 status;
-	status = (read_phy_reg(pi, 0x4ab));
-	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
-	    (status  & (0x1 << 15))) {
-		*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
-				     >> 0) >> 1);
-
-		if (wlc_phy_tpc_isenabled_lcnphy(pi))
-			cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
-		else
-			cck_offset = 0;
-
-		*cck_pwr = *ofdm_pwr + cck_offset;
-	} else {
-		*cck_pwr = 0;
-		*ofdm_pwr = 0;
-	}
-}
-
-void WLBANDINITFN(wlc_phy_cal_init_lcnphy) (phy_info_t *pi)
-{
-	return;
-
-}
-
-static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi, chanspec_t chanspec)
-{
-	u8 channel = CHSPEC_CHANNEL(chanspec);
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	if (channel == 14) {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
-
-	} else {
-		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
-
-	}
-	pi_lcn->lcnphy_bandedge_corr = 2;
-	if (channel == 1)
-		pi_lcn->lcnphy_bandedge_corr = 4;
-
-	if (channel == 1 || channel == 2 || channel == 3 ||
-	    channel == 4 || channel == 9 ||
-	    channel == 10 || channel == 11 || channel == 12) {
-		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
-		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
-		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
-
-		si_pmu_pllupd(pi->sh->sih);
-		write_phy_reg(pi, 0x942, 0);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
-		pi_lcn->lcnphy_spurmod = 0;
-		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
-
-		write_phy_reg(pi, 0x425, 0x5907);
-	} else {
-		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
-		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
-		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
-
-		si_pmu_pllupd(pi->sh->sih);
-		write_phy_reg(pi, 0x942, 0);
-		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
-
-		pi_lcn->lcnphy_spurmod = 0;
-		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
-
-		write_phy_reg(pi, 0x425, 0x590a);
-	}
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-}
-
-void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi)
-{
-	s8 index;
-	u16 index2;
-	phy_info_t *pi = (phy_info_t *) ppi;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
-		index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
-		index2 = (u16) (index * 2);
-		mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
-
-		pi_lcn->lcnphy_current_index = (s8)
-		    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
-	}
-}
-
-static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b)
-{
-	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
-
-	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
-
-	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
-
-	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
-
-	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
-
-	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
-
-}
-
-void WLBANDINITFN(wlc_phy_init_lcnphy) (phy_info_t *pi)
-{
-	u8 phybw40;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	pi_lcn->lcnphy_cal_counter = 0;
-	pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
-
-	or_phy_reg(pi, 0x44a, 0x80);
-	and_phy_reg(pi, 0x44a, 0x7f);
-
-	wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
-
-	write_phy_reg(pi, 0x60a, 160);
-
-	write_phy_reg(pi, 0x46a, 25);
-
-	wlc_lcnphy_baseband_init(pi);
-
-	wlc_lcnphy_radio_init(pi);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec))
-		wlc_lcnphy_tx_pwr_ctrl_init((wlc_phy_t *) pi);
-
-	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
-
-	si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
-
-	si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
-
-	if ((pi->sh->boardflags & BFL_FEM)
-	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
-
-	wlc_lcnphy_agc_temp_init(pi);
-
-	wlc_lcnphy_temp_adj(pi);
-
-	mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
-
-	udelay(100);
-	mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
-
-	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
-	pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
-	wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi, u16 *values_to_save)
-{
-	u16 vmid;
-	int i;
-	for (i = 0; i < 20; i++) {
-		values_to_save[i] =
-		    read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
-	}
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
-	mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
-
-	mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
-	mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
-
-	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
-		and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
-	else
-		and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
-	or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
-
-	or_radio_reg(pi, RADIO_2064_REG036, 0x01);
-	or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
-	udelay(20);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
-		else
-			or_radio_reg(pi, RADIO_2064_REG03A, 1);
-	} else {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
-		else
-			or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
-	}
-
-	udelay(20);
-
-	write_radio_reg(pi, RADIO_2064_REG025, 0xF);
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
-		else
-			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
-	} else {
-		if (CHSPEC_IS5G(pi->radio_chanspec))
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
-		else
-			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
-	}
-
-	udelay(20);
-
-	write_radio_reg(pi, RADIO_2064_REG005, 0x8);
-	or_radio_reg(pi, RADIO_2064_REG112, 0x80);
-	udelay(20);
-
-	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
-	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
-	udelay(20);
-
-	or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-	or_radio_reg(pi, RADIO_2064_REG113, 0x10);
-	udelay(20);
-
-	write_radio_reg(pi, RADIO_2064_REG007, 0x1);
-	udelay(20);
-
-	vmid = 0x2A6;
-	mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
-	write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
-	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
-	udelay(20);
-
-	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
-	udelay(20);
-	write_radio_reg(pi, RADIO_2064_REG012, 0x02);
-	or_radio_reg(pi, RADIO_2064_REG112, 0x06);
-	write_radio_reg(pi, RADIO_2064_REG036, 0x11);
-	write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
-	write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
-	write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
-	write_radio_reg(pi, RADIO_2064_REG092, 0x15);
-}
-
-static void
-wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo, u16 thresh,
-		    s16 *ptr, int mode)
-{
-	u32 curval1, curval2, stpptr, curptr, strptr, val;
-	u16 sslpnCalibClkEnCtrl, timer;
-	u16 old_sslpnCalibClkEnCtrl;
-	s16 imag, real;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	timer = 0;
-	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-
-	curval1 = R_REG(pi->sh->osh, &pi->regs->psm_corectlsts);
-	ptr[130] = 0;
-	W_REG(pi->sh->osh, &pi->regs->psm_corectlsts, ((1 << 6) | curval1));
-
-	W_REG(pi->sh->osh, &pi->regs->smpl_clct_strptr, 0x7E00);
-	W_REG(pi->sh->osh, &pi->regs->smpl_clct_stpptr, 0x8000);
-	udelay(20);
-	curval2 = R_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param);
-	W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, curval2 | 0x30);
-
-	write_phy_reg(pi, 0x555, 0x0);
-	write_phy_reg(pi, 0x5a6, 0x5);
-
-	write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
-	write_phy_reg(pi, 0x5cf, 3);
-	write_phy_reg(pi, 0x5a5, 0x3);
-	write_phy_reg(pi, 0x583, 0x0);
-	write_phy_reg(pi, 0x584, 0x0);
-	write_phy_reg(pi, 0x585, 0x0fff);
-	write_phy_reg(pi, 0x586, 0x0000);
-
-	write_phy_reg(pi, 0x580, 0x4501);
-
-	sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-	write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
-	stpptr = R_REG(pi->sh->osh, &pi->regs->smpl_clct_stpptr);
-	curptr = R_REG(pi->sh->osh, &pi->regs->smpl_clct_curptr);
-	do {
-		udelay(10);
-		curptr = R_REG(pi->sh->osh, &pi->regs->smpl_clct_curptr);
-		timer++;
-	} while ((curptr != stpptr) && (timer < 500));
-
-	W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, 0x2);
-	strptr = 0x7E00;
-	W_REG(pi->sh->osh, &pi->regs->tplatewrptr, strptr);
-	while (strptr < 0x8000) {
-		val = R_REG(pi->sh->osh, &pi->regs->tplatewrdata);
-		imag = ((val >> 16) & 0x3ff);
-		real = ((val) & 0x3ff);
-		if (imag > 511) {
-			imag -= 1024;
-		}
-		if (real > 511) {
-			real -= 1024;
-		}
-		if (pi_lcn->lcnphy_iqcal_swp_dis)
-			ptr[(strptr - 0x7E00) / 4] = real;
-		else
-			ptr[(strptr - 0x7E00) / 4] = imag;
-		if (clip_detect_algo) {
-			if (imag > thresh || imag < -thresh) {
-				strptr = 0x8000;
-				ptr[130] = 1;
-			}
-		}
-		strptr += 4;
-	}
-
-	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-	W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, curval2);
-	W_REG(pi->sh->osh, &pi->regs->psm_corectlsts, curval1);
-}
-
-static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi)
-{
-	lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
-
-	wlc_lcnphy_set_cc(pi, 0, 0, 0);
-	wlc_lcnphy_set_cc(pi, 2, 0, 0);
-	wlc_lcnphy_set_cc(pi, 3, 0, 0);
-	wlc_lcnphy_set_cc(pi, 4, 0, 0);
-
-	wlc_lcnphy_a1(pi, 4, 0, 0);
-	wlc_lcnphy_a1(pi, 3, 0, 0);
-	wlc_lcnphy_a1(pi, 2, 3, 2);
-	wlc_lcnphy_a1(pi, 0, 5, 8);
-	wlc_lcnphy_a1(pi, 2, 2, 1);
-	wlc_lcnphy_a1(pi, 0, 4, 3);
-
-	iqcc0 = wlc_lcnphy_get_cc(pi, 0);
-	locc2 = wlc_lcnphy_get_cc(pi, 2);
-	locc3 = wlc_lcnphy_get_cc(pi, 3);
-	locc4 = wlc_lcnphy_get_cc(pi, 4);
-}
-
-static void
-wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x, s16 coeff_y)
-{
-	u16 di0dq0;
-	u16 x, y, data_rf;
-	int k;
-	switch (cal_type) {
-	case 0:
-		wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
-		break;
-	case 2:
-		di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
-		wlc_lcnphy_set_tx_locc(pi, di0dq0);
-		break;
-	case 3:
-		k = wlc_lcnphy_calc_floor(coeff_x, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_x, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG089, data_rf);
-		k = wlc_lcnphy_calc_floor(coeff_y, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_y, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
-		break;
-	case 4:
-		k = wlc_lcnphy_calc_floor(coeff_x, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_x, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
-		k = wlc_lcnphy_calc_floor(coeff_y, 0);
-		y = 8 + k;
-		k = wlc_lcnphy_calc_floor(coeff_y, 1);
-		x = 8 - k;
-		data_rf = (x * 16 + y);
-		write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
-		break;
-	}
-}
-
-static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type)
-{
-	u16 a, b, didq;
-	u8 di0, dq0, ei, eq, fi, fq;
-	lcnphy_unsign16_struct cc;
-	cc.re = 0;
-	cc.im = 0;
-	switch (cal_type) {
-	case 0:
-		wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
-		cc.re = a;
-		cc.im = b;
-		break;
-	case 2:
-		didq = wlc_lcnphy_get_tx_locc(pi);
-		di0 = (((didq & 0xff00) << 16) >> 24);
-		dq0 = (((didq & 0x00ff) << 24) >> 24);
-		cc.re = (u16) di0;
-		cc.im = (u16) dq0;
-		break;
-	case 3:
-		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
-		cc.re = (u16) ei;
-		cc.im = (u16) eq;
-		break;
-	case 4:
-		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
-		cc.re = (u16) fi;
-		cc.im = (u16) fq;
-		break;
-	}
-	return cc;
-}
-
-static void
-wlc_lcnphy_a1(phy_info_t *pi, int cal_type, int num_levels, int step_size_lg2)
-{
-	const lcnphy_spb_tone_t *phy_c1;
-	lcnphy_spb_tone_t phy_c2;
-	lcnphy_unsign16_struct phy_c3;
-	int phy_c4, phy_c5, k, l, j, phy_c6;
-	u16 phy_c7, phy_c8, phy_c9;
-	s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
-	s16 *ptr, phy_c17;
-	s32 phy_c18, phy_c19;
-	u32 phy_c20, phy_c21;
-	bool phy_c22, phy_c23, phy_c24, phy_c25;
-	u16 phy_c26, phy_c27;
-	u16 phy_c28, phy_c29, phy_c30;
-	u16 phy_c31;
-	u16 *phy_c32;
-	phy_c21 = 0;
-	phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
-	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
-	if (NULL == ptr) {
-		return;
-	}
-
-	phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
-	if (NULL == phy_c32) {
-		return;
-	}
-	phy_c26 = read_phy_reg(pi, 0x6da);
-	phy_c27 = read_phy_reg(pi, 0x6db);
-	phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
-	write_phy_reg(pi, 0x93d, 0xC0);
-
-	wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
-	write_phy_reg(pi, 0x6da, 0xffff);
-	or_phy_reg(pi, 0x6db, 0x3);
-
-	wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
-	udelay(500);
-	phy_c28 = read_phy_reg(pi, 0x938);
-	phy_c29 = read_phy_reg(pi, 0x4d7);
-	phy_c30 = read_phy_reg(pi, 0x4d8);
-	or_phy_reg(pi, 0x938, 0x1 << 2);
-	or_phy_reg(pi, 0x4d7, 0x1 << 2);
-	or_phy_reg(pi, 0x4d7, 0x1 << 3);
-	mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
-	or_phy_reg(pi, 0x4d8, 1 << 0);
-	or_phy_reg(pi, 0x4d8, 1 << 1);
-	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
-	mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
-	phy_c1 = &lcnphy_spb_tone_3750[0];
-	phy_c4 = 32;
-
-	if (num_levels == 0) {
-		if (cal_type != 0) {
-			num_levels = 4;
-		} else {
-			num_levels = 9;
-		}
-	}
-	if (step_size_lg2 == 0) {
-		if (cal_type != 0) {
-			step_size_lg2 = 3;
-		} else {
-			step_size_lg2 = 8;
-		}
-	}
-
-	phy_c7 = (1 << step_size_lg2);
-	phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
-	phy_c15 = (s16) phy_c3.re;
-	phy_c16 = (s16) phy_c3.im;
-	if (cal_type == 2) {
-		if (phy_c3.re > 127)
-			phy_c15 = phy_c3.re - 256;
-		if (phy_c3.im > 127)
-			phy_c16 = phy_c3.im - 256;
-	}
-	wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
-	udelay(20);
-	for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
-		phy_c23 = 1;
-		phy_c22 = 0;
-		switch (cal_type) {
-		case 0:
-			phy_c10 = 511;
-			break;
-		case 2:
-			phy_c10 = 127;
-			break;
-		case 3:
-			phy_c10 = 15;
-			break;
-		case 4:
-			phy_c10 = 15;
-			break;
-		}
-
-		phy_c9 = read_phy_reg(pi, 0x93d);
-		phy_c9 = 2 * phy_c9;
-		phy_c24 = 0;
-		phy_c5 = 7;
-		phy_c25 = 1;
-		while (1) {
-			write_radio_reg(pi, RADIO_2064_REG026,
-					(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
-			udelay(50);
-			phy_c22 = 0;
-			ptr[130] = 0;
-			wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
-			if (ptr[130] == 1)
-				phy_c22 = 1;
-			if (phy_c22)
-				phy_c5 -= 1;
-			if ((phy_c22 != phy_c24) && (!phy_c25))
-				break;
-			if (!phy_c22)
-				phy_c5 += 1;
-			if (phy_c5 <= 0 || phy_c5 >= 7)
-				break;
-			phy_c24 = phy_c22;
-			phy_c25 = 0;
-		}
-
-		if (phy_c5 < 0)
-			phy_c5 = 0;
-		else if (phy_c5 > 7)
-			phy_c5 = 7;
-
-		for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
-			for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
-				phy_c11 = phy_c15 + k;
-				phy_c12 = phy_c16 + l;
-
-				if (phy_c11 < -phy_c10)
-					phy_c11 = -phy_c10;
-				else if (phy_c11 > phy_c10)
-					phy_c11 = phy_c10;
-				if (phy_c12 < -phy_c10)
-					phy_c12 = -phy_c10;
-				else if (phy_c12 > phy_c10)
-					phy_c12 = phy_c10;
-				wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
-						  phy_c12);
-				udelay(20);
-				wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
-
-				phy_c18 = 0;
-				phy_c19 = 0;
-				for (j = 0; j < 128; j++) {
-					if (cal_type != 0) {
-						phy_c6 = j % phy_c4;
-					} else {
-						phy_c6 = (2 * j) % phy_c4;
-					}
-					phy_c2.re = phy_c1[phy_c6].re;
-					phy_c2.im = phy_c1[phy_c6].im;
-					phy_c17 = ptr[j];
-					phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
-					phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
-				}
-
-				phy_c18 = phy_c18 >> 10;
-				phy_c19 = phy_c19 >> 10;
-				phy_c20 =
-				    ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
-
-				if (phy_c23 || phy_c20 < phy_c21) {
-					phy_c21 = phy_c20;
-					phy_c13 = phy_c11;
-					phy_c14 = phy_c12;
-				}
-				phy_c23 = 0;
-			}
-		}
-		phy_c23 = 1;
-		phy_c15 = phy_c13;
-		phy_c16 = phy_c14;
-		phy_c7 = phy_c7 >> 1;
-		wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
-		udelay(20);
-	}
-	goto cleanup;
- cleanup:
-	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
-	wlc_lcnphy_stop_tx_tone(pi);
-	write_phy_reg(pi, 0x6da, phy_c26);
-	write_phy_reg(pi, 0x6db, phy_c27);
-	write_phy_reg(pi, 0x938, phy_c28);
-	write_phy_reg(pi, 0x4d7, phy_c29);
-	write_phy_reg(pi, 0x4d8, phy_c30);
-	write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
-
-	kfree(phy_c32);
-	kfree(ptr);
-}
-
-static void
-wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi, u16 *values_to_save)
-{
-	int i;
-
-	and_phy_reg(pi, 0x44c, 0x0 >> 11);
-
-	and_phy_reg(pi, 0x43b, 0xC);
-
-	for (i = 0; i < 20; i++) {
-		write_radio_reg(pi, iqlo_loopback_rf_regs[i],
-				values_to_save[i]);
-	}
-}
-
-static void
-WLBANDINITFN(wlc_lcnphy_load_tx_gain_table) (phy_info_t *pi,
-					     const lcnphy_tx_gain_tbl_entry *
-					     gain_table) {
-	u32 j;
-	phytbl_info_t tab;
-	u32 val;
-	u16 pa_gain;
-	u16 gm_gain;
-
-	if (CHSPEC_IS5G(pi->radio_chanspec))
-		pa_gain = 0x70;
-	else
-		pa_gain = 0x70;
-
-	if (pi->sh->boardflags & BFL_FEM)
-		pa_gain = 0x10;
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 1;
-	tab.tbl_ptr = &val;
-
-	for (j = 0; j < 128; j++) {
-		gm_gain = gain_table[j].gm;
-		val = (((u32) pa_gain << 24) |
-		       (gain_table[j].pad << 16) |
-		       (gain_table[j].pga << 8) | gm_gain);
-
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
-		wlc_lcnphy_write_table(pi, &tab);
-
-		val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-}
-
-static void wlc_lcnphy_load_rfpower(phy_info_t *pi)
-{
-	phytbl_info_t tab;
-	u32 val, bbmult, rfgain;
-	u8 index;
-	u8 scale_factor = 1;
-	s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
-
-	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
-	tab.tbl_width = 32;
-	tab.tbl_len = 1;
-
-	for (index = 0; index < 128; index++) {
-		tab.tbl_ptr = &bbmult;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
-		wlc_lcnphy_read_table(pi, &tab);
-		bbmult = bbmult >> 20;
-
-		tab.tbl_ptr = &rfgain;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
-		wlc_lcnphy_read_table(pi, &tab);
-
-		qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
-		qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
-
-		if (qQ1 < qQ2) {
-			temp2 = qm_shr16(temp2, qQ2 - qQ1);
-			qQ = qQ1;
-		} else {
-			temp1 = qm_shr16(temp1, qQ1 - qQ2);
-			qQ = qQ2;
-		}
-		temp = qm_sub16(temp1, temp2);
-
-		if (qQ >= 4)
-			shift = qQ - 4;
-		else
-			shift = 4 - qQ;
-
-		val = (((index << shift) + (5 * temp) +
-			(1 << (scale_factor + shift - 3))) >> (scale_factor +
-							       shift - 2));
-
-		tab.tbl_ptr = &val;
-		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-}
-
-static void WLBANDINITFN(wlc_lcnphy_tbl_init) (phy_info_t *pi)
-{
-	uint idx;
-	u8 phybw40;
-	phytbl_info_t tab;
-	u32 val;
-
-	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-
-	for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
-		wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
-	}
-
-	if (pi->sh->boardflags & BFL_FEM_BT) {
-		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-		tab.tbl_width = 16;
-		tab.tbl_ptr = &val;
-		tab.tbl_len = 1;
-		val = 100;
-		tab.tbl_offset = 4;
-		wlc_lcnphy_write_table(pi, &tab);
-	}
-
-	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-	tab.tbl_width = 16;
-	tab.tbl_ptr = &val;
-	tab.tbl_len = 1;
-
-	val = 114;
-	tab.tbl_offset = 0;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	val = 130;
-	tab.tbl_offset = 1;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	val = 6;
-	tab.tbl_offset = 8;
-	wlc_lcnphy_write_table(pi, &tab);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (pi->sh->boardflags & BFL_FEM)
-			wlc_lcnphy_load_tx_gain_table(pi,
-						      dot11lcnphy_2GHz_extPA_gaintable_rev0);
-		else
-			wlc_lcnphy_load_tx_gain_table(pi,
-						      dot11lcnphy_2GHz_gaintable_rev0);
-	}
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			for (idx = 0;
-			     idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
-			     idx++)
-				if (pi->sh->boardflags & BFL_EXTLNA)
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
-							       [idx]);
-				else
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_2G_rev2
-							       [idx]);
-		} else {
-			for (idx = 0;
-			     idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
-			     idx++)
-				if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
-							       [idx]);
-				else
-					wlc_lcnphy_write_table(pi,
-							       &dot11lcnphytbl_rx_gain_info_5G_rev2
-							       [idx]);
-		}
-	}
-
-	if ((pi->sh->boardflags & BFL_FEM)
-	    && !(pi->sh->boardflags & BFL_FEM_BT))
-		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
-	else if (pi->sh->boardflags & BFL_FEM_BT) {
-		if (pi->sh->boardrev < 0x1250)
-			wlc_lcnphy_write_table(pi,
-					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
-		else
-			wlc_lcnphy_write_table(pi,
-					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
-	} else
-		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
-
-	wlc_lcnphy_load_rfpower(pi);
-
-	wlc_lcnphy_clear_papd_comptable(pi);
-}
-
-static void WLBANDINITFN(wlc_lcnphy_rev0_baseband_init) (phy_info_t *pi)
-{
-	u16 afectrl1;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
-
-	write_phy_reg(pi, 0x43b, 0x0);
-	write_phy_reg(pi, 0x43c, 0x0);
-	write_phy_reg(pi, 0x44c, 0x0);
-	write_phy_reg(pi, 0x4e6, 0x0);
-	write_phy_reg(pi, 0x4f9, 0x0);
-	write_phy_reg(pi, 0x4b0, 0x0);
-	write_phy_reg(pi, 0x938, 0x0);
-	write_phy_reg(pi, 0x4b0, 0x0);
-	write_phy_reg(pi, 0x44e, 0);
-
-	or_phy_reg(pi, 0x567, 0x03);
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-
-	if (!(pi->sh->boardflags & BFL_FEM))
-		wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
-
-	if (0) {
-		afectrl1 = 0;
-		afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
-				     (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
-								      lcnphy_rssi_gs
-								      << 10));
-		write_phy_reg(pi, 0x43e, afectrl1);
-	}
-
-	mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
-	if (pi->sh->boardflags & BFL_FEM) {
-		mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
-
-		write_phy_reg(pi, 0x910, 0x1);
-	}
-
-	mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
-	mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
-	mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
-
-}
-
-static void WLBANDINITFN(wlc_lcnphy_rev2_baseband_init) (phy_info_t *pi)
-{
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
-
-		mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
-	}
-}
-
-static void wlc_lcnphy_agc_temp_init(phy_info_t *pi)
-{
-	s16 temp;
-	phytbl_info_t tab;
-	u32 tableBuffer[2];
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	temp = (s16) read_phy_reg(pi, 0x4df);
-	pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
-
-	if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
-		pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
-
-	pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
-
-	if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
-		pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
-
-	tab.tbl_ptr = tableBuffer;
-	tab.tbl_len = 2;
-	tab.tbl_id = 17;
-	tab.tbl_offset = 59;
-	tab.tbl_width = 32;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	if (tableBuffer[0] > 63)
-		tableBuffer[0] -= 128;
-	pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
-
-	if (tableBuffer[1] > 63)
-		tableBuffer[1] -= 128;
-	pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
-
-	temp = (s16) (read_phy_reg(pi, 0x434)
-			& (0xff << 0));
-	if (temp > 127)
-		temp -= 256;
-	pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
-
-	pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
-					  & (0xff << 8))
-	    >> 8;
-	pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
-					   & (0xff << 0))
-	    >> 0;
-
-	tab.tbl_ptr = tableBuffer;
-	tab.tbl_len = 2;
-	tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
-	tab.tbl_offset = 28;
-	tab.tbl_width = 32;
-	wlc_lcnphy_read_table(pi, &tab);
-
-	pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
-	pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
-
-}
-
-static void WLBANDINITFN(wlc_lcnphy_bu_tweaks) (phy_info_t *pi)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	or_phy_reg(pi, 0x805, 0x1);
-
-	mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
-
-	mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
-
-	write_phy_reg(pi, 0x414, 0x1e10);
-	write_phy_reg(pi, 0x415, 0x0640);
-
-	mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
-
-	or_phy_reg(pi, 0x44a, 0x44);
-	write_phy_reg(pi, 0x44a, 0x80);
-	mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
-
-	mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
-
-	if (!(pi->sh->boardrev < 0x1204))
-		mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
-
-	write_phy_reg(pi, 0x7d6, 0x0902);
-	mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
-
-	mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-		mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
-
-		mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
-
-		mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
-
-		mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
-
-		mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
-
-		mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
-		mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
-		mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
-		mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
-		mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
-
-		mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
-
-		wlc_lcnphy_clear_tx_power_offsets(pi);
-		mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
-
-	}
-}
-
-static void WLBANDINITFN(wlc_lcnphy_baseband_init) (phy_info_t *pi)
-{
-
-	wlc_lcnphy_tbl_init(pi);
-	wlc_lcnphy_rev0_baseband_init(pi);
-	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
-		wlc_lcnphy_rev2_baseband_init(pi);
-	wlc_lcnphy_bu_tweaks(pi);
-}
-
-static void WLBANDINITFN(wlc_radio_2064_init) (phy_info_t *pi)
-{
-	u32 i;
-	lcnphy_radio_regs_t *lcnphyregs = NULL;
-
-	lcnphyregs = lcnphy_radio_regs_2064;
-
-	for (i = 0; lcnphyregs[i].address != 0xffff; i++)
-		if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
-			write_radio_reg(pi,
-					((lcnphyregs[i].address & 0x3fff) |
-					 RADIO_DEFAULT_CORE),
-					(u16) lcnphyregs[i].init_a);
-		else if (lcnphyregs[i].do_init_g)
-			write_radio_reg(pi,
-					((lcnphyregs[i].address & 0x3fff) |
-					 RADIO_DEFAULT_CORE),
-					(u16) lcnphyregs[i].init_g);
-
-	write_radio_reg(pi, RADIO_2064_REG032, 0x62);
-	write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-
-	write_radio_reg(pi, RADIO_2064_REG090, 0x10);
-
-	write_radio_reg(pi, RADIO_2064_REG010, 0x00);
-
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-
-		write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
-		write_radio_reg(pi, RADIO_2064_REG061, 0x72);
-		write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
-	}
-
-	write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
-	write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
-
-	mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
-
-	write_phy_reg(pi, 0x4ea, 0x4688);
-
-	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-
-	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
-
-	mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
-
-	wlc_lcnphy_set_tx_locc(pi, 0);
-
-	wlc_lcnphy_rcal(pi);
-
-	wlc_lcnphy_rc_cal(pi);
-}
-
-static void WLBANDINITFN(wlc_lcnphy_radio_init) (phy_info_t *pi)
-{
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	wlc_radio_2064_init(pi);
-}
-
-static void wlc_lcnphy_rcal(phy_info_t *pi)
-{
-	u8 rcal_value;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
-
-	or_radio_reg(pi, RADIO_2064_REG004, 0x40);
-	or_radio_reg(pi, RADIO_2064_REG120, 0x10);
-
-	or_radio_reg(pi, RADIO_2064_REG078, 0x80);
-	or_radio_reg(pi, RADIO_2064_REG129, 0x02);
-
-	or_radio_reg(pi, RADIO_2064_REG057, 0x01);
-
-	or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
-	mdelay(5);
-	SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
-
-	if (wlc_radio_2064_rcal_done(pi)) {
-		rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
-		rcal_value = rcal_value & 0x1f;
-	}
-
-	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
-
-	and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
-}
-
-static void wlc_lcnphy_rc_cal(phy_info_t *pi)
-{
-	u8 dflt_rc_cal_val;
-	u16 flt_val;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	dflt_rc_cal_val = 7;
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
-		dflt_rc_cal_val = 11;
-	flt_val =
-	    (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
-	    (dflt_rc_cal_val);
-	write_phy_reg(pi, 0x933, flt_val);
-	write_phy_reg(pi, 0x934, flt_val);
-	write_phy_reg(pi, 0x935, flt_val);
-	write_phy_reg(pi, 0x936, flt_val);
-	write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
-
-	return;
-}
-
-static bool wlc_phy_txpwr_srom_read_lcnphy(phy_info_t *pi)
-{
-	s8 txpwr = 0;
-	int i;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		u16 cckpo = 0;
-		u32 offset_ofdm, offset_mcs;
-
-		pi_lcn->lcnphy_tr_isolation_mid =
-		    (u8) PHY_GETINTVAR(pi, "triso2g");
-
-		pi_lcn->lcnphy_rx_power_offset =
-		    (u8) PHY_GETINTVAR(pi, "rxpo2g");
-
-		pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
-		pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
-		pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
-
-		pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
-		pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
-		pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
-
-		{
-			pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
-			pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
-			pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
-
-			pi_lcn->lcnphy_rssi_vf_hightemp =
-			    pi_lcn->lcnphy_rssi_vf;
-			pi_lcn->lcnphy_rssi_vc_hightemp =
-			    pi_lcn->lcnphy_rssi_vc;
-			pi_lcn->lcnphy_rssi_gs_hightemp =
-			    pi_lcn->lcnphy_rssi_gs;
-		}
-
-		txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
-		pi->tx_srom_max_2g = txpwr;
-
-		for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
-			pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
-			pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
-		}
-
-		cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
-		if (cckpo) {
-			uint max_pwr_chan = txpwr;
-
-			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
-				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
-				    ((cckpo & 0xf) * 2);
-				cckpo >>= 4;
-			}
-
-			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
-				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
-				    ((offset_ofdm & 0xf) * 2);
-				offset_ofdm >>= 4;
-			}
-		} else {
-			u8 opo = 0;
-
-			opo = (u8) PHY_GETINTVAR(pi, "opo");
-
-			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
-				pi->tx_srom_max_rate_2g[i] = txpwr;
-			}
-
-			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-
-			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
-				pi->tx_srom_max_rate_2g[i] = txpwr -
-				    ((offset_ofdm & 0xf) * 2);
-				offset_ofdm >>= 4;
-			}
-			offset_mcs =
-			    ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
-			    (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
-			pi_lcn->lcnphy_mcs20_po = offset_mcs;
-			for (i = TXP_FIRST_SISO_MCS_20;
-			     i <= TXP_LAST_SISO_MCS_20; i++) {
-				pi->tx_srom_max_rate_2g[i] =
-				    txpwr - ((offset_mcs & 0xf) * 2);
-				offset_mcs >>= 4;
-			}
-		}
-
-		pi_lcn->lcnphy_rawtempsense =
-		    (u16) PHY_GETINTVAR(pi, "rawtempsense");
-		pi_lcn->lcnphy_measPower =
-		    (u8) PHY_GETINTVAR(pi, "measpower");
-		pi_lcn->lcnphy_tempsense_slope =
-		    (u8) PHY_GETINTVAR(pi, "tempsense_slope");
-		pi_lcn->lcnphy_hw_iqcal_en =
-		    (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
-		pi_lcn->lcnphy_iqcal_swp_dis =
-		    (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
-		pi_lcn->lcnphy_tempcorrx =
-		    (u8) PHY_GETINTVAR(pi, "tempcorrx");
-		pi_lcn->lcnphy_tempsense_option =
-		    (u8) PHY_GETINTVAR(pi, "tempsense_option");
-		pi_lcn->lcnphy_freqoffset_corr =
-		    (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
-		if ((u8) getintvar(pi->vars, "aa2g") > 1)
-			wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi,
-					      (u8) getintvar(pi->vars,
-								"aa2g"));
-	}
-	pi_lcn->lcnphy_cck_dig_filt_type = -1;
-	if (PHY_GETVAR(pi, "cckdigfilttype")) {
-		s16 temp;
-		temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
-		if (temp >= 0) {
-			pi_lcn->lcnphy_cck_dig_filt_type = temp;
-		}
-	}
-
-	return true;
-}
-
-void wlc_2064_vco_cal(phy_info_t *pi)
-{
-	u8 calnrst;
-
-	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
-	calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
-	write_radio_reg(pi, RADIO_2064_REG056, calnrst);
-	udelay(1);
-	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
-	udelay(1);
-	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
-	udelay(300);
-	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
-}
-
-static void
-wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi, u8 channel)
-{
-	uint i;
-	const chan_info_2064_lcnphy_t *ci;
-	u8 rfpll_doubler = 0;
-	u8 pll_pwrup, pll_pwrup_ovr;
-	fixed qFxtal, qFref, qFvco, qFcal;
-	u8 d15, d16, f16, e44, e45;
-	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
-	u16 loop_bw, d30, setCount;
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-	ci = &chan_info_2064_lcnphy[0];
-	rfpll_doubler = 1;
-
-	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
-
-	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
-	if (!rfpll_doubler) {
-		loop_bw = PLL_2064_LOOP_BW;
-		d30 = PLL_2064_D30;
-	} else {
-		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
-		d30 = PLL_2064_D30_DOUBLER;
-	}
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
-			if (chan_info_2064_lcnphy[i].chan == channel)
-				break;
-
-		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
-			return;
-		}
-
-		ci = &chan_info_2064_lcnphy[i];
-	}
-
-	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
-
-	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
-
-	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
-
-	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
-
-	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
-		      (ci->logen_rccr_rx) << 2);
-
-	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
-
-	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
-		      (ci->pa_rxrf_lna2_freq_tune) << 4);
-
-	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
-
-	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
-	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
-
-	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
-
-	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
-	e44 = 0;
-	e45 = 0;
-
-	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
-	if (pi->xtalfreq > 26000000)
-		e44 = 1;
-	if (pi->xtalfreq > 52000000)
-		e45 = 1;
-	if (e44 == 0)
-		fcal_div = 1;
-	else if (e45 == 0)
-		fcal_div = 2;
-	else
-		fcal_div = 4;
-	fvco3 = (ci->freq * 3);
-	fref3 = 2 * fpfd;
-
-	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
-	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
-	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
-	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
-
-	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
-
-	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
-	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
-	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
-
-	d16 = (qFcal * 8 / (d15 + 1)) - 1;
-	write_radio_reg(pi, RADIO_2064_REG051, d16);
-
-	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
-	setCount = f16 * 3 * (ci->freq) / 32 - 1;
-	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
-		      (u8) (setCount >> 8));
-
-	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
-	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
-
-	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
-
-	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
-	while (div_frac >= fref3) {
-		div_int++;
-		div_frac -= fref3;
-	}
-	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
-
-	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
-		      (u8) (div_int >> 4));
-	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
-		      (u8) (div_int << 4));
-	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
-		      (u8) (div_frac >> 16));
-	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
-	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
-
-	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
-
-	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
-	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
-	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
-
-	{
-		u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
-		u16 c29, c38, c30, g30, d28;
-		c29 = loop_bw;
-		d29 = 200;
-		c38 = 1250;
-		h29 = d29 / c29;
-		h23 = 1;
-		c28 = 30;
-		d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
-			(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
-		       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
-		    + PLL_2064_LOW_END_KVCO;
-		h28_ten = (d28 * 10) / c28;
-		c30 = 2640;
-		e30 = (d30 - 680) / 490;
-		g30 = 680 + (e30 * 490);
-		h30_ten = (g30 * 10) / c30;
-		cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
-		mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
-	}
-	if (channel >= 1 && channel <= 5)
-		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
-	else
-		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
-	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
-
-	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
-	udelay(1);
-
-	wlc_2064_vco_cal(pi);
-
-	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
-	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
-	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
-		write_radio_reg(pi, RADIO_2064_REG038, 3);
-		write_radio_reg(pi, RADIO_2064_REG091, 7);
-	}
-}
-
-bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi)
-{
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
-		return 0;
-	else
-		return (LCNPHY_TX_PWR_CTRL_HW ==
-			wlc_lcnphy_get_tx_pwr_ctrl((pi)));
-}
-
-void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi)
-{
-	u16 pwr_ctrl;
-	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
-		wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
-	} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
-
-		pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-		wlc_lcnphy_txpower_recalc_target(pi);
-
-		wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
-	} else
-		return;
-}
-
-void wlc_phy_detach_lcnphy(phy_info_t *pi)
-{
-	kfree(pi->u.pi_lcnphy);
-}
-
-bool wlc_phy_attach_lcnphy(phy_info_t *pi)
-{
-	phy_info_lcnphy_t *pi_lcn;
-
-	pi->u.pi_lcnphy = kzalloc(sizeof(phy_info_lcnphy_t), GFP_ATOMIC);
-	if (pi->u.pi_lcnphy == NULL) {
-		return false;
-	}
-
-	pi_lcn = pi->u.pi_lcnphy;
-
-	if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
-		pi->hwpwrctrl = true;
-		pi->hwpwrctrl_capable = true;
-	}
-
-	pi->xtalfreq = si_alp_clock(pi->sh->sih);
-	ASSERT(0 == (pi->xtalfreq % 1000));
-
-	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
-
-	pi->pi_fptr.init = wlc_phy_init_lcnphy;
-	pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
-	pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
-	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
-	pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
-	pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
-	pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
-	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
-	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
-
-	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
-		return false;
-
-	if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
-		if (pi_lcn->lcnphy_tempsense_option == 3) {
-			pi->hwpwrctrl = true;
-			pi->hwpwrctrl_capable = true;
-			pi->temppwrctrl_capable = false;
-		} else {
-			pi->hwpwrctrl = false;
-			pi->hwpwrctrl_capable = false;
-			pi->temppwrctrl_capable = true;
-		}
-	}
-
-	return true;
-}
-
-static void wlc_lcnphy_set_rx_gain(phy_info_t *pi, u32 gain)
-{
-	u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
-
-	trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
-	ext_lna = (u16) (gain >> 29) & 0x01;
-	lna1 = (u16) (gain >> 0) & 0x0f;
-	lna2 = (u16) (gain >> 4) & 0x0f;
-	tia = (u16) (gain >> 8) & 0xf;
-	biq0 = (u16) (gain >> 12) & 0xf;
-	biq1 = (u16) (gain >> 16) & 0xf;
-
-	gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
-			     ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
-			     ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
-	gain16_19 = biq1;
-
-	mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
-	mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
-	mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
-	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
-	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-		mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
-	}
-	wlc_lcnphy_rx_gain_override_enable(pi, true);
-}
-
-static u32 wlc_lcnphy_get_receive_power(phy_info_t *pi, s32 *gain_index)
-{
-	u32 received_power = 0;
-	s32 max_index = 0;
-	u32 gain_code = 0;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	max_index = 36;
-	if (*gain_index >= 0)
-		gain_code = lcnphy_23bitgaincode_table[*gain_index];
-
-	if (-1 == *gain_index) {
-		*gain_index = 0;
-		while ((*gain_index <= (s32) max_index)
-		       && (received_power < 700)) {
-			wlc_lcnphy_set_rx_gain(pi,
-					       lcnphy_23bitgaincode_table
-					       [*gain_index]);
-			received_power =
-			    wlc_lcnphy_measure_digital_power(pi,
-							     pi_lcn->
-							     lcnphy_noise_samples);
-			(*gain_index)++;
-		}
-		(*gain_index)--;
-	} else {
-		wlc_lcnphy_set_rx_gain(pi, gain_code);
-		received_power =
-		    wlc_lcnphy_measure_digital_power(pi,
-						     pi_lcn->
-						     lcnphy_noise_samples);
-	}
-
-	return received_power;
-}
-
-s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index)
-{
-	s32 gain = 0;
-	s32 nominal_power_db;
-	s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
-	    input_power_db;
-	s32 received_power, temperature;
-	uint freq;
-	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
-
-	received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
-
-	gain = lcnphy_gain_table[gain_index];
-
-	nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
-
-	{
-		u32 power = (received_power * 16);
-		u32 msb1, msb2, val1, val2, diff1, diff2;
-		msb1 = ffs(power) - 1;
-		msb2 = msb1 + 1;
-		val1 = 1 << msb1;
-		val2 = 1 << msb2;
-		diff1 = (power - val1);
-		diff2 = (val2 - power);
-		if (diff1 < diff2)
-			log_val = msb1;
-		else
-			log_val = msb2;
-	}
-
-	log_val = log_val * 3;
-
-	gain_mismatch = (nominal_power_db / 2) - (log_val);
-
-	desired_gain = gain + gain_mismatch;
-
-	input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
-
-	if (input_power_offset_db > 127)
-		input_power_offset_db -= 256;
-
-	input_power_db = input_power_offset_db - desired_gain;
-
-	input_power_db =
-	    input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
-
-	freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
-	if ((freq > 2427) && (freq <= 2467))
-		input_power_db = input_power_db - 1;
-
-	temperature = pi_lcn->lcnphy_lastsensed_temperature;
-
-	if ((temperature - 15) < -30) {
-		input_power_db =
-		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
-		    7;
-	} else if ((temperature - 15) < 4) {
-		input_power_db =
-		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
-		    3;
-	} else {
-		input_power_db =
-		    input_power_db + (((temperature - 10 - 25) * 286) >> 12);
-	}
-
-	wlc_lcnphy_rx_gain_override_enable(pi, 0);
-
-	return input_power_db;
-}
-
-static int
-wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm, s16 filt_type)
-{
-	s16 filt_index = -1;
-	int j;
-
-	u16 addr[] = {
-		0x910,
-		0x91e,
-		0x91f,
-		0x924,
-		0x925,
-		0x926,
-		0x920,
-		0x921,
-		0x927,
-		0x928,
-		0x929,
-		0x922,
-		0x923,
-		0x930,
-		0x931,
-		0x932
-	};
-
-	u16 addr_ofdm[] = {
-		0x90f,
-		0x900,
-		0x901,
-		0x906,
-		0x907,
-		0x908,
-		0x902,
-		0x903,
-		0x909,
-		0x90a,
-		0x90b,
-		0x904,
-		0x905,
-		0x90c,
-		0x90d,
-		0x90e
-	};
-
-	if (!is_ofdm) {
-		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
-			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
-				filt_index = (s16) j;
-				break;
-			}
-		}
-
-		if (filt_index == -1) {
-			ASSERT(false);
-		} else {
-			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, addr[j],
-					      LCNPHY_txdigfiltcoeffs_cck
-					      [filt_index][j + 1]);
-			}
-		}
-	} else {
-		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
-			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
-				filt_index = (s16) j;
-				break;
-			}
-		}
-
-		if (filt_index == -1) {
-			ASSERT(false);
-		} else {
-			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, addr_ofdm[j],
-					      LCNPHY_txdigfiltcoeffs_ofdm
-					      [filt_index][j + 1]);
-			}
-		}
-	}
-
-	return (filt_index != -1) ? 0 : -1;
-}
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_lcn.h b/drivers/staging/brcm80211/phy/wlc_phy_lcn.h
deleted file mode 100644
index b7bfc72..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_lcn.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_lcn_h_
-#define _wlc_phy_lcn_h_
-
-struct phy_info_lcnphy {
-	int lcnphy_txrf_sp_9_override;
-	u8 lcnphy_full_cal_channel;
-	u8 lcnphy_cal_counter;
-	u16 lcnphy_cal_temper;
-	bool lcnphy_recal;
-
-	u8 lcnphy_rc_cap;
-	u32 lcnphy_mcs20_po;
-
-	u8 lcnphy_tr_isolation_mid;
-	u8 lcnphy_tr_isolation_low;
-	u8 lcnphy_tr_isolation_hi;
-
-	u8 lcnphy_bx_arch;
-	u8 lcnphy_rx_power_offset;
-	u8 lcnphy_rssi_vf;
-	u8 lcnphy_rssi_vc;
-	u8 lcnphy_rssi_gs;
-	u8 lcnphy_tssi_val;
-	u8 lcnphy_rssi_vf_lowtemp;
-	u8 lcnphy_rssi_vc_lowtemp;
-	u8 lcnphy_rssi_gs_lowtemp;
-
-	u8 lcnphy_rssi_vf_hightemp;
-	u8 lcnphy_rssi_vc_hightemp;
-	u8 lcnphy_rssi_gs_hightemp;
-
-	s16 lcnphy_pa0b0;
-	s16 lcnphy_pa0b1;
-	s16 lcnphy_pa0b2;
-
-	u16 lcnphy_rawtempsense;
-	u8 lcnphy_measPower;
-	u8 lcnphy_tempsense_slope;
-	u8 lcnphy_freqoffset_corr;
-	u8 lcnphy_tempsense_option;
-	u8 lcnphy_tempcorrx;
-	bool lcnphy_iqcal_swp_dis;
-	bool lcnphy_hw_iqcal_en;
-	uint lcnphy_bandedge_corr;
-	bool lcnphy_spurmod;
-	u16 lcnphy_tssi_tx_cnt;
-	u16 lcnphy_tssi_idx;
-	u16 lcnphy_tssi_npt;
-
-	u16 lcnphy_target_tx_freq;
-	s8 lcnphy_tx_power_idx_override;
-	u16 lcnphy_noise_samples;
-
-	u32 lcnphy_papdRxGnIdx;
-	u32 lcnphy_papd_rxGnCtrl_init;
-
-	u32 lcnphy_gain_idx_14_lowword;
-	u32 lcnphy_gain_idx_14_hiword;
-	u32 lcnphy_gain_idx_27_lowword;
-	u32 lcnphy_gain_idx_27_hiword;
-	s16 lcnphy_ofdmgainidxtableoffset;
-	s16 lcnphy_dsssgainidxtableoffset;
-	u32 lcnphy_tr_R_gain_val;
-	u32 lcnphy_tr_T_gain_val;
-	s8 lcnphy_input_pwr_offset_db;
-	u16 lcnphy_Med_Low_Gain_db;
-	u16 lcnphy_Very_Low_Gain_db;
-	s8 lcnphy_lastsensed_temperature;
-	s8 lcnphy_pkteng_rssi_slope;
-	u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
-	u8 lcnphy_volt_winner;
-	u8 lcnphy_volt_low;
-	u8 lcnphy_54_48_36_24mbps_backoff;
-	u8 lcnphy_11n_backoff;
-	u8 lcnphy_lowerofdm;
-	u8 lcnphy_cck;
-	u8 lcnphy_psat_2pt3_detected;
-	s32 lcnphy_lowest_Re_div_Im;
-	s8 lcnphy_final_papd_cal_idx;
-	u16 lcnphy_extstxctrl4;
-	u16 lcnphy_extstxctrl0;
-	u16 lcnphy_extstxctrl1;
-	s16 lcnphy_cck_dig_filt_type;
-	s16 lcnphy_ofdm_dig_filt_type;
-	lcnphy_cal_results_t lcnphy_cal_results;
-
-	u8 lcnphy_psat_pwr;
-	u8 lcnphy_psat_indx;
-	s32 lcnphy_min_phase;
-	u8 lcnphy_final_idx;
-	u8 lcnphy_start_idx;
-	u8 lcnphy_current_index;
-	u16 lcnphy_logen_buf_1;
-	u16 lcnphy_local_ovr_2;
-	u16 lcnphy_local_oval_6;
-	u16 lcnphy_local_oval_5;
-	u16 lcnphy_logen_mixer_1;
-
-	u8 lcnphy_aci_stat;
-	uint lcnphy_aci_start_time;
-	s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
-};
-#endif				/* _wlc_phy_lcn_h_ */
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_n.c b/drivers/staging/brcm80211/phy/wlc_phy_n.c
deleted file mode 100644
index c6cce8d..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_n.c
+++ /dev/null
@@ -1,29239 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <wlc_cfg.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <osl.h>
-#include <siutils.h>
-#include <sbchipc.h>
-#include <hndpmu.h>
-#include <bcmendian.h>
-
-#include <bcmdevs.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-
-#include <wlc_phy_radio.h>
-#include <wlc_phy_int.h>
-#include <wlc_phyreg_n.h>
-#include <wlc_phytbl_n.h>
-
-#define	READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
-	read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
-	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
-#define	WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
-	write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
-	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
-#define	WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
-	write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
-
-#define	READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
-	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
-	radio_type##_##jspace##1##_##reg_name));
-#define	WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
-	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
-	radio_type##_##jspace##1##_##reg_name), value);
-#define	READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
-	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
-	radio_type##_##reg_name##_##jspace##1));
-#define	WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
-	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
-	radio_type##_##reg_name##_##jspace##1), value);
-
-#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
-#define NPHY_ACI_CHANNEL_DELTA 5
-#define NPHY_ACI_CHANNEL_SKIP 4
-#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6
-#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5
-#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6
-#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5
-#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4
-#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3
-
-#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2
-
-#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8
-
-#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2
-
-#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8
-
-#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2
-
-#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8
-
-#define NPHY_NOISE_NOASSOC_ENTER_TH  400
-
-#define NPHY_NOISE_ASSOC_ENTER_TH  400
-
-#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH  400
-
-#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44
-#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56
-
-#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16
-
-#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8
-
-#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5)
-
-#define NPHY_RSSICAL_MAXREAD 31
-
-#define NPHY_RSSICAL_NPOLL 8
-#define NPHY_RSSICAL_MAXD  (1<<20)
-#define NPHY_MIN_RXIQ_PWR 2
-
-#define NPHY_RSSICAL_W1_TARGET 25
-#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET
-#define NPHY_RSSICAL_NB_TARGET 0
-
-#define NPHY_RSSICAL_W1_TARGET_REV3 29
-#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3
-
-#define NPHY_CALSANITY_RSSI_NB_MAX_POS  9
-#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
-#define NPHY_CALSANITY_RSSI_W1_MAX_POS  12
-#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
-#define NPHY_CALSANITY_RSSI_W2_MAX_POS  NPHY_CALSANITY_RSSI_W1_MAX_POS
-#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
-#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
-#define NPHY_RSSI_NB_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
-			       ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
-#define NPHY_RSSI_W1_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \
-			       ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG))
-#define NPHY_RSSI_W2_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \
-			       ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG))
-
-#define NPHY_IQCAL_NUMGAINS 9
-#define NPHY_N_GCTL 0x66
-
-#define NPHY_PAPD_EPS_TBL_SIZE 64
-#define NPHY_PAPD_SCL_TBL_SIZE 64
-#define NPHY_NUM_DIG_FILT_COEFFS 15
-
-#define NPHY_PAPD_COMP_OFF 0
-#define NPHY_PAPD_COMP_ON  1
-
-#define NPHY_SROM_TEMPSHIFT		32
-#define NPHY_SROM_MAXTEMPOFFSET		16
-#define NPHY_SROM_MINTEMPOFFSET		-16
-
-#define NPHY_CAL_MAXTEMPDELTA		64
-
-#define NPHY_NOISEVAR_TBLLEN40 256
-#define NPHY_NOISEVAR_TBLLEN20 128
-
-#define NPHY_ANARXLPFBW_REDUCTIONFACT 7
-
-#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
-
-typedef struct _nphy_iqcal_params {
-	u16 txlpf;
-	u16 txgm;
-	u16 pga;
-	u16 pad;
-	u16 ipa;
-	u16 cal_gain;
-	u16 ncorr[5];
-} nphy_iqcal_params_t;
-
-typedef struct _nphy_txiqcal_ladder {
-	u8 percent;
-	u8 g_env;
-} nphy_txiqcal_ladder_t;
-
-typedef struct {
-	nphy_txgains_t gains;
-	bool useindex;
-	u8 index;
-} nphy_ipa_txcalgains_t;
-
-typedef struct nphy_papd_restore_state_t {
-	u16 fbmix[2];
-	u16 vga_master[2];
-	u16 intpa_master[2];
-	u16 afectrl[2];
-	u16 afeoverride[2];
-	u16 pwrup[2];
-	u16 atten[2];
-	u16 mm;
-} nphy_papd_restore_state;
-
-typedef struct _nphy_ipa_txrxgain {
-	u16 hpvga;
-	u16 lpf_biq1;
-	u16 lpf_biq0;
-	u16 lna2;
-	u16 lna1;
-	s8 txpwrindex;
-} nphy_ipa_txrxgain_t;
-
-#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 2, 3, 3, 0, -1}
-};
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
-{0, 0, 0, 0, 0, 70},
-{0, 0, 0, 0, 0, 20},
-{0, 0, 0, 3, 0, 20},
-{0, 0, 3, 3, 0, 20},
-{0, 2, 3, 3, 0, 20}
-};
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { {0, 0, 0, 0, 0, 100},
-{0, 0, 0, 0, 0, 50},
-{0, 0, 0, 0, 0, -1},
-{0, 0, 0, 3, 0, -1},
-{0, 0, 3, 3, 0, -1},
-{0, 0, 5, 3, 0, -1}
-};
-
-nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { {0, 0, 0, 0, 0, 10},
-{0, 0, 0, 1, 0, 10},
-{0, 0, 1, 2, 0, 10},
-{0, 0, 1, 3, 0, 10},
-{0, 0, 4, 3, 0, 10},
-{0, 0, 6, 3, 0, 10}
-};
-
-#define NPHY_RXCAL_TONEAMP 181
-#define NPHY_RXCAL_TONEFREQ_40MHz 4000
-#define NPHY_RXCAL_TONEFREQ_20MHz 2000
-
-enum {
-	NPHY_RXCAL_GAIN_INIT = 0,
-	NPHY_RXCAL_GAIN_UP,
-	NPHY_RXCAL_GAIN_DOWN
-};
-
-#define wlc_phy_get_papd_nphy(pi) \
-	(read_phy_reg((pi), 0x1e7) & \
-			((0x1 << 15) | \
-			(0x1 << 14) | \
-			(0x1 << 13)))
-
-#define TXFILT_SHAPING_OFDM20   0
-#define TXFILT_SHAPING_OFDM40   1
-#define TXFILT_SHAPING_CCK      2
-#define TXFILT_DEFAULT_OFDM20   3
-#define TXFILT_DEFAULT_OFDM40   4
-
-u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
-	{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
-	 230, -44, 230, 201, -191, 201},
-	{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
-	 26, 34, -32, 34},
-	{-360, 164, -376, 164, -1533, 576, 308, -314, 308,
-	 121, -73, 121, 91, 124, 91},
-	{-295, 200, -363, 142, -1391, 826, 151, 301, 151,
-	 151, 301, 151, 602, -752, 602},
-	{-92, 58, -96, 49, -104, 44, 17, 35, 17,
-	 12, 25, 12, 13, 27, 13},
-	{-375, 136, -399, 209, -1479, 949, 130, 260, 130,
-	 230, -44, 230, 201, -191, 201},
-	{0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97,
-	 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a}
-};
-
-typedef struct _chan_info_nphy_2055 {
-	u16 chan;
-	u16 freq;
-	uint unknown;
-	u8 RF_pll_ref;
-	u8 RF_rf_pll_mod1;
-	u8 RF_rf_pll_mod0;
-	u8 RF_vco_cap_tail;
-	u8 RF_vco_cal1;
-	u8 RF_vco_cal2;
-	u8 RF_pll_lf_c1;
-	u8 RF_pll_lf_r1;
-	u8 RF_pll_lf_c2;
-	u8 RF_lgbuf_cen_buf;
-	u8 RF_lgen_tune1;
-	u8 RF_lgen_tune2;
-	u8 RF_core1_lgbuf_a_tune;
-	u8 RF_core1_lgbuf_g_tune;
-	u8 RF_core1_rxrf_reg1;
-	u8 RF_core1_tx_pga_pad_tn;
-	u8 RF_core1_tx_mx_bgtrim;
-	u8 RF_core2_lgbuf_a_tune;
-	u8 RF_core2_lgbuf_g_tune;
-	u8 RF_core2_rxrf_reg1;
-	u8 RF_core2_tx_pga_pad_tn;
-	u8 RF_core2_tx_mx_bgtrim;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_2055_t;
-
-typedef struct _chan_info_nphy_radio205x {
-	u16 chan;
-	u16 freq;
-	u8 RF_SYN_pll_vcocal1;
-	u8 RF_SYN_pll_vcocal2;
-	u8 RF_SYN_pll_refdiv;
-	u8 RF_SYN_pll_mmd2;
-	u8 RF_SYN_pll_mmd1;
-	u8 RF_SYN_pll_loopfilter1;
-	u8 RF_SYN_pll_loopfilter2;
-	u8 RF_SYN_pll_loopfilter3;
-	u8 RF_SYN_pll_loopfilter4;
-	u8 RF_SYN_pll_loopfilter5;
-	u8 RF_SYN_reserved_addr27;
-	u8 RF_SYN_reserved_addr28;
-	u8 RF_SYN_reserved_addr29;
-	u8 RF_SYN_logen_VCOBUF1;
-	u8 RF_SYN_logen_MIXER2;
-	u8 RF_SYN_logen_BUF3;
-	u8 RF_SYN_logen_BUF4;
-	u8 RF_RX0_lnaa_tune;
-	u8 RF_RX0_lnag_tune;
-	u8 RF_TX0_intpaa_boost_tune;
-	u8 RF_TX0_intpag_boost_tune;
-	u8 RF_TX0_pada_boost_tune;
-	u8 RF_TX0_padg_boost_tune;
-	u8 RF_TX0_pgaa_boost_tune;
-	u8 RF_TX0_pgag_boost_tune;
-	u8 RF_TX0_mixa_boost_tune;
-	u8 RF_TX0_mixg_boost_tune;
-	u8 RF_RX1_lnaa_tune;
-	u8 RF_RX1_lnag_tune;
-	u8 RF_TX1_intpaa_boost_tune;
-	u8 RF_TX1_intpag_boost_tune;
-	u8 RF_TX1_pada_boost_tune;
-	u8 RF_TX1_padg_boost_tune;
-	u8 RF_TX1_pgaa_boost_tune;
-	u8 RF_TX1_pgag_boost_tune;
-	u8 RF_TX1_mixa_boost_tune;
-	u8 RF_TX1_mixg_boost_tune;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_radio205x_t;
-
-typedef struct _chan_info_nphy_radio2057 {
-	u16 chan;
-	u16 freq;
-	u8 RF_vcocal_countval0;
-	u8 RF_vcocal_countval1;
-	u8 RF_rfpll_refmaster_sparextalsize;
-	u8 RF_rfpll_loopfilter_r1;
-	u8 RF_rfpll_loopfilter_c2;
-	u8 RF_rfpll_loopfilter_c1;
-	u8 RF_cp_kpd_idac;
-	u8 RF_rfpll_mmd0;
-	u8 RF_rfpll_mmd1;
-	u8 RF_vcobuf_tune;
-	u8 RF_logen_mx2g_tune;
-	u8 RF_logen_mx5g_tune;
-	u8 RF_logen_indbuf2g_tune;
-	u8 RF_logen_indbuf5g_tune;
-	u8 RF_txmix2g_tune_boost_pu_core0;
-	u8 RF_pad2g_tune_pus_core0;
-	u8 RF_pga_boost_tune_core0;
-	u8 RF_txmix5g_boost_tune_core0;
-	u8 RF_pad5g_tune_misc_pus_core0;
-	u8 RF_lna2g_tune_core0;
-	u8 RF_lna5g_tune_core0;
-	u8 RF_txmix2g_tune_boost_pu_core1;
-	u8 RF_pad2g_tune_pus_core1;
-	u8 RF_pga_boost_tune_core1;
-	u8 RF_txmix5g_boost_tune_core1;
-	u8 RF_pad5g_tune_misc_pus_core1;
-	u8 RF_lna2g_tune_core1;
-	u8 RF_lna5g_tune_core1;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_radio2057_t;
-
-typedef struct _chan_info_nphy_radio2057_rev5 {
-	u16 chan;
-	u16 freq;
-	u8 RF_vcocal_countval0;
-	u8 RF_vcocal_countval1;
-	u8 RF_rfpll_refmaster_sparextalsize;
-	u8 RF_rfpll_loopfilter_r1;
-	u8 RF_rfpll_loopfilter_c2;
-	u8 RF_rfpll_loopfilter_c1;
-	u8 RF_cp_kpd_idac;
-	u8 RF_rfpll_mmd0;
-	u8 RF_rfpll_mmd1;
-	u8 RF_vcobuf_tune;
-	u8 RF_logen_mx2g_tune;
-	u8 RF_logen_indbuf2g_tune;
-	u8 RF_txmix2g_tune_boost_pu_core0;
-	u8 RF_pad2g_tune_pus_core0;
-	u8 RF_lna2g_tune_core0;
-	u8 RF_txmix2g_tune_boost_pu_core1;
-	u8 RF_pad2g_tune_pus_core1;
-	u8 RF_lna2g_tune_core1;
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} chan_info_nphy_radio2057_rev5_t;
-
-typedef struct nphy_sfo_cfg {
-	u16 PHY_BW1a;
-	u16 PHY_BW2;
-	u16 PHY_BW3;
-	u16 PHY_BW4;
-	u16 PHY_BW5;
-	u16 PHY_BW6;
-} nphy_sfo_cfg_t;
-
-static chan_info_nphy_2055_t chan_info_nphy_2055[] = {
-	{
-	 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216},
-	{
-	 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215},
-	{
-	 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214},
-	{
-	 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213},
-	{
-	 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212},
-	{
-	 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211},
-	{
-	 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F},
-	{
-	 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E},
-	{
-	 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D},
-	{
-	 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C},
-	{
-	 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B},
-	{
-	 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A},
-	{
-	 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209},
-	{
-	 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
-	 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208},
-	{
-	 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
-	 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207},
-	{
-	 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
-	 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206},
-	{
-	 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
-	 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205},
-	{
-	 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
-	 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204},
-	{
-	 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
-	 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203},
-	{
-	 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
-	 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202},
-	{
-	 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
-	 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201},
-	{
-	 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
-	 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200},
-	{
-	 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C,
-	 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF},
-	{
-	 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
-	 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD},
-	{
-	 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
-	 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC},
-	{
-	 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
-	 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB},
-	{
-	 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
-	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
-	 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA},
-	{
-	 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
-	 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9},
-	{
-	 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
-	 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8},
-	{
-	 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
-	 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7},
-	{
-	 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
-	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
-	 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6},
-	{
-	 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
-	 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5},
-	{
-	 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
-	 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4},
-	{
-	 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
-	 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3},
-	{
-	 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
-	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
-	 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2},
-	{
-	 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
-	 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1},
-	{
-	 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
-	 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0},
-	{
-	 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
-	 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0},
-	{
-	 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
-	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
-	 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF},
-	{
-	 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
-	 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE},
-	{
-	 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
-	 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED},
-	{
-	 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
-	 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC},
-	{
-	 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
-	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
-	 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB},
-	{
-	 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
-	 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA},
-	{
-	 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
-	 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9},
-	{
-	 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
-	 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8},
-	{
-	 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
-	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
-	 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7},
-	{
-	 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
-	 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6},
-	{
-	 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
-	 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5},
-	{
-	 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
-	 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5},
-	{
-	 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
-	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
-	 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4},
-	{
-	 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
-	 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3},
-	{
-	 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
-	 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2},
-	{
-	 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
-	 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1},
-	{
-	 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
-	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
-	 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0},
-	{
-	 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF},
-	{
-	 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE},
-	{
-	 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD},
-	{
-	 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
-	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
-	 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD},
-	{
-	 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC},
-	{
-	 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB},
-	{
-	 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA},
-	{
-	 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
-	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
-	 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9},
-	{
-	 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8},
-	{
-	 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7},
-	{
-	 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7},
-	{
-	 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
-	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
-	 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6},
-	{
-	 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
-	 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5},
-	{
-	 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
-	 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4},
-	{
-	 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
-	 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3},
-	{
-	 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
-	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
-	 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2},
-	{
-	 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2},
-	{
-	 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1},
-	{
-	 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0},
-	{
-	 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF},
-	{
-	 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE},
-	{
-	 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE},
-	{
-	 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD},
-	{
-	 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC},
-	{
-	 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB},
-	{
-	 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB},
-	{
-	 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA},
-	{
-	 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA},
-	{
-	 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9},
-	{
-	 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9},
-	{
-	 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9},
-	{
-	 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8},
-	{
-	 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8},
-	{
-	 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8},
-	{
-	 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7},
-	{
-	 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7},
-	{
-	 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6},
-	{
-	 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6},
-	{
-	 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6},
-	{
-	 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5},
-	{
-	 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5},
-	{
-	 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4},
-	{
-	 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4},
-	{
-	 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4},
-	{
-	 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3},
-	{
-	 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3},
-	{
-	 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2},
-	{
-	 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2},
-	{
-	 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1},
-	{
-	 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0},
-	{
-	 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF},
-	{
-	 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF},
-	{
-	 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE},
-	{
-	 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD},
-	{
-	 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
-	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-	 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC},
-	{
-	 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D,
-	 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443},
-	{
-	 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C,
-	 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441},
-	{
-	 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
-	 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F},
-	{
-	 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
-	 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D},
-	{
-	 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C,
-	 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A},
-	{
-	 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B,
-	 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438},
-	{
-	 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A,
-	 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436},
-	{
-	 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A,
-	 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434},
-	{
-	 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09,
-	 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431},
-	{
-	 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08,
-	 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F},
-	{
-	 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08,
-	 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D},
-	{
-	 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08,
-	 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B},
-	{
-	 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07,
-	 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429},
-	{
-	 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
-	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07,
-	 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev3_2056[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
-	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
-	 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
-	 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
-	 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev4_2056_A1[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f,
-	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
-	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
-	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
-	 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f,
-	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
-	 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
-	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
-	 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
-	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
-	 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
-	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
-	 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev5_2056v5[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v6[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev5n6_2056v7[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
-	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
-	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70,
-	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
-	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
-	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
-	 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
-	 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
-	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
-	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
-	 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
-	 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
-	 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v8[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v11[] = {
-	{
-	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
-	{
-	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
-	{
-	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
-	{
-	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
-	{
-	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
-	{
-	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
-	{
-	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
-	{
-	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
-	{
-	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
-	{
-	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
-	{
-	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
-	{
-	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
-	{
-	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
-	{
-	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
-	{
-	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
-	{
-	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
-	{
-	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
-	{
-	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
-	{
-	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
-	{
-	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
-	{
-	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
-	{
-	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
-	{
-	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
-	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
-	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
-	{
-	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
-	{
-	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
-	{
-	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
-	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
-	{
-	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
-	{
-	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
-	{
-	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
-	{
-	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
-	{
-	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
-	{
-	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
-	{
-	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
-	{
-	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
-	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
-	{
-	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
-	{
-	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
-	{
-	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
-	{
-	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
-	{
-	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
-	{
-	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
-	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
-	{
-	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
-	{
-	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
-	{
-	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
-	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
-	{
-	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
-	{
-	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
-	{
-	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
-	{
-	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
-	{
-	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
-	{
-	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
-	{
-	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
-	{
-	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
-	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
-	{
-	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
-	{
-	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
-	{
-	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
-	{
-	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
-	{
-	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
-	{
-	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
-	{
-	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
-	{
-	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
-	{
-	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
-	{
-	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
-	{
-	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
-	{
-	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
-	{
-	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
-	{
-	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
-	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
-	{
-	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
-	{
-	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
-	{
-	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
-	{
-	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
-	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
-	{
-	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
-	{
-	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
-	{
-	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
-	{
-	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
-	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
-	{
-	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
-	{
-	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
-	{
-	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
-	{
-	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
-	{
-	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
-	{
-	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
-	{
-	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
-	{
-	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
-	{
-	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
-	{
-	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
-	{
-	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
-	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
-	{
-	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
-	{
-	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
-	{
-	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
-	{
-	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
-	{
-	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
-	{
-	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
-	{
-	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
-	{
-	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
-	{
-	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
-	{
-	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
-	{
-	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
-	{
-	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
-	{
-	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
-	{
-	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
-	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
-	{
-	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
-	{
-	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
-	{
-	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
-	{
-	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
-	{
-	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
-	{
-	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
-	{
-	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
-	{
-	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01,
-	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
-	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
-	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
-	{
-	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01,
-	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
-	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio2057_t chan_info_nphyrev7_2057_rev4[] = {
-	{
-	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214,
-	 0x0215,
-	 0x0216,
-	 },
-	{
-	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213,
-	 0x0214,
-	 0x0215,
-	 },
-	{
-	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212,
-	 0x0213,
-	 0x0214,
-	 },
-	{
-	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211,
-	 0x0212,
-	 0x0213,
-	 },
-	{
-	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f,
-	 0x0211,
-	 0x0212,
-	 },
-	{
-	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e,
-	 0x020f,
-	 0x0211,
-	 },
-	{
-	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d,
-	 0x020e,
-	 0x020f,
-	 },
-	{
-	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c,
-	 0x020d,
-	 0x020e,
-	 },
-	{
-	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b,
-	 0x020c,
-	 0x020d,
-	 },
-	{
-	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a,
-	 0x020b,
-	 0x020c,
-	 },
-	{
-	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209,
-	 0x020a,
-	 0x020b,
-	 },
-	{
-	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208,
-	 0x0209,
-	 0x020a,
-	 },
-	{
-	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207,
-	 0x0208,
-	 0x0209,
-	 },
-	{
-	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206,
-	 0x0207,
-	 0x0208,
-	 },
-	{
-	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00,
-	 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205,
-	 0x0206,
-	 0x0207,
-	 },
-	{
-	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204,
-	 0x0205,
-	 0x0206,
-	 },
-	{
-	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203,
-	 0x0204,
-	 0x0205,
-	 },
-	{
-	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202,
-	 0x0203,
-	 0x0204,
-	 },
-	{
-	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201,
-	 0x0202,
-	 0x0203,
-	 },
-	{
-	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200,
-	 0x0201,
-	 0x0202,
-	 },
-	{
-	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff,
-	 0x0200,
-	 0x0201,
-	 },
-	{
-	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe,
-	 0x01ff,
-	 0x0200,
-	 },
-	{
-	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd,
-	 0x01fe,
-	 0x01ff,
-	 },
-	{
-	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb,
-	 0x01fc,
-	 0x01fd,
-	 },
-	{
-	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa,
-	 0x01fb,
-	 0x01fc,
-	 },
-	{
-	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9,
-	 0x01fa,
-	 0x01fb,
-	 },
-	{
-	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8,
-	 0x01f9,
-	 0x01fa,
-	 },
-	{
-	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7,
-	 0x01f8,
-	 0x01f9,
-	 },
-	{
-	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6,
-	 0x01f7,
-	 0x01f8,
-	 },
-	{
-	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5,
-	 0x01f6,
-	 0x01f7,
-	 },
-	{
-	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4,
-	 0x01f5,
-	 0x01f6,
-	 },
-	{
-	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3,
-	 0x01f4,
-	 0x01f5,
-	 },
-	{
-	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2,
-	 0x01f3,
-	 0x01f4,
-	 },
-	{
-	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1,
-	 0x01f2,
-	 0x01f3,
-	 },
-	{
-	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
-	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0,
-	 0x01f1,
-	 0x01f2,
-	 },
-	{
-	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0,
-	 0x01f0,
-	 0x01f1,
-	 },
-	{
-	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef,
-	 0x01f0,
-	 0x01f0,
-	 },
-	{
-	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee,
-	 0x01ef,
-	 0x01f0,
-	 },
-	{
-	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed,
-	 0x01ee,
-	 0x01ef,
-	 },
-	{
-	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec,
-	 0x01ed,
-	 0x01ee,
-	 },
-	{
-	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
-	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb,
-	 0x01ec,
-	 0x01ed,
-	 },
-	{
-	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea,
-	 0x01eb,
-	 0x01ec,
-	 },
-	{
-	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9,
-	 0x01ea,
-	 0x01eb,
-	 },
-	{
-	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8,
-	 0x01e9,
-	 0x01ea,
-	 },
-	{
-	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7,
-	 0x01e8,
-	 0x01e9,
-	 },
-	{
-	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6,
-	 0x01e7,
-	 0x01e8,
-	 },
-	{
-	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00,
-	 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5,
-	 0x01e6,
-	 0x01e7,
-	 },
-	{
-	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5,
-	 0x01e5,
-	 0x01e6,
-	 },
-	{
-	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4,
-	 0x01e5,
-	 0x01e5,
-	 },
-	{
-	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3,
-	 0x01e4,
-	 0x01e5,
-	 },
-	{
-	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2,
-	 0x01e3,
-	 0x01e4,
-	 },
-	{
-	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1,
-	 0x01e2,
-	 0x01e3,
-	 },
-	{
-	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0,
-	 0x01e1,
-	 0x01e2,
-	 },
-	{
-	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00,
-	 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df,
-	 0x01e0,
-	 0x01e1,
-	 },
-	{
-	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de,
-	 0x01df,
-	 0x01e0,
-	 },
-	{
-	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd,
-	 0x01de,
-	 0x01df,
-	 },
-	{
-	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd,
-	 0x01dd,
-	 0x01de,
-	 },
-	{
-	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc,
-	 0x01dd,
-	 0x01dd,
-	 },
-	{
-	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db,
-	 0x01dc,
-	 0x01dd,
-	 },
-	{
-	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da,
-	 0x01db,
-	 0x01dc,
-	 },
-	{
-	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
-	 0x01da,
-	 0x01db,
-	 },
-	{
-	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
-	 0x01d9,
-	 0x01da,
-	 },
-	{
-	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
-	 0x01d8,
-	 0x01d9,
-	 },
-	{
-	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
-	 0x01d7,
-	 0x01d8,
-	 },
-	{
-	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
-	 0x01d7,
-	 0x01d7,
-	 },
-	{
-	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
-	 0x01d6,
-	 0x01d7,
-	 },
-	{
-	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00,
-	 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
-	 0x01d5,
-	 0x01d6,
-	 },
-	{
-	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
-	 0x01d4,
-	 0x01d5,
-	 },
-	{
-	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
-	 0x01d3,
-	 0x01d4,
-	 },
-	{
-	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
-	 0x01d2,
-	 0x01d3,
-	 },
-	{
-	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
-	 0x01d2,
-	 0x01d2,
-	 },
-	{
-	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
-	 0x01d1,
-	 0x01d2,
-	 },
-	{
-	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
-	 0x01d0,
-	 0x01d1,
-	 },
-	{
-	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
-	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
-	 0x01cf,
-	 0x01d0,
-	 },
-	{
-	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
-	 0x01ce,
-	 0x01cf,
-	 },
-	{
-	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
-	 0x01ce,
-	 0x01ce,
-	 },
-	{
-	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
-	 0x01cd,
-	 0x01ce,
-	 },
-	{
-	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
-	 0x01cc,
-	 0x01cd,
-	 },
-	{
-	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
-	 0x01cb,
-	 0x01cc,
-	 },
-	{
-	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
-	 0x01ca,
-	 0x01cb,
-	 },
-	{
-	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
-	 0x01ca,
-	 0x01cb,
-	 },
-	{
-	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
-	 0x01c9,
-	 0x01ca,
-	 },
-	{
-	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
-	 0x01c9,
-	 0x01ca,
-	 },
-	{
-	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
-	 0x01c9,
-	 0x01c9,
-	 },
-	{
-	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
-	 0x01c8,
-	 0x01c9,
-	 },
-	{
-	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
-	 0x01c8,
-	 0x01c9,
-	 },
-	{
-	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
-	 0x01c8,
-	 0x01c8,
-	 },
-	{
-	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
-	 0x01c7,
-	 0x01c8,
-	 },
-	{
-	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
-	 0x01c7,
-	 0x01c8,
-	 },
-	{
-	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
-	 0x01c6,
-	 0x01c7,
-	 },
-	{
-	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
-	 0x01c6,
-	 0x01c7,
-	 },
-	{
-	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
-	 0x01c6,
-	 0x01c6,
-	 },
-	{
-	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
-	 0x01c5,
-	 0x01c6,
-	 },
-	{
-	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
-	 0x01c5,
-	 0x01c6,
-	 },
-	{
-	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
-	 0x01c4,
-	 0x01c5,
-	 },
-	{
-	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
-	 0x01c4,
-	 0x01c5,
-	 },
-	{
-	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
-	 0x01c4,
-	 0x01c4,
-	 },
-	{
-	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
-	 0x01c3,
-	 0x01c4,
-	 },
-	{
-	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
-	 0x01c3,
-	 0x01c4,
-	 },
-	{
-	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
-	 0x01c2,
-	 0x01c3,
-	 },
-	{
-	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
-	 0x01c2,
-	 0x01c3,
-	 },
-	{
-	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
-	 0x01c2,
-	 0x01c2,
-	 },
-	{
-	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
-	 0x01c1,
-	 0x01c2,
-	 },
-	{
-	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
-	 0x01c0,
-	 0x01c1,
-	 },
-	{
-	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
-	 0x01bf,
-	 0x01c0,
-	 },
-	{
-	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
-	 0x01bf,
-	 0x01bf,
-	 },
-	{
-	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
-	 0x01be,
-	 0x01bf,
-	 },
-	{
-	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
-	 0x01bd,
-	 0x01be,
-	 },
-	{
-	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
-	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
-	 0x01bc,
-	 0x01bd,
-	 },
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
-	 0x043f,
-	 0x0443,
-	 },
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
-	 0x043d,
-	 0x0441,
-	 },
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
-	 0x043a,
-	 0x043f,
-	 },
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
-	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
-	 0x0438,
-	 0x043d,
-	 },
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
-	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
-	 0x0436,
-	 0x043a,
-	 },
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
-	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
-	 0x0434,
-	 0x0438,
-	 },
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
-	 0x0431,
-	 0x0436,
-	 },
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
-	 0x042f,
-	 0x0434,
-	 },
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
-	 0x042d,
-	 0x0431,
-	 },
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
-	 0x042b,
-	 0x042f,
-	 },
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
-	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
-	 0x0429,
-	 0x042d,
-	 },
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
-	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
-	 0x0427,
-	 0x042b,
-	 },
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
-	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
-	 0x0424,
-	 0x0429,
-	 },
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
-	 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11,
-	 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
-	 0x041f,
-	 0x0424}
-};
-
-static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev8_2057_rev5[] = {
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
-	 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
-	 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
-	 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
-	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
-	 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
-	 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
-	 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
-	 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
-	 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
-	 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
-	 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
-	 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
-	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
-	 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
-	 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
-	 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev9_2057_rev5v1[] = {
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
-	 0x043a, 0x043f, 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
-	 0x0438, 0x043d, 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
-	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
-	 0x0436, 0x043a, 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
-	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
-	 0x0434, 0x0438, 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
-	 0x0431, 0x0436, 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
-	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
-	 0x042f, 0x0434, 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
-	 0x042d, 0x0431, 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
-	 0x042b, 0x042f, 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
-	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
-	 0x0429, 0x042d, 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
-	 0x0427, 0x042b, 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
-	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
-	 0x0424, 0x0429, 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
-	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
-	 0x0422, 0x0427, 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
-	 0x0420, 0x0424, 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
-	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
-	 0x041b, 0x041f, 0x0424}
-};
-
-static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev7[] = {
-	{
-	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214,
-	 0x0215,
-	 0x0216},
-	{
-	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
-	 0x0214,
-	 0x0215},
-	{
-	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
-	 0x0213,
-	 0x0214},
-	{
-	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
-	 0x0212,
-	 0x0213},
-	{
-	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
-	 0x0211,
-	 0x0212},
-	{
-	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
-	 0x020f,
-	 0x0211},
-	{
-	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
-	 0x020e,
-	 0x020f},
-	{
-	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
-	 0x020d,
-	 0x020e},
-	{
-	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
-	 0x020c,
-	 0x020d},
-	{
-	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
-	 0x020b,
-	 0x020c},
-	{
-	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
-	 0x020a,
-	 0x020b},
-	{
-	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
-	 0x0209,
-	 0x020a},
-	{
-	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
-	 0x0208,
-	 0x0209},
-	{
-	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
-	 0x0207,
-	 0x0208},
-	{
-	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
-	 0x0206,
-	 0x0207},
-	{
-	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
-	 0x0205,
-	 0x0206},
-	{
-	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
-	 0x0204,
-	 0x0205},
-	{
-	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
-	 0x0203,
-	 0x0204},
-	{
-	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
-	 0x0202,
-	 0x0203},
-	{
-	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
-	 0x0201,
-	 0x0202},
-	{
-	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
-	 0x0200,
-	 0x0201},
-	{
-	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
-	 0x01ff,
-	 0x0200},
-	{
-	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
-	 0x01fe,
-	 0x01ff},
-	{
-	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
-	 0x01fc,
-	 0x01fd},
-	{
-	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
-	 0x01fb,
-	 0x01fc},
-	{
-	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
-	 0x01fa,
-	 0x01fb},
-	{
-	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
-	 0x01f9,
-	 0x01fa},
-	{
-	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
-	 0x01f8,
-	 0x01f9},
-	{
-	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
-	 0x01f7,
-	 0x01f8},
-	{
-	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
-	 0x01f6,
-	 0x01f7},
-	{
-	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
-	 0x01f5,
-	 0x01f6},
-	{
-	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
-	 0x01f4,
-	 0x01f5},
-	{
-	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
-	 0x01f3,
-	 0x01f4},
-	{
-	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
-	 0x01f2,
-	 0x01f3},
-	{
-	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
-	 0x01f1,
-	 0x01f2},
-	{
-	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
-	 0x01f0,
-	 0x01f1},
-	{
-	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
-	 0x01f0,
-	 0x01f0},
-	{
-	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
-	 0x01ef,
-	 0x01f0},
-	{
-	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
-	 0x01ee,
-	 0x01ef},
-	{
-	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
-	 0x01ed,
-	 0x01ee},
-	{
-	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
-	 0x01ec,
-	 0x01ed},
-	{
-	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
-	 0x01eb,
-	 0x01ec},
-	{
-	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
-	 0x01ea,
-	 0x01eb},
-	{
-	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
-	 0x01e9,
-	 0x01ea},
-	{
-	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
-	 0x01e8,
-	 0x01e9},
-	{
-	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
-	 0x01e7,
-	 0x01e8},
-	{
-	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
-	 0x01e6,
-	 0x01e7},
-	{
-	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
-	 0x01e5,
-	 0x01e6},
-	{
-	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
-	 0x01e5,
-	 0x01e5},
-	{
-	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
-	 0x01e4,
-	 0x01e5},
-	{
-	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
-	 0x01e3,
-	 0x01e4},
-	{
-	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
-	 0x01e2,
-	 0x01e3},
-	{
-	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
-	 0x01e1,
-	 0x01e2},
-	{
-	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
-	 0x01e0,
-	 0x01e1},
-	{
-	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
-	 0x01df,
-	 0x01e0},
-	{
-	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
-	 0x01de,
-	 0x01df},
-	{
-	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
-	 0x01dd,
-	 0x01de},
-	{
-	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
-	 0x01dd,
-	 0x01dd},
-	{
-	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
-	 0x01dc,
-	 0x01dd},
-	{
-	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
-	 0x01db,
-	 0x01dc},
-	{
-	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
-	 0x01da,
-	 0x01db},
-	{
-	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
-	 0x01d9,
-	 0x01da},
-	{
-	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
-	 0x01d8,
-	 0x01d9},
-	{
-	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
-	 0x01d7,
-	 0x01d8},
-	{
-	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
-	 0x01d7,
-	 0x01d7},
-	{
-	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
-	 0x01d6,
-	 0x01d7},
-	{
-	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
-	 0x01d5,
-	 0x01d6},
-	{
-	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
-	 0x01d4,
-	 0x01d5},
-	{
-	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
-	 0x01d3,
-	 0x01d4},
-	{
-	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
-	 0x01d2,
-	 0x01d3},
-	{
-	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
-	 0x01d2,
-	 0x01d2},
-	{
-	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
-	 0x01d1,
-	 0x01d2},
-	{
-	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
-	 0x01d0,
-	 0x01d1},
-	{
-	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
-	 0x01cf,
-	 0x01d0},
-	{
-	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
-	 0x01ce,
-	 0x01cf},
-	{
-	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
-	 0x01ce,
-	 0x01ce},
-	{
-	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
-	 0x01cd,
-	 0x01ce},
-	{
-	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
-	 0x01cc,
-	 0x01cd},
-	{
-	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
-	 0x01cb,
-	 0x01cc},
-	{
-	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
-	 0x01c9,
-	 0x01ca},
-	{
-	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
-	 0x01c9,
-	 0x01ca},
-	{
-	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
-	 0x01c9,
-	 0x01c9},
-	{
-	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
-	 0x01c8,
-	 0x01c9},
-	{
-	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
-	 0x01c8,
-	 0x01c9},
-	{
-	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
-	 0x01c8,
-	 0x01c8},
-	{
-	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
-	 0x01c6,
-	 0x01c7},
-	{
-	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
-	 0x01c6,
-	 0x01c7},
-	{
-	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
-	 0x01c6,
-	 0x01c6},
-	{
-	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
-	 0x01c4,
-	 0x01c5},
-	{
-	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
-	 0x01c4,
-	 0x01c5},
-	{
-	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
-	 0x01c4,
-	 0x01c4},
-	{
-	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
-	 0x01c2,
-	 0x01c3},
-	{
-	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
-	 0x01c2,
-	 0x01c3},
-	{
-	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
-	 0x01c2,
-	 0x01c2},
-	{
-	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
-	 0x01c1,
-	 0x01c2},
-	{
-	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
-	 0x01c0,
-	 0x01c1},
-	{
-	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
-	 0x01bf,
-	 0x01c0},
-	{
-	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
-	 0x01bf,
-	 0x01bf},
-	{
-	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
-	 0x01be,
-	 0x01bf},
-	{
-	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
-	 0x01bd,
-	 0x01be},
-	{
-	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
-	 0x01bc,
-	 0x01bd},
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
-	 0x043f,
-	 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
-	 0x043d,
-	 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
-	 0x043a,
-	 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
-	 0x0438,
-	 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
-	 0x0436,
-	 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
-	 0x0434,
-	 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
-	 0x0431,
-	 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
-	 0x042f,
-	 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
-	 0x042d,
-	 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
-	 0x042b,
-	 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
-	 0x0429,
-	 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
-	 0x0427,
-	 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
-	 0x0424,
-	 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
-	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
-	 0x041f,
-	 0x0424}
-};
-
-static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev8[] = {
-	{
-	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
-	 0x0214,
-	 0x0215},
-	{
-	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
-	 0x0213,
-	 0x0214},
-	{
-	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
-	 0x0212,
-	 0x0213},
-	{
-	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
-	 0x0211,
-	 0x0212},
-	{
-	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
-	 0x020f,
-	 0x0211},
-	{
-	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
-	 0x020e,
-	 0x020f},
-	{
-	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
-	 0x020d,
-	 0x020e},
-	{
-	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
-	 0x020c,
-	 0x020d},
-	{
-	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
-	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
-	 0x020b,
-	 0x020c},
-	{
-	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
-	 0x020a,
-	 0x020b},
-	{
-	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
-	 0x0209,
-	 0x020a},
-	{
-	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
-	 0x0208,
-	 0x0209},
-	{
-	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
-	 0x0207,
-	 0x0208},
-	{
-	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
-	 0x0206,
-	 0x0207},
-	{
-	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
-	 0x0205,
-	 0x0206},
-	{
-	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
-	 0x0204,
-	 0x0205},
-	{
-	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
-	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
-	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
-	 0x0203,
-	 0x0204},
-	{
-	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
-	 0x0202,
-	 0x0203},
-	{
-	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
-	 0x0201,
-	 0x0202},
-	{
-	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
-	 0x0200,
-	 0x0201},
-	{
-	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
-	 0x01ff,
-	 0x0200},
-	{
-	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
-	 0x01fe,
-	 0x01ff},
-	{
-	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
-	 0x01fc,
-	 0x01fd},
-	{
-	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
-	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
-	 0x01fb,
-	 0x01fc},
-	{
-	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
-	 0x01fa,
-	 0x01fb},
-	{
-	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
-	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
-	 0x01f9,
-	 0x01fa},
-	{
-	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
-	 0x01f8,
-	 0x01f9},
-	{
-	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
-	 0x01f7,
-	 0x01f8},
-	{
-	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
-	 0x01f6,
-	 0x01f7},
-	{
-	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
-	 0x01f5,
-	 0x01f6},
-	{
-	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
-	 0x01f4,
-	 0x01f5},
-	{
-	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
-	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
-	 0x01f3,
-	 0x01f4},
-	{
-	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
-	 0x01f2,
-	 0x01f3},
-	{
-	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
-	 0x01f1,
-	 0x01f2},
-	{
-	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
-	 0x01f0,
-	 0x01f1},
-	{
-	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
-	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
-	 0x01f0,
-	 0x01f0},
-	{
-	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
-	 0x01ef,
-	 0x01f0},
-	{
-	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
-	 0x01ee,
-	 0x01ef},
-	{
-	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
-	 0x01ed,
-	 0x01ee},
-	{
-	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
-	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
-	 0x01ec,
-	 0x01ed},
-	{
-	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
-	 0x01eb,
-	 0x01ec},
-	{
-	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
-	 0x01ea,
-	 0x01eb},
-	{
-	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
-	 0x01e9,
-	 0x01ea},
-	{
-	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
-	 0x01e8,
-	 0x01e9},
-	{
-	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
-	 0x01e7,
-	 0x01e8},
-	{
-	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
-	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
-	 0x01e6,
-	 0x01e7},
-	{
-	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
-	 0x01e5,
-	 0x01e6},
-	{
-	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
-	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
-	 0x01e5,
-	 0x01e5},
-	{
-	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
-	 0x01e4,
-	 0x01e5},
-	{
-	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
-	 0x01e3,
-	 0x01e4},
-	{
-	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
-	 0x01e2,
-	 0x01e3},
-	{
-	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
-	 0x01e1,
-	 0x01e2},
-	{
-	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
-	 0x01e0,
-	 0x01e1},
-	{
-	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
-	 0x01df,
-	 0x01e0},
-	{
-	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
-	 0x01de,
-	 0x01df},
-	{
-	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
-	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
-	 0x01dd,
-	 0x01de},
-	{
-	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
-	 0x01dd,
-	 0x01dd},
-	{
-	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
-	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
-	 0x01dc,
-	 0x01dd},
-	{
-	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
-	 0x01db,
-	 0x01dc},
-	{
-	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
-	 0x01da,
-	 0x01db},
-	{
-	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
-	 0x01d9,
-	 0x01da},
-	{
-	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
-	 0x01d8,
-	 0x01d9},
-	{
-	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
-	 0x01d7,
-	 0x01d8},
-	{
-	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
-	 0x01d7,
-	 0x01d7},
-	{
-	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
-	 0x01d6,
-	 0x01d7},
-	{
-	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
-	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
-	 0x01d5,
-	 0x01d6},
-	{
-	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
-	 0x01d4,
-	 0x01d5},
-	{
-	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
-	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
-	 0x01d3,
-	 0x01d4},
-	{
-	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
-	 0x01d2,
-	 0x01d3},
-	{
-	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
-	 0x01d2,
-	 0x01d2},
-	{
-	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
-	 0x01d1,
-	 0x01d2},
-	{
-	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
-	 0x01d0,
-	 0x01d1},
-	{
-	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
-	 0x01cf,
-	 0x01d0},
-	{
-	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
-	 0x01ce,
-	 0x01cf},
-	{
-	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
-	 0x01ce,
-	 0x01ce},
-	{
-	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
-	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
-	 0x01cd,
-	 0x01ce},
-	{
-	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
-	 0x01cc,
-	 0x01cd},
-	{
-	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
-	 0x01cb,
-	 0x01cc},
-	{
-	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
-	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
-	 0x01ca,
-	 0x01cb},
-	{
-	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
-	 0x01c9,
-	 0x01ca},
-	{
-	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
-	 0x01c9,
-	 0x01ca},
-	{
-	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
-	 0x01c9,
-	 0x01c9},
-	{
-	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
-	 0x01c8,
-	 0x01c9},
-	{
-	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
-	 0x01c8,
-	 0x01c9},
-	{
-	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
-	 0x01c8,
-	 0x01c8},
-	{
-	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
-	 0x01c7,
-	 0x01c8},
-	{
-	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
-	 0x01c6,
-	 0x01c7},
-	{
-	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
-	 0x01c6,
-	 0x01c7},
-	{
-	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
-	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
-	 0x01c6,
-	 0x01c6},
-	{
-	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
-	 0x01c5,
-	 0x01c6},
-	{
-	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
-	 0x01c4,
-	 0x01c5},
-	{
-	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
-	 0x01c4,
-	 0x01c5},
-	{
-	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
-	 0x01c4,
-	 0x01c4},
-	{
-	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
-	 0x01c3,
-	 0x01c4},
-	{
-	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
-	 0x01c2,
-	 0x01c3},
-	{
-	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
-	 0x01c2,
-	 0x01c3},
-	{
-	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
-	 0x01c2,
-	 0x01c2},
-	{
-	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
-	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
-	 0x01c1,
-	 0x01c2},
-	{
-	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
-	 0x01c0,
-	 0x01c1},
-	{
-	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
-	 0x01bf,
-	 0x01c0},
-	{
-	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
-	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
-	 0x01bf,
-	 0x01bf},
-	{
-	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
-	 0x01be,
-	 0x01bf},
-	{
-	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
-	 0x01bd,
-	 0x01be},
-	{
-	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
-	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
-	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
-	 0x01bc,
-	 0x01bd},
-	{
-	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
-	 0x043f,
-	 0x0443},
-	{
-	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
-	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
-	 0x043d,
-	 0x0441},
-	{
-	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
-	 0x043a,
-	 0x043f},
-	{
-	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
-	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
-	 0x0438,
-	 0x043d},
-	{
-	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
-	 0x0436,
-	 0x043a},
-	{
-	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
-	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
-	 0x0434,
-	 0x0438},
-	{
-	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
-	 0x0431,
-	 0x0436},
-	{
-	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
-	 0x042f,
-	 0x0434},
-	{
-	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
-	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
-	 0x042d,
-	 0x0431},
-	{
-	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
-	 0x042b,
-	 0x042f},
-	{
-	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
-	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
-	 0x0429,
-	 0x042d},
-	{
-	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
-	 0x0427,
-	 0x042b},
-	{
-	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
-	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
-	 0x0424,
-	 0x0429},
-	{
-	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
-	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
-	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
-	 0x041f,
-	 0x0424}
-};
-
-radio_regs_t regs_2055[] = {
-	{0x02, 0x80, 0x80, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0x27, 0x27, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0x27, 0x27, 0, 0},
-	{0x07, 0x7f, 0x7f, 1, 1},
-	{0x08, 0x7, 0x7, 1, 1},
-	{0x09, 0x7f, 0x7f, 1, 1},
-	{0x0A, 0x7, 0x7, 1, 1},
-	{0x0B, 0x15, 0x15, 0, 0},
-	{0x0C, 0x15, 0x15, 0, 0},
-	{0x0D, 0x4f, 0x4f, 1, 1},
-	{0x0E, 0x5, 0x5, 1, 1},
-	{0x0F, 0x4f, 0x4f, 1, 1},
-	{0x10, 0x5, 0x5, 1, 1},
-	{0x11, 0xd0, 0xd0, 0, 0},
-	{0x12, 0x2, 0x2, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0x40, 0x40, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0xc0, 0xc0, 0, 0},
-	{0x1E, 0xff, 0xff, 0, 0},
-	{0x1F, 0xc0, 0xc0, 0, 0},
-	{0x20, 0xff, 0xff, 0, 0},
-	{0x21, 0xc0, 0xc0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x2c, 0x2c, 0, 0},
-	{0x24, 0, 0, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0xa4, 0xa4, 0, 0},
-	{0x2E, 0x38, 0x38, 0, 0},
-	{0x2F, 0, 0, 0, 0},
-	{0x30, 0x4, 0x4, 1, 1},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0xa, 0xa, 0, 0},
-	{0x33, 0x87, 0x87, 0, 0},
-	{0x34, 0x9, 0x9, 0, 0},
-	{0x35, 0x70, 0x70, 0, 0},
-	{0x36, 0x11, 0x11, 0, 0},
-	{0x37, 0x18, 0x18, 1, 1},
-	{0x38, 0x6, 0x6, 0, 0},
-	{0x39, 0x4, 0x4, 1, 1},
-	{0x3A, 0x6, 0x6, 0, 0},
-	{0x3B, 0x9e, 0x9e, 0, 0},
-	{0x3C, 0x9, 0x9, 0, 0},
-	{0x3D, 0xc8, 0xc8, 1, 1},
-	{0x3E, 0x88, 0x88, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0, 0, 0, 0},
-	{0x42, 0x1, 0x1, 0, 0},
-	{0x43, 0x2, 0x2, 0, 0},
-	{0x44, 0x96, 0x96, 0, 0},
-	{0x45, 0x3e, 0x3e, 0, 0},
-	{0x46, 0x3e, 0x3e, 0, 0},
-	{0x47, 0x13, 0x13, 0, 0},
-	{0x48, 0x2, 0x2, 0, 0},
-	{0x49, 0x15, 0x15, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0, 0, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0, 0, 0, 0},
-	{0x50, 0x8, 0x8, 0, 0},
-	{0x51, 0x8, 0x8, 0, 0},
-	{0x52, 0x6, 0x6, 0, 0},
-	{0x53, 0x84, 0x84, 1, 1},
-	{0x54, 0xc3, 0xc3, 0, 0},
-	{0x55, 0x8f, 0x8f, 0, 0},
-	{0x56, 0xff, 0xff, 0, 0},
-	{0x57, 0xff, 0xff, 0, 0},
-	{0x58, 0x88, 0x88, 0, 0},
-	{0x59, 0x88, 0x88, 0, 0},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0xcc, 0xcc, 0, 0},
-	{0x5C, 0x6, 0x6, 0, 0},
-	{0x5D, 0x80, 0x80, 0, 0},
-	{0x5E, 0x80, 0x80, 0, 0},
-	{0x5F, 0xf8, 0xf8, 0, 0},
-	{0x60, 0x88, 0x88, 0, 0},
-	{0x61, 0x88, 0x88, 0, 0},
-	{0x62, 0x88, 0x8, 1, 1},
-	{0x63, 0x88, 0x88, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0x1, 0x1, 1, 1},
-	{0x66, 0x8a, 0x8a, 0, 0},
-	{0x67, 0x8, 0x8, 0, 0},
-	{0x68, 0x83, 0x83, 0, 0},
-	{0x69, 0x6, 0x6, 0, 0},
-	{0x6A, 0xa0, 0xa0, 0, 0},
-	{0x6B, 0xa, 0xa, 0, 0},
-	{0x6C, 0x87, 0x87, 1, 1},
-	{0x6D, 0x2a, 0x2a, 0, 0},
-	{0x6E, 0x2a, 0x2a, 0, 0},
-	{0x6F, 0x2a, 0x2a, 0, 0},
-	{0x70, 0x2a, 0x2a, 0, 0},
-	{0x71, 0x18, 0x18, 0, 0},
-	{0x72, 0x6a, 0x6a, 1, 1},
-	{0x73, 0xab, 0xab, 1, 1},
-	{0x74, 0x13, 0x13, 1, 1},
-	{0x75, 0xc1, 0xc1, 1, 1},
-	{0x76, 0xaa, 0xaa, 1, 1},
-	{0x77, 0x87, 0x87, 1, 1},
-	{0x78, 0, 0, 0, 0},
-	{0x79, 0x6, 0x6, 0, 0},
-	{0x7A, 0x7, 0x7, 0, 0},
-	{0x7B, 0x7, 0x7, 0, 0},
-	{0x7C, 0x15, 0x15, 0, 0},
-	{0x7D, 0x55, 0x55, 0, 0},
-	{0x7E, 0x97, 0x97, 1, 1},
-	{0x7F, 0x8, 0x8, 0, 0},
-	{0x80, 0x14, 0x14, 1, 1},
-	{0x81, 0x33, 0x33, 0, 0},
-	{0x82, 0x88, 0x88, 0, 0},
-	{0x83, 0x6, 0x6, 0, 0},
-	{0x84, 0x3, 0x3, 1, 1},
-	{0x85, 0xa, 0xa, 0, 0},
-	{0x86, 0x3, 0x3, 1, 1},
-	{0x87, 0x2a, 0x2a, 0, 0},
-	{0x88, 0xa4, 0xa4, 0, 0},
-	{0x89, 0x18, 0x18, 0, 0},
-	{0x8A, 0x28, 0x28, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0x4a, 0x4a, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0xf8, 0xf8, 0, 0},
-	{0x8F, 0x88, 0x88, 0, 0},
-	{0x90, 0x88, 0x88, 0, 0},
-	{0x91, 0x88, 0x8, 1, 1},
-	{0x92, 0x88, 0x88, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0x1, 0x1, 1, 1},
-	{0x95, 0x8a, 0x8a, 0, 0},
-	{0x96, 0x8, 0x8, 0, 0},
-	{0x97, 0x83, 0x83, 0, 0},
-	{0x98, 0x6, 0x6, 0, 0},
-	{0x99, 0xa0, 0xa0, 0, 0},
-	{0x9A, 0xa, 0xa, 0, 0},
-	{0x9B, 0x87, 0x87, 1, 1},
-	{0x9C, 0x2a, 0x2a, 0, 0},
-	{0x9D, 0x2a, 0x2a, 0, 0},
-	{0x9E, 0x2a, 0x2a, 0, 0},
-	{0x9F, 0x2a, 0x2a, 0, 0},
-	{0xA0, 0x18, 0x18, 0, 0},
-	{0xA1, 0x6a, 0x6a, 1, 1},
-	{0xA2, 0xab, 0xab, 1, 1},
-	{0xA3, 0x13, 0x13, 1, 1},
-	{0xA4, 0xc1, 0xc1, 1, 1},
-	{0xA5, 0xaa, 0xaa, 1, 1},
-	{0xA6, 0x87, 0x87, 1, 1},
-	{0xA7, 0, 0, 0, 0},
-	{0xA8, 0x6, 0x6, 0, 0},
-	{0xA9, 0x7, 0x7, 0, 0},
-	{0xAA, 0x7, 0x7, 0, 0},
-	{0xAB, 0x15, 0x15, 0, 0},
-	{0xAC, 0x55, 0x55, 0, 0},
-	{0xAD, 0x97, 0x97, 1, 1},
-	{0xAE, 0x8, 0x8, 0, 0},
-	{0xAF, 0x14, 0x14, 1, 1},
-	{0xB0, 0x33, 0x33, 0, 0},
-	{0xB1, 0x88, 0x88, 0, 0},
-	{0xB2, 0x6, 0x6, 0, 0},
-	{0xB3, 0x3, 0x3, 1, 1},
-	{0xB4, 0xa, 0xa, 0, 0},
-	{0xB5, 0x3, 0x3, 1, 1},
-	{0xB6, 0x2a, 0x2a, 0, 0},
-	{0xB7, 0xa4, 0xa4, 0, 0},
-	{0xB8, 0x18, 0x18, 0, 0},
-	{0xB9, 0x28, 0x28, 0, 0},
-	{0xBA, 0, 0, 0, 0},
-	{0xBB, 0x4a, 0x4a, 0, 0},
-	{0xBC, 0, 0, 0, 0},
-	{0xBD, 0x71, 0x71, 0, 0},
-	{0xBE, 0x72, 0x72, 0, 0},
-	{0xBF, 0x73, 0x73, 0, 0},
-	{0xC0, 0x74, 0x74, 0, 0},
-	{0xC1, 0x75, 0x75, 0, 0},
-	{0xC2, 0x76, 0x76, 0, 0},
-	{0xC3, 0x77, 0x77, 0, 0},
-	{0xC4, 0x78, 0x78, 0, 0},
-	{0xC5, 0x79, 0x79, 0, 0},
-	{0xC6, 0x7a, 0x7a, 0, 0},
-	{0xC7, 0, 0, 0, 0},
-	{0xC8, 0, 0, 0, 0},
-	{0xC9, 0, 0, 0, 0},
-	{0xCA, 0, 0, 0, 0},
-	{0xCB, 0, 0, 0, 0},
-	{0xCC, 0, 0, 0, 0},
-	{0xCD, 0, 0, 0, 0},
-	{0xCE, 0x6, 0x6, 0, 0},
-	{0xCF, 0, 0, 0, 0},
-	{0xD0, 0, 0, 0, 0},
-	{0xD1, 0x18, 0x18, 0, 0},
-	{0xD2, 0x88, 0x88, 0, 0},
-	{0xD3, 0, 0, 0, 0},
-	{0xD4, 0, 0, 0, 0},
-	{0xD5, 0, 0, 0, 0},
-	{0xD6, 0, 0, 0, 0},
-	{0xD7, 0, 0, 0, 0},
-	{0xD8, 0, 0, 0, 0},
-	{0xD9, 0, 0, 0, 0},
-	{0xDA, 0x6, 0x6, 0, 0},
-	{0xDB, 0, 0, 0, 0},
-	{0xDC, 0, 0, 0, 0},
-	{0xDD, 0x18, 0x18, 0, 0},
-	{0xDE, 0x88, 0x88, 0, 0},
-	{0xDF, 0, 0, 0, 0},
-	{0xE0, 0, 0, 0, 0},
-	{0xE1, 0, 0, 0, 0},
-	{0xE2, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_SYN_2056[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0xd, 0xd, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0x11, 0x11, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0xf, 0xf, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x2d, 0x2d, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0x74, 0x74, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x99, 0x99, 0, 0},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x44, 0x44, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0xf, 0xf, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0x50, 0x50, 1, 1},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x99, 0x99, 0, 0},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x66, 0x66, 0, 0},
-	{0x50, 0x66, 0x66, 0, 0},
-	{0x51, 0x57, 0x57, 0, 0},
-	{0x52, 0x57, 0x57, 0, 0},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x23, 0x23, 0, 0},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0x2, 0x2, 0, 0},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_A1[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0xd, 0xd, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056_A1[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0x11, 0x11, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0xf, 0xf, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x2d, 0x2d, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0x72, 0x72, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056_A1[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x44, 0x44, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0xf, 0xf, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0x50, 0x50, 1, 1},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x2f, 0x2f, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_rev5[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056_rev5[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0x11, 0x11, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0xf, 0xf, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x2d, 0x2d, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x71, 0x71, 1, 1},
-	{0x96, 0x71, 0x71, 1, 1},
-	{0x97, 0x72, 0x72, 1, 1},
-	{0x98, 0x73, 0x73, 1, 1},
-	{0x99, 0x74, 0x74, 1, 1},
-	{0x9A, 0x75, 0x75, 1, 1},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056_rev5[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 1, 1},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0, 0, 1, 1},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_rev6[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_TX_2056_rev6[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x70, 0x70, 0, 0},
-	{0x96, 0x70, 0x70, 0, 0},
-	{0x97, 0x70, 0x70, 0, 0},
-	{0x98, 0x70, 0x70, 0, 0},
-	{0x99, 0x70, 0x70, 0, 0},
-	{0x9A, 0x70, 0x70, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_RX_2056_rev6[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0x5, 0x5, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0}
-};
-
-radio_regs_t regs_SYN_2056_rev7[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_TX_2056_rev7[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x71, 0x71, 1, 1},
-	{0x96, 0x71, 0x71, 1, 1},
-	{0x97, 0x72, 0x72, 1, 1},
-	{0x98, 0x73, 0x73, 1, 1},
-	{0x99, 0x74, 0x74, 1, 1},
-	{0x9A, 0x75, 0x75, 1, 1},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_RX_2056_rev7[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 1, 1},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0, 0, 1, 1},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_SYN_2056_rev8[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x4, 0x4, 0, 0},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x30, 0x30, 0, 0},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0xd, 0xd, 0, 0},
-	{0x4C, 0xd, 0xd, 0, 0},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x6, 0x6, 0, 0},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_TX_2056_rev8[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x70, 0x70, 0, 0},
-	{0x96, 0x70, 0x70, 0, 0},
-	{0x97, 0x70, 0x70, 0, 0},
-	{0x98, 0x70, 0x70, 0, 0},
-	{0x99, 0x70, 0x70, 0, 0},
-	{0x9A, 0x70, 0x70, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_RX_2056_rev8[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0x5, 0x5, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_SYN_2056_rev11[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0x1, 0x1, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0x60, 0x60, 0, 0},
-	{0x23, 0x6, 0x6, 0, 0},
-	{0x24, 0xc, 0xc, 0, 0},
-	{0x25, 0, 0, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0, 0, 0, 0},
-	{0x28, 0x1, 0x1, 0, 0},
-	{0x29, 0, 0, 0, 0},
-	{0x2A, 0, 0, 0, 0},
-	{0x2B, 0, 0, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0, 0, 0, 0},
-	{0x2F, 0x1f, 0x1f, 0, 0},
-	{0x30, 0x15, 0x15, 0, 0},
-	{0x31, 0xf, 0xf, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0, 0, 0, 0},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0, 0, 0, 0},
-	{0x38, 0, 0, 0, 0},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0, 0, 0, 0},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x13, 0x13, 0, 0},
-	{0x3D, 0xf, 0xf, 0, 0},
-	{0x3E, 0x18, 0x18, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x20, 0x20, 0, 0},
-	{0x42, 0x20, 0x20, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x77, 0x77, 0, 0},
-	{0x45, 0x7, 0x7, 0, 0},
-	{0x46, 0x1, 0x1, 0, 0},
-	{0x47, 0x6, 0x6, 1, 1},
-	{0x48, 0xf, 0xf, 0, 0},
-	{0x49, 0x3f, 0x3f, 1, 1},
-	{0x4A, 0x32, 0x32, 0, 0},
-	{0x4B, 0x6, 0x6, 1, 1},
-	{0x4C, 0x6, 0x6, 1, 1},
-	{0x4D, 0x4, 0x4, 0, 0},
-	{0x4E, 0x2b, 0x2b, 1, 1},
-	{0x4F, 0x1, 0x1, 0, 0},
-	{0x50, 0x1c, 0x1c, 0, 0},
-	{0x51, 0x2, 0x2, 0, 0},
-	{0x52, 0x2, 0x2, 0, 0},
-	{0x53, 0xf7, 0xf7, 1, 1},
-	{0x54, 0xb4, 0xb4, 0, 0},
-	{0x55, 0xd2, 0xd2, 0, 0},
-	{0x56, 0, 0, 0, 0},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x4, 0x4, 0, 0},
-	{0x59, 0x96, 0x96, 0, 0},
-	{0x5A, 0x3e, 0x3e, 0, 0},
-	{0x5B, 0x3e, 0x3e, 0, 0},
-	{0x5C, 0x13, 0x13, 0, 0},
-	{0x5D, 0x2, 0x2, 0, 0},
-	{0x5E, 0, 0, 0, 0},
-	{0x5F, 0x7, 0x7, 0, 0},
-	{0x60, 0x7, 0x7, 1, 1},
-	{0x61, 0x8, 0x8, 0, 0},
-	{0x62, 0x3, 0x3, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0x40, 0x40, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0x1, 0x1, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0x60, 0x60, 0, 0},
-	{0x71, 0x66, 0x66, 0, 0},
-	{0x72, 0xc, 0xc, 0, 0},
-	{0x73, 0x66, 0x66, 0, 0},
-	{0x74, 0x8f, 0x8f, 1, 1},
-	{0x75, 0, 0, 0, 0},
-	{0x76, 0xcc, 0xcc, 0, 0},
-	{0x77, 0x1, 0x1, 0, 0},
-	{0x78, 0x66, 0x66, 0, 0},
-	{0x79, 0x66, 0x66, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0, 0, 0, 0},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0xff, 0xff, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0x95, 0, 0, 0, 0},
-	{0x96, 0, 0, 0, 0},
-	{0x97, 0, 0, 0, 0},
-	{0x98, 0, 0, 0, 0},
-	{0x99, 0, 0, 0, 0},
-	{0x9A, 0, 0, 0, 0},
-	{0x9B, 0, 0, 0, 0},
-	{0x9C, 0, 0, 0, 0},
-	{0x9D, 0, 0, 0, 0},
-	{0x9E, 0, 0, 0, 0},
-	{0x9F, 0x6, 0x6, 0, 0},
-	{0xA0, 0x66, 0x66, 0, 0},
-	{0xA1, 0x66, 0x66, 0, 0},
-	{0xA2, 0x66, 0x66, 0, 0},
-	{0xA3, 0x66, 0x66, 0, 0},
-	{0xA4, 0x66, 0x66, 0, 0},
-	{0xA5, 0x66, 0x66, 0, 0},
-	{0xA6, 0x66, 0x66, 0, 0},
-	{0xA7, 0x66, 0x66, 0, 0},
-	{0xA8, 0x66, 0x66, 0, 0},
-	{0xA9, 0x66, 0x66, 0, 0},
-	{0xAA, 0x66, 0x66, 0, 0},
-	{0xAB, 0x66, 0x66, 0, 0},
-	{0xAC, 0x66, 0x66, 0, 0},
-	{0xAD, 0x66, 0x66, 0, 0},
-	{0xAE, 0x66, 0x66, 0, 0},
-	{0xAF, 0x66, 0x66, 0, 0},
-	{0xB0, 0x66, 0x66, 0, 0},
-	{0xB1, 0x66, 0x66, 0, 0},
-	{0xB2, 0x66, 0x66, 0, 0},
-	{0xB3, 0xa, 0xa, 0, 0},
-	{0xB4, 0, 0, 0, 0},
-	{0xB5, 0, 0, 0, 0},
-	{0xB6, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_TX_2056_rev11[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0, 0, 0, 0},
-	{0x21, 0x88, 0x88, 0, 0},
-	{0x22, 0x88, 0x88, 0, 0},
-	{0x23, 0x88, 0x88, 0, 0},
-	{0x24, 0x88, 0x88, 0, 0},
-	{0x25, 0xc, 0xc, 0, 0},
-	{0x26, 0, 0, 0, 0},
-	{0x27, 0x3, 0x3, 0, 0},
-	{0x28, 0, 0, 0, 0},
-	{0x29, 0x3, 0x3, 0, 0},
-	{0x2A, 0x37, 0x37, 0, 0},
-	{0x2B, 0x3, 0x3, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0, 0, 0, 0},
-	{0x2E, 0x1, 0x1, 0, 0},
-	{0x2F, 0x1, 0x1, 0, 0},
-	{0x30, 0, 0, 0, 0},
-	{0x31, 0, 0, 0, 0},
-	{0x32, 0, 0, 0, 0},
-	{0x33, 0x11, 0x11, 0, 0},
-	{0x34, 0xee, 0xee, 1, 1},
-	{0x35, 0, 0, 0, 0},
-	{0x36, 0, 0, 0, 0},
-	{0x37, 0x3, 0x3, 0, 0},
-	{0x38, 0x50, 0x50, 1, 1},
-	{0x39, 0, 0, 0, 0},
-	{0x3A, 0x50, 0x50, 1, 1},
-	{0x3B, 0, 0, 0, 0},
-	{0x3C, 0x6e, 0x6e, 0, 0},
-	{0x3D, 0xf0, 0xf0, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0, 0, 0, 0},
-	{0x40, 0, 0, 0, 0},
-	{0x41, 0x3, 0x3, 0, 0},
-	{0x42, 0x3, 0x3, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x1e, 0x1e, 0, 0},
-	{0x45, 0, 0, 0, 0},
-	{0x46, 0x6e, 0x6e, 0, 0},
-	{0x47, 0xf0, 0xf0, 1, 1},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x2, 0x2, 0, 0},
-	{0x4A, 0xff, 0xff, 1, 1},
-	{0x4B, 0xc, 0xc, 0, 0},
-	{0x4C, 0, 0, 0, 0},
-	{0x4D, 0x38, 0x38, 0, 0},
-	{0x4E, 0x70, 0x70, 1, 1},
-	{0x4F, 0x2, 0x2, 0, 0},
-	{0x50, 0x88, 0x88, 0, 0},
-	{0x51, 0xc, 0xc, 0, 0},
-	{0x52, 0, 0, 0, 0},
-	{0x53, 0x8, 0x8, 0, 0},
-	{0x54, 0x70, 0x70, 1, 1},
-	{0x55, 0x2, 0x2, 0, 0},
-	{0x56, 0xff, 0xff, 1, 1},
-	{0x57, 0, 0, 0, 0},
-	{0x58, 0x83, 0x83, 0, 0},
-	{0x59, 0x77, 0x77, 1, 1},
-	{0x5A, 0, 0, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x88, 0x88, 0, 0},
-	{0x5D, 0, 0, 0, 0},
-	{0x5E, 0x8, 0x8, 0, 0},
-	{0x5F, 0x77, 0x77, 1, 1},
-	{0x60, 0x1, 0x1, 0, 0},
-	{0x61, 0, 0, 0, 0},
-	{0x62, 0x7, 0x7, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0x7, 0x7, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 1, 1},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0xa, 0xa, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0, 0, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0x2, 0x2, 0, 0},
-	{0x72, 0, 0, 0, 0},
-	{0x73, 0, 0, 0, 0},
-	{0x74, 0xe, 0xe, 0, 0},
-	{0x75, 0xe, 0xe, 0, 0},
-	{0x76, 0xe, 0xe, 0, 0},
-	{0x77, 0x13, 0x13, 0, 0},
-	{0x78, 0x13, 0x13, 0, 0},
-	{0x79, 0x1b, 0x1b, 0, 0},
-	{0x7A, 0x1b, 0x1b, 0, 0},
-	{0x7B, 0x55, 0x55, 0, 0},
-	{0x7C, 0x5b, 0x5b, 0, 0},
-	{0x7D, 0x30, 0x30, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0x70, 0x70, 0, 0},
-	{0x94, 0x70, 0x70, 0, 0},
-	{0x95, 0x70, 0x70, 0, 0},
-	{0x96, 0x70, 0x70, 0, 0},
-	{0x97, 0x70, 0x70, 0, 0},
-	{0x98, 0x70, 0x70, 0, 0},
-	{0x99, 0x70, 0x70, 0, 0},
-	{0x9A, 0x70, 0x70, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_regs_t regs_RX_2056_rev11[] = {
-	{0x02, 0, 0, 0, 0},
-	{0x03, 0, 0, 0, 0},
-	{0x04, 0, 0, 0, 0},
-	{0x05, 0, 0, 0, 0},
-	{0x06, 0, 0, 0, 0},
-	{0x07, 0, 0, 0, 0},
-	{0x08, 0, 0, 0, 0},
-	{0x09, 0, 0, 0, 0},
-	{0x0A, 0, 0, 0, 0},
-	{0x0B, 0, 0, 0, 0},
-	{0x0C, 0, 0, 0, 0},
-	{0x0D, 0, 0, 0, 0},
-	{0x0E, 0, 0, 0, 0},
-	{0x0F, 0, 0, 0, 0},
-	{0x10, 0, 0, 0, 0},
-	{0x11, 0, 0, 0, 0},
-	{0x12, 0, 0, 0, 0},
-	{0x13, 0, 0, 0, 0},
-	{0x14, 0, 0, 0, 0},
-	{0x15, 0, 0, 0, 0},
-	{0x16, 0, 0, 0, 0},
-	{0x17, 0, 0, 0, 0},
-	{0x18, 0, 0, 0, 0},
-	{0x19, 0, 0, 0, 0},
-	{0x1A, 0, 0, 0, 0},
-	{0x1B, 0, 0, 0, 0},
-	{0x1C, 0, 0, 0, 0},
-	{0x1D, 0, 0, 0, 0},
-	{0x1E, 0, 0, 0, 0},
-	{0x1F, 0, 0, 0, 0},
-	{0x20, 0x3, 0x3, 0, 0},
-	{0x21, 0, 0, 0, 0},
-	{0x22, 0, 0, 0, 0},
-	{0x23, 0x90, 0x90, 0, 0},
-	{0x24, 0x55, 0x55, 0, 0},
-	{0x25, 0x15, 0x15, 0, 0},
-	{0x26, 0x5, 0x5, 0, 0},
-	{0x27, 0x15, 0x15, 0, 0},
-	{0x28, 0x5, 0x5, 0, 0},
-	{0x29, 0x20, 0x20, 0, 0},
-	{0x2A, 0x11, 0x11, 0, 0},
-	{0x2B, 0x90, 0x90, 0, 0},
-	{0x2C, 0, 0, 0, 0},
-	{0x2D, 0x88, 0x88, 0, 0},
-	{0x2E, 0x32, 0x32, 0, 0},
-	{0x2F, 0x77, 0x77, 0, 0},
-	{0x30, 0x17, 0x17, 1, 1},
-	{0x31, 0xff, 0xff, 1, 1},
-	{0x32, 0x20, 0x20, 0, 0},
-	{0x33, 0, 0, 0, 0},
-	{0x34, 0x88, 0x88, 0, 0},
-	{0x35, 0x32, 0x32, 0, 0},
-	{0x36, 0x77, 0x77, 0, 0},
-	{0x37, 0x17, 0x17, 1, 1},
-	{0x38, 0xf0, 0xf0, 1, 1},
-	{0x39, 0x20, 0x20, 0, 0},
-	{0x3A, 0x8, 0x8, 0, 0},
-	{0x3B, 0x55, 0x55, 1, 1},
-	{0x3C, 0, 0, 0, 0},
-	{0x3D, 0x88, 0x88, 1, 1},
-	{0x3E, 0, 0, 0, 0},
-	{0x3F, 0x44, 0x44, 0, 0},
-	{0x40, 0x7, 0x7, 1, 1},
-	{0x41, 0x6, 0x6, 0, 0},
-	{0x42, 0x4, 0x4, 0, 0},
-	{0x43, 0, 0, 0, 0},
-	{0x44, 0x8, 0x8, 0, 0},
-	{0x45, 0x55, 0x55, 1, 1},
-	{0x46, 0, 0, 0, 0},
-	{0x47, 0x11, 0x11, 0, 0},
-	{0x48, 0, 0, 0, 0},
-	{0x49, 0x44, 0x44, 0, 0},
-	{0x4A, 0x7, 0x7, 0, 0},
-	{0x4B, 0x6, 0x6, 0, 0},
-	{0x4C, 0x4, 0x4, 0, 0},
-	{0x4D, 0, 0, 0, 0},
-	{0x4E, 0, 0, 0, 0},
-	{0x4F, 0x26, 0x26, 1, 1},
-	{0x50, 0x26, 0x26, 1, 1},
-	{0x51, 0xf, 0xf, 1, 1},
-	{0x52, 0xf, 0xf, 1, 1},
-	{0x53, 0x44, 0x44, 0, 0},
-	{0x54, 0, 0, 0, 0},
-	{0x55, 0, 0, 0, 0},
-	{0x56, 0x8, 0x8, 0, 0},
-	{0x57, 0x8, 0x8, 0, 0},
-	{0x58, 0x7, 0x7, 0, 0},
-	{0x59, 0x22, 0x22, 0, 0},
-	{0x5A, 0x22, 0x22, 0, 0},
-	{0x5B, 0x2, 0x2, 0, 0},
-	{0x5C, 0x4, 0x4, 1, 1},
-	{0x5D, 0x7, 0x7, 0, 0},
-	{0x5E, 0x55, 0x55, 0, 0},
-	{0x5F, 0x23, 0x23, 0, 0},
-	{0x60, 0x41, 0x41, 0, 0},
-	{0x61, 0x1, 0x1, 0, 0},
-	{0x62, 0xa, 0xa, 0, 0},
-	{0x63, 0, 0, 0, 0},
-	{0x64, 0, 0, 0, 0},
-	{0x65, 0, 0, 0, 0},
-	{0x66, 0, 0, 0, 0},
-	{0x67, 0, 0, 0, 0},
-	{0x68, 0, 0, 0, 0},
-	{0x69, 0, 0, 0, 0},
-	{0x6A, 0, 0, 0, 0},
-	{0x6B, 0xc, 0xc, 0, 0},
-	{0x6C, 0, 0, 0, 0},
-	{0x6D, 0, 0, 0, 0},
-	{0x6E, 0, 0, 0, 0},
-	{0x6F, 0, 0, 0, 0},
-	{0x70, 0, 0, 0, 0},
-	{0x71, 0, 0, 0, 0},
-	{0x72, 0x22, 0x22, 0, 0},
-	{0x73, 0x22, 0x22, 0, 0},
-	{0x74, 0, 0, 1, 1},
-	{0x75, 0xa, 0xa, 0, 0},
-	{0x76, 0x1, 0x1, 0, 0},
-	{0x77, 0x22, 0x22, 0, 0},
-	{0x78, 0x30, 0x30, 0, 0},
-	{0x79, 0, 0, 0, 0},
-	{0x7A, 0, 0, 0, 0},
-	{0x7B, 0, 0, 0, 0},
-	{0x7C, 0, 0, 0, 0},
-	{0x7D, 0x5, 0x5, 1, 1},
-	{0x7E, 0, 0, 0, 0},
-	{0x7F, 0, 0, 0, 0},
-	{0x80, 0, 0, 0, 0},
-	{0x81, 0, 0, 0, 0},
-	{0x82, 0, 0, 0, 0},
-	{0x83, 0, 0, 0, 0},
-	{0x84, 0, 0, 0, 0},
-	{0x85, 0, 0, 0, 0},
-	{0x86, 0, 0, 0, 0},
-	{0x87, 0, 0, 0, 0},
-	{0x88, 0, 0, 0, 0},
-	{0x89, 0, 0, 0, 0},
-	{0x8A, 0, 0, 0, 0},
-	{0x8B, 0, 0, 0, 0},
-	{0x8C, 0, 0, 0, 0},
-	{0x8D, 0, 0, 0, 0},
-	{0x8E, 0, 0, 0, 0},
-	{0x8F, 0, 0, 0, 0},
-	{0x90, 0, 0, 0, 0},
-	{0x91, 0, 0, 0, 0},
-	{0x92, 0, 0, 0, 0},
-	{0x93, 0, 0, 0, 0},
-	{0x94, 0, 0, 0, 0},
-	{0xFFFF, 0, 0, 0, 0},
-};
-
-radio_20xx_regs_t regs_2057_rev4[] = {
-	{0x00, 0x84, 0},
-	{0x01, 0, 0},
-	{0x02, 0x60, 0},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 1},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0xf7, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x4, 0},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x26, 1},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3A, 0x66, 0},
-	{0x3B, 0x66, 0},
-	{0x3C, 0xff, 1},
-	{0x3D, 0xff, 1},
-	{0x3E, 0xff, 1},
-	{0x3F, 0xff, 1},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x42, 0x19, 0},
-	{0x43, 0x7, 0},
-	{0x44, 0x6, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x48, 0x33, 0},
-	{0x49, 0x5, 0},
-	{0x4A, 0x77, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x75, 0},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0xa8, 0},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x30, 0},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0x19, 0},
-	{0x64, 0x62, 0},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x69, 0, 0},
-	{0x6A, 0x7e, 0},
-	{0x6B, 0x3f, 0},
-	{0x6C, 0x7f, 0},
-	{0x6D, 0x78, 0},
-	{0x6E, 0xc8, 0},
-	{0x6F, 0x88, 0},
-	{0x70, 0x8, 0},
-	{0x71, 0xf, 0},
-	{0x72, 0xbc, 0},
-	{0x73, 0x8, 0},
-	{0x74, 0x60, 0},
-	{0x75, 0x1e, 0},
-	{0x76, 0x70, 0},
-	{0x77, 0, 0},
-	{0x78, 0, 0},
-	{0x79, 0, 0},
-	{0x7A, 0x33, 0},
-	{0x7B, 0x1e, 0},
-	{0x7C, 0x62, 0},
-	{0x7D, 0x11, 0},
-	{0x80, 0x3c, 0},
-	{0x81, 0x9c, 0},
-	{0x82, 0xa, 0},
-	{0x83, 0x9d, 0},
-	{0x84, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 1},
-	{0x8B, 0x10, 1},
-	{0x8C, 0xf0, 1},
-	{0x8D, 0, 0},
-	{0x8E, 0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0x9B, 0, 0},
-	{0x9C, 0x87, 0},
-	{0x9D, 0x11, 0},
-	{0x9E, 0, 0},
-	{0x9F, 0x33, 0},
-	{0xA0, 0x88, 0},
-	{0xA1, 0xe1, 0},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 1},
-	{0xA5, 0x6d, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 1},
-	{0xA9, 0xc, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 1},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC1, 0, 0},
-	{0xC2, 0, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0, 0},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCC, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x75, 0},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0xa8, 0},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x30, 0},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0x19, 0},
-	{0xE9, 0x62, 0},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0xEE, 0, 0},
-	{0xEF, 0x7e, 0},
-	{0xF0, 0x3f, 0},
-	{0xF1, 0x7f, 0},
-	{0xF2, 0x78, 0},
-	{0xF3, 0xc8, 0},
-	{0xF4, 0x88, 0},
-	{0xF5, 0x8, 0},
-	{0xF6, 0xf, 0},
-	{0xF7, 0xbc, 0},
-	{0xF8, 0x8, 0},
-	{0xF9, 0x60, 0},
-	{0xFA, 0x1e, 0},
-	{0xFB, 0x70, 0},
-	{0xFC, 0, 0},
-	{0xFD, 0, 0},
-	{0xFE, 0, 0},
-	{0xFF, 0x33, 0},
-	{0x100, 0x1e, 0},
-	{0x101, 0x62, 0},
-	{0x102, 0x11, 0},
-	{0x105, 0x3c, 0},
-	{0x106, 0x9c, 0},
-	{0x107, 0xa, 0},
-	{0x108, 0x9d, 0},
-	{0x109, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 1},
-	{0x110, 0x10, 1},
-	{0x111, 0xf0, 1},
-	{0x112, 0, 0},
-	{0x113, 0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x120, 0, 0},
-	{0x121, 0x87, 0},
-	{0x122, 0x11, 0},
-	{0x123, 0, 0},
-	{0x124, 0x33, 0},
-	{0x125, 0x88, 0},
-	{0x126, 0xe1, 0},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 1},
-	{0x12A, 0x6d, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 1},
-	{0x12E, 0xc, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 1},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x146, 0, 0},
-	{0x147, 0, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0, 0},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x151, 0, 0},
-	{0x152, 0, 0},
-	{0x153, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0x2, 1},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17A, 0x21, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x17F, 0xaa, 0},
-	{0x180, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19A, 0x21, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x19F, 0xaa, 0},
-	{0x1A0, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0xFFFF, 0, 0},
-};
-
-radio_20xx_regs_t regs_2057_rev5[] = {
-	{0x00, 0, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 1},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0xf, 1},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0, 0},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0xf, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0, 0},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0xc, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0x1, 1},
-	{0x1C2, 0x80, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-radio_20xx_regs_t regs_2057_rev5v1[] = {
-	{0x00, 0x15, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 1},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0xf, 1},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0x1, 1},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0xf, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0x1, 1},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0xc, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0x1, 1},
-	{0x1C2, 0x80, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-radio_20xx_regs_t regs_2057_rev7[] = {
-	{0x00, 0, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 0},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3A, 0x66, 0},
-	{0x3B, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x3E, 0xff, 0},
-	{0x3F, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x42, 0x19, 0},
-	{0x43, 0x7, 0},
-	{0x44, 0x6, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x48, 0x33, 0},
-	{0x49, 0x5, 0},
-	{0x4A, 0x77, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0x13, 1},
-	{0x65, 0, 0},
-	{0x66, 0xee, 1},
-	{0x69, 0, 0},
-	{0x6A, 0x7e, 0},
-	{0x6B, 0x3f, 0},
-	{0x6C, 0x7f, 0},
-	{0x6D, 0x78, 0},
-	{0x6E, 0x58, 1},
-	{0x6F, 0x88, 0},
-	{0x70, 0x8, 0},
-	{0x71, 0xf, 0},
-	{0x72, 0xbc, 0},
-	{0x73, 0x8, 0},
-	{0x74, 0x60, 0},
-	{0x75, 0x13, 1},
-	{0x76, 0x70, 0},
-	{0x77, 0, 0},
-	{0x78, 0, 0},
-	{0x79, 0, 0},
-	{0x7A, 0x33, 0},
-	{0x7B, 0x13, 1},
-	{0x7C, 0x14, 1},
-	{0x7D, 0xee, 1},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x83, 0x9d, 0},
-	{0x84, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8D, 0, 0},
-	{0x8E, 0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0x9B, 0, 0},
-	{0x9C, 0x87, 0},
-	{0x9D, 0x11, 0},
-	{0x9E, 0, 0},
-	{0x9F, 0x33, 0},
-	{0xA0, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC1, 0, 0},
-	{0xC2, 0, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0, 0},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCC, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0x13, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0xee, 1},
-	{0xEE, 0, 0},
-	{0xEF, 0x7e, 0},
-	{0xF0, 0x3f, 0},
-	{0xF1, 0x7f, 0},
-	{0xF2, 0x78, 0},
-	{0xF3, 0x58, 1},
-	{0xF4, 0x88, 0},
-	{0xF5, 0x8, 0},
-	{0xF6, 0xf, 0},
-	{0xF7, 0xbc, 0},
-	{0xF8, 0x8, 0},
-	{0xF9, 0x60, 0},
-	{0xFA, 0x13, 1},
-	{0xFB, 0x70, 0},
-	{0xFC, 0, 0},
-	{0xFD, 0, 0},
-	{0xFE, 0, 0},
-	{0xFF, 0x33, 0},
-	{0x100, 0x13, 1},
-	{0x101, 0x14, 1},
-	{0x102, 0xee, 1},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x108, 0x9d, 0},
-	{0x109, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x112, 0, 0},
-	{0x113, 0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x120, 0, 0},
-	{0x121, 0x87, 0},
-	{0x122, 0x11, 0},
-	{0x123, 0, 0},
-	{0x124, 0x33, 0},
-	{0x125, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x146, 0, 0},
-	{0x147, 0, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0, 0},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x151, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17A, 0x21, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x17F, 0xaa, 0},
-	{0x180, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19A, 0x21, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x19F, 0xaa, 0},
-	{0x1A0, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0x5, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0, 0},
-	{0x1C2, 0xa0, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-radio_20xx_regs_t regs_2057_rev8[] = {
-	{0x00, 0x8, 1},
-	{0x01, 0x57, 1},
-	{0x02, 0x20, 1},
-	{0x03, 0x1f, 0},
-	{0x04, 0x4, 0},
-	{0x05, 0x2, 0},
-	{0x06, 0x1, 0},
-	{0x07, 0x1, 0},
-	{0x08, 0x1, 0},
-	{0x09, 0x69, 0},
-	{0x0A, 0x66, 0},
-	{0x0B, 0x6, 0},
-	{0x0C, 0x18, 0},
-	{0x0D, 0x3, 0},
-	{0x0E, 0x20, 0},
-	{0x0F, 0x20, 0},
-	{0x10, 0, 0},
-	{0x11, 0x7c, 0},
-	{0x12, 0x42, 0},
-	{0x13, 0xbd, 0},
-	{0x14, 0x7, 0},
-	{0x15, 0x87, 0},
-	{0x16, 0x8, 0},
-	{0x17, 0x17, 0},
-	{0x18, 0x7, 0},
-	{0x19, 0, 0},
-	{0x1A, 0x2, 0},
-	{0x1B, 0x13, 0},
-	{0x1C, 0x3e, 0},
-	{0x1D, 0x3e, 0},
-	{0x1E, 0x96, 0},
-	{0x1F, 0x4, 0},
-	{0x20, 0, 0},
-	{0x21, 0, 0},
-	{0x22, 0x17, 0},
-	{0x23, 0x6, 0},
-	{0x24, 0x1, 0},
-	{0x25, 0x6, 0},
-	{0x26, 0x4, 0},
-	{0x27, 0xd, 0},
-	{0x28, 0xd, 0},
-	{0x29, 0x30, 0},
-	{0x2A, 0x32, 0},
-	{0x2B, 0x8, 0},
-	{0x2C, 0x1c, 0},
-	{0x2D, 0x2, 0},
-	{0x2E, 0x4, 0},
-	{0x2F, 0x7f, 0},
-	{0x30, 0x27, 0},
-	{0x31, 0, 1},
-	{0x32, 0, 1},
-	{0x33, 0, 1},
-	{0x34, 0, 0},
-	{0x35, 0x20, 0},
-	{0x36, 0x18, 0},
-	{0x37, 0x7, 0},
-	{0x38, 0x66, 0},
-	{0x39, 0x66, 0},
-	{0x3A, 0x66, 0},
-	{0x3B, 0x66, 0},
-	{0x3C, 0xff, 0},
-	{0x3D, 0xff, 0},
-	{0x3E, 0xff, 0},
-	{0x3F, 0xff, 0},
-	{0x40, 0x16, 0},
-	{0x41, 0x7, 0},
-	{0x42, 0x19, 0},
-	{0x43, 0x7, 0},
-	{0x44, 0x6, 0},
-	{0x45, 0x3, 0},
-	{0x46, 0x1, 0},
-	{0x47, 0x7, 0},
-	{0x48, 0x33, 0},
-	{0x49, 0x5, 0},
-	{0x4A, 0x77, 0},
-	{0x4B, 0x66, 0},
-	{0x4C, 0x66, 0},
-	{0x4D, 0, 0},
-	{0x4E, 0x4, 0},
-	{0x4F, 0xc, 0},
-	{0x50, 0, 0},
-	{0x51, 0x70, 1},
-	{0x56, 0x7, 0},
-	{0x57, 0, 0},
-	{0x58, 0, 0},
-	{0x59, 0x88, 1},
-	{0x5A, 0, 0},
-	{0x5B, 0x1f, 0},
-	{0x5C, 0x20, 1},
-	{0x5D, 0x1, 0},
-	{0x5E, 0x30, 0},
-	{0x5F, 0x70, 0},
-	{0x60, 0, 0},
-	{0x61, 0, 0},
-	{0x62, 0x33, 1},
-	{0x63, 0xf, 1},
-	{0x64, 0xf, 1},
-	{0x65, 0, 0},
-	{0x66, 0x11, 0},
-	{0x69, 0, 0},
-	{0x6A, 0x7e, 0},
-	{0x6B, 0x3f, 0},
-	{0x6C, 0x7f, 0},
-	{0x6D, 0x78, 0},
-	{0x6E, 0x58, 1},
-	{0x6F, 0x88, 0},
-	{0x70, 0x8, 0},
-	{0x71, 0xf, 0},
-	{0x72, 0xbc, 0},
-	{0x73, 0x8, 0},
-	{0x74, 0x60, 0},
-	{0x75, 0x13, 1},
-	{0x76, 0x70, 0},
-	{0x77, 0, 0},
-	{0x78, 0, 0},
-	{0x79, 0, 0},
-	{0x7A, 0x33, 0},
-	{0x7B, 0x13, 1},
-	{0x7C, 0xf, 1},
-	{0x7D, 0xee, 1},
-	{0x80, 0x3c, 0},
-	{0x81, 0x1, 1},
-	{0x82, 0xa, 0},
-	{0x83, 0x9d, 0},
-	{0x84, 0xa, 0},
-	{0x85, 0, 0},
-	{0x86, 0x40, 0},
-	{0x87, 0x40, 0},
-	{0x88, 0x88, 0},
-	{0x89, 0x10, 0},
-	{0x8A, 0xf0, 0},
-	{0x8B, 0x10, 0},
-	{0x8C, 0xf0, 0},
-	{0x8D, 0, 0},
-	{0x8E, 0, 0},
-	{0x8F, 0x10, 0},
-	{0x90, 0x55, 0},
-	{0x91, 0x3f, 1},
-	{0x92, 0x36, 1},
-	{0x93, 0, 0},
-	{0x94, 0, 0},
-	{0x95, 0, 0},
-	{0x96, 0x87, 0},
-	{0x97, 0x11, 0},
-	{0x98, 0, 0},
-	{0x99, 0x33, 0},
-	{0x9A, 0x88, 0},
-	{0x9B, 0, 0},
-	{0x9C, 0x87, 0},
-	{0x9D, 0x11, 0},
-	{0x9E, 0, 0},
-	{0x9F, 0x33, 0},
-	{0xA0, 0x88, 0},
-	{0xA1, 0x20, 1},
-	{0xA2, 0x3f, 0},
-	{0xA3, 0x44, 0},
-	{0xA4, 0x8c, 0},
-	{0xA5, 0x6c, 0},
-	{0xA6, 0x22, 0},
-	{0xA7, 0xbe, 0},
-	{0xA8, 0x55, 0},
-	{0xAA, 0xc, 0},
-	{0xAB, 0xaa, 0},
-	{0xAC, 0x2, 0},
-	{0xAD, 0, 0},
-	{0xAE, 0x10, 0},
-	{0xAF, 0x1, 0},
-	{0xB0, 0, 0},
-	{0xB1, 0, 0},
-	{0xB2, 0x80, 0},
-	{0xB3, 0x60, 0},
-	{0xB4, 0x44, 0},
-	{0xB5, 0x55, 0},
-	{0xB6, 0x1, 0},
-	{0xB7, 0x55, 0},
-	{0xB8, 0x1, 0},
-	{0xB9, 0x5, 0},
-	{0xBA, 0x55, 0},
-	{0xBB, 0x55, 0},
-	{0xC1, 0, 0},
-	{0xC2, 0, 0},
-	{0xC3, 0, 0},
-	{0xC4, 0, 0},
-	{0xC5, 0, 0},
-	{0xC6, 0, 0},
-	{0xC7, 0, 0},
-	{0xC8, 0, 0},
-	{0xC9, 0x1, 1},
-	{0xCA, 0, 0},
-	{0xCB, 0, 0},
-	{0xCC, 0, 0},
-	{0xCD, 0, 0},
-	{0xCE, 0x5e, 0},
-	{0xCF, 0xc, 0},
-	{0xD0, 0xc, 0},
-	{0xD1, 0xc, 0},
-	{0xD2, 0, 0},
-	{0xD3, 0x2b, 0},
-	{0xD4, 0xc, 0},
-	{0xD5, 0, 0},
-	{0xD6, 0x70, 1},
-	{0xDB, 0x7, 0},
-	{0xDC, 0, 0},
-	{0xDD, 0, 0},
-	{0xDE, 0x88, 1},
-	{0xDF, 0, 0},
-	{0xE0, 0x1f, 0},
-	{0xE1, 0x20, 1},
-	{0xE2, 0x1, 0},
-	{0xE3, 0x30, 0},
-	{0xE4, 0x70, 0},
-	{0xE5, 0, 0},
-	{0xE6, 0, 0},
-	{0xE7, 0x33, 0},
-	{0xE8, 0xf, 1},
-	{0xE9, 0xf, 1},
-	{0xEA, 0, 0},
-	{0xEB, 0x11, 0},
-	{0xEE, 0, 0},
-	{0xEF, 0x7e, 0},
-	{0xF0, 0x3f, 0},
-	{0xF1, 0x7f, 0},
-	{0xF2, 0x78, 0},
-	{0xF3, 0x58, 1},
-	{0xF4, 0x88, 0},
-	{0xF5, 0x8, 0},
-	{0xF6, 0xf, 0},
-	{0xF7, 0xbc, 0},
-	{0xF8, 0x8, 0},
-	{0xF9, 0x60, 0},
-	{0xFA, 0x13, 1},
-	{0xFB, 0x70, 0},
-	{0xFC, 0, 0},
-	{0xFD, 0, 0},
-	{0xFE, 0, 0},
-	{0xFF, 0x33, 0},
-	{0x100, 0x13, 1},
-	{0x101, 0xf, 1},
-	{0x102, 0xee, 1},
-	{0x105, 0x3c, 0},
-	{0x106, 0x1, 1},
-	{0x107, 0xa, 0},
-	{0x108, 0x9d, 0},
-	{0x109, 0xa, 0},
-	{0x10A, 0, 0},
-	{0x10B, 0x40, 0},
-	{0x10C, 0x40, 0},
-	{0x10D, 0x88, 0},
-	{0x10E, 0x10, 0},
-	{0x10F, 0xf0, 0},
-	{0x110, 0x10, 0},
-	{0x111, 0xf0, 0},
-	{0x112, 0, 0},
-	{0x113, 0, 0},
-	{0x114, 0x10, 0},
-	{0x115, 0x55, 0},
-	{0x116, 0x3f, 1},
-	{0x117, 0x36, 1},
-	{0x118, 0, 0},
-	{0x119, 0, 0},
-	{0x11A, 0, 0},
-	{0x11B, 0x87, 0},
-	{0x11C, 0x11, 0},
-	{0x11D, 0, 0},
-	{0x11E, 0x33, 0},
-	{0x11F, 0x88, 0},
-	{0x120, 0, 0},
-	{0x121, 0x87, 0},
-	{0x122, 0x11, 0},
-	{0x123, 0, 0},
-	{0x124, 0x33, 0},
-	{0x125, 0x88, 0},
-	{0x126, 0x20, 1},
-	{0x127, 0x3f, 0},
-	{0x128, 0x44, 0},
-	{0x129, 0x8c, 0},
-	{0x12A, 0x6c, 0},
-	{0x12B, 0x22, 0},
-	{0x12C, 0xbe, 0},
-	{0x12D, 0x55, 0},
-	{0x12F, 0xc, 0},
-	{0x130, 0xaa, 0},
-	{0x131, 0x2, 0},
-	{0x132, 0, 0},
-	{0x133, 0x10, 0},
-	{0x134, 0x1, 0},
-	{0x135, 0, 0},
-	{0x136, 0, 0},
-	{0x137, 0x80, 0},
-	{0x138, 0x60, 0},
-	{0x139, 0x44, 0},
-	{0x13A, 0x55, 0},
-	{0x13B, 0x1, 0},
-	{0x13C, 0x55, 0},
-	{0x13D, 0x1, 0},
-	{0x13E, 0x5, 0},
-	{0x13F, 0x55, 0},
-	{0x140, 0x55, 0},
-	{0x146, 0, 0},
-	{0x147, 0, 0},
-	{0x148, 0, 0},
-	{0x149, 0, 0},
-	{0x14A, 0, 0},
-	{0x14B, 0, 0},
-	{0x14C, 0, 0},
-	{0x14D, 0, 0},
-	{0x14E, 0x1, 1},
-	{0x14F, 0, 0},
-	{0x150, 0, 0},
-	{0x151, 0, 0},
-	{0x154, 0xc, 0},
-	{0x155, 0xc, 0},
-	{0x156, 0xc, 0},
-	{0x157, 0, 0},
-	{0x158, 0x2b, 0},
-	{0x159, 0x84, 0},
-	{0x15A, 0x15, 0},
-	{0x15B, 0xf, 0},
-	{0x15C, 0, 0},
-	{0x15D, 0, 0},
-	{0x15E, 0, 1},
-	{0x15F, 0, 1},
-	{0x160, 0, 1},
-	{0x161, 0, 1},
-	{0x162, 0, 1},
-	{0x163, 0, 1},
-	{0x164, 0, 0},
-	{0x165, 0, 0},
-	{0x166, 0, 0},
-	{0x167, 0, 0},
-	{0x168, 0, 0},
-	{0x169, 0, 0},
-	{0x16A, 0, 1},
-	{0x16B, 0, 1},
-	{0x16C, 0, 1},
-	{0x16D, 0, 0},
-	{0x170, 0, 0},
-	{0x171, 0x77, 0},
-	{0x172, 0x77, 0},
-	{0x173, 0x77, 0},
-	{0x174, 0x77, 0},
-	{0x175, 0, 0},
-	{0x176, 0x3, 0},
-	{0x177, 0x37, 0},
-	{0x178, 0x3, 0},
-	{0x179, 0, 0},
-	{0x17A, 0x21, 0},
-	{0x17B, 0x21, 0},
-	{0x17C, 0, 0},
-	{0x17D, 0xaa, 0},
-	{0x17E, 0, 0},
-	{0x17F, 0xaa, 0},
-	{0x180, 0, 0},
-	{0x190, 0, 0},
-	{0x191, 0x77, 0},
-	{0x192, 0x77, 0},
-	{0x193, 0x77, 0},
-	{0x194, 0x77, 0},
-	{0x195, 0, 0},
-	{0x196, 0x3, 0},
-	{0x197, 0x37, 0},
-	{0x198, 0x3, 0},
-	{0x199, 0, 0},
-	{0x19A, 0x21, 0},
-	{0x19B, 0x21, 0},
-	{0x19C, 0, 0},
-	{0x19D, 0xaa, 0},
-	{0x19E, 0, 0},
-	{0x19F, 0xaa, 0},
-	{0x1A0, 0, 0},
-	{0x1A1, 0x2, 0},
-	{0x1A2, 0xf, 0},
-	{0x1A3, 0xf, 0},
-	{0x1A4, 0, 1},
-	{0x1A5, 0, 1},
-	{0x1A6, 0, 1},
-	{0x1A7, 0x2, 0},
-	{0x1A8, 0xf, 0},
-	{0x1A9, 0xf, 0},
-	{0x1AA, 0, 1},
-	{0x1AB, 0, 1},
-	{0x1AC, 0, 1},
-	{0x1AD, 0x84, 0},
-	{0x1AE, 0x60, 0},
-	{0x1AF, 0x47, 0},
-	{0x1B0, 0x47, 0},
-	{0x1B1, 0, 0},
-	{0x1B2, 0, 0},
-	{0x1B3, 0, 0},
-	{0x1B4, 0, 0},
-	{0x1B5, 0, 0},
-	{0x1B6, 0, 0},
-	{0x1B7, 0x5, 1},
-	{0x1B8, 0, 0},
-	{0x1B9, 0, 0},
-	{0x1BA, 0, 0},
-	{0x1BB, 0, 0},
-	{0x1BC, 0, 0},
-	{0x1BD, 0, 0},
-	{0x1BE, 0, 0},
-	{0x1BF, 0, 0},
-	{0x1C0, 0, 0},
-	{0x1C1, 0, 0},
-	{0x1C2, 0xa0, 1},
-	{0x1C3, 0, 0},
-	{0x1C4, 0, 0},
-	{0x1C5, 0, 0},
-	{0x1C6, 0, 0},
-	{0x1C7, 0, 0},
-	{0x1C8, 0, 0},
-	{0x1C9, 0, 0},
-	{0x1CA, 0, 0},
-	{0xFFFF, 0, 0}
-};
-
-static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 };
-
-static s32 nphy_lnagain_est0[] = { -315, 40370 };
-static s32 nphy_lnagain_est1[] = { -224, 23242 };
-
-static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
-	{
-	 {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
-	 {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
-	 {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
-	 {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
-	 {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
-	 {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
-	 {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
-	 {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
-	 {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
-	 },
-	{
-	 {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
-	 {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
-	 {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
-	 {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
-	 {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
-	 {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
-	 {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
-	 {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
-	 {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
-	 }
-};
-
-static const u32 nphy_tpc_txgain[] = {
-	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
-	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
-	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
-	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
-	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
-	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
-	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
-	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
-	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
-	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
-	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
-	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
-	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
-	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
-	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
-	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
-	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
-	0x03902942, 0x03902844, 0x03902842, 0x03902744,
-	0x03902742, 0x03902644, 0x03902642, 0x03902544,
-	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
-	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
-	0x03802842, 0x03802744, 0x03802742, 0x03802644,
-	0x03802642, 0x03802544, 0x03802542, 0x03802444,
-	0x03802442, 0x03802344, 0x03802342, 0x03802244,
-	0x03802242, 0x03802144, 0x03802142, 0x03802044,
-	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
-	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
-	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
-	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
-	0x03801842, 0x03801744, 0x03801742, 0x03801644,
-	0x03801642, 0x03801544, 0x03801542, 0x03801444,
-	0x03801442, 0x03801344, 0x03801342, 0x00002b00
-};
-
-static const u16 nphy_tpc_loscale[] = {
-	256, 256, 271, 271, 287, 256, 256, 271,
-	271, 287, 287, 304, 304, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 341,
-	341, 362, 362, 383, 383, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 256,
-	256, 271, 271, 287, 287, 304, 304, 322,
-	322, 341, 341, 362, 362, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 256,
-	256, 271, 271, 287, 287, 304, 304, 322,
-	322, 341, 341, 362, 362, 256, 256, 271,
-	271, 287, 287, 304, 304, 322, 322, 341,
-	341, 362, 362, 383, 383, 406, 406, 430,
-	430, 455, 455, 482, 482, 511, 511, 541,
-	541, 573, 573, 607, 607, 643, 643, 681,
-	681, 722, 722, 764, 764, 810, 810, 858,
-	858, 908, 908, 962, 962, 1019, 1019, 256
-};
-
-static u32 nphy_tpc_txgain_ipa[] = {
-	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
-	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
-	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
-	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
-	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
-	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
-	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
-	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
-	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
-	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
-	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
-	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
-	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
-	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
-	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
-	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
-	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
-	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
-	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
-	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
-	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
-	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
-	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
-	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
-	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
-	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
-	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
-	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
-	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
-	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
-	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
-	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025
-};
-
-static u32 nphy_tpc_txgain_ipa_rev5[] = {
-	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
-	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
-	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
-	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
-	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
-	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
-	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
-	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
-	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
-	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
-	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
-	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
-	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
-	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
-	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
-	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
-	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
-	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
-	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
-	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
-	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
-	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
-	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
-	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
-	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
-	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
-	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
-	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
-	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
-	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
-	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
-	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025
-};
-
-static u32 nphy_tpc_txgain_ipa_rev6[] = {
-	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
-	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
-	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
-	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
-	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
-	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
-	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
-	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
-	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
-	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
-	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
-	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
-	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
-	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
-	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
-	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
-	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
-	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
-	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
-	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
-	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
-	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
-	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
-	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
-	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
-	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
-	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
-	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
-	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
-	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
-	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
-	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = {
-	0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039,
-	0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032,
-	0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d,
-	0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c,
-	0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d,
-	0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a,
-	0x70570028, 0x704f002a, 0x7047002c, 0x7047002a,
-	0x70470028, 0x70470026, 0x70470024, 0x70470022,
-	0x7047001f, 0x70370027, 0x70370024, 0x70370022,
-	0x70370020, 0x7037001f, 0x7037001d, 0x7037001b,
-	0x7037001a, 0x70370018, 0x70370017, 0x7027001e,
-	0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022,
-	0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b,
-	0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015,
-	0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011,
-	0x70170019, 0x70170018, 0x70170016, 0x70170015,
-	0x70170014, 0x70170013, 0x70170012, 0x70170010,
-	0x70170010, 0x7017000f, 0x700f001d, 0x700f001b,
-	0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015,
-	0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011,
-	0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e,
-	0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b,
-	0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009,
-	0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007,
-	0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006,
-	0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004,
-	0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004,
-	0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003,
-	0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002,
-	0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001,
-	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001,
-	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = {
-	0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039,
-	0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032,
-	0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d,
-	0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c,
-	0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d,
-	0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a,
-	0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a,
-	0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022,
-	0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022,
-	0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b,
-	0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e,
-	0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022,
-	0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b,
-	0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015,
-	0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011,
-	0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015,
-	0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010,
-	0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b,
-	0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015,
-	0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011,
-	0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e,
-	0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b,
-	0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009,
-	0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007,
-	0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006,
-	0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004,
-	0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004,
-	0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003,
-	0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002,
-	0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001,
-	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001,
-	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = {
-	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
-	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
-	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
-	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
-	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
-	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
-	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
-	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
-	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
-	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
-	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
-	0x30170028, 0x30170026, 0x30170024, 0x30170022,
-	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
-	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
-	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
-	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
-	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
-	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
-	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
-};
-
-static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = {
-	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
-	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
-	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
-	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
-	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
-	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
-	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
-	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
-	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
-	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
-	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
-	0x30170028, 0x30170026, 0x30170024, 0x30170022,
-	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
-	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
-	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
-	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
-	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
-	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
-	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
-	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
-};
-
-static u32 nphy_tpc_txgain_ipa_5g[] = {
-	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
-	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
-	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
-	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
-	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
-	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
-	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
-	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
-	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
-	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
-	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
-	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
-	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
-	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
-	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
-	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
-	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
-	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
-	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
-	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
-	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
-	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
-	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
-	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
-	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
-	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
-	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
-	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
-	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
-	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
-	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
-	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f
-};
-
-static u32 nphy_tpc_txgain_ipa_5g_2057[] = {
-	0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039,
-	0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035,
-	0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033,
-	0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a,
-	0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039,
-	0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038,
-	0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038,
-	0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037,
-	0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036,
-	0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037,
-	0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036,
-	0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035,
-	0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033,
-	0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034,
-	0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032,
-	0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028,
-	0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020,
-	0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019,
-	0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014,
-	0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010,
-	0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d,
-	0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a,
-	0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008,
-	0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006,
-	0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005,
-	0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004,
-	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
-	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
-	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
-	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
-	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
-	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001
-};
-
-static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = {
-	0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a,
-	0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a,
-	0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028,
-	0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e,
-	0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e,
-	0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e,
-	0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d,
-	0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d,
-	0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c,
-	0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b,
-	0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b,
-	0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a,
-	0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029,
-	0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029,
-	0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027,
-	0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020,
-	0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019,
-	0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014,
-	0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f,
-	0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c,
-	0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a,
-	0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008,
-	0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006,
-	0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005,
-	0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004,
-	0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003,
-	0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
-	0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001,
-	0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001
-};
-
-static s8 nphy_papd_pga_gain_delta_ipa_2g[] = {
-	-114, -108, -98, -91, -84, -78, -70, -62,
-	-54, -46, -39, -31, -23, -15, -8, 0
-};
-
-static s8 nphy_papd_pga_gain_delta_ipa_5g[] = {
-	-100, -95, -89, -83, -77, -70, -63, -56,
-	-48, -41, -33, -25, -19, -12, -6, 0
-};
-
-static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = {
-	-159, -113, -86, -72, -62, -54, -48, -43,
-	-39, -35, -31, -28, -25, -23, -20, -18,
-	-17, -15, -13, -11, -10, -8, -7, -6,
-	-5, -4, -3, -3, -2, -1, -1, 0
-};
-
-static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = {
-	-109, -109, -82, -68, -58, -50, -44, -39,
-	-35, -31, -28, -26, -23, -21, -19, -17,
-	-16, -14, -13, -11, -10, -9, -8, -7,
-	-5, -5, -4, -3, -2, -1, -1, 0
-};
-
-static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = {
-	-122, -122, -95, -80, -69, -61, -54, -49,
-	-43, -39, -35, -32, -28, -26, -23, -21,
-	-18, -16, -15, -13, -11, -10, -8, -7,
-	-6, -5, -4, -3, -2, -1, -1, 0
-};
-
-static s8 nphy_papd_pgagain_dlt_5g_2057[] = {
-	-107, -101, -92, -85, -78, -71, -62, -55,
-	-47, -39, -32, -24, -19, -12, -6, 0
-};
-
-static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = {
-	-110, -104, -95, -88, -81, -74, -66, -58,
-	-50, -44, -36, -28, -23, -15, -8, 0
-};
-
-static u8 pad_gain_codes_used_2057rev5[] = {
-	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
-	10, 9, 8, 7, 6, 5, 4, 3, 2, 1
-};
-
-static u8 pad_gain_codes_used_2057rev7[] = {
-	15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
-	5, 4, 3, 2, 1
-};
-
-static u8 pad_all_gain_codes_2057[] = {
-	31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
-	21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
-	11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
-	1, 0
-};
-
-static u8 pga_all_gain_codes_2057[] = {
-	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
-};
-
-static u32 nphy_papd_scaltbl[] = {
-	0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038,
-	0x0887003c, 0x081f003f, 0x07a20043, 0x07340047,
-	0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059,
-	0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070,
-	0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d,
-	0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2,
-	0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0,
-	0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a,
-	0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162,
-	0x015d0177, 0x0149018e, 0x013701a5, 0x012601be,
-	0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232,
-	0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3,
-	0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a,
-	0x008b03af, 0x008303e7, 0x007c0422, 0x00750461,
-	0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583,
-	0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1
-};
-
-static u32 nphy_tpc_txgain_rev3[] = {
-	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
-	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
-	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
-	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
-	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
-	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
-	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
-	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
-	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
-	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
-	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
-	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
-	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
-	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
-	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
-	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
-	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
-	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
-	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
-	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
-	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
-	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
-	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
-	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
-	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
-	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
-	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
-	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
-	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
-	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
-	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
-	0x1041003c, 0x1041003b, 0x10410039, 0x10410037
-};
-
-static u32 nphy_tpc_txgain_HiPwrEPA[] = {
-	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
-	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
-	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
-	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
-	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
-	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
-	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
-	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
-	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
-	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
-	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
-	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
-	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
-	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
-	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
-	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
-	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
-	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
-	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
-	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
-	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
-	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
-	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
-	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
-	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
-	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
-	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
-	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
-	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
-	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
-	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
-	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
-};
-
-static u32 nphy_tpc_txgain_epa_2057rev3[] = {
-	0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d,
-	0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b,
-	0x8091003b, 0x8089003a, 0x8081003a, 0x80790039,
-	0x80710039, 0x8069003a, 0x8061003b, 0x8059003d,
-	0x8051003f, 0x80490042, 0x8049003e, 0x8049003b,
-	0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b,
-	0x80390038, 0x80390035, 0x8031003a, 0x80310036,
-	0x80310033, 0x8029003a, 0x80290037, 0x80290034,
-	0x80290031, 0x80210039, 0x80210036, 0x80210033,
-	0x80210030, 0x8019003c, 0x80190039, 0x80190036,
-	0x80190033, 0x80190030, 0x8019002d, 0x8019002b,
-	0x80190028, 0x8011003a, 0x80110036, 0x80110033,
-	0x80110030, 0x8011002e, 0x8011002b, 0x80110029,
-	0x80110027, 0x80110024, 0x80110022, 0x80110020,
-	0x8011001f, 0x8011001d, 0x8009003a, 0x80090037,
-	0x80090034, 0x80090031, 0x8009002e, 0x8009002c,
-	0x80090029, 0x80090027, 0x80090025, 0x80090023,
-	0x80090021, 0x8009001f, 0x8009001d, 0x8009011d,
-	0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d,
-	0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
-	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d
-};
-
-static u32 nphy_tpc_txgain_epa_2057rev5[] = {
-	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
-	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
-	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
-	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
-	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
-	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
-	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
-	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
-	0x10290031, 0x10210039, 0x10210036, 0x10210033,
-	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
-	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
-	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
-	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
-	0x10110027, 0x10110024, 0x10110022, 0x10110020,
-	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
-	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
-	0x10090029, 0x10090027, 0x10090025, 0x10090023,
-	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
-	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
-	0x10090015, 0x10090013, 0x10090012, 0x10090011,
-	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
-	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
-	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
-	0x10090008, 0x10090008, 0x10090007, 0x10090007,
-	0x10090007, 0x10090006, 0x10090006, 0x10090005,
-	0x10090005, 0x10090005, 0x10090005, 0x10090004,
-	0x10090004, 0x10090004, 0x10090004, 0x10090003,
-	0x10090003, 0x10090003, 0x10090003, 0x10090003,
-	0x10090003, 0x10090002, 0x10090002, 0x10090002,
-	0x10090002, 0x10090002, 0x10090002, 0x10090002,
-	0x10090002, 0x10090002, 0x10090001, 0x10090001,
-	0x10090001, 0x10090001, 0x10090001, 0x10090001
-};
-
-static u32 nphy_tpc_5GHz_txgain_rev3[] = {
-	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
-	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
-	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
-	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
-	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
-	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
-	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
-	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
-	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
-	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
-	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
-	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
-	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
-	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
-	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
-	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
-	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
-	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
-	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
-	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
-	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
-	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
-	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
-	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
-	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
-	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
-	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
-	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
-	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
-	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
-	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
-	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037
-};
-
-static u32 nphy_tpc_5GHz_txgain_rev4[] = {
-	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
-	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
-	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
-	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
-	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
-	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
-	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
-	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
-	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
-	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
-	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
-	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
-	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
-	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
-	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
-	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
-	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
-	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
-	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
-	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
-	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
-	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
-	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
-	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
-	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
-	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
-	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
-	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
-	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
-	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
-	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
-	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034
-};
-
-static u32 nphy_tpc_5GHz_txgain_rev5[] = {
-	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
-	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
-	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
-	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
-	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
-	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
-	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
-	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
-	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
-	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
-	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
-	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
-	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
-	0x09620039, 0x09620037, 0x09620035, 0x09620033,
-	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
-	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
-	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
-	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
-	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
-	0x06620039, 0x06620037, 0x06620035, 0x06620033,
-	0x05620046, 0x05620044, 0x05620042, 0x05620040,
-	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
-	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
-	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
-	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
-	0x03620038, 0x03620037, 0x03620035, 0x03620033,
-	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
-	0x02620046, 0x02620044, 0x02620043, 0x02620042,
-	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
-	0x01620043, 0x01620042, 0x01620041, 0x01620040,
-	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
-	0x0062003b, 0x00620039, 0x00620037, 0x00620035
-};
-
-static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
-	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
-	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
-	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
-	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
-	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
-	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
-	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
-	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
-	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
-	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
-	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
-	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
-	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
-	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
-	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
-	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
-	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
-	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
-	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
-	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
-	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
-	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
-	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
-	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
-	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
-	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
-	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
-	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
-	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
-	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
-	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
-	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
-};
-
-static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
-static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
-static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
-	0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
-static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
-	0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
-
-static bool wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
-				   chan_info_nphy_radio2057_t **t0,
-				   chan_info_nphy_radio205x_t **t1,
-				   chan_info_nphy_radio2057_rev5_t **t2,
-				   chan_info_nphy_2055_t **t3);
-static void wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chans,
-					const nphy_sfo_cfg_t *c);
-
-static void wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi,
-					    u16 reduction_factr);
-static void wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *,
-					     u32 *buf);
-static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr);
-static void wlc_phy_txlpfbw_nphy(phy_info_t *pi);
-static void wlc_phy_spurwar_nphy(phy_info_t *pi);
-
-static void wlc_phy_radio_preinit_2055(phy_info_t *pi);
-static void wlc_phy_radio_init_2055(phy_info_t *pi);
-static void wlc_phy_radio_postinit_2055(phy_info_t *pi);
-static void wlc_phy_radio_preinit_205x(phy_info_t *pi);
-static void wlc_phy_radio_init_2056(phy_info_t *pi);
-static void wlc_phy_radio_postinit_2056(phy_info_t *pi);
-static void wlc_phy_radio_init_2057(phy_info_t *pi);
-static void wlc_phy_radio_postinit_2057(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi);
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi);
-static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi);
-
-static void wlc_phy_restore_rssical_nphy(phy_info_t *pi);
-static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi);
-static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi);
-static int wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t tg,
-				      u8 type, bool d);
-static void wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rxcore,
-					     u16 *rg, u8 type);
-static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble);
-static void wlc_phy_savecal_nphy(phy_info_t *pi);
-static void wlc_phy_restorecal_nphy(phy_info_t *pi);
-static void wlc_phy_resetcca_nphy(phy_info_t *pi);
-
-static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi);
-static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi);
-static void wlc_phy_precal_txgain_nphy(phy_info_t *pi);
-static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core);
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi);
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi);
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi);
-static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi);
-static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1);
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi);
-
-static void wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32,
-			    u32 e);
-static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core);
-static void wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *,
-			    phy_cal_mode_t, u8);
-static void wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi,
-					  nphy_papd_restore_state *state);
-static void wlc_phy_papd_cal_setup_nphy(phy_info_t *pi,
-					nphy_papd_restore_state *state, u8);
-
-static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals);
-
-static void wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *evts,
-				   u8 *dlys, u8 len);
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset);
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
-				  u8 core_mask, u8 off,
-				  u8 override_id);
-
-static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type);
-static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi);
-
-static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi);
-static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
-					    u16 *pwr_offset,
-					    u8 tmp_max_pwr, u8 rate_start,
-					    u8 rate_end);
-
-static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi);
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi);
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi);
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi);
-
-static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi);
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core);
-static void wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0,
-					   u8 idx1);
-static void wlc_phy_a4(phy_info_t *pi, bool full_cal);
-
-static u16 wlc_phy_radio205x_rcal(phy_info_t *pi);
-
-static u16 wlc_phy_radio2057_rccal(phy_info_t *pi);
-
-static u16 wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz,
-					    u16 max_val,
-					    u8 dac_test_mode);
-static void wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
-					 u16 num_samps);
-static void wlc_phy_runsamples_nphy(phy_info_t *pi, u16 n, u16 lps,
-				    u16 wait, u8 iq, u8 dac_test_mode,
-				    bool modify_bbmult);
-
-bool wlc_phy_bist_check_phy(wlc_phy_t *pih)
-{
-	phy_info_t *pi = (phy_info_t *) pih;
-	u32 phybist0, phybist1, phybist2, phybist3, phybist4;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 16))
-		return true;
-
-	phybist0 = read_phy_reg(pi, 0x0e);
-	phybist1 = read_phy_reg(pi, 0x0f);
-	phybist2 = read_phy_reg(pi, 0xea);
-	phybist3 = read_phy_reg(pi, 0xeb);
-	phybist4 = read_phy_reg(pi, 0x156);
-
-	if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
-	    (phybist3 == 0) && (phybist4 == 0)) {
-		return true;
-	}
-
-	return false;
-}
-
-static void WLBANDINITFN(wlc_phy_bphy_init_nphy) (phy_info_t *pi)
-{
-	u16 addr, val;
-
-	ASSERT(ISNPHY(pi));
-
-	val = 0x1e1f;
-	for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT);
-	     addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) {
-		write_phy_reg(pi, addr, val);
-		if (addr == (NPHY_TO_BPHY_OFF + 0x97))
-			val = 0x3e3f;
-		else
-			val -= 0x0202;
-	}
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-
-		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
-
-		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
-
-		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
-
-	} else {
-
-		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
-	}
-}
-
-void
-wlc_phy_table_write_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
-			 u32 width, const void *data)
-{
-	mimophytbl_info_t tbl;
-
-	tbl.tbl_id = id;
-	tbl.tbl_len = len;
-	tbl.tbl_offset = offset;
-	tbl.tbl_width = width;
-	tbl.tbl_ptr = data;
-	wlc_phy_write_table_nphy(pi, &tbl);
-}
-
-void
-wlc_phy_table_read_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
-			u32 width, void *data)
-{
-	mimophytbl_info_t tbl;
-
-	tbl.tbl_id = id;
-	tbl.tbl_len = len;
-	tbl.tbl_offset = offset;
-	tbl.tbl_width = width;
-	tbl.tbl_ptr = data;
-	wlc_phy_read_table_nphy(pi, &tbl);
-}
-
-static void WLBANDINITFN(wlc_phy_static_table_download_nphy) (phy_info_t *pi)
-{
-	uint idx;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 16)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev16[idx]);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev7[idx]);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev3[idx]);
-	} else {
-		for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++)
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev0[idx]);
-	}
-}
-
-static void WLBANDINITFN(wlc_phy_tbl_init_nphy) (phy_info_t *pi)
-{
-	uint idx = 0;
-	u8 antswctrllut;
-
-	if (pi->phy_init_por)
-		wlc_phy_static_table_download_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
-		    pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
-
-		switch (antswctrllut) {
-		case 0:
-
-			break;
-
-		case 1:
-
-			if (pi->aa2g == 7) {
-
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_ANTSWCTRLLUT,
-							 2, 0x21, 8,
-							 &ant_sw_ctrl_tbl_rev8_2o3
-							 [0]);
-			} else {
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_ANTSWCTRLLUT,
-							 2, 0x21, 8,
-							 &ant_sw_ctrl_tbl_rev8
-							 [0]);
-			}
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x25, 8,
-						 &ant_sw_ctrl_tbl_rev8[2]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x29, 8,
-						 &ant_sw_ctrl_tbl_rev8[4]);
-			break;
-
-		case 2:
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x1, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
-						 [0]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x5, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
-						 [2]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x9, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
-						 [4]);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x21, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
-						 [0]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x25, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
-						 [2]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 2, 0x29, 8,
-						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
-						 [4]);
-			break;
-
-		default:
-
-			ASSERT(0);
-			break;
-		}
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
-
-			if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
-				antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
-				    pi->srom_fem2g.antswctrllut : pi->
-				    srom_fem5g.antswctrllut;
-				switch (antswctrllut) {
-				case 0:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile
-								 [idx]);
-					break;
-				case 1:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile1
-								 [idx]);
-					break;
-				case 2:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile2
-								 [idx]);
-					break;
-				case 3:
-					wlc_phy_write_table_nphy(pi,
-								 &mimophytbl_info_rev3_volatile3
-								 [idx]);
-					break;
-				default:
-
-					ASSERT(0);
-					break;
-				}
-			} else {
-				wlc_phy_write_table_nphy(pi,
-							 &mimophytbl_info_rev3_volatile
-							 [idx]);
-			}
-		}
-	} else {
-		for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
-			wlc_phy_write_table_nphy(pi,
-						 &mimophytbl_info_rev0_volatile
-						 [idx]);
-		}
-	}
-}
-
-static void
-wlc_phy_write_txmacreg_nphy(phy_info_t *pi, u16 holdoff, u16 delay)
-{
-	write_phy_reg(pi, 0x77, holdoff);
-	write_phy_reg(pi, 0xb4, delay);
-}
-
-void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs)
-{
-	u16 holdoff, delay;
-
-	if (rifs) {
-
-		holdoff = 0x10;
-		delay = 0x258;
-	} else {
-
-		holdoff = 0x15;
-		delay = 0x320;
-	}
-
-	wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
-
-	if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
-		pi->sh->_rifs_phy = rifs;
-	}
-}
-
-bool wlc_phy_attach_nphy(phy_info_t *pi)
-{
-	uint i;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
-		pi->phyhang_avoid = true;
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		pi->nphy_gband_spurwar_en = true;
-
-		if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
-			pi->nphy_aband_spurwar_en = true;
-		}
-	}
-	if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
-			pi->nphy_gband_spurwar2_en = true;
-		}
-	}
-
-	pi->n_preamble_override = AUTO;
-	if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4))
-		pi->n_preamble_override = WLC_N_PREAMBLE_MIXEDMODE;
-
-	pi->nphy_txrx_chain = AUTO;
-	pi->phy_scraminit = AUTO;
-
-	pi->nphy_rxcalparams = 0x010100B5;
-
-	pi->nphy_perical = PHY_PERICAL_MPHASE;
-	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
-	pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS;
-
-	pi->nphy_gain_boost = true;
-	pi->nphy_elna_gain_config = false;
-	pi->radio_is_on = false;
-
-	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
-		pi->nphy_txpwrindex[i].index = AUTO;
-	}
-
-	wlc_phy_txpwrctrl_config_nphy(pi);
-	if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
-		pi->hwpwrctrl_capable = true;
-
-	pi->pi_fptr.init = wlc_phy_init_nphy;
-	pi->pi_fptr.calinit = wlc_phy_cal_init_nphy;
-	pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy;
-	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy;
-
-	if (!wlc_phy_txpwr_srom_read_nphy(pi))
-		return false;
-
-	return true;
-}
-
-static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi)
-{
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
-		pi->phy_5g_pwrgain = true;
-		return;
-	}
-
-	pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
-	pi->phy_5g_pwrgain = false;
-
-	if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
-	    NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
-		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
-	else if ((pi->sh->sromrev >= 4)
-		 && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
-		pi->phy_5g_pwrgain = true;
-}
-
-void WLBANDINITFN(wlc_phy_init_nphy) (phy_info_t *pi)
-{
-	u16 val;
-	u16 clip1_ths[2];
-	nphy_txgains_t target_gain;
-	u8 tx_pwr_ctrl_state;
-	bool do_nphy_cal = false;
-	uint core;
-	uint origidx, intr_val;
-	d11regs_t *regs;
-	u32 d11_clk_ctl_st;
-
-	core = 0;
-
-	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
-		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
-	}
-
-	if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
-	    ((pi->sh->chippkg == BCM4717_PKG_ID) ||
-	     (pi->sh->chippkg == BCM4718_PKG_ID))) {
-		if ((pi->sh->boardflags & BFL_EXTLNA) &&
-		    (CHSPEC_IS2G(pi->radio_chanspec))) {
-			si_corereg(pi->sh->sih, SI_CC_IDX,
-				   offsetof(chipcregs_t, chipcontrol), 0x40,
-				   0x40);
-		}
-	}
-
-	if ((!PHY_IPA(pi)) && (pi->sh->chip == BCM5357_CHIP_ID)) {
-		si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
-				   CCTRL5357_EXTPA);
-	}
-
-	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
-	    CHSPEC_IS40(pi->radio_chanspec)) {
-
-		regs = (d11regs_t *) si_switch_core(pi->sh->sih, D11_CORE_ID,
-						    &origidx, &intr_val);
-		ASSERT(regs != NULL);
-
-		d11_clk_ctl_st = R_REG(pi->sh->osh, &regs->clk_ctl_st);
-		AND_REG(pi->sh->osh, &regs->clk_ctl_st,
-			~(CCS_FORCEHT | CCS_HTAREQ));
-
-		W_REG(pi->sh->osh, &regs->clk_ctl_st, d11_clk_ctl_st);
-
-		si_restore_core(pi->sh->sih, origidx, intr_val);
-	}
-
-	pi->use_int_tx_iqlo_cal_nphy =
-	    (PHY_IPA(pi) ||
-	     (NREV_GE(pi->pubpi.phy_rev, 7) ||
-	      (NREV_GE(pi->pubpi.phy_rev, 5)
-	       && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
-
-	pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
-
-	pi->nphy_deaf_count = 0;
-
-	wlc_phy_tbl_init_nphy(pi);
-
-	pi->nphy_crsminpwr_adjusted = false;
-	pi->nphy_noisevars_adjusted = false;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0xe7, 0);
-		write_phy_reg(pi, 0xec, 0);
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			write_phy_reg(pi, 0x342, 0);
-			write_phy_reg(pi, 0x343, 0);
-			write_phy_reg(pi, 0x346, 0);
-			write_phy_reg(pi, 0x347, 0);
-		}
-		write_phy_reg(pi, 0xe5, 0);
-		write_phy_reg(pi, 0xe6, 0);
-	} else {
-		write_phy_reg(pi, 0xec, 0);
-	}
-
-	write_phy_reg(pi, 0x91, 0);
-	write_phy_reg(pi, 0x92, 0);
-	if (NREV_LT(pi->pubpi.phy_rev, 6)) {
-		write_phy_reg(pi, 0x93, 0);
-		write_phy_reg(pi, 0x94, 0);
-	}
-
-	and_phy_reg(pi, 0xa1, ~3);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0x8f, 0);
-		write_phy_reg(pi, 0xa5, 0);
-	} else {
-		write_phy_reg(pi, 0xa5, 0);
-	}
-
-	if (NREV_IS(pi->pubpi.phy_rev, 2))
-		mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
-	else if (NREV_LT(pi->pubpi.phy_rev, 2))
-		mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
-
-	write_phy_reg(pi, 0x203, 32);
-	write_phy_reg(pi, 0x201, 32);
-
-	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
-		write_phy_reg(pi, 0x20d, 160);
-	else
-		write_phy_reg(pi, 0x20d, 184);
-
-	write_phy_reg(pi, 0x13a, 200);
-
-	write_phy_reg(pi, 0x70, 80);
-
-	write_phy_reg(pi, 0x1ff, 48);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 8)) {
-		wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
-	}
-
-	wlc_phy_stf_chain_upd_nphy(pi);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		write_phy_reg(pi, 0x180, 0xaa8);
-		write_phy_reg(pi, 0x181, 0x9a4);
-	}
-
-	if (PHY_IPA(pi)) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 0), (1) << 0);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
-				    0x29c, (0x1ff << 7),
-				    (pi->nphy_papd_epsilon_offset[core]) << 7);
-
-		}
-
-		wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
-	} else {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-			wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
-		}
-	}
-
-	wlc_phy_workarounds_nphy(pi);
-
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
-	val = read_phy_reg(pi, 0x01);
-	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
-	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
-	wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
-
-	wlc_phy_pa_override_nphy(pi, OFF);
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-	wlc_phy_pa_override_nphy(pi, ON);
-
-	wlc_phy_classifier_nphy(pi, 0, 0);
-	wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec))
-		wlc_phy_bphy_init_nphy(pi);
-
-	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-	wlc_phy_txpwr_fixpower_nphy(pi);
-
-	wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
-
-	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		u32 *tx_pwrctrl_tbl = NULL;
-		u16 idx;
-		s16 pga_gn = 0;
-		s16 pad_gn = 0;
-		s32 rfpwr_offset = 0;
-
-		if (PHY_IPA(pi)) {
-			tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
-		} else {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if NREV_IS
-					(pi->pubpi.phy_rev, 3) {
-					tx_pwrctrl_tbl =
-					    nphy_tpc_5GHz_txgain_rev3;
-				} else if NREV_IS
-					(pi->pubpi.phy_rev, 4) {
-					tx_pwrctrl_tbl =
-					    (pi->srom_fem5g.extpagain == 3) ?
-					    nphy_tpc_5GHz_txgain_HiPwrEPA :
-					    nphy_tpc_5GHz_txgain_rev4;
-				} else {
-					tx_pwrctrl_tbl =
-					    nphy_tpc_5GHz_txgain_rev5;
-				}
-
-			} else {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-					if (pi->pubpi.radiorev == 5) {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_epa_2057rev5;
-					} else if (pi->pubpi.radiorev == 3) {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_epa_2057rev3;
-					}
-
-				} else {
-					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
-					    (pi->srom_fem2g.extpagain == 3)) {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_HiPwrEPA;
-					} else {
-						tx_pwrctrl_tbl =
-						    nphy_tpc_txgain_rev3;
-					}
-				}
-			}
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
-					 192, 32, tx_pwrctrl_tbl);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
-					 192, 32, tx_pwrctrl_tbl);
-
-		pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-			for (idx = 0; idx < 128; idx++) {
-				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
-				pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
-
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					if ((pi->pubpi.radiorev == 3) ||
-					    (pi->pubpi.radiorev == 4) ||
-					    (pi->pubpi.radiorev == 6)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_padgain_dlt_2g_2057rev3n4
-						    [pad_gn];
-					} else if (pi->pubpi.radiorev == 5) {
-						rfpwr_offset = (s16)
-						    nphy_papd_padgain_dlt_2g_2057rev5
-						    [pad_gn];
-					} else if ((pi->pubpi.radiorev == 7)
-						   || (pi->pubpi.radiorev ==
-						       8)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_padgain_dlt_2g_2057rev7
-						    [pad_gn];
-					} else {
-						ASSERT(0);
-					}
-
-				} else {
-					if ((pi->pubpi.radiorev == 3) ||
-					    (pi->pubpi.radiorev == 4) ||
-					    (pi->pubpi.radiorev == 6)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_pgagain_dlt_5g_2057
-						    [pga_gn];
-					} else if ((pi->pubpi.radiorev == 7)
-						   || (pi->pubpi.radiorev ==
-						       8)) {
-						rfpwr_offset = (s16)
-						    nphy_papd_pgagain_dlt_5g_2057rev7
-						    [pga_gn];
-					} else {
-						ASSERT(0);
-					}
-				}
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE1TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE2TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-			}
-		} else {
-
-			for (idx = 0; idx < 128; idx++) {
-				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					rfpwr_offset = (s16)
-					    nphy_papd_pga_gain_delta_ipa_2g
-					    [pga_gn];
-				} else {
-					rfpwr_offset = (s16)
-					    nphy_papd_pga_gain_delta_ipa_5g
-					    [pga_gn];
-				}
-
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE1TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_CORE2TXPWRCTL,
-							 1, 576 + idx, 32,
-							 &rfpwr_offset);
-			}
-
-		}
-	} else {
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
-					 192, 32, nphy_tpc_txgain);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
-					 192, 32, nphy_tpc_txgain);
-	}
-
-	if (pi->sh->phyrxchain != 0x3) {
-		wlc_phy_rxcore_setstate_nphy((wlc_phy_t *) pi,
-					     pi->sh->phyrxchain);
-	}
-
-	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
-		wlc_phy_cal_perical_mphase_restart(pi);
-	}
-
-	if (!NORADIO_ENAB(pi->pubpi)) {
-		bool do_rssi_cal = false;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
-			    (pi->nphy_rssical_chanspec_2G == 0) :
-			    (pi->nphy_rssical_chanspec_5G == 0);
-
-			if (do_rssi_cal) {
-				wlc_phy_rssi_cal_nphy(pi);
-			} else {
-				wlc_phy_restore_rssical_nphy(pi);
-			}
-		} else {
-			wlc_phy_rssi_cal_nphy(pi);
-		}
-
-		if (!SCAN_RM_IN_PROGRESS(pi)) {
-			do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
-			    (pi->nphy_iqcal_chanspec_2G == 0) :
-			    (pi->nphy_iqcal_chanspec_5G == 0);
-		}
-
-		if (!pi->do_initcal)
-			do_nphy_cal = false;
-
-		if (do_nphy_cal) {
-
-			target_gain = wlc_phy_get_tx_gain_nphy(pi);
-
-			if (pi->antsel_type == ANTSEL_2x3)
-				wlc_phy_antsel_init((wlc_phy_t *) pi, true);
-
-			if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
-				wlc_phy_rssi_cal_nphy(pi);
-
-				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-					pi->nphy_cal_orig_pwr_idx[0] =
-					    pi->nphy_txpwrindex[PHY_CORE_0].
-					    index_internal;
-					pi->nphy_cal_orig_pwr_idx[1] =
-					    pi->nphy_txpwrindex[PHY_CORE_1].
-					    index_internal;
-
-					wlc_phy_precal_txgain_nphy(pi);
-					target_gain =
-					    wlc_phy_get_tx_gain_nphy(pi);
-				}
-
-				if (wlc_phy_cal_txiqlo_nphy
-				    (pi, target_gain, true, false) == BCME_OK) {
-					if (wlc_phy_cal_rxiq_nphy
-					    (pi, target_gain, 2,
-					     false) == BCME_OK) {
-						wlc_phy_savecal_nphy(pi);
-
-					}
-				}
-			} else if (pi->mphase_cal_phase_id ==
-				   MPHASE_CAL_STATE_IDLE) {
-
-				wlc_phy_cal_perical((wlc_phy_t *) pi,
-						    PHY_PERICAL_PHYINIT);
-			}
-		} else {
-			wlc_phy_restorecal_nphy(pi);
-		}
-	}
-
-	wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-
-	wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
-
-		write_phy_reg(pi, 0x70, 50);
-
-	wlc_phy_txlpfbw_nphy(pi);
-
-	wlc_phy_spurwar_nphy(pi);
-
-}
-
-static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble)
-{
-	bool gf_preamble = false;
-	u16 val;
-
-	if (preamble == WLC_N_PREAMBLE_GF) {
-		gf_preamble = true;
-	}
-
-	val = read_phy_reg(pi, 0xed);
-
-	val |= RX_GF_MM_AUTO;
-	val &= ~RX_GF_OR_MM;
-	if (gf_preamble)
-		val |= RX_GF_OR_MM;
-
-	write_phy_reg(pi, 0xed, val);
-}
-
-static void wlc_phy_resetcca_nphy(phy_info_t *pi)
-{
-	u16 val;
-
-	ASSERT(0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
-	val = read_phy_reg(pi, 0x01);
-	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
-	udelay(1);
-	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
-
-	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-}
-
-void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en)
-{
-	u16 rfctrlintc_override_val;
-
-	if (!en) {
-
-		pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
-		pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			rfctrlintc_override_val = 0x1480;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			rfctrlintc_override_val =
-			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
-		} else {
-			rfctrlintc_override_val =
-			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
-		}
-
-		write_phy_reg(pi, 0x91, rfctrlintc_override_val);
-		write_phy_reg(pi, 0x92, rfctrlintc_override_val);
-	} else {
-
-		write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
-		write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
-	}
-
-}
-
-void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi)
-{
-
-	u16 txrx_chain =
-	    (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
-	bool CoreActv_override = false;
-
-	if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN0) {
-		txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
-		CoreActv_override = true;
-
-		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
-			and_phy_reg(pi, 0xa0, ~0x20);
-		}
-	} else if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN1) {
-		txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
-		CoreActv_override = true;
-
-		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
-			or_phy_reg(pi, 0xa0, 0x20);
-		}
-	}
-
-	mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
-
-	if (CoreActv_override) {
-
-		pi->nphy_perical = PHY_PERICAL_DISABLE;
-		or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
-	} else {
-		pi->nphy_perical = PHY_PERICAL_MPHASE;
-		and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
-	}
-}
-
-void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask)
-{
-	u16 regval;
-	u16 tbl_buf[16];
-	uint i;
-	phy_info_t *pi = (phy_info_t *) pih;
-	u16 tbl_opcode;
-	bool suspend;
-
-	pi->sh->phyrxchain = rxcore_bitmask;
-
-	if (!pi->sh->clk)
-		return;
-
-	suspend =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!suspend)
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	regval = read_phy_reg(pi, 0xa2);
-	regval &= ~(0xf << 4);
-	regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
-	write_phy_reg(pi, 0xa2, regval);
-
-	if ((rxcore_bitmask & 0x3) != 0x3) {
-
-		write_phy_reg(pi, 0x20e, 1);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if (pi->rx2tx_biasentry == -1) {
-				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							ARRAY_SIZE(tbl_buf), 80,
-							16, tbl_buf);
-
-				for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
-					if (tbl_buf[i] ==
-					    NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
-
-						pi->rx2tx_biasentry = (u8) i;
-						tbl_opcode =
-						    NPHY_REV3_RFSEQ_CMD_NOP;
-						wlc_phy_table_write_nphy(pi,
-									 NPHY_TBL_ID_RFSEQ,
-									 1, i,
-									 16,
-									 &tbl_opcode);
-						break;
-					} else if (tbl_buf[i] ==
-						   NPHY_REV3_RFSEQ_CMD_END) {
-						break;
-					}
-				}
-			}
-		}
-	} else {
-
-		write_phy_reg(pi, 0x20e, 30);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if (pi->rx2tx_biasentry != -1) {
-				tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1, pi->rx2tx_biasentry,
-							 16, &tbl_opcode);
-				pi->rx2tx_biasentry = -1;
-			}
-		}
-	}
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	if (!suspend)
-		wlapi_enable_mac(pi->sh->physhim);
-}
-
-u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih)
-{
-	u16 regval, rxen_bits;
-	phy_info_t *pi = (phy_info_t *) pih;
-
-	regval = read_phy_reg(pi, 0xa2);
-	rxen_bits = (regval >> 4) & 0xf;
-
-	return (u8) rxen_bits;
-}
-
-bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pi)
-{
-	return PHY_IPA(pi);
-}
-
-static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi)
-{
-	u8 idx, idx2, i, delta_ind;
-
-	for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
-		pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
-	}
-
-	for (i = 0; i < 4; i++) {
-		idx2 = 0;
-
-		delta_ind = 0;
-
-		switch (i) {
-		case 0:
-
-			if (CHSPEC_IS40(pi->radio_chanspec)
-			    && NPHY_IS_SROM_REINTERPRET) {
-				idx = TXP_FIRST_MCS_40_SISO;
-			} else {
-				idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-				    TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
-				delta_ind = 1;
-			}
-			break;
-
-		case 1:
-
-			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-			    TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
-			break;
-
-		case 2:
-
-			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-			    TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
-			break;
-
-		case 3:
-
-			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
-			    TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
-			break;
-		}
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		idx = idx + delta_ind;
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx++];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		idx = idx + 1 - delta_ind;
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
-		    pi->tx_power_offset[idx];
-	}
-}
-
-void wlc_phy_cal_init_nphy(phy_info_t *pi)
-{
-}
-
-static void wlc_phy_war_force_trsw_to_R_cliplo_nphy(phy_info_t *pi, u8 core)
-{
-	if (core == PHY_CORE_0) {
-		write_phy_reg(pi, 0x38, 0x4);
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x37, 0x0060);
-		} else {
-			write_phy_reg(pi, 0x37, 0x1080);
-		}
-	} else if (core == PHY_CORE_1) {
-		write_phy_reg(pi, 0x2ae, 0x4);
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x2ad, 0x0060);
-		} else {
-			write_phy_reg(pi, 0x2ad, 0x1080);
-		}
-	}
-}
-
-static void wlc_phy_war_txchain_upd_nphy(phy_info_t *pi, u8 txchain)
-{
-	u8 txchain0, txchain1;
-
-	txchain0 = txchain & 0x1;
-	txchain1 = (txchain & 0x2) >> 1;
-	if (!txchain0) {
-		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
-	}
-
-	if (!txchain1) {
-		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
-	}
-}
-
-static void wlc_phy_workarounds_nphy(phy_info_t *pi)
-{
-	u8 rfseq_rx2tx_events[] = {
-		NPHY_RFSEQ_CMD_NOP,
-		NPHY_RFSEQ_CMD_RXG_FBW,
-		NPHY_RFSEQ_CMD_TR_SWITCH,
-		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_RFSEQ_CMD_TX_GAIN,
-		NPHY_RFSEQ_CMD_EXT_PA
-	};
-	u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
-	u8 rfseq_tx2rx_events[] = {
-		NPHY_RFSEQ_CMD_NOP,
-		NPHY_RFSEQ_CMD_EXT_PA,
-		NPHY_RFSEQ_CMD_TX_GAIN,
-		NPHY_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_RFSEQ_CMD_TR_SWITCH,
-		NPHY_RFSEQ_CMD_RXG_FBW,
-		NPHY_RFSEQ_CMD_CLR_HIQ_DIS
-	};
-	u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
-	u8 rfseq_tx2rx_events_rev3[] = {
-		NPHY_REV3_RFSEQ_CMD_EXT_PA,
-		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
-		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
-		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
-		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
-		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_REV3_RFSEQ_CMD_END
-	};
-	u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
-	u8 rfseq_rx2tx_events_rev3[] = {
-		NPHY_REV3_RFSEQ_CMD_NOP,
-		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
-		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
-		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
-		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
-		NPHY_REV3_RFSEQ_CMD_EXT_PA,
-		NPHY_REV3_RFSEQ_CMD_END
-	};
-	u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
-
-	u8 rfseq_rx2tx_events_rev3_ipa[] = {
-		NPHY_REV3_RFSEQ_CMD_NOP,
-		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
-		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
-		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
-		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
-		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
-		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
-		NPHY_REV3_RFSEQ_CMD_END
-	};
-	u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
-	u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
-
-	s16 alpha0, alpha1, alpha2;
-	s16 beta0, beta1, beta2;
-	u32 leg_data_weights, ht_data_weights, nss1_data_weights,
-	    stbc_data_weights;
-	u8 chan_freq_range = 0;
-	u16 dac_control = 0x0002;
-	u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
-	u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
-	u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
-	u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
-	u16 *aux_adc_vmid;
-	u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
-	u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
-	u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
-	u16 *aux_adc_gain;
-	u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
-	u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
-	s32 min_nvar_val = 0x18d;
-	s32 min_nvar_offset_6mbps = 20;
-	u8 pdetrange;
-	u8 triso;
-	u16 regval;
-	u16 afectrl_adc_ctrl1_rev7 = 0x20;
-	u16 afectrl_adc_ctrl2_rev7 = 0x0;
-	u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
-	u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
-	u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
-	u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
-	u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
-	u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
-	u16 ipalvlshift_3p3_war_en = 0;
-	u16 rccal_bcap_val, rccal_scap_val;
-	u16 rccal_tx20_11b_bcap = 0;
-	u16 rccal_tx20_11b_scap = 0;
-	u16 rccal_tx20_11n_bcap = 0;
-	u16 rccal_tx20_11n_scap = 0;
-	u16 rccal_tx40_11n_bcap = 0;
-	u16 rccal_tx40_11n_scap = 0;
-	u16 rx2tx_lpf_rc_lut_tx20_11b = 0;
-	u16 rx2tx_lpf_rc_lut_tx20_11n = 0;
-	u16 rx2tx_lpf_rc_lut_tx40_11n = 0;
-	u16 tx_lpf_bw_ofdm_20mhz = 0;
-	u16 tx_lpf_bw_ofdm_40mhz = 0;
-	u16 tx_lpf_bw_11b = 0;
-	u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt;
-	u16 txgm_idac_bleed = 0;
-	bool rccal_ovrd = false;
-	u16 freq;
-	int coreNum;
-
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
-	} else {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (!ISSIM_ENAB(pi->sh->sih)) {
-		or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-			mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
-
-			mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
-			mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
-			mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
-			mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
-			mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
-			mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
-			mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
-			mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
-			mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
-			mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
-			mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
-			mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
-			mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
-			mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
-			mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
-			mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
-		}
-
-		if (NREV_LE(pi->pubpi.phy_rev, 8)) {
-			write_phy_reg(pi, 0x23f, 0x1b0);
-			write_phy_reg(pi, 0x240, 0x1b0);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-			mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
-					 &dac_control);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
-					 &dac_control);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					1, 0, 32, &leg_data_weights);
-		leg_data_weights = leg_data_weights & 0xffffff;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 0, 32, &leg_data_weights);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-					 2, 0x15e, 16,
-					 rfseq_rx2tx_dacbufpu_rev7);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
-					 rfseq_rx2tx_dacbufpu_rev7);
-
-		if (PHY_IPA(pi)) {
-			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
-					       rfseq_rx2tx_events_rev3_ipa,
-					       rfseq_rx2tx_dlys_rev3_ipa,
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa) /
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa
-						[0]));
-		}
-
-		mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
-		mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
-
-		tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
-		tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
-		tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
-
-		if (PHY_IPA(pi)) {
-
-			if (((pi->pubpi.radiorev == 5)
-			     && (CHSPEC_IS40(pi->radio_chanspec) == 1))
-			    || (pi->pubpi.radiorev == 7)
-			    || (pi->pubpi.radiorev == 8)) {
-
-				rccal_bcap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_BCAP_VAL);
-				rccal_scap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_SCAP_VAL);
-
-				rccal_tx20_11b_bcap = rccal_bcap_val;
-				rccal_tx20_11b_scap = rccal_scap_val;
-
-				if ((pi->pubpi.radiorev == 5) &&
-				    (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
-
-					rccal_tx20_11n_bcap = rccal_bcap_val;
-					rccal_tx20_11n_scap = rccal_scap_val;
-					rccal_tx40_11n_bcap = 0xc;
-					rccal_tx40_11n_scap = 0xc;
-
-					rccal_ovrd = true;
-
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-
-					tx_lpf_bw_ofdm_20mhz = 4;
-					tx_lpf_bw_11b = 1;
-
-					if (CHSPEC_IS2G(pi->radio_chanspec)) {
-						rccal_tx20_11n_bcap = 0xc;
-						rccal_tx20_11n_scap = 0xc;
-						rccal_tx40_11n_bcap = 0xa;
-						rccal_tx40_11n_scap = 0xa;
-					} else {
-						rccal_tx20_11n_bcap = 0x14;
-						rccal_tx20_11n_scap = 0x14;
-						rccal_tx40_11n_bcap = 0xf;
-						rccal_tx40_11n_scap = 0xf;
-					}
-
-					rccal_ovrd = true;
-				}
-			}
-
-		} else {
-
-			if (pi->pubpi.radiorev == 5) {
-
-				tx_lpf_bw_ofdm_20mhz = 1;
-				tx_lpf_bw_ofdm_40mhz = 3;
-
-				rccal_bcap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_BCAP_VAL);
-				rccal_scap_val =
-				    read_radio_reg(pi,
-						   RADIO_2057_RCCAL_SCAP_VAL);
-
-				rccal_tx20_11b_bcap = rccal_bcap_val;
-				rccal_tx20_11b_scap = rccal_scap_val;
-
-				rccal_tx20_11n_bcap = 0x13;
-				rccal_tx20_11n_scap = 0x11;
-				rccal_tx40_11n_bcap = 0x13;
-				rccal_tx40_11n_scap = 0x11;
-
-				rccal_ovrd = true;
-			}
-		}
-
-		if (rccal_ovrd) {
-
-			rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
-			    (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
-			rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
-			    (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
-			rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
-			    (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
-
-			for (coreNum = 0; coreNum <= 1; coreNum++) {
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x152 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx20_11b);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x153 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx20_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x154 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx20_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x155 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x156 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x157 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x158 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-							 1,
-							 0x159 + coreNum * 0x10,
-							 16,
-							 &rx2tx_lpf_rc_lut_tx40_11n);
-			}
-
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
-							  1, 0x3, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		}
-
-		if (!NORADIO_ENAB(pi->pubpi)) {
-			write_phy_reg(pi, 0x32f, 0x3);
-		}
-
-		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  1, 0x3, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		}
-
-		if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
-		    (pi->pubpi.radiorev == 6)) {
-			if ((pi->sh->sromrev >= 8)
-			    && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
-				ipalvlshift_3p3_war_en = 1;
-
-			if (ipalvlshift_3p3_war_en) {
-				write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG,
-						0x5);
-				write_radio_reg(pi, RADIO_2057_GPAIO_SEL1,
-						0x30);
-				write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
-				or_radio_reg(pi,
-					     RADIO_2057_RXTXBIAS_CONFIG_CORE0,
-					     0x1);
-				or_radio_reg(pi,
-					     RADIO_2057_RXTXBIAS_CONFIG_CORE1,
-					     0x1);
-
-				ipa2g_mainbias = 0x1f;
-
-				ipa2g_casconv = 0x6f;
-
-				ipa2g_biasfilt = 0xaa;
-			} else {
-
-				ipa2g_mainbias = 0x2b;
-
-				ipa2g_casconv = 0x7f;
-
-				ipa2g_biasfilt = 0xee;
-			}
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				for (coreNum = 0; coreNum <= 1; coreNum++) {
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum, IPA2G_IMAIN,
-							 ipa2g_mainbias);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum, IPA2G_CASCONV,
-							 ipa2g_casconv);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum,
-							 IPA2G_BIAS_FILTER,
-							 ipa2g_biasfilt);
-				}
-			}
-		}
-
-		if (PHY_IPA(pi)) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				if ((pi->pubpi.radiorev == 3)
-				    || (pi->pubpi.radiorev == 4)
-				    || (pi->pubpi.radiorev == 6)) {
-
-					txgm_idac_bleed = 0x7f;
-				}
-
-				for (coreNum = 0; coreNum <= 1; coreNum++) {
-					if (txgm_idac_bleed != 0)
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 TXGM_IDAC_BLEED,
-								 txgm_idac_bleed);
-				}
-
-				if (pi->pubpi.radiorev == 5) {
-
-					for (coreNum = 0; coreNum <= 1;
-					     coreNum++) {
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 IPA2G_CASCONV,
-								 0x13);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 IPA2G_IMAIN,
-								 0x1f);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 IPA2G_BIAS_FILTER,
-								 0xee);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 PAD2G_IDACS,
-								 0x8a);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, coreNum,
-								 PAD_BIAS_FILTER_BWS,
-								 0x3e);
-					}
-
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-
-					if (CHSPEC_IS40(pi->radio_chanspec) ==
-					    0) {
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 0,
-								 IPA2G_IMAIN,
-								 0x14);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 1,
-								 IPA2G_IMAIN,
-								 0x12);
-					} else {
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 0,
-								 IPA2G_IMAIN,
-								 0x16);
-						WRITE_RADIO_REG4(pi, RADIO_2057,
-								 CORE, 1,
-								 IPA2G_IMAIN,
-								 0x16);
-					}
-				}
-
-			} else {
-				freq =
-				    CHAN5G_FREQ(CHSPEC_CHANNEL
-						(pi->radio_chanspec));
-				if (((freq >= 5180) && (freq <= 5230))
-				    || ((freq >= 5745) && (freq <= 5805))) {
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 0, IPA5G_BIAS_FILTER,
-							 0xff);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 1, IPA5G_BIAS_FILTER,
-							 0xff);
-				}
-			}
-		} else {
-
-			if (pi->pubpi.radiorev != 5) {
-				for (coreNum = 0; coreNum <= 1; coreNum++) {
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum,
-							 TXMIX2G_TUNE_BOOST_PU,
-							 0x61);
-					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
-							 coreNum,
-							 TXGM_IDAC_BLEED, 0x70);
-				}
-			}
-		}
-
-		if (pi->pubpi.radiorev == 4) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x05, 16,
-						 &afectrl_adc_ctrl1_rev7);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x15, 16,
-						 &afectrl_adc_ctrl1_rev7);
-
-			for (coreNum = 0; coreNum <= 1; coreNum++) {
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 AFE_VCM_CAL_MASTER, 0x0);
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 AFE_SET_VCM_I, 0x3f);
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 AFE_SET_VCM_Q, 0x3f);
-			}
-		} else {
-			mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
-			mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
-			mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
-			mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
-
-			mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
-			mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
-			mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
-			mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x05, 16,
-						 &afectrl_adc_ctrl2_rev7);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
-						 0x15, 16,
-						 &afectrl_adc_ctrl2_rev7);
-
-			mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
-			mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
-			mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
-			mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
-		}
-
-		write_phy_reg(pi, 0x6a, 0x2);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
-					 &min_nvar_offset_6mbps);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
-					 &rfseq_pktgn_lpf_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
-					 &rfseq_pktgn_lpf_h_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
-					 &rfseq_htpktgn_lpf_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
-					 &rfseq_cckpktgn_lpf_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
-					 &rfseq_tx2rx_lpf_h_hpc_rev7);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
-					 &rfseq_rx2tx_lpf_h_hpc_rev7);
-
-		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		} else {
-			min_nvar_val = noise_var_tbl_rev7[3];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-
-			min_nvar_val = noise_var_tbl_rev7[127];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		}
-
-		wlc_phy_workarounds_nphy_gainctrl(pi);
-
-		pdetrange =
-		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
-		    pdetrange : pi->srom_fem2g.pdetrange;
-
-		if (pdetrange == 0) {
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x70;
-				aux_adc_vmid_rev7_core1[3] = 0x70;
-				aux_adc_gain_rev7[3] = 2;
-			} else {
-				aux_adc_vmid_rev7_core0[3] = 0x80;
-				aux_adc_vmid_rev7_core1[3] = 0x80;
-				aux_adc_gain_rev7[3] = 3;
-			}
-		} else if (pdetrange == 1) {
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x7c;
-				aux_adc_vmid_rev7_core1[3] = 0x7c;
-				aux_adc_gain_rev7[3] = 2;
-			} else {
-				aux_adc_vmid_rev7_core0[3] = 0x8c;
-				aux_adc_vmid_rev7_core1[3] = 0x8c;
-				aux_adc_gain_rev7[3] = 1;
-			}
-		} else if (pdetrange == 2) {
-			if (pi->pubpi.radioid == BCM2057_ID) {
-				if ((pi->pubpi.radiorev == 5)
-				    || (pi->pubpi.radiorev == 7)
-				    || (pi->pubpi.radiorev == 8)) {
-					if (chan_freq_range ==
-					    WL_CHAN_FREQ_RANGE_2G) {
-						aux_adc_vmid_rev7_core0[3] =
-						    0x8c;
-						aux_adc_vmid_rev7_core1[3] =
-						    0x8c;
-						aux_adc_gain_rev7[3] = 0;
-					} else {
-						aux_adc_vmid_rev7_core0[3] =
-						    0x96;
-						aux_adc_vmid_rev7_core1[3] =
-						    0x96;
-						aux_adc_gain_rev7[3] = 0;
-					}
-				}
-			}
-
-		} else if (pdetrange == 3) {
-			if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x89;
-				aux_adc_vmid_rev7_core1[3] = 0x89;
-				aux_adc_gain_rev7[3] = 0;
-			}
-
-		} else if (pdetrange == 5) {
-
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				aux_adc_vmid_rev7_core0[3] = 0x80;
-				aux_adc_vmid_rev7_core1[3] = 0x80;
-				aux_adc_gain_rev7[3] = 3;
-			} else {
-				aux_adc_vmid_rev7_core0[3] = 0x70;
-				aux_adc_vmid_rev7_core1[3] = 0x70;
-				aux_adc_gain_rev7[3] = 2;
-			}
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
-					 &aux_adc_vmid_rev7_core0);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
-					 &aux_adc_vmid_rev7_core1);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
-					 &aux_adc_gain_rev7);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
-					 &aux_adc_gain_rev7);
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		write_phy_reg(pi, 0x23f, 0x1f8);
-		write_phy_reg(pi, 0x240, 0x1f8);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					1, 0, 32, &leg_data_weights);
-		leg_data_weights = leg_data_weights & 0xffffff;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 0, 32, &leg_data_weights);
-
-		alpha0 = 293;
-		alpha1 = 435;
-		alpha2 = 261;
-		beta0 = 366;
-		beta1 = 205;
-		beta2 = 32;
-		write_phy_reg(pi, 0x145, alpha0);
-		write_phy_reg(pi, 0x146, alpha1);
-		write_phy_reg(pi, 0x147, alpha2);
-		write_phy_reg(pi, 0x148, beta0);
-		write_phy_reg(pi, 0x149, beta1);
-		write_phy_reg(pi, 0x14a, beta2);
-
-		write_phy_reg(pi, 0x38, 0xC);
-		write_phy_reg(pi, 0x2ae, 0xC);
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
-				       rfseq_tx2rx_events_rev3,
-				       rfseq_tx2rx_dlys_rev3,
-				       sizeof(rfseq_tx2rx_events_rev3) /
-				       sizeof(rfseq_tx2rx_events_rev3[0]));
-
-		if (PHY_IPA(pi)) {
-			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
-					       rfseq_rx2tx_events_rev3_ipa,
-					       rfseq_rx2tx_dlys_rev3_ipa,
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa) /
-					       sizeof
-					       (rfseq_rx2tx_events_rev3_ipa
-						[0]));
-		}
-
-		if ((pi->sh->hw_phyrxchain != 0x3) &&
-		    (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
-
-			if (PHY_IPA(pi)) {
-				rfseq_rx2tx_dlys_rev3[5] = 59;
-				rfseq_rx2tx_dlys_rev3[6] = 1;
-				rfseq_rx2tx_events_rev3[7] =
-				    NPHY_REV3_RFSEQ_CMD_END;
-			}
-
-			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
-					       rfseq_rx2tx_events_rev3,
-					       rfseq_rx2tx_dlys_rev3,
-					       sizeof(rfseq_rx2tx_events_rev3) /
-					       sizeof(rfseq_rx2tx_events_rev3
-						      [0]));
-		}
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x6a, 0x2);
-		} else {
-			write_phy_reg(pi, 0x6a, 0x9c40);
-		}
-
-		mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
-
-		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		} else {
-			min_nvar_val = noise_var_tbl_rev3[3];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
-						 32, &min_nvar_val);
-
-			min_nvar_val = noise_var_tbl_rev3[127];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 127, 32, &min_nvar_val);
-		}
-
-		wlc_phy_workarounds_nphy_gainctrl(pi);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
-					 &dac_control);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
-					 &dac_control);
-
-		pdetrange =
-		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
-		    pdetrange : pi->srom_fem2g.pdetrange;
-
-		if (pdetrange == 0) {
-			if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-				aux_adc_vmid = aux_adc_vmid_rev4;
-				aux_adc_gain = aux_adc_gain_rev4;
-			} else {
-				aux_adc_vmid = aux_adc_vmid_rev3;
-				aux_adc_gain = aux_adc_gain_rev3;
-			}
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				switch (chan_freq_range) {
-				case WL_CHAN_FREQ_RANGE_5GL:
-					aux_adc_vmid[3] = 0x89;
-					aux_adc_gain[3] = 0;
-					break;
-				case WL_CHAN_FREQ_RANGE_5GM:
-					aux_adc_vmid[3] = 0x89;
-					aux_adc_gain[3] = 0;
-					break;
-				case WL_CHAN_FREQ_RANGE_5GH:
-					aux_adc_vmid[3] = 0x89;
-					aux_adc_gain[3] = 0;
-					break;
-				default:
-					break;
-				}
-			}
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, aux_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, aux_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, aux_adc_gain);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, aux_adc_gain);
-		} else if (pdetrange == 1) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, sk_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, sk_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, sk_adc_gain);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, sk_adc_gain);
-		} else if (pdetrange == 2) {
-
-			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
-			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
-
-			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-				chan_freq_range =
-				    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-				if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-					bcm_adc_vmid[3] = 0x8e;
-					bcm_adc_gain[3] = 0x03;
-				} else {
-					bcm_adc_vmid[3] = 0x94;
-					bcm_adc_gain[3] = 0x03;
-				}
-			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-				bcm_adc_vmid[3] = 0x84;
-				bcm_adc_gain[3] = 0x02;
-			}
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, bcm_adc_gain);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, bcm_adc_gain);
-		} else if (pdetrange == 3) {
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if ((NREV_GE(pi->pubpi.phy_rev, 4))
-			    && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
-
-				u16 auxadc_vmid[] = {
-					0xa2, 0xb4, 0xb4, 0x270 };
-				u16 auxadc_gain[] = {
-					0x02, 0x02, 0x02, 0x00 };
-
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x08, 16, auxadc_vmid);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x18, 16, auxadc_vmid);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x0c, 16, auxadc_gain);
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_AFECTRL, 4,
-							 0x1c, 16, auxadc_gain);
-			}
-		} else if ((pdetrange == 4) || (pdetrange == 5)) {
-			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
-			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
-			u16 Vmid[2], Av[2];
-
-			chan_freq_range =
-			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
-			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
-				Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
-				Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
-				Av[0] = (pdetrange == 4) ? 2 : 0;
-				Av[1] = (pdetrange == 4) ? 2 : 0;
-			} else {
-				Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
-				Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
-				Av[0] = (pdetrange == 4) ? 2 : 0;
-				Av[1] = (pdetrange == 4) ? 2 : 0;
-			}
-
-			bcm_adc_vmid[3] = Vmid[0];
-			bcm_adc_gain[3] = Av[0];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x08, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x0c, 16, bcm_adc_gain);
-
-			bcm_adc_vmid[3] = Vmid[1];
-			bcm_adc_gain[3] = Av[1];
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x18, 16, bcm_adc_vmid);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
-						 0x1c, 16, bcm_adc_gain);
-		} else {
-			ASSERT(0);
-		}
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1),
-				0x0);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0),
-				0x6);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1),
-				0x6);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0),
-				0x7);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1),
-				0x7);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0),
-				0x88);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1),
-				0x88);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1),
-				0x0);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1),
-				0x0);
-
-		triso =
-		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
-		    triso : pi->srom_fem2g.triso;
-		if (triso == 7) {
-			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
-			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
-		}
-
-		wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
-
-		if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
-		     (CHSPEC_IS5G(pi->radio_chanspec))) ||
-		    (((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
-		      (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
-		     (CHSPEC_IS2G(pi->radio_chanspec)))) {
-			nss1_data_weights = 0x00088888;
-			ht_data_weights = 0x00088888;
-			stbc_data_weights = 0x00088888;
-		} else {
-			nss1_data_weights = 0x88888888;
-			ht_data_weights = 0x88888888;
-			stbc_data_weights = 0x88888888;
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 1, 32, &nss1_data_weights);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 2, 32, &ht_data_weights);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
-					 1, 3, 32, &stbc_data_weights);
-
-		if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2056_TX_GMBB_IDAC |
-						RADIO_2056_TX0, 0x70);
-				write_radio_reg(pi,
-						RADIO_2056_TX_GMBB_IDAC |
-						RADIO_2056_TX1, 0x70);
-			}
-		}
-
-		if (!pi->edcrs_threshold_lock) {
-			write_phy_reg(pi, 0x224, 0x3eb);
-			write_phy_reg(pi, 0x225, 0x3eb);
-			write_phy_reg(pi, 0x226, 0x341);
-			write_phy_reg(pi, 0x227, 0x341);
-			write_phy_reg(pi, 0x228, 0x42b);
-			write_phy_reg(pi, 0x229, 0x42b);
-			write_phy_reg(pi, 0x22a, 0x381);
-			write_phy_reg(pi, 0x22b, 0x381);
-			write_phy_reg(pi, 0x22c, 0x42b);
-			write_phy_reg(pi, 0x22d, 0x42b);
-			write_phy_reg(pi, 0x22e, 0x381);
-			write_phy_reg(pi, 0x22f, 0x381);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-
-			if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
-				wlapi_bmac_mhf(pi->sh->physhim, MHF4,
-					       MHF4_BPHY_TXCORE0,
-					       MHF4_BPHY_TXCORE0, WLC_BAND_ALL);
-			}
-		}
-	} else {
-
-		if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
-		    (pi->sh->boardtype == 0x8b)) {
-			uint i;
-			u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
-			for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
-				rfseq_rx2tx_dlys[i] = war_dlys[i];
-		}
-
-		if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
-			and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
-			and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
-		} else {
-			or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
-			or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
-		}
-
-		regval = 0x000a;
-		wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
-		wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-			regval = 0xcdaa;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
-		}
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-			regval = 0x0000;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
-
-			regval = 0x7aab;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
-
-			regval = 0x0800;
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
-			wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
-		}
-
-		write_phy_reg(pi, 0xf8, 0x02d8);
-		write_phy_reg(pi, 0xf9, 0x0301);
-		write_phy_reg(pi, 0xfa, 0x02d8);
-		write_phy_reg(pi, 0xfb, 0x0301);
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
-				       rfseq_rx2tx_dlys,
-				       sizeof(rfseq_rx2tx_events) /
-				       sizeof(rfseq_rx2tx_events[0]));
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
-				       rfseq_tx2rx_dlys,
-				       sizeof(rfseq_tx2rx_events) /
-				       sizeof(rfseq_tx2rx_events[0]));
-
-		wlc_phy_workarounds_nphy_gainctrl(pi);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-			if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
-				wlapi_bmac_mhf(pi->sh->physhim, MHF3,
-					       MHF3_NPHY_MLADV_WAR,
-					       MHF3_NPHY_MLADV_WAR,
-					       WLC_BAND_ALL);
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
-			write_phy_reg(pi, 0x1e3, 0x0);
-			write_phy_reg(pi, 0x1e4, 0x0);
-		}
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
-
-		alpha0 = 293;
-		alpha1 = 435;
-		alpha2 = 261;
-		beta0 = 366;
-		beta1 = 205;
-		beta2 = 32;
-		write_phy_reg(pi, 0x145, alpha0);
-		write_phy_reg(pi, 0x146, alpha1);
-		write_phy_reg(pi, 0x147, alpha2);
-		write_phy_reg(pi, 0x148, beta0);
-		write_phy_reg(pi, 0x149, beta1);
-		write_phy_reg(pi, 0x14a, beta2);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-			mod_phy_reg(pi, 0x142, (0xf << 12), 0);
-
-			write_phy_reg(pi, 0x192, 0xb5);
-			write_phy_reg(pi, 0x193, 0xa4);
-			write_phy_reg(pi, 0x194, 0x0);
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
-			mod_phy_reg(pi, 0x221,
-				    NPHY_FORCESIG_DECODEGATEDCLKS,
-				    NPHY_FORCESIG_DECODEGATEDCLKS);
-		}
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi)
-{
-	u16 w1th, hpf_code, currband;
-	int ctr;
-	u8 rfseq_updategainu_events[] = {
-		NPHY_RFSEQ_CMD_RX_GAIN,
-		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
-		NPHY_RFSEQ_CMD_SET_HPF_BW
-	};
-	u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
-	s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
-	s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
-	s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
-	s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
-	s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
-	s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
-	s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
-	s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
-	s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
-	s8 *lna1_gain_db = NULL;
-	s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
-	s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
-	s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
-	s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
-	s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
-	s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
-	s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
-	s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
-	s8 *lna2_gain_db = NULL;
-	s8 tiaG_gain_db[] = {
-		0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
-	s8 tiaA_gain_db[] = {
-		0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
-	s8 tiaA_gain_db_rev4[] = {
-		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
-	s8 tiaA_gain_db_rev5[] = {
-		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
-	s8 tiaA_gain_db_rev6[] = {
-		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
-	s8 *tia_gain_db;
-	s8 tiaG_gainbits[] = {
-		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
-	s8 tiaA_gainbits[] = {
-		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
-	s8 tiaA_gainbits_rev4[] = {
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
-	s8 tiaA_gainbits_rev5[] = {
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
-	s8 tiaA_gainbits_rev6[] = {
-		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
-	s8 *tia_gainbits;
-	s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
-	s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
-	u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
-	u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
-	u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
-	u16 rfseqG_init_gain_rev5_elna[] = {
-		0x013f, 0x013f, 0x013f, 0x013f };
-	u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
-	u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
-	u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
-	u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
-	u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
-	u16 rfseqA_init_gain_rev4_elna[] = {
-		0x314f, 0x314f, 0x314f, 0x314f };
-	u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
-	u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
-	u16 *rfseq_init_gain;
-	u16 initG_gaincode = 0x627e;
-	u16 initG_gaincode_rev4 = 0x527e;
-	u16 initG_gaincode_rev5 = 0x427e;
-	u16 initG_gaincode_rev5_elna = 0x027e;
-	u16 initG_gaincode_rev6 = 0x527e;
-	u16 initG_gaincode_rev6_224B0 = 0x427e;
-	u16 initG_gaincode_rev6_elna = 0x127e;
-	u16 initA_gaincode = 0x52de;
-	u16 initA_gaincode_rev4 = 0x629e;
-	u16 initA_gaincode_rev4_elna = 0x329e;
-	u16 initA_gaincode_rev5 = 0x729e;
-	u16 initA_gaincode_rev6 = 0x729e;
-	u16 init_gaincode;
-	u16 clip1hiG_gaincode = 0x107e;
-	u16 clip1hiG_gaincode_rev4 = 0x007e;
-	u16 clip1hiG_gaincode_rev5 = 0x1076;
-	u16 clip1hiG_gaincode_rev6 = 0x007e;
-	u16 clip1hiA_gaincode = 0x00de;
-	u16 clip1hiA_gaincode_rev4 = 0x029e;
-	u16 clip1hiA_gaincode_rev5 = 0x029e;
-	u16 clip1hiA_gaincode_rev6 = 0x029e;
-	u16 clip1hi_gaincode;
-	u16 clip1mdG_gaincode = 0x0066;
-	u16 clip1mdA_gaincode = 0x00ca;
-	u16 clip1mdA_gaincode_rev4 = 0x1084;
-	u16 clip1mdA_gaincode_rev5 = 0x2084;
-	u16 clip1mdA_gaincode_rev6 = 0x2084;
-	u16 clip1md_gaincode = 0;
-	u16 clip1loG_gaincode = 0x0074;
-	u16 clip1loG_gaincode_rev5[] = {
-		0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
-	};
-	u16 clip1loG_gaincode_rev6[] = {
-		0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
-	};
-	u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
-	u16 clip1loA_gaincode = 0x00cc;
-	u16 clip1loA_gaincode_rev4 = 0x0086;
-	u16 clip1loA_gaincode_rev5 = 0x2086;
-	u16 clip1loA_gaincode_rev6 = 0x2086;
-	u16 clip1lo_gaincode;
-	u8 crsminG_th = 0x18;
-	u8 crsminG_th_rev5 = 0x18;
-	u8 crsminG_th_rev6 = 0x18;
-	u8 crsminA_th = 0x1e;
-	u8 crsminA_th_rev4 = 0x24;
-	u8 crsminA_th_rev5 = 0x24;
-	u8 crsminA_th_rev6 = 0x24;
-	u8 crsmin_th;
-	u8 crsminlG_th = 0x18;
-	u8 crsminlG_th_rev5 = 0x18;
-	u8 crsminlG_th_rev6 = 0x18;
-	u8 crsminlA_th = 0x1e;
-	u8 crsminlA_th_rev4 = 0x24;
-	u8 crsminlA_th_rev5 = 0x24;
-	u8 crsminlA_th_rev6 = 0x24;
-	u8 crsminl_th = 0;
-	u8 crsminuG_th = 0x18;
-	u8 crsminuG_th_rev5 = 0x18;
-	u8 crsminuG_th_rev6 = 0x18;
-	u8 crsminuA_th = 0x1e;
-	u8 crsminuA_th_rev4 = 0x24;
-	u8 crsminuA_th_rev5 = 0x24;
-	u8 crsminuA_th_rev6 = 0x24;
-	u8 crsminuA_th_rev6_224B0 = 0x2d;
-	u8 crsminu_th;
-	u16 nbclipG_th = 0x20d;
-	u16 nbclipG_th_rev4 = 0x1a1;
-	u16 nbclipG_th_rev5 = 0x1d0;
-	u16 nbclipG_th_rev6 = 0x1d0;
-	u16 nbclipA_th = 0x1a1;
-	u16 nbclipA_th_rev4 = 0x107;
-	u16 nbclipA_th_rev5 = 0x0a9;
-	u16 nbclipA_th_rev6 = 0x0f0;
-	u16 nbclip_th = 0;
-	u8 w1clipG_th = 5;
-	u8 w1clipG_th_rev5 = 9;
-	u8 w1clipG_th_rev6 = 5;
-	u8 w1clipA_th = 25, w1clip_th;
-	u8 rssi_gain_default = 0x50;
-	u8 rssiG_gain_rev6_224B0 = 0x50;
-	u8 rssiA_gain_rev5 = 0x90;
-	u8 rssiA_gain_rev6 = 0x90;
-	u8 rssi_gain;
-	u16 regval[21];
-	u8 triso;
-
-	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
-	    pi->srom_fem2g.triso;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		if (pi->pubpi.radiorev == 5) {
-
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
-		} else if (pi->pubpi.radiorev == 7) {
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
-
-			mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
-			mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
-
-		} else if ((pi->pubpi.radiorev == 3)
-			   || (pi->pubpi.radiorev == 8)) {
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
-
-			if (pi->pubpi.radiorev == 8) {
-				mod_phy_reg(pi, 0x283,
-					    (0xff << 0), (0x44 << 0));
-				mod_phy_reg(pi, 0x280,
-					    (0xff << 0), (0x44 << 0));
-			}
-		} else {
-			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
-		}
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
-
-		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-		currband =
-		    read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
-		if (currband == 0) {
-			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-				if (pi->pubpi.radiorev == 11) {
-					lna1_gain_db = lna1G_gain_db_rev6_224B0;
-					lna2_gain_db = lna2G_gain_db_rev6_224B0;
-					rfseq_init_gain =
-					    rfseqG_init_gain_rev6_224B0;
-					init_gaincode =
-					    initG_gaincode_rev6_224B0;
-					clip1hi_gaincode =
-					    clip1hiG_gaincode_rev6;
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev6_224B0;
-					nbclip_th = nbclipG_th_rev6;
-					w1clip_th = w1clipG_th_rev6;
-					crsmin_th = crsminG_th_rev6;
-					crsminl_th = crsminlG_th_rev6;
-					crsminu_th = crsminuG_th_rev6;
-					rssi_gain = rssiG_gain_rev6_224B0;
-				} else {
-					lna1_gain_db = lna1G_gain_db_rev6;
-					lna2_gain_db = lna2G_gain_db_rev6;
-					if (pi->sh->boardflags & BFL_EXTLNA) {
-
-						rfseq_init_gain =
-						    rfseqG_init_gain_rev6_elna;
-						init_gaincode =
-						    initG_gaincode_rev6_elna;
-					} else {
-						rfseq_init_gain =
-						    rfseqG_init_gain_rev6;
-						init_gaincode =
-						    initG_gaincode_rev6;
-					}
-					clip1hi_gaincode =
-					    clip1hiG_gaincode_rev6;
-					switch (triso) {
-					case 0:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[0];
-						break;
-					case 1:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[1];
-						break;
-					case 2:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[2];
-						break;
-					case 3:
-					default:
-
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[3];
-						break;
-					case 4:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[4];
-						break;
-					case 5:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[5];
-						break;
-					case 6:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[6];
-						break;
-					case 7:
-						clip1lo_gaincode =
-						    clip1loG_gaincode_rev6[7];
-						break;
-					}
-					nbclip_th = nbclipG_th_rev6;
-					w1clip_th = w1clipG_th_rev6;
-					crsmin_th = crsminG_th_rev6;
-					crsminl_th = crsminlG_th_rev6;
-					crsminu_th = crsminuG_th_rev6;
-					rssi_gain = rssi_gain_default;
-				}
-			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-				lna1_gain_db = lna1G_gain_db_rev5;
-				lna2_gain_db = lna2G_gain_db_rev5;
-				if (pi->sh->boardflags & BFL_EXTLNA) {
-
-					rfseq_init_gain =
-					    rfseqG_init_gain_rev5_elna;
-					init_gaincode =
-					    initG_gaincode_rev5_elna;
-				} else {
-					rfseq_init_gain = rfseqG_init_gain_rev5;
-					init_gaincode = initG_gaincode_rev5;
-				}
-				clip1hi_gaincode = clip1hiG_gaincode_rev5;
-				switch (triso) {
-				case 0:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[0];
-					break;
-				case 1:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[1];
-					break;
-				case 2:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[2];
-					break;
-				case 3:
-
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[3];
-					break;
-				case 4:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[4];
-					break;
-				case 5:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[5];
-					break;
-				case 6:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[6];
-					break;
-				case 7:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[7];
-					break;
-				default:
-					clip1lo_gaincode =
-					    clip1loG_gaincode_rev5[3];
-					break;
-				}
-				nbclip_th = nbclipG_th_rev5;
-				w1clip_th = w1clipG_th_rev5;
-				crsmin_th = crsminG_th_rev5;
-				crsminl_th = crsminlG_th_rev5;
-				crsminu_th = crsminuG_th_rev5;
-				rssi_gain = rssi_gain_default;
-			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-				lna1_gain_db = lna1G_gain_db_rev4;
-				lna2_gain_db = lna2G_gain_db;
-				rfseq_init_gain = rfseqG_init_gain_rev4;
-				init_gaincode = initG_gaincode_rev4;
-				clip1hi_gaincode = clip1hiG_gaincode_rev4;
-				clip1lo_gaincode = clip1loG_gaincode;
-				nbclip_th = nbclipG_th_rev4;
-				w1clip_th = w1clipG_th;
-				crsmin_th = crsminG_th;
-				crsminl_th = crsminlG_th;
-				crsminu_th = crsminuG_th;
-				rssi_gain = rssi_gain_default;
-			} else {
-				lna1_gain_db = lna1G_gain_db;
-				lna2_gain_db = lna2G_gain_db;
-				rfseq_init_gain = rfseqG_init_gain;
-				init_gaincode = initG_gaincode;
-				clip1hi_gaincode = clip1hiG_gaincode;
-				clip1lo_gaincode = clip1loG_gaincode;
-				nbclip_th = nbclipG_th;
-				w1clip_th = w1clipG_th;
-				crsmin_th = crsminG_th;
-				crsminl_th = crsminlG_th;
-				crsminu_th = crsminuG_th;
-				rssi_gain = rssi_gain_default;
-			}
-			tia_gain_db = tiaG_gain_db;
-			tia_gainbits = tiaG_gainbits;
-			clip1md_gaincode = clip1mdG_gaincode;
-		} else {
-			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-				lna1_gain_db = lna1A_gain_db_rev6;
-				lna2_gain_db = lna2A_gain_db_rev6;
-				tia_gain_db = tiaA_gain_db_rev6;
-				tia_gainbits = tiaA_gainbits_rev6;
-				rfseq_init_gain = rfseqA_init_gain_rev6;
-				init_gaincode = initA_gaincode_rev6;
-				clip1hi_gaincode = clip1hiA_gaincode_rev6;
-				clip1md_gaincode = clip1mdA_gaincode_rev6;
-				clip1lo_gaincode = clip1loA_gaincode_rev6;
-				crsmin_th = crsminA_th_rev6;
-				crsminl_th = crsminlA_th_rev6;
-				if ((pi->pubpi.radiorev == 11) &&
-				    (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
-					crsminu_th = crsminuA_th_rev6_224B0;
-				} else {
-					crsminu_th = crsminuA_th_rev6;
-				}
-				nbclip_th = nbclipA_th_rev6;
-				rssi_gain = rssiA_gain_rev6;
-			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-				lna1_gain_db = lna1A_gain_db_rev5;
-				lna2_gain_db = lna2A_gain_db_rev5;
-				tia_gain_db = tiaA_gain_db_rev5;
-				tia_gainbits = tiaA_gainbits_rev5;
-				rfseq_init_gain = rfseqA_init_gain_rev5;
-				init_gaincode = initA_gaincode_rev5;
-				clip1hi_gaincode = clip1hiA_gaincode_rev5;
-				clip1md_gaincode = clip1mdA_gaincode_rev5;
-				clip1lo_gaincode = clip1loA_gaincode_rev5;
-				crsmin_th = crsminA_th_rev5;
-				crsminl_th = crsminlA_th_rev5;
-				crsminu_th = crsminuA_th_rev5;
-				nbclip_th = nbclipA_th_rev5;
-				rssi_gain = rssiA_gain_rev5;
-			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-				lna1_gain_db = lna1A_gain_db_rev4;
-				lna2_gain_db = lna2A_gain_db_rev4;
-				tia_gain_db = tiaA_gain_db_rev4;
-				tia_gainbits = tiaA_gainbits_rev4;
-				if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
-
-					rfseq_init_gain =
-					    rfseqA_init_gain_rev4_elna;
-					init_gaincode =
-					    initA_gaincode_rev4_elna;
-				} else {
-					rfseq_init_gain = rfseqA_init_gain_rev4;
-					init_gaincode = initA_gaincode_rev4;
-				}
-				clip1hi_gaincode = clip1hiA_gaincode_rev4;
-				clip1md_gaincode = clip1mdA_gaincode_rev4;
-				clip1lo_gaincode = clip1loA_gaincode_rev4;
-				crsmin_th = crsminA_th_rev4;
-				crsminl_th = crsminlA_th_rev4;
-				crsminu_th = crsminuA_th_rev4;
-				nbclip_th = nbclipA_th_rev4;
-				rssi_gain = rssi_gain_default;
-			} else {
-				lna1_gain_db = lna1A_gain_db;
-				lna2_gain_db = lna2A_gain_db;
-				tia_gain_db = tiaA_gain_db;
-				tia_gainbits = tiaA_gainbits;
-				rfseq_init_gain = rfseqA_init_gain;
-				init_gaincode = initA_gaincode;
-				clip1hi_gaincode = clip1hiA_gaincode;
-				clip1md_gaincode = clip1mdA_gaincode;
-				clip1lo_gaincode = clip1loA_gaincode;
-				crsmin_th = crsminA_th;
-				crsminl_th = crsminlA_th;
-				crsminu_th = crsminuA_th;
-				nbclip_th = nbclipA_th;
-				rssi_gain = rssi_gain_default;
-			}
-			w1clip_th = w1clipA_th;
-		}
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
-				 RADIO_2056_RX0), 0x17);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
-				 RADIO_2056_RX1), 0x17);
-
-		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
-				0xf0);
-		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
-				0xf0);
-
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
-				0x0);
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
-				0x0);
-
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
-				rssi_gain);
-		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
-				rssi_gain);
-
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
-				 RADIO_2056_RX0), 0x17);
-		write_radio_reg(pi,
-				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
-				 RADIO_2056_RX1), 0x17);
-
-		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
-				0xFF);
-		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
-				0xFF);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
-					 8, lna1_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
-					 8, lna1_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
-					 8, lna2_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
-					 8, lna2_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
-					 8, tia_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
-					 8, tia_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
-					 8, tia_gainbits);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
-					 8, tia_gainbits);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
-					 8, &lpf_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
-					 8, &lpf_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
-					 8, &lpf_gainbits);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
-					 8, &lpf_gainbits);
-
-		write_phy_reg(pi, 0x20, init_gaincode);
-		write_phy_reg(pi, 0x2a7, init_gaincode);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-					 pi->pubpi.phy_corenum, 0x106, 16,
-					 rfseq_init_gain);
-
-		write_phy_reg(pi, 0x22, clip1hi_gaincode);
-		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
-
-		write_phy_reg(pi, 0x24, clip1md_gaincode);
-		write_phy_reg(pi, 0x2ab, clip1md_gaincode);
-
-		write_phy_reg(pi, 0x37, clip1lo_gaincode);
-		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
-
-		mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
-		mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
-		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
-
-		write_phy_reg(pi, 0x2b, nbclip_th);
-		write_phy_reg(pi, 0x41, nbclip_th);
-
-		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
-		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
-
-		write_phy_reg(pi, 0x150, 0x809c);
-
-	} else {
-
-		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-		write_phy_reg(pi, 0x2b, 0x84);
-		write_phy_reg(pi, 0x41, 0x84);
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-			write_phy_reg(pi, 0x6b, 0x2b);
-			write_phy_reg(pi, 0x6c, 0x2b);
-			write_phy_reg(pi, 0x6d, 0x9);
-			write_phy_reg(pi, 0x6e, 0x9);
-		}
-
-		w1th = NPHY_RSSICAL_W1_TARGET - 4;
-		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
-		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-			mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
-			mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
-
-			mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
-			mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
-		}
-
-		write_phy_reg(pi, 0x150, 0x809c);
-
-		if (pi->nphy_gain_boost)
-			if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
-			    (CHSPEC_IS40(pi->radio_chanspec)))
-				hpf_code = 4;
-			else
-				hpf_code = 5;
-		else if (CHSPEC_IS40(pi->radio_chanspec))
-			hpf_code = 6;
-		else
-			hpf_code = 7;
-
-		mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
-		mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
-
-		for (ctr = 0; ctr < 4; ctr++) {
-			regval[ctr] = (hpf_code << 8) | 0x7c;
-		}
-		wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
-
-		wlc_phy_adjust_lnagaintbl_nphy(pi);
-
-		if (pi->nphy_elna_gain_config) {
-			regval[0] = 0;
-			regval[1] = 1;
-			regval[2] = 1;
-			regval[3] = 1;
-			wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
-			wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
-
-			for (ctr = 0; ctr < 4; ctr++) {
-				regval[ctr] = (hpf_code << 8) | 0x74;
-			}
-			wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
-			for (ctr = 0; ctr < 21; ctr++) {
-				regval[ctr] = 3 * ctr;
-			}
-			wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
-			wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
-
-			for (ctr = 0; ctr < 21; ctr++) {
-				regval[ctr] = (u16) ctr;
-			}
-			wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
-			wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
-		}
-
-		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
-				       rfseq_updategainu_events,
-				       rfseq_updategainu_dlys,
-				       sizeof(rfseq_updategainu_events) /
-				       sizeof(rfseq_updategainu_events[0]));
-
-		mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
-
-		if (CHSPEC_IS2G(pi->radio_chanspec))
-			mod_phy_reg(pi,
-				    (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
-				    0x7f, 0x4);
-	}
-}
-
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi)
-{
-	s8 lna1_gain_db[] = { 8, 13, 17, 22 };
-	s8 lna2_gain_db[] = { -2, 7, 11, 15 };
-	s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
-	s8 tia_gainbits[] = {
-		0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
-
-	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-	mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
-
-	mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
-	mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
-				 lna1_gain_db);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
-				 lna1_gain_db);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
-				 lna2_gain_db);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
-				 lna2_gain_db);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
-				 tia_gain_db);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
-				 tia_gain_db);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
-				 tia_gainbits);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
-				 tia_gainbits);
-
-	write_phy_reg(pi, 0x37, 0x74);
-	write_phy_reg(pi, 0x2ad, 0x74);
-	write_phy_reg(pi, 0x38, 0x18);
-	write_phy_reg(pi, 0x2ae, 0x18);
-
-	write_phy_reg(pi, 0x2b, 0xe8);
-	write_phy_reg(pi, 0x41, 0xe8);
-
-	if (CHSPEC_IS20(pi->radio_chanspec)) {
-
-		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
-		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
-	} else {
-
-		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
-		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
-	}
-}
-
-static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi)
-{
-	u16 currband;
-	s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
-	s8 *lna1_gain_db = NULL;
-	s8 *lna1_gain_db_2 = NULL;
-	s8 *lna2_gain_db = NULL;
-	s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
-	s8 *tia_gain_db;
-	s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
-	s8 *tia_gainbits;
-	u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
-	u16 *rfseq_init_gain;
-	u16 init_gaincode;
-	u16 clip1hi_gaincode;
-	u16 clip1md_gaincode = 0;
-	u16 clip1md_gaincode_B;
-	u16 clip1lo_gaincode;
-	u16 clip1lo_gaincode_B;
-	u8 crsminl_th = 0;
-	u8 crsminu_th;
-	u16 nbclip_th = 0;
-	u8 w1clip_th;
-	u16 freq;
-	s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
-	u8 chg_nbclip_th = 0;
-
-	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
-	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
-
-	currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
-	if (currband == 0) {
-
-		lna1_gain_db = lna1G_gain_db_rev7;
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
-					 lna1_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
-					 lna1_gain_db);
-
-		mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
-
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
-			mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
-		}
-
-		mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-			mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
-			mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
-		}
-	} else {
-
-		init_gaincode = 0x9e;
-		clip1hi_gaincode = 0x9e;
-		clip1md_gaincode_B = 0x24;
-		clip1lo_gaincode = 0x8a;
-		clip1lo_gaincode_B = 8;
-		rfseq_init_gain = rfseqA_init_gain_rev7;
-
-		tia_gain_db = tiaA_gain_db_rev7;
-		tia_gainbits = tiaA_gainbits_rev7;
-
-		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-
-			w1clip_th = 25;
-			clip1md_gaincode = 0x82;
-
-			if ((freq <= 5080) || (freq == 5825)) {
-
-				s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
-				s8 lna1A_gain_db_2_rev7[] = {
-					11, 17, 22, 25 };
-				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
-
-				crsminu_th = 0x3e;
-				lna1_gain_db = lna1A_gain_db_rev7;
-				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
-				lna2_gain_db = lna2A_gain_db_rev7;
-			} else if ((freq >= 5500) && (freq <= 5700)) {
-
-				s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
-				s8 lna1A_gain_db_2_rev7[] = {
-					12, 18, 22, 26 };
-				s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
-
-				crsminu_th = 0x45;
-				clip1md_gaincode_B = 0x14;
-				nbclip_th = 0xff;
-				chg_nbclip_th = 1;
-				lna1_gain_db = lna1A_gain_db_rev7;
-				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
-				lna2_gain_db = lna2A_gain_db_rev7;
-			} else {
-
-				s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
-				s8 lna1A_gain_db_2_rev7[] = {
-					12, 18, 22, 26 };
-				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
-
-				crsminu_th = 0x41;
-				lna1_gain_db = lna1A_gain_db_rev7;
-				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
-				lna2_gain_db = lna2A_gain_db_rev7;
-			}
-
-			if (freq <= 4920) {
-				nvar_baseline_offset0 = 5;
-				nvar_baseline_offset1 = 5;
-			} else if ((freq > 4920) && (freq <= 5320)) {
-				nvar_baseline_offset0 = 3;
-				nvar_baseline_offset1 = 5;
-			} else if ((freq > 5320) && (freq <= 5700)) {
-				nvar_baseline_offset0 = 3;
-				nvar_baseline_offset1 = 2;
-			} else {
-				nvar_baseline_offset0 = 4;
-				nvar_baseline_offset1 = 0;
-			}
-		} else {
-
-			crsminu_th = 0x3a;
-			crsminl_th = 0x3a;
-			w1clip_th = 20;
-
-			if ((freq >= 4920) && (freq <= 5320)) {
-				nvar_baseline_offset0 = 4;
-				nvar_baseline_offset1 = 5;
-			} else if ((freq > 5320) && (freq <= 5550)) {
-				nvar_baseline_offset0 = 4;
-				nvar_baseline_offset1 = 2;
-			} else {
-				nvar_baseline_offset0 = 5;
-				nvar_baseline_offset1 = 3;
-			}
-		}
-
-		write_phy_reg(pi, 0x20, init_gaincode);
-		write_phy_reg(pi, 0x2a7, init_gaincode);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-					 pi->pubpi.phy_corenum, 0x106, 16,
-					 rfseq_init_gain);
-
-		write_phy_reg(pi, 0x22, clip1hi_gaincode);
-		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
-
-		write_phy_reg(pi, 0x36, clip1md_gaincode_B);
-		write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
-
-		write_phy_reg(pi, 0x37, clip1lo_gaincode);
-		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
-		write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
-		write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
-					 tia_gain_db);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
-					 tia_gain_db);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
-					 tia_gainbits);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
-					 tia_gainbits);
-
-		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
-
-		if (chg_nbclip_th == 1) {
-			write_phy_reg(pi, 0x2b, nbclip_th);
-			write_phy_reg(pi, 0x41, nbclip_th);
-		}
-
-		mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
-		mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
-
-		mod_phy_reg(pi, 0x2e4,
-			    (0x3f << 0), (nvar_baseline_offset0 << 0));
-
-		mod_phy_reg(pi, 0x2e4,
-			    (0x3f << 6), (nvar_baseline_offset1 << 6));
-
-		if (CHSPEC_IS20(pi->radio_chanspec)) {
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
-						 lna1_gain_db);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
-						 lna1_gain_db_2);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
-						 8, lna2_gain_db);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
-						 8, lna2_gain_db);
-
-			write_phy_reg(pi, 0x24, clip1md_gaincode);
-			write_phy_reg(pi, 0x2ab, clip1md_gaincode);
-		} else {
-			mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
-		}
-
-	}
-
-}
-
-static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi)
-{
-	uint core;
-	int ctr;
-	s16 gain_delta[2];
-	u8 curr_channel;
-	u16 minmax_gain[2];
-	u16 regval[4];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (pi->nphy_gain_boost) {
-		if ((CHSPEC_IS2G(pi->radio_chanspec))) {
-
-			gain_delta[0] = 6;
-			gain_delta[1] = 6;
-		} else {
-
-			curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-			gain_delta[0] =
-			    (s16)
-			    PHY_HW_ROUND(((nphy_lnagain_est0[0] *
-					   curr_channel) +
-					  nphy_lnagain_est0[1]), 13);
-			gain_delta[1] =
-			    (s16)
-			    PHY_HW_ROUND(((nphy_lnagain_est1[0] *
-					   curr_channel) +
-					  nphy_lnagain_est1[1]), 13);
-		}
-	} else {
-
-		gain_delta[0] = 0;
-		gain_delta[1] = 0;
-	}
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		if (pi->nphy_elna_gain_config) {
-
-			regval[0] = nphy_def_lnagains[2] + gain_delta[core];
-			regval[1] = nphy_def_lnagains[3] + gain_delta[core];
-			regval[2] = nphy_def_lnagains[3] + gain_delta[core];
-			regval[3] = nphy_def_lnagains[3] + gain_delta[core];
-		} else {
-			for (ctr = 0; ctr < 4; ctr++) {
-				regval[ctr] =
-				    nphy_def_lnagains[ctr] + gain_delta[core];
-			}
-		}
-		wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
-
-		minmax_gain[core] =
-		    (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
-	}
-
-	mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
-	mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on)
-{
-	if (on) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if (!pi->radio_is_on) {
-				wlc_phy_radio_preinit_205x(pi);
-				wlc_phy_radio_init_2057(pi);
-				wlc_phy_radio_postinit_2057(pi);
-			}
-
-			wlc_phy_chanspec_set((wlc_phy_t *) pi,
-					     pi->radio_chanspec);
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_radio_preinit_205x(pi);
-			wlc_phy_radio_init_2056(pi);
-			wlc_phy_radio_postinit_2056(pi);
-
-			wlc_phy_chanspec_set((wlc_phy_t *) pi,
-					     pi->radio_chanspec);
-		} else {
-			wlc_phy_radio_preinit_2055(pi);
-			wlc_phy_radio_init_2055(pi);
-			wlc_phy_radio_postinit_2055(pi);
-		}
-
-		pi->radio_is_on = true;
-
-	} else {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)
-		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
-			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
-			mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADA_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADG_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAA_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAG_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-			mod_radio_reg(pi,
-				      RADIO_2056_TX_MIXA_BOOST_TUNE |
-				      RADIO_2056_TX0, 0xf0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_MIXG_BOOST_TUNE |
-					RADIO_2056_TX0, 0);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADA_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PADG_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAA_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_PGAG_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-			mod_radio_reg(pi,
-				      RADIO_2056_TX_MIXA_BOOST_TUNE |
-				      RADIO_2056_TX1, 0xf0, 0);
-			write_radio_reg(pi,
-					RADIO_2056_TX_MIXG_BOOST_TUNE |
-					RADIO_2056_TX1, 0);
-
-			pi->radio_is_on = false;
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
-			pi->radio_is_on = false;
-		}
-
-	}
-}
-
-static void wlc_phy_radio_preinit_2055(phy_info_t *pi)
-{
-
-	and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
-	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
-
-	or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
-}
-
-static void wlc_phy_radio_init_2055(phy_info_t *pi)
-{
-	wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
-}
-
-static void wlc_phy_radio_postinit_2055(phy_info_t *pi)
-{
-
-	and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
-		      ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
-
-	if (((pi->sh->sromrev >= 4)
-	     && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
-	    || ((pi->sh->sromrev < 4))) {
-		and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
-		and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
-	}
-
-	mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
-	write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
-
-	and_radio_reg(pi, RADIO_2055_CAL_MISC,
-		      ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
-
-	or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
-
-	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
-
-	udelay(1000);
-
-	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
-
-	SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
-		   RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
-
-	ASSERT((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
-		RADIO_2055_RCAL_DONE) == RADIO_2055_RCAL_DONE);
-
-	and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
-		      ~(RADIO_2055_CAL_LPO_ENABLE));
-
-	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
-	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
-	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
-
-	mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
-		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
-	mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
-		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
-	if (pi->nphy_gain_boost) {
-		and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
-			      ~(RADIO_2055_GAINBST_DISABLE));
-		and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
-			      ~(RADIO_2055_GAINBST_DISABLE));
-	} else {
-		or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
-			     RADIO_2055_GAINBST_DISABLE);
-		or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
-			     RADIO_2055_GAINBST_DISABLE);
-	}
-
-	udelay(2);
-}
-
-static void wlc_phy_radio_preinit_205x(phy_info_t *pi)
-{
-
-	and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
-	and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE);
-
-	or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE);
-	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU);
-
-}
-
-static void wlc_phy_radio_init_2056(phy_info_t *pi)
-{
-	radio_regs_t *regs_SYN_2056_ptr = NULL;
-	radio_regs_t *regs_TX_2056_ptr = NULL;
-	radio_regs_t *regs_RX_2056_ptr = NULL;
-
-	if (NREV_IS(pi->pubpi.phy_rev, 3)) {
-		regs_SYN_2056_ptr = regs_SYN_2056;
-		regs_TX_2056_ptr = regs_TX_2056;
-		regs_RX_2056_ptr = regs_RX_2056;
-	} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-		regs_SYN_2056_ptr = regs_SYN_2056_A1;
-		regs_TX_2056_ptr = regs_TX_2056_A1;
-		regs_RX_2056_ptr = regs_RX_2056_A1;
-	} else {
-		switch (pi->pubpi.radiorev) {
-		case 5:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
-			regs_TX_2056_ptr = regs_TX_2056_rev5;
-			regs_RX_2056_ptr = regs_RX_2056_rev5;
-			break;
-
-		case 6:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
-			regs_TX_2056_ptr = regs_TX_2056_rev6;
-			regs_RX_2056_ptr = regs_RX_2056_rev6;
-			break;
-
-		case 7:
-		case 9:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
-			regs_TX_2056_ptr = regs_TX_2056_rev7;
-			regs_RX_2056_ptr = regs_RX_2056_rev7;
-			break;
-
-		case 8:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
-			regs_TX_2056_ptr = regs_TX_2056_rev8;
-			regs_RX_2056_ptr = regs_RX_2056_rev8;
-			break;
-
-		case 11:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
-			regs_TX_2056_ptr = regs_TX_2056_rev11;
-			regs_RX_2056_ptr = regs_RX_2056_rev11;
-			break;
-
-		default:
-			ASSERT(0);
-			break;
-		}
-	}
-
-	wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN);
-
-	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0);
-
-	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1);
-
-	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0);
-
-	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1);
-}
-
-static void wlc_phy_radio_postinit_2056(phy_info_t *pi)
-{
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb);
-
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2);
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2);
-	udelay(1000);
-	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
-
-	if ((pi->sh->boardflags2 & BFL2_LEGACY)
-	    || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
-
-		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
-	} else {
-
-		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
-	}
-
-	mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
-
-	if (pi->phy_init_por) {
-		wlc_phy_radio205x_rcal(pi);
-	}
-}
-
-static void wlc_phy_radio_init_2057(phy_info_t *pi)
-{
-	radio_20xx_regs_t *regs_2057_ptr = NULL;
-
-	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-		regs_2057_ptr = regs_2057_rev4;
-	} else if (NREV_IS(pi->pubpi.phy_rev, 8)
-		   || NREV_IS(pi->pubpi.phy_rev, 9)) {
-		switch (pi->pubpi.radiorev) {
-		case 5:
-
-			if (pi->pubpi.radiover == 0x0) {
-
-				regs_2057_ptr = regs_2057_rev5;
-
-			} else if (pi->pubpi.radiover == 0x1) {
-
-				regs_2057_ptr = regs_2057_rev5v1;
-			} else {
-				ASSERT(0);
-				break;
-			}
-
-		case 7:
-
-			regs_2057_ptr = regs_2057_rev7;
-			break;
-
-		case 8:
-
-			regs_2057_ptr = regs_2057_rev8;
-			break;
-
-		default:
-			ASSERT(0);
-			break;
-		}
-	} else {
-		ASSERT(0);
-	}
-
-	wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
-}
-
-static void wlc_phy_radio_postinit_2057(phy_info_t *pi)
-{
-
-	mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
-
-	if (pi->sh->chip == !BCM6362_CHIP_ID) {
-
-		mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x2, 0x2);
-	}
-
-	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
-	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
-	mdelay(2);
-	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
-	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
-
-	if (pi->phy_init_por) {
-		wlc_phy_radio205x_rcal(pi);
-		wlc_phy_radio2057_rccal(pi);
-	}
-
-	mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
-}
-
-static bool
-wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
-		       chan_info_nphy_radio2057_t **t0,
-		       chan_info_nphy_radio205x_t **t1,
-		       chan_info_nphy_radio2057_rev5_t **t2,
-		       chan_info_nphy_2055_t **t3)
-{
-	uint i;
-	chan_info_nphy_radio2057_t *chan_info_tbl_p_0 = NULL;
-	chan_info_nphy_radio205x_t *chan_info_tbl_p_1 = NULL;
-	chan_info_nphy_radio2057_rev5_t *chan_info_tbl_p_2 = NULL;
-	u32 tbl_len = 0;
-
-	int freq = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-			chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4);
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 8)
-			   || NREV_IS(pi->pubpi.phy_rev, 9)) {
-			switch (pi->pubpi.radiorev) {
-
-			case 5:
-
-				if (pi->pubpi.radiover == 0x0) {
-
-					chan_info_tbl_p_2 =
-					    chan_info_nphyrev8_2057_rev5;
-					tbl_len =
-					    ARRAY_SIZE
-					    (chan_info_nphyrev8_2057_rev5);
-
-				} else if (pi->pubpi.radiover == 0x1) {
-
-					chan_info_tbl_p_2 =
-					    chan_info_nphyrev9_2057_rev5v1;
-					tbl_len =
-					    ARRAY_SIZE
-					    (chan_info_nphyrev9_2057_rev5v1);
-
-				}
-				break;
-
-			case 7:
-				chan_info_tbl_p_0 =
-				    chan_info_nphyrev8_2057_rev7;
-				tbl_len =
-				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
-				break;
-
-			case 8:
-				chan_info_tbl_p_0 =
-				    chan_info_nphyrev8_2057_rev8;
-				tbl_len =
-				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
-				break;
-
-			default:
-				if (NORADIO_ENAB(pi->pubpi)) {
-					goto fail;
-				}
-				break;
-			}
-		} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
-
-			chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
-		} else {
-			goto fail;
-		}
-
-		for (i = 0; i < tbl_len; i++) {
-			if (pi->pubpi.radiorev == 5) {
-
-				if (chan_info_tbl_p_2[i].chan == channel)
-					break;
-			} else {
-
-				if (chan_info_tbl_p_0[i].chan == channel)
-					break;
-			}
-		}
-
-		if (i >= tbl_len) {
-			ASSERT(i < tbl_len);
-			goto fail;
-		}
-		if (pi->pubpi.radiorev == 5) {
-			*t2 = &chan_info_tbl_p_2[i];
-			freq = chan_info_tbl_p_2[i].freq;
-		} else {
-			*t0 = &chan_info_tbl_p_0[i];
-			freq = chan_info_tbl_p_0[i].freq;
-		}
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (NREV_IS(pi->pubpi.phy_rev, 3)) {
-			chan_info_tbl_p_1 = chan_info_nphyrev3_2056;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056);
-		} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
-			chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1;
-			tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1);
-		} else if (NREV_IS(pi->pubpi.phy_rev, 5)
-			   || NREV_IS(pi->pubpi.phy_rev, 6)) {
-			switch (pi->pubpi.radiorev) {
-			case 5:
-				chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5);
-				break;
-			case 6:
-				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6);
-				break;
-			case 7:
-			case 9:
-				chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
-				tbl_len =
-				    ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
-				break;
-			case 8:
-				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8);
-				break;
-			case 11:
-				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
-				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
-				break;
-			default:
-				if (NORADIO_ENAB(pi->pubpi)) {
-					goto fail;
-				}
-				break;
-			}
-		}
-
-		for (i = 0; i < tbl_len; i++) {
-			if (chan_info_tbl_p_1[i].chan == channel)
-				break;
-		}
-
-		if (i >= tbl_len) {
-			ASSERT(i < tbl_len);
-			goto fail;
-		}
-		*t1 = &chan_info_tbl_p_1[i];
-		freq = chan_info_tbl_p_1[i].freq;
-
-	} else {
-		for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++)
-			if (chan_info_nphy_2055[i].chan == channel)
-				break;
-
-		if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
-			ASSERT(i < ARRAY_SIZE(chan_info_nphy_2055));
-			goto fail;
-		}
-		*t3 = &chan_info_nphy_2055[i];
-		freq = chan_info_nphy_2055[i].freq;
-	}
-
-	*f = freq;
-	return true;
-
- fail:
-	*f = WL_CHAN_FREQ_RANGE_2G;
-	return false;
-}
-
-u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint channel)
-{
-	int freq;
-	chan_info_nphy_radio2057_t *t0 = NULL;
-	chan_info_nphy_radio205x_t *t1 = NULL;
-	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
-	chan_info_nphy_2055_t *t3 = NULL;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return WL_CHAN_FREQ_RANGE_2G;
-
-	if (channel == 0)
-		channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-
-	wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec))
-		return WL_CHAN_FREQ_RANGE_2G;
-
-	if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
-		return WL_CHAN_FREQ_RANGE_5GL;
-	} else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
-		return WL_CHAN_FREQ_RANGE_5GM;
-	} else {
-		return WL_CHAN_FREQ_RANGE_5GH;
-	}
-}
-
-static void
-wlc_phy_chanspec_radio2055_setup(phy_info_t *pi, chan_info_nphy_2055_t *ci)
-{
-
-	write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
-	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0);
-	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1);
-	write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1);
-	write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2);
-	write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1);
-	write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2);
-	write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf);
-	write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1);
-	write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE,
-			ci->RF_core1_lgbuf_a_tune);
-	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE,
-			ci->RF_core1_lgbuf_g_tune);
-	write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1);
-	write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN,
-			ci->RF_core1_tx_pga_pad_tn);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM,
-			ci->RF_core1_tx_mx_bgtrim);
-	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE,
-			ci->RF_core2_lgbuf_a_tune);
-	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE,
-			ci->RF_core2_lgbuf_g_tune);
-	write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN,
-			ci->RF_core2_tx_pga_pad_tn);
-	write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM,
-			ci->RF_core2_tx_mx_bgtrim);
-
-	udelay(50);
-
-	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05);
-	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45);
-
-	WLC_PHY_WAR_PR51571(pi);
-
-	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65);
-
-	udelay(300);
-}
-
-static void
-wlc_phy_chanspec_radio2056_setup(phy_info_t *pi,
-				 const chan_info_nphy_radio205x_t *ci)
-{
-	radio_regs_t *regs_SYN_2056_ptr = NULL;
-
-	write_radio_reg(pi,
-			RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_vcocal1);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_vcocal2);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN,
-			ci->RF_SYN_pll_refdiv);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_mmd2);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_mmd1);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter1);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter2);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter3);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter4);
-	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN,
-			ci->RF_SYN_pll_loopfilter5);
-	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN,
-			ci->RF_SYN_reserved_addr27);
-	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN,
-			ci->RF_SYN_reserved_addr28);
-	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN,
-			ci->RF_SYN_reserved_addr29);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_VCOBUF1);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_MIXER2);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_BUF3);
-	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN,
-			ci->RF_SYN_logen_BUF4);
-
-	write_radio_reg(pi,
-			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0,
-			ci->RF_RX0_lnaa_tune);
-	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0,
-			ci->RF_RX0_lnag_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_intpaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_intpag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_pada_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_padg_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_pgaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_pgag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_mixa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0,
-			ci->RF_TX0_mixg_boost_tune);
-
-	write_radio_reg(pi,
-			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1,
-			ci->RF_RX1_lnaa_tune);
-	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1,
-			ci->RF_RX1_lnag_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_intpaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_intpag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_pada_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_padg_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_pgaa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_pgag_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_mixa_boost_tune);
-	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1,
-			ci->RF_TX1_mixg_boost_tune);
-
-	if (NREV_IS(pi->pubpi.phy_rev, 3))
-		regs_SYN_2056_ptr = regs_SYN_2056;
-	else if (NREV_IS(pi->pubpi.phy_rev, 4))
-		regs_SYN_2056_ptr = regs_SYN_2056_A1;
-	else {
-		switch (pi->pubpi.radiorev) {
-		case 5:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
-			break;
-		case 6:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
-			break;
-		case 7:
-		case 9:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
-			break;
-		case 8:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
-			break;
-		case 11:
-			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
-			break;
-		}
-	}
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
-				RADIO_2056_SYN,
-				(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
-	} else {
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
-				RADIO_2056_SYN,
-				(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
-	}
-
-	if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
-					RADIO_2056_SYN, 0x1f);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
-					RADIO_2056_SYN, 0x1f);
-
-			if ((pi->sh->chip == BCM4716_CHIP_ID) ||
-			    (pi->sh->chip == BCM47162_CHIP_ID)) {
-
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_LOOPFILTER4 |
-						RADIO_2056_SYN, 0x14);
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_CP2 |
-						RADIO_2056_SYN, 0x00);
-			} else {
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_LOOPFILTER4 |
-						RADIO_2056_SYN, 0xb);
-				write_radio_reg(pi,
-						RADIO_2056_SYN_PLL_CP2 |
-						RADIO_2056_SYN, 0x14);
-			}
-		}
-	}
-
-	if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) &&
-	    (CHSPEC_IS2G(pi->radio_chanspec))) {
-		write_radio_reg(pi,
-				RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
-				0x1f);
-		write_radio_reg(pi,
-				RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
-				0x1f);
-		write_radio_reg(pi,
-				RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
-				0xb);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN,
-				0x20);
-	}
-
-	if (pi->sh->boardflags2 & BFL2_APLL_WAR) {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
-					RADIO_2056_SYN, 0x1f);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
-					RADIO_2056_SYN, 0x1f);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 |
-					RADIO_2056_SYN, 0x5);
-			write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
-					RADIO_2056_SYN, 0xc);
-		}
-	}
-
-	if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) {
-		u16 pag_boost_tune;
-		u16 padg_boost_tune;
-		u16 pgag_boost_tune;
-		u16 mixg_boost_tune;
-		u16 bias, cascbias;
-		uint core;
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 PADG_IDAC, 0xcc);
-
-				if ((pi->sh->chip == BCM4716_CHIP_ID) ||
-				    (pi->sh->chip ==
-				     BCM47162_CHIP_ID)) {
-					bias = 0x40;
-					cascbias = 0x45;
-					pag_boost_tune = 0x5;
-					pgag_boost_tune = 0x33;
-					padg_boost_tune = 0x77;
-					mixg_boost_tune = 0x55;
-				} else {
-					bias = 0x25;
-					cascbias = 0x20;
-
-					if ((pi->sh->chip ==
-					     BCM43224_CHIP_ID)
-					    || (pi->sh->chip ==
-						BCM43225_CHIP_ID)
-					    || (pi->sh->chip ==
-						BCM43421_CHIP_ID)) {
-						if (pi->sh->chippkg ==
-						    BCM43224_FAB_SMIC) {
-							bias = 0x2a;
-							cascbias = 0x38;
-						}
-					}
-
-					pag_boost_tune = 0x4;
-					pgag_boost_tune = 0x03;
-					padg_boost_tune = 0x77;
-					mixg_boost_tune = 0x65;
-				}
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IMAIN_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IAUX_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_CASCBIAS, cascbias);
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_BOOST_TUNE,
-						 pag_boost_tune);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 PGAG_BOOST_TUNE,
-						 pgag_boost_tune);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 PADG_BOOST_TUNE,
-						 padg_boost_tune);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 MIXG_BOOST_TUNE,
-						 mixg_boost_tune);
-			} else {
-
-				bias = IS40MHZ(pi) ? 0x40 : 0x20;
-
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IMAIN_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_IAUX_STAT, bias);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_CASCBIAS, 0x30);
-			}
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1,
-					 0xee);
-		}
-	}
-
-	if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6)
-	    && CHSPEC_IS5G(pi->radio_chanspec)) {
-		u16 paa_boost_tune;
-		u16 pada_boost_tune;
-		u16 pgaa_boost_tune;
-		u16 mixa_boost_tune;
-		u16 freq, pabias, cascbias;
-		uint core;
-
-		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
-
-		if (freq < 5150) {
-
-			paa_boost_tune = 0xa;
-			pada_boost_tune = 0x77;
-			pgaa_boost_tune = 0xf;
-			mixa_boost_tune = 0xf;
-		} else if (freq < 5340) {
-
-			paa_boost_tune = 0x8;
-			pada_boost_tune = 0x77;
-			pgaa_boost_tune = 0xfb;
-			mixa_boost_tune = 0xf;
-		} else if (freq < 5650) {
-
-			paa_boost_tune = 0x0;
-			pada_boost_tune = 0x77;
-			pgaa_boost_tune = 0xb;
-			mixa_boost_tune = 0xf;
-		} else {
-
-			paa_boost_tune = 0x0;
-			pada_boost_tune = 0x77;
-			if (freq != 5825) {
-				pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
-			} else {
-				pgaa_boost_tune = 6;
-			}
-			mixa_boost_tune = 0xf;
-		}
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_BOOST_TUNE, paa_boost_tune);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PADA_BOOST_TUNE, pada_boost_tune);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PGAA_BOOST_TUNE, pgaa_boost_tune);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 MIXA_BOOST_TUNE, mixa_boost_tune);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 TXSPARE1, 0x30);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PA_SPARE2, 0xee);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 PADA_CASCBIAS, 0x3);
-
-			cascbias = 0x30;
-
-			if ((pi->sh->chip == BCM43224_CHIP_ID) ||
-			    (pi->sh->chip == BCM43225_CHIP_ID) ||
-			    (pi->sh->chip == BCM43421_CHIP_ID)) {
-				if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
-					cascbias = 0x35;
-				}
-			}
-
-			pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_IAUX_STAT, pabias);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_IMAIN_STAT, pabias);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_CASCBIAS, cascbias);
-		}
-	}
-
-	udelay(50);
-
-	wlc_phy_radio205x_vcocal_nphy(pi);
-}
-
-void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0);
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0);
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04,
-			      (1 << 2));
-		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39);
-	}
-
-	udelay(300);
-}
-
-#define MAX_205x_RCAL_WAITLOOPS 10000
-
-static u16 wlc_phy_radio205x_rcal(phy_info_t *pi)
-{
-	u16 rcal_reg = 0;
-	int i;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (pi->pubpi.radiorev == 5) {
-
-			and_phy_reg(pi, 0x342, ~(0x1 << 1));
-
-			udelay(10);
-
-			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
-			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
-				      0x1);
-		}
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
-
-		udelay(10);
-
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
-
-		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-			rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
-			if (rcal_reg & 0x1) {
-				break;
-			}
-			udelay(100);
-		}
-
-		ASSERT(i < MAX_205x_RCAL_WAITLOOPS);
-
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
-
-		rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
-
-		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
-		if (pi->pubpi.radiorev == 5) {
-
-			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
-			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
-				      0x0);
-		}
-
-		if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
-
-			mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
-				      rcal_reg);
-			mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
-				      rcal_reg << 2);
-		}
-
-	} else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
-		u16 savereg;
-
-		savereg =
-		    read_radio_reg(pi,
-				   RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
-				savereg | 0x7);
-		udelay(10);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x1);
-		udelay(10);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x9);
-
-		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-			rcal_reg = read_radio_reg(pi,
-						  RADIO_2056_SYN_RCAL_CODE_OUT |
-						  RADIO_2056_SYN);
-			if (rcal_reg & 0x80) {
-				break;
-			}
-			udelay(100);
-		}
-
-		ASSERT(i < MAX_205x_RCAL_WAITLOOPS);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x1);
-
-		rcal_reg =
-		    read_radio_reg(pi,
-				   RADIO_2056_SYN_RCAL_CODE_OUT |
-				   RADIO_2056_SYN);
-
-		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
-				0x0);
-
-		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
-				savereg);
-
-		return rcal_reg & 0x1f;
-	}
-	return rcal_reg & 0x3e;
-}
-
-static void
-wlc_phy_chanspec_radio2057_setup(phy_info_t *pi,
-				 const chan_info_nphy_radio2057_t *ci,
-				 const chan_info_nphy_radio2057_rev5_t *ci2)
-{
-	int coreNum;
-	u16 txmix2g_tune_boost_pu = 0;
-	u16 pad2g_tune_pus = 0;
-
-	if (pi->pubpi.radiorev == 5) {
-
-		write_radio_reg(pi,
-				RADIO_2057_VCOCAL_COUNTVAL0,
-				ci2->RF_vcocal_countval0);
-		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
-				ci2->RF_vcocal_countval1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
-				ci2->RF_rfpll_refmaster_sparextalsize);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-				ci2->RF_rfpll_loopfilter_r1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-				ci2->RF_rfpll_loopfilter_c2);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-				ci2->RF_rfpll_loopfilter_c1);
-		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC,
-				ci2->RF_cp_kpd_idac);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1);
-		write_radio_reg(pi,
-				RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune);
-		write_radio_reg(pi,
-				RADIO_2057_LOGEN_MX2G_TUNE,
-				ci2->RF_logen_mx2g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
-				ci2->RF_logen_indbuf2g_tune);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
-				ci2->RF_txmix2g_tune_boost_pu_core0);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-				ci2->RF_pad2g_tune_pus_core0);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
-				ci2->RF_lna2g_tune_core0);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
-				ci2->RF_txmix2g_tune_boost_pu_core1);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-				ci2->RF_pad2g_tune_pus_core1);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
-				ci2->RF_lna2g_tune_core1);
-
-	} else {
-
-		write_radio_reg(pi,
-				RADIO_2057_VCOCAL_COUNTVAL0,
-				ci->RF_vcocal_countval0);
-		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
-				ci->RF_vcocal_countval1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
-				ci->RF_rfpll_refmaster_sparextalsize);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-				ci->RF_rfpll_loopfilter_r1);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-				ci->RF_rfpll_loopfilter_c2);
-		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-				ci->RF_rfpll_loopfilter_c1);
-		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0);
-		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1);
-		write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune);
-		write_radio_reg(pi,
-				RADIO_2057_LOGEN_MX2G_TUNE,
-				ci->RF_logen_mx2g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE,
-				ci->RF_logen_mx5g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
-				ci->RF_logen_indbuf2g_tune);
-		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE,
-				ci->RF_logen_indbuf5g_tune);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
-				ci->RF_txmix2g_tune_boost_pu_core0);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-				ci->RF_pad2g_tune_pus_core0);
-		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0,
-				ci->RF_pga_boost_tune_core0);
-		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0,
-				ci->RF_txmix5g_boost_tune_core0);
-		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0,
-				ci->RF_pad5g_tune_misc_pus_core0);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
-				ci->RF_lna2g_tune_core0);
-		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0,
-				ci->RF_lna5g_tune_core0);
-
-		write_radio_reg(pi,
-				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
-				ci->RF_txmix2g_tune_boost_pu_core1);
-		write_radio_reg(pi,
-				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-				ci->RF_pad2g_tune_pus_core1);
-		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1,
-				ci->RF_pga_boost_tune_core1);
-		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1,
-				ci->RF_txmix5g_boost_tune_core1);
-		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1,
-				ci->RF_pad5g_tune_misc_pus_core1);
-		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
-				ci->RF_lna2g_tune_core1);
-		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1,
-				ci->RF_lna5g_tune_core1);
-	}
-
-	if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x3f);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0x8);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0x8);
-		} else {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x1f);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0x8);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0x8);
-		}
-	} else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) ||
-		   (pi->pubpi.radiorev == 8)) {
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x1b);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0xa);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0xa);
-		} else {
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
-					0x1f);
-			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
-					0x8);
-			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
-					0x8);
-		}
-
-	}
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (PHY_IPA(pi)) {
-			if (pi->pubpi.radiorev == 3) {
-				txmix2g_tune_boost_pu = 0x6b;
-			}
-
-			if (pi->pubpi.radiorev == 5)
-				pad2g_tune_pus = 0x73;
-
-		} else {
-			if (pi->pubpi.radiorev != 5) {
-				pad2g_tune_pus = 0x3;
-
-				txmix2g_tune_boost_pu = 0x61;
-			}
-		}
-
-		for (coreNum = 0; coreNum <= 1; coreNum++) {
-
-			if (txmix2g_tune_boost_pu != 0)
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 TXMIX2G_TUNE_BOOST_PU,
-						 txmix2g_tune_boost_pu);
-
-			if (pad2g_tune_pus != 0)
-				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
-						 PAD2G_TUNE_PUS,
-						 pad2g_tune_pus);
-		}
-	}
-
-	udelay(50);
-
-	wlc_phy_radio205x_vcocal_nphy(pi);
-}
-
-static u16 wlc_phy_radio2057_rccal(phy_info_t *pi)
-{
-	u16 rccal_valid;
-	int i;
-	bool chip43226_6362A0;
-
-	chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
-			    || (pi->pubpi.radiorev == 4)
-			    || (pi->pubpi.radiorev == 6));
-
-	rccal_valid = 0;
-	if (chip43226_6362A0) {
-		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
-	} else {
-		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
-
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
-	}
-	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
-	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
-		if (rccal_valid & 0x2) {
-			break;
-		}
-		udelay(500);
-	}
-
-	ASSERT(rccal_valid & 0x2);
-
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
-	rccal_valid = 0;
-	if (chip43226_6362A0) {
-		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
-	} else {
-		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
-
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
-	}
-	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
-	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
-		if (rccal_valid & 0x2) {
-			break;
-		}
-		udelay(500);
-	}
-
-	ASSERT(rccal_valid & 0x2);
-
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
-	rccal_valid = 0;
-	if (chip43226_6362A0) {
-		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
-
-		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
-	} else {
-		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
-		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
-		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
-	}
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
-
-	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
-		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
-		if (rccal_valid & 0x2) {
-			break;
-		}
-		udelay(500);
-	}
-
-	ASSERT(rccal_valid & 0x2);
-
-	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
-
-	return rccal_valid;
-}
-
-static void
-wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi, u16 reduction_factr)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
-		    CHSPEC_IS40(pi->radio_chanspec)) {
-			if (!pi->nphy_anarxlpf_adjusted) {
-				write_radio_reg(pi,
-						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-						 RADIO_2056_RX0),
-						((pi->nphy_rccal_value +
-						  reduction_factr) | 0x80));
-
-				pi->nphy_anarxlpf_adjusted = true;
-			}
-		} else {
-			if (pi->nphy_anarxlpf_adjusted) {
-				write_radio_reg(pi,
-						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-						 RADIO_2056_RX0),
-						(pi->nphy_rccal_value | 0x80));
-
-				pi->nphy_anarxlpf_adjusted = false;
-			}
-		}
-	}
-}
-
-static void
-wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *tone_id_buf,
-				 u32 *noise_var_buf)
-{
-	int i;
-	u32 offset;
-	int tone_id;
-	int tbllen =
-	    CHSPEC_IS40(pi->
-			radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
-	    NPHY_NOISEVAR_TBLLEN20;
-
-	if (pi->nphy_noisevars_adjusted) {
-		for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
-			tone_id = pi->nphy_saved_noisevars.tone_id[i];
-			offset = (tone_id >= 0) ?
-			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 offset, 32,
-						 (void *)&pi->
-						 nphy_saved_noisevars.
-						 min_noise_vars[i]);
-		}
-
-		pi->nphy_saved_noisevars.bufcount = 0;
-		pi->nphy_noisevars_adjusted = false;
-	}
-
-	if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
-		pi->nphy_saved_noisevars.bufcount = 0;
-
-		for (i = 0; i < ntones; i++) {
-			tone_id = tone_id_buf[i];
-			offset = (tone_id >= 0) ?
-			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
-			pi->nphy_saved_noisevars.tone_id[i] = tone_id;
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						offset, 32,
-						&pi->nphy_saved_noisevars.
-						min_noise_vars[i]);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
-						 offset, 32,
-						 (void *)&noise_var_buf[i]);
-			pi->nphy_saved_noisevars.bufcount++;
-		}
-
-		pi->nphy_noisevars_adjusted = true;
-	}
-}
-
-static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr)
-{
-	u16 regval;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
-		    CHSPEC_IS40(pi->radio_chanspec)) {
-			if (!pi->nphy_crsminpwr_adjusted) {
-				regval = read_phy_reg(pi, 0x27d);
-				pi->nphy_crsminpwr[0] = regval & 0xff;
-				regval &= 0xff00;
-				regval |= (u16) minpwr;
-				write_phy_reg(pi, 0x27d, regval);
-
-				regval = read_phy_reg(pi, 0x280);
-				pi->nphy_crsminpwr[1] = regval & 0xff;
-				regval &= 0xff00;
-				regval |= (u16) minpwr;
-				write_phy_reg(pi, 0x280, regval);
-
-				regval = read_phy_reg(pi, 0x283);
-				pi->nphy_crsminpwr[2] = regval & 0xff;
-				regval &= 0xff00;
-				regval |= (u16) minpwr;
-				write_phy_reg(pi, 0x283, regval);
-
-				pi->nphy_crsminpwr_adjusted = true;
-			}
-		} else {
-			if (pi->nphy_crsminpwr_adjusted) {
-				regval = read_phy_reg(pi, 0x27d);
-				regval &= 0xff00;
-				regval |= pi->nphy_crsminpwr[0];
-				write_phy_reg(pi, 0x27d, regval);
-
-				regval = read_phy_reg(pi, 0x280);
-				regval &= 0xff00;
-				regval |= pi->nphy_crsminpwr[1];
-				write_phy_reg(pi, 0x280, regval);
-
-				regval = read_phy_reg(pi, 0x283);
-				regval &= 0xff00;
-				regval |= pi->nphy_crsminpwr[2];
-				write_phy_reg(pi, 0x283, regval);
-
-				pi->nphy_crsminpwr_adjusted = false;
-			}
-		}
-	}
-}
-
-static void wlc_phy_txlpfbw_nphy(phy_info_t *pi)
-{
-	u8 tx_lpf_bw = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			tx_lpf_bw = 3;
-		} else {
-			tx_lpf_bw = 1;
-		}
-
-		if (PHY_IPA(pi)) {
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				tx_lpf_bw = 5;
-			} else {
-				tx_lpf_bw = 4;
-			}
-		}
-		write_phy_reg(pi, 0xe8,
-			      (tx_lpf_bw << 0) |
-			      (tx_lpf_bw << 3) |
-			      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
-
-		if (PHY_IPA(pi)) {
-
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				tx_lpf_bw = 4;
-			} else {
-				tx_lpf_bw = 1;
-			}
-
-			write_phy_reg(pi, 0xe9,
-				      (tx_lpf_bw << 0) |
-				      (tx_lpf_bw << 3) |
-				      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
-		}
-	}
-}
-
-static void wlc_phy_spurwar_nphy(phy_info_t *pi)
-{
-	u16 cur_channel = 0;
-	int nphy_adj_tone_id_buf[] = { 57, 58 };
-	u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
-	bool isAdjustNoiseVar = false;
-	uint numTonesAdjust = 0;
-	u32 tempval = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-		cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
-
-		if (pi->nphy_gband_spurwar_en) {
-
-			wlc_phy_adjust_rx_analpfbw_nphy(pi,
-							NPHY_ANARXLPFBW_REDUCTIONFACT);
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				if ((cur_channel == 11)
-				    && CHSPEC_IS40(pi->radio_chanspec)) {
-
-					wlc_phy_adjust_min_noisevar_nphy(pi, 2,
-									 nphy_adj_tone_id_buf,
-									 nphy_adj_noise_var_buf);
-				} else {
-
-					wlc_phy_adjust_min_noisevar_nphy(pi, 0,
-									 NULL,
-									 NULL);
-				}
-			}
-			wlc_phy_adjust_crsminpwr_nphy(pi,
-						      NPHY_ADJUSTED_MINCRSPOWER);
-		}
-
-		if ((pi->nphy_gband_spurwar2_en)
-		    && CHSPEC_IS2G(pi->radio_chanspec)) {
-
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				switch (cur_channel) {
-				case 3:
-					nphy_adj_tone_id_buf[0] = 57;
-					nphy_adj_tone_id_buf[1] = 58;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 4:
-					nphy_adj_tone_id_buf[0] = 41;
-					nphy_adj_tone_id_buf[1] = 42;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 5:
-					nphy_adj_tone_id_buf[0] = 25;
-					nphy_adj_tone_id_buf[1] = 26;
-					nphy_adj_noise_var_buf[0] = 0x24f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 6:
-					nphy_adj_tone_id_buf[0] = 9;
-					nphy_adj_tone_id_buf[1] = 10;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				case 7:
-					nphy_adj_tone_id_buf[0] = 121;
-					nphy_adj_tone_id_buf[1] = 122;
-					nphy_adj_noise_var_buf[0] = 0x18f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				case 8:
-					nphy_adj_tone_id_buf[0] = 105;
-					nphy_adj_tone_id_buf[1] = 106;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x25f;
-					isAdjustNoiseVar = true;
-					break;
-				case 9:
-					nphy_adj_tone_id_buf[0] = 89;
-					nphy_adj_tone_id_buf[1] = 90;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				case 10:
-					nphy_adj_tone_id_buf[0] = 73;
-					nphy_adj_tone_id_buf[1] = 74;
-					nphy_adj_noise_var_buf[0] = 0x22f;
-					nphy_adj_noise_var_buf[1] = 0x24f;
-					isAdjustNoiseVar = true;
-					break;
-				default:
-					isAdjustNoiseVar = false;
-					break;
-				}
-			}
-
-			if (isAdjustNoiseVar) {
-				numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
-				    sizeof(nphy_adj_tone_id_buf[0]);
-
-				wlc_phy_adjust_min_noisevar_nphy(pi,
-								 numTonesAdjust,
-								 nphy_adj_tone_id_buf,
-								 nphy_adj_noise_var_buf);
-
-				tempval = 0;
-
-			} else {
-
-				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
-								 NULL);
-			}
-		}
-
-		if ((pi->nphy_aband_spurwar_en) &&
-		    (CHSPEC_IS5G(pi->radio_chanspec))) {
-			switch (cur_channel) {
-			case 54:
-				nphy_adj_tone_id_buf[0] = 32;
-				nphy_adj_noise_var_buf[0] = 0x25f;
-				break;
-			case 38:
-			case 102:
-			case 118:
-				if ((pi->sh->chip == BCM4716_CHIP_ID) &&
-				    (pi->sh->chippkg == BCM4717_PKG_ID)) {
-					nphy_adj_tone_id_buf[0] = 32;
-					nphy_adj_noise_var_buf[0] = 0x21f;
-				} else {
-					nphy_adj_tone_id_buf[0] = 0;
-					nphy_adj_noise_var_buf[0] = 0x0;
-				}
-				break;
-			case 134:
-				nphy_adj_tone_id_buf[0] = 32;
-				nphy_adj_noise_var_buf[0] = 0x21f;
-				break;
-			case 151:
-				nphy_adj_tone_id_buf[0] = 16;
-				nphy_adj_noise_var_buf[0] = 0x23f;
-				break;
-			case 153:
-			case 161:
-				nphy_adj_tone_id_buf[0] = 48;
-				nphy_adj_noise_var_buf[0] = 0x23f;
-				break;
-			default:
-				nphy_adj_tone_id_buf[0] = 0;
-				nphy_adj_noise_var_buf[0] = 0x0;
-				break;
-			}
-
-			if (nphy_adj_tone_id_buf[0]
-			    && nphy_adj_noise_var_buf[0]) {
-				wlc_phy_adjust_min_noisevar_nphy(pi, 1,
-								 nphy_adj_tone_id_buf,
-								 nphy_adj_noise_var_buf);
-			} else {
-				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
-								 NULL);
-			}
-		}
-
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, false);
-	}
-}
-
-static void
-wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chanspec,
-			    const nphy_sfo_cfg_t *ci)
-{
-	u16 val;
-
-	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
-	if (CHSPEC_IS5G(chanspec) && !val) {
-
-		val = R_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param);
-		W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param,
-		      (val | MAC_PHY_FORCE_CLK));
-
-		or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
-			   (BBCFG_RESETCCA | BBCFG_RESETRX));
-
-		W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, val);
-
-		or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
-	} else if (!CHSPEC_IS5G(chanspec) && val) {
-
-		and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
-
-		val = R_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param);
-		W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param,
-		      (val | MAC_PHY_FORCE_CLK));
-
-		and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
-			    (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
-
-		W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, val);
-	}
-
-	write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
-	write_phy_reg(pi, 0x1cf, ci->PHY_BW2);
-	write_phy_reg(pi, 0x1d0, ci->PHY_BW3);
-
-	write_phy_reg(pi, 0x1d1, ci->PHY_BW4);
-	write_phy_reg(pi, 0x1d2, ci->PHY_BW5);
-	write_phy_reg(pi, 0x1d3, ci->PHY_BW6);
-
-	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0);
-
-		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800);
-	} else {
-		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en,
-					NPHY_ClassifierCtrl_ofdm_en);
-
-		if (CHSPEC_IS2G(chanspec))
-			and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
-	}
-
-	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
-		wlc_phy_txpwr_fixpower_nphy(pi);
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-		wlc_phy_adjust_lnagaintbl_nphy(pi);
-	}
-
-	wlc_phy_txlpfbw_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)
-	    && (pi->phy_spuravoid != SPURAVOID_DISABLE)) {
-		u8 spuravoid = 0;
-
-		val = CHSPEC_CHANNEL(chanspec);
-		if (!CHSPEC_IS40(pi->radio_chanspec)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				if ((val == 13) || (val == 14) || (val == 153)) {
-					spuravoid = 1;
-				}
-			} else {
-
-				if (((val >= 5) && (val <= 8)) || (val == 13)
-				    || (val == 14)) {
-					spuravoid = 1;
-				}
-			}
-		} else {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				if (val == 54) {
-					spuravoid = 1;
-				}
-			} else {
-
-				if (pi->nphy_aband_spurwar_en &&
-				    ((val == 38) || (val == 102)
-				     || (val == 118))) {
-					if ((pi->sh->chip ==
-					     BCM4716_CHIP_ID)
-					    && (pi->sh->chippkg ==
-						BCM4717_PKG_ID)) {
-						spuravoid = 0;
-					} else {
-						spuravoid = 1;
-					}
-				}
-			}
-		}
-
-		if (pi->phy_spuravoid == SPURAVOID_FORCEON)
-			spuravoid = 1;
-
-		if ((pi->sh->chip == BCM4716_CHIP_ID) ||
-		    (pi->sh->chip == BCM47162_CHIP_ID)) {
-			si_pmu_spuravoid(pi->sh->sih, pi->sh->osh, spuravoid);
-		} else {
-			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
-			si_pmu_spuravoid(pi->sh->sih, pi->sh->osh, spuravoid);
-			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
-		}
-
-		if ((pi->sh->chip == BCM43224_CHIP_ID) ||
-		    (pi->sh->chip == BCM43225_CHIP_ID) ||
-		    (pi->sh->chip == BCM43421_CHIP_ID)) {
-
-			if (spuravoid == 1) {
-
-				W_REG(pi->sh->osh, &pi->regs->tsf_clk_frac_l,
-				      0x5341);
-				W_REG(pi->sh->osh, &pi->regs->tsf_clk_frac_h,
-				      0x8);
-			} else {
-
-				W_REG(pi->sh->osh, &pi->regs->tsf_clk_frac_l,
-				      0x8889);
-				W_REG(pi->sh->osh, &pi->regs->tsf_clk_frac_h,
-				      0x8);
-			}
-		}
-
-		if (!((pi->sh->chip == BCM4716_CHIP_ID) ||
-		      (pi->sh->chip == BCM47162_CHIP_ID))) {
-			wlapi_bmac_core_phypll_reset(pi->sh->physhim);
-		}
-
-		mod_phy_reg(pi, 0x01, (0x1 << 15),
-			    ((spuravoid > 0) ? (0x1 << 15) : 0));
-
-		wlc_phy_resetcca_nphy(pi);
-
-		pi->phy_isspuravoid = (spuravoid > 0);
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 7))
-		write_phy_reg(pi, 0x17e, 0x3830);
-
-	wlc_phy_spurwar_nphy(pi);
-}
-
-void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec)
-{
-	int freq;
-	chan_info_nphy_radio2057_t *t0 = NULL;
-	chan_info_nphy_radio205x_t *t1 = NULL;
-	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
-	chan_info_nphy_2055_t *t3 = NULL;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		return;
-	}
-
-	if (!wlc_phy_chan2freq_nphy
-	    (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
-		return;
-
-	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
-
-	if (CHSPEC_BW(chanspec) != pi->bw)
-		wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec));
-
-	if (CHSPEC_IS40(chanspec)) {
-		if (CHSPEC_SB_UPPER(chanspec)) {
-			or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
-			}
-		} else {
-			and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				and_phy_reg(pi, 0x310,
-					    (~PRIM_SEL_UP20 & 0xffff));
-			}
-		}
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-			if ((pi->pubpi.radiorev <= 4)
-			    || (pi->pubpi.radiorev == 6)) {
-				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0,
-					      0x2,
-					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
-					       : 0));
-				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1,
-					      0x2,
-					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
-					       : 0));
-			}
-
-			wlc_phy_chanspec_radio2057_setup(pi, t0, t2);
-			wlc_phy_chanspec_nphy_setup(pi, chanspec,
-						    (pi->pubpi.radiorev ==
-						     5) ? (const nphy_sfo_cfg_t
-							   *)&(t2->
-							       PHY_BW1a)
-						    : (const nphy_sfo_cfg_t *)
-						    &(t0->PHY_BW1a));
-
-		} else {
-
-			mod_radio_reg(pi,
-				      RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN,
-				      0x4,
-				      (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0));
-			wlc_phy_chanspec_radio2056_setup(pi, t1);
-
-			wlc_phy_chanspec_nphy_setup(pi, chanspec,
-						    (const nphy_sfo_cfg_t *)
-						    &(t1->PHY_BW1a));
-		}
-
-	} else {
-
-		mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70,
-			      (CHSPEC_IS5G(chanspec) ? (0x02 << 4)
-			       : (0x05 << 4)));
-
-		wlc_phy_chanspec_radio2055_setup(pi, t3);
-		wlc_phy_chanspec_nphy_setup(pi, chanspec,
-					    (const nphy_sfo_cfg_t *)&(t3->
-								      PHY_BW1a));
-	}
-
-}
-
-static void wlc_phy_savecal_nphy(phy_info_t *pi)
-{
-	void *tbl_ptr;
-	int coreNum;
-	u16 *txcal_radio_regs = NULL;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_2G);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_2G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			pi->calibration_cache.txcal_radio_regs_2G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[2] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_2G[3] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX1);
-
-			pi->calibration_cache.txcal_radio_regs_2G[4] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[5] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_2G[6] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_2G[7] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX1);
-		} else {
-			pi->calibration_cache.txcal_radio_regs_2G[0] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_2G[1] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_2G[2] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
-			pi->calibration_cache.txcal_radio_regs_2G[3] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
-		}
-
-		pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
-	} else {
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_5G);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_5G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			pi->calibration_cache.txcal_radio_regs_5G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[2] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_5G[3] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_FINE_Q |
-					   RADIO_2056_TX1);
-
-			pi->calibration_cache.txcal_radio_regs_5G[4] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[5] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX0);
-			pi->calibration_cache.txcal_radio_regs_5G[6] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_I |
-					   RADIO_2056_TX1);
-			pi->calibration_cache.txcal_radio_regs_5G[7] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_LOFT_COARSE_Q |
-					   RADIO_2056_TX1);
-		} else {
-			pi->calibration_cache.txcal_radio_regs_5G[0] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_5G[1] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
-			pi->calibration_cache.txcal_radio_regs_5G[2] =
-			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
-			pi->calibration_cache.txcal_radio_regs_5G[3] =
-			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
-		}
-
-		pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
-	}
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (coreNum = 0; coreNum <= 1; coreNum++) {
-
-			txcal_radio_regs[2 * coreNum] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_FINE_I);
-			txcal_radio_regs[2 * coreNum + 1] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_FINE_Q);
-
-			txcal_radio_regs[2 * coreNum + 4] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_COARSE_I);
-			txcal_radio_regs[2 * coreNum + 5] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					    LOFT_COARSE_Q);
-		}
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_restorecal_nphy(phy_info_t *pi)
-{
-	u16 *loft_comp;
-	u16 txcal_coeffs_bphy[4];
-	u16 *tbl_ptr;
-	int coreNum;
-	u16 *txcal_radio_regs = NULL;
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (pi->nphy_iqcal_chanspec_2G == 0)
-			return;
-
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
-		loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
-	} else {
-		if (pi->nphy_iqcal_chanspec_5G == 0)
-			return;
-
-		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
-		loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
-				 (void *)tbl_ptr);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		txcal_coeffs_bphy[0] = tbl_ptr[0];
-		txcal_coeffs_bphy[1] = tbl_ptr[1];
-		txcal_coeffs_bphy[2] = tbl_ptr[2];
-		txcal_coeffs_bphy[3] = tbl_ptr[3];
-	} else {
-		txcal_coeffs_bphy[0] = 0;
-		txcal_coeffs_bphy[1] = 0;
-		txcal_coeffs_bphy[2] = 0;
-		txcal_coeffs_bphy[3] = 0;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
-				 txcal_coeffs_bphy);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2))
-		wlc_phy_tx_iq_war_nphy(pi);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_2G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[0]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[1]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[2]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[3]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[4]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[5]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[6]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[7]);
-		} else {
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[0]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[1]);
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[2]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_2G[3]);
-		}
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_2G);
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			txcal_radio_regs =
-			    pi->calibration_cache.txcal_radio_regs_5G;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[0]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[1]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[2]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_FINE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[3]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[4]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX0,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[5]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_I |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[6]);
-			write_radio_reg(pi,
-					RADIO_2056_TX_LOFT_COARSE_Q |
-					RADIO_2056_TX1,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[7]);
-		} else {
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[0]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[1]);
-			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[2]);
-			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
-					pi->calibration_cache.
-					txcal_radio_regs_5G[3]);
-		}
-
-		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
-					  &pi->calibration_cache.
-					  rxcal_coeffs_5G);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (coreNum = 0; coreNum <= 1; coreNum++) {
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_FINE_I,
-					 txcal_radio_regs[2 * coreNum]);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_FINE_Q,
-					 txcal_radio_regs[2 * coreNum + 1]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_COARSE_I,
-					 txcal_radio_regs[2 * coreNum + 4]);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
-					 LOFT_COARSE_Q,
-					 txcal_radio_regs[2 * coreNum + 5]);
-		}
-	}
-}
-
-void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init)
-{
-	phy_info_t *pi = (phy_info_t *) ppi;
-	u16 mask = 0xfc00;
-	u32 mc = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7))
-		return;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188;
-
-		if (lut_init == false)
-			return;
-
-		if (pi->srom_fem2g.antswctrllut == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x02, 16, &v0);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x03, 16, &v1);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x08, 16, &v2);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x0C, 16, &v3);
-		} else {
-			ASSERT(0);
-		}
-
-		if (pi->srom_fem5g.antswctrllut == 0) {
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x12, 16, &v0);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x13, 16, &v1);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x18, 16, &v2);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
-						 1, 0x1C, 16, &v3);
-		} else {
-			ASSERT(0);
-		}
-	} else {
-
-		write_phy_reg(pi, 0xc8, 0x0);
-		write_phy_reg(pi, 0xc9, 0x0);
-
-		si_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
-
-		mc = R_REG(pi->sh->osh, &pi->regs->maccontrol);
-		mc &= ~MCTL_GPOUT_SEL_MASK;
-		W_REG(pi->sh->osh, &pi->regs->maccontrol, mc);
-
-		OR_REG(pi->sh->osh, &pi->regs->psm_gpio_oe, mask);
-
-		AND_REG(pi->sh->osh, &pi->regs->psm_gpio_out, ~mask);
-
-		if (lut_init) {
-			write_phy_reg(pi, 0xf8, 0x02d8);
-			write_phy_reg(pi, 0xf9, 0x0301);
-			write_phy_reg(pi, 0xfa, 0x02d8);
-			write_phy_reg(pi, 0xfb, 0x0301);
-		}
-	}
-}
-
-u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val)
-{
-	u16 curr_ctl, new_ctl;
-	bool suspended = false;
-
-	if (D11REV_IS(pi->sh->corerev, 16)) {
-		suspended =
-		    (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC) ?
-		    false : true;
-		if (!suspended)
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	}
-
-	curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0);
-
-	new_ctl = (curr_ctl & (~mask)) | (val & mask);
-
-	mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl);
-
-	if (D11REV_IS(pi->sh->corerev, 16) && !suspended)
-		wlapi_enable_mac(pi->sh->physhim);
-
-	return new_ctl;
-}
-
-static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals)
-{
-
-	if (write == 0) {
-		vals[0] = read_phy_reg(pi, 0x2c);
-		vals[1] = read_phy_reg(pi, 0x42);
-	} else {
-		write_phy_reg(pi, 0x2c, vals[0]);
-		write_phy_reg(pi, 0x42, vals[1]);
-	}
-}
-
-void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd)
-{
-	u16 trigger_mask, status_mask;
-	u16 orig_RfseqCoreActv;
-
-	switch (cmd) {
-	case NPHY_RFSEQ_RX2TX:
-		trigger_mask = NPHY_RfseqTrigger_rx2tx;
-		status_mask = NPHY_RfseqStatus_rx2tx;
-		break;
-	case NPHY_RFSEQ_TX2RX:
-		trigger_mask = NPHY_RfseqTrigger_tx2rx;
-		status_mask = NPHY_RfseqStatus_tx2rx;
-		break;
-	case NPHY_RFSEQ_RESET2RX:
-		trigger_mask = NPHY_RfseqTrigger_reset2rx;
-		status_mask = NPHY_RfseqStatus_reset2rx;
-		break;
-	case NPHY_RFSEQ_UPDATEGAINH:
-		trigger_mask = NPHY_RfseqTrigger_updategainh;
-		status_mask = NPHY_RfseqStatus_updategainh;
-		break;
-	case NPHY_RFSEQ_UPDATEGAINL:
-		trigger_mask = NPHY_RfseqTrigger_updategainl;
-		status_mask = NPHY_RfseqStatus_updategainl;
-		break;
-	case NPHY_RFSEQ_UPDATEGAINU:
-		trigger_mask = NPHY_RfseqTrigger_updategainu;
-		status_mask = NPHY_RfseqStatus_updategainu;
-		break;
-	default:
-		return;
-	}
-
-	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
-	or_phy_reg(pi, 0xa1,
-		   (NPHY_RfseqMode_CoreActv_override |
-		    NPHY_RfseqMode_Trigger_override));
-	or_phy_reg(pi, 0xa3, trigger_mask);
-	SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000);
-	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
-
-	ASSERT((read_phy_reg(pi, 0xa4) & status_mask) == 0);
-}
-
-static void
-wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *events, u8 *dlys,
-		       u8 len)
-{
-	u32 t1_offset, t2_offset;
-	u8 ctr;
-	u8 end_event =
-	    NREV_GE(pi->pubpi.phy_rev,
-		    3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
-	u8 end_dly = 1;
-
-	ASSERT(len <= 16);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	t1_offset = cmd << 4;
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
-				 events);
-	t2_offset = t1_offset + 0x080;
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
-				 dlys);
-
-	for (ctr = len; ctr < 16; ctr++) {
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
-					 t1_offset + ctr, 8, &end_event);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
-					 t2_offset + ctr, 8, &end_dly);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset)
-{
-	u16 lpf_bw_ctl_val = 0;
-	u16 rx2tx_lpf_rc_lut_offset = 0;
-
-	if (offset == 0) {
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			rx2tx_lpf_rc_lut_offset = 0x159;
-		} else {
-			rx2tx_lpf_rc_lut_offset = 0x154;
-		}
-	} else {
-		rx2tx_lpf_rc_lut_offset = offset;
-	}
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
-				(u32) rx2tx_lpf_rc_lut_offset, 16,
-				&lpf_bw_ctl_val);
-
-	lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
-
-	return lpf_bw_ctl_val;
-}
-
-static void
-wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
-				  u8 core_mask, u8 off, u8 override_id)
-{
-	u8 core_num;
-	u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
-	u8 val_shift = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		en_mask = field;
-		for (core_num = 0; core_num < 2; core_num++) {
-			if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
-
-				switch (field) {
-				case (0x1 << 2):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 1);
-					val_shift = 1;
-					break;
-				case (0x1 << 3):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 2);
-					val_shift = 2;
-					break;
-				case (0x1 << 4):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 4);
-					val_shift = 4;
-					break;
-				case (0x1 << 5):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 5);
-					val_shift = 5;
-					break;
-				case (0x1 << 6):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 6);
-					val_shift = 6;
-					break;
-				case (0x1 << 7):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7a :
-					    0x7d;
-					val_mask = (0x1 << 7);
-					val_shift = 7;
-					break;
-				case (0x1 << 10):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0xf8 :
-					    0xfa;
-					val_mask = (0x7 << 4);
-					val_shift = 4;
-					break;
-				case (0x1 << 11):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7b :
-					    0x7e;
-					val_mask = (0xffff << 0);
-					val_shift = 0;
-					break;
-				case (0x1 << 12):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x7c :
-					    0x7f;
-					val_mask = (0xffff << 0);
-					val_shift = 0;
-					break;
-				case (0x3 << 13):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x348 :
-					    0x349;
-					val_mask = (0xff << 0);
-					val_shift = 0;
-					break;
-				case (0x1 << 13):
-					en_addr = (core_num == 0) ? 0xe7 : 0xec;
-					val_addr = (core_num == 0) ? 0x348 :
-					    0x349;
-					val_mask = (0xf << 0);
-					val_shift = 0;
-					break;
-				default:
-					addr = 0xffff;
-					break;
-				}
-			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
-
-				switch (field) {
-				case (0x1 << 1):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 1);
-					val_shift = 1;
-					break;
-				case (0x1 << 3):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 3);
-					val_shift = 3;
-					break;
-				case (0x1 << 5):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 5);
-					val_shift = 5;
-					break;
-				case (0x1 << 4):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 4);
-					val_shift = 4;
-					break;
-				case (0x1 << 2):
-
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 2);
-					val_shift = 2;
-					break;
-				case (0x1 << 7):
-
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x7 << 8);
-					val_shift = 8;
-					break;
-				case (0x1 << 11):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 14);
-					val_shift = 14;
-					break;
-				case (0x1 << 10):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 13);
-					val_shift = 13;
-					break;
-				case (0x1 << 9):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 12);
-					val_shift = 12;
-					break;
-				case (0x1 << 8):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 11);
-					val_shift = 11;
-					break;
-				case (0x1 << 6):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 6);
-					val_shift = 6;
-					break;
-				case (0x1 << 0):
-					en_addr = (core_num == 0) ? 0x342 :
-					    0x343;
-					val_addr = (core_num == 0) ? 0x340 :
-					    0x341;
-					val_mask = (0x1 << 0);
-					val_shift = 0;
-					break;
-				default:
-					addr = 0xffff;
-					break;
-				}
-			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
-
-				switch (field) {
-				case (0x1 << 3):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 3);
-					val_shift = 3;
-					break;
-				case (0x1 << 1):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 1);
-					val_shift = 1;
-					break;
-				case (0x1 << 0):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 0);
-					val_shift = 0;
-					break;
-				case (0x1 << 2):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 2);
-					val_shift = 2;
-					break;
-				case (0x1 << 4):
-					en_addr = (core_num == 0) ? 0x346 :
-					    0x347;
-					val_addr = (core_num == 0) ? 0x344 :
-					    0x345;
-					val_mask = (0x1 << 4);
-					val_shift = 4;
-					break;
-				default:
-					addr = 0xffff;
-					break;
-				}
-			}
-
-			if (off) {
-				and_phy_reg(pi, en_addr, ~en_mask);
-				and_phy_reg(pi, val_addr, ~val_mask);
-			} else {
-
-				if ((core_mask == 0)
-				    || (core_mask & (1 << core_num))) {
-					or_phy_reg(pi, en_addr, en_mask);
-
-					if (addr != 0xffff) {
-						mod_phy_reg(pi, val_addr,
-							    val_mask,
-							    (value <<
-							     val_shift));
-					}
-				}
-			}
-		}
-	}
-}
-
-static void
-wlc_phy_rfctrl_override_nphy(phy_info_t *pi, u16 field, u16 value,
-			     u8 core_mask, u8 off)
-{
-	u8 core_num;
-	u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
-	    0, val_mask = 0;
-	u8 shift = 0, val_shift = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		en_mask = field;
-		for (core_num = 0; core_num < 2; core_num++) {
-
-			switch (field) {
-			case (0x1 << 1):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 0);
-				val_shift = 0;
-				break;
-			case (0x1 << 2):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 1);
-				val_shift = 1;
-				break;
-			case (0x1 << 3):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 2);
-				val_shift = 2;
-				break;
-			case (0x1 << 4):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 4);
-				val_shift = 4;
-				break;
-			case (0x1 << 5):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 5);
-				val_shift = 5;
-				break;
-			case (0x1 << 6):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 6);
-				val_shift = 6;
-				break;
-			case (0x1 << 7):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x1 << 7);
-				val_shift = 7;
-				break;
-			case (0x1 << 8):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x7 << 8);
-				val_shift = 8;
-				break;
-			case (0x1 << 11):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7a : 0x7d;
-				val_mask = (0x7 << 13);
-				val_shift = 13;
-				break;
-
-			case (0x1 << 9):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
-				val_mask = (0x7 << 0);
-				val_shift = 0;
-				break;
-
-			case (0x1 << 10):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
-				val_mask = (0x7 << 4);
-				val_shift = 4;
-				break;
-
-			case (0x1 << 12):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7b : 0x7e;
-				val_mask = (0xffff << 0);
-				val_shift = 0;
-				break;
-			case (0x1 << 13):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0x7c : 0x7f;
-				val_mask = (0xffff << 0);
-				val_shift = 0;
-				break;
-			case (0x1 << 14):
-				en_addr = (core_num == 0) ? 0xe7 : 0xec;
-				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
-				val_mask = (0x3 << 6);
-				val_shift = 6;
-				break;
-			case (0x1 << 0):
-				en_addr = (core_num == 0) ? 0xe5 : 0xe6;
-				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
-				val_mask = (0x1 << 15);
-				val_shift = 15;
-				break;
-			default:
-				addr = 0xffff;
-				break;
-			}
-
-			if (off) {
-				and_phy_reg(pi, en_addr, ~en_mask);
-				and_phy_reg(pi, val_addr, ~val_mask);
-			} else {
-
-				if ((core_mask == 0)
-				    || (core_mask & (1 << core_num))) {
-					or_phy_reg(pi, en_addr, en_mask);
-
-					if (addr != 0xffff) {
-						mod_phy_reg(pi, val_addr,
-							    val_mask,
-							    (value <<
-							     val_shift));
-					}
-				}
-			}
-		}
-	} else {
-
-		if (off) {
-			and_phy_reg(pi, 0xec, ~field);
-			value = 0x0;
-		} else {
-			or_phy_reg(pi, 0xec, field);
-		}
-
-		for (core_num = 0; core_num < 2; core_num++) {
-
-			switch (field) {
-			case (0x1 << 1):
-			case (0x1 << 9):
-			case (0x1 << 12):
-			case (0x1 << 13):
-			case (0x1 << 14):
-				addr = 0x78;
-
-				core_mask = 0x1;
-				break;
-			case (0x1 << 2):
-			case (0x1 << 3):
-			case (0x1 << 4):
-			case (0x1 << 5):
-			case (0x1 << 6):
-			case (0x1 << 7):
-			case (0x1 << 8):
-				addr = (core_num == 0) ? 0x7a : 0x7d;
-				break;
-			case (0x1 << 10):
-				addr = (core_num == 0) ? 0x7b : 0x7e;
-				break;
-			case (0x1 << 11):
-				addr = (core_num == 0) ? 0x7c : 0x7f;
-				break;
-			default:
-				addr = 0xffff;
-			}
-
-			switch (field) {
-			case (0x1 << 1):
-				mask = (0x7 << 3);
-				shift = 3;
-				break;
-			case (0x1 << 9):
-				mask = (0x1 << 2);
-				shift = 2;
-				break;
-			case (0x1 << 12):
-				mask = (0x1 << 8);
-				shift = 8;
-				break;
-			case (0x1 << 13):
-				mask = (0x1 << 9);
-				shift = 9;
-				break;
-			case (0x1 << 14):
-				mask = (0xf << 12);
-				shift = 12;
-				break;
-			case (0x1 << 2):
-				mask = (0x1 << 0);
-				shift = 0;
-				break;
-			case (0x1 << 3):
-				mask = (0x1 << 1);
-				shift = 1;
-				break;
-			case (0x1 << 4):
-				mask = (0x1 << 2);
-				shift = 2;
-				break;
-			case (0x1 << 5):
-				mask = (0x3 << 4);
-				shift = 4;
-				break;
-			case (0x1 << 6):
-				mask = (0x3 << 6);
-				shift = 6;
-				break;
-			case (0x1 << 7):
-				mask = (0x1 << 8);
-				shift = 8;
-				break;
-			case (0x1 << 8):
-				mask = (0x1 << 9);
-				shift = 9;
-				break;
-			case (0x1 << 10):
-				mask = 0x1fff;
-				shift = 0x0;
-				break;
-			case (0x1 << 11):
-				mask = 0x1fff;
-				shift = 0x0;
-				break;
-			default:
-				mask = 0x0;
-				shift = 0x0;
-				break;
-			}
-
-			if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
-				mod_phy_reg(pi, addr, mask, (value << shift));
-			}
-		}
-
-		or_phy_reg(pi, 0xec, (0x1 << 0));
-		or_phy_reg(pi, 0x78, (0x1 << 0));
-		udelay(1);
-		and_phy_reg(pi, 0xec, ~(0x1 << 0));
-	}
-}
-
-static void
-wlc_phy_rfctrl_override_1tomany_nphy(phy_info_t *pi, u16 cmd, u16 value,
-				     u8 core_mask, u8 off)
-{
-	u16 rfmxgain = 0, lpfgain = 0;
-	u16 tgain = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		switch (cmd) {
-		case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
-							  value, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  value, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  value, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
-							  core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_rxgain:
-			rfmxgain = value & 0x000ff;
-			lpfgain = value & 0x0ff00;
-			lpfgain = lpfgain >> 8;
-
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
-							  rfmxgain, core_mask,
-							  off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
-							  lpfgain, core_mask,
-							  off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			break;
-		case NPHY_REV7_RfctrlOverride_cmd_txgain:
-			tgain = value & 0x7fff;
-			lpfgain = value & 0x8000;
-			lpfgain = lpfgain >> 14;
-
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
-							  tgain, core_mask, off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
-							  lpfgain, core_mask,
-							  off,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			break;
-		}
-	}
-}
-
-static void
-wlc_phy_scale_offset_rssi_nphy(phy_info_t *pi, u16 scale, s8 offset,
-			       u8 coresel, u8 rail, u8 rssi_type)
-{
-	u16 valuetostuff;
-
-	offset = (offset > NPHY_RSSICAL_MAXREAD) ?
-	    NPHY_RSSICAL_MAXREAD : offset;
-	offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
-	    -NPHY_RSSICAL_MAXREAD - 1 : offset;
-
-	valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1a6, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1ac, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1b2, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
-		write_phy_reg(pi, 0x1b8, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1a4, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1aa, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1b0, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
-		write_phy_reg(pi, 0x1b6, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1a5, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1ab, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1b1, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
-		write_phy_reg(pi, 0x1b7, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1a7, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1ad, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1b3, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
-		write_phy_reg(pi, 0x1b9, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1a8, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1ae, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1b4, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
-		write_phy_reg(pi, 0x1ba, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
-		write_phy_reg(pi, 0x1a9, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
-		write_phy_reg(pi, 0x1b5, valuetostuff);
-	}
-
-	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
-		write_phy_reg(pi, 0x1af, valuetostuff);
-	}
-	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
-	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
-	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
-		write_phy_reg(pi, 0x1bb, valuetostuff);
-	}
-}
-
-void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core_code, u8 rssi_type)
-{
-	u16 mask, val;
-	u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val,
-	    startseq;
-	u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val,
-	    rfctrlovr_trigger_val;
-	u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask;
-	u16 rfctrlcmd_val, rfctrlovr_val;
-	u8 core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (core_code == RADIO_MIMO_CORESEL_OFF) {
-			mod_phy_reg(pi, 0x8f, (0x1 << 9), 0);
-			mod_phy_reg(pi, 0xa5, (0x1 << 9), 0);
-
-			mod_phy_reg(pi, 0xa6, (0x3 << 8), 0);
-			mod_phy_reg(pi, 0xa7, (0x3 << 8), 0);
-
-			mod_phy_reg(pi, 0xe5, (0x1 << 5), 0);
-			mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
-
-			mask = (0x1 << 2) |
-			    (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
-			mod_phy_reg(pi, 0xf9, mask, 0);
-			mod_phy_reg(pi, 0xfb, mask, 0);
-
-		} else {
-			for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-				if (core_code == RADIO_MIMO_CORESEL_CORE1
-				    && core == PHY_CORE_1)
-					continue;
-				else if (core_code == RADIO_MIMO_CORESEL_CORE2
-					 && core == PHY_CORE_0)
-					continue;
-
-				mod_phy_reg(pi, (core == PHY_CORE_0) ?
-					    0x8f : 0xa5, (0x1 << 9), 1 << 9);
-
-				if (rssi_type == NPHY_RSSI_SEL_W1 ||
-				    rssi_type == NPHY_RSSI_SEL_W2 ||
-				    rssi_type == NPHY_RSSI_SEL_NB) {
-
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xa6 : 0xa7,
-						    (0x3 << 8), 0);
-
-					mask = (0x1 << 2) |
-					    (0x1 << 3) |
-					    (0x1 << 4) | (0x1 << 5);
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xf9 : 0xfb,
-						    mask, 0);
-
-					if (rssi_type == NPHY_RSSI_SEL_W1) {
-						if (CHSPEC_IS5G
-						    (pi->radio_chanspec)) {
-							mask = (0x1 << 2);
-							val = 1 << 2;
-						} else {
-							mask = (0x1 << 3);
-							val = 1 << 3;
-						}
-					} else if (rssi_type ==
-						   NPHY_RSSI_SEL_W2) {
-						mask = (0x1 << 4);
-						val = 1 << 4;
-					} else {
-						mask = (0x1 << 5);
-						val = 1 << 5;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xf9 : 0xfb,
-						    mask, val);
-
-					mask = (0x1 << 5);
-					val = 1 << 5;
-					mod_phy_reg(pi, (core == PHY_CORE_0) ?
-						    0xe5 : 0xe6, mask, val);
-				} else {
-					if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
-						mask = (0x3 << 8);
-						val = 1 << 8;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-						mask = (0x3 << 10);
-						val = 1 << 10;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-					} else if (rssi_type ==
-						   NPHY_RSSI_SEL_IQ) {
-
-						mask = (0x3 << 8);
-						val = 2 << 8;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-						mask = (0x3 << 10);
-						val = 2 << 10;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-					} else {
-
-						mask = (0x3 << 8);
-						val = 3 << 8;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-						mask = (0x3 << 10);
-						val = 3 << 10;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0xa6
-							    : 0xa7, mask, val);
-
-						if (PHY_IPA(pi)) {
-							if (NREV_GE
-							    (pi->pubpi.phy_rev,
-							     7)) {
-
-								write_radio_reg
-								    (pi,
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2057_TX0_TX_SSI_MUX
-								      :
-								      RADIO_2057_TX1_TX_SSI_MUX),
-								     (CHSPEC_IS5G
-								      (pi->
-								       radio_chanspec)
-								      ? 0xc :
-								      0xe));
-							} else {
-								write_radio_reg
-								    (pi,
-								     RADIO_2056_TX_TX_SSI_MUX
-								     |
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2056_TX0
-								      :
-								      RADIO_2056_TX1),
-								     (CHSPEC_IS5G
-								      (pi->
-								       radio_chanspec)
-								      ? 0xc :
-								      0xe));
-							}
-						} else {
-
-							if (NREV_GE
-							    (pi->pubpi.phy_rev,
-							     7)) {
-								write_radio_reg
-								    (pi,
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2057_TX0_TX_SSI_MUX
-								      :
-								      RADIO_2057_TX1_TX_SSI_MUX),
-								     0x11);
-
-								if (pi->pubpi.
-								    radioid ==
-								    BCM2057_ID)
-									write_radio_reg
-									    (pi,
-									     RADIO_2057_IQTEST_SEL_PU,
-									     0x1);
-
-							} else {
-								write_radio_reg
-								    (pi,
-								     RADIO_2056_TX_TX_SSI_MUX
-								     |
-								     ((core ==
-								       PHY_CORE_0)
-								      ?
-								      RADIO_2056_TX0
-								      :
-								      RADIO_2056_TX1),
-								     0x11);
-							}
-						}
-
-						afectrlovr_rssi_val = 1 << 9;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x8f
-							    : 0xa5, (0x1 << 9),
-							    afectrlovr_rssi_val);
-					}
-				}
-			}
-		}
-	} else {
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
-		    (rssi_type == NPHY_RSSI_SEL_W2) ||
-		    (rssi_type == NPHY_RSSI_SEL_NB)) {
-
-			val = 0x0;
-		} else if (rssi_type == NPHY_RSSI_SEL_TBD) {
-
-			val = 0x1;
-		} else if (rssi_type == NPHY_RSSI_SEL_IQ) {
-
-			val = 0x2;
-		} else {
-
-			val = 0x3;
-		}
-		mask = ((0x3 << 12) | (0x3 << 14));
-		val = (val << 12) | (val << 14);
-		mod_phy_reg(pi, 0xa6, mask, val);
-		mod_phy_reg(pi, 0xa7, mask, val);
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
-		    (rssi_type == NPHY_RSSI_SEL_W2) ||
-		    (rssi_type == NPHY_RSSI_SEL_NB)) {
-			if (rssi_type == NPHY_RSSI_SEL_W1) {
-				val = 0x1;
-			}
-			if (rssi_type == NPHY_RSSI_SEL_W2) {
-				val = 0x2;
-			}
-			if (rssi_type == NPHY_RSSI_SEL_NB) {
-				val = 0x3;
-			}
-			mask = (0x3 << 4);
-			val = (val << 4);
-			mod_phy_reg(pi, 0x7a, mask, val);
-			mod_phy_reg(pi, 0x7d, mask, val);
-		}
-
-		if (core_code == RADIO_MIMO_CORESEL_OFF) {
-			afectrlovr_rssi_val = 0;
-			rfctrlcmd_rxen_val = 0;
-			rfctrlcmd_coresel_val = 0;
-			rfctrlovr_rssi_val = 0;
-			rfctrlovr_rxen_val = 0;
-			rfctrlovr_coresel_val = 0;
-			rfctrlovr_trigger_val = 0;
-			startseq = 0;
-		} else {
-			afectrlovr_rssi_val = 1;
-			rfctrlcmd_rxen_val = 1;
-			rfctrlcmd_coresel_val = core_code;
-			rfctrlovr_rssi_val = 1;
-			rfctrlovr_rxen_val = 1;
-			rfctrlovr_coresel_val = 1;
-			rfctrlovr_trigger_val = 1;
-			startseq = 1;
-		}
-
-		afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13));
-		afectrlovr_rssi_val = (afectrlovr_rssi_val <<
-				       12) | (afectrlovr_rssi_val << 13);
-		mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask,
-			    afectrlovr_rssi_val);
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
-		    (rssi_type == NPHY_RSSI_SEL_W2) ||
-		    (rssi_type == NPHY_RSSI_SEL_NB)) {
-			rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
-			rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
-			    (rfctrlcmd_coresel_val << 3);
-
-			rfctrlovr_mask = ((0x1 << 5) |
-					  (0x1 << 12) |
-					  (0x1 << 1) | (0x1 << 0));
-			rfctrlovr_val = (rfctrlovr_rssi_val <<
-					 5) |
-			    (rfctrlovr_rxen_val << 12) |
-			    (rfctrlovr_coresel_val << 1) |
-			    (rfctrlovr_trigger_val << 0);
-
-			mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
-			mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
-
-			mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0));
-			udelay(20);
-
-			mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
-		}
-	}
-}
-
-int
-wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type, s32 *rssi_buf,
-		       u8 nsamps)
-{
-	s16 rssi0, rssi1;
-	u16 afectrlCore1_save = 0;
-	u16 afectrlCore2_save = 0;
-	u16 afectrlOverride1_save = 0;
-	u16 afectrlOverride2_save = 0;
-	u16 rfctrlOverrideAux0_save = 0;
-	u16 rfctrlOverrideAux1_save = 0;
-	u16 rfctrlMiscReg1_save = 0;
-	u16 rfctrlMiscReg2_save = 0;
-	u16 rfctrlcmd_save = 0;
-	u16 rfctrloverride_save = 0;
-	u16 rfctrlrssiothers1_save = 0;
-	u16 rfctrlrssiothers2_save = 0;
-	s8 tmp_buf[4];
-	u8 ctr = 0, samp = 0;
-	s32 rssi_out_val;
-	u16 gpiosel_orig;
-
-	afectrlCore1_save = read_phy_reg(pi, 0xa6);
-	afectrlCore2_save = read_phy_reg(pi, 0xa7);
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
-		rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
-		afectrlOverride1_save = read_phy_reg(pi, 0x8f);
-		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
-		rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
-		rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
-	} else {
-		afectrlOverride1_save = read_phy_reg(pi, 0xa5);
-		rfctrlcmd_save = read_phy_reg(pi, 0x78);
-		rfctrloverride_save = read_phy_reg(pi, 0xec);
-		rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a);
-		rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d);
-	}
-
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
-
-	gpiosel_orig = read_phy_reg(pi, 0xca);
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		write_phy_reg(pi, 0xca, 5);
-	}
-
-	for (ctr = 0; ctr < 4; ctr++) {
-		rssi_buf[ctr] = 0;
-	}
-
-	for (samp = 0; samp < nsamps; samp++) {
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-			rssi0 = read_phy_reg(pi, 0x1c9);
-			rssi1 = read_phy_reg(pi, 0x1ca);
-		} else {
-			rssi0 = read_phy_reg(pi, 0x219);
-			rssi1 = read_phy_reg(pi, 0x21a);
-		}
-
-		ctr = 0;
-		tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2;
-		tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2;
-		tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
-		tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
-
-		for (ctr = 0; ctr < 4; ctr++) {
-			rssi_buf[ctr] += tmp_buf[ctr];
-		}
-
-	}
-
-	rssi_out_val = rssi_buf[3] & 0xff;
-	rssi_out_val |= (rssi_buf[2] & 0xff) << 8;
-	rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
-	rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		write_phy_reg(pi, 0xca, gpiosel_orig);
-	}
-
-	write_phy_reg(pi, 0xa6, afectrlCore1_save);
-	write_phy_reg(pi, 0xa7, afectrlCore2_save);
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save);
-		write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save);
-		write_phy_reg(pi, 0x8f, afectrlOverride1_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
-		write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save);
-		write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save);
-	} else {
-		write_phy_reg(pi, 0xa5, afectrlOverride1_save);
-		write_phy_reg(pi, 0x78, rfctrlcmd_save);
-		write_phy_reg(pi, 0xec, rfctrloverride_save);
-		write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save);
-		write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save);
-	}
-
-	return rssi_out_val;
-}
-
-s16 wlc_phy_tempsense_nphy(phy_info_t *pi)
-{
-	u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save;
-	u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save;
-	u16 pwrdet_rxtx_core1_save;
-	u16 pwrdet_rxtx_core2_save;
-	u16 afectrlCore1_save;
-	u16 afectrlCore2_save;
-	u16 afectrlOverride_save;
-	u16 afectrlOverride2_save;
-	u16 pd_pll_ts_save;
-	u16 gpioSel_save;
-	s32 radio_temp[4];
-	s32 radio_temp2[4];
-	u16 syn_tempprocsense_save;
-	s16 offset = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save;
-		u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save;
-		u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH;
-		s32 auxADC_Vl;
-		u16 RfctrlOverride5_save, RfctrlOverride6_save;
-		u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save;
-		u16 RSSIMultCoef0QPowerDet_save;
-		u16 tempsense_Rcal;
-
-		syn_tempprocsense_save =
-		    read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
-
-		afectrlCore1_save = read_phy_reg(pi, 0xa6);
-		afectrlCore2_save = read_phy_reg(pi, 0xa7);
-		afectrlOverride_save = read_phy_reg(pi, 0x8f);
-		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
-		RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae);
-		RfctrlOverride5_save = read_phy_reg(pi, 0x346);
-		RfctrlOverride6_save = read_phy_reg(pi, 0x347);
-		RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
-		RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					&auxADC_Vmid_save);
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					&auxADC_Av_save);
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
-					&auxADC_rssi_ctrlL_save);
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
-					&auxADC_rssi_ctrlH_save);
-
-		write_phy_reg(pi, 0x1ae, 0x0);
-
-		auxADC_rssi_ctrlL = 0x0;
-		auxADC_rssi_ctrlH = 0x20;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
-					 &auxADC_rssi_ctrlL);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
-					 &auxADC_rssi_ctrlH);
-
-		tempsense_Rcal = syn_tempprocsense_save & 0x1c;
-
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				tempsense_Rcal | 0x01);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
-						  1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		mod_phy_reg(pi, 0xa6, (0x1 << 7), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 7), 0);
-		mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7));
-		mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7));
-
-		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
-		udelay(5);
-		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
-		mod_phy_reg(pi, 0xa6, (0x1 << 3), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 3), 0);
-		mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3));
-		mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3));
-		mod_phy_reg(pi, 0xa6, (0x1 << 6), 0);
-		mod_phy_reg(pi, 0xa7, (0x1 << 6), 0);
-		mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6));
-		mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6));
-
-		auxADC_Vmid = 0xA3;
-		auxADC_Av = 0x0;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					 &auxADC_Vmid);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					 &auxADC_Av);
-
-		udelay(3);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				tempsense_Rcal | 0x03);
-
-		udelay(5);
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-
-		auxADC_Av = 0x7;
-		if (radio_temp[1] + radio_temp2[1] < -30) {
-			auxADC_Vmid = 0x45;
-			auxADC_Vl = 263;
-		} else if (radio_temp[1] + radio_temp2[1] < -9) {
-			auxADC_Vmid = 0x200;
-			auxADC_Vl = 467;
-		} else if (radio_temp[1] + radio_temp2[1] < 11) {
-			auxADC_Vmid = 0x266;
-			auxADC_Vl = 634;
-		} else {
-			auxADC_Vmid = 0x2D5;
-			auxADC_Vl = 816;
-		}
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					 &auxADC_Vmid);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					 &auxADC_Av);
-
-		udelay(3);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				tempsense_Rcal | 0x01);
-
-		udelay(5);
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-
-		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
-				syn_tempprocsense_save);
-
-		write_phy_reg(pi, 0xa6, afectrlCore1_save);
-		write_phy_reg(pi, 0xa7, afectrlCore2_save);
-		write_phy_reg(pi, 0x8f, afectrlOverride_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
-		write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save);
-		write_phy_reg(pi, 0x346, RfctrlOverride5_save);
-		write_phy_reg(pi, 0x347, RfctrlOverride6_save);
-		write_phy_reg(pi, 0x344, RfctrlMiscReg5_save);
-		write_phy_reg(pi, 0x345, RfctrlMiscReg5_save);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
-					 &auxADC_Vmid_save);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
-					 &auxADC_Av_save);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
-					 &auxADC_rssi_ctrlL_save);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
-					 &auxADC_rssi_ctrlH_save);
-
-		if (pi->sh->chip == BCM5357_CHIP_ID) {
-			radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
-					 + 88 * (auxADC_Vl) - 27111 +
-					 128) / 256;
-		} else if (pi->sh->chip == BCM43236_CHIP_ID) {
-			radio_temp[0] = (198 * (radio_temp[1] + radio_temp2[1])
-					 + 91 * (auxADC_Vl) - 27243 +
-					 128) / 256;
-		} else {
-			radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
-					 + 82 * (auxADC_Vl) - 28861 +
-					 128) / 256;
-		}
-
-		offset = (s16) pi->phy_tempsense_offset;
-
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		syn_tempprocsense_save =
-		    read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
-
-		afectrlCore1_save = read_phy_reg(pi, 0xa6);
-		afectrlCore2_save = read_phy_reg(pi, 0xa7);
-		afectrlOverride_save = read_phy_reg(pi, 0x8f);
-		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
-		gpioSel_save = read_phy_reg(pi, 0xca);
-
-		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		} else {
-			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
-		}
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
-		} else {
-			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
-		}
-
-		radio_temp[0] =
-		    (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
-
-		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
-				syn_tempprocsense_save);
-
-		write_phy_reg(pi, 0xca, gpioSel_save);
-		write_phy_reg(pi, 0xa6, afectrlCore1_save);
-		write_phy_reg(pi, 0xa7, afectrlCore2_save);
-		write_phy_reg(pi, 0x8f, afectrlOverride_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
-
-		offset = (s16) pi->phy_tempsense_offset;
-	} else {
-
-		pwrdet_rxtx_core1_save =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
-		pwrdet_rxtx_core2_save =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
-		core1_txrf_iqcal1_save =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
-		core1_txrf_iqcal2_save =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
-		core2_txrf_iqcal1_save =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
-		core2_txrf_iqcal2_save =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
-		pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
-
-		afectrlCore1_save = read_phy_reg(pi, 0xa6);
-		afectrlCore2_save = read_phy_reg(pi, 0xa7);
-		afectrlOverride_save = read_phy_reg(pi, 0xa5);
-		gpioSel_save = read_phy_reg(pi, 0xca);
-
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
-		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
-		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
-
-		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
-		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
-
-		radio_temp[0] = (radio_temp[0] + radio_temp2[0]);
-		radio_temp[1] = (radio_temp[1] + radio_temp2[1]);
-		radio_temp[2] = (radio_temp[2] + radio_temp2[2]);
-		radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
-
-		radio_temp[0] =
-		    (radio_temp[0] + radio_temp[1] + radio_temp[2] +
-		     radio_temp[3]);
-
-		radio_temp[0] =
-		    (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
-
-		radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
-
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
-				pwrdet_rxtx_core1_save);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
-				pwrdet_rxtx_core2_save);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
-				core1_txrf_iqcal1_save);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
-				core2_txrf_iqcal1_save);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
-				core1_txrf_iqcal2_save);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
-				core2_txrf_iqcal2_save);
-		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save);
-
-		write_phy_reg(pi, 0xca, gpioSel_save);
-		write_phy_reg(pi, 0xa6, afectrlCore1_save);
-		write_phy_reg(pi, 0xa7, afectrlCore2_save);
-		write_phy_reg(pi, 0xa5, afectrlOverride_save);
-	}
-
-	return (s16) radio_temp[0] + offset;
-}
-
-static void
-wlc_phy_set_rssi_2055_vcm(phy_info_t *pi, u8 rssi_type, u8 *vcm_buf)
-{
-	u8 core;
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		if (rssi_type == NPHY_RSSI_SEL_NB) {
-			if (core == PHY_CORE_0) {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE1_B0_NBRSSI_VCM,
-					      RADIO_2055_NBRSSI_VCM_I_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
-					      RADIO_2055_NBRSSI_VCM_Q_MASK,
-					      vcm_buf[2 * core +
-						      1] <<
-					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
-			} else {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE2_B0_NBRSSI_VCM,
-					      RADIO_2055_NBRSSI_VCM_I_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
-					      RADIO_2055_NBRSSI_VCM_Q_MASK,
-					      vcm_buf[2 * core +
-						      1] <<
-					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
-			}
-		} else {
-
-			if (core == PHY_CORE_0) {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
-					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
-			} else {
-				mod_radio_reg(pi,
-					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
-					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
-					      vcm_buf[2 *
-						      core] <<
-					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
-			}
-		}
-	}
-}
-
-void wlc_phy_rssi_cal_nphy(phy_info_t *pi)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		wlc_phy_rssi_cal_nphy_rev3(pi);
-	} else {
-		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
-		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
-		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
-	}
-}
-
-static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type)
-{
-	s32 target_code;
-	u16 classif_state;
-	u16 clip_state[2];
-	u16 rssi_ctrl_state[2], pd_state[2];
-	u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
-	u16 rfctrlintc_override_val;
-	u16 clip_off[] = { 0xffff, 0xffff };
-	u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
-	u8 vcm, min_vcm, vcm_tmp[4];
-	u8 vcm_final[4] = { 0, 0, 0, 0 };
-	u8 result_idx, ctr;
-	s32 poll_results[4][4] = {
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0}
-	};
-	s32 poll_miniq[4][2] = {
-		{0, 0},
-		{0, 0},
-		{0, 0},
-		{0, 0}
-	};
-	s32 min_d, curr_d;
-	s32 fine_digital_offset[4];
-	s32 poll_results_min[4] = { 0, 0, 0, 0 };
-	s32 min_poll;
-
-	switch (rssi_type) {
-	case NPHY_RSSI_SEL_NB:
-		target_code = NPHY_RSSICAL_NB_TARGET;
-		break;
-	case NPHY_RSSI_SEL_W1:
-		target_code = NPHY_RSSICAL_W1_TARGET;
-		break;
-	case NPHY_RSSI_SEL_W2:
-		target_code = NPHY_RSSICAL_W2_TARGET;
-		break;
-	default:
-		return;
-		break;
-	}
-
-	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
-	wlc_phy_clip_det_nphy(pi, 0, clip_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_off);
-
-	rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
-	rfctrlintc_override_val =
-	    CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
-
-	rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
-	rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
-	write_phy_reg(pi, 0x91, rfctrlintc_override_val);
-	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
-
-	rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
-	rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
-	write_phy_reg(pi, 0x92, rfctrlintc_override_val);
-	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
-
-	pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
-	    RADIO_2055_WBRSSI_G2_PD;
-	pd_state[0] =
-	    read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
-	pd_state[1] =
-	    read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
-	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
-	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
-	rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
-	    RADIO_2055_WBRSSI_G2_SEL;
-	rssi_ctrl_state[0] =
-	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
-	rssi_ctrl_state[1] =
-	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
-
-	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
-				       NPHY_RAIL_I, rssi_type);
-	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
-				       NPHY_RAIL_Q, rssi_type);
-
-	for (vcm = 0; vcm < 4; vcm++) {
-
-		vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
-		if (rssi_type != NPHY_RSSI_SEL_W2) {
-			wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
-		}
-
-		wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
-				       NPHY_RSSICAL_NPOLL);
-
-		if ((rssi_type == NPHY_RSSI_SEL_W1)
-		    || (rssi_type == NPHY_RSSI_SEL_W2)) {
-			for (ctr = 0; ctr < 2; ctr++) {
-				poll_miniq[vcm][ctr] =
-				    min(poll_results[vcm][ctr * 2 + 0],
-					poll_results[vcm][ctr * 2 + 1]);
-			}
-		}
-	}
-
-	for (result_idx = 0; result_idx < 4; result_idx++) {
-		min_d = NPHY_RSSICAL_MAXD;
-		min_vcm = 0;
-		min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
-		for (vcm = 0; vcm < 4; vcm++) {
-			curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
-				      poll_results[vcm][result_idx] :
-				      poll_miniq[vcm][result_idx / 2]) -
-				     (target_code * NPHY_RSSICAL_NPOLL));
-			if (curr_d < min_d) {
-				min_d = curr_d;
-				min_vcm = vcm;
-			}
-			if (poll_results[vcm][result_idx] < min_poll) {
-				min_poll = poll_results[vcm][result_idx];
-			}
-		}
-		vcm_final[result_idx] = min_vcm;
-		poll_results_min[result_idx] = min_poll;
-	}
-
-	if (rssi_type != NPHY_RSSI_SEL_W2) {
-		wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
-	}
-
-	for (result_idx = 0; result_idx < 4; result_idx++) {
-		fine_digital_offset[result_idx] =
-		    (target_code * NPHY_RSSICAL_NPOLL) -
-		    poll_results[vcm_final[result_idx]][result_idx];
-		if (fine_digital_offset[result_idx] < 0) {
-			fine_digital_offset[result_idx] =
-			    ABS(fine_digital_offset[result_idx]);
-			fine_digital_offset[result_idx] +=
-			    (NPHY_RSSICAL_NPOLL / 2);
-			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
-			fine_digital_offset[result_idx] =
-			    -fine_digital_offset[result_idx];
-		} else {
-			fine_digital_offset[result_idx] +=
-			    (NPHY_RSSICAL_NPOLL / 2);
-			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
-		}
-
-		if (poll_results_min[result_idx] ==
-		    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
-			fine_digital_offset[result_idx] =
-			    (target_code - NPHY_RSSICAL_MAXREAD - 1);
-		}
-
-		wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
-					       (s8)
-					       fine_digital_offset[result_idx],
-					       (result_idx / 2 ==
-						0) ? RADIO_MIMO_CORESEL_CORE1 :
-					       RADIO_MIMO_CORESEL_CORE2,
-					       (result_idx % 2 ==
-						0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
-					       rssi_type);
-	}
-
-	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
-	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
-	if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_NB);
-	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_W1);
-	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_W2);
-	} else {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
-				     NPHY_RSSI_SEL_W2);
-	}
-	if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_NB);
-	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_W1);
-	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_W2);
-	} else {
-		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
-				     NPHY_RSSI_SEL_W2);
-	}
-
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
-
-	write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
-	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
-	write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
-	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
-
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_state);
-
-	wlc_phy_resetcca_nphy(pi);
-}
-
-int BCMFASTPATH
-wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh)
-{
-	d11rxhdr_t *rxh = &wlc_rxh->rxhdr;
-	s16 rxpwr, rxpwr0, rxpwr1;
-	s16 phyRx0_l, phyRx2_l;
-
-	rxpwr = 0;
-	rxpwr0 = ltoh16(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
-	rxpwr1 = (ltoh16(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
-
-	if (rxpwr0 > 127)
-		rxpwr0 -= 256;
-	if (rxpwr1 > 127)
-		rxpwr1 -= 256;
-
-	phyRx0_l = ltoh16(rxh->PhyRxStatus_0) & 0x00ff;
-	phyRx2_l = ltoh16(rxh->PhyRxStatus_2) & 0x00ff;
-	if (phyRx2_l > 127)
-		phyRx2_l -= 256;
-
-	if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
-		rxpwr0 = rxpwr1;
-		rxpwr1 = phyRx2_l;
-	}
-
-	wlc_rxh->rxpwr[0] = (s8) rxpwr0;
-	wlc_rxh->rxpwr[1] = (s8) rxpwr1;
-	wlc_rxh->do_rssi_ma = 0;
-
-	if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
-		rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
-	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
-		rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
-	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
-		rxpwr = (rxpwr0 + rxpwr1) >> 1;
-	else
-		ASSERT(0);
-
-	return rxpwr;
-}
-
-static void
-wlc_phy_rfctrlintc_override_nphy(phy_info_t *pi, u8 field, u16 value,
-				 u8 core_code)
-{
-	u16 mask;
-	u16 val;
-	u8 core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			if (core_code == RADIO_MIMO_CORESEL_CORE1
-			    && core == PHY_CORE_1)
-				continue;
-			else if (core_code == RADIO_MIMO_CORESEL_CORE2
-				 && core == PHY_CORE_0)
-				continue;
-
-			if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-				mask = (0x1 << 10);
-				val = 1 << 10;
-				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
-					    0x92, mask, val);
-			}
-
-			if (field == NPHY_RfctrlIntc_override_OFF) {
-
-				write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
-					      0x92, 0);
-
-				wlc_phy_force_rfseq_nphy(pi,
-							 NPHY_RFSEQ_RESET2RX);
-			} else if (field == NPHY_RfctrlIntc_override_TRSW) {
-
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-					mask = (0x1 << 6) | (0x1 << 7);
-
-					val = value << 6;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-
-					or_phy_reg(pi,
-						   (core ==
-						    PHY_CORE_0) ? 0x91 : 0x92,
-						   (0x1 << 10));
-
-					and_phy_reg(pi, 0x2ff, (u16)
-						    ~(0x3 << 14));
-					or_phy_reg(pi, 0x2ff, (0x1 << 13));
-					or_phy_reg(pi, 0x2ff, (0x1 << 0));
-				} else {
-
-					mask = (0x1 << 6) |
-					    (0x1 << 7) |
-					    (0x1 << 8) | (0x1 << 9);
-					val = value << 6;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-
-					mask = (0x1 << 0);
-					val = 1 << 0;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xe7 : 0xec,
-						    mask, val);
-
-					mask = (core == PHY_CORE_0) ? (0x1 << 0)
-					    : (0x1 << 1);
-					val = 1 << ((core == PHY_CORE_0) ?
-						    0 : 1);
-					mod_phy_reg(pi, 0x78, mask, val);
-
-					SPINWAIT(((read_phy_reg(pi, 0x78) & val)
-						  != 0), 10000);
-					ASSERT((read_phy_reg(pi, 0x78) & val) ==
-					       0);
-
-					mask = (0x1 << 0);
-					val = 0 << 0;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0xe7 : 0xec,
-						    mask, val);
-				}
-			} else if (field == NPHY_RfctrlIntc_override_PA) {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-					mask = (0x1 << 4) | (0x1 << 5);
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						val = value << 5;
-					} else {
-						val = value << 4;
-					}
-
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-
-					or_phy_reg(pi,
-						   (core ==
-						    PHY_CORE_0) ? 0x91 : 0x92,
-						   (0x1 << 12));
-				} else {
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						mask = (0x1 << 5);
-						val = value << 5;
-					} else {
-						mask = (0x1 << 4);
-						val = value << 4;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				}
-			} else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-						mask = (0x1 << 0);
-						val = value << 0;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 2);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					} else {
-
-						mask = (0x1 << 2);
-						val = value << 2;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 0);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					}
-
-					mask = (0x1 << 11);
-					val = 1 << 11;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				} else {
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						mask = (0x1 << 0);
-						val = value << 0;
-					} else {
-						mask = (0x1 << 2);
-						val = value << 2;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				}
-			} else if (field ==
-				   NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
-				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-						mask = (0x1 << 1);
-						val = value << 1;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 3);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					} else {
-
-						mask = (0x1 << 3);
-						val = value << 3;
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, val);
-
-						mask = (0x1 << 1);
-						mod_phy_reg(pi,
-							    (core ==
-							     PHY_CORE_0) ? 0x91
-							    : 0x92, mask, 0);
-					}
-
-					mask = (0x1 << 11);
-					val = 1 << 11;
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				} else {
-
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						mask = (0x1 << 1);
-						val = value << 1;
-					} else {
-						mask = (0x1 << 3);
-						val = value << 3;
-					}
-					mod_phy_reg(pi,
-						    (core ==
-						     PHY_CORE_0) ? 0x91 : 0x92,
-						    mask, val);
-				}
-			}
-		}
-	} else {
-		return;
-	}
-}
-
-static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi)
-{
-	u16 classif_state;
-	u16 clip_state[2];
-	u16 clip_off[] = { 0xffff, 0xffff };
-	s32 target_code;
-	u8 vcm, min_vcm;
-	u8 vcm_final = 0;
-	u8 result_idx;
-	s32 poll_results[8][4] = {
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0},
-		{0, 0, 0, 0}
-	};
-	s32 poll_result_core[4] = { 0, 0, 0, 0 };
-	s32 min_d = NPHY_RSSICAL_MAXD, curr_d;
-	s32 fine_digital_offset[4];
-	s32 poll_results_min[4] = { 0, 0, 0, 0 };
-	s32 min_poll;
-	u8 vcm_level_max;
-	u8 core;
-	u8 wb_cnt;
-	u8 rssi_type;
-	u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save;
-	u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save;
-	u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save;
-	u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save;
-	u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save;
-	u16 NPHY_RfctrlCmd_save;
-	u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save;
-	u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save;
-	u8 rxcore_state;
-	u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save;
-	u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save;
-	u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
-	u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
-
-	NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
-	    NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
-	    NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
-	    NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
-
-	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
-	wlc_phy_clip_det_nphy(pi, 0, clip_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_off);
-
-	NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91);
-	NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92);
-	NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f);
-	NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5);
-	NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6);
-	NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7);
-	NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7);
-	NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342);
-		NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343);
-		NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346);
-		NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347);
-	}
-	NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
-	NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
-	NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78);
-	NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
-	NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340);
-		NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341);
-		NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
-		NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
-	}
-	NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a);
-	NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d);
-
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0,
-					 RADIO_MIMO_CORESEL_ALLRXTX);
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
-					 RADIO_MIMO_CORESEL_ALLRXTX);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
-						     0, 0, 0);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rx_pu,
-						     1, 0, 0);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-						  1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0);
-	}
-
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
-							  0, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
-							  0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		} else {
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
-		}
-
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
-							  0, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
-							  0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		} else {
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
-		}
-	}
-
-	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
-
-	vcm_level_max = 8;
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-		if ((rxcore_state & (1 << core)) == 0)
-			continue;
-
-		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-					       core ==
-					       PHY_CORE_0 ?
-					       RADIO_MIMO_CORESEL_CORE1 :
-					       RADIO_MIMO_CORESEL_CORE2,
-					       NPHY_RAIL_I, NPHY_RSSI_SEL_NB);
-		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-					       core ==
-					       PHY_CORE_0 ?
-					       RADIO_MIMO_CORESEL_CORE1 :
-					       RADIO_MIMO_CORESEL_CORE2,
-					       NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
-
-		for (vcm = 0; vcm < vcm_level_max; vcm++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-				mod_radio_reg(pi, (core == PHY_CORE_0) ?
-					      RADIO_2057_NB_MASTER_CORE0 :
-					      RADIO_2057_NB_MASTER_CORE1,
-					      RADIO_2057_VCM_MASK, vcm);
-			} else {
-
-				mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
-					      ((core ==
-						PHY_CORE_0) ? RADIO_2056_RX0 :
-					       RADIO_2056_RX1),
-					      RADIO_2056_VCM_MASK,
-					      vcm << RADIO_2056_RSSI_VCM_SHIFT);
-			}
-
-			wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
-					       &poll_results[vcm][0],
-					       NPHY_RSSICAL_NPOLL);
-		}
-
-		for (result_idx = 0; result_idx < 4; result_idx++) {
-			if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
-
-				min_d = NPHY_RSSICAL_MAXD;
-				min_vcm = 0;
-				min_poll =
-				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
-				    1;
-				for (vcm = 0; vcm < vcm_level_max; vcm++) {
-					curr_d = poll_results[vcm][result_idx] *
-					    poll_results[vcm][result_idx] +
-					    poll_results[vcm][result_idx + 1] *
-					    poll_results[vcm][result_idx + 1];
-					if (curr_d < min_d) {
-						min_d = curr_d;
-						min_vcm = vcm;
-					}
-					if (poll_results[vcm][result_idx] <
-					    min_poll) {
-						min_poll =
-						    poll_results[vcm]
-						    [result_idx];
-					}
-				}
-				vcm_final = min_vcm;
-				poll_results_min[result_idx] = min_poll;
-			}
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mod_radio_reg(pi, (core == PHY_CORE_0) ?
-				      RADIO_2057_NB_MASTER_CORE0 :
-				      RADIO_2057_NB_MASTER_CORE1,
-				      RADIO_2057_VCM_MASK, vcm_final);
-		} else {
-			mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
-				      ((core ==
-					PHY_CORE_0) ? RADIO_2056_RX0 :
-				       RADIO_2056_RX1), RADIO_2056_VCM_MASK,
-				      vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
-		}
-
-		for (result_idx = 0; result_idx < 4; result_idx++) {
-			if (core == result_idx / 2) {
-				fine_digital_offset[result_idx] =
-				    (NPHY_RSSICAL_NB_TARGET *
-				     NPHY_RSSICAL_NPOLL) -
-				    poll_results[vcm_final][result_idx];
-				if (fine_digital_offset[result_idx] < 0) {
-					fine_digital_offset[result_idx] =
-					    ABS(fine_digital_offset
-						[result_idx]);
-					fine_digital_offset[result_idx] +=
-					    (NPHY_RSSICAL_NPOLL / 2);
-					fine_digital_offset[result_idx] /=
-					    NPHY_RSSICAL_NPOLL;
-					fine_digital_offset[result_idx] =
-					    -fine_digital_offset[result_idx];
-				} else {
-					fine_digital_offset[result_idx] +=
-					    (NPHY_RSSICAL_NPOLL / 2);
-					fine_digital_offset[result_idx] /=
-					    NPHY_RSSICAL_NPOLL;
-				}
-
-				if (poll_results_min[result_idx] ==
-				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
-					fine_digital_offset[result_idx] =
-					    (NPHY_RSSICAL_NB_TARGET -
-					     NPHY_RSSICAL_MAXREAD - 1);
-				}
-
-				wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
-							       (s8)
-							       fine_digital_offset
-							       [result_idx],
-							       (result_idx /
-								2 ==
-								0) ?
-							       RADIO_MIMO_CORESEL_CORE1
-							       :
-							       RADIO_MIMO_CORESEL_CORE2,
-							       (result_idx %
-								2 ==
-								0) ? NPHY_RAIL_I
-							       : NPHY_RAIL_Q,
-							       NPHY_RSSI_SEL_NB);
-			}
-		}
-
-	}
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-		if ((rxcore_state & (1 << core)) == 0)
-			continue;
-
-		for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) {
-			if (wb_cnt == 0) {
-				rssi_type = NPHY_RSSI_SEL_W1;
-				target_code = NPHY_RSSICAL_W1_TARGET_REV3;
-			} else {
-				rssi_type = NPHY_RSSI_SEL_W2;
-				target_code = NPHY_RSSICAL_W2_TARGET_REV3;
-			}
-
-			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-						       core ==
-						       PHY_CORE_0 ?
-						       RADIO_MIMO_CORESEL_CORE1
-						       :
-						       RADIO_MIMO_CORESEL_CORE2,
-						       NPHY_RAIL_I, rssi_type);
-			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
-						       core ==
-						       PHY_CORE_0 ?
-						       RADIO_MIMO_CORESEL_CORE1
-						       :
-						       RADIO_MIMO_CORESEL_CORE2,
-						       NPHY_RAIL_Q, rssi_type);
-
-			wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core,
-					       NPHY_RSSICAL_NPOLL);
-
-			for (result_idx = 0; result_idx < 4; result_idx++) {
-				if (core == result_idx / 2) {
-					fine_digital_offset[result_idx] =
-					    (target_code * NPHY_RSSICAL_NPOLL) -
-					    poll_result_core[result_idx];
-					if (fine_digital_offset[result_idx] < 0) {
-						fine_digital_offset[result_idx]
-						    =
-						    ABS(fine_digital_offset
-							[result_idx]);
-						fine_digital_offset[result_idx]
-						    += (NPHY_RSSICAL_NPOLL / 2);
-						fine_digital_offset[result_idx]
-						    /= NPHY_RSSICAL_NPOLL;
-						fine_digital_offset[result_idx]
-						    =
-						    -fine_digital_offset
-						    [result_idx];
-					} else {
-						fine_digital_offset[result_idx]
-						    += (NPHY_RSSICAL_NPOLL / 2);
-						fine_digital_offset[result_idx]
-						    /= NPHY_RSSICAL_NPOLL;
-					}
-
-					wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
-								       (s8)
-								       fine_digital_offset
-								       [core *
-									2],
-								       (core ==
-									PHY_CORE_0)
-								       ?
-								       RADIO_MIMO_CORESEL_CORE1
-								       :
-								       RADIO_MIMO_CORESEL_CORE2,
-								       (result_idx
-									% 2 ==
-									0) ?
-								       NPHY_RAIL_I
-								       :
-								       NPHY_RAIL_Q,
-								       rssi_type);
-				}
-			}
-
-		}
-	}
-
-	write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save);
-	write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save);
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0xe7, (0x1 << 0), 0);
-
-	mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0);
-	mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1);
-	mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
-
-	write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save);
-	write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save);
-	write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save);
-	write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save);
-	write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save);
-	write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save);
-		write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save);
-		write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save);
-		write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save);
-	}
-	write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save);
-	write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save);
-	write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save);
-	write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save);
-	write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save);
-		write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save);
-		write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save);
-		write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save);
-	}
-	write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save);
-	write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			pi->rssical_cache.rssical_radio_regs_2G[0] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
-			pi->rssical_cache.rssical_radio_regs_2G[1] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
-		} else {
-			pi->rssical_cache.rssical_radio_regs_2G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX0);
-			pi->rssical_cache.rssical_radio_regs_2G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX1);
-		}
-
-		pi->rssical_cache.rssical_phyregs_2G[0] =
-		    read_phy_reg(pi, 0x1a6);
-		pi->rssical_cache.rssical_phyregs_2G[1] =
-		    read_phy_reg(pi, 0x1ac);
-		pi->rssical_cache.rssical_phyregs_2G[2] =
-		    read_phy_reg(pi, 0x1b2);
-		pi->rssical_cache.rssical_phyregs_2G[3] =
-		    read_phy_reg(pi, 0x1b8);
-		pi->rssical_cache.rssical_phyregs_2G[4] =
-		    read_phy_reg(pi, 0x1a4);
-		pi->rssical_cache.rssical_phyregs_2G[5] =
-		    read_phy_reg(pi, 0x1aa);
-		pi->rssical_cache.rssical_phyregs_2G[6] =
-		    read_phy_reg(pi, 0x1b0);
-		pi->rssical_cache.rssical_phyregs_2G[7] =
-		    read_phy_reg(pi, 0x1b6);
-		pi->rssical_cache.rssical_phyregs_2G[8] =
-		    read_phy_reg(pi, 0x1a5);
-		pi->rssical_cache.rssical_phyregs_2G[9] =
-		    read_phy_reg(pi, 0x1ab);
-		pi->rssical_cache.rssical_phyregs_2G[10] =
-		    read_phy_reg(pi, 0x1b1);
-		pi->rssical_cache.rssical_phyregs_2G[11] =
-		    read_phy_reg(pi, 0x1b7);
-
-		pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			pi->rssical_cache.rssical_radio_regs_5G[0] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
-			pi->rssical_cache.rssical_radio_regs_5G[1] =
-			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
-		} else {
-			pi->rssical_cache.rssical_radio_regs_5G[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX0);
-			pi->rssical_cache.rssical_radio_regs_5G[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RSSI_MISC |
-					   RADIO_2056_RX1);
-		}
-
-		pi->rssical_cache.rssical_phyregs_5G[0] =
-		    read_phy_reg(pi, 0x1a6);
-		pi->rssical_cache.rssical_phyregs_5G[1] =
-		    read_phy_reg(pi, 0x1ac);
-		pi->rssical_cache.rssical_phyregs_5G[2] =
-		    read_phy_reg(pi, 0x1b2);
-		pi->rssical_cache.rssical_phyregs_5G[3] =
-		    read_phy_reg(pi, 0x1b8);
-		pi->rssical_cache.rssical_phyregs_5G[4] =
-		    read_phy_reg(pi, 0x1a4);
-		pi->rssical_cache.rssical_phyregs_5G[5] =
-		    read_phy_reg(pi, 0x1aa);
-		pi->rssical_cache.rssical_phyregs_5G[6] =
-		    read_phy_reg(pi, 0x1b0);
-		pi->rssical_cache.rssical_phyregs_5G[7] =
-		    read_phy_reg(pi, 0x1b6);
-		pi->rssical_cache.rssical_phyregs_5G[8] =
-		    read_phy_reg(pi, 0x1a5);
-		pi->rssical_cache.rssical_phyregs_5G[9] =
-		    read_phy_reg(pi, 0x1ab);
-		pi->rssical_cache.rssical_phyregs_5G[10] =
-		    read_phy_reg(pi, 0x1b1);
-		pi->rssical_cache.rssical_phyregs_5G[11] =
-		    read_phy_reg(pi, 0x1b7);
-
-		pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
-	}
-
-	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
-	wlc_phy_clip_det_nphy(pi, 1, clip_state);
-}
-
-static void wlc_phy_restore_rssical_nphy(phy_info_t *pi)
-{
-	ASSERT(NREV_GE(pi->pubpi.phy_rev, 3));
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		if (pi->nphy_rssical_chanspec_2G == 0)
-			return;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[0]);
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[1]);
-		} else {
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[0]);
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_2G[1]);
-		}
-
-		write_phy_reg(pi, 0x1a6,
-			      pi->rssical_cache.rssical_phyregs_2G[0]);
-		write_phy_reg(pi, 0x1ac,
-			      pi->rssical_cache.rssical_phyregs_2G[1]);
-		write_phy_reg(pi, 0x1b2,
-			      pi->rssical_cache.rssical_phyregs_2G[2]);
-		write_phy_reg(pi, 0x1b8,
-			      pi->rssical_cache.rssical_phyregs_2G[3]);
-		write_phy_reg(pi, 0x1a4,
-			      pi->rssical_cache.rssical_phyregs_2G[4]);
-		write_phy_reg(pi, 0x1aa,
-			      pi->rssical_cache.rssical_phyregs_2G[5]);
-		write_phy_reg(pi, 0x1b0,
-			      pi->rssical_cache.rssical_phyregs_2G[6]);
-		write_phy_reg(pi, 0x1b6,
-			      pi->rssical_cache.rssical_phyregs_2G[7]);
-		write_phy_reg(pi, 0x1a5,
-			      pi->rssical_cache.rssical_phyregs_2G[8]);
-		write_phy_reg(pi, 0x1ab,
-			      pi->rssical_cache.rssical_phyregs_2G[9]);
-		write_phy_reg(pi, 0x1b1,
-			      pi->rssical_cache.rssical_phyregs_2G[10]);
-		write_phy_reg(pi, 0x1b7,
-			      pi->rssical_cache.rssical_phyregs_2G[11]);
-
-	} else {
-		if (pi->nphy_rssical_chanspec_5G == 0)
-			return;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[0]);
-			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
-				      RADIO_2057_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[1]);
-		} else {
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[0]);
-			mod_radio_reg(pi,
-				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
-				      RADIO_2056_VCM_MASK,
-				      pi->rssical_cache.
-				      rssical_radio_regs_5G[1]);
-		}
-
-		write_phy_reg(pi, 0x1a6,
-			      pi->rssical_cache.rssical_phyregs_5G[0]);
-		write_phy_reg(pi, 0x1ac,
-			      pi->rssical_cache.rssical_phyregs_5G[1]);
-		write_phy_reg(pi, 0x1b2,
-			      pi->rssical_cache.rssical_phyregs_5G[2]);
-		write_phy_reg(pi, 0x1b8,
-			      pi->rssical_cache.rssical_phyregs_5G[3]);
-		write_phy_reg(pi, 0x1a4,
-			      pi->rssical_cache.rssical_phyregs_5G[4]);
-		write_phy_reg(pi, 0x1aa,
-			      pi->rssical_cache.rssical_phyregs_5G[5]);
-		write_phy_reg(pi, 0x1b0,
-			      pi->rssical_cache.rssical_phyregs_5G[6]);
-		write_phy_reg(pi, 0x1b6,
-			      pi->rssical_cache.rssical_phyregs_5G[7]);
-		write_phy_reg(pi, 0x1a5,
-			      pi->rssical_cache.rssical_phyregs_5G[8]);
-		write_phy_reg(pi, 0x1ab,
-			      pi->rssical_cache.rssical_phyregs_5G[9]);
-		write_phy_reg(pi, 0x1b1,
-			      pi->rssical_cache.rssical_phyregs_5G[10]);
-		write_phy_reg(pi, 0x1b7,
-			      pi->rssical_cache.rssical_phyregs_5G[11]);
-	}
-}
-
-static u16
-wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
-			      u8 dac_test_mode)
-{
-	u8 phy_bw, is_phybw40;
-	u16 num_samps, t, spur;
-	fixed theta = 0, rot = 0;
-	u32 tbl_len;
-	cs32 *tone_buf = NULL;
-
-	is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
-	phy_bw = (is_phybw40 == 1) ? 40 : 20;
-	tbl_len = (phy_bw << 3);
-
-	if (dac_test_mode == 1) {
-		spur = read_phy_reg(pi, 0x01);
-		spur = (spur >> 15) & 1;
-		phy_bw = (spur == 1) ? 82 : 80;
-		phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw;
-
-		tbl_len = (phy_bw << 1);
-	}
-
-	tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
-	if (tone_buf == NULL) {
-		return 0;
-	}
-
-	num_samps = (u16) tbl_len;
-	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
-	theta = 0;
-
-	for (t = 0; t < num_samps; t++) {
-
-		wlc_phy_cordic(theta, &tone_buf[t]);
-
-		theta += rot;
-
-		tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val);
-		tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val);
-	}
-
-	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
-
-	if (tone_buf != NULL)
-		kfree(tone_buf);
-
-	return num_samps;
-}
-
-int
-wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
-		     u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
-{
-	u16 num_samps;
-	u16 loops = 0xffff;
-	u16 wait = 0;
-
-	num_samps =
-		wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
-	if (num_samps == 0) {
-		return BCME_ERROR;
-	}
-
-	wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
-				dac_test_mode, modify_bbmult);
-
-	return BCME_OK;
-}
-
-static void
-wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
-			     u16 num_samps)
-{
-	u16 t;
-	u32 *data_buf = NULL;
-
-	data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
-	if (data_buf == NULL) {
-		return;
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	for (t = 0; t < num_samps; t++) {
-		data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
-		    (((unsigned int)tone_buf[t].q) & 0x3ff);
-	}
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
-				 data_buf);
-
-	if (data_buf != NULL)
-		kfree(data_buf);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void
-wlc_phy_runsamples_nphy(phy_info_t *pi, u16 num_samps, u16 loops,
-			u16 wait, u8 iqmode, u8 dac_test_mode,
-			bool modify_bbmult)
-{
-	u16 bb_mult;
-	u8 phy_bw, sample_cmd;
-	u16 orig_RfseqCoreActv;
-	u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3,
-	    lpf_bw_ctl_miscreg4;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	phy_bw = 20;
-	if (CHSPEC_IS40(pi->radio_chanspec))
-		phy_bw = 40;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7);
-		lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
-		if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
-			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
-			    (0x7 << 8);
-			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
-			    (0x7 << 8);
-		} else {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  wlc_phy_read_lpf_bw_ctl_nphy
-							  (pi, 0), 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-			pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
-
-			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
-			    (0x7 << 8);
-			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
-			    (0x7 << 8);
-		}
-	}
-
-	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) {
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
-					&bb_mult);
-		pi->nphy_bb_mult_save =
-		    BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
-	}
-
-	if (modify_bbmult) {
-		bb_mult = (phy_bw == 20) ? 100 : 71;
-		bb_mult = (bb_mult << 8) + bb_mult;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
-					 &bb_mult);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	write_phy_reg(pi, 0xc6, num_samps - 1);
-
-	if (loops != 0xffff) {
-		write_phy_reg(pi, 0xc4, loops - 1);
-	} else {
-		write_phy_reg(pi, 0xc4, loops);
-	}
-	write_phy_reg(pi, 0xc5, wait);
-
-	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
-	or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
-	if (iqmode) {
-
-		and_phy_reg(pi, 0xc2, 0x7FFF);
-
-		or_phy_reg(pi, 0xc2, 0x8000);
-	} else {
-
-		sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1;
-		write_phy_reg(pi, 0xc3, sample_cmd);
-	}
-
-	SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000);
-
-	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
-}
-
-void wlc_phy_stopplayback_nphy(phy_info_t *pi)
-{
-	u16 playback_status;
-	u16 bb_mult;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	playback_status = read_phy_reg(pi, 0xc7);
-	if (playback_status & 0x1) {
-		or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
-	} else if (playback_status & 0x2) {
-
-		and_phy_reg(pi, 0xc2,
-			    (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
-	}
-
-	and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
-
-	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) {
-
-		bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
-					 &bb_mult);
-
-		pi->nphy_bb_mult_save = 0;
-	}
-
-	if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
-		if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  0, 0, 1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-			pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
-		}
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi)
-{
-	u16 base_idx[2], curr_gain[2];
-	u8 core_no;
-	nphy_txgains_t target_gain;
-	u32 *tx_pwrctrl_tbl = NULL;
-
-	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-					curr_gain);
-
-		if (pi->phyhang_avoid)
-			wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-		for (core_no = 0; core_no < 2; core_no++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				target_gain.ipa[core_no] =
-				    curr_gain[core_no] & 0x0007;
-				target_gain.pad[core_no] =
-				    ((curr_gain[core_no] & 0x00F8) >> 3);
-				target_gain.pga[core_no] =
-				    ((curr_gain[core_no] & 0x0F00) >> 8);
-				target_gain.txgm[core_no] =
-				    ((curr_gain[core_no] & 0x7000) >> 12);
-				target_gain.txlpf[core_no] =
-				    ((curr_gain[core_no] & 0x8000) >> 15);
-			} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				target_gain.ipa[core_no] =
-				    curr_gain[core_no] & 0x000F;
-				target_gain.pad[core_no] =
-				    ((curr_gain[core_no] & 0x00F0) >> 4);
-				target_gain.pga[core_no] =
-				    ((curr_gain[core_no] & 0x0F00) >> 8);
-				target_gain.txgm[core_no] =
-				    ((curr_gain[core_no] & 0x7000) >> 12);
-			} else {
-				target_gain.ipa[core_no] =
-				    curr_gain[core_no] & 0x0003;
-				target_gain.pad[core_no] =
-				    ((curr_gain[core_no] & 0x000C) >> 2);
-				target_gain.pga[core_no] =
-				    ((curr_gain[core_no] & 0x0070) >> 4);
-				target_gain.txgm[core_no] =
-				    ((curr_gain[core_no] & 0x0380) >> 7);
-			}
-		}
-	} else {
-		base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f;
-		base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
-		for (core_no = 0; core_no < 2; core_no++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				if (PHY_IPA(pi)) {
-					tx_pwrctrl_tbl =
-					    wlc_phy_get_ipa_gaintbl_nphy(pi);
-				} else {
-					if (CHSPEC_IS5G(pi->radio_chanspec)) {
-						if NREV_IS
-							(pi->pubpi.phy_rev, 3) {
-							tx_pwrctrl_tbl =
-							    nphy_tpc_5GHz_txgain_rev3;
-						} else if NREV_IS
-							(pi->pubpi.phy_rev, 4) {
-							tx_pwrctrl_tbl =
-							    (pi->srom_fem5g.
-							     extpagain ==
-							     3) ?
-							    nphy_tpc_5GHz_txgain_HiPwrEPA
-							    :
-							    nphy_tpc_5GHz_txgain_rev4;
-						} else {
-							tx_pwrctrl_tbl =
-							    nphy_tpc_5GHz_txgain_rev5;
-						}
-					} else {
-						if (NREV_GE
-						    (pi->pubpi.phy_rev, 7)) {
-							if (pi->pubpi.
-							    radiorev == 3) {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_epa_2057rev3;
-							} else if (pi->pubpi.
-								   radiorev ==
-								   5) {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_epa_2057rev5;
-							}
-
-						} else {
-							if (NREV_GE
-							    (pi->pubpi.phy_rev,
-							     5)
-							    && (pi->srom_fem2g.
-								extpagain ==
-								3)) {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_HiPwrEPA;
-							} else {
-								tx_pwrctrl_tbl =
-								    nphy_tpc_txgain_rev3;
-							}
-						}
-					}
-				}
-				if NREV_GE
-					(pi->pubpi.phy_rev, 7) {
-					target_gain.ipa[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 16) & 0x7;
-					target_gain.pad[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 19) & 0x1f;
-					target_gain.pga[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 24) & 0xf;
-					target_gain.txgm[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 28) & 0x7;
-					target_gain.txlpf[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 31) & 0x1;
-				} else {
-					target_gain.ipa[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 16) & 0xf;
-					target_gain.pad[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 20) & 0xf;
-					target_gain.pga[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 24) & 0xf;
-					target_gain.txgm[core_no] =
-					    (tx_pwrctrl_tbl[base_idx[core_no]]
-					     >> 28) & 0x7;
-				}
-			} else {
-				target_gain.ipa[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
-				    0x3;
-				target_gain.pad[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
-				    0x3;
-				target_gain.pga[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
-				    0x7;
-				target_gain.txgm[core_no] =
-				    (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
-				    0x7;
-			}
-		}
-	}
-
-	return target_gain;
-}
-
-static void
-wlc_phy_iqcal_gainparams_nphy(phy_info_t *pi, u16 core_no,
-			      nphy_txgains_t target_gain,
-			      nphy_iqcal_params_t *params)
-{
-	u8 k;
-	int idx;
-	u16 gain_index;
-	u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			params->txlpf = target_gain.txlpf[core_no];
-		}
-		params->txgm = target_gain.txgm[core_no];
-		params->pga = target_gain.pga[core_no];
-		params->pad = target_gain.pad[core_no];
-		params->ipa = target_gain.ipa[core_no];
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			params->cal_gain =
-			    ((params->txlpf << 15) | (params->
-						      txgm << 12) | (params->
-								     pga << 8) |
-			     (params->pad << 3) | (params->ipa));
-		} else {
-			params->cal_gain =
-			    ((params->txgm << 12) | (params->
-						     pga << 8) | (params->
-								  pad << 4) |
-			     (params->ipa));
-		}
-		params->ncorr[0] = 0x79;
-		params->ncorr[1] = 0x79;
-		params->ncorr[2] = 0x79;
-		params->ncorr[3] = 0x79;
-		params->ncorr[4] = 0x79;
-	} else {
-
-		gain_index = ((target_gain.pad[core_no] << 0) |
-			      (target_gain.pga[core_no] << 4) | (target_gain.
-								 txgm[core_no]
-								 << 8));
-
-		idx = -1;
-		for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
-			if (tbl_iqcal_gainparams_nphy[band_idx][k][0] ==
-			    gain_index) {
-				idx = k;
-				break;
-			}
-		}
-
-		ASSERT(idx != -1);
-
-		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
-		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
-		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
-		params->cal_gain = ((params->txgm << 7) | (params->pga << 4) |
-				    (params->pad << 2));
-		params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4];
-		params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5];
-		params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6];
-		params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7];
-	}
-}
-
-static void wlc_phy_txcal_radio_setup_nphy(phy_info_t *pi)
-{
-	u16 jtag_core, core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		for (core = 0; core <= 1; core++) {
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TX_SSI_MASTER);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    IQCAL_VCM_HG);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    IQCAL_IDAC);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TX_SSI_MUX);
-
-			if (pi->pubpi.radiorev != 5)
-				pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
-				    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-						    TSSIA);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TSSI_MISC1);
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x0a);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_VCM_HG, 0x43);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_IDAC, 0x55);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_VCM, 0x00);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSIG, 0x00);
-				if (pi->use_int_tx_iqlo_cal_nphy) {
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TX_SSI_MUX, 0x4);
-					if (!
-					    (pi->
-					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x31);
-					} else {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x21);
-					}
-				}
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_MISC1, 0x00);
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x06);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_VCM_HG, 0x43);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 IQCAL_IDAC, 0x55);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_VCM, 0x00);
-
-				if (pi->pubpi.radiorev != 5)
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIA, 0x00);
-				if (pi->use_int_tx_iqlo_cal_nphy) {
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TX_SSI_MUX,
-							 0x06);
-					if (!
-					    (pi->
-					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIG, 0x31);
-					} else {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIG, 0x21);
-					}
-				}
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSI_MISC1, 0x00);
-			}
-		}
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		for (core = 0; core <= 1; core++) {
-			jtag_core =
-			    (core ==
-			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TX_SSI_MASTER |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_IQCAL_VCM_HG |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_IQCAL_IDAC |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_VCM | jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TX_AMP_DET |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TX_SSI_MUX |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
-			    read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
-			    read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_MISC1 |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_MISC2 |
-					   jtag_core);
-
-			pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_TSSI_MISC3 |
-					   jtag_core);
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_SSI_MASTER |
-						jtag_core, 0x0a);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_VCM_HG |
-						jtag_core, 0x40);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_IDAC |
-						jtag_core, 0x55);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_VCM |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_AMP_DET |
-						jtag_core, 0x00);
-
-				if (PHY_IPA(pi)) {
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x4);
-					write_radio_reg(pi,
-							RADIO_2056_TX_TSSIA |
-							jtag_core, 0x1);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x00);
-					write_radio_reg(pi,
-							RADIO_2056_TX_TSSIA |
-							jtag_core, 0x2f);
-				}
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSIG | jtag_core,
-						0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC1 |
-						jtag_core, 0x00);
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC2 |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC3 |
-						jtag_core, 0x00);
-			} else {
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_SSI_MASTER |
-						jtag_core, 0x06);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_VCM_HG |
-						jtag_core, 0x40);
-				write_radio_reg(pi,
-						RADIO_2056_TX_IQCAL_IDAC |
-						jtag_core, 0x55);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_VCM |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_AMP_DET |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSIA | jtag_core,
-						0x00);
-
-				if (PHY_IPA(pi)) {
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x06);
-					if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-
-						write_radio_reg(pi,
-								RADIO_2056_TX_TSSIG
-								| jtag_core,
-								0x11);
-					} else {
-
-						write_radio_reg(pi,
-								RADIO_2056_TX_TSSIG
-								| jtag_core,
-								0x1);
-					}
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_TX_TX_SSI_MUX
-							| jtag_core, 0x00);
-					write_radio_reg(pi,
-							RADIO_2056_TX_TSSIG |
-							jtag_core, 0x20);
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC1 |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC2 |
-						jtag_core, 0x00);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TSSI_MISC3 |
-						jtag_core, 0x00);
-			}
-		}
-	} else {
-
-		pi->tx_rx_cal_radio_saveregs[0] =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
-		pi->tx_rx_cal_radio_saveregs[1] =
-		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
-
-		pi->tx_rx_cal_radio_saveregs[2] =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
-		pi->tx_rx_cal_radio_saveregs[3] =
-		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
-
-		pi->tx_rx_cal_radio_saveregs[4] =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
-		pi->tx_rx_cal_radio_saveregs[5] =
-		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
-
-		if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
-		    0) {
-
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
-		} else {
-
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20);
-			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20);
-		}
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-			or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20);
-			or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20);
-		} else {
-
-			and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf);
-			and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf);
-		}
-	}
-}
-
-static void wlc_phy_txcal_radio_cleanup_nphy(phy_info_t *pi)
-{
-	u16 jtag_core, core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (core = 0; core <= 1; core++) {
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-					 TX_SSI_MASTER,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  0]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  1]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  2]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  3]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  5]);
-
-			if (pi->pubpi.radiorev != 5)
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSIA,
-						 pi->
-						 tx_rx_cal_radio_saveregs[(core
-									   *
-									   11) +
-									  6]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  7]);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
-					 pi->
-					 tx_rx_cal_radio_saveregs[(core * 11) +
-								  8]);
-		}
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		for (core = 0; core <= 1; core++) {
-			jtag_core =
-			    (core ==
-			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 0]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_IQCAL_VCM_HG | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 1]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_IQCAL_IDAC | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 2]);
-
-			write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 3]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TX_AMP_DET | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 4]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TX_SSI_MUX | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 5]);
-
-			write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 6]);
-
-			write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 7]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TSSI_MISC1 | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 8]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TSSI_MISC2 | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 9]);
-
-			write_radio_reg(pi,
-					RADIO_2056_TX_TSSI_MISC3 | jtag_core,
-					pi->
-					tx_rx_cal_radio_saveregs[(core * 11) +
-								 10]);
-		}
-	} else {
-
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
-				pi->tx_rx_cal_radio_saveregs[0]);
-		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
-				pi->tx_rx_cal_radio_saveregs[1]);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
-				pi->tx_rx_cal_radio_saveregs[2]);
-		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
-				pi->tx_rx_cal_radio_saveregs[3]);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
-				pi->tx_rx_cal_radio_saveregs[4]);
-		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
-				pi->tx_rx_cal_radio_saveregs[5]);
-	}
-}
-
-static void wlc_phy_txcal_physetup_nphy(phy_info_t *pi)
-{
-	u16 val, mask;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
-		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
-
-		mask = ((0x3 << 8) | (0x3 << 10));
-		val = (0x2 << 8);
-		val |= (0x2 << 10);
-		mod_phy_reg(pi, 0xa6, mask, val);
-		mod_phy_reg(pi, 0xa7, mask, val);
-
-		val = read_phy_reg(pi, 0x8f);
-		pi->tx_rx_cal_phy_saveregs[2] = val;
-		val |= ((0x1 << 9) | (0x1 << 10));
-		write_phy_reg(pi, 0x8f, val);
-
-		val = read_phy_reg(pi, 0xa5);
-		pi->tx_rx_cal_phy_saveregs[3] = val;
-		val |= ((0x1 << 9) | (0x1 << 10));
-		write_phy_reg(pi, 0xa5, val);
-
-		pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01);
-		mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[5] = val;
-		val = 0;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
-					 &val);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[6] = val;
-		val = 0;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
-					 &val);
-
-		pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
-		pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
-
-		if (!(pi->use_int_tx_iqlo_cal_nphy)) {
-
-			wlc_phy_rfctrlintc_override_nphy(pi,
-							 NPHY_RfctrlIntc_override_PA,
-							 1,
-							 RADIO_MIMO_CORESEL_CORE1
-							 |
-							 RADIO_MIMO_CORESEL_CORE2);
-		} else {
-
-			wlc_phy_rfctrlintc_override_nphy(pi,
-							 NPHY_RfctrlIntc_override_PA,
-							 0,
-							 RADIO_MIMO_CORESEL_CORE1
-							 |
-							 RADIO_MIMO_CORESEL_CORE2);
-		}
-
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x2, RADIO_MIMO_CORESEL_CORE1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x8, RADIO_MIMO_CORESEL_CORE2);
-
-		pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
-		pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
-		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-							  wlc_phy_read_lpf_bw_ctl_nphy
-							  (pi, 0), 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-
-		if (pi->use_int_tx_iqlo_cal_nphy
-		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
-					      1 << 4);
-
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-						      1, 0);
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-						      1, 0);
-				} else {
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
-						      1, 0);
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
-						      1, 0);
-				}
-			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-				wlc_phy_rfctrl_override_nphy_rev7(pi,
-								  (0x1 << 3), 0,
-								  0x3, 0,
-								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			}
-		}
-	} else {
-		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
-		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
-
-		mask = ((0x3 << 12) | (0x3 << 14));
-		val = (0x2 << 12);
-		val |= (0x2 << 14);
-		mod_phy_reg(pi, 0xa6, mask, val);
-		mod_phy_reg(pi, 0xa7, mask, val);
-
-		val = read_phy_reg(pi, 0xa5);
-		pi->tx_rx_cal_phy_saveregs[2] = val;
-		val |= ((0x1 << 12) | (0x1 << 13));
-		write_phy_reg(pi, 0xa5, val);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[3] = val;
-		val |= 0x2000;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
-					 &val);
-
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
-					&val);
-		pi->tx_rx_cal_phy_saveregs[4] = val;
-		val |= 0x2000;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
-					 &val);
-
-		pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91);
-		pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92);
-		val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
-		write_phy_reg(pi, 0x91, val);
-		write_phy_reg(pi, 0x92, val);
-	}
-}
-
-static void wlc_phy_txcal_phycleanup_nphy(phy_info_t *pi)
-{
-	u16 mask;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]);
-		write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]);
-		write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]);
-		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]);
-		write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
-					 &pi->tx_rx_cal_phy_saveregs[5]);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
-					 &pi->tx_rx_cal_phy_saveregs[6]);
-
-		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]);
-		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]);
-
-		write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
-		write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
-							  1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-
-		wlc_phy_resetcca_nphy(pi);
-
-		if (pi->use_int_tx_iqlo_cal_nphy
-		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
-
-			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
-						      1, 1);
-					mod_radio_reg(pi,
-						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
-						      1, 1);
-				} else {
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
-						      1, 1);
-					mod_radio_reg(pi,
-						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
-						      1, 1);
-				}
-
-				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
-					      0);
-			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
-				wlc_phy_rfctrl_override_nphy_rev7(pi,
-								  (0x1 << 3), 0,
-								  0x3, 1,
-								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-			}
-		}
-	} else {
-		mask = ((0x3 << 12) | (0x3 << 14));
-		mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]);
-		mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]);
-		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
-					 &pi->tx_rx_cal_phy_saveregs[3]);
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
-					 &pi->tx_rx_cal_phy_saveregs[4]);
-
-		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]);
-		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]);
-	}
-}
-
-#define NPHY_CAL_TSSISAMPS	64
-#define NPHY_TEST_TONE_FREQ_40MHz 4000
-#define NPHY_TEST_TONE_FREQ_20MHz 2500
-
-void
-wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf, u8 num_samps)
-{
-	u16 tssi_reg;
-	s32 temp, pwrindex[2];
-	s32 idle_tssi[2];
-	s32 rssi_buf[4];
-	s32 tssival[2];
-	u8 tssi_type;
-
-	tssi_reg = read_phy_reg(pi, 0x1e9);
-
-	temp = (s32) (tssi_reg & 0x3f);
-	idle_tssi[0] = (temp <= 31) ? temp : (temp - 64);
-
-	temp = (s32) ((tssi_reg >> 8) & 0x3f);
-	idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
-
-	tssi_type =
-	    CHSPEC_IS5G(pi->radio_chanspec) ?
-	    (u8)NPHY_RSSI_SEL_TSSI_5G:(u8)NPHY_RSSI_SEL_TSSI_2G;
-
-	wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
-
-	tssival[0] = rssi_buf[0] / ((s32) num_samps);
-	tssival[1] = rssi_buf[2] / ((s32) num_samps);
-
-	pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
-	pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
-
-	if (pwrindex[0] < 0) {
-		pwrindex[0] = 0;
-	} else if (pwrindex[0] > 63) {
-		pwrindex[0] = 63;
-	}
-
-	if (pwrindex[1] < 0) {
-		pwrindex[1] = 0;
-	} else if (pwrindex[1] > 63) {
-		pwrindex[1] = 63;
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
-				(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1,
-				(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
-}
-
-static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi)
-{
-	u16 txcal_gain[2];
-
-	pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
-	pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
-	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
-	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				txcal_gain);
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
-		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
-	} else {
-		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
-		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 txcal_gain);
-}
-
-static void wlc_phy_precal_txgain_nphy(phy_info_t *pi)
-{
-	bool save_bbmult = false;
-	u8 txcal_index_2057_rev5n7 = 0;
-	u8 txcal_index_2057_rev3n4n6 = 10;
-
-	if (pi->use_int_tx_iqlo_cal_nphy) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if ((pi->pubpi.radiorev == 3) ||
-			    (pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				pi->nphy_txcal_pwr_idx[0] =
-				    txcal_index_2057_rev3n4n6;
-				pi->nphy_txcal_pwr_idx[1] =
-				    txcal_index_2057_rev3n4n6;
-				wlc_phy_txpwr_index_nphy(pi, 3,
-							 txcal_index_2057_rev3n4n6,
-							 false);
-			} else {
-
-				pi->nphy_txcal_pwr_idx[0] =
-				    txcal_index_2057_rev5n7;
-				pi->nphy_txcal_pwr_idx[1] =
-				    txcal_index_2057_rev5n7;
-				wlc_phy_txpwr_index_nphy(pi, 3,
-							 txcal_index_2057_rev5n7,
-							 false);
-			}
-			save_bbmult = true;
-
-		} else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-			wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
-			if (pi->sh->hw_phytxchain != 3) {
-				pi->nphy_txcal_pwr_idx[1] =
-				    pi->nphy_txcal_pwr_idx[0];
-				wlc_phy_txpwr_index_nphy(pi, 3,
-							 pi->
-							 nphy_txcal_pwr_idx[0],
-							 true);
-				save_bbmult = true;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-			if (PHY_IPA(pi)) {
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					wlc_phy_cal_txgainctrl_nphy(pi, 12,
-								    false);
-				} else {
-					pi->nphy_txcal_pwr_idx[0] = 80;
-					pi->nphy_txcal_pwr_idx[1] = 80;
-					wlc_phy_txpwr_index_nphy(pi, 3, 80,
-								 false);
-					save_bbmult = true;
-				}
-			} else {
-
-				wlc_phy_internal_cal_txgain_nphy(pi);
-				save_bbmult = true;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
-			if (PHY_IPA(pi)) {
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					wlc_phy_cal_txgainctrl_nphy(pi, 12,
-								    false);
-				} else {
-					wlc_phy_cal_txgainctrl_nphy(pi, 14,
-								    false);
-				}
-			} else {
-
-				wlc_phy_internal_cal_txgain_nphy(pi);
-				save_bbmult = true;
-			}
-		}
-
-	} else {
-		wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
-	}
-
-	if (save_bbmult) {
-		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
-					&pi->nphy_txcal_bbmult);
-	}
-}
-
-void
-wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower, bool debug)
-{
-	int gainctrl_loopidx;
-	uint core;
-	u16 m0m1, curr_m0m1;
-	s32 delta_power;
-	s32 txpwrindex;
-	s32 qdBm_power[2];
-	u16 orig_BBConfig;
-	u16 phy_saveregs[4];
-	u32 freq_test;
-	u16 ampl_test = 250;
-	uint stepsize;
-	bool phyhang_avoid_state = false;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		stepsize = 2;
-	} else {
-
-		stepsize = 1;
-	}
-
-	if (CHSPEC_IS40(pi->radio_chanspec)) {
-		freq_test = 5000;
-	} else {
-		freq_test = 2500;
-	}
-
-	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
-	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	phyhang_avoid_state = pi->phyhang_avoid;
-	pi->phyhang_avoid = false;
-
-	phy_saveregs[0] = read_phy_reg(pi, 0x91);
-	phy_saveregs[1] = read_phy_reg(pi, 0x92);
-	phy_saveregs[2] = read_phy_reg(pi, 0xe7);
-	phy_saveregs[3] = read_phy_reg(pi, 0xec);
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
-					 RADIO_MIMO_CORESEL_CORE1 |
-					 RADIO_MIMO_CORESEL_CORE2);
-
-	if (!debug) {
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x2, RADIO_MIMO_CORESEL_CORE1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x8, RADIO_MIMO_CORESEL_CORE2);
-	} else {
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x1, RADIO_MIMO_CORESEL_CORE1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x7, RADIO_MIMO_CORESEL_CORE2);
-	}
-
-	orig_BBConfig = read_phy_reg(pi, 0x01);
-	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
-
-		for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
-		     gainctrl_loopidx++) {
-			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
-					     false);
-
-			if (core == PHY_CORE_0) {
-				curr_m0m1 = m0m1 & 0xff00;
-			} else {
-				curr_m0m1 = m0m1 & 0x00ff;
-			}
-
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
-			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
-
-			udelay(50);
-
-			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
-						 NPHY_CAL_TSSISAMPS);
-
-			pi->nphy_bb_mult_save = 0;
-			wlc_phy_stopplayback_nphy(pi);
-
-			delta_power = (dBm_targetpower * 4) - qdBm_power[core];
-
-			txpwrindex -= stepsize * delta_power;
-			if (txpwrindex < 0) {
-				txpwrindex = 0;
-			} else if (txpwrindex > 127) {
-				txpwrindex = 127;
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if (NREV_IS(pi->pubpi.phy_rev, 4) &&
-				    (pi->srom_fem5g.extpagain == 3)) {
-					if (txpwrindex < 30) {
-						txpwrindex = 30;
-					}
-				}
-			} else {
-				if (NREV_GE(pi->pubpi.phy_rev, 5) &&
-				    (pi->srom_fem2g.extpagain == 3)) {
-					if (txpwrindex < 50) {
-						txpwrindex = 50;
-					}
-				}
-			}
-
-			wlc_phy_txpwr_index_nphy(pi, (1 << core),
-						 (u8) txpwrindex, true);
-		}
-
-		pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
-
-		if (debug) {
-			u16 radio_gain;
-			u16 dbg_m0m1;
-
-			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
-
-			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
-					     false);
-
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
-			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
-
-			udelay(100);
-
-			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
-						 NPHY_CAL_TSSISAMPS);
-
-			wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
-						&radio_gain);
-
-			mdelay(4000);
-			pi->nphy_bb_mult_save = 0;
-			wlc_phy_stopplayback_nphy(pi);
-		}
-	}
-
-	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
-	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
-
-	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
-
-	write_phy_reg(pi, 0x01, orig_BBConfig);
-
-	write_phy_reg(pi, 0x91, phy_saveregs[0]);
-	write_phy_reg(pi, 0x92, phy_saveregs[1]);
-	write_phy_reg(pi, 0xe7, phy_saveregs[2]);
-	write_phy_reg(pi, 0xec, phy_saveregs[3]);
-
-	pi->phyhang_avoid = phyhang_avoid_state;
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core)
-{
-	int index;
-	u32 bbmult_scale;
-	u16 bbmult;
-	u16 tblentry;
-
-	nphy_txiqcal_ladder_t ladder_lo[] = {
-		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
-		{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
-		{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
-	};
-
-	nphy_txiqcal_ladder_t ladder_iq[] = {
-		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
-		{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
-		{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
-	};
-
-	bbmult = (core == PHY_CORE_0) ?
-	    ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
-						     nphy_txcal_bbmult & 0xff);
-
-	for (index = 0; index < 18; index++) {
-		bbmult_scale = ladder_lo[index].percent * bbmult;
-		bbmult_scale /= 100;
-
-		tblentry =
-		    ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
-					 &tblentry);
-
-		bbmult_scale = ladder_iq[index].percent * bbmult;
-		bbmult_scale /= 100;
-
-		tblentry =
-		    ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
-					 16, &tblentry);
-	}
-}
-
-void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype)
-{
-	nphy_txgains_t target_gain;
-	u8 tx_pwr_ctrl_state;
-	bool fullcal = true;
-	bool restore_tx_gain = false;
-	bool mphase;
-
-	if (NORADIO_ENAB(pi->pubpi)) {
-		wlc_phy_cal_perical_mphase_reset(pi);
-		return;
-	}
-
-	if (PHY_MUTED(pi))
-		return;
-
-	ASSERT(pi->nphy_perical != PHY_PERICAL_DISABLE);
-
-	if (caltype == PHY_PERICAL_AUTO)
-		fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec);
-	else if (caltype == PHY_PERICAL_PARTIAL)
-		fullcal = false;
-
-	if (pi->cal_type_override != PHY_PERICAL_AUTO) {
-		fullcal =
-		    (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
-	}
-
-	if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
-		if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
-			wlc_phy_cal_perical_mphase_restart(pi);
-	}
-
-	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
-	}
-
-	wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	wlc_phyreg_enter((wlc_phy_t *) pi);
-
-	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
-	    (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
-		pi->nphy_cal_orig_pwr_idx[0] =
-		    (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
-		pi->nphy_cal_orig_pwr_idx[1] =
-		    (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
-
-		if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
-						0x110, 16,
-						pi->nphy_cal_orig_tx_gain);
-		} else {
-			pi->nphy_cal_orig_tx_gain[0] = 0;
-			pi->nphy_cal_orig_tx_gain[1] = 0;
-		}
-	}
-	target_gain = wlc_phy_get_tx_gain_nphy(pi);
-	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-	if (pi->antsel_type == ANTSEL_2x3)
-		wlc_phy_antsel_init((wlc_phy_t *) pi, true);
-
-	mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE);
-	if (!mphase) {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_precal_txgain_nphy(pi);
-			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
-			restore_tx_gain = true;
-
-			target_gain = pi->nphy_cal_target_gain;
-		}
-		if (BCME_OK ==
-		    wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
-			if (PHY_IPA(pi))
-				wlc_phy_a4(pi, true);
-
-			wlc_phyreg_exit((wlc_phy_t *) pi);
-			wlapi_enable_mac(pi->sh->physhim);
-			wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION,
-					     10000);
-			wlapi_suspend_mac_and_wait(pi->sh->physhim);
-			wlc_phyreg_enter((wlc_phy_t *) pi);
-
-			if (BCME_OK == wlc_phy_cal_rxiq_nphy(pi, target_gain,
-							     (pi->
-							      first_cal_after_assoc
-							      || (pi->
-								  cal_type_override
-								  ==
-								  PHY_PERICAL_FULL))
-							     ? 2 : 0, false)) {
-				wlc_phy_savecal_nphy(pi);
-
-				wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
-
-				pi->nphy_perical_last = pi->sh->now;
-			}
-		}
-		if (caltype != PHY_PERICAL_AUTO) {
-			wlc_phy_rssi_cal_nphy(pi);
-		}
-
-		if (pi->first_cal_after_assoc
-		    || (pi->cal_type_override == PHY_PERICAL_FULL)) {
-			pi->first_cal_after_assoc = false;
-			wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
-			wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_radio205x_vcocal_nphy(pi);
-		}
-	} else {
-		ASSERT(pi->nphy_perical >= PHY_PERICAL_MPHASE);
-
-		switch (pi->mphase_cal_phase_id) {
-		case MPHASE_CAL_STATE_INIT:
-			pi->nphy_perical_last = pi->sh->now;
-			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				wlc_phy_precal_txgain_nphy(pi);
-			}
-			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
-			pi->mphase_cal_phase_id++;
-			break;
-
-		case MPHASE_CAL_STATE_TXPHASE0:
-		case MPHASE_CAL_STATE_TXPHASE1:
-		case MPHASE_CAL_STATE_TXPHASE2:
-		case MPHASE_CAL_STATE_TXPHASE3:
-		case MPHASE_CAL_STATE_TXPHASE4:
-		case MPHASE_CAL_STATE_TXPHASE5:
-			if ((pi->radar_percal_mask & 0x10) != 0)
-				pi->nphy_rxcal_active = true;
-
-			if (wlc_phy_cal_txiqlo_nphy
-			    (pi, pi->nphy_cal_target_gain, fullcal,
-			     true) != BCME_OK) {
-
-				wlc_phy_cal_perical_mphase_reset(pi);
-				break;
-			}
-
-			if (NREV_LE(pi->pubpi.phy_rev, 2) &&
-			    (pi->mphase_cal_phase_id ==
-			     MPHASE_CAL_STATE_TXPHASE4)) {
-				pi->mphase_cal_phase_id += 2;
-			} else {
-				pi->mphase_cal_phase_id++;
-			}
-			break;
-
-		case MPHASE_CAL_STATE_PAPDCAL:
-			if ((pi->radar_percal_mask & 0x2) != 0)
-				pi->nphy_rxcal_active = true;
-
-			if (PHY_IPA(pi)) {
-				wlc_phy_a4(pi, true);
-			}
-			pi->mphase_cal_phase_id++;
-			break;
-
-		case MPHASE_CAL_STATE_RXCAL:
-			if ((pi->radar_percal_mask & 0x1) != 0)
-				pi->nphy_rxcal_active = true;
-			if (wlc_phy_cal_rxiq_nphy(pi, target_gain,
-						  (pi->first_cal_after_assoc ||
-						   (pi->cal_type_override ==
-						    PHY_PERICAL_FULL)) ? 2 : 0,
-						  false) == BCME_OK) {
-				wlc_phy_savecal_nphy(pi);
-			}
-
-			pi->mphase_cal_phase_id++;
-			break;
-
-		case MPHASE_CAL_STATE_RSSICAL:
-			if ((pi->radar_percal_mask & 0x4) != 0)
-				pi->nphy_rxcal_active = true;
-			wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
-			wlc_phy_rssi_cal_nphy(pi);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				wlc_phy_radio205x_vcocal_nphy(pi);
-			}
-			restore_tx_gain = true;
-
-			if (pi->first_cal_after_assoc) {
-				pi->mphase_cal_phase_id++;
-			} else {
-				wlc_phy_cal_perical_mphase_reset(pi);
-			}
-
-			break;
-
-		case MPHASE_CAL_STATE_IDLETSSI:
-			if ((pi->radar_percal_mask & 0x8) != 0)
-				pi->nphy_rxcal_active = true;
-
-			if (pi->first_cal_after_assoc) {
-				pi->first_cal_after_assoc = false;
-				wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
-				wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-			}
-
-			wlc_phy_cal_perical_mphase_reset(pi);
-			break;
-
-		default:
-			ASSERT(0);
-			wlc_phy_cal_perical_mphase_reset(pi);
-			break;
-		}
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (restore_tx_gain) {
-			if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) {
-
-				wlc_phy_txpwr_index_nphy(pi, 1,
-							 pi->
-							 nphy_cal_orig_pwr_idx
-							 [0], false);
-				wlc_phy_txpwr_index_nphy(pi, 2,
-							 pi->
-							 nphy_cal_orig_pwr_idx
-							 [1], false);
-
-				pi->nphy_txpwrindex[0].index = -1;
-				pi->nphy_txpwrindex[1].index = -1;
-			} else {
-				wlc_phy_txpwr_index_nphy(pi, (1 << 0),
-							 (s8) (pi->
-								 nphy_txpwrindex
-								 [0].
-								 index_internal),
-							 false);
-				wlc_phy_txpwr_index_nphy(pi, (1 << 1),
-							 (s8) (pi->
-								 nphy_txpwrindex
-								 [1].
-								 index_internal),
-							 false);
-			}
-		}
-	}
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-	wlc_phyreg_exit((wlc_phy_t *) pi);
-	wlapi_enable_mac(pi->sh->physhim);
-}
-
-int
-wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-			bool fullcal, bool mphase)
-{
-	u16 val;
-	u16 tbl_buf[11];
-	u8 cal_cnt;
-	u16 cal_cmd;
-	u8 num_cals, max_cal_cmds;
-	u16 core_no, cal_type;
-	u16 diq_start = 0;
-	u8 phy_bw;
-	u16 max_val;
-	u16 tone_freq;
-	u16 gain_save[2];
-	u16 cal_gain[2];
-	nphy_iqcal_params_t cal_params[2];
-	u32 tbl_len;
-	void *tbl_ptr;
-	bool ladder_updated[2];
-	u8 mphase_cal_lastphase = 0;
-	int bcmerror = BCME_OK;
-	bool phyhang_avoid_state = false;
-
-	u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
-		0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
-		    0x1902,
-		0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
-		    0x6407
-	};
-
-	u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
-		0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
-		    0x3200,
-		0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
-		    0x6407
-	};
-
-	u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
-		0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
-		    0x1202,
-		0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
-		    0x4707
-	};
-
-	u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
-		0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
-		    0x2300,
-		0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
-		    0x4707
-	};
-
-	u16 tbl_tx_iqlo_cal_startcoefs[] = {
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		    0x0000
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
-		0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
-		0x9123, 0x9264, 0x9086, 0x9245, 0x9056
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_recal[] = {
-		0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
-		0x9101, 0x9253, 0x9053, 0x9234, 0x9034
-	};
-
-	u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-		0x0000
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
-		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
-		0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
-	};
-
-	u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
-		0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
-		0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
-	};
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		phyhang_avoid_state = pi->phyhang_avoid;
-		pi->phyhang_avoid = false;
-	}
-
-	if (CHSPEC_IS40(pi->radio_chanspec)) {
-		phy_bw = 40;
-	} else {
-		phy_bw = 20;
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
-
-	for (core_no = 0; core_no <= 1; core_no++) {
-		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
-					      &cal_params[core_no]);
-		cal_gain[core_no] = cal_params[core_no].cal_gain;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
-
-	wlc_phy_txcal_radio_setup_nphy(pi);
-
-	wlc_phy_txcal_physetup_nphy(pi);
-
-	ladder_updated[0] = ladder_updated[1] = false;
-	if (!(NREV_GE(pi->pubpi.phy_rev, 6) ||
-	      (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi)
-	       && (CHSPEC_IS2G(pi->radio_chanspec))))) {
-
-		if (phy_bw == 40) {
-			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40);
-		} else {
-			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20);
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0,
-					 16, tbl_ptr);
-
-		if (phy_bw == 40) {
-			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40);
-		} else {
-			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20;
-			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20);
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32,
-					 16, tbl_ptr);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0xc2, 0x8ad9);
-	} else {
-		write_phy_reg(pi, 0xc2, 0x8aa9);
-	}
-
-	max_val = 250;
-	tone_freq = (phy_bw == 20) ? 2500 : 5000;
-
-	if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
-		wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false);
-		bcmerror = BCME_OK;
-	} else {
-		bcmerror =
-		    wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
-	}
-
-	if (bcmerror == BCME_OK) {
-
-		if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
-			tbl_ptr = pi->mphase_txcal_bestcoeffs;
-			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-				tbl_len -= 2;
-			}
-		} else {
-			if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
-
-				tbl_ptr = pi->nphy_txiqlocal_bestc;
-				tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
-				if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-					tbl_len -= 2;
-				}
-			} else {
-
-				fullcal = true;
-
-				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-					tbl_ptr =
-					    tbl_tx_iqlo_cal_startcoefs_nphyrev3;
-					tbl_len =
-					    ARRAY_SIZE
-					    (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
-				} else {
-					tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
-					tbl_len =
-					    ARRAY_SIZE
-					    (tbl_tx_iqlo_cal_startcoefs);
-				}
-			}
-		}
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64,
-					 16, tbl_ptr);
-
-		if (fullcal) {
-			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
-		} else {
-			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
-			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
-		}
-
-		if (mphase) {
-			cal_cnt = pi->mphase_txcal_cmdidx;
-			if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
-				num_cals = cal_cnt + pi->mphase_txcal_numcmds;
-			} else {
-				num_cals = max_cal_cmds;
-			}
-		} else {
-			cal_cnt = 0;
-			num_cals = max_cal_cmds;
-		}
-
-		for (; cal_cnt < num_cals; cal_cnt++) {
-
-			if (fullcal) {
-				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-				    tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
-				    [cal_cnt] :
-				    tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
-			} else {
-				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
-				    tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
-				    : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
-			}
-
-			core_no = ((cal_cmd & 0x3000) >> 12);
-			cal_type = ((cal_cmd & 0x0F00) >> 8);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 6) ||
-			    (NREV_IS(pi->pubpi.phy_rev, 5) &&
-			     PHY_IPA(pi)
-			     && (CHSPEC_IS2G(pi->radio_chanspec)))) {
-				if (!ladder_updated[core_no]) {
-					wlc_phy_update_txcal_ladder_nphy(pi,
-									 core_no);
-					ladder_updated[core_no] = true;
-				}
-			}
-
-			val =
-			    (cal_params[core_no].
-			     ncorr[cal_type] << 8) | NPHY_N_GCTL;
-			write_phy_reg(pi, 0xc1, val);
-
-			if ((cal_type == 1) || (cal_type == 3)
-			    || (cal_type == 4)) {
-
-				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-							1, 69 + core_no, 16,
-							tbl_buf);
-
-				diq_start = tbl_buf[0];
-
-				tbl_buf[0] = 0;
-				wlc_phy_table_write_nphy(pi,
-							 NPHY_TBL_ID_IQLOCAL, 1,
-							 69 + core_no, 16,
-							 tbl_buf);
-			}
-
-			write_phy_reg(pi, 0xc0, cal_cmd);
-
-			SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0),
-				 20000);
-			ASSERT((read_phy_reg(pi, 0xc0) & 0xc000) == 0);
-
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						tbl_len, 96, 16, tbl_buf);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						 tbl_len, 64, 16, tbl_buf);
-
-			if ((cal_type == 1) || (cal_type == 3)
-			    || (cal_type == 4)) {
-
-				tbl_buf[0] = diq_start;
-
-			}
-
-		}
-
-		if (mphase) {
-			pi->mphase_txcal_cmdidx = num_cals;
-			if (pi->mphase_txcal_cmdidx >= max_cal_cmds)
-				pi->mphase_txcal_cmdidx = 0;
-		}
-
-		mphase_cal_lastphase =
-		    (NREV_LE(pi->pubpi.phy_rev, 2)) ?
-		    MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
-
-		if (!mphase
-		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
-
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96,
-						16, tbl_buf);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
-						 16, tbl_buf);
-
-			if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-				tbl_buf[0] = 0;
-				tbl_buf[1] = 0;
-				tbl_buf[2] = 0;
-				tbl_buf[3] = 0;
-
-			}
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
-						 16, tbl_buf);
-
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101,
-						16, tbl_buf);
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
-						 16, tbl_buf);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
-						 16, tbl_buf);
-
-			tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-				tbl_len -= 2;
-			}
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						tbl_len, 96, 16,
-						pi->nphy_txiqlocal_bestc);
-
-			pi->nphy_txiqlocal_coeffsvalid = true;
-			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
-		} else {
-			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-
-				tbl_len -= 2;
-			}
-			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-						tbl_len, 96, 16,
-						pi->mphase_txcal_bestcoeffs);
-		}
-
-		wlc_phy_stopplayback_nphy(pi);
-
-		write_phy_reg(pi, 0xc2, 0x0000);
-
-	}
-
-	wlc_phy_txcal_phycleanup_nphy(pi);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 gain_save);
-
-	wlc_phy_txcal_radio_cleanup_nphy(pi);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-		if (!mphase
-		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase))
-			wlc_phy_tx_iq_war_nphy(pi);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		pi->phyhang_avoid = phyhang_avoid_state;
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	return bcmerror;
-}
-
-static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi)
-{
-	u16 tbl_buf[7];
-
-	ASSERT(NREV_LT(pi->pubpi.phy_rev, 2));
-
-	if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) &&
-	    (pi->nphy_txiqlocal_coeffsvalid)) {
-		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
-					ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf);
-
-		if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) ||
-		    (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) ||
-		    (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) ||
-		    (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) {
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
-						 16, pi->nphy_txiqlocal_bestc);
-
-			tbl_buf[0] = 0;
-			tbl_buf[1] = 0;
-			tbl_buf[2] = 0;
-			tbl_buf[3] = 0;
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
-						 16, tbl_buf);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
-						 16,
-						 &pi->nphy_txiqlocal_bestc[5]);
-
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
-						 16,
-						 &pi->nphy_txiqlocal_bestc[5]);
-		}
-	}
-}
-
-static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi)
-{
-	nphy_iq_comp_t tx_comp;
-
-	wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
-
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
-	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
-}
-
-void
-wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write, nphy_iq_comp_t *pcomp)
-{
-	if (write) {
-		write_phy_reg(pi, 0x9a, pcomp->a0);
-		write_phy_reg(pi, 0x9b, pcomp->b0);
-		write_phy_reg(pi, 0x9c, pcomp->a1);
-		write_phy_reg(pi, 0x9d, pcomp->b1);
-	} else {
-		pcomp->a0 = read_phy_reg(pi, 0x9a);
-		pcomp->b0 = read_phy_reg(pi, 0x9b);
-		pcomp->a1 = read_phy_reg(pi, 0x9c);
-		pcomp->b1 = read_phy_reg(pi, 0x9d);
-	}
-}
-
-void
-wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est, u16 num_samps,
-		       u8 wait_time, u8 wait_for_crs)
-{
-	u8 core;
-
-	write_phy_reg(pi, 0x12b, num_samps);
-	mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0));
-	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode,
-		    (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0);
-
-	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart);
-
-	SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0),
-		 10000);
-	ASSERT((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0);
-
-	if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
-		ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			est[core].i_pwr =
-			    (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
-			    | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
-			est[core].q_pwr =
-			    (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
-			    | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
-			est[core].iq_prod =
-			    (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
-			    read_phy_reg(pi, NPHY_IqestIqAccLo(core));
-		}
-	}
-}
-
-#define CAL_RETRY_CNT 2
-static void wlc_phy_calc_rx_iq_comp_nphy(phy_info_t *pi, u8 core_mask)
-{
-	u8 curr_core;
-	phy_iq_est_t est[PHY_CORE_MAX];
-	nphy_iq_comp_t old_comp, new_comp;
-	s32 iq = 0;
-	u32 ii = 0, qq = 0;
-	s16 iq_nbits, qq_nbits, brsh, arsh;
-	s32 a, b, temp;
-	int bcmerror = BCME_OK;
-	uint cal_retry = 0;
-
-	if (core_mask == 0x0)
-		return;
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp);
-	new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
-
- cal_try:
-	wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
-
-	new_comp = old_comp;
-
-	for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) {
-
-		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
-			iq = est[curr_core].iq_prod;
-			ii = est[curr_core].i_pwr;
-			qq = est[curr_core].q_pwr;
-		} else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
-			iq = est[curr_core].iq_prod;
-			ii = est[curr_core].i_pwr;
-			qq = est[curr_core].q_pwr;
-		} else {
-			continue;
-		}
-
-		if ((ii + qq) < NPHY_MIN_RXIQ_PWR) {
-			bcmerror = BCME_ERROR;
-			break;
-		}
-
-		iq_nbits = wlc_phy_nbits(iq);
-		qq_nbits = wlc_phy_nbits(qq);
-
-		arsh = 10 - (30 - iq_nbits);
-		if (arsh >= 0) {
-			a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
-			temp = (s32) (ii >> arsh);
-			if (temp == 0) {
-				bcmerror = BCME_ERROR;
-				break;
-			}
-		} else {
-			a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
-			temp = (s32) (ii << -arsh);
-			if (temp == 0) {
-				bcmerror = BCME_ERROR;
-				break;
-			}
-		}
-
-		a /= temp;
-
-		brsh = qq_nbits - 31 + 20;
-		if (brsh >= 0) {
-			b = (qq << (31 - qq_nbits));
-			temp = (s32) (ii >> brsh);
-			if (temp == 0) {
-				bcmerror = BCME_ERROR;
-				break;
-			}
-		} else {
-			b = (qq << (31 - qq_nbits));
-			temp = (s32) (ii << -brsh);
-			if (temp == 0) {
-				bcmerror = BCME_ERROR;
-				break;
-			}
-		}
-		b /= temp;
-		b -= a * a;
-		b = (s32) wlc_phy_sqrt_int((u32) b);
-		b -= (1 << 10);
-
-		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				new_comp.a0 = (s16) a & 0x3ff;
-				new_comp.b0 = (s16) b & 0x3ff;
-			} else {
-
-				new_comp.a0 = (s16) b & 0x3ff;
-				new_comp.b0 = (s16) a & 0x3ff;
-			}
-		}
-		if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				new_comp.a1 = (s16) a & 0x3ff;
-				new_comp.b1 = (s16) b & 0x3ff;
-			} else {
-
-				new_comp.a1 = (s16) b & 0x3ff;
-				new_comp.b1 = (s16) a & 0x3ff;
-			}
-		}
-	}
-
-	if (bcmerror != BCME_OK) {
-		printk("%s: Failed, cnt = %d\n", __func__, cal_retry);
-
-		if (cal_retry < CAL_RETRY_CNT) {
-			cal_retry++;
-			goto cal_try;
-		}
-
-		new_comp = old_comp;
-	} else if (cal_retry > 0) {
-	}
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
-}
-
-static void wlc_phy_rxcal_radio_setup_nphy(phy_info_t *pi, u8 rx_core)
-{
-	u16 offtune_val;
-	u16 bias_g = 0;
-	u16 bias_a = 0;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		if (rx_core == PHY_CORE_0) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
-						0xaf);
-
-			} else {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
-						0x7f);
-			}
-
-		} else {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
-						0xaf);
-
-			} else {
-				pi->tx_rx_cal_radio_saveregs[0] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
-				pi->tx_rx_cal_radio_saveregs[1] =
-				    read_radio_reg(pi,
-						   RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
-
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
-						0x3);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
-						0x7f);
-			}
-		}
-
-	} else {
-		if (rx_core == PHY_CORE_0) {
-			pi->tx_rx_cal_radio_saveregs[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_RXIQCAL_TXMUX |
-					   RADIO_2056_TX1);
-			pi->tx_rx_cal_radio_saveregs[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RXIQCAL_RXMUX |
-					   RADIO_2056_RX0);
-
-			if (pi->pubpi.radiorev >= 5) {
-				pi->tx_rx_cal_radio_saveregs[2] =
-				    read_radio_reg(pi,
-						   RADIO_2056_RX_RXSPARE2 |
-						   RADIO_2056_RX0);
-				pi->tx_rx_cal_radio_saveregs[3] =
-				    read_radio_reg(pi,
-						   RADIO_2056_TX_TXSPARE2 |
-						   RADIO_2056_TX1);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_MASTER
-							   | RADIO_2056_RX0);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX0, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX1, bias_a);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX0, bias_a);
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_TUNE
-							   | RADIO_2056_RX0);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAA_TUNE |
-						      RADIO_2056_RX0, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX1, 0x9);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX0, 0x9);
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_MASTER
-							   | RADIO_2056_RX0);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX0, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX1, bias_g);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX0, bias_g);
-
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_TUNE
-							   | RADIO_2056_RX0);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAG_TUNE |
-						      RADIO_2056_RX0, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX1, 0x6);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX0, 0x6);
-			}
-
-		} else {
-			pi->tx_rx_cal_radio_saveregs[0] =
-			    read_radio_reg(pi,
-					   RADIO_2056_TX_RXIQCAL_TXMUX |
-					   RADIO_2056_TX0);
-			pi->tx_rx_cal_radio_saveregs[1] =
-			    read_radio_reg(pi,
-					   RADIO_2056_RX_RXIQCAL_RXMUX |
-					   RADIO_2056_RX1);
-
-			if (pi->pubpi.radiorev >= 5) {
-				pi->tx_rx_cal_radio_saveregs[2] =
-				    read_radio_reg(pi,
-						   RADIO_2056_RX_RXSPARE2 |
-						   RADIO_2056_RX1);
-				pi->tx_rx_cal_radio_saveregs[3] =
-				    read_radio_reg(pi,
-						   RADIO_2056_TX_TXSPARE2 |
-						   RADIO_2056_TX0);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_MASTER
-							   | RADIO_2056_RX1);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX1, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX0, bias_a);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX1, bias_a);
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAA_TUNE
-							   | RADIO_2056_RX1);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAA_TUNE |
-						      RADIO_2056_RX1, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX0, 0x9);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX1, 0x9);
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_MASTER
-							   | RADIO_2056_RX1);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX1, 0x40);
-
-					write_radio_reg(pi,
-							RADIO_2056_TX_TXSPARE2 |
-							RADIO_2056_TX0, bias_g);
-
-					write_radio_reg(pi,
-							RADIO_2056_RX_RXSPARE2 |
-							RADIO_2056_RX1, bias_g);
-				} else {
-					pi->tx_rx_cal_radio_saveregs[4] =
-					    read_radio_reg(pi,
-							   RADIO_2056_RX_LNAG_TUNE
-							   | RADIO_2056_RX1);
-
-					offtune_val =
-					    (pi->
-					     tx_rx_cal_radio_saveregs[2] & 0xF0)
-					    >> 8;
-					offtune_val =
-					    (offtune_val <= 0x7) ? 0xF : 0;
-
-					mod_radio_reg(pi,
-						      RADIO_2056_RX_LNAG_TUNE |
-						      RADIO_2056_RX1, 0xF0,
-						      (offtune_val << 8));
-				}
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_RXIQCAL_TXMUX |
-						RADIO_2056_TX0, 0x6);
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXIQCAL_RXMUX |
-						RADIO_2056_RX1, 0x6);
-			}
-		}
-	}
-}
-
-static void wlc_phy_rxcal_radio_cleanup_nphy(phy_info_t *pi, u8 rx_core)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		if (rx_core == PHY_CORE_0) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-
-			} else {
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-			}
-
-		} else {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-
-			} else {
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
-						pi->
-						tx_rx_cal_radio_saveregs[0]);
-				write_radio_reg(pi,
-						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
-						pi->
-						tx_rx_cal_radio_saveregs[1]);
-			}
-		}
-
-	} else {
-		if (rx_core == PHY_CORE_0) {
-			write_radio_reg(pi,
-					RADIO_2056_TX_RXIQCAL_TXMUX |
-					RADIO_2056_TX1,
-					pi->tx_rx_cal_radio_saveregs[0]);
-
-			write_radio_reg(pi,
-					RADIO_2056_RX_RXIQCAL_RXMUX |
-					RADIO_2056_RX0,
-					pi->tx_rx_cal_radio_saveregs[1]);
-
-			if (pi->pubpi.radiorev >= 5) {
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXSPARE2 |
-						RADIO_2056_RX0,
-						pi->
-						tx_rx_cal_radio_saveregs[2]);
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TXSPARE2 |
-						RADIO_2056_TX1,
-						pi->
-						tx_rx_cal_radio_saveregs[3]);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_TUNE
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_TUNE
-							| RADIO_2056_RX0,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			}
-
-		} else {
-			write_radio_reg(pi,
-					RADIO_2056_TX_RXIQCAL_TXMUX |
-					RADIO_2056_TX0,
-					pi->tx_rx_cal_radio_saveregs[0]);
-
-			write_radio_reg(pi,
-					RADIO_2056_RX_RXIQCAL_RXMUX |
-					RADIO_2056_RX1,
-					pi->tx_rx_cal_radio_saveregs[1]);
-
-			if (pi->pubpi.radiorev >= 5) {
-				write_radio_reg(pi,
-						RADIO_2056_RX_RXSPARE2 |
-						RADIO_2056_RX1,
-						pi->
-						tx_rx_cal_radio_saveregs[2]);
-
-				write_radio_reg(pi,
-						RADIO_2056_TX_TXSPARE2 |
-						RADIO_2056_TX0,
-						pi->
-						tx_rx_cal_radio_saveregs[3]);
-			}
-
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_MASTER
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAA_TUNE
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			} else {
-				if (pi->pubpi.radiorev >= 5) {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_MASTER
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				} else {
-					write_radio_reg(pi,
-							RADIO_2056_RX_LNAG_TUNE
-							| RADIO_2056_RX1,
-							pi->
-							tx_rx_cal_radio_saveregs
-							[4]);
-				}
-			}
-		}
-	}
-}
-
-static void wlc_phy_rxcal_physetup_nphy(phy_info_t *pi, u8 rx_core)
-{
-	u8 tx_core;
-	u16 rx_antval, tx_antval;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		tx_core = rx_core;
-	} else {
-		tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
-	}
-
-	pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
-	pi->tx_rx_cal_phy_saveregs[1] =
-	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
-	pi->tx_rx_cal_phy_saveregs[2] =
-	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
-	pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
-	pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
-	pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
-	pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d);
-	pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7);
-	pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342);
-		pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343);
-		pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346);
-		pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347);
-	}
-
-	pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
-	pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
-	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (0) << 0);
-
-	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (0) << 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
-
-		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12);
-
-	} else {
-
-		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
-		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
-		mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4);
-		mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8);
-	}
-
-	mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0);
-	mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
-		    (0x1 << 2), (0x1 << 2));
-	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-		mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			    (0x1 << 0) | (0x1 << 1), 0);
-		mod_phy_reg(pi, (rx_core == PHY_CORE_0) ?
-			    0x8f : 0xa5,
-			    (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1));
-	}
-
-	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0,
-					 RADIO_MIMO_CORESEL_CORE1 |
-					 RADIO_MIMO_CORESEL_CORE2);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		if (CHSPEC_IS40(pi->radio_chanspec)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  2, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		} else {
-			wlc_phy_rfctrl_override_nphy_rev7(pi,
-							  (0x1 << 7),
-							  0, 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-						  0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0);
-	}
-
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 0x1, rx_core + 1);
-	} else {
-
-		if (rx_core == PHY_CORE_0) {
-			rx_antval = 0x1;
-			tx_antval = 0x8;
-		} else {
-			rx_antval = 0x4;
-			tx_antval = 0x2;
-		}
-
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 rx_antval, rx_core + 1);
-		wlc_phy_rfctrlintc_override_nphy(pi,
-						 NPHY_RfctrlIntc_override_TRSW,
-						 tx_antval, tx_core + 1);
-	}
-}
-
-static void wlc_phy_rxcal_phycleanup_nphy(phy_info_t *pi, u8 rx_core)
-{
-
-	write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]);
-	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7,
-		      pi->tx_rx_cal_phy_saveregs[1]);
-	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
-		      pi->tx_rx_cal_phy_saveregs[2]);
-	write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]);
-	write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]);
-
-	write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]);
-	write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]);
-	write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]);
-	write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]);
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]);
-		write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]);
-		write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]);
-		write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]);
-	}
-
-	write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
-	write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
-}
-
-static void
-wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rx_core,
-				 u16 *rxgain, u8 cal_type)
-{
-
-	u16 num_samps;
-	phy_iq_est_t est[PHY_CORE_MAX];
-	u8 tx_core;
-	nphy_iq_comp_t save_comp, zero_comp;
-	u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
-	    10000;
-	s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
-	bool gainctrl_done = false;
-	u8 mix_tia_gain = 3;
-	s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
-	s8 curr_gaintbl_index = 3;
-	u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
-	nphy_ipa_txrxgain_t *nphy_rxcal_gaintbl;
-	u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
-	int fine_gain_idx;
-	s8 txpwrindex;
-	u16 nphy_rxcal_txgain[2];
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		tx_core = rx_core;
-	} else {
-		tx_core = 1 - rx_core;
-	}
-
-	num_samps = 1024;
-	desired_log2_pwr = (cal_type == 0) ? 13 : 13;
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp);
-	zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0;
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
-
-	if (CHSPEC_IS5G(pi->radio_chanspec)) {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			mix_tia_gain = 3;
-		} else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-			mix_tia_gain = 4;
-		} else {
-			mix_tia_gain = 6;
-		}
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
-		} else {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
-		}
-	} else {
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
-		} else {
-			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
-		}
-	}
-
-	do {
-
-		hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
-		    0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
-		lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
-		lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
-		lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
-		lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
-		txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_rfctrl_override_1tomany_nphy(pi,
-							     NPHY_REV7_RfctrlOverride_cmd_rxgain,
-							     ((lpf_biq1 << 12) |
-							      (lpf_biq0 << 8) |
-							      (mix_tia_gain <<
-							       4) | (lna2 << 2)
-							      | lna1), 0x3, 0);
-		} else {
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
-						     ((hpvga << 12) |
-						      (lpf_biq1 << 10) |
-						      (lpf_biq0 << 8) |
-						      (mix_tia_gain << 4) |
-						      (lna2 << 2) | lna1), 0x3,
-						     0);
-		}
-
-		pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
-
-		if (txpwrindex == -1) {
-			nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval;
-			nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval;
-			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
-						 2, 0x110, 16,
-						 nphy_rxcal_txgain);
-		} else {
-			wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex,
-						 false);
-		}
-
-		wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ?
-				     NPHY_RXCAL_TONEFREQ_40MHz :
-				     NPHY_RXCAL_TONEFREQ_20MHz,
-				     NPHY_RXCAL_TONEAMP, 0, cal_type, false);
-
-		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
-		i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps;
-		q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps;
-		curr_pwr = i_pwr + q_pwr;
-
-		switch (gainctrl_dirn) {
-		case NPHY_RXCAL_GAIN_INIT:
-			if (curr_pwr > thresh_pwr) {
-				gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN;
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index--;
-			} else {
-				gainctrl_dirn = NPHY_RXCAL_GAIN_UP;
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index++;
-			}
-			break;
-
-		case NPHY_RXCAL_GAIN_UP:
-			if (curr_pwr > thresh_pwr) {
-				gainctrl_done = true;
-				optim_pwr = prev_pwr;
-				optim_gaintbl_index = prev_gaintbl_index;
-			} else {
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index++;
-			}
-			break;
-
-		case NPHY_RXCAL_GAIN_DOWN:
-			if (curr_pwr > thresh_pwr) {
-				prev_gaintbl_index = curr_gaintbl_index;
-				curr_gaintbl_index--;
-			} else {
-				gainctrl_done = true;
-				optim_pwr = curr_pwr;
-				optim_gaintbl_index = curr_gaintbl_index;
-			}
-			break;
-
-		default:
-			ASSERT(0);
-		}
-
-		if ((curr_gaintbl_index < 0) ||
-		    (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) {
-			gainctrl_done = true;
-			optim_pwr = curr_pwr;
-			optim_gaintbl_index = prev_gaintbl_index;
-		} else {
-			prev_pwr = curr_pwr;
-		}
-
-		wlc_phy_stopplayback_nphy(pi);
-	} while (!gainctrl_done);
-
-	hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga;
-	lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1;
-	lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0;
-	lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2;
-	lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1;
-	txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex;
-
-	actual_log2_pwr = wlc_phy_nbits(optim_pwr);
-	delta_pwr = desired_log2_pwr - actual_log2_pwr;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		fine_gain_idx = (int)lpf_biq1 + delta_pwr;
-
-		if (fine_gain_idx + (int)lpf_biq0 > 10) {
-			lpf_biq1 = 10 - lpf_biq0;
-		} else {
-			lpf_biq1 = (u16) max(fine_gain_idx, 0);
-		}
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
-						     ((lpf_biq1 << 12) |
-						      (lpf_biq0 << 8) |
-						      (mix_tia_gain << 4) |
-						      (lna2 << 2) | lna1), 0x3,
-						     0);
-	} else {
-		hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
-					     ((hpvga << 12) | (lpf_biq1 << 10) |
-					      (lpf_biq0 << 8) | (mix_tia_gain <<
-								 4) | (lna2 <<
-								       2) |
-					      lna1), 0x3, 0);
-
-	}
-
-	if (rxgain != NULL) {
-		*rxgain++ = lna1;
-		*rxgain++ = lna2;
-		*rxgain++ = mix_tia_gain;
-		*rxgain++ = lpf_biq0;
-		*rxgain++ = lpf_biq1;
-		*rxgain = hpvga;
-	}
-
-	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp);
-}
-
-static void
-wlc_phy_rxcal_gainctrl_nphy(phy_info_t *pi, u8 rx_core, u16 *rxgain,
-			    u8 cal_type)
-{
-	wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type);
-}
-
-static u8
-wlc_phy_rc_sweep_nphy(phy_info_t *pi, u8 core_idx, u8 loopback_type)
-{
-	u32 target_bws[2] = { 9500, 21000 };
-	u32 ref_tones[2] = { 3000, 6000 };
-	u32 target_bw, ref_tone;
-
-	u32 target_pwr_ratios[2] = { 28606, 18468 };
-	u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0;
-
-	u16 start_rccal_ovr_val = 128;
-	u16 txlpf_rccal_lpc_ovr_val = 128;
-	u16 rxlpf_rccal_hpc_ovr_val = 159;
-
-	u16 orig_txlpf_rccal_lpc_ovr_val;
-	u16 orig_rxlpf_rccal_hpc_ovr_val;
-	u16 radio_addr_offset_rx;
-	u16 radio_addr_offset_tx;
-	u16 orig_dcBypass;
-	u16 orig_RxStrnFilt40Num[6];
-	u16 orig_RxStrnFilt40Den[4];
-	u16 orig_rfctrloverride[2];
-	u16 orig_rfctrlauxreg[2];
-	u16 orig_rfctrlrssiothers;
-	u16 tx_lpf_bw = 4;
-
-	u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 };
-	u16 lpf_hpc = 7, hpvga_hpc = 7;
-
-	s8 rccal_stepsize;
-	u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0;
-	u32 ref_iq_vals = 0, target_iq_vals = 0;
-	u16 num_samps, log_num_samps = 10;
-	phy_iq_est_t est[PHY_CORE_MAX];
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		return 0;
-	}
-
-	num_samps = (1 << log_num_samps);
-
-	if (CHSPEC_IS40(pi->radio_chanspec)) {
-		target_bw = target_bws[1];
-		target_pwr_ratio = target_pwr_ratios[1];
-		ref_tone = ref_tones[1];
-		rx_lpf_bw = rx_lpf_bws[1];
-	} else {
-		target_bw = target_bws[0];
-		target_pwr_ratio = target_pwr_ratios[0];
-		ref_tone = ref_tones[0];
-		rx_lpf_bw = rx_lpf_bws[0];
-	}
-
-	if (core_idx == 0) {
-		radio_addr_offset_rx = RADIO_2056_RX0;
-		radio_addr_offset_tx =
-		    (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
-	} else {
-		radio_addr_offset_rx = RADIO_2056_RX1;
-		radio_addr_offset_tx =
-		    (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
-	}
-
-	orig_txlpf_rccal_lpc_ovr_val =
-	    read_radio_reg(pi,
-			   (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
-	orig_rxlpf_rccal_hpc_ovr_val =
-	    read_radio_reg(pi,
-			   (RADIO_2056_RX_RXLPF_RCCAL_HPC |
-			    radio_addr_offset_rx));
-
-	orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
-
-	orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267);
-	orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268);
-	orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269);
-	orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a);
-	orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b);
-	orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c);
-	orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d);
-	orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e);
-	orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f);
-	orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270);
-
-	orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7);
-	orig_rfctrloverride[1] = read_phy_reg(pi, 0xec);
-	orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8);
-	orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa);
-	orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d);
-
-	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
-			txlpf_rccal_lpc_ovr_val);
-
-	write_radio_reg(pi,
-			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
-			rxlpf_rccal_hpc_ovr_val);
-
-	mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8));
-
-	write_phy_reg(pi, 0x267, 0x02d4);
-	write_phy_reg(pi, 0x268, 0x0000);
-	write_phy_reg(pi, 0x269, 0x0000);
-	write_phy_reg(pi, 0x26a, 0x0000);
-	write_phy_reg(pi, 0x26b, 0x0000);
-	write_phy_reg(pi, 0x26c, 0x02d4);
-	write_phy_reg(pi, 0x26d, 0x0000);
-	write_phy_reg(pi, 0x26e, 0x0000);
-	write_phy_reg(pi, 0x26f, 0x0000);
-	write_phy_reg(pi, 0x270, 0x0000);
-
-	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8));
-	or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15));
-	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9));
-	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10));
-
-	mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8,
-		    (0x7 << 10), (tx_lpf_bw << 10));
-	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
-		    (0x7 << 0), (hpvga_hpc << 0));
-	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
-		    (0x7 << 4), (lpf_hpc << 4));
-	mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d,
-		    (0x7 << 8), (rx_lpf_bw << 8));
-
-	rccal_stepsize = 16;
-	rccal_val = start_rccal_ovr_val + rccal_stepsize;
-
-	while (rccal_stepsize >= 0) {
-		write_radio_reg(pi,
-				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-				 radio_addr_offset_rx), rccal_val);
-
-		if (rccal_stepsize == 16) {
-
-			wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP,
-					     0, 1, false);
-			udelay(2);
-
-			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
-
-			if (core_idx == 0) {
-				ref_iq_vals =
-				    max_t(u32, (est[0].i_pwr +
-					 est[0].q_pwr) >> (log_num_samps + 1),
-					1);
-			} else {
-				ref_iq_vals =
-				    max_t(u32, (est[1].i_pwr +
-					 est[1].q_pwr) >> (log_num_samps + 1),
-					1);
-			}
-
-			wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
-					     0, 1, false);
-			udelay(2);
-		}
-
-		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
-
-		if (core_idx == 0) {
-			target_iq_vals =
-			    (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
-							      1);
-		} else {
-			target_iq_vals =
-			    (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
-							      1);
-		}
-		pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
-
-		if (rccal_stepsize == 0) {
-			rccal_stepsize--;
-		} else if (rccal_stepsize == 1) {
-			last_rccal_val = rccal_val;
-			rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
-			last_pwr_ratio = pwr_ratio;
-			rccal_stepsize--;
-		} else {
-			rccal_stepsize = (rccal_stepsize >> 1);
-			rccal_val += ((pwr_ratio > target_pwr_ratio) ?
-				      rccal_stepsize : (-rccal_stepsize));
-		}
-
-		if (rccal_stepsize == -1) {
-			best_rccal_val =
-			    (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
-			     ABS((int)pwr_ratio -
-				 (int)target_pwr_ratio)) ? last_rccal_val :
-			    rccal_val;
-
-			if (CHSPEC_IS40(pi->radio_chanspec)) {
-				if ((best_rccal_val > 140)
-				    || (best_rccal_val < 135)) {
-					best_rccal_val = 138;
-				}
-			} else {
-				if ((best_rccal_val > 142)
-				    || (best_rccal_val < 137)) {
-					best_rccal_val = 140;
-				}
-			}
-
-			write_radio_reg(pi,
-					(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-					 radio_addr_offset_rx), best_rccal_val);
-		}
-	}
-
-	wlc_phy_stopplayback_nphy(pi);
-
-	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
-			orig_txlpf_rccal_lpc_ovr_val);
-	write_radio_reg(pi,
-			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
-			orig_rxlpf_rccal_hpc_ovr_val);
-
-	mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8));
-
-	write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]);
-	write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]);
-	write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]);
-	write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]);
-	write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]);
-	write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]);
-	write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]);
-	write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]);
-	write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]);
-	write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]);
-
-	write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]);
-	write_phy_reg(pi, 0xec, orig_rfctrloverride[1]);
-	write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]);
-	write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]);
-	write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers);
-
-	pi->nphy_anarxlpf_adjusted = false;
-
-	return best_rccal_val - 0x80;
-}
-
-#define WAIT_FOR_SCOPE	4000
-static int
-wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t target_gain,
-			   u8 cal_type, bool debug)
-{
-	u16 orig_BBConfig;
-	u8 core_no, rx_core;
-	u8 best_rccal[2];
-	u16 gain_save[2];
-	u16 cal_gain[2];
-	nphy_iqcal_params_t cal_params[2];
-	u8 rxcore_state;
-	s8 rxlpf_rccal_hpc, txlpf_rccal_lpc;
-	s8 txlpf_idac;
-	bool phyhang_avoid_state = false;
-	bool skip_rxiqcal = false;
-
-	orig_BBConfig = read_phy_reg(pi, 0x01);
-	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		phyhang_avoid_state = pi->phyhang_avoid;
-		pi->phyhang_avoid = false;
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
-
-	for (core_no = 0; core_no <= 1; core_no++) {
-		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
-					      &cal_params[core_no]);
-		cal_gain[core_no] = cal_params[core_no].cal_gain;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
-
-	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
-
-	for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
-
-		skip_rxiqcal =
-		    ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
-
-		wlc_phy_rxcal_physetup_nphy(pi, rx_core);
-
-		wlc_phy_rxcal_radio_setup_nphy(pi, rx_core);
-
-		if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) {
-
-			wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
-
-			wlc_phy_tx_tone_nphy(pi,
-					     (CHSPEC_IS40(pi->radio_chanspec)) ?
-					     NPHY_RXCAL_TONEFREQ_40MHz :
-					     NPHY_RXCAL_TONEFREQ_20MHz,
-					     NPHY_RXCAL_TONEAMP, 0, cal_type,
-					     false);
-
-			if (debug)
-				mdelay(WAIT_FOR_SCOPE);
-
-			wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1);
-			wlc_phy_stopplayback_nphy(pi);
-		}
-
-		if (((cal_type == 1) || (cal_type == 2))
-		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-			if (rx_core == PHY_CORE_1) {
-
-				if (rxcore_state == 1) {
-					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
-								      *) pi, 3);
-				}
-
-				wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
-							    1);
-
-				best_rccal[rx_core] =
-				    wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
-				pi->nphy_rccal_value = best_rccal[rx_core];
-
-				if (rxcore_state == 1) {
-					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
-								      *) pi,
-								     rxcore_state);
-				}
-			}
-		}
-
-		wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core);
-
-		wlc_phy_rxcal_phycleanup_nphy(pi, rx_core);
-		wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-	}
-
-	if ((cal_type == 1) || (cal_type == 2)) {
-
-		best_rccal[0] = best_rccal[1];
-		write_radio_reg(pi,
-				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
-				 RADIO_2056_RX0), (best_rccal[0] | 0x80));
-
-		for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
-			rxlpf_rccal_hpc =
-			    (((int)best_rccal[rx_core] - 12) >> 1) + 10;
-			txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
-
-			if (PHY_IPA(pi)) {
-				txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
-				txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
-						 TXLPF_IDAC_4, txlpf_idac);
-			}
-
-			rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
-			txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
-
-			write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
-					     ((rx_core ==
-					       PHY_CORE_0) ? RADIO_2056_RX0 :
-					      RADIO_2056_RX1)),
-					(rxlpf_rccal_hpc | 0x80));
-
-			write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL |
-					     ((rx_core ==
-					       PHY_CORE_0) ? RADIO_2056_TX0 :
-					      RADIO_2056_TX1)),
-					(txlpf_rccal_lpc | 0x80));
-		}
-	}
-
-	write_phy_reg(pi, 0x01, orig_BBConfig);
-
-	wlc_phy_resetcca_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
-						     0, 0x3, 1);
-	} else {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
-	}
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 gain_save);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
-		pi->phyhang_avoid = phyhang_avoid_state;
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	return BCME_OK;
-}
-
-static int
-wlc_phy_cal_rxiq_nphy_rev2(phy_info_t *pi, nphy_txgains_t target_gain,
-			   bool debug)
-{
-	phy_iq_est_t est[PHY_CORE_MAX];
-	u8 core_num, rx_core, tx_core;
-	u16 lna_vals[] = { 0x3, 0x3, 0x1 };
-	u16 hpf1_vals[] = { 0x7, 0x2, 0x0 };
-	u16 hpf2_vals[] = { 0x2, 0x0, 0x0 };
-	s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna;
-	s16 desired_log2_pwr, actual_log2_pwr, hpf_change;
-	u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride;
-	u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx;
-	u16 num_samps;
-	u32 i_pwr, q_pwr, tot_pwr[3];
-	u8 gain_pass, use_hpf_num;
-	u16 mask, val1, val2;
-	u16 core_no;
-	u16 gain_save[2];
-	u16 cal_gain[2];
-	nphy_iqcal_params_t cal_params[2];
-	u8 phy_bw;
-	int bcmerror = BCME_OK;
-	bool first_playtone = true;
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-		wlc_phy_reapply_txcal_coeffs_nphy(pi);
-	}
-
-	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
-
-	for (core_no = 0; core_no <= 1; core_no++) {
-		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
-					      &cal_params[core_no]);
-		cal_gain[core_no] = cal_params[core_no].cal_gain;
-	}
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
-
-	num_samps = 1024;
-	desired_log2_pwr = 13;
-
-	for (core_num = 0; core_num < 2; core_num++) {
-
-		rx_core = core_num;
-		tx_core = 1 - core_num;
-
-		orig_RfseqCoreActv = read_phy_reg(pi, 0xa2);
-		orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
-						0xa6 : 0xa7);
-		orig_AfectrlOverride = read_phy_reg(pi, 0xa5);
-		orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
-						 0x91 : 0x92);
-		orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ?
-						 0x91 : 0x92);
-
-		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
-		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
-
-		or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			   ((0x1 << 1) | (0x1 << 2)));
-		or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
-
-		if (((pi->nphy_rxcalparams) & 0xff000000)) {
-
-			write_phy_reg(pi,
-				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
-				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
-				       0x110));
-		} else {
-
-			write_phy_reg(pi,
-				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
-				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
-				       0x120));
-		}
-
-		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
-			      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
-			       0x114));
-
-		mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK;
-		if (rx_core == PHY_CORE_0) {
-			val1 = RADIO_2055_COUPLE_RX_MASK;
-			val2 = RADIO_2055_COUPLE_TX_MASK;
-		} else {
-			val1 = RADIO_2055_COUPLE_TX_MASK;
-			val2 = RADIO_2055_COUPLE_RX_MASK;
-		}
-
-		if ((pi->nphy_rxcalparams & 0x10000)) {
-			mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask,
-				      val1);
-			mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask,
-				      val2);
-		}
-
-		for (gain_pass = 0; gain_pass < 4; gain_pass++) {
-
-			if (debug)
-				mdelay(WAIT_FOR_SCOPE);
-
-			if (gain_pass < 3) {
-				curr_lna = lna_vals[gain_pass];
-				curr_hpf1 = hpf1_vals[gain_pass];
-				curr_hpf2 = hpf2_vals[gain_pass];
-			} else {
-
-				if (tot_pwr[1] > 10000) {
-					curr_lna = lna_vals[2];
-					curr_hpf1 = hpf1_vals[2];
-					curr_hpf2 = hpf2_vals[2];
-					use_hpf_num = 1;
-					curr_hpf = curr_hpf1;
-					actual_log2_pwr =
-					    wlc_phy_nbits(tot_pwr[2]);
-				} else {
-					if (tot_pwr[0] > 10000) {
-						curr_lna = lna_vals[1];
-						curr_hpf1 = hpf1_vals[1];
-						curr_hpf2 = hpf2_vals[1];
-						use_hpf_num = 1;
-						curr_hpf = curr_hpf1;
-						actual_log2_pwr =
-						    wlc_phy_nbits(tot_pwr[1]);
-					} else {
-						curr_lna = lna_vals[0];
-						curr_hpf1 = hpf1_vals[0];
-						curr_hpf2 = hpf2_vals[0];
-						use_hpf_num = 2;
-						curr_hpf = curr_hpf2;
-						actual_log2_pwr =
-						    wlc_phy_nbits(tot_pwr[0]);
-					}
-				}
-
-				hpf_change = desired_log2_pwr - actual_log2_pwr;
-				curr_hpf += hpf_change;
-				curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
-				if (use_hpf_num == 1) {
-					curr_hpf1 = curr_hpf;
-				} else {
-					curr_hpf2 = curr_hpf;
-				}
-			}
-
-			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
-						     ((curr_hpf2 << 8) |
-						      (curr_hpf1 << 4) |
-						      (curr_lna << 2)), 0x3, 0);
-			wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-			wlc_phy_stopplayback_nphy(pi);
-
-			if (first_playtone) {
-				bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
-								(u16) (pi->
-									  nphy_rxcalparams
-									  &
-									  0xffff),
-								0, 0, true);
-				first_playtone = false;
-			} else {
-				phy_bw =
-				    (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
-				wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
-							0, 0, 0, true);
-			}
-
-			if (bcmerror == BCME_OK) {
-				if (gain_pass < 3) {
-
-					wlc_phy_rx_iq_est_nphy(pi, est,
-							       num_samps, 32,
-							       0);
-					i_pwr =
-					    (est[rx_core].i_pwr +
-					     num_samps / 2) / num_samps;
-					q_pwr =
-					    (est[rx_core].q_pwr +
-					     num_samps / 2) / num_samps;
-					tot_pwr[gain_pass] = i_pwr + q_pwr;
-				} else {
-
-					wlc_phy_calc_rx_iq_comp_nphy(pi,
-								     (1 <<
-								      rx_core));
-				}
-
-				wlc_phy_stopplayback_nphy(pi);
-			}
-
-			if (bcmerror != BCME_OK)
-				break;
-		}
-
-		and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask);
-		and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask);
-
-		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 :
-			      0x92, orig_RfctrlIntcTx);
-		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 :
-			      0x92, orig_RfctrlIntcRx);
-		write_phy_reg(pi, 0xa5, orig_AfectrlOverride);
-		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 :
-			      0xa7, orig_AfectrlCore);
-		write_phy_reg(pi, 0xa2, orig_RfseqCoreActv);
-
-		if (bcmerror != BCME_OK)
-			break;
-	}
-
-	wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1);
-	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
-				 gain_save);
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	return bcmerror;
-}
-
-int
-wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
-		      u8 cal_type, bool debug)
-{
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		cal_type = 0;
-	}
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
-						  debug);
-	} else {
-		return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
-	}
-}
-
-static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi)
-{
-	int j, type = 2;
-	u16 addr_offset = 0x2c5;
-
-	for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-		write_phy_reg(pi, addr_offset + j,
-			      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
-	}
-}
-
-static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi)
-{
-	int j, type;
-	u16 addr_offset[] = { 0x186, 0x195,
-		0x2c5
-	};
-
-	for (type = 0; type < 3; type++) {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, addr_offset[type] + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
-		}
-	}
-
-	if (IS40MHZ(pi)) {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, 0x186 + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
-		}
-	} else {
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, 0x186 + j,
-					      NPHY_IPA_REV4_txdigi_filtcoeffs[5]
-					      [j]);
-			}
-		}
-
-		if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
-			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-				write_phy_reg(pi, 0x2c5 + j,
-					      NPHY_IPA_REV4_txdigi_filtcoeffs[6]
-					      [j]);
-			}
-		}
-	}
-}
-
-static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi)
-{
-	int j;
-
-	if (IS40MHZ(pi)) {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, 0x195 + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
-		}
-	} else {
-		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
-			write_phy_reg(pi, 0x186 + j,
-				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
-		}
-	}
-}
-
-static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi)
-{
-	u16 m0m1;
-
-	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
-
-	return m0m1;
-}
-
-static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1)
-{
-	u16 m0m1 = (u16) ((m0 << 8) | m1);
-
-	wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
-	wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
-}
-
-static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi)
-{
-	u32 *tx_pwrctrl_tbl = NULL;
-
-	if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-			if ((pi->pubpi.radiorev == 4)
-			    || (pi->pubpi.radiorev == 6)) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev4n6;
-			} else if (pi->pubpi.radiorev == 3) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev3;
-			} else if (pi->pubpi.radiorev == 5) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev5;
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_2g_2057rev7;
-			} else {
-				ASSERT(0);
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
-
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
-			if (pi->sh->chip == BCM47162_CHIP_ID) {
-
-				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
-			}
-
-		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
-
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
-		} else {
-
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
-		}
-
-	} else {
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if ((pi->pubpi.radiorev == 3) ||
-			    (pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				tx_pwrctrl_tbl =
-				    nphy_tpc_txgain_ipa_5g_2057rev7;
-			} else {
-				ASSERT(0);
-			}
-
-		} else {
-			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
-		}
-	}
-
-	return tx_pwrctrl_tbl;
-}
-
-static void
-wlc_phy_papd_cal_setup_nphy(phy_info_t *pi, nphy_papd_restore_state *state,
-			    u8 core)
-{
-	s32 tone_freq;
-	u8 off_core;
-	u16 mixgain = 0;
-
-	off_core = core ^ 0x1;
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
-							  wlc_phy_read_lpf_bw_ctl_nphy
-							  (pi, 0), 0, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if (pi->pubpi.radiorev == 5) {
-				mixgain = (core == 0) ? 0x20 : 0x00;
-
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				mixgain = 0x00;
-
-			} else if ((pi->pubpi.radiorev <= 4)
-				   || (pi->pubpi.radiorev == 6)) {
-
-				mixgain = 0x00;
-			} else {
-				ASSERT(0);
-			}
-
-		} else {
-			if ((pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				mixgain = 0x50;
-			} else if ((pi->pubpi.radiorev == 3)
-				   || (pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				mixgain = 0x0;
-			} else {
-				ASSERT(0);
-			}
-		}
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
-						  mixgain, (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
-						     1, (1 << core), 0);
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
-						     0, (1 << off_core), 0);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, 0x3, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
-						  0, (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
-						  (1 << core), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
-						    0xa6 : 0xa7);
-		state->afeoverride[core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
-		state->afectrl[off_core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
-		state->afeoverride[off_core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
-
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			    (0x1 << 2), 0);
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-				 0xa5), (0x1 << 2), (0x1 << 2));
-
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
-			    (0x1 << 2), (0x1 << 2));
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
-				 0x8f), (0x1 << 2), (0x1 << 2));
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			state->pwrup[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_2G_PWRUP);
-			state->atten[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_2G_ATTEN);
-			state->pwrup[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_2G_PWRUP);
-			state->atten[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_2G_ATTEN);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-					 TXRXCOUPLE_2G_PWRUP, 0xc);
-
-			if ((pi->pubpi.radiorev == 3) ||
-			    (pi->pubpi.radiorev == 4) ||
-			    (pi->pubpi.radiorev == 6)) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN, 0xf0);
-
-			} else if (pi->pubpi.radiorev == 5) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN,
-						 (core == 0) ? 0xf7 : 0xf2);
-
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN, 0xf0);
-
-			} else {
-				ASSERT(0);
-			}
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_2G_PWRUP, 0x0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_2G_ATTEN, 0xff);
-
-		} else {
-			state->pwrup[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_5G_PWRUP);
-			state->atten[core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
-					    TXRXCOUPLE_5G_ATTEN);
-			state->pwrup[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_5G_PWRUP);
-			state->atten[off_core] =
-			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					    TXRXCOUPLE_5G_ATTEN);
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-					 TXRXCOUPLE_5G_PWRUP, 0xc);
-
-			if ((pi->pubpi.radiorev == 7)
-			    || (pi->pubpi.radiorev == 8)) {
-
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_ATTEN, 0xf4);
-
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_ATTEN, 0xf0);
-			}
-
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_5G_PWRUP, 0x0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
-					 TXRXCOUPLE_5G_ATTEN, 0xff);
-		}
-
-		tone_freq = 4000;
-
-		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (1) << 13);
-
-		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
-
-		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-	} else {
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
-
-		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
-						    0xa6 : 0xa7);
-		state->afeoverride[core] =
-		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
-
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
-			    (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
-		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-				 0xa5),
-			    (0x1 << 0) |
-			    (0x1 << 1) |
-			    (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
-
-		state->vga_master[core] =
-		    READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
-		WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			state->fbmix[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
-					    TXFBMIX_G);
-			state->intpa_master[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
-					    INTPAG_MASTER);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
-					 0x03);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAG_MASTER, 0x04);
-		} else {
-			state->fbmix[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
-					    TXFBMIX_A);
-			state->intpa_master[core] =
-			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
-					    INTPAA_MASTER);
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
-					 0x03);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-					 INTPAA_MASTER, 0x04);
-
-		}
-
-		tone_freq = 4000;
-
-		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (1) << 0);
-
-		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
-	}
-}
-
-static void
-wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi, nphy_papd_restore_state *state)
-{
-	u8 core;
-
-	wlc_phy_stopplayback_nphy(pi);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_PWRUP, 0);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_2G_ATTEN,
-						 state->atten[core]);
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_PWRUP, 0);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TXRXCOUPLE_5G_ATTEN,
-						 state->atten[core]);
-			}
-		}
-
-		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  1, 0x3, 0,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		} else {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
-							  0, 0x3, 1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		}
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
-						  0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xa6 : 0xa7, state->afectrl[core]);
-			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
-				      0xa5, state->afeoverride[core]);
-		}
-
-		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
-					    (state->mm & 0xff));
-
-		if (NREV_IS(pi->pubpi.phy_rev, 7)
-		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
-			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
-							  1,
-							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
-		}
-	} else {
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
-					 state->vga_master[core]);
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
-						 TXFBMIX_G, state->fbmix[core]);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAG_MASTER,
-						 state->intpa_master[core]);
-			} else {
-				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
-						 TXFBMIX_A, state->fbmix[core]);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 INTPAA_MASTER,
-						 state->intpa_master[core]);
-			}
-
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xa6 : 0xa7, state->afectrl[core]);
-			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
-				      0xa5, state->afeoverride[core]);
-		}
-
-		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
-					    (state->mm & 0xff));
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
-	}
-}
-
-static void
-wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32 start,
-		u32 end)
-{
-	u32 *buf, *src, *dst, sz;
-
-	sz = end - start + 1;
-	ASSERT(end > start);
-	ASSERT(end < NPHY_PAPD_EPS_TBL_SIZE);
-
-	buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
-	if (NULL == buf) {
-		return;
-	}
-
-	src = buf;
-	dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
-
-	wlc_phy_table_read_nphy(pi,
-				(core ==
-				 PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
-				 NPHY_TBL_ID_EPSILONTBL1),
-				NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
-
-	do {
-		u32 phy_a1, phy_a2;
-		s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
-
-		phy_a1 = end - min(end, (winsz >> 1));
-		phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
-		phy_a3 = phy_a2 - phy_a1 + 1;
-		phy_a6 = 0;
-		phy_a7 = 0;
-
-		do {
-			wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
-						    &phy_a5);
-			phy_a6 += phy_a4;
-			phy_a7 += phy_a5;
-		} while (phy_a2-- != phy_a1);
-
-		phy_a6 /= phy_a3;
-		phy_a7 /= phy_a3;
-		dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
-	} while (end-- != start);
-
-	wlc_phy_table_write_nphy(pi,
-				 (core ==
-				  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
-				 NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
-
-	kfree(buf);
-}
-
-static void
-wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *txgains,
-		phy_cal_mode_t cal_mode, u8 core)
-{
-	u16 phy_a1, phy_a2, phy_a3;
-	u16 phy_a4, phy_a5;
-	bool phy_a6;
-	u8 phy_a7, m[2];
-	u32 phy_a8 = 0;
-	nphy_txgains_t phy_a9;
-
-	if (NREV_LT(pi->pubpi.phy_rev, 3))
-		return;
-
-	phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
-
-	ASSERT((cal_mode == CAL_FULL) || (cal_mode == CAL_GCTRL)
-	       || (cal_mode == CAL_SOFT));
-	phy_a6 = ((cal_mode == CAL_GCTRL)
-		  || (cal_mode == CAL_SOFT)) ? true : false;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			phy_a5 = ((phy_a9.txlpf[core] << 15) |
-				  (phy_a9.txgm[core] << 12) |
-				  (phy_a9.pga[core] << 8) |
-				  (txgains->gains.pad[core] << 3) |
-				  (phy_a9.ipa[core]));
-		} else {
-			phy_a5 = ((phy_a9.txlpf[core] << 15) |
-				  (phy_a9.txgm[core] << 12) |
-				  (txgains->gains.pga[core] << 8) |
-				  (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
-		}
-
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_txgain,
-						     phy_a5, (1 << core), 0);
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if ((pi->pubpi.radiorev <= 4)
-			    || (pi->pubpi.radiorev == 6)) {
-
-				m[core] = IS40MHZ(pi) ? 60 : 79;
-			} else {
-
-				m[core] = IS40MHZ(pi) ? 45 : 64;
-			}
-
-		} else {
-			m[core] = IS40MHZ(pi) ? 75 : 107;
-		}
-
-		m[phy_a7] = 0;
-		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
-		phy_a2 = 63;
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if (pi->sh->chip == BCM6362_CHIP_ID) {
-				phy_a1 = 35;
-				phy_a3 = 35;
-			} else if ((pi->pubpi.radiorev == 4)
-				   || (pi->pubpi.radiorev == 6)) {
-				phy_a1 = 30;
-				phy_a3 = 30;
-			} else {
-				phy_a1 = 25;
-				phy_a3 = 25;
-			}
-		} else {
-			if ((pi->pubpi.radiorev == 5)
-			    || (pi->pubpi.radiorev == 7)
-			    || (pi->pubpi.radiorev == 8)) {
-				phy_a1 = 25;
-				phy_a3 = 25;
-			} else {
-				phy_a1 = 35;
-				phy_a3 = 35;
-			}
-		}
-
-		if (cal_mode == CAL_GCTRL) {
-			if ((pi->pubpi.radiorev == 5)
-			    && (CHSPEC_IS2G(pi->radio_chanspec))) {
-				phy_a1 = 55;
-			} else if (((pi->pubpi.radiorev == 7) &&
-				    (CHSPEC_IS2G(pi->radio_chanspec))) ||
-				   ((pi->pubpi.radiorev == 8) &&
-				    (CHSPEC_IS2G(pi->radio_chanspec)))) {
-				phy_a1 = 60;
-			} else {
-				phy_a1 = 63;
-			}
-
-		} else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
-
-			phy_a1 = 35;
-			phy_a3 = 35;
-		}
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (1) << 0);
-
-		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (1) << 13);
-
-		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-		write_phy_reg(pi, 0x2a1, 0x80);
-		write_phy_reg(pi, 0x2a2, 0x100);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x7 << 4), (11) << 4);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x7 << 8), (11) << 8);
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x7 << 0), (0x3) << 0);
-
-		write_phy_reg(pi, 0x2e5, 0x20);
-
-		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  1, ((core == 0) ? 1 : 2), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, ((core == 0) ? 2 : 1), 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
-		write_phy_reg(pi, 0x2be, 1);
-		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
-						  0, 0x3, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-
-		wlc_phy_table_write_nphy(pi,
-					 (core ==
-					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
-					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
-					 32, &phy_a8);
-
-		if (cal_mode != CAL_GCTRL) {
-			if (CHSPEC_IS5G(pi->radio_chanspec)) {
-				wlc_phy_a1_nphy(pi, core, 5, 0, 35);
-			}
-		}
-
-		wlc_phy_rfctrl_override_1tomany_nphy(pi,
-						     NPHY_REV7_RfctrlOverride_cmd_txgain,
-						     phy_a5, (1 << core), 1);
-
-	} else {
-
-		if (txgains) {
-			if (txgains->useindex) {
-				phy_a4 = 15 - ((txgains->index) >> 3);
-				if (CHSPEC_IS2G(pi->radio_chanspec)) {
-					if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-						phy_a5 = 0x00f7 | (phy_a4 << 8);
-
-						if (pi->sh->chip ==
-						    BCM47162_CHIP_ID) {
-							phy_a5 =
-							    0x10f7 | (phy_a4 <<
-								      8);
-						}
-					} else
-					    if (NREV_IS(pi->pubpi.phy_rev, 5))
-						phy_a5 = 0x10f7 | (phy_a4 << 8);
-					else
-						phy_a5 = 0x50f7 | (phy_a4 << 8);
-				} else {
-					phy_a5 = 0x70f7 | (phy_a4 << 8);
-				}
-				wlc_phy_rfctrl_override_nphy(pi,
-							     (0x1 << 13),
-							     phy_a5,
-							     (1 << core), 0);
-			} else {
-				wlc_phy_rfctrl_override_nphy(pi,
-							     (0x1 << 13),
-							     0x5bf7,
-							     (1 << core), 0);
-			}
-		}
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			m[core] = IS40MHZ(pi) ? 45 : 64;
-		} else {
-			m[core] = IS40MHZ(pi) ? 75 : 107;
-		}
-
-		m[phy_a7] = 0;
-		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
-
-		phy_a2 = 63;
-
-		if (cal_mode == CAL_FULL) {
-			phy_a1 = 25;
-			phy_a3 = 25;
-		} else if (cal_mode == CAL_SOFT) {
-			phy_a1 = 25;
-			phy_a3 = 25;
-		} else if (cal_mode == CAL_GCTRL) {
-			phy_a1 = 63;
-			phy_a3 = 25;
-		} else {
-
-			phy_a1 = 25;
-			phy_a3 = 25;
-		}
-
-		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (1) << 0);
-
-		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
-			    0x29b, (0x1 << 0), (0) << 0);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 13), (1) << 13);
-
-			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 13), (0) << 13);
-
-			write_phy_reg(pi, 0x2a1, 0x20);
-			write_phy_reg(pi, 0x2a2, 0x60);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0xf << 4), (9) << 4);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0xf << 8), (9) << 8);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0xf << 0), (0x2) << 0);
-
-			write_phy_reg(pi, 0x2e5, 0x20);
-		} else {
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 11), (1) << 11);
-
-			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x1 << 11), (0) << 11);
-
-			write_phy_reg(pi, 0x2a1, 0x80);
-			write_phy_reg(pi, 0x2a2, 0x600);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x7 << 4), (0) << 4);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x7 << 8), (0) << 8);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
-				    0x2a4, (0x7 << 0), (0x3) << 0);
-
-			mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
-
-		}
-
-		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
-
-		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
-
-		write_phy_reg(pi, 0x2be, 1);
-		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
-
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
-
-		wlc_phy_table_write_nphy(pi,
-					 (core ==
-					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
-					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
-					 32, &phy_a8);
-
-		if (cal_mode != CAL_GCTRL) {
-			wlc_phy_a1_nphy(pi, core, 5, 0, 40);
-		}
-	}
-}
-
-static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core)
-{
-	int phy_a1;
-	int phy_a2;
-	bool phy_a3;
-	nphy_ipa_txcalgains_t phy_a4;
-	bool phy_a5 = false;
-	bool phy_a6 = true;
-	s32 phy_a7, phy_a8;
-	u32 phy_a9;
-	int phy_a10;
-	bool phy_a11 = false;
-	int phy_a12;
-	u8 phy_a13 = 0;
-	u8 phy_a14;
-	u8 *phy_a15 = NULL;
-
-	phy_a4.useindex = true;
-	phy_a12 = start_gain;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-
-		phy_a2 = 20;
-		phy_a1 = 1;
-
-		if (CHSPEC_IS2G(pi->radio_chanspec)) {
-			if (pi->pubpi.radiorev == 5) {
-
-				phy_a15 = pad_gain_codes_used_2057rev5;
-				phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
-				    sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
-
-			} else if ((pi->pubpi.radiorev == 7)
-				   || (pi->pubpi.radiorev == 8)) {
-
-				phy_a15 = pad_gain_codes_used_2057rev7;
-				phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
-				    sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
-
-			} else {
-
-				phy_a15 = pad_all_gain_codes_2057;
-				phy_a13 = sizeof(pad_all_gain_codes_2057) /
-				    sizeof(pad_all_gain_codes_2057[0]) - 1;
-			}
-
-		} else {
-
-			phy_a15 = pga_all_gain_codes_2057;
-			phy_a13 = sizeof(pga_all_gain_codes_2057) /
-			    sizeof(pga_all_gain_codes_2057[0]) - 1;
-		}
-
-		phy_a14 = 0;
-
-		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_a4.gains.pad[core] =
-				    (u16) phy_a15[phy_a12];
-			} else {
-				phy_a4.gains.pga[core] =
-				    (u16) phy_a15[phy_a12];
-			}
-
-			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
-			wlc_phy_table_read_nphy(pi,
-						(core ==
-						 PHY_CORE_0 ?
-						 NPHY_TBL_ID_EPSILONTBL0 :
-						 NPHY_TBL_ID_EPSILONTBL1), 1,
-						63, 32, &phy_a9);
-
-			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
-			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
-				  (phy_a8 == 4095) || (phy_a8 == -4096));
-
-			if (!phy_a6 && (phy_a3 != phy_a5)) {
-				if (!phy_a3) {
-					phy_a12 -= (u8) phy_a1;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			if (phy_a3)
-				phy_a12 += (u8) phy_a1;
-			else
-				phy_a12 -= (u8) phy_a1;
-
-			if ((phy_a12 < phy_a14) || (phy_a12 > phy_a13)) {
-				if (phy_a12 < phy_a14) {
-					phy_a12 = phy_a14;
-				} else {
-					phy_a12 = phy_a13;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			phy_a6 = false;
-			phy_a5 = phy_a3;
-		}
-
-	} else {
-		phy_a2 = 10;
-		phy_a1 = 8;
-		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
-			phy_a4.index = (u8) phy_a12;
-			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
-
-			wlc_phy_table_read_nphy(pi,
-						(core ==
-						 PHY_CORE_0 ?
-						 NPHY_TBL_ID_EPSILONTBL0 :
-						 NPHY_TBL_ID_EPSILONTBL1), 1,
-						63, 32, &phy_a9);
-
-			wlc_phy_papd_decode_epsilon(phy_a9, &phy_a7, &phy_a8);
-
-			phy_a3 = ((phy_a7 == 4095) || (phy_a7 == -4096) ||
-				  (phy_a8 == 4095) || (phy_a8 == -4096));
-
-			if (!phy_a6 && (phy_a3 != phy_a5)) {
-				if (!phy_a3) {
-					phy_a12 -= (u8) phy_a1;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			if (phy_a3)
-				phy_a12 += (u8) phy_a1;
-			else
-				phy_a12 -= (u8) phy_a1;
-
-			if ((phy_a12 < 0) || (phy_a12 > 127)) {
-				if (phy_a12 < 0) {
-					phy_a12 = 0;
-				} else {
-					phy_a12 = 127;
-				}
-				phy_a11 = true;
-				break;
-			}
-
-			phy_a6 = false;
-			phy_a5 = phy_a3;
-		}
-
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		return (u8) phy_a15[phy_a12];
-	} else {
-		return (u8) phy_a12;
-	}
-
-}
-
-static void wlc_phy_a4(phy_info_t *pi, bool full_cal)
-{
-	nphy_ipa_txcalgains_t phy_b1[2];
-	nphy_papd_restore_state phy_b2;
-	bool phy_b3;
-	u8 phy_b4;
-	u8 phy_b5;
-	s16 phy_b6, phy_b7, phy_b8;
-	u16 phy_b9;
-	s16 phy_b10, phy_b11, phy_b12;
-
-	phy_b11 = 0;
-	phy_b12 = 0;
-	phy_b7 = 0;
-	phy_b8 = 0;
-	phy_b6 = 0;
-
-	if (pi->nphy_papd_skip == 1)
-		return;
-
-	phy_b3 =
-	    (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-	if (!phy_b3) {
-		wlapi_suspend_mac_and_wait(pi->sh->physhim);
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	pi->nphy_force_papd_cal = false;
-
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++)
-		pi->nphy_papd_tx_gain_at_last_cal[phy_b5] =
-		    wlc_phy_txpwr_idx_cur_get_nphy(pi, phy_b5);
-
-	pi->nphy_papd_last_cal = pi->sh->now;
-	pi->nphy_papd_recal_counter++;
-
-	if (NORADIO_ENAB(pi->pubpi))
-		return;
-
-	phy_b4 = pi->nphy_txpwrctrl;
-	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL0, 64, 0, 32,
-				 nphy_papd_scaltbl);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SCALARTBL1, 64, 0, 32,
-				 nphy_papd_scaltbl);
-
-	phy_b9 = read_phy_reg(pi, 0x01);
-	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
-
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
-		s32 i, val = 0;
-		for (i = 0; i < 64; i++) {
-			wlc_phy_table_write_nphy(pi,
-						 ((phy_b5 ==
-						   PHY_CORE_0) ?
-						  NPHY_TBL_ID_EPSILONTBL0 :
-						  NPHY_TBL_ID_EPSILONTBL1), 1,
-						 i, 32, &val);
-		}
-	}
-
-	wlc_phy_ipa_restore_tx_digi_filts_nphy(pi);
-
-	phy_b2.mm = wlc_phy_ipa_get_bbmult_nphy(pi);
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
-		wlc_phy_papd_cal_setup_nphy(pi, &phy_b2, phy_b5);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-
-				if ((pi->pubpi.radiorev == 3)
-				    || (pi->pubpi.radiorev == 4)
-				    || (pi->pubpi.radiorev == 6)) {
-
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    23;
-
-				} else if (pi->pubpi.radiorev == 5) {
-
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    0;
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    wlc_phy_a3_nphy(pi,
-							    pi->
-							    nphy_papd_cal_gain_index
-							    [phy_b5], phy_b5);
-
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    0;
-					pi->nphy_papd_cal_gain_index[phy_b5] =
-					    wlc_phy_a3_nphy(pi,
-							    pi->
-							    nphy_papd_cal_gain_index
-							    [phy_b5], phy_b5);
-
-				} else {
-					ASSERT(0);
-				}
-
-				phy_b1[phy_b5].gains.pad[phy_b5] =
-				    pi->nphy_papd_cal_gain_index[phy_b5];
-
-			} else {
-				pi->nphy_papd_cal_gain_index[phy_b5] = 0;
-				pi->nphy_papd_cal_gain_index[phy_b5] =
-				    wlc_phy_a3_nphy(pi,
-						    pi->
-						    nphy_papd_cal_gain_index
-						    [phy_b5], phy_b5);
-				phy_b1[phy_b5].gains.pga[phy_b5] =
-				    pi->nphy_papd_cal_gain_index[phy_b5];
-			}
-		} else {
-			phy_b1[phy_b5].useindex = true;
-			phy_b1[phy_b5].index = 16;
-			phy_b1[phy_b5].index =
-			    wlc_phy_a3_nphy(pi, phy_b1[phy_b5].index, phy_b5);
-
-			pi->nphy_papd_cal_gain_index[phy_b5] =
-			    15 - ((phy_b1[phy_b5].index) >> 3);
-		}
-
-		switch (pi->nphy_papd_cal_type) {
-		case 0:
-			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_FULL, phy_b5);
-			break;
-		case 1:
-			wlc_phy_a2_nphy(pi, &phy_b1[phy_b5], CAL_SOFT, phy_b5);
-			break;
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
-		}
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_papd_cal_cleanup_nphy(pi, &phy_b2);
-	}
-
-	for (phy_b5 = 0; phy_b5 < pi->pubpi.phy_corenum; phy_b5++) {
-		int eps_offset = 0;
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				if (pi->pubpi.radiorev == 3) {
-					eps_offset = -2;
-				} else if (pi->pubpi.radiorev == 5) {
-					eps_offset = 3;
-				} else {
-					eps_offset = -1;
-				}
-			} else {
-				eps_offset = 2;
-			}
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_b8 = phy_b1[phy_b5].gains.pad[phy_b5];
-				phy_b10 = 0;
-				if ((pi->pubpi.radiorev == 3) ||
-				    (pi->pubpi.radiorev == 4) ||
-				    (pi->pubpi.radiorev == 6)) {
-					phy_b12 =
-					    -
-					    (nphy_papd_padgain_dlt_2g_2057rev3n4
-					     [phy_b8]
-					     + 1) / 2;
-					phy_b10 = -1;
-				} else if (pi->pubpi.radiorev == 5) {
-					phy_b12 =
-					    -(nphy_papd_padgain_dlt_2g_2057rev5
-					      [phy_b8]
-					      + 1) / 2;
-				} else if ((pi->pubpi.radiorev == 7) ||
-					   (pi->pubpi.radiorev == 8)) {
-					phy_b12 =
-					    -(nphy_papd_padgain_dlt_2g_2057rev7
-					      [phy_b8]
-					      + 1) / 2;
-				} else {
-					ASSERT(0);
-				}
-			} else {
-				phy_b7 = phy_b1[phy_b5].gains.pga[phy_b5];
-				if ((pi->pubpi.radiorev == 3) ||
-				    (pi->pubpi.radiorev == 4) ||
-				    (pi->pubpi.radiorev == 6)) {
-					phy_b11 =
-					    -(nphy_papd_pgagain_dlt_5g_2057
-					      [phy_b7]
-					      + 1) / 2;
-				} else if ((pi->pubpi.radiorev == 7)
-					   || (pi->pubpi.radiorev == 8)) {
-					phy_b11 =
-					    -(nphy_papd_pgagain_dlt_5g_2057rev7
-					      [phy_b7]
-					      + 1) / 2;
-				} else {
-					ASSERT(0);
-				}
-
-				phy_b10 = -9;
-			}
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_b6 =
-				    -60 + 27 + eps_offset + phy_b12 + phy_b10;
-			} else {
-				phy_b6 =
-				    -60 + 27 + eps_offset + phy_b11 + phy_b10;
-			}
-
-			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
-				    0x29c, (0x1ff << 7), (phy_b6) << 7);
-
-			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
-		} else {
-			if (NREV_LT(pi->pubpi.phy_rev, 5)) {
-				eps_offset = 4;
-			} else {
-				eps_offset = 2;
-			}
-
-			phy_b7 = 15 - ((phy_b1[phy_b5].index) >> 3);
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				phy_b11 =
-				    -(nphy_papd_pga_gain_delta_ipa_2g[phy_b7] +
-				      1) / 2;
-				phy_b10 = 0;
-			} else {
-				phy_b11 =
-				    -(nphy_papd_pga_gain_delta_ipa_5g[phy_b7] +
-				      1) / 2;
-				phy_b10 = -9;
-			}
-
-			phy_b6 = -60 + 27 + eps_offset + phy_b11 + phy_b10;
-
-			mod_phy_reg(pi, (phy_b5 == PHY_CORE_0) ? 0x298 :
-				    0x29c, (0x1ff << 7), (phy_b6) << 7);
-
-			pi->nphy_papd_epsilon_offset[phy_b5] = phy_b6;
-		}
-	}
-
-	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
-	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-		    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
-		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 13), (0) << 13);
-
-	} else {
-		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 11), (0) << 11);
-
-		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x2a3 :
-			    0x2a4, (0x1 << 11), (0) << 11);
-
-	}
-	pi->nphy_papdcomp = NPHY_PAPD_COMP_ON;
-
-	write_phy_reg(pi, 0x01, phy_b9);
-
-	wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, phy_b4);
-	if (phy_b4 == PHY_TPC_HW_OFF) {
-		wlc_phy_txpwr_index_nphy(pi, (1 << 0),
-					 (s8) (pi->nphy_txpwrindex[0].
-						 index_internal), false);
-		wlc_phy_txpwr_index_nphy(pi, (1 << 1),
-					 (s8) (pi->nphy_txpwrindex[1].
-						 index_internal), false);
-	}
-
-	wlc_phy_stay_in_carriersearch_nphy(pi, false);
-
-	if (!phy_b3) {
-		wlapi_enable_mac(pi->sh->physhim);
-	}
-}
-
-void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi)
-{
-	uint core;
-	u32 txgain;
-	u16 rad_gain, dac_gain, bbmult, m1m2;
-	u8 txpi[2], chan_freq_range;
-	s32 rfpwr_offset;
-
-	ASSERT(pi->nphy_txpwrctrl == PHY_TPC_HW_OFF);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	if (pi->sh->sromrev < 4) {
-		txpi[0] = txpi[1] = 72;
-	} else {
-
-		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
-		switch (chan_freq_range) {
-		case WL_CHAN_FREQ_RANGE_2G:
-			txpi[0] = pi->nphy_txpid2g[0];
-			txpi[1] = pi->nphy_txpid2g[1];
-			break;
-		case WL_CHAN_FREQ_RANGE_5GL:
-			txpi[0] = pi->nphy_txpid5gl[0];
-			txpi[1] = pi->nphy_txpid5gl[1];
-			break;
-		case WL_CHAN_FREQ_RANGE_5GM:
-			txpi[0] = pi->nphy_txpid5g[0];
-			txpi[1] = pi->nphy_txpid5g[1];
-			break;
-		case WL_CHAN_FREQ_RANGE_5GH:
-			txpi[0] = pi->nphy_txpid5gh[0];
-			txpi[1] = pi->nphy_txpid5gh[1];
-			break;
-		default:
-			txpi[0] = txpi[1] = 91;
-			break;
-		}
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		txpi[0] = txpi[1] = 30;
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		txpi[0] = txpi[1] = 40;
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
-
-		if ((txpi[0] < 40) || (txpi[0] > 100) ||
-		    (txpi[1] < 40) || (txpi[1] > 100))
-			txpi[0] = txpi[1] = 91;
-	}
-
-	pi->nphy_txpwrindex[PHY_CORE_0].index_internal = txpi[0];
-	pi->nphy_txpwrindex[PHY_CORE_1].index_internal = txpi[1];
-	pi->nphy_txpwrindex[PHY_CORE_0].index_internal_save = txpi[0];
-	pi->nphy_txpwrindex[PHY_CORE_1].index_internal_save = txpi[1];
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if (PHY_IPA(pi)) {
-				u32 *tx_gaintbl =
-				    wlc_phy_get_ipa_gaintbl_nphy(pi);
-				txgain = tx_gaintbl[txpi[core]];
-			} else {
-				if (CHSPEC_IS5G(pi->radio_chanspec)) {
-					if NREV_IS
-						(pi->pubpi.phy_rev, 3) {
-						txgain =
-						    nphy_tpc_5GHz_txgain_rev3
-						    [txpi[core]];
-					} else if NREV_IS
-						(pi->pubpi.phy_rev, 4) {
-						txgain =
-						    (pi->srom_fem5g.extpagain ==
-						     3) ?
-						    nphy_tpc_5GHz_txgain_HiPwrEPA
-						    [txpi[core]] :
-						    nphy_tpc_5GHz_txgain_rev4
-						    [txpi[core]];
-					} else {
-						txgain =
-						    nphy_tpc_5GHz_txgain_rev5
-						    [txpi[core]];
-					}
-				} else {
-					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
-					    (pi->srom_fem2g.extpagain == 3)) {
-						txgain =
-						    nphy_tpc_txgain_HiPwrEPA
-						    [txpi[core]];
-					} else {
-						txgain =
-						    nphy_tpc_txgain_rev3[txpi
-									 [core]];
-					}
-				}
-			}
-		} else {
-			txgain = nphy_tpc_txgain[txpi[core]];
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			rad_gain = (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
-		} else {
-			rad_gain = (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			dac_gain = (txgain >> 8) & ((1 << (10 - 8 + 1)) - 1);
-		} else {
-			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
-		}
-		bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-					 0xa5), (0x1 << 8), (0x1 << 8));
-		} else {
-			mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
-		}
-		write_phy_reg(pi, (core == PHY_CORE_0) ? 0xaa : 0xab, dac_gain);
-
-		wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
-					 &rad_gain);
-
-		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
-		m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
-		m1m2 |= ((core == PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
-		wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
-
-		if (PHY_IPA(pi)) {
-			wlc_phy_table_read_nphy(pi,
-						(core ==
-						 PHY_CORE_0 ?
-						 NPHY_TBL_ID_CORE1TXPWRCTL :
-						 NPHY_TBL_ID_CORE2TXPWRCTL), 1,
-						576 + txpi[core], 32,
-						&rfpwr_offset);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1ff << 4),
-				    ((s16) rfpwr_offset) << 4);
-
-			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 2), (1) << 2);
-
-		}
-	}
-
-	and_phy_reg(pi, 0xbf, (u16) (~(0x1f << 0)));
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void
-wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max, u16 *pwr_offset,
-				u8 tmp_max_pwr, u8 rate_start,
-				u8 rate_end)
-{
-	u8 rate;
-	u8 word_num, nibble_num;
-	u8 tmp_nibble;
-
-	for (rate = rate_start; rate <= rate_end; rate++) {
-		word_num = (rate - rate_start) >> 2;
-		nibble_num = (rate - rate_start) & 0x3;
-		tmp_nibble = (pwr_offset[word_num] >> 4 * nibble_num) & 0xf;
-
-		srom_max[rate] = tmp_max_pwr - 2 * tmp_nibble;
-	}
-}
-
-static void
-wlc_phy_txpwr_nphy_po_apply(u8 *srom_max, u8 pwr_offset,
-			    u8 rate_start, u8 rate_end)
-{
-	u8 rate;
-
-	for (rate = rate_start; rate <= rate_end; rate++) {
-		srom_max[rate] -= 2 * pwr_offset;
-	}
-}
-
-void
-wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
-				u8 rate_mcs_end, u8 rate_ofdm_start)
-{
-	u8 rate1, rate2;
-
-	rate2 = rate_ofdm_start;
-	for (rate1 = rate_mcs_start; rate1 <= rate_mcs_end - 1; rate1++) {
-		power[rate1] = power[rate2];
-		rate2 += (rate1 == rate_mcs_start) ? 2 : 1;
-	}
-	power[rate_mcs_end] = power[rate_mcs_end - 1];
-}
-
-void
-wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power, u8 rate_ofdm_start,
-				u8 rate_ofdm_end, u8 rate_mcs_start)
-{
-	u8 rate1, rate2;
-
-	for (rate1 = rate_ofdm_start, rate2 = rate_mcs_start;
-	     rate1 <= rate_ofdm_end; rate1++, rate2++) {
-		power[rate1] = power[rate2];
-		if (rate1 == rate_ofdm_start)
-			power[++rate1] = power[rate2];
-	}
-}
-
-void wlc_phy_txpwr_apply_nphy(phy_info_t *pi)
-{
-	uint rate1, rate2, band_num;
-	u8 tmp_bw40po = 0, tmp_cddpo = 0, tmp_stbcpo = 0;
-	u8 tmp_max_pwr = 0;
-	u16 pwr_offsets1[2], *pwr_offsets2 = NULL;
-	u8 *tx_srom_max_rate = NULL;
-
-	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
-		switch (band_num) {
-		case 0:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_2g,
-					  pi->nphy_pwrctrl_info[1].max_pwr_2g);
-
-			pwr_offsets1[0] = pi->cck2gpo;
-			wlc_phy_txpwr_nphy_srom_convert(pi->tx_srom_max_rate_2g,
-							pwr_offsets1,
-							tmp_max_pwr,
-							TXP_FIRST_CCK,
-							TXP_LAST_CCK);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm2gpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm2gpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs2gpo;
-
-			tmp_cddpo = pi->cdd2gpo;
-			tmp_stbcpo = pi->stbc2gpo;
-			tmp_bw40po = pi->bw402gpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_2g;
-			break;
-		case 1:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gm,
-					  pi->nphy_pwrctrl_info[1].max_pwr_5gm);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm5gpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm5gpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs5gpo;
-
-			tmp_cddpo = pi->cdd5gpo;
-			tmp_stbcpo = pi->stbc5gpo;
-			tmp_bw40po = pi->bw405gpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_5g_mid;
-			break;
-		case 2:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gl,
-					  pi->nphy_pwrctrl_info[1].max_pwr_5gl);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm5glpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm5glpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs5glpo;
-
-			tmp_cddpo = pi->cdd5glpo;
-			tmp_stbcpo = pi->stbc5glpo;
-			tmp_bw40po = pi->bw405glpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_5g_low;
-			break;
-		case 3:
-
-			tmp_max_pwr = min(pi->nphy_pwrctrl_info[0].max_pwr_5gh,
-					  pi->nphy_pwrctrl_info[1].max_pwr_5gh);
-
-			pwr_offsets1[0] = (u16) (pi->ofdm5ghpo & 0xffff);
-			pwr_offsets1[1] =
-			    (u16) (pi->ofdm5ghpo >> 16) & 0xffff;
-
-			pwr_offsets2 = pi->mcs5ghpo;
-
-			tmp_cddpo = pi->cdd5ghpo;
-			tmp_stbcpo = pi->stbc5ghpo;
-			tmp_bw40po = pi->bw405ghpo;
-
-			tx_srom_max_rate = pi->tx_srom_max_rate_5g_hi;
-			break;
-		}
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets1,
-						tmp_max_pwr, TXP_FIRST_OFDM,
-						TXP_LAST_OFDM);
-
-		wlc_phy_ofdm_to_mcs_powers_nphy(tx_srom_max_rate,
-						TXP_FIRST_MCS_20_SISO,
-						TXP_LAST_MCS_20_SISO,
-						TXP_FIRST_OFDM);
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
-						tmp_max_pwr,
-						TXP_FIRST_MCS_20_CDD,
-						TXP_LAST_MCS_20_CDD);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
-						    TXP_FIRST_MCS_20_CDD,
-						    TXP_LAST_MCS_20_CDD);
-		}
-
-		wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
-						TXP_FIRST_OFDM_20_CDD,
-						TXP_LAST_OFDM_20_CDD,
-						TXP_FIRST_MCS_20_CDD);
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate, pwr_offsets2,
-						tmp_max_pwr,
-						TXP_FIRST_MCS_20_STBC,
-						TXP_LAST_MCS_20_STBC);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
-						    tmp_stbcpo,
-						    TXP_FIRST_MCS_20_STBC,
-						    TXP_LAST_MCS_20_STBC);
-		}
-
-		wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-						&pwr_offsets2[2], tmp_max_pwr,
-						TXP_FIRST_MCS_20_SDM,
-						TXP_LAST_MCS_20_SDM);
-
-		if (NPHY_IS_SROM_REINTERPRET) {
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[4],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_SISO,
-							TXP_LAST_MCS_40_SISO);
-
-			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
-							TXP_FIRST_OFDM_40_SISO,
-							TXP_LAST_OFDM_40_SISO,
-							TXP_FIRST_MCS_40_SISO);
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[4],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_CDD,
-							TXP_LAST_MCS_40_CDD);
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate, tmp_cddpo,
-						    TXP_FIRST_MCS_40_CDD,
-						    TXP_LAST_MCS_40_CDD);
-
-			wlc_phy_mcs_to_ofdm_powers_nphy(tx_srom_max_rate,
-							TXP_FIRST_OFDM_40_CDD,
-							TXP_LAST_OFDM_40_CDD,
-							TXP_FIRST_MCS_40_CDD);
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[4],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_STBC,
-							TXP_LAST_MCS_40_STBC);
-
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
-						    tmp_stbcpo,
-						    TXP_FIRST_MCS_40_STBC,
-						    TXP_LAST_MCS_40_STBC);
-
-			wlc_phy_txpwr_nphy_srom_convert(tx_srom_max_rate,
-							&pwr_offsets2[6],
-							tmp_max_pwr,
-							TXP_FIRST_MCS_40_SDM,
-							TXP_LAST_MCS_40_SDM);
-		} else {
-
-			for (rate1 = TXP_FIRST_OFDM_40_SISO, rate2 =
-			     TXP_FIRST_OFDM; rate1 <= TXP_LAST_MCS_40_SDM;
-			     rate1++, rate2++)
-				tx_srom_max_rate[rate1] =
-				    tx_srom_max_rate[rate2];
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			wlc_phy_txpwr_nphy_po_apply(tx_srom_max_rate,
-						    tmp_bw40po,
-						    TXP_FIRST_OFDM_40_SISO,
-						    TXP_LAST_MCS_40_SDM);
-		}
-
-		tx_srom_max_rate[TXP_MCS_32] =
-		    tx_srom_max_rate[TXP_FIRST_MCS_40_CDD];
-	}
-
-	return;
-}
-
-static void wlc_phy_txpwr_srom_read_ppr_nphy(phy_info_t *pi)
-{
-	u16 bw40po, cddpo, stbcpo, bwduppo;
-	uint band_num;
-
-	if (pi->sh->sromrev >= 9) {
-
-		return;
-	}
-
-	bw40po = (u16) PHY_GETINTVAR(pi, "bw40po");
-	pi->bw402gpo = bw40po & 0xf;
-	pi->bw405gpo = (bw40po & 0xf0) >> 4;
-	pi->bw405glpo = (bw40po & 0xf00) >> 8;
-	pi->bw405ghpo = (bw40po & 0xf000) >> 12;
-
-	cddpo = (u16) PHY_GETINTVAR(pi, "cddpo");
-	pi->cdd2gpo = cddpo & 0xf;
-	pi->cdd5gpo = (cddpo & 0xf0) >> 4;
-	pi->cdd5glpo = (cddpo & 0xf00) >> 8;
-	pi->cdd5ghpo = (cddpo & 0xf000) >> 12;
-
-	stbcpo = (u16) PHY_GETINTVAR(pi, "stbcpo");
-	pi->stbc2gpo = stbcpo & 0xf;
-	pi->stbc5gpo = (stbcpo & 0xf0) >> 4;
-	pi->stbc5glpo = (stbcpo & 0xf00) >> 8;
-	pi->stbc5ghpo = (stbcpo & 0xf000) >> 12;
-
-	bwduppo = (u16) PHY_GETINTVAR(pi, "bwduppo");
-	pi->bwdup2gpo = bwduppo & 0xf;
-	pi->bwdup5gpo = (bwduppo & 0xf0) >> 4;
-	pi->bwdup5glpo = (bwduppo & 0xf00) >> 8;
-	pi->bwdup5ghpo = (bwduppo & 0xf000) >> 12;
-
-	for (band_num = 0; band_num < (CH_2G_GROUP + CH_5G_GROUP); band_num++) {
-		switch (band_num) {
-		case 0:
-
-			pi->nphy_txpid2g[PHY_CORE_0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid2ga0");
-			pi->nphy_txpid2g[PHY_CORE_1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid2ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
-			    (s8) PHY_GETINTVAR(pi, "maxp2ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g =
-			    (s8) PHY_GETINTVAR(pi, "maxp2ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw0a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw0a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw1a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw1a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw2a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa2gw2a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g =
-			    (s8) PHY_GETINTVAR(pi, "itt2ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g =
-			    (s8) PHY_GETINTVAR(pi, "itt2ga1");
-
-			pi->cck2gpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
-
-			pi->ofdm2gpo = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
-
-			pi->mcs2gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
-			pi->mcs2gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs2gpo1");
-			pi->mcs2gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs2gpo2");
-			pi->mcs2gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs2gpo3");
-			pi->mcs2gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs2gpo4");
-			pi->mcs2gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs2gpo5");
-			pi->mcs2gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs2gpo6");
-			pi->mcs2gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs2gpo7");
-			break;
-		case 1:
-
-			pi->nphy_txpid5g[PHY_CORE_0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5ga0");
-			pi->nphy_txpid5g[PHY_CORE_1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
-			    (s8) PHY_GETINTVAR(pi, "maxp5ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
-			    (s8) PHY_GETINTVAR(pi, "maxp5ga1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw0a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw0a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw1a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw1a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw2a0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5gw2a1");
-			pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm =
-			    (s8) PHY_GETINTVAR(pi, "itt5ga0");
-			pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm =
-			    (s8) PHY_GETINTVAR(pi, "itt5ga1");
-
-			pi->ofdm5gpo = (u32) PHY_GETINTVAR(pi, "ofdm5gpo");
-
-			pi->mcs5gpo[0] = (u16) PHY_GETINTVAR(pi, "mcs5gpo0");
-			pi->mcs5gpo[1] = (u16) PHY_GETINTVAR(pi, "mcs5gpo1");
-			pi->mcs5gpo[2] = (u16) PHY_GETINTVAR(pi, "mcs5gpo2");
-			pi->mcs5gpo[3] = (u16) PHY_GETINTVAR(pi, "mcs5gpo3");
-			pi->mcs5gpo[4] = (u16) PHY_GETINTVAR(pi, "mcs5gpo4");
-			pi->mcs5gpo[5] = (u16) PHY_GETINTVAR(pi, "mcs5gpo5");
-			pi->mcs5gpo[6] = (u16) PHY_GETINTVAR(pi, "mcs5gpo6");
-			pi->mcs5gpo[7] = (u16) PHY_GETINTVAR(pi, "mcs5gpo7");
-			break;
-		case 2:
-
-			pi->nphy_txpid5gl[0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gla0");
-			pi->nphy_txpid5gl[1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gla1");
-			pi->nphy_pwrctrl_info[0].max_pwr_5gl =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gla0");
-			pi->nphy_pwrctrl_info[1].max_pwr_5gl =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gla1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw0a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw0a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw1a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw1a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw2a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5glw2a1");
-			pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0;
-			pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0;
-
-			pi->ofdm5glpo = (u32) PHY_GETINTVAR(pi, "ofdm5glpo");
-
-			pi->mcs5glpo[0] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo0");
-			pi->mcs5glpo[1] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo1");
-			pi->mcs5glpo[2] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo2");
-			pi->mcs5glpo[3] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo3");
-			pi->mcs5glpo[4] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo4");
-			pi->mcs5glpo[5] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo5");
-			pi->mcs5glpo[6] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo6");
-			pi->mcs5glpo[7] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5glpo7");
-			break;
-		case 3:
-
-			pi->nphy_txpid5gh[0] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gha0");
-			pi->nphy_txpid5gh[1] =
-			    (u8) PHY_GETINTVAR(pi, "txpid5gha1");
-			pi->nphy_pwrctrl_info[0].max_pwr_5gh =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gha0");
-			pi->nphy_pwrctrl_info[1].max_pwr_5gh =
-			    (s8) PHY_GETINTVAR(pi, "maxp5gha1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw0a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw1a1");
-			pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a0");
-			pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 =
-			    (s16) PHY_GETINTVAR(pi, "pa5ghw2a1");
-			pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0;
-			pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0;
-
-			pi->ofdm5ghpo = (u32) PHY_GETINTVAR(pi, "ofdm5ghpo");
-
-			pi->mcs5ghpo[0] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo0");
-			pi->mcs5ghpo[1] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo1");
-			pi->mcs5ghpo[2] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo2");
-			pi->mcs5ghpo[3] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo3");
-			pi->mcs5ghpo[4] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo4");
-			pi->mcs5ghpo[5] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo5");
-			pi->mcs5ghpo[6] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo6");
-			pi->mcs5ghpo[7] =
-			    (u16) PHY_GETINTVAR(pi, "mcs5ghpo7");
-			break;
-		}
-	}
-
-	wlc_phy_txpwr_apply_nphy(pi);
-}
-
-static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi)
-{
-
-	pi->antswitch = (u8) PHY_GETINTVAR(pi, "antswitch");
-	pi->aa2g = (u8) PHY_GETINTVAR(pi, "aa2g");
-	pi->aa5g = (u8) PHY_GETINTVAR(pi, "aa5g");
-
-	pi->srom_fem2g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos2g");
-	pi->srom_fem2g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain2g");
-	pi->srom_fem2g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange2g");
-	pi->srom_fem2g.triso = (u8) PHY_GETINTVAR(pi, "triso2g");
-	pi->srom_fem2g.antswctrllut = (u8) PHY_GETINTVAR(pi, "antswctl2g");
-
-	pi->srom_fem5g.tssipos = (u8) PHY_GETINTVAR(pi, "tssipos5g");
-	pi->srom_fem5g.extpagain = (u8) PHY_GETINTVAR(pi, "extpagain5g");
-	pi->srom_fem5g.pdetrange = (u8) PHY_GETINTVAR(pi, "pdetrange5g");
-	pi->srom_fem5g.triso = (u8) PHY_GETINTVAR(pi, "triso5g");
-	if (PHY_GETVAR(pi, "antswctl5g")) {
-
-		pi->srom_fem5g.antswctrllut =
-		    (u8) PHY_GETINTVAR(pi, "antswctl5g");
-	} else {
-
-		pi->srom_fem5g.antswctrllut =
-		    (u8) PHY_GETINTVAR(pi, "antswctl2g");
-	}
-
-	wlc_phy_txpower_ipa_upd(pi);
-
-	pi->phy_txcore_disable_temp = (s16) PHY_GETINTVAR(pi, "tempthresh");
-	if (pi->phy_txcore_disable_temp == 0) {
-		pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
-	}
-
-	pi->phy_tempsense_offset = (s8) PHY_GETINTVAR(pi, "tempoffset");
-	if (pi->phy_tempsense_offset != 0) {
-		if (pi->phy_tempsense_offset >
-		    (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) {
-			pi->phy_tempsense_offset = NPHY_SROM_MAXTEMPOFFSET;
-		} else if (pi->phy_tempsense_offset < (NPHY_SROM_TEMPSHIFT +
-						    NPHY_SROM_MINTEMPOFFSET)) {
-			pi->phy_tempsense_offset = NPHY_SROM_MINTEMPOFFSET;
-		} else {
-			pi->phy_tempsense_offset -= NPHY_SROM_TEMPSHIFT;
-		}
-	}
-
-	pi->phy_txcore_enable_temp =
-	    pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP;
-
-	pi->phycal_tempdelta = (u8) PHY_GETINTVAR(pi, "phycal_tempdelta");
-	if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) {
-		pi->phycal_tempdelta = 0;
-	}
-
-	wlc_phy_txpwr_srom_read_ppr_nphy(pi);
-
-	return true;
-}
-
-void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi)
-{
-	u8 tx_pwr_ctrl_state;
-	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
-	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
-
-	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-		(void)R_REG(pi->sh->osh, &pi->regs->maccontrol);
-		udelay(1);
-	}
-
-	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-}
-
-static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi)
-{
-	u32 idx;
-	u16 iqloCalbuf[7];
-	u32 iqcomp, locomp, curr_locomp;
-	s8 locomp_i, locomp_q;
-	s8 curr_locomp_i, curr_locomp_q;
-	u32 tbl_id, tbl_len, tbl_offset;
-	u32 regval[128];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	wlc_phy_table_read_nphy(pi, 15, 7, 80, 16, iqloCalbuf);
-
-	tbl_len = 128;
-	tbl_offset = 320;
-	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
-	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-		iqcomp =
-		    (tbl_id ==
-		     26) ? (((u32) (iqloCalbuf[0] & 0x3ff)) << 10) |
-		    (iqloCalbuf[1] & 0x3ff)
-		    : (((u32) (iqloCalbuf[2] & 0x3ff)) << 10) |
-		    (iqloCalbuf[3] & 0x3ff);
-
-		for (idx = 0; idx < tbl_len; idx++) {
-			regval[idx] = iqcomp;
-		}
-		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
-					 regval);
-	}
-
-	tbl_offset = 448;
-	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
-	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
-		locomp =
-		    (u32) ((tbl_id == 26) ? iqloCalbuf[5] : iqloCalbuf[6]);
-		locomp_i = (s8) ((locomp >> 8) & 0xff);
-		locomp_q = (s8) ((locomp) & 0xff);
-		for (idx = 0; idx < tbl_len; idx++) {
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				curr_locomp_i = locomp_i;
-				curr_locomp_q = locomp_q;
-			} else {
-				curr_locomp_i = (s8) ((locomp_i *
-							 nphy_tpc_loscale[idx] +
-							 128) >> 8);
-				curr_locomp_q =
-				    (s8) ((locomp_q * nphy_tpc_loscale[idx] +
-					     128) >> 8);
-			}
-			curr_locomp = (u32) ((curr_locomp_i & 0xff) << 8);
-			curr_locomp |= (u32) (curr_locomp_q & 0xff);
-			regval[idx] = curr_locomp;
-		}
-		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
-					 regval);
-	}
-
-	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
-
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX1, 0xFFFF);
-		wlapi_bmac_write_shm(pi->sh->physhim, M_CURR_IDX2, 0xFFFF);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static void wlc_phy_ipa_internal_tssi_setup_nphy(phy_info_t *pi)
-{
-	u8 core;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x5);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MUX, 0xe);
-
-				if (pi->pubpi.radiorev != 5)
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIA, 0);
-
-				if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIG, 0x1);
-				} else {
-
-					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
-							 core, TSSIG, 0x31);
-				}
-			} else {
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MASTER, 0x9);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TX_SSI_MUX, 0xc);
-				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
-						 TSSIG, 0);
-
-				if (pi->pubpi.radiorev != 5) {
-					if (!NREV_IS(pi->pubpi.phy_rev, 7)) {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x1);
-					} else {
-
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TSSIA, 0x31);
-					}
-				}
-			}
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
-					 0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
-					 0);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
-					 0x3);
-			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
-					 0x0);
-		}
-	} else {
-		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR31,
-				(CHSPEC_IS2G(pi->radio_chanspec)) ? 0x128 :
-				0x80);
-		WRITE_RADIO_SYN(pi, RADIO_2056, RESERVED_ADDR30, 0x0);
-		WRITE_RADIO_SYN(pi, RADIO_2056, GPIO_MASTER1, 0x29);
-
-		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_VCM_HG,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, IQCAL_IDAC,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_VCM,
-					 0x3);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TX_AMP_DET,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC1,
-					 0x8);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC2,
-					 0x0);
-			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, TSSI_MISC3,
-					 0x0);
-
-			if (CHSPEC_IS2G(pi->radio_chanspec)) {
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MASTER, 0x5);
-
-				if (pi->pubpi.radiorev != 5)
-					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
-							 core, TSSIA, 0x0);
-				if (NREV_GE(pi->pubpi.phy_rev, 5)) {
-
-					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
-							 core, TSSIG, 0x31);
-				} else {
-					WRITE_RADIO_REG2(pi, RADIO_2056, TX,
-							 core, TSSIG, 0x11);
-				}
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MUX, 0xe);
-			} else {
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MASTER, 0x9);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TSSIA, 0x31);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TSSIG, 0x0);
-				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
-						 TX_SSI_MUX, 0xc);
-			}
-		}
-	}
-}
-
-static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi)
-{
-	s32 rssi_buf[4];
-	s32 int_val;
-
-	if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi) || PHY_MUTED(pi))
-
-		return;
-
-	if (PHY_IPA(pi)) {
-		wlc_phy_ipa_internal_tssi_setup_nphy(pi);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
-						  0, 0x3, 0,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 0);
-	}
-
-	wlc_phy_stopplayback_nphy(pi);
-
-	wlc_phy_tx_tone_nphy(pi, 4000, 0, 0, 0, false);
-
-	udelay(20);
-	int_val =
-	    wlc_phy_poll_rssi_nphy(pi, (u8) NPHY_RSSI_SEL_TSSI_2G, rssi_buf,
-				   1);
-	wlc_phy_stopplayback_nphy(pi);
-	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, 0);
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
-						  0, 0x3, 1,
-						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
-	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 3, 1);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
-		    (u8) ((int_val >> 24) & 0xff);
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
-		    (u8) ((int_val >> 24) & 0xff);
-
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
-		    (u8) ((int_val >> 8) & 0xff);
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
-		    (u8) ((int_val >> 8) & 0xff);
-	} else {
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_2g =
-		    (u8) ((int_val >> 24) & 0xff);
-
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_2g =
-		    (u8) ((int_val >> 8) & 0xff);
-
-		pi->nphy_pwrctrl_info[PHY_CORE_0].idle_tssi_5g =
-		    (u8) ((int_val >> 16) & 0xff);
-		pi->nphy_pwrctrl_info[PHY_CORE_1].idle_tssi_5g =
-		    (u8) ((int_val) & 0xff);
-	}
-
-}
-
-static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi)
-{
-	u32 idx;
-	s16 a1[2], b0[2], b1[2];
-	s8 target_pwr_qtrdbm[2];
-	s32 num, den, pwr_est;
-	u8 chan_freq_range;
-	u8 idle_tssi[2];
-	u32 tbl_id, tbl_len, tbl_offset;
-	u32 regval[64];
-	u8 core;
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-		(void)R_REG(pi->sh->osh, &pi->regs->maccontrol);
-		udelay(1);
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	or_phy_reg(pi, 0x122, (0x1 << 0));
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		and_phy_reg(pi, 0x1e7, (u16) (~(0x1 << 15)));
-	} else {
-
-		or_phy_reg(pi, 0x1e7, (0x1 << 15));
-	}
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
-	if (pi->sh->sromrev < 4) {
-		idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
-		idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-		target_pwr_qtrdbm[0] = 13 * 4;
-		target_pwr_qtrdbm[1] = 13 * 4;
-		a1[0] = -424;
-		a1[1] = -424;
-		b0[0] = 5612;
-		b0[1] = 5612;
-		b1[1] = -1393;
-		b1[0] = -1393;
-	} else {
-
-		chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
-		switch (chan_freq_range) {
-		case WL_CHAN_FREQ_RANGE_2G:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_2g;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_2g;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_b1;
-			break;
-		case WL_CHAN_FREQ_RANGE_5GL:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_5gl;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_5gl;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1;
-			break;
-		case WL_CHAN_FREQ_RANGE_5GM:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_5gm;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_5gm;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_b1;
-			break;
-		case WL_CHAN_FREQ_RANGE_5GH:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-			    pi->nphy_pwrctrl_info[0].max_pwr_5gh;
-			target_pwr_qtrdbm[1] =
-			    pi->nphy_pwrctrl_info[1].max_pwr_5gh;
-			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
-			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
-			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
-			b0[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0;
-			b1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1;
-			b1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1;
-			break;
-		default:
-			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
-			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-			target_pwr_qtrdbm[0] = 13 * 4;
-			target_pwr_qtrdbm[1] = 13 * 4;
-			a1[0] = -424;
-			a1[1] = -424;
-			b0[0] = 5612;
-			b0[1] = 5612;
-			b1[1] = -1393;
-			b1[0] = -1393;
-			break;
-		}
-	}
-
-	target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
-	target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
-
-	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-		if (pi->srom_fem2g.tssipos) {
-			or_phy_reg(pi, 0x1e9, (0x1 << 14));
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-			for (core = 0; core <= 1; core++) {
-				if (PHY_IPA(pi)) {
-
-					if (CHSPEC_IS2G(pi->radio_chanspec)) {
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TX_SSI_MUX,
-								 0xe);
-					} else {
-						WRITE_RADIO_REG3(pi, RADIO_2057,
-								 TX, core,
-								 TX_SSI_MUX,
-								 0xc);
-					}
-				} else {
-				}
-			}
-		} else {
-			if (PHY_IPA(pi)) {
-
-				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX0,
-						(CHSPEC_IS5G
-						 (pi->
-						  radio_chanspec)) ? 0xc : 0xe);
-				write_radio_reg(pi,
-						RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX1,
-						(CHSPEC_IS5G
-						 (pi->
-						  radio_chanspec)) ? 0xc : 0xe);
-			} else {
-
-				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX0, 0x11);
-				write_radio_reg(pi, RADIO_2056_TX_TX_SSI_MUX |
-						RADIO_2056_TX1, 0x11);
-			}
-		}
-	}
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12)) {
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, MCTL_PHYLOCK);
-		(void)R_REG(pi->sh->osh, &pi->regs->maccontrol);
-		udelay(1);
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
-	} else {
-		mod_phy_reg(pi, 0x1e7, (0x7f << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
-	}
-
-	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-		mod_phy_reg(pi, 0x222, (0xff << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7 << 0));
-	} else if (NREV_GT(pi->pubpi.phy_rev, 1)) {
-		mod_phy_reg(pi, 0x222, (0xff << 0),
-			    (NPHY_TxPwrCtrlCmd_pwrIndex_init << 0));
-	}
-
-	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
-		wlapi_bmac_mctrl(pi->sh->physhim, MCTL_PHYLOCK, 0);
-
-	write_phy_reg(pi, 0x1e8, (0x3 << 8) | (240 << 0));
-
-	write_phy_reg(pi, 0x1e9,
-		      (1 << 15) | (idle_tssi[0] << 0) | (idle_tssi[1] << 8));
-
-	write_phy_reg(pi, 0x1ea,
-		      (target_pwr_qtrdbm[0] << 0) |
-		      (target_pwr_qtrdbm[1] << 8));
-
-	tbl_len = 64;
-	tbl_offset = 0;
-	for (tbl_id = NPHY_TBL_ID_CORE1TXPWRCTL;
-	     tbl_id <= NPHY_TBL_ID_CORE2TXPWRCTL; tbl_id++) {
-
-		for (idx = 0; idx < tbl_len; idx++) {
-			num =
-			    8 * (16 * b0[tbl_id - 26] + b1[tbl_id - 26] * idx);
-			den = 32768 + a1[tbl_id - 26] * idx;
-			pwr_est = max(((4 * num + den / 2) / den), -8);
-			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
-				if (idx <=
-				    (uint) (31 - idle_tssi[tbl_id - 26] + 1))
-					pwr_est =
-					    max(pwr_est,
-						target_pwr_qtrdbm[tbl_id - 26] +
-						1);
-			}
-			regval[idx] = (u32) pwr_est;
-		}
-		wlc_phy_table_write_nphy(pi, tbl_id, tbl_len, tbl_offset, 32,
-					 regval);
-	}
-
-	wlc_phy_txpwr_limit_to_tbl_nphy(pi);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64, 8,
-				 pi->adj_pwr_tbl_nphy);
-	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64, 8,
-				 pi->adj_pwr_tbl_nphy);
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi)
-{
-	return read_phy_reg((pi), 0x1e7) & ((0x1 << 15) |
-					     (0x1 << 14) | (0x1 << 13));
-}
-
-static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core)
-{
-	u16 tmp;
-	tmp = read_phy_reg(pi, ((core == PHY_CORE_0) ? 0x1ed : 0x1ee));
-
-	tmp = (tmp & (0x7f << 8)) >> 8;
-	return (u8) tmp;
-}
-
-static void
-wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0, u8 idx1)
-{
-	mod_phy_reg(pi, 0x1e7, (0x7f << 0), idx0);
-
-	if (NREV_GT(pi->pubpi.phy_rev, 1))
-		mod_phy_reg(pi, 0x222, (0xff << 0), idx1);
-}
-
-u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi)
-{
-	u16 tmp;
-	u16 pwr_idx[2];
-
-	if (wlc_phy_txpwr_ison_nphy(pi)) {
-		pwr_idx[0] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_0);
-		pwr_idx[1] = wlc_phy_txpwr_idx_cur_get_nphy(pi, PHY_CORE_1);
-
-		tmp = (pwr_idx[0] << 8) | pwr_idx[1];
-	} else {
-		tmp =
-		    ((pi->nphy_txpwrindex[PHY_CORE_0].
-		      index_internal & 0xff) << 8) | (pi->
-						      nphy_txpwrindex
-						      [PHY_CORE_1].
-						      index_internal & 0xff);
-	}
-
-	return tmp;
-}
-
-void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi)
-{
-	if (PHY_IPA(pi)
-	    && (pi->nphy_force_papd_cal
-		|| (wlc_phy_txpwr_ison_nphy(pi)
-		    &&
-		    (((u32)
-		      ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 0) -
-			  pi->nphy_papd_tx_gain_at_last_cal[0]) >= 4)
-		     || ((u32)
-			 ABS(wlc_phy_txpwr_idx_cur_get_nphy(pi, 1) -
-			     pi->nphy_papd_tx_gain_at_last_cal[1]) >= 4))))) {
-		wlc_phy_a4(pi, true);
-	}
-}
-
-void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type)
-{
-	u16 mask = 0, val = 0, ishw = 0;
-	u8 ctr;
-	uint core;
-	u32 tbl_offset;
-	u32 tbl_len;
-	u16 regval[84];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	switch (ctrl_type) {
-	case PHY_TPC_HW_OFF:
-	case PHY_TPC_HW_ON:
-		pi->nphy_txpwrctrl = ctrl_type;
-		break;
-	default:
-		break;
-	}
-
-	if (ctrl_type == PHY_TPC_HW_OFF) {
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			if (wlc_phy_txpwr_ison_nphy(pi)) {
-				for (core = 0; core < pi->pubpi.phy_corenum;
-				     core++)
-					pi->nphy_txpwr_idx[core] =
-					    wlc_phy_txpwr_idx_cur_get_nphy(pi,
-									   (u8)
-									   core);
-			}
-
-		}
-
-		tbl_len = 84;
-		tbl_offset = 64;
-		for (ctr = 0; ctr < tbl_len; ctr++) {
-			regval[ctr] = 0;
-		}
-		wlc_phy_table_write_nphy(pi, 26, tbl_len, tbl_offset, 16,
-					 regval);
-		wlc_phy_table_write_nphy(pi, 27, tbl_len, tbl_offset, 16,
-					 regval);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-
-			and_phy_reg(pi, 0x1e7,
-				    (u16) (~((0x1 << 15) |
-						(0x1 << 14) | (0x1 << 13))));
-		} else {
-			and_phy_reg(pi, 0x1e7,
-				    (u16) (~((0x1 << 14) | (0x1 << 13))));
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			or_phy_reg(pi, 0x8f, (0x1 << 8));
-			or_phy_reg(pi, 0xa5, (0x1 << 8));
-		} else {
-			or_phy_reg(pi, 0xa5, (0x1 << 14));
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x53);
-		else if (NREV_LT(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x5a);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
-				       MHF1_IQSWAP_WAR, WLC_BAND_ALL);
-
-	} else {
-
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 84, 64,
-					 8, pi->adj_pwr_tbl_nphy);
-		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 84, 64,
-					 8, pi->adj_pwr_tbl_nphy);
-
-		ishw = (ctrl_type == PHY_TPC_HW_ON) ? 0x1 : 0x0;
-		mask = (0x1 << 14) | (0x1 << 13);
-		val = (ishw << 14) | (ishw << 13);
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			mask |= (0x1 << 15);
-			val |= (ishw << 15);
-		}
-
-		mod_phy_reg(pi, 0x1e7, mask, val);
-
-		if (CHSPEC_IS5G(pi->radio_chanspec)) {
-			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
-				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x32);
-				mod_phy_reg(pi, 0x222, (0xff << 0), 0x32);
-			} else {
-				mod_phy_reg(pi, 0x1e7, (0x7f << 0), 0x64);
-				if (NREV_GT(pi->pubpi.phy_rev, 1))
-					mod_phy_reg(pi, 0x222,
-						    (0xff << 0), 0x64);
-			}
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			if ((pi->nphy_txpwr_idx[0] != 128)
-			    && (pi->nphy_txpwr_idx[1] != 128)) {
-				wlc_phy_txpwr_idx_cur_set_nphy(pi,
-							       pi->
-							       nphy_txpwr_idx
-							       [0],
-							       pi->
-							       nphy_txpwr_idx
-							       [1]);
-			}
-		}
-
-		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-			and_phy_reg(pi, 0x8f, ~(0x1 << 8));
-			and_phy_reg(pi, 0xa5, ~(0x1 << 8));
-		} else {
-			and_phy_reg(pi, 0xa5, ~(0x1 << 14));
-		}
-
-		if (NREV_IS(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
-		else if (NREV_LT(pi->pubpi.phy_rev, 2))
-			mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
-
-		if (NREV_LT(pi->pubpi.phy_rev, 2) && IS40MHZ(pi))
-			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_IQSWAP_WAR,
-				       0x0, WLC_BAND_ALL);
-
-		if (PHY_IPA(pi)) {
-			mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 2), (0) << 2);
-
-			mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
-				    0x29b, (0x1 << 2), (0) << 2);
-
-		}
-
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-void
-wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask, s8 txpwrindex,
-			 bool restore_cals)
-{
-	u8 core, txpwrctl_tbl;
-	u16 tx_ind0, iq_ind0, lo_ind0;
-	u16 m1m2;
-	u32 txgain;
-	u16 rad_gain, dac_gain;
-	u8 bbmult;
-	u32 iqcomp;
-	u16 iqcomp_a, iqcomp_b;
-	u32 locomp;
-	u16 tmpval;
-	u8 tx_pwr_ctrl_state;
-	s32 rfpwr_offset;
-	u16 regval[2];
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, true);
-
-	tx_ind0 = 192;
-	iq_ind0 = 320;
-	lo_ind0 = 448;
-
-	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
-
-		if ((core_mask & (1 << core)) == 0) {
-			continue;
-		}
-
-		txpwrctl_tbl = (core == PHY_CORE_0) ? 26 : 27;
-
-		if (txpwrindex < 0) {
-			if (pi->nphy_txpwrindex[core].index < 0) {
-
-				continue;
-			}
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				mod_phy_reg(pi, 0x8f,
-					    (0x1 << 8),
-					    pi->nphy_txpwrindex[core].
-					    AfectrlOverride);
-				mod_phy_reg(pi, 0xa5, (0x1 << 8),
-					    pi->nphy_txpwrindex[core].
-					    AfectrlOverride);
-			} else {
-				mod_phy_reg(pi, 0xa5,
-					    (0x1 << 14),
-					    pi->nphy_txpwrindex[core].
-					    AfectrlOverride);
-			}
-
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xaa : 0xab,
-				      pi->nphy_txpwrindex[core].AfeCtrlDacGain);
-
-			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
-						 &pi->nphy_txpwrindex[core].
-						 rad_gain);
-
-			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
-			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
-			m1m2 |= ((core == PHY_CORE_0) ?
-				 (pi->nphy_txpwrindex[core].bbmult << 8) :
-				 (pi->nphy_txpwrindex[core].bbmult << 0));
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
-
-			if (restore_cals) {
-
-				wlc_phy_table_write_nphy(pi, 15, 2,
-							 (80 + 2 * core), 16,
-							 (void *)&pi->
-							 nphy_txpwrindex[core].
-							 iqcomp_a);
-
-				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
-							 16,
-							 &pi->
-							 nphy_txpwrindex[core].
-							 locomp);
-				wlc_phy_table_write_nphy(pi, 15, 1, (93 + core),
-							 16,
-							 (void *)&pi->
-							 nphy_txpwrindex[core].
-							 locomp);
-			}
-
-			wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
-
-			pi->nphy_txpwrindex[core].index_internal =
-			    pi->nphy_txpwrindex[core].index_internal_save;
-		} else {
-
-			if (pi->nphy_txpwrindex[core].index < 0) {
-
-				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-					mod_phy_reg(pi, 0x8f,
-						    (0x1 << 8),
-						    pi->nphy_txpwrindex[core].
-						    AfectrlOverride);
-					mod_phy_reg(pi, 0xa5, (0x1 << 8),
-						    pi->nphy_txpwrindex[core].
-						    AfectrlOverride);
-				} else {
-					pi->nphy_txpwrindex[core].
-					    AfectrlOverride =
-					    read_phy_reg(pi, 0xa5);
-				}
-
-				pi->nphy_txpwrindex[core].AfeCtrlDacGain =
-				    read_phy_reg(pi,
-						 (core ==
-						  PHY_CORE_0) ? 0xaa : 0xab);
-
-				wlc_phy_table_read_nphy(pi, 7, 1,
-							(0x110 + core), 16,
-							&pi->
-							nphy_txpwrindex[core].
-							rad_gain);
-
-				wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
-							&tmpval);
-				tmpval >>= ((core == PHY_CORE_0) ? 8 : 0);
-				tmpval &= 0xff;
-				pi->nphy_txpwrindex[core].bbmult =
-				    (u8) tmpval;
-
-				wlc_phy_table_read_nphy(pi, 15, 2,
-							(80 + 2 * core), 16,
-							(void *)&pi->
-							nphy_txpwrindex[core].
-							iqcomp_a);
-
-				wlc_phy_table_read_nphy(pi, 15, 1, (85 + core),
-							16,
-							(void *)&pi->
-							nphy_txpwrindex[core].
-							locomp);
-
-				pi->nphy_txpwrindex[core].index_internal_save =
-				    pi->nphy_txpwrindex[core].index_internal;
-			}
-
-			tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
-			wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
-
-			if (NREV_IS(pi->pubpi.phy_rev, 1))
-				wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
-
-			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
-						(tx_ind0 + txpwrindex), 32,
-						&txgain);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				rad_gain =
-				    (txgain >> 16) & ((1 << (32 - 16 + 1)) - 1);
-			} else {
-				rad_gain =
-				    (txgain >> 16) & ((1 << (28 - 16 + 1)) - 1);
-			}
-			dac_gain = (txgain >> 8) & ((1 << (13 - 8 + 1)) - 1);
-			bbmult = (txgain >> 0) & ((1 << (7 - 0 + 1)) - 1);
-
-			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
-				mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
-						 0xa5), (0x1 << 8), (0x1 << 8));
-			} else {
-				mod_phy_reg(pi, 0xa5, (0x1 << 14), (0x1 << 14));
-			}
-			write_phy_reg(pi, (core == PHY_CORE_0) ?
-				      0xaa : 0xab, dac_gain);
-
-			wlc_phy_table_write_nphy(pi, 7, 1, (0x110 + core), 16,
-						 &rad_gain);
-
-			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m1m2);
-			m1m2 &= ((core == PHY_CORE_0) ? 0x00ff : 0xff00);
-			m1m2 |=
-			    ((core ==
-			      PHY_CORE_0) ? (bbmult << 8) : (bbmult << 0));
-
-			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m1m2);
-
-			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
-						(iq_ind0 + txpwrindex), 32,
-						&iqcomp);
-			iqcomp_a = (iqcomp >> 10) & ((1 << (19 - 10 + 1)) - 1);
-			iqcomp_b = (iqcomp >> 0) & ((1 << (9 - 0 + 1)) - 1);
-
-			if (restore_cals) {
-				regval[0] = (u16) iqcomp_a;
-				regval[1] = (u16) iqcomp_b;
-				wlc_phy_table_write_nphy(pi, 15, 2,
-							 (80 + 2 * core), 16,
-							 regval);
-			}
-
-			wlc_phy_table_read_nphy(pi, txpwrctl_tbl, 1,
-						(lo_ind0 + txpwrindex), 32,
-						&locomp);
-			if (restore_cals) {
-				wlc_phy_table_write_nphy(pi, 15, 1, (85 + core),
-							 16, &locomp);
-			}
-
-			if (NREV_IS(pi->pubpi.phy_rev, 1))
-				wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
-
-			if (PHY_IPA(pi)) {
-				wlc_phy_table_read_nphy(pi,
-							(core ==
-							 PHY_CORE_0 ?
-							 NPHY_TBL_ID_CORE1TXPWRCTL
-							 :
-							 NPHY_TBL_ID_CORE2TXPWRCTL),
-							1, 576 + txpwrindex, 32,
-							&rfpwr_offset);
-
-				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-					    0x29b, (0x1ff << 4),
-					    ((s16) rfpwr_offset) << 4);
-
-				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
-					    0x29b, (0x1 << 2), (1) << 2);
-
-			}
-
-			wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
-		}
-
-		pi->nphy_txpwrindex[core].index = txpwrindex;
-	}
-
-	if (pi->phyhang_avoid)
-		wlc_phy_stay_in_carriersearch_nphy(pi, false);
-}
-
-void
-wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan, u8 *max_pwr,
-				   u8 txp_rate_idx)
-{
-	u8 chan_freq_range;
-
-	chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, chan);
-	switch (chan_freq_range) {
-	case WL_CHAN_FREQ_RANGE_2G:
-		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
-		break;
-	case WL_CHAN_FREQ_RANGE_5GM:
-		*max_pwr = pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
-		break;
-	case WL_CHAN_FREQ_RANGE_5GL:
-		*max_pwr = pi->tx_srom_max_rate_5g_low[txp_rate_idx];
-		break;
-	case WL_CHAN_FREQ_RANGE_5GH:
-		*max_pwr = pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
-		break;
-	default:
-		ASSERT(0);
-		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
-		break;
-	}
-
-	return;
-}
-
-void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable)
-{
-	u16 clip_off[] = { 0xffff, 0xffff };
-
-	ASSERT(0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
-
-	if (enable) {
-		if (pi->nphy_deaf_count == 0) {
-			pi->classifier_state =
-			    wlc_phy_classifier_nphy(pi, 0, 0);
-			wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
-			wlc_phy_clip_det_nphy(pi, 0, pi->clip_state);
-			wlc_phy_clip_det_nphy(pi, 1, clip_off);
-		}
-
-		pi->nphy_deaf_count++;
-
-		wlc_phy_resetcca_nphy(pi);
-
-	} else {
-		ASSERT(pi->nphy_deaf_count > 0);
-
-		pi->nphy_deaf_count--;
-
-		if (pi->nphy_deaf_count == 0) {
-			wlc_phy_classifier_nphy(pi, (0x7 << 0),
-						pi->classifier_state);
-			wlc_phy_clip_det_nphy(pi, 1, pi->clip_state);
-		}
-	}
-}
-
-void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode)
-{
-	wlapi_suspend_mac_and_wait(pi->sh->physhim);
-
-	if (mode) {
-		if (pi->nphy_deaf_count == 0)
-			wlc_phy_stay_in_carriersearch_nphy(pi, true);
-	} else {
-		if (pi->nphy_deaf_count > 0)
-			wlc_phy_stay_in_carriersearch_nphy(pi, false);
-	}
-	wlapi_enable_mac(pi->sh->physhim);
-}
diff --git a/drivers/staging/brcm80211/phy/wlc_phy_radio.h b/drivers/staging/brcm80211/phy/wlc_phy_radio.h
deleted file mode 100644
index 72176ae..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phy_radio.h
+++ /dev/null
@@ -1,1533 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef	_BCM20XX_H
-#define	_BCM20XX_H
-
-#define	RADIO_IDCODE			0x01
-
-#define RADIO_DEFAULT_CORE		0
-
-#define	RXC0_RSSI_RST			0x80
-#define	RXC0_MODE_RSSI			0x40
-#define	RXC0_MODE_OFF			0x20
-#define	RXC0_MODE_CM			0x10
-#define	RXC0_LAN_LOAD			0x08
-#define	RXC0_OFF_ADJ_MASK		0x07
-
-#define	TXC0_MODE_TXLPF			0x04
-#define	TXC0_PA_TSSI_EN			0x02
-#define	TXC0_TSSI_EN			0x01
-
-#define	TXC1_PA_GAIN_MASK		0x60
-#define	TXC1_PA_GAIN_3DB		0x40
-#define	TXC1_PA_GAIN_2DB		0x20
-#define	TXC1_TX_MIX_GAIN		0x10
-#define	TXC1_OFF_I_MASK			0x0c
-#define	TXC1_OFF_Q_MASK			0x03
-
-#define	RADIO_2055_READ_OFF		0x100
-#define	RADIO_2057_READ_OFF		0x200
-
-#define RADIO_2055_GEN_SPARE		0x00
-#define RADIO_2055_SP_PIN_PD		0x02
-#define RADIO_2055_SP_RSSI_CORE1	0x03
-#define RADIO_2055_SP_PD_MISC_CORE1	0x04
-#define RADIO_2055_SP_RSSI_CORE2	0x05
-#define RADIO_2055_SP_PD_MISC_CORE2	0x06
-#define RADIO_2055_SP_RX_GC1_CORE1	0x07
-#define RADIO_2055_SP_RX_GC2_CORE1	0x08
-#define RADIO_2055_SP_RX_GC1_CORE2	0x09
-#define RADIO_2055_SP_RX_GC2_CORE2	0x0a
-#define RADIO_2055_SP_LPF_BW_SELECT_CORE1 0x0b
-#define RADIO_2055_SP_LPF_BW_SELECT_CORE2 0x0c
-#define RADIO_2055_SP_TX_GC1_CORE1	0x0d
-#define RADIO_2055_SP_TX_GC2_CORE1	0x0e
-#define RADIO_2055_SP_TX_GC1_CORE2	0x0f
-#define RADIO_2055_SP_TX_GC2_CORE2	0x10
-#define RADIO_2055_MASTER_CNTRL1	0x11
-#define RADIO_2055_MASTER_CNTRL2	0x12
-#define RADIO_2055_PD_LGEN		0x13
-#define RADIO_2055_PD_PLL_TS		0x14
-#define RADIO_2055_PD_CORE1_LGBUF	0x15
-#define RADIO_2055_PD_CORE1_TX		0x16
-#define RADIO_2055_PD_CORE1_RXTX	0x17
-#define RADIO_2055_PD_CORE1_RSSI_MISC	0x18
-#define RADIO_2055_PD_CORE2_LGBUF	0x19
-#define RADIO_2055_PD_CORE2_TX		0x1a
-#define RADIO_2055_PD_CORE2_RXTX	0x1b
-#define RADIO_2055_PD_CORE2_RSSI_MISC	0x1c
-#define RADIO_2055_PWRDET_LGEN		0x1d
-#define RADIO_2055_PWRDET_LGBUF_CORE1	0x1e
-#define RADIO_2055_PWRDET_RXTX_CORE1	0x1f
-#define RADIO_2055_PWRDET_LGBUF_CORE2	0x20
-#define RADIO_2055_PWRDET_RXTX_CORE2	0x21
-#define RADIO_2055_RRCCAL_CNTRL_SPARE	0x22
-#define RADIO_2055_RRCCAL_N_OPT_SEL	0x23
-#define RADIO_2055_CAL_MISC		0x24
-#define RADIO_2055_CAL_COUNTER_OUT	0x25
-#define RADIO_2055_CAL_COUNTER_OUT2	0x26
-#define RADIO_2055_CAL_CVAR_CNTRL	0x27
-#define RADIO_2055_CAL_RVAR_CNTRL	0x28
-#define RADIO_2055_CAL_LPO_CNTRL	0x29
-#define RADIO_2055_CAL_TS		0x2a
-#define RADIO_2055_CAL_RCCAL_READ_TS	0x2b
-#define RADIO_2055_CAL_RCAL_READ_TS	0x2c
-#define RADIO_2055_PAD_DRIVER		0x2d
-#define RADIO_2055_XO_CNTRL1		0x2e
-#define RADIO_2055_XO_CNTRL2		0x2f
-#define RADIO_2055_XO_REGULATOR		0x30
-#define RADIO_2055_XO_MISC		0x31
-#define RADIO_2055_PLL_LF_C1		0x32
-#define RADIO_2055_PLL_CAL_VTH		0x33
-#define RADIO_2055_PLL_LF_C2		0x34
-#define RADIO_2055_PLL_REF		0x35
-#define RADIO_2055_PLL_LF_R1		0x36
-#define RADIO_2055_PLL_PFD_CP		0x37
-#define RADIO_2055_PLL_IDAC_CPOPAMP	0x38
-#define RADIO_2055_PLL_CP_REGULATOR	0x39
-#define RADIO_2055_PLL_RCAL		0x3a
-#define RADIO_2055_RF_PLL_MOD0		0x3b
-#define RADIO_2055_RF_PLL_MOD1		0x3c
-#define RADIO_2055_RF_MMD_IDAC1		0x3d
-#define RADIO_2055_RF_MMD_IDAC0		0x3e
-#define RADIO_2055_RF_MMD_SPARE		0x3f
-#define RADIO_2055_VCO_CAL1		0x40
-#define RADIO_2055_VCO_CAL2		0x41
-#define RADIO_2055_VCO_CAL3		0x42
-#define RADIO_2055_VCO_CAL4		0x43
-#define RADIO_2055_VCO_CAL5		0x44
-#define RADIO_2055_VCO_CAL6		0x45
-#define RADIO_2055_VCO_CAL7		0x46
-#define RADIO_2055_VCO_CAL8		0x47
-#define RADIO_2055_VCO_CAL9		0x48
-#define RADIO_2055_VCO_CAL10		0x49
-#define RADIO_2055_VCO_CAL11		0x4a
-#define RADIO_2055_VCO_CAL12		0x4b
-#define RADIO_2055_VCO_CAL13		0x4c
-#define RADIO_2055_VCO_CAL14		0x4d
-#define RADIO_2055_VCO_CAL15		0x4e
-#define RADIO_2055_VCO_CAL16		0x4f
-#define RADIO_2055_VCO_KVCO		0x50
-#define RADIO_2055_VCO_CAP_TAIL		0x51
-#define RADIO_2055_VCO_IDAC_VCO		0x52
-#define RADIO_2055_VCO_REGULATOR	0x53
-#define RADIO_2055_PLL_RF_VTH		0x54
-#define RADIO_2055_LGBUF_CEN_BUF	0x55
-#define RADIO_2055_LGEN_TUNE1		0x56
-#define RADIO_2055_LGEN_TUNE2		0x57
-#define RADIO_2055_LGEN_IDAC1		0x58
-#define RADIO_2055_LGEN_IDAC2		0x59
-#define RADIO_2055_LGEN_BIAS_CNT	0x5a
-#define RADIO_2055_LGEN_BIAS_IDAC	0x5b
-#define RADIO_2055_LGEN_RCAL		0x5c
-#define RADIO_2055_LGEN_DIV		0x5d
-#define RADIO_2055_LGEN_SPARE2		0x5e
-#define RADIO_2055_CORE1_LGBUF_A_TUNE	0x5f
-#define RADIO_2055_CORE1_LGBUF_G_TUNE	0x60
-#define RADIO_2055_CORE1_LGBUF_DIV	0x61
-#define RADIO_2055_CORE1_LGBUF_A_IDAC	0x62
-#define RADIO_2055_CORE1_LGBUF_G_IDAC	0x63
-#define RADIO_2055_CORE1_LGBUF_IDACFIL_OVR 0x64
-#define RADIO_2055_CORE1_LGBUF_SPARE	0x65
-#define RADIO_2055_CORE1_RXRF_SPC1	0x66
-#define RADIO_2055_CORE1_RXRF_REG1	0x67
-#define RADIO_2055_CORE1_RXRF_REG2	0x68
-#define RADIO_2055_CORE1_RXRF_RCAL	0x69
-#define RADIO_2055_CORE1_RXBB_BUFI_LPFCMP 0x6a
-#define RADIO_2055_CORE1_RXBB_LPF	0x6b
-#define RADIO_2055_CORE1_RXBB_MIDAC_HIPAS 0x6c
-#define RADIO_2055_CORE1_RXBB_VGA1_IDAC	0x6d
-#define RADIO_2055_CORE1_RXBB_VGA2_IDAC	0x6e
-#define RADIO_2055_CORE1_RXBB_VGA3_IDAC	0x6f
-#define RADIO_2055_CORE1_RXBB_BUFO_CTRL	0x70
-#define RADIO_2055_CORE1_RXBB_RCCAL_CTRL 0x71
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL1 0x72
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL2 0x73
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL3 0x74
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL4 0x75
-#define RADIO_2055_CORE1_RXBB_RSSI_CTRL5 0x76
-#define RADIO_2055_CORE1_RXBB_REGULATOR	0x77
-#define RADIO_2055_CORE1_RXBB_SPARE1	0x78
-#define RADIO_2055_CORE1_RXTXBB_RCAL	0x79
-#define RADIO_2055_CORE1_TXRF_SGM_PGA	0x7a
-#define RADIO_2055_CORE1_TXRF_SGM_PAD	0x7b
-#define RADIO_2055_CORE1_TXRF_CNTR_PGA1	0x7c
-#define RADIO_2055_CORE1_TXRF_CNTR_PAD1	0x7d
-#define RADIO_2055_CORE1_TX_RFPGA_IDAC	0x7e
-#define RADIO_2055_CORE1_TX_PGA_PAD_TN	0x7f
-#define RADIO_2055_CORE1_TX_PAD_IDAC1	0x80
-#define RADIO_2055_CORE1_TX_PAD_IDAC2	0x81
-#define RADIO_2055_CORE1_TX_MX_BGTRIM	0x82
-#define RADIO_2055_CORE1_TXRF_RCAL	0x83
-#define RADIO_2055_CORE1_TXRF_PAD_TSSI1	0x84
-#define RADIO_2055_CORE1_TXRF_PAD_TSSI2	0x85
-#define RADIO_2055_CORE1_TX_RF_SPARE	0x86
-#define RADIO_2055_CORE1_TXRF_IQCAL1	0x87
-#define RADIO_2055_CORE1_TXRF_IQCAL2	0x88
-#define RADIO_2055_CORE1_TXBB_RCCAL_CTRL 0x89
-#define RADIO_2055_CORE1_TXBB_LPF1	0x8a
-#define RADIO_2055_CORE1_TX_VOS_CNCL	0x8b
-#define RADIO_2055_CORE1_TX_LPF_MXGM_IDAC 0x8c
-#define RADIO_2055_CORE1_TX_BB_MXGM	0x8d
-#define RADIO_2055_CORE2_LGBUF_A_TUNE	0x8e
-#define RADIO_2055_CORE2_LGBUF_G_TUNE	0x8f
-#define RADIO_2055_CORE2_LGBUF_DIV	0x90
-#define RADIO_2055_CORE2_LGBUF_A_IDAC	0x91
-#define RADIO_2055_CORE2_LGBUF_G_IDAC	0x92
-#define RADIO_2055_CORE2_LGBUF_IDACFIL_OVR 0x93
-#define RADIO_2055_CORE2_LGBUF_SPARE	0x94
-#define RADIO_2055_CORE2_RXRF_SPC1	0x95
-#define RADIO_2055_CORE2_RXRF_REG1	0x96
-#define RADIO_2055_CORE2_RXRF_REG2	0x97
-#define RADIO_2055_CORE2_RXRF_RCAL	0x98
-#define RADIO_2055_CORE2_RXBB_BUFI_LPFCMP 0x99
-#define RADIO_2055_CORE2_RXBB_LPF	0x9a
-#define RADIO_2055_CORE2_RXBB_MIDAC_HIPAS 0x9b
-#define RADIO_2055_CORE2_RXBB_VGA1_IDAC	0x9c
-#define RADIO_2055_CORE2_RXBB_VGA2_IDAC	0x9d
-#define RADIO_2055_CORE2_RXBB_VGA3_IDAC	0x9e
-#define RADIO_2055_CORE2_RXBB_BUFO_CTRL	0x9f
-#define RADIO_2055_CORE2_RXBB_RCCAL_CTRL 0xa0
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL1 0xa1
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL2 0xa2
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL3 0xa3
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL4 0xa4
-#define RADIO_2055_CORE2_RXBB_RSSI_CTRL5 0xa5
-#define RADIO_2055_CORE2_RXBB_REGULATOR	0xa6
-#define RADIO_2055_CORE2_RXBB_SPARE1	0xa7
-#define RADIO_2055_CORE2_RXTXBB_RCAL	0xa8
-#define RADIO_2055_CORE2_TXRF_SGM_PGA	0xa9
-#define RADIO_2055_CORE2_TXRF_SGM_PAD	0xaa
-#define RADIO_2055_CORE2_TXRF_CNTR_PGA1	0xab
-#define RADIO_2055_CORE2_TXRF_CNTR_PAD1	0xac
-#define RADIO_2055_CORE2_TX_RFPGA_IDAC	0xad
-#define RADIO_2055_CORE2_TX_PGA_PAD_TN	0xae
-#define RADIO_2055_CORE2_TX_PAD_IDAC1	0xaf
-#define RADIO_2055_CORE2_TX_PAD_IDAC2	0xb0
-#define RADIO_2055_CORE2_TX_MX_BGTRIM	0xb1
-#define RADIO_2055_CORE2_TXRF_RCAL	0xb2
-#define RADIO_2055_CORE2_TXRF_PAD_TSSI1	0xb3
-#define RADIO_2055_CORE2_TXRF_PAD_TSSI2	0xb4
-#define RADIO_2055_CORE2_TX_RF_SPARE	0xb5
-#define RADIO_2055_CORE2_TXRF_IQCAL1	0xb6
-#define RADIO_2055_CORE2_TXRF_IQCAL2	0xb7
-#define RADIO_2055_CORE2_TXBB_RCCAL_CTRL 0xb8
-#define RADIO_2055_CORE2_TXBB_LPF1	0xb9
-#define RADIO_2055_CORE2_TX_VOS_CNCL	0xba
-#define RADIO_2055_CORE2_TX_LPF_MXGM_IDAC 0xbb
-#define RADIO_2055_CORE2_TX_BB_MXGM	0xbc
-#define RADIO_2055_PRG_GC_HPVGA23_21	0xbd
-#define RADIO_2055_PRG_GC_HPVGA23_22	0xbe
-#define RADIO_2055_PRG_GC_HPVGA23_23	0xbf
-#define RADIO_2055_PRG_GC_HPVGA23_24	0xc0
-#define RADIO_2055_PRG_GC_HPVGA23_25	0xc1
-#define RADIO_2055_PRG_GC_HPVGA23_26	0xc2
-#define RADIO_2055_PRG_GC_HPVGA23_27	0xc3
-#define RADIO_2055_PRG_GC_HPVGA23_28	0xc4
-#define RADIO_2055_PRG_GC_HPVGA23_29	0xc5
-#define RADIO_2055_PRG_GC_HPVGA23_30	0xc6
-#define RADIO_2055_CORE1_LNA_GAINBST	0xcd
-#define RADIO_2055_CORE1_B0_NBRSSI_VCM	0xd2
-#define RADIO_2055_CORE1_GEN_SPARE2		0xd6
-#define RADIO_2055_CORE2_LNA_GAINBST	0xd9
-#define RADIO_2055_CORE2_B0_NBRSSI_VCM	0xde
-#define RADIO_2055_CORE2_GEN_SPARE2		0xe2
-
-#define RADIO_2055_GAINBST_GAIN_DB	6
-#define RADIO_2055_GAINBST_CODE		0x6
-
-#define RADIO_2055_JTAGCTRL_MASK	0x04
-#define RADIO_2055_JTAGSYNC_MASK	0x08
-#define RADIO_2055_RRCAL_START		0x40
-#define RADIO_2055_RRCAL_RST_N		0x01
-#define RADIO_2055_CAL_LPO_ENABLE	0x80
-#define RADIO_2055_RCAL_DONE		0x80
-#define RADIO_2055_NBRSSI_VCM_I_MASK	0x03
-#define RADIO_2055_NBRSSI_VCM_I_SHIFT	0x00
-#define RADIO_2055_NBRSSI_VCM_Q_MASK	0x03
-#define RADIO_2055_NBRSSI_VCM_Q_SHIFT	0x00
-#define RADIO_2055_WBRSSI_VCM_IQ_MASK	0x0c
-#define RADIO_2055_WBRSSI_VCM_IQ_SHIFT	0x02
-#define RADIO_2055_NBRSSI_PD		0x01
-#define RADIO_2055_WBRSSI_G1_PD		0x04
-#define RADIO_2055_WBRSSI_G2_PD		0x02
-#define RADIO_2055_NBRSSI_SEL		0x01
-#define RADIO_2055_WBRSSI_G1_SEL	0x04
-#define RADIO_2055_WBRSSI_G2_SEL	0x02
-#define RADIO_2055_COUPLE_RX_MASK	0x01
-#define RADIO_2055_COUPLE_TX_MASK	0x02
-#define RADIO_2055_GAINBST_DISABLE	0x02
-#define RADIO_2055_GAINBST_VAL_MASK	0x07
-#define RADIO_2055_RXMX_GC_MASK		0x0c
-
-#define RADIO_MIMO_CORESEL_OFF		0x0
-#define RADIO_MIMO_CORESEL_CORE1	0x1
-#define RADIO_MIMO_CORESEL_CORE2	0x2
-#define RADIO_MIMO_CORESEL_CORE3	0x3
-#define RADIO_MIMO_CORESEL_CORE4	0x4
-#define RADIO_MIMO_CORESEL_ALLRX	0x5
-#define RADIO_MIMO_CORESEL_ALLTX	0x6
-#define RADIO_MIMO_CORESEL_ALLRXTX	0x7
-
-#define	RADIO_2064_READ_OFF		0x200
-
-#define RADIO_2064_REG000               0x0
-#define RADIO_2064_REG001               0x1
-#define RADIO_2064_REG002               0x2
-#define RADIO_2064_REG003               0x3
-#define RADIO_2064_REG004               0x4
-#define RADIO_2064_REG005               0x5
-#define RADIO_2064_REG006               0x6
-#define RADIO_2064_REG007               0x7
-#define RADIO_2064_REG008               0x8
-#define RADIO_2064_REG009               0x9
-#define RADIO_2064_REG00A               0xa
-#define RADIO_2064_REG00B               0xb
-#define RADIO_2064_REG00C               0xc
-#define RADIO_2064_REG00D               0xd
-#define RADIO_2064_REG00E               0xe
-#define RADIO_2064_REG00F               0xf
-#define RADIO_2064_REG010               0x10
-#define RADIO_2064_REG011               0x11
-#define RADIO_2064_REG012               0x12
-#define RADIO_2064_REG013               0x13
-#define RADIO_2064_REG014               0x14
-#define RADIO_2064_REG015               0x15
-#define RADIO_2064_REG016               0x16
-#define RADIO_2064_REG017               0x17
-#define RADIO_2064_REG018               0x18
-#define RADIO_2064_REG019               0x19
-#define RADIO_2064_REG01A               0x1a
-#define RADIO_2064_REG01B               0x1b
-#define RADIO_2064_REG01C               0x1c
-#define RADIO_2064_REG01D               0x1d
-#define RADIO_2064_REG01E               0x1e
-#define RADIO_2064_REG01F               0x1f
-#define RADIO_2064_REG020               0x20
-#define RADIO_2064_REG021               0x21
-#define RADIO_2064_REG022               0x22
-#define RADIO_2064_REG023               0x23
-#define RADIO_2064_REG024               0x24
-#define RADIO_2064_REG025               0x25
-#define RADIO_2064_REG026               0x26
-#define RADIO_2064_REG027               0x27
-#define RADIO_2064_REG028               0x28
-#define RADIO_2064_REG029               0x29
-#define RADIO_2064_REG02A               0x2a
-#define RADIO_2064_REG02B               0x2b
-#define RADIO_2064_REG02C               0x2c
-#define RADIO_2064_REG02D               0x2d
-#define RADIO_2064_REG02E               0x2e
-#define RADIO_2064_REG02F               0x2f
-#define RADIO_2064_REG030               0x30
-#define RADIO_2064_REG031               0x31
-#define RADIO_2064_REG032               0x32
-#define RADIO_2064_REG033               0x33
-#define RADIO_2064_REG034               0x34
-#define RADIO_2064_REG035               0x35
-#define RADIO_2064_REG036               0x36
-#define RADIO_2064_REG037               0x37
-#define RADIO_2064_REG038               0x38
-#define RADIO_2064_REG039               0x39
-#define RADIO_2064_REG03A               0x3a
-#define RADIO_2064_REG03B               0x3b
-#define RADIO_2064_REG03C               0x3c
-#define RADIO_2064_REG03D               0x3d
-#define RADIO_2064_REG03E               0x3e
-#define RADIO_2064_REG03F               0x3f
-#define RADIO_2064_REG040               0x40
-#define RADIO_2064_REG041               0x41
-#define RADIO_2064_REG042               0x42
-#define RADIO_2064_REG043               0x43
-#define RADIO_2064_REG044               0x44
-#define RADIO_2064_REG045               0x45
-#define RADIO_2064_REG046               0x46
-#define RADIO_2064_REG047               0x47
-#define RADIO_2064_REG048               0x48
-#define RADIO_2064_REG049               0x49
-#define RADIO_2064_REG04A               0x4a
-#define RADIO_2064_REG04B               0x4b
-#define RADIO_2064_REG04C               0x4c
-#define RADIO_2064_REG04D               0x4d
-#define RADIO_2064_REG04E               0x4e
-#define RADIO_2064_REG04F               0x4f
-#define RADIO_2064_REG050               0x50
-#define RADIO_2064_REG051               0x51
-#define RADIO_2064_REG052               0x52
-#define RADIO_2064_REG053               0x53
-#define RADIO_2064_REG054               0x54
-#define RADIO_2064_REG055               0x55
-#define RADIO_2064_REG056               0x56
-#define RADIO_2064_REG057               0x57
-#define RADIO_2064_REG058               0x58
-#define RADIO_2064_REG059               0x59
-#define RADIO_2064_REG05A               0x5a
-#define RADIO_2064_REG05B               0x5b
-#define RADIO_2064_REG05C               0x5c
-#define RADIO_2064_REG05D               0x5d
-#define RADIO_2064_REG05E               0x5e
-#define RADIO_2064_REG05F               0x5f
-#define RADIO_2064_REG060               0x60
-#define RADIO_2064_REG061               0x61
-#define RADIO_2064_REG062               0x62
-#define RADIO_2064_REG063               0x63
-#define RADIO_2064_REG064               0x64
-#define RADIO_2064_REG065               0x65
-#define RADIO_2064_REG066               0x66
-#define RADIO_2064_REG067               0x67
-#define RADIO_2064_REG068               0x68
-#define RADIO_2064_REG069               0x69
-#define RADIO_2064_REG06A               0x6a
-#define RADIO_2064_REG06B               0x6b
-#define RADIO_2064_REG06C               0x6c
-#define RADIO_2064_REG06D               0x6d
-#define RADIO_2064_REG06E               0x6e
-#define RADIO_2064_REG06F               0x6f
-#define RADIO_2064_REG070               0x70
-#define RADIO_2064_REG071               0x71
-#define RADIO_2064_REG072               0x72
-#define RADIO_2064_REG073               0x73
-#define RADIO_2064_REG074               0x74
-#define RADIO_2064_REG075               0x75
-#define RADIO_2064_REG076               0x76
-#define RADIO_2064_REG077               0x77
-#define RADIO_2064_REG078               0x78
-#define RADIO_2064_REG079               0x79
-#define RADIO_2064_REG07A               0x7a
-#define RADIO_2064_REG07B               0x7b
-#define RADIO_2064_REG07C               0x7c
-#define RADIO_2064_REG07D               0x7d
-#define RADIO_2064_REG07E               0x7e
-#define RADIO_2064_REG07F               0x7f
-#define RADIO_2064_REG080               0x80
-#define RADIO_2064_REG081               0x81
-#define RADIO_2064_REG082               0x82
-#define RADIO_2064_REG083               0x83
-#define RADIO_2064_REG084               0x84
-#define RADIO_2064_REG085               0x85
-#define RADIO_2064_REG086               0x86
-#define RADIO_2064_REG087               0x87
-#define RADIO_2064_REG088               0x88
-#define RADIO_2064_REG089               0x89
-#define RADIO_2064_REG08A               0x8a
-#define RADIO_2064_REG08B               0x8b
-#define RADIO_2064_REG08C               0x8c
-#define RADIO_2064_REG08D               0x8d
-#define RADIO_2064_REG08E               0x8e
-#define RADIO_2064_REG08F               0x8f
-#define RADIO_2064_REG090               0x90
-#define RADIO_2064_REG091               0x91
-#define RADIO_2064_REG092               0x92
-#define RADIO_2064_REG093               0x93
-#define RADIO_2064_REG094               0x94
-#define RADIO_2064_REG095               0x95
-#define RADIO_2064_REG096               0x96
-#define RADIO_2064_REG097               0x97
-#define RADIO_2064_REG098               0x98
-#define RADIO_2064_REG099               0x99
-#define RADIO_2064_REG09A               0x9a
-#define RADIO_2064_REG09B               0x9b
-#define RADIO_2064_REG09C               0x9c
-#define RADIO_2064_REG09D               0x9d
-#define RADIO_2064_REG09E               0x9e
-#define RADIO_2064_REG09F               0x9f
-#define RADIO_2064_REG0A0               0xa0
-#define RADIO_2064_REG0A1               0xa1
-#define RADIO_2064_REG0A2               0xa2
-#define RADIO_2064_REG0A3               0xa3
-#define RADIO_2064_REG0A4               0xa4
-#define RADIO_2064_REG0A5               0xa5
-#define RADIO_2064_REG0A6               0xa6
-#define RADIO_2064_REG0A7               0xa7
-#define RADIO_2064_REG0A8               0xa8
-#define RADIO_2064_REG0A9               0xa9
-#define RADIO_2064_REG0AA               0xaa
-#define RADIO_2064_REG0AB               0xab
-#define RADIO_2064_REG0AC               0xac
-#define RADIO_2064_REG0AD               0xad
-#define RADIO_2064_REG0AE               0xae
-#define RADIO_2064_REG0AF               0xaf
-#define RADIO_2064_REG0B0               0xb0
-#define RADIO_2064_REG0B1               0xb1
-#define RADIO_2064_REG0B2               0xb2
-#define RADIO_2064_REG0B3               0xb3
-#define RADIO_2064_REG0B4               0xb4
-#define RADIO_2064_REG0B5               0xb5
-#define RADIO_2064_REG0B6               0xb6
-#define RADIO_2064_REG0B7               0xb7
-#define RADIO_2064_REG0B8               0xb8
-#define RADIO_2064_REG0B9               0xb9
-#define RADIO_2064_REG0BA               0xba
-#define RADIO_2064_REG0BB               0xbb
-#define RADIO_2064_REG0BC               0xbc
-#define RADIO_2064_REG0BD               0xbd
-#define RADIO_2064_REG0BE               0xbe
-#define RADIO_2064_REG0BF               0xbf
-#define RADIO_2064_REG0C0               0xc0
-#define RADIO_2064_REG0C1               0xc1
-#define RADIO_2064_REG0C2               0xc2
-#define RADIO_2064_REG0C3               0xc3
-#define RADIO_2064_REG0C4               0xc4
-#define RADIO_2064_REG0C5               0xc5
-#define RADIO_2064_REG0C6               0xc6
-#define RADIO_2064_REG0C7               0xc7
-#define RADIO_2064_REG0C8               0xc8
-#define RADIO_2064_REG0C9               0xc9
-#define RADIO_2064_REG0CA               0xca
-#define RADIO_2064_REG0CB               0xcb
-#define RADIO_2064_REG0CC               0xcc
-#define RADIO_2064_REG0CD               0xcd
-#define RADIO_2064_REG0CE               0xce
-#define RADIO_2064_REG0CF               0xcf
-#define RADIO_2064_REG0D0               0xd0
-#define RADIO_2064_REG0D1               0xd1
-#define RADIO_2064_REG0D2               0xd2
-#define RADIO_2064_REG0D3               0xd3
-#define RADIO_2064_REG0D4               0xd4
-#define RADIO_2064_REG0D5               0xd5
-#define RADIO_2064_REG0D6               0xd6
-#define RADIO_2064_REG0D7               0xd7
-#define RADIO_2064_REG0D8               0xd8
-#define RADIO_2064_REG0D9               0xd9
-#define RADIO_2064_REG0DA               0xda
-#define RADIO_2064_REG0DB               0xdb
-#define RADIO_2064_REG0DC               0xdc
-#define RADIO_2064_REG0DD               0xdd
-#define RADIO_2064_REG0DE               0xde
-#define RADIO_2064_REG0DF               0xdf
-#define RADIO_2064_REG0E0               0xe0
-#define RADIO_2064_REG0E1               0xe1
-#define RADIO_2064_REG0E2               0xe2
-#define RADIO_2064_REG0E3               0xe3
-#define RADIO_2064_REG0E4               0xe4
-#define RADIO_2064_REG0E5               0xe5
-#define RADIO_2064_REG0E6               0xe6
-#define RADIO_2064_REG0E7               0xe7
-#define RADIO_2064_REG0E8               0xe8
-#define RADIO_2064_REG0E9               0xe9
-#define RADIO_2064_REG0EA               0xea
-#define RADIO_2064_REG0EB               0xeb
-#define RADIO_2064_REG0EC               0xec
-#define RADIO_2064_REG0ED               0xed
-#define RADIO_2064_REG0EE               0xee
-#define RADIO_2064_REG0EF               0xef
-#define RADIO_2064_REG0F0               0xf0
-#define RADIO_2064_REG0F1               0xf1
-#define RADIO_2064_REG0F2               0xf2
-#define RADIO_2064_REG0F3               0xf3
-#define RADIO_2064_REG0F4               0xf4
-#define RADIO_2064_REG0F5               0xf5
-#define RADIO_2064_REG0F6               0xf6
-#define RADIO_2064_REG0F7               0xf7
-#define RADIO_2064_REG0F8               0xf8
-#define RADIO_2064_REG0F9               0xf9
-#define RADIO_2064_REG0FA               0xfa
-#define RADIO_2064_REG0FB               0xfb
-#define RADIO_2064_REG0FC               0xfc
-#define RADIO_2064_REG0FD               0xfd
-#define RADIO_2064_REG0FE               0xfe
-#define RADIO_2064_REG0FF               0xff
-#define RADIO_2064_REG100               0x100
-#define RADIO_2064_REG101               0x101
-#define RADIO_2064_REG102               0x102
-#define RADIO_2064_REG103               0x103
-#define RADIO_2064_REG104               0x104
-#define RADIO_2064_REG105               0x105
-#define RADIO_2064_REG106               0x106
-#define RADIO_2064_REG107               0x107
-#define RADIO_2064_REG108               0x108
-#define RADIO_2064_REG109               0x109
-#define RADIO_2064_REG10A               0x10a
-#define RADIO_2064_REG10B               0x10b
-#define RADIO_2064_REG10C               0x10c
-#define RADIO_2064_REG10D               0x10d
-#define RADIO_2064_REG10E               0x10e
-#define RADIO_2064_REG10F               0x10f
-#define RADIO_2064_REG110               0x110
-#define RADIO_2064_REG111               0x111
-#define RADIO_2064_REG112               0x112
-#define RADIO_2064_REG113               0x113
-#define RADIO_2064_REG114               0x114
-#define RADIO_2064_REG115               0x115
-#define RADIO_2064_REG116               0x116
-#define RADIO_2064_REG117               0x117
-#define RADIO_2064_REG118               0x118
-#define RADIO_2064_REG119               0x119
-#define RADIO_2064_REG11A               0x11a
-#define RADIO_2064_REG11B               0x11b
-#define RADIO_2064_REG11C               0x11c
-#define RADIO_2064_REG11D               0x11d
-#define RADIO_2064_REG11E               0x11e
-#define RADIO_2064_REG11F               0x11f
-#define RADIO_2064_REG120               0x120
-#define RADIO_2064_REG121               0x121
-#define RADIO_2064_REG122               0x122
-#define RADIO_2064_REG123               0x123
-#define RADIO_2064_REG124               0x124
-#define RADIO_2064_REG125               0x125
-#define RADIO_2064_REG126               0x126
-#define RADIO_2064_REG127               0x127
-#define RADIO_2064_REG128               0x128
-#define RADIO_2064_REG129               0x129
-#define RADIO_2064_REG12A               0x12a
-#define RADIO_2064_REG12B               0x12b
-#define RADIO_2064_REG12C               0x12c
-#define RADIO_2064_REG12D               0x12d
-#define RADIO_2064_REG12E               0x12e
-#define RADIO_2064_REG12F               0x12f
-#define RADIO_2064_REG130               0x130
-
-#define RADIO_2056_SYN                           (0x0 << 12)
-#define RADIO_2056_TX0                           (0x2 << 12)
-#define RADIO_2056_TX1                           (0x3 << 12)
-#define RADIO_2056_RX0                           (0x6 << 12)
-#define RADIO_2056_RX1                           (0x7 << 12)
-#define RADIO_2056_ALLTX                         (0xe << 12)
-#define RADIO_2056_ALLRX                         (0xf << 12)
-
-#define RADIO_2056_SYN_RESERVED_ADDR0            0x0
-#define RADIO_2056_SYN_IDCODE                    0x1
-#define RADIO_2056_SYN_RESERVED_ADDR2            0x2
-#define RADIO_2056_SYN_RESERVED_ADDR3            0x3
-#define RADIO_2056_SYN_RESERVED_ADDR4            0x4
-#define RADIO_2056_SYN_RESERVED_ADDR5            0x5
-#define RADIO_2056_SYN_RESERVED_ADDR6            0x6
-#define RADIO_2056_SYN_RESERVED_ADDR7            0x7
-#define RADIO_2056_SYN_COM_CTRL                  0x8
-#define RADIO_2056_SYN_COM_PU                    0x9
-#define RADIO_2056_SYN_COM_OVR                   0xa
-#define RADIO_2056_SYN_COM_RESET                 0xb
-#define RADIO_2056_SYN_COM_RCAL                  0xc
-#define RADIO_2056_SYN_COM_RC_RXLPF              0xd
-#define RADIO_2056_SYN_COM_RC_TXLPF              0xe
-#define RADIO_2056_SYN_COM_RC_RXHPF              0xf
-#define RADIO_2056_SYN_RESERVED_ADDR16           0x10
-#define RADIO_2056_SYN_RESERVED_ADDR17           0x11
-#define RADIO_2056_SYN_RESERVED_ADDR18           0x12
-#define RADIO_2056_SYN_RESERVED_ADDR19           0x13
-#define RADIO_2056_SYN_RESERVED_ADDR20           0x14
-#define RADIO_2056_SYN_RESERVED_ADDR21           0x15
-#define RADIO_2056_SYN_RESERVED_ADDR22           0x16
-#define RADIO_2056_SYN_RESERVED_ADDR23           0x17
-#define RADIO_2056_SYN_RESERVED_ADDR24           0x18
-#define RADIO_2056_SYN_RESERVED_ADDR25           0x19
-#define RADIO_2056_SYN_RESERVED_ADDR26           0x1a
-#define RADIO_2056_SYN_RESERVED_ADDR27           0x1b
-#define RADIO_2056_SYN_RESERVED_ADDR28           0x1c
-#define RADIO_2056_SYN_RESERVED_ADDR29           0x1d
-#define RADIO_2056_SYN_RESERVED_ADDR30           0x1e
-#define RADIO_2056_SYN_RESERVED_ADDR31           0x1f
-#define RADIO_2056_SYN_GPIO_MASTER1              0x20
-#define RADIO_2056_SYN_GPIO_MASTER2              0x21
-#define RADIO_2056_SYN_TOPBIAS_MASTER            0x22
-#define RADIO_2056_SYN_TOPBIAS_RCAL              0x23
-#define RADIO_2056_SYN_AFEREG                    0x24
-#define RADIO_2056_SYN_TEMPPROCSENSE             0x25
-#define RADIO_2056_SYN_TEMPPROCSENSEIDAC         0x26
-#define RADIO_2056_SYN_TEMPPROCSENSERCAL         0x27
-#define RADIO_2056_SYN_LPO                       0x28
-#define RADIO_2056_SYN_VDDCAL_MASTER             0x29
-#define RADIO_2056_SYN_VDDCAL_IDAC               0x2a
-#define RADIO_2056_SYN_VDDCAL_STATUS             0x2b
-#define RADIO_2056_SYN_RCAL_MASTER               0x2c
-#define RADIO_2056_SYN_RCAL_CODE_OUT             0x2d
-#define RADIO_2056_SYN_RCCAL_CTRL0               0x2e
-#define RADIO_2056_SYN_RCCAL_CTRL1               0x2f
-#define RADIO_2056_SYN_RCCAL_CTRL2               0x30
-#define RADIO_2056_SYN_RCCAL_CTRL3               0x31
-#define RADIO_2056_SYN_RCCAL_CTRL4               0x32
-#define RADIO_2056_SYN_RCCAL_CTRL5               0x33
-#define RADIO_2056_SYN_RCCAL_CTRL6               0x34
-#define RADIO_2056_SYN_RCCAL_CTRL7               0x35
-#define RADIO_2056_SYN_RCCAL_CTRL8               0x36
-#define RADIO_2056_SYN_RCCAL_CTRL9               0x37
-#define RADIO_2056_SYN_RCCAL_CTRL10              0x38
-#define RADIO_2056_SYN_RCCAL_CTRL11              0x39
-#define RADIO_2056_SYN_ZCAL_SPARE1               0x3a
-#define RADIO_2056_SYN_ZCAL_SPARE2               0x3b
-#define RADIO_2056_SYN_PLL_MAST1                 0x3c
-#define RADIO_2056_SYN_PLL_MAST2                 0x3d
-#define RADIO_2056_SYN_PLL_MAST3                 0x3e
-#define RADIO_2056_SYN_PLL_BIAS_RESET            0x3f
-#define RADIO_2056_SYN_PLL_XTAL0                 0x40
-#define RADIO_2056_SYN_PLL_XTAL1                 0x41
-#define RADIO_2056_SYN_PLL_XTAL3                 0x42
-#define RADIO_2056_SYN_PLL_XTAL4                 0x43
-#define RADIO_2056_SYN_PLL_XTAL5                 0x44
-#define RADIO_2056_SYN_PLL_XTAL6                 0x45
-#define RADIO_2056_SYN_PLL_REFDIV                0x46
-#define RADIO_2056_SYN_PLL_PFD                   0x47
-#define RADIO_2056_SYN_PLL_CP1                   0x48
-#define RADIO_2056_SYN_PLL_CP2                   0x49
-#define RADIO_2056_SYN_PLL_CP3                   0x4a
-#define RADIO_2056_SYN_PLL_LOOPFILTER1           0x4b
-#define RADIO_2056_SYN_PLL_LOOPFILTER2           0x4c
-#define RADIO_2056_SYN_PLL_LOOPFILTER3           0x4d
-#define RADIO_2056_SYN_PLL_LOOPFILTER4           0x4e
-#define RADIO_2056_SYN_PLL_LOOPFILTER5           0x4f
-#define RADIO_2056_SYN_PLL_MMD1                  0x50
-#define RADIO_2056_SYN_PLL_MMD2                  0x51
-#define RADIO_2056_SYN_PLL_VCO1                  0x52
-#define RADIO_2056_SYN_PLL_VCO2                  0x53
-#define RADIO_2056_SYN_PLL_MONITOR1              0x54
-#define RADIO_2056_SYN_PLL_MONITOR2              0x55
-#define RADIO_2056_SYN_PLL_VCOCAL1               0x56
-#define RADIO_2056_SYN_PLL_VCOCAL2               0x57
-#define RADIO_2056_SYN_PLL_VCOCAL4               0x58
-#define RADIO_2056_SYN_PLL_VCOCAL5               0x59
-#define RADIO_2056_SYN_PLL_VCOCAL6               0x5a
-#define RADIO_2056_SYN_PLL_VCOCAL7               0x5b
-#define RADIO_2056_SYN_PLL_VCOCAL8               0x5c
-#define RADIO_2056_SYN_PLL_VCOCAL9               0x5d
-#define RADIO_2056_SYN_PLL_VCOCAL10              0x5e
-#define RADIO_2056_SYN_PLL_VCOCAL11              0x5f
-#define RADIO_2056_SYN_PLL_VCOCAL12              0x60
-#define RADIO_2056_SYN_PLL_VCOCAL13              0x61
-#define RADIO_2056_SYN_PLL_VREG                  0x62
-#define RADIO_2056_SYN_PLL_STATUS1               0x63
-#define RADIO_2056_SYN_PLL_STATUS2               0x64
-#define RADIO_2056_SYN_PLL_STATUS3               0x65
-#define RADIO_2056_SYN_LOGEN_PU0                 0x66
-#define RADIO_2056_SYN_LOGEN_PU1                 0x67
-#define RADIO_2056_SYN_LOGEN_PU2                 0x68
-#define RADIO_2056_SYN_LOGEN_PU3                 0x69
-#define RADIO_2056_SYN_LOGEN_PU5                 0x6a
-#define RADIO_2056_SYN_LOGEN_PU6                 0x6b
-#define RADIO_2056_SYN_LOGEN_PU7                 0x6c
-#define RADIO_2056_SYN_LOGEN_PU8                 0x6d
-#define RADIO_2056_SYN_LOGEN_BIAS_RESET          0x6e
-#define RADIO_2056_SYN_LOGEN_RCCR1               0x6f
-#define RADIO_2056_SYN_LOGEN_VCOBUF1             0x70
-#define RADIO_2056_SYN_LOGEN_MIXER1              0x71
-#define RADIO_2056_SYN_LOGEN_MIXER2              0x72
-#define RADIO_2056_SYN_LOGEN_BUF1                0x73
-#define RADIO_2056_SYN_LOGENBUF2                 0x74
-#define RADIO_2056_SYN_LOGEN_BUF3                0x75
-#define RADIO_2056_SYN_LOGEN_BUF4                0x76
-#define RADIO_2056_SYN_LOGEN_DIV1                0x77
-#define RADIO_2056_SYN_LOGEN_DIV2                0x78
-#define RADIO_2056_SYN_LOGEN_DIV3                0x79
-#define RADIO_2056_SYN_LOGEN_ACL1                0x7a
-#define RADIO_2056_SYN_LOGEN_ACL2                0x7b
-#define RADIO_2056_SYN_LOGEN_ACL3                0x7c
-#define RADIO_2056_SYN_LOGEN_ACL4                0x7d
-#define RADIO_2056_SYN_LOGEN_ACL5                0x7e
-#define RADIO_2056_SYN_LOGEN_ACL6                0x7f
-#define RADIO_2056_SYN_LOGEN_ACLOUT              0x80
-#define RADIO_2056_SYN_LOGEN_ACLCAL1             0x81
-#define RADIO_2056_SYN_LOGEN_ACLCAL2             0x82
-#define RADIO_2056_SYN_LOGEN_ACLCAL3             0x83
-#define RADIO_2056_SYN_CALEN                     0x84
-#define RADIO_2056_SYN_LOGEN_PEAKDET1            0x85
-#define RADIO_2056_SYN_LOGEN_CORE_ACL_OVR        0x86
-#define RADIO_2056_SYN_LOGEN_RX_DIFF_ACL_OVR     0x87
-#define RADIO_2056_SYN_LOGEN_TX_DIFF_ACL_OVR     0x88
-#define RADIO_2056_SYN_LOGEN_RX_CMOS_ACL_OVR     0x89
-#define RADIO_2056_SYN_LOGEN_TX_CMOS_ACL_OVR     0x8a
-#define RADIO_2056_SYN_LOGEN_VCOBUF2             0x8b
-#define RADIO_2056_SYN_LOGEN_MIXER3              0x8c
-#define RADIO_2056_SYN_LOGEN_BUF5                0x8d
-#define RADIO_2056_SYN_LOGEN_BUF6                0x8e
-#define RADIO_2056_SYN_LOGEN_CBUFRX1             0x8f
-#define RADIO_2056_SYN_LOGEN_CBUFRX2             0x90
-#define RADIO_2056_SYN_LOGEN_CBUFRX3             0x91
-#define RADIO_2056_SYN_LOGEN_CBUFRX4             0x92
-#define RADIO_2056_SYN_LOGEN_CBUFTX1             0x93
-#define RADIO_2056_SYN_LOGEN_CBUFTX2             0x94
-#define RADIO_2056_SYN_LOGEN_CBUFTX3             0x95
-#define RADIO_2056_SYN_LOGEN_CBUFTX4             0x96
-#define RADIO_2056_SYN_LOGEN_CMOSRX1             0x97
-#define RADIO_2056_SYN_LOGEN_CMOSRX2             0x98
-#define RADIO_2056_SYN_LOGEN_CMOSRX3             0x99
-#define RADIO_2056_SYN_LOGEN_CMOSRX4             0x9a
-#define RADIO_2056_SYN_LOGEN_CMOSTX1             0x9b
-#define RADIO_2056_SYN_LOGEN_CMOSTX2             0x9c
-#define RADIO_2056_SYN_LOGEN_CMOSTX3             0x9d
-#define RADIO_2056_SYN_LOGEN_CMOSTX4             0x9e
-#define RADIO_2056_SYN_LOGEN_VCOBUF2_OVRVAL      0x9f
-#define RADIO_2056_SYN_LOGEN_MIXER3_OVRVAL       0xa0
-#define RADIO_2056_SYN_LOGEN_BUF5_OVRVAL         0xa1
-#define RADIO_2056_SYN_LOGEN_BUF6_OVRVAL         0xa2
-#define RADIO_2056_SYN_LOGEN_CBUFRX1_OVRVAL      0xa3
-#define RADIO_2056_SYN_LOGEN_CBUFRX2_OVRVAL      0xa4
-#define RADIO_2056_SYN_LOGEN_CBUFRX3_OVRVAL      0xa5
-#define RADIO_2056_SYN_LOGEN_CBUFRX4_OVRVAL      0xa6
-#define RADIO_2056_SYN_LOGEN_CBUFTX1_OVRVAL      0xa7
-#define RADIO_2056_SYN_LOGEN_CBUFTX2_OVRVAL      0xa8
-#define RADIO_2056_SYN_LOGEN_CBUFTX3_OVRVAL      0xa9
-#define RADIO_2056_SYN_LOGEN_CBUFTX4_OVRVAL      0xaa
-#define RADIO_2056_SYN_LOGEN_CMOSRX1_OVRVAL      0xab
-#define RADIO_2056_SYN_LOGEN_CMOSRX2_OVRVAL      0xac
-#define RADIO_2056_SYN_LOGEN_CMOSRX3_OVRVAL      0xad
-#define RADIO_2056_SYN_LOGEN_CMOSRX4_OVRVAL      0xae
-#define RADIO_2056_SYN_LOGEN_CMOSTX1_OVRVAL      0xaf
-#define RADIO_2056_SYN_LOGEN_CMOSTX2_OVRVAL      0xb0
-#define RADIO_2056_SYN_LOGEN_CMOSTX3_OVRVAL      0xb1
-#define RADIO_2056_SYN_LOGEN_CMOSTX4_OVRVAL      0xb2
-#define RADIO_2056_SYN_LOGEN_ACL_WAITCNT         0xb3
-#define RADIO_2056_SYN_LOGEN_CORE_CALVALID       0xb4
-#define RADIO_2056_SYN_LOGEN_RX_CMOS_CALVALID    0xb5
-#define RADIO_2056_SYN_LOGEN_TX_CMOS_VALID       0xb6
-
-#define RADIO_2056_TX_RESERVED_ADDR0             0x0
-#define RADIO_2056_TX_IDCODE                     0x1
-#define RADIO_2056_TX_RESERVED_ADDR2             0x2
-#define RADIO_2056_TX_RESERVED_ADDR3             0x3
-#define RADIO_2056_TX_RESERVED_ADDR4             0x4
-#define RADIO_2056_TX_RESERVED_ADDR5             0x5
-#define RADIO_2056_TX_RESERVED_ADDR6             0x6
-#define RADIO_2056_TX_RESERVED_ADDR7             0x7
-#define RADIO_2056_TX_COM_CTRL                   0x8
-#define RADIO_2056_TX_COM_PU                     0x9
-#define RADIO_2056_TX_COM_OVR                    0xa
-#define RADIO_2056_TX_COM_RESET                  0xb
-#define RADIO_2056_TX_COM_RCAL                   0xc
-#define RADIO_2056_TX_COM_RC_RXLPF               0xd
-#define RADIO_2056_TX_COM_RC_TXLPF               0xe
-#define RADIO_2056_TX_COM_RC_RXHPF               0xf
-#define RADIO_2056_TX_RESERVED_ADDR16            0x10
-#define RADIO_2056_TX_RESERVED_ADDR17            0x11
-#define RADIO_2056_TX_RESERVED_ADDR18            0x12
-#define RADIO_2056_TX_RESERVED_ADDR19            0x13
-#define RADIO_2056_TX_RESERVED_ADDR20            0x14
-#define RADIO_2056_TX_RESERVED_ADDR21            0x15
-#define RADIO_2056_TX_RESERVED_ADDR22            0x16
-#define RADIO_2056_TX_RESERVED_ADDR23            0x17
-#define RADIO_2056_TX_RESERVED_ADDR24            0x18
-#define RADIO_2056_TX_RESERVED_ADDR25            0x19
-#define RADIO_2056_TX_RESERVED_ADDR26            0x1a
-#define RADIO_2056_TX_RESERVED_ADDR27            0x1b
-#define RADIO_2056_TX_RESERVED_ADDR28            0x1c
-#define RADIO_2056_TX_RESERVED_ADDR29            0x1d
-#define RADIO_2056_TX_RESERVED_ADDR30            0x1e
-#define RADIO_2056_TX_RESERVED_ADDR31            0x1f
-#define RADIO_2056_TX_IQCAL_GAIN_BW              0x20
-#define RADIO_2056_TX_LOFT_FINE_I                0x21
-#define RADIO_2056_TX_LOFT_FINE_Q                0x22
-#define RADIO_2056_TX_LOFT_COARSE_I              0x23
-#define RADIO_2056_TX_LOFT_COARSE_Q              0x24
-#define RADIO_2056_TX_TX_COM_MASTER1             0x25
-#define RADIO_2056_TX_TX_COM_MASTER2             0x26
-#define RADIO_2056_TX_RXIQCAL_TXMUX              0x27
-#define RADIO_2056_TX_TX_SSI_MASTER              0x28
-#define RADIO_2056_TX_IQCAL_VCM_HG               0x29
-#define RADIO_2056_TX_IQCAL_IDAC                 0x2a
-#define RADIO_2056_TX_TSSI_VCM                   0x2b
-#define RADIO_2056_TX_TX_AMP_DET                 0x2c
-#define RADIO_2056_TX_TX_SSI_MUX                 0x2d
-#define RADIO_2056_TX_TSSIA                      0x2e
-#define RADIO_2056_TX_TSSIG                      0x2f
-#define RADIO_2056_TX_TSSI_MISC1                 0x30
-#define RADIO_2056_TX_TSSI_MISC2                 0x31
-#define RADIO_2056_TX_TSSI_MISC3                 0x32
-#define RADIO_2056_TX_PA_SPARE1                  0x33
-#define RADIO_2056_TX_PA_SPARE2                  0x34
-#define RADIO_2056_TX_INTPAA_MASTER              0x35
-#define RADIO_2056_TX_INTPAA_GAIN                0x36
-#define RADIO_2056_TX_INTPAA_BOOST_TUNE          0x37
-#define RADIO_2056_TX_INTPAA_IAUX_STAT           0x38
-#define RADIO_2056_TX_INTPAA_IAUX_DYN            0x39
-#define RADIO_2056_TX_INTPAA_IMAIN_STAT          0x3a
-#define RADIO_2056_TX_INTPAA_IMAIN_DYN           0x3b
-#define RADIO_2056_TX_INTPAA_CASCBIAS            0x3c
-#define RADIO_2056_TX_INTPAA_PASLOPE             0x3d
-#define RADIO_2056_TX_INTPAA_PA_MISC             0x3e
-#define RADIO_2056_TX_INTPAG_MASTER              0x3f
-#define RADIO_2056_TX_INTPAG_GAIN                0x40
-#define RADIO_2056_TX_INTPAG_BOOST_TUNE          0x41
-#define RADIO_2056_TX_INTPAG_IAUX_STAT           0x42
-#define RADIO_2056_TX_INTPAG_IAUX_DYN            0x43
-#define RADIO_2056_TX_INTPAG_IMAIN_STAT          0x44
-#define RADIO_2056_TX_INTPAG_IMAIN_DYN           0x45
-#define RADIO_2056_TX_INTPAG_CASCBIAS            0x46
-#define RADIO_2056_TX_INTPAG_PASLOPE             0x47
-#define RADIO_2056_TX_INTPAG_PA_MISC             0x48
-#define RADIO_2056_TX_PADA_MASTER                0x49
-#define RADIO_2056_TX_PADA_IDAC                  0x4a
-#define RADIO_2056_TX_PADA_CASCBIAS              0x4b
-#define RADIO_2056_TX_PADA_GAIN                  0x4c
-#define RADIO_2056_TX_PADA_BOOST_TUNE            0x4d
-#define RADIO_2056_TX_PADA_SLOPE                 0x4e
-#define RADIO_2056_TX_PADG_MASTER                0x4f
-#define RADIO_2056_TX_PADG_IDAC                  0x50
-#define RADIO_2056_TX_PADG_CASCBIAS              0x51
-#define RADIO_2056_TX_PADG_GAIN                  0x52
-#define RADIO_2056_TX_PADG_BOOST_TUNE            0x53
-#define RADIO_2056_TX_PADG_SLOPE                 0x54
-#define RADIO_2056_TX_PGAA_MASTER                0x55
-#define RADIO_2056_TX_PGAA_IDAC                  0x56
-#define RADIO_2056_TX_PGAA_GAIN                  0x57
-#define RADIO_2056_TX_PGAA_BOOST_TUNE            0x58
-#define RADIO_2056_TX_PGAA_SLOPE                 0x59
-#define RADIO_2056_TX_PGAA_MISC                  0x5a
-#define RADIO_2056_TX_PGAG_MASTER                0x5b
-#define RADIO_2056_TX_PGAG_IDAC                  0x5c
-#define RADIO_2056_TX_PGAG_GAIN                  0x5d
-#define RADIO_2056_TX_PGAG_BOOST_TUNE            0x5e
-#define RADIO_2056_TX_PGAG_SLOPE                 0x5f
-#define RADIO_2056_TX_PGAG_MISC                  0x60
-#define RADIO_2056_TX_MIXA_MASTER                0x61
-#define RADIO_2056_TX_MIXA_BOOST_TUNE            0x62
-#define RADIO_2056_TX_MIXG                       0x63
-#define RADIO_2056_TX_MIXG_BOOST_TUNE            0x64
-#define RADIO_2056_TX_BB_GM_MASTER               0x65
-#define RADIO_2056_TX_GMBB_GM                    0x66
-#define RADIO_2056_TX_GMBB_IDAC                  0x67
-#define RADIO_2056_TX_TXLPF_MASTER               0x68
-#define RADIO_2056_TX_TXLPF_RCCAL                0x69
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF0           0x6a
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF1           0x6b
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF2           0x6c
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF3           0x6d
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF4           0x6e
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF5           0x6f
-#define RADIO_2056_TX_TXLPF_RCCAL_OFF6           0x70
-#define RADIO_2056_TX_TXLPF_BW                   0x71
-#define RADIO_2056_TX_TXLPF_GAIN                 0x72
-#define RADIO_2056_TX_TXLPF_IDAC                 0x73
-#define RADIO_2056_TX_TXLPF_IDAC_0               0x74
-#define RADIO_2056_TX_TXLPF_IDAC_1               0x75
-#define RADIO_2056_TX_TXLPF_IDAC_2               0x76
-#define RADIO_2056_TX_TXLPF_IDAC_3               0x77
-#define RADIO_2056_TX_TXLPF_IDAC_4               0x78
-#define RADIO_2056_TX_TXLPF_IDAC_5               0x79
-#define RADIO_2056_TX_TXLPF_IDAC_6               0x7a
-#define RADIO_2056_TX_TXLPF_OPAMP_IDAC           0x7b
-#define RADIO_2056_TX_TXLPF_MISC                 0x7c
-#define RADIO_2056_TX_TXSPARE1                   0x7d
-#define RADIO_2056_TX_TXSPARE2                   0x7e
-#define RADIO_2056_TX_TXSPARE3                   0x7f
-#define RADIO_2056_TX_TXSPARE4                   0x80
-#define RADIO_2056_TX_TXSPARE5                   0x81
-#define RADIO_2056_TX_TXSPARE6                   0x82
-#define RADIO_2056_TX_TXSPARE7                   0x83
-#define RADIO_2056_TX_TXSPARE8                   0x84
-#define RADIO_2056_TX_TXSPARE9                   0x85
-#define RADIO_2056_TX_TXSPARE10                  0x86
-#define RADIO_2056_TX_TXSPARE11                  0x87
-#define RADIO_2056_TX_TXSPARE12                  0x88
-#define RADIO_2056_TX_TXSPARE13                  0x89
-#define RADIO_2056_TX_TXSPARE14                  0x8a
-#define RADIO_2056_TX_TXSPARE15                  0x8b
-#define RADIO_2056_TX_TXSPARE16                  0x8c
-#define RADIO_2056_TX_STATUS_INTPA_GAIN          0x8d
-#define RADIO_2056_TX_STATUS_PAD_GAIN            0x8e
-#define RADIO_2056_TX_STATUS_PGA_GAIN            0x8f
-#define RADIO_2056_TX_STATUS_GM_TXLPF_GAIN       0x90
-#define RADIO_2056_TX_STATUS_TXLPF_BW            0x91
-#define RADIO_2056_TX_STATUS_TXLPF_RC            0x92
-#define RADIO_2056_TX_GMBB_IDAC0                 0x93
-#define RADIO_2056_TX_GMBB_IDAC1                 0x94
-#define RADIO_2056_TX_GMBB_IDAC2                 0x95
-#define RADIO_2056_TX_GMBB_IDAC3                 0x96
-#define RADIO_2056_TX_GMBB_IDAC4                 0x97
-#define RADIO_2056_TX_GMBB_IDAC5                 0x98
-#define RADIO_2056_TX_GMBB_IDAC6                 0x99
-#define RADIO_2056_TX_GMBB_IDAC7                 0x9a
-
-#define RADIO_2056_RX_RESERVED_ADDR0             0x0
-#define RADIO_2056_RX_IDCODE                     0x1
-#define RADIO_2056_RX_RESERVED_ADDR2             0x2
-#define RADIO_2056_RX_RESERVED_ADDR3             0x3
-#define RADIO_2056_RX_RESERVED_ADDR4             0x4
-#define RADIO_2056_RX_RESERVED_ADDR5             0x5
-#define RADIO_2056_RX_RESERVED_ADDR6             0x6
-#define RADIO_2056_RX_RESERVED_ADDR7             0x7
-#define RADIO_2056_RX_COM_CTRL                   0x8
-#define RADIO_2056_RX_COM_PU                     0x9
-#define RADIO_2056_RX_COM_OVR                    0xa
-#define RADIO_2056_RX_COM_RESET                  0xb
-#define RADIO_2056_RX_COM_RCAL                   0xc
-#define RADIO_2056_RX_COM_RC_RXLPF               0xd
-#define RADIO_2056_RX_COM_RC_TXLPF               0xe
-#define RADIO_2056_RX_COM_RC_RXHPF               0xf
-#define RADIO_2056_RX_RESERVED_ADDR16            0x10
-#define RADIO_2056_RX_RESERVED_ADDR17            0x11
-#define RADIO_2056_RX_RESERVED_ADDR18            0x12
-#define RADIO_2056_RX_RESERVED_ADDR19            0x13
-#define RADIO_2056_RX_RESERVED_ADDR20            0x14
-#define RADIO_2056_RX_RESERVED_ADDR21            0x15
-#define RADIO_2056_RX_RESERVED_ADDR22            0x16
-#define RADIO_2056_RX_RESERVED_ADDR23            0x17
-#define RADIO_2056_RX_RESERVED_ADDR24            0x18
-#define RADIO_2056_RX_RESERVED_ADDR25            0x19
-#define RADIO_2056_RX_RESERVED_ADDR26            0x1a
-#define RADIO_2056_RX_RESERVED_ADDR27            0x1b
-#define RADIO_2056_RX_RESERVED_ADDR28            0x1c
-#define RADIO_2056_RX_RESERVED_ADDR29            0x1d
-#define RADIO_2056_RX_RESERVED_ADDR30            0x1e
-#define RADIO_2056_RX_RESERVED_ADDR31            0x1f
-#define RADIO_2056_RX_RXIQCAL_RXMUX              0x20
-#define RADIO_2056_RX_RSSI_PU                    0x21
-#define RADIO_2056_RX_RSSI_SEL                   0x22
-#define RADIO_2056_RX_RSSI_GAIN                  0x23
-#define RADIO_2056_RX_RSSI_NB_IDAC               0x24
-#define RADIO_2056_RX_RSSI_WB2I_IDAC_1           0x25
-#define RADIO_2056_RX_RSSI_WB2I_IDAC_2           0x26
-#define RADIO_2056_RX_RSSI_WB2Q_IDAC_1           0x27
-#define RADIO_2056_RX_RSSI_WB2Q_IDAC_2           0x28
-#define RADIO_2056_RX_RSSI_POLE                  0x29
-#define RADIO_2056_RX_RSSI_WB1_IDAC              0x2a
-#define RADIO_2056_RX_RSSI_MISC                  0x2b
-#define RADIO_2056_RX_LNAA_MASTER                0x2c
-#define RADIO_2056_RX_LNAA_TUNE                  0x2d
-#define RADIO_2056_RX_LNAA_GAIN                  0x2e
-#define RADIO_2056_RX_LNA_A_SLOPE                0x2f
-#define RADIO_2056_RX_BIASPOLE_LNAA1_IDAC        0x30
-#define RADIO_2056_RX_LNAA2_IDAC                 0x31
-#define RADIO_2056_RX_LNA1A_MISC                 0x32
-#define RADIO_2056_RX_LNAG_MASTER                0x33
-#define RADIO_2056_RX_LNAG_TUNE                  0x34
-#define RADIO_2056_RX_LNAG_GAIN                  0x35
-#define RADIO_2056_RX_LNA_G_SLOPE                0x36
-#define RADIO_2056_RX_BIASPOLE_LNAG1_IDAC        0x37
-#define RADIO_2056_RX_LNAG2_IDAC                 0x38
-#define RADIO_2056_RX_LNA1G_MISC                 0x39
-#define RADIO_2056_RX_MIXA_MASTER                0x3a
-#define RADIO_2056_RX_MIXA_VCM                   0x3b
-#define RADIO_2056_RX_MIXA_CTRLPTAT              0x3c
-#define RADIO_2056_RX_MIXA_LOB_BIAS              0x3d
-#define RADIO_2056_RX_MIXA_CORE_IDAC             0x3e
-#define RADIO_2056_RX_MIXA_CMFB_IDAC             0x3f
-#define RADIO_2056_RX_MIXA_BIAS_AUX              0x40
-#define RADIO_2056_RX_MIXA_BIAS_MAIN             0x41
-#define RADIO_2056_RX_MIXA_BIAS_MISC             0x42
-#define RADIO_2056_RX_MIXA_MAST_BIAS             0x43
-#define RADIO_2056_RX_MIXG_MASTER                0x44
-#define RADIO_2056_RX_MIXG_VCM                   0x45
-#define RADIO_2056_RX_MIXG_CTRLPTAT              0x46
-#define RADIO_2056_RX_MIXG_LOB_BIAS              0x47
-#define RADIO_2056_RX_MIXG_CORE_IDAC             0x48
-#define RADIO_2056_RX_MIXG_CMFB_IDAC             0x49
-#define RADIO_2056_RX_MIXG_BIAS_AUX              0x4a
-#define RADIO_2056_RX_MIXG_BIAS_MAIN             0x4b
-#define RADIO_2056_RX_MIXG_BIAS_MISC             0x4c
-#define RADIO_2056_RX_MIXG_MAST_BIAS             0x4d
-#define RADIO_2056_RX_TIA_MASTER                 0x4e
-#define RADIO_2056_RX_TIA_IOPAMP                 0x4f
-#define RADIO_2056_RX_TIA_QOPAMP                 0x50
-#define RADIO_2056_RX_TIA_IMISC                  0x51
-#define RADIO_2056_RX_TIA_QMISC                  0x52
-#define RADIO_2056_RX_TIA_GAIN                   0x53
-#define RADIO_2056_RX_TIA_SPARE1                 0x54
-#define RADIO_2056_RX_TIA_SPARE2                 0x55
-#define RADIO_2056_RX_BB_LPF_MASTER              0x56
-#define RADIO_2056_RX_AACI_MASTER                0x57
-#define RADIO_2056_RX_RXLPF_IDAC                 0x58
-#define RADIO_2056_RX_RXLPF_OPAMPBIAS_LOWQ       0x59
-#define RADIO_2056_RX_RXLPF_OPAMPBIAS_HIGHQ      0x5a
-#define RADIO_2056_RX_RXLPF_BIAS_DCCANCEL        0x5b
-#define RADIO_2056_RX_RXLPF_OUTVCM               0x5c
-#define RADIO_2056_RX_RXLPF_INVCM_BODY           0x5d
-#define RADIO_2056_RX_RXLPF_CC_OP                0x5e
-#define RADIO_2056_RX_RXLPF_GAIN                 0x5f
-#define RADIO_2056_RX_RXLPF_Q_BW                 0x60
-#define RADIO_2056_RX_RXLPF_HP_CORNER_BW         0x61
-#define RADIO_2056_RX_RXLPF_RCCAL_HPC            0x62
-#define RADIO_2056_RX_RXHPF_OFF0                 0x63
-#define RADIO_2056_RX_RXHPF_OFF1                 0x64
-#define RADIO_2056_RX_RXHPF_OFF2                 0x65
-#define RADIO_2056_RX_RXHPF_OFF3                 0x66
-#define RADIO_2056_RX_RXHPF_OFF4                 0x67
-#define RADIO_2056_RX_RXHPF_OFF5                 0x68
-#define RADIO_2056_RX_RXHPF_OFF6                 0x69
-#define RADIO_2056_RX_RXHPF_OFF7                 0x6a
-#define RADIO_2056_RX_RXLPF_RCCAL_LPC            0x6b
-#define RADIO_2056_RX_RXLPF_OFF_0                0x6c
-#define RADIO_2056_RX_RXLPF_OFF_1                0x6d
-#define RADIO_2056_RX_RXLPF_OFF_2                0x6e
-#define RADIO_2056_RX_RXLPF_OFF_3                0x6f
-#define RADIO_2056_RX_RXLPF_OFF_4                0x70
-#define RADIO_2056_RX_UNUSED                     0x71
-#define RADIO_2056_RX_VGA_MASTER                 0x72
-#define RADIO_2056_RX_VGA_BIAS                   0x73
-#define RADIO_2056_RX_VGA_BIAS_DCCANCEL          0x74
-#define RADIO_2056_RX_VGA_GAIN                   0x75
-#define RADIO_2056_RX_VGA_HP_CORNER_BW           0x76
-#define RADIO_2056_RX_VGABUF_BIAS                0x77
-#define RADIO_2056_RX_VGABUF_GAIN_BW             0x78
-#define RADIO_2056_RX_TXFBMIX_A                  0x79
-#define RADIO_2056_RX_TXFBMIX_G                  0x7a
-#define RADIO_2056_RX_RXSPARE1                   0x7b
-#define RADIO_2056_RX_RXSPARE2                   0x7c
-#define RADIO_2056_RX_RXSPARE3                   0x7d
-#define RADIO_2056_RX_RXSPARE4                   0x7e
-#define RADIO_2056_RX_RXSPARE5                   0x7f
-#define RADIO_2056_RX_RXSPARE6                   0x80
-#define RADIO_2056_RX_RXSPARE7                   0x81
-#define RADIO_2056_RX_RXSPARE8                   0x82
-#define RADIO_2056_RX_RXSPARE9                   0x83
-#define RADIO_2056_RX_RXSPARE10                  0x84
-#define RADIO_2056_RX_RXSPARE11                  0x85
-#define RADIO_2056_RX_RXSPARE12                  0x86
-#define RADIO_2056_RX_RXSPARE13                  0x87
-#define RADIO_2056_RX_RXSPARE14                  0x88
-#define RADIO_2056_RX_RXSPARE15                  0x89
-#define RADIO_2056_RX_RXSPARE16                  0x8a
-#define RADIO_2056_RX_STATUS_LNAA_GAIN           0x8b
-#define RADIO_2056_RX_STATUS_LNAG_GAIN           0x8c
-#define RADIO_2056_RX_STATUS_MIXTIA_GAIN         0x8d
-#define RADIO_2056_RX_STATUS_RXLPF_GAIN          0x8e
-#define RADIO_2056_RX_STATUS_VGA_BUF_GAIN        0x8f
-#define RADIO_2056_RX_STATUS_RXLPF_Q             0x90
-#define RADIO_2056_RX_STATUS_RXLPF_BUF_BW        0x91
-#define RADIO_2056_RX_STATUS_RXLPF_VGA_HPC       0x92
-#define RADIO_2056_RX_STATUS_RXLPF_RC            0x93
-#define RADIO_2056_RX_STATUS_HPC_RC              0x94
-
-#define RADIO_2056_LNA1_A_PU		0x01
-#define RADIO_2056_LNA2_A_PU		0x02
-#define RADIO_2056_LNA1_G_PU		0x01
-#define RADIO_2056_LNA2_G_PU		0x02
-#define RADIO_2056_MIXA_PU_I		0x01
-#define RADIO_2056_MIXA_PU_Q		0x02
-#define RADIO_2056_MIXA_PU_GM		0x10
-#define RADIO_2056_MIXG_PU_I		0x01
-#define RADIO_2056_MIXG_PU_Q		0x02
-#define RADIO_2056_MIXG_PU_GM		0x10
-#define RADIO_2056_TIA_PU			0x01
-#define RADIO_2056_BB_LPF_PU		0x20
-#define RADIO_2056_W1_PU			0x02
-#define RADIO_2056_W2_PU			0x04
-#define RADIO_2056_NB_PU			0x08
-#define RADIO_2056_RSSI_W1_SEL		0x02
-#define RADIO_2056_RSSI_W2_SEL		0x04
-#define RADIO_2056_RSSI_NB_SEL		0x08
-#define RADIO_2056_VCM_MASK			0x1c
-#define RADIO_2056_RSSI_VCM_SHIFT	0x02
-
-#define RADIO_2057_DACBUF_VINCM_CORE0            0x0
-#define RADIO_2057_IDCODE                        0x1
-#define RADIO_2057_RCCAL_MASTER                  0x2
-#define RADIO_2057_RCCAL_CAP_SIZE                0x3
-#define RADIO_2057_RCAL_CONFIG                   0x4
-#define RADIO_2057_GPAIO_CONFIG                  0x5
-#define RADIO_2057_GPAIO_SEL1                    0x6
-#define RADIO_2057_GPAIO_SEL0                    0x7
-#define RADIO_2057_CLPO_CONFIG                   0x8
-#define RADIO_2057_BANDGAP_CONFIG                0x9
-#define RADIO_2057_BANDGAP_RCAL_TRIM             0xa
-#define RADIO_2057_AFEREG_CONFIG                 0xb
-#define RADIO_2057_TEMPSENSE_CONFIG              0xc
-#define RADIO_2057_XTAL_CONFIG1                  0xd
-#define RADIO_2057_XTAL_ICORE_SIZE               0xe
-#define RADIO_2057_XTAL_BUF_SIZE                 0xf
-#define RADIO_2057_XTAL_PULLCAP_SIZE             0x10
-#define RADIO_2057_RFPLL_MASTER                  0x11
-#define RADIO_2057_VCOMONITOR_VTH_L              0x12
-#define RADIO_2057_VCOMONITOR_VTH_H              0x13
-#define RADIO_2057_VCOCAL_BIASRESET_RFPLLREG_VOUT 0x14
-#define RADIO_2057_VCO_VARCSIZE_IDAC             0x15
-#define RADIO_2057_VCOCAL_COUNTVAL0              0x16
-#define RADIO_2057_VCOCAL_COUNTVAL1              0x17
-#define RADIO_2057_VCOCAL_INTCLK_COUNT           0x18
-#define RADIO_2057_VCOCAL_MASTER                 0x19
-#define RADIO_2057_VCOCAL_NUMCAPCHANGE           0x1a
-#define RADIO_2057_VCOCAL_WINSIZE                0x1b
-#define RADIO_2057_VCOCAL_DELAY_AFTER_REFRESH    0x1c
-#define RADIO_2057_VCOCAL_DELAY_AFTER_CLOSELOOP  0x1d
-#define RADIO_2057_VCOCAL_DELAY_AFTER_OPENLOOP   0x1e
-#define RADIO_2057_VCOCAL_DELAY_BEFORE_OPENLOOP  0x1f
-#define RADIO_2057_VCO_FORCECAPEN_FORCECAP1      0x20
-#define RADIO_2057_VCO_FORCECAP0                 0x21
-#define RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE 0x22
-#define RADIO_2057_RFPLL_PFD_RESET_PW            0x23
-#define RADIO_2057_RFPLL_LOOPFILTER_R2           0x24
-#define RADIO_2057_RFPLL_LOOPFILTER_R1           0x25
-#define RADIO_2057_RFPLL_LOOPFILTER_C3           0x26
-#define RADIO_2057_RFPLL_LOOPFILTER_C2           0x27
-#define RADIO_2057_RFPLL_LOOPFILTER_C1           0x28
-#define RADIO_2057_CP_KPD_IDAC                   0x29
-#define RADIO_2057_RFPLL_IDACS                   0x2a
-#define RADIO_2057_RFPLL_MISC_EN                 0x2b
-#define RADIO_2057_RFPLL_MMD0                    0x2c
-#define RADIO_2057_RFPLL_MMD1                    0x2d
-#define RADIO_2057_RFPLL_MISC_CAL_RESETN         0x2e
-#define RADIO_2057_JTAGXTAL_SIZE_CPBIAS_FILTRES  0x2f
-#define RADIO_2057_VCO_ALCREF_BBPLLXTAL_SIZE     0x30
-#define RADIO_2057_VCOCAL_READCAP0               0x31
-#define RADIO_2057_VCOCAL_READCAP1               0x32
-#define RADIO_2057_VCOCAL_STATUS                 0x33
-#define RADIO_2057_LOGEN_PUS                     0x34
-#define RADIO_2057_LOGEN_PTAT_RESETS             0x35
-#define RADIO_2057_VCOBUF_IDACS                  0x36
-#define RADIO_2057_VCOBUF_TUNE                   0x37
-#define RADIO_2057_CMOSBUF_TX2GQ_IDACS           0x38
-#define RADIO_2057_CMOSBUF_TX2GI_IDACS           0x39
-#define RADIO_2057_CMOSBUF_TX5GQ_IDACS           0x3a
-#define RADIO_2057_CMOSBUF_TX5GI_IDACS           0x3b
-#define RADIO_2057_CMOSBUF_RX2GQ_IDACS           0x3c
-#define RADIO_2057_CMOSBUF_RX2GI_IDACS           0x3d
-#define RADIO_2057_CMOSBUF_RX5GQ_IDACS           0x3e
-#define RADIO_2057_CMOSBUF_RX5GI_IDACS           0x3f
-#define RADIO_2057_LOGEN_MX2G_IDACS              0x40
-#define RADIO_2057_LOGEN_MX2G_TUNE               0x41
-#define RADIO_2057_LOGEN_MX5G_IDACS              0x42
-#define RADIO_2057_LOGEN_MX5G_TUNE               0x43
-#define RADIO_2057_LOGEN_MX5G_RCCR               0x44
-#define RADIO_2057_LOGEN_INDBUF2G_IDAC           0x45
-#define RADIO_2057_LOGEN_INDBUF2G_IBOOST         0x46
-#define RADIO_2057_LOGEN_INDBUF2G_TUNE           0x47
-#define RADIO_2057_LOGEN_INDBUF5G_IDAC           0x48
-#define RADIO_2057_LOGEN_INDBUF5G_IBOOST         0x49
-#define RADIO_2057_LOGEN_INDBUF5G_TUNE           0x4a
-#define RADIO_2057_CMOSBUF_TX_RCCR               0x4b
-#define RADIO_2057_CMOSBUF_RX_RCCR               0x4c
-#define RADIO_2057_LOGEN_SEL_PKDET               0x4d
-#define RADIO_2057_CMOSBUF_SHAREIQ_PTAT          0x4e
-#define RADIO_2057_RXTXBIAS_CONFIG_CORE0         0x4f
-#define RADIO_2057_TXGM_TXRF_PUS_CORE0           0x50
-#define RADIO_2057_TXGM_IDAC_BLEED_CORE0         0x51
-#define RADIO_2057_TXGM_GAIN_CORE0               0x56
-#define RADIO_2057_TXGM2G_PKDET_PUS_CORE0        0x57
-#define RADIO_2057_PAD2G_PTATS_CORE0             0x58
-#define RADIO_2057_PAD2G_IDACS_CORE0             0x59
-#define RADIO_2057_PAD2G_BOOST_PU_CORE0          0x5a
-#define RADIO_2057_PAD2G_CASCV_GAIN_CORE0        0x5b
-#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0   0x5c
-#define RADIO_2057_TXMIX2G_LODC_CORE0            0x5d
-#define RADIO_2057_PAD2G_TUNE_PUS_CORE0          0x5e
-#define RADIO_2057_IPA2G_GAIN_CORE0              0x5f
-#define RADIO_2057_TSSI2G_SPARE1_CORE0           0x60
-#define RADIO_2057_TSSI2G_SPARE2_CORE0           0x61
-#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE0  0x62
-#define RADIO_2057_IPA2G_IMAIN_CORE0             0x63
-#define RADIO_2057_IPA2G_CASCONV_CORE0           0x64
-#define RADIO_2057_IPA2G_CASCOFFV_CORE0          0x65
-#define RADIO_2057_IPA2G_BIAS_FILTER_CORE0       0x66
-#define RADIO_2057_TX5G_PKDET_CORE0              0x69
-#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE0      0x6a
-#define RADIO_2057_PAD5G_PTATS1_CORE0            0x6b
-#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE0      0x6c
-#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE0     0x6d
-#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE0       0x6e
-#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE0 0x6f
-#define RADIO_2057_PGA_BOOST_TUNE_CORE0          0x70
-#define RADIO_2057_PGA_GAIN_CORE0                0x71
-#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE0 0x72
-#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0      0x73
-#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0     0x74
-#define RADIO_2057_IPA5G_IAUX_CORE0              0x75
-#define RADIO_2057_IPA5G_GAIN_CORE0              0x76
-#define RADIO_2057_TSSI5G_SPARE1_CORE0           0x77
-#define RADIO_2057_TSSI5G_SPARE2_CORE0           0x78
-#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE0       0x79
-#define RADIO_2057_IPA5G_PTAT_CORE0              0x7a
-#define RADIO_2057_IPA5G_IMAIN_CORE0             0x7b
-#define RADIO_2057_IPA5G_CASCONV_CORE0           0x7c
-#define RADIO_2057_IPA5G_BIAS_FILTER_CORE0       0x7d
-#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE0     0x80
-#define RADIO_2057_TR2G_CONFIG1_CORE0_NU         0x81
-#define RADIO_2057_TR2G_CONFIG2_CORE0_NU         0x82
-#define RADIO_2057_LNA5G_RFEN_CORE0              0x83
-#define RADIO_2057_TR5G_CONFIG2_CORE0_NU         0x84
-#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE0      0x85
-#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE0 0x86
-#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE0  0x87
-#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE0   0x88
-#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE0      0x89
-#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE0      0x8a
-#define RADIO_2057_LNA2_IAUX_PTAT_CORE0          0x8b
-#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE0      0x8c
-#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE0 0x8d
-#define RADIO_2057_RXRFBIAS_BANDSEL_CORE0        0x8e
-#define RADIO_2057_TIA_CONFIG_CORE0              0x8f
-#define RADIO_2057_TIA_IQGAIN_CORE0              0x90
-#define RADIO_2057_TIA_IBIAS2_CORE0              0x91
-#define RADIO_2057_TIA_IBIAS1_CORE0              0x92
-#define RADIO_2057_TIA_SPARE_Q_CORE0             0x93
-#define RADIO_2057_TIA_SPARE_I_CORE0             0x94
-#define RADIO_2057_RXMIX2G_PUS_CORE0             0x95
-#define RADIO_2057_RXMIX2G_VCMREFS_CORE0         0x96
-#define RADIO_2057_RXMIX2G_LODC_QI_CORE0         0x97
-#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE0       0x98
-#define RADIO_2057_LNA2G_GAIN_CORE0              0x99
-#define RADIO_2057_LNA2G_TUNE_CORE0              0x9a
-#define RADIO_2057_RXMIX5G_PUS_CORE0             0x9b
-#define RADIO_2057_RXMIX5G_VCMREFS_CORE0         0x9c
-#define RADIO_2057_RXMIX5G_LODC_QI_CORE0         0x9d
-#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE0       0x9e
-#define RADIO_2057_LNA5G_GAIN_CORE0              0x9f
-#define RADIO_2057_LNA5G_TUNE_CORE0              0xa0
-#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE0    0xa1
-#define RADIO_2057_RXBB_BIAS_MASTER_CORE0        0xa2
-#define RADIO_2057_RXBB_VGABUF_IDACS_CORE0       0xa3
-#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE0 0xa4
-#define RADIO_2057_TXBUF_VINCM_CORE0             0xa5
-#define RADIO_2057_TXBUF_IDACS_CORE0             0xa6
-#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE0       0xa7
-#define RADIO_2057_RXBB_CC_CORE0                 0xa8
-#define RADIO_2057_RXBB_SPARE3_CORE0             0xa9
-#define RADIO_2057_RXBB_RCCAL_HPC_CORE0          0xaa
-#define RADIO_2057_LPF_IDACS_CORE0               0xab
-#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE0  0xac
-#define RADIO_2057_TXBUF_GAIN_CORE0              0xad
-#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE0   0xae
-#define RADIO_2057_RXBUF_DEGEN_CORE0             0xaf
-#define RADIO_2057_RXBB_SPARE2_CORE0             0xb0
-#define RADIO_2057_RXBB_SPARE1_CORE0             0xb1
-#define RADIO_2057_RSSI_MASTER_CORE0             0xb2
-#define RADIO_2057_W2_MASTER_CORE0               0xb3
-#define RADIO_2057_NB_MASTER_CORE0               0xb4
-#define RADIO_2057_W2_IDACS0_Q_CORE0             0xb5
-#define RADIO_2057_W2_IDACS1_Q_CORE0             0xb6
-#define RADIO_2057_W2_IDACS0_I_CORE0             0xb7
-#define RADIO_2057_W2_IDACS1_I_CORE0             0xb8
-#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE0  0xb9
-#define RADIO_2057_NB_IDACS_Q_CORE0              0xba
-#define RADIO_2057_NB_IDACS_I_CORE0              0xbb
-#define RADIO_2057_BACKUP4_CORE0                 0xc1
-#define RADIO_2057_BACKUP3_CORE0                 0xc2
-#define RADIO_2057_BACKUP2_CORE0                 0xc3
-#define RADIO_2057_BACKUP1_CORE0                 0xc4
-#define RADIO_2057_SPARE16_CORE0                 0xc5
-#define RADIO_2057_SPARE15_CORE0                 0xc6
-#define RADIO_2057_SPARE14_CORE0                 0xc7
-#define RADIO_2057_SPARE13_CORE0                 0xc8
-#define RADIO_2057_SPARE12_CORE0                 0xc9
-#define RADIO_2057_SPARE11_CORE0                 0xca
-#define RADIO_2057_TX2G_BIAS_RESETS_CORE0        0xcb
-#define RADIO_2057_TX5G_BIAS_RESETS_CORE0        0xcc
-#define RADIO_2057_IQTEST_SEL_PU                 0xcd
-#define RADIO_2057_XTAL_CONFIG2                  0xce
-#define RADIO_2057_BUFS_MISC_LPFBW_CORE0         0xcf
-#define RADIO_2057_TXLPF_RCCAL_CORE0             0xd0
-#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0xd1
-#define RADIO_2057_LPF_GAIN_CORE0                0xd2
-#define RADIO_2057_DACBUF_IDACS_BW_CORE0         0xd3
-#define RADIO_2057_RXTXBIAS_CONFIG_CORE1         0xd4
-#define RADIO_2057_TXGM_TXRF_PUS_CORE1           0xd5
-#define RADIO_2057_TXGM_IDAC_BLEED_CORE1         0xd6
-#define RADIO_2057_TXGM_GAIN_CORE1               0xdb
-#define RADIO_2057_TXGM2G_PKDET_PUS_CORE1        0xdc
-#define RADIO_2057_PAD2G_PTATS_CORE1             0xdd
-#define RADIO_2057_PAD2G_IDACS_CORE1             0xde
-#define RADIO_2057_PAD2G_BOOST_PU_CORE1          0xdf
-#define RADIO_2057_PAD2G_CASCV_GAIN_CORE1        0xe0
-#define RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1   0xe1
-#define RADIO_2057_TXMIX2G_LODC_CORE1            0xe2
-#define RADIO_2057_PAD2G_TUNE_PUS_CORE1          0xe3
-#define RADIO_2057_IPA2G_GAIN_CORE1              0xe4
-#define RADIO_2057_TSSI2G_SPARE1_CORE1           0xe5
-#define RADIO_2057_TSSI2G_SPARE2_CORE1           0xe6
-#define RADIO_2057_IPA2G_TUNEV_CASCV_PTAT_CORE1  0xe7
-#define RADIO_2057_IPA2G_IMAIN_CORE1             0xe8
-#define RADIO_2057_IPA2G_CASCONV_CORE1           0xe9
-#define RADIO_2057_IPA2G_CASCOFFV_CORE1          0xea
-#define RADIO_2057_IPA2G_BIAS_FILTER_CORE1       0xeb
-#define RADIO_2057_TX5G_PKDET_CORE1              0xee
-#define RADIO_2057_PGA_PTAT_TXGM5G_PU_CORE1      0xef
-#define RADIO_2057_PAD5G_PTATS1_CORE1            0xf0
-#define RADIO_2057_PAD5G_CLASS_PTATS2_CORE1      0xf1
-#define RADIO_2057_PGA_BOOSTPTAT_IMAIN_CORE1     0xf2
-#define RADIO_2057_PAD5G_CASCV_IMAIN_CORE1       0xf3
-#define RADIO_2057_TXMIX5G_IBOOST_PAD_IAUX_CORE1 0xf4
-#define RADIO_2057_PGA_BOOST_TUNE_CORE1          0xf5
-#define RADIO_2057_PGA_GAIN_CORE1                0xf6
-#define RADIO_2057_PAD5G_CASCOFFV_GAIN_PUS_CORE1 0xf7
-#define RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1      0xf8
-#define RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1     0xf9
-#define RADIO_2057_IPA5G_IAUX_CORE1              0xfa
-#define RADIO_2057_IPA5G_GAIN_CORE1              0xfb
-#define RADIO_2057_TSSI5G_SPARE1_CORE1           0xfc
-#define RADIO_2057_TSSI5G_SPARE2_CORE1           0xfd
-#define RADIO_2057_IPA5G_CASCOFFV_PU_CORE1       0xfe
-#define RADIO_2057_IPA5G_PTAT_CORE1              0xff
-#define RADIO_2057_IPA5G_IMAIN_CORE1             0x100
-#define RADIO_2057_IPA5G_CASCONV_CORE1           0x101
-#define RADIO_2057_IPA5G_BIAS_FILTER_CORE1       0x102
-#define RADIO_2057_PAD_BIAS_FILTER_BWS_CORE1     0x105
-#define RADIO_2057_TR2G_CONFIG1_CORE1_NU         0x106
-#define RADIO_2057_TR2G_CONFIG2_CORE1_NU         0x107
-#define RADIO_2057_LNA5G_RFEN_CORE1              0x108
-#define RADIO_2057_TR5G_CONFIG2_CORE1_NU         0x109
-#define RADIO_2057_RXRFBIAS_IBOOST_PU_CORE1      0x10a
-#define RADIO_2057_RXRF_IABAND_RXGM_IMAIN_PTAT_CORE1 0x10b
-#define RADIO_2057_RXGM_CMFBITAIL_AUXPTAT_CORE1  0x10c
-#define RADIO_2057_RXMIX_ICORE_RXGM_IAUX_CORE1   0x10d
-#define RADIO_2057_RXMIX_CMFBITAIL_PU_CORE1      0x10e
-#define RADIO_2057_LNA2_IMAIN_PTAT_PU_CORE1      0x10f
-#define RADIO_2057_LNA2_IAUX_PTAT_CORE1          0x110
-#define RADIO_2057_LNA1_IMAIN_PTAT_PU_CORE1      0x111
-#define RADIO_2057_LNA15G_INPUT_MATCH_TUNE_CORE1 0x112
-#define RADIO_2057_RXRFBIAS_BANDSEL_CORE1        0x113
-#define RADIO_2057_TIA_CONFIG_CORE1              0x114
-#define RADIO_2057_TIA_IQGAIN_CORE1              0x115
-#define RADIO_2057_TIA_IBIAS2_CORE1              0x116
-#define RADIO_2057_TIA_IBIAS1_CORE1              0x117
-#define RADIO_2057_TIA_SPARE_Q_CORE1             0x118
-#define RADIO_2057_TIA_SPARE_I_CORE1             0x119
-#define RADIO_2057_RXMIX2G_PUS_CORE1             0x11a
-#define RADIO_2057_RXMIX2G_VCMREFS_CORE1         0x11b
-#define RADIO_2057_RXMIX2G_LODC_QI_CORE1         0x11c
-#define RADIO_2057_W12G_BW_LNA2G_PUS_CORE1       0x11d
-#define RADIO_2057_LNA2G_GAIN_CORE1              0x11e
-#define RADIO_2057_LNA2G_TUNE_CORE1              0x11f
-#define RADIO_2057_RXMIX5G_PUS_CORE1             0x120
-#define RADIO_2057_RXMIX5G_VCMREFS_CORE1         0x121
-#define RADIO_2057_RXMIX5G_LODC_QI_CORE1         0x122
-#define RADIO_2057_W15G_BW_LNA5G_PUS_CORE1       0x123
-#define RADIO_2057_LNA5G_GAIN_CORE1              0x124
-#define RADIO_2057_LNA5G_TUNE_CORE1              0x125
-#define RADIO_2057_LPFSEL_TXRX_RXBB_PUS_CORE1    0x126
-#define RADIO_2057_RXBB_BIAS_MASTER_CORE1        0x127
-#define RADIO_2057_RXBB_VGABUF_IDACS_CORE1       0x128
-#define RADIO_2057_LPF_VCMREF_TXBUF_VCMREF_CORE1 0x129
-#define RADIO_2057_TXBUF_VINCM_CORE1             0x12a
-#define RADIO_2057_TXBUF_IDACS_CORE1             0x12b
-#define RADIO_2057_LPF_RESP_RXBUF_BW_CORE1       0x12c
-#define RADIO_2057_RXBB_CC_CORE1                 0x12d
-#define RADIO_2057_RXBB_SPARE3_CORE1             0x12e
-#define RADIO_2057_RXBB_RCCAL_HPC_CORE1          0x12f
-#define RADIO_2057_LPF_IDACS_CORE1               0x130
-#define RADIO_2057_LPFBYP_DCLOOP_BYP_IDAC_CORE1  0x131
-#define RADIO_2057_TXBUF_GAIN_CORE1              0x132
-#define RADIO_2057_AFELOOPBACK_AACI_RESP_CORE1   0x133
-#define RADIO_2057_RXBUF_DEGEN_CORE1             0x134
-#define RADIO_2057_RXBB_SPARE2_CORE1             0x135
-#define RADIO_2057_RXBB_SPARE1_CORE1             0x136
-#define RADIO_2057_RSSI_MASTER_CORE1             0x137
-#define RADIO_2057_W2_MASTER_CORE1               0x138
-#define RADIO_2057_NB_MASTER_CORE1               0x139
-#define RADIO_2057_W2_IDACS0_Q_CORE1             0x13a
-#define RADIO_2057_W2_IDACS1_Q_CORE1             0x13b
-#define RADIO_2057_W2_IDACS0_I_CORE1             0x13c
-#define RADIO_2057_W2_IDACS1_I_CORE1             0x13d
-#define RADIO_2057_RSSI_GPAIOSEL_W1_IDACS_CORE1  0x13e
-#define RADIO_2057_NB_IDACS_Q_CORE1              0x13f
-#define RADIO_2057_NB_IDACS_I_CORE1              0x140
-#define RADIO_2057_BACKUP4_CORE1                 0x146
-#define RADIO_2057_BACKUP3_CORE1                 0x147
-#define RADIO_2057_BACKUP2_CORE1                 0x148
-#define RADIO_2057_BACKUP1_CORE1                 0x149
-#define RADIO_2057_SPARE16_CORE1                 0x14a
-#define RADIO_2057_SPARE15_CORE1                 0x14b
-#define RADIO_2057_SPARE14_CORE1                 0x14c
-#define RADIO_2057_SPARE13_CORE1                 0x14d
-#define RADIO_2057_SPARE12_CORE1                 0x14e
-#define RADIO_2057_SPARE11_CORE1                 0x14f
-#define RADIO_2057_TX2G_BIAS_RESETS_CORE1        0x150
-#define RADIO_2057_TX5G_BIAS_RESETS_CORE1        0x151
-#define RADIO_2057_SPARE8_CORE1                  0x152
-#define RADIO_2057_SPARE7_CORE1                  0x153
-#define RADIO_2057_BUFS_MISC_LPFBW_CORE1         0x154
-#define RADIO_2057_TXLPF_RCCAL_CORE1             0x155
-#define RADIO_2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
-#define RADIO_2057_LPF_GAIN_CORE1                0x157
-#define RADIO_2057_DACBUF_IDACS_BW_CORE1         0x158
-#define RADIO_2057_DACBUF_VINCM_CORE1            0x159
-#define RADIO_2057_RCCAL_START_R1_Q1_P1          0x15a
-#define RADIO_2057_RCCAL_X1                      0x15b
-#define RADIO_2057_RCCAL_TRC0                    0x15c
-#define RADIO_2057_RCCAL_TRC1                    0x15d
-#define RADIO_2057_RCCAL_DONE_OSCCAP             0x15e
-#define RADIO_2057_RCCAL_N0_0                    0x15f
-#define RADIO_2057_RCCAL_N0_1                    0x160
-#define RADIO_2057_RCCAL_N1_0                    0x161
-#define RADIO_2057_RCCAL_N1_1                    0x162
-#define RADIO_2057_RCAL_STATUS                   0x163
-#define RADIO_2057_XTALPUOVR_PINCTRL             0x164
-#define RADIO_2057_OVR_REG0                      0x165
-#define RADIO_2057_OVR_REG1                      0x166
-#define RADIO_2057_OVR_REG2                      0x167
-#define RADIO_2057_OVR_REG3                      0x168
-#define RADIO_2057_OVR_REG4                      0x169
-#define RADIO_2057_RCCAL_SCAP_VAL                0x16a
-#define RADIO_2057_RCCAL_BCAP_VAL                0x16b
-#define RADIO_2057_RCCAL_HPC_VAL                 0x16c
-#define RADIO_2057_RCCAL_OVERRIDES               0x16d
-#define RADIO_2057_TX0_IQCAL_GAIN_BW             0x170
-#define RADIO_2057_TX0_LOFT_FINE_I               0x171
-#define RADIO_2057_TX0_LOFT_FINE_Q               0x172
-#define RADIO_2057_TX0_LOFT_COARSE_I             0x173
-#define RADIO_2057_TX0_LOFT_COARSE_Q             0x174
-#define RADIO_2057_TX0_TX_SSI_MASTER             0x175
-#define RADIO_2057_TX0_IQCAL_VCM_HG              0x176
-#define RADIO_2057_TX0_IQCAL_IDAC                0x177
-#define RADIO_2057_TX0_TSSI_VCM                  0x178
-#define RADIO_2057_TX0_TX_SSI_MUX                0x179
-#define RADIO_2057_TX0_TSSIA                     0x17a
-#define RADIO_2057_TX0_TSSIG                     0x17b
-#define RADIO_2057_TX0_TSSI_MISC1                0x17c
-#define RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN       0x17d
-#define RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP       0x17e
-#define RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN       0x17f
-#define RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP       0x180
-#define RADIO_2057_TX1_IQCAL_GAIN_BW             0x190
-#define RADIO_2057_TX1_LOFT_FINE_I               0x191
-#define RADIO_2057_TX1_LOFT_FINE_Q               0x192
-#define RADIO_2057_TX1_LOFT_COARSE_I             0x193
-#define RADIO_2057_TX1_LOFT_COARSE_Q             0x194
-#define RADIO_2057_TX1_TX_SSI_MASTER             0x195
-#define RADIO_2057_TX1_IQCAL_VCM_HG              0x196
-#define RADIO_2057_TX1_IQCAL_IDAC                0x197
-#define RADIO_2057_TX1_TSSI_VCM                  0x198
-#define RADIO_2057_TX1_TX_SSI_MUX                0x199
-#define RADIO_2057_TX1_TSSIA                     0x19a
-#define RADIO_2057_TX1_TSSIG                     0x19b
-#define RADIO_2057_TX1_TSSI_MISC1                0x19c
-#define RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN       0x19d
-#define RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP       0x19e
-#define RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN       0x19f
-#define RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP       0x1a0
-#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE0      0x1a1
-#define RADIO_2057_AFE_SET_VCM_I_CORE0           0x1a2
-#define RADIO_2057_AFE_SET_VCM_Q_CORE0           0x1a3
-#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE0    0x1a4
-#define RADIO_2057_AFE_STATUS_VCM_I_CORE0        0x1a5
-#define RADIO_2057_AFE_STATUS_VCM_Q_CORE0        0x1a6
-#define RADIO_2057_AFE_VCM_CAL_MASTER_CORE1      0x1a7
-#define RADIO_2057_AFE_SET_VCM_I_CORE1           0x1a8
-#define RADIO_2057_AFE_SET_VCM_Q_CORE1           0x1a9
-#define RADIO_2057_AFE_STATUS_VCM_IQADC_CORE1    0x1aa
-#define RADIO_2057_AFE_STATUS_VCM_I_CORE1        0x1ab
-#define RADIO_2057_AFE_STATUS_VCM_Q_CORE1        0x1ac
-
-#define RADIO_2057v7_DACBUF_VINCM_CORE0          0x1ad
-#define RADIO_2057v7_RCCAL_MASTER                0x1ae
-#define RADIO_2057v7_TR2G_CONFIG3_CORE0_NU       0x1af
-#define RADIO_2057v7_TR2G_CONFIG3_CORE1_NU       0x1b0
-#define RADIO_2057v7_LOGEN_PUS1                  0x1b1
-#define RADIO_2057v7_OVR_REG5                    0x1b2
-#define RADIO_2057v7_OVR_REG6                    0x1b3
-#define RADIO_2057v7_OVR_REG7                    0x1b4
-#define RADIO_2057v7_OVR_REG8                    0x1b5
-#define RADIO_2057v7_OVR_REG9                    0x1b6
-#define RADIO_2057v7_OVR_REG10                   0x1b7
-#define RADIO_2057v7_OVR_REG11                   0x1b8
-#define RADIO_2057v7_OVR_REG12                   0x1b9
-#define RADIO_2057v7_OVR_REG13                   0x1ba
-#define RADIO_2057v7_OVR_REG14                   0x1bb
-#define RADIO_2057v7_OVR_REG15                   0x1bc
-#define RADIO_2057v7_OVR_REG16                   0x1bd
-#define RADIO_2057v7_OVR_REG1                    0x1be
-#define RADIO_2057v7_OVR_REG18                   0x1bf
-#define RADIO_2057v7_OVR_REG19                   0x1c0
-#define RADIO_2057v7_OVR_REG20                   0x1c1
-#define RADIO_2057v7_OVR_REG21                   0x1c2
-#define RADIO_2057v7_OVR_REG2                    0x1c3
-#define RADIO_2057v7_OVR_REG23                   0x1c4
-#define RADIO_2057v7_OVR_REG24                   0x1c5
-#define RADIO_2057v7_OVR_REG25                   0x1c6
-#define RADIO_2057v7_OVR_REG26                   0x1c7
-#define RADIO_2057v7_OVR_REG27                   0x1c8
-#define RADIO_2057v7_OVR_REG28                   0x1c9
-#define RADIO_2057v7_IQTEST_SEL_PU2              0x1ca
-
-#define RADIO_2057_VCM_MASK			 0x7
-
-#endif				/* _BCM20XX_H */
diff --git a/drivers/staging/brcm80211/phy/wlc_phyreg_n.h b/drivers/staging/brcm80211/phy/wlc_phyreg_n.h
deleted file mode 100644
index 211bc3a..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phyreg_n.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define NPHY_TBL_ID_GAIN1		0
-#define NPHY_TBL_ID_GAIN2		1
-#define NPHY_TBL_ID_GAINBITS1		2
-#define NPHY_TBL_ID_GAINBITS2		3
-#define NPHY_TBL_ID_GAINLIMIT		4
-#define NPHY_TBL_ID_WRSSIGainLimit	5
-#define NPHY_TBL_ID_RFSEQ		7
-#define NPHY_TBL_ID_AFECTRL		8
-#define NPHY_TBL_ID_ANTSWCTRLLUT	9
-#define NPHY_TBL_ID_IQLOCAL		15
-#define NPHY_TBL_ID_NOISEVAR		16
-#define NPHY_TBL_ID_SAMPLEPLAY		17
-#define NPHY_TBL_ID_CORE1TXPWRCTL	26
-#define NPHY_TBL_ID_CORE2TXPWRCTL	27
-#define NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL	30
-
-#define NPHY_TBL_ID_EPSILONTBL0   31
-#define NPHY_TBL_ID_SCALARTBL0    32
-#define NPHY_TBL_ID_EPSILONTBL1   33
-#define NPHY_TBL_ID_SCALARTBL1    34
-
-#define	NPHY_TO_BPHY_OFF	0xc00
-
-#define NPHY_BandControl_currentBand			0x0001
-#define RFCC_CHIP0_PU			0x0400
-#define RFCC_POR_FORCE			0x0040
-#define RFCC_OE_POR_FORCE		0x0080
-#define NPHY_RfctrlIntc_override_OFF			0
-#define NPHY_RfctrlIntc_override_TRSW			1
-#define NPHY_RfctrlIntc_override_PA				2
-#define NPHY_RfctrlIntc_override_EXT_LNA_PU		3
-#define NPHY_RfctrlIntc_override_EXT_LNA_GAIN	4
-#define RIFS_ENABLE			0x80
-#define BPHY_BAND_SEL_UP20		0x10
-#define NPHY_MLenable			0x02
-
-#define NPHY_RfseqMode_CoreActv_override 0x0001
-#define NPHY_RfseqMode_Trigger_override	0x0002
-#define NPHY_RfseqCoreActv_TxRxChain0	(0x11)
-#define NPHY_RfseqCoreActv_TxRxChain1	(0x22)
-
-#define NPHY_RfseqTrigger_rx2tx		0x0001
-#define NPHY_RfseqTrigger_tx2rx		0x0002
-#define NPHY_RfseqTrigger_updategainh	0x0004
-#define NPHY_RfseqTrigger_updategainl	0x0008
-#define NPHY_RfseqTrigger_updategainu	0x0010
-#define NPHY_RfseqTrigger_reset2rx	0x0020
-#define NPHY_RfseqStatus_rx2tx		0x0001
-#define NPHY_RfseqStatus_tx2rx		0x0002
-#define NPHY_RfseqStatus_updategainh	0x0004
-#define NPHY_RfseqStatus_updategainl	0x0008
-#define NPHY_RfseqStatus_updategainu	0x0010
-#define NPHY_RfseqStatus_reset2rx	0x0020
-#define NPHY_ClassifierCtrl_cck_en	0x1
-#define NPHY_ClassifierCtrl_ofdm_en	0x2
-#define NPHY_ClassifierCtrl_waited_en	0x4
-#define NPHY_IQFlip_ADC1		0x0001
-#define NPHY_IQFlip_ADC2		0x0010
-#define NPHY_sampleCmd_STOP		0x0002
-
-#define RX_GF_OR_MM			0x0004
-#define RX_GF_MM_AUTO			0x0100
-
-#define NPHY_iqloCalCmdGctl_IQLO_CAL_EN	0x8000
-
-#define NPHY_IqestCmd_iqstart		0x1
-#define NPHY_IqestCmd_iqMode		0x2
-
-#define NPHY_TxPwrCtrlCmd_pwrIndex_init		0x40
-#define NPHY_TxPwrCtrlCmd_pwrIndex_init_rev7	0x19
-
-#define PRIM_SEL_UP20		0x8000
-
-#define NPHY_RFSEQ_RX2TX		0x0
-#define NPHY_RFSEQ_TX2RX		0x1
-#define NPHY_RFSEQ_RESET2RX		0x2
-#define NPHY_RFSEQ_UPDATEGAINH		0x3
-#define NPHY_RFSEQ_UPDATEGAINL		0x4
-#define NPHY_RFSEQ_UPDATEGAINU		0x5
-
-#define NPHY_RFSEQ_CMD_NOP		0x0
-#define NPHY_RFSEQ_CMD_RXG_FBW		0x1
-#define NPHY_RFSEQ_CMD_TR_SWITCH	0x2
-#define NPHY_RFSEQ_CMD_EXT_PA		0x3
-#define NPHY_RFSEQ_CMD_RXPD_TXPD	0x4
-#define NPHY_RFSEQ_CMD_TX_GAIN		0x5
-#define NPHY_RFSEQ_CMD_RX_GAIN		0x6
-#define NPHY_RFSEQ_CMD_SET_HPF_BW	0x7
-#define NPHY_RFSEQ_CMD_CLR_HIQ_DIS	0x8
-#define NPHY_RFSEQ_CMD_END		0xf
-
-#define NPHY_REV3_RFSEQ_CMD_NOP		0x0
-#define NPHY_REV3_RFSEQ_CMD_RXG_FBW	0x1
-#define NPHY_REV3_RFSEQ_CMD_TR_SWITCH	0x2
-#define NPHY_REV3_RFSEQ_CMD_INT_PA_PU	0x3
-#define NPHY_REV3_RFSEQ_CMD_EXT_PA	0x4
-#define NPHY_REV3_RFSEQ_CMD_RXPD_TXPD	0x5
-#define NPHY_REV3_RFSEQ_CMD_TX_GAIN	0x6
-#define NPHY_REV3_RFSEQ_CMD_RX_GAIN	0x7
-#define NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS	0x8
-#define NPHY_REV3_RFSEQ_CMD_SET_HPF_H_HPC	0x9
-#define NPHY_REV3_RFSEQ_CMD_SET_LPF_H_HPC	0xa
-#define NPHY_REV3_RFSEQ_CMD_SET_HPF_M_HPC	0xb
-#define NPHY_REV3_RFSEQ_CMD_SET_LPF_M_HPC	0xc
-#define NPHY_REV3_RFSEQ_CMD_SET_HPF_L_HPC	0xd
-#define NPHY_REV3_RFSEQ_CMD_SET_LPF_L_HPC	0xe
-#define NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS	0xf
-#define NPHY_REV3_RFSEQ_CMD_END		0x1f
-
-#define NPHY_RSSI_SEL_W1 		0x0
-#define NPHY_RSSI_SEL_W2 		0x1
-#define NPHY_RSSI_SEL_NB 		0x2
-#define NPHY_RSSI_SEL_IQ 		0x3
-#define NPHY_RSSI_SEL_TSSI_2G 		0x4
-#define NPHY_RSSI_SEL_TSSI_5G 		0x5
-#define NPHY_RSSI_SEL_TBD 		0x6
-
-#define NPHY_RAIL_I			0x0
-#define NPHY_RAIL_Q			0x1
-
-#define NPHY_FORCESIG_DECODEGATEDCLKS	0x8
-
-#define NPHY_REV7_RfctrlOverride_cmd_rxrf_pu 0x0
-#define NPHY_REV7_RfctrlOverride_cmd_rx_pu   0x1
-#define NPHY_REV7_RfctrlOverride_cmd_tx_pu   0x2
-#define NPHY_REV7_RfctrlOverride_cmd_rxgain  0x3
-#define NPHY_REV7_RfctrlOverride_cmd_txgain  0x4
-
-#define NPHY_REV7_RXGAINCODE_RFMXGAIN_MASK 0x000ff
-#define NPHY_REV7_RXGAINCODE_LPFGAIN_MASK  0x0ff00
-#define NPHY_REV7_RXGAINCODE_DVGAGAIN_MASK 0xf0000
-
-#define NPHY_REV7_TXGAINCODE_TGAIN_MASK     0x7fff
-#define NPHY_REV7_TXGAINCODE_LPFGAIN_MASK   0x8000
-#define NPHY_REV7_TXGAINCODE_BIQ0GAIN_SHIFT 14
-
-#define NPHY_REV7_RFCTRLOVERRIDE_ID0 0x0
-#define NPHY_REV7_RFCTRLOVERRIDE_ID1 0x1
-#define NPHY_REV7_RFCTRLOVERRIDE_ID2 0x2
-
-#define NPHY_IqestIqAccLo(core)  ((core == 0) ? 0x12c : 0x134)
-
-#define NPHY_IqestIqAccHi(core)  ((core == 0) ? 0x12d : 0x135)
-
-#define NPHY_IqestipwrAccLo(core)  ((core == 0) ? 0x12e : 0x136)
-
-#define NPHY_IqestipwrAccHi(core)  ((core == 0) ? 0x12f : 0x137)
-
-#define NPHY_IqestqpwrAccLo(core)  ((core == 0) ? 0x130 : 0x138)
-
-#define NPHY_IqestqpwrAccHi(core)  ((core == 0) ? 0x131 : 0x139)
diff --git a/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c b/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c
deleted file mode 100644
index 330b881..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.c
+++ /dev/null
@@ -1,3641 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <osl.h>
-#include <wlc_phy_int.h>
-#include <wlc_phytbl_lcn.h>
-
-const u32 dot11lcn_gain_tbl_rev0[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000004,
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x000000cd,
-	0x0000004f,
-	0x0000008f,
-	0x000000cf,
-	0x000000d3,
-	0x00000113,
-	0x00000513,
-	0x00000913,
-	0x00000953,
-	0x00000d53,
-	0x00001153,
-	0x00001193,
-	0x00005193,
-	0x00009193,
-	0x0000d193,
-	0x00011193,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000004,
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x000000cd,
-	0x0000004f,
-	0x0000008f,
-	0x000000cf,
-	0x000000d3,
-	0x00000113,
-	0x00000513,
-	0x00000913,
-	0x00000953,
-	0x00000d53,
-	0x00001153,
-	0x00005153,
-	0x00009153,
-	0x0000d153,
-	0x00011153,
-	0x00015153,
-	0x00019153,
-	0x0001d153,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 dot11lcn_gain_tbl_rev1[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000D,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x000000d1,
-	0x00000053,
-	0x00000093,
-	0x000000d3,
-	0x000000d7,
-	0x00000117,
-	0x00000517,
-	0x00000917,
-	0x00000957,
-	0x00000d57,
-	0x00001157,
-	0x00001197,
-	0x00005197,
-	0x00009197,
-	0x0000d197,
-	0x00011197,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000D,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x00000011,
-	0x00000051,
-	0x00000091,
-	0x000000d1,
-	0x00000053,
-	0x00000093,
-	0x000000d3,
-	0x000000d7,
-	0x00000117,
-	0x00000517,
-	0x00000917,
-	0x00000957,
-	0x00000d57,
-	0x00001157,
-	0x00005157,
-	0x00009157,
-	0x0000d157,
-	0x00011157,
-	0x00015157,
-	0x00019157,
-	0x0001d157,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 dot11lcn_aux_gain_idx_tbl_rev0[] = {
-	0x0401,
-	0x0402,
-	0x0403,
-	0x0404,
-	0x0405,
-	0x0406,
-	0x0407,
-	0x0408,
-	0x0409,
-	0x040a,
-	0x058b,
-	0x058c,
-	0x058d,
-	0x058e,
-	0x058f,
-	0x0090,
-	0x0091,
-	0x0092,
-	0x0193,
-	0x0194,
-	0x0195,
-	0x0196,
-	0x0197,
-	0x0198,
-	0x0199,
-	0x019a,
-	0x019b,
-	0x019c,
-	0x019d,
-	0x019e,
-	0x019f,
-	0x01a0,
-	0x01a1,
-	0x01a2,
-	0x01a3,
-	0x01a4,
-	0x01a5,
-	0x0000,
-};
-
-const u32 dot11lcn_gain_idx_tbl_rev0[] = {
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x20000000,
-	0x00000000,
-	0x30000000,
-	0x00000000,
-	0x40000000,
-	0x00000000,
-	0x50000000,
-	0x00000000,
-	0x60000000,
-	0x00000000,
-	0x70000000,
-	0x00000000,
-	0x80000000,
-	0x00000000,
-	0x90000000,
-	0x00000008,
-	0xa0000000,
-	0x00000008,
-	0xb0000000,
-	0x00000008,
-	0xc0000000,
-	0x00000008,
-	0xd0000000,
-	0x00000008,
-	0xe0000000,
-	0x00000008,
-	0xf0000000,
-	0x00000008,
-	0x00000000,
-	0x00000009,
-	0x10000000,
-	0x00000009,
-	0x20000000,
-	0x00000019,
-	0x30000000,
-	0x00000019,
-	0x40000000,
-	0x00000019,
-	0x50000000,
-	0x00000019,
-	0x60000000,
-	0x00000019,
-	0x70000000,
-	0x00000019,
-	0x80000000,
-	0x00000019,
-	0x90000000,
-	0x00000019,
-	0xa0000000,
-	0x00000019,
-	0xb0000000,
-	0x00000019,
-	0xc0000000,
-	0x00000019,
-	0xd0000000,
-	0x00000019,
-	0xe0000000,
-	0x00000019,
-	0xf0000000,
-	0x00000019,
-	0x00000000,
-	0x0000001a,
-	0x10000000,
-	0x0000001a,
-	0x20000000,
-	0x0000001a,
-	0x30000000,
-	0x0000001a,
-	0x40000000,
-	0x0000001a,
-	0x50000000,
-	0x00000002,
-	0x60000000,
-	0x00000002,
-	0x70000000,
-	0x00000002,
-	0x80000000,
-	0x00000002,
-	0x90000000,
-	0x00000002,
-	0xa0000000,
-	0x00000002,
-	0xb0000000,
-	0x00000002,
-	0xc0000000,
-	0x0000000a,
-	0xd0000000,
-	0x0000000a,
-	0xe0000000,
-	0x0000000a,
-	0xf0000000,
-	0x0000000a,
-	0x00000000,
-	0x0000000b,
-	0x10000000,
-	0x0000000b,
-	0x20000000,
-	0x0000000b,
-	0x30000000,
-	0x0000000b,
-	0x40000000,
-	0x0000000b,
-	0x50000000,
-	0x0000001b,
-	0x60000000,
-	0x0000001b,
-	0x70000000,
-	0x0000001b,
-	0x80000000,
-	0x0000001b,
-	0x90000000,
-	0x0000001b,
-	0xa0000000,
-	0x0000001b,
-	0xb0000000,
-	0x0000001b,
-	0xc0000000,
-	0x0000001b,
-	0xd0000000,
-	0x0000001b,
-	0xe0000000,
-	0x0000001b,
-	0xf0000000,
-	0x0000001b,
-	0x00000000,
-	0x0000001c,
-	0x10000000,
-	0x0000001c,
-	0x20000000,
-	0x0000001c,
-	0x30000000,
-	0x0000001c,
-	0x40000000,
-	0x0000001c,
-	0x50000000,
-	0x0000001c,
-	0x60000000,
-	0x0000001c,
-	0x70000000,
-	0x0000001c,
-	0x80000000,
-	0x0000001c,
-	0x90000000,
-	0x0000001c,
-};
-
-const u16 dot11lcn_aux_gain_idx_tbl_2G[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0001,
-	0x0080,
-	0x0081,
-	0x0100,
-	0x0101,
-	0x0180,
-	0x0181,
-	0x0182,
-	0x0183,
-	0x0184,
-	0x0185,
-	0x0186,
-	0x0187,
-	0x0188,
-	0x0285,
-	0x0289,
-	0x028a,
-	0x028b,
-	0x028c,
-	0x028d,
-	0x028e,
-	0x028f,
-	0x0290,
-	0x0291,
-	0x0292,
-	0x0293,
-	0x0294,
-	0x0295,
-	0x0296,
-	0x0297,
-	0x0298,
-	0x0299,
-	0x029a,
-	0x0000
-};
-
-const u8 dot11lcn_gain_val_tbl_2G[] = {
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x00,
-	0x0c,
-	0x03,
-	0xeb,
-	0xfe,
-	0x07,
-	0x0b,
-	0x0f,
-	0xfb,
-	0xfe,
-	0x01,
-	0x05,
-	0x08,
-	0x0b,
-	0x0e,
-	0x11,
-	0x14,
-	0x17,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-const u32 dot11lcn_gain_idx_tbl_2G[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x10000000,
-	0x00000008,
-	0x00000000,
-	0x00000010,
-	0x10000000,
-	0x00000010,
-	0x00000000,
-	0x00000018,
-	0x10000000,
-	0x00000018,
-	0x20000000,
-	0x00000018,
-	0x30000000,
-	0x00000018,
-	0x40000000,
-	0x00000018,
-	0x50000000,
-	0x00000018,
-	0x60000000,
-	0x00000018,
-	0x70000000,
-	0x00000018,
-	0x80000000,
-	0x00000018,
-	0x50000000,
-	0x00000028,
-	0x90000000,
-	0x00000028,
-	0xa0000000,
-	0x00000028,
-	0xb0000000,
-	0x00000028,
-	0xc0000000,
-	0x00000028,
-	0xd0000000,
-	0x00000028,
-	0xe0000000,
-	0x00000028,
-	0xf0000000,
-	0x00000028,
-	0x00000000,
-	0x00000029,
-	0x10000000,
-	0x00000029,
-	0x20000000,
-	0x00000029,
-	0x30000000,
-	0x00000029,
-	0x40000000,
-	0x00000029,
-	0x50000000,
-	0x00000029,
-	0x60000000,
-	0x00000029,
-	0x70000000,
-	0x00000029,
-	0x80000000,
-	0x00000029,
-	0x90000000,
-	0x00000029,
-	0xa0000000,
-	0x00000029,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x00000000,
-	0x00000008,
-	0x10000000,
-	0x00000008,
-	0x00000000,
-	0x00000010,
-	0x10000000,
-	0x00000010,
-	0x00000000,
-	0x00000018,
-	0x10000000,
-	0x00000018,
-	0x20000000,
-	0x00000018,
-	0x30000000,
-	0x00000018,
-	0x40000000,
-	0x00000018,
-	0x50000000,
-	0x00000018,
-	0x60000000,
-	0x00000018,
-	0x70000000,
-	0x00000018,
-	0x80000000,
-	0x00000018,
-	0x50000000,
-	0x00000028,
-	0x90000000,
-	0x00000028,
-	0xa0000000,
-	0x00000028,
-	0xb0000000,
-	0x00000028,
-	0xc0000000,
-	0x00000028,
-	0xd0000000,
-	0x00000028,
-	0xe0000000,
-	0x00000028,
-	0xf0000000,
-	0x00000028,
-	0x00000000,
-	0x00000029,
-	0x10000000,
-	0x00000029,
-	0x20000000,
-	0x00000029,
-	0x30000000,
-	0x00000029,
-	0x40000000,
-	0x00000029,
-	0x50000000,
-	0x00000029,
-	0x60000000,
-	0x00000029,
-	0x70000000,
-	0x00000029,
-	0x80000000,
-	0x00000029,
-	0x90000000,
-	0x00000029,
-	0xa0000000,
-	0x00000029,
-	0xb0000000,
-	0x00000029,
-	0xc0000000,
-	0x00000029,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_gain_tbl_2G[] = {
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x0000004d,
-	0x0000008d,
-	0x00000049,
-	0x00000089,
-	0x000000c9,
-	0x0000004b,
-	0x0000008b,
-	0x000000cb,
-	0x000000cf,
-	0x0000010f,
-	0x0000050f,
-	0x0000090f,
-	0x0000094f,
-	0x00000d4f,
-	0x0000114f,
-	0x0000118f,
-	0x0000518f,
-	0x0000918f,
-	0x0000d18f,
-	0x0001118f,
-	0x0001518f,
-	0x0001918f,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_gain_tbl_extlna_2G[] = {
-	0x00000000,
-	0x00000004,
-	0x00000008,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x00000003,
-	0x00000007,
-	0x0000000b,
-	0x0000000f,
-	0x0000004f,
-	0x0000008f,
-	0x000000cf,
-	0x0000010f,
-	0x0000014f,
-	0x0000018f,
-	0x0000058f,
-	0x0000098f,
-	0x00000d8f,
-	0x00008000,
-	0x00008004,
-	0x00008008,
-	0x00008001,
-	0x00008005,
-	0x00008009,
-	0x0000800d,
-	0x00008003,
-	0x00008007,
-	0x0000800b,
-	0x0000800f,
-	0x0000804f,
-	0x0000808f,
-	0x000080cf,
-	0x0000810f,
-	0x0000814f,
-	0x0000818f,
-	0x0000858f,
-	0x0000898f,
-	0x00008d8f,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u16 dot11lcn_aux_gain_idx_tbl_extlna_2G[] = {
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0400,
-	0x0401,
-	0x0402,
-	0x0403,
-	0x0404,
-	0x0483,
-	0x0484,
-	0x0485,
-	0x0486,
-	0x0583,
-	0x0584,
-	0x0585,
-	0x0587,
-	0x0588,
-	0x0589,
-	0x058a,
-	0x0687,
-	0x0688,
-	0x0689,
-	0x068a,
-	0x068b,
-	0x068c,
-	0x068d,
-	0x068e,
-	0x068f,
-	0x0690,
-	0x0691,
-	0x0692,
-	0x0693,
-	0x0000
-};
-
-const u8 dot11lcn_gain_val_tbl_extlna_2G[] = {
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x02,
-	0x08,
-	0x0e,
-	0x13,
-	0x1b,
-	0xfc,
-	0x00,
-	0x0f,
-	0x03,
-	0xeb,
-	0xfe,
-	0x07,
-	0x0b,
-	0x0f,
-	0xfb,
-	0xfe,
-	0x01,
-	0x05,
-	0x08,
-	0x0b,
-	0x0e,
-	0x11,
-	0x14,
-	0x17,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-const u32 dot11lcn_gain_idx_tbl_extlna_2G[] = {
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x00000000,
-	0x00000040,
-	0x10000000,
-	0x00000040,
-	0x20000000,
-	0x00000040,
-	0x30000000,
-	0x00000040,
-	0x40000000,
-	0x00000040,
-	0x30000000,
-	0x00000048,
-	0x40000000,
-	0x00000048,
-	0x50000000,
-	0x00000048,
-	0x60000000,
-	0x00000048,
-	0x30000000,
-	0x00000058,
-	0x40000000,
-	0x00000058,
-	0x50000000,
-	0x00000058,
-	0x70000000,
-	0x00000058,
-	0x80000000,
-	0x00000058,
-	0x90000000,
-	0x00000058,
-	0xa0000000,
-	0x00000058,
-	0x70000000,
-	0x00000068,
-	0x80000000,
-	0x00000068,
-	0x90000000,
-	0x00000068,
-	0xa0000000,
-	0x00000068,
-	0xb0000000,
-	0x00000068,
-	0xc0000000,
-	0x00000068,
-	0xd0000000,
-	0x00000068,
-	0xe0000000,
-	0x00000068,
-	0xf0000000,
-	0x00000068,
-	0x00000000,
-	0x00000069,
-	0x10000000,
-	0x00000069,
-	0x20000000,
-	0x00000069,
-	0x30000000,
-	0x00000069,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x40000000,
-	0x00000041,
-	0x50000000,
-	0x00000041,
-	0x60000000,
-	0x00000041,
-	0x70000000,
-	0x00000041,
-	0x80000000,
-	0x00000041,
-	0x70000000,
-	0x00000049,
-	0x80000000,
-	0x00000049,
-	0x90000000,
-	0x00000049,
-	0xa0000000,
-	0x00000049,
-	0x70000000,
-	0x00000059,
-	0x80000000,
-	0x00000059,
-	0x90000000,
-	0x00000059,
-	0xb0000000,
-	0x00000059,
-	0xc0000000,
-	0x00000059,
-	0xd0000000,
-	0x00000059,
-	0xe0000000,
-	0x00000059,
-	0xb0000000,
-	0x00000069,
-	0xc0000000,
-	0x00000069,
-	0xd0000000,
-	0x00000069,
-	0xe0000000,
-	0x00000069,
-	0xf0000000,
-	0x00000069,
-	0x00000000,
-	0x0000006a,
-	0x10000000,
-	0x0000006a,
-	0x20000000,
-	0x0000006a,
-	0x30000000,
-	0x0000006a,
-	0x40000000,
-	0x0000006a,
-	0x50000000,
-	0x0000006a,
-	0x60000000,
-	0x0000006a,
-	0x70000000,
-	0x0000006a,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_aux_gain_idx_tbl_5G[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0001,
-	0x0002,
-	0x0003,
-	0x0004,
-	0x0083,
-	0x0084,
-	0x0085,
-	0x0086,
-	0x0087,
-	0x0186,
-	0x0187,
-	0x0188,
-	0x0189,
-	0x018a,
-	0x018b,
-	0x018c,
-	0x018d,
-	0x018e,
-	0x018f,
-	0x0190,
-	0x0191,
-	0x0192,
-	0x0193,
-	0x0194,
-	0x0195,
-	0x0196,
-	0x0197,
-	0x0198,
-	0x0199,
-	0x019a,
-	0x019b,
-	0x019c,
-	0x019d,
-	0x0000
-};
-
-const u32 dot11lcn_gain_val_tbl_5G[] = {
-	0xf7,
-	0xfd,
-	0x00,
-	0x04,
-	0x04,
-	0x04,
-	0xf7,
-	0xfd,
-	0x00,
-	0x04,
-	0x04,
-	0x04,
-	0xf6,
-	0x00,
-	0x0c,
-	0x03,
-	0xeb,
-	0xfe,
-	0x06,
-	0x0a,
-	0x10,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00
-};
-
-const u32 dot11lcn_gain_idx_tbl_5G[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x10000000,
-	0x00000000,
-	0x20000000,
-	0x00000000,
-	0x30000000,
-	0x00000000,
-	0x40000000,
-	0x00000000,
-	0x30000000,
-	0x00000008,
-	0x40000000,
-	0x00000008,
-	0x50000000,
-	0x00000008,
-	0x60000000,
-	0x00000008,
-	0x70000000,
-	0x00000008,
-	0x60000000,
-	0x00000018,
-	0x70000000,
-	0x00000018,
-	0x80000000,
-	0x00000018,
-	0x90000000,
-	0x00000018,
-	0xa0000000,
-	0x00000018,
-	0xb0000000,
-	0x00000018,
-	0xc0000000,
-	0x00000018,
-	0xd0000000,
-	0x00000018,
-	0xe0000000,
-	0x00000018,
-	0xf0000000,
-	0x00000018,
-	0x00000000,
-	0x00000019,
-	0x10000000,
-	0x00000019,
-	0x20000000,
-	0x00000019,
-	0x30000000,
-	0x00000019,
-	0x40000000,
-	0x00000019,
-	0x50000000,
-	0x00000019,
-	0x60000000,
-	0x00000019,
-	0x70000000,
-	0x00000019,
-	0x80000000,
-	0x00000019,
-	0x90000000,
-	0x00000019,
-	0xa0000000,
-	0x00000019,
-	0xb0000000,
-	0x00000019,
-	0xc0000000,
-	0x00000019,
-	0xd0000000,
-	0x00000019,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const u32 dot11lcn_gain_tbl_5G[] = {
-	0x00000000,
-	0x00000040,
-	0x00000080,
-	0x00000001,
-	0x00000005,
-	0x00000009,
-	0x0000000d,
-	0x00000011,
-	0x00000015,
-	0x00000055,
-	0x00000095,
-	0x00000017,
-	0x0000001b,
-	0x0000005b,
-	0x0000009b,
-	0x000000db,
-	0x0000011b,
-	0x0000015b,
-	0x0000019b,
-	0x0000059b,
-	0x0000099b,
-	0x00000d9b,
-	0x0000119b,
-	0x0000519b,
-	0x0000919b,
-	0x0000d19b,
-	0x0001119b,
-	0x0001519b,
-	0x0001919b,
-	0x0001d19b,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev0[] = {
-	{&dot11lcn_gain_tbl_rev0,
-	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
-	 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
-	,
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[] = {
-	{&dot11lcn_gain_tbl_rev1,
-	 sizeof(dot11lcn_gain_tbl_rev1) / sizeof(dot11lcn_gain_tbl_rev1[0]), 18,
-	 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
-	,
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_2G_rev2[] = {
-	{&dot11lcn_gain_tbl_2G,
-	 sizeof(dot11lcn_gain_tbl_2G) / sizeof(dot11lcn_gain_tbl_2G[0]), 18, 0,
-	 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_2G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_2G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_2G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_2G,
-	 sizeof(dot11lcn_gain_idx_tbl_2G) / sizeof(dot11lcn_gain_idx_tbl_2G[0]),
-	 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_2G,
-	 sizeof(dot11lcn_gain_val_tbl_2G) / sizeof(dot11lcn_gain_val_tbl_2G[0]),
-	 17, 0, 8}
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_5G_rev2[] = {
-	{&dot11lcn_gain_tbl_5G,
-	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
-	 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
-	 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_5G,
-	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
-	 17, 0, 8}
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[] = {
-	{&dot11lcn_gain_tbl_extlna_2G,
-	 sizeof(dot11lcn_gain_tbl_extlna_2G) /
-	 sizeof(dot11lcn_gain_tbl_extlna_2G[0]), 18, 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_extlna_2G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_extlna_2G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_extlna_2G,
-	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G) /
-	 sizeof(dot11lcn_gain_idx_tbl_extlna_2G[0]), 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_extlna_2G,
-	 sizeof(dot11lcn_gain_val_tbl_extlna_2G) /
-	 sizeof(dot11lcn_gain_val_tbl_extlna_2G[0]), 17, 0, 8}
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[] = {
-	{&dot11lcn_gain_tbl_5G,
-	 sizeof(dot11lcn_gain_tbl_5G) / sizeof(dot11lcn_gain_tbl_5G[0]), 18, 0,
-	 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_5G[0]), 14, 0, 16}
-	,
-	{&dot11lcn_gain_idx_tbl_5G,
-	 sizeof(dot11lcn_gain_idx_tbl_5G) / sizeof(dot11lcn_gain_idx_tbl_5G[0]),
-	 13, 0, 32}
-	,
-	{&dot11lcn_gain_val_tbl_5G,
-	 sizeof(dot11lcn_gain_val_tbl_5G) / sizeof(dot11lcn_gain_val_tbl_5G[0]),
-	 17, 0, 8}
-};
-
-const u32 dot11lcnphytbl_rx_gain_info_sz_rev0 =
-    sizeof(dot11lcnphytbl_rx_gain_info_rev0) /
-    sizeof(dot11lcnphytbl_rx_gain_info_rev0[0]);
-
-const u32 dot11lcnphytbl_rx_gain_info_sz_rev1 =
-    sizeof(dot11lcnphytbl_rx_gain_info_rev1) /
-    sizeof(dot11lcnphytbl_rx_gain_info_rev1[0]);
-
-const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz =
-    sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2) /
-    sizeof(dot11lcnphytbl_rx_gain_info_2G_rev2[0]);
-
-const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz =
-    sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2) /
-    sizeof(dot11lcnphytbl_rx_gain_info_5G_rev2[0]);
-
-const u16 dot11lcn_min_sig_sq_tbl_rev0[] = {
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-	0x014d,
-};
-
-const u16 dot11lcn_noise_scale_tbl_rev0[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u32 dot11lcn_fltr_ctrl_tbl_rev0[] = {
-	0x000141f8,
-	0x000021f8,
-	0x000021fb,
-	0x000041fb,
-	0x0001fe4b,
-	0x0000217b,
-	0x00002133,
-	0x000040eb,
-	0x0001fea3,
-	0x0000024b,
-};
-
-const u32 dot11lcn_ps_ctrl_tbl_rev0[] = {
-	0x00100001,
-	0x00200010,
-	0x00300001,
-	0x00400010,
-	0x00500022,
-	0x00600122,
-	0x00700222,
-	0x00800322,
-	0x00900422,
-	0x00a00522,
-	0x00b00622,
-	0x00c00722,
-	0x00d00822,
-	0x00f00922,
-	0x00100a22,
-	0x00200b22,
-	0x00300c22,
-	0x00400d22,
-	0x00500e22,
-	0x00600f22,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[] = {
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x0007,
-	0x0005,
-	0x0006,
-	0x0004,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-	0x000b,
-	0x000b,
-	0x000a,
-	0x000a,
-
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[] = {
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0005,
-	0x0002,
-	0x0000,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-	0x0007,
-	0x0007,
-	0x0002,
-	0x0002,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-	0x0002,
-	0x0008,
-	0x0004,
-	0x0001,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-	0x000a,
-	0x0009,
-	0x0006,
-	0x0005,
-};
-
-const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-	0x0004,
-	0x0004,
-	0x0002,
-	0x0002,
-};
-
-const u8 dot11lcn_nf_table_rev0[] = {
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-	0x5f,
-	0x36,
-	0x29,
-	0x1f,
-};
-
-const u8 dot11lcn_gain_val_tbl_rev0[] = {
-	0x09,
-	0x0f,
-	0x14,
-	0x18,
-	0xfe,
-	0x07,
-	0x0b,
-	0x0f,
-	0xfb,
-	0xfe,
-	0x01,
-	0x05,
-	0x08,
-	0x0b,
-	0x0e,
-	0x11,
-	0x14,
-	0x17,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0x06,
-	0x09,
-	0x0c,
-	0x0f,
-	0x12,
-	0x15,
-	0x18,
-	0x1b,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x03,
-	0xeb,
-	0x00,
-	0x00,
-};
-
-const u8 dot11lcn_spur_tbl_rev0[] = {
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x02,
-	0x03,
-	0x01,
-	0x03,
-	0x02,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x02,
-	0x03,
-	0x01,
-	0x03,
-	0x02,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-	0x01,
-};
-
-const u16 dot11lcn_unsup_mcs_tbl_rev0[] = {
-	0x001a,
-	0x0034,
-	0x004e,
-	0x0068,
-	0x009c,
-	0x00d0,
-	0x00ea,
-	0x0104,
-	0x0034,
-	0x0068,
-	0x009c,
-	0x00d0,
-	0x0138,
-	0x01a0,
-	0x01d4,
-	0x0208,
-	0x004e,
-	0x009c,
-	0x00ea,
-	0x0138,
-	0x01d4,
-	0x0270,
-	0x02be,
-	0x030c,
-	0x0068,
-	0x00d0,
-	0x0138,
-	0x01a0,
-	0x0270,
-	0x0340,
-	0x03a8,
-	0x0410,
-	0x0018,
-	0x009c,
-	0x00d0,
-	0x0104,
-	0x00ea,
-	0x0138,
-	0x0186,
-	0x00d0,
-	0x0104,
-	0x0104,
-	0x0138,
-	0x016c,
-	0x016c,
-	0x01a0,
-	0x0138,
-	0x0186,
-	0x0186,
-	0x01d4,
-	0x0222,
-	0x0222,
-	0x0270,
-	0x0104,
-	0x0138,
-	0x016c,
-	0x0138,
-	0x016c,
-	0x01a0,
-	0x01d4,
-	0x01a0,
-	0x01d4,
-	0x0208,
-	0x0208,
-	0x023c,
-	0x0186,
-	0x01d4,
-	0x0222,
-	0x01d4,
-	0x0222,
-	0x0270,
-	0x02be,
-	0x0270,
-	0x02be,
-	0x030c,
-	0x030c,
-	0x035a,
-	0x0036,
-	0x006c,
-	0x00a2,
-	0x00d8,
-	0x0144,
-	0x01b0,
-	0x01e6,
-	0x021c,
-	0x006c,
-	0x00d8,
-	0x0144,
-	0x01b0,
-	0x0288,
-	0x0360,
-	0x03cc,
-	0x0438,
-	0x00a2,
-	0x0144,
-	0x01e6,
-	0x0288,
-	0x03cc,
-	0x0510,
-	0x05b2,
-	0x0654,
-	0x00d8,
-	0x01b0,
-	0x0288,
-	0x0360,
-	0x0510,
-	0x06c0,
-	0x0798,
-	0x0870,
-	0x0018,
-	0x0144,
-	0x01b0,
-	0x021c,
-	0x01e6,
-	0x0288,
-	0x032a,
-	0x01b0,
-	0x021c,
-	0x021c,
-	0x0288,
-	0x02f4,
-	0x02f4,
-	0x0360,
-	0x0288,
-	0x032a,
-	0x032a,
-	0x03cc,
-	0x046e,
-	0x046e,
-	0x0510,
-	0x021c,
-	0x0288,
-	0x02f4,
-	0x0288,
-	0x02f4,
-	0x0360,
-	0x03cc,
-	0x0360,
-	0x03cc,
-	0x0438,
-	0x0438,
-	0x04a4,
-	0x032a,
-	0x03cc,
-	0x046e,
-	0x03cc,
-	0x046e,
-	0x0510,
-	0x05b2,
-	0x0510,
-	0x05b2,
-	0x0654,
-	0x0654,
-	0x06f6,
-};
-
-const u16 dot11lcn_iq_local_tbl_rev0[] = {
-	0x0200,
-	0x0300,
-	0x0400,
-	0x0600,
-	0x0800,
-	0x0b00,
-	0x1000,
-	0x1001,
-	0x1002,
-	0x1003,
-	0x1004,
-	0x1005,
-	0x1006,
-	0x1007,
-	0x1707,
-	0x2007,
-	0x2d07,
-	0x4007,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0200,
-	0x0300,
-	0x0400,
-	0x0600,
-	0x0800,
-	0x0b00,
-	0x1000,
-	0x1001,
-	0x1002,
-	0x1003,
-	0x1004,
-	0x1005,
-	0x1006,
-	0x1007,
-	0x1707,
-	0x2007,
-	0x2d07,
-	0x4007,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x4000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u32 dot11lcn_papd_compdelta_tbl_rev0[] = {
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-	0x00080000,
-};
-
-const dot11lcnphytbl_info_t dot11lcnphytbl_info_rev0[] = {
-	{&dot11lcn_min_sig_sq_tbl_rev0,
-	 sizeof(dot11lcn_min_sig_sq_tbl_rev0) /
-	 sizeof(dot11lcn_min_sig_sq_tbl_rev0[0]), 2, 0, 16}
-	,
-	{&dot11lcn_noise_scale_tbl_rev0,
-	 sizeof(dot11lcn_noise_scale_tbl_rev0) /
-	 sizeof(dot11lcn_noise_scale_tbl_rev0[0]), 1, 0, 16}
-	,
-	{&dot11lcn_fltr_ctrl_tbl_rev0,
-	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0) /
-	 sizeof(dot11lcn_fltr_ctrl_tbl_rev0[0]), 11, 0, 32}
-	,
-	{&dot11lcn_ps_ctrl_tbl_rev0,
-	 sizeof(dot11lcn_ps_ctrl_tbl_rev0) /
-	 sizeof(dot11lcn_ps_ctrl_tbl_rev0[0]), 12, 0, 32}
-	,
-	{&dot11lcn_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_gain_idx_tbl_rev0[0]), 13, 0, 32}
-	,
-	{&dot11lcn_aux_gain_idx_tbl_rev0,
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0) /
-	 sizeof(dot11lcn_aux_gain_idx_tbl_rev0[0]), 14, 0, 16}
-	,
-	{&dot11lcn_sw_ctrl_tbl_rev0,
-	 sizeof(dot11lcn_sw_ctrl_tbl_rev0) /
-	 sizeof(dot11lcn_sw_ctrl_tbl_rev0[0]), 15, 0, 16}
-	,
-	{&dot11lcn_nf_table_rev0,
-	 sizeof(dot11lcn_nf_table_rev0) / sizeof(dot11lcn_nf_table_rev0[0]), 16,
-	 0, 8}
-	,
-	{&dot11lcn_gain_val_tbl_rev0,
-	 sizeof(dot11lcn_gain_val_tbl_rev0) /
-	 sizeof(dot11lcn_gain_val_tbl_rev0[0]), 17, 0, 8}
-	,
-	{&dot11lcn_gain_tbl_rev0,
-	 sizeof(dot11lcn_gain_tbl_rev0) / sizeof(dot11lcn_gain_tbl_rev0[0]), 18,
-	 0, 32}
-	,
-	{&dot11lcn_spur_tbl_rev0,
-	 sizeof(dot11lcn_spur_tbl_rev0) / sizeof(dot11lcn_spur_tbl_rev0[0]), 20,
-	 0, 8}
-	,
-	{&dot11lcn_unsup_mcs_tbl_rev0,
-	 sizeof(dot11lcn_unsup_mcs_tbl_rev0) /
-	 sizeof(dot11lcn_unsup_mcs_tbl_rev0[0]), 23, 0, 16}
-	,
-	{&dot11lcn_iq_local_tbl_rev0,
-	 sizeof(dot11lcn_iq_local_tbl_rev0) /
-	 sizeof(dot11lcn_iq_local_tbl_rev0[0]), 0, 0, 16}
-	,
-	{&dot11lcn_papd_compdelta_tbl_rev0,
-	 sizeof(dot11lcn_papd_compdelta_tbl_rev0) /
-	 sizeof(dot11lcn_papd_compdelta_tbl_rev0[0]), 24, 0, 32}
-	,
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313 = {
-	&dot11lcn_sw_ctrl_tbl_4313_rev0,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_rev0[0]), 15, 0, 16
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa = {
-	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0[0]), 15, 0, 16
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa = {
-	&dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_epa_rev0_combo[0]), 15, 0, 16
-};
-
-const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250 = {
-	&dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0,
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0) /
-	    sizeof(dot11lcn_sw_ctrl_tbl_4313_bt_epa_p250_rev0[0]), 15, 0, 16
-};
-
-const u32 dot11lcnphytbl_info_sz_rev0 =
-    sizeof(dot11lcnphytbl_info_rev0) / sizeof(dot11lcnphytbl_info_rev0[0]);
-
-const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[128] = {
-	{3, 0, 31, 0, 72,}
-	,
-	{3, 0, 31, 0, 70,}
-	,
-	{3, 0, 31, 0, 68,}
-	,
-	{3, 0, 30, 0, 67,}
-	,
-	{3, 0, 29, 0, 68,}
-	,
-	{3, 0, 28, 0, 68,}
-	,
-	{3, 0, 27, 0, 69,}
-	,
-	{3, 0, 26, 0, 70,}
-	,
-	{3, 0, 25, 0, 70,}
-	,
-	{3, 0, 24, 0, 71,}
-	,
-	{3, 0, 23, 0, 72,}
-	,
-	{3, 0, 23, 0, 70,}
-	,
-	{3, 0, 22, 0, 71,}
-	,
-	{3, 0, 21, 0, 72,}
-	,
-	{3, 0, 21, 0, 70,}
-	,
-	{3, 0, 21, 0, 68,}
-	,
-	{3, 0, 21, 0, 66,}
-	,
-	{3, 0, 21, 0, 64,}
-	,
-	{3, 0, 21, 0, 63,}
-	,
-	{3, 0, 20, 0, 64,}
-	,
-	{3, 0, 19, 0, 65,}
-	,
-	{3, 0, 19, 0, 64,}
-	,
-	{3, 0, 18, 0, 65,}
-	,
-	{3, 0, 18, 0, 64,}
-	,
-	{3, 0, 17, 0, 65,}
-	,
-	{3, 0, 17, 0, 64,}
-	,
-	{3, 0, 16, 0, 65,}
-	,
-	{3, 0, 16, 0, 64,}
-	,
-	{3, 0, 16, 0, 62,}
-	,
-	{3, 0, 16, 0, 60,}
-	,
-	{3, 0, 16, 0, 58,}
-	,
-	{3, 0, 15, 0, 61,}
-	,
-	{3, 0, 15, 0, 59,}
-	,
-	{3, 0, 14, 0, 61,}
-	,
-	{3, 0, 14, 0, 60,}
-	,
-	{3, 0, 14, 0, 58,}
-	,
-	{3, 0, 13, 0, 60,}
-	,
-	{3, 0, 13, 0, 59,}
-	,
-	{3, 0, 12, 0, 62,}
-	,
-	{3, 0, 12, 0, 60,}
-	,
-	{3, 0, 12, 0, 58,}
-	,
-	{3, 0, 11, 0, 62,}
-	,
-	{3, 0, 11, 0, 60,}
-	,
-	{3, 0, 11, 0, 59,}
-	,
-	{3, 0, 11, 0, 57,}
-	,
-	{3, 0, 10, 0, 61,}
-	,
-	{3, 0, 10, 0, 59,}
-	,
-	{3, 0, 10, 0, 57,}
-	,
-	{3, 0, 9, 0, 62,}
-	,
-	{3, 0, 9, 0, 60,}
-	,
-	{3, 0, 9, 0, 58,}
-	,
-	{3, 0, 9, 0, 57,}
-	,
-	{3, 0, 8, 0, 62,}
-	,
-	{3, 0, 8, 0, 60,}
-	,
-	{3, 0, 8, 0, 58,}
-	,
-	{3, 0, 8, 0, 57,}
-	,
-	{3, 0, 8, 0, 55,}
-	,
-	{3, 0, 7, 0, 61,}
-	,
-	{3, 0, 7, 0, 60,}
-	,
-	{3, 0, 7, 0, 58,}
-	,
-	{3, 0, 7, 0, 56,}
-	,
-	{3, 0, 7, 0, 55,}
-	,
-	{3, 0, 6, 0, 62,}
-	,
-	{3, 0, 6, 0, 60,}
-	,
-	{3, 0, 6, 0, 58,}
-	,
-	{3, 0, 6, 0, 57,}
-	,
-	{3, 0, 6, 0, 55,}
-	,
-	{3, 0, 6, 0, 54,}
-	,
-	{3, 0, 6, 0, 52,}
-	,
-	{3, 0, 5, 0, 61,}
-	,
-	{3, 0, 5, 0, 59,}
-	,
-	{3, 0, 5, 0, 57,}
-	,
-	{3, 0, 5, 0, 56,}
-	,
-	{3, 0, 5, 0, 54,}
-	,
-	{3, 0, 5, 0, 53,}
-	,
-	{3, 0, 5, 0, 51,}
-	,
-	{3, 0, 4, 0, 62,}
-	,
-	{3, 0, 4, 0, 60,}
-	,
-	{3, 0, 4, 0, 58,}
-	,
-	{3, 0, 4, 0, 57,}
-	,
-	{3, 0, 4, 0, 55,}
-	,
-	{3, 0, 4, 0, 54,}
-	,
-	{3, 0, 4, 0, 52,}
-	,
-	{3, 0, 4, 0, 51,}
-	,
-	{3, 0, 4, 0, 49,}
-	,
-	{3, 0, 4, 0, 48,}
-	,
-	{3, 0, 4, 0, 46,}
-	,
-	{3, 0, 3, 0, 60,}
-	,
-	{3, 0, 3, 0, 58,}
-	,
-	{3, 0, 3, 0, 57,}
-	,
-	{3, 0, 3, 0, 55,}
-	,
-	{3, 0, 3, 0, 54,}
-	,
-	{3, 0, 3, 0, 52,}
-	,
-	{3, 0, 3, 0, 51,}
-	,
-	{3, 0, 3, 0, 49,}
-	,
-	{3, 0, 3, 0, 48,}
-	,
-	{3, 0, 3, 0, 46,}
-	,
-	{3, 0, 3, 0, 45,}
-	,
-	{3, 0, 3, 0, 44,}
-	,
-	{3, 0, 3, 0, 43,}
-	,
-	{3, 0, 3, 0, 41,}
-	,
-	{3, 0, 2, 0, 61,}
-	,
-	{3, 0, 2, 0, 59,}
-	,
-	{3, 0, 2, 0, 57,}
-	,
-	{3, 0, 2, 0, 56,}
-	,
-	{3, 0, 2, 0, 54,}
-	,
-	{3, 0, 2, 0, 53,}
-	,
-	{3, 0, 2, 0, 51,}
-	,
-	{3, 0, 2, 0, 50,}
-	,
-	{3, 0, 2, 0, 48,}
-	,
-	{3, 0, 2, 0, 47,}
-	,
-	{3, 0, 2, 0, 46,}
-	,
-	{3, 0, 2, 0, 44,}
-	,
-	{3, 0, 2, 0, 43,}
-	,
-	{3, 0, 2, 0, 42,}
-	,
-	{3, 0, 2, 0, 41,}
-	,
-	{3, 0, 2, 0, 39,}
-	,
-	{3, 0, 2, 0, 38,}
-	,
-	{3, 0, 2, 0, 37,}
-	,
-	{3, 0, 2, 0, 36,}
-	,
-	{3, 0, 2, 0, 35,}
-	,
-	{3, 0, 2, 0, 34,}
-	,
-	{3, 0, 2, 0, 33,}
-	,
-	{3, 0, 2, 0, 32,}
-	,
-	{3, 0, 1, 0, 63,}
-	,
-	{3, 0, 1, 0, 61,}
-	,
-	{3, 0, 1, 0, 59,}
-	,
-	{3, 0, 1, 0, 57,}
-	,
-};
-
-const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[128] = {
-	{7, 0, 31, 0, 72,}
-	,
-	{7, 0, 31, 0, 70,}
-	,
-	{7, 0, 31, 0, 68,}
-	,
-	{7, 0, 30, 0, 67,}
-	,
-	{7, 0, 29, 0, 68,}
-	,
-	{7, 0, 28, 0, 68,}
-	,
-	{7, 0, 27, 0, 69,}
-	,
-	{7, 0, 26, 0, 70,}
-	,
-	{7, 0, 25, 0, 70,}
-	,
-	{7, 0, 24, 0, 71,}
-	,
-	{7, 0, 23, 0, 72,}
-	,
-	{7, 0, 23, 0, 70,}
-	,
-	{7, 0, 22, 0, 71,}
-	,
-	{7, 0, 21, 0, 72,}
-	,
-	{7, 0, 21, 0, 70,}
-	,
-	{7, 0, 21, 0, 68,}
-	,
-	{7, 0, 21, 0, 66,}
-	,
-	{7, 0, 21, 0, 64,}
-	,
-	{7, 0, 21, 0, 63,}
-	,
-	{7, 0, 20, 0, 64,}
-	,
-	{7, 0, 19, 0, 65,}
-	,
-	{7, 0, 19, 0, 64,}
-	,
-	{7, 0, 18, 0, 65,}
-	,
-	{7, 0, 18, 0, 64,}
-	,
-	{7, 0, 17, 0, 65,}
-	,
-	{7, 0, 17, 0, 64,}
-	,
-	{7, 0, 16, 0, 65,}
-	,
-	{7, 0, 16, 0, 64,}
-	,
-	{7, 0, 16, 0, 62,}
-	,
-	{7, 0, 16, 0, 60,}
-	,
-	{7, 0, 16, 0, 58,}
-	,
-	{7, 0, 15, 0, 61,}
-	,
-	{7, 0, 15, 0, 59,}
-	,
-	{7, 0, 14, 0, 61,}
-	,
-	{7, 0, 14, 0, 60,}
-	,
-	{7, 0, 14, 0, 58,}
-	,
-	{7, 0, 13, 0, 60,}
-	,
-	{7, 0, 13, 0, 59,}
-	,
-	{7, 0, 12, 0, 62,}
-	,
-	{7, 0, 12, 0, 60,}
-	,
-	{7, 0, 12, 0, 58,}
-	,
-	{7, 0, 11, 0, 62,}
-	,
-	{7, 0, 11, 0, 60,}
-	,
-	{7, 0, 11, 0, 59,}
-	,
-	{7, 0, 11, 0, 57,}
-	,
-	{7, 0, 10, 0, 61,}
-	,
-	{7, 0, 10, 0, 59,}
-	,
-	{7, 0, 10, 0, 57,}
-	,
-	{7, 0, 9, 0, 62,}
-	,
-	{7, 0, 9, 0, 60,}
-	,
-	{7, 0, 9, 0, 58,}
-	,
-	{7, 0, 9, 0, 57,}
-	,
-	{7, 0, 8, 0, 62,}
-	,
-	{7, 0, 8, 0, 60,}
-	,
-	{7, 0, 8, 0, 58,}
-	,
-	{7, 0, 8, 0, 57,}
-	,
-	{7, 0, 8, 0, 55,}
-	,
-	{7, 0, 7, 0, 61,}
-	,
-	{7, 0, 7, 0, 60,}
-	,
-	{7, 0, 7, 0, 58,}
-	,
-	{7, 0, 7, 0, 56,}
-	,
-	{7, 0, 7, 0, 55,}
-	,
-	{7, 0, 6, 0, 62,}
-	,
-	{7, 0, 6, 0, 60,}
-	,
-	{7, 0, 6, 0, 58,}
-	,
-	{7, 0, 6, 0, 57,}
-	,
-	{7, 0, 6, 0, 55,}
-	,
-	{7, 0, 6, 0, 54,}
-	,
-	{7, 0, 6, 0, 52,}
-	,
-	{7, 0, 5, 0, 61,}
-	,
-	{7, 0, 5, 0, 59,}
-	,
-	{7, 0, 5, 0, 57,}
-	,
-	{7, 0, 5, 0, 56,}
-	,
-	{7, 0, 5, 0, 54,}
-	,
-	{7, 0, 5, 0, 53,}
-	,
-	{7, 0, 5, 0, 51,}
-	,
-	{7, 0, 4, 0, 62,}
-	,
-	{7, 0, 4, 0, 60,}
-	,
-	{7, 0, 4, 0, 58,}
-	,
-	{7, 0, 4, 0, 57,}
-	,
-	{7, 0, 4, 0, 55,}
-	,
-	{7, 0, 4, 0, 54,}
-	,
-	{7, 0, 4, 0, 52,}
-	,
-	{7, 0, 4, 0, 51,}
-	,
-	{7, 0, 4, 0, 49,}
-	,
-	{7, 0, 4, 0, 48,}
-	,
-	{7, 0, 4, 0, 46,}
-	,
-	{7, 0, 3, 0, 60,}
-	,
-	{7, 0, 3, 0, 58,}
-	,
-	{7, 0, 3, 0, 57,}
-	,
-	{7, 0, 3, 0, 55,}
-	,
-	{7, 0, 3, 0, 54,}
-	,
-	{7, 0, 3, 0, 52,}
-	,
-	{7, 0, 3, 0, 51,}
-	,
-	{7, 0, 3, 0, 49,}
-	,
-	{7, 0, 3, 0, 48,}
-	,
-	{7, 0, 3, 0, 46,}
-	,
-	{7, 0, 3, 0, 45,}
-	,
-	{7, 0, 3, 0, 44,}
-	,
-	{7, 0, 3, 0, 43,}
-	,
-	{7, 0, 3, 0, 41,}
-	,
-	{7, 0, 2, 0, 61,}
-	,
-	{7, 0, 2, 0, 59,}
-	,
-	{7, 0, 2, 0, 57,}
-	,
-	{7, 0, 2, 0, 56,}
-	,
-	{7, 0, 2, 0, 54,}
-	,
-	{7, 0, 2, 0, 53,}
-	,
-	{7, 0, 2, 0, 51,}
-	,
-	{7, 0, 2, 0, 50,}
-	,
-	{7, 0, 2, 0, 48,}
-	,
-	{7, 0, 2, 0, 47,}
-	,
-	{7, 0, 2, 0, 46,}
-	,
-	{7, 0, 2, 0, 44,}
-	,
-	{7, 0, 2, 0, 43,}
-	,
-	{7, 0, 2, 0, 42,}
-	,
-	{7, 0, 2, 0, 41,}
-	,
-	{7, 0, 2, 0, 39,}
-	,
-	{7, 0, 2, 0, 38,}
-	,
-	{7, 0, 2, 0, 37,}
-	,
-	{7, 0, 2, 0, 36,}
-	,
-	{7, 0, 2, 0, 35,}
-	,
-	{7, 0, 2, 0, 34,}
-	,
-	{7, 0, 2, 0, 33,}
-	,
-	{7, 0, 2, 0, 32,}
-	,
-	{7, 0, 1, 0, 63,}
-	,
-	{7, 0, 1, 0, 61,}
-	,
-	{7, 0, 1, 0, 59,}
-	,
-	{7, 0, 1, 0, 57,}
-	,
-};
-
-const lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[128] = {
-	{255, 255, 0xf0, 0, 152,}
-	,
-	{255, 255, 0xf0, 0, 147,}
-	,
-	{255, 255, 0xf0, 0, 143,}
-	,
-	{255, 255, 0xf0, 0, 139,}
-	,
-	{255, 255, 0xf0, 0, 135,}
-	,
-	{255, 255, 0xf0, 0, 131,}
-	,
-	{255, 255, 0xf0, 0, 128,}
-	,
-	{255, 255, 0xf0, 0, 124,}
-	,
-	{255, 255, 0xf0, 0, 121,}
-	,
-	{255, 255, 0xf0, 0, 117,}
-	,
-	{255, 255, 0xf0, 0, 114,}
-	,
-	{255, 255, 0xf0, 0, 111,}
-	,
-	{255, 255, 0xf0, 0, 107,}
-	,
-	{255, 255, 0xf0, 0, 104,}
-	,
-	{255, 255, 0xf0, 0, 101,}
-	,
-	{255, 255, 0xf0, 0, 99,}
-	,
-	{255, 255, 0xf0, 0, 96,}
-	,
-	{255, 255, 0xf0, 0, 93,}
-	,
-	{255, 255, 0xf0, 0, 90,}
-	,
-	{255, 255, 0xf0, 0, 88,}
-	,
-	{255, 255, 0xf0, 0, 85,}
-	,
-	{255, 255, 0xf0, 0, 83,}
-	,
-	{255, 255, 0xf0, 0, 81,}
-	,
-	{255, 255, 0xf0, 0, 78,}
-	,
-	{255, 255, 0xf0, 0, 76,}
-	,
-	{255, 255, 0xf0, 0, 74,}
-	,
-	{255, 255, 0xf0, 0, 72,}
-	,
-	{255, 255, 0xf0, 0, 70,}
-	,
-	{255, 255, 0xf0, 0, 68,}
-	,
-	{255, 255, 0xf0, 0, 66,}
-	,
-	{255, 255, 0xf0, 0, 64,}
-	,
-	{255, 248, 0xf0, 0, 64,}
-	,
-	{255, 241, 0xf0, 0, 64,}
-	,
-	{255, 251, 0xe0, 0, 64,}
-	,
-	{255, 244, 0xe0, 0, 64,}
-	,
-	{255, 254, 0xd0, 0, 64,}
-	,
-	{255, 246, 0xd0, 0, 64,}
-	,
-	{255, 239, 0xd0, 0, 64,}
-	,
-	{255, 249, 0xc0, 0, 64,}
-	,
-	{255, 242, 0xc0, 0, 64,}
-	,
-	{255, 255, 0xb0, 0, 64,}
-	,
-	{255, 248, 0xb0, 0, 64,}
-	,
-	{255, 241, 0xb0, 0, 64,}
-	,
-	{255, 254, 0xa0, 0, 64,}
-	,
-	{255, 246, 0xa0, 0, 64,}
-	,
-	{255, 239, 0xa0, 0, 64,}
-	,
-	{255, 255, 0x90, 0, 64,}
-	,
-	{255, 248, 0x90, 0, 64,}
-	,
-	{255, 241, 0x90, 0, 64,}
-	,
-	{255, 234, 0x90, 0, 64,}
-	,
-	{255, 255, 0x80, 0, 64,}
-	,
-	{255, 248, 0x80, 0, 64,}
-	,
-	{255, 241, 0x80, 0, 64,}
-	,
-	{255, 234, 0x80, 0, 64,}
-	,
-	{255, 255, 0x70, 0, 64,}
-	,
-	{255, 248, 0x70, 0, 64,}
-	,
-	{255, 241, 0x70, 0, 64,}
-	,
-	{255, 234, 0x70, 0, 64,}
-	,
-	{255, 227, 0x70, 0, 64,}
-	,
-	{255, 221, 0x70, 0, 64,}
-	,
-	{255, 215, 0x70, 0, 64,}
-	,
-	{255, 208, 0x70, 0, 64,}
-	,
-	{255, 203, 0x70, 0, 64,}
-	,
-	{255, 197, 0x70, 0, 64,}
-	,
-	{255, 255, 0x60, 0, 64,}
-	,
-	{255, 248, 0x60, 0, 64,}
-	,
-	{255, 241, 0x60, 0, 64,}
-	,
-	{255, 234, 0x60, 0, 64,}
-	,
-	{255, 227, 0x60, 0, 64,}
-	,
-	{255, 221, 0x60, 0, 64,}
-	,
-	{255, 255, 0x50, 0, 64,}
-	,
-	{255, 248, 0x50, 0, 64,}
-	,
-	{255, 241, 0x50, 0, 64,}
-	,
-	{255, 234, 0x50, 0, 64,}
-	,
-	{255, 227, 0x50, 0, 64,}
-	,
-	{255, 221, 0x50, 0, 64,}
-	,
-	{255, 215, 0x50, 0, 64,}
-	,
-	{255, 208, 0x50, 0, 64,}
-	,
-	{255, 255, 0x40, 0, 64,}
-	,
-	{255, 248, 0x40, 0, 64,}
-	,
-	{255, 241, 0x40, 0, 64,}
-	,
-	{255, 234, 0x40, 0, 64,}
-	,
-	{255, 227, 0x40, 0, 64,}
-	,
-	{255, 221, 0x40, 0, 64,}
-	,
-	{255, 215, 0x40, 0, 64,}
-	,
-	{255, 208, 0x40, 0, 64,}
-	,
-	{255, 203, 0x40, 0, 64,}
-	,
-	{255, 197, 0x40, 0, 64,}
-	,
-	{255, 255, 0x30, 0, 64,}
-	,
-	{255, 248, 0x30, 0, 64,}
-	,
-	{255, 241, 0x30, 0, 64,}
-	,
-	{255, 234, 0x30, 0, 64,}
-	,
-	{255, 227, 0x30, 0, 64,}
-	,
-	{255, 221, 0x30, 0, 64,}
-	,
-	{255, 215, 0x30, 0, 64,}
-	,
-	{255, 208, 0x30, 0, 64,}
-	,
-	{255, 203, 0x30, 0, 64,}
-	,
-	{255, 197, 0x30, 0, 64,}
-	,
-	{255, 191, 0x30, 0, 64,}
-	,
-	{255, 186, 0x30, 0, 64,}
-	,
-	{255, 181, 0x30, 0, 64,}
-	,
-	{255, 175, 0x30, 0, 64,}
-	,
-	{255, 255, 0x20, 0, 64,}
-	,
-	{255, 248, 0x20, 0, 64,}
-	,
-	{255, 241, 0x20, 0, 64,}
-	,
-	{255, 234, 0x20, 0, 64,}
-	,
-	{255, 227, 0x20, 0, 64,}
-	,
-	{255, 221, 0x20, 0, 64,}
-	,
-	{255, 215, 0x20, 0, 64,}
-	,
-	{255, 208, 0x20, 0, 64,}
-	,
-	{255, 203, 0x20, 0, 64,}
-	,
-	{255, 197, 0x20, 0, 64,}
-	,
-	{255, 191, 0x20, 0, 64,}
-	,
-	{255, 186, 0x20, 0, 64,}
-	,
-	{255, 181, 0x20, 0, 64,}
-	,
-	{255, 175, 0x20, 0, 64,}
-	,
-	{255, 170, 0x20, 0, 64,}
-	,
-	{255, 166, 0x20, 0, 64,}
-	,
-	{255, 161, 0x20, 0, 64,}
-	,
-	{255, 156, 0x20, 0, 64,}
-	,
-	{255, 152, 0x20, 0, 64,}
-	,
-	{255, 148, 0x20, 0, 64,}
-	,
-	{255, 143, 0x20, 0, 64,}
-	,
-	{255, 139, 0x20, 0, 64,}
-	,
-	{255, 135, 0x20, 0, 64,}
-	,
-	{255, 132, 0x20, 0, 64,}
-	,
-	{255, 255, 0x10, 0, 64,}
-	,
-	{255, 248, 0x10, 0, 64,}
-	,
-};
diff --git a/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.h b/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.h
deleted file mode 100644
index 5a64a98..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phytbl_lcn.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-typedef phytbl_info_t dot11lcnphytbl_info_t;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev0[];
-extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev0;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa;
-extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_epa_combo;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_info_rev0[];
-extern const u32 dot11lcnphytbl_info_sz_rev0;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_2G_rev2[];
-extern const u32 dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_5G_rev2[];
-extern const u32 dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_2G_rev2[];
-
-extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_extlna_5G_rev2[];
-
-typedef struct {
-	unsigned char gm;
-	unsigned char pga;
-	unsigned char pad;
-	unsigned char dac;
-	unsigned char bb_mult;
-} lcnphy_tx_gain_tbl_entry;
-
-extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_gaintable_rev0[];
-extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_2GHz_extPA_gaintable_rev0[];
-
-extern const lcnphy_tx_gain_tbl_entry dot11lcnphy_5GHz_gaintable_rev0[];
diff --git a/drivers/staging/brcm80211/phy/wlc_phytbl_n.c b/drivers/staging/brcm80211/phy/wlc_phytbl_n.c
deleted file mode 100644
index a9fc193..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phytbl_n.c
+++ /dev/null
@@ -1,10634 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <osl.h>
-#include <wlc_phy_int.h>
-#include <wlc_phytbl_n.h>
-
-const u32 frame_struct_rev0[] = {
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x09804506,
-	0x00100030,
-	0x09804507,
-	0x00100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100004,
-	0x01000a0d,
-	0x00100024,
-	0x0980450e,
-	0x00100034,
-	0x0980450f,
-	0x00100034,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x01800504,
-	0x00100030,
-	0x11808505,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x11808504,
-	0x00100030,
-	0x3981ca05,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x10008a04,
-	0x00100000,
-	0x3981ca05,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100008,
-	0x01000a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x1180850c,
-	0x00100038,
-	0x3981ca0d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x10008a0c,
-	0x00100008,
-	0x3981ca0d,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x02001405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x0200140d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x0b004a06,
-	0x01900060,
-	0x5b02ca04,
-	0x00100060,
-	0x3b01d405,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x5802d404,
-	0x00100000,
-	0x3b01d405,
-	0x00100060,
-	0x0b004a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x5002940c,
-	0x00100010,
-	0x3201940d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x0b004a0e,
-	0x01900070,
-	0x5b02ca0c,
-	0x00100070,
-	0x3b01d40d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x5802d40c,
-	0x00100010,
-	0x3b01d40d,
-	0x00100070,
-	0x0b004a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x000f4800,
-	0x62031405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x53028a07,
-	0x01900060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x000f4808,
-	0x6203140d,
-	0x00100048,
-	0x53028a0e,
-	0x01900068,
-	0x53028a0f,
-	0x01900068,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100004,
-	0x11008a0d,
-	0x00100024,
-	0x1980c50e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x0180c506,
-	0x00100030,
-	0x0180c506,
-	0x00100030,
-	0x2180c50c,
-	0x00100030,
-	0x49820a0d,
-	0x0016a130,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x2000ca0c,
-	0x00100000,
-	0x49820a0d,
-	0x0016a130,
-	0x1980c50e,
-	0x00100030,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100008,
-	0x0200140d,
-	0x00100048,
-	0x0b004a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x03004a06,
-	0x01900060,
-	0x03004a06,
-	0x01900060,
-	0x6b030a0c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x6b03140c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x0b004a0e,
-	0x01900060,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x53028a0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u8 frame_lut_rev0[] = {
-	0x02,
-	0x04,
-	0x14,
-	0x14,
-	0x03,
-	0x05,
-	0x16,
-	0x16,
-	0x0a,
-	0x0c,
-	0x1c,
-	0x1c,
-	0x0b,
-	0x0d,
-	0x1e,
-	0x1e,
-	0x06,
-	0x08,
-	0x18,
-	0x18,
-	0x07,
-	0x09,
-	0x1a,
-	0x1a,
-	0x0e,
-	0x10,
-	0x20,
-	0x28,
-	0x0f,
-	0x11,
-	0x22,
-	0x2a,
-};
-
-const u32 tmap_tbl_rev0[] = {
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00011111,
-	0x11110000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00088aaa,
-	0xaaaa0000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xaaa8aaa0,
-	0x8aaa8aaa,
-	0xaa8a8a8a,
-	0x000aaa88,
-	0x8aaa0000,
-	0xaaa8a888,
-	0x8aa88a8a,
-	0x8a88a888,
-	0x08080a00,
-	0x0a08080a,
-	0x080a0a08,
-	0x00080808,
-	0x080a0000,
-	0x080a0808,
-	0x080a0808,
-	0x0a0a0a08,
-	0xa0a0a0a0,
-	0x80a0a080,
-	0x8080a0a0,
-	0x00008080,
-	0x80a00000,
-	0x80a080a0,
-	0xa080a0a0,
-	0x8080a0a0,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x99999000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x22000000,
-	0x2222b222,
-	0x22222222,
-	0x222222b2,
-	0xb2222220,
-	0x22222222,
-	0x22d22222,
-	0x00000222,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x33000000,
-	0x3333b333,
-	0x33333333,
-	0x333333b3,
-	0xb3333330,
-	0x33333333,
-	0x33d33333,
-	0x00000333,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x99b99b00,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb99,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x22222200,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0x22222222,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x11111111,
-	0xf1111111,
-	0x11111111,
-	0x11f11111,
-	0x01111111,
-	0xbb9bb900,
-	0xb9b9bb99,
-	0xb99bbbbb,
-	0xbbbb9b9b,
-	0xb9bb99bb,
-	0xb99999b9,
-	0xb9b9b99b,
-	0x00000bbb,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88aa,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x0a888aaa,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00000aaa,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0xbbbbbb00,
-	0x999bbbbb,
-	0x9bb99b9b,
-	0xb9b9b9bb,
-	0xb9b99bbb,
-	0xb9b9b9bb,
-	0xb9bb9b99,
-	0x00000999,
-	0x8a000000,
-	0xaa88a888,
-	0xa88888aa,
-	0xa88a8a88,
-	0xa88aa88a,
-	0x88a8aaaa,
-	0xa8aa8aaa,
-	0x0888a88a,
-	0x0b0b0b00,
-	0x090b0b0b,
-	0x0b090b0b,
-	0x0909090b,
-	0x09090b0b,
-	0x09090b0b,
-	0x09090b09,
-	0x00000909,
-	0x0a000000,
-	0x0a080808,
-	0x080a080a,
-	0x080a0a08,
-	0x080a080a,
-	0x0808080a,
-	0x0a0a0a08,
-	0x0808080a,
-	0xb0b0b000,
-	0x9090b0b0,
-	0x90b09090,
-	0xb0b0b090,
-	0xb0b090b0,
-	0x90b0b0b0,
-	0xb0b09090,
-	0x00000090,
-	0x80000000,
-	0xa080a080,
-	0xa08080a0,
-	0xa0808080,
-	0xa080a080,
-	0x80a0a0a0,
-	0xa0a080a0,
-	0x00a0a0a0,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x33000000,
-	0x3333f333,
-	0x33333333,
-	0x333333f3,
-	0xf3333330,
-	0x33333333,
-	0x33f33333,
-	0x00000333,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x99000000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88888000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x88a88a00,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdtrn_tbl_rev0[] = {
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0xfa58fa58,
-	0xf895043b,
-	0xff4c09c0,
-	0xfbc6ffa8,
-	0xfb84f384,
-	0x0798f6f9,
-	0x05760122,
-	0x058409f6,
-	0x0b500000,
-	0x05b7f542,
-	0x08860432,
-	0x06ddfee7,
-	0xfb84f384,
-	0xf9d90664,
-	0xf7e8025c,
-	0x00fff7bd,
-	0x05a805a8,
-	0xf7bd00ff,
-	0x025cf7e8,
-	0x0664f9d9,
-	0xf384fb84,
-	0xfee706dd,
-	0x04320886,
-	0xf54205b7,
-	0x00000b50,
-	0x09f60584,
-	0x01220576,
-	0xf6f90798,
-	0xf384fb84,
-	0xffa8fbc6,
-	0x09c0ff4c,
-	0x043bf895,
-	0x02d402d4,
-	0x07de0270,
-	0xfc96079c,
-	0xf90afe94,
-	0xfe00ff2c,
-	0x02d4065d,
-	0x092a0096,
-	0x0014fbb8,
-	0xfd2cfd2c,
-	0x076afb3c,
-	0x0096f752,
-	0xf991fd87,
-	0xfb2c0200,
-	0xfeb8f960,
-	0x08e0fc96,
-	0x049802a8,
-	0xfd2cfd2c,
-	0x02a80498,
-	0xfc9608e0,
-	0xf960feb8,
-	0x0200fb2c,
-	0xfd87f991,
-	0xf7520096,
-	0xfb3c076a,
-	0xfd2cfd2c,
-	0xfbb80014,
-	0x0096092a,
-	0x065d02d4,
-	0xff2cfe00,
-	0xfe94f90a,
-	0x079cfc96,
-	0x027007de,
-	0x02d402d4,
-	0x027007de,
-	0x079cfc96,
-	0xfe94f90a,
-	0xff2cfe00,
-	0x065d02d4,
-	0x0096092a,
-	0xfbb80014,
-	0xfd2cfd2c,
-	0xfb3c076a,
-	0xf7520096,
-	0xfd87f991,
-	0x0200fb2c,
-	0xf960feb8,
-	0xfc9608e0,
-	0x02a80498,
-	0xfd2cfd2c,
-	0x049802a8,
-	0x08e0fc96,
-	0xfeb8f960,
-	0xfb2c0200,
-	0xf991fd87,
-	0x0096f752,
-	0x076afb3c,
-	0xfd2cfd2c,
-	0x0014fbb8,
-	0x092a0096,
-	0x02d4065d,
-	0xfe00ff2c,
-	0xf90afe94,
-	0xfc96079c,
-	0x07de0270,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x061c061c,
-	0xff30009d,
-	0xffb21141,
-	0xfd87fb54,
-	0xf65dfe59,
-	0x02eef99e,
-	0x0166f03c,
-	0xfff809b6,
-	0x000008a4,
-	0x000af42b,
-	0x00eff577,
-	0xfa840bf2,
-	0xfc02ff51,
-	0x08260f67,
-	0xfff0036f,
-	0x0842f9c3,
-	0x00000000,
-	0x063df7be,
-	0xfc910010,
-	0xf099f7da,
-	0x00af03fe,
-	0xf40e057c,
-	0x0a89ff11,
-	0x0bd5fff6,
-	0xf75c0000,
-	0xf64a0008,
-	0x0fc4fe9a,
-	0x0662fd12,
-	0x01a709a3,
-	0x04ac0279,
-	0xeebf004e,
-	0xff6300d0,
-	0xf9e4f9e4,
-	0x00d0ff63,
-	0x004eeebf,
-	0x027904ac,
-	0x09a301a7,
-	0xfd120662,
-	0xfe9a0fc4,
-	0x0008f64a,
-	0x0000f75c,
-	0xfff60bd5,
-	0xff110a89,
-	0x057cf40e,
-	0x03fe00af,
-	0xf7daf099,
-	0x0010fc91,
-	0xf7be063d,
-	0x00000000,
-	0xf9c30842,
-	0x036ffff0,
-	0x0f670826,
-	0xff51fc02,
-	0x0bf2fa84,
-	0xf57700ef,
-	0xf42b000a,
-	0x08a40000,
-	0x09b6fff8,
-	0xf03c0166,
-	0xf99e02ee,
-	0xfe59f65d,
-	0xfb54fd87,
-	0x1141ffb2,
-	0x009dff30,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0xfa58fa58,
-	0xf8f0fe00,
-	0x0448073d,
-	0xfdc9fe46,
-	0xf9910258,
-	0x089d0407,
-	0xfd5cf71a,
-	0x02affde0,
-	0x083e0496,
-	0xff5a0740,
-	0xff7afd97,
-	0x00fe01f1,
-	0x0009082e,
-	0xfa94ff75,
-	0xfecdf8ea,
-	0xffb0f693,
-	0xfd2cfa58,
-	0x0433ff16,
-	0xfba405dd,
-	0xfa610341,
-	0x06a606cb,
-	0x0039fd2d,
-	0x0677fa97,
-	0x01fa05e0,
-	0xf896003e,
-	0x075a068b,
-	0x012cfc3e,
-	0xfa23f98d,
-	0xfc7cfd43,
-	0xff90fc0d,
-	0x01c10982,
-	0x00c601d6,
-	0xfd2cfd2c,
-	0x01d600c6,
-	0x098201c1,
-	0xfc0dff90,
-	0xfd43fc7c,
-	0xf98dfa23,
-	0xfc3e012c,
-	0x068b075a,
-	0x003ef896,
-	0x05e001fa,
-	0xfa970677,
-	0xfd2d0039,
-	0x06cb06a6,
-	0x0341fa61,
-	0x05ddfba4,
-	0xff160433,
-	0xfa58fd2c,
-	0xf693ffb0,
-	0xf8eafecd,
-	0xff75fa94,
-	0x082e0009,
-	0x01f100fe,
-	0xfd97ff7a,
-	0x0740ff5a,
-	0x0496083e,
-	0xfde002af,
-	0xf71afd5c,
-	0x0407089d,
-	0x0258f991,
-	0xfe46fdc9,
-	0x073d0448,
-	0xfe00f8f0,
-	0xfd2cfd2c,
-	0xfce00500,
-	0xfc09fddc,
-	0xfe680157,
-	0x04c70571,
-	0xfc3aff21,
-	0xfcd70228,
-	0x056d0277,
-	0x0200fe00,
-	0x0022f927,
-	0xfe3c032b,
-	0xfc44ff3c,
-	0x03e9fbdb,
-	0x04570313,
-	0x04c9ff5c,
-	0x000d03b8,
-	0xfa580000,
-	0xfbe900d2,
-	0xf9d0fe0b,
-	0x0125fdf9,
-	0x042501bf,
-	0x0328fa2b,
-	0xffa902f0,
-	0xfa250157,
-	0x0200fe00,
-	0x03740438,
-	0xff0405fd,
-	0x030cfe52,
-	0x0037fb39,
-	0xff6904c5,
-	0x04f8fd23,
-	0xfd31fc1b,
-	0xfd2cfd2c,
-	0xfc1bfd31,
-	0xfd2304f8,
-	0x04c5ff69,
-	0xfb390037,
-	0xfe52030c,
-	0x05fdff04,
-	0x04380374,
-	0xfe000200,
-	0x0157fa25,
-	0x02f0ffa9,
-	0xfa2b0328,
-	0x01bf0425,
-	0xfdf90125,
-	0xfe0bf9d0,
-	0x00d2fbe9,
-	0x0000fa58,
-	0x03b8000d,
-	0xff5c04c9,
-	0x03130457,
-	0xfbdb03e9,
-	0xff3cfc44,
-	0x032bfe3c,
-	0xf9270022,
-	0xfe000200,
-	0x0277056d,
-	0x0228fcd7,
-	0xff21fc3a,
-	0x057104c7,
-	0x0157fe68,
-	0xfddcfc09,
-	0x0500fce0,
-	0xfd2cfd2c,
-	0x0500fce0,
-	0xfddcfc09,
-	0x0157fe68,
-	0x057104c7,
-	0xff21fc3a,
-	0x0228fcd7,
-	0x0277056d,
-	0xfe000200,
-	0xf9270022,
-	0x032bfe3c,
-	0xff3cfc44,
-	0xfbdb03e9,
-	0x03130457,
-	0xff5c04c9,
-	0x03b8000d,
-	0x0000fa58,
-	0x00d2fbe9,
-	0xfe0bf9d0,
-	0xfdf90125,
-	0x01bf0425,
-	0xfa2b0328,
-	0x02f0ffa9,
-	0x0157fa25,
-	0xfe000200,
-	0x04380374,
-	0x05fdff04,
-	0xfe52030c,
-	0xfb390037,
-	0x04c5ff69,
-	0xfd2304f8,
-	0xfc1bfd31,
-	0xfd2cfd2c,
-	0xfd31fc1b,
-	0x04f8fd23,
-	0xff6904c5,
-	0x0037fb39,
-	0x030cfe52,
-	0xff0405fd,
-	0x03740438,
-	0x0200fe00,
-	0xfa250157,
-	0xffa902f0,
-	0x0328fa2b,
-	0x042501bf,
-	0x0125fdf9,
-	0xf9d0fe0b,
-	0xfbe900d2,
-	0xfa580000,
-	0x000d03b8,
-	0x04c9ff5c,
-	0x04570313,
-	0x03e9fbdb,
-	0xfc44ff3c,
-	0xfe3c032b,
-	0x0022f927,
-	0x0200fe00,
-	0x056d0277,
-	0xfcd70228,
-	0xfc3aff21,
-	0x04c70571,
-	0xfe680157,
-	0xfc09fddc,
-	0xfce00500,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-};
-
-const u32 intlv_tbl_rev0[] = {
-	0x00802070,
-	0x0671188d,
-	0x0a60192c,
-	0x0a300e46,
-	0x00c1188d,
-	0x080024d2,
-	0x00000070,
-};
-
-const u16 pilot_tbl_rev0[] = {
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0xff0a,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xff0a,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xf83f,
-	0xfa1f,
-	0xfa97,
-	0xfab5,
-	0xf2bd,
-	0xf0bf,
-	0xffff,
-	0xffff,
-	0xf017,
-	0xf815,
-	0xf215,
-	0xf095,
-	0xf035,
-	0xf01d,
-	0xffff,
-	0xffff,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xf01f,
-	0xf817,
-	0xfa15,
-	0xf295,
-	0xf0b5,
-	0xf03d,
-	0xffff,
-	0xffff,
-	0xf82a,
-	0xfa0a,
-	0xfa82,
-	0xfaa0,
-	0xf2a8,
-	0xf0aa,
-	0xffff,
-	0xffff,
-	0xf002,
-	0xf800,
-	0xf200,
-	0xf080,
-	0xf020,
-	0xf008,
-	0xffff,
-	0xffff,
-	0xf00a,
-	0xf802,
-	0xfa00,
-	0xf280,
-	0xf0a0,
-	0xf028,
-	0xffff,
-	0xffff,
-};
-
-const u32 pltlut_tbl_rev0[] = {
-	0x76540123,
-	0x62407351,
-	0x76543201,
-	0x76540213,
-	0x76540123,
-	0x76430521,
-};
-
-const u32 tdi_tbl20_ant0_rev0[] = {
-	0x00091226,
-	0x000a1429,
-	0x000b56ad,
-	0x000c58b0,
-	0x000d5ab3,
-	0x000e9cb6,
-	0x000f9eba,
-	0x0000c13d,
-	0x00020301,
-	0x00030504,
-	0x00040708,
-	0x0005090b,
-	0x00064b8e,
-	0x00095291,
-	0x000a5494,
-	0x000b9718,
-	0x000c9927,
-	0x000d9b2a,
-	0x000edd2e,
-	0x000fdf31,
-	0x000101b4,
-	0x000243b7,
-	0x000345bb,
-	0x000447be,
-	0x00058982,
-	0x00068c05,
-	0x00099309,
-	0x000a950c,
-	0x000bd78f,
-	0x000cd992,
-	0x000ddb96,
-	0x000f1d99,
-	0x00005fa8,
-	0x0001422c,
-	0x0002842f,
-	0x00038632,
-	0x00048835,
-	0x0005ca38,
-	0x0006ccbc,
-	0x0009d3bf,
-	0x000b1603,
-	0x000c1806,
-	0x000d1a0a,
-	0x000e1c0d,
-	0x000f5e10,
-	0x00008093,
-	0x00018297,
-	0x0002c49a,
-	0x0003c680,
-	0x0004c880,
-	0x00060b00,
-	0x00070d00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl20_ant1_rev0[] = {
-	0x00014b26,
-	0x00028d29,
-	0x000393ad,
-	0x00049630,
-	0x0005d833,
-	0x0006da36,
-	0x00099c3a,
-	0x000a9e3d,
-	0x000bc081,
-	0x000cc284,
-	0x000dc488,
-	0x000f068b,
-	0x0000488e,
-	0x00018b91,
-	0x0002d214,
-	0x0003d418,
-	0x0004d6a7,
-	0x000618aa,
-	0x00071aae,
-	0x0009dcb1,
-	0x000b1eb4,
-	0x000c0137,
-	0x000d033b,
-	0x000e053e,
-	0x000f4702,
-	0x00008905,
-	0x00020c09,
-	0x0003128c,
-	0x0004148f,
-	0x00051712,
-	0x00065916,
-	0x00091b19,
-	0x000a1d28,
-	0x000b5f2c,
-	0x000c41af,
-	0x000d43b2,
-	0x000e85b5,
-	0x000f87b8,
-	0x0000c9bc,
-	0x00024cbf,
-	0x00035303,
-	0x00045506,
-	0x0005978a,
-	0x0006998d,
-	0x00095b90,
-	0x000a5d93,
-	0x000b9f97,
-	0x000c821a,
-	0x000d8400,
-	0x000ec600,
-	0x000fc800,
-	0x00010a00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant0_rev0[] = {
-	0x0011a346,
-	0x00136ccf,
-	0x0014f5d9,
-	0x001641e2,
-	0x0017cb6b,
-	0x00195475,
-	0x001b2383,
-	0x001cad0c,
-	0x001e7616,
-	0x0000821f,
-	0x00020ba8,
-	0x0003d4b2,
-	0x00056447,
-	0x00072dd0,
-	0x0008b6da,
-	0x000a02e3,
-	0x000b8c6c,
-	0x000d15f6,
-	0x0011e484,
-	0x0013ae0d,
-	0x00153717,
-	0x00168320,
-	0x00180ca9,
-	0x00199633,
-	0x001b6548,
-	0x001ceed1,
-	0x001eb7db,
-	0x0000c3e4,
-	0x00024d6d,
-	0x000416f7,
-	0x0005a585,
-	0x00076f0f,
-	0x0008f818,
-	0x000a4421,
-	0x000bcdab,
-	0x000d9734,
-	0x00122649,
-	0x0013efd2,
-	0x001578dc,
-	0x0016c4e5,
-	0x00184e6e,
-	0x001a17f8,
-	0x001ba686,
-	0x001d3010,
-	0x001ef999,
-	0x00010522,
-	0x00028eac,
-	0x00045835,
-	0x0005e74a,
-	0x0007b0d3,
-	0x00093a5d,
-	0x000a85e6,
-	0x000c0f6f,
-	0x000dd8f9,
-	0x00126787,
-	0x00143111,
-	0x0015ba9a,
-	0x00170623,
-	0x00188fad,
-	0x001a5936,
-	0x001be84b,
-	0x001db1d4,
-	0x001f3b5e,
-	0x000146e7,
-	0x00031070,
-	0x000499fa,
-	0x00062888,
-	0x0007f212,
-	0x00097b9b,
-	0x000ac7a4,
-	0x000c50ae,
-	0x000e1a37,
-	0x0012a94c,
-	0x001472d5,
-	0x0015fc5f,
-	0x00174868,
-	0x0018d171,
-	0x001a9afb,
-	0x001c2989,
-	0x001df313,
-	0x001f7c9c,
-	0x000188a5,
-	0x000351af,
-	0x0004db38,
-	0x0006aa4d,
-	0x000833d7,
-	0x0009bd60,
-	0x000b0969,
-	0x000c9273,
-	0x000e5bfc,
-	0x00132a8a,
-	0x0014b414,
-	0x00163d9d,
-	0x001789a6,
-	0x001912b0,
-	0x001adc39,
-	0x001c6bce,
-	0x001e34d8,
-	0x001fbe61,
-	0x0001ca6a,
-	0x00039374,
-	0x00051cfd,
-	0x0006ec0b,
-	0x00087515,
-	0x0009fe9e,
-	0x000b4aa7,
-	0x000cd3b1,
-	0x000e9d3a,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant1_rev0[] = {
-	0x001edb36,
-	0x000129ca,
-	0x0002b353,
-	0x00047cdd,
-	0x0005c8e6,
-	0x000791ef,
-	0x00091bf9,
-	0x000aaa07,
-	0x000c3391,
-	0x000dfd1a,
-	0x00120923,
-	0x0013d22d,
-	0x00155c37,
-	0x0016eacb,
-	0x00187454,
-	0x001a3dde,
-	0x001b89e7,
-	0x001d12f0,
-	0x001f1cfa,
-	0x00016b88,
-	0x00033492,
-	0x0004be1b,
-	0x00060a24,
-	0x0007d32e,
-	0x00095d38,
-	0x000aec4c,
-	0x000c7555,
-	0x000e3edf,
-	0x00124ae8,
-	0x001413f1,
-	0x0015a37b,
-	0x00172c89,
-	0x0018b593,
-	0x001a419c,
-	0x001bcb25,
-	0x001d942f,
-	0x001f63b9,
-	0x0001ad4d,
-	0x00037657,
-	0x0004c260,
-	0x00068be9,
-	0x000814f3,
-	0x0009a47c,
-	0x000b2d8a,
-	0x000cb694,
-	0x000e429d,
-	0x00128c26,
-	0x001455b0,
-	0x0015e4ba,
-	0x00176e4e,
-	0x0018f758,
-	0x001a8361,
-	0x001c0cea,
-	0x001dd674,
-	0x001fa57d,
-	0x0001ee8b,
-	0x0003b795,
-	0x0005039e,
-	0x0006cd27,
-	0x000856b1,
-	0x0009e5c6,
-	0x000b6f4f,
-	0x000cf859,
-	0x000e8462,
-	0x00130deb,
-	0x00149775,
-	0x00162603,
-	0x0017af8c,
-	0x00193896,
-	0x001ac49f,
-	0x001c4e28,
-	0x001e17b2,
-	0x0000a6c7,
-	0x00023050,
-	0x0003f9da,
-	0x00054563,
-	0x00070eec,
-	0x00089876,
-	0x000a2704,
-	0x000bb08d,
-	0x000d3a17,
-	0x001185a0,
-	0x00134f29,
-	0x0014d8b3,
-	0x001667c8,
-	0x0017f151,
-	0x00197adb,
-	0x001b0664,
-	0x001c8fed,
-	0x001e5977,
-	0x0000e805,
-	0x0002718f,
-	0x00043b18,
-	0x000586a1,
-	0x0007502b,
-	0x0008d9b4,
-	0x000a68c9,
-	0x000bf252,
-	0x000dbbdc,
-	0x0011c7e5,
-	0x001390ee,
-	0x00151a78,
-	0x0016a906,
-	0x00183290,
-	0x0019bc19,
-	0x001b4822,
-	0x001cd12c,
-	0x001e9ab5,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 bdi_tbl_rev0[] = {
-	0x0070,
-	0x0126,
-	0x012c,
-	0x0246,
-	0x048d,
-	0x04d2,
-};
-
-const u32 chanest_tbl_rev0[] = {
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-};
-
-const u8 mcs_tbl_rev0[] = {
-	0x00,
-	0x08,
-	0x0a,
-	0x10,
-	0x12,
-	0x19,
-	0x1a,
-	0x1c,
-	0x40,
-	0x48,
-	0x4a,
-	0x50,
-	0x52,
-	0x59,
-	0x5a,
-	0x5c,
-	0x80,
-	0x88,
-	0x8a,
-	0x90,
-	0x92,
-	0x99,
-	0x9a,
-	0x9c,
-	0xc0,
-	0xc8,
-	0xca,
-	0xd0,
-	0xd2,
-	0xd9,
-	0xda,
-	0xdc,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x01,
-	0x02,
-	0x04,
-	0x08,
-	0x09,
-	0x0a,
-	0x0c,
-	0x10,
-	0x11,
-	0x12,
-	0x14,
-	0x18,
-	0x19,
-	0x1a,
-	0x1c,
-	0x20,
-	0x21,
-	0x22,
-	0x24,
-	0x40,
-	0x41,
-	0x42,
-	0x44,
-	0x48,
-	0x49,
-	0x4a,
-	0x4c,
-	0x50,
-	0x51,
-	0x52,
-	0x54,
-	0x58,
-	0x59,
-	0x5a,
-	0x5c,
-	0x60,
-	0x61,
-	0x62,
-	0x64,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u32 noise_var_tbl0_rev0[] = {
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-};
-
-const u32 noise_var_tbl1_rev0[] = {
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-};
-
-const u8 est_pwr_lut_core0_rev0[] = {
-	0x50,
-	0x4f,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3b,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x34,
-	0x33,
-	0x32,
-	0x31,
-	0x30,
-	0x2f,
-	0x2e,
-	0x2d,
-	0x2c,
-	0x2b,
-	0x2a,
-	0x29,
-	0x28,
-	0x27,
-	0x26,
-	0x25,
-	0x24,
-	0x23,
-	0x22,
-	0x21,
-	0x20,
-	0x1f,
-	0x1e,
-	0x1d,
-	0x1c,
-	0x1b,
-	0x1a,
-	0x19,
-	0x18,
-	0x17,
-	0x16,
-	0x15,
-	0x14,
-	0x13,
-	0x12,
-	0x11,
-};
-
-const u8 est_pwr_lut_core1_rev0[] = {
-	0x50,
-	0x4f,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3b,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x34,
-	0x33,
-	0x32,
-	0x31,
-	0x30,
-	0x2f,
-	0x2e,
-	0x2d,
-	0x2c,
-	0x2b,
-	0x2a,
-	0x29,
-	0x28,
-	0x27,
-	0x26,
-	0x25,
-	0x24,
-	0x23,
-	0x22,
-	0x21,
-	0x20,
-	0x1f,
-	0x1e,
-	0x1d,
-	0x1c,
-	0x1b,
-	0x1a,
-	0x19,
-	0x18,
-	0x17,
-	0x16,
-	0x15,
-	0x14,
-	0x13,
-	0x12,
-	0x11,
-};
-
-const u8 adj_pwr_lut_core0_rev0[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u8 adj_pwr_lut_core1_rev0[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u32 gainctrl_lut_core0_rev0[] = {
-	0x03cc2b44,
-	0x03cc2b42,
-	0x03cc2b40,
-	0x03cc2b3e,
-	0x03cc2b3d,
-	0x03cc2b3b,
-	0x03c82b44,
-	0x03c82b42,
-	0x03c82b40,
-	0x03c82b3e,
-	0x03c82b3d,
-	0x03c82b3b,
-	0x03c82b39,
-	0x03c82b38,
-	0x03c82b36,
-	0x03c82b34,
-	0x03c42b44,
-	0x03c42b42,
-	0x03c42b40,
-	0x03c42b3e,
-	0x03c42b3d,
-	0x03c42b3b,
-	0x03c42b39,
-	0x03c42b38,
-	0x03c42b36,
-	0x03c42b34,
-	0x03c42b33,
-	0x03c42b32,
-	0x03c42b30,
-	0x03c42b2f,
-	0x03c42b2d,
-	0x03c02b44,
-	0x03c02b42,
-	0x03c02b40,
-	0x03c02b3e,
-	0x03c02b3d,
-	0x03c02b3b,
-	0x03c02b39,
-	0x03c02b38,
-	0x03c02b36,
-	0x03c02b34,
-	0x03b02b44,
-	0x03b02b42,
-	0x03b02b40,
-	0x03b02b3e,
-	0x03b02b3d,
-	0x03b02b3b,
-	0x03b02b39,
-	0x03b02b38,
-	0x03b02b36,
-	0x03b02b34,
-	0x03b02b33,
-	0x03b02b32,
-	0x03b02b30,
-	0x03b02b2f,
-	0x03b02b2d,
-	0x03a02b44,
-	0x03a02b42,
-	0x03a02b40,
-	0x03a02b3e,
-	0x03a02b3d,
-	0x03a02b3b,
-	0x03a02b39,
-	0x03a02b38,
-	0x03a02b36,
-	0x03a02b34,
-	0x03902b44,
-	0x03902b42,
-	0x03902b40,
-	0x03902b3e,
-	0x03902b3d,
-	0x03902b3b,
-	0x03902b39,
-	0x03902b38,
-	0x03902b36,
-	0x03902b34,
-	0x03902b33,
-	0x03902b32,
-	0x03902b30,
-	0x03802b44,
-	0x03802b42,
-	0x03802b40,
-	0x03802b3e,
-	0x03802b3d,
-	0x03802b3b,
-	0x03802b39,
-	0x03802b38,
-	0x03802b36,
-	0x03802b34,
-	0x03802b33,
-	0x03802b32,
-	0x03802b30,
-	0x03802b2f,
-	0x03802b2d,
-	0x03802b2c,
-	0x03802b2b,
-	0x03802b2a,
-	0x03802b29,
-	0x03802b27,
-	0x03802b26,
-	0x03802b25,
-	0x03802b24,
-	0x03802b23,
-	0x03802b22,
-	0x03802b21,
-	0x03802b20,
-	0x03802b1f,
-	0x03802b1e,
-	0x03802b1e,
-	0x03802b1d,
-	0x03802b1c,
-	0x03802b1b,
-	0x03802b1a,
-	0x03802b1a,
-	0x03802b19,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x00002b00,
-};
-
-const u32 gainctrl_lut_core1_rev0[] = {
-	0x03cc2b44,
-	0x03cc2b42,
-	0x03cc2b40,
-	0x03cc2b3e,
-	0x03cc2b3d,
-	0x03cc2b3b,
-	0x03c82b44,
-	0x03c82b42,
-	0x03c82b40,
-	0x03c82b3e,
-	0x03c82b3d,
-	0x03c82b3b,
-	0x03c82b39,
-	0x03c82b38,
-	0x03c82b36,
-	0x03c82b34,
-	0x03c42b44,
-	0x03c42b42,
-	0x03c42b40,
-	0x03c42b3e,
-	0x03c42b3d,
-	0x03c42b3b,
-	0x03c42b39,
-	0x03c42b38,
-	0x03c42b36,
-	0x03c42b34,
-	0x03c42b33,
-	0x03c42b32,
-	0x03c42b30,
-	0x03c42b2f,
-	0x03c42b2d,
-	0x03c02b44,
-	0x03c02b42,
-	0x03c02b40,
-	0x03c02b3e,
-	0x03c02b3d,
-	0x03c02b3b,
-	0x03c02b39,
-	0x03c02b38,
-	0x03c02b36,
-	0x03c02b34,
-	0x03b02b44,
-	0x03b02b42,
-	0x03b02b40,
-	0x03b02b3e,
-	0x03b02b3d,
-	0x03b02b3b,
-	0x03b02b39,
-	0x03b02b38,
-	0x03b02b36,
-	0x03b02b34,
-	0x03b02b33,
-	0x03b02b32,
-	0x03b02b30,
-	0x03b02b2f,
-	0x03b02b2d,
-	0x03a02b44,
-	0x03a02b42,
-	0x03a02b40,
-	0x03a02b3e,
-	0x03a02b3d,
-	0x03a02b3b,
-	0x03a02b39,
-	0x03a02b38,
-	0x03a02b36,
-	0x03a02b34,
-	0x03902b44,
-	0x03902b42,
-	0x03902b40,
-	0x03902b3e,
-	0x03902b3d,
-	0x03902b3b,
-	0x03902b39,
-	0x03902b38,
-	0x03902b36,
-	0x03902b34,
-	0x03902b33,
-	0x03902b32,
-	0x03902b30,
-	0x03802b44,
-	0x03802b42,
-	0x03802b40,
-	0x03802b3e,
-	0x03802b3d,
-	0x03802b3b,
-	0x03802b39,
-	0x03802b38,
-	0x03802b36,
-	0x03802b34,
-	0x03802b33,
-	0x03802b32,
-	0x03802b30,
-	0x03802b2f,
-	0x03802b2d,
-	0x03802b2c,
-	0x03802b2b,
-	0x03802b2a,
-	0x03802b29,
-	0x03802b27,
-	0x03802b26,
-	0x03802b25,
-	0x03802b24,
-	0x03802b23,
-	0x03802b22,
-	0x03802b21,
-	0x03802b20,
-	0x03802b1f,
-	0x03802b1e,
-	0x03802b1e,
-	0x03802b1d,
-	0x03802b1c,
-	0x03802b1b,
-	0x03802b1a,
-	0x03802b1a,
-	0x03802b19,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x03802b18,
-	0x00002b00,
-};
-
-const u32 iq_lut_core0_rev0[] = {
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-};
-
-const u32 iq_lut_core1_rev0[] = {
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-	0x0000007f,
-};
-
-const u16 loft_lut_core0_rev0[] = {
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-};
-
-const u16 loft_lut_core1_rev0[] = {
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-	0x0000,
-	0x0101,
-	0x0002,
-	0x0103,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev0_volatile[] = {
-	{&bdi_tbl_rev0, sizeof(bdi_tbl_rev0) / sizeof(bdi_tbl_rev0[0]), 21, 0,
-	 16}
-	,
-	{&pltlut_tbl_rev0, sizeof(pltlut_tbl_rev0) / sizeof(pltlut_tbl_rev0[0]),
-	 20, 0, 32}
-	,
-	{&gainctrl_lut_core0_rev0,
-	 sizeof(gainctrl_lut_core0_rev0) / sizeof(gainctrl_lut_core0_rev0[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev0,
-	 sizeof(gainctrl_lut_core1_rev0) / sizeof(gainctrl_lut_core1_rev0[0]),
-	 27, 192, 32}
-	,
-
-	{&est_pwr_lut_core0_rev0,
-	 sizeof(est_pwr_lut_core0_rev0) / sizeof(est_pwr_lut_core0_rev0[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev0,
-	 sizeof(est_pwr_lut_core1_rev0) / sizeof(est_pwr_lut_core1_rev0[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev0,
-	 sizeof(adj_pwr_lut_core0_rev0) / sizeof(adj_pwr_lut_core0_rev0[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev0,
-	 sizeof(adj_pwr_lut_core1_rev0) / sizeof(adj_pwr_lut_core1_rev0[0]), 27,
-	 64, 8}
-	,
-	{&iq_lut_core0_rev0,
-	 sizeof(iq_lut_core0_rev0) / sizeof(iq_lut_core0_rev0[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev0,
-	 sizeof(iq_lut_core1_rev0) / sizeof(iq_lut_core1_rev0[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev0,
-	 sizeof(loft_lut_core0_rev0) / sizeof(loft_lut_core0_rev0[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev0,
-	 sizeof(loft_lut_core1_rev0) / sizeof(loft_lut_core1_rev0[0]), 27, 448,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev0[] = {
-	{&frame_struct_rev0,
-	 sizeof(frame_struct_rev0) / sizeof(frame_struct_rev0[0]), 10, 0, 32}
-	,
-	{&frame_lut_rev0, sizeof(frame_lut_rev0) / sizeof(frame_lut_rev0[0]),
-	 24, 0, 8}
-	,
-	{&tmap_tbl_rev0, sizeof(tmap_tbl_rev0) / sizeof(tmap_tbl_rev0[0]), 12,
-	 0, 32}
-	,
-	{&tdtrn_tbl_rev0, sizeof(tdtrn_tbl_rev0) / sizeof(tdtrn_tbl_rev0[0]),
-	 14, 0, 32}
-	,
-	{&intlv_tbl_rev0, sizeof(intlv_tbl_rev0) / sizeof(intlv_tbl_rev0[0]),
-	 13, 0, 32}
-	,
-	{&pilot_tbl_rev0, sizeof(pilot_tbl_rev0) / sizeof(pilot_tbl_rev0[0]),
-	 11, 0, 16}
-	,
-	{&tdi_tbl20_ant0_rev0,
-	 sizeof(tdi_tbl20_ant0_rev0) / sizeof(tdi_tbl20_ant0_rev0[0]), 19, 128,
-	 32}
-	,
-	{&tdi_tbl20_ant1_rev0,
-	 sizeof(tdi_tbl20_ant1_rev0) / sizeof(tdi_tbl20_ant1_rev0[0]), 19, 256,
-	 32}
-	,
-	{&tdi_tbl40_ant0_rev0,
-	 sizeof(tdi_tbl40_ant0_rev0) / sizeof(tdi_tbl40_ant0_rev0[0]), 19, 640,
-	 32}
-	,
-	{&tdi_tbl40_ant1_rev0,
-	 sizeof(tdi_tbl40_ant1_rev0) / sizeof(tdi_tbl40_ant1_rev0[0]), 19, 768,
-	 32}
-	,
-	{&chanest_tbl_rev0,
-	 sizeof(chanest_tbl_rev0) / sizeof(chanest_tbl_rev0[0]), 22, 0, 32}
-	,
-	{&mcs_tbl_rev0, sizeof(mcs_tbl_rev0) / sizeof(mcs_tbl_rev0[0]), 18, 0, 8}
-	,
-	{&noise_var_tbl0_rev0,
-	 sizeof(noise_var_tbl0_rev0) / sizeof(noise_var_tbl0_rev0[0]), 16, 0,
-	 32}
-	,
-	{&noise_var_tbl1_rev0,
-	 sizeof(noise_var_tbl1_rev0) / sizeof(noise_var_tbl1_rev0[0]), 16, 128,
-	 32}
-	,
-};
-
-const u32 mimophytbl_info_sz_rev0 =
-    sizeof(mimophytbl_info_rev0) / sizeof(mimophytbl_info_rev0[0]);
-const u32 mimophytbl_info_sz_rev0_volatile =
-    sizeof(mimophytbl_info_rev0_volatile) /
-    sizeof(mimophytbl_info_rev0_volatile[0]);
-
-const u16 ant_swctrl_tbl_rev3[] = {
-	0x0082,
-	0x0082,
-	0x0211,
-	0x0222,
-	0x0328,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0144,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0188,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0082,
-	0x0082,
-	0x0211,
-	0x0222,
-	0x0328,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0144,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0188,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 ant_swctrl_tbl_rev3_1[] = {
-	0x0022,
-	0x0022,
-	0x0011,
-	0x0022,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0011,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0022,
-	0x0022,
-	0x0011,
-	0x0022,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0011,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0022,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 ant_swctrl_tbl_rev3_2[] = {
-	0x0088,
-	0x0088,
-	0x0044,
-	0x0088,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0044,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0088,
-	0x0088,
-	0x0044,
-	0x0088,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0044,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0088,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 ant_swctrl_tbl_rev3_3[] = {
-	0x022,
-	0x022,
-	0x011,
-	0x022,
-	0x000,
-	0x000,
-	0x000,
-	0x000,
-	0x011,
-	0x000,
-	0x000,
-	0x000,
-	0x022,
-	0x000,
-	0x000,
-	0x3cc,
-	0x022,
-	0x022,
-	0x011,
-	0x022,
-	0x000,
-	0x000,
-	0x000,
-	0x000,
-	0x011,
-	0x000,
-	0x000,
-	0x000,
-	0x022,
-	0x000,
-	0x000,
-	0x3cc
-};
-
-const u32 frame_struct_rev3[] = {
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x09804506,
-	0x00100030,
-	0x09804507,
-	0x00100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100004,
-	0x01000a0d,
-	0x00100024,
-	0x0980450e,
-	0x00100034,
-	0x0980450f,
-	0x00100034,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x01800504,
-	0x00100030,
-	0x11808505,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000a04,
-	0x00100000,
-	0x11008a05,
-	0x00100020,
-	0x21810506,
-	0x00100030,
-	0x21810506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x1980c506,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x11808504,
-	0x00100030,
-	0x3981ca05,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x10008a04,
-	0x00100000,
-	0x3981ca05,
-	0x00100030,
-	0x1980c506,
-	0x00100030,
-	0x29814507,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a0c,
-	0x00100008,
-	0x01000a0d,
-	0x00100028,
-	0x1980c50e,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x1180850c,
-	0x00100038,
-	0x3981ca0d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x10008a0c,
-	0x00100008,
-	0x3981ca0d,
-	0x00100038,
-	0x1980c50e,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x02001405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x13008a06,
-	0x01900060,
-	0x13008a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x0200140d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x0b004a06,
-	0x01900060,
-	0x0b004a06,
-	0x01900060,
-	0x5b02ca04,
-	0x00100060,
-	0x3b01d405,
-	0x00100060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x5802d404,
-	0x00100000,
-	0x3b01d405,
-	0x00100060,
-	0x0b004a06,
-	0x01900060,
-	0x23010a07,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x5002940c,
-	0x00100010,
-	0x3201940d,
-	0x00100050,
-	0x0b004a0e,
-	0x01900070,
-	0x0b004a0e,
-	0x01900070,
-	0x5b02ca0c,
-	0x00100070,
-	0x3b01d40d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x5802d40c,
-	0x00100010,
-	0x3b01d40d,
-	0x00100070,
-	0x0b004a0e,
-	0x01900070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x000f4800,
-	0x62031405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x53028a07,
-	0x01900060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x000f4808,
-	0x6203140d,
-	0x00100048,
-	0x53028a0e,
-	0x01900068,
-	0x53028a0f,
-	0x01900068,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100004,
-	0x11008a0d,
-	0x00100024,
-	0x1980c50e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x2181050e,
-	0x00100034,
-	0x0180050c,
-	0x00100038,
-	0x1180850d,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000a0c,
-	0x00100008,
-	0x11008a0d,
-	0x00100028,
-	0x2181050e,
-	0x00100038,
-	0x2181050e,
-	0x00100038,
-	0x1181850d,
-	0x00100038,
-	0x2981450f,
-	0x01100038,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x08004a04,
-	0x00100000,
-	0x01000a05,
-	0x00100020,
-	0x0180c506,
-	0x00100030,
-	0x0180c506,
-	0x00100030,
-	0x2180c50c,
-	0x00100030,
-	0x49820a0d,
-	0x0016a130,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x2000ca0c,
-	0x00100000,
-	0x49820a0d,
-	0x0016a130,
-	0x1980c50e,
-	0x00100030,
-	0x41824a0d,
-	0x0016a130,
-	0x2981450f,
-	0x01100030,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100008,
-	0x0200140d,
-	0x00100048,
-	0x0b004a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x13008a0e,
-	0x01900068,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x13008a0e,
-	0x01900070,
-	0x13008a0e,
-	0x01900070,
-	0x1b014a0d,
-	0x00100070,
-	0x23010a0f,
-	0x01500070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x50029404,
-	0x00100000,
-	0x32019405,
-	0x00100040,
-	0x03004a06,
-	0x01900060,
-	0x03004a06,
-	0x01900060,
-	0x6b030a0c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x6b03140c,
-	0x00100060,
-	0x4b02140d,
-	0x0016a160,
-	0x0b004a0e,
-	0x01900060,
-	0x4302540d,
-	0x0016a160,
-	0x23010a0f,
-	0x01500060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x53028a06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x43020a04,
-	0x00100060,
-	0x1b00ca05,
-	0x00100060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x53028a0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x43020a0c,
-	0x00100070,
-	0x1b00ca0d,
-	0x00100070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x40021404,
-	0x00100000,
-	0x1a00d405,
-	0x00100040,
-	0x5b02ca06,
-	0x01900060,
-	0x5b02ca06,
-	0x01900060,
-	0x53028a07,
-	0x0190c060,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x4002140c,
-	0x00100010,
-	0x1a00d40d,
-	0x00100050,
-	0x5b02ca0e,
-	0x01900070,
-	0x5b02ca0e,
-	0x01900070,
-	0x53028a0f,
-	0x0190c070,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 pilot_tbl_rev3[] = {
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0xff08,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0x80d5,
-	0xff0a,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xff82,
-	0xffa0,
-	0xff28,
-	0xff0a,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xffff,
-	0xf83f,
-	0xfa1f,
-	0xfa97,
-	0xfab5,
-	0xf2bd,
-	0xf0bf,
-	0xffff,
-	0xffff,
-	0xf017,
-	0xf815,
-	0xf215,
-	0xf095,
-	0xf035,
-	0xf01d,
-	0xffff,
-	0xffff,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xff08,
-	0xff02,
-	0xff80,
-	0xff20,
-	0xf01f,
-	0xf817,
-	0xfa15,
-	0xf295,
-	0xf0b5,
-	0xf03d,
-	0xffff,
-	0xffff,
-	0xf82a,
-	0xfa0a,
-	0xfa82,
-	0xfaa0,
-	0xf2a8,
-	0xf0aa,
-	0xffff,
-	0xffff,
-	0xf002,
-	0xf800,
-	0xf200,
-	0xf080,
-	0xf020,
-	0xf008,
-	0xffff,
-	0xffff,
-	0xf00a,
-	0xf802,
-	0xfa00,
-	0xf280,
-	0xf0a0,
-	0xf028,
-	0xffff,
-	0xffff,
-};
-
-const u32 tmap_tbl_rev3[] = {
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00011111,
-	0x11110000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00088aaa,
-	0xaaaa0000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xaaa8aaa0,
-	0x8aaa8aaa,
-	0xaa8a8a8a,
-	0x000aaa88,
-	0x8aaa0000,
-	0xaaa8a888,
-	0x8aa88a8a,
-	0x8a88a888,
-	0x08080a00,
-	0x0a08080a,
-	0x080a0a08,
-	0x00080808,
-	0x080a0000,
-	0x080a0808,
-	0x080a0808,
-	0x0a0a0a08,
-	0xa0a0a0a0,
-	0x80a0a080,
-	0x8080a0a0,
-	0x00008080,
-	0x80a00000,
-	0x80a080a0,
-	0xa080a0a0,
-	0x8080a0a0,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x99999000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x22000000,
-	0x2222b222,
-	0x22222222,
-	0x222222b2,
-	0xb2222220,
-	0x22222222,
-	0x22d22222,
-	0x00000222,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x33000000,
-	0x3333b333,
-	0x33333333,
-	0x333333b3,
-	0xb3333330,
-	0x33333333,
-	0x33d33333,
-	0x00000333,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x99b99b00,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb99,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x22222200,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0x22222222,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x11111111,
-	0xf1111111,
-	0x11111111,
-	0x11f11111,
-	0x01111111,
-	0xbb9bb900,
-	0xb9b9bb99,
-	0xb99bbbbb,
-	0xbbbb9b9b,
-	0xb9bb99bb,
-	0xb99999b9,
-	0xb9b9b99b,
-	0x00000bbb,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88aa,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x0a888aaa,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00000aaa,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0xbbbbbb00,
-	0x999bbbbb,
-	0x9bb99b9b,
-	0xb9b9b9bb,
-	0xb9b99bbb,
-	0xb9b9b9bb,
-	0xb9bb9b99,
-	0x00000999,
-	0x8a000000,
-	0xaa88a888,
-	0xa88888aa,
-	0xa88a8a88,
-	0xa88aa88a,
-	0x88a8aaaa,
-	0xa8aa8aaa,
-	0x0888a88a,
-	0x0b0b0b00,
-	0x090b0b0b,
-	0x0b090b0b,
-	0x0909090b,
-	0x09090b0b,
-	0x09090b0b,
-	0x09090b09,
-	0x00000909,
-	0x0a000000,
-	0x0a080808,
-	0x080a080a,
-	0x080a0a08,
-	0x080a080a,
-	0x0808080a,
-	0x0a0a0a08,
-	0x0808080a,
-	0xb0b0b000,
-	0x9090b0b0,
-	0x90b09090,
-	0xb0b0b090,
-	0xb0b090b0,
-	0x90b0b0b0,
-	0xb0b09090,
-	0x00000090,
-	0x80000000,
-	0xa080a080,
-	0xa08080a0,
-	0xa0808080,
-	0xa080a080,
-	0x80a0a0a0,
-	0xa0a080a0,
-	0x00a0a0a0,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x33000000,
-	0x3333f333,
-	0x33333333,
-	0x333333f3,
-	0xf3333330,
-	0x33333333,
-	0x33f33333,
-	0x00000333,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x99000000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88888000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x88a88a00,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 intlv_tbl_rev3[] = {
-	0x00802070,
-	0x0671188d,
-	0x0a60192c,
-	0x0a300e46,
-	0x00c1188d,
-	0x080024d2,
-	0x00000070,
-};
-
-const u32 tdtrn_tbl_rev3[] = {
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x061c061c,
-	0x0050ee68,
-	0xf592fe36,
-	0xfe5212f6,
-	0x00000c38,
-	0xfe5212f6,
-	0xf592fe36,
-	0x0050ee68,
-	0x061c061c,
-	0xee680050,
-	0xfe36f592,
-	0x12f6fe52,
-	0x0c380000,
-	0x12f6fe52,
-	0xfe36f592,
-	0xee680050,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0x05e305e3,
-	0x004def0c,
-	0xf5f3fe47,
-	0xfe611246,
-	0x00000bc7,
-	0xfe611246,
-	0xf5f3fe47,
-	0x004def0c,
-	0x05e305e3,
-	0xef0c004d,
-	0xfe47f5f3,
-	0x1246fe61,
-	0x0bc70000,
-	0x1246fe61,
-	0xfe47f5f3,
-	0xef0c004d,
-	0xfa58fa58,
-	0xf895043b,
-	0xff4c09c0,
-	0xfbc6ffa8,
-	0xfb84f384,
-	0x0798f6f9,
-	0x05760122,
-	0x058409f6,
-	0x0b500000,
-	0x05b7f542,
-	0x08860432,
-	0x06ddfee7,
-	0xfb84f384,
-	0xf9d90664,
-	0xf7e8025c,
-	0x00fff7bd,
-	0x05a805a8,
-	0xf7bd00ff,
-	0x025cf7e8,
-	0x0664f9d9,
-	0xf384fb84,
-	0xfee706dd,
-	0x04320886,
-	0xf54205b7,
-	0x00000b50,
-	0x09f60584,
-	0x01220576,
-	0xf6f90798,
-	0xf384fb84,
-	0xffa8fbc6,
-	0x09c0ff4c,
-	0x043bf895,
-	0x02d402d4,
-	0x07de0270,
-	0xfc96079c,
-	0xf90afe94,
-	0xfe00ff2c,
-	0x02d4065d,
-	0x092a0096,
-	0x0014fbb8,
-	0xfd2cfd2c,
-	0x076afb3c,
-	0x0096f752,
-	0xf991fd87,
-	0xfb2c0200,
-	0xfeb8f960,
-	0x08e0fc96,
-	0x049802a8,
-	0xfd2cfd2c,
-	0x02a80498,
-	0xfc9608e0,
-	0xf960feb8,
-	0x0200fb2c,
-	0xfd87f991,
-	0xf7520096,
-	0xfb3c076a,
-	0xfd2cfd2c,
-	0xfbb80014,
-	0x0096092a,
-	0x065d02d4,
-	0xff2cfe00,
-	0xfe94f90a,
-	0x079cfc96,
-	0x027007de,
-	0x02d402d4,
-	0x027007de,
-	0x079cfc96,
-	0xfe94f90a,
-	0xff2cfe00,
-	0x065d02d4,
-	0x0096092a,
-	0xfbb80014,
-	0xfd2cfd2c,
-	0xfb3c076a,
-	0xf7520096,
-	0xfd87f991,
-	0x0200fb2c,
-	0xf960feb8,
-	0xfc9608e0,
-	0x02a80498,
-	0xfd2cfd2c,
-	0x049802a8,
-	0x08e0fc96,
-	0xfeb8f960,
-	0xfb2c0200,
-	0xf991fd87,
-	0x0096f752,
-	0x076afb3c,
-	0xfd2cfd2c,
-	0x0014fbb8,
-	0x092a0096,
-	0x02d4065d,
-	0xfe00ff2c,
-	0xf90afe94,
-	0xfc96079c,
-	0x07de0270,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x062a0000,
-	0xfefa0759,
-	0x08b80908,
-	0xf396fc2d,
-	0xf9d6045c,
-	0xfc4ef608,
-	0xf748f596,
-	0x07b207bf,
-	0x062a062a,
-	0xf84ef841,
-	0xf748f596,
-	0x03b209f8,
-	0xf9d6045c,
-	0x0c6a03d3,
-	0x08b80908,
-	0x0106f8a7,
-	0x062a0000,
-	0xfefaf8a7,
-	0x08b8f6f8,
-	0xf39603d3,
-	0xf9d6fba4,
-	0xfc4e09f8,
-	0xf7480a6a,
-	0x07b2f841,
-	0x062af9d6,
-	0xf84e07bf,
-	0xf7480a6a,
-	0x03b2f608,
-	0xf9d6fba4,
-	0x0c6afc2d,
-	0x08b8f6f8,
-	0x01060759,
-	0x061c061c,
-	0xff30009d,
-	0xffb21141,
-	0xfd87fb54,
-	0xf65dfe59,
-	0x02eef99e,
-	0x0166f03c,
-	0xfff809b6,
-	0x000008a4,
-	0x000af42b,
-	0x00eff577,
-	0xfa840bf2,
-	0xfc02ff51,
-	0x08260f67,
-	0xfff0036f,
-	0x0842f9c3,
-	0x00000000,
-	0x063df7be,
-	0xfc910010,
-	0xf099f7da,
-	0x00af03fe,
-	0xf40e057c,
-	0x0a89ff11,
-	0x0bd5fff6,
-	0xf75c0000,
-	0xf64a0008,
-	0x0fc4fe9a,
-	0x0662fd12,
-	0x01a709a3,
-	0x04ac0279,
-	0xeebf004e,
-	0xff6300d0,
-	0xf9e4f9e4,
-	0x00d0ff63,
-	0x004eeebf,
-	0x027904ac,
-	0x09a301a7,
-	0xfd120662,
-	0xfe9a0fc4,
-	0x0008f64a,
-	0x0000f75c,
-	0xfff60bd5,
-	0xff110a89,
-	0x057cf40e,
-	0x03fe00af,
-	0xf7daf099,
-	0x0010fc91,
-	0xf7be063d,
-	0x00000000,
-	0xf9c30842,
-	0x036ffff0,
-	0x0f670826,
-	0xff51fc02,
-	0x0bf2fa84,
-	0xf57700ef,
-	0xf42b000a,
-	0x08a40000,
-	0x09b6fff8,
-	0xf03c0166,
-	0xf99e02ee,
-	0xfe59f65d,
-	0xfb54fd87,
-	0x1141ffb2,
-	0x009dff30,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0x05e30000,
-	0xff060705,
-	0x085408a0,
-	0xf425fc59,
-	0xfa1d042a,
-	0xfc78f67a,
-	0xf7acf60e,
-	0x075a0766,
-	0x05e305e3,
-	0xf8a6f89a,
-	0xf7acf60e,
-	0x03880986,
-	0xfa1d042a,
-	0x0bdb03a7,
-	0x085408a0,
-	0x00faf8fb,
-	0x05e30000,
-	0xff06f8fb,
-	0x0854f760,
-	0xf42503a7,
-	0xfa1dfbd6,
-	0xfc780986,
-	0xf7ac09f2,
-	0x075af89a,
-	0x05e3fa1d,
-	0xf8a60766,
-	0xf7ac09f2,
-	0x0388f67a,
-	0xfa1dfbd6,
-	0x0bdbfc59,
-	0x0854f760,
-	0x00fa0705,
-	0xfa58fa58,
-	0xf8f0fe00,
-	0x0448073d,
-	0xfdc9fe46,
-	0xf9910258,
-	0x089d0407,
-	0xfd5cf71a,
-	0x02affde0,
-	0x083e0496,
-	0xff5a0740,
-	0xff7afd97,
-	0x00fe01f1,
-	0x0009082e,
-	0xfa94ff75,
-	0xfecdf8ea,
-	0xffb0f693,
-	0xfd2cfa58,
-	0x0433ff16,
-	0xfba405dd,
-	0xfa610341,
-	0x06a606cb,
-	0x0039fd2d,
-	0x0677fa97,
-	0x01fa05e0,
-	0xf896003e,
-	0x075a068b,
-	0x012cfc3e,
-	0xfa23f98d,
-	0xfc7cfd43,
-	0xff90fc0d,
-	0x01c10982,
-	0x00c601d6,
-	0xfd2cfd2c,
-	0x01d600c6,
-	0x098201c1,
-	0xfc0dff90,
-	0xfd43fc7c,
-	0xf98dfa23,
-	0xfc3e012c,
-	0x068b075a,
-	0x003ef896,
-	0x05e001fa,
-	0xfa970677,
-	0xfd2d0039,
-	0x06cb06a6,
-	0x0341fa61,
-	0x05ddfba4,
-	0xff160433,
-	0xfa58fd2c,
-	0xf693ffb0,
-	0xf8eafecd,
-	0xff75fa94,
-	0x082e0009,
-	0x01f100fe,
-	0xfd97ff7a,
-	0x0740ff5a,
-	0x0496083e,
-	0xfde002af,
-	0xf71afd5c,
-	0x0407089d,
-	0x0258f991,
-	0xfe46fdc9,
-	0x073d0448,
-	0xfe00f8f0,
-	0xfd2cfd2c,
-	0xfce00500,
-	0xfc09fddc,
-	0xfe680157,
-	0x04c70571,
-	0xfc3aff21,
-	0xfcd70228,
-	0x056d0277,
-	0x0200fe00,
-	0x0022f927,
-	0xfe3c032b,
-	0xfc44ff3c,
-	0x03e9fbdb,
-	0x04570313,
-	0x04c9ff5c,
-	0x000d03b8,
-	0xfa580000,
-	0xfbe900d2,
-	0xf9d0fe0b,
-	0x0125fdf9,
-	0x042501bf,
-	0x0328fa2b,
-	0xffa902f0,
-	0xfa250157,
-	0x0200fe00,
-	0x03740438,
-	0xff0405fd,
-	0x030cfe52,
-	0x0037fb39,
-	0xff6904c5,
-	0x04f8fd23,
-	0xfd31fc1b,
-	0xfd2cfd2c,
-	0xfc1bfd31,
-	0xfd2304f8,
-	0x04c5ff69,
-	0xfb390037,
-	0xfe52030c,
-	0x05fdff04,
-	0x04380374,
-	0xfe000200,
-	0x0157fa25,
-	0x02f0ffa9,
-	0xfa2b0328,
-	0x01bf0425,
-	0xfdf90125,
-	0xfe0bf9d0,
-	0x00d2fbe9,
-	0x0000fa58,
-	0x03b8000d,
-	0xff5c04c9,
-	0x03130457,
-	0xfbdb03e9,
-	0xff3cfc44,
-	0x032bfe3c,
-	0xf9270022,
-	0xfe000200,
-	0x0277056d,
-	0x0228fcd7,
-	0xff21fc3a,
-	0x057104c7,
-	0x0157fe68,
-	0xfddcfc09,
-	0x0500fce0,
-	0xfd2cfd2c,
-	0x0500fce0,
-	0xfddcfc09,
-	0x0157fe68,
-	0x057104c7,
-	0xff21fc3a,
-	0x0228fcd7,
-	0x0277056d,
-	0xfe000200,
-	0xf9270022,
-	0x032bfe3c,
-	0xff3cfc44,
-	0xfbdb03e9,
-	0x03130457,
-	0xff5c04c9,
-	0x03b8000d,
-	0x0000fa58,
-	0x00d2fbe9,
-	0xfe0bf9d0,
-	0xfdf90125,
-	0x01bf0425,
-	0xfa2b0328,
-	0x02f0ffa9,
-	0x0157fa25,
-	0xfe000200,
-	0x04380374,
-	0x05fdff04,
-	0xfe52030c,
-	0xfb390037,
-	0x04c5ff69,
-	0xfd2304f8,
-	0xfc1bfd31,
-	0xfd2cfd2c,
-	0xfd31fc1b,
-	0x04f8fd23,
-	0xff6904c5,
-	0x0037fb39,
-	0x030cfe52,
-	0xff0405fd,
-	0x03740438,
-	0x0200fe00,
-	0xfa250157,
-	0xffa902f0,
-	0x0328fa2b,
-	0x042501bf,
-	0x0125fdf9,
-	0xf9d0fe0b,
-	0xfbe900d2,
-	0xfa580000,
-	0x000d03b8,
-	0x04c9ff5c,
-	0x04570313,
-	0x03e9fbdb,
-	0xfc44ff3c,
-	0xfe3c032b,
-	0x0022f927,
-	0x0200fe00,
-	0x056d0277,
-	0xfcd70228,
-	0xfc3aff21,
-	0x04c70571,
-	0xfe680157,
-	0xfc09fddc,
-	0xfce00500,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-	0x05a80000,
-	0xff1006be,
-	0x0800084a,
-	0xf49cfc7e,
-	0xfa580400,
-	0xfc9cf6da,
-	0xf800f672,
-	0x0710071c,
-	0x05a805a8,
-	0xf8f0f8e4,
-	0xf800f672,
-	0x03640926,
-	0xfa580400,
-	0x0b640382,
-	0x0800084a,
-	0x00f0f942,
-	0x05a80000,
-	0xff10f942,
-	0x0800f7b6,
-	0xf49c0382,
-	0xfa58fc00,
-	0xfc9c0926,
-	0xf800098e,
-	0x0710f8e4,
-	0x05a8fa58,
-	0xf8f0071c,
-	0xf800098e,
-	0x0364f6da,
-	0xfa58fc00,
-	0x0b64fc7e,
-	0x0800f7b6,
-	0x00f006be,
-};
-
-const u32 noise_var_tbl_rev3[] = {
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-	0x02110211,
-	0x0000014d,
-};
-
-const u16 mcs_tbl_rev3[] = {
-	0x0000,
-	0x0008,
-	0x000a,
-	0x0010,
-	0x0012,
-	0x0019,
-	0x001a,
-	0x001c,
-	0x0080,
-	0x0088,
-	0x008a,
-	0x0090,
-	0x0092,
-	0x0099,
-	0x009a,
-	0x009c,
-	0x0100,
-	0x0108,
-	0x010a,
-	0x0110,
-	0x0112,
-	0x0119,
-	0x011a,
-	0x011c,
-	0x0180,
-	0x0188,
-	0x018a,
-	0x0190,
-	0x0192,
-	0x0199,
-	0x019a,
-	0x019c,
-	0x0000,
-	0x0098,
-	0x00a0,
-	0x00a8,
-	0x009a,
-	0x00a2,
-	0x00aa,
-	0x0120,
-	0x0128,
-	0x0128,
-	0x0130,
-	0x0138,
-	0x0138,
-	0x0140,
-	0x0122,
-	0x012a,
-	0x012a,
-	0x0132,
-	0x013a,
-	0x013a,
-	0x0142,
-	0x01a8,
-	0x01b0,
-	0x01b8,
-	0x01b0,
-	0x01b8,
-	0x01c0,
-	0x01c8,
-	0x01c0,
-	0x01c8,
-	0x01d0,
-	0x01d0,
-	0x01d8,
-	0x01aa,
-	0x01b2,
-	0x01ba,
-	0x01b2,
-	0x01ba,
-	0x01c2,
-	0x01ca,
-	0x01c2,
-	0x01ca,
-	0x01d2,
-	0x01d2,
-	0x01da,
-	0x0001,
-	0x0002,
-	0x0004,
-	0x0009,
-	0x000c,
-	0x0011,
-	0x0014,
-	0x0018,
-	0x0020,
-	0x0021,
-	0x0022,
-	0x0024,
-	0x0081,
-	0x0082,
-	0x0084,
-	0x0089,
-	0x008c,
-	0x0091,
-	0x0094,
-	0x0098,
-	0x00a0,
-	0x00a1,
-	0x00a2,
-	0x00a4,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-	0x0007,
-};
-
-const u32 tdi_tbl20_ant0_rev3[] = {
-	0x00091226,
-	0x000a1429,
-	0x000b56ad,
-	0x000c58b0,
-	0x000d5ab3,
-	0x000e9cb6,
-	0x000f9eba,
-	0x0000c13d,
-	0x00020301,
-	0x00030504,
-	0x00040708,
-	0x0005090b,
-	0x00064b8e,
-	0x00095291,
-	0x000a5494,
-	0x000b9718,
-	0x000c9927,
-	0x000d9b2a,
-	0x000edd2e,
-	0x000fdf31,
-	0x000101b4,
-	0x000243b7,
-	0x000345bb,
-	0x000447be,
-	0x00058982,
-	0x00068c05,
-	0x00099309,
-	0x000a950c,
-	0x000bd78f,
-	0x000cd992,
-	0x000ddb96,
-	0x000f1d99,
-	0x00005fa8,
-	0x0001422c,
-	0x0002842f,
-	0x00038632,
-	0x00048835,
-	0x0005ca38,
-	0x0006ccbc,
-	0x0009d3bf,
-	0x000b1603,
-	0x000c1806,
-	0x000d1a0a,
-	0x000e1c0d,
-	0x000f5e10,
-	0x00008093,
-	0x00018297,
-	0x0002c49a,
-	0x0003c680,
-	0x0004c880,
-	0x00060b00,
-	0x00070d00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl20_ant1_rev3[] = {
-	0x00014b26,
-	0x00028d29,
-	0x000393ad,
-	0x00049630,
-	0x0005d833,
-	0x0006da36,
-	0x00099c3a,
-	0x000a9e3d,
-	0x000bc081,
-	0x000cc284,
-	0x000dc488,
-	0x000f068b,
-	0x0000488e,
-	0x00018b91,
-	0x0002d214,
-	0x0003d418,
-	0x0004d6a7,
-	0x000618aa,
-	0x00071aae,
-	0x0009dcb1,
-	0x000b1eb4,
-	0x000c0137,
-	0x000d033b,
-	0x000e053e,
-	0x000f4702,
-	0x00008905,
-	0x00020c09,
-	0x0003128c,
-	0x0004148f,
-	0x00051712,
-	0x00065916,
-	0x00091b19,
-	0x000a1d28,
-	0x000b5f2c,
-	0x000c41af,
-	0x000d43b2,
-	0x000e85b5,
-	0x000f87b8,
-	0x0000c9bc,
-	0x00024cbf,
-	0x00035303,
-	0x00045506,
-	0x0005978a,
-	0x0006998d,
-	0x00095b90,
-	0x000a5d93,
-	0x000b9f97,
-	0x000c821a,
-	0x000d8400,
-	0x000ec600,
-	0x000fc800,
-	0x00010a00,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant0_rev3[] = {
-	0x0011a346,
-	0x00136ccf,
-	0x0014f5d9,
-	0x001641e2,
-	0x0017cb6b,
-	0x00195475,
-	0x001b2383,
-	0x001cad0c,
-	0x001e7616,
-	0x0000821f,
-	0x00020ba8,
-	0x0003d4b2,
-	0x00056447,
-	0x00072dd0,
-	0x0008b6da,
-	0x000a02e3,
-	0x000b8c6c,
-	0x000d15f6,
-	0x0011e484,
-	0x0013ae0d,
-	0x00153717,
-	0x00168320,
-	0x00180ca9,
-	0x00199633,
-	0x001b6548,
-	0x001ceed1,
-	0x001eb7db,
-	0x0000c3e4,
-	0x00024d6d,
-	0x000416f7,
-	0x0005a585,
-	0x00076f0f,
-	0x0008f818,
-	0x000a4421,
-	0x000bcdab,
-	0x000d9734,
-	0x00122649,
-	0x0013efd2,
-	0x001578dc,
-	0x0016c4e5,
-	0x00184e6e,
-	0x001a17f8,
-	0x001ba686,
-	0x001d3010,
-	0x001ef999,
-	0x00010522,
-	0x00028eac,
-	0x00045835,
-	0x0005e74a,
-	0x0007b0d3,
-	0x00093a5d,
-	0x000a85e6,
-	0x000c0f6f,
-	0x000dd8f9,
-	0x00126787,
-	0x00143111,
-	0x0015ba9a,
-	0x00170623,
-	0x00188fad,
-	0x001a5936,
-	0x001be84b,
-	0x001db1d4,
-	0x001f3b5e,
-	0x000146e7,
-	0x00031070,
-	0x000499fa,
-	0x00062888,
-	0x0007f212,
-	0x00097b9b,
-	0x000ac7a4,
-	0x000c50ae,
-	0x000e1a37,
-	0x0012a94c,
-	0x001472d5,
-	0x0015fc5f,
-	0x00174868,
-	0x0018d171,
-	0x001a9afb,
-	0x001c2989,
-	0x001df313,
-	0x001f7c9c,
-	0x000188a5,
-	0x000351af,
-	0x0004db38,
-	0x0006aa4d,
-	0x000833d7,
-	0x0009bd60,
-	0x000b0969,
-	0x000c9273,
-	0x000e5bfc,
-	0x00132a8a,
-	0x0014b414,
-	0x00163d9d,
-	0x001789a6,
-	0x001912b0,
-	0x001adc39,
-	0x001c6bce,
-	0x001e34d8,
-	0x001fbe61,
-	0x0001ca6a,
-	0x00039374,
-	0x00051cfd,
-	0x0006ec0b,
-	0x00087515,
-	0x0009fe9e,
-	0x000b4aa7,
-	0x000cd3b1,
-	0x000e9d3a,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 tdi_tbl40_ant1_rev3[] = {
-	0x001edb36,
-	0x000129ca,
-	0x0002b353,
-	0x00047cdd,
-	0x0005c8e6,
-	0x000791ef,
-	0x00091bf9,
-	0x000aaa07,
-	0x000c3391,
-	0x000dfd1a,
-	0x00120923,
-	0x0013d22d,
-	0x00155c37,
-	0x0016eacb,
-	0x00187454,
-	0x001a3dde,
-	0x001b89e7,
-	0x001d12f0,
-	0x001f1cfa,
-	0x00016b88,
-	0x00033492,
-	0x0004be1b,
-	0x00060a24,
-	0x0007d32e,
-	0x00095d38,
-	0x000aec4c,
-	0x000c7555,
-	0x000e3edf,
-	0x00124ae8,
-	0x001413f1,
-	0x0015a37b,
-	0x00172c89,
-	0x0018b593,
-	0x001a419c,
-	0x001bcb25,
-	0x001d942f,
-	0x001f63b9,
-	0x0001ad4d,
-	0x00037657,
-	0x0004c260,
-	0x00068be9,
-	0x000814f3,
-	0x0009a47c,
-	0x000b2d8a,
-	0x000cb694,
-	0x000e429d,
-	0x00128c26,
-	0x001455b0,
-	0x0015e4ba,
-	0x00176e4e,
-	0x0018f758,
-	0x001a8361,
-	0x001c0cea,
-	0x001dd674,
-	0x001fa57d,
-	0x0001ee8b,
-	0x0003b795,
-	0x0005039e,
-	0x0006cd27,
-	0x000856b1,
-	0x0009e5c6,
-	0x000b6f4f,
-	0x000cf859,
-	0x000e8462,
-	0x00130deb,
-	0x00149775,
-	0x00162603,
-	0x0017af8c,
-	0x00193896,
-	0x001ac49f,
-	0x001c4e28,
-	0x001e17b2,
-	0x0000a6c7,
-	0x00023050,
-	0x0003f9da,
-	0x00054563,
-	0x00070eec,
-	0x00089876,
-	0x000a2704,
-	0x000bb08d,
-	0x000d3a17,
-	0x001185a0,
-	0x00134f29,
-	0x0014d8b3,
-	0x001667c8,
-	0x0017f151,
-	0x00197adb,
-	0x001b0664,
-	0x001c8fed,
-	0x001e5977,
-	0x0000e805,
-	0x0002718f,
-	0x00043b18,
-	0x000586a1,
-	0x0007502b,
-	0x0008d9b4,
-	0x000a68c9,
-	0x000bf252,
-	0x000dbbdc,
-	0x0011c7e5,
-	0x001390ee,
-	0x00151a78,
-	0x0016a906,
-	0x00183290,
-	0x0019bc19,
-	0x001b4822,
-	0x001cd12c,
-	0x001e9ab5,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 pltlut_tbl_rev3[] = {
-	0x76540213,
-	0x62407351,
-	0x76543210,
-	0x76540213,
-	0x76540213,
-	0x76430521,
-};
-
-const u32 chanest_tbl_rev3[] = {
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x44444444,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-	0x10101010,
-};
-
-const u8 frame_lut_rev3[] = {
-	0x02,
-	0x04,
-	0x14,
-	0x14,
-	0x03,
-	0x05,
-	0x16,
-	0x16,
-	0x0a,
-	0x0c,
-	0x1c,
-	0x1c,
-	0x0b,
-	0x0d,
-	0x1e,
-	0x1e,
-	0x06,
-	0x08,
-	0x18,
-	0x18,
-	0x07,
-	0x09,
-	0x1a,
-	0x1a,
-	0x0e,
-	0x10,
-	0x20,
-	0x28,
-	0x0f,
-	0x11,
-	0x22,
-	0x2a,
-};
-
-const u8 est_pwr_lut_core0_rev3[] = {
-	0x55,
-	0x54,
-	0x54,
-	0x53,
-	0x52,
-	0x52,
-	0x51,
-	0x51,
-	0x50,
-	0x4f,
-	0x4f,
-	0x4e,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x33,
-	0x32,
-	0x31,
-	0x2f,
-	0x2e,
-	0x2c,
-	0x2b,
-	0x29,
-	0x27,
-	0x25,
-	0x23,
-	0x21,
-	0x1f,
-	0x1d,
-	0x1a,
-	0x18,
-	0x15,
-	0x12,
-	0x0e,
-	0x0b,
-	0x07,
-	0x02,
-	0xfd,
-};
-
-const u8 est_pwr_lut_core1_rev3[] = {
-	0x55,
-	0x54,
-	0x54,
-	0x53,
-	0x52,
-	0x52,
-	0x51,
-	0x51,
-	0x50,
-	0x4f,
-	0x4f,
-	0x4e,
-	0x4e,
-	0x4d,
-	0x4c,
-	0x4c,
-	0x4b,
-	0x4a,
-	0x49,
-	0x49,
-	0x48,
-	0x47,
-	0x46,
-	0x46,
-	0x45,
-	0x44,
-	0x43,
-	0x42,
-	0x41,
-	0x40,
-	0x40,
-	0x3f,
-	0x3e,
-	0x3d,
-	0x3c,
-	0x3a,
-	0x39,
-	0x38,
-	0x37,
-	0x36,
-	0x35,
-	0x33,
-	0x32,
-	0x31,
-	0x2f,
-	0x2e,
-	0x2c,
-	0x2b,
-	0x29,
-	0x27,
-	0x25,
-	0x23,
-	0x21,
-	0x1f,
-	0x1d,
-	0x1a,
-	0x18,
-	0x15,
-	0x12,
-	0x0e,
-	0x0b,
-	0x07,
-	0x02,
-	0xfd,
-};
-
-const u8 adj_pwr_lut_core0_rev3[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u8 adj_pwr_lut_core1_rev3[] = {
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-};
-
-const u32 gainctrl_lut_core0_rev3[] = {
-	0x5bf70044,
-	0x5bf70042,
-	0x5bf70040,
-	0x5bf7003e,
-	0x5bf7003c,
-	0x5bf7003b,
-	0x5bf70039,
-	0x5bf70037,
-	0x5bf70036,
-	0x5bf70034,
-	0x5bf70033,
-	0x5bf70031,
-	0x5bf70030,
-	0x5ba70044,
-	0x5ba70042,
-	0x5ba70040,
-	0x5ba7003e,
-	0x5ba7003c,
-	0x5ba7003b,
-	0x5ba70039,
-	0x5ba70037,
-	0x5ba70036,
-	0x5ba70034,
-	0x5ba70033,
-	0x5b770044,
-	0x5b770042,
-	0x5b770040,
-	0x5b77003e,
-	0x5b77003c,
-	0x5b77003b,
-	0x5b770039,
-	0x5b770037,
-	0x5b770036,
-	0x5b770034,
-	0x5b770033,
-	0x5b770031,
-	0x5b770030,
-	0x5b77002f,
-	0x5b77002d,
-	0x5b77002c,
-	0x5b470044,
-	0x5b470042,
-	0x5b470040,
-	0x5b47003e,
-	0x5b47003c,
-	0x5b47003b,
-	0x5b470039,
-	0x5b470037,
-	0x5b470036,
-	0x5b470034,
-	0x5b470033,
-	0x5b470031,
-	0x5b470030,
-	0x5b47002f,
-	0x5b47002d,
-	0x5b47002c,
-	0x5b47002b,
-	0x5b47002a,
-	0x5b270044,
-	0x5b270042,
-	0x5b270040,
-	0x5b27003e,
-	0x5b27003c,
-	0x5b27003b,
-	0x5b270039,
-	0x5b270037,
-	0x5b270036,
-	0x5b270034,
-	0x5b270033,
-	0x5b270031,
-	0x5b270030,
-	0x5b27002f,
-	0x5b170044,
-	0x5b170042,
-	0x5b170040,
-	0x5b17003e,
-	0x5b17003c,
-	0x5b17003b,
-	0x5b170039,
-	0x5b170037,
-	0x5b170036,
-	0x5b170034,
-	0x5b170033,
-	0x5b170031,
-	0x5b170030,
-	0x5b17002f,
-	0x5b17002d,
-	0x5b17002c,
-	0x5b17002b,
-	0x5b17002a,
-	0x5b170028,
-	0x5b170027,
-	0x5b170026,
-	0x5b170025,
-	0x5b170024,
-	0x5b170023,
-	0x5b070044,
-	0x5b070042,
-	0x5b070040,
-	0x5b07003e,
-	0x5b07003c,
-	0x5b07003b,
-	0x5b070039,
-	0x5b070037,
-	0x5b070036,
-	0x5b070034,
-	0x5b070033,
-	0x5b070031,
-	0x5b070030,
-	0x5b07002f,
-	0x5b07002d,
-	0x5b07002c,
-	0x5b07002b,
-	0x5b07002a,
-	0x5b070028,
-	0x5b070027,
-	0x5b070026,
-	0x5b070025,
-	0x5b070024,
-	0x5b070023,
-	0x5b070022,
-	0x5b070021,
-	0x5b070020,
-	0x5b07001f,
-	0x5b07001e,
-	0x5b07001d,
-	0x5b07001d,
-	0x5b07001c,
-};
-
-const u32 gainctrl_lut_core1_rev3[] = {
-	0x5bf70044,
-	0x5bf70042,
-	0x5bf70040,
-	0x5bf7003e,
-	0x5bf7003c,
-	0x5bf7003b,
-	0x5bf70039,
-	0x5bf70037,
-	0x5bf70036,
-	0x5bf70034,
-	0x5bf70033,
-	0x5bf70031,
-	0x5bf70030,
-	0x5ba70044,
-	0x5ba70042,
-	0x5ba70040,
-	0x5ba7003e,
-	0x5ba7003c,
-	0x5ba7003b,
-	0x5ba70039,
-	0x5ba70037,
-	0x5ba70036,
-	0x5ba70034,
-	0x5ba70033,
-	0x5b770044,
-	0x5b770042,
-	0x5b770040,
-	0x5b77003e,
-	0x5b77003c,
-	0x5b77003b,
-	0x5b770039,
-	0x5b770037,
-	0x5b770036,
-	0x5b770034,
-	0x5b770033,
-	0x5b770031,
-	0x5b770030,
-	0x5b77002f,
-	0x5b77002d,
-	0x5b77002c,
-	0x5b470044,
-	0x5b470042,
-	0x5b470040,
-	0x5b47003e,
-	0x5b47003c,
-	0x5b47003b,
-	0x5b470039,
-	0x5b470037,
-	0x5b470036,
-	0x5b470034,
-	0x5b470033,
-	0x5b470031,
-	0x5b470030,
-	0x5b47002f,
-	0x5b47002d,
-	0x5b47002c,
-	0x5b47002b,
-	0x5b47002a,
-	0x5b270044,
-	0x5b270042,
-	0x5b270040,
-	0x5b27003e,
-	0x5b27003c,
-	0x5b27003b,
-	0x5b270039,
-	0x5b270037,
-	0x5b270036,
-	0x5b270034,
-	0x5b270033,
-	0x5b270031,
-	0x5b270030,
-	0x5b27002f,
-	0x5b170044,
-	0x5b170042,
-	0x5b170040,
-	0x5b17003e,
-	0x5b17003c,
-	0x5b17003b,
-	0x5b170039,
-	0x5b170037,
-	0x5b170036,
-	0x5b170034,
-	0x5b170033,
-	0x5b170031,
-	0x5b170030,
-	0x5b17002f,
-	0x5b17002d,
-	0x5b17002c,
-	0x5b17002b,
-	0x5b17002a,
-	0x5b170028,
-	0x5b170027,
-	0x5b170026,
-	0x5b170025,
-	0x5b170024,
-	0x5b170023,
-	0x5b070044,
-	0x5b070042,
-	0x5b070040,
-	0x5b07003e,
-	0x5b07003c,
-	0x5b07003b,
-	0x5b070039,
-	0x5b070037,
-	0x5b070036,
-	0x5b070034,
-	0x5b070033,
-	0x5b070031,
-	0x5b070030,
-	0x5b07002f,
-	0x5b07002d,
-	0x5b07002c,
-	0x5b07002b,
-	0x5b07002a,
-	0x5b070028,
-	0x5b070027,
-	0x5b070026,
-	0x5b070025,
-	0x5b070024,
-	0x5b070023,
-	0x5b070022,
-	0x5b070021,
-	0x5b070020,
-	0x5b07001f,
-	0x5b07001e,
-	0x5b07001d,
-	0x5b07001d,
-	0x5b07001c,
-};
-
-const u32 iq_lut_core0_rev3[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 iq_lut_core1_rev3[] = {
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u16 loft_lut_core0_rev3[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 loft_lut_core1_rev3[] = {
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-	0x0000,
-};
-
-const u16 papd_comp_rfpwr_tbl_core0_rev3[] = {
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-};
-
-const u16 papd_comp_rfpwr_tbl_core1_rev3[] = {
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x0036,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x002a,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x001e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x000e,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01fc,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01ee,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-	0x01d6,
-};
-
-const u32 papd_comp_epsilon_tbl_core0_rev3[] = {
-	0x00000000,
-	0x00001fa0,
-	0x00019f78,
-	0x0001df7e,
-	0x03fa9f86,
-	0x03fd1f90,
-	0x03fe5f8a,
-	0x03fb1f94,
-	0x03fd9fa0,
-	0x00009f98,
-	0x03fd1fac,
-	0x03ff9fa2,
-	0x03fe9fae,
-	0x00001fae,
-	0x03fddfb4,
-	0x03ff1fb8,
-	0x03ff9fbc,
-	0x03ffdfbe,
-	0x03fe9fc2,
-	0x03fedfc6,
-	0x03fedfc6,
-	0x03ff9fc8,
-	0x03ff5fc6,
-	0x03fedfc2,
-	0x03ff9fc0,
-	0x03ff5fac,
-	0x03ff5fac,
-	0x03ff9fa2,
-	0x03ff9fa6,
-	0x03ff9faa,
-	0x03ff5fb0,
-	0x03ff5fb4,
-	0x03ff1fca,
-	0x03ff5fce,
-	0x03fcdfdc,
-	0x03fb4006,
-	0x00000030,
-	0x03ff808a,
-	0x03ff80da,
-	0x0000016c,
-	0x03ff8318,
-	0x03ff063a,
-	0x03fd8bd6,
-	0x00014ffe,
-	0x00034ffe,
-	0x00034ffe,
-	0x0003cffe,
-	0x00040ffe,
-	0x00040ffe,
-	0x0003cffe,
-	0x0003cffe,
-	0x00020ffe,
-	0x03fe0ffe,
-	0x03fdcffe,
-	0x03f94ffe,
-	0x03f54ffe,
-	0x03f44ffe,
-	0x03ef8ffe,
-	0x03ee0ffe,
-	0x03ebcffe,
-	0x03e8cffe,
-	0x03e74ffe,
-	0x03e4cffe,
-	0x03e38ffe,
-};
-
-const u32 papd_cal_scalars_tbl_core0_rev3[] = {
-	0x05af005a,
-	0x0571005e,
-	0x05040066,
-	0x04bd006c,
-	0x047d0072,
-	0x04430078,
-	0x03f70081,
-	0x03cb0087,
-	0x03870091,
-	0x035e0098,
-	0x032e00a1,
-	0x030300aa,
-	0x02d800b4,
-	0x02ae00bf,
-	0x028900ca,
-	0x026400d6,
-	0x024100e3,
-	0x022200f0,
-	0x020200ff,
-	0x01e5010e,
-	0x01ca011e,
-	0x01b0012f,
-	0x01990140,
-	0x01830153,
-	0x016c0168,
-	0x0158017d,
-	0x01450193,
-	0x013301ab,
-	0x012101c5,
-	0x011101e0,
-	0x010201fc,
-	0x00f4021a,
-	0x00e6011d,
-	0x00d9012e,
-	0x00cd0140,
-	0x00c20153,
-	0x00b70167,
-	0x00ac017c,
-	0x00a30193,
-	0x009a01ab,
-	0x009101c4,
-	0x008901df,
-	0x008101fb,
-	0x007a0219,
-	0x00730239,
-	0x006d025b,
-	0x0067027e,
-	0x006102a4,
-	0x005c02cc,
-	0x005602f6,
-	0x00520323,
-	0x004d0353,
-	0x00490385,
-	0x004503bb,
-	0x004103f3,
-	0x003d042f,
-	0x003a046f,
-	0x003704b2,
-	0x003404f9,
-	0x00310545,
-	0x002e0596,
-	0x002b05f5,
-	0x00290640,
-	0x002606a4,
-};
-
-const u32 papd_comp_epsilon_tbl_core1_rev3[] = {
-	0x00000000,
-	0x00001fa0,
-	0x00019f78,
-	0x0001df7e,
-	0x03fa9f86,
-	0x03fd1f90,
-	0x03fe5f8a,
-	0x03fb1f94,
-	0x03fd9fa0,
-	0x00009f98,
-	0x03fd1fac,
-	0x03ff9fa2,
-	0x03fe9fae,
-	0x00001fae,
-	0x03fddfb4,
-	0x03ff1fb8,
-	0x03ff9fbc,
-	0x03ffdfbe,
-	0x03fe9fc2,
-	0x03fedfc6,
-	0x03fedfc6,
-	0x03ff9fc8,
-	0x03ff5fc6,
-	0x03fedfc2,
-	0x03ff9fc0,
-	0x03ff5fac,
-	0x03ff5fac,
-	0x03ff9fa2,
-	0x03ff9fa6,
-	0x03ff9faa,
-	0x03ff5fb0,
-	0x03ff5fb4,
-	0x03ff1fca,
-	0x03ff5fce,
-	0x03fcdfdc,
-	0x03fb4006,
-	0x00000030,
-	0x03ff808a,
-	0x03ff80da,
-	0x0000016c,
-	0x03ff8318,
-	0x03ff063a,
-	0x03fd8bd6,
-	0x00014ffe,
-	0x00034ffe,
-	0x00034ffe,
-	0x0003cffe,
-	0x00040ffe,
-	0x00040ffe,
-	0x0003cffe,
-	0x0003cffe,
-	0x00020ffe,
-	0x03fe0ffe,
-	0x03fdcffe,
-	0x03f94ffe,
-	0x03f54ffe,
-	0x03f44ffe,
-	0x03ef8ffe,
-	0x03ee0ffe,
-	0x03ebcffe,
-	0x03e8cffe,
-	0x03e74ffe,
-	0x03e4cffe,
-	0x03e38ffe,
-};
-
-const u32 papd_cal_scalars_tbl_core1_rev3[] = {
-	0x05af005a,
-	0x0571005e,
-	0x05040066,
-	0x04bd006c,
-	0x047d0072,
-	0x04430078,
-	0x03f70081,
-	0x03cb0087,
-	0x03870091,
-	0x035e0098,
-	0x032e00a1,
-	0x030300aa,
-	0x02d800b4,
-	0x02ae00bf,
-	0x028900ca,
-	0x026400d6,
-	0x024100e3,
-	0x022200f0,
-	0x020200ff,
-	0x01e5010e,
-	0x01ca011e,
-	0x01b0012f,
-	0x01990140,
-	0x01830153,
-	0x016c0168,
-	0x0158017d,
-	0x01450193,
-	0x013301ab,
-	0x012101c5,
-	0x011101e0,
-	0x010201fc,
-	0x00f4021a,
-	0x00e6011d,
-	0x00d9012e,
-	0x00cd0140,
-	0x00c20153,
-	0x00b70167,
-	0x00ac017c,
-	0x00a30193,
-	0x009a01ab,
-	0x009101c4,
-	0x008901df,
-	0x008101fb,
-	0x007a0219,
-	0x00730239,
-	0x006d025b,
-	0x0067027e,
-	0x006102a4,
-	0x005c02cc,
-	0x005602f6,
-	0x00520323,
-	0x004d0353,
-	0x00490385,
-	0x004503bb,
-	0x004103f3,
-	0x003d042f,
-	0x003a046f,
-	0x003704b2,
-	0x003404f9,
-	0x00310545,
-	0x002e0596,
-	0x002b05f5,
-	0x00290640,
-	0x002606a4,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile[] = {
-	{&ant_swctrl_tbl_rev3,
-	 sizeof(ant_swctrl_tbl_rev3) / sizeof(ant_swctrl_tbl_rev3[0]), 9, 0, 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile1[] = {
-	{&ant_swctrl_tbl_rev3_1,
-	 sizeof(ant_swctrl_tbl_rev3_1) / sizeof(ant_swctrl_tbl_rev3_1[0]), 9, 0,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile2[] = {
-	{&ant_swctrl_tbl_rev3_2,
-	 sizeof(ant_swctrl_tbl_rev3_2) / sizeof(ant_swctrl_tbl_rev3_2[0]), 9, 0,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3_volatile3[] = {
-	{&ant_swctrl_tbl_rev3_3,
-	 sizeof(ant_swctrl_tbl_rev3_3) / sizeof(ant_swctrl_tbl_rev3_3[0]), 9, 0,
-	 16}
-	,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev3[] = {
-	{&frame_struct_rev3,
-	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
-	,
-	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
-	 11, 0, 16}
-	,
-	{&tmap_tbl_rev3, sizeof(tmap_tbl_rev3) / sizeof(tmap_tbl_rev3[0]), 12,
-	 0, 32}
-	,
-	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
-	 13, 0, 32}
-	,
-	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
-	 14, 0, 32}
-	,
-	{&noise_var_tbl_rev3,
-	 sizeof(noise_var_tbl_rev3) / sizeof(noise_var_tbl_rev3[0]), 16, 0, 32}
-	,
-	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
-	 16}
-	,
-	{&tdi_tbl20_ant0_rev3,
-	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
-	 32}
-	,
-	{&tdi_tbl20_ant1_rev3,
-	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
-	 32}
-	,
-	{&tdi_tbl40_ant0_rev3,
-	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
-	 32}
-	,
-	{&tdi_tbl40_ant1_rev3,
-	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
-	 32}
-	,
-	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
-	 20, 0, 32}
-	,
-	{&chanest_tbl_rev3,
-	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
-	,
-	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
-	 24, 0, 8}
-	,
-	{&est_pwr_lut_core0_rev3,
-	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev3,
-	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev3,
-	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev3,
-	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
-	 64, 8}
-	,
-	{&gainctrl_lut_core0_rev3,
-	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev3,
-	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
-	 27, 192, 32}
-	,
-	{&iq_lut_core0_rev3,
-	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev3,
-	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev3,
-	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev3,
-	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
-	 16}
-};
-
-const u32 mimophytbl_info_sz_rev3 =
-    sizeof(mimophytbl_info_rev3) / sizeof(mimophytbl_info_rev3[0]);
-const u32 mimophytbl_info_sz_rev3_volatile =
-    sizeof(mimophytbl_info_rev3_volatile) /
-    sizeof(mimophytbl_info_rev3_volatile[0]);
-const u32 mimophytbl_info_sz_rev3_volatile1 =
-    sizeof(mimophytbl_info_rev3_volatile1) /
-    sizeof(mimophytbl_info_rev3_volatile1[0]);
-const u32 mimophytbl_info_sz_rev3_volatile2 =
-    sizeof(mimophytbl_info_rev3_volatile2) /
-    sizeof(mimophytbl_info_rev3_volatile2[0]);
-const u32 mimophytbl_info_sz_rev3_volatile3 =
-    sizeof(mimophytbl_info_rev3_volatile3) /
-    sizeof(mimophytbl_info_rev3_volatile3[0]);
-
-const u32 tmap_tbl_rev7[] = {
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00011111,
-	0x11110000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00088aaa,
-	0xaaaa0000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xaaa8aaa0,
-	0x8aaa8aaa,
-	0xaa8a8a8a,
-	0x000aaa88,
-	0x8aaa0000,
-	0xaaa8a888,
-	0x8aa88a8a,
-	0x8a88a888,
-	0x08080a00,
-	0x0a08080a,
-	0x080a0a08,
-	0x00080808,
-	0x080a0000,
-	0x080a0808,
-	0x080a0808,
-	0x0a0a0a08,
-	0xa0a0a0a0,
-	0x80a0a080,
-	0x8080a0a0,
-	0x00008080,
-	0x80a00000,
-	0x80a080a0,
-	0xa080a0a0,
-	0x8080a0a0,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x99999000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x22000000,
-	0x2222b222,
-	0x22222222,
-	0x222222b2,
-	0xb2222220,
-	0x22222222,
-	0x22d22222,
-	0x00000222,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x33000000,
-	0x3333b333,
-	0x33333333,
-	0x333333b3,
-	0xb3333330,
-	0x33333333,
-	0x33d33333,
-	0x00000333,
-	0x22000000,
-	0x2222a222,
-	0x22222222,
-	0x222222a2,
-	0xa2222220,
-	0x22222222,
-	0x22c22222,
-	0x00000222,
-	0x99b99b00,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb99,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x22222200,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0x22222222,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x11111111,
-	0xf1111111,
-	0x11111111,
-	0x11f11111,
-	0x01111111,
-	0xbb9bb900,
-	0xb9b9bb99,
-	0xb99bbbbb,
-	0xbbbb9b9b,
-	0xb9bb99bb,
-	0xb99999b9,
-	0xb9b9b99b,
-	0x00000bbb,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88aa,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x0a888aaa,
-	0xaa000000,
-	0xa8a8aa88,
-	0xa88aaaaa,
-	0xaaaa8a8a,
-	0xa8aa88a0,
-	0xa88888a8,
-	0xa8a8a88a,
-	0x00000aaa,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0xbbbbbb00,
-	0x999bbbbb,
-	0x9bb99b9b,
-	0xb9b9b9bb,
-	0xb9b99bbb,
-	0xb9b9b9bb,
-	0xb9bb9b99,
-	0x00000999,
-	0x8a000000,
-	0xaa88a888,
-	0xa88888aa,
-	0xa88a8a88,
-	0xa88aa88a,
-	0x88a8aaaa,
-	0xa8aa8aaa,
-	0x0888a88a,
-	0x0b0b0b00,
-	0x090b0b0b,
-	0x0b090b0b,
-	0x0909090b,
-	0x09090b0b,
-	0x09090b0b,
-	0x09090b09,
-	0x00000909,
-	0x0a000000,
-	0x0a080808,
-	0x080a080a,
-	0x080a0a08,
-	0x080a080a,
-	0x0808080a,
-	0x0a0a0a08,
-	0x0808080a,
-	0xb0b0b000,
-	0x9090b0b0,
-	0x90b09090,
-	0xb0b0b090,
-	0xb0b090b0,
-	0x90b0b0b0,
-	0xb0b09090,
-	0x00000090,
-	0x80000000,
-	0xa080a080,
-	0xa08080a0,
-	0xa0808080,
-	0xa080a080,
-	0x80a0a0a0,
-	0xa0a080a0,
-	0x00a0a0a0,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x11000000,
-	0x1111f111,
-	0x11111111,
-	0x111111f1,
-	0xf1111110,
-	0x11111111,
-	0x11f11111,
-	0x00000111,
-	0x33000000,
-	0x3333f333,
-	0x33333333,
-	0x333333f3,
-	0xf3333330,
-	0x33333333,
-	0x33f33333,
-	0x00000333,
-	0x22000000,
-	0x2222f222,
-	0x22222222,
-	0x222222f2,
-	0xf2222220,
-	0x22222222,
-	0x22f22222,
-	0x00000222,
-	0x99000000,
-	0x9b9b99bb,
-	0x9bb99999,
-	0x9999b9b9,
-	0x9b99bb90,
-	0x9bbbbb9b,
-	0x9b9b9bb9,
-	0x00000999,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88888000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00aaa888,
-	0x88a88a00,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x000aa888,
-	0x88880000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa88,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x08aaa888,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x11000000,
-	0x1111a111,
-	0x11111111,
-	0x111111a1,
-	0xa1111110,
-	0x11111111,
-	0x11c11111,
-	0x00000111,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x88000000,
-	0x8a8a88aa,
-	0x8aa88888,
-	0x8888a8a8,
-	0x8a88aa80,
-	0x8aaaaa8a,
-	0x8a8a8aa8,
-	0x00000888,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-	0x00000000,
-};
-
-const u32 noise_var_tbl_rev7[] = {
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-	0x020c020c,
-	0x0000014d,
-};
-
-const u32 papd_comp_epsilon_tbl_core0_rev7[] = {
-	0x00000000,
-	0x00000000,
-	0x00016023,
-	0x00006028,
-	0x00034036,
-	0x0003402e,
-	0x0007203c,
-	0x0006e037,
-	0x00070030,
-	0x0009401f,
-	0x0009a00f,
-	0x000b600d,
-	0x000c8007,
-	0x000ce007,
-	0x00101fff,
-	0x00121ff9,
-	0x0012e004,
-	0x0014dffc,
-	0x0016dff6,
-	0x0018dfe9,
-	0x001b3fe5,
-	0x001c5fd0,
-	0x001ddfc2,
-	0x001f1fb6,
-	0x00207fa4,
-	0x00219f8f,
-	0x0022ff7d,
-	0x00247f6c,
-	0x0024df5b,
-	0x00267f4b,
-	0x0027df3b,
-	0x0029bf3b,
-	0x002b5f2f,
-	0x002d3f2e,
-	0x002f5f2a,
-	0x002fff15,
-	0x00315f0b,
-	0x0032defa,
-	0x0033beeb,
-	0x0034fed9,
-	0x00353ec5,
-	0x00361eb0,
-	0x00363e9b,
-	0x0036be87,
-	0x0036be70,
-	0x0038fe67,
-	0x0044beb2,
-	0x00513ef3,
-	0x00595f11,
-	0x00669f3d,
-	0x0078dfdf,
-	0x00a143aa,
-	0x01642fff,
-	0x0162afff,
-	0x01620fff,
-	0x0160cfff,
-	0x015f0fff,
-	0x015dafff,
-	0x015bcfff,
-	0x015bcfff,
-	0x015b4fff,
-	0x015acfff,
-	0x01590fff,
-	0x0156cfff,
-};
-
-const u32 papd_cal_scalars_tbl_core0_rev7[] = {
-	0x0b5e002d,
-	0x0ae2002f,
-	0x0a3b0032,
-	0x09a70035,
-	0x09220038,
-	0x08ab003b,
-	0x081f003f,
-	0x07a20043,
-	0x07340047,
-	0x06d2004b,
-	0x067a004f,
-	0x06170054,
-	0x05bf0059,
-	0x0571005e,
-	0x051e0064,
-	0x04d3006a,
-	0x04910070,
-	0x044c0077,
-	0x040f007e,
-	0x03d90085,
-	0x03a1008d,
-	0x036f0095,
-	0x033d009e,
-	0x030b00a8,
-	0x02e000b2,
-	0x02b900bc,
-	0x029200c7,
-	0x026d00d3,
-	0x024900e0,
-	0x022900ed,
-	0x020a00fb,
-	0x01ec010a,
-	0x01d20119,
-	0x01b7012a,
-	0x019e013c,
-	0x0188014e,
-	0x01720162,
-	0x015d0177,
-	0x0149018e,
-	0x013701a5,
-	0x012601be,
-	0x011501d8,
-	0x010601f4,
-	0x00f70212,
-	0x00e90231,
-	0x00dc0253,
-	0x00d00276,
-	0x00c4029b,
-	0x00b902c3,
-	0x00af02ed,
-	0x00a50319,
-	0x009c0348,
-	0x0093037a,
-	0x008b03af,
-	0x008303e6,
-	0x007c0422,
-	0x00750460,
-	0x006e04a3,
-	0x006804e9,
-	0x00620533,
-	0x005d0582,
-	0x005805d6,
-	0x0053062e,
-	0x004e068c,
-};
-
-const u32 papd_comp_epsilon_tbl_core1_rev7[] = {
-	0x00000000,
-	0x00000000,
-	0x00016023,
-	0x00006028,
-	0x00034036,
-	0x0003402e,
-	0x0007203c,
-	0x0006e037,
-	0x00070030,
-	0x0009401f,
-	0x0009a00f,
-	0x000b600d,
-	0x000c8007,
-	0x000ce007,
-	0x00101fff,
-	0x00121ff9,
-	0x0012e004,
-	0x0014dffc,
-	0x0016dff6,
-	0x0018dfe9,
-	0x001b3fe5,
-	0x001c5fd0,
-	0x001ddfc2,
-	0x001f1fb6,
-	0x00207fa4,
-	0x00219f8f,
-	0x0022ff7d,
-	0x00247f6c,
-	0x0024df5b,
-	0x00267f4b,
-	0x0027df3b,
-	0x0029bf3b,
-	0x002b5f2f,
-	0x002d3f2e,
-	0x002f5f2a,
-	0x002fff15,
-	0x00315f0b,
-	0x0032defa,
-	0x0033beeb,
-	0x0034fed9,
-	0x00353ec5,
-	0x00361eb0,
-	0x00363e9b,
-	0x0036be87,
-	0x0036be70,
-	0x0038fe67,
-	0x0044beb2,
-	0x00513ef3,
-	0x00595f11,
-	0x00669f3d,
-	0x0078dfdf,
-	0x00a143aa,
-	0x01642fff,
-	0x0162afff,
-	0x01620fff,
-	0x0160cfff,
-	0x015f0fff,
-	0x015dafff,
-	0x015bcfff,
-	0x015bcfff,
-	0x015b4fff,
-	0x015acfff,
-	0x01590fff,
-	0x0156cfff,
-};
-
-const u32 papd_cal_scalars_tbl_core1_rev7[] = {
-	0x0b5e002d,
-	0x0ae2002f,
-	0x0a3b0032,
-	0x09a70035,
-	0x09220038,
-	0x08ab003b,
-	0x081f003f,
-	0x07a20043,
-	0x07340047,
-	0x06d2004b,
-	0x067a004f,
-	0x06170054,
-	0x05bf0059,
-	0x0571005e,
-	0x051e0064,
-	0x04d3006a,
-	0x04910070,
-	0x044c0077,
-	0x040f007e,
-	0x03d90085,
-	0x03a1008d,
-	0x036f0095,
-	0x033d009e,
-	0x030b00a8,
-	0x02e000b2,
-	0x02b900bc,
-	0x029200c7,
-	0x026d00d3,
-	0x024900e0,
-	0x022900ed,
-	0x020a00fb,
-	0x01ec010a,
-	0x01d20119,
-	0x01b7012a,
-	0x019e013c,
-	0x0188014e,
-	0x01720162,
-	0x015d0177,
-	0x0149018e,
-	0x013701a5,
-	0x012601be,
-	0x011501d8,
-	0x010601f4,
-	0x00f70212,
-	0x00e90231,
-	0x00dc0253,
-	0x00d00276,
-	0x00c4029b,
-	0x00b902c3,
-	0x00af02ed,
-	0x00a50319,
-	0x009c0348,
-	0x0093037a,
-	0x008b03af,
-	0x008303e6,
-	0x007c0422,
-	0x00750460,
-	0x006e04a3,
-	0x006804e9,
-	0x00620533,
-	0x005d0582,
-	0x005805d6,
-	0x0053062e,
-	0x004e068c,
-};
-
-const mimophytbl_info_t mimophytbl_info_rev7[] = {
-	{&frame_struct_rev3,
-	 sizeof(frame_struct_rev3) / sizeof(frame_struct_rev3[0]), 10, 0, 32}
-	,
-	{&pilot_tbl_rev3, sizeof(pilot_tbl_rev3) / sizeof(pilot_tbl_rev3[0]),
-	 11, 0, 16}
-	,
-	{&tmap_tbl_rev7, sizeof(tmap_tbl_rev7) / sizeof(tmap_tbl_rev7[0]), 12,
-	 0, 32}
-	,
-	{&intlv_tbl_rev3, sizeof(intlv_tbl_rev3) / sizeof(intlv_tbl_rev3[0]),
-	 13, 0, 32}
-	,
-	{&tdtrn_tbl_rev3, sizeof(tdtrn_tbl_rev3) / sizeof(tdtrn_tbl_rev3[0]),
-	 14, 0, 32}
-	,
-	{&noise_var_tbl_rev7,
-	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
-	,
-	{&mcs_tbl_rev3, sizeof(mcs_tbl_rev3) / sizeof(mcs_tbl_rev3[0]), 18, 0,
-	 16}
-	,
-	{&tdi_tbl20_ant0_rev3,
-	 sizeof(tdi_tbl20_ant0_rev3) / sizeof(tdi_tbl20_ant0_rev3[0]), 19, 128,
-	 32}
-	,
-	{&tdi_tbl20_ant1_rev3,
-	 sizeof(tdi_tbl20_ant1_rev3) / sizeof(tdi_tbl20_ant1_rev3[0]), 19, 256,
-	 32}
-	,
-	{&tdi_tbl40_ant0_rev3,
-	 sizeof(tdi_tbl40_ant0_rev3) / sizeof(tdi_tbl40_ant0_rev3[0]), 19, 640,
-	 32}
-	,
-	{&tdi_tbl40_ant1_rev3,
-	 sizeof(tdi_tbl40_ant1_rev3) / sizeof(tdi_tbl40_ant1_rev3[0]), 19, 768,
-	 32}
-	,
-	{&pltlut_tbl_rev3, sizeof(pltlut_tbl_rev3) / sizeof(pltlut_tbl_rev3[0]),
-	 20, 0, 32}
-	,
-	{&chanest_tbl_rev3,
-	 sizeof(chanest_tbl_rev3) / sizeof(chanest_tbl_rev3[0]), 22, 0, 32}
-	,
-	{&frame_lut_rev3, sizeof(frame_lut_rev3) / sizeof(frame_lut_rev3[0]),
-	 24, 0, 8}
-	,
-	{&est_pwr_lut_core0_rev3,
-	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev3,
-	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev3,
-	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev3,
-	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
-	 64, 8}
-	,
-	{&gainctrl_lut_core0_rev3,
-	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev3,
-	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
-	 27, 192, 32}
-	,
-	{&iq_lut_core0_rev3,
-	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev3,
-	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev3,
-	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev3,
-	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
-	 16}
-	,
-	{&papd_comp_rfpwr_tbl_core0_rev3,
-	 sizeof(papd_comp_rfpwr_tbl_core0_rev3) /
-	 sizeof(papd_comp_rfpwr_tbl_core0_rev3[0]), 26, 576, 16}
-	,
-	{&papd_comp_rfpwr_tbl_core1_rev3,
-	 sizeof(papd_comp_rfpwr_tbl_core1_rev3) /
-	 sizeof(papd_comp_rfpwr_tbl_core1_rev3[0]), 27, 576, 16}
-	,
-	{&papd_comp_epsilon_tbl_core0_rev7,
-	 sizeof(papd_comp_epsilon_tbl_core0_rev7) /
-	 sizeof(papd_comp_epsilon_tbl_core0_rev7[0]), 31, 0, 32}
-	,
-	{&papd_cal_scalars_tbl_core0_rev7,
-	 sizeof(papd_cal_scalars_tbl_core0_rev7) /
-	 sizeof(papd_cal_scalars_tbl_core0_rev7[0]), 32, 0, 32}
-	,
-	{&papd_comp_epsilon_tbl_core1_rev7,
-	 sizeof(papd_comp_epsilon_tbl_core1_rev7) /
-	 sizeof(papd_comp_epsilon_tbl_core1_rev7[0]), 33, 0, 32}
-	,
-	{&papd_cal_scalars_tbl_core1_rev7,
-	 sizeof(papd_cal_scalars_tbl_core1_rev7) /
-	 sizeof(papd_cal_scalars_tbl_core1_rev7[0]), 34, 0, 32}
-	,
-};
-
-const u32 mimophytbl_info_sz_rev7 =
-    sizeof(mimophytbl_info_rev7) / sizeof(mimophytbl_info_rev7[0]);
-
-const mimophytbl_info_t mimophytbl_info_rev16[] = {
-	{&noise_var_tbl_rev7,
-	 sizeof(noise_var_tbl_rev7) / sizeof(noise_var_tbl_rev7[0]), 16, 0, 32}
-	,
-	{&est_pwr_lut_core0_rev3,
-	 sizeof(est_pwr_lut_core0_rev3) / sizeof(est_pwr_lut_core0_rev3[0]), 26,
-	 0, 8}
-	,
-	{&est_pwr_lut_core1_rev3,
-	 sizeof(est_pwr_lut_core1_rev3) / sizeof(est_pwr_lut_core1_rev3[0]), 27,
-	 0, 8}
-	,
-	{&adj_pwr_lut_core0_rev3,
-	 sizeof(adj_pwr_lut_core0_rev3) / sizeof(adj_pwr_lut_core0_rev3[0]), 26,
-	 64, 8}
-	,
-	{&adj_pwr_lut_core1_rev3,
-	 sizeof(adj_pwr_lut_core1_rev3) / sizeof(adj_pwr_lut_core1_rev3[0]), 27,
-	 64, 8}
-	,
-	{&gainctrl_lut_core0_rev3,
-	 sizeof(gainctrl_lut_core0_rev3) / sizeof(gainctrl_lut_core0_rev3[0]),
-	 26, 192, 32}
-	,
-	{&gainctrl_lut_core1_rev3,
-	 sizeof(gainctrl_lut_core1_rev3) / sizeof(gainctrl_lut_core1_rev3[0]),
-	 27, 192, 32}
-	,
-	{&iq_lut_core0_rev3,
-	 sizeof(iq_lut_core0_rev3) / sizeof(iq_lut_core0_rev3[0]), 26, 320, 32}
-	,
-	{&iq_lut_core1_rev3,
-	 sizeof(iq_lut_core1_rev3) / sizeof(iq_lut_core1_rev3[0]), 27, 320, 32}
-	,
-	{&loft_lut_core0_rev3,
-	 sizeof(loft_lut_core0_rev3) / sizeof(loft_lut_core0_rev3[0]), 26, 448,
-	 16}
-	,
-	{&loft_lut_core1_rev3,
-	 sizeof(loft_lut_core1_rev3) / sizeof(loft_lut_core1_rev3[0]), 27, 448,
-	 16}
-	,
-};
-
-const u32 mimophytbl_info_sz_rev16 =
-    sizeof(mimophytbl_info_rev16) / sizeof(mimophytbl_info_rev16[0]);
diff --git a/drivers/staging/brcm80211/phy/wlc_phytbl_n.h b/drivers/staging/brcm80211/phy/wlc_phytbl_n.h
deleted file mode 100644
index 396122f..0000000
--- a/drivers/staging/brcm80211/phy/wlc_phytbl_n.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define ANT_SWCTRL_TBL_REV3_IDX (0)
-
-typedef phytbl_info_t mimophytbl_info_t;
-
-extern const mimophytbl_info_t mimophytbl_info_rev0[],
-    mimophytbl_info_rev0_volatile[];
-extern const u32 mimophytbl_info_sz_rev0, mimophytbl_info_sz_rev0_volatile;
-
-extern const mimophytbl_info_t mimophytbl_info_rev3[],
-    mimophytbl_info_rev3_volatile[], mimophytbl_info_rev3_volatile1[],
-    mimophytbl_info_rev3_volatile2[], mimophytbl_info_rev3_volatile3[];
-extern const u32 mimophytbl_info_sz_rev3, mimophytbl_info_sz_rev3_volatile,
-    mimophytbl_info_sz_rev3_volatile1, mimophytbl_info_sz_rev3_volatile2,
-    mimophytbl_info_sz_rev3_volatile3;
-
-extern const u32 noise_var_tbl_rev3[];
-
-extern const mimophytbl_info_t mimophytbl_info_rev7[];
-extern const u32 mimophytbl_info_sz_rev7;
-extern const u32 noise_var_tbl_rev7[];
-
-extern const mimophytbl_info_t mimophytbl_info_rev16[];
-extern const u32 mimophytbl_info_sz_rev16;
diff --git a/drivers/staging/brcm80211/sys/d11ucode_ext.h b/drivers/staging/brcm80211/sys/d11ucode_ext.h
deleted file mode 100644
index c0c0d66..0000000
--- a/drivers/staging/brcm80211/sys/d11ucode_ext.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-enum {
-	D11UCODE_NAMETAG_START = 0,
-	D11LCN0BSINITVALS24,
-	D11LCN0INITVALS24,
-	D11LCN1BSINITVALS24,
-	D11LCN1INITVALS24,
-	D11LCN2BSINITVALS24,
-	D11LCN2INITVALS24,
-	D11N0ABSINITVALS16,
-	D11N0BSINITVALS16,
-	D11N0INITVALS16,
-	D11UCODE_OVERSIGHT16_MIMO,
-	D11UCODE_OVERSIGHT16_MIMOSZ,
-	D11UCODE_OVERSIGHT24_LCN,
-	D11UCODE_OVERSIGHT24_LCNSZ,
-	D11UCODE_OVERSIGHT_BOMMAJOR,
-	D11UCODE_OVERSIGHT_BOMMINOR
-};
-#define UCODE_LOADER_API_VER 0
diff --git a/drivers/staging/brcm80211/sys/wl_dbg.h b/drivers/staging/brcm80211/sys/wl_dbg.h
deleted file mode 100644
index 54af257..0000000
--- a/drivers/staging/brcm80211/sys/wl_dbg.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_dbg_h_
-#define _wl_dbg_h_
-
-/* wl_msg_level is a bit vector with defs in wlioctl.h */
-extern u32 wl_msg_level;
-
-#define WL_NONE(fmt, args...) no_printk(fmt, ##args)
-
-#define WL_PRINT(level, fmt, args...)		\
-do {						\
-	if (wl_msg_level & level)		\
-		printk(fmt, ##args);		\
-} while (0)
-
-#ifdef BCMDBG
-
-#define	WL_ERROR(fmt, args...)	WL_PRINT(WL_ERROR_VAL, fmt, ##args)
-#define	WL_TRACE(fmt, args...)	WL_PRINT(WL_TRACE_VAL, fmt, ##args)
-#define WL_AMPDU(fmt, args...)	WL_PRINT(WL_AMPDU_VAL, fmt, ##args)
-#define WL_FFPLD(fmt, args...)	WL_PRINT(WL_FFPLD_VAL, fmt, ##args)
-
-#define WL_ERROR_ON()		(wl_msg_level & WL_ERROR_VAL)
-
-/* Extra message control for AMPDU debugging */
-#define   WL_AMPDU_UPDN_VAL	0x00000001	/* Config up/down related  */
-#define   WL_AMPDU_ERR_VAL	0x00000002	/* Calls to beaocn update  */
-#define   WL_AMPDU_TX_VAL	0x00000004	/* Transmit data path */
-#define   WL_AMPDU_RX_VAL	0x00000008	/* Receive data path  */
-#define   WL_AMPDU_CTL_VAL	0x00000010	/* TSF-related items  */
-#define   WL_AMPDU_HW_VAL       0x00000020	/* AMPDU_HW */
-#define   WL_AMPDU_HWTXS_VAL    0x00000040	/* AMPDU_HWTXS */
-#define   WL_AMPDU_HWDBG_VAL    0x00000080	/* AMPDU_DBG */
-
-extern u32 wl_ampdu_dbg;
-
-#define WL_AMPDU_PRINT(level, fmt, args...)	\
-do {						\
-	if (wl_ampdu_dbg & level) {		\
-		WL_AMPDU(fmt, ##args);		\
-	}					\
-} while (0)
-
-#define WL_AMPDU_UPDN(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_UPDN_VAL, fmt, ##args)
-#define WL_AMPDU_RX(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_RX_VAL, fmt, ##args)
-#define WL_AMPDU_ERR(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_ERR_VAL, fmt, ##args)
-#define WL_AMPDU_TX(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_TX_VAL, fmt, ##args)
-#define WL_AMPDU_CTL(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_CTL_VAL, fmt, ##args)
-#define WL_AMPDU_HW(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_HW_VAL, fmt, ##args)
-#define WL_AMPDU_HWTXS(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_HWTXS_VAL, fmt, ##args)
-#define WL_AMPDU_HWDBG(fmt, args...)			\
-	WL_AMPDU_PRINT(WL_AMPDU_HWDBG_VAL, fmt, ##args)
-#define WL_AMPDU_ERR_ON() (wl_ampdu_dbg & WL_AMPDU_ERR_VAL)
-#define WL_AMPDU_HW_ON() (wl_ampdu_dbg & WL_AMPDU_HW_VAL)
-#define WL_AMPDU_HWTXS_ON() (wl_ampdu_dbg & WL_AMPDU_HWTXS_VAL)
-
-#else				/* BCMDBG */
-
-#define	WL_ERROR(fmt, args...)		no_printk(fmt, ##args)
-#define	WL_TRACE(fmt, args...)		no_printk(fmt, ##args)
-#define WL_AMPDU(fmt, args...)		no_printk(fmt, ##args)
-#define WL_FFPLD(fmt, args...)		no_printk(fmt, ##args)
-
-#define WL_ERROR_ON()		0
-
-#define WL_AMPDU_UPDN(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_RX(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_ERR(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_TX(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_CTL(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_HW(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_HWTXS(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_HWDBG(fmt, args...)	no_printk(fmt, ##args)
-#define WL_AMPDU_ERR_ON()       0
-#define WL_AMPDU_HW_ON()        0
-#define WL_AMPDU_HWTXS_ON()     0
-
-#endif				/* BCMDBG */
-
-#endif				/* _wl_dbg_h_ */
diff --git a/drivers/staging/brcm80211/sys/wl_export.h b/drivers/staging/brcm80211/sys/wl_export.h
deleted file mode 100644
index aa8b5a3..0000000
--- a/drivers/staging/brcm80211/sys/wl_export.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_export_h_
-#define _wl_export_h_
-
-/* misc callbacks */
-struct wl_info;
-struct wl_if;
-struct wlc_if;
-extern void wl_init(struct wl_info *wl);
-extern uint wl_reset(struct wl_info *wl);
-extern void wl_intrson(struct wl_info *wl);
-extern u32 wl_intrsoff(struct wl_info *wl);
-extern void wl_intrsrestore(struct wl_info *wl, u32 macintmask);
-extern void wl_event(struct wl_info *wl, char *ifname, wlc_event_t *e);
-extern void wl_event_sendup(struct wl_info *wl, const wlc_event_t *e,
-			    u8 *data, u32 len);
-extern int wl_up(struct wl_info *wl);
-extern void wl_down(struct wl_info *wl);
-extern void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
-			     int prio);
-extern bool wl_alloc_dma_resources(struct wl_info *wl, uint dmaddrwidth);
-
-/* timer functions */
-struct wl_timer;
-extern struct wl_timer *wl_init_timer(struct wl_info *wl,
-				      void (*fn) (void *arg), void *arg,
-				      const char *name);
-extern void wl_free_timer(struct wl_info *wl, struct wl_timer *timer);
-extern void wl_add_timer(struct wl_info *wl, struct wl_timer *timer, uint ms,
-			 int periodic);
-extern bool wl_del_timer(struct wl_info *wl, struct wl_timer *timer);
-
-extern uint wl_buf_to_pktcopy(struct osl_info *osh, void *p, unsigned char *buf,
-			      int len, uint offset);
-extern void *wl_get_pktbuffer(struct osl_info *osh, int len);
-extern int wl_set_pktlen(struct osl_info *osh, void *p, int len);
-
-#define wl_sort_bsslist(a, b) false
-
-extern int wl_tkip_miccheck(struct wl_info *wl, void *p, int hdr_len,
-			    bool group_key, int id);
-extern int wl_tkip_micadd(struct wl_info *wl, void *p, int hdr_len);
-extern int wl_tkip_encrypt(struct wl_info *wl, void *p, int hdr_len);
-extern int wl_tkip_decrypt(struct wl_info *wl, void *p, int hdr_len,
-			   bool group_key);
-extern void wl_tkip_printstats(struct wl_info *wl, bool group_key);
-extern int wl_tkip_keyset(struct wl_info *wl, wsec_key_t *key);
-#endif				/* _wl_export_h_ */
diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.c b/drivers/staging/brcm80211/sys/wl_mac80211.c
deleted file mode 100644
index cd8392b..0000000
--- a/drivers/staging/brcm80211/sys/wl_mac80211.c
+++ /dev/null
@@ -1,1855 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define __UNDEF_NO_VERSION__
-
-#include <linux/kernel.h>
-#include <linux/etherdevice.h>
-#include <linux/string.h>
-#include <linux/pci_ids.h>
-#include <bcmdefs.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <osl.h>
-#define WLC_MAXBSSCFG		1	/* single BSS configs */
-
-#include <wlc_cfg.h>
-#include <net/mac80211.h>
-#include <phy_version.h>
-#include <bcmutils.h>
-#include <pcicfg.h>
-#include <wlioctl.h>
-#include <wlc_key.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <wlc_channel.h>
-#include <wlc_pub.h>
-#include <wlc_scb.h>
-#include <wl_dbg.h>
-#include <wl_export.h>
-
-#include <wl_mac80211.h>
-#include <linux/firmware.h>
-#include <wl_ucode.h>
-#include <d11ucode_ext.h>
-
-
-static void wl_timer(unsigned long data);
-static void _wl_timer(wl_timer_t *t);
-
-
-static int ieee_hw_init(struct ieee80211_hw *hw);
-static int ieee_hw_rate_init(struct ieee80211_hw *hw);
-
-static int wl_linux_watchdog(void *ctx);
-
-/* Flags we support */
-#define MAC_FILTERS (FIF_PROMISC_IN_BSS | \
-	FIF_ALLMULTI | \
-	FIF_FCSFAIL | \
-	FIF_PLCPFAIL | \
-	FIF_CONTROL | \
-	FIF_OTHER_BSS | \
-	FIF_BCN_PRBRESP_PROMISC)
-
-static int wl_found;
-
-struct ieee80211_tkip_data {
-#define TKIP_KEY_LEN 32
-	u8 key[TKIP_KEY_LEN];
-	int key_set;
-
-	u32 tx_iv32;
-	u16 tx_iv16;
-	u16 tx_ttak[5];
-	int tx_phase1_done;
-
-	u32 rx_iv32;
-	u16 rx_iv16;
-	u16 rx_ttak[5];
-	int rx_phase1_done;
-	u32 rx_iv32_new;
-	u16 rx_iv16_new;
-
-	u32 dot11RSNAStatsTKIPReplays;
-	u32 dot11RSNAStatsTKIPICVErrors;
-	u32 dot11RSNAStatsTKIPLocalMICFailures;
-
-	int key_idx;
-
-	struct crypto_tfm *tfm_arc4;
-	struct crypto_tfm *tfm_michael;
-
-	/* scratch buffers for virt_to_page() (crypto API) */
-	u8 rx_hdr[16], tx_hdr[16];
-};
-
-#define WL_DEV_IF(dev)		((struct wl_if *)netdev_priv(dev))
-#define	WL_INFO(dev)		((struct wl_info *)(WL_DEV_IF(dev)->wl))
-static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev);
-static void wl_release_fw(struct wl_info *wl);
-
-/* local prototypes */
-static int wl_start(struct sk_buff *skb, struct wl_info *wl);
-static int wl_start_int(struct wl_info *wl, struct ieee80211_hw *hw,
-			struct sk_buff *skb);
-static void wl_dpc(unsigned long data);
-
-MODULE_AUTHOR("Broadcom Corporation");
-MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver.");
-MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
-MODULE_LICENSE("Dual BSD/GPL");
-
-/* recognized PCI IDs */
-static struct pci_device_id wl_id_table[] = {
-	{PCI_VENDOR_ID_BROADCOM, 0x4357, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43225 2G */
-	{PCI_VENDOR_ID_BROADCOM, 0x4353, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 43224 DUAL */
-	{PCI_VENDOR_ID_BROADCOM, 0x4727, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},	/* 4313 DUAL */
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, wl_id_table);
-static void wl_remove(struct pci_dev *pdev);
-
-
-#ifdef BCMDBG
-static int msglevel = 0xdeadbeef;
-module_param(msglevel, int, 0);
-static int phymsglevel = 0xdeadbeef;
-module_param(phymsglevel, int, 0);
-#endif				/* BCMDBG */
-
-#define HW_TO_WL(hw)	 (hw->priv)
-#define WL_TO_HW(wl)	  (wl->pub->ieee_hw)
-static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int wl_ops_start(struct ieee80211_hw *hw);
-static void wl_ops_stop(struct ieee80211_hw *hw);
-static int wl_ops_add_interface(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif);
-static void wl_ops_remove_interface(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif);
-static int wl_ops_config(struct ieee80211_hw *hw, u32 changed);
-static void wl_ops_bss_info_changed(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_bss_conf *info,
-				    u32 changed);
-static void wl_ops_configure_filter(struct ieee80211_hw *hw,
-				    unsigned int changed_flags,
-				    unsigned int *total_flags, u64 multicast);
-static int wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
-			  bool set);
-static void wl_ops_sw_scan_start(struct ieee80211_hw *hw);
-static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw);
-static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf);
-static int wl_ops_get_stats(struct ieee80211_hw *hw,
-			    struct ieee80211_low_level_stats *stats);
-static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
-static void wl_ops_sta_notify(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      enum sta_notify_cmd cmd,
-			      struct ieee80211_sta *sta);
-static int wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
-			  const struct ieee80211_tx_queue_params *params);
-static u64 wl_ops_get_tsf(struct ieee80211_hw *hw);
-static int wl_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		      struct ieee80211_sta *sta);
-static int wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			 struct ieee80211_sta *sta);
-static int wl_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-			   enum ieee80211_ampdu_mlme_action action,
-			   struct ieee80211_sta *sta, u16 tid, u16 *ssn);
-
-static int wl_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	int status;
-	struct wl_info *wl = hw->priv;
-	WL_LOCK(wl);
-	if (!wl->pub->up) {
-		WL_ERROR("ops->tx called while down\n");
-		status = -ENETDOWN;
-		goto done;
-	}
-	status = wl_start(skb, wl);
- done:
-	WL_UNLOCK(wl);
-	return status;
-}
-
-static int wl_ops_start(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	/*
-	  struct ieee80211_channel *curchan = hw->conf.channel;
-	  WL_NONE("%s : Initial channel: %d\n", __func__, curchan->hw_value);
-	*/
-
-	WL_LOCK(wl);
-	ieee80211_wake_queues(hw);
-	WL_UNLOCK(wl);
-
-	return 0;
-}
-
-static void wl_ops_stop(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	ASSERT(wl);
-	WL_LOCK(wl);
-	ieee80211_stop_queues(hw);
-	WL_UNLOCK(wl);
-}
-
-static int
-wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	struct wl_info *wl;
-	int err;
-
-	/* Just STA for now */
-	if (vif->type != NL80211_IFTYPE_AP &&
-	    vif->type != NL80211_IFTYPE_MESH_POINT &&
-	    vif->type != NL80211_IFTYPE_STATION &&
-	    vif->type != NL80211_IFTYPE_WDS &&
-	    vif->type != NL80211_IFTYPE_ADHOC) {
-		WL_ERROR("%s: Attempt to add type %d, only STA for now\n",
-			 __func__, vif->type);
-		return -EOPNOTSUPP;
-	}
-
-	wl = HW_TO_WL(hw);
-	WL_LOCK(wl);
-	err = wl_up(wl);
-	WL_UNLOCK(wl);
-
-	if (err != 0)
-		WL_ERROR("%s: wl_up() returned %d\n", __func__, err);
-	return err;
-}
-
-static void
-wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	struct wl_info *wl;
-
-	wl = HW_TO_WL(hw);
-
-	/* put driver in down state */
-	WL_LOCK(wl);
-	wl_down(wl);
-	WL_UNLOCK(wl);
-}
-
-static int
-ieee_set_channel(struct ieee80211_hw *hw, struct ieee80211_channel *chan,
-		 enum nl80211_channel_type type)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	int err = 0;
-
-	switch (type) {
-	case NL80211_CHAN_HT20:
-	case NL80211_CHAN_NO_HT:
-		err = wlc_set(wl->wlc, WLC_SET_CHANNEL, chan->hw_value);
-		break;
-	case NL80211_CHAN_HT40MINUS:
-	case NL80211_CHAN_HT40PLUS:
-		WL_ERROR("%s: Need to implement 40 Mhz Channels!\n", __func__);
-		break;
-	}
-
-	if (err)
-		return -EIO;
-	return err;
-}
-
-static int wl_ops_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct ieee80211_conf *conf = &hw->conf;
-	struct wl_info *wl = HW_TO_WL(hw);
-	int err = 0;
-	int new_int;
-
-	WL_LOCK(wl);
-	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
-		WL_NONE("%s: Setting listen interval to %d\n",
-			__func__, conf->listen_interval);
-		if (wlc_iovar_setint
-		    (wl->wlc, "bcn_li_bcn", conf->listen_interval)) {
-			WL_ERROR("%s: Error setting listen_interval\n",
-				 __func__);
-			err = -EIO;
-			goto config_out;
-		}
-		wlc_iovar_getint(wl->wlc, "bcn_li_bcn", &new_int);
-		ASSERT(new_int == conf->listen_interval);
-	}
-	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
-		WL_NONE("Need to set monitor mode\n");
-	if (changed & IEEE80211_CONF_CHANGE_PS)
-		WL_NONE("Need to set Power-save mode\n");
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		WL_NONE("%s: Setting tx power to %d dbm\n",
-			__func__, conf->power_level);
-		if (wlc_iovar_setint
-		    (wl->wlc, "qtxpower", conf->power_level * 4)) {
-			WL_ERROR("%s: Error setting power_level\n", __func__);
-			err = -EIO;
-			goto config_out;
-		}
-		wlc_iovar_getint(wl->wlc, "qtxpower", &new_int);
-		if (new_int != (conf->power_level * 4))
-			WL_ERROR("%s: Power level req != actual, %d %d\n",
-				 __func__, conf->power_level * 4, new_int);
-	}
-	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
-		err = ieee_set_channel(hw, conf->channel, conf->channel_type);
-	}
-	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
-		WL_NONE("%s: srl %d, lrl %d\n",
-			__func__,
-			conf->short_frame_max_tx_count,
-			conf->long_frame_max_tx_count);
-		if (wlc_set
-		    (wl->wlc, WLC_SET_SRL,
-		     conf->short_frame_max_tx_count) < 0) {
-			WL_ERROR("%s: Error setting srl\n", __func__);
-			err = -EIO;
-			goto config_out;
-		}
-		if (wlc_set(wl->wlc, WLC_SET_LRL, conf->long_frame_max_tx_count)
-		    < 0) {
-			WL_ERROR("%s: Error setting lrl\n", __func__);
-			err = -EIO;
-			goto config_out;
-		}
-	}
-
- config_out:
-	WL_UNLOCK(wl);
-	return err;
-}
-
-static void
-wl_ops_bss_info_changed(struct ieee80211_hw *hw,
-			struct ieee80211_vif *vif,
-			struct ieee80211_bss_conf *info, u32 changed)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	int val;
-
-
-	if (changed & BSS_CHANGED_ASSOC) {
-		WL_ERROR("Associated:\t%s\n", info->assoc ? "True" : "False");
-		/* association status changed (associated/disassociated)
-		 * also implies a change in the AID.
-		 */
-	}
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		WL_NONE("Use_cts_prot:\t%s Implement me\n",
-			info->use_cts_prot ? "True" : "False");
-		/* CTS protection changed */
-	}
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		WL_NONE("Short preamble:\t%s Implement me\n",
-			info->use_short_preamble ? "True" : "False");
-		/* preamble changed */
-	}
-	if (changed & BSS_CHANGED_ERP_SLOT) {
-		WL_NONE("Changing short slot:\t%s\n",
-			info->use_short_slot ? "True" : "False");
-		if (info->use_short_slot)
-			val = 1;
-		else
-			val = 0;
-		wlc_set(wl->wlc, WLC_SET_SHORTSLOT_OVERRIDE, val);
-		/* slot timing changed */
-	}
-
-	if (changed & BSS_CHANGED_HT) {
-		WL_NONE("%s: HT mode - Implement me\n", __func__);
-		/* 802.11n parameters changed */
-	}
-	if (changed & BSS_CHANGED_BASIC_RATES) {
-		WL_NONE("Need to change Basic Rates:\t0x%x! Implement me\n",
-			(u32) info->basic_rates);
-		/* Basic rateset changed */
-	}
-	if (changed & BSS_CHANGED_BEACON_INT) {
-		WL_NONE("Beacon Interval:\t%d Implement me\n",
-			info->beacon_int);
-		/* Beacon interval changed */
-	}
-	if (changed & BSS_CHANGED_BSSID) {
-		WL_NONE("new BSSID:\taid %d  bss:%pM\n",
-			info->aid, info->bssid);
-		/* BSSID changed, for whatever reason (IBSS and managed mode) */
-		/* FIXME: need to store bssid in bsscfg */
-		wlc_set_addrmatch(wl->wlc, RCM_BSSID_OFFSET,
-				  (struct ether_addr *)info->bssid);
-	}
-	if (changed & BSS_CHANGED_BEACON) {
-		WL_ERROR("BSS_CHANGED_BEACON\n");
-		/* Beacon data changed, retrieve new beacon (beaconing modes) */
-	}
-	if (changed & BSS_CHANGED_BEACON_ENABLED) {
-		WL_ERROR("Beacon enabled:\t%s\n",
-			 info->enable_beacon ? "True" : "False");
-		/* Beaconing should be enabled/disabled (beaconing modes) */
-	}
-	return;
-}
-
-static void
-wl_ops_configure_filter(struct ieee80211_hw *hw,
-			unsigned int changed_flags,
-			unsigned int *total_flags, u64 multicast)
-{
-	struct wl_info *wl = hw->priv;
-
-	changed_flags &= MAC_FILTERS;
-	*total_flags &= MAC_FILTERS;
-	if (changed_flags & FIF_PROMISC_IN_BSS)
-		WL_ERROR("FIF_PROMISC_IN_BSS\n");
-	if (changed_flags & FIF_ALLMULTI)
-		WL_ERROR("FIF_ALLMULTI\n");
-	if (changed_flags & FIF_FCSFAIL)
-		WL_ERROR("FIF_FCSFAIL\n");
-	if (changed_flags & FIF_PLCPFAIL)
-		WL_ERROR("FIF_PLCPFAIL\n");
-	if (changed_flags & FIF_CONTROL)
-		WL_ERROR("FIF_CONTROL\n");
-	if (changed_flags & FIF_OTHER_BSS)
-		WL_ERROR("FIF_OTHER_BSS\n");
-	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
-		WL_NONE("FIF_BCN_PRBRESP_PROMISC\n");
-		WL_LOCK(wl);
-		if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
-			wl->pub->mac80211_state |= MAC80211_PROMISC_BCNS;
-			wlc_mac_bcn_promisc_change(wl->wlc, 1);
-		} else {
-			wlc_mac_bcn_promisc_change(wl->wlc, 0);
-			wl->pub->mac80211_state &= ~MAC80211_PROMISC_BCNS;
-		}
-		WL_UNLOCK(wl);
-	}
-	return;
-}
-
-static int
-wl_ops_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set)
-{
-	WL_ERROR("%s: Enter\n", __func__);
-	return 0;
-}
-
-static void wl_ops_sw_scan_start(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	WL_NONE("Scan Start\n");
-	WL_LOCK(wl);
-	wlc_scan_start(wl->wlc);
-	WL_UNLOCK(wl);
-	return;
-}
-
-static void wl_ops_sw_scan_complete(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = hw->priv;
-	WL_NONE("Scan Complete\n");
-	WL_LOCK(wl);
-	wlc_scan_stop(wl->wlc);
-	WL_UNLOCK(wl);
-	return;
-}
-
-static void wl_ops_set_tsf(struct ieee80211_hw *hw, u64 tsf)
-{
-	WL_ERROR("%s: Enter\n", __func__);
-	return;
-}
-
-static int
-wl_ops_get_stats(struct ieee80211_hw *hw,
-		 struct ieee80211_low_level_stats *stats)
-{
-	WL_ERROR("%s: Enter\n", __func__);
-	return 0;
-}
-
-static int wl_ops_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
-	WL_ERROR("%s: Enter\n", __func__);
-	return 0;
-}
-
-static void
-wl_ops_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-		  enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
-{
-	WL_NONE("%s: Enter\n", __func__);
-	switch (cmd) {
-	default:
-		WL_ERROR("%s: Unknown cmd = %d\n", __func__, cmd);
-		break;
-	}
-	return;
-}
-
-static int
-wl_ops_conf_tx(struct ieee80211_hw *hw, u16 queue,
-	       const struct ieee80211_tx_queue_params *params)
-{
-	struct wl_info *wl = hw->priv;
-
-	WL_NONE("%s: Enter (WME config)\n", __func__);
-	WL_NONE("queue %d, txop %d, cwmin %d, cwmax %d, aifs %d\n", queue,
-		 params->txop, params->cw_min, params->cw_max, params->aifs);
-
-	WL_LOCK(wl);
-	wlc_wme_setparams(wl->wlc, queue, (void *)params, true);
-	WL_UNLOCK(wl);
-
-	return 0;
-}
-
-static u64 wl_ops_get_tsf(struct ieee80211_hw *hw)
-{
-	WL_ERROR("%s: Enter\n", __func__);
-	return 0;
-}
-
-static int
-wl_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-	   struct ieee80211_sta *sta)
-{
-	struct scb *scb;
-
-	int i;
-	struct wl_info *wl = hw->priv;
-
-	/* Init the scb */
-	scb = (struct scb *)sta->drv_priv;
-	memset(scb, 0, sizeof(struct scb));
-	for (i = 0; i < NUMPRIO; i++)
-		scb->seqctl[i] = 0xFFFF;
-	scb->seqctl_nonqos = 0xFFFF;
-	scb->magic = SCB_MAGIC;
-
-	wl->pub->global_scb = scb;
-	wl->pub->global_ampdu = &(scb->scb_ampdu);
-	wl->pub->global_ampdu->scb = scb;
-	wl->pub->global_ampdu->max_pdu = 16;
-	pktq_init(&scb->scb_ampdu.txq, AMPDU_MAX_SCB_TID,
-		  AMPDU_MAX_SCB_TID * PKTQ_LEN_DEFAULT);
-
-	sta->ht_cap.ht_supported = true;
-	sta->ht_cap.ampdu_factor = AMPDU_RX_FACTOR_64K;
-	sta->ht_cap.ampdu_density = AMPDU_DEF_MPDU_DENSITY;
-	sta->ht_cap.cap = IEEE80211_HT_CAP_GRN_FLD |
-	    IEEE80211_HT_CAP_SGI_20 |
-	    IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT;
-
-	/* minstrel_ht initiates addBA on our behalf by calling ieee80211_start_tx_ba_session() */
-	return 0;
-}
-
-static int
-wl_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
-	      struct ieee80211_sta *sta)
-{
-	WL_NONE("%s: Enter\n", __func__);
-	return 0;
-}
-
-static int
-wl_ampdu_action(struct ieee80211_hw *hw,
-		struct ieee80211_vif *vif,
-		enum ieee80211_ampdu_mlme_action action,
-		struct ieee80211_sta *sta, u16 tid, u16 *ssn)
-{
-#if defined(BCMDBG)
-	struct scb *scb = (struct scb *)sta->drv_priv;
-#endif
-	struct wl_info *wl = hw->priv;
-
-	ASSERT(scb->magic == SCB_MAGIC);
-	switch (action) {
-	case IEEE80211_AMPDU_RX_START:
-		WL_NONE("%s: action = IEEE80211_AMPDU_RX_START\n", __func__);
-		break;
-	case IEEE80211_AMPDU_RX_STOP:
-		WL_NONE("%s: action = IEEE80211_AMPDU_RX_STOP\n", __func__);
-		break;
-	case IEEE80211_AMPDU_TX_START:
-		if (!wlc_aggregatable(wl->wlc, tid)) {
-			/* WL_ERROR("START: tid %d is not agg' able, return FAILURE to stack\n", tid); */
-			return -1;
-		}
-		/* XXX: Use the starting sequence number provided ... */
-		*ssn = 0;
-		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
-
-	case IEEE80211_AMPDU_TX_STOP:
-		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
-		break;
-	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		/* Not sure what to do here */
-		/* Power save wakeup */
-		WL_NONE("%s: action = IEEE80211_AMPDU_TX_OPERATIONAL\n",
-			__func__);
-		break;
-	default:
-		WL_ERROR("%s: Invalid command, ignoring\n", __func__);
-	}
-
-	return 0;
-}
-
-static const struct ieee80211_ops wl_ops = {
-	.tx = wl_ops_tx,
-	.start = wl_ops_start,
-	.stop = wl_ops_stop,
-	.add_interface = wl_ops_add_interface,
-	.remove_interface = wl_ops_remove_interface,
-	.config = wl_ops_config,
-	.bss_info_changed = wl_ops_bss_info_changed,
-	.configure_filter = wl_ops_configure_filter,
-	.set_tim = wl_ops_set_tim,
-	.sw_scan_start = wl_ops_sw_scan_start,
-	.sw_scan_complete = wl_ops_sw_scan_complete,
-	.set_tsf = wl_ops_set_tsf,
-	.get_stats = wl_ops_get_stats,
-	.set_rts_threshold = wl_ops_set_rts_threshold,
-	.sta_notify = wl_ops_sta_notify,
-	.conf_tx = wl_ops_conf_tx,
-	.get_tsf = wl_ops_get_tsf,
-	.sta_add = wl_sta_add,
-	.sta_remove = wl_sta_remove,
-	.ampdu_action = wl_ampdu_action,
-};
-
-static int wl_set_hint(struct wl_info *wl, char *abbrev)
-{
-	WL_ERROR("%s: Sending country code %c%c to MAC80211\n",
-		 __func__, abbrev[0], abbrev[1]);
-	return regulatory_hint(wl->pub->ieee_hw->wiphy, abbrev);
-}
-
-/**
- * attach to the WL device.
- *
- * Attach to the WL device identified by vendor and device parameters.
- * regs is a host accessible memory address pointing to WL device registers.
- *
- * wl_attach is not defined as static because in the case where no bus
- * is defined, wl_attach will never be called, and thus, gcc will issue
- * a warning that this function is defined but not used if we declare
- * it as static.
- */
-static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs,
-			    uint bustype, void *btparam, uint irq)
-{
-	struct wl_info *wl;
-	struct osl_info *osh;
-	int unit, err;
-
-	unsigned long base_addr;
-	struct ieee80211_hw *hw;
-	u8 perm[ETH_ALEN];
-
-	unit = wl_found;
-	err = 0;
-
-	if (unit < 0) {
-		WL_ERROR("wl%d: unit number overflow, exiting\n", unit);
-		return NULL;
-	}
-
-	osh = osl_attach(btparam, bustype);
-	ASSERT(osh);
-
-	/* allocate private info */
-	hw = pci_get_drvdata(btparam);	/* btparam == pdev */
-	wl = hw->priv;
-	ASSERT(wl);
-
-	wl->osh = osh;
-	atomic_set(&wl->callbacks, 0);
-
-	/* setup the bottom half handler */
-	tasklet_init(&wl->tasklet, wl_dpc, (unsigned long) wl);
-
-
-
-	base_addr = regs;
-
-	if (bustype == PCI_BUS) {
-		wl->piomode = false;
-	} else if (bustype == RPC_BUS) {
-		/* Do nothing */
-	} else {
-		bustype = PCI_BUS;
-		WL_TRACE("force to PCI\n");
-	}
-	wl->bcm_bustype = bustype;
-
-	wl->regsva = ioremap_nocache(base_addr, PCI_BAR0_WINSZ);
-	if (wl->regsva == NULL) {
-		WL_ERROR("wl%d: ioremap() failed\n", unit);
-		goto fail;
-	}
-	spin_lock_init(&wl->lock);
-	spin_lock_init(&wl->isr_lock);
-
-	/* prepare ucode */
-	if (wl_request_fw(wl, (struct pci_dev *)btparam)) {
-		printf("%s: Failed to find firmware usually in %s\n",
-			KBUILD_MODNAME, "/lib/firmware/brcm");
-		wl_release_fw(wl);
-		wl_remove((struct pci_dev *)btparam);
-		goto fail1;
-	}
-
-	/* common load-time initialization */
-	wl->wlc = wlc_attach((void *)wl, vendor, device, unit, wl->piomode, osh,
-			     wl->regsva, wl->bcm_bustype, btparam, &err);
-	wl_release_fw(wl);
-	if (!wl->wlc) {
-		printf("%s: wlc_attach() failed with code %d\n",
-			KBUILD_MODNAME, err);
-		goto fail;
-	}
-	wl->pub = wlc_pub(wl->wlc);
-
-	wl->pub->ieee_hw = hw;
-	ASSERT(wl->pub->ieee_hw);
-	ASSERT(wl->pub->ieee_hw->priv == wl);
-
-
-	if (wlc_iovar_setint(wl->wlc, "mpc", 0)) {
-		WL_ERROR("wl%d: Error setting MPC variable to 0\n", unit);
-	}
-
-	/* register our interrupt handler */
-	if (request_irq(irq, wl_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
-		WL_ERROR("wl%d: request_irq() failed\n", unit);
-		goto fail;
-	}
-	wl->irq = irq;
-
-	/* register module */
-	wlc_module_register(wl->pub, NULL, "linux", wl, NULL, wl_linux_watchdog,
-			    NULL);
-
-	if (ieee_hw_init(hw)) {
-		WL_ERROR("wl%d: %s: ieee_hw_init failed!\n", unit, __func__);
-		goto fail;
-	}
-
-	bcopy(&wl->pub->cur_etheraddr, perm, ETH_ALEN);
-	ASSERT(is_valid_ether_addr(perm));
-	SET_IEEE80211_PERM_ADDR(hw, perm);
-
-	err = ieee80211_register_hw(hw);
-	if (err) {
-		WL_ERROR("%s: ieee80211_register_hw failed, status %d\n",
-			 __func__, err);
-	}
-
-	if (wl->pub->srom_ccode[0])
-		err = wl_set_hint(wl, wl->pub->srom_ccode);
-	else
-		err = wl_set_hint(wl, "US");
-	if (err) {
-		WL_ERROR("%s: regulatory_hint failed, status %d\n",
-			 __func__, err);
-	}
-	WL_ERROR("wl%d: Broadcom BCM43xx 802.11 MAC80211 Driver (" PHY_VERSION_STR ")",
-		 unit);
-
-#ifdef BCMDBG
-	printf(" (Compiled at " __TIME__ " on " __DATE__ ")");
-#endif				/* BCMDBG */
-	printf("\n");
-
-	wl_found++;
-	return wl;
-
-fail:
-	wl_free(wl);
-fail1:
-	return NULL;
-}
-
-
-
-#define CHAN2GHZ(channel, freqency, chflags)  { \
-	.band = IEEE80211_BAND_2GHZ, \
-	.center_freq = (freqency), \
-	.hw_value = (channel), \
-	.flags = chflags, \
-	.max_antenna_gain = 0, \
-	.max_power = 19, \
-}
-
-static struct ieee80211_channel wl_2ghz_chantable[] = {
-	CHAN2GHZ(1, 2412, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(2, 2417, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(3, 2422, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(4, 2427, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN2GHZ(5, 2432, 0),
-	CHAN2GHZ(6, 2437, 0),
-	CHAN2GHZ(7, 2442, 0),
-	CHAN2GHZ(8, 2447, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(9, 2452, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(10, 2457, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(11, 2462, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(12, 2467,
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(13, 2472,
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN2GHZ(14, 2484,
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define CHAN5GHZ(channel, chflags)  { \
-	.band = IEEE80211_BAND_5GHZ, \
-	.center_freq = 5000 + 5*(channel), \
-	.hw_value = (channel), \
-	.flags = chflags, \
-	.max_antenna_gain = 0, \
-	.max_power = 21, \
-}
-
-static struct ieee80211_channel wl_5ghz_nphy_chantable[] = {
-	/* UNII-1 */
-	CHAN5GHZ(36, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(40, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(44, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(48, IEEE80211_CHAN_NO_HT40PLUS),
-	/* UNII-2 */
-	CHAN5GHZ(52,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(56,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(60,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(64,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	/* MID */
-	CHAN5GHZ(100,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(104,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(108,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(112,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(116,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(120,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(124,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(128,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(132,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(136,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(140,
-		 IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS |
-		 IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_HT40PLUS |
-		 IEEE80211_CHAN_NO_HT40MINUS),
-	/* UNII-3 */
-	CHAN5GHZ(149, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(153, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(157, IEEE80211_CHAN_NO_HT40MINUS),
-	CHAN5GHZ(161, IEEE80211_CHAN_NO_HT40PLUS),
-	CHAN5GHZ(165, IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
-};
-
-#define RATE(rate100m, _flags) { \
-	.bitrate = (rate100m), \
-	.flags = (_flags), \
-	.hw_value = (rate100m / 5), \
-}
-
-static struct ieee80211_rate wl_legacy_ratetable[] = {
-	RATE(10, 0),
-	RATE(20, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(55, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(110, IEEE80211_RATE_SHORT_PREAMBLE),
-	RATE(60, 0),
-	RATE(90, 0),
-	RATE(120, 0),
-	RATE(180, 0),
-	RATE(240, 0),
-	RATE(360, 0),
-	RATE(480, 0),
-	RATE(540, 0),
-};
-
-static struct ieee80211_supported_band wl_band_2GHz_nphy = {
-	.band = IEEE80211_BAND_2GHZ,
-	.channels = wl_2ghz_chantable,
-	.n_channels = ARRAY_SIZE(wl_2ghz_chantable),
-	.bitrates = wl_legacy_ratetable,
-	.n_bitrates = ARRAY_SIZE(wl_legacy_ratetable),
-	.ht_cap = {
-		   /* from include/linux/ieee80211.h */
-		   .cap = IEEE80211_HT_CAP_GRN_FLD |
-		   IEEE80211_HT_CAP_SGI_20 |
-		   IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
-		   .ht_supported = true,
-		   .ampdu_factor = AMPDU_RX_FACTOR_64K,
-		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
-		   .mcs = {
-			   /* placeholders for now */
-			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
-			   .rx_highest = 500,
-			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
-		   }
-};
-
-static struct ieee80211_supported_band wl_band_5GHz_nphy = {
-	.band = IEEE80211_BAND_5GHZ,
-	.channels = wl_5ghz_nphy_chantable,
-	.n_channels = ARRAY_SIZE(wl_5ghz_nphy_chantable),
-	.bitrates = wl_legacy_ratetable + 4,
-	.n_bitrates = ARRAY_SIZE(wl_legacy_ratetable) - 4,
-	.ht_cap = {
-		   /* use IEEE80211_HT_CAP_* from include/linux/ieee80211.h */
-		   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,	/* No 40 mhz yet */
-		   .ht_supported = true,
-		   .ampdu_factor = AMPDU_RX_FACTOR_64K,
-		   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
-		   .mcs = {
-			   /* placeholders for now */
-			   .rx_mask = {0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0},
-			   .rx_highest = 500,
-			   .tx_params = IEEE80211_HT_MCS_TX_DEFINED}
-		   }
-};
-
-static int ieee_hw_rate_init(struct ieee80211_hw *hw)
-{
-	struct wl_info *wl = HW_TO_WL(hw);
-	int has_5g;
-	char phy_list[4];
-
-	has_5g = 0;
-
-	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
-	hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
-
-	if (wlc_get(wl->wlc, WLC_GET_PHYLIST, (int *)&phy_list) < 0) {
-		WL_ERROR("Phy list failed\n");
-	}
-	WL_NONE("%s: phylist = %c\n", __func__, phy_list[0]);
-
-	if (phy_list[0] == 'n' || phy_list[0] == 'c') {
-		if (phy_list[0] == 'c') {
-			/* Single stream */
-			wl_band_2GHz_nphy.ht_cap.mcs.rx_mask[1] = 0;
-			wl_band_2GHz_nphy.ht_cap.mcs.rx_highest = 72;
-		}
-		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl_band_2GHz_nphy;
-	} else {
-		BUG();
-		return -1;
-	}
-
-	/* Assume all bands use the same phy.  True for 11n devices. */
-	if (NBANDS_PUB(wl->pub) > 1) {
-		has_5g++;
-		if (phy_list[0] == 'n' || phy_list[0] == 'c') {
-			hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-			    &wl_band_5GHz_nphy;
-		} else {
-			return -1;
-		}
-	}
-
-	WL_NONE("%s: 2ghz = %d, 5ghz = %d\n", __func__, 1, has_5g);
-
-	return 0;
-}
-
-static int ieee_hw_init(struct ieee80211_hw *hw)
-{
-	hw->flags = IEEE80211_HW_SIGNAL_DBM
-	    /* | IEEE80211_HW_CONNECTION_MONITOR  What is this? */
-	    | IEEE80211_HW_REPORTS_TX_ACK_STATUS
-	    | IEEE80211_HW_AMPDU_AGGREGATION;
-
-	hw->extra_tx_headroom = wlc_get_header_len();
-	/* FIXME: should get this from wlc->machwcap */
-	hw->queues = 4;
-	/* FIXME: this doesn't seem to be used properly in minstrel_ht.
-	 * mac80211/status.c:ieee80211_tx_status() checks this value,
-	 * but mac80211/rc80211_minstrel_ht.c:minstrel_ht_get_rate()
-	 * appears to always set 3 rates
-	 */
-	hw->max_rates = 2;	/* Primary rate and 1 fallback rate */
-
-	hw->channel_change_time = 7 * 1000;	/* channel change time is dependant on chip and band  */
-	hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-
-	hw->rate_control_algorithm = "minstrel_ht";
-
-	hw->sta_data_size = sizeof(struct scb);
-	return ieee_hw_rate_init(hw);
-}
-
-/**
- * determines if a device is a WL device, and if so, attaches it.
- *
- * This function determines if a device pointed to by pdev is a WL device,
- * and if so, performs a wl_attach() on it.
- *
- */
-int __devinit
-wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int rc;
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-	u32 val;
-
-	ASSERT(pdev);
-
-	WL_TRACE("%s: bus %d slot %d func %d irq %d\n",
-		 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
-		 PCI_FUNC(pdev->devfn), pdev->irq);
-
-	if ((pdev->vendor != PCI_VENDOR_ID_BROADCOM) ||
-	    (((pdev->device & 0xff00) != 0x4300) &&
-	     ((pdev->device & 0xff00) != 0x4700) &&
-	     ((pdev->device < 43000) || (pdev->device > 43999))))
-		return -ENODEV;
-
-	rc = pci_enable_device(pdev);
-	if (rc) {
-		WL_ERROR("%s: Cannot enable device %d-%d_%d\n",
-			 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
-			 PCI_FUNC(pdev->devfn));
-		return -ENODEV;
-	}
-	pci_set_master(pdev);
-
-	pci_read_config_dword(pdev, 0x40, &val);
-	if ((val & 0x0000ff00) != 0)
-		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-	hw = ieee80211_alloc_hw(sizeof(struct wl_info), &wl_ops);
-	if (!hw) {
-		WL_ERROR("%s: ieee80211_alloc_hw failed\n", __func__);
-		rc = -ENOMEM;
-		goto err_1;
-	}
-
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-
-	pci_set_drvdata(pdev, hw);
-
-	memset(hw->priv, 0, sizeof(*wl));
-
-	wl = wl_attach(pdev->vendor, pdev->device, pci_resource_start(pdev, 0),
-		       PCI_BUS, pdev, pdev->irq);
-
-	if (!wl) {
-		WL_ERROR("%s: %s: wl_attach failed!\n",
-			 KBUILD_MODNAME, __func__);
-		return -ENODEV;
-	}
-	return 0;
- err_1:
-	WL_ERROR("%s: err_1: Major hoarkage\n", __func__);
-	return 0;
-}
-
-static int wl_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-
-	WL_TRACE("wl: wl_suspend\n");
-
-	hw = pci_get_drvdata(pdev);
-	wl = HW_TO_WL(hw);
-	if (!wl) {
-		WL_ERROR("wl: wl_suspend: pci_get_drvdata failed\n");
-		return -ENODEV;
-	}
-
-	/* only need to flag hw is down for proper resume */
-	WL_LOCK(wl);
-	wl->pub->hw_up = false;
-	WL_UNLOCK(wl);
-
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	return pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static int wl_resume(struct pci_dev *pdev)
-{
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-	int err = 0;
-	u32 val;
-
-	WL_TRACE("wl: wl_resume\n");
-	hw = pci_get_drvdata(pdev);
-	wl = HW_TO_WL(hw);
-	if (!wl) {
-		WL_ERROR("wl: wl_resume: pci_get_drvdata failed\n");
-		return -ENODEV;
-	}
-
-	err = pci_set_power_state(pdev, PCI_D0);
-	if (err)
-		return err;
-
-	pci_restore_state(pdev);
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-
-	pci_set_master(pdev);
-
-	pci_read_config_dword(pdev, 0x40, &val);
-	if ((val & 0x0000ff00) != 0)
-		pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
-
-	/*
-	*  done. driver will be put in up state
-	*  in wl_ops_add_interface() call.
-	*/
-	return err;
-}
-
-static void wl_remove(struct pci_dev *pdev)
-{
-	struct wl_info *wl;
-	struct ieee80211_hw *hw;
-
-	hw = pci_get_drvdata(pdev);
-	wl = HW_TO_WL(hw);
-	if (!wl) {
-		WL_ERROR("wl: wl_remove: pci_get_drvdata failed\n");
-		return;
-	}
-	if (!wlc_chipmatch(pdev->vendor, pdev->device)) {
-		WL_ERROR("wl: wl_remove: wlc_chipmatch failed\n");
-		return;
-	}
-	if (wl->wlc) {
-		ieee80211_unregister_hw(hw);
-		WL_LOCK(wl);
-		wl_down(wl);
-		WL_UNLOCK(wl);
-		WL_NONE("%s: Down\n", __func__);
-	}
-	pci_disable_device(pdev);
-
-	wl_free(wl);
-
-	pci_set_drvdata(pdev, NULL);
-	ieee80211_free_hw(hw);
-}
-
-static struct pci_driver wl_pci_driver = {
-	.name = "brcm80211",
-	.probe = wl_pci_probe,
-	.suspend = wl_suspend,
-	.resume = wl_resume,
-	.remove = __devexit_p(wl_remove),
-	.id_table = wl_id_table,
-};
-
-/**
- * This is the main entry point for the WL driver.
- *
- * This function determines if a device pointed to by pdev is a WL device,
- * and if so, performs a wl_attach() on it.
- *
- */
-static int __init wl_module_init(void)
-{
-	int error = -ENODEV;
-
-#ifdef BCMDBG
-	if (msglevel != 0xdeadbeef)
-		wl_msg_level = msglevel;
-	else {
-		char *var = getvar(NULL, "wl_msglevel");
-		if (var)
-			wl_msg_level = simple_strtoul(var, NULL, 0);
-	}
-	{
-		extern u32 phyhal_msg_level;
-
-		if (phymsglevel != 0xdeadbeef)
-			phyhal_msg_level = phymsglevel;
-		else {
-			char *var = getvar(NULL, "phy_msglevel");
-			if (var)
-				phyhal_msg_level = simple_strtoul(var, NULL, 0);
-		}
-	}
-#endif				/* BCMDBG */
-
-	error = pci_register_driver(&wl_pci_driver);
-	if (!error)
-		return 0;
-
-
-
-	return error;
-}
-
-/**
- * This function unloads the WL driver from the system.
- *
- * This function unconditionally unloads the WL driver module from the
- * system.
- *
- */
-static void __exit wl_module_exit(void)
-{
-	pci_unregister_driver(&wl_pci_driver);
-
-}
-
-module_init(wl_module_init);
-module_exit(wl_module_exit);
-
-/**
- * This function frees the WL per-device resources.
- *
- * This function frees resources owned by the WL device pointed to
- * by the wl parameter.
- *
- */
-void wl_free(struct wl_info *wl)
-{
-	wl_timer_t *t, *next;
-	struct osl_info *osh;
-
-	ASSERT(wl);
-	/* free ucode data */
-	if (wl->fw.fw_cnt)
-		wl_ucode_data_free();
-	if (wl->irq)
-		free_irq(wl->irq, wl);
-
-	/* kill dpc */
-	tasklet_kill(&wl->tasklet);
-
-	if (wl->pub) {
-		wlc_module_unregister(wl->pub, "linux", wl);
-	}
-
-	/* free common resources */
-	if (wl->wlc) {
-		wlc_detach(wl->wlc);
-		wl->wlc = NULL;
-		wl->pub = NULL;
-	}
-
-	/* virtual interface deletion is deferred so we cannot spinwait */
-
-	/* wait for all pending callbacks to complete */
-	while (atomic_read(&wl->callbacks) > 0)
-		schedule();
-
-	/* free timers */
-	for (t = wl->timers; t; t = next) {
-		next = t->next;
-#ifdef BCMDBG
-		if (t->name)
-			kfree(t->name);
-#endif
-		kfree(t);
-	}
-
-	osh = wl->osh;
-
-	/*
-	 * unregister_netdev() calls get_stats() which may read chip registers
-	 * so we cannot unmap the chip registers until after calling unregister_netdev() .
-	 */
-	if (wl->regsva && wl->bcm_bustype != SDIO_BUS &&
-	    wl->bcm_bustype != JTAG_BUS) {
-		iounmap((void *)wl->regsva);
-	}
-	wl->regsva = NULL;
-
-
-	osl_detach(osh);
-}
-
-/* transmit a packet */
-static int BCMFASTPATH wl_start(struct sk_buff *skb, struct wl_info *wl)
-{
-	if (!wl)
-		return -ENETDOWN;
-
-	return wl_start_int(wl, WL_TO_HW(wl), skb);
-}
-
-static int BCMFASTPATH
-wl_start_int(struct wl_info *wl, struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	wlc_sendpkt_mac80211(wl->wlc, skb, hw);
-	return NETDEV_TX_OK;
-}
-
-void wl_txflowcontrol(struct wl_info *wl, struct wl_if *wlif, bool state,
-		      int prio)
-{
-	WL_ERROR("Shouldn't be here %s\n", __func__);
-}
-
-void wl_init(struct wl_info *wl)
-{
-	WL_TRACE("wl%d: wl_init\n", wl->pub->unit);
-
-	wl_reset(wl);
-
-	wlc_init(wl->wlc);
-}
-
-uint wl_reset(struct wl_info *wl)
-{
-	WL_TRACE("wl%d: wl_reset\n", wl->pub->unit);
-
-	wlc_reset(wl->wlc);
-
-	/* dpc will not be rescheduled */
-	wl->resched = 0;
-
-	return 0;
-}
-
-/*
- * These are interrupt on/off entry points. Disable interrupts
- * during interrupt state transition.
- */
-void BCMFASTPATH wl_intrson(struct wl_info *wl)
-{
-	unsigned long flags;
-
-	INT_LOCK(wl, flags);
-	wlc_intrson(wl->wlc);
-	INT_UNLOCK(wl, flags);
-}
-
-bool wl_alloc_dma_resources(struct wl_info *wl, uint addrwidth)
-{
-	return true;
-}
-
-u32 BCMFASTPATH wl_intrsoff(struct wl_info *wl)
-{
-	unsigned long flags;
-	u32 status;
-
-	INT_LOCK(wl, flags);
-	status = wlc_intrsoff(wl->wlc);
-	INT_UNLOCK(wl, flags);
-	return status;
-}
-
-void wl_intrsrestore(struct wl_info *wl, u32 macintmask)
-{
-	unsigned long flags;
-
-	INT_LOCK(wl, flags);
-	wlc_intrsrestore(wl->wlc, macintmask);
-	INT_UNLOCK(wl, flags);
-}
-
-int wl_up(struct wl_info *wl)
-{
-	int error = 0;
-
-	if (wl->pub->up)
-		return 0;
-
-	error = wlc_up(wl->wlc);
-
-	return error;
-}
-
-void wl_down(struct wl_info *wl)
-{
-	uint callbacks, ret_val = 0;
-
-	/* call common down function */
-	ret_val = wlc_down(wl->wlc);
-	callbacks = atomic_read(&wl->callbacks) - ret_val;
-
-	/* wait for down callbacks to complete */
-	WL_UNLOCK(wl);
-
-	/* For HIGH_only driver, it's important to actually schedule other work,
-	 * not just spin wait since everything runs at schedule level
-	 */
-	SPINWAIT((atomic_read(&wl->callbacks) > callbacks), 100 * 1000);
-
-	WL_LOCK(wl);
-}
-
-irqreturn_t BCMFASTPATH wl_isr(int irq, void *dev_id)
-{
-	struct wl_info *wl;
-	bool ours, wantdpc;
-	unsigned long flags;
-
-	wl = (struct wl_info *) dev_id;
-
-	WL_ISRLOCK(wl, flags);
-
-	/* call common first level interrupt handler */
-	ours = wlc_isr(wl->wlc, &wantdpc);
-	if (ours) {
-		/* if more to do... */
-		if (wantdpc) {
-
-			/* ...and call the second level interrupt handler */
-			/* schedule dpc */
-			ASSERT(wl->resched == false);
-			tasklet_schedule(&wl->tasklet);
-		}
-	}
-
-	WL_ISRUNLOCK(wl, flags);
-
-	return IRQ_RETVAL(ours);
-}
-
-static void BCMFASTPATH wl_dpc(unsigned long data)
-{
-	struct wl_info *wl;
-
-	wl = (struct wl_info *) data;
-
-	WL_LOCK(wl);
-
-	/* call the common second level interrupt handler */
-	if (wl->pub->up) {
-		if (wl->resched) {
-			unsigned long flags;
-
-			INT_LOCK(wl, flags);
-			wlc_intrsupd(wl->wlc);
-			INT_UNLOCK(wl, flags);
-		}
-
-		wl->resched = wlc_dpc(wl->wlc, true);
-	}
-
-	/* wlc_dpc() may bring the driver down */
-	if (!wl->pub->up)
-		goto done;
-
-	/* re-schedule dpc */
-	if (wl->resched)
-		tasklet_schedule(&wl->tasklet);
-	else {
-		/* re-enable interrupts */
-		wl_intrson(wl);
-	}
-
- done:
-	WL_UNLOCK(wl);
-}
-
-static void wl_link_up(struct wl_info *wl, char *ifname)
-{
-	WL_ERROR("wl%d: link up (%s)\n", wl->pub->unit, ifname);
-}
-
-static void wl_link_down(struct wl_info *wl, char *ifname)
-{
-	WL_ERROR("wl%d: link down (%s)\n", wl->pub->unit, ifname);
-}
-
-void wl_event(struct wl_info *wl, char *ifname, wlc_event_t *e)
-{
-
-	switch (e->event.event_type) {
-	case WLC_E_LINK:
-	case WLC_E_NDIS_LINK:
-		if (e->event.flags & WLC_EVENT_MSG_LINK)
-			wl_link_up(wl, ifname);
-		else
-			wl_link_down(wl, ifname);
-		break;
-	case WLC_E_RADIO:
-		break;
-	}
-}
-
-static void wl_timer(unsigned long data)
-{
-	_wl_timer((wl_timer_t *) data);
-}
-
-static void _wl_timer(wl_timer_t *t)
-{
-	WL_LOCK(t->wl);
-
-	if (t->set) {
-		if (t->periodic) {
-			t->timer.expires = jiffies + t->ms * HZ / 1000;
-			atomic_inc(&t->wl->callbacks);
-			add_timer(&t->timer);
-			t->set = true;
-		} else
-			t->set = false;
-
-		t->fn(t->arg);
-	}
-
-	atomic_dec(&t->wl->callbacks);
-
-	WL_UNLOCK(t->wl);
-}
-
-wl_timer_t *wl_init_timer(struct wl_info *wl, void (*fn) (void *arg), void *arg,
-			  const char *name)
-{
-	wl_timer_t *t;
-
-	t = kmalloc(sizeof(wl_timer_t), GFP_ATOMIC);
-	if (!t) {
-		WL_ERROR("wl%d: wl_init_timer: out of memory\n", wl->pub->unit);
-		return 0;
-	}
-
-	memset(t, 0, sizeof(wl_timer_t));
-
-	init_timer(&t->timer);
-	t->timer.data = (unsigned long) t;
-	t->timer.function = wl_timer;
-	t->wl = wl;
-	t->fn = fn;
-	t->arg = arg;
-	t->next = wl->timers;
-	wl->timers = t;
-
-#ifdef BCMDBG
-	t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC);
-	if (t->name)
-		strcpy(t->name, name);
-#endif
-
-	return t;
-}
-
-/* BMAC_NOTE: Add timer adds only the kernel timer since it's going to be more accurate
- * as well as it's easier to make it periodic
- */
-void wl_add_timer(struct wl_info *wl, wl_timer_t *t, uint ms, int periodic)
-{
-#ifdef BCMDBG
-	if (t->set) {
-		WL_ERROR("%s: Already set. Name: %s, per %d\n",
-			 __func__, t->name, periodic);
-	}
-#endif
-	ASSERT(!t->set);
-
-	t->ms = ms;
-	t->periodic = (bool) periodic;
-	t->set = true;
-	t->timer.expires = jiffies + ms * HZ / 1000;
-
-	atomic_inc(&wl->callbacks);
-	add_timer(&t->timer);
-}
-
-/* return true if timer successfully deleted, false if still pending */
-bool wl_del_timer(struct wl_info *wl, wl_timer_t *t)
-{
-	if (t->set) {
-		t->set = false;
-		if (!del_timer(&t->timer)) {
-			return false;
-		}
-		atomic_dec(&wl->callbacks);
-	}
-
-	return true;
-}
-
-void wl_free_timer(struct wl_info *wl, wl_timer_t *t)
-{
-	wl_timer_t *tmp;
-
-	/* delete the timer in case it is active */
-	wl_del_timer(wl, t);
-
-	if (wl->timers == t) {
-		wl->timers = wl->timers->next;
-#ifdef BCMDBG
-		if (t->name)
-			kfree(t->name);
-#endif
-		kfree(t);
-		return;
-
-	}
-
-	tmp = wl->timers;
-	while (tmp) {
-		if (tmp->next == t) {
-			tmp->next = t->next;
-#ifdef BCMDBG
-			if (t->name)
-				kfree(t->name);
-#endif
-			kfree(t);
-			return;
-		}
-		tmp = tmp->next;
-	}
-
-}
-
-static int wl_linux_watchdog(void *ctx)
-{
-	struct wl_info *wl = (struct wl_info *) ctx;
-	struct net_device_stats *stats = NULL;
-	uint id;
-	/* refresh stats */
-	if (wl->pub->up) {
-		ASSERT(wl->stats_id < 2);
-
-		id = 1 - wl->stats_id;
-
-		stats = &wl->stats_watchdog[id];
-		stats->rx_packets = WLCNTVAL(wl->pub->_cnt->rxframe);
-		stats->tx_packets = WLCNTVAL(wl->pub->_cnt->txframe);
-		stats->rx_bytes = WLCNTVAL(wl->pub->_cnt->rxbyte);
-		stats->tx_bytes = WLCNTVAL(wl->pub->_cnt->txbyte);
-		stats->rx_errors = WLCNTVAL(wl->pub->_cnt->rxerror);
-		stats->tx_errors = WLCNTVAL(wl->pub->_cnt->txerror);
-		stats->collisions = 0;
-
-		stats->rx_length_errors = 0;
-		stats->rx_over_errors = WLCNTVAL(wl->pub->_cnt->rxoflo);
-		stats->rx_crc_errors = WLCNTVAL(wl->pub->_cnt->rxcrc);
-		stats->rx_frame_errors = 0;
-		stats->rx_fifo_errors = WLCNTVAL(wl->pub->_cnt->rxoflo);
-		stats->rx_missed_errors = 0;
-
-		stats->tx_fifo_errors = WLCNTVAL(wl->pub->_cnt->txuflo);
-
-		wl->stats_id = id;
-
-	}
-
-	return 0;
-}
-
-struct wl_fw_hdr {
-	u32 offset;
-	u32 len;
-	u32 idx;
-};
-
-char *wl_firmwares[WL_MAX_FW] = {
-	"brcm/bcm43xx",
-	NULL
-};
-
-int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, u32 idx)
-{
-	int i, entry;
-	const u8 *pdata;
-	struct wl_fw_hdr *hdr;
-	for (i = 0; i < wl->fw.fw_cnt; i++) {
-		hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
-		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
-		     entry++, hdr++) {
-			if (hdr->idx == idx) {
-				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
-				*pbuf = kmalloc(hdr->len, GFP_ATOMIC);
-				if (*pbuf == NULL) {
-					printf("fail to alloc %d bytes\n",
-					       hdr->len);
-				}
-				bcopy(pdata, *pbuf, hdr->len);
-				return 0;
-			}
-		}
-	}
-	printf("ERROR: ucode buf tag:%d can not be found!\n", idx);
-	*pbuf = NULL;
-	return -1;
-}
-
-int wl_ucode_init_uint(struct wl_info *wl, u32 *data, u32 idx)
-{
-	int i, entry;
-	const u8 *pdata;
-	struct wl_fw_hdr *hdr;
-	for (i = 0; i < wl->fw.fw_cnt; i++) {
-		hdr = (struct wl_fw_hdr *)wl->fw.fw_hdr[i]->data;
-		for (entry = 0; entry < wl->fw.hdr_num_entries[i];
-		     entry++, hdr++) {
-			if (hdr->idx == idx) {
-				pdata = wl->fw.fw_bin[i]->data + hdr->offset;
-				ASSERT(hdr->len == 4);
-				*data = *((u32 *) pdata);
-				return 0;
-			}
-		}
-	}
-	printf("ERROR: ucode tag:%d can not be found!\n", idx);
-	return -1;
-}
-
-static int wl_request_fw(struct wl_info *wl, struct pci_dev *pdev)
-{
-	int status;
-	struct device *device = &pdev->dev;
-	char fw_name[100];
-	int i;
-
-	memset((void *)&wl->fw, 0, sizeof(struct wl_firmware));
-	for (i = 0; i < WL_MAX_FW; i++) {
-		if (wl_firmwares[i] == NULL)
-			break;
-		sprintf(fw_name, "%s-%d.fw", wl_firmwares[i],
-			UCODE_LOADER_API_VER);
-		WL_NONE("request fw %s\n", fw_name);
-		status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
-		if (status) {
-			printf("%s: fail to load firmware %s\n",
-				KBUILD_MODNAME, fw_name);
-			wl_release_fw(wl);
-			return status;
-		}
-		WL_NONE("request fw %s\n", fw_name);
-		sprintf(fw_name, "%s_hdr-%d.fw", wl_firmwares[i],
-			UCODE_LOADER_API_VER);
-		status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
-		if (status) {
-			printf("%s: fail to load firmware %s\n",
-				KBUILD_MODNAME, fw_name);
-			wl_release_fw(wl);
-			return status;
-		}
-		wl->fw.hdr_num_entries[i] =
-		    wl->fw.fw_hdr[i]->size / (sizeof(struct wl_fw_hdr));
-		WL_NONE("request fw %s find: %d entries\n",
-			fw_name, wl->fw.hdr_num_entries[i]);
-	}
-	wl->fw.fw_cnt = i;
-	return wl_ucode_data_init(wl);
-}
-
-void wl_ucode_free_buf(void *p)
-{
-	kfree(p);
-}
-
-static void wl_release_fw(struct wl_info *wl)
-{
-	int i;
-	for (i = 0; i < WL_MAX_FW; i++) {
-		release_firmware(wl->fw.fw_bin[i]);
-		release_firmware(wl->fw.fw_hdr[i]);
-	}
-}
-
-
-/*
- * checks validity of all firmware images loaded from user space
- */
-int wl_check_firmwares(struct wl_info *wl)
-{
-	int i;
-	int entry;
-	int rc = 0;
-	const struct firmware *fw;
-	const struct firmware *fw_hdr;
-	struct wl_fw_hdr *ucode_hdr;
-	for (i = 0; i < WL_MAX_FW && rc == 0; i++) {
-		fw =  wl->fw.fw_bin[i];
-		fw_hdr = wl->fw.fw_hdr[i];
-		if (fw == NULL && fw_hdr == NULL) {
-			break;
-		} else if (fw == NULL || fw_hdr == NULL) {
-			WL_ERROR("%s: invalid bin/hdr fw\n", __func__);
-			rc = -EBADF;
-		} else if (fw_hdr->size % sizeof(struct wl_fw_hdr)) {
-			WL_ERROR("%s: non integral fw hdr file size %d/%zu\n",
-				 __func__, fw_hdr->size,
-				 sizeof(struct wl_fw_hdr));
-			rc = -EBADF;
-		} else if (fw->size < MIN_FW_SIZE || fw->size > MAX_FW_SIZE) {
-			WL_ERROR("%s: out of bounds fw file size %d\n",
-				 __func__, fw->size);
-			rc = -EBADF;
-		} else {
-			/* check if ucode section overruns firmware image */
-			ucode_hdr = (struct wl_fw_hdr *)fw_hdr->data;
-			for (entry = 0; entry < wl->fw.hdr_num_entries[i] && rc;
-			     entry++, ucode_hdr++) {
-				if (ucode_hdr->offset + ucode_hdr->len >
-				    fw->size) {
-					WL_ERROR("%s: conflicting bin/hdr\n",
-						 __func__);
-					rc = -EBADF;
-				}
-			}
-		}
-	}
-	if (rc == 0 && wl->fw.fw_cnt != i) {
-		WL_ERROR("%s: invalid fw_cnt=%d\n", __func__, wl->fw.fw_cnt);
-		rc = -EBADF;
-	}
-	return rc;
-}
-
diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.h b/drivers/staging/brcm80211/sys/wl_mac80211.h
deleted file mode 100644
index bb39b77..0000000
--- a/drivers/staging/brcm80211/sys/wl_mac80211.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wl_mac80211_h_
-#define _wl_mac80211_h_
-
-#include <wlc_types.h>
-
-/* BMAC Note: High-only driver is no longer working in softirq context as it needs to block and
- * sleep so perimeter lock has to be a semaphore instead of spinlock. This requires timers to be
- * submitted to workqueue instead of being on kernel timer
- */
-typedef struct wl_timer {
-	struct timer_list timer;
-	struct wl_info *wl;
-	void (*fn) (void *);
-	void *arg;		/* argument to fn */
-	uint ms;
-	bool periodic;
-	bool set;
-	struct wl_timer *next;
-#ifdef BCMDBG
-	char *name;		/* Description of the timer */
-#endif
-} wl_timer_t;
-
-/* contortion to call functions at safe time */
-/* In 2.6.20 kernels work functions get passed a pointer to the struct work, so things
- * will continue to work as long as the work structure is the first component of the task structure.
- */
-typedef struct wl_task {
-	struct work_struct work;
-	void *context;
-} wl_task_t;
-
-struct wl_if {
-	uint subunit;		/* WDS/BSS unit */
-	struct pci_dev *pci_dev;
-};
-
-#define WL_MAX_FW		4
-struct wl_firmware {
-	u32 fw_cnt;
-	const struct firmware *fw_bin[WL_MAX_FW];
-	const struct firmware *fw_hdr[WL_MAX_FW];
-	u32 hdr_num_entries[WL_MAX_FW];
-};
-
-struct wl_info {
-	struct wlc_pub *pub;		/* pointer to public wlc state */
-	void *wlc;		/* pointer to private common os-independent data */
-	struct osl_info *osh;		/* pointer to os handler */
-	u32 magic;
-
-	int irq;
-
-	spinlock_t lock;	/* per-device perimeter lock */
-	spinlock_t isr_lock;	/* per-device ISR synchronization lock */
-	uint bcm_bustype;	/* bus type */
-	bool piomode;		/* set from insmod argument */
-	void *regsva;		/* opaque chip registers virtual address */
-	atomic_t callbacks;	/* # outstanding callback functions */
-	struct wl_timer *timers;	/* timer cleanup queue */
-	struct tasklet_struct tasklet;	/* dpc tasklet */
-	bool resched;		/* dpc needs to be and is rescheduled */
-#ifdef LINUXSTA_PS
-	u32 pci_psstate[16];	/* pci ps-state save/restore */
-#endif
-	/* RPC, handle, lock, txq, workitem */
-	uint stats_id;		/* the current set of stats */
-	/* ping-pong stats counters updated by Linux watchdog */
-	struct net_device_stats stats_watchdog[2];
-	struct wl_firmware fw;
-};
-
-#define WL_LOCK(wl)	spin_lock_bh(&(wl)->lock)
-#define WL_UNLOCK(wl)	spin_unlock_bh(&(wl)->lock)
-
-/* locking from inside wl_isr */
-#define WL_ISRLOCK(wl, flags) do {spin_lock(&(wl)->isr_lock); (void)(flags); } while (0)
-#define WL_ISRUNLOCK(wl, flags) do {spin_unlock(&(wl)->isr_lock); (void)(flags); } while (0)
-
-/* locking under WL_LOCK() to synchronize with wl_isr */
-#define INT_LOCK(wl, flags)	spin_lock_irqsave(&(wl)->isr_lock, flags)
-#define INT_UNLOCK(wl, flags)	spin_unlock_irqrestore(&(wl)->isr_lock, flags)
-
-#ifndef PCI_D0
-#define PCI_D0		0
-#endif
-
-#ifndef PCI_D3hot
-#define PCI_D3hot	3
-#endif
-
-/* exported functions */
-
-extern irqreturn_t wl_isr(int irq, void *dev_id);
-
-extern int __devinit wl_pci_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent);
-extern void wl_free(struct wl_info *wl);
-extern int wl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-
-#endif				/* _wl_mac80211_h_ */
diff --git a/drivers/staging/brcm80211/sys/wl_ucode.h b/drivers/staging/brcm80211/sys/wl_ucode.h
deleted file mode 100644
index 2a0f402..0000000
--- a/drivers/staging/brcm80211/sys/wl_ucode.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define MIN_FW_SIZE 40000	/* minimum firmware file size in bytes */
-#define MAX_FW_SIZE 150000
-
-typedef struct d11init {
-	u16 addr;
-	u16 size;
-	u32 value;
-} d11init_t;
-
-extern d11init_t *d11lcn0bsinitvals24;
-extern d11init_t *d11lcn0initvals24;
-extern d11init_t *d11lcn1bsinitvals24;
-extern d11init_t *d11lcn1initvals24;
-extern d11init_t *d11lcn2bsinitvals24;
-extern d11init_t *d11lcn2initvals24;
-extern d11init_t *d11n0absinitvals16;
-extern d11init_t *d11n0bsinitvals16;
-extern d11init_t *d11n0initvals16;
-extern u32 *bcm43xx_16_mimo;
-extern u32 bcm43xx_16_mimosz;
-extern u32 *bcm43xx_24_lcn;
-extern u32 bcm43xx_24_lcnsz;
-extern u32 *bcm43xx_bommajor;
-extern u32 *bcm43xx_bomminor;
-
-extern int wl_ucode_data_init(struct wl_info *wl);
-extern void wl_ucode_data_free(void);
-
-extern int wl_ucode_init_buf(struct wl_info *wl, void **pbuf, unsigned int idx);
-extern int wl_ucode_init_uint(struct wl_info *wl, unsigned *data,
-			      unsigned int idx);
-extern void wl_ucode_free_buf(void *);
-extern int  wl_check_firmwares(struct wl_info *wl);
diff --git a/drivers/staging/brcm80211/sys/wl_ucode_loader.c b/drivers/staging/brcm80211/sys/wl_ucode_loader.c
deleted file mode 100644
index 23e10f3..0000000
--- a/drivers/staging/brcm80211/sys/wl_ucode_loader.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/types.h>
-#include <bcmdefs.h>
-#include <d11ucode_ext.h>
-#include <wl_ucode.h>
-
-
-
-d11init_t *d11lcn0bsinitvals24;
-d11init_t *d11lcn0initvals24;
-d11init_t *d11lcn1bsinitvals24;
-d11init_t *d11lcn1initvals24;
-d11init_t *d11lcn2bsinitvals24;
-d11init_t *d11lcn2initvals24;
-d11init_t *d11n0absinitvals16;
-d11init_t *d11n0bsinitvals16;
-d11init_t *d11n0initvals16;
-u32 *bcm43xx_16_mimo;
-u32 bcm43xx_16_mimosz;
-u32 *bcm43xx_24_lcn;
-u32 bcm43xx_24_lcnsz;
-u32 *bcm43xx_bommajor;
-u32 *bcm43xx_bomminor;
-
-int wl_ucode_data_init(struct wl_info *wl)
-{
-	int rc;
-	rc = wl_check_firmwares(wl);
-	if (rc < 0)
-		return rc;
-	wl_ucode_init_buf(wl, (void **)&d11lcn0bsinitvals24,
-			  D11LCN0BSINITVALS24);
-	wl_ucode_init_buf(wl, (void **)&d11lcn0initvals24, D11LCN0INITVALS24);
-	wl_ucode_init_buf(wl, (void **)&d11lcn1bsinitvals24,
-			  D11LCN1BSINITVALS24);
-	wl_ucode_init_buf(wl, (void **)&d11lcn1initvals24, D11LCN1INITVALS24);
-	wl_ucode_init_buf(wl, (void **)&d11lcn2bsinitvals24,
-			  D11LCN2BSINITVALS24);
-	wl_ucode_init_buf(wl, (void **)&d11lcn2initvals24, D11LCN2INITVALS24);
-	wl_ucode_init_buf(wl, (void **)&d11n0absinitvals16, D11N0ABSINITVALS16);
-	wl_ucode_init_buf(wl, (void **)&d11n0bsinitvals16, D11N0BSINITVALS16);
-	wl_ucode_init_buf(wl, (void **)&d11n0initvals16, D11N0INITVALS16);
-	wl_ucode_init_buf(wl, (void **)&bcm43xx_16_mimo,
-			  D11UCODE_OVERSIGHT16_MIMO);
-	wl_ucode_init_uint(wl, &bcm43xx_16_mimosz, D11UCODE_OVERSIGHT16_MIMOSZ);
-	wl_ucode_init_buf(wl, (void **)&bcm43xx_24_lcn,
-			  D11UCODE_OVERSIGHT24_LCN);
-	wl_ucode_init_uint(wl, &bcm43xx_24_lcnsz, D11UCODE_OVERSIGHT24_LCNSZ);
-	wl_ucode_init_buf(wl, (void **)&bcm43xx_bommajor,
-			  D11UCODE_OVERSIGHT_BOMMAJOR);
-	wl_ucode_init_buf(wl, (void **)&bcm43xx_bomminor,
-			  D11UCODE_OVERSIGHT_BOMMINOR);
-
-	return 0;
-}
-
-void wl_ucode_data_free(void)
-{
-	wl_ucode_free_buf((void *)d11lcn0bsinitvals24);
-	wl_ucode_free_buf((void *)d11lcn0initvals24);
-	wl_ucode_free_buf((void *)d11lcn1bsinitvals24);
-	wl_ucode_free_buf((void *)d11lcn1initvals24);
-	wl_ucode_free_buf((void *)d11lcn2bsinitvals24);
-	wl_ucode_free_buf((void *)d11lcn2initvals24);
-	wl_ucode_free_buf((void *)d11n0absinitvals16);
-	wl_ucode_free_buf((void *)d11n0bsinitvals16);
-	wl_ucode_free_buf((void *)d11n0initvals16);
-	wl_ucode_free_buf((void *)bcm43xx_16_mimo);
-	wl_ucode_free_buf((void *)bcm43xx_24_lcn);
-	wl_ucode_free_buf((void *)bcm43xx_bommajor);
-	wl_ucode_free_buf((void *)bcm43xx_bomminor);
-
-	return;
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_alloc.c b/drivers/staging/brcm80211/sys/wlc_alloc.c
deleted file mode 100644
index 746439e..0000000
--- a/drivers/staging/brcm80211/sys/wlc_alloc.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <wlc_cfg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <wlioctl.h>
-#include <wlc_pub.h>
-#include <wlc_key.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_alloc.h>
-#include <wl_dbg.h>
-
-static struct wlc_pub *wlc_pub_malloc(struct osl_info *osh, uint unit,
-				      uint *err, uint devid);
-static void wlc_pub_mfree(struct osl_info *osh, struct wlc_pub *pub);
-static void wlc_tunables_init(wlc_tunables_t *tunables, uint devid);
-
-void *wlc_calloc(struct osl_info *osh, uint unit, uint size)
-{
-	void *item;
-
-	item = kzalloc(size, GFP_ATOMIC);
-	if (item == NULL)
-		WL_ERROR("wl%d: %s: out of memory\n", unit, __func__);
-	return item;
-}
-
-void wlc_tunables_init(wlc_tunables_t *tunables, uint devid)
-{
-	tunables->ntxd = NTXD;
-	tunables->nrxd = NRXD;
-	tunables->rxbufsz = RXBUFSZ;
-	tunables->nrxbufpost = NRXBUFPOST;
-	tunables->maxscb = MAXSCB;
-	tunables->ampdunummpdu = AMPDU_NUM_MPDU;
-	tunables->maxpktcb = MAXPKTCB;
-	tunables->maxucodebss = WLC_MAX_UCODE_BSS;
-	tunables->maxucodebss4 = WLC_MAX_UCODE_BSS4;
-	tunables->maxbss = MAXBSS;
-	tunables->datahiwat = WLC_DATAHIWAT;
-	tunables->ampdudatahiwat = WLC_AMPDUDATAHIWAT;
-	tunables->rxbnd = RXBND;
-	tunables->txsbnd = TXSBND;
-}
-
-static struct wlc_pub *wlc_pub_malloc(struct osl_info *osh, uint unit,
-				      uint *err, uint devid)
-{
-	struct wlc_pub *pub;
-
-	pub = (struct wlc_pub *) wlc_calloc(osh, unit, sizeof(struct wlc_pub));
-	if (pub == NULL) {
-		*err = 1001;
-		goto fail;
-	}
-
-	pub->tunables = (wlc_tunables_t *)wlc_calloc(osh, unit,
-		sizeof(wlc_tunables_t));
-	if (pub->tunables == NULL) {
-		*err = 1028;
-		goto fail;
-	}
-
-	/* need to init the tunables now */
-	wlc_tunables_init(pub->tunables, devid);
-
-	pub->multicast = (struct ether_addr *)wlc_calloc(osh, unit,
-		(sizeof(struct ether_addr) * MAXMULTILIST));
-	if (pub->multicast == NULL) {
-		*err = 1003;
-		goto fail;
-	}
-
-	return pub;
-
- fail:
-	wlc_pub_mfree(osh, pub);
-	return NULL;
-}
-
-static void wlc_pub_mfree(struct osl_info *osh, struct wlc_pub *pub)
-{
-	if (pub == NULL)
-		return;
-
-	if (pub->multicast)
-		kfree(pub->multicast);
-	if (pub->tunables) {
-		kfree(pub->tunables);
-		pub->tunables = NULL;
-	}
-
-	kfree(pub);
-}
-
-wlc_bsscfg_t *wlc_bsscfg_malloc(struct osl_info *osh, uint unit)
-{
-	wlc_bsscfg_t *cfg;
-
-	cfg = (wlc_bsscfg_t *) wlc_calloc(osh, unit, sizeof(wlc_bsscfg_t));
-	if (cfg == NULL)
-		goto fail;
-
-	cfg->current_bss = (wlc_bss_info_t *)wlc_calloc(osh, unit,
-		sizeof(wlc_bss_info_t));
-	if (cfg->current_bss == NULL)
-		goto fail;
-
-	return cfg;
-
- fail:
-	wlc_bsscfg_mfree(osh, cfg);
-	return NULL;
-}
-
-void wlc_bsscfg_mfree(struct osl_info *osh, wlc_bsscfg_t *cfg)
-{
-	if (cfg == NULL)
-		return;
-
-	if (cfg->maclist) {
-		kfree(cfg->maclist);
-		cfg->maclist = NULL;
-	}
-
-	if (cfg->current_bss != NULL) {
-		wlc_bss_info_t *current_bss = cfg->current_bss;
-		if (current_bss->bcn_prb != NULL)
-			kfree(current_bss->bcn_prb);
-		kfree(current_bss);
-		cfg->current_bss = NULL;
-	}
-
-	kfree(cfg);
-}
-
-void wlc_bsscfg_ID_assign(struct wlc_info *wlc, wlc_bsscfg_t *bsscfg)
-{
-	bsscfg->ID = wlc->next_bsscfg_ID;
-	wlc->next_bsscfg_ID++;
-}
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-struct wlc_info *wlc_attach_malloc(struct osl_info *osh, uint unit, uint *err,
-			      uint devid)
-{
-	struct wlc_info *wlc;
-
-	wlc = (struct wlc_info *) wlc_calloc(osh, unit,
-					     sizeof(struct wlc_info));
-	if (wlc == NULL) {
-		*err = 1002;
-		goto fail;
-	}
-
-	wlc->hwrxoff = WL_HWRXOFF;
-
-	/* allocate struct wlc_pub state structure */
-	wlc->pub = wlc_pub_malloc(osh, unit, err, devid);
-	if (wlc->pub == NULL) {
-		*err = 1003;
-		goto fail;
-	}
-	wlc->pub->wlc = wlc;
-
-	/* allocate struct wlc_hw_info state structure */
-
-	wlc->hw = (struct wlc_hw_info *)wlc_calloc(osh, unit,
-		sizeof(struct wlc_hw_info));
-	if (wlc->hw == NULL) {
-		*err = 1005;
-		goto fail;
-	}
-	wlc->hw->wlc = wlc;
-
-	wlc->hw->bandstate[0] = (wlc_hwband_t *)wlc_calloc(osh, unit,
-		(sizeof(wlc_hwband_t) * MAXBANDS));
-	if (wlc->hw->bandstate[0] == NULL) {
-		*err = 1006;
-		goto fail;
-	} else {
-		int i;
-
-		for (i = 1; i < MAXBANDS; i++) {
-			wlc->hw->bandstate[i] = (wlc_hwband_t *)
-			    ((unsigned long)wlc->hw->bandstate[0] +
-			     (sizeof(wlc_hwband_t) * i));
-		}
-	}
-
-	wlc->modulecb = (modulecb_t *)wlc_calloc(osh, unit,
-		sizeof(modulecb_t) * WLC_MAXMODULES);
-	if (wlc->modulecb == NULL) {
-		*err = 1009;
-		goto fail;
-	}
-
-	wlc->default_bss = (wlc_bss_info_t *)wlc_calloc(osh, unit,
-		sizeof(wlc_bss_info_t));
-	if (wlc->default_bss == NULL) {
-		*err = 1010;
-		goto fail;
-	}
-
-	wlc->cfg = wlc_bsscfg_malloc(osh, unit);
-	if (wlc->cfg == NULL) {
-		*err = 1011;
-		goto fail;
-	}
-	wlc_bsscfg_ID_assign(wlc, wlc->cfg);
-
-	wlc->pkt_callback = (pkt_cb_t *)wlc_calloc(osh, unit,
-		(sizeof(pkt_cb_t) * (wlc->pub->tunables->maxpktcb + 1)));
-	if (wlc->pkt_callback == NULL) {
-		*err = 1013;
-		goto fail;
-	}
-
-	wlc->wsec_def_keys[0] = (wsec_key_t *)wlc_calloc(osh, unit,
-		(sizeof(wsec_key_t) * WLC_DEFAULT_KEYS));
-	if (wlc->wsec_def_keys[0] == NULL) {
-		*err = 1015;
-		goto fail;
-	} else {
-		int i;
-		for (i = 1; i < WLC_DEFAULT_KEYS; i++) {
-			wlc->wsec_def_keys[i] = (wsec_key_t *)
-			    ((unsigned long)wlc->wsec_def_keys[0] +
-			     (sizeof(wsec_key_t) * i));
-		}
-	}
-
-	wlc->protection = (wlc_protection_t *)wlc_calloc(osh, unit,
-		sizeof(wlc_protection_t));
-	if (wlc->protection == NULL) {
-		*err = 1016;
-		goto fail;
-	}
-
-	wlc->stf = (wlc_stf_t *)wlc_calloc(osh, unit, sizeof(wlc_stf_t));
-	if (wlc->stf == NULL) {
-		*err = 1017;
-		goto fail;
-	}
-
-	wlc->bandstate[0] = (struct wlcband *)wlc_calloc(osh, unit,
-				(sizeof(struct wlcband)*MAXBANDS));
-	if (wlc->bandstate[0] == NULL) {
-		*err = 1025;
-		goto fail;
-	} else {
-		int i;
-
-		for (i = 1; i < MAXBANDS; i++) {
-			wlc->bandstate[i] =
-			    (struct wlcband *) ((unsigned long)wlc->bandstate[0]
-			    + (sizeof(struct wlcband)*i));
-		}
-	}
-
-	wlc->corestate = (struct wlccore *)wlc_calloc(osh, unit,
-						      sizeof(struct wlccore));
-	if (wlc->corestate == NULL) {
-		*err = 1026;
-		goto fail;
-	}
-
-	wlc->corestate->macstat_snapshot =
-		(macstat_t *)wlc_calloc(osh, unit, sizeof(macstat_t));
-	if (wlc->corestate->macstat_snapshot == NULL) {
-		*err = 1027;
-		goto fail;
-	}
-
-	return wlc;
-
- fail:
-	wlc_detach_mfree(wlc, osh);
-	return NULL;
-}
-
-void wlc_detach_mfree(struct wlc_info *wlc, struct osl_info *osh)
-{
-	if (wlc == NULL)
-		return;
-
-	if (wlc->modulecb) {
-		kfree(wlc->modulecb);
-		wlc->modulecb = NULL;
-	}
-
-	if (wlc->default_bss) {
-		kfree(wlc->default_bss);
-		wlc->default_bss = NULL;
-	}
-	if (wlc->cfg) {
-		wlc_bsscfg_mfree(osh, wlc->cfg);
-		wlc->cfg = NULL;
-	}
-
-	if (wlc->pkt_callback && wlc->pub && wlc->pub->tunables) {
-		kfree(wlc->pkt_callback);
-		wlc->pkt_callback = NULL;
-	}
-
-	if (wlc->wsec_def_keys[0])
-		kfree(wlc->wsec_def_keys[0]);
-	if (wlc->protection) {
-		kfree(wlc->protection);
-		wlc->protection = NULL;
-	}
-
-	if (wlc->stf) {
-		kfree(wlc->stf);
-		wlc->stf = NULL;
-	}
-
-	if (wlc->bandstate[0])
-		kfree(wlc->bandstate[0]);
-
-	if (wlc->corestate) {
-		if (wlc->corestate->macstat_snapshot) {
-	kfree(wlc->corestate->macstat_snapshot);			wlc->corestate->macstat_snapshot = NULL;
-		}
-		kfree(wlc->corestate);
-		wlc->corestate = NULL;
-	}
-
-	if (wlc->pub) {
-		/* free pub struct */
-		wlc_pub_mfree(osh, wlc->pub);
-		wlc->pub = NULL;
-	}
-
-	if (wlc->hw) {
-		if (wlc->hw->bandstate[0]) {
-			kfree(wlc->hw->bandstate[0]);
-			wlc->hw->bandstate[0] = NULL;
-		}
-
-		/* free hw struct */
-		kfree(wlc->hw);
-		wlc->hw = NULL;
-	}
-
-	/* free the wlc */
-	kfree(wlc);
-	wlc = NULL;
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_alloc.h b/drivers/staging/brcm80211/sys/wlc_alloc.h
deleted file mode 100644
index ac34f78..0000000
--- a/drivers/staging/brcm80211/sys/wlc_alloc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-extern void *wlc_calloc(struct osl_info *osh, uint unit, uint size);
-
-extern struct wlc_info *wlc_attach_malloc(struct osl_info *osh, uint unit,
-					  uint *err, uint devid);
-extern void wlc_detach_mfree(struct wlc_info *wlc, struct osl_info *osh);
-
-struct wlc_bsscfg;
-extern struct wlc_bsscfg *wlc_bsscfg_malloc(struct osl_info *osh, uint unit);
-extern void wlc_bsscfg_mfree(struct osl_info *osh, struct wlc_bsscfg *cfg);
diff --git a/drivers/staging/brcm80211/sys/wlc_ampdu.c b/drivers/staging/brcm80211/sys/wlc_ampdu.c
deleted file mode 100644
index d749917..0000000
--- a/drivers/staging/brcm80211/sys/wlc_ampdu.c
+++ /dev/null
@@ -1,1355 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <wlc_cfg.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmendian.h>
-#include <wlioctl.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_pub.h>
-#include <wlc_key.h>
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_phy_hal.h>
-#include <wlc_antsel.h>
-#include <wlc_scb.h>
-#include <net/mac80211.h>
-#include <wlc_ampdu.h>
-#include <wl_export.h>
-#include <wl_dbg.h>
-
-
-#define AMPDU_MAX_MPDU		32	/* max number of mpdus in an ampdu */
-#define AMPDU_NUM_MPDU_LEGACY	16	/* max number of mpdus in an ampdu to a legacy */
-#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
-#define AMPDU_TX_BA_DEF_WSIZE	64	/* default Tx ba window size (in pdu) */
-#define AMPDU_RX_BA_DEF_WSIZE   64	/* max Rx ba window size (in pdu) */
-#define AMPDU_RX_BA_MAX_WSIZE   64	/* default Rx ba window size (in pdu) */
-#define	AMPDU_MAX_DUR		5	/* max dur of tx ampdu (in msec) */
-#define AMPDU_DEF_RETRY_LIMIT	5	/* default tx retry limit */
-#define AMPDU_DEF_RR_RETRY_LIMIT	2	/* default tx retry limit at reg rate */
-#define AMPDU_DEF_TXPKT_WEIGHT	2	/* default weight of ampdu in txfifo */
-#define AMPDU_DEF_FFPLD_RSVD	2048	/* default ffpld reserved bytes */
-#define AMPDU_INI_FREE		10	/* # of inis to be freed on detach */
-#define	AMPDU_SCB_MAX_RELEASE	20	/* max # of mpdus released at a time */
-
-#define NUM_FFPLD_FIFO 4	/* number of fifo concerned by pre-loading */
-#define FFPLD_TX_MAX_UNFL   200	/* default value of the average number of ampdu
-				 * without underflows
-				 */
-#define FFPLD_MPDU_SIZE 1800	/* estimate of maximum mpdu size */
-#define FFPLD_MAX_MCS 23	/* we don't deal with mcs 32 */
-#define FFPLD_PLD_INCR 1000	/* increments in bytes */
-#define FFPLD_MAX_AMPDU_CNT 5000	/* maximum number of ampdu we
-					 * accumulate between resets.
-					 */
-
-#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
-
-/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
-#define AMPDU_MAX_MPDU_OVERHEAD (DOT11_FCS_LEN + DOT11_ICV_AES_LEN + AMPDU_DELIMITER_LEN + 3 \
-	+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
-
-#ifdef BCMDBG
-u32 wl_ampdu_dbg =
-    WL_AMPDU_UPDN_VAL |
-    WL_AMPDU_ERR_VAL |
-    WL_AMPDU_TX_VAL |
-    WL_AMPDU_RX_VAL |
-    WL_AMPDU_CTL_VAL |
-    WL_AMPDU_HW_VAL | WL_AMPDU_HWTXS_VAL | WL_AMPDU_HWDBG_VAL;
-#endif
-
-/* structure to hold tx fifo information and pre-loading state
- * counters specific to tx underflows of ampdus
- * some counters might be redundant with the ones in wlc or ampdu structures.
- * This allows to maintain a specific state independantly of
- * how often and/or when the wlc counters are updated.
- */
-typedef struct wlc_fifo_info {
-	u16 ampdu_pld_size;	/* number of bytes to be pre-loaded */
-	u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];	/* per-mcs max # of mpdus in an ampdu */
-	u16 prev_txfunfl;	/* num of underflows last read from the HW macstats counter */
-	u32 accum_txfunfl;	/* num of underflows since we modified pld params */
-	u32 accum_txampdu;	/* num of tx ampdu since we modified pld params  */
-	u32 prev_txampdu;	/* previous reading of tx ampdu */
-	u32 dmaxferrate;	/* estimated dma avg xfer rate in kbits/sec */
-} wlc_fifo_info_t;
-
-/* AMPDU module specific state */
-struct ampdu_info {
-	struct wlc_info *wlc;	/* pointer to main wlc structure */
-	int scb_handle;		/* scb cubby handle to retrieve data from scb */
-	u8 ini_enable[AMPDU_MAX_SCB_TID];	/* per-tid initiator enable/disable of ampdu */
-	u8 ba_tx_wsize;	/* Tx ba window size (in pdu) */
-	u8 ba_rx_wsize;	/* Rx ba window size (in pdu) */
-	u8 retry_limit;	/* mpdu transmit retry limit */
-	u8 rr_retry_limit;	/* mpdu transmit retry limit at regular rate */
-	u8 retry_limit_tid[AMPDU_MAX_SCB_TID];	/* per-tid mpdu transmit retry limit */
-	/* per-tid mpdu transmit retry limit at regular rate */
-	u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
-	u8 mpdu_density;	/* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
-	s8 max_pdu;		/* max pdus allowed in ampdu */
-	u8 dur;		/* max duration of an ampdu (in msec) */
-	u8 txpkt_weight;	/* weight of ampdu in txfifo; reduces rate lag */
-	u8 rx_factor;	/* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
-	u32 ffpld_rsvd;	/* number of bytes to reserve for preload */
-	u32 max_txlen[MCS_TABLE_SIZE][2][2];	/* max size of ampdu per mcs, bw and sgi */
-	void *ini_free[AMPDU_INI_FREE];	/* array of ini's to be freed on detach */
-	bool mfbr;		/* enable multiple fallback rate */
-	u32 tx_max_funl;	/* underflows should be kept such that
-				 * (tx_max_funfl*underflows) < tx frames
-				 */
-	wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO];	/* table of fifo infos  */
-
-};
-
-#define AMPDU_CLEANUPFLAG_RX   (0x1)
-#define AMPDU_CLEANUPFLAG_TX   (0x2)
-
-#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
-#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
-
-static void wlc_ffpld_init(struct ampdu_info *ampdu);
-static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
-static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
-
-static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
-						   scb_ampdu_t *scb_ampdu,
-						   u8 tid, bool override);
-static void ampdu_cleanup_tid_ini(struct ampdu_info *ampdu,
-				  scb_ampdu_t *scb_ampdu,
-				  u8 tid, bool force);
-static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
-static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
-static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
-
-#define wlc_ampdu_txflowcontrol(a, b, c)	do {} while (0)
-
-static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
-					  struct scb *scb,
-					  struct sk_buff *p, tx_status_t *txs,
-					  u32 frmtxstatus, u32 frmtxstatus2);
-
-static inline u16 pkt_txh_seqnum(struct wlc_info *wlc, struct sk_buff *p)
-{
-	d11txh_t *txh;
-	struct dot11_header *h;
-	txh = (d11txh_t *) p->data;
-	h = (struct dot11_header *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-	return ltoh16(h->seq) >> SEQNUM_SHIFT;
-}
-
-struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
-{
-	struct ampdu_info *ampdu;
-	int i;
-
-	/* some code depends on packed structures */
-	ASSERT(DOT11_MAXNUMFRAGS == NBITS(u16));
-	ASSERT(ISPOWEROF2(AMPDU_TX_BA_MAX_WSIZE));
-	ASSERT(ISPOWEROF2(AMPDU_RX_BA_MAX_WSIZE));
-	ASSERT(wlc->pub->tunables->ampdunummpdu <= AMPDU_MAX_MPDU);
-	ASSERT(wlc->pub->tunables->ampdunummpdu > 0);
-
-	ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
-	if (!ampdu) {
-		WL_ERROR("wl%d: wlc_ampdu_attach: out of mem\n",
-			 wlc->pub->unit);
-		return NULL;
-	}
-	ampdu->wlc = wlc;
-
-	for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
-		ampdu->ini_enable[i] = true;
-	/* Disable ampdu for VO by default */
-	ampdu->ini_enable[PRIO_8021D_VO] = false;
-	ampdu->ini_enable[PRIO_8021D_NC] = false;
-
-	/* Disable ampdu for BK by default since not enough fifo space */
-	ampdu->ini_enable[PRIO_8021D_NONE] = false;
-	ampdu->ini_enable[PRIO_8021D_BK] = false;
-
-	ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
-	ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
-	ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
-	ampdu->max_pdu = AUTO;
-	ampdu->dur = AMPDU_MAX_DUR;
-	ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
-
-	ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
-	/* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
-	if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
-		ampdu->rx_factor = AMPDU_RX_FACTOR_32K;
-	else
-		ampdu->rx_factor = AMPDU_RX_FACTOR_64K;
-	ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
-	ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
-
-	for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
-		ampdu->retry_limit_tid[i] = ampdu->retry_limit;
-		ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
-	}
-
-	ampdu_update_max_txlen(ampdu, ampdu->dur);
-	ampdu->mfbr = false;
-	/* try to set ampdu to the default value */
-	wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
-
-	ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
-	wlc_ffpld_init(ampdu);
-
-	return ampdu;
-}
-
-void wlc_ampdu_detach(struct ampdu_info *ampdu)
-{
-	int i;
-
-	if (!ampdu)
-		return;
-
-	/* free all ini's which were to be freed on callbacks which were never called */
-	for (i = 0; i < AMPDU_INI_FREE; i++) {
-		if (ampdu->ini_free[i]) {
-			kfree(ampdu->ini_free[i]);
-		}
-	}
-
-	wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
-	kfree(ampdu);
-}
-
-void scb_ampdu_cleanup(struct ampdu_info *ampdu, struct scb *scb)
-{
-	scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	u8 tid;
-
-	WL_AMPDU_UPDN("scb_ampdu_cleanup: enter\n");
-	ASSERT(scb_ampdu);
-
-	for (tid = 0; tid < AMPDU_MAX_SCB_TID; tid++) {
-		ampdu_cleanup_tid_ini(ampdu, scb_ampdu, tid, false);
-	}
-}
-
-/* reset the ampdu state machine so that it can gracefully handle packets that were
- * freed from the dma and tx queues during reinit
- */
-void wlc_ampdu_reset(struct ampdu_info *ampdu)
-{
-	WL_NONE("%s: Entering\n", __func__);
-}
-
-static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
-{
-	scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	int i;
-
-	scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
-
-	/* go back to legacy size if some preloading is occuring */
-	for (i = 0; i < NUM_FFPLD_FIFO; i++) {
-		if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
-			scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
-	}
-
-	/* apply user override */
-	if (ampdu->max_pdu != AUTO)
-		scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
-
-	scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
-
-	if (scb_ampdu->max_rxlen)
-		scb_ampdu->release =
-		    min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
-
-	scb_ampdu->release = min(scb_ampdu->release,
-				 ampdu->fifo_tb[TX_AC_BE_FIFO].
-				 mcs2ampdu_table[FFPLD_MAX_MCS]);
-
-	ASSERT(scb_ampdu->release);
-}
-
-void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
-{
-	scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
-}
-
-static void wlc_ffpld_init(struct ampdu_info *ampdu)
-{
-	int i, j;
-	wlc_fifo_info_t *fifo;
-
-	for (j = 0; j < NUM_FFPLD_FIFO; j++) {
-		fifo = (ampdu->fifo_tb + j);
-		fifo->ampdu_pld_size = 0;
-		for (i = 0; i <= FFPLD_MAX_MCS; i++)
-			fifo->mcs2ampdu_table[i] = 255;
-		fifo->dmaxferrate = 0;
-		fifo->accum_txampdu = 0;
-		fifo->prev_txfunfl = 0;
-		fifo->accum_txfunfl = 0;
-
-	}
-}
-
-/* evaluate the dma transfer rate using the tx underflows as feedback.
- * If necessary, increase tx fifo preloading. If not enough,
- * decrease maximum ampdu size for each mcs till underflows stop
- * Return 1 if pre-loading not active, -1 if not an underflow event,
- * 0 if pre-loading module took care of the event.
- */
-static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
-{
-	struct ampdu_info *ampdu = wlc->ampdu;
-	u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
-	u32 txunfl_ratio;
-	u8 max_mpdu;
-	u32 current_ampdu_cnt = 0;
-	u16 max_pld_size;
-	u32 new_txunfl;
-	wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
-	uint xmtfifo_sz;
-	u16 cur_txunfl;
-
-	/* return if we got here for a different reason than underflows */
-	cur_txunfl =
-	    wlc_read_shm(wlc,
-			 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
-	new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
-	if (new_txunfl == 0) {
-		WL_FFPLD("check_txunfl : TX status FRAG set but no tx underflows\n");
-		return -1;
-	}
-	fifo->prev_txfunfl = cur_txunfl;
-
-	if (!ampdu->tx_max_funl)
-		return 1;
-
-	/* check if fifo is big enough */
-	if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
-		WL_FFPLD("check_txunfl : get xmtfifo_sz failed\n");
-		return -1;
-	}
-
-	if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
-		return 1;
-
-	max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
-	fifo->accum_txfunfl += new_txunfl;
-
-	/* we need to wait for at least 10 underflows */
-	if (fifo->accum_txfunfl < 10)
-		return 0;
-
-	WL_FFPLD("ampdu_count %d  tx_underflows %d\n",
-		 current_ampdu_cnt, fifo->accum_txfunfl);
-
-	/*
-	   compute the current ratio of tx unfl per ampdu.
-	   When the current ampdu count becomes too
-	   big while the ratio remains small, we reset
-	   the current count in order to not
-	   introduce too big of a latency in detecting a
-	   large amount of tx underflows later.
-	 */
-
-	txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
-
-	if (txunfl_ratio > ampdu->tx_max_funl) {
-		if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
-			fifo->accum_txfunfl = 0;
-		}
-		return 0;
-	}
-	max_mpdu =
-	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
-
-	/* In case max value max_pdu is already lower than
-	   the fifo depth, there is nothing more we can do.
-	 */
-
-	if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
-		WL_FFPLD(("tx fifo pld : max ampdu fits in fifo\n)"));
-		fifo->accum_txfunfl = 0;
-		return 0;
-	}
-
-	if (fifo->ampdu_pld_size < max_pld_size) {
-
-		/* increment by TX_FIFO_PLD_INC bytes */
-		fifo->ampdu_pld_size += FFPLD_PLD_INCR;
-		if (fifo->ampdu_pld_size > max_pld_size)
-			fifo->ampdu_pld_size = max_pld_size;
-
-		/* update scb release size */
-		scb_ampdu_update_config_all(ampdu);
-
-		/*
-		   compute a new dma xfer rate for max_mpdu @ max mcs.
-		   This is the minimum dma rate that
-		   can acheive no unferflow condition for the current mpdu size.
-		 */
-		/* note : we divide/multiply by 100 to avoid integer overflows */
-		fifo->dmaxferrate =
-		    (((phy_rate / 100) *
-		      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
-		     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
-
-		WL_FFPLD("DMA estimated transfer rate %d; pre-load size %d\n",
-			 fifo->dmaxferrate, fifo->ampdu_pld_size);
-	} else {
-
-		/* decrease ampdu size */
-		if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
-			if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
-				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
-				    AMPDU_NUM_MPDU_LEGACY - 1;
-			else
-				fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
-
-			/* recompute the table */
-			wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
-
-			/* update scb release size */
-			scb_ampdu_update_config_all(ampdu);
-		}
-	}
-	fifo->accum_txfunfl = 0;
-	return 0;
-}
-
-static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
-{
-	int i;
-	u32 phy_rate, dma_rate, tmp;
-	u8 max_mpdu;
-	wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
-
-	/* recompute the dma rate */
-	/* note : we divide/multiply by 100 to avoid integer overflows */
-	max_mpdu =
-	    min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
-	phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
-	dma_rate =
-	    (((phy_rate / 100) *
-	      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
-	     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
-	fifo->dmaxferrate = dma_rate;
-
-	/* fill up the mcs2ampdu table; do not recalc the last mcs */
-	dma_rate = dma_rate >> 7;
-	for (i = 0; i < FFPLD_MAX_MCS; i++) {
-		/* shifting to keep it within integer range */
-		phy_rate = MCS_RATE(i, true, false) >> 7;
-		if (phy_rate > dma_rate) {
-			tmp = ((fifo->ampdu_pld_size * phy_rate) /
-			       ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
-			tmp = min_t(u32, tmp, 255);
-			fifo->mcs2ampdu_table[i] = (u8) tmp;
-		}
-	}
-}
-
-static void BCMFASTPATH
-wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
-	      uint prec)
-{
-	scb_ampdu_t *scb_ampdu;
-	scb_ampdu_tid_ini_t *ini;
-	u8 tid = (u8) (p->priority);
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-
-	/* initialize initiator on first packet; sends addba req */
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	if (ini->magic != INI_MAGIC) {
-		ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
-	}
-	return;
-}
-
-int BCMFASTPATH
-wlc_sendampdu(struct ampdu_info *ampdu, wlc_txq_info_t *qi,
-	      struct sk_buff **pdu, int prec)
-{
-	struct wlc_info *wlc;
-	struct osl_info *osh;
-	struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
-	u8 tid, ndelim;
-	int err = 0;
-	u8 preamble_type = WLC_GF_PREAMBLE;
-	u8 fbr_preamble_type = WLC_GF_PREAMBLE;
-	u8 rts_preamble_type = WLC_LONG_PREAMBLE;
-	u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
-
-	bool rr = true, fbr = false;
-	uint i, count = 0, fifo, seg_cnt = 0;
-	u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
-	u32 ampdu_len, maxlen = 0;
-	d11txh_t *txh = NULL;
-	u8 *plcp;
-	struct dot11_header *h;
-	struct scb *scb;
-	scb_ampdu_t *scb_ampdu;
-	scb_ampdu_tid_ini_t *ini;
-	u8 mcs = 0;
-	bool use_rts = false, use_cts = false;
-	ratespec_t rspec = 0, rspec_fallback = 0;
-	ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
-	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-	struct dot11_rts_frame *rts;
-	u8 rr_retry_limit;
-	wlc_fifo_info_t *f;
-	bool fbr_iscck;
-	struct ieee80211_tx_info *tx_info;
-	u16 qlen;
-
-	wlc = ampdu->wlc;
-	osh = wlc->osh;
-	p = *pdu;
-
-	ASSERT(p);
-
-	tid = (u8) (p->priority);
-	ASSERT(tid < AMPDU_MAX_SCB_TID);
-
-	f = ampdu->fifo_tb + prio2fifo[tid];
-
-	scb = wlc->pub->global_scb;
-	ASSERT(scb->magic == SCB_MAGIC);
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	ASSERT(scb_ampdu);
-	ini = &scb_ampdu->ini[tid];
-
-	/* Let pressure continue to build ... */
-	qlen = pktq_plen(&qi->q, prec);
-	if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
-		return BCME_BUSY;
-	}
-
-	wlc_ampdu_agg(ampdu, scb, p, tid);
-
-	if (wlc->block_datafifo) {
-		WL_ERROR("%s: Fifo blocked\n", __func__);
-		return BCME_BUSY;
-	}
-	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
-	ampdu_len = 0;
-	dma_len = 0;
-	while (p) {
-		struct ieee80211_tx_rate *txrate;
-
-		tx_info = IEEE80211_SKB_CB(p);
-		txrate = tx_info->status.rates;
-
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			err = wlc_prep_pdu(wlc, p, &fifo);
-		} else {
-			WL_ERROR("%s: AMPDU flag is off!\n", __func__);
-			*pdu = NULL;
-			err = 0;
-			break;
-		}
-
-		if (err) {
-			if (err == BCME_BUSY) {
-				WL_ERROR("wl%d: wlc_sendampdu: prep_xdu retry; seq 0x%x\n",
-					 wlc->pub->unit, seq);
-				WLCNTINCR(ampdu->cnt->sduretry);
-				*pdu = p;
-				break;
-			}
-
-			/* error in the packet; reject it */
-			WL_AMPDU_ERR("wl%d: wlc_sendampdu: prep_xdu rejected; seq 0x%x\n",
-				     wlc->pub->unit, seq);
-			WLCNTINCR(ampdu->cnt->sdurejected);
-
-			*pdu = NULL;
-			break;
-		}
-
-		/* pkt is good to be aggregated */
-		ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
-		txh = (d11txh_t *) p->data;
-		plcp = (u8 *) (txh + 1);
-		h = (struct dot11_header *)(plcp + D11_PHY_HDR_LEN);
-		seq = ltoh16(h->seq) >> SEQNUM_SHIFT;
-		index = TX_SEQ_TO_INDEX(seq);
-
-		/* check mcl fields and test whether it can be agg'd */
-		mcl = ltoh16(txh->MacTxControlLow);
-		mcl &= ~TXC_AMPDU_MASK;
-		fbr_iscck = !(ltoh16(txh->XtraFrameTypes) & 0x3);
-		ASSERT(!fbr_iscck);
-		txh->PreloadSize = 0;	/* always default to 0 */
-
-		/*  Handle retry limits */
-		if (txrate[0].count <= rr_retry_limit) {
-			txrate[0].count++;
-			rr = true;
-			fbr = false;
-			ASSERT(!fbr);
-		} else {
-			fbr = true;
-			rr = false;
-			txrate[1].count++;
-		}
-
-		/* extract the length info */
-		len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
-		    : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-
-		/* retrieve null delimiter count */
-		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
-		seg_cnt += 1;
-
-		WL_AMPDU_TX("wl%d: wlc_sendampdu: mpdu %d plcp_len %d\n",
-			    wlc->pub->unit, count, len);
-
-		/*
-		 * aggregateable mpdu. For ucode/hw agg,
-		 * test whether need to break or change the epoch
-		 */
-		if (count == 0) {
-			u16 fc;
-			mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
-			/* refill the bits since might be a retx mpdu */
-			mcl |= TXC_STARTMSDU;
-			rts = (struct dot11_rts_frame *)&txh->rts_frame;
-			fc = ltoh16(rts->fc);
-			if ((fc & FC_KIND_MASK) == FC_RTS) {
-				mcl |= TXC_SENDRTS;
-				use_rts = true;
-			}
-			if ((fc & FC_KIND_MASK) == FC_CTS) {
-				mcl |= TXC_SENDCTS;
-				use_cts = true;
-			}
-		} else {
-			mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
-			mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
-		}
-
-		len = roundup(len, 4);
-		ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
-
-		dma_len += (u16) pkttotlen(osh, p);
-
-		WL_AMPDU_TX("wl%d: wlc_sendampdu: ampdu_len %d seg_cnt %d null delim %d\n",
-			    wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
-
-		txh->MacTxControlLow = htol16(mcl);
-
-		/* this packet is added */
-		pkt[count++] = p;
-
-		/* patch the first MPDU */
-		if (count == 1) {
-			u8 plcp0, plcp3, is40, sgi;
-			struct ieee80211_sta *sta;
-
-			sta = tx_info->control.sta;
-
-			if (rr) {
-				plcp0 = plcp[0];
-				plcp3 = plcp[3];
-			} else {
-				plcp0 = txh->FragPLCPFallback[0];
-				plcp3 = txh->FragPLCPFallback[3];
-
-			}
-			is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
-			sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
-			mcs = plcp0 & ~MIMO_PLCP_40MHZ;
-			ASSERT(mcs < MCS_TABLE_SIZE);
-			maxlen =
-			    min(scb_ampdu->max_rxlen,
-				ampdu->max_txlen[mcs][is40][sgi]);
-
-			WL_NONE("sendampdu: sgi %d, is40 %d, mcs %d\n",
-				sgi, is40, mcs);
-
-			maxlen = 64 * 1024;	/* XXX Fix me to honor real max_rxlen */
-
-			if (is40)
-				mimo_ctlchbw =
-				    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
-				    ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
-			/* rebuild the rspec and rspec_fallback */
-			rspec = RSPEC_MIMORATE;
-			rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
-			if (plcp[0] & MIMO_PLCP_40MHZ)
-				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
-
-			if (fbr_iscck)	/* CCK */
-				rspec_fallback =
-				    CCK_RSPEC(CCK_PHY2MAC_RATE
-					      (txh->FragPLCPFallback[0]));
-			else {	/* MIMO */
-				rspec_fallback = RSPEC_MIMORATE;
-				rspec_fallback |=
-				    txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
-				if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
-					rspec_fallback |=
-					    (PHY_TXC1_BW_40MHZ <<
-					     RSPEC_BW_SHIFT);
-			}
-
-			if (use_rts || use_cts) {
-				rts_rspec =
-				    wlc_rspec_to_rts_rspec(wlc, rspec, false,
-							   mimo_ctlchbw);
-				rts_rspec_fallback =
-				    wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
-							   false, mimo_ctlchbw);
-			}
-		}
-
-		/* if (first mpdu for host agg) */
-		/* test whether to add more */
-		if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
-		    (count == f->mcs2ampdu_table[mcs])) {
-			WL_AMPDU_ERR("wl%d: PR 37644: stopping ampdu at %d for mcs %d\n",
-				     wlc->pub->unit, count, mcs);
-			break;
-		}
-
-		if (count == scb_ampdu->max_pdu) {
-			WL_NONE("Stop taking from q, reached %d deep\n",
-				scb_ampdu->max_pdu);
-			break;
-		}
-
-		/* check to see if the next pkt is a candidate for aggregation */
-		p = pktq_ppeek(&qi->q, prec);
-		tx_info = IEEE80211_SKB_CB(p);	/* tx_info must be checked with current p */
-
-		if (p) {
-			if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
-			    ((u8) (p->priority) == tid)) {
-
-				plen =
-				    pkttotlen(osh, p) + AMPDU_MAX_MPDU_OVERHEAD;
-				plen = max(scb_ampdu->min_len, plen);
-
-				if ((plen + ampdu_len) > maxlen) {
-					p = NULL;
-					WL_ERROR("%s: Bogus plen #1\n",
-						 __func__);
-					ASSERT(3 == 4);
-					continue;
-				}
-
-				/* check if there are enough descriptors available */
-				if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
-					WL_ERROR("%s: No fifo space   !!!!!!\n",
-						 __func__);
-					p = NULL;
-					continue;
-				}
-				p = pktq_pdeq(&qi->q, prec);
-				ASSERT(p);
-			} else {
-				p = NULL;
-			}
-		}
-	}			/* end while(p) */
-
-	ini->tx_in_transit += count;
-
-	if (count) {
-		WLCNTADD(ampdu->cnt->txmpdu, count);
-
-		/* patch up the last txh */
-		txh = (d11txh_t *) pkt[count - 1]->data;
-		mcl = ltoh16(txh->MacTxControlLow);
-		mcl &= ~TXC_AMPDU_MASK;
-		mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
-		txh->MacTxControlLow = htol16(mcl);
-
-		/* remove the null delimiter after last mpdu */
-		ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
-		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
-		ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
-
-		/* remove the pad len from last mpdu */
-		fbr_iscck = ((ltoh16(txh->XtraFrameTypes) & 0x3) == 0);
-		len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
-		    : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
-		ampdu_len -= roundup(len, 4) - len;
-
-		/* patch up the first txh & plcp */
-		txh = (d11txh_t *) pkt[0]->data;
-		plcp = (u8 *) (txh + 1);
-
-		WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
-		/* mark plcp to indicate ampdu */
-		WLC_SET_MIMO_PLCP_AMPDU(plcp);
-
-		/* reset the mixed mode header durations */
-		if (txh->MModeLen) {
-			u16 mmodelen =
-			    wlc_calc_lsig_len(wlc, rspec, ampdu_len);
-			txh->MModeLen = htol16(mmodelen);
-			preamble_type = WLC_MM_PREAMBLE;
-		}
-		if (txh->MModeFbrLen) {
-			u16 mmfbrlen =
-			    wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
-			txh->MModeFbrLen = htol16(mmfbrlen);
-			fbr_preamble_type = WLC_MM_PREAMBLE;
-		}
-
-		/* set the preload length */
-		if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
-			dma_len = min(dma_len, f->ampdu_pld_size);
-			txh->PreloadSize = htol16(dma_len);
-		} else
-			txh->PreloadSize = 0;
-
-		mch = ltoh16(txh->MacTxControlHigh);
-
-		/* update RTS dur fields */
-		if (use_rts || use_cts) {
-			u16 durid;
-			rts = (struct dot11_rts_frame *)&txh->rts_frame;
-			if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
-			    TXC_PREAMBLE_RTS_MAIN_SHORT)
-				rts_preamble_type = WLC_SHORT_PREAMBLE;
-
-			if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
-			    TXC_PREAMBLE_RTS_FB_SHORT)
-				rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
-
-			durid =
-			    wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
-						   rspec, rts_preamble_type,
-						   preamble_type, ampdu_len,
-						   true);
-			rts->durid = htol16(durid);
-			durid = wlc_compute_rtscts_dur(wlc, use_cts,
-						       rts_rspec_fallback,
-						       rspec_fallback,
-						       rts_fbr_preamble_type,
-						       fbr_preamble_type,
-						       ampdu_len, true);
-			txh->RTSDurFallback = htol16(durid);
-			/* set TxFesTimeNormal */
-			txh->TxFesTimeNormal = rts->durid;
-			/* set fallback rate version of TxFesTimeNormal */
-			txh->TxFesTimeFallback = txh->RTSDurFallback;
-		}
-
-		/* set flag and plcp for fallback rate */
-		if (fbr) {
-			WLCNTADD(ampdu->cnt->txfbr_mpdu, count);
-			WLCNTINCR(ampdu->cnt->txfbr_ampdu);
-			mch |= TXC_AMPDU_FBR;
-			txh->MacTxControlHigh = htol16(mch);
-			WLC_SET_MIMO_PLCP_AMPDU(plcp);
-			WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
-		}
-
-		WL_AMPDU_TX("wl%d: wlc_sendampdu: count %d ampdu_len %d\n",
-			    wlc->pub->unit, count, ampdu_len);
-
-		/* inform rate_sel if it this is a rate probe pkt */
-		frameid = ltoh16(txh->TxFrameID);
-		if (frameid & TXFID_RATE_PROBE_MASK) {
-			WL_ERROR("%s: XXX what to do with TXFID_RATE_PROBE_MASK!?\n",
-				 __func__);
-		}
-		for (i = 0; i < count; i++)
-			wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
-				   ampdu->txpkt_weight);
-
-	}
-	/* endif (count) */
-	return err;
-}
-
-void BCMFASTPATH
-wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
-		     struct sk_buff *p, tx_status_t *txs)
-{
-	scb_ampdu_t *scb_ampdu;
-	struct wlc_info *wlc = ampdu->wlc;
-	scb_ampdu_tid_ini_t *ini;
-	u32 s1 = 0, s2 = 0;
-	struct ieee80211_tx_info *tx_info;
-
-	tx_info = IEEE80211_SKB_CB(p);
-	ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
-	ASSERT(scb);
-	ASSERT(scb->magic == SCB_MAGIC);
-	ASSERT(txs->status & TX_STATUS_AMPDU);
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	ASSERT(scb_ampdu);
-	ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
-	ASSERT(ini->scb == scb);
-
-	/* BMAC_NOTE: For the split driver, second level txstatus comes later
-	 * So if the ACK was received then wait for the second level else just
-	 * call the first one
-	 */
-	if (txs->status & TX_STATUS_ACK_RCV) {
-		u8 status_delay = 0;
-
-		/* wait till the next 8 bytes of txstatus is available */
-		while (((s1 =
-			 R_REG(wlc->osh,
-			       &wlc->regs->frmtxstatus)) & TXS_V) == 0) {
-			udelay(1);
-			status_delay++;
-			if (status_delay > 10) {
-				ASSERT(status_delay <= 10);
-				return;
-			}
-		}
-
-		ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
-		ASSERT(s1 & TX_STATUS_AMPDU);
-		s2 = R_REG(wlc->osh, &wlc->regs->frmtxstatus2);
-	}
-
-	wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
-	wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
-}
-
-void
-rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
-	    tx_status_t *txs, u8 mcs)
-{
-	struct ieee80211_tx_rate *txrate = tx_info->status.rates;
-	int i;
-
-	/* clear the rest of the rates */
-	for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
-		txrate[i].idx = -1;
-		txrate[i].count = 0;
-	}
-}
-
-#define SHORTNAME "AMPDU status"
-
-static void BCMFASTPATH
-wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
-			      struct sk_buff *p, tx_status_t *txs,
-			      u32 s1, u32 s2)
-{
-	scb_ampdu_t *scb_ampdu;
-	struct wlc_info *wlc = ampdu->wlc;
-	scb_ampdu_tid_ini_t *ini;
-	u8 bitmap[8], queue, tid;
-	d11txh_t *txh;
-	u8 *plcp;
-	struct dot11_header *h;
-	u16 seq, start_seq = 0, bindex, index, mcl;
-	u8 mcs = 0;
-	bool ba_recd = false, ack_recd = false;
-	u8 suc_mpdu = 0, tot_mpdu = 0;
-	uint supr_status;
-	bool update_rate = true, retry = true, tx_error = false;
-	u16 mimoantsel = 0;
-	u8 antselid = 0;
-	u8 retry_limit, rr_retry_limit;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
-
-#ifdef BCMDBG
-	u8 hole[AMPDU_MAX_MPDU];
-	memset(hole, 0, sizeof(hole));
-#endif
-
-	ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
-	ASSERT(txs->status & TX_STATUS_AMPDU);
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	ASSERT(scb_ampdu);
-
-	tid = (u8) (p->priority);
-
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	retry_limit = ampdu->retry_limit_tid[tid];
-	rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
-
-	ASSERT(ini->scb == scb);
-
-	memset(bitmap, 0, sizeof(bitmap));
-	queue = txs->frameid & TXFID_QUEUE_MASK;
-	ASSERT(queue < AC_COUNT);
-
-	supr_status = txs->status & TX_STATUS_SUPR_MASK;
-
-	if (txs->status & TX_STATUS_ACK_RCV) {
-		if (TX_STATUS_SUPR_UF == supr_status) {
-			update_rate = false;
-		}
-
-		ASSERT(txs->status & TX_STATUS_INTERMEDIATE);
-		start_seq = txs->sequence >> SEQNUM_SHIFT;
-		bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
-		    TX_STATUS_BA_BMAP03_SHIFT;
-
-		ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
-		ASSERT(s1 & TX_STATUS_AMPDU);
-
-		bitmap[0] |=
-		    (s1 & TX_STATUS_BA_BMAP47_MASK) <<
-		    TX_STATUS_BA_BMAP47_SHIFT;
-		bitmap[1] = (s1 >> 8) & 0xff;
-		bitmap[2] = (s1 >> 16) & 0xff;
-		bitmap[3] = (s1 >> 24) & 0xff;
-
-		bitmap[4] = s2 & 0xff;
-		bitmap[5] = (s2 >> 8) & 0xff;
-		bitmap[6] = (s2 >> 16) & 0xff;
-		bitmap[7] = (s2 >> 24) & 0xff;
-
-		ba_recd = true;
-	} else {
-		WLCNTINCR(ampdu->cnt->noba);
-		if (supr_status) {
-			update_rate = false;
-			if (supr_status == TX_STATUS_SUPR_BADCH) {
-				WL_ERROR("%s: Pkt tx suppressed, illegal channel possibly %d\n",
-					 __func__,
-					 CHSPEC_CHANNEL(wlc->default_bss->chanspec));
-			} else {
-				if (supr_status == TX_STATUS_SUPR_FRAG)
-					WL_NONE("%s: AMPDU frag err\n",
-						__func__);
-				else
-					WL_ERROR("%s: wlc_ampdu_dotxstatus: supr_status 0x%x\n",
-						 __func__, supr_status);
-			}
-			/* no need to retry for badch; will fail again */
-			if (supr_status == TX_STATUS_SUPR_BADCH ||
-			    supr_status == TX_STATUS_SUPR_EXPTIME) {
-				retry = false;
-				WLCNTINCR(wlc->pub->_cnt->txchanrej);
-			} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
-
-				WLCNTINCR(wlc->pub->_cnt->txexptime);
-
-				/* TX underflow : try tuning pre-loading or ampdu size */
-			} else if (supr_status == TX_STATUS_SUPR_FRAG) {
-				/* if there were underflows, but pre-loading is not active,
-				   notify rate adaptation.
-				 */
-				if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
-				    > 0) {
-					tx_error = true;
-				}
-			}
-		} else if (txs->phyerr) {
-			update_rate = false;
-			WLCNTINCR(wlc->pub->_cnt->txphyerr);
-			WL_ERROR("wl%d: wlc_ampdu_dotxstatus: tx phy error (0x%x)\n",
-				 wlc->pub->unit, txs->phyerr);
-
-#ifdef BCMDBG
-			if (WL_ERROR_ON()) {
-				prpkt("txpkt (AMPDU)", wlc->osh, p);
-				wlc_print_txdesc((d11txh_t *) p->data);
-				wlc_print_txstatus(txs);
-			}
-#endif				/* BCMDBG */
-		}
-	}
-
-	/* loop through all pkts and retry if not acked */
-	while (p) {
-		tx_info = IEEE80211_SKB_CB(p);
-		ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
-		txh = (d11txh_t *) p->data;
-		mcl = ltoh16(txh->MacTxControlLow);
-		plcp = (u8 *) (txh + 1);
-		h = (struct dot11_header *)(plcp + D11_PHY_HDR_LEN);
-		seq = ltoh16(h->seq) >> SEQNUM_SHIFT;
-
-		if (tot_mpdu == 0) {
-			mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
-			mimoantsel = ltoh16(txh->ABI_MimoAntSel);
-		}
-
-		index = TX_SEQ_TO_INDEX(seq);
-		ack_recd = false;
-		if (ba_recd) {
-			bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
-
-			WL_AMPDU_TX("%s: tid %d seq is %d, start_seq is %d, bindex is %d set %d, index %d\n",
-				    __func__, tid, seq, start_seq, bindex,
-				    isset(bitmap, bindex), index);
-
-			/* if acked then clear bit and free packet */
-			if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
-			    && isset(bitmap, bindex)) {
-				ini->tx_in_transit--;
-				ini->txretry[index] = 0;
-
-				/* ampdu_ack_len: number of acked aggregated frames */
-				/* ampdu_ack_map: block ack bit map for the aggregation */
-				/* ampdu_len: number of aggregated frames */
-				rate_status(wlc, tx_info, txs, mcs);
-				tx_info->flags |= IEEE80211_TX_STAT_ACK;
-				tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
-
-				/* XXX TODO: Make these accurate. */
-				tx_info->status.ampdu_ack_len =
-				    (txs->
-				     status & TX_STATUS_FRM_RTX_MASK) >>
-				    TX_STATUS_FRM_RTX_SHIFT;
-				tx_info->status.ampdu_len =
-				    (txs->
-				     status & TX_STATUS_FRM_RTX_MASK) >>
-				    TX_STATUS_FRM_RTX_SHIFT;
-
-				skb_pull(p, D11_PHY_HDR_LEN);
-				skb_pull(p, D11_TXH_LEN);
-
-				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
-							    p);
-				ack_recd = true;
-				suc_mpdu++;
-			}
-		}
-		/* either retransmit or send bar if ack not recd */
-		if (!ack_recd) {
-			struct ieee80211_tx_rate *txrate =
-			    tx_info->status.rates;
-			if (retry && (txrate[0].count < (int)retry_limit)) {
-				ini->txretry[index]++;
-				ini->tx_in_transit--;
-				/* Use high prededence for retransmit to give some punch */
-				/* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
-				wlc_txq_enq(wlc, scb, p,
-					    WLC_PRIO_TO_HI_PREC(tid));
-			} else {
-				/* Retry timeout */
-				ini->tx_in_transit--;
-				ieee80211_tx_info_clear_status(tx_info);
-				tx_info->flags |=
-				    IEEE80211_TX_STAT_AMPDU_NO_BACK;
-				skb_pull(p, D11_PHY_HDR_LEN);
-				skb_pull(p, D11_TXH_LEN);
-				WL_ERROR("%s: BA Timeout, seq %d, in_transit %d\n",
-					 SHORTNAME, seq, ini->tx_in_transit);
-				ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
-							    p);
-			}
-		}
-		tot_mpdu++;
-
-		/* break out if last packet of ampdu */
-		if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
-		    TXC_AMPDU_LAST)
-			break;
-
-		p = GETNEXTTXP(wlc, queue);
-		if (p == NULL) {
-			ASSERT(p);
-			break;
-		}
-	}
-	wlc_send_q(wlc, wlc->active_queue);
-
-	/* update rate state */
-	if (WLANTSEL_ENAB(wlc))
-		antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
-
-	wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
-}
-
-static void
-ampdu_cleanup_tid_ini(struct ampdu_info *ampdu, scb_ampdu_t *scb_ampdu, u8 tid,
-		      bool force)
-{
-	scb_ampdu_tid_ini_t *ini;
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	if (!ini)
-		return;
-
-	WL_AMPDU_CTL("wl%d: ampdu_cleanup_tid_ini: tid %d\n",
-		     ampdu->wlc->pub->unit, tid);
-
-	if (ini->tx_in_transit && !force)
-		return;
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, ini->scb);
-	ASSERT(ini == &scb_ampdu->ini[ini->tid]);
-
-	/* free all buffered tx packets */
-	pktq_pflush(ampdu->wlc->osh, &scb_ampdu->txq, ini->tid, true, NULL, 0);
-}
-
-/* initialize the initiator code for tid */
-static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
-						   scb_ampdu_t *scb_ampdu,
-						   u8 tid, bool override)
-{
-	scb_ampdu_tid_ini_t *ini;
-
-	ASSERT(scb_ampdu);
-	ASSERT(scb_ampdu->scb);
-	ASSERT(SCB_AMPDU(scb_ampdu->scb));
-	ASSERT(tid < AMPDU_MAX_SCB_TID);
-
-	/* check for per-tid control of ampdu */
-	if (!ampdu->ini_enable[tid]) {
-		WL_ERROR("%s: Rejecting tid %d\n", __func__, tid);
-		return NULL;
-	}
-
-	ini = SCB_AMPDU_INI(scb_ampdu, tid);
-	ini->tid = tid;
-	ini->scb = scb_ampdu->scb;
-	ini->magic = INI_MAGIC;
-	WLCNTINCR(ampdu->cnt->txaddbareq);
-
-	return ini;
-}
-
-int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
-{
-	struct wlc_info *wlc = ampdu->wlc;
-
-	wlc->pub->_ampdu = false;
-
-	if (on) {
-		if (!N_ENAB(wlc->pub)) {
-			WL_AMPDU_ERR("wl%d: driver not nmode enabled\n",
-				     wlc->pub->unit);
-			return BCME_UNSUPPORTED;
-		}
-		if (!wlc_ampdu_cap(ampdu)) {
-			WL_AMPDU_ERR("wl%d: device not ampdu capable\n",
-				     wlc->pub->unit);
-			return BCME_UNSUPPORTED;
-		}
-		wlc->pub->_ampdu = on;
-	}
-
-	return 0;
-}
-
-bool wlc_ampdu_cap(struct ampdu_info *ampdu)
-{
-	if (WLC_PHY_11N_CAP(ampdu->wlc->band))
-		return true;
-	else
-		return false;
-}
-
-static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
-{
-	u32 rate, mcs;
-
-	for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
-		/* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
-		/* 20MHz, No SGI */
-		rate = MCS_RATE(mcs, false, false);
-		ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
-		/* 40 MHz, No SGI */
-		rate = MCS_RATE(mcs, true, false);
-		ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
-		/* 20MHz, SGI */
-		rate = MCS_RATE(mcs, false, true);
-		ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
-		/* 40 MHz, SGI */
-		rate = MCS_RATE(mcs, true, true);
-		ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
-	}
-}
-
-u8 BCMFASTPATH
-wlc_ampdu_null_delim_cnt(struct ampdu_info *ampdu, struct scb *scb,
-			 ratespec_t rspec, int phylen)
-{
-	scb_ampdu_t *scb_ampdu;
-	int bytes, cnt, tmp;
-	u8 tx_density;
-
-	ASSERT(scb);
-	ASSERT(SCB_AMPDU(scb));
-
-	scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
-	ASSERT(scb_ampdu);
-
-	if (scb_ampdu->mpdu_density == 0)
-		return 0;
-
-	/* RSPEC2RATE is in kbps units ==> ~RSPEC2RATE/2^13 is in bytes/usec
-	   density x is in 2^(x-4) usec
-	   ==> # of bytes needed for req density = rate/2^(17-x)
-	   ==> # of null delimiters = ceil(ceil(rate/2^(17-x)) - phylen)/4)
-	 */
-
-	tx_density = scb_ampdu->mpdu_density;
-
-	ASSERT(tx_density <= AMPDU_MAX_MPDU_DENSITY);
-	tmp = 1 << (17 - tx_density);
-	bytes = CEIL(RSPEC2RATE(rspec), tmp);
-
-	if (bytes > phylen) {
-		cnt = CEIL(bytes - phylen, AMPDU_DELIMITER_LEN);
-		ASSERT(cnt <= 255);
-		return (u8) cnt;
-	} else
-		return 0;
-}
-
-void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
-{
-	char template[T_RAM_ACCESS_SZ * 2];
-
-	/* driver needs to write the ta in the template; ta is at offset 16 */
-	memset(template, 0, sizeof(template));
-	bcopy((char *)wlc->pub->cur_etheraddr.octet, template, ETH_ALEN);
-	wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
-			       template);
-}
-
-bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
-{
-	return wlc->ampdu->ini_enable[tid];
-}
-
-void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
-{
-	struct wlc_info *wlc = ampdu->wlc;
-
-	/* Extend ucode internal watchdog timer to match larger received frames */
-	if ((ampdu->rx_factor & HT_PARAMS_RX_FACTOR_MASK) ==
-	    AMPDU_RX_FACTOR_64K) {
-		wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
-		wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
-	} else {
-		wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
-		wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
-	}
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_ampdu.h b/drivers/staging/brcm80211/sys/wlc_ampdu.h
deleted file mode 100644
index 03457f6..0000000
--- a/drivers/staging/brcm80211/sys/wlc_ampdu.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_ampdu_h_
-#define _wlc_ampdu_h_
-
-extern struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc);
-extern void wlc_ampdu_detach(struct ampdu_info *ampdu);
-extern bool wlc_ampdu_cap(struct ampdu_info *ampdu);
-extern int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
-extern int wlc_sendampdu(struct ampdu_info *ampdu, wlc_txq_info_t *qi,
-			 struct sk_buff **aggp, int prec);
-extern void wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
-				 struct sk_buff *p, tx_status_t *txs);
-extern void wlc_ampdu_reset(struct ampdu_info *ampdu);
-extern void wlc_ampdu_macaddr_upd(struct wlc_info *wlc);
-extern void wlc_ampdu_shm_upd(struct ampdu_info *ampdu);
-
-extern u8 wlc_ampdu_null_delim_cnt(struct ampdu_info *ampdu, struct scb *scb,
-				      ratespec_t rspec, int phylen);
-extern void scb_ampdu_cleanup(struct ampdu_info *ampdu, struct scb *scb);
-
-#endif				/* _wlc_ampdu_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_antsel.c b/drivers/staging/brcm80211/sys/wlc_antsel.c
deleted file mode 100644
index 402ddf8..0000000
--- a/drivers/staging/brcm80211/sys/wlc_antsel.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <wlc_cfg.h>
-
-#ifdef WLANTSEL
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <wlioctl.h>
-
-#include <bcmdevs.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_key.h>
-#include <wlc_pub.h>
-#include <wl_dbg.h>
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_bmac.h>
-#include <wlc_phy_hal.h>
-#include <wl_export.h>
-#include <wlc_antsel.h>
-#include <wlc_phy_shim.h>
-
-/* useful macros */
-#define WLC_ANTSEL_11N_0(ant)	((((ant) & ANT_SELCFG_MASK) >> 4) & 0xf)
-#define WLC_ANTSEL_11N_1(ant)	(((ant) & ANT_SELCFG_MASK) & 0xf)
-#define WLC_ANTIDX_11N(ant)	(((WLC_ANTSEL_11N_0(ant)) << 2) + (WLC_ANTSEL_11N_1(ant)))
-#define WLC_ANT_ISAUTO_11N(ant)	(((ant) & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO)
-#define WLC_ANTSEL_11N(ant)	((ant) & ANT_SELCFG_MASK)
-
-/* antenna switch */
-/* defines for no boardlevel antenna diversity */
-#define ANT_SELCFG_DEF_2x2	0x01	/* default antenna configuration */
-
-/* 2x3 antdiv defines and tables for GPIO communication */
-#define ANT_SELCFG_NUM_2x3	3
-#define ANT_SELCFG_DEF_2x3	0x01	/* default antenna configuration */
-
-/* 2x4 antdiv rev4 defines and tables for GPIO communication */
-#define ANT_SELCFG_NUM_2x4	4
-#define ANT_SELCFG_DEF_2x4	0x02	/* default antenna configuration */
-
-/* static functions */
-static int wlc_antsel_cfgupd(struct antsel_info *asi, wlc_antselcfg_t *antsel);
-static u8 wlc_antsel_id2antcfg(struct antsel_info *asi, u8 id);
-static u16 wlc_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg);
-static void wlc_antsel_init_cfg(struct antsel_info *asi,
-				wlc_antselcfg_t *antsel,
-				bool auto_sel);
-
-const u16 mimo_2x4_div_antselpat_tbl[] = {
-	0, 0, 0x9, 0xa,		/* ant0: 0 ant1: 2,3 */
-	0, 0, 0x5, 0x6,		/* ant0: 1 ant1: 2,3 */
-	0, 0, 0, 0,		/* n.a.              */
-	0, 0, 0, 0		/* n.a.              */
-};
-
-const u8 mimo_2x4_div_antselid_tbl[16] = {
-	0, 0, 0, 0, 0, 2, 3, 0,
-	0, 0, 1, 0, 0, 0, 0, 0	/* pat to antselid */
-};
-
-const u16 mimo_2x3_div_antselpat_tbl[] = {
-	16, 0, 1, 16,		/* ant0: 0 ant1: 1,2 */
-	16, 16, 16, 16,		/* n.a.              */
-	16, 2, 16, 16,		/* ant0: 2 ant1: 1   */
-	16, 16, 16, 16		/* n.a.              */
-};
-
-const u8 mimo_2x3_div_antselid_tbl[16] = {
-	0, 1, 2, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0	/* pat to antselid */
-};
-
-struct antsel_info *wlc_antsel_attach(struct wlc_info *wlc,
-				      struct osl_info *osh,
-				      struct wlc_pub *pub,
-				      struct wlc_hw_info *wlc_hw) {
-	struct antsel_info *asi;
-
-	asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC);
-	if (!asi) {
-		WL_ERROR("wl%d: wlc_antsel_attach: out of mem\n", pub->unit);
-		return NULL;
-	}
-
-	asi->wlc = wlc;
-	asi->pub = pub;
-	asi->antsel_type = ANTSEL_NA;
-	asi->antsel_avail = false;
-	asi->antsel_antswitch = (u8) getintvar(asi->pub->vars, "antswitch");
-
-	if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) {
-		switch (asi->antsel_antswitch) {
-		case ANTSWITCH_TYPE_1:
-		case ANTSWITCH_TYPE_2:
-		case ANTSWITCH_TYPE_3:
-			/* 4321/2 board with 2x3 switch logic */
-			asi->antsel_type = ANTSEL_2x3;
-			/* Antenna selection availability */
-			if (((u16) getintvar(asi->pub->vars, "aa2g") == 7) ||
-			    ((u16) getintvar(asi->pub->vars, "aa5g") == 7)) {
-				asi->antsel_avail = true;
-			} else
-			    if (((u16) getintvar(asi->pub->vars, "aa2g") ==
-				 3)
-				|| ((u16) getintvar(asi->pub->vars, "aa5g")
-				    == 3)) {
-				asi->antsel_avail = false;
-			} else {
-				asi->antsel_avail = false;
-				WL_ERROR("wlc_antsel_attach: 2o3 board cfg invalid\n");
-				ASSERT(0);
-			}
-			break;
-		default:
-			break;
-		}
-	} else if ((asi->pub->sromrev == 4) &&
-		   ((u16) getintvar(asi->pub->vars, "aa2g") == 7) &&
-		   ((u16) getintvar(asi->pub->vars, "aa5g") == 0)) {
-		/* hack to match old 4321CB2 cards with 2of3 antenna switch */
-		asi->antsel_type = ANTSEL_2x3;
-		asi->antsel_avail = true;
-	} else if (asi->pub->boardflags2 & BFL2_2X4_DIV) {
-		asi->antsel_type = ANTSEL_2x4;
-		asi->antsel_avail = true;
-	}
-
-	/* Set the antenna selection type for the low driver */
-	wlc_bmac_antsel_type_set(wlc_hw, asi->antsel_type);
-
-	/* Init (auto/manual) antenna selection */
-	wlc_antsel_init_cfg(asi, &asi->antcfg_11n, true);
-	wlc_antsel_init_cfg(asi, &asi->antcfg_cur, true);
-
-	return asi;
-}
-
-void wlc_antsel_detach(struct antsel_info *asi)
-{
-	if (!asi)
-		return;
-
-	kfree(asi);
-}
-
-void wlc_antsel_init(struct antsel_info *asi)
-{
-	if ((asi->antsel_type == ANTSEL_2x3) ||
-	    (asi->antsel_type == ANTSEL_2x4))
-		wlc_antsel_cfgupd(asi, &asi->antcfg_11n);
-}
-
-/* boardlevel antenna selection: init antenna selection structure */
-static void
-wlc_antsel_init_cfg(struct antsel_info *asi, wlc_antselcfg_t *antsel,
-		    bool auto_sel)
-{
-	if (asi->antsel_type == ANTSEL_2x3) {
-		u8 antcfg_def = ANT_SELCFG_DEF_2x3 |
-		    ((asi->antsel_avail && auto_sel) ? ANT_SELCFG_AUTO : 0);
-		antsel->ant_config[ANT_SELCFG_TX_DEF] = antcfg_def;
-		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = antcfg_def;
-		antsel->ant_config[ANT_SELCFG_RX_DEF] = antcfg_def;
-		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = antcfg_def;
-		antsel->num_antcfg = ANT_SELCFG_NUM_2x3;
-
-	} else if (asi->antsel_type == ANTSEL_2x4) {
-
-		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x4;
-		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x4;
-		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x4;
-		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x4;
-		antsel->num_antcfg = ANT_SELCFG_NUM_2x4;
-
-	} else {		/* no antenna selection available */
-
-		antsel->ant_config[ANT_SELCFG_TX_DEF] = ANT_SELCFG_DEF_2x2;
-		antsel->ant_config[ANT_SELCFG_TX_UNICAST] = ANT_SELCFG_DEF_2x2;
-		antsel->ant_config[ANT_SELCFG_RX_DEF] = ANT_SELCFG_DEF_2x2;
-		antsel->ant_config[ANT_SELCFG_RX_UNICAST] = ANT_SELCFG_DEF_2x2;
-		antsel->num_antcfg = 0;
-	}
-}
-
-void BCMFASTPATH
-wlc_antsel_antcfg_get(struct antsel_info *asi, bool usedef, bool sel,
-		      u8 antselid, u8 fbantselid, u8 *antcfg,
-		      u8 *fbantcfg)
-{
-	u8 ant;
-
-	/* if use default, assign it and return */
-	if (usedef) {
-		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_DEF];
-		*fbantcfg = *antcfg;
-		return;
-	}
-
-	if (!sel) {
-		*antcfg = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
-		*fbantcfg = *antcfg;
-
-	} else {
-		ant = asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
-		if ((ant & ANT_SELCFG_AUTO) == ANT_SELCFG_AUTO) {
-			*antcfg = wlc_antsel_id2antcfg(asi, antselid);
-			*fbantcfg = wlc_antsel_id2antcfg(asi, fbantselid);
-		} else {
-			*antcfg =
-			    asi->antcfg_11n.ant_config[ANT_SELCFG_TX_UNICAST];
-			*fbantcfg = *antcfg;
-		}
-	}
-	return;
-}
-
-/* boardlevel antenna selection: convert mimo_antsel (ucode interface) to id */
-u8 wlc_antsel_antsel2id(struct antsel_info *asi, u16 antsel)
-{
-	u8 antselid = 0;
-
-	if (asi->antsel_type == ANTSEL_2x4) {
-		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
-		antselid = mimo_2x4_div_antselid_tbl[(antsel & 0xf)];
-		return antselid;
-
-	} else if (asi->antsel_type == ANTSEL_2x3) {
-		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
-		antselid = mimo_2x3_div_antselid_tbl[(antsel & 0xf)];
-		return antselid;
-	}
-
-	return antselid;
-}
-
-/* boardlevel antenna selection: convert id to ant_cfg */
-static u8 wlc_antsel_id2antcfg(struct antsel_info *asi, u8 id)
-{
-	u8 antcfg = ANT_SELCFG_DEF_2x2;
-
-	if (asi->antsel_type == ANTSEL_2x4) {
-		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
-		antcfg = (((id & 0x2) << 3) | ((id & 0x1) + 2));
-		return antcfg;
-
-	} else if (asi->antsel_type == ANTSEL_2x3) {
-		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
-		antcfg = (((id & 0x02) << 4) | ((id & 0x1) + 1));
-		return antcfg;
-	}
-
-	return antcfg;
-}
-
-/* boardlevel antenna selection: convert ant_cfg to mimo_antsel (ucode interface) */
-static u16 wlc_antsel_antcfg2antsel(struct antsel_info *asi, u8 ant_cfg)
-{
-	u8 idx = WLC_ANTIDX_11N(WLC_ANTSEL_11N(ant_cfg));
-	u16 mimo_antsel = 0;
-
-	if (asi->antsel_type == ANTSEL_2x4) {
-		/* 2x4 antenna diversity board, 4 cfgs: 0-2 0-3 1-2 1-3 */
-		mimo_antsel = (mimo_2x4_div_antselpat_tbl[idx] & 0xf);
-		return mimo_antsel;
-
-	} else if (asi->antsel_type == ANTSEL_2x3) {
-		/* 2x3 antenna selection, 3 cfgs: 0-1 0-2 2-1 */
-		mimo_antsel = (mimo_2x3_div_antselpat_tbl[idx] & 0xf);
-		return mimo_antsel;
-	}
-
-	return mimo_antsel;
-}
-
-/* boardlevel antenna selection: ucode interface control */
-static int wlc_antsel_cfgupd(struct antsel_info *asi, wlc_antselcfg_t *antsel)
-{
-	struct wlc_info *wlc = asi->wlc;
-	u8 ant_cfg;
-	u16 mimo_antsel;
-
-	ASSERT(asi->antsel_type != ANTSEL_NA);
-
-	/* 1) Update TX antconfig for all frames that are not unicast data
-	 *    (aka default TX)
-	 */
-	ant_cfg = antsel->ant_config[ANT_SELCFG_TX_DEF];
-	mimo_antsel = wlc_antsel_antcfg2antsel(asi, ant_cfg);
-	wlc_write_shm(wlc, M_MIMO_ANTSEL_TXDFLT, mimo_antsel);
-	/* Update driver stats for currently selected default tx/rx antenna config */
-	asi->antcfg_cur.ant_config[ANT_SELCFG_TX_DEF] = ant_cfg;
-
-	/* 2) Update RX antconfig for all frames that are not unicast data
-	 *    (aka default RX)
-	 */
-	ant_cfg = antsel->ant_config[ANT_SELCFG_RX_DEF];
-	mimo_antsel = wlc_antsel_antcfg2antsel(asi, ant_cfg);
-	wlc_write_shm(wlc, M_MIMO_ANTSEL_RXDFLT, mimo_antsel);
-	/* Update driver stats for currently selected default tx/rx antenna config */
-	asi->antcfg_cur.ant_config[ANT_SELCFG_RX_DEF] = ant_cfg;
-
-	return 0;
-}
-
-#endif				/* WLANTSEL */
diff --git a/drivers/staging/brcm80211/sys/wlc_antsel.h b/drivers/staging/brcm80211/sys/wlc_antsel.h
deleted file mode 100644
index 8875b58..0000000
--- a/drivers/staging/brcm80211/sys/wlc_antsel.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_antsel_h_
-#define _wlc_antsel_h_
-extern struct antsel_info *wlc_antsel_attach(struct wlc_info *wlc,
-					struct osl_info *osh,
-					struct wlc_pub *pub,
-					struct wlc_hw_info *wlc_hw);
-extern void wlc_antsel_detach(struct antsel_info *asi);
-extern void wlc_antsel_init(struct antsel_info *asi);
-extern void wlc_antsel_antcfg_get(struct antsel_info *asi, bool usedef,
-				  bool sel,
-				  u8 id, u8 fbid, u8 *antcfg,
-				  u8 *fbantcfg);
-extern u8 wlc_antsel_antsel2id(struct antsel_info *asi, u16 antsel);
-#endif				/* _wlc_antsel_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_bmac.c b/drivers/staging/brcm80211/sys/wlc_bmac.c
deleted file mode 100644
index 69f600a..0000000
--- a/drivers/staging/brcm80211/sys/wlc_bmac.c
+++ /dev/null
@@ -1,4236 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#include <linux/kernel.h>
-#include <wlc_cfg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <proto/802.11.h>
-#include <bcmwifi.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmendian.h>
-#include <wlioctl.h>
-#include <sbconfig.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-#include <hndpmu.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_pub.h>
-#include <wlc_channel.h>
-#include <bcmsrom.h>
-#include <wlc_key.h>
-#include <bcmdevs.h>
-/* BMAC_NOTE: a WLC_HIGH compile include of wlc.h adds in more structures and type
- * dependencies. Need to include these to files to allow a clean include of wlc.h
- * with WLC_HIGH defined.
- * At some point we may be able to skip the include of wlc.h and instead just
- * define a stub wlc_info and band struct to allow rpc calls to get the rpc handle.
- */
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_bmac.h>
-#include <wlc_phy_shim.h>
-#include <wlc_phy_hal.h>
-#include <wl_export.h>
-#include "wl_ucode.h"
-#include "d11ucode_ext.h"
-#include <bcmotp.h>
-
-/* BMAC_NOTE: With WLC_HIGH defined, some fns in this file make calls to high level
- * functions defined in the headers below. We should be eliminating those calls and
- * will be able to delete these include lines.
- */
-#include <wlc_antsel.h>
-
-#include <pcie_core.h>
-
-#include <wlc_alloc.h>
-#include <wl_dbg.h>
-
-#define	TIMER_INTERVAL_WATCHDOG_BMAC	1000	/* watchdog timer, in unit of ms */
-
-#define	SYNTHPU_DLY_APHY_US	3700	/* a phy synthpu_dly time in us */
-#define	SYNTHPU_DLY_BPHY_US	1050	/* b/g phy synthpu_dly time in us, default */
-#define	SYNTHPU_DLY_NPHY_US	2048	/* n phy REV3 synthpu_dly time in us, default */
-#define	SYNTHPU_DLY_LPPHY_US	300	/* lpphy synthpu_dly time in us */
-
-#define	SYNTHPU_DLY_PHY_US_QT	100	/* QT synthpu_dly time in us */
-
-#ifndef BMAC_DUP_TO_REMOVE
-#define WLC_RM_WAIT_TX_SUSPEND		4	/* Wait Tx Suspend */
-
-#define	ANTCNT			10	/* vanilla M_MAX_ANTCNT value */
-
-#endif				/* BMAC_DUP_TO_REMOVE */
-
-#define DMAREG(wlc_hw, direction, fifonum)	(D11REV_LT(wlc_hw->corerev, 11) ? \
-	((direction == DMA_TX) ? \
-		(void *)&(wlc_hw->regs->fifo.f32regs.dmaregs[fifonum].xmt) : \
-		(void *)&(wlc_hw->regs->fifo.f32regs.dmaregs[fifonum].rcv)) : \
-	((direction == DMA_TX) ? \
-		(void *)&(wlc_hw->regs->fifo.f64regs[fifonum].dmaxmt) : \
-		(void *)&(wlc_hw->regs->fifo.f64regs[fifonum].dmarcv)))
-
-/*
- * The following table lists the buffer memory allocated to xmt fifos in HW.
- * the size is in units of 256bytes(one block), total size is HW dependent
- * ucode has default fifo partition, sw can overwrite if necessary
- *
- * This is documented in twiki under the topic UcodeTxFifo. Please ensure
- * the twiki is updated before making changes.
- */
-
-#define XMTFIFOTBL_STARTREV	20	/* Starting corerev for the fifo size table */
-
-static u16 xmtfifo_sz[][NFIFO] = {
-	{20, 192, 192, 21, 17, 5},	/* corerev 20: 5120, 49152, 49152, 5376, 4352, 1280 */
-	{9, 58, 22, 14, 14, 5},	/* corerev 21: 2304, 14848, 5632, 3584, 3584, 1280 */
-	{20, 192, 192, 21, 17, 5},	/* corerev 22: 5120, 49152, 49152, 5376, 4352, 1280 */
-	{20, 192, 192, 21, 17, 5},	/* corerev 23: 5120, 49152, 49152, 5376, 4352, 1280 */
-	{9, 58, 22, 14, 14, 5},	/* corerev 24: 2304, 14848, 5632, 3584, 3584, 1280 */
-};
-
-static void wlc_clkctl_clk(struct wlc_hw_info *wlc, uint mode);
-static void wlc_coreinit(struct wlc_info *wlc);
-
-/* used by wlc_wakeucode_init() */
-static void wlc_write_inits(struct wlc_hw_info *wlc_hw, const d11init_t *inits);
-static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
-			    const uint nbytes);
-static void wlc_ucode_download(struct wlc_hw_info *wlc);
-static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw);
-
-/* used by wlc_dpc() */
-static bool wlc_bmac_dotxstatus(struct wlc_hw_info *wlc, tx_status_t *txs,
-				u32 s2);
-static bool wlc_bmac_txstatus_corerev4(struct wlc_hw_info *wlc);
-static bool wlc_bmac_txstatus(struct wlc_hw_info *wlc, bool bound, bool *fatal);
-static bool wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound);
-
-/* used by wlc_down() */
-static void wlc_flushqueues(struct wlc_info *wlc);
-
-static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs);
-static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw);
-static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw);
-
-/* Low Level Prototypes */
-static u16 wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset,
-				   u32 sel);
-static void wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset,
-				  u16 v, u32 sel);
-static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme);
-static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw);
-static void wlc_ucode_bsinit(struct wlc_hw_info *wlc_hw);
-static bool wlc_validboardtype(struct wlc_hw_info *wlc);
-static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw);
-static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw);
-static void wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init);
-static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw);
-static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw);
-static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw);
-static u32 wlc_wlintrsoff(struct wlc_info *wlc);
-static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask);
-static void wlc_gpio_init(struct wlc_info *wlc);
-static void wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn,
-				      int len);
-static void wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn,
-				      int len);
-static void wlc_bmac_bsinit(struct wlc_info *wlc, chanspec_t chanspec);
-static u32 wlc_setband_inact(struct wlc_info *wlc, uint bandunit);
-static void wlc_bmac_setband(struct wlc_hw_info *wlc_hw, uint bandunit,
-			     chanspec_t chanspec);
-static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
-					bool shortslot);
-static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw);
-static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw,
-					     u8 rate);
-
-/* === Low Level functions === */
-
-void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot)
-{
-	wlc_hw->shortslot = shortslot;
-
-	if (BAND_2G(wlc_hw->band->bandtype) && wlc_hw->up) {
-		wlc_suspend_mac_and_wait(wlc_hw->wlc);
-		wlc_bmac_update_slot_timing(wlc_hw, shortslot);
-		wlc_enable_mac(wlc_hw->wlc);
-	}
-}
-
-/*
- * Update the slot timing for standard 11b/g (20us slots)
- * or shortslot 11g (9us slots)
- * The PSM needs to be suspended for this call.
- */
-static void wlc_bmac_update_slot_timing(struct wlc_hw_info *wlc_hw,
-					bool shortslot)
-{
-	struct osl_info *osh;
-	d11regs_t *regs;
-
-	osh = wlc_hw->osh;
-	regs = wlc_hw->regs;
-
-	if (shortslot) {
-		/* 11g short slot: 11a timing */
-		W_REG(osh, &regs->ifs_slot, 0x0207);	/* APHY_SLOT_TIME */
-		wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, APHY_SLOT_TIME);
-	} else {
-		/* 11g long slot: 11b timing */
-		W_REG(osh, &regs->ifs_slot, 0x0212);	/* BPHY_SLOT_TIME */
-		wlc_bmac_write_shm(wlc_hw, M_DOT11_SLOT, BPHY_SLOT_TIME);
-	}
-}
-
-static void WLBANDINITFN(wlc_ucode_bsinit) (struct wlc_hw_info *wlc_hw)
-{
-	/* init microcode host flags */
-	wlc_write_mhf(wlc_hw, wlc_hw->band->mhfs);
-
-	/* do band-specific ucode IHR, SHM, and SCR inits */
-	if (D11REV_IS(wlc_hw->corerev, 23)) {
-		if (WLCISNPHY(wlc_hw->band)) {
-			wlc_write_inits(wlc_hw, d11n0bsinitvals16);
-		} else {
-			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
-				 __func__, wlc_hw->unit, wlc_hw->corerev);
-		}
-	} else {
-		if (D11REV_IS(wlc_hw->corerev, 24)) {
-			if (WLCISLCNPHY(wlc_hw->band)) {
-				wlc_write_inits(wlc_hw, d11lcn0bsinitvals24);
-			} else
-				WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
-					 __func__, wlc_hw->unit,
-					 wlc_hw->corerev);
-		} else {
-			WL_ERROR("%s: wl%d: unsupported corerev %d\n",
-				 __func__, wlc_hw->unit, wlc_hw->corerev);
-		}
-	}
-}
-
-/* switch to new band but leave it inactive */
-static u32 WLBANDINITFN(wlc_setband_inact) (struct wlc_info *wlc, uint bandunit)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	u32 macintmask;
-	u32 tmp;
-
-	WL_TRACE("wl%d: wlc_setband_inact\n", wlc_hw->unit);
-
-	ASSERT(bandunit != wlc_hw->band->bandunit);
-	ASSERT(si_iscoreup(wlc_hw->sih));
-	ASSERT((R_REG(wlc_hw->osh, &wlc_hw->regs->maccontrol) & MCTL_EN_MAC) ==
-	       0);
-
-	/* disable interrupts */
-	macintmask = wl_intrsoff(wlc->wl);
-
-	/* radio off */
-	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
-	ASSERT(wlc_hw->clk);
-
-	if (D11REV_LT(wlc_hw->corerev, 17))
-		tmp = R_REG(wlc_hw->osh, &wlc_hw->regs->maccontrol);
-
-	wlc_bmac_core_phy_clk(wlc_hw, OFF);
-
-	wlc_setxband(wlc_hw, bandunit);
-
-	return macintmask;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-static bool BCMFASTPATH
-wlc_bmac_recv(struct wlc_hw_info *wlc_hw, uint fifo, bool bound)
-{
-	struct sk_buff *p;
-	struct sk_buff *head = NULL;
-	struct sk_buff *tail = NULL;
-	uint n = 0;
-	uint bound_limit = bound ? wlc_hw->wlc->pub->tunables->rxbnd : -1;
-	u32 tsf_h, tsf_l;
-	wlc_d11rxhdr_t *wlc_rxhdr = NULL;
-
-	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
-	/* gather received frames */
-	while ((p = dma_rx(wlc_hw->di[fifo]))) {
-
-		if (!tail)
-			head = tail = p;
-		else {
-			tail->prev = p;
-			tail = p;
-		}
-
-		/* !give others some time to run! */
-		if (++n >= bound_limit)
-			break;
-	}
-
-	/* get the TSF REG reading */
-	wlc_bmac_read_tsf(wlc_hw, &tsf_l, &tsf_h);
-
-	/* post more rbufs */
-	dma_rxfill(wlc_hw->di[fifo]);
-
-	/* process each frame */
-	while ((p = head) != NULL) {
-		head = head->prev;
-		p->prev = NULL;
-
-		/* record the tsf_l in wlc_rxd11hdr */
-		wlc_rxhdr = (wlc_d11rxhdr_t *) p->data;
-		wlc_rxhdr->tsf_l = htol32(tsf_l);
-
-		/* compute the RSSI from d11rxhdr and record it in wlc_rxd11hr */
-		wlc_phy_rssi_compute(wlc_hw->band->pi, wlc_rxhdr);
-
-		wlc_recv(wlc_hw->wlc, p);
-	}
-
-	return n >= bound_limit;
-}
-
-/* second-level interrupt processing
- *   Return true if another dpc needs to be re-scheduled. false otherwise.
- *   Param 'bounded' indicates if applicable loops should be bounded.
- */
-bool BCMFASTPATH wlc_dpc(struct wlc_info *wlc, bool bounded)
-{
-	u32 macintstatus;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	bool fatal = false;
-
-	if (DEVICEREMOVED(wlc)) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
-		wl_down(wlc->wl);
-		return false;
-	}
-
-	/* grab and clear the saved software intstatus bits */
-	macintstatus = wlc->macintstatus;
-	wlc->macintstatus = 0;
-
-	WL_TRACE("wl%d: wlc_dpc: macintstatus 0x%x\n",
-		 wlc_hw->unit, macintstatus);
-
-	if (macintstatus & MI_PRQ) {
-		/* Process probe request FIFO */
-		ASSERT(0 && "PRQ Interrupt in non-MBSS");
-	}
-
-	/* BCN template is available */
-	/* ZZZ: Use AP_ACTIVE ? */
-	if (AP_ENAB(wlc->pub) && (!APSTA_ENAB(wlc->pub) || wlc->aps_associated)
-	    && (macintstatus & MI_BCNTPL)) {
-		wlc_update_beacon(wlc);
-	}
-
-	/* PMQ entry addition */
-	if (macintstatus & MI_PMQ) {
-	}
-
-	/* tx status */
-	if (macintstatus & MI_TFS) {
-		if (wlc_bmac_txstatus(wlc->hw, bounded, &fatal))
-			wlc->macintstatus |= MI_TFS;
-		if (fatal) {
-			WL_ERROR("MI_TFS: fatal\n");
-			goto fatal;
-		}
-	}
-
-	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
-		wlc_tbtt(wlc, regs);
-
-	/* ATIM window end */
-	if (macintstatus & MI_ATIMWINEND) {
-		WL_TRACE("wlc_isr: end of ATIM window\n");
-
-		OR_REG(wlc_hw->osh, &regs->maccommand, wlc->qvalid);
-		wlc->qvalid = 0;
-	}
-
-	/* phy tx error */
-	if (macintstatus & MI_PHYTXERR) {
-		WLCNTINCR(wlc->pub->_cnt->txphyerr);
-	}
-
-	/* received data or control frame, MI_DMAINT is indication of RX_FIFO interrupt */
-	if (macintstatus & MI_DMAINT) {
-		if (wlc_bmac_recv(wlc_hw, RX_FIFO, bounded)) {
-			wlc->macintstatus |= MI_DMAINT;
-		}
-	}
-
-	/* TX FIFO suspend/flush completion */
-	if (macintstatus & MI_TXSTOP) {
-		if (wlc_bmac_tx_fifo_suspended(wlc_hw, TX_DATA_FIFO)) {
-			/*      WL_ERROR("dpc: fifo_suspend_comlete\n"); */
-		}
-	}
-
-	/* noise sample collected */
-	if (macintstatus & MI_BG_NOISE) {
-		wlc_phy_noise_sample_intr(wlc_hw->band->pi);
-	}
-
-	if (macintstatus & MI_GP0) {
-		WL_ERROR("wl%d: PSM microcode watchdog fired at %d (seconds). Resetting.\n",
-			 wlc_hw->unit, wlc_hw->now);
-
-		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
-					__func__, wlc_hw->sih->chip,
-					wlc_hw->sih->chiprev);
-
-		WLCNTINCR(wlc->pub->_cnt->psmwds);
-
-		/* big hammer */
-		wl_init(wlc->wl);
-	}
-
-	/* gptimer timeout */
-	if (macintstatus & MI_TO) {
-		W_REG(wlc_hw->osh, &regs->gptimer, 0);
-	}
-
-	if (macintstatus & MI_RFDISABLE) {
-#if defined(BCMDBG)
-		u32 rfd = R_REG(wlc_hw->osh, &regs->phydebug) & PDBG_RFD;
-#endif
-
-		WL_ERROR("wl%d: MAC Detected a change on the RF Disable Input 0x%x\n",
-			 wlc_hw->unit, rfd);
-
-		WLCNTINCR(wlc->pub->_cnt->rfdisable);
-	}
-
-	/* send any enq'd tx packets. Just makes sure to jump start tx */
-	if (!pktq_empty(&wlc->active_queue->q))
-		wlc_send_q(wlc, wlc->active_queue);
-
-	ASSERT(wlc_ps_check(wlc));
-
-	/* make sure the bound indication and the implementation are in sync */
-	ASSERT(bounded == true || wlc->macintstatus == 0);
-
-	/* it isn't done and needs to be resched if macintstatus is non-zero */
-	return wlc->macintstatus != 0;
-
- fatal:
-	wl_init(wlc->wl);
-	return wlc->macintstatus != 0;
-}
-
-/* common low-level watchdog code */
-void wlc_bmac_watchdog(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-
-	WL_TRACE("wl%d: wlc_bmac_watchdog\n", wlc_hw->unit);
-
-	if (!wlc_hw->up)
-		return;
-
-	/* increment second count */
-	wlc_hw->now++;
-
-	/* Check for FIFO error interrupts */
-	wlc_bmac_fifoerrors(wlc_hw);
-
-	/* make sure RX dma has buffers */
-	dma_rxfill(wlc->hw->di[RX_FIFO]);
-	if (D11REV_IS(wlc_hw->corerev, 4)) {
-		dma_rxfill(wlc->hw->di[RX_TXSTATUS_FIFO]);
-	}
-
-	wlc_phy_watchdog(wlc_hw->band->pi);
-}
-
-void
-wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
-		      bool mute, struct txpwr_limits *txpwr)
-{
-	uint bandunit;
-
-	WL_TRACE("wl%d: wlc_bmac_set_chanspec 0x%x\n",
-		 wlc_hw->unit, chanspec);
-
-	wlc_hw->chanspec = chanspec;
-
-	/* Switch bands if necessary */
-	if (NBANDS_HW(wlc_hw) > 1) {
-		bandunit = CHSPEC_WLCBANDUNIT(chanspec);
-		if (wlc_hw->band->bandunit != bandunit) {
-			/* wlc_bmac_setband disables other bandunit,
-			 *  use light band switch if not up yet
-			 */
-			if (wlc_hw->up) {
-				wlc_phy_chanspec_radio_set(wlc_hw->
-							   bandstate[bandunit]->
-							   pi, chanspec);
-				wlc_bmac_setband(wlc_hw, bandunit, chanspec);
-			} else {
-				wlc_setxband(wlc_hw, bandunit);
-			}
-		}
-	}
-
-	wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
-
-	if (!wlc_hw->up) {
-		if (wlc_hw->clk)
-			wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr,
-						  chanspec);
-		wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
-	} else {
-		wlc_phy_chanspec_set(wlc_hw->band->pi, chanspec);
-		wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
-
-		/* Update muting of the channel */
-		wlc_bmac_mute(wlc_hw, mute, 0);
-	}
-}
-
-int wlc_bmac_revinfo_get(struct wlc_hw_info *wlc_hw,
-			 wlc_bmac_revinfo_t *revinfo)
-{
-	si_t *sih = wlc_hw->sih;
-	uint idx;
-
-	revinfo->vendorid = wlc_hw->vendorid;
-	revinfo->deviceid = wlc_hw->deviceid;
-
-	revinfo->boardrev = wlc_hw->boardrev;
-	revinfo->corerev = wlc_hw->corerev;
-	revinfo->sromrev = wlc_hw->sromrev;
-	revinfo->chiprev = sih->chiprev;
-	revinfo->chip = sih->chip;
-	revinfo->chippkg = sih->chippkg;
-	revinfo->boardtype = sih->boardtype;
-	revinfo->boardvendor = sih->boardvendor;
-	revinfo->bustype = sih->bustype;
-	revinfo->buscoretype = sih->buscoretype;
-	revinfo->buscorerev = sih->buscorerev;
-	revinfo->issim = sih->issim;
-
-	revinfo->nbands = NBANDS_HW(wlc_hw);
-
-	for (idx = 0; idx < NBANDS_HW(wlc_hw); idx++) {
-		wlc_hwband_t *band = wlc_hw->bandstate[idx];
-		revinfo->band[idx].bandunit = band->bandunit;
-		revinfo->band[idx].bandtype = band->bandtype;
-		revinfo->band[idx].phytype = band->phytype;
-		revinfo->band[idx].phyrev = band->phyrev;
-		revinfo->band[idx].radioid = band->radioid;
-		revinfo->band[idx].radiorev = band->radiorev;
-		revinfo->band[idx].abgphy_encore = band->abgphy_encore;
-		revinfo->band[idx].anarev = 0;
-
-	}
-	return 0;
-}
-
-int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw, wlc_bmac_state_t *state)
-{
-	state->machwcap = wlc_hw->machwcap;
-
-	return 0;
-}
-
-static bool wlc_bmac_attach_dmapio(struct wlc_info *wlc, uint j, bool wme)
-{
-	uint i;
-	char name[8];
-	/* ucode host flag 2 needed for pio mode, independent of band and fifo */
-	u16 pio_mhf2 = 0;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	uint unit = wlc_hw->unit;
-	wlc_tunables_t *tune = wlc->pub->tunables;
-
-	/* name and offsets for dma_attach */
-	snprintf(name, sizeof(name), "wl%d", unit);
-
-	if (wlc_hw->di[0] == 0) {	/* Init FIFOs */
-		uint addrwidth;
-		int dma_attach_err = 0;
-		struct osl_info *osh = wlc_hw->osh;
-
-		/* Find out the DMA addressing capability and let OS know
-		 * All the channels within one DMA core have 'common-minimum' same
-		 * capability
-		 */
-		addrwidth =
-		    dma_addrwidth(wlc_hw->sih, DMAREG(wlc_hw, DMA_TX, 0));
-
-		if (!wl_alloc_dma_resources(wlc_hw->wlc->wl, addrwidth)) {
-			WL_ERROR("wl%d: wlc_attach: alloc_dma_resources failed\n",
-				 unit);
-			return false;
-		}
-
-		/*
-		 * FIFO 0
-		 * TX: TX_AC_BK_FIFO (TX AC Background data packets)
-		 * RX: RX_FIFO (RX data packets)
-		 */
-		ASSERT(TX_AC_BK_FIFO == 0);
-		ASSERT(RX_FIFO == 0);
-		wlc_hw->di[0] = dma_attach(osh, name, wlc_hw->sih,
-					   (wme ? DMAREG(wlc_hw, DMA_TX, 0) :
-					    NULL), DMAREG(wlc_hw, DMA_RX, 0),
-					   (wme ? tune->ntxd : 0), tune->nrxd,
-					   tune->rxbufsz, -1, tune->nrxbufpost,
-					   WL_HWRXOFF, &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[0]);
-
-		/*
-		 * FIFO 1
-		 * TX: TX_AC_BE_FIFO (TX AC Best-Effort data packets)
-		 *   (legacy) TX_DATA_FIFO (TX data packets)
-		 * RX: UNUSED
-		 */
-		ASSERT(TX_AC_BE_FIFO == 1);
-		ASSERT(TX_DATA_FIFO == 1);
-		wlc_hw->di[1] = dma_attach(osh, name, wlc_hw->sih,
-					   DMAREG(wlc_hw, DMA_TX, 1), NULL,
-					   tune->ntxd, 0, 0, -1, 0, 0,
-					   &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[1]);
-
-		/*
-		 * FIFO 2
-		 * TX: TX_AC_VI_FIFO (TX AC Video data packets)
-		 * RX: UNUSED
-		 */
-		ASSERT(TX_AC_VI_FIFO == 2);
-		wlc_hw->di[2] = dma_attach(osh, name, wlc_hw->sih,
-					   DMAREG(wlc_hw, DMA_TX, 2), NULL,
-					   tune->ntxd, 0, 0, -1, 0, 0,
-					   &wl_msg_level);
-		dma_attach_err |= (NULL == wlc_hw->di[2]);
-		/*
-		 * FIFO 3
-		 * TX: TX_AC_VO_FIFO (TX AC Voice data packets)
-		 *   (legacy) TX_CTL_FIFO (TX control & mgmt packets)
-		 * RX: RX_TXSTATUS_FIFO (transmit-status packets)
-		 *      for corerev < 5 only
-		 */
-		ASSERT(TX_AC_VO_FIFO == 3);
-		ASSERT(TX_CTL_FIFO == 3);
-		if (D11REV_IS(wlc_hw->corerev, 4)) {
-			ASSERT(RX_TXSTATUS_FIFO == 3);
-			wlc_hw->di[3] = dma_attach(osh, name, wlc_hw->sih,
-						   DMAREG(wlc_hw, DMA_TX, 3),
-						   DMAREG(wlc_hw, DMA_RX, 3),
-						   tune->ntxd, tune->nrxd,
-						   sizeof(tx_status_t), -1,
-						   tune->nrxbufpost, 0,
-						   &wl_msg_level);
-			dma_attach_err |= (NULL == wlc_hw->di[3]);
-		} else {
-			wlc_hw->di[3] = dma_attach(osh, name, wlc_hw->sih,
-						   DMAREG(wlc_hw, DMA_TX, 3),
-						   NULL, tune->ntxd, 0, 0, -1,
-						   0, 0, &wl_msg_level);
-			dma_attach_err |= (NULL == wlc_hw->di[3]);
-		}
-/* Cleaner to leave this as if with AP defined */
-
-		if (dma_attach_err) {
-			WL_ERROR("wl%d: wlc_attach: dma_attach failed\n", unit);
-			return false;
-		}
-
-		/* get pointer to dma engine tx flow control variable */
-		for (i = 0; i < NFIFO; i++)
-			if (wlc_hw->di[i])
-				wlc_hw->txavail[i] =
-				    (uint *) dma_getvar(wlc_hw->di[i],
-							"&txavail");
-	}
-
-	/* initial ucode host flags */
-	wlc_mhfdef(wlc, wlc_hw->band->mhfs, pio_mhf2);
-
-	return true;
-}
-
-static void wlc_bmac_detach_dmapio(struct wlc_hw_info *wlc_hw)
-{
-	uint j;
-
-	for (j = 0; j < NFIFO; j++) {
-		if (wlc_hw->di[j]) {
-			dma_detach(wlc_hw->di[j]);
-			wlc_hw->di[j] = NULL;
-		}
-	}
-}
-
-/* low level attach
- *    run backplane attach, init nvram
- *    run phy attach
- *    initialize software state for each core and band
- *    put the whole chip in reset(driver down state), no clock
- */
-int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device, uint unit,
-		    bool piomode, struct osl_info *osh, void *regsva,
-		    uint bustype, void *btparam)
-{
-	struct wlc_hw_info *wlc_hw;
-	d11regs_t *regs;
-	char *macaddr = NULL;
-	char *vars;
-	uint err = 0;
-	uint j;
-	bool wme = false;
-	shared_phy_params_t sha_params;
-
-	WL_TRACE("wl%d: wlc_bmac_attach: vendor 0x%x device 0x%x\n",
-		 unit, vendor, device);
-
-	ASSERT(sizeof(wlc_d11rxhdr_t) <= WL_HWRXOFF);
-
-	wme = true;
-
-	wlc_hw = wlc->hw;
-	wlc_hw->wlc = wlc;
-	wlc_hw->unit = unit;
-	wlc_hw->osh = osh;
-	wlc_hw->band = wlc_hw->bandstate[0];
-	wlc_hw->_piomode = piomode;
-
-	/* populate struct wlc_hw_info with default values  */
-	wlc_bmac_info_init(wlc_hw);
-
-	/*
-	 * Do the hardware portion of the attach.
-	 * Also initialize software state that depends on the particular hardware
-	 * we are running.
-	 */
-	wlc_hw->sih = si_attach((uint) device, osh, regsva, bustype, btparam,
-				&wlc_hw->vars, &wlc_hw->vars_size);
-	if (wlc_hw->sih == NULL) {
-		WL_ERROR("wl%d: wlc_bmac_attach: si_attach failed\n", unit);
-		err = 11;
-		goto fail;
-	}
-	vars = wlc_hw->vars;
-
-	/*
-	 * Get vendid/devid nvram overwrites, which could be different
-	 * than those the BIOS recognizes for devices on PCMCIA_BUS,
-	 * SDIO_BUS, and SROMless devices on PCI_BUS.
-	 */
-#ifdef BCMBUSTYPE
-	bustype = BCMBUSTYPE;
-#endif
-	if (bustype != SI_BUS) {
-		char *var;
-
-		var = getvar(vars, "vendid");
-		if (var) {
-			vendor = (u16) simple_strtoul(var, NULL, 0);
-			WL_ERROR("Overriding vendor id = 0x%x\n", vendor);
-		}
-		var = getvar(vars, "devid");
-		if (var) {
-			u16 devid = (u16) simple_strtoul(var, NULL, 0);
-			if (devid != 0xffff) {
-				device = devid;
-				WL_ERROR("Overriding device id = 0x%x\n",
-					 device);
-			}
-		}
-
-		/* verify again the device is supported */
-		if (!wlc_chipmatch(vendor, device)) {
-			WL_ERROR("wl%d: wlc_bmac_attach: Unsupported vendor/device (0x%x/0x%x)\n",
-				 unit, vendor, device);
-			err = 12;
-			goto fail;
-		}
-	}
-
-	wlc_hw->vendorid = vendor;
-	wlc_hw->deviceid = device;
-
-	/* set bar0 window to point at D11 core */
-	wlc_hw->regs = (d11regs_t *) si_setcore(wlc_hw->sih, D11_CORE_ID, 0);
-	wlc_hw->corerev = si_corerev(wlc_hw->sih);
-
-	regs = wlc_hw->regs;
-
-	wlc->regs = wlc_hw->regs;
-
-	/* validate chip, chiprev and corerev */
-	if (!wlc_isgoodchip(wlc_hw)) {
-		err = 13;
-		goto fail;
-	}
-
-	/* initialize power control registers */
-	si_clkctl_init(wlc_hw->sih);
-
-	/* request fastclock and force fastclock for the rest of attach
-	 * bring the d11 core out of reset.
-	 *   For PMU chips, the first wlc_clkctl_clk is no-op since core-clk is still false;
-	 *   But it will be called again inside wlc_corereset, after d11 is out of reset.
-	 */
-	wlc_clkctl_clk(wlc_hw, CLK_FAST);
-	wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-
-	if (!wlc_bmac_validate_chip_access(wlc_hw)) {
-		WL_ERROR("wl%d: wlc_bmac_attach: validate_chip_access failed\n",
-			 unit);
-		err = 14;
-		goto fail;
-	}
-
-	/* get the board rev, used just below */
-	j = getintvar(vars, "boardrev");
-	/* promote srom boardrev of 0xFF to 1 */
-	if (j == BOARDREV_PROMOTABLE)
-		j = BOARDREV_PROMOTED;
-	wlc_hw->boardrev = (u16) j;
-	if (!wlc_validboardtype(wlc_hw)) {
-		WL_ERROR("wl%d: wlc_bmac_attach: Unsupported Broadcom board type (0x%x)" " or revision level (0x%x)\n",
-			 unit, wlc_hw->sih->boardtype, wlc_hw->boardrev);
-		err = 15;
-		goto fail;
-	}
-	wlc_hw->sromrev = (u8) getintvar(vars, "sromrev");
-	wlc_hw->boardflags = (u32) getintvar(vars, "boardflags");
-	wlc_hw->boardflags2 = (u32) getintvar(vars, "boardflags2");
-
-	if (D11REV_LE(wlc_hw->corerev, 4)
-	    || (wlc_hw->boardflags & BFL_NOPLLDOWN))
-		wlc_bmac_pllreq(wlc_hw, true, WLC_PLLREQ_SHARED);
-
-	if ((wlc_hw->sih->bustype == PCI_BUS)
-	    && (si_pci_war16165(wlc_hw->sih)))
-		wlc->war16165 = true;
-
-	/* check device id(srom, nvram etc.) to set bands */
-	if (wlc_hw->deviceid == BCM43224_D11N_ID) {
-		/* Dualband boards */
-		wlc_hw->_nbands = 2;
-	} else
-		wlc_hw->_nbands = 1;
-
-	if ((wlc_hw->sih->chip == BCM43225_CHIP_ID))
-		wlc_hw->_nbands = 1;
-
-	/* BMAC_NOTE: remove init of pub values when wlc_attach() unconditionally does the
-	 * init of these values
-	 */
-	wlc->vendorid = wlc_hw->vendorid;
-	wlc->deviceid = wlc_hw->deviceid;
-	wlc->pub->sih = wlc_hw->sih;
-	wlc->pub->corerev = wlc_hw->corerev;
-	wlc->pub->sromrev = wlc_hw->sromrev;
-	wlc->pub->boardrev = wlc_hw->boardrev;
-	wlc->pub->boardflags = wlc_hw->boardflags;
-	wlc->pub->boardflags2 = wlc_hw->boardflags2;
-	wlc->pub->_nbands = wlc_hw->_nbands;
-
-	wlc_hw->physhim = wlc_phy_shim_attach(wlc_hw, wlc->wl, wlc);
-
-	if (wlc_hw->physhim == NULL) {
-		WL_ERROR("wl%d: wlc_bmac_attach: wlc_phy_shim_attach failed\n",
-			 unit);
-		err = 25;
-		goto fail;
-	}
-
-	/* pass all the parameters to wlc_phy_shared_attach in one struct */
-	sha_params.osh = osh;
-	sha_params.sih = wlc_hw->sih;
-	sha_params.physhim = wlc_hw->physhim;
-	sha_params.unit = unit;
-	sha_params.corerev = wlc_hw->corerev;
-	sha_params.vars = vars;
-	sha_params.vid = wlc_hw->vendorid;
-	sha_params.did = wlc_hw->deviceid;
-	sha_params.chip = wlc_hw->sih->chip;
-	sha_params.chiprev = wlc_hw->sih->chiprev;
-	sha_params.chippkg = wlc_hw->sih->chippkg;
-	sha_params.sromrev = wlc_hw->sromrev;
-	sha_params.boardtype = wlc_hw->sih->boardtype;
-	sha_params.boardrev = wlc_hw->boardrev;
-	sha_params.boardvendor = wlc_hw->sih->boardvendor;
-	sha_params.boardflags = wlc_hw->boardflags;
-	sha_params.boardflags2 = wlc_hw->boardflags2;
-	sha_params.bustype = wlc_hw->sih->bustype;
-	sha_params.buscorerev = wlc_hw->sih->buscorerev;
-
-	/* alloc and save pointer to shared phy state area */
-	wlc_hw->phy_sh = wlc_phy_shared_attach(&sha_params);
-	if (!wlc_hw->phy_sh) {
-		err = 16;
-		goto fail;
-	}
-
-	/* initialize software state for each core and band */
-	for (j = 0; j < NBANDS_HW(wlc_hw); j++) {
-		/*
-		 * band0 is always 2.4Ghz
-		 * band1, if present, is 5Ghz
-		 */
-
-		/* So if this is a single band 11a card, use band 1 */
-		if (IS_SINGLEBAND_5G(wlc_hw->deviceid))
-			j = BAND_5G_INDEX;
-
-		wlc_setxband(wlc_hw, j);
-
-		wlc_hw->band->bandunit = j;
-		wlc_hw->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
-		wlc->band->bandunit = j;
-		wlc->band->bandtype = j ? WLC_BAND_5G : WLC_BAND_2G;
-		wlc->core->coreidx = si_coreidx(wlc_hw->sih);
-
-		if (D11REV_GE(wlc_hw->corerev, 13)) {
-			wlc_hw->machwcap = R_REG(wlc_hw->osh, &regs->machwcap);
-			wlc_hw->machwcap_backup = wlc_hw->machwcap;
-		}
-
-		/* init tx fifo size */
-		ASSERT((wlc_hw->corerev - XMTFIFOTBL_STARTREV) <
-		       ARRAY_SIZE(xmtfifo_sz));
-		wlc_hw->xmtfifo_sz =
-		    xmtfifo_sz[(wlc_hw->corerev - XMTFIFOTBL_STARTREV)];
-
-		/* Get a phy for this band */
-		wlc_hw->band->pi = wlc_phy_attach(wlc_hw->phy_sh,
-			(void *)regs, wlc_hw->band->bandtype, vars);
-		if (wlc_hw->band->pi == NULL) {
-			WL_ERROR("wl%d: wlc_bmac_attach: wlc_phy_attach failed\n",
-				 unit);
-			err = 17;
-			goto fail;
-		}
-
-		wlc_phy_machwcap_set(wlc_hw->band->pi, wlc_hw->machwcap);
-
-		wlc_phy_get_phyversion(wlc_hw->band->pi, &wlc_hw->band->phytype,
-				       &wlc_hw->band->phyrev,
-				       &wlc_hw->band->radioid,
-				       &wlc_hw->band->radiorev);
-		wlc_hw->band->abgphy_encore =
-		    wlc_phy_get_encore(wlc_hw->band->pi);
-		wlc->band->abgphy_encore = wlc_phy_get_encore(wlc_hw->band->pi);
-		wlc_hw->band->core_flags =
-		    wlc_phy_get_coreflags(wlc_hw->band->pi);
-
-		/* verify good phy_type & supported phy revision */
-		if (WLCISNPHY(wlc_hw->band)) {
-			if (NCONF_HAS(wlc_hw->band->phyrev))
-				goto good_phy;
-			else
-				goto bad_phy;
-		} else if (WLCISLCNPHY(wlc_hw->band)) {
-			if (LCNCONF_HAS(wlc_hw->band->phyrev))
-				goto good_phy;
-			else
-				goto bad_phy;
-		} else {
- bad_phy:
-			WL_ERROR("wl%d: wlc_bmac_attach: unsupported phy type/rev (%d/%d)\n",
-				 unit,
-				 wlc_hw->band->phytype, wlc_hw->band->phyrev);
-			err = 18;
-			goto fail;
-		}
-
- good_phy:
-		/* BMAC_NOTE: wlc->band->pi should not be set below and should be done in the
-		 * high level attach. However we can not make that change until all low level access
-		 * is changed to wlc_hw->band->pi. Instead do the wlc->band->pi init below, keeping
-		 * wlc_hw->band->pi as well for incremental update of low level fns, and cut over
-		 * low only init when all fns updated.
-		 */
-		wlc->band->pi = wlc_hw->band->pi;
-		wlc->band->phytype = wlc_hw->band->phytype;
-		wlc->band->phyrev = wlc_hw->band->phyrev;
-		wlc->band->radioid = wlc_hw->band->radioid;
-		wlc->band->radiorev = wlc_hw->band->radiorev;
-
-		/* default contention windows size limits */
-		wlc_hw->band->CWmin = APHY_CWMIN;
-		wlc_hw->band->CWmax = PHY_CWMAX;
-
-		if (!wlc_bmac_attach_dmapio(wlc, j, wme)) {
-			err = 19;
-			goto fail;
-		}
-	}
-
-	/* disable core to match driver "down" state */
-	wlc_coredisable(wlc_hw);
-
-	/* Match driver "down" state */
-	if (wlc_hw->sih->bustype == PCI_BUS)
-		si_pci_down(wlc_hw->sih);
-
-	/* register sb interrupt callback functions */
-	si_register_intr_callback(wlc_hw->sih, (void *)wlc_wlintrsoff,
-				  (void *)wlc_wlintrsrestore, NULL, wlc);
-
-	/* turn off pll and xtal to match driver "down" state */
-	wlc_bmac_xtal(wlc_hw, OFF);
-
-	/* *********************************************************************
-	 * The hardware is in the DOWN state at this point. D11 core
-	 * or cores are in reset with clocks off, and the board PLLs
-	 * are off if possible.
-	 *
-	 * Beyond this point, wlc->sbclk == false and chip registers
-	 * should not be touched.
-	 *********************************************************************
-	 */
-
-	/* init etheraddr state variables */
-	macaddr = wlc_get_macaddr(wlc_hw);
-	if (macaddr == NULL) {
-		WL_ERROR("wl%d: wlc_bmac_attach: macaddr not found\n", unit);
-		err = 21;
-		goto fail;
-	}
-	bcm_ether_atoe(macaddr, &wlc_hw->etheraddr);
-	if (is_broadcast_ether_addr(wlc_hw->etheraddr.octet) ||
-	    is_zero_ether_addr(wlc_hw->etheraddr.octet)) {
-		WL_ERROR("wl%d: wlc_bmac_attach: bad macaddr %s\n",
-			 unit, macaddr);
-		err = 22;
-		goto fail;
-	}
-
-	WL_ERROR("%s:: deviceid 0x%x nbands %d board 0x%x macaddr: %s\n",
-		 __func__, wlc_hw->deviceid, wlc_hw->_nbands,
-		 wlc_hw->sih->boardtype, macaddr);
-
-	return err;
-
- fail:
-	WL_ERROR("wl%d: wlc_bmac_attach: failed with err %d\n", unit, err);
-	return err;
-}
-
-/*
- * Initialize wlc_info default values ...
- * may get overrides later in this function
- *  BMAC_NOTES, move low out and resolve the dangling ones
- */
-void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw)
-{
-	struct wlc_info *wlc = wlc_hw->wlc;
-
-	/* set default sw macintmask value */
-	wlc->defmacintmask = DEF_MACINTMASK;
-
-	/* various 802.11g modes */
-	wlc_hw->shortslot = false;
-
-	wlc_hw->SFBL = RETRY_SHORT_FB;
-	wlc_hw->LFBL = RETRY_LONG_FB;
-
-	/* default mac retry limits */
-	wlc_hw->SRL = RETRY_SHORT_DEF;
-	wlc_hw->LRL = RETRY_LONG_DEF;
-	wlc_hw->chanspec = CH20MHZ_CHSPEC(1);
-}
-
-/*
- * low level detach
- */
-int wlc_bmac_detach(struct wlc_info *wlc)
-{
-	uint i;
-	wlc_hwband_t *band;
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	int callbacks;
-
-	callbacks = 0;
-
-	if (wlc_hw->sih) {
-		/* detach interrupt sync mechanism since interrupt is disabled and per-port
-		 * interrupt object may has been freed. this must be done before sb core switch
-		 */
-		si_deregister_intr_callback(wlc_hw->sih);
-
-		if (wlc_hw->sih->bustype == PCI_BUS)
-			si_pci_sleep(wlc_hw->sih);
-	}
-
-	wlc_bmac_detach_dmapio(wlc_hw);
-
-	band = wlc_hw->band;
-	for (i = 0; i < NBANDS_HW(wlc_hw); i++) {
-		if (band->pi) {
-			/* Detach this band's phy */
-			wlc_phy_detach(band->pi);
-			band->pi = NULL;
-		}
-		band = wlc_hw->bandstate[OTHERBANDUNIT(wlc)];
-	}
-
-	/* Free shared phy state */
-	wlc_phy_shared_detach(wlc_hw->phy_sh);
-
-	wlc_phy_shim_detach(wlc_hw->physhim);
-
-	/* free vars */
-	if (wlc_hw->vars) {
-		kfree(wlc_hw->vars);
-		wlc_hw->vars = NULL;
-	}
-
-	if (wlc_hw->sih) {
-		si_detach(wlc_hw->sih);
-		wlc_hw->sih = NULL;
-	}
-
-	return callbacks;
-
-}
-
-void wlc_bmac_reset(struct wlc_hw_info *wlc_hw)
-{
-	WL_TRACE("wl%d: wlc_bmac_reset\n", wlc_hw->unit);
-
-	WLCNTINCR(wlc_hw->wlc->pub->_cnt->reset);
-
-	/* reset the core */
-	if (!DEVICEREMOVED(wlc_hw->wlc))
-		wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-
-	/* purge the dma rings */
-	wlc_flushqueues(wlc_hw->wlc);
-
-	wlc_reset_bmac_done(wlc_hw->wlc);
-}
-
-void
-wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
-			  bool mute) {
-	u32 macintmask;
-	bool fastclk;
-	struct wlc_info *wlc = wlc_hw->wlc;
-
-	WL_TRACE("wl%d: wlc_bmac_init\n", wlc_hw->unit);
-
-	/* request FAST clock if not on */
-	fastclk = wlc_hw->forcefastclk;
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	/* disable interrupts */
-	macintmask = wl_intrsoff(wlc->wl);
-
-	/* set up the specified band and chanspec */
-	wlc_setxband(wlc_hw, CHSPEC_WLCBANDUNIT(chanspec));
-	wlc_phy_chanspec_radio_set(wlc_hw->band->pi, chanspec);
-
-	/* do one-time phy inits and calibration */
-	wlc_phy_cal_init(wlc_hw->band->pi);
-
-	/* core-specific initialization */
-	wlc_coreinit(wlc);
-
-	/* suspend the tx fifos and mute the phy for preism cac time */
-	if (mute)
-		wlc_bmac_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
-
-	/* band-specific inits */
-	wlc_bmac_bsinit(wlc, chanspec);
-
-	/* restore macintmask */
-	wl_intrsrestore(wlc->wl, macintmask);
-
-	/* seed wake_override with WLC_WAKE_OVERRIDE_MACSUSPEND since the mac is suspended
-	 * and wlc_enable_mac() will clear this override bit.
-	 */
-	mboolset(wlc_hw->wake_override, WLC_WAKE_OVERRIDE_MACSUSPEND);
-
-	/*
-	 * initialize mac_suspend_depth to 1 to match ucode initial suspended state
-	 */
-	wlc_hw->mac_suspend_depth = 1;
-
-	/* restore the clk */
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw)
-{
-	uint coremask;
-
-	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
-
-	ASSERT(wlc_hw->wlc->pub->hw_up && wlc_hw->wlc->macintmask == 0);
-
-	/*
-	 * Enable pll and xtal, initialize the power control registers,
-	 * and force fastclock for the remainder of wlc_up().
-	 */
-	wlc_bmac_xtal(wlc_hw, ON);
-	si_clkctl_init(wlc_hw->sih);
-	wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	/*
-	 * Configure pci/pcmcia here instead of in wlc_attach()
-	 * to allow mfg hotswap:  down, hotswap (chip power cycle), up.
-	 */
-	coremask = (1 << wlc_hw->wlc->core->coreidx);
-
-	if (wlc_hw->sih->bustype == PCI_BUS)
-		si_pci_setup(wlc_hw->sih, coremask);
-
-	ASSERT(si_coreid(wlc_hw->sih) == D11_CORE_ID);
-
-	/*
-	 * Need to read the hwradio status here to cover the case where the system
-	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
-	 */
-	if (wlc_bmac_radio_read_hwdisabled(wlc_hw)) {
-		/* put SB PCI in down state again */
-		if (wlc_hw->sih->bustype == PCI_BUS)
-			si_pci_down(wlc_hw->sih);
-		wlc_bmac_xtal(wlc_hw, OFF);
-		return BCME_RADIOOFF;
-	}
-
-	if (wlc_hw->sih->bustype == PCI_BUS)
-		si_pci_up(wlc_hw->sih);
-
-	/* reset the d11 core */
-	wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-
-	return 0;
-}
-
-int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw)
-{
-	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
-
-	wlc_hw->up = true;
-	wlc_phy_hw_state_upd(wlc_hw->band->pi, true);
-
-	/* FULLY enable dynamic power control and d11 core interrupt */
-	wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-	ASSERT(wlc_hw->wlc->macintmask == 0);
-	wl_intrson(wlc_hw->wlc->wl);
-	return 0;
-}
-
-int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw)
-{
-	bool dev_gone;
-	uint callbacks = 0;
-
-	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
-
-	if (!wlc_hw->up)
-		return callbacks;
-
-	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
-	/* disable interrupts */
-	if (dev_gone)
-		wlc_hw->wlc->macintmask = 0;
-	else {
-		/* now disable interrupts */
-		wl_intrsoff(wlc_hw->wlc->wl);
-
-		/* ensure we're running on the pll clock again */
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-	}
-	/* down phy at the last of this stage */
-	callbacks += wlc_phy_down(wlc_hw->band->pi);
-
-	return callbacks;
-}
-
-int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw)
-{
-	uint callbacks = 0;
-	bool dev_gone;
-
-	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
-
-	if (!wlc_hw->up)
-		return callbacks;
-
-	wlc_hw->up = false;
-	wlc_phy_hw_state_upd(wlc_hw->band->pi, false);
-
-	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
-	if (dev_gone) {
-		wlc_hw->sbclk = false;
-		wlc_hw->clk = false;
-		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-
-		/* reclaim any posted packets */
-		wlc_flushqueues(wlc_hw->wlc);
-	} else {
-
-		/* Reset and disable the core */
-		if (si_iscoreup(wlc_hw->sih)) {
-			if (R_REG(wlc_hw->osh, &wlc_hw->regs->maccontrol) &
-			    MCTL_EN_MAC)
-				wlc_suspend_mac_and_wait(wlc_hw->wlc);
-			callbacks += wl_reset(wlc_hw->wlc->wl);
-			wlc_coredisable(wlc_hw);
-		}
-
-		/* turn off primary xtal and pll */
-		if (!wlc_hw->noreset) {
-			if (wlc_hw->sih->bustype == PCI_BUS)
-				si_pci_down(wlc_hw->sih);
-			wlc_bmac_xtal(wlc_hw, OFF);
-		}
-	}
-
-	return callbacks;
-}
-
-void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw)
-{
-	if (D11REV_IS(wlc_hw->corerev, 4))	/* no slowclock */
-		udelay(5);
-	else {
-		/* delay before first read of ucode state */
-		udelay(40);
-
-		/* wait until ucode is no longer asleep */
-		SPINWAIT((wlc_bmac_read_shm(wlc_hw, M_UCODE_DBGST) ==
-			  DBGST_ASLEEP), wlc_hw->wlc->fastpwrup_dly);
-	}
-
-	ASSERT(wlc_bmac_read_shm(wlc_hw, M_UCODE_DBGST) != DBGST_ASLEEP);
-}
-
-void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw, struct ether_addr *ea)
-{
-	bcopy(&wlc_hw->etheraddr, ea, ETH_ALEN);
-}
-
-void wlc_bmac_set_hw_etheraddr(struct wlc_hw_info *wlc_hw,
-			       struct ether_addr *ea)
-{
-	bcopy(ea, &wlc_hw->etheraddr, ETH_ALEN);
-}
-
-int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw)
-{
-	return wlc_hw->band->bandtype;
-}
-
-void *wlc_cur_phy(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	return (void *)wlc_hw->band->pi;
-}
-
-/* control chip clock to save power, enable dynamic clock or force fast clock */
-static void wlc_clkctl_clk(struct wlc_hw_info *wlc_hw, uint mode)
-{
-	if (PMUCTL_ENAB(wlc_hw->sih)) {
-		/* new chips with PMU, CCS_FORCEHT will distribute the HT clock on backplane,
-		 *  but mac core will still run on ALP(not HT) when it enters powersave mode,
-		 *      which means the FCA bit may not be set.
-		 *      should wakeup mac if driver wants it to run on HT.
-		 */
-
-		if (wlc_hw->clk) {
-			if (mode == CLK_FAST) {
-				OR_REG(wlc_hw->osh, &wlc_hw->regs->clk_ctl_st,
-				       CCS_FORCEHT);
-
-				udelay(64);
-
-				SPINWAIT(((R_REG
-					   (wlc_hw->osh,
-					    &wlc_hw->regs->
-					    clk_ctl_st) & CCS_HTAVAIL) == 0),
-					 PMU_MAX_TRANSITION_DLY);
-				ASSERT(R_REG
-				       (wlc_hw->osh,
-					&wlc_hw->regs->
-					clk_ctl_st) & CCS_HTAVAIL);
-			} else {
-				if ((wlc_hw->sih->pmurev == 0) &&
-				    (R_REG
-				     (wlc_hw->osh,
-				      &wlc_hw->regs->
-				      clk_ctl_st) & (CCS_FORCEHT | CCS_HTAREQ)))
-					SPINWAIT(((R_REG
-						   (wlc_hw->osh,
-						    &wlc_hw->regs->
-						    clk_ctl_st) & CCS_HTAVAIL)
-						  == 0),
-						 PMU_MAX_TRANSITION_DLY);
-				AND_REG(wlc_hw->osh, &wlc_hw->regs->clk_ctl_st,
-					~CCS_FORCEHT);
-			}
-		}
-		wlc_hw->forcefastclk = (mode == CLK_FAST);
-	} else {
-		bool wakeup_ucode;
-
-		/* old chips w/o PMU, force HT through cc,
-		 * then use FCA to verify mac is running fast clock
-		 */
-
-		wakeup_ucode = D11REV_LT(wlc_hw->corerev, 9);
-
-		if (wlc_hw->up && wakeup_ucode)
-			wlc_ucode_wake_override_set(wlc_hw,
-						    WLC_WAKE_OVERRIDE_CLKCTL);
-
-		wlc_hw->forcefastclk = si_clkctl_cc(wlc_hw->sih, mode);
-
-		if (D11REV_LT(wlc_hw->corerev, 11)) {
-			/* ucode WAR for old chips */
-			if (wlc_hw->forcefastclk)
-				wlc_bmac_mhf(wlc_hw, MHF1, MHF1_FORCEFASTCLK,
-					     MHF1_FORCEFASTCLK, WLC_BAND_ALL);
-			else
-				wlc_bmac_mhf(wlc_hw, MHF1, MHF1_FORCEFASTCLK, 0,
-					     WLC_BAND_ALL);
-		}
-
-		/* check fast clock is available (if core is not in reset) */
-		if (D11REV_GT(wlc_hw->corerev, 4) && wlc_hw->forcefastclk
-		    && wlc_hw->clk)
-			ASSERT(si_core_sflags(wlc_hw->sih, 0, 0) & SISF_FCLKA);
-
-		/* keep the ucode wake bit on if forcefastclk is on
-		 * since we do not want ucode to put us back to slow clock
-		 * when it dozes for PM mode.
-		 * Code below matches the wake override bit with current forcefastclk state
-		 * Only setting bit in wake_override instead of waking ucode immediately
-		 * since old code (wlc.c 1.4499) had this behavior. Older code set
-		 * wlc->forcefastclk but only had the wake happen if the wakup_ucode work
-		 * (protected by an up check) was executed just below.
-		 */
-		if (wlc_hw->forcefastclk)
-			mboolset(wlc_hw->wake_override,
-				 WLC_WAKE_OVERRIDE_FORCEFAST);
-		else
-			mboolclr(wlc_hw->wake_override,
-				 WLC_WAKE_OVERRIDE_FORCEFAST);
-
-		/* ok to clear the wakeup now */
-		if (wlc_hw->up && wakeup_ucode)
-			wlc_ucode_wake_override_clear(wlc_hw,
-						      WLC_WAKE_OVERRIDE_CLKCTL);
-	}
-}
-
-/* set initial host flags value */
-static void
-wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-
-	memset(mhfs, 0, MHFMAX * sizeof(u16));
-
-	mhfs[MHF2] |= mhf2_init;
-
-	/* prohibit use of slowclock on multifunction boards */
-	if (wlc_hw->boardflags & BFL_NOPLLDOWN)
-		mhfs[MHF1] |= MHF1_FORCEFASTCLK;
-
-	if (WLCISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 2)) {
-		mhfs[MHF2] |= MHF2_NPHY40MHZ_WAR;
-		mhfs[MHF1] |= MHF1_IQSWAP_WAR;
-	}
-}
-
-/* set or clear ucode host flag bits
- * it has an optimization for no-change write
- * it only writes through shared memory when the core has clock;
- * pre-CLK changes should use wlc_write_mhf to get around the optimization
- *
- *
- * bands values are: WLC_BAND_AUTO <--- Current band only
- *                   WLC_BAND_5G   <--- 5G band only
- *                   WLC_BAND_2G   <--- 2G band only
- *                   WLC_BAND_ALL  <--- All bands
- */
-void
-wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask, u16 val,
-	     int bands)
-{
-	u16 save;
-	u16 addr[MHFMAX] = {
-		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
-		M_HOST_FLAGS5
-	};
-	wlc_hwband_t *band;
-
-	ASSERT((val & ~mask) == 0);
-	ASSERT(idx < MHFMAX);
-	ASSERT(ARRAY_SIZE(addr) == MHFMAX);
-
-	switch (bands) {
-		/* Current band only or all bands,
-		 * then set the band to current band
-		 */
-	case WLC_BAND_AUTO:
-	case WLC_BAND_ALL:
-		band = wlc_hw->band;
-		break;
-	case WLC_BAND_5G:
-		band = wlc_hw->bandstate[BAND_5G_INDEX];
-		break;
-	case WLC_BAND_2G:
-		band = wlc_hw->bandstate[BAND_2G_INDEX];
-		break;
-	default:
-		ASSERT(0);
-		band = NULL;
-	}
-
-	if (band) {
-		save = band->mhfs[idx];
-		band->mhfs[idx] = (band->mhfs[idx] & ~mask) | val;
-
-		/* optimization: only write through if changed, and
-		 * changed band is the current band
-		 */
-		if (wlc_hw->clk && (band->mhfs[idx] != save)
-		    && (band == wlc_hw->band))
-			wlc_bmac_write_shm(wlc_hw, addr[idx],
-					   (u16) band->mhfs[idx]);
-	}
-
-	if (bands == WLC_BAND_ALL) {
-		wlc_hw->bandstate[0]->mhfs[idx] =
-		    (wlc_hw->bandstate[0]->mhfs[idx] & ~mask) | val;
-		wlc_hw->bandstate[1]->mhfs[idx] =
-		    (wlc_hw->bandstate[1]->mhfs[idx] & ~mask) | val;
-	}
-}
-
-u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands)
-{
-	wlc_hwband_t *band;
-	ASSERT(idx < MHFMAX);
-
-	switch (bands) {
-	case WLC_BAND_AUTO:
-		band = wlc_hw->band;
-		break;
-	case WLC_BAND_5G:
-		band = wlc_hw->bandstate[BAND_5G_INDEX];
-		break;
-	case WLC_BAND_2G:
-		band = wlc_hw->bandstate[BAND_2G_INDEX];
-		break;
-	default:
-		ASSERT(0);
-		band = NULL;
-	}
-
-	if (!band)
-		return 0;
-
-	return band->mhfs[idx];
-}
-
-static void wlc_write_mhf(struct wlc_hw_info *wlc_hw, u16 *mhfs)
-{
-	u8 idx;
-	u16 addr[] = {
-		M_HOST_FLAGS1, M_HOST_FLAGS2, M_HOST_FLAGS3, M_HOST_FLAGS4,
-		M_HOST_FLAGS5
-	};
-
-	ASSERT(ARRAY_SIZE(addr) == MHFMAX);
-
-	for (idx = 0; idx < MHFMAX; idx++) {
-		wlc_bmac_write_shm(wlc_hw, addr[idx], mhfs[idx]);
-	}
-}
-
-/* set the maccontrol register to desired reset state and
- * initialize the sw cache of the register
- */
-static void wlc_mctrl_reset(struct wlc_hw_info *wlc_hw)
-{
-	/* IHR accesses are always enabled, PSM disabled, HPS off and WAKE on */
-	wlc_hw->maccontrol = 0;
-	wlc_hw->suspended_fifos = 0;
-	wlc_hw->wake_override = 0;
-	wlc_hw->mute_override = 0;
-	wlc_bmac_mctrl(wlc_hw, ~0, MCTL_IHR_EN | MCTL_WAKE);
-}
-
-/* set or clear maccontrol bits */
-void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val)
-{
-	u32 maccontrol;
-	u32 new_maccontrol;
-
-	ASSERT((val & ~mask) == 0);
-
-	maccontrol = wlc_hw->maccontrol;
-	new_maccontrol = (maccontrol & ~mask) | val;
-
-	/* if the new maccontrol value is the same as the old, nothing to do */
-	if (new_maccontrol == maccontrol)
-		return;
-
-	/* something changed, cache the new value */
-	wlc_hw->maccontrol = new_maccontrol;
-
-	/* write the new values with overrides applied */
-	wlc_mctrl_write(wlc_hw);
-}
-
-/* write the software state of maccontrol and overrides to the maccontrol register */
-static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw)
-{
-	u32 maccontrol = wlc_hw->maccontrol;
-
-	/* OR in the wake bit if overridden */
-	if (wlc_hw->wake_override)
-		maccontrol |= MCTL_WAKE;
-
-	/* set AP and INFRA bits for mute if needed */
-	if (wlc_hw->mute_override) {
-		maccontrol &= ~(MCTL_AP);
-		maccontrol |= MCTL_INFRA;
-	}
-
-	W_REG(wlc_hw->osh, &wlc_hw->regs->maccontrol, maccontrol);
-}
-
-void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw, u32 override_bit)
-{
-	ASSERT((wlc_hw->wake_override & override_bit) == 0);
-
-	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE)) {
-		mboolset(wlc_hw->wake_override, override_bit);
-		return;
-	}
-
-	mboolset(wlc_hw->wake_override, override_bit);
-
-	wlc_mctrl_write(wlc_hw);
-	wlc_bmac_wait_for_wake(wlc_hw);
-
-	return;
-}
-
-void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw, u32 override_bit)
-{
-	ASSERT(wlc_hw->wake_override & override_bit);
-
-	mboolclr(wlc_hw->wake_override, override_bit);
-
-	if (wlc_hw->wake_override || (wlc_hw->maccontrol & MCTL_WAKE))
-		return;
-
-	wlc_mctrl_write(wlc_hw);
-
-	return;
-}
-
-/* When driver needs ucode to stop beaconing, it has to make sure that
- * MCTL_AP is clear and MCTL_INFRA is set
- * Mode           MCTL_AP        MCTL_INFRA
- * AP                1              1
- * STA               0              1 <--- This will ensure no beacons
- * IBSS              0              0
- */
-static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw)
-{
-	wlc_hw->mute_override = 1;
-
-	/* if maccontrol already has AP == 0 and INFRA == 1 without this
-	 * override, then there is no change to write
-	 */
-	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
-		return;
-
-	wlc_mctrl_write(wlc_hw);
-
-	return;
-}
-
-/* Clear the override on AP and INFRA bits */
-static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw)
-{
-	if (wlc_hw->mute_override == 0)
-		return;
-
-	wlc_hw->mute_override = 0;
-
-	/* if maccontrol already has AP == 0 and INFRA == 1 without this
-	 * override, then there is no change to write
-	 */
-	if ((wlc_hw->maccontrol & (MCTL_AP | MCTL_INFRA)) == MCTL_INFRA)
-		return;
-
-	wlc_mctrl_write(wlc_hw);
-}
-
-/*
- * Write a MAC address to the rcmta structure
- */
-void
-wlc_bmac_set_rcmta(struct wlc_hw_info *wlc_hw, int idx,
-		   const struct ether_addr *addr)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	volatile u16 *objdata16 = (volatile u16 *)&regs->objdata;
-	u32 mac_hm;
-	u16 mac_l;
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
-
-	ASSERT(wlc_hw->corerev > 4);
-
-	mac_hm =
-	    (addr->octet[3] << 24) | (addr->octet[2] << 16) | (addr->
-							       octet[1] << 8) |
-	    addr->octet[0];
-	mac_l = (addr->octet[5] << 8) | addr->octet[4];
-
-	osh = wlc_hw->osh;
-
-	W_REG(osh, &regs->objaddr, (OBJADDR_RCMTA_SEL | (idx * 2)));
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, &regs->objdata, mac_hm);
-	W_REG(osh, &regs->objaddr, (OBJADDR_RCMTA_SEL | ((idx * 2) + 1)));
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, objdata16, mac_l);
-}
-
-/*
- * Write a MAC address to the given match reg offset in the RXE match engine.
- */
-void
-wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw, int match_reg_offset,
-		       const struct ether_addr *addr)
-{
-	d11regs_t *regs;
-	u16 mac_l;
-	u16 mac_m;
-	u16 mac_h;
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: wlc_bmac_set_addrmatch\n", wlc_hw->unit);
-
-	ASSERT((match_reg_offset < RCM_SIZE) || (wlc_hw->corerev == 4));
-
-	regs = wlc_hw->regs;
-	mac_l = addr->octet[0] | (addr->octet[1] << 8);
-	mac_m = addr->octet[2] | (addr->octet[3] << 8);
-	mac_h = addr->octet[4] | (addr->octet[5] << 8);
-
-	osh = wlc_hw->osh;
-
-	/* enter the MAC addr into the RXE match registers */
-	W_REG(osh, &regs->rcm_ctl, RCM_INC_DATA | match_reg_offset);
-	W_REG(osh, &regs->rcm_mat_data, mac_l);
-	W_REG(osh, &regs->rcm_mat_data, mac_m);
-	W_REG(osh, &regs->rcm_mat_data, mac_h);
-
-}
-
-void
-wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset, int len,
-			    void *buf)
-{
-	d11regs_t *regs;
-	u32 word;
-	bool be_bit;
-#ifdef IL_BIGENDIAN
-	volatile u16 *dptr = NULL;
-#endif				/* IL_BIGENDIAN */
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: wlc_bmac_write_template_ram\n", wlc_hw->unit);
-
-	regs = wlc_hw->regs;
-	osh = wlc_hw->osh;
-
-	ASSERT(IS_ALIGNED(offset, sizeof(u32)));
-	ASSERT(IS_ALIGNED(len, sizeof(u32)));
-	ASSERT((offset & ~0xffff) == 0);
-
-	W_REG(osh, &regs->tplatewrptr, offset);
-
-	/* if MCTL_BIGEND bit set in mac control register,
-	 * the chip swaps data in fifo, as well as data in
-	 * template ram
-	 */
-	be_bit = (R_REG(osh, &regs->maccontrol) & MCTL_BIGEND) != 0;
-
-	while (len > 0) {
-		bcopy((u8 *) buf, &word, sizeof(u32));
-
-		if (be_bit)
-			word = hton32(word);
-		else
-			word = htol32(word);
-
-		W_REG(osh, &regs->tplatewrdata, word);
-
-		buf = (u8 *) buf + sizeof(u32);
-		len -= sizeof(u32);
-	}
-}
-
-void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin)
-{
-	struct osl_info *osh;
-
-	osh = wlc_hw->osh;
-	wlc_hw->band->CWmin = newmin;
-
-	W_REG(osh, &wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMIN);
-	(void)R_REG(osh, &wlc_hw->regs->objaddr);
-	W_REG(osh, &wlc_hw->regs->objdata, newmin);
-}
-
-void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax)
-{
-	struct osl_info *osh;
-
-	osh = wlc_hw->osh;
-	wlc_hw->band->CWmax = newmax;
-
-	W_REG(osh, &wlc_hw->regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_CWMAX);
-	(void)R_REG(osh, &wlc_hw->regs->objaddr);
-	W_REG(osh, &wlc_hw->regs->objdata, newmax);
-}
-
-void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw)
-{
-	bool fastclk;
-	u32 tmp;
-
-	/* request FAST clock if not on */
-	fastclk = wlc_hw->forcefastclk;
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	wlc_phy_bw_state_set(wlc_hw->band->pi, bw);
-
-	ASSERT(wlc_hw->clk);
-	if (D11REV_LT(wlc_hw->corerev, 17))
-		tmp = R_REG(wlc_hw->osh, &wlc_hw->regs->maccontrol);
-
-	wlc_bmac_phy_reset(wlc_hw);
-	wlc_phy_init(wlc_hw->band->pi, wlc_phy_chanspec_get(wlc_hw->band->pi));
-
-	/* restore the clk */
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-static void
-wlc_write_hw_bcntemplate0(struct wlc_hw_info *wlc_hw, void *bcn, int len)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	wlc_bmac_write_template_ram(wlc_hw, T_BCN0_TPL_BASE, (len + 3) & ~3,
-				    bcn);
-	/* write beacon length to SCR */
-	ASSERT(len < 65536);
-	wlc_bmac_write_shm(wlc_hw, M_BCN0_FRM_BYTESZ, (u16) len);
-	/* mark beacon0 valid */
-	OR_REG(wlc_hw->osh, &regs->maccommand, MCMD_BCN0VLD);
-}
-
-static void
-wlc_write_hw_bcntemplate1(struct wlc_hw_info *wlc_hw, void *bcn, int len)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	wlc_bmac_write_template_ram(wlc_hw, T_BCN1_TPL_BASE, (len + 3) & ~3,
-				    bcn);
-	/* write beacon length to SCR */
-	ASSERT(len < 65536);
-	wlc_bmac_write_shm(wlc_hw, M_BCN1_FRM_BYTESZ, (u16) len);
-	/* mark beacon1 valid */
-	OR_REG(wlc_hw->osh, &regs->maccommand, MCMD_BCN1VLD);
-}
-
-/* mac is assumed to be suspended at this point */
-void
-wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw, void *bcn, int len,
-			       bool both)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	if (both) {
-		wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
-		wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
-	} else {
-		/* bcn 0 */
-		if (!(R_REG(wlc_hw->osh, &regs->maccommand) & MCMD_BCN0VLD))
-			wlc_write_hw_bcntemplate0(wlc_hw, bcn, len);
-		/* bcn 1 */
-		else if (!
-			 (R_REG(wlc_hw->osh, &regs->maccommand) & MCMD_BCN1VLD))
-			wlc_write_hw_bcntemplate1(wlc_hw, bcn, len);
-		else		/* one template should always have been available */
-			ASSERT(0);
-	}
-}
-
-static void WLBANDINITFN(wlc_bmac_upd_synthpu) (struct wlc_hw_info *wlc_hw)
-{
-	u16 v;
-	struct wlc_info *wlc = wlc_hw->wlc;
-	/* update SYNTHPU_DLY */
-
-	if (WLCISLCNPHY(wlc->band)) {
-		v = SYNTHPU_DLY_LPPHY_US;
-	} else if (WLCISNPHY(wlc->band) && (NREV_GE(wlc->band->phyrev, 3))) {
-		v = SYNTHPU_DLY_NPHY_US;
-	} else {
-		v = SYNTHPU_DLY_BPHY_US;
-	}
-
-	wlc_bmac_write_shm(wlc_hw, M_SYNTHPU_DLY, v);
-}
-
-/* band-specific init */
-static void
-WLBANDINITFN(wlc_bmac_bsinit) (struct wlc_info *wlc, chanspec_t chanspec)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-
-	WL_TRACE("wl%d: wlc_bmac_bsinit: bandunit %d\n",
-		 wlc_hw->unit, wlc_hw->band->bandunit);
-
-	/* sanity check */
-	if (PHY_TYPE(R_REG(wlc_hw->osh, &wlc_hw->regs->phyversion)) !=
-	    PHY_TYPE_LCNXN)
-		ASSERT((uint)
-		       PHY_TYPE(R_REG(wlc_hw->osh, &wlc_hw->regs->phyversion))
-		       == wlc_hw->band->phytype);
-
-	wlc_ucode_bsinit(wlc_hw);
-
-	wlc_phy_init(wlc_hw->band->pi, chanspec);
-
-	wlc_ucode_txant_set(wlc_hw);
-
-	/* cwmin is band-specific, update hardware with value for current band */
-	wlc_bmac_set_cwmin(wlc_hw, wlc_hw->band->CWmin);
-	wlc_bmac_set_cwmax(wlc_hw, wlc_hw->band->CWmax);
-
-	wlc_bmac_update_slot_timing(wlc_hw,
-				    BAND_5G(wlc_hw->band->
-					    bandtype) ? true : wlc_hw->
-				    shortslot);
-
-	/* write phytype and phyvers */
-	wlc_bmac_write_shm(wlc_hw, M_PHYTYPE, (u16) wlc_hw->band->phytype);
-	wlc_bmac_write_shm(wlc_hw, M_PHYVER, (u16) wlc_hw->band->phyrev);
-
-	/* initialize the txphyctl1 rate table since shmem is shared between bands */
-	wlc_upd_ofdm_pctl1_table(wlc_hw);
-
-	wlc_bmac_upd_synthpu(wlc_hw);
-}
-
-void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk)
-{
-	WL_TRACE("wl%d: wlc_bmac_core_phy_clk: clk %d\n", wlc_hw->unit, clk);
-
-	wlc_hw->phyclk = clk;
-
-	if (OFF == clk) {	/* clear gmode bit, put phy into reset */
-
-		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC | SICF_GMODE),
-			       (SICF_PRST | SICF_FGC));
-		udelay(1);
-		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_PRST);
-		udelay(1);
-
-	} else {		/* take phy out of reset */
-
-		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_FGC), SICF_FGC);
-		udelay(1);
-		si_core_cflags(wlc_hw->sih, (SICF_FGC), 0);
-		udelay(1);
-
-	}
-}
-
-/* Perform a soft reset of the PHY PLL */
-void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw)
-{
-	WL_TRACE("wl%d: wlc_bmac_core_phypll_reset\n", wlc_hw->unit);
-
-	si_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_addr), ~0, 0);
-	udelay(1);
-	si_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
-	udelay(1);
-	si_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 4);
-	udelay(1);
-	si_corereg(wlc_hw->sih, SI_CC_IDX,
-		   offsetof(chipcregs_t, chipcontrol_data), 0x4, 0);
-	udelay(1);
-}
-
-/* light way to turn on phy clock without reset for NPHY only
- *  refer to wlc_bmac_core_phy_clk for full version
- */
-void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk)
-{
-	/* support(necessary for NPHY and HYPHY) only */
-	if (!WLCISNPHY(wlc_hw->band))
-		return;
-
-	if (ON == clk)
-		si_core_cflags(wlc_hw->sih, SICF_FGC, SICF_FGC);
-	else
-		si_core_cflags(wlc_hw->sih, SICF_FGC, 0);
-
-}
-
-void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk)
-{
-	if (ON == clk)
-		si_core_cflags(wlc_hw->sih, SICF_MPCLKE, SICF_MPCLKE);
-	else
-		si_core_cflags(wlc_hw->sih, SICF_MPCLKE, 0);
-}
-
-void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw)
-{
-	wlc_phy_t *pih = wlc_hw->band->pi;
-	u32 phy_bw_clkbits;
-	bool phy_in_reset = false;
-
-	WL_TRACE("wl%d: wlc_bmac_phy_reset\n", wlc_hw->unit);
-
-	if (pih == NULL)
-		return;
-
-	phy_bw_clkbits = wlc_phy_clk_bwbits(wlc_hw->band->pi);
-
-	/* Specfic reset sequence required for NPHY rev 3 and 4 */
-	if (WLCISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3) &&
-	    NREV_LE(wlc_hw->band->phyrev, 4)) {
-		/* Set the PHY bandwidth */
-		si_core_cflags(wlc_hw->sih, SICF_BWMASK, phy_bw_clkbits);
-
-		udelay(1);
-
-		/* Perform a soft reset of the PHY PLL */
-		wlc_bmac_core_phypll_reset(wlc_hw);
-
-		/* reset the PHY */
-		si_core_cflags(wlc_hw->sih, (SICF_PRST | SICF_PCLKE),
-			       (SICF_PRST | SICF_PCLKE));
-		phy_in_reset = true;
-	} else {
-
-		si_core_cflags(wlc_hw->sih,
-			       (SICF_PRST | SICF_PCLKE | SICF_BWMASK),
-			       (SICF_PRST | SICF_PCLKE | phy_bw_clkbits));
-	}
-
-	udelay(2);
-	wlc_bmac_core_phy_clk(wlc_hw, ON);
-
-	if (pih)
-		wlc_phy_anacore(pih, ON);
-}
-
-/* switch to and initialize new band */
-static void
-WLBANDINITFN(wlc_bmac_setband) (struct wlc_hw_info *wlc_hw, uint bandunit,
-				chanspec_t chanspec) {
-	struct wlc_info *wlc = wlc_hw->wlc;
-	u32 macintmask;
-
-	ASSERT(NBANDS_HW(wlc_hw) > 1);
-	ASSERT(bandunit != wlc_hw->band->bandunit);
-
-	/* Enable the d11 core before accessing it */
-	if (!si_iscoreup(wlc_hw->sih)) {
-		si_core_reset(wlc_hw->sih, 0, 0);
-		ASSERT(si_iscoreup(wlc_hw->sih));
-		wlc_mctrl_reset(wlc_hw);
-	}
-
-	macintmask = wlc_setband_inact(wlc, bandunit);
-
-	if (!wlc_hw->up)
-		return;
-
-	wlc_bmac_core_phy_clk(wlc_hw, ON);
-
-	/* band-specific initializations */
-	wlc_bmac_bsinit(wlc, chanspec);
-
-	/*
-	 * If there are any pending software interrupt bits,
-	 * then replace these with a harmless nonzero value
-	 * so wlc_dpc() will re-enable interrupts when done.
-	 */
-	if (wlc->macintstatus)
-		wlc->macintstatus = MI_DMAINT;
-
-	/* restore macintmask */
-	wl_intrsrestore(wlc->wl, macintmask);
-
-	/* ucode should still be suspended.. */
-	ASSERT((R_REG(wlc_hw->osh, &wlc_hw->regs->maccontrol) & MCTL_EN_MAC) ==
-	       0);
-}
-
-/* low-level band switch utility routine */
-void WLBANDINITFN(wlc_setxband) (struct wlc_hw_info *wlc_hw, uint bandunit)
-{
-	WL_TRACE("wl%d: wlc_setxband: bandunit %d\n", wlc_hw->unit, bandunit);
-
-	wlc_hw->band = wlc_hw->bandstate[bandunit];
-
-	/* BMAC_NOTE: until we eliminate need for wlc->band refs in low level code */
-	wlc_hw->wlc->band = wlc_hw->wlc->bandstate[bandunit];
-
-	/* set gmode core flag */
-	if (wlc_hw->sbclk && !wlc_hw->noreset) {
-		si_core_cflags(wlc_hw->sih, SICF_GMODE,
-			       ((bandunit == 0) ? SICF_GMODE : 0));
-	}
-}
-
-static bool wlc_isgoodchip(struct wlc_hw_info *wlc_hw)
-{
-
-	/* reject unsupported corerev */
-	if (!VALID_COREREV(wlc_hw->corerev)) {
-		WL_ERROR("unsupported core rev %d\n", wlc_hw->corerev);
-		return false;
-	}
-
-	return true;
-}
-
-static bool wlc_validboardtype(struct wlc_hw_info *wlc_hw)
-{
-	bool goodboard = true;
-	uint boardrev = wlc_hw->boardrev;
-
-	if (boardrev == 0)
-		goodboard = false;
-	else if (boardrev > 0xff) {
-		uint brt = (boardrev & 0xf000) >> 12;
-		uint b0 = (boardrev & 0xf00) >> 8;
-		uint b1 = (boardrev & 0xf0) >> 4;
-		uint b2 = boardrev & 0xf;
-
-		if ((brt > 2) || (brt == 0) || (b0 > 9) || (b0 == 0) || (b1 > 9)
-		    || (b2 > 9))
-			goodboard = false;
-	}
-
-	if (wlc_hw->sih->boardvendor != VENDOR_BROADCOM)
-		return goodboard;
-
-	return goodboard;
-}
-
-static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw)
-{
-	const char *varname = "macaddr";
-	char *macaddr;
-
-	/* If macaddr exists, use it (Sromrev4, CIS, ...). */
-	macaddr = getvar(wlc_hw->vars, varname);
-	if (macaddr != NULL)
-		return macaddr;
-
-	if (NBANDS_HW(wlc_hw) > 1)
-		varname = "et1macaddr";
-	else
-		varname = "il0macaddr";
-
-	macaddr = getvar(wlc_hw->vars, varname);
-	if (macaddr == NULL) {
-		WL_ERROR("wl%d: wlc_get_macaddr: macaddr getvar(%s) not found\n",
-			 wlc_hw->unit, varname);
-	}
-
-	return macaddr;
-}
-
-/*
- * Return true if radio is disabled, otherwise false.
- * hw radio disable signal is an external pin, users activate it asynchronously
- * this function could be called when driver is down and w/o clock
- * it operates on different registers depending on corerev and boardflag.
- */
-bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw)
-{
-	bool v, clk, xtal;
-	u32 resetbits = 0, flags = 0;
-
-	xtal = wlc_hw->sbclk;
-	if (!xtal)
-		wlc_bmac_xtal(wlc_hw, ON);
-
-	/* may need to take core out of reset first */
-	clk = wlc_hw->clk;
-	if (!clk) {
-		if (D11REV_LE(wlc_hw->corerev, 11))
-			resetbits |= SICF_PCLKE;
-
-		/*
-		 * corerev >= 18, mac no longer enables phyclk automatically when driver accesses
-		 * phyreg throughput mac. This can be skipped since only mac reg is accessed below
-		 */
-		if (D11REV_GE(wlc_hw->corerev, 18))
-			flags |= SICF_PCLKE;
-
-		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
-		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43421_CHIP_ID))
-			wlc_hw->regs =
-			    (d11regs_t *) si_setcore(wlc_hw->sih, D11_CORE_ID,
-						     0);
-		si_core_reset(wlc_hw->sih, flags, resetbits);
-		wlc_mctrl_reset(wlc_hw);
-	}
-
-	v = ((R_REG(wlc_hw->osh, &wlc_hw->regs->phydebug) & PDBG_RFD) != 0);
-
-	/* put core back into reset */
-	if (!clk)
-		si_core_disable(wlc_hw->sih, 0);
-
-	if (!xtal)
-		wlc_bmac_xtal(wlc_hw, OFF);
-
-	return v;
-}
-
-/* Initialize just the hardware when coming out of POR or S3/S5 system states */
-void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw)
-{
-	if (wlc_hw->wlc->pub->hw_up)
-		return;
-
-	WL_TRACE("wl%d: %s:\n", wlc_hw->unit, __func__);
-
-	/*
-	 * Enable pll and xtal, initialize the power control registers,
-	 * and force fastclock for the remainder of wlc_up().
-	 */
-	wlc_bmac_xtal(wlc_hw, ON);
-	si_clkctl_init(wlc_hw->sih);
-	wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	if (wlc_hw->sih->bustype == PCI_BUS) {
-		si_pci_fixcfg(wlc_hw->sih);
-
-		/* AI chip doesn't restore bar0win2 on hibernation/resume, need sw fixup */
-		if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43225_CHIP_ID) ||
-		    (wlc_hw->sih->chip == BCM43421_CHIP_ID))
-			wlc_hw->regs =
-			    (d11regs_t *) si_setcore(wlc_hw->sih, D11_CORE_ID,
-						     0);
-	}
-
-	/* Inform phy that a POR reset has occurred so it does a complete phy init */
-	wlc_phy_por_inform(wlc_hw->band->pi);
-
-	wlc_hw->ucode_loaded = false;
-	wlc_hw->wlc->pub->hw_up = true;
-
-	if ((wlc_hw->boardflags & BFL_FEM)
-	    && (wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
-		if (!
-		    (wlc_hw->boardrev >= 0x1250
-		     && (wlc_hw->boardflags & BFL_FEM_BT)))
-			si_epa_4313war(wlc_hw->sih);
-	}
-}
-
-static bool wlc_dma_rxreset(struct wlc_hw_info *wlc_hw, uint fifo)
-{
-	struct hnddma_pub *di = wlc_hw->di[fifo];
-	struct osl_info *osh;
-
-	if (D11REV_LT(wlc_hw->corerev, 12)) {
-		bool rxidle = true;
-		u16 rcv_frm_cnt = 0;
-
-		osh = wlc_hw->osh;
-
-		W_REG(osh, &wlc_hw->regs->rcv_fifo_ctl, fifo << 8);
-		SPINWAIT((!(rxidle = dma_rxidle(di))) &&
-			 ((rcv_frm_cnt =
-			   R_REG(osh, &wlc_hw->regs->rcv_frm_cnt)) != 0),
-			 50000);
-
-		if (!rxidle && (rcv_frm_cnt != 0))
-			WL_ERROR("wl%d: %s: rxdma[%d] not idle && rcv_frm_cnt(%d) not zero\n",
-				 wlc_hw->unit, __func__, fifo, rcv_frm_cnt);
-		mdelay(2);
-	}
-
-	return dma_rxreset(di);
-}
-
-/* d11 core reset
- *   ensure fask clock during reset
- *   reset dma
- *   reset d11(out of reset)
- *   reset phy(out of reset)
- *   clear software macintstatus for fresh new start
- * one testing hack wlc_hw->noreset will bypass the d11/phy reset
- */
-void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags)
-{
-	d11regs_t *regs;
-	uint i;
-	bool fastclk;
-	u32 resetbits = 0;
-
-	if (flags == WLC_USE_COREFLAGS)
-		flags = (wlc_hw->band->pi ? wlc_hw->band->core_flags : 0);
-
-	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
-
-	regs = wlc_hw->regs;
-
-	/* request FAST clock if not on  */
-	fastclk = wlc_hw->forcefastclk;
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	/* reset the dma engines except first time thru */
-	if (si_iscoreup(wlc_hw->sih)) {
-		for (i = 0; i < NFIFO; i++)
-			if ((wlc_hw->di[i]) && (!dma_txreset(wlc_hw->di[i]))) {
-				WL_ERROR("wl%d: %s: dma_txreset[%d]: cannot stop dma\n",
-					 wlc_hw->unit, __func__, i);
-			}
-
-		if ((wlc_hw->di[RX_FIFO])
-		    && (!wlc_dma_rxreset(wlc_hw, RX_FIFO))) {
-			WL_ERROR("wl%d: %s: dma_rxreset[%d]: cannot stop dma\n",
-				 wlc_hw->unit, __func__, RX_FIFO);
-		}
-		if (D11REV_IS(wlc_hw->corerev, 4)
-		    && wlc_hw->di[RX_TXSTATUS_FIFO]
-		    && (!wlc_dma_rxreset(wlc_hw, RX_TXSTATUS_FIFO))) {
-			WL_ERROR("wl%d: %s: dma_rxreset[%d]: cannot stop dma\n",
-				 wlc_hw->unit, __func__, RX_TXSTATUS_FIFO);
-		}
-	}
-	/* if noreset, just stop the psm and return */
-	if (wlc_hw->noreset) {
-		wlc_hw->wlc->macintstatus = 0;	/* skip wl_dpc after down */
-		wlc_bmac_mctrl(wlc_hw, MCTL_PSM_RUN | MCTL_EN_MAC, 0);
-		return;
-	}
-
-	if (D11REV_LE(wlc_hw->corerev, 11))
-		resetbits |= SICF_PCLKE;
-
-	/*
-	 * corerev >= 18, mac no longer enables phyclk automatically when driver accesses phyreg
-	 * throughput mac, AND phy_reset is skipped at early stage when band->pi is invalid
-	 * need to enable PHY CLK
-	 */
-	if (D11REV_GE(wlc_hw->corerev, 18))
-		flags |= SICF_PCLKE;
-
-	/* reset the core
-	 * In chips with PMU, the fastclk request goes through d11 core reg 0x1e0, which
-	 *  is cleared by the core_reset. have to re-request it.
-	 *  This adds some delay and we can optimize it by also requesting fastclk through
-	 *  chipcommon during this period if necessary. But that has to work coordinate
-	 *  with other driver like mips/arm since they may touch chipcommon as well.
-	 */
-	wlc_hw->clk = false;
-	si_core_reset(wlc_hw->sih, flags, resetbits);
-	wlc_hw->clk = true;
-	if (wlc_hw->band && wlc_hw->band->pi)
-		wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, true);
-
-	wlc_mctrl_reset(wlc_hw);
-
-	if (PMUCTL_ENAB(wlc_hw->sih))
-		wlc_clkctl_clk(wlc_hw, CLK_FAST);
-
-	wlc_bmac_phy_reset(wlc_hw);
-
-	/* turn on PHY_PLL */
-	wlc_bmac_core_phypll_ctl(wlc_hw, true);
-
-	/* clear sw intstatus */
-	wlc_hw->wlc->macintstatus = 0;
-
-	/* restore the clk setting */
-	if (!fastclk)
-		wlc_clkctl_clk(wlc_hw, CLK_DYNAMIC);
-}
-
-/* If the ucode that supports corerev 5 is used for corerev 9 and above,
- * txfifo sizes needs to be modified(increased) since the newer cores
- * have more memory.
- */
-static void wlc_corerev_fifofixup(struct wlc_hw_info *wlc_hw)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	u16 fifo_nu;
-	u16 txfifo_startblk = TXFIFO_START_BLK, txfifo_endblk;
-	u16 txfifo_def, txfifo_def1;
-	u16 txfifo_cmd;
-	struct osl_info *osh;
-
-	if (D11REV_LT(wlc_hw->corerev, 9))
-		goto exit;
-
-	/* tx fifos start at TXFIFO_START_BLK from the Base address */
-	txfifo_startblk = TXFIFO_START_BLK;
-
-	osh = wlc_hw->osh;
-
-	/* sequence of operations:  reset fifo, set fifo size, reset fifo */
-	for (fifo_nu = 0; fifo_nu < NFIFO; fifo_nu++) {
-
-		txfifo_endblk = txfifo_startblk + wlc_hw->xmtfifo_sz[fifo_nu];
-		txfifo_def = (txfifo_startblk & 0xff) |
-		    (((txfifo_endblk - 1) & 0xff) << TXFIFO_FIFOTOP_SHIFT);
-		txfifo_def1 = ((txfifo_startblk >> 8) & 0x1) |
-		    ((((txfifo_endblk -
-			1) >> 8) & 0x1) << TXFIFO_FIFOTOP_SHIFT);
-		txfifo_cmd =
-		    TXFIFOCMD_RESET_MASK | (fifo_nu << TXFIFOCMD_FIFOSEL_SHIFT);
-
-		W_REG(osh, &regs->xmtfifocmd, txfifo_cmd);
-		W_REG(osh, &regs->xmtfifodef, txfifo_def);
-		if (D11REV_GE(wlc_hw->corerev, 16))
-			W_REG(osh, &regs->xmtfifodef1, txfifo_def1);
-
-		W_REG(osh, &regs->xmtfifocmd, txfifo_cmd);
-
-		txfifo_startblk += wlc_hw->xmtfifo_sz[fifo_nu];
-	}
- exit:
-	/* need to propagate to shm location to be in sync since ucode/hw won't do this */
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE0,
-			   wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]);
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE1,
-			   wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]);
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE2,
-			   ((wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO] << 8) | wlc_hw->
-			    xmtfifo_sz[TX_AC_BK_FIFO]));
-	wlc_bmac_write_shm(wlc_hw, M_FIFOSIZE3,
-			   ((wlc_hw->xmtfifo_sz[TX_ATIM_FIFO] << 8) | wlc_hw->
-			    xmtfifo_sz[TX_BCMC_FIFO]));
-}
-
-/* d11 core init
- *   reset PSM
- *   download ucode/PCM
- *   let ucode run to suspended
- *   download ucode inits
- *   config other core registers
- *   init dma
- */
-static void wlc_coreinit(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs;
-	u32 sflags;
-	uint bcnint_us;
-	uint i = 0;
-	bool fifosz_fixup = false;
-	struct osl_info *osh;
-	int err = 0;
-	u16 buf[NFIFO];
-
-	regs = wlc_hw->regs;
-	osh = wlc_hw->osh;
-
-	WL_TRACE("wl%d: wlc_coreinit\n", wlc_hw->unit);
-
-	/* reset PSM */
-	wlc_bmac_mctrl(wlc_hw, ~0, (MCTL_IHR_EN | MCTL_PSM_JMP_0 | MCTL_WAKE));
-
-	wlc_ucode_download(wlc_hw);
-	/*
-	 * FIFOSZ fixup
-	 * 1) core5-9 use ucode 5 to save space since the PSM is the same
-	 * 2) newer chips, driver wants to controls the fifo allocation
-	 */
-	if (D11REV_GE(wlc_hw->corerev, 4))
-		fifosz_fixup = true;
-
-	/* let the PSM run to the suspended state, set mode to BSS STA */
-	W_REG(osh, &regs->macintstatus, -1);
-	wlc_bmac_mctrl(wlc_hw, ~0,
-		       (MCTL_IHR_EN | MCTL_INFRA | MCTL_PSM_RUN | MCTL_WAKE));
-
-	/* wait for ucode to self-suspend after auto-init */
-	SPINWAIT(((R_REG(osh, &regs->macintstatus) & MI_MACSSPNDD) == 0),
-		 1000 * 1000);
-	if ((R_REG(osh, &regs->macintstatus) & MI_MACSSPNDD) == 0)
-		WL_ERROR("wl%d: wlc_coreinit: ucode did not self-suspend!\n",
-			 wlc_hw->unit);
-
-	wlc_gpio_init(wlc);
-
-	sflags = si_core_sflags(wlc_hw->sih, 0, 0);
-
-	if (D11REV_IS(wlc_hw->corerev, 23)) {
-		if (WLCISNPHY(wlc_hw->band))
-			wlc_write_inits(wlc_hw, d11n0initvals16);
-		else
-			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
-				 __func__, wlc_hw->unit, wlc_hw->corerev);
-	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
-		if (WLCISLCNPHY(wlc_hw->band)) {
-			wlc_write_inits(wlc_hw, d11lcn0initvals24);
-		} else {
-			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
-				 __func__, wlc_hw->unit, wlc_hw->corerev);
-		}
-	} else {
-		WL_ERROR("%s: wl%d: unsupported corerev %d\n",
-			 __func__, wlc_hw->unit, wlc_hw->corerev);
-	}
-
-	/* For old ucode, txfifo sizes needs to be modified(increased) for Corerev >= 9 */
-	if (fifosz_fixup == true) {
-		wlc_corerev_fifofixup(wlc_hw);
-	}
-
-	/* check txfifo allocations match between ucode and driver */
-	buf[TX_AC_BE_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE0);
-	if (buf[TX_AC_BE_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BE_FIFO]) {
-		i = TX_AC_BE_FIFO;
-		err = -1;
-	}
-	buf[TX_AC_VI_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE1);
-	if (buf[TX_AC_VI_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VI_FIFO]) {
-		i = TX_AC_VI_FIFO;
-		err = -1;
-	}
-	buf[TX_AC_BK_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE2);
-	buf[TX_AC_VO_FIFO] = (buf[TX_AC_BK_FIFO] >> 8) & 0xff;
-	buf[TX_AC_BK_FIFO] &= 0xff;
-	if (buf[TX_AC_BK_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_BK_FIFO]) {
-		i = TX_AC_BK_FIFO;
-		err = -1;
-	}
-	if (buf[TX_AC_VO_FIFO] != wlc_hw->xmtfifo_sz[TX_AC_VO_FIFO]) {
-		i = TX_AC_VO_FIFO;
-		err = -1;
-	}
-	buf[TX_BCMC_FIFO] = wlc_bmac_read_shm(wlc_hw, M_FIFOSIZE3);
-	buf[TX_ATIM_FIFO] = (buf[TX_BCMC_FIFO] >> 8) & 0xff;
-	buf[TX_BCMC_FIFO] &= 0xff;
-	if (buf[TX_BCMC_FIFO] != wlc_hw->xmtfifo_sz[TX_BCMC_FIFO]) {
-		i = TX_BCMC_FIFO;
-		err = -1;
-	}
-	if (buf[TX_ATIM_FIFO] != wlc_hw->xmtfifo_sz[TX_ATIM_FIFO]) {
-		i = TX_ATIM_FIFO;
-		err = -1;
-	}
-	if (err != 0) {
-		WL_ERROR("wlc_coreinit: txfifo mismatch: ucode size %d driver size %d index %d\n",
-			 buf[i], wlc_hw->xmtfifo_sz[i], i);
-		/* DO NOT ASSERT corerev < 4 even there is a mismatch
-		 * shmem, since driver don't overwrite those chip and
-		 * ucode initialize data will be used.
-		 */
-		if (D11REV_GE(wlc_hw->corerev, 4))
-			ASSERT(0);
-	}
-
-	/* make sure we can still talk to the mac */
-	ASSERT(R_REG(osh, &regs->maccontrol) != 0xffffffff);
-
-	/* band-specific inits done by wlc_bsinit() */
-
-	/* Set up frame burst size and antenna swap threshold init values */
-	wlc_bmac_write_shm(wlc_hw, M_MBURST_SIZE, MAXTXFRAMEBURST);
-	wlc_bmac_write_shm(wlc_hw, M_MAX_ANTCNT, ANTCNT);
-
-	/* enable one rx interrupt per received frame */
-	W_REG(osh, &regs->intrcvlazy[0], (1 << IRL_FC_SHIFT));
-	if (D11REV_IS(wlc_hw->corerev, 4))
-		W_REG(osh, &regs->intrcvlazy[3], (1 << IRL_FC_SHIFT));
-
-	/* set the station mode (BSS STA) */
-	wlc_bmac_mctrl(wlc_hw,
-		       (MCTL_INFRA | MCTL_DISCARD_PMQ | MCTL_AP),
-		       (MCTL_INFRA | MCTL_DISCARD_PMQ));
-
-	/* set up Beacon interval */
-	bcnint_us = 0x8000 << 10;
-	W_REG(osh, &regs->tsf_cfprep, (bcnint_us << CFPREP_CBI_SHIFT));
-	W_REG(osh, &regs->tsf_cfpstart, bcnint_us);
-	W_REG(osh, &regs->macintstatus, MI_GP1);
-
-	/* write interrupt mask */
-	W_REG(osh, &regs->intctrlregs[RX_FIFO].intmask, DEF_RXINTMASK);
-	if (D11REV_IS(wlc_hw->corerev, 4))
-		W_REG(osh, &regs->intctrlregs[RX_TXSTATUS_FIFO].intmask,
-		      DEF_RXINTMASK);
-
-	/* allow the MAC to control the PHY clock (dynamic on/off) */
-	wlc_bmac_macphyclk_set(wlc_hw, ON);
-
-	/* program dynamic clock control fast powerup delay register */
-	if (D11REV_GT(wlc_hw->corerev, 4)) {
-		wlc->fastpwrup_dly = si_clkctl_fast_pwrup_delay(wlc_hw->sih);
-		W_REG(osh, &regs->scc_fastpwrup_dly, wlc->fastpwrup_dly);
-	}
-
-	/* tell the ucode the corerev */
-	wlc_bmac_write_shm(wlc_hw, M_MACHW_VER, (u16) wlc_hw->corerev);
-
-	/* tell the ucode MAC capabilities */
-	if (D11REV_GE(wlc_hw->corerev, 13)) {
-		wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_L,
-				   (u16) (wlc_hw->machwcap & 0xffff));
-		wlc_bmac_write_shm(wlc_hw, M_MACHW_CAP_H,
-				   (u16) ((wlc_hw->
-					      machwcap >> 16) & 0xffff));
-	}
-
-	/* write retry limits to SCR, this done after PSM init */
-	W_REG(osh, &regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, &regs->objdata, wlc_hw->SRL);
-	W_REG(osh, &regs->objaddr, OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, &regs->objdata, wlc_hw->LRL);
-
-	/* write rate fallback retry limits */
-	wlc_bmac_write_shm(wlc_hw, M_SFRMTXCNTFBRTHSD, wlc_hw->SFBL);
-	wlc_bmac_write_shm(wlc_hw, M_LFRMTXCNTFBRTHSD, wlc_hw->LFBL);
-
-	if (D11REV_GE(wlc_hw->corerev, 16)) {
-		AND_REG(osh, &regs->ifs_ctl, 0x0FFF);
-		W_REG(osh, &regs->ifs_aifsn, EDCF_AIFSN_MIN);
-	}
-
-	/* dma initializations */
-	wlc->txpend16165war = 0;
-
-	/* init the tx dma engines */
-	for (i = 0; i < NFIFO; i++) {
-		if (wlc_hw->di[i])
-			dma_txinit(wlc_hw->di[i]);
-	}
-
-	/* init the rx dma engine(s) and post receive buffers */
-	dma_rxinit(wlc_hw->di[RX_FIFO]);
-	dma_rxfill(wlc_hw->di[RX_FIFO]);
-	if (D11REV_IS(wlc_hw->corerev, 4)) {
-		dma_rxinit(wlc_hw->di[RX_TXSTATUS_FIFO]);
-		dma_rxfill(wlc_hw->di[RX_TXSTATUS_FIFO]);
-	}
-}
-
-/* This function is used for changing the tsf frac register
- * If spur avoidance mode is off, the mac freq will be 80/120/160Mhz
- * If spur avoidance mode is on1, the mac freq will be 82/123/164Mhz
- * If spur avoidance mode is on2, the mac freq will be 84/126/168Mhz
- * HTPHY Formula is 2^26/freq(MHz) e.g.
- * For spuron2 - 126MHz -> 2^26/126 = 532610.0
- *  - 532610 = 0x82082 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x2082
- * For spuron: 123MHz -> 2^26/123    = 545600.5
- *  - 545601 = 0x85341 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x5341
- * For spur off: 120MHz -> 2^26/120    = 559240.5
- *  - 559241 = 0x88889 => tsf_clk_frac_h = 0x8, tsf_clk_frac_l = 0x8889
- */
-
-void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode)
-{
-	d11regs_t *regs;
-	struct osl_info *osh;
-	regs = wlc_hw->regs;
-	osh = wlc_hw->osh;
-
-	if ((wlc_hw->sih->chip == BCM43224_CHIP_ID) ||
-	    (wlc_hw->sih->chip == BCM43225_CHIP_ID)) {
-		if (spurmode == WL_SPURAVOID_ON2) {	/* 126Mhz */
-			W_REG(osh, &regs->tsf_clk_frac_l, 0x2082);
-			W_REG(osh, &regs->tsf_clk_frac_h, 0x8);
-		} else if (spurmode == WL_SPURAVOID_ON1) {	/* 123Mhz */
-			W_REG(osh, &regs->tsf_clk_frac_l, 0x5341);
-			W_REG(osh, &regs->tsf_clk_frac_h, 0x8);
-		} else {	/* 120Mhz */
-			W_REG(osh, &regs->tsf_clk_frac_l, 0x8889);
-			W_REG(osh, &regs->tsf_clk_frac_h, 0x8);
-		}
-	} else if (WLCISLCNPHY(wlc_hw->band)) {
-		if (spurmode == WL_SPURAVOID_ON1) {	/* 82Mhz */
-			W_REG(osh, &regs->tsf_clk_frac_l, 0x7CE0);
-			W_REG(osh, &regs->tsf_clk_frac_h, 0xC);
-		} else {	/* 80Mhz */
-			W_REG(osh, &regs->tsf_clk_frac_l, 0xCCCD);
-			W_REG(osh, &regs->tsf_clk_frac_h, 0xC);
-		}
-	}
-}
-
-/* Initialize GPIOs that are controlled by D11 core */
-static void wlc_gpio_init(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs;
-	u32 gc, gm;
-	struct osl_info *osh;
-
-	regs = wlc_hw->regs;
-	osh = wlc_hw->osh;
-
-	/* use GPIO select 0 to get all gpio signals from the gpio out reg */
-	wlc_bmac_mctrl(wlc_hw, MCTL_GPOUT_SEL_MASK, 0);
-
-	/*
-	 * Common GPIO setup:
-	 *      G0 = LED 0 = WLAN Activity
-	 *      G1 = LED 1 = WLAN 2.4 GHz Radio State
-	 *      G2 = LED 2 = WLAN 5 GHz Radio State
-	 *      G4 = radio disable input (HI enabled, LO disabled)
-	 */
-
-	gc = gm = 0;
-
-	/* Allocate GPIOs for mimo antenna diversity feature */
-	if (WLANTSEL_ENAB(wlc)) {
-		if (wlc_hw->antsel_type == ANTSEL_2x3) {
-			/* Enable antenna diversity, use 2x3 mode */
-			wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
-				     MHF3_ANTSEL_EN, WLC_BAND_ALL);
-			wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE,
-				     MHF3_ANTSEL_MODE, WLC_BAND_ALL);
-
-			/* init superswitch control */
-			wlc_phy_antsel_init(wlc_hw->band->pi, false);
-
-		} else if (wlc_hw->antsel_type == ANTSEL_2x4) {
-			ASSERT((gm & BOARD_GPIO_12) == 0);
-			gm |= gc |= (BOARD_GPIO_12 | BOARD_GPIO_13);
-			/* The board itself is powered by these GPIOs (when not sending pattern)
-			 * So set them high
-			 */
-			OR_REG(osh, &regs->psm_gpio_oe,
-			       (BOARD_GPIO_12 | BOARD_GPIO_13));
-			OR_REG(osh, &regs->psm_gpio_out,
-			       (BOARD_GPIO_12 | BOARD_GPIO_13));
-
-			/* Enable antenna diversity, use 2x4 mode */
-			wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_EN,
-				     MHF3_ANTSEL_EN, WLC_BAND_ALL);
-			wlc_bmac_mhf(wlc_hw, MHF3, MHF3_ANTSEL_MODE, 0,
-				     WLC_BAND_ALL);
-
-			/* Configure the desired clock to be 4Mhz */
-			wlc_bmac_write_shm(wlc_hw, M_ANTSEL_CLKDIV,
-					   ANTSEL_CLKDIV_4MHZ);
-		}
-	}
-	/* gpio 9 controls the PA.  ucode is responsible for wiggling out and oe */
-	if (wlc_hw->boardflags & BFL_PACTRL)
-		gm |= gc |= BOARD_GPIO_PACTRL;
-
-	/* apply to gpiocontrol register */
-	si_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY);
-}
-
-static void wlc_ucode_download(struct wlc_hw_info *wlc_hw)
-{
-	struct wlc_info *wlc;
-	wlc = wlc_hw->wlc;
-
-	if (wlc_hw->ucode_loaded)
-		return;
-
-	if (D11REV_IS(wlc_hw->corerev, 23)) {
-		if (WLCISNPHY(wlc_hw->band)) {
-			wlc_ucode_write(wlc_hw, bcm43xx_16_mimo,
-					bcm43xx_16_mimosz);
-			wlc_hw->ucode_loaded = true;
-		} else
-			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
-				 __func__, wlc_hw->unit, wlc_hw->corerev);
-	} else if (D11REV_IS(wlc_hw->corerev, 24)) {
-		if (WLCISLCNPHY(wlc_hw->band)) {
-			wlc_ucode_write(wlc_hw, bcm43xx_24_lcn,
-					bcm43xx_24_lcnsz);
-			wlc_hw->ucode_loaded = true;
-		} else {
-			WL_ERROR("%s: wl%d: unsupported phy in corerev %d\n",
-				 __func__, wlc_hw->unit, wlc_hw->corerev);
-		}
-	}
-}
-
-static void wlc_ucode_write(struct wlc_hw_info *wlc_hw, const u32 ucode[],
-			      const uint nbytes) {
-	struct osl_info *osh;
-	d11regs_t *regs = wlc_hw->regs;
-	uint i;
-	uint count;
-
-	osh = wlc_hw->osh;
-
-	WL_TRACE("wl%d: wlc_ucode_write\n", wlc_hw->unit);
-
-	ASSERT(IS_ALIGNED(nbytes, sizeof(u32)));
-
-	count = (nbytes / sizeof(u32));
-
-	W_REG(osh, &regs->objaddr, (OBJADDR_AUTO_INC | OBJADDR_UCM_SEL));
-	(void)R_REG(osh, &regs->objaddr);
-	for (i = 0; i < count; i++)
-		W_REG(osh, &regs->objdata, ucode[i]);
-}
-
-static void wlc_write_inits(struct wlc_hw_info *wlc_hw, const d11init_t *inits)
-{
-	int i;
-	struct osl_info *osh;
-	volatile u8 *base;
-
-	WL_TRACE("wl%d: wlc_write_inits\n", wlc_hw->unit);
-
-	osh = wlc_hw->osh;
-	base = (volatile u8 *)wlc_hw->regs;
-
-	for (i = 0; inits[i].addr != 0xffff; i++) {
-		ASSERT((inits[i].size == 2) || (inits[i].size == 4));
-
-		if (inits[i].size == 2)
-			W_REG(osh, (u16 *)(base + inits[i].addr),
-			      inits[i].value);
-		else if (inits[i].size == 4)
-			W_REG(osh, (u32 *)(base + inits[i].addr),
-			      inits[i].value);
-	}
-}
-
-static void wlc_ucode_txant_set(struct wlc_hw_info *wlc_hw)
-{
-	u16 phyctl;
-	u16 phytxant = wlc_hw->bmac_phytxant;
-	u16 mask = PHY_TXC_ANT_MASK;
-
-	/* set the Probe Response frame phy control word */
-	phyctl = wlc_bmac_read_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS);
-	phyctl = (phyctl & ~mask) | phytxant;
-	wlc_bmac_write_shm(wlc_hw, M_CTXPRS_BLK + C_CTX_PCTLWD_POS, phyctl);
-
-	/* set the Response (ACK/CTS) frame phy control word */
-	phyctl = wlc_bmac_read_shm(wlc_hw, M_RSP_PCTLWD);
-	phyctl = (phyctl & ~mask) | phytxant;
-	wlc_bmac_write_shm(wlc_hw, M_RSP_PCTLWD, phyctl);
-}
-
-void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant)
-{
-	/* update sw state */
-	wlc_hw->bmac_phytxant = phytxant;
-
-	/* push to ucode if up */
-	if (!wlc_hw->up)
-		return;
-	wlc_ucode_txant_set(wlc_hw);
-
-}
-
-u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw)
-{
-	return (u16) wlc_hw->wlc->stf->txant;
-}
-
-void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw, u8 antsel_type)
-{
-	wlc_hw->antsel_type = antsel_type;
-
-	/* Update the antsel type for phy module to use */
-	wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
-}
-
-void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw)
-{
-	bool fatal = false;
-	uint unit;
-	uint intstatus, idx;
-	d11regs_t *regs = wlc_hw->regs;
-
-	unit = wlc_hw->unit;
-
-	for (idx = 0; idx < NFIFO; idx++) {
-		/* read intstatus register and ignore any non-error bits */
-		intstatus =
-		    R_REG(wlc_hw->osh,
-			  &regs->intctrlregs[idx].intstatus) & I_ERRORS;
-		if (!intstatus)
-			continue;
-
-		WL_TRACE("wl%d: wlc_bmac_fifoerrors: intstatus%d 0x%x\n",
-			 unit, idx, intstatus);
-
-		if (intstatus & I_RO) {
-			WL_ERROR("wl%d: fifo %d: receive fifo overflow\n",
-				 unit, idx);
-			WLCNTINCR(wlc_hw->wlc->pub->_cnt->rxoflo);
-			fatal = true;
-		}
-
-		if (intstatus & I_PC) {
-			WL_ERROR("wl%d: fifo %d: descriptor error\n",
-				 unit, idx);
-			WLCNTINCR(wlc_hw->wlc->pub->_cnt->dmade);
-			fatal = true;
-		}
-
-		if (intstatus & I_PD) {
-			WL_ERROR("wl%d: fifo %d: data error\n", unit, idx);
-			WLCNTINCR(wlc_hw->wlc->pub->_cnt->dmada);
-			fatal = true;
-		}
-
-		if (intstatus & I_DE) {
-			WL_ERROR("wl%d: fifo %d: descriptor protocol error\n",
-				 unit, idx);
-			WLCNTINCR(wlc_hw->wlc->pub->_cnt->dmape);
-			fatal = true;
-		}
-
-		if (intstatus & I_RU) {
-			WL_ERROR("wl%d: fifo %d: receive descriptor underflow\n",
-				 idx, unit);
-			WLCNTINCR(wlc_hw->wlc->pub->_cnt->rxuflo[idx]);
-		}
-
-		if (intstatus & I_XU) {
-			WL_ERROR("wl%d: fifo %d: transmit fifo underflow\n",
-				 idx, unit);
-			WLCNTINCR(wlc_hw->wlc->pub->_cnt->txuflo);
-			fatal = true;
-		}
-
-		if (fatal) {
-			wlc_fatal_error(wlc_hw->wlc);	/* big hammer */
-			break;
-		} else
-			W_REG(wlc_hw->osh, &regs->intctrlregs[idx].intstatus,
-			      intstatus);
-	}
-}
-
-void wlc_intrson(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	ASSERT(wlc->defmacintmask);
-	wlc->macintmask = wlc->defmacintmask;
-	W_REG(wlc_hw->osh, &wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-/* callback for siutils.c, which has only wlc handler, no wl
- * they both check up, not only because there is no need to off/restore d11 interrupt
- *  but also because per-port code may require sync with valid interrupt.
- */
-
-static u32 wlc_wlintrsoff(struct wlc_info *wlc)
-{
-	if (!wlc->hw->up)
-		return 0;
-
-	return wl_intrsoff(wlc->wl);
-}
-
-static void wlc_wlintrsrestore(struct wlc_info *wlc, u32 macintmask)
-{
-	if (!wlc->hw->up)
-		return;
-
-	wl_intrsrestore(wlc->wl, macintmask);
-}
-
-u32 wlc_intrsoff(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	u32 macintmask;
-
-	if (!wlc_hw->clk)
-		return 0;
-
-	macintmask = wlc->macintmask;	/* isr can still happen */
-
-	W_REG(wlc_hw->osh, &wlc_hw->regs->macintmask, 0);
-	(void)R_REG(wlc_hw->osh, &wlc_hw->regs->macintmask);	/* sync readback */
-	udelay(1);		/* ensure int line is no longer driven */
-	wlc->macintmask = 0;
-
-	/* return previous macintmask; resolve race between us and our isr */
-	return wlc->macintstatus ? 0 : macintmask;
-}
-
-void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	if (!wlc_hw->clk)
-		return;
-
-	wlc->macintmask = macintmask;
-	W_REG(wlc_hw->osh, &wlc_hw->regs->macintmask, wlc->macintmask);
-}
-
-void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, mbool flags)
-{
-	struct ether_addr null_ether_addr = { {0, 0, 0, 0, 0, 0} };
-
-	if (on) {
-		/* suspend tx fifos */
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_BK_FIFO);
-		wlc_bmac_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
-
-		/* zero the address match register so we do not send ACKs */
-		wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
-				       &null_ether_addr);
-	} else {
-		/* resume tx fifos */
-		if (!wlc_hw->wlc->tx_suspended) {
-			wlc_bmac_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
-		}
-		wlc_bmac_tx_fifo_resume(wlc_hw, TX_CTL_FIFO);
-		wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_BK_FIFO);
-		wlc_bmac_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
-
-		/* Restore address */
-		wlc_bmac_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
-				       &wlc_hw->etheraddr);
-	}
-
-	wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
-
-	if (on)
-		wlc_ucode_mute_override_set(wlc_hw);
-	else
-		wlc_ucode_mute_override_clear(wlc_hw);
-}
-
-void wlc_bmac_set_deaf(struct wlc_hw_info *wlc_hw, bool user_flag)
-{
-	wlc_phy_set_deaf(wlc_hw->band->pi, user_flag);
-}
-
-int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo, uint *blocks)
-{
-	if (fifo >= NFIFO)
-		return BCME_RANGE;
-
-	*blocks = wlc_hw->xmtfifo_sz[fifo];
-
-	return 0;
-}
-
-int wlc_bmac_xmtfifo_sz_set(struct wlc_hw_info *wlc_hw, uint fifo, uint blocks)
-{
-	if (fifo >= NFIFO || blocks > 299)
-		return BCME_RANGE;
-
-	/* BMAC_NOTE, change blocks to u16 */
-	wlc_hw->xmtfifo_sz[fifo] = (u16) blocks;
-
-	return 0;
-}
-
-/* wlc_bmac_tx_fifo_suspended:
- * Check the MAC's tx suspend status for a tx fifo.
- *
- * When the MAC acknowledges a tx suspend, it indicates that no more
- * packets will be transmitted out the radio. This is independent of
- * DMA channel suspension---the DMA may have finished suspending, or may still
- * be pulling data into a tx fifo, by the time the MAC acks the suspend
- * request.
- */
-bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw, uint tx_fifo)
-{
-	/* check that a suspend has been requested and is no longer pending */
-
-	/*
-	 * for DMA mode, the suspend request is set in xmtcontrol of the DMA engine,
-	 * and the tx fifo suspend at the lower end of the MAC is acknowledged in the
-	 * chnstatus register.
-	 * The tx fifo suspend completion is independent of the DMA suspend completion and
-	 *   may be acked before or after the DMA is suspended.
-	 */
-	if (dma_txsuspended(wlc_hw->di[tx_fifo]) &&
-	    (R_REG(wlc_hw->osh, &wlc_hw->regs->chnstatus) &
-	     (1 << tx_fifo)) == 0)
-		return true;
-
-	return false;
-}
-
-void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo)
-{
-	u8 fifo = 1 << tx_fifo;
-
-	/* Two clients of this code, 11h Quiet period and scanning. */
-
-	/* only suspend if not already suspended */
-	if ((wlc_hw->suspended_fifos & fifo) == fifo)
-		return;
-
-	/* force the core awake only if not already */
-	if (wlc_hw->suspended_fifos == 0)
-		wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_TXFIFO);
-
-	wlc_hw->suspended_fifos |= fifo;
-
-	if (wlc_hw->di[tx_fifo]) {
-		/* Suspending AMPDU transmissions in the middle can cause underflow
-		 * which may result in mismatch between ucode and driver
-		 * so suspend the mac before suspending the FIFO
-		 */
-		if (WLC_PHY_11N_CAP(wlc_hw->band))
-			wlc_suspend_mac_and_wait(wlc_hw->wlc);
-
-		dma_txsuspend(wlc_hw->di[tx_fifo]);
-
-		if (WLC_PHY_11N_CAP(wlc_hw->band))
-			wlc_enable_mac(wlc_hw->wlc);
-	}
-}
-
-void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo)
-{
-	/* BMAC_NOTE: WLC_TX_FIFO_ENAB is done in wlc_dpc() for DMA case but need to be done
-	 * here for PIO otherwise the watchdog will catch the inconsistency and fire
-	 */
-	/* Two clients of this code, 11h Quiet period and scanning. */
-	if (wlc_hw->di[tx_fifo])
-		dma_txresume(wlc_hw->di[tx_fifo]);
-
-	/* allow core to sleep again */
-	if (wlc_hw->suspended_fifos == 0)
-		return;
-	else {
-		wlc_hw->suspended_fifos &= ~(1 << tx_fifo);
-		if (wlc_hw->suspended_fifos == 0)
-			wlc_ucode_wake_override_clear(wlc_hw,
-						      WLC_WAKE_OVERRIDE_TXFIFO);
-	}
-}
-
-/*
- * Read and clear macintmask and macintstatus and intstatus registers.
- * This routine should be called with interrupts off
- * Return:
- *   -1 if DEVICEREMOVED(wlc) evaluates to true;
- *   0 if the interrupt is not for us, or we are in some special cases;
- *   device interrupt status bits otherwise.
- */
-static inline u32 wlc_intstatus(struct wlc_info *wlc, bool in_isr)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	u32 macintstatus;
-	u32 intstatus_rxfifo, intstatus_txsfifo;
-	struct osl_info *osh;
-
-	osh = wlc_hw->osh;
-
-	/* macintstatus includes a DMA interrupt summary bit */
-	macintstatus = R_REG(osh, &regs->macintstatus);
-
-	WL_TRACE("wl%d: macintstatus: 0x%x\n", wlc_hw->unit, macintstatus);
-
-	/* detect cardbus removed, in power down(suspend) and in reset */
-	if (DEVICEREMOVED(wlc))
-		return -1;
-
-	/* DEVICEREMOVED succeeds even when the core is still resetting,
-	 * handle that case here.
-	 */
-	if (macintstatus == 0xffffffff)
-		return 0;
-
-	/* defer unsolicited interrupts */
-	macintstatus &= (in_isr ? wlc->macintmask : wlc->defmacintmask);
-
-	/* if not for us */
-	if (macintstatus == 0)
-		return 0;
-
-	/* interrupts are already turned off for CFE build
-	 * Caution: For CFE Turning off the interrupts again has some undesired
-	 * consequences
-	 */
-	/* turn off the interrupts */
-	W_REG(osh, &regs->macintmask, 0);
-	(void)R_REG(osh, &regs->macintmask);	/* sync readback */
-	wlc->macintmask = 0;
-
-	/* clear device interrupts */
-	W_REG(osh, &regs->macintstatus, macintstatus);
-
-	/* MI_DMAINT is indication of non-zero intstatus */
-	if (macintstatus & MI_DMAINT) {
-		if (D11REV_IS(wlc_hw->corerev, 4)) {
-			intstatus_rxfifo =
-			    R_REG(osh, &regs->intctrlregs[RX_FIFO].intstatus);
-			intstatus_txsfifo =
-			    R_REG(osh,
-				  &regs->intctrlregs[RX_TXSTATUS_FIFO].
-				  intstatus);
-			WL_TRACE("wl%d: intstatus_rxfifo 0x%x, intstatus_txsfifo 0x%x\n",
-				 wlc_hw->unit,
-				 intstatus_rxfifo, intstatus_txsfifo);
-
-			/* defer unsolicited interrupt hints */
-			intstatus_rxfifo &= DEF_RXINTMASK;
-			intstatus_txsfifo &= DEF_RXINTMASK;
-
-			/* MI_DMAINT bit in macintstatus is indication of RX_FIFO interrupt */
-			/* clear interrupt hints */
-			if (intstatus_rxfifo)
-				W_REG(osh,
-				      &regs->intctrlregs[RX_FIFO].intstatus,
-				      intstatus_rxfifo);
-			else
-				macintstatus &= ~MI_DMAINT;
-
-			/* MI_TFS bit in macintstatus is encoding of RX_TXSTATUS_FIFO interrupt */
-			if (intstatus_txsfifo) {
-				W_REG(osh,
-				      &regs->intctrlregs[RX_TXSTATUS_FIFO].
-				      intstatus, intstatus_txsfifo);
-				macintstatus |= MI_TFS;
-			}
-		} else {
-			/*
-			 * For corerevs >= 5, only fifo interrupt enabled is I_RI in RX_FIFO.
-			 * If MI_DMAINT is set, assume it is set and clear the interrupt.
-			 */
-			W_REG(osh, &regs->intctrlregs[RX_FIFO].intstatus,
-			      DEF_RXINTMASK);
-		}
-	}
-
-	return macintstatus;
-}
-
-/* Update wlc->macintstatus and wlc->intstatus[]. */
-/* Return true if they are updated successfully. false otherwise */
-bool wlc_intrsupd(struct wlc_info *wlc)
-{
-	u32 macintstatus;
-
-	ASSERT(wlc->macintstatus != 0);
-
-	/* read and clear macintstatus and intstatus registers */
-	macintstatus = wlc_intstatus(wlc, false);
-
-	/* device is removed */
-	if (macintstatus == 0xffffffff)
-		return false;
-
-	/* update interrupt status in software */
-	wlc->macintstatus |= macintstatus;
-
-	return true;
-}
-
-/*
- * First-level interrupt processing.
- * Return true if this was our interrupt, false otherwise.
- * *wantdpc will be set to true if further wlc_dpc() processing is required,
- * false otherwise.
- */
-bool BCMFASTPATH wlc_isr(struct wlc_info *wlc, bool *wantdpc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	u32 macintstatus;
-
-	*wantdpc = false;
-
-	if (!wlc_hw->up || !wlc->macintmask)
-		return false;
-
-	/* read and clear macintstatus and intstatus registers */
-	macintstatus = wlc_intstatus(wlc, true);
-
-	if (macintstatus == 0xffffffff)
-		WL_ERROR("DEVICEREMOVED detected in the ISR code path\n");
-
-	/* it is not for us */
-	if (macintstatus == 0)
-		return false;
-
-	*wantdpc = true;
-
-	/* save interrupt status bits */
-	ASSERT(wlc->macintstatus == 0);
-	wlc->macintstatus = macintstatus;
-
-	return true;
-
-}
-
-/* process tx completion events for corerev < 5 */
-static bool wlc_bmac_txstatus_corerev4(struct wlc_hw_info *wlc_hw)
-{
-	struct sk_buff *status_p;
-	tx_status_t *txs;
-	struct osl_info *osh;
-	bool fatal = false;
-
-	WL_TRACE("wl%d: wlc_txstatusrecv\n", wlc_hw->unit);
-
-	osh = wlc_hw->osh;
-
-	while (!fatal && (status_p = dma_rx(wlc_hw->di[RX_TXSTATUS_FIFO]))) {
-
-		txs = (tx_status_t *) status_p->data;
-		/* MAC uses little endian only */
-		ltoh16_buf((void *)txs, sizeof(tx_status_t));
-
-		/* shift low bits for tx_status_t status compatibility */
-		txs->status = (txs->status & ~TXS_COMPAT_MASK)
-		    | (((txs->status & TXS_COMPAT_MASK) << TXS_COMPAT_SHIFT));
-
-		fatal = wlc_bmac_dotxstatus(wlc_hw, txs, 0);
-
-		pkt_buf_free_skb(osh, status_p, false);
-	}
-
-	if (fatal)
-		return true;
-
-	/* post more rbufs */
-	dma_rxfill(wlc_hw->di[RX_TXSTATUS_FIFO]);
-
-	return false;
-}
-
-static bool BCMFASTPATH
-wlc_bmac_dotxstatus(struct wlc_hw_info *wlc_hw, tx_status_t *txs, u32 s2)
-{
-	/* discard intermediate indications for ucode with one legitimate case:
-	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
-	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
-	 *   transmission count)
-	 */
-	if (!(txs->status & TX_STATUS_AMPDU)
-	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
-		return false;
-	}
-
-	return wlc_dotxstatus(wlc_hw->wlc, txs, s2);
-}
-
-/* process tx completion events in BMAC
- * Return true if more tx status need to be processed. false otherwise.
- */
-static bool BCMFASTPATH
-wlc_bmac_txstatus(struct wlc_hw_info *wlc_hw, bool bound, bool *fatal)
-{
-	bool morepending = false;
-	struct wlc_info *wlc = wlc_hw->wlc;
-
-	WL_TRACE("wl%d: wlc_bmac_txstatus\n", wlc_hw->unit);
-
-	if (D11REV_IS(wlc_hw->corerev, 4)) {
-		/* to retire soon */
-		*fatal = wlc_bmac_txstatus_corerev4(wlc->hw);
-
-		if (*fatal)
-			return 0;
-	} else {
-		/* corerev >= 5 */
-		d11regs_t *regs;
-		struct osl_info *osh;
-		tx_status_t txstatus, *txs;
-		u32 s1, s2;
-		uint n = 0;
-		/* Param 'max_tx_num' indicates max. # tx status to process before break out. */
-		uint max_tx_num = bound ? wlc->pub->tunables->txsbnd : -1;
-
-		txs = &txstatus;
-		regs = wlc_hw->regs;
-		osh = wlc_hw->osh;
-		while (!(*fatal)
-		       && (s1 = R_REG(osh, &regs->frmtxstatus)) & TXS_V) {
-
-			if (s1 == 0xffffffff) {
-				WL_ERROR("wl%d: %s: dead chip\n",
-					 wlc_hw->unit, __func__);
-				ASSERT(s1 != 0xffffffff);
-				return morepending;
-			}
-
-			s2 = R_REG(osh, &regs->frmtxstatus2);
-
-			txs->status = s1 & TXS_STATUS_MASK;
-			txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT;
-			txs->sequence = s2 & TXS_SEQ_MASK;
-			txs->phyerr = (s2 & TXS_PTX_MASK) >> TXS_PTX_SHIFT;
-			txs->lasttxtime = 0;
-
-			*fatal = wlc_bmac_dotxstatus(wlc_hw, txs, s2);
-
-			/* !give others some time to run! */
-			if (++n >= max_tx_num)
-				break;
-		}
-
-		if (*fatal)
-			return 0;
-
-		if (n >= max_tx_num)
-			morepending = true;
-	}
-
-	if (!pktq_empty(&wlc->active_queue->q))
-		wlc_send_q(wlc, wlc->active_queue);
-
-	return morepending;
-}
-
-void wlc_suspend_mac_and_wait(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	u32 mc, mi;
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: wlc_suspend_mac_and_wait: bandunit %d\n",
-		 wlc_hw->unit, wlc_hw->band->bandunit);
-
-	/*
-	 * Track overlapping suspend requests
-	 */
-	wlc_hw->mac_suspend_depth++;
-	if (wlc_hw->mac_suspend_depth > 1)
-		return;
-
-	osh = wlc_hw->osh;
-
-	/* force the core awake */
-	wlc_ucode_wake_override_set(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
-
-	mc = R_REG(osh, &regs->maccontrol);
-
-	if (mc == 0xffffffff) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-	ASSERT(!(mc & MCTL_PSM_JMP_0));
-	ASSERT(mc & MCTL_PSM_RUN);
-	ASSERT(mc & MCTL_EN_MAC);
-
-	mi = R_REG(osh, &regs->macintstatus);
-	if (mi == 0xffffffff) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-	ASSERT(!(mi & MI_MACSSPNDD));
-
-	wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, 0);
-
-	SPINWAIT(!(R_REG(osh, &regs->macintstatus) & MI_MACSSPNDD),
-		 WLC_MAX_MAC_SUSPEND);
-
-	if (!(R_REG(osh, &regs->macintstatus) & MI_MACSSPNDD)) {
-		WL_ERROR("wl%d: wlc_suspend_mac_and_wait: waited %d uS and MI_MACSSPNDD is still not on.\n",
-			 wlc_hw->unit, WLC_MAX_MAC_SUSPEND);
-		WL_ERROR("wl%d: psmdebug 0x%08x, phydebug 0x%08x, psm_brc 0x%04x\n",
-			 wlc_hw->unit,
-			 R_REG(osh, &regs->psmdebug),
-			 R_REG(osh, &regs->phydebug),
-			 R_REG(osh, &regs->psm_brc));
-	}
-
-	mc = R_REG(osh, &regs->maccontrol);
-	if (mc == 0xffffffff) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc_hw->unit, __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-	ASSERT(!(mc & MCTL_PSM_JMP_0));
-	ASSERT(mc & MCTL_PSM_RUN);
-	ASSERT(!(mc & MCTL_EN_MAC));
-}
-
-void wlc_enable_mac(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	d11regs_t *regs = wlc_hw->regs;
-	u32 mc, mi;
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: wlc_enable_mac: bandunit %d\n",
-		 wlc_hw->unit, wlc->band->bandunit);
-
-	/*
-	 * Track overlapping suspend requests
-	 */
-	ASSERT(wlc_hw->mac_suspend_depth > 0);
-	wlc_hw->mac_suspend_depth--;
-	if (wlc_hw->mac_suspend_depth > 0)
-		return;
-
-	osh = wlc_hw->osh;
-
-	mc = R_REG(osh, &regs->maccontrol);
-	ASSERT(!(mc & MCTL_PSM_JMP_0));
-	ASSERT(!(mc & MCTL_EN_MAC));
-	ASSERT(mc & MCTL_PSM_RUN);
-
-	wlc_bmac_mctrl(wlc_hw, MCTL_EN_MAC, MCTL_EN_MAC);
-	W_REG(osh, &regs->macintstatus, MI_MACSSPNDD);
-
-	mc = R_REG(osh, &regs->maccontrol);
-	ASSERT(!(mc & MCTL_PSM_JMP_0));
-	ASSERT(mc & MCTL_EN_MAC);
-	ASSERT(mc & MCTL_PSM_RUN);
-
-	mi = R_REG(osh, &regs->macintstatus);
-	ASSERT(!(mi & MI_MACSSPNDD));
-
-	wlc_ucode_wake_override_clear(wlc_hw, WLC_WAKE_OVERRIDE_MACSUSPEND);
-}
-
-void wlc_bmac_ifsctl_edcrs_set(struct wlc_hw_info *wlc_hw, bool abie, bool isht)
-{
-	if (!(WLCISNPHY(wlc_hw->band) && (D11REV_GE(wlc_hw->corerev, 16))))
-		return;
-
-	if (isht) {
-		if (WLCISNPHY(wlc_hw->band) && NREV_LT(wlc_hw->band->phyrev, 3)) {
-			AND_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-				~IFS_CTL1_EDCRS);
-		}
-	} else {
-		/* enable EDCRS for non-11n association */
-		OR_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1, IFS_CTL1_EDCRS);
-	}
-
-	if (WLCISNPHY(wlc_hw->band) && NREV_GE(wlc_hw->band->phyrev, 3)) {
-		if (CHSPEC_IS20(wlc_hw->chanspec)) {
-			/* 20 mhz, use 20U ED only */
-			OR_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-			       IFS_CTL1_EDCRS);
-			AND_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-				~IFS_CTL1_EDCRS_20L);
-			AND_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-				~IFS_CTL1_EDCRS_40);
-		} else {
-			/* 40 mhz, use 20U 20L and 40 ED */
-			OR_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-			       IFS_CTL1_EDCRS);
-			OR_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-			       IFS_CTL1_EDCRS_20L);
-			OR_REG(wlc_hw->osh, &wlc_hw->regs->ifs_ctl1,
-			       IFS_CTL1_EDCRS_40);
-		}
-	}
-}
-
-static void wlc_upd_ofdm_pctl1_table(struct wlc_hw_info *wlc_hw)
-{
-	u8 rate;
-	u8 rates[8] = {
-		WLC_RATE_6M, WLC_RATE_9M, WLC_RATE_12M, WLC_RATE_18M,
-		WLC_RATE_24M, WLC_RATE_36M, WLC_RATE_48M, WLC_RATE_54M
-	};
-	u16 entry_ptr;
-	u16 pctl1;
-	uint i;
-
-	if (!WLC_PHY_11N_CAP(wlc_hw->band))
-		return;
-
-	/* walk the phy rate table and update the entries */
-	for (i = 0; i < ARRAY_SIZE(rates); i++) {
-		rate = rates[i];
-
-		entry_ptr = wlc_bmac_ofdm_ratetable_offset(wlc_hw, rate);
-
-		/* read the SHM Rate Table entry OFDM PCTL1 values */
-		pctl1 =
-		    wlc_bmac_read_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS);
-
-		/* modify the value */
-		pctl1 &= ~PHY_TXC1_MODE_MASK;
-		pctl1 |= (wlc_hw->hw_stf_ss_opmode << PHY_TXC1_MODE_SHIFT);
-
-		/* Update the SHM Rate Table entry OFDM PCTL1 values */
-		wlc_bmac_write_shm(wlc_hw, entry_ptr + M_RT_OFDM_PCTL1_POS,
-				   pctl1);
-	}
-}
-
-static u16 wlc_bmac_ofdm_ratetable_offset(struct wlc_hw_info *wlc_hw, u8 rate)
-{
-	uint i;
-	u8 plcp_rate = 0;
-	struct plcp_signal_rate_lookup {
-		u8 rate;
-		u8 signal_rate;
-	};
-	/* OFDM RATE sub-field of PLCP SIGNAL field, per 802.11 sec 17.3.4.1 */
-	const struct plcp_signal_rate_lookup rate_lookup[] = {
-		{WLC_RATE_6M, 0xB},
-		{WLC_RATE_9M, 0xF},
-		{WLC_RATE_12M, 0xA},
-		{WLC_RATE_18M, 0xE},
-		{WLC_RATE_24M, 0x9},
-		{WLC_RATE_36M, 0xD},
-		{WLC_RATE_48M, 0x8},
-		{WLC_RATE_54M, 0xC}
-	};
-
-	for (i = 0; i < ARRAY_SIZE(rate_lookup); i++) {
-		if (rate == rate_lookup[i].rate) {
-			plcp_rate = rate_lookup[i].signal_rate;
-			break;
-		}
-	}
-
-	/* Find the SHM pointer to the rate table entry by looking in the
-	 * Direct-map Table
-	 */
-	return 2 * wlc_bmac_read_shm(wlc_hw, M_RT_DIRMAP_A + (plcp_rate * 2));
-}
-
-void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode)
-{
-	wlc_hw->hw_stf_ss_opmode = stf_mode;
-
-	if (wlc_hw->clk)
-		wlc_upd_ofdm_pctl1_table(wlc_hw);
-}
-
-void BCMFASTPATH
-wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
-		  u32 *tsf_h_ptr)
-{
-	d11regs_t *regs = wlc_hw->regs;
-
-	/* read the tsf timer low, then high to get an atomic read */
-	*tsf_l_ptr = R_REG(wlc_hw->osh, &regs->tsf_timerlow);
-	*tsf_h_ptr = R_REG(wlc_hw->osh, &regs->tsf_timerhigh);
-
-	return;
-}
-
-bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw)
-{
-	d11regs_t *regs;
-	u32 w, val;
-	volatile u16 *reg16;
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: validate_chip_access\n", wlc_hw->unit);
-
-	regs = wlc_hw->regs;
-	osh = wlc_hw->osh;
-
-	/* Validate dchip register access */
-
-	W_REG(osh, &regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(osh, &regs->objaddr);
-	w = R_REG(osh, &regs->objdata);
-
-	/* Can we write and read back a 32bit register? */
-	W_REG(osh, &regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, &regs->objdata, (u32) 0xaa5555aa);
-
-	W_REG(osh, &regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(osh, &regs->objaddr);
-	val = R_REG(osh, &regs->objdata);
-	if (val != (u32) 0xaa5555aa) {
-		WL_ERROR("wl%d: validate_chip_access: SHM = 0x%x, expected 0xaa5555aa\n",
-			 wlc_hw->unit, val);
-		return false;
-	}
-
-	W_REG(osh, &regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, &regs->objdata, (u32) 0x55aaaa55);
-
-	W_REG(osh, &regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(osh, &regs->objaddr);
-	val = R_REG(osh, &regs->objdata);
-	if (val != (u32) 0x55aaaa55) {
-		WL_ERROR("wl%d: validate_chip_access: SHM = 0x%x, expected 0x55aaaa55\n",
-			 wlc_hw->unit, val);
-		return false;
-	}
-
-	W_REG(osh, &regs->objaddr, OBJADDR_SHM_SEL | 0);
-	(void)R_REG(osh, &regs->objaddr);
-	W_REG(osh, &regs->objdata, w);
-
-	if (D11REV_LT(wlc_hw->corerev, 11)) {
-		/* if 32 bit writes are split into 16 bit writes, are they in the correct order
-		 * for our interface, low to high
-		 */
-		reg16 = (volatile u16 *)&regs->tsf_cfpstart;
-
-		/* write the CFPStart register low half explicitly, starting a buffered write */
-		W_REG(osh, reg16, 0xAAAA);
-
-		/* Write a 32 bit value to CFPStart to test the 16 bit split order.
-		 * If the low 16 bits are written first, followed by the high 16 bits then the
-		 * 32 bit value 0xCCCCBBBB should end up in the register.
-		 * If the order is reversed, then the write to the high half will trigger a buffered
-		 * write of 0xCCCCAAAA.
-		 * If the bus is 32 bits, then this is not much of a test, and the reg should
-		 * have the correct value 0xCCCCBBBB.
-		 */
-		W_REG(osh, &regs->tsf_cfpstart, 0xCCCCBBBB);
-
-		/* verify with the 16 bit registers that have no side effects */
-		val = R_REG(osh, &regs->tsf_cfpstrt_l);
-		if (val != (uint) 0xBBBB) {
-			WL_ERROR("wl%d: validate_chip_access: tsf_cfpstrt_l = 0x%x, expected 0x%x\n",
-				 wlc_hw->unit, val, 0xBBBB);
-			return false;
-		}
-		val = R_REG(osh, &regs->tsf_cfpstrt_h);
-		if (val != (uint) 0xCCCC) {
-			WL_ERROR("wl%d: validate_chip_access: tsf_cfpstrt_h = 0x%x, expected 0x%x\n",
-				 wlc_hw->unit, val, 0xCCCC);
-			return false;
-		}
-
-	}
-
-	/* clear CFPStart */
-	W_REG(osh, &regs->tsf_cfpstart, 0);
-
-	w = R_REG(osh, &regs->maccontrol);
-	if ((w != (MCTL_IHR_EN | MCTL_WAKE)) &&
-	    (w != (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE))) {
-		WL_ERROR("wl%d: validate_chip_access: maccontrol = 0x%x, expected 0x%x or 0x%x\n",
-			 wlc_hw->unit, w,
-			 (MCTL_IHR_EN | MCTL_WAKE),
-			 (MCTL_IHR_EN | MCTL_GMODE | MCTL_WAKE));
-		return false;
-	}
-
-	return true;
-}
-
-#define PHYPLL_WAIT_US	100000
-
-void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on)
-{
-	d11regs_t *regs;
-	struct osl_info *osh;
-	u32 tmp;
-
-	WL_TRACE("wl%d: wlc_bmac_core_phypll_ctl\n", wlc_hw->unit);
-
-	tmp = 0;
-	regs = wlc_hw->regs;
-	osh = wlc_hw->osh;
-
-	if (D11REV_LE(wlc_hw->corerev, 16) || D11REV_IS(wlc_hw->corerev, 20))
-		return;
-
-	if (on) {
-		if ((wlc_hw->sih->chip == BCM4313_CHIP_ID)) {
-			OR_REG(osh, &regs->clk_ctl_st,
-			       (CCS_ERSRC_REQ_HT | CCS_ERSRC_REQ_D11PLL |
-				CCS_ERSRC_REQ_PHYPLL));
-			SPINWAIT((R_REG(osh, &regs->clk_ctl_st) &
-				  (CCS_ERSRC_AVAIL_HT)) != (CCS_ERSRC_AVAIL_HT),
-				 PHYPLL_WAIT_US);
-
-			tmp = R_REG(osh, &regs->clk_ctl_st);
-			if ((tmp & (CCS_ERSRC_AVAIL_HT)) !=
-			    (CCS_ERSRC_AVAIL_HT)) {
-				WL_ERROR("%s: turn on PHY PLL failed\n",
-					 __func__);
-				ASSERT(0);
-			}
-		} else {
-			OR_REG(osh, &regs->clk_ctl_st,
-			       (CCS_ERSRC_REQ_D11PLL | CCS_ERSRC_REQ_PHYPLL));
-			SPINWAIT((R_REG(osh, &regs->clk_ctl_st) &
-				  (CCS_ERSRC_AVAIL_D11PLL |
-				   CCS_ERSRC_AVAIL_PHYPLL)) !=
-				 (CCS_ERSRC_AVAIL_D11PLL |
-				  CCS_ERSRC_AVAIL_PHYPLL), PHYPLL_WAIT_US);
-
-			tmp = R_REG(osh, &regs->clk_ctl_st);
-			if ((tmp &
-			     (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL))
-			    !=
-			    (CCS_ERSRC_AVAIL_D11PLL | CCS_ERSRC_AVAIL_PHYPLL)) {
-				WL_ERROR("%s: turn on PHY PLL failed\n",
-					 __func__);
-				ASSERT(0);
-			}
-		}
-	} else {
-		/* Since the PLL may be shared, other cores can still be requesting it;
-		 * so we'll deassert the request but not wait for status to comply.
-		 */
-		AND_REG(osh, &regs->clk_ctl_st, ~CCS_ERSRC_REQ_PHYPLL);
-		tmp = R_REG(osh, &regs->clk_ctl_st);
-	}
-}
-
-void wlc_coredisable(struct wlc_hw_info *wlc_hw)
-{
-	bool dev_gone;
-
-	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
-
-	ASSERT(!wlc_hw->up);
-
-	dev_gone = DEVICEREMOVED(wlc_hw->wlc);
-
-	if (dev_gone)
-		return;
-
-	if (wlc_hw->noreset)
-		return;
-
-	/* radio off */
-	wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-
-	/* turn off analog core */
-	wlc_phy_anacore(wlc_hw->band->pi, OFF);
-
-	/* turn off PHYPLL to save power */
-	wlc_bmac_core_phypll_ctl(wlc_hw, false);
-
-	/* No need to set wlc->pub->radio_active = OFF
-	 * because this function needs down capability and
-	 * radio_active is designed for BCMNODOWN.
-	 */
-
-	/* remove gpio controls */
-	if (wlc_hw->ucode_dbgsel)
-		si_gpiocontrol(wlc_hw->sih, ~0, 0, GPIO_DRV_PRIORITY);
-
-	wlc_hw->clk = false;
-	si_core_disable(wlc_hw->sih, 0);
-	wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-}
-
-/* power both the pll and external oscillator on/off */
-void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want)
-{
-	WL_TRACE("wl%d: wlc_bmac_xtal: want %d\n", wlc_hw->unit, want);
-
-	/* dont power down if plldown is false or we must poll hw radio disable */
-	if (!want && wlc_hw->pllreq)
-		return;
-
-	if (wlc_hw->sih)
-		si_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want);
-
-	wlc_hw->sbclk = want;
-	if (!wlc_hw->sbclk) {
-		wlc_hw->clk = false;
-		if (wlc_hw->band && wlc_hw->band->pi)
-			wlc_phy_hw_clk_state_upd(wlc_hw->band->pi, false);
-	}
-}
-
-static void wlc_flushqueues(struct wlc_info *wlc)
-{
-	struct wlc_hw_info *wlc_hw = wlc->hw;
-	uint i;
-
-	wlc->txpend16165war = 0;
-
-	/* free any posted tx packets */
-	for (i = 0; i < NFIFO; i++)
-		if (wlc_hw->di[i]) {
-			dma_txreclaim(wlc_hw->di[i], HNDDMA_RANGE_ALL);
-			TXPKTPENDCLR(wlc, i);
-			WL_TRACE("wlc_flushqueues: pktpend fifo %d cleared\n",
-				 i);
-		}
-
-	/* free any posted rx packets */
-	dma_rxreclaim(wlc_hw->di[RX_FIFO]);
-	if (D11REV_IS(wlc_hw->corerev, 4))
-		dma_rxreclaim(wlc_hw->di[RX_TXSTATUS_FIFO]);
-}
-
-u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset)
-{
-	return wlc_bmac_read_objmem(wlc_hw, offset, OBJADDR_SHM_SEL);
-}
-
-void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v)
-{
-	wlc_bmac_write_objmem(wlc_hw, offset, v, OBJADDR_SHM_SEL);
-}
-
-/* Set a range of shared memory to a value.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void wlc_bmac_set_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v, int len)
-{
-	int i;
-
-	/* offset and len need to be even */
-	ASSERT((offset & 1) == 0);
-	ASSERT((len & 1) == 0);
-
-	if (len <= 0)
-		return;
-
-	for (i = 0; i < len; i += 2) {
-		wlc_bmac_write_objmem(wlc_hw, offset + i, v, OBJADDR_SHM_SEL);
-	}
-}
-
-static u16
-wlc_bmac_read_objmem(struct wlc_hw_info *wlc_hw, uint offset, u32 sel)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
-	volatile u16 *objdata_hi = objdata_lo + 1;
-	u16 v;
-
-	ASSERT((offset & 1) == 0);
-
-	W_REG(wlc_hw->osh, &regs->objaddr, sel | (offset >> 2));
-	(void)R_REG(wlc_hw->osh, &regs->objaddr);
-	if (offset & 2) {
-		v = R_REG(wlc_hw->osh, objdata_hi);
-	} else {
-		v = R_REG(wlc_hw->osh, objdata_lo);
-	}
-
-	return v;
-}
-
-static void
-wlc_bmac_write_objmem(struct wlc_hw_info *wlc_hw, uint offset, u16 v, u32 sel)
-{
-	d11regs_t *regs = wlc_hw->regs;
-	volatile u16 *objdata_lo = (volatile u16 *)&regs->objdata;
-	volatile u16 *objdata_hi = objdata_lo + 1;
-
-	ASSERT((offset & 1) == 0);
-
-	W_REG(wlc_hw->osh, &regs->objaddr, sel | (offset >> 2));
-	(void)R_REG(wlc_hw->osh, &regs->objaddr);
-	if (offset & 2) {
-		W_REG(wlc_hw->osh, objdata_hi, v);
-	} else {
-		W_REG(wlc_hw->osh, objdata_lo, v);
-	}
-}
-
-/* Copy a buffer to shared memory of specified type .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw, uint offset, const void *buf,
-		       int len, u32 sel)
-{
-	u16 v;
-	const u8 *p = (const u8 *)buf;
-	int i;
-
-	/* offset and len need to be even */
-	ASSERT((offset & 1) == 0);
-	ASSERT((len & 1) == 0);
-
-	if (len <= 0)
-		return;
-
-	for (i = 0; i < len; i += 2) {
-		v = p[i] | (p[i + 1] << 8);
-		wlc_bmac_write_objmem(wlc_hw, offset + i, v, sel);
-	}
-}
-
-/* Copy a piece of shared memory of specified type to a buffer .
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- * 'sel' selects the type of memory
- */
-void
-wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset, void *buf,
-			 int len, u32 sel)
-{
-	u16 v;
-	u8 *p = (u8 *) buf;
-	int i;
-
-	/* offset and len need to be even */
-	ASSERT((offset & 1) == 0);
-	ASSERT((len & 1) == 0);
-
-	if (len <= 0)
-		return;
-
-	for (i = 0; i < len; i += 2) {
-		v = wlc_bmac_read_objmem(wlc_hw, offset + i, sel);
-		p[i] = v & 0xFF;
-		p[i + 1] = (v >> 8) & 0xFF;
-	}
-}
-
-void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf, uint *len)
-{
-	WL_TRACE("wlc_bmac_copyfrom_vars, nvram vars totlen=%d\n",
-		 wlc_hw->vars_size);
-
-	*buf = wlc_hw->vars;
-	*len = wlc_hw->vars_size;
-}
-
-void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL, u16 LRL)
-{
-	wlc_hw->SRL = SRL;
-	wlc_hw->LRL = LRL;
-
-	/* write retry limit to SCR, shouldn't need to suspend */
-	if (wlc_hw->up) {
-		W_REG(wlc_hw->osh, &wlc_hw->regs->objaddr,
-		      OBJADDR_SCR_SEL | S_DOT11_SRC_LMT);
-		(void)R_REG(wlc_hw->osh, &wlc_hw->regs->objaddr);
-		W_REG(wlc_hw->osh, &wlc_hw->regs->objdata, wlc_hw->SRL);
-		W_REG(wlc_hw->osh, &wlc_hw->regs->objaddr,
-		      OBJADDR_SCR_SEL | S_DOT11_LRC_LMT);
-		(void)R_REG(wlc_hw->osh, &wlc_hw->regs->objaddr);
-		W_REG(wlc_hw->osh, &wlc_hw->regs->objdata, wlc_hw->LRL);
-	}
-}
-
-void wlc_bmac_set_noreset(struct wlc_hw_info *wlc_hw, bool noreset_flag)
-{
-	wlc_hw->noreset = noreset_flag;
-}
-
-void wlc_bmac_set_ucode_loaded(struct wlc_hw_info *wlc_hw, bool ucode_loaded)
-{
-	wlc_hw->ucode_loaded = ucode_loaded;
-}
-
-void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set, mbool req_bit)
-{
-	ASSERT(req_bit);
-
-	if (set) {
-		if (mboolisset(wlc_hw->pllreq, req_bit))
-			return;
-
-		mboolset(wlc_hw->pllreq, req_bit);
-
-		if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
-			if (!wlc_hw->sbclk) {
-				wlc_bmac_xtal(wlc_hw, ON);
-			}
-		}
-	} else {
-		if (!mboolisset(wlc_hw->pllreq, req_bit))
-			return;
-
-		mboolclr(wlc_hw->pllreq, req_bit);
-
-		if (mboolisset(wlc_hw->pllreq, WLC_PLLREQ_FLIP)) {
-			if (wlc_hw->sbclk) {
-				wlc_bmac_xtal(wlc_hw, OFF);
-			}
-		}
-	}
-
-	return;
-}
-
-void wlc_bmac_set_clk(struct wlc_hw_info *wlc_hw, bool on)
-{
-	if (on) {
-		/* power up pll and oscillator */
-		wlc_bmac_xtal(wlc_hw, ON);
-
-		/* enable core(s), ignore bandlocked
-		 * Leave with the same band selected as we entered
-		 */
-		wlc_bmac_corereset(wlc_hw, WLC_USE_COREFLAGS);
-	} else {
-		/* if already down, must skip the core disable */
-		if (wlc_hw->clk) {
-			/* disable core(s), ignore bandlocked */
-			wlc_coredisable(wlc_hw);
-		}
-		/* power down pll and oscillator */
-		wlc_bmac_xtal(wlc_hw, OFF);
-	}
-}
-
-/* this will be true for all ai chips */
-bool wlc_bmac_taclear(struct wlc_hw_info *wlc_hw, bool ta_ok)
-{
-	return true;
-}
-
-/* Lower down relevant GPIOs like LED when going down w/o
- * doing PCI config cycles or touching interrupts
- */
-void wlc_gpio_fast_deinit(struct wlc_hw_info *wlc_hw)
-{
-	if ((wlc_hw == NULL) || (wlc_hw->sih == NULL))
-		return;
-
-	/* Only chips with internal bus or PCIE cores or certain PCI cores
-	 * are able to switch cores w/o disabling interrupts
-	 */
-	if (!((wlc_hw->sih->bustype == SI_BUS) ||
-	      ((wlc_hw->sih->bustype == PCI_BUS) &&
-	       ((wlc_hw->sih->buscoretype == PCIE_CORE_ID) ||
-		(wlc_hw->sih->buscorerev >= 13)))))
-		return;
-
-	WL_TRACE("wl%d: %s\n", wlc_hw->unit, __func__);
-	return;
-}
-
-bool wlc_bmac_radio_hw(struct wlc_hw_info *wlc_hw, bool enable)
-{
-	/* Do not access Phy registers if core is not up */
-	if (si_iscoreup(wlc_hw->sih) == false)
-		return false;
-
-	if (enable) {
-		if (PMUCTL_ENAB(wlc_hw->sih)) {
-			AND_REG(wlc_hw->osh, &wlc_hw->regs->clk_ctl_st,
-				~CCS_FORCEHWREQOFF);
-			si_pmu_radio_enable(wlc_hw->sih, true);
-		}
-
-		wlc_phy_anacore(wlc_hw->band->pi, ON);
-		wlc_phy_switch_radio(wlc_hw->band->pi, ON);
-
-		/* resume d11 core */
-		wlc_enable_mac(wlc_hw->wlc);
-	} else {
-		/* suspend d11 core */
-		wlc_suspend_mac_and_wait(wlc_hw->wlc);
-
-		wlc_phy_switch_radio(wlc_hw->band->pi, OFF);
-		wlc_phy_anacore(wlc_hw->band->pi, OFF);
-
-		if (PMUCTL_ENAB(wlc_hw->sih)) {
-			si_pmu_radio_enable(wlc_hw->sih, false);
-			OR_REG(wlc_hw->osh, &wlc_hw->regs->clk_ctl_st,
-			       CCS_FORCEHWREQOFF);
-		}
-	}
-
-	return true;
-}
-
-u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate)
-{
-	u16 table_ptr;
-	u8 phy_rate, index;
-
-	/* get the phy specific rate encoding for the PLCP SIGNAL field */
-	/* XXX4321 fixup needed ? */
-	if (IS_OFDM(rate))
-		table_ptr = M_RT_DIRMAP_A;
-	else
-		table_ptr = M_RT_DIRMAP_B;
-
-	/* for a given rate, the LS-nibble of the PLCP SIGNAL field is
-	 * the index into the rate table.
-	 */
-	phy_rate = rate_info[rate] & RATE_MASK;
-	index = phy_rate & 0xf;
-
-	/* Find the SHM pointer to the rate table entry by looking in the
-	 * Direct-map Table
-	 */
-	return 2 * wlc_bmac_read_shm(wlc_hw, table_ptr + (index * 2));
-}
-
-void wlc_bmac_set_txpwr_percent(struct wlc_hw_info *wlc_hw, u8 val)
-{
-	wlc_phy_txpwr_percent_set(wlc_hw->band->pi, val);
-}
-
-void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail)
-{
-	wlc_hw->antsel_avail = antsel_avail;
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_bmac.h b/drivers/staging/brcm80211/sys/wlc_bmac.h
deleted file mode 100644
index 98150aa..0000000
--- a/drivers/staging/brcm80211/sys/wlc_bmac.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/* XXXXX this interface is under wlc.c by design
- * http://hwnbu-twiki.broadcom.com/bin/view/Mwgroup/WlBmacDesign
- *
- *        high driver files(e.g. wlc_ampdu.c etc)
- *             wlc.h/wlc.c
- *         wlc_bmac.h/wlc_bmac.c
- *
- *  So don't include this in files other than wlc.c, wlc_bmac* wl_rte.c(dongle port) and wl_phy.c
- *  create wrappers in wlc.c if needed
- */
-
-/* Revision and other info required from BMAC driver for functioning of high ONLY driver */
-typedef struct wlc_bmac_revinfo {
-	uint vendorid;		/* PCI vendor id */
-	uint deviceid;		/* device id of chip */
-
-	uint boardrev;		/* version # of particular board */
-	uint corerev;		/* core revision */
-	uint sromrev;		/* srom revision */
-	uint chiprev;		/* chip revision */
-	uint chip;		/* chip number */
-	uint chippkg;		/* chip package */
-	uint boardtype;		/* board type */
-	uint boardvendor;	/* board vendor */
-	uint bustype;		/* SB_BUS, PCI_BUS  */
-	uint buscoretype;	/* PCI_CORE_ID, PCIE_CORE_ID, PCMCIA_CORE_ID */
-	uint buscorerev;	/* buscore rev */
-	u32 issim;		/* chip is in simulation or emulation */
-
-	uint nbands;
-
-	struct band_info {
-		uint bandunit;	/* To match on both sides */
-		uint bandtype;	/* To match on both sides */
-		uint radiorev;
-		uint phytype;
-		uint phyrev;
-		uint anarev;
-		uint radioid;
-		bool abgphy_encore;
-	} band[MAXBANDS];
-} wlc_bmac_revinfo_t;
-
-/* dup state between BMAC(struct wlc_hw_info) and HIGH(struct wlc_info)
-   driver */
-typedef struct wlc_bmac_state {
-	u32 machwcap;	/* mac hw capibility */
-	u32 preamble_ovr;	/* preamble override */
-} wlc_bmac_state_t;
-
-enum {
-	IOV_BMAC_DIAG,
-	IOV_BMAC_SBGPIOTIMERVAL,
-	IOV_BMAC_SBGPIOOUT,
-	IOV_BMAC_CCGPIOCTRL,	/* CC GPIOCTRL REG */
-	IOV_BMAC_CCGPIOOUT,	/* CC GPIOOUT REG */
-	IOV_BMAC_CCGPIOOUTEN,	/* CC GPIOOUTEN REG */
-	IOV_BMAC_CCGPIOIN,	/* CC GPIOIN REG */
-	IOV_BMAC_WPSGPIO,	/* WPS push button GPIO pin */
-	IOV_BMAC_OTPDUMP,
-	IOV_BMAC_OTPSTAT,
-	IOV_BMAC_PCIEASPM,	/* obfuscation clkreq/aspm control */
-	IOV_BMAC_PCIEADVCORRMASK,	/* advanced correctable error mask */
-	IOV_BMAC_PCIECLKREQ,	/* PCIE 1.1 clockreq enab support */
-	IOV_BMAC_PCIELCREG,	/* PCIE LCREG */
-	IOV_BMAC_SBGPIOTIMERMASK,
-	IOV_BMAC_RFDISABLEDLY,
-	IOV_BMAC_PCIEREG,	/* PCIE REG */
-	IOV_BMAC_PCICFGREG,	/* PCI Config register */
-	IOV_BMAC_PCIESERDESREG,	/* PCIE SERDES REG (dev, 0}offset) */
-	IOV_BMAC_PCIEGPIOOUT,	/* PCIEOUT REG */
-	IOV_BMAC_PCIEGPIOOUTEN,	/* PCIEOUTEN REG */
-	IOV_BMAC_PCIECLKREQENCTRL,	/* clkreqenctrl REG (PCIE REV > 6.0 */
-	IOV_BMAC_DMALPBK,
-	IOV_BMAC_CCREG,
-	IOV_BMAC_COREREG,
-	IOV_BMAC_SDCIS,
-	IOV_BMAC_SDIO_DRIVE,
-	IOV_BMAC_OTPW,
-	IOV_BMAC_NVOTPW,
-	IOV_BMAC_SROM,
-	IOV_BMAC_SRCRC,
-	IOV_BMAC_CIS_SOURCE,
-	IOV_BMAC_CISVAR,
-	IOV_BMAC_OTPLOCK,
-	IOV_BMAC_OTP_CHIPID,
-	IOV_BMAC_CUSTOMVAR1,
-	IOV_BMAC_BOARDFLAGS,
-	IOV_BMAC_BOARDFLAGS2,
-	IOV_BMAC_WPSLED,
-	IOV_BMAC_NVRAM_SOURCE,
-	IOV_BMAC_OTP_RAW_READ,
-	IOV_BMAC_LAST
-};
-
-typedef enum {
-	BMAC_DUMP_GPIO_ID,
-	BMAC_DUMP_SI_ID,
-	BMAC_DUMP_SIREG_ID,
-	BMAC_DUMP_SICLK_ID,
-	BMAC_DUMP_CCREG_ID,
-	BMAC_DUMP_PCIEREG_ID,
-	BMAC_DUMP_PHYREG_ID,
-	BMAC_DUMP_PHYTBL_ID,
-	BMAC_DUMP_PHYTBL2_ID,
-	BMAC_DUMP_PHY_RADIOREG_ID,
-	BMAC_DUMP_LAST
-} wlc_bmac_dump_id_t;
-
-typedef enum {
-	WLCHW_STATE_ATTACH,
-	WLCHW_STATE_CLK,
-	WLCHW_STATE_UP,
-	WLCHW_STATE_ASSOC,
-	WLCHW_STATE_LAST
-} wlc_bmac_state_id_t;
-
-extern int wlc_bmac_attach(struct wlc_info *wlc, u16 vendor, u16 device,
-			   uint unit, bool piomode, struct osl_info *osh,
-			   void *regsva, uint bustype, void *btparam);
-extern int wlc_bmac_detach(struct wlc_info *wlc);
-extern void wlc_bmac_watchdog(void *arg);
-extern void wlc_bmac_info_init(struct wlc_hw_info *wlc_hw);
-
-/* up/down, reset, clk */
-extern void wlc_bmac_xtal(struct wlc_hw_info *wlc_hw, bool want);
-
-extern void wlc_bmac_copyto_objmem(struct wlc_hw_info *wlc_hw,
-				   uint offset, const void *buf, int len,
-				   u32 sel);
-extern void wlc_bmac_copyfrom_objmem(struct wlc_hw_info *wlc_hw, uint offset,
-				     void *buf, int len, u32 sel);
-#define wlc_bmac_copyfrom_shm(wlc_hw, offset, buf, len)                 \
-	wlc_bmac_copyfrom_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-#define wlc_bmac_copyto_shm(wlc_hw, offset, buf, len)                   \
-	wlc_bmac_copyto_objmem(wlc_hw, offset, buf, len, OBJADDR_SHM_SEL)
-
-extern void wlc_bmac_core_phy_clk(struct wlc_hw_info *wlc_hw, bool clk);
-extern void wlc_bmac_core_phypll_reset(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_core_phypll_ctl(struct wlc_hw_info *wlc_hw, bool on);
-extern void wlc_bmac_phyclk_fgc(struct wlc_hw_info *wlc_hw, bool clk);
-extern void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk);
-extern void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags);
-extern void wlc_bmac_reset(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
-			  bool mute);
-extern int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags);
-extern void wlc_bmac_switch_macfreq(struct wlc_hw_info *wlc_hw, u8 spurmode);
-
-/* chanspec, ucode interface */
-extern int wlc_bmac_bandtype(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_set_chanspec(struct wlc_hw_info *wlc_hw,
-				  chanspec_t chanspec,
-				  bool mute, struct txpwr_limits *txpwr);
-
-extern void wlc_bmac_txfifo(struct wlc_hw_info *wlc_hw, uint fifo, void *p,
-			    bool commit, u16 frameid, u8 txpktpend);
-extern int wlc_bmac_xmtfifo_sz_get(struct wlc_hw_info *wlc_hw, uint fifo,
-				   uint *blocks);
-extern void wlc_bmac_mhf(struct wlc_hw_info *wlc_hw, u8 idx, u16 mask,
-			 u16 val, int bands);
-extern void wlc_bmac_mctrl(struct wlc_hw_info *wlc_hw, u32 mask, u32 val);
-extern u16 wlc_bmac_mhf_get(struct wlc_hw_info *wlc_hw, u8 idx, int bands);
-extern int wlc_bmac_xmtfifo_sz_set(struct wlc_hw_info *wlc_hw, uint fifo,
-				   uint blocks);
-extern void wlc_bmac_txant_set(struct wlc_hw_info *wlc_hw, u16 phytxant);
-extern u16 wlc_bmac_get_txant(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_antsel_type_set(struct wlc_hw_info *wlc_hw,
-				     u8 antsel_type);
-extern int wlc_bmac_revinfo_get(struct wlc_hw_info *wlc_hw,
-				wlc_bmac_revinfo_t *revinfo);
-extern int wlc_bmac_state_get(struct wlc_hw_info *wlc_hw,
-			      wlc_bmac_state_t *state);
-extern void wlc_bmac_write_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v);
-extern u16 wlc_bmac_read_shm(struct wlc_hw_info *wlc_hw, uint offset);
-extern void wlc_bmac_set_shm(struct wlc_hw_info *wlc_hw, uint offset, u16 v,
-			     int len);
-extern void wlc_bmac_write_template_ram(struct wlc_hw_info *wlc_hw, int offset,
-					int len, void *buf);
-extern void wlc_bmac_copyfrom_vars(struct wlc_hw_info *wlc_hw, char **buf,
-				   uint *len);
-
-extern void wlc_bmac_process_ps_switch(struct wlc_hw_info *wlc,
-				       struct ether_addr *ea, s8 ps_on);
-extern void wlc_bmac_hw_etheraddr(struct wlc_hw_info *wlc_hw,
-				  struct ether_addr *ea);
-extern void wlc_bmac_set_hw_etheraddr(struct wlc_hw_info *wlc_hw,
-				      struct ether_addr *ea);
-extern bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw);
-
-extern bool wlc_bmac_radio_read_hwdisabled(struct wlc_hw_info *wlc_hw);
-extern void wlc_bmac_set_shortslot(struct wlc_hw_info *wlc_hw, bool shortslot);
-extern void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool want, mbool flags);
-extern void wlc_bmac_set_deaf(struct wlc_hw_info *wlc_hw, bool user_flag);
-extern void wlc_bmac_band_stf_ss_set(struct wlc_hw_info *wlc_hw, u8 stf_mode);
-
-extern void wlc_bmac_wait_for_wake(struct wlc_hw_info *wlc_hw);
-extern bool wlc_bmac_tx_fifo_suspended(struct wlc_hw_info *wlc_hw,
-				       uint tx_fifo);
-extern void wlc_bmac_tx_fifo_suspend(struct wlc_hw_info *wlc_hw, uint tx_fifo);
-extern void wlc_bmac_tx_fifo_resume(struct wlc_hw_info *wlc_hw, uint tx_fifo);
-
-extern void wlc_ucode_wake_override_set(struct wlc_hw_info *wlc_hw,
-					u32 override_bit);
-extern void wlc_ucode_wake_override_clear(struct wlc_hw_info *wlc_hw,
-					  u32 override_bit);
-
-extern void wlc_bmac_set_rcmta(struct wlc_hw_info *wlc_hw, int idx,
-			       const struct ether_addr *addr);
-extern void wlc_bmac_set_addrmatch(struct wlc_hw_info *wlc_hw,
-				   int match_reg_offset,
-				   const struct ether_addr *addr);
-extern void wlc_bmac_write_hw_bcntemplates(struct wlc_hw_info *wlc_hw,
-					   void *bcn, int len, bool both);
-
-extern void wlc_bmac_read_tsf(struct wlc_hw_info *wlc_hw, u32 *tsf_l_ptr,
-			      u32 *tsf_h_ptr);
-extern void wlc_bmac_set_cwmin(struct wlc_hw_info *wlc_hw, u16 newmin);
-extern void wlc_bmac_set_cwmax(struct wlc_hw_info *wlc_hw, u16 newmax);
-extern void wlc_bmac_set_noreset(struct wlc_hw_info *wlc, bool noreset_flag);
-extern void wlc_bmac_set_ucode_loaded(struct wlc_hw_info *wlc,
-				      bool ucode_loaded);
-
-extern void wlc_bmac_retrylimit_upd(struct wlc_hw_info *wlc_hw, u16 SRL,
-				    u16 LRL);
-
-extern void wlc_bmac_fifoerrors(struct wlc_hw_info *wlc_hw);
-
-
-/* API for BMAC driver (e.g. wlc_phy.c etc) */
-
-extern void wlc_bmac_bw_set(struct wlc_hw_info *wlc_hw, u16 bw);
-extern void wlc_bmac_pllreq(struct wlc_hw_info *wlc_hw, bool set,
-			    mbool req_bit);
-extern void wlc_bmac_set_clk(struct wlc_hw_info *wlc_hw, bool on);
-extern bool wlc_bmac_taclear(struct wlc_hw_info *wlc_hw, bool ta_ok);
-extern void wlc_bmac_hw_up(struct wlc_hw_info *wlc_hw);
-
-extern void wlc_bmac_dump(struct wlc_hw_info *wlc_hw, struct bcmstrbuf *b,
-			  wlc_bmac_dump_id_t dump_id);
-extern void wlc_gpio_fast_deinit(struct wlc_hw_info *wlc_hw);
-
-extern bool wlc_bmac_radio_hw(struct wlc_hw_info *wlc_hw, bool enable);
-extern u16 wlc_bmac_rate_shm_offset(struct wlc_hw_info *wlc_hw, u8 rate);
-
-extern void wlc_bmac_assert_type_set(struct wlc_hw_info *wlc_hw, u32 type);
-extern void wlc_bmac_set_txpwr_percent(struct wlc_hw_info *wlc_hw, u8 val);
-extern void wlc_bmac_blink_sync(struct wlc_hw_info *wlc_hw, u32 led_pins);
-extern void wlc_bmac_ifsctl_edcrs_set(struct wlc_hw_info *wlc_hw, bool abie,
-				      bool isht);
-
-extern void wlc_bmac_antsel_set(struct wlc_hw_info *wlc_hw, u32 antsel_avail);
diff --git a/drivers/staging/brcm80211/sys/wlc_bsscfg.h b/drivers/staging/brcm80211/sys/wlc_bsscfg.h
deleted file mode 100644
index d6a1971..0000000
--- a/drivers/staging/brcm80211/sys/wlc_bsscfg.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_BSSCFG_H_
-#define _WLC_BSSCFG_H_
-
-#include <wlc_types.h>
-
-/* Check if a particular BSS config is AP or STA */
-#define BSSCFG_AP(cfg)		(0)
-#define BSSCFG_STA(cfg)		(1)
-
-#define BSSCFG_IBSS(cfg)	(!(cfg)->BSS)
-
-/* forward declarations */
-typedef struct wlc_bsscfg wlc_bsscfg_t;
-
-#include <wlc_rate.h>
-
-#define NTXRATE			64	/* # tx MPDUs rate is reported for */
-#define MAXMACLIST		64	/* max # source MAC matches */
-#define BCN_TEMPLATE_COUNT 	2
-
-/* Iterator for "associated" STA bss configs:
-   (struct wlc_info *wlc, int idx, wlc_bsscfg_t *cfg) */
-#define FOREACH_AS_STA(wlc, idx, cfg) \
-	for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) \
-		if ((cfg = (wlc)->bsscfg[idx]) && BSSCFG_STA(cfg) && cfg->associated)
-
-/* As above for all non-NULL BSS configs */
-#define FOREACH_BSS(wlc, idx, cfg) \
-	for (idx = 0; (int) idx < WLC_MAXBSSCFG; idx++) \
-		if ((cfg = (wlc)->bsscfg[idx]))
-
-/* BSS configuration state */
-struct wlc_bsscfg {
-	struct wlc_info *wlc;	/* wlc to which this bsscfg belongs to. */
-	bool up;		/* is this configuration up operational */
-	bool enable;		/* is this configuration enabled */
-	bool associated;	/* is BSS in ASSOCIATED state */
-	bool BSS;		/* infraustructure or adhac */
-	bool dtim_programmed;
-#ifdef LATER
-	bool _ap;		/* is this configuration an AP */
-	struct wlc_if *wlcif;	/* virtual interface, NULL for primary bsscfg */
-	void *sup;		/* pointer to supplicant state */
-	s8 sup_type;		/* type of supplicant */
-	bool sup_enable_wpa;	/* supplicant WPA on/off */
-	void *authenticator;	/* pointer to authenticator state */
-	bool sup_auth_pending;	/* flag for auth timeout */
-#endif
-	u8 SSID_len;		/* the length of SSID */
-	u8 SSID[DOT11_MAX_SSID_LEN];	/* SSID string */
-	struct scb *bcmc_scb[MAXBANDS];	/* one bcmc_scb per band */
-	s8 _idx;		/* the index of this bsscfg,
-				 * assigned at wlc_bsscfg_alloc()
-				 */
-	/* MAC filter */
-	uint nmac;		/* # of entries on maclist array */
-	int macmode;		/* allow/deny stations on maclist array */
-	struct ether_addr *maclist;	/* list of source MAC addrs to match */
-
-	/* security */
-	u32 wsec;		/* wireless security bitvec */
-	s16 auth;		/* 802.11 authentication: Open, Shared Key, WPA */
-	s16 openshared;	/* try Open auth first, then Shared Key */
-	bool wsec_restrict;	/* drop unencrypted packets if wsec is enabled */
-	bool eap_restrict;	/* restrict data until 802.1X auth succeeds */
-	u16 WPA_auth;	/* WPA: authenticated key management */
-	bool wpa2_preauth;	/* default is true, wpa_cap sets value */
-	bool wsec_portopen;	/* indicates keys are plumbed */
-	wsec_iv_t wpa_none_txiv;	/* global txiv for WPA_NONE, tkip and aes */
-	int wsec_index;		/* 0-3: default tx key, -1: not set */
-	wsec_key_t *bss_def_keys[WLC_DEFAULT_KEYS];	/* default key storage */
-
-	/* TKIP countermeasures */
-	bool tkip_countermeasures;	/* flags TKIP no-assoc period */
-	u32 tk_cm_dt;	/* detect timer */
-	u32 tk_cm_bt;	/* blocking timer */
-	u32 tk_cm_bt_tmstmp;	/* Timestamp when TKIP BT is activated */
-	bool tk_cm_activate;	/* activate countermeasures after EAPOL-Key sent */
-
-	struct ether_addr BSSID;	/* BSSID (associated) */
-	struct ether_addr cur_etheraddr;	/* h/w address */
-	u16 bcmc_fid;	/* the last BCMC FID queued to TX_BCMC_FIFO */
-	u16 bcmc_fid_shm;	/* the last BCMC FID written to shared mem */
-
-	u32 flags;		/* WLC_BSSCFG flags; see below */
-
-	u8 *bcn;		/* AP beacon */
-	uint bcn_len;		/* AP beacon length */
-	bool ar_disassoc;	/* disassociated in associated recreation */
-
-	int auth_atmptd;	/* auth type (open/shared) attempted */
-
-	pmkid_cand_t pmkid_cand[MAXPMKID];	/* PMKID candidate list */
-	uint npmkid_cand;	/* num PMKID candidates */
-	pmkid_t pmkid[MAXPMKID];	/* PMKID cache */
-	uint npmkid;		/* num cached PMKIDs */
-
-	wlc_bss_info_t *target_bss;	/* BSS parms during tran. to ASSOCIATED state */
-	wlc_bss_info_t *current_bss;	/* BSS parms in ASSOCIATED state */
-
-	/* PM states */
-	bool PMawakebcn;	/* bcn recvd during current waking state */
-	bool PMpending;		/* waiting for tx status with PM indicated set */
-	bool priorPMstate;	/* Detecting PM state transitions */
-	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
-
-	/* BSSID entry in RCMTA, use the wsec key management infrastructure to
-	 * manage the RCMTA entries.
-	 */
-	wsec_key_t *rcmta;
-
-	/* 'unique' ID of this bsscfg, assigned at bsscfg allocation */
-	u16 ID;
-
-	uint txrspecidx;	/* index into tx rate circular buffer */
-	ratespec_t txrspec[NTXRATE][2];	/* circular buffer of prev MPDUs tx rates */
-};
-
-#define WLC_BSSCFG_11N_DISABLE	0x1000	/* Do not advertise .11n IEs for this BSS */
-#define WLC_BSSCFG_HW_BCN	0x20	/* The BSS is generating beacons in HW */
-
-#define HWBCN_ENAB(cfg)		(((cfg)->flags & WLC_BSSCFG_HW_BCN) != 0)
-#define HWPRB_ENAB(cfg)		(((cfg)->flags & WLC_BSSCFG_HW_PRB) != 0)
-
-extern void wlc_bsscfg_ID_assign(struct wlc_info *wlc, wlc_bsscfg_t * bsscfg);
-
-/* Extend N_ENAB to per-BSS */
-#define BSS_N_ENAB(wlc, cfg) \
-	(N_ENAB((wlc)->pub) && !((cfg)->flags & WLC_BSSCFG_11N_DISABLE))
-
-#define MBSS_BCN_ENAB(cfg)       0
-#define MBSS_PRB_ENAB(cfg)       0
-#define SOFTBCN_ENAB(pub)    (0)
-#define SOFTPRB_ENAB(pub)    (0)
-#define wlc_bsscfg_tx_check(a) do { } while (0);
-
-#endif				/* _WLC_BSSCFG_H_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_cfg.h b/drivers/staging/brcm80211/sys/wlc_cfg.h
deleted file mode 100644
index 3decb7d..0000000
--- a/drivers/staging/brcm80211/sys/wlc_cfg.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_cfg_h_
-#define _wlc_cfg_h_
-
-#define NBANDS(wlc) ((wlc)->pub->_nbands)
-#define NBANDS_PUB(pub) ((pub)->_nbands)
-#define NBANDS_HW(hw) ((hw)->_nbands)
-
-#define IS_SINGLEBAND_5G(device)	0
-
-/* **** Core type/rev defaults **** */
-#define D11_DEFAULT	0x0fffffb0	/* Supported  D11 revs: 4, 5, 7-27
-					 * also need to update wlc.h MAXCOREREV
-					 */
-
-#define NPHY_DEFAULT	0x000001ff	/* Supported nphy revs:
-					 *      0       4321a0
-					 *      1       4321a1
-					 *      2       4321b0/b1/c0/c1
-					 *      3       4322a0
-					 *      4       4322a1
-					 *      5       4716a0
-					 *      6       43222a0, 43224a0
-					 *      7       43226a0
-					 *      8       5357a0, 43236a0
-					 */
-
-#define LCNPHY_DEFAULT	0x00000007	/* Supported lcnphy revs:
-					 *      0       4313a0, 4336a0, 4330a0
-					 *      1
-					 *      2       4330a0
-					 */
-
-#define SSLPNPHY_DEFAULT 0x0000000f	/* Supported sslpnphy revs:
-					 *      0       4329a0/k0
-					 *      1       4329b0/4329C0
-					 *      2       4319a0
-					 *      3       5356a0
-					 */
-
-
-/* For undefined values, use defaults */
-#ifndef D11CONF
-#define D11CONF	D11_DEFAULT
-#endif
-#ifndef NCONF
-#define NCONF	NPHY_DEFAULT
-#endif
-#ifndef LCNCONF
-#define LCNCONF	LCNPHY_DEFAULT
-#endif
-
-#ifndef SSLPNCONF
-#define SSLPNCONF	SSLPNPHY_DEFAULT
-#endif
-
-#define BAND2G
-#define BAND5G
-#define WLANTSEL	1
-
-/********************************************************************
- * Phy/Core Configuration.  Defines macros to to check core phy/rev *
- * compile-time configuration.  Defines default core support.       *
- * ******************************************************************
- */
-
-/* Basic macros to check a configuration bitmask */
-
-#define CONF_HAS(config, val)	((config) & (1 << (val)))
-#define CONF_MSK(config, mask)	((config) & (mask))
-#define MSK_RANGE(low, hi)	((1 << ((hi)+1)) - (1 << (low)))
-#define CONF_RANGE(config, low, hi) (CONF_MSK(config, MSK_RANGE(low, high)))
-
-#define CONF_IS(config, val)	((config) == (1 << (val)))
-#define CONF_GE(config, val)	((config) & (0-(1 << (val))))
-#define CONF_GT(config, val)	((config) & (0-2*(1 << (val))))
-#define CONF_LT(config, val)	((config) & ((1 << (val))-1))
-#define CONF_LE(config, val)	((config) & (2*(1 << (val))-1))
-
-/* Wrappers for some of the above, specific to config constants */
-
-#define NCONF_HAS(val)	CONF_HAS(NCONF, val)
-#define NCONF_MSK(mask)	CONF_MSK(NCONF, mask)
-#define NCONF_IS(val)	CONF_IS(NCONF, val)
-#define NCONF_GE(val)	CONF_GE(NCONF, val)
-#define NCONF_GT(val)	CONF_GT(NCONF, val)
-#define NCONF_LT(val)	CONF_LT(NCONF, val)
-#define NCONF_LE(val)	CONF_LE(NCONF, val)
-
-#define LCNCONF_HAS(val)	CONF_HAS(LCNCONF, val)
-#define LCNCONF_MSK(mask)	CONF_MSK(LCNCONF, mask)
-#define LCNCONF_IS(val)		CONF_IS(LCNCONF, val)
-#define LCNCONF_GE(val)		CONF_GE(LCNCONF, val)
-#define LCNCONF_GT(val)		CONF_GT(LCNCONF, val)
-#define LCNCONF_LT(val)		CONF_LT(LCNCONF, val)
-#define LCNCONF_LE(val)		CONF_LE(LCNCONF, val)
-
-#define D11CONF_HAS(val) CONF_HAS(D11CONF, val)
-#define D11CONF_MSK(mask) CONF_MSK(D11CONF, mask)
-#define D11CONF_IS(val)	CONF_IS(D11CONF, val)
-#define D11CONF_GE(val)	CONF_GE(D11CONF, val)
-#define D11CONF_GT(val)	CONF_GT(D11CONF, val)
-#define D11CONF_LT(val)	CONF_LT(D11CONF, val)
-#define D11CONF_LE(val)	CONF_LE(D11CONF, val)
-
-#define PHYCONF_HAS(val) CONF_HAS(PHYTYPE, val)
-#define PHYCONF_IS(val)	CONF_IS(PHYTYPE, val)
-
-#define NREV_IS(var, val)	(NCONF_HAS(val) && (NCONF_IS(val) || ((var) == (val))))
-#define NREV_GE(var, val)	(NCONF_GE(val) && (!NCONF_LT(val) || ((var) >= (val))))
-#define NREV_GT(var, val)	(NCONF_GT(val) && (!NCONF_LE(val) || ((var) > (val))))
-#define NREV_LT(var, val)	(NCONF_LT(val) && (!NCONF_GE(val) || ((var) < (val))))
-#define NREV_LE(var, val)	(NCONF_LE(val) && (!NCONF_GT(val) || ((var) <= (val))))
-
-#define LCNREV_IS(var, val)	(LCNCONF_HAS(val) && (LCNCONF_IS(val) || ((var) == (val))))
-#define LCNREV_GE(var, val)	(LCNCONF_GE(val) && (!LCNCONF_LT(val) || ((var) >= (val))))
-#define LCNREV_GT(var, val)	(LCNCONF_GT(val) && (!LCNCONF_LE(val) || ((var) > (val))))
-#define LCNREV_LT(var, val)	(LCNCONF_LT(val) && (!LCNCONF_GE(val) || ((var) < (val))))
-#define LCNREV_LE(var, val)	(LCNCONF_LE(val) && (!LCNCONF_GT(val) || ((var) <= (val))))
-
-#define D11REV_IS(var, val)	(D11CONF_HAS(val) && (D11CONF_IS(val) || ((var) == (val))))
-#define D11REV_GE(var, val)	(D11CONF_GE(val) && (!D11CONF_LT(val) || ((var) >= (val))))
-#define D11REV_GT(var, val)	(D11CONF_GT(val) && (!D11CONF_LE(val) || ((var) > (val))))
-#define D11REV_LT(var, val)	(D11CONF_LT(val) && (!D11CONF_GE(val) || ((var) < (val))))
-#define D11REV_LE(var, val)	(D11CONF_LE(val) && (!D11CONF_GT(val) || ((var) <= (val))))
-
-#define PHYTYPE_IS(var, val)	(PHYCONF_HAS(val) && (PHYCONF_IS(val) || ((var) == (val))))
-
-/* Finally, early-exit from switch case if anyone wants it... */
-
-#define CASECHECK(config, val)	if (!(CONF_HAS(config, val))) break
-#define CASEMSK(config, mask)	if (!(CONF_MSK(config, mask))) break
-
-#if (D11CONF ^ (D11CONF & D11_DEFAULT))
-#error "Unsupported MAC revision configured"
-#endif
-#if (NCONF ^ (NCONF & NPHY_DEFAULT))
-#error "Unsupported NPHY revision configured"
-#endif
-#if (LCNCONF ^ (LCNCONF & LCNPHY_DEFAULT))
-#error "Unsupported LPPHY revision configured"
-#endif
-
-/* *** Consistency checks *** */
-#if !D11CONF
-#error "No MAC revisions configured!"
-#endif
-
-#if !NCONF && !LCNCONF && !SSLPNCONF
-#error "No PHY configured!"
-#endif
-
-/* Set up PHYTYPE automatically: (depends on PHY_TYPE_X, from d11.h) */
-
-#define _PHYCONF_N (1 << PHY_TYPE_N)
-
-#if LCNCONF
-#define _PHYCONF_LCN (1 << PHY_TYPE_LCN)
-#else
-#define _PHYCONF_LCN 0
-#endif				/* LCNCONF */
-
-#if SSLPNCONF
-#define _PHYCONF_SSLPN (1 << PHY_TYPE_SSN)
-#else
-#define _PHYCONF_SSLPN 0
-#endif				/* SSLPNCONF */
-
-#define PHYTYPE (_PHYCONF_N | _PHYCONF_LCN | _PHYCONF_SSLPN)
-
-/* Utility macro to identify 802.11n (HT) capable PHYs */
-#define PHYTYPE_11N_CAP(phytype) \
-	(PHYTYPE_IS(phytype, PHY_TYPE_N) ||	\
-	 PHYTYPE_IS(phytype, PHY_TYPE_LCN) || \
-	 PHYTYPE_IS(phytype, PHY_TYPE_SSN))
-
-/* Last but not least: shorter wlc-specific var checks */
-#define WLCISNPHY(band)		PHYTYPE_IS((band)->phytype, PHY_TYPE_N)
-#define WLCISLCNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_LCN)
-#define WLCISSSLPNPHY(band)	PHYTYPE_IS((band)->phytype, PHY_TYPE_SSN)
-
-#define WLC_PHY_11N_CAP(band)	PHYTYPE_11N_CAP((band)->phytype)
-
-/**********************************************************************
- * ------------- End of Core phy/rev configuration. ----------------- *
- * ********************************************************************
- */
-
-/*************************************************
- * Defaults for tunables (e.g. sizing constants)
- *
- * For each new tunable, add a member to the end
- * of wlc_tunables_t in wlc_pub.h to enable
- * runtime checks of tunable values. (Directly
- * using the macros in code invalidates ROM code)
- *
- * ***********************************************
- */
-#ifndef NTXD
-#define NTXD		256	/* Max # of entries in Tx FIFO based on 4kb page size */
-#endif				/* NTXD */
-#ifndef NRXD
-#define NRXD		256	/* Max # of entries in Rx FIFO based on 4kb page size */
-#endif				/* NRXD */
-
-#ifndef NRXBUFPOST
-#define	NRXBUFPOST	32	/* try to keep this # rbufs posted to the chip */
-#endif				/* NRXBUFPOST */
-
-#ifndef MAXSCB			/* station control blocks in cache */
-#define MAXSCB		32	/* Maximum SCBs in cache for STA */
-#endif				/* MAXSCB */
-
-#ifndef AMPDU_NUM_MPDU
-#define AMPDU_NUM_MPDU		16	/* max allowed number of mpdus in an ampdu (2 streams) */
-#endif				/* AMPDU_NUM_MPDU */
-
-#ifndef AMPDU_NUM_MPDU_3STREAMS
-#define AMPDU_NUM_MPDU_3STREAMS	32	/* max allowed number of mpdus in an ampdu for 3+ streams */
-#endif				/* AMPDU_NUM_MPDU_3STREAMS */
-
-/* Count of packet callback structures. either of following
- * 1. Set to the number of SCBs since a STA
- * can queue up a rate callback for each IBSS STA it knows about, and an AP can
- * queue up an "are you there?" Null Data callback for each associated STA
- * 2. controlled by tunable config file
- */
-#ifndef MAXPKTCB
-#define MAXPKTCB	MAXSCB	/* Max number of packet callbacks */
-#endif				/* MAXPKTCB */
-
-#ifndef CTFPOOLSZ
-#define CTFPOOLSZ       128
-#endif				/* CTFPOOLSZ */
-
-/* NetBSD also needs to keep track of this */
-#define WLC_MAX_UCODE_BSS	(16)	/* Number of BSS handled in ucode bcn/prb */
-#define WLC_MAX_UCODE_BSS4	(4)	/* Number of BSS handled in sw bcn/prb */
-#ifndef WLC_MAXBSSCFG
-#define WLC_MAXBSSCFG		(1)	/* max # BSS configs */
-#endif				/* WLC_MAXBSSCFG */
-
-#ifndef MAXBSS
-#define MAXBSS		64	/* max # available networks */
-#endif				/* MAXBSS */
-
-#ifndef WLC_DATAHIWAT
-#define WLC_DATAHIWAT		50	/* data msg txq hiwat mark */
-#endif				/* WLC_DATAHIWAT */
-
-#ifndef WLC_AMPDUDATAHIWAT
-#define WLC_AMPDUDATAHIWAT 255
-#endif				/* WLC_AMPDUDATAHIWAT */
-
-/* bounded rx loops */
-#ifndef RXBND
-#define RXBND		8	/* max # frames to process in wlc_recv() */
-#endif				/* RXBND */
-#ifndef TXSBND
-#define TXSBND		8	/* max # tx status to process in wlc_txstatus() */
-#endif				/* TXSBND */
-
-#define BAND_5G(bt)	((bt) == WLC_BAND_5G)
-#define BAND_2G(bt)	((bt) == WLC_BAND_2G)
-
-#define WLBANDINITDATA(_data)	_data
-#define WLBANDINITFN(_fn)	_fn
-
-#define WLANTSEL_ENAB(wlc)	1
-
-#endif				/* _wlc_cfg_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_channel.c b/drivers/staging/brcm80211/sys/wlc_channel.c
deleted file mode 100644
index a35c152..0000000
--- a/drivers/staging/brcm80211/sys/wlc_channel.c
+++ /dev/null
@@ -1,1609 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <bcmdefs.h>
-#include <wlc_cfg.h>
-#include <osl.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <wlioctl.h>
-#include <wlc_pub.h>
-#include <wlc_key.h>
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_bmac.h>
-#include <wlc_stf.h>
-#include <wlc_channel.h>
-#include <wl_dbg.h>
-
-typedef struct wlc_cm_band {
-	u8 locale_flags;	/* locale_info_t flags */
-	chanvec_t valid_channels;	/* List of valid channels in the country */
-	const chanvec_t *restricted_channels;	/* List of restricted use channels */
-	const chanvec_t *radar_channels;	/* List of radar sensitive channels */
-	u8 PAD[8];
-} wlc_cm_band_t;
-
-struct wlc_cm_info {
-	struct wlc_pub *pub;
-	struct wlc_info *wlc;
-	char srom_ccode[WLC_CNTRY_BUF_SZ];	/* Country Code in SROM */
-	uint srom_regrev;	/* Regulatory Rev for the SROM ccode */
-	const country_info_t *country;	/* current country def */
-	char ccode[WLC_CNTRY_BUF_SZ];	/* current internal Country Code */
-	uint regrev;		/* current Regulatory Revision */
-	char country_abbrev[WLC_CNTRY_BUF_SZ];	/* current advertised ccode */
-	wlc_cm_band_t bandstate[MAXBANDS];	/* per-band state (one per phy/radio) */
-	/* quiet channels currently for radar sensitivity or 11h support */
-	chanvec_t quiet_channels;	/* channels on which we cannot transmit */
-};
-
-static int wlc_channels_init(wlc_cm_info_t *wlc_cm,
-			     const country_info_t *country);
-static void wlc_set_country_common(wlc_cm_info_t *wlc_cm,
-				   const char *country_abbrev,
-				   const char *ccode, uint regrev,
-				   const country_info_t *country);
-static int wlc_country_aggregate_map(wlc_cm_info_t *wlc_cm, const char *ccode,
-				     char *mapped_ccode, uint *mapped_regrev);
-static const country_info_t *wlc_country_lookup_direct(const char *ccode,
-						       uint regrev);
-static const country_info_t *wlc_countrycode_map(wlc_cm_info_t *wlc_cm,
-						 const char *ccode,
-						 char *mapped_ccode,
-						 uint *mapped_regrev);
-static void wlc_channels_commit(wlc_cm_info_t *wlc_cm);
-static bool wlc_japan_ccode(const char *ccode);
-static void wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm_info_t *
-								 wlc_cm,
-								 struct
-								 txpwr_limits
-								 *txpwr,
-								 u8
-								 local_constraint_qdbm);
-void wlc_locale_add_channels(chanvec_t *target, const chanvec_t *channels);
-static const locale_mimo_info_t *wlc_get_mimo_2g(u8 locale_idx);
-static const locale_mimo_info_t *wlc_get_mimo_5g(u8 locale_idx);
-
-/* QDB() macro takes a dB value and converts to a quarter dB value */
-#ifdef QDB
-#undef QDB
-#endif
-#define QDB(n) ((n) * WLC_TXPWR_DB_FACTOR)
-
-/* Regulatory Matrix Spreadsheet (CLM) MIMO v3.7.9 */
-
-/*
- * Some common channel sets
- */
-
-/* No channels */
-static const chanvec_t chanvec_none = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 2.4 GHz HW channels */
-const chanvec_t chanvec_all_2G = {
-	{0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* All 5 GHz HW channels */
-const chanvec_t chanvec_all_5G = {
-	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x11, 0x11,
-	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,
-	 0x11, 0x11, 0x20, 0x22, 0x22, 0x00, 0x00, 0x11,
-	 0x11, 0x11, 0x11, 0x01}
-};
-
-/*
- * Radar channel sets
- */
-
-/* No radar */
-#define radar_set_none chanvec_none
-
-static const chanvec_t radar_set1 = {	/* Channels 52 - 64, 100 - 140 */
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,	/* 52 - 60 */
-	 0x01, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x11,	/* 64, 100 - 124 */
-	 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 128 - 140 */
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/*
- * Restricted channel sets
- */
-
-#define restricted_set_none chanvec_none
-
-/* Channels 34, 38, 42, 46 */
-static const chanvec_t restricted_set_japan_legacy = {
-	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12, 13 */
-static const chanvec_t restricted_set_2g_short = {
-	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channel 165 */
-static const chanvec_t restricted_chan_165 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 36 - 48 & 149 - 165 */
-static const chanvec_t restricted_low_hi = {
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x20, 0x22, 0x22, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Channels 12 - 14 */
-static const chanvec_t restricted_set_12_13_14 = {
-	{0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-#define  LOCALE_CHAN_01_11	 (1<<0)
-#define  LOCALE_CHAN_12_13	 (1<<1)
-#define  LOCALE_CHAN_14		 (1<<2)
-#define  LOCALE_SET_5G_LOW_JP1   (1<<3)	/* 34-48, step 2 */
-#define  LOCALE_SET_5G_LOW_JP2   (1<<4)	/* 34-46, step 4 */
-#define  LOCALE_SET_5G_LOW1      (1<<5)	/* 36-48, step 4 */
-#define  LOCALE_SET_5G_LOW2      (1<<6)	/* 52 */
-#define  LOCALE_SET_5G_LOW3      (1<<7)	/* 56-64, step 4 */
-#define  LOCALE_SET_5G_MID1      (1<<8)	/* 100-116, step 4 */
-#define  LOCALE_SET_5G_MID2	 (1<<9)	/* 120-124, step 4 */
-#define  LOCALE_SET_5G_MID3      (1<<10)	/* 128 */
-#define  LOCALE_SET_5G_HIGH1     (1<<11)	/* 132-140, step 4 */
-#define  LOCALE_SET_5G_HIGH2     (1<<12)	/* 149-161, step 4 */
-#define  LOCALE_SET_5G_HIGH3     (1<<13)	/* 165 */
-#define  LOCALE_CHAN_52_140_ALL  (1<<14)
-#define  LOCALE_SET_5G_HIGH4     (1<<15)	/* 184-216 */
-
-#define  LOCALE_CHAN_36_64       (LOCALE_SET_5G_LOW1 | LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define  LOCALE_CHAN_52_64       (LOCALE_SET_5G_LOW2 | LOCALE_SET_5G_LOW3)
-#define  LOCALE_CHAN_100_124	 (LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2)
-#define  LOCALE_CHAN_100_140     \
-	(LOCALE_SET_5G_MID1 | LOCALE_SET_5G_MID2 | LOCALE_SET_5G_MID3 | LOCALE_SET_5G_HIGH1)
-#define  LOCALE_CHAN_149_165     (LOCALE_SET_5G_HIGH2 | LOCALE_SET_5G_HIGH3)
-#define  LOCALE_CHAN_184_216     LOCALE_SET_5G_HIGH4
-
-#define  LOCALE_CHAN_01_14	(LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13 | LOCALE_CHAN_14)
-
-#define  LOCALE_RADAR_SET_NONE		  0
-#define  LOCALE_RADAR_SET_1		  1
-
-#define  LOCALE_RESTRICTED_NONE		  0
-#define  LOCALE_RESTRICTED_SET_2G_SHORT   1
-#define  LOCALE_RESTRICTED_CHAN_165       2
-#define  LOCALE_CHAN_ALL_5G		  3
-#define  LOCALE_RESTRICTED_JAPAN_LEGACY   4
-#define  LOCALE_RESTRICTED_11D_2G	  5
-#define  LOCALE_RESTRICTED_11D_5G	  6
-#define  LOCALE_RESTRICTED_LOW_HI	  7
-#define  LOCALE_RESTRICTED_12_13_14	  8
-
-/* global memory to provide working buffer for expanded locale */
-
-static const chanvec_t *g_table_radar_set[] = {
-	&chanvec_none,
-	&radar_set1
-};
-
-static const chanvec_t *g_table_restricted_chan[] = {
-	&chanvec_none,		/* restricted_set_none */
-	&restricted_set_2g_short,
-	&restricted_chan_165,
-	&chanvec_all_5G,
-	&restricted_set_japan_legacy,
-	&chanvec_all_2G,	/* restricted_set_11d_2G */
-	&chanvec_all_5G,	/* restricted_set_11d_5G */
-	&restricted_low_hi,
-	&restricted_set_12_13_14
-};
-
-static const chanvec_t locale_2g_01_11 = {
-	{0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_2g_12_13 = {
-	{0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_2g_14 = {
-	{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW_JP1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x01, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW_JP2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x01, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_LOW3 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
-	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_MID1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x11, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_MID2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_MID3 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH1 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH2 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x20, 0x22, 0x02, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH3 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_52_140_ALL = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
-	 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
-	 0x11, 0x11, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static const chanvec_t locale_5g_HIGH4 = {
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
-	 0x11, 0x11, 0x11, 0x11}
-};
-
-static const chanvec_t *g_table_locale_base[] = {
-	&locale_2g_01_11,
-	&locale_2g_12_13,
-	&locale_2g_14,
-	&locale_5g_LOW_JP1,
-	&locale_5g_LOW_JP2,
-	&locale_5g_LOW1,
-	&locale_5g_LOW2,
-	&locale_5g_LOW3,
-	&locale_5g_MID1,
-	&locale_5g_MID2,
-	&locale_5g_MID3,
-	&locale_5g_HIGH1,
-	&locale_5g_HIGH2,
-	&locale_5g_HIGH3,
-	&locale_5g_52_140_ALL,
-	&locale_5g_HIGH4
-};
-
-void wlc_locale_add_channels(chanvec_t *target, const chanvec_t *channels)
-{
-	u8 i;
-	for (i = 0; i < sizeof(chanvec_t); i++) {
-		target->vec[i] |= channels->vec[i];
-	}
-}
-
-void wlc_locale_get_channels(const locale_info_t *locale, chanvec_t *channels)
-{
-	u8 i;
-
-	memset(channels, 0, sizeof(chanvec_t));
-
-	for (i = 0; i < ARRAY_SIZE(g_table_locale_base); i++) {
-		if (locale->valid_channels & (1 << i)) {
-			wlc_locale_add_channels(channels,
-						g_table_locale_base[i]);
-		}
-	}
-}
-
-/*
- * Locale Definitions - 2.4 GHz
- */
-static const locale_info_t locale_i = {	/* locale i. channel 1 - 13 */
-	LOCALE_CHAN_01_11 | LOCALE_CHAN_12_13,
-	LOCALE_RADAR_SET_NONE,
-	LOCALE_RESTRICTED_SET_2G_SHORT,
-	{QDB(19), QDB(19), QDB(19),
-	 QDB(19), QDB(19), QDB(19)},
-	{20, 20, 20, 0},
-	WLC_EIRP
-};
-
-/*
- * Locale Definitions - 5 GHz
- */
-static const locale_info_t locale_11 = {
-	/* locale 11. channel 36 - 48, 52 - 64, 100 - 140, 149 - 165 */
-	LOCALE_CHAN_36_64 | LOCALE_CHAN_100_140 | LOCALE_CHAN_149_165,
-	LOCALE_RADAR_SET_1,
-	LOCALE_RESTRICTED_NONE,
-	{QDB(21), QDB(21), QDB(21), QDB(21), QDB(21)},
-	{23, 23, 23, 30, 30},
-	WLC_EIRP | WLC_DFS_EU
-};
-
-#define LOCALE_2G_IDX_i			0
-static const locale_info_t *g_locale_2g_table[] = {
-	&locale_i
-};
-
-#define LOCALE_5G_IDX_11	0
-static const locale_info_t *g_locale_5g_table[] = {
-	&locale_11
-};
-
-/*
- * MIMO Locale Definitions - 2.4 GHz
- */
-static const locale_mimo_info_t locale_bn = {
-	{QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
-	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
-	 QDB(13), QDB(13), QDB(13)},
-	{0, 0, QDB(13), QDB(13), QDB(13),
-	 QDB(13), QDB(13), QDB(13), QDB(13), QDB(13),
-	 QDB(13), 0, 0},
-	0
-};
-
-/* locale mimo 2g indexes */
-#define LOCALE_MIMO_IDX_bn			0
-
-static const locale_mimo_info_t *g_mimo_2g_table[] = {
-	&locale_bn
-};
-
-/*
- * MIMO Locale Definitions - 5 GHz
- */
-static const locale_mimo_info_t locale_11n = {
-	{ /* 12.5 dBm */ 50, 50, 50, QDB(15), QDB(15)},
-	{QDB(14), QDB(15), QDB(15), QDB(15), QDB(15)},
-	0
-};
-
-#define LOCALE_MIMO_IDX_11n			0
-static const locale_mimo_info_t *g_mimo_5g_table[] = {
-	&locale_11n
-};
-
-#ifdef LC
-#undef LC
-#endif
-#define LC(id)	LOCALE_MIMO_IDX_ ## id
-
-#ifdef LC_2G
-#undef LC_2G
-#endif
-#define LC_2G(id)	LOCALE_2G_IDX_ ## id
-
-#ifdef LC_5G
-#undef LC_5G
-#endif
-#define LC_5G(id)	LOCALE_5G_IDX_ ## id
-
-#define LOCALES(band2, band5, mimo2, mimo5)     {LC_2G(band2), LC_5G(band5), LC(mimo2), LC(mimo5)}
-
-static const struct {
-	char abbrev[WLC_CNTRY_BUF_SZ];	/* country abbreviation */
-	country_info_t country;
-} cntry_locales[] = {
-	{
-	"X2", LOCALES(i, 11, bn, 11n)},	/* Worldwide RoW 2 */
-};
-
-#ifdef SUPPORT_40MHZ
-/* 20MHz channel info for 40MHz pairing support */
-struct chan20_info {
-	u8 sb;
-	u8 adj_sbs;
-};
-
-/* indicates adjacent channels that are allowed for a 40 Mhz channel and
- * those that permitted by the HT
- */
-struct chan20_info chan20_info[] = {
-	/* 11b/11g */
-/* 0 */ {1, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 1 */ {2, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 2 */ {3, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 3 */ {4, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 4 */ {5, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 5 */ {6, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 6 */ {7, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 7 */ {8, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 8 */ {9, (CH_UPPER_SB | CH_LOWER_SB | CH_EWA_VALID)},
-/* 9 */ {10, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 10 */ {11, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 11 */ {12, (CH_LOWER_SB)},
-/* 12 */ {13, (CH_LOWER_SB)},
-/* 13 */ {14, (CH_LOWER_SB)},
-
-/* 11a japan high */
-/* 14 */ {34, (CH_UPPER_SB)},
-/* 15 */ {38, (CH_LOWER_SB)},
-/* 16 */ {42, (CH_LOWER_SB)},
-/* 17 */ {46, (CH_LOWER_SB)},
-
-/* 11a usa low */
-/* 18 */ {36, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 19 */ {40, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 20 */ {44, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 21 */ {48, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 22 */ {52, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 23 */ {56, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 24 */ {60, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 25 */ {64, (CH_LOWER_SB | CH_EWA_VALID)},
-
-/* 11a Europe */
-/* 26 */ {100, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 27 */ {104, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 28 */ {108, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 29 */ {112, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 30 */ {116, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 31 */ {120, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 32 */ {124, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 33 */ {128, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 34 */ {132, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 35 */ {136, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 36 */ {140, (CH_LOWER_SB)},
-
-/* 11a usa high, ref5 only */
-/* The 0x80 bit in pdiv means these are REF5, other entries are REF20 */
-/* 37 */ {149, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 38 */ {153, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 39 */ {157, (CH_UPPER_SB | CH_EWA_VALID)},
-/* 40 */ {161, (CH_LOWER_SB | CH_EWA_VALID)},
-/* 41 */ {165, (CH_LOWER_SB)},
-
-/* 11a japan */
-/* 42 */ {184, (CH_UPPER_SB)},
-/* 43 */ {188, (CH_LOWER_SB)},
-/* 44 */ {192, (CH_UPPER_SB)},
-/* 45 */ {196, (CH_LOWER_SB)},
-/* 46 */ {200, (CH_UPPER_SB)},
-/* 47 */ {204, (CH_LOWER_SB)},
-/* 48 */ {208, (CH_UPPER_SB)},
-/* 49 */ {212, (CH_LOWER_SB)},
-/* 50 */ {216, (CH_LOWER_SB)}
-};
-#endif				/* SUPPORT_40MHZ */
-
-const locale_info_t *wlc_get_locale_2g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_locale_2g_table)) {
-		WL_ERROR("%s: locale 2g index size out of range %d\n",
-			 __func__, locale_idx);
-		ASSERT(locale_idx < ARRAY_SIZE(g_locale_2g_table));
-		return NULL;
-	}
-	return g_locale_2g_table[locale_idx];
-}
-
-const locale_info_t *wlc_get_locale_5g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_locale_5g_table)) {
-		WL_ERROR("%s: locale 5g index size out of range %d\n",
-			 __func__, locale_idx);
-		ASSERT(locale_idx < ARRAY_SIZE(g_locale_5g_table));
-		return NULL;
-	}
-	return g_locale_5g_table[locale_idx];
-}
-
-const locale_mimo_info_t *wlc_get_mimo_2g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_mimo_2g_table)) {
-		WL_ERROR("%s: mimo 2g index size out of range %d\n",
-			 __func__, locale_idx);
-		return NULL;
-	}
-	return g_mimo_2g_table[locale_idx];
-}
-
-const locale_mimo_info_t *wlc_get_mimo_5g(u8 locale_idx)
-{
-	if (locale_idx >= ARRAY_SIZE(g_mimo_5g_table)) {
-		WL_ERROR("%s: mimo 5g index size out of range %d\n",
-			 __func__, locale_idx);
-		return NULL;
-	}
-	return g_mimo_5g_table[locale_idx];
-}
-
-wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc)
-{
-	wlc_cm_info_t *wlc_cm;
-	char country_abbrev[WLC_CNTRY_BUF_SZ];
-	const country_info_t *country;
-	struct wlc_pub *pub = wlc->pub;
-	char *ccode;
-
-	WL_TRACE("wl%d: wlc_channel_mgr_attach\n", wlc->pub->unit);
-
-	wlc_cm = kzalloc(sizeof(wlc_cm_info_t), GFP_ATOMIC);
-	if (wlc_cm == NULL) {
-		WL_ERROR("wl%d: %s: out of memory", pub->unit, __func__);
-		return NULL;
-	}
-	wlc_cm->pub = pub;
-	wlc_cm->wlc = wlc;
-	wlc->cmi = wlc_cm;
-
-	/* store the country code for passing up as a regulatory hint */
-	ccode = getvar(wlc->pub->vars, "ccode");
-	if (ccode) {
-		strncpy(wlc->pub->srom_ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
-		WL_NONE("%s: SROM country code is %c%c\n",
-			__func__,
-			wlc->pub->srom_ccode[0], wlc->pub->srom_ccode[1]);
-	}
-
-	/* internal country information which must match regulatory constraints in firmware */
-	memset(country_abbrev, 0, WLC_CNTRY_BUF_SZ);
-	strncpy(country_abbrev, "X2", sizeof(country_abbrev) - 1);
-	country = wlc_country_lookup(wlc, country_abbrev);
-
-	ASSERT(country != NULL);
-
-	/* save default country for exiting 11d regulatory mode */
-	strncpy(wlc->country_default, country_abbrev, WLC_CNTRY_BUF_SZ - 1);
-
-	/* initialize autocountry_default to driver default */
-	strncpy(wlc->autocountry_default, "X2", WLC_CNTRY_BUF_SZ - 1);
-
-	wlc_set_countrycode(wlc_cm, country_abbrev);
-
-	return wlc_cm;
-}
-
-void wlc_channel_mgr_detach(wlc_cm_info_t *wlc_cm)
-{
-	if (wlc_cm)
-		kfree(wlc_cm);
-}
-
-const char *wlc_channel_country_abbrev(wlc_cm_info_t *wlc_cm)
-{
-	return wlc_cm->country_abbrev;
-}
-
-u8 wlc_channel_locale_flags(wlc_cm_info_t *wlc_cm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-
-	return wlc_cm->bandstate[wlc->band->bandunit].locale_flags;
-}
-
-u8 wlc_channel_locale_flags_in_band(wlc_cm_info_t *wlc_cm, uint bandunit)
-{
-	return wlc_cm->bandstate[bandunit].locale_flags;
-}
-
-/* return chanvec for a given country code and band */
-bool
-wlc_channel_get_chanvec(struct wlc_info *wlc, const char *country_abbrev,
-			int bandtype, chanvec_t *channels)
-{
-	const country_info_t *country;
-	const locale_info_t *locale = NULL;
-
-	country = wlc_country_lookup(wlc, country_abbrev);
-	if (country == NULL)
-		return false;
-
-	if (bandtype == WLC_BAND_2G)
-		locale = wlc_get_locale_2g(country->locale_2G);
-	else if (bandtype == WLC_BAND_5G)
-		locale = wlc_get_locale_5g(country->locale_5G);
-	if (locale == NULL)
-		return false;
-
-	wlc_locale_get_channels(locale, channels);
-	return true;
-}
-
-/* set the driver's current country and regulatory information using a country code
- * as the source. Lookup built in country information found with the country code.
- */
-int wlc_set_countrycode(wlc_cm_info_t *wlc_cm, const char *ccode)
-{
-	char country_abbrev[WLC_CNTRY_BUF_SZ];
-	strncpy(country_abbrev, ccode, WLC_CNTRY_BUF_SZ);
-	return wlc_set_countrycode_rev(wlc_cm, country_abbrev, ccode, -1);
-}
-
-int
-wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
-			const char *country_abbrev,
-			const char *ccode, int regrev)
-{
-	const country_info_t *country;
-	char mapped_ccode[WLC_CNTRY_BUF_SZ];
-	uint mapped_regrev;
-
-	WL_NONE("%s: (country_abbrev \"%s\", ccode \"%s\", regrev %d) SPROM \"%s\"/%u\n",
-		__func__, country_abbrev, ccode, regrev,
-		wlc_cm->srom_ccode, wlc_cm->srom_regrev);
-
-	/* if regrev is -1, lookup the mapped country code,
-	 * otherwise use the ccode and regrev directly
-	 */
-	if (regrev == -1) {
-		/* map the country code to a built-in country code, regrev, and country_info */
-		country =
-		    wlc_countrycode_map(wlc_cm, ccode, mapped_ccode,
-					&mapped_regrev);
-	} else {
-		/* find the matching built-in country definition */
-		ASSERT(0);
-		country = wlc_country_lookup_direct(ccode, regrev);
-		strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
-		mapped_regrev = regrev;
-	}
-
-	if (country == NULL)
-		return BCME_BADARG;
-
-	/* set the driver state for the country */
-	wlc_set_country_common(wlc_cm, country_abbrev, mapped_ccode,
-			       mapped_regrev, country);
-
-	return 0;
-}
-
-/* set the driver's current country and regulatory information using a country code
- * as the source. Look up built in country information found with the country code.
- */
-static void
-wlc_set_country_common(wlc_cm_info_t *wlc_cm,
-		       const char *country_abbrev,
-		       const char *ccode, uint regrev,
-		       const country_info_t *country)
-{
-	const locale_mimo_info_t *li_mimo;
-	const locale_info_t *locale;
-	struct wlc_info *wlc = wlc_cm->wlc;
-	char prev_country_abbrev[WLC_CNTRY_BUF_SZ];
-
-	ASSERT(country != NULL);
-
-	/* save current country state */
-	wlc_cm->country = country;
-
-	memset(&prev_country_abbrev, 0, WLC_CNTRY_BUF_SZ);
-	strncpy(prev_country_abbrev, wlc_cm->country_abbrev,
-		WLC_CNTRY_BUF_SZ - 1);
-
-	strncpy(wlc_cm->country_abbrev, country_abbrev, WLC_CNTRY_BUF_SZ - 1);
-	strncpy(wlc_cm->ccode, ccode, WLC_CNTRY_BUF_SZ - 1);
-	wlc_cm->regrev = regrev;
-
-	/* disable/restore nmode based on country regulations */
-	li_mimo = wlc_get_mimo_2g(country->locale_mimo_2G);
-	if (li_mimo && (li_mimo->flags & WLC_NO_MIMO)) {
-		wlc_set_nmode(wlc, OFF);
-		wlc->stf->no_cddstbc = true;
-	} else {
-		wlc->stf->no_cddstbc = false;
-		if (N_ENAB(wlc->pub) != wlc->protection->nmode_user)
-			wlc_set_nmode(wlc, wlc->protection->nmode_user);
-	}
-
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
-	/* set or restore gmode as required by regulatory */
-	locale = wlc_get_locale_2g(country->locale_2G);
-	if (locale && (locale->flags & WLC_NO_OFDM)) {
-		wlc_set_gmode(wlc, GMODE_LEGACY_B, false);
-	} else {
-		wlc_set_gmode(wlc, wlc->protection->gmode_user, false);
-	}
-
-	wlc_channels_init(wlc_cm, country);
-
-	return;
-}
-
-/* Lookup a country info structure from a null terminated country code
- * The lookup is case sensitive.
- */
-const country_info_t *wlc_country_lookup(struct wlc_info *wlc,
-					 const char *ccode)
-{
-	const country_info_t *country;
-	char mapped_ccode[WLC_CNTRY_BUF_SZ];
-	uint mapped_regrev;
-
-	/* map the country code to a built-in country code, regrev, and country_info struct */
-	country =
-	    wlc_countrycode_map(wlc->cmi, ccode, mapped_ccode, &mapped_regrev);
-
-	return country;
-}
-
-static const country_info_t *wlc_countrycode_map(wlc_cm_info_t *wlc_cm,
-						 const char *ccode,
-						 char *mapped_ccode,
-						 uint *mapped_regrev)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	const country_info_t *country;
-	uint srom_regrev = wlc_cm->srom_regrev;
-	const char *srom_ccode = wlc_cm->srom_ccode;
-	int mapped;
-
-	/* check for currently supported ccode size */
-	if (strlen(ccode) > (WLC_CNTRY_BUF_SZ - 1)) {
-		WL_ERROR("wl%d: %s: ccode \"%s\" too long for match\n",
-			 wlc->pub->unit, __func__, ccode);
-		return NULL;
-	}
-
-	/* default mapping is the given ccode and regrev 0 */
-	strncpy(mapped_ccode, ccode, WLC_CNTRY_BUF_SZ);
-	*mapped_regrev = 0;
-
-	/* If the desired country code matches the srom country code,
-	 * then the mapped country is the srom regulatory rev.
-	 * Otherwise look for an aggregate mapping.
-	 */
-	if (!strcmp(srom_ccode, ccode)) {
-		*mapped_regrev = srom_regrev;
-		mapped = 0;
-		WL_ERROR("srom_code == ccode %s\n", __func__);
-		ASSERT(0);
-	} else {
-		mapped =
-		    wlc_country_aggregate_map(wlc_cm, ccode, mapped_ccode,
-					      mapped_regrev);
-	}
-
-	/* find the matching built-in country definition */
-	country = wlc_country_lookup_direct(mapped_ccode, *mapped_regrev);
-
-	/* if there is not an exact rev match, default to rev zero */
-	if (country == NULL && *mapped_regrev != 0) {
-		*mapped_regrev = 0;
-		ASSERT(0);
-		country =
-		    wlc_country_lookup_direct(mapped_ccode, *mapped_regrev);
-	}
-
-	return country;
-}
-
-static int
-wlc_country_aggregate_map(wlc_cm_info_t *wlc_cm, const char *ccode,
-			  char *mapped_ccode, uint *mapped_regrev)
-{
-	return false;
-}
-
-/* Lookup a country info structure from a null terminated country
- * abbreviation and regrev directly with no translation.
- */
-static const country_info_t *wlc_country_lookup_direct(const char *ccode,
-						       uint regrev)
-{
-	uint size, i;
-
-	/* Should just return 0 for single locale driver. */
-	/* Keep it this way in case we add more locales. (for now anyway) */
-
-	/* all other country def arrays are for regrev == 0, so if regrev is non-zero, fail */
-	if (regrev > 0)
-		return NULL;
-
-	/* find matched table entry from country code */
-	size = ARRAY_SIZE(cntry_locales);
-	for (i = 0; i < size; i++) {
-		if (strcmp(ccode, cntry_locales[i].abbrev) == 0) {
-			return &cntry_locales[i].country;
-		}
-	}
-
-	WL_ERROR("%s: Returning NULL\n", __func__);
-	ASSERT(0);
-	return NULL;
-}
-
-static int
-wlc_channels_init(wlc_cm_info_t *wlc_cm, const country_info_t *country)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint i, j;
-	struct wlcband *band;
-	const locale_info_t *li;
-	chanvec_t sup_chan;
-	const locale_mimo_info_t *li_mimo;
-
-	band = wlc->band;
-	for (i = 0; i < NBANDS(wlc);
-	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
-		li = BAND_5G(band->bandtype) ?
-		    wlc_get_locale_5g(country->locale_5G) :
-		    wlc_get_locale_2g(country->locale_2G);
-		ASSERT(li);
-		wlc_cm->bandstate[band->bandunit].locale_flags = li->flags;
-		li_mimo = BAND_5G(band->bandtype) ?
-		    wlc_get_mimo_5g(country->locale_mimo_5G) :
-		    wlc_get_mimo_2g(country->locale_mimo_2G);
-		ASSERT(li_mimo);
-
-		/* merge the mimo non-mimo locale flags */
-		wlc_cm->bandstate[band->bandunit].locale_flags |=
-		    li_mimo->flags;
-
-		wlc_cm->bandstate[band->bandunit].restricted_channels =
-		    g_table_restricted_chan[li->restricted_channels];
-		wlc_cm->bandstate[band->bandunit].radar_channels =
-		    g_table_radar_set[li->radar_channels];
-
-		/* set the channel availability,
-		 * masking out the channels that may not be supported on this phy
-		 */
-		wlc_phy_chanspec_band_validch(band->pi, band->bandtype,
-					      &sup_chan);
-		wlc_locale_get_channels(li,
-					&wlc_cm->bandstate[band->bandunit].
-					valid_channels);
-		for (j = 0; j < sizeof(chanvec_t); j++)
-			wlc_cm->bandstate[band->bandunit].valid_channels.
-			    vec[j] &= sup_chan.vec[j];
-	}
-
-	wlc_quiet_channels_reset(wlc_cm);
-	wlc_channels_commit(wlc_cm);
-
-	return 0;
-}
-
-/* Update the radio state (enable/disable) and tx power targets
- * based on a new set of channel/regulatory information
- */
-static void wlc_channels_commit(wlc_cm_info_t *wlc_cm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint chan;
-	struct txpwr_limits txpwr;
-
-	/* search for the existence of any valid channel */
-	for (chan = 0; chan < MAXCHANNEL; chan++) {
-		if (VALID_CHANNEL20_DB(wlc, chan)) {
-			break;
-		}
-	}
-	if (chan == MAXCHANNEL)
-		chan = INVCHANNEL;
-
-	/* based on the channel search above, set or clear WL_RADIO_COUNTRY_DISABLE */
-	if (chan == INVCHANNEL) {
-		/* country/locale with no valid channels, set the radio disable bit */
-		mboolset(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
-		WL_ERROR("wl%d: %s: no valid channel for \"%s\" nbands %d bandlocked %d\n",
-			 wlc->pub->unit, __func__,
-			 wlc_cm->country_abbrev, NBANDS(wlc), wlc->bandlocked);
-	} else
-	    if (mboolisset(wlc->pub->radio_disabled,
-		WL_RADIO_COUNTRY_DISABLE)) {
-		/* country/locale with valid channel, clear the radio disable bit */
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_COUNTRY_DISABLE);
-	}
-
-	/* Now that the country abbreviation is set, if the radio supports 2G, then
-	 * set channel 14 restrictions based on the new locale.
-	 */
-	if (NBANDS(wlc) > 1 || BAND_2G(wlc->band->bandtype)) {
-		wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
-						     wlc_japan(wlc) ? true :
-						     false);
-	}
-
-	if (wlc->pub->up && chan != INVCHANNEL) {
-		wlc_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
-		wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm,
-								     &txpwr,
-								     WLC_TXPWR_MAX);
-		wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
-	}
-}
-
-/* reset the quiet channels vector to the union of the restricted and radar channel sets */
-void wlc_quiet_channels_reset(wlc_cm_info_t *wlc_cm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint i, j;
-	struct wlcband *band;
-	const chanvec_t *chanvec;
-
-	memset(&wlc_cm->quiet_channels, 0, sizeof(chanvec_t));
-
-	band = wlc->band;
-	for (i = 0; i < NBANDS(wlc);
-	     i++, band = wlc->bandstate[OTHERBANDUNIT(wlc)]) {
-
-		/* initialize quiet channels for restricted channels */
-		chanvec = wlc_cm->bandstate[band->bandunit].restricted_channels;
-		for (j = 0; j < sizeof(chanvec_t); j++)
-			wlc_cm->quiet_channels.vec[j] |= chanvec->vec[j];
-
-	}
-}
-
-bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
-{
-	return N_ENAB(wlc_cm->wlc->pub) && CHSPEC_IS40(chspec) ?
-		(isset
-		 (wlc_cm->quiet_channels.vec,
-		  LOWER_20_SB(CHSPEC_CHANNEL(chspec)))
-		 || isset(wlc_cm->quiet_channels.vec,
-			  UPPER_20_SB(CHSPEC_CHANNEL(chspec)))) : isset(wlc_cm->
-									quiet_channels.
-									vec,
-									CHSPEC_CHANNEL
-									(chspec));
-}
-
-/* Is the channel valid for the current locale? (but don't consider channels not
- *   available due to bandlocking)
- */
-bool wlc_valid_channel20_db(wlc_cm_info_t *wlc_cm, uint val)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-
-	return VALID_CHANNEL20(wlc, val) ||
-		(!wlc->bandlocked
-		 && VALID_CHANNEL20_IN_BAND(wlc, OTHERBANDUNIT(wlc), val));
-}
-
-/* Is the channel valid for the current locale and specified band? */
-bool
-wlc_valid_channel20_in_band(wlc_cm_info_t *wlc_cm, uint bandunit, uint val)
-{
-	return ((val < MAXCHANNEL)
-		&& isset(wlc_cm->bandstate[bandunit].valid_channels.vec, val));
-}
-
-/* Is the channel valid for the current locale and current band? */
-bool wlc_valid_channel20(wlc_cm_info_t *wlc_cm, uint val)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-
-	return ((val < MAXCHANNEL) &&
-		isset(wlc_cm->bandstate[wlc->band->bandunit].valid_channels.vec,
-		      val));
-}
-
-/* Is the 40 MHz allowed for the current locale and specified band? */
-bool wlc_valid_40chanspec_in_band(wlc_cm_info_t *wlc_cm, uint bandunit)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-
-	return (((wlc_cm->bandstate[bandunit].
-		  locale_flags & (WLC_NO_MIMO | WLC_NO_40MHZ)) == 0)
-		&& wlc->bandstate[bandunit]->mimo_cap_40);
-}
-
-static void
-wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm_info_t *wlc_cm,
-						     struct txpwr_limits *txpwr,
-						     u8
-						     local_constraint_qdbm)
-{
-	int j;
-
-	/* CCK Rates */
-	for (j = 0; j < WL_TX_POWER_CCK_NUM; j++) {
-		txpwr->cck[j] = min(txpwr->cck[j], local_constraint_qdbm);
-	}
-
-	/* 20 MHz Legacy OFDM SISO */
-	for (j = 0; j < WL_TX_POWER_OFDM_NUM; j++) {
-		txpwr->ofdm[j] = min(txpwr->ofdm[j], local_constraint_qdbm);
-	}
-
-	/* 20 MHz Legacy OFDM CDD */
-	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
-		txpwr->ofdm_cdd[j] =
-		    min(txpwr->ofdm_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 40 MHz Legacy OFDM SISO */
-	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
-		txpwr->ofdm_40_siso[j] =
-		    min(txpwr->ofdm_40_siso[j], local_constraint_qdbm);
-	}
-
-	/* 40 MHz Legacy OFDM CDD */
-	for (j = 0; j < WLC_NUM_RATES_OFDM; j++) {
-		txpwr->ofdm_40_cdd[j] =
-		    min(txpwr->ofdm_40_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 0-7 SISO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_20_siso[j] =
-		    min(txpwr->mcs_20_siso[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 0-7 CDD */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_20_cdd[j] =
-		    min(txpwr->mcs_20_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 0-7 STBC */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_20_stbc[j] =
-		    min(txpwr->mcs_20_stbc[j], local_constraint_qdbm);
-	}
-
-	/* 20MHz MCS 8-15 MIMO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_2_STREAM; j++)
-		txpwr->mcs_20_mimo[j] =
-		    min(txpwr->mcs_20_mimo[j], local_constraint_qdbm);
-
-	/* 40MHz MCS 0-7 SISO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_40_siso[j] =
-		    min(txpwr->mcs_40_siso[j], local_constraint_qdbm);
-	}
-
-	/* 40MHz MCS 0-7 CDD */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_40_cdd[j] =
-		    min(txpwr->mcs_40_cdd[j], local_constraint_qdbm);
-	}
-
-	/* 40MHz MCS 0-7 STBC */
-	for (j = 0; j < WLC_NUM_RATES_MCS_1_STREAM; j++) {
-		txpwr->mcs_40_stbc[j] =
-		    min(txpwr->mcs_40_stbc[j], local_constraint_qdbm);
-	}
-
-	/* 40MHz MCS 8-15 MIMO */
-	for (j = 0; j < WLC_NUM_RATES_MCS_2_STREAM; j++)
-		txpwr->mcs_40_mimo[j] =
-		    min(txpwr->mcs_40_mimo[j], local_constraint_qdbm);
-
-	/* 40MHz MCS 32 */
-	txpwr->mcs32 = min(txpwr->mcs32, local_constraint_qdbm);
-
-}
-
-void
-wlc_channel_set_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chanspec,
-			 u8 local_constraint_qdbm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	struct txpwr_limits txpwr;
-
-	wlc_channel_reg_limits(wlc_cm, chanspec, &txpwr);
-
-	wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
-							     local_constraint_qdbm);
-
-	wlc_bmac_set_chanspec(wlc->hw, chanspec,
-			      (wlc_quiet_chanspec(wlc_cm, chanspec) != 0),
-			      &txpwr);
-}
-
-int
-wlc_channel_set_txpower_limit(wlc_cm_info_t *wlc_cm,
-			      u8 local_constraint_qdbm)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	struct txpwr_limits txpwr;
-
-	wlc_channel_reg_limits(wlc_cm, wlc->chanspec, &txpwr);
-
-	wlc_channel_min_txpower_limits_with_local_constraint(wlc_cm, &txpwr,
-							     local_constraint_qdbm);
-
-	wlc_phy_txpower_limit_set(wlc->band->pi, &txpwr, wlc->chanspec);
-
-	return 0;
-}
-
-#ifdef POWER_DBG
-static void wlc_phy_txpower_limits_dump(txpwr_limits_t *txpwr)
-{
-	int i;
-	char fraction[4][4] = { "   ", ".25", ".5 ", ".75" };
-
-	printf("CCK                ");
-	for (i = 0; i < WLC_NUM_RATES_CCK; i++) {
-		printf(" %2d%s", txpwr->cck[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->cck[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("20 MHz OFDM SISO   ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		printf(" %2d%s", txpwr->ofdm[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->ofdm[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("20 MHz OFDM CDD    ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		printf(" %2d%s", txpwr->ofdm_cdd[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->ofdm_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("40 MHz OFDM SISO   ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		printf(" %2d%s", txpwr->ofdm_40_siso[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->ofdm_40_siso[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("40 MHz OFDM CDD    ");
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		printf(" %2d%s", txpwr->ofdm_40_cdd[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->ofdm_40_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("20 MHz MCS0-7 SISO ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_20_siso[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_20_siso[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("20 MHz MCS0-7 CDD  ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_20_cdd[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_20_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("20 MHz MCS0-7 STBC ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_20_stbc[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_20_stbc[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("20 MHz MCS8-15 SDM ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_20_mimo[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_20_mimo[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("40 MHz MCS0-7 SISO ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_40_siso[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_40_siso[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("40 MHz MCS0-7 CDD  ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_40_cdd[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_40_cdd[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("40 MHz MCS0-7 STBC ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_40_stbc[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_40_stbc[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("40 MHz MCS8-15 SDM ");
-	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
-		printf(" %2d%s", txpwr->mcs_40_mimo[i] / WLC_TXPWR_DB_FACTOR,
-		       fraction[txpwr->mcs_40_mimo[i] % WLC_TXPWR_DB_FACTOR]);
-	}
-	printf("\n");
-
-	printf("MCS32               %2d%s\n",
-	       txpwr->mcs32 / WLC_TXPWR_DB_FACTOR,
-	       fraction[txpwr->mcs32 % WLC_TXPWR_DB_FACTOR]);
-}
-#endif				/* POWER_DBG */
-
-void
-wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm, chanspec_t chanspec,
-		       txpwr_limits_t *txpwr)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	uint i;
-	uint chan;
-	int maxpwr;
-	int delta;
-	const country_info_t *country;
-	struct wlcband *band;
-	const locale_info_t *li;
-	int conducted_max;
-	int conducted_ofdm_max;
-	const locale_mimo_info_t *li_mimo;
-	int maxpwr20, maxpwr40;
-	int maxpwr_idx;
-	uint j;
-
-	memset(txpwr, 0, sizeof(txpwr_limits_t));
-
-	if (!wlc_valid_chanspec_db(wlc_cm, chanspec)) {
-		country = wlc_country_lookup(wlc, wlc->autocountry_default);
-		if (country == NULL)
-			return;
-	} else {
-		country = wlc_cm->country;
-	}
-
-	chan = CHSPEC_CHANNEL(chanspec);
-	band = wlc->bandstate[CHSPEC_WLCBANDUNIT(chanspec)];
-	li = BAND_5G(band->bandtype) ?
-	    wlc_get_locale_5g(country->locale_5G) :
-	    wlc_get_locale_2g(country->locale_2G);
-
-	li_mimo = BAND_5G(band->bandtype) ?
-	    wlc_get_mimo_5g(country->locale_mimo_5G) :
-	    wlc_get_mimo_2g(country->locale_mimo_2G);
-
-	if (li->flags & WLC_EIRP) {
-		delta = band->antgain;
-	} else {
-		delta = 0;
-		if (band->antgain > QDB(6))
-			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
-	}
-
-	if (li == &locale_i) {
-		conducted_max = QDB(22);
-		conducted_ofdm_max = QDB(22);
-	}
-
-	/* CCK txpwr limits for 2.4G band */
-	if (BAND_2G(band->bandtype)) {
-		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_CCK(chan)];
-
-		maxpwr = maxpwr - delta;
-		maxpwr = max(maxpwr, 0);
-		maxpwr = min(maxpwr, conducted_max);
-
-		for (i = 0; i < WLC_NUM_RATES_CCK; i++)
-			txpwr->cck[i] = (u8) maxpwr;
-	}
-
-	/* OFDM txpwr limits for 2.4G or 5G bands */
-	if (BAND_2G(band->bandtype)) {
-		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_2G_OFDM(chan)];
-
-	} else {
-		maxpwr = li->maxpwr[CHANNEL_POWER_IDX_5G(chan)];
-	}
-
-	maxpwr = maxpwr - delta;
-	maxpwr = max(maxpwr, 0);
-	maxpwr = min(maxpwr, conducted_ofdm_max);
-
-	/* Keep OFDM lmit below CCK limit */
-	if (BAND_2G(band->bandtype))
-		maxpwr = min_t(int, maxpwr, txpwr->cck[0]);
-
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		txpwr->ofdm[i] = (u8) maxpwr;
-	}
-
-	for (i = 0; i < WLC_NUM_RATES_OFDM; i++) {
-		/* OFDM 40 MHz SISO has the same power as the corresponding MCS0-7 rate unless
-		 * overriden by the locale specific code. We set this value to 0 as a
-		 * flag (presumably 0 dBm isn't a possibility) and then copy the MCS0-7 value
-		 * to the 40 MHz value if it wasn't explicitly set.
-		 */
-		txpwr->ofdm_40_siso[i] = 0;
-
-		txpwr->ofdm_cdd[i] = (u8) maxpwr;
-
-		txpwr->ofdm_40_cdd[i] = 0;
-	}
-
-	/* MIMO/HT specific limits */
-	if (li_mimo->flags & WLC_EIRP) {
-		delta = band->antgain;
-	} else {
-		delta = 0;
-		if (band->antgain > QDB(6))
-			delta = band->antgain - QDB(6);	/* Excess over 6 dB */
-	}
-
-	if (BAND_2G(band->bandtype))
-		maxpwr_idx = (chan - 1);
-	else
-		maxpwr_idx = CHANNEL_POWER_IDX_5G(chan);
-
-	maxpwr20 = li_mimo->maxpwr20[maxpwr_idx];
-	maxpwr40 = li_mimo->maxpwr40[maxpwr_idx];
-
-	maxpwr20 = maxpwr20 - delta;
-	maxpwr20 = max(maxpwr20, 0);
-	maxpwr40 = maxpwr40 - delta;
-	maxpwr40 = max(maxpwr40, 0);
-
-	/* Fill in the MCS 0-7 (SISO) rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-
-		/* 20 MHz has the same power as the corresponding OFDM rate unless
-		 * overriden by the locale specific code.
-		 */
-		txpwr->mcs_20_siso[i] = txpwr->ofdm[i];
-		txpwr->mcs_40_siso[i] = 0;
-	}
-
-	/* Fill in the MCS 0-7 CDD rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		txpwr->mcs_20_cdd[i] = (u8) maxpwr20;
-		txpwr->mcs_40_cdd[i] = (u8) maxpwr40;
-	}
-
-	/* These locales have SISO expressed in the table and override CDD later */
-	if (li_mimo == &locale_bn) {
-		if (li_mimo == &locale_bn) {
-			maxpwr20 = QDB(16);
-			maxpwr40 = 0;
-
-			if (chan >= 3 && chan <= 11) {
-				maxpwr40 = QDB(16);
-			}
-		}
-
-		for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-			txpwr->mcs_20_siso[i] = (u8) maxpwr20;
-			txpwr->mcs_40_siso[i] = (u8) maxpwr40;
-		}
-	}
-
-	/* Fill in the MCS 0-7 STBC rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		txpwr->mcs_20_stbc[i] = 0;
-		txpwr->mcs_40_stbc[i] = 0;
-	}
-
-	/* Fill in the MCS 8-15 SDM rates */
-	for (i = 0; i < WLC_NUM_RATES_MCS_2_STREAM; i++) {
-		txpwr->mcs_20_mimo[i] = (u8) maxpwr20;
-		txpwr->mcs_40_mimo[i] = (u8) maxpwr40;
-	}
-
-	/* Fill in MCS32 */
-	txpwr->mcs32 = (u8) maxpwr40;
-
-	for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) {
-		if (txpwr->ofdm_40_cdd[i] == 0)
-			txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
-		if (i == 0) {
-			i = i + 1;
-			if (txpwr->ofdm_40_cdd[i] == 0)
-				txpwr->ofdm_40_cdd[i] = txpwr->mcs_40_cdd[j];
-		}
-	}
-
-	/* Copy the 40 MHZ MCS 0-7 CDD value to the 40 MHZ MCS 0-7 SISO value if it wasn't
-	 * provided explicitly.
-	 */
-
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		if (txpwr->mcs_40_siso[i] == 0)
-			txpwr->mcs_40_siso[i] = txpwr->mcs_40_cdd[i];
-	}
-
-	for (i = 0, j = 0; i < WLC_NUM_RATES_OFDM; i++, j++) {
-		if (txpwr->ofdm_40_siso[i] == 0)
-			txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
-		if (i == 0) {
-			i = i + 1;
-			if (txpwr->ofdm_40_siso[i] == 0)
-				txpwr->ofdm_40_siso[i] = txpwr->mcs_40_siso[j];
-		}
-	}
-
-	/* Copy the 20 and 40 MHz MCS0-7 CDD values to the corresponding STBC values if they weren't
-	 * provided explicitly.
-	 */
-	for (i = 0; i < WLC_NUM_RATES_MCS_1_STREAM; i++) {
-		if (txpwr->mcs_20_stbc[i] == 0)
-			txpwr->mcs_20_stbc[i] = txpwr->mcs_20_cdd[i];
-
-		if (txpwr->mcs_40_stbc[i] == 0)
-			txpwr->mcs_40_stbc[i] = txpwr->mcs_40_cdd[i];
-	}
-
-#ifdef POWER_DBG
-	wlc_phy_txpower_limits_dump(txpwr);
-#endif
-	return;
-}
-
-/* Returns true if currently set country is Japan or variant */
-bool wlc_japan(struct wlc_info *wlc)
-{
-	return wlc_japan_ccode(wlc->cmi->country_abbrev);
-}
-
-/* JP, J1 - J10 are Japan ccodes */
-static bool wlc_japan_ccode(const char *ccode)
-{
-	return (ccode[0] == 'J' &&
-		(ccode[1] == 'P' || (ccode[1] >= '1' && ccode[1] <= '9')));
-}
-
-/*
- * Validate the chanspec for this locale, for 40MHZ we need to also check that the sidebands
- * are valid 20MZH channels in this locale and they are also a legal HT combination
- */
-static bool
-wlc_valid_chanspec_ext(wlc_cm_info_t *wlc_cm, chanspec_t chspec, bool dualband)
-{
-	struct wlc_info *wlc = wlc_cm->wlc;
-	u8 channel = CHSPEC_CHANNEL(chspec);
-
-	/* check the chanspec */
-	if (wf_chspec_malformed(chspec)) {
-		WL_ERROR("wl%d: malformed chanspec 0x%x\n",
-			 wlc->pub->unit, chspec);
-		ASSERT(0);
-		return false;
-	}
-
-	if (CHANNEL_BANDUNIT(wlc_cm->wlc, channel) !=
-	    CHSPEC_WLCBANDUNIT(chspec))
-		return false;
-
-	/* Check a 20Mhz channel */
-	if (CHSPEC_IS20(chspec)) {
-		if (dualband)
-			return VALID_CHANNEL20_DB(wlc_cm->wlc, channel);
-		else
-			return VALID_CHANNEL20(wlc_cm->wlc, channel);
-	}
-#ifdef SUPPORT_40MHZ
-	/* We know we are now checking a 40MHZ channel, so we should only be here
-	 * for NPHYS
-	 */
-	if (WLCISNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band)) {
-		u8 upper_sideband = 0, idx;
-		u8 num_ch20_entries =
-		    sizeof(chan20_info) / sizeof(struct chan20_info);
-
-		if (!VALID_40CHANSPEC_IN_BAND(wlc, CHSPEC_WLCBANDUNIT(chspec)))
-			return false;
-
-		if (dualband) {
-			if (!VALID_CHANNEL20_DB(wlc, LOWER_20_SB(channel)) ||
-			    !VALID_CHANNEL20_DB(wlc, UPPER_20_SB(channel)))
-				return false;
-		} else {
-			if (!VALID_CHANNEL20(wlc, LOWER_20_SB(channel)) ||
-			    !VALID_CHANNEL20(wlc, UPPER_20_SB(channel)))
-				return false;
-		}
-
-		/* find the lower sideband info in the sideband array */
-		for (idx = 0; idx < num_ch20_entries; idx++) {
-			if (chan20_info[idx].sb == LOWER_20_SB(channel))
-				upper_sideband = chan20_info[idx].adj_sbs;
-		}
-		/* check that the lower sideband allows an upper sideband */
-		if ((upper_sideband & (CH_UPPER_SB | CH_EWA_VALID)) ==
-		    (CH_UPPER_SB | CH_EWA_VALID))
-			return true;
-		return false;
-	}
-#endif				/* 40 MHZ */
-
-	return false;
-}
-
-bool wlc_valid_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
-{
-	return wlc_valid_chanspec_ext(wlc_cm, chspec, false);
-}
-
-bool wlc_valid_chanspec_db(wlc_cm_info_t *wlc_cm, chanspec_t chspec)
-{
-	return wlc_valid_chanspec_ext(wlc_cm, chspec, true);
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_channel.h b/drivers/staging/brcm80211/sys/wlc_channel.h
deleted file mode 100644
index 1f170af..0000000
--- a/drivers/staging/brcm80211/sys/wlc_channel.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_CHANNEL_H_
-#define _WLC_CHANNEL_H_
-
-#include <wlc_phy_hal.h>
-
-#define WLC_TXPWR_DB_FACTOR 4	/* conversion for phy txpwr cacluations that use .25 dB units */
-
-struct wlc_info;
-
-/* maxpwr mapping to 5GHz band channels:
- * maxpwr[0] - channels [34-48]
- * maxpwr[1] - channels [52-60]
- * maxpwr[2] - channels [62-64]
- * maxpwr[3] - channels [100-140]
- * maxpwr[4] - channels [149-165]
- */
-#define BAND_5G_PWR_LVLS	5	/* 5 power levels for 5G */
-
-/* power level in group of 2.4GHz band channels:
- * maxpwr[0] - CCK  channels [1]
- * maxpwr[1] - CCK  channels [2-10]
- * maxpwr[2] - CCK  channels [11-14]
- * maxpwr[3] - OFDM channels [1]
- * maxpwr[4] - OFDM channels [2-10]
- * maxpwr[5] - OFDM channels [11-14]
- */
-
-/* macro to get 2.4 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_2G_CCK(c) (((c) < 2) ? 0 : (((c) < 11) ? 1 : 2))	/* cck index */
-#define CHANNEL_POWER_IDX_2G_OFDM(c) (((c) < 2) ? 3 : (((c) < 11) ? 4 : 5))	/* ofdm index */
-
-/* macro to get 5 GHz channel group index for tx power */
-#define CHANNEL_POWER_IDX_5G(c) \
-	(((c) < 52) ? 0 : (((c) < 62) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4))))
-
-#define WLC_MAXPWR_TBL_SIZE		6	/* max of BAND_5G_PWR_LVLS and 6 for 2.4 GHz */
-#define WLC_MAXPWR_MIMO_TBL_SIZE	14	/* max of BAND_5G_PWR_LVLS and 14 for 2.4 GHz */
-
-/* locale channel and power info. */
-typedef struct {
-	u32 valid_channels;
-	u8 radar_channels;	/* List of radar sensitive channels */
-	u8 restricted_channels;	/* List of channels used only if APs are detected */
-	s8 maxpwr[WLC_MAXPWR_TBL_SIZE];	/* Max tx pwr in qdBm for each sub-band */
-	s8 pub_maxpwr[BAND_5G_PWR_LVLS];	/* Country IE advertised max tx pwr in dBm
-						 * per sub-band
-						 */
-	u8 flags;
-} locale_info_t;
-
-/* bits for locale_info flags */
-#define WLC_PEAK_CONDUCTED	0x00	/* Peak for locals */
-#define WLC_EIRP		0x01	/* Flag for EIRP */
-#define WLC_DFS_TPC		0x02	/* Flag for DFS TPC */
-#define WLC_NO_OFDM		0x04	/* Flag for No OFDM */
-#define WLC_NO_40MHZ		0x08	/* Flag for No MIMO 40MHz */
-#define WLC_NO_MIMO		0x10	/* Flag for No MIMO, 20 or 40 MHz */
-#define WLC_RADAR_TYPE_EU       0x20	/* Flag for EU */
-#define WLC_DFS_FCC             WLC_DFS_TPC	/* Flag for DFS FCC */
-#define WLC_DFS_EU              (WLC_DFS_TPC | WLC_RADAR_TYPE_EU)	/* Flag for DFS EU */
-
-#define ISDFS_EU(fl)		(((fl) & WLC_DFS_EU) == WLC_DFS_EU)
-
-/* locale per-channel tx power limits for MIMO frames
- * maxpwr arrays are index by channel for 2.4 GHz limits, and
- * by sub-band for 5 GHz limits using CHANNEL_POWER_IDX_5G(channel)
- */
-typedef struct {
-	s8 maxpwr20[WLC_MAXPWR_MIMO_TBL_SIZE];	/* tx 20 MHz power limits, qdBm units */
-	s8 maxpwr40[WLC_MAXPWR_MIMO_TBL_SIZE];	/* tx 40 MHz power limits, qdBm units */
-	u8 flags;
-} locale_mimo_info_t;
-
-extern const chanvec_t chanvec_all_2G;
-extern const chanvec_t chanvec_all_5G;
-
-/*
- * Country names and abbreviations with locale defined from ISO 3166
- */
-struct country_info {
-	const u8 locale_2G;	/* 2.4G band locale */
-	const u8 locale_5G;	/* 5G band locale */
-	const u8 locale_mimo_2G;	/* 2.4G mimo info */
-	const u8 locale_mimo_5G;	/* 5G mimo info */
-};
-
-typedef struct country_info country_info_t;
-
-typedef struct wlc_cm_info wlc_cm_info_t;
-
-extern wlc_cm_info_t *wlc_channel_mgr_attach(struct wlc_info *wlc);
-extern void wlc_channel_mgr_detach(wlc_cm_info_t *wlc_cm);
-
-extern int wlc_set_countrycode(wlc_cm_info_t *wlc_cm, const char *ccode);
-extern int wlc_set_countrycode_rev(wlc_cm_info_t *wlc_cm,
-				   const char *country_abbrev,
-				   const char *ccode, int regrev);
-
-extern const char *wlc_channel_country_abbrev(wlc_cm_info_t *wlc_cm);
-extern u8 wlc_channel_locale_flags(wlc_cm_info_t *wlc_cm);
-extern u8 wlc_channel_locale_flags_in_band(wlc_cm_info_t *wlc_cm,
-					      uint bandunit);
-
-extern void wlc_quiet_channels_reset(wlc_cm_info_t *wlc_cm);
-extern bool wlc_quiet_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
-
-#define	VALID_CHANNEL20_DB(wlc, val) wlc_valid_channel20_db((wlc)->cmi, val)
-#define	VALID_CHANNEL20_IN_BAND(wlc, bandunit, val) \
-	wlc_valid_channel20_in_band((wlc)->cmi, bandunit, val)
-#define	VALID_CHANNEL20(wlc, val) wlc_valid_channel20((wlc)->cmi, val)
-#define VALID_40CHANSPEC_IN_BAND(wlc, bandunit) wlc_valid_40chanspec_in_band((wlc)->cmi, bandunit)
-
-extern bool wlc_valid_chanspec(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
-extern bool wlc_valid_chanspec_db(wlc_cm_info_t *wlc_cm, chanspec_t chspec);
-extern bool wlc_valid_channel20_db(wlc_cm_info_t *wlc_cm, uint val);
-extern bool wlc_valid_channel20_in_band(wlc_cm_info_t *wlc_cm, uint bandunit,
-					uint val);
-extern bool wlc_valid_channel20(wlc_cm_info_t *wlc_cm, uint val);
-extern bool wlc_valid_40chanspec_in_band(wlc_cm_info_t *wlc_cm, uint bandunit);
-
-extern void wlc_channel_reg_limits(wlc_cm_info_t *wlc_cm,
-				   chanspec_t chanspec,
-				   struct txpwr_limits *txpwr);
-extern void wlc_channel_set_chanspec(wlc_cm_info_t *wlc_cm,
-				     chanspec_t chanspec,
-				     u8 local_constraint_qdbm);
-extern int wlc_channel_set_txpower_limit(wlc_cm_info_t *wlc_cm,
-					 u8 local_constraint_qdbm);
-
-extern const country_info_t *wlc_country_lookup(struct wlc_info *wlc,
-						const char *ccode);
-extern void wlc_locale_get_channels(const locale_info_t *locale,
-				    chanvec_t *valid_channels);
-extern const locale_info_t *wlc_get_locale_2g(u8 locale_idx);
-extern const locale_info_t *wlc_get_locale_5g(u8 locale_idx);
-extern bool wlc_japan(struct wlc_info *wlc);
-
-extern u8 wlc_get_regclass(wlc_cm_info_t *wlc_cm, chanspec_t chanspec);
-extern bool wlc_channel_get_chanvec(struct wlc_info *wlc,
-				    const char *country_abbrev, int bandtype,
-				    chanvec_t *channels);
-
-#endif				/* _WLC_CHANNEL_H */
diff --git a/drivers/staging/brcm80211/sys/wlc_event.c b/drivers/staging/brcm80211/sys/wlc_event.c
deleted file mode 100644
index dabd709..0000000
--- a/drivers/staging/brcm80211/sys/wlc_event.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <bcmdefs.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <wlioctl.h>
-#include <wlc_cfg.h>
-#include <wlc_pub.h>
-#include <wlc_key.h>
-#include <wl_export.h>
-#include <wlc_event.h>
-
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_mac80211.h>
-#ifdef MSGTRACE
-#include <msgtrace.h>
-#endif
-#include <wl_dbg.h>
-
-/* Local prototypes */
-static void wlc_timer_cb(void *arg);
-
-/* Private data structures */
-struct wlc_eventq {
-	wlc_event_t *head;
-	wlc_event_t *tail;
-	struct wlc_info *wlc;
-	void *wl;
-	struct wlc_pub *pub;
-	bool tpending;
-	bool workpending;
-	struct wl_timer *timer;
-	wlc_eventq_cb_t cb;
-	u8 event_inds_mask[broken_roundup(WLC_E_LAST, NBBY) / NBBY];
-};
-
-/*
- * Export functions
- */
-wlc_eventq_t *wlc_eventq_attach(struct wlc_pub *pub, struct wlc_info *wlc,
-				void *wl,
-				wlc_eventq_cb_t cb)
-{
-	wlc_eventq_t *eq;
-
-	eq = kzalloc(sizeof(wlc_eventq_t), GFP_ATOMIC);
-	if (eq == NULL)
-		return NULL;
-
-	eq->cb = cb;
-	eq->wlc = wlc;
-	eq->wl = wl;
-	eq->pub = pub;
-
-	eq->timer = wl_init_timer(eq->wl, wlc_timer_cb, eq, "eventq");
-	if (!eq->timer) {
-		WL_ERROR("wl%d: wlc_eventq_attach: timer failed\n",
-			 pub->unit);
-		kfree(eq);
-		return NULL;
-	}
-
-	return eq;
-}
-
-int wlc_eventq_detach(wlc_eventq_t *eq)
-{
-	/* Clean up pending events */
-	wlc_eventq_down(eq);
-
-	if (eq->timer) {
-		if (eq->tpending) {
-			wl_del_timer(eq->wl, eq->timer);
-			eq->tpending = false;
-		}
-		wl_free_timer(eq->wl, eq->timer);
-		eq->timer = NULL;
-	}
-
-	ASSERT(wlc_eventq_avail(eq) == false);
-	kfree(eq);
-	return 0;
-}
-
-int wlc_eventq_down(wlc_eventq_t *eq)
-{
-	int callbacks = 0;
-	if (eq->tpending && !eq->workpending) {
-		if (!wl_del_timer(eq->wl, eq->timer))
-			callbacks++;
-
-		ASSERT(wlc_eventq_avail(eq) == true);
-		ASSERT(eq->workpending == false);
-		eq->workpending = true;
-		if (eq->cb)
-			eq->cb(eq->wlc);
-
-		ASSERT(eq->workpending == true);
-		eq->workpending = false;
-		eq->tpending = false;
-	} else {
-		ASSERT(eq->workpending || wlc_eventq_avail(eq) == false);
-	}
-	return callbacks;
-}
-
-wlc_event_t *wlc_event_alloc(wlc_eventq_t *eq)
-{
-	wlc_event_t *e;
-
-	e = kzalloc(sizeof(wlc_event_t), GFP_ATOMIC);
-
-	if (e == NULL)
-		return NULL;
-
-	return e;
-}
-
-void wlc_event_free(wlc_eventq_t *eq, wlc_event_t *e)
-{
-	ASSERT(e->data == NULL);
-	ASSERT(e->next == NULL);
-	kfree(e);
-}
-
-void wlc_eventq_enq(wlc_eventq_t *eq, wlc_event_t *e)
-{
-	ASSERT(e->next == NULL);
-	e->next = NULL;
-
-	if (eq->tail) {
-		eq->tail->next = e;
-		eq->tail = e;
-	} else
-		eq->head = eq->tail = e;
-
-	if (!eq->tpending) {
-		eq->tpending = true;
-		/* Use a zero-delay timer to trigger
-		 * delayed processing of the event.
-		 */
-		wl_add_timer(eq->wl, eq->timer, 0, 0);
-	}
-}
-
-wlc_event_t *wlc_eventq_deq(wlc_eventq_t *eq)
-{
-	wlc_event_t *e;
-
-	e = eq->head;
-	if (e) {
-		eq->head = e->next;
-		e->next = NULL;
-
-		if (eq->head == NULL)
-			eq->tail = eq->head;
-	}
-	return e;
-}
-
-wlc_event_t *wlc_eventq_next(wlc_eventq_t *eq, wlc_event_t *e)
-{
-#ifdef BCMDBG
-	wlc_event_t *etmp;
-
-	for (etmp = eq->head; etmp; etmp = etmp->next) {
-		if (etmp == e)
-			break;
-	}
-	ASSERT(etmp != NULL);
-#endif
-
-	return e->next;
-}
-
-int wlc_eventq_cnt(wlc_eventq_t *eq)
-{
-	wlc_event_t *etmp;
-	int cnt = 0;
-
-	for (etmp = eq->head; etmp; etmp = etmp->next)
-		cnt++;
-
-	return cnt;
-}
-
-bool wlc_eventq_avail(wlc_eventq_t *eq)
-{
-	return (eq->head != NULL);
-}
-
-/*
- * Local Functions
- */
-static void wlc_timer_cb(void *arg)
-{
-	struct wlc_eventq *eq = (struct wlc_eventq *)arg;
-
-	ASSERT(eq->tpending == true);
-	ASSERT(wlc_eventq_avail(eq) == true);
-	ASSERT(eq->workpending == false);
-	eq->workpending = true;
-
-	if (eq->cb)
-		eq->cb(eq->wlc);
-
-	ASSERT(wlc_eventq_avail(eq) == false);
-	ASSERT(eq->tpending == true);
-	eq->workpending = false;
-	eq->tpending = false;
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_event.h b/drivers/staging/brcm80211/sys/wlc_event.h
deleted file mode 100644
index e75582d..0000000
--- a/drivers/staging/brcm80211/sys/wlc_event.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_EVENT_H_
-#define _WLC_EVENT_H_
-
-typedef struct wlc_eventq wlc_eventq_t;
-
-typedef void (*wlc_eventq_cb_t) (void *arg);
-
-extern wlc_eventq_t *wlc_eventq_attach(struct wlc_pub *pub,
-				       struct wlc_info *wlc,
-				       void *wl, wlc_eventq_cb_t cb);
-extern int wlc_eventq_detach(wlc_eventq_t *eq);
-extern int wlc_eventq_down(wlc_eventq_t *eq);
-extern void wlc_event_free(wlc_eventq_t *eq, wlc_event_t *e);
-extern wlc_event_t *wlc_eventq_next(wlc_eventq_t *eq, wlc_event_t *e);
-extern int wlc_eventq_cnt(wlc_eventq_t *eq);
-extern bool wlc_eventq_avail(wlc_eventq_t *eq);
-extern wlc_event_t *wlc_eventq_deq(wlc_eventq_t *eq);
-extern void wlc_eventq_enq(wlc_eventq_t *eq, wlc_event_t *e);
-extern wlc_event_t *wlc_event_alloc(wlc_eventq_t *eq);
-
-extern int wlc_eventq_register_ind(wlc_eventq_t *eq, void *bitvect);
-extern int wlc_eventq_query_ind(wlc_eventq_t *eq, void *bitvect);
-extern int wlc_eventq_test_ind(wlc_eventq_t *eq, int et);
-extern int wlc_eventq_set_ind(wlc_eventq_t *eq, uint et, bool on);
-extern void wlc_eventq_flush(wlc_eventq_t *eq);
-extern void wlc_assign_event_msg(struct wlc_info *wlc, wl_event_msg_t *msg,
-				 const wlc_event_t *e, u8 *data,
-				 u32 len);
-
-#ifdef MSGTRACE
-extern void wlc_event_sendup_trace(struct wlc_info *wlc, hndrte_dev_t *bus,
-				   u8 *hdr, u16 hdrlen, u8 *buf,
-				   u16 buflen);
-#endif
-
-#endif				/* _WLC_EVENT_H_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_key.h b/drivers/staging/brcm80211/sys/wlc_key.h
deleted file mode 100644
index 6678c69..0000000
--- a/drivers/staging/brcm80211/sys/wlc_key.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_key_h_
-#define _wlc_key_h_
-
-struct scb;
-struct wlc_info;
-struct wlc_bsscfg;
-/* Maximum # of keys that wl driver supports in S/W.
- * Keys supported in H/W is less than or equal to WSEC_MAX_KEYS.
- */
-#define WSEC_MAX_KEYS		54	/* Max # of keys (50 + 4 default keys) */
-#define WLC_DEFAULT_KEYS	4	/* Default # of keys */
-
-#define WSEC_MAX_WOWL_KEYS 5	/* Max keys in WOWL mode (1 + 4 default keys) */
-
-#define WPA2_GTK_MAX	3
-
-/*
-* Max # of keys currently supported:
-*
-*     s/w keys if WSEC_SW(wlc->wsec).
-*     h/w keys otherwise.
-*/
-#define WLC_MAX_WSEC_KEYS(wlc) WSEC_MAX_KEYS
-
-/* number of 802.11 default (non-paired, group keys) */
-#define WSEC_MAX_DEFAULT_KEYS	4	/* # of default keys */
-
-/* Max # of hardware keys supported */
-#define WLC_MAX_WSEC_HW_KEYS(wlc) WSEC_MAX_RCMTA_KEYS
-
-/* Max # of hardware TKIP MIC keys supported */
-#define WLC_MAX_TKMIC_HW_KEYS(wlc) ((D11REV_GE((wlc)->pub->corerev, 13)) ? \
-		WSEC_MAX_TKMIC_ENGINE_KEYS : 0)
-
-#define WSEC_HW_TKMIC_KEY(wlc, key, bsscfg) \
-	(((D11REV_GE((wlc)->pub->corerev, 13)) && ((wlc)->machwcap & MCAP_TKIPMIC)) && \
-	 (key) && ((key)->algo == CRYPTO_ALGO_TKIP) && \
-	 !WSEC_SOFTKEY(wlc, key, bsscfg) && \
-	WSEC_KEY_INDEX(wlc, key) >= WLC_DEFAULT_KEYS && \
-	(WSEC_KEY_INDEX(wlc, key) < WSEC_MAX_TKMIC_ENGINE_KEYS))
-
-/* index of key in key table */
-#define WSEC_KEY_INDEX(wlc, key)	((key)->idx)
-
-#define WSEC_SOFTKEY(wlc, key, bsscfg) (WLC_SW_KEYS(wlc, bsscfg) || \
-	WSEC_KEY_INDEX(wlc, key) >= WLC_MAX_WSEC_HW_KEYS(wlc))
-
-/* get a key, non-NULL only if key allocated and not clear */
-#define WSEC_KEY(wlc, i)	(((wlc)->wsec_keys[i] && (wlc)->wsec_keys[i]->len) ? \
-	(wlc)->wsec_keys[i] : NULL)
-
-#define WSEC_SCB_KEY_VALID(scb)	(((scb)->key && (scb)->key->len) ? true : false)
-
-/* default key */
-#define WSEC_BSS_DEFAULT_KEY(bsscfg) (((bsscfg)->wsec_index == -1) ? \
-	(struct wsec_key *)NULL:(bsscfg)->bss_def_keys[(bsscfg)->wsec_index])
-
-/* Macros for key management in IBSS mode */
-#define WSEC_IBSS_MAX_PEERS	16	/* Max # of IBSS Peers */
-#define WSEC_IBSS_RCMTA_INDEX(idx) \
-	(((idx - WSEC_MAX_DEFAULT_KEYS) % WSEC_IBSS_MAX_PEERS) + WSEC_MAX_DEFAULT_KEYS)
-
-/* contiguous # key slots for infrastructure mode STA */
-#define WSEC_BSS_STA_KEY_GROUP_SIZE	5
-
-typedef struct wsec_iv {
-	u32 hi;		/* upper 32 bits of IV */
-	u16 lo;		/* lower 16 bits of IV */
-} wsec_iv_t;
-
-#define WLC_NUMRXIVS	16	/* # rx IVs (one per 802.11e TID) */
-
-typedef struct wsec_key {
-	struct ether_addr ea;	/* per station */
-	u8 idx;		/* key index in wsec_keys array */
-	u8 id;		/* key ID [0-3] */
-	u8 algo;		/* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */
-	u8 rcmta;		/* rcmta entry index, same as idx by default */
-	u16 flags;		/* misc flags */
-	u8 algo_hw;		/* cache for hw register */
-	u8 aes_mode;		/* cache for hw register */
-	s8 iv_len;		/* IV length */
-	s8 icv_len;		/* ICV length */
-	u32 len;		/* key length..don't move this var */
-	/* data is 4byte aligned */
-	u8 data[DOT11_MAX_KEY_SIZE];	/* key data */
-	wsec_iv_t rxiv[WLC_NUMRXIVS];	/* Rx IV (one per TID) */
-	wsec_iv_t txiv;		/* Tx IV */
-
-} wsec_key_t;
-
-#define broken_roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-typedef struct {
-	u8 vec[broken_roundup(WSEC_MAX_KEYS, NBBY) / NBBY];	/* bitvec of wsec_key indexes */
-} wsec_key_vec_t;
-
-/* For use with wsec_key_t.flags */
-
-#define WSEC_BS_UPDATE		(1 << 0)	/* Indicates hw needs key update on BS switch */
-#define WSEC_PRIMARY_KEY	(1 << 1)	/* Indicates this key is the primary (ie tx) key */
-#define WSEC_TKIP_ERROR		(1 << 2)	/* Provoke deliberate MIC error */
-#define WSEC_REPLAY_ERROR	(1 << 3)	/* Provoke deliberate replay */
-#define WSEC_IBSS_PEER_GROUP_KEY	(1 << 7)	/* Flag: group key for a IBSS PEER */
-#define WSEC_ICV_ERROR		(1 << 8)	/* Provoke deliberate ICV error */
-
-#define wlc_key_insert(a, b, c, d, e, f, g, h, i, j) (BCME_ERROR)
-#define wlc_key_update(a, b, c) do {} while (0)
-#define wlc_key_remove(a, b, c) do {} while (0)
-#define wlc_key_remove_all(a, b) do {} while (0)
-#define wlc_key_delete(a, b, c) do {} while (0)
-#define wlc_scb_key_delete(a, b) do {} while (0)
-#define wlc_key_lookup(a, b, c, d, e) (NULL)
-#define wlc_key_hw_init_all(a) do {} while (0)
-#define wlc_key_hw_init(a, b, c)  do {} while (0)
-#define wlc_key_hw_wowl_init(a, b, c, d) do {} while (0)
-#define wlc_key_sw_wowl_update(a, b, c, d, e) do {} while (0)
-#define wlc_key_sw_wowl_create(a, b, c) (BCME_ERROR)
-#define wlc_key_iv_update(a, b, c, d, e) do {(void)e; } while (0)
-#define wlc_key_iv_init(a, b, c) do {} while (0)
-#define wlc_key_set_error(a, b, c) (BCME_ERROR)
-#define wlc_key_dump_hw(a, b) (BCME_ERROR)
-#define wlc_key_dump_sw(a, b) (BCME_ERROR)
-#define wlc_key_defkeyflag(a) (0)
-#define wlc_rcmta_add_bssid(a, b) do {} while (0)
-#define wlc_rcmta_del_bssid(a, b) do {} while (0)
-#define wlc_key_scb_delete(a, b) do {} while (0)
-
-#endif				/* _wlc_key_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_mac80211.c b/drivers/staging/brcm80211/sys/wlc_mac80211.c
deleted file mode 100644
index e37e805..0000000
--- a/drivers/staging/brcm80211/sys/wlc_mac80211.c
+++ /dev/null
@@ -1,8476 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <linux/ctype.h>
-#include <linux/etherdevice.h>
-#include <bcmdefs.h>
-#include <bcmdevs.h>
-#include <wlc_cfg.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <bcmwifi.h>
-#include <siutils.h>
-#include <bcmendian.h>
-#include <proto/wpa.h>
-#include <pcicfg.h>
-#include <bcmsrom.h>
-#include <wlioctl.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-#include <hndpmu.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_pub.h>
-#include <wlc_key.h>
-#include <wlc_bsscfg.h>
-#include <wlc_channel.h>
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_bmac.h>
-#include <wlc_scb.h>
-#include <wlc_phy_hal.h>
-#include <wlc_phy_shim.h>
-#include <wlc_antsel.h>
-#include <wlc_stf.h>
-#include <wlc_ampdu.h>
-#include <wlc_event.h>
-#include <wl_export.h>
-#include "d11ucode_ext.h"
-#include <wlc_alloc.h>
-#include <net/mac80211.h>
-#include <wl_dbg.h>
-
-
-/*
- * buffer length needed for wlc_format_ssid
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN	((4 * DOT11_MAX_SSID_LEN) + 1)
-
-#define	TIMER_INTERVAL_WATCHDOG	1000	/* watchdog timer, in unit of ms */
-#define	TIMER_INTERVAL_RADIOCHK	800	/* radio monitor timer, in unit of ms */
-
-#ifndef WLC_MPC_MAX_DELAYCNT
-#define	WLC_MPC_MAX_DELAYCNT	10	/* Max MPC timeout, in unit of watchdog */
-#endif
-#define	WLC_MPC_MIN_DELAYCNT	1	/* Min MPC timeout, in unit of watchdog */
-#define	WLC_MPC_THRESHOLD	3	/* MPC count threshold level */
-
-#define	BEACON_INTERVAL_DEFAULT	100	/* beacon interval, in unit of 1024TU */
-#define	DTIM_INTERVAL_DEFAULT	3	/* DTIM interval, in unit of beacon interval */
-
-/* Scale down delays to accommodate QT slow speed */
-#define	BEACON_INTERVAL_DEF_QT	20	/* beacon interval, in unit of 1024TU */
-#define	DTIM_INTERVAL_DEF_QT	1	/* DTIM interval, in unit of beacon interval */
-
-#define	TBTT_ALIGN_LEEWAY_US	100	/* min leeway before first TBTT in us */
-
-/*
- * driver maintains internal 'tick'(wlc->pub->now) which increments in 1s OS timer(soft
- * watchdog) it is not a wall clock and won't increment when driver is in "down" state
- * this low resolution driver tick can be used for maintenance tasks such as phy
- * calibration and scb update
- */
-
-/* watchdog trigger mode: OSL timer or TBTT */
-#define WLC_WATCHDOG_TBTT(wlc) \
-	(wlc->stas_associated > 0 && wlc->PM != PM_OFF && wlc->pub->align_wd_tbtt)
-
-/* To inform the ucode of the last mcast frame posted so that it can clear moredata bit */
-#define BCMCFID(wlc, fid) wlc_bmac_write_shm((wlc)->hw, M_BCMC_FID, (fid))
-
-#define WLC_WAR16165(wlc) (wlc->pub->sih->bustype == PCI_BUS && \
-				(!AP_ENAB(wlc->pub)) && (wlc->war16165))
-
-/* debug/trace */
-uint wl_msg_level =
-#if defined(BCMDBG)
-    WL_ERROR_VAL;
-#else
-    0;
-#endif				/* BCMDBG */
-
-/* Find basic rate for a given rate */
-#define WLC_BASIC_RATE(wlc, rspec)	(IS_MCS(rspec) ? \
-			(wlc)->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK].leg_ofdm] : \
-			(wlc)->band->basic_rate[rspec & RSPEC_RATE_MASK])
-
-#define FRAMETYPE(r, mimoframe)	(IS_MCS(r) ? mimoframe	: (IS_CCK(r) ? FT_CCK : FT_OFDM))
-
-#define RFDISABLE_DEFAULT	10000000	/* rfdisable delay timer 500 ms, runs of ALP clock */
-
-#define WLC_TEMPSENSE_PERIOD		10	/* 10 second timeout */
-
-#define SCAN_IN_PROGRESS(x)	0
-
-#define EPI_VERSION_NUM		0x054b0b00
-
-#ifdef BCMDBG
-/* pointer to most recently allocated wl/wlc */
-static struct wlc_info *wlc_info_dbg = (struct wlc_info *) (NULL);
-#endif
-
-/* IOVar table */
-
-/* Parameter IDs, for use only internally to wlc -- in the wlc_iovars
- * table and by the wlc_doiovar() function.  No ordering is imposed:
- * the table is keyed by name, and the function uses a switch.
- */
-enum {
-	IOV_MPC = 1,
-	IOV_QTXPOWER,
-	IOV_BCN_LI_BCN,		/* Beacon listen interval in # of beacons */
-	IOV_LAST		/* In case of a need to check max ID number */
-};
-
-const bcm_iovar_t wlc_iovars[] = {
-	{"mpc", IOV_MPC, (IOVF_OPEN_ALLOW), IOVT_BOOL, 0},
-	{"qtxpower", IOV_QTXPOWER, (IOVF_WHL | IOVF_OPEN_ALLOW), IOVT_UINT32,
-	 0},
-	{"bcn_li_bcn", IOV_BCN_LI_BCN, 0, IOVT_UINT8, 0},
-	{NULL, 0, 0, 0, 0}
-};
-
-const u8 prio2fifo[NUMPRIO] = {
-	TX_AC_BE_FIFO,		/* 0    BE      AC_BE   Best Effort */
-	TX_AC_BK_FIFO,		/* 1    BK      AC_BK   Background */
-	TX_AC_BK_FIFO,		/* 2    --      AC_BK   Background */
-	TX_AC_BE_FIFO,		/* 3    EE      AC_BE   Best Effort */
-	TX_AC_VI_FIFO,		/* 4    CL      AC_VI   Video */
-	TX_AC_VI_FIFO,		/* 5    VI      AC_VI   Video */
-	TX_AC_VO_FIFO,		/* 6    VO      AC_VO   Voice */
-	TX_AC_VO_FIFO		/* 7    NC      AC_VO   Voice */
-};
-
-/* precedences numbers for wlc queues. These are twice as may levels as
- * 802.1D priorities.
- * Odd numbers are used for HI priority traffic at same precedence levels
- * These constants are used ONLY by wlc_prio2prec_map.  Do not use them elsewhere.
- */
-#define	_WLC_PREC_NONE		0	/* None = - */
-#define	_WLC_PREC_BK		2	/* BK - Background */
-#define	_WLC_PREC_BE		4	/* BE - Best-effort */
-#define	_WLC_PREC_EE		6	/* EE - Excellent-effort */
-#define	_WLC_PREC_CL		8	/* CL - Controlled Load */
-#define	_WLC_PREC_VI		10	/* Vi - Video */
-#define	_WLC_PREC_VO		12	/* Vo - Voice */
-#define	_WLC_PREC_NC		14	/* NC - Network Control */
-
-/* 802.1D Priority to precedence queue mapping */
-const u8 wlc_prio2prec_map[] = {
-	_WLC_PREC_BE,		/* 0 BE - Best-effort */
-	_WLC_PREC_BK,		/* 1 BK - Background */
-	_WLC_PREC_NONE,		/* 2 None = - */
-	_WLC_PREC_EE,		/* 3 EE - Excellent-effort */
-	_WLC_PREC_CL,		/* 4 CL - Controlled Load */
-	_WLC_PREC_VI,		/* 5 Vi - Video */
-	_WLC_PREC_VO,		/* 6 Vo - Voice */
-	_WLC_PREC_NC,		/* 7 NC - Network Control */
-};
-
-/* Sanity check for tx_prec_map and fifo synchup
- * Either there are some packets pending for the fifo, else if fifo is empty then
- * all the corresponding precmap bits should be set
- */
-#define WLC_TX_FIFO_CHECK(wlc, fifo) (TXPKTPENDGET((wlc), (fifo)) ||	\
-	(TXPKTPENDGET((wlc), (fifo)) == 0 && \
-	((wlc)->tx_prec_map & (wlc)->fifo2prec_map[(fifo)]) == \
-	(wlc)->fifo2prec_map[(fifo)]))
-
-/* TX FIFO number to WME/802.1E Access Category */
-const u8 wme_fifo2ac[] = { AC_BK, AC_BE, AC_VI, AC_VO, AC_BE, AC_BE };
-
-/* WME/802.1E Access Category to TX FIFO number */
-static const u8 wme_ac2fifo[] = { 1, 0, 2, 3 };
-
-static bool in_send_q = false;
-
-/* Shared memory location index for various AC params */
-#define wme_shmemacindex(ac)	wme_ac2fifo[ac]
-
-#ifdef BCMDBG
-static const char *fifo_names[] = {
-	"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
-const char *aci_names[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" };
-#endif
-
-static const u8 acbitmap2maxprio[] = {
-	PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
-	PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
-	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
-	PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
-};
-
-/* currently the best mechanism for determining SIFS is the band in use */
-#define SIFS(band) ((band)->bandtype == WLC_BAND_5G ? APHY_SIFS_TIME : BPHY_SIFS_TIME);
-
-/* value for # replay counters currently supported */
-#define WLC_REPLAY_CNTRS_VALUE	WPA_CAP_16_REPLAY_CNTRS
-
-/* local prototypes */
-static u16 BCMFASTPATH wlc_d11hdrs_mac80211(struct wlc_info *wlc,
-					       struct ieee80211_hw *hw,
-					       struct sk_buff *p,
-					       struct scb *scb, uint frag,
-					       uint nfrags, uint queue,
-					       uint next_frag_len,
-					       wsec_key_t *key,
-					       ratespec_t rspec_override);
-
-static void wlc_bss_default_init(struct wlc_info *wlc);
-static void wlc_ucode_mac_upd(struct wlc_info *wlc);
-static ratespec_t mac80211_wlc_set_nrate(struct wlc_info *wlc,
-					 struct wlcband *cur_band, u32 int_val);
-static void wlc_tx_prec_map_init(struct wlc_info *wlc);
-static void wlc_watchdog(void *arg);
-static void wlc_watchdog_by_timer(void *arg);
-static int wlc_set_rateset(struct wlc_info *wlc, wlc_rateset_t *rs_arg);
-static int wlc_iovar_rangecheck(struct wlc_info *wlc, u32 val,
-				const bcm_iovar_t *vi);
-static u8 wlc_local_constraint_qdbm(struct wlc_info *wlc);
-
-/* send and receive */
-static wlc_txq_info_t *wlc_txq_alloc(struct wlc_info *wlc,
-				     struct osl_info *osh);
-static void wlc_txq_free(struct wlc_info *wlc, struct osl_info *osh,
-			 wlc_txq_info_t *qi);
-static void wlc_txflowcontrol_signal(struct wlc_info *wlc, wlc_txq_info_t *qi,
-				     bool on, int prio);
-static void wlc_txflowcontrol_reset(struct wlc_info *wlc);
-static u16 wlc_compute_airtime(struct wlc_info *wlc, ratespec_t rspec,
-				  uint length);
-static void wlc_compute_cck_plcp(ratespec_t rate, uint length, u8 *plcp);
-static void wlc_compute_ofdm_plcp(ratespec_t rate, uint length, u8 *plcp);
-static void wlc_compute_mimo_plcp(ratespec_t rate, uint length, u8 *plcp);
-static u16 wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate,
-				    u8 preamble_type, uint next_frag_len);
-static void wlc_recvctl(struct wlc_info *wlc, struct osl_info *osh,
-			d11rxhdr_t *rxh, struct sk_buff *p);
-static uint wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t rate,
-			       u8 preamble_type, uint dur);
-static uint wlc_calc_ack_time(struct wlc_info *wlc, ratespec_t rate,
-			      u8 preamble_type);
-static uint wlc_calc_cts_time(struct wlc_info *wlc, ratespec_t rate,
-			      u8 preamble_type);
-/* interrupt, up/down, band */
-static void wlc_setband(struct wlc_info *wlc, uint bandunit);
-static chanspec_t wlc_init_chanspec(struct wlc_info *wlc);
-static void wlc_bandinit_ordered(struct wlc_info *wlc, chanspec_t chanspec);
-static void wlc_bsinit(struct wlc_info *wlc);
-static int wlc_duty_cycle_set(struct wlc_info *wlc, int duty_cycle, bool isOFDM,
-			      bool writeToShm);
-static void wlc_radio_hwdisable_upd(struct wlc_info *wlc);
-static bool wlc_radio_monitor_start(struct wlc_info *wlc);
-static void wlc_radio_timer(void *arg);
-static void wlc_radio_enable(struct wlc_info *wlc);
-static void wlc_radio_upd(struct wlc_info *wlc);
-
-/* scan, association, BSS */
-static uint wlc_calc_ba_time(struct wlc_info *wlc, ratespec_t rate,
-			     u8 preamble_type);
-static void wlc_update_mimo_band_bwcap(struct wlc_info *wlc, u8 bwcap);
-static void wlc_ht_update_sgi_rx(struct wlc_info *wlc, int val);
-static void wlc_ht_update_ldpc(struct wlc_info *wlc, s8 val);
-static void wlc_war16165(struct wlc_info *wlc, bool tx);
-
-static void wlc_process_eventq(void *arg);
-static void wlc_wme_retries_write(struct wlc_info *wlc);
-static bool wlc_attach_stf_ant_init(struct wlc_info *wlc);
-static uint wlc_attach_module(struct wlc_info *wlc);
-static void wlc_detach_module(struct wlc_info *wlc);
-static void wlc_timers_deinit(struct wlc_info *wlc);
-static void wlc_down_led_upd(struct wlc_info *wlc);
-static uint wlc_down_del_timer(struct wlc_info *wlc);
-static void wlc_ofdm_rateset_war(struct wlc_info *wlc);
-static int _wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-		      struct wlc_if *wlcif);
-
-#if defined(BCMDBG)
-void wlc_get_rcmta(struct wlc_info *wlc, int idx, struct ether_addr *addr)
-{
-	d11regs_t *regs = wlc->regs;
-	u32 v32;
-	struct osl_info *osh;
-
-	WL_TRACE("wl%d: %s\n", WLCWLUNIT(wlc), __func__);
-
-	ASSERT(wlc->pub->corerev > 4);
-
-	osh = wlc->osh;
-
-	W_REG(osh, &regs->objaddr, (OBJADDR_RCMTA_SEL | (idx * 2)));
-	(void)R_REG(osh, &regs->objaddr);
-	v32 = R_REG(osh, &regs->objdata);
-	addr->octet[0] = (u8) v32;
-	addr->octet[1] = (u8) (v32 >> 8);
-	addr->octet[2] = (u8) (v32 >> 16);
-	addr->octet[3] = (u8) (v32 >> 24);
-	W_REG(osh, &regs->objaddr, (OBJADDR_RCMTA_SEL | ((idx * 2) + 1)));
-	(void)R_REG(osh, &regs->objaddr);
-	v32 = R_REG(osh, (volatile u16 *)&regs->objdata);
-	addr->octet[4] = (u8) v32;
-	addr->octet[5] = (u8) (v32 >> 8);
-}
-#endif				/* defined(BCMDBG) */
-
-/* keep the chip awake if needed */
-bool wlc_stay_awake(struct wlc_info *wlc)
-{
-	return true;
-}
-
-/* conditions under which the PM bit should be set in outgoing frames and STAY_AWAKE is meaningful
- */
-bool wlc_ps_allowed(struct wlc_info *wlc)
-{
-	int idx;
-	wlc_bsscfg_t *cfg;
-
-	/* disallow PS when one of the following global conditions meets */
-	if (!wlc->pub->associated || !wlc->PMenabled || wlc->PM_override)
-		return false;
-
-	/* disallow PS when one of these meets when not scanning */
-	if (!wlc->PMblocked) {
-		if (AP_ACTIVE(wlc) || wlc->monitor)
-			return false;
-	}
-
-	FOREACH_AS_STA(wlc, idx, cfg) {
-		/* disallow PS when one of the following bsscfg specific conditions meets */
-		if (!cfg->BSS || !WLC_PORTOPEN(cfg))
-			return false;
-
-		if (!cfg->dtim_programmed)
-			return false;
-	}
-
-	return true;
-}
-
-void wlc_reset(struct wlc_info *wlc)
-{
-	WL_TRACE("wl%d: wlc_reset\n", wlc->pub->unit);
-
-	wlc->check_for_unaligned_tbtt = false;
-
-	/* slurp up hw mac counters before core reset */
-	if (WLC_UPDATE_STATS(wlc)) {
-		wlc_statsupd(wlc);
-
-		/* reset our snapshot of macstat counters */
-		memset((char *)wlc->core->macstat_snapshot, 0,
-			sizeof(macstat_t));
-	}
-
-	wlc_bmac_reset(wlc->hw);
-	wlc_ampdu_reset(wlc->ampdu);
-	wlc->txretried = 0;
-
-}
-
-void wlc_fatal_error(struct wlc_info *wlc)
-{
-	WL_ERROR("wl%d: fatal error, reinitializing\n", wlc->pub->unit);
-	wl_init(wlc->wl);
-}
-
-/* Return the channel the driver should initialize during wlc_init.
- * the channel may have to be changed from the currently configured channel
- * if other configurations are in conflict (bandlocked, 11n mode disabled,
- * invalid channel for current country, etc.)
- */
-static chanspec_t wlc_init_chanspec(struct wlc_info *wlc)
-{
-	chanspec_t chanspec =
-	    1 | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE |
-	    WL_CHANSPEC_BAND_2G;
-
-	/* make sure the channel is on the supported band if we are band-restricted */
-	if (wlc->bandlocked || NBANDS(wlc) == 1) {
-		ASSERT(CHSPEC_WLCBANDUNIT(chanspec) == wlc->band->bandunit);
-	}
-	ASSERT(wlc_valid_chanspec_db(wlc->cmi, chanspec));
-	return chanspec;
-}
-
-struct scb global_scb;
-
-static void wlc_init_scb(struct wlc_info *wlc, struct scb *scb)
-{
-	int i;
-	scb->flags = SCB_WMECAP | SCB_HTCAP;
-	for (i = 0; i < NUMPRIO; i++)
-		scb->seqnum[i] = 0;
-}
-
-void wlc_init(struct wlc_info *wlc)
-{
-	d11regs_t *regs;
-	chanspec_t chanspec;
-	int i;
-	wlc_bsscfg_t *bsscfg;
-	bool mute = false;
-
-	WL_TRACE("wl%d: wlc_init\n", wlc->pub->unit);
-
-	regs = wlc->regs;
-
-	/* This will happen if a big-hammer was executed. In that case, we want to go back
-	 * to the channel that we were on and not new channel
-	 */
-	if (wlc->pub->associated)
-		chanspec = wlc->home_chanspec;
-	else
-		chanspec = wlc_init_chanspec(wlc);
-
-	wlc_bmac_init(wlc->hw, chanspec, mute);
-
-	wlc->seckeys = wlc_bmac_read_shm(wlc->hw, M_SECRXKEYS_PTR) * 2;
-	if (D11REV_GE(wlc->pub->corerev, 15) && (wlc->machwcap & MCAP_TKIPMIC))
-		wlc->tkmickeys =
-		    wlc_bmac_read_shm(wlc->hw, M_TKMICKEYS_PTR) * 2;
-
-	/* update beacon listen interval */
-	wlc_bcn_li_upd(wlc);
-	wlc->bcn_wait_prd =
-	    (u8) (wlc_bmac_read_shm(wlc->hw, M_NOSLPZNATDTIM) >> 10);
-	ASSERT(wlc->bcn_wait_prd > 0);
-
-	/* the world is new again, so is our reported rate */
-	wlc_reprate_init(wlc);
-
-	/* write ethernet address to core */
-	FOREACH_BSS(wlc, i, bsscfg) {
-		wlc_set_mac(bsscfg);
-		wlc_set_bssid(bsscfg);
-	}
-
-	/* Update tsf_cfprep if associated and up */
-	if (wlc->pub->associated) {
-		FOREACH_BSS(wlc, i, bsscfg) {
-			if (bsscfg->up) {
-				u32 bi;
-
-				/* get beacon period from bsscfg and convert to uS */
-				bi = bsscfg->current_bss->beacon_period << 10;
-				/* update the tsf_cfprep register */
-				/* since init path would reset to default value */
-				W_REG(wlc->osh, &regs->tsf_cfprep,
-				      (bi << CFPREP_CBI_SHIFT));
-
-				/* Update maccontrol PM related bits */
-				wlc_set_ps_ctrl(wlc);
-
-				break;
-			}
-		}
-	}
-
-	wlc_key_hw_init_all(wlc);
-
-	wlc_bandinit_ordered(wlc, chanspec);
-
-	wlc_init_scb(wlc, &global_scb);
-
-	/* init probe response timeout */
-	wlc_write_shm(wlc, M_PRS_MAXTIME, wlc->prb_resp_timeout);
-
-	/* init max burst txop (framebursting) */
-	wlc_write_shm(wlc, M_MBURST_TXOP,
-		      (wlc->
-		       _rifs ? (EDCF_AC_VO_TXOP_AP << 5) : MAXFRAMEBURST_TXOP));
-
-	/* initialize maximum allowed duty cycle */
-	wlc_duty_cycle_set(wlc, wlc->tx_duty_cycle_ofdm, true, true);
-	wlc_duty_cycle_set(wlc, wlc->tx_duty_cycle_cck, false, true);
-
-	/* Update some shared memory locations related to max AMPDU size allowed to received */
-	wlc_ampdu_shm_upd(wlc->ampdu);
-
-	/* band-specific inits */
-	wlc_bsinit(wlc);
-
-	/* Enable EDCF mode (while the MAC is suspended) */
-	if (EDCF_ENAB(wlc->pub)) {
-		OR_REG(wlc->osh, &regs->ifs_ctl, IFS_USEEDCF);
-		wlc_edcf_setparams(wlc->cfg, false);
-	}
-
-	/* Init precedence maps for empty FIFOs */
-	wlc_tx_prec_map_init(wlc);
-
-	/* read the ucode version if we have not yet done so */
-	if (wlc->ucode_rev == 0) {
-		wlc->ucode_rev =
-		    wlc_read_shm(wlc, M_BOM_REV_MAJOR) << NBITS(u16);
-		wlc->ucode_rev |= wlc_read_shm(wlc, M_BOM_REV_MINOR);
-	}
-
-	/* ..now really unleash hell (allow the MAC out of suspend) */
-	wlc_enable_mac(wlc);
-
-	/* clear tx flow control */
-	wlc_txflowcontrol_reset(wlc);
-
-	/* clear tx data fifo suspends */
-	wlc->tx_suspended = false;
-
-	/* enable the RF Disable Delay timer */
-	if (D11REV_GE(wlc->pub->corerev, 10))
-		W_REG(wlc->osh, &wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
-
-	/* initialize mpc delay */
-	wlc->mpc_delay_off = wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
-
-	/*
-	 * Initialize WME parameters; if they haven't been set by some other
-	 * mechanism (IOVar, etc) then read them from the hardware.
-	 */
-	if (WLC_WME_RETRY_SHORT_GET(wlc, 0) == 0) {	/* Unintialized; read from HW */
-		int ac;
-
-		ASSERT(wlc->clk);
-		for (ac = 0; ac < AC_COUNT; ac++) {
-			wlc->wme_retries[ac] =
-			    wlc_read_shm(wlc, M_AC_TXLMT_ADDR(ac));
-		}
-	}
-}
-
-void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc)
-{
-	wlc->bcnmisc_monitor = promisc;
-	wlc_mac_bcn_promisc(wlc);
-}
-
-void wlc_mac_bcn_promisc(struct wlc_info *wlc)
-{
-	if ((AP_ENAB(wlc->pub) && (N_ENAB(wlc->pub) || wlc->band->gmode)) ||
-	    wlc->bcnmisc_ibss || wlc->bcnmisc_scan || wlc->bcnmisc_monitor)
-		wlc_mctrl(wlc, MCTL_BCNS_PROMISC, MCTL_BCNS_PROMISC);
-	else
-		wlc_mctrl(wlc, MCTL_BCNS_PROMISC, 0);
-}
-
-/* set or clear maccontrol bits MCTL_PROMISC and MCTL_KEEPCONTROL */
-void wlc_mac_promisc(struct wlc_info *wlc)
-{
-	u32 promisc_bits = 0;
-
-	/* promiscuous mode just sets MCTL_PROMISC
-	 * Note: APs get all BSS traffic without the need to set the MCTL_PROMISC bit
-	 * since all BSS data traffic is directed at the AP
-	 */
-	if (PROMISC_ENAB(wlc->pub) && !AP_ENAB(wlc->pub) && !wlc->wet)
-		promisc_bits |= MCTL_PROMISC;
-
-	/* monitor mode needs both MCTL_PROMISC and MCTL_KEEPCONTROL
-	 * Note: monitor mode also needs MCTL_BCNS_PROMISC, but that is
-	 * handled in wlc_mac_bcn_promisc()
-	 */
-	if (MONITOR_ENAB(wlc))
-		promisc_bits |= MCTL_PROMISC | MCTL_KEEPCONTROL;
-
-	wlc_mctrl(wlc, MCTL_PROMISC | MCTL_KEEPCONTROL, promisc_bits);
-}
-
-/* check if hps and wake states of sw and hw are in sync */
-bool wlc_ps_check(struct wlc_info *wlc)
-{
-	bool res = true;
-	bool hps, wake;
-	bool wake_ok;
-
-	if (!AP_ACTIVE(wlc)) {
-		volatile u32 tmp;
-		tmp = R_REG(wlc->osh, &wlc->regs->maccontrol);
-
-		/* If deviceremoved is detected, then don't take any action as this can be called
-		 * in any context. Assume that caller will take care of the condition. This is just
-		 * to avoid assert
-		 */
-		if (tmp == 0xffffffff) {
-			WL_ERROR("wl%d: %s: dead chip\n",
-				 wlc->pub->unit, __func__);
-			return DEVICEREMOVED(wlc);
-		}
-
-		hps = PS_ALLOWED(wlc);
-
-		if (hps != ((tmp & MCTL_HPS) != 0)) {
-			int idx;
-			wlc_bsscfg_t *cfg;
-			WL_ERROR("wl%d: hps not sync, sw %d, maccontrol 0x%x\n",
-				 wlc->pub->unit, hps, tmp);
-			FOREACH_BSS(wlc, idx, cfg) {
-				if (!BSSCFG_STA(cfg))
-					continue;
-			}
-
-			res = false;
-		}
-		/* For a monolithic build the wake check can be exact since it looks at wake
-		 * override bits. The MCTL_WAKE bit should match the 'wake' value.
-		 */
-		wake = STAY_AWAKE(wlc) || wlc->hw->wake_override;
-		wake_ok = (wake == ((tmp & MCTL_WAKE) != 0));
-		if (hps && !wake_ok) {
-			WL_ERROR("wl%d: wake not sync, sw %d maccontrol 0x%x\n",
-				 wlc->pub->unit, wake, tmp);
-			res = false;
-		}
-	}
-	ASSERT(res);
-	return res;
-}
-
-/* push sw hps and wake state through hardware */
-void wlc_set_ps_ctrl(struct wlc_info *wlc)
-{
-	u32 v1, v2;
-	bool hps, wake;
-	bool awake_before;
-
-	hps = PS_ALLOWED(wlc);
-	wake = hps ? (STAY_AWAKE(wlc)) : true;
-
-	WL_TRACE("wl%d: wlc_set_ps_ctrl: hps %d wake %d\n",
-		 wlc->pub->unit, hps, wake);
-
-	v1 = R_REG(wlc->osh, &wlc->regs->maccontrol);
-	v2 = 0;
-	if (hps)
-		v2 |= MCTL_HPS;
-	if (wake)
-		v2 |= MCTL_WAKE;
-
-	wlc_mctrl(wlc, MCTL_WAKE | MCTL_HPS, v2);
-
-	awake_before = ((v1 & MCTL_WAKE) || ((v1 & MCTL_HPS) == 0));
-
-	if (wake && !awake_before)
-		wlc_bmac_wait_for_wake(wlc->hw);
-
-}
-
-/*
- * Write this BSS config's MAC address to core.
- * Updates RXE match engine.
- */
-int wlc_set_mac(wlc_bsscfg_t *cfg)
-{
-	int err = 0;
-	struct wlc_info *wlc = cfg->wlc;
-
-	if (cfg == wlc->cfg) {
-		/* enter the MAC addr into the RXE match registers */
-		wlc_set_addrmatch(wlc, RCM_MAC_OFFSET, &cfg->cur_etheraddr);
-	}
-
-	wlc_ampdu_macaddr_upd(wlc);
-
-	return err;
-}
-
-/* Write the BSS config's BSSID address to core (set_bssid in d11procs.tcl).
- * Updates RXE match engine.
- */
-void wlc_set_bssid(wlc_bsscfg_t *cfg)
-{
-	struct wlc_info *wlc = cfg->wlc;
-
-	/* if primary config, we need to update BSSID in RXE match registers */
-	if (cfg == wlc->cfg) {
-		wlc_set_addrmatch(wlc, RCM_BSSID_OFFSET, &cfg->BSSID);
-	}
-#ifdef SUPPORT_HWKEYS
-	else if (BSSCFG_STA(cfg) && cfg->BSS) {
-		wlc_rcmta_add_bssid(wlc, cfg);
-	}
-#endif
-}
-
-/*
- * Suspend the the MAC and update the slot timing
- * for standard 11b/g (20us slots) or shortslot 11g (9us slots).
- */
-void wlc_switch_shortslot(struct wlc_info *wlc, bool shortslot)
-{
-	int idx;
-	wlc_bsscfg_t *cfg;
-
-	ASSERT(wlc->band->gmode);
-
-	/* use the override if it is set */
-	if (wlc->shortslot_override != WLC_SHORTSLOT_AUTO)
-		shortslot = (wlc->shortslot_override == WLC_SHORTSLOT_ON);
-
-	if (wlc->shortslot == shortslot)
-		return;
-
-	wlc->shortslot = shortslot;
-
-	/* update the capability based on current shortslot mode */
-	FOREACH_BSS(wlc, idx, cfg) {
-		if (!cfg->associated)
-			continue;
-		cfg->current_bss->capability &= ~DOT11_CAP_SHORTSLOT;
-		if (wlc->shortslot)
-			cfg->current_bss->capability |= DOT11_CAP_SHORTSLOT;
-	}
-
-	wlc_bmac_set_shortslot(wlc->hw, shortslot);
-}
-
-static u8 wlc_local_constraint_qdbm(struct wlc_info *wlc)
-{
-	u8 local;
-	s16 local_max;
-
-	local = WLC_TXPWR_MAX;
-	if (wlc->pub->associated &&
-	    (wf_chspec_ctlchan(wlc->chanspec) ==
-	     wf_chspec_ctlchan(wlc->home_chanspec))) {
-
-		/* get the local power constraint if we are on the AP's
-		 * channel [802.11h, 7.3.2.13]
-		 */
-		/* Clamp the value between 0 and WLC_TXPWR_MAX w/o overflowing the target */
-		local_max =
-		    (wlc->txpwr_local_max -
-		     wlc->txpwr_local_constraint) * WLC_TXPWR_DB_FACTOR;
-		if (local_max > 0 && local_max < WLC_TXPWR_MAX)
-			return (u8) local_max;
-		if (local_max < 0)
-			return 0;
-	}
-
-	return local;
-}
-
-/* propagate home chanspec to all bsscfgs in case bsscfg->current_bss->chanspec is referenced */
-void wlc_set_home_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	if (wlc->home_chanspec != chanspec) {
-		int idx;
-		wlc_bsscfg_t *cfg;
-
-		wlc->home_chanspec = chanspec;
-
-		FOREACH_BSS(wlc, idx, cfg) {
-			if (!cfg->associated)
-				continue;
-			cfg->target_bss->chanspec = chanspec;
-			cfg->current_bss->chanspec = chanspec;
-		}
-
-	}
-}
-
-static void wlc_set_phy_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	/* Save our copy of the chanspec */
-	wlc->chanspec = chanspec;
-
-	/* Set the chanspec and power limits for this locale after computing
-	 * any 11h local tx power constraints.
-	 */
-	wlc_channel_set_chanspec(wlc->cmi, chanspec,
-				 wlc_local_constraint_qdbm(wlc));
-
-	if (wlc->stf->ss_algosel_auto)
-		wlc_stf_ss_algo_channel_get(wlc, &wlc->stf->ss_algo_channel,
-					    chanspec);
-
-	wlc_stf_ss_update(wlc, wlc->band);
-
-}
-
-void wlc_set_chanspec(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	uint bandunit;
-	bool switchband = false;
-	chanspec_t old_chanspec = wlc->chanspec;
-
-	if (!wlc_valid_chanspec_db(wlc->cmi, chanspec)) {
-		WL_ERROR("wl%d: %s: Bad channel %d\n",
-			 wlc->pub->unit, __func__, CHSPEC_CHANNEL(chanspec));
-		ASSERT(wlc_valid_chanspec_db(wlc->cmi, chanspec));
-		return;
-	}
-
-	/* Switch bands if necessary */
-	if (NBANDS(wlc) > 1) {
-		bandunit = CHSPEC_WLCBANDUNIT(chanspec);
-		if (wlc->band->bandunit != bandunit || wlc->bandinit_pending) {
-			switchband = true;
-			if (wlc->bandlocked) {
-				WL_ERROR("wl%d: %s: chspec %d band is locked!\n",
-					 wlc->pub->unit, __func__,
-					 CHSPEC_CHANNEL(chanspec));
-				return;
-			}
-			/* BMAC_NOTE: should the setband call come after the wlc_bmac_chanspec() ?
-			 * if the setband updates (wlc_bsinit) use low level calls to inspect and
-			 * set state, the state inspected may be from the wrong band, or the
-			 * following wlc_bmac_set_chanspec() may undo the work.
-			 */
-			wlc_setband(wlc, bandunit);
-		}
-	}
-
-	ASSERT(N_ENAB(wlc->pub) || !CHSPEC_IS40(chanspec));
-
-	/* sync up phy/radio chanspec */
-	wlc_set_phy_chanspec(wlc, chanspec);
-
-	/* init antenna selection */
-	if (CHSPEC_WLC_BW(old_chanspec) != CHSPEC_WLC_BW(chanspec)) {
-		if (WLANTSEL_ENAB(wlc))
-			wlc_antsel_init(wlc->asi);
-
-		/* Fix the hardware rateset based on bw.
-		 * Mainly add MCS32 for 40Mhz, remove MCS 32 for 20Mhz
-		 */
-		wlc_rateset_bw_mcs_filter(&wlc->band->hw_rateset,
-					  wlc->band->
-					  mimo_cap_40 ? CHSPEC_WLC_BW(chanspec)
-					  : 0);
-	}
-
-	/* update some mac configuration since chanspec changed */
-	wlc_ucode_mac_upd(wlc);
-}
-
-#if defined(BCMDBG)
-static int wlc_get_current_txpwr(struct wlc_info *wlc, void *pwr, uint len)
-{
-	txpwr_limits_t txpwr;
-	tx_power_t power;
-	tx_power_legacy_t *old_power = NULL;
-	int r, c;
-	uint qdbm;
-	bool override;
-
-	if (len == sizeof(tx_power_legacy_t))
-		old_power = (tx_power_legacy_t *) pwr;
-	else if (len < sizeof(tx_power_t))
-		return BCME_BUFTOOSHORT;
-
-	memset(&power, 0, sizeof(tx_power_t));
-
-	power.chanspec = WLC_BAND_PI_RADIO_CHANSPEC;
-	if (wlc->pub->associated)
-		power.local_chanspec = wlc->home_chanspec;
-
-	/* Return the user target tx power limits for the various rates.  Note  wlc_phy.c's
-	 * public interface only implements getting and setting a single value for all of
-	 * rates, so we need to fill the array ourselves.
-	 */
-	wlc_phy_txpower_get(wlc->band->pi, &qdbm, &override);
-	for (r = 0; r < WL_TX_POWER_RATES; r++) {
-		power.user_limit[r] = (u8) qdbm;
-	}
-
-	power.local_max = wlc->txpwr_local_max * WLC_TXPWR_DB_FACTOR;
-	power.local_constraint =
-	    wlc->txpwr_local_constraint * WLC_TXPWR_DB_FACTOR;
-
-	power.antgain[0] = wlc->bandstate[BAND_2G_INDEX]->antgain;
-	power.antgain[1] = wlc->bandstate[BAND_5G_INDEX]->antgain;
-
-	wlc_channel_reg_limits(wlc->cmi, power.chanspec, &txpwr);
-
-#if WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK
-#error "WL_TX_POWER_CCK_NUM != WLC_NUM_RATES_CCK"
-#endif
-
-	/* CCK tx power limits */
-	for (c = 0, r = WL_TX_POWER_CCK_FIRST; c < WL_TX_POWER_CCK_NUM;
-	     c++, r++)
-		power.reg_limit[r] = txpwr.cck[c];
-
-#if WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM
-#error "WL_TX_POWER_OFDM_NUM != WLC_NUM_RATES_OFDM"
-#endif
-
-	/* 20 MHz OFDM SISO tx power limits */
-	for (c = 0, r = WL_TX_POWER_OFDM_FIRST; c < WL_TX_POWER_OFDM_NUM;
-	     c++, r++)
-		power.reg_limit[r] = txpwr.ofdm[c];
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-
-		/* 20 MHz OFDM CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_OFDM20_CDD_FIRST;
-		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
-			power.reg_limit[r] = txpwr.ofdm_cdd[c];
-
-		/* 40 MHz OFDM SISO tx power limits */
-		for (c = 0, r = WL_TX_POWER_OFDM40_SISO_FIRST;
-		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
-			power.reg_limit[r] = txpwr.ofdm_40_siso[c];
-
-		/* 40 MHz OFDM CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_OFDM40_CDD_FIRST;
-		     c < WL_TX_POWER_OFDM_NUM; c++, r++)
-			power.reg_limit[r] = txpwr.ofdm_40_cdd[c];
-
-#if WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM
-#error "WL_TX_POWER_MCS_1_STREAM_NUM != WLC_NUM_RATES_MCS_1_STREAM"
-#endif
-
-		/* 20MHz MCS0-7 SISO tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_SISO_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_siso[c];
-
-		/* 20MHz MCS0-7 CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_CDD_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_cdd[c];
-
-		/* 20MHz MCS0-7 STBC tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_STBC_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_stbc[c];
-
-		/* 40MHz MCS0-7 SISO tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_SISO_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_siso[c];
-
-		/* 40MHz MCS0-7 CDD tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_CDD_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_cdd[c];
-
-		/* 40MHz MCS0-7 STBC tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_STBC_FIRST;
-		     c < WLC_NUM_RATES_MCS_1_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_stbc[c];
-
-#if WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM
-#error "WL_TX_POWER_MCS_2_STREAM_NUM != WLC_NUM_RATES_MCS_2_STREAM"
-#endif
-
-		/* 20MHz MCS8-15 SDM tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS20_SDM_FIRST;
-		     c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_20_mimo[c];
-
-		/* 40MHz MCS8-15 SDM tx power limits */
-		for (c = 0, r = WL_TX_POWER_MCS40_SDM_FIRST;
-		     c < WLC_NUM_RATES_MCS_2_STREAM; c++, r++)
-			power.reg_limit[r] = txpwr.mcs_40_mimo[c];
-
-		/* MCS 32 */
-		power.reg_limit[WL_TX_POWER_MCS_32] = txpwr.mcs32;
-	}
-
-	wlc_phy_txpower_get_current(wlc->band->pi, &power,
-				    CHSPEC_CHANNEL(power.chanspec));
-
-	/* copy the tx_power_t struct to the return buffer,
-	 * or convert to a tx_power_legacy_t struct
-	 */
-	if (!old_power) {
-		bcopy(&power, pwr, sizeof(tx_power_t));
-	} else {
-		int band_idx = CHSPEC_IS2G(power.chanspec) ? 0 : 1;
-
-		memset(old_power, 0, sizeof(tx_power_legacy_t));
-
-		old_power->txpwr_local_max = power.local_max;
-		old_power->txpwr_local_constraint = power.local_constraint;
-		if (CHSPEC_IS2G(power.chanspec)) {
-			old_power->txpwr_chan_reg_max = txpwr.cck[0];
-			old_power->txpwr_est_Pout[band_idx] =
-			    power.est_Pout_cck;
-			old_power->txpwr_est_Pout_gofdm = power.est_Pout[0];
-		} else {
-			old_power->txpwr_chan_reg_max = txpwr.ofdm[0];
-			old_power->txpwr_est_Pout[band_idx] = power.est_Pout[0];
-		}
-		old_power->txpwr_antgain[0] = power.antgain[0];
-		old_power->txpwr_antgain[1] = power.antgain[1];
-
-		for (r = 0; r < NUM_PWRCTRL_RATES; r++) {
-			old_power->txpwr_band_max[r] = power.user_limit[r];
-			old_power->txpwr_limit[r] = power.reg_limit[r];
-			old_power->txpwr_target[band_idx][r] = power.target[r];
-			if (CHSPEC_IS2G(power.chanspec))
-				old_power->txpwr_bphy_cck_max[r] =
-				    power.board_limit[r];
-			else
-				old_power->txpwr_aphy_max[r] =
-				    power.board_limit[r];
-		}
-	}
-
-	return 0;
-}
-#endif				/* defined(BCMDBG) */
-
-static u32 wlc_watchdog_backup_bi(struct wlc_info *wlc)
-{
-	u32 bi;
-	bi = 2 * wlc->cfg->current_bss->dtim_period *
-	    wlc->cfg->current_bss->beacon_period;
-	if (wlc->bcn_li_dtim)
-		bi *= wlc->bcn_li_dtim;
-	else if (wlc->bcn_li_bcn)
-		/* recalculate bi based on bcn_li_bcn */
-		bi = 2 * wlc->bcn_li_bcn * wlc->cfg->current_bss->beacon_period;
-
-	if (bi < 2 * TIMER_INTERVAL_WATCHDOG)
-		bi = 2 * TIMER_INTERVAL_WATCHDOG;
-	return bi;
-}
-
-/* Change to run the watchdog either from a periodic timer or from tbtt handler.
- * Call watchdog from tbtt handler if tbtt is true, watchdog timer otherwise.
- */
-void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt)
-{
-	/* make sure changing watchdog driver is allowed */
-	if (!wlc->pub->up || !wlc->pub->align_wd_tbtt)
-		return;
-	if (!tbtt && wlc->WDarmed) {
-		wl_del_timer(wlc->wl, wlc->wdtimer);
-		wlc->WDarmed = false;
-	}
-
-	/* stop watchdog timer and use tbtt interrupt to drive watchdog */
-	if (tbtt && wlc->WDarmed) {
-		wl_del_timer(wlc->wl, wlc->wdtimer);
-		wlc->WDarmed = false;
-		wlc->WDlast = OSL_SYSUPTIME();
-	}
-	/* arm watchdog timer and drive the watchdog there */
-	else if (!tbtt && !wlc->WDarmed) {
-		wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
-			     true);
-		wlc->WDarmed = true;
-	}
-	if (tbtt && !wlc->WDarmed) {
-		wl_add_timer(wlc->wl, wlc->wdtimer, wlc_watchdog_backup_bi(wlc),
-			     true);
-		wlc->WDarmed = true;
-	}
-}
-
-ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc, wlc_rateset_t *rs)
-{
-	ratespec_t lowest_basic_rspec;
-	uint i;
-
-	/* Use the lowest basic rate */
-	lowest_basic_rspec = rs->rates[0] & RATE_MASK;
-	for (i = 0; i < rs->count; i++) {
-		if (rs->rates[i] & WLC_RATE_FLAG) {
-			lowest_basic_rspec = rs->rates[i] & RATE_MASK;
-			break;
-		}
-	}
-#if NCONF
-	/* pick siso/cdd as default for OFDM (note no basic rate MCSs are supported yet) */
-	if (IS_OFDM(lowest_basic_rspec)) {
-		lowest_basic_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
-	}
-#endif
-
-	return lowest_basic_rspec;
-}
-
-/* This function changes the phytxctl for beacon based on current beacon ratespec AND txant
- * setting as per this table:
- *  ratespec     CCK		ant = wlc->stf->txant
- *  		OFDM		ant = 3
- */
-void wlc_beacon_phytxctl_txant_upd(struct wlc_info *wlc, ratespec_t bcn_rspec)
-{
-	u16 phyctl;
-	u16 phytxant = wlc->stf->phytxant;
-	u16 mask = PHY_TXC_ANT_MASK;
-
-	/* for non-siso rates or default setting, use the available chains */
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		phytxant = wlc_stf_phytxchain_sel(wlc, bcn_rspec);
-	}
-
-	phyctl = wlc_read_shm(wlc, M_BCN_PCTLWD);
-	phyctl = (phyctl & ~mask) | phytxant;
-	wlc_write_shm(wlc, M_BCN_PCTLWD, phyctl);
-}
-
-/* centralized protection config change function to simplify debugging, no consistency checking
- * this should be called only on changes to avoid overhead in periodic function
-*/
-void wlc_protection_upd(struct wlc_info *wlc, uint idx, int val)
-{
-	WL_TRACE("wlc_protection_upd: idx %d, val %d\n", idx, val);
-
-	switch (idx) {
-	case WLC_PROT_G_SPEC:
-		wlc->protection->_g = (bool) val;
-		break;
-	case WLC_PROT_G_OVR:
-		wlc->protection->g_override = (s8) val;
-		break;
-	case WLC_PROT_G_USER:
-		wlc->protection->gmode_user = (u8) val;
-		break;
-	case WLC_PROT_OVERLAP:
-		wlc->protection->overlap = (s8) val;
-		break;
-	case WLC_PROT_N_USER:
-		wlc->protection->nmode_user = (s8) val;
-		break;
-	case WLC_PROT_N_CFG:
-		wlc->protection->n_cfg = (s8) val;
-		break;
-	case WLC_PROT_N_CFG_OVR:
-		wlc->protection->n_cfg_override = (s8) val;
-		break;
-	case WLC_PROT_N_NONGF:
-		wlc->protection->nongf = (bool) val;
-		break;
-	case WLC_PROT_N_NONGF_OVR:
-		wlc->protection->nongf_override = (s8) val;
-		break;
-	case WLC_PROT_N_PAM_OVR:
-		wlc->protection->n_pam_override = (s8) val;
-		break;
-	case WLC_PROT_N_OBSS:
-		wlc->protection->n_obss = (bool) val;
-		break;
-
-	default:
-		ASSERT(0);
-		break;
-	}
-
-}
-
-static void wlc_ht_update_sgi_rx(struct wlc_info *wlc, int val)
-{
-	wlc->ht_cap.cap &= ~(HT_CAP_SHORT_GI_20 | HT_CAP_SHORT_GI_40);
-	wlc->ht_cap.cap |= (val & WLC_N_SGI_20) ? HT_CAP_SHORT_GI_20 : 0;
-	wlc->ht_cap.cap |= (val & WLC_N_SGI_40) ? HT_CAP_SHORT_GI_40 : 0;
-
-	if (wlc->pub->up) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-	}
-}
-
-static void wlc_ht_update_ldpc(struct wlc_info *wlc, s8 val)
-{
-	wlc->stf->ldpc = val;
-
-	wlc->ht_cap.cap &= ~HT_CAP_LDPC_CODING;
-	if (wlc->stf->ldpc != OFF)
-		wlc->ht_cap.cap |= HT_CAP_LDPC_CODING;
-
-	if (wlc->pub->up) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-		wlc_phy_ldpc_override_set(wlc->band->pi, (val ? true : false));
-	}
-}
-
-/*
- * ucode, hwmac update
- *    Channel dependent updates for ucode and hw
- */
-static void wlc_ucode_mac_upd(struct wlc_info *wlc)
-{
-	/* enable or disable any active IBSSs depending on whether or not
-	 * we are on the home channel
-	 */
-	if (wlc->home_chanspec == WLC_BAND_PI_RADIO_CHANSPEC) {
-		if (wlc->pub->associated) {
-			/* BMAC_NOTE: This is something that should be fixed in ucode inits.
-			 * I think that the ucode inits set up the bcn templates and shm values
-			 * with a bogus beacon. This should not be done in the inits. If ucode needs
-			 * to set up a beacon for testing, the test routines should write it down,
-			 * not expect the inits to populate a bogus beacon.
-			 */
-			if (WLC_PHY_11N_CAP(wlc->band)) {
-				wlc_write_shm(wlc, M_BCN_TXTSF_OFFSET,
-					      wlc->band->bcntsfoff);
-			}
-		}
-	} else {
-		/* disable an active IBSS if we are not on the home channel */
-	}
-
-	/* update the various promisc bits */
-	wlc_mac_bcn_promisc(wlc);
-	wlc_mac_promisc(wlc);
-}
-
-static void wlc_bandinit_ordered(struct wlc_info *wlc, chanspec_t chanspec)
-{
-	wlc_rateset_t default_rateset;
-	uint parkband;
-	uint i, band_order[2];
-
-	WL_TRACE("wl%d: wlc_bandinit_ordered\n", wlc->pub->unit);
-	/*
-	 * We might have been bandlocked during down and the chip power-cycled (hibernate).
-	 * figure out the right band to park on
-	 */
-	if (wlc->bandlocked || NBANDS(wlc) == 1) {
-		ASSERT(CHSPEC_WLCBANDUNIT(chanspec) == wlc->band->bandunit);
-
-		parkband = wlc->band->bandunit;	/* updated in wlc_bandlock() */
-		band_order[0] = band_order[1] = parkband;
-	} else {
-		/* park on the band of the specified chanspec */
-		parkband = CHSPEC_WLCBANDUNIT(chanspec);
-
-		/* order so that parkband initialize last */
-		band_order[0] = parkband ^ 1;
-		band_order[1] = parkband;
-	}
-
-	/* make each band operational, software state init */
-	for (i = 0; i < NBANDS(wlc); i++) {
-		uint j = band_order[i];
-
-		wlc->band = wlc->bandstate[j];
-
-		wlc_default_rateset(wlc, &default_rateset);
-
-		/* fill in hw_rate */
-		wlc_rateset_filter(&default_rateset, &wlc->band->hw_rateset,
-				   false, WLC_RATES_CCK_OFDM, RATE_MASK,
-				   (bool) N_ENAB(wlc->pub));
-
-		/* init basic rate lookup */
-		wlc_rate_lookup_init(wlc, &default_rateset);
-	}
-
-	/* sync up phy/radio chanspec */
-	wlc_set_phy_chanspec(wlc, chanspec);
-}
-
-/* band-specific init */
-static void WLBANDINITFN(wlc_bsinit) (struct wlc_info *wlc)
-{
-	WL_TRACE("wl%d: wlc_bsinit: bandunit %d\n",
-		 wlc->pub->unit, wlc->band->bandunit);
-
-	/* write ucode ACK/CTS rate table */
-	wlc_set_ratetable(wlc);
-
-	/* update some band specific mac configuration */
-	wlc_ucode_mac_upd(wlc);
-
-	/* init antenna selection */
-	if (WLANTSEL_ENAB(wlc))
-		wlc_antsel_init(wlc->asi);
-
-}
-
-/* switch to and initialize new band */
-static void WLBANDINITFN(wlc_setband) (struct wlc_info *wlc, uint bandunit)
-{
-	int idx;
-	wlc_bsscfg_t *cfg;
-
-	ASSERT(NBANDS(wlc) > 1);
-	ASSERT(!wlc->bandlocked);
-	ASSERT(bandunit != wlc->band->bandunit || wlc->bandinit_pending);
-
-	wlc->band = wlc->bandstate[bandunit];
-
-	if (!wlc->pub->up)
-		return;
-
-	/* wait for at least one beacon before entering sleeping state */
-	wlc->PMawakebcn = true;
-	FOREACH_AS_STA(wlc, idx, cfg)
-	    cfg->PMawakebcn = true;
-	wlc_set_ps_ctrl(wlc);
-
-	/* band-specific initializations */
-	wlc_bsinit(wlc);
-}
-
-/* Initialize a WME Parameter Info Element with default STA parameters from WMM Spec, Table 12 */
-void wlc_wme_initparams_sta(struct wlc_info *wlc, wme_param_ie_t *pe)
-{
-	static const wme_param_ie_t stadef = {
-		WME_OUI,
-		WME_TYPE,
-		WME_SUBTYPE_PARAM_IE,
-		WME_VER,
-		0,
-		0,
-		{
-		 {EDCF_AC_BE_ACI_STA, EDCF_AC_BE_ECW_STA,
-		  HTOL16(EDCF_AC_BE_TXOP_STA)},
-		 {EDCF_AC_BK_ACI_STA, EDCF_AC_BK_ECW_STA,
-		  HTOL16(EDCF_AC_BK_TXOP_STA)},
-		 {EDCF_AC_VI_ACI_STA, EDCF_AC_VI_ECW_STA,
-		  HTOL16(EDCF_AC_VI_TXOP_STA)},
-		 {EDCF_AC_VO_ACI_STA, EDCF_AC_VO_ECW_STA,
-		  HTOL16(EDCF_AC_VO_TXOP_STA)}
-		 }
-	};
-
-	ASSERT(sizeof(*pe) == WME_PARAM_IE_LEN);
-	memcpy(pe, &stadef, sizeof(*pe));
-}
-
-void wlc_wme_setparams(struct wlc_info *wlc, u16 aci, void *arg, bool suspend)
-{
-	int i;
-	shm_acparams_t acp_shm;
-	u16 *shm_entry;
-	struct ieee80211_tx_queue_params *params = arg;
-
-	ASSERT(wlc);
-
-	/* Only apply params if the core is out of reset and has clocks */
-	if (!wlc->clk) {
-		WL_ERROR("wl%d: %s : no-clock\n", wlc->pub->unit, __func__);
-		return;
-	}
-
-	/*
-	 * AP uses AC params from wme_param_ie_ap.
-	 * AP advertises AC params from wme_param_ie.
-	 * STA uses AC params from wme_param_ie.
-	 */
-
-	wlc->wme_admctl = 0;
-
-	do {
-		memset((char *)&acp_shm, 0, sizeof(shm_acparams_t));
-		/* find out which ac this set of params applies to */
-		ASSERT(aci < AC_COUNT);
-		/* set the admission control policy for this AC */
-		/* wlc->wme_admctl |= 1 << aci; *//* should be set ??  seems like off by default */
-
-		/* fill in shm ac params struct */
-		acp_shm.txop = ltoh16(params->txop);
-		/* convert from units of 32us to us for ucode */
-		wlc->edcf_txop[aci & 0x3] = acp_shm.txop =
-		    EDCF_TXOP2USEC(acp_shm.txop);
-		acp_shm.aifs = (params->aifs & EDCF_AIFSN_MASK);
-
-		if (aci == AC_VI && acp_shm.txop == 0
-		    && acp_shm.aifs < EDCF_AIFSN_MAX)
-			acp_shm.aifs++;
-
-		if (acp_shm.aifs < EDCF_AIFSN_MIN
-		    || acp_shm.aifs > EDCF_AIFSN_MAX) {
-			WL_ERROR("wl%d: wlc_edcf_setparams: bad aifs %d\n",
-				 wlc->pub->unit, acp_shm.aifs);
-			continue;
-		}
-
-		acp_shm.cwmin = params->cw_min;
-		acp_shm.cwmax = params->cw_max;
-		acp_shm.cwcur = acp_shm.cwmin;
-		acp_shm.bslots =
-		    R_REG(wlc->osh, &wlc->regs->tsf_random) & acp_shm.cwcur;
-		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
-		/* Indicate the new params to the ucode */
-		acp_shm.status = wlc_read_shm(wlc, (M_EDCF_QINFO +
-						    wme_shmemacindex(aci) *
-						    M_EDCF_QLEN +
-						    M_EDCF_STATUS_OFF));
-		acp_shm.status |= WME_STATUS_NEWAC;
-
-		/* Fill in shm acparam table */
-		shm_entry = (u16 *) &acp_shm;
-		for (i = 0; i < (int)sizeof(shm_acparams_t); i += 2)
-			wlc_write_shm(wlc,
-				      M_EDCF_QINFO +
-				      wme_shmemacindex(aci) * M_EDCF_QLEN + i,
-				      *shm_entry++);
-
-	} while (0);
-
-	if (suspend)
-		wlc_suspend_mac_and_wait(wlc);
-
-	if (suspend)
-		wlc_enable_mac(wlc);
-
-}
-
-void wlc_edcf_setparams(wlc_bsscfg_t *cfg, bool suspend)
-{
-	struct wlc_info *wlc = cfg->wlc;
-	uint aci, i, j;
-	edcf_acparam_t *edcf_acp;
-	shm_acparams_t acp_shm;
-	u16 *shm_entry;
-
-	ASSERT(cfg);
-	ASSERT(wlc);
-
-	/* Only apply params if the core is out of reset and has clocks */
-	if (!wlc->clk)
-		return;
-
-	/*
-	 * AP uses AC params from wme_param_ie_ap.
-	 * AP advertises AC params from wme_param_ie.
-	 * STA uses AC params from wme_param_ie.
-	 */
-
-	edcf_acp = (edcf_acparam_t *) &wlc->wme_param_ie.acparam[0];
-
-	wlc->wme_admctl = 0;
-
-	for (i = 0; i < AC_COUNT; i++, edcf_acp++) {
-		memset((char *)&acp_shm, 0, sizeof(shm_acparams_t));
-		/* find out which ac this set of params applies to */
-		aci = (edcf_acp->ACI & EDCF_ACI_MASK) >> EDCF_ACI_SHIFT;
-		ASSERT(aci < AC_COUNT);
-		/* set the admission control policy for this AC */
-		if (edcf_acp->ACI & EDCF_ACM_MASK) {
-			wlc->wme_admctl |= 1 << aci;
-		}
-
-		/* fill in shm ac params struct */
-		acp_shm.txop = ltoh16(edcf_acp->TXOP);
-		/* convert from units of 32us to us for ucode */
-		wlc->edcf_txop[aci] = acp_shm.txop =
-		    EDCF_TXOP2USEC(acp_shm.txop);
-		acp_shm.aifs = (edcf_acp->ACI & EDCF_AIFSN_MASK);
-
-		if (aci == AC_VI && acp_shm.txop == 0
-		    && acp_shm.aifs < EDCF_AIFSN_MAX)
-			acp_shm.aifs++;
-
-		if (acp_shm.aifs < EDCF_AIFSN_MIN
-		    || acp_shm.aifs > EDCF_AIFSN_MAX) {
-			WL_ERROR("wl%d: wlc_edcf_setparams: bad aifs %d\n",
-				 wlc->pub->unit, acp_shm.aifs);
-			continue;
-		}
-
-		/* CWmin = 2^(ECWmin) - 1 */
-		acp_shm.cwmin = EDCF_ECW2CW(edcf_acp->ECW & EDCF_ECWMIN_MASK);
-		/* CWmax = 2^(ECWmax) - 1 */
-		acp_shm.cwmax = EDCF_ECW2CW((edcf_acp->ECW & EDCF_ECWMAX_MASK)
-					    >> EDCF_ECWMAX_SHIFT);
-		acp_shm.cwcur = acp_shm.cwmin;
-		acp_shm.bslots =
-		    R_REG(wlc->osh, &wlc->regs->tsf_random) & acp_shm.cwcur;
-		acp_shm.reggap = acp_shm.bslots + acp_shm.aifs;
-		/* Indicate the new params to the ucode */
-		acp_shm.status = wlc_read_shm(wlc, (M_EDCF_QINFO +
-						    wme_shmemacindex(aci) *
-						    M_EDCF_QLEN +
-						    M_EDCF_STATUS_OFF));
-		acp_shm.status |= WME_STATUS_NEWAC;
-
-		/* Fill in shm acparam table */
-		shm_entry = (u16 *) &acp_shm;
-		for (j = 0; j < (int)sizeof(shm_acparams_t); j += 2)
-			wlc_write_shm(wlc,
-				      M_EDCF_QINFO +
-				      wme_shmemacindex(aci) * M_EDCF_QLEN + j,
-				      *shm_entry++);
-	}
-
-	if (suspend)
-		wlc_suspend_mac_and_wait(wlc);
-
-	if (AP_ENAB(wlc->pub) && WME_ENAB(wlc->pub)) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, false);
-	}
-
-	if (suspend)
-		wlc_enable_mac(wlc);
-
-}
-
-bool wlc_timers_init(struct wlc_info *wlc, int unit)
-{
-	wlc->wdtimer = wl_init_timer(wlc->wl, wlc_watchdog_by_timer,
-		wlc, "watchdog");
-	if (!wlc->wdtimer) {
-		WL_ERROR("wl%d:  wl_init_timer for wdtimer failed\n", unit);
-		goto fail;
-	}
-
-	wlc->radio_timer = wl_init_timer(wlc->wl, wlc_radio_timer,
-		wlc, "radio");
-	if (!wlc->radio_timer) {
-		WL_ERROR("wl%d:  wl_init_timer for radio_timer failed\n", unit);
-		goto fail;
-	}
-
-	return true;
-
- fail:
-	return false;
-}
-
-/*
- * Initialize wlc_info default values ...
- * may get overrides later in this function
- */
-void wlc_info_init(struct wlc_info *wlc, int unit)
-{
-	int i;
-	/* Assume the device is there until proven otherwise */
-	wlc->device_present = true;
-
-	/* set default power output percentage to 100 percent */
-	wlc->txpwr_percent = 100;
-
-	/* Save our copy of the chanspec */
-	wlc->chanspec = CH20MHZ_CHSPEC(1);
-
-	/* initialize CCK preamble mode to unassociated state */
-	wlc->shortpreamble = false;
-
-	wlc->legacy_probe = true;
-
-	/* various 802.11g modes */
-	wlc->shortslot = false;
-	wlc->shortslot_override = WLC_SHORTSLOT_AUTO;
-
-	wlc->barker_overlap_control = true;
-	wlc->barker_preamble = WLC_BARKER_SHORT_ALLOWED;
-	wlc->txburst_limit_override = AUTO;
-
-	wlc_protection_upd(wlc, WLC_PROT_G_OVR, WLC_PROTECTION_AUTO);
-	wlc_protection_upd(wlc, WLC_PROT_G_SPEC, false);
-
-	wlc_protection_upd(wlc, WLC_PROT_N_CFG_OVR, WLC_PROTECTION_AUTO);
-	wlc_protection_upd(wlc, WLC_PROT_N_CFG, WLC_N_PROTECTION_OFF);
-	wlc_protection_upd(wlc, WLC_PROT_N_NONGF_OVR, WLC_PROTECTION_AUTO);
-	wlc_protection_upd(wlc, WLC_PROT_N_NONGF, false);
-	wlc_protection_upd(wlc, WLC_PROT_N_PAM_OVR, AUTO);
-
-	wlc_protection_upd(wlc, WLC_PROT_OVERLAP, WLC_PROTECTION_CTL_OVERLAP);
-
-	/* 802.11g draft 4.0 NonERP elt advertisement */
-	wlc->include_legacy_erp = true;
-
-	wlc->stf->ant_rx_ovr = ANT_RX_DIV_DEF;
-	wlc->stf->txant = ANT_TX_DEF;
-
-	wlc->prb_resp_timeout = WLC_PRB_RESP_TIMEOUT;
-
-	wlc->usr_fragthresh = DOT11_DEFAULT_FRAG_LEN;
-	for (i = 0; i < NFIFO; i++)
-		wlc->fragthresh[i] = DOT11_DEFAULT_FRAG_LEN;
-	wlc->RTSThresh = DOT11_DEFAULT_RTS_LEN;
-
-	/* default rate fallback retry limits */
-	wlc->SFBL = RETRY_SHORT_FB;
-	wlc->LFBL = RETRY_LONG_FB;
-
-	/* default mac retry limits */
-	wlc->SRL = RETRY_SHORT_DEF;
-	wlc->LRL = RETRY_LONG_DEF;
-
-	/* init PM state */
-	wlc->PM = PM_OFF;	/* User's setting of PM mode through IOCTL */
-	wlc->PM_override = false;	/* Prevents from going to PM if our AP is 'ill' */
-	wlc->PMenabled = false;	/* Current PM state */
-	wlc->PMpending = false;	/* Tracks whether STA indicated PM in the last attempt */
-	wlc->PMblocked = false;	/* To allow blocking going into PM during RM and scans */
-
-	/* In WMM Auto mode, PM is allowed if association is a UAPSD association */
-	wlc->WME_PM_blocked = false;
-
-	/* Init wme queuing method */
-	wlc->wme_prec_queuing = false;
-
-	/* Overrides for the core to stay awake under zillion conditions Look for STAY_AWAKE */
-	wlc->wake = false;
-	/* Are we waiting for a response to PS-Poll that we sent */
-	wlc->PSpoll = false;
-
-	/* APSD defaults */
-	wlc->wme_apsd = true;
-	wlc->apsd_sta_usp = false;
-	wlc->apsd_trigger_timeout = 0;	/* disable the trigger timer */
-	wlc->apsd_trigger_ac = AC_BITMAP_ALL;
-
-	/* Set flag to indicate that hw keys should be used when available. */
-	wlc->wsec_swkeys = false;
-
-	/* init the 4 static WEP default keys */
-	for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
-		wlc->wsec_keys[i] = wlc->wsec_def_keys[i];
-		wlc->wsec_keys[i]->idx = (u8) i;
-	}
-
-	wlc->_regulatory_domain = false;	/* 802.11d */
-
-	/* WME QoS mode is Auto by default */
-	wlc->pub->_wme = AUTO;
-
-#ifdef BCMSDIODEV_ENABLED
-	wlc->pub->_priofc = true;	/* enable priority flow control for sdio dongle */
-#endif
-
-	wlc->pub->_ampdu = AMPDU_AGG_HOST;
-	wlc->pub->bcmerror = 0;
-	wlc->ibss_allowed = true;
-	wlc->ibss_coalesce_allowed = true;
-	wlc->pub->_coex = ON;
-
-	/* intialize mpc delay */
-	wlc->mpc_delay_off = wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
-
-	wlc->pr80838_war = true;
-}
-
-static bool wlc_state_bmac_sync(struct wlc_info *wlc)
-{
-	wlc_bmac_state_t state_bmac;
-
-	if (wlc_bmac_state_get(wlc->hw, &state_bmac) != 0)
-		return false;
-
-	wlc->machwcap = state_bmac.machwcap;
-	wlc_protection_upd(wlc, WLC_PROT_N_PAM_OVR,
-			   (s8) state_bmac.preamble_ovr);
-
-	return true;
-}
-
-static uint wlc_attach_module(struct wlc_info *wlc)
-{
-	uint err = 0;
-	uint unit;
-	unit = wlc->pub->unit;
-
-	wlc->asi = wlc_antsel_attach(wlc, wlc->osh, wlc->pub, wlc->hw);
-	if (wlc->asi == NULL) {
-		WL_ERROR("wl%d: wlc_attach: wlc_antsel_attach failed\n", unit);
-		err = 44;
-		goto fail;
-	}
-
-	wlc->ampdu = wlc_ampdu_attach(wlc);
-	if (wlc->ampdu == NULL) {
-		WL_ERROR("wl%d: wlc_attach: wlc_ampdu_attach failed\n", unit);
-		err = 50;
-		goto fail;
-	}
-
-	/* Initialize event queue; needed before following calls */
-	wlc->eventq =
-	    wlc_eventq_attach(wlc->pub, wlc, wlc->wl, wlc_process_eventq);
-	if (wlc->eventq == NULL) {
-		WL_ERROR("wl%d: wlc_attach: wlc_eventq_attachfailed\n", unit);
-		err = 57;
-		goto fail;
-	}
-
-	if ((wlc_stf_attach(wlc) != 0)) {
-		WL_ERROR("wl%d: wlc_attach: wlc_stf_attach failed\n", unit);
-		err = 68;
-		goto fail;
-	}
- fail:
-	return err;
-}
-
-struct wlc_pub *wlc_pub(void *wlc)
-{
-	return ((struct wlc_info *) wlc)->pub;
-}
-
-#define CHIP_SUPPORTS_11N(wlc) 	1
-
-/*
- * The common driver entry routine. Error codes should be unique
- */
-void *wlc_attach(void *wl, u16 vendor, u16 device, uint unit, bool piomode,
-		 struct osl_info *osh, void *regsva, uint bustype,
-		 void *btparam, uint *perr)
-{
-	struct wlc_info *wlc;
-	uint err = 0;
-	uint j;
-	struct wlc_pub *pub;
-	wlc_txq_info_t *qi;
-	uint n_disabled;
-
-	WL_NONE("wl%d: %s: vendor 0x%x device 0x%x\n",
-		unit, __func__, vendor, device);
-
-	ASSERT(WSEC_MAX_RCMTA_KEYS <= WSEC_MAX_KEYS);
-	ASSERT(WSEC_MAX_DEFAULT_KEYS == WLC_DEFAULT_KEYS);
-
-	/* some code depends on packed structures */
-	ASSERT(sizeof(struct ether_addr) == ETH_ALEN);
-	ASSERT(sizeof(struct ether_header) == ETH_HLEN);
-	ASSERT(sizeof(d11regs_t) == SI_CORE_SIZE);
-	ASSERT(sizeof(ofdm_phy_hdr_t) == D11_PHY_HDR_LEN);
-	ASSERT(sizeof(cck_phy_hdr_t) == D11_PHY_HDR_LEN);
-	ASSERT(sizeof(d11txh_t) == D11_TXH_LEN);
-	ASSERT(sizeof(d11rxhdr_t) == RXHDR_LEN);
-	ASSERT(sizeof(struct dot11_header) == DOT11_A4_HDR_LEN);
-	ASSERT(sizeof(struct dot11_rts_frame) == DOT11_RTS_LEN);
-	ASSERT(sizeof(struct dot11_management_header) == DOT11_MGMT_HDR_LEN);
-	ASSERT(sizeof(struct dot11_bcn_prb) == DOT11_BCN_PRB_LEN);
-	ASSERT(sizeof(tx_status_t) == TXSTATUS_LEN);
-	ASSERT(sizeof(ht_cap_ie_t) == HT_CAP_IE_LEN);
-#ifdef BRCM_FULLMAC
-	ASSERT(offsetof(wl_scan_params_t, channel_list) ==
-	       WL_SCAN_PARAMS_FIXED_SIZE);
-#endif
-	ASSERT(IS_ALIGNED(offsetof(wsec_key_t, data), sizeof(u32)));
-	ASSERT(ISPOWEROF2(MA_WINDOW_SZ));
-
-	ASSERT(sizeof(wlc_d11rxhdr_t) <= WL_HWRXOFF);
-
-	/*
-	 * Number of replay counters value used in WPA IE must match # rxivs
-	 * supported in wsec_key_t struct. See 802.11i/D3.0 sect. 7.3.2.17
-	 * 'RSN Information Element' figure 8 for this mapping.
-	 */
-	ASSERT((WPA_CAP_16_REPLAY_CNTRS == WLC_REPLAY_CNTRS_VALUE
-		&& 16 == WLC_NUMRXIVS)
-	       || (WPA_CAP_4_REPLAY_CNTRS == WLC_REPLAY_CNTRS_VALUE
-		   && 4 == WLC_NUMRXIVS));
-
-	/* allocate struct wlc_info state and its substructures */
-	wlc = (struct wlc_info *) wlc_attach_malloc(osh, unit, &err, device);
-	if (wlc == NULL)
-		goto fail;
-	wlc->osh = osh;
-	pub = wlc->pub;
-
-#if defined(BCMDBG)
-	wlc_info_dbg = wlc;
-#endif
-
-	wlc->band = wlc->bandstate[0];
-	wlc->core = wlc->corestate;
-	wlc->wl = wl;
-	pub->unit = unit;
-	pub->osh = osh;
-	wlc->btparam = btparam;
-	pub->_piomode = piomode;
-	wlc->bandinit_pending = false;
-	/* By default restrict TKIP associations from 11n STA's */
-	wlc->ht_wsec_restriction = WLC_HT_TKIP_RESTRICT;
-
-	/* populate struct wlc_info with default values  */
-	wlc_info_init(wlc, unit);
-
-	/* update sta/ap related parameters */
-	wlc_ap_upd(wlc);
-
-	/* 11n_disable nvram */
-	n_disabled = getintvar(pub->vars, "11n_disable");
-
-	/* register a module (to handle iovars) */
-	wlc_module_register(wlc->pub, wlc_iovars, "wlc_iovars", wlc,
-			    wlc_doiovar, NULL, NULL);
-
-	/* low level attach steps(all hw accesses go inside, no more in rest of the attach) */
-	err = wlc_bmac_attach(wlc, vendor, device, unit, piomode, osh, regsva,
-			      bustype, btparam);
-	if (err)
-		goto fail;
-
-	/* for some states, due to different info pointer(e,g, wlc, wlc_hw) or master/slave split,
-	 * HIGH driver(both monolithic and HIGH_ONLY) needs to sync states FROM BMAC portion driver
-	 */
-	if (!wlc_state_bmac_sync(wlc)) {
-		err = 20;
-		goto fail;
-	}
-
-	pub->phy_11ncapable = WLC_PHY_11N_CAP(wlc->band);
-
-	/* propagate *vars* from BMAC driver to high driver */
-	wlc_bmac_copyfrom_vars(wlc->hw, &pub->vars, &wlc->vars_size);
-
-
-	/* set maximum allowed duty cycle */
-	wlc->tx_duty_cycle_ofdm =
-	    (u16) getintvar(pub->vars, "tx_duty_cycle_ofdm");
-	wlc->tx_duty_cycle_cck =
-	    (u16) getintvar(pub->vars, "tx_duty_cycle_cck");
-
-	wlc_stf_phy_chain_calc(wlc);
-
-	/* txchain 1: txant 0, txchain 2: txant 1 */
-	if (WLCISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
-		wlc->stf->txant = wlc->stf->hw_txchain - 1;
-
-	/* push to BMAC driver */
-	wlc_phy_stf_chain_init(wlc->band->pi, wlc->stf->hw_txchain,
-			       wlc->stf->hw_rxchain);
-
-	/* pull up some info resulting from the low attach */
-	{
-		int i;
-		for (i = 0; i < NFIFO; i++)
-			wlc->core->txavail[i] = wlc->hw->txavail[i];
-	}
-
-	wlc_bmac_hw_etheraddr(wlc->hw, &wlc->perm_etheraddr);
-
-	bcopy((char *)&wlc->perm_etheraddr, (char *)&pub->cur_etheraddr,
-	      ETH_ALEN);
-
-	for (j = 0; j < NBANDS(wlc); j++) {
-		/* Use band 1 for single band 11a */
-		if (IS_SINGLEBAND_5G(wlc->deviceid))
-			j = BAND_5G_INDEX;
-
-		wlc->band = wlc->bandstate[j];
-
-		if (!wlc_attach_stf_ant_init(wlc)) {
-			err = 24;
-			goto fail;
-		}
-
-		/* default contention windows size limits */
-		wlc->band->CWmin = APHY_CWMIN;
-		wlc->band->CWmax = PHY_CWMAX;
-
-		/* init gmode value */
-		if (BAND_2G(wlc->band->bandtype)) {
-			wlc->band->gmode = GMODE_AUTO;
-			wlc_protection_upd(wlc, WLC_PROT_G_USER,
-					   wlc->band->gmode);
-		}
-
-		/* init _n_enab supported mode */
-		if (WLC_PHY_11N_CAP(wlc->band) && CHIP_SUPPORTS_11N(wlc)) {
-			if (n_disabled & WLFEATURE_DISABLE_11N) {
-				pub->_n_enab = OFF;
-				wlc_protection_upd(wlc, WLC_PROT_N_USER, OFF);
-			} else {
-				pub->_n_enab = SUPPORT_11N;
-				wlc_protection_upd(wlc, WLC_PROT_N_USER,
-						   ((pub->_n_enab ==
-						     SUPPORT_11N) ? WL_11N_2x2 :
-						    WL_11N_3x3));
-			}
-		}
-
-		/* init per-band default rateset, depend on band->gmode */
-		wlc_default_rateset(wlc, &wlc->band->defrateset);
-
-		/* fill in hw_rateset (used early by WLC_SET_RATESET) */
-		wlc_rateset_filter(&wlc->band->defrateset,
-				   &wlc->band->hw_rateset, false,
-				   WLC_RATES_CCK_OFDM, RATE_MASK,
-				   (bool) N_ENAB(wlc->pub));
-	}
-
-	/* update antenna config due to wlc->stf->txant/txchain/ant_rx_ovr change */
-	wlc_stf_phy_txant_upd(wlc);
-
-	/* attach each modules */
-	err = wlc_attach_module(wlc);
-	if (err != 0)
-		goto fail;
-
-	if (!wlc_timers_init(wlc, unit)) {
-		WL_ERROR("wl%d: %s: wlc_init_timer failed\n", unit, __func__);
-		err = 32;
-		goto fail;
-	}
-
-	/* depend on rateset, gmode */
-	wlc->cmi = wlc_channel_mgr_attach(wlc);
-	if (!wlc->cmi) {
-		WL_ERROR("wl%d: %s: wlc_channel_mgr_attach failed\n",
-			 unit, __func__);
-		err = 33;
-		goto fail;
-	}
-
-	/* init default when all parameters are ready, i.e. ->rateset */
-	wlc_bss_default_init(wlc);
-
-	/*
-	 * Complete the wlc default state initializations..
-	 */
-
-	/* allocate our initial queue */
-	qi = wlc_txq_alloc(wlc, osh);
-	if (qi == NULL) {
-		WL_ERROR("wl%d: %s: failed to malloc tx queue\n",
-			 unit, __func__);
-		err = 100;
-		goto fail;
-	}
-	wlc->active_queue = qi;
-
-	wlc->bsscfg[0] = wlc->cfg;
-	wlc->cfg->_idx = 0;
-	wlc->cfg->wlc = wlc;
-	pub->txmaxpkts = MAXTXPKTS;
-
-	WLCNTSET(pub->_cnt->version, WL_CNT_T_VERSION);
-	WLCNTSET(pub->_cnt->length, sizeof(wl_cnt_t));
-
-	WLCNTSET(pub->_wme_cnt->version, WL_WME_CNT_VERSION);
-	WLCNTSET(pub->_wme_cnt->length, sizeof(wl_wme_cnt_t));
-
-	wlc_wme_initparams_sta(wlc, &wlc->wme_param_ie);
-
-	wlc->mimoft = FT_HT;
-	wlc->ht_cap.cap = HT_CAP;
-	if (HT_ENAB(wlc->pub))
-		wlc->stf->ldpc = AUTO;
-
-	wlc->mimo_40txbw = AUTO;
-	wlc->ofdm_40txbw = AUTO;
-	wlc->cck_40txbw = AUTO;
-	wlc_update_mimo_band_bwcap(wlc, WLC_N_BW_20IN2G_40IN5G);
-
-	/* Enable setting the RIFS Mode bit by default in HT Info IE */
-	wlc->rifs_advert = AUTO;
-
-	/* Set default values of SGI */
-	if (WLC_SGI_CAP_PHY(wlc)) {
-		wlc_ht_update_sgi_rx(wlc, (WLC_N_SGI_20 | WLC_N_SGI_40));
-		wlc->sgi_tx = AUTO;
-	} else if (WLCISSSLPNPHY(wlc->band)) {
-		wlc_ht_update_sgi_rx(wlc, (WLC_N_SGI_20 | WLC_N_SGI_40));
-		wlc->sgi_tx = AUTO;
-	} else {
-		wlc_ht_update_sgi_rx(wlc, 0);
-		wlc->sgi_tx = OFF;
-	}
-
-	/* *******nvram 11n config overrides Start ********* */
-
-	/* apply the sgi override from nvram conf */
-	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_TX)
-		wlc->sgi_tx = OFF;
-
-	if (n_disabled & WLFEATURE_DISABLE_11N_SGI_RX)
-		wlc_ht_update_sgi_rx(wlc, 0);
-
-	/* apply the stbc override from nvram conf */
-	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_TX) {
-		wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
-		wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
-		wlc->ht_cap.cap &= ~HT_CAP_TX_STBC;
-	}
-	if (n_disabled & WLFEATURE_DISABLE_11N_STBC_RX)
-		wlc_stf_stbc_rx_set(wlc, HT_CAP_RX_STBC_NO);
-
-	/* apply the GF override from nvram conf */
-	if (n_disabled & WLFEATURE_DISABLE_11N_GF)
-		wlc->ht_cap.cap &= ~HT_CAP_GF;
-
-	/* initialize radio_mpc_disable according to wlc->mpc */
-	wlc_radio_mpc_upd(wlc);
-
-	if (WLANTSEL_ENAB(wlc)) {
-		if ((wlc->pub->sih->chip) == BCM43235_CHIP_ID) {
-			if ((getintvar(wlc->pub->vars, "aa2g") == 7) ||
-			    (getintvar(wlc->pub->vars, "aa5g") == 7)) {
-				wlc_bmac_antsel_set(wlc->hw, 1);
-			}
-		} else {
-			wlc_bmac_antsel_set(wlc->hw, wlc->asi->antsel_avail);
-		}
-	}
-
-	if (perr)
-		*perr = 0;
-
-	return (void *)wlc;
-
- fail:
-	WL_ERROR("wl%d: %s: failed with err %d\n", unit, __func__, err);
-	if (wlc)
-		wlc_detach(wlc);
-
-	if (perr)
-		*perr = err;
-	return NULL;
-}
-
-static void wlc_attach_antgain_init(struct wlc_info *wlc)
-{
-	uint unit;
-	unit = wlc->pub->unit;
-
-	if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
-		/* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
-		wlc->band->antgain = 8;
-	} else if (wlc->band->antgain == -1) {
-		WL_ERROR("wl%d: %s: Invalid antennas available in srom, using 2dB\n",
-			 unit, __func__);
-		wlc->band->antgain = 8;
-	} else {
-		s8 gain, fract;
-		/* Older sroms specified gain in whole dbm only.  In order
-		 * be able to specify qdbm granularity and remain backward compatible
-		 * the whole dbms are now encoded in only low 6 bits and remaining qdbms
-		 * are encoded in the hi 2 bits. 6 bit signed number ranges from
-		 * -32 - 31. Examples: 0x1 = 1 db,
-		 * 0xc1 = 1.75 db (1 + 3 quarters),
-		 * 0x3f = -1 (-1 + 0 quarters),
-		 * 0x7f = -.75 (-1 in low 6 bits + 1 quarters in hi 2 bits) = -3 qdbm.
-		 * 0xbf = -.50 (-1 in low 6 bits + 2 quarters in hi 2 bits) = -2 qdbm.
-		 */
-		gain = wlc->band->antgain & 0x3f;
-		gain <<= 2;	/* Sign extend */
-		gain >>= 2;
-		fract = (wlc->band->antgain & 0xc0) >> 6;
-		wlc->band->antgain = 4 * gain + fract;
-	}
-}
-
-static bool wlc_attach_stf_ant_init(struct wlc_info *wlc)
-{
-	int aa;
-	uint unit;
-	char *vars;
-	int bandtype;
-
-	unit = wlc->pub->unit;
-	vars = wlc->pub->vars;
-	bandtype = wlc->band->bandtype;
-
-	/* get antennas available */
-	aa = (s8) getintvar(vars, (BAND_5G(bandtype) ? "aa5g" : "aa2g"));
-	if (aa == 0)
-		aa = (s8) getintvar(vars,
-				      (BAND_5G(bandtype) ? "aa1" : "aa0"));
-	if ((aa < 1) || (aa > 15)) {
-		WL_ERROR("wl%d: %s: Invalid antennas available in srom (0x%x), using 3\n",
-			 unit, __func__, aa);
-		aa = 3;
-	}
-
-	/* reset the defaults if we have a single antenna */
-	if (aa == 1) {
-		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_0;
-		wlc->stf->txant = ANT_TX_FORCE_0;
-	} else if (aa == 2) {
-		wlc->stf->ant_rx_ovr = ANT_RX_DIV_FORCE_1;
-		wlc->stf->txant = ANT_TX_FORCE_1;
-	} else {
-	}
-
-	/* Compute Antenna Gain */
-	wlc->band->antgain =
-	    (s8) getintvar(vars, (BAND_5G(bandtype) ? "ag1" : "ag0"));
-	wlc_attach_antgain_init(wlc);
-
-	return true;
-}
-
-
-static void wlc_timers_deinit(struct wlc_info *wlc)
-{
-	/* free timer state */
-	if (wlc->wdtimer) {
-		wl_free_timer(wlc->wl, wlc->wdtimer);
-		wlc->wdtimer = NULL;
-	}
-	if (wlc->radio_timer) {
-		wl_free_timer(wlc->wl, wlc->radio_timer);
-		wlc->radio_timer = NULL;
-	}
-}
-
-static void wlc_detach_module(struct wlc_info *wlc)
-{
-	if (wlc->asi) {
-		wlc_antsel_detach(wlc->asi);
-		wlc->asi = NULL;
-	}
-
-	if (wlc->ampdu) {
-		wlc_ampdu_detach(wlc->ampdu);
-		wlc->ampdu = NULL;
-	}
-
-	wlc_stf_detach(wlc);
-}
-
-/*
- * Return a count of the number of driver callbacks still pending.
- *
- * General policy is that wlc_detach can only dealloc/free software states. It can NOT
- *  touch hardware registers since the d11core may be in reset and clock may not be available.
- *    One exception is sb register access, which is possible if crystal is turned on
- * After "down" state, driver should avoid software timer with the exception of radio_monitor.
- */
-uint wlc_detach(struct wlc_info *wlc)
-{
-	uint i;
-	uint callbacks = 0;
-
-	if (wlc == NULL)
-		return 0;
-
-	WL_TRACE("wl%d: %s\n", wlc->pub->unit, __func__);
-
-	ASSERT(!wlc->pub->up);
-
-	callbacks += wlc_bmac_detach(wlc);
-
-	/* delete software timers */
-	if (!wlc_radio_monitor_stop(wlc))
-		callbacks++;
-
-	if (wlc->eventq) {
-		wlc_eventq_detach(wlc->eventq);
-		wlc->eventq = NULL;
-	}
-
-	wlc_channel_mgr_detach(wlc->cmi);
-
-	wlc_timers_deinit(wlc);
-
-	wlc_detach_module(wlc);
-
-	/* free other state */
-
-
-#ifdef BCMDBG
-	if (wlc->country_ie_override) {
-		kfree(wlc->country_ie_override);
-		wlc->country_ie_override = NULL;
-	}
-#endif				/* BCMDBG */
-
-	{
-		/* free dumpcb list */
-		dumpcb_t *prev, *ptr;
-		prev = ptr = wlc->dumpcb_head;
-		while (ptr) {
-			ptr = prev->next;
-			kfree(prev);
-			prev = ptr;
-		}
-		wlc->dumpcb_head = NULL;
-	}
-
-	/* Detach from iovar manager */
-	wlc_module_unregister(wlc->pub, "wlc_iovars", wlc);
-
-	while (wlc->tx_queues != NULL) {
-		wlc_txq_free(wlc, wlc->osh, wlc->tx_queues);
-	}
-
-	/*
-	 * consistency check: wlc_module_register/wlc_module_unregister calls
-	 * should match therefore nothing should be left here.
-	 */
-	for (i = 0; i < WLC_MAXMODULES; i++)
-		ASSERT(wlc->modulecb[i].name[0] == '\0');
-
-	wlc_detach_mfree(wlc, wlc->osh);
-	return callbacks;
-}
-
-/* update state that depends on the current value of "ap" */
-void wlc_ap_upd(struct wlc_info *wlc)
-{
-	if (AP_ENAB(wlc->pub))
-		wlc->PLCPHdr_override = WLC_PLCP_AUTO;	/* AP: short not allowed, but not enforced */
-	else
-		wlc->PLCPHdr_override = WLC_PLCP_SHORT;	/* STA-BSS; short capable */
-
-	/* disable vlan_mode on AP since some legacy STAs cannot rx tagged pkts */
-	wlc->vlan_mode = AP_ENAB(wlc->pub) ? OFF : AUTO;
-
-	/* fixup mpc */
-	wlc->mpc = true;
-}
-
-/* read hwdisable state and propagate to wlc flag */
-static void wlc_radio_hwdisable_upd(struct wlc_info *wlc)
-{
-	if (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO || wlc->pub->hw_off)
-		return;
-
-	if (wlc_bmac_radio_read_hwdisabled(wlc->hw)) {
-		mboolset(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
-	} else {
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
-	}
-}
-
-/* return true if Minimum Power Consumption should be entered, false otherwise */
-bool wlc_is_non_delay_mpc(struct wlc_info *wlc)
-{
-	return false;
-}
-
-bool wlc_ismpc(struct wlc_info *wlc)
-{
-	return (wlc->mpc_delay_off == 0) && (wlc_is_non_delay_mpc(wlc));
-}
-
-void wlc_radio_mpc_upd(struct wlc_info *wlc)
-{
-	bool mpc_radio, radio_state;
-
-	/*
-	 * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
-	 * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
-	 * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
-	 * the radio is going down.
-	 */
-	if (!wlc->mpc) {
-		if (!wlc->pub->radio_disabled)
-			return;
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-		wlc_radio_upd(wlc);
-		if (!wlc->pub->radio_disabled)
-			wlc_radio_monitor_stop(wlc);
-		return;
-	}
-
-	/*
-	 * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in wlc->pub->radio_disabled
-	 * to go ON, always call radio_upd synchronously
-	 * to go OFF, postpone radio_upd to later when context is safe(e.g. watchdog)
-	 */
-	radio_state =
-	    (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
-	     ON);
-	mpc_radio = (wlc_ismpc(wlc) == true) ? OFF : ON;
-
-	if (radio_state == ON && mpc_radio == OFF)
-		wlc->mpc_delay_off = wlc->mpc_dlycnt;
-	else if (radio_state == OFF && mpc_radio == ON) {
-		mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-		wlc_radio_upd(wlc);
-		if (wlc->mpc_offcnt < WLC_MPC_THRESHOLD) {
-			wlc->mpc_dlycnt = WLC_MPC_MAX_DELAYCNT;
-		} else
-			wlc->mpc_dlycnt = WLC_MPC_MIN_DELAYCNT;
-		wlc->mpc_dur += OSL_SYSUPTIME() - wlc->mpc_laston_ts;
-	}
-	/* Below logic is meant to capture the transition from mpc off to mpc on for reasons
-	 * other than wlc->mpc_delay_off keeping the mpc off. In that case reset
-	 * wlc->mpc_delay_off to wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
-	 */
-	if ((wlc->prev_non_delay_mpc == false) &&
-	    (wlc_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off) {
-		wlc->mpc_delay_off = wlc->mpc_dlycnt;
-	}
-	wlc->prev_non_delay_mpc = wlc_is_non_delay_mpc(wlc);
-}
-
-/*
- * centralized radio disable/enable function,
- * invoke radio enable/disable after updating hwradio status
- */
-static void wlc_radio_upd(struct wlc_info *wlc)
-{
-	if (wlc->pub->radio_disabled)
-		wlc_radio_disable(wlc);
-	else
-		wlc_radio_enable(wlc);
-}
-
-/* maintain LED behavior in down state */
-static void wlc_down_led_upd(struct wlc_info *wlc)
-{
-	ASSERT(!wlc->pub->up);
-
-	/* maintain LEDs while in down state, turn on sbclk if not available yet */
-	/* turn on sbclk if necessary */
-	if (!AP_ENAB(wlc->pub)) {
-		wlc_pllreq(wlc, true, WLC_PLLREQ_FLIP);
-
-		wlc_pllreq(wlc, false, WLC_PLLREQ_FLIP);
-	}
-}
-
-void wlc_radio_disable(struct wlc_info *wlc)
-{
-	if (!wlc->pub->up) {
-		wlc_down_led_upd(wlc);
-		return;
-	}
-
-	wlc_radio_monitor_start(wlc);
-	wl_down(wlc->wl);
-}
-
-static void wlc_radio_enable(struct wlc_info *wlc)
-{
-	if (wlc->pub->up)
-		return;
-
-	if (DEVICEREMOVED(wlc))
-		return;
-
-	if (!wlc->down_override) {	/* imposed by wl down/out ioctl */
-		wl_up(wlc->wl);
-	}
-}
-
-/* periodical query hw radio button while driver is "down" */
-static void wlc_radio_timer(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-
-	if (DEVICEREMOVED(wlc)) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc->pub->unit, __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-
-	/* cap mpc off count */
-	if (wlc->mpc_offcnt < WLC_MPC_MAX_DELAYCNT)
-		wlc->mpc_offcnt++;
-
-	/* validate all the reasons driver could be down and running this radio_timer */
-	ASSERT(wlc->pub->radio_disabled || wlc->down_override);
-	wlc_radio_hwdisable_upd(wlc);
-	wlc_radio_upd(wlc);
-}
-
-static bool wlc_radio_monitor_start(struct wlc_info *wlc)
-{
-	/* Don't start the timer if HWRADIO feature is disabled */
-	if (wlc->radio_monitor || (wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO))
-		return true;
-
-	wlc->radio_monitor = true;
-	wlc_pllreq(wlc, true, WLC_PLLREQ_RADIO_MON);
-	wl_add_timer(wlc->wl, wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
-	return true;
-}
-
-bool wlc_radio_monitor_stop(struct wlc_info *wlc)
-{
-	if (!wlc->radio_monitor)
-		return true;
-
-	ASSERT((wlc->pub->wlfeatureflag & WL_SWFL_NOHWRADIO) !=
-	       WL_SWFL_NOHWRADIO);
-
-	wlc->radio_monitor = false;
-	wlc_pllreq(wlc, false, WLC_PLLREQ_RADIO_MON);
-	return wl_del_timer(wlc->wl, wlc->radio_timer);
-}
-
-/* bring the driver down, but don't reset hardware */
-void wlc_out(struct wlc_info *wlc)
-{
-	wlc_bmac_set_noreset(wlc->hw, true);
-	wlc_radio_upd(wlc);
-	wl_down(wlc->wl);
-	wlc_bmac_set_noreset(wlc->hw, false);
-
-	/* core clk is true in BMAC driver due to noreset, need to mirror it in HIGH */
-	wlc->clk = true;
-
-	/* This will make sure that when 'up' is done
-	 * after 'out' it'll restore hardware (especially gpios)
-	 */
-	wlc->pub->hw_up = false;
-}
-
-#if defined(BCMDBG)
-/* Verify the sanity of wlc->tx_prec_map. This can be done only by making sure that
- * if there is no packet pending for the FIFO, then the corresponding prec bits should be set
- * in prec_map. Of course, ignore this rule when block_datafifo is set
- */
-static bool wlc_tx_prec_map_verify(struct wlc_info *wlc)
-{
-	/* For non-WME, both fifos have overlapping prec_map. So it's an error only if both
-	 * fail the check.
-	 */
-	if (!EDCF_ENAB(wlc->pub)) {
-		if (!(WLC_TX_FIFO_CHECK(wlc, TX_DATA_FIFO) ||
-		      WLC_TX_FIFO_CHECK(wlc, TX_CTL_FIFO)))
-			return false;
-		else
-			return true;
-	}
-
-	return WLC_TX_FIFO_CHECK(wlc, TX_AC_BK_FIFO)
-		&& WLC_TX_FIFO_CHECK(wlc, TX_AC_BE_FIFO)
-		&& WLC_TX_FIFO_CHECK(wlc, TX_AC_VI_FIFO)
-		&& WLC_TX_FIFO_CHECK(wlc, TX_AC_VO_FIFO);
-}
-#endif				/* BCMDBG */
-
-static void wlc_watchdog_by_timer(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	wlc_watchdog(arg);
-	if (WLC_WATCHDOG_TBTT(wlc)) {
-		/* set to normal osl watchdog period */
-		wl_del_timer(wlc->wl, wlc->wdtimer);
-		wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG,
-			     true);
-	}
-}
-
-/* common watchdog code */
-static void wlc_watchdog(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	int i;
-	wlc_bsscfg_t *cfg;
-
-	WL_TRACE("wl%d: wlc_watchdog\n", wlc->pub->unit);
-
-	if (!wlc->pub->up)
-		return;
-
-	if (DEVICEREMOVED(wlc)) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc->pub->unit, __func__);
-		wl_down(wlc->wl);
-		return;
-	}
-
-	/* increment second count */
-	wlc->pub->now++;
-
-	/* delay radio disable */
-	if (wlc->mpc_delay_off) {
-		if (--wlc->mpc_delay_off == 0) {
-			mboolset(wlc->pub->radio_disabled,
-				 WL_RADIO_MPC_DISABLE);
-			if (wlc->mpc && wlc_ismpc(wlc))
-				wlc->mpc_offcnt = 0;
-			wlc->mpc_laston_ts = OSL_SYSUPTIME();
-		}
-	}
-
-	/* mpc sync */
-	wlc_radio_mpc_upd(wlc);
-	/* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
-	wlc_radio_hwdisable_upd(wlc);
-	wlc_radio_upd(wlc);
-	/* if ismpc, driver should be in down state if up/down is allowed */
-	if (wlc->mpc && wlc_ismpc(wlc))
-		ASSERT(!wlc->pub->up);
-	/* if radio is disable, driver may be down, quit here */
-	if (wlc->pub->radio_disabled)
-		return;
-
-	wlc_bmac_watchdog(wlc);
-
-	/* occasionally sample mac stat counters to detect 16-bit counter wrap */
-	if ((WLC_UPDATE_STATS(wlc))
-	    && (!(wlc->pub->now % SW_TIMER_MAC_STAT_UPD)))
-		wlc_statsupd(wlc);
-
-	/* Manage TKIP countermeasures timers */
-	FOREACH_BSS(wlc, i, cfg) {
-		if (cfg->tk_cm_dt) {
-			cfg->tk_cm_dt--;
-		}
-		if (cfg->tk_cm_bt) {
-			cfg->tk_cm_bt--;
-		}
-	}
-
-	/* Call any registered watchdog handlers */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (wlc->modulecb[i].watchdog_fn)
-			wlc->modulecb[i].watchdog_fn(wlc->modulecb[i].hdl);
-	}
-
-	if (WLCISNPHY(wlc->band) && !wlc->pub->tempsense_disable &&
-	    ((wlc->pub->now - wlc->tempsense_lasttime) >=
-	     WLC_TEMPSENSE_PERIOD)) {
-		wlc->tempsense_lasttime = wlc->pub->now;
-		wlc_tempsense_upd(wlc);
-	}
-	/* BMAC_NOTE: for HIGH_ONLY driver, this seems being called after RPC bus failed */
-	ASSERT(wlc_bmac_taclear(wlc->hw, true));
-
-	/* Verify that tx_prec_map and fifos are in sync to avoid lock ups */
-	ASSERT(wlc_tx_prec_map_verify(wlc));
-
-	ASSERT(wlc_ps_check(wlc));
-}
-
-/* make interface operational */
-int wlc_up(struct wlc_info *wlc)
-{
-	WL_TRACE("wl%d: %s:\n", wlc->pub->unit, __func__);
-
-	/* HW is turned off so don't try to access it */
-	if (wlc->pub->hw_off || DEVICEREMOVED(wlc))
-		return BCME_RADIOOFF;
-
-	if (!wlc->pub->hw_up) {
-		wlc_bmac_hw_up(wlc->hw);
-		wlc->pub->hw_up = true;
-	}
-
-	if ((wlc->pub->boardflags & BFL_FEM)
-	    && (wlc->pub->sih->chip == BCM4313_CHIP_ID)) {
-		if (wlc->pub->boardrev >= 0x1250
-		    && (wlc->pub->boardflags & BFL_FEM_BT)) {
-			wlc_mhf(wlc, MHF5, MHF5_4313_GPIOCTRL,
-				MHF5_4313_GPIOCTRL, WLC_BAND_ALL);
-		} else {
-			wlc_mhf(wlc, MHF4, MHF4_EXTPA_ENABLE, MHF4_EXTPA_ENABLE,
-				WLC_BAND_ALL);
-		}
-	}
-
-	/*
-	 * Need to read the hwradio status here to cover the case where the system
-	 * is loaded with the hw radio disabled. We do not want to bring the driver up in this case.
-	 * if radio is disabled, abort up, lower power, start radio timer and return 0(for NDIS)
-	 * don't call radio_update to avoid looping wlc_up.
-	 *
-	 * wlc_bmac_up_prep() returns either 0 or BCME_RADIOOFF only
-	 */
-	if (!wlc->pub->radio_disabled) {
-		int status = wlc_bmac_up_prep(wlc->hw);
-		if (status == BCME_RADIOOFF) {
-			if (!mboolisset
-			    (wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE)) {
-				int idx;
-				wlc_bsscfg_t *bsscfg;
-				mboolset(wlc->pub->radio_disabled,
-					 WL_RADIO_HW_DISABLE);
-
-				FOREACH_BSS(wlc, idx, bsscfg) {
-					if (!BSSCFG_STA(bsscfg)
-					    || !bsscfg->enable || !bsscfg->BSS)
-						continue;
-					WL_ERROR("wl%d.%d: wlc_up: rfdisable -> " "wlc_bsscfg_disable()\n",
-						 wlc->pub->unit, idx);
-				}
-			}
-		} else
-			ASSERT(!status);
-	}
-
-	if (wlc->pub->radio_disabled) {
-		wlc_radio_monitor_start(wlc);
-		return 0;
-	}
-
-	/* wlc_bmac_up_prep has done wlc_corereset(). so clk is on, set it */
-	wlc->clk = true;
-
-	wlc_radio_monitor_stop(wlc);
-
-	/* Set EDCF hostflags */
-	if (EDCF_ENAB(wlc->pub)) {
-		wlc_mhf(wlc, MHF1, MHF1_EDCF, MHF1_EDCF, WLC_BAND_ALL);
-	} else {
-		wlc_mhf(wlc, MHF1, MHF1_EDCF, 0, WLC_BAND_ALL);
-	}
-
-	if (WLC_WAR16165(wlc))
-		wlc_mhf(wlc, MHF2, MHF2_PCISLOWCLKWAR, MHF2_PCISLOWCLKWAR,
-			WLC_BAND_ALL);
-
-	wl_init(wlc->wl);
-	wlc->pub->up = true;
-
-	if (wlc->bandinit_pending) {
-		wlc_suspend_mac_and_wait(wlc);
-		wlc_set_chanspec(wlc, wlc->default_bss->chanspec);
-		wlc->bandinit_pending = false;
-		wlc_enable_mac(wlc);
-	}
-
-	wlc_bmac_up_finish(wlc->hw);
-
-	/* other software states up after ISR is running */
-	/* start APs that were to be brought up but are not up  yet */
-	/* if (AP_ENAB(wlc->pub)) wlc_restart_ap(wlc->ap); */
-
-	/* Program the TX wme params with the current settings */
-	wlc_wme_retries_write(wlc);
-
-	/* start one second watchdog timer */
-	ASSERT(!wlc->WDarmed);
-	wl_add_timer(wlc->wl, wlc->wdtimer, TIMER_INTERVAL_WATCHDOG, true);
-	wlc->WDarmed = true;
-
-	/* ensure antenna config is up to date */
-	wlc_stf_phy_txant_upd(wlc);
-	/* ensure LDPC config is in sync */
-	wlc_ht_update_ldpc(wlc, wlc->stf->ldpc);
-
-	return 0;
-}
-
-/* Initialize the base precedence map for dequeueing from txq based on WME settings */
-static void wlc_tx_prec_map_init(struct wlc_info *wlc)
-{
-	wlc->tx_prec_map = WLC_PREC_BMP_ALL;
-	memset(wlc->fifo2prec_map, 0, NFIFO * sizeof(u16));
-
-	/* For non-WME, both fifos have overlapping MAXPRIO. So just disable all precedences
-	 * if either is full.
-	 */
-	if (!EDCF_ENAB(wlc->pub)) {
-		wlc->fifo2prec_map[TX_DATA_FIFO] = WLC_PREC_BMP_ALL;
-		wlc->fifo2prec_map[TX_CTL_FIFO] = WLC_PREC_BMP_ALL;
-	} else {
-		wlc->fifo2prec_map[TX_AC_BK_FIFO] = WLC_PREC_BMP_AC_BK;
-		wlc->fifo2prec_map[TX_AC_BE_FIFO] = WLC_PREC_BMP_AC_BE;
-		wlc->fifo2prec_map[TX_AC_VI_FIFO] = WLC_PREC_BMP_AC_VI;
-		wlc->fifo2prec_map[TX_AC_VO_FIFO] = WLC_PREC_BMP_AC_VO;
-	}
-}
-
-static uint wlc_down_del_timer(struct wlc_info *wlc)
-{
-	uint callbacks = 0;
-
-	return callbacks;
-}
-
-/*
- * Mark the interface nonoperational, stop the software mechanisms,
- * disable the hardware, free any transient buffer state.
- * Return a count of the number of driver callbacks still pending.
- */
-uint wlc_down(struct wlc_info *wlc)
-{
-
-	uint callbacks = 0;
-	int i;
-	bool dev_gone = false;
-	wlc_txq_info_t *qi;
-
-	WL_TRACE("wl%d: %s:\n", wlc->pub->unit, __func__);
-
-	/* check if we are already in the going down path */
-	if (wlc->going_down) {
-		WL_ERROR("wl%d: %s: Driver going down so return\n",
-			 wlc->pub->unit, __func__);
-		return 0;
-	}
-	if (!wlc->pub->up)
-		return callbacks;
-
-	/* in between, mpc could try to bring down again.. */
-	wlc->going_down = true;
-
-	callbacks += wlc_bmac_down_prep(wlc->hw);
-
-	dev_gone = DEVICEREMOVED(wlc);
-
-	/* Call any registered down handlers */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (wlc->modulecb[i].down_fn)
-			callbacks +=
-			    wlc->modulecb[i].down_fn(wlc->modulecb[i].hdl);
-	}
-
-	/* cancel the watchdog timer */
-	if (wlc->WDarmed) {
-		if (!wl_del_timer(wlc->wl, wlc->wdtimer))
-			callbacks++;
-		wlc->WDarmed = false;
-	}
-	/* cancel all other timers */
-	callbacks += wlc_down_del_timer(wlc);
-
-	/* interrupt must have been blocked */
-	ASSERT((wlc->macintmask == 0) || !wlc->pub->up);
-
-	wlc->pub->up = false;
-
-	wlc_phy_mute_upd(wlc->band->pi, false, PHY_MUTE_ALL);
-
-	/* clear txq flow control */
-	wlc_txflowcontrol_reset(wlc);
-
-	/* flush tx queues */
-	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
-		pktq_flush(wlc->osh, &qi->q, true, NULL, 0);
-		ASSERT(pktq_empty(&qi->q));
-	}
-
-	/* flush event queue.
-	 * Should be the last thing done after all the events are generated
-	 * Just delivers the events synchronously instead of waiting for a timer
-	 */
-	callbacks += wlc_eventq_down(wlc->eventq);
-
-	callbacks += wlc_bmac_down_finish(wlc->hw);
-
-	/* wlc_bmac_down_finish has done wlc_coredisable(). so clk is off */
-	wlc->clk = false;
-
-
-	/* Verify all packets are flushed from the driver */
-	if (wlc->osh->pktalloced != 0) {
-		WL_ERROR("%d packets not freed at wlc_down!!!!!!\n",
-			 wlc->osh->pktalloced);
-	}
-#ifdef BCMDBG
-	/* Since all the packets should have been freed,
-	 * all callbacks should have been called
-	 */
-	for (i = 1; i <= wlc->pub->tunables->maxpktcb; i++)
-		ASSERT(wlc->pkt_callback[i].fn == NULL);
-#endif
-	wlc->going_down = false;
-	return callbacks;
-}
-
-/* Set the current gmode configuration */
-int wlc_set_gmode(struct wlc_info *wlc, u8 gmode, bool config)
-{
-	int ret = 0;
-	uint i;
-	wlc_rateset_t rs;
-	/* Default to 54g Auto */
-	s8 shortslot = WLC_SHORTSLOT_AUTO;	/* Advertise and use shortslot (-1/0/1 Auto/Off/On) */
-	bool shortslot_restrict = false;	/* Restrict association to stations that support shortslot
-						 */
-	bool ignore_bcns = true;	/* Ignore legacy beacons on the same channel */
-	bool ofdm_basic = false;	/* Make 6, 12, and 24 basic rates */
-	int preamble = WLC_PLCP_LONG;	/* Advertise and use short preambles (-1/0/1 Auto/Off/On) */
-	bool preamble_restrict = false;	/* Restrict association to stations that support short
-					 * preambles
-					 */
-	struct wlcband *band;
-
-	/* if N-support is enabled, allow Gmode set as long as requested
-	 * Gmode is not GMODE_LEGACY_B
-	 */
-	if (N_ENAB(wlc->pub) && gmode == GMODE_LEGACY_B)
-		return BCME_UNSUPPORTED;
-
-	/* verify that we are dealing with 2G band and grab the band pointer */
-	if (wlc->band->bandtype == WLC_BAND_2G)
-		band = wlc->band;
-	else if ((NBANDS(wlc) > 1) &&
-		 (wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype == WLC_BAND_2G))
-		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
-	else
-		return BCME_BADBAND;
-
-	/* Legacy or bust when no OFDM is supported by regulatory */
-	if ((wlc_channel_locale_flags_in_band(wlc->cmi, band->bandunit) &
-	     WLC_NO_OFDM) && (gmode != GMODE_LEGACY_B))
-		return BCME_RANGE;
-
-	/* update configuration value */
-	if (config == true)
-		wlc_protection_upd(wlc, WLC_PROT_G_USER, gmode);
-
-	/* Clear supported rates filter */
-	memset(&wlc->sup_rates_override, 0, sizeof(wlc_rateset_t));
-
-	/* Clear rateset override */
-	memset(&rs, 0, sizeof(wlc_rateset_t));
-
-	switch (gmode) {
-	case GMODE_LEGACY_B:
-		shortslot = WLC_SHORTSLOT_OFF;
-		wlc_rateset_copy(&gphy_legacy_rates, &rs);
-
-		break;
-
-	case GMODE_LRS:
-		if (AP_ENAB(wlc->pub))
-			wlc_rateset_copy(&cck_rates, &wlc->sup_rates_override);
-		break;
-
-	case GMODE_AUTO:
-		/* Accept defaults */
-		break;
-
-	case GMODE_ONLY:
-		ofdm_basic = true;
-		preamble = WLC_PLCP_SHORT;
-		preamble_restrict = true;
-		break;
-
-	case GMODE_PERFORMANCE:
-		if (AP_ENAB(wlc->pub))	/* Put all rates into the Supported Rates element */
-			wlc_rateset_copy(&cck_ofdm_rates,
-					 &wlc->sup_rates_override);
-
-		shortslot = WLC_SHORTSLOT_ON;
-		shortslot_restrict = true;
-		ofdm_basic = true;
-		preamble = WLC_PLCP_SHORT;
-		preamble_restrict = true;
-		break;
-
-	default:
-		/* Error */
-		WL_ERROR("wl%d: %s: invalid gmode %d\n",
-			 wlc->pub->unit, __func__, gmode);
-		return BCME_UNSUPPORTED;
-	}
-
-	/*
-	 * If we are switching to gmode == GMODE_LEGACY_B,
-	 * clean up rate info that may refer to OFDM rates.
-	 */
-	if ((gmode == GMODE_LEGACY_B) && (band->gmode != GMODE_LEGACY_B)) {
-		band->gmode = gmode;
-		if (band->rspec_override && !IS_CCK(band->rspec_override)) {
-			band->rspec_override = 0;
-			wlc_reprate_init(wlc);
-		}
-		if (band->mrspec_override && !IS_CCK(band->mrspec_override)) {
-			band->mrspec_override = 0;
-		}
-	}
-
-	band->gmode = gmode;
-
-	wlc->ignore_bcns = ignore_bcns;
-
-	wlc->shortslot_override = shortslot;
-
-	if (AP_ENAB(wlc->pub)) {
-		/* wlc->ap->shortslot_restrict = shortslot_restrict; */
-		wlc->PLCPHdr_override =
-		    (preamble !=
-		     WLC_PLCP_LONG) ? WLC_PLCP_SHORT : WLC_PLCP_AUTO;
-	}
-
-	if ((AP_ENAB(wlc->pub) && preamble != WLC_PLCP_LONG)
-	    || preamble == WLC_PLCP_SHORT)
-		wlc->default_bss->capability |= DOT11_CAP_SHORT;
-	else
-		wlc->default_bss->capability &= ~DOT11_CAP_SHORT;
-
-	/* Update shortslot capability bit for AP and IBSS */
-	if ((AP_ENAB(wlc->pub) && shortslot == WLC_SHORTSLOT_AUTO) ||
-	    shortslot == WLC_SHORTSLOT_ON)
-		wlc->default_bss->capability |= DOT11_CAP_SHORTSLOT;
-	else
-		wlc->default_bss->capability &= ~DOT11_CAP_SHORTSLOT;
-
-	/* Use the default 11g rateset */
-	if (!rs.count)
-		wlc_rateset_copy(&cck_ofdm_rates, &rs);
-
-	if (ofdm_basic) {
-		for (i = 0; i < rs.count; i++) {
-			if (rs.rates[i] == WLC_RATE_6M
-			    || rs.rates[i] == WLC_RATE_12M
-			    || rs.rates[i] == WLC_RATE_24M)
-				rs.rates[i] |= WLC_RATE_FLAG;
-		}
-	}
-
-	/* Set default bss rateset */
-	wlc->default_bss->rateset.count = rs.count;
-	bcopy((char *)rs.rates, (char *)wlc->default_bss->rateset.rates,
-	      sizeof(wlc->default_bss->rateset.rates));
-
-	return ret;
-}
-
-static int wlc_nmode_validate(struct wlc_info *wlc, s32 nmode)
-{
-	int err = 0;
-
-	switch (nmode) {
-
-	case OFF:
-		break;
-
-	case AUTO:
-	case WL_11N_2x2:
-	case WL_11N_3x3:
-		if (!(WLC_PHY_11N_CAP(wlc->band)))
-			err = BCME_BADBAND;
-		break;
-
-	default:
-		err = BCME_RANGE;
-		break;
-	}
-
-	return err;
-}
-
-int wlc_set_nmode(struct wlc_info *wlc, s32 nmode)
-{
-	uint i;
-	int err;
-
-	err = wlc_nmode_validate(wlc, nmode);
-	ASSERT(err == 0);
-	if (err)
-		return err;
-
-	switch (nmode) {
-	case OFF:
-		wlc->pub->_n_enab = OFF;
-		wlc->default_bss->flags &= ~WLC_BSS_HT;
-		/* delete the mcs rates from the default and hw ratesets */
-		wlc_rateset_mcs_clear(&wlc->default_bss->rateset);
-		for (i = 0; i < NBANDS(wlc); i++) {
-			memset(wlc->bandstate[i]->hw_rateset.mcs, 0,
-			       MCSSET_LEN);
-			if (IS_MCS(wlc->band->rspec_override)) {
-				wlc->bandstate[i]->rspec_override = 0;
-				wlc_reprate_init(wlc);
-			}
-			if (IS_MCS(wlc->band->mrspec_override))
-				wlc->bandstate[i]->mrspec_override = 0;
-		}
-		break;
-
-	case AUTO:
-		if (wlc->stf->txstreams == WL_11N_3x3)
-			nmode = WL_11N_3x3;
-		else
-			nmode = WL_11N_2x2;
-	case WL_11N_2x2:
-	case WL_11N_3x3:
-		ASSERT(WLC_PHY_11N_CAP(wlc->band));
-		/* force GMODE_AUTO if NMODE is ON */
-		wlc_set_gmode(wlc, GMODE_AUTO, true);
-		if (nmode == WL_11N_3x3)
-			wlc->pub->_n_enab = SUPPORT_HT;
-		else
-			wlc->pub->_n_enab = SUPPORT_11N;
-		wlc->default_bss->flags |= WLC_BSS_HT;
-		/* add the mcs rates to the default and hw ratesets */
-		wlc_rateset_mcs_build(&wlc->default_bss->rateset,
-				      wlc->stf->txstreams);
-		for (i = 0; i < NBANDS(wlc); i++)
-			memcpy(wlc->bandstate[i]->hw_rateset.mcs,
-			       wlc->default_bss->rateset.mcs, MCSSET_LEN);
-		break;
-
-	default:
-		ASSERT(0);
-		break;
-	}
-
-	return err;
-}
-
-static int wlc_set_rateset(struct wlc_info *wlc, wlc_rateset_t *rs_arg)
-{
-	wlc_rateset_t rs, new;
-	uint bandunit;
-
-	bcopy((char *)rs_arg, (char *)&rs, sizeof(wlc_rateset_t));
-
-	/* check for bad count value */
-	if ((rs.count == 0) || (rs.count > WLC_NUMRATES))
-		return BCME_BADRATESET;
-
-	/* try the current band */
-	bandunit = wlc->band->bandunit;
-	bcopy((char *)&rs, (char *)&new, sizeof(wlc_rateset_t));
-	if (wlc_rate_hwrs_filter_sort_validate
-	    (&new, &wlc->bandstate[bandunit]->hw_rateset, true,
-	     wlc->stf->txstreams))
-		goto good;
-
-	/* try the other band */
-	if (IS_MBAND_UNLOCKED(wlc)) {
-		bandunit = OTHERBANDUNIT(wlc);
-		bcopy((char *)&rs, (char *)&new, sizeof(wlc_rateset_t));
-		if (wlc_rate_hwrs_filter_sort_validate(&new,
-						       &wlc->
-						       bandstate[bandunit]->
-						       hw_rateset, true,
-						       wlc->stf->txstreams))
-			goto good;
-	}
-
-	return BCME_ERROR;
-
- good:
-	/* apply new rateset */
-	bcopy((char *)&new, (char *)&wlc->default_bss->rateset,
-	      sizeof(wlc_rateset_t));
-	bcopy((char *)&new, (char *)&wlc->bandstate[bandunit]->defrateset,
-	      sizeof(wlc_rateset_t));
-	return 0;
-}
-
-/* simplified integer set interface for common ioctl handler */
-int wlc_set(struct wlc_info *wlc, int cmd, int arg)
-{
-	return wlc_ioctl(wlc, cmd, (void *)&arg, sizeof(arg), NULL);
-}
-
-/* simplified integer get interface for common ioctl handler */
-int wlc_get(struct wlc_info *wlc, int cmd, int *arg)
-{
-	return wlc_ioctl(wlc, cmd, arg, sizeof(int), NULL);
-}
-
-static void wlc_ofdm_rateset_war(struct wlc_info *wlc)
-{
-	u8 r;
-	bool war = false;
-
-	if (wlc->cfg->associated)
-		r = wlc->cfg->current_bss->rateset.rates[0];
-	else
-		r = wlc->default_bss->rateset.rates[0];
-
-	wlc_phy_ofdm_rateset_war(wlc->band->pi, war);
-
-	return;
-}
-
-int
-wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-	  struct wlc_if *wlcif)
-{
-	return _wlc_ioctl(wlc, cmd, arg, len, wlcif);
-}
-
-/* common ioctl handler. return: 0=ok, -1=error, positive=particular error */
-static int
-_wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-	   struct wlc_if *wlcif)
-{
-	int val, *pval;
-	bool bool_val;
-	int bcmerror;
-	d11regs_t *regs;
-	uint i;
-	struct scb *nextscb;
-	bool ta_ok;
-	uint band;
-	rw_reg_t *r;
-	wlc_bsscfg_t *bsscfg;
-	struct osl_info *osh;
-	wlc_bss_info_t *current_bss;
-
-	/* update bsscfg pointer */
-	bsscfg = NULL;		/* XXX: Hack bsscfg to be size one and use this globally */
-	current_bss = NULL;
-
-	/* initialize the following to get rid of compiler warning */
-	nextscb = NULL;
-	ta_ok = false;
-	band = 0;
-	r = NULL;
-
-	/* If the device is turned off, then it's not "removed" */
-	if (!wlc->pub->hw_off && DEVICEREMOVED(wlc)) {
-		WL_ERROR("wl%d: %s: dead chip\n", wlc->pub->unit, __func__);
-		wl_down(wlc->wl);
-		return BCME_ERROR;
-	}
-
-	ASSERT(!(wlc->pub->hw_off && wlc->pub->up));
-
-	/* default argument is generic integer */
-	pval = arg ? (int *)arg:NULL;
-
-	/* This will prevent the misaligned access */
-	if (pval && (u32) len >= sizeof(val))
-		bcopy(pval, &val, sizeof(val));
-	else
-		val = 0;
-
-	/* bool conversion to avoid duplication below */
-	bool_val = val != 0;
-
-	if (cmd != WLC_SET_CHANNEL)
-		WL_NONE("WLC_IOCTL: cmd %d val 0x%x (%d) len %d\n",
-			cmd, (uint)val, val, len);
-
-	bcmerror = 0;
-	regs = wlc->regs;
-	osh = wlc->osh;
-
-	/* A few commands don't need any arguments; all the others do. */
-	switch (cmd) {
-	case WLC_UP:
-	case WLC_OUT:
-	case WLC_DOWN:
-	case WLC_DISASSOC:
-	case WLC_RESTART:
-	case WLC_REBOOT:
-	case WLC_START_CHANNEL_QA:
-	case WLC_INIT:
-		break;
-
-	default:
-		if ((arg == NULL) || (len <= 0)) {
-			WL_ERROR("wl%d: %s: Command %d needs arguments\n",
-				 wlc->pub->unit, __func__, cmd);
-			bcmerror = BCME_BADARG;
-			goto done;
-		}
-	}
-
-	switch (cmd) {
-
-#if defined(BCMDBG)
-	case WLC_GET_MSGLEVEL:
-		*pval = wl_msg_level;
-		break;
-
-	case WLC_SET_MSGLEVEL:
-		wl_msg_level = val;
-		break;
-#endif
-
-	case WLC_GET_INSTANCE:
-		*pval = wlc->pub->unit;
-		break;
-
-	case WLC_GET_CHANNEL:{
-			channel_info_t *ci = (channel_info_t *) arg;
-
-			ASSERT(len > (int)sizeof(ci));
-
-			ci->hw_channel =
-			    CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC);
-			ci->target_channel =
-			    CHSPEC_CHANNEL(wlc->default_bss->chanspec);
-			ci->scan_channel = 0;
-
-			break;
-		}
-
-	case WLC_SET_CHANNEL:{
-			chanspec_t chspec = CH20MHZ_CHSPEC(val);
-
-			if (val < 0 || val > MAXCHANNEL) {
-				bcmerror = BCME_OUTOFRANGECHAN;
-				break;
-			}
-
-			if (!wlc_valid_chanspec_db(wlc->cmi, chspec)) {
-				bcmerror = BCME_BADCHAN;
-				break;
-			}
-
-			if (!wlc->pub->up && IS_MBAND_UNLOCKED(wlc)) {
-				if (wlc->band->bandunit !=
-				    CHSPEC_WLCBANDUNIT(chspec))
-					wlc->bandinit_pending = true;
-				else
-					wlc->bandinit_pending = false;
-			}
-
-			wlc->default_bss->chanspec = chspec;
-			/* wlc_BSSinit() will sanitize the rateset before using it.. */
-			if (wlc->pub->up && !wlc->pub->associated &&
-			    (WLC_BAND_PI_RADIO_CHANSPEC != chspec)) {
-				wlc_set_home_chanspec(wlc, chspec);
-				wlc_suspend_mac_and_wait(wlc);
-				wlc_set_chanspec(wlc, chspec);
-				wlc_enable_mac(wlc);
-			}
-			break;
-		}
-
-#if defined(BCMDBG)
-	case WLC_GET_UCFLAGS:
-		if (!wlc->pub->up) {
-			bcmerror = BCME_NOTUP;
-			break;
-		}
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (val >= MHFMAX) {
-			bcmerror = BCME_RANGE;
-			break;
-		}
-
-		*pval = wlc_bmac_mhf_get(wlc->hw, (u8) val, WLC_BAND_AUTO);
-		break;
-
-	case WLC_SET_UCFLAGS:
-		if (!wlc->pub->up) {
-			bcmerror = BCME_NOTUP;
-			break;
-		}
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		i = (u16) val;
-		if (i >= MHFMAX) {
-			bcmerror = BCME_RANGE;
-			break;
-		}
-
-		wlc_mhf(wlc, (u8) i, 0xffff, (u16) (val >> NBITS(u16)),
-			WLC_BAND_AUTO);
-		break;
-
-	case WLC_GET_SHMEM:
-		ta_ok = true;
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (val & 1) {
-			bcmerror = BCME_BADADDR;
-			break;
-		}
-
-		*pval = wlc_read_shm(wlc, (u16) val);
-		break;
-
-	case WLC_SET_SHMEM:
-		ta_ok = true;
-
-		/* optional band is stored in the second integer of incoming buffer */
-		band =
-		    (len <
-		     (int)(2 * sizeof(int))) ? WLC_BAND_AUTO : ((int *)arg)[1];
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (val & 1) {
-			bcmerror = BCME_BADADDR;
-			break;
-		}
-
-		wlc_write_shm(wlc, (u16) val,
-			      (u16) (val >> NBITS(u16)));
-		break;
-
-	case WLC_R_REG:	/* MAC registers */
-		ta_ok = true;
-		r = (rw_reg_t *) arg;
-		band = WLC_BAND_AUTO;
-
-		if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
-			bcmerror = BCME_BUFTOOSHORT;
-			break;
-		}
-
-		if (len >= (int)sizeof(rw_reg_t))
-			band = r->band;
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if ((r->byteoff + r->size) > sizeof(d11regs_t)) {
-			bcmerror = BCME_BADADDR;
-			break;
-		}
-		if (r->size == sizeof(u32))
-			r->val =
-			    R_REG(osh,
-				  (u32 *)((unsigned char *)(unsigned long)regs +
-					      r->byteoff));
-		else if (r->size == sizeof(u16))
-			r->val =
-			    R_REG(osh,
-				  (u16 *)((unsigned char *)(unsigned long)regs +
-					      r->byteoff));
-		else
-			bcmerror = BCME_BADADDR;
-		break;
-
-	case WLC_W_REG:
-		ta_ok = true;
-		r = (rw_reg_t *) arg;
-		band = WLC_BAND_AUTO;
-
-		if (len < (int)(sizeof(rw_reg_t) - sizeof(uint))) {
-			bcmerror = BCME_BUFTOOSHORT;
-			break;
-		}
-
-		if (len >= (int)sizeof(rw_reg_t))
-			band = r->band;
-
-		/* bcmerror checking */
-		bcmerror = wlc_iocregchk(wlc, band);
-		if (bcmerror)
-			break;
-
-		if (r->byteoff + r->size > sizeof(d11regs_t)) {
-			bcmerror = BCME_BADADDR;
-			break;
-		}
-		if (r->size == sizeof(u32))
-			W_REG(osh,
-			      (u32 *)((unsigned char *)(unsigned long) regs +
-					  r->byteoff), r->val);
-		else if (r->size == sizeof(u16))
-			W_REG(osh,
-			      (u16 *)((unsigned char *)(unsigned long) regs +
-					  r->byteoff), r->val);
-		else
-			bcmerror = BCME_BADADDR;
-		break;
-#endif				/* BCMDBG */
-
-	case WLC_GET_TXANT:
-		*pval = wlc->stf->txant;
-		break;
-
-	case WLC_SET_TXANT:
-		bcmerror = wlc_stf_ant_txant_validate(wlc, (s8) val);
-		if (bcmerror < 0)
-			break;
-
-		wlc->stf->txant = (s8) val;
-
-		/* if down, we are done */
-		if (!wlc->pub->up)
-			break;
-
-		wlc_suspend_mac_and_wait(wlc);
-
-		wlc_stf_phy_txant_upd(wlc);
-		wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
-
-		wlc_enable_mac(wlc);
-
-		break;
-
-	case WLC_GET_ANTDIV:{
-			u8 phy_antdiv;
-
-			/* return configured value if core is down */
-			if (!wlc->pub->up) {
-				*pval = wlc->stf->ant_rx_ovr;
-
-			} else {
-				if (wlc_phy_ant_rxdiv_get
-				    (wlc->band->pi, &phy_antdiv))
-					*pval = (int)phy_antdiv;
-				else
-					*pval = (int)wlc->stf->ant_rx_ovr;
-			}
-
-			break;
-		}
-	case WLC_SET_ANTDIV:
-		/* values are -1=driver default, 0=force0, 1=force1, 2=start1, 3=start0 */
-		if ((val < -1) || (val > 3)) {
-			bcmerror = BCME_RANGE;
-			break;
-		}
-
-		if (val == -1)
-			val = ANT_RX_DIV_DEF;
-
-		wlc->stf->ant_rx_ovr = (u8) val;
-		wlc_phy_ant_rxdiv_set(wlc->band->pi, (u8) val);
-		break;
-
-	case WLC_GET_RX_ANT:{	/* get latest used rx antenna */
-			u16 rxstatus;
-
-			if (!wlc->pub->up) {
-				bcmerror = BCME_NOTUP;
-				break;
-			}
-
-			rxstatus = R_REG(wlc->osh, &wlc->regs->phyrxstatus0);
-			if (rxstatus == 0xdead || rxstatus == (u16) -1) {
-				bcmerror = BCME_ERROR;
-				break;
-			}
-			*pval = (rxstatus & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;
-			break;
-		}
-
-#if defined(BCMDBG)
-	case WLC_GET_UCANTDIV:
-		if (!wlc->clk) {
-			bcmerror = BCME_NOCLK;
-			break;
-		}
-
-		*pval =
-		    (wlc_bmac_mhf_get(wlc->hw, MHF1, WLC_BAND_AUTO) &
-		     MHF1_ANTDIV);
-		break;
-
-	case WLC_SET_UCANTDIV:{
-			if (!wlc->pub->up) {
-				bcmerror = BCME_NOTUP;
-				break;
-			}
-
-			/* if multiband, band must be locked */
-			if (IS_MBAND_UNLOCKED(wlc)) {
-				bcmerror = BCME_NOTBANDLOCKED;
-				break;
-			}
-
-			/* 4322 supports antdiv in phy, no need to set it to ucode */
-			if (WLCISNPHY(wlc->band)
-			    && D11REV_IS(wlc->pub->corerev, 16)) {
-				WL_ERROR("wl%d: can't set ucantdiv for 4322\n",
-					 wlc->pub->unit);
-				bcmerror = BCME_UNSUPPORTED;
-			} else
-				wlc_mhf(wlc, MHF1, MHF1_ANTDIV,
-					(val ? MHF1_ANTDIV : 0), WLC_BAND_AUTO);
-			break;
-		}
-#endif				/* defined(BCMDBG) */
-
-	case WLC_GET_SRL:
-		*pval = wlc->SRL;
-		break;
-
-	case WLC_SET_SRL:
-		if (val >= 1 && val <= RETRY_SHORT_MAX) {
-			int ac;
-			wlc->SRL = (u16) val;
-
-			wlc_bmac_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
-			for (ac = 0; ac < AC_COUNT; ac++) {
-				WLC_WME_RETRY_SHORT_SET(wlc, ac, wlc->SRL);
-			}
-			wlc_wme_retries_write(wlc);
-		} else
-			bcmerror = BCME_RANGE;
-		break;
-
-	case WLC_GET_LRL:
-		*pval = wlc->LRL;
-		break;
-
-	case WLC_SET_LRL:
-		if (val >= 1 && val <= 255) {
-			int ac;
-			wlc->LRL = (u16) val;
-
-			wlc_bmac_retrylimit_upd(wlc->hw, wlc->SRL, wlc->LRL);
-
-			for (ac = 0; ac < AC_COUNT; ac++) {
-				WLC_WME_RETRY_LONG_SET(wlc, ac, wlc->LRL);
-			}
-			wlc_wme_retries_write(wlc);
-		} else
-			bcmerror = BCME_RANGE;
-		break;
-
-	case WLC_GET_CWMIN:
-		*pval = wlc->band->CWmin;
-		break;
-
-	case WLC_SET_CWMIN:
-		if (!wlc->clk) {
-			bcmerror = BCME_NOCLK;
-			break;
-		}
-
-		if (val >= 1 && val <= 255) {
-			wlc_set_cwmin(wlc, (u16) val);
-		} else
-			bcmerror = BCME_RANGE;
-		break;
-
-	case WLC_GET_CWMAX:
-		*pval = wlc->band->CWmax;
-		break;
-
-	case WLC_SET_CWMAX:
-		if (!wlc->clk) {
-			bcmerror = BCME_NOCLK;
-			break;
-		}
-
-		if (val >= 255 && val <= 2047) {
-			wlc_set_cwmax(wlc, (u16) val);
-		} else
-			bcmerror = BCME_RANGE;
-		break;
-
-	case WLC_GET_RADIO:	/* use mask if don't want to expose some internal bits */
-		*pval = wlc->pub->radio_disabled;
-		break;
-
-	case WLC_SET_RADIO:{	/* 32 bits input, higher 16 bits are mask, lower 16 bits are value to
-				 * set
-				 */
-			u16 radiomask, radioval;
-			uint validbits =
-			    WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE;
-			mbool new = 0;
-
-			radiomask = (val & 0xffff0000) >> 16;
-			radioval = val & 0x0000ffff;
-
-			if ((radiomask == 0) || (radiomask & ~validbits)
-			    || (radioval & ~validbits)
-			    || ((radioval & ~radiomask) != 0)) {
-				WL_ERROR("SET_RADIO with wrong bits 0x%x\n",
-					 val);
-				bcmerror = BCME_RANGE;
-				break;
-			}
-
-			new =
-			    (wlc->pub->radio_disabled & ~radiomask) | radioval;
-			wlc->pub->radio_disabled = new;
-
-			wlc_radio_hwdisable_upd(wlc);
-			wlc_radio_upd(wlc);
-			break;
-		}
-
-	case WLC_GET_PHYTYPE:
-		*pval = WLC_PHYTYPE(wlc->band->phytype);
-		break;
-
-#if defined(BCMDBG)
-	case WLC_GET_KEY:
-		if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc))) {
-			wl_wsec_key_t key;
-
-			wsec_key_t *src_key = wlc->wsec_keys[val];
-
-			if (len < (int)sizeof(key)) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-
-			memset((char *)&key, 0, sizeof(key));
-			if (src_key) {
-				key.index = src_key->id;
-				key.len = src_key->len;
-				bcopy(src_key->data, key.data, key.len);
-				key.algo = src_key->algo;
-				if (WSEC_SOFTKEY(wlc, src_key, bsscfg))
-					key.flags |= WL_SOFT_KEY;
-				if (src_key->flags & WSEC_PRIMARY_KEY)
-					key.flags |= WL_PRIMARY_KEY;
-
-				bcopy(src_key->ea.octet, key.ea.octet,
-				      ETH_ALEN);
-			}
-
-			bcopy((char *)&key, arg, sizeof(key));
-		} else
-			bcmerror = BCME_BADKEYIDX;
-		break;
-#endif				/* defined(BCMDBG) */
-
-	case WLC_SET_KEY:
-		bcmerror =
-		    wlc_iovar_op(wlc, "wsec_key", NULL, 0, arg, len, IOV_SET,
-				 wlcif);
-		break;
-
-	case WLC_GET_KEY_SEQ:{
-			wsec_key_t *key;
-
-			if (len < DOT11_WPA_KEY_RSC_LEN) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-
-			/* Return the key's tx iv as an EAPOL sequence counter.
-			 * This will be used to supply the RSC value to a supplicant.
-			 * The format is 8 bytes, with least significant in seq[0].
-			 */
-
-			key = WSEC_KEY(wlc, val);
-			if ((val >= 0) && (val < WLC_MAX_WSEC_KEYS(wlc)) &&
-				(key != NULL)) {
-				u8 seq[DOT11_WPA_KEY_RSC_LEN];
-				u16 lo;
-				u32 hi;
-				/* group keys in WPA-NONE (IBSS only, AES and TKIP) use a global TXIV */
-				if ((bsscfg->WPA_auth & WPA_AUTH_NONE) &&
-				    is_zero_ether_addr(key->ea.octet)) {
-					lo = bsscfg->wpa_none_txiv.lo;
-					hi = bsscfg->wpa_none_txiv.hi;
-				} else {
-					lo = key->txiv.lo;
-					hi = key->txiv.hi;
-				}
-
-				/* format the buffer, low to high */
-				seq[0] = lo & 0xff;
-				seq[1] = (lo >> 8) & 0xff;
-				seq[2] = hi & 0xff;
-				seq[3] = (hi >> 8) & 0xff;
-				seq[4] = (hi >> 16) & 0xff;
-				seq[5] = (hi >> 24) & 0xff;
-				seq[6] = 0;
-				seq[7] = 0;
-
-				bcopy((char *)seq, arg, sizeof(seq));
-			} else {
-				bcmerror = BCME_BADKEYIDX;
-			}
-			break;
-		}
-
-	case WLC_GET_CURR_RATESET:{
-			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
-			wlc_rateset_t *rs;
-
-			if (bsscfg->associated)
-				rs = &current_bss->rateset;
-			else
-				rs = &wlc->default_bss->rateset;
-
-			if (len < (int)(rs->count + sizeof(rs->count))) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-
-			/* Copy only legacy rateset section */
-			ret_rs->count = rs->count;
-			bcopy(&rs->rates, &ret_rs->rates, rs->count);
-			break;
-		}
-
-	case WLC_GET_RATESET:{
-			wlc_rateset_t rs;
-			wl_rateset_t *ret_rs = (wl_rateset_t *) arg;
-
-			memset(&rs, 0, sizeof(wlc_rateset_t));
-			wlc_default_rateset(wlc, (wlc_rateset_t *) &rs);
-
-			if (len < (int)(rs.count + sizeof(rs.count))) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-
-			/* Copy only legacy rateset section */
-			ret_rs->count = rs.count;
-			bcopy(&rs.rates, &ret_rs->rates, rs.count);
-			break;
-		}
-
-	case WLC_SET_RATESET:{
-			wlc_rateset_t rs;
-			wl_rateset_t *in_rs = (wl_rateset_t *) arg;
-
-			if (len < (int)(in_rs->count + sizeof(in_rs->count))) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-
-			if (in_rs->count > WLC_NUMRATES) {
-				bcmerror = BCME_BUFTOOLONG;
-				break;
-			}
-
-			memset(&rs, 0, sizeof(wlc_rateset_t));
-
-			/* Copy only legacy rateset section */
-			rs.count = in_rs->count;
-			bcopy(&in_rs->rates, &rs.rates, rs.count);
-
-			/* merge rateset coming in with the current mcsset */
-			if (N_ENAB(wlc->pub)) {
-				if (bsscfg->associated)
-					bcopy(&current_bss->rateset.mcs[0],
-					      rs.mcs, MCSSET_LEN);
-				else
-					bcopy(&wlc->default_bss->rateset.mcs[0],
-					      rs.mcs, MCSSET_LEN);
-			}
-
-			bcmerror = wlc_set_rateset(wlc, &rs);
-
-			if (!bcmerror)
-				wlc_ofdm_rateset_war(wlc);
-
-			break;
-		}
-
-	case WLC_GET_BCNPRD:
-		if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
-			*pval = current_bss->beacon_period;
-		else
-			*pval = wlc->default_bss->beacon_period;
-		break;
-
-	case WLC_SET_BCNPRD:
-		/* range [1, 0xffff] */
-		if (val >= DOT11_MIN_BEACON_PERIOD
-		    && val <= DOT11_MAX_BEACON_PERIOD) {
-			wlc->default_bss->beacon_period = (u16) val;
-		} else
-			bcmerror = BCME_RANGE;
-		break;
-
-	case WLC_GET_DTIMPRD:
-		if (BSSCFG_STA(bsscfg) && bsscfg->BSS && bsscfg->associated)
-			*pval = current_bss->dtim_period;
-		else
-			*pval = wlc->default_bss->dtim_period;
-		break;
-
-	case WLC_SET_DTIMPRD:
-		/* range [1, 0xff] */
-		if (val >= DOT11_MIN_DTIM_PERIOD
-		    && val <= DOT11_MAX_DTIM_PERIOD) {
-			wlc->default_bss->dtim_period = (u8) val;
-		} else
-			bcmerror = BCME_RANGE;
-		break;
-
-#ifdef SUPPORT_PS
-	case WLC_GET_PM:
-		*pval = wlc->PM;
-		break;
-
-	case WLC_SET_PM:
-		if ((val >= PM_OFF) && (val <= PM_MAX)) {
-			wlc->PM = (u8) val;
-			if (wlc->pub->up) {
-			}
-			/* Change watchdog driver to align watchdog with tbtt if possible */
-			wlc_watchdog_upd(wlc, PS_ALLOWED(wlc));
-		} else
-			bcmerror = BCME_ERROR;
-		break;
-#endif				/* SUPPORT_PS */
-
-#ifdef SUPPORT_PS
-#ifdef BCMDBG
-	case WLC_GET_WAKE:
-		if (AP_ENAB(wlc->pub)) {
-			bcmerror = BCME_NOTSTA;
-			break;
-		}
-		*pval = wlc->wake;
-		break;
-
-	case WLC_SET_WAKE:
-		if (AP_ENAB(wlc->pub)) {
-			bcmerror = BCME_NOTSTA;
-			break;
-		}
-
-		wlc->wake = val ? true : false;
-
-		/* if down, we're done */
-		if (!wlc->pub->up)
-			break;
-
-		/* apply to the mac */
-		wlc_set_ps_ctrl(wlc);
-		break;
-#endif				/* BCMDBG */
-#endif				/* SUPPORT_PS */
-
-	case WLC_GET_REVINFO:
-		bcmerror = wlc_get_revision_info(wlc, arg, (uint) len);
-		break;
-
-	case WLC_GET_AP:
-		*pval = (int)AP_ENAB(wlc->pub);
-		break;
-
-	case WLC_GET_ATIM:
-		if (bsscfg->associated)
-			*pval = (int)current_bss->atim_window;
-		else
-			*pval = (int)wlc->default_bss->atim_window;
-		break;
-
-	case WLC_SET_ATIM:
-		wlc->default_bss->atim_window = (u32) val;
-		break;
-
-	case WLC_GET_PKTCNTS:{
-			get_pktcnt_t *pktcnt = (get_pktcnt_t *) pval;
-			if (WLC_UPDATE_STATS(wlc))
-				wlc_statsupd(wlc);
-			pktcnt->rx_good_pkt = WLCNTVAL(wlc->pub->_cnt->rxframe);
-			pktcnt->rx_bad_pkt = WLCNTVAL(wlc->pub->_cnt->rxerror);
-			pktcnt->tx_good_pkt =
-			    WLCNTVAL(wlc->pub->_cnt->txfrmsnt);
-			pktcnt->tx_bad_pkt =
-			    WLCNTVAL(wlc->pub->_cnt->txerror) +
-			    WLCNTVAL(wlc->pub->_cnt->txfail);
-			if (len >= (int)sizeof(get_pktcnt_t)) {
-				/* Be backward compatible - only if buffer is large enough  */
-				pktcnt->rx_ocast_good_pkt =
-				    WLCNTVAL(wlc->pub->_cnt->rxmfrmocast);
-			}
-			break;
-		}
-
-#ifdef SUPPORT_HWKEY
-	case WLC_GET_WSEC:
-		bcmerror =
-		    wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_GET,
-				 wlcif);
-		break;
-
-	case WLC_SET_WSEC:
-		bcmerror =
-		    wlc_iovar_op(wlc, "wsec", NULL, 0, arg, len, IOV_SET,
-				 wlcif);
-		break;
-
-	case WLC_GET_WPA_AUTH:
-		*pval = (int)bsscfg->WPA_auth;
-		break;
-
-	case WLC_SET_WPA_AUTH:
-		/* change of WPA_Auth modifies the PS_ALLOWED state */
-		if (BSSCFG_STA(bsscfg)) {
-			bsscfg->WPA_auth = (u16) val;
-		} else
-			bsscfg->WPA_auth = (u16) val;
-		break;
-#endif				/* SUPPORT_HWKEY */
-
-	case WLC_GET_BANDLIST:
-		/* count of number of bands, followed by each band type */
-		*pval++ = NBANDS(wlc);
-		*pval++ = wlc->band->bandtype;
-		if (NBANDS(wlc) > 1)
-			*pval++ = wlc->bandstate[OTHERBANDUNIT(wlc)]->bandtype;
-		break;
-
-	case WLC_GET_BAND:
-		*pval = wlc->bandlocked ? wlc->band->bandtype : WLC_BAND_AUTO;
-		break;
-
-	case WLC_GET_PHYLIST:
-		{
-			unsigned char *cp = arg;
-			if (len < 3) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-
-			if (WLCISNPHY(wlc->band)) {
-				*cp++ = 'n';
-			} else if (WLCISLCNPHY(wlc->band)) {
-				*cp++ = 'c';
-			} else if (WLCISSSLPNPHY(wlc->band)) {
-				*cp++ = 's';
-			}
-			*cp = '\0';
-			break;
-		}
-
-	case WLC_GET_SHORTSLOT:
-		*pval = wlc->shortslot;
-		break;
-
-	case WLC_GET_SHORTSLOT_OVERRIDE:
-		*pval = wlc->shortslot_override;
-		break;
-
-	case WLC_SET_SHORTSLOT_OVERRIDE:
-		if ((val != WLC_SHORTSLOT_AUTO) &&
-		    (val != WLC_SHORTSLOT_OFF) && (val != WLC_SHORTSLOT_ON)) {
-			bcmerror = BCME_RANGE;
-			break;
-		}
-
-		wlc->shortslot_override = (s8) val;
-
-		/* shortslot is an 11g feature, so no more work if we are
-		 * currently on the 5G band
-		 */
-		if (BAND_5G(wlc->band->bandtype))
-			break;
-
-		if (wlc->pub->up && wlc->pub->associated) {
-			/* let watchdog or beacon processing update shortslot */
-		} else if (wlc->pub->up) {
-			/* unassociated shortslot is off */
-			wlc_switch_shortslot(wlc, false);
-		} else {
-			/* driver is down, so just update the wlc_info value */
-			if (wlc->shortslot_override == WLC_SHORTSLOT_AUTO) {
-				wlc->shortslot = false;
-			} else {
-				wlc->shortslot =
-				    (wlc->shortslot_override ==
-				     WLC_SHORTSLOT_ON);
-			}
-		}
-
-		break;
-
-	case WLC_GET_LEGACY_ERP:
-		*pval = wlc->include_legacy_erp;
-		break;
-
-	case WLC_SET_LEGACY_ERP:
-		if (wlc->include_legacy_erp == bool_val)
-			break;
-
-		wlc->include_legacy_erp = bool_val;
-
-		if (AP_ENAB(wlc->pub) && wlc->clk) {
-			wlc_update_beacon(wlc);
-			wlc_update_probe_resp(wlc, true);
-		}
-		break;
-
-	case WLC_GET_GMODE:
-		if (wlc->band->bandtype == WLC_BAND_2G)
-			*pval = wlc->band->gmode;
-		else if (NBANDS(wlc) > 1)
-			*pval = wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode;
-		break;
-
-	case WLC_SET_GMODE:
-		if (!wlc->pub->associated)
-			bcmerror = wlc_set_gmode(wlc, (u8) val, true);
-		else {
-			bcmerror = BCME_ASSOCIATED;
-			break;
-		}
-		break;
-
-	case WLC_GET_GMODE_PROTECTION:
-		*pval = wlc->protection->_g;
-		break;
-
-	case WLC_GET_PROTECTION_CONTROL:
-		*pval = wlc->protection->overlap;
-		break;
-
-	case WLC_SET_PROTECTION_CONTROL:
-		if ((val != WLC_PROTECTION_CTL_OFF) &&
-		    (val != WLC_PROTECTION_CTL_LOCAL) &&
-		    (val != WLC_PROTECTION_CTL_OVERLAP)) {
-			bcmerror = BCME_RANGE;
-			break;
-		}
-
-		wlc_protection_upd(wlc, WLC_PROT_OVERLAP, (s8) val);
-
-		/* Current g_protection will sync up to the specified control alg in watchdog
-		 * if the driver is up and associated.
-		 * If the driver is down or not associated, the control setting has no effect.
-		 */
-		break;
-
-	case WLC_GET_GMODE_PROTECTION_OVERRIDE:
-		*pval = wlc->protection->g_override;
-		break;
-
-	case WLC_SET_GMODE_PROTECTION_OVERRIDE:
-		if ((val != WLC_PROTECTION_AUTO) &&
-		    (val != WLC_PROTECTION_OFF) && (val != WLC_PROTECTION_ON)) {
-			bcmerror = BCME_RANGE;
-			break;
-		}
-
-		wlc_protection_upd(wlc, WLC_PROT_G_OVR, (s8) val);
-
-		break;
-
-	case WLC_SET_SUP_RATESET_OVERRIDE:{
-			wlc_rateset_t rs, new;
-
-			/* copyin */
-			if (len < (int)sizeof(wlc_rateset_t)) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-			bcopy((char *)arg, (char *)&rs, sizeof(wlc_rateset_t));
-
-			/* check for bad count value */
-			if (rs.count > WLC_NUMRATES) {
-				bcmerror = BCME_BADRATESET;	/* invalid rateset */
-				break;
-			}
-
-			/* this command is only appropriate for gmode operation */
-			if (!(wlc->band->gmode ||
-			      ((NBANDS(wlc) > 1)
-			       && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
-				bcmerror = BCME_BADBAND;	/* gmode only command when not in gmode */
-				break;
-			}
-
-			/* check for an empty rateset to clear the override */
-			if (rs.count == 0) {
-				memset(&wlc->sup_rates_override, 0,
-				      sizeof(wlc_rateset_t));
-				break;
-			}
-
-			/* validate rateset by comparing pre and post sorted against 11g hw rates */
-			wlc_rateset_filter(&rs, &new, false, WLC_RATES_CCK_OFDM,
-					   RATE_MASK, BSS_N_ENAB(wlc, bsscfg));
-			wlc_rate_hwrs_filter_sort_validate(&new,
-							   &cck_ofdm_rates,
-							   false,
-							   wlc->stf->txstreams);
-			if (rs.count != new.count) {
-				bcmerror = BCME_BADRATESET;	/* invalid rateset */
-				break;
-			}
-
-			/* apply new rateset to the override */
-			bcopy((char *)&new, (char *)&wlc->sup_rates_override,
-			      sizeof(wlc_rateset_t));
-
-			/* update bcn and probe resp if needed */
-			if (wlc->pub->up && AP_ENAB(wlc->pub)
-			    && wlc->pub->associated) {
-				wlc_update_beacon(wlc);
-				wlc_update_probe_resp(wlc, true);
-			}
-			break;
-		}
-
-	case WLC_GET_SUP_RATESET_OVERRIDE:
-		/* this command is only appropriate for gmode operation */
-		if (!(wlc->band->gmode ||
-		      ((NBANDS(wlc) > 1)
-		       && wlc->bandstate[OTHERBANDUNIT(wlc)]->gmode))) {
-			bcmerror = BCME_BADBAND;	/* gmode only command when not in gmode */
-			break;
-		}
-		if (len < (int)sizeof(wlc_rateset_t)) {
-			bcmerror = BCME_BUFTOOSHORT;
-			break;
-		}
-		bcopy((char *)&wlc->sup_rates_override, (char *)arg,
-		      sizeof(wlc_rateset_t));
-
-		break;
-
-	case WLC_GET_PRB_RESP_TIMEOUT:
-		*pval = wlc->prb_resp_timeout;
-		break;
-
-	case WLC_SET_PRB_RESP_TIMEOUT:
-		if (wlc->pub->up) {
-			bcmerror = BCME_NOTDOWN;
-			break;
-		}
-		if (val < 0 || val >= 0xFFFF) {
-			bcmerror = BCME_RANGE;	/* bad value */
-			break;
-		}
-		wlc->prb_resp_timeout = (u16) val;
-		break;
-
-	case WLC_GET_KEY_PRIMARY:{
-			wsec_key_t *key;
-
-			/* treat the 'val' parm as the key id */
-			key = WSEC_BSS_DEFAULT_KEY(bsscfg);
-			if (key != NULL) {
-				*pval = key->id == val ? true : false;
-			} else {
-				bcmerror = BCME_BADKEYIDX;
-			}
-			break;
-		}
-
-	case WLC_SET_KEY_PRIMARY:{
-			wsec_key_t *key, *old_key;
-
-			bcmerror = BCME_BADKEYIDX;
-
-			/* treat the 'val' parm as the key id */
-			for (i = 0; i < WSEC_MAX_DEFAULT_KEYS; i++) {
-				key = bsscfg->bss_def_keys[i];
-				if (key != NULL && key->id == val) {
-					old_key = WSEC_BSS_DEFAULT_KEY(bsscfg);
-					if (old_key != NULL)
-						old_key->flags &=
-						    ~WSEC_PRIMARY_KEY;
-					key->flags |= WSEC_PRIMARY_KEY;
-					bsscfg->wsec_index = i;
-					bcmerror = BCME_OK;
-				}
-			}
-			break;
-		}
-
-#ifdef BCMDBG
-	case WLC_INIT:
-		wl_init(wlc->wl);
-		break;
-#endif
-
-	case WLC_SET_VAR:
-	case WLC_GET_VAR:{
-			char *name;
-			/* validate the name value */
-			name = (char *)arg;
-			for (i = 0; i < (uint) len && *name != '\0';
-			     i++, name++)
-				;
-
-			if (i == (uint) len) {
-				bcmerror = BCME_BUFTOOSHORT;
-				break;
-			}
-			i++;	/* include the null in the string length */
-
-			if (cmd == WLC_GET_VAR) {
-				bcmerror =
-				    wlc_iovar_op(wlc, arg,
-						 (void *)((s8 *) arg + i),
-						 len - i, arg, len, IOV_GET,
-						 wlcif);
-			} else
-				bcmerror =
-				    wlc_iovar_op(wlc, arg, NULL, 0,
-						 (void *)((s8 *) arg + i),
-						 len - i, IOV_SET, wlcif);
-
-			break;
-		}
-
-	case WLC_SET_WSEC_PMK:
-		bcmerror = BCME_UNSUPPORTED;
-		break;
-
-#if defined(BCMDBG)
-	case WLC_CURRENT_PWR:
-		if (!wlc->pub->up)
-			bcmerror = BCME_NOTUP;
-		else
-			bcmerror = wlc_get_current_txpwr(wlc, arg, len);
-		break;
-#endif
-
-	case WLC_LAST:
-		WL_ERROR("%s: WLC_LAST\n", __func__);
-	}
- done:
-
-	if (bcmerror) {
-		if (VALID_BCMERROR(bcmerror))
-			wlc->pub->bcmerror = bcmerror;
-		else {
-			bcmerror = 0;
-		}
-
-	}
-	/* BMAC_NOTE: for HIGH_ONLY driver, this seems being called after RPC bus failed */
-	/* In hw_off condition, IOCTLs that reach here are deemed safe but taclear would
-	 * certainly result in getting -1 for register reads. So skip ta_clear altogether
-	 */
-	if (!(wlc->pub->hw_off))
-		ASSERT(wlc_bmac_taclear(wlc->hw, ta_ok) || !ta_ok);
-
-	return bcmerror;
-}
-
-#if defined(BCMDBG)
-/* consolidated register access ioctl error checking */
-int wlc_iocregchk(struct wlc_info *wlc, uint band)
-{
-	/* if band is specified, it must be the current band */
-	if ((band != WLC_BAND_AUTO) && (band != (uint) wlc->band->bandtype))
-		return BCME_BADBAND;
-
-	/* if multiband and band is not specified, band must be locked */
-	if ((band == WLC_BAND_AUTO) && IS_MBAND_UNLOCKED(wlc))
-		return BCME_NOTBANDLOCKED;
-
-	/* must have core clocks */
-	if (!wlc->clk)
-		return BCME_NOCLK;
-
-	return 0;
-}
-#endif				/* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-/* For some ioctls, make sure that the pi pointer matches the current phy */
-int wlc_iocpichk(struct wlc_info *wlc, uint phytype)
-{
-	if (wlc->band->phytype != phytype)
-		return BCME_BADBAND;
-	return 0;
-}
-#endif
-
-/* Look up the given var name in the given table */
-static const bcm_iovar_t *wlc_iovar_lookup(const bcm_iovar_t *table,
-					   const char *name)
-{
-	const bcm_iovar_t *vi;
-	const char *lookup_name;
-
-	/* skip any ':' delimited option prefixes */
-	lookup_name = strrchr(name, ':');
-	if (lookup_name != NULL)
-		lookup_name++;
-	else
-		lookup_name = name;
-
-	ASSERT(table != NULL);
-
-	for (vi = table; vi->name; vi++) {
-		if (!strcmp(vi->name, lookup_name))
-			return vi;
-	}
-	/* ran to end of table */
-
-	return NULL;		/* var name not found */
-}
-
-/* simplified integer get interface for common WLC_GET_VAR ioctl handler */
-int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg)
-{
-	return wlc_iovar_op(wlc, name, NULL, 0, arg, sizeof(s32), IOV_GET,
-			    NULL);
-}
-
-/* simplified integer set interface for common WLC_SET_VAR ioctl handler */
-int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg)
-{
-	return wlc_iovar_op(wlc, name, NULL, 0, (void *)&arg, sizeof(arg),
-			    IOV_SET, NULL);
-}
-
-/* simplified s8 get interface for common WLC_GET_VAR ioctl handler */
-int wlc_iovar_gets8(struct wlc_info *wlc, const char *name, s8 *arg)
-{
-	int iovar_int;
-	int err;
-
-	err =
-	    wlc_iovar_op(wlc, name, NULL, 0, &iovar_int, sizeof(iovar_int),
-			 IOV_GET, NULL);
-	if (!err)
-		*arg = (s8) iovar_int;
-
-	return err;
-}
-
-/*
- * register iovar table, watchdog and down handlers.
- * calling function must keep 'iovars' until wlc_module_unregister is called.
- * 'iovar' must have the last entry's name field being NULL as terminator.
- */
-int wlc_module_register(struct wlc_pub *pub, const bcm_iovar_t *iovars,
-			const char *name, void *hdl, iovar_fn_t i_fn,
-			watchdog_fn_t w_fn, down_fn_t d_fn)
-{
-	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
-	int i;
-
-	ASSERT(name != NULL);
-	ASSERT(i_fn != NULL || w_fn != NULL || d_fn != NULL);
-
-	/* find an empty entry and just add, no duplication check! */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (wlc->modulecb[i].name[0] == '\0') {
-			strncpy(wlc->modulecb[i].name, name,
-				sizeof(wlc->modulecb[i].name) - 1);
-			wlc->modulecb[i].iovars = iovars;
-			wlc->modulecb[i].hdl = hdl;
-			wlc->modulecb[i].iovar_fn = i_fn;
-			wlc->modulecb[i].watchdog_fn = w_fn;
-			wlc->modulecb[i].down_fn = d_fn;
-			return 0;
-		}
-	}
-
-	/* it is time to increase the capacity */
-	ASSERT(i < WLC_MAXMODULES);
-	return BCME_NORESOURCE;
-}
-
-/* unregister module callbacks */
-int wlc_module_unregister(struct wlc_pub *pub, const char *name, void *hdl)
-{
-	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
-	int i;
-
-	if (wlc == NULL)
-		return BCME_NOTFOUND;
-
-	ASSERT(name != NULL);
-
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (!strcmp(wlc->modulecb[i].name, name) &&
-		    (wlc->modulecb[i].hdl == hdl)) {
-			memset(&wlc->modulecb[i], 0, sizeof(modulecb_t));
-			return 0;
-		}
-	}
-
-	/* table not found! */
-	return BCME_NOTFOUND;
-}
-
-/* Write WME tunable parameters for retransmit/max rate from wlc struct to ucode */
-static void wlc_wme_retries_write(struct wlc_info *wlc)
-{
-	int ac;
-
-	/* Need clock to do this */
-	if (!wlc->clk)
-		return;
-
-	for (ac = 0; ac < AC_COUNT; ac++) {
-		wlc_write_shm(wlc, M_AC_TXLMT_ADDR(ac), wlc->wme_retries[ac]);
-	}
-}
-
-/* Get or set an iovar.  The params/p_len pair specifies any additional
- * qualifying parameters (e.g. an "element index") for a get, while the
- * arg/len pair is the buffer for the value to be set or retrieved.
- * Operation (get/set) is specified by the last argument.
- * interface context provided by wlcif
- *
- * All pointers may point into the same buffer.
- */
-int
-wlc_iovar_op(struct wlc_info *wlc, const char *name,
-	     void *params, int p_len, void *arg, int len,
-	     bool set, struct wlc_if *wlcif)
-{
-	int err = 0;
-	int val_size;
-	const bcm_iovar_t *vi = NULL;
-	u32 actionid;
-	int i;
-
-	ASSERT(name != NULL);
-
-	ASSERT(len >= 0);
-
-	/* Get MUST have return space */
-	ASSERT(set || (arg && len));
-
-	ASSERT(!(wlc->pub->hw_off && wlc->pub->up));
-
-	/* Set does NOT take qualifiers */
-	ASSERT(!set || (!params && !p_len));
-
-	if (!set && (len == sizeof(int)) &&
-	    !(IS_ALIGNED((unsigned long)(arg), (uint) sizeof(int)))) {
-		WL_ERROR("wl%d: %s unaligned get ptr for %s\n",
-			 wlc->pub->unit, __func__, name);
-		ASSERT(0);
-	}
-
-	/* find the given iovar name */
-	for (i = 0; i < WLC_MAXMODULES; i++) {
-		if (!wlc->modulecb[i].iovars)
-			continue;
-		vi = wlc_iovar_lookup(wlc->modulecb[i].iovars, name);
-		if (vi)
-			break;
-	}
-	/* iovar name not found */
-	if (i >= WLC_MAXMODULES) {
-		err = BCME_UNSUPPORTED;
-		goto exit;
-	}
-
-	/* set up 'params' pointer in case this is a set command so that
-	 * the convenience int and bool code can be common to set and get
-	 */
-	if (params == NULL) {
-		params = arg;
-		p_len = len;
-	}
-
-	if (vi->type == IOVT_VOID)
-		val_size = 0;
-	else if (vi->type == IOVT_BUFFER)
-		val_size = len;
-	else
-		/* all other types are integer sized */
-		val_size = sizeof(int);
-
-	actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
-
-	/* Do the actual parameter implementation */
-	err = wlc->modulecb[i].iovar_fn(wlc->modulecb[i].hdl, vi, actionid,
-					name, params, p_len, arg, len, val_size,
-					wlcif);
-
- exit:
-	return err;
-}
-
-int
-wlc_iovar_check(struct wlc_pub *pub, const bcm_iovar_t *vi, void *arg, int len,
-		bool set)
-{
-	struct wlc_info *wlc = (struct wlc_info *) pub->wlc;
-	int err = 0;
-	s32 int_val = 0;
-
-	/* check generic condition flags */
-	if (set) {
-		if (((vi->flags & IOVF_SET_DOWN) && wlc->pub->up) ||
-		    ((vi->flags & IOVF_SET_UP) && !wlc->pub->up)) {
-			err = (wlc->pub->up ? BCME_NOTDOWN : BCME_NOTUP);
-		} else if ((vi->flags & IOVF_SET_BAND)
-			   && IS_MBAND_UNLOCKED(wlc)) {
-			err = BCME_NOTBANDLOCKED;
-		} else if ((vi->flags & IOVF_SET_CLK) && !wlc->clk) {
-			err = BCME_NOCLK;
-		}
-	} else {
-		if (((vi->flags & IOVF_GET_DOWN) && wlc->pub->up) ||
-		    ((vi->flags & IOVF_GET_UP) && !wlc->pub->up)) {
-			err = (wlc->pub->up ? BCME_NOTDOWN : BCME_NOTUP);
-		} else if ((vi->flags & IOVF_GET_BAND)
-			   && IS_MBAND_UNLOCKED(wlc)) {
-			err = BCME_NOTBANDLOCKED;
-		} else if ((vi->flags & IOVF_GET_CLK) && !wlc->clk) {
-			err = BCME_NOCLK;
-		}
-	}
-
-	if (err)
-		goto exit;
-
-	/* length check on io buf */
-	err = bcm_iovar_lencheck(vi, arg, len, set);
-	if (err)
-		goto exit;
-
-	/* On set, check value ranges for integer types */
-	if (set) {
-		switch (vi->type) {
-		case IOVT_BOOL:
-		case IOVT_INT8:
-		case IOVT_INT16:
-		case IOVT_INT32:
-		case IOVT_UINT8:
-		case IOVT_UINT16:
-		case IOVT_UINT32:
-			bcopy(arg, &int_val, sizeof(int));
-			err = wlc_iovar_rangecheck(wlc, int_val, vi);
-			break;
-		}
-	}
- exit:
-	return err;
-}
-
-/* handler for iovar table wlc_iovars */
-/*
- * IMPLEMENTATION NOTE: In order to avoid checking for get/set in each
- * iovar case, the switch statement maps the iovar id into separate get
- * and set values.  If you add a new iovar to the switch you MUST use
- * IOV_GVAL and/or IOV_SVAL in the case labels to avoid conflict with
- * another case.
- * Please use params for additional qualifying parameters.
- */
-int
-wlc_doiovar(void *hdl, const bcm_iovar_t *vi, u32 actionid,
-	    const char *name, void *params, uint p_len, void *arg, int len,
-	    int val_size, struct wlc_if *wlcif)
-{
-	struct wlc_info *wlc = hdl;
-	wlc_bsscfg_t *bsscfg;
-	int err = 0;
-	s32 int_val = 0;
-	s32 int_val2 = 0;
-	s32 *ret_int_ptr;
-	bool bool_val;
-	bool bool_val2;
-	wlc_bss_info_t *current_bss;
-
-	WL_TRACE("wl%d: %s\n", wlc->pub->unit, __func__);
-
-	bsscfg = NULL;
-	current_bss = NULL;
-
-	err = wlc_iovar_check(wlc->pub, vi, arg, len, IOV_ISSET(actionid));
-	if (err != 0)
-		return err;
-
-	/* convenience int and bool vals for first 8 bytes of buffer */
-	if (p_len >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
-
-	if (p_len >= (int)sizeof(int_val) * 2)
-		bcopy((void *)((unsigned long)params + sizeof(int_val)), &int_val2,
-		      sizeof(int_val));
-
-	/* convenience int ptr for 4-byte gets (requires int aligned arg) */
-	ret_int_ptr = (s32 *) arg;
-
-	bool_val = (int_val != 0) ? true : false;
-	bool_val2 = (int_val2 != 0) ? true : false;
-
-	WL_TRACE("wl%d: %s: id %d\n",
-		 wlc->pub->unit, __func__, IOV_ID(actionid));
-	/* Do the actual parameter implementation */
-	switch (actionid) {
-
-	case IOV_GVAL(IOV_QTXPOWER):{
-			uint qdbm;
-			bool override;
-
-			err = wlc_phy_txpower_get(wlc->band->pi, &qdbm,
-				&override);
-			if (err != BCME_OK)
-				return err;
-
-			/* Return qdbm units */
-			*ret_int_ptr =
-			    qdbm | (override ? WL_TXPWR_OVERRIDE : 0);
-			break;
-		}
-
-		/* As long as override is false, this only sets the *user* targets.
-		   User can twiddle this all he wants with no harm.
-		   wlc_phy_txpower_set() explicitly sets override to false if
-		   not internal or test.
-		 */
-	case IOV_SVAL(IOV_QTXPOWER):{
-			u8 qdbm;
-			bool override;
-
-			/* Remove override bit and clip to max qdbm value */
-			qdbm = (u8)min_t(u32, (int_val & ~WL_TXPWR_OVERRIDE), 0xff);
-			/* Extract override setting */
-			override = (int_val & WL_TXPWR_OVERRIDE) ? true : false;
-			err =
-			    wlc_phy_txpower_set(wlc->band->pi, qdbm, override);
-			break;
-		}
-
-	case IOV_GVAL(IOV_MPC):
-		*ret_int_ptr = (s32) wlc->mpc;
-		break;
-
-	case IOV_SVAL(IOV_MPC):
-		wlc->mpc = bool_val;
-		wlc_radio_mpc_upd(wlc);
-
-		break;
-
-	case IOV_GVAL(IOV_BCN_LI_BCN):
-		*ret_int_ptr = wlc->bcn_li_bcn;
-		break;
-
-	case IOV_SVAL(IOV_BCN_LI_BCN):
-		wlc->bcn_li_bcn = (u8) int_val;
-		if (wlc->pub->up)
-			wlc_bcn_li_upd(wlc);
-		break;
-
-	default:
-		WL_ERROR("wl%d: %s: unsupported\n", wlc->pub->unit, __func__);
-		err = BCME_UNSUPPORTED;
-		break;
-	}
-
-	goto exit;		/* avoid unused label warning */
-
- exit:
-	return err;
-}
-
-static int
-wlc_iovar_rangecheck(struct wlc_info *wlc, u32 val, const bcm_iovar_t *vi)
-{
-	int err = 0;
-	u32 min_val = 0;
-	u32 max_val = 0;
-
-	/* Only ranged integers are checked */
-	switch (vi->type) {
-	case IOVT_INT32:
-		max_val |= 0x7fffffff;
-		/* fall through */
-	case IOVT_INT16:
-		max_val |= 0x00007fff;
-		/* fall through */
-	case IOVT_INT8:
-		max_val |= 0x0000007f;
-		min_val = ~max_val;
-		if (vi->flags & IOVF_NTRL)
-			min_val = 1;
-		else if (vi->flags & IOVF_WHL)
-			min_val = 0;
-		/* Signed values are checked against max_val and min_val */
-		if ((s32) val < (s32) min_val
-		    || (s32) val > (s32) max_val)
-			err = BCME_RANGE;
-		break;
-
-	case IOVT_UINT32:
-		max_val |= 0xffffffff;
-		/* fall through */
-	case IOVT_UINT16:
-		max_val |= 0x0000ffff;
-		/* fall through */
-	case IOVT_UINT8:
-		max_val |= 0x000000ff;
-		if (vi->flags & IOVF_NTRL)
-			min_val = 1;
-		if ((val < min_val) || (val > max_val))
-			err = BCME_RANGE;
-		break;
-	}
-
-	return err;
-}
-
-#ifdef BCMDBG
-static const char *supr_reason[] = {
-	"None", "PMQ Entry", "Flush request",
-	"Previous frag failure", "Channel mismatch",
-	"Lifetime Expiry", "Underflow"
-};
-
-static void wlc_print_txs_status(u16 s)
-{
-	printf("[15:12]  %d  frame attempts\n", (s & TX_STATUS_FRM_RTX_MASK) >>
-	       TX_STATUS_FRM_RTX_SHIFT);
-	printf(" [11:8]  %d  rts attempts\n", (s & TX_STATUS_RTS_RTX_MASK) >>
-	       TX_STATUS_RTS_RTX_SHIFT);
-	printf("    [7]  %d  PM mode indicated\n",
-	       ((s & TX_STATUS_PMINDCTD) ? 1 : 0));
-	printf("    [6]  %d  intermediate status\n",
-	       ((s & TX_STATUS_INTERMEDIATE) ? 1 : 0));
-	printf("    [5]  %d  AMPDU\n", (s & TX_STATUS_AMPDU) ? 1 : 0);
-	printf("  [4:2]  %d  Frame Suppressed Reason (%s)\n",
-	       ((s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT),
-	       supr_reason[(s & TX_STATUS_SUPR_MASK) >> TX_STATUS_SUPR_SHIFT]);
-	printf("    [1]  %d  acked\n", ((s & TX_STATUS_ACK_RCV) ? 1 : 0));
-}
-#endif				/* BCMDBG */
-
-void wlc_print_txstatus(tx_status_t *txs)
-{
-#if defined(BCMDBG)
-	u16 s = txs->status;
-	u16 ackphyrxsh = txs->ackphyrxsh;
-
-	printf("\ntxpkt (MPDU) Complete\n");
-
-	printf("FrameID: %04x   ", txs->frameid);
-	printf("TxStatus: %04x", s);
-	printf("\n");
-#ifdef BCMDBG
-	wlc_print_txs_status(s);
-#endif
-	printf("LastTxTime: %04x ", txs->lasttxtime);
-	printf("Seq: %04x ", txs->sequence);
-	printf("PHYTxStatus: %04x ", txs->phyerr);
-	printf("RxAckRSSI: %04x ",
-	       (ackphyrxsh & PRXS1_JSSI_MASK) >> PRXS1_JSSI_SHIFT);
-	printf("RxAckSQ: %04x", (ackphyrxsh & PRXS1_SQ_MASK) >> PRXS1_SQ_SHIFT);
-	printf("\n");
-#endif				/* defined(BCMDBG) */
-}
-
-#define MACSTATUPD(name) \
-	wlc_ctrupd_cache(macstats.name, &wlc->core->macstat_snapshot->name, &wlc->pub->_cnt->name)
-
-void wlc_statsupd(struct wlc_info *wlc)
-{
-	int i;
-#ifdef BCMDBG
-	u16 delta;
-	u16 rxf0ovfl;
-	u16 txfunfl[NFIFO];
-#endif				/* BCMDBG */
-
-	/* if driver down, make no sense to update stats */
-	if (!wlc->pub->up)
-		return;
-
-#ifdef BCMDBG
-	/* save last rx fifo 0 overflow count */
-	rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
-
-	/* save last tx fifo  underflow count */
-	for (i = 0; i < NFIFO; i++)
-		txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
-#endif				/* BCMDBG */
-
-#ifdef BCMDBG
-	/* check for rx fifo 0 overflow */
-	delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
-	if (delta)
-		WL_ERROR("wl%d: %u rx fifo 0 overflows!\n",
-			 wlc->pub->unit, delta);
-
-	/* check for tx fifo underflows */
-	for (i = 0; i < NFIFO; i++) {
-		delta =
-		    (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
-			      txfunfl[i]);
-		if (delta)
-			WL_ERROR("wl%d: %u tx fifo %d underflows!\n",
-				 wlc->pub->unit, delta, i);
-	}
-#endif				/* BCMDBG */
-
-	/* dot11 counter update */
-
-	WLCNTSET(wlc->pub->_cnt->txrts,
-		 (wlc->pub->_cnt->rxctsucast -
-		  wlc->pub->_cnt->d11cnt_txrts_off));
-	WLCNTSET(wlc->pub->_cnt->rxcrc,
-		 (wlc->pub->_cnt->rxbadfcs - wlc->pub->_cnt->d11cnt_rxcrc_off));
-	WLCNTSET(wlc->pub->_cnt->txnocts,
-		 ((wlc->pub->_cnt->txrtsfrm - wlc->pub->_cnt->rxctsucast) -
-		  wlc->pub->_cnt->d11cnt_txnocts_off));
-
-	/* merge counters from dma module */
-	for (i = 0; i < NFIFO; i++) {
-		if (wlc->hw->di[i]) {
-			WLCNTADD(wlc->pub->_cnt->txnobuf,
-				 (wlc->hw->di[i])->txnobuf);
-			WLCNTADD(wlc->pub->_cnt->rxnobuf,
-				 (wlc->hw->di[i])->rxnobuf);
-			WLCNTADD(wlc->pub->_cnt->rxgiant,
-				 (wlc->hw->di[i])->rxgiants);
-			dma_counterreset(wlc->hw->di[i]);
-		}
-	}
-
-	/*
-	 * Aggregate transmit and receive errors that probably resulted
-	 * in the loss of a frame are computed on the fly.
-	 */
-	WLCNTSET(wlc->pub->_cnt->txerror,
-		 wlc->pub->_cnt->txnobuf + wlc->pub->_cnt->txnoassoc +
-		 wlc->pub->_cnt->txuflo + wlc->pub->_cnt->txrunt +
-		 wlc->pub->_cnt->dmade + wlc->pub->_cnt->dmada +
-		 wlc->pub->_cnt->dmape);
-	WLCNTSET(wlc->pub->_cnt->rxerror,
-		 wlc->pub->_cnt->rxoflo + wlc->pub->_cnt->rxnobuf +
-		 wlc->pub->_cnt->rxfragerr + wlc->pub->_cnt->rxrunt +
-		 wlc->pub->_cnt->rxgiant + wlc->pub->_cnt->rxnoscb +
-		 wlc->pub->_cnt->rxbadsrcmac);
-	for (i = 0; i < NFIFO; i++)
-		WLCNTADD(wlc->pub->_cnt->rxerror, wlc->pub->_cnt->rxuflo[i]);
-}
-
-bool wlc_chipmatch(u16 vendor, u16 device)
-{
-	if (vendor != VENDOR_BROADCOM) {
-		WL_ERROR("wlc_chipmatch: unknown vendor id %04x\n", vendor);
-		return false;
-	}
-
-	if ((device == BCM43224_D11N_ID) || (device == BCM43225_D11N2G_ID))
-		return true;
-
-	if (device == BCM4313_D11N2G_ID)
-		return true;
-	if ((device == BCM43236_D11N_ID) || (device == BCM43236_D11N2G_ID))
-		return true;
-
-	WL_ERROR("wlc_chipmatch: unknown device id %04x\n", device);
-	return false;
-}
-
-#if defined(BCMDBG)
-void wlc_print_txdesc(d11txh_t *txh)
-{
-	u16 mtcl = ltoh16(txh->MacTxControlLow);
-	u16 mtch = ltoh16(txh->MacTxControlHigh);
-	u16 mfc = ltoh16(txh->MacFrameControl);
-	u16 tfest = ltoh16(txh->TxFesTimeNormal);
-	u16 ptcw = ltoh16(txh->PhyTxControlWord);
-	u16 ptcw_1 = ltoh16(txh->PhyTxControlWord_1);
-	u16 ptcw_1_Fbr = ltoh16(txh->PhyTxControlWord_1_Fbr);
-	u16 ptcw_1_Rts = ltoh16(txh->PhyTxControlWord_1_Rts);
-	u16 ptcw_1_FbrRts = ltoh16(txh->PhyTxControlWord_1_FbrRts);
-	u16 mainrates = ltoh16(txh->MainRates);
-	u16 xtraft = ltoh16(txh->XtraFrameTypes);
-	u8 *iv = txh->IV;
-	u8 *ra = txh->TxFrameRA;
-	u16 tfestfb = ltoh16(txh->TxFesTimeFallback);
-	u8 *rtspfb = txh->RTSPLCPFallback;
-	u16 rtsdfb = ltoh16(txh->RTSDurFallback);
-	u8 *fragpfb = txh->FragPLCPFallback;
-	u16 fragdfb = ltoh16(txh->FragDurFallback);
-	u16 mmodelen = ltoh16(txh->MModeLen);
-	u16 mmodefbrlen = ltoh16(txh->MModeFbrLen);
-	u16 tfid = ltoh16(txh->TxFrameID);
-	u16 txs = ltoh16(txh->TxStatus);
-	u16 mnmpdu = ltoh16(txh->MaxNMpdus);
-	u16 mabyte = ltoh16(txh->MaxABytes_MRT);
-	u16 mabyte_f = ltoh16(txh->MaxABytes_FBR);
-	u16 mmbyte = ltoh16(txh->MinMBytes);
-
-	u8 *rtsph = txh->RTSPhyHeader;
-	struct dot11_rts_frame rts = txh->rts_frame;
-	char hexbuf[256];
-
-	/* add plcp header along with txh descriptor */
-	prhex("Raw TxDesc + plcp header", (unsigned char *) txh, sizeof(d11txh_t) + 48);
-
-	printf("TxCtlLow: %04x ", mtcl);
-	printf("TxCtlHigh: %04x ", mtch);
-	printf("FC: %04x ", mfc);
-	printf("FES Time: %04x\n", tfest);
-	printf("PhyCtl: %04x%s ", ptcw,
-	       (ptcw & PHY_TXC_SHORT_HDR) ? " short" : "");
-	printf("PhyCtl_1: %04x ", ptcw_1);
-	printf("PhyCtl_1_Fbr: %04x\n", ptcw_1_Fbr);
-	printf("PhyCtl_1_Rts: %04x ", ptcw_1_Rts);
-	printf("PhyCtl_1_Fbr_Rts: %04x\n", ptcw_1_FbrRts);
-	printf("MainRates: %04x ", mainrates);
-	printf("XtraFrameTypes: %04x ", xtraft);
-	printf("\n");
-
-	bcm_format_hex(hexbuf, iv, sizeof(txh->IV));
-	printf("SecIV:       %s\n", hexbuf);
-	bcm_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
-	printf("RA:          %s\n", hexbuf);
-
-	printf("Fb FES Time: %04x ", tfestfb);
-	bcm_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
-	printf("RTS PLCP: %s ", hexbuf);
-	printf("RTS DUR: %04x ", rtsdfb);
-	bcm_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
-	printf("PLCP: %s ", hexbuf);
-	printf("DUR: %04x", fragdfb);
-	printf("\n");
-
-	printf("MModeLen: %04x ", mmodelen);
-	printf("MModeFbrLen: %04x\n", mmodefbrlen);
-
-	printf("FrameID:     %04x\n", tfid);
-	printf("TxStatus:    %04x\n", txs);
-
-	printf("MaxNumMpdu:  %04x\n", mnmpdu);
-	printf("MaxAggbyte:  %04x\n", mabyte);
-	printf("MaxAggbyte_fb:  %04x\n", mabyte_f);
-	printf("MinByte:     %04x\n", mmbyte);
-
-	bcm_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
-	printf("RTS PLCP: %s ", hexbuf);
-	bcm_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
-	printf("RTS Frame: %s", hexbuf);
-	printf("\n");
-
-}
-#endif				/* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-void wlc_print_rxh(d11rxhdr_t *rxh)
-{
-	u16 len = rxh->RxFrameSize;
-	u16 phystatus_0 = rxh->PhyRxStatus_0;
-	u16 phystatus_1 = rxh->PhyRxStatus_1;
-	u16 phystatus_2 = rxh->PhyRxStatus_2;
-	u16 phystatus_3 = rxh->PhyRxStatus_3;
-	u16 macstatus1 = rxh->RxStatus1;
-	u16 macstatus2 = rxh->RxStatus2;
-	char flagstr[64];
-	char lenbuf[20];
-	static const bcm_bit_desc_t macstat_flags[] = {
-		{RXS_FCSERR, "FCSErr"},
-		{RXS_RESPFRAMETX, "Reply"},
-		{RXS_PBPRES, "PADDING"},
-		{RXS_DECATMPT, "DeCr"},
-		{RXS_DECERR, "DeCrErr"},
-		{RXS_BCNSENT, "Bcn"},
-		{0, NULL}
-	};
-
-	prhex("Raw RxDesc", (unsigned char *) rxh, sizeof(d11rxhdr_t));
-
-	bcm_format_flags(macstat_flags, macstatus1, flagstr, 64);
-
-	snprintf(lenbuf, sizeof(lenbuf), "0x%x", len);
-
-	printf("RxFrameSize:     %6s (%d)%s\n", lenbuf, len,
-	       (rxh->PhyRxStatus_0 & PRXS0_SHORTH) ? " short preamble" : "");
-	printf("RxPHYStatus:     %04x %04x %04x %04x\n",
-	       phystatus_0, phystatus_1, phystatus_2, phystatus_3);
-	printf("RxMACStatus:     %x %s\n", macstatus1, flagstr);
-	printf("RXMACaggtype: %x\n", (macstatus2 & RXS_AGGTYPE_MASK));
-	printf("RxTSFTime:       %04x\n", rxh->RxTSFTime);
-}
-#endif				/* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len)
-{
-	uint i, c;
-	char *p = buf;
-	char *endp = buf + SSID_FMT_BUF_LEN;
-
-	if (ssid_len > DOT11_MAX_SSID_LEN)
-		ssid_len = DOT11_MAX_SSID_LEN;
-
-	for (i = 0; i < ssid_len; i++) {
-		c = (uint) ssid[i];
-		if (c == '\\') {
-			*p++ = '\\';
-			*p++ = '\\';
-		} else if (isprint((unsigned char) c)) {
-			*p++ = (char)c;
-		} else {
-			p += snprintf(p, (endp - p), "\\x%02X", c);
-		}
-	}
-	*p = '\0';
-	ASSERT(p < endp);
-
-	return (int)(p - buf);
-}
-#endif				/* defined(BCMDBG) */
-
-u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate)
-{
-	return wlc_bmac_rate_shm_offset(wlc->hw, rate);
-}
-
-/* Callback for device removed */
-
-/*
- * Attempts to queue a packet onto a multiple-precedence queue,
- * if necessary evicting a lower precedence packet from the queue.
- *
- * 'prec' is the precedence number that has already been mapped
- * from the packet priority.
- *
- * Returns true if packet consumed (queued), false if not.
- */
-bool BCMFASTPATH
-wlc_prec_enq(struct wlc_info *wlc, struct pktq *q, void *pkt, int prec)
-{
-	return wlc_prec_enq_head(wlc, q, pkt, prec, false);
-}
-
-bool BCMFASTPATH
-wlc_prec_enq_head(struct wlc_info *wlc, struct pktq *q, struct sk_buff *pkt,
-		  int prec, bool head)
-{
-	struct sk_buff *p;
-	int eprec = -1;		/* precedence to evict from */
-
-	/* Determine precedence from which to evict packet, if any */
-	if (pktq_pfull(q, prec))
-		eprec = prec;
-	else if (pktq_full(q)) {
-		p = pktq_peek_tail(q, &eprec);
-		ASSERT(p != NULL);
-		if (eprec > prec) {
-			WL_ERROR("%s: Failing: eprec %d > prec %d\n",
-				 __func__, eprec, prec);
-			return false;
-		}
-	}
-
-	/* Evict if needed */
-	if (eprec >= 0) {
-		bool discard_oldest;
-
-		/* Detect queueing to unconfigured precedence */
-		ASSERT(!pktq_pempty(q, eprec));
-
-		discard_oldest = AC_BITMAP_TST(wlc->wme_dp, eprec);
-
-		/* Refuse newer packet unless configured to discard oldest */
-		if (eprec == prec && !discard_oldest) {
-			WL_ERROR("%s: No where to go, prec == %d\n",
-				 __func__, prec);
-			return false;
-		}
-
-		/* Evict packet according to discard policy */
-		p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q,
-									  eprec);
-		ASSERT(p != NULL);
-
-		/* Increment wme stats */
-		if (WME_ENAB(wlc->pub)) {
-			WLCNTINCR(wlc->pub->_wme_cnt->
-				  tx_failed[WME_PRIO2AC(p->priority)].packets);
-			WLCNTADD(wlc->pub->_wme_cnt->
-				 tx_failed[WME_PRIO2AC(p->priority)].bytes,
-				 pkttotlen(wlc->osh, p));
-		}
-
-		ASSERT(0);
-		pkt_buf_free_skb(wlc->osh, p, true);
-		WLCNTINCR(wlc->pub->_cnt->txnobuf);
-	}
-
-	/* Enqueue */
-	if (head)
-		p = pktq_penq_head(q, prec, pkt);
-	else
-		p = pktq_penq(q, prec, pkt);
-	ASSERT(p != NULL);
-
-	return true;
-}
-
-void BCMFASTPATH wlc_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
-			     uint prec)
-{
-	struct wlc_info *wlc = (struct wlc_info *) ctx;
-	wlc_txq_info_t *qi = wlc->active_queue;	/* Check me */
-	struct pktq *q = &qi->q;
-	int prio;
-
-	prio = sdu->priority;
-
-	ASSERT(pktq_max(q) >= wlc->pub->tunables->datahiwat);
-
-	if (!wlc_prec_enq(wlc, q, sdu, prec)) {
-		if (!EDCF_ENAB(wlc->pub)
-		    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL))
-			WL_ERROR("wl%d: wlc_txq_enq: txq overflow\n",
-				 wlc->pub->unit);
-
-		/* ASSERT(9 == 8); *//* XXX we might hit this condtion in case packet flooding from mac80211 stack */
-		pkt_buf_free_skb(wlc->osh, sdu, true);
-		WLCNTINCR(wlc->pub->_cnt->txnobuf);
-	}
-
-	/* Check if flow control needs to be turned on after enqueuing the packet
-	 *   Don't turn on flow control if EDCF is enabled. Driver would make the decision on what
-	 *   to drop instead of relying on stack to make the right decision
-	 */
-	if (!EDCF_ENAB(wlc->pub)
-	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
-		if (pktq_len(q) >= wlc->pub->tunables->datahiwat) {
-			wlc_txflowcontrol(wlc, qi, ON, ALLPRIO);
-		}
-	} else if (wlc->pub->_priofc) {
-		if (pktq_plen(q, wlc_prio2prec_map[prio]) >=
-		    wlc->pub->tunables->datahiwat) {
-			wlc_txflowcontrol(wlc, qi, ON, prio);
-		}
-	}
-}
-
-bool BCMFASTPATH
-wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu,
-		     struct ieee80211_hw *hw)
-{
-	u8 prio;
-	uint fifo;
-	void *pkt;
-	struct scb *scb = &global_scb;
-	struct dot11_header *d11_header = (struct dot11_header *)(sdu->data);
-	u16 type, fc;
-
-	ASSERT(sdu);
-
-	fc = ltoh16(d11_header->fc);
-	type = FC_TYPE(fc);
-
-	/* 802.11 standard requires management traffic to go at highest priority */
-	prio = (type == FC_TYPE_DATA ? sdu->priority : MAXPRIO);
-	fifo = prio2fifo[prio];
-
-	ASSERT((uint) skb_headroom(sdu) >= TXOFF);
-	ASSERT(!(sdu->next));
-	ASSERT(!(sdu->prev));
-	ASSERT(fifo < NFIFO);
-
-	pkt = sdu;
-	if (unlikely
-	    (wlc_d11hdrs_mac80211(wlc, hw, pkt, scb, 0, 1, fifo, 0, NULL, 0)))
-		return -EINVAL;
-	wlc_txq_enq(wlc, scb, pkt, WLC_PRIO_TO_PREC(prio));
-	wlc_send_q(wlc, wlc->active_queue);
-
-	WLCNTINCR(wlc->pub->_cnt->ieee_tx);
-	return 0;
-}
-
-void BCMFASTPATH wlc_send_q(struct wlc_info *wlc, wlc_txq_info_t *qi)
-{
-	struct sk_buff *pkt[DOT11_MAXNUMFRAGS];
-	int prec;
-	u16 prec_map;
-	int err = 0, i, count;
-	uint fifo;
-	struct pktq *q = &qi->q;
-	struct ieee80211_tx_info *tx_info;
-
-	/* only do work for the active queue */
-	if (qi != wlc->active_queue)
-		return;
-
-	if (in_send_q)
-		return;
-	else
-		in_send_q = true;
-
-	prec_map = wlc->tx_prec_map;
-
-	/* Send all the enq'd pkts that we can.
-	 * Dequeue packets with precedence with empty HW fifo only
-	 */
-	while (prec_map && (pkt[0] = pktq_mdeq(q, prec_map, &prec))) {
-		tx_info = IEEE80211_SKB_CB(pkt[0]);
-		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-			err = wlc_sendampdu(wlc->ampdu, qi, pkt, prec);
-		} else {
-			count = 1;
-			err = wlc_prep_pdu(wlc, pkt[0], &fifo);
-			if (!err) {
-				for (i = 0; i < count; i++) {
-					wlc_txfifo(wlc, fifo, pkt[i], true, 1);
-				}
-			}
-		}
-
-		if (err == BCME_BUSY) {
-			pktq_penq_head(q, prec, pkt[0]);
-			/* If send failed due to any other reason than a change in
-			 * HW FIFO condition, quit. Otherwise, read the new prec_map!
-			 */
-			if (prec_map == wlc->tx_prec_map)
-				break;
-			prec_map = wlc->tx_prec_map;
-		}
-	}
-
-	/* Check if flow control needs to be turned off after sending the packet */
-	if (!EDCF_ENAB(wlc->pub)
-	    || (wlc->pub->wlfeatureflag & WL_SWFL_FLOWCONTROL)) {
-		if (wlc_txflowcontrol_prio_isset(wlc, qi, ALLPRIO)
-		    && (pktq_len(q) < wlc->pub->tunables->datahiwat / 2)) {
-			wlc_txflowcontrol(wlc, qi, OFF, ALLPRIO);
-		}
-	} else if (wlc->pub->_priofc) {
-		int prio;
-		for (prio = MAXPRIO; prio >= 0; prio--) {
-			if (wlc_txflowcontrol_prio_isset(wlc, qi, prio) &&
-			    (pktq_plen(q, wlc_prio2prec_map[prio]) <
-			     wlc->pub->tunables->datahiwat / 2)) {
-				wlc_txflowcontrol(wlc, qi, OFF, prio);
-			}
-		}
-	}
-	in_send_q = false;
-}
-
-/*
- * bcmc_fid_generate:
- * Generate frame ID for a BCMC packet.  The frag field is not used
- * for MC frames so is used as part of the sequence number.
- */
-static inline u16
-bcmc_fid_generate(struct wlc_info *wlc, wlc_bsscfg_t *bsscfg, d11txh_t *txh)
-{
-	u16 frameid;
-
-	frameid = ltoh16(txh->TxFrameID) & ~(TXFID_SEQ_MASK | TXFID_QUEUE_MASK);
-	frameid |=
-	    (((wlc->
-	       mc_fid_counter++) << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
-	    TX_BCMC_FIFO;
-
-	return frameid;
-}
-
-void BCMFASTPATH
-wlc_txfifo(struct wlc_info *wlc, uint fifo, struct sk_buff *p, bool commit,
-	   s8 txpktpend)
-{
-	u16 frameid = INVALIDFID;
-	d11txh_t *txh;
-
-	ASSERT(fifo < NFIFO);
-	txh = (d11txh_t *) (p->data);
-
-	/* When a BC/MC frame is being committed to the BCMC fifo via DMA (NOT PIO), update
-	 * ucode or BSS info as appropriate.
-	 */
-	if (fifo == TX_BCMC_FIFO) {
-		frameid = ltoh16(txh->TxFrameID);
-
-	}
-
-	if (WLC_WAR16165(wlc))
-		wlc_war16165(wlc, true);
-
-
-	/* Bump up pending count for if not using rpc. If rpc is used, this will be handled
-	 * in wlc_bmac_txfifo()
-	 */
-	if (commit) {
-		TXPKTPENDINC(wlc, fifo, txpktpend);
-		WL_TRACE("wlc_txfifo, pktpend inc %d to %d\n",
-			 txpktpend, TXPKTPENDGET(wlc, fifo));
-	}
-
-	/* Commit BCMC sequence number in the SHM frame ID location */
-	if (frameid != INVALIDFID)
-		BCMCFID(wlc, frameid);
-
-	if (dma_txfast(wlc->hw->di[fifo], p, commit) < 0) {
-		WL_ERROR("wlc_txfifo: fatal, toss frames !!!\n");
-	}
-}
-
-static u16
-wlc_compute_airtime(struct wlc_info *wlc, ratespec_t rspec, uint length)
-{
-	u16 usec = 0;
-	uint mac_rate = RSPEC2RATE(rspec);
-	uint nsyms;
-
-	if (IS_MCS(rspec)) {
-		/* not supported yet */
-		ASSERT(0);
-	} else if (IS_OFDM(rspec)) {
-		/* nsyms = Ceiling(Nbits / (Nbits/sym))
-		 *
-		 * Nbits = length * 8
-		 * Nbits/sym = Mbps * 4 = mac_rate * 2
-		 */
-		nsyms = CEIL((length * 8), (mac_rate * 2));
-
-		/* usec = symbols * usec/symbol */
-		usec = (u16) (nsyms * APHY_SYMBOL_TIME);
-		return usec;
-	} else {
-		switch (mac_rate) {
-		case WLC_RATE_1M:
-			usec = length << 3;
-			break;
-		case WLC_RATE_2M:
-			usec = length << 2;
-			break;
-		case WLC_RATE_5M5:
-			usec = (length << 4) / 11;
-			break;
-		case WLC_RATE_11M:
-			usec = (length << 3) / 11;
-			break;
-		default:
-			WL_ERROR("wl%d: wlc_compute_airtime: unsupported rspec 0x%x\n",
-				 wlc->pub->unit, rspec);
-			ASSERT((const char *)"Bad phy_rate" == NULL);
-			break;
-		}
-	}
-
-	return usec;
-}
-
-void BCMFASTPATH
-wlc_compute_plcp(struct wlc_info *wlc, ratespec_t rspec, uint length, u8 *plcp)
-{
-	if (IS_MCS(rspec)) {
-		wlc_compute_mimo_plcp(rspec, length, plcp);
-	} else if (IS_OFDM(rspec)) {
-		wlc_compute_ofdm_plcp(rspec, length, plcp);
-	} else {
-		wlc_compute_cck_plcp(rspec, length, plcp);
-	}
-	return;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void wlc_compute_mimo_plcp(ratespec_t rspec, uint length, u8 *plcp)
-{
-	u8 mcs = (u8) (rspec & RSPEC_RATE_MASK);
-	ASSERT(IS_MCS(rspec));
-	plcp[0] = mcs;
-	if (RSPEC_IS40MHZ(rspec) || (mcs == 32))
-		plcp[0] |= MIMO_PLCP_40MHZ;
-	WLC_SET_MIMO_PLCP_LEN(plcp, length);
-	plcp[3] = RSPEC_MIMOPLCP3(rspec);	/* rspec already holds this byte */
-	plcp[3] |= 0x7;		/* set smoothing, not sounding ppdu & reserved */
-	plcp[4] = 0;		/* number of extension spatial streams bit 0 & 1 */
-	plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void BCMFASTPATH
-wlc_compute_ofdm_plcp(ratespec_t rspec, u32 length, u8 *plcp)
-{
-	u8 rate_signal;
-	u32 tmp = 0;
-	int rate = RSPEC2RATE(rspec);
-
-	ASSERT(IS_OFDM(rspec));
-
-	/* encode rate per 802.11a-1999 sec 17.3.4.1, with lsb transmitted first */
-	rate_signal = rate_info[rate] & RATE_MASK;
-	ASSERT(rate_signal != 0);
-
-	memset(plcp, 0, D11_PHY_HDR_LEN);
-	D11A_PHY_HDR_SRATE((ofdm_phy_hdr_t *) plcp, rate_signal);
-
-	tmp = (length & 0xfff) << 5;
-	plcp[2] |= (tmp >> 16) & 0xff;
-	plcp[1] |= (tmp >> 8) & 0xff;
-	plcp[0] |= tmp & 0xff;
-
-	return;
-}
-
-/*
- * Compute PLCP, but only requires actual rate and length of pkt.
- * Rate is given in the driver standard multiple of 500 kbps.
- * le is set for 11 Mbps rate if necessary.
- * Broken out for PRQ.
- */
-
-static void wlc_cck_plcp_set(int rate_500, uint length, u8 *plcp)
-{
-	u16 usec = 0;
-	u8 le = 0;
-
-	switch (rate_500) {
-	case WLC_RATE_1M:
-		usec = length << 3;
-		break;
-	case WLC_RATE_2M:
-		usec = length << 2;
-		break;
-	case WLC_RATE_5M5:
-		usec = (length << 4) / 11;
-		if ((length << 4) - (usec * 11) > 0)
-			usec++;
-		break;
-	case WLC_RATE_11M:
-		usec = (length << 3) / 11;
-		if ((length << 3) - (usec * 11) > 0) {
-			usec++;
-			if ((usec * 11) - (length << 3) >= 8)
-				le = D11B_PLCP_SIGNAL_LE;
-		}
-		break;
-
-	default:
-		WL_ERROR("wlc_cck_plcp_set: unsupported rate %d\n", rate_500);
-		rate_500 = WLC_RATE_1M;
-		usec = length << 3;
-		break;
-	}
-	/* PLCP signal byte */
-	plcp[0] = rate_500 * 5;	/* r (500kbps) * 5 == r (100kbps) */
-	/* PLCP service byte */
-	plcp[1] = (u8) (le | D11B_PLCP_SIGNAL_LOCKED);
-	/* PLCP length u16, little endian */
-	plcp[2] = usec & 0xff;
-	plcp[3] = (usec >> 8) & 0xff;
-	/* PLCP CRC16 */
-	plcp[4] = 0;
-	plcp[5] = 0;
-}
-
-/* Rate: 802.11 rate code, length: PSDU length in octets */
-static void wlc_compute_cck_plcp(ratespec_t rspec, uint length, u8 *plcp)
-{
-	int rate = RSPEC2RATE(rspec);
-
-	ASSERT(IS_CCK(rspec));
-
-	wlc_cck_plcp_set(rate, length, plcp);
-}
-
-/* wlc_compute_frame_dur()
- *
- * Calculate the 802.11 MAC header DUR field for MPDU
- * DUR for a single frame = 1 SIFS + 1 ACK
- * DUR for a frame with following frags = 3 SIFS + 2 ACK + next frag time
- *
- * rate			MPDU rate in unit of 500kbps
- * next_frag_len	next MPDU length in bytes
- * preamble_type	use short/GF or long/MM PLCP header
- */
-static u16 BCMFASTPATH
-wlc_compute_frame_dur(struct wlc_info *wlc, ratespec_t rate, u8 preamble_type,
-		      uint next_frag_len)
-{
-	u16 dur, sifs;
-
-	sifs = SIFS(wlc->band);
-
-	dur = sifs;
-	dur += (u16) wlc_calc_ack_time(wlc, rate, preamble_type);
-
-	if (next_frag_len) {
-		/* Double the current DUR to get 2 SIFS + 2 ACKs */
-		dur *= 2;
-		/* add another SIFS and the frag time */
-		dur += sifs;
-		dur +=
-		    (u16) wlc_calc_frame_time(wlc, rate, preamble_type,
-						 next_frag_len);
-	}
-	return dur;
-}
-
-/* wlc_compute_rtscts_dur()
- *
- * Calculate the 802.11 MAC header DUR field for an RTS or CTS frame
- * DUR for normal RTS/CTS w/ frame = 3 SIFS + 1 CTS + next frame time + 1 ACK
- * DUR for CTS-TO-SELF w/ frame    = 2 SIFS         + next frame time + 1 ACK
- *
- * cts			cts-to-self or rts/cts
- * rts_rate		rts or cts rate in unit of 500kbps
- * rate			next MPDU rate in unit of 500kbps
- * frame_len		next MPDU frame length in bytes
- */
-u16 BCMFASTPATH
-wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only, ratespec_t rts_rate,
-		       ratespec_t frame_rate, u8 rts_preamble_type,
-		       u8 frame_preamble_type, uint frame_len, bool ba)
-{
-	u16 dur, sifs;
-
-	sifs = SIFS(wlc->band);
-
-	if (!cts_only) {	/* RTS/CTS */
-		dur = 3 * sifs;
-		dur +=
-		    (u16) wlc_calc_cts_time(wlc, rts_rate,
-					       rts_preamble_type);
-	} else {		/* CTS-TO-SELF */
-		dur = 2 * sifs;
-	}
-
-	dur +=
-	    (u16) wlc_calc_frame_time(wlc, frame_rate, frame_preamble_type,
-					 frame_len);
-	if (ba)
-		dur +=
-		    (u16) wlc_calc_ba_time(wlc, frame_rate,
-					      WLC_SHORT_PREAMBLE);
-	else
-		dur +=
-		    (u16) wlc_calc_ack_time(wlc, frame_rate,
-					       frame_preamble_type);
-	return dur;
-}
-
-static bool wlc_phy_rspec_check(struct wlc_info *wlc, u16 bw, ratespec_t rspec)
-{
-	if (IS_MCS(rspec)) {
-		uint mcs = rspec & RSPEC_RATE_MASK;
-
-		if (mcs < 8) {
-			ASSERT(RSPEC_STF(rspec) < PHY_TXC1_MODE_SDM);
-		} else if ((mcs >= 8) && (mcs <= 23)) {
-			ASSERT(RSPEC_STF(rspec) == PHY_TXC1_MODE_SDM);
-		} else if (mcs == 32) {
-			ASSERT(RSPEC_STF(rspec) < PHY_TXC1_MODE_SDM);
-			ASSERT(bw == PHY_TXC1_BW_40MHZ_DUP);
-		}
-	} else if (IS_OFDM(rspec)) {
-		ASSERT(RSPEC_STF(rspec) < PHY_TXC1_MODE_STBC);
-	} else {
-		ASSERT(IS_CCK(rspec));
-
-		ASSERT((bw == PHY_TXC1_BW_20MHZ)
-		       || (bw == PHY_TXC1_BW_20MHZ_UP));
-		ASSERT(RSPEC_STF(rspec) == PHY_TXC1_MODE_SISO);
-	}
-
-	return true;
-}
-
-u16 BCMFASTPATH wlc_phytxctl1_calc(struct wlc_info *wlc, ratespec_t rspec)
-{
-	u16 phyctl1 = 0;
-	u16 bw;
-
-	if (WLCISLCNPHY(wlc->band)) {
-		bw = PHY_TXC1_BW_20MHZ;
-	} else {
-		bw = RSPEC_GET_BW(rspec);
-		/* 10Mhz is not supported yet */
-		if (bw < PHY_TXC1_BW_20MHZ) {
-			WL_ERROR("wlc_phytxctl1_calc: bw %d is not supported yet, set to 20L\n",
-				 bw);
-			bw = PHY_TXC1_BW_20MHZ;
-		}
-
-		wlc_phy_rspec_check(wlc, bw, rspec);
-	}
-
-	if (IS_MCS(rspec)) {
-		uint mcs = rspec & RSPEC_RATE_MASK;
-
-		/* bw, stf, coding-type is part of RSPEC_PHYTXBYTE2 returns */
-		phyctl1 = RSPEC_PHYTXBYTE2(rspec);
-		/* set the upper byte of phyctl1 */
-		phyctl1 |= (mcs_table[mcs].tx_phy_ctl3 << 8);
-	} else if (IS_CCK(rspec) && !WLCISLCNPHY(wlc->band)
-		   && !WLCISSSLPNPHY(wlc->band)) {
-		/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
-		/* Eventually MIMOPHY would also be converted to this format */
-		/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
-		phyctl1 = (bw | (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
-	} else {		/* legacy OFDM/CCK */
-		s16 phycfg;
-		/* get the phyctl byte from rate phycfg table */
-		phycfg = wlc_rate_legacy_phyctl(RSPEC2RATE(rspec));
-		if (phycfg == -1) {
-			WL_ERROR("wlc_phytxctl1_calc: wrong legacy OFDM/CCK rate\n");
-			ASSERT(0);
-			phycfg = 0;
-		}
-		/* set the upper byte of phyctl1 */
-		phyctl1 =
-		    (bw | (phycfg << 8) |
-		     (RSPEC_STF(rspec) << PHY_TXC1_MODE_SHIFT));
-	}
-
-#ifdef BCMDBG
-	/* phy clock must support 40Mhz if tx descriptor uses it */
-	if ((phyctl1 & PHY_TXC1_BW_MASK) >= PHY_TXC1_BW_40MHZ) {
-		ASSERT(CHSPEC_WLC_BW(wlc->chanspec) == WLC_40_MHZ);
-		ASSERT(wlc->chanspec == wlc_phy_chanspec_get(wlc->band->pi));
-	}
-#endif				/* BCMDBG */
-	return phyctl1;
-}
-
-ratespec_t BCMFASTPATH
-wlc_rspec_to_rts_rspec(struct wlc_info *wlc, ratespec_t rspec, bool use_rspec,
-		       u16 mimo_ctlchbw)
-{
-	ratespec_t rts_rspec = 0;
-
-	if (use_rspec) {
-		/* use frame rate as rts rate */
-		rts_rspec = rspec;
-
-	} else if (wlc->band->gmode && wlc->protection->_g && !IS_CCK(rspec)) {
-		/* Use 11Mbps as the g protection RTS target rate and fallback.
-		 * Use the WLC_BASIC_RATE() lookup to find the best basic rate under the
-		 * target in case 11 Mbps is not Basic.
-		 * 6 and 9 Mbps are not usually selected by rate selection, but even
-		 * if the OFDM rate we are protecting is 6 or 9 Mbps, 11 is more robust.
-		 */
-		rts_rspec = WLC_BASIC_RATE(wlc, WLC_RATE_11M);
-	} else {
-		/* calculate RTS rate and fallback rate based on the frame rate
-		 * RTS must be sent at a basic rate since it is a
-		 * control frame, sec 9.6 of 802.11 spec
-		 */
-		rts_rspec = WLC_BASIC_RATE(wlc, rspec);
-	}
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		/* set rts txbw to correct side band */
-		rts_rspec &= ~RSPEC_BW_MASK;
-
-		/* if rspec/rspec_fallback is 40MHz, then send RTS on both 20MHz channel
-		 * (DUP), otherwise send RTS on control channel
-		 */
-		if (RSPEC_IS40MHZ(rspec) && !IS_CCK(rts_rspec))
-			rts_rspec |= (PHY_TXC1_BW_40MHZ_DUP << RSPEC_BW_SHIFT);
-		else
-			rts_rspec |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
-		/* pick siso/cdd as default for ofdm */
-		if (IS_OFDM(rts_rspec)) {
-			rts_rspec &= ~RSPEC_STF_MASK;
-			rts_rspec |= (wlc->stf->ss_opmode << RSPEC_STF_SHIFT);
-		}
-	}
-	return rts_rspec;
-}
-
-/*
- * Add d11txh_t, cck_phy_hdr_t.
- *
- * 'p' data must start with 802.11 MAC header
- * 'p' must allow enough bytes of local headers to be "pushed" onto the packet
- *
- * headroom == D11_PHY_HDR_LEN + D11_TXH_LEN (D11_TXH_LEN is now 104 bytes)
- *
- */
-static u16 BCMFASTPATH
-wlc_d11hdrs_mac80211(struct wlc_info *wlc, struct ieee80211_hw *hw,
-		     struct sk_buff *p, struct scb *scb, uint frag,
-		     uint nfrags, uint queue, uint next_frag_len,
-		     wsec_key_t *key, ratespec_t rspec_override)
-{
-	struct dot11_header *h;
-	d11txh_t *txh;
-	u8 *plcp, plcp_fallback[D11_PHY_HDR_LEN];
-	struct osl_info *osh;
-	int len, phylen, rts_phylen;
-	u16 fc, type, frameid, mch, phyctl, xfts, mainrates;
-	u16 seq = 0, mcl = 0, status = 0;
-	ratespec_t rspec[2] = { WLC_RATE_1M, WLC_RATE_1M }, rts_rspec[2] = {
-	WLC_RATE_1M, WLC_RATE_1M};
-	bool use_rts = false;
-	bool use_cts = false;
-	bool use_rifs = false;
-	bool short_preamble[2] = { false, false };
-	u8 preamble_type[2] = { WLC_LONG_PREAMBLE, WLC_LONG_PREAMBLE };
-	u8 rts_preamble_type[2] = { WLC_LONG_PREAMBLE, WLC_LONG_PREAMBLE };
-	u8 *rts_plcp, rts_plcp_fallback[D11_PHY_HDR_LEN];
-	struct dot11_rts_frame *rts = NULL;
-	bool qos;
-	uint ac;
-	u32 rate_val[2];
-	bool hwtkmic = false;
-	u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
-#ifdef WLANTSEL
-#define ANTCFG_NONE 0xFF
-	u8 antcfg = ANTCFG_NONE;
-	u8 fbantcfg = ANTCFG_NONE;
-#endif
-	uint phyctl1_stf = 0;
-	u16 durid = 0;
-	struct ieee80211_tx_rate *txrate[2];
-	int k;
-	struct ieee80211_tx_info *tx_info;
-	bool is_mcs[2];
-	u16 mimo_txbw;
-	u8 mimo_preamble_type;
-
-	frameid = 0;
-
-	ASSERT(queue < NFIFO);
-
-	osh = wlc->osh;
-
-	/* locate 802.11 MAC header */
-	h = (struct dot11_header *)(p->data);
-	fc = ltoh16(h->fc);
-	type = FC_TYPE(fc);
-
-	qos = (type == FC_TYPE_DATA && FC_SUBTYPE_ANY_QOS(FC_SUBTYPE(fc)));
-
-	/* compute length of frame in bytes for use in PLCP computations */
-	len = pkttotlen(osh, p);
-	phylen = len + DOT11_FCS_LEN;
-
-	/* If WEP enabled, add room in phylen for the additional bytes of
-	 * ICV which MAC generates.  We do NOT add the additional bytes to
-	 * the packet itself, thus phylen = packet length + ICV_LEN + FCS_LEN
-	 * in this case
-	 */
-	if (key) {
-		phylen += key->icv_len;
-	}
-
-	/* Get tx_info */
-	tx_info = IEEE80211_SKB_CB(p);
-	ASSERT(tx_info);
-
-	/* add PLCP */
-	plcp = skb_push(p, D11_PHY_HDR_LEN);
-
-	/* add Broadcom tx descriptor header */
-	txh = (d11txh_t *) skb_push(p, D11_TXH_LEN);
-	memset((char *)txh, 0, D11_TXH_LEN);
-
-	/* setup frameid */
-	if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
-		/* non-AP STA should never use BCMC queue */
-		ASSERT(queue != TX_BCMC_FIFO);
-		if (queue == TX_BCMC_FIFO) {
-			WL_ERROR("wl%d: %s: ASSERT queue == TX_BCMC!\n",
-				 WLCWLUNIT(wlc), __func__);
-			frameid = bcmc_fid_generate(wlc, NULL, txh);
-		} else {
-			/* Increment the counter for first fragment */
-			if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) {
-				SCB_SEQNUM(scb, p->priority)++;
-			}
-
-			/* extract fragment number from frame first */
-			seq = ltoh16(seq) & FRAGNUM_MASK;
-			seq |= (SCB_SEQNUM(scb, p->priority) << SEQNUM_SHIFT);
-			h->seq = htol16(seq);
-
-			frameid = ((seq << TXFID_SEQ_SHIFT) & TXFID_SEQ_MASK) |
-			    (queue & TXFID_QUEUE_MASK);
-		}
-	}
-	frameid |= queue & TXFID_QUEUE_MASK;
-
-	/* set the ignpmq bit for all pkts tx'd in PS mode and for beacons */
-	if (SCB_PS(scb) || ((fc & FC_KIND_MASK) == FC_BEACON))
-		mcl |= TXC_IGNOREPMQ;
-
-	ASSERT(hw->max_rates <= IEEE80211_TX_MAX_RATES);
-	ASSERT(hw->max_rates == 2);
-
-	txrate[0] = tx_info->control.rates;
-	txrate[1] = txrate[0] + 1;
-
-	ASSERT(txrate[0]->idx >= 0);
-	/* if rate control algorithm didn't give us a fallback rate, use the primary rate */
-	if (txrate[1]->idx < 0) {
-		txrate[1] = txrate[0];
-	}
-
-	for (k = 0; k < hw->max_rates; k++) {
-		is_mcs[k] =
-		    txrate[k]->flags & IEEE80211_TX_RC_MCS ? true : false;
-		if (!is_mcs[k]) {
-			ASSERT(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU));
-			if ((txrate[k]->idx >= 0)
-			    && (txrate[k]->idx <
-				hw->wiphy->bands[tx_info->band]->n_bitrates)) {
-				rate_val[k] =
-				    hw->wiphy->bands[tx_info->band]->
-				    bitrates[txrate[k]->idx].hw_value;
-				short_preamble[k] =
-				    txrate[k]->
-				    flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE ?
-				    true : false;
-			} else {
-				ASSERT((txrate[k]->idx >= 0) &&
-				       (txrate[k]->idx <
-					hw->wiphy->bands[tx_info->band]->
-					n_bitrates));
-				rate_val[k] = WLC_RATE_1M;
-			}
-		} else {
-			rate_val[k] = txrate[k]->idx;
-		}
-		/* Currently only support same setting for primay and fallback rates.
-		 * Unify flags for each rate into a single value for the frame
-		 */
-		use_rts |=
-		    txrate[k]->
-		    flags & IEEE80211_TX_RC_USE_RTS_CTS ? true : false;
-		use_cts |=
-		    txrate[k]->
-		    flags & IEEE80211_TX_RC_USE_CTS_PROTECT ? true : false;
-
-		if (is_mcs[k])
-			rate_val[k] |= NRATE_MCS_INUSE;
-
-		rspec[k] = mac80211_wlc_set_nrate(wlc, wlc->band, rate_val[k]);
-
-		/* (1) RATE: determine and validate primary rate and fallback rates */
-		if (!RSPEC_ACTIVE(rspec[k])) {
-			ASSERT(RSPEC_ACTIVE(rspec[k]));
-			rspec[k] = WLC_RATE_1M;
-		} else {
-			if (WLANTSEL_ENAB(wlc) &&
-			    !is_multicast_ether_addr(h->a1.octet)) {
-				/* set tx antenna config */
-				wlc_antsel_antcfg_get(wlc->asi, false, false, 0,
-						      0, &antcfg, &fbantcfg);
-			}
-		}
-	}
-
-	phyctl1_stf = wlc->stf->ss_opmode;
-
-	if (N_ENAB(wlc->pub)) {
-		for (k = 0; k < hw->max_rates; k++) {
-			/* apply siso/cdd to single stream mcs's or ofdm if rspec is auto selected */
-			if (((IS_MCS(rspec[k]) &&
-			      IS_SINGLE_STREAM(rspec[k] & RSPEC_RATE_MASK)) ||
-			     IS_OFDM(rspec[k]))
-			    && ((rspec[k] & RSPEC_OVERRIDE_MCS_ONLY)
-				|| !(rspec[k] & RSPEC_OVERRIDE))) {
-				rspec[k] &= ~(RSPEC_STF_MASK | RSPEC_STC_MASK);
-
-				/* For SISO MCS use STBC if possible */
-				if (IS_MCS(rspec[k])
-				    && WLC_STF_SS_STBC_TX(wlc, scb)) {
-					u8 stc;
-
-					ASSERT(WLC_STBC_CAP_PHY(wlc));
-					stc = 1;	/* Nss for single stream is always 1 */
-					rspec[k] |=
-					    (PHY_TXC1_MODE_STBC <<
-					     RSPEC_STF_SHIFT) | (stc <<
-								 RSPEC_STC_SHIFT);
-				} else
-					rspec[k] |=
-					    (phyctl1_stf << RSPEC_STF_SHIFT);
-			}
-
-			/* Is the phy configured to use 40MHZ frames? If so then pick the desired txbw */
-			if (CHSPEC_WLC_BW(wlc->chanspec) == WLC_40_MHZ) {
-				/* default txbw is 20in40 SB */
-				mimo_ctlchbw = mimo_txbw =
-				    CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
-				    ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
-
-				if (IS_MCS(rspec[k])) {
-					/* mcs 32 must be 40b/w DUP */
-					if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
-						mimo_txbw =
-						    PHY_TXC1_BW_40MHZ_DUP;
-						/* use override */
-					} else if (wlc->mimo_40txbw != AUTO)
-						mimo_txbw = wlc->mimo_40txbw;
-					/* else check if dst is using 40 Mhz */
-					else if (scb->flags & SCB_IS40)
-						mimo_txbw = PHY_TXC1_BW_40MHZ;
-				} else if (IS_OFDM(rspec[k])) {
-					if (wlc->ofdm_40txbw != AUTO)
-						mimo_txbw = wlc->ofdm_40txbw;
-				} else {
-					ASSERT(IS_CCK(rspec[k]));
-					if (wlc->cck_40txbw != AUTO)
-						mimo_txbw = wlc->cck_40txbw;
-				}
-			} else {
-				/* mcs32 is 40 b/w only.
-				 * This is possible for probe packets on a STA during SCAN
-				 */
-				if ((rspec[k] & RSPEC_RATE_MASK) == 32) {
-					/* mcs 0 */
-					rspec[k] = RSPEC_MIMORATE;
-				}
-				mimo_txbw = PHY_TXC1_BW_20MHZ;
-			}
-
-			/* Set channel width */
-			rspec[k] &= ~RSPEC_BW_MASK;
-			if ((k == 0) || ((k > 0) && IS_MCS(rspec[k])))
-				rspec[k] |= (mimo_txbw << RSPEC_BW_SHIFT);
-			else
-				rspec[k] |= (mimo_ctlchbw << RSPEC_BW_SHIFT);
-
-			/* Set Short GI */
-#ifdef NOSGIYET
-			if (IS_MCS(rspec[k])
-			    && (txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
-				rspec[k] |= RSPEC_SHORT_GI;
-			else if (!(txrate[k]->flags & IEEE80211_TX_RC_SHORT_GI))
-				rspec[k] &= ~RSPEC_SHORT_GI;
-#else
-			rspec[k] &= ~RSPEC_SHORT_GI;
-#endif
-
-			mimo_preamble_type = WLC_MM_PREAMBLE;
-			if (txrate[k]->flags & IEEE80211_TX_RC_GREEN_FIELD)
-				mimo_preamble_type = WLC_GF_PREAMBLE;
-
-			if ((txrate[k]->flags & IEEE80211_TX_RC_MCS)
-			    && (!IS_MCS(rspec[k]))) {
-				WL_ERROR("wl%d: %s: IEEE80211_TX_RC_MCS != IS_MCS(rspec)\n",
-					 WLCWLUNIT(wlc), __func__);
-				ASSERT(0 && "Rate mismatch");
-			}
-
-			if (IS_MCS(rspec[k])) {
-				preamble_type[k] = mimo_preamble_type;
-
-				/* if SGI is selected, then forced mm for single stream */
-				if ((rspec[k] & RSPEC_SHORT_GI)
-				    && IS_SINGLE_STREAM(rspec[k] &
-							RSPEC_RATE_MASK)) {
-					preamble_type[k] = WLC_MM_PREAMBLE;
-				}
-			}
-
-			/* mimo bw field MUST now be valid in the rspec (it affects duration calculations) */
-			ASSERT(VALID_RATE_DBG(wlc, rspec[0]));
-
-			/* should be better conditionalized */
-			if (!IS_MCS(rspec[0])
-			    && (tx_info->control.rates[0].
-				flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE))
-				preamble_type[k] = WLC_SHORT_PREAMBLE;
-
-			ASSERT(!IS_MCS(rspec[0])
-			       || WLC_IS_MIMO_PREAMBLE(preamble_type[k]));
-		}
-	} else {
-		for (k = 0; k < hw->max_rates; k++) {
-			/* Set ctrlchbw as 20Mhz */
-			ASSERT(!IS_MCS(rspec[k]));
-			rspec[k] &= ~RSPEC_BW_MASK;
-			rspec[k] |= (PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT);
-
-			/* for nphy, stf of ofdm frames must follow policies */
-			if (WLCISNPHY(wlc->band) && IS_OFDM(rspec[k])) {
-				rspec[k] &= ~RSPEC_STF_MASK;
-				rspec[k] |= phyctl1_stf << RSPEC_STF_SHIFT;
-			}
-		}
-	}
-
-	/* Reset these for use with AMPDU's */
-	txrate[0]->count = 0;
-	txrate[1]->count = 0;
-
-	/* (3) PLCP: determine PLCP header and MAC duration, fill d11txh_t */
-	wlc_compute_plcp(wlc, rspec[0], phylen, plcp);
-	wlc_compute_plcp(wlc, rspec[1], phylen, plcp_fallback);
-	bcopy(plcp_fallback, (char *)&txh->FragPLCPFallback,
-	      sizeof(txh->FragPLCPFallback));
-
-	/* Length field now put in CCK FBR CRC field */
-	if (IS_CCK(rspec[1])) {
-		txh->FragPLCPFallback[4] = phylen & 0xff;
-		txh->FragPLCPFallback[5] = (phylen & 0xff00) >> 8;
-	}
-
-	/* MIMO-RATE: need validation ?? */
-	mainrates =
-	    IS_OFDM(rspec[0]) ? D11A_PHY_HDR_GRATE((ofdm_phy_hdr_t *) plcp) :
-	    plcp[0];
-
-	/* DUR field for main rate */
-	if ((fc != FC_PS_POLL) &&
-	    !is_multicast_ether_addr(h->a1.octet) && !use_rifs) {
-		durid =
-		    wlc_compute_frame_dur(wlc, rspec[0], preamble_type[0],
-					  next_frag_len);
-		h->durid = htol16(durid);
-	} else if (use_rifs) {
-		/* NAV protect to end of next max packet size */
-		durid =
-		    (u16) wlc_calc_frame_time(wlc, rspec[0],
-						 preamble_type[0],
-						 DOT11_MAX_FRAG_LEN);
-		durid += RIFS_11N_TIME;
-		h->durid = htol16(durid);
-	}
-
-	/* DUR field for fallback rate */
-	if (fc == FC_PS_POLL)
-		txh->FragDurFallback = h->durid;
-	else if (is_multicast_ether_addr(h->a1.octet) || use_rifs)
-		txh->FragDurFallback = 0;
-	else {
-		durid = wlc_compute_frame_dur(wlc, rspec[1],
-					      preamble_type[1], next_frag_len);
-		txh->FragDurFallback = htol16(durid);
-	}
-
-	/* (4) MAC-HDR: MacTxControlLow */
-	if (frag == 0)
-		mcl |= TXC_STARTMSDU;
-
-	if (!is_multicast_ether_addr(h->a1.octet))
-		mcl |= TXC_IMMEDACK;
-
-	if (BAND_5G(wlc->band->bandtype))
-		mcl |= TXC_FREQBAND_5G;
-
-	if (CHSPEC_IS40(WLC_BAND_PI_RADIO_CHANSPEC))
-		mcl |= TXC_BW_40;
-
-	/* set AMIC bit if using hardware TKIP MIC */
-	if (hwtkmic)
-		mcl |= TXC_AMIC;
-
-	txh->MacTxControlLow = htol16(mcl);
-
-	/* MacTxControlHigh */
-	mch = 0;
-
-	/* Set fallback rate preamble type */
-	if ((preamble_type[1] == WLC_SHORT_PREAMBLE) ||
-	    (preamble_type[1] == WLC_GF_PREAMBLE)) {
-		ASSERT((preamble_type[1] == WLC_GF_PREAMBLE) ||
-		       (!IS_MCS(rspec[1])));
-		if (RSPEC2RATE(rspec[1]) != WLC_RATE_1M)
-			mch |= TXC_PREAMBLE_DATA_FB_SHORT;
-	}
-
-	/* MacFrameControl */
-	bcopy((char *)&h->fc, (char *)&txh->MacFrameControl, sizeof(u16));
-
-	txh->TxFesTimeNormal = htol16(0);
-
-	txh->TxFesTimeFallback = htol16(0);
-
-	/* TxFrameRA */
-	bcopy((char *)&h->a1, (char *)&txh->TxFrameRA, ETH_ALEN);
-
-	/* TxFrameID */
-	txh->TxFrameID = htol16(frameid);
-
-	/* TxStatus, Note the case of recreating the first frag of a suppressed frame
-	 * then we may need to reset the retry cnt's via the status reg
-	 */
-	txh->TxStatus = htol16(status);
-
-	if (D11REV_GE(wlc->pub->corerev, 16)) {
-		/* extra fields for ucode AMPDU aggregation, the new fields are added to
-		 * the END of previous structure so that it's compatible in driver.
-		 * In old rev ucode, these fields should be ignored
-		 */
-		txh->MaxNMpdus = htol16(0);
-		txh->MaxABytes_MRT = htol16(0);
-		txh->MaxABytes_FBR = htol16(0);
-		txh->MinMBytes = htol16(0);
-	}
-
-	/* (5) RTS/CTS: determine RTS/CTS PLCP header and MAC duration, furnish d11txh_t */
-	/* RTS PLCP header and RTS frame */
-	if (use_rts || use_cts) {
-		if (use_rts && use_cts)
-			use_cts = false;
-
-		for (k = 0; k < 2; k++) {
-			rts_rspec[k] = wlc_rspec_to_rts_rspec(wlc, rspec[k],
-							      false,
-							      mimo_ctlchbw);
-		}
-
-		if (!IS_OFDM(rts_rspec[0]) &&
-		    !((RSPEC2RATE(rts_rspec[0]) == WLC_RATE_1M) ||
-		      (wlc->PLCPHdr_override == WLC_PLCP_LONG))) {
-			rts_preamble_type[0] = WLC_SHORT_PREAMBLE;
-			mch |= TXC_PREAMBLE_RTS_MAIN_SHORT;
-		}
-
-		if (!IS_OFDM(rts_rspec[1]) &&
-		    !((RSPEC2RATE(rts_rspec[1]) == WLC_RATE_1M) ||
-		      (wlc->PLCPHdr_override == WLC_PLCP_LONG))) {
-			rts_preamble_type[1] = WLC_SHORT_PREAMBLE;
-			mch |= TXC_PREAMBLE_RTS_FB_SHORT;
-		}
-
-		/* RTS/CTS additions to MacTxControlLow */
-		if (use_cts) {
-			txh->MacTxControlLow |= htol16(TXC_SENDCTS);
-		} else {
-			txh->MacTxControlLow |= htol16(TXC_SENDRTS);
-			txh->MacTxControlLow |= htol16(TXC_LONGFRAME);
-		}
-
-		/* RTS PLCP header */
-		ASSERT(IS_ALIGNED((unsigned long)txh->RTSPhyHeader, sizeof(u16)));
-		rts_plcp = txh->RTSPhyHeader;
-		if (use_cts)
-			rts_phylen = DOT11_CTS_LEN + DOT11_FCS_LEN;
-		else
-			rts_phylen = DOT11_RTS_LEN + DOT11_FCS_LEN;
-
-		wlc_compute_plcp(wlc, rts_rspec[0], rts_phylen, rts_plcp);
-
-		/* fallback rate version of RTS PLCP header */
-		wlc_compute_plcp(wlc, rts_rspec[1], rts_phylen,
-				 rts_plcp_fallback);
-		bcopy(rts_plcp_fallback, (char *)&txh->RTSPLCPFallback,
-		      sizeof(txh->RTSPLCPFallback));
-
-		/* RTS frame fields... */
-		rts = (struct dot11_rts_frame *)&txh->rts_frame;
-
-		durid = wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec[0],
-					       rspec[0], rts_preamble_type[0],
-					       preamble_type[0], phylen, false);
-		rts->durid = htol16(durid);
-		/* fallback rate version of RTS DUR field */
-		durid = wlc_compute_rtscts_dur(wlc, use_cts,
-					       rts_rspec[1], rspec[1],
-					       rts_preamble_type[1],
-					       preamble_type[1], phylen, false);
-		txh->RTSDurFallback = htol16(durid);
-
-		if (use_cts) {
-			rts->fc = htol16(FC_CTS);
-			bcopy((char *)&h->a2, (char *)&rts->ra, ETH_ALEN);
-		} else {
-			rts->fc = htol16((u16) FC_RTS);
-			bcopy((char *)&h->a1, (char *)&rts->ra,
-			      2 * ETH_ALEN);
-		}
-
-		/* mainrate
-		 *    low 8 bits: main frag rate/mcs,
-		 *    high 8 bits: rts/cts rate/mcs
-		 */
-		mainrates |= (IS_OFDM(rts_rspec[0]) ?
-			      D11A_PHY_HDR_GRATE((ofdm_phy_hdr_t *) rts_plcp) :
-			      rts_plcp[0]) << 8;
-	} else {
-		memset((char *)txh->RTSPhyHeader, 0, D11_PHY_HDR_LEN);
-		memset((char *)&txh->rts_frame, 0,
-			sizeof(struct dot11_rts_frame));
-		memset((char *)txh->RTSPLCPFallback, 0,
-		      sizeof(txh->RTSPLCPFallback));
-		txh->RTSDurFallback = 0;
-	}
-
-#ifdef SUPPORT_40MHZ
-	/* add null delimiter count */
-	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && IS_MCS(rspec)) {
-		txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] =
-		    wlc_ampdu_null_delim_cnt(wlc->ampdu, scb, rspec, phylen);
-	}
-#endif
-
-	/* Now that RTS/RTS FB preamble types are updated, write the final value */
-	txh->MacTxControlHigh = htol16(mch);
-
-	/* MainRates (both the rts and frag plcp rates have been calculated now) */
-	txh->MainRates = htol16(mainrates);
-
-	/* XtraFrameTypes */
-	xfts = FRAMETYPE(rspec[1], wlc->mimoft);
-	xfts |= (FRAMETYPE(rts_rspec[0], wlc->mimoft) << XFTS_RTS_FT_SHIFT);
-	xfts |= (FRAMETYPE(rts_rspec[1], wlc->mimoft) << XFTS_FBRRTS_FT_SHIFT);
-	xfts |=
-	    CHSPEC_CHANNEL(WLC_BAND_PI_RADIO_CHANSPEC) << XFTS_CHANNEL_SHIFT;
-	txh->XtraFrameTypes = htol16(xfts);
-
-	/* PhyTxControlWord */
-	phyctl = FRAMETYPE(rspec[0], wlc->mimoft);
-	if ((preamble_type[0] == WLC_SHORT_PREAMBLE) ||
-	    (preamble_type[0] == WLC_GF_PREAMBLE)) {
-		ASSERT((preamble_type[0] == WLC_GF_PREAMBLE)
-		       || !IS_MCS(rspec[0]));
-		if (RSPEC2RATE(rspec[0]) != WLC_RATE_1M)
-			phyctl |= PHY_TXC_SHORT_HDR;
-		WLCNTINCR(wlc->pub->_cnt->txprshort);
-	}
-
-	/* phytxant is properly bit shifted */
-	phyctl |= wlc_stf_d11hdrs_phyctl_txant(wlc, rspec[0]);
-	txh->PhyTxControlWord = htol16(phyctl);
-
-	/* PhyTxControlWord_1 */
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		u16 phyctl1 = 0;
-
-		phyctl1 = wlc_phytxctl1_calc(wlc, rspec[0]);
-		txh->PhyTxControlWord_1 = htol16(phyctl1);
-		phyctl1 = wlc_phytxctl1_calc(wlc, rspec[1]);
-		txh->PhyTxControlWord_1_Fbr = htol16(phyctl1);
-
-		if (use_rts || use_cts) {
-			phyctl1 = wlc_phytxctl1_calc(wlc, rts_rspec[0]);
-			txh->PhyTxControlWord_1_Rts = htol16(phyctl1);
-			phyctl1 = wlc_phytxctl1_calc(wlc, rts_rspec[1]);
-			txh->PhyTxControlWord_1_FbrRts = htol16(phyctl1);
-		}
-
-		/*
-		 * For mcs frames, if mixedmode(overloaded with long preamble) is going to be set,
-		 * fill in non-zero MModeLen and/or MModeFbrLen
-		 *  it will be unnecessary if they are separated
-		 */
-		if (IS_MCS(rspec[0]) && (preamble_type[0] == WLC_MM_PREAMBLE)) {
-			u16 mmodelen =
-			    wlc_calc_lsig_len(wlc, rspec[0], phylen);
-			txh->MModeLen = htol16(mmodelen);
-		}
-
-		if (IS_MCS(rspec[1]) && (preamble_type[1] == WLC_MM_PREAMBLE)) {
-			u16 mmodefbrlen =
-			    wlc_calc_lsig_len(wlc, rspec[1], phylen);
-			txh->MModeFbrLen = htol16(mmodefbrlen);
-		}
-	}
-
-	if (IS_MCS(rspec[0]))
-		ASSERT(IS_MCS(rspec[1]));
-
-	ASSERT(!IS_MCS(rspec[0]) ||
-	       ((preamble_type[0] == WLC_MM_PREAMBLE) == (txh->MModeLen != 0)));
-	ASSERT(!IS_MCS(rspec[1]) ||
-	       ((preamble_type[1] == WLC_MM_PREAMBLE) ==
-		(txh->MModeFbrLen != 0)));
-
-	ac = wme_fifo2ac[queue];
-	if (SCB_WME(scb) && qos && wlc->edcf_txop[ac]) {
-		uint frag_dur, dur, dur_fallback;
-
-		ASSERT(!is_multicast_ether_addr(h->a1.octet));
-
-		/* WME: Update TXOP threshold */
-		if ((!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) && (frag == 0)) {
-			frag_dur =
-			    wlc_calc_frame_time(wlc, rspec[0], preamble_type[0],
-						phylen);
-
-			if (rts) {
-				/* 1 RTS or CTS-to-self frame */
-				dur =
-				    wlc_calc_cts_time(wlc, rts_rspec[0],
-						      rts_preamble_type[0]);
-				dur_fallback =
-				    wlc_calc_cts_time(wlc, rts_rspec[1],
-						      rts_preamble_type[1]);
-				/* (SIFS + CTS) + SIFS + frame + SIFS + ACK */
-				dur += ltoh16(rts->durid);
-				dur_fallback += ltoh16(txh->RTSDurFallback);
-			} else if (use_rifs) {
-				dur = frag_dur;
-				dur_fallback = 0;
-			} else {
-				/* frame + SIFS + ACK */
-				dur = frag_dur;
-				dur +=
-				    wlc_compute_frame_dur(wlc, rspec[0],
-							  preamble_type[0], 0);
-
-				dur_fallback =
-				    wlc_calc_frame_time(wlc, rspec[1],
-							preamble_type[1],
-							phylen);
-				dur_fallback +=
-				    wlc_compute_frame_dur(wlc, rspec[1],
-							  preamble_type[1], 0);
-			}
-			/* NEED to set TxFesTimeNormal (hard) */
-			txh->TxFesTimeNormal = htol16((u16) dur);
-			/* NEED to set fallback rate version of TxFesTimeNormal (hard) */
-			txh->TxFesTimeFallback = htol16((u16) dur_fallback);
-
-			/* update txop byte threshold (txop minus intraframe overhead) */
-			if (wlc->edcf_txop[ac] >= (dur - frag_dur)) {
-				{
-					uint newfragthresh;
-
-					newfragthresh =
-					    wlc_calc_frame_len(wlc, rspec[0],
-							       preamble_type[0],
-							       (wlc->
-								edcf_txop[ac] -
-								(dur -
-								 frag_dur)));
-					/* range bound the fragthreshold */
-					if (newfragthresh < DOT11_MIN_FRAG_LEN)
-						newfragthresh =
-						    DOT11_MIN_FRAG_LEN;
-					else if (newfragthresh >
-						 wlc->usr_fragthresh)
-						newfragthresh =
-						    wlc->usr_fragthresh;
-					/* update the fragthresh and do txc update */
-					if (wlc->fragthresh[queue] !=
-					    (u16) newfragthresh) {
-						wlc->fragthresh[queue] =
-						    (u16) newfragthresh;
-					}
-				}
-			} else
-				WL_ERROR("wl%d: %s txop invalid for rate %d\n",
-					 wlc->pub->unit, fifo_names[queue],
-					 RSPEC2RATE(rspec[0]));
-
-			if (dur > wlc->edcf_txop[ac])
-				WL_ERROR("wl%d: %s: %s txop exceeded phylen %d/%d dur %d/%d\n",
-					 wlc->pub->unit, __func__,
-					 fifo_names[queue],
-					 phylen, wlc->fragthresh[queue],
-					 dur, wlc->edcf_txop[ac]);
-		}
-	}
-
-	return 0;
-}
-
-void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs)
-{
-	wlc_bsscfg_t *cfg = wlc->cfg;
-
-	WLCNTINCR(wlc->pub->_cnt->tbtt);
-
-	if (BSSCFG_STA(cfg)) {
-		/* run watchdog here if the watchdog timer is not armed */
-		if (WLC_WATCHDOG_TBTT(wlc)) {
-			u32 cur, delta;
-			if (wlc->WDarmed) {
-				wl_del_timer(wlc->wl, wlc->wdtimer);
-				wlc->WDarmed = false;
-			}
-
-			cur = OSL_SYSUPTIME();
-			delta = cur > wlc->WDlast ? cur - wlc->WDlast :
-			    (u32) ~0 - wlc->WDlast + cur + 1;
-			if (delta >= TIMER_INTERVAL_WATCHDOG) {
-				wlc_watchdog((void *)wlc);
-				wlc->WDlast = cur;
-			}
-
-			wl_add_timer(wlc->wl, wlc->wdtimer,
-				     wlc_watchdog_backup_bi(wlc), true);
-			wlc->WDarmed = true;
-		}
-	}
-
-	if (!cfg->BSS) {
-		/* DirFrmQ is now valid...defer setting until end of ATIM window */
-		wlc->qvalid |= MCMD_DIRFRMQVAL;
-	}
-}
-
-/* GP timer is a freerunning 32 bit counter, decrements at 1 us rate */
-void wlc_hwtimer_gptimer_set(struct wlc_info *wlc, uint us)
-{
-	ASSERT(wlc->pub->corerev >= 3);	/* no gptimer in earlier revs */
-	W_REG(wlc->osh, &wlc->regs->gptimer, us);
-}
-
-void wlc_hwtimer_gptimer_abort(struct wlc_info *wlc)
-{
-	ASSERT(wlc->pub->corerev >= 3);
-	W_REG(wlc->osh, &wlc->regs->gptimer, 0);
-}
-
-static void wlc_hwtimer_gptimer_cb(struct wlc_info *wlc)
-{
-	/* when interrupt is generated, the counter is loaded with last value
-	 * written and continue to decrement. So it has to be cleaned first
-	 */
-	W_REG(wlc->osh, &wlc->regs->gptimer, 0);
-}
-
-/*
- * This fn has all the high level dpc processing from wlc_dpc.
- * POLICY: no macinstatus change, no bounding loop.
- *         All dpc bounding should be handled in BMAC dpc, like txstatus and rxint
- */
-void wlc_high_dpc(struct wlc_info *wlc, u32 macintstatus)
-{
-	d11regs_t *regs = wlc->regs;
-#ifdef BCMDBG
-	char flagstr[128];
-	static const bcm_bit_desc_t int_flags[] = {
-		{MI_MACSSPNDD, "MACSSPNDD"},
-		{MI_BCNTPL, "BCNTPL"},
-		{MI_TBTT, "TBTT"},
-		{MI_BCNSUCCESS, "BCNSUCCESS"},
-		{MI_BCNCANCLD, "BCNCANCLD"},
-		{MI_ATIMWINEND, "ATIMWINEND"},
-		{MI_PMQ, "PMQ"},
-		{MI_NSPECGEN_0, "NSPECGEN_0"},
-		{MI_NSPECGEN_1, "NSPECGEN_1"},
-		{MI_MACTXERR, "MACTXERR"},
-		{MI_NSPECGEN_3, "NSPECGEN_3"},
-		{MI_PHYTXERR, "PHYTXERR"},
-		{MI_PME, "PME"},
-		{MI_GP0, "GP0"},
-		{MI_GP1, "GP1"},
-		{MI_DMAINT, "DMAINT"},
-		{MI_TXSTOP, "TXSTOP"},
-		{MI_CCA, "CCA"},
-		{MI_BG_NOISE, "BG_NOISE"},
-		{MI_DTIM_TBTT, "DTIM_TBTT"},
-		{MI_PRQ, "PRQ"},
-		{MI_PWRUP, "PWRUP"},
-		{MI_RFDISABLE, "RFDISABLE"},
-		{MI_TFS, "TFS"},
-		{MI_PHYCHANGED, "PHYCHANGED"},
-		{MI_TO, "TO"},
-		{0, NULL}
-	};
-
-	if (macintstatus & ~(MI_TBTT | MI_TXSTOP)) {
-		bcm_format_flags(int_flags, macintstatus, flagstr,
-				 sizeof(flagstr));
-		WL_TRACE("wl%d: macintstatus 0x%x %s\n",
-			 wlc->pub->unit, macintstatus, flagstr);
-	}
-#endif				/* BCMDBG */
-
-	if (macintstatus & MI_PRQ) {
-		/* Process probe request FIFO */
-		ASSERT(0 && "PRQ Interrupt in non-MBSS");
-	}
-
-	/* TBTT indication */
-	/* ucode only gives either TBTT or DTIM_TBTT, not both */
-	if (macintstatus & (MI_TBTT | MI_DTIM_TBTT))
-		wlc_tbtt(wlc, regs);
-
-	if (macintstatus & MI_GP0) {
-		WL_ERROR("wl%d: PSM microcode watchdog fired at %d (seconds). Resetting.\n",
-			 wlc->pub->unit, wlc->pub->now);
-
-		printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
-					__func__, wlc->pub->sih->chip,
-					wlc->pub->sih->chiprev);
-
-		WLCNTINCR(wlc->pub->_cnt->psmwds);
-
-		/* big hammer */
-		wl_init(wlc->wl);
-	}
-
-	/* gptimer timeout */
-	if (macintstatus & MI_TO) {
-		wlc_hwtimer_gptimer_cb(wlc);
-	}
-
-	if (macintstatus & MI_RFDISABLE) {
-		WL_ERROR("wl%d: MAC Detected a change on the RF Disable Input 0x%x\n",
-			 wlc->pub->unit,
-			 R_REG(wlc->osh, &regs->phydebug) & PDBG_RFD);
-		/* delay the cleanup to wl_down in IBSS case */
-		if ((R_REG(wlc->osh, &regs->phydebug) & PDBG_RFD)) {
-			int idx;
-			wlc_bsscfg_t *bsscfg;
-			FOREACH_BSS(wlc, idx, bsscfg) {
-				if (!BSSCFG_STA(bsscfg) || !bsscfg->enable
-				    || !bsscfg->BSS)
-					continue;
-				WL_ERROR("wl%d: wlc_dpc: rfdisable -> wlc_bsscfg_disable()\n",
-					 wlc->pub->unit);
-			}
-		}
-	}
-
-	/* send any enq'd tx packets. Just makes sure to jump start tx */
-	if (!pktq_empty(&wlc->active_queue->q))
-		wlc_send_q(wlc, wlc->active_queue);
-
-	ASSERT(wlc_ps_check(wlc));
-}
-
-static void *wlc_15420war(struct wlc_info *wlc, uint queue)
-{
-	struct hnddma_pub *di;
-	void *p;
-
-	ASSERT(queue < NFIFO);
-
-	if ((D11REV_IS(wlc->pub->corerev, 4))
-	    || (D11REV_GT(wlc->pub->corerev, 6)))
-		return NULL;
-
-	di = wlc->hw->di[queue];
-	ASSERT(di != NULL);
-
-	/* get next packet, ignoring XmtStatus.Curr */
-	p = dma_getnexttxp(di, HNDDMA_RANGE_ALL);
-
-	/* sw block tx dma */
-	dma_txblock(di);
-
-	/* if tx ring is now empty, reset and re-init the tx dma channel */
-	if (dma_txactive(wlc->hw->di[queue]) == 0) {
-		WLCNTINCR(wlc->pub->_cnt->txdmawar);
-		if (!dma_txreset(di))
-			WL_ERROR("wl%d: %s: dma_txreset[%d]: cannot stop dma\n",
-				 wlc->pub->unit, __func__, queue);
-		dma_txinit(di);
-	}
-	return p;
-}
-
-static void wlc_war16165(struct wlc_info *wlc, bool tx)
-{
-	if (tx) {
-		/* the post-increment is used in STAY_AWAKE macro */
-		if (wlc->txpend16165war++ == 0)
-			wlc_set_ps_ctrl(wlc);
-	} else {
-		wlc->txpend16165war--;
-		if (wlc->txpend16165war == 0)
-			wlc_set_ps_ctrl(wlc);
-	}
-}
-
-/* process an individual tx_status_t */
-/* WLC_HIGH_API */
-bool BCMFASTPATH
-wlc_dotxstatus(struct wlc_info *wlc, tx_status_t *txs, u32 frm_tx2)
-{
-	struct sk_buff *p;
-	uint queue;
-	d11txh_t *txh;
-	struct scb *scb = NULL;
-	bool free_pdu;
-	struct osl_info *osh;
-	int tx_rts, tx_frame_count, tx_rts_count;
-	uint totlen, supr_status;
-	bool lastframe;
-	struct dot11_header *h;
-	u16 fc;
-	u16 mcl;
-	struct ieee80211_tx_info *tx_info;
-	struct ieee80211_tx_rate *txrate;
-	int i;
-
-	(void)(frm_tx2);	/* Compiler reference to avoid unused variable warning */
-
-	/* discard intermediate indications for ucode with one legitimate case:
-	 *   e.g. if "useRTS" is set. ucode did a successful rts/cts exchange, but the subsequent
-	 *   tx of DATA failed. so it will start rts/cts from the beginning (resetting the rts
-	 *   transmission count)
-	 */
-	if (!(txs->status & TX_STATUS_AMPDU)
-	    && (txs->status & TX_STATUS_INTERMEDIATE)) {
-		WLCNTADD(wlc->pub->_cnt->txnoack,
-			 ((txs->
-			   status & TX_STATUS_FRM_RTX_MASK) >>
-			  TX_STATUS_FRM_RTX_SHIFT));
-		WL_ERROR("%s: INTERMEDIATE but not AMPDU\n", __func__);
-		return false;
-	}
-
-	osh = wlc->osh;
-	queue = txs->frameid & TXFID_QUEUE_MASK;
-	ASSERT(queue < NFIFO);
-	if (queue >= NFIFO) {
-		p = NULL;
-		goto fatal;
-	}
-
-	p = GETNEXTTXP(wlc, queue);
-	if (WLC_WAR16165(wlc))
-		wlc_war16165(wlc, false);
-	if (p == NULL)
-		p = wlc_15420war(wlc, queue);
-	ASSERT(p != NULL);
-	if (p == NULL)
-		goto fatal;
-
-	txh = (d11txh_t *) (p->data);
-	mcl = ltoh16(txh->MacTxControlLow);
-
-	if (txs->phyerr) {
-		WL_ERROR("phyerr 0x%x, rate 0x%x\n",
-			 txs->phyerr, txh->MainRates);
-		wlc_print_txdesc(txh);
-		wlc_print_txstatus(txs);
-	}
-
-	ASSERT(txs->frameid == htol16(txh->TxFrameID));
-	if (txs->frameid != htol16(txh->TxFrameID))
-		goto fatal;
-
-	tx_info = IEEE80211_SKB_CB(p);
-	h = (struct dot11_header *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-	fc = ltoh16(h->fc);
-
-	scb = (struct scb *)tx_info->control.sta->drv_priv;
-
-	if (N_ENAB(wlc->pub)) {
-		u8 *plcp = (u8 *) (txh + 1);
-		if (PLCP3_ISSGI(plcp[3]))
-			WLCNTINCR(wlc->pub->_cnt->txmpdu_sgi);
-		if (PLCP3_ISSTBC(plcp[3]))
-			WLCNTINCR(wlc->pub->_cnt->txmpdu_stbc);
-	}
-
-	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
-		ASSERT((mcl & TXC_AMPDU_MASK) != TXC_AMPDU_NONE);
-		wlc_ampdu_dotxstatus(wlc->ampdu, scb, p, txs);
-		return false;
-	}
-
-	supr_status = txs->status & TX_STATUS_SUPR_MASK;
-	if (supr_status == TX_STATUS_SUPR_BADCH)
-		WL_NONE("%s: Pkt tx suppressed, possibly channel %d\n",
-			__func__, CHSPEC_CHANNEL(wlc->default_bss->chanspec));
-
-	tx_rts = htol16(txh->MacTxControlLow) & TXC_SENDRTS;
-	tx_frame_count =
-	    (txs->status & TX_STATUS_FRM_RTX_MASK) >> TX_STATUS_FRM_RTX_SHIFT;
-	tx_rts_count =
-	    (txs->status & TX_STATUS_RTS_RTX_MASK) >> TX_STATUS_RTS_RTX_SHIFT;
-
-	lastframe = (fc & FC_MOREFRAG) == 0;
-
-	if (!lastframe) {
-		WL_ERROR("Not last frame!\n");
-	} else {
-		u16 sfbl, lfbl;
-		ieee80211_tx_info_clear_status(tx_info);
-		if (queue < AC_COUNT) {
-			sfbl = WLC_WME_RETRY_SFB_GET(wlc, wme_fifo2ac[queue]);
-			lfbl = WLC_WME_RETRY_LFB_GET(wlc, wme_fifo2ac[queue]);
-		} else {
-			sfbl = wlc->SFBL;
-			lfbl = wlc->LFBL;
-		}
-
-		txrate = tx_info->status.rates;
-		/* FIXME: this should use a combination of sfbl, lfbl depending on frame length and RTS setting */
-		if ((tx_frame_count > sfbl) && (txrate[1].idx >= 0)) {
-			/* rate selection requested a fallback rate and we used it */
-			txrate->count = lfbl;
-			txrate[1].count = tx_frame_count - lfbl;
-		} else {
-			/* rate selection did not request fallback rate, or we didn't need it */
-			txrate->count = tx_frame_count;
-			/* rc80211_minstrel.c:minstrel_tx_status() expects unused rates to be marked with idx = -1 */
-			txrate[1].idx = -1;
-			txrate[1].count = 0;
-		}
-
-		/* clear the rest of the rates */
-		for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
-			txrate[i].idx = -1;
-			txrate[i].count = 0;
-		}
-
-		if (txs->status & TX_STATUS_ACK_RCV)
-			tx_info->flags |= IEEE80211_TX_STAT_ACK;
-	}
-
-	totlen = pkttotlen(osh, p);
-	free_pdu = true;
-
-	wlc_txfifo_complete(wlc, queue, 1);
-
-	if (lastframe) {
-		p->next = NULL;
-		p->prev = NULL;
-		wlc->txretried = 0;
-		/* remove PLCP & Broadcom tx descriptor header */
-		skb_pull(p, D11_PHY_HDR_LEN);
-		skb_pull(p, D11_TXH_LEN);
-		ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw, p);
-		WLCNTINCR(wlc->pub->_cnt->ieee_tx_status);
-	} else {
-		WL_ERROR("%s: Not last frame => not calling tx_status\n",
-			 __func__);
-	}
-
-	return false;
-
- fatal:
-	ASSERT(0);
-	if (p)
-		pkt_buf_free_skb(osh, p, true);
-
-	return true;
-
-}
-
-void BCMFASTPATH
-wlc_txfifo_complete(struct wlc_info *wlc, uint fifo, s8 txpktpend)
-{
-	TXPKTPENDDEC(wlc, fifo, txpktpend);
-	WL_TRACE("wlc_txfifo_complete, pktpend dec %d to %d\n",
-		 txpktpend, TXPKTPENDGET(wlc, fifo));
-
-	/* There is more room; mark precedences related to this FIFO sendable */
-	WLC_TX_FIFO_ENAB(wlc, fifo);
-	ASSERT(TXPKTPENDGET(wlc, fifo) >= 0);
-
-	if (!TXPKTPENDTOT(wlc)) {
-		if (wlc->block_datafifo & DATA_BLOCK_TX_SUPR)
-			wlc_bsscfg_tx_check(wlc);
-	}
-
-	/* Clear MHF2_TXBCMC_NOW flag if BCMC fifo has drained */
-	if (AP_ENAB(wlc->pub) &&
-	    wlc->bcmcfifo_drain && !TXPKTPENDGET(wlc, TX_BCMC_FIFO)) {
-		wlc->bcmcfifo_drain = false;
-		wlc_mhf(wlc, MHF2, MHF2_TXBCMC_NOW, 0, WLC_BAND_AUTO);
-	}
-
-	/* figure out which bsscfg is being worked on... */
-}
-
-/* Given the beacon interval in kus, and a 64 bit TSF in us,
- * return the offset (in us) of the TSF from the last TBTT
- */
-u32 wlc_calc_tbtt_offset(u32 bp, u32 tsf_h, u32 tsf_l)
-{
-	u32 k, btklo, btkhi, offset;
-
-	/* TBTT is always an even multiple of the beacon_interval,
-	 * so the TBTT less than or equal to the beacon timestamp is
-	 * the beacon timestamp minus the beacon timestamp modulo
-	 * the beacon interval.
-	 *
-	 * TBTT = BT - (BT % BIu)
-	 *      = (BTk - (BTk % BP)) * 2^10
-	 *
-	 * BT = beacon timestamp (usec, 64bits)
-	 * BTk = beacon timestamp (Kusec, 54bits)
-	 * BP = beacon interval (Kusec, 16bits)
-	 * BIu = BP * 2^10 = beacon interval (usec, 26bits)
-	 *
-	 * To keep the calculations in u32s, the modulo operation
-	 * on the high part of BT needs to be done in parts using the
-	 * relations:
-	 * X*Y mod Z = ((X mod Z) * (Y mod Z)) mod Z
-	 * and
-	 * (X + Y) mod Z = ((X mod Z) + (Y mod Z)) mod Z
-	 *
-	 * So, if BTk[n] = u16 n [0,3] of BTk.
-	 * BTk % BP = SUM((BTk[n] * 2^16n) % BP , 0<=n<4) % BP
-	 * and the SUM term can be broken down:
-	 * (BTk[n] *     2^16n)    % BP
-	 * (BTk[n] * (2^16n % BP)) % BP
-	 *
-	 * Create a set of power of 2 mod BP constants:
-	 * K[n] = 2^(16n) % BP
-	 *      = (K[n-1] * 2^16) % BP
-	 * K[2] = 2^32 % BP = ((2^16 % BP) * 2^16) % BP
-	 *
-	 * BTk % BP = BTk[0-1] % BP +
-	 *            (BTk[2] * K[2]) % BP +
-	 *            (BTk[3] * K[3]) % BP
-	 *
-	 * Since K[n] < 2^16 and BTk[n] is < 2^16, then BTk[n] * K[n] < 2^32
-	 */
-
-	/* BTk = BT >> 10, btklo = BTk[0-3], bkthi = BTk[4-6] */
-	btklo = (tsf_h << 22) | (tsf_l >> 10);
-	btkhi = tsf_h >> 10;
-
-	/* offset = BTk % BP */
-	offset = btklo % bp;
-
-	/* K[2] = ((2^16 % BP) * 2^16) % BP */
-	k = (u32) (1 << 16) % bp;
-	k = (u32) (k * 1 << 16) % (u32) bp;
-
-	/* offset += (BTk[2] * K[2]) % BP */
-	offset += ((btkhi & 0xffff) * k) % bp;
-
-	/* BTk[3] */
-	btkhi = btkhi >> 16;
-
-	/* k[3] = (K[2] * 2^16) % BP */
-	k = (k << 16) % bp;
-
-	/* offset += (BTk[3] * K[3]) % BP */
-	offset += ((btkhi & 0xffff) * k) % bp;
-
-	offset = offset % bp;
-
-	/* convert offset from kus to us by shifting up 10 bits and
-	 * add in the low 10 bits of tsf that we ignored
-	 */
-	offset = (offset << 10) + (tsf_l & 0x3FF);
-
-	return offset;
-}
-
-/* Update beacon listen interval in shared memory */
-void wlc_bcn_li_upd(struct wlc_info *wlc)
-{
-	if (AP_ENAB(wlc->pub))
-		return;
-
-	/* wake up every DTIM is the default */
-	if (wlc->bcn_li_dtim == 1)
-		wlc_write_shm(wlc, M_BCN_LI, 0);
-	else
-		wlc_write_shm(wlc, M_BCN_LI,
-			      (wlc->bcn_li_dtim << 8) | wlc->bcn_li_bcn);
-}
-
-static void
-prep_mac80211_status(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p,
-		     struct ieee80211_rx_status *rx_status)
-{
-	u32 tsf_l, tsf_h;
-	wlc_d11rxhdr_t *wlc_rxh = (wlc_d11rxhdr_t *) rxh;
-	int preamble;
-	int channel;
-	ratespec_t rspec;
-	unsigned char *plcp;
-
-	wlc_read_tsf(wlc, &tsf_l, &tsf_h);	/* mactime */
-	rx_status->mactime = tsf_h;
-	rx_status->mactime <<= 32;
-	rx_status->mactime |= tsf_l;
-	rx_status->flag |= RX_FLAG_TSFT;
-
-	channel = WLC_CHAN_CHANNEL(rxh->RxChan);
-
-	/* XXX  Channel/badn needs to be filtered against whether we are single/dual band card */
-	if (channel > 14) {
-		rx_status->band = IEEE80211_BAND_5GHZ;
-		rx_status->freq = wf_channel2mhz(channel, WF_CHAN_FACTOR_5_G);
-	} else {
-		rx_status->band = IEEE80211_BAND_2GHZ;
-		rx_status->freq = wf_channel2mhz(channel, WF_CHAN_FACTOR_2_4_G);
-	}
-
-	rx_status->signal = wlc_rxh->rssi;	/* signal */
-
-	/* noise */
-	/* qual */
-	rx_status->antenna = (rxh->PhyRxStatus_0 & PRXS0_RXANT_UPSUBBAND) ? 1 : 0;	/* ant */
-
-	plcp = p->data;
-
-	rspec = wlc_compute_rspec(rxh, plcp);
-	if (IS_MCS(rspec)) {
-		rx_status->rate_idx = rspec & RSPEC_RATE_MASK;
-		rx_status->flag |= RX_FLAG_HT;
-		if (RSPEC_IS40MHZ(rspec))
-			rx_status->flag |= RX_FLAG_40MHZ;
-	} else {
-		switch (RSPEC2RATE(rspec)) {
-		case WLC_RATE_1M:
-			rx_status->rate_idx = 0;
-			break;
-		case WLC_RATE_2M:
-			rx_status->rate_idx = 1;
-			break;
-		case WLC_RATE_5M5:
-			rx_status->rate_idx = 2;
-			break;
-		case WLC_RATE_11M:
-			rx_status->rate_idx = 3;
-			break;
-		case WLC_RATE_6M:
-			rx_status->rate_idx = 4;
-			break;
-		case WLC_RATE_9M:
-			rx_status->rate_idx = 5;
-			break;
-		case WLC_RATE_12M:
-			rx_status->rate_idx = 6;
-			break;
-		case WLC_RATE_18M:
-			rx_status->rate_idx = 7;
-			break;
-		case WLC_RATE_24M:
-			rx_status->rate_idx = 8;
-			break;
-		case WLC_RATE_36M:
-			rx_status->rate_idx = 9;
-			break;
-		case WLC_RATE_48M:
-			rx_status->rate_idx = 10;
-			break;
-		case WLC_RATE_54M:
-			rx_status->rate_idx = 11;
-			break;
-		default:
-			WL_ERROR("%s: Unknown rate\n", __func__);
-		}
-
-		/* Determine short preamble and rate_idx */
-		preamble = 0;
-		if (IS_CCK(rspec)) {
-			if (rxh->PhyRxStatus_0 & PRXS0_SHORTH)
-				WL_ERROR("Short CCK\n");
-			rx_status->flag |= RX_FLAG_SHORTPRE;
-		} else if (IS_OFDM(rspec)) {
-			rx_status->flag |= RX_FLAG_SHORTPRE;
-		} else {
-			WL_ERROR("%s: Unknown modulation\n", __func__);
-		}
-	}
-
-	if (PLCP3_ISSGI(plcp[3]))
-		rx_status->flag |= RX_FLAG_SHORT_GI;
-
-	if (rxh->RxStatus1 & RXS_DECERR) {
-		rx_status->flag |= RX_FLAG_FAILED_PLCP_CRC;
-		WL_ERROR("%s:  RX_FLAG_FAILED_PLCP_CRC\n", __func__);
-	}
-	if (rxh->RxStatus1 & RXS_FCSERR) {
-		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-		WL_ERROR("%s:  RX_FLAG_FAILED_FCS_CRC\n", __func__);
-	}
-}
-
-static void
-wlc_recvctl(struct wlc_info *wlc, struct osl_info *osh, d11rxhdr_t *rxh,
-	    struct sk_buff *p)
-{
-	int len_mpdu;
-	struct ieee80211_rx_status rx_status;
-#if defined(BCMDBG)
-	struct sk_buff *skb = p;
-#endif				/* BCMDBG */
-	/* Todo:
-	 * Cache plcp for first MPDU of AMPD and use chacched version for INTERMEDIATE.
-	 * Test for INTERMEDIATE  like so:
-	 * if (!(plcp[0] | plcp[1] | plcp[2]))
-	 */
-
-	memset(&rx_status, 0, sizeof(rx_status));
-	prep_mac80211_status(wlc, rxh, p, &rx_status);
-
-	/* mac header+body length, exclude CRC and plcp header */
-	len_mpdu = p->len - D11_PHY_HDR_LEN - DOT11_FCS_LEN;
-	skb_pull(p, D11_PHY_HDR_LEN);
-	__skb_trim(p, len_mpdu);
-
-	ASSERT(!(p->next));
-	ASSERT(!(p->prev));
-
-	ASSERT(IS_ALIGNED((unsigned long)skb->data, 2));
-
-	memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
-	ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
-
-	WLCNTINCR(wlc->pub->_cnt->ieee_rx);
-	osh->pktalloced--;
-	return;
-}
-
-void wlc_bss_list_free(struct wlc_info *wlc, wlc_bss_list_t *bss_list)
-{
-	uint index;
-	wlc_bss_info_t *bi;
-
-	if (!bss_list) {
-		WL_ERROR("%s: Attempting to free NULL list\n", __func__);
-		return;
-	}
-	/* inspect all BSS descriptor */
-	for (index = 0; index < bss_list->count; index++) {
-		bi = bss_list->ptrs[index];
-		if (bi) {
-			if (bi->bcn_prb) {
-				kfree(bi->bcn_prb);
-			}
-			kfree(bi);
-			bss_list->ptrs[index] = NULL;
-		}
-	}
-	bss_list->count = 0;
-}
-
-/* Process received frames */
-/*
- * Return true if more frames need to be processed. false otherwise.
- * Param 'bound' indicates max. # frames to process before break out.
- */
-/* WLC_HIGH_API */
-void BCMFASTPATH wlc_recv(struct wlc_info *wlc, struct sk_buff *p)
-{
-	d11rxhdr_t *rxh;
-	struct dot11_header *h;
-	struct osl_info *osh;
-	u16 fc;
-	uint len;
-	bool is_amsdu;
-
-	WL_TRACE("wl%d: wlc_recv\n", wlc->pub->unit);
-
-	osh = wlc->osh;
-
-	/* frame starts with rxhdr */
-	rxh = (d11rxhdr_t *) (p->data);
-
-	/* strip off rxhdr */
-	skb_pull(p, wlc->hwrxoff);
-
-	/* fixup rx header endianness */
-	ltoh16_buf((void *)rxh, sizeof(d11rxhdr_t));
-
-	/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
-	if (rxh->RxStatus1 & RXS_PBPRES) {
-		if (p->len < 2) {
-			WLCNTINCR(wlc->pub->_cnt->rxrunt);
-			WL_ERROR("wl%d: wlc_recv: rcvd runt of len %d\n",
-				 wlc->pub->unit, p->len);
-			goto toss;
-		}
-		skb_pull(p, 2);
-	}
-
-	h = (struct dot11_header *)(p->data + D11_PHY_HDR_LEN);
-	len = p->len;
-
-	if (rxh->RxStatus1 & RXS_FCSERR) {
-		if (wlc->pub->mac80211_state & MAC80211_PROMISC_BCNS) {
-			WL_ERROR("FCSERR while scanning******* - tossing\n");
-			goto toss;
-		} else {
-			WL_ERROR("RCSERR!!!\n");
-			goto toss;
-		}
-	}
-
-	/* check received pkt has at least frame control field */
-	if (len >= D11_PHY_HDR_LEN + sizeof(h->fc)) {
-		fc = ltoh16(h->fc);
-	} else {
-		WLCNTINCR(wlc->pub->_cnt->rxrunt);
-		goto toss;
-	}
-
-	is_amsdu = rxh->RxStatus2 & RXS_AMSDU_MASK;
-
-	/* explicitly test bad src address to avoid sending bad deauth */
-	if (!is_amsdu) {
-		/* CTS and ACK CTL frames are w/o a2 */
-		if (FC_TYPE(fc) == FC_TYPE_DATA || FC_TYPE(fc) == FC_TYPE_MNG) {
-			if ((is_zero_ether_addr(h->a2.octet) ||
-			     is_multicast_ether_addr(h->a2.octet))) {
-				WL_ERROR("wl%d: %s: dropping a frame with invalid src mac address, a2: %pM\n",
-					 wlc->pub->unit, __func__, &h->a2);
-				WLCNTINCR(wlc->pub->_cnt->rxbadsrcmac);
-				goto toss;
-			}
-			WLCNTINCR(wlc->pub->_cnt->rxfrag);
-		}
-	}
-
-	/* due to sheer numbers, toss out probe reqs for now */
-	if (FC_TYPE(fc) == FC_TYPE_MNG) {
-		if ((fc & FC_KIND_MASK) == FC_PROBE_REQ)
-			goto toss;
-	}
-
-	if (is_amsdu) {
-		WL_ERROR("%s: is_amsdu causing toss\n", __func__);
-		goto toss;
-	}
-
-	wlc_recvctl(wlc, osh, rxh, p);
-	return;
-
- toss:
-	pkt_buf_free_skb(osh, p, false);
-}
-
-/* calculate frame duration for Mixed-mode L-SIG spoofing, return
- * number of bytes goes in the length field
- *
- * Formula given by HT PHY Spec v 1.13
- *   len = 3(nsyms + nstream + 3) - 3
- */
-u16 BCMFASTPATH
-wlc_calc_lsig_len(struct wlc_info *wlc, ratespec_t ratespec, uint mac_len)
-{
-	uint nsyms, len = 0, kNdps;
-
-	WL_TRACE("wl%d: wlc_calc_lsig_len: rate %d, len%d\n",
-		 wlc->pub->unit, RSPEC2RATE(ratespec), mac_len);
-
-	if (IS_MCS(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		/* MCS_TXS(mcs) returns num tx streams - 1 */
-		int tot_streams = (MCS_TXS(mcs) + 1) + RSPEC_STC(ratespec);
-
-		ASSERT(WLC_PHY_11N_CAP(wlc->band));
-		/* the payload duration calculation matches that of regular ofdm */
-		/* 1000Ndbps = kbps * 4 */
-		kNdps =
-		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
-			     RSPEC_ISSGI(ratespec)) * 4;
-
-		if (RSPEC_STC(ratespec) == 0)
-			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-			nsyms =
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, kNdps);
-		else
-			/* STBC needs to have even number of symbols */
-			nsyms =
-			    2 *
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
-		nsyms += (tot_streams + 3);	/* (+3) account for HT-SIG(2) and HT-STF(1) */
-		/* 3 bytes/symbol @ legacy 6Mbps rate */
-		len = (3 * nsyms) - 3;	/* (-3) excluding service bits and tail bits */
-	}
-
-	return (u16) len;
-}
-
-/* calculate frame duration of a given rate and length, return time in usec unit */
-uint BCMFASTPATH
-wlc_calc_frame_time(struct wlc_info *wlc, ratespec_t ratespec, u8 preamble_type,
-		    uint mac_len)
-{
-	uint nsyms, dur = 0, Ndps, kNdps;
-	uint rate = RSPEC2RATE(ratespec);
-
-	if (rate == 0) {
-		ASSERT(0);
-		WL_ERROR("wl%d: WAR: using rate of 1 mbps\n", wlc->pub->unit);
-		rate = WLC_RATE_1M;
-	}
-
-	WL_TRACE("wl%d: wlc_calc_frame_time: rspec 0x%x, preamble_type %d, len%d\n",
-		 wlc->pub->unit, ratespec, preamble_type, mac_len);
-
-	if (IS_MCS(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
-		ASSERT(WLC_PHY_11N_CAP(wlc->band));
-		ASSERT(WLC_IS_MIMO_PREAMBLE(preamble_type));
-
-		dur = PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
-		if (preamble_type == WLC_MM_PREAMBLE)
-			dur += PREN_MM_EXT;
-		/* 1000Ndbps = kbps * 4 */
-		kNdps =
-		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
-			     RSPEC_ISSGI(ratespec)) * 4;
-
-		if (RSPEC_STC(ratespec) == 0)
-			/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-			nsyms =
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, kNdps);
-		else
-			/* STBC needs to have even number of symbols */
-			nsyms =
-			    2 *
-			    CEIL((APHY_SERVICE_NBITS + 8 * mac_len +
-				  APHY_TAIL_NBITS) * 1000, 2 * kNdps);
-
-		dur += APHY_SYMBOL_TIME * nsyms;
-		if (BAND_2G(wlc->band->bandtype))
-			dur += DOT11_OFDM_SIGNAL_EXTENSION;
-	} else if (IS_OFDM(rate)) {
-		dur = APHY_PREAMBLE_TIME;
-		dur += APHY_SIGNAL_TIME;
-		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
-		Ndps = rate * 2;
-		/* NSyms = CEILING((SERVICE + 8*NBytes + TAIL) / Ndbps) */
-		nsyms =
-		    CEIL((APHY_SERVICE_NBITS + 8 * mac_len + APHY_TAIL_NBITS),
-			 Ndps);
-		dur += APHY_SYMBOL_TIME * nsyms;
-		if (BAND_2G(wlc->band->bandtype))
-			dur += DOT11_OFDM_SIGNAL_EXTENSION;
-	} else {
-		/* calc # bits * 2 so factor of 2 in rate (1/2 mbps) will divide out */
-		mac_len = mac_len * 8 * 2;
-		/* calc ceiling of bits/rate = microseconds of air time */
-		dur = (mac_len + rate - 1) / rate;
-		if (preamble_type & WLC_SHORT_PREAMBLE)
-			dur += BPHY_PLCP_SHORT_TIME;
-		else
-			dur += BPHY_PLCP_TIME;
-	}
-	return dur;
-}
-
-/* The opposite of wlc_calc_frame_time */
-static uint
-wlc_calc_frame_len(struct wlc_info *wlc, ratespec_t ratespec, u8 preamble_type,
-		   uint dur)
-{
-	uint nsyms, mac_len, Ndps, kNdps;
-	uint rate = RSPEC2RATE(ratespec);
-
-	WL_TRACE("wl%d: wlc_calc_frame_len: rspec 0x%x, preamble_type %d, dur %d\n",
-		 wlc->pub->unit, ratespec, preamble_type, dur);
-
-	if (IS_MCS(ratespec)) {
-		uint mcs = ratespec & RSPEC_RATE_MASK;
-		int tot_streams = MCS_TXS(mcs) + RSPEC_STC(ratespec);
-		ASSERT(WLC_PHY_11N_CAP(wlc->band));
-		dur -= PREN_PREAMBLE + (tot_streams * PREN_PREAMBLE_EXT);
-		/* payload calculation matches that of regular ofdm */
-		if (BAND_2G(wlc->band->bandtype))
-			dur -= DOT11_OFDM_SIGNAL_EXTENSION;
-		/* kNdbps = kbps * 4 */
-		kNdps =
-		    MCS_RATE(mcs, RSPEC_IS40MHZ(ratespec),
-			     RSPEC_ISSGI(ratespec)) * 4;
-		nsyms = dur / APHY_SYMBOL_TIME;
-		mac_len =
-		    ((nsyms * kNdps) -
-		     ((APHY_SERVICE_NBITS + APHY_TAIL_NBITS) * 1000)) / 8000;
-	} else if (IS_OFDM(ratespec)) {
-		dur -= APHY_PREAMBLE_TIME;
-		dur -= APHY_SIGNAL_TIME;
-		/* Ndbps = Mbps * 4 = rate(500Kbps) * 2 */
-		Ndps = rate * 2;
-		nsyms = dur / APHY_SYMBOL_TIME;
-		mac_len =
-		    ((nsyms * Ndps) -
-		     (APHY_SERVICE_NBITS + APHY_TAIL_NBITS)) / 8;
-	} else {
-		if (preamble_type & WLC_SHORT_PREAMBLE)
-			dur -= BPHY_PLCP_SHORT_TIME;
-		else
-			dur -= BPHY_PLCP_TIME;
-		mac_len = dur * rate;
-		/* divide out factor of 2 in rate (1/2 mbps) */
-		mac_len = mac_len / 8 / 2;
-	}
-	return mac_len;
-}
-
-static uint
-wlc_calc_ba_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
-{
-	WL_TRACE("wl%d: wlc_calc_ba_time: rspec 0x%x, preamble_type %d\n",
-		 wlc->pub->unit, rspec, preamble_type);
-	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
-	 * or equal to the rate of the immediately previous frame in the FES
-	 */
-	rspec = WLC_BASIC_RATE(wlc, rspec);
-	ASSERT(VALID_RATE_DBG(wlc, rspec));
-
-	/* BA len == 32 == 16(ctl hdr) + 4(ba len) + 8(bitmap) + 4(fcs) */
-	return wlc_calc_frame_time(wlc, rspec, preamble_type,
-				   (DOT11_BA_LEN + DOT11_BA_BITMAP_LEN +
-				    DOT11_FCS_LEN));
-}
-
-static uint BCMFASTPATH
-wlc_calc_ack_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
-{
-	uint dur = 0;
-
-	WL_TRACE("wl%d: wlc_calc_ack_time: rspec 0x%x, preamble_type %d\n",
-		 wlc->pub->unit, rspec, preamble_type);
-	/* Spec 9.6: ack rate is the highest rate in BSSBasicRateSet that is less than
-	 * or equal to the rate of the immediately previous frame in the FES
-	 */
-	rspec = WLC_BASIC_RATE(wlc, rspec);
-	ASSERT(VALID_RATE_DBG(wlc, rspec));
-
-	/* ACK frame len == 14 == 2(fc) + 2(dur) + 6(ra) + 4(fcs) */
-	dur =
-	    wlc_calc_frame_time(wlc, rspec, preamble_type,
-				(DOT11_ACK_LEN + DOT11_FCS_LEN));
-	return dur;
-}
-
-static uint
-wlc_calc_cts_time(struct wlc_info *wlc, ratespec_t rspec, u8 preamble_type)
-{
-	WL_TRACE("wl%d: wlc_calc_cts_time: ratespec 0x%x, preamble_type %d\n",
-		 wlc->pub->unit, rspec, preamble_type);
-	return wlc_calc_ack_time(wlc, rspec, preamble_type);
-}
-
-/* derive wlc->band->basic_rate[] table from 'rateset' */
-void wlc_rate_lookup_init(struct wlc_info *wlc, wlc_rateset_t *rateset)
-{
-	u8 rate;
-	u8 mandatory;
-	u8 cck_basic = 0;
-	u8 ofdm_basic = 0;
-	u8 *br = wlc->band->basic_rate;
-	uint i;
-
-	/* incoming rates are in 500kbps units as in 802.11 Supported Rates */
-	memset(br, 0, WLC_MAXRATE + 1);
-
-	/* For each basic rate in the rates list, make an entry in the
-	 * best basic lookup.
-	 */
-	for (i = 0; i < rateset->count; i++) {
-		/* only make an entry for a basic rate */
-		if (!(rateset->rates[i] & WLC_RATE_FLAG))
-			continue;
-
-		/* mask off basic bit */
-		rate = (rateset->rates[i] & RATE_MASK);
-
-		if (rate > WLC_MAXRATE) {
-			WL_ERROR("wlc_rate_lookup_init: invalid rate 0x%X in rate set\n",
-				 rateset->rates[i]);
-			continue;
-		}
-
-		br[rate] = rate;
-	}
-
-	/* The rate lookup table now has non-zero entries for each
-	 * basic rate, equal to the basic rate: br[basicN] = basicN
-	 *
-	 * To look up the best basic rate corresponding to any
-	 * particular rate, code can use the basic_rate table
-	 * like this
-	 *
-	 * basic_rate = wlc->band->basic_rate[tx_rate]
-	 *
-	 * Make sure there is a best basic rate entry for
-	 * every rate by walking up the table from low rates
-	 * to high, filling in holes in the lookup table
-	 */
-
-	for (i = 0; i < wlc->band->hw_rateset.count; i++) {
-		rate = wlc->band->hw_rateset.rates[i];
-		ASSERT(rate <= WLC_MAXRATE);
-
-		if (br[rate] != 0) {
-			/* This rate is a basic rate.
-			 * Keep track of the best basic rate so far by
-			 * modulation type.
-			 */
-			if (IS_OFDM(rate))
-				ofdm_basic = rate;
-			else
-				cck_basic = rate;
-
-			continue;
-		}
-
-		/* This rate is not a basic rate so figure out the
-		 * best basic rate less than this rate and fill in
-		 * the hole in the table
-		 */
-
-		br[rate] = IS_OFDM(rate) ? ofdm_basic : cck_basic;
-
-		if (br[rate] != 0)
-			continue;
-
-		if (IS_OFDM(rate)) {
-			/* In 11g and 11a, the OFDM mandatory rates are 6, 12, and 24 Mbps */
-			if (rate >= WLC_RATE_24M)
-				mandatory = WLC_RATE_24M;
-			else if (rate >= WLC_RATE_12M)
-				mandatory = WLC_RATE_12M;
-			else
-				mandatory = WLC_RATE_6M;
-		} else {
-			/* In 11b, all the CCK rates are mandatory 1 - 11 Mbps */
-			mandatory = rate;
-		}
-
-		br[rate] = mandatory;
-	}
-}
-
-static void wlc_write_rate_shm(struct wlc_info *wlc, u8 rate, u8 basic_rate)
-{
-	u8 phy_rate, index;
-	u8 basic_phy_rate, basic_index;
-	u16 dir_table, basic_table;
-	u16 basic_ptr;
-
-	/* Shared memory address for the table we are reading */
-	dir_table = IS_OFDM(basic_rate) ? M_RT_DIRMAP_A : M_RT_DIRMAP_B;
-
-	/* Shared memory address for the table we are writing */
-	basic_table = IS_OFDM(rate) ? M_RT_BBRSMAP_A : M_RT_BBRSMAP_B;
-
-	/*
-	 * for a given rate, the LS-nibble of the PLCP SIGNAL field is
-	 * the index into the rate table.
-	 */
-	phy_rate = rate_info[rate] & RATE_MASK;
-	basic_phy_rate = rate_info[basic_rate] & RATE_MASK;
-	index = phy_rate & 0xf;
-	basic_index = basic_phy_rate & 0xf;
-
-	/* Find the SHM pointer to the ACK rate entry by looking in the
-	 * Direct-map Table
-	 */
-	basic_ptr = wlc_read_shm(wlc, (dir_table + basic_index * 2));
-
-	/* Update the SHM BSS-basic-rate-set mapping table with the pointer
-	 * to the correct basic rate for the given incoming rate
-	 */
-	wlc_write_shm(wlc, (basic_table + index * 2), basic_ptr);
-}
-
-static const wlc_rateset_t *wlc_rateset_get_hwrs(struct wlc_info *wlc)
-{
-	const wlc_rateset_t *rs_dflt;
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		if (BAND_5G(wlc->band->bandtype))
-			rs_dflt = &ofdm_mimo_rates;
-		else
-			rs_dflt = &cck_ofdm_mimo_rates;
-	} else if (wlc->band->gmode)
-		rs_dflt = &cck_ofdm_rates;
-	else
-		rs_dflt = &cck_rates;
-
-	return rs_dflt;
-}
-
-void wlc_set_ratetable(struct wlc_info *wlc)
-{
-	const wlc_rateset_t *rs_dflt;
-	wlc_rateset_t rs;
-	u8 rate, basic_rate;
-	uint i;
-
-	rs_dflt = wlc_rateset_get_hwrs(wlc);
-	ASSERT(rs_dflt != NULL);
-
-	wlc_rateset_copy(rs_dflt, &rs);
-	wlc_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
-	/* walk the phy rate table and update SHM basic rate lookup table */
-	for (i = 0; i < rs.count; i++) {
-		rate = rs.rates[i] & RATE_MASK;
-
-		/* for a given rate WLC_BASIC_RATE returns the rate at
-		 * which a response ACK/CTS should be sent.
-		 */
-		basic_rate = WLC_BASIC_RATE(wlc, rate);
-		if (basic_rate == 0) {
-			/* This should only happen if we are using a
-			 * restricted rateset.
-			 */
-			basic_rate = rs.rates[0] & RATE_MASK;
-		}
-
-		wlc_write_rate_shm(wlc, rate, basic_rate);
-	}
-}
-
-/*
- * Return true if the specified rate is supported by the specified band.
- * WLC_BAND_AUTO indicates the current band.
- */
-bool wlc_valid_rate(struct wlc_info *wlc, ratespec_t rspec, int band,
-		    bool verbose)
-{
-	wlc_rateset_t *hw_rateset;
-	uint i;
-
-	if ((band == WLC_BAND_AUTO) || (band == wlc->band->bandtype)) {
-		hw_rateset = &wlc->band->hw_rateset;
-	} else if (NBANDS(wlc) > 1) {
-		hw_rateset = &wlc->bandstate[OTHERBANDUNIT(wlc)]->hw_rateset;
-	} else {
-		/* other band specified and we are a single band device */
-		return false;
-	}
-
-	/* check if this is a mimo rate */
-	if (IS_MCS(rspec)) {
-		if (!VALID_MCS((rspec & RSPEC_RATE_MASK)))
-			goto error;
-
-		return isset(hw_rateset->mcs, (rspec & RSPEC_RATE_MASK));
-	}
-
-	for (i = 0; i < hw_rateset->count; i++)
-		if (hw_rateset->rates[i] == RSPEC2RATE(rspec))
-			return true;
- error:
-	if (verbose) {
-		WL_ERROR("wl%d: wlc_valid_rate: rate spec 0x%x not in hw_rateset\n",
-			 wlc->pub->unit, rspec);
-	}
-
-	return false;
-}
-
-static void wlc_update_mimo_band_bwcap(struct wlc_info *wlc, u8 bwcap)
-{
-	uint i;
-	struct wlcband *band;
-
-	for (i = 0; i < NBANDS(wlc); i++) {
-		if (IS_SINGLEBAND_5G(wlc->deviceid))
-			i = BAND_5G_INDEX;
-		band = wlc->bandstate[i];
-		if (band->bandtype == WLC_BAND_5G) {
-			if ((bwcap == WLC_N_BW_40ALL)
-			    || (bwcap == WLC_N_BW_20IN2G_40IN5G))
-				band->mimo_cap_40 = true;
-			else
-				band->mimo_cap_40 = false;
-		} else {
-			ASSERT(band->bandtype == WLC_BAND_2G);
-			if (bwcap == WLC_N_BW_40ALL)
-				band->mimo_cap_40 = true;
-			else
-				band->mimo_cap_40 = false;
-		}
-	}
-
-	wlc->mimo_band_bwcap = bwcap;
-}
-
-void wlc_mod_prb_rsp_rate_table(struct wlc_info *wlc, uint frame_len)
-{
-	const wlc_rateset_t *rs_dflt;
-	wlc_rateset_t rs;
-	u8 rate;
-	u16 entry_ptr;
-	u8 plcp[D11_PHY_HDR_LEN];
-	u16 dur, sifs;
-	uint i;
-
-	sifs = SIFS(wlc->band);
-
-	rs_dflt = wlc_rateset_get_hwrs(wlc);
-	ASSERT(rs_dflt != NULL);
-
-	wlc_rateset_copy(rs_dflt, &rs);
-	wlc_rateset_mcs_upd(&rs, wlc->stf->txstreams);
-
-	/* walk the phy rate table and update MAC core SHM basic rate table entries */
-	for (i = 0; i < rs.count; i++) {
-		rate = rs.rates[i] & RATE_MASK;
-
-		entry_ptr = wlc_rate_shm_offset(wlc, rate);
-
-		/* Calculate the Probe Response PLCP for the given rate */
-		wlc_compute_plcp(wlc, rate, frame_len, plcp);
-
-		/* Calculate the duration of the Probe Response frame plus SIFS for the MAC */
-		dur =
-		    (u16) wlc_calc_frame_time(wlc, rate, WLC_LONG_PREAMBLE,
-						 frame_len);
-		dur += sifs;
-
-		/* Update the SHM Rate Table entry Probe Response values */
-		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS,
-			      (u16) (plcp[0] + (plcp[1] << 8)));
-		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_PLCP_POS + 2,
-			      (u16) (plcp[2] + (plcp[3] << 8)));
-		wlc_write_shm(wlc, entry_ptr + M_RT_PRS_DUR_POS, dur);
-	}
-}
-
-u16
-wlc_compute_bcntsfoff(struct wlc_info *wlc, ratespec_t rspec,
-		      bool short_preamble, bool phydelay)
-{
-	uint bcntsfoff = 0;
-
-	if (IS_MCS(rspec)) {
-		WL_ERROR("wl%d: recd beacon with mcs rate; rspec 0x%x\n",
-			 wlc->pub->unit, rspec);
-	} else if (IS_OFDM(rspec)) {
-		/* tx delay from MAC through phy to air (2.1 usec) +
-		 * phy header time (preamble + PLCP SIGNAL == 20 usec) +
-		 * PLCP SERVICE + MAC header time (SERVICE + FC + DUR + A1 + A2 + A3 + SEQ == 26
-		 * bytes at beacon rate)
-		 */
-		bcntsfoff += phydelay ? D11A_PHY_TX_DELAY : 0;
-		bcntsfoff += APHY_PREAMBLE_TIME + APHY_SIGNAL_TIME;
-		bcntsfoff +=
-		    wlc_compute_airtime(wlc, rspec,
-					APHY_SERVICE_NBITS / 8 +
-					DOT11_MAC_HDR_LEN);
-	} else {
-		/* tx delay from MAC through phy to air (3.4 usec) +
-		 * phy header time (long preamble + PLCP == 192 usec) +
-		 * MAC header time (FC + DUR + A1 + A2 + A3 + SEQ == 24 bytes at beacon rate)
-		 */
-		bcntsfoff += phydelay ? D11B_PHY_TX_DELAY : 0;
-		bcntsfoff +=
-		    short_preamble ? D11B_PHY_SPREHDR_TIME :
-		    D11B_PHY_LPREHDR_TIME;
-		bcntsfoff += wlc_compute_airtime(wlc, rspec, DOT11_MAC_HDR_LEN);
-	}
-	return (u16) (bcntsfoff);
-}
-
-/*	Max buffering needed for beacon template/prb resp template is 142 bytes.
- *
- *	PLCP header is 6 bytes.
- *	802.11 A3 header is 24 bytes.
- *	Max beacon frame body template length is 112 bytes.
- *	Max probe resp frame body template length is 110 bytes.
- *
- *      *len on input contains the max length of the packet available.
- *
- *	The *len value is set to the number of bytes in buf used, and starts with the PLCP
- *	and included up to, but not including, the 4 byte FCS.
- */
-static void
-wlc_bcn_prb_template(struct wlc_info *wlc, uint type, ratespec_t bcn_rspec,
-		     wlc_bsscfg_t *cfg, u16 *buf, int *len)
-{
-	cck_phy_hdr_t *plcp;
-	struct dot11_management_header *h;
-	int hdr_len, body_len;
-
-	ASSERT(*len >= 142);
-	ASSERT(type == FC_BEACON || type == FC_PROBE_RESP);
-
-	if (MBSS_BCN_ENAB(cfg) && type == FC_BEACON)
-		hdr_len = DOT11_MAC_HDR_LEN;
-	else
-		hdr_len = D11_PHY_HDR_LEN + DOT11_MAC_HDR_LEN;
-	body_len = *len - hdr_len;	/* calc buffer size provided for frame body */
-
-	*len = hdr_len + body_len;	/* return actual size */
-
-	/* format PHY and MAC headers */
-	memset((char *)buf, 0, hdr_len);
-
-	plcp = (cck_phy_hdr_t *) buf;
-
-	/* PLCP for Probe Response frames are filled in from core's rate table */
-	if (type == FC_BEACON && !MBSS_BCN_ENAB(cfg)) {
-		/* fill in PLCP */
-		wlc_compute_plcp(wlc, bcn_rspec,
-				 (DOT11_MAC_HDR_LEN + body_len + DOT11_FCS_LEN),
-				 (u8 *) plcp);
-
-	}
-	/* "Regular" and 16 MBSS but not for 4 MBSS */
-	/* Update the phytxctl for the beacon based on the rspec */
-	if (!SOFTBCN_ENAB(cfg))
-		wlc_beacon_phytxctl_txant_upd(wlc, bcn_rspec);
-
-	if (MBSS_BCN_ENAB(cfg) && type == FC_BEACON)
-		h = (struct dot11_management_header *)&plcp[0];
-	else
-		h = (struct dot11_management_header *)&plcp[1];
-
-	/* fill in 802.11 header */
-	h->fc = htol16((u16) type);
-
-	/* DUR is 0 for multicast bcn, or filled in by MAC for prb resp */
-	/* A1 filled in by MAC for prb resp, broadcast for bcn */
-	if (type == FC_BEACON)
-		bcopy((const char *)&ether_bcast, (char *)&h->da,
-		      ETH_ALEN);
-	bcopy((char *)&cfg->cur_etheraddr, (char *)&h->sa, ETH_ALEN);
-	bcopy((char *)&cfg->BSSID, (char *)&h->bssid, ETH_ALEN);
-
-	/* SEQ filled in by MAC */
-
-	return;
-}
-
-int wlc_get_header_len()
-{
-	return TXOFF;
-}
-
-/* Update a beacon for a particular BSS
- * For MBSS, this updates the software template and sets "latest" to the index of the
- * template updated.
- * Otherwise, it updates the hardware template.
- */
-void wlc_bss_update_beacon(struct wlc_info *wlc, wlc_bsscfg_t *cfg)
-{
-	int len = BCN_TMPL_LEN;
-
-	/* Clear the soft intmask */
-	wlc->defmacintmask &= ~MI_BCNTPL;
-
-	if (!cfg->up) {		/* Only allow updates on an UP bss */
-		return;
-	}
-
-	if (MBSS_BCN_ENAB(cfg)) {	/* Optimize:  Some of if/else could be combined */
-	} else if (HWBCN_ENAB(cfg)) {	/* Hardware beaconing for this config */
-		u16 bcn[BCN_TMPL_LEN / 2];
-		u32 both_valid = MCMD_BCN0VLD | MCMD_BCN1VLD;
-		d11regs_t *regs = wlc->regs;
-		struct osl_info *osh = NULL;
-
-		osh = wlc->osh;
-
-		/* Check if both templates are in use, if so sched. an interrupt
-		 *      that will call back into this routine
-		 */
-		if ((R_REG(osh, &regs->maccommand) & both_valid) == both_valid) {
-			/* clear any previous status */
-			W_REG(osh, &regs->macintstatus, MI_BCNTPL);
-		}
-		/* Check that after scheduling the interrupt both of the
-		 *      templates are still busy. if not clear the int. & remask
-		 */
-		if ((R_REG(osh, &regs->maccommand) & both_valid) == both_valid) {
-			wlc->defmacintmask |= MI_BCNTPL;
-			return;
-		}
-
-		wlc->bcn_rspec =
-		    wlc_lowest_basic_rspec(wlc, &cfg->current_bss->rateset);
-		ASSERT(wlc_valid_rate
-		       (wlc, wlc->bcn_rspec,
-			CHSPEC_IS2G(cfg->current_bss->
-				    chanspec) ? WLC_BAND_2G : WLC_BAND_5G,
-			true));
-
-		/* update the template and ucode shm */
-		wlc_bcn_prb_template(wlc, FC_BEACON, wlc->bcn_rspec, cfg, bcn,
-				     &len);
-		wlc_write_hw_bcntemplates(wlc, bcn, len, false);
-	}
-}
-
-/*
- * Update all beacons for the system.
- */
-void wlc_update_beacon(struct wlc_info *wlc)
-{
-	int idx;
-	wlc_bsscfg_t *bsscfg;
-
-	/* update AP or IBSS beacons */
-	FOREACH_BSS(wlc, idx, bsscfg) {
-		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
-			wlc_bss_update_beacon(wlc, bsscfg);
-	}
-}
-
-/* Write ssid into shared memory */
-void wlc_shm_ssid_upd(struct wlc_info *wlc, wlc_bsscfg_t *cfg)
-{
-	u8 *ssidptr = cfg->SSID;
-	u16 base = M_SSID;
-	u8 ssidbuf[DOT11_MAX_SSID_LEN];
-
-	/* padding the ssid with zero and copy it into shm */
-	memset(ssidbuf, 0, DOT11_MAX_SSID_LEN);
-	bcopy(ssidptr, ssidbuf, cfg->SSID_len);
-
-	wlc_copyto_shm(wlc, base, ssidbuf, DOT11_MAX_SSID_LEN);
-
-	if (!MBSS_BCN_ENAB(cfg))
-		wlc_write_shm(wlc, M_SSIDLEN, (u16) cfg->SSID_len);
-}
-
-void wlc_update_probe_resp(struct wlc_info *wlc, bool suspend)
-{
-	int idx;
-	wlc_bsscfg_t *bsscfg;
-
-	/* update AP or IBSS probe responses */
-	FOREACH_BSS(wlc, idx, bsscfg) {
-		if (bsscfg->up && (BSSCFG_AP(bsscfg) || !bsscfg->BSS))
-			wlc_bss_update_probe_resp(wlc, bsscfg, suspend);
-	}
-}
-
-void
-wlc_bss_update_probe_resp(struct wlc_info *wlc, wlc_bsscfg_t *cfg, bool suspend)
-{
-	u16 prb_resp[BCN_TMPL_LEN / 2];
-	int len = BCN_TMPL_LEN;
-
-	/* write the probe response to hardware, or save in the config structure */
-	if (!MBSS_PRB_ENAB(cfg)) {
-
-		/* create the probe response template */
-		wlc_bcn_prb_template(wlc, FC_PROBE_RESP, 0, cfg, prb_resp,
-				     &len);
-
-		if (suspend)
-			wlc_suspend_mac_and_wait(wlc);
-
-		/* write the probe response into the template region */
-		wlc_bmac_write_template_ram(wlc->hw, T_PRS_TPL_BASE,
-					    (len + 3) & ~3, prb_resp);
-
-		/* write the length of the probe response frame (+PLCP/-FCS) */
-		wlc_write_shm(wlc, M_PRB_RESP_FRM_LEN, (u16) len);
-
-		/* write the SSID and SSID length */
-		wlc_shm_ssid_upd(wlc, cfg);
-
-		/*
-		 * Write PLCP headers and durations for probe response frames at all rates.
-		 * Use the actual frame length covered by the PLCP header for the call to
-		 * wlc_mod_prb_rsp_rate_table() by subtracting the PLCP len and adding the FCS.
-		 */
-		len += (-D11_PHY_HDR_LEN + DOT11_FCS_LEN);
-		wlc_mod_prb_rsp_rate_table(wlc, (u16) len);
-
-		if (suspend)
-			wlc_enable_mac(wlc);
-	} else {		/* Generating probe resp in sw; update local template */
-		ASSERT(0 && "No software probe response support without MBSS");
-	}
-}
-
-/* prepares pdu for transmission. returns BCM error codes */
-int wlc_prep_pdu(struct wlc_info *wlc, struct sk_buff *pdu, uint *fifop)
-{
-	struct osl_info *osh;
-	uint fifo;
-	d11txh_t *txh;
-	struct dot11_header *h;
-	struct scb *scb;
-	u16 fc;
-
-	osh = wlc->osh;
-
-	ASSERT(pdu);
-	txh = (d11txh_t *) (pdu->data);
-	ASSERT(txh);
-	h = (struct dot11_header *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
-	ASSERT(h);
-	fc = ltoh16(h->fc);
-
-	/* get the pkt queue info. This was put at wlc_sendctl or wlc_send for PDU */
-	fifo = ltoh16(txh->TxFrameID) & TXFID_QUEUE_MASK;
-
-	scb = NULL;
-
-	*fifop = fifo;
-
-	/* return if insufficient dma resources */
-	if (TXAVAIL(wlc, fifo) < MAX_DMA_SEGS) {
-		/* Mark precedences related to this FIFO, unsendable */
-		WLC_TX_FIFO_CLEAR(wlc, fifo);
-		return BCME_BUSY;
-	}
-
-	if (FC_TYPE(ltoh16(txh->MacFrameControl)) != FC_TYPE_DATA)
-		WLCNTINCR(wlc->pub->_cnt->txctl);
-
-	return 0;
-}
-
-/* init tx reported rate mechanism */
-void wlc_reprate_init(struct wlc_info *wlc)
-{
-	int i;
-	wlc_bsscfg_t *bsscfg;
-
-	FOREACH_BSS(wlc, i, bsscfg) {
-		wlc_bsscfg_reprate_init(bsscfg);
-	}
-}
-
-/* per bsscfg init tx reported rate mechanism */
-void wlc_bsscfg_reprate_init(wlc_bsscfg_t *bsscfg)
-{
-	bsscfg->txrspecidx = 0;
-	memset((char *)bsscfg->txrspec, 0, sizeof(bsscfg->txrspec));
-}
-
-/* Retrieve a consolidated set of revision information,
- * typically for the WLC_GET_REVINFO ioctl
- */
-int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len)
-{
-	wlc_rev_info_t *rinfo = (wlc_rev_info_t *) buf;
-
-	if (len < WL_REV_INFO_LEGACY_LENGTH)
-		return BCME_BUFTOOSHORT;
-
-	rinfo->vendorid = wlc->vendorid;
-	rinfo->deviceid = wlc->deviceid;
-	rinfo->radiorev = (wlc->band->radiorev << IDCODE_REV_SHIFT) |
-	    (wlc->band->radioid << IDCODE_ID_SHIFT);
-	rinfo->chiprev = wlc->pub->sih->chiprev;
-	rinfo->corerev = wlc->pub->corerev;
-	rinfo->boardid = wlc->pub->sih->boardtype;
-	rinfo->boardvendor = wlc->pub->sih->boardvendor;
-	rinfo->boardrev = wlc->pub->boardrev;
-	rinfo->ucoderev = wlc->ucode_rev;
-	rinfo->driverrev = EPI_VERSION_NUM;
-	rinfo->bus = wlc->pub->sih->bustype;
-	rinfo->chipnum = wlc->pub->sih->chip;
-
-	if (len >= (offsetof(wlc_rev_info_t, chippkg))) {
-		rinfo->phytype = wlc->band->phytype;
-		rinfo->phyrev = wlc->band->phyrev;
-		rinfo->anarev = 0;	/* obsolete stuff, suppress */
-	}
-
-	if (len >= sizeof(*rinfo)) {
-		rinfo->chippkg = wlc->pub->sih->chippkg;
-	}
-
-	return BCME_OK;
-}
-
-void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs)
-{
-	wlc_rateset_default(rs, NULL, wlc->band->phytype, wlc->band->bandtype,
-			    false, RATE_MASK_FULL, (bool) N_ENAB(wlc->pub),
-			    CHSPEC_WLC_BW(wlc->default_bss->chanspec),
-			    wlc->stf->txstreams);
-}
-
-static void wlc_bss_default_init(struct wlc_info *wlc)
-{
-	chanspec_t chanspec;
-	struct wlcband *band;
-	wlc_bss_info_t *bi = wlc->default_bss;
-
-	/* init default and target BSS with some sane initial values */
-	memset((char *)(bi), 0, sizeof(wlc_bss_info_t));
-	bi->beacon_period = ISSIM_ENAB(wlc->pub->sih) ? BEACON_INTERVAL_DEF_QT :
-	    BEACON_INTERVAL_DEFAULT;
-	bi->dtim_period = ISSIM_ENAB(wlc->pub->sih) ? DTIM_INTERVAL_DEF_QT :
-	    DTIM_INTERVAL_DEFAULT;
-
-	/* fill the default channel as the first valid channel
-	 * starting from the 2G channels
-	 */
-	chanspec = CH20MHZ_CHSPEC(1);
-	ASSERT(chanspec != INVCHANSPEC);
-
-	wlc->home_chanspec = bi->chanspec = chanspec;
-
-	/* find the band of our default channel */
-	band = wlc->band;
-	if (NBANDS(wlc) > 1 && band->bandunit != CHSPEC_WLCBANDUNIT(chanspec))
-		band = wlc->bandstate[OTHERBANDUNIT(wlc)];
-
-	/* init bss rates to the band specific default rate set */
-	wlc_rateset_default(&bi->rateset, NULL, band->phytype, band->bandtype,
-			    false, RATE_MASK_FULL, (bool) N_ENAB(wlc->pub),
-			    CHSPEC_WLC_BW(chanspec), wlc->stf->txstreams);
-
-	if (N_ENAB(wlc->pub))
-		bi->flags |= WLC_BSS_HT;
-}
-
-/* Deferred event processing */
-static void wlc_process_eventq(void *arg)
-{
-	struct wlc_info *wlc = (struct wlc_info *) arg;
-	wlc_event_t *etmp;
-
-	while ((etmp = wlc_eventq_deq(wlc->eventq))) {
-		/* Perform OS specific event processing */
-		wl_event(wlc->wl, etmp->event.ifname, etmp);
-		if (etmp->data) {
-			kfree(etmp->data);
-			etmp->data = NULL;
-		}
-		wlc_event_free(wlc->eventq, etmp);
-	}
-}
-
-void
-wlc_uint64_sub(u32 *a_high, u32 *a_low, u32 b_high, u32 b_low)
-{
-	if (b_low > *a_low) {
-		/* low half needs a carry */
-		b_high += 1;
-	}
-	*a_low -= b_low;
-	*a_high -= b_high;
-}
-
-static ratespec_t
-mac80211_wlc_set_nrate(struct wlc_info *wlc, struct wlcband *cur_band,
-		       u32 int_val)
-{
-	u8 stf = (int_val & NRATE_STF_MASK) >> NRATE_STF_SHIFT;
-	u8 rate = int_val & NRATE_RATE_MASK;
-	ratespec_t rspec;
-	bool ismcs = ((int_val & NRATE_MCS_INUSE) == NRATE_MCS_INUSE);
-	bool issgi = ((int_val & NRATE_SGI_MASK) >> NRATE_SGI_SHIFT);
-	bool override_mcs_only = ((int_val & NRATE_OVERRIDE_MCS_ONLY)
-				  == NRATE_OVERRIDE_MCS_ONLY);
-	int bcmerror = 0;
-
-	if (!ismcs) {
-		return (ratespec_t) rate;
-	}
-
-	/* validate the combination of rate/mcs/stf is allowed */
-	if (N_ENAB(wlc->pub) && ismcs) {
-		/* mcs only allowed when nmode */
-		if (stf > PHY_TXC1_MODE_SDM) {
-			WL_ERROR("wl%d: %s: Invalid stf\n",
-				 WLCWLUNIT(wlc), __func__);
-			bcmerror = BCME_RANGE;
-			goto done;
-		}
-
-		/* mcs 32 is a special case, DUP mode 40 only */
-		if (rate == 32) {
-			if (!CHSPEC_IS40(wlc->home_chanspec) ||
-			    ((stf != PHY_TXC1_MODE_SISO)
-			     && (stf != PHY_TXC1_MODE_CDD))) {
-				WL_ERROR("wl%d: %s: Invalid mcs 32\n",
-					 WLCWLUNIT(wlc), __func__);
-				bcmerror = BCME_RANGE;
-				goto done;
-			}
-			/* mcs > 7 must use stf SDM */
-		} else if (rate > HIGHEST_SINGLE_STREAM_MCS) {
-			/* mcs > 7 must use stf SDM */
-			if (stf != PHY_TXC1_MODE_SDM) {
-				WL_TRACE("wl%d: %s: enabling SDM mode for mcs %d\n",
-					 WLCWLUNIT(wlc), __func__, rate);
-				stf = PHY_TXC1_MODE_SDM;
-			}
-		} else {
-			/* MCS 0-7 may use SISO, CDD, and for phy_rev >= 3 STBC */
-			if ((stf > PHY_TXC1_MODE_STBC) ||
-			    (!WLC_STBC_CAP_PHY(wlc)
-			     && (stf == PHY_TXC1_MODE_STBC))) {
-				WL_ERROR("wl%d: %s: Invalid STBC\n",
-					 WLCWLUNIT(wlc), __func__);
-				bcmerror = BCME_RANGE;
-				goto done;
-			}
-		}
-	} else if (IS_OFDM(rate)) {
-		if ((stf != PHY_TXC1_MODE_CDD) && (stf != PHY_TXC1_MODE_SISO)) {
-			WL_ERROR("wl%d: %s: Invalid OFDM\n",
-				 WLCWLUNIT(wlc), __func__);
-			bcmerror = BCME_RANGE;
-			goto done;
-		}
-	} else if (IS_CCK(rate)) {
-		if ((cur_band->bandtype != WLC_BAND_2G)
-		    || (stf != PHY_TXC1_MODE_SISO)) {
-			WL_ERROR("wl%d: %s: Invalid CCK\n",
-				 WLCWLUNIT(wlc), __func__);
-			bcmerror = BCME_RANGE;
-			goto done;
-		}
-	} else {
-		WL_ERROR("wl%d: %s: Unknown rate type\n",
-			 WLCWLUNIT(wlc), __func__);
-		bcmerror = BCME_RANGE;
-		goto done;
-	}
-	/* make sure multiple antennae are available for non-siso rates */
-	if ((stf != PHY_TXC1_MODE_SISO) && (wlc->stf->txstreams == 1)) {
-		WL_ERROR("wl%d: %s: SISO antenna but !SISO request\n",
-			 WLCWLUNIT(wlc), __func__);
-		bcmerror = BCME_RANGE;
-		goto done;
-	}
-
-	rspec = rate;
-	if (ismcs) {
-		rspec |= RSPEC_MIMORATE;
-		/* For STBC populate the STC field of the ratespec */
-		if (stf == PHY_TXC1_MODE_STBC) {
-			u8 stc;
-			stc = 1;	/* Nss for single stream is always 1 */
-			rspec |= (stc << RSPEC_STC_SHIFT);
-		}
-	}
-
-	rspec |= (stf << RSPEC_STF_SHIFT);
-
-	if (override_mcs_only)
-		rspec |= RSPEC_OVERRIDE_MCS_ONLY;
-
-	if (issgi)
-		rspec |= RSPEC_SHORT_GI;
-
-	if ((rate != 0)
-	    && !wlc_valid_rate(wlc, rspec, cur_band->bandtype, true)) {
-		return rate;
-	}
-
-	return rspec;
- done:
-	WL_ERROR("Hoark\n");
-	return rate;
-}
-
-/* formula:  IDLE_BUSY_RATIO_X_16 = (100-duty_cycle)/duty_cycle*16 */
-static int
-wlc_duty_cycle_set(struct wlc_info *wlc, int duty_cycle, bool isOFDM,
-		   bool writeToShm)
-{
-	int idle_busy_ratio_x_16 = 0;
-	uint offset =
-	    isOFDM ? M_TX_IDLE_BUSY_RATIO_X_16_OFDM :
-	    M_TX_IDLE_BUSY_RATIO_X_16_CCK;
-	if (duty_cycle > 100 || duty_cycle < 0) {
-		WL_ERROR("wl%d:  duty cycle value off limit\n", wlc->pub->unit);
-		return BCME_RANGE;
-	}
-	if (duty_cycle)
-		idle_busy_ratio_x_16 = (100 - duty_cycle) * 16 / duty_cycle;
-	/* Only write to shared memory  when wl is up */
-	if (writeToShm)
-		wlc_write_shm(wlc, offset, (u16) idle_busy_ratio_x_16);
-
-	if (isOFDM)
-		wlc->tx_duty_cycle_ofdm = (u16) duty_cycle;
-	else
-		wlc->tx_duty_cycle_cck = (u16) duty_cycle;
-
-	return BCME_OK;
-}
-
-/* Read a single u16 from shared memory.
- * SHM 'offset' needs to be an even address
- */
-u16 wlc_read_shm(struct wlc_info *wlc, uint offset)
-{
-	return wlc_bmac_read_shm(wlc->hw, offset);
-}
-
-/* Write a single u16 to shared memory.
- * SHM 'offset' needs to be an even address
- */
-void wlc_write_shm(struct wlc_info *wlc, uint offset, u16 v)
-{
-	wlc_bmac_write_shm(wlc->hw, offset, v);
-}
-
-/* Set a range of shared memory to a value.
- * SHM 'offset' needs to be an even address and
- * Range length 'len' must be an even number of bytes
- */
-void wlc_set_shm(struct wlc_info *wlc, uint offset, u16 v, int len)
-{
-	/* offset and len need to be even */
-	ASSERT((offset & 1) == 0);
-	ASSERT((len & 1) == 0);
-
-	if (len <= 0)
-		return;
-
-	wlc_bmac_set_shm(wlc->hw, offset, v, len);
-}
-
-/* Copy a buffer to shared memory.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void wlc_copyto_shm(struct wlc_info *wlc, uint offset, const void *buf, int len)
-{
-	/* offset and len need to be even */
-	ASSERT((offset & 1) == 0);
-	ASSERT((len & 1) == 0);
-
-	if (len <= 0)
-		return;
-	wlc_bmac_copyto_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
-
-}
-
-/* Copy from shared memory to a buffer.
- * SHM 'offset' needs to be an even address and
- * Buffer length 'len' must be an even number of bytes
- */
-void wlc_copyfrom_shm(struct wlc_info *wlc, uint offset, void *buf, int len)
-{
-	/* offset and len need to be even */
-	ASSERT((offset & 1) == 0);
-	ASSERT((len & 1) == 0);
-
-	if (len <= 0)
-		return;
-
-	wlc_bmac_copyfrom_objmem(wlc->hw, offset, buf, len, OBJADDR_SHM_SEL);
-}
-
-/* wrapper BMAC functions to for HIGH driver access */
-void wlc_mctrl(struct wlc_info *wlc, u32 mask, u32 val)
-{
-	wlc_bmac_mctrl(wlc->hw, mask, val);
-}
-
-void wlc_corereset(struct wlc_info *wlc, u32 flags)
-{
-	wlc_bmac_corereset(wlc->hw, flags);
-}
-
-void wlc_mhf(struct wlc_info *wlc, u8 idx, u16 mask, u16 val, int bands)
-{
-	wlc_bmac_mhf(wlc->hw, idx, mask, val, bands);
-}
-
-u16 wlc_mhf_get(struct wlc_info *wlc, u8 idx, int bands)
-{
-	return wlc_bmac_mhf_get(wlc->hw, idx, bands);
-}
-
-int wlc_xmtfifo_sz_get(struct wlc_info *wlc, uint fifo, uint *blocks)
-{
-	return wlc_bmac_xmtfifo_sz_get(wlc->hw, fifo, blocks);
-}
-
-void wlc_write_template_ram(struct wlc_info *wlc, int offset, int len,
-			    void *buf)
-{
-	wlc_bmac_write_template_ram(wlc->hw, offset, len, buf);
-}
-
-void wlc_write_hw_bcntemplates(struct wlc_info *wlc, void *bcn, int len,
-			       bool both)
-{
-	wlc_bmac_write_hw_bcntemplates(wlc->hw, bcn, len, both);
-}
-
-void
-wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
-		  const struct ether_addr *addr)
-{
-	wlc_bmac_set_addrmatch(wlc->hw, match_reg_offset, addr);
-}
-
-void wlc_set_rcmta(struct wlc_info *wlc, int idx, const struct ether_addr *addr)
-{
-	wlc_bmac_set_rcmta(wlc->hw, idx, addr);
-}
-
-void wlc_read_tsf(struct wlc_info *wlc, u32 *tsf_l_ptr, u32 *tsf_h_ptr)
-{
-	wlc_bmac_read_tsf(wlc->hw, tsf_l_ptr, tsf_h_ptr);
-}
-
-void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin)
-{
-	wlc->band->CWmin = newmin;
-	wlc_bmac_set_cwmin(wlc->hw, newmin);
-}
-
-void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax)
-{
-	wlc->band->CWmax = newmax;
-	wlc_bmac_set_cwmax(wlc->hw, newmax);
-}
-
-void wlc_fifoerrors(struct wlc_info *wlc)
-{
-
-	wlc_bmac_fifoerrors(wlc->hw);
-}
-
-/* Search mem rw utilities */
-
-void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit)
-{
-	wlc_bmac_pllreq(wlc->hw, set, req_bit);
-}
-
-void wlc_reset_bmac_done(struct wlc_info *wlc)
-{
-}
-
-void wlc_ht_mimops_cap_update(struct wlc_info *wlc, u8 mimops_mode)
-{
-	wlc->ht_cap.cap &= ~HT_CAP_MIMO_PS_MASK;
-	wlc->ht_cap.cap |= (mimops_mode << HT_CAP_MIMO_PS_SHIFT);
-
-	if (AP_ENAB(wlc->pub) && wlc->clk) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-	}
-}
-
-/* check for the particular priority flow control bit being set */
-bool
-wlc_txflowcontrol_prio_isset(struct wlc_info *wlc, wlc_txq_info_t *q, int prio)
-{
-	uint prio_mask;
-
-	if (prio == ALLPRIO) {
-		prio_mask = TXQ_STOP_FOR_PRIOFC_MASK;
-	} else {
-		ASSERT(prio >= 0 && prio <= MAXPRIO);
-		prio_mask = NBITVAL(prio);
-	}
-
-	return (q->stopped & prio_mask) == prio_mask;
-}
-
-/* propogate the flow control to all interfaces using the given tx queue */
-void wlc_txflowcontrol(struct wlc_info *wlc, wlc_txq_info_t *qi,
-		       bool on, int prio)
-{
-	uint prio_bits;
-	uint cur_bits;
-
-	WL_ERROR("%s: flow control kicks in\n", __func__);
-
-	if (prio == ALLPRIO) {
-		prio_bits = TXQ_STOP_FOR_PRIOFC_MASK;
-	} else {
-		ASSERT(prio >= 0 && prio <= MAXPRIO);
-		prio_bits = NBITVAL(prio);
-	}
-
-	cur_bits = qi->stopped & prio_bits;
-
-	/* Check for the case of no change and return early
-	 * Otherwise update the bit and continue
-	 */
-	if (on) {
-		if (cur_bits == prio_bits) {
-			return;
-		}
-		mboolset(qi->stopped, prio_bits);
-	} else {
-		if (cur_bits == 0) {
-			return;
-		}
-		mboolclr(qi->stopped, prio_bits);
-	}
-
-	/* If there is a flow control override we will not change the external
-	 * flow control state.
-	 */
-	if (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK) {
-		return;
-	}
-
-	wlc_txflowcontrol_signal(wlc, qi, on, prio);
-}
-
-void
-wlc_txflowcontrol_override(struct wlc_info *wlc, wlc_txq_info_t *qi, bool on,
-			   uint override)
-{
-	uint prev_override;
-
-	ASSERT(override != 0);
-	ASSERT((override & TXQ_STOP_FOR_PRIOFC_MASK) == 0);
-
-	prev_override = (qi->stopped & ~TXQ_STOP_FOR_PRIOFC_MASK);
-
-	/* Update the flow control bits and do an early return if there is
-	 * no change in the external flow control state.
-	 */
-	if (on) {
-		mboolset(qi->stopped, override);
-		/* if there was a previous override bit on, then setting this
-		 * makes no difference.
-		 */
-		if (prev_override) {
-			return;
-		}
-
-		wlc_txflowcontrol_signal(wlc, qi, ON, ALLPRIO);
-	} else {
-		mboolclr(qi->stopped, override);
-		/* clearing an override bit will only make a difference for
-		 * flow control if it was the only bit set. For any other
-		 * override setting, just return
-		 */
-		if (prev_override != override) {
-			return;
-		}
-
-		if (qi->stopped == 0) {
-			wlc_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
-		} else {
-			int prio;
-
-			for (prio = MAXPRIO; prio >= 0; prio--) {
-				if (!mboolisset(qi->stopped, NBITVAL(prio)))
-					wlc_txflowcontrol_signal(wlc, qi, OFF,
-								 prio);
-			}
-		}
-	}
-}
-
-static void wlc_txflowcontrol_reset(struct wlc_info *wlc)
-{
-	wlc_txq_info_t *qi;
-
-	for (qi = wlc->tx_queues; qi != NULL; qi = qi->next) {
-		if (qi->stopped) {
-			wlc_txflowcontrol_signal(wlc, qi, OFF, ALLPRIO);
-			qi->stopped = 0;
-		}
-	}
-}
-
-static void
-wlc_txflowcontrol_signal(struct wlc_info *wlc, wlc_txq_info_t *qi, bool on,
-			 int prio)
-{
-	struct wlc_if *wlcif;
-
-	for (wlcif = wlc->wlcif_list; wlcif != NULL; wlcif = wlcif->next) {
-		if (wlcif->qi == qi && wlcif->flags & WLC_IF_LINKED)
-			wl_txflowcontrol(wlc->wl, wlcif->wlif, on, prio);
-	}
-}
-
-static wlc_txq_info_t *wlc_txq_alloc(struct wlc_info *wlc, struct osl_info *osh)
-{
-	wlc_txq_info_t *qi, *p;
-
-	qi = (wlc_txq_info_t *) wlc_calloc(osh, wlc->pub->unit,
-					   sizeof(wlc_txq_info_t));
-	if (qi == NULL) {
-		return NULL;
-	}
-
-	/* Have enough room for control packets along with HI watermark */
-	/* Also, add room to txq for total psq packets if all the SCBs leave PS mode */
-	/* The watermark for flowcontrol to OS packets will remain the same */
-	pktq_init(&qi->q, WLC_PREC_COUNT,
-		  (2 * wlc->pub->tunables->datahiwat) + PKTQ_LEN_DEFAULT +
-		  wlc->pub->psq_pkts_total);
-
-	/* add this queue to the the global list */
-	p = wlc->tx_queues;
-	if (p == NULL) {
-		wlc->tx_queues = qi;
-	} else {
-		while (p->next != NULL)
-			p = p->next;
-		p->next = qi;
-	}
-
-	return qi;
-}
-
-static void wlc_txq_free(struct wlc_info *wlc, struct osl_info *osh,
-			 wlc_txq_info_t *qi)
-{
-	wlc_txq_info_t *p;
-
-	if (qi == NULL)
-		return;
-
-	/* remove the queue from the linked list */
-	p = wlc->tx_queues;
-	if (p == qi)
-		wlc->tx_queues = p->next;
-	else {
-		while (p != NULL && p->next != qi)
-			p = p->next;
-		ASSERT(p->next == qi);
-		if (p != NULL)
-			p->next = p->next->next;
-	}
-
-	kfree(qi);
-}
-
-/*
- * Flag 'scan in progress' to withold dynamic phy calibration
- */
-void wlc_scan_start(struct wlc_info *wlc)
-{
-	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, true);
-}
-
-void wlc_scan_stop(struct wlc_info *wlc)
-{
-	wlc_phy_hold_upd(wlc->band->pi, PHY_HOLD_FOR_SCAN, false);
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_mac80211.h b/drivers/staging/brcm80211/sys/wlc_mac80211.h
deleted file mode 100644
index 5df996b..0000000
--- a/drivers/staging/brcm80211/sys/wlc_mac80211.h
+++ /dev/null
@@ -1,988 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_h_
-#define _wlc_h_
-
-#include <wlioctl.h>
-#include <wlc_phy_hal.h>
-#include <wlc_channel.h>
-#include <wlc_bsscfg.h>
-#include <wlc_scb.h>
-
-#define MA_WINDOW_SZ		8	/* moving average window size */
-#define	WL_HWRXOFF		38	/* chip rx buffer offset */
-#define	INVCHANNEL		255	/* invalid channel */
-#define	MAXCOREREV		28	/* max # supported core revisions (0 .. MAXCOREREV - 1) */
-#define WLC_MAXMODULES		22	/* max #  wlc_module_register() calls */
-
-/* network protection config */
-#define	WLC_PROT_G_SPEC		1	/* SPEC g protection */
-#define	WLC_PROT_G_OVR		2	/* SPEC g prot override */
-#define	WLC_PROT_G_USER		3	/* gmode specified by user */
-#define	WLC_PROT_OVERLAP	4	/* overlap */
-#define	WLC_PROT_N_USER		10	/* nmode specified by user */
-#define	WLC_PROT_N_CFG		11	/* n protection */
-#define	WLC_PROT_N_CFG_OVR	12	/* n protection override */
-#define	WLC_PROT_N_NONGF	13	/* non-GF protection */
-#define	WLC_PROT_N_NONGF_OVR	14	/* non-GF protection override */
-#define	WLC_PROT_N_PAM_OVR	15	/* n preamble override */
-#define	WLC_PROT_N_OBSS		16	/* non-HT OBSS present */
-
-#define WLC_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
-
-/* Maximum wait time for a MAC suspend */
-#define	WLC_MAX_MAC_SUSPEND	83000	/* uS: 83mS is max packet time (64KB ampdu @ 6Mbps) */
-
-/* Probe Response timeout - responses for probe requests older that this are tossed, zero to disable
- */
-#define WLC_PRB_RESP_TIMEOUT	0	/* Disable probe response timeout */
-
-/* transmit buffer max headroom for protocol headers */
-#define TXOFF (D11_TXH_LEN + D11_PHY_HDR_LEN)
-
-/* For managing scan result lists */
-typedef struct wlc_bss_list {
-	uint count;
-	bool beacon;		/* set for beacon, cleared for probe response */
-	wlc_bss_info_t *ptrs[MAXBSS];
-} wlc_bss_list_t;
-
-#define	SW_TIMER_MAC_STAT_UPD		30	/* periodic MAC stats update */
-
-/* Double check that unsupported cores are not enabled */
-#if CONF_MSK(D11CONF, 0x4f) || CONF_GE(D11CONF, MAXCOREREV)
-#error "Configuration for D11CONF includes unsupported versions."
-#endif				/* Bad versions */
-
-#define	VALID_COREREV(corerev)	CONF_HAS(D11CONF, corerev)
-
-/* values for shortslot_override */
-#define WLC_SHORTSLOT_AUTO	-1	/* Driver will manage Shortslot setting */
-#define WLC_SHORTSLOT_OFF	0	/* Turn off short slot */
-#define WLC_SHORTSLOT_ON	1	/* Turn on short slot */
-
-/* value for short/long and mixmode/greenfield preamble */
-
-#define WLC_LONG_PREAMBLE	(0)
-#define WLC_SHORT_PREAMBLE	(1 << 0)
-#define WLC_GF_PREAMBLE		(1 << 1)
-#define WLC_MM_PREAMBLE		(1 << 2)
-#define WLC_IS_MIMO_PREAMBLE(_pre) (((_pre) == WLC_GF_PREAMBLE) || ((_pre) == WLC_MM_PREAMBLE))
-
-/* values for barker_preamble */
-#define WLC_BARKER_SHORT_ALLOWED	0	/* Short pre-amble allowed */
-
-/* A fifo is full. Clear precedences related to that FIFO */
-#define WLC_TX_FIFO_CLEAR(wlc, fifo) ((wlc)->tx_prec_map &= ~(wlc)->fifo2prec_map[fifo])
-
-/* Fifo is NOT full. Enable precedences for that FIFO */
-#define WLC_TX_FIFO_ENAB(wlc, fifo)  ((wlc)->tx_prec_map |= (wlc)->fifo2prec_map[fifo])
-
-/* TxFrameID */
-/* seq and frag bits: SEQNUM_SHIFT, FRAGNUM_MASK (802.11.h) */
-/* rate epoch bits: TXFID_RATE_SHIFT, TXFID_RATE_MASK ((wlc_rate.c) */
-#define TXFID_QUEUE_MASK	0x0007	/* Bits 0-2 */
-#define TXFID_SEQ_MASK		0x7FE0	/* Bits 5-15 */
-#define TXFID_SEQ_SHIFT		5	/* Number of bit shifts */
-#define	TXFID_RATE_PROBE_MASK	0x8000	/* Bit 15 for rate probe */
-#define TXFID_RATE_MASK		0x0018	/* Mask for bits 3 and 4 */
-#define TXFID_RATE_SHIFT	3	/* Shift 3 bits for rate mask */
-
-/* promote boardrev */
-#define BOARDREV_PROMOTABLE	0xFF	/* from */
-#define BOARDREV_PROMOTED	1	/* to */
-
-/* if wpa is in use then portopen is true when the group key is plumbed otherwise it is always true
- */
-#define WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
-#define WLC_SW_KEYS(wlc, bsscfg) ((((wlc)->wsec_swkeys) || \
-	((bsscfg)->wsec & WSEC_SWFLAG)))
-
-#define WLC_PORTOPEN(cfg) \
-	(((cfg)->WPA_auth != WPA_AUTH_DISABLED && WSEC_ENABLED((cfg)->wsec)) ? \
-	(cfg)->wsec_portopen : true)
-
-#define PS_ALLOWED(wlc)	wlc_ps_allowed(wlc)
-#define STAY_AWAKE(wlc) wlc_stay_awake(wlc)
-
-#define DATA_BLOCK_TX_SUPR	(1 << 4)
-
-/* 802.1D Priority to TX FIFO number for wme */
-extern const u8 prio2fifo[];
-
-/* Ucode MCTL_WAKE override bits */
-#define WLC_WAKE_OVERRIDE_CLKCTL	0x01
-#define WLC_WAKE_OVERRIDE_PHYREG	0x02
-#define WLC_WAKE_OVERRIDE_MACSUSPEND	0x04
-#define WLC_WAKE_OVERRIDE_TXFIFO	0x08
-#define WLC_WAKE_OVERRIDE_FORCEFAST	0x10
-
-/* stuff pulled in from wlc.c */
-
-/* Interrupt bit error summary.  Don't include I_RU: we refill DMA at other
- * times; and if we run out, constant I_RU interrupts may cause lockup.  We
- * will still get error counts from rx0ovfl.
- */
-#define	I_ERRORS	(I_PC | I_PD | I_DE | I_RO | I_XU)
-/* default software intmasks */
-#define	DEF_RXINTMASK	(I_RI)	/* enable rx int on rxfifo only */
-#define	DEF_MACINTMASK	(MI_TXSTOP | MI_TBTT | MI_ATIMWINEND | MI_PMQ | \
-			 MI_PHYTXERR | MI_DMAINT | MI_TFS | MI_BG_NOISE | \
-			 MI_CCA | MI_TO | MI_GP0 | MI_RFDISABLE | MI_PWRUP)
-
-#define	RETRY_SHORT_DEF			7	/* Default Short retry Limit */
-#define	RETRY_SHORT_MAX			255	/* Maximum Short retry Limit */
-#define	RETRY_LONG_DEF			4	/* Default Long retry count */
-#define	RETRY_SHORT_FB			3	/* Short retry count for fallback rate */
-#define	RETRY_LONG_FB			2	/* Long retry count for fallback rate */
-
-#define	MAXTXPKTS		6	/* max # pkts pending */
-
-/* frameburst */
-#define	MAXTXFRAMEBURST		8	/* vanilla xpress mode: max frames/burst */
-#define	MAXFRAMEBURST_TXOP	10000	/* Frameburst TXOP in usec */
-
-/* Per-AC retry limit register definitions; uses bcmdefs.h bitfield macros */
-#define EDCF_SHORT_S            0
-#define EDCF_SFB_S              4
-#define EDCF_LONG_S             8
-#define EDCF_LFB_S              12
-#define EDCF_SHORT_M            BITFIELD_MASK(4)
-#define EDCF_SFB_M              BITFIELD_MASK(4)
-#define EDCF_LONG_M             BITFIELD_MASK(4)
-#define EDCF_LFB_M              BITFIELD_MASK(4)
-
-#define WLC_WME_RETRY_SHORT_GET(wlc, ac)    GFIELD(wlc->wme_retries[ac], EDCF_SHORT)
-#define WLC_WME_RETRY_SFB_GET(wlc, ac)      GFIELD(wlc->wme_retries[ac], EDCF_SFB)
-#define WLC_WME_RETRY_LONG_GET(wlc, ac)     GFIELD(wlc->wme_retries[ac], EDCF_LONG)
-#define WLC_WME_RETRY_LFB_GET(wlc, ac)      GFIELD(wlc->wme_retries[ac], EDCF_LFB)
-
-#define WLC_WME_RETRY_SHORT_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SHORT, val))
-#define WLC_WME_RETRY_SFB_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_SFB, val))
-#define WLC_WME_RETRY_LONG_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LONG, val))
-#define WLC_WME_RETRY_LFB_SET(wlc, ac, val) \
-	(wlc->wme_retries[ac] = SFIELD(wlc->wme_retries[ac], EDCF_LFB, val))
-
-/* PLL requests */
-#define WLC_PLLREQ_SHARED	0x1	/* pll is shared on old chips */
-#define WLC_PLLREQ_RADIO_MON	0x2	/* hold pll for radio monitor register checking */
-#define WLC_PLLREQ_FLIP		0x4	/* hold/release pll for some short operation */
-
-/* Do we support this rate? */
-#define VALID_RATE_DBG(wlc, rspec) wlc_valid_rate(wlc, rspec, WLC_BAND_AUTO, true)
-
-/*
- * Macros to check if AP or STA is active.
- * AP Active means more than just configured: driver and BSS are "up";
- * that is, we are beaconing/responding as an AP (aps_associated).
- * STA Active similarly means the driver is up and a configured STA BSS
- * is up: either associated (stas_associated) or trying.
- *
- * Macro definitions vary as per AP/STA ifdefs, allowing references to
- * ifdef'd structure fields and constant values (0) for optimization.
- * Make sure to enclose blocks of code such that any routines they
- * reference can also be unused and optimized out by the linker.
- */
-/* NOTE: References structure fields defined in wlc.h */
-#define AP_ACTIVE(wlc)	(0)
-
-/*
- * Detect Card removed.
- * Even checking an sbconfig register read will not false trigger when the core is in reset.
- * it breaks CF address mechanism. Accessing gphy phyversion will cause SB error if aphy
- * is in reset on 4306B0-DB. Need a simple accessible reg with fixed 0/1 pattern
- * (some platforms return all 0).
- * If clocks are present, call the sb routine which will figure out if the device is removed.
- */
-#define DEVICEREMOVED(wlc)      \
-	((wlc->hw->clk) ?   \
-	((R_REG(wlc->hw->osh, &wlc->hw->regs->maccontrol) & \
-	(MCTL_PSM_JMP_0 | MCTL_IHR_EN)) != MCTL_IHR_EN) : \
-	(si_deviceremoved(wlc->hw->sih)))
-
-#define WLCWLUNIT(wlc)		((wlc)->pub->unit)
-
-typedef struct wlc_protection {
-	bool _g;		/* use g spec protection, driver internal */
-	s8 g_override;	/* override for use of g spec protection */
-	u8 gmode_user;	/* user config gmode, operating band->gmode is different */
-	s8 overlap;		/* Overlap BSS/IBSS protection for both 11g and 11n */
-	s8 nmode_user;	/* user config nmode, operating pub->nmode is different */
-	s8 n_cfg;		/* use OFDM protection on MIMO frames */
-	s8 n_cfg_override;	/* override for use of N protection */
-	bool nongf;		/* non-GF present protection */
-	s8 nongf_override;	/* override for use of GF protection */
-	s8 n_pam_override;	/* override for preamble: MM or GF */
-	bool n_obss;		/* indicated OBSS Non-HT STA present */
-
-	uint longpre_detect_timeout;	/* #sec until long preamble bcns gone */
-	uint barker_detect_timeout;	/* #sec until bcns signaling Barker long preamble */
-	/* only is gone */
-	uint ofdm_ibss_timeout;	/* #sec until ofdm IBSS beacons gone */
-	uint ofdm_ovlp_timeout;	/* #sec until ofdm overlapping BSS bcns gone */
-	uint nonerp_ibss_timeout;	/* #sec until nonerp IBSS beacons gone */
-	uint nonerp_ovlp_timeout;	/* #sec until nonerp overlapping BSS bcns gone */
-	uint g_ibss_timeout;	/* #sec until bcns signaling Use_Protection gone */
-	uint n_ibss_timeout;	/* #sec until bcns signaling Use_OFDM_Protection gone */
-	uint ht20in40_ovlp_timeout;	/* #sec until 20MHz overlapping OPMODE gone */
-	uint ht20in40_ibss_timeout;	/* #sec until 20MHz-only HT station bcns gone */
-	uint non_gf_ibss_timeout;	/* #sec until non-GF bcns gone */
-} wlc_protection_t;
-
-/* anything affects the single/dual streams/antenna operation */
-typedef struct wlc_stf {
-	u8 hw_txchain;	/* HW txchain bitmap cfg */
-	u8 txchain;		/* txchain bitmap being used */
-	u8 txstreams;	/* number of txchains being used */
-
-	u8 hw_rxchain;	/* HW rxchain bitmap cfg */
-	u8 rxchain;		/* rxchain bitmap being used */
-	u8 rxstreams;	/* number of rxchains being used */
-
-	u8 ant_rx_ovr;	/* rx antenna override */
-	s8 txant;		/* userTx antenna setting */
-	u16 phytxant;	/* phyTx antenna setting in txheader */
-
-	u8 ss_opmode;	/* singlestream Operational mode, 0:siso; 1:cdd */
-	bool ss_algosel_auto;	/* if true, use wlc->stf->ss_algo_channel; */
-	/* else use wlc->band->stf->ss_mode_band; */
-	u16 ss_algo_channel;	/* ss based on per-channel algo: 0: SISO, 1: CDD 2: STBC */
-	u8 no_cddstbc;	/* stf override, 1: no CDD (or STBC) allowed */
-
-	u8 rxchain_restore_delay;	/* delay time to restore default rxchain */
-
-	s8 ldpc;		/* AUTO/ON/OFF ldpc cap supported */
-	u8 txcore[MAX_STREAMS_SUPPORTED + 1];	/* bitmap of selected core for each Nsts */
-	s8 spatial_policy;
-} wlc_stf_t;
-
-#define WLC_STF_SS_STBC_TX(wlc, scb) \
-	(((wlc)->stf->txstreams > 1) && (((wlc)->band->band_stf_stbc_tx == ON) || \
-	 (SCB_STBC_CAP((scb)) &&					\
-	  (wlc)->band->band_stf_stbc_tx == AUTO &&			\
-	  isset(&((wlc)->stf->ss_algo_channel), PHY_TXC1_MODE_STBC))))
-
-#define WLC_STBC_CAP_PHY(wlc) (WLCISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3))
-
-#define WLC_SGI_CAP_PHY(wlc) ((WLCISNPHY(wlc->band) && NREV_GE(wlc->band->phyrev, 3)) || \
-	WLCISLCNPHY(wlc->band))
-
-#define WLC_CHAN_PHYTYPE(x)     (((x) & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT)
-#define WLC_CHAN_CHANNEL(x)     (((x) & RXS_CHAN_ID_MASK) >> RXS_CHAN_ID_SHIFT)
-#define WLC_RX_CHANNEL(rxh)	(WLC_CHAN_CHANNEL((rxh)->RxChan))
-
-/* wlc_bss_info flag bit values */
-#define WLC_BSS_HT		0x0020	/* BSS is HT (MIMO) capable */
-
-/* Flags used in wlc_txq_info.stopped */
-#define TXQ_STOP_FOR_PRIOFC_MASK	0x000000FF	/* per prio flow control bits */
-#define TXQ_STOP_FOR_PKT_DRAIN		0x00000100	/* stop txq enqueue for packet drain */
-#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL	0x00000200	/* stop txq enqueue for ampdu flow control */
-
-#define WLC_HT_WEP_RESTRICT	0x01	/* restrict HT with WEP */
-#define WLC_HT_TKIP_RESTRICT	0x02	/* restrict HT with TKIP */
-
-/*
- * core state (mac)
- */
-struct wlccore {
-	uint coreidx;		/* # sb enumerated core */
-
-	/* fifo */
-	uint *txavail[NFIFO];	/* # tx descriptors available */
-	s16 txpktpend[NFIFO];	/* tx admission control */
-
-	macstat_t *macstat_snapshot;	/* mac hw prev read values */
-};
-
-/*
- * band state (phy+ana+radio)
- */
-struct wlcband {
-	int bandtype;		/* WLC_BAND_2G, WLC_BAND_5G */
-	uint bandunit;		/* bandstate[] index */
-
-	u16 phytype;		/* phytype */
-	u16 phyrev;
-	u16 radioid;
-	u16 radiorev;
-	wlc_phy_t *pi;		/* pointer to phy specific information */
-	bool abgphy_encore;
-
-	u8 gmode;		/* currently active gmode (see wlioctl.h) */
-
-	struct scb *hwrs_scb;	/* permanent scb for hw rateset */
-
-	wlc_rateset_t defrateset;	/* band-specific copy of default_bss.rateset */
-
-	ratespec_t rspec_override;	/* 802.11 rate override */
-	ratespec_t mrspec_override;	/* multicast rate override */
-	u8 band_stf_ss_mode;	/* Configured STF type, 0:siso; 1:cdd */
-	s8 band_stf_stbc_tx;	/* STBC TX 0:off; 1:force on; -1:auto */
-	wlc_rateset_t hw_rateset;	/* rates supported by chip (phy-specific) */
-	u8 basic_rate[WLC_MAXRATE + 1];	/* basic rates indexed by rate */
-	bool mimo_cap_40;	/* 40 MHz cap enabled on this band */
-	s8 antgain;		/* antenna gain from srom */
-
-	u16 CWmin;		/* The minimum size of contention window, in unit of aSlotTime */
-	u16 CWmax;		/* The maximum size of contention window, in unit of aSlotTime */
-	u16 bcntsfoff;	/* beacon tsf offset */
-};
-
-/* generic function callback takes just one arg */
-typedef void (*cb_fn_t) (void *);
-
-/* tx completion callback takes 3 args */
-typedef void (*pkcb_fn_t) (struct wlc_info *wlc, uint txstatus, void *arg);
-
-typedef struct pkt_cb {
-	pkcb_fn_t fn;		/* function to call when tx frame completes */
-	void *arg;		/* void arg for fn */
-	u8 nextidx;		/* index of next call back if threading */
-	bool entered;		/* recursion check */
-} pkt_cb_t;
-
-	/* module control blocks */
-typedef struct modulecb {
-	char name[32];		/* module name : NULL indicates empty array member */
-	const bcm_iovar_t *iovars;	/* iovar table */
-	void *hdl;		/* handle passed when handler 'doiovar' is called */
-	watchdog_fn_t watchdog_fn;	/* watchdog handler */
-	iovar_fn_t iovar_fn;	/* iovar handler */
-	down_fn_t down_fn;	/* down handler. Note: the int returned
-				 * by the down function is a count of the
-				 * number of timers that could not be
-				 * freed.
-				 */
-} modulecb_t;
-
-	/* dump control blocks */
-typedef struct dumpcb_s {
-	const char *name;	/* dump name */
-	dump_fn_t dump_fn;	/* 'wl dump' handler */
-	void *dump_fn_arg;
-	struct dumpcb_s *next;
-} dumpcb_t;
-
-/* virtual interface */
-struct wlc_if {
-	struct wlc_if *next;
-	u8 type;		/* WLC_IFTYPE_BSS or WLC_IFTYPE_WDS */
-	u8 index;		/* assigned in wl_add_if(), index of the wlif if any,
-				 * not necessarily corresponding to bsscfg._idx or
-				 * AID2PVBMAP(scb).
-				 */
-	u8 flags;		/* flags for the interface */
-	struct wl_if *wlif;		/* pointer to wlif */
-	struct wlc_txq_info *qi;	/* pointer to associated tx queue */
-	union {
-		struct scb *scb;	/* pointer to scb if WLC_IFTYPE_WDS */
-		struct wlc_bsscfg *bsscfg;	/* pointer to bsscfg if WLC_IFTYPE_BSS */
-	} u;
-};
-
-/* flags for the interface */
-#define WLC_IF_LINKED		0x02	/* this interface is linked to a wl_if */
-
-typedef struct wlc_hwband {
-	int bandtype;		/* WLC_BAND_2G, WLC_BAND_5G */
-	uint bandunit;		/* bandstate[] index */
-	u16 mhfs[MHFMAX];	/* MHF array shadow */
-	u8 bandhw_stf_ss_mode;	/* HW configured STF type, 0:siso; 1:cdd */
-	u16 CWmin;
-	u16 CWmax;
-	u32 core_flags;
-
-	u16 phytype;		/* phytype */
-	u16 phyrev;
-	u16 radioid;
-	u16 radiorev;
-	wlc_phy_t *pi;		/* pointer to phy specific information */
-	bool abgphy_encore;
-} wlc_hwband_t;
-
-struct wlc_hw_info {
-	struct osl_info *osh;		/* pointer to os handle */
-	bool _piomode;		/* true if pio mode */
-	struct wlc_info *wlc;
-
-	/* fifo */
-	struct hnddma_pub *di[NFIFO];	/* hnddma handles, per fifo */
-
-	uint unit;		/* device instance number */
-
-	/* version info */
-	u16 vendorid;	/* PCI vendor id */
-	u16 deviceid;	/* PCI device id */
-	uint corerev;		/* core revision */
-	u8 sromrev;		/* version # of the srom */
-	u16 boardrev;	/* version # of particular board */
-	u32 boardflags;	/* Board specific flags from srom */
-	u32 boardflags2;	/* More board flags if sromrev >= 4 */
-	u32 machwcap;	/* MAC capabilities (corerev >= 13) */
-	u32 machwcap_backup;	/* backup of machwcap (corerev >= 13) */
-	u16 ucode_dbgsel;	/* dbgsel for ucode debug(config gpio) */
-
-	si_t *sih;		/* SB handle (cookie for siutils calls) */
-	char *vars;		/* "environment" name=value */
-	uint vars_size;		/* size of vars, free vars on detach */
-	d11regs_t *regs;	/* pointer to device registers */
-	void *physhim;		/* phy shim layer handler */
-	void *phy_sh;		/* pointer to shared phy state */
-	wlc_hwband_t *band;	/* pointer to active per-band state */
-	wlc_hwband_t *bandstate[MAXBANDS];	/* per-band state (one per phy/radio) */
-	u16 bmac_phytxant;	/* cache of high phytxant state */
-	bool shortslot;		/* currently using 11g ShortSlot timing */
-	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
-	u16 LRL;		/* 802.11 dot11LongRetryLimit */
-	u16 SFBL;		/* Short Frame Rate Fallback Limit */
-	u16 LFBL;		/* Long Frame Rate Fallback Limit */
-
-	bool up;		/* d11 hardware up and running */
-	uint now;		/* # elapsed seconds */
-	uint _nbands;		/* # bands supported */
-	chanspec_t chanspec;	/* bmac chanspec shadow */
-
-	uint *txavail[NFIFO];	/* # tx descriptors available */
-	u16 *xmtfifo_sz;	/* fifo size in 256B for each xmt fifo */
-
-	mbool pllreq;		/* pll requests to keep PLL on */
-
-	u8 suspended_fifos;	/* Which TX fifo to remain awake for */
-	u32 maccontrol;	/* Cached value of maccontrol */
-	uint mac_suspend_depth;	/* current depth of mac_suspend levels */
-	u32 wake_override;	/* Various conditions to force MAC to WAKE mode */
-	u32 mute_override;	/* Prevent ucode from sending beacons */
-	struct ether_addr etheraddr;	/* currently configured ethernet address */
-	u32 led_gpio_mask;	/* LED GPIO Mask */
-	bool noreset;		/* true= do not reset hw, used by WLC_OUT */
-	bool forcefastclk;	/* true if the h/w is forcing the use of fast clk */
-	bool clk;		/* core is out of reset and has clock */
-	bool sbclk;		/* sb has clock */
-	struct bmac_pmq *bmac_pmq; /*  bmac PM states derived from ucode PMQ */
-	bool phyclk;		/* phy is out of reset and has clock */
-	bool dma_lpbk;		/* core is in DMA loopback */
-
-	bool ucode_loaded;	/* true after ucode downloaded */
-
-
-	u8 hw_stf_ss_opmode;	/* STF single stream operation mode */
-	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
-				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
-				 */
-	u32 antsel_avail;	/*
-				 * put struct antsel_info here if more info is
-				 * needed
-				 */
-};
-
-/* TX Queue information
- *
- * Each flow of traffic out of the device has a TX Queue with independent
- * flow control. Several interfaces may be associated with a single TX Queue
- * if they belong to the same flow of traffic from the device. For multi-channel
- * operation there are independent TX Queues for each channel.
- */
-typedef struct wlc_txq_info {
-	struct wlc_txq_info *next;
-	struct pktq q;
-	uint stopped;		/* tx flow control bits */
-} wlc_txq_info_t;
-
-/*
- * Principal common (os-independent) software data structure.
- */
-struct wlc_info {
-	struct wlc_pub *pub;		/* pointer to wlc public state */
-	struct osl_info *osh;		/* pointer to os handle */
-	struct wl_info *wl;	/* pointer to os-specific private state */
-	d11regs_t *regs;	/* pointer to device registers */
-
-	struct wlc_hw_info *hw;	/* HW related state used primarily by BMAC */
-
-	/* clock */
-	int clkreq_override;	/* setting for clkreq for PCIE : Auto, 0, 1 */
-	u16 fastpwrup_dly;	/* time in us needed to bring up d11 fast clock */
-
-	/* interrupt */
-	u32 macintstatus;	/* bit channel between isr and dpc */
-	u32 macintmask;	/* sw runtime master macintmask value */
-	u32 defmacintmask;	/* default "on" macintmask value */
-
-	/* up and down */
-	bool device_present;	/* (removable) device is present */
-
-	bool clk;		/* core is out of reset and has clock */
-
-	/* multiband */
-	struct wlccore *core;	/* pointer to active io core */
-	struct wlcband *band;	/* pointer to active per-band state */
-	struct wlccore *corestate;	/* per-core state (one per hw core) */
-	/* per-band state (one per phy/radio): */
-	struct wlcband *bandstate[MAXBANDS];
-
-	bool war16165;		/* PCI slow clock 16165 war flag */
-
-	bool tx_suspended;	/* data fifos need to remain suspended */
-
-	uint txpend16165war;
-
-	/* packet queue */
-	uint qvalid;		/* DirFrmQValid and BcMcFrmQValid */
-
-	/* Regulatory power limits */
-	s8 txpwr_local_max;	/* regulatory local txpwr max */
-	u8 txpwr_local_constraint;	/* local power contraint in dB */
-
-
-	struct ampdu_info *ampdu;	/* ampdu module handler */
-	struct antsel_info *asi;	/* antsel module handler */
-	wlc_cm_info_t *cmi;	/* channel manager module handler */
-
-	void *btparam;		/* bus type specific cookie */
-
-	uint vars_size;		/* size of vars, free vars on detach */
-
-	u16 vendorid;	/* PCI vendor id */
-	u16 deviceid;	/* PCI device id */
-	uint ucode_rev;		/* microcode revision */
-
-	u32 machwcap;	/* MAC capabilities, BMAC shadow */
-
-	struct ether_addr perm_etheraddr;	/* original sprom local ethernet address */
-
-	bool bandlocked;	/* disable auto multi-band switching */
-	bool bandinit_pending;	/* track band init in auto band */
-
-	bool radio_monitor;	/* radio timer is running */
-	bool down_override;	/* true=down */
-	bool going_down;	/* down path intermediate variable */
-
-	bool mpc;		/* enable minimum power consumption */
-	u8 mpc_dlycnt;	/* # of watchdog cnt before turn disable radio */
-	u8 mpc_offcnt;	/* # of watchdog cnt that radio is disabled */
-	u8 mpc_delay_off;	/* delay radio disable by # of watchdog cnt */
-	u8 prev_non_delay_mpc;	/* prev state wlc_is_non_delay_mpc */
-
-	/* timer */
-	struct wl_timer *wdtimer;	/* timer for watchdog routine */
-	uint fast_timer;	/* Periodic timeout for 'fast' timer */
-	uint slow_timer;	/* Periodic timeout for 'slow' timer */
-	uint glacial_timer;	/* Periodic timeout for 'glacial' timer */
-	uint phycal_mlo;	/* last time measurelow calibration was done */
-	uint phycal_txpower;	/* last time txpower calibration was done */
-
-	struct wl_timer *radio_timer;	/* timer for hw radio button monitor routine */
-	struct wl_timer *pspoll_timer;	/* periodic pspoll timer */
-
-	/* promiscuous */
-	bool monitor;		/* monitor (MPDU sniffing) mode */
-	bool bcnmisc_ibss;	/* bcns promisc mode override for IBSS */
-	bool bcnmisc_scan;	/* bcns promisc mode override for scan */
-	bool bcnmisc_monitor;	/* bcns promisc mode override for monitor */
-
-	u8 bcn_wait_prd;	/* max waiting period (for beacon) in 1024TU */
-
-	/* driver feature */
-	bool _rifs;		/* enable per-packet rifs */
-	s32 rifs_advert;	/* RIFS mode advertisement */
-	s8 sgi_tx;		/* sgi tx */
-	bool wet;		/* true if wireless ethernet bridging mode */
-
-	/* AP-STA synchronization, power save */
-	bool check_for_unaligned_tbtt;	/* check unaligned tbtt flag */
-	bool PM_override;	/* no power-save flag, override PM(user input) */
-	bool PMenabled;		/* current power-management state (CAM or PS) */
-	bool PMpending;		/* waiting for tx status with PM indicated set */
-	bool PMblocked;		/* block any PSPolling in PS mode, used to buffer
-				 * AP traffic, also used to indicate in progress
-				 * of scan, rm, etc. off home channel activity.
-				 */
-	bool PSpoll;		/* whether there is an outstanding PS-Poll frame */
-	u8 PM;		/* power-management mode (CAM, PS or FASTPS) */
-	bool PMawakebcn;	/* bcn recvd during current waking state */
-
-	bool WME_PM_blocked;	/* Can STA go to PM when in WME Auto mode */
-	bool wake;		/* host-specified PS-mode sleep state */
-	u8 pspoll_prd;	/* pspoll interval in milliseconds */
-	u8 bcn_li_bcn;	/* beacon listen interval in # beacons */
-	u8 bcn_li_dtim;	/* beacon listen interval in # dtims */
-
-	bool WDarmed;		/* watchdog timer is armed */
-	u32 WDlast;		/* last time wlc_watchdog() was called */
-
-	/* WME */
-	ac_bitmap_t wme_dp;	/* Discard (oldest first) policy per AC */
-	bool wme_apsd;		/* enable Advanced Power Save Delivery */
-	ac_bitmap_t wme_admctl;	/* bit i set if AC i under admission control */
-	u16 edcf_txop[AC_COUNT];	/* current txop for each ac */
-	wme_param_ie_t wme_param_ie;	/* WME parameter info element, which on STA
-					 * contains parameters in use locally, and on
-					 * AP contains parameters advertised to STA
-					 * in beacons and assoc responses.
-					 */
-	bool wme_prec_queuing;	/* enable/disable non-wme STA prec queuing */
-	u16 wme_retries[AC_COUNT];	/* per-AC retry limits */
-
-	int vlan_mode;		/* OK to use 802.1Q Tags (ON, OFF, AUTO) */
-	u16 tx_prec_map;	/* Precedence map based on HW FIFO space */
-	u16 fifo2prec_map[NFIFO];	/* pointer to fifo2_prec map based on WME */
-
-	/* BSS Configurations */
-	wlc_bsscfg_t *bsscfg[WLC_MAXBSSCFG];	/* set of BSS configurations, idx 0 is default and
-						 * always valid
-						 */
-	wlc_bsscfg_t *cfg;	/* the primary bsscfg (can be AP or STA) */
-	u8 stas_associated;	/* count of ASSOCIATED STA bsscfgs */
-	u8 aps_associated;	/* count of UP AP bsscfgs */
-	u8 block_datafifo;	/* prohibit posting frames to data fifos */
-	bool bcmcfifo_drain;	/* TX_BCMC_FIFO is set to drain */
-
-	/* tx queue */
-	wlc_txq_info_t *tx_queues;	/* common TX Queue list */
-
-	/* event */
-	wlc_eventq_t *eventq;	/* event queue for deferred processing */
-
-	/* security */
-	wsec_key_t *wsec_keys[WSEC_MAX_KEYS];	/* dynamic key storage */
-	wsec_key_t *wsec_def_keys[WLC_DEFAULT_KEYS];	/* default key storage */
-	bool wsec_swkeys;	/* indicates that all keys should be
-				 * treated as sw keys (used for debugging)
-				 */
-	modulecb_t *modulecb;
-	dumpcb_t *dumpcb_head;
-
-	u8 mimoft;		/* SIGN or 11N */
-	u8 mimo_band_bwcap;	/* bw cap per band type */
-	s8 txburst_limit_override;	/* tx burst limit override */
-	u16 txburst_limit;	/* tx burst limit value */
-	s8 cck_40txbw;	/* 11N, cck tx b/w override when in 40MHZ mode */
-	s8 ofdm_40txbw;	/* 11N, ofdm tx b/w override when in 40MHZ mode */
-	s8 mimo_40txbw;	/* 11N, mimo tx b/w override when in 40MHZ mode */
-	ht_cap_ie_t ht_cap;	/* HT CAP IE being advertised by this node */
-
-	uint seckeys;		/* 54 key table shm address */
-	uint tkmickeys;		/* 12 TKIP MIC key table shm address */
-
-	wlc_bss_info_t *default_bss;	/* configured BSS parameters */
-
-	u16 AID;		/* association ID */
-	u16 counter;		/* per-sdu monotonically increasing counter */
-	u16 mc_fid_counter;	/* BC/MC FIFO frame ID counter */
-
-	bool ibss_allowed;	/* false, all IBSS will be ignored during a scan
-				 * and the driver will not allow the creation of
-				 * an IBSS network
-				 */
-	bool ibss_coalesce_allowed;
-
-	char country_default[WLC_CNTRY_BUF_SZ];	/* saved country for leaving 802.11d
-						 * auto-country mode
-						 */
-	char autocountry_default[WLC_CNTRY_BUF_SZ];	/* initial country for 802.11d
-							 * auto-country mode
-							 */
-#ifdef BCMDBG
-	bcm_tlv_t *country_ie_override;	/* debug override of announced Country IE */
-#endif
-
-	u16 prb_resp_timeout;	/* do not send prb resp if request older than this,
-					 * 0 = disable
-					 */
-
-	wlc_rateset_t sup_rates_override;	/* use only these rates in 11g supported rates if
-						 * specifed
-						 */
-
-	chanspec_t home_chanspec;	/* shared home chanspec */
-
-	/* PHY parameters */
-	chanspec_t chanspec;	/* target operational channel */
-	u16 usr_fragthresh;	/* user configured fragmentation threshold */
-	u16 fragthresh[NFIFO];	/* per-fifo fragmentation thresholds */
-	u16 RTSThresh;	/* 802.11 dot11RTSThreshold */
-	u16 SRL;		/* 802.11 dot11ShortRetryLimit */
-	u16 LRL;		/* 802.11 dot11LongRetryLimit */
-	u16 SFBL;		/* Short Frame Rate Fallback Limit */
-	u16 LFBL;		/* Long Frame Rate Fallback Limit */
-
-	/* network config */
-	bool shortpreamble;	/* currently operating with CCK ShortPreambles */
-	bool shortslot;		/* currently using 11g ShortSlot timing */
-	s8 barker_preamble;	/* current Barker Preamble Mode */
-	s8 shortslot_override;	/* 11g ShortSlot override */
-	bool include_legacy_erp;	/* include Legacy ERP info elt ID 47 as well as g ID 42 */
-	bool barker_overlap_control;	/* true: be aware of overlapping BSSs for barker */
-	bool ignore_bcns;	/* override: ignore non shortslot bcns in a 11g network */
-	bool legacy_probe;	/* restricts probe requests to CCK rates */
-
-	wlc_protection_t *protection;
-	s8 PLCPHdr_override;	/* 802.11b Preamble Type override */
-
-	wlc_stf_t *stf;
-
-	pkt_cb_t *pkt_callback;	/* tx completion callback handlers */
-
-	u32 txretried;	/* tx retried number in one msdu */
-
-	ratespec_t bcn_rspec;	/* save bcn ratespec purpose */
-
-	bool apsd_sta_usp;	/* Unscheduled Service Period in progress on STA */
-	struct wl_timer *apsd_trigger_timer;	/* timer for wme apsd trigger frames */
-	u32 apsd_trigger_timeout;	/* timeout value for apsd_trigger_timer (in ms)
-					 * 0 == disable
-					 */
-	ac_bitmap_t apsd_trigger_ac;	/* Permissible Acess Category in which APSD Null
-					 * Trigger frames can be send
-					 */
-	u8 htphy_membership;	/* HT PHY membership */
-
-	bool _regulatory_domain;	/* 802.11d enabled? */
-
-	u8 mimops_PM;
-
-	u8 txpwr_percent;	/* power output percentage */
-
-	u8 ht_wsec_restriction;	/* the restriction of HT with TKIP or WEP */
-
-	uint tempsense_lasttime;
-
-	u16 tx_duty_cycle_ofdm;	/* maximum allowed duty cycle for OFDM */
-	u16 tx_duty_cycle_cck;	/* maximum allowed duty cycle for CCK */
-
-	u16 next_bsscfg_ID;
-
-	struct wlc_if *wlcif_list;	/* linked list of wlc_if structs */
-	wlc_txq_info_t *active_queue;	/* txq for the currently active transmit context */
-	u32 mpc_dur;		/* total time (ms) in mpc mode except for the
-				 * portion since radio is turned off last time
-				 */
-	u32 mpc_laston_ts;	/* timestamp (ms) when radio is turned off last
-				 * time
-				 */
-	bool pr80838_war;
-	uint hwrxoff;
-};
-
-/* antsel module specific state */
-struct antsel_info {
-	struct wlc_info *wlc;	/* pointer to main wlc structure */
-	struct wlc_pub *pub;		/* pointer to public fn */
-	u8 antsel_type;	/* Type of boardlevel mimo antenna switch-logic
-				 * 0 = N/A, 1 = 2x4 board, 2 = 2x3 CB2 board
-				 */
-	u8 antsel_antswitch;	/* board level antenna switch type */
-	bool antsel_avail;	/* Ant selection availability (SROM based) */
-	wlc_antselcfg_t antcfg_11n;	/* antenna configuration */
-	wlc_antselcfg_t antcfg_cur;	/* current antenna config (auto) */
-};
-
-#define	CHANNEL_BANDUNIT(wlc, ch) (((ch) <= CH_MAX_2G_CHANNEL) ? BAND_2G_INDEX : BAND_5G_INDEX)
-#define	OTHERBANDUNIT(wlc)	((uint)((wlc)->band->bandunit ? BAND_2G_INDEX : BAND_5G_INDEX))
-
-#define IS_MBAND_UNLOCKED(wlc) \
-	((NBANDS(wlc) > 1) && !(wlc)->bandlocked)
-
-#define WLC_BAND_PI_RADIO_CHANSPEC wlc_phy_chanspec_get(wlc->band->pi)
-
-/* sum the individual fifo tx pending packet counts */
-#define	TXPKTPENDTOT(wlc) ((wlc)->core->txpktpend[0] + (wlc)->core->txpktpend[1] + \
-	(wlc)->core->txpktpend[2] + (wlc)->core->txpktpend[3])
-#define TXPKTPENDGET(wlc, fifo)		((wlc)->core->txpktpend[(fifo)])
-#define TXPKTPENDINC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] += (val))
-#define TXPKTPENDDEC(wlc, fifo, val)	((wlc)->core->txpktpend[(fifo)] -= (val))
-#define TXPKTPENDCLR(wlc, fifo)		((wlc)->core->txpktpend[(fifo)] = 0)
-#define TXAVAIL(wlc, fifo)		(*(wlc)->core->txavail[(fifo)])
-#define GETNEXTTXP(wlc, _queue)								\
-		dma_getnexttxp((wlc)->hw->di[(_queue)], HNDDMA_RANGE_TRANSMITTED)
-
-#define WLC_IS_MATCH_SSID(wlc, ssid1, ssid2, len1, len2) \
-	((len1 == len2) && !memcmp(ssid1, ssid2, len1))
-
-extern void wlc_high_dpc(struct wlc_info *wlc, u32 macintstatus);
-extern void wlc_fatal_error(struct wlc_info *wlc);
-extern void wlc_bmac_rpc_watchdog(struct wlc_info *wlc);
-extern void wlc_recv(struct wlc_info *wlc, struct sk_buff *p);
-extern bool wlc_dotxstatus(struct wlc_info *wlc, tx_status_t *txs, u32 frm_tx2);
-extern void wlc_txfifo(struct wlc_info *wlc, uint fifo, struct sk_buff *p,
-		       bool commit, s8 txpktpend);
-extern void wlc_txfifo_complete(struct wlc_info *wlc, uint fifo, s8 txpktpend);
-extern void wlc_txq_enq(void *ctx, struct scb *scb, struct sk_buff *sdu,
-			uint prec);
-extern void wlc_info_init(struct wlc_info *wlc, int unit);
-extern void wlc_print_txstatus(tx_status_t *txs);
-extern int wlc_xmtfifo_sz_get(struct wlc_info *wlc, uint fifo, uint *blocks);
-extern void wlc_write_template_ram(struct wlc_info *wlc, int offset, int len,
-				   void *buf);
-extern void wlc_write_hw_bcntemplates(struct wlc_info *wlc, void *bcn, int len,
-				      bool both);
-#if defined(BCMDBG)
-extern void wlc_get_rcmta(struct wlc_info *wlc, int idx,
-			  struct ether_addr *addr);
-#endif
-extern void wlc_set_rcmta(struct wlc_info *wlc, int idx,
-			  const struct ether_addr *addr);
-extern void wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
-			      const struct ether_addr *addr);
-extern void wlc_read_tsf(struct wlc_info *wlc, u32 *tsf_l_ptr,
-			 u32 *tsf_h_ptr);
-extern void wlc_set_cwmin(struct wlc_info *wlc, u16 newmin);
-extern void wlc_set_cwmax(struct wlc_info *wlc, u16 newmax);
-extern void wlc_fifoerrors(struct wlc_info *wlc);
-extern void wlc_pllreq(struct wlc_info *wlc, bool set, mbool req_bit);
-extern void wlc_reset_bmac_done(struct wlc_info *wlc);
-extern void wlc_protection_upd(struct wlc_info *wlc, uint idx, int val);
-extern void wlc_hwtimer_gptimer_set(struct wlc_info *wlc, uint us);
-extern void wlc_hwtimer_gptimer_abort(struct wlc_info *wlc);
-
-#if defined(BCMDBG)
-extern void wlc_print_rxh(d11rxhdr_t *rxh);
-extern void wlc_print_hdrs(struct wlc_info *wlc, const char *prefix, u8 *frame,
-			   d11txh_t *txh, d11rxhdr_t *rxh, uint len);
-extern void wlc_print_txdesc(d11txh_t *txh);
-#endif
-#if defined(BCMDBG)
-extern void wlc_print_dot11_mac_hdr(u8 *buf, int len);
-#endif
-
-extern void wlc_setxband(struct wlc_hw_info *wlc_hw, uint bandunit);
-extern void wlc_coredisable(struct wlc_hw_info *wlc_hw);
-
-extern bool wlc_valid_rate(struct wlc_info *wlc, ratespec_t rate, int band,
-			   bool verbose);
-extern void wlc_ap_upd(struct wlc_info *wlc);
-
-/* helper functions */
-extern void wlc_shm_ssid_upd(struct wlc_info *wlc, wlc_bsscfg_t *cfg);
-extern int wlc_set_gmode(struct wlc_info *wlc, u8 gmode, bool config);
-
-extern void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc);
-extern void wlc_mac_bcn_promisc(struct wlc_info *wlc);
-extern void wlc_mac_promisc(struct wlc_info *wlc);
-extern void wlc_txflowcontrol(struct wlc_info *wlc, wlc_txq_info_t *qi, bool on,
-			      int prio);
-extern void wlc_txflowcontrol_override(struct wlc_info *wlc, wlc_txq_info_t *qi,
-				       bool on, uint override);
-extern bool wlc_txflowcontrol_prio_isset(struct wlc_info *wlc,
-					 wlc_txq_info_t *qi, int prio);
-extern void wlc_send_q(struct wlc_info *wlc, wlc_txq_info_t *qi);
-extern int wlc_prep_pdu(struct wlc_info *wlc, struct sk_buff *pdu, uint *fifo);
-
-extern u16 wlc_calc_lsig_len(struct wlc_info *wlc, ratespec_t ratespec,
-				uint mac_len);
-extern ratespec_t wlc_rspec_to_rts_rspec(struct wlc_info *wlc, ratespec_t rspec,
-					 bool use_rspec, u16 mimo_ctlchbw);
-extern u16 wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only,
-				     ratespec_t rts_rate, ratespec_t frame_rate,
-				     u8 rts_preamble_type,
-				     u8 frame_preamble_type, uint frame_len,
-				     bool ba);
-
-extern void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs);
-
-#if defined(BCMDBG)
-extern void wlc_dump_ie(struct wlc_info *wlc, bcm_tlv_t *ie,
-			struct bcmstrbuf *b);
-#endif
-
-extern bool wlc_ps_check(struct wlc_info *wlc);
-extern void wlc_reprate_init(struct wlc_info *wlc);
-extern void wlc_bsscfg_reprate_init(wlc_bsscfg_t *bsscfg);
-extern void wlc_uint64_sub(u32 *a_high, u32 *a_low, u32 b_high,
-			   u32 b_low);
-extern u32 wlc_calc_tbtt_offset(u32 bi, u32 tsf_h, u32 tsf_l);
-
-/* Shared memory access */
-extern void wlc_write_shm(struct wlc_info *wlc, uint offset, u16 v);
-extern u16 wlc_read_shm(struct wlc_info *wlc, uint offset);
-extern void wlc_set_shm(struct wlc_info *wlc, uint offset, u16 v, int len);
-extern void wlc_copyto_shm(struct wlc_info *wlc, uint offset, const void *buf,
-			   int len);
-extern void wlc_copyfrom_shm(struct wlc_info *wlc, uint offset, void *buf,
-			     int len);
-
-extern void wlc_update_beacon(struct wlc_info *wlc);
-extern void wlc_bss_update_beacon(struct wlc_info *wlc,
-				  struct wlc_bsscfg *bsscfg);
-
-extern void wlc_update_probe_resp(struct wlc_info *wlc, bool suspend);
-extern void wlc_bss_update_probe_resp(struct wlc_info *wlc, wlc_bsscfg_t *cfg,
-				      bool suspend);
-
-extern bool wlc_ismpc(struct wlc_info *wlc);
-extern bool wlc_is_non_delay_mpc(struct wlc_info *wlc);
-extern void wlc_radio_mpc_upd(struct wlc_info *wlc);
-extern bool wlc_prec_enq(struct wlc_info *wlc, struct pktq *q, void *pkt,
-			 int prec);
-extern bool wlc_prec_enq_head(struct wlc_info *wlc, struct pktq *q,
-			      struct sk_buff *pkt, int prec, bool head);
-extern u16 wlc_phytxctl1_calc(struct wlc_info *wlc, ratespec_t rspec);
-extern void wlc_compute_plcp(struct wlc_info *wlc, ratespec_t rate, uint length,
-			     u8 *plcp);
-extern uint wlc_calc_frame_time(struct wlc_info *wlc, ratespec_t ratespec,
-				u8 preamble_type, uint mac_len);
-
-extern void wlc_set_chanspec(struct wlc_info *wlc, chanspec_t chanspec);
-
-extern bool wlc_timers_init(struct wlc_info *wlc, int unit);
-
-extern const bcm_iovar_t wlc_iovars[];
-
-extern int wlc_doiovar(void *hdl, const bcm_iovar_t *vi, u32 actionid,
-		       const char *name, void *params, uint p_len, void *arg,
-		       int len, int val_size, struct wlc_if *wlcif);
-
-#if defined(BCMDBG)
-extern void wlc_print_ies(struct wlc_info *wlc, u8 *ies, uint ies_len);
-#endif
-
-extern int wlc_set_nmode(struct wlc_info *wlc, s32 nmode);
-extern void wlc_ht_mimops_cap_update(struct wlc_info *wlc, u8 mimops_mode);
-extern void wlc_mimops_action_ht_send(struct wlc_info *wlc,
-				      wlc_bsscfg_t *bsscfg, u8 mimops_mode);
-
-extern void wlc_switch_shortslot(struct wlc_info *wlc, bool shortslot);
-extern void wlc_set_bssid(wlc_bsscfg_t *cfg);
-extern void wlc_edcf_setparams(wlc_bsscfg_t *cfg, bool suspend);
-
-extern void wlc_set_ratetable(struct wlc_info *wlc);
-extern int wlc_set_mac(wlc_bsscfg_t *cfg);
-extern void wlc_beacon_phytxctl_txant_upd(struct wlc_info *wlc,
-					  ratespec_t bcn_rate);
-extern void wlc_mod_prb_rsp_rate_table(struct wlc_info *wlc, uint frame_len);
-extern ratespec_t wlc_lowest_basic_rspec(struct wlc_info *wlc,
-					 wlc_rateset_t *rs);
-extern u16 wlc_compute_bcntsfoff(struct wlc_info *wlc, ratespec_t rspec,
-				    bool short_preamble, bool phydelay);
-extern void wlc_radio_disable(struct wlc_info *wlc);
-extern void wlc_bcn_li_upd(struct wlc_info *wlc);
-
-extern int wlc_get_revision_info(struct wlc_info *wlc, void *buf, uint len);
-extern void wlc_out(struct wlc_info *wlc);
-extern void wlc_set_home_chanspec(struct wlc_info *wlc, chanspec_t chanspec);
-extern void wlc_watchdog_upd(struct wlc_info *wlc, bool tbtt);
-extern bool wlc_ps_allowed(struct wlc_info *wlc);
-extern bool wlc_stay_awake(struct wlc_info *wlc);
-extern void wlc_wme_initparams_sta(struct wlc_info *wlc, wme_param_ie_t *pe);
-
-extern void wlc_bss_list_free(struct wlc_info *wlc, wlc_bss_list_t *bss_list);
-extern void wlc_ht_mimops_cap_update(struct wlc_info *wlc, u8 mimops_mode);
-#endif				/* _wlc_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_phy_shim.c b/drivers/staging/brcm80211/sys/wlc_phy_shim.c
deleted file mode 100644
index 8bd4ede..0000000
--- a/drivers/staging/brcm80211/sys/wlc_phy_shim.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-/*
- * This is "two-way" interface, acting as the SHIM layer between WL and PHY layer.
- *   WL driver can optinally call this translation layer to do some preprocessing, then reach PHY.
- *   On the PHY->WL driver direction, all calls go through this layer since PHY doesn't have the
- *   access to wlc_hw pointer.
- */
-
-#include <linux/kernel.h>
-#include <bcmdefs.h>
-#include <wlc_cfg.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <osl.h>
-#include <bcmutils.h>
-
-#include <proto/802.11.h>
-#include <bcmwifi.h>
-#include <siutils.h>
-#include <bcmendian.h>
-#include <wlioctl.h>
-#include <sbconfig.h>
-#include <sbchipc.h>
-#include <pcicfg.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <hnddma.h>
-#include <hndpmu.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_pub.h>
-#include <wlc_channel.h>
-#include <bcmsrom.h>
-#include <wlc_key.h>
-#include <wlc_event.h>
-
-#include <wlc_mac80211.h>
-
-#include <wlc_bmac.h>
-#include <wlc_phy_shim.h>
-#include <wlc_phy_hal.h>
-#include <wl_export.h>
-#include <wl_dbg.h>
-
-/* PHY SHIM module specific state */
-struct wlc_phy_shim_info {
-	struct wlc_hw_info *wlc_hw;	/* pointer to main wlc_hw structure */
-	void *wlc;		/* pointer to main wlc structure */
-	void *wl;		/* pointer to os-specific private state */
-};
-
-wlc_phy_shim_info_t *wlc_phy_shim_attach(struct wlc_hw_info *wlc_hw,
-						       void *wl, void *wlc) {
-	wlc_phy_shim_info_t *physhim = NULL;
-
-	physhim = kzalloc(sizeof(wlc_phy_shim_info_t), GFP_ATOMIC);
-	if (!physhim) {
-		WL_ERROR("wl%d: wlc_phy_shim_attach: out of mem\n",
-			 wlc_hw->unit);
-		return NULL;
-	}
-	physhim->wlc_hw = wlc_hw;
-	physhim->wlc = wlc;
-	physhim->wl = wl;
-
-	return physhim;
-}
-
-void wlc_phy_shim_detach(wlc_phy_shim_info_t *physhim)
-{
-	if (!physhim)
-		return;
-
-	kfree(physhim);
-}
-
-struct wlapi_timer *wlapi_init_timer(wlc_phy_shim_info_t *physhim,
-				     void (*fn) (void *arg), void *arg,
-				     const char *name)
-{
-	return (struct wlapi_timer *)wl_init_timer(physhim->wl, fn, arg, name);
-}
-
-void wlapi_free_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t)
-{
-	wl_free_timer(physhim->wl, (struct wl_timer *)t);
-}
-
-void
-wlapi_add_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t, uint ms,
-		int periodic)
-{
-	wl_add_timer(physhim->wl, (struct wl_timer *)t, ms, periodic);
-}
-
-bool wlapi_del_timer(wlc_phy_shim_info_t *physhim, struct wlapi_timer *t)
-{
-	return wl_del_timer(physhim->wl, (struct wl_timer *)t);
-}
-
-void wlapi_intrson(wlc_phy_shim_info_t *physhim)
-{
-	wl_intrson(physhim->wl);
-}
-
-u32 wlapi_intrsoff(wlc_phy_shim_info_t *physhim)
-{
-	return wl_intrsoff(physhim->wl);
-}
-
-void wlapi_intrsrestore(wlc_phy_shim_info_t *physhim, u32 macintmask)
-{
-	wl_intrsrestore(physhim->wl, macintmask);
-}
-
-void wlapi_bmac_write_shm(wlc_phy_shim_info_t *physhim, uint offset, u16 v)
-{
-	wlc_bmac_write_shm(physhim->wlc_hw, offset, v);
-}
-
-u16 wlapi_bmac_read_shm(wlc_phy_shim_info_t *physhim, uint offset)
-{
-	return wlc_bmac_read_shm(physhim->wlc_hw, offset);
-}
-
-void
-wlapi_bmac_mhf(wlc_phy_shim_info_t *physhim, u8 idx, u16 mask,
-	       u16 val, int bands)
-{
-	wlc_bmac_mhf(physhim->wlc_hw, idx, mask, val, bands);
-}
-
-void wlapi_bmac_corereset(wlc_phy_shim_info_t *physhim, u32 flags)
-{
-	wlc_bmac_corereset(physhim->wlc_hw, flags);
-}
-
-void wlapi_suspend_mac_and_wait(wlc_phy_shim_info_t *physhim)
-{
-	wlc_suspend_mac_and_wait(physhim->wlc);
-}
-
-void wlapi_switch_macfreq(wlc_phy_shim_info_t *physhim, u8 spurmode)
-{
-	wlc_bmac_switch_macfreq(physhim->wlc_hw, spurmode);
-}
-
-void wlapi_enable_mac(wlc_phy_shim_info_t *physhim)
-{
-	wlc_enable_mac(physhim->wlc);
-}
-
-void wlapi_bmac_mctrl(wlc_phy_shim_info_t *physhim, u32 mask, u32 val)
-{
-	wlc_bmac_mctrl(physhim->wlc_hw, mask, val);
-}
-
-void wlapi_bmac_phy_reset(wlc_phy_shim_info_t *physhim)
-{
-	wlc_bmac_phy_reset(physhim->wlc_hw);
-}
-
-void wlapi_bmac_bw_set(wlc_phy_shim_info_t *physhim, u16 bw)
-{
-	wlc_bmac_bw_set(physhim->wlc_hw, bw);
-}
-
-u16 wlapi_bmac_get_txant(wlc_phy_shim_info_t *physhim)
-{
-	return wlc_bmac_get_txant(physhim->wlc_hw);
-}
-
-void wlapi_bmac_phyclk_fgc(wlc_phy_shim_info_t *physhim, bool clk)
-{
-	wlc_bmac_phyclk_fgc(physhim->wlc_hw, clk);
-}
-
-void wlapi_bmac_macphyclk_set(wlc_phy_shim_info_t *physhim, bool clk)
-{
-	wlc_bmac_macphyclk_set(physhim->wlc_hw, clk);
-}
-
-void wlapi_bmac_core_phypll_ctl(wlc_phy_shim_info_t *physhim, bool on)
-{
-	wlc_bmac_core_phypll_ctl(physhim->wlc_hw, on);
-}
-
-void wlapi_bmac_core_phypll_reset(wlc_phy_shim_info_t *physhim)
-{
-	wlc_bmac_core_phypll_reset(physhim->wlc_hw);
-}
-
-void wlapi_bmac_ucode_wake_override_phyreg_set(wlc_phy_shim_info_t *physhim)
-{
-	wlc_ucode_wake_override_set(physhim->wlc_hw, WLC_WAKE_OVERRIDE_PHYREG);
-}
-
-void wlapi_bmac_ucode_wake_override_phyreg_clear(wlc_phy_shim_info_t *physhim)
-{
-	wlc_ucode_wake_override_clear(physhim->wlc_hw,
-				      WLC_WAKE_OVERRIDE_PHYREG);
-}
-
-void
-wlapi_bmac_write_template_ram(wlc_phy_shim_info_t *physhim, int offset,
-			      int len, void *buf)
-{
-	wlc_bmac_write_template_ram(physhim->wlc_hw, offset, len, buf);
-}
-
-u16 wlapi_bmac_rate_shm_offset(wlc_phy_shim_info_t *physhim, u8 rate)
-{
-	return wlc_bmac_rate_shm_offset(physhim->wlc_hw, rate);
-}
-
-void wlapi_ucode_sample_init(wlc_phy_shim_info_t *physhim)
-{
-}
-
-void
-wlapi_copyfrom_objmem(wlc_phy_shim_info_t *physhim, uint offset, void *buf,
-		      int len, u32 sel)
-{
-	wlc_bmac_copyfrom_objmem(physhim->wlc_hw, offset, buf, len, sel);
-}
-
-void
-wlapi_copyto_objmem(wlc_phy_shim_info_t *physhim, uint offset, const void *buf,
-		    int l, u32 sel)
-{
-	wlc_bmac_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel);
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_phy_shim.h b/drivers/staging/brcm80211/sys/wlc_phy_shim.h
deleted file mode 100644
index c151a5d..0000000
--- a/drivers/staging/brcm80211/sys/wlc_phy_shim.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_phy_shim_h_
-#define _wlc_phy_shim_h_
-
-#define RADAR_TYPE_NONE		0	/* Radar type None */
-#define RADAR_TYPE_ETSI_1	1	/* ETSI 1 Radar type */
-#define RADAR_TYPE_ETSI_2	2	/* ETSI 2 Radar type */
-#define RADAR_TYPE_ETSI_3	3	/* ETSI 3 Radar type */
-#define RADAR_TYPE_ITU_E	4	/* ITU E Radar type */
-#define RADAR_TYPE_ITU_K	5	/* ITU K Radar type */
-#define RADAR_TYPE_UNCLASSIFIED	6	/* Unclassified Radar type  */
-#define RADAR_TYPE_BIN5		7	/* long pulse radar type */
-#define RADAR_TYPE_STG2 	8	/* staggered-2 radar */
-#define RADAR_TYPE_STG3 	9	/* staggered-3 radar */
-#define RADAR_TYPE_FRA		10	/* French radar */
-
-/* French radar pulse widths */
-#define FRA_T1_20MHZ	52770
-#define FRA_T2_20MHZ	61538
-#define FRA_T3_20MHZ	66002
-#define FRA_T1_40MHZ	105541
-#define FRA_T2_40MHZ	123077
-#define FRA_T3_40MHZ	132004
-#define FRA_ERR_20MHZ	60
-#define FRA_ERR_40MHZ	120
-
-#define ANTSEL_NA		0	/* No boardlevel selection available */
-#define ANTSEL_2x4		1	/* 2x4 boardlevel selection available */
-#define ANTSEL_2x3		2	/* 2x3 CB2 boardlevel selection available */
-
-/* Rx Antenna diversity control values */
-#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
-#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
-#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
-#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
-#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
-#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
-
-/* Forward declarations */
-struct wlc_hw_info;
-typedef struct wlc_phy_shim_info wlc_phy_shim_info_t;
-
-extern wlc_phy_shim_info_t *wlc_phy_shim_attach(struct wlc_hw_info *wlc_hw,
-						void *wl, void *wlc);
-extern void wlc_phy_shim_detach(wlc_phy_shim_info_t *physhim);
-
-/* PHY to WL utility functions */
-struct wlapi_timer;
-extern struct wlapi_timer *wlapi_init_timer(wlc_phy_shim_info_t *physhim,
-					    void (*fn) (void *arg), void *arg,
-					    const char *name);
-extern void wlapi_free_timer(wlc_phy_shim_info_t *physhim,
-			     struct wlapi_timer *t);
-extern void wlapi_add_timer(wlc_phy_shim_info_t *physhim,
-			    struct wlapi_timer *t, uint ms, int periodic);
-extern bool wlapi_del_timer(wlc_phy_shim_info_t *physhim,
-			    struct wlapi_timer *t);
-extern void wlapi_intrson(wlc_phy_shim_info_t *physhim);
-extern u32 wlapi_intrsoff(wlc_phy_shim_info_t *physhim);
-extern void wlapi_intrsrestore(wlc_phy_shim_info_t *physhim,
-			       u32 macintmask);
-
-extern void wlapi_bmac_write_shm(wlc_phy_shim_info_t *physhim, uint offset,
-				 u16 v);
-extern u16 wlapi_bmac_read_shm(wlc_phy_shim_info_t *physhim, uint offset);
-extern void wlapi_bmac_mhf(wlc_phy_shim_info_t *physhim, u8 idx,
-			   u16 mask, u16 val, int bands);
-extern void wlapi_bmac_corereset(wlc_phy_shim_info_t *physhim, u32 flags);
-extern void wlapi_suspend_mac_and_wait(wlc_phy_shim_info_t *physhim);
-extern void wlapi_switch_macfreq(wlc_phy_shim_info_t *physhim, u8 spurmode);
-extern void wlapi_enable_mac(wlc_phy_shim_info_t *physhim);
-extern void wlapi_bmac_mctrl(wlc_phy_shim_info_t *physhim, u32 mask,
-			     u32 val);
-extern void wlapi_bmac_phy_reset(wlc_phy_shim_info_t *physhim);
-extern void wlapi_bmac_bw_set(wlc_phy_shim_info_t *physhim, u16 bw);
-extern void wlapi_bmac_phyclk_fgc(wlc_phy_shim_info_t *physhim, bool clk);
-extern void wlapi_bmac_macphyclk_set(wlc_phy_shim_info_t *physhim, bool clk);
-extern void wlapi_bmac_core_phypll_ctl(wlc_phy_shim_info_t *physhim, bool on);
-extern void wlapi_bmac_core_phypll_reset(wlc_phy_shim_info_t *physhim);
-extern void wlapi_bmac_ucode_wake_override_phyreg_set(wlc_phy_shim_info_t *
-						      physhim);
-extern void wlapi_bmac_ucode_wake_override_phyreg_clear(wlc_phy_shim_info_t *
-							physhim);
-extern void wlapi_bmac_write_template_ram(wlc_phy_shim_info_t *physhim, int o,
-					  int len, void *buf);
-extern u16 wlapi_bmac_rate_shm_offset(wlc_phy_shim_info_t *physhim,
-					 u8 rate);
-extern void wlapi_ucode_sample_init(wlc_phy_shim_info_t *physhim);
-extern void wlapi_copyfrom_objmem(wlc_phy_shim_info_t *physhim, uint,
-				  void *buf, int, u32 sel);
-extern void wlapi_copyto_objmem(wlc_phy_shim_info_t *physhim, uint,
-				const void *buf, int, u32);
-
-extern void wlapi_high_update_phy_mode(wlc_phy_shim_info_t *physhim,
-				       u32 phy_mode);
-extern u16 wlapi_bmac_get_txant(wlc_phy_shim_info_t *physhim);
-#endif				/* _wlc_phy_shim_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_pub.h b/drivers/staging/brcm80211/sys/wlc_pub.h
deleted file mode 100644
index aff4130..0000000
--- a/drivers/staging/brcm80211/sys/wlc_pub.h
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_pub_h_
-#define _wlc_pub_h_
-
-#include <wlc_types.h>
-#include <wlc_scb.h>
-
-#define	WLC_NUMRATES	16	/* max # of rates in a rateset */
-#define	MAXMULTILIST	32	/* max # multicast addresses */
-#define	D11_PHY_HDR_LEN	6	/* Phy header length - 6 bytes */
-
-/* phy types */
-#define	PHY_TYPE_A	0	/* Phy type A */
-#define	PHY_TYPE_G	2	/* Phy type G */
-#define	PHY_TYPE_N	4	/* Phy type N */
-#define	PHY_TYPE_LP	5	/* Phy type Low Power A/B/G */
-#define	PHY_TYPE_SSN	6	/* Phy type Single Stream N */
-#define	PHY_TYPE_LCN	8	/* Phy type Single Stream N */
-#define	PHY_TYPE_LCNXN	9	/* Phy type 2-stream N */
-#define	PHY_TYPE_HT	7	/* Phy type 3-Stream N */
-
-/* bw */
-#define WLC_10_MHZ	10	/* 10Mhz nphy channel bandwidth */
-#define WLC_20_MHZ	20	/* 20Mhz nphy channel bandwidth */
-#define WLC_40_MHZ	40	/* 40Mhz nphy channel bandwidth */
-
-#define CHSPEC_WLC_BW(chanspec)	(CHSPEC_IS40(chanspec) ? WLC_40_MHZ : \
-				 CHSPEC_IS20(chanspec) ? WLC_20_MHZ : \
-							 WLC_10_MHZ)
-
-#define	WLC_RSSI_MINVAL		-200	/* Low value, e.g. for forcing roam */
-#define	WLC_RSSI_NO_SIGNAL	-91	/* NDIS RSSI link quality cutoffs */
-#define	WLC_RSSI_VERY_LOW	-80	/* Very low quality cutoffs */
-#define	WLC_RSSI_LOW		-70	/* Low quality cutoffs */
-#define	WLC_RSSI_GOOD		-68	/* Good quality cutoffs */
-#define	WLC_RSSI_VERY_GOOD	-58	/* Very good quality cutoffs */
-#define	WLC_RSSI_EXCELLENT	-57	/* Excellent quality cutoffs */
-
-#define WLC_PHYTYPE(_x) (_x)	/* macro to perform WLC PHY -> D11 PHY TYPE, currently 1:1 */
-
-#define MA_WINDOW_SZ		8	/* moving average window size */
-
-#define WLC_SNR_INVALID		0	/* invalid SNR value */
-
-/* a large TX Power as an init value to factor out of min() calculations,
- * keep low enough to fit in an s8, units are .25 dBm
- */
-#define WLC_TXPWR_MAX		(127)	/* ~32 dBm = 1,500 mW */
-
-/* legacy rx Antenna diversity for SISO rates */
-#define	ANT_RX_DIV_FORCE_0		0	/* Use antenna 0 */
-#define	ANT_RX_DIV_FORCE_1		1	/* Use antenna 1 */
-#define	ANT_RX_DIV_START_1		2	/* Choose starting with 1 */
-#define	ANT_RX_DIV_START_0		3	/* Choose starting with 0 */
-#define	ANT_RX_DIV_ENABLE		3	/* APHY bbConfig Enable RX Diversity */
-#define ANT_RX_DIV_DEF		ANT_RX_DIV_START_0	/* default antdiv setting */
-
-/* legacy rx Antenna diversity for SISO rates */
-#define ANT_TX_FORCE_0		0	/* Tx on antenna 0, "legacy term Main" */
-#define ANT_TX_FORCE_1		1	/* Tx on antenna 1, "legacy term Aux" */
-#define ANT_TX_LAST_RX		3	/* Tx on phy's last good Rx antenna */
-#define ANT_TX_DEF			3	/* driver's default tx antenna setting */
-
-#define TXCORE_POLICY_ALL	0x1	/* use all available core for transmit */
-
-/* Tx Chain values */
-#define TXCHAIN_DEF		0x1	/* def bitmap of txchain */
-#define TXCHAIN_DEF_NPHY	0x3	/* default bitmap of tx chains for nphy */
-#define TXCHAIN_DEF_HTPHY	0x7	/* default bitmap of tx chains for nphy */
-#define RXCHAIN_DEF		0x1	/* def bitmap of rxchain */
-#define RXCHAIN_DEF_NPHY	0x3	/* default bitmap of rx chains for nphy */
-#define RXCHAIN_DEF_HTPHY	0x7	/* default bitmap of rx chains for nphy */
-#define ANTSWITCH_NONE		0	/* no antenna switch */
-#define ANTSWITCH_TYPE_1	1	/* antenna switch on 4321CB2, 2of3 */
-#define ANTSWITCH_TYPE_2	2	/* antenna switch on 4321MPCI, 2of3 */
-#define ANTSWITCH_TYPE_3	3	/* antenna switch on 4322, 2of3 */
-
-#define RXBUFSZ		PKTBUFSZ
-#ifndef AIDMAPSZ
-#define AIDMAPSZ	(roundup(MAXSCB, NBBY)/NBBY)	/* aid bitmap size in bytes */
-#endif				/* AIDMAPSZ */
-
-typedef struct wlc_tunables {
-	int ntxd;		/* size of tx descriptor table */
-	int nrxd;		/* size of rx descriptor table */
-	int rxbufsz;		/* size of rx buffers to post */
-	int nrxbufpost;		/* # of rx buffers to post */
-	int maxscb;		/* # of SCBs supported */
-	int ampdunummpdu;	/* max number of mpdu in an ampdu */
-	int maxpktcb;		/* max # of packet callbacks */
-	int maxucodebss;	/* max # of BSS handled in ucode bcn/prb */
-	int maxucodebss4;	/* max # of BSS handled in sw bcn/prb */
-	int maxbss;		/* max # of bss info elements in scan list */
-	int datahiwat;		/* data msg txq hiwat mark */
-	int ampdudatahiwat;	/* AMPDU msg txq hiwat mark */
-	int rxbnd;		/* max # of rx bufs to process before deferring to dpc */
-	int txsbnd;		/* max # tx status to process in wlc_txstatus() */
-	int memreserved;	/* memory reserved for BMAC's USB dma rx */
-} wlc_tunables_t;
-
-typedef struct wlc_rateset {
-	uint count;		/* number of rates in rates[] */
-	u8 rates[WLC_NUMRATES];	/* rates in 500kbps units w/hi bit set if basic */
-	u8 htphy_membership;	/* HT PHY Membership */
-	u8 mcs[MCSSET_LEN];	/* supported mcs index bit map */
-} wlc_rateset_t;
-
-struct rsn_parms {
-	u8 flags;		/* misc booleans (e.g., supported) */
-	u8 multicast;	/* multicast cipher */
-	u8 ucount;		/* count of unicast ciphers */
-	u8 unicast[4];	/* unicast ciphers */
-	u8 acount;		/* count of auth modes */
-	u8 auth[4];		/* Authentication modes */
-	u8 PAD[4];		/* padding for future growth */
-};
-
-/*
- * buffer length needed for wlc_format_ssid
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN	((4 * DOT11_MAX_SSID_LEN) + 1)
-
-#define RSN_FLAGS_SUPPORTED		0x1	/* Flag for rsn_params */
-#define RSN_FLAGS_PREAUTH		0x2	/* Flag for WPA2 rsn_params */
-
-/* All the HT-specific default advertised capabilities (including AMPDU)
- * should be grouped here at one place
- */
-#define AMPDU_DEF_MPDU_DENSITY	6	/* default mpdu density (110 ==> 4us) */
-
-/* defaults for the HT (MIMO) bss */
-#define HT_CAP	((HT_CAP_MIMO_PS_OFF << HT_CAP_MIMO_PS_SHIFT) | HT_CAP_40MHZ | \
-	HT_CAP_GF | HT_CAP_MAX_AMSDU | HT_CAP_DSSS_CCK)
-
-/* WLC packet type is a void * */
-typedef void *wlc_pkt_t;
-
-/* Event data type */
-typedef struct wlc_event {
-	wl_event_msg_t event;	/* encapsulated event */
-	struct ether_addr *addr;	/* used to keep a trace of the potential present of
-					 * an address in wlc_event_msg_t
-					 */
-	int bsscfgidx;		/* BSS config when needed */
-	struct wl_if *wlif;	/* pointer to wlif */
-	void *data;		/* used to hang additional data on an event */
-	struct wlc_event *next;	/* enables ordered list of pending events */
-} wlc_event_t;
-
-/* wlc internal bss_info, wl external one is in wlioctl.h */
-typedef struct wlc_bss_info {
-	struct ether_addr BSSID;	/* network BSSID */
-	u16 flags;		/* flags for internal attributes */
-	u8 SSID_len;		/* the length of SSID */
-	u8 SSID[32];		/* SSID string */
-	s16 RSSI;		/* receive signal strength (in dBm) */
-	s16 SNR;		/* receive signal SNR in dB */
-	u16 beacon_period;	/* units are Kusec */
-	u16 atim_window;	/* units are Kusec */
-	chanspec_t chanspec;	/* Channel num, bw, ctrl_sb and band */
-	s8 infra;		/* 0=IBSS, 1=infrastructure, 2=unknown */
-	wlc_rateset_t rateset;	/* supported rates */
-	u8 dtim_period;	/* DTIM period */
-	s8 phy_noise;		/* noise right after tx (in dBm) */
-	u16 capability;	/* Capability information */
-	struct dot11_bcn_prb *bcn_prb;	/* beacon/probe response frame (ioctl na) */
-	u16 bcn_prb_len;	/* beacon/probe response frame length (ioctl na) */
-	u8 wme_qosinfo;	/* QoS Info from WME IE; valid if WLC_BSS_WME flag set */
-	struct rsn_parms wpa;
-	struct rsn_parms wpa2;
-	u16 qbss_load_aac;	/* qbss load available admission capacity */
-	/* qbss_load_chan_free <- (0xff - channel_utilization of qbss_load_ie_t) */
-	u8 qbss_load_chan_free;	/* indicates how free the channel is */
-	u8 mcipher;		/* multicast cipher */
-	u8 wpacfg;		/* wpa config index */
-} wlc_bss_info_t;
-
-/* forward declarations */
-struct wlc_if;
-
-/* wlc_ioctl error codes */
-#define WLC_ENOIOCTL	1	/* No such Ioctl */
-#define WLC_EINVAL	2	/* Invalid value */
-#define WLC_ETOOSMALL	3	/* Value too small */
-#define WLC_ETOOBIG	4	/* Value too big */
-#define WLC_ERANGE	5	/* Out of range */
-#define WLC_EDOWN	6	/* Down */
-#define WLC_EUP		7	/* Up */
-#define WLC_ENOMEM	8	/* No Memory */
-#define WLC_EBUSY	9	/* Busy */
-
-/* IOVar flags for common error checks */
-#define IOVF_MFG	(1<<3)	/* flag for mfgtest iovars */
-#define IOVF_WHL	(1<<4)	/* value must be whole (0-max) */
-#define IOVF_NTRL	(1<<5)	/* value must be natural (1-max) */
-
-#define IOVF_SET_UP	(1<<6)	/* set requires driver be up */
-#define IOVF_SET_DOWN	(1<<7)	/* set requires driver be down */
-#define IOVF_SET_CLK	(1<<8)	/* set requires core clock */
-#define IOVF_SET_BAND	(1<<9)	/* set requires fixed band */
-
-#define IOVF_GET_UP	(1<<10)	/* get requires driver be up */
-#define IOVF_GET_DOWN	(1<<11)	/* get requires driver be down */
-#define IOVF_GET_CLK	(1<<12)	/* get requires core clock */
-#define IOVF_GET_BAND	(1<<13)	/* get requires fixed band */
-#define IOVF_OPEN_ALLOW	(1<<14)	/* set allowed iovar for opensrc */
-
-/* watchdog down and dump callback function proto's */
-typedef int (*watchdog_fn_t) (void *handle);
-typedef int (*down_fn_t) (void *handle);
-typedef int (*dump_fn_t) (void *handle, struct bcmstrbuf *b);
-
-/* IOVar handler
- *
- * handle - a pointer value registered with the function
- * vi - iovar_info that was looked up
- * actionid - action ID, calculated by IOV_GVAL() and IOV_SVAL() based on varid.
- * name - the actual iovar name
- * params/plen - parameters and length for a get, input only.
- * arg/len - buffer and length for value to be set or retrieved, input or output.
- * vsize - value size, valid for integer type only.
- * wlcif - interface context (wlc_if pointer)
- *
- * All pointers may point into the same buffer.
- */
-typedef int (*iovar_fn_t) (void *handle, const bcm_iovar_t *vi,
-			   u32 actionid, const char *name, void *params,
-			   uint plen, void *arg, int alen, int vsize,
-			   struct wlc_if *wlcif);
-
-#define MAC80211_PROMISC_BCNS	(1 << 0)
-#define MAC80211_SCAN		(1 << 1)
-
-/*
- * Public portion of "common" os-independent state structure.
- * The wlc handle points at this.
- */
-struct wlc_pub {
-	void *wlc;
-
-	struct ieee80211_hw *ieee_hw;
-	struct scb *global_scb;
-	scb_ampdu_t *global_ampdu;
-	uint mac80211_state;
-	uint unit;		/* device instance number */
-	uint corerev;		/* core revision */
-	struct osl_info *osh;		/* pointer to os handle */
-	si_t *sih;		/* SB handle (cookie for siutils calls) */
-	char *vars;		/* "environment" name=value */
-	bool up;		/* interface up and running */
-	bool hw_off;		/* HW is off */
-	wlc_tunables_t *tunables;	/* tunables: ntxd, nrxd, maxscb, etc. */
-	bool hw_up;		/* one time hw up/down(from boot or hibernation) */
-	bool _piomode;		/* true if pio mode *//* BMAC_NOTE: NEED In both */
-	uint _nbands;		/* # bands supported */
-	uint now;		/* # elapsed seconds */
-
-	bool promisc;		/* promiscuous destination address */
-	bool delayed_down;	/* down delayed */
-	bool _ap;		/* AP mode enabled */
-	bool _apsta;		/* simultaneous AP/STA mode enabled */
-	bool _assoc_recreate;	/* association recreation on up transitions */
-	int _wme;		/* WME QoS mode */
-	u8 _mbss;		/* MBSS mode on */
-	bool allmulti;		/* enable all multicasts */
-	bool associated;	/* true:part of [I]BSS, false: not */
-	/* (union of stas_associated, aps_associated) */
-	bool phytest_on;	/* whether a PHY test is running */
-	bool bf_preempt_4306;	/* True to enable 'darwin' mode */
-	bool _ampdu;		/* ampdu enabled or not */
-	bool _cac;		/* 802.11e CAC enabled */
-	u8 _n_enab;		/* bitmap of 11N + HT support */
-	bool _n_reqd;		/* N support required for clients */
-
-	s8 _coex;		/* 20/40 MHz BSS Management AUTO, ENAB, DISABLE */
-	bool _priofc;		/* Priority-based flowcontrol */
-
-	struct ether_addr cur_etheraddr;	/* our local ethernet address */
-
-	struct ether_addr *multicast;	/* ptr to list of multicast addresses */
-	uint nmulticast;	/* # enabled multicast addresses */
-
-	u32 wlfeatureflag;	/* Flags to control sw features from registry */
-	int psq_pkts_total;	/* total num of ps pkts */
-
-	u16 txmaxpkts;	/* max number of large pkts allowed to be pending */
-
-	/* s/w decryption counters */
-	u32 swdecrypt;	/* s/w decrypt attempts */
-
-	int bcmerror;		/* last bcm error */
-
-	mbool radio_disabled;	/* bit vector for radio disabled reasons */
-	bool radio_active;	/* radio on/off state */
-	u16 roam_time_thresh;	/* Max. # secs. of not hearing beacons
-					 * before roaming.
-					 */
-	bool align_wd_tbtt;	/* Align watchdog with tbtt indication
-				 * handling. This flag is cleared by default
-				 * and is set by per port code explicitly and
-				 * you need to make sure the OSL_SYSUPTIME()
-				 * is implemented properly in osl of that port
-				 * when it enables this Power Save feature.
-				 */
-
-	u16 boardrev;	/* version # of particular board */
-	u8 sromrev;		/* version # of the srom */
-	char srom_ccode[WLC_CNTRY_BUF_SZ];	/* Country Code in SROM */
-	u32 boardflags;	/* Board specific flags from srom */
-	u32 boardflags2;	/* More board flags if sromrev >= 4 */
-	bool tempsense_disable;	/* disable periodic tempsense check */
-
-	bool _lmac;		/* lmac module included and enabled */
-	bool _lmacproto;	/* lmac protocol module included and enabled */
-	bool phy_11ncapable;	/* the PHY/HW is capable of 802.11N */
-	bool _ampdumac;		/* mac assist ampdu enabled or not */
-};
-
-/* wl_monitor rx status per packet */
-typedef struct wl_rxsts {
-	uint pkterror;		/* error flags per pkt */
-	uint phytype;		/* 802.11 A/B/G ... */
-	uint channel;		/* channel */
-	uint datarate;		/* rate in 500kbps */
-	uint antenna;		/* antenna pkts received on */
-	uint pktlength;		/* pkt length minus bcm phy hdr */
-	u32 mactime;		/* time stamp from mac, count per 1us */
-	uint sq;		/* signal quality */
-	s32 signal;		/* in dbm */
-	s32 noise;		/* in dbm */
-	uint preamble;		/* Unknown, short, long */
-	uint encoding;		/* Unknown, CCK, PBCC, OFDM */
-	uint nfrmtype;		/* special 802.11n frames(AMPDU, AMSDU) */
-	struct wl_if *wlif;	/* wl interface */
-} wl_rxsts_t;
-
-/* status per error RX pkt */
-#define WL_RXS_CRC_ERROR		0x00000001	/* CRC Error in packet */
-#define WL_RXS_RUNT_ERROR		0x00000002	/* Runt packet */
-#define WL_RXS_ALIGN_ERROR		0x00000004	/* Misaligned packet */
-#define WL_RXS_OVERSIZE_ERROR		0x00000008	/* packet bigger than RX_LENGTH (usually 1518) */
-#define WL_RXS_WEP_ICV_ERROR		0x00000010	/* Integrity Check Value error */
-#define WL_RXS_WEP_ENCRYPTED		0x00000020	/* Encrypted with WEP */
-#define WL_RXS_PLCP_SHORT		0x00000040	/* Short PLCP error */
-#define WL_RXS_DECRYPT_ERR		0x00000080	/* Decryption error */
-#define WL_RXS_OTHER_ERR		0x80000000	/* Other errors */
-
-/* phy type */
-#define WL_RXS_PHY_A			0x00000000	/* A phy type */
-#define WL_RXS_PHY_B			0x00000001	/* B phy type */
-#define WL_RXS_PHY_G			0x00000002	/* G phy type */
-#define WL_RXS_PHY_N			0x00000004	/* N phy type */
-
-/* encoding */
-#define WL_RXS_ENCODING_CCK		0x00000000	/* CCK encoding */
-#define WL_RXS_ENCODING_OFDM		0x00000001	/* OFDM encoding */
-
-/* preamble */
-#define WL_RXS_UNUSED_STUB		0x0	/* stub to match with wlc_ethereal.h */
-#define WL_RXS_PREAMBLE_SHORT		0x00000001	/* Short preamble */
-#define WL_RXS_PREAMBLE_LONG		0x00000002	/* Long preamble */
-#define WL_RXS_PREAMBLE_MIMO_MM		0x00000003	/* MIMO mixed mode preamble */
-#define WL_RXS_PREAMBLE_MIMO_GF		0x00000004	/* MIMO green field preamble */
-
-#define WL_RXS_NFRM_AMPDU_FIRST		0x00000001	/* first MPDU in A-MPDU */
-#define WL_RXS_NFRM_AMPDU_SUB		0x00000002	/* subsequent MPDU(s) in A-MPDU */
-#define WL_RXS_NFRM_AMSDU_FIRST		0x00000004	/* first MSDU in A-MSDU */
-#define WL_RXS_NFRM_AMSDU_SUB		0x00000008	/* subsequent MSDU(s) in A-MSDU */
-
-/* forward declare and use the struct notation so we don't have to
- * have it defined if not necessary.
- */
-struct wlc_info;
-struct wlc_hw_info;
-struct wlc_bsscfg;
-struct wlc_if;
-
-/***********************************************
- * Feature-related macros to optimize out code *
- * *********************************************
- */
-
-/* AP Support (versus STA) */
-#define	AP_ENAB(pub)	(0)
-
-/* Macro to check if APSTA mode enabled */
-#define APSTA_ENAB(pub)	(0)
-
-/* Some useful combinations */
-#define STA_ONLY(pub)	(!AP_ENAB(pub))
-#define AP_ONLY(pub)	(AP_ENAB(pub) && !APSTA_ENAB(pub))
-
-#define ENAB_1x1	0x01
-#define ENAB_2x2	0x02
-#define ENAB_3x3	0x04
-#define ENAB_4x4	0x08
-#define SUPPORT_11N	(ENAB_1x1|ENAB_2x2)
-#define SUPPORT_HT	(ENAB_1x1|ENAB_2x2|ENAB_3x3)
-/* WL11N Support */
-#if ((defined(NCONF) && (NCONF != 0)) || (defined(LCNCONF) && (LCNCONF != 0)) || \
-	(defined(HTCONF) && (HTCONF != 0)) || (defined(SSLPNCONF) && (SSLPNCONF != 0)))
-#define N_ENAB(pub) ((pub)->_n_enab & SUPPORT_11N)
-#define N_REQD(pub) ((pub)->_n_reqd)
-#else
-#define N_ENAB(pub)	0
-#define N_REQD(pub)	0
-#endif
-
-#if (defined(HTCONF) && (HTCONF != 0))
-#define HT_ENAB(pub) (((pub)->_n_enab & SUPPORT_HT) == SUPPORT_HT)
-#else
-#define HT_ENAB(pub) 0
-#endif
-
-#define AMPDU_AGG_HOST	1
-#define AMPDU_ENAB(pub) ((pub)->_ampdu)
-
-#define EDCF_ENAB(pub) (WME_ENAB(pub))
-#define QOS_ENAB(pub) (WME_ENAB(pub) || N_ENAB(pub))
-
-#define MONITOR_ENAB(wlc)	((wlc)->monitor)
-
-#define PROMISC_ENAB(wlc)	((wlc)->promisc)
-
-#define	WLC_PREC_COUNT		16	/* Max precedence level implemented */
-
-/* pri is priority encoded in the packet. This maps the Packet priority to
- * enqueue precedence as defined in wlc_prec_map
- */
-extern const u8 wlc_prio2prec_map[];
-#define WLC_PRIO_TO_PREC(pri)	wlc_prio2prec_map[(pri) & 7]
-
-/* This maps priority to one precedence higher - Used by PS-Poll response packets to
- * simulate enqueue-at-head operation, but still maintain the order on the queue
- */
-#define WLC_PRIO_TO_HI_PREC(pri)	min(WLC_PRIO_TO_PREC(pri) + 1, WLC_PREC_COUNT - 1)
-
-extern const u8 wme_fifo2ac[];
-#define WME_PRIO2AC(prio)	wme_fifo2ac[prio2fifo[(prio)]]
-
-/* Mask to describe all precedence levels */
-#define WLC_PREC_BMP_ALL		MAXBITVAL(WLC_PREC_COUNT)
-
-/* Define a bitmap of precedences comprised by each AC */
-#define WLC_PREC_BMP_AC_BE	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BE)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BE)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_EE)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_EE)))
-#define WLC_PREC_BMP_AC_BK	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_BK)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_BK)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NONE)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NONE)))
-#define WLC_PREC_BMP_AC_VI	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_CL)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_CL)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VI)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VI)))
-#define WLC_PREC_BMP_AC_VO	(NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_VO)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_VO)) |	\
-				NBITVAL(WLC_PRIO_TO_PREC(PRIO_8021D_NC)) |	\
-				NBITVAL(WLC_PRIO_TO_HI_PREC(PRIO_8021D_NC)))
-
-/* WME Support */
-#define WME_ENAB(pub) ((pub)->_wme != OFF)
-#define WME_AUTO(wlc) ((wlc)->pub->_wme == AUTO)
-
-#define WLC_USE_COREFLAGS	0xffffffff	/* invalid core flags, use the saved coreflags */
-
-#define WLC_UPDATE_STATS(wlc)	0	/* No stats support */
-#define WLCNTINCR(a)		/* No stats support */
-#define WLCNTDECR(a)		/* No stats support */
-#define WLCNTADD(a, delta)	/* No stats support */
-#define WLCNTSET(a, value)	/* No stats support */
-#define WLCNTVAL(a)		0	/* No stats support */
-
-/* common functions for every port */
-extern void *wlc_attach(void *wl, u16 vendor, u16 device, uint unit,
-			bool piomode, struct osl_info *osh, void *regsva,
-			uint bustype, void *btparam, uint *perr);
-extern uint wlc_detach(struct wlc_info *wlc);
-extern int wlc_up(struct wlc_info *wlc);
-extern uint wlc_down(struct wlc_info *wlc);
-
-extern int wlc_set(struct wlc_info *wlc, int cmd, int arg);
-extern int wlc_get(struct wlc_info *wlc, int cmd, int *arg);
-extern int wlc_iovar_getint(struct wlc_info *wlc, const char *name, int *arg);
-extern int wlc_iovar_setint(struct wlc_info *wlc, const char *name, int arg);
-extern bool wlc_chipmatch(u16 vendor, u16 device);
-extern void wlc_init(struct wlc_info *wlc);
-extern void wlc_reset(struct wlc_info *wlc);
-
-extern void wlc_intrson(struct wlc_info *wlc);
-extern u32 wlc_intrsoff(struct wlc_info *wlc);
-extern void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask);
-extern bool wlc_intrsupd(struct wlc_info *wlc);
-extern bool wlc_isr(struct wlc_info *wlc, bool *wantdpc);
-extern bool wlc_dpc(struct wlc_info *wlc, bool bounded);
-extern bool wlc_send80211_raw(struct wlc_info *wlc, struct wlc_if *wlcif,
-			      void *p, uint ac);
-extern bool wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu,
-				 struct ieee80211_hw *hw);
-extern int wlc_iovar_op(struct wlc_info *wlc, const char *name, void *params,
-			int p_len, void *arg, int len, bool set,
-			struct wlc_if *wlcif);
-extern int wlc_ioctl(struct wlc_info *wlc, int cmd, void *arg, int len,
-		     struct wlc_if *wlcif);
-/* helper functions */
-extern void wlc_statsupd(struct wlc_info *wlc);
-extern int wlc_get_header_len(void);
-extern void wlc_mac_bcn_promisc_change(struct wlc_info *wlc, bool promisc);
-extern void wlc_set_addrmatch(struct wlc_info *wlc, int match_reg_offset,
-			      const struct ether_addr *addr);
-extern void wlc_wme_setparams(struct wlc_info *wlc, u16 aci, void *arg,
-			      bool suspend);
-
-extern struct wlc_pub *wlc_pub(void *wlc);
-
-/* common functions for every port */
-extern int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_up_finish(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_down_prep(struct wlc_hw_info *wlc_hw);
-extern int wlc_bmac_down_finish(struct wlc_hw_info *wlc_hw);
-
-extern u32 wlc_reg_read(struct wlc_info *wlc, void *r, uint size);
-extern void wlc_reg_write(struct wlc_info *wlc, void *r, u32 v, uint size);
-extern void wlc_corereset(struct wlc_info *wlc, u32 flags);
-extern void wlc_mhf(struct wlc_info *wlc, u8 idx, u16 mask, u16 val,
-		    int bands);
-extern u16 wlc_mhf_get(struct wlc_info *wlc, u8 idx, int bands);
-extern u32 wlc_delta_txfunfl(struct wlc_info *wlc, int fifo);
-extern void wlc_rate_lookup_init(struct wlc_info *wlc, wlc_rateset_t *rateset);
-extern void wlc_default_rateset(struct wlc_info *wlc, wlc_rateset_t *rs);
-
-/* wlc_phy.c helper functions */
-extern void wlc_set_ps_ctrl(struct wlc_info *wlc);
-extern void wlc_mctrl(struct wlc_info *wlc, u32 mask, u32 val);
-extern void wlc_scb_ratesel_init_all(struct wlc_info *wlc);
-
-/* ioctl */
-extern int wlc_iovar_gets8(struct wlc_info *wlc, const char *name,
-			     s8 *arg);
-extern int wlc_iovar_check(struct wlc_pub *pub, const bcm_iovar_t *vi,
-			   void *arg,
-			   int len, bool set);
-
-extern int wlc_module_register(struct wlc_pub *pub, const bcm_iovar_t *iovars,
-			       const char *name, void *hdl, iovar_fn_t iovar_fn,
-			       watchdog_fn_t watchdog_fn, down_fn_t down_fn);
-extern int wlc_module_unregister(struct wlc_pub *pub, const char *name,
-				 void *hdl);
-extern void wlc_event_if(struct wlc_info *wlc, struct wlc_bsscfg *cfg,
-			 wlc_event_t *e, const struct ether_addr *addr);
-extern void wlc_suspend_mac_and_wait(struct wlc_info *wlc);
-extern void wlc_enable_mac(struct wlc_info *wlc);
-extern u16 wlc_rate_shm_offset(struct wlc_info *wlc, u8 rate);
-extern u32 wlc_get_rspec_history(struct wlc_bsscfg *cfg);
-extern u32 wlc_get_current_highest_rate(struct wlc_bsscfg *cfg);
-extern void wlc_scan_start(struct wlc_info *wlc);
-extern void wlc_scan_stop(struct wlc_info *wlc);
-
-static inline int wlc_iovar_getuint(struct wlc_info *wlc, const char *name,
-				    uint *arg)
-{
-	return wlc_iovar_getint(wlc, name, (int *)arg);
-}
-
-static inline int wlc_iovar_getu8(struct wlc_info *wlc, const char *name,
-				     u8 *arg)
-{
-	return wlc_iovar_gets8(wlc, name, (s8 *) arg);
-}
-
-static inline int wlc_iovar_setuint(struct wlc_info *wlc, const char *name,
-				    uint arg)
-{
-	return wlc_iovar_setint(wlc, name, (int)arg);
-}
-
-#if defined(BCMDBG)
-extern int wlc_iocregchk(struct wlc_info *wlc, uint band);
-#endif
-#if defined(BCMDBG)
-extern int wlc_iocpichk(struct wlc_info *wlc, uint phytype);
-#endif
-
-/* helper functions */
-extern void wlc_getrand(struct wlc_info *wlc, u8 *buf, int len);
-
-struct scb;
-extern void wlc_ps_on(struct wlc_info *wlc, struct scb *scb);
-extern void wlc_ps_off(struct wlc_info *wlc, struct scb *scb, bool discard);
-extern bool wlc_radio_monitor_stop(struct wlc_info *wlc);
-
-#if defined(BCMDBG)
-extern int wlc_format_ssid(char *buf, const unsigned char ssid[], uint ssid_len);
-#endif
-
-extern void wlc_pmkid_build_cand_list(struct wlc_bsscfg *cfg, bool check_SSID);
-extern void wlc_pmkid_event(struct wlc_bsscfg *cfg);
-
-#define	MAXBANDS		2	/* Maximum #of bands */
-/* bandstate array indices */
-#define BAND_2G_INDEX		0	/* wlc->bandstate[x] index */
-#define BAND_5G_INDEX		1	/* wlc->bandstate[x] index */
-
-#define BAND_2G_NAME		"2.4G"
-#define BAND_5G_NAME		"5G"
-
-/* BMAC RPC: 7 u32 params: pkttotlen, fifo, commit, fid, txpktpend, pktflag, rpc_id */
-#define WLC_RPCTX_PARAMS		32
-
-#endif				/* _wlc_pub_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_rate.c b/drivers/staging/brcm80211/sys/wlc_rate.c
deleted file mode 100644
index ab7d0be..0000000
--- a/drivers/staging/brcm80211/sys/wlc_rate.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#include <linux/kernel.h>
-#include <bcmdefs.h>
-#include <wlc_cfg.h>
-#include <osl.h>
-#include <linux/module.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmendian.h>
-#include <wlioctl.h>
-
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <proto/802.11.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wl_dbg.h>
-#include <wlc_pub.h>
-
-/* Rate info per rate: It tells whether a rate is ofdm or not and its phy_rate value */
-const u8 rate_info[WLC_MAXRATE + 1] = {
-	/*  0     1     2     3     4     5     6     7     8     9 */
-/*   0 */ 0x00, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  10 */ 0x00, 0x37, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x00,
-/*  20 */ 0x00, 0x00, 0x6e, 0x00, 0x8a, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x00, 0x00, 0x00,
-/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00,
-/*  50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  60 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  70 */ 0x00, 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  80 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-/*  90 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00,
-/* 100 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c
-};
-
-/* rates are in units of Kbps */
-const mcs_info_t mcs_table[MCS_TABLE_SIZE] = {
-	/* MCS  0: SS 1, MOD: BPSK,  CR 1/2 */
-	{6500, 13500, CEIL(6500 * 10, 9), CEIL(13500 * 10, 9), 0x00,
-	 WLC_RATE_6M},
-	/* MCS  1: SS 1, MOD: QPSK,  CR 1/2 */
-	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x08,
-	 WLC_RATE_12M},
-	/* MCS  2: SS 1, MOD: QPSK,  CR 3/4 */
-	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x0A,
-	 WLC_RATE_18M},
-	/* MCS  3: SS 1, MOD: 16QAM, CR 1/2 */
-	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x10,
-	 WLC_RATE_24M},
-	/* MCS  4: SS 1, MOD: 16QAM, CR 3/4 */
-	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x12,
-	 WLC_RATE_36M},
-	/* MCS  5: SS 1, MOD: 64QAM, CR 2/3 */
-	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x19,
-	 WLC_RATE_48M},
-	/* MCS  6: SS 1, MOD: 64QAM, CR 3/4 */
-	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x1A,
-	 WLC_RATE_54M},
-	/* MCS  7: SS 1, MOD: 64QAM, CR 5/6 */
-	{65000, 135000, CEIL(65000 * 10, 9), CEIL(135000 * 10, 9), 0x1C,
-	 WLC_RATE_54M},
-	/* MCS  8: SS 2, MOD: BPSK,  CR 1/2 */
-	{13000, 27000, CEIL(13000 * 10, 9), CEIL(27000 * 10, 9), 0x40,
-	 WLC_RATE_6M},
-	/* MCS  9: SS 2, MOD: QPSK,  CR 1/2 */
-	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0x48,
-	 WLC_RATE_12M},
-	/* MCS 10: SS 2, MOD: QPSK,  CR 3/4 */
-	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x4A,
-	 WLC_RATE_18M},
-	/* MCS 11: SS 2, MOD: 16QAM, CR 1/2 */
-	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0x50,
-	 WLC_RATE_24M},
-	/* MCS 12: SS 2, MOD: 16QAM, CR 3/4 */
-	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x52,
-	 WLC_RATE_36M},
-	/* MCS 13: SS 2, MOD: 64QAM, CR 2/3 */
-	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0x59,
-	 WLC_RATE_48M},
-	/* MCS 14: SS 2, MOD: 64QAM, CR 3/4 */
-	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x5A,
-	 WLC_RATE_54M},
-	/* MCS 15: SS 2, MOD: 64QAM, CR 5/6 */
-	{130000, 270000, CEIL(130000 * 10, 9), CEIL(270000 * 10, 9), 0x5C,
-	 WLC_RATE_54M},
-	/* MCS 16: SS 3, MOD: BPSK,  CR 1/2 */
-	{19500, 40500, CEIL(19500 * 10, 9), CEIL(40500 * 10, 9), 0x80,
-	 WLC_RATE_6M},
-	/* MCS 17: SS 3, MOD: QPSK,  CR 1/2 */
-	{39000, 81000, CEIL(39000 * 10, 9), CEIL(81000 * 10, 9), 0x88,
-	 WLC_RATE_12M},
-	/* MCS 18: SS 3, MOD: QPSK,  CR 3/4 */
-	{58500, 121500, CEIL(58500 * 10, 9), CEIL(121500 * 10, 9), 0x8A,
-	 WLC_RATE_18M},
-	/* MCS 19: SS 3, MOD: 16QAM, CR 1/2 */
-	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0x90,
-	 WLC_RATE_24M},
-	/* MCS 20: SS 3, MOD: 16QAM, CR 3/4 */
-	{117000, 243000, CEIL(117000 * 10, 9), CEIL(243000 * 10, 9), 0x92,
-	 WLC_RATE_36M},
-	/* MCS 21: SS 3, MOD: 64QAM, CR 2/3 */
-	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0x99,
-	 WLC_RATE_48M},
-	/* MCS 22: SS 3, MOD: 64QAM, CR 3/4 */
-	{175500, 364500, CEIL(175500 * 10, 9), CEIL(364500 * 10, 9), 0x9A,
-	 WLC_RATE_54M},
-	/* MCS 23: SS 3, MOD: 64QAM, CR 5/6 */
-	{195000, 405000, CEIL(195000 * 10, 9), CEIL(405000 * 10, 9), 0x9B,
-	 WLC_RATE_54M},
-	/* MCS 24: SS 4, MOD: BPSK,  CR 1/2 */
-	{26000, 54000, CEIL(26000 * 10, 9), CEIL(54000 * 10, 9), 0xC0,
-	 WLC_RATE_6M},
-	/* MCS 25: SS 4, MOD: QPSK,  CR 1/2 */
-	{52000, 108000, CEIL(52000 * 10, 9), CEIL(108000 * 10, 9), 0xC8,
-	 WLC_RATE_12M},
-	/* MCS 26: SS 4, MOD: QPSK,  CR 3/4 */
-	{78000, 162000, CEIL(78000 * 10, 9), CEIL(162000 * 10, 9), 0xCA,
-	 WLC_RATE_18M},
-	/* MCS 27: SS 4, MOD: 16QAM, CR 1/2 */
-	{104000, 216000, CEIL(104000 * 10, 9), CEIL(216000 * 10, 9), 0xD0,
-	 WLC_RATE_24M},
-	/* MCS 28: SS 4, MOD: 16QAM, CR 3/4 */
-	{156000, 324000, CEIL(156000 * 10, 9), CEIL(324000 * 10, 9), 0xD2,
-	 WLC_RATE_36M},
-	/* MCS 29: SS 4, MOD: 64QAM, CR 2/3 */
-	{208000, 432000, CEIL(208000 * 10, 9), CEIL(432000 * 10, 9), 0xD9,
-	 WLC_RATE_48M},
-	/* MCS 30: SS 4, MOD: 64QAM, CR 3/4 */
-	{234000, 486000, CEIL(234000 * 10, 9), CEIL(486000 * 10, 9), 0xDA,
-	 WLC_RATE_54M},
-	/* MCS 31: SS 4, MOD: 64QAM, CR 5/6 */
-	{260000, 540000, CEIL(260000 * 10, 9), CEIL(540000 * 10, 9), 0xDB,
-	 WLC_RATE_54M},
-	/* MCS 32: SS 1, MOD: BPSK,  CR 1/2 */
-	{0, 6000, 0, CEIL(6000 * 10, 9), 0x00, WLC_RATE_6M},
-};
-
-/* phycfg for legacy OFDM frames: code rate, modulation scheme, spatial streams
- *   Number of spatial streams: always 1
- *   other fields: refer to table 78 of section 17.3.2.2 of the original .11a standard
- */
-typedef struct legacy_phycfg {
-	u32 rate_ofdm;	/* ofdm mac rate */
-	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
-} legacy_phycfg_t;
-
-#define LEGACY_PHYCFG_TABLE_SIZE	12	/* Number of legacy_rate_cfg entries in the table */
-
-/* In CCK mode LPPHY overloads OFDM Modulation bits with CCK Data Rate */
-/* Eventually MIMOPHY would also be converted to this format */
-/* 0 = 1Mbps; 1 = 2Mbps; 2 = 5.5Mbps; 3 = 11Mbps */
-static const legacy_phycfg_t legacy_phycfg_table[LEGACY_PHYCFG_TABLE_SIZE] = {
-	{WLC_RATE_1M, 0x00},	/* CCK  1Mbps,  data rate  0 */
-	{WLC_RATE_2M, 0x08},	/* CCK  2Mbps,  data rate  1 */
-	{WLC_RATE_5M5, 0x10},	/* CCK  5.5Mbps,  data rate  2 */
-	{WLC_RATE_11M, 0x18},	/* CCK  11Mbps,  data rate   3 */
-	{WLC_RATE_6M, 0x00},	/* OFDM  6Mbps,  code rate 1/2, BPSK,   1 spatial stream */
-	{WLC_RATE_9M, 0x02},	/* OFDM  9Mbps,  code rate 3/4, BPSK,   1 spatial stream */
-	{WLC_RATE_12M, 0x08},	/* OFDM  12Mbps, code rate 1/2, QPSK,   1 spatial stream */
-	{WLC_RATE_18M, 0x0A},	/* OFDM  18Mbps, code rate 3/4, QPSK,   1 spatial stream */
-	{WLC_RATE_24M, 0x10},	/* OFDM  24Mbps, code rate 1/2, 16-QAM, 1 spatial stream */
-	{WLC_RATE_36M, 0x12},	/* OFDM  36Mbps, code rate 3/4, 16-QAM, 1 spatial stream */
-	{WLC_RATE_48M, 0x19},	/* OFDM  48Mbps, code rate 2/3, 64-QAM, 1 spatial stream */
-	{WLC_RATE_54M, 0x1A},	/* OFDM  54Mbps, code rate 3/4, 64-QAM, 1 spatial stream */
-};
-
-/* Hardware rates (also encodes default basic rates) */
-
-const wlc_rateset_t cck_ofdm_mimo_rates = {
-	12,
-	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
-	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
-	 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t ofdm_mimo_rates = {
-	8,
-	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
-	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-/* Default ratesets that include MCS32 for 40BW channels */
-const wlc_rateset_t cck_ofdm_40bw_mimo_rates = {
-	12,
-	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
-	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
-	 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t ofdm_40bw_mimo_rates = {
-	8,
-	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
-	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
-	0x00,
-	{0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t cck_ofdm_rates = {
-	12,
-	{			/*    1b,   2b,   5.5b, 6,    9,    11b,  12,   18,   24,   36,   48,   54 Mbps */
-	 0x82, 0x84, 0x8b, 0x0c, 0x12, 0x96, 0x18, 0x24, 0x30, 0x48, 0x60,
-	 0x6c},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t gphy_legacy_rates = {
-	4,
-	{			/*    1b,   2b,   5.5b,  11b Mbps */
-	 0x82, 0x84, 0x8b, 0x96},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t ofdm_rates = {
-	8,
-	{			/*    6b,   9,    12b,  18,   24b,  36,   48,   54 Mbps */
-	 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-const wlc_rateset_t cck_rates = {
-	4,
-	{			/*    1b,   2b,   5.5,  11 Mbps */
-	 0x82, 0x84, 0x0b, 0x16},
-	0x00,
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00, 0x00, 0x00, 0x00}
-};
-
-static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate);
-
-/* check if rateset is valid.
- * if check_brate is true, rateset without a basic rate is considered NOT valid.
- */
-static bool wlc_rateset_valid(wlc_rateset_t *rs, bool check_brate)
-{
-	uint idx;
-
-	if (!rs->count)
-		return false;
-
-	if (!check_brate)
-		return true;
-
-	/* error if no basic rates */
-	for (idx = 0; idx < rs->count; idx++) {
-		if (rs->rates[idx] & WLC_RATE_FLAG)
-			return true;
-	}
-	return false;
-}
-
-void wlc_rateset_mcs_upd(wlc_rateset_t *rs, u8 txstreams)
-{
-	int i;
-	for (i = txstreams; i < MAX_STREAMS_SUPPORTED; i++)
-		rs->mcs[i] = 0;
-}
-
-/* filter based on hardware rateset, and sort filtered rateset with basic bit(s) preserved,
- * and check if resulting rateset is valid.
-*/
-bool
-wlc_rate_hwrs_filter_sort_validate(wlc_rateset_t *rs,
-				   const wlc_rateset_t *hw_rs,
-				   bool check_brate, u8 txstreams)
-{
-	u8 rateset[WLC_MAXRATE + 1];
-	u8 r;
-	uint count;
-	uint i;
-
-	memset(rateset, 0, sizeof(rateset));
-	count = rs->count;
-
-	for (i = 0; i < count; i++) {
-		/* mask off "basic rate" bit, WLC_RATE_FLAG */
-		r = (int)rs->rates[i] & RATE_MASK;
-		if ((r > WLC_MAXRATE) || (rate_info[r] == 0)) {
-			continue;
-		}
-		rateset[r] = rs->rates[i];	/* preserve basic bit! */
-	}
-
-	/* fill out the rates in order, looking at only supported rates */
-	count = 0;
-	for (i = 0; i < hw_rs->count; i++) {
-		r = hw_rs->rates[i] & RATE_MASK;
-		ASSERT(r <= WLC_MAXRATE);
-		if (rateset[r])
-			rs->rates[count++] = rateset[r];
-	}
-
-	rs->count = count;
-
-	/* only set the mcs rate bit if the equivalent hw mcs bit is set */
-	for (i = 0; i < MCSSET_LEN; i++)
-		rs->mcs[i] = (rs->mcs[i] & hw_rs->mcs[i]);
-
-	if (wlc_rateset_valid(rs, check_brate))
-		return true;
-	else
-		return false;
-}
-
-/* caluclate the rate of a rx'd frame and return it as a ratespec */
-ratespec_t BCMFASTPATH wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp)
-{
-	int phy_type;
-	ratespec_t rspec = PHY_TXC1_BW_20MHZ << RSPEC_BW_SHIFT;
-
-	phy_type =
-	    ((rxh->RxChan & RXS_CHAN_PHYTYPE_MASK) >> RXS_CHAN_PHYTYPE_SHIFT);
-
-	if ((phy_type == PHY_TYPE_N) || (phy_type == PHY_TYPE_SSN) ||
-	    (phy_type == PHY_TYPE_LCN) || (phy_type == PHY_TYPE_HT)) {
-		switch (rxh->PhyRxStatus_0 & PRXS0_FT_MASK) {
-		case PRXS0_CCK:
-			rspec =
-			    CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
-			break;
-		case PRXS0_OFDM:
-			rspec =
-			    OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->
-					      rlpt[0]);
-			break;
-		case PRXS0_PREN:
-			rspec = (plcp[0] & MIMO_PLCP_MCS_MASK) | RSPEC_MIMORATE;
-			if (plcp[0] & MIMO_PLCP_40MHZ) {
-				/* indicate rspec is for 40 MHz mode */
-				rspec &= ~RSPEC_BW_MASK;
-				rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
-			}
-			break;
-		case PRXS0_STDN:
-			/* fallthru */
-		default:
-			/* not supported */
-			ASSERT(0);
-			break;
-		}
-		if (PLCP3_ISSGI(plcp[3]))
-			rspec |= RSPEC_SHORT_GI;
-	} else
-	    if ((phy_type == PHY_TYPE_A) || (rxh->PhyRxStatus_0 & PRXS0_OFDM))
-		rspec = OFDM_PHY2MAC_RATE(((ofdm_phy_hdr_t *) plcp)->rlpt[0]);
-	else
-		rspec = CCK_PHY2MAC_RATE(((cck_phy_hdr_t *) plcp)->signal);
-
-	return rspec;
-}
-
-/* copy rateset src to dst as-is (no masking or sorting) */
-void wlc_rateset_copy(const wlc_rateset_t *src, wlc_rateset_t *dst)
-{
-	bcopy(src, dst, sizeof(wlc_rateset_t));
-}
-
-/*
- * Copy and selectively filter one rateset to another.
- * 'basic_only' means only copy basic rates.
- * 'rates' indicates cck (11b) and ofdm rates combinations.
- *    - 0: cck and ofdm
- *    - 1: cck only
- *    - 2: ofdm only
- * 'xmask' is the copy mask (typically 0x7f or 0xff).
- */
-void
-wlc_rateset_filter(wlc_rateset_t *src, wlc_rateset_t *dst, bool basic_only,
-		   u8 rates, uint xmask, bool mcsallow)
-{
-	uint i;
-	uint r;
-	uint count;
-
-	count = 0;
-	for (i = 0; i < src->count; i++) {
-		r = src->rates[i];
-		if (basic_only && !(r & WLC_RATE_FLAG))
-			continue;
-		if ((rates == WLC_RATES_CCK) && IS_OFDM((r & RATE_MASK)))
-			continue;
-		if ((rates == WLC_RATES_OFDM) && IS_CCK((r & RATE_MASK)))
-			continue;
-		dst->rates[count++] = r & xmask;
-	}
-	dst->count = count;
-	dst->htphy_membership = src->htphy_membership;
-
-	if (mcsallow && rates != WLC_RATES_CCK)
-		bcopy(&src->mcs[0], &dst->mcs[0], MCSSET_LEN);
-	else
-		wlc_rateset_mcs_clear(dst);
-}
-
-/* select rateset for a given phy_type and bandtype and filter it, sort it
- * and fill rs_tgt with result
- */
-void
-wlc_rateset_default(wlc_rateset_t *rs_tgt, const wlc_rateset_t *rs_hw,
-		    uint phy_type, int bandtype, bool cck_only, uint rate_mask,
-		    bool mcsallow, u8 bw, u8 txstreams)
-{
-	const wlc_rateset_t *rs_dflt;
-	wlc_rateset_t rs_sel;
-	if ((PHYTYPE_IS(phy_type, PHY_TYPE_HT)) ||
-	    (PHYTYPE_IS(phy_type, PHY_TYPE_N)) ||
-	    (PHYTYPE_IS(phy_type, PHY_TYPE_LCN)) ||
-	    (PHYTYPE_IS(phy_type, PHY_TYPE_SSN))) {
-		if (BAND_5G(bandtype)) {
-			rs_dflt = (bw == WLC_20_MHZ ?
-				   &ofdm_mimo_rates : &ofdm_40bw_mimo_rates);
-		} else {
-			rs_dflt = (bw == WLC_20_MHZ ?
-				   &cck_ofdm_mimo_rates :
-				   &cck_ofdm_40bw_mimo_rates);
-		}
-	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_LP)) {
-		rs_dflt = (BAND_5G(bandtype)) ? &ofdm_rates : &cck_ofdm_rates;
-	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_A)) {
-		rs_dflt = &ofdm_rates;
-	} else if (PHYTYPE_IS(phy_type, PHY_TYPE_G)) {
-		rs_dflt = &cck_ofdm_rates;
-	} else {
-		ASSERT(0);	/* should not happen */
-		rs_dflt = &cck_rates;	/* force cck */
-	}
-
-	/* if hw rateset is not supplied, assign selected rateset to it */
-	if (!rs_hw)
-		rs_hw = rs_dflt;
-
-	wlc_rateset_copy(rs_dflt, &rs_sel);
-	wlc_rateset_mcs_upd(&rs_sel, txstreams);
-	wlc_rateset_filter(&rs_sel, rs_tgt, false,
-			   cck_only ? WLC_RATES_CCK : WLC_RATES_CCK_OFDM,
-			   rate_mask, mcsallow);
-	wlc_rate_hwrs_filter_sort_validate(rs_tgt, rs_hw, false,
-					   mcsallow ? txstreams : 1);
-}
-
-s16 BCMFASTPATH wlc_rate_legacy_phyctl(uint rate)
-{
-	uint i;
-	for (i = 0; i < LEGACY_PHYCFG_TABLE_SIZE; i++)
-		if (rate == legacy_phycfg_table[i].rate_ofdm)
-			return legacy_phycfg_table[i].tx_phy_ctl3;
-
-	return -1;
-}
-
-void wlc_rateset_mcs_clear(wlc_rateset_t *rateset)
-{
-	uint i;
-	for (i = 0; i < MCSSET_LEN; i++)
-		rateset->mcs[i] = 0;
-}
-
-void wlc_rateset_mcs_build(wlc_rateset_t *rateset, u8 txstreams)
-{
-	bcopy(&cck_ofdm_mimo_rates.mcs[0], &rateset->mcs[0], MCSSET_LEN);
-	wlc_rateset_mcs_upd(rateset, txstreams);
-}
-
-/* Based on bandwidth passed, allow/disallow MCS 32 in the rateset */
-void wlc_rateset_bw_mcs_filter(wlc_rateset_t *rateset, u8 bw)
-{
-	if (bw == WLC_40_MHZ)
-		setbit(rateset->mcs, 32);
-	else
-		clrbit(rateset->mcs, 32);
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_rate.h b/drivers/staging/brcm80211/sys/wlc_rate.h
deleted file mode 100644
index 25ba2a4..0000000
--- a/drivers/staging/brcm80211/sys/wlc_rate.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _WLC_RATE_H_
-#define _WLC_RATE_H_
-
-extern const u8 rate_info[];
-extern const struct wlc_rateset cck_ofdm_mimo_rates;
-extern const struct wlc_rateset ofdm_mimo_rates;
-extern const struct wlc_rateset cck_ofdm_rates;
-extern const struct wlc_rateset ofdm_rates;
-extern const struct wlc_rateset cck_rates;
-extern const struct wlc_rateset gphy_legacy_rates;
-extern const struct wlc_rateset wlc_lrs_rates;
-extern const struct wlc_rateset rate_limit_1_2;
-
-typedef struct mcs_info {
-	u32 phy_rate_20;	/* phy rate in kbps [20Mhz] */
-	u32 phy_rate_40;	/* phy rate in kbps [40Mhz] */
-	u32 phy_rate_20_sgi;	/* phy rate in kbps [20Mhz] with SGI */
-	u32 phy_rate_40_sgi;	/* phy rate in kbps [40Mhz] with SGI */
-	u8 tx_phy_ctl3;	/* phy ctl byte 3, code rate, modulation type, # of streams */
-	u8 leg_ofdm;		/* matching legacy ofdm rate in 500bkps */
-} mcs_info_t;
-
-#define WLC_MAXMCS	32	/* max valid mcs index */
-#define MCS_TABLE_SIZE	33	/* Number of mcs entries in the table */
-extern const mcs_info_t mcs_table[];
-
-#define MCS_INVALID	0xFF
-#define MCS_CR_MASK	0x07	/* Code Rate bit mask */
-#define MCS_MOD_MASK	0x38	/* Modulation bit shift */
-#define MCS_MOD_SHIFT	3	/* MOdulation bit shift */
-#define MCS_TXS_MASK	0xc0	/* num tx streams - 1 bit mask */
-#define MCS_TXS_SHIFT	6	/* num tx streams - 1 bit shift */
-#define MCS_CR(_mcs)	(mcs_table[_mcs].tx_phy_ctl3 & MCS_CR_MASK)
-#define MCS_MOD(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_MOD_MASK) >> MCS_MOD_SHIFT)
-#define MCS_TXS(_mcs)	((mcs_table[_mcs].tx_phy_ctl3 & MCS_TXS_MASK) >> MCS_TXS_SHIFT)
-#define MCS_RATE(_mcs, _is40, _sgi)	(_sgi ? \
-	(_is40 ? mcs_table[_mcs].phy_rate_40_sgi : mcs_table[_mcs].phy_rate_20_sgi) : \
-	(_is40 ? mcs_table[_mcs].phy_rate_40 : mcs_table[_mcs].phy_rate_20))
-#define VALID_MCS(_mcs)	((_mcs < MCS_TABLE_SIZE))
-
-#define	WLC_RATE_FLAG	0x80	/* Rate flag: basic or ofdm */
-
-/* Macros to use the rate_info table */
-#define	RATE_MASK	0x7f	/* Rate value mask w/o basic rate flag */
-#define	RATE_MASK_FULL	0xff	/* Rate value mask with basic rate flag */
-
-#define WLC_RATE_500K_TO_BPS(rate)	((rate) * 500000)	/* convert 500kbps to bps */
-
-/* rate spec : holds rate and mode specific information required to generate a tx frame. */
-/* Legacy CCK and OFDM information is held in the same manner as was done in the past    */
-/* (in the lower byte) the upper 3 bytes primarily hold MIMO specific information        */
-typedef u32 ratespec_t;
-
-/* rate spec bit fields */
-#define RSPEC_RATE_MASK		0x0000007F	/* Either 500Kbps units or MIMO MCS idx */
-#define RSPEC_MIMORATE		0x08000000	/* mimo MCS is stored in RSPEC_RATE_MASK */
-#define RSPEC_BW_MASK		0x00000700	/* mimo bw mask */
-#define RSPEC_BW_SHIFT		8	/* mimo bw shift */
-#define RSPEC_STF_MASK		0x00003800	/* mimo Space/Time/Frequency mode mask */
-#define RSPEC_STF_SHIFT		11	/* mimo Space/Time/Frequency mode shift */
-#define RSPEC_CT_MASK		0x0000C000	/* mimo coding type mask */
-#define RSPEC_CT_SHIFT		14	/* mimo coding type shift */
-#define RSPEC_STC_MASK		0x00300000	/* mimo num STC streams per PLCP defn. */
-#define RSPEC_STC_SHIFT		20	/* mimo num STC streams per PLCP defn. */
-#define RSPEC_LDPC_CODING	0x00400000	/* mimo bit indicates adv coding in use */
-#define RSPEC_SHORT_GI		0x00800000	/* mimo bit indicates short GI in use */
-#define RSPEC_OVERRIDE		0x80000000	/* bit indicates override both rate & mode */
-#define RSPEC_OVERRIDE_MCS_ONLY 0x40000000	/* bit indicates override rate only */
-
-#define WLC_HTPHY		127	/* HT PHY Membership */
-
-#define RSPEC_ACTIVE(rspec)	(rspec & (RSPEC_RATE_MASK | RSPEC_MIMORATE))
-#define RSPEC2RATE(rspec)      	((rspec & RSPEC_MIMORATE) ? \
-	MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec)) : \
-	(rspec & RSPEC_RATE_MASK))
-/* return rate in unit of 500Kbps -- for internal use in wlc_rate_sel.c */
-#define RSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
-		MCS_RATE((rspec & RSPEC_RATE_MASK), state->is40bw, RSPEC_ISSGI(rspec))/500 : \
-		(rspec & RSPEC_RATE_MASK))
-#define CRSPEC2RATE500K(rspec)	((rspec & RSPEC_MIMORATE) ? \
-		MCS_RATE((rspec & RSPEC_RATE_MASK), RSPEC_IS40MHZ(rspec), RSPEC_ISSGI(rspec))/500 :\
-		(rspec & RSPEC_RATE_MASK))
-
-#define RSPEC2KBPS(rspec)	(IS_MCS(rspec) ? RSPEC2RATE(rspec) : RSPEC2RATE(rspec)*500)
-#define RSPEC_PHYTXBYTE2(rspec)	((rspec & 0xff00) >> 8)
-#define RSPEC_GET_BW(rspec)	((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT)
-#define RSPEC_IS40MHZ(rspec)	((((rspec & RSPEC_BW_MASK) >> RSPEC_BW_SHIFT) == \
-				PHY_TXC1_BW_40MHZ) || (((rspec & RSPEC_BW_MASK) >> \
-				RSPEC_BW_SHIFT) == PHY_TXC1_BW_40MHZ_DUP))
-#define RSPEC_ISSGI(rspec)	((rspec & RSPEC_SHORT_GI) == RSPEC_SHORT_GI)
-#define RSPEC_MIMOPLCP3(rspec)	((rspec & 0xf00000) >> 16)
-#define PLCP3_ISSGI(plcp)	(plcp & (RSPEC_SHORT_GI >> 16))
-#define RSPEC_STC(rspec)	((rspec & RSPEC_STC_MASK) >> RSPEC_STC_SHIFT)
-#define RSPEC_STF(rspec)	((rspec & RSPEC_STF_MASK) >> RSPEC_STF_SHIFT)
-#define PLCP3_ISSTBC(plcp)	((plcp & (RSPEC_STC_MASK) >> 16) == 0x10)
-#define PLCP3_STC_MASK          0x30
-#define PLCP3_STC_SHIFT         4
-
-/* Rate info table; takes a legacy rate or ratespec_t */
-#define	IS_MCS(r)     	(r & RSPEC_MIMORATE)
-#define	IS_OFDM(r)     	(!IS_MCS(r) && (rate_info[(r) & RSPEC_RATE_MASK] & WLC_RATE_FLAG))
-#define	IS_CCK(r)	(!IS_MCS(r) && (((r) & RATE_MASK) == WLC_RATE_1M || \
-			 ((r) & RATE_MASK) == WLC_RATE_2M || \
-			 ((r) & RATE_MASK) == WLC_RATE_5M5 || ((r) & RATE_MASK) == WLC_RATE_11M))
-#define IS_SINGLE_STREAM(mcs)	(((mcs) <= HIGHEST_SINGLE_STREAM_MCS) || ((mcs) == 32))
-#define CCK_RSPEC(cck)		((cck) & RSPEC_RATE_MASK)
-#define OFDM_RSPEC(ofdm)	(((ofdm) & RSPEC_RATE_MASK) |\
-	(PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT))
-#define LEGACY_RSPEC(rate)	(IS_CCK(rate) ? CCK_RSPEC(rate) : OFDM_RSPEC(rate))
-
-#define MCS_RSPEC(mcs)		(((mcs) & RSPEC_RATE_MASK) | RSPEC_MIMORATE | \
-	(IS_SINGLE_STREAM(mcs) ? (PHY_TXC1_MODE_CDD << RSPEC_STF_SHIFT) : \
-	(PHY_TXC1_MODE_SDM << RSPEC_STF_SHIFT)))
-
-/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */
-extern const u8 ofdm_rate_lookup[];
-#define OFDM_PHY2MAC_RATE(rlpt)		(ofdm_rate_lookup[rlpt & 0x7])
-#define CCK_PHY2MAC_RATE(signal)	(signal/5)
-
-/* Rates specified in wlc_rateset_filter() */
-#define WLC_RATES_CCK_OFDM	0
-#define WLC_RATES_CCK		1
-#define WLC_RATES_OFDM		2
-
-/* use the stuct form instead of typedef to fix dependency problems */
-struct wlc_rateset;
-
-/* sanitize, and sort a rateset with the basic bit(s) preserved, validate rateset */
-extern bool wlc_rate_hwrs_filter_sort_validate(struct wlc_rateset *rs,
-					       const struct wlc_rateset *hw_rs,
-					       bool check_brate,
-					       u8 txstreams);
-/* copy rateset src to dst as-is (no masking or sorting) */
-extern void wlc_rateset_copy(const struct wlc_rateset *src,
-			     struct wlc_rateset *dst);
-
-/* would be nice to have these documented ... */
-extern ratespec_t wlc_compute_rspec(d11rxhdr_t *rxh, u8 *plcp);
-
-extern void wlc_rateset_filter(struct wlc_rateset *src, struct wlc_rateset *dst,
-			       bool basic_only, u8 rates, uint xmask,
-			       bool mcsallow);
-extern void wlc_rateset_default(struct wlc_rateset *rs_tgt,
-				const struct wlc_rateset *rs_hw, uint phy_type,
-				int bandtype, bool cck_only, uint rate_mask,
-				bool mcsallow, u8 bw, u8 txstreams);
-extern s16 wlc_rate_legacy_phyctl(uint rate);
-
-extern void wlc_rateset_mcs_upd(struct wlc_rateset *rs, u8 txstreams);
-extern void wlc_rateset_mcs_clear(struct wlc_rateset *rateset);
-extern void wlc_rateset_mcs_build(struct wlc_rateset *rateset, u8 txstreams);
-extern void wlc_rateset_bw_mcs_filter(struct wlc_rateset *rateset, u8 bw);
-
-#endif				/* _WLC_RATE_H_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_scb.h b/drivers/staging/brcm80211/sys/wlc_scb.h
deleted file mode 100644
index fe84e99..0000000
--- a/drivers/staging/brcm80211/sys/wlc_scb.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_scb_h_
-#define _wlc_scb_h_
-
-#include <proto/802.1d.h>
-
-extern bool wlc_aggregatable(struct wlc_info *wlc, u8 tid);
-
-#define AMPDU_TX_BA_MAX_WSIZE	64	/* max Tx ba window size (in pdu) */
-/* structure to store per-tid state for the ampdu initiator */
-typedef struct scb_ampdu_tid_ini {
-	u32 magic;
-	u8 tx_in_transit;	/* number of pending mpdus in transit in driver */
-	u8 tid;		/* initiator tid for easy lookup */
-	u8 txretry[AMPDU_TX_BA_MAX_WSIZE];	/* tx retry count; indexed by seq modulo */
-	struct scb *scb;	/* backptr for easy lookup */
-} scb_ampdu_tid_ini_t;
-
-#define AMPDU_MAX_SCB_TID	NUMPRIO
-
-typedef struct scb_ampdu {
-	struct scb *scb;	/* back pointer for easy reference */
-	u8 mpdu_density;	/* mpdu density */
-	u8 max_pdu;		/* max pdus allowed in ampdu */
-	u8 release;		/* # of mpdus released at a time */
-	u16 min_len;		/* min mpdu len to support the density */
-	u32 max_rxlen;	/* max ampdu rcv length; 8k, 16k, 32k, 64k */
-	struct pktq txq;	/* sdu transmit queue pending aggregation */
-
-	/* This could easily be a ini[] pointer and we keep this info in wl itself instead
-	 * of having mac80211 hold it for us.  Also could be made dynamic per tid instead of
-	 * static.
-	 */
-	scb_ampdu_tid_ini_t ini[AMPDU_MAX_SCB_TID];	/* initiator info - per tid (NUMPRIO) */
-} scb_ampdu_t;
-
-#define SCB_MAGIC 	0xbeefcafe
-#define INI_MAGIC 	0xabcd1234
-
-/* station control block - one per remote MAC address */
-struct scb {
-	u32 magic;
-	u32 flags;		/* various bit flags as defined below */
-	u32 flags2;		/* various bit flags2 as defined below */
-	u8 state;		/* current state bitfield of auth/assoc process */
-	struct ether_addr ea;	/* station address */
-	void *fragbuf[NUMPRIO];	/* defragmentation buffer per prio */
-	uint fragresid[NUMPRIO];	/* #bytes unused in frag buffer per prio */
-
-	u16 seqctl[NUMPRIO];	/* seqctl of last received frame (for dups) */
-	u16 seqctl_nonqos;	/* seqctl of last received frame (for dups) for
-				 * non-QoS data and management
-				 */
-	u16 seqnum[NUMPRIO];	/* WME: driver maintained sw seqnum per priority */
-
-	scb_ampdu_t scb_ampdu;	/* AMPDU state including per tid info */
-};
-
-/* scb flags */
-#define SCB_WMECAP		0x0040	/* may ONLY be set if WME_ENAB(wlc) */
-#define SCB_HTCAP		0x10000	/* HT (MIMO) capable device */
-#define SCB_IS40		0x80000	/* 40MHz capable */
-#define SCB_STBCCAP		0x40000000	/* STBC Capable */
-#define SCB_WME(a)		((a)->flags & SCB_WMECAP)/* implies WME_ENAB */
-#define SCB_SEQNUM(scb, prio)	((scb)->seqnum[(prio)])
-#define SCB_PS(a)		NULL
-#define SCB_STBC_CAP(a)		((a)->flags & SCB_STBCCAP)
-#define SCB_AMPDU(a)		true
-#endif				/* _wlc_scb_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_stf.c b/drivers/staging/brcm80211/sys/wlc_stf.c
deleted file mode 100644
index 8975b09..0000000
--- a/drivers/staging/brcm80211/sys/wlc_stf.c
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <wlc_cfg.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <siutils.h>
-#include <bcmendian.h>
-#include <proto/802.11.h>
-#include <wlioctl.h>
-#include <bcmwifi.h>
-#include <sbhndpio.h>
-#include <sbhnddma.h>
-#include <d11.h>
-#include <wlc_rate.h>
-#include <wlc_pub.h>
-#include <wlc_key.h>
-#include <wlc_channel.h>
-#include <wlc_bsscfg.h>
-#include <wlc_event.h>
-#include <wlc_mac80211.h>
-#include <wlc_scb.h>
-#include <wl_export.h>
-#include <wlc_bmac.h>
-#include <wlc_stf.h>
-#include <wl_dbg.h>
-
-#define WLC_STF_SS_STBC_RX(wlc) (WLCISNPHY(wlc->band) && \
-	NREV_GT(wlc->band->phyrev, 3) && NREV_LE(wlc->band->phyrev, 6))
-
-static s8 wlc_stf_stbc_rx_get(struct wlc_info *wlc);
-static bool wlc_stf_stbc_tx_set(struct wlc_info *wlc, s32 int_val);
-static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 val);
-static int wlc_stf_spatial_policy_set(struct wlc_info *wlc, int val);
-static void wlc_stf_stbc_rx_ht_update(struct wlc_info *wlc, int val);
-
-static void _wlc_stf_phy_txant_upd(struct wlc_info *wlc);
-static u16 _wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec);
-
-#define NSTS_1	1
-#define NSTS_2	2
-#define NSTS_3	3
-#define NSTS_4	4
-const u8 txcore_default[5] = {
-	(0),			/* bitmap of the core enabled */
-	(0x01),			/* For Nsts = 1, enable core 1 */
-	(0x03),			/* For Nsts = 2, enable core 1 & 2 */
-	(0x07),			/* For Nsts = 3, enable core 1, 2 & 3 */
-	(0x0f)			/* For Nsts = 4, enable all cores */
-};
-
-static void wlc_stf_stbc_rx_ht_update(struct wlc_info *wlc, int val)
-{
-	ASSERT((val == HT_CAP_RX_STBC_NO)
-	       || (val == HT_CAP_RX_STBC_ONE_STREAM));
-
-	/* MIMOPHYs rev3-6 cannot receive STBC with only one rx core active */
-	if (WLC_STF_SS_STBC_RX(wlc)) {
-		if ((wlc->stf->rxstreams == 1) && (val != HT_CAP_RX_STBC_NO))
-			return;
-	}
-
-	wlc->ht_cap.cap &= ~HT_CAP_RX_STBC_MASK;
-	wlc->ht_cap.cap |= (val << HT_CAP_RX_STBC_SHIFT);
-
-	if (wlc->pub->up) {
-		wlc_update_beacon(wlc);
-		wlc_update_probe_resp(wlc, true);
-	}
-}
-
-/* every WLC_TEMPSENSE_PERIOD seconds temperature check to decide whether to turn on/off txchain */
-void wlc_tempsense_upd(struct wlc_info *wlc)
-{
-	wlc_phy_t *pi = wlc->band->pi;
-	uint active_chains, txchain;
-
-	/* Check if the chip is too hot. Disable one Tx chain, if it is */
-	/* high 4 bits are for Rx chain, low 4 bits are  for Tx chain */
-	active_chains = wlc_phy_stf_chain_active_get(pi);
-	txchain = active_chains & 0xf;
-
-	if (wlc->stf->txchain == wlc->stf->hw_txchain) {
-		if (txchain && (txchain < wlc->stf->hw_txchain)) {
-			/* turn off 1 tx chain */
-			wlc_stf_txchain_set(wlc, txchain, true);
-		}
-	} else if (wlc->stf->txchain < wlc->stf->hw_txchain) {
-		if (txchain == wlc->stf->hw_txchain) {
-			/* turn back on txchain */
-			wlc_stf_txchain_set(wlc, txchain, true);
-		}
-	}
-}
-
-void
-wlc_stf_ss_algo_channel_get(struct wlc_info *wlc, u16 *ss_algo_channel,
-			    chanspec_t chanspec)
-{
-	tx_power_t power;
-	u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id;
-
-	/* Clear previous settings */
-	*ss_algo_channel = 0;
-
-	if (!wlc->pub->up) {
-		*ss_algo_channel = (u16) -1;
-		return;
-	}
-
-	wlc_phy_txpower_get_current(wlc->band->pi, &power,
-				    CHSPEC_CHANNEL(chanspec));
-
-	siso_mcs_id = (CHSPEC_IS40(chanspec)) ?
-	    WL_TX_POWER_MCS40_SISO_FIRST : WL_TX_POWER_MCS20_SISO_FIRST;
-	cdd_mcs_id = (CHSPEC_IS40(chanspec)) ?
-	    WL_TX_POWER_MCS40_CDD_FIRST : WL_TX_POWER_MCS20_CDD_FIRST;
-	stbc_mcs_id = (CHSPEC_IS40(chanspec)) ?
-	    WL_TX_POWER_MCS40_STBC_FIRST : WL_TX_POWER_MCS20_STBC_FIRST;
-
-	/* criteria to choose stf mode */
-
-	/* the "+3dbm (12 0.25db units)" is to account for the fact that with CDD, tx occurs
-	 * on both chains
-	 */
-	if (power.target[siso_mcs_id] > (power.target[cdd_mcs_id] + 12))
-		setbit(ss_algo_channel, PHY_TXC1_MODE_SISO);
-	else
-		setbit(ss_algo_channel, PHY_TXC1_MODE_CDD);
-
-	/* STBC is ORed into to algo channel as STBC requires per-packet SCB capability check
-	 * so cannot be default mode of operation. One of SISO, CDD have to be set
-	 */
-	if (power.target[siso_mcs_id] <= (power.target[stbc_mcs_id] + 12))
-		setbit(ss_algo_channel, PHY_TXC1_MODE_STBC);
-}
-
-static s8 wlc_stf_stbc_rx_get(struct wlc_info *wlc)
-{
-	return (wlc->ht_cap.cap & HT_CAP_RX_STBC_MASK) >> HT_CAP_RX_STBC_SHIFT;
-}
-
-static bool wlc_stf_stbc_tx_set(struct wlc_info *wlc, s32 int_val)
-{
-	if ((int_val != AUTO) && (int_val != OFF) && (int_val != ON)) {
-		return false;
-	}
-
-	if ((int_val == ON) && (wlc->stf->txstreams == 1))
-		return false;
-
-	if ((int_val == OFF) || (wlc->stf->txstreams == 1)
-	    || !WLC_STBC_CAP_PHY(wlc))
-		wlc->ht_cap.cap &= ~HT_CAP_TX_STBC;
-	else
-		wlc->ht_cap.cap |= HT_CAP_TX_STBC;
-
-	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = (s8) int_val;
-	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = (s8) int_val;
-
-	return true;
-}
-
-bool wlc_stf_stbc_rx_set(struct wlc_info *wlc, s32 int_val)
-{
-	if ((int_val != HT_CAP_RX_STBC_NO)
-	    && (int_val != HT_CAP_RX_STBC_ONE_STREAM)) {
-		return false;
-	}
-
-	if (WLC_STF_SS_STBC_RX(wlc)) {
-		if ((int_val != HT_CAP_RX_STBC_NO)
-		    && (wlc->stf->rxstreams == 1))
-			return false;
-	}
-
-	wlc_stf_stbc_rx_ht_update(wlc, int_val);
-	return true;
-}
-
-static int wlc_stf_txcore_set(struct wlc_info *wlc, u8 Nsts, u8 core_mask)
-{
-	WL_TRACE("wl%d: %s: Nsts %d core_mask %x\n",
-		 wlc->pub->unit, __func__, Nsts, core_mask);
-
-	ASSERT((Nsts > 0) && (Nsts <= MAX_STREAMS_SUPPORTED));
-
-	if (WLC_BITSCNT(core_mask) > wlc->stf->txstreams) {
-		core_mask = 0;
-	}
-
-	if ((WLC_BITSCNT(core_mask) == wlc->stf->txstreams) &&
-	    ((core_mask & ~wlc->stf->txchain)
-	     || !(core_mask & wlc->stf->txchain))) {
-		core_mask = wlc->stf->txchain;
-	}
-
-	ASSERT(!core_mask || Nsts <= WLC_BITSCNT(core_mask));
-
-	wlc->stf->txcore[Nsts] = core_mask;
-	/* Nsts = 1..4, txcore index = 1..4 */
-	if (Nsts == 1) {
-		/* Needs to update beacon and ucode generated response
-		 * frames when 1 stream core map changed
-		 */
-		wlc->stf->phytxant = core_mask << PHY_TXC_ANT_SHIFT;
-		wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant);
-		if (wlc->clk) {
-			wlc_suspend_mac_and_wait(wlc);
-			wlc_beacon_phytxctl_txant_upd(wlc, wlc->bcn_rspec);
-			wlc_enable_mac(wlc);
-		}
-	}
-
-	return BCME_OK;
-}
-
-static int wlc_stf_spatial_policy_set(struct wlc_info *wlc, int val)
-{
-	int i;
-	u8 core_mask = 0;
-
-	WL_TRACE("wl%d: %s: val %x\n", wlc->pub->unit, __func__, val);
-
-	wlc->stf->spatial_policy = (s8) val;
-	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++) {
-		core_mask = (val == MAX_SPATIAL_EXPANSION) ?
-		    wlc->stf->txchain : txcore_default[i];
-		wlc_stf_txcore_set(wlc, (u8) i, core_mask);
-	}
-	return BCME_OK;
-}
-
-int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force)
-{
-	u8 txchain = (u8) int_val;
-	u8 txstreams;
-	uint i;
-
-	if (wlc->stf->txchain == txchain)
-		return BCME_OK;
-
-	if ((txchain & ~wlc->stf->hw_txchain)
-	    || !(txchain & wlc->stf->hw_txchain))
-		return BCME_RANGE;
-
-	/* if nrate override is configured to be non-SISO STF mode, reject reducing txchain to 1 */
-	txstreams = (u8) WLC_BITSCNT(txchain);
-	if (txstreams > MAX_STREAMS_SUPPORTED)
-		return BCME_RANGE;
-
-	if (txstreams == 1) {
-		for (i = 0; i < NBANDS(wlc); i++)
-			if ((RSPEC_STF(wlc->bandstate[i]->rspec_override) !=
-			     PHY_TXC1_MODE_SISO)
-			    || (RSPEC_STF(wlc->bandstate[i]->mrspec_override) !=
-				PHY_TXC1_MODE_SISO)) {
-				if (!force)
-					return BCME_ERROR;
-
-				/* over-write the override rspec */
-				if (RSPEC_STF(wlc->bandstate[i]->rspec_override)
-				    != PHY_TXC1_MODE_SISO) {
-					wlc->bandstate[i]->rspec_override = 0;
-					WL_ERROR("%s(): temp sense override non-SISO rspec_override\n",
-						 __func__);
-				}
-				if (RSPEC_STF
-				    (wlc->bandstate[i]->mrspec_override) !=
-				    PHY_TXC1_MODE_SISO) {
-					wlc->bandstate[i]->mrspec_override = 0;
-					WL_ERROR("%s(): temp sense override non-SISO mrspec_override\n",
-						 __func__);
-				}
-			}
-	}
-
-	wlc->stf->txchain = txchain;
-	wlc->stf->txstreams = txstreams;
-	wlc_stf_stbc_tx_set(wlc, wlc->band->band_stf_stbc_tx);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
-	wlc->stf->txant =
-	    (wlc->stf->txstreams == 1) ? ANT_TX_FORCE_0 : ANT_TX_DEF;
-	_wlc_stf_phy_txant_upd(wlc);
-
-	wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
-			      wlc->stf->rxchain);
-
-	for (i = 1; i <= MAX_STREAMS_SUPPORTED; i++)
-		wlc_stf_txcore_set(wlc, (u8) i, txcore_default[i]);
-
-	return BCME_OK;
-}
-
-int wlc_stf_rxchain_set(struct wlc_info *wlc, s32 int_val)
-{
-	u8 rxchain_cnt;
-	u8 rxchain = (u8) int_val;
-	u8 mimops_mode;
-	u8 old_rxchain, old_rxchain_cnt;
-
-	if (wlc->stf->rxchain == rxchain)
-		return BCME_OK;
-
-	if ((rxchain & ~wlc->stf->hw_rxchain)
-	    || !(rxchain & wlc->stf->hw_rxchain))
-		return BCME_RANGE;
-
-	rxchain_cnt = (u8) WLC_BITSCNT(rxchain);
-	if (WLC_STF_SS_STBC_RX(wlc)) {
-		if ((rxchain_cnt == 1)
-		    && (wlc_stf_stbc_rx_get(wlc) != HT_CAP_RX_STBC_NO))
-			return BCME_RANGE;
-	}
-
-	if (APSTA_ENAB(wlc->pub) && (wlc->pub->associated))
-		return BCME_ASSOCIATED;
-
-	old_rxchain = wlc->stf->rxchain;
-	old_rxchain_cnt = wlc->stf->rxstreams;
-
-	wlc->stf->rxchain = rxchain;
-	wlc->stf->rxstreams = rxchain_cnt;
-
-	if (rxchain_cnt != old_rxchain_cnt) {
-		mimops_mode =
-		    (rxchain_cnt == 1) ? HT_CAP_MIMO_PS_ON : HT_CAP_MIMO_PS_OFF;
-		wlc->mimops_PM = mimops_mode;
-		if (AP_ENAB(wlc->pub)) {
-			wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
-					      wlc->stf->rxchain);
-			wlc_ht_mimops_cap_update(wlc, mimops_mode);
-			if (wlc->pub->associated)
-				wlc_mimops_action_ht_send(wlc, wlc->cfg,
-							  mimops_mode);
-			return BCME_OK;
-		}
-		if (wlc->pub->associated) {
-			if (mimops_mode == HT_CAP_MIMO_PS_OFF) {
-				/* if mimops is off, turn on the Rx chain first */
-				wlc_phy_stf_chain_set(wlc->band->pi,
-						      wlc->stf->txchain,
-						      wlc->stf->rxchain);
-				wlc_ht_mimops_cap_update(wlc, mimops_mode);
-			}
-		} else {
-			wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
-					      wlc->stf->rxchain);
-			wlc_ht_mimops_cap_update(wlc, mimops_mode);
-		}
-	} else if (old_rxchain != rxchain)
-		wlc_phy_stf_chain_set(wlc->band->pi, wlc->stf->txchain,
-				      wlc->stf->rxchain);
-
-	return BCME_OK;
-}
-
-/* update wlc->stf->ss_opmode which represents the operational stf_ss mode we're using */
-int wlc_stf_ss_update(struct wlc_info *wlc, struct wlcband *band)
-{
-	int ret_code = 0;
-	u8 prev_stf_ss;
-	u8 upd_stf_ss;
-
-	prev_stf_ss = wlc->stf->ss_opmode;
-
-	/* NOTE: opmode can only be SISO or CDD as STBC is decided on a per-packet basis */
-	if (WLC_STBC_CAP_PHY(wlc) &&
-	    wlc->stf->ss_algosel_auto
-	    && (wlc->stf->ss_algo_channel != (u16) -1)) {
-		ASSERT(isset(&wlc->stf->ss_algo_channel, PHY_TXC1_MODE_CDD)
-		       || isset(&wlc->stf->ss_algo_channel,
-				PHY_TXC1_MODE_SISO));
-		upd_stf_ss = (wlc->stf->no_cddstbc || (wlc->stf->txstreams == 1)
-			      || isset(&wlc->stf->ss_algo_channel,
-				       PHY_TXC1_MODE_SISO)) ? PHY_TXC1_MODE_SISO
-		    : PHY_TXC1_MODE_CDD;
-	} else {
-		if (wlc->band != band)
-			return ret_code;
-		upd_stf_ss = (wlc->stf->no_cddstbc
-			      || (wlc->stf->txstreams ==
-				  1)) ? PHY_TXC1_MODE_SISO : band->
-		    band_stf_ss_mode;
-	}
-	if (prev_stf_ss != upd_stf_ss) {
-		wlc->stf->ss_opmode = upd_stf_ss;
-		wlc_bmac_band_stf_ss_set(wlc->hw, upd_stf_ss);
-	}
-
-	return ret_code;
-}
-
-int wlc_stf_attach(struct wlc_info *wlc)
-{
-	wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_SISO;
-	wlc->bandstate[BAND_5G_INDEX]->band_stf_ss_mode = PHY_TXC1_MODE_CDD;
-
-	if (WLCISNPHY(wlc->band) &&
-	    (wlc_phy_txpower_hw_ctrl_get(wlc->band->pi) != PHY_TPC_HW_ON))
-		wlc->bandstate[BAND_2G_INDEX]->band_stf_ss_mode =
-		    PHY_TXC1_MODE_CDD;
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_2G_INDEX]);
-	wlc_stf_ss_update(wlc, wlc->bandstate[BAND_5G_INDEX]);
-
-	wlc_stf_stbc_rx_ht_update(wlc, HT_CAP_RX_STBC_NO);
-	wlc->bandstate[BAND_2G_INDEX]->band_stf_stbc_tx = OFF;
-	wlc->bandstate[BAND_5G_INDEX]->band_stf_stbc_tx = OFF;
-
-	if (WLC_STBC_CAP_PHY(wlc)) {
-		wlc->stf->ss_algosel_auto = true;
-		wlc->stf->ss_algo_channel = (u16) -1;	/* Init the default value */
-	}
-	return 0;
-}
-
-void wlc_stf_detach(struct wlc_info *wlc)
-{
-}
-
-int wlc_stf_ant_txant_validate(struct wlc_info *wlc, s8 val)
-{
-	int bcmerror = BCME_OK;
-
-	/* when there is only 1 tx_streams, don't allow to change the txant */
-	if (WLCISNPHY(wlc->band) && (wlc->stf->txstreams == 1))
-		return ((val == wlc->stf->txant) ? bcmerror : BCME_RANGE);
-
-	switch (val) {
-	case -1:
-		val = ANT_TX_DEF;
-		break;
-	case 0:
-		val = ANT_TX_FORCE_0;
-		break;
-	case 1:
-		val = ANT_TX_FORCE_1;
-		break;
-	case 3:
-		val = ANT_TX_LAST_RX;
-		break;
-	default:
-		bcmerror = BCME_RANGE;
-		break;
-	}
-
-	if (bcmerror == BCME_OK)
-		wlc->stf->txant = (s8) val;
-
-	return bcmerror;
-
-}
-
-/*
- * Centralized txant update function. call it whenever wlc->stf->txant and/or wlc->stf->txchain
- *  change
- *
- * Antennas are controlled by ucode indirectly, which drives PHY or GPIO to
- *   achieve various tx/rx antenna selection schemes
- *
- * legacy phy, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means auto(last rx)
- * for NREV<3, bit 6 and bit 7 means antenna 0 and 1 respectively, bit6+bit7 means last rx and
- *    do tx-antenna selection for SISO transmissions
- * for NREV=3, bit 6 and bit _8_ means antenna 0 and 1 respectively, bit6+bit7 means last rx and
- *    do tx-antenna selection for SISO transmissions
- * for NREV>=7, bit 6 and bit 7 mean antenna 0 and 1 respectively, nit6+bit7 means both cores active
-*/
-static void _wlc_stf_phy_txant_upd(struct wlc_info *wlc)
-{
-	s8 txant;
-
-	txant = (s8) wlc->stf->txant;
-	ASSERT(txant == ANT_TX_FORCE_0 || txant == ANT_TX_FORCE_1
-	       || txant == ANT_TX_LAST_RX);
-
-	if (WLC_PHY_11N_CAP(wlc->band)) {
-		if (txant == ANT_TX_FORCE_0) {
-			wlc->stf->phytxant = PHY_TXC_ANT_0;
-		} else if (txant == ANT_TX_FORCE_1) {
-			wlc->stf->phytxant = PHY_TXC_ANT_1;
-
-			if (WLCISNPHY(wlc->band) &&
-			    NREV_GE(wlc->band->phyrev, 3)
-			    && NREV_LT(wlc->band->phyrev, 7)) {
-				wlc->stf->phytxant = PHY_TXC_ANT_2;
-			}
-		} else {
-			if (WLCISLCNPHY(wlc->band) || WLCISSSLPNPHY(wlc->band))
-				wlc->stf->phytxant = PHY_TXC_LCNPHY_ANT_LAST;
-			else {
-				/* keep this assert to catch out of sync wlc->stf->txcore */
-				ASSERT(wlc->stf->txchain > 0);
-				wlc->stf->phytxant =
-				    wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
-			}
-		}
-	} else {
-		if (txant == ANT_TX_FORCE_0)
-			wlc->stf->phytxant = PHY_TXC_OLD_ANT_0;
-		else if (txant == ANT_TX_FORCE_1)
-			wlc->stf->phytxant = PHY_TXC_OLD_ANT_1;
-		else
-			wlc->stf->phytxant = PHY_TXC_OLD_ANT_LAST;
-	}
-
-	wlc_bmac_txant_set(wlc->hw, wlc->stf->phytxant);
-}
-
-void wlc_stf_phy_txant_upd(struct wlc_info *wlc)
-{
-	_wlc_stf_phy_txant_upd(wlc);
-}
-
-void wlc_stf_phy_chain_calc(struct wlc_info *wlc)
-{
-	/* get available rx/tx chains */
-	wlc->stf->hw_txchain = (u8) getintvar(wlc->pub->vars, "txchain");
-	wlc->stf->hw_rxchain = (u8) getintvar(wlc->pub->vars, "rxchain");
-
-	/* these parameter are intended to be used for all PHY types */
-	if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) {
-		if (WLCISNPHY(wlc->band)) {
-			wlc->stf->hw_txchain = TXCHAIN_DEF_NPHY;
-		} else {
-			wlc->stf->hw_txchain = TXCHAIN_DEF;
-		}
-	}
-
-	wlc->stf->txchain = wlc->stf->hw_txchain;
-	wlc->stf->txstreams = (u8) WLC_BITSCNT(wlc->stf->hw_txchain);
-
-	if (wlc->stf->hw_rxchain == 0 || wlc->stf->hw_rxchain == 0xf) {
-		if (WLCISNPHY(wlc->band)) {
-			wlc->stf->hw_rxchain = RXCHAIN_DEF_NPHY;
-		} else {
-			wlc->stf->hw_rxchain = RXCHAIN_DEF;
-		}
-	}
-
-	wlc->stf->rxchain = wlc->stf->hw_rxchain;
-	wlc->stf->rxstreams = (u8) WLC_BITSCNT(wlc->stf->hw_rxchain);
-
-	/* initialize the txcore table */
-	bcopy(txcore_default, wlc->stf->txcore, sizeof(wlc->stf->txcore));
-
-	/* default spatial_policy */
-	wlc->stf->spatial_policy = MIN_SPATIAL_EXPANSION;
-	wlc_stf_spatial_policy_set(wlc, MIN_SPATIAL_EXPANSION);
-}
-
-static u16 _wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec)
-{
-	u16 phytxant = wlc->stf->phytxant;
-
-	if (RSPEC_STF(rspec) != PHY_TXC1_MODE_SISO) {
-		ASSERT(wlc->stf->txstreams > 1);
-		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
-	} else if (wlc->stf->txant == ANT_TX_DEF)
-		phytxant = wlc->stf->txchain << PHY_TXC_ANT_SHIFT;
-	phytxant &= PHY_TXC_ANT_MASK;
-	return phytxant;
-}
-
-u16 wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec)
-{
-	return _wlc_stf_phytxchain_sel(wlc, rspec);
-}
-
-u16 wlc_stf_d11hdrs_phyctl_txant(struct wlc_info *wlc, ratespec_t rspec)
-{
-	u16 phytxant = wlc->stf->phytxant;
-	u16 mask = PHY_TXC_ANT_MASK;
-
-	/* for non-siso rates or default setting, use the available chains */
-	if (WLCISNPHY(wlc->band)) {
-		ASSERT(wlc->stf->txchain != 0);
-		phytxant = _wlc_stf_phytxchain_sel(wlc, rspec);
-		mask = PHY_TXC_HTANT_MASK;
-	}
-	phytxant |= phytxant & mask;
-	return phytxant;
-}
diff --git a/drivers/staging/brcm80211/sys/wlc_stf.h b/drivers/staging/brcm80211/sys/wlc_stf.h
deleted file mode 100644
index 8de6382..0000000
--- a/drivers/staging/brcm80211/sys/wlc_stf.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_stf_h_
-#define _wlc_stf_h_
-
-#define MIN_SPATIAL_EXPANSION	0
-#define MAX_SPATIAL_EXPANSION	1
-
-extern int wlc_stf_attach(struct wlc_info *wlc);
-extern void wlc_stf_detach(struct wlc_info *wlc);
-
-extern void wlc_tempsense_upd(struct wlc_info *wlc);
-extern void wlc_stf_ss_algo_channel_get(struct wlc_info *wlc,
-					u16 *ss_algo_channel,
-					chanspec_t chanspec);
-extern int wlc_stf_ss_update(struct wlc_info *wlc, struct wlcband *band);
-extern void wlc_stf_phy_txant_upd(struct wlc_info *wlc);
-extern int wlc_stf_txchain_set(struct wlc_info *wlc, s32 int_val, bool force);
-extern int wlc_stf_rxchain_set(struct wlc_info *wlc, s32 int_val);
-extern bool wlc_stf_stbc_rx_set(struct wlc_info *wlc, s32 int_val);
-
-extern int wlc_stf_ant_txant_validate(struct wlc_info *wlc, s8 val);
-extern void wlc_stf_phy_txant_upd(struct wlc_info *wlc);
-extern void wlc_stf_phy_chain_calc(struct wlc_info *wlc);
-extern u16 wlc_stf_phytxchain_sel(struct wlc_info *wlc, ratespec_t rspec);
-extern u16 wlc_stf_d11hdrs_phyctl_txant(struct wlc_info *wlc, ratespec_t rspec);
-extern u16 wlc_stf_spatial_expansion_get(struct wlc_info *wlc,
-					 ratespec_t rspec);
-#endif				/* _wlc_stf_h_ */
diff --git a/drivers/staging/brcm80211/sys/wlc_types.h b/drivers/staging/brcm80211/sys/wlc_types.h
deleted file mode 100644
index df6e04c..0000000
--- a/drivers/staging/brcm80211/sys/wlc_types.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _wlc_types_h_
-#define _wlc_types_h_
-
-/* forward declarations */
-
-struct wlc_info;
-struct wlc_hw_info;
-struct wlc_if;
-struct wl_if;
-struct ampdu_info;
-struct antsel_info;
-struct bmac_pmq;
-
-struct d11init;
-
-#ifndef _hnddma_pub_
-#define _hnddma_pub_
-struct hnddma_pub;
-#endif				/* _hnddma_pub_ */
-
-#endif				/* _wlc_types_h_ */
diff --git a/drivers/staging/brcm80211/util/aiutils.c b/drivers/staging/brcm80211/util/aiutils.c
index ddd2f9d..5708690 100644
--- a/drivers/staging/brcm80211/util/aiutils.c
+++ b/drivers/staging/brcm80211/util/aiutils.c
@@ -18,10 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <bcmdefs.h>
-#ifdef BRCM_FULLMAC
-#include <linux/netdevice.h>
-#endif
-#include <osl.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <bcmutils.h>
@@ -44,7 +40,7 @@ get_erom_ent(si_t *sih, u32 **eromptr, u32 mask, u32 match)
 	uint inv = 0, nom = 0;
 
 	while (true) {
-		ent = R_REG(si_osh(sih), *eromptr);
+		ent = R_REG(*eromptr);
 		(*eromptr)++;
 
 		if (mask == 0)
@@ -118,7 +114,7 @@ void ai_scan(si_t *sih, void *regs, uint devid)
 	chipcregs_t *cc = (chipcregs_t *) regs;
 	u32 erombase, *eromptr, *eromlim;
 
-	erombase = R_REG(sii->osh, &cc->eromptr);
+	erombase = R_REG(&cc->eromptr);
 
 	switch (sih->bustype) {
 	case SI_BUS:
@@ -130,14 +126,12 @@ void ai_scan(si_t *sih, void *regs, uint devid)
 		sii->curwrap = (void *)((unsigned long)regs + SI_CORE_SIZE);
 
 		/* Now point the window at the erom */
-		pci_write_config_dword(sii->osh->pdev, PCI_BAR0_WIN, erombase);
+		pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, erombase);
 		eromptr = regs;
 		break;
 
-#ifdef BCMSDIO
 	case SPI_BUS:
 	case SDIO_BUS:
-#endif				/* BCMSDIO */
 		eromptr = (u32 *)(unsigned long)erombase;
 		break;
 
@@ -352,16 +346,14 @@ void *ai_setcoreidx(si_t *sih, uint coreidx)
 
 	case PCI_BUS:
 		/* point bar0 window */
-		pci_write_config_dword(sii->osh->pdev, PCI_BAR0_WIN, addr);
+		pci_write_config_dword(sii->pbus, PCI_BAR0_WIN, addr);
 		regs = sii->curmap;
 		/* point bar0 2nd 4KB window */
-		pci_write_config_dword(sii->osh->pdev, PCI_BAR0_WIN2, wrap);
+		pci_write_config_dword(sii->pbus, PCI_BAR0_WIN2, wrap);
 		break;
 
-#ifdef BCMSDIO
 	case SPI_BUS:
 	case SDIO_BUS:
-#endif				/* BCMSDIO */
 		sii->curmap = regs = (void *)(unsigned long)addr;
 		sii->curwrap = (void *)(unsigned long)wrap;
 		break;
@@ -434,7 +426,7 @@ uint ai_flag(si_t *sih)
 	}
 	ai = sii->curwrap;
 
-	return R_REG(sii->osh, &ai->oobselouta30) & 0x1f;
+	return R_REG(&ai->oobselouta30) & 0x1f;
 }
 
 void ai_setint(si_t *sih, int siflag)
@@ -445,7 +437,7 @@ void ai_write_wrap_reg(si_t *sih, u32 offset, u32 val)
 {
 	si_info_t *sii = SI_INFO(sih);
 	u32 *w = (u32 *) sii->curwrap;
-	W_REG(sii->osh, w + (offset / 4), val);
+	W_REG(w + (offset / 4), val);
 	return;
 }
 
@@ -477,9 +469,9 @@ bool ai_iscoreup(si_t *sih)
 	sii = SI_INFO(sih);
 	ai = sii->curwrap;
 
-	return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) ==
+	return (((R_REG(&ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) ==
 		 SICF_CLOCK_EN)
-		&& ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0));
+		&& ((R_REG(&ai->resetctrl) & AIRC_RESET) == 0));
 }
 
 /*
@@ -560,12 +552,12 @@ uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
 
 	/* mask and set */
 	if (mask || val) {
-		w = (R_REG(sii->osh, r) & ~mask) | val;
-		W_REG(sii->osh, r, w);
+		w = (R_REG(r) & ~mask) | val;
+		W_REG(r, w);
 	}
 
 	/* readback */
-	w = R_REG(sii->osh, r);
+	w = R_REG(r);
 
 	if (!fast) {
 		/* restore core index */
@@ -590,14 +582,14 @@ void ai_core_disable(si_t *sih, u32 bits)
 	ai = sii->curwrap;
 
 	/* if core is already in reset, just return */
-	if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET)
+	if (R_REG(&ai->resetctrl) & AIRC_RESET)
 		return;
 
-	W_REG(sii->osh, &ai->ioctrl, bits);
-	dummy = R_REG(sii->osh, &ai->ioctrl);
+	W_REG(&ai->ioctrl, bits);
+	dummy = R_REG(&ai->ioctrl);
 	udelay(10);
 
-	W_REG(sii->osh, &ai->resetctrl, AIRC_RESET);
+	W_REG(&ai->resetctrl, AIRC_RESET);
 	udelay(1);
 }
 
@@ -624,13 +616,13 @@ void ai_core_reset(si_t *sih, u32 bits, u32 resetbits)
 	/*
 	 * Now do the initialization sequence.
 	 */
-	W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
-	dummy = R_REG(sii->osh, &ai->ioctrl);
-	W_REG(sii->osh, &ai->resetctrl, 0);
+	W_REG(&ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN));
+	dummy = R_REG(&ai->ioctrl);
+	W_REG(&ai->resetctrl, 0);
 	udelay(1);
 
-	W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN));
-	dummy = R_REG(sii->osh, &ai->ioctrl);
+	W_REG(&ai->ioctrl, (bits | SICF_CLOCK_EN));
+	dummy = R_REG(&ai->ioctrl);
 	udelay(1);
 }
 
@@ -654,8 +646,8 @@ void ai_core_cflags_wo(si_t *sih, u32 mask, u32 val)
 	ASSERT((val & ~mask) == 0);
 
 	if (mask || val) {
-		w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
-		W_REG(sii->osh, &ai->ioctrl, w);
+		w = ((R_REG(&ai->ioctrl) & ~mask) | val);
+		W_REG(&ai->ioctrl, w);
 	}
 }
 
@@ -678,11 +670,11 @@ u32 ai_core_cflags(si_t *sih, u32 mask, u32 val)
 	ASSERT((val & ~mask) == 0);
 
 	if (mask || val) {
-		w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val);
-		W_REG(sii->osh, &ai->ioctrl, w);
+		w = ((R_REG(&ai->ioctrl) & ~mask) | val);
+		W_REG(&ai->ioctrl, w);
 	}
 
-	return R_REG(sii->osh, &ai->ioctrl);
+	return R_REG(&ai->ioctrl);
 }
 
 u32 ai_core_sflags(si_t *sih, u32 mask, u32 val)
@@ -704,10 +696,10 @@ u32 ai_core_sflags(si_t *sih, u32 mask, u32 val)
 	ASSERT((mask & ~SISF_CORE_BITS) == 0);
 
 	if (mask || val) {
-		w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val);
-		W_REG(sii->osh, &ai->iostatus, w);
+		w = ((R_REG(&ai->iostatus) & ~mask) | val);
+		W_REG(&ai->iostatus, w);
 	}
 
-	return R_REG(sii->osh, &ai->iostatus);
+	return R_REG(&ai->iostatus);
 }
 
diff --git a/drivers/staging/brcm80211/util/bcmotp.c b/drivers/staging/brcm80211/util/bcmotp.c
index d820e7b..ba71c10 100644
--- a/drivers/staging/brcm80211/util/bcmotp.c
+++ b/drivers/staging/brcm80211/util/bcmotp.c
@@ -18,13 +18,11 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <bcmdevs.h>
 #include <bcmutils.h>
 #include <siutils.h>
-#include <bcmendian.h>
 #include <hndsoc.h>
 #include <sbchipc.h>
 #include <bcmotp.h>
@@ -79,7 +77,6 @@ typedef struct {
 	uint ccrev;		/* chipc revision */
 	otp_fn_t *fn;		/* OTP functions */
 	si_t *sih;		/* Saved sb handle */
-	struct osl_info *osh;
 
 #ifdef BCMIPXOTP
 	/* IPX OTP section */
@@ -183,7 +180,7 @@ static u16 ipxotp_otpr(void *oh, chipcregs_t *cc, uint wn)
 	ASSERT(wn < oi->wsize);
 	ASSERT(cc != NULL);
 
-	return R_REG(oi->osh, &cc->sromotp[wn]);
+	return R_REG(&cc->sromotp[wn]);
 }
 
 static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
@@ -199,10 +196,10 @@ static u16 ipxotp_read_bit(void *oh, chipcregs_t *cc, uint off)
 	    ((OTPPOC_READ << OTPP_OC_SHIFT) & OTPP_OC_MASK) |
 	    ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) |
 	    ((col << OTPP_COL_SHIFT) & OTPP_COL_MASK);
-	W_REG(oi->osh, &cc->otpprog, otpp);
+	W_REG(&cc->otpprog, otpp);
 
 	for (k = 0;
-	     ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY)
+	     ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
 	     && (k < OTPP_TRIES); k++)
 		;
 	if (k >= OTPP_TRIES) {
@@ -261,9 +258,9 @@ static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
 	otpp =
 	    OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK);
 
-	W_REG(oi->osh, &cc->otpprog, otpp);
+	W_REG(&cc->otpprog, otpp);
 	for (k = 0;
-	     ((st = R_REG(oi->osh, &cc->otpprog)) & OTPP_START_BUSY)
+	     ((st = R_REG(&cc->otpprog)) & OTPP_START_BUSY)
 	     && (k < OTPP_TRIES); k++)
 		;
 	if (k >= OTPP_TRIES) {
@@ -271,7 +268,7 @@ static void _ipxotp_init(otpinfo_t *oi, chipcregs_t *cc)
 	}
 
 	/* Read OTP lock bits and subregion programmed indication bits */
-	oi->status = R_REG(oi->osh, &cc->otpstatus);
+	oi->status = R_REG(&cc->otpstatus);
 
 	if ((oi->sih->chip == BCM43224_CHIP_ID)
 	    || (oi->sih->chip == BCM43225_CHIP_ID)) {
@@ -570,56 +567,49 @@ static int hndotp_size(void *oh)
 
 static u16 hndotp_otpr(void *oh, chipcregs_t *cc, uint wn)
 {
+#ifdef BCMDBG
 	otpinfo_t *oi = (otpinfo_t *) oh;
-	struct osl_info *osh;
+#endif
 	volatile u16 *ptr;
 
 	ASSERT(wn < ((oi->size / 2) + OTP_RC_LIM_OFF));
 	ASSERT(cc != NULL);
 
-	osh = si_osh(oi->sih);
-
 	ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
-	return R_REG(osh, &ptr[wn]);
+	return R_REG(&ptr[wn]);
 }
 
 static u16 hndotp_otproff(void *oh, chipcregs_t *cc, int woff)
 {
 	otpinfo_t *oi = (otpinfo_t *) oh;
-	struct osl_info *osh;
 	volatile u16 *ptr;
 
 	ASSERT(woff >= (-((int)oi->size / 2)));
 	ASSERT(woff < OTP_LIM_OFF);
 	ASSERT(cc != NULL);
 
-	osh = si_osh(oi->sih);
-
 	ptr = (volatile u16 *)((volatile char *)cc + CC_SROM_OTP);
 
-	return R_REG(osh, &ptr[(oi->size / 2) + woff]);
+	return R_REG(&ptr[(oi->size / 2) + woff]);
 }
 
 static u16 hndotp_read_bit(void *oh, chipcregs_t *cc, uint idx)
 {
-	otpinfo_t *oi = (otpinfo_t *) oh;
 	uint k, row, col;
 	u32 otpp, st;
-	struct osl_info *osh;
 
-	osh = si_osh(oi->sih);
 	row = idx / 65;
 	col = idx % 65;
 
 	otpp = OTPP_START_BUSY | OTPP_READ |
 	    ((row << OTPP_ROW_SHIFT) & OTPP_ROW_MASK) | (col & OTPP_COL_MASK);
 
-	W_REG(osh, &cc->otpprog, otpp);
-	st = R_REG(osh, &cc->otpprog);
+	W_REG(&cc->otpprog, otpp);
+	st = R_REG(&cc->otpprog);
 	for (k = 0;
 	     ((st & OTPP_START_BUSY) == OTPP_START_BUSY) && (k < OTPP_TRIES);
 	     k++)
-		st = R_REG(osh, &cc->otpprog);
+		st = R_REG(&cc->otpprog);
 
 	if (k >= OTPP_TRIES) {
 		return 0xffff;
@@ -638,17 +628,15 @@ static void *hndotp_init(si_t *sih)
 	otpinfo_t *oi;
 	u32 cap = 0, clkdiv, otpdiv = 0;
 	void *ret = NULL;
-	struct osl_info *osh;
 
 	oi = &otpinfo;
 
 	idx = si_coreidx(sih);
-	osh = si_osh(oi->sih);
 
 	/* Check for otp */
 	cc = si_setcoreidx(sih, SI_CC_IDX);
 	if (cc != NULL) {
-		cap = R_REG(osh, &cc->capabilities);
+		cap = R_REG(&cc->capabilities);
 		if ((cap & CC_CAP_OTPSIZE) == 0) {
 			/* Nothing there */
 			goto out;
@@ -671,7 +659,7 @@ static void *hndotp_init(si_t *sih)
 		if (oi->ccrev >= 18)
 			oi->size -= ((OTP_RC0_OFF - OTP_BOUNDARY_OFF) * 2);
 
-		oi->hwprot = (int)(R_REG(osh, &cc->otpstatus) & OTPS_PROTECT);
+		oi->hwprot = (int)(R_REG(&cc->otpstatus) & OTPS_PROTECT);
 		oi->boundary = -1;
 
 		/* Check the region signature */
@@ -691,10 +679,10 @@ static void *hndotp_init(si_t *sih)
 			otpdiv = 12;
 
 		if (otpdiv) {
-			clkdiv = R_REG(osh, &cc->clkdiv);
+			clkdiv = R_REG(&cc->clkdiv);
 			clkdiv =
 			    (clkdiv & ~CLKD_OTP) | (otpdiv << CLKD_OTP_SHIFT);
-			W_REG(osh, &cc->clkdiv, clkdiv);
+			W_REG(&cc->clkdiv, clkdiv);
 		}
 		udelay(10);
 
@@ -818,7 +806,7 @@ static int hndotp_nvread(void *oh, char *data, uint *len)
 			if (offset + dsz >= *len) {
 				goto out;
 			}
-			bcopy((char *)&rawotp[i + 2], &data[offset], dsz);
+			memcpy(&data[offset], &rawotp[i + 2], dsz);
 			offset += dsz;
 			/* Remove extra null characters at the end */
 			while (offset > 1 &&
@@ -842,8 +830,7 @@ static int hndotp_nvread(void *oh, char *data, uint *len)
 	*len = offset;
 
  out:
-	if (rawotp)
-		kfree(rawotp);
+	kfree(rawotp);
 	si_setcoreidx(oi->sih, idx);
 
 	return rc;
@@ -921,7 +908,6 @@ void *otp_init(si_t *sih)
 	}
 
 	oi->sih = sih;
-	oi->osh = si_osh(oi->sih);
 
 	ret = (oi->fn->init) (sih);
 
diff --git a/drivers/staging/brcm80211/util/bcmsrom.c b/drivers/staging/brcm80211/util/bcmsrom.c
index 19d4502..eca35b9 100644
--- a/drivers/staging/brcm80211/util/bcmsrom.c
+++ b/drivers/staging/brcm80211/util/bcmsrom.c
@@ -17,7 +17,6 @@
 #include <linux/string.h>
 #include <linux/etherdevice.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <stdarg.h>
@@ -25,7 +24,6 @@
 #include <hndsoc.h>
 #include <sbchipc.h>
 #include <bcmdevs.h>
-#include <bcmendian.h>
 #include <pcicfg.h>
 #include <siutils.h>
 #include <bcmsrom.h>
@@ -44,7 +42,7 @@
 #include <sbsdpcmdev.h>
 #endif
 
-#include <proto/ethernet.h>	/* for sprom content groking */
+#include <linux/if_ether.h>
 
 #define	BS_ERROR(args)
 
@@ -68,29 +66,26 @@ extern uint _varsz;
 
 #define SROM_CIS_SINGLE	1
 
-static int initvars_srom_si(si_t *sih, struct osl_info *osh, void *curmap,
-			    char **vars, uint *count);
-static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off,
-			       varbuf_t *b);
-static int initvars_srom_pci(si_t *sih, void *curmap, char **vars,
-			     uint *count);
+static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *count);
+static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b);
+static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count);
 static int initvars_flash_si(si_t *sih, char **vars, uint *count);
 #ifdef BCMSDIO
-static int initvars_cis_sdio(struct osl_info *osh, char **vars, uint *count);
-static int sprom_cmd_sdio(struct osl_info *osh, u8 cmd);
-static int sprom_read_sdio(struct osl_info *osh, u16 addr, u16 *data);
+static int initvars_cis_sdio(char **vars, uint *count);
+static int sprom_cmd_sdio(u8 cmd);
+static int sprom_read_sdio(u16 addr, u16 *data);
 #endif				/* BCMSDIO */
-static int sprom_read_pci(struct osl_info *osh, si_t *sih, u16 *sprom,
+static int sprom_read_pci(si_t *sih, u16 *sprom,
 			  uint wordoff, u16 *buf, uint nwords, bool check_crc);
 #if defined(BCMNVRAMR)
-static int otp_read_pci(struct osl_info *osh, si_t *sih, u16 *buf, uint bufsz);
+static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz);
 #endif
-static u16 srom_cc_cmd(si_t *sih, struct osl_info *osh, void *ccregs, u32 cmd,
+static u16 srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
 			  uint wordoff, u16 data);
 
-static int initvars_table(struct osl_info *osh, char *start, char *end,
+static int initvars_table(char *start, char *end,
 			  char **vars, uint *count);
-static int initvars_flash(si_t *sih, struct osl_info *osh, char **vp,
+static int initvars_flash(si_t *sih, char **vp,
 			  uint len);
 
 /* Initialization of varbuf structure */
@@ -158,7 +153,7 @@ static int varbuf_append(varbuf_t *b, const char *fmt, ...)
  * Initialize local vars from the right source for this platform.
  * Return 0 on success, nonzero on error.
  */
-int srom_var_init(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
+int srom_var_init(si_t *sih, uint bustype, void *curmap,
 		  char **vars, uint *count)
 {
 	uint len;
@@ -175,7 +170,7 @@ int srom_var_init(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
 	switch (bustype) {
 	case SI_BUS:
 	case JTAG_BUS:
-		return initvars_srom_si(sih, osh, curmap, vars, count);
+		return initvars_srom_si(sih, curmap, vars, count);
 
 	case PCI_BUS:
 		ASSERT(curmap != NULL);
@@ -186,7 +181,7 @@ int srom_var_init(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
 
 #ifdef BCMSDIO
 	case SDIO_BUS:
-		return initvars_cis_sdio(osh, vars, count);
+		return initvars_cis_sdio(vars, count);
 #endif				/* BCMSDIO */
 
 	default:
@@ -197,7 +192,7 @@ int srom_var_init(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
 
 /* support only 16-bit word read from srom */
 int
-srom_read(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
+srom_read(si_t *sih, uint bustype, void *curmap,
 	  uint byteoff, uint nbytes, u16 *buf, bool check_crc)
 {
 	uint off, nw;
@@ -226,12 +221,12 @@ srom_read(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
 				return 1;
 
 			if (sprom_read_pci
-			    (osh, sih, srom, off, buf, nw, check_crc))
+			    (sih, srom, off, buf, nw, check_crc))
 				return 1;
 		}
 #if defined(BCMNVRAMR)
 		else {
-			if (otp_read_pci(osh, sih, buf, SROM_MAX))
+			if (otp_read_pci(sih, buf, SROM_MAX))
 				return 1;
 		}
 #endif
@@ -241,7 +236,7 @@ srom_read(si_t *sih, uint bustype, void *curmap, struct osl_info *osh,
 		nw = nbytes / 2;
 		for (i = 0; i < nw; i++) {
 			if (sprom_read_sdio
-			    (osh, (u16) (off + i), (u16 *) (buf + i)))
+			    ((u16) (off + i), (u16 *) (buf + i)))
 				return 1;
 		}
 #endif				/* BCMSDIO */
@@ -379,7 +374,7 @@ u8 patch_pair;
 /* For dongle HW, accept partial calibration parameters */
 #define BCMDONGLECASE(n)
 
-int srom_parsecis(struct osl_info *osh, u8 *pcis[], uint ciscnt, char **vars,
+int srom_parsecis(u8 *pcis[], uint ciscnt, char **vars,
 		  uint *count)
 {
 	char eabuf[32];
@@ -1336,8 +1331,8 @@ int srom_parsecis(struct osl_info *osh, u8 *pcis[], uint ciscnt, char **vars,
 						u8 srev = cis[i + 1 + 70];
 						ASSERT(srev == 3);
 						/* make tuple value 16-bit aligned and parse it */
-						bcopy(&cis[i + 1], srom,
-						      sizeof(srom));
+						memcpy(srom, &cis[i + 1],
+						       sizeof(srom));
 						_initvars_srom_pci(srev, srom,
 								   SROM3_SWRGN_OFF,
 								   &b);
@@ -1399,7 +1394,7 @@ int srom_parsecis(struct osl_info *osh, u8 *pcis[], uint ciscnt, char **vars,
 	*b.buf++ = '\0';
 
 	ASSERT(b.buf - base <= MAXSZ_NVRAM_VARS);
-	err = initvars_table(osh, base, b.buf, vars, count);
+	err = initvars_table(base, b.buf, vars, count);
 
 	kfree(base);
 	return err;
@@ -1409,22 +1404,22 @@ int srom_parsecis(struct osl_info *osh, u8 *pcis[], uint ciscnt, char **vars,
  * not in the bus cores.
  */
 static u16
-srom_cc_cmd(si_t *sih, struct osl_info *osh, void *ccregs, u32 cmd,
+srom_cc_cmd(si_t *sih, void *ccregs, u32 cmd,
 	    uint wordoff, u16 data)
 {
 	chipcregs_t *cc = (chipcregs_t *) ccregs;
 	uint wait_cnt = 1000;
 
 	if ((cmd == SRC_OP_READ) || (cmd == SRC_OP_WRITE)) {
-		W_REG(osh, &cc->sromaddress, wordoff * 2);
+		W_REG(&cc->sromaddress, wordoff * 2);
 		if (cmd == SRC_OP_WRITE)
-			W_REG(osh, &cc->sromdata, data);
+			W_REG(&cc->sromdata, data);
 	}
 
-	W_REG(osh, &cc->sromcontrol, SRC_START | cmd);
+	W_REG(&cc->sromcontrol, SRC_START | cmd);
 
 	while (wait_cnt--) {
-		if ((R_REG(osh, &cc->sromcontrol) & SRC_BUSY) == 0)
+		if ((R_REG(&cc->sromcontrol) & SRC_BUSY) == 0)
 			break;
 	}
 
@@ -1433,17 +1428,29 @@ srom_cc_cmd(si_t *sih, struct osl_info *osh, void *ccregs, u32 cmd,
 		return 0xffff;
 	}
 	if (cmd == SRC_OP_READ)
-		return (u16) R_REG(osh, &cc->sromdata);
+		return (u16) R_REG(&cc->sromdata);
 	else
 		return 0xffff;
 }
 
+static inline void ltoh16_buf(u16 *buf, unsigned int size)
+{
+	for (size /= 2; size; size--)
+		*(buf + size) = le16_to_cpu(*(buf + size));
+}
+
+static inline void htol16_buf(u16 *buf, unsigned int size)
+{
+	for (size /= 2; size; size--)
+		*(buf + size) = cpu_to_le16(*(buf + size));
+}
+
 /*
  * Read in and validate sprom.
  * Return 0 on success, nonzero on error.
  */
 static int
-sprom_read_pci(struct osl_info *osh, si_t *sih, u16 *sprom, uint wordoff,
+sprom_read_pci(si_t *sih, u16 *sprom, uint wordoff,
 	       u16 *buf, uint nwords, bool check_crc)
 {
 	int err = 0;
@@ -1460,14 +1467,14 @@ sprom_read_pci(struct osl_info *osh, si_t *sih, u16 *sprom, uint wordoff,
 
 			ccregs = (void *)((u8 *) sprom - CC_SROM_OTP);
 			buf[i] =
-			    srom_cc_cmd(sih, osh, ccregs, SRC_OP_READ,
+			    srom_cc_cmd(sih, ccregs, SRC_OP_READ,
 					wordoff + i, 0);
 
 		} else {
 			if (ISSIM_ENAB(sih))
-				buf[i] = R_REG(osh, &sprom[wordoff + i]);
+				buf[i] = R_REG(&sprom[wordoff + i]);
 
-			buf[i] = R_REG(osh, &sprom[wordoff + i]);
+			buf[i] = R_REG(&sprom[wordoff + i]);
 		}
 
 	}
@@ -1503,7 +1510,7 @@ sprom_read_pci(struct osl_info *osh, si_t *sih, u16 *sprom, uint wordoff,
 }
 
 #if defined(BCMNVRAMR)
-static int otp_read_pci(struct osl_info *osh, si_t *sih, u16 *buf, uint bufsz)
+static int otp_read_pci(si_t *sih, u16 *buf, uint bufsz)
 {
 	u8 *otp;
 	uint sz = OTP_SZ_MAX / 2;	/* size in words */
@@ -1518,10 +1525,9 @@ static int otp_read_pci(struct osl_info *osh, si_t *sih, u16 *buf, uint bufsz)
 
 	err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
 
-	bcopy(otp, buf, bufsz);
+	memcpy(buf, otp, bufsz);
 
-	if (otp)
-		kfree(otp);
+	kfree(otp);
 
 	/* Check CRC */
 	if (buf[0] == 0xffff) {
@@ -1551,7 +1557,7 @@ static int otp_read_pci(struct osl_info *osh, si_t *sih, u16 *buf, uint bufsz)
 * Create variable table from memory.
 * Return 0 on success, nonzero on error.
 */
-static int initvars_table(struct osl_info *osh, char *start, char *end,
+static int initvars_table(char *start, char *end,
 			  char **vars, uint *count)
 {
 	int c = (int)(end - start);
@@ -1562,7 +1568,7 @@ static int initvars_table(struct osl_info *osh, char *start, char *end,
 		ASSERT(vp != NULL);
 		if (!vp)
 			return BCME_NOMEM;
-		bcopy(start, vp, c);
+		memcpy(vp, start, c);
 		*vars = vp;
 		*count = c;
 	} else {
@@ -1578,8 +1584,7 @@ static int initvars_table(struct osl_info *osh, char *start, char *end,
  * of the table upon enter and to the end of the table upon exit when success.
  * Return 0 on success, nonzero on error.
  */
-static int initvars_flash(si_t *sih, struct osl_info *osh, char **base,
-			  uint len)
+static int initvars_flash(si_t *sih, char **base, uint len)
 {
 	char *vp = *base;
 	char *flash;
@@ -1639,7 +1644,6 @@ static int initvars_flash(si_t *sih, struct osl_info *osh, char **base,
  */
 static int initvars_flash_si(si_t *sih, char **vars, uint *count)
 {
-	struct osl_info *osh = si_osh(sih);
 	char *vp, *base;
 	int err;
 
@@ -1651,9 +1655,9 @@ static int initvars_flash_si(si_t *sih, char **vars, uint *count)
 	if (!vp)
 		return BCME_NOMEM;
 
-	err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
+	err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
 	if (err == 0)
-		err = initvars_table(osh, base, vp, vars, count);
+		err = initvars_table(base, vp, vars, count);
 
 	kfree(base);
 
@@ -1725,16 +1729,16 @@ static void _initvars_srom_pci(u8 sromrev, u16 *srom, uint off, varbuf_t *b)
 			continue;
 
 		if (flags & SRFL_ETHADDR) {
-			struct ether_addr ea;
+			u8 ea[ETH_ALEN];
 
-			ea.octet[0] = (srom[srv->off - off] >> 8) & 0xff;
-			ea.octet[1] = srom[srv->off - off] & 0xff;
-			ea.octet[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
-			ea.octet[3] = srom[srv->off + 1 - off] & 0xff;
-			ea.octet[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
-			ea.octet[5] = srom[srv->off + 2 - off] & 0xff;
+			ea[0] = (srom[srv->off - off] >> 8) & 0xff;
+			ea[1] = srom[srv->off - off] & 0xff;
+			ea[2] = (srom[srv->off + 1 - off] >> 8) & 0xff;
+			ea[3] = srom[srv->off + 1 - off] & 0xff;
+			ea[4] = (srom[srv->off + 2 - off] >> 8) & 0xff;
+			ea[5] = srom[srv->off + 2 - off] & 0xff;
 
-			varbuf_append(b, "%s=%pM", name, ea.octet);
+			varbuf_append(b, "%s=%pM", name, ea);
 		} else {
 			ASSERT(mask_valid(srv->mask));
 			ASSERT(mask_width(srv->mask));
@@ -1850,7 +1854,6 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
 	u32 sr;
 	varbuf_t b;
 	char *vp, *base = NULL;
-	struct osl_info *osh = si_osh(sih);
 	bool flash = false;
 	int err = 0;
 
@@ -1868,7 +1871,7 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
 	sromwindow = (u16 *) SROM_OFFSET(sih);
 	if (si_is_sprom_available(sih)) {
 		err =
-		    sprom_read_pci(osh, sih, sromwindow, 0, srom, SROM_WORDS,
+		    sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
 				   true);
 
 		if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
@@ -1878,7 +1881,7 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
 			 && (sih->buscorerev >= 0xe)))) {
 			/* sromrev >= 4, read more */
 			err =
-			    sprom_read_pci(osh, sih, sromwindow, 0, srom,
+			    sprom_read_pci(sih, sromwindow, 0, srom,
 					   SROM4_WORDS, true);
 			sromrev = srom[SROM4_CRCREV] & 0xff;
 			if (err)
@@ -1896,24 +1899,29 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
 	}
 #if defined(BCMNVRAMR)
 	/* Use OTP if SPROM not available */
-	else if ((err = otp_read_pci(osh, sih, srom, SROM_MAX)) == 0) {
-		/* OTP only contain SROM rev8/rev9 for now */
-		sromrev = srom[SROM4_CRCREV] & 0xff;
-	}
-#endif
 	else {
-		err = 1;
-		BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
+		err = otp_read_pci(sih, srom, SROM_MAX);
+		if (err == 0)
+			/* OTP only contain SROM rev8/rev9 for now */
+			sromrev = srom[SROM4_CRCREV] & 0xff;
+		else
+			err = 1;
 	}
+#else
+	else
+		err = 1;
+#endif
 
-	/* We want internal/wltest driver to come up with default sromvars so we can
-	 * program a blank SPROM/OTP.
+	/*
+	 * We want internal/wltest driver to come up with default
+	 * sromvars so we can program a blank SPROM/OTP.
 	 */
 	if (err) {
 		char *value;
 		u32 val;
 		val = 0;
 
+		BS_ERROR(("Neither SPROM nor OTP has valid image\n"));
 		value = si_getdevpathvar(sih, "sromrev");
 		if (value) {
 			sromrev = (u8) simple_strtoul(value, NULL, 0);
@@ -1957,7 +1965,7 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
 
 	/* read variables from flash */
 	if (flash) {
-		err = initvars_flash(sih, osh, &vp, MAXSZ_NVRAM_VARS);
+		err = initvars_flash(sih, &vp, MAXSZ_NVRAM_VARS);
 		if (err)
 			goto errout;
 		goto varsdone;
@@ -1976,7 +1984,7 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
 	ASSERT((vp - base) <= MAXSZ_NVRAM_VARS);
 
  varsdone:
-	err = initvars_table(osh, base, vp, vars, count);
+	err = initvars_table(base, vp, vars, count);
 
  errout:
 	if (base)
@@ -1991,7 +1999,7 @@ static int initvars_srom_pci(si_t *sih, void *curmap, char **vars, uint *count)
  * Read the SDIO cis and call parsecis to initialize the vars.
  * Return 0 on success, nonzero on error.
  */
-static int initvars_cis_sdio(struct osl_info *osh, char **vars, uint *count)
+static int initvars_cis_sdio(char **vars, uint *count)
 {
 	u8 *cis[SBSDIO_NUM_FUNCTION + 1];
 	uint fn, numfn;
@@ -2016,7 +2024,7 @@ static int initvars_cis_sdio(struct osl_info *osh, char **vars, uint *count)
 	}
 
 	if (!rc)
-		rc = srom_parsecis(osh, cis, fn, vars, count);
+		rc = srom_parsecis(cis, fn, vars, count);
 
 	while (fn-- > 0)
 		kfree(cis[fn]);
@@ -2025,7 +2033,7 @@ static int initvars_cis_sdio(struct osl_info *osh, char **vars, uint *count)
 }
 
 /* set SDIO sprom command register */
-static int sprom_cmd_sdio(struct osl_info *osh, u8 cmd)
+static int sprom_cmd_sdio(u8 cmd)
 {
 	u8 status = 0;
 	uint wait_cnt = 1000;
@@ -2045,7 +2053,7 @@ static int sprom_cmd_sdio(struct osl_info *osh, u8 cmd)
 }
 
 /* read a word from the SDIO srom */
-static int sprom_read_sdio(struct osl_info *osh, u16 addr, u16 *data)
+static int sprom_read_sdio(u16 addr, u16 *data)
 {
 	u8 addr_l, addr_h, data_l, data_h;
 
@@ -2059,7 +2067,7 @@ static int sprom_read_sdio(struct osl_info *osh, u16 addr, u16 *data)
 			 NULL);
 
 	/* do read */
-	if (sprom_cmd_sdio(osh, SBSDIO_SPROM_READ))
+	if (sprom_cmd_sdio(SBSDIO_SPROM_READ))
 		return 1;
 
 	/* read data */
@@ -2073,8 +2081,7 @@ static int sprom_read_sdio(struct osl_info *osh, u16 addr, u16 *data)
 }
 #endif				/* BCMSDIO */
 
-static int initvars_srom_si(si_t *sih, struct osl_info *osh, void *curmap,
-			    char **vars, uint *varsz)
+static int initvars_srom_si(si_t *sih, void *curmap, char **vars, uint *varsz)
 {
 	/* Search flash nvram section for srom variables */
 	return initvars_flash_si(sih, vars, varsz);
diff --git a/drivers/staging/brcm80211/util/bcmsrom_tbl.h b/drivers/staging/brcm80211/util/bcmsrom_tbl.h
new file mode 100644
index 0000000..22ae7c1
--- /dev/null
+++ b/drivers/staging/brcm80211/util/bcmsrom_tbl.h
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_bcmsrom_tbl_h_
+#define	_bcmsrom_tbl_h_
+
+#include "sbpcmcia.h"
+#include "wlioctl.h"
+
+typedef struct {
+	const char *name;
+	u32 revmask;
+	u32 flags;
+	u16 off;
+	u16 mask;
+} sromvar_t;
+
+#define SRFL_MORE	1	/* value continues as described by the next entry */
+#define	SRFL_NOFFS	2	/* value bits can't be all one's */
+#define	SRFL_PRHEX	4	/* value is in hexdecimal format */
+#define	SRFL_PRSIGN	8	/* value is in signed decimal format */
+#define	SRFL_CCODE	0x10	/* value is in country code format */
+#define	SRFL_ETHADDR	0x20	/* value is an Ethernet address */
+#define SRFL_LEDDC	0x40	/* value is an LED duty cycle */
+#define SRFL_NOVAR	0x80	/* do not generate a nvram param, entry is for mfgc */
+
+/* Assumptions:
+ * - Ethernet address spans across 3 consective words
+ *
+ * Table rules:
+ * - Add multiple entries next to each other if a value spans across multiple words
+ *   (even multiple fields in the same word) with each entry except the last having
+ *   it's SRFL_MORE bit set.
+ * - Ethernet address entry does not follow above rule and must not have SRFL_MORE
+ *   bit set. Its SRFL_ETHADDR bit implies it takes multiple words.
+ * - The last entry's name field must be NULL to indicate the end of the table. Other
+ *   entries must have non-NULL name.
+ */
+
+static const sromvar_t pci_sromvars[] = {
+	{"devid", 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, 0xffff},
+	{"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK},
+	{"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
+	{"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
+	{"boardflags", 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
+	{"boardflags", 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
+	{"", 0, 0, SROM_BFL2, 0xffff},
+	{"boardflags", 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL, 0xffff},
+	{"", 0, 0, SROM3_BFL2, 0xffff},
+	{"boardflags", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0, 0xffff},
+	{"", 0, 0, SROM4_BFL1, 0xffff},
+	{"boardflags", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0, 0xffff},
+	{"", 0, 0, SROM5_BFL1, 0xffff},
+	{"boardflags", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, 0xffff},
+	{"", 0, 0, SROM8_BFL1, 0xffff},
+	{"boardflags2", 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2, 0xffff},
+	{"", 0, 0, SROM4_BFL3, 0xffff},
+	{"boardflags2", 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2, 0xffff},
+	{"", 0, 0, SROM5_BFL3, 0xffff},
+	{"boardflags2", 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, 0xffff},
+	{"", 0, 0, SROM8_BFL3, 0xffff},
+	{"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
+	{"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
+	{"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff},
+	{"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff},
+	{"boardnum", 0x000000e0, 0, SROM5_MACLO, 0xffff},
+	{"boardnum", 0xffffff00, 0, SROM8_MACLO, 0xffff},
+	{"cc", 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
+	{"regrev", 0x00000008, 0, SROM_OPO, 0xff00},
+	{"regrev", 0x00000010, 0, SROM4_REGREV, 0x00ff},
+	{"regrev", 0x000000e0, 0, SROM5_REGREV, 0x00ff},
+	{"regrev", 0xffffff00, 0, SROM8_REGREV, 0x00ff},
+	{"ledbh0", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
+	{"ledbh1", 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
+	{"ledbh2", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
+	{"ledbh3", 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
+	{"ledbh0", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
+	{"ledbh1", 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
+	{"ledbh2", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
+	{"ledbh3", 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
+	{"ledbh0", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
+	{"ledbh1", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
+	{"ledbh2", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
+	{"ledbh3", 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
+	{"ledbh0", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
+	{"ledbh1", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
+	{"ledbh2", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
+	{"ledbh3", 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
+	{"pa0b0", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
+	{"pa0b1", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
+	{"pa0b2", 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
+	{"pa0itssit", 0x0000000e, 0, SROM_ITT, 0x00ff},
+	{"pa0maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
+	{"pa0b0", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
+	{"pa0b1", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
+	{"pa0b2", 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
+	{"pa0itssit", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
+	{"pa0maxpwr", 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
+	{"opo", 0x0000000c, 0, SROM_OPO, 0x00ff},
+	{"opo", 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
+	{"aa2g", 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
+	{"aa2g", 0x000000f0, 0, SROM4_AA, 0x00ff},
+	{"aa2g", 0xffffff00, 0, SROM8_AA, 0x00ff},
+	{"aa5g", 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
+	{"aa5g", 0x000000f0, 0, SROM4_AA, 0xff00},
+	{"aa5g", 0xffffff00, 0, SROM8_AA, 0xff00},
+	{"ag0", 0x0000000e, 0, SROM_AG10, 0x00ff},
+	{"ag1", 0x0000000e, 0, SROM_AG10, 0xff00},
+	{"ag0", 0x000000f0, 0, SROM4_AG10, 0x00ff},
+	{"ag1", 0x000000f0, 0, SROM4_AG10, 0xff00},
+	{"ag2", 0x000000f0, 0, SROM4_AG32, 0x00ff},
+	{"ag3", 0x000000f0, 0, SROM4_AG32, 0xff00},
+	{"ag0", 0xffffff00, 0, SROM8_AG10, 0x00ff},
+	{"ag1", 0xffffff00, 0, SROM8_AG10, 0xff00},
+	{"ag2", 0xffffff00, 0, SROM8_AG32, 0x00ff},
+	{"ag3", 0xffffff00, 0, SROM8_AG32, 0xff00},
+	{"pa1b0", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
+	{"pa1b1", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
+	{"pa1b2", 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
+	{"pa1lob0", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
+	{"pa1lob1", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
+	{"pa1lob2", 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
+	{"pa1hib0", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
+	{"pa1hib1", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
+	{"pa1hib2", 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
+	{"pa1itssit", 0x0000000e, 0, SROM_ITT, 0xff00},
+	{"pa1maxpwr", 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
+	{"pa1lomaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
+	{"pa1himaxpwr", 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
+	{"pa1b0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
+	{"pa1b1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
+	{"pa1b2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
+	{"pa1lob0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff},
+	{"pa1lob1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff},
+	{"pa1lob2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff},
+	{"pa1hib0", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff},
+	{"pa1hib1", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff},
+	{"pa1hib2", 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff},
+	{"pa1itssit", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00},
+	{"pa1maxpwr", 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
+	{"pa1lomaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
+	{"pa1himaxpwr", 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
+	{"bxa2g", 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
+	{"rssisav2g", 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
+	{"rssismc2g", 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
+	{"rssismf2g", 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
+	{"bxa2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
+	{"rssisav2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
+	{"rssismc2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
+	{"rssismf2g", 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
+	{"bxa5g", 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
+	{"rssisav5g", 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
+	{"rssismc5g", 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
+	{"rssismf5g", 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
+	{"bxa5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
+	{"rssisav5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
+	{"rssismc5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
+	{"rssismf5g", 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
+	{"tri2g", 0x00000008, 0, SROM_TRI52G, 0x00ff},
+	{"tri5g", 0x00000008, 0, SROM_TRI52G, 0xff00},
+	{"tri5gl", 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
+	{"tri5gh", 0x00000008, 0, SROM_TRI5GHL, 0xff00},
+	{"tri2g", 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
+	{"tri5g", 0xffffff00, 0, SROM8_TRI52G, 0xff00},
+	{"tri5gl", 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
+	{"tri5gh", 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
+	{"rxpo2g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
+	{"rxpo5g", 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
+	{"rxpo2g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
+	{"rxpo5g", 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
+	{"txchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_TXCHAIN_MASK},
+	{"rxchain", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_RXCHAIN_MASK},
+	{"antswitch", 0x000000f0, SRFL_NOFFS, SROM4_TXRXC, SROM4_SWITCH_MASK},
+	{"txchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_TXCHAIN_MASK},
+	{"rxchain", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_RXCHAIN_MASK},
+	{"antswitch", 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, SROM4_SWITCH_MASK},
+	{"tssipos2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_PDET_RANGE_MASK},
+	{"triso2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK},
+	{"antswctl2g", 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_ANTSWLUT_MASK},
+	{"tssipos5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TSSIPOS_MASK},
+	{"extpagain5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_EXTPA_GAIN_MASK},
+	{"pdetrange5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_PDET_RANGE_MASK},
+	{"triso5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK},
+	{"antswctl5g", 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_ANTSWLUT_MASK},
+	{"tempthresh", 0xffffff00, 0, SROM8_THERMAL, 0xff00},
+	{"tempoffset", 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
+	{"txpid2ga0", 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
+	{"txpid2ga1", 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
+	{"txpid2ga2", 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
+	{"txpid2ga3", 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
+	{"txpid5ga0", 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
+	{"txpid5ga1", 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
+	{"txpid5ga2", 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
+	{"txpid5ga3", 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
+	{"txpid5gla0", 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
+	{"txpid5gla1", 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
+	{"txpid5gla2", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
+	{"txpid5gla3", 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
+	{"txpid5gha0", 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
+	{"txpid5gha1", 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
+	{"txpid5gha2", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
+	{"txpid5gha3", 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
+
+	{"ccode", 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
+	{"ccode", 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
+	{"ccode", 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
+	{"ccode", 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
+	{"macaddr", 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
+	{"macaddr", 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
+	{"macaddr", 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
+	{"macaddr", 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
+	{"il0macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0, 0xffff},
+	{"et1macaddr", 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1, 0xffff},
+	{"leddc", 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, 0xffff},
+	{"leddc", 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC, 0xffff},
+	{"leddc", 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC, 0xffff},
+	{"leddc", 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC, 0xffff},
+	{"rawtempsense", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0x01ff},
+	{"measpower", 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, 0xfe00},
+	{"tempsense_slope", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+	 0x00ff},
+	{"tempcorrx", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, 0xfc00},
+	{"tempsense_option", 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX,
+	 0x0300},
+	{"freqoffset_corr", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP,
+	 0x000f},
+	{"iqcal_swp_dis", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0010},
+	{"hw_iqcal_en", 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, 0x0020},
+	{"phycal_tempdelta", 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, 0x00ff},
+
+	{"cck2gpo", 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
+	{"cck2gpo", 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
+	{"ofdm2gpo", 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
+	{"ofdm5gpo", 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
+	{"ofdm5glpo", 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
+	{"ofdm5ghpo", 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
+	{"", 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
+	{"ofdm2gpo", 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
+	{"ofdm5gpo", 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_5G_OFDMPO + 1, 0xffff},
+	{"ofdm5glpo", 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
+	{"ofdm5ghpo", 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
+	{"", 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
+	{"mcs2gpo0", 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
+	{"mcs2gpo1", 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
+	{"mcs2gpo2", 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
+	{"mcs2gpo3", 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
+	{"mcs2gpo4", 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
+	{"mcs2gpo5", 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
+	{"mcs2gpo6", 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
+	{"mcs2gpo7", 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
+	{"mcs5gpo0", 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
+	{"mcs5gpo1", 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
+	{"mcs5gpo2", 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
+	{"mcs5gpo3", 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
+	{"mcs5gpo4", 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
+	{"mcs5gpo5", 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
+	{"mcs5gpo6", 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
+	{"mcs5gpo7", 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
+	{"mcs5glpo0", 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
+	{"mcs5glpo1", 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
+	{"mcs5glpo2", 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
+	{"mcs5glpo3", 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
+	{"mcs5glpo4", 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
+	{"mcs5glpo5", 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
+	{"mcs5glpo6", 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
+	{"mcs5glpo7", 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
+	{"mcs5ghpo0", 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
+	{"mcs5ghpo1", 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
+	{"mcs5ghpo2", 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
+	{"mcs5ghpo3", 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
+	{"mcs5ghpo4", 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
+	{"mcs5ghpo5", 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
+	{"mcs5ghpo6", 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
+	{"mcs5ghpo7", 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
+	{"mcs2gpo0", 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
+	{"mcs2gpo1", 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
+	{"mcs2gpo2", 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
+	{"mcs2gpo3", 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff},
+	{"mcs2gpo4", 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff},
+	{"mcs2gpo5", 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff},
+	{"mcs2gpo6", 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff},
+	{"mcs2gpo7", 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff},
+	{"mcs5gpo0", 0x00000100, 0, SROM8_5G_MCSPO, 0xffff},
+	{"mcs5gpo1", 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff},
+	{"mcs5gpo2", 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff},
+	{"mcs5gpo3", 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff},
+	{"mcs5gpo4", 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff},
+	{"mcs5gpo5", 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff},
+	{"mcs5gpo6", 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff},
+	{"mcs5gpo7", 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff},
+	{"mcs5glpo0", 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff},
+	{"mcs5glpo1", 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff},
+	{"mcs5glpo2", 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff},
+	{"mcs5glpo3", 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff},
+	{"mcs5glpo4", 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff},
+	{"mcs5glpo5", 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff},
+	{"mcs5glpo6", 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff},
+	{"mcs5glpo7", 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff},
+	{"mcs5ghpo0", 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff},
+	{"mcs5ghpo1", 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff},
+	{"mcs5ghpo2", 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff},
+	{"mcs5ghpo3", 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff},
+	{"mcs5ghpo4", 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff},
+	{"mcs5ghpo5", 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
+	{"mcs5ghpo6", 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
+	{"mcs5ghpo7", 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
+	{"cddpo", 0x000000f0, 0, SROM4_CDDPO, 0xffff},
+	{"stbcpo", 0x000000f0, 0, SROM4_STBCPO, 0xffff},
+	{"bw40po", 0x000000f0, 0, SROM4_BW40PO, 0xffff},
+	{"bwduppo", 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
+	{"cddpo", 0x00000100, 0, SROM8_CDDPO, 0xffff},
+	{"stbcpo", 0x00000100, 0, SROM8_STBCPO, 0xffff},
+	{"bw40po", 0x00000100, 0, SROM8_BW40PO, 0xffff},
+	{"bwduppo", 0x00000100, 0, SROM8_BWDUPPO, 0xffff},
+
+	/* power per rate from sromrev 9 */
+	{"cckbw202gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff},
+	{"cckbw20ul2gpo", 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff},
+	{"legofdmbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff},
+	{"legofdmbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff},
+	{"legofdmbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff},
+	{"legofdmbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20,
+	 0xffff},
+	{"", 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff},
+	{"legofdmbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_LOFDMBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff},
+	{"mcsbw202gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul2gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, 0xffff},
+	{"", 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw402gpo", 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff},
+	{"mcsbw205glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul5glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw405glpo", 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff},
+	{"mcsbw205gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul5gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw405gmpo", 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff},
+	{"mcsbw205ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, 0xffff},
+	{"", 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff},
+	{"mcsbw20ul5ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20UL,
+	 0xffff},
+	{"", 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff},
+	{"mcsbw405ghpo", 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, 0xffff},
+	{"", 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff},
+	{"mcs32po", 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff},
+	{"legofdm40duppo", 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff},
+
+	{NULL, 0, 0, 0, 0}
+};
+
+static const sromvar_t perpath_pci_sromvars[] = {
+	{"maxp2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
+	{"itt2ga", 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
+	{"itt5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
+	{"pa2gw0a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
+	{"pa2gw1a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
+	{"pa2gw2a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
+	{"pa2gw3a", 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
+	{"maxp5ga", 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
+	{"maxp5gha", 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
+	{"maxp5gla", 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
+	{"pa5gw0a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
+	{"pa5gw1a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
+	{"pa5gw2a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
+	{"pa5gw3a", 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
+	{"pa5glw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
+	{"pa5glw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1, 0xffff},
+	{"pa5glw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2, 0xffff},
+	{"pa5glw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3, 0xffff},
+	{"pa5ghw0a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
+	{"pa5ghw1a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1, 0xffff},
+	{"pa5ghw2a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2, 0xffff},
+	{"pa5ghw3a", 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3, 0xffff},
+	{"maxp2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
+	{"itt2ga", 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
+	{"itt5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
+	{"pa2gw0a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff},
+	{"pa2gw1a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff},
+	{"pa2gw2a", 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff},
+	{"maxp5ga", 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff},
+	{"maxp5gha", 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff},
+	{"maxp5gla", 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00},
+	{"pa5gw0a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff},
+	{"pa5gw1a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff},
+	{"pa5gw2a", 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff},
+	{"pa5glw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff},
+	{"pa5glw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, 0xffff},
+	{"pa5glw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, 0xffff},
+	{"pa5ghw0a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff},
+	{"pa5ghw1a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, 0xffff},
+	{"pa5ghw2a", 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, 0xffff},
+	{NULL, 0, 0, 0, 0}
+};
+
+#if !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP))
+#define	PHY_TYPE_N		4	/* N-Phy value */
+#define	PHY_TYPE_LP		5	/* LP-Phy value */
+#endif				/* !(defined(PHY_TYPE_N) && defined(PHY_TYPE_LP)) */
+#if !defined(PHY_TYPE_NULL)
+#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
+#endif				/* !defined(PHY_TYPE_NULL) */
+
+typedef struct {
+	u16 phy_type;
+	u16 bandrange;
+	u16 chain;
+	const char *vars;
+} pavars_t;
+
+static const pavars_t pavars[] = {
+	/* NPHY */
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 0, "pa2gw0a0 pa2gw1a0 pa2gw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G, 1, "pa2gw0a1 pa2gw1a1 pa2gw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 0,
+	 "pa5glw0a0 pa5glw1a0 pa5glw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL, 1,
+	 "pa5glw0a1 pa5glw1a1 pa5glw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 0, "pa5gw0a0 pa5gw1a0 pa5gw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM, 1, "pa5gw0a1 pa5gw1a1 pa5gw2a1"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 0,
+	 "pa5ghw0a0 pa5ghw1a0 pa5ghw2a0"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH, 1,
+	 "pa5ghw0a1 pa5ghw1a1 pa5ghw2a1"},
+	/* LPPHY */
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_2G, 0, "pa0b0 pa0b1 pa0b2"},
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GL, 0, "pa1lob0 pa1lob1 pa1lob2"},
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GM, 0, "pa1b0 pa1b1 pa1b2"},
+	{PHY_TYPE_LP, WL_CHAN_FREQ_RANGE_5GH, 0, "pa1hib0 pa1hib1 pa1hib2"},
+	{PHY_TYPE_NULL, 0, 0, ""}
+};
+
+typedef struct {
+	u16 phy_type;
+	u16 bandrange;
+	const char *vars;
+} povars_t;
+
+static const povars_t povars[] = {
+	/* NPHY */
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_2G,
+	 "mcs2gpo0 mcs2gpo1 mcs2gpo2 mcs2gpo3 "
+	 "mcs2gpo4 mcs2gpo5 mcs2gpo6 mcs2gpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GL,
+	 "mcs5glpo0 mcs5glpo1 mcs5glpo2 mcs5glpo3 "
+	 "mcs5glpo4 mcs5glpo5 mcs5glpo6 mcs5glpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GM,
+	 "mcs5gpo0 mcs5gpo1 mcs5gpo2 mcs5gpo3 "
+	 "mcs5gpo4 mcs5gpo5 mcs5gpo6 mcs5gpo7"},
+	{PHY_TYPE_N, WL_CHAN_FREQ_RANGE_5GH,
+	 "mcs5ghpo0 mcs5ghpo1 mcs5ghpo2 mcs5ghpo3 "
+	 "mcs5ghpo4 mcs5ghpo5 mcs5ghpo6 mcs5ghpo7"},
+	{PHY_TYPE_NULL, 0, ""}
+};
+
+typedef struct {
+	u8 tag;		/* Broadcom subtag name */
+	u8 len;		/* Length field of the tuple, note that it includes the
+				 * subtag name (1 byte): 1 + tuple content length
+				 */
+	const char *params;
+} cis_tuple_t;
+
+#define OTP_RAW		(0xff - 1)	/* Reserved tuple number for wrvar Raw input */
+#define OTP_VERS_1	(0xff - 2)	/* CISTPL_VERS_1 */
+#define OTP_MANFID	(0xff - 3)	/* CISTPL_MANFID */
+#define OTP_RAW1	(0xff - 4)	/* Like RAW, but comes first */
+
+static const cis_tuple_t cis_hnbuvars[] = {
+	{OTP_RAW1, 0, ""},	/* special case */
+	{OTP_VERS_1, 0, "smanf sproductname"},	/* special case (non BRCM tuple) */
+	{OTP_MANFID, 4, "2manfid 2prodid"},	/* special case (non BRCM tuple) */
+	{HNBU_SROMREV, 2, "1sromrev"},
+	/* NOTE: subdevid is also written to boardtype.
+	 *       Need to write HNBU_BOARDTYPE to change it if it is different.
+	 */
+	{HNBU_CHIPID, 11, "2vendid 2devid 2chiprev 2subvendid 2subdevid"},
+	{HNBU_BOARDREV, 3, "2boardrev"},
+	{HNBU_PAPARMS, 10, "2pa0b0 2pa0b1 2pa0b2 1pa0itssit 1pa0maxpwr 1opo"},
+	{HNBU_AA, 3, "1aa2g 1aa5g"},
+	{HNBU_AA, 3, "1aa0 1aa1"},	/* backward compatibility */
+	{HNBU_AG, 5, "1ag0 1ag1 1ag2 1ag3"},
+	{HNBU_BOARDFLAGS, 9, "4boardflags 4boardflags2"},
+	{HNBU_LEDS, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"},
+	{HNBU_CCODE, 4, "2ccode 1cctl"},
+	{HNBU_CCKPO, 3, "2cckpo"},
+	{HNBU_OFDMPO, 5, "4ofdmpo"},
+	{HNBU_RDLID, 3, "2rdlid"},
+	{HNBU_RSSISMBXA2G, 3, "0rssismf2g 0rssismc2g 0rssisav2g 0bxa2g"},	/* special case */
+	{HNBU_RSSISMBXA5G, 3, "0rssismf5g 0rssismc5g 0rssisav5g 0bxa5g"},	/* special case */
+	{HNBU_XTALFREQ, 5, "4xtalfreq"},
+	{HNBU_TRI2G, 2, "1tri2g"},
+	{HNBU_TRI5G, 4, "1tri5gl 1tri5g 1tri5gh"},
+	{HNBU_RXPO2G, 2, "1rxpo2g"},
+	{HNBU_RXPO5G, 2, "1rxpo5g"},
+	{HNBU_BOARDNUM, 3, "2boardnum"},
+	{HNBU_MACADDR, 7, "6macaddr"},	/* special case */
+	{HNBU_RDLSN, 3, "2rdlsn"},
+	{HNBU_BOARDTYPE, 3, "2boardtype"},
+	{HNBU_LEDDC, 3, "2leddc"},
+	{HNBU_RDLRNDIS, 2, "1rdlndis"},
+	{HNBU_CHAINSWITCH, 5, "1txchain 1rxchain 2antswitch"},
+	{HNBU_REGREV, 2, "1regrev"},
+	{HNBU_FEM, 5, "0antswctl2g, 0triso2g, 0pdetrange2g, 0extpagain2g, 0tssipos2g" "0antswctl5g, 0triso5g, 0pdetrange5g, 0extpagain5g, 0tssipos5g"},	/* special case */
+	{HNBU_PAPARMS_C0, 31, "1maxp2ga0 1itt2ga0 2pa2gw0a0 2pa2gw1a0 "
+	 "2pa2gw2a0 1maxp5ga0 1itt5ga0 1maxp5gha0 1maxp5gla0 2pa5gw0a0 "
+	 "2pa5gw1a0 2pa5gw2a0 2pa5glw0a0 2pa5glw1a0 2pa5glw2a0 2pa5ghw0a0 "
+	 "2pa5ghw1a0 2pa5ghw2a0"},
+	{HNBU_PAPARMS_C1, 31, "1maxp2ga1 1itt2ga1 2pa2gw0a1 2pa2gw1a1 "
+	 "2pa2gw2a1 1maxp5ga1 1itt5ga1 1maxp5gha1 1maxp5gla1 2pa5gw0a1 "
+	 "2pa5gw1a1 2pa5gw2a1 2pa5glw0a1 2pa5glw1a1 2pa5glw2a1 2pa5ghw0a1 "
+	 "2pa5ghw1a1 2pa5ghw2a1"},
+	{HNBU_PO_CCKOFDM, 19, "2cck2gpo 4ofdm2gpo 4ofdm5gpo 4ofdm5glpo "
+	 "4ofdm5ghpo"},
+	{HNBU_PO_MCS2G, 17, "2mcs2gpo0 2mcs2gpo1 2mcs2gpo2 2mcs2gpo3 "
+	 "2mcs2gpo4 2mcs2gpo5 2mcs2gpo6 2mcs2gpo7"},
+	{HNBU_PO_MCS5GM, 17, "2mcs5gpo0 2mcs5gpo1 2mcs5gpo2 2mcs5gpo3 "
+	 "2mcs5gpo4 2mcs5gpo5 2mcs5gpo6 2mcs5gpo7"},
+	{HNBU_PO_MCS5GLH, 33, "2mcs5glpo0 2mcs5glpo1 2mcs5glpo2 2mcs5glpo3 "
+	 "2mcs5glpo4 2mcs5glpo5 2mcs5glpo6 2mcs5glpo7 "
+	 "2mcs5ghpo0 2mcs5ghpo1 2mcs5ghpo2 2mcs5ghpo3 "
+	 "2mcs5ghpo4 2mcs5ghpo5 2mcs5ghpo6 2mcs5ghpo7"},
+	{HNBU_CCKFILTTYPE, 2, "1cckdigfilttype"},
+	{HNBU_PO_CDD, 3, "2cddpo"},
+	{HNBU_PO_STBC, 3, "2stbcpo"},
+	{HNBU_PO_40M, 3, "2bw40po"},
+	{HNBU_PO_40MDUP, 3, "2bwduppo"},
+	{HNBU_RDLRWU, 2, "1rdlrwu"},
+	{HNBU_WPS, 3, "1wpsgpio 1wpsled"},
+	{HNBU_USBFS, 2, "1usbfs"},
+	{HNBU_CUSTOM1, 5, "4customvar1"},
+	{OTP_RAW, 0, ""},	/* special case */
+	{HNBU_OFDMPO5G, 13, "4ofdm5gpo 4ofdm5glpo 4ofdm5ghpo"},
+	{HNBU_USBEPNUM, 3, "2usbepnum"},
+	{0xFF, 0, ""}
+};
+
+#endif				/* _bcmsrom_tbl_h_ */
diff --git a/drivers/staging/brcm80211/util/bcmutils.c b/drivers/staging/brcm80211/util/bcmutils.c
index fd30cc6..fb0bccc 100644
--- a/drivers/staging/brcm80211/util/bcmutils.c
+++ b/drivers/staging/brcm80211/util/bcmutils.c
@@ -17,23 +17,65 @@
 #include <linux/ctype.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <bcmdefs.h>
-#include <stdarg.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
-#include <osl.h>
+#include <linux/sched.h>
+#include <bcmdefs.h>
+#include <stdarg.h>
 #include <bcmutils.h>
 #include <siutils.h>
 #include <bcmnvram.h>
-#include <bcmendian.h>
 #include <bcmdevs.h>
-#include <proto/ethernet.h>
-#include <proto/802.1d.h>
 #include <proto/802.11.h>
 
+/* Global ASSERT type flag */
+u32 g_assert_type;
+
+struct sk_buff *BCMFASTPATH pkt_buf_get_skb(uint len)
+{
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(len);
+	if (skb) {
+		skb_put(skb, len);
+		skb->priority = 0;
+	}
+
+	return skb;
+}
+
+/* Free the driver packet. Free the tag if present */
+void BCMFASTPATH pkt_buf_free_skb(struct sk_buff *skb)
+{
+	struct sk_buff *nskb;
+	int nest = 0;
+
+	ASSERT(skb);
+
+	/* perversion: we use skb->next to chain multi-skb packets */
+	while (skb) {
+		nskb = skb->next;
+		skb->next = NULL;
+
+		if (skb->destructor)
+			/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
+			 * destructor exists
+			 */
+			dev_kfree_skb_any(skb);
+		else
+			/* can free immediately (even in_irq()) if destructor
+			 * does not exist
+			 */
+			dev_kfree_skb(skb);
+
+		nest++;
+		skb = nskb;
+	}
+}
+
 /* copy a buffer into a pkt buffer chain */
-uint pktfrombuf(struct osl_info *osh, struct sk_buff *p, uint offset, int len,
+uint pktfrombuf(struct sk_buff *p, uint offset, int len,
 		unsigned char *buf)
 {
 	uint n, ret = 0;
@@ -51,7 +93,7 @@ uint pktfrombuf(struct osl_info *osh, struct sk_buff *p, uint offset, int len,
 	/* copy the data */
 	for (; p && len; p = p->next) {
 		n = min((uint) (p->len) - offset, (uint) len);
-		bcopy(buf, p->data + offset, n);
+		memcpy(p->data + offset, buf, n);
 		buf += n;
 		len -= n;
 		ret += n;
@@ -61,7 +103,7 @@ uint pktfrombuf(struct osl_info *osh, struct sk_buff *p, uint offset, int len,
 	return ret;
 }
 /* return total length of buffer chain */
-uint BCMFASTPATH pkttotlen(struct osl_info *osh, struct sk_buff *p)
+uint BCMFASTPATH pkttotlen(struct sk_buff *p)
 {
 	uint total;
 
@@ -188,7 +230,7 @@ struct sk_buff *BCMFASTPATH pktq_pdeq_tail(struct pktq *pq, int prec)
 }
 
 #ifdef BRCM_FULLMAC
-void pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir)
+void pktq_pflush(struct pktq *pq, int prec, bool dir)
 {
 	struct pktq_prec *q;
 	struct sk_buff *p;
@@ -198,7 +240,7 @@ void pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir)
 	while (p) {
 		q->head = p->prev;
 		p->prev = NULL;
-		pkt_buf_free_skb(osh, p, dir);
+		pkt_buf_free_skb(p);
 		q->len--;
 		pq->len--;
 		p = q->head;
@@ -207,16 +249,16 @@ void pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir)
 	q->tail = NULL;
 }
 
-void pktq_flush(struct osl_info *osh, struct pktq *pq, bool dir)
+void pktq_flush(struct pktq *pq, bool dir)
 {
 	int prec;
 	for (prec = 0; prec < pq->num_prec; prec++)
-		pktq_pflush(osh, pq, prec, dir);
+		pktq_pflush(pq, prec, dir);
 	ASSERT(pq->len == 0);
 }
 #else /* !BRCM_FULLMAC */
 void
-pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir,
+pktq_pflush(struct pktq *pq, int prec, bool dir,
 	    ifpkt_cb_t fn, int arg)
 {
 	struct pktq_prec *q;
@@ -232,7 +274,7 @@ pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir,
 			else
 				prev->prev = p->prev;
 			p->prev = NULL;
-			pkt_buf_free_skb(osh, p, dir);
+			pkt_buf_free_skb(p);
 			q->len--;
 			pq->len--;
 			p = (head ? q->head : prev->prev);
@@ -248,12 +290,12 @@ pktq_pflush(struct osl_info *osh, struct pktq *pq, int prec, bool dir,
 	}
 }
 
-void pktq_flush(struct osl_info *osh, struct pktq *pq, bool dir,
+void pktq_flush(struct pktq *pq, bool dir,
 		ifpkt_cb_t fn, int arg)
 {
 	int prec;
 	for (prec = 0; prec < pq->num_prec; prec++)
-		pktq_pflush(osh, pq, prec, dir, fn, arg);
+		pktq_pflush(pq, prec, dir, fn, arg);
 	if (fn == NULL)
 		ASSERT(pq->len == 0);
 }
@@ -348,12 +390,12 @@ struct sk_buff *BCMFASTPATH pktq_mdeq(struct pktq *pq, uint prec_bmp,
 }
 
 /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
-int bcm_ether_atoe(char *p, struct ether_addr *ea)
+int bcm_ether_atoe(char *p, u8 *ea)
 {
 	int i = 0;
 
 	for (;;) {
-		ea->octet[i++] = (char)simple_strtoul(p, &p, 16);
+		ea[i++] = (char)simple_strtoul(p, &p, 16);
 		if (!*p++ || i == 6)
 			break;
 	}
@@ -410,12 +452,12 @@ int getintvar(char *vars, const char *name)
 
 #if defined(BCMDBG)
 /* pretty hex print a pkt buffer chain */
-void prpkt(const char *msg, struct osl_info *osh, struct sk_buff *p0)
+void prpkt(const char *msg, struct sk_buff *p0)
 {
 	struct sk_buff *p;
 
 	if (msg && (msg[0] != '\0'))
-		printf("%s:\n", msg);
+		printk(KERN_DEBUG "%s:\n", msg);
 
 	for (p = p0; p; p = p->next)
 		prhex(NULL, p->data, p->len);
@@ -866,7 +908,7 @@ void prhex(const char *msg, unsigned char *buf, uint nbytes)
 	uint i;
 
 	if (msg && (msg[0] != '\0'))
-		printf("%s:\n", msg);
+		printk(KERN_DEBUG "%s:\n", msg);
 
 	p = line;
 	for (i = 0; i < nbytes; i++) {
@@ -882,7 +924,7 @@ void prhex(const char *msg, unsigned char *buf, uint nbytes)
 		}
 
 		if (i % 16 == 15) {
-			printf("%s\n", line);	/* flush line */
+			printk(KERN_DEBUG "%s\n", line);	/* flush line */
 			p = line;
 			len = sizeof(line);
 		}
@@ -890,7 +932,7 @@ void prhex(const char *msg, unsigned char *buf, uint nbytes)
 
 	/* flush last partial line */
 	if (p != line)
-		printf("%s\n", line);
+		printk(KERN_DEBUG "%s\n", line);
 }
 
 char *bcm_chipname(uint chipid, char *buf, uint len)
@@ -1048,3 +1090,49 @@ int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
 	return r;
 }
 
+#if defined(BCMDBG_ASSERT)
+void osl_assert(char *exp, char *file, int line)
+{
+	char tempbuf[256];
+	char *basename;
+
+	basename = strrchr(file, '/');
+	/* skip the '/' */
+	if (basename)
+		basename++;
+
+	if (!basename)
+		basename = file;
+
+	snprintf(tempbuf, 256,
+		 "assertion \"%s\" failed: file \"%s\", line %d\n", exp,
+		 basename, line);
+
+	/*
+	 * Print assert message and give it time to
+	 * be written to /var/log/messages
+	 */
+	if (!in_interrupt()) {
+		const int delay = 3;
+		printk(KERN_ERR "%s", tempbuf);
+		printk(KERN_ERR "panic in %d seconds\n", delay);
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(delay * HZ);
+	}
+
+	switch (g_assert_type) {
+	case 0:
+		panic(KERN_ERR "%s", tempbuf);
+		break;
+	case 1:
+		printk(KERN_ERR "%s", tempbuf);
+		BUG();
+		break;
+	case 2:
+		printk(KERN_ERR "%s", tempbuf);
+		break;
+	default:
+		break;
+	}
+}
+#endif				/* defined(BCMDBG_ASSERT) */
diff --git a/drivers/staging/brcm80211/util/bcmwifi.c b/drivers/staging/brcm80211/util/bcmwifi.c
index 81e54bd..d82c2b2 100644
--- a/drivers/staging/brcm80211/util/bcmwifi.c
+++ b/drivers/staging/brcm80211/util/bcmwifi.c
@@ -15,10 +15,6 @@
  */
 #include <linux/ctype.h>
 #include <linux/kernel.h>
-#ifdef BRCM_FULLMAC
-#include <linux/netdevice.h>
-#endif
-#include <osl.h>
 #include <bcmdefs.h>
 #include <bcmutils.h>
 #include <bcmwifi.h>
@@ -82,29 +78,6 @@ u8 wf_chspec_ctlchan(chanspec_t chspec)
 	return ctl_chan;
 }
 
-chanspec_t wf_chspec_ctlchspec(chanspec_t chspec)
-{
-	chanspec_t ctl_chspec = 0;
-	u8 channel;
-
-	ASSERT(!wf_chspec_malformed(chspec));
-
-	/* Is there a sideband ? */
-	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) {
-		return chspec;
-	} else {
-		if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) {
-			channel = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
-		} else {
-			channel = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
-		}
-		ctl_chspec =
-		    channel | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE;
-		ctl_chspec |= CHSPEC_BAND(chspec);
-	}
-	return ctl_chspec;
-}
-
 /*
  * Return the channel number for a given frequency and base frequency.
  * The returned channel number is relative to the given base frequency.
@@ -161,33 +134,3 @@ int wf_mhz2channel(uint freq, uint start_factor)
 	return ch;
 }
 
-/*
- * Return the center frequency in MHz of the given channel and base frequency.
- * The channel number is interpreted relative to the given base frequency.
- *
- * The valid channel range is [1, 14] in the 2.4 GHz band and [0, 200] otherwise.
- * The base frequency is specified as (start_factor * 500 kHz).
- * Constants WF_CHAN_FACTOR_2_4_G, WF_CHAN_FACTOR_4_G, and WF_CHAN_FACTOR_5_G
- * are defined for 2.4 GHz, 4 GHz, and 5 GHz bands.
- * The channel range of [1, 14] is only checked for a start_factor of
- * WF_CHAN_FACTOR_2_4_G (4814 = 2407 * 2).
- * Odd start_factors produce channels on .5 MHz boundaries, in which case
- * the answer is rounded down to an integral MHz.
- * -1 is returned for an out of range channel.
- *
- * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2
- */
-int wf_channel2mhz(uint ch, uint start_factor)
-{
-	int freq;
-
-	if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) ||
-	    (ch > 200))
-		freq = -1;
-	else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14))
-		freq = 2484;
-	else
-		freq = ch * 5 + start_factor / 2;
-
-	return freq;
-}
diff --git a/drivers/staging/brcm80211/util/hnddma.c b/drivers/staging/brcm80211/util/hnddma.c
index d088692..8a81eb9 100644
--- a/drivers/staging/brcm80211/util/hnddma.c
+++ b/drivers/staging/brcm80211/util/hnddma.c
@@ -20,8 +20,6 @@
 #include <linux/pci.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
-#include <osl.h>
-#include <bcmendian.h>
 #include <hndsoc.h>
 #include <bcmutils.h>
 #include <siutils.h>
@@ -33,6 +31,10 @@
 #include <asm/addrspace.h>
 #endif
 
+#ifdef BRCM_FULLMAC
+#error "hnddma.c shouldn't be needed for FULLMAC"
+#endif
+
 /* debug/trace */
 #ifdef BCMDBG
 #define	DMA_ERROR(args) \
@@ -40,14 +42,14 @@
 		if (!(*di->msg_level & 1)) \
 			; \
 		else \
-			printf args; \
+			printk args; \
 	} while (0)
 #define	DMA_TRACE(args) \
 	do { \
 		if (!(*di->msg_level & 2)) \
 			; \
 		else \
-			printf args; \
+			printk args; \
 	} while (0)
 #else
 #define	DMA_ERROR(args)
@@ -56,11 +58,6 @@
 
 #define	DMA_NONE(args)
 
-#define d32txregs	dregs.d32_u.txregs_32
-#define d32rxregs	dregs.d32_u.rxregs_32
-#define txd32		dregs.d32_u.txd_32
-#define rxd32		dregs.d32_u.rxd_32
-
 #define d64txregs	dregs.d64_u.txregs_64
 #define d64rxregs	dregs.d64_u.rxregs_64
 #define txd64		dregs.d64_u.txd_64
@@ -82,20 +79,13 @@ typedef struct dma_info {
 	uint *msg_level;	/* message level pointer */
 	char name[MAXNAMEL];	/* callers name for diag msgs */
 
-	void *osh;		/* os handle */
-	si_t *sih;		/* sb handle */
+	void *pbus;		/* bus handle */
 
 	bool dma64;		/* this dma engine is operating in 64-bit mode */
 	bool addrext;		/* this dma engine supports DmaExtendedAddrChanges */
 
 	union {
 		struct {
-			dma32regs_t *txregs_32;	/* 32-bit dma tx engine registers */
-			dma32regs_t *rxregs_32;	/* 32-bit dma rx engine registers */
-			dma32dd_t *txd_32;	/* pointer to dma32 tx descriptor ring */
-			dma32dd_t *rxd_32;	/* pointer to dma32 rx descriptor ring */
-		} d32_u;
-		struct {
 			dma64regs_t *txregs_64;	/* 64-bit dma tx engine registers */
 			dma64regs_t *rxregs_64;	/* 64-bit dma rx engine registers */
 			dma64dd_t *txd_64;	/* pointer to dma64 tx descriptor ring */
@@ -109,7 +99,6 @@ typedef struct dma_info {
 	u16 txin;		/* index of next descriptor to reclaim */
 	u16 txout;		/* index of next descriptor to post */
 	void **txp;		/* pointer to parallel array of pointers to packets */
-	osldma_t *tx_dmah;	/* DMA TX descriptor ring handle */
 	hnddma_seg_map_t *txp_dmah;	/* DMA MAP meta-data handle */
 	dmaaddr_t txdpa;	/* Aligned physical address of descriptor ring */
 	dmaaddr_t txdpaorig;	/* Original physical address of descriptor ring */
@@ -124,7 +113,6 @@ typedef struct dma_info {
 	u16 rxin;		/* index of next descriptor to reclaim */
 	u16 rxout;		/* index of next descriptor to post */
 	void **rxp;		/* pointer to parallel array of pointers to packets */
-	osldma_t *rx_dmah;	/* DMA RX descriptor ring handle */
 	hnddma_seg_map_t *rxp_dmah;	/* DMA MAP meta-data handle */
 	dmaaddr_t rxdpa;	/* Aligned physical address of descriptor ring */
 	dmaaddr_t rxdpaorig;	/* Original physical address of descriptor ring */
@@ -151,25 +139,6 @@ typedef struct dma_info {
 	bool aligndesc_4k;	/* descriptor base need to be aligned or not */
 } dma_info_t;
 
-/*
- * If BCMDMA32 is defined, hnddma will support both 32-bit and 64-bit DMA engines.
- * Otherwise it will support only 64-bit.
- *
- * DMA32_ENAB indicates whether hnddma is compiled with support for 32-bit DMA engines.
- * DMA64_ENAB indicates whether hnddma is compiled with support for 64-bit DMA engines.
- *
- * DMA64_MODE indicates whether the current DMA engine is running as 64-bit.
- */
-#ifdef BCMDMA32
-#define	DMA32_ENAB(di)		1
-#define	DMA64_ENAB(di)		1
-#define	DMA64_MODE(di)		((di)->dma64)
-#else				/* !BCMDMA32 */
-#define	DMA32_ENAB(di)		0
-#define	DMA64_ENAB(di)		1
-#define	DMA64_MODE(di)		1
-#endif				/* !BCMDMA32 */
-
 /* DMA Scatter-gather list is supported. Note this is limited to TX direction only */
 #ifdef BCMDMASGLISTOSL
 #define DMASGLIST_ENAB true
@@ -228,31 +197,9 @@ static void _dma_counterreset(dma_info_t *di);
 static void _dma_fifoloopbackenable(dma_info_t *di);
 static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags);
 static u8 dma_align_sizetobits(uint size);
-static void *dma_ringalloc(struct osl_info *osh, u32 boundary, uint size,
+static void *dma_ringalloc(dma_info_t *di, u32 boundary, uint size,
 			   u16 *alignbits, uint *alloced,
-			   dmaaddr_t *descpa, osldma_t **dmah);
-
-/* Prototypes for 32-bit routines */
-static bool dma32_alloc(dma_info_t *di, uint direction);
-static bool dma32_txreset(dma_info_t *di);
-static bool dma32_rxreset(dma_info_t *di);
-static bool dma32_txsuspendedidle(dma_info_t *di);
-static int dma32_txfast(dma_info_t *di, struct sk_buff *p0, bool commit);
-static void *dma32_getnexttxp(dma_info_t *di, txd_range_t range);
-static void *dma32_getnextrxp(dma_info_t *di, bool forceall);
-static void dma32_txrotate(dma_info_t *di);
-static bool dma32_rxidle(dma_info_t *di);
-static void dma32_txinit(dma_info_t *di);
-static bool dma32_txenabled(dma_info_t *di);
-static void dma32_txsuspend(dma_info_t *di);
-static void dma32_txresume(dma_info_t *di);
-static bool dma32_txsuspended(dma_info_t *di);
-static void dma32_txreclaim(dma_info_t *di, txd_range_t range);
-static bool dma32_txstopped(dma_info_t *di);
-static bool dma32_rxstopped(dma_info_t *di);
-static bool dma32_rxenabled(dma_info_t *di);
-
-static bool _dma32_addrext(struct osl_info *osh, dma32regs_t *dma32regs);
+			   dmaaddr_t *descpa);
 
 /* Prototypes for 64-bit routines */
 static bool dma64_alloc(dma_info_t *di, uint direction);
@@ -276,7 +223,7 @@ static void dma64_txreclaim(dma_info_t *di, txd_range_t range);
 static bool dma64_txstopped(dma_info_t *di);
 static bool dma64_rxstopped(dma_info_t *di);
 static bool dma64_rxenabled(dma_info_t *di);
-static bool _dma64_addrext(struct osl_info *osh, dma64regs_t *dma64regs);
+static bool _dma64_addrext(dma64regs_t *dma64regs);
 
 static inline u32 parity32(u32 data);
 
@@ -327,54 +274,7 @@ const di_fcn_t dma64proc = {
 	39
 };
 
-static const di_fcn_t dma32proc = {
-	(di_detach_t) _dma_detach,
-	(di_txinit_t) dma32_txinit,
-	(di_txreset_t) dma32_txreset,
-	(di_txenabled_t) dma32_txenabled,
-	(di_txsuspend_t) dma32_txsuspend,
-	(di_txresume_t) dma32_txresume,
-	(di_txsuspended_t) dma32_txsuspended,
-	(di_txsuspendedidle_t) dma32_txsuspendedidle,
-	(di_txfast_t) dma32_txfast,
-	NULL,
-	NULL,
-	(di_txstopped_t) dma32_txstopped,
-	(di_txreclaim_t) dma32_txreclaim,
-	(di_getnexttxp_t) dma32_getnexttxp,
-	(di_peeknexttxp_t) _dma_peeknexttxp,
-	(di_txblock_t) _dma_txblock,
-	(di_txunblock_t) _dma_txunblock,
-	(di_txactive_t) _dma_txactive,
-	(di_txrotate_t) dma32_txrotate,
-
-	(di_rxinit_t) _dma_rxinit,
-	(di_rxreset_t) dma32_rxreset,
-	(di_rxidle_t) dma32_rxidle,
-	(di_rxstopped_t) dma32_rxstopped,
-	(di_rxenable_t) _dma_rxenable,
-	(di_rxenabled_t) dma32_rxenabled,
-	(di_rx_t) _dma_rx,
-	(di_rxfill_t) _dma_rxfill,
-	(di_rxreclaim_t) _dma_rxreclaim,
-	(di_getnextrxp_t) _dma_getnextrxp,
-	(di_peeknextrxp_t) _dma_peeknextrxp,
-	(di_rxparam_get_t) _dma_rx_param_get,
-
-	(di_fifoloopbackenable_t) _dma_fifoloopbackenable,
-	(di_getvar_t) _dma_getvar,
-	(di_counterreset_t) _dma_counterreset,
-	(di_ctrlflags_t) _dma_ctrlflags,
-	NULL,
-	NULL,
-	NULL,
-	(di_rxactive_t) _dma_rxactive,
-	(di_txpending_t) _dma_txpending,
-	(di_txcommitted_t) _dma_txcommitted,
-	39
-};
-
-struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
+struct hnddma_pub *dma_attach(char *name, si_t *sih,
 		     void *dmaregstx, void *dmaregsrx, uint ntxd,
 		     uint nrxd, uint rxbufsize, int rxextheadroom,
 		     uint nrxpost, uint rxoffset, uint *msg_level)
@@ -386,7 +286,7 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 	di = kzalloc(sizeof(dma_info_t), GFP_ATOMIC);
 	if (di == NULL) {
 #ifdef BCMDBG
-		printf("dma_attach: out of memory\n");
+		printk(KERN_ERR "dma_attach: out of memory\n");
 #endif
 		return NULL;
 	}
@@ -396,11 +296,7 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 	/* old chips w/o sb is no longer supported */
 	ASSERT(sih != NULL);
 
-	if (DMA64_ENAB(di))
-		di->dma64 =
-		    ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
-	else
-		di->dma64 = 0;
+	di->dma64 = ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64);
 
 	/* check arguments */
 	ASSERT(ISPOWEROF2(ntxd));
@@ -412,23 +308,11 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 		ASSERT(dmaregstx == NULL);
 
 	/* init dma reg pointer */
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		ASSERT(ntxd <= D64MAXDD);
-		ASSERT(nrxd <= D64MAXDD);
-		di->d64txregs = (dma64regs_t *) dmaregstx;
-		di->d64rxregs = (dma64regs_t *) dmaregsrx;
-		di->hnddma.di_fn = (const di_fcn_t *)&dma64proc;
-	} else if (DMA32_ENAB(di)) {
-		ASSERT(ntxd <= D32MAXDD);
-		ASSERT(nrxd <= D32MAXDD);
-		di->d32txregs = (dma32regs_t *) dmaregstx;
-		di->d32rxregs = (dma32regs_t *) dmaregsrx;
-		di->hnddma.di_fn = (const di_fcn_t *)&dma32proc;
-	} else {
-		DMA_ERROR(("dma_attach: driver doesn't support 32-bit DMA\n"));
-		ASSERT(0);
-		goto fail;
-	}
+	ASSERT(ntxd <= D64MAXDD);
+	ASSERT(nrxd <= D64MAXDD);
+	di->d64txregs = (dma64regs_t *) dmaregstx;
+	di->d64rxregs = (dma64regs_t *) dmaregsrx;
+	di->hnddma.di_fn = (const di_fcn_t *)&dma64proc;
 
 	/* Default flags (which can be changed by the driver calling dma_ctrlflags
 	 * before enable): For backwards compatibility both Rx Overflow Continue
@@ -438,14 +322,17 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 	di->hnddma.di_fn->ctrlflags(&di->hnddma, DMA_CTRL_ROC | DMA_CTRL_PEN,
 				    0);
 
-	DMA_TRACE(("%s: dma_attach: %s osh %p flags 0x%x ntxd %d nrxd %d rxbufsize %d " "rxextheadroom %d nrxpost %d rxoffset %d dmaregstx %p dmaregsrx %p\n", name, (DMA64_MODE(di) ? "DMA64" : "DMA32"), osh, di->hnddma.dmactrlflags, ntxd, nrxd, rxbufsize, rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
+	DMA_TRACE(("%s: dma_attach: %s flags 0x%x ntxd %d nrxd %d "
+		   "rxbufsize %d rxextheadroom %d nrxpost %d rxoffset %d "
+		   "dmaregstx %p dmaregsrx %p\n", name, "DMA64",
+		   di->hnddma.dmactrlflags, ntxd, nrxd, rxbufsize,
+		   rxextheadroom, nrxpost, rxoffset, dmaregstx, dmaregsrx));
 
 	/* make a private copy of our callers name */
 	strncpy(di->name, name, MAXNAMEL);
 	di->name[MAXNAMEL - 1] = '\0';
 
-	di->osh = osh;
-	di->sih = sih;
+	di->pbus = ((struct si_info *)sih)->pbus;
 
 	/* save tunables */
 	di->ntxd = (u16) ntxd;
@@ -472,15 +359,9 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 	di->dataoffsetlow = 0;
 	/* for pci bus, add offset */
 	if (sih->bustype == PCI_BUS) {
-		if ((sih->buscoretype == PCIE_CORE_ID) && DMA64_MODE(di)) {
-			/* pcie with DMA64 */
-			di->ddoffsetlow = 0;
-			di->ddoffsethigh = SI_PCIE_DMA_H32;
-		} else {
-			/* pci(DMA32/DMA64) or pcie with DMA32 */
-			di->ddoffsetlow = SI_PCI_DMA;
-			di->ddoffsethigh = 0;
-		}
+		/* pcie with DMA64 */
+		di->ddoffsetlow = 0;
+		di->ddoffsethigh = SI_PCIE_DMA_H32;
 		di->dataoffsetlow = di->ddoffsetlow;
 		di->dataoffsethigh = di->ddoffsethigh;
 	}
@@ -500,14 +381,11 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 	/* does the descriptors need to be aligned and if yes, on 4K/8K or not */
 	di->aligndesc_4k = _dma_descriptor_align(di);
 	if (di->aligndesc_4k) {
-		if (DMA64_MODE(di)) {
-			di->dmadesc_align = D64RINGALIGN_BITS;
-			if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
-				/* for smaller dd table, HW relax the alignment requirement */
-				di->dmadesc_align = D64RINGALIGN_BITS - 1;
-			}
-		} else
-			di->dmadesc_align = D32RINGALIGN_BITS;
+		di->dmadesc_align = D64RINGALIGN_BITS;
+		if ((ntxd < D64MAXDD / 2) && (nrxd < D64MAXDD / 2)) {
+			/* for smaller dd table, HW relax alignment reqmnt */
+			di->dmadesc_align = D64RINGALIGN_BITS - 1;
+		}
 	} else
 		di->dmadesc_align = 4;	/* 16 byte alignment */
 
@@ -583,32 +461,6 @@ struct hnddma_pub *dma_attach(struct osl_info *osh, char *name, si_t *sih,
 	return NULL;
 }
 
-/* init the tx or rx descriptor */
-static inline void
-dma32_dd_upd(dma_info_t *di, dma32dd_t *ddring, dmaaddr_t pa, uint outidx,
-	     u32 *flags, u32 bufcount)
-{
-	/* dma32 uses 32-bit control to fit both flags and bufcounter */
-	*flags = *flags | (bufcount & CTRL_BC_MASK);
-
-	if ((di->dataoffsetlow == 0) || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-		W_SM(&ddring[outidx].addr,
-		     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
-		W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags));
-	} else {
-		/* address extension */
-		u32 ae;
-		ASSERT(di->addrext);
-		ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >> PCI32ADDR_HIGH_SHIFT;
-		PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
-		*flags |= (ae << CTRL_AE_SHIFT);
-		W_SM(&ddring[outidx].addr,
-		     BUS_SWAP32(PHYSADDRLO(pa) + di->dataoffsetlow));
-		W_SM(&ddring[outidx].ctrl, BUS_SWAP32(*flags));
-	}
-}
-
 /* Check for odd number of 1's */
 static inline u32 parity32(u32 data)
 {
@@ -669,24 +521,21 @@ dma64_dd_upd(dma_info_t *di, dma64dd_t *ddring, dmaaddr_t pa, uint outidx,
 	}
 }
 
-static bool _dma32_addrext(struct osl_info *osh, dma32regs_t *dma32regs)
+static bool _dma_alloc(dma_info_t *di, uint direction)
 {
-	u32 w;
-
-	OR_REG(osh, &dma32regs->control, XC_AE);
-	w = R_REG(osh, &dma32regs->control);
-	AND_REG(osh, &dma32regs->control, ~XC_AE);
-	return (w & XC_AE) == XC_AE;
+	return dma64_alloc(di, direction);
 }
 
-static bool _dma_alloc(dma_info_t *di, uint direction)
+void *dma_alloc_consistent(struct pci_dev *pdev, uint size, u16 align_bits,
+			       uint *alloced, unsigned long *pap)
 {
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		return dma64_alloc(di, direction);
-	} else if (DMA32_ENAB(di)) {
-		return dma32_alloc(di, direction);
-	} else
-		ASSERT(0);
+	if (align_bits) {
+		u16 align = (1 << align_bits);
+		if (!IS_ALIGNED(PAGE_SIZE, align))
+			size += align;
+		*alloced = size;
+	}
+	return pci_alloc_consistent(pdev, size, (dma_addr_t *) pap);
 }
 
 /* !! may be called with core in reset */
@@ -700,67 +549,45 @@ static void _dma_detach(dma_info_t *di)
 	ASSERT(di->rxin == di->rxout);
 
 	/* free dma descriptor rings */
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		if (di->txd64)
-			DMA_FREE_CONSISTENT(di->osh,
-					    ((s8 *)di->txd64 -
-					     di->txdalign), di->txdalloc,
-					    (di->txdpaorig), &di->tx_dmah);
-		if (di->rxd64)
-			DMA_FREE_CONSISTENT(di->osh,
-					    ((s8 *)di->rxd64 -
-					     di->rxdalign), di->rxdalloc,
-					    (di->rxdpaorig), &di->rx_dmah);
-	} else if (DMA32_ENAB(di)) {
-		if (di->txd32)
-			DMA_FREE_CONSISTENT(di->osh,
-					    ((s8 *)di->txd32 -
-					     di->txdalign), di->txdalloc,
-					    (di->txdpaorig), &di->tx_dmah);
-		if (di->rxd32)
-			DMA_FREE_CONSISTENT(di->osh,
-					    ((s8 *)di->rxd32 -
-					     di->rxdalign), di->rxdalloc,
-					    (di->rxdpaorig), &di->rx_dmah);
-	} else
-		ASSERT(0);
+	if (di->txd64)
+		pci_free_consistent(di->pbus, di->txdalloc,
+				    ((s8 *)di->txd64 - di->txdalign),
+				    (di->txdpaorig));
+	if (di->rxd64)
+		pci_free_consistent(di->pbus, di->rxdalloc,
+				    ((s8 *)di->rxd64 - di->rxdalign),
+				    (di->rxdpaorig));
 
 	/* free packet pointer vectors */
-	if (di->txp)
-		kfree((void *)di->txp);
-	if (di->rxp)
-		kfree((void *)di->rxp);
+	kfree(di->txp);
+	kfree(di->rxp);
 
 	/* free tx packet DMA handles */
-	if (di->txp_dmah)
-		kfree(di->txp_dmah);
+	kfree(di->txp_dmah);
 
 	/* free rx packet DMA handles */
-	if (di->rxp_dmah)
-		kfree(di->rxp_dmah);
+	kfree(di->rxp_dmah);
 
 	/* free our private info structure */
-	kfree((void *)di);
+	kfree(di);
 
 }
 
 static bool _dma_descriptor_align(dma_info_t *di)
 {
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		u32 addrl;
-
-		/* Check to see if the descriptors need to be aligned on 4K/8K or not */
-		if (di->d64txregs != NULL) {
-			W_REG(di->osh, &di->d64txregs->addrlow, 0xff0);
-			addrl = R_REG(di->osh, &di->d64txregs->addrlow);
-			if (addrl != 0)
-				return false;
-		} else if (di->d64rxregs != NULL) {
-			W_REG(di->osh, &di->d64rxregs->addrlow, 0xff0);
-			addrl = R_REG(di->osh, &di->d64rxregs->addrlow);
-			if (addrl != 0)
-				return false;
-		}
+	u32 addrl;
+
+	/* Check to see if the descriptors need to be aligned on 4K/8K or not */
+	if (di->d64txregs != NULL) {
+		W_REG(&di->d64txregs->addrlow, 0xff0);
+		addrl = R_REG(&di->d64txregs->addrlow);
+		if (addrl != 0)
+			return false;
+	} else if (di->d64rxregs != NULL) {
+		W_REG(&di->d64rxregs->addrlow, 0xff0);
+		addrl = R_REG(&di->d64rxregs->addrlow);
+		if (addrl != 0)
+			return false;
 	}
 	return true;
 }
@@ -768,133 +595,84 @@ static bool _dma_descriptor_align(dma_info_t *di)
 /* return true if this dma engine supports DmaExtendedAddrChanges, otherwise false */
 static bool _dma_isaddrext(dma_info_t *di)
 {
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		/* DMA64 supports full 32- or 64-bit operation. AE is always valid */
-
-		/* not all tx or rx channel are available */
-		if (di->d64txregs != NULL) {
-			if (!_dma64_addrext(di->osh, di->d64txregs)) {
-				DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have AE set\n", di->name));
-				ASSERT(0);
-			}
-			return true;
-		} else if (di->d64rxregs != NULL) {
-			if (!_dma64_addrext(di->osh, di->d64rxregs)) {
-				DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have AE set\n", di->name));
-				ASSERT(0);
-			}
-			return true;
-		}
-		return false;
-	} else if (DMA32_ENAB(di)) {
-		if (di->d32txregs)
-			return _dma32_addrext(di->osh, di->d32txregs);
-		else if (di->d32rxregs)
-			return _dma32_addrext(di->osh, di->d32rxregs);
-	} else
-		ASSERT(0);
+	/* DMA64 supports full 32- or 64-bit operation. AE is always valid */
 
+	/* not all tx or rx channel are available */
+	if (di->d64txregs != NULL) {
+		if (!_dma64_addrext(di->d64txregs)) {
+			DMA_ERROR(("%s: _dma_isaddrext: DMA64 tx doesn't have "
+				   "AE set\n", di->name));
+			ASSERT(0);
+		}
+		return true;
+	} else if (di->d64rxregs != NULL) {
+		if (!_dma64_addrext(di->d64rxregs)) {
+			DMA_ERROR(("%s: _dma_isaddrext: DMA64 rx doesn't have "
+				   "AE set\n", di->name));
+			ASSERT(0);
+		}
+		return true;
+	}
 	return false;
 }
 
 /* initialize descriptor table base address */
 static void _dma_ddtable_init(dma_info_t *di, uint direction, dmaaddr_t pa)
 {
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		if (!di->aligndesc_4k) {
-			if (direction == DMA_TX)
-				di->xmtptrbase = PHYSADDRLO(pa);
-			else
-				di->rcvptrbase = PHYSADDRLO(pa);
-		}
+	if (!di->aligndesc_4k) {
+		if (direction == DMA_TX)
+			di->xmtptrbase = PHYSADDRLO(pa);
+		else
+			di->rcvptrbase = PHYSADDRLO(pa);
+	}
 
-		if ((di->ddoffsetlow == 0)
-		    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-			if (direction == DMA_TX) {
-				W_REG(di->osh, &di->d64txregs->addrlow,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-				W_REG(di->osh, &di->d64txregs->addrhigh,
-				      (PHYSADDRHI(pa) + di->ddoffsethigh));
-			} else {
-				W_REG(di->osh, &di->d64rxregs->addrlow,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-				W_REG(di->osh, &di->d64rxregs->addrhigh,
-				      (PHYSADDRHI(pa) + di->ddoffsethigh));
-			}
+	if ((di->ddoffsetlow == 0)
+	    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
+		if (direction == DMA_TX) {
+			W_REG(&di->d64txregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64txregs->addrhigh,
+			      (PHYSADDRHI(pa) + di->ddoffsethigh));
 		} else {
-			/* DMA64 32bits address extension */
-			u32 ae;
-			ASSERT(di->addrext);
-			ASSERT(PHYSADDRHI(pa) == 0);
-
-			/* shift the high bit(s) from pa to ae */
-			ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
-			    PCI32ADDR_HIGH_SHIFT;
-			PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
-			if (direction == DMA_TX) {
-				W_REG(di->osh, &di->d64txregs->addrlow,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-				W_REG(di->osh, &di->d64txregs->addrhigh,
-				      di->ddoffsethigh);
-				SET_REG(di->osh, &di->d64txregs->control,
-					D64_XC_AE, (ae << D64_XC_AE_SHIFT));
-			} else {
-				W_REG(di->osh, &di->d64rxregs->addrlow,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-				W_REG(di->osh, &di->d64rxregs->addrhigh,
-				      di->ddoffsethigh);
-				SET_REG(di->osh, &di->d64rxregs->control,
-					D64_RC_AE, (ae << D64_RC_AE_SHIFT));
-			}
+			W_REG(&di->d64rxregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64rxregs->addrhigh,
+				(PHYSADDRHI(pa) + di->ddoffsethigh));
 		}
-
-	} else if (DMA32_ENAB(di)) {
+	} else {
+		/* DMA64 32bits address extension */
+		u32 ae;
+		ASSERT(di->addrext);
 		ASSERT(PHYSADDRHI(pa) == 0);
-		if ((di->ddoffsetlow == 0)
-		    || !(PHYSADDRLO(pa) & PCI32ADDR_HIGH)) {
-			if (direction == DMA_TX)
-				W_REG(di->osh, &di->d32txregs->addr,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-			else
-				W_REG(di->osh, &di->d32rxregs->addr,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
+
+		/* shift the high bit(s) from pa to ae */
+		ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
+		    PCI32ADDR_HIGH_SHIFT;
+		PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
+
+		if (direction == DMA_TX) {
+			W_REG(&di->d64txregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64txregs->addrhigh,
+			      di->ddoffsethigh);
+			SET_REG(&di->d64txregs->control,
+				D64_XC_AE, (ae << D64_XC_AE_SHIFT));
 		} else {
-			/* dma32 address extension */
-			u32 ae;
-			ASSERT(di->addrext);
-
-			/* shift the high bit(s) from pa to ae */
-			ae = (PHYSADDRLO(pa) & PCI32ADDR_HIGH) >>
-			    PCI32ADDR_HIGH_SHIFT;
-			PHYSADDRLO(pa) &= ~PCI32ADDR_HIGH;
-
-			if (direction == DMA_TX) {
-				W_REG(di->osh, &di->d32txregs->addr,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-				SET_REG(di->osh, &di->d32txregs->control, XC_AE,
-					ae << XC_AE_SHIFT);
-			} else {
-				W_REG(di->osh, &di->d32rxregs->addr,
-				      (PHYSADDRLO(pa) + di->ddoffsetlow));
-				SET_REG(di->osh, &di->d32rxregs->control, RC_AE,
-					ae << RC_AE_SHIFT);
-			}
+			W_REG(&di->d64rxregs->addrlow,
+			      (PHYSADDRLO(pa) + di->ddoffsetlow));
+			W_REG(&di->d64rxregs->addrhigh,
+			      di->ddoffsethigh);
+			SET_REG(&di->d64rxregs->control,
+				D64_RC_AE, (ae << D64_RC_AE_SHIFT));
 		}
-	} else
-		ASSERT(0);
+	}
 }
 
 static void _dma_fifoloopbackenable(dma_info_t *di)
 {
 	DMA_TRACE(("%s: dma_fifoloopbackenable\n", di->name));
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di))
-		OR_REG(di->osh, &di->d64txregs->control, D64_XC_LE);
-	else if (DMA32_ENAB(di))
-		OR_REG(di->osh, &di->d32txregs->control, XC_LE);
-	else
-		ASSERT(0);
+	OR_REG(&di->d64txregs->control, D64_XC_LE);
 }
 
 static void _dma_rxinit(dma_info_t *di)
@@ -907,62 +685,40 @@ static void _dma_rxinit(dma_info_t *di)
 	di->rxin = di->rxout = 0;
 
 	/* clear rx descriptor ring */
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		memset((void *)di->rxd64, '\0',
-			 (di->nrxd * sizeof(dma64dd_t)));
+	memset((void *)di->rxd64, '\0',
+		(di->nrxd * sizeof(dma64dd_t)));
 
-		/* DMA engine with out alignment requirement requires table to be inited
-		 * before enabling the engine
-		 */
-		if (!di->aligndesc_4k)
-			_dma_ddtable_init(di, DMA_RX, di->rxdpa);
+	/* DMA engine with out alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (!di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
 
-		_dma_rxenable(di);
+	_dma_rxenable(di);
 
-		if (di->aligndesc_4k)
-			_dma_ddtable_init(di, DMA_RX, di->rxdpa);
-	} else if (DMA32_ENAB(di)) {
-		memset((void *)di->rxd32, '\0',
-			 (di->nrxd * sizeof(dma32dd_t)));
-		_dma_rxenable(di);
+	if (di->aligndesc_4k)
 		_dma_ddtable_init(di, DMA_RX, di->rxdpa);
-	} else
-		ASSERT(0);
 }
 
 static void _dma_rxenable(dma_info_t *di)
 {
 	uint dmactrlflags = di->hnddma.dmactrlflags;
+	u32 control;
 
 	DMA_TRACE(("%s: dma_rxenable\n", di->name));
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		u32 control =
-		    (R_REG(di->osh, &di->d64rxregs->control) & D64_RC_AE) |
-		    D64_RC_RE;
+	control =
+	    (R_REG(&di->d64rxregs->control) & D64_RC_AE) |
+	    D64_RC_RE;
 
-		if ((dmactrlflags & DMA_CTRL_PEN) == 0)
-			control |= D64_RC_PD;
+	if ((dmactrlflags & DMA_CTRL_PEN) == 0)
+		control |= D64_RC_PD;
 
-		if (dmactrlflags & DMA_CTRL_ROC)
-			control |= D64_RC_OC;
+	if (dmactrlflags & DMA_CTRL_ROC)
+		control |= D64_RC_OC;
 
-		W_REG(di->osh, &di->d64rxregs->control,
-		      ((di->rxoffset << D64_RC_RO_SHIFT) | control));
-	} else if (DMA32_ENAB(di)) {
-		u32 control =
-		    (R_REG(di->osh, &di->d32rxregs->control) & RC_AE) | RC_RE;
-
-		if ((dmactrlflags & DMA_CTRL_PEN) == 0)
-			control |= RC_PD;
-
-		if (dmactrlflags & DMA_CTRL_ROC)
-			control |= RC_OC;
-
-		W_REG(di->osh, &di->d32rxregs->control,
-		      ((di->rxoffset << RC_RO_SHIFT) | control));
-	} else
-		ASSERT(0);
+	W_REG(&di->d64rxregs->control,
+		((di->rxoffset << D64_RC_RO_SHIFT) | control));
 }
 
 static void
@@ -994,7 +750,7 @@ static void *BCMFASTPATH _dma_rx(dma_info_t *di)
 	if (head == NULL)
 		return NULL;
 
-	len = ltoh16(*(u16 *) (head->data));
+	len = le16_to_cpu(*(u16 *) (head->data));
 	DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
 
 #if defined(__mips__)
@@ -1003,7 +759,7 @@ static void *BCMFASTPATH _dma_rx(dma_info_t *di)
 		while (!(len = *(u16 *) OSL_UNCACHED(head->data)))
 			udelay(1);
 
-		*(u16 *) (head->data) = htol16((u16) len);
+		*(u16 *) (head->data) = cpu_to_le16((u16) len);
 	}
 #endif				/* defined(__mips__) */
 
@@ -1028,14 +784,11 @@ static void *BCMFASTPATH _dma_rx(dma_info_t *di)
 		if (resid > 0) {
 			uint cur;
 			ASSERT(p == NULL);
-			cur = (DMA64_ENAB(di) && DMA64_MODE(di)) ?
-			    B2I(((R_REG(di->osh, &di->d64rxregs->status0) &
+			cur =
+			    B2I(((R_REG(&di->d64rxregs->status0) &
 				  D64_RS0_CD_MASK) -
 				 di->rcvptrbase) & D64_RS0_CD_MASK,
-				dma64dd_t) : B2I(R_REG(di->osh,
-						       &di->d32rxregs->
-						       status) & RS_CD_MASK,
-						 dma32dd_t);
+				dma64dd_t);
 			DMA_ERROR(("_dma_rx, rxin %d rxout %d, hw_curr %d\n",
 				   di->rxin, di->rxout, cur));
 		}
@@ -1044,7 +797,7 @@ static void *BCMFASTPATH _dma_rx(dma_info_t *di)
 		if ((di->hnddma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
 			DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
 				   di->name, len));
-			pkt_buf_free_skb(di->osh, head, false);
+			pkt_buf_free_skb(head);
 			di->hnddma.rxgiants++;
 			goto next_frame;
 		}
@@ -1092,24 +845,15 @@ static bool BCMFASTPATH _dma_rxfill(dma_info_t *di)
 		   size to be allocated
 		 */
 
-		p = pkt_buf_get_skb(di->osh, di->rxbufsize + extra_offset);
+		p = pkt_buf_get_skb(di->rxbufsize + extra_offset);
 
 		if (p == NULL) {
 			DMA_ERROR(("%s: dma_rxfill: out of rxbufs\n",
 				   di->name));
-			if (i == 0) {
-				if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-					if (dma64_rxidle(di)) {
-						DMA_ERROR(("%s: rxfill64: ring is empty !\n", di->name));
-						ring_empty = true;
-					}
-				} else if (DMA32_ENAB(di)) {
-					if (dma32_rxidle(di)) {
-						DMA_ERROR(("%s: rxfill32: ring is empty !\n", di->name));
-						ring_empty = true;
-					}
-				} else
-					ASSERT(0);
+			if (i == 0 && dma64_rxidle(di)) {
+				DMA_ERROR(("%s: rxfill64: ring is empty !\n",
+					   di->name));
+				ring_empty = true;
 			}
 			di->hnddma.rxnobuf++;
 			break;
@@ -1127,8 +871,8 @@ static bool BCMFASTPATH _dma_rxfill(dma_info_t *di)
 			memset(&di->rxp_dmah[rxout], 0,
 				sizeof(hnddma_seg_map_t));
 
-		pa = DMA_MAP(di->osh, p->data,
-			     di->rxbufsize, DMA_RX, p, &di->rxp_dmah[rxout]);
+		pa = pci_map_single(di->pbus, p->data,
+			di->rxbufsize, PCI_DMA_FROMDEVICE);
 
 		ASSERT(IS_ALIGNED(PHYSADDRLO(pa), 4));
 
@@ -1138,34 +882,19 @@ static bool BCMFASTPATH _dma_rxfill(dma_info_t *di)
 
 		/* reset flags for each descriptor */
 		flags = 0;
-		if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-			if (rxout == (di->nrxd - 1))
-				flags = D64_CTRL1_EOT;
-
-			dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
-				     di->rxbufsize);
-		} else if (DMA32_ENAB(di)) {
-			if (rxout == (di->nrxd - 1))
-				flags = CTRL_EOT;
-
-			ASSERT(PHYSADDRHI(pa) == 0);
-			dma32_dd_upd(di, di->rxd32, pa, rxout, &flags,
-				     di->rxbufsize);
-		} else
-			ASSERT(0);
+		if (rxout == (di->nrxd - 1))
+			flags = D64_CTRL1_EOT;
+
+		dma64_dd_upd(di, di->rxd64, pa, rxout, &flags,
+			     di->rxbufsize);
 		rxout = NEXTRXD(rxout);
 	}
 
 	di->rxout = rxout;
 
 	/* update the chip lastdscr pointer */
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		W_REG(di->osh, &di->d64rxregs->ptr,
-		      di->rcvptrbase + I2B(rxout, dma64dd_t));
-	} else if (DMA32_ENAB(di)) {
-		W_REG(di->osh, &di->d32rxregs->ptr, I2B(rxout, dma32dd_t));
-	} else
-		ASSERT(0);
+	W_REG(&di->d64rxregs->ptr,
+	      di->rcvptrbase + I2B(rxout, dma64dd_t));
 
 	return ring_empty;
 }
@@ -1178,17 +907,10 @@ static void *_dma_peeknexttxp(dma_info_t *di)
 	if (di->ntxd == 0)
 		return NULL;
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		end =
-		    B2I(((R_REG(di->osh, &di->d64txregs->status0) &
-			  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
-			dma64dd_t);
-	} else if (DMA32_ENAB(di)) {
-		end =
-		    B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK,
-			dma32dd_t);
-	} else
-		ASSERT(0);
+	end =
+	    B2I(((R_REG(&di->d64txregs->status0) &
+		  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
+		  dma64dd_t);
 
 	for (i = di->txin; i != end; i = NEXTTXD(i))
 		if (di->txp[i])
@@ -1205,17 +927,10 @@ static void *_dma_peeknextrxp(dma_info_t *di)
 	if (di->nrxd == 0)
 		return NULL;
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		end =
-		    B2I(((R_REG(di->osh, &di->d64rxregs->status0) &
-			  D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
-			dma64dd_t);
-	} else if (DMA32_ENAB(di)) {
-		end =
-		    B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK,
-			dma32dd_t);
-	} else
-		ASSERT(0);
+	end =
+	    B2I(((R_REG(&di->d64rxregs->status0) &
+		  D64_RS0_CD_MASK) - di->rcvptrbase) & D64_RS0_CD_MASK,
+		  dma64dd_t);
 
 	for (i = di->rxin; i != end; i = NEXTRXD(i))
 		if (di->rxp[i])
@@ -1231,7 +946,7 @@ static void _dma_rxreclaim(dma_info_t *di)
 	DMA_TRACE(("%s: dma_rxreclaim\n", di->name));
 
 	while ((p = _dma_getnextrxp(di, true)))
-		pkt_buf_free_skb(di->osh, p, false);
+		pkt_buf_free_skb(p);
 }
 
 static void *BCMFASTPATH _dma_getnextrxp(dma_info_t *di, bool forceall)
@@ -1239,12 +954,7 @@ static void *BCMFASTPATH _dma_getnextrxp(dma_info_t *di, bool forceall)
 	if (di->nrxd == 0)
 		return NULL;
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		return dma64_getnextrxp(di, forceall);
-	} else if (DMA32_ENAB(di)) {
-		return dma32_getnextrxp(di, forceall);
-	} else
-		ASSERT(0);
+	return dma64_getnextrxp(di, forceall);
 }
 
 static void _dma_txblock(dma_info_t *di)
@@ -1266,17 +976,10 @@ static uint _dma_txpending(dma_info_t *di)
 {
 	uint curr;
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		curr =
-		    B2I(((R_REG(di->osh, &di->d64txregs->status0) &
-			  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
-			dma64dd_t);
-	} else if (DMA32_ENAB(di)) {
-		curr =
-		    B2I(R_REG(di->osh, &di->d32txregs->status) & XS_CD_MASK,
-			dma32dd_t);
-	} else
-		ASSERT(0);
+	curr =
+	    B2I(((R_REG(&di->d64txregs->status0) &
+		  D64_XS0_CD_MASK) - di->xmtptrbase) & D64_XS0_CD_MASK,
+		  dma64dd_t);
 
 	return NTXDACTIVE(curr, di->txout);
 }
@@ -1289,12 +992,7 @@ static uint _dma_txcommitted(dma_info_t *di)
 	if (txin == di->txout)
 		return 0;
 
-	if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-		ptr = B2I(R_REG(di->osh, &di->d64txregs->ptr), dma64dd_t);
-	} else if (DMA32_ENAB(di)) {
-		ptr = B2I(R_REG(di->osh, &di->d32txregs->ptr), dma32dd_t);
-	} else
-		ASSERT(0);
+	ptr = B2I(R_REG(&di->d64txregs->ptr), dma64dd_t);
 
 	return NTXDACTIVE(di->txin, ptr);
 }
@@ -1330,33 +1028,19 @@ static uint _dma_ctrlflags(dma_info_t *di, uint mask, uint flags)
 	if (dmactrlflags & DMA_CTRL_PEN) {
 		u32 control;
 
-		if (DMA64_ENAB(di) && DMA64_MODE(di)) {
-			control = R_REG(di->osh, &di->d64txregs->control);
-			W_REG(di->osh, &di->d64txregs->control,
-			      control | D64_XC_PD);
-			if (R_REG(di->osh, &di->d64txregs->control) & D64_XC_PD) {
-				/* We *can* disable it so it is supported,
-				 * restore control register
-				 */
-				W_REG(di->osh, &di->d64txregs->control,
-				      control);
-			} else {
-				/* Not supported, don't allow it to be enabled */
-				dmactrlflags &= ~DMA_CTRL_PEN;
-			}
-		} else if (DMA32_ENAB(di)) {
-			control = R_REG(di->osh, &di->d32txregs->control);
-			W_REG(di->osh, &di->d32txregs->control,
-			      control | XC_PD);
-			if (R_REG(di->osh, &di->d32txregs->control) & XC_PD) {
-				W_REG(di->osh, &di->d32txregs->control,
-				      control);
-			} else {
-				/* Not supported, don't allow it to be enabled */
-				dmactrlflags &= ~DMA_CTRL_PEN;
-			}
-		} else
-			ASSERT(0);
+		control = R_REG(&di->d64txregs->control);
+		W_REG(&di->d64txregs->control,
+		      control | D64_XC_PD);
+		if (R_REG(&di->d64txregs->control) & D64_XC_PD) {
+			/* We *can* disable it so it is supported,
+			 * restore control register
+			 */
+			W_REG(&di->d64txregs->control,
+			control);
+		} else {
+			/* Not supported, don't allow it to be enabled */
+			dmactrlflags &= ~DMA_CTRL_PEN;
+		}
 	}
 
 	di->hnddma.dmactrlflags = dmactrlflags;
@@ -1375,11 +1059,6 @@ static unsigned long _dma_getvar(dma_info_t *di, const char *name)
 	return 0;
 }
 
-void dma_txpioloopback(struct osl_info *osh, dma32regs_t *regs)
-{
-	OR_REG(osh, &regs->control, XC_LE);
-}
-
 static
 u8 dma_align_sizetobits(uint size)
 {
@@ -1398,16 +1077,16 @@ u8 dma_align_sizetobits(uint size)
  * descriptor ring size aligned location. This will ensure that the ring will
  * not cross page boundary
  */
-static void *dma_ringalloc(struct osl_info *osh, u32 boundary, uint size,
+static void *dma_ringalloc(dma_info_t *di, u32 boundary, uint size,
 			   u16 *alignbits, uint *alloced,
-			   dmaaddr_t *descpa, osldma_t **dmah)
+			   dmaaddr_t *descpa)
 {
 	void *va;
 	u32 desc_strtaddr;
 	u32 alignbytes = 1 << *alignbits;
 
-	va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced, descpa,
-		dmah);
+	va = dma_alloc_consistent(di->pbus, size, *alignbits, alloced, descpa);
+
 	if (NULL == va)
 		return NULL;
 
@@ -1415,18 +1094,18 @@ static void *dma_ringalloc(struct osl_info *osh, u32 boundary, uint size,
 	if (((desc_strtaddr + size - 1) & boundary) != (desc_strtaddr
 							& boundary)) {
 		*alignbits = dma_align_sizetobits(size);
-		DMA_FREE_CONSISTENT(osh, va, size, *descpa, dmah);
-		va = DMA_ALLOC_CONSISTENT(osh, size, *alignbits, alloced,
-					  descpa, dmah);
+		pci_free_consistent(di->pbus, size, va, *descpa);
+		va = dma_alloc_consistent(di->pbus, size, *alignbits,
+			alloced, descpa);
 	}
 	return va;
 }
 
-/* 32-bit DMA functions */
+/* 64-bit DMA functions */
 
-static void dma32_txinit(dma_info_t *di)
+static void dma64_txinit(dma_info_t *di)
 {
-	u32 control = XC_XE;
+	u32 control = D64_XC_XE;
 
 	DMA_TRACE(("%s: dma_txinit\n", di->name));
 
@@ -1437,50 +1116,62 @@ static void dma32_txinit(dma_info_t *di)
 	di->hnddma.txavail = di->ntxd - 1;
 
 	/* clear tx descriptor ring */
-	memset((void *)di->txd32, '\0', (di->ntxd * sizeof(dma32dd_t)));
+	memset((void *)di->txd64, '\0', (di->ntxd * sizeof(dma64dd_t)));
+
+	/* DMA engine with out alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (!di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_TX, di->txdpa);
 
 	if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0)
-		control |= XC_PD;
-	W_REG(di->osh, &di->d32txregs->control, control);
-	_dma_ddtable_init(di, DMA_TX, di->txdpa);
+		control |= D64_XC_PD;
+	OR_REG(&di->d64txregs->control, control);
+
+	/* DMA engine with alignment requirement requires table to be inited
+	 * before enabling the engine
+	 */
+	if (di->aligndesc_4k)
+		_dma_ddtable_init(di, DMA_TX, di->txdpa);
 }
 
-static bool dma32_txenabled(dma_info_t *di)
+static bool dma64_txenabled(dma_info_t *di)
 {
 	u32 xc;
 
 	/* If the chip is dead, it is not enabled :-) */
-	xc = R_REG(di->osh, &di->d32txregs->control);
-	return (xc != 0xffffffff) && (xc & XC_XE);
+	xc = R_REG(&di->d64txregs->control);
+	return (xc != 0xffffffff) && (xc & D64_XC_XE);
 }
 
-static void dma32_txsuspend(dma_info_t *di)
+static void dma64_txsuspend(dma_info_t *di)
 {
 	DMA_TRACE(("%s: dma_txsuspend\n", di->name));
 
 	if (di->ntxd == 0)
 		return;
 
-	OR_REG(di->osh, &di->d32txregs->control, XC_SE);
+	OR_REG(&di->d64txregs->control, D64_XC_SE);
 }
 
-static void dma32_txresume(dma_info_t *di)
+static void dma64_txresume(dma_info_t *di)
 {
 	DMA_TRACE(("%s: dma_txresume\n", di->name));
 
 	if (di->ntxd == 0)
 		return;
 
-	AND_REG(di->osh, &di->d32txregs->control, ~XC_SE);
+	AND_REG(&di->d64txregs->control, ~D64_XC_SE);
 }
 
-static bool dma32_txsuspended(dma_info_t *di)
+static bool dma64_txsuspended(dma_info_t *di)
 {
-	return (di->ntxd == 0)
-	    || ((R_REG(di->osh, &di->d32txregs->control) & XC_SE) == XC_SE);
+	return (di->ntxd == 0) ||
+	    ((R_REG(&di->d64txregs->control) & D64_XC_SE) ==
+	     D64_XC_SE);
 }
 
-static void dma32_txreclaim(dma_info_t *di, txd_range_t range)
+static void BCMFASTPATH dma64_txreclaim(dma_info_t *di, txd_range_t range)
 {
 	void *p;
 
@@ -1493,86 +1184,82 @@ static void dma32_txreclaim(dma_info_t *di, txd_range_t range)
 	if (di->txin == di->txout)
 		return;
 
-	while ((p = dma32_getnexttxp(di, range)))
-		pkt_buf_free_skb(di->osh, p, true);
+	while ((p = dma64_getnexttxp(di, range))) {
+		/* For unframed data, we don't have any packets to free */
+		if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED))
+			pkt_buf_free_skb(p);
+	}
 }
 
-static bool dma32_txstopped(dma_info_t *di)
+static bool dma64_txstopped(dma_info_t *di)
 {
-	return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) ==
-		XS_XS_STOPPED);
+	return ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
+		D64_XS0_XS_STOPPED);
 }
 
-static bool dma32_rxstopped(dma_info_t *di)
+static bool dma64_rxstopped(dma_info_t *di)
 {
-	return ((R_REG(di->osh, &di->d32rxregs->status) & RS_RS_MASK) ==
-		RS_RS_STOPPED);
+	return ((R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
+		D64_RS0_RS_STOPPED);
 }
 
-static bool dma32_alloc(dma_info_t *di, uint direction)
+static bool dma64_alloc(dma_info_t *di, uint direction)
 {
-	uint size;
+	u16 size;
 	uint ddlen;
 	void *va;
-	uint alloced;
+	uint alloced = 0;
 	u16 align;
 	u16 align_bits;
 
-	ddlen = sizeof(dma32dd_t);
+	ddlen = sizeof(dma64dd_t);
 
 	size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
-
-	alloced = 0;
 	align_bits = di->dmadesc_align;
 	align = (1 << align_bits);
 
 	if (direction == DMA_TX) {
-		va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits,
-			&alloced, &di->txdpaorig, &di->tx_dmah);
+		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+			&alloced, &di->txdpaorig);
 		if (va == NULL) {
-			DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
+			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
 			return false;
 		}
-
-		PHYSADDRHISET(di->txdpa, 0);
-		ASSERT(PHYSADDRHI(di->txdpaorig) == 0);
-		di->txd32 = (dma32dd_t *) roundup((unsigned long)va, align);
-		di->txdalign =
-		    (uint) ((s8 *)di->txd32 - (s8 *) va);
-
+		align = (1 << align_bits);
+		di->txd64 = (dma64dd_t *) roundup((unsigned long)va, align);
+		di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
 		PHYSADDRLOSET(di->txdpa,
 			      PHYSADDRLO(di->txdpaorig) + di->txdalign);
 		/* Make sure that alignment didn't overflow */
 		ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig));
 
+		PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
 		di->txdalloc = alloced;
-		ASSERT(IS_ALIGNED((unsigned long)di->txd32, align));
+		ASSERT(IS_ALIGNED((unsigned long)di->txd64, align));
 	} else {
-		va = dma_ringalloc(di->osh, D32RINGALIGN, size, &align_bits,
-			&alloced, &di->rxdpaorig, &di->rx_dmah);
+		va = dma_ringalloc(di, D64RINGALIGN, size, &align_bits,
+			&alloced, &di->rxdpaorig);
 		if (va == NULL) {
-			DMA_ERROR(("%s: dma_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
+			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
 			return false;
 		}
-
-		PHYSADDRHISET(di->rxdpa, 0);
-		ASSERT(PHYSADDRHI(di->rxdpaorig) == 0);
-		di->rxd32 = (dma32dd_t *) roundup((unsigned long)va, align);
-		di->rxdalign =
-		    (uint) ((s8 *)di->rxd32 - (s8 *) va);
-
+		align = (1 << align_bits);
+		di->rxd64 = (dma64dd_t *) roundup((unsigned long)va, align);
+		di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
 		PHYSADDRLOSET(di->rxdpa,
 			      PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
 		/* Make sure that alignment didn't overflow */
 		ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig));
+
+		PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
 		di->rxdalloc = alloced;
-		ASSERT(IS_ALIGNED((unsigned long)di->rxd32, align));
+		ASSERT(IS_ALIGNED((unsigned long)di->rxd64, align));
 	}
 
 	return true;
 }
 
-static bool dma32_txreset(dma_info_t *di)
+static bool dma64_txreset(dma_info_t *di)
 {
 	u32 status;
 
@@ -1580,658 +1267,94 @@ static bool dma32_txreset(dma_info_t *di)
 		return true;
 
 	/* suspend tx DMA first */
-	W_REG(di->osh, &di->d32txregs->control, XC_SE);
+	W_REG(&di->d64txregs->control, D64_XC_SE);
 	SPINWAIT(((status =
-		   (R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK))
-		  != XS_XS_DISABLED) && (status != XS_XS_IDLE)
-		 && (status != XS_XS_STOPPED), (10000));
+		   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
+		  != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
+		 && (status != D64_XS0_XS_STOPPED), 10000);
 
-	W_REG(di->osh, &di->d32txregs->control, 0);
-	SPINWAIT(((status = (R_REG(di->osh,
-				   &di->d32txregs->status) & XS_XS_MASK)) !=
-		  XS_XS_DISABLED), 10000);
+	W_REG(&di->d64txregs->control, 0);
+	SPINWAIT(((status =
+		   (R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK))
+		  != D64_XS0_XS_DISABLED), 10000);
 
 	/* wait for the last transaction to complete */
 	udelay(300);
 
-	return status == XS_XS_DISABLED;
+	return status == D64_XS0_XS_DISABLED;
 }
 
-static bool dma32_rxidle(dma_info_t *di)
+static bool dma64_rxidle(dma_info_t *di)
 {
 	DMA_TRACE(("%s: dma_rxidle\n", di->name));
 
 	if (di->nrxd == 0)
 		return true;
 
-	return ((R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK) ==
-		R_REG(di->osh, &di->d32rxregs->ptr));
+	return ((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
+		(R_REG(&di->d64rxregs->ptr) & D64_RS0_CD_MASK));
 }
 
-static bool dma32_rxreset(dma_info_t *di)
+static bool dma64_rxreset(dma_info_t *di)
 {
 	u32 status;
 
 	if (di->nrxd == 0)
 		return true;
 
-	W_REG(di->osh, &di->d32rxregs->control, 0);
-	SPINWAIT(((status = (R_REG(di->osh,
-				   &di->d32rxregs->status) & RS_RS_MASK)) !=
-		  RS_RS_DISABLED), 10000);
+	W_REG(&di->d64rxregs->control, 0);
+	SPINWAIT(((status =
+		   (R_REG(&di->d64rxregs->status0) & D64_RS0_RS_MASK))
+		  != D64_RS0_RS_DISABLED), 10000);
 
-	return status == RS_RS_DISABLED;
+	return status == D64_RS0_RS_DISABLED;
 }
 
-static bool dma32_rxenabled(dma_info_t *di)
+static bool dma64_rxenabled(dma_info_t *di)
 {
 	u32 rc;
 
-	rc = R_REG(di->osh, &di->d32rxregs->control);
-	return (rc != 0xffffffff) && (rc & RC_RE);
+	rc = R_REG(&di->d64rxregs->control);
+	return (rc != 0xffffffff) && (rc & D64_RC_RE);
 }
 
-static bool dma32_txsuspendedidle(dma_info_t *di)
+static bool dma64_txsuspendedidle(dma_info_t *di)
 {
+
 	if (di->ntxd == 0)
 		return true;
 
-	if (!(R_REG(di->osh, &di->d32txregs->control) & XC_SE))
+	if (!(R_REG(&di->d64txregs->control) & D64_XC_SE))
 		return 0;
 
-	if ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) != XS_XS_IDLE)
-		return 0;
+	if ((R_REG(&di->d64txregs->status0) & D64_XS0_XS_MASK) ==
+	    D64_XS0_XS_IDLE)
+		return 1;
 
-	udelay(2);
-	return ((R_REG(di->osh, &di->d32txregs->status) & XS_XS_MASK) ==
-		XS_XS_IDLE);
+	return 0;
 }
 
-/* !! tx entry routine
- * supports full 32bit dma engine buffer addressing so
- * dma buffers can cross 4 Kbyte page boundaries.
- *
- * WARNING: call must check the return value for error.
- *   the error(toss frames) could be fatal and cause many subsequent hard to debug problems
+/* Useful when sending unframed data.  This allows us to get a progress report from the DMA.
+ * We return a pointer to the beginning of the DATA buffer of the current descriptor.
+ * If DMA is idle, we return NULL.
  */
-static int dma32_txfast(dma_info_t *di, struct sk_buff *p0, bool commit)
+static void *dma64_getpos(dma_info_t *di, bool direction)
 {
-	struct sk_buff *p, *next;
-	unsigned char *data;
-	uint len;
-	u16 txout;
-	u32 flags = 0;
-	dmaaddr_t pa;
+	void *va;
+	bool idle;
+	u32 cd_offset;
 
-	DMA_TRACE(("%s: dma_txfast\n", di->name));
-
-	txout = di->txout;
-
-	/*
-	 * Walk the chain of packet buffers
-	 * allocating and initializing transmit descriptor entries.
-	 */
-	for (p = p0; p; p = next) {
-		uint nsegs, j;
-		hnddma_seg_map_t *map;
-
-		data = p->data;
-		len = p->len;
-#ifdef BCM_DMAPAD
-		len += PKTDMAPAD(di->osh, p);
-#endif
-		next = p->next;
-
-		/* return nonzero if out of tx descriptors */
-		if (NEXTTXD(txout) == di->txin)
-			goto outoftxd;
-
-		if (len == 0)
-			continue;
-
-		if (DMASGLIST_ENAB)
-			memset(&di->txp_dmah[txout], 0,
-				sizeof(hnddma_seg_map_t));
-
-		/* get physical address of buffer start */
-		pa = DMA_MAP(di->osh, data, len, DMA_TX, p,
-			     &di->txp_dmah[txout]);
-
-		if (DMASGLIST_ENAB) {
-			map = &di->txp_dmah[txout];
-
-			/* See if all the segments can be accounted for */
-			if (map->nsegs >
-			    (uint) (di->ntxd - NTXDACTIVE(di->txin, di->txout) -
-				    1))
-				goto outoftxd;
-
-			nsegs = map->nsegs;
-		} else
-			nsegs = 1;
-
-		for (j = 1; j <= nsegs; j++) {
-			flags = 0;
-			if (p == p0 && j == 1)
-				flags |= CTRL_SOF;
-
-			/* With a DMA segment list, Descriptor table is filled
-			 * using the segment list instead of looping over
-			 * buffers in multi-chain DMA. Therefore, EOF for SGLIST is when
-			 * end of segment list is reached.
-			 */
-			if ((!DMASGLIST_ENAB && next == NULL) ||
-			    (DMASGLIST_ENAB && j == nsegs))
-				flags |= (CTRL_IOC | CTRL_EOF);
-			if (txout == (di->ntxd - 1))
-				flags |= CTRL_EOT;
-
-			if (DMASGLIST_ENAB) {
-				len = map->segs[j - 1].length;
-				pa = map->segs[j - 1].addr;
-			}
-			ASSERT(PHYSADDRHI(pa) == 0);
-
-			dma32_dd_upd(di, di->txd32, pa, txout, &flags, len);
-			ASSERT(di->txp[txout] == NULL);
-
-			txout = NEXTTXD(txout);
-		}
-
-		/* See above. No need to loop over individual buffers */
-		if (DMASGLIST_ENAB)
-			break;
-	}
-
-	/* if last txd eof not set, fix it */
-	if (!(flags & CTRL_EOF))
-		W_SM(&di->txd32[PREVTXD(txout)].ctrl,
-		     BUS_SWAP32(flags | CTRL_IOC | CTRL_EOF));
-
-	/* save the packet */
-	di->txp[PREVTXD(txout)] = p0;
-
-	/* bump the tx descriptor index */
-	di->txout = txout;
-
-	/* kick the chip */
-	if (commit)
-		W_REG(di->osh, &di->d32txregs->ptr, I2B(txout, dma32dd_t));
-
-	/* tx flow control */
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	return 0;
-
- outoftxd:
-	DMA_ERROR(("%s: dma_txfast: out of txds\n", di->name));
-	pkt_buf_free_skb(di->osh, p0, true);
-	di->hnddma.txavail = 0;
-	di->hnddma.txnobuf++;
-	return -1;
-}
-
-/*
- * Reclaim next completed txd (txds if using chained buffers) in the range
- * specified and return associated packet.
- * If range is HNDDMA_RANGE_TRANSMITTED, reclaim descriptors that have be
- * transmitted as noted by the hardware "CurrDescr" pointer.
- * If range is HNDDMA_RANGE_TRANSFERED, reclaim descriptors that have be
- * transfered by the DMA as noted by the hardware "ActiveDescr" pointer.
- * If range is HNDDMA_RANGE_ALL, reclaim all txd(s) posted to the ring and
- * return associated packet regardless of the value of hardware pointers.
- */
-static void *dma32_getnexttxp(dma_info_t *di, txd_range_t range)
-{
-	u16 start, end, i;
-	u16 active_desc;
-	void *txp;
-
-	DMA_TRACE(("%s: dma_getnexttxp %s\n", di->name,
-		   (range == HNDDMA_RANGE_ALL) ? "all" :
-		   ((range ==
-		     HNDDMA_RANGE_TRANSMITTED) ? "transmitted" :
-		    "transfered")));
-
-	if (di->ntxd == 0)
-		return NULL;
-
-	txp = NULL;
-
-	start = di->txin;
-	if (range == HNDDMA_RANGE_ALL)
-		end = di->txout;
-	else {
-		dma32regs_t *dregs = di->d32txregs;
-
-		end =
-		    (u16) B2I(R_REG(di->osh, &dregs->status) & XS_CD_MASK,
-				 dma32dd_t);
-
-		if (range == HNDDMA_RANGE_TRANSFERED) {
-			active_desc =
-			    (u16) ((R_REG(di->osh, &dregs->status) &
-				       XS_AD_MASK) >> XS_AD_SHIFT);
-			active_desc = (u16) B2I(active_desc, dma32dd_t);
-			if (end != active_desc)
-				end = PREVTXD(active_desc);
-		}
-	}
-
-	if ((start == 0) && (end > di->txout))
-		goto bogus;
-
-	for (i = start; i != end && !txp; i = NEXTTXD(i)) {
-		dmaaddr_t pa;
-		hnddma_seg_map_t *map = NULL;
-		uint size, j, nsegs;
-
-		PHYSADDRLOSET(pa,
-			      (BUS_SWAP32(R_SM(&di->txd32[i].addr)) -
-			       di->dataoffsetlow));
-		PHYSADDRHISET(pa, 0);
-
-		if (DMASGLIST_ENAB) {
-			map = &di->txp_dmah[i];
-			size = map->origsize;
-			nsegs = map->nsegs;
-		} else {
-			size =
-			    (BUS_SWAP32(R_SM(&di->txd32[i].ctrl)) &
-			     CTRL_BC_MASK);
-			nsegs = 1;
-		}
-
-		for (j = nsegs; j > 0; j--) {
-			W_SM(&di->txd32[i].addr, 0xdeadbeef);
-
-			txp = di->txp[i];
-			di->txp[i] = NULL;
-			if (j > 1)
-				i = NEXTTXD(i);
-		}
-
-		DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map);
-	}
-
-	di->txin = i;
-
-	/* tx flow control */
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	return txp;
-
- bogus:
-	DMA_NONE(("dma_getnexttxp: bogus curr: start %d end %d txout %d force %d\n", start, end, di->txout, forceall));
-	return NULL;
-}
-
-static void *dma32_getnextrxp(dma_info_t *di, bool forceall)
-{
-	uint i, curr;
-	void *rxp;
-	dmaaddr_t pa;
-	/* if forcing, dma engine must be disabled */
-	ASSERT(!forceall || !dma32_rxenabled(di));
-
-	i = di->rxin;
-
-	/* return if no packets posted */
-	if (i == di->rxout)
-		return NULL;
-
-	curr =
-	    B2I(R_REG(di->osh, &di->d32rxregs->status) & RS_CD_MASK, dma32dd_t);
-
-	/* ignore curr if forceall */
-	if (!forceall && (i == curr))
-		return NULL;
-
-	/* get the packet pointer that corresponds to the rx descriptor */
-	rxp = di->rxp[i];
-	ASSERT(rxp);
-	di->rxp[i] = NULL;
-
-	PHYSADDRLOSET(pa,
-		      (BUS_SWAP32(R_SM(&di->rxd32[i].addr)) -
-		       di->dataoffsetlow));
-	PHYSADDRHISET(pa, 0);
-
-	/* clear this packet from the descriptor ring */
-	DMA_UNMAP(di->osh, pa, di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]);
-
-	W_SM(&di->rxd32[i].addr, 0xdeadbeef);
-
-	di->rxin = NEXTRXD(i);
-
-	return rxp;
-}
-
-/*
- * Rotate all active tx dma ring entries "forward" by (ActiveDescriptor - txin).
- */
-static void dma32_txrotate(dma_info_t *di)
-{
-	u16 ad;
-	uint nactive;
-	uint rot;
-	u16 old, new;
-	u32 w;
-	u16 first, last;
-
-	ASSERT(dma32_txsuspendedidle(di));
-
-	nactive = _dma_txactive(di);
-	ad = (u16) (B2I
-		       (((R_REG(di->osh, &di->d32txregs->status) & XS_AD_MASK)
-			 >> XS_AD_SHIFT), dma32dd_t));
-	rot = TXD(ad - di->txin);
-
-	ASSERT(rot < di->ntxd);
-
-	/* full-ring case is a lot harder - don't worry about this */
-	if (rot >= (di->ntxd - nactive)) {
-		DMA_ERROR(("%s: dma_txrotate: ring full - punt\n", di->name));
-		return;
-	}
-
-	first = di->txin;
-	last = PREVTXD(di->txout);
-
-	/* move entries starting at last and moving backwards to first */
-	for (old = last; old != PREVTXD(first); old = PREVTXD(old)) {
-		new = TXD(old + rot);
-
-		/*
-		 * Move the tx dma descriptor.
-		 * EOT is set only in the last entry in the ring.
-		 */
-		w = BUS_SWAP32(R_SM(&di->txd32[old].ctrl)) & ~CTRL_EOT;
-		if (new == (di->ntxd - 1))
-			w |= CTRL_EOT;
-		W_SM(&di->txd32[new].ctrl, BUS_SWAP32(w));
-		W_SM(&di->txd32[new].addr, R_SM(&di->txd32[old].addr));
-
-		/* zap the old tx dma descriptor address field */
-		W_SM(&di->txd32[old].addr, BUS_SWAP32(0xdeadbeef));
-
-		/* move the corresponding txp[] entry */
-		ASSERT(di->txp[new] == NULL);
-		di->txp[new] = di->txp[old];
-
-		/* Move the segment map as well */
-		if (DMASGLIST_ENAB) {
-			bcopy(&di->txp_dmah[old], &di->txp_dmah[new],
-			      sizeof(hnddma_seg_map_t));
-			memset(&di->txp_dmah[old], 0, sizeof(hnddma_seg_map_t));
-		}
-
-		di->txp[old] = NULL;
-	}
-
-	/* update txin and txout */
-	di->txin = ad;
-	di->txout = TXD(di->txout + rot);
-	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
-
-	/* kick the chip */
-	W_REG(di->osh, &di->d32txregs->ptr, I2B(di->txout, dma32dd_t));
-}
-
-/* 64-bit DMA functions */
-
-static void dma64_txinit(dma_info_t *di)
-{
-	u32 control = D64_XC_XE;
-
-	DMA_TRACE(("%s: dma_txinit\n", di->name));
-
-	if (di->ntxd == 0)
-		return;
-
-	di->txin = di->txout = 0;
-	di->hnddma.txavail = di->ntxd - 1;
-
-	/* clear tx descriptor ring */
-	memset((void *)di->txd64, '\0', (di->ntxd * sizeof(dma64dd_t)));
-
-	/* DMA engine with out alignment requirement requires table to be inited
-	 * before enabling the engine
-	 */
-	if (!di->aligndesc_4k)
-		_dma_ddtable_init(di, DMA_TX, di->txdpa);
-
-	if ((di->hnddma.dmactrlflags & DMA_CTRL_PEN) == 0)
-		control |= D64_XC_PD;
-	OR_REG(di->osh, &di->d64txregs->control, control);
-
-	/* DMA engine with alignment requirement requires table to be inited
-	 * before enabling the engine
-	 */
-	if (di->aligndesc_4k)
-		_dma_ddtable_init(di, DMA_TX, di->txdpa);
-}
-
-static bool dma64_txenabled(dma_info_t *di)
-{
-	u32 xc;
-
-	/* If the chip is dead, it is not enabled :-) */
-	xc = R_REG(di->osh, &di->d64txregs->control);
-	return (xc != 0xffffffff) && (xc & D64_XC_XE);
-}
-
-static void dma64_txsuspend(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_txsuspend\n", di->name));
-
-	if (di->ntxd == 0)
-		return;
-
-	OR_REG(di->osh, &di->d64txregs->control, D64_XC_SE);
-}
-
-static void dma64_txresume(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_txresume\n", di->name));
-
-	if (di->ntxd == 0)
-		return;
-
-	AND_REG(di->osh, &di->d64txregs->control, ~D64_XC_SE);
-}
-
-static bool dma64_txsuspended(dma_info_t *di)
-{
-	return (di->ntxd == 0) ||
-	    ((R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE) ==
-	     D64_XC_SE);
-}
-
-static void BCMFASTPATH dma64_txreclaim(dma_info_t *di, txd_range_t range)
-{
-	void *p;
-
-	DMA_TRACE(("%s: dma_txreclaim %s\n", di->name,
-		   (range == HNDDMA_RANGE_ALL) ? "all" :
-		   ((range ==
-		     HNDDMA_RANGE_TRANSMITTED) ? "transmitted" :
-		    "transfered")));
-
-	if (di->txin == di->txout)
-		return;
-
-	while ((p = dma64_getnexttxp(di, range))) {
-		/* For unframed data, we don't have any packets to free */
-		if (!(di->hnddma.dmactrlflags & DMA_CTRL_UNFRAMED))
-			pkt_buf_free_skb(di->osh, p, true);
-	}
-}
-
-static bool dma64_txstopped(dma_info_t *di)
-{
-	return ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) ==
-		D64_XS0_XS_STOPPED);
-}
-
-static bool dma64_rxstopped(dma_info_t *di)
-{
-	return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK) ==
-		D64_RS0_RS_STOPPED);
-}
-
-static bool dma64_alloc(dma_info_t *di, uint direction)
-{
-	u16 size;
-	uint ddlen;
-	void *va;
-	uint alloced = 0;
-	u16 align;
-	u16 align_bits;
-
-	ddlen = sizeof(dma64dd_t);
-
-	size = (direction == DMA_TX) ? (di->ntxd * ddlen) : (di->nrxd * ddlen);
-	align_bits = di->dmadesc_align;
-	align = (1 << align_bits);
-
-	if (direction == DMA_TX) {
-		va = dma_ringalloc(di->osh, D64RINGALIGN, size, &align_bits,
-			&alloced, &di->txdpaorig, &di->tx_dmah);
-		if (va == NULL) {
-			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(ntxd) failed\n", di->name));
-			return false;
-		}
-		align = (1 << align_bits);
-		di->txd64 = (dma64dd_t *) roundup((unsigned long)va, align);
-		di->txdalign = (uint) ((s8 *)di->txd64 - (s8 *) va);
-		PHYSADDRLOSET(di->txdpa,
-			      PHYSADDRLO(di->txdpaorig) + di->txdalign);
-		/* Make sure that alignment didn't overflow */
-		ASSERT(PHYSADDRLO(di->txdpa) >= PHYSADDRLO(di->txdpaorig));
-
-		PHYSADDRHISET(di->txdpa, PHYSADDRHI(di->txdpaorig));
-		di->txdalloc = alloced;
-		ASSERT(IS_ALIGNED((unsigned long)di->txd64, align));
-	} else {
-		va = dma_ringalloc(di->osh, D64RINGALIGN, size, &align_bits,
-			&alloced, &di->rxdpaorig, &di->rx_dmah);
-		if (va == NULL) {
-			DMA_ERROR(("%s: dma64_alloc: DMA_ALLOC_CONSISTENT(nrxd) failed\n", di->name));
-			return false;
-		}
-		align = (1 << align_bits);
-		di->rxd64 = (dma64dd_t *) roundup((unsigned long)va, align);
-		di->rxdalign = (uint) ((s8 *)di->rxd64 - (s8 *) va);
-		PHYSADDRLOSET(di->rxdpa,
-			      PHYSADDRLO(di->rxdpaorig) + di->rxdalign);
-		/* Make sure that alignment didn't overflow */
-		ASSERT(PHYSADDRLO(di->rxdpa) >= PHYSADDRLO(di->rxdpaorig));
-
-		PHYSADDRHISET(di->rxdpa, PHYSADDRHI(di->rxdpaorig));
-		di->rxdalloc = alloced;
-		ASSERT(IS_ALIGNED((unsigned long)di->rxd64, align));
-	}
-
-	return true;
-}
-
-static bool dma64_txreset(dma_info_t *di)
-{
-	u32 status;
-
-	if (di->ntxd == 0)
-		return true;
-
-	/* suspend tx DMA first */
-	W_REG(di->osh, &di->d64txregs->control, D64_XC_SE);
-	SPINWAIT(((status =
-		   (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK))
-		  != D64_XS0_XS_DISABLED) && (status != D64_XS0_XS_IDLE)
-		 && (status != D64_XS0_XS_STOPPED), 10000);
-
-	W_REG(di->osh, &di->d64txregs->control, 0);
-	SPINWAIT(((status =
-		   (R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK))
-		  != D64_XS0_XS_DISABLED), 10000);
-
-	/* wait for the last transaction to complete */
-	udelay(300);
-
-	return status == D64_XS0_XS_DISABLED;
-}
-
-static bool dma64_rxidle(dma_info_t *di)
-{
-	DMA_TRACE(("%s: dma_rxidle\n", di->name));
-
-	if (di->nrxd == 0)
-		return true;
-
-	return ((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) ==
-		(R_REG(di->osh, &di->d64rxregs->ptr) & D64_RS0_CD_MASK));
-}
-
-static bool dma64_rxreset(dma_info_t *di)
-{
-	u32 status;
-
-	if (di->nrxd == 0)
-		return true;
-
-	W_REG(di->osh, &di->d64rxregs->control, 0);
-	SPINWAIT(((status =
-		   (R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_RS_MASK))
-		  != D64_RS0_RS_DISABLED), 10000);
-
-	return status == D64_RS0_RS_DISABLED;
-}
-
-static bool dma64_rxenabled(dma_info_t *di)
-{
-	u32 rc;
-
-	rc = R_REG(di->osh, &di->d64rxregs->control);
-	return (rc != 0xffffffff) && (rc & D64_RC_RE);
-}
-
-static bool dma64_txsuspendedidle(dma_info_t *di)
-{
-
-	if (di->ntxd == 0)
-		return true;
-
-	if (!(R_REG(di->osh, &di->d64txregs->control) & D64_XC_SE))
-		return 0;
-
-	if ((R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_XS_MASK) ==
-	    D64_XS0_XS_IDLE)
-		return 1;
-
-	return 0;
-}
-
-/* Useful when sending unframed data.  This allows us to get a progress report from the DMA.
- * We return a pointer to the beginning of the DATA buffer of the current descriptor.
- * If DMA is idle, we return NULL.
- */
-static void *dma64_getpos(dma_info_t *di, bool direction)
-{
-	void *va;
-	bool idle;
-	u32 cd_offset;
-
-	if (direction == DMA_TX) {
-		cd_offset =
-		    R_REG(di->osh, &di->d64txregs->status0) & D64_XS0_CD_MASK;
-		idle = !NTXDACTIVE(di->txin, di->txout);
-		va = di->txp[B2I(cd_offset, dma64dd_t)];
-	} else {
-		cd_offset =
-		    R_REG(di->osh, &di->d64rxregs->status0) & D64_XS0_CD_MASK;
-		idle = !NRXDACTIVE(di->rxin, di->rxout);
-		va = di->rxp[B2I(cd_offset, dma64dd_t)];
-	}
+	if (direction == DMA_TX) {
+		cd_offset =
+		    R_REG(&di->d64txregs->status0) & D64_XS0_CD_MASK;
+		idle = !NTXDACTIVE(di->txin, di->txout);
+		va = di->txp[B2I(cd_offset, dma64dd_t)];
+	} else {
+		cd_offset =
+		    R_REG(&di->d64rxregs->status0) & D64_XS0_CD_MASK;
+		idle = !NRXDACTIVE(di->rxin, di->rxout);
+		va = di->rxp[B2I(cd_offset, dma64dd_t)];
+	}
 
 	/* If DMA is IDLE, return NULL */
 	if (idle) {
@@ -2265,7 +1388,7 @@ static int dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit)
 	if (len == 0)
 		return 0;
 
-	pa = DMA_MAP(di->osh, buf, len, DMA_TX, NULL, &di->txp_dmah[txout]);
+	pa = pci_map_single(di->pbus, buf, len, PCI_DMA_TODEVICE);
 
 	flags = (D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF);
 
@@ -2284,7 +1407,7 @@ static int dma64_txunframed(dma_info_t *di, void *buf, uint len, bool commit)
 
 	/* kick the chip */
 	if (commit) {
-		W_REG(di->osh, &di->d64txregs->ptr,
+		W_REG(&di->d64txregs->ptr,
 		      di->xmtptrbase + I2B(txout, dma64dd_t));
 	}
 
@@ -2345,8 +1468,7 @@ static int BCMFASTPATH dma64_txfast(dma_info_t *di, struct sk_buff *p0,
 			memset(&di->txp_dmah[txout], 0,
 				sizeof(hnddma_seg_map_t));
 
-		pa = DMA_MAP(di->osh, data, len, DMA_TX, p,
-			     &di->txp_dmah[txout]);
+		pa = pci_map_single(di->pbus, data, len, PCI_DMA_TODEVICE);
 
 		if (DMASGLIST_ENAB) {
 			map = &di->txp_dmah[txout];
@@ -2405,7 +1527,7 @@ static int BCMFASTPATH dma64_txfast(dma_info_t *di, struct sk_buff *p0,
 
 	/* kick the chip */
 	if (commit)
-		W_REG(di->osh, &di->d64txregs->ptr,
+		W_REG(&di->d64txregs->ptr,
 		      di->xmtptrbase + I2B(txout, dma64dd_t));
 
 	/* tx flow control */
@@ -2415,7 +1537,7 @@ static int BCMFASTPATH dma64_txfast(dma_info_t *di, struct sk_buff *p0,
 
  outoftxd:
 	DMA_ERROR(("%s: dma_txfast: out of txds !!!\n", di->name));
-	pkt_buf_free_skb(di->osh, p0, true);
+	pkt_buf_free_skb(p0);
 	di->hnddma.txavail = 0;
 	di->hnddma.txnobuf++;
 	return -1;
@@ -2456,13 +1578,13 @@ static void *BCMFASTPATH dma64_getnexttxp(dma_info_t *di, txd_range_t range)
 
 		end =
 		    (u16) (B2I
-			      (((R_REG(di->osh, &dregs->status0) &
+			      (((R_REG(&dregs->status0) &
 				 D64_XS0_CD_MASK) -
 				di->xmtptrbase) & D64_XS0_CD_MASK, dma64dd_t));
 
 		if (range == HNDDMA_RANGE_TRANSFERED) {
 			active_desc =
-			    (u16) (R_REG(di->osh, &dregs->status1) &
+			    (u16) (R_REG(&dregs->status1) &
 				      D64_XS1_AD_MASK);
 			active_desc =
 			    (active_desc - di->xmtptrbase) & D64_XS0_CD_MASK;
@@ -2508,7 +1630,7 @@ static void *BCMFASTPATH dma64_getnexttxp(dma_info_t *di, txd_range_t range)
 				i = NEXTTXD(i);
 		}
 
-		DMA_UNMAP(di->osh, pa, size, DMA_TX, txp, map);
+		pci_unmap_single(di->pbus, pa, size, PCI_DMA_TODEVICE);
 	}
 
 	di->txin = i;
@@ -2539,7 +1661,7 @@ static void *BCMFASTPATH dma64_getnextrxp(dma_info_t *di, bool forceall)
 		return NULL;
 
 	curr =
-	    B2I(((R_REG(di->osh, &di->d64rxregs->status0) & D64_RS0_CD_MASK) -
+	    B2I(((R_REG(&di->d64rxregs->status0) & D64_RS0_CD_MASK) -
 		 di->rcvptrbase) & D64_RS0_CD_MASK, dma64dd_t);
 
 	/* ignore curr if forceall */
@@ -2559,7 +1681,7 @@ static void *BCMFASTPATH dma64_getnextrxp(dma_info_t *di, bool forceall)
 		       di->dataoffsethigh));
 
 	/* clear this packet from the descriptor ring */
-	DMA_UNMAP(di->osh, pa, di->rxbufsize, DMA_RX, rxp, &di->rxp_dmah[i]);
+	pci_unmap_single(di->pbus, pa, di->rxbufsize, PCI_DMA_FROMDEVICE);
 
 	W_SM(&di->rxd64[i].addrlow, 0xdeadbeef);
 	W_SM(&di->rxd64[i].addrhigh, 0xdeadbeef);
@@ -2569,12 +1691,12 @@ static void *BCMFASTPATH dma64_getnextrxp(dma_info_t *di, bool forceall)
 	return rxp;
 }
 
-static bool _dma64_addrext(struct osl_info *osh, dma64regs_t * dma64regs)
+static bool _dma64_addrext(dma64regs_t *dma64regs)
 {
 	u32 w;
-	OR_REG(osh, &dma64regs->control, D64_XC_AE);
-	w = R_REG(osh, &dma64regs->control);
-	AND_REG(osh, &dma64regs->control, ~D64_XC_AE);
+	OR_REG(&dma64regs->control, D64_XC_AE);
+	w = R_REG(&dma64regs->control);
+	AND_REG(&dma64regs->control, ~D64_XC_AE);
 	return (w & D64_XC_AE) == D64_XC_AE;
 }
 
@@ -2594,7 +1716,7 @@ static void dma64_txrotate(dma_info_t *di)
 
 	nactive = _dma_txactive(di);
 	ad = (u16) (B2I
-		       ((((R_REG(di->osh, &di->d64txregs->status1) &
+		       ((((R_REG(&di->d64txregs->status1) &
 			   D64_XS1_AD_MASK)
 			  - di->xmtptrbase) & D64_XS1_AD_MASK), dma64dd_t));
 	rot = TXD(ad - di->txin);
@@ -2639,8 +1761,8 @@ static void dma64_txrotate(dma_info_t *di)
 
 		/* Move the map */
 		if (DMASGLIST_ENAB) {
-			bcopy(&di->txp_dmah[old], &di->txp_dmah[new],
-			      sizeof(hnddma_seg_map_t));
+			memcpy(&di->txp_dmah[new], &di->txp_dmah[old],
+			       sizeof(hnddma_seg_map_t));
 			memset(&di->txp_dmah[old], 0, sizeof(hnddma_seg_map_t));
 		}
 
@@ -2653,17 +1775,12 @@ static void dma64_txrotate(dma_info_t *di)
 	di->hnddma.txavail = di->ntxd - NTXDACTIVE(di->txin, di->txout) - 1;
 
 	/* kick the chip */
-	W_REG(di->osh, &di->d64txregs->ptr,
+	W_REG(&di->d64txregs->ptr,
 	      di->xmtptrbase + I2B(di->txout, dma64dd_t));
 }
 
 uint dma_addrwidth(si_t *sih, void *dmaregs)
 {
-	dma32regs_t *dma32regs;
-	struct osl_info *osh;
-
-	osh = si_osh(sih);
-
 	/* Perform 64-bit checks only if we want to advertise 64-bit (> 32bit) capability) */
 	/* DMA engine is 64-bit capable */
 	if ((si_core_sflags(sih, 0, 0) & SISF_DMA64) == SISF_DMA64) {
@@ -2674,23 +1791,32 @@ uint dma_addrwidth(si_t *sih, void *dmaregs)
 			    ((sih->bustype == PCI_BUS) &&
 			     (sih->buscoretype == PCIE_CORE_ID)))
 				return DMADDRWIDTH_64;
-
-		/* DMA64 is always 32-bit capable, AE is always true */
-		ASSERT(_dma64_addrext(osh, (dma64regs_t *) dmaregs));
-
-		return DMADDRWIDTH_32;
 	}
+	ASSERT(0); /* DMA hardware not supported by this driver*/
+	return DMADDRWIDTH_64;
+}
 
-	/* Start checking for 32-bit / 30-bit addressing */
-	dma32regs = (dma32regs_t *) dmaregs;
-
-	/* For System Backplane, PCIE bus or addrext feature, 32-bits ok */
-	if ((sih->bustype == SI_BUS) ||
-	    ((sih->bustype == PCI_BUS)
-	     && sih->buscoretype == PCIE_CORE_ID)
-	    || (_dma32_addrext(osh, dma32regs)))
-		return DMADDRWIDTH_32;
-
-	/* Fallthru */
-	return DMADDRWIDTH_30;
+/*
+ * Mac80211 initiated actions sometimes require packets in the DMA queue to be
+ * modified. The modified portion of the packet is not under control of the DMA
+ * engine. This function calls a caller-supplied function for each packet in
+ * the caller specified dma chain.
+ */
+void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a)
+{
+	dma_info_t *di = (dma_info_t *) dmah;
+	uint i =   di->txin;
+	uint end = di->txout;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+
+	while (i != end) {
+		skb = (struct sk_buff *)di->txp[i];
+		if (skb != NULL) {
+			tx_info = (struct ieee80211_tx_info *)skb->cb;
+			(callback_fnc)(tx_info, arg_a);
+		}
+		i = NEXTTXD(i);
+	}
 }
diff --git a/drivers/staging/brcm80211/util/hndpmu.c b/drivers/staging/brcm80211/util/hndpmu.c
index 6cc59a8..59e3ede 100644
--- a/drivers/staging/brcm80211/util/hndpmu.c
+++ b/drivers/staging/brcm80211/util/hndpmu.c
@@ -18,11 +18,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#ifdef BRCM_FULLMAC
-#include <linux/netdevice.h>
-#endif
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <siutils.h>
 #include <bcmdevs.h>
@@ -34,7 +30,11 @@
 #define	PMU_ERROR(args)
 
 #ifdef BCMDBG
-#define	PMU_MSG(args)	printf args
+#define	PMU_MSG(args)	printk args
+
+/* debug-only definitions */
+/* #define BCMDBG_FORCEHT */
+/* #define CHIPC_UART_ALWAYS_ON */
 #else
 #define	PMU_MSG(args)
 #endif				/* BCMDBG */
@@ -45,23 +45,20 @@
 #define	PMU_NONE(args)
 
 /* PLL controls/clocks */
-static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
-			     u32 xtal);
-static u32 si_pmu1_cpuclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc);
-static u32 si_pmu1_alpclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc);
+static void si_pmu1_pllinit0(si_t *sih, chipcregs_t *cc, u32 xtal);
+static u32 si_pmu1_cpuclk0(si_t *sih, chipcregs_t *cc);
+static u32 si_pmu1_alpclk0(si_t *sih, chipcregs_t *cc);
 
 /* PMU resources */
 static bool si_pmu_res_depfltr_bb(si_t *sih);
 static bool si_pmu_res_depfltr_ncb(si_t *sih);
 static bool si_pmu_res_depfltr_paldo(si_t *sih);
 static bool si_pmu_res_depfltr_npaldo(si_t *sih);
-static u32 si_pmu_res_deps(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
-			      u32 rsrcs, bool all);
-static uint si_pmu_res_uptime(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
-			      u8 rsrc);
+static u32 si_pmu_res_deps(si_t *sih, chipcregs_t *cc, u32 rsrcs, bool all);
+static uint si_pmu_res_uptime(si_t *sih, chipcregs_t *cc, u8 rsrc);
 static void si_pmu_res_masks(si_t *sih, u32 * pmin, u32 * pmax);
 static void si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc,
-				       struct osl_info *osh, u8 spuravoid);
+				       u8 spuravoid);
 
 static void si_pmu_set_4330_plldivs(si_t *sih);
 
@@ -106,8 +103,7 @@ void si_pmu_pllupd(si_t *sih)
 }
 
 /* Setup switcher voltage */
-void si_pmu_set_switcher_voltage(si_t *sih, struct osl_info *osh, u8 bb_voltage,
-				 u8 rf_voltage)
+void si_pmu_set_switcher_voltage(si_t *sih, u8 bb_voltage, u8 rf_voltage)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -119,17 +115,17 @@ void si_pmu_set_switcher_voltage(si_t *sih, struct osl_info *osh, u8 bb_voltage,
 	cc = si_setcoreidx(sih, SI_CC_IDX);
 	ASSERT(cc != NULL);
 
-	W_REG(osh, &cc->regcontrol_addr, 0x01);
-	W_REG(osh, &cc->regcontrol_data, (u32) (bb_voltage & 0x1f) << 22);
+	W_REG(&cc->regcontrol_addr, 0x01);
+	W_REG(&cc->regcontrol_data, (u32) (bb_voltage & 0x1f) << 22);
 
-	W_REG(osh, &cc->regcontrol_addr, 0x00);
-	W_REG(osh, &cc->regcontrol_data, (u32) (rf_voltage & 0x1f) << 14);
+	W_REG(&cc->regcontrol_addr, 0x00);
+	W_REG(&cc->regcontrol_data, (u32) (rf_voltage & 0x1f) << 14);
 
 	/* Return to original core */
 	si_setcoreidx(sih, origidx);
 }
 
-void si_pmu_set_ldo_voltage(si_t *sih, struct osl_info *osh, u8 ldo, u8 voltage)
+void si_pmu_set_ldo_voltage(si_t *sih, u8 ldo, u8 voltage)
 {
 	u8 sr_cntl_shift = 0, rc_shift = 0, shift = 0, mask = 0;
 	u8 addr = 0;
@@ -187,7 +183,7 @@ void si_pmu_set_ldo_voltage(si_t *sih, struct osl_info *osh, u8 ldo, u8 voltage)
 /* d11 slow to fast clock transition time in slow clock cycles */
 #define D11SCC_SLOW2FAST_TRANSITION	2
 
-u16 si_pmu_fast_pwrup_delay(si_t *sih, struct osl_info *osh)
+u16 si_pmu_fast_pwrup_delay(si_t *sih)
 {
 	uint delay = PMU_MAX_TRANSITION_DLY;
 	chipcregs_t *cc;
@@ -222,7 +218,7 @@ u16 si_pmu_fast_pwrup_delay(si_t *sih, struct osl_info *osh)
 		else {
 			u32 ilp = si_ilp_clock(sih);
 			delay =
-			    (si_pmu_res_uptime(sih, osh, cc, RES4329_HT_AVAIL) +
+			    (si_pmu_res_uptime(sih, cc, RES4329_HT_AVAIL) +
 			     D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
 							      1) / ilp);
 			delay = (11 * delay) / 10;
@@ -237,7 +233,7 @@ u16 si_pmu_fast_pwrup_delay(si_t *sih, struct osl_info *osh)
 		else {
 			u32 ilp = si_ilp_clock(sih);
 			delay =
-			    (si_pmu_res_uptime(sih, osh, cc, RES4336_HT_AVAIL) +
+			    (si_pmu_res_uptime(sih, cc, RES4336_HT_AVAIL) +
 			     D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
 							      1) / ilp);
 			delay = (11 * delay) / 10;
@@ -249,7 +245,7 @@ u16 si_pmu_fast_pwrup_delay(si_t *sih, struct osl_info *osh)
 		else {
 			u32 ilp = si_ilp_clock(sih);
 			delay =
-			    (si_pmu_res_uptime(sih, osh, cc, RES4330_HT_AVAIL) +
+			    (si_pmu_res_uptime(sih, cc, RES4330_HT_AVAIL) +
 			     D11SCC_SLOW2FAST_TRANSITION) * ((1000000 + ilp -
 							      1) / ilp);
 			delay = (11 * delay) / 10;
@@ -264,7 +260,7 @@ u16 si_pmu_fast_pwrup_delay(si_t *sih, struct osl_info *osh)
 	return (u16) delay;
 }
 
-u32 si_pmu_force_ilp(si_t *sih, struct osl_info *osh, bool force)
+u32 si_pmu_force_ilp(si_t *sih, bool force)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -277,12 +273,12 @@ u32 si_pmu_force_ilp(si_t *sih, struct osl_info *osh, bool force)
 	cc = si_setcoreidx(sih, SI_CC_IDX);
 	ASSERT(cc != NULL);
 
-	oldpmucontrol = R_REG(osh, &cc->pmucontrol);
+	oldpmucontrol = R_REG(&cc->pmucontrol);
 	if (force)
-		W_REG(osh, &cc->pmucontrol, oldpmucontrol &
+		W_REG(&cc->pmucontrol, oldpmucontrol &
 		      ~(PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
 	else
-		W_REG(osh, &cc->pmucontrol, oldpmucontrol |
+		W_REG(&cc->pmucontrol, oldpmucontrol |
 		      (PCTL_HT_REQ_EN | PCTL_ALP_REQ_EN));
 
 	/* Return to original core */
@@ -682,7 +678,7 @@ static void si_pmu_res_masks(si_t *sih, u32 * pmin, u32 * pmax)
 }
 
 /* initialize PMU resources */
-void si_pmu_res_init(si_t *sih, struct osl_info *osh)
+void si_pmu_res_init(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -777,9 +773,9 @@ void si_pmu_res_init(si_t *sih, struct osl_info *osh)
 		PMU_MSG(("Changing rsrc %d res_updn_timer to 0x%x\n",
 			 pmu_res_updown_table[pmu_res_updown_table_sz].resnum,
 			 pmu_res_updown_table[pmu_res_updown_table_sz].updown));
-		W_REG(osh, &cc->res_table_sel,
+		W_REG(&cc->res_table_sel,
 		      pmu_res_updown_table[pmu_res_updown_table_sz].resnum);
-		W_REG(osh, &cc->res_updn_timer,
+		W_REG(&cc->res_updn_timer,
 		      pmu_res_updown_table[pmu_res_updown_table_sz].updown);
 	}
 	/* Apply nvram overrides to up/down timers */
@@ -790,8 +786,8 @@ void si_pmu_res_init(si_t *sih, struct osl_info *osh)
 			continue;
 		PMU_MSG(("Applying %s=%s to rsrc %d res_updn_timer\n", name,
 			 val, i));
-		W_REG(osh, &cc->res_table_sel, (u32) i);
-		W_REG(osh, &cc->res_updn_timer,
+		W_REG(&cc->res_table_sel, (u32) i);
+		W_REG(&cc->res_updn_timer,
 		      (u32) simple_strtoul(val, NULL, 0));
 	}
 
@@ -806,24 +802,24 @@ void si_pmu_res_init(si_t *sih, struct osl_info *osh)
 			if ((pmu_res_depend_table[pmu_res_depend_table_sz].
 			     res_mask & PMURES_BIT(i)) == 0)
 				continue;
-			W_REG(osh, &cc->res_table_sel, i);
+			W_REG(&cc->res_table_sel, i);
 			switch (pmu_res_depend_table[pmu_res_depend_table_sz].
 				action) {
 			case RES_DEPEND_SET:
 				PMU_MSG(("Changing rsrc %d res_dep_mask to 0x%x\n", i, pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask));
-				W_REG(osh, &cc->res_dep_mask,
+				W_REG(&cc->res_dep_mask,
 				      pmu_res_depend_table
 				      [pmu_res_depend_table_sz].depend_mask);
 				break;
 			case RES_DEPEND_ADD:
 				PMU_MSG(("Adding 0x%x to rsrc %d res_dep_mask\n", pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
-				OR_REG(osh, &cc->res_dep_mask,
+				OR_REG(&cc->res_dep_mask,
 				       pmu_res_depend_table
 				       [pmu_res_depend_table_sz].depend_mask);
 				break;
 			case RES_DEPEND_REMOVE:
 				PMU_MSG(("Removing 0x%x from rsrc %d res_dep_mask\n", pmu_res_depend_table[pmu_res_depend_table_sz].depend_mask, i));
-				AND_REG(osh, &cc->res_dep_mask,
+				AND_REG(&cc->res_dep_mask,
 					~pmu_res_depend_table
 					[pmu_res_depend_table_sz].depend_mask);
 				break;
@@ -841,8 +837,8 @@ void si_pmu_res_init(si_t *sih, struct osl_info *osh)
 			continue;
 		PMU_MSG(("Applying %s=%s to rsrc %d res_dep_mask\n", name, val,
 			 i));
-		W_REG(osh, &cc->res_table_sel, (u32) i);
-		W_REG(osh, &cc->res_dep_mask,
+		W_REG(&cc->res_table_sel, (u32) i);
+		W_REG(&cc->res_dep_mask,
 		      (u32) simple_strtoul(val, NULL, 0));
 	}
 
@@ -855,14 +851,14 @@ void si_pmu_res_init(si_t *sih, struct osl_info *osh)
 
 	if (max_mask) {
 		PMU_MSG(("Changing max_res_mask to 0x%x\n", max_mask));
-		W_REG(osh, &cc->max_res_mask, max_mask);
+		W_REG(&cc->max_res_mask, max_mask);
 	}
 
 	/* Program min resource mask */
 
 	if (min_mask) {
 		PMU_MSG(("Changing min_res_mask to 0x%x\n", min_mask));
-		W_REG(osh, &cc->min_res_mask, min_mask);
+		W_REG(&cc->min_res_mask, min_mask);
 	}
 
 	/* Add some delay; allow resources to come up and settle. */
@@ -1183,13 +1179,13 @@ static u32 si_pmu1_pllfvco0(si_t *sih)
 
 /* query alp/xtal clock frequency */
 static u32
-si_pmu1_alpclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc)
+si_pmu1_alpclk0(si_t *sih, chipcregs_t *cc)
 {
 	const pmu1_xtaltab0_t *xt;
 	u32 xf;
 
 	/* Find the frequency in the table */
-	xf = (R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
+	xf = (R_REG(&cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
 	    PCTL_XTALFREQ_SHIFT;
 	for (xt = si_pmu1_xtaltab0(sih); xt != NULL && xt->fref != 0; xt++)
 		if (xt->xf == xf)
@@ -1208,8 +1204,7 @@ si_pmu1_alpclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc)
  * case the xtal frequency is unknown to the s/w so we need to call
  * si_pmu1_xtaldef0() wherever it is needed to return a default value.
  */
-static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
-			     u32 xtal)
+static void si_pmu1_pllinit0(si_t *sih, chipcregs_t *cc, u32 xtal)
 {
 	const pmu1_xtaltab0_t *xt;
 	u32 tmp;
@@ -1237,7 +1232,7 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	/*  for 4319 bootloader already programs the PLL but bootloader does not program the
 	   PLL4 and PLL5. So Skip this check for 4319
 	 */
-	if ((((R_REG(osh, &cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
+	if ((((R_REG(&cc->pmucontrol) & PCTL_XTALFREQ_MASK) >>
 	      PCTL_XTALFREQ_SHIFT) == xt->xf) &&
 	    !((sih->chip == BCM4319_CHIP_ID)
 	      || (sih->chip == BCM4330_CHIP_ID))) {
@@ -1254,16 +1249,16 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	case BCM4329_CHIP_ID:
 		/* Change the BBPLL drive strength to 8 for all channels */
 		buf_strength = 0x888888;
-		AND_REG(osh, &cc->min_res_mask,
+		AND_REG(&cc->min_res_mask,
 			~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
 			  PMURES_BIT(RES4329_HT_AVAIL)));
-		AND_REG(osh, &cc->max_res_mask,
+		AND_REG(&cc->max_res_mask,
 			~(PMURES_BIT(RES4329_BBPLL_PWRSW_PU) |
 			  PMURES_BIT(RES4329_HT_AVAIL)));
-		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
+		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
 			 PMU_MAX_TRANSITION_DLY);
-		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+		ASSERT(!(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL));
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
 		if (xt->fref == 38400)
 			tmp = 0x200024C0;
 		else if (xt->fref == 37400)
@@ -1272,17 +1267,16 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 			tmp = 0x200024C0;
 		else
 			tmp = 0x200005C0;	/* Chip Dflt Settings */
-		W_REG(osh, &cc->pllcontrol_data, tmp);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+		W_REG(&cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
 		tmp =
-		    R_REG(osh,
-			  &cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
+		    R_REG(&cc->pllcontrol_data) & PMU1_PLL0_PC5_CLK_DRV_MASK;
 		if ((xt->fref == 38400) || (xt->fref == 37400)
 		    || (xt->fref == 26000))
 			tmp |= 0x15;
 		else
 			tmp |= 0x25;	/* Chip Dflt Settings */
-		W_REG(osh, &cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_data, tmp);
 		break;
 
 	case BCM4319_CHIP_ID:
@@ -1294,50 +1288,50 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 		 * after a delay (more than downtime for HT_AVAIL) remove the
 		 * BBPLL resource; backplane clock moves to ALP from HT.
 		 */
-		AND_REG(osh, &cc->min_res_mask,
+		AND_REG(&cc->min_res_mask,
 			~(PMURES_BIT(RES4319_HT_AVAIL)));
-		AND_REG(osh, &cc->max_res_mask,
+		AND_REG(&cc->max_res_mask,
 			~(PMURES_BIT(RES4319_HT_AVAIL)));
 
 		udelay(100);
-		AND_REG(osh, &cc->min_res_mask,
+		AND_REG(&cc->min_res_mask,
 			~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
-		AND_REG(osh, &cc->max_res_mask,
+		AND_REG(&cc->max_res_mask,
 			~(PMURES_BIT(RES4319_BBPLL_PWRSW_PU)));
 
 		udelay(100);
-		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
+		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
 			 PMU_MAX_TRANSITION_DLY);
-		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+		ASSERT(!(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL));
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
 		tmp = 0x200005c0;
-		W_REG(osh, &cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_data, tmp);
 		break;
 
 	case BCM4336_CHIP_ID:
-		AND_REG(osh, &cc->min_res_mask,
+		AND_REG(&cc->min_res_mask,
 			~(PMURES_BIT(RES4336_HT_AVAIL) |
 			  PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
-		AND_REG(osh, &cc->max_res_mask,
+		AND_REG(&cc->max_res_mask,
 			~(PMURES_BIT(RES4336_HT_AVAIL) |
 			  PMURES_BIT(RES4336_MACPHY_CLKAVAIL)));
 		udelay(100);
-		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
+		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
 			 PMU_MAX_TRANSITION_DLY);
-		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
+		ASSERT(!(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL));
 		break;
 
 	case BCM4330_CHIP_ID:
-		AND_REG(osh, &cc->min_res_mask,
+		AND_REG(&cc->min_res_mask,
 			~(PMURES_BIT(RES4330_HT_AVAIL) |
 			  PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
-		AND_REG(osh, &cc->max_res_mask,
+		AND_REG(&cc->max_res_mask,
 			~(PMURES_BIT(RES4330_HT_AVAIL) |
 			  PMURES_BIT(RES4330_MACPHY_CLKAVAIL)));
 		udelay(100);
-		SPINWAIT(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL,
+		SPINWAIT(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL,
 			 PMU_MAX_TRANSITION_DLY);
-		ASSERT(!(R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL));
+		ASSERT(!(R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL));
 		break;
 
 	default:
@@ -1347,15 +1341,15 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	PMU_MSG(("Done masking\n"));
 
 	/* Write p1div and p2div to pllcontrol[0] */
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-	tmp = R_REG(osh, &cc->pllcontrol_data) &
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+	tmp = R_REG(&cc->pllcontrol_data) &
 	    ~(PMU1_PLL0_PC0_P1DIV_MASK | PMU1_PLL0_PC0_P2DIV_MASK);
 	tmp |=
 	    ((xt->
 	      p1div << PMU1_PLL0_PC0_P1DIV_SHIFT) & PMU1_PLL0_PC0_P1DIV_MASK) |
 	    ((xt->
 	      p2div << PMU1_PLL0_PC0_P2DIV_SHIFT) & PMU1_PLL0_PC0_P2DIV_MASK);
-	W_REG(osh, &cc->pllcontrol_data, tmp);
+	W_REG(&cc->pllcontrol_data, tmp);
 
 	if ((sih->chip == BCM4330_CHIP_ID))
 		si_pmu_set_4330_plldivs(sih);
@@ -1363,11 +1357,11 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	if ((sih->chip == BCM4329_CHIP_ID)
 	    && (sih->chiprev == 0)) {
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		tmp = R_REG(osh, &cc->pllcontrol_data);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+		tmp = R_REG(&cc->pllcontrol_data);
 		tmp = tmp & (~DOT11MAC_880MHZ_CLK_DIVISOR_MASK);
 		tmp = tmp | DOT11MAC_880MHZ_CLK_DIVISOR_VAL;
-		W_REG(osh, &cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_data, tmp);
 	}
 	if ((sih->chip == BCM4319_CHIP_ID) ||
 	    (sih->chip == BCM4336_CHIP_ID) ||
@@ -1377,8 +1371,8 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 		ndiv_mode = PMU1_PLL0_PC2_NDIV_MODE_MASH;
 
 	/* Write ndiv_int and ndiv_mode to pllcontrol[2] */
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-	tmp = R_REG(osh, &cc->pllcontrol_data) &
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+	tmp = R_REG(&cc->pllcontrol_data) &
 	    ~(PMU1_PLL0_PC2_NDIV_INT_MASK | PMU1_PLL0_PC2_NDIV_MODE_MASK);
 	tmp |=
 	    ((xt->
@@ -1386,26 +1380,25 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	     PMU1_PLL0_PC2_NDIV_INT_MASK) | ((ndiv_mode <<
 					      PMU1_PLL0_PC2_NDIV_MODE_SHIFT) &
 					     PMU1_PLL0_PC2_NDIV_MODE_MASK);
-	W_REG(osh, &cc->pllcontrol_data, tmp);
+	W_REG(&cc->pllcontrol_data, tmp);
 
 	/* Write ndiv_frac to pllcontrol[3] */
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-	tmp = R_REG(osh, &cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+	tmp = R_REG(&cc->pllcontrol_data) & ~PMU1_PLL0_PC3_NDIV_FRAC_MASK;
 	tmp |= ((xt->ndiv_frac << PMU1_PLL0_PC3_NDIV_FRAC_SHIFT) &
 		PMU1_PLL0_PC3_NDIV_FRAC_MASK);
-	W_REG(osh, &cc->pllcontrol_data, tmp);
+	W_REG(&cc->pllcontrol_data, tmp);
 
 	/* Write clock driving strength to pllcontrol[5] */
 	if (buf_strength) {
 		PMU_MSG(("Adjusting PLL buffer drive strength: %x\n",
 			 buf_strength));
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
 		tmp =
-		    R_REG(osh,
-			  &cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
+		    R_REG(&cc->pllcontrol_data) & ~PMU1_PLL0_PC5_CLK_DRV_MASK;
 		tmp |= (buf_strength << PMU1_PLL0_PC5_CLK_DRV_SHIFT);
-		W_REG(osh, &cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_data, tmp);
 	}
 
 	PMU_MSG(("Done pll\n"));
@@ -1415,10 +1408,9 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	 */
 	if ((sih->chip == BCM4319_CHIP_ID)
 	    && (xt->fref != XTAL_FREQ_30000MHZ)) {
-		W_REG(osh, &cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
+		W_REG(&cc->chipcontrol_addr, PMU1_PLL0_CHIPCTL2);
 		tmp =
-		    R_REG(osh,
-			  &cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
+		    R_REG(&cc->chipcontrol_data) & ~CCTL_4319USB_XTAL_SEL_MASK;
 		if (xt->fref == XTAL_FREQ_24000MHZ) {
 			tmp |=
 			    (CCTL_4319USB_24MHZ_PLL_SEL <<
@@ -1428,15 +1420,15 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 			    (CCTL_4319USB_48MHZ_PLL_SEL <<
 			     CCTL_4319USB_XTAL_SEL_SHIFT);
 		}
-		W_REG(osh, &cc->chipcontrol_data, tmp);
+		W_REG(&cc->chipcontrol_data, tmp);
 	}
 
 	/* Flush deferred pll control registers writes */
 	if (sih->pmurev >= 2)
-		OR_REG(osh, &cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
+		OR_REG(&cc->pmucontrol, PCTL_PLL_PLLCTL_UPD);
 
 	/* Write XtalFreq. Set the divisor also. */
-	tmp = R_REG(osh, &cc->pmucontrol) &
+	tmp = R_REG(&cc->pmucontrol) &
 	    ~(PCTL_ILP_DIV_MASK | PCTL_XTALFREQ_MASK);
 	tmp |= (((((xt->fref + 127) / 128) - 1) << PCTL_ILP_DIV_SHIFT) &
 		PCTL_ILP_DIV_MASK) |
@@ -1445,16 +1437,16 @@ static void si_pmu1_pllinit0(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	if ((sih->chip == BCM4329_CHIP_ID)
 	    && sih->chiprev == 0) {
 		/* clear the htstretch before clearing HTReqEn */
-		AND_REG(osh, &cc->clkstretch, ~CSTRETCH_HT);
+		AND_REG(&cc->clkstretch, ~CSTRETCH_HT);
 		tmp &= ~PCTL_HT_REQ_EN;
 	}
 
-	W_REG(osh, &cc->pmucontrol, tmp);
+	W_REG(&cc->pmucontrol, tmp);
 }
 
 /* query the CPU clock frequency */
 static u32
-si_pmu1_cpuclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc)
+si_pmu1_cpuclk0(si_t *sih, chipcregs_t *cc)
 {
 	u32 tmp, m1div;
 #ifdef BCMDBG
@@ -1464,30 +1456,30 @@ si_pmu1_cpuclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc)
 	u32 FVCO = si_pmu1_pllfvco0(sih);
 
 	/* Read m1div from pllcontrol[1] */
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+	tmp = R_REG(&cc->pllcontrol_data);
 	m1div = (tmp & PMU1_PLL0_PC1_M1DIV_MASK) >> PMU1_PLL0_PC1_M1DIV_SHIFT;
 
 #ifdef BCMDBG
 	/* Read p2div/p1div from pllcontrol[0] */
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+	tmp = R_REG(&cc->pllcontrol_data);
 	p2div = (tmp & PMU1_PLL0_PC0_P2DIV_MASK) >> PMU1_PLL0_PC0_P2DIV_SHIFT;
 	p1div = (tmp & PMU1_PLL0_PC0_P1DIV_MASK) >> PMU1_PLL0_PC0_P1DIV_SHIFT;
 
 	/* Calculate fvco based on xtal freq and ndiv and pdiv */
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+	tmp = R_REG(&cc->pllcontrol_data);
 	ndiv_int =
 	    (tmp & PMU1_PLL0_PC2_NDIV_INT_MASK) >> PMU1_PLL0_PC2_NDIV_INT_SHIFT;
 
-	W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+	tmp = R_REG(&cc->pllcontrol_data);
 	ndiv_frac =
 	    (tmp & PMU1_PLL0_PC3_NDIV_FRAC_MASK) >>
 	    PMU1_PLL0_PC3_NDIV_FRAC_SHIFT;
 
-	fref = si_pmu1_alpclk0(sih, osh, cc) / 1000;
+	fref = si_pmu1_alpclk0(sih, cc) / 1000;
 
 	fvco = (fref * ndiv_int) << 8;
 	fvco += (fref * (ndiv_frac >> 12)) >> 4;
@@ -1508,7 +1500,7 @@ si_pmu1_cpuclk0(si_t *sih, struct osl_info *osh, chipcregs_t *cc)
 }
 
 /* initialize PLL */
-void si_pmu_pll_init(si_t *sih, struct osl_info *osh, uint xtalfreq)
+void si_pmu_pll_init(si_t *sih, uint xtalfreq)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -1527,7 +1519,7 @@ void si_pmu_pll_init(si_t *sih, struct osl_info *osh, uint xtalfreq)
 	case BCM4329_CHIP_ID:
 		if (xtalfreq == 0)
 			xtalfreq = 38400;
-		si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
+		si_pmu1_pllinit0(sih, cc, xtalfreq);
 		break;
 	case BCM4313_CHIP_ID:
 	case BCM43224_CHIP_ID:
@@ -1543,7 +1535,7 @@ void si_pmu_pll_init(si_t *sih, struct osl_info *osh, uint xtalfreq)
 	case BCM4319_CHIP_ID:
 	case BCM4336_CHIP_ID:
 	case BCM4330_CHIP_ID:
-		si_pmu1_pllinit0(sih, osh, cc, xtalfreq);
+		si_pmu1_pllinit0(sih, cc, xtalfreq);
 		break;
 	default:
 		PMU_MSG(("No PLL init done for chip %s rev %d pmurev %d\n",
@@ -1553,7 +1545,7 @@ void si_pmu_pll_init(si_t *sih, struct osl_info *osh, uint xtalfreq)
 	}
 
 #ifdef BCMDBG_FORCEHT
-	OR_REG(osh, &cc->clk_ctl_st, CCS_FORCEHT);
+	OR_REG(&cc->clk_ctl_st, CCS_FORCEHT);
 #endif
 
 	/* Return to original core */
@@ -1561,7 +1553,7 @@ void si_pmu_pll_init(si_t *sih, struct osl_info *osh, uint xtalfreq)
 }
 
 /* query alp/xtal clock frequency */
-u32 si_pmu_alp_clock(si_t *sih, struct osl_info *osh)
+u32 si_pmu_alp_clock(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -1599,7 +1591,7 @@ u32 si_pmu_alp_clock(si_t *sih, struct osl_info *osh)
 	case BCM4336_CHIP_ID:
 	case BCM4330_CHIP_ID:
 
-		clock = si_pmu1_alpclk0(sih, osh, cc);
+		clock = si_pmu1_alpclk0(sih, cc);
 		break;
 	case BCM5356_CHIP_ID:
 		/* always 25Mhz */
@@ -1622,8 +1614,7 @@ u32 si_pmu_alp_clock(si_t *sih, struct osl_info *osh)
  * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
  */
 static u32
-si_pmu5_clock(si_t *sih, struct osl_info *osh, chipcregs_t *cc, uint pll0,
-			  uint m) {
+si_pmu5_clock(si_t *sih, chipcregs_t *cc, uint pll0, uint m) {
 	u32 tmp, div, ndiv, p1, p2, fc;
 
 	if ((pll0 & 3) || (pll0 > PMU4716_MAINPLL_PLL0)) {
@@ -1639,29 +1630,28 @@ si_pmu5_clock(si_t *sih, struct osl_info *osh, chipcregs_t *cc, uint pll0,
 
 	if (sih->chip == BCM5357_CHIP_ID) {
 		/* Detect failure in clock setting */
-		if ((R_REG(osh, &cc->chipstatus) & 0x40000) != 0) {
+		if ((R_REG(&cc->chipstatus) & 0x40000) != 0)
 			return 133 * 1000000;
-		}
 	}
 
-	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
-	(void)R_REG(osh, &cc->pllcontrol_addr);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, pll0 + PMU5_PLL_P1P2_OFF);
+	(void)R_REG(&cc->pllcontrol_addr);
+	tmp = R_REG(&cc->pllcontrol_data);
 	p1 = (tmp & PMU5_PLL_P1_MASK) >> PMU5_PLL_P1_SHIFT;
 	p2 = (tmp & PMU5_PLL_P2_MASK) >> PMU5_PLL_P2_SHIFT;
 
-	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
-	(void)R_REG(osh, &cc->pllcontrol_addr);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, pll0 + PMU5_PLL_M14_OFF);
+	(void)R_REG(&cc->pllcontrol_addr);
+	tmp = R_REG(&cc->pllcontrol_data);
 	div = (tmp >> ((m - 1) * PMU5_PLL_MDIV_WIDTH)) & PMU5_PLL_MDIV_MASK;
 
-	W_REG(osh, &cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
-	(void)R_REG(osh, &cc->pllcontrol_addr);
-	tmp = R_REG(osh, &cc->pllcontrol_data);
+	W_REG(&cc->pllcontrol_addr, pll0 + PMU5_PLL_NM5_OFF);
+	(void)R_REG(&cc->pllcontrol_addr);
+	tmp = R_REG(&cc->pllcontrol_data);
 	ndiv = (tmp & PMU5_PLL_NDIV_MASK) >> PMU5_PLL_NDIV_SHIFT;
 
 	/* Do calculation in Mhz */
-	fc = si_pmu_alp_clock(sih, osh) / 1000000;
+	fc = si_pmu_alp_clock(sih) / 1000000;
 	fc = (p1 * ndiv * fc) / p2;
 
 	PMU_NONE(("%s: p1=%d, p2=%d, ndiv=%d(0x%x), m%d=%d; fc=%d, clock=%d\n",
@@ -1675,7 +1665,7 @@ si_pmu5_clock(si_t *sih, struct osl_info *osh, chipcregs_t *cc, uint pll0,
 /* For designs that feed the same clock to both backplane
  * and CPU just return the CPU clock speed.
  */
-u32 si_pmu_si_clock(si_t *sih, struct osl_info *osh)
+u32 si_pmu_si_clock(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -1704,19 +1694,19 @@ u32 si_pmu_si_clock(si_t *sih, struct osl_info *osh)
 	case BCM4748_CHIP_ID:
 	case BCM47162_CHIP_ID:
 		clock =
-		    si_pmu5_clock(sih, osh, cc, PMU4716_MAINPLL_PLL0,
+		    si_pmu5_clock(sih, cc, PMU4716_MAINPLL_PLL0,
 				  PMU5_MAINPLL_SI);
 		break;
 	case BCM4329_CHIP_ID:
 		if (sih->chiprev == 0)
 			clock = 38400 * 1000;
 		else
-			clock = si_pmu1_cpuclk0(sih, osh, cc);
+			clock = si_pmu1_cpuclk0(sih, cc);
 		break;
 	case BCM4319_CHIP_ID:
 	case BCM4336_CHIP_ID:
 	case BCM4330_CHIP_ID:
-		clock = si_pmu1_cpuclk0(sih, osh, cc);
+		clock = si_pmu1_cpuclk0(sih, cc);
 		break;
 	case BCM4313_CHIP_ID:
 		/* 80MHz backplane clock */
@@ -1732,12 +1722,12 @@ u32 si_pmu_si_clock(si_t *sih, struct osl_info *osh)
 		break;
 	case BCM5356_CHIP_ID:
 		clock =
-		    si_pmu5_clock(sih, osh, cc, PMU5356_MAINPLL_PLL0,
+		    si_pmu5_clock(sih, cc, PMU5356_MAINPLL_PLL0,
 				  PMU5_MAINPLL_SI);
 		break;
 	case BCM5357_CHIP_ID:
 		clock =
-		    si_pmu5_clock(sih, osh, cc, PMU5357_MAINPLL_PLL0,
+		    si_pmu5_clock(sih, cc, PMU5357_MAINPLL_PLL0,
 				  PMU5_MAINPLL_SI);
 		break;
 	default:
@@ -1754,7 +1744,7 @@ u32 si_pmu_si_clock(si_t *sih, struct osl_info *osh)
 }
 
 /* query CPU clock frequency */
-u32 si_pmu_cpu_clock(si_t *sih, struct osl_info *osh)
+u32 si_pmu_cpu_clock(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -1787,18 +1777,18 @@ u32 si_pmu_cpu_clock(si_t *sih, struct osl_info *osh)
 		cc = si_setcoreidx(sih, SI_CC_IDX);
 		ASSERT(cc != NULL);
 
-		clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_CPU);
+		clock = si_pmu5_clock(sih, cc, pll, PMU5_MAINPLL_CPU);
 
 		/* Return to original core */
 		si_setcoreidx(sih, origidx);
 	} else
-		clock = si_pmu_si_clock(sih, osh);
+		clock = si_pmu_si_clock(sih);
 
 	return clock;
 }
 
 /* query memory clock frequency */
-u32 si_pmu_mem_clock(si_t *sih, struct osl_info *osh)
+u32 si_pmu_mem_clock(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -1831,12 +1821,12 @@ u32 si_pmu_mem_clock(si_t *sih, struct osl_info *osh)
 		cc = si_setcoreidx(sih, SI_CC_IDX);
 		ASSERT(cc != NULL);
 
-		clock = si_pmu5_clock(sih, osh, cc, pll, PMU5_MAINPLL_MEM);
+		clock = si_pmu5_clock(sih, cc, pll, PMU5_MAINPLL_MEM);
 
 		/* Return to original core */
 		si_setcoreidx(sih, origidx);
 	} else {
-		clock = si_pmu_si_clock(sih, osh);
+		clock = si_pmu_si_clock(sih);
 	}
 
 	return clock;
@@ -1847,7 +1837,7 @@ u32 si_pmu_mem_clock(si_t *sih, struct osl_info *osh)
 
 static u32 ilpcycles_per_sec;
 
-u32 si_pmu_ilp_clock(si_t *sih, struct osl_info *osh)
+u32 si_pmu_ilp_clock(si_t *sih)
 {
 	if (ISSIM_ENAB(sih))
 		return ILP_CLOCK;
@@ -1857,9 +1847,9 @@ u32 si_pmu_ilp_clock(si_t *sih, struct osl_info *osh)
 		u32 origidx = si_coreidx(sih);
 		chipcregs_t *cc = si_setcoreidx(sih, SI_CC_IDX);
 		ASSERT(cc != NULL);
-		start = R_REG(osh, &cc->pmutimer);
+		start = R_REG(&cc->pmutimer);
 		mdelay(ILP_CALC_DUR);
-		end = R_REG(osh, &cc->pmutimer);
+		end = R_REG(&cc->pmutimer);
 		delta = end - start;
 		ilpcycles_per_sec = delta * (1000 / ILP_CALC_DUR);
 		si_setcoreidx(sih, origidx);
@@ -1911,8 +1901,7 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = {
 #define SDIOD_DRVSTR_KEY(chip, pmu)	(((chip) << 16) | (pmu))
 
 void
-si_sdiod_drive_strength_init(si_t *sih, struct osl_info *osh,
-					 u32 drivestrength) {
+si_sdiod_drive_strength_init(si_t *sih, u32 drivestrength) {
 	chipcregs_t *cc;
 	uint origidx, intr_val = 0;
 	sdiod_drive_str_t *str_tab = NULL;
@@ -1966,12 +1955,12 @@ si_sdiod_drive_strength_init(si_t *sih, struct osl_info *osh,
 			}
 		}
 
-		W_REG(osh, &cc->chipcontrol_addr, 1);
-		cc_data_temp = R_REG(osh, &cc->chipcontrol_data);
+		W_REG(&cc->chipcontrol_addr, 1);
+		cc_data_temp = R_REG(&cc->chipcontrol_data);
 		cc_data_temp &= ~str_mask;
 		drivestrength_sel <<= str_shift;
 		cc_data_temp |= drivestrength_sel;
-		W_REG(osh, &cc->chipcontrol_data, cc_data_temp);
+		W_REG(&cc->chipcontrol_data, cc_data_temp);
 
 		PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n",
 			 drivestrength, cc_data_temp));
@@ -1982,7 +1971,7 @@ si_sdiod_drive_strength_init(si_t *sih, struct osl_info *osh,
 }
 
 /* initialize PMU */
-void si_pmu_init(si_t *sih, struct osl_info *osh)
+void si_pmu_init(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -1995,17 +1984,17 @@ void si_pmu_init(si_t *sih, struct osl_info *osh)
 	ASSERT(cc != NULL);
 
 	if (sih->pmurev == 1)
-		AND_REG(osh, &cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
+		AND_REG(&cc->pmucontrol, ~PCTL_NOILP_ON_WAIT);
 	else if (sih->pmurev >= 2)
-		OR_REG(osh, &cc->pmucontrol, PCTL_NOILP_ON_WAIT);
+		OR_REG(&cc->pmucontrol, PCTL_NOILP_ON_WAIT);
 
 	if ((sih->chip == BCM4329_CHIP_ID) && (sih->chiprev == 2)) {
 		/* Fix for 4329b0 bad LPOM state. */
-		W_REG(osh, &cc->regcontrol_addr, 2);
-		OR_REG(osh, &cc->regcontrol_data, 0x100);
+		W_REG(&cc->regcontrol_addr, 2);
+		OR_REG(&cc->regcontrol_data, 0x100);
 
-		W_REG(osh, &cc->regcontrol_addr, 3);
-		OR_REG(osh, &cc->regcontrol_data, 0x4);
+		W_REG(&cc->regcontrol_addr, 3);
+		OR_REG(&cc->regcontrol_data, 0x4);
 	}
 
 	/* Return to original core */
@@ -2014,22 +2003,21 @@ void si_pmu_init(si_t *sih, struct osl_info *osh)
 
 /* Return up time in ILP cycles for the given resource. */
 static uint
-si_pmu_res_uptime(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
-			      u8 rsrc) {
+si_pmu_res_uptime(si_t *sih, chipcregs_t *cc, u8 rsrc) {
 	u32 deps;
 	uint up, i, dup, dmax;
 	u32 min_mask = 0, max_mask = 0;
 
 	/* uptime of resource 'rsrc' */
-	W_REG(osh, &cc->res_table_sel, rsrc);
-	up = (R_REG(osh, &cc->res_updn_timer) >> 8) & 0xff;
+	W_REG(&cc->res_table_sel, rsrc);
+	up = (R_REG(&cc->res_updn_timer) >> 8) & 0xff;
 
 	/* direct dependancies of resource 'rsrc' */
-	deps = si_pmu_res_deps(sih, osh, cc, PMURES_BIT(rsrc), false);
+	deps = si_pmu_res_deps(sih, cc, PMURES_BIT(rsrc), false);
 	for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
 		if (!(deps & PMURES_BIT(i)))
 			continue;
-		deps &= ~si_pmu_res_deps(sih, osh, cc, PMURES_BIT(i), true);
+		deps &= ~si_pmu_res_deps(sih, cc, PMURES_BIT(i), true);
 	}
 	si_pmu_res_masks(sih, &min_mask, &max_mask);
 	deps &= ~min_mask;
@@ -2039,7 +2027,7 @@ si_pmu_res_uptime(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 	for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
 		if (!(deps & PMURES_BIT(i)))
 			continue;
-		dup = si_pmu_res_uptime(sih, osh, cc, (u8) i);
+		dup = si_pmu_res_uptime(sih, cc, (u8) i);
 		if (dmax < dup)
 			dmax = dup;
 	}
@@ -2051,7 +2039,7 @@ si_pmu_res_uptime(si_t *sih, struct osl_info *osh, chipcregs_t *cc,
 
 /* Return dependancies (direct or all/indirect) for the given resources */
 static u32
-si_pmu_res_deps(si_t *sih, struct osl_info *osh, chipcregs_t *cc, u32 rsrcs,
+si_pmu_res_deps(si_t *sih, chipcregs_t *cc, u32 rsrcs,
 		bool all)
 {
 	u32 deps = 0;
@@ -2060,18 +2048,18 @@ si_pmu_res_deps(si_t *sih, struct osl_info *osh, chipcregs_t *cc, u32 rsrcs,
 	for (i = 0; i <= PMURES_MAX_RESNUM; i++) {
 		if (!(rsrcs & PMURES_BIT(i)))
 			continue;
-		W_REG(osh, &cc->res_table_sel, i);
-		deps |= R_REG(osh, &cc->res_dep_mask);
+		W_REG(&cc->res_table_sel, i);
+		deps |= R_REG(&cc->res_dep_mask);
 	}
 
 	return !all ? deps : (deps
 			      ? (deps |
-				 si_pmu_res_deps(sih, osh, cc, deps,
+				 si_pmu_res_deps(sih, cc, deps,
 						 true)) : 0);
 }
 
 /* power up/down OTP through PMU resources */
-void si_pmu_otp_power(si_t *sih, struct osl_info *osh, bool on)
+void si_pmu_otp_power(si_t *sih, bool on)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -2111,7 +2099,7 @@ void si_pmu_otp_power(si_t *sih, struct osl_info *osh, bool on)
 		u32 otps;
 
 		/* Figure out the dependancies (exclude min_res_mask) */
-		u32 deps = si_pmu_res_deps(sih, osh, cc, rsrcs, true);
+		u32 deps = si_pmu_res_deps(sih, cc, rsrcs, true);
 		u32 min_mask = 0, max_mask = 0;
 		si_pmu_res_masks(sih, &min_mask, &max_mask);
 		deps &= ~min_mask;
@@ -2119,17 +2107,17 @@ void si_pmu_otp_power(si_t *sih, struct osl_info *osh, bool on)
 		if (on) {
 			PMU_MSG(("Adding rsrc 0x%x to min_res_mask\n",
 				 rsrcs | deps));
-			OR_REG(osh, &cc->min_res_mask, (rsrcs | deps));
-			SPINWAIT(!(R_REG(osh, &cc->res_state) & rsrcs),
+			OR_REG(&cc->min_res_mask, (rsrcs | deps));
+			SPINWAIT(!(R_REG(&cc->res_state) & rsrcs),
 				 PMU_MAX_TRANSITION_DLY);
-			ASSERT(R_REG(osh, &cc->res_state) & rsrcs);
+			ASSERT(R_REG(&cc->res_state) & rsrcs);
 		} else {
 			PMU_MSG(("Removing rsrc 0x%x from min_res_mask\n",
 				 rsrcs | deps));
-			AND_REG(osh, &cc->min_res_mask, ~(rsrcs | deps));
+			AND_REG(&cc->min_res_mask, ~(rsrcs | deps));
 		}
 
-		SPINWAIT((((otps = R_REG(osh, &cc->otpstatus)) & OTPS_READY) !=
+		SPINWAIT((((otps = R_REG(&cc->otpstatus)) & OTPS_READY) !=
 			  (on ? OTPS_READY : 0)), 100);
 		ASSERT((otps & OTPS_READY) == (on ? OTPS_READY : 0));
 		if ((otps & OTPS_READY) != (on ? OTPS_READY : 0))
@@ -2141,7 +2129,7 @@ void si_pmu_otp_power(si_t *sih, struct osl_info *osh, bool on)
 	si_setcoreidx(sih, origidx);
 }
 
-void si_pmu_rcal(si_t *sih, struct osl_info *osh)
+void si_pmu_rcal(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -2159,60 +2147,56 @@ void si_pmu_rcal(si_t *sih, struct osl_info *osh)
 			u32 val;
 
 			/* Kick RCal */
-			W_REG(osh, &cc->chipcontrol_addr, 1);
+			W_REG(&cc->chipcontrol_addr, 1);
 
 			/* Power Down RCAL Block */
-			AND_REG(osh, &cc->chipcontrol_data, ~0x04);
+			AND_REG(&cc->chipcontrol_data, ~0x04);
 
 			/* Power Up RCAL block */
-			OR_REG(osh, &cc->chipcontrol_data, 0x04);
+			OR_REG(&cc->chipcontrol_data, 0x04);
 
 			/* Wait for completion */
-			SPINWAIT(0 == (R_REG(osh, &cc->chipstatus) & 0x08),
+			SPINWAIT(0 == (R_REG(&cc->chipstatus) & 0x08),
 				 10 * 1000 * 1000);
-			ASSERT(R_REG(osh, &cc->chipstatus) & 0x08);
+			ASSERT(R_REG(&cc->chipstatus) & 0x08);
 
 			/* Drop the LSB to convert from 5 bit code to 4 bit code */
 			rcal_code =
-			    (u8) (R_REG(osh, &cc->chipstatus) >> 5) & 0x0f;
+			    (u8) (R_REG(&cc->chipstatus) >> 5) & 0x0f;
 
 			PMU_MSG(("RCal completed, status 0x%x, code 0x%x\n",
-				 R_REG(osh, &cc->chipstatus), rcal_code));
+				 R_REG(&cc->chipstatus), rcal_code));
 
 			/* Write RCal code into pmu_vreg_ctrl[32:29] */
-			W_REG(osh, &cc->regcontrol_addr, 0);
+			W_REG(&cc->regcontrol_addr, 0);
 			val =
-			    R_REG(osh,
-				  &cc->
-				  regcontrol_data) & ~((u32) 0x07 << 29);
+			    R_REG(&cc->regcontrol_data) & ~((u32) 0x07 << 29);
 			val |= (u32) (rcal_code & 0x07) << 29;
-			W_REG(osh, &cc->regcontrol_data, val);
-			W_REG(osh, &cc->regcontrol_addr, 1);
-			val = R_REG(osh, &cc->regcontrol_data) & ~(u32) 0x01;
+			W_REG(&cc->regcontrol_data, val);
+			W_REG(&cc->regcontrol_addr, 1);
+			val = R_REG(&cc->regcontrol_data) & ~(u32) 0x01;
 			val |= (u32) ((rcal_code >> 3) & 0x01);
-			W_REG(osh, &cc->regcontrol_data, val);
+			W_REG(&cc->regcontrol_data, val);
 
 			/* Write RCal code into pmu_chip_ctrl[33:30] */
-			W_REG(osh, &cc->chipcontrol_addr, 0);
+			W_REG(&cc->chipcontrol_addr, 0);
 			val =
-			    R_REG(osh,
-				  &cc->
-				  chipcontrol_data) & ~((u32) 0x03 << 30);
+			    R_REG(&cc->chipcontrol_data) & ~((u32) 0x03 << 30);
 			val |= (u32) (rcal_code & 0x03) << 30;
-			W_REG(osh, &cc->chipcontrol_data, val);
-			W_REG(osh, &cc->chipcontrol_addr, 1);
+			W_REG(&cc->chipcontrol_data, val);
+			W_REG(&cc->chipcontrol_addr, 1);
 			val =
-			    R_REG(osh, &cc->chipcontrol_data) & ~(u32) 0x03;
+			    R_REG(&cc->chipcontrol_data) & ~(u32) 0x03;
 			val |= (u32) ((rcal_code >> 2) & 0x03);
-			W_REG(osh, &cc->chipcontrol_data, val);
+			W_REG(&cc->chipcontrol_data, val);
 
 			/* Set override in pmu_chip_ctrl[29] */
-			W_REG(osh, &cc->chipcontrol_addr, 0);
-			OR_REG(osh, &cc->chipcontrol_data, (0x01 << 29));
+			W_REG(&cc->chipcontrol_addr, 0);
+			OR_REG(&cc->chipcontrol_data, (0x01 << 29));
 
 			/* Power off RCal block */
-			W_REG(osh, &cc->chipcontrol_addr, 1);
-			AND_REG(osh, &cc->chipcontrol_data, ~0x04);
+			W_REG(&cc->chipcontrol_addr, 1);
+			AND_REG(&cc->chipcontrol_data, ~0x04);
 
 			break;
 		}
@@ -2224,7 +2208,7 @@ void si_pmu_rcal(si_t *sih, struct osl_info *osh)
 	si_setcoreidx(sih, origidx);
 }
 
-void si_pmu_spuravoid(si_t *sih, struct osl_info *osh, u8 spuravoid)
+void si_pmu_spuravoid(si_t *sih, u8 spuravoid)
 {
 	chipcregs_t *cc;
 	uint origidx, intr_val;
@@ -2237,23 +2221,23 @@ void si_pmu_spuravoid(si_t *sih, struct osl_info *osh, u8 spuravoid)
 
 	/* force the HT off  */
 	if (sih->chip == BCM4336_CHIP_ID) {
-		tmp = R_REG(osh, &cc->max_res_mask);
+		tmp = R_REG(&cc->max_res_mask);
 		tmp &= ~RES4336_HT_AVAIL;
-		W_REG(osh, &cc->max_res_mask, tmp);
+		W_REG(&cc->max_res_mask, tmp);
 		/* wait for the ht to really go away */
-		SPINWAIT(((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0),
+		SPINWAIT(((R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL) == 0),
 			 10000);
-		ASSERT((R_REG(osh, &cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
+		ASSERT((R_REG(&cc->clk_ctl_st) & CCS_HTAVAIL) == 0);
 	}
 
 	/* update the pll changes */
-	si_pmu_spuravoid_pllupdate(sih, cc, osh, spuravoid);
+	si_pmu_spuravoid_pllupdate(sih, cc, spuravoid);
 
 	/* enable HT back on  */
 	if (sih->chip == BCM4336_CHIP_ID) {
-		tmp = R_REG(osh, &cc->max_res_mask);
+		tmp = R_REG(&cc->max_res_mask);
 		tmp |= RES4336_HT_AVAIL;
-		W_REG(osh, &cc->max_res_mask, tmp);
+		W_REG(&cc->max_res_mask, tmp);
 	}
 
 	/* Return to original core */
@@ -2261,8 +2245,7 @@ void si_pmu_spuravoid(si_t *sih, struct osl_info *osh, u8 spuravoid)
 }
 
 static void
-si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, struct osl_info *osh,
-			   u8 spuravoid)
+si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, u8 spuravoid)
 {
 	u32 tmp = 0;
 	u8 phypll_offset = 0;
@@ -2279,44 +2262,44 @@ si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, struct osl_info *osh,
 		phypll_offset = (sih->chip == BCM5357_CHIP_ID) ? 6 : 0;
 
 		/* RMW only the P1 divider */
-		W_REG(osh, &cc->pllcontrol_addr,
+		W_REG(&cc->pllcontrol_addr,
 		      PMU1_PLL0_PLLCTL0 + phypll_offset);
-		tmp = R_REG(osh, &cc->pllcontrol_data);
+		tmp = R_REG(&cc->pllcontrol_data);
 		tmp &= (~(PMU1_PLL0_PC0_P1DIV_MASK));
 		tmp |=
 		    (bcm5357_bcm43236_p1div[spuravoid] <<
 		     PMU1_PLL0_PC0_P1DIV_SHIFT);
-		W_REG(osh, &cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_data, tmp);
 
 		/* RMW only the int feedback divider */
-		W_REG(osh, &cc->pllcontrol_addr,
+		W_REG(&cc->pllcontrol_addr,
 		      PMU1_PLL0_PLLCTL2 + phypll_offset);
-		tmp = R_REG(osh, &cc->pllcontrol_data);
+		tmp = R_REG(&cc->pllcontrol_data);
 		tmp &= ~(PMU1_PLL0_PC2_NDIV_INT_MASK);
 		tmp |=
 		    (bcm5357_bcm43236_ndiv[spuravoid]) <<
 		    PMU1_PLL0_PC2_NDIV_INT_SHIFT;
-		W_REG(osh, &cc->pllcontrol_data, tmp);
+		W_REG(&cc->pllcontrol_data, tmp);
 
 		tmp = 1 << 10;
 		break;
 
 	case BCM4331_CHIP_ID:
 		if (spuravoid == 2) {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11500014);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x0FC00a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11500014);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x0FC00a08);
 		} else if (spuravoid == 1) {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11500014);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11500014);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x0F600a08);
 		} else {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11100014);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11100014);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x03000a08);
 		}
 		tmp = 1 << 10;
 		break;
@@ -2326,47 +2309,47 @@ si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, struct osl_info *osh,
 	case BCM43421_CHIP_ID:
 	case BCM6362_CHIP_ID:
 		if (spuravoid == 1) {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11500010);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(osh, &cc->pllcontrol_data, 0x000C0C06);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x0F600a08);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(osh, &cc->pllcontrol_data, 0x2001E920);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11500010);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+			W_REG(&cc->pllcontrol_data, 0x000C0C06);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x0F600a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+			W_REG(&cc->pllcontrol_data, 0x00000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+			W_REG(&cc->pllcontrol_data, 0x2001E920);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+			W_REG(&cc->pllcontrol_data, 0x88888815);
 		} else {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11100010);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(osh, &cc->pllcontrol_data, 0x000c0c06);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11100010);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+			W_REG(&cc->pllcontrol_data, 0x000c0c06);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x03000a08);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+			W_REG(&cc->pllcontrol_data, 0x00000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+			W_REG(&cc->pllcontrol_data, 0x200005c0);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+			W_REG(&cc->pllcontrol_data, 0x88888815);
 		}
 		tmp = 1 << 10;
 		break;
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-		W_REG(osh, &cc->pllcontrol_data, 0x11100008);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		W_REG(osh, &cc->pllcontrol_data, 0x0c000c06);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-		W_REG(osh, &cc->pllcontrol_data, 0x03000a08);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-		W_REG(osh, &cc->pllcontrol_data, 0x00000000);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-		W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		W_REG(osh, &cc->pllcontrol_data, 0x88888855);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+		W_REG(&cc->pllcontrol_data, 0x11100008);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+		W_REG(&cc->pllcontrol_data, 0x0c000c06);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+		W_REG(&cc->pllcontrol_data, 0x03000a08);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+		W_REG(&cc->pllcontrol_data, 0x00000000);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+		W_REG(&cc->pllcontrol_data, 0x200005c0);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+		W_REG(&cc->pllcontrol_data, 0x88888855);
 
 		tmp = 1 << 10;
 		break;
@@ -2375,74 +2358,74 @@ si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, struct osl_info *osh,
 	case BCM4748_CHIP_ID:
 	case BCM47162_CHIP_ID:
 		if (spuravoid == 1) {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11500060);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(osh, &cc->pllcontrol_data, 0x080C0C06);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x0F600000);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(osh, &cc->pllcontrol_data, 0x2001E924);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11500060);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+			W_REG(&cc->pllcontrol_data, 0x080C0C06);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x0F600000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+			W_REG(&cc->pllcontrol_data, 0x00000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+			W_REG(&cc->pllcontrol_data, 0x2001E924);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+			W_REG(&cc->pllcontrol_data, 0x88888815);
 		} else {
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-			W_REG(osh, &cc->pllcontrol_data, 0x11100060);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-			W_REG(osh, &cc->pllcontrol_data, 0x080c0c06);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x03000000);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
-			W_REG(osh, &cc->pllcontrol_data, 0x00000000);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-			W_REG(osh, &cc->pllcontrol_data, 0x200005c0);
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-			W_REG(osh, &cc->pllcontrol_data, 0x88888815);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+			W_REG(&cc->pllcontrol_data, 0x11100060);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+			W_REG(&cc->pllcontrol_data, 0x080c0c06);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x03000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+			W_REG(&cc->pllcontrol_data, 0x00000000);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+			W_REG(&cc->pllcontrol_data, 0x200005c0);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+			W_REG(&cc->pllcontrol_data, 0x88888815);
 		}
 
 		tmp = 3 << 9;
 		break;
 
 	case BCM4319_CHIP_ID:
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-		W_REG(osh, &cc->pllcontrol_data, 0x11100070);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		W_REG(osh, &cc->pllcontrol_data, 0x1014140a);
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		W_REG(osh, &cc->pllcontrol_data, 0x88888854);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+		W_REG(&cc->pllcontrol_data, 0x11100070);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+		W_REG(&cc->pllcontrol_data, 0x1014140a);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+		W_REG(&cc->pllcontrol_data, 0x88888854);
 
 		if (spuravoid == 1) {	/* spur_avoid ON, enable 41/82/164Mhz clock mode */
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x05201828);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x05201828);
 		} else {	/* enable 40/80/160Mhz clock mode */
-			W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-			W_REG(osh, &cc->pllcontrol_data, 0x05001828);
+			W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+			W_REG(&cc->pllcontrol_data, 0x05001828);
 		}
 		break;
 	case BCM4336_CHIP_ID:
 		/* Looks like these are only for default xtal freq 26MHz */
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
-		W_REG(osh, &cc->pllcontrol_data, 0x02100020);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL0);
+		W_REG(&cc->pllcontrol_data, 0x02100020);
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
-		W_REG(osh, &cc->pllcontrol_data, 0x0C0C0C0C);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL1);
+		W_REG(&cc->pllcontrol_data, 0x0C0C0C0C);
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
-		W_REG(osh, &cc->pllcontrol_data, 0x01240C0C);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL2);
+		W_REG(&cc->pllcontrol_data, 0x01240C0C);
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
-		W_REG(osh, &cc->pllcontrol_data, 0x202C2820);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL4);
+		W_REG(&cc->pllcontrol_data, 0x202C2820);
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
-		W_REG(osh, &cc->pllcontrol_data, 0x88888825);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL5);
+		W_REG(&cc->pllcontrol_data, 0x88888825);
 
-		W_REG(osh, &cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
+		W_REG(&cc->pllcontrol_addr, PMU1_PLL0_PLLCTL3);
 		if (spuravoid == 1) {
-			W_REG(osh, &cc->pllcontrol_data, 0x00EC4EC4);
+			W_REG(&cc->pllcontrol_data, 0x00EC4EC4);
 		} else {
-			W_REG(osh, &cc->pllcontrol_data, 0x00762762);
+			W_REG(&cc->pllcontrol_data, 0x00762762);
 		}
 
 		tmp = PCTL_PLL_PLLCTL_UPD;
@@ -2453,11 +2436,11 @@ si_pmu_spuravoid_pllupdate(si_t *sih, chipcregs_t *cc, struct osl_info *osh,
 		break;
 	}
 
-	tmp |= R_REG(osh, &cc->pmucontrol);
-	W_REG(osh, &cc->pmucontrol, tmp);
+	tmp |= R_REG(&cc->pmucontrol);
+	W_REG(&cc->pmucontrol, tmp);
 }
 
-bool si_pmu_is_otp_powered(si_t *sih, struct osl_info *osh)
+bool si_pmu_is_otp_powered(si_t *sih)
 {
 	uint idx;
 	chipcregs_t *cc;
@@ -2470,19 +2453,19 @@ bool si_pmu_is_otp_powered(si_t *sih, struct osl_info *osh)
 
 	switch (sih->chip) {
 	case BCM4329_CHIP_ID:
-		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4329_OTP_PU))
+		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4329_OTP_PU))
 		    != 0;
 		break;
 	case BCM4319_CHIP_ID:
-		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4319_OTP_PU))
+		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4319_OTP_PU))
 		    != 0;
 		break;
 	case BCM4336_CHIP_ID:
-		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4336_OTP_PU))
+		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4336_OTP_PU))
 		    != 0;
 		break;
 	case BCM4330_CHIP_ID:
-		st = (R_REG(osh, &cc->res_state) & PMURES_BIT(RES4330_OTP_PU))
+		st = (R_REG(&cc->res_state) & PMURES_BIT(RES4330_OTP_PU))
 		    != 0;
 		break;
 
@@ -2507,12 +2490,7 @@ bool si_pmu_is_otp_powered(si_t *sih, struct osl_info *osh)
 	return st;
 }
 
-void
-#if defined(BCMDBG)
-si_pmu_sprom_enable(si_t *sih, struct osl_info *osh, bool enable)
-#else
-si_pmu_sprom_enable(si_t *sih, struct osl_info *osh, bool enable)
-#endif
+void si_pmu_sprom_enable(si_t *sih, bool enable)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -2527,7 +2505,7 @@ si_pmu_sprom_enable(si_t *sih, struct osl_info *osh, bool enable)
 }
 
 /* initialize PMU chip controls and other chip level stuff */
-void si_pmu_chip_init(si_t *sih, struct osl_info *osh)
+void si_pmu_chip_init(si_t *sih)
 {
 	uint origidx;
 
@@ -2539,7 +2517,7 @@ void si_pmu_chip_init(si_t *sih, struct osl_info *osh)
 #endif				/* CHIPC_UART_ALWAYS_ON */
 
 	/* Gate off SPROM clock and chip select signals */
-	si_pmu_sprom_enable(sih, osh, false);
+	si_pmu_sprom_enable(sih, false);
 
 	/* Remember original core */
 	origidx = si_coreidx(sih);
@@ -2549,26 +2527,26 @@ void si_pmu_chip_init(si_t *sih, struct osl_info *osh)
 }
 
 /* initialize PMU switch/regulators */
-void si_pmu_swreg_init(si_t *sih, struct osl_info *osh)
+void si_pmu_swreg_init(si_t *sih)
 {
 	ASSERT(sih->cccaps & CC_CAP_PMU);
 
 	switch (sih->chip) {
 	case BCM4336_CHIP_ID:
 		/* Reduce CLDO PWM output voltage to 1.2V */
-		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
+		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_CLDO_PWM, 0xe);
 		/* Reduce CLDO BURST output voltage to 1.2V */
-		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CLDO_BURST,
+		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_CLDO_BURST,
 				       0xe);
 		/* Reduce LNLDO1 output voltage to 1.2V */
-		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_LNLDO1, 0xe);
+		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_LNLDO1, 0xe);
 		if (sih->chiprev == 0)
 			si_pmu_regcontrol(sih, 2, 0x400000, 0x400000);
 		break;
 
 	case BCM4330_CHIP_ID:
 		/* CBUCK Voltage is 1.8 by default and set that to 1.5 */
-		si_pmu_set_ldo_voltage(sih, osh, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
+		si_pmu_set_ldo_voltage(sih, SET_LDO_VOLTAGE_CBUCK_PWM, 0);
 		break;
 	default:
 		break;
@@ -2593,8 +2571,7 @@ void si_pmu_radio_enable(si_t *sih, bool enable)
 
 /* Wait for a particular clock level to be on the backplane */
 u32
-si_pmu_waitforclk_on_backplane(si_t *sih, struct osl_info *osh, u32 clk,
-			       u32 delay)
+si_pmu_waitforclk_on_backplane(si_t *sih, u32 clk, u32 delay)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -2607,12 +2584,12 @@ si_pmu_waitforclk_on_backplane(si_t *sih, struct osl_info *osh, u32 clk,
 	ASSERT(cc != NULL);
 
 	if (delay)
-		SPINWAIT(((R_REG(osh, &cc->pmustatus) & clk) != clk), delay);
+		SPINWAIT(((R_REG(&cc->pmustatus) & clk) != clk), delay);
 
 	/* Return to original core */
 	si_setcoreidx(sih, origidx);
 
-	return R_REG(osh, &cc->pmustatus) & clk;
+	return R_REG(&cc->pmustatus) & clk;
 }
 
 /*
@@ -2622,7 +2599,7 @@ si_pmu_waitforclk_on_backplane(si_t *sih, struct osl_info *osh, u32 clk,
 
 #define EXT_ILP_HZ 32768
 
-u32 si_pmu_measure_alpclk(si_t *sih, struct osl_info *osh)
+u32 si_pmu_measure_alpclk(si_t *sih)
 {
 	chipcregs_t *cc;
 	uint origidx;
@@ -2638,11 +2615,11 @@ u32 si_pmu_measure_alpclk(si_t *sih, struct osl_info *osh)
 	cc = si_setcoreidx(sih, SI_CC_IDX);
 	ASSERT(cc != NULL);
 
-	if (R_REG(osh, &cc->pmustatus) & PST_EXTLPOAVAIL) {
+	if (R_REG(&cc->pmustatus) & PST_EXTLPOAVAIL) {
 		u32 ilp_ctr, alp_hz;
 
 		/* Enable the reg to measure the freq, in case disabled before */
-		W_REG(osh, &cc->pmu_xtalfreq,
+		W_REG(&cc->pmu_xtalfreq,
 		      1U << PMU_XTALFREQ_REG_MEASURE_SHIFT);
 
 		/* Delay for well over 4 ILP clocks */
@@ -2650,11 +2627,10 @@ u32 si_pmu_measure_alpclk(si_t *sih, struct osl_info *osh)
 
 		/* Read the latched number of ALP ticks per 4 ILP ticks */
 		ilp_ctr =
-		    R_REG(osh,
-			  &cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
+		    R_REG(&cc->pmu_xtalfreq) & PMU_XTALFREQ_REG_ILPCTR_MASK;
 
 		/* Turn off the PMU_XTALFREQ_REG_MEASURE_SHIFT bit to save power */
-		W_REG(osh, &cc->pmu_xtalfreq, 0);
+		W_REG(&cc->pmu_xtalfreq, 0);
 
 		/* Calculate ALP frequency */
 		alp_hz = (ilp_ctr * EXT_ILP_HZ) / 4;
diff --git a/drivers/staging/brcm80211/util/linux_osl.c b/drivers/staging/brcm80211/util/linux_osl.c
deleted file mode 100644
index e6716e8..0000000
--- a/drivers/staging/brcm80211/util/linux_osl.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2010 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/delay.h>
-#include <linux/fs.h>
-#ifdef mips
-#include <asm/paccess.h>
-#endif				/* mips */
-#include <bcmendian.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/netdevice.h>
-#include <linux/sched.h>
-#include <bcmdefs.h>
-#include <osl.h>
-#include <bcmutils.h>
-#include <pcicfg.h>
-
-
-#define OS_HANDLE_MAGIC		0x1234abcd	/* Magic # to recognise osh */
-#define BCM_MEM_FILENAME_LEN 	24	/* Mem. filename length */
-
-/* Global ASSERT type flag */
-u32 g_assert_type;
-
-struct osl_info *osl_attach(void *pdev, uint bustype)
-{
-	struct osl_info *osh;
-
-	osh = kmalloc(sizeof(struct osl_info), GFP_ATOMIC);
-	ASSERT(osh);
-
-	memset(osh, 0, sizeof(struct osl_info));
-
-	osh->magic = OS_HANDLE_MAGIC;
-	osh->pdev = pdev;
-	osh->bustype = bustype;
-
-	switch (bustype) {
-	case PCI_BUS:
-	case SI_BUS:
-	case PCMCIA_BUS:
-		osh->mmbus = true;
-		break;
-	case JTAG_BUS:
-	case SDIO_BUS:
-	case USB_BUS:
-	case SPI_BUS:
-	case RPC_BUS:
-		osh->mmbus = false;
-		break;
-	default:
-		ASSERT(false);
-		break;
-	}
-
-	return osh;
-}
-
-void osl_detach(struct osl_info *osh)
-{
-	if (osh == NULL)
-		return;
-
-	ASSERT(osh->magic == OS_HANDLE_MAGIC);
-	kfree(osh);
-}
-
-struct sk_buff *BCMFASTPATH pkt_buf_get_skb(struct osl_info *osh, uint len)
-{
-	struct sk_buff *skb;
-
-	skb = dev_alloc_skb(len);
-	if (skb) {
-		skb_put(skb, len);
-		skb->priority = 0;
-
-		osh->pktalloced++;
-	}
-
-	return skb;
-}
-
-/* Free the driver packet. Free the tag if present */
-void BCMFASTPATH pkt_buf_free_skb(struct osl_info *osh, struct sk_buff *skb, bool send)
-{
-	struct sk_buff *nskb;
-	int nest = 0;
-
-	ASSERT(skb);
-
-	/* perversion: we use skb->next to chain multi-skb packets */
-	while (skb) {
-		nskb = skb->next;
-		skb->next = NULL;
-
-		if (skb->destructor)
-			/* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
-			 * destructor exists
-			 */
-			dev_kfree_skb_any(skb);
-		else
-			/* can free immediately (even in_irq()) if destructor
-			 * does not exist
-			 */
-			dev_kfree_skb(skb);
-
-		osh->pktalloced--;
-		nest++;
-		skb = nskb;
-	}
-}
-
-/* return bus # for the pci device pointed by osh->pdev */
-uint osl_pci_bus(struct osl_info *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-	return ((struct pci_dev *)osh->pdev)->bus->number;
-}
-
-/* return slot # for the pci device pointed by osh->pdev */
-uint osl_pci_slot(struct osl_info *osh)
-{
-	ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev);
-
-	return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn);
-}
-
-void *osl_dma_alloc_consistent(struct osl_info *osh, uint size, u16 align_bits,
-			       uint *alloced, unsigned long *pap)
-{
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-	if (align_bits) {
-		u16 align = (1 << align_bits);
-		if (!IS_ALIGNED(PAGE_SIZE, align))
-			size += align;
-		*alloced = size;
-	}
-	return pci_alloc_consistent(osh->pdev, size, (dma_addr_t *) pap);
-}
-
-void osl_dma_free_consistent(struct osl_info *osh, void *va, uint size,
-			     unsigned long pa)
-{
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-
-	pci_free_consistent(osh->pdev, size, va, (dma_addr_t) pa);
-}
-
-uint BCMFASTPATH osl_dma_map(struct osl_info *osh, void *va, uint size,
-			     int direction)
-{
-	int dir;
-
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-	dir = (direction == DMA_TX) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE;
-	return pci_map_single(osh->pdev, va, size, dir);
-}
-
-void BCMFASTPATH osl_dma_unmap(struct osl_info *osh, uint pa, uint size,
-			       int direction)
-{
-	int dir;
-
-	ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC)));
-	dir = (direction == DMA_TX) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE;
-	pci_unmap_single(osh->pdev, (u32) pa, size, dir);
-}
-
-#if defined(BCMDBG_ASSERT)
-void osl_assert(char *exp, char *file, int line)
-{
-	char tempbuf[256];
-	char *basename;
-
-	basename = strrchr(file, '/');
-	/* skip the '/' */
-	if (basename)
-		basename++;
-
-	if (!basename)
-		basename = file;
-
-#ifdef BCMDBG_ASSERT
-	snprintf(tempbuf, 256,
-		 "assertion \"%s\" failed: file \"%s\", line %d\n", exp,
-		 basename, line);
-
-	/* Print assert message and give it time to be written to /var/log/messages */
-	if (!in_interrupt()) {
-		const int delay = 3;
-		printk(KERN_ERR "%s", tempbuf);
-		printk(KERN_ERR "panic in %d seconds\n", delay);
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(delay * HZ);
-	}
-
-	switch (g_assert_type) {
-	case 0:
-		panic(KERN_ERR "%s", tempbuf);
-		break;
-	case 1:
-		printk(KERN_ERR "%s", tempbuf);
-		BUG();
-		break;
-	case 2:
-		printk(KERN_ERR "%s", tempbuf);
-		break;
-	default:
-		break;
-	}
-#endif				/* BCMDBG_ASSERT */
-
-}
-#endif				/* defined(BCMDBG_ASSERT) */
-
diff --git a/drivers/staging/brcm80211/util/nicpci.c b/drivers/staging/brcm80211/util/nicpci.c
index 56e658c..a1fb2f0 100644
--- a/drivers/staging/brcm80211/util/nicpci.c
+++ b/drivers/staging/brcm80211/util/nicpci.c
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <siutils.h>
 #include <hndsoc.h>
@@ -36,7 +35,7 @@ typedef struct {
 	} regs;			/* Memory mapped register to the core */
 
 	si_t *sih;		/* System interconnect handle */
-	struct osl_info *osh;		/* OSL handle */
+	struct pci_dev *dev;
 	u8 pciecap_lcreg_offset;	/* PCIE capability LCreg offset in the config space */
 	bool pcie_pr42767;
 	u8 pcie_polarity;
@@ -80,7 +79,7 @@ static bool pcicore_pmecap(pcicore_info_t *pi);
 /* Initialize the PCI core. It's caller's responsibility to make sure that this is done
  * only once
  */
-void *pcicore_init(si_t *sih, struct osl_info *osh, void *regs)
+void *pcicore_init(si_t *sih, void *pdev, void *regs)
 {
 	pcicore_info_t *pi;
 
@@ -94,13 +93,13 @@ void *pcicore_init(si_t *sih, struct osl_info *osh, void *regs)
 	}
 
 	pi->sih = sih;
-	pi->osh = osh;
+	pi->dev = pdev;
 
 	if (sih->buscoretype == PCIE_CORE_ID) {
 		u8 cap_ptr;
 		pi->regs.pcieregs = (sbpcieregs_t *) regs;
 		cap_ptr =
-		    pcicore_find_pci_capability(pi->osh, PCI_CAP_PCIECAP_ID,
+		    pcicore_find_pci_capability(pi->dev, PCI_CAP_PCIECAP_ID,
 						NULL, NULL);
 		ASSERT(cap_ptr);
 		pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET;
@@ -122,7 +121,7 @@ void pcicore_deinit(void *pch)
 /* return cap_offset if requested capability exists in the PCI config space */
 /* Note that it's caller's responsibility to make sure it's a pci bus */
 u8
-pcicore_find_pci_capability(struct osl_info *osh, u8 req_cap_id,
+pcicore_find_pci_capability(void *dev, u8 req_cap_id,
 			    unsigned char *buf, u32 *buflen)
 {
 	u8 cap_id;
@@ -131,29 +130,29 @@ pcicore_find_pci_capability(struct osl_info *osh, u8 req_cap_id,
 	u8 byte_val;
 
 	/* check for Header type 0 */
-	pci_read_config_byte(osh->pdev, PCI_CFG_HDR, &byte_val);
+	pci_read_config_byte(dev, PCI_CFG_HDR, &byte_val);
 	if ((byte_val & 0x7f) != PCI_HEADER_NORMAL)
 		goto end;
 
 	/* check if the capability pointer field exists */
-	pci_read_config_byte(osh->pdev, PCI_CFG_STAT, &byte_val);
+	pci_read_config_byte(dev, PCI_CFG_STAT, &byte_val);
 	if (!(byte_val & PCI_CAPPTR_PRESENT))
 		goto end;
 
-	pci_read_config_byte(osh->pdev, PCI_CFG_CAPPTR, &cap_ptr);
+	pci_read_config_byte(dev, PCI_CFG_CAPPTR, &cap_ptr);
 	/* check if the capability pointer is 0x00 */
 	if (cap_ptr == 0x00)
 		goto end;
 
 	/* loop thr'u the capability list and see if the pcie capabilty exists */
 
-	pci_read_config_byte(osh->pdev, cap_ptr, &cap_id);
+	pci_read_config_byte(dev, cap_ptr, &cap_id);
 
 	while (cap_id != req_cap_id) {
-		pci_read_config_byte(osh->pdev, cap_ptr + 1, &cap_ptr);
+		pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr);
 		if (cap_ptr == 0x00)
 			break;
-		pci_read_config_byte(osh->pdev, cap_ptr, &cap_id);
+		pci_read_config_byte(dev, cap_ptr, &cap_id);
 	}
 	if (cap_id != req_cap_id) {
 		goto end;
@@ -172,7 +171,7 @@ pcicore_find_pci_capability(struct osl_info *osh, u8 req_cap_id,
 			bufsize = SZPCR - cap_data;
 		*buflen = bufsize;
 		while (bufsize--) {
-			pci_read_config_byte(osh->pdev, cap_data, buf);
+			pci_read_config_byte(dev, cap_data, buf);
 			cap_data++;
 			buf++;
 		}
@@ -183,7 +182,7 @@ pcicore_find_pci_capability(struct osl_info *osh, u8 req_cap_id,
 
 /* ***** Register Access API */
 uint
-pcie_readreg(struct osl_info *osh, sbpcieregs_t *pcieregs, uint addrtype,
+pcie_readreg(sbpcieregs_t *pcieregs, uint addrtype,
 	     uint offset)
 {
 	uint retval = 0xFFFFFFFF;
@@ -192,14 +191,14 @@ pcie_readreg(struct osl_info *osh, sbpcieregs_t *pcieregs, uint addrtype,
 
 	switch (addrtype) {
 	case PCIE_CONFIGREGS:
-		W_REG(osh, (&pcieregs->configaddr), offset);
-		(void)R_REG(osh, (&pcieregs->configaddr));
-		retval = R_REG(osh, &(pcieregs->configdata));
+		W_REG((&pcieregs->configaddr), offset);
+		(void)R_REG((&pcieregs->configaddr));
+		retval = R_REG(&(pcieregs->configdata));
 		break;
 	case PCIE_PCIEREGS:
-		W_REG(osh, &(pcieregs->pcieindaddr), offset);
-		(void)R_REG(osh, (&pcieregs->pcieindaddr));
-		retval = R_REG(osh, &(pcieregs->pcieinddata));
+		W_REG(&(pcieregs->pcieindaddr), offset);
+		(void)R_REG((&pcieregs->pcieindaddr));
+		retval = R_REG(&(pcieregs->pcieinddata));
 		break;
 	default:
 		ASSERT(0);
@@ -210,19 +209,19 @@ pcie_readreg(struct osl_info *osh, sbpcieregs_t *pcieregs, uint addrtype,
 }
 
 uint
-pcie_writereg(struct osl_info *osh, sbpcieregs_t *pcieregs, uint addrtype,
+pcie_writereg(sbpcieregs_t *pcieregs, uint addrtype,
 	      uint offset, uint val)
 {
 	ASSERT(pcieregs != NULL);
 
 	switch (addrtype) {
 	case PCIE_CONFIGREGS:
-		W_REG(osh, (&pcieregs->configaddr), offset);
-		W_REG(osh, (&pcieregs->configdata), val);
+		W_REG((&pcieregs->configaddr), offset);
+		W_REG((&pcieregs->configdata), val);
 		break;
 	case PCIE_PCIEREGS:
-		W_REG(osh, (&pcieregs->pcieindaddr), offset);
-		W_REG(osh, (&pcieregs->pcieinddata), val);
+		W_REG((&pcieregs->pcieindaddr), offset);
+		W_REG((&pcieregs->pcieinddata), val);
 		break;
 	default:
 		ASSERT(0);
@@ -242,12 +241,12 @@ static bool pcie_mdiosetblock(pcicore_info_t *pi, uint blk)
 					       MDIODATA_DEVADDR_SHF) |
 	    (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | MDIODATA_TA | (blk <<
 									 4);
-	W_REG(pi->osh, &pcieregs->mdiodata, mdiodata);
+	W_REG(&pcieregs->mdiodata, mdiodata);
 
 	PR28829_DELAY();
 	/* retry till the transaction is complete */
 	while (i < pcie_serdes_spinwait) {
-		if (R_REG(pi->osh, &(pcieregs->mdiocontrol)) &
+		if (R_REG(&(pcieregs->mdiocontrol)) &
 		    MDIOCTL_ACCESS_DONE) {
 			break;
 		}
@@ -273,7 +272,7 @@ pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
 	uint pcie_serdes_spinwait = 10;
 
 	/* enable mdio access to SERDES */
-	W_REG(pi->osh, (&pcieregs->mdiocontrol),
+	W_REG((&pcieregs->mdiocontrol),
 	      MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL);
 
 	if (pi->sih->buscorerev >= 10) {
@@ -294,22 +293,22 @@ pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
 		mdiodata |=
 		    (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | *val);
 
-	W_REG(pi->osh, &pcieregs->mdiodata, mdiodata);
+	W_REG(&pcieregs->mdiodata, mdiodata);
 
 	PR28829_DELAY();
 
 	/* retry till the transaction is complete */
 	while (i < pcie_serdes_spinwait) {
-		if (R_REG(pi->osh, &(pcieregs->mdiocontrol)) &
+		if (R_REG(&(pcieregs->mdiocontrol)) &
 		    MDIOCTL_ACCESS_DONE) {
 			if (!write) {
 				PR28829_DELAY();
 				*val =
-				    (R_REG(pi->osh, &(pcieregs->mdiodata)) &
+				    (R_REG(&(pcieregs->mdiodata)) &
 				     MDIODATA_MASK);
 			}
 			/* Disable mdio access to SERDES */
-			W_REG(pi->osh, (&pcieregs->mdiocontrol), 0);
+			W_REG((&pcieregs->mdiocontrol), 0);
 			return 0;
 		}
 		udelay(1000);
@@ -318,7 +317,7 @@ pcie_mdioop(pcicore_info_t *pi, uint physmedia, uint regaddr, bool write,
 
 	PCI_ERROR(("pcie_mdioop: timed out op: %d\n", write));
 	/* Disable mdio access to SERDES */
-	W_REG(pi->osh, (&pcieregs->mdiocontrol), 0);
+	W_REG((&pcieregs->mdiocontrol), 0);
 	return 1;
 }
 
@@ -347,15 +346,15 @@ u8 pcie_clkreq(void *pch, u32 mask, u32 val)
 	if (!offset)
 		return 0;
 
-	pci_read_config_dword(pi->osh->pdev, offset, &reg_val);
+	pci_read_config_dword(pi->dev, offset, &reg_val);
 	/* set operation */
 	if (mask) {
 		if (val)
 			reg_val |= PCIE_CLKREQ_ENAB;
 		else
 			reg_val &= ~PCIE_CLKREQ_ENAB;
-		pci_write_config_dword(pi->osh->pdev, offset, reg_val);
-		pci_read_config_dword(pi->osh->pdev, offset, &reg_val);
+		pci_write_config_dword(pi->dev, offset, reg_val);
+		pci_read_config_dword(pi->dev, offset, &reg_val);
 	}
 	if (reg_val & PCIE_CLKREQ_ENAB)
 		return 1;
@@ -367,19 +366,18 @@ static void pcie_extendL1timer(pcicore_info_t *pi, bool extend)
 {
 	u32 w;
 	si_t *sih = pi->sih;
-	struct osl_info *osh = pi->osh;
 	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
 
 	if (!PCIE_PUB(sih) || sih->buscorerev < 7)
 		return;
 
-	w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
+	w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
 	if (extend)
 		w |= PCIE_ASPMTIMER_EXTEND;
 	else
 		w &= ~PCIE_ASPMTIMER_EXTEND;
-	pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
-	w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
+	pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w);
+	w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG);
 }
 
 /* centralized clkreq control policy */
@@ -432,7 +430,7 @@ static void pcie_war_polarity(pcicore_info_t *pi)
 	if (pi->pcie_polarity != 0)
 		return;
 
-	w = pcie_readreg(pi->osh, pi->regs.pcieregs, PCIE_PCIEREGS,
+	w = pcie_readreg(pi->regs.pcieregs, PCIE_PCIEREGS,
 			 PCIE_PLP_STATUSREG);
 
 	/* Detect the current polarity at attach and force that polarity and
@@ -464,7 +462,7 @@ static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
 	if (!ISSIM_ENAB(sih)) {
 
 		reg16 = &pcieregs->sprom[SRSH_ASPM_OFFSET];
-		val16 = R_REG(pi->osh, reg16);
+		val16 = R_REG(reg16);
 
 		val16 &= ~SRSH_ASPM_ENB;
 		if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB)
@@ -474,18 +472,18 @@ static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
 		else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB)
 			val16 |= SRSH_ASPM_L0s_ENB;
 
-		W_REG(pi->osh, reg16, val16);
+		W_REG(reg16, val16);
 
-		pci_read_config_dword(pi->osh->pdev, pi->pciecap_lcreg_offset,
+		pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset,
 					&w);
 		w &= ~PCIE_ASPM_ENAB;
 		w |= pi->pcie_war_aspm_ovr;
-		pci_write_config_dword(pi->osh->pdev,
+		pci_write_config_dword(pi->dev,
 					pi->pciecap_lcreg_offset, w);
 	}
 
 	reg16 = &pcieregs->sprom[SRSH_CLKREQ_OFFSET_REV5];
-	val16 = R_REG(pi->osh, reg16);
+	val16 = R_REG(reg16);
 
 	if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) {
 		val16 |= SRSH_CLKREQ_ENB;
@@ -493,7 +491,7 @@ static void pcie_war_aspm_clkreq(pcicore_info_t *pi)
 	} else
 		val16 &= ~SRSH_CLKREQ_ENB;
 
-	W_REG(pi->osh, reg16, val16);
+	W_REG(reg16, val16);
 }
 
 /* Apply the polarity determined at the start */
@@ -521,11 +519,11 @@ static void pcie_misc_config_fixup(pcicore_info_t *pi)
 	u16 val16, *reg16;
 
 	reg16 = &pcieregs->sprom[SRSH_PCIE_MISC_CONFIG];
-	val16 = R_REG(pi->osh, reg16);
+	val16 = R_REG(reg16);
 
 	if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) {
 		val16 |= SRSH_L23READY_EXIT_NOPERST;
-		W_REG(pi->osh, reg16, val16);
+		W_REG(reg16, val16);
 	}
 }
 
@@ -544,29 +542,28 @@ static void pcie_war_noplldown(pcicore_info_t *pi)
 
 	/*  clear srom shadow backdoor */
 	reg16 = &pcieregs->sprom[SRSH_BD_OFFSET];
-	W_REG(pi->osh, reg16, 0);
+	W_REG(reg16, 0);
 }
 
 /* Needs to happen when coming out of 'standby'/'hibernate' */
 static void pcie_war_pci_setup(pcicore_info_t *pi)
 {
 	si_t *sih = pi->sih;
-	struct osl_info *osh = pi->osh;
 	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
 	u32 w;
 
 	if ((sih->buscorerev == 0) || (sih->buscorerev == 1)) {
-		w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS,
+		w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
 				 PCIE_TLP_WORKAROUNDSREG);
 		w |= 0x8;
-		pcie_writereg(osh, pcieregs, PCIE_PCIEREGS,
+		pcie_writereg(pcieregs, PCIE_PCIEREGS,
 			      PCIE_TLP_WORKAROUNDSREG, w);
 	}
 
 	if (sih->buscorerev == 1) {
-		w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
+		w = pcie_readreg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG);
 		w |= (0x40);
-		pcie_writereg(osh, pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
+		pcie_writereg(pcieregs, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w);
 	}
 
 	if (sih->buscorerev == 0) {
@@ -575,11 +572,11 @@ static void pcie_war_pci_setup(pcicore_info_t *pi)
 		pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466);
 	} else if (PCIE_ASPM(sih)) {
 		/* Change the L1 threshold for better performance */
-		w = pcie_readreg(osh, pcieregs, PCIE_PCIEREGS,
+		w = pcie_readreg(pcieregs, PCIE_PCIEREGS,
 				 PCIE_DLLP_PMTHRESHREG);
 		w &= ~(PCIE_L1THRESHOLDTIME_MASK);
 		w |= (PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT);
-		pcie_writereg(osh, pcieregs, PCIE_PCIEREGS,
+		pcie_writereg(pcieregs, PCIE_PCIEREGS,
 			      PCIE_DLLP_PMTHRESHREG, w);
 
 		pcie_war_serdes(pi);
@@ -668,9 +665,9 @@ void pcicore_sleep(void *pch)
 	if (!pi || !PCIE_ASPM(pi->sih))
 		return;
 
-	pci_read_config_dword(pi->osh->pdev, pi->pciecap_lcreg_offset, &w);
+	pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w);
 	w &= ~PCIE_CAP_LCREG_ASPML1;
-	pci_write_config_dword(pi->osh->pdev, pi->pciecap_lcreg_offset, w);
+	pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w);
 
 	pi->pcie_pr42767 = false;
 }
@@ -690,19 +687,20 @@ void pcicore_down(void *pch, int state)
 
 /* ***** Wake-on-wireless-LAN (WOWL) support functions ***** */
 /* Just uses PCI config accesses to find out, when needed before sb_attach is done */
-bool pcicore_pmecap_fast(struct osl_info *osh)
+bool pcicore_pmecap_fast(void *pch)
 {
+	pcicore_info_t *pi = (pcicore_info_t *) pch;
 	u8 cap_ptr;
 	u32 pmecap;
 
 	cap_ptr =
-	    pcicore_find_pci_capability(osh, PCI_CAP_POWERMGMTCAP_ID, NULL,
+	    pcicore_find_pci_capability(pi->dev, PCI_CAP_POWERMGMTCAP_ID, NULL,
 					NULL);
 
 	if (!cap_ptr)
 		return false;
 
-	pci_read_config_dword(osh->pdev, cap_ptr, &pmecap);
+	pci_read_config_dword(pi->dev, cap_ptr, &pmecap);
 
 	return (pmecap & PME_CAP_PM_STATES) != 0;
 }
@@ -717,7 +715,7 @@ static bool pcicore_pmecap(pcicore_info_t *pi)
 
 	if (!pi->pmecap_offset) {
 		cap_ptr =
-		    pcicore_find_pci_capability(pi->osh,
+		    pcicore_find_pci_capability(pi->dev,
 						PCI_CAP_POWERMGMTCAP_ID, NULL,
 						NULL);
 		if (!cap_ptr)
@@ -725,7 +723,7 @@ static bool pcicore_pmecap(pcicore_info_t *pi)
 
 		pi->pmecap_offset = cap_ptr;
 
-		pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset,
+		pci_read_config_dword(pi->dev, pi->pmecap_offset,
 					&pmecap);
 
 		/* At least one state can generate PME */
@@ -745,10 +743,10 @@ void pcicore_pmeen(void *pch)
 	if (!pcicore_pmecap(pi))
 		return;
 
-	pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset + PME_CSR_OFFSET,
+	pci_read_config_dword(pi->dev, pi->pmecap_offset + PME_CSR_OFFSET,
 				&w);
 	w |= (PME_CSR_PME_EN);
-	pci_write_config_dword(pi->osh->pdev,
+	pci_write_config_dword(pi->dev,
 				pi->pmecap_offset + PME_CSR_OFFSET, w);
 }
 
@@ -763,7 +761,7 @@ bool pcicore_pmestat(void *pch)
 	if (!pcicore_pmecap(pi))
 		return false;
 
-	pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset + PME_CSR_OFFSET,
+	pci_read_config_dword(pi->dev, pi->pmecap_offset + PME_CSR_OFFSET,
 				&w);
 
 	return (w & PME_CSR_PME_STAT) == PME_CSR_PME_STAT;
@@ -779,7 +777,7 @@ void pcicore_pmeclr(void *pch)
 	if (!pcicore_pmecap(pi))
 		return;
 
-	pci_read_config_dword(pi->osh->pdev, pi->pmecap_offset + PME_CSR_OFFSET,
+	pci_read_config_dword(pi->dev, pi->pmecap_offset + PME_CSR_OFFSET,
 				&w);
 
 	PCI_ERROR(("pcicore_pci_pmeclr PMECSR : 0x%x\n", w));
@@ -787,7 +785,7 @@ void pcicore_pmeclr(void *pch)
 	/* PMESTAT is cleared by writing 1 to it */
 	w &= ~(PME_CSR_PME_EN);
 
-	pci_write_config_dword(pi->osh->pdev,
+	pci_write_config_dword(pi->dev,
 				pi->pmecap_offset + PME_CSR_OFFSET, w);
 }
 
@@ -803,9 +801,9 @@ u32 pcie_lcreg(void *pch, u32 mask, u32 val)
 
 	/* set operation */
 	if (mask)
-		pci_write_config_dword(pi->osh->pdev, offset, val);
+		pci_write_config_dword(pi->dev, offset, val);
 
-	pci_read_config_dword(pi->osh->pdev, offset, &tmpval);
+	pci_read_config_dword(pi->dev, offset, &tmpval);
 	return tmpval;
 }
 
@@ -815,11 +813,10 @@ pcicore_pciereg(void *pch, u32 offset, u32 mask, u32 val, uint type)
 	u32 reg_val = 0;
 	pcicore_info_t *pi = (pcicore_info_t *) pch;
 	sbpcieregs_t *pcieregs = pi->regs.pcieregs;
-	struct osl_info *osh = pi->osh;
 
 	if (mask) {
 		PCI_ERROR(("PCIEREG: 0x%x writeval  0x%x\n", offset, val));
-		pcie_writereg(osh, pcieregs, type, offset, val);
+		pcie_writereg(pcieregs, type, offset, val);
 	}
 
 	/* Should not read register 0x154 */
@@ -827,7 +824,7 @@ pcicore_pciereg(void *pch, u32 offset, u32 mask, u32 val, uint type)
 	    && type == PCIE_PCIEREGS)
 		return reg_val;
 
-	reg_val = pcie_readreg(osh, pcieregs, type, offset);
+	reg_val = pcie_readreg(pcieregs, type, offset);
 	PCI_ERROR(("PCIEREG: 0x%x readval is 0x%x\n", offset, reg_val));
 
 	return reg_val;
diff --git a/drivers/staging/brcm80211/util/nvram/nvram_ro.c b/drivers/staging/brcm80211/util/nvram/nvram_ro.c
index e4d41ee..a697ff1 100644
--- a/drivers/staging/brcm80211/util/nvram/nvram_ro.c
+++ b/drivers/staging/brcm80211/util/nvram/nvram_ro.c
@@ -17,10 +17,8 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <siutils.h>
-#include <bcmendian.h>
 #include <bcmnvram.h>
 #include <sbchipc.h>
 #include <bcmsrom.h>
@@ -49,13 +47,10 @@ static char *findvar(char *vars, char *lim, const char *name);
 /* copy flash to ram */
 static void get_flash_nvram(si_t *sih, struct nvram_header *nvh)
 {
-	struct osl_info *osh;
 	uint nvs, bufsz;
 	vars_t *new;
 
-	osh = si_osh(sih);
-
-	nvs = R_REG(osh, &nvh->len) - sizeof(struct nvram_header);
+	nvs = R_REG(&nvh->len) - sizeof(struct nvram_header);
 	bufsz = nvs + VARS_T_OH;
 
 	new = kmalloc(bufsz, GFP_ATOMIC);
@@ -70,7 +65,7 @@ static void get_flash_nvram(si_t *sih, struct nvram_header *nvh)
 	new->next = vars;
 	vars = new;
 
-	bcopy((char *)(&nvh[1]), new->vars, nvs);
+	memcpy(new->vars, &nvh[1], nvs);
 
 	NVR_MSG(("%s: flash nvram @ %p, copied %d bytes to %p\n", __func__,
 		 nvh, nvs, new->vars));
@@ -195,7 +190,7 @@ int nvram_getall(char *buf, int count)
 			len = strlen(from) + 1;
 			if (resid < (acc + len))
 				return BCME_BUFTOOSHORT;
-			bcopy(from, to, len);
+			memcpy(to, from, len);
 			acc += len;
 			from += len;
 			to += len;
diff --git a/drivers/staging/brcm80211/util/pci_core.h b/drivers/staging/brcm80211/util/pci_core.h
new file mode 100644
index 0000000..9153dcb
--- /dev/null
+++ b/drivers/staging/brcm80211/util/pci_core.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_PCI_CORE_H_
+#define	_PCI_CORE_H_
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif
+
+/* Sonics side: PCI core and host control registers */
+struct sbpciregs {
+	u32 control;		/* PCI control */
+	u32 PAD[3];
+	u32 arbcontrol;	/* PCI arbiter control */
+	u32 clkrun;		/* Clkrun Control (>=rev11) */
+	u32 PAD[2];
+	u32 intstatus;	/* Interrupt status */
+	u32 intmask;		/* Interrupt mask */
+	u32 sbtopcimailbox;	/* Sonics to PCI mailbox */
+	u32 PAD[9];
+	u32 bcastaddr;	/* Sonics broadcast address */
+	u32 bcastdata;	/* Sonics broadcast data */
+	u32 PAD[2];
+	u32 gpioin;		/* ro: gpio input (>=rev2) */
+	u32 gpioout;		/* rw: gpio output (>=rev2) */
+	u32 gpioouten;	/* rw: gpio output enable (>= rev2) */
+	u32 gpiocontrol;	/* rw: gpio control (>= rev2) */
+	u32 PAD[36];
+	u32 sbtopci0;	/* Sonics to PCI translation 0 */
+	u32 sbtopci1;	/* Sonics to PCI translation 1 */
+	u32 sbtopci2;	/* Sonics to PCI translation 2 */
+	u32 PAD[189];
+	u32 pcicfg[4][64];	/* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */
+	u16 sprom[36];	/* SPROM shadow Area */
+	u32 PAD[46];
+};
+
+#endif				/* _LANGUAGE_ASSEMBLY */
+
+/* PCI control */
+#define PCI_RST_OE	0x01	/* When set, drives PCI_RESET out to pin */
+#define PCI_RST		0x02	/* Value driven out to pin */
+#define PCI_CLK_OE	0x04	/* When set, drives clock as gated by PCI_CLK out to pin */
+#define PCI_CLK		0x08	/* Gate for clock driven out to pin */
+
+/* PCI arbiter control */
+#define PCI_INT_ARB	0x01	/* When set, use an internal arbiter */
+#define PCI_EXT_ARB	0x02	/* When set, use an external arbiter */
+/* ParkID - for PCI corerev >= 8 */
+#define PCI_PARKID_MASK		0x1c	/* Selects which agent is parked on an idle bus */
+#define PCI_PARKID_SHIFT	2
+#define PCI_PARKID_EXT0		0	/* External master 0 */
+#define PCI_PARKID_EXT1		1	/* External master 1 */
+#define PCI_PARKID_EXT2		2	/* External master 2 */
+#define PCI_PARKID_EXT3		3	/* External master 3 (rev >= 11) */
+#define PCI_PARKID_INT		3	/* Internal master (rev < 11) */
+#define PCI11_PARKID_INT	4	/* Internal master (rev >= 11) */
+#define PCI_PARKID_LAST		4	/* Last active master (rev < 11) */
+#define PCI11_PARKID_LAST	5	/* Last active master (rev >= 11) */
+
+#define PCI_CLKRUN_DSBL	0x8000	/* Bit 15 forceClkrun */
+
+/* Interrupt status/mask */
+#define PCI_INTA	0x01	/* PCI INTA# is asserted */
+#define PCI_INTB	0x02	/* PCI INTB# is asserted */
+#define PCI_SERR	0x04	/* PCI SERR# has been asserted (write one to clear) */
+#define PCI_PERR	0x08	/* PCI PERR# has been asserted (write one to clear) */
+#define PCI_PME		0x10	/* PCI PME# is asserted */
+
+/* (General) PCI/SB mailbox interrupts, two bits per pci function */
+#define	MAILBOX_F0_0	0x100	/* function 0, int 0 */
+#define	MAILBOX_F0_1	0x200	/* function 0, int 1 */
+#define	MAILBOX_F1_0	0x400	/* function 1, int 0 */
+#define	MAILBOX_F1_1	0x800	/* function 1, int 1 */
+#define	MAILBOX_F2_0	0x1000	/* function 2, int 0 */
+#define	MAILBOX_F2_1	0x2000	/* function 2, int 1 */
+#define	MAILBOX_F3_0	0x4000	/* function 3, int 0 */
+#define	MAILBOX_F3_1	0x8000	/* function 3, int 1 */
+
+/* Sonics broadcast address */
+#define BCAST_ADDR_MASK	0xff	/* Broadcast register address */
+
+/* Sonics to PCI translation types */
+#define SBTOPCI0_MASK	0xfc000000
+#define SBTOPCI1_MASK	0xfc000000
+#define SBTOPCI2_MASK	0xc0000000
+#define SBTOPCI_MEM	0
+#define SBTOPCI_IO	1
+#define SBTOPCI_CFG0	2
+#define SBTOPCI_CFG1	3
+#define	SBTOPCI_PREF	0x4	/* prefetch enable */
+#define	SBTOPCI_BURST	0x8	/* burst enable */
+#define	SBTOPCI_RC_MASK		0x30	/* read command (>= rev11) */
+#define	SBTOPCI_RC_READ		0x00	/* memory read */
+#define	SBTOPCI_RC_READLINE	0x10	/* memory read line */
+#define	SBTOPCI_RC_READMULTI	0x20	/* memory read multiple */
+
+/* PCI core index in SROM shadow area */
+#define SRSH_PI_OFFSET	0	/* first word */
+#define SRSH_PI_MASK	0xf000	/* bit 15:12 */
+#define SRSH_PI_SHIFT	12	/* bit 15:12 */
+
+#endif				/* _PCI_CORE_H_ */
diff --git a/drivers/staging/brcm80211/util/sbpcmcia.h b/drivers/staging/brcm80211/util/sbpcmcia.h
new file mode 100644
index 0000000..6b9923f5
--- /dev/null
+++ b/drivers/staging/brcm80211/util/sbpcmcia.h
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_SBPCMCIA_H
+#define	_SBPCMCIA_H
+
+/* All the addresses that are offsets in attribute space are divided
+ * by two to account for the fact that odd bytes are invalid in
+ * attribute space and our read/write routines make the space appear
+ * as if they didn't exist. Still we want to show the original numbers
+ * as documented in the hnd_pcmcia core manual.
+ */
+
+/* PCMCIA Function Configuration Registers */
+#define	PCMCIA_FCR		(0x700 / 2)
+
+#define	FCR0_OFF		0
+#define	FCR1_OFF		(0x40 / 2)
+#define	FCR2_OFF		(0x80 / 2)
+#define	FCR3_OFF		(0xc0 / 2)
+
+#define	PCMCIA_FCR0		(0x700 / 2)
+#define	PCMCIA_FCR1		(0x740 / 2)
+#define	PCMCIA_FCR2		(0x780 / 2)
+#define	PCMCIA_FCR3		(0x7c0 / 2)
+
+/* Standard PCMCIA FCR registers */
+
+#define	PCMCIA_COR		0
+
+#define	COR_RST			0x80
+#define	COR_LEV			0x40
+#define	COR_IRQEN		0x04
+#define	COR_BLREN		0x01
+#define	COR_FUNEN		0x01
+
+#define	PCICIA_FCSR		(2 / 2)
+#define	PCICIA_PRR		(4 / 2)
+#define	PCICIA_SCR		(6 / 2)
+#define	PCICIA_ESR		(8 / 2)
+
+#define PCM_MEMOFF		0x0000
+#define F0_MEMOFF		0x1000
+#define F1_MEMOFF		0x2000
+#define F2_MEMOFF		0x3000
+#define F3_MEMOFF		0x4000
+
+/* Memory base in the function fcr's */
+#define MEM_ADDR0		(0x728 / 2)
+#define MEM_ADDR1		(0x72a / 2)
+#define MEM_ADDR2		(0x72c / 2)
+
+/* PCMCIA base plus Srom access in fcr0: */
+#define PCMCIA_ADDR0		(0x072e / 2)
+#define PCMCIA_ADDR1		(0x0730 / 2)
+#define PCMCIA_ADDR2		(0x0732 / 2)
+
+#define MEM_SEG			(0x0734 / 2)
+#define SROM_CS			(0x0736 / 2)
+#define SROM_DATAL		(0x0738 / 2)
+#define SROM_DATAH		(0x073a / 2)
+#define SROM_ADDRL		(0x073c / 2)
+#define SROM_ADDRH		(0x073e / 2)
+#define	SROM_INFO2		(0x0772 / 2)	/* Corerev >= 2 && <= 5 */
+#define	SROM_INFO		(0x07be / 2)	/* Corerev >= 6 */
+
+/*  Values for srom_cs: */
+#define SROM_IDLE		0
+#define SROM_WRITE		1
+#define SROM_READ		2
+#define SROM_WEN		4
+#define SROM_WDS		7
+#define SROM_DONE		8
+
+/* Fields in srom_info: */
+#define	SRI_SZ_MASK		0x03
+#define	SRI_BLANK		0x04
+#define	SRI_OTP			0x80
+
+#if !defined(ESTA_POSTMOGRIFY_REMOVAL)
+/* CIS stuff */
+
+/* The CIS stops where the FCRs start */
+#define	CIS_SIZE		PCMCIA_FCR
+
+/* CIS tuple length field max */
+#define CIS_TUPLE_LEN_MAX	0xff
+
+/* Standard tuples we know about */
+
+#define CISTPL_NULL			0x00
+#define	CISTPL_VERS_1		0x15	/* CIS ver, manf, dev & ver strings */
+#define	CISTPL_MANFID		0x20	/* Manufacturer and device id */
+#define CISTPL_FUNCID		0x21	/* Function identification */
+#define	CISTPL_FUNCE		0x22	/* Function extensions */
+#define	CISTPL_CFTABLE		0x1b	/* Config table entry */
+#define	CISTPL_END		0xff	/* End of the CIS tuple chain */
+
+/* Function identifier provides context for the function extentions tuple */
+#define CISTPL_FID_SDIO		0x0c	/* Extensions defined by SDIO spec */
+
+/* Function extensions for LANs (assumed for extensions other than SDIO) */
+#define	LAN_TECH		1	/* Technology type */
+#define	LAN_SPEED		2	/* Raw bit rate */
+#define	LAN_MEDIA		3	/* Transmission media */
+#define	LAN_NID			4	/* Node identification (aka MAC addr) */
+#define	LAN_CONN		5	/* Connector standard */
+
+/* CFTable */
+#define CFTABLE_REGWIN_2K	0x08	/* 2k reg windows size */
+#define CFTABLE_REGWIN_4K	0x10	/* 4k reg windows size */
+#define CFTABLE_REGWIN_8K	0x20	/* 8k reg windows size */
+
+/* Vendor unique tuples are 0x80-0x8f. Within Broadcom we'll
+ * take one for HNBU, and use "extensions" (a la FUNCE) within it.
+ */
+
+#define	CISTPL_BRCM_HNBU	0x80
+
+/* Subtypes of BRCM_HNBU: */
+
+#define HNBU_SROMREV		0x00	/* A byte with sromrev, 1 if not present */
+#define HNBU_CHIPID		0x01	/* Two 16bit values: PCI vendor & device id */
+#define HNBU_BOARDREV		0x02	/* One byte board revision */
+#define HNBU_PAPARMS		0x03	/* PA parameters: 8 (sromrev == 1)
+					 * or 9 (sromrev > 1) bytes
+					 */
+#define HNBU_OEM		0x04	/* Eight bytes OEM data (sromrev == 1) */
+#define HNBU_CC			0x05	/* Default country code (sromrev == 1) */
+#define	HNBU_AA			0x06	/* Antennas available */
+#define	HNBU_AG			0x07	/* Antenna gain */
+#define HNBU_BOARDFLAGS		0x08	/* board flags (2 or 4 bytes) */
+#define HNBU_LEDS		0x09	/* LED set */
+#define HNBU_CCODE		0x0a	/* Country code (2 bytes ascii + 1 byte cctl)
+					 * in rev 2
+					 */
+#define HNBU_CCKPO		0x0b	/* 2 byte cck power offsets in rev 3 */
+#define HNBU_OFDMPO		0x0c	/* 4 byte 11g ofdm power offsets in rev 3 */
+#define HNBU_GPIOTIMER		0x0d	/* 2 bytes with on/off values in rev 3 */
+#define HNBU_PAPARMS5G		0x0e	/* 5G PA params */
+#define HNBU_ANT5G		0x0f	/* 4328 5G antennas available/gain */
+#define HNBU_RDLID		0x10	/* 2 byte USB remote downloader (RDL) product Id */
+#define HNBU_RSSISMBXA2G	0x11	/* 4328 2G RSSI mid pt sel & board switch arch,
+					 * 2 bytes, rev 3.
+					 */
+#define HNBU_RSSISMBXA5G	0x12	/* 4328 5G RSSI mid pt sel & board switch arch,
+					 * 2 bytes, rev 3.
+					 */
+#define HNBU_XTALFREQ		0x13	/* 4 byte Crystal frequency in kilohertz */
+#define HNBU_TRI2G		0x14	/* 4328 2G TR isolation, 1 byte */
+#define HNBU_TRI5G		0x15	/* 4328 5G TR isolation, 3 bytes */
+#define HNBU_RXPO2G		0x16	/* 4328 2G RX power offset, 1 byte */
+#define HNBU_RXPO5G		0x17	/* 4328 5G RX power offset, 1 byte */
+#define HNBU_BOARDNUM		0x18	/* board serial number, independent of mac addr */
+#define HNBU_MACADDR		0x19	/* mac addr override for the standard CIS LAN_NID */
+#define HNBU_RDLSN		0x1a	/* 2 bytes; serial # advertised in USB descriptor */
+#define HNBU_BOARDTYPE		0x1b	/* 2 bytes; boardtype */
+#define HNBU_LEDDC		0x1c	/* 2 bytes; LED duty cycle */
+#define HNBU_HNBUCIS		0x1d	/* what follows is proprietary HNBU CIS format */
+#define HNBU_PAPARMS_SSLPNPHY	0x1e	/* SSLPNPHY PA params */
+#define HNBU_RSSISMBXA2G_SSLPNPHY 0x1f	/* SSLPNPHY RSSI mid pt sel & board switch arch */
+#define HNBU_RDLRNDIS		0x20	/* 1 byte; 1 = RDL advertises RNDIS config */
+#define HNBU_CHAINSWITCH	0x21	/* 2 byte; txchain, rxchain */
+#define HNBU_REGREV		0x22	/* 1 byte; */
+#define HNBU_FEM		0x23	/* 2 or 4 byte: 11n frontend specification */
+#define HNBU_PAPARMS_C0		0x24	/* 8 or 30 bytes: 11n pa paramater for chain 0 */
+#define HNBU_PAPARMS_C1		0x25	/* 8 or 30 bytes: 11n pa paramater for chain 1 */
+#define HNBU_PAPARMS_C2		0x26	/* 8 or 30 bytes: 11n pa paramater for chain 2 */
+#define HNBU_PAPARMS_C3		0x27	/* 8 or 30 bytes: 11n pa paramater for chain 3 */
+#define HNBU_PO_CCKOFDM		0x28	/* 6 or 18 bytes: cck2g/ofdm2g/ofdm5g power offset */
+#define HNBU_PO_MCS2G		0x29	/* 8 bytes: mcs2g power offset */
+#define HNBU_PO_MCS5GM		0x2a	/* 8 bytes: mcs5g mid band power offset */
+#define HNBU_PO_MCS5GLH		0x2b	/* 16 bytes: mcs5g low-high band power offset */
+#define HNBU_PO_CDD		0x2c	/* 2 bytes: cdd2g/5g power offset */
+#define HNBU_PO_STBC		0x2d	/* 2 bytes: stbc2g/5g power offset */
+#define HNBU_PO_40M		0x2e	/* 2 bytes: 40Mhz channel 2g/5g power offset */
+#define HNBU_PO_40MDUP		0x2f	/* 2 bytes: 40Mhz channel dup 2g/5g power offset */
+
+#define HNBU_RDLRWU		0x30	/* 1 byte; 1 = RDL advertises Remote Wake-up */
+#define HNBU_WPS		0x31	/* 1 byte; GPIO pin for WPS button */
+#define HNBU_USBFS		0x32	/* 1 byte; 1 = USB advertises FS mode only */
+#define HNBU_BRMIN		0x33	/* 4 byte bootloader min resource mask */
+#define HNBU_BRMAX		0x34	/* 4 byte bootloader max resource mask */
+#define HNBU_PATCH		0x35	/* bootloader patch addr(2b) & data(4b) pair */
+#define HNBU_CCKFILTTYPE	0x36	/* CCK digital filter selection options */
+#define HNBU_OFDMPO5G		0x37	/* 4 * 3 = 12 byte 11a ofdm power offsets in rev 3 */
+
+#define HNBU_USBEPNUM		0x40	/* USB endpoint numbers */
+#define HNBU_SROM3SWRGN		0x80	/* 78 bytes; srom rev 3 s/w region without crc8
+					 * plus extra info appended.
+					 */
+#define HNBU_RESERVED		0x81	/* Reserved for non-BRCM post-mfg additions */
+#define HNBU_CUSTOM1		0x82	/* 4 byte; For non-BRCM post-mfg additions */
+#define HNBU_CUSTOM2		0x83	/* Reserved; For non-BRCM post-mfg additions */
+#endif				/* !defined(ESTA_POSTMOGRIFY_REMOVAL) */
+
+/* sbtmstatelow */
+#define SBTML_INT_ACK		0x40000	/* ack the sb interrupt */
+#define SBTML_INT_EN		0x20000	/* enable sb interrupt */
+
+/* sbtmstatehigh */
+#define SBTMH_INT_STATUS	0x40000	/* sb interrupt status */
+
+#endif				/* _SBPCMCIA_H */
diff --git a/drivers/staging/brcm80211/util/sbsocram.h b/drivers/staging/brcm80211/util/sbsocram.h
new file mode 100644
index 0000000..0cfe985
--- /dev/null
+++ b/drivers/staging/brcm80211/util/sbsocram.h
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef	_SBSOCRAM_H
+#define	_SBSOCRAM_H
+
+#ifndef _LANGUAGE_ASSEMBLY
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif				/* PAD */
+
+/* Memcsocram core registers */
+typedef volatile struct sbsocramregs {
+	u32 coreinfo;
+	u32 bwalloc;
+	u32 extracoreinfo;
+	u32 biststat;
+	u32 bankidx;
+	u32 standbyctrl;
+
+	u32 errlogstatus;	/* rev 6 */
+	u32 errlogaddr;	/* rev 6 */
+	/* used for patching rev 3 & 5 */
+	u32 cambankidx;
+	u32 cambankstandbyctrl;
+	u32 cambankpatchctrl;
+	u32 cambankpatchtblbaseaddr;
+	u32 cambankcmdreg;
+	u32 cambankdatareg;
+	u32 cambankmaskreg;
+	u32 PAD[1];
+	u32 bankinfo;	/* corev 8 */
+	u32 PAD[15];
+	u32 extmemconfig;
+	u32 extmemparitycsr;
+	u32 extmemparityerrdata;
+	u32 extmemparityerrcnt;
+	u32 extmemwrctrlandsize;
+	u32 PAD[84];
+	u32 workaround;
+	u32 pwrctl;		/* corerev >= 2 */
+} sbsocramregs_t;
+
+#endif				/* _LANGUAGE_ASSEMBLY */
+
+/* Register offsets */
+#define	SR_COREINFO		0x00
+#define	SR_BWALLOC		0x04
+#define	SR_BISTSTAT		0x0c
+#define	SR_BANKINDEX		0x10
+#define	SR_BANKSTBYCTL		0x14
+#define SR_PWRCTL		0x1e8
+
+/* Coreinfo register */
+#define	SRCI_PT_MASK		0x00070000	/* corerev >= 6; port type[18:16] */
+#define	SRCI_PT_SHIFT		16
+/* port types : SRCI_PT_<processorPT>_<backplanePT> */
+#define SRCI_PT_OCP_OCP		0
+#define SRCI_PT_AXI_OCP		1
+#define SRCI_PT_ARM7AHB_OCP	2
+#define SRCI_PT_CM3AHB_OCP	3
+#define SRCI_PT_AXI_AXI		4
+#define SRCI_PT_AHB_AXI		5
+/* corerev >= 3 */
+#define SRCI_LSS_MASK		0x00f00000
+#define SRCI_LSS_SHIFT		20
+#define SRCI_LRS_MASK		0x0f000000
+#define SRCI_LRS_SHIFT		24
+
+/* In corerev 0, the memory size is 2 to the power of the
+ * base plus 16 plus to the contents of the memsize field plus 1.
+ */
+#define	SRCI_MS0_MASK		0xf
+#define SR_MS0_BASE		16
+
+/*
+ * In corerev 1 the bank size is 2 ^ the bank size field plus 14,
+ * the memory size is number of banks times bank size.
+ * The same applies to rom size.
+ */
+#define	SRCI_ROMNB_MASK		0xf000
+#define	SRCI_ROMNB_SHIFT	12
+#define	SRCI_ROMBSZ_MASK	0xf00
+#define	SRCI_ROMBSZ_SHIFT	8
+#define	SRCI_SRNB_MASK		0xf0
+#define	SRCI_SRNB_SHIFT		4
+#define	SRCI_SRBSZ_MASK		0xf
+#define	SRCI_SRBSZ_SHIFT	0
+
+#define SR_BSZ_BASE		14
+
+/* Standby control register */
+#define	SRSC_SBYOVR_MASK	0x80000000
+#define	SRSC_SBYOVR_SHIFT	31
+#define	SRSC_SBYOVRVAL_MASK	0x60000000
+#define	SRSC_SBYOVRVAL_SHIFT	29
+#define	SRSC_SBYEN_MASK		0x01000000	/* rev >= 3 */
+#define	SRSC_SBYEN_SHIFT	24
+
+/* Power control register */
+#define SRPC_PMU_STBYDIS_MASK	0x00000010	/* rev >= 3 */
+#define SRPC_PMU_STBYDIS_SHIFT	4
+#define SRPC_STBYOVRVAL_MASK	0x00000008
+#define SRPC_STBYOVRVAL_SHIFT	3
+#define SRPC_STBYOVR_MASK	0x00000007
+#define SRPC_STBYOVR_SHIFT	0
+
+/* Extra core capability register */
+#define SRECC_NUM_BANKS_MASK   0x000000F0
+#define SRECC_NUM_BANKS_SHIFT  4
+#define SRECC_BANKSIZE_MASK    0x0000000F
+#define SRECC_BANKSIZE_SHIFT   0
+
+#define SRECC_BANKSIZE(value)	 (1 << (value))
+
+/* CAM bank patch control */
+#define SRCBPC_PATCHENABLE 0x80000000
+
+#define SRP_ADDRESS   0x0001FFFC
+#define SRP_VALID     0x8000
+
+/* CAM bank command reg */
+#define SRCMD_WRITE  0x00020000
+#define SRCMD_READ   0x00010000
+#define SRCMD_DONE   0x80000000
+
+#define SRCMD_DONE_DLY	1000
+
+/* bankidx and bankinfo reg defines corerev >= 8 */
+#define SOCRAM_BANKINFO_SZMASK		0x3f
+#define SOCRAM_BANKIDX_ROM_MASK		0x100
+
+#define SOCRAM_BANKIDX_MEMTYPE_SHIFT	8
+/* socram bankinfo memtype */
+#define SOCRAM_MEMTYPE_RAM		0
+#define SOCRAM_MEMTYPE_R0M		1
+#define SOCRAM_MEMTYPE_DEVRAM		2
+
+#define	SOCRAM_BANKINFO_REG		0x40
+#define	SOCRAM_BANKIDX_REG		0x10
+#define	SOCRAM_BANKINFO_STDBY_MASK	0x400
+#define	SOCRAM_BANKINFO_STDBY_TIMER	0x800
+
+/* bankinfo rev >= 10 */
+#define SOCRAM_BANKINFO_DEVRAMSEL_SHIFT	13
+#define SOCRAM_BANKINFO_DEVRAMSEL_MASK	0x2000
+#define SOCRAM_BANKINFO_DEVRAMPRO_SHIFT	14
+#define SOCRAM_BANKINFO_DEVRAMPRO_MASK	0x4000
+
+/* extracoreinfo register */
+#define SOCRAM_DEVRAMBANK_MASK		0xF000
+#define SOCRAM_DEVRAMBANK_SHIFT		12
+
+/* bank info to calculate bank size */
+#define	SOCRAM_BANKINFO_SZBASE		8192
+#define SOCRAM_BANKSIZE_SHIFT		13	/* SOCRAM_BANKINFO_SZBASE */
+
+#endif				/* _SBSOCRAM_H */
diff --git a/drivers/staging/brcm80211/util/sbutils.c b/drivers/staging/brcm80211/util/sbutils.c
index 63c3ab1..21dde8e 100644
--- a/drivers/staging/brcm80211/util/sbutils.c
+++ b/drivers/staging/brcm80211/util/sbutils.c
@@ -19,7 +19,6 @@
 #ifdef BRCM_FULLMAC
 #include <linux/netdevice.h>
 #endif
-#include <osl.h>
 #include <bcmutils.h>
 #include <siutils.h>
 #include <bcmdevs.h>
@@ -54,12 +53,12 @@ static void *_sb_setcoreidx(si_info_t *sii, uint coreidx);
 
 static u32 sb_read_sbreg(si_info_t *sii, volatile u32 *sbr)
 {
-	return R_REG(sii->osh, sbr);
+	return R_REG(sbr);
 }
 
 static void sb_write_sbreg(si_info_t *sii, volatile u32 *sbr, u32 v)
 {
-	W_REG(sii->osh, sbr, v);
+	W_REG(sbr, v);
 }
 
 uint sb_coreid(si_t *sih)
@@ -178,8 +177,8 @@ uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
 			w = (R_SBREG(sii, r) & ~mask) | val;
 			W_SBREG(sii, r, w);
 		} else {
-			w = (R_REG(sii->osh, r) & ~mask) | val;
-			W_REG(sii->osh, r, w);
+			w = (R_REG(r) & ~mask) | val;
+			W_REG(r, w);
 		}
 	}
 
@@ -187,7 +186,7 @@ uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val)
 	if (regoff >= SBCONFIGOFF)
 		w = R_SBREG(sii, r);
 	else
-		w = R_REG(sii->osh, r);
+		w = R_REG(r);
 
 	if (!fast) {
 		/* restore core index */
@@ -246,7 +245,7 @@ static uint _sb_scan(si_info_t *sii, u32 sba, void *regs, uint bus, u32 sbba,
 				 total # cores in the chip */
 			if (((ccrev == 4) || (ccrev >= 6)))
 				numcores =
-				    (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK)
+				    (R_REG(&cc->chipid) & CID_CC_MASK)
 				    >> CID_CC_SHIFT;
 			else {
 				/* Older chips */
@@ -368,94 +367,6 @@ static void *_sb_setcoreidx(si_info_t *sii, uint coreidx)
 	return regs;
 }
 
-/* traverse all cores to find and clear source of serror */
-static void sb_serr_clear(si_info_t *sii)
-{
-	sbconfig_t *sb;
-	uint origidx;
-	uint i, intr_val = 0;
-	void *corereg = NULL;
-
-	INTR_OFF(sii, intr_val);
-	origidx = si_coreidx(&sii->pub);
-
-	for (i = 0; i < sii->numcores; i++) {
-		corereg = sb_setcoreidx(&sii->pub, i);
-		if (NULL != corereg) {
-			sb = REGS2SB(corereg);
-			if ((R_SBREG(sii, &sb->sbtmstatehigh)) & SBTMH_SERR) {
-				AND_SBREG(sii, &sb->sbtmstatehigh, ~SBTMH_SERR);
-				SI_ERROR(("sb_serr_clear: SError core 0x%x\n",
-				sb_coreid(&sii->pub)));
-			}
-		}
-	}
-
-	sb_setcoreidx(&sii->pub, origidx);
-	INTR_RESTORE(sii, intr_val);
-}
-
-/*
- * Check if any inband, outband or timeout errors has happened and clear them.
- * Must be called with chip clk on !
- */
-bool sb_taclear(si_t *sih, bool details)
-{
-	si_info_t *sii;
-	sbconfig_t *sb;
-	uint origidx;
-	uint intr_val = 0;
-	bool rc = false;
-	u32 inband = 0, serror = 0, timeout = 0;
-	void *corereg = NULL;
-	volatile u32 imstate, tmstate;
-
-	sii = SI_INFO(sih);
-
-	if ((sii->pub.bustype == SDIO_BUS) ||
-	    (sii->pub.bustype == SPI_BUS)) {
-
-		INTR_OFF(sii, intr_val);
-		origidx = si_coreidx(sih);
-
-		corereg = si_setcore(sih, PCMCIA_CORE_ID, 0);
-		if (NULL == corereg)
-			corereg = si_setcore(sih, SDIOD_CORE_ID, 0);
-		if (NULL != corereg) {
-			sb = REGS2SB(corereg);
-
-			imstate = R_SBREG(sii, &sb->sbimstate);
-			if ((imstate != 0xffffffff)
-			    && (imstate & (SBIM_IBE | SBIM_TO))) {
-				AND_SBREG(sii, &sb->sbimstate,
-					  ~(SBIM_IBE | SBIM_TO));
-				/* inband = imstate & SBIM_IBE; cmd error */
-				timeout = imstate & SBIM_TO;
-			}
-			tmstate = R_SBREG(sii, &sb->sbtmstatehigh);
-			if ((tmstate != 0xffffffff)
-			    && (tmstate & SBTMH_INT_STATUS)) {
-				sb_serr_clear(sii);
-				serror = 1;
-				OR_SBREG(sii, &sb->sbtmstatelow, SBTML_INT_ACK);
-				AND_SBREG(sii, &sb->sbtmstatelow,
-					  ~SBTML_INT_ACK);
-			}
-		}
-
-		sb_setcoreidx(sih, origidx);
-		INTR_RESTORE(sii, intr_val);
-	}
-
-	if (inband | timeout | serror) {
-		rc = true;
-		SI_ERROR(("sb_taclear: inband 0x%x, serror 0x%x, timeout "
-			"0x%x!\n", inband, serror, timeout));
-	}
-
-	return rc;
-}
-
 void sb_core_disable(si_t *sih, u32 bits)
 {
 	si_info_t *sii;
@@ -563,26 +474,3 @@ void sb_core_reset(si_t *sih, u32 bits, u32 resetbits)
 	dummy = R_SBREG(sii, &sb->sbtmstatelow);
 	udelay(1);
 }
-
-u32 sb_base(u32 admatch)
-{
-	u32 base;
-	uint type;
-
-	type = admatch & SBAM_TYPE_MASK;
-	ASSERT(type < 3);
-
-	base = 0;
-
-	if (type == 0) {
-		base = admatch & SBAM_BASE0_MASK;
-	} else if (type == 1) {
-		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
-		base = admatch & SBAM_BASE1_MASK;
-	} else if (type == 2) {
-		ASSERT(!(admatch & SBAM_ADNEG));	/* neg not supported */
-		base = admatch & SBAM_BASE2_MASK;
-	}
-
-	return base;
-}
diff --git a/drivers/staging/brcm80211/util/siutils.c b/drivers/staging/brcm80211/util/siutils.c
index b66de9b..ed168ce 100644
--- a/drivers/staging/brcm80211/util/siutils.c
+++ b/drivers/staging/brcm80211/util/siutils.c
@@ -18,10 +18,6 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <bcmdefs.h>
-#ifdef BRCM_FULLMAC
-#include <linux/netdevice.h>
-#endif
-#include <osl.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <bcmutils.h>
@@ -58,8 +54,8 @@
 #endif
 
 /* local prototypes */
-static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
-			      void *regs, uint bustype, void *sdh, char **vars,
+static si_info_t *si_doattach(si_info_t *sii, uint devid, void *regs,
+			      uint bustype, void *sdh, char **vars,
 			      uint *varsz);
 static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid,
 			    void *sdh);
@@ -86,7 +82,7 @@ static u32 si_gpioreservation;
  * vars - pointer to a pointer area for "environment" variables
  * varsz - pointer to int to return the size of the vars
  */
-si_t *si_attach(uint devid, struct osl_info *osh, void *regs, uint bustype,
+si_t *si_attach(uint devid, void *regs, uint bustype,
 		void *sdh, char **vars, uint *varsz)
 {
 	si_info_t *sii;
@@ -98,7 +94,7 @@ si_t *si_attach(uint devid, struct osl_info *osh, void *regs, uint bustype,
 		return NULL;
 	}
 
-	if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) ==
+	if (si_doattach(sii, devid, regs, bustype, sdh, vars, varsz) ==
 	    NULL) {
 		kfree(sii);
 		return NULL;
@@ -183,19 +179,19 @@ static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
 
 	/* get chipcommon chipstatus */
 	if (sii->pub.ccrev >= 11)
-		sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus);
+		sii->pub.chipst = R_REG(&cc->chipstatus);
 
 	/* get chipcommon capabilites */
-	sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities);
+	sii->pub.cccaps = R_REG(&cc->capabilities);
 	/* get chipcommon extended capabilities */
 
 #ifndef BRCM_FULLMAC
 	if (sii->pub.ccrev >= 35)
-		sii->pub.cccaps_ext = R_REG(sii->osh, &cc->capabilities_ext);
+		sii->pub.cccaps_ext = R_REG(&cc->capabilities_ext);
 #endif
 	/* get pmu rev and caps */
 	if (sii->pub.cccaps & CC_CAP_PMU) {
-		sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities);
+		sii->pub.pmucaps = R_REG(&cc->pmucapabilities);
 		sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK;
 	}
 
@@ -290,7 +286,7 @@ static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype,
 		if (SI_FAST(sii)) {
 			if (!sii->pch) {
 				sii->pch = (void *)pcicore_init(
-					&sii->pub, sii->osh,
+					&sii->pub, sii->pbus,
 					(void *)PCIEREGS(sii));
 				if (sii->pch == NULL)
 					return false;
@@ -316,7 +312,7 @@ static __used void si_nvram_process(si_info_t *sii, char *pvars)
 	switch (sii->pub.bustype) {
 	case PCI_BUS:
 		/* do a pci config read to get subsystem id and subvendor id */
-		pci_read_config_dword(sii->osh->pdev, PCI_CFG_SVID, &w);
+		pci_read_config_dword(sii->pbus, PCI_CFG_SVID, &w);
 		/* Let nvram variables override subsystem Vend/ID */
 		sii->pub.boardvendor = (u16)si_getdevpathintvar(&sii->pub,
 			"boardvendor");
@@ -369,8 +365,8 @@ static __used void si_nvram_process(si_info_t *sii, char *pvars)
 /* this is will make Sonics calls directly, since Sonics is no longer supported in the Si abstraction */
 /* this has been customized for the bcm 4329 ONLY */
 #ifdef BCMSDIO
-static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
-			      void *regs, uint bustype, void *sdh,
+static si_info_t *si_doattach(si_info_t *sii, uint devid,
+			      void *regs, uint bustype, void *pbus,
 			      char **vars, uint *varsz)
 {
 	struct si_pub *sih = &sii->pub;
@@ -388,15 +384,14 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	sih->buscoreidx = BADIDX;
 
 	sii->curmap = regs;
-	sii->sdh = sdh;
-	sii->osh = osh;
+	sii->pbus = pbus;
 
 	/* find Chipcommon address */
 	cc = (chipcregs_t *) sii->curmap;
 	sih->bustype = bustype;
 
 	/* bus/core/clk setup for register access */
-	if (!si_buscore_prep(sii, bustype, devid, sdh)) {
+	if (!si_buscore_prep(sii, bustype, devid, pbus)) {
 		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
 			  bustype));
 		return NULL;
@@ -407,7 +402,7 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	 *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
 	 *   some way of recognizing them needs to be added here.
 	 */
-	w = R_REG(osh, &cc->chipid);
+	w = R_REG(&cc->chipid);
 	sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
 	/* Might as wll fill in chip id rev & pkg */
 	sih->chip = w & CID_ID_MASK;
@@ -458,8 +453,8 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	if (sii->pub.ccrev >= 20) {
 #endif
 	cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
-	W_REG(osh, &cc->gpiopullup, 0);
-	W_REG(osh, &cc->gpiopulldown, 0);
+	W_REG(&cc->gpiopullup, 0);
+	W_REG(&cc->gpiopulldown, 0);
 	sb_setcoreidx(sih, origidx);
 #ifdef BRCM_FULLMAC
 	}
@@ -469,15 +464,15 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	/* PMU specific initializations */
 	if (PMUCTL_ENAB(sih)) {
 		u32 xtalfreq;
-		si_pmu_init(sih, sii->osh);
-		si_pmu_chip_init(sih, sii->osh);
+		si_pmu_init(sih);
+		si_pmu_chip_init(sih);
 		xtalfreq = getintvar(pvars, "xtalfreq");
 		/* If xtalfreq var not available, try to measure it */
 		if (xtalfreq == 0)
-			xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
-		si_pmu_pll_init(sih, sii->osh, xtalfreq);
-		si_pmu_res_init(sih, sii->osh);
-		si_pmu_swreg_init(sih, sii->osh);
+			xtalfreq = si_pmu_measure_alpclk(sih);
+		si_pmu_pll_init(sih, xtalfreq);
+		si_pmu_res_init(sih);
+		si_pmu_swreg_init(sih);
 	}
 
 	/* setup the GPIO based LED powersave register */
@@ -499,8 +494,8 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 }
 
 #else				/* BCMSDIO */
-static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
-			      void *regs, uint bustype, void *sdh,
+static si_info_t *si_doattach(si_info_t *sii, uint devid,
+			      void *regs, uint bustype, void *pbus,
 			      char **vars, uint *varsz)
 {
 	struct si_pub *sih = &sii->pub;
@@ -518,12 +513,11 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	sih->buscoreidx = BADIDX;
 
 	sii->curmap = regs;
-	sii->sdh = sdh;
-	sii->osh = osh;
+	sii->pbus = pbus;
 
 	/* check to see if we are a si core mimic'ing a pci core */
 	if (bustype == PCI_BUS) {
-		pci_read_config_dword(sii->osh->pdev, PCI_SPROM_CONTROL,  &w);
+		pci_read_config_dword(sii->pbus, PCI_SPROM_CONTROL,  &w);
 		if (w == 0xffffffff) {
 			SI_ERROR(("%s: incoming bus is PCI but it's a lie, "
 				" switching to SI devid:0x%x\n",
@@ -534,10 +528,10 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 
 	/* find Chipcommon address */
 	if (bustype == PCI_BUS) {
-		pci_read_config_dword(sii->osh->pdev, PCI_BAR0_WIN, &savewin);
+		pci_read_config_dword(sii->pbus, PCI_BAR0_WIN, &savewin);
 		if (!GOODCOREADDR(savewin, SI_ENUM_BASE))
 			savewin = SI_ENUM_BASE;
-		pci_write_config_dword(sii->osh->pdev, PCI_BAR0_WIN,
+		pci_write_config_dword(sii->pbus, PCI_BAR0_WIN,
 				       SI_ENUM_BASE);
 		cc = (chipcregs_t *) regs;
 	} else {
@@ -547,7 +541,7 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	sih->bustype = bustype;
 
 	/* bus/core/clk setup for register access */
-	if (!si_buscore_prep(sii, bustype, devid, sdh)) {
+	if (!si_buscore_prep(sii, bustype, devid, pbus)) {
 		SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n",
 			  bustype));
 		return NULL;
@@ -558,7 +552,7 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 	 *   If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon),
 	 *   some way of recognizing them needs to be added here.
 	 */
-	w = R_REG(osh, &cc->chipid);
+	w = R_REG(&cc->chipid);
 	sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT;
 	/* Might as wll fill in chip id rev & pkg */
 	sih->chip = w & CID_ID_MASK;
@@ -598,10 +592,10 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 
 		if ((cc->chipstatus & CST43236_BP_CLK) != 0) {
 			uint clkdiv;
-			clkdiv = R_REG(osh, &cc->clkdiv);
+			clkdiv = R_REG(&cc->clkdiv);
 			/* otp_clk_div is even number, 120/14 < 9mhz */
 			clkdiv = (clkdiv & ~CLKD_OTP) | (14 << CLKD_OTP_SHIFT);
-			W_REG(osh, &cc->clkdiv, clkdiv);
+			W_REG(&cc->clkdiv, clkdiv);
 			SI_ERROR(("%s: set clkdiv to %x\n", __func__, clkdiv));
 		}
 		udelay(10);
@@ -612,7 +606,7 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 
 	/* Init nvram from sprom/otp if they exist */
 	if (srom_var_init
-	    (&sii->pub, bustype, regs, sii->osh, vars, varsz)) {
+	    (&sii->pub, bustype, regs, vars, varsz)) {
 		SI_ERROR(("si_doattach: srom_var_init failed: bad srom\n"));
 		goto exit;
 	}
@@ -621,22 +615,22 @@ static si_info_t *si_doattach(si_info_t *sii, uint devid, struct osl_info *osh,
 
 	/* === NVRAM, clock is ready === */
 	cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
-	W_REG(osh, &cc->gpiopullup, 0);
-	W_REG(osh, &cc->gpiopulldown, 0);
+	W_REG(&cc->gpiopullup, 0);
+	W_REG(&cc->gpiopulldown, 0);
 	si_setcoreidx(sih, origidx);
 
 	/* PMU specific initializations */
 	if (PMUCTL_ENAB(sih)) {
 		u32 xtalfreq;
-		si_pmu_init(sih, sii->osh);
-		si_pmu_chip_init(sih, sii->osh);
+		si_pmu_init(sih);
+		si_pmu_chip_init(sih);
 		xtalfreq = getintvar(pvars, "xtalfreq");
 		/* If xtalfreq var not available, try to measure it */
 		if (xtalfreq == 0)
-			xtalfreq = si_pmu_measure_alpclk(sih, sii->osh);
-		si_pmu_pll_init(sih, sii->osh, xtalfreq);
-		si_pmu_res_init(sih, sii->osh);
-		si_pmu_swreg_init(sih, sii->osh);
+			xtalfreq = si_pmu_measure_alpclk(sih);
+		si_pmu_pll_init(sih, xtalfreq);
+		si_pmu_res_init(sih);
+		si_pmu_swreg_init(sih);
 	}
 
 	/* setup the GPIO based LED powersave register */
@@ -700,7 +694,7 @@ void si_detach(si_t *sih)
 	uint idx;
 
 	struct si_pub *si_local = NULL;
-	bcopy(&sih, &si_local, sizeof(si_t **));
+	memcpy(&si_local, &sih, sizeof(si_t **));
 
 	sii = SI_INFO(sih);
 
@@ -729,14 +723,6 @@ void si_detach(si_t *sih)
 		kfree(sii);
 }
 
-struct osl_info *si_osh(si_t *sih)
-{
-	si_info_t *sii;
-
-	sii = SI_INFO(sih);
-	return sii->osh;
-}
-
 /* register driver interrupt disabling and restoring callback functions */
 void
 si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn,
@@ -996,7 +982,7 @@ void si_core_reset(si_t *sih, u32 bits, u32 resetbits)
 u32 si_alp_clock(si_t *sih)
 {
 	if (PMUCTL_ENAB(sih))
-		return si_pmu_alp_clock(sih, si_osh(sih));
+		return si_pmu_alp_clock(sih);
 
 	return ALP_CLOCK;
 }
@@ -1004,7 +990,7 @@ u32 si_alp_clock(si_t *sih)
 u32 si_ilp_clock(si_t *sih)
 {
 	if (PMUCTL_ENAB(sih))
-		return si_pmu_ilp_clock(sih, si_osh(sih));
+		return si_pmu_ilp_clock(sih);
 
 	return ILP_CLOCK;
 }
@@ -1090,7 +1076,7 @@ static uint si_slowclk_src(si_info_t *sii)
 
 	if (sii->pub.ccrev < 6) {
 		if (sii->pub.bustype == PCI_BUS) {
-			pci_read_config_dword(sii->osh->pdev, PCI_GPIO_OUT,
+			pci_read_config_dword(sii->pbus, PCI_GPIO_OUT,
 					      &val);
 			if (val & PCI_CFG_GPIO_SCS)
 				return SCC_SS_PCI;
@@ -1098,7 +1084,7 @@ static uint si_slowclk_src(si_info_t *sii)
 		return SCC_SS_XTAL;
 	} else if (sii->pub.ccrev < 10) {
 		cc = (chipcregs_t *) si_setcoreidx(&sii->pub, sii->curidx);
-		return R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK;
+		return R_REG(&cc->slow_clk_ctl) & SCC_SS_MASK;
 	} else			/* Insta-clock */
 		return SCC_SS_XTAL;
 }
@@ -1112,7 +1098,7 @@ static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
 	ASSERT(SI_FAST(sii) || si_coreid(&sii->pub) == CC_CORE_ID);
 
 	/* shouldn't be here unless we've established the chip has dynamic clk control */
-	ASSERT(R_REG(sii->osh, &cc->capabilities) & CC_CAP_PWR_CTL);
+	ASSERT(R_REG(&cc->capabilities) & CC_CAP_PWR_CTL);
 
 	slowclk = si_slowclk_src(sii);
 	if (sii->pub.ccrev < 6) {
@@ -1124,7 +1110,7 @@ static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
 				: (XTALMINFREQ / 32);
 	} else if (sii->pub.ccrev < 10) {
 		div = 4 *
-		    (((R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_CD_MASK) >>
+		    (((R_REG(&cc->slow_clk_ctl) & SCC_CD_MASK) >>
 		      SCC_CD_SHIFT) + 1);
 		if (slowclk == SCC_SS_LPO)
 			return max_freq ? LPOMAXFREQ : LPOMINFREQ;
@@ -1138,7 +1124,7 @@ static uint si_slowclk_freq(si_info_t *sii, bool max_freq, chipcregs_t *cc)
 			ASSERT(0);
 	} else {
 		/* Chipc rev 10 is InstaClock */
-		div = R_REG(sii->osh, &cc->system_clk_ctl) >> SYCC_CD_SHIFT;
+		div = R_REG(&cc->system_clk_ctl) >> SYCC_CD_SHIFT;
 		div = 4 * (div + 1);
 		return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div);
 	}
@@ -1168,8 +1154,8 @@ static void si_clkctl_setdelay(si_info_t *sii, void *chipcregs)
 	pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000;
 	fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000;
 
-	W_REG(sii->osh, &cc->pll_on_delay, pll_on_delay);
-	W_REG(sii->osh, &cc->fref_sel_delay, fref_sel_delay);
+	W_REG(&cc->pll_on_delay, pll_on_delay);
+	W_REG(&cc->fref_sel_delay, fref_sel_delay);
 }
 
 /* initialize power control delay registers */
@@ -1199,7 +1185,7 @@ void si_clkctl_init(si_t *sih)
 
 	/* set all Instaclk chip ILP to 1 MHz */
 	if (sih->ccrev >= 10)
-		SET_REG(sii->osh, &cc->system_clk_ctl, SYCC_CD_MASK,
+		SET_REG(&cc->system_clk_ctl, SYCC_CD_MASK,
 			(ILP_DIV_1MHZ << SYCC_CD_SHIFT));
 
 	si_clkctl_setdelay(sii, (void *)cc);
@@ -1222,7 +1208,7 @@ u16 si_clkctl_fast_pwrup_delay(si_t *sih)
 	sii = SI_INFO(sih);
 	if (PMUCTL_ENAB(sih)) {
 		INTR_OFF(sii, intr_val);
-		fpdelay = si_pmu_fast_pwrup_delay(sih, sii->osh);
+		fpdelay = si_pmu_fast_pwrup_delay(sih);
 		INTR_RESTORE(sii, intr_val);
 		return fpdelay;
 	}
@@ -1246,7 +1232,7 @@ u16 si_clkctl_fast_pwrup_delay(si_t *sih)
 	ASSERT(cc != NULL);
 
 	slowminfreq = si_slowclk_freq(sii, false, cc);
-	fpdelay = (((R_REG(sii->osh, &cc->pll_on_delay) + 2) * 1000000) +
+	fpdelay = (((R_REG(&cc->pll_on_delay) + 2) * 1000000) +
 		   (slowminfreq - 1)) / slowminfreq;
 
  done:
@@ -1277,9 +1263,9 @@ int si_clkctl_xtal(si_t *sih, uint what, bool on)
 		if (PCIE(sii))
 			return -1;
 
-		pci_read_config_dword(sii->osh->pdev, PCI_GPIO_IN, &in);
-		pci_read_config_dword(sii->osh->pdev, PCI_GPIO_OUT, &out);
-		pci_read_config_dword(sii->osh->pdev, PCI_GPIO_OUTEN, &outen);
+		pci_read_config_dword(sii->pbus, PCI_GPIO_IN, &in);
+		pci_read_config_dword(sii->pbus, PCI_GPIO_OUT, &out);
+		pci_read_config_dword(sii->pbus, PCI_GPIO_OUTEN, &outen);
 
 		/*
 		 * Avoid glitching the clock if GPRS is already using it.
@@ -1300,9 +1286,9 @@ int si_clkctl_xtal(si_t *sih, uint what, bool on)
 				out |= PCI_CFG_GPIO_XTAL;
 				if (what & PLL)
 					out |= PCI_CFG_GPIO_PLL;
-				pci_write_config_dword(sii->osh->pdev,
+				pci_write_config_dword(sii->pbus,
 						       PCI_GPIO_OUT, out);
-				pci_write_config_dword(sii->osh->pdev,
+				pci_write_config_dword(sii->pbus,
 						       PCI_GPIO_OUTEN, outen);
 				udelay(XTAL_ON_DELAY);
 			}
@@ -1310,7 +1296,7 @@ int si_clkctl_xtal(si_t *sih, uint what, bool on)
 			/* turn pll on */
 			if (what & PLL) {
 				out &= ~PCI_CFG_GPIO_PLL;
-				pci_write_config_dword(sii->osh->pdev,
+				pci_write_config_dword(sii->pbus,
 						       PCI_GPIO_OUT, out);
 				mdelay(2);
 			}
@@ -1319,9 +1305,9 @@ int si_clkctl_xtal(si_t *sih, uint what, bool on)
 				out &= ~PCI_CFG_GPIO_XTAL;
 			if (what & PLL)
 				out |= PCI_CFG_GPIO_PLL;
-			pci_write_config_dword(sii->osh->pdev,
+			pci_write_config_dword(sii->pbus,
 					       PCI_GPIO_OUT, out);
-			pci_write_config_dword(sii->osh->pdev,
+			pci_write_config_dword(sii->pbus,
 					       PCI_GPIO_OUTEN, outen);
 		}
 
@@ -1397,20 +1383,20 @@ static bool _si_clkctl_cc(si_info_t *sii, uint mode)
 		if (sii->pub.ccrev < 10) {
 			/* don't forget to force xtal back on before we clear SCC_DYN_XTAL.. */
 			si_clkctl_xtal(&sii->pub, XTAL, ON);
-			SET_REG(sii->osh, &cc->slow_clk_ctl,
+			SET_REG(&cc->slow_clk_ctl,
 				(SCC_XC | SCC_FS | SCC_IP), SCC_IP);
 		} else if (sii->pub.ccrev < 20) {
-			OR_REG(sii->osh, &cc->system_clk_ctl, SYCC_HR);
+			OR_REG(&cc->system_clk_ctl, SYCC_HR);
 		} else {
-			OR_REG(sii->osh, &cc->clk_ctl_st, CCS_FORCEHT);
+			OR_REG(&cc->clk_ctl_st, CCS_FORCEHT);
 		}
 
 		/* wait for the PLL */
 		if (PMUCTL_ENAB(&sii->pub)) {
 			u32 htavail = CCS_HTAVAIL;
-			SPINWAIT(((R_REG(sii->osh, &cc->clk_ctl_st) & htavail)
+			SPINWAIT(((R_REG(&cc->clk_ctl_st) & htavail)
 				  == 0), PMU_MAX_TRANSITION_DLY);
-			ASSERT(R_REG(sii->osh, &cc->clk_ctl_st) & htavail);
+			ASSERT(R_REG(&cc->clk_ctl_st) & htavail);
 		} else {
 			udelay(PLL_DELAY);
 		}
@@ -1418,20 +1404,20 @@ static bool _si_clkctl_cc(si_info_t *sii, uint mode)
 
 	case CLK_DYNAMIC:	/* enable dynamic clock control */
 		if (sii->pub.ccrev < 10) {
-			scc = R_REG(sii->osh, &cc->slow_clk_ctl);
+			scc = R_REG(&cc->slow_clk_ctl);
 			scc &= ~(SCC_FS | SCC_IP | SCC_XC);
 			if ((scc & SCC_SS_MASK) != SCC_SS_XTAL)
 				scc |= SCC_XC;
-			W_REG(sii->osh, &cc->slow_clk_ctl, scc);
+			W_REG(&cc->slow_clk_ctl, scc);
 
 			/* for dynamic control, we have to release our xtal_pu "force on" */
 			if (scc & SCC_XC)
 				si_clkctl_xtal(&sii->pub, XTAL, OFF);
 		} else if (sii->pub.ccrev < 20) {
 			/* Instaclock */
-			AND_REG(sii->osh, &cc->system_clk_ctl, ~SYCC_HR);
+			AND_REG(&cc->system_clk_ctl, ~SYCC_HR);
 		} else {
-			AND_REG(sii->osh, &cc->clk_ctl_st, ~CCS_FORCEHT);
+			AND_REG(&cc->clk_ctl_st, ~CCS_FORCEHT);
 		}
 		break;
 
@@ -1464,10 +1450,11 @@ int si_devpath(si_t *sih, char *path, int size)
 		slen = snprintf(path, (size_t) size, "sb/%u/", si_coreidx(sih));
 		break;
 	case PCI_BUS:
-		ASSERT((SI_INFO(sih))->osh != NULL);
+		ASSERT((SI_INFO(sih))->pbus != NULL);
 		slen = snprintf(path, (size_t) size, "pci/%u/%u/",
-				OSL_PCI_BUS((SI_INFO(sih))->osh),
-				OSL_PCI_SLOT((SI_INFO(sih))->osh));
+			((struct pci_dev *)((SI_INFO(sih))->pbus))->bus->number,
+			PCI_SLOT(
+			    ((struct pci_dev *)((SI_INFO(sih))->pbus))->devfn));
 		break;
 
 #ifdef BCMSDIO
@@ -1552,7 +1539,7 @@ static __used bool si_ispcie(si_info_t *sii)
 		return false;
 
 	cap_ptr =
-	    pcicore_find_pci_capability(sii->osh, PCI_CAP_PCIECAP_ID, NULL,
+	    pcicore_find_pci_capability(sii->pbus, PCI_CAP_PCIECAP_ID, NULL,
 					NULL);
 	if (!cap_ptr)
 		return false;
@@ -1585,8 +1572,8 @@ void si_sdio_init(si_t *sih)
 		SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " "through SD core %d (%p)\n", sih->buscorerev, idx, sii->curidx, sdpregs));
 
 		/* enable backplane error and core interrupts */
-		W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT);
-		W_REG(sii->osh, &sdpregs->sbintmask,
+		W_REG(&sdpregs->hostintmask, I_SBINT);
+		W_REG(&sdpregs->sbintmask,
 		      (I_SB_SERR | I_SB_RESPERR | (1 << idx)));
 
 		/* switch back to previous core */
@@ -1594,7 +1581,7 @@ void si_sdio_init(si_t *sih)
 	}
 
 	/* enable interrupts */
-	bcmsdh_intr_enable(sii->sdh);
+	bcmsdh_intr_enable(sii->pbus);
 
 }
 #endif				/* BCMSDIO */
@@ -1690,24 +1677,24 @@ void si_pci_setup(si_t *sih, uint coremask)
 	 */
 	if (PCIE(sii) || (PCI(sii) && ((sii->pub.buscorerev) >= 6))) {
 		/* pci config write to set this core bit in PCIIntMask */
-		pci_read_config_dword(sii->osh->pdev, PCI_INT_MASK, &w);
+		pci_read_config_dword(sii->pbus, PCI_INT_MASK, &w);
 		w |= (coremask << PCI_SBIM_SHIFT);
-		pci_write_config_dword(sii->osh->pdev, PCI_INT_MASK, w);
+		pci_write_config_dword(sii->pbus, PCI_INT_MASK, w);
 	} else {
 		/* set sbintvec bit for our flag number */
 		si_setint(sih, siflag);
 	}
 
 	if (PCI(sii)) {
-		OR_REG(sii->osh, &pciregs->sbtopci2,
+		OR_REG(&pciregs->sbtopci2,
 		       (SBTOPCI_PREF | SBTOPCI_BURST));
 		if (sii->pub.buscorerev >= 11) {
-			OR_REG(sii->osh, &pciregs->sbtopci2,
+			OR_REG(&pciregs->sbtopci2,
 			       SBTOPCI_RC_READMULTI);
-			w = R_REG(sii->osh, &pciregs->clkrun);
-			W_REG(sii->osh, &pciregs->clkrun,
+			w = R_REG(&pciregs->clkrun);
+			W_REG(&pciregs->clkrun,
 			      (w | PCI_CLKRUN_DSBL));
-			w = R_REG(sii->osh, &pciregs->clkrun);
+			w = R_REG(&pciregs->clkrun);
 		}
 
 		/* switch back to previous core */
@@ -1749,12 +1736,12 @@ int si_pci_fixcfg(si_t *sih)
 		reg16 = &pciregs->sprom[SRSH_PI_OFFSET];
 	}
 	pciidx = si_coreidx(&sii->pub);
-	val16 = R_REG(sii->osh, reg16);
+	val16 = R_REG(reg16);
 	if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != (u16) pciidx) {
 		val16 =
 		    (u16) (pciidx << SRSH_PI_SHIFT) | (val16 &
 							  ~SRSH_PI_MASK);
-		W_REG(sii->osh, reg16, val16);
+		W_REG(reg16, val16);
 	}
 
 	/* restore the original index */
@@ -1795,8 +1782,8 @@ socram_banksize(si_info_t *sii, sbsocramregs_t *regs, u8 index,
 
 	ASSERT(mem_type <= SOCRAM_MEMTYPE_DEVRAM);
 
-	W_REG(sii->osh, &regs->bankidx, bankidx);
-	bankinfo = R_REG(sii->osh, &regs->bankinfo);
+	W_REG(&regs->bankidx, bankidx);
+	bankinfo = R_REG(&regs->bankinfo);
 	banksize =
 	    SOCRAM_BANKINFO_SZBASE * ((bankinfo & SOCRAM_BANKINFO_SZMASK) + 1);
 	return banksize;
@@ -1831,7 +1818,7 @@ u32 si_socram_size(si_t *sih)
 	if (!wasup)
 		si_core_reset(sih, 0, 0);
 	corerev = si_corerev(sih);
-	coreinfo = R_REG(sii->osh, &regs->coreinfo);
+	coreinfo = R_REG(&regs->coreinfo);
 
 	/* Calculate size from coreinfo based on rev */
 	if (corerev == 0)
@@ -1879,22 +1866,22 @@ void si_chipcontrl_epa4331(si_t *sih, bool on)
 
 	cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
 
-	val = R_REG(sii->osh, &cc->chipcontrol);
+	val = R_REG(&cc->chipcontrol);
 
 	if (on) {
 		if (sih->chippkg == 9 || sih->chippkg == 0xb) {
 			/* Ext PA Controls for 4331 12x9 Package */
-			W_REG(sii->osh, &cc->chipcontrol, val |
+			W_REG(&cc->chipcontrol, val |
 			      (CCTRL4331_EXTPA_EN |
 			       CCTRL4331_EXTPA_ON_GPIO2_5));
 		} else {
 			/* Ext PA Controls for 4331 12x12 Package */
-			W_REG(sii->osh, &cc->chipcontrol,
+			W_REG(&cc->chipcontrol,
 			      val | (CCTRL4331_EXTPA_EN));
 		}
 	} else {
 		val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5);
-		W_REG(sii->osh, &cc->chipcontrol, val);
+		W_REG(&cc->chipcontrol, val);
 	}
 
 	si_setcoreidx(sih, origidx);
@@ -1913,8 +1900,8 @@ void si_epa_4313war(si_t *sih)
 	cc = (chipcregs_t *) si_setcore(sih, CC_CORE_ID, 0);
 
 	/* EPA Fix */
-	W_REG(sii->osh, &cc->gpiocontrol,
-	      R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
+	W_REG(&cc->gpiocontrol,
+	      R_REG(&cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK);
 
 	si_setcoreidx(sih, origidx);
 }
@@ -1929,8 +1916,8 @@ bool si_deviceremoved(si_t *sih)
 
 	switch (sih->bustype) {
 	case PCI_BUS:
-		ASSERT(sii->osh != NULL);
-		pci_read_config_dword(sii->osh->pdev, PCI_CFG_VID, &w);
+		ASSERT(sii->pbus != NULL);
+		pci_read_config_dword(sii->pbus, PCI_CFG_VID, &w);
 		if ((w & 0xFFFF) != VENDOR_BROADCOM)
 			return true;
 		break;
@@ -1952,7 +1939,7 @@ bool si_is_sprom_available(si_t *sih)
 		sii = SI_INFO(sih);
 		origidx = sii->curidx;
 		cc = si_setcoreidx(sih, SI_CC_IDX);
-		sromctrl = R_REG(sii->osh, &cc->sromcontrol);
+		sromctrl = R_REG(&cc->sromcontrol);
 		si_setcoreidx(sih, origidx);
 		return sromctrl & SRC_PRESENT;
 	}
@@ -2006,14 +1993,14 @@ bool si_is_otp_disabled(si_t *sih)
 bool si_is_otp_powered(si_t *sih)
 {
 	if (PMUCTL_ENAB(sih))
-		return si_pmu_is_otp_powered(sih, si_osh(sih));
+		return si_pmu_is_otp_powered(sih);
 	return true;
 }
 
 void si_otp_power(si_t *sih, bool on)
 {
 	if (PMUCTL_ENAB(sih))
-		si_pmu_otp_power(sih, si_osh(sih), on);
+		si_pmu_otp_power(sih, on);
 	udelay(1000);
 }
 
diff --git a/drivers/staging/brcm80211/util/siutils_priv.h b/drivers/staging/brcm80211/util/siutils_priv.h
index 0284614..a03ff61 100644
--- a/drivers/staging/brcm80211/util/siutils_priv.h
+++ b/drivers/staging/brcm80211/util/siutils_priv.h
@@ -25,8 +25,6 @@ extern uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask,
 		       uint val);
 extern bool sb_iscoreup(si_t *sih);
 void *sb_setcoreidx(si_t *sih, uint coreidx);
-extern u32 sb_base(u32 admatch);
 extern void sb_core_reset(si_t *sih, u32 bits, u32 resetbits);
 extern void sb_core_disable(si_t *sih, u32 bits);
-extern bool sb_taclear(si_t *sih, bool details);
 #endif				/* _siutils_priv_h_ */
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 093032b..a4ceb29 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -910,9 +910,28 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
 		case INSN_BITS:
 			if (insn->n != 2) {
 				ret = -EINVAL;
-				break;
+			} else {
+				/* Most drivers ignore the base channel in
+				 * insn->chanspec.  Fix this here if
+				 * the subdevice has <= 32 channels.  */
+				unsigned int shift;
+				unsigned int orig_mask;
+
+				orig_mask = data[0];
+				if (s->n_chan <= 32) {
+					shift = CR_CHAN(insn->chanspec);
+					if (shift > 0) {
+						insn->chanspec = 0;
+						data[0] <<= shift;
+						data[1] <<= shift;
+					}
+				} else
+					shift = 0;
+				ret = s->insn_bits(dev, s, insn, data);
+				data[0] = orig_mask;
+				if (shift > 0)
+					data[1] >>= shift;
 			}
-			ret = s->insn_bits(dev, s, insn, data);
 			break;
 		case INSN_CONFIG:
 			ret = check_insn_config_length(insn, data);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index dca861e..6d60e91 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -471,9 +471,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
 
 		async->buf_page_list =
 		    vzalloc(sizeof(struct comedi_buf_page) * n_pages);
-		if (async->buf_page_list) {
+		if (async->buf_page_list)
 			pages = vmalloc(sizeof(struct page *) * n_pages);
-		}
+
 		if (pages) {
 			for (i = 0; i < n_pages; i++) {
 				if (s->async_dma_dir != DMA_NONE) {
diff --git a/drivers/staging/comedi/drivers/8255.c b/drivers/staging/comedi/drivers/8255.c
index 95049a8..6c26ac8 100644
--- a/drivers/staging/comedi/drivers/8255.c
+++ b/drivers/staging/comedi/drivers/8255.c
@@ -383,14 +383,7 @@ EXPORT_SYMBOL(subdev_8255_init_irq);
 
 void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-	if (s->private) {
-		/* this test does nothing, so comment it out
-		 * if (subdevpriv->have_irq) {
-		 * }
-		 */
-
-		kfree(s->private);
-	}
+	kfree(s->private);
 }
 EXPORT_SYMBOL(subdev_8255_cleanup);
 
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index 3275fc5..0941643 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -53,6 +53,15 @@ Configuration options:
 For commands, the scanned channels must be consecutive
 (i.e. 4-5-6-7, 2-3-4,...), and must all have the same
 range and aref.
+
+AI Triggering:
+   For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
+   For 1602 series, the start_arg is interpreted as follows:
+     start_arg == 0                   => gated triger (level high)
+     start_arg == CR_INVERT           => gated triger (level low)
+     start_arg == CR_EDGE             => Rising edge
+     start_arg == CR_EDGE | CR_INVERT => Falling edge
+   For the other boards the trigger will be done on rising edge
 */
 /*
 
@@ -135,6 +144,8 @@ analog triggering on 1602 series
 #define   EXT_TRIGGER 0x2	/*  external start trigger */
 #define   ANALOG_TRIGGER 0x3	/*  external analog trigger */
 #define   TRIGGER_MASK	0x3	/*  mask of bits that determine start trigger */
+#define   TGPOL	0x04		/*  invert the edge/level of the external trigger (1602 only) */
+#define   TGSEL	0x08		/*  if set edge triggered, otherwise level trigerred (1602 only) */
 #define   TGEN	0x10		/*  enable external start trigger */
 #define   BURSTE 0x20		/*  burst mode enable */
 #define   XTRCL	0x80		/*  clear external trigger */
@@ -257,6 +268,8 @@ struct cb_pcidas_board {
 	const struct comedi_lrange *ranges;
 	enum trimpot_model trimpot;
 	unsigned has_dac08:1;
+	unsigned has_ai_trig_gated:1;	/* Tells if the AI trigger can be gated */
+	unsigned has_ai_trig_invert:1;	/* Tells if the AI trigger can be inverted */
 };
 
 static const struct cb_pcidas_board cb_pcidas_boards[] = {
@@ -274,6 +287,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD8402,
 	 .has_dac08 = 1,
+	 .has_ai_trig_gated = 1,
+	 .has_ai_trig_invert = 1,
 	 },
 	{
 	 .name = "pci-das1200",
@@ -288,6 +303,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD7376,
 	 .has_dac08 = 0,
+	 .has_ai_trig_gated = 0,
+	 .has_ai_trig_invert = 0,
 	 },
 	{
 	 .name = "pci-das1602/12",
@@ -303,6 +320,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD7376,
 	 .has_dac08 = 0,
+	 .has_ai_trig_gated = 1,
+	 .has_ai_trig_invert = 1,
 	 },
 	{
 	 .name = "pci-das1200/jr",
@@ -317,6 +336,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD7376,
 	 .has_dac08 = 0,
+	 .has_ai_trig_gated = 0,
+	 .has_ai_trig_invert = 0,
 	 },
 	{
 	 .name = "pci-das1602/16/jr",
@@ -331,6 +352,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD8402,
 	 .has_dac08 = 1,
+	 .has_ai_trig_gated = 1,
+	 .has_ai_trig_invert = 1,
 	 },
 	{
 	 .name = "pci-das1000",
@@ -345,6 +368,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD7376,
 	 .has_dac08 = 0,
+	 .has_ai_trig_gated = 0,
+	 .has_ai_trig_invert = 0,
 	 },
 	{
 	 .name = "pci-das1001",
@@ -359,6 +384,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_alt_ranges,
 	 .trimpot = AD7376,
 	 .has_dac08 = 0,
+	 .has_ai_trig_gated = 0,
+	 .has_ai_trig_invert = 0,
 	 },
 	{
 	 .name = "pci-das1002",
@@ -373,6 +400,8 @@ static const struct cb_pcidas_board cb_pcidas_boards[] = {
 	 .ranges = &cb_pcidas_ranges,
 	 .trimpot = AD7376,
 	 .has_dac08 = 0,
+	 .has_ai_trig_gated = 0,
+	 .has_ai_trig_invert = 0,
 	 },
 };
 
@@ -1113,9 +1142,27 @@ static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
 
 	/* step 3: make sure arguments are trivially compatible */
 
-	if (cmd->start_arg != 0) {
-		cmd->start_arg = 0;
-		err++;
+	switch (cmd->start_src) {
+	case TRIG_EXT:
+		/* External trigger, only CR_EDGE and CR_INVERT flags allowed */
+		if ((cmd->start_arg
+		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
+			cmd->start_arg &=
+			    ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
+			err++;
+		}
+		if (!thisboard->has_ai_trig_invert &&
+		    (cmd->start_arg & CR_INVERT)) {
+			cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
+			err++;
+		}
+		break;
+	default:
+		if (cmd->start_arg != 0) {
+			cmd->start_arg = 0;
+			err++;
+		}
+		break;
 	}
 
 	if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -1270,9 +1317,14 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
 	bits = 0;
 	if (cmd->start_src == TRIG_NOW)
 		bits |= SW_TRIGGER;
-	else if (cmd->start_src == TRIG_EXT)
+	else if (cmd->start_src == TRIG_EXT) {
 		bits |= EXT_TRIGGER | TGEN | XTRCL;
-	else {
+		if (thisboard->has_ai_trig_invert
+		    && (cmd->start_arg & CR_INVERT))
+			bits |= TGPOL;
+		if (thisboard->has_ai_trig_gated && (cmd->start_arg & CR_EDGE))
+			bits |= TGSEL;
+	} else {
 		comedi_error(dev, "bug!");
 		return -1;
 	}
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index 0af1b46..e7905ba 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -1695,10 +1695,8 @@ static int das16_detach(struct comedi_device *dev)
 		}
 		if (devpriv->dma_chan)
 			free_dma(devpriv->dma_chan);
-		if (devpriv->user_ai_range_table)
-			kfree(devpriv->user_ai_range_table);
-		if (devpriv->user_ao_range_table)
-			kfree(devpriv->user_ao_range_table);
+		kfree(devpriv->user_ai_range_table);
+		kfree(devpriv->user_ao_range_table);
 	}
 
 	if (dev->irq)
diff --git a/drivers/staging/comedi/drivers/icp_multi.c b/drivers/staging/comedi/drivers/icp_multi.c
index 809d17e..0bab39b 100644
--- a/drivers/staging/comedi/drivers/icp_multi.c
+++ b/drivers/staging/comedi/drivers/icp_multi.c
@@ -176,13 +176,13 @@ static const struct boardtype boardtypes[] = {
 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
 
 static struct comedi_driver driver_icp_multi = {
-driver_name: "icp_multi",
-module : THIS_MODULE,
-attach : icp_multi_attach,
-detach : icp_multi_detach,
-num_names : n_boardtypes,
-board_name : &boardtypes[0].name,
-offset : sizeof(struct boardtype),
+	.driver_name = "icp_multi",
+	.module = THIS_MODULE,
+	.attach = icp_multi_attach,
+	.detach = icp_multi_detach,
+	.num_names = n_boardtypes,
+	.board_name = &boardtypes[0].name,
+	.offset = sizeof(struct boardtype),
 };
 
 static int __init driver_icp_multi_init_module(void)
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index e6825c2..75511ba 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -119,10 +119,10 @@ static int me4000_attach(struct comedi_device *dev,
 			 struct comedi_devconfig *it);
 static int me4000_detach(struct comedi_device *dev);
 static struct comedi_driver driver_me4000 = {
-driver_name: "me4000",
-module : THIS_MODULE,
-attach : me4000_attach,
-detach : me4000_detach,
+	.driver_name = "me4000",
+	.module = THIS_MODULE,
+	.attach = me4000_attach,
+	.detach = me4000_detach,
 };
 
 /*-----------------------------------------------------------------------------
diff --git a/drivers/staging/comedi/drivers/ni_at_a2150.c b/drivers/staging/comedi/drivers/ni_at_a2150.c
index e46d62b..4d0053e 100644
--- a/drivers/staging/comedi/drivers/ni_at_a2150.c
+++ b/drivers/staging/comedi/drivers/ni_at_a2150.c
@@ -479,8 +479,7 @@ static int a2150_detach(struct comedi_device *dev)
 	if (devpriv) {
 		if (devpriv->dma)
 			free_dma(devpriv->dma);
-		if (devpriv->dma_buffer)
-			kfree(devpriv->dma_buffer);
+		kfree(devpriv->dma_buffer);
 	}
 
 	return 0;
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 0728c3c..241fe52 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -797,8 +797,7 @@ int labpc_common_detach(struct comedi_device *dev)
 		subdev_8255_cleanup(dev, dev->subdevices + 2);
 
 	/* only free stuff if it has been allocated by _attach */
-	if (devpriv->dma_buffer)
-		kfree(devpriv->dma_buffer);
+	kfree(devpriv->dma_buffer);
 	if (devpriv->dma_chan)
 		free_dma(devpriv->dma_chan);
 	if (dev->irq)
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 3d0f018..ef3cc4f 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -108,7 +108,7 @@ struct pcl816_board {
 	const char *name;	/*  board name */
 	int n_ranges;		/*  len of range list */
 	int n_aichan;		/*  num of A/D chans in diferencial mode */
-	unsigned int ai_ns_min;	/*  minimal alllowed delay between samples (in ns) */
+	unsigned int ai_ns_min;	/*  minimal allowed delay between samples (in ns) */
 	int n_aochan;		/*  num of D/A chans */
 	int n_dichan;		/*  num of DI chans */
 	int n_dochan;		/*  num of DO chans */
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index d2bd6f8..f58d75b 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -261,7 +261,7 @@ struct pcl818_board {
 	int n_ranges;		/*  len of range list */
 	int n_aichan_se;	/*  num of A/D chans in single ended  mode */
 	int n_aichan_diff;	/*  num of A/D chans in diferencial mode */
-	unsigned int ns_min;	/*  minimal alllowed delay between samples (in ns) */
+	unsigned int ns_min;	/*  minimal allowed delay between samples (in ns) */
 	int n_aochan;		/*  num of D/A chans */
 	int n_dichan;		/*  num of DI chans */
 	int n_dochan;		/*  num of DO chans */
@@ -349,7 +349,7 @@ struct pcl818_private {
 	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
 	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
 	unsigned char neverending_ai;	/*  if=1, then we do neverending record (you must use cancel()) */
-	unsigned int ns_min;	/*  manimal alllowed delay between samples (in us) for actual card */
+	unsigned int ns_min;	/*  manimal allowed delay between samples (in us) for actual card */
 	int i8253_osc_base;	/*  1/frequency of on board oscilator in ns */
 	int irq_free;		/*  1=have allocated IRQ */
 	int irq_blocked;	/*  1=IRQ now uses any subdev */
diff --git a/drivers/staging/comedi/drivers/rtd520.c b/drivers/staging/comedi/drivers/rtd520.c
index aa8aeee..357858d 100644
--- a/drivers/staging/comedi/drivers/rtd520.c
+++ b/drivers/staging/comedi/drivers/rtd520.c
@@ -59,7 +59,7 @@ Configuration options:
     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 
+    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.
@@ -136,7 +136,7 @@ Configuration options:
 #define RTD_DMA_TIMEOUT	33000	/* 1 msec */
 #else
 /* by delaying, power and electrical noise are reduced somewhat */
-#define WAIT_QUIETLY	udelay (1)
+#define WAIT_QUIETLY	udelay(1)
 #define RTD_ADC_TIMEOUT	2000	/* in usec */
 #define RTD_DAC_TIMEOUT	2000	/* in usec */
 #define RTD_DMA_TIMEOUT	1000	/* in usec */
@@ -414,296 +414,296 @@ struct rtdPrivate {
 
 /* Reset board */
 #define RtdResetBoard(dev) \
-    writel (0, devpriv->las0+LAS0_BOARD_RESET)
+	writel(0, devpriv->las0+LAS0_BOARD_RESET)
 
 /* Reset channel gain table read pointer */
 #define RtdResetCGT(dev) \
-    writel (0, devpriv->las0+LAS0_CGT_RESET)
+	writel(0, devpriv->las0+LAS0_CGT_RESET)
 
 /* Reset channel gain table read and write pointers */
 #define RtdClearCGT(dev) \
-    writel (0, devpriv->las0+LAS0_CGT_CLEAR)
+	writel(0, devpriv->las0+LAS0_CGT_CLEAR)
 
 /* Reset channel gain table read and write pointers */
 #define RtdEnableCGT(dev, v) \
-    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
+	writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
 
 /* Write channel gain table entry */
 #define RtdWriteCGTable(dev, v) \
-    writel (v, devpriv->las0+LAS0_CGT_WRITE)
+	writel(v, devpriv->las0+LAS0_CGT_WRITE)
 
 /* Write Channel Gain Latch */
 #define RtdWriteCGLatch(dev, v) \
-    writel (v, devpriv->las0+LAS0_CGL_WRITE)
+	writel(v, devpriv->las0+LAS0_CGL_WRITE)
 
 /* Reset ADC FIFO */
 #define RtdAdcClearFifo(dev) \
-    writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
+	writel(0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
 
 /* Set ADC start conversion source select (write only) */
 #define RtdAdcConversionSource(dev, v) \
-    writel (v, devpriv->las0+LAS0_ADC_CONVERSION)
+	writel(v, devpriv->las0+LAS0_ADC_CONVERSION)
 
 /* Set burst start source select (write only) */
 #define RtdBurstStartSource(dev, v) \
-    writel (v, devpriv->las0+LAS0_BURST_START)
+	writel(v, devpriv->las0+LAS0_BURST_START)
 
 /* Set Pacer start source select (write only) */
 #define RtdPacerStartSource(dev, v) \
-    writel (v, devpriv->las0+LAS0_PACER_START)
+	writel(v, devpriv->las0+LAS0_PACER_START)
 
 /* Set Pacer stop source select (write only) */
 #define RtdPacerStopSource(dev, v) \
-    writel (v, devpriv->las0+LAS0_PACER_STOP)
+	writel(v, devpriv->las0+LAS0_PACER_STOP)
 
 /* Set Pacer clock source select (write only) 0=external 1=internal */
 #define RtdPacerClockSource(dev, v) \
-    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
+	writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
 
 /* Set sample counter source select (write only) */
 #define RtdAdcSampleCounterSource(dev, v) \
-    writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC)
+	writel(v, devpriv->las0+LAS0_ADC_SCNT_SRC)
 
 /* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */
 #define RtdPacerTriggerMode(dev, v) \
-    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
+	writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
 
 /* Set About counter stop enable (write only) */
 #define RtdAboutStopEnable(dev, v) \
-    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
+	writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
 
 /* Set external trigger polarity (write only) 0=positive edge, 1=negative */
 #define RtdTriggerPolarity(dev, v) \
-    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
+	writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
 
 /* Start single ADC conversion */
 #define RtdAdcStart(dev) \
-    writew (0, devpriv->las0+LAS0_ADC)
+	writew(0, devpriv->las0+LAS0_ADC)
 
 /* Read one ADC data value (12bit (with sign extend) as 16bit) */
 /* Note: matches what DMA would get.  Actual value >> 3 */
 #define RtdAdcFifoGet(dev) \
-    readw (devpriv->las1+LAS1_ADC_FIFO)
+	readw(devpriv->las1+LAS1_ADC_FIFO)
 
 /* Read two ADC data values (DOESNT WORK) */
 #define RtdAdcFifoGet2(dev) \
-    readl (devpriv->las1+LAS1_ADC_FIFO)
+	readl(devpriv->las1+LAS1_ADC_FIFO)
 
 /* FIFO status */
 #define RtdFifoStatus(dev) \
-    readl (devpriv->las0+LAS0_ADC)
+	readl(devpriv->las0+LAS0_ADC)
 
 /* pacer start/stop read=start, write=stop*/
 #define RtdPacerStart(dev) \
-    readl (devpriv->las0+LAS0_PACER)
+	readl(devpriv->las0+LAS0_PACER)
 #define RtdPacerStop(dev) \
-    writel (0, devpriv->las0+LAS0_PACER)
+	writel(0, devpriv->las0+LAS0_PACER)
 
 /* Interrupt status */
 #define RtdInterruptStatus(dev) \
-    readw (devpriv->las0+LAS0_IT)
+	readw(devpriv->las0+LAS0_IT)
 
 /* Interrupt mask */
 #define RtdInterruptMask(dev, v) \
-    writew ((devpriv->intMask = (v)), devpriv->las0+LAS0_IT)
+	writew((devpriv->intMask = (v)), devpriv->las0+LAS0_IT)
 
 /* Interrupt status clear (only bits set in mask) */
 #define RtdInterruptClear(dev) \
-    readw (devpriv->las0+LAS0_CLEAR)
+	readw(devpriv->las0+LAS0_CLEAR)
 
 /* Interrupt clear mask */
 #define RtdInterruptClearMask(dev, v) \
-    writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
+	writew((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
 
 /* Interrupt overrun status */
 #define RtdInterruptOverrunStatus(dev) \
-    readl (devpriv->las0+LAS0_OVERRUN)
+	readl(devpriv->las0+LAS0_OVERRUN)
 
 /* Interrupt overrun clear */
 #define RtdInterruptOverrunClear(dev) \
-    writel (0, devpriv->las0+LAS0_OVERRUN)
+	writel(0, devpriv->las0+LAS0_OVERRUN)
 
 /* Pacer counter, 24bit */
 #define RtdPacerCount(dev) \
-    readl (devpriv->las0+LAS0_PCLK)
+	readl(devpriv->las0+LAS0_PCLK)
 #define RtdPacerCounter(dev, v) \
-    writel ((v) & 0xffffff, devpriv->las0+LAS0_PCLK)
+	writel((v) & 0xffffff, devpriv->las0+LAS0_PCLK)
 
 /* Burst counter, 10bit */
 #define RtdBurstCount(dev) \
-    readl (devpriv->las0+LAS0_BCLK)
+	readl(devpriv->las0+LAS0_BCLK)
 #define RtdBurstCounter(dev, v) \
-    writel ((v) & 0x3ff, devpriv->las0+LAS0_BCLK)
+	writel((v) & 0x3ff, devpriv->las0+LAS0_BCLK)
 
 /* Delay counter, 16bit */
 #define RtdDelayCount(dev) \
-    readl (devpriv->las0+LAS0_DCLK)
+	readl(devpriv->las0+LAS0_DCLK)
 #define RtdDelayCounter(dev, v) \
-    writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK)
+	writel((v) & 0xffff, devpriv->las0+LAS0_DCLK)
 
 /* About counter, 16bit */
 #define RtdAboutCount(dev) \
-    readl (devpriv->las0+LAS0_ACNT)
+	readl(devpriv->las0+LAS0_ACNT)
 #define RtdAboutCounter(dev, v) \
-    writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT)
+	writel((v) & 0xffff, devpriv->las0+LAS0_ACNT)
 
 /* ADC sample counter, 10bit */
 #define RtdAdcSampleCount(dev) \
-    readl (devpriv->las0+LAS0_ADC_SCNT)
+	readl(devpriv->las0+LAS0_ADC_SCNT)
 #define RtdAdcSampleCounter(dev, v) \
-    writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
+	writel((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
 
 /* User Timer/Counter (8254) */
 #define RtdUtcCounterGet(dev, n) \
-    readb (devpriv->las0 \
-        + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
+	readb(devpriv->las0 \
+		+ ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
 
 #define RtdUtcCounterPut(dev, n, v) \
-    writeb ((v) & 0xff, devpriv->las0 \
-        + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
+	writeb((v) & 0xff, devpriv->las0 \
+		+ ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
 
 /* Set UTC (8254) control byte  */
 #define RtdUtcCtrlPut(dev, n, v) \
-    writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
-      devpriv->las0 + LAS0_UTC_CTRL)
+	writeb(devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
+		devpriv->las0 + LAS0_UTC_CTRL)
 
 /* Set UTCn clock source (write only) */
 #define RtdUtcClockSource(dev, n, v) \
-    writew (v, devpriv->las0 \
-        + ((n <= 0) ? LAS0_UTC0_CLOCK : \
-           ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
+	writew(v, devpriv->las0 \
+		+ ((n <= 0) ? LAS0_UTC0_CLOCK : \
+			((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
 
 /* Set UTCn gate source (write only) */
 #define RtdUtcGateSource(dev, n, v) \
-    writew (v, devpriv->las0 \
-        + ((n <= 0) ? LAS0_UTC0_GATE : \
-           ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
+	writew(v, devpriv->las0 \
+		+ ((n <= 0) ? LAS0_UTC0_GATE : \
+			((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
 
 /* User output N source select (write only) */
 #define RtdUsrOutSource(dev, n, v) \
-    writel (v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
+	writel(v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
 
 /* Digital IO */
 #define RtdDio0Read(dev) \
-    (readw (devpriv->las0+LAS0_DIO0) & 0xff)
+	(readw(devpriv->las0+LAS0_DIO0) & 0xff)
 #define RtdDio0Write(dev, v) \
-    writew ((v) & 0xff, devpriv->las0+LAS0_DIO0)
+	writew((v) & 0xff, devpriv->las0+LAS0_DIO0)
 
 #define RtdDio1Read(dev) \
-    (readw (devpriv->las0+LAS0_DIO1) & 0xff)
+	(readw(devpriv->las0+LAS0_DIO1) & 0xff)
 #define RtdDio1Write(dev, v) \
-    writew ((v) & 0xff, devpriv->las0+LAS0_DIO1)
+	writew((v) & 0xff, devpriv->las0+LAS0_DIO1)
 
 #define RtdDioStatusRead(dev) \
-    (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff)
+	(readw(devpriv->las0+LAS0_DIO_STATUS) & 0xff)
 #define RtdDioStatusWrite(dev, v) \
-    writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
+	writew((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
 
 #define RtdDio0CtrlRead(dev) \
-    (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
+	(readw(devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
 #define RtdDio0CtrlWrite(dev, v) \
-    writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
+	writew((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
 
 /* Digital to Analog converter */
 /* Write one data value (sign + 12bit + marker bits) */
 /* Note: matches what DMA would put.  Actual value << 3 */
 #define RtdDacFifoPut(dev, n, v) \
-    writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
+	writew((v), devpriv->las1 + (((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
 
 /* Start single DAC conversion */
 #define RtdDacUpdate(dev, n) \
-    writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
+	writew(0, devpriv->las0 + (((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
 
 /* Start single DAC conversion on both DACs */
 #define RtdDacBothUpdate(dev) \
-    writew (0, devpriv->las0+LAS0_DAC)
+	writew(0, devpriv->las0+LAS0_DAC)
 
 /* Set DAC output type and range */
 #define RtdDacRange(dev, n, v) \
-    writew ((v) & 7, devpriv->las0 \
-	+(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
+	writew((v) & 7, devpriv->las0 \
+		+(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
 
 /* Reset DAC FIFO */
 #define RtdDacClearFifo(dev, n) \
-    writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
+	writel(0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
 
 /* Set source for DMA 0 (write only, shadow?) */
 #define RtdDma0Source(dev, n) \
-    writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
+	writel((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
 
 /* Set source for DMA 1 (write only, shadow?) */
 #define RtdDma1Source(dev, n) \
-    writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
+	writel((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
 
 /* Reset board state for DMA 0 */
 #define RtdDma0Reset(dev) \
-    writel (0, devpriv->las0+LAS0_DMA0_RESET)
+	writel(0, devpriv->las0+LAS0_DMA0_RESET)
 
 /* Reset board state for DMA 1 */
 #define RtdDma1Reset(dev) \
-    writel (0, devpriv->las0+LAS0_DMA1_SRC)
+	writel(0, devpriv->las0+LAS0_DMA1_SRC)
 
 /* PLX9080 interrupt mask and status */
 #define RtdPlxInterruptRead(dev) \
-    readl (devpriv->lcfg+LCFG_ITCSR)
+	readl(devpriv->lcfg+LCFG_ITCSR)
 #define RtdPlxInterruptWrite(dev, v) \
-    writel (v, devpriv->lcfg+LCFG_ITCSR)
+	writel(v, devpriv->lcfg+LCFG_ITCSR)
 
 /* Set  mode for DMA 0 */
 #define RtdDma0Mode(dev, m) \
-    writel ((m), devpriv->lcfg+LCFG_DMAMODE0)
+	writel((m), devpriv->lcfg+LCFG_DMAMODE0)
 
 /* Set PCI address for DMA 0 */
 #define RtdDma0PciAddr(dev, a) \
-    writel ((a), devpriv->lcfg+LCFG_DMAPADR0)
+	writel((a), devpriv->lcfg+LCFG_DMAPADR0)
 
 /* Set local address for DMA 0 */
 #define RtdDma0LocalAddr(dev, a) \
-    writel ((a), devpriv->lcfg+LCFG_DMALADR0)
+	writel((a), devpriv->lcfg+LCFG_DMALADR0)
 
 /* Set byte count for DMA 0 */
 #define RtdDma0Count(dev, c) \
-    writel ((c), devpriv->lcfg+LCFG_DMASIZ0)
+	writel((c), devpriv->lcfg+LCFG_DMASIZ0)
 
 /* Set next descriptor for DMA 0 */
 #define RtdDma0Next(dev, a) \
-    writel ((a), devpriv->lcfg+LCFG_DMADPR0)
+	writel((a), devpriv->lcfg+LCFG_DMADPR0)
 
 /* Set  mode for DMA 1 */
 #define RtdDma1Mode(dev, m) \
-    writel ((m), devpriv->lcfg+LCFG_DMAMODE1)
+	writel((m), devpriv->lcfg+LCFG_DMAMODE1)
 
 /* Set PCI address for DMA 1 */
 #define RtdDma1PciAddr(dev, a) \
-    writel ((a), devpriv->lcfg+LCFG_DMAADR1)
+	writel((a), devpriv->lcfg+LCFG_DMAADR1)
 
 /* Set local address for DMA 1 */
 #define RtdDma1LocalAddr(dev, a) \
-    writel ((a), devpriv->lcfg+LCFG_DMALADR1)
+	writel((a), devpriv->lcfg+LCFG_DMALADR1)
 
 /* Set byte count for DMA 1 */
 #define RtdDma1Count(dev, c) \
-    writel ((c), devpriv->lcfg+LCFG_DMASIZ1)
+	writel((c), devpriv->lcfg+LCFG_DMASIZ1)
 
 /* Set next descriptor for DMA 1 */
 #define RtdDma1Next(dev, a) \
-    writel ((a), devpriv->lcfg+LCFG_DMADPR1)
+	writel((a), devpriv->lcfg+LCFG_DMADPR1)
 
 /* Set control for DMA 0 (write only, shadow?) */
 #define RtdDma0Control(dev, n) \
-    writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
+	writeb(devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
 
 /* Get status for DMA 0 */
 #define RtdDma0Status(dev) \
-    readb (devpriv->lcfg+LCFG_DMACSR0)
+	readb(devpriv->lcfg+LCFG_DMACSR0)
 
 /* Set control for DMA 1 (write only, shadow?) */
 #define RtdDma1Control(dev, n) \
-    writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
+	writeb(devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
 
 /* Get status for DMA 1 */
 #define RtdDma1Status(dev) \
-    readb (devpriv->lcfg+LCFG_DMACSR1)
+	readb(devpriv->lcfg+LCFG_DMACSR1)
 
 /*
  * The struct comedi_driver structure tells the Comedi core module
@@ -760,9 +760,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	int index;
 #endif
 
-	printk("comedi%d: rtd520 attaching.\n", dev->minor);
+	printk(KERN_INFO "comedi%d: rtd520 attaching.\n", dev->minor);
 
-#if defined (CONFIG_COMEDI_DEBUG) && defined (USE_DMA)
+#if defined(CONFIG_COMEDI_DEBUG) && defined(USE_DMA)
 	/* You can set this a load time: modprobe comedi comedi_debug=1 */
 	if (0 == comedi_debug)	/* force DMA debug printks */
 		comedi_debug = 1;
@@ -800,10 +800,10 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	if (!pcidev) {
 		if (it->options[0] && it->options[1]) {
-			printk("No RTD card at bus=%d slot=%d.\n",
+			printk(KERN_INFO "No RTD card at bus=%d slot=%d.\n",
 			       it->options[0], it->options[1]);
 		} else {
-			printk("No RTD card found.\n");
+			printk(KERN_INFO "No RTD card found.\n");
 		}
 		return -EIO;
 	}
@@ -812,7 +812,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 
 	ret = comedi_pci_enable(pcidev, DRV_NAME);
 	if (ret < 0) {
-		printk("Failed to enable PCI device and request regions.\n");
+		printk(KERN_INFO "Failed to enable PCI device and request regions.\n");
 		return ret;
 	}
 	devpriv->got_regions = 1;
@@ -830,9 +830,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE);
 	devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE);
 
-	if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) {
+	if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)
 		return -ENOMEM;
-	}
+
 
 	DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name,
 		(unsigned long long)physLas0, (unsigned long long)physLas1,
@@ -849,7 +849,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		pci_read_config_byte(devpriv->pci_dev,
 				     PCI_LATENCY_TIMER, &pci_latency);
 		if (pci_latency < 32) {
-			printk("%s: PCI latency changed from %d to %d\n",
+			printk(KERN_INFO "%s: PCI latency changed from %d to %d\n",
 			       dev->board_name, pci_latency, 32);
 			pci_write_config_byte(devpriv->pci_dev,
 					      PCI_LATENCY_TIMER, 32);
@@ -875,9 +875,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	 * Allocate the subdevice structures.  alloc_subdevice() is a
 	 * convenient macro defined in comedidev.h.
 	 */
-	if (alloc_subdevices(dev, 4) < 0) {
+	if (alloc_subdevices(dev, 4) < 0)
 		return -ENOMEM;
-	}
+
 
 	s = dev->subdevices + 0;
 	dev->read_subdev = s;
@@ -887,11 +887,11 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	    SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
 	s->n_chan = thisboard->aiChans;
 	s->maxdata = (1 << thisboard->aiBits) - 1;
-	if (thisboard->aiMaxGain <= 32) {
+	if (thisboard->aiMaxGain <= 32)
 		s->range_table = &rtd_ai_7520_range;
-	} else {
+	else
 		s->range_table = &rtd_ai_4520_range;
-	}
+
 	s->len_chanlist = RTD_MAX_CHANLIST;	/* devpriv->fifoLen */
 	s->insn_read = rtd_ai_rinsn;
 	s->do_cmd = rtd_ai_cmd;
@@ -961,9 +961,9 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	printk("( irq=%u )", dev->irq);
 
 	ret = rtd520_probe_fifo_depth(dev);
-	if (ret < 0) {
+	if (ret < 0)
 		return ret;
-	}
+
 	devpriv->fifoLen = ret;
 	printk("( fifoLen=%d )", devpriv->fifoLen);
 
@@ -1028,7 +1028,7 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 		RtdDma0Mode(dev, DMA_MODE_BITS);
 		RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);	/* set DMA trigger source */
 	} else {
-		printk("( no IRQ->no DMA )");
+		printk(KERN_INFO "( no IRQ->no DMA )");
 	}
 #endif /* USE_DMA */
 
@@ -1071,18 +1071,18 @@ static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 
 	/* release all regions that were allocated */
-	if (devpriv->las0) {
+	if (devpriv->las0)
 		iounmap(devpriv->las0);
-	}
-	if (devpriv->las1) {
+
+	if (devpriv->las1)
 		iounmap(devpriv->las1);
-	}
-	if (devpriv->lcfg) {
+
+	if (devpriv->lcfg)
 		iounmap(devpriv->lcfg);
-	}
-	if (devpriv->pci_dev) {
+
+	if (devpriv->pci_dev)
 		pci_dev_put(devpriv->pci_dev);
-	}
+
 	return ret;
 #endif
 }
@@ -1158,24 +1158,24 @@ static int rtd_detach(struct comedi_device *dev)
 		}
 
 		/* release all regions that were allocated */
-		if (devpriv->las0) {
+		if (devpriv->las0)
 			iounmap(devpriv->las0);
-		}
-		if (devpriv->las1) {
+
+		if (devpriv->las1)
 			iounmap(devpriv->las1);
-		}
-		if (devpriv->lcfg) {
+
+		if (devpriv->lcfg)
 			iounmap(devpriv->lcfg);
-		}
+
 		if (devpriv->pci_dev) {
-			if (devpriv->got_regions) {
+			if (devpriv->got_regions)
 				comedi_pci_disable(devpriv->pci_dev);
-			}
+
 			pci_dev_put(devpriv->pci_dev);
 		}
 	}
 
-	printk("comedi%d: rtd520: removed.\n", dev->minor);
+	printk(KERN_INFO "comedi%d: rtd520: removed.\n", dev->minor);
 
 	return 0;
 }
@@ -1275,13 +1275,13 @@ static int rtd520_probe_fifo_depth(struct comedi_device *dev)
 		}
 	}
 	if (i == limit) {
-		printk("\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
+		printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
 		return -EIO;
 	}
 	RtdAdcClearFifo(dev);
 	if (fifo_size != 0x400 && fifo_size != 0x2000) {
 		printk
-		    ("\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
+		    (KERN_INFO "\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
 		     DRV_NAME, fifo_size);
 		return -EIO;
 	}
@@ -1335,11 +1335,10 @@ static int rtd_ai_rinsn(struct comedi_device *dev,
 		d = RtdAdcFifoGet(dev);	/* get 2s comp value */
 		/*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->chanBipolar, 0))
 			data[n] = d + 2048;	/* convert to comedi unsigned data */
-		} else {
+		else
 			data[n] = d;
-		}
 	}
 
 	/* return the number of samples read/written */
@@ -1375,11 +1374,11 @@ static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
 		d = RtdAdcFifoGet(dev);	/* get 2s comp value */
 
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan))
 			sample = d + 2048;	/* convert to comedi unsigned data */
-		} else {
+		else
 			sample = d;
-		}
+
 		if (!comedi_buf_put(s->async, sample))
 			return -1;
 
@@ -1403,11 +1402,11 @@ static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
 		}
 
 		d = d >> 3;	/* low 3 bits are marker lines */
-		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
+		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan))
 			sample = d + 2048;	/* convert to comedi unsigned data */
-		} else {
+		else
 			sample = d;
-		}
+
 		if (!comedi_buf_put(s->async, sample))
 			return -1;
 
@@ -1493,9 +1492,9 @@ static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 
 		if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
 			sample = (*dp >> 3) + 2048;	/* convert to comedi unsigned data */
-		} else {
+		else
 			sample = *dp >> 3;	/* low 3 bits are marker lines */
-		}
+
 		*dp++ = sample;	/* put processed value back */
 
 		if (++s->async->cur_chan >= s->async->cmd.chanlist_len)
@@ -1546,9 +1545,8 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
 	u16 fifoStatus;
 	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog in subdevice */
 
-	if (!dev->attached) {
+	if (!dev->attached)
 		return IRQ_NONE;
-	}
 
 	devpriv->intCount++;	/* DEBUG statistics */
 
@@ -1594,9 +1592,8 @@ static irqreturn_t rtd_interrupt(int irq,	/* interrupt number (ignored) */
 
 	status = RtdInterruptStatus(dev);
 	/* if interrupt was not caused by our board, or handled above */
-	if (0 == status) {
+	if (0 == status)
 		return IRQ_HANDLED;
-	}
 
 	if (status & IRQM_ADC_ABOUT_CNT) {	/* sample count -> read FIFO */
 		/* since the priority interrupt controller may have queued a sample
@@ -1734,33 +1731,32 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 
 	tmp = cmd->start_src;
 	cmd->start_src &= TRIG_NOW;
-	if (!cmd->start_src || tmp != cmd->start_src) {
+	if (!cmd->start_src || tmp != cmd->start_src)
 		err++;
-	}
 
 	tmp = cmd->scan_begin_src;
 	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
-	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) {
+	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
 		err++;
-	}
+
 
 	tmp = cmd->convert_src;
 	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
-	if (!cmd->convert_src || tmp != cmd->convert_src) {
+	if (!cmd->convert_src || tmp != cmd->convert_src)
 		err++;
-	}
+
 
 	tmp = cmd->scan_end_src;
 	cmd->scan_end_src &= TRIG_COUNT;
-	if (!cmd->scan_end_src || tmp != cmd->scan_end_src) {
+	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
 		err++;
-	}
+
 
 	tmp = cmd->stop_src;
 	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
-	if (!cmd->stop_src || tmp != cmd->stop_src) {
+	if (!cmd->stop_src || tmp != cmd->stop_src)
 		err++;
-	}
+
 
 	if (err)
 		return 1;
@@ -1772,16 +1768,14 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 	    cmd->scan_begin_src != TRIG_EXT) {
 		err++;
 	}
-	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) {
+	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
 		err++;
-	}
-	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) {
+
+	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
 		err++;
-	}
 
-	if (err) {
+	if (err)
 		return 2;
-	}
 
 	/* step 3: make sure arguments are trivially compatible */
 
@@ -1882,9 +1876,9 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 		}
 	}
 
-	if (err) {
+	if (err)
 		return 3;
-	}
+
 
 	/* step 4: fix up any arguments */
 
@@ -1896,17 +1890,17 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 		tmp = cmd->scan_begin_arg;
 		rtd_ns_to_timer(&cmd->scan_begin_arg,
 				cmd->flags & TRIG_ROUND_MASK);
-		if (tmp != cmd->scan_begin_arg) {
+		if (tmp != cmd->scan_begin_arg)
 			err++;
-		}
+
 	}
 	if (cmd->convert_src == TRIG_TIMER) {
 		tmp = cmd->convert_arg;
 		rtd_ns_to_timer(&cmd->convert_arg,
 				cmd->flags & TRIG_ROUND_MASK);
-		if (tmp != cmd->convert_arg) {
+		if (tmp != cmd->convert_arg)
 			err++;
-		}
+
 		if (cmd->scan_begin_src == TRIG_TIMER
 		    && (cmd->scan_begin_arg
 			< (cmd->convert_arg * cmd->scan_end_arg))) {
@@ -1916,9 +1910,8 @@ static int rtd_ai_cmdtest(struct comedi_device *dev,
 		}
 	}
 
-	if (err) {
+	if (err)
 		return 4;
-	}
 
 	return 0;
 }
@@ -2221,7 +2214,7 @@ static int rtd_ao_winsn(struct comedi_device *dev,
 		/* VERIFY: comedi range and offset conversions */
 
 		if ((range > 1)	/* bipolar */
-		    &&(data[i] < 2048)) {
+		    && (data[i] < 2048)) {
 			/* offset and sign extend */
 			val = (((int)data[i]) - 2048) << 3;
 		} else {	/* unipolor */
@@ -2267,9 +2260,9 @@ static int rtd_ao_rinsn(struct comedi_device *dev,
 	int i;
 	int chan = CR_CHAN(insn->chanspec);
 
-	for (i = 0; i < insn->n; i++) {
+	for (i = 0; i < insn->n; i++)
 		data[i] = devpriv->aoValue[chan];
-	}
+
 
 	return i;
 }
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index c9be9e0..ebfce33 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -907,12 +907,8 @@ static int serial2002_detach(struct comedi_device *dev)
 	printk("comedi%d: serial2002: remove\n", dev->minor);
 	for (i = 0; i < 5; i++) {
 		s = &dev->subdevices[i];
-		if (s->maxdata_list) {
-			kfree(s->maxdata_list);
-		}
-		if (s->range_table_list) {
-			kfree(s->range_table_list);
-		}
+		kfree(s->maxdata_list);
+		kfree(s->range_table_list);
 	}
 	return 0;
 }
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 696ee04..be93c30 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -2265,12 +2265,8 @@ static void tidy_up(struct usbduxsub *usbduxsub_tmp)
 			usbduxsub_unlink_OutURBs(usbduxsub_tmp);
 		}
 		for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) {
-			if (usbduxsub_tmp->urbOut[i]->transfer_buffer) {
-				kfree(usbduxsub_tmp->
-				      urbOut[i]->transfer_buffer);
-				usbduxsub_tmp->urbOut[i]->transfer_buffer =
-				    NULL;
-			}
+			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]);
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
index 153ddbf..13a514d 100644
--- a/drivers/staging/crystalhd/crystalhd_hw.c
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
@@ -1965,6 +1965,7 @@ enum BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *hw)
 		} else {
 			BCMLOG_ERR("Insufficient Memory For RX\n");
 			crystalhd_hw_free_dma_rings(hw);
+			kfree(rpkt);
 			return BC_STS_INSUFF_RES;
 		}
 		rpkt->desc_mem.pdma_desc_start = mem;
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
index 719e70b..7e0c199 100644
--- a/drivers/staging/crystalhd/crystalhd_lnx.c
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -393,8 +393,7 @@ static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
 
 	/* Allocate general purpose ioctl pool. */
 	for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
-		/* FIXME: jarod: why atomic? */
-		temp = kzalloc(sizeof(struct crystalhd_ioctl_data), GFP_ATOMIC);
+		temp = kzalloc(sizeof(struct crystalhd_ioctl_data), GFP_KERNEL);
 		if (!temp) {
 			BCMLOG_ERR("ioctl data pool kzalloc failed\n");
 			rc = -ENOMEM;
@@ -549,8 +548,7 @@ static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
 	       pdev->vendor, pdev->device, pdev->subsystem_vendor,
 	       pdev->subsystem_device);
 
-	/* FIXME: jarod: why atomic? */
-	pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC);
+	pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_KERNEL);
 	if (!pinfo) {
 		BCMLOG_ERR("Failed to allocate memory\n");
 		return -ENOMEM;
@@ -561,10 +559,10 @@ static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
 	rc = pci_enable_device(pdev);
 	if (rc) {
 		BCMLOG_ERR("Failed to enable PCI device\n");
-		return rc;
+		goto err;
 	}
 
-	snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d",
+	snprintf(pinfo->name, sizeof(pinfo->name), "crystalhd_pci_e:%d:%d:%d",
 		 pdev->bus->number, PCI_SLOT(pdev->devfn),
 		 PCI_FUNC(pdev->devfn));
 
@@ -572,7 +570,8 @@ static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
 	if (rc) {
 		BCMLOG_ERR("Failed to setup memory regions.\n");
 		pci_disable_device(pdev);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto err;
 	}
 
 	pinfo->present	= 1;
@@ -587,7 +586,8 @@ static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
 	if (rc) {
 		BCMLOG_ERR("_enable_int err:%d\n", rc);
 		pci_disable_device(pdev);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err;
 	}
 
 	/* Set dma mask... */
@@ -600,14 +600,16 @@ static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
 	} else {
 		BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
 		pci_disable_device(pdev);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err;
 	}
 
 	sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
 	if (sts != BC_STS_SUCCESS) {
 		BCMLOG_ERR("cmd setup :%d\n", sts);
 		pci_disable_device(pdev);
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err;
 	}
 
 	pci_set_master(pdev);
@@ -617,6 +619,10 @@ static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
 	g_adp_info = pinfo;
 
 	return 0;
+
+err:
+	kfree(pinfo);
+	return rc;
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/staging/cs5535_gpio/cs5535_gpio.c b/drivers/staging/cs5535_gpio/cs5535_gpio.c
index 0cf1e5f..b25f9d1 100644
--- a/drivers/staging/cs5535_gpio/cs5535_gpio.c
+++ b/drivers/staging/cs5535_gpio/cs5535_gpio.c
@@ -146,7 +146,8 @@ static ssize_t cs5535_gpio_read(struct file *file, char __user *buf,
 
 	/* add a line-feed if there is room */
 	if ((i == ARRAY_SIZE(rm)) && (count < len)) {
-		put_user('\n', buf + count);
+		if (put_user('\n', buf + count))
+			return -EFAULT;
 		count++;
 	}
 
diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c
index 7992a3b..0f9ca77 100644
--- a/drivers/staging/cx25821/cx25821-audio-upstream.c
+++ b/drivers/staging/cx25821/cx25821-audio-upstream.c
@@ -244,13 +244,10 @@ void cx25821_stop_upstream_audio(struct cx25821_dev *dev)
 	dev->_audioframe_count = 0;
 	dev->_audiofile_status = END_OF_FILE;
 
-	if (dev->_irq_audio_queues) {
-		kfree(dev->_irq_audio_queues);
-		dev->_irq_audio_queues = NULL;
-	}
+	kfree(dev->_irq_audio_queues);
+	dev->_irq_audio_queues = NULL;
 
-	if (dev->_audiofilename != NULL)
-		kfree(dev->_audiofilename);
+	kfree(dev->_audiofilename);
 }
 
 void cx25821_free_mem_upstream_audio(struct cx25821_dev *dev)
diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
index e2efacd..655357d 100644
--- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
+++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c
@@ -234,13 +234,10 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev)
 	dev->_frame_count_ch2 = 0;
 	dev->_file_status_ch2 = END_OF_FILE;
 
-	if (dev->_irq_queues_ch2) {
-		kfree(dev->_irq_queues_ch2);
-		dev->_irq_queues_ch2 = NULL;
-	}
+	kfree(dev->_irq_queues_ch2);
+	dev->_irq_queues_ch2 = NULL;
 
-	if (dev->_filename_ch2 != NULL)
-		kfree(dev->_filename_ch2);
+	kfree(dev->_filename_ch2);
 
 	tmp = cx_read(VID_CH_MODE_SEL);
 	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c
index 31b4e3c..eb0172b 100644
--- a/drivers/staging/cx25821/cx25821-video-upstream.c
+++ b/drivers/staging/cx25821/cx25821-video-upstream.c
@@ -279,13 +279,10 @@ void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev)
 	dev->_frame_count = 0;
 	dev->_file_status = END_OF_FILE;
 
-	if (dev->_irq_queues) {
-		kfree(dev->_irq_queues);
-		dev->_irq_queues = NULL;
-	}
+	kfree(dev->_irq_queues);
+	dev->_irq_queues = NULL;
 
-	if (dev->_filename != NULL)
-		kfree(dev->_filename);
+	kfree(dev->_filename);
 
 	tmp = cx_read(VID_CH_MODE_SEL);
 	cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00);
diff --git a/drivers/staging/cxt1e1/hwprobe.c b/drivers/staging/cxt1e1/hwprobe.c
index c517cc2..de8ac0b 100644
--- a/drivers/staging/cxt1e1/hwprobe.c
+++ b/drivers/staging/cxt1e1/hwprobe.c
@@ -317,7 +317,7 @@ c4hw_attach_all (void)
         pr_warning("No boards found\n");
         return ENODEV;
     }
-    /* sanity check for consistant hardware found */
+    /* sanity check for consistent hardware found */
     for (i = 0, hi = hdw_info; i < MAX_BOARDS; i++, hi++)
     {
         if (hi->pci_slot != 0xff && (!hi->addr[0] || !hi->addr[1]))
diff --git a/drivers/staging/cxt1e1/linux.c b/drivers/staging/cxt1e1/linux.c
index 0f78f89..9ced08f 100644
--- a/drivers/staging/cxt1e1/linux.c
+++ b/drivers/staging/cxt1e1/linux.c
@@ -548,7 +548,7 @@ do_set_port (struct net_device * ndev, void *data)
         return -EINVAL;             /* get card info */
 
     if (pp.portnum >= ci->max_port) /* sanity check */
-        return ENXIO;
+        return -ENXIO;
 
     memcpy (&ci->port[pp.portnum].p, &pp, sizeof (struct sbecom_port_param));
     return mkret (c4_set_port (ci, pp.portnum));
diff --git a/drivers/staging/cxt1e1/pmcc4.h b/drivers/staging/cxt1e1/pmcc4.h
index ef6ac7f..e046b87 100644
--- a/drivers/staging/cxt1e1/pmcc4.h
+++ b/drivers/staging/cxt1e1/pmcc4.h
@@ -31,7 +31,7 @@
  * $Log: pmcc4.h,v $
  * Revision 1.4  2005/11/01 19:24:48  rickd
  * Remove de-implement function prototypes.  Several <int> to
- * <status_t> changes for consistant usage of same.
+ * <status_t> changes for consistent usage of same.
  *
  * Revision 1.3  2005/09/28 00:10:08  rickd
  * Add GNU license info. Use config params from libsbew.h
diff --git a/drivers/staging/cxt1e1/pmcc4_drv.c b/drivers/staging/cxt1e1/pmcc4_drv.c
index 341e7a9..e1f07fa 100644
--- a/drivers/staging/cxt1e1/pmcc4_drv.c
+++ b/drivers/staging/cxt1e1/pmcc4_drv.c
@@ -44,7 +44,7 @@
  * Code cleanup.  Default channel config to HDLC_FCS16.
  *
  * Revision 2.7  2005/10/18 18:16:30  rickd
- * Further NCOMM code repairs - (1) interrupt matrix usage inconsistant
+ * Further NCOMM code repairs - (1) interrupt matrix usage inconsistent
  * for indexing into nciInterrupt[][], code missing double parameters.
  * (2) check input of ncomm interrupt registration cardID for correct
  * boundary values.
diff --git a/drivers/staging/dabusb/dabusb.c b/drivers/staging/dabusb/dabusb.c
index f3e25e9..21768a6 100644
--- a/drivers/staging/dabusb/dabusb.c
+++ b/drivers/staging/dabusb/dabusb.c
@@ -33,8 +33,8 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
 #include <linux/delay.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
@@ -66,28 +66,29 @@ static struct usb_driver dabusb_driver;
 
 /*-------------------------------------------------------------------*/
 
-static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src)
+static int dabusb_add_buf_tail(pdabusb_t s, struct list_head *dst,
+			       struct list_head *src)
 {
 	unsigned long flags;
 	struct list_head *tmp;
 	int ret = 0;
 
-	spin_lock_irqsave (&s->lock, flags);
+	spin_lock_irqsave(&s->lock, flags);
 
-	if (list_empty (src)) {
-		// no elements in source buffer
+	if (list_empty(src)) {
+		/* no elements in source buffer */
 		ret = -1;
 		goto err;
 	}
 	tmp = src->next;
-	list_move_tail (tmp, dst);
+	list_move_tail(tmp, dst);
 
-  err:	spin_unlock_irqrestore (&s->lock, flags);
+err:	spin_unlock_irqrestore(&s->lock, flags);
 	return ret;
 }
 /*-------------------------------------------------------------------*/
 #ifdef DEBUG
-static void dump_urb (struct urb *urb)
+static void dump_urb(struct urb *urb)
 {
 	dbg("urb                   :%p", urb);
 	dbg("dev                   :%p", urb->dev);
@@ -107,26 +108,26 @@ static void dump_urb (struct urb *urb)
 }
 #endif
 /*-------------------------------------------------------------------*/
-static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q)
+static int dabusb_cancel_queue(pdabusb_t s, struct list_head *q)
 {
 	unsigned long flags;
 	pbuff_t b;
 
 	dbg("dabusb_cancel_queue");
 
-	spin_lock_irqsave (&s->lock, flags);
+	spin_lock_irqsave(&s->lock, flags);
 
 	list_for_each_entry(b, q, buff_list) {
 #ifdef DEBUG
 		dump_urb(b->purb);
 #endif
-		usb_unlink_urb (b->purb);
+		usb_unlink_urb(b->purb);
 	}
-	spin_unlock_irqrestore (&s->lock, flags);
+	spin_unlock_irqrestore(&s->lock, flags);
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-static int dabusb_free_queue (struct list_head *q)
+static int dabusb_free_queue(struct list_head *q)
 {
 	struct list_head *tmp;
 	struct list_head *p;
@@ -134,7 +135,7 @@ static int dabusb_free_queue (struct list_head *q)
 
 	dbg("dabusb_free_queue");
 	for (p = q->next; p != q;) {
-		b = list_entry (p, buff_t, buff_list);
+		b = list_entry(p, buff_t, buff_list);
 
 #ifdef DEBUG
 		dump_urb(b->purb);
@@ -142,23 +143,23 @@ static int dabusb_free_queue (struct list_head *q)
 		kfree(b->purb->transfer_buffer);
 		usb_free_urb(b->purb);
 		tmp = p->next;
-		list_del (p);
-		kfree (b);
+		list_del(p);
+		kfree(b);
 		p = tmp;
 	}
 
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-static int dabusb_free_buffers (pdabusb_t s)
+static int dabusb_free_buffers(pdabusb_t s)
 {
 	unsigned long flags;
 	dbg("dabusb_free_buffers");
 
 	spin_lock_irqsave(&s->lock, flags);
 
-	dabusb_free_queue (&s->free_buff_list);
-	dabusb_free_queue (&s->rec_buff_list);
+	dabusb_free_queue(&s->free_buff_list);
+	dabusb_free_queue(&s->rec_buff_list);
 
 	spin_unlock_irqrestore(&s->lock, flags);
 
@@ -166,7 +167,7 @@ static int dabusb_free_buffers (pdabusb_t s)
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-static void dabusb_iso_complete (struct urb *purb)
+static void dabusb_iso_complete(struct urb *purb)
 {
 	pbuff_t b = purb->context;
 	pdabusb_t s = b->s;
@@ -177,42 +178,45 @@ static void dabusb_iso_complete (struct urb *purb)
 
 	dbg("dabusb_iso_complete");
 
-	// process if URB was not killed
+	/* process if URB was not killed */
 	if (purb->status != -ENOENT) {
-		unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
-		int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe));
+		unsigned int pipe = usb_rcvisocpipe(purb->dev, _DABUSB_ISOPIPE);
+		int pipesize = usb_maxpacket(purb->dev, pipe,
+					     usb_pipeout(pipe));
 		for (i = 0; i < purb->number_of_packets; i++)
 			if (!purb->iso_frame_desc[i].status) {
 				len = purb->iso_frame_desc[i].actual_length;
 				if (len <= pipesize) {
-					memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len);
+					memcpy(buf + dst, buf + purb->iso_frame_desc[i].offset, len);
 					dst += len;
-				}
-				else
+				} else
 					dev_err(&purb->dev->dev,
-						"dabusb_iso_complete: invalid len %d\n", len);
-			}
-			else
-				dev_warn(&purb->dev->dev, "dabusb_iso_complete: corrupted packet status: %d\n", purb->iso_frame_desc[i].status);
+						"dabusb_iso_complete: invalid len %d\n",
+						len);
+			} else
+				dev_warn(&purb->dev->dev,
+					 "dabusb_iso_complete: corrupted packet status: %d\n",
+					 purb->iso_frame_desc[i].status);
 		if (dst != purb->actual_length)
 			dev_err(&purb->dev->dev,
 				"dst!=purb->actual_length:%d!=%d\n",
 					dst, purb->actual_length);
 	}
 
-	if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
+	if (atomic_dec_and_test(&s->pending_io) &&
+	    !s->remove_pending && s->state != _stopped) {
 		s->overruns++;
 		dev_err(&purb->dev->dev, "overrun (%d)\n", s->overruns);
 	}
-	wake_up (&s->wait);
+	wake_up(&s->wait);
 }
 /*-------------------------------------------------------------------*/
-static int dabusb_alloc_buffers (pdabusb_t s)
+static int dabusb_alloc_buffers(pdabusb_t s)
 {
 	int transfer_len = 0;
 	pbuff_t b;
-	unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE);
-	int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe));
+	unsigned int pipe = usb_rcvisocpipe(s->usbdev, _DABUSB_ISOPIPE);
+	int pipesize = usb_maxpacket(s->usbdev, pipe, usb_pipeout(pipe));
 	int packets = _ISOPIPESIZE / pipesize;
 	int transfer_buffer_length = packets * pipesize;
 	int i;
@@ -221,7 +225,7 @@ static int dabusb_alloc_buffers (pdabusb_t s)
 		 pipesize, packets, transfer_buffer_length);
 
 	while (transfer_len < (s->total_buffer_size << 10)) {
-		b = kzalloc(sizeof (buff_t), GFP_KERNEL);
+		b = kzalloc(sizeof(buff_t), GFP_KERNEL);
 		if (!b) {
 			dev_err(&s->usbdev->dev,
 				"kzalloc(sizeof(buff_t))==NULL\n");
@@ -231,14 +235,15 @@ static int dabusb_alloc_buffers (pdabusb_t s)
 		b->purb = usb_alloc_urb(packets, GFP_KERNEL);
 		if (!b->purb) {
 			dev_err(&s->usbdev->dev, "usb_alloc_urb == NULL\n");
-			kfree (b);
+			kfree(b);
 			goto err;
 		}
 
-		b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL);
+		b->purb->transfer_buffer = kmalloc(transfer_buffer_length,
+						   GFP_KERNEL);
 		if (!b->purb->transfer_buffer) {
-			kfree (b->purb);
-			kfree (b);
+			kfree(b->purb);
+			kfree(b);
 			dev_err(&s->usbdev->dev,
 				"kmalloc(%d)==NULL\n", transfer_buffer_length);
 			goto err;
@@ -258,18 +263,18 @@ static int dabusb_alloc_buffers (pdabusb_t s)
 		}
 
 		transfer_len += transfer_buffer_length;
-		list_add_tail (&b->buff_list, &s->free_buff_list);
+		list_add_tail(&b->buff_list, &s->free_buff_list);
 	}
 	s->got_mem = transfer_len;
 
 	return 0;
 
-	err:
-	dabusb_free_buffers (s);
+err:
+	dabusb_free_buffers(s);
 	return -ENOMEM;
 }
 /*-------------------------------------------------------------------*/
-static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
+static int dabusb_bulk(pdabusb_t s, pbulk_transfer_t pb)
 {
 	int ret;
 	unsigned int pipe;
@@ -278,25 +283,26 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
 	dbg("dabusb_bulk");
 
 	if (!pb->pipe)
-		pipe = usb_rcvbulkpipe (s->usbdev, 2);
+		pipe = usb_rcvbulkpipe(s->usbdev, 2);
 	else
-		pipe = usb_sndbulkpipe (s->usbdev, 2);
+		pipe = usb_sndbulkpipe(s->usbdev, 2);
 
-	ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100);
-	if(ret<0) {
+	ret = usb_bulk_msg(s->usbdev, pipe, pb->data,
+			   pb->size, &actual_length, 100);
+	if (ret < 0) {
 		dev_err(&s->usbdev->dev,
 			"usb_bulk_msg failed(%d)\n", ret);
 
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
+		if (usb_set_interface(s->usbdev, _DABUSB_IF, 1) < 0) {
 			dev_err(&s->usbdev->dev, "set_interface failed\n");
 			return -EINVAL;
 		}
 
 	}
 
-	if( ret == -EPIPE ) {
+	if (ret == -EPIPE) {
 		dev_warn(&s->usbdev->dev, "CLEAR_FEATURE request to remove STALL condition.\n");
-		if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
+		if (usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe)))
 			dev_err(&s->usbdev->dev, "request failed\n");
 	}
 
@@ -304,11 +310,11 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
 	return ret;
 }
 /* --------------------------------------------------------------------- */
-static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data,
+static int dabusb_writemem(pdabusb_t s, int pos, const unsigned char *data,
 			    int len)
 {
 	int ret;
-	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
+	unsigned char *transfer_buffer =  kmalloc(len, GFP_KERNEL);
 
 	if (!transfer_buffer) {
 		dev_err(&s->usbdev->dev,
@@ -316,21 +322,22 @@ static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data,
 		return -ENOMEM;
 	}
 
-	memcpy (transfer_buffer, data, len);
+	memcpy(transfer_buffer, data, len);
 
-	ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
+	ret = usb_control_msg(s->usbdev, usb_sndctrlpipe(s->usbdev, 0),
+			      0xa0, 0x40, pos, 0, transfer_buffer, len, 300);
 
-	kfree (transfer_buffer);
+	kfree(transfer_buffer);
 	return ret;
 }
 /* --------------------------------------------------------------------- */
-static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
+static int dabusb_8051_reset(pdabusb_t s, unsigned char reset_bit)
 {
-	dbg("dabusb_8051_reset: %d",reset_bit);
-	return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
+	dbg("dabusb_8051_reset: %d", reset_bit);
+	return dabusb_writemem(s, CPUCS_REG, &reset_bit, 1);
 }
 /* --------------------------------------------------------------------- */
-static int dabusb_loadmem (pdabusb_t s, const char *fname)
+static int dabusb_loadmem(pdabusb_t s, const char *fname)
 {
 	int ret;
 	const struct ihex_binrec *rec;
@@ -344,7 +351,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname)
 			"Failed to load \"dabusb/firmware.fw\": %d\n", ret);
 		goto out;
 	}
-	ret = dabusb_8051_reset (s, 1);
+	ret = dabusb_8051_reset(s, 1);
 
 	for (rec = (const struct ihex_binrec *)fw->data; rec;
 	     rec = ihex_next_binrec(rec)) {
@@ -361,7 +368,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname)
 			break;
 		}
 	}
-	ret = dabusb_8051_reset (s, 0);
+	ret = dabusb_8051_reset(s, 0);
 	release_firmware(fw);
  out:
 	dbg("dabusb_loadmem: exit");
@@ -369,7 +376,7 @@ static int dabusb_loadmem (pdabusb_t s, const char *fname)
 	return ret;
 }
 /* --------------------------------------------------------------------- */
-static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b)
+static int dabusb_fpga_clear(pdabusb_t s, pbulk_transfer_t b)
 {
 	b->size = 4;
 	b->data[0] = 0x2a;
@@ -379,10 +386,10 @@ static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b)
 
 	dbg("dabusb_fpga_clear");
 
-	return dabusb_bulk (s, b);
+	return dabusb_bulk(s, b);
 }
 /* --------------------------------------------------------------------- */
-static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
+static int dabusb_fpga_init(pdabusb_t s, pbulk_transfer_t b)
 {
 	b->size = 4;
 	b->data[0] = 0x2c;
@@ -392,12 +399,12 @@ static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
 
 	dbg("dabusb_fpga_init");
 
-	return dabusb_bulk (s, b);
+	return dabusb_bulk(s, b);
 }
 /* --------------------------------------------------------------------- */
-static int dabusb_fpga_download (pdabusb_t s, const char *fname)
+static int dabusb_fpga_download(pdabusb_t s, const char *fname)
 {
-	pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
+	pbulk_transfer_t b = kmalloc(sizeof(bulk_transfer_t), GFP_KERNEL);
 	const struct firmware *fw;
 	unsigned int blen, n;
 	int ret;
@@ -419,8 +426,8 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
 	}
 
 	b->pipe = 1;
-	ret = dabusb_fpga_clear (s, b);
-	mdelay (10);
+	ret = dabusb_fpga_clear(s, b);
+	mdelay(10);
 	blen = fw->data[73] + (fw->data[72] << 8);
 
 	dbg("Bitstream len: %i", blen);
@@ -431,19 +438,19 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
 	b->data[3] = 60;
 
 	for (n = 0; n <= blen + 60; n += 60) {
-		// some cclks for startup
+		/* some cclks for startup */
 		b->size = 64;
-		memcpy (b->data + 4, fw->data + 74 + n, 60);
-		ret = dabusb_bulk (s, b);
+		memcpy(b->data + 4, fw->data + 74 + n, 60);
+		ret = dabusb_bulk(s, b);
 		if (ret < 0) {
 			dev_err(&s->usbdev->dev, "dabusb_bulk failed.\n");
 			break;
 		}
-		mdelay (1);
+		mdelay(1);
 	}
 
-	ret = dabusb_fpga_init (s, b);
-	kfree (b);
+	ret = dabusb_fpga_init(s, b);
+	kfree(b);
 	release_firmware(fw);
 
 	dbg("exit dabusb_fpga_download");
@@ -451,12 +458,12 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
 	return ret;
 }
 
-static int dabusb_stop (pdabusb_t s)
+static int dabusb_stop(pdabusb_t s)
 {
 	dbg("dabusb_stop");
 
 	s->state = _stopped;
-	dabusb_cancel_queue (s, &s->rec_buff_list);
+	dabusb_cancel_queue(s, &s->rec_buff_list);
 
 	dbg("pending_io: %d", s->pending_io.counter);
 
@@ -464,50 +471,53 @@ static int dabusb_stop (pdabusb_t s)
 	return 0;
 }
 
-static int dabusb_startrek (pdabusb_t s)
+static int dabusb_startrek(pdabusb_t s)
 {
 	if (!s->got_mem && s->state != _started) {
 
 		dbg("dabusb_startrek");
 
-		if (dabusb_alloc_buffers (s) < 0)
+		if (dabusb_alloc_buffers(s) < 0)
 			return -ENOMEM;
-		dabusb_stop (s);
+		dabusb_stop(s);
 		s->state = _started;
 		s->readptr = 0;
 	}
 
-	if (!list_empty (&s->free_buff_list)) {
+	if (!list_empty(&s->free_buff_list)) {
 		pbuff_t end;
 		int ret;
 
-	while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
+	while (!dabusb_add_buf_tail(s, &s->rec_buff_list, &s->free_buff_list)) {
 
-			dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
+			dbg("submitting: end:%p s->rec_buff_list:%p",
+			    s->rec_buff_list.prev, &s->rec_buff_list);
 
-			end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
+			end = list_entry(s->rec_buff_list.prev,
+					 buff_t, buff_list);
 
-			ret = usb_submit_urb (end->purb, GFP_KERNEL);
+			ret = usb_submit_urb(end->purb, GFP_KERNEL);
 			if (ret) {
 				dev_err(&s->usbdev->dev,
 					"usb_submit_urb returned:%d\n", ret);
-				if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
+				if (dabusb_add_buf_tail(s, &s->free_buff_list,
+							&s->rec_buff_list))
 					dev_err(&s->usbdev->dev,
 						"startrek: dabusb_add_buf_tail failed\n");
 				break;
-			}
-			else
-				atomic_inc (&s->pending_io);
+			} else
+				atomic_inc(&s->pending_io);
 		}
-		dbg("pending_io: %d",s->pending_io.counter);
+		dbg("pending_io: %d", s->pending_io.counter);
 	}
 
 	return 0;
 }
 
-static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos)
+static ssize_t dabusb_read(struct file *file, char __user *buf,
+			   size_t count, loff_t *ppos)
 {
-	pdabusb_t s = (pdabusb_t) file->private_data;
+	pdabusb_t s = (pdabusb_t)file->private_data;
 	unsigned long flags;
 	unsigned ret = 0;
 	int rem;
@@ -528,11 +538,11 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l
 		return -EIO;
 
 	while (count > 0) {
-		dabusb_startrek (s);
+		dabusb_startrek(s);
 
-		spin_lock_irqsave (&s->lock, flags);
+		spin_lock_irqsave(&s->lock, flags);
 
-		if (list_empty (&s->rec_buff_list)) {
+		if (list_empty(&s->rec_buff_list)) {
 
 			spin_unlock_irqrestore(&s->lock, flags);
 
@@ -541,30 +551,30 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l
 			goto err;
 		}
 
-		b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
+		b = list_entry(s->rec_buff_list.next, buff_t, buff_list);
 		purb = b->purb;
 
 		spin_unlock_irqrestore(&s->lock, flags);
 
 		if (purb->status == -EINPROGRESS) {
-			if (file->f_flags & O_NONBLOCK)		// return nonblocking
-			 {
+			/* return nonblocking */
+			if (file->f_flags & O_NONBLOCK) {
 				if (!ret)
 					ret = -EAGAIN;
 				goto err;
 			}
 
-			interruptible_sleep_on (&s->wait);
+			interruptible_sleep_on(&s->wait);
 
-			if (signal_pending (current)) {
+			if (signal_pending(current)) {
 				if (!ret)
 					ret = -ERESTARTSYS;
 				goto err;
 			}
 
-			spin_lock_irqsave (&s->lock, flags);
+			spin_lock_irqsave(&s->lock, flags);
 
-			if (list_empty (&s->rec_buff_list)) {
+			if (list_empty(&s->rec_buff_list)) {
 				spin_unlock_irqrestore(&s->lock, flags);
 				dev_err(&s->usbdev->dev,
 					"error: still no buffer available.\n");
@@ -578,16 +588,20 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l
 			goto err;
 		}
 
-		rem = purb->actual_length - s->readptr;		// set remaining bytes to copy
+		/* set remaining bytes to copy */
+		rem = purb->actual_length - s->readptr;
 
 		if (count >= rem)
 			cnt = rem;
 		else
 			cnt = count;
 
-		dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
+		dbg("copy_to_user:%p %p %d", buf,
+		    purb->transfer_buffer + s->readptr, cnt);
 
-		if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
+		if (copy_to_user(buf,
+				purb->transfer_buffer + s->readptr,
+				cnt)) {
 			dev_err(&s->usbdev->dev, "read: copy_to_user failed\n");
 			if (!ret)
 				ret = -EFAULT;
@@ -600,18 +614,19 @@ static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, l
 		ret += cnt;
 
 		if (s->readptr == purb->actual_length) {
-			// finished, take next buffer
-			if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
+			/* finished, take next buffer */
+			if (dabusb_add_buf_tail(s, &s->free_buff_list,
+						&s->rec_buff_list))
 				dev_err(&s->usbdev->dev,
 					"read: dabusb_add_buf_tail failed\n");
 			s->readptr = 0;
 		}
 	}
-      err:			//mutex_unlock(&s->mutex);
+err:			/*mutex_unlock(&s->mutex);*/
 	return ret;
 }
 
-static int dabusb_open (struct inode *inode, struct file *file)
+static int dabusb_open(struct inode *inode, struct file *file)
 {
 	int devnum = iminor(inode);
 	pdabusb_t s;
@@ -632,11 +647,11 @@ static int dabusb_open (struct inode *inode, struct file *file)
 			return -EBUSY;
 		msleep_interruptible(500);
 
-		if (signal_pending (current))
+		if (signal_pending(current))
 			return -EAGAIN;
 		mutex_lock(&s->mutex);
 	}
-	if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
+	if (usb_set_interface(s->usbdev, _DABUSB_IF, 1) < 0) {
 		mutex_unlock(&s->mutex);
 		dev_err(&s->usbdev->dev, "set_interface failed\n");
 		return -EINVAL;
@@ -651,31 +666,30 @@ static int dabusb_open (struct inode *inode, struct file *file)
 	return r;
 }
 
-static int dabusb_release (struct inode *inode, struct file *file)
+static int dabusb_release(struct inode *inode, struct file *file)
 {
-	pdabusb_t s = (pdabusb_t) file->private_data;
+	pdabusb_t s = (pdabusb_t)file->private_data;
 
 	dbg("dabusb_release");
 
 	mutex_lock(&s->mutex);
-	dabusb_stop (s);
-	dabusb_free_buffers (s);
+	dabusb_stop(s);
+	dabusb_free_buffers(s);
 	mutex_unlock(&s->mutex);
 
 	if (!s->remove_pending) {
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
+		if (usb_set_interface(s->usbdev, _DABUSB_IF, 0) < 0)
 			dev_err(&s->usbdev->dev, "set_interface failed\n");
-	}
-	else
-		wake_up (&s->remove_ok);
+	} else
+		wake_up(&s->remove_ok);
 
 	s->opened = 0;
 	return 0;
 }
 
-static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
+static long dabusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	pdabusb_t s = (pdabusb_t) file->private_data;
+	pdabusb_t s = (pdabusb_t)file->private_data;
 	pbulk_transfer_t pbulk;
 	int ret = 0;
 	int version = DABUSB_VERSION;
@@ -703,20 +717,20 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg
 			break;
 		}
 
-		ret=dabusb_bulk (s, pbulk);
-		if(ret==0)
+		ret = dabusb_bulk(s, pbulk);
+		if (ret == 0)
 			if (copy_to_user((void __user *)arg, pbulk,
 					 sizeof(bulk_transfer_t)))
 				ret = -EFAULT;
-		kfree (pbulk);
+		kfree(pbulk);
 		break;
 
 	case IOCTL_DAB_OVERRUNS:
-		ret = put_user (s->overruns, (unsigned int __user *) arg);
+		ret = put_user(s->overruns, (unsigned int __user *) arg);
 		break;
 
 	case IOCTL_DAB_VERSION:
-		ret = put_user (version, (unsigned int __user *) arg);
+		ret = put_user(version, (unsigned int __user *) arg);
 		break;
 
 	default:
@@ -727,8 +741,7 @@ static long dabusb_ioctl (struct file *file, unsigned int cmd, unsigned long arg
 	return ret;
 }
 
-static const struct file_operations dabusb_fops =
-{
+static const struct file_operations dabusb_fops = {
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.read =		dabusb_read,
@@ -751,7 +764,7 @@ static struct usb_class_driver dabusb_class = {
 
 
 /* --------------------------------------------------------------------- */
-static int dabusb_probe (struct usb_interface *intf,
+static int dabusb_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
 	struct usb_device *usbdev = interface_to_usbdev(intf);
@@ -780,54 +793,53 @@ static int dabusb_probe (struct usb_interface *intf,
 	s->usbdev = usbdev;
 	s->devnum = intf->minor;
 
-	if (usb_reset_configuration (usbdev) < 0) {
+	if (usb_reset_configuration(usbdev) < 0) {
 		dev_err(&intf->dev, "reset_configuration failed\n");
 		goto reject;
 	}
 	if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) {
-		dabusb_loadmem (s, NULL);
+		dabusb_loadmem(s, NULL);
 		goto reject;
-	}
-	else {
-		dabusb_fpga_download (s, NULL);
+	} else {
+		dabusb_fpga_download(s, NULL);
 
-		if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
+		if (usb_set_interface(s->usbdev, _DABUSB_IF, 0) < 0) {
 			dev_err(&intf->dev, "set_interface failed\n");
 			goto reject;
 		}
 	}
 	dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber);
-	usb_set_intfdata (intf, s);
+	usb_set_intfdata(intf, s);
 	mutex_unlock(&s->mutex);
 
 	retval = usb_register_dev(intf, &dabusb_class);
 	if (retval) {
-		usb_set_intfdata (intf, NULL);
+		usb_set_intfdata(intf, NULL);
 		return -ENOMEM;
 	}
 
 	return 0;
 
-      reject:
+reject:
 	mutex_unlock(&s->mutex);
 	s->usbdev = NULL;
 	return -ENODEV;
 }
 
-static void dabusb_disconnect (struct usb_interface *intf)
+static void dabusb_disconnect(struct usb_interface *intf)
 {
 	wait_queue_t __wait;
-	pdabusb_t s = usb_get_intfdata (intf);
+	pdabusb_t s = usb_get_intfdata(intf);
 
 	dbg("dabusb_disconnect");
 
 	init_waitqueue_entry(&__wait, current);
 
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 	if (s) {
-		usb_deregister_dev (intf, &dabusb_class);
+		usb_deregister_dev(intf, &dabusb_class);
 		s->remove_pending = 1;
-		wake_up (&s->wait);
+		wake_up(&s->wait);
 		add_wait_queue(&s->remove_ok, &__wait);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		if (s->state == _started)
@@ -840,13 +852,13 @@ static void dabusb_disconnect (struct usb_interface *intf)
 	}
 }
 
-static struct usb_device_id dabusb_ids [] = {
-	// { USB_DEVICE(0x0547, 0x2131) },	/* An2131 chip, no boot ROM */
+static struct usb_device_id dabusb_ids[] = {
+	/* { USB_DEVICE(0x0547, 0x2131) },*/	/* An2131 chip, no boot ROM */
 	{ USB_DEVICE(0x0547, 0x9999) },
 	{ }						/* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, dabusb_ids);
+MODULE_DEVICE_TABLE(usb, dabusb_ids);
 
 static struct usb_driver dabusb_driver = {
 	.name =		"dabusb",
@@ -857,7 +869,7 @@ static struct usb_driver dabusb_driver = {
 
 /* --------------------------------------------------------------------- */
 
-static int __init dabusb_init (void)
+static int __init dabusb_init(void)
 {
 	int retval;
 	unsigned u;
@@ -865,15 +877,15 @@ static int __init dabusb_init (void)
 	/* initialize struct */
 	for (u = 0; u < NRDABUSB; u++) {
 		pdabusb_t s = &dabusb[u];
-		memset (s, 0, sizeof (dabusb_t));
-		mutex_init (&s->mutex);
+		memset(s, 0, sizeof(dabusb_t));
+		mutex_init(&s->mutex);
 		s->usbdev = NULL;
 		s->total_buffer_size = buffers;
-		init_waitqueue_head (&s->wait);
-		init_waitqueue_head (&s->remove_ok);
-		spin_lock_init (&s->lock);
-		INIT_LIST_HEAD (&s->free_buff_list);
-		INIT_LIST_HEAD (&s->rec_buff_list);
+		init_waitqueue_head(&s->wait);
+		init_waitqueue_head(&s->remove_ok);
+		spin_lock_init(&s->lock);
+		INIT_LIST_HEAD(&s->free_buff_list);
+		INIT_LIST_HEAD(&s->rec_buff_list);
 	}
 
 	/* register misc device */
@@ -890,25 +902,25 @@ out:
 	return retval;
 }
 
-static void __exit dabusb_cleanup (void)
+static void __exit dabusb_cleanup(void)
 {
 	dbg("dabusb_cleanup");
 
-	usb_deregister (&dabusb_driver);
+	usb_deregister(&dabusb_driver);
 }
 
 /* --------------------------------------------------------------------- */
 
-MODULE_AUTHOR( DRIVER_AUTHOR );
-MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE("dabusb/firmware.fw");
 MODULE_FIRMWARE("dabusb/bitstream.bin");
 
 module_param(buffers, int, 0);
-MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
+MODULE_PARM_DESC(buffers, "Number of buffers (default=256)");
 
-module_init (dabusb_init);
-module_exit (dabusb_cleanup);
+module_init(dabusb_init);
+module_exit(dabusb_cleanup);
 
 /* --------------------------------------------------------------------- */
diff --git a/drivers/staging/dabusb/dabusb.h b/drivers/staging/dabusb/dabusb.h
index 00eb34c..c1772ef 100644
--- a/drivers/staging/dabusb/dabusb.h
+++ b/drivers/staging/dabusb/dabusb.h
@@ -1,10 +1,9 @@
 #define _BULK_DATA_LEN 64
-typedef struct
-{
+typedef struct {
 	unsigned char data[_BULK_DATA_LEN];
 	unsigned int size;
 	unsigned int pipe;
-}bulk_transfer_t,*pbulk_transfer_t;
+} bulk_transfer_t, *pbulk_transfer_t;
 
 #define DABUSB_MINOR 240		/* some unassigned USB minor */
 #define DABUSB_VERSION 0x1000
@@ -14,10 +13,9 @@ typedef struct
 
 #ifdef __KERNEL__
 
-typedef enum { _stopped=0, _started } driver_state_t;
+typedef enum { _stopped = 0, _started } driver_state_t;
 
-typedef struct
-{
+typedef struct {
 	struct mutex mutex;
 	struct usb_device *usbdev;
 	wait_queue_head_t wait;
@@ -34,17 +32,15 @@ typedef struct
 	int devnum;
 	struct list_head free_buff_list;
 	struct list_head rec_buff_list;
-} dabusb_t,*pdabusb_t;
+} dabusb_t, *pdabusb_t;
 
-typedef struct
-{
+typedef struct {
 	pdabusb_t s;
 	struct urb *purb;
 	struct list_head buff_list;
-} buff_t,*pbuff_t;
+} buff_t, *pbuff_t;
 
-typedef struct
-{
+typedef struct {
 	wait_queue_head_t wait;
 } bulk_completion_context_t, *pbulk_completion_context_t;
 
@@ -54,11 +50,11 @@ typedef struct
 #define _ISOPIPESIZE	16384
 
 #define _BULK_DATA_LEN 64
-// Vendor specific request code for Anchor Upload/Download
-// This one is implemented in the core
+/* Vendor specific request code for Anchor Upload/Download
+ *This one is implemented in the core */
 #define ANCHOR_LOAD_INTERNAL  0xA0
 
-// EZ-USB Control and Status Register.  Bit 0 controls 8051 reset
+/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
 #define CPUCS_REG    0x7F92
 #define _TOTAL_BUFFERS 384
 
@@ -67,19 +63,18 @@ typedef struct
 #ifndef _BYTE_DEFINED
 #define _BYTE_DEFINED
 typedef unsigned char BYTE;
-#endif // !_BYTE_DEFINED
+#endif /* !_BYTE_DEFINED */
 
 #ifndef _WORD_DEFINED
 #define _WORD_DEFINED
 typedef unsigned short WORD;
-#endif // !_WORD_DEFINED
+#endif /* !_WORD_DEFINED */
 
-typedef struct _INTEL_HEX_RECORD
-{
-   BYTE  Length;
-   WORD  Address;
-   BYTE  Type;
-   BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
+typedef struct _INTEL_HEX_RECORD {
+	BYTE  Length;
+	WORD  Address;
+	BYTE  Type;
+	BYTE  Data[MAX_INTEL_HEX_RECORD_LENGTH];
 } INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
 
 #endif
diff --git a/drivers/staging/easycap/Kconfig b/drivers/staging/easycap/Kconfig
index bd96f39..6ed208c 100644
--- a/drivers/staging/easycap/Kconfig
+++ b/drivers/staging/easycap/Kconfig
@@ -1,6 +1,6 @@
 config EASYCAP
 	tristate "EasyCAP USB ID 05e1:0408 support"
-	depends on USB && VIDEO_DEV
+	depends on USB && VIDEO_DEV && (SND || SOUND_OSS_CORE)
 
 	---help---
 	  This is an integrated audio/video driver for EasyCAP cards with
@@ -15,3 +15,44 @@ config EASYCAP
 	  To compile this driver as a module, choose M here: the
 	  module will be called easycap
 
+choice
+        prompt "Sound Interface"
+        depends on EASYCAP
+        default EASYCAP_SND
+	---help---
+
+config EASYCAP_SND
+        bool "ALSA"
+	depends on SND
+	select SND_PCM
+
+        ---help---
+          Say 'Y' if you want to use ALSA interface
+
+	  This will disable Open Sound System (OSS) binding.
+
+config EASYCAP_OSS
+	bool "OSS (DEPRECATED)"
+	depends on SOUND_OSS_CORE
+
+	---help---
+	  Say 'Y' if you prefer Open Sound System (OSS) interface
+
+	  This will disable Advanced Linux Sound Architecture (ALSA) binding.
+
+	  Once binding to ALSA interface will be stable this option will be
+          removed.
+endchoice
+
+config EASYCAP_DEBUG
+	bool "Enable EasyCAP driver debugging"
+	depends on EASYCAP
+
+	---help---
+	  This option enables debug printouts
+
+	  To enable debug, pass the debug level to the debug module
+          parameter:
+
+          modprobe easycap debug=[0..9]
+
diff --git a/drivers/staging/easycap/Makefile b/drivers/staging/easycap/Makefile
index f1f2fbe..b13e9ac 100644
--- a/drivers/staging/easycap/Makefile
+++ b/drivers/staging/easycap/Makefile
@@ -1,14 +1,12 @@
+easycap-objs := easycap_main.o
+easycap-objs += easycap_low.o
+easycap-objs += easycap_ioctl.o
+easycap-objs += easycap_settings.o
+easycap-objs += easycap_testcard.o
+easycap-objs += easycap_sound.o
+easycap-$(CONFIG_EASYCAP_OSS) += easycap_sound_oss.o
 
-obj-$(CONFIG_EASYCAP)	+= easycap.o
-
-easycap-y	:= easycap_main.o easycap_low.o easycap_sound.o
-easycap-y	+= easycap_ioctl.o easycap_settings.o
-easycap-y	+= easycap_testcard.o
+obj-$(CONFIG_EASYCAP)       += easycap.o
 
 ccflags-y := -Wall
-# Impose all or none of the following:
-ccflags-y += -DEASYCAP_IS_VIDEODEV_CLIENT
-ccflags-y += -DEASYCAP_NEEDS_V4L2_DEVICE_H
-ccflags-y += -DEASYCAP_NEEDS_V4L2_FOPS
-ccflags-y += -DEASYCAP_NEEDS_UNLOCKED_IOCTL
 
diff --git a/drivers/staging/easycap/easycap.h b/drivers/staging/easycap/easycap.h
index 8ebf96f..1f94e23 100644
--- a/drivers/staging/easycap/easycap.h
+++ b/drivers/staging/easycap/easycap.h
@@ -29,19 +29,14 @@
  *  THE FOLLOWING PARAMETERS ARE UNDEFINED:
  *
  *                EASYCAP_DEBUG
- *                EASYCAP_IS_VIDEODEV_CLIENT
- *                EASYCAP_NEEDS_USBVIDEO_H
- *                EASYCAP_NEEDS_V4L2_DEVICE_H
- *                EASYCAP_NEEDS_V4L2_FOPS
- *                EASYCAP_NEEDS_UNLOCKED_IOCTL
  *
  *  IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
  *  OPTIONS.
  */
 /*---------------------------------------------------------------------------*/
 
-#if (!defined(EASYCAP_H))
-#define EASYCAP_H
+#ifndef __EASYCAP_H__
+#define __EASYCAP_H__
 
 /*---------------------------------------------------------------------------*/
 /*
@@ -49,7 +44,6 @@
  */
 /*---------------------------------------------------------------------------*/
 #define  PATIENCE  500
-#undef   PREFER_NTSC
 #define  PERSEVERE
 /*---------------------------------------------------------------------------*/
 /*
@@ -57,15 +51,11 @@
  */
 /*---------------------------------------------------------------------------*/
 #undef  EASYCAP_TESTCARD
-#undef  EASYCAP_TESTTONE
-#undef  NOREADBACK
-#undef  AUDIOTIME
 /*---------------------------------------------------------------------------*/
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/kref.h>
 #include <linux/usb.h>
@@ -80,26 +70,25 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
+#ifndef CONFIG_EASYCAP_OSS
+#include <linux/vmalloc.h>
+#include <linux/sound.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#endif /* !CONFIG_EASYCAP_OSS */
 #include <media/v4l2-dev.h>
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
 #include <media/v4l2-device.h>
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 #include <linux/videodev2.h>
 #include <linux/soundcard.h>
-#if defined(EASYCAP_NEEDS_USBVIDEO_H)
-#include <config/video/usbvideo.h>
-#endif /*EASYCAP_NEEDS_USBVIDEO_H*/
 
-#if (!defined(PAGE_SIZE))
+#ifndef PAGE_SIZE
 #error "PAGE_SIZE not defined"
-#endif
+#endif /* PAGE_SIZE */
 
-#define STRINGIZE_AGAIN(x) #x
-#define STRINGIZE(x) STRINGIZE_AGAIN(x)
 /*---------------------------------------------------------------------------*/
 /*  VENDOR, PRODUCT:  Syntek Semiconductor Co., Ltd
  *
@@ -113,7 +102,7 @@
 #define USB_EASYCAP_VENDOR_ID	0x05e1
 #define USB_EASYCAP_PRODUCT_ID	0x0408
 
-#define EASYCAP_DRIVER_VERSION "0.8.41"
+#define EASYCAP_DRIVER_VERSION "0.9.01"
 #define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
 
 #define USB_SKEL_MINOR_BASE     192
@@ -159,7 +148,8 @@
  */
 /*---------------------------------------------------------------------------*/
 #define AUDIO_ISOC_BUFFER_MANY 16
-#define AUDIO_ISOC_ORDER 3
+#define AUDIO_ISOC_ORDER 1
+#define AUDIO_ISOC_FRAMESPERDESC 32
 #define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
 /*---------------------------------------------------------------------------*/
 /*
@@ -167,6 +157,7 @@
  */
 /*---------------------------------------------------------------------------*/
 #define AUDIO_FRAGMENT_MANY 32
+#define PAGES_PER_AUDIO_FRAGMENT 4
 /*---------------------------------------------------------------------------*/
 /*
  *  IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
@@ -207,28 +198,28 @@
  */
 /*---------------------------------------------------------------------------*/
 enum {
-AT_720x576,
-AT_704x576,
-AT_640x480,
-AT_720x480,
-AT_360x288,
-AT_320x240,
-AT_360x240,
-RESOLUTION_MANY
+	AT_720x576,
+	AT_704x576,
+	AT_640x480,
+	AT_720x480,
+	AT_360x288,
+	AT_320x240,
+	AT_360x240,
+	RESOLUTION_MANY
 };
 enum {
-FMT_UYVY,
-FMT_YUY2,
-FMT_RGB24,
-FMT_RGB32,
-FMT_BGR24,
-FMT_BGR32,
-PIXELFORMAT_MANY
+	FMT_UYVY,
+	FMT_YUY2,
+	FMT_RGB24,
+	FMT_RGB32,
+	FMT_BGR24,
+	FMT_BGR32,
+	PIXELFORMAT_MANY
 };
 enum {
-FIELD_NONE,
-FIELD_INTERLACED,
-INTERLACE_MANY
+	FIELD_NONE,
+	FIELD_INTERLACED,
+	INTERLACE_MANY
 };
 #define SETTINGS_MANY	(STANDARD_MANY * \
 			RESOLUTION_MANY * \
@@ -241,50 +232,50 @@ INTERLACE_MANY
  */
 /*---------------------------------------------------------------------------*/
 struct easycap_dongle {
-struct easycap *peasycap;
-struct mutex mutex_video;
-struct mutex mutex_audio;
+	struct easycap *peasycap;
+	struct mutex mutex_video;
+	struct mutex mutex_audio;
 };
 /*---------------------------------------------------------------------------*/
 struct data_buffer {
-struct list_head list_head;
-void *pgo;
-void *pto;
-__u16 kount;
-__u16 input;
+	struct list_head list_head;
+	void *pgo;
+	void *pto;
+	u16 kount;
+	u16 input;
 };
 /*---------------------------------------------------------------------------*/
 struct data_urb {
-struct list_head list_head;
-struct urb *purb;
-int isbuf;
-int length;
+	struct list_head list_head;
+	struct urb *purb;
+	int isbuf;
+	int length;
 };
 /*---------------------------------------------------------------------------*/
 struct easycap_standard {
-__u16 mask;
+	u16 mask;
 struct v4l2_standard v4l2_standard;
 };
 struct easycap_format {
-__u16 mask;
-char name[128];
+	u16 mask;
+	char name[128];
 struct v4l2_format v4l2_format;
 };
 struct inputset {
-int input;
-int input_ok;
-int standard_offset;
-int standard_offset_ok;
-int format_offset;
-int format_offset_ok;
-int brightness;
-int brightness_ok;
-int contrast;
-int contrast_ok;
-int saturation;
-int saturation_ok;
-int hue;
-int hue_ok;
+	int input;
+	int input_ok;
+	int standard_offset;
+	int standard_offset_ok;
+	int format_offset;
+	int format_offset_ok;
+	int brightness;
+	int brightness_ok;
+	int contrast;
+	int contrast_ok;
+	int saturation;
+	int saturation_ok;
+	int hue;
+	int hue_ok;
 };
 /*---------------------------------------------------------------------------*/
 /*
@@ -295,171 +286,182 @@ int hue_ok;
 /*---------------------------------------------------------------------------*/
 struct easycap {
 #define TELLTALE "expectedstring"
-char telltale[16];
-int isdongle;
-
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-struct video_device video_device;
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-struct v4l2_device v4l2_device;
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-int status;
-unsigned int audio_pages_per_fragment;
-unsigned int audio_bytes_per_fragment;
-unsigned int audio_buffer_page_many;
+	char telltale[16];
+	int isdongle;
+	int minor;
+
+	struct video_device video_device;
+	struct v4l2_device v4l2_device;
+
+	int status;
+	unsigned int audio_pages_per_fragment;
+	unsigned int audio_bytes_per_fragment;
+	unsigned int audio_buffer_page_many;
 
 #define UPSAMPLE
-#if defined(UPSAMPLE)
-__s16 oldaudio;
+#ifdef UPSAMPLE
+	s16 oldaudio;
 #endif /*UPSAMPLE*/
 
-int ilk;
-bool microphone;
-
-struct usb_device *pusb_device;
-struct usb_interface *pusb_interface;
-
-struct kref kref;
-
-int queued[FRAME_BUFFER_MANY];
-int done[FRAME_BUFFER_MANY];
-
-wait_queue_head_t wq_video;
-wait_queue_head_t wq_audio;
-
-int input;
-int polled;
-int standard_offset;
-int format_offset;
-struct inputset inputset[INPUT_MANY];
-
-bool ntsc;
-int fps;
-int usec;
-int tolerate;
-int skip;
-int skipped;
-int lost[INPUT_MANY];
-int merit[180];
-
-struct timeval timeval0;
-struct timeval timeval1;
-struct timeval timeval2;
-struct timeval timeval3;
-struct timeval timeval6;
-struct timeval timeval7;
-struct timeval timeval8;
-long long int dnbydt;
-
-int    video_interface;
-int    video_altsetting_on;
-int    video_altsetting_off;
-int    video_endpointnumber;
-int    video_isoc_maxframesize;
-int    video_isoc_buffer_size;
-int    video_isoc_framesperdesc;
-
-int    video_isoc_streaming;
-int    video_isoc_sequence;
-int    video_idle;
-int    video_eof;
-int    video_junk;
-
-struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY];
-struct data_buffer \
-	     field_buffer[FIELD_BUFFER_MANY][(FIELD_BUFFER_SIZE/PAGE_SIZE)];
-struct data_buffer \
-	     frame_buffer[FRAME_BUFFER_MANY][(FRAME_BUFFER_SIZE/PAGE_SIZE)];
-
-struct list_head urb_video_head;
-struct list_head *purb_video_head;
-
-__u8 cache[8];
-__u8 *pcache;
-int video_mt;
-int audio_mt;
-long long audio_bytes;
-__u32 isequence;
-
-int vma_many;
-
+	int ilk;
+	bool microphone;
+
+	struct usb_device *pusb_device;
+	struct usb_interface *pusb_interface;
+
+	struct kref kref;
+
+	int queued[FRAME_BUFFER_MANY];
+	int done[FRAME_BUFFER_MANY];
+
+	wait_queue_head_t wq_video;
+	wait_queue_head_t wq_audio;
+	wait_queue_head_t wq_trigger;
+
+	int input;
+	int polled;
+	int standard_offset;
+	int format_offset;
+	struct inputset inputset[INPUT_MANY];
+
+	bool ntsc;
+	int fps;
+	int usec;
+	int tolerate;
+	int skip;
+	int skipped;
+	int lost[INPUT_MANY];
+	int merit[180];
+
+	struct timeval timeval0;
+	struct timeval timeval1;
+	struct timeval timeval2;
+	struct timeval timeval3;
+	struct timeval timeval6;
+	struct timeval timeval7;
+	struct timeval timeval8;
+	long long int dnbydt;
+
+	int    video_interface;
+	int    video_altsetting_on;
+	int    video_altsetting_off;
+	int    video_endpointnumber;
+	int    video_isoc_maxframesize;
+	int    video_isoc_buffer_size;
+	int    video_isoc_framesperdesc;
+
+	int    video_isoc_streaming;
+	int    video_isoc_sequence;
+	int    video_idle;
+	int    video_eof;
+	int    video_junk;
+
+	struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY];
+	struct data_buffer field_buffer[FIELD_BUFFER_MANY]
+					[(FIELD_BUFFER_SIZE/PAGE_SIZE)];
+	struct data_buffer frame_buffer[FRAME_BUFFER_MANY]
+					[(FRAME_BUFFER_SIZE/PAGE_SIZE)];
+
+	struct list_head urb_video_head;
+	struct list_head *purb_video_head;
+
+	u8 cache[8];
+	u8 *pcache;
+	int video_mt;
+	int audio_mt;
+	long long audio_bytes;
+	u32 isequence;
+
+	int vma_many;
 /*---------------------------------------------------------------------------*/
 /*
  *  BUFFER INDICATORS
  */
 /*---------------------------------------------------------------------------*/
-int field_fill;		/* Field buffer being filled by easycap_complete().  */
+	int field_fill;	/* Field buffer being filled by easycap_complete().  */
 			/*   Bumped only by easycap_complete().              */
-int field_page;		/* Page of field buffer page being filled by         */
+	int field_page;	/* Page of field buffer page being filled by         */
 			/*   easycap_complete().                             */
-int field_read;		/* Field buffer to be read by field2frame().         */
+	int field_read;	/* Field buffer to be read by field2frame().         */
 			/*   Bumped only by easycap_complete().              */
-int frame_fill;		/* Frame buffer being filled by field2frame().       */
+	int frame_fill;	/* Frame buffer being filled by field2frame().       */
 			/*   Bumped only by easycap_dqbuf() when             */
 			/*   field2frame() has created a complete frame.     */
-int frame_read;		/* Frame buffer offered to user by DQBUF.            */
+	int frame_read;	/* Frame buffer offered to user by DQBUF.            */
 			/*   Set only by easycap_dqbuf() to trail frame_fill.*/
-int frame_lock;		/* Flag set to 1 by DQBUF and cleared by QBUF        */
+	int frame_lock;	/* Flag set to 1 by DQBUF and cleared by QBUF        */
 /*---------------------------------------------------------------------------*/
 /*
  *  IMAGE PROPERTIES
  */
 /*---------------------------------------------------------------------------*/
-__u32                   pixelformat;
-int                     width;
-int                     height;
-int                     bytesperpixel;
-bool                    byteswaporder;
-bool                    decimatepixel;
-bool                    offerfields;
-int                     frame_buffer_used;
-int                     frame_buffer_many;
-int                     videofieldamount;
-
-int                     brightness;
-int                     contrast;
-int                     saturation;
-int                     hue;
-
-int allocation_video_urb;
-int allocation_video_page;
-int allocation_video_struct;
-int registered_video;
+	u32                   pixelformat;
+	int                     width;
+	int                     height;
+	int                     bytesperpixel;
+	bool                    byteswaporder;
+	bool                    decimatepixel;
+	bool                    offerfields;
+	int                     frame_buffer_used;
+	int                     frame_buffer_many;
+	int                     videofieldamount;
+
+	int                     brightness;
+	int                     contrast;
+	int                     saturation;
+	int                     hue;
+
+	int allocation_video_urb;
+	int allocation_video_page;
+	int allocation_video_struct;
+	int registered_video;
+/*---------------------------------------------------------------------------*/
+/*
+ *  ALSA
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef CONFIG_EASYCAP_OSS
+	struct snd_pcm_hardware alsa_hardware;
+	struct snd_card *psnd_card;
+	struct snd_pcm *psnd_pcm;
+	struct snd_pcm_substream *psubstream;
+	int dma_fill;
+	int dma_next;
+	int dma_read;
+#endif /* !CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
 /*
  *  SOUND PROPERTIES
  */
 /*---------------------------------------------------------------------------*/
-int audio_interface;
-int audio_altsetting_on;
-int audio_altsetting_off;
-int audio_endpointnumber;
-int audio_isoc_maxframesize;
-int audio_isoc_buffer_size;
-int audio_isoc_framesperdesc;
+	int audio_interface;
+	int audio_altsetting_on;
+	int audio_altsetting_off;
+	int audio_endpointnumber;
+	int audio_isoc_maxframesize;
+	int audio_isoc_buffer_size;
+	int audio_isoc_framesperdesc;
 
-int audio_isoc_streaming;
-int audio_idle;
-int audio_eof;
-int volume;
-int mute;
+	int audio_isoc_streaming;
+	int audio_idle;
+	int audio_eof;
+	int volume;
+	int mute;
+	s8 gain;
 
-struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY];
+	struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY];
 
-struct list_head urb_audio_head;
-struct list_head *purb_audio_head;
+	struct list_head urb_audio_head;
+	struct list_head *purb_audio_head;
 /*---------------------------------------------------------------------------*/
 /*
  *  BUFFER INDICATORS
  */
 /*---------------------------------------------------------------------------*/
-int audio_fill;		/* Audio buffer being filled by easysnd_complete().  */
-			/*   Bumped only by easysnd_complete().              */
-int audio_read;		/* Audio buffer page being read by easysnd_read().   */
-			/*   Set by easysnd_read() to trail audio_fill by    */
+	int audio_fill;	/* Audio buffer being filled by easycap_complete().  */
+			/*   Bumped only by easycap_complete().              */
+	int audio_read;	/* Audio buffer page being read by easycap_read().   */
+			/*   Set by easycap_read() to trail audio_fill by    */
 			/*   one fragment.                                   */
 /*---------------------------------------------------------------------------*/
 /*
@@ -467,61 +469,36 @@ int audio_read;		/* Audio buffer page being read by easysnd_read().   */
  */
 /*---------------------------------------------------------------------------*/
 
-int audio_buffer_many;
+	int audio_buffer_many;
 
-int allocation_audio_urb;
-int allocation_audio_page;
-int allocation_audio_struct;
-int registered_audio;
+	int allocation_audio_urb;
+	int allocation_audio_page;
+	int allocation_audio_struct;
+	int registered_audio;
 
-long long int audio_sample;
-long long int audio_niveau;
-long long int audio_square;
+	long long int audio_sample;
+	long long int audio_niveau;
+	long long int audio_square;
 
-struct data_buffer audio_buffer[];
+	struct data_buffer audio_buffer[];
 };
 /*---------------------------------------------------------------------------*/
 /*
  *  VIDEO FUNCTION PROTOTYPES
  */
-/*---------------------------------------------------------------------------*/
-void             easycap_complete(struct urb *);
-int              easycap_open(struct inode *, struct file *);
-int              easycap_release(struct inode *, struct file *);
-long             easycap_ioctl_noinode(struct file *, unsigned int, \
-								unsigned long);
-int              easycap_ioctl(struct inode *, struct file *, unsigned int, \
-								unsigned long);
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-int              easycap_open_noinode(struct file *);
-int              easycap_release_noinode(struct file *);
-int              videodev_release(struct video_device *);
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-
-unsigned int     easycap_poll(struct file *, poll_table *);
-int              easycap_mmap(struct file *, struct vm_area_struct *);
-int              easycap_usb_probe(struct usb_interface *, \
-						const struct usb_device_id *);
-void             easycap_usb_disconnect(struct usb_interface *);
-void             easycap_delete(struct kref *);
-
-void             easycap_vma_open(struct vm_area_struct *);
-void             easycap_vma_close(struct vm_area_struct *);
-int              easycap_vma_fault(struct vm_area_struct *, struct vm_fault *);
+long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long);
 int              easycap_dqbuf(struct easycap *, int);
 int              submit_video_urbs(struct easycap *);
 int              kill_video_urbs(struct easycap *);
 int              field2frame(struct easycap *);
-int              redaub(struct easycap *, void *, void *, \
-						int, int, __u8, __u8, bool);
+int              redaub(struct easycap *, void *, void *,
+						int, int, u8, u8, bool);
 void             easycap_testcard(struct easycap *, int);
 int              fillin_formats(void);
-int              reset(struct easycap *);
 int              newinput(struct easycap *, int);
 int              adjust_standard(struct easycap *, v4l2_std_id);
-int              adjust_format(struct easycap *, __u32, __u32, __u32, \
+int              adjust_format(struct easycap *, u32, u32, u32,
 								int, bool);
 int              adjust_brightness(struct easycap *, int);
 int              adjust_contrast(struct easycap *, int);
@@ -533,19 +510,17 @@ int              adjust_volume(struct easycap *, int);
  *  AUDIO FUNCTION PROTOTYPES
  */
 /*---------------------------------------------------------------------------*/
-void             easysnd_complete(struct urb *);
-ssize_t          easysnd_read(struct file *, char __user *, size_t, loff_t *);
-int              easysnd_open(struct inode *, struct file *);
-int              easysnd_release(struct inode *, struct file *);
-long             easysnd_ioctl_noinode(struct file *, unsigned int, \
-								unsigned long);
-int              easysnd_ioctl(struct inode *, struct file *, unsigned int, \
-								unsigned long);
-unsigned int     easysnd_poll(struct file *, poll_table *);
-void             easysnd_delete(struct kref *);
+#ifndef CONFIG_EASYCAP_OSS
+int		easycap_alsa_probe(struct easycap *);
+void            easycap_alsa_complete(struct urb *);
+#else /* CONFIG_EASYCAP_OSS */
+void             easyoss_complete(struct urb *);
+#endif /* !CONFIG_EASYCAP_OSS */
+
+int              easycap_sound_setup(struct easycap *);
 int              submit_audio_urbs(struct easycap *);
 int              kill_audio_urbs(struct easycap *);
-void             easysnd_testtone(struct easycap *, int);
+void             easyoss_testtone(struct easycap *, int);
 int              audio_setup(struct easycap *);
 /*---------------------------------------------------------------------------*/
 /*
@@ -553,9 +528,9 @@ int              audio_setup(struct easycap *);
  */
 /*---------------------------------------------------------------------------*/
 int              audio_gainget(struct usb_device *);
-int              audio_gainset(struct usb_device *, __s8);
+int              audio_gainset(struct usb_device *, s8);
 
-int              set_interface(struct usb_device *, __u16);
+int              set_interface(struct usb_device *, u16);
 int              wakeup_device(struct usb_device *);
 int              confirm_resolution(struct usb_device *);
 int              confirm_stream(struct usb_device *);
@@ -569,48 +544,26 @@ int              ready_saa(struct usb_device *);
 int              merit_saa(struct usb_device *);
 int              check_vt(struct usb_device *);
 int              select_input(struct usb_device *, int, int);
-int              set_resolution(struct usb_device *, \
-						__u16, __u16, __u16, __u16);
-
-int              read_saa(struct usb_device *, __u16);
-int              read_stk(struct usb_device *, __u32);
-int              write_saa(struct usb_device *, __u16, __u16);
-int              wait_i2c(struct usb_device *);
-int              write_000(struct usb_device *, __u16, __u16);
+int              set_resolution(struct usb_device *,
+						u16, u16, u16, u16);
+
+int              read_saa(struct usb_device *, u16);
+int              read_stk(struct usb_device *, u32);
+int              write_saa(struct usb_device *, u16, u16);
+int              write_000(struct usb_device *, u16, u16);
 int              start_100(struct usb_device *);
 int              stop_100(struct usb_device *);
 int              write_300(struct usb_device *);
-int              read_vt(struct usb_device *, __u16);
-int              write_vt(struct usb_device *, __u16, __u16);
-int              regset(struct usb_device *, __u16, __u16);
-int              regget(struct usb_device *, __u16, void *);
+int              read_vt(struct usb_device *, u16);
+int              write_vt(struct usb_device *, u16, u16);
 int		isdongle(struct easycap *);
 /*---------------------------------------------------------------------------*/
 struct signed_div_result {
-long long int quotient;
-unsigned long long int remainder;
+	long long int quotient;
+	unsigned long long int remainder;
 } signed_div(long long int, long long int);
-/*---------------------------------------------------------------------------*/
-/*
- *  MACROS
- */
-/*---------------------------------------------------------------------------*/
-#define GET(X, Y, Z) do { \
-	int rc; \
-	*(Z) = (__u16)0; \
-	rc = regget(X, Y, Z); \
-	if (0 > rc) { \
-		JOT(8, ":-(%i\n", __LINE__);  return(rc); \
-	} \
-} while (0)
 
-#define SET(X, Y, Z) do { \
-	int rc; \
-	rc = regset(X, Y, Z); \
-	if (0 > rc) { \
-		JOT(8, ":-(%i\n", __LINE__);  return(rc); \
-	} \
-} while (0)
+
 /*---------------------------------------------------------------------------*/
 /*
  *  MACROS SAM(...) AND JOM(...) ALLOW DIAGNOSTIC OUTPUT TO BE TAGGED WITH
@@ -619,6 +572,8 @@ unsigned long long int remainder;
  *  IMMEDIATELY OBVIOUS FROM A CASUAL READING OF THE SOURCE CODE.  BEWARE.
 */
 /*---------------------------------------------------------------------------*/
+const char *strerror(int err);
+
 #define SAY(format, args...) do { \
 	printk(KERN_DEBUG "easycap:: %s: " \
 			format, __func__, ##args); \
@@ -628,7 +583,8 @@ unsigned long long int remainder;
 			format, peasycap->isdongle, __func__, ##args);\
 } while (0)
 
-#if defined(EASYCAP_DEBUG)
+#ifdef CONFIG_EASYCAP_DEBUG
+extern int easycap_debug;
 #define JOT(n, format, args...) do { \
 	if (n <= easycap_debug) { \
 		printk(KERN_DEBUG "easycap:: %s: " \
@@ -645,7 +601,7 @@ unsigned long long int remainder;
 #else
 #define JOT(n, format, args...) do {} while (0)
 #define JOM(n, format, args...) do {} while (0)
-#endif /*EASYCAP_DEBUG*/
+#endif /* CONFIG_EASYCAP_DEBUG */
 
 #define MICROSECONDS(X, Y) \
 			((1000000*((long long int)(X.tv_sec - Y.tv_sec))) + \
@@ -677,4 +633,19 @@ unsigned long long int remainder;
 } while (0)
 /*---------------------------------------------------------------------------*/
 
-#endif /*EASYCAP_H*/
+/*---------------------------------------------------------------------------*/
+/* globals
+ */
+/*---------------------------------------------------------------------------*/
+
+extern bool easycap_readback;
+extern const struct easycap_standard easycap_standard[];
+extern struct easycap_format easycap_format[];
+extern struct v4l2_queryctrl easycap_control[];
+extern struct usb_driver easycap_usb_driver;
+extern struct easycap_dongle easycapdc60_dongle[];
+#ifdef CONFIG_EASYCAP_OSS
+extern struct usb_class_driver easyoss_class;
+#endif /* !CONFIG_EASYCAP_OSS */
+
+#endif /* !__EASYCAP_H__  */
diff --git a/drivers/staging/easycap/easycap_debug.h b/drivers/staging/easycap/easycap_debug.h
deleted file mode 100644
index b6b5718..0000000
--- a/drivers/staging/easycap/easycap_debug.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
-*                                                                            *
-*  easycap_debug.h                                                           *
-*                                                                            *
-*****************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The software is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-extern int easycap_debug;
-extern int easycap_gain;
-extern struct easycap_dongle easycap_dongle[];
diff --git a/drivers/staging/easycap/easycap_ioctl.c b/drivers/staging/easycap/easycap_ioctl.c
index 447953a..28a28e0 100644
--- a/drivers/staging/easycap/easycap_ioctl.c
+++ b/drivers/staging/easycap/easycap_ioctl.c
@@ -25,11 +25,7 @@
 */
 /*****************************************************************************/
 
-#include <linux/smp_lock.h>
 #include "easycap.h"
-#include "easycap_debug.h"
-#include "easycap_standard.h"
-#include "easycap_ioctl.h"
 
 /*--------------------------------------------------------------------------*/
 /*
@@ -45,277 +41,297 @@
 /*---------------------------------------------------------------------------*/
 int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
 {
-struct easycap_standard const *peasycap_standard;
-__u16 reg, set;
-int ir, rc, need, k;
-unsigned int itwas, isnow;
-bool resubmit;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-peasycap_standard = &easycap_standard[0];
-while (0xFFFF != peasycap_standard->mask) {
-	if (std_id == peasycap_standard->v4l2_standard.id)
-		break;
-	peasycap_standard++;
-}
-if (0xFFFF == peasycap_standard->mask) {
+	struct easycap_standard const *peasycap_standard;
+	u16 reg, set;
+	int ir, rc, need, k;
+	unsigned int itwas, isnow;
+	bool resubmit;
+
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
 	peasycap_standard = &easycap_standard[0];
 	while (0xFFFF != peasycap_standard->mask) {
-		if (std_id & peasycap_standard->v4l2_standard.id)
+		if (std_id == peasycap_standard->v4l2_standard.id)
 			break;
 		peasycap_standard++;
 	}
-}
-if (0xFFFF == peasycap_standard->mask) {
-	SAM("ERROR: 0x%08X=std_id: standard not found\n", \
-							(unsigned int)std_id);
-	return -EINVAL;
-}
-SAM("selected standard: %s\n", \
-			&(peasycap_standard->v4l2_standard.name[0]));
-if (peasycap->standard_offset == \
-			(int)(peasycap_standard - &easycap_standard[0])) {
-	SAM("requested standard already in effect\n");
-	return 0;
-}
-peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]);
-for (k = 0; k < INPUT_MANY;  k++) {
-	if (!peasycap->inputset[k].standard_offset_ok) {
-			peasycap->inputset[k].standard_offset = \
-						peasycap->standard_offset;
+	if (0xFFFF == peasycap_standard->mask) {
+		peasycap_standard = &easycap_standard[0];
+		while (0xFFFF != peasycap_standard->mask) {
+			if (std_id & peasycap_standard->v4l2_standard.id)
+				break;
+			peasycap_standard++;
+		}
 	}
-}
-if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-	peasycap->inputset[peasycap->input].standard_offset = \
-						peasycap->standard_offset;
-	peasycap->inputset[peasycap->input].standard_offset_ok = 1;
-} else
-	JOM(8, "%i=peasycap->input\n", peasycap->input);
-peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
-		peasycap_standard->v4l2_standard.frameperiod.numerator;
-switch (peasycap->fps) {
-case 6:
-case 30: {
-	peasycap->ntsc = true;
-	break;
-}
-case 5:
-case 25: {
-	peasycap->ntsc = false;
-	break;
-}
-default: {
-	SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
-	return -ENOENT;
-}
-}
-JOM(8, "%i frames-per-second\n", peasycap->fps);
-if (0x8000 & peasycap_standard->mask) {
-	peasycap->skip = 5;
-	peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
-	peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
-} else {
-	peasycap->skip = 0;
-	peasycap->usec = 1000000 / (2 * peasycap->fps);
-	peasycap->tolerate = 1000 * (25 / peasycap->fps);
-}
-if (peasycap->video_isoc_streaming) {
-	resubmit = true;
-	kill_video_urbs(peasycap);
-} else
-	resubmit = false;
+	if (0xFFFF == peasycap_standard->mask) {
+		SAM("ERROR: 0x%08X=std_id: standard not found\n",
+		    (unsigned int)std_id);
+		return -EINVAL;
+	}
+	SAM("selected standard: %s\n",
+	    &(peasycap_standard->v4l2_standard.name[0]));
+	if (peasycap->standard_offset == peasycap_standard - easycap_standard) {
+		SAM("requested standard already in effect\n");
+		return 0;
+	}
+	peasycap->standard_offset = peasycap_standard - easycap_standard;
+	for (k = 0; k < INPUT_MANY;  k++) {
+		if (!peasycap->inputset[k].standard_offset_ok) {
+			peasycap->inputset[k].standard_offset =
+				peasycap->standard_offset;
+		}
+	}
+	if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+		peasycap->inputset[peasycap->input].standard_offset =
+			peasycap->standard_offset;
+		peasycap->inputset[peasycap->input].standard_offset_ok = 1;
+	} else
+		JOM(8, "%i=peasycap->input\n", peasycap->input);
+
+	peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator /
+			peasycap_standard->v4l2_standard.frameperiod.numerator;
+	switch (peasycap->fps) {
+	case 6:
+	case 30: {
+		peasycap->ntsc = true;
+		break;
+	}
+	case 5:
+	case 25: {
+		peasycap->ntsc = false;
+		break;
+	}
+	default: {
+		SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
+		return -ENOENT;
+	}
+	}
+	JOM(8, "%i frames-per-second\n", peasycap->fps);
+	if (0x8000 & peasycap_standard->mask) {
+		peasycap->skip = 5;
+		peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
+		peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
+	} else {
+		peasycap->skip = 0;
+		peasycap->usec = 1000000 / (2 * peasycap->fps);
+		peasycap->tolerate = 1000 * (25 / peasycap->fps);
+	}
+	if (peasycap->video_isoc_streaming) {
+		resubmit = true;
+		kill_video_urbs(peasycap);
+	} else
+		resubmit = false;
 /*--------------------------------------------------------------------------*/
 /*
  *  SAA7113H DATASHEET PAGE 44, TABLE 42
  */
 /*--------------------------------------------------------------------------*/
-need = 0;  itwas = 0;  reg = 0x00;  set = 0x00;
-switch (peasycap_standard->mask & 0x000F) {
-case NTSC_M_JP: {
-	reg = 0x0A;  set = 0x95;
-	ir = read_saa(peasycap->pusb_device, reg);
-	if (0 > ir)
-		SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
-	else
-		itwas = (unsigned int)ir;
-	rc = write_saa(peasycap->pusb_device, reg, set);
-	if (0 != rc)
-		SAM("ERROR: failed to set SAA register " \
-			"0x%02X to 0x%02X for JP standard\n", reg, set);
-	else {
-		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+	need = 0;
+	itwas = 0;
+	reg = 0x00;
+	set = 0x00;
+	switch (peasycap_standard->mask & 0x000F) {
+	case NTSC_M_JP: {
+		reg = 0x0A;
+		set = 0x95;
+		ir = read_saa(peasycap->pusb_device, reg);
 		if (0 > ir)
-			JOM(8, "SAA register 0x%02X changed " \
-				"to 0x%02X\n", reg, isnow);
+			SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 		else
-			JOM(8, "SAA register 0x%02X changed " \
-				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-	}
+			itwas = (unsigned int)ir;
+		rc = write_saa(peasycap->pusb_device, reg, set);
+		if (rc)
+			SAM("ERROR: failed to set SAA register "
+			    "0x%02X to 0x%02X for JP standard\n", reg, set);
+		else {
+			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+			if (0 > ir)
+				JOM(8, "SAA register 0x%02X changed "
+				    "to 0x%02X\n", reg, isnow);
+			else
+				JOM(8, "SAA register 0x%02X changed "
+				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+		}
 
-	reg = 0x0B;  set = 0x48;
-	ir = read_saa(peasycap->pusb_device, reg);
-	if (0 > ir)
-		SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
-	else
-		itwas = (unsigned int)ir;
-	rc = write_saa(peasycap->pusb_device, reg, set);
-	if (0 != rc)
-		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
-						"for JP standard\n", reg, set);
-	else {
-		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+		reg = 0x0B;
+		set = 0x48;
+		ir = read_saa(peasycap->pusb_device, reg);
 		if (0 > ir)
-			JOM(8, "SAA register 0x%02X changed " \
-				"to 0x%02X\n", reg, isnow);
+			SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
 		else
-			JOM(8, "SAA register 0x%02X changed " \
-				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-	}
+			itwas = (unsigned int)ir;
+		rc = write_saa(peasycap->pusb_device, reg, set);
+		if (rc)
+			SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X "
+			    "for JP standard\n", reg, set);
+		else {
+			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+			if (0 > ir)
+				JOM(8, "SAA register 0x%02X changed "
+				    "to 0x%02X\n", reg, isnow);
+			else
+				JOM(8, "SAA register 0x%02X changed "
+				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+		}
 /*--------------------------------------------------------------------------*/
 /*
  *  NOTE:  NO break HERE:  RUN ON TO NEXT CASE
  */
 /*--------------------------------------------------------------------------*/
-}
-case NTSC_M:
-case PAL_BGHIN: {
-	reg = 0x0E;  set = 0x01;  need = 1;  break;
-}
-case NTSC_N_443:
-case PAL_60: {
-	reg = 0x0E;  set = 0x11;  need = 1;  break;
-}
-case NTSC_443:
-case PAL_Nc: {
-	reg = 0x0E;  set = 0x21;  need = 1;  break;
-}
-case NTSC_N:
-case PAL_M: {
-	reg = 0x0E;  set = 0x31;  need = 1;  break;
-}
-case SECAM: {
-	reg = 0x0E;  set = 0x51;  need = 1;  break;
-}
-default:
-	break;
-}
+	}
+	case NTSC_M:
+	case PAL_BGHIN: {
+		reg = 0x0E;
+		set = 0x01;
+		need = 1;
+		break;
+	}
+	case NTSC_N_443:
+	case PAL_60: {
+		reg = 0x0E;
+		set = 0x11;
+		need = 1;
+		break;
+	}
+	case NTSC_443:
+	case PAL_Nc: {
+		reg = 0x0E;
+		set = 0x21;
+		need = 1;
+		break;
+	}
+	case NTSC_N:
+	case PAL_M: {
+		reg = 0x0E;
+		set = 0x31;
+		need = 1;
+		break;
+	}
+	case SECAM: {
+		reg = 0x0E;
+		set = 0x51;
+		need = 1;
+		break;
+	}
+	default:
+		break;
+	}
 /*--------------------------------------------------------------------------*/
-if (need) {
-	ir = read_saa(peasycap->pusb_device, reg);
-	if (0 > ir)
-		SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
-	else
-		itwas = (unsigned int)ir;
-	rc = write_saa(peasycap->pusb_device, reg, set);
-	if (0 != write_saa(peasycap->pusb_device, reg, set)) {
-		SAM("ERROR: failed to set SAA register " \
-			"0x%02X to 0x%02X for table 42\n", reg, set);
-	} else {
-		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+	if (need) {
+		ir = read_saa(peasycap->pusb_device, reg);
 		if (0 > ir)
-			JOM(8, "SAA register 0x%02X changed " \
-				"to 0x%02X\n", reg, isnow);
+			SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
 		else
-			JOM(8, "SAA register 0x%02X changed " \
-				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+			itwas = (unsigned int)ir;
+		rc = write_saa(peasycap->pusb_device, reg, set);
+		if (0 != write_saa(peasycap->pusb_device, reg, set)) {
+			SAM("ERROR: failed to set SAA register "
+			    "0x%02X to 0x%02X for table 42\n", reg, set);
+		} else {
+			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+			if (0 > ir)
+				JOM(8, "SAA register 0x%02X changed "
+				    "to 0x%02X\n", reg, isnow);
+			else
+				JOM(8, "SAA register 0x%02X changed "
+				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+		}
 	}
-}
 /*--------------------------------------------------------------------------*/
 /*
- *  SAA7113H DATASHEET PAGE 41
- */
+	 *  SAA7113H DATASHEET PAGE 41
+	 */
 /*--------------------------------------------------------------------------*/
-reg = 0x08;
-ir = read_saa(peasycap->pusb_device, reg);
-if (0 > ir)
-	SAM("ERROR: failed to read SAA register 0x%02X " \
-						"so cannot reset\n", reg);
-else {
-	itwas = (unsigned int)ir;
-	if (peasycap_standard->mask & 0x0001)
-		set = itwas | 0x40 ;
-	else
-		set = itwas & ~0x40 ;
-	rc  = write_saa(peasycap->pusb_device, reg, set);
-	if (0 != rc)
-		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
-								reg, set);
+	reg = 0x08;
+	ir = read_saa(peasycap->pusb_device, reg);
+	if (0 > ir)
+		SAM("ERROR: failed to read SAA register 0x%02X "
+		    "so cannot reset\n", reg);
 	else {
-		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-		if (0 > ir)
-			JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
-								reg, isnow);
+		itwas = (unsigned int)ir;
+		if (peasycap_standard->mask & 0x0001)
+			set = itwas | 0x40 ;
 		else
-			JOM(8, "SAA register 0x%02X changed " \
-				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+			set = itwas & ~0x40 ;
+		rc  = write_saa(peasycap->pusb_device, reg, set);
+		if (rc)
+			SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
+			    reg, set);
+		else {
+			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+			if (0 > ir)
+				JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
+				    reg, isnow);
+			else
+				JOM(8, "SAA register 0x%02X changed "
+				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+		}
 	}
-}
 /*--------------------------------------------------------------------------*/
 /*
  *  SAA7113H DATASHEET PAGE 51, TABLE 57
  */
 /*---------------------------------------------------------------------------*/
-reg = 0x40;
-ir = read_saa(peasycap->pusb_device, reg);
-if (0 > ir)
-	SAM("ERROR: failed to read SAA register 0x%02X " \
-						"so cannot reset\n", reg);
-else {
-	itwas = (unsigned int)ir;
-	if (peasycap_standard->mask & 0x0001)
-		set = itwas | 0x80 ;
-	else
-		set = itwas & ~0x80 ;
-	rc = write_saa(peasycap->pusb_device, reg, set);
-	if (0 != rc)
-		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
-								reg, set);
+	reg = 0x40;
+	ir = read_saa(peasycap->pusb_device, reg);
+	if (0 > ir)
+		SAM("ERROR: failed to read SAA register 0x%02X "
+		    "so cannot reset\n", reg);
 	else {
-		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-		if (0 > ir)
-			JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
-								reg, isnow);
+		itwas = (unsigned int)ir;
+		if (peasycap_standard->mask & 0x0001)
+			set = itwas | 0x80 ;
 		else
-			JOM(8, "SAA register 0x%02X changed " \
-				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+			set = itwas & ~0x80 ;
+		rc = write_saa(peasycap->pusb_device, reg, set);
+		if (rc)
+			SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
+			    reg, set);
+		else {
+			isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
+			if (0 > ir)
+				JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
+				    reg, isnow);
+			else
+				JOM(8, "SAA register 0x%02X changed "
+				    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+		}
 	}
-}
 /*--------------------------------------------------------------------------*/
 /*
- *  SAA7113H DATASHEET PAGE 53, TABLE 66
- */
+	 *  SAA7113H DATASHEET PAGE 53, TABLE 66
+	 */
 /*--------------------------------------------------------------------------*/
-reg = 0x5A;
-ir = read_saa(peasycap->pusb_device, reg);
-if (0 > ir)
-	SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
+	reg = 0x5A;
+	ir = read_saa(peasycap->pusb_device, reg);
+	if (0 > ir)
+		SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
 	itwas = (unsigned int)ir;
 	if (peasycap_standard->mask & 0x0001)
 		set = 0x0A ;
 	else
 		set = 0x07 ;
 	if (0 != write_saa(peasycap->pusb_device, reg, set))
-		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
-								reg, set);
+		SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
+		    reg, set);
 	else {
 		isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
 		if (0 > ir)
 			JOM(8, "SAA register 0x%02X changed "
-				"to 0x%02X\n", reg, isnow);
+			    "to 0x%02X\n", reg, isnow);
 		else
 			JOM(8, "SAA register 0x%02X changed "
-				"from 0x%02X to 0x%02X\n", reg, itwas, isnow);
+			    "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
 	}
-if (true == resubmit)
-	submit_video_urbs(peasycap);
-return 0;
+	if (resubmit)
+		submit_video_urbs(peasycap);
+	return 0;
 }
 /*****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -342,2478 +358,2121 @@ return 0;
  *  ERRORS RETURN A NEGATIVE NUMBER.
  */
 /*--------------------------------------------------------------------------*/
-int adjust_format(struct easycap *peasycap, \
-	__u32 width, __u32 height, __u32 pixelformat, int field, bool try)
+int adjust_format(struct easycap *peasycap,
+		  u32 width, u32 height, u32 pixelformat, int field, bool try)
 {
-struct easycap_format *peasycap_format, *peasycap_best_format;
-__u16 mask;
-struct usb_device *p;
-int miss, multiplier, best, k;
-char bf[5], fo[32], *pc;
-__u32 uc;
-bool resubmit;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if (0 > peasycap->standard_offset) {
-	JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
-	return -EBUSY;
-}
-p = peasycap->pusb_device;
-if ((struct usb_device *)NULL == p) {
-	SAM("ERROR: peaycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-pc = &bf[0];
-uc = pixelformat;
-memcpy((void *)pc, (void *)(&uc), 4);
-bf[4] = 0;
-mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
-SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \
-				width, height, pc, pixelformat, field, mask);
-switch (field) {
-case V4L2_FIELD_ANY: {
-	strcpy(&fo[0], "V4L2_FIELD_ANY ");
-	break;
-}
-case V4L2_FIELD_NONE: {
-	strcpy(&fo[0], "V4L2_FIELD_NONE");
-	break;
-}
-case V4L2_FIELD_TOP: {
-	strcpy(&fo[0], "V4L2_FIELD_TOP");
-	break;
-}
-case V4L2_FIELD_BOTTOM: {
-	strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
-	break;
-}
-case V4L2_FIELD_INTERLACED: {
-	strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
-	break;
-}
-case V4L2_FIELD_SEQ_TB: {
-	strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
-	break;
-}
-case V4L2_FIELD_SEQ_BT: {
-	strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
-	break;
-}
-case V4L2_FIELD_ALTERNATE: {
-	strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
-	break;
-}
-case V4L2_FIELD_INTERLACED_TB: {
-	strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
-	break;
-}
-case V4L2_FIELD_INTERLACED_BT: {
-	strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
-	break;
-}
-default: {
-	strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
-	break;
-}
-}
-SAM("sought:    %s\n", &fo[0]);
-if (V4L2_FIELD_ANY == field) {
-	field = V4L2_FIELD_NONE;
-	SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
-}
-peasycap_best_format = (struct easycap_format *)NULL;
-peasycap_format = &easycap_format[0];
-while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
-	JOM(16, ".> %i %i 0x%08X %ix%i\n", \
-		peasycap_format->mask & 0x01,
-		peasycap_format->v4l2_format.fmt.pix.field,
-		peasycap_format->v4l2_format.fmt.pix.pixelformat,
-		peasycap_format->v4l2_format.fmt.pix.width,
-		peasycap_format->v4l2_format.fmt.pix.height);
-
-	if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
-		(peasycap_format->v4l2_format.fmt.pix.field == field) && \
-		(peasycap_format->v4l2_format.fmt.pix.pixelformat == \
-							pixelformat) && \
-		(peasycap_format->v4l2_format.fmt.pix.width  == width) && \
-		(peasycap_format->v4l2_format.fmt.pix.height == height)) {
+	struct easycap_format *peasycap_format, *peasycap_best_format;
+	u16 mask;
+	struct usb_device *p;
+	int miss, multiplier, best, k;
+	char bf[5], fo[32], *pc;
+	u32 uc;
+	bool resubmit;
+
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (0 > peasycap->standard_offset) {
+		JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
+		return -EBUSY;
+	}
+	p = peasycap->pusb_device;
+	if (!p) {
+		SAM("ERROR: peaycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	pc = &bf[0];
+	uc = pixelformat;
+	memcpy((void *)pc, (void *)(&uc), 4);
+	bf[4] = 0;
+	mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
+	SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n",
+	    width, height, pc, pixelformat, field, mask);
+	switch (field) {
+	case V4L2_FIELD_ANY: {
+		strcpy(&fo[0], "V4L2_FIELD_ANY ");
+		break;
+	}
+	case V4L2_FIELD_NONE: {
+		strcpy(&fo[0], "V4L2_FIELD_NONE");
+		break;
+	}
+	case V4L2_FIELD_TOP: {
+		strcpy(&fo[0], "V4L2_FIELD_TOP");
+		break;
+	}
+	case V4L2_FIELD_BOTTOM: {
+		strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
+		break;
+	}
+	case V4L2_FIELD_INTERLACED: {
+		strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
+		break;
+	}
+	case V4L2_FIELD_SEQ_TB: {
+		strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
+		break;
+	}
+	case V4L2_FIELD_SEQ_BT: {
+		strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
+		break;
+	}
+	case V4L2_FIELD_ALTERNATE: {
+		strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
+		break;
+	}
+	case V4L2_FIELD_INTERLACED_TB: {
+		strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
+		break;
+	}
+	case V4L2_FIELD_INTERLACED_BT: {
+		strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
+		break;
+	}
+	default: {
+		strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
+		break;
+	}
+	}
+	SAM("sought:    %s\n", &fo[0]);
+	if (V4L2_FIELD_ANY == field) {
+		field = V4L2_FIELD_NONE;
+		SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
+	}
+	peasycap_best_format = NULL;
+	peasycap_format = &easycap_format[0];
+	while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
+		JOM(16, ".> %i %i 0x%08X %ix%i\n",
+		    peasycap_format->mask & 0x01,
+		    peasycap_format->v4l2_format.fmt.pix.field,
+		    peasycap_format->v4l2_format.fmt.pix.pixelformat,
+		    peasycap_format->v4l2_format.fmt.pix.width,
+		    peasycap_format->v4l2_format.fmt.pix.height);
+
+		if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
+		    (peasycap_format->v4l2_format.fmt.pix.field == field) &&
+		    (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat) &&
+		    (peasycap_format->v4l2_format.fmt.pix.width  == width) &&
+		    (peasycap_format->v4l2_format.fmt.pix.height == height)) {
+
 			peasycap_best_format = peasycap_format;
 			break;
 		}
-	peasycap_format++;
-}
-if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
-	SAM("cannot do: %ix%i with standard mask 0x%02X\n", \
-							width, height, mask);
-	peasycap_format = &easycap_format[0];  best = -1;
-	while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
-		if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
-				 (peasycap_format->v4l2_format.fmt.pix\
-						.field == field) && \
-				 (peasycap_format->v4l2_format.fmt.pix\
-						.pixelformat == pixelformat)) {
-			miss = abs(peasycap_format->\
-					v4l2_format.fmt.pix.width  - width);
-			if ((best > miss) || (best < 0)) {
-				best = miss;
-				peasycap_best_format = peasycap_format;
-				if (!miss)
-					break;
+		peasycap_format++;
+	}
+	if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
+		SAM("cannot do: %ix%i with standard mask 0x%02X\n",
+		    width, height, mask);
+		peasycap_format = &easycap_format[0];
+		best = -1;
+		while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
+			if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
+			    (peasycap_format->v4l2_format.fmt.pix.field == field) &&
+			    (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat)) {
+
+				miss = abs(peasycap_format->v4l2_format.fmt.pix.width  - width);
+				if ((best > miss) || (best < 0)) {
+					best = miss;
+					peasycap_best_format = peasycap_format;
+					if (!miss)
+						break;
+				}
 			}
+			peasycap_format++;
+		}
+		if (-1 == best) {
+			SAM("cannot do %ix... with standard mask 0x%02X\n",
+			    width, mask);
+			SAM("cannot do ...x%i with standard mask 0x%02X\n",
+			    height, mask);
+			SAM("           %ix%i unmatched\n", width, height);
+			return peasycap->format_offset;
 		}
-		peasycap_format++;
 	}
-	if (-1 == best) {
-		SAM("cannot do %ix... with standard mask 0x%02X\n", \
-								width, mask);
-		SAM("cannot do ...x%i with standard mask 0x%02X\n", \
-								height, mask);
-		SAM("           %ix%i unmatched\n", width, height);
-		return peasycap->format_offset;
+	if (!peasycap_best_format) {
+		SAM("MISTAKE: peasycap_best_format is NULL");
+		return -EINVAL;
 	}
-}
-if ((struct easycap_format *)NULL == peasycap_best_format) {
-	SAM("MISTAKE: peasycap_best_format is NULL");
-	return -EINVAL;
-}
-peasycap_format = peasycap_best_format;
+	peasycap_format = peasycap_best_format;
 
 /*...........................................................................*/
-if (true == try)
-	return (int)(peasycap_best_format - &easycap_format[0]);
+	if (try)
+		return peasycap_best_format - easycap_format;
 /*...........................................................................*/
 
-if (false != try) {
-	SAM("MISTAKE: true==try where is should be false\n");
-	return -EINVAL;
-}
-SAM("actioning: %ix%i %s\n", \
-			peasycap_format->v4l2_format.fmt.pix.width, \
-			peasycap_format->v4l2_format.fmt.pix.height,
-			&peasycap_format->name[0]);
-peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
-peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
-peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
-peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
+	if (false != try) {
+		SAM("MISTAKE: true==try where is should be false\n");
+		return -EINVAL;
+	}
+	SAM("actioning: %ix%i %s\n",
+	    peasycap_format->v4l2_format.fmt.pix.width,
+	    peasycap_format->v4l2_format.fmt.pix.height,
+	    &peasycap_format->name[0]);
+	peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
+	peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
+	peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
+	peasycap->format_offset = peasycap_format - easycap_format;
 
 
-for (k = 0; k < INPUT_MANY; k++) {
-	if (!peasycap->inputset[k].format_offset_ok) {
-		peasycap->inputset[k].format_offset = \
-						peasycap->format_offset;
+	for (k = 0; k < INPUT_MANY; k++) {
+		if (!peasycap->inputset[k].format_offset_ok) {
+			peasycap->inputset[k].format_offset =
+				peasycap->format_offset;
+		}
 	}
-}
-if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-	peasycap->inputset[peasycap->input].format_offset = \
-						peasycap->format_offset;
-	peasycap->inputset[peasycap->input].format_offset_ok = 1;
-} else
-	JOM(8, "%i=peasycap->input\n", peasycap->input);
-
-
-
-peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
-if (0x0100 & peasycap_format->mask)
-	peasycap->byteswaporder = true;
-else
-	peasycap->byteswaporder = false;
-if (0x0200 & peasycap_format->mask)
-	peasycap->skip = 5;
-else
-	peasycap->skip = 0;
-if (0x0800 & peasycap_format->mask)
-	peasycap->decimatepixel = true;
-else
-	peasycap->decimatepixel = false;
-if (0x1000 & peasycap_format->mask)
-	peasycap->offerfields = true;
-else
-	peasycap->offerfields = false;
-if (true == peasycap->decimatepixel)
-	multiplier = 2;
-else
-	multiplier = 1;
-peasycap->videofieldamount = multiplier * peasycap->width * \
-					multiplier * peasycap->height;
-peasycap->frame_buffer_used = peasycap->bytesperpixel * \
-					peasycap->width * peasycap->height;
-if (peasycap->video_isoc_streaming) {
-	resubmit = true;
-	kill_video_urbs(peasycap);
-} else
-	resubmit = false;
+	if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+		peasycap->inputset[peasycap->input].format_offset =
+			peasycap->format_offset;
+		peasycap->inputset[peasycap->input].format_offset_ok = 1;
+	} else
+		JOM(8, "%i=peasycap->input\n", peasycap->input);
+
+
+
+	peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
+	if (0x0100 & peasycap_format->mask)
+		peasycap->byteswaporder = true;
+	else
+		peasycap->byteswaporder = false;
+	if (0x0200 & peasycap_format->mask)
+		peasycap->skip = 5;
+	else
+		peasycap->skip = 0;
+	if (0x0800 & peasycap_format->mask)
+		peasycap->decimatepixel = true;
+	else
+		peasycap->decimatepixel = false;
+	if (0x1000 & peasycap_format->mask)
+		peasycap->offerfields = true;
+	else
+		peasycap->offerfields = false;
+	if (peasycap->decimatepixel)
+		multiplier = 2;
+	else
+		multiplier = 1;
+	peasycap->videofieldamount =
+		multiplier * peasycap->width * multiplier * peasycap->height;
+	peasycap->frame_buffer_used =
+		peasycap->bytesperpixel * peasycap->width * peasycap->height;
+	if (peasycap->video_isoc_streaming) {
+		resubmit = true;
+		kill_video_urbs(peasycap);
+	} else
+		resubmit = false;
 /*---------------------------------------------------------------------------*/
 /*
- *  PAL
- */
+	 *  PAL
+	 */
 /*---------------------------------------------------------------------------*/
-if (0 == (0x01 & peasycap_format->mask)) {
-	if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
-			(576 == \
-			peasycap_format->v4l2_format.fmt.pix.height)) || \
-			((360 == \
-			peasycap_format->v4l2_format.fmt.pix.width) && \
-			(288 == \
-			peasycap_format->v4l2_format.fmt.pix.height))) {
-		if (0 != set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
-			SAM("ERROR: set_resolution() failed\n");
-			return -EINVAL;
-		}
-	} else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && \
-			(576 == peasycap_format->v4l2_format.fmt.pix.height)) {
-		if (0 != set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
-			SAM("ERROR: set_resolution() failed\n");
-			return -EINVAL;
-		}
-	} else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
-			(480 == \
-			peasycap_format->v4l2_format.fmt.pix.height)) || \
-			((320 == \
-			peasycap_format->v4l2_format.fmt.pix.width) && \
-			(240 == \
-			peasycap_format->v4l2_format.fmt.pix.height))) {
-		if (0 != set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
-			SAM("ERROR: set_resolution() failed\n");
+	if (0 == (0x01 & peasycap_format->mask)) {
+		if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
+		     (576 == peasycap_format->v4l2_format.fmt.pix.height)) ||
+		    ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
+		     (288 == peasycap_format->v4l2_format.fmt.pix.height))) {
+			if (set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
+				SAM("ERROR: set_resolution() failed\n");
+				return -EINVAL;
+			}
+		} else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) &&
+			   (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
+			if (set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
+				SAM("ERROR: set_resolution() failed\n");
+				return -EINVAL;
+			}
+		} else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
+			    (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
+			   ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
+			    (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
+			if (set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
+				SAM("ERROR: set_resolution() failed\n");
+				return -EINVAL;
+			}
+		} else {
+			SAM("MISTAKE: bad format, cannot set resolution\n");
 			return -EINVAL;
 		}
-	} else {
-		SAM("MISTAKE: bad format, cannot set resolution\n");
-		return -EINVAL;
-	}
 /*---------------------------------------------------------------------------*/
 /*
  *  NTSC
  */
 /*---------------------------------------------------------------------------*/
-} else {
-	if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
-			(480 == \
-			peasycap_format->v4l2_format.fmt.pix.height)) || \
-			((360 == \
-			peasycap_format->v4l2_format.fmt.pix.width) && \
-			(240 == \
-			peasycap_format->v4l2_format.fmt.pix.height))) {
-		if (0 != set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
-			SAM("ERROR: set_resolution() failed\n");
-			return -EINVAL;
-		}
-	} else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
-			(480 == \
-			peasycap_format->v4l2_format.fmt.pix.height)) || \
-			((320 == \
-			peasycap_format->v4l2_format.fmt.pix.width) && \
-			(240 == \
-			peasycap_format->v4l2_format.fmt.pix.height))) {
-		if (0 != set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
-			SAM("ERROR: set_resolution() failed\n");
+	} else {
+		if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
+		     (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
+		    ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
+		     (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
+			if (set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
+				SAM("ERROR: set_resolution() failed\n");
+				return -EINVAL;
+			}
+		} else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
+			    (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
+			   ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
+			    (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
+			if (set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
+				SAM("ERROR: set_resolution() failed\n");
+				return -EINVAL;
+			}
+		} else {
+			SAM("MISTAKE: bad format, cannot set resolution\n");
 			return -EINVAL;
 		}
-	} else {
-		SAM("MISTAKE: bad format, cannot set resolution\n");
-		return -EINVAL;
 	}
-}
 /*---------------------------------------------------------------------------*/
-if (true == resubmit)
-	submit_video_urbs(peasycap);
-return (int)(peasycap_best_format - &easycap_format[0]);
+	if (resubmit)
+		submit_video_urbs(peasycap);
+
+	return peasycap_best_format - easycap_format;
 }
 /*****************************************************************************/
 int adjust_brightness(struct easycap *peasycap, int value)
 {
-unsigned int mood;
-int i1, k;
+	unsigned int mood;
+	int i1, k;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-i1 = 0;
-while (0xFFFFFFFF != easycap_control[i1].id) {
-	if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
-		if ((easycap_control[i1].minimum > value) || \
-					(easycap_control[i1].maximum < value))
-			value = easycap_control[i1].default_value;
-
-		if ((easycap_control[i1].minimum <= peasycap->brightness) && \
-					(easycap_control[i1].maximum >= \
-						peasycap->brightness)) {
-			if (peasycap->brightness == value) {
-				SAM("unchanged brightness at  0x%02X\n", \
-								value);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	i1 = 0;
+	while (0xFFFFFFFF != easycap_control[i1].id) {
+		if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
+			if ((easycap_control[i1].minimum > value) ||
+			    (easycap_control[i1].maximum < value))
+				value = easycap_control[i1].default_value;
+
+			if ((easycap_control[i1].minimum <= peasycap->brightness) &&
+			    (easycap_control[i1].maximum >= peasycap->brightness)) {
+				if (peasycap->brightness == value) {
+					SAM("unchanged brightness at  0x%02X\n",
+					    value);
+					return 0;
+				}
+			}
+			peasycap->brightness = value;
+			for (k = 0; k < INPUT_MANY; k++) {
+				if (!peasycap->inputset[k].brightness_ok)
+					peasycap->inputset[k].brightness =
+						peasycap->brightness;
+			}
+			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+				peasycap->inputset[peasycap->input].brightness =
+					peasycap->brightness;
+				peasycap->inputset[peasycap->input].brightness_ok = 1;
+			} else
+				JOM(8, "%i=peasycap->input\n", peasycap->input);
+			mood = 0x00FF & (unsigned int)peasycap->brightness;
+			if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
+				SAM("adjusting brightness to  0x%02X\n", mood);
 				return 0;
+			} else {
+				SAM("WARNING: failed to adjust brightness "
+				    "to 0x%02X\n", mood);
+				return -ENOENT;
 			}
+			break;
 		}
-		peasycap->brightness = value;
-		for (k = 0; k < INPUT_MANY; k++) {
-			if (!peasycap->inputset[k].brightness_ok)
-				peasycap->inputset[k].brightness = \
-							peasycap->brightness;
-		}
-		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-			peasycap->inputset[peasycap->input].brightness = \
-							peasycap->brightness;
-			peasycap->inputset[peasycap->input].brightness_ok = 1;
-		} else
-			JOM(8, "%i=peasycap->input\n", peasycap->input);
-		mood = 0x00FF & (unsigned int)peasycap->brightness;
-		if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
-			SAM("adjusting brightness to  0x%02X\n", mood);
-			return 0;
-		} else {
-			SAM("WARNING: failed to adjust brightness " \
-							"to 0x%02X\n", mood);
-			return -ENOENT;
-		}
-		break;
+		i1++;
 	}
-	i1++;
-}
-SAM("WARNING: failed to adjust brightness: control not found\n");
-return -ENOENT;
+	SAM("WARNING: failed to adjust brightness: control not found\n");
+	return -ENOENT;
 }
 /*****************************************************************************/
 int adjust_contrast(struct easycap *peasycap, int value)
 {
-unsigned int mood;
-int i1, k;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-i1 = 0;
-while (0xFFFFFFFF != easycap_control[i1].id) {
-	if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
-		if ((easycap_control[i1].minimum > value) || \
-					(easycap_control[i1].maximum < value))
-			value = easycap_control[i1].default_value;
+	unsigned int mood;
+	int i1, k;
 
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	i1 = 0;
+	while (0xFFFFFFFF != easycap_control[i1].id) {
+		if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
+			if ((easycap_control[i1].minimum > value) ||
+			    (easycap_control[i1].maximum < value))
+				value = easycap_control[i1].default_value;
+
+
+			if ((easycap_control[i1].minimum <= peasycap->contrast) &&
+			    (easycap_control[i1].maximum >= peasycap->contrast)) {
+				if (peasycap->contrast == value) {
+					SAM("unchanged contrast at  0x%02X\n", value);
+					return 0;
+				}
+			}
+			peasycap->contrast = value;
+			for (k = 0; k < INPUT_MANY; k++) {
+				if (!peasycap->inputset[k].contrast_ok)
+					peasycap->inputset[k].contrast = peasycap->contrast;
+			}
 
+			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+				peasycap->inputset[peasycap->input].contrast =
+						peasycap->contrast;
+				peasycap->inputset[peasycap->input].contrast_ok = 1;
+			} else
+				JOM(8, "%i=peasycap->input\n", peasycap->input);
 
-		if ((easycap_control[i1].minimum <= peasycap->contrast) && \
-				(easycap_control[i1].maximum >= \
-							peasycap->contrast)) {
-			if (peasycap->contrast == value) {
-				SAM("unchanged contrast at  0x%02X\n", value);
+			mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
+			if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
+				SAM("adjusting contrast to  0x%02X\n", mood);
 				return 0;
+			} else {
+				SAM("WARNING: failed to adjust contrast to "
+				    "0x%02X\n", mood);
+				return -ENOENT;
 			}
+			break;
 		}
-		peasycap->contrast = value;
-		for (k = 0; k < INPUT_MANY; k++) {
-			if (!peasycap->inputset[k].contrast_ok) {
-				peasycap->inputset[k].contrast = \
-							peasycap->contrast;
-			}
-		}
-		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-			peasycap->inputset[peasycap->input].contrast = \
-							peasycap->contrast;
-			peasycap->inputset[peasycap->input].contrast_ok = 1;
-		} else
-			JOM(8, "%i=peasycap->input\n", peasycap->input);
-		mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
-		if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
-			SAM("adjusting contrast to  0x%02X\n", mood);
-			return 0;
-		} else {
-			SAM("WARNING: failed to adjust contrast to " \
-							"0x%02X\n", mood);
-			return -ENOENT;
-		}
-		break;
+		i1++;
 	}
-	i1++;
-}
-SAM("WARNING: failed to adjust contrast: control not found\n");
-return -ENOENT;
+	SAM("WARNING: failed to adjust contrast: control not found\n");
+	return -ENOENT;
 }
 /*****************************************************************************/
 int adjust_saturation(struct easycap *peasycap, int value)
 {
-unsigned int mood;
-int i1, k;
+	unsigned int mood;
+	int i1, k;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-i1 = 0;
-while (0xFFFFFFFF != easycap_control[i1].id) {
-	if (V4L2_CID_SATURATION == easycap_control[i1].id) {
-		if ((easycap_control[i1].minimum > value) || \
-					(easycap_control[i1].maximum < value))
-			value = easycap_control[i1].default_value;
-
-
-		if ((easycap_control[i1].minimum <= peasycap->saturation) && \
-					(easycap_control[i1].maximum >= \
-						peasycap->saturation)) {
-			if (peasycap->saturation == value) {
-				SAM("unchanged saturation at  0x%02X\n", \
-								value);
-				return 0;
-			}
-		}
-		peasycap->saturation = value;
-		for (k = 0; k < INPUT_MANY; k++) {
-			if (!peasycap->inputset[k].saturation_ok) {
-				peasycap->inputset[k].saturation = \
-							peasycap->saturation;
-			}
-		}
-		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-			peasycap->inputset[peasycap->input].saturation = \
-							peasycap->saturation;
-			peasycap->inputset[peasycap->input].saturation_ok = 1;
-		} else
-			JOM(8, "%i=peasycap->input\n", peasycap->input);
-		mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
-		if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
-			SAM("adjusting saturation to  0x%02X\n", mood);
-			return 0;
-		} else {
-			SAM("WARNING: failed to adjust saturation to " \
-							"0x%02X\n", mood);
-			return -ENOENT;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	i1 = 0;
+	while (0xFFFFFFFF != easycap_control[i1].id) {
+		if (V4L2_CID_SATURATION == easycap_control[i1].id) {
+			if ((easycap_control[i1].minimum > value) ||
+			    (easycap_control[i1].maximum < value))
+				value = easycap_control[i1].default_value;
+
+
+			if ((easycap_control[i1].minimum <= peasycap->saturation) &&
+			    (easycap_control[i1].maximum >= peasycap->saturation)) {
+				if (peasycap->saturation == value) {
+					SAM("unchanged saturation at  0x%02X\n",
+					    value);
+					return 0;
+				}
+			}
+			peasycap->saturation = value;
+			for (k = 0; k < INPUT_MANY; k++) {
+				if (!peasycap->inputset[k].saturation_ok)
+					peasycap->inputset[k].saturation =
+						peasycap->saturation;
+			}
+			if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
+				peasycap->inputset[peasycap->input].saturation =
+					peasycap->saturation;
+				peasycap->inputset[peasycap->input].saturation_ok = 1;
+			} else
+				JOM(8, "%i=peasycap->input\n", peasycap->input);
+			mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
+			if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
+				SAM("adjusting saturation to  0x%02X\n", mood);
+				return 0;
+			} else {
+				SAM("WARNING: failed to adjust saturation to "
+				    "0x%02X\n", mood);
+				return -ENOENT;
+			}
+			break;
 		}
-		break;
+		i1++;
 	}
-	i1++;
-}
-SAM("WARNING: failed to adjust saturation: control not found\n");
-return -ENOENT;
+	SAM("WARNING: failed to adjust saturation: control not found\n");
+	return -ENOENT;
 }
 /*****************************************************************************/
 int adjust_hue(struct easycap *peasycap, int value)
 {
-unsigned int mood;
-int i1, i2, k;
+	unsigned int mood;
+	int i1, i2, k;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-i1 = 0;
-while (0xFFFFFFFF != easycap_control[i1].id) {
-	if (V4L2_CID_HUE == easycap_control[i1].id) {
-		if ((easycap_control[i1].minimum > value) || \
-					(easycap_control[i1].maximum < value))
-			value = easycap_control[i1].default_value;
-
-		if ((easycap_control[i1].minimum <= peasycap->hue) && \
-					(easycap_control[i1].maximum >= \
-							peasycap->hue)) {
-			if (peasycap->hue == value) {
-				SAM("unchanged hue at  0x%02X\n", value);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	i1 = 0;
+	while (0xFFFFFFFF != easycap_control[i1].id) {
+		if (V4L2_CID_HUE == easycap_control[i1].id) {
+			if ((easycap_control[i1].minimum > value) ||
+			    (easycap_control[i1].maximum < value))
+				value = easycap_control[i1].default_value;
+
+			if ((easycap_control[i1].minimum <= peasycap->hue) &&
+			    (easycap_control[i1].maximum >= peasycap->hue)) {
+				if (peasycap->hue == value) {
+					SAM("unchanged hue at  0x%02X\n", value);
+					return 0;
+				}
+			}
+			peasycap->hue = value;
+			for (k = 0; k < INPUT_MANY; k++) {
+				if (!peasycap->inputset[k].hue_ok)
+					peasycap->inputset[k].hue = peasycap->hue;
+			}
+			if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
+				peasycap->inputset[peasycap->input].hue = peasycap->hue;
+				peasycap->inputset[peasycap->input].hue_ok = 1;
+			} else
+				JOM(8, "%i=peasycap->input\n", peasycap->input);
+			i2 = peasycap->hue - 128;
+			mood = 0x00FF & ((int) i2);
+			if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
+				SAM("adjusting hue to  0x%02X\n", mood);
 				return 0;
+			} else {
+				SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
+				return -ENOENT;
 			}
+			break;
 		}
-		peasycap->hue = value;
-		for (k = 0; k < INPUT_MANY; k++) {
-			if (!peasycap->inputset[k].hue_ok)
-				peasycap->inputset[k].hue = peasycap->hue;
-		}
-		if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-			peasycap->inputset[peasycap->input].hue = \
-							peasycap->hue;
-			peasycap->inputset[peasycap->input].hue_ok = 1;
-		} else
-			JOM(8, "%i=peasycap->input\n", peasycap->input);
-		i2 = peasycap->hue - 128;
-		mood = 0x00FF & ((int) i2);
-		if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
-			SAM("adjusting hue to  0x%02X\n", mood);
-			return 0;
-		} else {
-			SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
-			return -ENOENT;
-		}
-		break;
+		i1++;
 	}
-	i1++;
-}
-SAM("WARNING: failed to adjust hue: control not found\n");
-return -ENOENT;
+	SAM("WARNING: failed to adjust hue: control not found\n");
+	return -ENOENT;
 }
 /*****************************************************************************/
 int adjust_volume(struct easycap *peasycap, int value)
 {
-__s8 mood;
-int i1;
+	s8 mood;
+	int i1;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-i1 = 0;
-while (0xFFFFFFFF != easycap_control[i1].id) {
-	if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
-		if ((easycap_control[i1].minimum > value) || \
-				(easycap_control[i1].maximum < value))
-			value = easycap_control[i1].default_value;
-		if ((easycap_control[i1].minimum <= peasycap->volume) && \
-					(easycap_control[i1].maximum >= \
-							peasycap->volume)) {
-			if (peasycap->volume == value) {
-				SAM("unchanged volume at  0x%02X\n", value);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	i1 = 0;
+	while (0xFFFFFFFF != easycap_control[i1].id) {
+		if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
+			if ((easycap_control[i1].minimum > value) ||
+			    (easycap_control[i1].maximum < value))
+				value = easycap_control[i1].default_value;
+
+			if ((easycap_control[i1].minimum <= peasycap->volume) &&
+			    (easycap_control[i1].maximum >= peasycap->volume)) {
+				if (peasycap->volume == value) {
+					SAM("unchanged volume at  0x%02X\n", value);
+					return 0;
+				}
+			}
+			peasycap->volume = value;
+			mood = (16 > peasycap->volume) ? 16 :
+				((31 < peasycap->volume) ? 31 :
+				  (s8) peasycap->volume);
+			if (!audio_gainset(peasycap->pusb_device, mood)) {
+				SAM("adjusting volume to 0x%02X\n", mood);
 				return 0;
+			} else {
+				SAM("WARNING: failed to adjust volume to "
+				    "0x%2X\n", mood);
+				return -ENOENT;
 			}
+			break;
 		}
-		peasycap->volume = value;
-		mood = (16 > peasycap->volume) ? 16 : \
-			((31 < peasycap->volume) ? 31 : \
-			(__s8) peasycap->volume);
-		if (!audio_gainset(peasycap->pusb_device, mood)) {
-			SAM("adjusting volume to 0x%02X\n", mood);
-			return 0;
-		} else {
-			SAM("WARNING: failed to adjust volume to " \
-							"0x%2X\n", mood);
-			return -ENOENT;
-		}
-		break;
+		i1++;
 	}
-i1++;
-}
-SAM("WARNING: failed to adjust volume: control not found\n");
-return -ENOENT;
+	SAM("WARNING: failed to adjust volume: control not found\n");
+	return -ENOENT;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
- *            usb_set_interface(peasycap->pusb_device, \
- *                              peasycap->audio_interface, \
+ *            usb_set_interface(peasycap->pusb_device,
+ *                              peasycap->audio_interface,
  *                              peasycap->audio_altsetting_off);
  *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
- *  -ESHUTDOWN.  THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT
+ *  -ESHUTDOWN.  THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
  *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
  */
 /*---------------------------------------------------------------------------*/
-int adjust_mute(struct easycap *peasycap, int value)
+static int adjust_mute(struct easycap *peasycap, int value)
 {
-int i1;
+	int i1;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-i1 = 0;
-while (0xFFFFFFFF != easycap_control[i1].id) {
-	if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
-		peasycap->mute = value;
-		switch (peasycap->mute) {
-		case 1: {
-			peasycap->audio_idle = 1;
-			peasycap->timeval0.tv_sec = 0;
-			SAM("adjusting mute: %i=peasycap->audio_idle\n", \
-							peasycap->audio_idle);
-			return 0;
-		}
-		default: {
-			peasycap->audio_idle = 0;
-			SAM("adjusting mute: %i=peasycap->audio_idle\n", \
-							peasycap->audio_idle);
-			return 0;
-		}
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	i1 = 0;
+	while (0xFFFFFFFF != easycap_control[i1].id) {
+		if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
+			peasycap->mute = value;
+			switch (peasycap->mute) {
+			case 1: {
+				peasycap->audio_idle = 1;
+				peasycap->timeval0.tv_sec = 0;
+				SAM("adjusting mute: %i=peasycap->audio_idle\n",
+				    peasycap->audio_idle);
+				return 0;
+			}
+			default: {
+				peasycap->audio_idle = 0;
+				SAM("adjusting mute: %i=peasycap->audio_idle\n",
+				    peasycap->audio_idle);
+				return 0;
+			}
+			}
+			break;
 		}
-		break;
+		i1++;
 	}
-	i1++;
-}
-SAM("WARNING: failed to adjust mute: control not found\n");
-return -ENOENT;
-}
-/*****************************************************************************/
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
-	(defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
-long
-easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
-	return (long)easycap_ioctl((struct inode *)NULL, file, cmd, arg);
+	SAM("WARNING: failed to adjust mute: control not found\n");
+	return -ENOENT;
 }
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 /*---------------------------------------------------------------------------*/
-int
-easycap_ioctl(struct inode *inode, struct file *file,
-					unsigned int cmd, unsigned long arg)
+long easycap_unlocked_ioctl(struct file *file,
+			    unsigned int cmd, unsigned long arg)
 {
-struct easycap *peasycap;
-struct usb_device *p;
-int kd;
+	struct easycap *peasycap;
+	struct usb_device *p;
+	int kd;
 
-if (NULL == file) {
-	SAY("ERROR:  file is NULL\n");
-	return -ERESTARTSYS;
-}
-peasycap = file->private_data;
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL\n");
-	return -1;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap\n");
-	return -EFAULT;
-}
-p = peasycap->pusb_device;
-if (NULL == p) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-kd = isdongle(peasycap);
-if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
-		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
-		return -ERESTARTSYS;
-	}
-	JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
-/*---------------------------------------------------------------------------*/
-/*
- *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
- *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
- *  IF NECESSARY, BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-	if (kd != isdongle(peasycap))
-		return -ERESTARTSYS;
-	if (NULL == file) {
+	if (!file) {
 		SAY("ERROR:  file is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
 		return -ERESTARTSYS;
 	}
 	peasycap = file->private_data;
-	if (NULL == peasycap) {
+	if (!peasycap) {
 		SAY("ERROR:  peasycap is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ERESTARTSYS;
+		return -1;
 	}
 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
 		SAY("ERROR: bad peasycap\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
 		return -EFAULT;
 	}
 	p = peasycap->pusb_device;
-	if (NULL == peasycap->pusb_device) {
+	if (!p) {
 		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ERESTARTSYS;
+		return -EFAULT;
 	}
-} else {
+	kd = isdongle(peasycap);
+	if (0 <= kd && DONGLE_MANY > kd) {
+		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+			SAY("ERROR: cannot lock "
+			    "easycapdc60_dongle[%i].mutex_video\n", kd);
+			return -ERESTARTSYS;
+		}
+		JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
+/*---------------------------------------------------------------------------*/
+/*
+ *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
+ *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
+ *  IF NECESSARY, BAIL OUT.
+ */
+/*---------------------------------------------------------------------------*/
+		if (kd != isdongle(peasycap))
+			return -ERESTARTSYS;
+		if (!file) {
+			SAY("ERROR:  file is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+		peasycap = file->private_data;
+		if (!peasycap) {
+			SAY("ERROR:  peasycap is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+			SAY("ERROR: bad peasycap\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		p = peasycap->pusb_device;
+		if (!peasycap->pusb_device) {
+			SAM("ERROR: peasycap->pusb_device is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+	} else {
 /*---------------------------------------------------------------------------*/
 /*
  *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
  *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-	return -ERESTARTSYS;
-}
+ */
 /*---------------------------------------------------------------------------*/
-switch (cmd) {
-case VIDIOC_QUERYCAP: {
-	struct v4l2_capability v4l2_capability;
-	char version[16], *p1, *p2;
-	int i, rc, k[3];
-	long lng;
-
-	JOM(8, "VIDIOC_QUERYCAP\n");
-
-	if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
-		SAM("ERROR: bad driver version string\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
+		return -ERESTARTSYS;
 	}
-	strcpy(&version[0], EASYCAP_DRIVER_VERSION);
-	for (i = 0; i < 3; i++)
-		k[i] = 0;
-	p2 = &version[0];  i = 0;
-	while (*p2) {
-		p1 = p2;
-		while (*p2 && ('.' != *p2))
-			p2++;
-		if (*p2)
-			*p2++ = 0;
-		if (3 > i) {
-			rc = (int) strict_strtol(p1, 10, &lng);
-			if (0 != rc) {
-				SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
-								rc, p1);
-				mutex_unlock(&easycap_dongle[kd].mutex_video);
-				return -EINVAL;
+/*---------------------------------------------------------------------------*/
+	switch (cmd) {
+	case VIDIOC_QUERYCAP: {
+		struct v4l2_capability v4l2_capability;
+		char version[16], *p1, *p2;
+		int i, rc, k[3];
+		long lng;
+
+		JOM(8, "VIDIOC_QUERYCAP\n");
+
+		if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
+			SAM("ERROR: bad driver version string\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		strcpy(&version[0], EASYCAP_DRIVER_VERSION);
+		for (i = 0; i < 3; i++)
+			k[i] = 0;
+		p2 = &version[0];
+		i = 0;
+		while (*p2) {
+			p1 = p2;
+			while (*p2 && ('.' != *p2))
+				p2++;
+			if (*p2)
+				*p2++ = 0;
+			if (3 > i) {
+				rc = (int) strict_strtol(p1, 10, &lng);
+				if (rc) {
+					SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
+					    rc, p1);
+					mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+					return -EINVAL;
+				}
+				k[i] = (int)lng;
 			}
-			k[i] = (int)lng;
+			i++;
 		}
-		i++;
-	}
 
-	memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
-	strlcpy(&v4l2_capability.driver[0], "easycap", \
-					sizeof(v4l2_capability.driver));
+		memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
+		strlcpy(&v4l2_capability.driver[0],
+			"easycap", sizeof(v4l2_capability.driver));
 
-	v4l2_capability.capabilities = \
-				V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
-				V4L2_CAP_AUDIO         | V4L2_CAP_READWRITE;
+		v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
+						V4L2_CAP_STREAMING |
+						V4L2_CAP_AUDIO |
+						V4L2_CAP_READWRITE;
 
-	v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
-	JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
+		v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
+		JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
 
-	strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \
-		sizeof(v4l2_capability.card));
+		strlcpy(&v4l2_capability.card[0],
+			"EasyCAP DC60", sizeof(v4l2_capability.card));
 
-	if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\
+		if (usb_make_path(peasycap->pusb_device,
+				&v4l2_capability.bus_info[0],
 				sizeof(v4l2_capability.bus_info)) < 0) {
-		strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \
-					sizeof(v4l2_capability.bus_info));
-		JOM(8, "%s=v4l2_capability.bus_info\n", \
-					&v4l2_capability.bus_info[0]);
-	}
-	if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
-					sizeof(struct v4l2_capability))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+
+			strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
+				sizeof(v4l2_capability.bus_info));
+			JOM(8, "%s=v4l2_capability.bus_info\n",
+				&v4l2_capability.bus_info[0]);
+		}
+		if (copy_to_user((void __user *)arg, &v4l2_capability,
+				sizeof(struct v4l2_capability))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_ENUMINPUT: {
-	struct v4l2_input v4l2_input;
-	__u32 index;
+	case VIDIOC_ENUMINPUT: {
+		struct v4l2_input v4l2_input;
+		u32 index;
 
-	JOM(8, "VIDIOC_ENUMINPUT\n");
+		JOM(8, "VIDIOC_ENUMINPUT\n");
 
-	if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
+		if (copy_from_user(&v4l2_input, (void __user *)arg,
 					sizeof(struct v4l2_input))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	index = v4l2_input.index;
-	memset(&v4l2_input, 0, sizeof(struct v4l2_input));
-
-	switch (index) {
-	case 0: {
-		v4l2_input.index = index;
-		strcpy(&v4l2_input.name[0], "CVBS0");
-		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-		v4l2_input.audioset = 0x01;
-		v4l2_input.tuner = 0;
-		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
-				V4L2_STD_NTSC ;
-		v4l2_input.status = 0;
-		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-		break;
-	}
-	case 1: {
-		v4l2_input.index = index;
-		strcpy(&v4l2_input.name[0], "CVBS1");
-		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-		v4l2_input.audioset = 0x01;
-		v4l2_input.tuner = 0;
-		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
-				V4L2_STD_NTSC ;
-		v4l2_input.status = 0;
-		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-		break;
-	}
-	case 2: {
-		v4l2_input.index = index;
-		strcpy(&v4l2_input.name[0], "CVBS2");
-		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-		v4l2_input.audioset = 0x01;
-		v4l2_input.tuner = 0;
-		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
-				V4L2_STD_NTSC ;
-		v4l2_input.status = 0;
-		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-		break;
-	}
-	case 3: {
-		v4l2_input.index = index;
-		strcpy(&v4l2_input.name[0], "CVBS3");
-		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-		v4l2_input.audioset = 0x01;
-		v4l2_input.tuner = 0;
-		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
-				V4L2_STD_NTSC ;
-		v4l2_input.status = 0;
-		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-		break;
-	}
-	case 4: {
-		v4l2_input.index = index;
-		strcpy(&v4l2_input.name[0], "CVBS4");
-		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-		v4l2_input.audioset = 0x01;
-		v4l2_input.tuner = 0;
-		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
-				V4L2_STD_NTSC ;
-		v4l2_input.status = 0;
-		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-		break;
-	}
-	case 5: {
-		v4l2_input.index = index;
-		strcpy(&v4l2_input.name[0], "S-VIDEO");
-		v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-		v4l2_input.audioset = 0x01;
-		v4l2_input.tuner = 0;
-		v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
-				V4L2_STD_NTSC ;
-		v4l2_input.status = 0;
-		JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-		break;
-	}
-	default: {
-		JOM(8, "%i=index: exhausts inputs\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	}
+		index = v4l2_input.index;
+		memset(&v4l2_input, 0, sizeof(struct v4l2_input));
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
-						sizeof(struct v4l2_input))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		switch (index) {
+		case 0: {
+			v4l2_input.index = index;
+			strcpy(&v4l2_input.name[0], "CVBS0");
+			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
+			v4l2_input.audioset = 0x01;
+			v4l2_input.tuner = 0;
+			v4l2_input.std = V4L2_STD_PAL |
+					V4L2_STD_SECAM |
+					V4L2_STD_NTSC ;
+			v4l2_input.status = 0;
+			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
+			break;
+		}
+		case 1: {
+			v4l2_input.index = index;
+			strcpy(&v4l2_input.name[0], "CVBS1");
+			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
+			v4l2_input.audioset = 0x01;
+			v4l2_input.tuner = 0;
+			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
+					V4L2_STD_NTSC;
+			v4l2_input.status = 0;
+			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
+			break;
+		}
+		case 2: {
+			v4l2_input.index = index;
+			strcpy(&v4l2_input.name[0], "CVBS2");
+			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
+			v4l2_input.audioset = 0x01;
+			v4l2_input.tuner = 0;
+			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
+					V4L2_STD_NTSC ;
+			v4l2_input.status = 0;
+			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
+			break;
+		}
+		case 3: {
+			v4l2_input.index = index;
+			strcpy(&v4l2_input.name[0], "CVBS3");
+			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
+			v4l2_input.audioset = 0x01;
+			v4l2_input.tuner = 0;
+			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
+					V4L2_STD_NTSC ;
+			v4l2_input.status = 0;
+			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
+			break;
+		}
+		case 4: {
+			v4l2_input.index = index;
+			strcpy(&v4l2_input.name[0], "CVBS4");
+			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
+			v4l2_input.audioset = 0x01;
+			v4l2_input.tuner = 0;
+			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
+					V4L2_STD_NTSC ;
+			v4l2_input.status = 0;
+			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
+			break;
+		}
+		case 5: {
+			v4l2_input.index = index;
+			strcpy(&v4l2_input.name[0], "S-VIDEO");
+			v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
+			v4l2_input.audioset = 0x01;
+			v4l2_input.tuner = 0;
+			v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
+					V4L2_STD_NTSC ;
+			v4l2_input.status = 0;
+			JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
+			break;
+		}
+		default: {
+			JOM(8, "%i=index: exhausts inputs\n", index);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		}
+
+		if (copy_to_user((void __user *)arg, &v4l2_input,
+				sizeof(struct v4l2_input))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_INPUT: {
-	__u32 index;
-
-	JOM(8, "VIDIOC_G_INPUT\n");
-	index = (__u32)peasycap->input;
-	JOM(8, "user is told: %i\n", index);
-	if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+	case VIDIOC_G_INPUT: {
+		u32 index;
+
+		JOM(8, "VIDIOC_G_INPUT\n");
+		index = (u32)peasycap->input;
+		JOM(8, "user is told: %i\n", index);
+		if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_S_INPUT:
+	case VIDIOC_S_INPUT:
 	{
-	__u32 index;
-	int rc;
+		u32 index;
+		int rc;
 
-	JOM(8, "VIDIOC_S_INPUT\n");
+		JOM(8, "VIDIOC_S_INPUT\n");
 
-	if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	JOM(8, "user requests input %i\n", index);
+		JOM(8, "user requests input %i\n", index);
 
-	if ((int)index == peasycap->input) {
-		SAM("requested input already in effect\n");
-		break;
-	}
+		if ((int)index == peasycap->input) {
+			SAM("requested input already in effect\n");
+			break;
+		}
 
-	if ((0 > index) || (INPUT_MANY <= index)) {
-		JOM(8, "ERROR:  bad requested input: %i\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
+		if ((0 > index) || (INPUT_MANY <= index)) {
+			JOM(8, "ERROR:  bad requested input: %i\n", index);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
 
-	rc = newinput(peasycap, (int)index);
-	if (0 == rc) {
-		JOM(8, "newinput(.,%i) OK\n", (int)index);
-	} else {
-		SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		rc = newinput(peasycap, (int)index);
+		if (0 == rc) {
+			JOM(8, "newinput(.,%i) OK\n", (int)index);
+		} else {
+			SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_ENUMAUDIO: {
-	JOM(8, "VIDIOC_ENUMAUDIO\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
+	case VIDIOC_ENUMAUDIO: {
+		JOM(8, "VIDIOC_ENUMAUDIO\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
+	}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_ENUMAUDOUT: {
-	struct v4l2_audioout v4l2_audioout;
+	case VIDIOC_ENUMAUDOUT: {
+		struct v4l2_audioout v4l2_audioout;
 
-	JOM(8, "VIDIOC_ENUMAUDOUT\n");
+		JOM(8, "VIDIOC_ENUMAUDOUT\n");
 
-	if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
+		if (copy_from_user(&v4l2_audioout, (void __user *)arg,
 					sizeof(struct v4l2_audioout))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (0 != v4l2_audioout.index) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
-	v4l2_audioout.index = 0;
-	strcpy(&v4l2_audioout.name[0], "Soundtrack");
+		if (0 != v4l2_audioout.index) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
+		v4l2_audioout.index = 0;
+		strcpy(&v4l2_audioout.name[0], "Soundtrack");
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
-					sizeof(struct v4l2_audioout))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		if (copy_to_user((void __user *)arg, &v4l2_audioout,
+				sizeof(struct v4l2_audioout))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_QUERYCTRL: {
-	int i1;
-	struct v4l2_queryctrl v4l2_queryctrl;
+	case VIDIOC_QUERYCTRL: {
+		int i1;
+		struct v4l2_queryctrl v4l2_queryctrl;
 
-	JOM(8, "VIDIOC_QUERYCTRL\n");
+		JOM(8, "VIDIOC_QUERYCTRL\n");
 
-	if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
-					sizeof(struct v4l2_queryctrl))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
+				sizeof(struct v4l2_queryctrl))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	i1 = 0;
-	while (0xFFFFFFFF != easycap_control[i1].id) {
-		if (easycap_control[i1].id == v4l2_queryctrl.id) {
-			JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]" \
-				".name\n", &easycap_control[i1].name[0], i1);
-			memcpy(&v4l2_queryctrl, &easycap_control[i1], \
-						sizeof(struct v4l2_queryctrl));
-			break;
+		i1 = 0;
+		while (0xFFFFFFFF != easycap_control[i1].id) {
+			if (easycap_control[i1].id == v4l2_queryctrl.id) {
+				JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]"
+				    ".name\n", &easycap_control[i1].name[0], i1);
+				memcpy(&v4l2_queryctrl, &easycap_control[i1],
+				       sizeof(struct v4l2_queryctrl));
+				break;
+			}
+			i1++;
 		}
-		i1++;
+		if (0xFFFFFFFF == easycap_control[i1].id) {
+			JOM(8, "%i=index: exhausts controls\n", i1);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
+				sizeof(struct v4l2_queryctrl))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	if (0xFFFFFFFF == easycap_control[i1].id) {
-		JOM(8, "%i=index: exhausts controls\n", i1);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_QUERYMENU: {
+		JOM(8, "VIDIOC_QUERYMENU unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
-	if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
-					sizeof(struct v4l2_queryctrl))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_QUERYMENU: {
-	JOM(8, "VIDIOC_QUERYMENU unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_CTRL: {
-	struct v4l2_control *pv4l2_control;
-
-	JOM(8, "VIDIOC_G_CTRL\n");
-	pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
-	if (!pv4l2_control) {
-		SAM("ERROR: out of memory\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ENOMEM;
-	}
-	if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
-					sizeof(struct v4l2_control))) {
-		kfree(pv4l2_control);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+	case VIDIOC_G_CTRL: {
+		struct v4l2_control *pv4l2_control;
+
+		JOM(8, "VIDIOC_G_CTRL\n");
+		pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
+		if (!pv4l2_control) {
+			SAM("ERROR: out of memory\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ENOMEM;
+		}
+		if (0 != copy_from_user(pv4l2_control, (void __user *)arg,
+				sizeof(struct v4l2_control))) {
+			kfree(pv4l2_control);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	switch (pv4l2_control->id) {
-	case V4L2_CID_BRIGHTNESS: {
-		pv4l2_control->value = peasycap->brightness;
-		JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
-		break;
-	}
-	case V4L2_CID_CONTRAST: {
-		pv4l2_control->value = peasycap->contrast;
-		JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
-		break;
-	}
-	case V4L2_CID_SATURATION: {
-		pv4l2_control->value = peasycap->saturation;
-		JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
-		break;
-	}
-	case V4L2_CID_HUE: {
-		pv4l2_control->value = peasycap->hue;
-		JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
-		break;
-	}
-	case V4L2_CID_AUDIO_VOLUME: {
-		pv4l2_control->value = peasycap->volume;
-		JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
-		break;
-	}
-	case V4L2_CID_AUDIO_MUTE: {
-		if (1 == peasycap->mute)
-			pv4l2_control->value = true;
-		else
-			pv4l2_control->value = false;
-		JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
-		break;
-	}
-	default: {
-		SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
-							pv4l2_control->id);
-		kfree(pv4l2_control);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	}
-	if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
-					sizeof(struct v4l2_control))) {
+		switch (pv4l2_control->id) {
+		case V4L2_CID_BRIGHTNESS: {
+			pv4l2_control->value = peasycap->brightness;
+			JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
+			break;
+		}
+		case V4L2_CID_CONTRAST: {
+			pv4l2_control->value = peasycap->contrast;
+			JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
+			break;
+		}
+		case V4L2_CID_SATURATION: {
+			pv4l2_control->value = peasycap->saturation;
+			JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
+			break;
+		}
+		case V4L2_CID_HUE: {
+			pv4l2_control->value = peasycap->hue;
+			JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
+			break;
+		}
+		case V4L2_CID_AUDIO_VOLUME: {
+			pv4l2_control->value = peasycap->volume;
+			JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
+			break;
+		}
+		case V4L2_CID_AUDIO_MUTE: {
+			if (1 == peasycap->mute)
+				pv4l2_control->value = true;
+			else
+				pv4l2_control->value = false;
+			JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
+			break;
+		}
+		default: {
+			SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
+			    pv4l2_control->id);
+			kfree(pv4l2_control);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		}
+		if (copy_to_user((void __user *)arg, pv4l2_control,
+				sizeof(struct v4l2_control))) {
+			kfree(pv4l2_control);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 		kfree(pv4l2_control);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		break;
 	}
-	kfree(pv4l2_control);
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-#if defined(VIDIOC_S_CTRL_OLD)
-case VIDIOC_S_CTRL_OLD: {
-	JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
-}
-#endif /*VIDIOC_S_CTRL_OLD*/
-case VIDIOC_S_CTRL:
+	case VIDIOC_S_CTRL:
 	{
-	struct v4l2_control v4l2_control;
+		struct v4l2_control v4l2_control;
 
-	JOM(8, "VIDIOC_S_CTRL\n");
+		JOM(8, "VIDIOC_S_CTRL\n");
 
-	if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
-					sizeof(struct v4l2_control))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
+				sizeof(struct v4l2_control))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	switch (v4l2_control.id) {
-	case V4L2_CID_BRIGHTNESS: {
-		JOM(8, "user requests brightness %i\n", v4l2_control.value);
-		if (0 != adjust_brightness(peasycap, v4l2_control.value))
-			;
-		break;
-	}
-	case V4L2_CID_CONTRAST: {
-		JOM(8, "user requests contrast %i\n", v4l2_control.value);
-		if (0 != adjust_contrast(peasycap, v4l2_control.value))
-			;
-		break;
-	}
-	case V4L2_CID_SATURATION: {
-		JOM(8, "user requests saturation %i\n", v4l2_control.value);
-		if (0 != adjust_saturation(peasycap, v4l2_control.value))
-			;
-		break;
-	}
-	case V4L2_CID_HUE: {
-		JOM(8, "user requests hue %i\n", v4l2_control.value);
-		if (0 != adjust_hue(peasycap, v4l2_control.value))
-			;
-		break;
-	}
-	case V4L2_CID_AUDIO_VOLUME: {
-		JOM(8, "user requests volume %i\n", v4l2_control.value);
-		if (0 != adjust_volume(peasycap, v4l2_control.value))
-			;
-		break;
-	}
-	case V4L2_CID_AUDIO_MUTE: {
-		int mute;
+		switch (v4l2_control.id) {
+		case V4L2_CID_BRIGHTNESS: {
+			JOM(8, "user requests brightness %i\n", v4l2_control.value);
+			if (0 != adjust_brightness(peasycap, v4l2_control.value))
+				;
+			break;
+		}
+		case V4L2_CID_CONTRAST: {
+			JOM(8, "user requests contrast %i\n", v4l2_control.value);
+			if (0 != adjust_contrast(peasycap, v4l2_control.value))
+				;
+			break;
+		}
+		case V4L2_CID_SATURATION: {
+			JOM(8, "user requests saturation %i\n", v4l2_control.value);
+			if (0 != adjust_saturation(peasycap, v4l2_control.value))
+				;
+			break;
+		}
+		case V4L2_CID_HUE: {
+			JOM(8, "user requests hue %i\n", v4l2_control.value);
+			if (0 != adjust_hue(peasycap, v4l2_control.value))
+				;
+			break;
+		}
+		case V4L2_CID_AUDIO_VOLUME: {
+			JOM(8, "user requests volume %i\n", v4l2_control.value);
+			if (0 != adjust_volume(peasycap, v4l2_control.value))
+				;
+			break;
+		}
+		case V4L2_CID_AUDIO_MUTE: {
+			int mute;
 
-		JOM(8, "user requests mute %i\n", v4l2_control.value);
-		if (true == v4l2_control.value)
-			mute = 1;
-		else
-			mute = 0;
+			JOM(8, "user requests mute %i\n", v4l2_control.value);
+			if (v4l2_control.value)
+				mute = 1;
+			else
+				mute = 0;
 
-		if (0 != adjust_mute(peasycap, mute))
-			SAM("WARNING: failed to adjust mute to %i\n", mute);
+			if (0 != adjust_mute(peasycap, mute))
+				SAM("WARNING: failed to adjust mute to %i\n", mute);
+			break;
+		}
+		default: {
+			SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
+			    v4l2_control.id);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		}
 		break;
 	}
-	default: {
-		SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
-							v4l2_control.id);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	}
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_S_EXT_CTRLS: {
-	JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_ENUM_FMT: {
-	__u32 index;
-	struct v4l2_fmtdesc v4l2_fmtdesc;
-
-	JOM(8, "VIDIOC_ENUM_FMT\n");
-
-	if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
-					sizeof(struct v4l2_fmtdesc))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
-
-	index = v4l2_fmtdesc.index;
-	memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
-
-	v4l2_fmtdesc.index = index;
-	v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-	switch (index) {
-	case 0: {
-		v4l2_fmtdesc.flags = 0;
-		strcpy(&v4l2_fmtdesc.description[0], "uyvy");
-		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
-		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-		break;
-	}
-	case 1: {
-		v4l2_fmtdesc.flags = 0;
-		strcpy(&v4l2_fmtdesc.description[0], "yuy2");
-		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
-		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-		break;
-	}
-	case 2: {
-		v4l2_fmtdesc.flags = 0;
-		strcpy(&v4l2_fmtdesc.description[0], "rgb24");
-		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
-		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-		break;
-	}
-	case 3: {
-		v4l2_fmtdesc.flags = 0;
-		strcpy(&v4l2_fmtdesc.description[0], "rgb32");
-		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
-		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-		break;
-	}
-	case 4: {
-		v4l2_fmtdesc.flags = 0;
-		strcpy(&v4l2_fmtdesc.description[0], "bgr24");
-		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
-		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-		break;
-	}
-	case 5: {
-		v4l2_fmtdesc.flags = 0;
-		strcpy(&v4l2_fmtdesc.description[0], "bgr32");
-		v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
-		JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-		break;
-	}
-	default: {
-		JOM(8, "%i=index: exhausts formats\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+	case VIDIOC_S_EXT_CTRLS: {
+		JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 		return -EINVAL;
 	}
-	}
-	if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
-					sizeof(struct v4l2_fmtdesc))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*
- *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
- *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
-*/
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_ENUM_FRAMESIZES: {
-	__u32 index;
-	struct v4l2_frmsizeenum v4l2_frmsizeenum;
+	case VIDIOC_ENUM_FMT: {
+		u32 index;
+		struct v4l2_fmtdesc v4l2_fmtdesc;
 
-	JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
+		JOM(8, "VIDIOC_ENUM_FMT\n");
 
-	if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
-					sizeof(struct v4l2_frmsizeenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
+				sizeof(struct v4l2_fmtdesc))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	index = v4l2_frmsizeenum.index;
+		index = v4l2_fmtdesc.index;
+		memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
 
-	v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;
+		v4l2_fmtdesc.index = index;
+		v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-	if (true == peasycap->ntsc) {
 		switch (index) {
 		case 0: {
-			v4l2_frmsizeenum.discrete.width = 640;
-			v4l2_frmsizeenum.discrete.height = 480;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						 discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
+			v4l2_fmtdesc.flags = 0;
+			strcpy(&v4l2_fmtdesc.description[0], "uyvy");
+			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
+			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 			break;
 		}
 		case 1: {
-			v4l2_frmsizeenum.discrete.width = 320;
-			v4l2_frmsizeenum.discrete.height = 240;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
+			v4l2_fmtdesc.flags = 0;
+			strcpy(&v4l2_fmtdesc.description[0], "yuy2");
+			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
+			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 			break;
 		}
 		case 2: {
-			v4l2_frmsizeenum.discrete.width = 720;
-			v4l2_frmsizeenum.discrete.height = 480;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
+			v4l2_fmtdesc.flags = 0;
+			strcpy(&v4l2_fmtdesc.description[0], "rgb24");
+			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
+			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 			break;
 		}
 		case 3: {
-			v4l2_frmsizeenum.discrete.width = 360;
-			v4l2_frmsizeenum.discrete.height = 240;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
-			break;
-		}
-		default: {
-			JOM(8, "%i=index: exhausts framesizes\n", index);
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
-			return -EINVAL;
-		}
-		}
-	} else {
-		switch (index) {
-		case 0: {
-			v4l2_frmsizeenum.discrete.width = 640;
-			v4l2_frmsizeenum.discrete.height = 480;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
-			break;
-		}
-		case 1: {
-			v4l2_frmsizeenum.discrete.width = 320;
-			v4l2_frmsizeenum.discrete.height = 240;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
+			v4l2_fmtdesc.flags = 0;
+			strcpy(&v4l2_fmtdesc.description[0], "rgb32");
+			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
+			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 			break;
 		}
-		case 2: {
-			v4l2_frmsizeenum.discrete.width = 704;
-			v4l2_frmsizeenum.discrete.height = 576;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
-			break;
-		}
-		case 3: {
-			v4l2_frmsizeenum.discrete.width = 720;
-			v4l2_frmsizeenum.discrete.height = 576;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
+		case 4: {
+			v4l2_fmtdesc.flags = 0;
+			strcpy(&v4l2_fmtdesc.description[0], "bgr24");
+			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
+			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 			break;
 		}
-		case 4: {
-			v4l2_frmsizeenum.discrete.width = 360;
-			v4l2_frmsizeenum.discrete.height = 288;
-			JOM(8, "%i=index: %ix%i\n", index, \
-					(int)(v4l2_frmsizeenum.\
-						discrete.width), \
-					(int)(v4l2_frmsizeenum.\
-						discrete.height));
+		case 5: {
+			v4l2_fmtdesc.flags = 0;
+			strcpy(&v4l2_fmtdesc.description[0], "bgr32");
+			v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
+			JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
 			break;
 		}
 		default: {
-			JOM(8, "%i=index: exhausts framesizes\n", index);
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
+			JOM(8, "%i=index: exhausts formats\n", index);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -EINVAL;
 		}
 		}
+		if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
+				sizeof(struct v4l2_fmtdesc))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
-					sizeof(struct v4l2_frmsizeenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 /*
- *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
- *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
-*/
+	 *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
+	 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
+	*/
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_ENUM_FRAMEINTERVALS: {
-	__u32 index;
-	int denominator;
-	struct v4l2_frmivalenum v4l2_frmivalenum;
+	case VIDIOC_ENUM_FRAMESIZES: {
+		u32 index;
+		struct v4l2_frmsizeenum v4l2_frmsizeenum;
 
-	JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
+		JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
 
-	if (peasycap->fps)
-		denominator = peasycap->fps;
-	else {
-		if (true == peasycap->ntsc)
-			denominator = 30;
-		else
-			denominator = 25;
-	}
+		if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
+				sizeof(struct v4l2_frmsizeenum))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
-					sizeof(struct v4l2_frmivalenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		index = v4l2_frmsizeenum.index;
+
+		v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
+
+		if (peasycap->ntsc) {
+			switch (index) {
+			case 0: {
+				v4l2_frmsizeenum.discrete.width = 640;
+				v4l2_frmsizeenum.discrete.height = 480;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 1: {
+				v4l2_frmsizeenum.discrete.width = 320;
+				v4l2_frmsizeenum.discrete.height = 240;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 2: {
+				v4l2_frmsizeenum.discrete.width = 720;
+				v4l2_frmsizeenum.discrete.height = 480;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 3: {
+				v4l2_frmsizeenum.discrete.width = 360;
+				v4l2_frmsizeenum.discrete.height = 240;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			default: {
+				JOM(8, "%i=index: exhausts framesizes\n", index);
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+				return -EINVAL;
+			}
+			}
+		} else {
+			switch (index) {
+			case 0: {
+				v4l2_frmsizeenum.discrete.width = 640;
+				v4l2_frmsizeenum.discrete.height = 480;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 1: {
+				v4l2_frmsizeenum.discrete.width = 320;
+				v4l2_frmsizeenum.discrete.height = 240;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 2: {
+				v4l2_frmsizeenum.discrete.width = 704;
+				v4l2_frmsizeenum.discrete.height = 576;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 3: {
+				v4l2_frmsizeenum.discrete.width = 720;
+				v4l2_frmsizeenum.discrete.height = 576;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			case 4: {
+				v4l2_frmsizeenum.discrete.width = 360;
+				v4l2_frmsizeenum.discrete.height = 288;
+				JOM(8, "%i=index: %ix%i\n", index,
+				    (int)(v4l2_frmsizeenum.
+					  discrete.width),
+				    (int)(v4l2_frmsizeenum.
+					  discrete.height));
+				break;
+			}
+			default: {
+				JOM(8, "%i=index: exhausts framesizes\n", index);
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+				return -EINVAL;
+			}
+			}
+		}
+		if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
+				sizeof(struct v4l2_frmsizeenum))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+/*
+	 *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
+	 *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
+	*/
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_ENUM_FRAMEINTERVALS: {
+		u32 index;
+		int denominator;
+		struct v4l2_frmivalenum v4l2_frmivalenum;
+
+		JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
+
+		if (peasycap->fps)
+			denominator = peasycap->fps;
+		else {
+			if (peasycap->ntsc)
+				denominator = 30;
+			else
+				denominator = 25;
+		}
 
-	index = v4l2_frmivalenum.index;
+		if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
+				sizeof(struct v4l2_frmivalenum))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;
+		index = v4l2_frmivalenum.index;
 
-	switch (index) {
-	case 0: {
-		v4l2_frmivalenum.discrete.numerator = 1;
-		v4l2_frmivalenum.discrete.denominator = denominator;
-		JOM(8, "%i=index: %i/%i\n", index, \
-			(int)(v4l2_frmivalenum.discrete.numerator), \
-			(int)(v4l2_frmivalenum.discrete.denominator));
-		break;
-	}
-	case 1: {
-		v4l2_frmivalenum.discrete.numerator = 1;
-		v4l2_frmivalenum.discrete.denominator = denominator/5;
-		JOM(8, "%i=index: %i/%i\n", index, \
-			(int)(v4l2_frmivalenum.discrete.numerator), \
-			(int)(v4l2_frmivalenum.discrete.denominator));
-		break;
-	}
-	default: {
-		JOM(8, "%i=index: exhausts frameintervals\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	}
-	if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
+		v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
+
+		switch (index) {
+		case 0: {
+			v4l2_frmivalenum.discrete.numerator = 1;
+			v4l2_frmivalenum.discrete.denominator = denominator;
+			JOM(8, "%i=index: %i/%i\n", index,
+			    (int)(v4l2_frmivalenum.discrete.numerator),
+			    (int)(v4l2_frmivalenum.discrete.denominator));
+			break;
+		}
+		case 1: {
+			v4l2_frmivalenum.discrete.numerator = 1;
+			v4l2_frmivalenum.discrete.denominator = denominator/5;
+			JOM(8, "%i=index: %i/%i\n", index,
+			    (int)(v4l2_frmivalenum.discrete.numerator),
+			    (int)(v4l2_frmivalenum.discrete.denominator));
+			break;
+		}
+		default: {
+			JOM(8, "%i=index: exhausts frameintervals\n", index);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		}
+		if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
 					sizeof(struct v4l2_frmivalenum))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_FMT: {
-	struct v4l2_format *pv4l2_format;
-	struct v4l2_pix_format *pv4l2_pix_format;
-
-	JOM(8, "VIDIOC_G_FMT\n");
-	pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
-	if (!pv4l2_format) {
-		SAM("ERROR: out of memory\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ENOMEM;
-	}
-	pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
-	if (!pv4l2_pix_format) {
-		SAM("ERROR: out of memory\n");
-		kfree(pv4l2_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ENOMEM;
-	}
-	if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
+	case VIDIOC_G_FMT: {
+		struct v4l2_format *pv4l2_format;
+		struct v4l2_pix_format *pv4l2_pix_format;
+
+		JOM(8, "VIDIOC_G_FMT\n");
+		pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
+		if (!pv4l2_format) {
+			SAM("ERROR: out of memory\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ENOMEM;
+		}
+		pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
+		if (!pv4l2_pix_format) {
+			SAM("ERROR: out of memory\n");
+			kfree(pv4l2_format);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ENOMEM;
+		}
+		if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
 					sizeof(struct v4l2_format))) {
-		kfree(pv4l2_format);
-		kfree(pv4l2_pix_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			kfree(pv4l2_format);
+			kfree(pv4l2_pix_format);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		kfree(pv4l2_format);
-		kfree(pv4l2_pix_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
+		if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			kfree(pv4l2_format);
+			kfree(pv4l2_pix_format);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
 
-	memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
-	pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	memcpy(&pv4l2_format->fmt.pix, \
-			 &easycap_format[peasycap->format_offset]\
-			.v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
-	JOM(8, "user is told: %s\n", \
-			&easycap_format[peasycap->format_offset].name[0]);
+		memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
+		pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		memcpy(&pv4l2_format->fmt.pix,
+		       &easycap_format[peasycap->format_offset]
+		       .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
+		JOM(8, "user is told: %s\n",
+		    &easycap_format[peasycap->format_offset].name[0]);
 
-	if (0 != copy_to_user((void __user *)arg, pv4l2_format, \
+		if (copy_to_user((void __user *)arg, pv4l2_format,
 					sizeof(struct v4l2_format))) {
+			kfree(pv4l2_format);
+			kfree(pv4l2_pix_format);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 		kfree(pv4l2_format);
 		kfree(pv4l2_pix_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		break;
 	}
-	kfree(pv4l2_format);
-	kfree(pv4l2_pix_format);
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_TRY_FMT:
-case VIDIOC_S_FMT: {
-	struct v4l2_format v4l2_format;
-	struct v4l2_pix_format v4l2_pix_format;
-	bool try;
-	int best_format;
-
-	if (VIDIOC_TRY_FMT == cmd) {
-		JOM(8, "VIDIOC_TRY_FMT\n");
-		try = true;
-	} else {
-		JOM(8, "VIDIOC_S_FMT\n");
-		try = false;
-	}
+	case VIDIOC_TRY_FMT:
+	case VIDIOC_S_FMT: {
+		struct v4l2_format v4l2_format;
+		struct v4l2_pix_format v4l2_pix_format;
+		bool try;
+		int best_format;
+
+		if (VIDIOC_TRY_FMT == cmd) {
+			JOM(8, "VIDIOC_TRY_FMT\n");
+			try = true;
+		} else {
+			JOM(8, "VIDIOC_S_FMT\n");
+			try = false;
+		}
 
-	if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
+		if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
 					sizeof(struct v4l2_format))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	best_format = adjust_format(peasycap, \
-					v4l2_format.fmt.pix.width, \
-					v4l2_format.fmt.pix.height, \
-					v4l2_format.fmt.pix.pixelformat, \
-					v4l2_format.fmt.pix.field, \
+		best_format = adjust_format(peasycap,
+					v4l2_format.fmt.pix.width,
+					v4l2_format.fmt.pix.height,
+					v4l2_format.fmt.pix.pixelformat,
+					v4l2_format.fmt.pix.field,
 					try);
-	if (0 > best_format) {
-		if (-EBUSY == best_format) {
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
-			return -EBUSY;
+		if (0 > best_format) {
+			if (-EBUSY == best_format) {
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+				return -EBUSY;
+			}
+			JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ENOENT;
 		}
-		JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ENOENT;
-	}
 /*...........................................................................*/
-	memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
-	v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
+		v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 
-	memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\
-			.v4l2_format.fmt.pix), sizeof(v4l2_pix_format));
-	JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
+		memcpy(&(v4l2_format.fmt.pix),
+			&(easycap_format[best_format].v4l2_format.fmt.pix),
+			sizeof(v4l2_pix_format));
+		JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
+		if (copy_to_user((void __user *)arg, &v4l2_format,
 					sizeof(struct v4l2_format))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_CROPCAP: {
-	struct v4l2_cropcap v4l2_cropcap;
+	case VIDIOC_CROPCAP: {
+		struct v4l2_cropcap v4l2_cropcap;
 
-	JOM(8, "VIDIOC_CROPCAP\n");
+		JOM(8, "VIDIOC_CROPCAP\n");
 
-	if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
+		if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
 					sizeof(struct v4l2_cropcap))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
-
-	if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
-
-	memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
-	v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	v4l2_cropcap.bounds.left      = 0;
-	v4l2_cropcap.bounds.top       = 0;
-	v4l2_cropcap.bounds.width     = peasycap->width;
-	v4l2_cropcap.bounds.height    = peasycap->height;
-	v4l2_cropcap.defrect.left     = 0;
-	v4l2_cropcap.defrect.top      = 0;
-	v4l2_cropcap.defrect.width    = peasycap->width;
-	v4l2_cropcap.defrect.height   = peasycap->height;
-	v4l2_cropcap.pixelaspect.numerator = 1;
-	v4l2_cropcap.pixelaspect.denominator = 1;
-
-	JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
+		if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+
+		memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
+		v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		v4l2_cropcap.bounds.left      = 0;
+		v4l2_cropcap.bounds.top       = 0;
+		v4l2_cropcap.bounds.width     = peasycap->width;
+		v4l2_cropcap.bounds.height    = peasycap->height;
+		v4l2_cropcap.defrect.left     = 0;
+		v4l2_cropcap.defrect.top      = 0;
+		v4l2_cropcap.defrect.width    = peasycap->width;
+		v4l2_cropcap.defrect.height   = peasycap->height;
+		v4l2_cropcap.pixelaspect.numerator = 1;
+		v4l2_cropcap.pixelaspect.denominator = 1;
+
+		JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
+
+		if (copy_to_user((void __user *)arg, &v4l2_cropcap,
 					sizeof(struct v4l2_cropcap))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_CROP:
-case VIDIOC_S_CROP: {
-	JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_QUERYSTD: {
-	JOM(8, "VIDIOC_QUERYSTD: " \
-			"EasyCAP is incapable of detecting standard\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*---------------------------------------------------------------------------*/
-/*
- *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
- *  FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
- *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
- */
-/*---------------------------------------------------------------------------*/
-case VIDIOC_ENUMSTD: {
-	int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
-	struct v4l2_standard v4l2_standard;
-	__u32 index;
-	struct easycap_standard const *peasycap_standard;
-
-	JOM(8, "VIDIOC_ENUMSTD\n");
-
-	if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
-					sizeof(struct v4l2_standard))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+	case VIDIOC_G_CROP:
+	case VIDIOC_S_CROP: {
+		JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	index = v4l2_standard.index;
-
-	last3 = last2; last2 = last1; last1 = last0; last0 = index;
-	if ((index == last3) && (index == last2) && \
-			(index == last1) && (index == last0)) {
-		index++;
-		last3 = last2; last2 = last1; last1 = last0; last0 = index;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_QUERYSTD: {
+		JOM(8, "VIDIOC_QUERYSTD: "
+		    "EasyCAP is incapable of detecting standard\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
+		break;
 	}
+	/*-------------------------------------------------------------------*/
+	/*
+	 *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3
+	 *  CONSTITUTE A WORKAROUND *  FOR WHAT APPEARS TO BE
+	 *  A BUG IN 64-BIT mplayer.
+	 *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
+	 */
+	/*------------------------------------------------------------------*/
+	case VIDIOC_ENUMSTD: {
+		int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
+		struct v4l2_standard v4l2_standard;
+		u32 index;
+		struct easycap_standard const *peasycap_standard;
+
+		JOM(8, "VIDIOC_ENUMSTD\n");
+
+		if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
+					sizeof(struct v4l2_standard))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		index = v4l2_standard.index;
+
+		last3 = last2;
+		last2 = last1;
+		last1 = last0;
+		last0 = index;
+		if ((index == last3) && (index == last2) &&
+		    (index == last1) && (index == last0)) {
+			index++;
+			last3 = last2;
+			last2 = last1;
+			last1 = last0;
+			last0 = index;
+		}
 
-	memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
+		memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
 
-	peasycap_standard = &easycap_standard[0];
-	while (0xFFFF != peasycap_standard->mask) {
-		if ((int)(peasycap_standard - &easycap_standard[0]) == index)
-			break;
-		peasycap_standard++;
-	}
-	if (0xFFFF == peasycap_standard->mask) {
-		JOM(8, "%i=index: exhausts standards\n", index);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	JOM(8, "%i=index: %s\n", index, \
-				&(peasycap_standard->v4l2_standard.name[0]));
-	memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), \
-					sizeof(struct v4l2_standard));
+		peasycap_standard = &easycap_standard[0];
+		while (0xFFFF != peasycap_standard->mask) {
+			if ((int)(peasycap_standard - &easycap_standard[0]) == index)
+				break;
+			peasycap_standard++;
+		}
+		if (0xFFFF == peasycap_standard->mask) {
+			JOM(8, "%i=index: exhausts standards\n", index);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		JOM(8, "%i=index: %s\n", index,
+		    &(peasycap_standard->v4l2_standard.name[0]));
+		memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
+		       sizeof(struct v4l2_standard));
 
-	v4l2_standard.index = index;
+		v4l2_standard.index = index;
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
-					sizeof(struct v4l2_standard))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		if (copy_to_user((void __user *)arg, &v4l2_standard,
+				sizeof(struct v4l2_standard))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_STD: {
-	v4l2_std_id std_id;
-	struct easycap_standard const *peasycap_standard;
+	case VIDIOC_G_STD: {
+		v4l2_std_id std_id;
+		struct easycap_standard const *peasycap_standard;
 
-	JOM(8, "VIDIOC_G_STD\n");
+		JOM(8, "VIDIOC_G_STD\n");
 
-	if (0 > peasycap->standard_offset) {
-		JOM(8, "%i=peasycap->standard_offset\n", \
-					peasycap->standard_offset);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EBUSY;
-	}
+		if (0 > peasycap->standard_offset) {
+			JOM(8, "%i=peasycap->standard_offset\n",
+			    peasycap->standard_offset);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EBUSY;
+		}
 
-	if (0 != copy_from_user(&std_id, (void __user *)arg, \
-						sizeof(v4l2_std_id))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&std_id, (void __user *)arg,
+					sizeof(v4l2_std_id))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	peasycap_standard = &easycap_standard[peasycap->standard_offset];
-	std_id = peasycap_standard->v4l2_standard.id;
+		peasycap_standard = &easycap_standard[peasycap->standard_offset];
+		std_id = peasycap_standard->v4l2_standard.id;
 
-	JOM(8, "user is told: %s\n", \
-				&peasycap_standard->v4l2_standard.name[0]);
+		JOM(8, "user is told: %s\n",
+		    &peasycap_standard->v4l2_standard.name[0]);
 
-	if (0 != copy_to_user((void __user *)arg, &std_id, \
-						sizeof(v4l2_std_id))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		if (copy_to_user((void __user *)arg, &std_id,
+					sizeof(v4l2_std_id))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_S_STD: {
-	v4l2_std_id std_id;
-	int rc;
+	case VIDIOC_S_STD: {
+		v4l2_std_id std_id;
+		int rc;
 
-	JOM(8, "VIDIOC_S_STD\n");
+		JOM(8, "VIDIOC_S_STD\n");
 
-	if (0 != copy_from_user(&std_id, (void __user *)arg, \
-						sizeof(v4l2_std_id))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&std_id, (void __user *)arg,
+					sizeof(v4l2_std_id))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	JOM(8, "User requests standard: 0x%08X%08X\n", \
-		(int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
-		(int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
+		JOM(8, "User requests standard: 0x%08X%08X\n",
+		    (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
+		    (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
 
-	rc = adjust_standard(peasycap, std_id);
-	if (0 > rc) {
-		JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ENOENT;
+		rc = adjust_standard(peasycap, std_id);
+		if (0 > rc) {
+			JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ENOENT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_REQBUFS: {
-	int nbuffers;
-	struct v4l2_requestbuffers v4l2_requestbuffers;
+	case VIDIOC_REQBUFS: {
+		int nbuffers;
+		struct v4l2_requestbuffers v4l2_requestbuffers;
 
-	JOM(8, "VIDIOC_REQBUFS\n");
+		JOM(8, "VIDIOC_REQBUFS\n");
 
-	if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
-				sizeof(struct v4l2_requestbuffers))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (0 != copy_from_user(&v4l2_requestbuffers,
+					(void __user *)arg,
+					sizeof(struct v4l2_requestbuffers))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	nbuffers = v4l2_requestbuffers.count;
-	JOM(8, "                   User requests %i buffers ...\n", nbuffers);
-	if (nbuffers < 2)
-		nbuffers = 2;
-	if (nbuffers > FRAME_BUFFER_MANY)
-		nbuffers = FRAME_BUFFER_MANY;
-	if (v4l2_requestbuffers.count == nbuffers) {
-		JOM(8, "                   ... agree to  %i buffers\n", \
-								nbuffers);
-	} else {
-		JOM(8, "                  ... insist on  %i buffers\n", \
-								nbuffers);
-		v4l2_requestbuffers.count = nbuffers;
-	}
-	peasycap->frame_buffer_many = nbuffers;
+		if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		nbuffers = v4l2_requestbuffers.count;
+		JOM(8, "                   User requests %i buffers ...\n", nbuffers);
+		if (nbuffers < 2)
+			nbuffers = 2;
+		if (nbuffers > FRAME_BUFFER_MANY)
+			nbuffers = FRAME_BUFFER_MANY;
+		if (v4l2_requestbuffers.count == nbuffers) {
+			JOM(8, "                   ... agree to  %i buffers\n",
+			    nbuffers);
+		} else {
+			JOM(8, "                  ... insist on  %i buffers\n",
+			    nbuffers);
+			v4l2_requestbuffers.count = nbuffers;
+		}
+		peasycap->frame_buffer_many = nbuffers;
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
-				sizeof(struct v4l2_requestbuffers))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
+					sizeof(struct v4l2_requestbuffers))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_QUERYBUF: {
-	__u32 index;
-	struct v4l2_buffer v4l2_buffer;
+	case VIDIOC_QUERYBUF: {
+		u32 index;
+		struct v4l2_buffer v4l2_buffer;
 
-	JOM(8, "VIDIOC_QUERYBUF\n");
+		JOM(8, "VIDIOC_QUERYBUF\n");
 
-	if (peasycap->video_eof) {
-		JOM(8, "returning -EIO because  %i=video_eof\n", \
-							peasycap->video_eof);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EIO;
-	}
+		if (peasycap->video_eof) {
+			JOM(8, "returning -EIO because  %i=video_eof\n",
+			    peasycap->video_eof);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EIO;
+		}
 
-	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
+		if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	index = v4l2_buffer.index;
-	if (index < 0 || index >= peasycap->frame_buffer_many)
-		return -EINVAL;
-	memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
-	v4l2_buffer.index = index;
-	v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	v4l2_buffer.bytesused = peasycap->frame_buffer_used;
-	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
-						peasycap->done[index] | \
-						peasycap->queued[index];
-	v4l2_buffer.field = V4L2_FIELD_NONE;
-	v4l2_buffer.memory = V4L2_MEMORY_MMAP;
-	v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
-	v4l2_buffer.length = FRAME_BUFFER_SIZE;
-
-	JOM(16, "  %10i=index\n", v4l2_buffer.index);
-	JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
-	JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
-	JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
-	JOM(16, "  %10i=field\n", v4l2_buffer.field);
-	JOM(16, "  %10li=timestamp.tv_usec\n", \
-					 (long)v4l2_buffer.timestamp.tv_usec);
-	JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
-	JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
-	JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
-	JOM(16, "  %10i=length\n", v4l2_buffer.length);
-
-	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
+		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		index = v4l2_buffer.index;
+		if (index < 0 || index >= peasycap->frame_buffer_many)
+			return -EINVAL;
+		memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
+		v4l2_buffer.index = index;
+		v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		v4l2_buffer.bytesused = peasycap->frame_buffer_used;
+		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
+					peasycap->done[index] |
+					peasycap->queued[index];
+		v4l2_buffer.field = V4L2_FIELD_NONE;
+		v4l2_buffer.memory = V4L2_MEMORY_MMAP;
+		v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
+		v4l2_buffer.length = FRAME_BUFFER_SIZE;
+
+		JOM(16, "  %10i=index\n", v4l2_buffer.index);
+		JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
+		JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
+		JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
+		JOM(16, "  %10i=field\n", v4l2_buffer.field);
+		JOM(16, "  %10li=timestamp.tv_usec\n",
+		    (long)v4l2_buffer.timestamp.tv_usec);
+		JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
+		JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
+		JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
+		JOM(16, "  %10i=length\n", v4l2_buffer.length);
+
+		if (copy_to_user((void __user *)arg, &v4l2_buffer,
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_QBUF: {
-	struct v4l2_buffer v4l2_buffer;
+	case VIDIOC_QBUF: {
+		struct v4l2_buffer v4l2_buffer;
 
-	JOM(8, "VIDIOC_QBUF\n");
+		JOM(8, "VIDIOC_QBUF\n");
 
-	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
+		if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	if (v4l2_buffer.index < 0 || \
-		 (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
+		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		if (v4l2_buffer.index < 0 ||
+		    v4l2_buffer.index >= peasycap->frame_buffer_many) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
 
-	peasycap->done[v4l2_buffer.index]   = 0;
-	peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
+		peasycap->done[v4l2_buffer.index]   = 0;
+		peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
 
-	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
+		if (copy_to_user((void __user *)arg, &v4l2_buffer,
 					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	JOM(8, ".....   user queueing frame buffer %i\n", \
-						(int)v4l2_buffer.index);
+		JOM(8, ".....   user queueing frame buffer %i\n",
+		    (int)v4l2_buffer.index);
 
-	peasycap->frame_lock = 0;
+		peasycap->frame_lock = 0;
 
-	break;
-}
+		break;
+	}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_DQBUF:
+	case VIDIOC_DQBUF:
 	{
-#if defined(AUDIOTIME)
-	struct signed_div_result sdr;
-	long long int above, below, dnbydt, fudge, sll;
-	unsigned long long int ull;
-	struct timeval timeval8;
-	struct timeval timeval1;
-#endif /*AUDIOTIME*/
-	struct timeval timeval, timeval2;
-	int i, j;
-	struct v4l2_buffer v4l2_buffer;
-	int rcdq;
-	__u16 input;
-
-	JOM(8, "VIDIOC_DQBUF\n");
-
-	if ((peasycap->video_idle) || (peasycap->video_eof)) {
-		JOM(8, "returning -EIO because  " \
-				"%i=video_idle  %i=video_eof\n", \
-				peasycap->video_idle, peasycap->video_eof);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EIO;
-	}
-
-	if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
-					sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		struct timeval timeval, timeval2;
+		int i, j;
+		struct v4l2_buffer v4l2_buffer;
+		int rcdq;
+		u16 input;
+
+		JOM(8, "VIDIOC_DQBUF\n");
+
+		if ((peasycap->video_idle) || (peasycap->video_eof)) {
+			JOM(8, "returning -EIO because  "
+			    "%i=video_idle  %i=video_eof\n",
+			    peasycap->video_idle, peasycap->video_eof);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EIO;
+		}
 
-	if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
+		if (copy_from_user(&v4l2_buffer, (void __user *)arg,
+				  sizeof(struct v4l2_buffer))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (true == peasycap->offerfields) {
-		/*-----------------------------------------------------------*/
-		/*
-		 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
-		 *  V4L2_FIELD_BOTTOM
-		*/
-		/*-----------------------------------------------------------*/
-		if (V4L2_FIELD_TOP == v4l2_buffer.field)
-			JOM(8, "user wants V4L2_FIELD_TOP\n");
-		else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
-			JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
-		else if (V4L2_FIELD_ANY == v4l2_buffer.field)
-			JOM(8, "user wants V4L2_FIELD_ANY\n");
-		else
-			JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
-							v4l2_buffer.field);
-	}
+		if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
 
-	if (!peasycap->video_isoc_streaming) {
-		JOM(16, "returning -EIO because video urbs not streaming\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EIO;
-	}
-/*---------------------------------------------------------------------------*/
-/*
- *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
- *  THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE.  IN THIS
- *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
- */
-/*---------------------------------------------------------------------------*/
+		if (peasycap->offerfields) {
+			/*---------------------------------------------------*/
+			/*
+			 *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
+			 *  V4L2_FIELD_BOTTOM
+			 */
+			/*---------------------------------------------------*/
+			if (V4L2_FIELD_TOP == v4l2_buffer.field)
+				JOM(8, "user wants V4L2_FIELD_TOP\n");
+			else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
+				JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
+			else if (V4L2_FIELD_ANY == v4l2_buffer.field)
+				JOM(8, "user wants V4L2_FIELD_ANY\n");
+			else
+				JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
+				    v4l2_buffer.field);
+		}
 
-	if (!peasycap->polled) {
-		do {
-			rcdq = easycap_dqbuf(peasycap, 0);
-			if (-EIO == rcdq) {
-				JOM(8, "returning -EIO because " \
-						"dqbuf() returned -EIO\n");
-				mutex_unlock(&easycap_dongle[kd].mutex_video);
+		if (!peasycap->video_isoc_streaming) {
+			JOM(16, "returning -EIO because video urbs not streaming\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EIO;
+		}
+	/*-------------------------------------------------------------------*/
+	/*
+	 *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
+	 *  AS DETERMINED BY FINDING
+	 *  THE FLAG peasycap->polled SET, THERE MUST BE
+	 *  NO FURTHER WAIT HERE.  IN THIS
+	 *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
+	 */
+	/*-------------------------------------------------------------------*/
+
+		if (!peasycap->polled) {
+			do {
+				rcdq = easycap_dqbuf(peasycap, 0);
+				if (-EIO == rcdq) {
+					JOM(8, "returning -EIO because "
+					    "dqbuf() returned -EIO\n");
+					mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+					return -EIO;
+				}
+			} while (0 != rcdq);
+		} else {
+			if (peasycap->video_eof) {
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 				return -EIO;
 			}
-		} while (0 != rcdq);
-	} else {
-		if (peasycap->video_eof) {
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
-			return -EIO;
 		}
-	}
-	if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
-		SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
-					peasycap->done[peasycap->frame_read]);
-	}
-	peasycap->polled = 0;
-
-	if (!(peasycap->isequence % 10)) {
-		for (i = 0; i < 179; i++)
-			peasycap->merit[i] = peasycap->merit[i+1];
-		peasycap->merit[179] = merit_saa(peasycap->pusb_device);
-		j = 0;
-		for (i = 0; i < 180; i++)
-			j += peasycap->merit[i];
-		if (90 < j) {
-			SAM("easycap driver shutting down " \
-							"on condition blue\n");
-			peasycap->video_eof = 1; peasycap->audio_eof = 1;
+		if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
+			JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
+			    peasycap->done[peasycap->frame_read]);
+		}
+		peasycap->polled = 0;
+
+		if (!(peasycap->isequence % 10)) {
+			for (i = 0; i < 179; i++)
+				peasycap->merit[i] = peasycap->merit[i+1];
+			peasycap->merit[179] = merit_saa(peasycap->pusb_device);
+			j = 0;
+			for (i = 0; i < 180; i++)
+				j += peasycap->merit[i];
+			if (90 < j) {
+				SAM("easycap driver shutting down "
+				    "on condition blue\n");
+				peasycap->video_eof = 1;
+				peasycap->audio_eof = 1;
+			}
 		}
-	}
-
-	v4l2_buffer.index = peasycap->frame_read;
-	v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	v4l2_buffer.bytesused = peasycap->frame_buffer_used;
-	v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
-	if (true == peasycap->offerfields)
-		v4l2_buffer.field = V4L2_FIELD_BOTTOM;
-	else
-		v4l2_buffer.field = V4L2_FIELD_NONE;
-	do_gettimeofday(&timeval);
-	timeval2 = timeval;
 
-#if defined(AUDIOTIME)
-	if (!peasycap->timeval0.tv_sec) {
-		timeval8 = timeval;
-		timeval1 = timeval;
+		v4l2_buffer.index = peasycap->frame_read;
+		v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		v4l2_buffer.bytesused = peasycap->frame_buffer_used;
+		v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
+		if (peasycap->offerfields)
+			v4l2_buffer.field = V4L2_FIELD_BOTTOM;
+		else
+			v4l2_buffer.field = V4L2_FIELD_NONE;
+		do_gettimeofday(&timeval);
 		timeval2 = timeval;
-		dnbydt = 192000;
-		peasycap->timeval0 = timeval8;
-	} else {
-		dnbydt = peasycap->dnbydt;
-		timeval1 = peasycap->timeval1;
-		above = dnbydt * MICROSECONDS(timeval, timeval1);
-		below = 192000;
-		sdr = signed_div(above, below);
-
-		above = sdr.quotient + timeval1.tv_usec - 350000;
-
-		below = 1000000;
-		sdr = signed_div(above, below);
-		timeval2.tv_usec = sdr.remainder;
-		timeval2.tv_sec = timeval1.tv_sec + sdr.quotient;
-	}
-	if (!(peasycap->isequence % 500)) {
-		fudge = ((long long int)(1000000)) * \
-				((long long int)(timeval.tv_sec - \
-						timeval2.tv_sec)) + \
-				(long long int)(timeval.tv_usec - \
-						timeval2.tv_usec);
-		sdr = signed_div(fudge, 1000);
-		sll = sdr.quotient;
-		ull = sdr.remainder;
-
-		SAM("%5lli.%-3lli=ms timestamp fudge\n", sll, ull);
-	}
-#endif /*AUDIOTIME*/
-
-	v4l2_buffer.timestamp = timeval2;
-	v4l2_buffer.sequence = peasycap->isequence++;
-	v4l2_buffer.memory = V4L2_MEMORY_MMAP;
-	v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
-	v4l2_buffer.length = FRAME_BUFFER_SIZE;
-
-	JOM(16, "  %10i=index\n", v4l2_buffer.index);
-	JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
-	JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
-	JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
-	JOM(16, "  %10i=field\n", v4l2_buffer.field);
-	JOM(16, "  %10li=timestamp.tv_sec\n", \
-					(long)v4l2_buffer.timestamp.tv_sec);
-	JOM(16, "  %10li=timestamp.tv_usec\n", \
-					(long)v4l2_buffer.timestamp.tv_usec);
-	JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
-	JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
-	JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
-	JOM(16, "  %10i=length\n", v4l2_buffer.length);
-
-	if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
-						sizeof(struct v4l2_buffer))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
 
-	input = peasycap->frame_buffer[peasycap->frame_read][0].input;
-	if (0x08 & input) {
-		JOM(8, "user is offered frame buffer %i, input %i\n", \
-					peasycap->frame_read, (0x07 & input));
-	} else {
-		JOM(8, "user is offered frame buffer %i\n", \
-							peasycap->frame_read);
-	}
-	peasycap->frame_lock = 1;
-	JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
-	if (peasycap->frame_read == peasycap->frame_fill) {
-		if (peasycap->frame_lock) {
-			JOM(8, "WORRY:  filling frame buffer " \
-						"while offered to user\n");
+		v4l2_buffer.timestamp = timeval2;
+		v4l2_buffer.sequence = peasycap->isequence++;
+		v4l2_buffer.memory = V4L2_MEMORY_MMAP;
+		v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
+		v4l2_buffer.length = FRAME_BUFFER_SIZE;
+
+		JOM(16, "  %10i=index\n", v4l2_buffer.index);
+		JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
+		JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
+		JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
+		JOM(16, "  %10i=field\n", v4l2_buffer.field);
+		JOM(16, "  %10li=timestamp.tv_sec\n",
+		    (long)v4l2_buffer.timestamp.tv_sec);
+		JOM(16, "  %10li=timestamp.tv_usec\n",
+		    (long)v4l2_buffer.timestamp.tv_usec);
+		JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
+		JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
+		JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
+		JOM(16, "  %10i=length\n", v4l2_buffer.length);
+
+		if (copy_to_user((void __user *)arg, &v4l2_buffer,
+					sizeof(struct v4l2_buffer))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+
+		input = peasycap->frame_buffer[peasycap->frame_read][0].input;
+		if (0x08 & input) {
+			JOM(8, "user is offered frame buffer %i, input %i\n",
+			    peasycap->frame_read, (0x07 & input));
+		} else {
+			JOM(8, "user is offered frame buffer %i\n",
+			    peasycap->frame_read);
+		}
+		peasycap->frame_lock = 1;
+		JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
+		if (peasycap->frame_read == peasycap->frame_fill) {
+			if (peasycap->frame_lock) {
+				JOM(8, "WORRY:  filling frame buffer "
+				    "while offered to user\n");
+			}
 		}
+		break;
 	}
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_STREAMON: {
-	int i;
+	case VIDIOC_STREAMON: {
+		int i;
 
-	JOM(8, "VIDIOC_STREAMON\n");
+		JOM(8, "VIDIOC_STREAMON\n");
 
-	peasycap->isequence = 0;
-	for (i = 0; i < 180; i++)
-		peasycap->merit[i] = 0;
-	if ((struct usb_device *)NULL == peasycap->pusb_device) {
-		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		peasycap->isequence = 0;
+		for (i = 0; i < 180; i++)
+			peasycap->merit[i] = 0;
+		if (!peasycap->pusb_device) {
+			SAM("ERROR: peasycap->pusb_device is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
+		submit_video_urbs(peasycap);
+		peasycap->video_idle = 0;
+		peasycap->audio_idle = 0;
+		peasycap->video_eof = 0;
+		peasycap->audio_eof = 0;
+		break;
 	}
-	submit_video_urbs(peasycap);
-	peasycap->video_idle = 0;
-	peasycap->audio_idle = 0;
-	peasycap->video_eof = 0;
-	peasycap->audio_eof = 0;
-	break;
-}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_STREAMOFF: {
-	JOM(8, "VIDIOC_STREAMOFF\n");
+	case VIDIOC_STREAMOFF: {
+		JOM(8, "VIDIOC_STREAMOFF\n");
 
-	if ((struct usb_device *)NULL == peasycap->pusb_device) {
-		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
+		if (!peasycap->pusb_device) {
+			SAM("ERROR: peasycap->pusb_device is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	peasycap->video_idle = 1;
-	peasycap->audio_idle = 1;  peasycap->timeval0.tv_sec = 0;
+		peasycap->video_idle = 1;
+		peasycap->audio_idle = 1;
+		peasycap->timeval0.tv_sec = 0;
 /*---------------------------------------------------------------------------*/
 /*
  *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
  *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
  */
 /*---------------------------------------------------------------------------*/
-	JOM(8, "calling wake_up on wq_video and wq_audio\n");
-	wake_up_interruptible(&(peasycap->wq_video));
-	wake_up_interruptible(&(peasycap->wq_audio));
+		JOM(8, "calling wake_up on wq_video and wq_audio\n");
+		wake_up_interruptible(&(peasycap->wq_video));
+#ifdef CONFIG_EASYCAP_OSS
+		wake_up_interruptible(&(peasycap->wq_audio));
+
+#else
+		if (peasycap->psubstream)
+			snd_pcm_period_elapsed(peasycap->psubstream);
+#endif /* CONFIG_EASYCAP_OSS */
 /*---------------------------------------------------------------------------*/
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_PARM: {
-	struct v4l2_streamparm *pv4l2_streamparm;
-
-	JOM(8, "VIDIOC_G_PARM\n");
-	pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
-	if (!pv4l2_streamparm) {
-		SAM("ERROR: out of memory\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ENOMEM;
-	}
-	if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
-					sizeof(struct v4l2_streamparm))) {
-		kfree(pv4l2_streamparm);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
+		break;
 	}
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_G_PARM: {
+		struct v4l2_streamparm *pv4l2_streamparm;
+
+		JOM(8, "VIDIOC_G_PARM\n");
+		pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
+		if (!pv4l2_streamparm) {
+			SAM("ERROR: out of memory\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ENOMEM;
+		}
+		if (copy_from_user(pv4l2_streamparm,
+			(void __user *)arg, sizeof(struct v4l2_streamparm))) {
+			kfree(pv4l2_streamparm);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EFAULT;
+		}
 
-	if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		kfree(pv4l2_streamparm);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EINVAL;
-	}
-	pv4l2_streamparm->parm.capture.capability = 0;
-	pv4l2_streamparm->parm.capture.capturemode = 0;
-	pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
+		if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			kfree(pv4l2_streamparm);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -EINVAL;
+		}
+		pv4l2_streamparm->parm.capture.capability = 0;
+		pv4l2_streamparm->parm.capture.capturemode = 0;
+		pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
 
-	if (peasycap->fps) {
-		pv4l2_streamparm->parm.capture.timeperframe.\
-						denominator = peasycap->fps;
-	} else {
-		if (true == peasycap->ntsc) {
-			pv4l2_streamparm->parm.capture.timeperframe.\
-						denominator = 30;
+		if (peasycap->fps) {
+			pv4l2_streamparm->parm.capture.timeperframe.
+			denominator = peasycap->fps;
 		} else {
-			pv4l2_streamparm->parm.capture.timeperframe.\
-						denominator = 25;
+			if (peasycap->ntsc) {
+				pv4l2_streamparm->parm.capture.timeperframe.
+				denominator = 30;
+			} else {
+				pv4l2_streamparm->parm.capture.timeperframe.
+				denominator = 25;
+			}
 		}
-	}
-
-	pv4l2_streamparm->parm.capture.readbuffers = \
-						peasycap->frame_buffer_many;
-	pv4l2_streamparm->parm.capture.extendedmode = 0;
-	if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
-					sizeof(struct v4l2_streamparm))) {
-		kfree(pv4l2_streamparm);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -EFAULT;
-	}
-	kfree(pv4l2_streamparm);
-	break;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_S_PARM: {
-	JOM(8, "VIDIOC_S_PARM unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_AUDIO: {
-	JOM(8, "VIDIOC_G_AUDIO unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_S_AUDIO: {
-	JOM(8, "VIDIOC_S_AUDIO unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_S_TUNER: {
-	JOM(8, "VIDIOC_S_TUNER unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_FBUF:
-case VIDIOC_S_FBUF:
-case VIDIOC_OVERLAY: {
-	JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-case VIDIOC_G_TUNER: {
-	JOM(8, "VIDIOC_G_TUNER unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-case VIDIOC_G_FREQUENCY:
-case VIDIOC_S_FREQUENCY: {
-	JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -EINVAL;
-}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-default: {
-	JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	return -ENOIOCTLCMD;
-}
-}
-mutex_unlock(&easycap_dongle[kd].mutex_video);
-JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
-return 0;
-}
-/*****************************************************************************/
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
-	(defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
-long
-easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
-	return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
-}
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*---------------------------------------------------------------------------*/
-int
-easysnd_ioctl(struct inode *inode, struct file *file,
-					unsigned int cmd, unsigned long arg)
-{
-struct easycap *peasycap;
-struct usb_device *p;
-int kd;
-
-if (NULL == file) {
-	SAY("ERROR:  file is NULL\n");
-	return -ERESTARTSYS;
-}
-peasycap = file->private_data;
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL.\n");
-	return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap\n");
-	return -EFAULT;
-}
-p = peasycap->pusb_device;
-if (NULL == p) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-kd = isdongle(peasycap);
-if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
-		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
-		return -ERESTARTSYS;
-	}
-	JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
-/*---------------------------------------------------------------------------*/
-/*
- *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
- *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
- *  IF NECESSARY, BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-	if (kd != isdongle(peasycap))
-		return -ERESTARTSYS;
-	if (NULL == file) {
-		SAY("ERROR:  file is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
-	}
-	peasycap = file->private_data;
-	if (NULL == peasycap) {
-		SAY("ERROR:  peasycap is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
-	}
-	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
-	}
-	p = peasycap->pusb_device;
-	if (NULL == peasycap->pusb_device) {
-		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
-	}
-} else {
-/*---------------------------------------------------------------------------*/
-/*
- *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
- *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-	return -ERESTARTSYS;
-}
-/*---------------------------------------------------------------------------*/
-switch (cmd) {
-case SNDCTL_DSP_GETCAPS: {
-	int caps;
-	JOM(8, "SNDCTL_DSP_GETCAPS\n");
-
-#if defined(UPSAMPLE)
-	if (true == peasycap->microphone)
-		caps = 0x04400000;
-	else
-		caps = 0x04400000;
-#else
-	if (true == peasycap->microphone)
-		caps = 0x02400000;
-	else
-		caps = 0x04400000;
-#endif /*UPSAMPLE*/
 
-	if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
-	}
-	break;
-}
-case SNDCTL_DSP_GETFMTS: {
-	int incoming;
-	JOM(8, "SNDCTL_DSP_GETFMTS\n");
-
-#if defined(UPSAMPLE)
-	if (true == peasycap->microphone)
-		incoming = AFMT_S16_LE;
-	else
-		incoming = AFMT_S16_LE;
-#else
-	if (true == peasycap->microphone)
-		incoming = AFMT_S16_LE;
-	else
-		incoming = AFMT_S16_LE;
-#endif /*UPSAMPLE*/
-
-	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
-	}
-	break;
-}
-case SNDCTL_DSP_SETFMT: {
-	int incoming, outgoing;
-	JOM(8, "SNDCTL_DSP_SETFMT\n");
-	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
-	}
-	JOM(8, "........... %i=incoming\n", incoming);
-
-#if defined(UPSAMPLE)
-	if (true == peasycap->microphone)
-		outgoing = AFMT_S16_LE;
-	else
-		outgoing = AFMT_S16_LE;
-#else
-	if (true == peasycap->microphone)
-		outgoing = AFMT_S16_LE;
-	else
-		outgoing = AFMT_S16_LE;
-#endif /*UPSAMPLE*/
-
-	if (incoming != outgoing) {
-		JOM(8, "........... %i=outgoing\n", outgoing);
-		JOM(8, "        cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
-		JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
-		if (0 != copy_to_user((void __user *)arg, &outgoing, \
-								sizeof(int))) {
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
+		pv4l2_streamparm->parm.capture.readbuffers =
+			peasycap->frame_buffer_many;
+		pv4l2_streamparm->parm.capture.extendedmode = 0;
+		if (copy_to_user((void __user *)arg,
+				pv4l2_streamparm,
+				sizeof(struct v4l2_streamparm))) {
+			kfree(pv4l2_streamparm);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
 			return -EFAULT;
 		}
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EINVAL ;
-	}
-	break;
-}
-case SNDCTL_DSP_STEREO: {
-	int incoming;
-	JOM(8, "SNDCTL_DSP_STEREO\n");
-	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+		kfree(pv4l2_streamparm);
+		break;
 	}
-	JOM(8, "........... %i=incoming\n", incoming);
-
-#if defined(UPSAMPLE)
-	if (true == peasycap->microphone)
-		incoming = 1;
-	else
-		incoming = 1;
-#else
-	if (true == peasycap->microphone)
-		incoming = 0;
-	else
-		incoming = 1;
-#endif /*UPSAMPLE*/
-
-	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_S_PARM: {
+		JOM(8, "VIDIOC_S_PARM unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	break;
-}
-case SNDCTL_DSP_SPEED: {
-	int incoming;
-	JOM(8, "SNDCTL_DSP_SPEED\n");
-	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_G_AUDIO: {
+		JOM(8, "VIDIOC_G_AUDIO unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	JOM(8, "........... %i=incoming\n", incoming);
-
-#if defined(UPSAMPLE)
-	if (true == peasycap->microphone)
-		incoming = 32000;
-	else
-		incoming = 48000;
-#else
-	if (true == peasycap->microphone)
-		incoming = 8000;
-	else
-		incoming = 48000;
-#endif /*UPSAMPLE*/
-
-	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_S_AUDIO: {
+		JOM(8, "VIDIOC_S_AUDIO unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	break;
-}
-case SNDCTL_DSP_GETTRIGGER: {
-	int incoming;
-	JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
-	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_S_TUNER: {
+		JOM(8, "VIDIOC_S_TUNER unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	JOM(8, "........... %i=incoming\n", incoming);
-
-	incoming = PCM_ENABLE_INPUT;
-	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_G_FBUF:
+	case VIDIOC_S_FBUF:
+	case VIDIOC_OVERLAY: {
+		JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	break;
-}
-case SNDCTL_DSP_SETTRIGGER: {
-	int incoming;
-	JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
-	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	case VIDIOC_G_TUNER: {
+		JOM(8, "VIDIOC_G_TUNER unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	JOM(8, "........... %i=incoming\n", incoming);
-	JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \
-				"0x%x=PCM_ENABLE_OUTPUT\n", \
-					PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
-	;
-	;
-	;
-	;
-	break;
-}
-case SNDCTL_DSP_GETBLKSIZE: {
-	int incoming;
-	JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
-	if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+	case VIDIOC_G_FREQUENCY:
+	case VIDIOC_S_FREQUENCY: {
+		JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -EINVAL;
 	}
-	JOM(8, "........... %i=incoming\n", incoming);
-	incoming = peasycap->audio_bytes_per_fragment;
-	if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
+	default: {
+		JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		return -ENOIOCTLCMD;
 	}
-	break;
-}
-case SNDCTL_DSP_GETISPACE: {
-	struct audio_buf_info audio_buf_info;
-
-	JOM(8, "SNDCTL_DSP_GETISPACE\n");
-
-	audio_buf_info.bytes      = peasycap->audio_bytes_per_fragment;
-	audio_buf_info.fragments  = 1;
-	audio_buf_info.fragsize   = 0;
-	audio_buf_info.fragstotal = 0;
-
-	if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
-								sizeof(int))) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EFAULT;
 	}
-	break;
-}
-case 0x00005401:
-case 0x00005402:
-case 0x00005403:
-case 0x00005404:
-case 0x00005405:
-case 0x00005406: {
-	JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
-	return -ENOIOCTLCMD;
-}
-default: {
-	JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
-	return -ENOIOCTLCMD;
-}
-}
-mutex_unlock(&easycap_dongle[kd].mutex_audio);
-return 0;
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+	JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
+	return 0;
 }
 /*****************************************************************************/
-
-
diff --git a/drivers/staging/easycap/easycap_ioctl.h b/drivers/staging/easycap/easycap_ioctl.h
deleted file mode 100644
index 210cd62..0000000
--- a/drivers/staging/easycap/easycap_ioctl.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*****************************************************************************
-*                                                                            *
-*  easycap_ioctl.h                                                           *
-*                                                                            *
-*****************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The software is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-extern struct easycap_format easycap_format[];
-extern struct v4l2_queryctrl easycap_control[];
diff --git a/drivers/staging/easycap/easycap_low.c b/drivers/staging/easycap/easycap_low.c
index 28c4d1e..0385735 100644
--- a/drivers/staging/easycap/easycap_low.c
+++ b/drivers/staging/easycap/easycap_low.c
@@ -39,10 +39,29 @@
 /****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
+
+#define GET(X, Y, Z) do { \
+	int __rc; \
+	*(Z) = (u16)0; \
+	__rc = regget(X, Y, Z, sizeof(u8)); \
+	if (0 > __rc) { \
+		JOT(8, ":-(%i\n", __LINE__);  return __rc; \
+	} \
+} while (0)
+
+#define SET(X, Y, Z) do { \
+	int __rc; \
+	__rc = regset(X, Y, Z); \
+	if (0 > __rc) { \
+		JOT(8, ":-(%i\n", __LINE__);  return __rc; \
+	} \
+} while (0)
 
 /*--------------------------------------------------------------------------*/
-const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
+static const struct stk1160config {
+	int reg;
+	int set;
+} stk1160configPAL[256] = {
 		{0x000, 0x0098},
 		{0x002, 0x0093},
 
@@ -84,7 +103,7 @@ const struct stk1160config { int reg; int set; } stk1160configPAL[256] = {
 		{0xFFF, 0xFFFF}
 };
 /*--------------------------------------------------------------------------*/
-const struct stk1160config stk1160configNTSC[256] = {
+static const struct stk1160config stk1160configNTSC[256] = {
 		{0x000, 0x0098},
 		{0x002, 0x0093},
 
@@ -126,13 +145,12 @@ const struct stk1160config stk1160configNTSC[256] = {
 		{0xFFF, 0xFFFF}
 };
 /*--------------------------------------------------------------------------*/
-const struct saa7113config { int reg; int set; } saa7113configPAL[256] = {
+static const struct saa7113config {
+	int reg;
+	int set;
+} saa7113configPAL[256] = {
 		{0x01, 0x08},
-#if defined(ANTIALIAS)
-		{0x02, 0xC0},
-#else
 		{0x02, 0x80},
-#endif /*ANTIALIAS*/
 		{0x03, 0x33},
 		{0x04, 0x00},
 		{0x05, 0x00},
@@ -184,13 +202,9 @@ const struct saa7113config { int reg; int set; } saa7113configPAL[256] = {
 		{0xFF, 0xFF}
 };
 /*--------------------------------------------------------------------------*/
-const struct saa7113config saa7113configNTSC[256] = {
+static const struct saa7113config saa7113configNTSC[256] = {
 		{0x01, 0x08},
-#if defined(ANTIALIAS)
-		{0x02, 0xC0},
-#else
 		{0x02, 0x80},
-#endif /*ANTIALIAS*/
 		{0x03, 0x33},
 		{0x04, 0x00},
 		{0x05, 0x00},
@@ -241,139 +255,210 @@ const struct saa7113config saa7113configNTSC[256] = {
 
 		{0xFF, 0xFF}
 };
+
+static int regget(struct usb_device *pusb_device,
+		u16 index, void *reg, int reg_size)
+{
+	int rc;
+
+	if (!pusb_device)
+		return -ENODEV;
+
+	rc = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0),
+			0x00,
+			(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
+			0x00,
+			index, reg, reg_size, 50000);
+
+	return rc;
+}
+
+static int regset(struct usb_device *pusb_device, u16 index, u16 value)
+{
+	int rc;
+
+	if (!pusb_device)
+		return -ENODEV;
+
+	rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
+			0x01,
+			(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
+			value, index, NULL, 0, 500);
+
+	if (rc < 0)
+		return rc;
+
+	if (easycap_readback) {
+		u16 igot = 0;
+		rc = regget(pusb_device, index, &igot, sizeof(igot));
+		igot = 0xFF & igot;
+		switch (index) {
+		case 0x000:
+		case 0x500:
+		case 0x502:
+		case 0x503:
+		case 0x504:
+		case 0x506:
+		case 0x507:
+			break;
+
+		case 0x204:
+		case 0x205:
+		case 0x350:
+		case 0x351:
+			if (igot)
+				JOT(8, "unexpected 0x%02X "
+					"for STK register 0x%03X\n",
+					igot, index);
+			break;
+
+		default:
+			if ((0xFF & value) != igot)
+				JOT(8, "unexpected 0x%02X != 0x%02X "
+					"for STK register 0x%03X\n",
+						igot, value, index);
+			break;
+		}
+	}
+
+	return rc;
+}
+/*--------------------------------------------------------------------------*/
+/*
+ *  FUNCTION wait_i2c() RETURNS 0 ON SUCCESS
+*/
 /*--------------------------------------------------------------------------*/
+static int wait_i2c(struct usb_device *p)
+{
+	u16 get0;
+	u8 igot;
+	const int max = 2;
+	int k;
+
+	if (!p)
+		return -ENODEV;
+
+	for (k = 0;  k < max;  k++) {
+		GET(p, 0x0201, &igot);  get0 = igot;
+		switch (get0) {
+		case 0x04:
+		case 0x01:
+			return 0;
+		case 0x00:
+			msleep(20);
+			continue;
+		default:
+			return get0 - 1;
+		}
+	}
+	return -1;
+}
 
 /****************************************************************************/
-int
-confirm_resolution(struct usb_device *p)
+int confirm_resolution(struct usb_device *p)
 {
-__u8 get0, get1, get2, get3, get4, get5, get6, get7;
-
-if (NULL == p)
-	return -ENODEV;
-GET(p, 0x0110, &get0);
-GET(p, 0x0111, &get1);
-GET(p, 0x0112, &get2);
-GET(p, 0x0113, &get3);
-GET(p, 0x0114, &get4);
-GET(p, 0x0115, &get5);
-GET(p, 0x0116, &get6);
-GET(p, 0x0117, &get7);
-JOT(8,  "0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X\n", \
-	get0, get1, get2, get3, get4, get5, get6, get7);
-JOT(8,  "....cf PAL_720x526: " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X\n", \
-	0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001);
-JOT(8,  "....cf PAL_704x526: " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X\n", \
-	0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001);
-JOT(8,  "....cf VGA_640x480: " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X, " \
-	"0x%03X, 0x%03X\n", \
-	0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001);
-return 0;
+	u8 get0, get1, get2, get3, get4, get5, get6, get7;
+
+	if (!p)
+		return -ENODEV;
+	GET(p, 0x0110, &get0);
+	GET(p, 0x0111, &get1);
+	GET(p, 0x0112, &get2);
+	GET(p, 0x0113, &get3);
+	GET(p, 0x0114, &get4);
+	GET(p, 0x0115, &get5);
+	GET(p, 0x0116, &get6);
+	GET(p, 0x0117, &get7);
+	JOT(8,  "0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X\n",
+		get0, get1, get2, get3, get4, get5, get6, get7);
+	JOT(8,  "....cf PAL_720x526: "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X\n",
+		0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001);
+	JOT(8,  "....cf PAL_704x526: "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X\n",
+		0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001);
+	JOT(8,  "....cf VGA_640x480: "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X, "
+		"0x%03X, 0x%03X\n",
+		0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001);
+	return 0;
 }
 /****************************************************************************/
-int
-confirm_stream(struct usb_device *p)
+int confirm_stream(struct usb_device *p)
 {
-__u16 get2;
-__u8 igot;
-
-if (NULL == p)
-	return -ENODEV;
-GET(p, 0x0100, &igot);  get2 = 0x80 & igot;
-if (0x80 == get2)
-	JOT(8, "confirm_stream:  OK\n");
-else
-	JOT(8, "confirm_stream:  STUCK\n");
-return 0;
+	u16 get2;
+	u8 igot;
+
+	if (!p)
+		return -ENODEV;
+	GET(p, 0x0100, &igot);  get2 = 0x80 & igot;
+	if (0x80 == get2)
+		JOT(8, "confirm_stream:  OK\n");
+	else
+		JOT(8, "confirm_stream:  STUCK\n");
+	return 0;
 }
 /****************************************************************************/
-int
-setup_stk(struct usb_device *p, bool ntsc)
+int setup_stk(struct usb_device *p, bool ntsc)
 {
-int i0;
-
-if (NULL == p)
-	return -ENODEV;
-i0 = 0;
-if (true == ntsc) {
-	while (0xFFF != stk1160configNTSC[i0].reg) {
-		SET(p, stk1160configNTSC[i0].reg, stk1160configNTSC[i0].set);
-		i0++;
-	}
-} else {
-	while (0xFFF != stk1160configPAL[i0].reg) {
-		SET(p, stk1160configPAL[i0].reg, stk1160configPAL[i0].set);
-		i0++;
-	}
-}
+	int i;
+	const struct stk1160config *cfg;
+	if (!p)
+		return -ENODEV;
+	cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
+	for (i = 0; cfg[i].reg != 0xFFF; i++)
+		SET(p, cfg[i].reg, cfg[i].set);
 
-write_300(p);
+	write_300(p);
 
-return 0;
+	return 0;
 }
 /****************************************************************************/
-int
-setup_saa(struct usb_device *p, bool ntsc)
+int setup_saa(struct usb_device *p, bool ntsc)
 {
-int i0, ir;
-
-if (NULL == p)
-	return -ENODEV;
-i0 = 0;
-if (true == ntsc) {
-	while (0xFF != saa7113configNTSC[i0].reg) {
-		ir = write_saa(p, saa7113configNTSC[i0].reg, \
-					saa7113configNTSC[i0].set);
-		i0++;
-	}
-} else {
-	while (0xFF != saa7113configPAL[i0].reg) {
-		ir = write_saa(p, saa7113configPAL[i0].reg, \
-					saa7113configPAL[i0].set);
-		i0++;
-	}
-}
-return 0;
+	int i, ir;
+	const struct saa7113config *cfg;
+	if (!p)
+		return -ENODEV;
+	cfg = (ntsc) ?  saa7113configNTSC : saa7113configPAL;
+	for (i = 0; cfg[i].reg != 0xFF; i++)
+		ir = write_saa(p, cfg[i].reg, cfg[i].set);
+	return 0;
 }
 /****************************************************************************/
-int
-write_000(struct usb_device *p, __u16 set2, __u16 set0)
+int write_000(struct usb_device *p, u16 set2, u16 set0)
 {
-__u8 igot0, igot2;
-
-if (NULL == p)
-	return -ENODEV;
-GET(p, 0x0002, &igot2);
-GET(p, 0x0000, &igot0);
-SET(p, 0x0002, set2);
-SET(p, 0x0000, set0);
-return 0;
+	u8 igot0, igot2;
+
+	if (!p)
+		return -ENODEV;
+	GET(p, 0x0002, &igot2);
+	GET(p, 0x0000, &igot0);
+	SET(p, 0x0002, set2);
+	SET(p, 0x0000, set0);
+	return 0;
 }
 /****************************************************************************/
-int
-write_saa(struct usb_device *p, __u16 reg0, __u16 set0)
+int write_saa(struct usb_device *p, u16 reg0, u16 set0)
 {
-if (NULL == p)
-	return -ENODEV;
-SET(p, 0x200, 0x00);
-SET(p, 0x204, reg0);
-SET(p, 0x205, set0);
-SET(p, 0x200, 0x01);
-return wait_i2c(p);
+	if (!p)
+		return -ENODEV;
+	SET(p, 0x200, 0x00);
+	SET(p, 0x204, reg0);
+	SET(p, 0x205, set0);
+	SET(p, 0x200, 0x01);
+	return wait_i2c(p);
 }
 /****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -386,32 +471,32 @@ return wait_i2c(p);
  */
 /*--------------------------------------------------------------------------*/
 int
-write_vt(struct usb_device *p, __u16 reg0, __u16 set0)
+write_vt(struct usb_device *p, u16 reg0, u16 set0)
 {
-__u8 igot;
-__u16 got502, got503;
-__u16 set502, set503;
+	u8 igot;
+	u16 got502, got503;
+	u16 set502, set503;
 
-if (NULL == p)
-	return -ENODEV;
-SET(p, 0x0504, reg0);
-SET(p, 0x0500, 0x008B);
+	if (!p)
+		return -ENODEV;
+	SET(p, 0x0504, reg0);
+	SET(p, 0x0500, 0x008B);
 
-GET(p, 0x0502, &igot);  got502 = (0xFF & igot);
-GET(p, 0x0503, &igot);  got503 = (0xFF & igot);
+	GET(p, 0x0502, &igot);  got502 = (0xFF & igot);
+	GET(p, 0x0503, &igot);  got503 = (0xFF & igot);
 
-JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n", \
-					reg0, set0, ((got503 << 8) | got502));
+	JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n",
+				reg0, set0, ((got503 << 8) | got502));
 
-set502 =  (0x00FF & set0);
-set503 = ((0xFF00 & set0) >> 8);
+	set502 =  (0x00FF & set0);
+	set503 = ((0xFF00 & set0) >> 8);
 
-SET(p, 0x0504, reg0);
-SET(p, 0x0502, set502);
-SET(p, 0x0503, set503);
-SET(p, 0x0500, 0x008C);
+	SET(p, 0x0504, reg0);
+	SET(p, 0x0502, set502);
+	SET(p, 0x0503, set503);
+	SET(p, 0x0500, 0x008C);
 
-return 0;
+	return 0;
 }
 /****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -423,23 +508,23 @@ return 0;
  *  REGISTER 504:  TARGET ADDRESS ON VT1612A
  */
 /*--------------------------------------------------------------------------*/
-int
-read_vt(struct usb_device *p, __u16 reg0)
+int read_vt(struct usb_device *p, u16 reg0)
 {
-__u8 igot;
-__u16 got502, got503;
+	u8 igot;
+	u16 got502, got503;
 
-if (NULL == p)
-	return -ENODEV;
-SET(p, 0x0504, reg0);
-SET(p, 0x0500, 0x008B);
+	if (!p)
+		return -ENODEV;
+	SET(p, 0x0504, reg0);
+	SET(p, 0x0500, 0x008B);
 
-GET(p, 0x0502, &igot);  got502 = (0xFF & igot);
-GET(p, 0x0503, &igot);  got503 = (0xFF & igot);
+	GET(p, 0x0502, &igot);  got502 = (0xFF & igot);
+	GET(p, 0x0503, &igot);  got503 = (0xFF & igot);
 
-JOT(16, "read_vt(., 0x%04X): has 0x%04X\n", reg0, ((got503 << 8) | got502));
+	JOT(16, "read_vt(., 0x%04X): has 0x%04X\n",
+			reg0, ((got503 << 8) | got502));
 
-return (got503 << 8) | got502;
+	return (got503 << 8) | got502;
 }
 /****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -447,18 +532,17 @@ return (got503 << 8) | got502;
  *  THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
  */
 /*--------------------------------------------------------------------------*/
-int
-write_300(struct usb_device *p)
+int write_300(struct usb_device *p)
 {
-if (NULL == p)
-	return -ENODEV;
-SET(p, 0x300, 0x0012);
-SET(p, 0x350, 0x002D);
-SET(p, 0x351, 0x0001);
-SET(p, 0x352, 0x0000);
-SET(p, 0x353, 0x0000);
-SET(p, 0x300, 0x0080);
-return 0;
+	if (!p)
+		return -ENODEV;
+	SET(p, 0x300, 0x0012);
+	SET(p, 0x350, 0x002D);
+	SET(p, 0x351, 0x0001);
+	SET(p, 0x352, 0x0000);
+	SET(p, 0x353, 0x0000);
+	SET(p, 0x300, 0x0080);
+	return 0;
 }
 /****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -467,75 +551,42 @@ return 0;
  *  REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL.
  */
 /*--------------------------------------------------------------------------*/
-int
-check_saa(struct usb_device *p, bool ntsc)
+int check_saa(struct usb_device *p, bool ntsc)
 {
-int i0, ir, rc;
-
-if (NULL == p)
-	return -ENODEV;
-i0 = 0;
-rc = 0;
-if (true == ntsc) {
-	while (0xFF != saa7113configNTSC[i0].reg) {
-		if (0x0F == saa7113configNTSC[i0].reg) {
-			i0++;
+	int i, ir, rc = 0;
+	struct saa7113config const *cfg;
+	if (!p)
+		return -ENODEV;
+
+	cfg = (ntsc) ? saa7113configNTSC : saa7113configPAL;
+	for (i = 0; cfg[i].reg != 0xFF; i++) {
+		if (0x0F == cfg[i].reg)
 			continue;
+		ir = read_saa(p, cfg[i].reg);
+		if (ir != cfg[i].set) {
+			SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n",
+				cfg[i].reg, ir, cfg[i].set);
+				rc--;
 		}
-
-		ir = read_saa(p, saa7113configNTSC[i0].reg);
-		if (ir != saa7113configNTSC[i0].set) {
-			SAY("SAA register 0x%02X has 0x%02X, " \
-						"expected 0x%02X\n", \
-						saa7113configNTSC[i0].reg, \
-						ir, saa7113configNTSC[i0].set);
-			rc--;
-		}
-		i0++;
 	}
-} else {
-	while (0xFF != saa7113configPAL[i0].reg) {
-		if (0x0F == saa7113configPAL[i0].reg) {
-			i0++;
-			continue;
-		}
 
-		ir = read_saa(p, saa7113configPAL[i0].reg);
-		if (ir != saa7113configPAL[i0].set) {
-			SAY("SAA register 0x%02X has 0x%02X, " \
-						"expected 0x%02X\n", \
-						saa7113configPAL[i0].reg, \
-						ir, saa7113configPAL[i0].set);
-			rc--;
-		}
-		i0++;
-	}
-}
-if (-8 > rc)
-	return rc;
-else
-	return 0;
+	return (rc < -8) ? rc : 0;
 }
 /****************************************************************************/
-int
-merit_saa(struct usb_device *p)
+int merit_saa(struct usb_device *p)
 {
-int rc;
-
-if (NULL == p)
-	return -ENODEV;
-rc = read_saa(p, 0x1F);
-if ((0 > rc) || (0x02 & rc))
-	return 1 ;
-else
-	return 0;
+	int rc;
+
+	if (!p)
+		return -ENODEV;
+	rc = read_saa(p, 0x1F);
+	return ((0 > rc) || (0x02 & rc)) ? 1 : 0;
 }
 /****************************************************************************/
-int
-ready_saa(struct usb_device *p)
+int ready_saa(struct usb_device *p)
 {
-int j, rc, rate;
-const int max = 5, marktime = PATIENCE/5;
+	int j, rc, rate;
+	const int max = 5, marktime = PATIENCE/5;
 /*--------------------------------------------------------------------------*/
 /*
  *   RETURNS    0     FOR INTERLACED       50 Hz
@@ -544,38 +595,38 @@ const int max = 5, marktime = PATIENCE/5;
  *              3     FOR NON-INTERLACED   60 Hz
 */
 /*--------------------------------------------------------------------------*/
-if (NULL == p)
-	return -ENODEV;
-j = 0;
-while (max > j) {
-	rc = read_saa(p, 0x1F);
-	if (0 <= rc) {
-		if (0 == (0x40 & rc))
-			break;
-		if (1 == (0x01 & rc))
-			break;
-	}
-	msleep(marktime);
-	j++;
-}
-if (max == j)
-	return -1;
-else {
-	if (0x20 & rc) {
-		rate = 2;
-		JOT(8, "hardware detects 60 Hz\n");
-	} else {
-		rate = 0;
-		JOT(8, "hardware detects 50 Hz\n");
+	if (!p)
+		return -ENODEV;
+	j = 0;
+	while (max > j) {
+		rc = read_saa(p, 0x1F);
+		if (0 <= rc) {
+			if (0 == (0x40 & rc))
+				break;
+			if (1 == (0x01 & rc))
+				break;
+		}
+		msleep(marktime);
+		j++;
 	}
-	if (0x80 & rc)
-		JOT(8, "hardware detects interlacing\n");
+	if (max == j)
+		return -1;
 	else {
-		rate++;
-		JOT(8, "hardware detects no interlacing\n");
+		if (0x20 & rc) {
+			rate = 2;
+			JOT(8, "hardware detects 60 Hz\n");
+		} else {
+			rate = 0;
+			JOT(8, "hardware detects 50 Hz\n");
+		}
+		if (0x80 & rc)
+			JOT(8, "hardware detects interlacing\n");
+		else {
+			rate++;
+			JOT(8, "hardware detects no interlacing\n");
+		}
 	}
-}
-return 0;
+	return 0;
 }
 /****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -585,106 +636,61 @@ return 0;
  *  REGISTER  0x100:  ACCEPT ALSO (0x80 | stk1160config....[.].set)
  */
 /*--------------------------------------------------------------------------*/
-int
-check_stk(struct usb_device *p, bool ntsc)
+int check_stk(struct usb_device *p, bool ntsc)
 {
-int i0, ir;
-
-if (NULL == p)
-	return -ENODEV;
-i0 = 0;
-if (true == ntsc) {
-	while (0xFFF != stk1160configNTSC[i0].reg) {
-		if (0x000 == stk1160configNTSC[i0].reg) {
-			i0++; continue;
-		}
-		if (0x002 == stk1160configNTSC[i0].reg) {
-			i0++; continue;
-		}
-		ir = read_stk(p, stk1160configNTSC[i0].reg);
-		if (0x100 == stk1160configNTSC[i0].reg) {
-			if ((ir != (0xFF & stk1160configNTSC[i0].set)) && \
-					(ir != (0x80 | (0xFF & \
-					stk1160configNTSC[i0].set))) && \
-					(0xFFFF != \
-					stk1160configNTSC[i0].set)) {
-				SAY("STK register 0x%03X has 0x%02X, " \
-						"expected 0x%02X\n", \
-						stk1160configNTSC[i0].reg, \
-						ir, stk1160configNTSC[i0].set);
-				}
-			i0++; continue;
-			}
-		if ((ir != (0xFF & stk1160configNTSC[i0].set)) && \
-				(0xFFFF != stk1160configNTSC[i0].set)) {
-			SAY("STK register 0x%03X has 0x%02X, " \
-						"expected 0x%02X\n", \
-						stk1160configNTSC[i0].reg, \
-						ir, stk1160configNTSC[i0].set);
-		}
-		i0++;
-	}
-} else {
-	while (0xFFF != stk1160configPAL[i0].reg) {
-		if (0x000 == stk1160configPAL[i0].reg) {
-			i0++; continue;
-		}
-		if (0x002 == stk1160configPAL[i0].reg) {
-			i0++; continue;
-		}
-		ir = read_stk(p, stk1160configPAL[i0].reg);
-		if (0x100 == stk1160configPAL[i0].reg) {
-			if ((ir != (0xFF & stk1160configPAL[i0].set)) && \
-					(ir != (0x80 | (0xFF & \
-					stk1160configPAL[i0].set))) && \
-					(0xFFFF != \
-					stk1160configPAL[i0].set)) {
-				SAY("STK register 0x%03X has 0x%02X, " \
-						"expected 0x%02X\n", \
-						stk1160configPAL[i0].reg, \
-						ir, stk1160configPAL[i0].set);
-				}
-			i0++; continue;
+	int i, ir;
+	const struct stk1160config *cfg;
+
+	if (!p)
+		return -ENODEV;
+	cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
+
+	for (i = 0; 0xFFF != cfg[i].reg; i++) {
+		if (0x000 == cfg[i].reg || 0x002 == cfg[i].reg)
+			continue;
+
+
+		ir = read_stk(p, cfg[i].reg);
+		if (0x100 == cfg[i].reg) {
+			if ((ir != (0xFF & cfg[i].set)) &&
+			    (ir != (0x80 | (0xFF & cfg[i].set))) &&
+			    (0xFFFF != cfg[i].set)) {
+				SAY("STK reg[0x%03X]=0x%02X expected 0x%02X\n",
+					cfg[i].reg, ir, cfg[i].set);
 			}
-		if ((ir != (0xFF & stk1160configPAL[i0].set)) && \
-				(0xFFFF != stk1160configPAL[i0].set)) {
-			SAY("STK register 0x%03X has 0x%02X, " \
-						"expected 0x%02X\n", \
-						stk1160configPAL[i0].reg, \
-						ir, stk1160configPAL[i0].set);
+			continue;
 		}
-		i0++;
+		if ((ir != (0xFF & cfg[i].set)) && (0xFFFF != cfg[i].set))
+			SAY("STK register 0x%03X has 0x%02X,expected 0x%02X\n",
+				cfg[i].reg, ir, cfg[i].set);
 	}
-}
-return 0;
+	return 0;
 }
 /****************************************************************************/
-int
-read_saa(struct usb_device *p, __u16 reg0)
+int read_saa(struct usb_device *p, u16 reg0)
 {
-__u8 igot;
+	u8 igot;
 
-if (NULL == p)
-	return -ENODEV;
-SET(p, 0x208, reg0);
-SET(p, 0x200, 0x20);
-if (0 != wait_i2c(p))
-	return -1;
-igot = 0;
-GET(p, 0x0209, &igot);
-return igot;
+	if (!p)
+		return -ENODEV;
+	SET(p, 0x208, reg0);
+	SET(p, 0x200, 0x20);
+	if (0 != wait_i2c(p))
+		return -1;
+	igot = 0;
+	GET(p, 0x0209, &igot);
+	return igot;
 }
 /****************************************************************************/
-int
-read_stk(struct usb_device *p, __u32 reg0)
+int read_stk(struct usb_device *p, u32 reg0)
 {
-__u8 igot;
+	u8 igot;
 
-if (NULL == p)
-	return -ENODEV;
-igot = 0;
-GET(p, reg0, &igot);
-return igot;
+	if (!p)
+		return -ENODEV;
+	igot = 0;
+	GET(p, reg0, &igot);
+	return igot;
 }
 /****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -708,307 +714,186 @@ return igot;
 int
 select_input(struct usb_device *p, int input, int mode)
 {
-int ir;
-
-if (NULL == p)
-	return -ENODEV;
-stop_100(p);
-switch (input) {
-case 0:
-case 1: {
-	if (0 != write_saa(p, 0x02, 0x80)) {
-		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
-									input);
-	}
-	SET(p, 0x0000, 0x0098);
-	SET(p, 0x0002, 0x0078);
-	break;
-}
-case 2: {
-	if (0 != write_saa(p, 0x02, 0x80)) {
-		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
-									input);
+	int ir;
+
+	if (!p)
+		return -ENODEV;
+	stop_100(p);
+	switch (input) {
+	case 0:
+	case 1: {
+		if (0 != write_saa(p, 0x02, 0x80))
+			SAY("ERROR: failed to set SAA register 0x02 "
+						"for input %i\n", input);
+
+		SET(p, 0x0000, 0x0098);
+		SET(p, 0x0002, 0x0078);
+		break;
 	}
-	SET(p, 0x0000, 0x0090);
-	SET(p, 0x0002, 0x0078);
-	break;
-}
-case 3: {
-	if (0 != write_saa(p, 0x02, 0x80)) {
-		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
-									input);
+	case 2: {
+		if (0 != write_saa(p, 0x02, 0x80))
+			SAY("ERROR: failed to set SAA register 0x02 "
+						"for input %i\n", input);
+
+		SET(p, 0x0000, 0x0090);
+		SET(p, 0x0002, 0x0078);
+		break;
 	}
-	SET(p, 0x0000, 0x0088);
-	SET(p, 0x0002, 0x0078);
-	break;
-}
-case 4: {
-	if (0 != write_saa(p, 0x02, 0x80)) {
-		SAY("ERROR: failed to set SAA register 0x02 for input %i\n", \
-									input);
+	case 3: {
+		if (0 != write_saa(p, 0x02, 0x80))
+			SAY("ERROR: failed to set SAA register 0x02 "
+					" for input %i\n", input);
+
+		SET(p, 0x0000, 0x0088);
+		SET(p, 0x0002, 0x0078);
+		break;
 	}
-	SET(p, 0x0000, 0x0080);
-	SET(p, 0x0002, 0x0078);
-	break;
-}
-case 5: {
-	if (9 != mode)
-		mode = 7;
-	switch (mode) {
-	case 7: {
-		if (0 != write_saa(p, 0x02, 0x87)) {
-			SAY("ERROR: failed to set SAA register 0x02 " \
-						"for input %i\n", input);
-		}
-		if (0 != write_saa(p, 0x05, 0xFF)) {
-			SAY("ERROR: failed to set SAA register 0x05 " \
+	case 4: {
+		if (0 != write_saa(p, 0x02, 0x80)) {
+			SAY("ERROR: failed to set SAA register 0x02 "
 						"for input %i\n", input);
 		}
+		SET(p, 0x0000, 0x0080);
+		SET(p, 0x0002, 0x0078);
 		break;
 	}
-	case 9: {
-		if (0 != write_saa(p, 0x02, 0x89)) {
-			SAY("ERROR: failed to set SAA register 0x02 " \
+	case 5: {
+		if (9 != mode)
+			mode = 7;
+		switch (mode) {
+		case 7: {
+			if (0 != write_saa(p, 0x02, 0x87))
+				SAY("ERROR: failed to set SAA register 0x02 "
+						"for input %i\n", input);
+
+			if (0 != write_saa(p, 0x05, 0xFF))
+				SAY("ERROR: failed to set SAA register 0x05 "
 						"for input %i\n", input);
+
+			break;
 		}
-		if (0 != write_saa(p, 0x05, 0x00)) {
-			SAY("ERROR: failed to set SAA register 0x05 " \
+		case 9: {
+			if (0 != write_saa(p, 0x02, 0x89))
+				SAY("ERROR: failed to set SAA register 0x02 "
 						"for input %i\n", input);
+
+			if (0 != write_saa(p, 0x05, 0x00))
+				SAY("ERROR: failed to set SAA register 0x05 "
+						"for input %i\n", input);
+
+			break;
 		}
-	break;
+		default:
+			SAY("MISTAKE:  bad mode: %i\n", mode);
+			return -1;
+		}
+
+		if (0 != write_saa(p, 0x04, 0x00))
+			SAY("ERROR: failed to set SAA register 0x04 "
+					"for input %i\n", input);
+
+		if (0 != write_saa(p, 0x09, 0x80))
+			SAY("ERROR: failed to set SAA register 0x09 "
+						"for input %i\n", input);
+
+		SET(p, 0x0002, 0x0093);
+		break;
 	}
-	default: {
-		SAY("MISTAKE:  bad mode: %i\n", mode);
+	default:
+		SAY("ERROR:  bad input: %i\n", input);
 		return -1;
 	}
-	}
-	if (0 != write_saa(p, 0x04, 0x00)) {
-		SAY("ERROR: failed to set SAA register 0x04 for input %i\n", \
-									input);
-	}
-	if (0 != write_saa(p, 0x09, 0x80)) {
-		SAY("ERROR: failed to set SAA register 0x09 for input %i\n", \
-									input);
-	}
-	SET(p, 0x0002, 0x0093);
-	break;
-}
-default: {
-	SAY("ERROR:  bad input: %i\n", input);
-	return -1;
-}
-}
-ir = read_stk(p, 0x00);
-JOT(8, "STK register 0x00 has 0x%02X\n", ir);
-ir = read_saa(p, 0x02);
-JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
 
-start_100(p);
+	ir = read_stk(p, 0x00);
+	JOT(8, "STK register 0x00 has 0x%02X\n", ir);
+	ir = read_saa(p, 0x02);
+	JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
+
+	start_100(p);
 
-return 0;
+	return 0;
 }
 /****************************************************************************/
-int
-set_resolution(struct usb_device *p, \
-				__u16 set0, __u16 set1, __u16 set2, __u16 set3)
+int set_resolution(struct usb_device *p,
+		   u16 set0, u16 set1, u16 set2, u16 set3)
 {
-__u16 u0x0111, u0x0113, u0x0115, u0x0117;
-
-if (NULL == p)
-	return -ENODEV;
-u0x0111 = ((0xFF00 & set0) >> 8);
-u0x0113 = ((0xFF00 & set1) >> 8);
-u0x0115 = ((0xFF00 & set2) >> 8);
-u0x0117 = ((0xFF00 & set3) >> 8);
-
-SET(p, 0x0110, (0x00FF & set0));
-SET(p, 0x0111, u0x0111);
-SET(p, 0x0112, (0x00FF & set1));
-SET(p, 0x0113, u0x0113);
-SET(p, 0x0114, (0x00FF & set2));
-SET(p, 0x0115, u0x0115);
-SET(p, 0x0116, (0x00FF & set3));
-SET(p, 0x0117, u0x0117);
-
-return 0;
+	u16 u0x0111, u0x0113, u0x0115, u0x0117;
+
+	if (!p)
+		return -ENODEV;
+	u0x0111 = ((0xFF00 & set0) >> 8);
+	u0x0113 = ((0xFF00 & set1) >> 8);
+	u0x0115 = ((0xFF00 & set2) >> 8);
+	u0x0117 = ((0xFF00 & set3) >> 8);
+
+	SET(p, 0x0110, (0x00FF & set0));
+	SET(p, 0x0111, u0x0111);
+	SET(p, 0x0112, (0x00FF & set1));
+	SET(p, 0x0113, u0x0113);
+	SET(p, 0x0114, (0x00FF & set2));
+	SET(p, 0x0115, u0x0115);
+	SET(p, 0x0116, (0x00FF & set3));
+	SET(p, 0x0117, u0x0117);
+
+	return 0;
 }
 /****************************************************************************/
-int
-start_100(struct usb_device *p)
+int start_100(struct usb_device *p)
 {
-__u16 get116, get117, get0;
-__u8 igot116, igot117, igot;
-
-if (NULL == p)
-	return -ENODEV;
-GET(p, 0x0116, &igot116);
-get116 = igot116;
-GET(p, 0x0117, &igot117);
-get117 = igot117;
-SET(p, 0x0116, 0x0000);
-SET(p, 0x0117, 0x0000);
-
-GET(p, 0x0100, &igot);
-get0 = igot;
-SET(p, 0x0100, (0x80 | get0));
-
-SET(p, 0x0116, get116);
-SET(p, 0x0117, get117);
-
-return 0;
+	u16 get116, get117, get0;
+	u8 igot116, igot117, igot;
+
+	if (!p)
+		return -ENODEV;
+	GET(p, 0x0116, &igot116);
+	get116 = igot116;
+	GET(p, 0x0117, &igot117);
+	get117 = igot117;
+	SET(p, 0x0116, 0x0000);
+	SET(p, 0x0117, 0x0000);
+
+	GET(p, 0x0100, &igot);
+	get0 = igot;
+	SET(p, 0x0100, (0x80 | get0));
+
+	SET(p, 0x0116, get116);
+	SET(p, 0x0117, get117);
+
+	return 0;
 }
 /****************************************************************************/
-int
-stop_100(struct usb_device *p)
+int stop_100(struct usb_device *p)
 {
-__u16 get0;
-__u8 igot;
-
-if (NULL == p)
-	return -ENODEV;
-GET(p, 0x0100, &igot);
-get0 = igot;
-SET(p, 0x0100, (0x7F & get0));
-return 0;
+	u16 get0;
+	u8 igot;
+
+	if (!p)
+		return -ENODEV;
+	GET(p, 0x0100, &igot);
+	get0 = igot;
+	SET(p, 0x0100, (0x7F & get0));
+	return 0;
 }
 /****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  FUNCTION wait_i2c() RETURNS 0 ON SUCCESS
-*/
-/*--------------------------------------------------------------------------*/
-int
-wait_i2c(struct usb_device *p)
-{
-__u16 get0;
-__u8 igot;
-const int max = 2;
-int k;
-
-if (NULL == p)
-	return -ENODEV;
-for (k = 0;  k < max;  k++) {
-	GET(p, 0x0201, &igot);  get0 = igot;
-	switch (get0) {
-	case 0x04:
-	case 0x01: {
-		return 0;
-	}
-	case 0x00: {
-		msleep(20);
-		continue;
-	}
-	default: {
-		return get0 - 1;
-	}
-	}
-}
-return -1;
-}
 /****************************************************************************/
-int
-regset(struct usb_device *pusb_device, __u16 index, __u16 value)
-{
-__u16 igot;
-int rc0, rc1;
-
-if (!pusb_device)
-	return -ENODEV;
-rc1 = 0;  igot = 0;
-rc0 = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \
-		(__u8)0x01, \
-		(__u8)(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \
-		(__u16)value, \
-		(__u16)index, \
-		(void *)NULL, \
-		(__u16)0, \
-		(int)500);
-
-#if defined(NOREADBACK)
-#
-#else
-rc1 = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \
-		(__u8)0x00, \
-		(__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \
-		(__u16)0x00, \
-		(__u16)index, \
-		(void *)&igot, \
-		(__u16)sizeof(__u16), \
-		(int)50000);
-igot = 0xFF & igot;
-switch (index) {
-case 0x000:
-case 0x500:
-case 0x502:
-case 0x503:
-case 0x504:
-case 0x506:
-case 0x507: {
-	break;
-}
-case 0x204:
-case 0x205:
-case 0x350:
-case 0x351: {
-	if (0 != (0xFF & igot)) {
-		JOT(8, "unexpected 0x%02X for STK register 0x%03X\n", \
-								igot, index);
-	}
-break;
-}
-default: {
-	if ((0xFF & value) != (0xFF & igot)) {
-		JOT(8, "unexpected 0x%02X != 0x%02X " \
-					"for STK register 0x%03X\n", \
-					igot, value, index);
-	}
-break;
-}
-}
-#endif /* ! NOREADBACK*/
-
-return (0 > rc0) ? rc0 : rc1;
-}
 /*****************************************************************************/
-int
-regget(struct usb_device *pusb_device, __u16 index, void *pvoid)
-{
-int ir;
-
-if (!pusb_device)
-	return -ENODEV;
-ir = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \
-		(__u8)0x00, \
-		(__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \
-		(__u16)0x00, \
-		(__u16)index, \
-		(void *)pvoid, \
-		sizeof(__u8), \
-		(int)50000);
-return 0xFF & ir;
-}
-/*****************************************************************************/
-int
-wakeup_device(struct usb_device *pusb_device)
+int wakeup_device(struct usb_device *pusb_device)
 {
-if (!pusb_device)
-	return -ENODEV;
-return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \
-		(__u8)USB_REQ_SET_FEATURE, \
-		(__u8)(USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE), \
-		USB_DEVICE_REMOTE_WAKEUP, \
-		(__u16)0, \
-		(void *) NULL, \
-		(__u16)0, \
-		(int)50000);
+	if (!pusb_device)
+		return -ENODEV;
+	return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
+			USB_REQ_SET_FEATURE,
+			USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
+			USB_DEVICE_REMOTE_WAKEUP,
+			0, NULL, 0, 50000);
 }
 /*****************************************************************************/
 int
 audio_setup(struct easycap *peasycap)
 {
-struct usb_device *pusb_device;
-unsigned char buffer[1];
-int rc, id1, id2;
+	struct usb_device *pusb_device;
+	u8 buffer[1];
+	int rc, id1, id2;
 /*---------------------------------------------------------------------------*/
 /*
  *                                IMPORTANT:
@@ -1017,44 +902,47 @@ int rc, id1, id2;
  *  TO ENABLE AUDIO  THE VALUE 0x0200 MUST BE SENT.
  */
 /*---------------------------------------------------------------------------*/
-const __u8 request = 0x01;
-const __u8 requesttype = \
-		(__u8)(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
-const __u16 value_unmute = 0x0200;
-const __u16 index = 0x0301;
-const __u16 length = 1;
-
-if (NULL == peasycap)
-	return -EFAULT;
-
-pusb_device = peasycap->pusb_device;
-if (NULL == pusb_device)
-	return -ENODEV;
-
-JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n",	\
-			requesttype, request,		\
-			(0x00FF & value_unmute),	\
-			(0xFF00 & value_unmute) >> 8,	\
-			(0x00FF & index),		\
-			(0xFF00 & index) >> 8,		\
-			(0x00FF & length),		\
-			(0xFF00 & length) >> 8);
-
-buffer[0] = 0x01;
-
-rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),	\
-			(__u8)request,					\
-			(__u8)requesttype,				\
-			(__u16)value_unmute,				\
-			(__u16)index,					\
-			(void *)&buffer[0],				\
-			(__u16)length,					\
-			(int)50000);
-
-JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0]));
-if (rc != (int)length)
-	SAY("ERROR: usb_control_msg returned %i\n", rc);
-
+	const u8 request = 0x01;
+	const u8 requesttype = USB_DIR_OUT |
+			       USB_TYPE_CLASS |
+			       USB_RECIP_INTERFACE;
+	const u16 value_unmute = 0x0200;
+	const u16 index = 0x0301;
+	const u16 length = 1;
+
+	if (!peasycap)
+		return -EFAULT;
+
+	pusb_device = peasycap->pusb_device;
+	if (!pusb_device)
+		return -ENODEV;
+
+	JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n",
+				requesttype, request,
+				(0x00FF & value_unmute),
+				(0xFF00 & value_unmute) >> 8,
+				(0x00FF & index),
+				(0xFF00 & index) >> 8,
+				(0x00FF & length),
+				(0xFF00 & length) >> 8);
+
+	buffer[0] = 0x01;
+
+	rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
+				request, requesttype, value_unmute,
+				index, &buffer[0], length, 50000);
+
+	JOT(8, "0x%02X=buffer\n", buffer[0]);
+	if (rc != (int)length) {
+		switch (rc) {
+		case -EPIPE:
+			SAY("usb_control_msg returned -EPIPE\n");
+			break;
+		default:
+			SAY("ERROR: usb_control_msg returned %i\n", rc);
+			break;
+		}
+	}
 /*--------------------------------------------------------------------------*/
 /*
  *  REGISTER 500:  SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
@@ -1070,84 +958,79 @@ if (rc != (int)length)
  *                    THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
  */
 /*--------------------------------------------------------------------------*/
-SET(pusb_device, 0x0500, 0x0094);
-SET(pusb_device, 0x0500, 0x008C);
-SET(pusb_device, 0x0506, 0x0001);
-SET(pusb_device, 0x0507, 0x0000);
-id1 = read_vt(pusb_device, 0x007C);
-id2 = read_vt(pusb_device, 0x007E);
-SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2);
+	SET(pusb_device, 0x0500, 0x0094);
+	SET(pusb_device, 0x0500, 0x008C);
+	SET(pusb_device, 0x0506, 0x0001);
+	SET(pusb_device, 0x0507, 0x0000);
+	id1 = read_vt(pusb_device, 0x007C);
+	id2 = read_vt(pusb_device, 0x007E);
+	SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2);
 /*---------------------------------------------------------------------------*/
 /*
  *  SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
 */
 /*---------------------------------------------------------------------------*/
-if (31 < easycap_gain)
-	easycap_gain = 31;
-if (0 > easycap_gain)
-	easycap_gain = 0;
-if (0 != audio_gainset(pusb_device, (__s8)easycap_gain))
-	SAY("ERROR: audio_gainset() failed\n");
-check_vt(pusb_device);
-return 0;
+	if (0 != audio_gainset(pusb_device, peasycap->gain))
+		SAY("ERROR: audio_gainset() failed\n");
+	check_vt(pusb_device);
+	return 0;
 }
 /*****************************************************************************/
-int
-check_vt(struct usb_device *pusb_device)
+int check_vt(struct usb_device *pusb_device)
 {
-int igot;
-
-if (!pusb_device)
-	return -ENODEV;
-igot = read_vt(pusb_device, 0x0002);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x02\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x02);
-
-igot = read_vt(pusb_device, 0x000E);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x0E\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x0E);
-
-igot = read_vt(pusb_device, 0x0010);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x10\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x10);
-
-igot = read_vt(pusb_device, 0x0012);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x12\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x12);
-
-igot = read_vt(pusb_device, 0x0014);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x14\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x14);
-
-igot = read_vt(pusb_device, 0x0016);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x16\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x16);
-
-igot = read_vt(pusb_device, 0x0018);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x18\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x18);
-
-igot = read_vt(pusb_device, 0x001C);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x1C\n");
-if (0x8000 & igot)
-	SAY("register 0x%02X muted\n", 0x1C);
-
-return 0;
+	int igot;
+
+	if (!pusb_device)
+		return -ENODEV;
+	igot = read_vt(pusb_device, 0x0002);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x02\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x02);
+
+	igot = read_vt(pusb_device, 0x000E);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x0E\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x0E);
+
+	igot = read_vt(pusb_device, 0x0010);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x10\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x10);
+
+	igot = read_vt(pusb_device, 0x0012);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x12\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x12);
+
+	igot = read_vt(pusb_device, 0x0014);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x14\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x14);
+
+	igot = read_vt(pusb_device, 0x0016);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x16\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x16);
+
+	igot = read_vt(pusb_device, 0x0018);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x18\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x18);
+
+	igot = read_vt(pusb_device, 0x001C);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x1C\n");
+	if (0x8000 & igot)
+		SAY("register 0x%02X muted\n", 0x1C);
+
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -1164,85 +1047,83 @@ return 0;
  *        31                12.0                  22.5            34.5
 */
 /*---------------------------------------------------------------------------*/
-int
-audio_gainset(struct usb_device *pusb_device, __s8 loud)
+int audio_gainset(struct usb_device *pusb_device, s8 loud)
 {
-int igot;
-__u8 u8;
-__u16 mute;
-
-if (NULL == pusb_device)
-	return -ENODEV;
-if (0 > loud)
-	loud = 0;
-if (31 < loud)
-	loud = 31;
-
-write_vt(pusb_device, 0x0002, 0x8000);
+	int igot;
+	u8 tmp;
+	u16 mute;
+
+	if (!pusb_device)
+		return -ENODEV;
+	if (0 > loud)
+		loud = 0;
+	if (31 < loud)
+		loud = 31;
+
+	write_vt(pusb_device, 0x0002, 0x8000);
 /*---------------------------------------------------------------------------*/
-igot = read_vt(pusb_device, 0x000E);
-if (0 > igot) {
-	SAY("ERROR: failed to read VT1612A register 0x0E\n");
-	mute = 0x0000;
-} else
-	mute = 0x8000 & ((unsigned int)igot);
-mute = 0;
-
-if (16 > loud)
-	u8 = 0x01 | (0x001F & (((__u8)(15 - loud)) << 1));
-else
-	u8 = 0;
-
-JOT(8, "0x%04X=(mute|u8) for VT1612A register 0x0E\n", mute | u8);
-write_vt(pusb_device, 0x000E, (mute | u8));
+	igot = read_vt(pusb_device, 0x000E);
+	if (0 > igot) {
+		SAY("ERROR: failed to read VT1612A register 0x0E\n");
+		mute = 0x0000;
+	} else
+		mute = 0x8000 & ((unsigned int)igot);
+	mute = 0;
+
+	if (16 > loud)
+		tmp = 0x01 | (0x001F & (((u8)(15 - loud)) << 1));
+	else
+		tmp = 0;
+
+	JOT(8, "0x%04X=(mute|tmp) for VT1612A register 0x0E\n", mute | tmp);
+	write_vt(pusb_device, 0x000E, (mute | tmp));
 /*---------------------------------------------------------------------------*/
-igot = read_vt(pusb_device, 0x0010);
-if (0 > igot) {
-	SAY("ERROR: failed to read VT1612A register 0x10\n");
-	mute = 0x0000;
-} else
-	mute = 0x8000 & ((unsigned int)igot);
-mute = 0;
-
-JOT(8, "0x%04X=(mute|u8|(u8<<8)) for VT1612A register 0x10,...0x18\n", \
-							mute | u8 | (u8 << 8));
-write_vt(pusb_device, 0x0010, (mute | u8 | (u8 << 8)));
-write_vt(pusb_device, 0x0012, (mute | u8 | (u8 << 8)));
-write_vt(pusb_device, 0x0014, (mute | u8 | (u8 << 8)));
-write_vt(pusb_device, 0x0016, (mute | u8 | (u8 << 8)));
-write_vt(pusb_device, 0x0018, (mute | u8 | (u8 << 8)));
+	igot = read_vt(pusb_device, 0x0010);
+	if (0 > igot) {
+		SAY("ERROR: failed to read VT1612A register 0x10\n");
+		mute = 0x0000;
+	} else
+		mute = 0x8000 & ((unsigned int)igot);
+	mute = 0;
+
+	JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x10,...0x18\n",
+						mute | tmp | (tmp << 8));
+	write_vt(pusb_device, 0x0010, (mute | tmp | (tmp << 8)));
+	write_vt(pusb_device, 0x0012, (mute | tmp | (tmp << 8)));
+	write_vt(pusb_device, 0x0014, (mute | tmp | (tmp << 8)));
+	write_vt(pusb_device, 0x0016, (mute | tmp | (tmp << 8)));
+	write_vt(pusb_device, 0x0018, (mute | tmp | (tmp << 8)));
 /*---------------------------------------------------------------------------*/
-igot = read_vt(pusb_device, 0x001C);
-if (0 > igot) {
-	SAY("ERROR: failed to read VT1612A register 0x1C\n");
-	mute = 0x0000;
-} else
-	mute = 0x8000 & ((unsigned int)igot);
-mute = 0;
-
-if (16 <= loud)
-	u8 = 0x000F & (__u8)(loud - 16);
-else
-	u8 = 0;
-
-JOT(8, "0x%04X=(mute|u8|(u8<<8)) for VT1612A register 0x1C\n", \
-							mute | u8 | (u8 << 8));
-write_vt(pusb_device, 0x001C, (mute | u8 | (u8 << 8)));
-write_vt(pusb_device, 0x001A, 0x0404);
-write_vt(pusb_device, 0x0002, 0x0000);
-return 0;
+	igot = read_vt(pusb_device, 0x001C);
+	if (0 > igot) {
+		SAY("ERROR: failed to read VT1612A register 0x1C\n");
+		mute = 0x0000;
+	} else
+		mute = 0x8000 & ((unsigned int)igot);
+	mute = 0;
+
+	if (16 <= loud)
+		tmp = 0x000F & (u8)(loud - 16);
+	else
+		tmp = 0;
+
+	JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x1C\n",
+						mute | tmp | (tmp << 8));
+	write_vt(pusb_device, 0x001C, (mute | tmp | (tmp << 8)));
+	write_vt(pusb_device, 0x001A, 0x0404);
+	write_vt(pusb_device, 0x0002, 0x0000);
+	return 0;
 }
 /*****************************************************************************/
-int
-audio_gainget(struct usb_device *pusb_device)
+int audio_gainget(struct usb_device *pusb_device)
 {
-int igot;
-
-if (NULL == pusb_device)
-	return -ENODEV;
-igot = read_vt(pusb_device, 0x001C);
-if (0 > igot)
-	SAY("ERROR: failed to read VT1612A register 0x1C\n");
-return igot;
+	int igot;
+
+	if (!pusb_device)
+		return -ENODEV;
+	igot = read_vt(pusb_device, 0x001C);
+	if (0 > igot)
+		SAY("ERROR: failed to read VT1612A register 0x1C\n");
+	return igot;
 }
 /*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_main.c b/drivers/staging/easycap/easycap_main.c
index acc1f56..cee3252 100644
--- a/drivers/staging/easycap/easycap_main.c
+++ b/drivers/staging/easycap/easycap_main.c
@@ -29,47 +29,86 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_standard.h"
-#include "easycap_ioctl.h"
+#include <linux/usb/audio.h>
 
-static int easycap_debug;
-static int easycap_bars;
-int easycap_gain = 16;
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
+MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
+MODULE_VERSION(EASYCAP_DRIVER_VERSION);
+
+#ifdef CONFIG_EASYCAP_DEBUG
+int easycap_debug;
 module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
+#endif /* CONFIG_EASYCAP_DEBUG */
+
+bool easycap_readback;
+module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(readback, "read back written registers: (default false)");
+
+static int easycap_bars = 1;
 module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(bars,
+	"Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
+
+static int easycap_gain = 16;
 module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
 
-/*---------------------------------------------------------------------------*/
-/*
- *  dongle_this IS INDISPENSIBLY static BECAUSE FUNCTION easycap_usb_probe()
- *  IS CALLED SUCCESSIVELY FOR INTERFACES 0, 1, 2 AND THE POINTER peasycap
- *  ALLOCATED DURING THE PROBING OF INTERFACE 0 MUST BE REMEMBERED WHEN
- *  PROBING INTERFACES 1 AND 2.
- *
- *  IOCTL LOCKING IS DONE AT MODULE LEVEL, NOT DEVICE LEVEL.
-*/
-/*---------------------------------------------------------------------------*/
+static bool easycap_ntsc;
+module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ntsc, "NTCS default encoding (default PAL)");
 
-struct easycap_dongle easycap_dongle[DONGLE_MANY];
-static int dongle_this;
-static int dongle_done;
 
-/*---------------------------------------------------------------------------*/
-/*
- *  PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
- */
-/*---------------------------------------------------------------------------*/
-struct usb_device_id easycap_usb_device_id_table[] = {
-{ USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID) },
-{ }
-};
-MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
-struct usb_driver easycap_usb_driver = {
-.name = "easycap",
-.id_table = easycap_usb_device_id_table,
-.probe = easycap_usb_probe,
-.disconnect = easycap_usb_disconnect,
-};
+
+struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
+static struct mutex mutex_dongle;
+static void easycap_complete(struct urb *purb);
+static int reset(struct easycap *peasycap);
+
+const char *strerror(int err)
+{
+#define ERRNOSTR(_e) case _e: return # _e
+	switch (err) {
+	case 0: return "OK";
+	ERRNOSTR(ENOMEM);
+	ERRNOSTR(ENODEV);
+	ERRNOSTR(ENXIO);
+	ERRNOSTR(EINVAL);
+	ERRNOSTR(EAGAIN);
+	ERRNOSTR(EFBIG);
+	ERRNOSTR(EPIPE);
+	ERRNOSTR(EMSGSIZE);
+	ERRNOSTR(ENOSPC);
+	ERRNOSTR(EINPROGRESS);
+	ERRNOSTR(ENOSR);
+	ERRNOSTR(EOVERFLOW);
+	ERRNOSTR(EPROTO);
+	ERRNOSTR(EILSEQ);
+	ERRNOSTR(ETIMEDOUT);
+	ERRNOSTR(EOPNOTSUPP);
+	ERRNOSTR(EPFNOSUPPORT);
+	ERRNOSTR(EAFNOSUPPORT);
+	ERRNOSTR(EADDRINUSE);
+	ERRNOSTR(EADDRNOTAVAIL);
+	ERRNOSTR(ENOBUFS);
+	ERRNOSTR(EISCONN);
+	ERRNOSTR(ENOTCONN);
+	ERRNOSTR(ESHUTDOWN);
+	ERRNOSTR(ENOENT);
+	ERRNOSTR(ECONNRESET);
+	ERRNOSTR(ETIME);
+	ERRNOSTR(ECOMM);
+	ERRNOSTR(EREMOTEIO);
+	ERRNOSTR(EXDEV);
+	ERRNOSTR(EPERM);
+	default: return "unknown";
+	}
+
+#undef ERRNOSTR
+}
+
 /*---------------------------------------------------------------------------*/
 /*
  *  PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE
@@ -79,171 +118,77 @@ struct usb_driver easycap_usb_driver = {
  *        THIS IS THE CASE FOR OpenSUSE.
  */
 /*---------------------------------------------------------------------------*/
-const struct file_operations easycap_fops = {
-	.owner		= THIS_MODULE,
-	.open		= easycap_open,
-	.release	= easycap_release,
-#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
-	.unlocked_ioctl	= easycap_ioctl_noinode,
-#else
-	.ioctl		= easycap_ioctl,
-#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
-	.poll		= easycap_poll,
-	.mmap		= easycap_mmap,
-	.llseek		= no_llseek,
-};
-struct vm_operations_struct easycap_vm_ops = {
-	.open  = easycap_vma_open,
-	.close = easycap_vma_close,
-	.fault = easycap_vma_fault,
-};
-struct usb_class_driver easycap_class = {
-	.name = "usb/easycap%d",
-	.fops = &easycap_fops,
-	.minor_base = USB_SKEL_MINOR_BASE,
-};
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-#if defined(EASYCAP_NEEDS_V4L2_FOPS)
-const struct v4l2_file_operations v4l2_fops = {
-	.owner		= THIS_MODULE,
-	.open		= easycap_open_noinode,
-	.release	= easycap_release_noinode,
-#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
-	.unlocked_ioctl	= easycap_ioctl_noinode,
-#else
-	.ioctl		= easycap_ioctl,
-#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
-	.poll		= easycap_poll,
-	.mmap		= easycap_mmap,
-};
-#endif /*EASYCAP_NEEDS_V4L2_FOPS*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*--------------------------------------------------------------------------*/
-/*
- *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
- */
-/*--------------------------------------------------------------------------*/
-const struct file_operations easysnd_fops = {
-	.owner		= THIS_MODULE,
-	.open		= easysnd_open,
-	.release	= easysnd_release,
-#if defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)
-	.unlocked_ioctl	= easysnd_ioctl_noinode,
-#else
-	.ioctl		= easysnd_ioctl,
-#endif /*EASYCAP_NEEDS_UNLOCKED_IOCTL*/
-	.read		= easysnd_read,
-	.llseek		= no_llseek,
-};
-struct usb_class_driver easysnd_class = {
-.name = "usb/easysnd%d",
-.fops = &easysnd_fops,
-.minor_base = USB_SKEL_MINOR_BASE,
-};
 /****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
 */
 /*---------------------------------------------------------------------------*/
-int
-isdongle(struct easycap *peasycap)
+int isdongle(struct easycap *peasycap)
 {
-int k;
-if (NULL == peasycap)
-	return -2;
-for (k = 0; k < DONGLE_MANY; k++) {
-	if (easycap_dongle[k].peasycap == peasycap) {
-		peasycap->isdongle = k;
-		return k;
+	int k;
+	if (!peasycap)
+		return -2;
+	for (k = 0; k < DONGLE_MANY; k++) {
+		if (easycapdc60_dongle[k].peasycap == peasycap) {
+			peasycap->isdongle = k;
+			return k;
+		}
 	}
+	return -1;
 }
-return -1;
-}
-/*****************************************************************************/
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-int
-easycap_open_noinode(struct file *file)
-{
-return easycap_open((struct inode *)NULL, file);
-}
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-int
-easycap_open(struct inode *inode, struct file *file)
+static int easycap_open(struct inode *inode, struct file *file)
 {
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-struct usb_interface *pusb_interface;
-#else
-struct video_device *pvideo_device;
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-struct easycap *peasycap;
-int rc;
+	struct video_device *pvideo_device;
+	struct easycap *peasycap;
+	int rc;
 
-JOT(4, "\n");
-SAY("==========OPEN=========\n");
+	JOT(4, "\n");
+	SAY("==========OPEN=========\n");
 
-peasycap = (struct easycap *)NULL;
-/*---------------------------------------------------------------------------*/
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-if ((struct inode *)NULL == inode) {
-	SAY("ERROR: inode is NULL.\n");
-	return -EFAULT;
-}
-pusb_interface = usb_find_interface(&easycap_usb_driver, iminor(inode));
-if (!pusb_interface) {
-	SAY("ERROR: pusb_interface is NULL.\n");
-	return -EFAULT;
-}
-peasycap = usb_get_intfdata(pusb_interface);
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#else
-pvideo_device = video_devdata(file);
-if ((struct video_device *)NULL == pvideo_device) {
-	SAY("ERROR: pvideo_device is NULL.\n");
-	return -EFAULT;
-}
-peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-if (NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-} else {
-	JOM(16, "0x%08lX=peasycap->pusb_device\n", \
-					(long int)peasycap->pusb_device);
-}
-file->private_data = peasycap;
-rc = wakeup_device(peasycap->pusb_device);
-if (0 == rc)
-	JOM(8, "wakeup_device() OK\n");
-else {
-	SAM("ERROR: wakeup_device() returned %i\n", rc);
-	if (-ENODEV == rc)
-		SAM("ERROR: wakeup_device() returned -ENODEV\n");
-	else
-		SAM("ERROR: wakeup_device() returned %i\n", rc);
-	return rc;
-}
-peasycap->input = 0;
-rc = reset(peasycap);
-if (0 != rc) {
-	SAM("ERROR: reset() returned %i\n", rc);
-	return -EFAULT;
-}
-return 0;
+	pvideo_device = video_devdata(file);
+	if (!pvideo_device) {
+		SAY("ERROR: pvideo_device is NULL.\n");
+		return -EFAULT;
+	}
+	peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	} else {
+		JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
+	}
+	file->private_data = peasycap;
+	rc = wakeup_device(peasycap->pusb_device);
+	if (0 == rc)
+		JOM(8, "wakeup_device() OK\n");
+	else {
+		SAM("ERROR: wakeup_device() rc = %i\n", rc);
+		if (-ENODEV == rc)
+			SAM("ERROR: wakeup_device() returned -ENODEV\n");
+		else
+			SAM("ERROR: wakeup_device() rc = %i\n", rc);
+		return rc;
+	}
+	peasycap->input = 0;
+	rc = reset(peasycap);
+	if (rc) {
+		SAM("ERROR: reset() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	return 0;
 }
+
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
@@ -253,18 +198,18 @@ return 0;
  *  A BAD VIDEO FRAME SIZE.
 */
 /*---------------------------------------------------------------------------*/
-int
-reset(struct easycap *peasycap)
+static int reset(struct easycap *peasycap)
 {
-struct easycap_standard const *peasycap_standard;
-int i, rc, input, rate;
-bool ntsc, other;
+	struct easycap_standard const *peasycap_standard;
+	int i, rc, input, rate;
+	bool ntsc, other;
+	int fmtidx;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-input = peasycap->input;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	input = peasycap->input;
 
 /*---------------------------------------------------------------------------*/
 /*
@@ -277,74 +222,70 @@ input = peasycap->input;
  *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
 */
 /*---------------------------------------------------------------------------*/
-other = false;
-if (true == peasycap->ntsc)
-	JOM(8, "true=peasycap->ntsc\n");
-else
-	JOM(8, "false=peasycap->ntsc\n");
-rate = ready_saa(peasycap->pusb_device);
-if (0 > rate) {
-	JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
-	if (true == peasycap->ntsc) {
-		JOM(8, "... trying PAL ...\n");  ntsc = false;
-	} else {
-		JOM(8, "... trying NTSC ...\n"); ntsc = true;
-}
-rc = setup_stk(peasycap->pusb_device, ntsc);
-if (0 == rc)
-	JOM(4, "setup_stk() OK\n");
-else {
-	SAM("ERROR: setup_stk() returned %i\n", rc);
-	return -EFAULT;
-}
-rc = setup_saa(peasycap->pusb_device, ntsc);
-if (0 == rc)
-	JOM(4, "setup_saa() OK\n");
-else {
-	SAM("ERROR: setup_saa() returned %i\n", rc);
-	return -EFAULT;
-}
-rate = ready_saa(peasycap->pusb_device);
-if (0 > rate) {
-	JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
-	JOM(8, "... saa register 0x1F has 0x%02X\n", \
-				read_saa(peasycap->pusb_device, 0x1F));
-	ntsc = peasycap->ntsc;
+	other = false;
+	JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
+
+	rate = ready_saa(peasycap->pusb_device);
+	if (0 > rate) {
+		JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
+		if (peasycap->ntsc) {
+			JOM(8, "... trying PAL ...\n");  ntsc = false;
+		} else {
+			JOM(8, "... trying NTSC ...\n"); ntsc = true;
+	}
+	rc = setup_stk(peasycap->pusb_device, ntsc);
+	if (0 == rc)
+		JOM(4, "setup_stk() OK\n");
+	else {
+		SAM("ERROR: setup_stk() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	rc = setup_saa(peasycap->pusb_device, ntsc);
+	if (0 == rc)
+		JOM(4, "setup_saa() OK\n");
+	else {
+		SAM("ERROR: setup_saa() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	rate = ready_saa(peasycap->pusb_device);
+	if (0 > rate) {
+		JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
+		JOM(8, "... saa register 0x1F has 0x%02X\n",
+					read_saa(peasycap->pusb_device, 0x1F));
+		ntsc = peasycap->ntsc;
+		} else {
+			JOM(8, "... success at second try:  %i=rate\n", rate);
+			ntsc = (0 < (rate/2)) ? true : false ;
+			other = true;
+		}
 	} else {
-		JOM(8, "... success at second try:  %i=rate\n", rate);
-		ntsc = (0 < (rate/2)) ? true : false ;
-		other = true;
+		JOM(8, "... success at first try:  %i=rate\n", rate);
+		ntsc = (0 < rate/2) ? true : false ;
 	}
-} else {
-	JOM(8, "... success at first try:  %i=rate\n", rate);
-	ntsc = (0 < rate/2) ? true : false ;
-}
-if (true == ntsc)
-	JOM(8, "true=ntsc\n");
-else
-	JOM(8, "false=ntsc\n");
-/*---------------------------------------------------------------------------*/
-
-rc = setup_stk(peasycap->pusb_device, ntsc);
-if (0 == rc)
-	JOM(4, "setup_stk() OK\n");
-else {
-	SAM("ERROR: setup_stk() returned %i\n", rc);
-	return -EFAULT;
-}
-rc = setup_saa(peasycap->pusb_device, ntsc);
-if (0 == rc)
-	JOM(4, "setup_saa() OK\n");
-else {
-	SAM("ERROR: setup_saa() returned %i\n", rc);
-	return -EFAULT;
-}
+	JOM(8, "ntsc=%d\n", ntsc);
+/*---------------------------------------------------------------------------*/
+
+	rc = setup_stk(peasycap->pusb_device, ntsc);
+	if (0 == rc)
+		JOM(4, "setup_stk() OK\n");
+	else {
+		SAM("ERROR: setup_stk() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	rc = setup_saa(peasycap->pusb_device, ntsc);
+	if (0 == rc)
+		JOM(4, "setup_saa() OK\n");
+	else {
+		SAM("ERROR: setup_saa() rc = %i\n", rc);
+		return -EFAULT;
+	}
+
+	for (i = 0; i < 180; i++)
+		peasycap->merit[i] = 0;
 
-for (i = 0; i < 180; i++)
-	peasycap->merit[i] = 0;
-peasycap->video_eof = 0;
-peasycap->audio_eof = 0;
-do_gettimeofday(&peasycap->timeval7);
+	peasycap->video_eof = 0;
+	peasycap->audio_eof = 0;
+	do_gettimeofday(&peasycap->timeval7);
 /*---------------------------------------------------------------------------*/
 /*
  * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
@@ -352,87 +293,75 @@ do_gettimeofday(&peasycap->timeval7);
  * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
 */
 /*---------------------------------------------------------------------------*/
-peasycap->input = -8192;
-peasycap->standard_offset = -8192;
-if (true == other) {
-	peasycap_standard = &easycap_standard[0];
-	while (0xFFFF != peasycap_standard->mask) {
-		if (true == ntsc) {
-			if (NTSC_M == \
-				peasycap_standard->v4l2_standard.index) {
-				peasycap->inputset[input].standard_offset = \
-						peasycap_standard - \
-							&easycap_standard[0];
-				break;
-			}
-		} else {
-			if (PAL_BGHIN == \
-				peasycap_standard->v4l2_standard.index) {
-				peasycap->inputset[input].standard_offset = \
-						peasycap_standard -
-							&easycap_standard[0];
+	peasycap->input = -8192;
+	peasycap->standard_offset = -8192;
+	fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
+	if (other) {
+		peasycap_standard = &easycap_standard[0];
+		while (0xFFFF != peasycap_standard->mask) {
+			if (fmtidx == peasycap_standard->v4l2_standard.index) {
+				peasycap->inputset[input].standard_offset =
+					peasycap_standard - easycap_standard;
 				break;
 			}
+			peasycap_standard++;
 		}
-		peasycap_standard++;
-	}
-	if (0xFFFF == peasycap_standard->mask) {
-		SAM("ERROR: standard not found\n");
-		return -EINVAL;
+		if (0xFFFF == peasycap_standard->mask) {
+			SAM("ERROR: standard not found\n");
+			return -EINVAL;
+		}
+		JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
+			peasycap->inputset[input].standard_offset, input);
 	}
-JOM(8, "%i=peasycap->inputset[%i].standard_offset\n", \
-		peasycap->inputset[input].standard_offset, input);
-}
-peasycap->format_offset = -8192;
-peasycap->brightness = -8192;
-peasycap->contrast = -8192;
-peasycap->saturation = -8192;
-peasycap->hue = -8192;
+	peasycap->format_offset = -8192;
+	peasycap->brightness = -8192;
+	peasycap->contrast = -8192;
+	peasycap->saturation = -8192;
+	peasycap->hue = -8192;
 
-rc = newinput(peasycap, input);
+	rc = newinput(peasycap, input);
 
-if (0 == rc)
+	if (rc) {
+		SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
+		return -EFAULT;
+	}
 	JOM(4, "restored input, standard and format\n");
-else {
-	SAM("ERROR: newinput(.,%i) returned %i\n", rc, input);
-	return -EFAULT;
-}
-if (true == peasycap->ntsc)
-	JOM(8, "true=peasycap->ntsc\n");
-else
-	JOM(8, "false=peasycap->ntsc\n");
-
-if (0 > peasycap->input) {
-	SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
-	return -ENOENT;
-}
-if (0 > peasycap->standard_offset) {
-	SAM("MISTAKE:  %i=peasycap->standard_offset\n", \
-						peasycap->standard_offset);
-	return -ENOENT;
-}
-if (0 > peasycap->format_offset) {
-	SAM("MISTAKE:  %i=peasycap->format_offset\n", \
-						peasycap->format_offset);
-	return -ENOENT;
-}
-if (0 > peasycap->brightness) {
-	SAM("MISTAKE:  %i=peasycap->brightness\n", peasycap->brightness);
-	return -ENOENT;
-}
-if (0 > peasycap->contrast) {
-	SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
-	return -ENOENT;
-}
-if (0 > peasycap->saturation) {
-	SAM("MISTAKE:  %i=peasycap->saturation\n", peasycap->saturation);
-	return -ENOENT;
-}
-if (0 > peasycap->hue) {
-	SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
-	return -ENOENT;
-}
-return 0;
+
+	JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
+
+	if (0 > peasycap->input) {
+		SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
+		return -ENOENT;
+	}
+	if (0 > peasycap->standard_offset) {
+		SAM("MISTAKE:  %i=peasycap->standard_offset\n",
+				peasycap->standard_offset);
+		return -ENOENT;
+	}
+	if (0 > peasycap->format_offset) {
+		SAM("MISTAKE:  %i=peasycap->format_offset\n",
+				peasycap->format_offset);
+		return -ENOENT;
+	}
+	if (0 > peasycap->brightness) {
+		SAM("MISTAKE:  %i=peasycap->brightness\n",
+				peasycap->brightness);
+		return -ENOENT;
+	}
+	if (0 > peasycap->contrast) {
+		SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
+		return -ENOENT;
+	}
+	if (0 > peasycap->saturation) {
+		SAM("MISTAKE:  %i=peasycap->saturation\n",
+				peasycap->saturation);
+		return -ENOENT;
+	}
+	if (0 > peasycap->hue) {
+		SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
+		return -ENOENT;
+	}
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -454,21 +383,21 @@ return 0;
 int
 newinput(struct easycap *peasycap, int input)
 {
-int rc, k, m, mood, off;
-int inputnow, video_idlenow, audio_idlenow;
-bool resubmit;
+	int rc, k, m, mood, off;
+	int inputnow, video_idlenow, audio_idlenow;
+	bool resubmit;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-JOM(8, "%i=input sought\n", input);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	JOM(8, "%i=input sought\n", input);
 
-if (0 > input && INPUT_MANY <= input)
-	return -ENOENT;
-inputnow = peasycap->input;
-if (input == inputnow)
-	return 0;
+	if (0 > input && INPUT_MANY <= input)
+		return -ENOENT;
+	inputnow = peasycap->input;
+	if (input == inputnow)
+		return 0;
 /*---------------------------------------------------------------------------*/
 /*
  *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
@@ -477,414 +406,317 @@ if (input == inputnow)
  *  ROUTINE.
 */
 /*---------------------------------------------------------------------------*/
-video_idlenow = peasycap->video_idle;
-audio_idlenow = peasycap->audio_idle;
+	video_idlenow = peasycap->video_idle;
+	audio_idlenow = peasycap->audio_idle;
 
-peasycap->video_idle = 1;
-peasycap->audio_idle = 1;
-if (peasycap->video_isoc_streaming) {
-	resubmit = true;
-	kill_video_urbs(peasycap);
-} else
-	resubmit = false;
-/*---------------------------------------------------------------------------*/
-if (NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -ENODEV;
-}
-rc = usb_set_interface(peasycap->pusb_device,
-			peasycap->video_interface, \
-			peasycap->video_altsetting_off);
-if (0 != rc) {
-	SAM("ERROR: usb_set_interface() returned %i\n", rc);
-	return -EFAULT;
-}
-rc = stop_100(peasycap->pusb_device);
-if (0 != rc) {
-	SAM("ERROR: stop_100() returned %i\n", rc);
-	return -EFAULT;
-}
-for (k = 0; k < FIELD_BUFFER_MANY; k++) {
-	for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
-		memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
-}
-for (k = 0; k < FRAME_BUFFER_MANY; k++) {
-	for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
-		memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
-}
-peasycap->field_page = 0;
-peasycap->field_read = 0;
-peasycap->field_fill = 0;
-
-peasycap->frame_read = 0;
-peasycap->frame_fill = 0;
-for (k = 0; k < peasycap->input; k++) {
-	(peasycap->frame_fill)++;
-	if (peasycap->frame_buffer_many <= peasycap->frame_fill)
-		peasycap->frame_fill = 0;
-}
-peasycap->input = input;
-select_input(peasycap->pusb_device, peasycap->input, 9);
+	peasycap->video_idle = 1;
+	peasycap->audio_idle = 1;
+	if (peasycap->video_isoc_streaming) {
+		resubmit = true;
+		kill_video_urbs(peasycap);
+	} else {
+		resubmit = false;
+	}
 /*---------------------------------------------------------------------------*/
-if (input == peasycap->inputset[input].input) {
-	off = peasycap->inputset[input].standard_offset;
-	if (off != peasycap->standard_offset) {
-		rc = adjust_standard(peasycap, \
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -ENODEV;
+	}
+	rc = usb_set_interface(peasycap->pusb_device,
+				peasycap->video_interface,
+				peasycap->video_altsetting_off);
+	if (rc) {
+		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	rc = stop_100(peasycap->pusb_device);
+	if (rc) {
+		SAM("ERROR: stop_100() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	for (k = 0; k < FIELD_BUFFER_MANY; k++) {
+		for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
+			memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
+	}
+	for (k = 0; k < FRAME_BUFFER_MANY; k++) {
+		for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
+			memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
+	}
+	peasycap->field_page = 0;
+	peasycap->field_read = 0;
+	peasycap->field_fill = 0;
+
+	peasycap->frame_read = 0;
+	peasycap->frame_fill = 0;
+	for (k = 0; k < peasycap->input; k++) {
+		(peasycap->frame_fill)++;
+		if (peasycap->frame_buffer_many <= peasycap->frame_fill)
+			peasycap->frame_fill = 0;
+	}
+	peasycap->input = input;
+	select_input(peasycap->pusb_device, peasycap->input, 9);
+/*---------------------------------------------------------------------------*/
+	if (input == peasycap->inputset[input].input) {
+		off = peasycap->inputset[input].standard_offset;
+		if (off != peasycap->standard_offset) {
+			rc = adjust_standard(peasycap,
 				easycap_standard[off].v4l2_standard.id);
-		if (0 != rc) {
-			SAM("ERROR: adjust_standard() returned %i\n", rc);
-			return -EFAULT;
-		}
-		JOM(8, "%i=peasycap->standard_offset\n", \
-						peasycap->standard_offset);
-	} else {
-		JOM(8, "%i=peasycap->standard_offset unchanged\n", \
+			if (rc) {
+				SAM("ERROR: adjust_standard() rc = %i\n", rc);
+				return -EFAULT;
+			}
+			JOM(8, "%i=peasycap->standard_offset\n",
+				peasycap->standard_offset);
+		} else {
+			JOM(8, "%i=peasycap->standard_offset unchanged\n",
 						peasycap->standard_offset);
-	}
-	off = peasycap->inputset[input].format_offset;
-	if (off != peasycap->format_offset) {
-		rc = adjust_format(peasycap, \
-			easycap_format[off].v4l2_format.fmt.pix.width, \
-			easycap_format[off].v4l2_format.fmt.pix.height, \
-			easycap_format[off].v4l2_format.fmt.pix.pixelformat, \
-			easycap_format[off].v4l2_format.fmt.pix.field, false);
-		if (0 > rc) {
-			SAM("ERROR: adjust_format() returned %i\n", rc);
-			return -EFAULT;
 		}
-		JOM(8, "%i=peasycap->format_offset\n", peasycap->format_offset);
-	} else {
-		JOM(8, "%i=peasycap->format_offset unchanged\n", \
-						peasycap->format_offset);
-	}
-	mood = peasycap->inputset[input].brightness;
-	if (mood != peasycap->brightness) {
-		rc = adjust_brightness(peasycap, mood);
-		if (0 != rc) {
-			SAM("ERROR: adjust_brightness returned %i\n", rc);
-			return -EFAULT;
+		off = peasycap->inputset[input].format_offset;
+		if (off != peasycap->format_offset) {
+			struct v4l2_pix_format *pix =
+				&easycap_format[off].v4l2_format.fmt.pix;
+			rc = adjust_format(peasycap,
+				pix->width, pix->height,
+				pix->pixelformat, pix->field, false);
+			if (0 > rc) {
+				SAM("ERROR: adjust_format() rc = %i\n", rc);
+				return -EFAULT;
+			}
+			JOM(8, "%i=peasycap->format_offset\n",
+					peasycap->format_offset);
+		} else {
+			JOM(8, "%i=peasycap->format_offset unchanged\n",
+					peasycap->format_offset);
 		}
-		JOM(8, "%i=peasycap->brightness\n", peasycap->brightness);
-	}
-	mood = peasycap->inputset[input].contrast;
-	if (mood != peasycap->contrast) {
-		rc = adjust_contrast(peasycap, mood);
-		if (0 != rc) {
-			SAM("ERROR: adjust_contrast returned %i\n", rc);
-			return -EFAULT;
+		mood = peasycap->inputset[input].brightness;
+		if (mood != peasycap->brightness) {
+			rc = adjust_brightness(peasycap, mood);
+			if (rc) {
+				SAM("ERROR: adjust_brightness rc = %i\n", rc);
+				return -EFAULT;
+			}
+			JOM(8, "%i=peasycap->brightness\n",
+					peasycap->brightness);
 		}
-		JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
-	}
-	mood = peasycap->inputset[input].saturation;
-	if (mood != peasycap->saturation) {
-		rc = adjust_saturation(peasycap, mood);
-		if (0 != rc) {
-			SAM("ERROR: adjust_saturation returned %i\n", rc);
-			return -EFAULT;
+		mood = peasycap->inputset[input].contrast;
+		if (mood != peasycap->contrast) {
+			rc = adjust_contrast(peasycap, mood);
+			if (rc) {
+				SAM("ERROR: adjust_contrast rc = %i\n", rc);
+				return -EFAULT;
+			}
+			JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
 		}
-		JOM(8, "%i=peasycap->saturation\n", peasycap->saturation);
-	}
-	mood = peasycap->inputset[input].hue;
-	if (mood != peasycap->hue) {
-		rc = adjust_hue(peasycap, mood);
-		if (0 != rc) {
-			SAM("ERROR: adjust_hue returned %i\n", rc);
-			return -EFAULT;
+		mood = peasycap->inputset[input].saturation;
+		if (mood != peasycap->saturation) {
+			rc = adjust_saturation(peasycap, mood);
+			if (rc) {
+				SAM("ERROR: adjust_saturation rc = %i\n", rc);
+				return -EFAULT;
+			}
+			JOM(8, "%i=peasycap->saturation\n",
+					peasycap->saturation);
+		}
+		mood = peasycap->inputset[input].hue;
+		if (mood != peasycap->hue) {
+			rc = adjust_hue(peasycap, mood);
+			if (rc) {
+				SAM("ERROR: adjust_hue rc = %i\n", rc);
+				return -EFAULT;
+			}
+			JOM(8, "%i=peasycap->hue\n", peasycap->hue);
 		}
-		JOM(8, "%i=peasycap->hue\n", peasycap->hue);
+	} else {
+		SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
+		return -ENOENT;
 	}
-} else {
-	SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
-	return -ENOENT;
-}
 /*---------------------------------------------------------------------------*/
-if (NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -ENODEV;
-}
-rc = usb_set_interface(peasycap->pusb_device,
-			peasycap->video_interface, \
-			peasycap->video_altsetting_on);
-if (0 != rc) {
-	SAM("ERROR: usb_set_interface() returned %i\n", rc);
-	return -EFAULT;
-}
-rc = start_100(peasycap->pusb_device);
-if (0 != rc) {
-	SAM("ERROR: start_100() returned %i\n", rc);
-	return -EFAULT;
-}
-if (true == resubmit)
-	submit_video_urbs(peasycap);
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -ENODEV;
+	}
+	rc = usb_set_interface(peasycap->pusb_device,
+				peasycap->video_interface,
+				peasycap->video_altsetting_on);
+	if (rc) {
+		SAM("ERROR: usb_set_interface() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	rc = start_100(peasycap->pusb_device);
+	if (rc) {
+		SAM("ERROR: start_100() rc = %i\n", rc);
+		return -EFAULT;
+	}
+	if (resubmit)
+		submit_video_urbs(peasycap);
 
-peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
-peasycap->video_idle = video_idlenow;
-peasycap->audio_idle = audio_idlenow;
-peasycap->video_junk = 0;
+	peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
+	peasycap->video_idle = video_idlenow;
+	peasycap->audio_idle = audio_idlenow;
+	peasycap->video_junk = 0;
 
-return 0;
+	return 0;
 }
 /*****************************************************************************/
-int
-submit_video_urbs(struct easycap *peasycap)
+int submit_video_urbs(struct easycap *peasycap)
 {
-struct data_urb *pdata_urb;
-struct urb *purb;
-struct list_head *plist_head;
-int j, isbad, nospc, m, rc;
-int isbuf;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
+	struct data_urb *pdata_urb;
+	struct urb *purb;
+	struct list_head *plist_head;
+	int j, isbad, nospc, m, rc;
+	int isbuf;
 
-if (NULL == peasycap->purb_video_head) {
-	SAY("ERROR: peasycap->urb_video_head uninitialized\n");
-	return -EFAULT;
-}
-if (NULL == peasycap->pusb_device) {
-	SAY("ERROR: peasycap->pusb_device is NULL\n");
-	return -ENODEV;
-}
-if (!peasycap->video_isoc_streaming) {
-	JOM(4, "submission of all video urbs\n");
-	isbad = 0;  nospc = 0;  m = 0;
-	list_for_each(plist_head, (peasycap->purb_video_head)) {
-		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-		if (NULL != pdata_urb) {
-			purb = pdata_urb->purb;
-			if (NULL != purb) {
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+
+	if (!peasycap->purb_video_head) {
+		SAY("ERROR: peasycap->urb_video_head uninitialized\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAY("ERROR: peasycap->pusb_device is NULL\n");
+		return -ENODEV;
+	}
+	if (!peasycap->video_isoc_streaming) {
+		JOM(4, "submission of all video urbs\n");
+		isbad = 0;  nospc = 0;  m = 0;
+		list_for_each(plist_head, (peasycap->purb_video_head)) {
+			pdata_urb = list_entry(plist_head,
+						struct data_urb, list_head);
+			if (pdata_urb && pdata_urb->purb) {
+				purb = pdata_urb->purb;
 				isbuf = pdata_urb->isbuf;
 				purb->interval = 1;
 				purb->dev = peasycap->pusb_device;
-				purb->pipe = \
-					usb_rcvisocpipe(peasycap->pusb_device,\
+				purb->pipe =
+					usb_rcvisocpipe(peasycap->pusb_device,
 					peasycap->video_endpointnumber);
 				purb->transfer_flags = URB_ISO_ASAP;
-				purb->transfer_buffer = \
+				purb->transfer_buffer =
 					peasycap->video_isoc_buffer[isbuf].pgo;
-				purb->transfer_buffer_length = \
+				purb->transfer_buffer_length =
 					peasycap->video_isoc_buffer_size;
 				purb->complete = easycap_complete;
 				purb->context = peasycap;
 				purb->start_frame = 0;
-				purb->number_of_packets = \
+				purb->number_of_packets =
 					peasycap->video_isoc_framesperdesc;
 
-				for (j = 0;  j < peasycap->\
-					video_isoc_framesperdesc; j++) {
-						purb->iso_frame_desc[j].\
-						offset = j * \
-						peasycap->\
-						video_isoc_maxframesize;
-						purb->iso_frame_desc[j].\
-						length = peasycap->\
-						video_isoc_maxframesize;
-					}
+				for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
+					purb->iso_frame_desc[j]. offset =
+						j * peasycap->video_isoc_maxframesize;
+					purb->iso_frame_desc[j]. length =
+						peasycap->video_isoc_maxframesize;
+				}
 
 				rc = usb_submit_urb(purb, GFP_KERNEL);
-				if (0 != rc) {
+				if (rc) {
 					isbad++;
-					SAM("ERROR: usb_submit_urb() failed " \
-							"for urb with rc:\n");
-					switch (rc) {
-					case -ENOMEM: {
-						SAM("ERROR: -ENOMEM=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -ENODEV: {
-						SAM("ERROR: -ENODEV=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -ENXIO: {
-						SAM("ERROR: -ENXIO=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -EINVAL: {
-						SAM("ERROR: -EINVAL=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -EAGAIN: {
-						SAM("ERROR: -EAGAIN=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -EFBIG: {
-						SAM("ERROR: -EFBIG=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -EPIPE: {
-						SAM("ERROR: -EPIPE=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -EMSGSIZE: {
-						SAM("ERROR: -EMSGSIZE=" \
-							"usb_submit_urb()\n");
-						break;
-					}
-					case -ENOSPC: {
+					SAM("ERROR: usb_submit_urb() failed "
+						"for urb with rc:-%s\n",
+							strerror(rc));
+					if (rc == -ENOSPC)
 						nospc++;
-						break;
-					}
-					default: {
-						SAM("ERROR: %i=" \
-							"usb_submit_urb()\n",\
-							rc);
-						break;
-					}
-					}
 				} else {
 					m++;
 				}
-				} else {
-					 isbad++;
-				}
 			} else {
-				 isbad++;
+				isbad++;
 			}
 		}
-	if (nospc) {
-		SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
-		SAM(".....  possibly inadequate USB bandwidth\n");
-		peasycap->video_eof = 1;
-	}
+		if (nospc) {
+			SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
+			SAM(".....  possibly inadequate USB bandwidth\n");
+			peasycap->video_eof = 1;
+		}
 
-	if (isbad) {
-		JOM(4, "attempting cleanup instead of submitting\n");
-		list_for_each(plist_head, (peasycap->purb_video_head)) {
-			pdata_urb = list_entry(plist_head, struct data_urb, \
-								list_head);
-			if (NULL != pdata_urb) {
-				purb = pdata_urb->purb;
-				if (NULL != purb)
-					usb_kill_urb(purb);
+		if (isbad) {
+			JOM(4, "attempting cleanup instead of submitting\n");
+			list_for_each(plist_head, (peasycap->purb_video_head)) {
+				pdata_urb = list_entry(plist_head,
+						struct data_urb, list_head);
+				if (pdata_urb) {
+					purb = pdata_urb->purb;
+					if (purb)
+						usb_kill_urb(purb);
+				}
 			}
+			peasycap->video_isoc_streaming = 0;
+		} else {
+			peasycap->video_isoc_streaming = 1;
+			JOM(4, "submitted %i video urbs\n", m);
 		}
-		peasycap->video_isoc_streaming = 0;
 	} else {
-		peasycap->video_isoc_streaming = 1;
-		JOM(4, "submitted %i video urbs\n", m);
+		JOM(4, "already streaming video urbs\n");
 	}
-} else {
-	JOM(4, "already streaming video urbs\n");
-}
-return 0;
+	return 0;
 }
 /*****************************************************************************/
-int
-kill_video_urbs(struct easycap *peasycap)
+int kill_video_urbs(struct easycap *peasycap)
 {
-int m;
-struct list_head *plist_head;
-struct data_urb *pdata_urb;
+	int m;
+	struct list_head *plist_head;
+	struct data_urb *pdata_urb;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if (peasycap->video_isoc_streaming) {
-	if ((struct list_head *)NULL != peasycap->purb_video_head) {
-		peasycap->video_isoc_streaming = 0;
-		JOM(4, "killing video urbs\n");
-		m = 0;
-		list_for_each(plist_head, (peasycap->purb_video_head)) {
-			pdata_urb = list_entry(plist_head, struct data_urb, \
-								list_head);
-			if (NULL != pdata_urb) {
-				if (NULL != pdata_urb->purb) {
-					usb_kill_urb(pdata_urb->purb);
-					m++;
-				}
-			}
-		}
-		JOM(4, "%i video urbs killed\n", m);
-	} else {
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->video_isoc_streaming) {
+		JOM(8, "%i=video_isoc_streaming, no video urbs killed\n",
+			peasycap->video_isoc_streaming);
+		return 0;
+	}
+	if (!peasycap->purb_video_head) {
 		SAM("ERROR: peasycap->purb_video_head is NULL\n");
 		return -EFAULT;
 	}
-} else {
-	JOM(8, "%i=video_isoc_streaming, no video urbs killed\n", \
-					peasycap->video_isoc_streaming);
-}
-return 0;
+
+	peasycap->video_isoc_streaming = 0;
+	JOM(4, "killing video urbs\n");
+	m = 0;
+	list_for_each(plist_head, (peasycap->purb_video_head)) {
+		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
+		if (pdata_urb && pdata_urb->purb) {
+			usb_kill_urb(pdata_urb->purb);
+			m++;
+		}
+	}
+	JOM(4, "%i video urbs killed\n", m);
+
+	return 0;
 }
 /****************************************************************************/
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-int
-easycap_release_noinode(struct file *file)
-{
-return easycap_release((struct inode *)NULL, file);
-}
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 /*--------------------------------------------------------------------------*/
-int
-easycap_release(struct inode *inode, struct file *file)
+static int easycap_open_noinode(struct file *file)
 {
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-struct easycap *peasycap;
-
-JOT(4, "\n");
-
-peasycap = file->private_data;
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL.\n");
-	SAY("ending unsuccessfully\n");
-	return -EFAULT;
+	return easycap_open(NULL, file);
 }
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-if (0 != kill_video_urbs(peasycap)) {
-	SAM("ERROR: kill_video_urbs() failed\n");
-	return -EFAULT;
-}
-JOM(4, "ending successfully\n");
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#else
-#
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 
-return 0;
-}
-/****************************************************************************/
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-int
-videodev_release(struct video_device *pvideo_device)
+static int videodev_release(struct video_device *pvideo_device)
 {
-struct easycap *peasycap;
+	struct easycap *peasycap;
 
-JOT(4, "\n");
-
-peasycap = video_get_drvdata(pvideo_device);
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL\n");
-	SAY("ending unsuccessfully\n");
-	return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-if (0 != kill_video_urbs(peasycap)) {
-	SAM("ERROR: kill_video_urbs() failed\n");
-	return -EFAULT;
-}
-JOM(4, "ending successfully\n");
-return 0;
+	peasycap = video_get_drvdata(pvideo_device);
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL\n");
+		SAY("ending unsuccessfully\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return -EFAULT;
+	}
+	if (0 != kill_video_urbs(peasycap)) {
+		SAM("ERROR: kill_video_urbs() failed\n");
+		return -EFAULT;
+	}
+	JOM(4, "ending successfully\n");
+	return 0;
 }
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 /*****************************************************************************/
 /*--------------------------------------------------------------------------*/
@@ -896,318 +728,331 @@ return 0;
  *  peasycap->pusb_device IS NO LONGER VALID.
  */
 /*---------------------------------------------------------------------------*/
-void
-easycap_delete(struct kref *pkref)
+static void easycap_delete(struct kref *pkref)
 {
-int k, m, gone, kd;
-int allocation_video_urb, allocation_video_page, allocation_video_struct;
-int allocation_audio_urb, allocation_audio_page, allocation_audio_struct;
-int registered_video, registered_audio;
-struct easycap *peasycap;
-struct data_urb *pdata_urb;
-struct list_head *plist_head, *plist_next;
-
-JOT(4, "\n");
-
-peasycap = container_of(pkref, struct easycap, kref);
-if (NULL == peasycap) {
-	SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
-	return;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return;
-}
-kd = isdongle(peasycap);
+	struct easycap *peasycap;
+	struct data_urb *pdata_urb;
+	struct list_head *plist_head, *plist_next;
+	int k, m, gone, kd;
+	int allocation_video_urb;
+	int allocation_video_page;
+	int allocation_video_struct;
+	int allocation_audio_urb;
+	int allocation_audio_page;
+	int allocation_audio_struct;
+	int registered_video, registered_audio;
+
+	peasycap = container_of(pkref, struct easycap, kref);
+	if (!peasycap) {
+		SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
+		return;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return;
+	}
+	kd = isdongle(peasycap);
 /*---------------------------------------------------------------------------*/
 /*
  *  FREE VIDEO.
  */
 /*---------------------------------------------------------------------------*/
-if ((struct list_head *)NULL != peasycap->purb_video_head) {
-	JOM(4, "freeing video urbs\n");
-	m = 0;
-	list_for_each(plist_head, (peasycap->purb_video_head)) {
-		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-		if (NULL == pdata_urb)
-			JOM(4, "ERROR: pdata_urb is NULL\n");
-		else {
-			if ((struct urb *)NULL != pdata_urb->purb) {
-				usb_free_urb(pdata_urb->purb);
-				pdata_urb->purb = (struct urb *)NULL;
-				peasycap->allocation_video_urb -= 1;
+	if (peasycap->purb_video_head) {
+		JOM(4, "freeing video urbs\n");
+		m = 0;
+		list_for_each(plist_head, (peasycap->purb_video_head)) {
+			pdata_urb = list_entry(plist_head,
+						struct data_urb, list_head);
+			if (!pdata_urb) {
+				JOM(4, "ERROR: pdata_urb is NULL\n");
+			} else {
+				if (pdata_urb->purb) {
+					usb_free_urb(pdata_urb->purb);
+					pdata_urb->purb = NULL;
+					peasycap->allocation_video_urb -= 1;
+					m++;
+				}
+			}
+		}
+
+		JOM(4, "%i video urbs freed\n", m);
+/*---------------------------------------------------------------------------*/
+		JOM(4, "freeing video data_urb structures.\n");
+		m = 0;
+		list_for_each_safe(plist_head, plist_next,
+					peasycap->purb_video_head) {
+			pdata_urb = list_entry(plist_head,
+						struct data_urb, list_head);
+			if (pdata_urb) {
+				peasycap->allocation_video_struct -=
+						sizeof(struct data_urb);
+				kfree(pdata_urb);
+				pdata_urb = NULL;
 				m++;
 			}
 		}
+		JOM(4, "%i video data_urb structures freed\n", m);
+		JOM(4, "setting peasycap->purb_video_head=NULL\n");
+		peasycap->purb_video_head = NULL;
 	}
-
-	JOM(4, "%i video urbs freed\n", m);
 /*---------------------------------------------------------------------------*/
-	JOM(4, "freeing video data_urb structures.\n");
+	JOM(4, "freeing video isoc buffers.\n");
 	m = 0;
-	list_for_each_safe(plist_head, plist_next, peasycap->purb_video_head) {
-		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-		if ((struct data_urb *)NULL != pdata_urb) {
-			kfree(pdata_urb);  pdata_urb = (struct data_urb *)NULL;
-			peasycap->allocation_video_struct -= \
-						sizeof(struct data_urb);
+	for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY;  k++) {
+		if (peasycap->video_isoc_buffer[k].pgo) {
+			free_pages((unsigned long)
+				   peasycap->video_isoc_buffer[k].pgo,
+					VIDEO_ISOC_ORDER);
+			peasycap->video_isoc_buffer[k].pgo = NULL;
+			peasycap->allocation_video_page -=
+						BIT(VIDEO_ISOC_ORDER);
 			m++;
 		}
 	}
-	JOM(4, "%i video data_urb structures freed\n", m);
-	JOM(4, "setting peasycap->purb_video_head=NULL\n");
-	peasycap->purb_video_head = (struct list_head *)NULL;
-}
+	JOM(4, "isoc video buffers freed: %i pages\n",
+			m * (0x01 << VIDEO_ISOC_ORDER));
 /*---------------------------------------------------------------------------*/
-JOM(4, "freeing video isoc buffers.\n");
-m = 0;
-for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY;  k++) {
-	if ((void *)NULL != peasycap->video_isoc_buffer[k].pgo) {
-		free_pages((unsigned long)\
-				(peasycap->video_isoc_buffer[k].pgo), \
-				VIDEO_ISOC_ORDER);
-		peasycap->video_isoc_buffer[k].pgo = (void *)NULL;
-		peasycap->allocation_video_page -= \
-				((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
-		m++;
-	}
-}
-JOM(4, "isoc video buffers freed: %i pages\n", m * (0x01 << VIDEO_ISOC_ORDER));
-/*---------------------------------------------------------------------------*/
-JOM(4, "freeing video field buffers.\n");
-gone = 0;
-for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
-	for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
-		if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
-			free_page((unsigned long)\
-					(peasycap->field_buffer[k][m].pgo));
-			peasycap->field_buffer[k][m].pgo = (void *)NULL;
-			peasycap->allocation_video_page -= 1;
-			gone++;
+	JOM(4, "freeing video field buffers.\n");
+	gone = 0;
+	for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
+		for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
+			if (peasycap->field_buffer[k][m].pgo) {
+				free_page((unsigned long)
+					  peasycap->field_buffer[k][m].pgo);
+				peasycap->field_buffer[k][m].pgo = NULL;
+				peasycap->allocation_video_page -= 1;
+				gone++;
+			}
 		}
 	}
-}
-JOM(4, "video field buffers freed: %i pages\n", gone);
-/*---------------------------------------------------------------------------*/
-JOM(4, "freeing video frame buffers.\n");
-gone = 0;
-for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
-	for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
-		if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) {
-			free_page((unsigned long)\
-					(peasycap->frame_buffer[k][m].pgo));
-			peasycap->frame_buffer[k][m].pgo = (void *)NULL;
-			peasycap->allocation_video_page -= 1;
-			gone++;
+	JOM(4, "video field buffers freed: %i pages\n", gone);
+/*---------------------------------------------------------------------------*/
+	JOM(4, "freeing video frame buffers.\n");
+	gone = 0;
+	for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
+		for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
+			if (peasycap->frame_buffer[k][m].pgo) {
+				free_page((unsigned long)
+					  peasycap->frame_buffer[k][m].pgo);
+				peasycap->frame_buffer[k][m].pgo = NULL;
+				peasycap->allocation_video_page -= 1;
+				gone++;
+			}
 		}
 	}
-}
-JOM(4, "video frame buffers freed: %i pages\n", gone);
+	JOM(4, "video frame buffers freed: %i pages\n", gone);
 /*---------------------------------------------------------------------------*/
 /*
  *  FREE AUDIO.
  */
 /*---------------------------------------------------------------------------*/
-if ((struct list_head *)NULL != peasycap->purb_audio_head) {
-	JOM(4, "freeing audio urbs\n");
-	m = 0;
-	list_for_each(plist_head, (peasycap->purb_audio_head)) {
-		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-		if (NULL == pdata_urb)
-			JOM(4, "ERROR: pdata_urb is NULL\n");
-		else {
-			if ((struct urb *)NULL != pdata_urb->purb) {
-				usb_free_urb(pdata_urb->purb);
-				pdata_urb->purb = (struct urb *)NULL;
-				peasycap->allocation_audio_urb -= 1;
+	if (peasycap->purb_audio_head) {
+		JOM(4, "freeing audio urbs\n");
+		m = 0;
+		list_for_each(plist_head, (peasycap->purb_audio_head)) {
+			pdata_urb = list_entry(plist_head,
+					struct data_urb, list_head);
+			if (!pdata_urb)
+				JOM(4, "ERROR: pdata_urb is NULL\n");
+			else {
+				if (pdata_urb->purb) {
+					usb_free_urb(pdata_urb->purb);
+					pdata_urb->purb = NULL;
+					peasycap->allocation_audio_urb -= 1;
+					m++;
+				}
+			}
+		}
+		JOM(4, "%i audio urbs freed\n", m);
+/*---------------------------------------------------------------------------*/
+		JOM(4, "freeing audio data_urb structures.\n");
+		m = 0;
+		list_for_each_safe(plist_head, plist_next,
+					peasycap->purb_audio_head) {
+			pdata_urb = list_entry(plist_head,
+					struct data_urb, list_head);
+			if (pdata_urb) {
+				peasycap->allocation_audio_struct -=
+							sizeof(struct data_urb);
+				kfree(pdata_urb);
+				pdata_urb = NULL;
 				m++;
 			}
 		}
+		JOM(4, "%i audio data_urb structures freed\n", m);
+		JOM(4, "setting peasycap->purb_audio_head=NULL\n");
+		peasycap->purb_audio_head = NULL;
 	}
-	JOM(4, "%i audio urbs freed\n", m);
 /*---------------------------------------------------------------------------*/
-	JOM(4, "freeing audio data_urb structures.\n");
+	JOM(4, "freeing audio isoc buffers.\n");
 	m = 0;
-	list_for_each_safe(plist_head, plist_next, peasycap->purb_audio_head) {
-		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-		if ((struct data_urb *)NULL != pdata_urb) {
-			kfree(pdata_urb);  pdata_urb = (struct data_urb *)NULL;
-			peasycap->allocation_audio_struct -= \
-						sizeof(struct data_urb);
+	for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
+		if (peasycap->audio_isoc_buffer[k].pgo) {
+			free_pages((unsigned long)
+					(peasycap->audio_isoc_buffer[k].pgo),
+					AUDIO_ISOC_ORDER);
+			peasycap->audio_isoc_buffer[k].pgo = NULL;
+			peasycap->allocation_audio_page -=
+					BIT(AUDIO_ISOC_ORDER);
 			m++;
 		}
 	}
-JOM(4, "%i audio data_urb structures freed\n", m);
-JOM(4, "setting peasycap->purb_audio_head=NULL\n");
-peasycap->purb_audio_head = (struct list_head *)NULL;
-}
-/*---------------------------------------------------------------------------*/
-JOM(4, "freeing audio isoc buffers.\n");
-m = 0;
-for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
-	if ((void *)NULL != peasycap->audio_isoc_buffer[k].pgo) {
-		free_pages((unsigned long)\
-				(peasycap->audio_isoc_buffer[k].pgo), \
-				AUDIO_ISOC_ORDER);
-		peasycap->audio_isoc_buffer[k].pgo = (void *)NULL;
-		peasycap->allocation_audio_page -= \
-				((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
-		m++;
-	}
-}
-JOM(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \
+	JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
 					m * (0x01 << AUDIO_ISOC_ORDER));
 /*---------------------------------------------------------------------------*/
-JOM(4, "freeing audio buffers.\n");
-gone = 0;
-for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
-	if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
-		free_page((unsigned long)(peasycap->audio_buffer[k].pgo));
-		peasycap->audio_buffer[k].pgo = (void *)NULL;
-		peasycap->allocation_audio_page -= 1;
-		gone++;
+#ifdef CONFIG_EASYCAP_OSS
+	JOM(4, "freeing audio buffers.\n");
+	gone = 0;
+	for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
+		if (peasycap->audio_buffer[k].pgo) {
+			free_page((unsigned long)peasycap->audio_buffer[k].pgo);
+			peasycap->audio_buffer[k].pgo = NULL;
+			peasycap->allocation_audio_page -= 1;
+			gone++;
+		}
+	}
+	JOM(4, "easyoss_delete(): audio buffers freed: %i pages\n", gone);
+#endif /* CONFIG_EASYCAP_OSS */
+/*---------------------------------------------------------------------------*/
+	JOM(4, "freeing easycap structure.\n");
+	allocation_video_urb    = peasycap->allocation_video_urb;
+	allocation_video_page   = peasycap->allocation_video_page;
+	allocation_video_struct = peasycap->allocation_video_struct;
+	registered_video        = peasycap->registered_video;
+	allocation_audio_urb    = peasycap->allocation_audio_urb;
+	allocation_audio_page   = peasycap->allocation_audio_page;
+	allocation_audio_struct = peasycap->allocation_audio_struct;
+	registered_audio        = peasycap->registered_audio;
+
+	kfree(peasycap);
+
+	if (0 <= kd && DONGLE_MANY > kd) {
+		if (mutex_lock_interruptible(&mutex_dongle)) {
+			SAY("ERROR: cannot down mutex_dongle\n");
+		} else {
+			JOM(4, "locked mutex_dongle\n");
+			easycapdc60_dongle[kd].peasycap = NULL;
+			mutex_unlock(&mutex_dongle);
+			JOM(4, "unlocked mutex_dongle\n");
+			JOT(4, "   null-->dongle[%i].peasycap\n", kd);
+			allocation_video_struct -= sizeof(struct easycap);
+		}
+	} else {
+		SAY("ERROR: cannot purge dongle[].peasycap");
 	}
-}
-JOM(4, "easysnd_delete(): audio buffers freed: %i pages\n", gone);
-/*---------------------------------------------------------------------------*/
-JOM(4, "freeing easycap structure.\n");
-allocation_video_urb    = peasycap->allocation_video_urb;
-allocation_video_page   = peasycap->allocation_video_page;
-allocation_video_struct = peasycap->allocation_video_struct;
-registered_video        = peasycap->registered_video;
-allocation_audio_urb    = peasycap->allocation_audio_urb;
-allocation_audio_page   = peasycap->allocation_audio_page;
-allocation_audio_struct = peasycap->allocation_audio_struct;
-registered_audio        = peasycap->registered_audio;
-
-kfree(peasycap);
-if (0 <= kd && DONGLE_MANY > kd) {
-	easycap_dongle[kd].peasycap = (struct easycap *)NULL;
-	JOT(4, "   null-->easycap_dongle[%i].peasycap\n", kd);
-	allocation_video_struct -= sizeof(struct easycap);
-} else {
-	SAY("ERROR: cannot purge easycap_dongle[].peasycap");
-}
 /*---------------------------------------------------------------------------*/
-SAY("%8i= video urbs     after all deletions\n", allocation_video_urb);
-SAY("%8i= video pages    after all deletions\n", allocation_video_page);
-SAY("%8i= video structs  after all deletions\n", allocation_video_struct);
-SAY("%8i= video devices  after all deletions\n", registered_video);
-SAY("%8i= audio urbs     after all deletions\n", allocation_audio_urb);
-SAY("%8i= audio pages    after all deletions\n", allocation_audio_page);
-SAY("%8i= audio structs  after all deletions\n", allocation_audio_struct);
-SAY("%8i= audio devices  after all deletions\n", registered_audio);
-
-JOT(4, "ending.\n");
-return;
+	SAY("%8i=video urbs    after all deletions\n", allocation_video_urb);
+	SAY("%8i=video pages   after all deletions\n", allocation_video_page);
+	SAY("%8i=video structs after all deletions\n", allocation_video_struct);
+	SAY("%8i=video devices after all deletions\n", registered_video);
+	SAY("%8i=audio urbs    after all deletions\n", allocation_audio_urb);
+	SAY("%8i=audio pages   after all deletions\n", allocation_audio_page);
+	SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
+	SAY("%8i=audio devices after all deletions\n", registered_audio);
+
+	JOT(4, "ending.\n");
+	return;
 }
 /*****************************************************************************/
-unsigned int easycap_poll(struct file *file, poll_table *wait)
+static unsigned int easycap_poll(struct file *file, poll_table *wait)
 {
-struct easycap *peasycap;
-int rc, kd;
+	struct easycap *peasycap;
+	int rc, kd;
 
-JOT(8, "\n");
+	JOT(8, "\n");
 
-if (NULL == ((poll_table *)wait))
-	JOT(8, "WARNING:  poll table pointer is NULL ... continuing\n");
-if ((struct file *)NULL == file) {
-	SAY("ERROR:  file pointer is NULL\n");
-	return -ERESTARTSYS;
-}
-peasycap = file->private_data;
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL\n");
-	return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-if (NULL == peasycap->pusb_device) {
-	SAY("ERROR:  peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-/*---------------------------------------------------------------------------*/
-kd = isdongle(peasycap);
-if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
-		SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd);
-		return -ERESTARTSYS;
-	}
-	JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
-	/*-------------------------------------------------------------------*/
-	/*
-	 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
-	 *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
-	 *  IF NECESSARY, BAIL OUT.
-	*/
-	/*-------------------------------------------------------------------*/
-	if (kd != isdongle(peasycap))
-		return -ERESTARTSYS;
-	if (NULL == file) {
-		SAY("ERROR:  file is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
+	if (NULL == ((poll_table *)wait))
+		JOT(8, "WARNING:  poll table pointer is NULL ... continuing\n");
+	if (!file) {
+		SAY("ERROR:  file pointer is NULL\n");
 		return -ERESTARTSYS;
 	}
 	peasycap = file->private_data;
-	if (NULL == peasycap) {
+	if (!peasycap) {
 		SAY("ERROR:  peasycap is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ERESTARTSYS;
+		return -EFAULT;
 	}
 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: 0x%08lX\n", \
-						(unsigned long int) peasycap);
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ERESTARTSYS;
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return -EFAULT;
 	}
-	if (NULL == peasycap->pusb_device) {
-		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return -ERESTARTSYS;
+	if (!peasycap->pusb_device) {
+		SAY("ERROR:  peasycap->pusb_device is NULL\n");
+		return -EFAULT;
 	}
-} else
-	/*-------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+	kd = isdongle(peasycap);
+	if (0 <= kd && DONGLE_MANY > kd) {
+		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+			SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
+			return -ERESTARTSYS;
+		}
+		JOM(4, "locked dongle[%i].mutex_video\n", kd);
+	/*
+	 *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
+	 *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
+	 *  IF NECESSARY, BAIL OUT.
+	 */
+		if (kd != isdongle(peasycap))
+			return -ERESTARTSYS;
+		if (!file) {
+			SAY("ERROR:  file is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+		peasycap = file->private_data;
+		if (!peasycap) {
+			SAY("ERROR:  peasycap is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+			SAY("ERROR: bad peasycap: %p\n", peasycap);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+		if (!peasycap->pusb_device) {
+			SAM("ERROR: peasycap->pusb_device is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return -ERESTARTSYS;
+		}
+	} else
 	/*
 	 *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
 	 *  BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
 	 *  HAVE FAILED.  BAIL OUT.
 	*/
-	/*-------------------------------------------------------------------*/
-	return -ERESTARTSYS;
-/*---------------------------------------------------------------------------*/
-rc = easycap_dqbuf(peasycap, 0);
-peasycap->polled = 1;
-mutex_unlock(&easycap_dongle[kd].mutex_video);
-if (0 == rc)
-	return POLLIN | POLLRDNORM;
-else
-	return POLLERR;
-}
+		return -ERESTARTSYS;
+/*---------------------------------------------------------------------------*/
+	rc = easycap_dqbuf(peasycap, 0);
+	peasycap->polled = 1;
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+	if (0 == rc)
+		return POLLIN | POLLRDNORM;
+	else
+		return POLLERR;
+	}
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
  */
 /*---------------------------------------------------------------------------*/
-int
-easycap_dqbuf(struct easycap *peasycap, int mode)
+int easycap_dqbuf(struct easycap *peasycap, int mode)
 {
-int input, ifield, miss, rc;
+	int input, ifield, miss, rc;
 
-JOT(8, "\n");
 
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL\n");
-	return -EFAULT;
-}
-if (NULL == peasycap->pusb_device) {
-	SAY("ERROR:  peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-ifield = 0;
-JOM(8, "%i=ifield\n", ifield);
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAY("ERROR:  peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	ifield = 0;
+	JOM(8, "%i=ifield\n", ifield);
 /*---------------------------------------------------------------------------*/
 /*
  *  CHECK FOR LOST INPUT SIGNAL.
@@ -1223,187 +1068,179 @@ JOM(8, "%i=ifield\n", ifield);
  *    INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
 */
 /*---------------------------------------------------------------------------*/
-input = peasycap->input;
-if (0 <= input && INPUT_MANY > input) {
-	rc = read_saa(peasycap->pusb_device, 0x1F);
-	if (0 <= rc) {
-		if (rc & 0x40)
-			peasycap->lost[input] += 1;
-		else
-			peasycap->lost[input] -= 2;
+	input = peasycap->input;
+	if (0 <= input && INPUT_MANY > input) {
+		rc = read_saa(peasycap->pusb_device, 0x1F);
+		if (0 <= rc) {
+			if (rc & 0x40)
+				peasycap->lost[input] += 1;
+			else
+				peasycap->lost[input] -= 2;
 
-	if (0 > peasycap->lost[input])
-		peasycap->lost[input] = 0;
-	else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
-		peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
+		if (0 > peasycap->lost[input])
+			peasycap->lost[input] = 0;
+		else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
+			peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
+		}
 	}
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  WAIT FOR FIELD ifield  (0 => TOP, 1 => BOTTOM)
  */
 /*---------------------------------------------------------------------------*/
-miss = 0;
-while ((peasycap->field_read == peasycap->field_fill) || \
-				(0 != (0xFF00 & peasycap->field_buffer\
-					[peasycap->field_read][0].kount)) || \
-				(ifield != (0x00FF & peasycap->field_buffer\
+	miss = 0;
+	while ((peasycap->field_read == peasycap->field_fill) ||
+	       (0 != (0xFF00 & peasycap->field_buffer
+					[peasycap->field_read][0].kount)) ||
+	      (ifield != (0x00FF & peasycap->field_buffer
 					[peasycap->field_read][0].kount))) {
-	if (mode)
-		return -EAGAIN;
+		if (mode)
+			return -EAGAIN;
 
-	JOM(8, "first wait  on wq_video, " \
-				"%i=field_read  %i=field_fill\n", \
+		JOM(8, "first wait  on wq_video, %i=field_read %i=field_fill\n",
 				peasycap->field_read, peasycap->field_fill);
 
-	if (0 != (wait_event_interruptible(peasycap->wq_video, \
-			(peasycap->video_idle || peasycap->video_eof  || \
-			((peasycap->field_read != peasycap->field_fill) && \
-				(0 == (0xFF00 & peasycap->field_buffer\
-					[peasycap->field_read][0].kount)) && \
-				(ifield == (0x00FF & peasycap->field_buffer\
-					[peasycap->field_read][0].kount))))))) {
-		SAM("aborted by signal\n");
-		return -EIO;
+		if (0 != (wait_event_interruptible(peasycap->wq_video,
+				(peasycap->video_idle || peasycap->video_eof  ||
+				((peasycap->field_read != peasycap->field_fill) &&
+				(0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
+				(ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
+			SAM("aborted by signal\n");
+			return -EIO;
 		}
-	if (peasycap->video_idle) {
-		JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n", \
+		if (peasycap->video_idle) {
+			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
 							peasycap->video_idle);
-		return -EAGAIN;
-	}
-	if (peasycap->video_eof) {
-		JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
-		#if defined(PERSEVERE)
-		if (1 == peasycap->status) {
-			JOM(8, "persevering ...\n");
-			peasycap->video_eof = 0;
-			peasycap->audio_eof = 0;
-			if (0 != reset(peasycap)) {
-				JOM(8, " ... failed ... returning -EIO\n");
-				peasycap->video_eof = 1;
-				peasycap->audio_eof = 1;
-				kill_video_urbs(peasycap);
-				return -EIO;
-			}
-			peasycap->status = 0;
-			JOM(8, " ... OK ... returning -EAGAIN\n");
 			return -EAGAIN;
 		}
-		#endif /*PERSEVERE*/
-		peasycap->video_eof = 1;
-		peasycap->audio_eof = 1;
-		kill_video_urbs(peasycap);
-		JOM(8, "returning -EIO\n");
-		return -EIO;
+		if (peasycap->video_eof) {
+			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
+			#if defined(PERSEVERE)
+			if (1 == peasycap->status) {
+				JOM(8, "persevering ...\n");
+				peasycap->video_eof = 0;
+				peasycap->audio_eof = 0;
+				if (0 != reset(peasycap)) {
+					JOM(8, " ... failed  returning -EIO\n");
+					peasycap->video_eof = 1;
+					peasycap->audio_eof = 1;
+					kill_video_urbs(peasycap);
+					return -EIO;
+				}
+				peasycap->status = 0;
+				JOM(8, " ... OK  returning -EAGAIN\n");
+				return -EAGAIN;
+			}
+			#endif /*PERSEVERE*/
+			peasycap->video_eof = 1;
+			peasycap->audio_eof = 1;
+			kill_video_urbs(peasycap);
+			JOM(8, "returning -EIO\n");
+			return -EIO;
+		}
+		miss++;
 	}
-miss++;
-}
-JOM(8, "first awakening on wq_video after %i waits\n", miss);
+	JOM(8, "first awakening on wq_video after %i waits\n", miss);
 
-rc = field2frame(peasycap);
-if (0 != rc)
-	SAM("ERROR: field2frame() returned %i\n", rc);
+	rc = field2frame(peasycap);
+	if (rc)
+		SAM("ERROR: field2frame() rc = %i\n", rc);
 /*---------------------------------------------------------------------------*/
 /*
  *  WAIT FOR THE OTHER FIELD
  */
 /*---------------------------------------------------------------------------*/
-if (ifield)
-	ifield = 0;
-else
-	ifield = 1;
-miss = 0;
-while ((peasycap->field_read == peasycap->field_fill) || \
-				(0 != (0xFF00 & peasycap->field_buffer\
-					[peasycap->field_read][0].kount)) || \
-				(ifield != (0x00FF & peasycap->field_buffer\
-					[peasycap->field_read][0].kount))) {
-	if (mode)
-		return -EAGAIN;
+	if (ifield)
+		ifield = 0;
+	else
+		ifield = 1;
+	miss = 0;
+	while ((peasycap->field_read == peasycap->field_fill) ||
+	       (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
+	       (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
+		if (mode)
+			return -EAGAIN;
 
-	JOM(8, "second wait on wq_video, " \
-				"%i=field_read  %i=field_fill\n", \
+		JOM(8, "second wait on wq_video %i=field_read  %i=field_fill\n",
 				peasycap->field_read, peasycap->field_fill);
-	if (0 != (wait_event_interruptible(peasycap->wq_video, \
-			(peasycap->video_idle || peasycap->video_eof  || \
-			((peasycap->field_read != peasycap->field_fill) && \
-				(0 == (0xFF00 & peasycap->field_buffer\
-					[peasycap->field_read][0].kount)) && \
-				(ifield == (0x00FF & peasycap->field_buffer\
-					[peasycap->field_read][0].\
-								kount))))))) {
-		SAM("aborted by signal\n");
-		return -EIO;
-	}
-	if (peasycap->video_idle) {
-		JOM(8, "%i=peasycap->video_idle ... returning -EAGAIN\n", \
+		if (0 != (wait_event_interruptible(peasycap->wq_video,
+			(peasycap->video_idle || peasycap->video_eof  ||
+			((peasycap->field_read != peasycap->field_fill) &&
+			 (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
+			 (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
+			SAM("aborted by signal\n");
+			return -EIO;
+		}
+		if (peasycap->video_idle) {
+			JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
 							peasycap->video_idle);
-		return -EAGAIN;
-	}
-	if (peasycap->video_eof) {
-		JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
-		#if defined(PERSEVERE)
-		if (1 == peasycap->status) {
-			JOM(8, "persevering ...\n");
-			peasycap->video_eof = 0;
-			peasycap->audio_eof = 0;
-			if (0 != reset(peasycap)) {
-				JOM(8, " ... failed ... returning -EIO\n");
-				peasycap->video_eof = 1;
-				peasycap->audio_eof = 1;
-				kill_video_urbs(peasycap);
-				return -EIO;
-			}
-			peasycap->status = 0;
-			JOM(8, " ... OK ... returning -EAGAIN\n");
 			return -EAGAIN;
 		}
-		#endif /*PERSEVERE*/
-		peasycap->video_eof = 1;
-		peasycap->audio_eof = 1;
-		kill_video_urbs(peasycap);
-		JOM(8, "returning -EIO\n");
-		return -EIO;
+		if (peasycap->video_eof) {
+			JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
+#if defined(PERSEVERE)
+			if (1 == peasycap->status) {
+				JOM(8, "persevering ...\n");
+				peasycap->video_eof = 0;
+				peasycap->audio_eof = 0;
+				if (0 != reset(peasycap)) {
+					JOM(8, " ... failed returning -EIO\n");
+					peasycap->video_eof = 1;
+					peasycap->audio_eof = 1;
+					kill_video_urbs(peasycap);
+					return -EIO;
+				}
+				peasycap->status = 0;
+				JOM(8, " ... OK ... returning -EAGAIN\n");
+				return -EAGAIN;
+			}
+#endif /*PERSEVERE*/
+			peasycap->video_eof = 1;
+			peasycap->audio_eof = 1;
+			kill_video_urbs(peasycap);
+			JOM(8, "returning -EIO\n");
+			return -EIO;
+		}
+		miss++;
 	}
-miss++;
-}
-JOM(8, "second awakening on wq_video after %i waits\n", miss);
+	JOM(8, "second awakening on wq_video after %i waits\n", miss);
 
-rc = field2frame(peasycap);
-if (0 != rc)
-	SAM("ERROR: field2frame() returned %i\n", rc);
+	rc = field2frame(peasycap);
+	if (rc)
+		SAM("ERROR: field2frame() rc = %i\n", rc);
 /*---------------------------------------------------------------------------*/
 /*
  *  WASTE THIS FRAME
 */
 /*---------------------------------------------------------------------------*/
-if (0 != peasycap->skip) {
-	peasycap->skipped++;
-	if (peasycap->skip != peasycap->skipped)
-		return peasycap->skip - peasycap->skipped;
-	peasycap->skipped = 0;
-}
+	if (peasycap->skip) {
+		peasycap->skipped++;
+		if (peasycap->skip != peasycap->skipped)
+			return peasycap->skip - peasycap->skipped;
+		else
+			peasycap->skipped = 0;
+	}
 /*---------------------------------------------------------------------------*/
-peasycap->frame_read = peasycap->frame_fill;
-peasycap->queued[peasycap->frame_read] = 0;
-peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
+	peasycap->frame_read = peasycap->frame_fill;
+	peasycap->queued[peasycap->frame_read] = 0;
+	peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
 
-(peasycap->frame_fill)++;
-if (peasycap->frame_buffer_many <= peasycap->frame_fill)
-	peasycap->frame_fill = 0;
+	peasycap->frame_fill++;
+	if (peasycap->frame_buffer_many <= peasycap->frame_fill)
+		peasycap->frame_fill = 0;
 
-if (0x01 & easycap_standard[peasycap->standard_offset].mask) {
-	peasycap->frame_buffer[peasycap->frame_read][0].kount = \
+	if (0x01 & easycap_standard[peasycap->standard_offset].mask)
+		peasycap->frame_buffer[peasycap->frame_read][0].kount =
 							V4L2_FIELD_TOP;
-} else {
-	peasycap->frame_buffer[peasycap->frame_read][0].kount = \
+	else
+		peasycap->frame_buffer[peasycap->frame_read][0].kount =
 							V4L2_FIELD_BOTTOM;
-}
 
-JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
-JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
 
-return 0;
+	JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
+	JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
+
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -1421,222 +1258,204 @@ return 0;
 int
 field2frame(struct easycap *peasycap)
 {
-struct timeval timeval;
-long long int above, below;
-__u32 remainder;
-struct signed_div_result sdr;
-
-void *pex, *pad;
-int kex, kad, mex, mad, rex, rad, rad2;
-int c2, c3, w2, w3, cz, wz;
-int rc, bytesperpixel, multiplier, much, more, over, rump, caches, input;
-__u8 mask, margin;
-bool odd, isuy, decimatepixel, offerfields, badinput;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
+	struct timeval timeval;
+	long long int above, below;
+	u32 remainder;
+	struct signed_div_result sdr;
+
+	void *pex, *pad;
+	int kex, kad, mex, mad, rex, rad, rad2;
+	int c2, c3, w2, w3, cz, wz;
+	int rc, bytesperpixel, multiplier;
+	int  much, more, over, rump, caches, input;
+	u8 mask, margin;
+	bool odd, isuy, decimatepixel, offerfields, badinput;
+
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
 
-badinput = false;
-input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
+	badinput = false;
+	input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
 
-JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> " \
-						"frame buffer %i\n", \
-			peasycap->field_buffer[peasycap->field_read][0].kount,\
-			peasycap->field_buffer[peasycap->field_read][0].input,\
+	JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> "
+							"frame buffer %i\n",
+			peasycap->field_buffer[peasycap->field_read][0].kount,
+			peasycap->field_buffer[peasycap->field_read][0].input,
 			peasycap->field_read, peasycap->frame_fill);
-JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
-if (true == peasycap->offerfields)
-	JOM(8, "===== offerfields\n");
+	JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
+	if (peasycap->offerfields)
+		JOM(8, "===== offerfields\n");
 
 /*---------------------------------------------------------------------------*/
 /*
  *  REJECT OR CLEAN BAD FIELDS
  */
 /*---------------------------------------------------------------------------*/
-if (peasycap->field_read == peasycap->field_fill) {
-	SAM("ERROR: on entry, still filling field buffer %i\n", \
-							peasycap->field_read);
-	return 0;
-}
-#if defined(EASYCAP_TESTCARD)
-easycap_testcard(peasycap, peasycap->field_read);
+	if (peasycap->field_read == peasycap->field_fill) {
+		SAM("ERROR: on entry, still filling field buffer %i\n",
+						peasycap->field_read);
+		return 0;
+	}
+#ifdef EASYCAP_TESTCARD
+	easycap_testcard(peasycap, peasycap->field_read);
 #else
-if (0 <= input && INPUT_MANY > input) {
-	if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
-		easycap_testcard(peasycap, peasycap->field_read);
-}
+	if (0 <= input && INPUT_MANY > input) {
+		if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
+			easycap_testcard(peasycap, peasycap->field_read);
+	}
 #endif /*EASYCAP_TESTCARD*/
 /*---------------------------------------------------------------------------*/
 
-offerfields = peasycap->offerfields;
-bytesperpixel = peasycap->bytesperpixel;
-decimatepixel = peasycap->decimatepixel;
-
-if ((2 != bytesperpixel) && \
-			(3 != bytesperpixel) && \
-			(4 != bytesperpixel)) {
-	SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
-	return -EFAULT;
-}
-if (true == decimatepixel)
-	multiplier = 2;
-else
-	multiplier = 1;
-
-w2 = 2 * multiplier * (peasycap->width);
-w3 = bytesperpixel * \
-		multiplier * \
-		(peasycap->width);
-wz = multiplier * \
-		(peasycap->height) * \
-		multiplier * \
-		(peasycap->width);
-
-kex = peasycap->field_read;  mex = 0;
-kad = peasycap->frame_fill;  mad = 0;
-
-pex = peasycap->field_buffer[kex][0].pgo;  rex = PAGE_SIZE;
-pad = peasycap->frame_buffer[kad][0].pgo;  rad = PAGE_SIZE;
-if (peasycap->field_buffer[kex][0].kount)
-	odd = true;
-else
-	odd = false;
-
-if ((true == odd) && (false == decimatepixel)) {
-	JOM(8, "  initial skipping    %4i          bytes p.%4i\n", \
-							w3/multiplier, mad);
-	pad += (w3 / multiplier);  rad -= (w3 / multiplier);
-}
-isuy = true;
-mask = 0;  rump = 0;  caches = 0;
+	offerfields = peasycap->offerfields;
+	bytesperpixel = peasycap->bytesperpixel;
+	decimatepixel = peasycap->decimatepixel;
 
-cz = 0;
-while (cz < wz) {
-	/*-------------------------------------------------------------------*/
-	/*
-	**  PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
-	**  READ   w2   BYTES FROM FIELD BUFFER,
-	**  WRITE  w3   BYTES TO FRAME BUFFER
-	**/
-	/*-------------------------------------------------------------------*/
-	if (false == decimatepixel) {
-		over = w2;
-		do {
-			much = over;  more = 0;  margin = 0;  mask = 0x00;
-			if (rex < much)
-				much = rex;
-			rump = 0;
-
-			if (much % 2) {
-				SAM("MISTAKE: much is odd\n");
-				return -EFAULT;
-			}
+	if ((2 != bytesperpixel) &&
+	    (3 != bytesperpixel) &&
+	    (4 != bytesperpixel)) {
+		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
+		return -EFAULT;
+	}
+	if (decimatepixel)
+		multiplier = 2;
+	else
+		multiplier = 1;
+
+	w2 = 2 * multiplier * (peasycap->width);
+	w3 = bytesperpixel * multiplier * (peasycap->width);
+	wz = multiplier * (peasycap->height) *
+		multiplier * (peasycap->width);
+
+	kex = peasycap->field_read;  mex = 0;
+	kad = peasycap->frame_fill;  mad = 0;
+
+	pex = peasycap->field_buffer[kex][0].pgo;  rex = PAGE_SIZE;
+	pad = peasycap->frame_buffer[kad][0].pgo;  rad = PAGE_SIZE;
+	odd = !!(peasycap->field_buffer[kex][0].kount);
+
+	if (odd && (!decimatepixel)) {
+		JOM(8, "initial skipping %4i bytes p.%4i\n",
+					w3/multiplier, mad);
+		pad += (w3 / multiplier); rad -= (w3 / multiplier);
+	}
+	isuy = true;
+	mask = 0;  rump = 0;  caches = 0;
+
+	cz = 0;
+	while (cz < wz) {
+		/*
+		 *  PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
+		 *  READ   w2   BYTES FROM FIELD BUFFER,
+		 *  WRITE  w3   BYTES TO FRAME BUFFER
+		 */
+		if (!decimatepixel) {
+			over = w2;
+			do {
+				much = over;  more = 0;
+				margin = 0;  mask = 0x00;
+				if (rex < much)
+					much = rex;
+				rump = 0;
+
+				if (much % 2) {
+					SAM("MISTAKE: much is odd\n");
+					return -EFAULT;
+				}
 
-			more = (bytesperpixel * \
-					much) / 2;
+				more = (bytesperpixel *
+						much) / 2;
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-			if (1 < bytesperpixel) {
-				if (rad * 2 < much * bytesperpixel) {
-					/*
-					**   INJUDICIOUS ALTERATION OF THIS
-					**   STATEMENT BLOCK WILL CAUSE
-					**   BREAKAGE.  BEWARE.
-					**/
-					rad2 = rad + bytesperpixel - 1;
-					much = ((((2 * \
-						rad2)/bytesperpixel)/2) * 2);
-					rump = ((bytesperpixel * \
-							much) / 2) - rad;
-					more = rad;
+				if (1 < bytesperpixel) {
+					if (rad * 2 < much * bytesperpixel) {
+						/*
+						 * INJUDICIOUS ALTERATION OF
+						 * THIS STATEMENT BLOCK WILL
+						 * CAUSE BREAKAGE.  BEWARE.
+						 */
+						rad2 = rad + bytesperpixel - 1;
+						much = ((((2 * rad2)/bytesperpixel)/2) * 2);
+						rump = ((bytesperpixel * much) / 2) - rad;
+						more = rad;
 					}
-				mask = (__u8)rump;
-				margin = 0;
-				if (much == rex) {
-					mask |= 0x04;
-					if ((mex + 1) < FIELD_BUFFER_SIZE/ \
-								PAGE_SIZE) {
-						margin = *((__u8 *)(peasycap->\
-							field_buffer\
-							[kex][mex + 1].pgo));
-					} else
-						mask |= 0x08;
+					mask = (u8)rump;
+					margin = 0;
+					if (much == rex) {
+						mask |= 0x04;
+						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
+							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
+						else
+							mask |= 0x08;
+					}
+				} else {
+					SAM("MISTAKE: %i=bytesperpixel\n",
+							bytesperpixel);
+					return -EFAULT;
 				}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-			} else {
-				SAM("MISTAKE: %i=bytesperpixel\n", \
-						bytesperpixel);
-				return -EFAULT;
-			}
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-			if (rump)
-				caches++;
-				if (true == badinput) {
-					JOM(8, "ERROR: 0x%02X=->field_buffer" \
-						"[%i][%i].input, " \
-						"0x%02X=(0x08|->input)\n", \
-						peasycap->field_buffer\
-						[kex][mex].input, kex, mex, \
-						(0x08|peasycap->input));
+				if (rump)
+					caches++;
+					if (badinput) {
+						JOM(8, "ERROR: 0x%02X=->field_buffer"
+							"[%i][%i].input, "
+							"0x%02X=(0x08|->input)\n",
+							peasycap->field_buffer
+							[kex][mex].input, kex, mex,
+							(0x08|peasycap->input));
+					}
+				rc = redaub(peasycap, pad, pex, much, more,
+								mask, margin, isuy);
+				if (0 > rc) {
+					SAM("ERROR: redaub() failed\n");
+					return -EFAULT;
 				}
-			rc = redaub(peasycap, pad, pex, much, more, \
-							mask, margin, isuy);
-			if (0 > rc) {
-				SAM("ERROR: redaub() failed\n");
-				return -EFAULT;
-			}
-			if (much % 4) {
-				if (isuy)
-					isuy = false;
-				else
-					isuy = true;
-			}
-			over -= much;   cz += much;
-			pex  += much;  rex -= much;
-			if (!rex) {
-				mex++;
-				pex = peasycap->field_buffer[kex][mex].pgo;
-				rex = PAGE_SIZE;
-				if (peasycap->field_buffer[kex][mex].input != \
-						(0x08|peasycap->input))
-					badinput = true;
-			}
-			pad  += more;
-			rad -= more;
-			if (!rad) {
-				mad++;
-				pad = peasycap->frame_buffer[kad][mad].pgo;
-				rad = PAGE_SIZE;
-				if (rump) {
-					pad += rump;
-					rad -= rump;
+				if (much % 4)
+					isuy = !isuy;
+
+				over -= much;   cz += much;
+				pex  += much;  rex -= much;
+				if (!rex) {
+					mex++;
+					pex = peasycap->field_buffer[kex][mex].pgo;
+					rex = PAGE_SIZE;
+					if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
+						badinput = true;
 				}
-			}
-		} while (over);
+				pad  += more;
+				rad -= more;
+				if (!rad) {
+					mad++;
+					pad = peasycap->frame_buffer[kad][mad].pgo;
+					rad = PAGE_SIZE;
+					if (rump) {
+						pad += rump;
+						rad -= rump;
+					}
+				}
+			} while (over);
 /*---------------------------------------------------------------------------*/
 /*
  *  SKIP  w3 BYTES IN TARGET FRAME BUFFER,
  *  UNLESS IT IS THE LAST LINE OF AN ODD FRAME
  */
 /*---------------------------------------------------------------------------*/
-		if ((false == odd) || (cz != wz)) {
-			over = w3;
-			do {
-				if (!rad) {
-					mad++;
-					pad = peasycap->frame_buffer\
-						[kad][mad].pgo;
-					rad = PAGE_SIZE;
-				}
-				more = over;
-				if (rad < more)
-					more = rad;
-				over -= more;
-				pad  += more;
-				rad  -= more;
-			} while (over);
-		}
+			if (!odd || (cz != wz)) {
+				over = w3;
+				do {
+					if (!rad) {
+						mad++;
+						pad = peasycap->frame_buffer
+							[kad][mad].pgo;
+						rad = PAGE_SIZE;
+					}
+					more = over;
+					if (rad < more)
+						more = rad;
+					over -= more;
+					pad  += more;
+					rad  -= more;
+				} while (over);
+			}
 /*---------------------------------------------------------------------------*/
 /*
  *  PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
@@ -1645,214 +1464,205 @@ while (cz < wz) {
  *  WRITE  w3 / 2  BYTES TO FRAME BUFFER
  */
 /*---------------------------------------------------------------------------*/
-	} else if (false == odd) {
-		over = w2;
-		do {
-			much = over;  more = 0;  margin = 0;  mask = 0x00;
-			if (rex < much)
-				much = rex;
-			rump = 0;
+		} else if (!odd) {
+			over = w2;
+			do {
+				much = over;  more = 0;  margin = 0;  mask = 0x00;
+				if (rex < much)
+					much = rex;
+				rump = 0;
 
-			if (much % 2) {
-				SAM("MISTAKE: much is odd\n");
-				return -EFAULT;
-			}
+				if (much % 2) {
+					SAM("MISTAKE: much is odd\n");
+					return -EFAULT;
+				}
 
-			more = (bytesperpixel * \
-					much) / 4;
+				more = (bytesperpixel * much) / 4;
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-			if (1 < bytesperpixel) {
-				if (rad * 4 < much * bytesperpixel) {
-					/*
-					**   INJUDICIOUS ALTERATION OF THIS
-					**   STATEMENT BLOCK WILL CAUSE
-					**   BREAKAGE.  BEWARE.
-					**/
-					rad2 = rad + bytesperpixel - 1;
-					much = ((((2 * rad2)/bytesperpixel)/2)\
-									* 4);
-					rump = ((bytesperpixel * \
-							much) / 4) - rad;
-					more = rad;
+				if (1 < bytesperpixel) {
+					if (rad * 4 < much * bytesperpixel) {
+						/*
+						 * INJUDICIOUS ALTERATION OF
+						 * THIS STATEMENT BLOCK
+						 * WILL CAUSE BREAKAGE.
+						 * BEWARE.
+						 */
+						rad2 = rad + bytesperpixel - 1;
+						much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
+						rump = ((bytesperpixel * much) / 4) - rad;
+						more = rad;
 					}
-				mask = (__u8)rump;
-				margin = 0;
-				if (much == rex) {
-					mask |= 0x04;
-					if ((mex + 1) < FIELD_BUFFER_SIZE/ \
-								PAGE_SIZE) {
-						margin = *((__u8 *)(peasycap->\
-							field_buffer\
-							[kex][mex + 1].pgo));
-						}
-					else
-						mask |= 0x08;
+					mask = (u8)rump;
+					margin = 0;
+					if (much == rex) {
+						mask |= 0x04;
+						if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
+							margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
+						else
+							mask |= 0x08;
 					}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
 				} else {
-					SAM("MISTAKE: %i=bytesperpixel\n", \
+					SAM("MISTAKE: %i=bytesperpixel\n",
 						bytesperpixel);
 					return -EFAULT;
 				}
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-			if (rump)
-				caches++;
-
-				if (true == badinput) {
-					JOM(8, "ERROR: 0x%02X=->field_buffer" \
-						"[%i][%i].input, " \
-						"0x%02X=(0x08|->input)\n", \
-						peasycap->field_buffer\
-						[kex][mex].input, kex, mex, \
-						(0x08|peasycap->input));
-				}
-			rc = redaub(peasycap, pad, pex, much, more, \
+				if (rump)
+					caches++;
+
+					if (badinput) {
+						JOM(8, "ERROR: 0x%02X=->field_buffer"
+							"[%i][%i].input, "
+							"0x%02X=(0x08|->input)\n",
+							peasycap->field_buffer
+							[kex][mex].input, kex, mex,
+							(0x08|peasycap->input));
+					}
+				rc = redaub(peasycap, pad, pex, much, more,
 							mask, margin, isuy);
-			if (0 > rc) {
-				SAM("ERROR: redaub() failed\n");
-				return -EFAULT;
-			}
-			over -= much;   cz += much;
-			pex  += much;  rex -= much;
-			if (!rex) {
-				mex++;
-				pex = peasycap->field_buffer[kex][mex].pgo;
-				rex = PAGE_SIZE;
-				if (peasycap->field_buffer[kex][mex].input != \
-						(0x08|peasycap->input))
-					badinput = true;
-			}
-			pad  += more;
-			rad -= more;
-			if (!rad) {
-				mad++;
-				pad = peasycap->frame_buffer[kad][mad].pgo;
-				rad = PAGE_SIZE;
-				if (rump) {
-					pad += rump;
-					rad -= rump;
+				if (0 > rc) {
+					SAM("ERROR: redaub() failed\n");
+					return -EFAULT;
 				}
-			}
-		} while (over);
+				over -= much;   cz += much;
+				pex  += much;  rex -= much;
+				if (!rex) {
+					mex++;
+					pex = peasycap->field_buffer[kex][mex].pgo;
+					rex = PAGE_SIZE;
+					if (peasycap->field_buffer[kex][mex].input !=
+							(0x08|peasycap->input))
+						badinput = true;
+				}
+				pad  += more;
+				rad -= more;
+				if (!rad) {
+					mad++;
+					pad = peasycap->frame_buffer[kad][mad].pgo;
+					rad = PAGE_SIZE;
+					if (rump) {
+						pad += rump;
+						rad -= rump;
+					}
+				}
+			} while (over);
 /*---------------------------------------------------------------------------*/
 /*
  *  OTHERWISE JUST
  *  READ   w2   BYTES FROM FIELD BUFFER AND DISCARD THEM
  */
 /*---------------------------------------------------------------------------*/
-	} else {
-		over = w2;
-		do {
-			if (!rex) {
-				mex++;
-				pex = peasycap->field_buffer[kex][mex].pgo;
-				rex = PAGE_SIZE;
-				if (peasycap->field_buffer[kex][mex].input != \
-						(0x08|peasycap->input)) {
-					JOM(8, "ERROR: 0x%02X=->field_buffer"\
-						"[%i][%i].input, " \
-						"0x%02X=(0x08|->input)\n", \
-						peasycap->field_buffer\
-						[kex][mex].input, kex, mex, \
-						(0x08|peasycap->input));
-					badinput = true;
+		} else {
+			over = w2;
+			do {
+				if (!rex) {
+					mex++;
+					pex = peasycap->field_buffer[kex][mex].pgo;
+					rex = PAGE_SIZE;
+					if (peasycap->field_buffer[kex][mex].input !=
+							(0x08|peasycap->input)) {
+						JOM(8, "ERROR: 0x%02X=->field_buffer"
+							"[%i][%i].input, "
+							"0x%02X=(0x08|->input)\n",
+							peasycap->field_buffer
+							[kex][mex].input, kex, mex,
+							(0x08|peasycap->input));
+						badinput = true;
+					}
 				}
-			}
-			much = over;
-			if (rex < much)
-				much = rex;
-			over -= much;
-			cz += much;
-			pex  += much;
-			rex -= much;
-		} while (over);
+				much = over;
+				if (rex < much)
+					much = rex;
+				over -= much;
+				cz += much;
+				pex  += much;
+				rex -= much;
+			} while (over);
+		}
 	}
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  SANITY CHECKS
  */
 /*---------------------------------------------------------------------------*/
-c2 = (mex + 1)*PAGE_SIZE - rex;
-if (cz != c2)
-	SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
-c3 = (mad + 1)*PAGE_SIZE - rad;
-
-if (false == decimatepixel) {
-	if (bytesperpixel * \
-		cz != c3) \
-		SAM("ERROR: discrepancy %i in bytes written\n", \
-						c3 - (bytesperpixel * \
-									cz));
-} else {
-	if (false == odd) {
-		if (bytesperpixel * \
-			cz != (4 * c3))
-			SAM("ERROR: discrepancy %i in bytes written\n", \
-						(2*c3)-(bytesperpixel * \
-									cz));
-		} else {
-			if (0 != c3)
-				SAM("ERROR: discrepancy %i " \
-						"in bytes written\n", c3);
-		}
-}
-if (rump)
-	SAM("WORRY: undischarged cache at end of line in frame buffer\n");
+	c2 = (mex + 1)*PAGE_SIZE - rex;
+	if (cz != c2)
+		SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
+	c3 = (mad + 1)*PAGE_SIZE - rad;
+
+	if (!decimatepixel) {
+		if (bytesperpixel * cz != c3)
+			SAM("ERROR: discrepancy %i in bytes written\n",
+					c3 - (bytesperpixel * cz));
+	} else {
+		if (!odd) {
+			if (bytesperpixel *
+				cz != (4 * c3))
+				SAM("ERROR: discrepancy %i in bytes written\n",
+					(2*c3)-(bytesperpixel * cz));
+			} else {
+				if (0 != c3)
+					SAM("ERROR: discrepancy %i "
+					    "in bytes written\n", c3);
+			}
+	}
+	if (rump)
+		SAM("WORRY: undischarged cache at end of line in frame buffer\n");
 
-JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
-JOM(8, "===== field2frame(): %i=mad  %i=rad\n", mad, rad);
+	JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
+	JOM(8, "===== field2frame(): %i=mad  %i=rad\n", mad, rad);
 
-if (true == odd)
-	JOM(8, "+++++ field2frame():  frame buffer %i is full\n", kad);
+	if (odd)
+		JOM(8, "+++++ field2frame():  frame buffer %i is full\n", kad);
 
-if (peasycap->field_read == peasycap->field_fill)
-	SAM("WARNING: on exit, filling field buffer %i\n", \
-							peasycap->field_read);
+	if (peasycap->field_read == peasycap->field_fill)
+		SAM("WARNING: on exit, filling field buffer %i\n",
+						peasycap->field_read);
 /*---------------------------------------------------------------------------*/
 /*
  *  CALCULATE VIDEO STREAMING RATE
  */
 /*---------------------------------------------------------------------------*/
-do_gettimeofday(&timeval);
-if (peasycap->timeval6.tv_sec) {
-	below = ((long long int)(1000000)) * \
-		((long long int)(timeval.tv_sec - \
-					peasycap->timeval6.tv_sec)) + \
-		 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
-	above = (long long int)1000000;
+	do_gettimeofday(&timeval);
+	if (peasycap->timeval6.tv_sec) {
+		below = ((long long int)(1000000)) *
+			((long long int)(timeval.tv_sec -
+						peasycap->timeval6.tv_sec)) +
+			 (long long int)(timeval.tv_usec - peasycap->timeval6.tv_usec);
+		above = (long long int)1000000;
 
-	sdr = signed_div(above, below);
-	above = sdr.quotient;
-	remainder = (__u32)sdr.remainder;
+		sdr = signed_div(above, below);
+		above = sdr.quotient;
+		remainder = (u32)sdr.remainder;
 
-	JOM(8, "video streaming at %3lli.%03i fields per second\n", above, \
-							(remainder/1000));
-}
-peasycap->timeval6 = timeval;
+		JOM(8, "video streaming at %3lli.%03i fields per second\n",
+				above, (remainder/1000));
+	}
+	peasycap->timeval6 = timeval;
 
-if (caches)
-	JOM(8, "%i=caches\n", caches);
-return 0;
+	if (caches)
+		JOM(8, "%i=caches\n", caches);
+	return 0;
 }
 /*****************************************************************************/
 struct signed_div_result
 signed_div(long long int above, long long int below)
 {
-struct signed_div_result sdr;
-
-if (((0 <= above) && (0 <= below)) || ((0  > above) && (0  > below))) {
-	sdr.remainder = (unsigned long long int) do_div(above, below);
-	sdr.quotient  = (long long int) above;
-} else {
-	if (0 > above)
-		above = -above;
-	if (0 > below)
-		below = -below;
-	sdr.remainder = (unsigned long long int) do_div(above, below);
-	sdr.quotient  = -((long long int) above);
-}
-return sdr;
+	struct signed_div_result sdr;
+
+	if (((0 <= above) && (0 <= below)) || ((0  > above) && (0  > below))) {
+		sdr.remainder = (unsigned long long int) do_div(above, below);
+		sdr.quotient  = (long long int) above;
+	} else {
+		if (0 > above)
+			above = -above;
+		if (0 > below)
+			below = -below;
+		sdr.remainder = (unsigned long long int) do_div(above, below);
+		sdr.quotient  = -((long long int) above);
+	}
+	return sdr;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -1881,345 +1691,176 @@ return sdr;
  */
 /*---------------------------------------------------------------------------*/
 int
-redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more, \
-					__u8 mask, __u8 margin, bool isuy)
+redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more,
+					u8 mask, u8 margin, bool isuy)
 {
-static __s32 ay[256], bu[256], rv[256], gu[256], gv[256];
-__u8 *pcache;
-__u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
-int  bytesperpixel;
-bool byteswaporder, decimatepixel, last;
-int j, rump;
-__s32 s32;
-
-if (much % 2) {
-	SAM("MISTAKE: much is odd\n");
-	return -EFAULT;
-}
-bytesperpixel = peasycap->bytesperpixel;
-byteswaporder = peasycap->byteswaporder;
-decimatepixel = peasycap->decimatepixel;
-
-/*---------------------------------------------------------------------------*/
-if (!bu[255]) {
-	for (j = 0; j < 112; j++) {
-		s32 = (0xFF00 & (453 * j)) >> 8;
-		bu[j + 128] =  s32; bu[127 - j] = -s32;
-		s32 = (0xFF00 & (359 * j)) >> 8;
-		rv[j + 128] =  s32; rv[127 - j] = -s32;
-		s32 = (0xFF00 & (88 * j)) >> 8;
-		gu[j + 128] =  s32; gu[127 - j] = -s32;
-		s32 = (0xFF00 & (183 * j)) >> 8;
-		gv[j + 128] =  s32; gv[127 - j] = -s32;
-	}
-	for (j = 0; j < 16; j++) {
-		bu[j] = bu[16]; rv[j] = rv[16];
-		gu[j] = gu[16]; gv[j] = gv[16];
-	}
-	for (j = 240; j < 256; j++) {
-		bu[j] = bu[239]; rv[j] = rv[239];
-		gu[j] = gu[239]; gv[j] = gv[239];
-	}
-	for (j =  16; j < 236; j++)
-		ay[j] = j;
-	for (j =   0; j <  16; j++)
-		ay[j] = ay[16];
-	for (j = 236; j < 256; j++)
-		ay[j] = ay[235];
-	JOM(8, "lookup tables are prepared\n");
-}
-pcache = peasycap->pcache;
-if (NULL == pcache)
-	pcache = &peasycap->cache[0];
+	static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
+	u8 *pcache;
+	u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
+	int  bytesperpixel;
+	bool byteswaporder, decimatepixel, last;
+	int j, rump;
+	s32 tmp;
+
+	if (much % 2) {
+		SAM("MISTAKE: much is odd\n");
+		return -EFAULT;
+	}
+	bytesperpixel = peasycap->bytesperpixel;
+	byteswaporder = peasycap->byteswaporder;
+	decimatepixel = peasycap->decimatepixel;
+
+/*---------------------------------------------------------------------------*/
+	if (!bu[255]) {
+		for (j = 0; j < 112; j++) {
+			tmp = (0xFF00 & (453 * j)) >> 8;
+			bu[j + 128] =  tmp; bu[127 - j] = -tmp;
+			tmp = (0xFF00 & (359 * j)) >> 8;
+			rv[j + 128] =  tmp; rv[127 - j] = -tmp;
+			tmp = (0xFF00 & (88 * j)) >> 8;
+			gu[j + 128] =  tmp; gu[127 - j] = -tmp;
+			tmp = (0xFF00 & (183 * j)) >> 8;
+			gv[j + 128] =  tmp; gv[127 - j] = -tmp;
+		}
+		for (j = 0; j < 16; j++) {
+			bu[j] = bu[16]; rv[j] = rv[16];
+			gu[j] = gu[16]; gv[j] = gv[16];
+		}
+		for (j = 240; j < 256; j++) {
+			bu[j] = bu[239]; rv[j] = rv[239];
+			gu[j] = gu[239]; gv[j] = gv[239];
+		}
+		for (j =  16; j < 236; j++)
+			ay[j] = j;
+		for (j =   0; j <  16; j++)
+			ay[j] = ay[16];
+		for (j = 236; j < 256; j++)
+			ay[j] = ay[235];
+		JOM(8, "lookup tables are prepared\n");
+	}
+	pcache = peasycap->pcache;
+	if (!pcache)
+		pcache = &peasycap->cache[0];
 /*---------------------------------------------------------------------------*/
 /*
  *  TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
  */
 /*---------------------------------------------------------------------------*/
-if (!pcache) {
-	SAM("MISTAKE: pcache is NULL\n");
-	return -EFAULT;
-}
+	if (!pcache) {
+		SAM("MISTAKE: pcache is NULL\n");
+		return -EFAULT;
+	}
 
-if (pcache != &peasycap->cache[0])
-	JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
-p2 = &peasycap->cache[0];
-p3 = (__u8 *)pad - (int)(pcache - &peasycap->cache[0]);
-while (p2 < pcache) {
-	*p3++ = *p2;  p2++;
-}
-pcache = &peasycap->cache[0];
-if (p3 != pad) {
-	SAM("MISTAKE: pointer misalignment\n");
-	return -EFAULT;
-}
-/*---------------------------------------------------------------------------*/
-rump = (int)(0x03 & mask);
-u = 0; v = 0;
-p2 = (__u8 *)pex;  pz = p2 + much;  pr = p3 + more;  last = false;
-p2++;
-
-if (true == isuy)
-	u = *(p2 - 1);
-else
-	v = *(p2 - 1);
-
-if (rump)
-	JOM(16, "%4i=much  %4i=more  %i=rump\n", much, more, rump);
-
-/*---------------------------------------------------------------------------*/
-switch (bytesperpixel) {
-case 2: {
-	if (false == decimatepixel) {
-		memcpy(pad, pex, (size_t)much);
-		if (false == byteswaporder)
-			/*---------------------------------------------------*/
-			/*
-			**  UYVY
-			*/
-			/*---------------------------------------------------*/
-			return 0;
-		else {
-			/*---------------------------------------------------*/
-			/*
-			**  YUYV
-			*/
-			/*---------------------------------------------------*/
-			p3 = (__u8 *)pad;  pz = p3 + much;
-			while  (pz > p3) {
-				c = *p3;
-				*p3 = *(p3 + 1);
-				*(p3 + 1) = c;
-				p3 += 2;
-			}
-			return 0;
-		}
-	} else {
-		if (false == byteswaporder) {
-			/*---------------------------------------------------*/
-			/*
-			**  UYVY DECIMATED
-			*/
-			/*---------------------------------------------------*/
-			p2 = (__u8 *)pex;  p3 = (__u8 *)pad;  pz = p2 + much;
-			while (pz > p2) {
-				*p3 = *p2;
-				*(p3 + 1) = *(p2 + 1);
-				*(p3 + 2) = *(p2 + 2);
-				*(p3 + 3) = *(p2 + 3);
-				p3 += 4;  p2 += 8;
-			}
-			return 0;
-		} else {
-			/*---------------------------------------------------*/
-			/*
-			**  YUYV DECIMATED
-			**/
-			/*---------------------------------------------------*/
-			p2 = (__u8 *)pex;  p3 = (__u8 *)pad;  pz = p2 + much;
-			while (pz > p2) {
-				*p3 = *(p2 + 1);
-				*(p3 + 1) = *p2;
-				*(p3 + 2) = *(p2 + 3);
-				*(p3 + 3) = *(p2 + 2);
-				p3 += 4;  p2 += 8;
-			}
-			return 0;
-		}
+	if (pcache != &peasycap->cache[0])
+		JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
+	p2 = &peasycap->cache[0];
+	p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
+	while (p2 < pcache) {
+		*p3++ = *p2;  p2++;
 	}
-	break;
-	}
-case 3:
-	{
-	if (false == decimatepixel) {
-		if (false == byteswaporder) {
-			/*---------------------------------------------------*/
-			/*
-			**  RGB
-			**/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
-						if (0x08 & mask)
-							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
-					else
-						u = *(p2 + 1);
-				}
+	pcache = &peasycap->cache[0];
+	if (p3 != pad) {
+		SAM("MISTAKE: pointer misalignment\n");
+		return -EFAULT;
+	}
+/*---------------------------------------------------------------------------*/
+	rump = (int)(0x03 & mask);
+	u = 0; v = 0;
+	p2 = (u8 *)pex;  pz = p2 + much;  pr = p3 + more;  last = false;
+	p2++;
 
-				s32 = ay[(int)y] + rv[(int)v];
-				r = (255 < s32) ? 255 : ((0 > s32) ? \
-							0 : (__u8)s32);
-				s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
-				g = (255 < s32) ? 255 : ((0 > s32) ? \
-							0 : (__u8)s32);
-				s32 = ay[(int)y] + bu[(int)u];
-				b = (255 < s32) ? 255 : ((0 > s32) ? \
-							0 : (__u8)s32);
-
-				if ((true == last) && rump) {
-					pcache = &peasycap->cache[0];
-					switch (bytesperpixel - rump) {
-					case 1: {
-						*p3 = r;
-						*pcache++ = g;
-						*pcache++ = b;
-						break;
-					}
-					case 2: {
-						*p3 = r;
-						*(p3 + 1) = g;
-						*pcache++ = b;
-						break;
-					}
-					default: {
-						SAM("MISTAKE: %i=rump\n", \
-							bytesperpixel - rump);
-						return -EFAULT;
-					}
-					}
-				} else {
-					*p3 = r;
-					*(p3 + 1) = g;
-					*(p3 + 2) = b;
+	if (isuy)
+		u = *(p2 - 1);
+	else
+		v = *(p2 - 1);
+
+	if (rump)
+		JOM(16, "%4i=much  %4i=more  %i=rump\n", much, more, rump);
+
+/*---------------------------------------------------------------------------*/
+	switch (bytesperpixel) {
+	case 2: {
+		if (!decimatepixel) {
+			memcpy(pad, pex, (size_t)much);
+			if (!byteswaporder) {
+				/* UYVY */
+				return 0;
+			} else {
+				/* YUYV */
+				p3 = (u8 *)pad;  pz = p3 + much;
+				while  (pz > p3) {
+					c = *p3;
+					*p3 = *(p3 + 1);
+					*(p3 + 1) = c;
+					p3 += 2;
 				}
-				p2 += 2;
-				if (true == isuy)
-					isuy = false;
-				else
-					isuy = true;
-				p3 += bytesperpixel;
+				return 0;
 			}
-			return 0;
 		} else {
-			/*---------------------------------------------------*/
-			/*
-			**  BGR
-			*/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					}
-				else
-					if (0x08 & mask)
-						;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
-					else
-						u = *(p2 + 1);
+			if (!byteswaporder) {
+				/*  UYVY DECIMATED */
+				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
+				while (pz > p2) {
+					*p3 = *p2;
+					*(p3 + 1) = *(p2 + 1);
+					*(p3 + 2) = *(p2 + 2);
+					*(p3 + 3) = *(p2 + 3);
+					p3 += 4;  p2 += 8;
 				}
-
-				s32 = ay[(int)y] + rv[(int)v];
-				r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-				s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
-				g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-				s32 = ay[(int)y] + bu[(int)u];
-				b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-
-				if ((true == last) && rump) {
-					pcache = &peasycap->cache[0];
-					switch (bytesperpixel - rump) {
-					case 1: {
-						*p3 = b;
-						*pcache++ = g;
-						*pcache++ = r;
-						break;
-					}
-					case 2: {
-						*p3 = b;
-						*(p3 + 1) = g;
-						*pcache++ = r;
-						break;
-					}
-					default: {
-						SAM("MISTAKE: %i=rump\n", \
-							bytesperpixel - rump);
-						return -EFAULT;
-					}
-					}
-				} else {
-					*p3 = b;
-					*(p3 + 1) = g;
-					*(p3 + 2) = r;
-					}
-				p2 += 2;
-				if (true == isuy)
-					isuy = false;
-				else
-					isuy = true;
-				p3 += bytesperpixel;
+				return 0;
+			} else {
+				/* YUYV DECIMATED */
+				p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
+				while (pz > p2) {
+					*p3 = *(p2 + 1);
+					*(p3 + 1) = *p2;
+					*(p3 + 2) = *(p2 + 3);
+					*(p3 + 3) = *(p2 + 2);
+					p3 += 4;  p2 += 8;
 				}
+				return 0;
 			}
-		return 0;
-	} else {
-		if (false == byteswaporder) {
-			/*---------------------------------------------------*/
-			/*
-			**  RGB DECIMATED
-			*/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
-						if (0x08 & mask)
-							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
+		}
+		break;
+		}
+	case 3:
+		{
+		if (!decimatepixel) {
+			if (!byteswaporder) {
+				/* RGB */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
 					else
-						u = *(p2 + 1);
-				}
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
+					}
 
-				if (true == isuy) {
-					s32 = ay[(int)y] + rv[(int)v];
-					r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] - gu[(int)u] - \
-								gv[(int)v];
-					g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] + bu[(int)u];
-					b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-
-					if ((true == last) && rump) {
+					tmp = ay[(int)y] + rv[(int)v];
+					r = (255 < tmp) ? 255 : ((0 > tmp) ?
+								0 : (u8)tmp);
+					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
+					g = (255 < tmp) ? 255 : ((0 > tmp) ?
+								0 : (u8)tmp);
+					tmp = ay[(int)y] + bu[(int)u];
+					b = (255 < tmp) ? 255 : ((0 > tmp) ?
+								0 : (u8)tmp);
+
+					if (last && rump) {
 						pcache = &peasycap->cache[0];
 						switch (bytesperpixel - rump) {
 						case 1: {
@@ -2235,9 +1876,8 @@ case 3:
 							break;
 						}
 						default: {
-							SAM("MISTAKE: " \
-							"%i=rump\n", \
-							bytesperpixel - rump);
+							SAM("MISTAKE: %i=rump\n",
+								bytesperpixel - rump);
 							return -EFAULT;
 						}
 						}
@@ -2246,56 +1886,50 @@ case 3:
 						*(p3 + 1) = g;
 						*(p3 + 2) = b;
 					}
-					isuy = false;
+					p2 += 2;
+					if (isuy)
+						isuy = false;
+					else
+						isuy = true;
 					p3 += bytesperpixel;
-				} else {
-					isuy = true;
 				}
-				p2 += 2;
-			}
-			return 0;
-		} else {
-			/*---------------------------------------------------*/
-			/*
-			 *  BGR DECIMATED
-			 */
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
+				return 0;
+			} else {
+				/* BGR */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
+					else
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						}
+					else
 						if (0x08 & mask)
 							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
-					else
-						u = *(p2 + 1);
-				}
-
-				if (true == isuy) {
-
-					s32 = ay[(int)y] + rv[(int)v];
-					r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] - gu[(int)u] - \
-								gv[(int)v];
-					g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] + bu[(int)u];
-					b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
+					}
 
-					if ((true == last) && rump) {
+					tmp = ay[(int)y] + rv[(int)v];
+					r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
+					g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+					tmp = ay[(int)y] + bu[(int)u];
+					b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+					if (last && rump) {
 						pcache = &peasycap->cache[0];
 						switch (bytesperpixel - rump) {
 						case 1: {
@@ -2311,9 +1945,8 @@ case 3:
 							break;
 						}
 						default: {
-							SAM("MISTAKE: " \
-							"%i=rump\n", \
-							bytesperpixel - rump);
+							SAM("MISTAKE: %i=rump\n",
+								bytesperpixel - rump);
 							return -EFAULT;
 						}
 						}
@@ -2322,229 +1955,201 @@ case 3:
 						*(p3 + 1) = g;
 						*(p3 + 2) = r;
 						}
-					isuy = false;
+					p2 += 2;
+					if (isuy)
+						isuy = false;
+					else
+						isuy = true;
 					p3 += bytesperpixel;
 					}
-				else
-					isuy = true;
-				p2 += 2;
 				}
 			return 0;
-			}
-		}
-	break;
-	}
-case 4:
-	{
-	if (false == decimatepixel) {
-		if (false == byteswaporder) {
-			/*---------------------------------------------------*/
-			/*
-			**  RGBA
-			*/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
-						 if (0x08 & mask)
-							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
+		} else {
+			if (!byteswaporder) {
+				/*  RGB DECIMATED */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
 					else
-						u = *(p2 + 1);
-				}
-
-				s32 = ay[(int)y] + rv[(int)v];
-				r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-				s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
-				g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-				s32 = ay[(int)y] + bu[(int)u];
-				b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-
-				if ((true == last) && rump) {
-					pcache = &peasycap->cache[0];
-					switch (bytesperpixel - rump) {
-					case 1: {
-						*p3 = r;
-						*pcache++ = g;
-						*pcache++ = b;
-						*pcache++ = 0;
-						break;
-					}
-					case 2: {
-						*p3 = r;
-						*(p3 + 1) = g;
-						*pcache++ = b;
-						*pcache++ = 0;
-						break;
-					}
-					case 3: {
-						*p3 = r;
-						*(p3 + 1) = g;
-						*(p3 + 2) = b;
-						*pcache++ = 0;
-						break;
-					}
-					default: {
-						SAM("MISTAKE: %i=rump\n", \
-							bytesperpixel - rump);
-						return -EFAULT;
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
 					}
+
+					if (isuy) {
+						tmp = ay[(int)y] + rv[(int)v];
+						r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] - gu[(int)u] -
+									gv[(int)v];
+						g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] + bu[(int)u];
+						b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+						if (last && rump) {
+							pcache = &peasycap->cache[0];
+							switch (bytesperpixel - rump) {
+							case 1: {
+								*p3 = r;
+								*pcache++ = g;
+								*pcache++ = b;
+								break;
+							}
+							case 2: {
+								*p3 = r;
+								*(p3 + 1) = g;
+								*pcache++ = b;
+								break;
+							}
+							default: {
+								SAM("MISTAKE: "
+								"%i=rump\n",
+								bytesperpixel - rump);
+								return -EFAULT;
+							}
+							}
+						} else {
+							*p3 = r;
+							*(p3 + 1) = g;
+							*(p3 + 2) = b;
+						}
+						isuy = false;
+						p3 += bytesperpixel;
+					} else {
+						isuy = true;
 					}
-				} else {
-					*p3 = r;
-					*(p3 + 1) = g;
-					*(p3 + 2) = b;
-					*(p3 + 3) = 0;
+					p2 += 2;
 				}
-				p2 += 2;
-				if (true == isuy)
-					isuy = false;
-				else
-					isuy = true;
-				p3 += bytesperpixel;
-			}
-			return 0;
-		} else {
-			/*---------------------------------------------------*/
-			/*
-			**  BGRA
-			*/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
-						 if (0x08 & mask)
-							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
+				return 0;
+			} else {
+				/* BGR DECIMATED */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
 					else
-						u = *(p2 + 1);
-				}
-
-				s32 = ay[(int)y] + rv[(int)v];
-				r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-				s32 = ay[(int)y] - gu[(int)u] - gv[(int)v];
-				g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-				s32 = ay[(int)y] + bu[(int)u];
-				b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-
-				if ((true == last) && rump) {
-					pcache = &peasycap->cache[0];
-					switch (bytesperpixel - rump) {
-					case 1: {
-						*p3 = b;
-						*pcache++ = g;
-						*pcache++ = r;
-						*pcache++ = 0;
-						break;
-					}
-					case 2: {
-						*p3 = b;
-						*(p3 + 1) = g;
-						*pcache++ = r;
-						*pcache++ = 0;
-						break;
-					}
-					case 3: {
-						*p3 = b;
-						*(p3 + 1) = g;
-						*(p3 + 2) = r;
-						*pcache++ = 0;
-						break;
-					}
-					default: {
-						SAM("MISTAKE: %i=rump\n", \
-							bytesperpixel - rump);
-						return -EFAULT;
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
 					}
+
+					if (isuy) {
+
+						tmp = ay[(int)y] + rv[(int)v];
+						r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] - gu[(int)u] -
+									gv[(int)v];
+						g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] + bu[(int)u];
+						b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+						if (last && rump) {
+							pcache = &peasycap->cache[0];
+							switch (bytesperpixel - rump) {
+							case 1: {
+								*p3 = b;
+								*pcache++ = g;
+								*pcache++ = r;
+								break;
+							}
+							case 2: {
+								*p3 = b;
+								*(p3 + 1) = g;
+								*pcache++ = r;
+								break;
+							}
+							default: {
+								SAM("MISTAKE: "
+								"%i=rump\n",
+								bytesperpixel - rump);
+								return -EFAULT;
+							}
+							}
+						} else {
+							*p3 = b;
+							*(p3 + 1) = g;
+							*(p3 + 2) = r;
+							}
+						isuy = false;
+						p3 += bytesperpixel;
+						}
+					else
+						isuy = true;
+					p2 += 2;
 					}
-				} else {
-					*p3 = b;
-					*(p3 + 1) = g;
-					*(p3 + 2) = r;
-					*(p3 + 3) = 0;
+				return 0;
 				}
-				p2 += 2;
-				if (true == isuy)
-					isuy = false;
-				else
-					isuy = true;
-				p3 += bytesperpixel;
 			}
+		break;
 		}
-		return 0;
-	} else {
-		if (false == byteswaporder) {
-			/*---------------------------------------------------*/
-			/*
-			**  RGBA DECIMATED
-			*/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
-						if (0x08 & mask)
-							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
+	case 4:
+		{
+		if (!decimatepixel) {
+			if (!byteswaporder) {
+				/* RGBA */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
 					else
-						u = *(p2 + 1);
-				}
-
-				if (true == isuy) {
-
-					s32 = ay[(int)y] + rv[(int)v];
-					r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] - gu[(int)u] - \
-								gv[(int)v];
-					g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] + bu[(int)u];
-					b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							 if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
+					}
 
-					if ((true == last) && rump) {
+					tmp = ay[(int)y] + rv[(int)v];
+					r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
+					g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+					tmp = ay[(int)y] + bu[(int)u];
+					b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+					if (last && rump) {
 						pcache = &peasycap->cache[0];
 						switch (bytesperpixel - rump) {
 						case 1: {
@@ -2569,67 +2174,62 @@ case 4:
 							break;
 						}
 						default: {
-							SAM("MISTAKE: " \
-							"%i=rump\n", \
-							bytesperpixel - \
-							rump);
+							SAM("MISTAKE: %i=rump\n",
+								bytesperpixel - rump);
 							return -EFAULT;
-							}
+						}
 						}
 					} else {
 						*p3 = r;
 						*(p3 + 1) = g;
 						*(p3 + 2) = b;
 						*(p3 + 3) = 0;
-						}
-					isuy = false;
-					p3 += bytesperpixel;
-				} else
-					isuy = true;
-				p2 += 2;
-			}
-			return 0;
-		} else {
-			/*---------------------------------------------------*/
-			/*
-			**  BGRA DECIMATED
-			*/
-			/*---------------------------------------------------*/
-			while (pz > p2) {
-				if (pr <= (p3 + bytesperpixel))
-					last = true;
-				else
-					last = false;
-				y = *p2;
-				if ((true == last) && (0x0C & mask)) {
-					if (0x04 & mask) {
-						if (true == isuy)
-							v = margin;
-						else
-							u = margin;
-					} else
-						if (0x08 & mask)
-							;
-				} else {
-					if (true == isuy)
-						v = *(p2 + 1);
+					}
+					p2 += 2;
+					if (isuy)
+						isuy = false;
 					else
-						u = *(p2 + 1);
+						isuy = true;
+					p3 += bytesperpixel;
 				}
+				return 0;
+			} else {
+				/*
+				 *  BGRA
+				 */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
+					else
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							 if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
+					}
 
-				if (true == isuy) {
-					s32 = ay[(int)y] + rv[(int)v];
-					r = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] - gu[(int)u] - \
-								gv[(int)v];
-					g = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-					s32 = ay[(int)y] + bu[(int)u];
-					b = (255 < s32) ? 255 : ((0 > s32) ? \
-								0 : (__u8)s32);
-
-					if ((true == last) && rump) {
+					tmp = ay[(int)y] + rv[(int)v];
+					r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+					tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
+					g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+					tmp = ay[(int)y] + bu[(int)u];
+					b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+					if (last && rump) {
 						pcache = &peasycap->cache[0];
 						switch (bytesperpixel - rump) {
 						case 1: {
@@ -2653,157 +2253,322 @@ case 4:
 							*pcache++ = 0;
 							break;
 						}
-						default: {
-							SAM("MISTAKE: " \
-							"%i=rump\n", \
-							bytesperpixel - rump);
+						default:
+							SAM("MISTAKE: %i=rump\n",
+								bytesperpixel - rump);
 							return -EFAULT;
 						}
-						}
 					} else {
 						*p3 = b;
 						*(p3 + 1) = g;
 						*(p3 + 2) = r;
 						*(p3 + 3) = 0;
 					}
-					isuy = false;
+					p2 += 2;
+					if (isuy)
+						isuy = false;
+					else
+						isuy = true;
 					p3 += bytesperpixel;
-				} else
-					isuy = true;
+				}
+			}
+			return 0;
+		} else {
+			if (!byteswaporder) {
+				/*
+				 *  RGBA DECIMATED
+				 */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
+					else
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
+					}
+
+					if (isuy) {
+
+						tmp = ay[(int)y] + rv[(int)v];
+						r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] - gu[(int)u] -
+									gv[(int)v];
+						g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] + bu[(int)u];
+						b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+						if (last && rump) {
+							pcache = &peasycap->cache[0];
+							switch (bytesperpixel - rump) {
+							case 1: {
+								*p3 = r;
+								*pcache++ = g;
+								*pcache++ = b;
+								*pcache++ = 0;
+								break;
+							}
+							case 2: {
+								*p3 = r;
+								*(p3 + 1) = g;
+								*pcache++ = b;
+								*pcache++ = 0;
+								break;
+							}
+							case 3: {
+								*p3 = r;
+								*(p3 + 1) = g;
+								*(p3 + 2) = b;
+								*pcache++ = 0;
+								break;
+							}
+							default: {
+								SAM("MISTAKE: "
+								"%i=rump\n",
+								bytesperpixel -
+								rump);
+								return -EFAULT;
+								}
+							}
+						} else {
+							*p3 = r;
+							*(p3 + 1) = g;
+							*(p3 + 2) = b;
+							*(p3 + 3) = 0;
+							}
+						isuy = false;
+						p3 += bytesperpixel;
+					} else
+						isuy = true;
 					p2 += 2;
 				}
 				return 0;
+			} else {
+				/*
+				 *  BGRA DECIMATED
+				 */
+				while (pz > p2) {
+					if (pr <= (p3 + bytesperpixel))
+						last = true;
+					else
+						last = false;
+					y = *p2;
+					if (last && (0x0C & mask)) {
+						if (0x04 & mask) {
+							if (isuy)
+								v = margin;
+							else
+								u = margin;
+						} else
+							if (0x08 & mask)
+								;
+					} else {
+						if (isuy)
+							v = *(p2 + 1);
+						else
+							u = *(p2 + 1);
+					}
+
+					if (isuy) {
+						tmp = ay[(int)y] + rv[(int)v];
+						r = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] - gu[(int)u] -
+									gv[(int)v];
+						g = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+						tmp = ay[(int)y] + bu[(int)u];
+						b = (255 < tmp) ? 255 : ((0 > tmp) ?
+									0 : (u8)tmp);
+
+						if (last && rump) {
+							pcache = &peasycap->cache[0];
+							switch (bytesperpixel - rump) {
+							case 1: {
+								*p3 = b;
+								*pcache++ = g;
+								*pcache++ = r;
+								*pcache++ = 0;
+								break;
+							}
+							case 2: {
+								*p3 = b;
+								*(p3 + 1) = g;
+								*pcache++ = r;
+								*pcache++ = 0;
+								break;
+							}
+							case 3: {
+								*p3 = b;
+								*(p3 + 1) = g;
+								*(p3 + 2) = r;
+								*pcache++ = 0;
+								break;
+							}
+							default: {
+								SAM("MISTAKE: "
+								"%i=rump\n",
+								bytesperpixel - rump);
+								return -EFAULT;
+							}
+							}
+						} else {
+							*p3 = b;
+							*(p3 + 1) = g;
+							*(p3 + 2) = r;
+							*(p3 + 3) = 0;
+						}
+						isuy = false;
+						p3 += bytesperpixel;
+					} else
+						isuy = true;
+						p2 += 2;
+					}
+					return 0;
+				}
 			}
+		break;
+		}
+	default: {
+		SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
+		return -EFAULT;
 		}
-	break;
-	}
-default: {
-	SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
-	return -EFAULT;
 	}
-}
-return 0;
+	return 0;
 }
 /*****************************************************************************/
-/*---------------------------------------------------------------------------*/
 /*
  *  SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
  */
-/*---------------------------------------------------------------------------*/
-int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
-{
-
-JOT(8, "\n");
-
-pvma->vm_ops = &easycap_vm_ops;
-pvma->vm_flags |= VM_RESERVED;
-if (NULL != file)
-	pvma->vm_private_data = file->private_data;
-easycap_vma_open(pvma);
-return 0;
-}
 /*****************************************************************************/
-void
-easycap_vma_open(struct vm_area_struct *pvma)
+static void easycap_vma_open(struct vm_area_struct *pvma)
 {
-struct easycap *peasycap;
+	struct easycap *peasycap;
 
-peasycap = pvma->vm_private_data;
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
+	peasycap = pvma->vm_private_data;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return;
+	}
+	peasycap->vma_many++;
+	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
 	return;
 }
-peasycap->vma_many++;
-JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
-return;
-}
 /*****************************************************************************/
-void
-easycap_vma_close(struct vm_area_struct *pvma)
+static void easycap_vma_close(struct vm_area_struct *pvma)
 {
-struct easycap *peasycap;
+	struct easycap *peasycap;
 
-peasycap = pvma->vm_private_data;
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
+	peasycap = pvma->vm_private_data;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return;
+	}
+	peasycap->vma_many--;
+	JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
 	return;
 }
-peasycap->vma_many--;
-JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
-return;
-}
 /*****************************************************************************/
-int
-easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
+static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
 {
-int k, m, retcode;
-void *pbuf;
-struct page *page;
-struct easycap *peasycap;
+	int k, m, retcode;
+	void *pbuf;
+	struct page *page;
+	struct easycap *peasycap;
 
-retcode = VM_FAULT_NOPAGE;
-pbuf = (void *)NULL;
-page = (struct page *)NULL;
+	retcode = VM_FAULT_NOPAGE;
 
-if (NULL == pvma) {
-	SAY("pvma is NULL\n");
-	return retcode;
-}
-if (NULL == pvmf) {
-	SAY("pvmf is NULL\n");
-	return retcode;
-}
+	if (!pvma) {
+		SAY("pvma is NULL\n");
+		return retcode;
+	}
+	if (!pvmf) {
+		SAY("pvmf is NULL\n");
+		return retcode;
+	}
 
-k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
-m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
+	k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
+	m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
 
-if (!m)
-	JOT(4, "%4i=k, %4i=m\n", k, m);
-else
-	JOT(16, "%4i=k, %4i=m\n", k, m);
+	if (!m)
+		JOT(4, "%4i=k, %4i=m\n", k, m);
+	else
+		JOT(16, "%4i=k, %4i=m\n", k, m);
 
-if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
-	SAY("ERROR: buffer index %i out of range\n", k);
-	return retcode;
-}
-if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
-	SAY("ERROR: page number  %i out of range\n", m);
-	return retcode;
-}
-peasycap = pvma->vm_private_data;
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return retcode;
-}
+	if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
+		SAY("ERROR: buffer index %i out of range\n", k);
+		return retcode;
+	}
+	if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
+		SAY("ERROR: page number  %i out of range\n", m);
+		return retcode;
+	}
+	peasycap = pvma->vm_private_data;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return retcode;
+	}
 /*---------------------------------------------------------------------------*/
-pbuf = peasycap->frame_buffer[k][m].pgo;
-if (NULL == pbuf) {
-	SAM("ERROR:  pbuf is NULL\n");
-	goto finish;
-}
-page = virt_to_page(pbuf);
-if (NULL == page) {
-	SAM("ERROR:  page is NULL\n");
-	goto finish;
-}
-get_page(page);
-/*---------------------------------------------------------------------------*/
-finish:
-if (NULL == page) {
-	SAM("ERROR:  page is NULL after get_page(page)\n");
-} else {
-	pvmf->page = page;
-	retcode = VM_FAULT_MINOR;
+	pbuf = peasycap->frame_buffer[k][m].pgo;
+	if (!pbuf) {
+		SAM("ERROR:  pbuf is NULL\n");
+		return retcode;
+	}
+	page = virt_to_page(pbuf);
+	if (!page) {
+		SAM("ERROR:  page is NULL\n");
+		return retcode;
+	}
+	get_page(page);
+/*---------------------------------------------------------------------------*/
+	if (!page) {
+		SAM("ERROR:  page is NULL after get_page(page)\n");
+	} else {
+		pvmf->page = page;
+		retcode = VM_FAULT_MINOR;
+	}
+	return retcode;
 }
-return retcode;
+
+static const struct vm_operations_struct easycap_vm_ops = {
+	.open  = easycap_vma_open,
+	.close = easycap_vma_close,
+	.fault = easycap_vma_fault,
+};
+
+static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
+{
+	JOT(8, "\n");
+
+	pvma->vm_ops = &easycap_vm_ops;
+	pvma->vm_flags |= VM_RESERVED;
+	if (file)
+		pvma->vm_private_data = file->private_data;
+	easycap_vma_open(pvma);
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -2832,291 +2597,128 @@ return retcode;
  *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
  */
 /*---------------------------------------------------------------------------*/
-void
-easycap_complete(struct urb *purb)
+static void easycap_complete(struct urb *purb)
 {
-struct easycap *peasycap;
-struct data_buffer *pfield_buffer;
-char errbuf[16];
-int i, more, much, leap, rc, last;
-int videofieldamount;
-unsigned int override, bad;
-int framestatus, framelength, frameactual, frameoffset;
-__u8 *pu;
-
-if (NULL == purb) {
-	SAY("ERROR: easycap_complete(): purb is NULL\n");
-	return;
-}
-peasycap = purb->context;
-if (NULL == peasycap) {
-	SAY("ERROR: easycap_complete(): peasycap is NULL\n");
-	return;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return;
-}
-if (peasycap->video_eof)
-	return;
-for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
-	if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
-		break;
-JOM(16, "%2i=urb\n", i);
-last = peasycap->video_isoc_sequence;
-if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \
-						(0 != i)) || \
-	(((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \
-						((last + 1) != i))) {
-	JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n", last, i);
-}
-peasycap->video_isoc_sequence = i;
+	struct easycap *peasycap;
+	struct data_buffer *pfield_buffer;
+	char errbuf[16];
+	int i, more, much, leap, rc, last;
+	int videofieldamount;
+	unsigned int override, bad;
+	int framestatus, framelength, frameactual, frameoffset;
+	u8 *pu;
+
+	if (!purb) {
+		SAY("ERROR: easycap_complete(): purb is NULL\n");
+		return;
+	}
+	peasycap = purb->context;
+	if (!peasycap) {
+		SAY("ERROR: easycap_complete(): peasycap is NULL\n");
+		return;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return;
+	}
+	if (peasycap->video_eof)
+		return;
+	for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
+		if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
+			break;
+	JOM(16, "%2i=urb\n", i);
+	last = peasycap->video_isoc_sequence;
+	if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
+	     (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
+		JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
+						last, i);
+	}
+	peasycap->video_isoc_sequence = i;
 
-if (peasycap->video_idle) {
-	JOM(16, "%i=video_idle  %i=video_isoc_streaming\n", \
-			peasycap->video_idle, peasycap->video_isoc_streaming);
-	if (peasycap->video_isoc_streaming) {
-		rc = usb_submit_urb(purb, GFP_ATOMIC);
-		if (0 != rc) {
-			switch (rc) {
-			case -ENOMEM: {
-				SAM("ENOMEM\n");
-				break;
-			}
-			case -ENODEV: {
-				SAM("ENODEV\n");
-				break;
-			}
-			case -ENXIO: {
-				SAM("ENXIO\n");
-				break;
-			}
-			case -EINVAL: {
-				SAM("EINVAL\n");
-				break;
-			}
-			case -EAGAIN: {
-				SAM("EAGAIN\n");
-				break;
-			}
-			case -EFBIG: {
-				SAM("EFBIG\n");
-				break;
-			}
-			case -EPIPE: {
-				SAM("EPIPE\n");
-				break;
-			}
-			case -EMSGSIZE: {
-				SAM("EMSGSIZE\n");
-				break;
-			}
-			case -ENOSPC: {
-				SAM("ENOSPC\n");
-				break;
-			}
-			default: {
-				SAM("0x%08X\n", rc);
-				break;
-			}
+	if (peasycap->video_idle) {
+		JOM(16, "%i=video_idle  %i=video_isoc_streaming\n",
+				peasycap->video_idle, peasycap->video_isoc_streaming);
+		if (peasycap->video_isoc_streaming) {
+			rc = usb_submit_urb(purb, GFP_ATOMIC);
+			if (rc) {
+				SAM("%s:%d ENOMEM\n", strerror(rc), rc);
+				if (-ENODEV != rc)
+					SAM("ERROR: while %i=video_idle, "
+								"usb_submit_urb() "
+								"failed with rc:\n",
+								peasycap->video_idle);
 			}
-			if (-ENODEV != rc) \
-				SAM("ERROR: while %i=video_idle, " \
-							"usb_submit_urb() " \
-							"failed with rc:\n", \
-							peasycap->video_idle);
 		}
+	return;
 	}
-return;
-}
-override = 0;
+	override = 0;
 /*---------------------------------------------------------------------------*/
-if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
-	SAM("ERROR: bad peasycap->field_fill\n");
-	return;
-}
-if (purb->status) {
-	if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
-		JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
+	if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
+		SAM("ERROR: bad peasycap->field_fill\n");
 		return;
 	}
+	if (purb->status) {
+		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
+			JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
+			return;
+		}
 
-	(peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
-	SAM("ERROR: bad urb status:\n");
-	switch (purb->status) {
-	case -EINPROGRESS: {
-		SAM("-EINPROGRESS\n"); break;
-	}
-	case -ENOSR: {
-		SAM("-ENOSR\n"); break;
-	}
-	case -EPIPE: {
-		SAM("-EPIPE\n"); break;
-	}
-	case -EOVERFLOW: {
-		SAM("-EOVERFLOW\n"); break;
-	}
-	case -EPROTO: {
-		SAM("-EPROTO\n"); break;
-	}
-	case -EILSEQ: {
-		SAM("-EILSEQ\n"); break;
-	}
-	case -ETIMEDOUT: {
-		SAM("-ETIMEDOUT\n"); break;
-	}
-	case -EMSGSIZE: {
-		SAM("-EMSGSIZE\n"); break;
-	}
-	case -EOPNOTSUPP: {
-		SAM("-EOPNOTSUPP\n"); break;
-	}
-	case -EPFNOSUPPORT: {
-		SAM("-EPFNOSUPPORT\n"); break;
-	}
-	case -EAFNOSUPPORT: {
-		SAM("-EAFNOSUPPORT\n"); break;
-	}
-	case -EADDRINUSE: {
-		SAM("-EADDRINUSE\n"); break;
-	}
-	case -EADDRNOTAVAIL: {
-		SAM("-EADDRNOTAVAIL\n"); break;
-	}
-	case -ENOBUFS: {
-		SAM("-ENOBUFS\n"); break;
-	}
-	case -EISCONN: {
-		SAM("-EISCONN\n"); break;
-	}
-	case -ENOTCONN: {
-		SAM("-ENOTCONN\n"); break;
-	}
-	case -ESHUTDOWN: {
-		SAM("-ESHUTDOWN\n"); break;
-	}
-	case -ENOENT: {
-		SAM("-ENOENT\n"); break;
-	}
-	case -ECONNRESET: {
-		SAM("-ECONNRESET\n"); break;
-	}
-	case -ENOSPC: {
-		SAM("ENOSPC\n"); break;
-	}
-	default: {
-		SAM("unknown error code 0x%08X\n", purb->status); break;
-	}
-	}
+		(peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
+		SAM("ERROR: bad urb status -%s: %d\n",
+				strerror(purb->status), purb->status);
 /*---------------------------------------------------------------------------*/
-} else {
-	for (i = 0;  i < purb->number_of_packets; i++) {
-		if (0 != purb->iso_frame_desc[i].status) {
-			(peasycap->field_buffer\
-				[peasycap->field_fill][0].kount) |= 0x8000 ;
-			switch (purb->iso_frame_desc[i].status) {
-			case  0: {
-				strcpy(&errbuf[0], "OK"); break;
-			}
-			case -ENOENT: {
-				strcpy(&errbuf[0], "-ENOENT"); break;
-			}
-			case -EINPROGRESS: {
-				strcpy(&errbuf[0], "-EINPROGRESS"); break;
-			}
-			case -EPROTO: {
-				strcpy(&errbuf[0], "-EPROTO"); break;
-			}
-			case -EILSEQ: {
-				strcpy(&errbuf[0], "-EILSEQ"); break;
-			}
-			case -ETIME: {
-				strcpy(&errbuf[0], "-ETIME"); break;
-			}
-			case -ETIMEDOUT: {
-				strcpy(&errbuf[0], "-ETIMEDOUT"); break;
-			}
-			case -EPIPE: {
-				strcpy(&errbuf[0], "-EPIPE"); break;
-			}
-			case -ECOMM: {
-				strcpy(&errbuf[0], "-ECOMM"); break;
-			}
-			case -ENOSR: {
-				strcpy(&errbuf[0], "-ENOSR"); break;
-			}
-			case -EOVERFLOW: {
-				strcpy(&errbuf[0], "-EOVERFLOW"); break;
-			}
-			case -EREMOTEIO: {
-				strcpy(&errbuf[0], "-EREMOTEIO"); break;
-			}
-			case -ENODEV: {
-				strcpy(&errbuf[0], "-ENODEV"); break;
-			}
-			case -EXDEV: {
-				strcpy(&errbuf[0], "-EXDEV"); break;
-			}
-			case -EINVAL: {
-				strcpy(&errbuf[0], "-EINVAL"); break;
-			}
-			case -ECONNRESET: {
-				strcpy(&errbuf[0], "-ECONNRESET"); break;
-			}
-			case -ENOSPC: {
-				SAM("ENOSPC\n"); break;
-			}
-			case -ESHUTDOWN: {
-				strcpy(&errbuf[0], "-ESHUTDOWN"); break;
-			}
-			default: {
-				strcpy(&errbuf[0], "unknown error"); break;
-			}
-			}
-		}
-		framestatus = purb->iso_frame_desc[i].status;
-		framelength = purb->iso_frame_desc[i].length;
-		frameactual = purb->iso_frame_desc[i].actual_length;
-		frameoffset = purb->iso_frame_desc[i].offset;
-
-		JOM(16, "frame[%2i]:" \
-				"%4i=status "  \
-				"%4i=actual "  \
-				"%4i=length "  \
-				"%5i=offset\n", \
-			i, framestatus, frameactual, framelength, frameoffset);
-		if (!purb->iso_frame_desc[i].status) {
-			more = purb->iso_frame_desc[i].actual_length;
-			pfield_buffer = &peasycap->field_buffer\
-				  [peasycap->field_fill][peasycap->field_page];
-			videofieldamount = (peasycap->field_page * \
-				PAGE_SIZE) + \
-				(int)(pfield_buffer->pto - pfield_buffer->pgo);
-		if (4 == more)
-			peasycap->video_mt++;
-		if (4 < more) {
-			if (peasycap->video_mt) {
-				JOM(8, "%4i empty video urb frames\n", \
-							peasycap->video_mt);
-				peasycap->video_mt = 0;
-			}
-			if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
-				SAM("ERROR: bad peasycap->field_fill\n");
-				return;
-			}
-			if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
-							peasycap->field_page) {
-				SAM("ERROR: bad peasycap->field_page\n");
-				return;
+	} else {
+		for (i = 0;  i < purb->number_of_packets; i++) {
+			if (0 != purb->iso_frame_desc[i].status) {
+				(peasycap->field_buffer
+					[peasycap->field_fill][0].kount) |= 0x8000 ;
+				/* FIXME: 1. missing '-' check boundaries */
+				strcpy(&errbuf[0],
+					strerror(purb->iso_frame_desc[i].status));
 			}
-			pfield_buffer = &peasycap->field_buffer\
-				[peasycap->field_fill][peasycap->field_page];
-			pu = (__u8 *)(purb->transfer_buffer + \
-					purb->iso_frame_desc[i].offset);
-			if (0x80 & *pu)
-				leap = 8;
-			else
-				leap = 4;
+			framestatus = purb->iso_frame_desc[i].status;
+			framelength = purb->iso_frame_desc[i].length;
+			frameactual = purb->iso_frame_desc[i].actual_length;
+			frameoffset = purb->iso_frame_desc[i].offset;
+
+			JOM(16, "frame[%2i]:"
+					"%4i=status "
+					"%4i=actual "
+					"%4i=length "
+					"%5i=offset\n",
+				i, framestatus, frameactual, framelength, frameoffset);
+			if (!purb->iso_frame_desc[i].status) {
+				more = purb->iso_frame_desc[i].actual_length;
+				pfield_buffer = &peasycap->field_buffer
+					  [peasycap->field_fill][peasycap->field_page];
+				videofieldamount = (peasycap->field_page *
+					PAGE_SIZE) +
+					(int)(pfield_buffer->pto - pfield_buffer->pgo);
+			if (4 == more)
+				peasycap->video_mt++;
+			if (4 < more) {
+				if (peasycap->video_mt) {
+					JOM(8, "%4i empty video urb frames\n",
+								peasycap->video_mt);
+					peasycap->video_mt = 0;
+				}
+				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
+					SAM("ERROR: bad peasycap->field_fill\n");
+					return;
+				}
+				if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
+								peasycap->field_page) {
+					SAM("ERROR: bad peasycap->field_page\n");
+					return;
+				}
+				pfield_buffer = &peasycap->field_buffer
+					[peasycap->field_fill][peasycap->field_page];
+				pu = (u8 *)(purb->transfer_buffer +
+						purb->iso_frame_desc[i].offset);
+				if (0x80 & *pu)
+					leap = 8;
+				else
+					leap = 4;
 /*--------------------------------------------------------------------------*/
 /*
  *  EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
@@ -3134,196 +2736,195 @@ if (purb->status) {
  *  RESTS WITH dqbuf().
  */
 /*---------------------------------------------------------------------------*/
-			if ((8 == more) || override) {
-				if (videofieldamount > \
-						peasycap->videofieldamount) {
-					if (2 == videofieldamount - \
-							peasycap->\
-							videofieldamount) {
-						(peasycap->field_buffer\
-						[peasycap->field_fill]\
-							[0].kount) |= 0x0100;
-						peasycap->video_junk += (1 + \
-							VIDEO_JUNK_TOLERATE);
-					} else
-						(peasycap->field_buffer\
-						[peasycap->field_fill]\
-							[0].kount) |= 0x4000;
-					} else if (videofieldamount < \
-							peasycap->\
-							videofieldamount) {
-						(peasycap->field_buffer\
-						[peasycap->field_fill]\
-							[0].kount) |= 0x2000;
-					}
-					bad = 0xFF00 & peasycap->field_buffer\
-						[peasycap->field_fill]\
-						[0].kount;
-					if (!bad) {
-						(peasycap->video_junk)--;
-						if (-VIDEO_JUNK_TOLERATE > \
-							peasycap->video_junk) \
-							peasycap->video_junk =\
-							-VIDEO_JUNK_TOLERATE;
-						peasycap->field_read = \
-							(peasycap->\
-								field_fill)++;
-						if (FIELD_BUFFER_MANY <= \
-								peasycap->\
-								field_fill)
-							peasycap->\
-								field_fill = 0;
+				if ((8 == more) || override) {
+					if (videofieldamount >
+							peasycap->videofieldamount) {
+						if (2 == videofieldamount -
+								peasycap->
+								videofieldamount) {
+							(peasycap->field_buffer
+							[peasycap->field_fill]
+								[0].kount) |= 0x0100;
+							peasycap->video_junk += (1 +
+								VIDEO_JUNK_TOLERATE);
+						} else
+							(peasycap->field_buffer
+							[peasycap->field_fill]
+								[0].kount) |= 0x4000;
+						} else if (videofieldamount <
+								peasycap->
+								videofieldamount) {
+							(peasycap->field_buffer
+							[peasycap->field_fill]
+								[0].kount) |= 0x2000;
+						}
+						bad = 0xFF00 & peasycap->field_buffer
+							[peasycap->field_fill]
+							[0].kount;
+						if (!bad) {
+							(peasycap->video_junk)--;
+							if (-VIDEO_JUNK_TOLERATE >
+								peasycap->video_junk)
+								peasycap->video_junk =
+								-VIDEO_JUNK_TOLERATE;
+							peasycap->field_read =
+								(peasycap->
+									field_fill)++;
+							if (FIELD_BUFFER_MANY <=
+									peasycap->
+									field_fill)
+								peasycap->
+									field_fill = 0;
+							peasycap->field_page = 0;
+							pfield_buffer = &peasycap->
+								field_buffer
+								[peasycap->
+								field_fill]
+								[peasycap->
+								field_page];
+							pfield_buffer->pto =
+								pfield_buffer->pgo;
+							JOM(8, "bumped to: %i="
+								"peasycap->"
+								"field_fill  %i="
+								"parity\n",
+								peasycap->field_fill,
+								0x00FF &
+								pfield_buffer->kount);
+							JOM(8, "field buffer %i has "
+								"%i bytes fit to be "
+								"read\n",
+								peasycap->field_read,
+								videofieldamount);
+							JOM(8, "wakeup call to "
+								"wq_video, "
+								"%i=field_read "
+								"%i=field_fill "
+								"%i=parity\n",
+								peasycap->field_read,
+								peasycap->field_fill,
+								0x00FF & peasycap->
+								field_buffer
+								[peasycap->
+								field_read][0].kount);
+							wake_up_interruptible
+								(&(peasycap->
+									 wq_video));
+							do_gettimeofday
+								(&peasycap->timeval7);
+						} else {
+						peasycap->video_junk++;
+						if (bad & 0x0010)
+							peasycap->video_junk +=
+							(1 + VIDEO_JUNK_TOLERATE/2);
+						JOM(8, "field buffer %i had %i "
+							"bytes, now discarded: "
+							"0x%04X\n",
+							peasycap->field_fill,
+							videofieldamount,
+							(0xFF00 &
+							peasycap->field_buffer
+							[peasycap->field_fill][0].
+							kount));
+						(peasycap->field_fill)++;
+
+						if (FIELD_BUFFER_MANY <=
+								peasycap->field_fill)
+							peasycap->field_fill = 0;
 						peasycap->field_page = 0;
-						pfield_buffer = &peasycap->\
-							field_buffer\
-							[peasycap->\
-							field_fill]\
-							[peasycap->\
-							field_page];
-						pfield_buffer->pto = \
-							pfield_buffer->pgo;
-						JOM(8, "bumped to: %i="\
-							"peasycap->" \
-							"field_fill  %i="\
-							"parity\n", \
-							peasycap->field_fill, \
-							0x00FF & \
-							pfield_buffer->kount);
-						JOM(8, "field buffer %i has "\
-							"%i bytes fit to be "\
-							"read\n", \
-							peasycap->field_read, \
-							videofieldamount);
-						JOM(8, "wakeup call to "\
-							"wq_video, " \
-							"%i=field_read "\
-							"%i=field_fill "\
-							"%i=parity\n", \
-							peasycap->field_read, \
-							peasycap->field_fill, \
-							0x00FF & peasycap->\
-							field_buffer\
-							[peasycap->\
-							field_read][0].kount);
-						wake_up_interruptible\
-							(&(peasycap->\
-								 wq_video));
-						do_gettimeofday\
-							(&peasycap->timeval7);
-					} else {
-					peasycap->video_junk++;
-					if (bad & 0x0010) \
-						peasycap->video_junk += \
-						(1 + VIDEO_JUNK_TOLERATE/2);
-					JOM(8, "field buffer %i had %i " \
-						"bytes, now discarded: "\
-						"0x%04X\n", \
-						peasycap->field_fill, \
-						videofieldamount,\
-						(0xFF00 & \
-						peasycap->field_buffer\
-						[peasycap->field_fill][0].\
-						kount));
-					(peasycap->field_fill)++;
-
-					if (FIELD_BUFFER_MANY <= \
-							peasycap->field_fill)
-						peasycap->field_fill = 0;
-					peasycap->field_page = 0;
-					pfield_buffer = \
-						&peasycap->field_buffer\
-						[peasycap->field_fill]\
-						[peasycap->field_page];
-					pfield_buffer->pto = \
-							pfield_buffer->pgo;
-
-					JOM(8, "bumped to: %i=peasycap->" \
-						"field_fill  %i=parity\n", \
-						peasycap->field_fill, \
-						0x00FF & pfield_buffer->kount);
-				}
-				if (8 == more) {
-					JOM(8, "end-of-field: received " \
-						"parity byte 0x%02X\n", \
-						(0xFF & *pu));
-					if (0x40 & *pu)
-						pfield_buffer->kount = 0x0000;
-					else
-						pfield_buffer->kount = 0x0001;
-					pfield_buffer->input = 0x08 | \
-						(0x07 & peasycap->input);
-					JOM(8, "end-of-field: 0x%02X=kount\n",\
-						0xFF & pfield_buffer->kount);
+						pfield_buffer =
+							&peasycap->field_buffer
+							[peasycap->field_fill]
+							[peasycap->field_page];
+						pfield_buffer->pto =
+								pfield_buffer->pgo;
+
+						JOM(8, "bumped to: %i=peasycap->"
+							"field_fill  %i=parity\n",
+							peasycap->field_fill,
+							0x00FF & pfield_buffer->kount);
+					}
+					if (8 == more) {
+						JOM(8, "end-of-field: received "
+							"parity byte 0x%02X\n",
+							(0xFF & *pu));
+						if (0x40 & *pu)
+							pfield_buffer->kount = 0x0000;
+						else
+							pfield_buffer->kount = 0x0001;
+						pfield_buffer->input = 0x08 |
+							(0x07 & peasycap->input);
+						JOM(8, "end-of-field: 0x%02X=kount\n",
+							0xFF & pfield_buffer->kount);
+					}
 				}
-			}
 /*---------------------------------------------------------------------------*/
 /*
  *  COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
  */
 /*---------------------------------------------------------------------------*/
-			pu += leap;
-			more -= leap;
+				pu += leap;
+				more -= leap;
 
-			if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
-				SAM("ERROR: bad peasycap->field_fill\n");
-				return;
-			}
-			if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
-							peasycap->field_page) {
-				SAM("ERROR: bad peasycap->field_page\n");
-				return;
-			}
-			pfield_buffer = &peasycap->field_buffer\
-				[peasycap->field_fill][peasycap->field_page];
-			while (more) {
-				pfield_buffer = &peasycap->field_buffer\
-						[peasycap->field_fill]\
-						[peasycap->field_page];
-				if (PAGE_SIZE < (pfield_buffer->pto - \
-							pfield_buffer->pgo)) {
-					SAM("ERROR: bad pfield_buffer->pto\n");
+				if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
+					SAM("ERROR: bad peasycap->field_fill\n");
 					return;
 				}
-				if (PAGE_SIZE == (pfield_buffer->pto - \
-							pfield_buffer->pgo)) {
-					(peasycap->field_page)++;
-					if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \
-							peasycap->field_page) {
-						JOM(16, "wrapping peasycap->" \
-							"field_page\n");
-						peasycap->field_page = 0;
-					}
-					pfield_buffer = &peasycap->\
-							field_buffer\
-							[peasycap->field_fill]\
-							[peasycap->field_page];
-					pfield_buffer->pto = \
-							pfield_buffer->pgo;
-					pfield_buffer->input = 0x08 | \
-						(0x07 & peasycap->input);
-					if ((peasycap->field_buffer[peasycap->\
-							field_fill][0]).\
-								input != \
-							pfield_buffer->input)
-						(peasycap->field_buffer\
-							[peasycap->field_fill]\
-							[0]).kount |= 0x1000;
+				if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
+					SAM("ERROR: bad peasycap->field_page\n");
+					return;
 				}
+				pfield_buffer = &peasycap->field_buffer
+					[peasycap->field_fill][peasycap->field_page];
+				while (more) {
+					pfield_buffer = &peasycap->field_buffer
+							[peasycap->field_fill]
+							[peasycap->field_page];
+					if (PAGE_SIZE < (pfield_buffer->pto -
+								pfield_buffer->pgo)) {
+						SAM("ERROR: bad pfield_buffer->pto\n");
+						return;
+					}
+					if (PAGE_SIZE == (pfield_buffer->pto -
+								pfield_buffer->pgo)) {
+						(peasycap->field_page)++;
+						if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
+								peasycap->field_page) {
+							JOM(16, "wrapping peasycap->"
+								"field_page\n");
+							peasycap->field_page = 0;
+						}
+						pfield_buffer = &peasycap->
+								field_buffer
+								[peasycap->field_fill]
+								[peasycap->field_page];
+						pfield_buffer->pto = pfield_buffer->pgo;
+						pfield_buffer->input = 0x08 |
+							(0x07 & peasycap->input);
+						if ((peasycap->field_buffer[peasycap->
+								field_fill][0]).
+									input !=
+								pfield_buffer->input)
+							(peasycap->field_buffer
+								[peasycap->field_fill]
+								[0]).kount |= 0x1000;
+					}
 
-				much = PAGE_SIZE - (int)(pfield_buffer->pto - \
+					much = PAGE_SIZE -
+						(int)(pfield_buffer->pto -
 							pfield_buffer->pgo);
 
-				if (much > more)
-					much = more;
-				memcpy(pfield_buffer->pto, pu, much);
-				pu += much;
-				(pfield_buffer->pto) += much;
-				more -= much;
+					if (much > more)
+						much = more;
+					memcpy(pfield_buffer->pto, pu, much);
+					pu += much;
+					(pfield_buffer->pto) += much;
+					more -= much;
+					}
 				}
 			}
 		}
 	}
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
@@ -3332,218 +2933,130 @@ if (purb->status) {
  *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
  */
 /*---------------------------------------------------------------------------*/
-if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
-	SAM("easycap driver shutting down on condition green\n");
-	peasycap->status = 1;
-	peasycap->video_eof = 1;
-	peasycap->video_junk = 0;
-	wake_up_interruptible(&peasycap->wq_video);
+	if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
+		SAM("easycap driver shutting down on condition green\n");
+		peasycap->status = 1;
+		peasycap->video_eof = 1;
+		peasycap->video_junk = 0;
+		wake_up_interruptible(&peasycap->wq_video);
 #if !defined(PERSEVERE)
-	peasycap->audio_eof = 1;
-	wake_up_interruptible(&peasycap->wq_audio);
+		peasycap->audio_eof = 1;
+		wake_up_interruptible(&peasycap->wq_audio);
 #endif /*PERSEVERE*/
-	return;
-}
-if (peasycap->video_isoc_streaming) {
-	rc = usb_submit_urb(purb, GFP_ATOMIC);
-	if (0 != rc) {
-		switch (rc) {
-		case -ENOMEM: {
-			SAM("ENOMEM\n"); break;
-		}
-		case -ENODEV: {
-			SAM("ENODEV\n"); break;
-		}
-		case -ENXIO: {
-			SAM("ENXIO\n"); break;
-		}
-		case -EINVAL: {
-			SAM("EINVAL\n"); break;
-		}
-		case -EAGAIN: {
-			SAM("EAGAIN\n"); break;
-		}
-		case -EFBIG: {
-			SAM("EFBIG\n"); break;
-		}
-		case -EPIPE: {
-			SAM("EPIPE\n"); break;
-		}
-		case -EMSGSIZE: {
-			SAM("EMSGSIZE\n");  break;
-		}
-		case -ENOSPC: {
-			SAM("ENOSPC\n"); break;
-		}
-		default: {
-			SAM("0x%08X\n", rc); break;
-		}
+		return;
+	}
+	if (peasycap->video_isoc_streaming) {
+		rc = usb_submit_urb(purb, GFP_ATOMIC);
+		if (rc) {
+			SAM("%s: %d\n", strerror(rc), rc);
+			if (-ENODEV != rc)
+				SAM("ERROR: while %i=video_idle, "
+					"usb_submit_urb() "
+					"failed with rc:\n",
+					peasycap->video_idle);
 		}
-		if (-ENODEV != rc) \
-			SAM("ERROR: while %i=video_idle, " \
-						"usb_submit_urb() " \
-						"failed with rc:\n", \
-						peasycap->video_idle);
 	}
+	return;
 }
-return;
-}
+static const struct file_operations easycap_fops = {
+	.owner		= THIS_MODULE,
+	.open		= easycap_open,
+	.unlocked_ioctl	= easycap_unlocked_ioctl,
+	.poll		= easycap_poll,
+	.mmap		= easycap_mmap,
+	.llseek		= no_llseek,
+};
+static const struct usb_class_driver easycap_class = {
+	.name = "usb/easycap%d",
+	.fops = &easycap_fops,
+	.minor_base = USB_SKEL_MINOR_BASE,
+};
+/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
+static const struct v4l2_file_operations v4l2_fops = {
+	.owner		= THIS_MODULE,
+	.open		= easycap_open_noinode,
+	.unlocked_ioctl	= easycap_unlocked_ioctl,
+	.poll		= easycap_poll,
+	.mmap		= easycap_mmap,
+};
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
- *
- *                                  FIXME
- *
- *
- *  THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE EasyCAP
- *  IS PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST.
- *  IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops.
- *
- *  THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE.
+ *  WHEN THE EasyCAP IS PHYSICALLY PLUGGED IN, THIS FUNCTION IS CALLED THREE
+ *  TIMES, ONCE FOR EACH OF THE THREE INTERFACES.  BEWARE.
  */
 /*---------------------------------------------------------------------------*/
-int
-easycap_usb_probe(struct usb_interface *pusb_interface, \
-						const struct usb_device_id *id)
+static int easycap_usb_probe(struct usb_interface *pusb_interface,
+			    const struct usb_device_id *pusb_device_id)
 {
-struct usb_device *pusb_device, *pusb_device1;
-struct usb_host_interface *pusb_host_interface;
-struct usb_endpoint_descriptor *pepd;
-struct usb_interface_descriptor *pusb_interface_descriptor;
-struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
-struct urb *purb;
-struct easycap *peasycap;
-struct data_urb *pdata_urb;
-size_t wMaxPacketSize;
-int ISOCwMaxPacketSize;
-int BULKwMaxPacketSize;
-int INTwMaxPacketSize;
-int CTRLwMaxPacketSize;
-__u8 bEndpointAddress;
-__u8 ISOCbEndpointAddress;
-__u8 INTbEndpointAddress;
-int isin, i, j, k, m, rc;
-__u8 bInterfaceNumber;
-__u8 bInterfaceClass;
-__u8 bInterfaceSubClass;
-void *pbuf;
-int okalt[8], isokalt;
-int okepn[8];
-int okmps[8];
-int maxpacketsize;
-__u16 mask;
-__s32 value;
-struct easycap_format *peasycap_format;
-
-JOT(4, "\n");
-
-if (!dongle_done) {
-	dongle_done = 1;
-	for (k = 0; k < DONGLE_MANY; k++) {
-		easycap_dongle[k].peasycap = (struct easycap *)NULL;
-		mutex_init(&easycap_dongle[k].mutex_video);
-		mutex_init(&easycap_dongle[k].mutex_audio);
-	}
-}
+	struct usb_device *pusb_device;
+	struct usb_host_interface *pusb_host_interface;
+	struct usb_endpoint_descriptor *pepd;
+	struct usb_interface_descriptor *pusb_interface_descriptor;
+	struct urb *purb;
+	struct easycap *peasycap;
+	int ndong;
+	struct data_urb *pdata_urb;
+	size_t wMaxPacketSize;
+	int ISOCwMaxPacketSize;
+	int BULKwMaxPacketSize;
+	int INTwMaxPacketSize;
+	int CTRLwMaxPacketSize;
+	u8 bEndpointAddress;
+	u8 ISOCbEndpointAddress;
+	u8 INTbEndpointAddress;
+	int isin, i, j, k, m, rc;
+	u8 bInterfaceNumber;
+	u8 bInterfaceClass;
+	u8 bInterfaceSubClass;
+	void *pbuf;
+	int okalt[8], isokalt;
+	int okepn[8];
+	int okmps[8];
+	int maxpacketsize;
+	u16 mask;
+	s32 value;
+	struct easycap_format *peasycap_format;
+	int fmtidx;
+	struct inputset *inputset;
+	struct v4l2_device *pv4l2_device;
 
-peasycap = (struct easycap *)NULL;
-
-if ((struct usb_interface *)NULL == pusb_interface) {
-	SAY("ERROR: pusb_interface is NULL\n");
-	return -EFAULT;
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  GET POINTER TO STRUCTURE usb_device
  */
 /*---------------------------------------------------------------------------*/
-pusb_device1 = container_of(pusb_interface->dev.parent, \
-						struct usb_device, dev);
-if ((struct usb_device *)NULL == pusb_device1) {
-	SAY("ERROR: pusb_device1 is NULL\n");
-	return -EFAULT;
-}
-pusb_device = usb_get_dev(pusb_device1);
-if ((struct usb_device *)NULL == pusb_device) {
-	SAY("ERROR: pusb_device is NULL\n");
-	return -EFAULT;
-}
-if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) {
-	JOT(4, "ERROR: pusb_device1 != pusb_device\n");
-	return -EFAULT;
-}
-
-JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
+	pusb_device = interface_to_usbdev(pusb_interface);
 
+	JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
 /*---------------------------------------------------------------------------*/
-pusb_host_interface = pusb_interface->cur_altsetting;
-if (NULL == pusb_host_interface) {
-	SAY("ERROR: pusb_host_interface is NULL\n");
-	return -EFAULT;
-}
-pusb_interface_descriptor = &(pusb_host_interface->desc);
-if (NULL == pusb_interface_descriptor) {
-	SAY("ERROR: pusb_interface_descriptor is NULL\n");
-	return -EFAULT;
-}
+	pusb_host_interface = pusb_interface->cur_altsetting;
+	if (!pusb_host_interface) {
+		SAY("ERROR: pusb_host_interface is NULL\n");
+		return -EFAULT;
+	}
+	pusb_interface_descriptor = &(pusb_host_interface->desc);
+	if (!pusb_interface_descriptor) {
+		SAY("ERROR: pusb_interface_descriptor is NULL\n");
+		return -EFAULT;
+	}
 /*---------------------------------------------------------------------------*/
 /*
  *  GET PROPERTIES OF PROBED INTERFACE
  */
 /*---------------------------------------------------------------------------*/
-bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
-bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
-bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
+	bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
+	bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
+	bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
 
-JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n", \
+	JOT(4, "intf[%i]: num_altsetting=%i\n",
 			bInterfaceNumber, pusb_interface->num_altsetting);
-JOT(4, "intf[%i]: pusb_interface->cur_altsetting - " \
-			"pusb_interface->altsetting=%li\n", bInterfaceNumber, \
-			(long int)(pusb_interface->cur_altsetting - \
-						pusb_interface->altsetting));
-switch (bInterfaceClass) {
-case USB_CLASS_AUDIO: {
-	JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n", \
-				bInterfaceNumber, bInterfaceClass); break;
-	}
-case USB_CLASS_VIDEO: {
-	JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n", \
-				bInterfaceNumber, bInterfaceClass); break;
-	}
-case USB_CLASS_VENDOR_SPEC: {
-	JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n", \
-				bInterfaceNumber, bInterfaceClass); break;
-	}
-default:
-	break;
-}
-switch (bInterfaceSubClass) {
-case 0x01: {
-	JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n", \
-			bInterfaceNumber, bInterfaceSubClass); break;
-}
-case 0x02: {
-	JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n", \
-			bInterfaceNumber, bInterfaceSubClass); break;
-}
-case 0x03: {
-	JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n", \
-			bInterfaceNumber, bInterfaceSubClass); break;
-}
-default:
-	break;
-}
-/*---------------------------------------------------------------------------*/
-pusb_interface_assoc_descriptor = pusb_interface->intf_assoc;
-if (NULL != pusb_interface_assoc_descriptor) {
-	JOT(4, "intf[%i]: bFirstInterface=0x%02X  bInterfaceCount=0x%02X\n", \
-			bInterfaceNumber, \
-			pusb_interface_assoc_descriptor->bFirstInterface, \
-			pusb_interface_assoc_descriptor->bInterfaceCount);
-} else {
-JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \
-							bInterfaceNumber);
-}
+	JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
+		bInterfaceNumber,
+		(long int)(pusb_interface->cur_altsetting -
+				pusb_interface->altsetting));
+	JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
+			bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
 /*---------------------------------------------------------------------------*/
 /*
  *  A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED.
@@ -3553,788 +3066,785 @@ JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \
  *
  *  THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
  *  INTERFACES 1 AND 2 ARE PROBED.
- *
- *  IF TWO EasyCAPs ARE PLUGGED IN NEARLY SIMULTANEOUSLY THERE WILL
- *  BE TROUBLE.  BEWARE.
 */
 /*---------------------------------------------------------------------------*/
-if (0 == bInterfaceNumber) {
-	peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
-	if (NULL == peasycap) {
-		SAY("ERROR: Could not allocate peasycap\n");
-		return -ENOMEM;
-	}
-	SAM("allocated 0x%08lX=peasycap\n", (unsigned long int) peasycap);
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-	SAM("where     0x%08lX=&peasycap->video_device\n", \
-				(unsigned long int) &peasycap->video_device);
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-	SAM("and       0x%08lX=&peasycap->v4l2_device\n", \
-				(unsigned long int) &peasycap->v4l2_device);
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+	if (0 == bInterfaceNumber) {
+		peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
+		if (!peasycap) {
+			SAY("ERROR: Could not allocate peasycap\n");
+			return -ENOMEM;
+		}
 /*---------------------------------------------------------------------------*/
 /*
  *  PERFORM URGENT INTIALIZATIONS ...
 */
 /*---------------------------------------------------------------------------*/
-	strcpy(&peasycap->telltale[0], TELLTALE);
-	kref_init(&peasycap->kref);
-	JOM(8, "intf[%i]: after kref_init(..._video) " \
-			"%i=peasycap->kref.refcount.counter\n", \
-			bInterfaceNumber, peasycap->kref.refcount.counter);
-
-	init_waitqueue_head(&peasycap->wq_video);
-	init_waitqueue_head(&peasycap->wq_audio);
-
-	for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) {
-		if (NULL == easycap_dongle[dongle_this].peasycap) {
-			if (0 == mutex_is_locked(&easycap_dongle\
-						[dongle_this].mutex_video)) {
-				if (0 == mutex_is_locked(&easycap_dongle\
-						[dongle_this].mutex_audio)) {
-					easycap_dongle\
-						[dongle_this].peasycap = \
-								peasycap;
-					JOM(8, "intf[%i]: peasycap-->easycap" \
-						"_dongle[%i].peasycap\n", \
-						bInterfaceNumber, dongle_this);
+		peasycap->minor = -1;
+		strcpy(&peasycap->telltale[0], TELLTALE);
+		kref_init(&peasycap->kref);
+		JOM(8, "intf[%i]: after kref_init(..._video) "
+				"%i=peasycap->kref.refcount.counter\n",
+				bInterfaceNumber, peasycap->kref.refcount.counter);
+
+		/* module params */
+		peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
+
+		init_waitqueue_head(&peasycap->wq_video);
+		init_waitqueue_head(&peasycap->wq_audio);
+		init_waitqueue_head(&peasycap->wq_trigger);
+
+		if (mutex_lock_interruptible(&mutex_dongle)) {
+			SAY("ERROR: cannot down mutex_dongle\n");
+			return -ERESTARTSYS;
+		} else {
+/*---------------------------------------------------------------------------*/
+		/*
+		 *  FOR INTERFACES 1 AND 2 THE POINTER peasycap WILL NEED TO
+		 *  TO BE THE SAME AS THAT ALLOCATED NOW FOR INTERFACE 0.
+		 *
+		 *  NORMALLY ndong WILL NOT HAVE CHANGED SINCE INTERFACE 0 WAS
+		 *  PROBED, BUT THIS MAY NOT BE THE CASE IF, FOR EXAMPLE, TWO
+		 *  EASYCAPs ARE PLUGGED IN SIMULTANEOUSLY.
+		*/
+/*---------------------------------------------------------------------------*/
+			for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+				if ((!easycapdc60_dongle[ndong].peasycap) &&
+						(!mutex_is_locked(&easycapdc60_dongle
+							[ndong].mutex_video)) &&
+						(!mutex_is_locked(&easycapdc60_dongle
+							[ndong].mutex_audio))) {
+					easycapdc60_dongle[ndong].peasycap = peasycap;
+					peasycap->isdongle = ndong;
+					JOM(8, "intf[%i]: peasycap-->easycap"
+							"_dongle[%i].peasycap\n",
+							bInterfaceNumber, ndong);
 					break;
 				}
 			}
-		}
-	}
-	if (DONGLE_MANY <= dongle_this) {
-		SAM("ERROR: too many dongles\n");
-		return -ENOMEM;
-	}
-
-	peasycap->allocation_video_struct = sizeof(struct easycap);
-	peasycap->allocation_video_page = 0;
-	peasycap->allocation_video_urb = 0;
-	peasycap->allocation_audio_struct = 0;
-	peasycap->allocation_audio_page = 0;
-	peasycap->allocation_audio_urb = 0;
+			if (DONGLE_MANY <= ndong) {
+				SAM("ERROR: too many dongles\n");
+				mutex_unlock(&mutex_dongle);
+				return -ENOMEM;
+			}
+			mutex_unlock(&mutex_dongle);
+		}
+		peasycap->allocation_video_struct = sizeof(struct easycap);
+		peasycap->allocation_video_page = 0;
+		peasycap->allocation_video_urb = 0;
+		peasycap->allocation_audio_struct = 0;
+		peasycap->allocation_audio_page = 0;
+		peasycap->allocation_audio_urb = 0;
 
 /*---------------------------------------------------------------------------*/
 /*
  *  ... AND FURTHER INITIALIZE THE STRUCTURE
 */
 /*---------------------------------------------------------------------------*/
-	peasycap->pusb_device = pusb_device;
-	peasycap->pusb_interface = pusb_interface;
+		peasycap->pusb_device = pusb_device;
+		peasycap->pusb_interface = pusb_interface;
 
-	peasycap->ilk = 0;
-	peasycap->microphone = false;
+		peasycap->ilk = 0;
+		peasycap->microphone = false;
 
-	peasycap->video_interface = -1;
-	peasycap->video_altsetting_on = -1;
-	peasycap->video_altsetting_off = -1;
-	peasycap->video_endpointnumber = -1;
-	peasycap->video_isoc_maxframesize = -1;
-	peasycap->video_isoc_buffer_size = -1;
+		peasycap->video_interface = -1;
+		peasycap->video_altsetting_on = -1;
+		peasycap->video_altsetting_off = -1;
+		peasycap->video_endpointnumber = -1;
+		peasycap->video_isoc_maxframesize = -1;
+		peasycap->video_isoc_buffer_size = -1;
 
-	peasycap->audio_interface = -1;
-	peasycap->audio_altsetting_on = -1;
-	peasycap->audio_altsetting_off = -1;
-	peasycap->audio_endpointnumber = -1;
-	peasycap->audio_isoc_maxframesize = -1;
-	peasycap->audio_isoc_buffer_size = -1;
+		peasycap->audio_interface = -1;
+		peasycap->audio_altsetting_on = -1;
+		peasycap->audio_altsetting_off = -1;
+		peasycap->audio_endpointnumber = -1;
+		peasycap->audio_isoc_maxframesize = -1;
+		peasycap->audio_isoc_buffer_size = -1;
 
-	peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
+		peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
 
-	for (k = 0; k < INPUT_MANY; k++)
-		peasycap->lost[k] = 0;
-	peasycap->skip = 0;
-	peasycap->skipped = 0;
-	peasycap->offerfields = 0;
+		for (k = 0; k < INPUT_MANY; k++)
+			peasycap->lost[k] = 0;
+		peasycap->skip = 0;
+		peasycap->skipped = 0;
+		peasycap->offerfields = 0;
 /*---------------------------------------------------------------------------*/
 /*
  *  DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
  */
 /*---------------------------------------------------------------------------*/
-	rc = fillin_formats();
-	if (0 > rc) {
-		SAM("ERROR: fillin_formats() returned %i\n", rc);
-		return -EFAULT;
-	}
-	JOM(4, "%i formats available\n", rc);
+		rc = fillin_formats();
+		if (0 > rc) {
+			SAM("ERROR: fillin_formats() rc = %i\n", rc);
+			return -EFAULT;
+		}
+		JOM(4, "%i formats available\n", rc);
 /*---------------------------------------------------------------------------*/
 /*
  *  ... AND POPULATE easycap.inputset[]
 */
 /*---------------------------------------------------------------------------*/
-	for (k = 0; k < INPUT_MANY; k++) {
-		peasycap->inputset[k].input_ok = 0;
-		peasycap->inputset[k].standard_offset_ok = 0;
-		peasycap->inputset[k].format_offset_ok = 0;
-		peasycap->inputset[k].brightness_ok = 0;
-		peasycap->inputset[k].contrast_ok = 0;
-		peasycap->inputset[k].saturation_ok = 0;
-		peasycap->inputset[k].hue_ok = 0;
-	}
-	if (true == peasycap->ntsc) {
-		i = 0;
+		/* FIXME: maybe we just use memset 0 */
+		inputset = peasycap->inputset;
+		for (k = 0; k < INPUT_MANY; k++) {
+			inputset[k].input_ok = 0;
+			inputset[k].standard_offset_ok = 0;
+			inputset[k].format_offset_ok = 0;
+			inputset[k].brightness_ok = 0;
+			inputset[k].contrast_ok = 0;
+			inputset[k].saturation_ok = 0;
+			inputset[k].hue_ok = 0;
+		}
+
+		fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
 		m = 0;
 		mask = 0;
-		while (0xFFFF != easycap_standard[i].mask) {
-			if (NTSC_M == easycap_standard[i].\
-							v4l2_standard.index) {
+		for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
+			if (fmtidx == easycap_standard[i].v4l2_standard.index) {
 				m++;
-				for (k = 0; k < INPUT_MANY; k++) {
-					peasycap->inputset[k].\
-							standard_offset = i;
-				}
-			mask = easycap_standard[i].mask;
+				for (k = 0; k < INPUT_MANY; k++)
+					inputset[k].standard_offset = i;
+
+				mask = easycap_standard[i].mask;
 			}
-			i++;
 		}
-	} else {
-		i = 0;
+
+		if (1 != m) {
+			SAM("ERROR: "
+			    "inputset->standard_offset unpopulated, %i=m\n", m);
+			return -ENOENT;
+		}
+
+		peasycap_format = &easycap_format[0];
 		m = 0;
-		mask = 0;
-		while (0xFFFF != easycap_standard[i].mask) {
-			if (PAL_BGHIN == easycap_standard[i].\
-							v4l2_standard.index) {
+		for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
+			struct v4l2_pix_format *pix =
+				&peasycap_format->v4l2_format.fmt.pix;
+			if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
+			    pix->field == V4L2_FIELD_NONE &&
+			    pix->pixelformat == V4L2_PIX_FMT_UYVY &&
+			    pix->width  == 640 && pix->height == 480) {
 				m++;
-				for (k = 0; k < INPUT_MANY; k++) {
-					peasycap->inputset[k].\
-							standard_offset = i;
-				}
-			mask = easycap_standard[i].mask;
+				for (k = 0; k < INPUT_MANY; k++)
+					inputset[k].format_offset = i;
+				break;
 			}
-			i++;
+			peasycap_format++;
+		}
+		if (1 != m) {
+			SAM("ERROR: inputset[]->format_offset unpopulated\n");
+			return -ENOENT;
 		}
-	}
-
-	if (1 != m) {
-		SAM("MISTAKE: easycap.inputset[].standard_offset " \
-						"unpopulated, %i=m\n", m);
-		return -ENOENT;
-	}
 
-	peasycap_format = &easycap_format[0];
-	i = 0;
-	m = 0;
-	while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
-		if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \
-				(peasycap_format->\
-					v4l2_format.fmt.pix.field == \
-							V4L2_FIELD_NONE) && \
-				(peasycap_format->\
-					v4l2_format.fmt.pix.pixelformat == \
-							V4L2_PIX_FMT_UYVY) && \
-				(peasycap_format->\
-					v4l2_format.fmt.pix.width  == \
-							640) && \
-				(peasycap_format->\
-					v4l2_format.fmt.pix.height == 480)) {
-			m++;
-			for (k = 0; k < INPUT_MANY; k++)
-				peasycap->inputset[k].format_offset = i;
-			break;
+		m = 0;
+		for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
+			value = easycap_control[i].default_value;
+			if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
+				m++;
+				for (k = 0; k < INPUT_MANY; k++)
+					inputset[k].brightness = value;
+			} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
+				m++;
+				for (k = 0; k < INPUT_MANY; k++)
+					inputset[k].contrast = value;
+			} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
+				m++;
+				for (k = 0; k < INPUT_MANY; k++)
+					inputset[k].saturation = value;
+			} else if (V4L2_CID_HUE == easycap_control[i].id) {
+				m++;
+				for (k = 0; k < INPUT_MANY; k++)
+					inputset[k].hue = value;
+			}
 		}
-	peasycap_format++;
-	i++;
-	}
-	if (1 != m) {
-		SAM("MISTAKE: easycap.inputset[].format_offset unpopulated\n");
-	return -ENOENT;
-	}
 
-	i = 0;
-	m = 0;
-	while (0xFFFFFFFF != easycap_control[i].id) {
-		value = easycap_control[i].default_value;
-		if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
-			m++;
-			for (k = 0; k < INPUT_MANY; k++)
-				peasycap->inputset[k].brightness = value;
-		} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
-			m++;
-			for (k = 0; k < INPUT_MANY; k++)
-				peasycap->inputset[k].contrast = value;
-		} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
-			m++;
-			for (k = 0; k < INPUT_MANY; k++)
-				peasycap->inputset[k].saturation = value;
-		} else if (V4L2_CID_HUE == easycap_control[i].id) {
-			m++;
-			for (k = 0; k < INPUT_MANY; k++)
-				peasycap->inputset[k].hue = value;
+		if (4 != m) {
+			SAM("ERROR: inputset[]->brightness underpopulated\n");
+			return -ENOENT;
 		}
-		i++;
-	}
-	if (4 != m) {
-		SAM("MISTAKE: easycap.inputset[].brightness,... " \
-						"underpopulated\n");
-		return -ENOENT;
-	}
-	for (k = 0; k < INPUT_MANY; k++)
-		peasycap->inputset[k].input = k;
-	JOM(4, "populated easycap.inputset[]\n");
-	JOM(4, "finished initialization\n");
-} else {
+		for (k = 0; k < INPUT_MANY; k++)
+			inputset[k].input = k;
+		JOM(4, "populated inputset[]\n");
+		JOM(4, "finished initialization\n");
+	} else {
 /*---------------------------------------------------------------------------*/
-	/*
-	 *  FOR INTERFACES 1 AND 2 THE POINTER peasycap IS OBTAINED BY ASSUMING
-	 *  THAT dongle_this HAS NOT CHANGED SINCE INTERFACE 0 WAS PROBED.  IF
-	 *  THIS IS NOT THE CASE, FOR EXAMPLE WHEN TWO EASYCAPs ARE PLUGGED IN
-	 *  SIMULTANEOUSLY, THERE WILL BE SERIOUS TROUBLE.
-	*/
+/*
+ *                                 FIXME
+ *
+ *  IDENTIFY THE APPROPRIATE POINTER peasycap FOR INTERFACES 1 AND 2.
+ *  THE ADDRESS OF peasycap->pusb_device IS RELUCTANTLY USED FOR THIS PURPOSE.
+ */
 /*---------------------------------------------------------------------------*/
-	if ((0 > dongle_this) || (DONGLE_MANY <= dongle_this)) {
-		SAY("ERROR: bad dongle count\n");
-		return -EFAULT;
-	}
-	peasycap = easycap_dongle[dongle_this].peasycap;
-	JOT(8, "intf[%i]: easycap_dongle[%i].peasycap-->peasycap\n", \
-						bInterfaceNumber, dongle_this);
-
-	if ((struct easycap *)NULL == peasycap) {
-		SAY("ERROR: peasycap is NULL when probing interface %i\n", \
-							bInterfaceNumber);
-		return -EFAULT;
+		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
+			if (pusb_device == easycapdc60_dongle[ndong].peasycap->
+									pusb_device) {
+				peasycap = easycapdc60_dongle[ndong].peasycap;
+				JOT(8, "intf[%i]: dongle[%i].peasycap\n",
+						bInterfaceNumber, ndong);
+				break;
+			}
+		}
+		if (DONGLE_MANY <= ndong) {
+			SAY("ERROR: peasycap is unknown when probing interface %i\n",
+								bInterfaceNumber);
+			return -ENODEV;
+		}
+		if (!peasycap) {
+			SAY("ERROR: peasycap is NULL when probing interface %i\n",
+								bInterfaceNumber);
+			return -ENODEV;
+		}
+/*---------------------------------------------------------------------------*/
+/*
+ *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
+ *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
+ *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
+ *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
+*/
+/*---------------------------------------------------------------------------*/
+		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+			pv4l2_device = usb_get_intfdata(pusb_interface);
+			if (!pv4l2_device) {
+				SAY("ERROR: pv4l2_device is NULL\n");
+				return -ENODEV;
+			}
+			peasycap = (struct easycap *)
+				container_of(pv4l2_device, struct easycap, v4l2_device);
+		}
 	}
-}
 /*---------------------------------------------------------------------------*/
-if ((USB_CLASS_VIDEO == bInterfaceClass) || \
-		(USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
-	if (-1 == peasycap->video_interface) {
-		peasycap->video_interface = bInterfaceNumber;
-		JOM(4, "setting peasycap->video_interface=%i\n", \
+	if ((USB_CLASS_VIDEO == bInterfaceClass) ||
+	    (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
+		if (-1 == peasycap->video_interface) {
+			peasycap->video_interface = bInterfaceNumber;
+			JOM(4, "setting peasycap->video_interface=%i\n",
+							peasycap->video_interface);
+		} else {
+			if (peasycap->video_interface != bInterfaceNumber) {
+				SAM("ERROR: attempting to reset "
+						"peasycap->video_interface\n");
+				SAM("...... continuing with "
+						"%i=peasycap->video_interface\n",
 						peasycap->video_interface);
-	} else {
-		if (peasycap->video_interface != bInterfaceNumber) {
-			SAM("ERROR: attempting to reset " \
-					"peasycap->video_interface\n");
-			SAM("...... continuing with " \
-					"%i=peasycap->video_interface\n", \
-					peasycap->video_interface);
+			}
 		}
-	}
-} else if ((USB_CLASS_AUDIO == bInterfaceClass) && \
-						(0x02 == bInterfaceSubClass)) {
-	if (-1 == peasycap->audio_interface) {
-		peasycap->audio_interface = bInterfaceNumber;
-		JOM(4, "setting peasycap->audio_interface=%i\n", \
-						 peasycap->audio_interface);
-	} else {
-		if (peasycap->audio_interface != bInterfaceNumber) {
-			SAM("ERROR: attempting to reset " \
-					"peasycap->audio_interface\n");
-			SAM("...... continuing with " \
-					"%i=peasycap->audio_interface\n", \
-					peasycap->audio_interface);
+	} else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
+		   (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
+		if (-1 == peasycap->audio_interface) {
+			peasycap->audio_interface = bInterfaceNumber;
+			JOM(4, "setting peasycap->audio_interface=%i\n",
+							 peasycap->audio_interface);
+		} else {
+			if (peasycap->audio_interface != bInterfaceNumber) {
+				SAM("ERROR: attempting to reset "
+						"peasycap->audio_interface\n");
+				SAM("...... continuing with "
+						"%i=peasycap->audio_interface\n",
+						peasycap->audio_interface);
+			}
 		}
 	}
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  INVESTIGATE ALL ALTSETTINGS.
  *  DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
  */
 /*---------------------------------------------------------------------------*/
-isokalt = 0;
-
-for (i = 0; i < pusb_interface->num_altsetting; i++) {
-	pusb_host_interface = &(pusb_interface->altsetting[i]);
-	if ((struct usb_host_interface *)NULL == pusb_host_interface) {
-		SAM("ERROR: pusb_host_interface is NULL\n");
-		return -EFAULT;
-	}
-	pusb_interface_descriptor = &(pusb_host_interface->desc);
-	if ((struct usb_interface_descriptor *)NULL == \
-						pusb_interface_descriptor) {
-		SAM("ERROR: pusb_interface_descriptor is NULL\n");
-		return -EFAULT;
-	}
+	isokalt = 0;
 
-	JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
-	JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
-	JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
-	JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
-	JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
-	JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
-	JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
-	JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n", \
-	bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
-
-	ISOCwMaxPacketSize = -1;
-	BULKwMaxPacketSize = -1;
-	INTwMaxPacketSize = -1;
-	CTRLwMaxPacketSize = -1;
-	ISOCbEndpointAddress = 0;
-	INTbEndpointAddress = 0;
-
-	if (0 == pusb_interface_descriptor->bNumEndpoints)
-				JOM(4, "intf[%i]alt[%i] has no endpoints\n", \
-							bInterfaceNumber, i);
-/*---------------------------------------------------------------------------*/
-	for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
-		pepd = &(pusb_host_interface->endpoint[j].desc);
-		if ((struct usb_endpoint_descriptor *)NULL == pepd) {
-			SAM("ERROR:  pepd is NULL.\n");
-			SAM("...... skipping\n");
-			continue;
+	for (i = 0; i < pusb_interface->num_altsetting; i++) {
+		pusb_host_interface = &(pusb_interface->altsetting[i]);
+		if (!pusb_host_interface) {
+			SAM("ERROR: pusb_host_interface is NULL\n");
+			return -EFAULT;
 		}
-		wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
-		bEndpointAddress = pepd->bEndpointAddress;
-
-		JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n", \
-				bInterfaceNumber, i, j, \
-				pepd->bEndpointAddress);
-		JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n", \
-				bInterfaceNumber, i, j, \
-				pepd->bmAttributes);
-		JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n", \
-				bInterfaceNumber, i, j, \
-				pepd->wMaxPacketSize);
-		JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
-				bInterfaceNumber, i, j, \
-				pepd->bInterval);
-
-		if (pepd->bEndpointAddress & USB_DIR_IN) {
-			JOM(4, "intf[%i]alt[%i]end[%i] is an  IN  endpoint\n",\
-						bInterfaceNumber, i, j);
-			isin = 1;
-		} else {
-			JOM(4, "intf[%i]alt[%i]end[%i] is an  OUT endpoint\n",\
-						bInterfaceNumber, i, j);
-			SAM("ERROR: OUT endpoint unexpected\n");
-			SAM("...... continuing\n");
-			isin = 0;
+		pusb_interface_descriptor = &(pusb_host_interface->desc);
+		if (!pusb_interface_descriptor) {
+			SAM("ERROR: pusb_interface_descriptor is NULL\n");
+			return -EFAULT;
 		}
-		if ((pepd->bmAttributes & \
-				USB_ENDPOINT_XFERTYPE_MASK) == \
-				USB_ENDPOINT_XFER_ISOC) {
-			JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",\
-						bInterfaceNumber, i, j);
-			if (isin) {
-				switch (bInterfaceClass) {
-				case USB_CLASS_VIDEO:
-				case USB_CLASS_VENDOR_SPEC: {
-					if (!peasycap) {
-						SAM("MISTAKE: " \
-							"peasycap is NULL\n");
-						return -EFAULT;
-					}
-					if (pepd->wMaxPacketSize) {
-						if (8 > isokalt) {
-							okalt[isokalt] = i;
-							JOM(4,\
-							"%i=okalt[%i]\n", \
-							okalt[isokalt], \
-							isokalt);
-							okepn[isokalt] = \
-							pepd->\
-							bEndpointAddress & \
-							0x0F;
-							JOM(4,\
-							"%i=okepn[%i]\n", \
-							okepn[isokalt], \
-							isokalt);
-							okmps[isokalt] = \
-							le16_to_cpu(pepd->\
-							wMaxPacketSize);
-							JOM(4,\
-							"%i=okmps[%i]\n", \
-							okmps[isokalt], \
-							isokalt);
-							isokalt++;
+
+		JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
+		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
+		JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
+		JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
+		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
+		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
+		JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
+		JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n",
+		bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
+
+		ISOCwMaxPacketSize = -1;
+		BULKwMaxPacketSize = -1;
+		INTwMaxPacketSize = -1;
+		CTRLwMaxPacketSize = -1;
+		ISOCbEndpointAddress = 0;
+		INTbEndpointAddress = 0;
+
+		if (0 == pusb_interface_descriptor->bNumEndpoints)
+			JOM(4, "intf[%i]alt[%i] has no endpoints\n",
+						bInterfaceNumber, i);
+/*---------------------------------------------------------------------------*/
+		for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
+			pepd = &(pusb_host_interface->endpoint[j].desc);
+			if (!pepd) {
+				SAM("ERROR:  pepd is NULL.\n");
+				SAM("...... skipping\n");
+				continue;
+			}
+			wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
+			bEndpointAddress = pepd->bEndpointAddress;
+
+			JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n",
+					bInterfaceNumber, i, j,
+					pepd->bEndpointAddress);
+			JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n",
+					bInterfaceNumber, i, j,
+					pepd->bmAttributes);
+			JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n",
+					bInterfaceNumber, i, j,
+					pepd->wMaxPacketSize);
+			JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
+					bInterfaceNumber, i, j,
+					pepd->bInterval);
+
+			if (pepd->bEndpointAddress & USB_DIR_IN) {
+				JOM(4, "intf[%i]alt[%i]end[%i] is an  IN  endpoint\n",
+							bInterfaceNumber, i, j);
+				isin = 1;
+			} else {
+				JOM(4, "intf[%i]alt[%i]end[%i] is an  OUT endpoint\n",
+							bInterfaceNumber, i, j);
+				SAM("ERROR: OUT endpoint unexpected\n");
+				SAM("...... continuing\n");
+				isin = 0;
+			}
+			if ((pepd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+						USB_ENDPOINT_XFER_ISOC) {
+				JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",
+							bInterfaceNumber, i, j);
+				if (isin) {
+					switch (bInterfaceClass) {
+					case USB_CLASS_VIDEO:
+					case USB_CLASS_VENDOR_SPEC: {
+						if (!peasycap) {
+							SAM("MISTAKE: "
+								"peasycap is NULL\n");
+							return -EFAULT;
 						}
-					} else {
-						if (-1 == peasycap->\
-							video_altsetting_off) {
-							peasycap->\
-							video_altsetting_off =\
-									 i;
-							JOM(4, "%i=video_" \
-							"altsetting_off " \
-								"<====\n", \
-							peasycap->\
-							video_altsetting_off);
+						if (pepd->wMaxPacketSize) {
+							if (8 > isokalt) {
+								okalt[isokalt] = i;
+								JOM(4,
+								"%i=okalt[%i]\n",
+								okalt[isokalt],
+								isokalt);
+								okepn[isokalt] =
+								pepd->
+								bEndpointAddress &
+								0x0F;
+								JOM(4,
+								"%i=okepn[%i]\n",
+								okepn[isokalt],
+								isokalt);
+								okmps[isokalt] =
+								le16_to_cpu(pepd->
+								wMaxPacketSize);
+								JOM(4,
+								"%i=okmps[%i]\n",
+								okmps[isokalt],
+								isokalt);
+								isokalt++;
+							}
 						} else {
-							SAM("ERROR: peasycap" \
-							"->video_altsetting_" \
-							"off already set\n");
-							SAM("...... " \
-							"continuing with " \
-							"%i=peasycap->video_" \
-							"altsetting_off\n", \
-							peasycap->\
-							video_altsetting_off);
+							if (-1 == peasycap->
+								video_altsetting_off) {
+								peasycap->
+								video_altsetting_off =
+										 i;
+								JOM(4, "%i=video_"
+								"altsetting_off "
+									"<====\n",
+								peasycap->
+								video_altsetting_off);
+							} else {
+								SAM("ERROR: peasycap"
+								"->video_altsetting_"
+								"off already set\n");
+								SAM("...... "
+								"continuing with "
+								"%i=peasycap->video_"
+								"altsetting_off\n",
+								peasycap->
+								video_altsetting_off);
+							}
 						}
-					}
-					break;
-				}
-				case USB_CLASS_AUDIO: {
-					if (0x02 != bInterfaceSubClass)
 						break;
-					if (!peasycap) {
-						SAM("MISTAKE: " \
-						"peasycap is NULL\n");
-						return -EFAULT;
 					}
-					if (pepd->wMaxPacketSize) {
-						if (8 > isokalt) {
-							okalt[isokalt] = i ;
-							JOM(4,\
-							"%i=okalt[%i]\n", \
-							okalt[isokalt], \
-							isokalt);
-							okepn[isokalt] = \
-							pepd->\
-							bEndpointAddress & \
-							0x0F;
-							JOM(4,\
-							"%i=okepn[%i]\n", \
-							okepn[isokalt], \
-							isokalt);
-							okmps[isokalt] = \
-							le16_to_cpu(pepd->\
-							wMaxPacketSize);
-							JOM(4,\
-							"%i=okmps[%i]\n",\
-							okmps[isokalt], \
-							isokalt);
-							isokalt++;
+					case USB_CLASS_AUDIO: {
+						if (bInterfaceSubClass !=
+						    USB_SUBCLASS_AUDIOSTREAMING)
+							break;
+						if (!peasycap) {
+							SAM("MISTAKE: "
+							"peasycap is NULL\n");
+							return -EFAULT;
 						}
-					} else {
-						if (-1 == peasycap->\
-							audio_altsetting_off) {
-							peasycap->\
-							audio_altsetting_off =\
-									 i;
-							JOM(4, "%i=audio_" \
-							"altsetting_off " \
-							"<====\n", \
-							peasycap->\
-							audio_altsetting_off);
+						if (pepd->wMaxPacketSize) {
+							if (8 > isokalt) {
+								okalt[isokalt] = i ;
+								JOM(4,
+								"%i=okalt[%i]\n",
+								okalt[isokalt],
+								isokalt);
+								okepn[isokalt] =
+								pepd->
+								bEndpointAddress &
+								0x0F;
+								JOM(4,
+								"%i=okepn[%i]\n",
+								okepn[isokalt],
+								isokalt);
+								okmps[isokalt] =
+								le16_to_cpu(pepd->
+								wMaxPacketSize);
+								JOM(4,
+								"%i=okmps[%i]\n",
+								okmps[isokalt],
+								isokalt);
+								isokalt++;
+							}
 						} else {
-							SAM("ERROR: peasycap" \
-							"->audio_altsetting_" \
-							"off already set\n");
-							SAM("...... " \
-							"continuing with " \
-							"%i=peasycap->\
-							audio_altsetting_" \
-							"off\n",
-							peasycap->\
-							audio_altsetting_off);
+							if (-1 == peasycap->
+								audio_altsetting_off) {
+								peasycap->
+								audio_altsetting_off =
+										 i;
+								JOM(4, "%i=audio_"
+								"altsetting_off "
+								"<====\n",
+								peasycap->
+								audio_altsetting_off);
+							} else {
+								SAM("ERROR: peasycap"
+								"->audio_altsetting_"
+								"off already set\n");
+								SAM("...... "
+								"continuing with "
+								"%i=peasycap->"
+								"audio_altsetting_"
+								"off\n",
+								peasycap->
+								audio_altsetting_off);
+							}
 						}
-					}
-				break;
-				}
-				default:
 					break;
+					}
+					default:
+						break;
+					}
 				}
+			} else if ((pepd->bmAttributes &
+							USB_ENDPOINT_XFERTYPE_MASK) ==
+							USB_ENDPOINT_XFER_BULK) {
+				JOM(4, "intf[%i]alt[%i]end[%i] is a  BULK endpoint\n",
+							bInterfaceNumber, i, j);
+			} else if ((pepd->bmAttributes &
+							USB_ENDPOINT_XFERTYPE_MASK) ==
+							USB_ENDPOINT_XFER_INT) {
+				JOM(4, "intf[%i]alt[%i]end[%i] is an  INT endpoint\n",
+							bInterfaceNumber, i, j);
+			} else {
+				JOM(4, "intf[%i]alt[%i]end[%i] is a  CTRL endpoint\n",
+							bInterfaceNumber, i, j);
+			}
+			if (0 == pepd->wMaxPacketSize) {
+				JOM(4, "intf[%i]alt[%i]end[%i] "
+							"has zero packet size\n",
+							bInterfaceNumber, i, j);
 			}
-		} else if ((pepd->bmAttributes & \
-						USB_ENDPOINT_XFERTYPE_MASK) ==\
-						USB_ENDPOINT_XFER_BULK) {
-			JOM(4, "intf[%i]alt[%i]end[%i] is a  BULK endpoint\n",\
-						bInterfaceNumber, i, j);
-		} else if ((pepd->bmAttributes & \
-						USB_ENDPOINT_XFERTYPE_MASK) ==\
-						USB_ENDPOINT_XFER_INT) {
-			JOM(4, "intf[%i]alt[%i]end[%i] is an  INT endpoint\n",\
-						bInterfaceNumber, i, j);
-		} else {
-			JOM(4, "intf[%i]alt[%i]end[%i] is a  CTRL endpoint\n",\
-						bInterfaceNumber, i, j);
-		}
-		if (0 == pepd->wMaxPacketSize) {
-			JOM(4, "intf[%i]alt[%i]end[%i] " \
-						"has zero packet size\n", \
-						bInterfaceNumber, i, j);
 		}
 	}
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  PERFORM INITIALIZATION OF THE PROBED INTERFACE
  */
 /*---------------------------------------------------------------------------*/
-JOM(4, "initialization begins for interface %i\n", \
-				pusb_interface_descriptor->bInterfaceNumber);
-switch (bInterfaceNumber) {
+	JOM(4, "initialization begins for interface %i\n",
+		pusb_interface_descriptor->bInterfaceNumber);
+	switch (bInterfaceNumber) {
 /*---------------------------------------------------------------------------*/
 /*
  *  INTERFACE 0 IS THE VIDEO INTERFACE
  */
 /*---------------------------------------------------------------------------*/
-case 0: {
-	if (!peasycap) {
-		SAM("MISTAKE: peasycap is NULL\n");
-		return -EFAULT;
-	}
-	if (!isokalt) {
-		SAM("ERROR:  no viable video_altsetting_on\n");
-		return -ENOENT;
-	} else {
-		peasycap->video_altsetting_on = okalt[isokalt - 1];
-		JOM(4, "%i=video_altsetting_on <====\n", \
-					peasycap->video_altsetting_on);
-	}
+	case 0: {
+		if (!peasycap) {
+			SAM("MISTAKE: peasycap is NULL\n");
+			return -EFAULT;
+		}
+		if (!isokalt) {
+			SAM("ERROR:  no viable video_altsetting_on\n");
+			return -ENOENT;
+		} else {
+			peasycap->video_altsetting_on = okalt[isokalt - 1];
+			JOM(4, "%i=video_altsetting_on <====\n",
+						peasycap->video_altsetting_on);
+		}
 /*---------------------------------------------------------------------------*/
 /*
  *  DECIDE THE VIDEO STREAMING PARAMETERS
  */
 /*---------------------------------------------------------------------------*/
-	peasycap->video_endpointnumber = okepn[isokalt - 1];
-	JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
-	maxpacketsize = okmps[isokalt - 1];
-	if (USB_2_0_MAXPACKETSIZE > maxpacketsize) {
-		peasycap->video_isoc_maxframesize = maxpacketsize;
-	} else {
-		peasycap->video_isoc_maxframesize = \
-						USB_2_0_MAXPACKETSIZE;
-	}
-	JOM(4, "%i=video_isoc_maxframesize\n", \
-				peasycap->video_isoc_maxframesize);
-	if (0 >= peasycap->video_isoc_maxframesize) {
-		SAM("ERROR:  bad video_isoc_maxframesize\n");
-		SAM("        possibly because port is USB 1.1\n");
-		return -ENOENT;
-	}
-	peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
-	JOM(4, "%i=video_isoc_framesperdesc\n", \
-				peasycap->video_isoc_framesperdesc);
-	if (0 >= peasycap->video_isoc_framesperdesc) {
-		SAM("ERROR:  bad video_isoc_framesperdesc\n");
-		return -ENOENT;
-	}
-	peasycap->video_isoc_buffer_size = \
-				peasycap->video_isoc_maxframesize * \
-				peasycap->video_isoc_framesperdesc;
-	JOM(4, "%i=video_isoc_buffer_size\n", \
-				peasycap->video_isoc_buffer_size);
-	if ((PAGE_SIZE << VIDEO_ISOC_ORDER) < \
-				peasycap->video_isoc_buffer_size) {
-		SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
-		return -EFAULT;
-	}
+		peasycap->video_endpointnumber = okepn[isokalt - 1];
+		JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
+		maxpacketsize = okmps[isokalt - 1];
+
+		peasycap->video_isoc_maxframesize =
+				min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
+		if (0 >= peasycap->video_isoc_maxframesize) {
+			SAM("ERROR:  bad video_isoc_maxframesize\n");
+			SAM("        possibly because port is USB 1.1\n");
+			return -ENOENT;
+		}
+		JOM(4, "%i=video_isoc_maxframesize\n",
+					peasycap->video_isoc_maxframesize);
+
+		peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
+		JOM(4, "%i=video_isoc_framesperdesc\n",
+					peasycap->video_isoc_framesperdesc);
+		if (0 >= peasycap->video_isoc_framesperdesc) {
+			SAM("ERROR:  bad video_isoc_framesperdesc\n");
+			return -ENOENT;
+		}
+		peasycap->video_isoc_buffer_size =
+					peasycap->video_isoc_maxframesize *
+					peasycap->video_isoc_framesperdesc;
+		JOM(4, "%i=video_isoc_buffer_size\n",
+					peasycap->video_isoc_buffer_size);
+		if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
+					peasycap->video_isoc_buffer_size) {
+			SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
+			return -EFAULT;
+		}
 /*---------------------------------------------------------------------------*/
-	if (-1 == peasycap->video_interface) {
-		SAM("MISTAKE:  video_interface is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->video_altsetting_on) {
-		SAM("MISTAKE:  video_altsetting_on is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->video_altsetting_off) {
-		SAM("MISTAKE:  video_interface_off is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->video_endpointnumber) {
-		SAM("MISTAKE:  video_endpointnumber is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->video_isoc_maxframesize) {
-		SAM("MISTAKE:  video_isoc_maxframesize is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->video_isoc_buffer_size) {
-		SAM("MISTAKE:  video_isoc_buffer_size is unset\n");
-		return -EFAULT;
-	}
+		if (-1 == peasycap->video_interface) {
+			SAM("MISTAKE:  video_interface is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->video_altsetting_on) {
+			SAM("MISTAKE:  video_altsetting_on is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->video_altsetting_off) {
+			SAM("MISTAKE:  video_interface_off is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->video_endpointnumber) {
+			SAM("MISTAKE:  video_endpointnumber is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->video_isoc_maxframesize) {
+			SAM("MISTAKE:  video_isoc_maxframesize is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->video_isoc_buffer_size) {
+			SAM("MISTAKE:  video_isoc_buffer_size is unset\n");
+			return -EFAULT;
+		}
 /*---------------------------------------------------------------------------*/
 /*
  *  ALLOCATE MEMORY FOR VIDEO BUFFERS.  LISTS MUST BE INITIALIZED FIRST.
  */
 /*---------------------------------------------------------------------------*/
-	INIT_LIST_HEAD(&(peasycap->urb_video_head));
-	peasycap->purb_video_head = &(peasycap->urb_video_head);
-/*---------------------------------------------------------------------------*/
-	JOM(4, "allocating %i frame buffers of size %li\n",  \
-			FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
-	JOM(4, ".... each scattered over %li pages\n", \
-						FRAME_BUFFER_SIZE/PAGE_SIZE);
-
-	for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
-		for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
-			if ((void *)NULL != peasycap->frame_buffer[k][m].pgo)
-				SAM("attempting to reallocate frame " \
-								" buffers\n");
-			else {
-				pbuf = (void *)__get_free_page(GFP_KERNEL);
-				if ((void *)NULL == pbuf) {
-					SAM("ERROR: Could not allocate frame "\
-						"buffer %i page %i\n", k, m);
-					return -ENOMEM;
-				} else
-					peasycap->allocation_video_page += 1;
-				peasycap->frame_buffer[k][m].pgo = pbuf;
+		INIT_LIST_HEAD(&(peasycap->urb_video_head));
+		peasycap->purb_video_head = &(peasycap->urb_video_head);
+/*---------------------------------------------------------------------------*/
+		JOM(4, "allocating %i frame buffers of size %li\n",
+				FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
+		JOM(4, ".... each scattered over %li pages\n",
+							FRAME_BUFFER_SIZE/PAGE_SIZE);
+
+		for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
+			for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
+				if (peasycap->frame_buffer[k][m].pgo)
+					SAM("attempting to reallocate frame "
+									" buffers\n");
+				else {
+					pbuf = (void *)__get_free_page(GFP_KERNEL);
+					if (!pbuf) {
+						SAM("ERROR: Could not allocate frame "
+							"buffer %i page %i\n", k, m);
+						return -ENOMEM;
+					} else
+						peasycap->allocation_video_page += 1;
+					peasycap->frame_buffer[k][m].pgo = pbuf;
+				}
+				peasycap->frame_buffer[k][m].pto =
+						peasycap->frame_buffer[k][m].pgo;
 			}
-			peasycap->frame_buffer[k][m].pto = \
-					peasycap->frame_buffer[k][m].pgo;
 		}
-	}
-
-	peasycap->frame_fill = 0;
-	peasycap->frame_read = 0;
-	JOM(4, "allocation of frame buffers done:  %i pages\n", k * \
-								m);
-/*---------------------------------------------------------------------------*/
-	JOM(4, "allocating %i field buffers of size %li\n",  \
-			FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
-	JOM(4, ".... each scattered over %li pages\n", \
-					FIELD_BUFFER_SIZE/PAGE_SIZE);
 
-	for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
-		for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
-			if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
-				SAM("ERROR: attempting to reallocate " \
-							"field buffers\n");
-			} else {
-				pbuf = (void *) __get_free_page(GFP_KERNEL);
-				if ((void *)NULL == pbuf) {
-					SAM("ERROR: Could not allocate field" \
-						" buffer %i page %i\n", k, m);
-					return -ENOMEM;
+		peasycap->frame_fill = 0;
+		peasycap->frame_read = 0;
+		JOM(4, "allocation of frame buffers done:  %i pages\n", k *
+									m);
+/*---------------------------------------------------------------------------*/
+		JOM(4, "allocating %i field buffers of size %li\n",
+				FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
+		JOM(4, ".... each scattered over %li pages\n",
+						FIELD_BUFFER_SIZE/PAGE_SIZE);
+
+		for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
+			for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
+				if (peasycap->field_buffer[k][m].pgo) {
+					SAM("ERROR: attempting to reallocate "
+								"field buffers\n");
+				} else {
+					pbuf = (void *) __get_free_page(GFP_KERNEL);
+					if (!pbuf) {
+						SAM("ERROR: Could not allocate field"
+							" buffer %i page %i\n", k, m);
+						return -ENOMEM;
+						}
+					else
+						peasycap->allocation_video_page += 1;
+					peasycap->field_buffer[k][m].pgo = pbuf;
 					}
-				else
-					peasycap->allocation_video_page += 1;
-				peasycap->field_buffer[k][m].pgo = pbuf;
-				}
-			peasycap->field_buffer[k][m].pto = \
-					peasycap->field_buffer[k][m].pgo;
+				peasycap->field_buffer[k][m].pto =
+						peasycap->field_buffer[k][m].pgo;
+			}
+			peasycap->field_buffer[k][0].kount = 0x0200;
 		}
-		peasycap->field_buffer[k][0].kount = 0x0200;
-	}
-	peasycap->field_fill = 0;
-	peasycap->field_page = 0;
-	peasycap->field_read = 0;
-	JOM(4, "allocation of field buffers done:  %i pages\n", k * \
-								m);
-/*---------------------------------------------------------------------------*/
-	JOM(4, "allocating %i isoc video buffers of size %i\n",  \
-					VIDEO_ISOC_BUFFER_MANY, \
-					peasycap->video_isoc_buffer_size);
-	JOM(4, ".... each occupying contiguous memory pages\n");
-
-	for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
-		pbuf = (void *)__get_free_pages(GFP_KERNEL, VIDEO_ISOC_ORDER);
-		if (NULL == pbuf) {
-			SAM("ERROR: Could not allocate isoc video buffer " \
-								"%i\n", k);
-			return -ENOMEM;
-		} else
-			peasycap->allocation_video_page += \
-				((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
+		peasycap->field_fill = 0;
+		peasycap->field_page = 0;
+		peasycap->field_read = 0;
+		JOM(4, "allocation of field buffers done:  %i pages\n", k *
+									m);
+/*---------------------------------------------------------------------------*/
+		JOM(4, "allocating %i isoc video buffers of size %i\n",
+						VIDEO_ISOC_BUFFER_MANY,
+						peasycap->video_isoc_buffer_size);
+		JOM(4, ".... each occupying contiguous memory pages\n");
+
+		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
+			pbuf = (void *)__get_free_pages(GFP_KERNEL,
+							VIDEO_ISOC_ORDER);
+			if (!pbuf) {
+				SAM("ERROR: Could not allocate isoc video buffer "
+									"%i\n", k);
+				return -ENOMEM;
+			} else
+				peasycap->allocation_video_page +=
+					BIT(VIDEO_ISOC_ORDER);
 
-		peasycap->video_isoc_buffer[k].pgo = pbuf;
-		peasycap->video_isoc_buffer[k].pto = pbuf + \
-					peasycap->video_isoc_buffer_size;
-		peasycap->video_isoc_buffer[k].kount = k;
-	}
-	JOM(4, "allocation of isoc video buffers done: %i pages\n", \
-					k * (0x01 << VIDEO_ISOC_ORDER));
+			peasycap->video_isoc_buffer[k].pgo = pbuf;
+			peasycap->video_isoc_buffer[k].pto =
+				pbuf + peasycap->video_isoc_buffer_size;
+			peasycap->video_isoc_buffer[k].kount = k;
+		}
+		JOM(4, "allocation of isoc video buffers done: %i pages\n",
+						k * (0x01 << VIDEO_ISOC_ORDER));
 /*---------------------------------------------------------------------------*/
 /*
  *  ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
  */
 /*---------------------------------------------------------------------------*/
-	JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
-	JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n", \
-					peasycap->video_isoc_framesperdesc);
-	JOM(4, "using %i=peasycap->video_isoc_maxframesize\n", \
-					peasycap->video_isoc_maxframesize);
-	JOM(4, "using %i=peasycap->video_isoc_buffer_sizen", \
-					peasycap->video_isoc_buffer_size);
-
-	for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
-		purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc, \
-								GFP_KERNEL);
-		if (NULL == purb) {
-			SAM("ERROR: usb_alloc_urb returned NULL for buffer " \
-								"%i\n", k);
-			return -ENOMEM;
-		} else
-			peasycap->allocation_video_urb += 1;
+		JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
+		JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
+						peasycap->video_isoc_framesperdesc);
+		JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
+						peasycap->video_isoc_maxframesize);
+		JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
+						peasycap->video_isoc_buffer_size);
+
+		for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY; k++) {
+			purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
+									GFP_KERNEL);
+			if (!purb) {
+				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
+									"%i\n", k);
+				return -ENOMEM;
+			} else
+				peasycap->allocation_video_urb += 1;
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-		pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
-		if (NULL == pdata_urb) {
-			SAM("ERROR: Could not allocate struct data_urb.\n");
-			return -ENOMEM;
-		} else
-			peasycap->allocation_video_struct += \
-						sizeof(struct data_urb);
+			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
+			if (!pdata_urb) {
+				SAM("ERROR: Could not allocate struct data_urb.\n");
+				return -ENOMEM;
+			} else
+				peasycap->allocation_video_struct +=
+							sizeof(struct data_urb);
 
-		pdata_urb->purb = purb;
-		pdata_urb->isbuf = k;
-		pdata_urb->length = 0;
-		list_add_tail(&(pdata_urb->list_head), \
-						peasycap->purb_video_head);
+			pdata_urb->purb = purb;
+			pdata_urb->isbuf = k;
+			pdata_urb->length = 0;
+			list_add_tail(&(pdata_urb->list_head),
+							peasycap->purb_video_head);
 /*---------------------------------------------------------------------------*/
 /*
  *  ... AND INITIALIZE THEM
  */
 /*---------------------------------------------------------------------------*/
-		if (!k) {
-			JOM(4, "initializing video urbs thus:\n");
-			JOM(4, "  purb->interval = 1;\n");
-			JOM(4, "  purb->dev = peasycap->pusb_device;\n");
-			JOM(4, "  purb->pipe = usb_rcvisocpipe" \
-					"(peasycap->pusb_device,%i);\n", \
-					peasycap->video_endpointnumber);
-			JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
-			JOM(4, "  purb->transfer_buffer = peasycap->" \
-					"video_isoc_buffer[.].pgo;\n");
-			JOM(4, "  purb->transfer_buffer_length = %i;\n", \
-					peasycap->video_isoc_buffer_size);
-			JOM(4, "  purb->complete = easycap_complete;\n");
-			JOM(4, "  purb->context = peasycap;\n");
-			JOM(4, "  purb->start_frame = 0;\n");
-			JOM(4, "  purb->number_of_packets = %i;\n", \
-					peasycap->video_isoc_framesperdesc);
-			JOM(4, "  for (j = 0; j < %i; j++)\n", \
-					peasycap->video_isoc_framesperdesc);
-			JOM(4, "    {\n");
-			JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",\
-					peasycap->video_isoc_maxframesize);
-			JOM(4, "    purb->iso_frame_desc[j].length = %i;\n", \
-					peasycap->video_isoc_maxframesize);
-			JOM(4, "    }\n");
-		}
+			if (!k) {
+				JOM(4, "initializing video urbs thus:\n");
+				JOM(4, "  purb->interval = 1;\n");
+				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
+				JOM(4, "  purb->pipe = usb_rcvisocpipe"
+						"(peasycap->pusb_device,%i);\n",
+						peasycap->video_endpointnumber);
+				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
+				JOM(4, "  purb->transfer_buffer = peasycap->"
+						"video_isoc_buffer[.].pgo;\n");
+				JOM(4, "  purb->transfer_buffer_length = %i;\n",
+						peasycap->video_isoc_buffer_size);
+				JOM(4, "  purb->complete = easycap_complete;\n");
+				JOM(4, "  purb->context = peasycap;\n");
+				JOM(4, "  purb->start_frame = 0;\n");
+				JOM(4, "  purb->number_of_packets = %i;\n",
+						peasycap->video_isoc_framesperdesc);
+				JOM(4, "  for (j = 0; j < %i; j++)\n",
+						peasycap->video_isoc_framesperdesc);
+				JOM(4, "    {\n");
+				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
+						peasycap->video_isoc_maxframesize);
+				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
+						peasycap->video_isoc_maxframesize);
+				JOM(4, "    }\n");
+			}
 
-		purb->interval = 1;
-		purb->dev = peasycap->pusb_device;
-		purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \
-					peasycap->video_endpointnumber);
-		purb->transfer_flags = URB_ISO_ASAP;
-		purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
-		purb->transfer_buffer_length = \
-					peasycap->video_isoc_buffer_size;
-		purb->complete = easycap_complete;
-		purb->context = peasycap;
-		purb->start_frame = 0;
-		purb->number_of_packets = peasycap->video_isoc_framesperdesc;
-		for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
-			purb->iso_frame_desc[j].offset = j * \
-					peasycap->video_isoc_maxframesize;
-			purb->iso_frame_desc[j].length = \
-					peasycap->video_isoc_maxframesize;
+			purb->interval = 1;
+			purb->dev = peasycap->pusb_device;
+			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
+						peasycap->video_endpointnumber);
+			purb->transfer_flags = URB_ISO_ASAP;
+			purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
+			purb->transfer_buffer_length =
+						peasycap->video_isoc_buffer_size;
+			purb->complete = easycap_complete;
+			purb->context = peasycap;
+			purb->start_frame = 0;
+			purb->number_of_packets = peasycap->video_isoc_framesperdesc;
+			for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
+				purb->iso_frame_desc[j].offset = j *
+						peasycap->video_isoc_maxframesize;
+				purb->iso_frame_desc[j].length =
+						peasycap->video_isoc_maxframesize;
+			}
 		}
-	}
-	JOM(4, "allocation of %i struct urb done.\n", k);
+		JOM(4, "allocation of %i struct urb done.\n", k);
 /*--------------------------------------------------------------------------*/
 /*
  *  SAVE POINTER peasycap IN THIS INTERFACE.
  */
 /*--------------------------------------------------------------------------*/
-	usb_set_intfdata(pusb_interface, peasycap);
+		usb_set_intfdata(pusb_interface, peasycap);
 /*---------------------------------------------------------------------------*/
 /*
  *  IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
@@ -4343,448 +3853,435 @@ case 0: {
  *  BEWARE.
 */
 /*---------------------------------------------------------------------------*/
-#if defined(PREFER_NTSC)
-	peasycap->ntsc = true;
-	JOM(8, "defaulting initially to NTSC\n");
-#else
-	peasycap->ntsc = false;
-	JOM(8, "defaulting initially to PAL\n");
-#endif /*PREFER_NTSC*/
-	rc = reset(peasycap);
-	if (0 != rc) {
-		SAM("ERROR: reset() returned %i\n", rc);
-		return -EFAULT;
-	}
+		peasycap->ntsc = easycap_ntsc;
+		JOM(8, "defaulting initially to %s\n",
+			easycap_ntsc ? "NTSC" : "PAL");
+		rc = reset(peasycap);
+		if (rc) {
+			SAM("ERROR: reset() rc = %i\n", rc);
+			return -EFAULT;
+		}
 /*--------------------------------------------------------------------------*/
 /*
  *  THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
  */
 /*--------------------------------------------------------------------------*/
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-	if (0 != (usb_register_dev(pusb_interface, &easycap_class))) {
-		err("Not able to get a minor for this device");
-		usb_set_intfdata(pusb_interface, NULL);
-		return -ENODEV;
-	} else {
-		(peasycap->registered_video)++;
-		SAM("easycap attached to minor #%d\n", pusb_interface->minor);
-		break;
-	}
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#else
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-	if (0 != (v4l2_device_register(&(pusb_interface->dev), \
-						&(peasycap->v4l2_device)))) {
-		SAM("v4l2_device_register() failed\n");
-		return -ENODEV;
-	} else {
-		JOM(4, "registered device instance: %s\n", \
-					&(peasycap->v4l2_device.name[0]));
-	}
+		if (0 != (v4l2_device_register(&(pusb_interface->dev),
+							&(peasycap->v4l2_device)))) {
+			SAM("v4l2_device_register() failed\n");
+			return -ENODEV;
+		} else {
+			JOM(4, "registered device instance: %s\n",
+						&(peasycap->v4l2_device.name[0]));
+		}
 /*---------------------------------------------------------------------------*/
 /*
- *                                   FIXME
+ *                                 FIXME
  *
  *
  *  THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
 */
 /*---------------------------------------------------------------------------*/
-	peasycap->video_device.v4l2_dev = (struct v4l2_device *)NULL;
+		peasycap->video_device.v4l2_dev = NULL;
 /*---------------------------------------------------------------------------*/
 
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
 
-	strcpy(&peasycap->video_device.name[0], "easycapdc60");
-#if defined(EASYCAP_NEEDS_V4L2_FOPS)
-	peasycap->video_device.fops = &v4l2_fops;
-#else
-	peasycap->video_device.fops = &easycap_fops;
-#endif /*EASYCAP_NEEDS_V4L2_FOPS*/
-	peasycap->video_device.minor = -1;
-	peasycap->video_device.release = (void *)(&videodev_release);
+		strcpy(&peasycap->video_device.name[0], "easycapdc60");
+		peasycap->video_device.fops = &v4l2_fops;
+		peasycap->video_device.minor = -1;
+		peasycap->video_device.release = (void *)(&videodev_release);
 
-	video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
+		video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
+
+		if (0 != (video_register_device(&(peasycap->video_device),
+							VFL_TYPE_GRABBER, -1))) {
+			err("Not able to register with videodev");
+			videodev_release(&(peasycap->video_device));
+			return -ENODEV;
+		} else {
+			(peasycap->registered_video)++;
+			SAM("registered with videodev: %i=minor\n",
+							peasycap->video_device.minor);
+			peasycap->minor = peasycap->video_device.minor;
+		}
+/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
-	if (0 != (video_register_device(&(peasycap->video_device), \
-						VFL_TYPE_GRABBER, -1))) {
-		err("Not able to register with videodev");
-		videodev_release(&(peasycap->video_device));
-		return -ENODEV;
-	} else {
-		(peasycap->registered_video)++;
-		SAM("registered with videodev: %i=minor\n", \
-						peasycap->video_device.minor);
+		break;
 	}
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-	break;
-}
 /*--------------------------------------------------------------------------*/
 /*
  *  INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
  *  INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
  */
 /*--------------------------------------------------------------------------*/
-case 1: {
-	if (!peasycap) {
-		SAM("ERROR: peasycap is NULL\n");
-		return -EFAULT;
-	}
+	case 1: {
+		if (!peasycap) {
+			SAM("MISTAKE: peasycap is NULL\n");
+			return -EFAULT;
+		}
 /*--------------------------------------------------------------------------*/
 /*
  *  SAVE POINTER peasycap IN INTERFACE 1
  */
 /*--------------------------------------------------------------------------*/
-	usb_set_intfdata(pusb_interface, peasycap);
-	JOM(4, "no initialization required for interface %i\n", \
-				pusb_interface_descriptor->bInterfaceNumber);
-	break;
-}
-/*--------------------------------------------------------------------------*/
-case 2: {
-	if (!peasycap) {
-		SAM("MISTAKE: peasycap is NULL\n");
-		return -EFAULT;
-	}
-	if (!isokalt) {
-		SAM("ERROR:  no viable audio_altsetting_on\n");
-		return -ENOENT;
-	} else {
-		peasycap->audio_altsetting_on = okalt[isokalt - 1];
-		JOM(4, "%i=audio_altsetting_on <====\n", \
-						peasycap->audio_altsetting_on);
-	}
-
-	peasycap->audio_endpointnumber = okepn[isokalt - 1];
-	JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
-
-	peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
-	JOM(4, "%i=audio_isoc_maxframesize\n", \
-					peasycap->audio_isoc_maxframesize);
-	if (0 >= peasycap->audio_isoc_maxframesize) {
-		SAM("ERROR:  bad audio_isoc_maxframesize\n");
-		return -ENOENT;
-	}
-	if (9 == peasycap->audio_isoc_maxframesize) {
-		peasycap->ilk |= 0x02;
-		SAM("hardware is FOUR-CVBS\n");
-		peasycap->microphone = true;
-		peasycap->audio_pages_per_fragment = 4;
-	} else if (256 == peasycap->audio_isoc_maxframesize) {
-		peasycap->ilk &= ~0x02;
-		SAM("hardware is CVBS+S-VIDEO\n");
-		peasycap->microphone = false;
-		peasycap->audio_pages_per_fragment = 4;
-	} else {
-		SAM("hardware is unidentified:\n");
-		SAM("%i=audio_isoc_maxframesize\n", \
-					peasycap->audio_isoc_maxframesize);
-		return -ENOENT;
+		usb_set_intfdata(pusb_interface, peasycap);
+		JOM(4, "no initialization required for interface %i\n",
+					pusb_interface_descriptor->bInterfaceNumber);
+		break;
 	}
+/*--------------------------------------------------------------------------*/
+	case 2: {
+		if (!peasycap) {
+			SAM("MISTAKE: peasycap is NULL\n");
+			return -EFAULT;
+		}
+		if (!isokalt) {
+			SAM("ERROR:  no viable audio_altsetting_on\n");
+			return -ENOENT;
+		} else {
+			peasycap->audio_altsetting_on = okalt[isokalt - 1];
+			JOM(4, "%i=audio_altsetting_on <====\n",
+							peasycap->audio_altsetting_on);
+		}
 
-	peasycap->audio_bytes_per_fragment = \
-					peasycap->audio_pages_per_fragment * \
-								PAGE_SIZE ;
-	peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY * \
-					peasycap->audio_pages_per_fragment);
-
-	JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
-	JOM(4, "%6i=audio_pages_per_fragment\n", \
-					peasycap->audio_pages_per_fragment);
-	JOM(4, "%6i=audio_bytes_per_fragment\n", \
-					peasycap->audio_bytes_per_fragment);
-	JOM(4, "%6i=audio_buffer_page_many\n", \
-					peasycap->audio_buffer_page_many);
+		peasycap->audio_endpointnumber = okepn[isokalt - 1];
+		JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
 
-	peasycap->audio_isoc_framesperdesc = 128;
+		peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
+		JOM(4, "%i=audio_isoc_maxframesize\n",
+						peasycap->audio_isoc_maxframesize);
+		if (0 >= peasycap->audio_isoc_maxframesize) {
+			SAM("ERROR:  bad audio_isoc_maxframesize\n");
+			return -ENOENT;
+		}
+		if (9 == peasycap->audio_isoc_maxframesize) {
+			peasycap->ilk |= 0x02;
+			SAM("audio hardware is microphone\n");
+			peasycap->microphone = true;
+			peasycap->audio_pages_per_fragment =
+					PAGES_PER_AUDIO_FRAGMENT;
+		} else if (256 == peasycap->audio_isoc_maxframesize) {
+			peasycap->ilk &= ~0x02;
+			SAM("audio hardware is AC'97\n");
+			peasycap->microphone = false;
+			peasycap->audio_pages_per_fragment =
+					PAGES_PER_AUDIO_FRAGMENT;
+		} else {
+			SAM("hardware is unidentified:\n");
+			SAM("%i=audio_isoc_maxframesize\n",
+				peasycap->audio_isoc_maxframesize);
+			return -ENOENT;
+		}
 
-	JOM(4, "%i=audio_isoc_framesperdesc\n", \
-					peasycap->audio_isoc_framesperdesc);
-	if (0 >= peasycap->audio_isoc_framesperdesc) {
-		SAM("ERROR:  bad audio_isoc_framesperdesc\n");
-		return -ENOENT;
-	}
+		peasycap->audio_bytes_per_fragment =
+				peasycap->audio_pages_per_fragment * PAGE_SIZE;
+		peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
+				peasycap->audio_pages_per_fragment);
+
+		JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
+		JOM(4, "%6i=audio_pages_per_fragment\n",
+						peasycap->audio_pages_per_fragment);
+		JOM(4, "%6i=audio_bytes_per_fragment\n",
+						peasycap->audio_bytes_per_fragment);
+		JOM(4, "%6i=audio_buffer_page_many\n",
+						peasycap->audio_buffer_page_many);
+
+		peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
+
+		JOM(4, "%i=audio_isoc_framesperdesc\n",
+						peasycap->audio_isoc_framesperdesc);
+		if (0 >= peasycap->audio_isoc_framesperdesc) {
+			SAM("ERROR:  bad audio_isoc_framesperdesc\n");
+			return -ENOENT;
+		}
 
-	peasycap->audio_isoc_buffer_size = \
-				peasycap->audio_isoc_maxframesize * \
-				peasycap->audio_isoc_framesperdesc;
-	JOM(4, "%i=audio_isoc_buffer_size\n", \
-					peasycap->audio_isoc_buffer_size);
-	if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
-			SAM("MISTAKE:  audio_isoc_buffer_size bigger "
-			"than %li=AUDIO_ISOC_BUFFER_SIZE\n", \
-						AUDIO_ISOC_BUFFER_SIZE);
-		return -EFAULT;
-	}
-	if (-1 == peasycap->audio_interface) {
-		SAM("MISTAKE:  audio_interface is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->audio_altsetting_on) {
-		SAM("MISTAKE:  audio_altsetting_on is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->audio_altsetting_off) {
-		SAM("MISTAKE:  audio_interface_off is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->audio_endpointnumber) {
-		SAM("MISTAKE:  audio_endpointnumber is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->audio_isoc_maxframesize) {
-		SAM("MISTAKE:  audio_isoc_maxframesize is unset\n");
-		return -EFAULT;
-	}
-	if (-1 == peasycap->audio_isoc_buffer_size) {
-		SAM("MISTAKE:  audio_isoc_buffer_size is unset\n");
-		return -EFAULT;
-	}
+		peasycap->audio_isoc_buffer_size =
+					peasycap->audio_isoc_maxframesize *
+					peasycap->audio_isoc_framesperdesc;
+		JOM(4, "%i=audio_isoc_buffer_size\n",
+						peasycap->audio_isoc_buffer_size);
+		if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
+				SAM("MISTAKE:  audio_isoc_buffer_size bigger "
+				"than %li=AUDIO_ISOC_BUFFER_SIZE\n",
+							AUDIO_ISOC_BUFFER_SIZE);
+			return -EFAULT;
+		}
+		if (-1 == peasycap->audio_interface) {
+			SAM("MISTAKE:  audio_interface is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->audio_altsetting_on) {
+			SAM("MISTAKE:  audio_altsetting_on is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->audio_altsetting_off) {
+			SAM("MISTAKE:  audio_interface_off is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->audio_endpointnumber) {
+			SAM("MISTAKE:  audio_endpointnumber is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->audio_isoc_maxframesize) {
+			SAM("MISTAKE:  audio_isoc_maxframesize is unset\n");
+			return -EFAULT;
+		}
+		if (-1 == peasycap->audio_isoc_buffer_size) {
+			SAM("MISTAKE:  audio_isoc_buffer_size is unset\n");
+			return -EFAULT;
+		}
 /*---------------------------------------------------------------------------*/
 /*
  *  ALLOCATE MEMORY FOR AUDIO BUFFERS.  LISTS MUST BE INITIALIZED FIRST.
  */
 /*---------------------------------------------------------------------------*/
-	INIT_LIST_HEAD(&(peasycap->urb_audio_head));
-	peasycap->purb_audio_head = &(peasycap->urb_audio_head);
+		INIT_LIST_HEAD(&(peasycap->urb_audio_head));
+		peasycap->purb_audio_head = &(peasycap->urb_audio_head);
 
-	JOM(4, "allocating an audio buffer\n");
-	JOM(4, ".... scattered over %i pages\n", \
-					peasycap->audio_buffer_page_many);
+#ifdef CONFIG_EASYCAP_OSS
+		JOM(4, "allocating an audio buffer\n");
+		JOM(4, ".... scattered over %i pages\n",
+						peasycap->audio_buffer_page_many);
 
-	for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
-		if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
-			SAM("ERROR: attempting to reallocate audio buffers\n");
-		} else {
-			pbuf = (void *) __get_free_page(GFP_KERNEL);
-			if ((void *)NULL == pbuf) {
-				SAM("ERROR: Could not allocate audio " \
-							"buffer page %i\n", k);
-				return -ENOMEM;
-			} else
-				peasycap->allocation_audio_page += 1;
+		for (k = 0;  k < peasycap->audio_buffer_page_many;  k++) {
+			if (peasycap->audio_buffer[k].pgo) {
+				SAM("ERROR: attempting to reallocate audio buffers\n");
+			} else {
+				pbuf = (void *) __get_free_page(GFP_KERNEL);
+				if (!pbuf) {
+					SAM("ERROR: Could not allocate audio "
+								"buffer page %i\n", k);
+					return -ENOMEM;
+				} else
+					peasycap->allocation_audio_page += 1;
 
-			peasycap->audio_buffer[k].pgo = pbuf;
+				peasycap->audio_buffer[k].pgo = pbuf;
+			}
+			peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
 		}
-		peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
-	}
 
-	peasycap->audio_fill = 0;
-	peasycap->audio_read = 0;
-	JOM(4, "allocation of audio buffer done:  %i pages\n", k);
-/*---------------------------------------------------------------------------*/
-	JOM(4, "allocating %i isoc audio buffers of size %i\n",  \
-		AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
-	JOM(4, ".... each occupying contiguous memory pages\n");
-
-	for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
-		pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER);
-		if (NULL == pbuf) {
-			SAM("ERROR: Could not allocate isoc audio buffer " \
-							"%i\n", k);
-			return -ENOMEM;
-		} else
-			peasycap->allocation_audio_page += \
-				((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
+		peasycap->audio_fill = 0;
+		peasycap->audio_read = 0;
+		JOM(4, "allocation of audio buffer done:  %i pages\n", k);
+#endif /* CONFIG_EASYCAP_OSS */
+/*---------------------------------------------------------------------------*/
+		JOM(4, "allocating %i isoc audio buffers of size %i\n",
+			AUDIO_ISOC_BUFFER_MANY,
+			peasycap->audio_isoc_buffer_size);
+		JOM(4, ".... each occupying contiguous memory pages\n");
+
+		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
+			pbuf = (void *)__get_free_pages(GFP_KERNEL,
+							AUDIO_ISOC_ORDER);
+			if (!pbuf) {
+				SAM("ERROR: Could not allocate isoc audio buffer "
+								"%i\n", k);
+				return -ENOMEM;
+			} else
+				peasycap->allocation_audio_page +=
+						BIT(AUDIO_ISOC_ORDER);
 
-		peasycap->audio_isoc_buffer[k].pgo = pbuf;
-		peasycap->audio_isoc_buffer[k].pto = pbuf + \
-		peasycap->audio_isoc_buffer_size;
-		peasycap->audio_isoc_buffer[k].kount = k;
-	}
-	JOM(4, "allocation of isoc audio buffers done.\n");
+			peasycap->audio_isoc_buffer[k].pgo = pbuf;
+			peasycap->audio_isoc_buffer[k].pto = pbuf +
+			peasycap->audio_isoc_buffer_size;
+			peasycap->audio_isoc_buffer[k].kount = k;
+		}
+		JOM(4, "allocation of isoc audio buffers done.\n");
 /*---------------------------------------------------------------------------*/
 /*
  *  ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
  */
 /*---------------------------------------------------------------------------*/
-	JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
-	JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n", \
+		JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
+		JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
 					peasycap->audio_isoc_framesperdesc);
-	JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n", \
+		JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
 					peasycap->audio_isoc_maxframesize);
-	JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n", \
+		JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
 					peasycap->audio_isoc_buffer_size);
 
-	for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY; k++) {
-		purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc, \
+		for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY; k++) {
+			purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
 								GFP_KERNEL);
-		if (NULL == purb) {
-			SAM("ERROR: usb_alloc_urb returned NULL for buffer " \
-							"%i\n", k);
-			return -ENOMEM;
-		} else
+			if (!purb) {
+				SAM("ERROR: usb_alloc_urb returned NULL for buffer "
+								"%i\n", k);
+				return -ENOMEM;
+			}
 			peasycap->allocation_audio_urb += 1 ;
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-		pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
-		if (NULL == pdata_urb) {
-			SAM("ERROR: Could not allocate struct data_urb.\n");
-			return -ENOMEM;
-		} else
-			peasycap->allocation_audio_struct += \
+			pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
+			if (!pdata_urb) {
+				SAM("ERROR: Could not allocate struct data_urb.\n");
+				return -ENOMEM;
+			}
+			peasycap->allocation_audio_struct +=
 						sizeof(struct data_urb);
 
-		pdata_urb->purb = purb;
-		pdata_urb->isbuf = k;
-		pdata_urb->length = 0;
-		list_add_tail(&(pdata_urb->list_head), \
-						peasycap->purb_audio_head);
+			pdata_urb->purb = purb;
+			pdata_urb->isbuf = k;
+			pdata_urb->length = 0;
+			list_add_tail(&(pdata_urb->list_head),
+							peasycap->purb_audio_head);
 /*---------------------------------------------------------------------------*/
 /*
  *  ... AND INITIALIZE THEM
  */
 /*---------------------------------------------------------------------------*/
-		if (!k) {
-			JOM(4, "initializing audio urbs thus:\n");
-			JOM(4, "  purb->interval = 1;\n");
-			JOM(4, "  purb->dev = peasycap->pusb_device;\n");
-			JOM(4, "  purb->pipe = usb_rcvisocpipe(peasycap->" \
-					"pusb_device,%i);\n", \
-					peasycap->audio_endpointnumber);
-			JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
-			JOM(4, "  purb->transfer_buffer = " \
-				"peasycap->audio_isoc_buffer[.].pgo;\n");
-			JOM(4, "  purb->transfer_buffer_length = %i;\n", \
+			if (!k) {
+				JOM(4, "initializing audio urbs thus:\n");
+				JOM(4, "  purb->interval = 1;\n");
+				JOM(4, "  purb->dev = peasycap->pusb_device;\n");
+				JOM(4, "  purb->pipe = usb_rcvisocpipe(peasycap->"
+						"pusb_device,%i);\n",
+						peasycap->audio_endpointnumber);
+				JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
+				JOM(4, "  purb->transfer_buffer = "
+					"peasycap->audio_isoc_buffer[.].pgo;\n");
+				JOM(4, "  purb->transfer_buffer_length = %i;\n",
 					peasycap->audio_isoc_buffer_size);
-			JOM(4, "  purb->complete = easysnd_complete;\n");
-			JOM(4, "  purb->context = peasycap;\n");
-			JOM(4, "  purb->start_frame = 0;\n");
-			JOM(4, "  purb->number_of_packets = %i;\n", \
-					peasycap->audio_isoc_framesperdesc);
-			JOM(4, "  for (j = 0; j < %i; j++)\n", \
-					peasycap->audio_isoc_framesperdesc);
-			JOM(4, "    {\n");
-			JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",\
+#ifdef CONFIG_EASYCAP_OSS
+				JOM(4, "  purb->complete = easyoss_complete;\n");
+#else /* CONFIG_EASYCAP_OSS */
+				JOM(4, "  purb->complete = easycap_alsa_complete;\n");
+#endif /* CONFIG_EASYCAP_OSS */
+				JOM(4, "  purb->context = peasycap;\n");
+				JOM(4, "  purb->start_frame = 0;\n");
+				JOM(4, "  purb->number_of_packets = %i;\n",
+						peasycap->audio_isoc_framesperdesc);
+				JOM(4, "  for (j = 0; j < %i; j++)\n",
+						peasycap->audio_isoc_framesperdesc);
+				JOM(4, "    {\n");
+				JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
 					peasycap->audio_isoc_maxframesize);
-			JOM(4, "    purb->iso_frame_desc[j].length = %i;\n", \
+				JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
 					peasycap->audio_isoc_maxframesize);
-			JOM(4, "    }\n");
+				JOM(4, "    }\n");
 			}
 
-		purb->interval = 1;
-		purb->dev = peasycap->pusb_device;
-		purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \
-					peasycap->audio_endpointnumber);
-		purb->transfer_flags = URB_ISO_ASAP;
-		purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
-		purb->transfer_buffer_length = \
-					peasycap->audio_isoc_buffer_size;
-		purb->complete = easysnd_complete;
-		purb->context = peasycap;
-		purb->start_frame = 0;
-		purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
-		for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
-			purb->iso_frame_desc[j].offset = j * \
-					peasycap->audio_isoc_maxframesize;
-			purb->iso_frame_desc[j].length = \
-					peasycap->audio_isoc_maxframesize;
+			purb->interval = 1;
+			purb->dev = peasycap->pusb_device;
+			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
+						peasycap->audio_endpointnumber);
+			purb->transfer_flags = URB_ISO_ASAP;
+			purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
+			purb->transfer_buffer_length =
+						peasycap->audio_isoc_buffer_size;
+#ifdef CONFIG_EASYCAP_OSS
+			purb->complete = easyoss_complete;
+#else /* CONFIG_EASYCAP_OSS */
+			purb->complete = easycap_alsa_complete;
+#endif /* CONFIG_EASYCAP_OSS */
+			purb->context = peasycap;
+			purb->start_frame = 0;
+			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
+			for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
+				purb->iso_frame_desc[j].offset = j *
+						peasycap->audio_isoc_maxframesize;
+				purb->iso_frame_desc[j].length =
+						peasycap->audio_isoc_maxframesize;
+			}
 		}
-	}
-	JOM(4, "allocation of %i struct urb done.\n", k);
+		JOM(4, "allocation of %i struct urb done.\n", k);
 /*---------------------------------------------------------------------------*/
 /*
  *  SAVE POINTER peasycap IN THIS INTERFACE.
  */
 /*---------------------------------------------------------------------------*/
-	usb_set_intfdata(pusb_interface, peasycap);
+		usb_set_intfdata(pusb_interface, peasycap);
 /*---------------------------------------------------------------------------*/
 /*
  *  THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
  */
 /*---------------------------------------------------------------------------*/
-	rc = usb_register_dev(pusb_interface, &easysnd_class);
-	if (0 != rc) {
-		err("Not able to get a minor for this device.");
-		usb_set_intfdata(pusb_interface, NULL);
-		return -ENODEV;
-	} else {
-		JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",\
-					(int)peasycap->kref.refcount.counter);
-		kref_get(&peasycap->kref);
-		(peasycap->registered_audio)++;
+#ifndef CONFIG_EASYCAP_OSS
+		JOM(4, "initializing ALSA card\n");
+
+		rc = easycap_alsa_probe(peasycap);
+		if (rc) {
+			err("easycap_alsa_probe() rc = %i\n", rc);
+			return -ENODEV;
+		} else {
+			JOM(8, "kref_get() with %i=kref.refcount.counter\n",
+					peasycap->kref.refcount.counter);
+			kref_get(&peasycap->kref);
+			peasycap->registered_audio++;
+		}
+
+#else /* CONFIG_EASYCAP_OSS */
+		rc = usb_register_dev(pusb_interface, &easyoss_class);
+		if (rc) {
+			SAY("ERROR: usb_register_dev() failed\n");
+			usb_set_intfdata(pusb_interface, NULL);
+			return -ENODEV;
+		} else {
+			JOM(8, "kref_get() with %i=kref.refcount.counter\n",
+					peasycap->kref.refcount.counter);
+			kref_get(&peasycap->kref);
+			peasycap->registered_audio++;
+		}
+		SAM("easyoss attached to minor #%d\n", pusb_interface->minor);
+#endif /* CONFIG_EASYCAP_OSS */
+
+		break;
 	}
 /*---------------------------------------------------------------------------*/
 /*
- *  LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
- */
-/*---------------------------------------------------------------------------*/
-	SAM("easysnd attached to minor #%d\n", pusb_interface->minor);
-	break;
-}
-/*---------------------------------------------------------------------------*/
-/*
  *  INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
  */
 /*---------------------------------------------------------------------------*/
-default: {
-	JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
-	return -EINVAL;
-}
-}
-JOM(4, "ends successfully for interface %i\n", \
-				pusb_interface_descriptor->bInterfaceNumber);
-return 0;
+	default:
+		JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
+		return -EINVAL;
+	}
+	SAM("ends successfully for interface %i\n", bInterfaceNumber);
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
  *  WHEN THIS FUNCTION IS CALLED THE EasyCAP HAS ALREADY BEEN PHYSICALLY
  *  UNPLUGGED.  HENCE peasycap->pusb_device IS NO LONGER VALID.
+ *
+ *  THIS FUNCTION AFFECTS BOTH OSS AND ALSA.  BEWARE.
  */
 /*---------------------------------------------------------------------------*/
-void
-easycap_usb_disconnect(struct usb_interface *pusb_interface)
+static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
 {
-struct usb_host_interface *pusb_host_interface;
-struct usb_interface_descriptor *pusb_interface_descriptor;
-__u8 bInterfaceNumber;
-struct easycap *peasycap;
-
-struct list_head *plist_head;
-struct data_urb *pdata_urb;
-int minor, m, kd;
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-struct v4l2_device *pv4l2_device;
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
+	struct usb_host_interface *pusb_host_interface;
+	struct usb_interface_descriptor *pusb_interface_descriptor;
+	u8 bInterfaceNumber;
+	struct easycap *peasycap;
 
-JOT(4, "\n");
+	struct list_head *plist_head;
+	struct data_urb *pdata_urb;
+	int minor, m, kd;
+	struct v4l2_device *pv4l2_device;
 
-if ((struct usb_interface *)NULL == pusb_interface) {
-	JOT(4, "ERROR: pusb_interface is NULL\n");
-	return;
-}
-pusb_host_interface = pusb_interface->cur_altsetting;
-if ((struct usb_host_interface *)NULL == pusb_host_interface) {
-	JOT(4, "ERROR: pusb_host_interface is NULL\n");
-	return;
-}
-pusb_interface_descriptor = &(pusb_host_interface->desc);
-if ((struct usb_interface_descriptor *)NULL == pusb_interface_descriptor) {
-	JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
-	return;
-}
-bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
-minor = pusb_interface->minor;
-JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
+	JOT(4, "\n");
 
-if (1 == bInterfaceNumber)
-	return;
+	pusb_host_interface = pusb_interface->cur_altsetting;
+	if (!pusb_host_interface) {
+		JOT(4, "ERROR: pusb_host_interface is NULL\n");
+		return;
+	}
+	pusb_interface_descriptor = &(pusb_host_interface->desc);
+	if (!pusb_interface_descriptor) {
+		JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
+		return;
+	}
+	bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
+	minor = pusb_interface->minor;
+	JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
 
-peasycap = usb_get_intfdata(pusb_interface);
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return;
-}
-/*---------------------------------------------------------------------------*/
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-#
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#else
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
+	if (1 == bInterfaceNumber)
+		return;
+
+	peasycap = usb_get_intfdata(pusb_interface);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return;
+	}
 /*---------------------------------------------------------------------------*/
 /*
  *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
@@ -4793,80 +4290,72 @@ if (NULL == peasycap) {
  *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
 */
 /*---------------------------------------------------------------------------*/
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	pv4l2_device = usb_get_intfdata(pusb_interface);
-	if ((struct v4l2_device *)NULL == pv4l2_device) {
-		SAY("ERROR: pv4l2_device is NULL\n");
-		return;
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		pv4l2_device = usb_get_intfdata(pusb_interface);
+		if (!pv4l2_device) {
+			SAY("ERROR: pv4l2_device is NULL\n");
+			return;
+		}
+		peasycap = (struct easycap *)
+			container_of(pv4l2_device, struct easycap, v4l2_device);
 	}
-	peasycap = (struct easycap *) \
-		container_of(pv4l2_device, struct easycap, v4l2_device);
-}
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 /*---------------------------------------------------------------------------*/
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return;
-}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return;
+	}
 /*---------------------------------------------------------------------------*/
 /*
  *  IF THE WAIT QUEUES ARE NOT CLEARED A DEADLOCK IS POSSIBLE.  BEWARE.
 */
 /*---------------------------------------------------------------------------*/
-peasycap->video_eof = 1;
-peasycap->audio_eof = 1;
-wake_up_interruptible(&(peasycap->wq_video));
-wake_up_interruptible(&(peasycap->wq_audio));
-/*---------------------------------------------------------------------------*/
-switch (bInterfaceNumber) {
-case 0: {
-	if ((struct list_head *)NULL != peasycap->purb_video_head) {
-		JOM(4, "killing video urbs\n");
-		m = 0;
-		list_for_each(plist_head, (peasycap->purb_video_head))
-			{
-			pdata_urb = list_entry(plist_head, \
-					struct data_urb, list_head);
-			if ((struct data_urb *)NULL != pdata_urb) {
-				if ((struct urb *)NULL != \
-						pdata_urb->purb) {
-					usb_kill_urb(pdata_urb->purb);
-					m++;
+	peasycap->video_eof = 1;
+	peasycap->audio_eof = 1;
+	wake_up_interruptible(&(peasycap->wq_video));
+	wake_up_interruptible(&(peasycap->wq_audio));
+/*---------------------------------------------------------------------------*/
+	switch (bInterfaceNumber) {
+	case 0: {
+		if (peasycap->purb_video_head) {
+			JOM(4, "killing video urbs\n");
+			m = 0;
+			list_for_each(plist_head, peasycap->purb_video_head) {
+				pdata_urb = list_entry(plist_head,
+						struct data_urb, list_head);
+				if (pdata_urb) {
+					if (pdata_urb->purb) {
+						usb_kill_urb(pdata_urb->purb);
+						m++;
+					}
 				}
 			}
+			JOM(4, "%i video urbs killed\n", m);
 		}
-		JOM(4, "%i video urbs killed\n", m);
+		break;
 	}
-	break;
-}
 /*---------------------------------------------------------------------------*/
-case 2: {
-	if ((struct list_head *)NULL != peasycap->purb_audio_head) {
-		JOM(4, "killing audio urbs\n");
-		m = 0;
-		list_for_each(plist_head, \
-					(peasycap->purb_audio_head)) {
-			pdata_urb = list_entry(plist_head, \
-					struct data_urb, list_head);
-			if ((struct data_urb *)NULL != pdata_urb) {
-				if ((struct urb *)NULL != \
-						pdata_urb->purb) {
-					usb_kill_urb(pdata_urb->purb);
-					m++;
+	case 2: {
+		if (peasycap->purb_audio_head) {
+			JOM(4, "killing audio urbs\n");
+			m = 0;
+			list_for_each(plist_head, peasycap->purb_audio_head) {
+				pdata_urb = list_entry(plist_head,
+						struct data_urb, list_head);
+				if (pdata_urb) {
+					if (pdata_urb->purb) {
+						usb_kill_urb(pdata_urb->purb);
+						m++;
+					}
 				}
 			}
+			JOM(4, "%i audio urbs killed\n", m);
 		}
-		JOM(4, "%i audio urbs killed\n", m);
+		break;
+	}
+	default:
+		break;
 	}
-	break;
-}
-/*---------------------------------------------------------------------------*/
-default:
-	break;
-}
 /*--------------------------------------------------------------------------*/
 /*
  *  DEREGISTER
@@ -4876,183 +4365,174 @@ default:
  *  AN EasyCAP IS UNPLUGGED WHILE THE URBS ARE RUNNING.  BEWARE.
  */
 /*--------------------------------------------------------------------------*/
-kd = isdongle(peasycap);
-switch (bInterfaceNumber) {
-case 0: {
-	if (0 <= kd && DONGLE_MANY > kd) {
-		wake_up_interruptible(&peasycap->wq_video);
-		JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd);
-		if (mutex_lock_interruptible(&easycap_dongle[kd].\
+	kd = isdongle(peasycap);
+	switch (bInterfaceNumber) {
+	case 0: {
+		if (0 <= kd && DONGLE_MANY > kd) {
+			wake_up_interruptible(&peasycap->wq_video);
+			JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
+			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
 								mutex_video)) {
-			SAY("ERROR: cannot lock easycap_dongle[%i]." \
-							"mutex_video\n", kd);
-			return;
+				SAY("ERROR: "
+				    "cannot lock dongle[%i].mutex_video\n", kd);
+				return;
+			}
+			JOM(4, "locked dongle[%i].mutex_video\n", kd);
+		} else {
+			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
 		}
-		JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
-	} else
-		SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
 /*---------------------------------------------------------------------------*/
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-	if ((struct easycap *)NULL == peasycap) {
-		SAM("ERROR: peasycap has become NULL\n");
-	} else {
-		usb_deregister_dev(pusb_interface, &easycap_class);
-		(peasycap->registered_video)--;
-		JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
-		SAM("easycap detached from minor #%d\n", minor);
-	}
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#else
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-	if (!peasycap->v4l2_device.name[0]) {
-		SAM("ERROR: peasycap->v4l2_device.name is empty\n");
-		if (0 <= kd && DONGLE_MANY > kd)
-			mutex_unlock(&easycap_dongle[kd].mutex_video);
-		return;
-	}
-	v4l2_device_disconnect(&peasycap->v4l2_device);
-	JOM(4, "v4l2_device_disconnect() OK\n");
-	v4l2_device_unregister(&peasycap->v4l2_device);
-	JOM(4, "v4l2_device_unregister() OK\n");
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-
-	video_unregister_device(&peasycap->video_device);
-	JOM(4, "intf[%i]: video_unregister_device() OK\n", bInterfaceNumber);
-	(peasycap->registered_video)--;
-	JOM(4, "unregistered with videodev: %i=minor\n", minor);
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
+		if (!peasycap->v4l2_device.name[0]) {
+			SAM("ERROR: peasycap->v4l2_device.name is empty\n");
+			if (0 <= kd && DONGLE_MANY > kd)
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			return;
+		}
+		v4l2_device_disconnect(&peasycap->v4l2_device);
+		JOM(4, "v4l2_device_disconnect() OK\n");
+		v4l2_device_unregister(&peasycap->v4l2_device);
+		JOM(4, "v4l2_device_unregister() OK\n");
+
+		video_unregister_device(&peasycap->video_device);
+		JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
+				bInterfaceNumber, minor);
+		peasycap->registered_video--;
 /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
-	if (0 <= kd && DONGLE_MANY > kd) {
-		mutex_unlock(&easycap_dongle[kd].mutex_video);
-		JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+		if (0 <= kd && DONGLE_MANY > kd) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
+		}
+		break;
 	}
-	break;
-}
-case 2: {
-	if (0 <= kd && DONGLE_MANY > kd) {
-		wake_up_interruptible(&peasycap->wq_audio);
-		JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd);
-		if (mutex_lock_interruptible(&easycap_dongle[kd].\
+	case 2: {
+		if (0 <= kd && DONGLE_MANY > kd) {
+			wake_up_interruptible(&peasycap->wq_audio);
+			JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
+			if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
 								mutex_audio)) {
-			SAY("ERROR: cannot lock easycap_dongle[%i]." \
-							"mutex_audio\n", kd);
-			return;
+				SAY("ERROR: "
+				    "cannot lock dongle[%i].mutex_audio\n", kd);
+				return;
+			}
+			JOM(4, "locked dongle[%i].mutex_audio\n", kd);
+		} else
+			SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
+#ifndef CONFIG_EASYCAP_OSS
+		if (0 != snd_card_free(peasycap->psnd_card)) {
+			SAY("ERROR: snd_card_free() failed\n");
+		} else {
+			peasycap->psnd_card = NULL;
+			(peasycap->registered_audio)--;
 		}
-		JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
-	} else
-		SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
-
-	usb_deregister_dev(pusb_interface, &easysnd_class);
-	(peasycap->registered_audio)--;
-
-	JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
-	SAM("easysnd detached from minor #%d\n", minor);
-
-	if (0 <= kd && DONGLE_MANY > kd) {
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		JOM(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd);
+#else /* CONFIG_EASYCAP_OSS */
+		usb_deregister_dev(pusb_interface, &easyoss_class);
+		peasycap->registered_audio--;
+		JOM(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber);
+		SAM("easyoss detached from minor #%d\n", minor);
+#endif /* CONFIG_EASYCAP_OSS */
+		if (0 <= kd && DONGLE_MANY > kd) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
+		}
+		break;
+	}
+	default:
+		break;
 	}
-	break;
-}
-default:
-	break;
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap
+ *  (ALSO WHEN ALSA HAS BEEN IN USE)
  */
 /*---------------------------------------------------------------------------*/
-if (!peasycap->kref.refcount.counter) {
-	SAM("ERROR: peasycap->kref.refcount.counter is zero "
-						"so cannot call kref_put()\n");
-	SAM("ending unsuccessfully: may cause memory leak\n");
-	return;
-}
-if (0 <= kd && DONGLE_MANY > kd) {
-	JOM(4, "about to lock easycap_dongle[%i].mutex_video\n", kd);
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
-		SAY("ERROR: cannot down easycap_dongle[%i].mutex_video\n", kd);
-		SAM("ending unsuccessfully: may cause memory leak\n");
-	return;
-	}
-	JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
-	JOM(4, "about to lock easycap_dongle[%i].mutex_audio\n", kd);
-	if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
-		SAY("ERROR: cannot down easycap_dongle[%i].mutex_audio\n", kd);
-		mutex_unlock(&(easycap_dongle[kd].mutex_video));
-		JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
+	if (!peasycap->kref.refcount.counter) {
+		SAM("ERROR: peasycap->kref.refcount.counter is zero "
+							"so cannot call kref_put()\n");
 		SAM("ending unsuccessfully: may cause memory leak\n");
 		return;
 	}
-	JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
-}
-JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n", \
-		bInterfaceNumber, (int)peasycap->kref.refcount.counter);
-kref_put(&peasycap->kref, easycap_delete);
-JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
-if (0 <= kd && DONGLE_MANY > kd) {
-	mutex_unlock(&(easycap_dongle[kd].mutex_audio));
-	JOT(4, "unlocked easycap_dongle[%i].mutex_audio\n", kd);
-	mutex_unlock(&easycap_dongle[kd].mutex_video);
-	JOT(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
-}
+	if (0 <= kd && DONGLE_MANY > kd) {
+		JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
+		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
+			SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
+			SAM("ending unsuccessfully: may cause memory leak\n");
+			return;
+		}
+		JOM(4, "locked dongle[%i].mutex_video\n", kd);
+		JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
+		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
+			SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
+			mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
+			JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
+			SAM("ending unsuccessfully: may cause memory leak\n");
+			return;
+		}
+		JOM(4, "locked dongle[%i].mutex_audio\n", kd);
+	}
+	JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
+			bInterfaceNumber, (int)peasycap->kref.refcount.counter);
+	kref_put(&peasycap->kref, easycap_delete);
+	JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
+	if (0 <= kd && DONGLE_MANY > kd) {
+		mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
+		JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
+		JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
+	}
 /*---------------------------------------------------------------------------*/
-JOM(4, "ends\n");
-return;
+	JOM(4, "ends\n");
+	return;
 }
 /*****************************************************************************/
-int __init
-easycap_module_init(void)
-{
-int result;
 
-SAY("========easycap=======\n");
-JOT(4, "begins.  %i=debug %i=bars %i=gain\n", easycap_debug, easycap_bars, \
-						easycap_gain);
-SAY("version: " EASYCAP_DRIVER_VERSION "\n");
 /*---------------------------------------------------------------------------*/
 /*
- *  REGISTER THIS DRIVER WITH THE USB SUBSYTEM.
+ *  PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO
  */
 /*---------------------------------------------------------------------------*/
-JOT(4, "registering driver easycap\n");
+static struct usb_device_id easycap_usb_device_id_table[] = {
+	{USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
+	{ }
+};
 
-result = usb_register(&easycap_usb_driver);
-if (0 != result)
-	SAY("ERROR:  usb_register returned %i\n", result);
+MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
+struct usb_driver easycap_usb_driver = {
+	.name = "easycap",
+	.id_table = easycap_usb_device_id_table,
+	.probe = easycap_usb_probe,
+	.disconnect = easycap_usb_disconnect,
+};
 
-JOT(4, "ends\n");
-return result;
-}
-/*****************************************************************************/
-void __exit
-easycap_module_exit(void)
+static int __init easycap_module_init(void)
 {
-JOT(4, "begins\n");
+	int k, rc;
 
-/*---------------------------------------------------------------------------*/
-/*
- *  DEREGISTER THIS DRIVER WITH THE USB SUBSYTEM.
- */
-/*---------------------------------------------------------------------------*/
-usb_deregister(&easycap_usb_driver);
+	printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
+
+	JOT(4, "begins.  %i=debug %i=bars %i=gain\n",
+		easycap_debug, easycap_bars, easycap_gain);
+
+	mutex_init(&mutex_dongle);
+	for (k = 0; k < DONGLE_MANY; k++) {
+		easycapdc60_dongle[k].peasycap = NULL;
+		mutex_init(&easycapdc60_dongle[k].mutex_video);
+		mutex_init(&easycapdc60_dongle[k].mutex_audio);
+	}
+	rc = usb_register(&easycap_usb_driver);
+	if (rc)
+		printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
 
-JOT(4, "ends\n");
+	return rc;
+}
+/*****************************************************************************/
+static void __exit easycap_module_exit(void)
+{
+	usb_deregister(&easycap_usb_driver);
 }
 /*****************************************************************************/
 
 module_init(easycap_module_init);
 module_exit(easycap_module_exit);
 
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
-MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
-MODULE_VERSION(EASYCAP_DRIVER_VERSION);
-#if defined(EASYCAP_DEBUG)
-MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
-#endif /*EASYCAP_DEBUG*/
-MODULE_PARM_DESC(bars, \
-	"Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
-MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
 /*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_settings.c b/drivers/staging/easycap/easycap_settings.c
index df3f17d..898559d 100644
--- a/drivers/staging/easycap/easycap_settings.c
+++ b/drivers/staging/easycap/easycap_settings.c
@@ -26,7 +26,6 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
 
 /*---------------------------------------------------------------------------*/
 /*
@@ -40,252 +39,255 @@
  */
 /*---------------------------------------------------------------------------*/
 const struct easycap_standard easycap_standard[] = {
-{
-.mask = 0x00FF & PAL_BGHIN ,
-.v4l2_standard = {
-	.index = PAL_BGHIN,
-	.id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
-					V4L2_STD_PAL_I | V4L2_STD_PAL_N),
-	.name = "PAL_BGHIN",
-	.frameperiod = {1, 25},
-	.framelines = 625,
-	.reserved = {0, 0, 0, 0}
-	}
-},
+	{
+		.mask = 0x00FF & PAL_BGHIN ,
+		.v4l2_standard = {
+			.index = PAL_BGHIN,
+			.id = (V4L2_STD_PAL_B |
+				V4L2_STD_PAL_G | V4L2_STD_PAL_H |
+				V4L2_STD_PAL_I | V4L2_STD_PAL_N),
+			.name = "PAL_BGHIN",
+			.frameperiod = {1, 25},
+			.framelines = 625,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & NTSC_N_443 ,
-.v4l2_standard = {
-	.index = NTSC_N_443,
-	.id = V4L2_STD_UNKNOWN,
-	.name = "NTSC_N_443",
-	.frameperiod = {1, 25},
-	.framelines = 480,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & NTSC_N_443 ,
+		.v4l2_standard = {
+			.index = NTSC_N_443,
+			.id = V4L2_STD_UNKNOWN,
+			.name = "NTSC_N_443",
+			.frameperiod = {1, 25},
+			.framelines = 480,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & PAL_Nc ,
-.v4l2_standard = {
-	.index = PAL_Nc,
-	.id = V4L2_STD_PAL_Nc,
-	.name = "PAL_Nc",
-	.frameperiod = {1, 25},
-	.framelines = 625,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & PAL_Nc ,
+		.v4l2_standard = {
+			.index = PAL_Nc,
+			.id = V4L2_STD_PAL_Nc,
+			.name = "PAL_Nc",
+			.frameperiod = {1, 25},
+			.framelines = 625,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & NTSC_N ,
-.v4l2_standard = {
-	.index = NTSC_N,
-	.id = V4L2_STD_UNKNOWN,
-	.name = "NTSC_N",
-	.frameperiod = {1, 25},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & NTSC_N ,
+		.v4l2_standard = {
+			.index = NTSC_N,
+			.id = V4L2_STD_UNKNOWN,
+			.name = "NTSC_N",
+			.frameperiod = {1, 25},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & SECAM ,
-.v4l2_standard = {
-	.index = SECAM,
-	.id = V4L2_STD_SECAM,
-	.name = "SECAM",
-	.frameperiod = {1, 25},
-	.framelines = 625,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & SECAM ,
+		.v4l2_standard = {
+			.index = SECAM,
+			.id = V4L2_STD_SECAM,
+			.name = "SECAM",
+			.frameperiod = {1, 25},
+			.framelines = 625,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & NTSC_M ,
-.v4l2_standard = {
-	.index = NTSC_M,
-	.id = V4L2_STD_NTSC_M,
-	.name = "NTSC_M",
-	.frameperiod = {1, 30},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & NTSC_M ,
+		.v4l2_standard = {
+			.index = NTSC_M,
+			.id = V4L2_STD_NTSC_M,
+			.name = "NTSC_M",
+			.frameperiod = {1, 30},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & NTSC_M_JP ,
-.v4l2_standard = {
-	.index = NTSC_M_JP,
-	.id = V4L2_STD_NTSC_M_JP,
-	.name = "NTSC_M_JP",
-	.frameperiod = {1, 30},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & NTSC_M_JP ,
+		.v4l2_standard = {
+			.index = NTSC_M_JP,
+			.id = V4L2_STD_NTSC_M_JP,
+			.name = "NTSC_M_JP",
+			.frameperiod = {1, 30},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & PAL_60 ,
-.v4l2_standard = {
-	.index = PAL_60,
-	.id = V4L2_STD_PAL_60,
-	.name = "PAL_60",
-	.frameperiod = {1, 30},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & PAL_60 ,
+		.v4l2_standard = {
+			.index = PAL_60,
+			.id = V4L2_STD_PAL_60,
+			.name = "PAL_60",
+			.frameperiod = {1, 30},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & NTSC_443 ,
-.v4l2_standard = {
-	.index = NTSC_443,
-	.id = V4L2_STD_NTSC_443,
-	.name = "NTSC_443",
-	.frameperiod = {1, 30},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & NTSC_443 ,
+		.v4l2_standard = {
+			.index = NTSC_443,
+			.id = V4L2_STD_NTSC_443,
+			.name = "NTSC_443",
+			.frameperiod = {1, 30},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x00FF & PAL_M ,
-.v4l2_standard = {
-	.index = PAL_M,
-	.id = V4L2_STD_PAL_M,
-	.name = "PAL_M",
-	.frameperiod = {1, 30},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x00FF & PAL_M ,
+		.v4l2_standard = {
+			.index = PAL_M,
+			.id = V4L2_STD_PAL_M,
+			.name = "PAL_M",
+			.frameperiod = {1, 30},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & PAL_BGHIN_SLOW),
-.v4l2_standard = {
-	.index = PAL_BGHIN_SLOW,
-	.id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
-				V4L2_STD_PAL_I | V4L2_STD_PAL_N | \
-					(((v4l2_std_id)0x01) << 32)),
-	.name = "PAL_BGHIN_SLOW",
-	.frameperiod = {1, 5},
-	.framelines = 625,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & PAL_BGHIN_SLOW),
+		.v4l2_standard = {
+			.index = PAL_BGHIN_SLOW,
+			.id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G |
+				V4L2_STD_PAL_H |
+				V4L2_STD_PAL_I | V4L2_STD_PAL_N |
+				(((v4l2_std_id)0x01) << 32)),
+			.name = "PAL_BGHIN_SLOW",
+			.frameperiod = {1, 5},
+			.framelines = 625,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & NTSC_N_443_SLOW),
-.v4l2_standard = {
-	.index = NTSC_N_443_SLOW,
-	.id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x11) << 32)),
-	.name = "NTSC_N_443_SLOW",
-	.frameperiod = {1, 5},
-	.framelines = 480,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & NTSC_N_443_SLOW),
+		.v4l2_standard = {
+			.index = NTSC_N_443_SLOW,
+			.id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x11) << 32)),
+			.name = "NTSC_N_443_SLOW",
+			.frameperiod = {1, 5},
+			.framelines = 480,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & PAL_Nc_SLOW),
-.v4l2_standard = {
-	.index = PAL_Nc_SLOW,
-	.id = (V4L2_STD_PAL_Nc | (((v4l2_std_id)0x01) << 32)),
-	.name = "PAL_Nc_SLOW",
-	.frameperiod = {1, 5},
-	.framelines = 625,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & PAL_Nc_SLOW),
+		.v4l2_standard = {
+			.index = PAL_Nc_SLOW,
+			.id = (V4L2_STD_PAL_Nc | (((v4l2_std_id)0x01) << 32)),
+			.name = "PAL_Nc_SLOW",
+			.frameperiod = {1, 5},
+			.framelines = 625,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & NTSC_N_SLOW),
-.v4l2_standard = {
-	.index = NTSC_N_SLOW,
-	.id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x21) << 32)),
-	.name = "NTSC_N_SLOW",
-	.frameperiod = {1, 5},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & NTSC_N_SLOW),
+		.v4l2_standard = {
+			.index = NTSC_N_SLOW,
+			.id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x21) << 32)),
+			.name = "NTSC_N_SLOW",
+			.frameperiod = {1, 5},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & SECAM_SLOW),
-.v4l2_standard = {
-	.index = SECAM_SLOW,
-	.id = (V4L2_STD_SECAM | (((v4l2_std_id)0x01) << 32)),
-	.name = "SECAM_SLOW",
-	.frameperiod = {1, 5},
-	.framelines = 625,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & SECAM_SLOW),
+		.v4l2_standard = {
+			.index = SECAM_SLOW,
+			.id = (V4L2_STD_SECAM | (((v4l2_std_id)0x01) << 32)),
+			.name = "SECAM_SLOW",
+			.frameperiod = {1, 5},
+			.framelines = 625,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & NTSC_M_SLOW),
-.v4l2_standard = {
-	.index = NTSC_M_SLOW,
-	.id = (V4L2_STD_NTSC_M | (((v4l2_std_id)0x01) << 32)),
-	.name = "NTSC_M_SLOW",
-	.frameperiod = {1, 6},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & NTSC_M_SLOW),
+		.v4l2_standard = {
+			.index = NTSC_M_SLOW,
+			.id = (V4L2_STD_NTSC_M | (((v4l2_std_id)0x01) << 32)),
+			.name = "NTSC_M_SLOW",
+			.frameperiod = {1, 6},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & NTSC_M_JP_SLOW),
-.v4l2_standard = {
-	.index = NTSC_M_JP_SLOW,
-	.id = (V4L2_STD_NTSC_M_JP | (((v4l2_std_id)0x01) << 32)),
-	.name = "NTSC_M_JP_SLOW",
-	.frameperiod = {1, 6},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & NTSC_M_JP_SLOW),
+		.v4l2_standard = {
+			.index = NTSC_M_JP_SLOW,
+			.id = (V4L2_STD_NTSC_M_JP |
+				(((v4l2_std_id)0x01) << 32)),
+			.name = "NTSC_M_JP_SLOW",
+			.frameperiod = {1, 6},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & PAL_60_SLOW),
-.v4l2_standard = {
-	.index = PAL_60_SLOW,
-	.id = (V4L2_STD_PAL_60 | (((v4l2_std_id)0x01) << 32)),
-	.name = "PAL_60_SLOW",
-	.frameperiod = {1, 6},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & PAL_60_SLOW),
+		.v4l2_standard = {
+			.index = PAL_60_SLOW,
+			.id = (V4L2_STD_PAL_60 | (((v4l2_std_id)0x01) << 32)),
+			.name = "PAL_60_SLOW",
+			.frameperiod = {1, 6},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & NTSC_443_SLOW),
-.v4l2_standard = {
-	.index = NTSC_443_SLOW,
-	.id = (V4L2_STD_NTSC_443 | (((v4l2_std_id)0x01) << 32)),
-	.name = "NTSC_443_SLOW",
-	.frameperiod = {1, 6},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & NTSC_443_SLOW),
+		.v4l2_standard = {
+			.index = NTSC_443_SLOW,
+			.id = (V4L2_STD_NTSC_443 | (((v4l2_std_id)0x01) << 32)),
+			.name = "NTSC_443_SLOW",
+			.frameperiod = {1, 6},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0x8000 | (0x00FF & PAL_M_SLOW),
-.v4l2_standard = {
-	.index = PAL_M_SLOW,
-	.id = (V4L2_STD_PAL_M | (((v4l2_std_id)0x01) << 32)),
-	.name = "PAL_M_SLOW",
-	.frameperiod = {1, 6},
-	.framelines = 525,
-	.reserved = {0, 0, 0, 0}
-}
-},
+	{
+		.mask = 0x8000 | (0x00FF & PAL_M_SLOW),
+		.v4l2_standard = {
+			.index = PAL_M_SLOW,
+			.id = (V4L2_STD_PAL_M | (((v4l2_std_id)0x01) << 32)),
+			.name = "PAL_M_SLOW",
+			.frameperiod = {1, 6},
+			.framelines = 525,
+			.reserved = {0, 0, 0, 0}
+		}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.mask = 0xFFFF
-}
+	{
+		.mask = 0xFFFF
+	}
 };
 /*---------------------------------------------------------------------------*/
 /*
@@ -311,371 +313,384 @@ const struct easycap_standard easycap_standard[] = {
 
 struct easycap_format easycap_format[1 + SETTINGS_MANY];
 
-int
-fillin_formats(void)
+int fillin_formats(void)
 {
-int i, j, k, m, n;
-__u32 width, height, pixelformat, bytesperline, sizeimage;
-__u32 field, colorspace;
-__u16 mask1, mask2, mask3, mask4;
-char name1[32], name2[32], name3[32], name4[32];
+	const char *name1, *name2, *name3, *name4;
+	struct v4l2_format *fmt;
+	int i, j, k, m, n;
+	u32 width, height, pixelformat, bytesperline, sizeimage;
+	u16 mask1, mask2, mask3, mask4;
+	enum v4l2_field field;
+	enum v4l2_colorspace colorspace;
 
-for (i = 0, n = 0; i < STANDARD_MANY; i++) {
-	mask1 = 0x0000;
-	switch (i) {
-	case PAL_BGHIN: {
-		mask1 = 0x1F & PAL_BGHIN;
-		strcpy(&name1[0], "PAL_BGHIN");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case SECAM: {
-		mask1 = 0x1F & SECAM;
-		strcpy(&name1[0], "SECAM");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case PAL_Nc: {
-		mask1 = 0x1F & PAL_Nc;
-		strcpy(&name1[0], "PAL_Nc");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case PAL_60: {
-		mask1 = 0x1F & PAL_60;
-		strcpy(&name1[0], "PAL_60");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case PAL_M: {
-		mask1 = 0x1F & PAL_M;
-		strcpy(&name1[0], "PAL_M");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case NTSC_M: {
-		mask1 = 0x1F & NTSC_M;
-		strcpy(&name1[0], "NTSC_M");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_443: {
-		mask1 = 0x1F & NTSC_443;
-		strcpy(&name1[0], "NTSC_443");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_M_JP: {
-		mask1 = 0x1F & NTSC_M_JP;
-		strcpy(&name1[0], "NTSC_M_JP");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_N: {
-		mask1 = 0x1F & NTSC_M;
-		strcpy(&name1[0], "NTSC_N");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_N_443: {
-		mask1 = 0x1F & NTSC_N_443;
-		strcpy(&name1[0], "NTSC_N_443");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case PAL_BGHIN_SLOW: {
-		mask1 = 0x001F & PAL_BGHIN_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "PAL_BGHIN_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case SECAM_SLOW: {
-		mask1 = 0x001F & SECAM_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "SECAM_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case PAL_Nc_SLOW: {
-		mask1 = 0x001F & PAL_Nc_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "PAL_Nc_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case PAL_60_SLOW: {
-		mask1 = 0x001F & PAL_60_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "PAL_60_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case PAL_M_SLOW: {
-		mask1 = 0x001F & PAL_M_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "PAL_M_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-		break;
-	}
-	case NTSC_M_SLOW: {
-		mask1 = 0x001F & NTSC_M_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "NTSC_M_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_443_SLOW: {
-		mask1 = 0x001F & NTSC_443_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "NTSC_443_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_M_JP_SLOW: {
-		mask1 = 0x001F & NTSC_M_JP_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "NTSC_M_JP_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_N_SLOW: {
-		mask1 = 0x001F & NTSC_N_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "NTSC_N_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	case NTSC_N_443_SLOW: {
-		mask1 = 0x001F & NTSC_N_443_SLOW;
-		mask1 |= 0x0200;
-		strcpy(&name1[0], "NTSC_N_443_SLOW");
-		colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-		break;
-	}
-	default:
-		return -1;
-	}
-
-	for (j = 0; j < RESOLUTION_MANY; j++) {
-		mask2 = 0x0000;
-		switch (j) {
-		case AT_720x576: {
-			if (0x1 & mask1)
-				continue;
-			strcpy(&name2[0], "_AT_720x576");
-			width = 720; height = 576; break;
-		}
-		case AT_704x576: {
-			if (0x1 & mask1)
-				continue;
-			strcpy(&name2[0], "_AT_704x576");
-			width = 704; height = 576; break;
-		}
-		case AT_640x480: {
-			strcpy(&name2[0], "_AT_640x480");
-			width = 640; height = 480; break;
-		}
-		case AT_720x480: {
-			if (!(0x1 & mask1))
-				continue;
-			strcpy(&name2[0], "_AT_720x480");
-			width = 720; height = 480; break;
-		}
-		case AT_360x288: {
-			if (0x1 & mask1)
-				continue;
-			strcpy(&name2[0], "_AT_360x288");
-			width = 360; height = 288; mask2 = 0x0800; break;
-		}
-		case AT_320x240: {
-			strcpy(&name2[0], "_AT_320x240");
-			width = 320; height = 240; mask2 = 0x0800; break;
-		}
-		case AT_360x240: {
-			if (!(0x1 & mask1))
-				continue;
-			strcpy(&name2[0], "_AT_360x240");
-			width = 360; height = 240; mask2 = 0x0800; break;
+	for (i = 0, n = 0; i < STANDARD_MANY; i++) {
+		mask1 = 0x0000;
+		switch (i) {
+		case PAL_BGHIN: {
+			mask1 = 0x1F & PAL_BGHIN;
+			name1 = "PAL_BGHIN";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case SECAM: {
+			mask1 = 0x1F & SECAM;
+			name1 = "SECAM";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case PAL_Nc: {
+			mask1 = 0x1F & PAL_Nc;
+			name1 = "PAL_Nc";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case PAL_60: {
+			mask1 = 0x1F & PAL_60;
+			name1 = "PAL_60";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case PAL_M: {
+			mask1 = 0x1F & PAL_M;
+			name1 = "PAL_M";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case NTSC_M: {
+			mask1 = 0x1F & NTSC_M;
+			name1 = "NTSC_M";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_443: {
+			mask1 = 0x1F & NTSC_443;
+			name1 = "NTSC_443";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_M_JP: {
+			mask1 = 0x1F & NTSC_M_JP;
+			name1 = "NTSC_M_JP";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_N: {
+			mask1 = 0x1F & NTSC_M;
+			name1 = "NTSC_N";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_N_443: {
+			mask1 = 0x1F & NTSC_N_443;
+			name1 = "NTSC_N_443";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case PAL_BGHIN_SLOW: {
+			mask1 = 0x001F & PAL_BGHIN_SLOW;
+			mask1 |= 0x0200;
+			name1 = "PAL_BGHIN_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case SECAM_SLOW: {
+			mask1 = 0x001F & SECAM_SLOW;
+			mask1 |= 0x0200;
+			name1 = "SECAM_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case PAL_Nc_SLOW: {
+			mask1 = 0x001F & PAL_Nc_SLOW;
+			mask1 |= 0x0200;
+			name1 = "PAL_Nc_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case PAL_60_SLOW: {
+			mask1 = 0x001F & PAL_60_SLOW;
+			mask1 |= 0x0200;
+			name1 = "PAL_60_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case PAL_M_SLOW: {
+			mask1 = 0x001F & PAL_M_SLOW;
+			mask1 |= 0x0200;
+			name1 = "PAL_M_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
+			break;
+		}
+		case NTSC_M_SLOW: {
+			mask1 = 0x001F & NTSC_M_SLOW;
+			mask1 |= 0x0200;
+			name1 = "NTSC_M_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_443_SLOW: {
+			mask1 = 0x001F & NTSC_443_SLOW;
+			mask1 |= 0x0200;
+			name1 = "NTSC_443_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_M_JP_SLOW: {
+			mask1 = 0x001F & NTSC_M_JP_SLOW;
+			mask1 |= 0x0200;
+			name1 = "NTSC_M_JP_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_N_SLOW: {
+			mask1 = 0x001F & NTSC_N_SLOW;
+			mask1 |= 0x0200;
+			name1 = "NTSC_N_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
+		}
+		case NTSC_N_443_SLOW: {
+			mask1 = 0x001F & NTSC_N_443_SLOW;
+			mask1 |= 0x0200;
+			name1 = "NTSC_N_443_SLOW";
+			colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
+			break;
 		}
 		default:
-			return -2;
+			return -1;
 		}
 
-		for (k = 0; k < PIXELFORMAT_MANY; k++) {
-			mask3 = 0x0000;
-			switch (k) {
-			case FMT_UYVY: {
-				strcpy(&name3[0], "_" STRINGIZE(FMT_UYVY));
-				pixelformat = V4L2_PIX_FMT_UYVY;
-				mask3 |= (0x02 << 5);
+		for (j = 0; j < RESOLUTION_MANY; j++) {
+			mask2 = 0x0000;
+			switch (j) {
+			case AT_720x576: {
+				if (0x1 & mask1)
+					continue;
+				name2 = "_AT_720x576";
+				width = 720;
+				height = 576;
 				break;
 			}
-			case FMT_YUY2: {
-				strcpy(&name3[0], "_" STRINGIZE(FMT_YUY2));
-				pixelformat = V4L2_PIX_FMT_YUYV;
-				mask3 |= (0x02 << 5);
-				mask3 |= 0x0100;
+			case AT_704x576: {
+				if (0x1 & mask1)
+					continue;
+				name2 = "_AT_704x576";
+				width = 704;
+				height = 576;
 				break;
 			}
-			case FMT_RGB24: {
-				strcpy(&name3[0], "_" STRINGIZE(FMT_RGB24));
-				pixelformat = V4L2_PIX_FMT_RGB24;
-				mask3 |= (0x03 << 5);
+			case AT_640x480: {
+				name2 = "_AT_640x480";
+				width = 640;
+				height = 480;
 				break;
 			}
-			case FMT_RGB32: {
-				strcpy(&name3[0], "_" STRINGIZE(FMT_RGB32));
-				pixelformat = V4L2_PIX_FMT_RGB32;
-				mask3 |= (0x04 << 5);
+			case AT_720x480: {
+				if (!(0x1 & mask1))
+					continue;
+				name2 = "_AT_720x480";
+				width = 720;
+				height = 480;
 				break;
 			}
-			case FMT_BGR24: {
-				strcpy(&name3[0], "_" STRINGIZE(FMT_BGR24));
-				pixelformat = V4L2_PIX_FMT_BGR24;
-				mask3 |= (0x03 << 5);
-				mask3 |= 0x0100;
+			case AT_360x288: {
+				if (0x1 & mask1)
+					continue;
+				name2 = "_AT_360x288";
+				width = 360;
+				height = 288;
+				mask2 = 0x0800;
 				break;
 			}
-			case FMT_BGR32: {
-				strcpy(&name3[0], "_" STRINGIZE(FMT_BGR32));
-				pixelformat = V4L2_PIX_FMT_BGR32;
-				mask3 |= (0x04 << 5);
-				mask3 |= 0x0100;
+			case AT_320x240: {
+				name2 = "_AT_320x240";
+				width = 320;
+				height = 240;
+				mask2 = 0x0800;
+				break;
+			}
+			case AT_360x240: {
+				if (!(0x1 & mask1))
+					continue;
+				name2 = "_AT_360x240";
+				width = 360;
+				height = 240;
+				mask2 = 0x0800;
 				break;
 			}
 			default:
-				return -3;
+				return -2;
 			}
-			bytesperline = width * ((mask3 & 0x00F0) >> 4);
-			sizeimage =  bytesperline * height;
 
-			for (m = 0; m < INTERLACE_MANY; m++) {
-				mask4 = 0x0000;
-				switch (m) {
-				case FIELD_NONE: {
-					strcpy(&name4[0], "-n");
-					field = V4L2_FIELD_NONE;
+			for (k = 0; k < PIXELFORMAT_MANY; k++) {
+				mask3 = 0x0000;
+				switch (k) {
+				case FMT_UYVY: {
+					name3 = __stringify(FMT_UYVY);
+					pixelformat = V4L2_PIX_FMT_UYVY;
+					mask3 |= (0x02 << 5);
+					break;
+				}
+				case FMT_YUY2: {
+					name3 = __stringify(FMT_YUY2);
+					pixelformat = V4L2_PIX_FMT_YUYV;
+					mask3 |= (0x02 << 5);
+					mask3 |= 0x0100;
+					break;
+				}
+				case FMT_RGB24: {
+					name3 = __stringify(FMT_RGB24);
+					pixelformat = V4L2_PIX_FMT_RGB24;
+					mask3 |= (0x03 << 5);
+					break;
+				}
+				case FMT_RGB32: {
+					name3 = __stringify(FMT_RGB32);
+					pixelformat = V4L2_PIX_FMT_RGB32;
+					mask3 |= (0x04 << 5);
 					break;
 				}
-				case FIELD_INTERLACED: {
-					strcpy(&name4[0], "-i");
-					mask4 |= 0x1000;
-					field = V4L2_FIELD_INTERLACED;
+				case FMT_BGR24: {
+					name3 = __stringify(FMT_BGR24);
+					pixelformat = V4L2_PIX_FMT_BGR24;
+					mask3 |= (0x03 << 5);
+					mask3 |= 0x0100;
+					break;
+				}
+				case FMT_BGR32: {
+					name3 = __stringify(FMT_BGR32);
+					pixelformat = V4L2_PIX_FMT_BGR32;
+					mask3 |= (0x04 << 5);
+					mask3 |= 0x0100;
 					break;
 				}
 				default:
-					return -4;
+					return -3;
 				}
-				if (SETTINGS_MANY <= n)
-					return -5;
-				strcpy(&easycap_format[n].name[0], &name1[0]);
-				strcat(&easycap_format[n].name[0], &name2[0]);
-				strcat(&easycap_format[n].name[0], &name3[0]);
-				strcat(&easycap_format[n].name[0], &name4[0]);
-				easycap_format[n].mask = \
+				bytesperline = width * ((mask3 & 0x00F0) >> 4);
+				sizeimage =  bytesperline * height;
+
+				for (m = 0; m < INTERLACE_MANY; m++) {
+					mask4 = 0x0000;
+					switch (m) {
+					case FIELD_NONE: {
+						name4 = "-n";
+						field = V4L2_FIELD_NONE;
+						break;
+					}
+					case FIELD_INTERLACED: {
+						name4 = "-i";
+						mask4 |= 0x1000;
+						field = V4L2_FIELD_INTERLACED;
+						break;
+					}
+					default:
+						return -4;
+					}
+					if (SETTINGS_MANY <= n)
+						return -5;
+
+					strcpy(easycap_format[n].name, name1);
+					strcat(easycap_format[n].name, name2);
+					strcat(easycap_format[n].name, "_");
+					strcat(easycap_format[n].name, name3);
+					strcat(easycap_format[n].name, name4);
+					easycap_format[n].mask =
 						mask1 | mask2 | mask3 | mask4;
-				easycap_format[n].v4l2_format\
-					.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.width = width;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.height = height;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.pixelformat = pixelformat;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.field = field;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.bytesperline = bytesperline;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.sizeimage = sizeimage;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.colorspace = colorspace;
-				easycap_format[n].v4l2_format\
-					.fmt.pix.priv = 0;
-				n++;
+					fmt = &easycap_format[n].v4l2_format;
+
+					fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+					fmt->fmt.pix.width = width;
+					fmt->fmt.pix.height = height;
+					fmt->fmt.pix.pixelformat = pixelformat;
+					fmt->fmt.pix.field = field;
+					fmt->fmt.pix.bytesperline = bytesperline;
+					fmt->fmt.pix.sizeimage = sizeimage;
+					fmt->fmt.pix.colorspace = colorspace;
+					fmt->fmt.pix.priv = 0;
+					n++;
+				}
 			}
 		}
 	}
-}
-if ((1 + SETTINGS_MANY) <= n)
-	return -6;
-easycap_format[n].mask = 0xFFFF;
-return n;
+	if ((1 + SETTINGS_MANY) <= n)
+		return -6;
+	easycap_format[n].mask = 0xFFFF;
+	return n;
 }
 /*---------------------------------------------------------------------------*/
-struct v4l2_queryctrl easycap_control[] = \
-{{
-.id       = V4L2_CID_BRIGHTNESS,
-.type     = V4L2_CTRL_TYPE_INTEGER,
-.name     = "Brightness",
-.minimum  = 0,
-.maximum  = 255,
-.step     =  1,
-.default_value = SAA_0A_DEFAULT,
-.flags    = 0,
-.reserved = {0, 0}
-},
+struct v4l2_queryctrl easycap_control[] = {
+	{
+		.id       = V4L2_CID_BRIGHTNESS,
+		.type     = V4L2_CTRL_TYPE_INTEGER,
+		.name     = "Brightness",
+		.minimum  = 0,
+		.maximum  = 255,
+		.step     =  1,
+		.default_value = SAA_0A_DEFAULT,
+		.flags    = 0,
+		.reserved = {0, 0}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.id       = V4L2_CID_CONTRAST,
-.type     = V4L2_CTRL_TYPE_INTEGER,
-.name     = "Contrast",
-.minimum  = 0,
-.maximum  = 255,
-.step     =   1,
-.default_value = SAA_0B_DEFAULT + 128,
-.flags    = 0,
-.reserved = {0, 0}
-},
+	{
+		.id       = V4L2_CID_CONTRAST,
+		.type     = V4L2_CTRL_TYPE_INTEGER,
+		.name     = "Contrast",
+		.minimum  = 0,
+		.maximum  = 255,
+		.step     =   1,
+		.default_value = SAA_0B_DEFAULT + 128,
+		.flags    = 0,
+		.reserved = {0, 0}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.id       = V4L2_CID_SATURATION,
-.type     = V4L2_CTRL_TYPE_INTEGER,
-.name     = "Saturation",
-.minimum  = 0,
-.maximum  = 255,
-.step     =   1,
-.default_value = SAA_0C_DEFAULT + 128,
-.flags    = 0,
-.reserved = {0, 0}
-},
+	{
+		.id       = V4L2_CID_SATURATION,
+		.type     = V4L2_CTRL_TYPE_INTEGER,
+		.name     = "Saturation",
+		.minimum  = 0,
+		.maximum  = 255,
+		.step     =   1,
+		.default_value = SAA_0C_DEFAULT + 128,
+		.flags    = 0,
+		.reserved = {0, 0}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.id       = V4L2_CID_HUE,
-.type     = V4L2_CTRL_TYPE_INTEGER,
-.name     = "Hue",
-.minimum  = 0,
-.maximum  = 255,
-.step     =   1,
-.default_value = SAA_0D_DEFAULT + 128,
-.flags    = 0,
-.reserved = {0, 0}
-},
+	{
+		.id       = V4L2_CID_HUE,
+		.type     = V4L2_CTRL_TYPE_INTEGER,
+		.name     = "Hue",
+		.minimum  = 0,
+		.maximum  = 255,
+		.step     =   1,
+		.default_value = SAA_0D_DEFAULT + 128,
+		.flags    = 0,
+		.reserved = {0, 0}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.id       = V4L2_CID_AUDIO_VOLUME,
-.type     = V4L2_CTRL_TYPE_INTEGER,
-.name     = "Volume",
-.minimum  = 0,
-.maximum  = 31,
-.step     =   1,
-.default_value = 16,
-.flags    = 0,
-.reserved = {0, 0}
-},
+	{
+		.id       = V4L2_CID_AUDIO_VOLUME,
+		.type     = V4L2_CTRL_TYPE_INTEGER,
+		.name     = "Volume",
+		.minimum  = 0,
+		.maximum  = 31,
+		.step     =   1,
+		.default_value = 16,
+		.flags    = 0,
+		.reserved = {0, 0}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.id       = V4L2_CID_AUDIO_MUTE,
-.type     = V4L2_CTRL_TYPE_BOOLEAN,
-.name     = "Mute",
-.default_value = true,
-.flags    = 0,
-.reserved = {0, 0}
-},
+	{
+		.id       = V4L2_CID_AUDIO_MUTE,
+		.type     = V4L2_CTRL_TYPE_BOOLEAN,
+		.name     = "Mute",
+		.default_value = true,
+		.flags    = 0,
+		.reserved = {0, 0}
+	},
 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-{
-.id = 0xFFFFFFFF
-}
+	{
+		.id = 0xFFFFFFFF
+	}
 };
 /*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_sound.c b/drivers/staging/easycap/easycap_sound.c
index 24d8bb4..a3402b0 100644
--- a/drivers/staging/easycap/easycap_sound.c
+++ b/drivers/staging/easycap/easycap_sound.c
@@ -29,1009 +29,681 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
-#include "easycap_sound.h"
+
+#ifndef CONFIG_EASYCAP_OSS
+/*--------------------------------------------------------------------------*/
+/*
+ *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
+ */
+/*--------------------------------------------------------------------------*/
+static const struct snd_pcm_hardware alsa_hardware = {
+	.info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP           |
+		SNDRV_PCM_INFO_INTERLEAVED    |
+		SNDRV_PCM_INFO_MMAP_VALID,
+	.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
+	.rate_min = 32000,
+	.rate_max = 48000,
+	.channels_min = 2,
+	.channels_max = 2,
+	.buffer_bytes_max = PAGE_SIZE *
+			    PAGES_PER_AUDIO_FRAGMENT *
+			    AUDIO_FRAGMENT_MANY,
+	.period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
+	.period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
+	.periods_min = AUDIO_FRAGMENT_MANY,
+	.periods_max = AUDIO_FRAGMENT_MANY * 2,
+};
+
 
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
- *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
+ *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
  *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
  *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
  */
 /*---------------------------------------------------------------------------*/
 void
-easysnd_complete(struct urb *purb)
+easycap_alsa_complete(struct urb *purb)
 {
-struct easycap *peasycap;
-struct data_buffer *paudio_buffer;
-__u8 *p1, *p2;
-__s16 s16;
-int i, j, more, much, leap, rc;
-#if defined(UPSAMPLE)
-int k;
-__s16 oldaudio, newaudio, delta;
+	struct easycap *peasycap;
+	struct snd_pcm_substream *pss;
+	struct snd_pcm_runtime *prt;
+	int dma_bytes, fragment_bytes;
+	int isfragment;
+	u8 *p1, *p2;
+	s16 tmp;
+	int i, j, more, much, rc;
+#ifdef UPSAMPLE
+	int k;
+	s16 oldaudio, newaudio, delta;
 #endif /*UPSAMPLE*/
 
-JOT(16, "\n");
-
-if (NULL == purb) {
-	SAY("ERROR: purb is NULL\n");
-	return;
-}
-peasycap = purb->context;
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap\n");
-	return;
-}
-
-much = 0;
+	JOT(16, "\n");
 
-if (peasycap->audio_idle) {
-	JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n", \
-			peasycap->audio_idle, peasycap->audio_isoc_streaming);
-	if (peasycap->audio_isoc_streaming) {
-		rc = usb_submit_urb(purb, GFP_ATOMIC);
-		if (0 != rc) {
-			if (-ENODEV != rc)
-				SAM("ERROR: while %i=audio_idle, " \
-					"usb_submit_urb() failed with rc:\n", \
-							peasycap->audio_idle);
-			switch (rc) {
-			case -ENOMEM: {
-				SAM("-ENOMEM\n");
-				break;
-			}
-			case -ENODEV: {
-				break;
-			}
-			case -ENXIO: {
-				SAM("-ENXIO\n");
-				break;
-			}
-			case -EINVAL: {
-				SAM("-EINVAL\n");
-				break;
-			}
-			case -EAGAIN: {
-				SAM("-EAGAIN\n");
-				break;
-			}
-			case -EFBIG: {
-				SAM("-EFBIG\n");
-				break;
-			}
-			case -EPIPE: {
-				SAM("-EPIPE\n");
-				break;
-			}
-			case -EMSGSIZE: {
-				SAM("-EMSGSIZE\n");
-				break;
-			}
-			case -ENOSPC: {
-				SAM("-ENOSPC\n");
-				break;
-			}
-			default: {
-				SAM("unknown error: 0x%08X\n", rc);
-				break;
-			}
-			}
-		}
-	}
-return;
-}
-/*---------------------------------------------------------------------------*/
-if (purb->status) {
-	if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
-		JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
+	if (!purb) {
+		SAY("ERROR: purb is NULL\n");
 		return;
 	}
-	SAM("ERROR: non-zero urb status:\n");
-	switch (purb->status) {
-	case -EINPROGRESS: {
-		SAM("-EINPROGRESS\n");
-		break;
-	}
-	case -ENOSR: {
-		SAM("-ENOSR\n");
-		break;
-	}
-	case -EPIPE: {
-		SAM("-EPIPE\n");
-		break;
-	}
-	case -EOVERFLOW: {
-		SAM("-EOVERFLOW\n");
-		break;
-	}
-	case -EPROTO: {
-		SAM("-EPROTO\n");
-		break;
-	}
-	case -EILSEQ: {
-		SAM("-EILSEQ\n");
-		break;
-	}
-	case -ETIMEDOUT: {
-		SAM("-ETIMEDOUT\n");
-		break;
-	}
-	case -EMSGSIZE: {
-		SAM("-EMSGSIZE\n");
-		break;
-	}
-	case -EOPNOTSUPP: {
-		SAM("-EOPNOTSUPP\n");
-		break;
-	}
-	case -EPFNOSUPPORT: {
-		SAM("-EPFNOSUPPORT\n");
-		break;
-	}
-	case -EAFNOSUPPORT: {
-		SAM("-EAFNOSUPPORT\n");
-		break;
-	}
-	case -EADDRINUSE: {
-		SAM("-EADDRINUSE\n");
-		break;
-	}
-	case -EADDRNOTAVAIL: {
-		SAM("-EADDRNOTAVAIL\n");
-		break;
-	}
-	case -ENOBUFS: {
-		SAM("-ENOBUFS\n");
-		break;
-	}
-	case -EISCONN: {
-		SAM("-EISCONN\n");
-		break;
-	}
-	case -ENOTCONN: {
-		SAM("-ENOTCONN\n");
-		break;
-	}
-	case -ESHUTDOWN: {
-		SAM("-ESHUTDOWN\n");
-		break;
-	}
-	case -ENOENT: {
-		SAM("-ENOENT\n");
-		break;
-	}
-	case -ECONNRESET: {
-		SAM("-ECONNRESET\n");
-		break;
-	}
-	case -ENOSPC: {
-		SAM("ENOSPC\n");
-		break;
-	}
-	default: {
-		SAM("unknown error code 0x%08X\n", purb->status);
-		break;
+	peasycap = purb->context;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return;
 	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return;
 	}
-/*---------------------------------------------------------------------------*/
-/*
- *  RESUBMIT THIS URB AFTER AN ERROR
- *
- *  (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH)
- */
-/*---------------------------------------------------------------------------*/
-	if (peasycap->audio_isoc_streaming) {
-		rc = usb_submit_urb(purb, GFP_ATOMIC);
-		if (0 != rc) {
-			SAM("ERROR: while %i=audio_idle, usb_submit_urb() "
-				"failed with rc:\n", peasycap->audio_idle);
-			switch (rc) {
-			case -ENOMEM: {
-				SAM("-ENOMEM\n");
-				break;
-			}
-			case -ENODEV: {
-				SAM("-ENODEV\n");
-				break;
-			}
-			case -ENXIO: {
-				SAM("-ENXIO\n");
-				break;
-			}
-			case -EINVAL: {
-				SAM("-EINVAL\n");
-				break;
-			}
-			case -EAGAIN: {
-				SAM("-EAGAIN\n");
-				break;
-			}
-			case -EFBIG: {
-				SAM("-EFBIG\n");
-				break;
-			}
-			case -EPIPE: {
-				SAM("-EPIPE\n");
-				break;
-			}
-			case -EMSGSIZE: {
-				SAM("-EMSGSIZE\n");
-				break;
-			}
-			default: {
-				SAM("0x%08X\n", rc); break;
-			}
-			}
+	much = 0;
+	if (peasycap->audio_idle) {
+		JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
+		    peasycap->audio_idle, peasycap->audio_isoc_streaming);
+		if (peasycap->audio_isoc_streaming)
+			goto resubmit;
+	}
+/*---------------------------------------------------------------------------*/
+	pss = peasycap->psubstream;
+	if (!pss)
+		goto resubmit;
+	prt = pss->runtime;
+	if (!prt)
+		goto resubmit;
+	dma_bytes = (int)prt->dma_bytes;
+	if (0 == dma_bytes)
+		goto resubmit;
+	fragment_bytes = 4 * ((int)prt->period_size);
+	if (0 == fragment_bytes)
+		goto resubmit;
+/* -------------------------------------------------------------------------*/
+	if (purb->status) {
+		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
+			JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
+			return;
 		}
+		SAM("ERROR: non-zero urb status: -%s: %d\n",
+		    strerror(purb->status), purb->status);
+		goto resubmit;
 	}
-	return;
-}
 /*---------------------------------------------------------------------------*/
 /*
  *  PROCEED HERE WHEN NO ERROR
  */
 /*---------------------------------------------------------------------------*/
-#if defined(UPSAMPLE)
-oldaudio = peasycap->oldaudio;
+
+#ifdef UPSAMPLE
+	oldaudio = peasycap->oldaudio;
 #endif /*UPSAMPLE*/
 
-for (i = 0;  i < purb->number_of_packets; i++) {
-	switch (purb->iso_frame_desc[i].status) {
-	case  0: {
-		break;
-	}
-	case -ENOENT: {
-		SAM("-ENOENT\n");
-		break;
-	}
-	case -EINPROGRESS: {
-		SAM("-EINPROGRESS\n");
-		break;
-	}
-	case -EPROTO: {
-		SAM("-EPROTO\n");
-		break;
-	}
-	case -EILSEQ: {
-		SAM("-EILSEQ\n");
-		break;
-	}
-	case -ETIME: {
-		SAM("-ETIME\n");
-		break;
-	}
-	case -ETIMEDOUT: {
-		SAM("-ETIMEDOUT\n");
-		break;
-	}
-	case -EPIPE: {
-		SAM("-EPIPE\n");
-		break;
-	}
-	case -ECOMM: {
-		SAM("-ECOMM\n");
-		break;
-	}
-	case -ENOSR: {
-		SAM("-ENOSR\n");
-		break;
-	}
-	case -EOVERFLOW: {
-		SAM("-EOVERFLOW\n");
-		break;
-	}
-	case -EREMOTEIO: {
-		SAM("-EREMOTEIO\n");
-		break;
-	}
-	case -ENODEV: {
-		SAM("-ENODEV\n");
-		break;
-	}
-	case -EXDEV: {
-		SAM("-EXDEV\n");
-		break;
-	}
-	case -EINVAL: {
-		SAM("-EINVAL\n");
-		break;
-	}
-	case -ECONNRESET: {
-		SAM("-ECONNRESET\n");
-		break;
-	}
-	case -ENOSPC: {
-		SAM("-ENOSPC\n");
-		break;
-	}
-	case -ESHUTDOWN: {
-		SAM("-ESHUTDOWN\n");
-		break;
-	}
-	default: {
-		SAM("unknown error:0x%08X\n", purb->iso_frame_desc[i].status);
-		break;
-	}
-	}
-	if (!purb->iso_frame_desc[i].status) {
+	for (i = 0;  i < purb->number_of_packets; i++) {
+		if (purb->iso_frame_desc[i].status < 0) {
+			SAM("-%s: %d\n",
+			    strerror(purb->iso_frame_desc[i].status),
+			    purb->iso_frame_desc[i].status);
+		}
+		if (purb->iso_frame_desc[i].status) {
+			JOM(12, "discarding audio samples because "
+			    "%i=purb->iso_frame_desc[i].status\n",
+			    purb->iso_frame_desc[i].status);
+			continue;
+		}
 		more = purb->iso_frame_desc[i].actual_length;
-
-#if defined(TESTTONE)
-		if (!more)
-			more = purb->iso_frame_desc[i].length;
-#endif
-
-		if (!more)
+		if (more == 0) {
 			peasycap->audio_mt++;
-		else {
-			if (peasycap->audio_mt) {
-				JOM(16, "%4i empty audio urb frames\n", \
-							peasycap->audio_mt);
-				peasycap->audio_mt = 0;
-			}
+			continue;
+		}
+		if (0 > more) {
+			SAM("MISTAKE: more is negative\n");
+			return;
+		}
 
-			p1 = (__u8 *)(purb->transfer_buffer + \
-					purb->iso_frame_desc[i].offset);
+		if (peasycap->audio_mt) {
+			JOM(12, "%4i empty audio urb frames\n",
+			    peasycap->audio_mt);
+			peasycap->audio_mt = 0;
+		}
 
-			leap = 0;
-			p1 += leap;
-			more -= leap;
-/*---------------------------------------------------------------------------*/
-/*
- *  COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
- *  CONVERTING 8-BIT MONO TO 16-BIT SIGNED LITTLE-ENDIAN SAMPLES IF NECESSARY
- */
-/*---------------------------------------------------------------------------*/
-			while (more) {
-				if (0 > more) {
-					SAM("easysnd_complete: MISTAKE: " \
-							"more is negative\n");
-					return;
+		p1 = (u8 *)(purb->transfer_buffer +
+				purb->iso_frame_desc[i].offset);
+
+		/*
+		 *  COPY more BYTES FROM ISOC BUFFER
+		 *  TO THE DMA BUFFER, CONVERTING
+		 *  8-BIT MONO TO 16-BIT SIGNED
+		 *  LITTLE-ENDIAN SAMPLES IF NECESSARY
+		 */
+		while (more) {
+			much = dma_bytes - peasycap->dma_fill;
+			if (0 > much) {
+				SAM("MISTAKE: much is negative\n");
+				return;
+			}
+			if (0 == much) {
+				peasycap->dma_fill = 0;
+				peasycap->dma_next = fragment_bytes;
+				JOM(8, "wrapped dma buffer\n");
+			}
+			if (!peasycap->microphone) {
+				if (much > more)
+					much = more;
+				memcpy(prt->dma_area + peasycap->dma_fill,
+					p1, much);
+				p1 += much;
+				more -= much;
+			} else {
+#ifdef UPSAMPLE
+				if (much % 16)
+					JOM(8, "MISTAKE? much"
+					    " is not divisible by 16\n");
+				if (much > (16 * more))
+					much = 16 * more;
+				p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
+
+				for (j = 0;  j < (much / 16);  j++) {
+					newaudio =  ((int) *p1) - 128;
+					newaudio = 128 * newaudio;
+
+					delta = (newaudio - oldaudio) / 4;
+					tmp = oldaudio + delta;
+
+					for (k = 0;  k < 4;  k++) {
+						*p2 = (0x00FF & tmp);
+						*(p2 + 1) = (0xFF00 & tmp) >> 8;
+						p2 += 2;
+						*p2 = (0x00FF & tmp);
+						*(p2 + 1) = (0xFF00 & tmp) >> 8;
+						p2 += 2;
+						tmp += delta;
+					}
+					p1++;
+					more--;
+					oldaudio = tmp;
 				}
-				if (peasycap->audio_buffer_page_many <= \
-							peasycap->audio_fill) {
-					SAM("ERROR: bad " \
-						"peasycap->audio_fill\n");
-					return;
+#else /*!UPSAMPLE*/
+				if (much > (2 * more))
+					much = 2 * more;
+				p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
+
+				for (j = 0;  j < (much / 2);  j++) {
+					tmp = ((int) *p1) - 128;
+					tmp = 128 * tmp;
+					*p2 = (0x00FF & tmp);
+					*(p2 + 1) = (0xFF00 & tmp) >> 8;
+					p1++;
+					p2 += 2;
+					more--;
 				}
-
-				paudio_buffer = &peasycap->audio_buffer\
-							[peasycap->audio_fill];
-				if (PAGE_SIZE < (paudio_buffer->pto - \
-						paudio_buffer->pgo)) {
-					SAM("ERROR: bad paudio_buffer->pto\n");
+#endif /*UPSAMPLE*/
+			}
+			peasycap->dma_fill += much;
+			if (peasycap->dma_fill >= peasycap->dma_next) {
+				isfragment = peasycap->dma_fill / fragment_bytes;
+				if (0 > isfragment) {
+					SAM("MISTAKE: isfragment is negative\n");
 					return;
 				}
-				if (PAGE_SIZE == (paudio_buffer->pto - \
-							paudio_buffer->pgo)) {
-
-#if defined(TESTTONE)
-					easysnd_testtone(peasycap, \
-							peasycap->audio_fill);
-#endif /*TESTTONE*/
-
-					paudio_buffer->pto = \
-							paudio_buffer->pgo;
-					(peasycap->audio_fill)++;
-					if (peasycap->\
-						audio_buffer_page_many <= \
-							peasycap->audio_fill)
-						peasycap->audio_fill = 0;
-
-					JOM(12, "bumped peasycap->" \
-							"audio_fill to %i\n", \
-							peasycap->audio_fill);
-
-					paudio_buffer = &peasycap->\
-							audio_buffer\
-							[peasycap->audio_fill];
-					paudio_buffer->pto = \
-							paudio_buffer->pgo;
-
-					if (!(peasycap->audio_fill % \
-						peasycap->\
-						audio_pages_per_fragment)) {
-						JOM(12, "wakeup call on wq_" \
-						"audio, %i=frag reading  %i" \
-						"=fragment fill\n", \
-						(peasycap->audio_read / \
-						peasycap->\
-						audio_pages_per_fragment), \
-						(peasycap->audio_fill / \
-						peasycap->\
-						audio_pages_per_fragment));
-						wake_up_interruptible\
-						(&(peasycap->wq_audio));
-					}
+				peasycap->dma_read = (isfragment - 1) * fragment_bytes;
+				peasycap->dma_next = (isfragment + 1) * fragment_bytes;
+				if (dma_bytes < peasycap->dma_next)
+					peasycap->dma_next = fragment_bytes;
+
+				if (0 <= peasycap->dma_read) {
+					JOM(8, "snd_pcm_period_elapsed(), %i="
+					    "isfragment\n", isfragment);
+					snd_pcm_period_elapsed(pss);
 				}
-
-				much = PAGE_SIZE - (int)(paudio_buffer->pto -\
-							 paudio_buffer->pgo);
-
-				if (false == peasycap->microphone) {
-					if (much > more)
-						much = more;
-
-					memcpy(paudio_buffer->pto, p1, much);
-					p1 += much;
-					more -= much;
-				} else {
-#if defined(UPSAMPLE)
-					if (much % 16)
-						JOM(8, "MISTAKE? much" \
-						" is not divisible by 16\n");
-					if (much > (16 * \
-							more))
-						much = 16 * \
-							more;
-					p2 = (__u8 *)paudio_buffer->pto;
-
-					for (j = 0;  j < (much/16);  j++) {
-						newaudio =  ((int) *p1) - 128;
-						newaudio = 128 * \
-								newaudio;
-
-						delta = (newaudio - oldaudio) \
-									/ 4;
-						s16 = oldaudio + delta;
-
-						for (k = 0;  k < 4;  k++) {
-							*p2 = (0x00FF & s16);
-							*(p2 + 1) = (0xFF00 & \
-								s16) >> 8;
-							p2 += 2;
-							*p2 = (0x00FF & s16);
-							*(p2 + 1) = (0xFF00 & \
-								s16) >> 8;
-							p2 += 2;
-
-							s16 += delta;
-						}
-						p1++;
-						more--;
-						oldaudio = s16;
-					}
-#else
-					if (much > (2 * more))
-						much = 2 * more;
-					p2 = (__u8 *)paudio_buffer->pto;
-
-					for (j = 0;  j < (much / 2);  j++) {
-						s16 =  ((int) *p1) - 128;
-						s16 = 128 * \
-								s16;
-						*p2 = (0x00FF & s16);
-						*(p2 + 1) = (0xFF00 & s16) >> \
-									8;
-						p1++;  p2 += 2;
-						more--;
-					}
-#endif /*UPSAMPLE*/
-				}
-				(paudio_buffer->pto) += much;
 			}
 		}
-	} else {
-		JOM(12, "discarding audio samples because " \
-			"%i=purb->iso_frame_desc[i].status\n", \
-				purb->iso_frame_desc[i].status);
-	}
 
-#if defined(UPSAMPLE)
-peasycap->oldaudio = oldaudio;
+#ifdef UPSAMPLE
+		peasycap->oldaudio = oldaudio;
 #endif /*UPSAMPLE*/
 
-}
+	}
 /*---------------------------------------------------------------------------*/
 /*
- *  RESUBMIT THIS URB AFTER NO ERROR
+ *  RESUBMIT THIS URB
  */
 /*---------------------------------------------------------------------------*/
-if (peasycap->audio_isoc_streaming) {
+resubmit:
+	if (peasycap->audio_isoc_streaming == 0)
+		return;
+
 	rc = usb_submit_urb(purb, GFP_ATOMIC);
-	if (0 != rc) {
-		if (-ENODEV != rc) {
-			SAM("ERROR: while %i=audio_idle, " \
-					"usb_submit_urb() failed " \
-					"with rc:\n", peasycap->audio_idle);
-		}
-		switch (rc) {
-		case -ENOMEM: {
-			SAM("-ENOMEM\n");
-			break;
-		}
-		case -ENODEV: {
-			break;
-		}
-		case -ENXIO: {
-			SAM("-ENXIO\n");
-			break;
-		}
-		case -EINVAL: {
-			SAM("-EINVAL\n");
-			break;
-		}
-		case -EAGAIN: {
-			SAM("-EAGAIN\n");
-			break;
-		}
-		case -EFBIG: {
-			SAM("-EFBIG\n");
-			break;
-		}
-		case -EPIPE: {
-			SAM("-EPIPE\n");
-			break;
-		}
-		case -EMSGSIZE: {
-			SAM("-EMSGSIZE\n");
-			break;
-		}
-		case -ENOSPC: {
-			SAM("-ENOSPC\n");
-			break;
-		}
-		default: {
-			SAM("unknown error: 0x%08X\n", rc);
-			break;
-		}
+	if (rc) {
+		if ((-ENODEV != rc) && (-ENOENT != rc)) {
+			SAM("ERROR: while %i=audio_idle, usb_submit_urb failed "
+			    "with rc: -%s :%d\n",
+				peasycap->audio_idle, strerror(rc), rc);
 		}
+		if (0 < peasycap->audio_isoc_streaming)
+			peasycap->audio_isoc_streaming--;
 	}
-}
-return;
+	return;
 }
 /*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
- *  STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
- *  HAVE AN IOCTL INTERFACE.
- */
-/*---------------------------------------------------------------------------*/
-int
-easysnd_open(struct inode *inode, struct file *file)
+static int easycap_alsa_open(struct snd_pcm_substream *pss)
 {
-struct usb_interface *pusb_interface;
-struct easycap *peasycap;
-int subminor, rc;
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-struct v4l2_device *pv4l2_device;
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-
-JOT(4, "begins\n");
-
-subminor = iminor(inode);
-
-pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
-if (NULL == pusb_interface) {
-	SAY("ERROR: pusb_interface is NULL\n");
-	SAY("ending unsuccessfully\n");
-	return -1;
-}
-peasycap = usb_get_intfdata(pusb_interface);
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	SAY("ending unsuccessfully\n");
-	return -1;
-}
-/*---------------------------------------------------------------------------*/
-#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
-#
-/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
-#else
-#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
-/*---------------------------------------------------------------------------*/
-/*
- *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
- *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
- *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
- *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
-*/
-/*---------------------------------------------------------------------------*/
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	pv4l2_device = usb_get_intfdata(pusb_interface);
-	if ((struct v4l2_device *)NULL == pv4l2_device) {
-		SAY("ERROR: pv4l2_device is NULL\n");
+	struct snd_pcm *psnd_pcm;
+	struct snd_card *psnd_card;
+	struct easycap *peasycap;
+
+	JOT(4, "\n");
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
+	}
+	psnd_pcm = pss->pcm;
+	if (!psnd_pcm) {
+		SAY("ERROR:  psnd_pcm is NULL\n");
+		return -EFAULT;
+	}
+	psnd_card = psnd_pcm->card;
+	if (!psnd_card) {
+		SAY("ERROR:  psnd_card is NULL\n");
 		return -EFAULT;
 	}
-	peasycap = (struct easycap *) \
-		container_of(pv4l2_device, struct easycap, v4l2_device);
-}
-#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
-#
-#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*---------------------------------------------------------------------------*/
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-/*---------------------------------------------------------------------------*/
-
-file->private_data = peasycap;
 
-/*---------------------------------------------------------------------------*/
-/*
- *  INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-JOM(4, "starting initialization\n");
+	peasycap = psnd_card->private_data;
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return -EFAULT;
+	}
+	if (peasycap->psnd_card != psnd_card) {
+		SAM("ERROR: bad peasycap->psnd_card\n");
+		return -EFAULT;
+	}
+	if (peasycap->psubstream) {
+		SAM("ERROR: bad peasycap->psubstream\n");
+		return -EFAULT;
+	}
+	pss->private_data = peasycap;
+	peasycap->psubstream = pss;
+	pss->runtime->hw = peasycap->alsa_hardware;
+	pss->runtime->private_data = peasycap;
+	pss->private_data = peasycap;
 
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -ENODEV;
+	if (0 != easycap_sound_setup(peasycap)) {
+		JOM(4, "ending unsuccessfully\n");
+		return -EFAULT;
+	}
+	JOM(4, "ending successfully\n");
+	return 0;
 }
-JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
-
-rc = audio_setup(peasycap);
-if (0 <= rc)
-	JOM(8, "audio_setup() returned %i\n", rc);
-else
-	JOM(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc);
+/*****************************************************************************/
+static int easycap_alsa_close(struct snd_pcm_substream *pss)
+{
+	struct easycap *peasycap;
 
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device has become NULL\n");
-	return -ENODEV;
-}
-/*---------------------------------------------------------------------------*/
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device has become NULL\n");
-	return -ENODEV;
+	JOT(4, "\n");
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
+	}
+	peasycap = snd_pcm_substream_chip(pss);
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return -EFAULT;
+	}
+	pss->private_data = NULL;
+	peasycap->psubstream = NULL;
+	JOT(4, "ending successfully\n");
+	return 0;
 }
-rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
-					peasycap->audio_altsetting_on);
-JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
-					peasycap->audio_altsetting_on, rc);
-
-rc = wakeup_device(peasycap->pusb_device);
-if (0 == rc)
-	JOM(8, "wakeup_device() returned %i\n", rc);
-else
-	JOM(8, "ERROR: wakeup_device() returned %i\n", rc);
-
-peasycap->audio_eof = 0;
-peasycap->audio_idle = 0;
-
-peasycap->timeval1.tv_sec  = 0;
-peasycap->timeval1.tv_usec = 0;
-
-submit_audio_urbs(peasycap);
+/*****************************************************************************/
+static int easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
+{
+	struct snd_pcm_runtime *prt;
+	JOT(4, "\n");
 
-JOM(4, "finished initialization\n");
-return 0;
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
+	}
+	prt = pss->runtime;
+	if (!prt) {
+		SAY("ERROR: substream.runtime is NULL\n");
+		return -EFAULT;
+	}
+	if (prt->dma_area) {
+		if (prt->dma_bytes > sz)
+			return 0;
+		vfree(prt->dma_area);
+	}
+	prt->dma_area = vmalloc(sz);
+	if (!prt->dma_area)
+		return -ENOMEM;
+	prt->dma_bytes = sz;
+	return 0;
 }
 /*****************************************************************************/
-int
-easysnd_release(struct inode *inode, struct file *file)
+static int easycap_alsa_hw_params(struct snd_pcm_substream *pss,
+				 struct snd_pcm_hw_params *phw)
 {
-struct easycap *peasycap;
+	int rc;
 
-JOT(4, "begins\n");
-
-peasycap = file->private_data;
-if (NULL == peasycap) {
-	SAY("ERROR:  peasycap is NULL.\n");
-	return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-if (0 != kill_audio_urbs(peasycap)) {
-	SAM("ERROR: kill_audio_urbs() failed\n");
-	return -EFAULT;
-}
-JOM(4, "ending successfully\n");
-return 0;
+	JOT(4, "%i\n", (params_buffer_bytes(phw)));
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
+	}
+	rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
+	if (rc)
+		return rc;
+	return 0;
 }
 /*****************************************************************************/
-ssize_t
-easysnd_read(struct file *file, char __user *puserspacebuffer, \
-						size_t kount, loff_t *poff)
+static int easycap_alsa_hw_free(struct snd_pcm_substream *pss)
 {
-struct timeval timeval;
-long long int above, below, mean;
-struct signed_div_result sdr;
-unsigned char *p0;
-long int kount1, more, rc, l0, lm;
-int fragment, kd;
-struct easycap *peasycap;
-struct data_buffer *pdata_buffer;
-size_t szret;
-
-/*---------------------------------------------------------------------------*/
-/*
- *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
- *
- ******************************************************************************
- *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
- *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
- ******************************************************************************
- */
-/*---------------------------------------------------------------------------*/
-
-JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
+	struct snd_pcm_runtime *prt;
+	JOT(4, "\n");
 
-if (NULL == file) {
-	SAY("ERROR:  file is NULL\n");
-	return -ERESTARTSYS;
-}
-peasycap = file->private_data;
-if (NULL == peasycap) {
-	SAY("ERROR in easysnd_read(): peasycap is NULL\n");
-	return -EFAULT;
-}
-if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-	SAY("ERROR: bad peasycap: 0x%08lX\n", (unsigned long int) peasycap);
-	return -EFAULT;
-}
-if (NULL == peasycap->pusb_device) {
-	SAY("ERROR in easysnd_read(): peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-kd = isdongle(peasycap);
-if (0 <= kd && DONGLE_MANY > kd) {
-	if (mutex_lock_interruptible(&(easycap_dongle[kd].mutex_audio))) {
-		SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
-		return -ERESTARTSYS;
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
 	}
-	JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
-/*---------------------------------------------------------------------------*/
-/*
- *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
- *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
- *  IF NECESSARY, BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-	if (kd != isdongle(peasycap))
-		return -ERESTARTSYS;
-	if (NULL == file) {
-		SAY("ERROR:  file is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
+	prt = pss->runtime;
+	if (!prt) {
+		SAY("ERROR: substream.runtime is NULL\n");
+		return -EFAULT;
+	}
+	if (prt->dma_area) {
+		JOT(8, "prt->dma_area = %p\n", prt->dma_area);
+		vfree(prt->dma_area);
+		prt->dma_area = NULL;
+	} else
+		JOT(8, "dma_area already freed\n");
+	return 0;
+}
+/*****************************************************************************/
+static int easycap_alsa_prepare(struct snd_pcm_substream *pss)
+{
+	struct easycap *peasycap;
+	struct snd_pcm_runtime *prt;
+
+	JOT(4, "\n");
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
 	}
-	peasycap = file->private_data;
-	if (NULL == peasycap) {
+	prt = pss->runtime;
+	peasycap = snd_pcm_substream_chip(pss);
+	if (!peasycap) {
 		SAY("ERROR:  peasycap is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
+		return -EFAULT;
 	}
 	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
-		SAY("ERROR: bad peasycap: 0x%08lX\n", \
-						(unsigned long int) peasycap);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
+		SAY("ERROR: bad peasycap\n");
+		return -EFAULT;
 	}
-	if (NULL == peasycap->pusb_device) {
-		SAM("ERROR: peasycap->pusb_device is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
+
+	JOM(16, "ALSA decides %8i Hz=rate\n", pss->runtime->rate);
+	JOM(16, "ALSA decides %8ld =period_size\n", pss->runtime->period_size);
+	JOM(16, "ALSA decides %8i =periods\n", pss->runtime->periods);
+	JOM(16, "ALSA decides %8ld =buffer_size\n", pss->runtime->buffer_size);
+	JOM(16, "ALSA decides %8zd =dma_bytes\n", pss->runtime->dma_bytes);
+	JOM(16, "ALSA decides %8ld =boundary\n", pss->runtime->boundary);
+	JOM(16, "ALSA decides %8i =period_step\n", pss->runtime->period_step);
+	JOM(16, "ALSA decides %8i =sample_bits\n", pss->runtime->sample_bits);
+	JOM(16, "ALSA decides %8i =frame_bits\n", pss->runtime->frame_bits);
+	JOM(16, "ALSA decides %8ld =min_align\n", pss->runtime->min_align);
+	JOM(12, "ALSA decides %8ld =hw_ptr_base\n", pss->runtime->hw_ptr_base);
+	JOM(12, "ALSA decides %8ld =hw_ptr_interrupt\n",
+		pss->runtime->hw_ptr_interrupt);
+
+	if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
+		SAY("MISTAKE:  unexpected ALSA parameters\n");
+		return -ENOENT;
 	}
-} else {
-/*---------------------------------------------------------------------------*/
-/*
- *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
- *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
-*/
-/*---------------------------------------------------------------------------*/
-	return -ERESTARTSYS;
+	return 0;
 }
-/*---------------------------------------------------------------------------*/
-if (file->f_flags & O_NONBLOCK)
-	JOT(16, "NONBLOCK  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
-else
-	JOT(8, "BLOCKING  kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
-
-if ((0 > peasycap->audio_read) || \
-		(peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
-	SAM("ERROR: peasycap->audio_read out of range\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
-	return -EFAULT;
-}
-pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
-if ((struct data_buffer *)NULL == pdata_buffer) {
-	SAM("ERROR: pdata_buffer is NULL\n");
-	mutex_unlock(&easycap_dongle[kd].mutex_audio);
-	return -EFAULT;
+/*****************************************************************************/
+static int easycap_alsa_ack(struct snd_pcm_substream *pss)
+{
+	return 0;
 }
-JOM(12, "before wait, %i=frag read  %i=frag fill\n", \
-		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
-		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
-while ((fragment == (peasycap->audio_fill / \
-				peasycap->audio_pages_per_fragment)) || \
-		(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
-	if (file->f_flags & O_NONBLOCK) {
-		JOM(16, "returning -EAGAIN as instructed\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -EAGAIN;
+/*****************************************************************************/
+static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
+{
+	struct easycap *peasycap;
+	int retval;
+
+	JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
+	    SNDRV_PCM_TRIGGER_STOP);
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
+		return -EFAULT;
 	}
-	rc = wait_event_interruptible(peasycap->wq_audio, \
-		(peasycap->audio_idle  || peasycap->audio_eof   || \
-		((fragment != (peasycap->audio_fill / \
-				peasycap->audio_pages_per_fragment)) && \
-		(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
-	if (0 != rc) {
-		SAM("aborted by signal\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
+	peasycap = snd_pcm_substream_chip(pss);
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL\n");
+		return -EFAULT;
 	}
-	if (peasycap->audio_eof) {
-		JOM(8, "returning 0 because  %i=audio_eof\n", \
-							peasycap->audio_eof);
-		kill_audio_urbs(peasycap);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return 0;
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return -EFAULT;
 	}
-	if (peasycap->audio_idle) {
-		JOM(16, "returning 0 because  %i=audio_idle\n", \
-							peasycap->audio_idle);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START: {
+		peasycap->audio_idle = 0;
+		break;
 	}
-	if (!peasycap->audio_isoc_streaming) {
-		JOM(16, "returning 0 because audio urbs not streaming\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return 0;
+	case SNDRV_PCM_TRIGGER_STOP: {
+		peasycap->audio_idle = 1;
+		break;
 	}
+	default:
+		retval = -EINVAL;
+	}
+	return 0;
 }
-JOM(12, "after  wait, %i=frag read  %i=frag fill\n", \
-		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
-		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-szret = (size_t)0;
-while (fragment == (peasycap->audio_read / \
-				peasycap->audio_pages_per_fragment)) {
-	if (NULL == pdata_buffer->pgo) {
-		SAM("ERROR: pdata_buffer->pgo is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+/*****************************************************************************/
+static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss)
+{
+	struct easycap *peasycap;
+	snd_pcm_uframes_t offset;
+
+	JOT(16, "\n");
+	if (!pss) {
+		SAY("ERROR:  pss is NULL\n");
 		return -EFAULT;
 	}
-	if (NULL == pdata_buffer->pto) {
-		SAM("ERROR: pdata_buffer->pto is NULL\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+	peasycap = snd_pcm_substream_chip(pss);
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL\n");
 		return -EFAULT;
 	}
-	kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
-	if (0 > kount1) {
-		SAM("easysnd_read: MISTAKE: kount1 is negative\n");
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
-		return -ERESTARTSYS;
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return -EFAULT;
 	}
-	if (!kount1) {
-		(peasycap->audio_read)++;
-		if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
-			peasycap->audio_read = 0;
-		JOM(12, "bumped peasycap->audio_read to %i\n", \
-						peasycap->audio_read);
-
-		if (fragment != (peasycap->audio_read / \
-					peasycap->audio_pages_per_fragment))
-			break;
-
-		if ((0 > peasycap->audio_read) || \
-			(peasycap->audio_buffer_page_many <= \
-					peasycap->audio_read)) {
-			SAM("ERROR: peasycap->audio_read out of range\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
-		if ((struct data_buffer *)NULL == pdata_buffer) {
-			SAM("ERROR: pdata_buffer is NULL\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		if (NULL == pdata_buffer->pgo) {
-			SAM("ERROR: pdata_buffer->pgo is NULL\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		if (NULL == pdata_buffer->pto) {
-			SAM("ERROR: pdata_buffer->pto is NULL\n");
-			mutex_unlock(&easycap_dongle[kd].mutex_audio);
-			return -EFAULT;
-		}
-		kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
+	if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
+		JOM(8, "returning -EIO because  "
+		    "%i=audio_idle  %i=audio_eof\n",
+		    peasycap->audio_idle, peasycap->audio_eof);
+		return -EIO;
 	}
-	JOM(12, "ready  to send %li bytes\n", (long int) kount1);
-	JOM(12, "still  to send %li bytes\n", (long int) kount);
-	more = kount1;
-	if (more > kount)
-		more = kount;
-	JOM(12, "agreed to send %li bytes from page %i\n", \
-						more, peasycap->audio_read);
-	if (!more)
-		break;
+/*---------------------------------------------------------------------------*/
+	if (0 > peasycap->dma_read) {
+		JOM(8, "returning -EBUSY\n");
+		return -EBUSY;
+	}
+	offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
+	JOM(8, "ALSA decides %8i   =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
+	JOM(8, "ALSA decides %8i   =hw_ptr_interrupt\n",
+	    (int)pss->runtime->hw_ptr_interrupt);
+	JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n",
+	    (int)offset, peasycap->dma_read, peasycap->dma_next);
+	return offset;
+}
+/*****************************************************************************/
+static struct page *
+easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
+{
+	return vmalloc_to_page(pss->runtime->dma_area + offset);
+}
+/*****************************************************************************/
+
+static struct snd_pcm_ops easycap_alsa_pcm_ops = {
+	.open      = easycap_alsa_open,
+	.close     = easycap_alsa_close,
+	.ioctl     = snd_pcm_lib_ioctl,
+	.hw_params = easycap_alsa_hw_params,
+	.hw_free   = easycap_alsa_hw_free,
+	.prepare   = easycap_alsa_prepare,
+	.ack       = easycap_alsa_ack,
+	.trigger   = easycap_alsa_trigger,
+	.pointer   = easycap_alsa_pointer,
+	.page      = easycap_alsa_page,
+};
 
+/*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
- *  ACCUMULATE DYNAMIC-RANGE INFORMATION
- */
+ *  THE FUNCTION snd_card_create() HAS  THIS_MODULE  AS AN ARGUMENT.  THIS
+ *  MEANS MODULE easycap.  BEWARE.
+*/
 /*---------------------------------------------------------------------------*/
-	p0 = (unsigned char *)pdata_buffer->pgo;  l0 = 0;  lm = more/2;
-	while (l0 < lm) {
-		SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau, \
-				&peasycap->audio_square);  l0++;  p0 += 2;
+int easycap_alsa_probe(struct easycap *peasycap)
+{
+	int rc;
+	struct snd_card *psnd_card;
+	struct snd_pcm *psnd_pcm;
+
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -ENODEV;
 	}
-/*---------------------------------------------------------------------------*/
-	rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
-	if (0 != rc) {
-		SAM("ERROR: copy_to_user() returned %li\n", rc);
-		mutex_unlock(&easycap_dongle[kd].mutex_audio);
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
 		return -EFAULT;
 	}
-	*poff += (loff_t)more;
-	szret += (size_t)more;
-	pdata_buffer->pto += more;
-	puserspacebuffer += more;
-	kount -= (size_t)more;
-}
-JOM(12, "after  read, %i=frag read  %i=frag fill\n", \
-		(peasycap->audio_read / peasycap->audio_pages_per_fragment), \
-		(peasycap->audio_fill / peasycap->audio_pages_per_fragment));
-if (kount < 0) {
-	SAM("MISTAKE:  %li=kount  %li=szret\n", \
-					(long int)kount, (long int)szret);
+	if (0 > peasycap->minor) {
+		SAY("ERROR: no minor\n");
+		return -ENODEV;
+	}
+
+	peasycap->alsa_hardware = alsa_hardware;
+	if (peasycap->microphone) {
+		peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
+		peasycap->alsa_hardware.rate_min = 32000;
+		peasycap->alsa_hardware.rate_max = 32000;
+	} else {
+		peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
+		peasycap->alsa_hardware.rate_min = 48000;
+		peasycap->alsa_hardware.rate_max = 48000;
+	}
+
+	if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa",
+				THIS_MODULE, 0, &psnd_card)) {
+		SAY("ERROR: Cannot do ALSA snd_card_create()\n");
+		return -EFAULT;
+	}
+
+	sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
+	strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
+	strcpy(&psnd_card->shortname[0], "easycap_alsa");
+	sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
+
+	psnd_card->dev = &peasycap->pusb_device->dev;
+	psnd_card->private_data = peasycap;
+	peasycap->psnd_card = psnd_card;
+
+	rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
+	if (rc) {
+		SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
+		snd_card_free(psnd_card);
+		return -EFAULT;
+	}
+
+	snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&easycap_alsa_pcm_ops);
+	psnd_pcm->info_flags = 0;
+	strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
+	psnd_pcm->private_data = peasycap;
+	peasycap->psnd_pcm = psnd_pcm;
+	peasycap->psubstream = NULL;
+
+	rc = snd_card_register(psnd_card);
+	if (rc) {
+		SAM("ERROR: Cannot do ALSA snd_card_register()\n");
+		snd_card_free(psnd_card);
+		return -EFAULT;
+	}
+
+	SAM("registered %s\n", &psnd_card->id[0]);
+	return 0;
 }
+#endif /*! CONFIG_EASYCAP_OSS */
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
 /*---------------------------------------------------------------------------*/
 /*
- *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
+ *  COMMON AUDIO INITIALIZATION
  */
 /*---------------------------------------------------------------------------*/
-if (peasycap->audio_sample) {
-	below = peasycap->audio_sample;
-	above = peasycap->audio_square;
-	sdr = signed_div(above, below);
-	above = sdr.quotient;
-	mean = peasycap->audio_niveau;
-	sdr = signed_div(mean, peasycap->audio_sample);
-
-	JOM(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n", \
-				sdr.quotient, above, peasycap->audio_sample);
-
-	sdr = signed_div(above, 32768);
-	JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
-}
-/*---------------------------------------------------------------------------*/
-/*
- *  UPDATE THE AUDIO CLOCK
- */
+int
+easycap_sound_setup(struct easycap *peasycap)
+{
+	int rc;
+
+	JOM(4, "starting initialization\n");
+
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL.\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -ENODEV;
+	}
+	JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
+
+	rc = audio_setup(peasycap);
+	JOM(8, "audio_setup() returned %i\n", rc);
+
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device has become NULL\n");
+		return -ENODEV;
+	}
 /*---------------------------------------------------------------------------*/
-do_gettimeofday(&timeval);
-if (!peasycap->timeval1.tv_sec) {
-	peasycap->audio_bytes = 0;
-	peasycap->timeval3 = timeval;
-	peasycap->timeval1 = peasycap->timeval3;
-	sdr.quotient = 192000;
-} else {
-	peasycap->audio_bytes += (long long int) szret;
-	below = ((long long int)(1000000)) * \
-		((long long int)(timeval.tv_sec  - \
-						peasycap->timeval3.tv_sec)) + \
-		(long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
-	above = 1000000 * ((long long int) peasycap->audio_bytes);
-
-	if (below)
-		sdr = signed_div(above, below);
-	else
-		sdr.quotient = 192000;
-}
-JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
-peasycap->dnbydt = sdr.quotient;
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device has become NULL\n");
+		return -ENODEV;
+	}
+	rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
+			       peasycap->audio_altsetting_on);
+	JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
+	    peasycap->audio_altsetting_on, rc);
 
-JOM(8, "returning %li\n", (long int)szret);
-mutex_unlock(&easycap_dongle[kd].mutex_audio);
-return szret;
+	rc = wakeup_device(peasycap->pusb_device);
+	JOM(8, "wakeup_device() returned %i\n", rc);
+
+	peasycap->audio_eof = 0;
+	peasycap->audio_idle = 0;
+
+	peasycap->timeval1.tv_sec  = 0;
+	peasycap->timeval1.tv_usec = 0;
+
+	submit_audio_urbs(peasycap);
+
+	JOM(4, "finished initialization\n");
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -1042,120 +714,75 @@ return szret;
 int
 submit_audio_urbs(struct easycap *peasycap)
 {
-struct data_urb *pdata_urb;
-struct urb *purb;
-struct list_head *plist_head;
-int j, isbad, nospc, m, rc;
-int isbuf;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if ((struct list_head *)NULL == peasycap->purb_audio_head) {
-	SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
-	return -EFAULT;
-}
-if ((struct usb_device *)NULL == peasycap->pusb_device) {
-	SAM("ERROR: peasycap->pusb_device is NULL\n");
-	return -EFAULT;
-}
-if (!peasycap->audio_isoc_streaming) {
+	struct data_urb *pdata_urb;
+	struct urb *purb;
+	struct list_head *plist_head;
+	int j, isbad, nospc, m, rc;
+	int isbuf;
+
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (!peasycap->purb_audio_head) {
+		SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+
+	if (peasycap->audio_isoc_streaming) {
+		JOM(4, "already streaming audio urbs\n");
+		return 0;
+	}
+
 	JOM(4, "initial submission of all audio urbs\n");
 	rc = usb_set_interface(peasycap->pusb_device,
-					peasycap->audio_interface, \
-					peasycap->audio_altsetting_on);
-	JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", \
-					peasycap->audio_interface, \
-					peasycap->audio_altsetting_on, rc);
-
-	isbad = 0;  nospc = 0;  m = 0;
-	list_for_each(plist_head, (peasycap->purb_audio_head)) {
+			       peasycap->audio_interface,
+			       peasycap->audio_altsetting_on);
+	JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
+	    peasycap->audio_interface,
+	    peasycap->audio_altsetting_on, rc);
+
+	isbad = 0;
+	nospc = 0;
+	m = 0;
+	list_for_each(plist_head, peasycap->purb_audio_head) {
 		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-		if (NULL != pdata_urb) {
+		if (pdata_urb && pdata_urb->purb) {
 			purb = pdata_urb->purb;
-			if (NULL != purb) {
-				isbuf = pdata_urb->isbuf;
+			isbuf = pdata_urb->isbuf;
 
-				purb->interval = 1;
-				purb->dev = peasycap->pusb_device;
-				purb->pipe = \
-					usb_rcvisocpipe(peasycap->pusb_device,\
+			purb->interval = 1;
+			purb->dev = peasycap->pusb_device;
+			purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
 					peasycap->audio_endpointnumber);
-				purb->transfer_flags = URB_ISO_ASAP;
-				purb->transfer_buffer = \
-					peasycap->audio_isoc_buffer[isbuf].pgo;
-				purb->transfer_buffer_length = \
-					peasycap->audio_isoc_buffer_size;
-				purb->complete = easysnd_complete;
-				purb->context = peasycap;
-				purb->start_frame = 0;
-				purb->number_of_packets = \
-					peasycap->audio_isoc_framesperdesc;
-				for (j = 0;  j < peasycap->\
-						audio_isoc_framesperdesc; \
-									j++) {
-					purb->iso_frame_desc[j].offset = j * \
-						peasycap->\
-						audio_isoc_maxframesize;
-					purb->iso_frame_desc[j].length = \
-						peasycap->\
-						audio_isoc_maxframesize;
-				}
+			purb->transfer_flags = URB_ISO_ASAP;
+			purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
+			purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
+#ifdef CONFIG_EASYCAP_OSS
+			purb->complete = easyoss_complete;
+#else /* CONFIG_EASYCAP_OSS */
+			purb->complete = easycap_alsa_complete;
+#endif /* CONFIG_EASYCAP_OSS */
+			purb->context = peasycap;
+			purb->start_frame = 0;
+			purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
+			for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
+				purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize;
+				purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize;
+			}
 
-				rc = usb_submit_urb(purb, GFP_KERNEL);
-				if (0 != rc) {
-					isbad++;
-					SAM("ERROR: usb_submit_urb() failed" \
-							" for urb with rc:\n");
-					switch (rc) {
-					case -ENOMEM: {
-						SAM("-ENOMEM\n");
-						break;
-					}
-					case -ENODEV: {
-						SAM("-ENODEV\n");
-						break;
-					}
-					case -ENXIO: {
-						SAM("-ENXIO\n");
-						break;
-					}
-					case -EINVAL: {
-						SAM("-EINVAL\n");
-						break;
-					}
-					case -EAGAIN: {
-						SAM("-EAGAIN\n");
-						break;
-					}
-					case -EFBIG: {
-						SAM("-EFBIG\n");
-						break;
-					}
-					case -EPIPE: {
-						SAM("-EPIPE\n");
-						break;
-					}
-					case -EMSGSIZE: {
-						SAM("-EMSGSIZE\n");
-						break;
-					}
-					case -ENOSPC: {
-						nospc++;
-						break;
-					}
-					default: {
-						SAM("unknown error code %i\n",\
-								 rc);
-						break;
-					}
-					}
-				} else {
-					 m++;
-				}
-			} else {
+			rc = usb_submit_urb(purb, GFP_KERNEL);
+			if (rc) {
 				isbad++;
+				SAM("ERROR: usb_submit_urb() failed"
+				    " for urb with rc: -%s: %d\n",
+				    strerror(rc), rc);
+			} else {
+				m++;
 			}
 		} else {
 			isbad++;
@@ -1169,23 +796,17 @@ if (!peasycap->audio_isoc_streaming) {
 	if (isbad) {
 		JOM(4, "attempting cleanup instead of submitting\n");
 		list_for_each(plist_head, (peasycap->purb_audio_head)) {
-			pdata_urb = list_entry(plist_head, struct data_urb, \
-								list_head);
-			if (NULL != pdata_urb) {
-				purb = pdata_urb->purb;
-				if (NULL != purb)
-					usb_kill_urb(purb);
-			}
+			pdata_urb = list_entry(plist_head, struct data_urb, list_head);
+			if (pdata_urb && pdata_urb->purb)
+				usb_kill_urb(pdata_urb->purb);
 		}
 		peasycap->audio_isoc_streaming = 0;
 	} else {
-		peasycap->audio_isoc_streaming = 1;
+		peasycap->audio_isoc_streaming = m;
 		JOM(4, "submitted %i audio urbs\n", m);
 	}
-} else
-	JOM(4, "already streaming audio urbs\n");
 
-return 0;
+	return 0;
 }
 /*****************************************************************************/
 /*---------------------------------------------------------------------------*/
@@ -1196,38 +817,38 @@ return 0;
 int
 kill_audio_urbs(struct easycap *peasycap)
 {
-int m;
-struct list_head *plist_head;
-struct data_urb *pdata_urb;
+	int m;
+	struct list_head *plist_head;
+	struct data_urb *pdata_urb;
 
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return -EFAULT;
-}
-if (peasycap->audio_isoc_streaming) {
-	if ((struct list_head *)NULL != peasycap->purb_audio_head) {
-		peasycap->audio_isoc_streaming = 0;
-		JOM(4, "killing audio urbs\n");
-		m = 0;
-		list_for_each(plist_head, (peasycap->purb_audio_head)) {
-			pdata_urb = list_entry(plist_head, struct data_urb,
-								list_head);
-			if ((struct data_urb *)NULL != pdata_urb) {
-				if ((struct urb *)NULL != pdata_urb->purb) {
-					usb_kill_urb(pdata_urb->purb);
-					m++;
-				}
-			}
-		}
-		JOM(4, "%i audio urbs killed\n", m);
-	} else {
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return -EFAULT;
+	}
+
+	if (!peasycap->audio_isoc_streaming) {
+		JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n",
+		    peasycap->audio_isoc_streaming);
+		return 0;
+	}
+
+	if (!peasycap->purb_audio_head) {
 		SAM("ERROR: peasycap->purb_audio_head is NULL\n");
 		return -EFAULT;
 	}
-} else {
-	JOM(8, "%i=audio_isoc_streaming, no audio urbs killed\n", \
-					peasycap->audio_isoc_streaming);
-}
-return 0;
+
+	peasycap->audio_isoc_streaming = 0;
+	JOM(4, "killing audio urbs\n");
+	m = 0;
+	list_for_each(plist_head, (peasycap->purb_audio_head)) {
+		pdata_urb = list_entry(plist_head, struct data_urb, list_head);
+		if (pdata_urb && pdata_urb->purb) {
+			usb_kill_urb(pdata_urb->purb);
+			m++;
+		}
+	}
+	JOM(4, "%i audio urbs killed\n", m);
+
+	return 0;
 }
 /*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_sound.h b/drivers/staging/easycap/easycap_sound.h
deleted file mode 100644
index 4912739..0000000
--- a/drivers/staging/easycap/easycap_sound.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*****************************************************************************
-*                                                                            *
-*  easycap_sound.h                                                           *
-*                                                                            *
-*****************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The software is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-extern struct easycap *peasycap;
-extern struct usb_driver easycap_usb_driver;
diff --git a/drivers/staging/easycap/easycap_sound_oss.c b/drivers/staging/easycap/easycap_sound_oss.c
new file mode 100644
index 0000000..d92baf2
--- /dev/null
+++ b/drivers/staging/easycap/easycap_sound_oss.c
@@ -0,0 +1,954 @@
+/******************************************************************************
+*                                                                             *
+*  easycap_sound.c                                                            *
+*                                                                             *
+*  Audio driver for EasyCAP USB2.0 Video Capture Device DC60                  *
+*                                                                             *
+*                                                                             *
+******************************************************************************/
+/*
+ *
+ *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
+ *
+ *
+ *  This is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The software is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this software; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+*/
+/*****************************************************************************/
+
+#include "easycap.h"
+
+/*****************************************************************************/
+/****************************                       **************************/
+/****************************   Open Sound System   **************************/
+/****************************                       **************************/
+/*****************************************************************************/
+/*--------------------------------------------------------------------------*/
+/*
+ *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
+ */
+/*--------------------------------------------------------------------------*/
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
+ *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
+ *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
+ */
+/*---------------------------------------------------------------------------*/
+void
+easyoss_complete(struct urb *purb)
+{
+	struct easycap *peasycap;
+	struct data_buffer *paudio_buffer;
+	u8 *p1, *p2;
+	s16 tmp;
+	int i, j, more, much, leap, rc;
+#ifdef UPSAMPLE
+	int k;
+	s16 oldaudio, newaudio, delta;
+#endif /*UPSAMPLE*/
+
+	JOT(16, "\n");
+
+	if (!purb) {
+		SAY("ERROR: purb is NULL\n");
+		return;
+	}
+	peasycap = purb->context;
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return;
+	}
+	much = 0;
+	if (peasycap->audio_idle) {
+		JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
+		    peasycap->audio_idle, peasycap->audio_isoc_streaming);
+		if (peasycap->audio_isoc_streaming) {
+			rc = usb_submit_urb(purb, GFP_ATOMIC);
+			if (rc) {
+				if (-ENODEV != rc && -ENOENT != rc) {
+					SAM("ERROR: while %i=audio_idle, "
+					    "usb_submit_urb() failed with rc: -%s: %d\n",
+					    peasycap->audio_idle,
+					    strerror(rc), rc);
+				}
+			}
+		}
+		return;
+	}
+/*---------------------------------------------------------------------------*/
+	if (purb->status) {
+		if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
+			JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
+			return;
+		}
+		SAM("ERROR: non-zero urb status: -%s: %d\n",
+		    strerror(purb->status), purb->status);
+		goto resubmit;
+	}
+/*---------------------------------------------------------------------------*/
+/*
+ *  PROCEED HERE WHEN NO ERROR
+ */
+/*---------------------------------------------------------------------------*/
+#ifdef UPSAMPLE
+	oldaudio = peasycap->oldaudio;
+#endif /*UPSAMPLE*/
+
+	for (i = 0;  i < purb->number_of_packets; i++) {
+		if (!purb->iso_frame_desc[i].status) {
+
+			SAM("-%s\n", strerror(purb->iso_frame_desc[i].status));
+
+			more = purb->iso_frame_desc[i].actual_length;
+
+			if (!more)
+				peasycap->audio_mt++;
+			else {
+				if (peasycap->audio_mt) {
+					JOM(12, "%4i empty audio urb frames\n",
+					    peasycap->audio_mt);
+					peasycap->audio_mt = 0;
+				}
+
+				p1 = (u8 *)(purb->transfer_buffer + purb->iso_frame_desc[i].offset);
+
+				leap = 0;
+				p1 += leap;
+				more -= leap;
+				/*
+				 *  COPY more BYTES FROM ISOC BUFFER
+				 *  TO AUDIO BUFFER, CONVERTING
+				 *  8-BIT MONO TO 16-BIT SIGNED
+				 *  LITTLE-ENDIAN SAMPLES IF NECESSARY
+				 */
+				while (more) {
+					if (0 > more) {
+						SAM("MISTAKE: more is negative\n");
+						return;
+					}
+					if (peasycap->audio_buffer_page_many <= peasycap->audio_fill) {
+						SAM("ERROR: bad peasycap->audio_fill\n");
+						return;
+					}
+
+					paudio_buffer = &peasycap->audio_buffer[peasycap->audio_fill];
+					if (PAGE_SIZE < (paudio_buffer->pto - paudio_buffer->pgo)) {
+						SAM("ERROR: bad paudio_buffer->pto\n");
+						return;
+					}
+					if (PAGE_SIZE == (paudio_buffer->pto - paudio_buffer->pgo)) {
+
+						paudio_buffer->pto = paudio_buffer->pgo;
+						(peasycap->audio_fill)++;
+						if (peasycap->audio_buffer_page_many <= peasycap->audio_fill)
+							peasycap->audio_fill = 0;
+
+						JOM(8, "bumped peasycap->"
+						    "audio_fill to %i\n",
+						    peasycap->audio_fill);
+
+						paudio_buffer = &peasycap->audio_buffer[peasycap->audio_fill];
+						paudio_buffer->pto = paudio_buffer->pgo;
+
+						if (!(peasycap->audio_fill % peasycap->audio_pages_per_fragment)) {
+							JOM(12, "wakeup call on wq_audio, %i=frag reading  %i=fragment fill\n",
+							    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
+							    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
+							wake_up_interruptible(&(peasycap->wq_audio));
+						}
+					}
+
+					much = PAGE_SIZE - (int)(paudio_buffer->pto - paudio_buffer->pgo);
+
+					if (!peasycap->microphone) {
+						if (much > more)
+							much = more;
+
+						memcpy(paudio_buffer->pto, p1, much);
+						p1 += much;
+						more -= much;
+					} else {
+#ifdef UPSAMPLE
+						if (much % 16)
+							JOM(8, "MISTAKE? much"
+							    " is not divisible by 16\n");
+						if (much > (16 * more))
+							much = 16 * more;
+						p2 = (u8 *)paudio_buffer->pto;
+
+						for (j = 0;  j < (much/16);  j++) {
+							newaudio =  ((int) *p1) - 128;
+							newaudio = 128 * newaudio;
+
+							delta = (newaudio - oldaudio) / 4;
+							tmp = oldaudio + delta;
+
+							for (k = 0;  k < 4;  k++) {
+								*p2 = (0x00FF & tmp);
+								*(p2 + 1) = (0xFF00 & tmp) >> 8;
+								p2 += 2;
+								*p2 = (0x00FF & tmp);
+								*(p2 + 1) = (0xFF00 & tmp) >> 8;
+								p2 += 2;
+
+								tmp += delta;
+							}
+							p1++;
+							more--;
+							oldaudio = tmp;
+						}
+#else /*!UPSAMPLE*/
+						if (much > (2 * more))
+							much = 2 * more;
+						p2 = (u8 *)paudio_buffer->pto;
+
+						for (j = 0;  j < (much / 2);  j++) {
+							tmp =  ((int) *p1) - 128;
+							tmp = 128 * tmp;
+							*p2 = (0x00FF & tmp);
+							*(p2 + 1) = (0xFF00 & tmp) >> 8;
+							p1++;
+							p2 += 2;
+							more--;
+						}
+#endif /*UPSAMPLE*/
+					}
+					(paudio_buffer->pto) += much;
+				}
+			}
+		} else {
+			JOM(12, "discarding audio samples because "
+			    "%i=purb->iso_frame_desc[i].status\n",
+			    purb->iso_frame_desc[i].status);
+		}
+
+#ifdef UPSAMPLE
+		peasycap->oldaudio = oldaudio;
+#endif /*UPSAMPLE*/
+
+	}
+/*---------------------------------------------------------------------------*/
+/*
+ *  RESUBMIT THIS URB
+ */
+/*---------------------------------------------------------------------------*/
+resubmit:
+	if (peasycap->audio_isoc_streaming) {
+		rc = usb_submit_urb(purb, GFP_ATOMIC);
+		if (rc) {
+			if (-ENODEV != rc && -ENOENT != rc) {
+				SAM("ERROR: while %i=audio_idle, "
+				    "usb_submit_urb() failed "
+				    "with rc: -%s: %d\n", peasycap->audio_idle,
+				    strerror(rc), rc);
+			}
+		}
+	}
+	return;
+}
+/*****************************************************************************/
+/*---------------------------------------------------------------------------*/
+/*
+ *  THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
+ *  STREAM FROM /dev/easyoss1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
+ *  HAVE AN IOCTL INTERFACE.
+ */
+/*---------------------------------------------------------------------------*/
+static int easyoss_open(struct inode *inode, struct file *file)
+{
+	struct usb_interface *pusb_interface;
+	struct easycap *peasycap;
+	int subminor;
+	struct v4l2_device *pv4l2_device;
+
+	JOT(4, "begins\n");
+
+	subminor = iminor(inode);
+
+	pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
+	if (!pusb_interface) {
+		SAY("ERROR: pusb_interface is NULL\n");
+		SAY("ending unsuccessfully\n");
+		return -1;
+	}
+	peasycap = usb_get_intfdata(pusb_interface);
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		SAY("ending unsuccessfully\n");
+		return -1;
+	}
+/*---------------------------------------------------------------------------*/
+/*
+ *  SOME VERSIONS OF THE videodev MODULE OVERWRITE THE DATA WHICH HAS
+ *  BEEN WRITTEN BY THE CALL TO usb_set_intfdata() IN easycap_usb_probe(),
+ *  REPLACING IT WITH A POINTER TO THE EMBEDDED v4l2_device STRUCTURE.
+ *  TO DETECT THIS, THE STRING IN THE easycap.telltale[] BUFFER IS CHECKED.
+*/
+/*---------------------------------------------------------------------------*/
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		pv4l2_device = usb_get_intfdata(pusb_interface);
+		if (!pv4l2_device) {
+			SAY("ERROR: pv4l2_device is NULL\n");
+			return -EFAULT;
+		}
+		peasycap = container_of(pv4l2_device,
+				struct easycap, v4l2_device);
+	}
+/*---------------------------------------------------------------------------*/
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return -EFAULT;
+	}
+/*---------------------------------------------------------------------------*/
+
+	file->private_data = peasycap;
+
+	if (0 != easycap_sound_setup(peasycap)) {
+		;
+		;
+	}
+	return 0;
+}
+/*****************************************************************************/
+static int easyoss_release(struct inode *inode, struct file *file)
+{
+	struct easycap *peasycap;
+
+	JOT(4, "begins\n");
+
+	peasycap = file->private_data;
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL.\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return -EFAULT;
+	}
+	if (0 != kill_audio_urbs(peasycap)) {
+		SAM("ERROR: kill_audio_urbs() failed\n");
+		return -EFAULT;
+	}
+	JOM(4, "ending successfully\n");
+	return 0;
+}
+/*****************************************************************************/
+static ssize_t easyoss_read(struct file *file, char __user *puserspacebuffer,
+			    size_t kount, loff_t *poff)
+{
+	struct timeval timeval;
+	long long int above, below, mean;
+	struct signed_div_result sdr;
+	unsigned char *p0;
+	long int kount1, more, rc, l0, lm;
+	int fragment, kd;
+	struct easycap *peasycap;
+	struct data_buffer *pdata_buffer;
+	size_t szret;
+
+/*---------------------------------------------------------------------------*/
+/*
+ *  DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
+ *
+ ******************************************************************************
+ *****  N.B.  IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
+ *****        THIS CONDITION SIGNIFIES END-OF-FILE.                      ******
+ ******************************************************************************
+ */
+/*---------------------------------------------------------------------------*/
+
+	JOT(8, "%5zd=kount  %5lld=*poff\n", kount, *poff);
+
+	if (!file) {
+		SAY("ERROR:  file is NULL\n");
+		return -ERESTARTSYS;
+	}
+	peasycap = file->private_data;
+	if (!peasycap) {
+		SAY("ERROR in easyoss_read(): peasycap is NULL\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap: %p\n", peasycap);
+		return -EFAULT;
+	}
+	if (!peasycap->pusb_device) {
+		SAY("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	kd = isdongle(peasycap);
+	if (0 <= kd && DONGLE_MANY > kd) {
+		if (mutex_lock_interruptible(&(easycapdc60_dongle[kd].mutex_audio))) {
+			SAY("ERROR: "
+			    "cannot lock dongle[%i].mutex_audio\n", kd);
+			return -ERESTARTSYS;
+		}
+		JOM(4, "locked dongle[%i].mutex_audio\n", kd);
+		/*
+		 *  MEANWHILE, easycap_usb_disconnect()
+		 *  MAY HAVE FREED POINTER peasycap,
+		 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
+		 *  IF NECESSARY, BAIL OUT.
+		 */
+		if (kd != isdongle(peasycap))
+			return -ERESTARTSYS;
+		if (!file) {
+			SAY("ERROR:  file is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		peasycap = file->private_data;
+		if (!peasycap) {
+			SAY("ERROR:  peasycap is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+			SAY("ERROR: bad peasycap: %p\n", peasycap);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		if (!peasycap->pusb_device) {
+			SAM("ERROR: peasycap->pusb_device is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+	} else {
+		/*
+		 *  IF easycap_usb_disconnect()
+		 *  HAS ALREADY FREED POINTER peasycap BEFORE THE
+		 *  ATTEMPT TO ACQUIRE THE SEMAPHORE,
+		 *  isdongle() WILL HAVE FAILED.  BAIL OUT.
+		 */
+		return -ERESTARTSYS;
+	}
+/*---------------------------------------------------------------------------*/
+	JOT(16, "%sBLOCKING kount=%zd, *poff=%lld\n",
+		(file->f_flags & O_NONBLOCK) ? "NON" : "", kount, *poff);
+
+	if ((0 > peasycap->audio_read) ||
+	    (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
+		SAM("ERROR: peasycap->audio_read out of range\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+		return -EFAULT;
+	}
+	pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
+	if (!pdata_buffer) {
+		SAM("ERROR: pdata_buffer is NULL\n");
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+		return -EFAULT;
+	}
+	JOM(12, "before wait, %i=frag read  %i=frag fill\n",
+	    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
+	    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
+	fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
+	while ((fragment == (peasycap->audio_fill / peasycap->audio_pages_per_fragment)) ||
+		(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
+		if (file->f_flags & O_NONBLOCK) {
+			JOM(16, "returning -EAGAIN as instructed\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EAGAIN;
+		}
+		rc = wait_event_interruptible(peasycap->wq_audio,
+				(peasycap->audio_idle  || peasycap->audio_eof ||
+				((fragment !=
+					(peasycap->audio_fill / peasycap->audio_pages_per_fragment)) &&
+				(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
+		if (rc) {
+			SAM("aborted by signal\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		if (peasycap->audio_eof) {
+			JOM(8, "returning 0 because  %i=audio_eof\n",
+			    peasycap->audio_eof);
+			kill_audio_urbs(peasycap);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return 0;
+		}
+		if (peasycap->audio_idle) {
+			JOM(16, "returning 0 because  %i=audio_idle\n",
+			    peasycap->audio_idle);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return 0;
+		}
+		if (!peasycap->audio_isoc_streaming) {
+			JOM(16, "returning 0 because audio urbs not streaming\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return 0;
+		}
+	}
+	JOM(12, "after  wait, %i=frag read  %i=frag fill\n",
+	    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
+	    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
+	szret = (size_t)0;
+	fragment = (peasycap->audio_read / peasycap->audio_pages_per_fragment);
+	while (fragment == (peasycap->audio_read / peasycap->audio_pages_per_fragment)) {
+		if (!pdata_buffer->pgo) {
+			SAM("ERROR: pdata_buffer->pgo is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		if (!pdata_buffer->pto) {
+			SAM("ERROR: pdata_buffer->pto is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
+		if (0 > kount1) {
+			SAM("MISTAKE: kount1 is negative\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		if (!kount1) {
+			peasycap->audio_read++;
+			if (peasycap->audio_buffer_page_many <= peasycap->audio_read)
+				peasycap->audio_read = 0;
+			JOM(12, "bumped peasycap->audio_read to %i\n",
+			    peasycap->audio_read);
+
+			if (fragment != (peasycap->audio_read / peasycap->audio_pages_per_fragment))
+				break;
+
+			if ((0 > peasycap->audio_read) ||
+			    (peasycap->audio_buffer_page_many <= peasycap->audio_read)) {
+				SAM("ERROR: peasycap->audio_read out of range\n");
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+				return -EFAULT;
+			}
+			pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
+			if (!pdata_buffer) {
+				SAM("ERROR: pdata_buffer is NULL\n");
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+				return -EFAULT;
+			}
+			if (!pdata_buffer->pgo) {
+				SAM("ERROR: pdata_buffer->pgo is NULL\n");
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+				return -EFAULT;
+			}
+			if (!pdata_buffer->pto) {
+				SAM("ERROR: pdata_buffer->pto is NULL\n");
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+				return -EFAULT;
+			}
+			kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
+		}
+		JOM(12, "ready  to send %zd bytes\n", kount1);
+		JOM(12, "still  to send %li bytes\n", (long int) kount);
+		more = kount1;
+		if (more > kount)
+			more = kount;
+		JOM(12, "agreed to send %li bytes from page %i\n",
+		    more, peasycap->audio_read);
+		if (!more)
+			break;
+
+		/*
+		 *  ACCUMULATE DYNAMIC-RANGE INFORMATION
+		 */
+		p0 = (unsigned char *)pdata_buffer->pgo;
+		l0 = 0;
+		lm = more/2;
+		while (l0 < lm) {
+			SUMMER(p0, &peasycap->audio_sample,
+				&peasycap->audio_niveau,
+				&peasycap->audio_square);
+			l0++;
+			p0 += 2;
+		}
+		/*-----------------------------------------------------------*/
+		rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
+		if (rc) {
+			SAM("ERROR: copy_to_user() returned %li\n", rc);
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		*poff += (loff_t)more;
+		szret += (size_t)more;
+		pdata_buffer->pto += more;
+		puserspacebuffer += more;
+		kount -= (size_t)more;
+	}
+	JOM(12, "after  read, %i=frag read  %i=frag fill\n",
+	    (peasycap->audio_read / peasycap->audio_pages_per_fragment),
+	    (peasycap->audio_fill / peasycap->audio_pages_per_fragment));
+	if (kount < 0) {
+		SAM("MISTAKE:  %li=kount  %li=szret\n",
+		    (long int)kount, (long int)szret);
+	}
+/*---------------------------------------------------------------------------*/
+/*
+ *  CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
+ */
+/*---------------------------------------------------------------------------*/
+	if (peasycap->audio_sample) {
+		below = peasycap->audio_sample;
+		above = peasycap->audio_square;
+		sdr = signed_div(above, below);
+		above = sdr.quotient;
+		mean = peasycap->audio_niveau;
+		sdr = signed_div(mean, peasycap->audio_sample);
+
+		JOM(8, "%8lli=mean  %8lli=meansquare after %lli samples, =>\n",
+		    sdr.quotient, above, peasycap->audio_sample);
+
+		sdr = signed_div(above, 32768);
+		JOM(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
+	}
+/*---------------------------------------------------------------------------*/
+/*
+ *  UPDATE THE AUDIO CLOCK
+ */
+/*---------------------------------------------------------------------------*/
+	do_gettimeofday(&timeval);
+	if (!peasycap->timeval1.tv_sec) {
+		peasycap->audio_bytes = 0;
+		peasycap->timeval3 = timeval;
+		peasycap->timeval1 = peasycap->timeval3;
+		sdr.quotient = 192000;
+	} else {
+		peasycap->audio_bytes += (long long int) szret;
+		below = ((long long int)(1000000)) *
+			((long long int)(timeval.tv_sec  - peasycap->timeval3.tv_sec)) +
+			(long long int)(timeval.tv_usec - peasycap->timeval3.tv_usec);
+		above = 1000000 * ((long long int) peasycap->audio_bytes);
+
+		if (below)
+			sdr = signed_div(above, below);
+		else
+			sdr.quotient = 192000;
+	}
+	JOM(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
+	peasycap->dnbydt = sdr.quotient;
+
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+	JOM(4, "unlocked easycapdc60_dongle[%i].mutex_audio\n", kd);
+	JOM(8, "returning %li\n", (long int)szret);
+	return szret;
+
+}
+/*---------------------------------------------------------------------------*/
+static long easyoss_unlocked_ioctl(struct file *file,
+				   unsigned int cmd, unsigned long arg)
+{
+	struct easycap *peasycap;
+	struct usb_device *p;
+	int kd;
+
+	if (!file) {
+		SAY("ERROR:  file is NULL\n");
+		return -ERESTARTSYS;
+	}
+	peasycap = file->private_data;
+	if (!peasycap) {
+		SAY("ERROR:  peasycap is NULL.\n");
+		return -EFAULT;
+	}
+	if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+		SAY("ERROR: bad peasycap\n");
+		return -EFAULT;
+	}
+	p = peasycap->pusb_device;
+	if (!p) {
+		SAM("ERROR: peasycap->pusb_device is NULL\n");
+		return -EFAULT;
+	}
+	kd = isdongle(peasycap);
+	if (0 <= kd && DONGLE_MANY > kd) {
+		if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
+			SAY("ERROR: cannot lock "
+			    "easycapdc60_dongle[%i].mutex_audio\n", kd);
+			return -ERESTARTSYS;
+		}
+		JOM(4, "locked easycapdc60_dongle[%i].mutex_audio\n", kd);
+		/*
+		 *  MEANWHILE, easycap_usb_disconnect()
+		 *  MAY HAVE FREED POINTER peasycap,
+		 *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
+		 *  IF NECESSARY, BAIL OUT.
+		*/
+		if (kd != isdongle(peasycap))
+			return -ERESTARTSYS;
+		if (!file) {
+			SAY("ERROR:  file is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		peasycap = file->private_data;
+		if (!peasycap) {
+			SAY("ERROR:  peasycap is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+		if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
+			SAY("ERROR: bad peasycap\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		p = peasycap->pusb_device;
+		if (!peasycap->pusb_device) {
+			SAM("ERROR: peasycap->pusb_device is NULL\n");
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -ERESTARTSYS;
+		}
+	} else {
+		/*
+		 *  IF easycap_usb_disconnect()
+		 *  HAS ALREADY FREED POINTER peasycap BEFORE THE
+		 *  ATTEMPT TO ACQUIRE THE SEMAPHORE,
+		 *  isdongle() WILL HAVE FAILED.  BAIL OUT.
+		 */
+		return -ERESTARTSYS;
+	}
+/*---------------------------------------------------------------------------*/
+	switch (cmd) {
+	case SNDCTL_DSP_GETCAPS: {
+		int caps;
+		JOM(8, "SNDCTL_DSP_GETCAPS\n");
+
+#ifdef UPSAMPLE
+		if (peasycap->microphone)
+			caps = 0x04400000;
+		else
+			caps = 0x04400000;
+#else
+		if (peasycap->microphone)
+			caps = 0x02400000;
+		else
+			caps = 0x04400000;
+#endif /*UPSAMPLE*/
+
+		if (copy_to_user((void __user *)arg, &caps, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case SNDCTL_DSP_GETFMTS: {
+		int incoming;
+		JOM(8, "SNDCTL_DSP_GETFMTS\n");
+
+#ifdef UPSAMPLE
+		if (peasycap->microphone)
+			incoming = AFMT_S16_LE;
+		else
+			incoming = AFMT_S16_LE;
+#else
+		if (peasycap->microphone)
+			incoming = AFMT_S16_LE;
+		else
+			incoming = AFMT_S16_LE;
+#endif /*UPSAMPLE*/
+
+		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case SNDCTL_DSP_SETFMT: {
+		int incoming, outgoing;
+		JOM(8, "SNDCTL_DSP_SETFMT\n");
+		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		JOM(8, "........... %i=incoming\n", incoming);
+
+#ifdef UPSAMPLE
+		if (peasycap->microphone)
+			outgoing = AFMT_S16_LE;
+		else
+			outgoing = AFMT_S16_LE;
+#else
+		if (peasycap->microphone)
+			outgoing = AFMT_S16_LE;
+		else
+			outgoing = AFMT_S16_LE;
+#endif /*UPSAMPLE*/
+
+		if (incoming != outgoing) {
+			JOM(8, "........... %i=outgoing\n", outgoing);
+			JOM(8, "        cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
+			JOM(8, "        cf. %i=AFMT_U8\n", AFMT_U8);
+			if (copy_to_user((void __user *)arg, &outgoing, sizeof(int))) {
+				mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+				return -EFAULT;
+			}
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EINVAL ;
+		}
+		break;
+	}
+	case SNDCTL_DSP_STEREO: {
+		int incoming;
+		JOM(8, "SNDCTL_DSP_STEREO\n");
+		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		JOM(8, "........... %i=incoming\n", incoming);
+
+#ifdef UPSAMPLE
+		if (peasycap->microphone)
+			incoming = 1;
+		else
+			incoming = 1;
+#else
+		if (peasycap->microphone)
+			incoming = 0;
+		else
+			incoming = 1;
+#endif /*UPSAMPLE*/
+
+		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case SNDCTL_DSP_SPEED: {
+		int incoming;
+		JOM(8, "SNDCTL_DSP_SPEED\n");
+		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		JOM(8, "........... %i=incoming\n", incoming);
+
+#ifdef UPSAMPLE
+		if (peasycap->microphone)
+			incoming = 32000;
+		else
+			incoming = 48000;
+#else
+		if (peasycap->microphone)
+			incoming = 8000;
+		else
+			incoming = 48000;
+#endif /*UPSAMPLE*/
+
+		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case SNDCTL_DSP_GETTRIGGER: {
+		int incoming;
+		JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
+		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		JOM(8, "........... %i=incoming\n", incoming);
+
+		incoming = PCM_ENABLE_INPUT;
+		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case SNDCTL_DSP_SETTRIGGER: {
+		int incoming;
+		JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
+		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		JOM(8, "........... %i=incoming\n", incoming);
+		JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT "
+		    "0x%x=PCM_ENABLE_OUTPUT\n",
+		    PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
+		;
+		;
+		;
+		;
+		break;
+	}
+	case SNDCTL_DSP_GETBLKSIZE: {
+		int incoming;
+		JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
+		if (copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		JOM(8, "........... %i=incoming\n", incoming);
+		incoming = peasycap->audio_bytes_per_fragment;
+		if (copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case SNDCTL_DSP_GETISPACE: {
+		struct audio_buf_info audio_buf_info;
+
+		JOM(8, "SNDCTL_DSP_GETISPACE\n");
+
+		audio_buf_info.bytes      = peasycap->audio_bytes_per_fragment;
+		audio_buf_info.fragments  = 1;
+		audio_buf_info.fragsize   = 0;
+		audio_buf_info.fragstotal = 0;
+
+		if (copy_to_user((void __user *)arg, &audio_buf_info, sizeof(int))) {
+			mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+			return -EFAULT;
+		}
+		break;
+	}
+	case 0x00005401:
+	case 0x00005402:
+	case 0x00005403:
+	case 0x00005404:
+	case 0x00005405:
+	case 0x00005406: {
+		JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+		return -ENOIOCTLCMD;
+	}
+	default: {
+		JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
+		mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+		return -ENOIOCTLCMD;
+	}
+	}
+	mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
+	return 0;
+}
+/*****************************************************************************/
+
+static const struct file_operations easyoss_fops = {
+	.owner		= THIS_MODULE,
+	.open		= easyoss_open,
+	.release	= easyoss_release,
+	.unlocked_ioctl	= easyoss_unlocked_ioctl,
+	.read		= easyoss_read,
+	.llseek		= no_llseek,
+};
+struct usb_class_driver easyoss_class = {
+	.name = "usb/easyoss%d",
+	.fops = &easyoss_fops,
+	.minor_base = USB_SKEL_MINOR_BASE,
+};
+/*****************************************************************************/
diff --git a/drivers/staging/easycap/easycap_standard.h b/drivers/staging/easycap/easycap_standard.h
deleted file mode 100644
index cadc8d2..0000000
--- a/drivers/staging/easycap/easycap_standard.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*****************************************************************************
-*                                                                            *
-*  easycap_standard.h                                                        *
-*                                                                            *
-*****************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The software is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-extern struct easycap_standard easycap_standard[];
diff --git a/drivers/staging/easycap/easycap_testcard.c b/drivers/staging/easycap/easycap_testcard.c
index e27dfe9..0f71470 100644
--- a/drivers/staging/easycap/easycap_testcard.c
+++ b/drivers/staging/easycap/easycap_testcard.c
@@ -26,397 +26,130 @@
 /*****************************************************************************/
 
 #include "easycap.h"
-#include "easycap_debug.h"
 
 /*****************************************************************************/
 #define TESTCARD_BYTESPERLINE (2 * 720)
 void
 easycap_testcard(struct easycap *peasycap, int field)
 {
-int total;
-int y, u, v, r, g, b;
-unsigned char uyvy[4];
-int i1, line, k, m, n, more, much, barwidth, barheight;
-unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2;
-struct data_buffer *pfield_buffer;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
-	return;
-}
-JOM(8, "%i=field\n", field);
-switch (peasycap->width) {
-case 720:
-case 360: {
-	barwidth = (2 * 720) / 8;
-	break;
-}
-case 704:
-case 352: {
-	barwidth = (2 * 704) / 8;
-	break;
-}
-case 640:
-case 320: {
-	barwidth = (2 * 640) / 8;
-	break;
-}
-default: {
-	SAM("ERROR:  cannot set barwidth\n");
-	return;
-}
-}
-if (TESTCARD_BYTESPERLINE < barwidth) {
-	SAM("ERROR: barwidth is too large\n");
-	return;
-}
-switch (peasycap->height) {
-case 576:
-case 288: {
-	barheight = 576;
-	break;
-}
-case 480:
-case 240: {
-	barheight = 480;
-	break;
-}
-default: {
-	SAM("ERROR: cannot set barheight\n");
-	return;
-}
-}
-total = 0;
-k = field;
-m = 0;
-n = 0;
-
-for (line = 0;  line < (barheight / 2);  line++) {
-	for (i1 = 0;  i1 < 8;  i1++) {
-		r = (i1 * 256)/8;
-		g = (i1 * 256)/8;
-		b = (i1 * 256)/8;
-
-		y =  299*r/1000 + 587*g/1000 + 114*b/1000 ;
-		u = -147*r/1000 - 289*g/1000 + 436*b/1000 ;  u = u + 128;
-		v =  615*r/1000 - 515*g/1000 - 100*b/1000 ;  v = v + 128;
-
-		uyvy[0] =  0xFF & u ;
-		uyvy[1] =  0xFF & y ;
-		uyvy[2] =  0xFF & v ;
-		uyvy[3] =  0xFF & y ;
-
-		p1 = &bfbar[0];
-		while (p1 < &bfbar[barwidth]) {
-			*p1++ = uyvy[0] ;
-			*p1++ = uyvy[1] ;
-			*p1++ = uyvy[2] ;
-			*p1++ = uyvy[3] ;
-			total += 4;
-			}
-
-		p1 = &bfbar[0];
-		more = barwidth;
-
-		while (more) {
-			if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) {
-				SAM("ERROR:  bad m reached\n");
-				return;
+	int total;
+	int y, u, v, r, g, b;
+	unsigned char uyvy[4];
+	int i1, line, k, m, n, more, much, barwidth, barheight;
+	unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2;
+	struct data_buffer *pfield_buffer;
+
+	if (!peasycap) {
+		SAY("ERROR: peasycap is NULL\n");
+		return;
+	}
+	JOM(8, "%i=field\n", field);
+	switch (peasycap->width) {
+	case 720:
+	case 360: {
+		barwidth = (2 * 720) / 8;
+		break;
+	}
+	case 704:
+	case 352: {
+		barwidth = (2 * 704) / 8;
+		break;
+	}
+	case 640:
+	case 320: {
+		barwidth = (2 * 640) / 8;
+		break;
+	}
+	default: {
+		SAM("ERROR:  cannot set barwidth\n");
+		return;
+	}
+	}
+	if (TESTCARD_BYTESPERLINE < barwidth) {
+		SAM("ERROR: barwidth is too large\n");
+		return;
+	}
+	switch (peasycap->height) {
+	case 576:
+	case 288: {
+		barheight = 576;
+		break;
+	}
+	case 480:
+	case 240: {
+		barheight = 480;
+		break;
+	}
+	default: {
+		SAM("ERROR: cannot set barheight\n");
+		return;
+	}
+	}
+	total = 0;
+	k = field;
+	m = 0;
+	n = 0;
+
+	for (line = 0;  line < (barheight / 2);  line++) {
+		for (i1 = 0;  i1 < 8;  i1++) {
+			r = (i1 * 256)/8;
+			g = (i1 * 256)/8;
+			b = (i1 * 256)/8;
+
+			y =  299*r/1000 + 587*g/1000 + 114*b/1000 ;
+			u = -147*r/1000 - 289*g/1000 + 436*b/1000 ;
+			u = u + 128;
+			v =  615*r/1000 - 515*g/1000 - 100*b/1000 ;
+			v = v + 128;
+
+			uyvy[0] =  0xFF & u ;
+			uyvy[1] =  0xFF & y ;
+			uyvy[2] =  0xFF & v ;
+			uyvy[3] =  0xFF & y ;
+
+			p1 = &bfbar[0];
+			while (p1 < &bfbar[barwidth]) {
+				*p1++ = uyvy[0] ;
+				*p1++ = uyvy[1] ;
+				*p1++ = uyvy[2] ;
+				*p1++ = uyvy[3] ;
+				total += 4;
 			}
-		if (PAGE_SIZE < n) {
-			SAM("ERROR:  bad n reached\n"); return;
-		}
 
-		if (0 > more) {
-			SAM("ERROR:  internal fault\n");
-			return;
-		}
-
-		much = PAGE_SIZE - n;
-		if (much > more)
-			much = more;
-		pfield_buffer = &peasycap->field_buffer[k][m];
-		p2 = pfield_buffer->pgo + n;
-		memcpy(p2, p1, much);
-
-		p1 += much;
-		n += much;
-		more -= much;
-		if (PAGE_SIZE == n) {
-			m++;
-			n = 0;
+			p1 = &bfbar[0];
+			more = barwidth;
+
+			while (more) {
+				if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) {
+					SAM("ERROR:  bad m reached\n");
+					return;
+				}
+				if (PAGE_SIZE < n) {
+					SAM("ERROR:  bad n reached\n");
+					return;
+				}
+
+				if (0 > more) {
+					SAM("ERROR:  internal fault\n");
+					return;
+				}
+
+				much = PAGE_SIZE - n;
+				if (much > more)
+					much = more;
+				pfield_buffer = &peasycap->field_buffer[k][m];
+				p2 = pfield_buffer->pgo + n;
+				memcpy(p2, p1, much);
+
+				p1 += much;
+				n += much;
+				more -= much;
+				if (PAGE_SIZE == n) {
+					m++;
+					n = 0;
+				}
 			}
 		}
 	}
-}
-return;
-}
-/*****************************************************************************/
-#if defined(EASYCAP_TESTTONE)
-/*-----------------------------------------------------------------------------
-THE tones[] ARRAY BELOW IS THE OUTPUT OF THIS PROGRAM,
-COMPILED gcc -o prog -lm prog.c
-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-#include <stdio.h>
-#include <math.h>
-
-int main(void);
-int
-main(void)
-{
-int i1, i2, last;
-double d1, d2;
-
-last = 1024 - 1;
-d1 = 10.0*3.14159265/1024.0;
-printf("int tones[2048] =\n{\n");
-for (i1 = 0;  i1 <= last;  i1++)
-	{
-	d2 = ((double)i1) * d1;
-	i2 = (int)(16384.0*sin(d2));
-
-	if (last != i1)
-		{
-		printf("%6i, ", i2);  printf("%6i, ", i2);
-		if (!((i1 + 1)%5)) printf("\n");
-		}
-	else
-		{
-		printf("%6i, ", i2);  printf("%6i\n};\n", i2);
-		}
-	}
-return 0;
-}
------------------------------------------------------------------------------*/
-int tones[2048] = {
-0,     0,   502,   502,  1004,  1004,  1505,  1505,  2005,  2005,
-2503,  2503,  2998,  2998,  3491,  3491,  3980,  3980,  4466,  4466,
-4948,  4948,  5424,  5424,  5896,  5896,  6362,  6362,  6822,  6822,
-7276,  7276,  7723,  7723,  8162,  8162,  8594,  8594,  9018,  9018,
-9434,  9434,  9840,  9840, 10237, 10237, 10625, 10625, 11002, 11002,
-11370, 11370, 11726, 11726, 12072, 12072, 12406, 12406, 12728, 12728,
-13038, 13038, 13337, 13337, 13622, 13622, 13895, 13895, 14155, 14155,
-14401, 14401, 14634, 14634, 14853, 14853, 15058, 15058, 15249, 15249,
-15426, 15426, 15588, 15588, 15735, 15735, 15868, 15868, 15985, 15985,
-16088, 16088, 16175, 16175, 16248, 16248, 16305, 16305, 16346, 16346,
-16372, 16372, 16383, 16383, 16379, 16379, 16359, 16359, 16323, 16323,
-16272, 16272, 16206, 16206, 16125, 16125, 16028, 16028, 15917, 15917,
-15790, 15790, 15649, 15649, 15492, 15492, 15322, 15322, 15136, 15136,
-14937, 14937, 14723, 14723, 14496, 14496, 14255, 14255, 14001, 14001,
-13733, 13733, 13452, 13452, 13159, 13159, 12854, 12854, 12536, 12536,
-12207, 12207, 11866, 11866, 11513, 11513, 11150, 11150, 10777, 10777,
-10393, 10393, 10000, 10000,  9597,  9597,  9185,  9185,  8765,  8765,
-8336,  8336,  7900,  7900,  7456,  7456,  7005,  7005,  6547,  6547,
-6083,  6083,  5614,  5614,  5139,  5139,  4659,  4659,  4175,  4175,
-3687,  3687,  3196,  3196,  2701,  2701,  2204,  2204,  1705,  1705,
-1205,  1205,   703,   703,   201,   201,  -301,  -301,  -803,  -803,
--1305, -1305, -1805, -1805, -2304, -2304, -2801, -2801, -3294, -3294,
--3785, -3785, -4272, -4272, -4756, -4756, -5234, -5234, -5708, -5708,
--6176, -6176, -6639, -6639, -7095, -7095, -7545, -7545, -7988, -7988,
--8423, -8423, -8850, -8850, -9268, -9268, -9679, -9679, -10079, -10079,
--10471, -10471, -10853, -10853, -11224, -11224, -11585, -11585, -11935, -11935,
--12273, -12273, -12600, -12600, -12916, -12916, -13219, -13219, -13510, -13510,
--13788, -13788, -14053, -14053, -14304, -14304, -14543, -14543, -14767, -14767,
--14978, -14978, -15175, -15175, -15357, -15357, -15525, -15525, -15678, -15678,
--15817, -15817, -15940, -15940, -16049, -16049, -16142, -16142, -16221, -16221,
--16284, -16284, -16331, -16331, -16364, -16364, -16381, -16381, -16382, -16382,
--16368, -16368, -16339, -16339, -16294, -16294, -16234, -16234, -16159, -16159,
--16069, -16069, -15963, -15963, -15842, -15842, -15707, -15707, -15557, -15557,
--15392, -15392, -15212, -15212, -15018, -15018, -14810, -14810, -14589, -14589,
--14353, -14353, -14104, -14104, -13842, -13842, -13566, -13566, -13278, -13278,
--12977, -12977, -12665, -12665, -12340, -12340, -12003, -12003, -11656, -11656,
--11297, -11297, -10928, -10928, -10548, -10548, -10159, -10159, -9759, -9759,
--9351, -9351, -8934, -8934, -8509, -8509, -8075, -8075, -7634, -7634,
--7186, -7186, -6731, -6731, -6269, -6269, -5802, -5802, -5329, -5329,
--4852, -4852, -4369, -4369, -3883, -3883, -3393, -3393, -2900, -2900,
--2404, -2404, -1905, -1905, -1405, -1405,  -904,  -904,  -402,  -402,
-100,   100,   603,   603,  1105,  1105,  1605,  1605,  2105,  2105,
-2602,  2602,  3097,  3097,  3589,  3589,  4078,  4078,  4563,  4563,
-5043,  5043,  5519,  5519,  5990,  5990,  6455,  6455,  6914,  6914,
-7366,  7366,  7811,  7811,  8249,  8249,  8680,  8680,  9102,  9102,
-9516,  9516,  9920,  9920, 10315, 10315, 10701, 10701, 11077, 11077,
-11442, 11442, 11796, 11796, 12139, 12139, 12471, 12471, 12791, 12791,
-13099, 13099, 13395, 13395, 13678, 13678, 13948, 13948, 14205, 14205,
-14449, 14449, 14679, 14679, 14895, 14895, 15098, 15098, 15286, 15286,
-15459, 15459, 15618, 15618, 15763, 15763, 15892, 15892, 16007, 16007,
-16107, 16107, 16191, 16191, 16260, 16260, 16314, 16314, 16353, 16353,
-16376, 16376, 16384, 16384, 16376, 16376, 16353, 16353, 16314, 16314,
-16260, 16260, 16191, 16191, 16107, 16107, 16007, 16007, 15892, 15892,
-15763, 15763, 15618, 15618, 15459, 15459, 15286, 15286, 15098, 15098,
-14895, 14895, 14679, 14679, 14449, 14449, 14205, 14205, 13948, 13948,
-13678, 13678, 13395, 13395, 13099, 13099, 12791, 12791, 12471, 12471,
-12139, 12139, 11796, 11796, 11442, 11442, 11077, 11077, 10701, 10701,
-10315, 10315,  9920,  9920,  9516,  9516,  9102,  9102,  8680,  8680,
-8249,  8249,  7811,  7811,  7366,  7366,  6914,  6914,  6455,  6455,
-5990,  5990,  5519,  5519,  5043,  5043,  4563,  4563,  4078,  4078,
-3589,  3589,  3097,  3097,  2602,  2602,  2105,  2105,  1605,  1605,
-1105,  1105,   603,   603,   100,   100,  -402,  -402,  -904,  -904,
--1405, -1405, -1905, -1905, -2404, -2404, -2900, -2900, -3393, -3393,
--3883, -3883, -4369, -4369, -4852, -4852, -5329, -5329, -5802, -5802,
--6269, -6269, -6731, -6731, -7186, -7186, -7634, -7634, -8075, -8075,
--8509, -8509, -8934, -8934, -9351, -9351, -9759, -9759, -10159, -10159,
--10548, -10548, -10928, -10928, -11297, -11297, -11656, -11656, -12003, -12003,
--12340, -12340, -12665, -12665, -12977, -12977, -13278, -13278, -13566, -13566,
--13842, -13842, -14104, -14104, -14353, -14353, -14589, -14589, -14810, -14810,
--15018, -15018, -15212, -15212, -15392, -15392, -15557, -15557, -15707, -15707,
--15842, -15842, -15963, -15963, -16069, -16069, -16159, -16159, -16234, -16234,
--16294, -16294, -16339, -16339, -16368, -16368, -16382, -16382, -16381, -16381,
--16364, -16364, -16331, -16331, -16284, -16284, -16221, -16221, -16142, -16142,
--16049, -16049, -15940, -15940, -15817, -15817, -15678, -15678, -15525, -15525,
--15357, -15357, -15175, -15175, -14978, -14978, -14767, -14767, -14543, -14543,
--14304, -14304, -14053, -14053, -13788, -13788, -13510, -13510, -13219, -13219,
--12916, -12916, -12600, -12600, -12273, -12273, -11935, -11935, -11585, -11585,
--11224, -11224, -10853, -10853, -10471, -10471, -10079, -10079, -9679, -9679,
--9268, -9268, -8850, -8850, -8423, -8423, -7988, -7988, -7545, -7545,
--7095, -7095, -6639, -6639, -6176, -6176, -5708, -5708, -5234, -5234,
--4756, -4756, -4272, -4272, -3785, -3785, -3294, -3294, -2801, -2801,
--2304, -2304, -1805, -1805, -1305, -1305,  -803,  -803,  -301,  -301,
-201,   201,   703,   703,  1205,  1205,  1705,  1705,  2204,  2204,
-2701,  2701,  3196,  3196,  3687,  3687,  4175,  4175,  4659,  4659,
-5139,  5139,  5614,  5614,  6083,  6083,  6547,  6547,  7005,  7005,
-7456,  7456,  7900,  7900,  8336,  8336,  8765,  8765,  9185,  9185,
-9597,  9597, 10000, 10000, 10393, 10393, 10777, 10777, 11150, 11150,
-11513, 11513, 11866, 11866, 12207, 12207, 12536, 12536, 12854, 12854,
-13159, 13159, 13452, 13452, 13733, 13733, 14001, 14001, 14255, 14255,
-14496, 14496, 14723, 14723, 14937, 14937, 15136, 15136, 15322, 15322,
-15492, 15492, 15649, 15649, 15790, 15790, 15917, 15917, 16028, 16028,
-16125, 16125, 16206, 16206, 16272, 16272, 16323, 16323, 16359, 16359,
-16379, 16379, 16383, 16383, 16372, 16372, 16346, 16346, 16305, 16305,
-16248, 16248, 16175, 16175, 16088, 16088, 15985, 15985, 15868, 15868,
-15735, 15735, 15588, 15588, 15426, 15426, 15249, 15249, 15058, 15058,
-14853, 14853, 14634, 14634, 14401, 14401, 14155, 14155, 13895, 13895,
-13622, 13622, 13337, 13337, 13038, 13038, 12728, 12728, 12406, 12406,
-12072, 12072, 11726, 11726, 11370, 11370, 11002, 11002, 10625, 10625,
-10237, 10237,  9840,  9840,  9434,  9434,  9018,  9018,  8594,  8594,
-8162,  8162,  7723,  7723,  7276,  7276,  6822,  6822,  6362,  6362,
-5896,  5896,  5424,  5424,  4948,  4948,  4466,  4466,  3980,  3980,
-3491,  3491,  2998,  2998,  2503,  2503,  2005,  2005,  1505,  1505,
-1004,  1004,   502,   502,     0,     0,  -502,  -502, -1004, -1004,
--1505, -1505, -2005, -2005, -2503, -2503, -2998, -2998, -3491, -3491,
--3980, -3980, -4466, -4466, -4948, -4948, -5424, -5424, -5896, -5896,
--6362, -6362, -6822, -6822, -7276, -7276, -7723, -7723, -8162, -8162,
--8594, -8594, -9018, -9018, -9434, -9434, -9840, -9840, -10237, -10237,
--10625, -10625, -11002, -11002, -11370, -11370, -11726, -11726, -12072, -12072,
--12406, -12406, -12728, -12728, -13038, -13038, -13337, -13337, -13622, -13622,
--13895, -13895, -14155, -14155, -14401, -14401, -14634, -14634, -14853, -14853,
--15058, -15058, -15249, -15249, -15426, -15426, -15588, -15588, -15735, -15735,
--15868, -15868, -15985, -15985, -16088, -16088, -16175, -16175, -16248, -16248,
--16305, -16305, -16346, -16346, -16372, -16372, -16383, -16383, -16379, -16379,
--16359, -16359, -16323, -16323, -16272, -16272, -16206, -16206, -16125, -16125,
--16028, -16028, -15917, -15917, -15790, -15790, -15649, -15649, -15492, -15492,
--15322, -15322, -15136, -15136, -14937, -14937, -14723, -14723, -14496, -14496,
--14255, -14255, -14001, -14001, -13733, -13733, -13452, -13452, -13159, -13159,
--12854, -12854, -12536, -12536, -12207, -12207, -11866, -11866, -11513, -11513,
--11150, -11150, -10777, -10777, -10393, -10393, -10000, -10000, -9597, -9597,
--9185, -9185, -8765, -8765, -8336, -8336, -7900, -7900, -7456, -7456,
--7005, -7005, -6547, -6547, -6083, -6083, -5614, -5614, -5139, -5139,
--4659, -4659, -4175, -4175, -3687, -3687, -3196, -3196, -2701, -2701,
--2204, -2204, -1705, -1705, -1205, -1205,  -703,  -703,  -201,  -201,
-301,   301,   803,   803,  1305,  1305,  1805,  1805,  2304,  2304,
-2801,  2801,  3294,  3294,  3785,  3785,  4272,  4272,  4756,  4756,
-5234,  5234,  5708,  5708,  6176,  6176,  6639,  6639,  7095,  7095,
-7545,  7545,  7988,  7988,  8423,  8423,  8850,  8850,  9268,  9268,
-9679,  9679, 10079, 10079, 10471, 10471, 10853, 10853, 11224, 11224,
-11585, 11585, 11935, 11935, 12273, 12273, 12600, 12600, 12916, 12916,
-13219, 13219, 13510, 13510, 13788, 13788, 14053, 14053, 14304, 14304,
-14543, 14543, 14767, 14767, 14978, 14978, 15175, 15175, 15357, 15357,
-15525, 15525, 15678, 15678, 15817, 15817, 15940, 15940, 16049, 16049,
-16142, 16142, 16221, 16221, 16284, 16284, 16331, 16331, 16364, 16364,
-16381, 16381, 16382, 16382, 16368, 16368, 16339, 16339, 16294, 16294,
-16234, 16234, 16159, 16159, 16069, 16069, 15963, 15963, 15842, 15842,
-15707, 15707, 15557, 15557, 15392, 15392, 15212, 15212, 15018, 15018,
-14810, 14810, 14589, 14589, 14353, 14353, 14104, 14104, 13842, 13842,
-13566, 13566, 13278, 13278, 12977, 12977, 12665, 12665, 12340, 12340,
-12003, 12003, 11656, 11656, 11297, 11297, 10928, 10928, 10548, 10548,
-10159, 10159,  9759,  9759,  9351,  9351,  8934,  8934,  8509,  8509,
-8075,  8075,  7634,  7634,  7186,  7186,  6731,  6731,  6269,  6269,
-5802,  5802,  5329,  5329,  4852,  4852,  4369,  4369,  3883,  3883,
-3393,  3393,  2900,  2900,  2404,  2404,  1905,  1905,  1405,  1405,
-904,   904,   402,   402,  -100,  -100,  -603,  -603, -1105, -1105,
--1605, -1605, -2105, -2105, -2602, -2602, -3097, -3097, -3589, -3589,
--4078, -4078, -4563, -4563, -5043, -5043, -5519, -5519, -5990, -5990,
--6455, -6455, -6914, -6914, -7366, -7366, -7811, -7811, -8249, -8249,
--8680, -8680, -9102, -9102, -9516, -9516, -9920, -9920, -10315, -10315,
--10701, -10701, -11077, -11077, -11442, -11442, -11796, -11796, -12139, -12139,
--12471, -12471, -12791, -12791, -13099, -13099, -13395, -13395, -13678, -13678,
--13948, -13948, -14205, -14205, -14449, -14449, -14679, -14679, -14895, -14895,
--15098, -15098, -15286, -15286, -15459, -15459, -15618, -15618, -15763, -15763,
--15892, -15892, -16007, -16007, -16107, -16107, -16191, -16191, -16260, -16260,
--16314, -16314, -16353, -16353, -16376, -16376, -16383, -16383, -16376, -16376,
--16353, -16353, -16314, -16314, -16260, -16260, -16191, -16191, -16107, -16107,
--16007, -16007, -15892, -15892, -15763, -15763, -15618, -15618, -15459, -15459,
--15286, -15286, -15098, -15098, -14895, -14895, -14679, -14679, -14449, -14449,
--14205, -14205, -13948, -13948, -13678, -13678, -13395, -13395, -13099, -13099,
--12791, -12791, -12471, -12471, -12139, -12139, -11796, -11796, -11442, -11442,
--11077, -11077, -10701, -10701, -10315, -10315, -9920, -9920, -9516, -9516,
--9102, -9102, -8680, -8680, -8249, -8249, -7811, -7811, -7366, -7366,
--6914, -6914, -6455, -6455, -5990, -5990, -5519, -5519, -5043, -5043,
--4563, -4563, -4078, -4078, -3589, -3589, -3097, -3097, -2602, -2602,
--2105, -2105, -1605, -1605, -1105, -1105,  -603,  -603,  -100,  -100,
-402,   402,   904,   904,  1405,  1405,  1905,  1905,  2404,  2404,
-2900,  2900,  3393,  3393,  3883,  3883,  4369,  4369,  4852,  4852,
-5329,  5329,  5802,  5802,  6269,  6269,  6731,  6731,  7186,  7186,
-7634,  7634,  8075,  8075,  8509,  8509,  8934,  8934,  9351,  9351,
-9759,  9759, 10159, 10159, 10548, 10548, 10928, 10928, 11297, 11297,
-11656, 11656, 12003, 12003, 12340, 12340, 12665, 12665, 12977, 12977,
-13278, 13278, 13566, 13566, 13842, 13842, 14104, 14104, 14353, 14353,
-14589, 14589, 14810, 14810, 15018, 15018, 15212, 15212, 15392, 15392,
-15557, 15557, 15707, 15707, 15842, 15842, 15963, 15963, 16069, 16069,
-16159, 16159, 16234, 16234, 16294, 16294, 16339, 16339, 16368, 16368,
-16382, 16382, 16381, 16381, 16364, 16364, 16331, 16331, 16284, 16284,
-16221, 16221, 16142, 16142, 16049, 16049, 15940, 15940, 15817, 15817,
-15678, 15678, 15525, 15525, 15357, 15357, 15175, 15175, 14978, 14978,
-14767, 14767, 14543, 14543, 14304, 14304, 14053, 14053, 13788, 13788,
-13510, 13510, 13219, 13219, 12916, 12916, 12600, 12600, 12273, 12273,
-11935, 11935, 11585, 11585, 11224, 11224, 10853, 10853, 10471, 10471,
-10079, 10079,  9679,  9679,  9268,  9268,  8850,  8850,  8423,  8423,
-7988,  7988,  7545,  7545,  7095,  7095,  6639,  6639,  6176,  6176,
-5708,  5708,  5234,  5234,  4756,  4756,  4272,  4272,  3785,  3785,
-3294,  3294,  2801,  2801,  2304,  2304,  1805,  1805,  1305,  1305,
-803,   803,   301,   301,  -201,  -201,  -703,  -703, -1205, -1205,
--1705, -1705, -2204, -2204, -2701, -2701, -3196, -3196, -3687, -3687,
--4175, -4175, -4659, -4659, -5139, -5139, -5614, -5614, -6083, -6083,
--6547, -6547, -7005, -7005, -7456, -7456, -7900, -7900, -8336, -8336,
--8765, -8765, -9185, -9185, -9597, -9597, -10000, -10000, -10393, -10393,
--10777, -10777, -11150, -11150, -11513, -11513, -11866, -11866, -12207, -12207,
--12536, -12536, -12854, -12854, -13159, -13159, -13452, -13452, -13733, -13733,
--14001, -14001, -14255, -14255, -14496, -14496, -14723, -14723, -14937, -14937,
--15136, -15136, -15322, -15322, -15492, -15492, -15649, -15649, -15790, -15790,
--15917, -15917, -16028, -16028, -16125, -16125, -16206, -16206, -16272, -16272,
--16323, -16323, -16359, -16359, -16379, -16379, -16383, -16383, -16372, -16372,
--16346, -16346, -16305, -16305, -16248, -16248, -16175, -16175, -16088, -16088,
--15985, -15985, -15868, -15868, -15735, -15735, -15588, -15588, -15426, -15426,
--15249, -15249, -15058, -15058, -14853, -14853, -14634, -14634, -14401, -14401,
--14155, -14155, -13895, -13895, -13622, -13622, -13337, -13337, -13038, -13038,
--12728, -12728, -12406, -12406, -12072, -12072, -11726, -11726, -11370, -11370,
--11002, -11002, -10625, -10625, -10237, -10237, -9840, -9840, -9434, -9434,
--9018, -9018, -8594, -8594, -8162, -8162, -7723, -7723, -7276, -7276,
--6822, -6822, -6362, -6362, -5896, -5896, -5424, -5424, -4948, -4948,
--4466, -4466, -3980, -3980, -3491, -3491, -2998, -2998, -2503, -2503,
--2005, -2005, -1505, -1505, -1004, -1004,  -502,  -502
-};
-/*****************************************************************************/
-void
-easysnd_testtone(struct easycap *peasycap, int audio_fill)
-{
-int i1;
-unsigned char *p2;
-struct data_buffer *paudio_buffer;
-
-if (NULL == peasycap) {
-	SAY("ERROR: peasycap is NULL\n");
 	return;
 }
-JOM(8, "%i=audio_fill\n", audio_fill);
-paudio_buffer = &peasycap->audio_buffer[audio_fill];
-p2 = (unsigned char *)(paudio_buffer->pgo);
-for (i1 = 0;  i1 < PAGE_SIZE;  i1 += 4, p2 += 4) {
-	*p2       = (unsigned char) (0x00FF & tones[i1/2]);
-	*(p2 + 1) = (unsigned char)((0xFF00 & tones[i1/2]) >> 8);
-	*(p2 + 2) = (unsigned char) (0x00FF & tones[i1/2 + 1]);
-	*(p2 + 3) = (unsigned char)((0xFF00 & tones[i1/2 + 1]) >> 8);
-	}
-return;
-}
-#endif /*EASYCAP_TESTTONE*/
-/*****************************************************************************/
diff --git a/drivers/staging/echo/echo.c b/drivers/staging/echo/echo.c
index 58c4e90..3c188d5 100644
--- a/drivers/staging/echo/echo.c
+++ b/drivers/staging/echo/echo.c
@@ -544,7 +544,7 @@ int16_t oslec_update(struct oslec_state *ec, int16_t tx, int16_t rx)
 				 * Just random numbers rolled off very vaguely
 				 * Hoth-like.  DR: This noise doesn't sound
 				 * quite right to me - I suspect there are some
-				 * overlfow issues in the filtering as it's too
+				 * overflow issues in the filtering as it's too
 				 * "crackly".
 				 * TODO: debug this, maybe just play noise at
 				 * high level or look at spectrum.
diff --git a/drivers/staging/et131x/et1310_eeprom.c b/drivers/staging/et131x/et1310_eeprom.c
index 5a8e6b9..2375840 100644
--- a/drivers/staging/et131x/et1310_eeprom.c
+++ b/drivers/staging/et131x/et1310_eeprom.c
@@ -396,12 +396,12 @@ int et131x_init_eeprom(struct et131x_adapter *etdev)
 	/* Read the EEPROM for information regarding LED behavior. Refer to
 	 * ET1310_phy.c, et131x_xcvr_init(), for its use.
 	 */
-	eeprom_read(etdev, 0x70, &etdev->eepromData[0]);
-	eeprom_read(etdev, 0x71, &etdev->eepromData[1]);
+	eeprom_read(etdev, 0x70, &etdev->eeprom_data[0]);
+	eeprom_read(etdev, 0x71, &etdev->eeprom_data[1]);
 
-	if (etdev->eepromData[0] != 0xcd)
+	if (etdev->eeprom_data[0] != 0xcd)
 		/* Disable all optional features */
-		etdev->eepromData[1] = 0x00;
+		etdev->eeprom_data[1] = 0x00;
 
 	return 0;
 }
diff --git a/drivers/staging/et131x/et1310_mac.c b/drivers/staging/et131x/et1310_mac.c
index 16fa13d..78f72fa 100644
--- a/drivers/staging/et131x/et1310_mac.c
+++ b/drivers/staging/et131x/et1310_mac.c
@@ -136,12 +136,12 @@ void ConfigMACRegs1(struct et131x_adapter *etdev)
 	 * station address is used for generating and checking pause control
 	 * packets.
 	 */
-	station2.bits.Octet1 = etdev->CurrentAddress[0];
-	station2.bits.Octet2 = etdev->CurrentAddress[1];
-	station1.bits.Octet3 = etdev->CurrentAddress[2];
-	station1.bits.Octet4 = etdev->CurrentAddress[3];
-	station1.bits.Octet5 = etdev->CurrentAddress[4];
-	station1.bits.Octet6 = etdev->CurrentAddress[5];
+	station2.bits.Octet1 = etdev->addr[0];
+	station2.bits.Octet2 = etdev->addr[1];
+	station1.bits.Octet3 = etdev->addr[2];
+	station1.bits.Octet4 = etdev->addr[3];
+	station1.bits.Octet5 = etdev->addr[4];
+	station1.bits.Octet6 = etdev->addr[5];
 	writel(station1.value, &pMac->station_addr_1.value);
 	writel(station2.value, &pMac->station_addr_2.value);
 
@@ -191,7 +191,7 @@ void ConfigMACRegs2(struct et131x_adapter *etdev)
 	cfg1 |= CFG1_RX_ENABLE|CFG1_TX_ENABLE|CFG1_TX_FLOW;
 	/* Initialize loop back to off */
 	cfg1 &= ~(CFG1_LOOPBACK|CFG1_RX_FLOW);
-	if (etdev->FlowControl == RxOnly || etdev->FlowControl == Both)
+	if (etdev->flowcontrol == FLOW_RXONLY || etdev->flowcontrol == FLOW_BOTH)
 		cfg1 |= CFG1_RX_FLOW;
 	writel(cfg1, &pMac->cfg1);
 
@@ -280,14 +280,14 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
 	writel(0, &pRxMac->mask4_word3);
 
 	/* Lets setup the WOL Source Address */
-	sa_lo.bits.sa3 = etdev->CurrentAddress[2];
-	sa_lo.bits.sa4 = etdev->CurrentAddress[3];
-	sa_lo.bits.sa5 = etdev->CurrentAddress[4];
-	sa_lo.bits.sa6 = etdev->CurrentAddress[5];
+	sa_lo.bits.sa3 = etdev->addr[2];
+	sa_lo.bits.sa4 = etdev->addr[3];
+	sa_lo.bits.sa5 = etdev->addr[4];
+	sa_lo.bits.sa6 = etdev->addr[5];
 	writel(sa_lo.value, &pRxMac->sa_lo.value);
 
-	sa_hi.bits.sa1 = etdev->CurrentAddress[0];
-	sa_hi.bits.sa2 = etdev->CurrentAddress[1];
+	sa_hi.bits.sa1 = etdev->addr[0];
+	sa_hi.bits.sa2 = etdev->addr[1];
 	writel(sa_hi.value, &pRxMac->sa_hi.value);
 
 	/* Disable all Packet Filtering */
@@ -373,7 +373,7 @@ void ConfigTxMacRegs(struct et131x_adapter *etdev)
 	 * cfpt - control frame pause timer set to 64 (0x40)
 	 * cfep - control frame extended pause timer set to 0x0
 	 */
-	if (etdev->FlowControl == None)
+	if (etdev->flowcontrol == FLOW_NONE)
 		writel(0, &txmac->cf_param);
 	else
 		writel(0x40, &txmac->cf_param);
@@ -414,7 +414,7 @@ void ConfigMacStatRegs(struct et131x_adapter *etdev)
 void ConfigFlowControl(struct et131x_adapter *etdev)
 {
 	if (etdev->duplex_mode == 0) {
-		etdev->FlowControl = None;
+		etdev->flowcontrol = FLOW_NONE;
 	} else {
 		char remote_pause, remote_async_pause;
 
@@ -426,22 +426,22 @@ void ConfigFlowControl(struct et131x_adapter *etdev)
 
 		if ((remote_pause == TRUEPHY_BIT_SET) &&
 		    (remote_async_pause == TRUEPHY_BIT_SET)) {
-			etdev->FlowControl = etdev->RegistryFlowControl;
+			etdev->flowcontrol = etdev->wanted_flow;
 		} else if ((remote_pause == TRUEPHY_BIT_SET) &&
 			   (remote_async_pause == TRUEPHY_BIT_CLEAR)) {
-			if (etdev->RegistryFlowControl == Both)
-				etdev->FlowControl = Both;
+			if (etdev->wanted_flow == FLOW_BOTH)
+				etdev->flowcontrol = FLOW_BOTH;
 			else
-				etdev->FlowControl = None;
+				etdev->flowcontrol = FLOW_NONE;
 		} else if ((remote_pause == TRUEPHY_BIT_CLEAR) &&
 			   (remote_async_pause == TRUEPHY_BIT_CLEAR)) {
-			etdev->FlowControl = None;
+			etdev->flowcontrol = FLOW_NONE;
 		} else {/* if (remote_pause == TRUEPHY_CLEAR_BIT &&
 			       remote_async_pause == TRUEPHY_SET_BIT) */
-			if (etdev->RegistryFlowControl == Both)
-				etdev->FlowControl = RxOnly;
+			if (etdev->wanted_flow == FLOW_BOTH)
+				etdev->flowcontrol = FLOW_RXONLY;
 			else
-				etdev->FlowControl = None;
+				etdev->flowcontrol = FLOW_NONE;
 		}
 	}
 }
@@ -597,20 +597,20 @@ void SetupDeviceForUnicast(struct et131x_adapter *etdev)
 	 * Set up unicast packet filter reg 3 to be the octets 2 - 5 of the
 	 * MAC address for first address
 	 */
-	uni_pf3.bits.addr1_1 = etdev->CurrentAddress[0];
-	uni_pf3.bits.addr1_2 = etdev->CurrentAddress[1];
-	uni_pf3.bits.addr2_1 = etdev->CurrentAddress[0];
-	uni_pf3.bits.addr2_2 = etdev->CurrentAddress[1];
-
-	uni_pf2.bits.addr2_3 = etdev->CurrentAddress[2];
-	uni_pf2.bits.addr2_4 = etdev->CurrentAddress[3];
-	uni_pf2.bits.addr2_5 = etdev->CurrentAddress[4];
-	uni_pf2.bits.addr2_6 = etdev->CurrentAddress[5];
-
-	uni_pf1.bits.addr1_3 = etdev->CurrentAddress[2];
-	uni_pf1.bits.addr1_4 = etdev->CurrentAddress[3];
-	uni_pf1.bits.addr1_5 = etdev->CurrentAddress[4];
-	uni_pf1.bits.addr1_6 = etdev->CurrentAddress[5];
+	uni_pf3.bits.addr1_1 = etdev->addr[0];
+	uni_pf3.bits.addr1_2 = etdev->addr[1];
+	uni_pf3.bits.addr2_1 = etdev->addr[0];
+	uni_pf3.bits.addr2_2 = etdev->addr[1];
+
+	uni_pf2.bits.addr2_3 = etdev->addr[2];
+	uni_pf2.bits.addr2_4 = etdev->addr[3];
+	uni_pf2.bits.addr2_5 = etdev->addr[4];
+	uni_pf2.bits.addr2_6 = etdev->addr[5];
+
+	uni_pf1.bits.addr1_3 = etdev->addr[2];
+	uni_pf1.bits.addr1_4 = etdev->addr[3];
+	uni_pf1.bits.addr1_5 = etdev->addr[4];
+	uni_pf1.bits.addr1_6 = etdev->addr[5];
 
 	pm_csr = readl(&etdev->regs->global.pm_csr);
 	if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) {
diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c
index 21c5eee..2798a2f 100644
--- a/drivers/staging/et131x/et1310_phy.c
+++ b/drivers/staging/et131x/et1310_phy.c
@@ -242,23 +242,23 @@ int MiWrite(struct et131x_adapter *etdev, u8 xcvrReg, u16 value)
 int et131x_xcvr_find(struct et131x_adapter *etdev)
 {
 	u8 xcvr_addr;
-	MI_IDR1_t idr1;
-	MI_IDR2_t idr2;
+	u16 idr1;
+	u16 idr2;
 	u32 xcvr_id;
 
 	/* We need to get xcvr id and address we just get the first one */
 	for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) {
 		/* Read the ID from the PHY */
 		PhyMiRead(etdev, xcvr_addr,
-			  (u8) offsetof(MI_REGS_t, idr1),
-			  &idr1.value);
+			  (u8) offsetof(struct mi_regs, idr1),
+			  &idr1);
 		PhyMiRead(etdev, xcvr_addr,
-			  (u8) offsetof(MI_REGS_t, idr2),
-			  &idr2.value);
+			  (u8) offsetof(struct mi_regs, idr2),
+			  &idr2);
 
-		xcvr_id = (u32) ((idr1.value << 16) | idr2.value);
+		xcvr_id = (u32) ((idr1 << 16) | idr2);
 
-		if (idr1.value != 0 && idr1.value != 0xffff) {
+		if (idr1 != 0 && idr1 != 0xffff) {
 			etdev->Stats.xcvr_id = xcvr_id;
 			etdev->Stats.xcvr_addr = xcvr_addr;
 			return 0;
@@ -577,24 +577,22 @@ void et131x_setphy_normal(struct et131x_adapter *etdev)
  */
 static void et131x_xcvr_init(struct et131x_adapter *etdev)
 {
-	MI_IMR_t imr;
-	MI_ISR_t isr;
-	MI_LCR2_t lcr2;
+	u16 imr;
+	u16 isr;
+	u16 lcr2;
 
 	/* Zero out the adapter structure variable representing BMSR */
 	etdev->Bmsr.value = 0;
 
-	MiRead(etdev, (u8) offsetof(MI_REGS_t, isr), &isr.value);
-	MiRead(etdev, (u8) offsetof(MI_REGS_t, imr), &imr.value);
+	MiRead(etdev, (u8) offsetof(struct mi_regs, isr), &isr);
+	MiRead(etdev, (u8) offsetof(struct mi_regs, imr), &imr);
 
 	/* Set the link status interrupt only.  Bad behavior when link status
 	 * and auto neg are set, we run into a nested interrupt problem
 	 */
-	imr.bits.int_en = 0x1;
-	imr.bits.link_status = 0x1;
-	imr.bits.autoneg_status = 0x1;
+        imr |= 0x0105;
 
-	MiWrite(etdev, (u8) offsetof(MI_REGS_t, imr), imr.value);
+	MiWrite(etdev, (u8) offsetof(struct mi_regs, imr), imr);
 
 	/* Set the LED behavior such that LED 1 indicates speed (off =
 	 * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
@@ -604,29 +602,33 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev)
 	 * vendors; The LED behavior is now determined by vendor data in the
 	 * EEPROM. However, the above description is the default.
 	 */
-	if ((etdev->eepromData[1] & 0x4) == 0) {
-		MiRead(etdev, (u8) offsetof(MI_REGS_t, lcr2),
-		       &lcr2.value);
-		if ((etdev->eepromData[1] & 0x8) == 0)
-			lcr2.bits.led_tx_rx = 0x3;
+	if ((etdev->eeprom_data[1] & 0x4) == 0) {
+		MiRead(etdev, (u8) offsetof(struct mi_regs, lcr2),
+		       &lcr2);
+
+		lcr2 &= 0x00FF;
+		lcr2 |= 0xA000;	/* led link */
+
+		if ((etdev->eeprom_data[1] & 0x8) == 0)
+			lcr2 |= 0x0300;
 		else
-			lcr2.bits.led_tx_rx = 0x4;
-		lcr2.bits.led_link = 0xa;
-		MiWrite(etdev, (u8) offsetof(MI_REGS_t, lcr2),
-			lcr2.value);
+			lcr2 |= 0x0400;
+
+		MiWrite(etdev, (u8) offsetof(struct mi_regs, lcr2),
+			lcr2);
 	}
 
 	/* Determine if we need to go into a force mode and set it */
 	if (etdev->AiForceSpeed == 0 && etdev->AiForceDpx == 0) {
-		if (etdev->RegistryFlowControl == TxOnly ||
-		    etdev->RegistryFlowControl == Both)
+		if (etdev->wanted_flow == FLOW_TXONLY ||
+		    etdev->wanted_flow == FLOW_BOTH)
 			ET1310_PhyAccessMiBit(etdev,
 					      TRUEPHY_BIT_SET, 4, 11, NULL);
 		else
 			ET1310_PhyAccessMiBit(etdev,
 					      TRUEPHY_BIT_CLEAR, 4, 11, NULL);
 
-		if (etdev->RegistryFlowControl == Both)
+		if (etdev->wanted_flow == FLOW_BOTH)
 			ET1310_PhyAccessMiBit(etdev,
 					      TRUEPHY_BIT_SET, 4, 10, NULL);
 		else
@@ -645,15 +647,15 @@ static void et131x_xcvr_init(struct et131x_adapter *etdev)
 
 	/* Set to the correct force mode. */
 	if (etdev->AiForceDpx != 1) {
-		if (etdev->RegistryFlowControl == TxOnly ||
-		    etdev->RegistryFlowControl == Both)
+		if (etdev->wanted_flow == FLOW_TXONLY ||
+		    etdev->wanted_flow == FLOW_BOTH)
 			ET1310_PhyAccessMiBit(etdev,
 				      TRUEPHY_BIT_SET, 4, 11, NULL);
 		else
 			ET1310_PhyAccessMiBit(etdev,
 					      TRUEPHY_BIT_CLEAR, 4, 11, NULL);
 
-		if (etdev->RegistryFlowControl == Both)
+		if (etdev->wanted_flow == FLOW_BOTH)
 			ET1310_PhyAccessMiBit(etdev,
 					      TRUEPHY_BIT_SET, 4, 10, NULL);
 		else
@@ -740,7 +742,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev,
 
 	if (bmsr_ints.bits.link_status) {
 		if (bmsr.bits.link_status) {
-			etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
+			etdev->boot_coma = 20;
 
 			/* Update our state variables and indicate the
 			 * connected state
@@ -831,7 +833,7 @@ void et131x_Mii_check(struct et131x_adapter *etdev,
 			etdev->linkspeed = speed;
 			etdev->duplex_mode = duplex;
 
-			etdev->PoMgmt.TransPhyComaModeOnBoot = 20;
+			etdev->boot_coma = 20;
 
 			if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) {
 				/*
diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h
index 47907ba..78349ad 100644
--- a/drivers/staging/et131x/et1310_phy.h
+++ b/drivers/staging/et131x/et1310_phy.h
@@ -98,7 +98,7 @@
 #define VMI_RESERVED31_REG                  31
 
 /* PHY Register Mapping(MI) Management Interface Regs */
-typedef struct _MI_REGS_t {
+struct mi_regs {
 	u8 bmcr;	/* Basic mode control reg(Reg 0x00) */
 	u8 bmsr;	/* Basic mode status reg(Reg 0x01) */
 	u8 idr1;	/* Phy identifier reg 1(Reg 0x02) */
@@ -124,7 +124,7 @@ typedef struct _MI_REGS_t {
 	u8 lcr1;		/* LED Control 1 Reg(Reg 0x1B) */
 	u8 lcr2;		/* LED Control 2 Reg(Reg 0x1C) */
 	u8 mi_res4[3];	/* Future use by MI working group(Reg 0x1D - 0x1F) */
-} MI_REGS_t, *PMI_REGS_t;
+};
 
 /* MI Register 0: Basic mode control register */
 typedef union _MI_BMCR_t {
@@ -200,30 +200,6 @@ typedef union _MI_BMSR_t {
 	} bits;
 } MI_BMSR_t, *PMI_BMSR_t;
 
-/* MI Register 2: Physical Identifier 1 */
-typedef union _MI_IDR1_t {
-	u16 value;
-	struct {
-		u16 ieee_address:16;	/* 0x0282 default(bits 0-15) */
-	} bits;
-} MI_IDR1_t, *PMI_IDR1_t;
-
-/* MI Register 3: Physical Identifier 2 */
-typedef union _MI_IDR2_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 ieee_address:6;	/* 111100 default(bits 10-15) */
-		u16 model_no:6;		/* 000001 default(bits 4-9) */
-		u16 rev_no:4;		/* 0010   default(bits 0-3) */
-#else
-		u16 rev_no:4;		/* 0010   default(bits 0-3) */
-		u16 model_no:6;		/* 000001 default(bits 4-9) */
-		u16 ieee_address:6;	/* 111100 default(bits 10-15) */
-#endif
-	} bits;
-} MI_IDR2_t, *PMI_IDR2_t;
-
 /* MI Register 4: Auto-negotiation advertisement register */
 typedef union _MI_ANAR_t {
 	u16 value;
@@ -258,481 +234,194 @@ typedef union _MI_ANAR_t {
 	} bits;
 } MI_ANAR_t, *PMI_ANAR_t;
 
-/* MI Register 5: Auto-negotiation link partner advertisement register */
-typedef struct _MI_ANLPAR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 np_indication:1;	/* bit 15 */
-		u16 acknowledge:1;		/* bit 14 */
-		u16 remote_fault:1;	/* bit 13 */
-		u16 res1:1;		/* bit 12 */
-		u16 cap_asmpause:1;	/* bit 11 */
-		u16 cap_pause:1;		/* bit 10 */
-		u16 cap_100T4:1;		/* bit 9 */
-		u16 cap_100fdx:1;		/* bit 8 */
-		u16 cap_100hdx:1;		/* bit 7 */
-		u16 cap_10fdx:1;		/* bit 6 */
-		u16 cap_10hdx:1;		/* bit 5 */
-		u16 selector:5;		/* bits 0-4 */
-#else
-		u16 selector:5;		/* bits 0-4 */
-		u16 cap_10hdx:1;		/* bit 5 */
-		u16 cap_10fdx:1;		/* bit 6 */
-		u16 cap_100hdx:1;		/* bit 7 */
-		u16 cap_100fdx:1;		/* bit 8 */
-		u16 cap_100T4:1;		/* bit 9 */
-		u16 cap_pause:1;		/* bit 10 */
-		u16 cap_asmpause:1;	/* bit 11 */
-		u16 res1:1;		/* bit 12 */
-		u16 remote_fault:1;	/* bit 13 */
-		u16 acknowledge:1;		/* bit 14 */
-		u16 np_indication:1;	/* bit 15 */
-#endif
-	} bits;
-} MI_ANLPAR_t, *PMI_ANLPAR_t;
+/* MI Register 5: Auto-negotiation link partner advertisement register
+ *	15:	np_indication
+ *	14:	acknowledge
+ *	13:	remote_fault
+ *	12:	res1:1;		
+ *	11:	cap_asmpause
+ *	10:	cap_pause
+ *	9:	cap_100T4
+ *	8:	cap_100fdx
+ *	7:	cap_100hdx
+ *	6:	cap_10fdx
+ *	5:	cap_10hdx
+ *	4-0:	selector
+ */
 
-/* MI Register 6: Auto-negotiation expansion register */
-typedef union _MI_ANER_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res:11;	/* bits 5-15 */
-		u16 pdf:1;		/* bit 4 */
-		u16 lp_np_able:1;	/* bit 3 */
-		u16 np_able:1;	/* bit 2 */
-		u16 page_rx:1;	/* bit 1 */
-		u16 lp_an_able:1;	/* bit 0 */
-#else
-		u16 lp_an_able:1;	/* bit 0 */
-		u16 page_rx:1;	/* bit 1 */
-		u16 np_able:1;	/* bit 2 */
-		u16 lp_np_able:1;	/* bit 3 */
-		u16 pdf:1;		/* bit 4 */
-		u16 res:11;	/* bits 5-15 */
-#endif
-	} bits;
-} MI_ANER_t, *PMI_ANER_t;
+/* MI Register 6: Auto-negotiation expansion register
+ *	15-5:	reserved
+ *	4:	pdf
+ *	3:	lp_np_able
+ *	2:	np_able
+ *	1:	page_rx
+ *	0:	lp_an_able
+ */
 
-/* MI Register 7: Auto-negotiation next page transmit reg(0x07) */
-typedef union _MI_ANNPTR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 np:1;		/* bit 15 */
-		u16 res1:1;	/* bit 14 */
-		u16 msg_page:1;	/* bit 13 */
-		u16 ack2:1;	/* bit 12 */
-		u16 toggle:1;	/* bit 11 */
-		u16 msg:11;	/* bits 0-10 */
-#else
-		u16 msg:11;	/* bits 0-10 */
-		u16 toggle:1;	/* bit 11 */
-		u16 ack2:1;	/* bit 12 */
-		u16 msg_page:1;	/* bit 13 */
-		u16 res1:1;	/* bit 14 */
-		u16 np:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_ANNPTR_t, *PMI_ANNPTR_t;
+/* MI Register 7: Auto-negotiation next page transmit reg(0x07) 
+ *	15:	np
+ *	14:	reserved
+ *	13:	msg_page
+ *	12:	ack2
+ *	11:	toggle
+ *	10-0	msg
+ */
 
-/* MI Register 8: Link Partner Next Page Reg(0x08) */
-typedef union _MI_LPNPR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 np:1;		/* bit 15 */
-		u16 ack:1;		/* bit 14 */
-		u16 msg_page:1;	/* bit 13 */
-		u16 ack2:1;	/* bit 12 */
-		u16 toggle:1;	/* bit 11 */
-		u16 msg:11;	/* bits 0-10 */
-#else
-		u16 msg:11;	/* bits 0-10 */
-		u16 toggle:1;	/* bit 11 */
-		u16 ack2:1;	/* bit 12 */
-		u16 msg_page:1;	/* bit 13 */
-		u16 ack:1;		/* bit 14 */
-		u16 np:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_LPNPR_t, *PMI_LPNPR_t;
+/* MI Register 8: Link Partner Next Page Reg(0x08) 
+ *	15:	np
+ *	14:	ack
+ *	13:	msg_page
+ *	12:	ack2
+ *	11:	toggle
+ *	10-0:	msg
+ */
 
-/* MI Register 9: 1000BaseT Control Reg(0x09) */
-typedef union _MI_GCR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 test_mode:3;		/* bits 13-15 */
-		u16 ms_config_en:1;	/* bit 12 */
-		u16 ms_value:1;		/* bit 11 */
-		u16 port_type:1;		/* bit 10 */
-		u16 link_1000fdx:1;	/* bit 9 */
-		u16 link_1000hdx:1;	/* bit 8 */
-		u16 res:8;			/* bit 0-7 */
-#else
-		u16 res:8;			/* bit 0-7 */
-		u16 link_1000hdx:1;	/* bit 8 */
-		u16 link_1000fdx:1;	/* bit 9 */
-		u16 port_type:1;		/* bit 10 */
-		u16 ms_value:1;		/* bit 11 */
-		u16 ms_config_en:1;	/* bit 12 */
-		u16 test_mode:3;		/* bits 13-15 */
-#endif
-	} bits;
-} MI_GCR_t, *PMI_GCR_t;
+/* MI Register 9: 1000BaseT Control Reg(0x09)
+ *	15-13:	test_mode
+ *	12:	ms_config_en
+ *	11:	ms_value
+ *	10:	port_type
+ *	9:	link_1000fdx
+ *	8:	link_1000hdx
+ *	7-0:	reserved
+ */
 
-/* MI Register 10: 1000BaseT Status Reg(0x0A) */
-typedef union _MI_GSR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 ms_config_fault:1;	/* bit 15 */
-		u16 ms_resolve:1;		/* bit 14 */
-		u16 local_rx_status:1;	/* bit 13 */
-		u16 remote_rx_status:1;	/* bit 12 */
-		u16 link_1000fdx:1;	/* bit 11 */
-		u16 link_1000hdx:1;	/* bit 10 */
-		u16 res:2;			/* bits 8-9 */
-		u16 idle_err_cnt:8;	/* bits 0-7 */
-#else
-		u16 idle_err_cnt:8;	/* bits 0-7 */
-		u16 res:2;			/* bits 8-9 */
-		u16 link_1000hdx:1;	/* bit 10 */
-		u16 link_1000fdx:1;	/* bit 11 */
-		u16 remote_rx_status:1;	/* bit 12 */
-		u16 local_rx_status:1;	/* bit 13 */
-		u16 ms_resolve:1;		/* bit 14 */
-		u16 ms_config_fault:1;	/* bit 15 */
-#endif
-	} bits;
-} MI_GSR_t, *PMI_GSR_t;
+/* MI Register 10: 1000BaseT Status Reg(0x0A)
+ *	15:	ms_config_fault
+ *	14:	ms_resolve
+ *	13:	local_rx_status
+ *	12:	remote_rx_status
+ *	11:	link_1000fdx
+ *	10:	link_1000hdx
+ *	9-8:	reserved
+ *	7-0:	idle_err_cnt
+ */
 
 /* MI Register 11 - 14: Reserved Regs(0x0B - 0x0E) */
-typedef union _MI_RES_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res15:1;	/* bit 15 */
-		u16 res14:1;	/* bit 14 */
-		u16 res13:1;	/* bit 13 */
-		u16 res12:1;	/* bit 12 */
-		u16 res11:1;	/* bit 11 */
-		u16 res10:1;	/* bit 10 */
-		u16 res9:1;	/* bit 9 */
-		u16 res8:1;	/* bit 8 */
-		u16 res7:1;	/* bit 7 */
-		u16 res6:1;	/* bit 6 */
-		u16 res5:1;	/* bit 5 */
-		u16 res4:1;	/* bit 4 */
-		u16 res3:1;	/* bit 3 */
-		u16 res2:1;	/* bit 2 */
-		u16 res1:1;	/* bit 1 */
-		u16 res0:1;	/* bit 0 */
-#else
-		u16 res0:1;	/* bit 0 */
-		u16 res1:1;	/* bit 1 */
-		u16 res2:1;	/* bit 2 */
-		u16 res3:1;	/* bit 3 */
-		u16 res4:1;	/* bit 4 */
-		u16 res5:1;	/* bit 5 */
-		u16 res6:1;	/* bit 6 */
-		u16 res7:1;	/* bit 7 */
-		u16 res8:1;	/* bit 8 */
-		u16 res9:1;	/* bit 9 */
-		u16 res10:1;	/* bit 10 */
-		u16 res11:1;	/* bit 11 */
-		u16 res12:1;	/* bit 12 */
-		u16 res13:1;	/* bit 13 */
-		u16 res14:1;	/* bit 14 */
-		u16 res15:1;	/* bit 15 */
-#endif
-	} bits;
-} MI_RES_t, *PMI_RES_t;
 
-/* MI Register 15: Extended status Reg(0x0F) */
-typedef union _MI_ESR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 link_1000Xfdx:1;	/* bit 15 */
-		u16 link_1000Xhdx:1;	/* bit 14 */
-		u16 link_1000fdx:1;	/* bit 13 */
-		u16 link_1000hdx:1;	/* bit 12 */
-		u16 res:12;		/* bit 0-11 */
-#else
-		u16 res:12;		/* bit 0-11 */
-		u16 link_1000hdx:1;	/* bit 12 */
-		u16 link_1000fdx:1;	/* bit 13 */
-		u16 link_1000Xhdx:1;	/* bit 14 */
-		u16 link_1000Xfdx:1;	/* bit 15 */
-#endif
-	} bits;
-} MI_ESR_t, *PMI_ESR_t;
+/* MI Register 15: Extended status Reg(0x0F)
+ *	15:	link_1000Xfdx
+ *	14:	link_1000Xhdx
+ *	13:	link_1000fdx
+ *	12:	link_1000hdx
+ *	11-0:	reserved
+ */
 
 /* MI Register 16 - 18: Reserved Reg(0x10-0x12) */
 
-/* MI Register 19: Loopback Control Reg(0x13) */
-typedef union _MI_LCR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 mii_en:1;		/* bit 15 */
-		u16 pcs_en:1;		/* bit 14 */
-		u16 pmd_en:1;		/* bit 13 */
-		u16 all_digital_en:1;	/* bit 12 */
-		u16 replica_en:1;		/* bit 11 */
-		u16 line_driver_en:1;	/* bit 10 */
-		u16 res:10;		/* bit 0-9 */
-#else
-		u16 res:10;		/* bit 0-9 */
-		u16 line_driver_en:1;	/* bit 10 */
-		u16 replica_en:1;		/* bit 11 */
-		u16 all_digital_en:1;	/* bit 12 */
-		u16 pmd_en:1;		/* bit 13 */
-		u16 pcs_en:1;		/* bit 14 */
-		u16 mii_en:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_LCR_t, *PMI_LCR_t;
+/* MI Register 19: Loopback Control Reg(0x13)
+ *	15:	mii_en
+ *	14:	pcs_en
+ *	13:	pmd_en
+ *	12:	all_digital_en
+ *	11:	replica_en
+ *	10:	line_driver_en
+ *	9-0:	reserved
+ */
 
 /* MI Register 20: Reserved Reg(0x14) */
 
-/* MI Register 21: Management Interface Control Reg(0x15) */
-typedef union _MI_MICR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res1:5;		/* bits 11-15 */
-		u16 mi_error_count:7;	/* bits 4-10 */
-		u16 res2:1;		/* bit 3 */
-		u16 ignore_10g_fr:1;	/* bit 2 */
-		u16 res3:1;		/* bit 1 */
-		u16 preamble_supress_en:1;	/* bit 0 */
-#else
-		u16 preamble_supress_en:1;	/* bit 0 */
-		u16 res3:1;		/* bit 1 */
-		u16 ignore_10g_fr:1;	/* bit 2 */
-		u16 res2:1;		/* bit 3 */
-		u16 mi_error_count:7;	/* bits 4-10 */
-		u16 res1:5;		/* bits 11-15 */
-#endif
-	} bits;
-} MI_MICR_t, *PMI_MICR_t;
+/* MI Register 21: Management Interface Control Reg(0x15)
+ *	15-11:	reserved
+ *	10-4:	mi_error_count
+ *	3:	reserved
+ *	2:	ignore_10g_fr
+ *	1:	reserved
+ *	0:	preamble_supress_en
+ */
 
-/* MI Register 22: PHY Configuration Reg(0x16) */
-typedef union _MI_PHY_CONFIG_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 crs_tx_en:1;		/* bit 15 */
-		u16 res1:1;		/* bit 14 */
-		u16 tx_fifo_depth:2;	/* bits 12-13 */
-		u16 speed_downshift:2;	/* bits 10-11 */
-		u16 pbi_detect:1;		/* bit 9 */
-		u16 tbi_rate:1;		/* bit 8 */
-		u16 alternate_np:1;	/* bit 7 */
-		u16 group_mdio_en:1;	/* bit 6 */
-		u16 tx_clock_en:1;		/* bit 5 */
-		u16 sys_clock_en:1;	/* bit 4 */
-		u16 res2:1;		/* bit 3 */
-		u16 mac_if_mode:3;		/* bits 0-2 */
-#else
-		u16 mac_if_mode:3;		/* bits 0-2 */
-		u16 res2:1;		/* bit 3 */
-		u16 sys_clock_en:1;	/* bit 4 */
-		u16 tx_clock_en:1;		/* bit 5 */
-		u16 group_mdio_en:1;	/* bit 6 */
-		u16 alternate_np:1;	/* bit 7 */
-		u16 tbi_rate:1;		/* bit 8 */
-		u16 pbi_detect:1;		/* bit 9 */
-		u16 speed_downshift:2;	/* bits 10-11 */
-		u16 tx_fifo_depth:2;	/* bits 12-13 */
-		u16 res1:1;		/* bit 14 */
-		u16 crs_tx_en:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_PHY_CONFIG_t, *PMI_PHY_CONFIG_t;
+/* MI Register 22: PHY Configuration Reg(0x16)
+ *	15:	crs_tx_en
+ *	14:	reserved
+ *	13-12:	tx_fifo_depth
+ *	11-10:	speed_downshift
+ *	9:	pbi_detect
+ *	8:	tbi_rate
+ *	7:	alternate_np
+ *	6:	group_mdio_en
+ *	5:	tx_clock_en
+ *	4:	sys_clock_en
+ *	3:	reserved
+ *	2-0:	mac_if_mode
+ */
 
-/* MI Register 23: PHY CONTROL Reg(0x17) */
-typedef union _MI_PHY_CONTROL_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res1:1;		/* bit 15 */
-		u16 tdr_en:1;		/* bit 14 */
-		u16 res2:1;		/* bit 13 */
-		u16 downshift_attempts:2;	/* bits 11-12 */
-		u16 res3:5;		/* bit 6-10 */
-		u16 jabber_10baseT:1;	/* bit 5 */
-		u16 sqe_10baseT:1;		/* bit 4 */
-		u16 tp_loopback_10baseT:1;	/* bit 3 */
-		u16 preamble_gen_en:1;	/* bit 2 */
-		u16 res4:1;		/* bit 1 */
-		u16 force_int:1;		/* bit 0 */
-#else
-		u16 force_int:1;		/* bit 0 */
-		u16 res4:1;		/* bit 1 */
-		u16 preamble_gen_en:1;	/* bit 2 */
-		u16 tp_loopback_10baseT:1;	/* bit 3 */
-		u16 sqe_10baseT:1;		/* bit 4 */
-		u16 jabber_10baseT:1;	/* bit 5 */
-		u16 res3:5;		/* bit 6-10 */
-		u16 downshift_attempts:2;	/* bits 11-12 */
-		u16 res2:1;		/* bit 13 */
-		u16 tdr_en:1;		/* bit 14 */
-		u16 res1:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_PHY_CONTROL_t, *PMI_PHY_CONTROL_t;
+/* MI Register 23: PHY CONTROL Reg(0x17)
+ *	15:	reserved
+ *	14:	tdr_en
+ *	13:	reserved
+ *	12-11:	downshift_attempts
+ *	10-6:	reserved
+ *	5:	jabber_10baseT
+ *	4:	sqe_10baseT
+ *	3:	tp_loopback_10baseT
+ *	2:	preamble_gen_en
+ *	1:	reserved
+ *	0:	force_int
+ */
 
-/* MI Register 24: Interrupt Mask Reg(0x18) */
-typedef union _MI_IMR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res1:6;		/* bits 10-15 */
-		u16 mdio_sync_lost:1;	/* bit 9 */
-		u16 autoneg_status:1;	/* bit 8 */
-		u16 hi_bit_err:1;		/* bit 7 */
-		u16 np_rx:1;		/* bit 6 */
-		u16 err_counter_full:1;	/* bit 5 */
-		u16 fifo_over_underflow:1;	/* bit 4 */
-		u16 rx_status:1;		/* bit 3 */
-		u16 link_status:1;		/* bit 2 */
-		u16 automatic_speed:1;	/* bit 1 */
-		u16 int_en:1;		/* bit 0 */
-#else
-		u16 int_en:1;		/* bit 0 */
-		u16 automatic_speed:1;	/* bit 1 */
-		u16 link_status:1;		/* bit 2 */
-		u16 rx_status:1;		/* bit 3 */
-		u16 fifo_over_underflow:1;	/* bit 4 */
-		u16 err_counter_full:1;	/* bit 5 */
-		u16 np_rx:1;		/* bit 6 */
-		u16 hi_bit_err:1;		/* bit 7 */
-		u16 autoneg_status:1;	/* bit 8 */
-		u16 mdio_sync_lost:1;	/* bit 9 */
-		u16 res1:6;		/* bits 10-15 */
-#endif
-	} bits;
-} MI_IMR_t, *PMI_IMR_t;
+/* MI Register 24: Interrupt Mask Reg(0x18)
+ *	15-10:	reserved
+ *	9:	mdio_sync_lost
+ *	8:	autoneg_status
+ *	7:	hi_bit_err
+ *	6:	np_rx
+ *	5:	err_counter_full
+ *	4:	fifo_over_underflow
+ *	3:	rx_status
+ *	2:	link_status
+ *	1:	automatic_speed
+ *	0:	int_en
+ */
 
-/* MI Register 25: Interrupt Status Reg(0x19) */
-typedef union _MI_ISR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res1:6;		/* bits 10-15 */
-		u16 mdio_sync_lost:1;	/* bit 9 */
-		u16 autoneg_status:1;	/* bit 8 */
-		u16 hi_bit_err:1;		/* bit 7 */
-		u16 np_rx:1;		/* bit 6 */
-		u16 err_counter_full:1;	/* bit 5 */
-		u16 fifo_over_underflow:1;	/* bit 4 */
-		u16 rx_status:1;		/* bit 3 */
-		u16 link_status:1;		/* bit 2 */
-		u16 automatic_speed:1;	/* bit 1 */
-		u16 int_en:1;		/* bit 0 */
-#else
-		u16 int_en:1;		/* bit 0 */
-		u16 automatic_speed:1;	/* bit 1 */
-		u16 link_status:1;		/* bit 2 */
-		u16 rx_status:1;		/* bit 3 */
-		u16 fifo_over_underflow:1;	/* bit 4 */
-		u16 err_counter_full:1;	/* bit 5 */
-		u16 np_rx:1;		/* bit 6 */
-		u16 hi_bit_err:1;		/* bit 7 */
-		u16 autoneg_status:1;	/* bit 8 */
-		u16 mdio_sync_lost:1;	/* bit 9 */
-		u16 res1:6;		/* bits 10-15 */
-#endif
-	} bits;
-} MI_ISR_t, *PMI_ISR_t;
 
-/* MI Register 26: PHY Status Reg(0x1A) */
-typedef union _MI_PSR_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res1:1;		/* bit 15 */
-		u16 autoneg_fault:2;	/* bit 13-14 */
-		u16 autoneg_status:1;	/* bit 12 */
-		u16 mdi_x_status:1;	/* bit 11 */
-		u16 polarity_status:1;	/* bit 10 */
-		u16 speed_status:2;	/* bits 8-9 */
-		u16 duplex_status:1;	/* bit 7 */
-		u16 link_status:1;		/* bit 6 */
-		u16 tx_status:1;		/* bit 5 */
-		u16 rx_status:1;		/* bit 4 */
-		u16 collision_status:1;	/* bit 3 */
-		u16 autoneg_en:1;		/* bit 2 */
-		u16 pause_en:1;		/* bit 1 */
-		u16 asymmetric_dir:1;	/* bit 0 */
-#else
-		u16 asymmetric_dir:1;	/* bit 0 */
-		u16 pause_en:1;		/* bit 1 */
-		u16 autoneg_en:1;		/* bit 2 */
-		u16 collision_status:1;	/* bit 3 */
-		u16 rx_status:1;		/* bit 4 */
-		u16 tx_status:1;		/* bit 5 */
-		u16 link_status:1;		/* bit 6 */
-		u16 duplex_status:1;	/* bit 7 */
-		u16 speed_status:2;	/* bits 8-9 */
-		u16 polarity_status:1;	/* bit 10 */
-		u16 mdi_x_status:1;	/* bit 11 */
-		u16 autoneg_status:1;	/* bit 12 */
-		u16 autoneg_fault:2;	/* bit 13-14 */
-		u16 res1:1;		/* bit 15 */
-#endif
-	} bits;
-} MI_PSR_t, *PMI_PSR_t;
+/* MI Register 25: Interrupt Status Reg(0x19)
+ *	15-10:	reserved
+ *	9:	mdio_sync_lost
+ *	8:	autoneg_status
+ *	7:	hi_bit_err
+ *	6:	np_rx
+ *	5:	err_counter_full
+ *	4:	fifo_over_underflow
+ *	3:	rx_status
+ *	2:	link_status
+ *	1:	automatic_speed
+ *	0:	int_en
+ */
 
-/* MI Register 27: LED Control Reg 1(0x1B) */
-typedef union _MI_LCR1_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 res1:2;		/* bits 14-15 */
-		u16 led_dup_indicate:2;	/* bits 12-13 */
-		u16 led_10baseT:2;		/* bits 10-11 */
-		u16 led_collision:2;	/* bits 8-9 */
-		u16 res2:2;		/* bits 6-7 */
-		u16 res3:2;		/* bits 4-5 */
-		u16 pulse_dur:2;		/* bits 2-3 */
-		u16 pulse_stretch1:1;	/* bit 1 */
-		u16 pulse_stretch0:1;	/* bit 0 */
-#else
-		u16 pulse_stretch0:1;	/* bit 0 */
-		u16 pulse_stretch1:1;	/* bit 1 */
-		u16 pulse_dur:2;		/* bits 2-3 */
-		u16 res3:2;		/* bits 4-5 */
-		u16 res2:2;		/* bits 6-7 */
-		u16 led_collision:2;	/* bits 8-9 */
-		u16 led_10baseT:2;		/* bits 10-11 */
-		u16 led_dup_indicate:2;	/* bits 12-13 */
-		u16 res1:2;		/* bits 14-15 */
-#endif
-	} bits;
-} MI_LCR1_t, *PMI_LCR1_t;
+/* MI Register 26: PHY Status Reg(0x1A)
+ *	15:	reserved
+ *	14-13:	autoneg_fault
+ *	12:	autoneg_status
+ *	11:	mdi_x_status
+ *	10:	polarity_status
+ *	9-8:	speed_status
+ *	7:	duplex_status
+ *	6:	link_status
+ *	5:	tx_status
+ *	4:	rx_status
+ *	3:	collision_status
+ *	2:	autoneg_en
+ *	1:	pause_en
+ *	0:	asymmetric_dir
+ */
 
-/* MI Register 28: LED Control Reg 2(0x1C) */
-typedef union _MI_LCR2_t {
-	u16 value;
-	struct {
-#ifdef _BIT_FIELDS_HTOL
-		u16 led_link:4;		/* bits 12-15 */
-		u16 led_tx_rx:4;		/* bits 8-11 */
-		u16 led_100BaseTX:4;	/* bits 4-7 */
-		u16 led_1000BaseT:4;	/* bits 0-3 */
-#else
-		u16 led_1000BaseT:4;	/* bits 0-3 */
-		u16 led_100BaseTX:4;	/* bits 4-7 */
-		u16 led_tx_rx:4;		/* bits 8-11 */
-		u16 led_link:4;		/* bits 12-15 */
-#endif
-	} bits;
-} MI_LCR2_t, *PMI_LCR2_t;
+/* MI Register 27: LED Control Reg 1(0x1B)
+ *	15-14:	reserved
+ *	13-12:	led_dup_indicate
+ *	11-10:	led_10baseT
+ *	9-8:	led_collision
+ *	7-4:	reserved
+ *	3-2:	pulse_dur
+ *	1:	pulse_stretch1
+ *	0:	pulse_stretch0
+ */
+
+/* MI Register 28: LED Control Reg 2(0x1C)
+ *	15-12:	led_link
+ *	11-8:	led_tx_rx
+ *	7-4:	led_100BaseTX
+ *	3-0:	led_1000BaseT
+ */
 
 /* MI Register 29 - 31: Reserved Reg(0x1D - 0x1E) */
 
diff --git a/drivers/staging/et131x/et1310_pm.c b/drivers/staging/et131x/et1310_pm.c
index c64bb2c..2bc1944 100644
--- a/drivers/staging/et131x/et1310_pm.c
+++ b/drivers/staging/et131x/et1310_pm.c
@@ -109,30 +109,30 @@
 void EnablePhyComa(struct et131x_adapter *etdev)
 {
 	unsigned long flags;
-	u32 GlobalPmCSR;
+	u32 pmcsr;
 
-	GlobalPmCSR = readl(&etdev->regs->global.pm_csr);
+	pmcsr = readl(&etdev->regs->global.pm_csr);
 
 	/* Save the GbE PHY speed and duplex modes. Need to restore this
 	 * when cable is plugged back in
 	 */
-	etdev->PoMgmt.PowerDownSpeed = etdev->AiForceSpeed;
-	etdev->PoMgmt.PowerDownDuplex = etdev->AiForceDpx;
+	etdev->pdown_speed = etdev->AiForceSpeed;
+	etdev->pdown_duplex = etdev->AiForceDpx;
 
 	/* Stop sending packets. */
-	spin_lock_irqsave(&etdev->SendHWLock, flags);
+	spin_lock_irqsave(&etdev->send_hw_lock, flags);
 	etdev->Flags |= fMP_ADAPTER_LOWER_POWER;
-	spin_unlock_irqrestore(&etdev->SendHWLock, flags);
+	spin_unlock_irqrestore(&etdev->send_hw_lock, flags);
 
 	/* Wait for outstanding Receive packets */
 
 	/* Gate off JAGCore 3 clock domains */
-	GlobalPmCSR &= ~ET_PMCSR_INIT;
-	writel(GlobalPmCSR, &etdev->regs->global.pm_csr);
+	pmcsr &= ~ET_PMCSR_INIT;
+	writel(pmcsr, &etdev->regs->global.pm_csr);
 
 	/* Program gigE PHY in to Coma mode */
-	GlobalPmCSR |= ET_PM_PHY_SW_COMA;
-	writel(GlobalPmCSR, &etdev->regs->global.pm_csr);
+	pmcsr |= ET_PM_PHY_SW_COMA;
+	writel(pmcsr, &etdev->regs->global.pm_csr);
 }
 
 /**
@@ -141,20 +141,20 @@ void EnablePhyComa(struct et131x_adapter *etdev)
  */
 void DisablePhyComa(struct et131x_adapter *etdev)
 {
-	u32 GlobalPmCSR;
+	u32 pmcsr;
 
-	GlobalPmCSR = readl(&etdev->regs->global.pm_csr);
+	pmcsr = readl(&etdev->regs->global.pm_csr);
 
 	/* Disable phy_sw_coma register and re-enable JAGCore clocks */
-	GlobalPmCSR |= ET_PMCSR_INIT;
-	GlobalPmCSR &= ~ET_PM_PHY_SW_COMA;
-	writel(GlobalPmCSR, &etdev->regs->global.pm_csr);
+	pmcsr |= ET_PMCSR_INIT;
+	pmcsr &= ~ET_PM_PHY_SW_COMA;
+	writel(pmcsr, &etdev->regs->global.pm_csr);
 
 	/* Restore the GbE PHY speed and duplex modes;
 	 * Reset JAGCore; re-configure and initialize JAGCore and gigE PHY
 	 */
-	etdev->AiForceSpeed = etdev->PoMgmt.PowerDownSpeed;
-	etdev->AiForceDpx = etdev->PoMgmt.PowerDownDuplex;
+	etdev->AiForceSpeed = etdev->pdown_speed;
+	etdev->AiForceDpx = etdev->pdown_duplex;
 
 	/* Re-initialize the send structures */
 	et131x_init_send(etdev);
diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c
index 8e04bdd..339136f 100644
--- a/drivers/staging/et131x/et1310_rx.c
+++ b/drivers/staging/et131x/et1310_rx.c
@@ -88,7 +88,7 @@
 #include "et1310_rx.h"
 #include "et131x.h"
 
-void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd);
+void nic_return_rfd(struct et131x_adapter *etdev, struct rfd *rfd);
 
 /**
  * et131x_rx_dma_memory_alloc
@@ -372,7 +372,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
 	 * RFDs will be allocated from this pool.
 	 */
 	rx_ring->RecvLookaside = kmem_cache_create(adapter->netdev->name,
-						   sizeof(MP_RFD),
+						   sizeof(struct rfd),
 						   0,
 						   SLAB_CACHE_DMA |
 						   SLAB_HWCACHE_ALIGN,
@@ -396,7 +396,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 	u32 index;
 	u32 bufsize;
 	u32 pktStatRingSize;
-	PMP_RFD rfd;
+	struct rfd *rfd;
 	struct rx_ring *rx_ring;
 
 	/* Setup some convenience pointers */
@@ -406,11 +406,11 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 	WARN_ON(rx_ring->nReadyRecv != rx_ring->NumRfd);
 
 	while (!list_empty(&rx_ring->RecvList)) {
-		rfd = (MP_RFD *) list_entry(rx_ring->RecvList.next,
-					       MP_RFD, list_node);
+		rfd = (struct rfd *) list_entry(rx_ring->RecvList.next,
+				struct rfd, list_node);
 
 		list_del(&rfd->list_node);
-		rfd->Packet = NULL;
+		rfd->skb = NULL;
 		kmem_cache_free(adapter->rx_ring.RecvLookaside, rfd);
 	}
 
@@ -537,7 +537,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
 int et131x_init_recv(struct et131x_adapter *adapter)
 {
 	int status = -ENOMEM;
-	PMP_RFD rfd = NULL;
+	struct rfd *rfd = NULL;
 	u32 rfdct;
 	u32 numrfd = 0;
 	struct rx_ring *rx_ring;
@@ -557,7 +557,7 @@ int et131x_init_recv(struct et131x_adapter *adapter)
 			continue;
 		}
 
-		rfd->Packet = NULL;
+		rfd->skb = NULL;
 
 		/* Add this RFD to the RecvList */
 		list_add_tail(&rfd->list_node, &rx_ring->RecvList);
@@ -622,7 +622,7 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev)
 	writel((psr_num_des * LO_MARK_PERCENT_FOR_PSR) / 100,
 	       &rx_dma->psr_min_des);
 
-	spin_lock_irqsave(&etdev->RcvLock, flags);
+	spin_lock_irqsave(&etdev->rcv_lock, flags);
 
 	/* These local variables track the PSR in the adapter structure */
 	rx_local->local_psr_full = 0;
@@ -688,7 +688,7 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev)
 	 */
 	writel(PARM_RX_TIME_INT_DEF, &rx_dma->max_pkt_time);
 
-	spin_unlock_irqrestore(&etdev->RcvLock, flags);
+	spin_unlock_irqrestore(&etdev->rcv_lock, flags);
 }
 
 /**
@@ -717,10 +717,10 @@ void et131x_rx_dma_disable(struct et131x_adapter *etdev)
 	/* Setup the receive dma configuration register */
 	writel(0x00002001, &etdev->regs->rxdma.csr);
 	csr = readl(&etdev->regs->rxdma.csr);
-	if ((csr & 0x00020000) != 1) {	/* Check halt status (bit 17) */
+	if ((csr & 0x00020000) == 0) {	/* Check halt status (bit 17) */
 		udelay(5);
 		csr = readl(&etdev->regs->rxdma.csr);
-		if ((csr & 0x00020000) != 1)
+		if ((csr & 0x00020000) == 0)
 			dev_err(&etdev->pdev->dev,
 			"RX Dma failed to enter halt state. CSR 0x%08x\n",
 				csr);
@@ -776,12 +776,12 @@ void et131x_rx_dma_enable(struct et131x_adapter *etdev)
  * the packet to it, puts the RFD in the RecvPendList, and also returns
  * the pointer to the RFD.
  */
-PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
+struct rfd * nic_rx_pkts(struct et131x_adapter *etdev)
 {
 	struct rx_ring *rx_local = &etdev->rx_ring;
 	struct rx_status_block *status;
 	struct pkt_stat_desc *psr;
-	PMP_RFD rfd;
+	struct rfd *rfd;
 	u32 i;
 	u8 *buf;
 	unsigned long flags;
@@ -854,21 +854,21 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
 	}
 
 	/* Get and fill the RFD. */
-	spin_lock_irqsave(&etdev->RcvLock, flags);
+	spin_lock_irqsave(&etdev->rcv_lock, flags);
 
 	rfd = NULL;
 	element = rx_local->RecvList.next;
-	rfd = (PMP_RFD) list_entry(element, MP_RFD, list_node);
+	rfd = (struct rfd *) list_entry(element, struct rfd, list_node);
 
 	if (rfd == NULL) {
-		spin_unlock_irqrestore(&etdev->RcvLock, flags);
+		spin_unlock_irqrestore(&etdev->rcv_lock, flags);
 		return NULL;
 	}
 
 	list_del(&rfd->list_node);
 	rx_local->nReadyRecv--;
 
-	spin_unlock_irqrestore(&etdev->RcvLock, flags);
+	spin_unlock_irqrestore(&etdev->rcv_lock, flags);
 
 	rfd->bufferindex = bindex;
 	rfd->ringindex = rindex;
@@ -887,8 +887,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
 		if (etdev->ReplicaPhyLoopbk == 1) {
 			buf = rx_local->fbr[rindex]->virt[bindex];
 
-			if (memcmp(&buf[6], &etdev->CurrentAddress[0],
-				   ETH_ALEN) == 0) {
+			if (memcmp(&buf[6], etdev->addr, ETH_ALEN) == 0) {
 				if (memcmp(&buf[42], "Replica packet",
 					   ETH_HLEN)) {
 					etdev->ReplicaPhyLoopbkPF = 1;
@@ -939,7 +938,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
 				 * of Multicast address we have, then
 				 * this means we did not find this
 				 * packet's matching address in our
-				 * list.  Set the PacketSize to zero,
+				 * list.  Set the len to zero,
 				 * so we free our RFD when we return
 				 * from this function.
 				 */
@@ -963,21 +962,21 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
 	if (len > 0) {
 		struct sk_buff *skb = NULL;
 
-		/* rfd->PacketSize = len - 4; */
-		rfd->PacketSize = len;
+		/*rfd->len = len - 4; */
+		rfd->len = len;
 
-		skb = dev_alloc_skb(rfd->PacketSize + 2);
+		skb = dev_alloc_skb(rfd->len + 2);
 		if (!skb) {
 			dev_err(&etdev->pdev->dev,
 				  "Couldn't alloc an SKB for Rx\n");
 			return NULL;
 		}
 
-		etdev->net_stats.rx_bytes += rfd->PacketSize;
+		etdev->net_stats.rx_bytes += rfd->len;
 
-		memcpy(skb_put(skb, rfd->PacketSize),
+		memcpy(skb_put(skb, rfd->len),
 		       rx_local->fbr[rindex]->virt[bindex],
-		       rfd->PacketSize);
+		       rfd->len);
 
 		skb->dev = etdev->netdev;
 		skb->protocol = eth_type_trans(skb, etdev->netdev);
@@ -985,7 +984,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
 
 		netif_rx(skb);
 	} else {
-		rfd->PacketSize = 0;
+		rfd->len = 0;
 	}
 
 	nic_return_rfd(etdev, rfd);
@@ -1012,7 +1011,7 @@ void et131x_reset_recv(struct et131x_adapter *etdev)
  */
 void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
 {
-	PMP_RFD rfd = NULL;
+	struct rfd *rfd = NULL;
 	u32 count = 0;
 	bool done = true;
 
@@ -1036,7 +1035,7 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
 		 */
 		if (!etdev->PacketFilter ||
 		    !(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) ||
-		    rfd->PacketSize == 0) {
+		    rfd->len == 0) {
 			continue;
 		}
 
@@ -1083,7 +1082,7 @@ static inline u32 bump_fbr(u32 *fbr, u32 limit)
  * @etdev: pointer to our adapter
  * @rfd: pointer to the RFD
  */
-void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd)
+void nic_return_rfd(struct et131x_adapter *etdev, struct rfd *rfd)
 {
 	struct rx_ring *rx_local = &etdev->rx_ring;
 	struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
@@ -1146,10 +1145,10 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd)
 	/* The processing on this RFD is done, so put it back on the tail of
 	 * our list
 	 */
-	spin_lock_irqsave(&etdev->RcvLock, flags);
+	spin_lock_irqsave(&etdev->rcv_lock, flags);
 	list_add_tail(&rfd->list_node, &rx_local->RecvList);
 	rx_local->nReadyRecv++;
-	spin_unlock_irqrestore(&etdev->RcvLock, flags);
+	spin_unlock_irqrestore(&etdev->rcv_lock, flags);
 
 	WARN_ON(rx_local->nReadyRecv > rx_local->NumRfd);
 }
diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c
index 0f3473d..4241d2a 100644
--- a/drivers/staging/et131x/et1310_tx.c
+++ b/drivers/staging/et131x/et1310_tx.c
@@ -547,7 +547,7 @@ static int nic_send_packet(struct et131x_adapter *etdev, struct tcb *tcb)
 	tcb->index_start = etdev->tx_ring.send_idx;
 	tcb->stale = 0;
 
-	spin_lock_irqsave(&etdev->SendHWLock, flags);
+	spin_lock_irqsave(&etdev->send_hw_lock, flags);
 
 	thiscopy = NUM_DESC_PER_RING_TX -
 				INDEX10(etdev->tx_ring.send_idx);
@@ -613,7 +613,7 @@ static int nic_send_packet(struct et131x_adapter *etdev, struct tcb *tcb)
 		writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO,
 		       &etdev->regs->global.watchdog_timer);
 	}
-	spin_unlock_irqrestore(&etdev->SendHWLock, flags);
+	spin_unlock_irqrestore(&etdev->send_hw_lock, flags);
 
 	return 0;
 }
diff --git a/drivers/staging/et131x/et131x.h b/drivers/staging/et131x/et131x.h
index a8abfe6..8aa3365 100644
--- a/drivers/staging/et131x/et131x.h
+++ b/drivers/staging/et131x/et131x.h
@@ -126,9 +126,9 @@ void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
 int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter);
 void et131x_rx_dma_memory_free(struct et131x_adapter *adapter);
 int et131x_rfd_resources_alloc(struct et131x_adapter *adapter,
-			       struct _MP_RFD *pMpRfd);
+			       struct rfd *rfd);
 void et131x_rfd_resources_free(struct et131x_adapter *adapter,
-			       struct _MP_RFD *pMpRfd);
+			       struct rfd *rfd);
 int et131x_init_recv(struct et131x_adapter *adapter);
 
 void ConfigRxDmaRegs(struct et131x_adapter *adapter);
diff --git a/drivers/staging/et131x/et131x_adapter.h b/drivers/staging/et131x/et131x_adapter.h
index 64a678f..c852f86 100644
--- a/drivers/staging/et131x/et131x_adapter.h
+++ b/drivers/staging/et131x/et131x_adapter.h
@@ -83,21 +83,19 @@
 #define LO_MARK_PERCENT_FOR_RX      15
 
 /* RFD (Receive Frame Descriptor) */
-typedef struct _MP_RFD {
+struct rfd {
 	struct list_head list_node;
-	struct sk_buff *Packet;
-	u32 PacketSize;	/* total size of receive frame */
+	struct sk_buff *skb;
+	u32 len;	/* total size of receive frame */
 	u16 bufferindex;
 	u8 ringindex;
-} MP_RFD, *PMP_RFD;
+};
 
-/* Enum for Flow Control */
-typedef enum _eflow_control_t {
-	Both = 0,
-	TxOnly = 1,
-	RxOnly = 2,
-	None = 3
-} eFLOW_CONTROL_t, *PeFLOW_CONTROL_t;
+/* Flow Control */
+#define FLOW_BOTH	0
+#define FLOW_TXONLY	1
+#define FLOW_RXONLY	2
+#define FLOW_NONE	3
 
 /* Struct to define some device statistics */
 typedef struct _ce_stats_t {
@@ -147,19 +145,6 @@ typedef struct _ce_stats_t {
 	u32 InterruptStatus;
 } CE_STATS_t, *PCE_STATS_t;
 
-typedef struct _MP_POWER_MGMT {
-	/* variable putting the phy into coma mode when boot up with no cable
-	 * plugged in after 5 seconds
-	 */
-	u8 TransPhyComaModeOnBoot;
-
-	/* Next two used to save power information at power down. This
-	 * information will be used during power up to set up parts of Power
-	 * Management in JAGCore
-	 */
-	u16 PowerDownSpeed;
-	u8 PowerDownDuplex;
-} MP_POWER_MGMT, *PMP_POWER_MGMT;
 
 /* The private adapter structure */
 struct et131x_adapter {
@@ -173,19 +158,19 @@ struct et131x_adapter {
 	u32 HwErrCount;
 
 	/* Configuration  */
-	u8 PermanentAddress[ETH_ALEN];
-	u8 CurrentAddress[ETH_ALEN];
+	u8 rom_addr[ETH_ALEN];
+	u8 addr[ETH_ALEN];
 	bool has_eeprom;
-	u8 eepromData[2];
+	u8 eeprom_data[2];
 
 	/* Spinlocks */
 	spinlock_t Lock;
 
 	spinlock_t TCBSendQLock;
 	spinlock_t TCBReadyQLock;
-	spinlock_t SendHWLock;
+	spinlock_t send_hw_lock;
 
-	spinlock_t RcvLock;
+	spinlock_t rcv_lock;
 	spinlock_t RcvPendLock;
 	spinlock_t FbrLock;
 
@@ -205,7 +190,7 @@ struct et131x_adapter {
 
 	/* Registry parameters */
 	u8 SpeedDuplex;		/* speed/duplex */
-	eFLOW_CONTROL_t RegistryFlowControl;	/* for 802.3x flow control */
+	u8 wanted_flow;		/* Flow we want for 802.3x flow control */
 	u8 RegistryPhyComa;	/* Phy Coma mode enable/disable */
 
 	u32 RegistryRxMemEnd;	/* Size of internal rx memory */
@@ -214,8 +199,8 @@ struct et131x_adapter {
 
 	/* Derived from the registry: */
 	u8 AiForceDpx;		/* duplex setting */
-	u16 AiForceSpeed;		/* 'Speed', user over-ride of line speed */
-	eFLOW_CONTROL_t FlowControl;	/* flow control validated by the far-end */
+	u16 AiForceSpeed;	/* 'Speed', user over-ride of line speed */
+	u8 flowcontrol;		/* flow control validated by the far-end */
 	enum {
 		NETIF_STATUS_INVALID = 0,
 		NETIF_STATUS_MEDIA_CONNECT,
@@ -225,7 +210,19 @@ struct et131x_adapter {
 
 	/* Minimize init-time */
 	struct timer_list ErrorTimer;
-	MP_POWER_MGMT PoMgmt;
+
+	/* variable putting the phy into coma mode when boot up with no cable
+	 * plugged in after 5 seconds
+	 */
+	u8 boot_coma;
+
+	/* Next two used to save power information at power down. This
+	 * information will be used during power up to set up parts of Power
+	 * Management in JAGCore
+	 */
+	u16 pdown_speed;
+	u8 pdown_duplex;
+
 	u32 CachedMaskValue;
 
 	/* Xcvr status at last poll */
diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c
index f62ba7a..50237ac 100644
--- a/drivers/staging/et131x/et131x_initpci.c
+++ b/drivers/staging/et131x/et131x_initpci.c
@@ -131,32 +131,32 @@ void et131x_hwaddr_init(struct et131x_adapter *adapter)
 	 * EEPROM then we need to generate the last octet and set it on the
 	 * device
 	 */
-	if (adapter->PermanentAddress[0] == 0x00 &&
-	    adapter->PermanentAddress[1] == 0x00 &&
-	    adapter->PermanentAddress[2] == 0x00 &&
-	    adapter->PermanentAddress[3] == 0x00 &&
-	    adapter->PermanentAddress[4] == 0x00 &&
-	    adapter->PermanentAddress[5] == 0x00) {
+	if (adapter->rom_addr[0] == 0x00 &&
+	    adapter->rom_addr[1] == 0x00 &&
+	    adapter->rom_addr[2] == 0x00 &&
+	    adapter->rom_addr[3] == 0x00 &&
+	    adapter->rom_addr[4] == 0x00 &&
+	    adapter->rom_addr[5] == 0x00) {
 		/*
 		 * We need to randomly generate the last octet so we
 		 * decrease our chances of setting the mac address to
 		 * same as another one of our cards in the system
 		 */
-		get_random_bytes(&adapter->CurrentAddress[5], 1);
+		get_random_bytes(&adapter->addr[5], 1);
 		/*
 		 * We have the default value in the register we are
 		 * working with so we need to copy the current
 		 * address into the permanent address
 		 */
-		memcpy(adapter->PermanentAddress,
-			adapter->CurrentAddress, ETH_ALEN);
+		memcpy(adapter->rom_addr,
+			adapter->addr, ETH_ALEN);
 	} else {
 		/* We do not have an override address, so set the
 		 * current address to the permanent address and add
 		 * it to the device
 		 */
-		memcpy(adapter->CurrentAddress,
-		       adapter->PermanentAddress, ETH_ALEN);
+		memcpy(adapter->addr,
+		       adapter->rom_addr, ETH_ALEN);
 	}
 }
 
@@ -193,17 +193,17 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
 	max_payload &= 0x07;	/* Only the lower 3 bits are valid */
 
 	if (max_payload < 2) {
-		static const u16 AckNak[2] = { 0x76, 0xD0 };
-		static const u16 Replay[2] = { 0x1E0, 0x2ED };
+		static const u16 acknak[2] = { 0x76, 0xD0 };
+		static const u16 replay[2] = { 0x1E0, 0x2ED };
 
 		if (pci_write_config_word(pdev, ET1310_PCI_ACK_NACK,
-					       AckNak[max_payload])) {
+					       acknak[max_payload])) {
 			dev_err(&pdev->dev,
 			  "Could not write PCI config space for ACK/NAK\n");
 			return -EIO;
 		}
 		if (pci_write_config_word(pdev, ET1310_PCI_REPLAY,
-					       Replay[max_payload])) {
+					       replay[max_payload])) {
 			dev_err(&pdev->dev,
 			  "Could not write PCI config space for Replay Timer\n");
 			return -EIO;
@@ -245,12 +245,12 @@ static int et131x_pci_init(struct et131x_adapter *adapter,
 
 	for (i = 0; i < ETH_ALEN; i++) {
 		if (pci_read_config_byte(pdev, ET1310_PCI_MAC_ADDRESS + i,
-					adapter->PermanentAddress + i)) {
+					adapter->rom_addr + i)) {
 			dev_err(&pdev->dev, "Could not read PCI config space for MAC address\n");
 			return -EIO;
 		}
 	}
-	memcpy(adapter->CurrentAddress, adapter->PermanentAddress, ETH_ALEN);
+	memcpy(adapter->addr, adapter->rom_addr, ETH_ALEN);
 	return 0;
 }
 
@@ -276,11 +276,11 @@ void et131x_error_timer_handler(unsigned long data)
 
 	if (!etdev->Bmsr.bits.link_status &&
 	    etdev->RegistryPhyComa &&
-	    etdev->PoMgmt.TransPhyComaModeOnBoot < 11) {
-		etdev->PoMgmt.TransPhyComaModeOnBoot++;
+	    etdev->boot_coma < 11) {
+		etdev->boot_coma++;
 	}
 
-	if (etdev->PoMgmt.TransPhyComaModeOnBoot == 10) {
+	if (etdev->boot_coma == 10) {
 		if (!etdev->Bmsr.bits.link_status
 		    && etdev->RegistryPhyComa) {
 			if ((pm_csr & ET_PM_PHY_SW_COMA) == 0) {
@@ -555,8 +555,8 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
 	spin_lock_init(&etdev->Lock);
 	spin_lock_init(&etdev->TCBSendQLock);
 	spin_lock_init(&etdev->TCBReadyQLock);
-	spin_lock_init(&etdev->SendHWLock);
-	spin_lock_init(&etdev->RcvLock);
+	spin_lock_init(&etdev->send_hw_lock);
+	spin_lock_init(&etdev->rcv_lock);
 	spin_lock_init(&etdev->RcvPendLock);
 	spin_lock_init(&etdev->FbrLock);
 	spin_lock_init(&etdev->PHYLock);
@@ -570,7 +570,7 @@ static struct et131x_adapter *et131x_adapter_init(struct net_device *netdev,
 	etdev->RegistryJumboPacket = 1514;	/* 1514-9216 */
 
 	/* Set the MAC address to a default */
-	memcpy(etdev->CurrentAddress, default_mac, ETH_ALEN);
+	memcpy(etdev->addr, default_mac, ETH_ALEN);
 
 	/* Decode SpeedDuplex
 	 *
@@ -711,7 +711,7 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
 	INIT_WORK(&adapter->task, et131x_isr_handler);
 
 	/* Copy address into the net_device struct */
-	memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN);
+	memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN);
 
 	/* Setup et1310 as per the documentation */
 	et131x_adapter_setup(adapter);
@@ -728,7 +728,7 @@ static int __devinit et131x_pci_setup(struct pci_dev *pdev,
 
 	/* Initialize variable for counting how long we do not have
 							link status */
-	adapter->PoMgmt.TransPhyComaModeOnBoot = 0;
+	adapter->boot_coma = 0;
 
 	/* We can enable interrupts now
 	 *
diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c
index 36f68fe..ce4d930 100644
--- a/drivers/staging/et131x/et131x_isr.c
+++ b/drivers/staging/et131x/et131x_isr.c
@@ -119,7 +119,7 @@ void et131x_enable_interrupts(struct et131x_adapter *adapter)
 	u32 mask;
 
 	/* Enable all global interrupts */
-	if (adapter->FlowControl == TxOnly || adapter->FlowControl == Both)
+	if (adapter->flowcontrol == FLOW_TXONLY || adapter->flowcontrol == FLOW_BOTH)
 		mask = INT_MASK_ENABLE;
 	else
 		mask = INT_MASK_ENABLE_NO_FLOW;
@@ -177,8 +177,8 @@ irqreturn_t et131x_isr(int irq, void *dev_id)
 	 */
 	status = readl(&adapter->regs->global.int_status);
 
-	if (adapter->FlowControl == TxOnly ||
-	    adapter->FlowControl == Both) {
+	if (adapter->flowcontrol == FLOW_TXONLY ||
+	    adapter->flowcontrol == FLOW_BOTH) {
 		status &= ~INT_MASK_ENABLE;
 	} else {
 		status &= ~INT_MASK_ENABLE_NO_FLOW;
@@ -295,8 +295,8 @@ void et131x_isr_handler(struct work_struct *work)
 			/* If the user has flow control on, then we will
 			 * send a pause packet, otherwise just exit
 			 */
-			if (etdev->FlowControl == TxOnly ||
-			    etdev->FlowControl == Both) {
+			if (etdev->flowcontrol == FLOW_TXONLY ||
+			    etdev->flowcontrol == FLOW_BOTH) {
 				u32 pm_csr;
 
 				/* Tell the device to send a pause packet via
@@ -366,7 +366,7 @@ void et131x_isr_handler(struct work_struct *work)
 		if (status & ET_INTR_PHY) {
 			u32 pm_csr;
 			MI_BMSR_t BmsrInts, BmsrData;
-			MI_ISR_t myIsr;
+			u16 myisr;
 
 			/* If we are in coma mode when we get this interrupt,
 			 * we need to disable it.
@@ -384,12 +384,12 @@ void et131x_isr_handler(struct work_struct *work)
 			/* Read the PHY ISR to clear the reason for the
 			 * interrupt.
 			 */
-			MiRead(etdev, (uint8_t) offsetof(MI_REGS_t, isr),
-			       &myIsr.value);
+			MiRead(etdev, (uint8_t) offsetof(struct mi_regs, isr),
+			       &myisr);
 
 			if (!etdev->ReplicaPhyLoopbk) {
 				MiRead(etdev,
-				       (uint8_t) offsetof(MI_REGS_t, bmsr),
+				       (uint8_t) offsetof(struct mi_regs, bmsr),
 				       &BmsrData.value);
 
 				BmsrInts.value =
diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c
index 106d548..0c298ca 100644
--- a/drivers/staging/et131x/et131x_netdev.c
+++ b/drivers/staging/et131x/et131x_netdev.c
@@ -603,7 +603,7 @@ int et131x_change_mtu(struct net_device *netdev, int new_mtu)
 	et131x_init_send(adapter);
 
 	et131x_hwaddr_init(adapter);
-	memcpy(netdev->dev_addr, adapter->CurrentAddress, ETH_ALEN);
+	memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN);
 
 	/* Init the device with the new settings */
 	et131x_adapter_setup(adapter);
diff --git a/drivers/staging/ft1000/Kconfig b/drivers/staging/ft1000/Kconfig
index d6da130..c54b4e8 100644
--- a/drivers/staging/ft1000/Kconfig
+++ b/drivers/staging/ft1000/Kconfig
@@ -13,7 +13,7 @@ config FT1000_USB
 
 config FT1000_PCMCIA
 	tristate "Driver for ft1000 pcmcia device."
-	depends on PCMCIA && BROKEN
+	depends on PCMCIA
 	depends on NET
 	help
 	  Say Y if you want to have support for Flarion card also called
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
index 2163eae..10af477 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.c
@@ -39,9 +39,6 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
-//#include <pcmcia/version.h>		// Slavius 21.10.2009 removed from kernel
-#include <pcmcia/cs_types.h>
-#include <pcmcia/cs.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -51,8 +48,6 @@
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
-#include "ft1000_cs.h"			// Slavius 21.10.2009 because CS_SUCCESS constant is missing due to removed pcmcia/version.h
-
 /*====================================================================*/
 
 /* Module parameters */
@@ -82,9 +77,8 @@ MODULE_LICENSE("GPL");
 
 /*====================================================================*/
 
-struct net_device *init_ft1000_card(int, int, unsigned char *,
-					void *ft1000_reset, struct pcmcia_device * link,
-					struct device *fdev);
+struct net_device *init_ft1000_card(struct pcmcia_device *link,
+					void *ft1000_reset);
 void stop_ft1000_card(struct net_device *);
 
 static int ft1000_config(struct pcmcia_device *link);
@@ -111,73 +105,7 @@ typedef struct local_info_t {
 
 static void ft1000_reset(struct pcmcia_device * link)
 {
-	conf_reg_t reg;
-
-	DEBUG(0, "ft1000_cs:ft1000_reset is called................\n");
-
-	/* Soft-Reset card */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = COR_SOFT_RESET;
-	pcmcia_access_configuration_register(link, &reg);
-
-	/* Wait until the card has acknowledged our reset */
-	udelay(2);
-
-	/* Restore original COR configuration index */
-	/* Need at least 2 write to respond */
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = COR_DEFAULT;
-	pcmcia_access_configuration_register(link, &reg);
-
-	/* Wait until the card has finished restarting */
-	udelay(1);
-
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = COR_DEFAULT;
-	pcmcia_access_configuration_register(link, &reg);
-
-	/* Wait until the card has finished restarting */
-	udelay(1);
-
-	reg.Action = CS_WRITE;
-	reg.Offset = CISREG_COR;
-	reg.Value = COR_DEFAULT;
-	pcmcia_access_configuration_register(link, &reg);
-
-	/* Wait until the card has finished restarting */
-	udelay(1);
-
-}
-
-/*====================================================================*/
-
-static int get_tuple_first(struct pcmcia_device *link, tuple_t * tuple,
-			   cisparse_t * parse)
-{
-	int i;
-	i = pcmcia_get_first_tuple(link, tuple);
-	if (i != CS_SUCCESS)
-		return i;
-	i = pcmcia_get_tuple_data(link, tuple);
-	if (i != CS_SUCCESS)
-		return i;
-	return pcmcia_parse_tuple(tuple, parse);	// Slavius 21.10.2009 removed unused link parameter
-}
-
-static int get_tuple_next(struct pcmcia_device *link, tuple_t * tuple,
-			  cisparse_t * parse)
-{
-	int i;
-	i = pcmcia_get_next_tuple(link, tuple);
-	if (i != CS_SUCCESS)
-		return i;
-	i = pcmcia_get_tuple_data(link, tuple);
-	if (i != CS_SUCCESS)
-		return i;
-	return pcmcia_parse_tuple(tuple, parse);	// Slavius 21.10.2009 removed unused link parameter
+	pcmcia_reset_card(link->socket);
 }
 
 /*======================================================================
@@ -192,23 +120,19 @@ static int ft1000_attach(struct pcmcia_device *link)
 
 	DEBUG(0, "ft1000_cs: ft1000_attach()\n");
 
-	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+	local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
 	if (!local) {
 		return -ENOMEM;
 	}
-	memset(local, 0, sizeof(local_info_t));
 	local->link = link;
 
 	link->priv = local;
 	local->dev = NULL;
 
-	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
-	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-	link->conf.Attributes = CONF_ENABLE_IRQ;
-	link->conf.IntType = INT_MEMORY_AND_IO;
-	link->irq.Handler = NULL;
+	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
 
 	return ft1000_config(link);
+
 }				/* ft1000_attach */
 
 /*======================================================================
@@ -235,7 +159,7 @@ static void ft1000_detach(struct pcmcia_device *link)
 		stop_ft1000_card(dev);
 	}
 
-	ft1000_release(link);
+	pcmcia_disable_device(link);
 
 	/* This points to the parent local_info_t struct */
 	free_netdev(dev);
@@ -244,166 +168,53 @@ static void ft1000_detach(struct pcmcia_device *link)
 
 /*======================================================================
 
+   Check if the io window is configured
+
+======================================================================*/
+int ft1000_confcheck(struct pcmcia_device *link, void *priv_data)
+{
+
+	return pcmcia_request_io(link);
+}				/* ft1000_confcheck */
+
+/*======================================================================
+
     ft1000_config() is scheduled to run after a CARD_INSERTION event
     is received, to configure the PCMCIA socket, and to make the
     device available to the system.
 
 ======================================================================*/
 
-#define CS_CHECK(fn, ret) \
-	do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-
-#define CFG_CHECK(fn, ret) \
-	last_fn = (fn); if ((last_ret = (ret)) != 0) goto next_entry
-
-static int ft1000_config(struct pcmcia_device * link)
+static int ft1000_config(struct pcmcia_device *link)
 {
-	tuple_t tuple;
-	cisparse_t parse;
-	int last_fn, last_ret, i;
-	u_char buf[64];
-	cistpl_lan_node_id_t *node_id;
-	cistpl_cftable_entry_t dflt = { 0 };
-	cistpl_cftable_entry_t *cfg;
-	unsigned char mac_address[6];
+	int  ret;
 
-	DEBUG(0, "ft1000_cs: ft1000_config(0x%p)\n", link);
-
-	/*
-	   This reads the card's CONFIG tuple to find its configuration
-	   registers.
-	 */
-//	tuple.DesiredTuple = CISTPL_CONFIG;
-//	tuple.Attributes = 0;
-	tuple.TupleData = buf;
-	tuple.TupleDataMax = sizeof(buf);
-	tuple.TupleOffset = 0;
-//	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-//	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
-//	CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
-//	link->conf.ConfigBase = parse.config.base;
-//	link->conf.Present = parse.config.rmask[0];
+	dev_dbg(&link->dev, "ft1000_cs: ft1000_config(0x%p)\n", link);
 
-	/*
-	   In this loop, we scan the CIS for configuration table entries,
-	   each of which describes a valid card configuration, including
-	   voltage, IO window, memory window, and interrupt settings.
-
-	   We make no assumptions about the card to be configured: we use
-	   just the information available in the CIS.  In an ideal world,
-	   this would work for any PCMCIA card, but it requires a complete
-	   and accurate CIS.  In practice, a driver usually "knows" most of
-	   these things without consulting the CIS, and most client drivers
-	   will only use the CIS to fill in implementation-defined details.
-	 */
-	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-	tuple.Attributes = 0;
-	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-	while (1) {
-		cfg = &(parse.cftable_entry);
-		CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
-		CFG_CHECK(ParseTuple,
-			  pcmcia_parse_tuple(&tuple, &parse));		// Slavius 21.10.2009 removed unused link parameter
-
-		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
-			dflt = *cfg;
-		if (cfg->index == 0)
-			goto next_entry;
-		link->conf.ConfigIndex = cfg->index;
-
-		/* Do we need to allocate an interrupt? */
-		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-			link->conf.Attributes |= CONF_ENABLE_IRQ;
-
-		/* IO window settings */
-		link->io.NumPorts1 = link->io.NumPorts2 = 0;
-		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
-			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
-			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-			if (!(io->flags & CISTPL_IO_8BIT)) {
-				DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_16\n");
-				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
-			}
-			if (!(io->flags & CISTPL_IO_16BIT)) {
-				DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_8\n");
-				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-			}
-			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
-			link->io.BasePort1 = io->win[0].base;
-			link->io.NumPorts1 = io->win[0].len;
-			if (io->nwin > 1) {
-				link->io.Attributes2 = link->io.Attributes1;
-				link->io.BasePort2 = io->win[1].base;
-				link->io.NumPorts2 = io->win[1].len;
-			}
-			/* This reserves IO space but doesn't actually enable it */
-			pcmcia_request_io(link, &link->io);
-		}
-
-		break;
-
-	 next_entry:
-		last_ret = pcmcia_get_next_tuple(link, &tuple);
-	}
-	if (last_ret != CS_SUCCESS) {
-		cs_error(link, RequestIO, last_ret);
-		goto failed;
+	/* setup IO window */
+	ret = pcmcia_loop_config(link, ft1000_confcheck, NULL);
+	if (ret) {
+		printk(KERN_INFO "ft1000: Could not configure pcmcia\n");
+		return -ENODEV;
 	}
 
-	/*
-	   Allocate an interrupt line.  Note that this does not assign a
-	   handler to the interrupt, unless the 'Handler' member of the
-	   irq structure is initialized.
-	 */
-		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
-
-	/*
-	   This actually configures the PCMCIA socket -- setting up
-	   the I/O windows and the interrupt mapping, and putting the
-	   card and host interface into "Memory and IO" mode.
-	 */
-	CS_CHECK(RequestConfiguration,
-		 pcmcia_request_configuration(link, &link->conf));
-
-	/* Get MAC address from tuples */
-
-	tuple.Attributes = tuple.TupleOffset = 0;
-	tuple.TupleData = buf;
-	tuple.TupleDataMax = sizeof(buf);
-
-	/* Check for a LAN function extension tuple */
-	tuple.DesiredTuple = CISTPL_FUNCE;
-	i = get_tuple_first(link, &tuple, &parse);
-	while (i == CS_SUCCESS) {
-		if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID)
-			break;
-		i = get_tuple_next(link, &tuple, &parse);
+	/* configure device */
+	ret = pcmcia_enable_device(link);
+	if (ret) {
+		printk(KERN_INFO "ft1000: could not enable pcmcia\n");
+		goto failed;
 	}
 
-	if (i == CS_SUCCESS) {
-		node_id = (cistpl_lan_node_id_t *) parse.funce.data;
-		if (node_id->nb == 6) {
-			for (i = 0; i < 6; i++)
-				mac_address[i] = node_id->id[i];
-		}
+	((local_info_t *) link->priv)->dev = init_ft1000_card(link,
+								&ft1000_reset);
+	if (((local_info_t *) link->priv)->dev == NULL) {
+		printk(KERN_INFO "ft1000: Could not register as network device\n");
+		goto failed;
 	}
 
-	((local_info_t *) link->priv)->dev =
-		init_ft1000_card(link->irq.AssignedIRQ, link->io.BasePort1,
-				 &mac_address[0], ft1000_reset, link,
-				 &handle_to_dev(link));
-
-	/*
-	   At this point, the dev_node_t structure(s) need to be
-	   initialized and arranged in a linked list at link->dev.
-	 */
-
 	/* Finally, report what we've done */
 
 	return 0;
-
-cs_failed:
-	cs_error(link, last_fn, last_ret);
 failed:
 	ft1000_release(link);
 	return -ENODEV;
@@ -429,14 +240,11 @@ static void ft1000_release(struct pcmcia_device * link)
 	   no one will try to access the device or its data structures.
 	 */
 
-	/* Unlink the device chain */
-	link->dev_node = NULL;
-
 	/*
 	   In a normal driver, additional code may be needed to release
 	   other kernel data structures associated with this device.
 	 */
-
+	kfree((local_info_t *) link->priv);
 	/* Don't bother checking to see if these succeed or not */
 
 	 pcmcia_disable_device(link);
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.h
deleted file mode 100644
index 2b5e383..0000000
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_cs.h
+++ /dev/null
@@ -1 +0,0 @@
-#define CS_SUCCESS	0x00
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
index 0bf398d..b0729fc 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_dnld.c
@@ -30,7 +30,6 @@
 #include <linux/netdevice.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
-#include <linux/slab.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
@@ -310,7 +309,7 @@ USHORT hdr_checksum(PPSEUDO_HDR pHdr)
 	return chksum;
 }
 
-int card_download(struct net_device *dev, void *pFileStart, UINT FileLength)
+int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength)
 {
 	FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
 	int Status = SUCCESS;
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
index 588afd5..ff691d9 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
@@ -43,6 +43,10 @@
 #include <linux/firmware.h>
 #include <linux/ethtool.h>
 
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
 #ifdef FT_DEBUG
 #define DEBUG(n, args...) printk(KERN_DEBUG args);
 #else
@@ -53,7 +57,7 @@
 #include "ft1000_dev.h"
 #include "ft1000.h"
 
-int card_download(struct net_device *dev, void *pFileStart, UINT FileLength);
+int card_download(struct net_device *dev, const u8 *pFileStart, UINT FileLength);
 
 void ft1000InitProc(struct net_device *dev);
 void ft1000CleanupProc(struct net_device *dev);
@@ -1936,7 +1940,7 @@ int ft1000_copy_down_pkt(struct net_device *dev, u16 * packet, u16 len)
 	}
 
 	info->stats.tx_packets++;
-	// Add 14 bytes for MAC adddress plus ethernet type
+	// Add 14 bytes for MAC address plus ethernet type
 	info->stats.tx_bytes += (len + 14);
 	return SUCCESS;
 }
@@ -2148,13 +2152,11 @@ static const struct ethtool_ops ops = {
 	.get_link = ft1000_get_link
 };
 
-struct net_device *init_ft1000_card(unsigned short irq, int port,
-					unsigned char *mac_addr, void *ft1000_reset,
-					void *link, struct device *fdev)
+struct net_device *init_ft1000_card(struct pcmcia_device *link,
+					void *ft1000_reset)
 {
 	FT1000_INFO *info;
 	struct net_device *dev;
-	int i;
 
 	static const struct net_device_ops ft1000ops =		// Slavius 21.10.2009 due to kernel changes
 	{
@@ -2165,8 +2167,8 @@ struct net_device *init_ft1000_card(unsigned short irq, int port,
 	};
 
 	DEBUG(1, "ft1000_hw: init_ft1000_card()\n");
-	DEBUG(1, "ft1000_hw: irq = %d\n", irq);
-	DEBUG(1, "ft1000_hw: port = 0x%04x\n", port);
+	DEBUG(1, "ft1000_hw: irq = %d\n", link->irq);
+	DEBUG(1, "ft1000_hw: port = 0x%04x\n", link->resource[0]->start);
 
 	flarion_ft1000_cnt++;
 
@@ -2184,7 +2186,7 @@ struct net_device *init_ft1000_card(unsigned short irq, int port,
 		return NULL;
 	}
 
-	SET_NETDEV_DEV(dev, fdev);
+	SET_NETDEV_DEV(dev, &link->dev);
 	info = netdev_priv(dev);
 
 	memset(info, 0, sizeof(FT1000_INFO));
@@ -2227,15 +2229,13 @@ struct net_device *init_ft1000_card(unsigned short irq, int port,
 
 	DEBUG(0, "device name = %s\n", dev->name);
 
-	for (i = 0; i < 6; i++) {
-		dev->dev_addr[i] = mac_addr[i];
-		DEBUG(1, "ft1000_hw: mac_addr %d = 0x%02x\n", i, mac_addr[i]);
+	dev->irq = link->irq;
+	dev->base_addr = link->resource[0]->start;
+	if (pcmcia_get_mac_from_cis(link, dev)) {
+		printk(KERN_ERR "ft1000: Could not read mac address\n");
+		goto err_dev;
 	}
 
-	netif_stop_queue(dev);
-	dev->irq = irq;
-	dev->base_addr = port;
-
 	if (request_irq(dev->irq, ft1000_interrupt, IRQF_SHARED, dev->name, dev)) {
 		printk(KERN_ERR "ft1000: Could not request_irq\n");
 		goto err_dev;
@@ -2254,13 +2254,13 @@ struct net_device *init_ft1000_card(unsigned short irq, int port,
 	info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID);
 	if (info->AsicID == ELECTRABUZZ_ID) {
 		DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n");
-		if (request_firmware(&fw_entry, "ft1000.img", fdev) != 0) {
+		if (request_firmware(&fw_entry, "ft1000.img", &link->dev) != 0) {
 			printk(KERN_INFO "ft1000: Could not open ft1000.img\n");
 			goto err_unreg;
 		}
 	} else {
 		DEBUG(0, "ft1000_hw: MAGNEMITE ASIC\n");
-		if (request_firmware(&fw_entry, "ft2000.img", fdev) != 0) {
+		if (request_firmware(&fw_entry, "ft2000.img", &link->dev) != 0) {
 			printk(KERN_INFO "ft1000: Could not open ft2000.img\n");
 			goto err_unreg;
 		}
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
index 149ba59..19db23f 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
@@ -471,14 +471,14 @@ static long ft1000_ioctl (struct file *file, unsigned int command,
         // Connect Message
         DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_CONNECT\n");
         ConnectionMsg[79] = 0xfc;
-			   CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
+			   card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
 
         break;
     case IOCTL_DISCONNECT:
         // Disconnect Message
         DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_DISCONNECT\n");
         ConnectionMsg[79] = 0xfd;
-			   CardSendCommand(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
+			   card_send_command(ft1000dev, (unsigned short *)ConnectionMsg, 0x4c);
         break;
     case IOCTL_GET_DSP_STAT_CMD:
         //DEBUG("FT1000:ft1000_ioctl: IOCTL_FT1000_GET_DSP_STAT called\n");
@@ -642,7 +642,7 @@ static long ft1000_ioctl (struct file *file, unsigned int command,
                             }
                             pmsg++;
 				ppseudo_hdr = (struct pseudo_hdr *)pmsg;
-                           CardSendCommand(ft1000dev,(unsigned short*)dpram_data,total_len+2);
+                           card_send_command(ft1000dev,(unsigned short*)dpram_data,total_len+2);
 
 
                             info->app_info[app_index].nTxMsg++;
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
index 17546d8..8e62242 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
@@ -125,65 +125,48 @@ struct dsp_image_info {
 //---------------------------------------------------------------------------
 static u32 check_usb_db (struct ft1000_device *ft1000dev)
 {
-   int               loopcnt;
-   u16            temp;
-   u32             status;
-
-   loopcnt = 0;
-   while (loopcnt < 10)
-   {
-
-      status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_DOORBELL);
-      DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n", temp);
-      if (temp & 0x0080)
-      {
-           DEBUG("FT1000:Got checkusb doorbell\n");
-           status = ft1000_write_register (ft1000dev, 0x0080, FT1000_REG_DOORBELL);
-           status = ft1000_write_register (ft1000dev, 0x0100, FT1000_REG_DOORBELL);
-           status = ft1000_write_register (ft1000dev,  0x8000, FT1000_REG_DOORBELL);
-           break;
-      }
-      else
-      {
-           loopcnt++;
-           msleep (10);
-      }
-
-   } //end of while
-
-
-   loopcnt = 0;
-   while (loopcnt < 20)
-   {
-
-      status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_DOORBELL);
-      DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp);
-      if (temp & 0x8000)
-      {
-         loopcnt++;
-         msleep (10);
-      }
-      else
-      {
-         DEBUG("check_usb_db: door bell is cleared, return 0\n");
-         return 0;
-      }
-#if 0
-      // Check if Card is present
-      status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_SUP_IMASK);
-      if (temp == 0x0000) {
-          break;
-      }
-
-      status = ft1000_read_register (ft1000dev, &temp, FT1000_REG_ASIC_ID);
-      if (temp == 0xffff) {
-         break;
-      }
-#endif
-   }
+	int loopcnt;
+	u16 temp;
+	u32 status;
+
+	loopcnt = 0;
+
+	while (loopcnt < 10) {
+		status = ft1000_read_register(ft1000dev, &temp,
+					       FT1000_REG_DOORBELL);
+		DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n",
+		       temp);
+		if (temp & 0x0080) {
+			DEBUG("FT1000:Got checkusb doorbell\n");
+			status = ft1000_write_register(ft1000dev, 0x0080,
+						FT1000_REG_DOORBELL);
+			status = ft1000_write_register(ft1000dev, 0x0100,
+						FT1000_REG_DOORBELL);
+			status = ft1000_write_register(ft1000dev,  0x8000,
+						FT1000_REG_DOORBELL);
+			break;
+		} else {
+			loopcnt++;
+			msleep(10);
+		}
 
-   return HANDSHAKE_MAG_TIMEOUT_VALUE;
+	}
+
+	loopcnt = 0;
+	while (loopcnt < 20) {
+		status = ft1000_read_register(ft1000dev, &temp,
+					       FT1000_REG_DOORBELL);
+		DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp);
+		if (temp & 0x8000) {
+			loopcnt++;
+			msleep(10);
+		} else	{
+			DEBUG("check_usb_db: door bell is cleared, return 0\n");
+			return 0;
+		}
+	}
 
+	return HANDSHAKE_MAG_TIMEOUT_VALUE;
 }
 
 //---------------------------------------------------------------------------
@@ -202,57 +185,49 @@ static u32 check_usb_db (struct ft1000_device *ft1000dev)
 //---------------------------------------------------------------------------
 static u16 get_handshake(struct ft1000_device *ft1000dev, u16 expected_value)
 {
-   u16            handshake;
-   int               loopcnt;
-   u32             status=0;
+	u16 handshake;
+	int loopcnt;
+	u32 status = 0;
 	struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
 
-   loopcnt = 0;
-   while (loopcnt < 100)
-   {
+	loopcnt = 0;
+
+	while (loopcnt < 100) {
+		/* Need to clear downloader doorbell if Hartley ASIC */
+		status = ft1000_write_register(ft1000dev,  FT1000_DB_DNLD_RX,
+						FT1000_REG_DOORBELL);
+		if (pft1000info->fcodeldr) {
+			DEBUG(" get_handshake: fcodeldr is %d\n",
+				pft1000info->fcodeldr);
+			pft1000info->fcodeldr = 0;
+			status = check_usb_db(ft1000dev);
+			if (status != STATUS_SUCCESS) {
+				DEBUG("get_handshake: check_usb_db failed\n");
+				status = STATUS_FAILURE;
+				break;
+			}
+			status = ft1000_write_register(ft1000dev,
+					FT1000_DB_DNLD_RX,
+					FT1000_REG_DOORBELL);
+		}
 
-           // Need to clear downloader doorbell if Hartley ASIC
-           status = ft1000_write_register (ft1000dev,  FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL);
-           //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp);
-               if (pft1000info->fcodeldr)
-               {
-                   DEBUG(" get_handshake: fcodeldr is %d\n", pft1000info->fcodeldr);
-                   pft1000info->fcodeldr = 0;
-                   status = check_usb_db(ft1000dev);
-                   if (status != STATUS_SUCCESS)
-                   {
-                       DEBUG("get_handshake: check_usb_db failed\n");
-                       status = STATUS_FAILURE;
-                       break;
-                   }
-                   status = ft1000_write_register (ft1000dev,  FT1000_DB_DNLD_RX, FT1000_REG_DOORBELL);
-               }
-
-                status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
-                //DEBUG("get_handshake: handshake is %x\n", tempx);
-                handshake = ntohs(handshake);
-                //DEBUG("get_handshake: after swap, handshake is %x\n", handshake);
-
-        if (status)
-           return HANDSHAKE_TIMEOUT_VALUE;
-
-        //DEBUG("get_handshake: handshake= %x\n", handshake);
-        if ((handshake == expected_value) || (handshake == HANDSHAKE_RESET_VALUE_USB))
-        {
-            //DEBUG("get_handshake: return handshake %x\n", handshake);
-            return handshake;
-        }
-        else
-        {
-            loopcnt++;
-            msleep (10);
-        }
-        //DEBUG("HANDSHKE LOOP: %d\n", loopcnt);
+		status = ft1000_read_dpram16(ft1000dev,
+				DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
+		handshake = ntohs(handshake);
 
-   }
+		if (status)
+			return HANDSHAKE_TIMEOUT_VALUE;
+
+		if ((handshake == expected_value) ||
+		    (handshake == HANDSHAKE_RESET_VALUE_USB)) {
+			return handshake;
+		} else	{
+			loopcnt++;
+			msleep(10);
+		}
+	}
 
-   //DEBUG("get_handshake: return handshake time out\n");
-   return HANDSHAKE_TIMEOUT_VALUE;
+	return HANDSHAKE_TIMEOUT_VALUE;
 }
 
 //---------------------------------------------------------------------------
@@ -271,65 +246,74 @@ static u16 get_handshake(struct ft1000_device *ft1000dev, u16 expected_value)
 //---------------------------------------------------------------------------
 static void put_handshake(struct ft1000_device *ft1000dev,u16 handshake_value)
 {
-    u32 tempx;
-    u16 tempword;
-    u32 status;
-
-
-
-        tempx = (u32)handshake_value;
-        tempx = ntohl(tempx);
-
-        tempword = (u16)(tempx & 0xffff);
-        status = ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, tempword, 0);
-        tempword = (u16)(tempx >> 16);
-        status = ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, tempword, 1);
-        status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, FT1000_REG_DOORBELL);
+	u32 tempx;
+	u16 tempword;
+	u32 status;
+
+	tempx = (u32)handshake_value;
+	tempx = ntohl(tempx);
+
+	tempword = (u16)(tempx & 0xffff);
+	status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
+					tempword, 0);
+	tempword = (u16)(tempx >> 16);
+	status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
+					tempword, 1);
+	status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
+					FT1000_REG_DOORBELL);
 }
 
 static u16 get_handshake_usb(struct ft1000_device *ft1000dev, u16 expected_value)
 {
-   u16            handshake;
-   int               loopcnt;
-   u16            temp;
-   u32             status=0;
+	u16 handshake;
+	int loopcnt;
+	u16 temp;
+	u32 status = 0;
 
 	struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
-   loopcnt = 0;
-   handshake = 0;
-   while (loopcnt < 100)
-   {
-       if (pft1000info->usbboot == 2) {
-           status = ft1000_read_dpram32 (ft1000dev, 0, (u8 *)&(pft1000info->tempbuf[0]), 64);
-           for (temp=0; temp<16; temp++)
-               DEBUG("tempbuf %d = 0x%x\n", temp, pft1000info->tempbuf[temp]);
-           status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
-           DEBUG("handshake from read_dpram16 = 0x%x\n", handshake);
-           if (pft1000info->dspalive == pft1000info->tempbuf[6])
-               handshake = 0;
-           else {
-               handshake = pft1000info->tempbuf[1];
-               pft1000info->dspalive = pft1000info->tempbuf[6];
-           }
-       }
-       else {
-           status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
-       }
-       loopcnt++;
-       msleep(10);
-       handshake = ntohs(handshake);
-       if ((handshake == expected_value) || (handshake == HANDSHAKE_RESET_VALUE_USB))
-       {
-           return handshake;
-       }
-   }
+	loopcnt = 0;
+	handshake = 0;
+
+	while (loopcnt < 100) {
+		if (pft1000info->usbboot == 2) {
+			status = ft1000_read_dpram32(ft1000dev, 0,
+					(u8 *)&(pft1000info->tempbuf[0]), 64);
+			for (temp = 0; temp < 16; temp++) {
+				DEBUG("tempbuf %d = 0x%x\n", temp,
+					pft1000info->tempbuf[temp]);
+			}
+			status = ft1000_read_dpram16(ft1000dev,
+						DWNLD_MAG1_HANDSHAKE_LOC,
+						(u8 *)&handshake, 1);
+			DEBUG("handshake from read_dpram16 = 0x%x\n",
+				handshake);
+			if (pft1000info->dspalive == pft1000info->tempbuf[6]) {
+				handshake = 0;
+			} else {
+				handshake = pft1000info->tempbuf[1];
+				pft1000info->dspalive =
+						pft1000info->tempbuf[6];
+			}
+		} else {
+			status = ft1000_read_dpram16(ft1000dev,
+						DWNLD_MAG1_HANDSHAKE_LOC,
+						(u8 *)&handshake, 1);
+		}
+
+		loopcnt++;
+		msleep(10);
+		handshake = ntohs(handshake);
+		if ((handshake == expected_value) ||
+		    (handshake == HANDSHAKE_RESET_VALUE_USB))
+			return handshake;
+	}
 
-   return HANDSHAKE_TIMEOUT_VALUE;
+	return HANDSHAKE_TIMEOUT_VALUE;
 }
 
 static void put_handshake_usb(struct ft1000_device *ft1000dev,u16 handshake_value)
 {
-   int i;
+	int i;
 
         for (i=0; i<1000; i++);
 }
@@ -348,62 +332,56 @@ static void put_handshake_usb(struct ft1000_device *ft1000dev,u16 handshake_valu
 //---------------------------------------------------------------------------
 static u16 get_request_type(struct ft1000_device *ft1000dev)
 {
-   u16   request_type;
-   u32    status;
-   u16   tempword;
-   u32    tempx;
+	u16 request_type;
+	u32 status;
+	u16 tempword;
+	u32 tempx;
 	struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
 
-   if ( pft1000info->bootmode == 1)
-   {
-       status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
-       tempx = ntohl(tempx);
-   }
-   else
-   {
-       tempx = 0;
-
-       status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
-       tempx |= (tempword << 16);
-       tempx = ntohl(tempx);
-   }
-   request_type = (u16)tempx;
-
-   //DEBUG("get_request_type: request_type is %x\n", request_type);
-   return request_type;
-
+	if (pft1000info->bootmode == 1) {
+		status = fix_ft1000_read_dpram32(ft1000dev,
+				DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
+		tempx = ntohl(tempx);
+	} else {
+		tempx = 0;
+		status = ft1000_read_dpram16(ft1000dev,
+				DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
+		tempx |= (tempword << 16);
+		tempx = ntohl(tempx);
+	}
+	request_type = (u16)tempx;
+
+	return request_type;
 }
 
 static u16 get_request_type_usb(struct ft1000_device *ft1000dev)
 {
-   u16   request_type;
-   u32    status;
-   u16   tempword;
-   u32    tempx;
+	u16 request_type;
+	u32 status;
+	u16 tempword;
+	u32 tempx;
 	struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
-   if ( pft1000info->bootmode == 1)
-   {
-       status = fix_ft1000_read_dpram32 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
-       tempx = ntohl(tempx);
-   }
-   else
-   {
-       if (pft1000info->usbboot == 2) {
-          tempx = pft1000info->tempbuf[2];
-          tempword = pft1000info->tempbuf[3];
-       }
-       else {
-          tempx = 0;
-          status = ft1000_read_dpram16 (ft1000dev, DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
-       }
-       tempx |= (tempword << 16);
-       tempx = ntohl(tempx);
-   }
-   request_type = (u16)tempx;
 
-   //DEBUG("get_request_type: request_type is %x\n", request_type);
-   return request_type;
+	if (pft1000info->bootmode == 1) {
+		status = fix_ft1000_read_dpram32(ft1000dev,
+				DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
+		tempx = ntohl(tempx);
+	} else {
+		if (pft1000info->usbboot == 2) {
+			tempx = pft1000info->tempbuf[2];
+			tempword = pft1000info->tempbuf[3];
+		} else {
+			tempx = 0;
+			status = ft1000_read_dpram16(ft1000dev,
+					DWNLD_MAG1_TYPE_LOC,
+					(u8 *)&tempword, 1);
+		}
+		tempx |= (tempword << 16);
+		tempx = ntohl(tempx);
+	}
+	request_type = (u16)tempx;
 
+	return request_type;
 }
 
 //---------------------------------------------------------------------------
@@ -420,60 +398,28 @@ static u16 get_request_type_usb(struct ft1000_device *ft1000dev)
 //---------------------------------------------------------------------------
 static long get_request_value(struct ft1000_device *ft1000dev)
 {
-   u32     value;
-   u16   tempword;
-   u32    status;
+	u32 value;
+	u16 tempword;
+	u32 status;
 	struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
 
-
-       if ( pft1000info->bootmode == 1)
-       {
-	   status = fix_ft1000_read_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&value);
-	   value = ntohl(value);
-       }
-       else
-       {
-	   status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0);
-	   value = tempword;
-           status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
-	   value |= (tempword << 16);
-	   value = ntohl(value);
-       }
-
-
-   //DEBUG("get_request_value: value is %x\n", value);
-   return value;
-
+	if (pft1000info->bootmode == 1) {
+		status = fix_ft1000_read_dpram32(ft1000dev,
+				DWNLD_MAG1_SIZE_LOC, (u8 *)&value);
+		value = ntohl(value);
+	} else	{
+		status = ft1000_read_dpram16(ft1000dev,
+				DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0);
+		value = tempword;
+		status = ft1000_read_dpram16(ft1000dev,
+				DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
+		value |= (tempword << 16);
+		value = ntohl(value);
+	}
+
+	return value;
 }
 
-#if 0
-static long get_request_value_usb(struct ft1000_device *ft1000dev)
-{
-   u32     value;
-   u16   tempword;
-   u32    status;
-   struct ft1000_info * pft1000info = netdev_priv(ft1000dev->net);
-
-       if (pft1000info->usbboot == 2) {
-          value = pft1000info->tempbuf[4];
-          tempword = pft1000info->tempbuf[5];
-       }
-       else {
-          value = 0;
-          status = ft1000_read_dpram16(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
-       }
-
-       value |= (tempword << 16);
-       value = ntohl(value);
-
-   if (pft1000info->usbboot == 1)
-       pft1000info->usbboot = 2;
-
-   //DEBUG("get_request_value_usb: value is %x\n", value);
-   return value;
-
-}
-#endif
 
 //---------------------------------------------------------------------------
 // Function:    put_request_value
@@ -490,16 +436,12 @@ static long get_request_value_usb(struct ft1000_device *ft1000dev)
 //---------------------------------------------------------------------------
 static void put_request_value(struct ft1000_device *ft1000dev, long lvalue)
 {
-   u32    tempx;
-   u32    status;
-
-       tempx = ntohl(lvalue);
-       status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC, (u8 *)&tempx);
-
-
-
-   //DEBUG("put_request_value: value is %x\n", lvalue);
+	u32    tempx;
+	u32    status;
 
+	tempx = ntohl(lvalue);
+	status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
+					  (u8 *)&tempx);
 }
 
 
@@ -518,16 +460,27 @@ static void put_request_value(struct ft1000_device *ft1000dev, long lvalue)
 //---------------------------------------------------------------------------
 static u16 hdr_checksum(struct pseudo_hdr *pHdr)
 {
-   u16   *usPtr = (u16 *)pHdr;
-   u16   chksum;
+	u16   *usPtr = (u16 *)pHdr;
+	u16   chksum;
 
 
-  chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
-                    usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
+	chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
+	usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
 
-  return chksum;
+	return chksum;
 }
 
+static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset)
+{
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if (buff_w[i] != buff_r[i + offset])
+			return -1;
+	}
+
+	return 0;
+}
 
 //---------------------------------------------------------------------------
 // Function:    write_blk
@@ -550,9 +503,7 @@ static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFi
 {
    u32 Status = STATUS_SUCCESS;
    u16 dpram;
-   long temp_word_length;
    int loopcnt, i, j;
-   u16 *pTempFile;
    u16 tempword;
    u16 tempbuffer[64];
    u16 resultbuffer[64];
@@ -571,8 +522,6 @@ static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFi
    word_length--;
    tempword = (u16)word_length;
    word_length = (word_length / 16) + 1;
-   pTempFile = *pUsFile;
-   temp_word_length = word_length;
    for (; word_length > 0; word_length--) /* In words */
    {
 	   loopcnt = 0;
@@ -622,43 +571,31 @@ static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFi
 	    	       Status = ft1000_read_dpram32 (ft1000dev, dpram, (u8 *)&resultbuffer[0], 64);
 		       if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
 		       {
-		           for (i=0; i<28; i++)
-		           {
-			       if (resultbuffer[i] != tempbuffer[i])
-			       {
-			           //NdisMSleep (100);
-                                   DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
-				   msleep(10);
-     	  			   Status = STATUS_FAILURE;
-				   break;
+				if (check_buffers(tempbuffer, resultbuffer, 28, 0)) {
+					DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
+					msleep(10);
+					Status = STATUS_FAILURE;
+					break;
 				}
-			   }
    			   Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (u8 *)&resultbuffer[0], 64);
-		           for (i=0; i<16; i++)
-		           {
-    			       if (resultbuffer[i] != tempbuffer[i+24])
-    			       {
-                                   //NdisMSleep (100);
-                                   DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
-				   msleep(10);
-				   Status = STATUS_FAILURE;
-				   break;
+
+				if (check_buffers(tempbuffer, resultbuffer, 16, 24)) {
+					DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
+					msleep(10);
+					Status = STATUS_FAILURE;
+					break;
 				}
-			   }
+			   
 			}
 			else
 			{
-			    for (i=0; i<32; i++)
-			    {
-    			        if (resultbuffer[i] != tempbuffer[i])
-    			        {
-                                    //NdisMSleep (100);
-                                    DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
-				    msleep(10);
-				    Status = STATUS_FAILURE;
-				    break;
+				if (check_buffers(tempbuffer, resultbuffer, 32, 0)) {
+					DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
+					msleep(10);
+					Status = STATUS_FAILURE;
+					break;
 				}
-			    }
+			    
 			}
 
 			if (Status == STATUS_SUCCESS)
@@ -702,60 +639,35 @@ static void usb_dnld_complete (struct urb *urb)
 // Notes:
 //
 //---------------------------------------------------------------------------
-static u32 write_blk_fifo (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length)
+static u32 write_blk_fifo(struct ft1000_device *ft1000dev, u16 **pUsFile,
+			  u8 **pUcFile, long word_length)
 {
-   u32 Status = STATUS_SUCCESS;
-   int byte_length;
-   long aligncnt;
+	u32 Status = STATUS_SUCCESS;
+	int byte_length;
 
-   byte_length = word_length * 4;
+	byte_length = word_length * 4;
 
-   if (byte_length % 4)
-      aligncnt = 4 - (byte_length % 4);
-   else
-      aligncnt = 0;
-   byte_length += aligncnt;
+	if (byte_length && ((byte_length % 64) == 0))
+		byte_length += 4;
 
-   if (byte_length && ((byte_length % 64) == 0)) {
-      byte_length += 4;
-   }
+	if (byte_length < 64)
+		byte_length = 68;
 
-   if (byte_length < 64)
-       byte_length = 68;
-
-#if 0
-   pblk = kzalloc(byte_length, GFP_KERNEL);
-   memcpy (pblk, *pUcFile, byte_length);
-
-   pipe = usb_sndbulkpipe (ft1000dev->dev, ft1000dev->bulk_out_endpointAddr);
-
-   Status = usb_bulk_msg (ft1000dev->dev,
-                          pipe,
-                          pblk,
-                          byte_length,
-                          &cnt,
-                          10);
-   DEBUG("write_blk_fifo Status = 0x%8x Bytes Transfer = %d Data = 0x%x\n", Status, cnt, *pblk);
-
-   kfree(pblk);
-#else
-    usb_init_urb(ft1000dev->tx_urb);
-    memcpy (ft1000dev->tx_buf, *pUcFile, byte_length);
-    usb_fill_bulk_urb(ft1000dev->tx_urb,
-                      ft1000dev->dev,
-                      usb_sndbulkpipe(ft1000dev->dev, ft1000dev->bulk_out_endpointAddr),
-                      ft1000dev->tx_buf,
-                      byte_length,
-                      usb_dnld_complete,
-                      (void*)ft1000dev);
-
-    usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
-#endif
-
-   *pUsFile = *pUsFile + (word_length << 1);
-   *pUcFile = *pUcFile + (word_length << 2);
+	usb_init_urb(ft1000dev->tx_urb);
+	memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
+	usb_fill_bulk_urb(ft1000dev->tx_urb,
+			  ft1000dev->dev,
+			  usb_sndbulkpipe(ft1000dev->dev,
+					  ft1000dev->bulk_out_endpointAddr),
+			  ft1000dev->tx_buf, byte_length, usb_dnld_complete,
+			  (void *)ft1000dev);
 
-   return Status;
+	usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
+
+	*pUsFile = *pUsFile + (word_length << 1);
+	*pUcFile = *pUcFile + (word_length << 2);
+
+	return Status;
 }
 
 //---------------------------------------------------------------------------
@@ -770,460 +682,534 @@ static u32 write_blk_fifo (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **
 //  Returns:    status                  - return code
 //---------------------------------------------------------------------------
 
-u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, u32  FileLength)
+u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart,
+		u32 FileLength)
 {
-   u16                     status = STATUS_SUCCESS;
-   u32                    state;
-   u16                  handshake;
+	u16 status = STATUS_SUCCESS;
+	u32 state;
+	u16 handshake;
 	struct pseudo_hdr *pseudo_header;
-   u16                  pseudo_header_len;
-   long                    word_length;
-   u16                  request;
-   u16                  temp;
-   u16                  tempword;
+	u16 pseudo_header_len;
+	long word_length;
+	u16 request;
+	u16 temp;
+	u16 tempword;
 
 	struct dsp_file_hdr *file_hdr;
 	struct dsp_image_info *dsp_img_info = NULL;
-   long                    requested_version;
-   bool                 correct_version;
+	long requested_version;
+	bool correct_version;
 	struct drv_msg *mailbox_data;
-   u16                  *data = NULL;
-   u16                  *s_file = NULL;
-   u8                   *c_file = NULL;
-   u8                   *boot_end = NULL, *code_end= NULL;
-   int                     image;
-   long                    loader_code_address, loader_code_size = 0;
-   long                    run_address = 0, run_size = 0;
-
-   u32                   templong;
-   u32                   image_chksum = 0;
-
-   u16                  dpram = 0;
-   u8 *pbuffer;
+	u16 *data = NULL;
+	u16 *s_file = NULL;
+	u8 *c_file = NULL;
+	u8 *boot_end = NULL, *code_end = NULL;
+	int image;
+	long loader_code_address, loader_code_size = 0;
+	long run_address = 0, run_size = 0;
+
+	u32 templong;
+	u32 image_chksum = 0;
+
+	u16 dpram = 0;
+	u8 *pbuffer;
 	struct prov_record *pprov_record;
 	struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
 
-   DEBUG("Entered   scram_dnldr...\n");
+	DEBUG("Entered   scram_dnldr...\n");
 
-   pft1000info->fcodeldr = 0;
-   pft1000info->usbboot = 0;
-   pft1000info->dspalive = 0xffff;
+	pft1000info->fcodeldr = 0;
+	pft1000info->usbboot = 0;
+	pft1000info->dspalive = 0xffff;
 
+	//
+	// Get version id of file, at first 4 bytes of file, for newer files.
+	//
 
-   //
-   // Get version id of file, at first 4 bytes of file, for newer files.
-   //
+	state = STATE_START_DWNLD;
 
-   state = STATE_START_DWNLD;
+	file_hdr = (struct dsp_file_hdr *)pFileStart;
 
-   file_hdr = (struct dsp_file_hdr *)pFileStart;
+	ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
 
-   ft1000_write_register (ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
+	s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
+	c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
 
-      s_file = (u16 *)(pFileStart + file_hdr->loader_offset);
-      c_file = (u8 *)(pFileStart + file_hdr->loader_offset);
+	boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
 
-      boot_end = (u8 *)(pFileStart + file_hdr->loader_code_end);
+	loader_code_address = file_hdr->loader_code_address;
+	loader_code_size = file_hdr->loader_code_size;
+	correct_version = FALSE;
 
-      loader_code_address = file_hdr->loader_code_address;
-      loader_code_size = file_hdr->loader_code_size;
-      correct_version = FALSE;
+	while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) {
+		switch (state) {
+		case STATE_START_DWNLD:
+			DEBUG("FT1000:STATE_START_DWNLD\n");
+			if (pft1000info->usbboot)
+				handshake =
+				    get_handshake_usb(ft1000dev,
+						      HANDSHAKE_DSP_BL_READY);
+			else
+				handshake =
+				    get_handshake(ft1000dev,
+						  HANDSHAKE_DSP_BL_READY);
+
+			if (handshake == HANDSHAKE_DSP_BL_READY) {
+				DEBUG
+				    ("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
+				put_handshake(ft1000dev,
+					      HANDSHAKE_DRIVER_READY);
+			} else {
+				DEBUG
+				    ("FT1000:download:Download error: Handshake failed\n");
+				status = STATUS_FAILURE;
+			}
 
-   while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE))
-   {
-      switch (state)
-      {
-      case  STATE_START_DWNLD:
-         DEBUG("FT1000:STATE_START_DWNLD\n");
-         if (pft1000info->usbboot)
-             handshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY);
-         else
-             handshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY);
-
-         if (handshake == HANDSHAKE_DSP_BL_READY)
-         {
-            DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
-            put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY);
-         }
-         else
-         {
-            DEBUG("FT1000:download:Download error: Handshake failed\n");
-            status = STATUS_FAILURE;
-         }
-
-         state = STATE_BOOT_DWNLD;
-
-         break;
-
-      case STATE_BOOT_DWNLD:
-         DEBUG("FT1000:STATE_BOOT_DWNLD\n");
-         pft1000info->bootmode = 1;
-         handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
-         if (handshake == HANDSHAKE_REQUEST)
-         {
-            /*
-             * Get type associated with the request.
-             */
-            request = get_request_type(ft1000dev);
-            switch (request)
-            {
-            case  REQUEST_RUN_ADDRESS:
-               DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
-               put_request_value(ft1000dev, loader_code_address);
-               break;
-            case  REQUEST_CODE_LENGTH:
-               DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
-               put_request_value(ft1000dev, loader_code_size);
-               break;
-            case  REQUEST_DONE_BL:
-               DEBUG("FT1000:REQUEST_DONE_BL\n");
-               /* Reposition ptrs to beginning of code section */
-               s_file = (u16 *)(boot_end);
-               c_file = (u8 *)(boot_end);
-               //DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file);
-               //DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file);
-               state = STATE_CODE_DWNLD;
-               pft1000info->fcodeldr = 1;
-               break;
-            case  REQUEST_CODE_SEGMENT:
-               //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");
-               word_length = get_request_value(ft1000dev);
-               //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length);
-               //NdisMSleep (100);
-               if (word_length > MAX_LENGTH)
-               {
-                  DEBUG("FT1000:download:Download error: Max length exceeded\n");
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               if ( (word_length*2 + c_file) > boot_end)
-               {
-                  /*
-                   * Error, beyond boot code range.
-                   */
-                  DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundry.\n",
-                                                            (int)word_length);
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               /*
-                * Position ASIC DPRAM auto-increment pointer.
-                */
-				    dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
+			state = STATE_BOOT_DWNLD;
+
+			break;
+
+		case STATE_BOOT_DWNLD:
+			DEBUG("FT1000:STATE_BOOT_DWNLD\n");
+			pft1000info->bootmode = 1;
+			handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
+			if (handshake == HANDSHAKE_REQUEST) {
+				/*
+				 * Get type associated with the request.
+				 */
+				request = get_request_type(ft1000dev);
+				switch (request) {
+				case REQUEST_RUN_ADDRESS:
+					DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
+					put_request_value(ft1000dev,
+							  loader_code_address);
+					break;
+				case REQUEST_CODE_LENGTH:
+					DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
+					put_request_value(ft1000dev,
+							  loader_code_size);
+					break;
+				case REQUEST_DONE_BL:
+					DEBUG("FT1000:REQUEST_DONE_BL\n");
+					/* Reposition ptrs to beginning of code section */
+					s_file = (u16 *) (boot_end);
+					c_file = (u8 *) (boot_end);
+					//DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file);
+					//DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file);
+					state = STATE_CODE_DWNLD;
+					pft1000info->fcodeldr = 1;
+					break;
+				case REQUEST_CODE_SEGMENT:
+					//DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");
+					word_length =
+					    get_request_value(ft1000dev);
+					//DEBUG("FT1000:word_length = 0x%x\n", (int)word_length);
+					//NdisMSleep (100);
+					if (word_length > MAX_LENGTH) {
+						DEBUG
+						    ("FT1000:download:Download error: Max length exceeded\n");
+						status = STATUS_FAILURE;
+						break;
+					}
+					if ((word_length * 2 + c_file) >
+					    boot_end) {
+						/*
+						 * Error, beyond boot code range.
+						 */
+						DEBUG
+						    ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundry.\n",
+						     (int)word_length);
+						status = STATUS_FAILURE;
+						break;
+					}
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+					dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
 					if (word_length & 0x1)
 						word_length++;
 					word_length = word_length / 2;
 
-			status =   write_blk(ft1000dev, &s_file, &c_file, word_length);
-			//DEBUG("write_blk returned %d\n", status);
-               break;
-            default:
-               DEBUG("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",request);
-               status = STATUS_FAILURE;
-               break;
-            }
-            if (pft1000info->usbboot)
-                put_handshake_usb(ft1000dev, HANDSHAKE_RESPONSE);
-            else
-                put_handshake(ft1000dev, HANDSHAKE_RESPONSE);
-         }
-         else
-         {
-            DEBUG("FT1000:download:Download error: Handshake failed\n");
-            status = STATUS_FAILURE;
-         }
-
-         break;
-
-      case STATE_CODE_DWNLD:
-         //DEBUG("FT1000:STATE_CODE_DWNLD\n");
-         pft1000info->bootmode = 0;
-         if (pft1000info->usbboot)
-            handshake = get_handshake_usb(ft1000dev, HANDSHAKE_REQUEST);
-         else
-            handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
-         if (handshake == HANDSHAKE_REQUEST)
-         {
-            /*
-             * Get type associated with the request.
-             */
-            if (pft1000info->usbboot)
-                request = get_request_type_usb(ft1000dev);
-            else
-                request = get_request_type(ft1000dev);
-            switch (request)
-            {
-            case REQUEST_FILE_CHECKSUM:
-                DEBUG("FT1000:download:image_chksum = 0x%8x\n", image_chksum);
-                put_request_value(ft1000dev, image_chksum);
-                break;
-            case  REQUEST_RUN_ADDRESS:
-               DEBUG("FT1000:download:  REQUEST_RUN_ADDRESS\n");
-               if (correct_version)
-               {
-                  DEBUG("FT1000:download:run_address = 0x%8x\n", (int)run_address);
-                  put_request_value(ft1000dev, run_address);
-               }
-               else
-               {
-                  DEBUG("FT1000:download:Download error: Got Run address request before image offset request.\n");
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               break;
-            case  REQUEST_CODE_LENGTH:
-               DEBUG("FT1000:download:REQUEST_CODE_LENGTH\n");
-               if (correct_version)
-               {
-                  DEBUG("FT1000:download:run_size = 0x%8x\n", (int)run_size);
-                  put_request_value(ft1000dev, run_size);
-               }
-               else
-               {
-                  DEBUG("FT1000:download:Download error: Got Size request before image offset request.\n");
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               break;
-            case  REQUEST_DONE_CL:
-               pft1000info->usbboot = 3;
-               /* Reposition ptrs to beginning of provisioning section */
-                  s_file = (u16 *)(pFileStart + file_hdr->commands_offset);
-                  c_file = (u8 *)(pFileStart + file_hdr->commands_offset);
-               state = STATE_DONE_DWNLD;
-               break;
-            case  REQUEST_CODE_SEGMENT:
-               //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n");
-               if (!correct_version)
-               {
-                  DEBUG("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
-                  status = STATUS_FAILURE;
-                  break;
-               }
-#if 0
-               word_length = get_request_value_usb(ft1000dev);
-               //DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
-               if (word_length > MAX_LENGTH/2)
-#else
-               word_length = get_request_value(ft1000dev);
-               //DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
-               if (word_length > MAX_LENGTH)
-#endif
-               {
-                  DEBUG("FT1000:download:Download error: Max length exceeded\n");
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               if ( (word_length*2 + c_file) > code_end)
-               {
-                  /*
-                   * Error, beyond boot code range.
-                   */
-                  DEBUG("FT1000:download:Download error: Requested len=%d exceeds DSP code boundry.\n",
-                               (int)word_length);
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               /*
-                * Position ASIC DPRAM auto-increment pointer.
-                */
-		   dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
-		   if (word_length & 0x1)
-			word_length++;
-		   word_length = word_length / 2;
-
-   	       write_blk_fifo (ft1000dev, &s_file, &c_file, word_length);
-               if (pft1000info->usbboot == 0)
-                   pft1000info->usbboot++;
-               if (pft1000info->usbboot == 1) {
-                   tempword = 0;
-                   ft1000_write_dpram16 (ft1000dev, DWNLD_MAG1_PS_HDR_LOC, tempword, 0);
-               }
-
-               break;
-
-            case  REQUEST_MAILBOX_DATA:
-               DEBUG("FT1000:download: REQUEST_MAILBOX_DATA\n");
-               // Convert length from byte count to word count. Make sure we round up.
-               word_length = (long)(pft1000info->DSPInfoBlklen + 1)/2;
-               put_request_value(ft1000dev, word_length);
-		mailbox_data = (struct drv_msg *)&(pft1000info->DSPInfoBlk[0]);
-               /*
-                * Position ASIC DPRAM auto-increment pointer.
-                */
-
-
-                   data = (u16 *)&mailbox_data->data[0];
-                   dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
-                   if (word_length & 0x1)
-                       word_length++;
-
-                   word_length = (word_length / 2);
-
-
-               for (; word_length > 0; word_length--) /* In words */
-               {
-
-                      templong = *data++;
-					  templong |= (*data++ << 16);
-                      status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (u8 *)&templong);
-
-               }
-               break;
-
-            case  REQUEST_VERSION_INFO:
-               DEBUG("FT1000:download:REQUEST_VERSION_INFO\n");
-               word_length = file_hdr->version_data_size;
-               put_request_value(ft1000dev, word_length);
-               /*
-                * Position ASIC DPRAM auto-increment pointer.
-                */
-
-               s_file = (u16 *)(pFileStart + file_hdr->version_data_offset);
-
-
-                   dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
-                   if (word_length & 0x1)
-                       word_length++;
-
-                   word_length = (word_length / 2);
-
-
-               for (; word_length > 0; word_length--) /* In words */
-               {
-
-                      templong = ntohs(*s_file++);
-					  temp = ntohs(*s_file++);
-					  templong |= (temp << 16);
-                      status = fix_ft1000_write_dpram32 (ft1000dev, dpram++, (u8 *)&templong);
-
-               }
-               break;
-
-            case  REQUEST_CODE_BY_VERSION:
-               DEBUG("FT1000:download:REQUEST_CODE_BY_VERSION\n");
-               correct_version = FALSE;
-               requested_version = get_request_value(ft1000dev);
-
-                   dsp_img_info = (struct dsp_image_info *)(pFileStart + sizeof(struct dsp_file_hdr ));
-
-               for (image = 0; image < file_hdr->nDspImages; image++)
-               {
-
-                       temp = (u16)(dsp_img_info->version);
-                       templong = temp;
-                       temp = (u16)(dsp_img_info->version >> 16);
-                       templong |= (temp << 16);
-                   if (templong == (u32)requested_version)
-                       {
-                           correct_version = TRUE;
-                           DEBUG("FT1000:download: correct_version is TRUE\n");
-                           s_file = (u16 *)(pFileStart + dsp_img_info->begin_offset);
-                           c_file = (u8 *)(pFileStart + dsp_img_info->begin_offset);
-                           code_end = (u8 *)(pFileStart + dsp_img_info->end_offset);
-                           run_address = dsp_img_info->run_address;
-                           run_size = dsp_img_info->image_size;
-                           image_chksum = (u32)dsp_img_info->checksum;
-                           break;
-                        }
-                        dsp_img_info++;
-
-
-               } //end of for
-
-               if (!correct_version)
-               {
-                  /*
-                   * Error, beyond boot code range.
-                   */
-                  DEBUG("FT1000:download:Download error: Bad Version Request = 0x%x.\n",(int)requested_version);
-                  status = STATUS_FAILURE;
-                  break;
-               }
-               break;
-
-            default:
-               DEBUG("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",request);
-               status = STATUS_FAILURE;
-               break;
-            }
-            if (pft1000info->usbboot)
-                put_handshake_usb(ft1000dev, HANDSHAKE_RESPONSE);
-            else
-                put_handshake(ft1000dev, HANDSHAKE_RESPONSE);
-         }
-         else
-         {
-            DEBUG("FT1000:download:Download error: Handshake failed\n");
-            status = STATUS_FAILURE;
-         }
-
-         break;
-
-      case STATE_DONE_DWNLD:
-         DEBUG("FT1000:download:Code loader is done...\n");
-         state = STATE_SECTION_PROV;
-         break;
-
-      case  STATE_SECTION_PROV:
-         DEBUG("FT1000:download:STATE_SECTION_PROV\n");
-		pseudo_header = (struct pseudo_hdr *)c_file;
-
-         if (pseudo_header->checksum == hdr_checksum(pseudo_header))
-         {
-            if (pseudo_header->portdest != 0x80 /* Dsp OAM */)
-            {
-               state = STATE_DONE_PROV;
-               break;
-            }
-            pseudo_header_len = ntohs(pseudo_header->length);    /* Byte length for PROV records */
-
-            // Get buffer for provisioning data
-		pbuffer = kmalloc((pseudo_header_len + sizeof(struct pseudo_hdr)), GFP_ATOMIC);
-            if (pbuffer) {
-		memcpy(pbuffer, (void *)c_file, (u32)(pseudo_header_len + sizeof(struct pseudo_hdr)));
-                // link provisioning data
-		pprov_record = kmalloc(sizeof(struct prov_record), GFP_ATOMIC);
-                if (pprov_record) {
-                    pprov_record->pprov_data = pbuffer;
-                    list_add_tail (&pprov_record->list, &pft1000info->prov_list);
-                    // Move to next entry if available
-			c_file = (u8 *)((unsigned long)c_file + (u32)((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
-                    if ( (unsigned long)(c_file) - (unsigned long)(pFileStart) >= (unsigned long)FileLength) {
-                       state = STATE_DONE_FILE;
-                    }
-                }
-                else {
-                    kfree(pbuffer);
-                    status = STATUS_FAILURE;
-                }
-            }
-            else {
-                status = STATUS_FAILURE;
-            }
-         }
-         else
-         {
-            /* Checksum did not compute */
-            status = STATUS_FAILURE;
-         }
-         DEBUG("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n", state, status);
-         break;
-
-      case  STATE_DONE_PROV:
-         DEBUG("FT1000:download:STATE_DONE_PROV\n");
-         state = STATE_DONE_FILE;
-         break;
-
-
-      default:
-         status = STATUS_FAILURE;
-         break;
-      } /* End Switch */
-
-      if (status != STATUS_SUCCESS) {
-          break;
-      }
+					status =
+					    write_blk(ft1000dev, &s_file,
+						      &c_file, word_length);
+					//DEBUG("write_blk returned %d\n", status);
+					break;
+				default:
+					DEBUG
+					    ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",
+					     request);
+					status = STATUS_FAILURE;
+					break;
+				}
+				if (pft1000info->usbboot)
+					put_handshake_usb(ft1000dev,
+							  HANDSHAKE_RESPONSE);
+				else
+					put_handshake(ft1000dev,
+						      HANDSHAKE_RESPONSE);
+			} else {
+				DEBUG
+				    ("FT1000:download:Download error: Handshake failed\n");
+				status = STATUS_FAILURE;
+			}
+
+			break;
+
+		case STATE_CODE_DWNLD:
+			//DEBUG("FT1000:STATE_CODE_DWNLD\n");
+			pft1000info->bootmode = 0;
+			if (pft1000info->usbboot)
+				handshake =
+				    get_handshake_usb(ft1000dev,
+						      HANDSHAKE_REQUEST);
+			else
+				handshake =
+				    get_handshake(ft1000dev, HANDSHAKE_REQUEST);
+			if (handshake == HANDSHAKE_REQUEST) {
+				/*
+				 * Get type associated with the request.
+				 */
+				if (pft1000info->usbboot)
+					request =
+					    get_request_type_usb(ft1000dev);
+				else
+					request = get_request_type(ft1000dev);
+				switch (request) {
+				case REQUEST_FILE_CHECKSUM:
+					DEBUG
+					    ("FT1000:download:image_chksum = 0x%8x\n",
+					     image_chksum);
+					put_request_value(ft1000dev,
+							  image_chksum);
+					break;
+				case REQUEST_RUN_ADDRESS:
+					DEBUG
+					    ("FT1000:download:  REQUEST_RUN_ADDRESS\n");
+					if (correct_version) {
+						DEBUG
+						    ("FT1000:download:run_address = 0x%8x\n",
+						     (int)run_address);
+						put_request_value(ft1000dev,
+								  run_address);
+					} else {
+						DEBUG
+						    ("FT1000:download:Download error: Got Run address request before image offset request.\n");
+						status = STATUS_FAILURE;
+						break;
+					}
+					break;
+				case REQUEST_CODE_LENGTH:
+					DEBUG
+					    ("FT1000:download:REQUEST_CODE_LENGTH\n");
+					if (correct_version) {
+						DEBUG
+						    ("FT1000:download:run_size = 0x%8x\n",
+						     (int)run_size);
+						put_request_value(ft1000dev,
+								  run_size);
+					} else {
+						DEBUG
+						    ("FT1000:download:Download error: Got Size request before image offset request.\n");
+						status = STATUS_FAILURE;
+						break;
+					}
+					break;
+				case REQUEST_DONE_CL:
+					pft1000info->usbboot = 3;
+					/* Reposition ptrs to beginning of provisioning section */
+					s_file =
+					    (u16 *) (pFileStart +
+						     file_hdr->commands_offset);
+					c_file =
+					    (u8 *) (pFileStart +
+						    file_hdr->commands_offset);
+					state = STATE_DONE_DWNLD;
+					break;
+				case REQUEST_CODE_SEGMENT:
+					//DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n");
+					if (!correct_version) {
+						DEBUG
+						    ("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
+						status = STATUS_FAILURE;
+						break;
+					}
+
+					word_length =
+					    get_request_value(ft1000dev);
+					//DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
+					if (word_length > MAX_LENGTH) {
+						DEBUG
+						    ("FT1000:download:Download error: Max length exceeded\n");
+						status = STATUS_FAILURE;
+						break;
+					}
+					if ((word_length * 2 + c_file) >
+					    code_end) {
+						/*
+						 * Error, beyond boot code range.
+						 */
+						DEBUG
+						    ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundry.\n",
+						     (int)word_length);
+						status = STATUS_FAILURE;
+						break;
+					}
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+					dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
+					if (word_length & 0x1)
+						word_length++;
+					word_length = word_length / 2;
+
+					write_blk_fifo(ft1000dev, &s_file,
+						       &c_file, word_length);
+					if (pft1000info->usbboot == 0)
+						pft1000info->usbboot++;
+					if (pft1000info->usbboot == 1) {
+						tempword = 0;
+						ft1000_write_dpram16(ft1000dev,
+								     DWNLD_MAG1_PS_HDR_LOC,
+								     tempword,
+								     0);
+					}
+
+					break;
+
+				case REQUEST_MAILBOX_DATA:
+					DEBUG
+					    ("FT1000:download: REQUEST_MAILBOX_DATA\n");
+					// Convert length from byte count to word count. Make sure we round up.
+					word_length =
+					    (long)(pft1000info->DSPInfoBlklen +
+						   1) / 2;
+					put_request_value(ft1000dev,
+							  word_length);
+					mailbox_data =
+					    (struct drv_msg *)&(pft1000info->
+								DSPInfoBlk[0]);
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+
+					data = (u16 *) & mailbox_data->data[0];
+					dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
+					if (word_length & 0x1)
+						word_length++;
+
+					word_length = (word_length / 2);
+
+					for (; word_length > 0; word_length--) {	/* In words */
+
+						templong = *data++;
+						templong |= (*data++ << 16);
+						status =
+						    fix_ft1000_write_dpram32
+						    (ft1000dev, dpram++,
+						     (u8 *) & templong);
+
+					}
+					break;
+
+				case REQUEST_VERSION_INFO:
+					DEBUG
+					    ("FT1000:download:REQUEST_VERSION_INFO\n");
+					word_length =
+					    file_hdr->version_data_size;
+					put_request_value(ft1000dev,
+							  word_length);
+					/*
+					 * Position ASIC DPRAM auto-increment pointer.
+					 */
+
+					s_file =
+					    (u16 *) (pFileStart +
+						     file_hdr->
+						     version_data_offset);
+
+					dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
+					if (word_length & 0x1)
+						word_length++;
+
+					word_length = (word_length / 2);
+
+					for (; word_length > 0; word_length--) {	/* In words */
+
+						templong = ntohs(*s_file++);
+						temp = ntohs(*s_file++);
+						templong |= (temp << 16);
+						status =
+						    fix_ft1000_write_dpram32
+						    (ft1000dev, dpram++,
+						     (u8 *) & templong);
+
+					}
+					break;
+
+				case REQUEST_CODE_BY_VERSION:
+					DEBUG
+					    ("FT1000:download:REQUEST_CODE_BY_VERSION\n");
+					correct_version = FALSE;
+					requested_version =
+					    get_request_value(ft1000dev);
+
+					dsp_img_info =
+					    (struct dsp_image_info *)(pFileStart
+								      +
+								      sizeof
+								      (struct
+								       dsp_file_hdr));
+
+					for (image = 0;
+					     image < file_hdr->nDspImages;
+					     image++) {
+
+						if (dsp_img_info->version ==
+						    requested_version) {
+							correct_version = TRUE;
+							DEBUG
+							    ("FT1000:download: correct_version is TRUE\n");
+							s_file =
+							    (u16 *) (pFileStart
+								     +
+								     dsp_img_info->
+								     begin_offset);
+							c_file =
+							    (u8 *) (pFileStart +
+								    dsp_img_info->
+								    begin_offset);
+							code_end =
+							    (u8 *) (pFileStart +
+								    dsp_img_info->
+								    end_offset);
+							run_address =
+							    dsp_img_info->
+							    run_address;
+							run_size =
+							    dsp_img_info->
+							    image_size;
+							image_chksum =
+							    (u32) dsp_img_info->
+							    checksum;
+							break;
+						}
+						dsp_img_info++;
+
+					}	//end of for
+
+					if (!correct_version) {
+						/*
+						 * Error, beyond boot code range.
+						 */
+						DEBUG
+						    ("FT1000:download:Download error: Bad Version Request = 0x%x.\n",
+						     (int)requested_version);
+						status = STATUS_FAILURE;
+						break;
+					}
+					break;
+
+				default:
+					DEBUG
+					    ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",
+					     request);
+					status = STATUS_FAILURE;
+					break;
+				}
+				if (pft1000info->usbboot)
+					put_handshake_usb(ft1000dev,
+							  HANDSHAKE_RESPONSE);
+				else
+					put_handshake(ft1000dev,
+						      HANDSHAKE_RESPONSE);
+			} else {
+				DEBUG
+				    ("FT1000:download:Download error: Handshake failed\n");
+				status = STATUS_FAILURE;
+			}
+
+			break;
+
+		case STATE_DONE_DWNLD:
+			DEBUG("FT1000:download:Code loader is done...\n");
+			state = STATE_SECTION_PROV;
+			break;
+
+		case STATE_SECTION_PROV:
+			DEBUG("FT1000:download:STATE_SECTION_PROV\n");
+			pseudo_header = (struct pseudo_hdr *)c_file;
+
+			if (pseudo_header->checksum ==
+			    hdr_checksum(pseudo_header)) {
+				if (pseudo_header->portdest !=
+				    0x80 /* Dsp OAM */ ) {
+					state = STATE_DONE_PROV;
+					break;
+				}
+				pseudo_header_len = ntohs(pseudo_header->length);	/* Byte length for PROV records */
+
+				// Get buffer for provisioning data
+				pbuffer =
+				    kmalloc((pseudo_header_len +
+					     sizeof(struct pseudo_hdr)),
+					    GFP_ATOMIC);
+				if (pbuffer) {
+					memcpy(pbuffer, (void *)c_file,
+					       (u32) (pseudo_header_len +
+						      sizeof(struct
+							     pseudo_hdr)));
+					// link provisioning data
+					pprov_record =
+					    kmalloc(sizeof(struct prov_record),
+						    GFP_ATOMIC);
+					if (pprov_record) {
+						pprov_record->pprov_data =
+						    pbuffer;
+						list_add_tail(&pprov_record->
+							      list,
+							      &pft1000info->
+							      prov_list);
+						// Move to next entry if available
+						c_file =
+						    (u8 *) ((unsigned long)
+							    c_file +
+							    (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
+						if ((unsigned long)(c_file) -
+						    (unsigned long)(pFileStart)
+						    >=
+						    (unsigned long)FileLength) {
+							state = STATE_DONE_FILE;
+						}
+					} else {
+						kfree(pbuffer);
+						status = STATUS_FAILURE;
+					}
+				} else {
+					status = STATUS_FAILURE;
+				}
+			} else {
+				/* Checksum did not compute */
+				status = STATUS_FAILURE;
+			}
+			DEBUG
+			    ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n",
+			     state, status);
+			break;
+
+		case STATE_DONE_PROV:
+			DEBUG("FT1000:download:STATE_DONE_PROV\n");
+			state = STATE_DONE_FILE;
+			break;
+
+		default:
+			status = STATUS_FAILURE;
+			break;
+		}		/* End Switch */
+
+		if (status != STATUS_SUCCESS) {
+			break;
+		}
 
 /****
       // Check if Card is present
@@ -1238,11 +1224,12 @@ u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart, u32  FileLeng
       }
 ****/
 
-   } /* End while */
+	}			/* End while */
 
-   DEBUG("Download exiting with status = 0x%8x\n", status);
-   ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX, FT1000_REG_DOORBELL);
+	DEBUG("Download exiting with status = 0x%8x\n", status);
+	ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
+			      FT1000_REG_DOORBELL);
 
-   return status;
+	return status;
 }
 
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
index 643a637..78dcd49 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
@@ -65,45 +65,26 @@ static u8 tempbuffer[1600];
 // Notes:
 //
 //---------------------------------------------------------------------------
-static int ft1000_control(struct ft1000_device *ft1000dev,unsigned int pipe,
-                          u8 request,
-                          u8 requesttype,
-                          u16 value,
-                          u16 index,
-                          void *data,
-                          u16 size,
-                          int timeout)
+static int ft1000_control(struct ft1000_device *ft1000dev, unsigned int pipe,
+			  u8 request, u8 requesttype, u16 value, u16 index,
+			  void *data, u16 size, int timeout)
 {
 	u16 ret;
 
-    if (ft1000dev == NULL )
-    {
-        DEBUG("NULL ft1000dev, failure\n");
-	return -ENODEV;
-    }
-    else if ( ft1000dev->dev == NULL )
-    {
-        DEBUG("NULL ft1000dev->dev, failure\n");
-	return -ENODEV;
-    }
+	if ((ft1000dev == NULL) || (ft1000dev->dev == NULL)) {
+		DEBUG("ft1000dev or ft1000dev->dev == NULL, failure\n");
+		return -ENODEV;
+	}
 
-    ret = usb_control_msg(ft1000dev->dev,
-                          pipe,
-                          request,
-                          requesttype,
-                          value,
-                          index,
-                          data,
-                          size,
-                          LARGE_TIMEOUT);
+	ret = usb_control_msg(ft1000dev->dev, pipe, request, requesttype,
+			      value, index, data, size, LARGE_TIMEOUT);
 
 	if (ret > 0)
 		ret = 0;
 
-    return ret;
-
-
+	return ret;
 }
+
 //---------------------------------------------------------------------------
 // Function:    ft1000_read_register
 //
@@ -120,28 +101,22 @@ static int ft1000_control(struct ft1000_device *ft1000dev,unsigned int pipe,
 //
 //---------------------------------------------------------------------------
 
-u16 ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegIndx)
+int ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data,
+			 u16 nRegIndx)
 {
-    u16 ret = STATUS_SUCCESS;
-
-    //DEBUG("ft1000_read_register: reg index is %d\n", nRegIndx);
-    //DEBUG("ft1000_read_register: spin_lock locked\n");
-    ret = ft1000_control(ft1000dev,
-                         usb_rcvctrlpipe(ft1000dev->dev,0),
-                         HARLEY_READ_REGISTER,   //request --READ_REGISTER
-                         HARLEY_READ_OPERATION,  //requestType
-                         0,                      //value
-                         nRegIndx,               //index
-                         Data,                   //data
-                         2,                      //data size
-                         LARGE_TIMEOUT );        //timeout
-
-   //DEBUG("ft1000_read_register: ret is  %d \n", ret);
-
-   //DEBUG("ft1000_read_register: data is  %x \n", *Data);
-
-   return ret;
+	int ret = STATUS_SUCCESS;
+
+	ret = ft1000_control(ft1000dev,
+			     usb_rcvctrlpipe(ft1000dev->dev, 0),
+			     HARLEY_READ_REGISTER,
+			     HARLEY_READ_OPERATION,
+			     0,
+			     nRegIndx,
+			     Data,
+			     2,
+			     LARGE_TIMEOUT);
 
+	return ret;
 }
 
 //---------------------------------------------------------------------------
@@ -159,23 +134,22 @@ u16 ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegInd
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIndx)
+int ft1000_write_register(struct ft1000_device *ft1000dev, u16 value,
+			  u16 nRegIndx)
 {
-     u16 ret = STATUS_SUCCESS;
-
-     //DEBUG("ft1000_write_register: value is: %d, reg index is: %d\n", value, nRegIndx);
+	int ret = STATUS_SUCCESS;
+
+	ret = ft1000_control(ft1000dev,
+			     usb_sndctrlpipe(ft1000dev->dev, 0),
+			     HARLEY_WRITE_REGISTER,
+			     HARLEY_WRITE_OPERATION,
+			     value,
+			     nRegIndx,
+			     NULL,
+			     0,
+			     LARGE_TIMEOUT);
 
-     ret = ft1000_control(ft1000dev,
-                           usb_sndctrlpipe(ft1000dev->dev, 0),
-                           HARLEY_WRITE_REGISTER,       //request -- WRITE_REGISTER
-                           HARLEY_WRITE_OPERATION,      //requestType
-                           value,
-                           nRegIndx,
-                           NULL,
-                           0,
-                           LARGE_TIMEOUT );
-
-    return ret;
+	return ret;
 }
 
 //---------------------------------------------------------------------------
@@ -195,27 +169,22 @@ u16 ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIn
 //
 //---------------------------------------------------------------------------
 
-u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt)
+int ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer,
+			u16 cnt)
 {
-    u16 ret = STATUS_SUCCESS;
-
-    //DEBUG("ft1000_read_dpram32: indx: %d  cnt: %d\n", indx, cnt);
-    ret =ft1000_control(ft1000dev,
-                         usb_rcvctrlpipe(ft1000dev->dev,0),
-                         HARLEY_READ_DPRAM_32,                //request --READ_DPRAM_32
-                         HARLEY_READ_OPERATION,               //requestType
-                         0,                                   //value
-                         indx,                                //index
-                         buffer,                              //data
-                         cnt,                                 //data size
-                         LARGE_TIMEOUT );                     //timeout
-
-   //DEBUG("ft1000_read_dpram32: ret is  %d \n", ret);
-
-   //DEBUG("ft1000_read_dpram32: ret=%d \n", ret);
-
-   return ret;
+	int ret = STATUS_SUCCESS;
+
+	ret = ft1000_control(ft1000dev,
+			     usb_rcvctrlpipe(ft1000dev->dev, 0),
+			     HARLEY_READ_DPRAM_32,
+			     HARLEY_READ_OPERATION,
+			     0,
+			     indx,
+			     buffer,
+			     cnt,
+			     LARGE_TIMEOUT);
 
+	return ret;
 }
 
 //---------------------------------------------------------------------------
@@ -234,25 +203,25 @@ u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt)
+int ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer,
+			 u16 cnt)
 {
-     u16 ret = STATUS_SUCCESS;
-
-     //DEBUG("ft1000_write_dpram32: indx: %d   buffer: %x cnt: %d\n", indx, buffer, cnt);
-     if ( cnt % 4)
-         cnt += cnt - (cnt % 4);
-
-     ret = ft1000_control(ft1000dev,
-                           usb_sndctrlpipe(ft1000dev->dev, 0),
-                           HARLEY_WRITE_DPRAM_32,              //request -- WRITE_DPRAM_32
-                           HARLEY_WRITE_OPERATION,             //requestType
-                           0,                                  //value
-                           indx,                               //index
-                           buffer,                             //buffer
-                           cnt,                                //buffer size
-                           LARGE_TIMEOUT );
-
-    return ret;
+	int ret = STATUS_SUCCESS;
+
+	if (cnt % 4)
+		cnt += cnt - (cnt % 4);
+
+	ret = ft1000_control(ft1000dev,
+			     usb_sndctrlpipe(ft1000dev->dev, 0),
+			     HARLEY_WRITE_DPRAM_32,
+			     HARLEY_WRITE_OPERATION,
+			     0,
+			     indx,
+			     buffer,
+			     cnt,
+			     LARGE_TIMEOUT);
+
+	return ret;
 }
 
 //---------------------------------------------------------------------------
@@ -271,36 +240,28 @@ u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer,
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u8 highlow)
+int ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer,
+			u8 highlow)
 {
-    u16 ret = STATUS_SUCCESS;
-
-    //DEBUG("ft1000_read_dpram16: indx: %d  hightlow: %d\n", indx, highlow);
-
-    u8 request;
-
-    if (highlow == 0 )
-        request = HARLEY_READ_DPRAM_LOW;
-    else
-        request = HARLEY_READ_DPRAM_HIGH;
-
-    ret = ft1000_control(ft1000dev,
-                         usb_rcvctrlpipe(ft1000dev->dev,0),
-                         request,                     //request --READ_DPRAM_H/L
-                         HARLEY_READ_OPERATION,       //requestType
-                         0,                           //value
-                         indx,                        //index
-                         buffer,                      //data
-                         2,                           //data size
-                         LARGE_TIMEOUT );             //timeout
-
-   //DEBUG("ft1000_read_dpram16: ret is  %d \n", ret);
-
-
-   //DEBUG("ft1000_read_dpram16: data is  %x \n", *buffer);
-
-   return ret;
+	int ret = STATUS_SUCCESS;
+	u8 request;
+
+	if (highlow == 0)
+		request = HARLEY_READ_DPRAM_LOW;
+	else
+		request = HARLEY_READ_DPRAM_HIGH;
+
+	ret = ft1000_control(ft1000dev,
+			     usb_rcvctrlpipe(ft1000dev->dev, 0),
+			     request,
+			     HARLEY_READ_OPERATION,
+			     0,
+			     indx,
+			     buffer,
+			     2,
+			     LARGE_TIMEOUT);
 
+	return ret;
 }
 
 //---------------------------------------------------------------------------
@@ -319,33 +280,27 @@ u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow)
+int ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow)
 {
-     u16 ret = STATUS_SUCCESS;
-
-
+	int ret = STATUS_SUCCESS;
+	u8 request;
+
+	if (highlow == 0)
+		request = HARLEY_WRITE_DPRAM_LOW;
+	else
+		request = HARLEY_WRITE_DPRAM_HIGH;
+
+	ret = ft1000_control(ft1000dev,
+			     usb_sndctrlpipe(ft1000dev->dev, 0),
+			     request,
+			     HARLEY_WRITE_OPERATION,
+			     value,
+			     indx,
+			     NULL,
+			     0,
+			     LARGE_TIMEOUT);
 
-     //DEBUG("ft1000_write_dpram16: indx: %d  value: %d  highlow: %d\n", indx, value, highlow);
-
-     u8 request;
-
-
-     if ( highlow == 0 )
-         request = HARLEY_WRITE_DPRAM_LOW;
-     else
-         request = HARLEY_WRITE_DPRAM_HIGH;
-
-     ret = ft1000_control(ft1000dev,
-                           usb_sndctrlpipe(ft1000dev->dev, 0),
-                           request,                             //request -- WRITE_DPRAM_H/L
-                           HARLEY_WRITE_OPERATION,              //requestType
-                           value,                                   //value
-                           indx,                                //index
-                           NULL,                               //buffer
-                           0,                                   //buffer size
-                           LARGE_TIMEOUT );
-
-    return ret;
+	return ret;
 }
 
 //---------------------------------------------------------------------------
@@ -364,36 +319,31 @@ u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer)
+int fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx,
+			    u8 *buffer)
 {
-    u8 buf[16];
-    u16 pos;
-    u16 ret = STATUS_SUCCESS;
-
-    //DEBUG("fix_ft1000_read_dpram32: indx: %d  \n", indx);
-    pos = (indx / 4)*4;
-    ret = ft1000_read_dpram32(ft1000dev, pos, buf, 16);
-    if (ret == STATUS_SUCCESS)
-    {
-        pos = (indx % 4)*4;
-        *buffer++ = buf[pos++];
-        *buffer++ = buf[pos++];
-        *buffer++ = buf[pos++];
-        *buffer++ = buf[pos++];
-    }
-    else
-    {
-        DEBUG("fix_ft1000_read_dpram32: DPRAM32 Read failed\n");
-        *buffer++ = 0;
-        *buffer++ = 0;
-        *buffer++ = 0;
-        *buffer++ = 0;
-
-    }
-
-   //DEBUG("fix_ft1000_read_dpram32: data is  %x \n", *buffer);
-   return ret;
+	u8 buf[16];
+	u16 pos;
+	int ret = STATUS_SUCCESS;
+
+	pos = (indx / 4) * 4;
+	ret = ft1000_read_dpram32(ft1000dev, pos, buf, 16);
+
+	if (ret == STATUS_SUCCESS) {
+		pos = (indx % 4) * 4;
+		*buffer++ = buf[pos++];
+		*buffer++ = buf[pos++];
+		*buffer++ = buf[pos++];
+		*buffer++ = buf[pos++];
+	} else {
+		DEBUG("fix_ft1000_read_dpram32: DPRAM32 Read failed\n");
+		*buffer++ = 0;
+		*buffer++ = 0;
+		*buffer++ = 0;
+		*buffer++ = 0;
+	}
 
+	return ret;
 }
 
 
@@ -413,70 +363,60 @@ u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffe
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer)
+int fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer)
 {
-    u16 pos1;
-    u16 pos2;
-    u16 i;
-    u8 buf[32];
-    u8 resultbuffer[32];
-    u8 *pdata;
-    u16 ret  = STATUS_SUCCESS;
-
-    //DEBUG("fix_ft1000_write_dpram32: Entered:\n");
-
-    pos1 = (indx / 4)*4;
-    pdata = buffer;
-    ret = ft1000_read_dpram32(ft1000dev, pos1, buf, 16);
-    if (ret == STATUS_SUCCESS)
-    {
-        pos2 = (indx % 4)*4;
-        buf[pos2++] = *buffer++;
-        buf[pos2++] = *buffer++;
-        buf[pos2++] = *buffer++;
-        buf[pos2++] = *buffer++;
-        ret = ft1000_write_dpram32(ft1000dev, pos1, buf, 16);
-    }
-    else
-    {
-        DEBUG("fix_ft1000_write_dpram32: DPRAM32 Read failed\n");
-
-        return ret;
-    }
-
-    ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16);
-    if (ret == STATUS_SUCCESS)
-    {
-        buffer = pdata;
-        for (i=0; i<16; i++)
-        {
-            if (buf[i] != resultbuffer[i]){
+	u16 pos1;
+	u16 pos2;
+	u16 i;
+	u8 buf[32];
+	u8 resultbuffer[32];
+	u8 *pdata;
+	int ret  = STATUS_SUCCESS;
+
+	pos1 = (indx / 4) * 4;
+	pdata = buffer;
+	ret = ft1000_read_dpram32(ft1000dev, pos1, buf, 16);
+
+	if (ret == STATUS_SUCCESS) {
+		pos2 = (indx % 4)*4;
+		buf[pos2++] = *buffer++;
+		buf[pos2++] = *buffer++;
+		buf[pos2++] = *buffer++;
+		buf[pos2++] = *buffer++;
+		ret = ft1000_write_dpram32(ft1000dev, pos1, buf, 16);
+	} else {
+		DEBUG("fix_ft1000_write_dpram32: DPRAM32 Read failed\n");
+		return ret;
+	}
 
-                ret = STATUS_FAILURE;
-            }
-        }
-    }
+	ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16);
 
-    if (ret == STATUS_FAILURE)
-    {
-        ret = ft1000_write_dpram32(ft1000dev, pos1, (u8 *)&tempbuffer[0], 16);
-        ret = ft1000_read_dpram32(ft1000dev, pos1, (u8 *)&resultbuffer[0], 16);
-        if (ret == STATUS_SUCCESS)
-        {
-            buffer = pdata;
-            for (i=0; i<16; i++)
-            {
-                if (tempbuffer[i] != resultbuffer[i])
-                {
-                    ret = STATUS_FAILURE;
-                    DEBUG("fix_ft1000_write_dpram32 Failed to write\n");
-                }
-            }
-         }
-    }
+	if (ret == STATUS_SUCCESS) {
+		buffer = pdata;
+		for (i = 0; i < 16; i++) {
+			if (buf[i] != resultbuffer[i])
+				ret = STATUS_FAILURE;
+		}
+	}
 
-    return ret;
+	if (ret == STATUS_FAILURE) {
+		ret = ft1000_write_dpram32(ft1000dev, pos1,
+					   (u8 *)&tempbuffer[0], 16);
+		ret = ft1000_read_dpram32(ft1000dev, pos1,
+					  (u8 *)&resultbuffer[0], 16);
+		if (ret == STATUS_SUCCESS) {
+			buffer = pdata;
+			for (i = 0; i < 16; i++) {
+				if (tempbuffer[i] != resultbuffer[i]) {
+					ret = STATUS_FAILURE;
+					DEBUG("%s Failed to write\n",
+					      __func__);
+				}
+			}
+		}
+	}
 
+	return ret;
 }
 
 
@@ -490,37 +430,44 @@ u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buff
 //
 //  Returns:    None
 //-----------------------------------------------------------------------
-static void card_reset_dsp (struct ft1000_device *ft1000dev, bool value)
+static void card_reset_dsp(struct ft1000_device *ft1000dev, bool value)
 {
-    u16 status = STATUS_SUCCESS;
-    u16 tempword;
-
-    status = ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL);
-    status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_CTRL);
-    if (value)
-    {
-        DEBUG("Reset DSP\n");
-        status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
-        tempword |= DSP_RESET_BIT;
-        status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET);
-    }
-    else
-    {
-        DEBUG("Activate DSP\n");
-        status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
-	tempword |= DSP_ENCRYPTED;
-	tempword &= ~DSP_UNENCRYPTED;
-	status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET);
-        status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
-        tempword &= ~EFUSE_MEM_DISABLE;
-        tempword &= ~DSP_RESET_BIT;
-        status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET);
-        status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
-    }
+	u16 status = STATUS_SUCCESS;
+	u16 tempword;
+
+	status = ft1000_write_register(ft1000dev, HOST_INTF_BE,
+					FT1000_REG_SUP_CTRL);
+	status = ft1000_read_register(ft1000dev, &tempword,
+				      FT1000_REG_SUP_CTRL);
+
+	if (value) {
+		DEBUG("Reset DSP\n");
+		status = ft1000_read_register(ft1000dev, &tempword,
+					      FT1000_REG_RESET);
+		tempword |= DSP_RESET_BIT;
+		status = ft1000_write_register(ft1000dev, tempword,
+					       FT1000_REG_RESET);
+	} else {
+		DEBUG("Activate DSP\n");
+		status = ft1000_read_register(ft1000dev, &tempword,
+					      FT1000_REG_RESET);
+		tempword |= DSP_ENCRYPTED;
+		tempword &= ~DSP_UNENCRYPTED;
+		status = ft1000_write_register(ft1000dev, tempword,
+					       FT1000_REG_RESET);
+		status = ft1000_read_register(ft1000dev, &tempword,
+					      FT1000_REG_RESET);
+		tempword &= ~EFUSE_MEM_DISABLE;
+		tempword &= ~DSP_RESET_BIT;
+		status = ft1000_write_register(ft1000dev, tempword,
+					       FT1000_REG_RESET);
+		status = ft1000_read_register(ft1000dev, &tempword,
+					      FT1000_REG_RESET);
+	}
 }
 
 //---------------------------------------------------------------------------
-// Function:    CardSendCommand
+// Function:    card_send_command
 //
 // Parameters:  ft1000_device  - device structure
 //              ptempbuffer - command buffer
@@ -534,51 +481,47 @@ static void card_reset_dsp (struct ft1000_device *ft1000dev, bool value)
 // Notes:
 //
 //---------------------------------------------------------------------------
-void CardSendCommand(struct ft1000_device *ft1000dev, void *ptempbuffer, int size)
+void card_send_command(struct ft1000_device *ft1000dev, void *ptempbuffer,
+		       int size)
 {
-    unsigned short temp;
-    unsigned char *commandbuf;
+	unsigned short temp;
+	unsigned char *commandbuf;
 
-    DEBUG("CardSendCommand: enter CardSendCommand... size=%d\n", size);
+	DEBUG("card_send_command: enter card_send_command... size=%d\n", size);
 
-    commandbuf =(unsigned char*) kmalloc(size+2, GFP_KERNEL);
-    memcpy((void*)commandbuf+2, (void*)ptempbuffer, size);
+	commandbuf = (unsigned char *)kmalloc(size + 2, GFP_KERNEL);
+	memcpy((void *)commandbuf + 2, (void *)ptempbuffer, size);
 
-    //DEBUG("CardSendCommand: Command Send\n");
+	//DEBUG("card_send_command: Command Send\n");
 
-    ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
+	ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
 
-    if (temp & 0x0100)
-    {
-       msleep(10);
-    }
+	if (temp & 0x0100)
+		msleep(10);
 
-    // check for odd word
-    size = size + 2;
-    if (size % 4)
-    {
-       // Must force to be 32 bit aligned
-       size += 4 - (size % 4);
-    }
+	/* check for odd word */
+	size = size + 2;
 
+	/* Must force to be 32 bit aligned */
+	if (size % 4)
+		size += 4 - (size % 4);
 
-    //DEBUG("CardSendCommand: write dpram ... size=%d\n", size);
-    ft1000_write_dpram32(ft1000dev, 0,commandbuf, size);
-    msleep(1);
-    //DEBUG("CardSendCommand: write into doorbell ...\n");
-    ft1000_write_register(ft1000dev,  FT1000_DB_DPRAM_TX ,FT1000_REG_DOORBELL) ;
-    msleep(1);
+	//DEBUG("card_send_command: write dpram ... size=%d\n", size);
+	ft1000_write_dpram32(ft1000dev, 0, commandbuf, size);
+	msleep(1);
+	//DEBUG("card_send_command: write into doorbell ...\n");
+	ft1000_write_register(ft1000dev, FT1000_DB_DPRAM_TX,
+			      FT1000_REG_DOORBELL);
+	msleep(1);
 
-    ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
-    //DEBUG("CardSendCommand: read doorbell ...temp=%x\n", temp);
-    if ( (temp & 0x0100) == 0)
-    {
-       //DEBUG("CardSendCommand: Message sent\n");
-    }
+	ft1000_read_register(ft1000dev, &temp, FT1000_REG_DOORBELL);
+	//DEBUG("card_send_command: read doorbell ...temp=%x\n", temp);
+	if ((temp & 0x0100) == 0) {
+		//DEBUG("card_send_command: Message sent\n");
+	}
 
 }
 
-
 //--------------------------------------------------------------------------
 //
 //  Function:   dsp_reload
@@ -591,49 +534,52 @@ void CardSendCommand(struct ft1000_device *ft1000dev, void *ptempbuffer, int siz
 //-----------------------------------------------------------------------
 int dsp_reload(struct ft1000_device *ft1000dev)
 {
-    u16 status;
-    u16 tempword;
-    u32 templong;
+	u16 status;
+	u16 tempword;
+	u32 templong;
 
 	struct ft1000_info *pft1000info;
 
-    pft1000info = netdev_priv(ft1000dev->net);
+	pft1000info = netdev_priv(ft1000dev->net);
 
-    pft1000info->CardReady = 0;
+	pft1000info->CardReady = 0;
 
-    // Program Interrupt Mask register
-    status = ft1000_write_register (ft1000dev, 0xffff, FT1000_REG_SUP_IMASK);
+	/* Program Interrupt Mask register */
+	status = ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_SUP_IMASK);
 
-    status = ft1000_read_register (ft1000dev, &tempword, FT1000_REG_RESET);
-    tempword |= ASIC_RESET_BIT;
-    status = ft1000_write_register (ft1000dev, tempword, FT1000_REG_RESET);
-    msleep(1000);
-    status = ft1000_read_register (ft1000dev, &tempword, FT1000_REG_RESET);
-    DEBUG("Reset Register = 0x%x\n", tempword);
+	status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
+	tempword |= ASIC_RESET_BIT;
+	status = ft1000_write_register(ft1000dev, tempword, FT1000_REG_RESET);
+	msleep(1000);
+	status = ft1000_read_register(ft1000dev, &tempword, FT1000_REG_RESET);
+	DEBUG("Reset Register = 0x%x\n", tempword);
 
-    // Toggle DSP reset
-    card_reset_dsp (ft1000dev, 1);
-    msleep(1000);
-    card_reset_dsp (ft1000dev, 0);
-    msleep(1000);
+	/* Toggle DSP reset */
+	card_reset_dsp(ft1000dev, 1);
+	msleep(1000);
+	card_reset_dsp(ft1000dev, 0);
+	msleep(1000);
 
-    status = ft1000_write_register (ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL);
+	status =
+	    ft1000_write_register(ft1000dev, HOST_INTF_BE, FT1000_REG_SUP_CTRL);
 
-    // Let's check for FEFE
-    status = ft1000_read_dpram32 (ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX, (u8 *)&templong, 4);
-    DEBUG("templong (fefe) = 0x%8x\n", templong);
+	/* Let's check for FEFE */
+	status =
+	    ft1000_read_dpram32(ft1000dev, FT1000_MAG_DPRAM_FEFE_INDX,
+				(u8 *) &templong, 4);
+	DEBUG("templong (fefe) = 0x%8x\n", templong);
 
-    // call codeloader
-    status = scram_dnldr(ft1000dev, pFileStart, FileLength);
+	/* call codeloader */
+	status = scram_dnldr(ft1000dev, pFileStart, FileLength);
 
 	if (status != STATUS_SUCCESS)
 		return -EIO;
 
-    msleep(1000);
+	msleep(1000);
 
-    DEBUG("dsp_reload returned\n");
-	return 0;
+	DEBUG("dsp_reload returned\n");
 
+	return 0;
 }
 
 //---------------------------------------------------------------------------
@@ -647,32 +593,33 @@ int dsp_reload(struct ft1000_device *ft1000dev)
 //     none
 //
 //---------------------------------------------------------------------------
-static void ft1000_reset_asic (struct net_device *dev)
+static void ft1000_reset_asic(struct net_device *dev)
 {
 	struct ft1000_info *info = netdev_priv(dev);
-    struct ft1000_device *ft1000dev = info->pFt1000Dev;
-    u16 tempword;
+	struct ft1000_device *ft1000dev = info->pFt1000Dev;
+	u16 tempword;
 
-    DEBUG("ft1000_hw:ft1000_reset_asic called\n");
+	DEBUG("ft1000_hw:ft1000_reset_asic called\n");
 
-    info->ASICResetNum++;
+	info->ASICResetNum++;
 
-    // Let's use the register provided by the Magnemite ASIC to reset the
-    // ASIC and DSP.
-    ft1000_write_register(ft1000dev,  (DSP_RESET_BIT | ASIC_RESET_BIT), FT1000_REG_RESET );
+	/* Let's use the register provided by the Magnemite ASIC to reset the
+	 * ASIC and DSP.
+	 */
+	ft1000_write_register(ft1000dev, (DSP_RESET_BIT | ASIC_RESET_BIT),
+			      FT1000_REG_RESET);
 
-    mdelay(1);
+	mdelay(1);
 
-    // set watermark to -1 in order to not generate an interrrupt
-    ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_MAG_WATERMARK);
-
-    // clear interrupts
-    ft1000_read_register (ft1000dev, &tempword, FT1000_REG_SUP_ISR);
-    DEBUG("ft1000_hw: interrupt status register = 0x%x\n",tempword);
-    ft1000_write_register (ft1000dev,  tempword, FT1000_REG_SUP_ISR);
-    ft1000_read_register (ft1000dev, &tempword, FT1000_REG_SUP_ISR);
-    DEBUG("ft1000_hw: interrupt status register = 0x%x\n",tempword);
+	/* set watermark to -1 in order to not generate an interrrupt */
+	ft1000_write_register(ft1000dev, 0xffff, FT1000_REG_MAG_WATERMARK);
 
+	/* clear interrupts */
+	ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_ISR);
+	DEBUG("ft1000_hw: interrupt status register = 0x%x\n", tempword);
+	ft1000_write_register(ft1000dev, tempword, FT1000_REG_SUP_ISR);
+	ft1000_read_register(ft1000dev, &tempword, FT1000_REG_SUP_ISR);
+	DEBUG("ft1000_hw: interrupt status register = 0x%x\n", tempword);
 }
 
 
@@ -687,54 +634,53 @@ static void ft1000_reset_asic (struct net_device *dev)
 //              TRUE  (card reset successful)
 //
 //---------------------------------------------------------------------------
-static int ft1000_reset_card (struct net_device *dev)
+static int ft1000_reset_card(struct net_device *dev)
 {
 	struct ft1000_info *info = netdev_priv(dev);
-    struct ft1000_device *ft1000dev = info->pFt1000Dev;
-    u16 tempword;
+	struct ft1000_device *ft1000dev = info->pFt1000Dev;
+	u16 tempword;
 	struct prov_record *ptr;
 
-    DEBUG("ft1000_hw:ft1000_reset_card called.....\n");
-
-    info->fCondResetPend = 1;
-    info->CardReady = 0;
-    info->fProvComplete = 0;
-
-    // Make sure we free any memory reserve for provisioning
-    while (list_empty(&info->prov_list) == 0) {
-        DEBUG("ft1000_hw:ft1000_reset_card:deleting provisioning record\n");
-	ptr = list_entry(info->prov_list.next, struct prov_record, list);
-        list_del(&ptr->list);
-        kfree(ptr->pprov_data);
-        kfree(ptr);
-    }
-
-    DEBUG("ft1000_hw:ft1000_reset_card: reset asic\n");
-    //reset ASIC
-    ft1000_reset_asic(dev);
+	DEBUG("ft1000_hw:ft1000_reset_card called.....\n");
 
-    info->DSPResetNum++;
+	info->fCondResetPend = 1;
+	info->CardReady = 0;
+	info->fProvComplete = 0;
 
-    DEBUG("ft1000_hw:ft1000_reset_card: call dsp_reload\n");
-    dsp_reload(ft1000dev);
+	/* Make sure we free any memory reserve for provisioning */
+	while (list_empty(&info->prov_list) == 0) {
+		DEBUG("ft1000_reset_card:deleting provisioning record\n");
+		ptr =
+		    list_entry(info->prov_list.next, struct prov_record, list);
+		list_del(&ptr->list);
+		kfree(ptr->pprov_data);
+		kfree(ptr);
+	}
 
-    DEBUG("dsp reload successful\n");
+	DEBUG("ft1000_hw:ft1000_reset_card: reset asic\n");
+	ft1000_reset_asic(dev);
 
+	info->DSPResetNum++;
 
-    mdelay(10);
+	DEBUG("ft1000_hw:ft1000_reset_card: call dsp_reload\n");
+	dsp_reload(ft1000dev);
 
-    // Initialize DSP heartbeat area to ho
-    ft1000_write_dpram16(ft1000dev, FT1000_MAG_HI_HO, ho_mag, FT1000_MAG_HI_HO_INDX);
-    ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (u8 *)&tempword, FT1000_MAG_HI_HO_INDX);
-    DEBUG("ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n", tempword);
+	DEBUG("dsp reload successful\n");
 
+	mdelay(10);
 
+	/* Initialize DSP heartbeat area */
+	ft1000_write_dpram16(ft1000dev, FT1000_MAG_HI_HO, ho_mag,
+			     FT1000_MAG_HI_HO_INDX);
+	ft1000_read_dpram16(ft1000dev, FT1000_MAG_HI_HO, (u8 *) &tempword,
+			    FT1000_MAG_HI_HO_INDX);
+	DEBUG("ft1000_hw:ft1000_reset_card:hi_ho value = 0x%x\n", tempword);
 
-    info->CardReady = 1;
+	info->CardReady = 1;
 
-    info->fCondResetPend = 0;
-    return TRUE;
+	info->fCondResetPend = 0;
 
+	return TRUE;
 }
 
 
@@ -742,10 +688,10 @@ static int ft1000_reset_card (struct net_device *dev)
 #ifdef HAVE_NET_DEVICE_OPS
 static const struct net_device_ops ftnet_ops =
 {
-.ndo_open = &ft1000_open,
-.ndo_stop = &ft1000_close,
-.ndo_start_xmit = &ft1000_start_xmit,
-.ndo_get_stats = &ft1000_netdev_stats,
+	.ndo_open = &ft1000_open,
+	.ndo_stop = &ft1000_close,
+	.ndo_start_xmit = &ft1000_start_xmit,
+	.ndo_get_stats = &ft1000_netdev_stats,
 };
 #endif
 
@@ -764,9 +710,9 @@ static const struct net_device_ops ftnet_ops =
 // Notes:
 //
 //---------------------------------------------------------------------------
-u16 init_ft1000_netdev(struct ft1000_device *ft1000dev)
+int init_ft1000_netdev(struct ft1000_device *ft1000dev)
 {
-    struct net_device *netdev;
+	struct net_device *netdev;
 	struct ft1000_info *pInfo = NULL;
 	struct dpram_blk *pdpram_blk;
 	int i, ret_val;
@@ -774,27 +720,23 @@ u16 init_ft1000_netdev(struct ft1000_device *ft1000dev)
 	char card_nr[2];
 	unsigned long gCardIndex = 0;
 
-    DEBUG("Enter init_ft1000_netdev...\n");
-
+	DEBUG("Enter init_ft1000_netdev...\n");
 
 	netdev = alloc_etherdev(sizeof(struct ft1000_info));
-    if (!netdev )
-    {
-        DEBUG("init_ft1000_netdev: can not allocate network device\n");
-	return -ENOMEM;
-    }
+	if (!netdev) {
+		DEBUG("init_ft1000_netdev: can not allocate network device\n");
+		return -ENOMEM;
+	}
 
 	pInfo = netdev_priv(netdev);
 
-    //DEBUG("init_ft1000_netdev: gFt1000Info=%x, netdev=%x, ft1000dev=%x\n", gFt1000Info, netdev, ft1000dev);
-
 	memset(pInfo, 0, sizeof(struct ft1000_info));
 
-    dev_alloc_name(netdev, netdev->name);
+	dev_alloc_name(netdev, netdev->name);
 
-        DEBUG("init_ft1000_netdev: network device name is %s\n", netdev->name);
+	DEBUG("init_ft1000_netdev: network device name is %s\n", netdev->name);
 
-	if ( strncmp(netdev->name,"eth", 3) == 0) {
+	if (strncmp(netdev->name, "eth", 3) == 0) {
 		card_nr[0] = netdev->name[3];
 		card_nr[1] = '\0';
 		ret_val = strict_strtoul(card_nr, 10, &gCardIndex);
@@ -803,89 +745,83 @@ u16 init_ft1000_netdev(struct ft1000_device *ft1000dev)
 			goto err_net;
 		}
 
-            pInfo->CardNumber = gCardIndex;
-            DEBUG("card number = %d\n", pInfo->CardNumber);
-        }
-        else {
-            printk(KERN_ERR "ft1000: Invalid device name\n");
+		pInfo->CardNumber = gCardIndex;
+		DEBUG("card number = %d\n", pInfo->CardNumber);
+	} else {
+		printk(KERN_ERR "ft1000: Invalid device name\n");
 		ret_val = -ENXIO;
 		goto err_net;
-        }
+	}
 
-    memset(&pInfo->stats, 0, sizeof(struct net_device_stats) );
-
-   spin_lock_init(&pInfo->dpram_lock);
-    pInfo->pFt1000Dev = ft1000dev;
-    pInfo->DrvErrNum = 0;
-    pInfo->ASICResetNum = 0;
-    pInfo->registered = 1;
-    pInfo->ft1000_reset = ft1000_reset;
-    pInfo->mediastate = 0;
-    pInfo->fifo_cnt = 0;
-    pInfo->DeviceCreated = FALSE;
-    pInfo->CurrentInterruptEnableMask = ISR_DEFAULT_MASK;
-    pInfo->InterruptsEnabled = FALSE;
-    pInfo->CardReady = 0;
-    pInfo->DSP_TIME[0] = 0;
-    pInfo->DSP_TIME[1] = 0;
-    pInfo->DSP_TIME[2] = 0;
-    pInfo->DSP_TIME[3] = 0;
-    pInfo->fAppMsgPend = 0;
-    pInfo->fCondResetPend = 0;
+	memset(&pInfo->stats, 0, sizeof(struct net_device_stats));
+
+	spin_lock_init(&pInfo->dpram_lock);
+	pInfo->pFt1000Dev = ft1000dev;
+	pInfo->DrvErrNum = 0;
+	pInfo->ASICResetNum = 0;
+	pInfo->registered = 1;
+	pInfo->ft1000_reset = ft1000_reset;
+	pInfo->mediastate = 0;
+	pInfo->fifo_cnt = 0;
+	pInfo->DeviceCreated = FALSE;
+	pInfo->CurrentInterruptEnableMask = ISR_DEFAULT_MASK;
+	pInfo->InterruptsEnabled = FALSE;
+	pInfo->CardReady = 0;
+	pInfo->DSP_TIME[0] = 0;
+	pInfo->DSP_TIME[1] = 0;
+	pInfo->DSP_TIME[2] = 0;
+	pInfo->DSP_TIME[3] = 0;
+	pInfo->fAppMsgPend = 0;
+	pInfo->fCondResetPend = 0;
 	pInfo->usbboot = 0;
 	pInfo->dspalive = 0;
 	memset(&pInfo->tempbuf[0], 0, sizeof(pInfo->tempbuf));
 
-    INIT_LIST_HEAD(&pInfo->prov_list);
+	INIT_LIST_HEAD(&pInfo->prov_list);
 
 	INIT_LIST_HEAD(&pInfo->nodes.list);
-//mbelian
+
 #ifdef HAVE_NET_DEVICE_OPS
 	netdev->netdev_ops = &ftnet_ops;
 #else
-    netdev->hard_start_xmit = &ft1000_start_xmit;
-    netdev->get_stats = &ft1000_netdev_stats;
-    netdev->open = &ft1000_open;
-    netdev->stop = &ft1000_close;
+	netdev->hard_start_xmit = &ft1000_start_xmit;
+	netdev->get_stats = &ft1000_netdev_stats;
+	netdev->open = &ft1000_open;
+	netdev->stop = &ft1000_close;
 #endif
 
-    ft1000dev->net = netdev;
+	ft1000dev->net = netdev;
 
+	DEBUG("Initialize free_buff_lock and freercvpool\n");
+	spin_lock_init(&free_buff_lock);
 
+	/* initialize a list of buffers to be use for queuing
+	 * up receive command data
+	 */
+	INIT_LIST_HEAD(&freercvpool);
 
-//init free_buff_lock, freercvpool, numofmsgbuf, pdpram_blk
-//only init once per card
-//Jim
-    	  DEBUG("Initialize free_buff_lock and freercvpool\n");
-        spin_lock_init(&free_buff_lock);
-
-        // initialize a list of buffers to be use for queuing up receive command data
-        INIT_LIST_HEAD (&freercvpool);
-
-        // create list of free buffers
-        for (i=0; i<NUM_OF_FREE_BUFFERS; i++) {
-            // Get memory for DPRAM_DATA link list
+	/* create list of free buffers */
+	for (i = 0; i < NUM_OF_FREE_BUFFERS; i++) {
+		/* Get memory for DPRAM_DATA link list */
 		pdpram_blk = kmalloc(sizeof(struct dpram_blk), GFP_KERNEL);
 		if (pdpram_blk == NULL) {
 			ret_val = -ENOMEM;
 			goto err_free;
 		}
-            // Get a block of memory to store command data
-            pdpram_blk->pbuffer = kmalloc ( MAX_CMD_SQSIZE, GFP_KERNEL );
+		/* Get a block of memory to store command data */
+		pdpram_blk->pbuffer = kmalloc(MAX_CMD_SQSIZE, GFP_KERNEL);
 		if (pdpram_blk->pbuffer == NULL) {
 			ret_val = -ENOMEM;
 			kfree(pdpram_blk);
 			goto err_free;
 		}
-            // link provisioning data
-            list_add_tail (&pdpram_blk->list, &freercvpool);
-        }
-        numofmsgbuf = NUM_OF_FREE_BUFFERS;
-
+		/* link provisioning data */
+		list_add_tail(&pdpram_blk->list, &freercvpool);
+	}
+	numofmsgbuf = NUM_OF_FREE_BUFFERS;
 
 	return 0;
 
-
 err_free:
 	list_for_each_safe(cur, tmp, &freercvpool) {
 		pdpram_blk = list_entry(cur, struct dpram_blk, list);
@@ -898,8 +834,6 @@ err_net:
 	return ret_val;
 }
 
-
-
 //---------------------------------------------------------------------------
 // Function:    reg_ft1000_netdev
 //
@@ -914,46 +848,42 @@ err_net:
 // Notes:
 //
 //---------------------------------------------------------------------------
-int reg_ft1000_netdev(struct ft1000_device *ft1000dev, struct usb_interface *intf)
+int reg_ft1000_netdev(struct ft1000_device *ft1000dev,
+		      struct usb_interface *intf)
 {
-    struct net_device *netdev;
+	struct net_device *netdev;
 	struct ft1000_info *pInfo;
 	int rc;
 
-    netdev = ft1000dev->net;
-    pInfo = netdev_priv(ft1000dev->net);
-    DEBUG("Enter reg_ft1000_netdev...\n");
+	netdev = ft1000dev->net;
+	pInfo = netdev_priv(ft1000dev->net);
+	DEBUG("Enter reg_ft1000_netdev...\n");
 
+	ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID);
 
-    ft1000_read_register(ft1000dev, &pInfo->AsicID, FT1000_REG_ASIC_ID);
-
-    usb_set_intfdata(intf, pInfo);
-    SET_NETDEV_DEV(netdev, &intf->dev);
-
-    rc = register_netdev(netdev);
-    if (rc)
-    {
-        DEBUG("reg_ft1000_netdev: could not register network device\n");
-        free_netdev(netdev);
-	return rc;
-    }
-
+	usb_set_intfdata(intf, pInfo);
+	SET_NETDEV_DEV(netdev, &intf->dev);
 
-    //Create character device, implemented by Jim
-    ft1000_create_dev(ft1000dev);
+	rc = register_netdev(netdev);
+	if (rc) {
+		DEBUG("reg_ft1000_netdev: could not register network device\n");
+		free_netdev(netdev);
+		return rc;
+	}
 
-    DEBUG ("reg_ft1000_netdev returned\n");
+	ft1000_create_dev(ft1000dev);
 
-    pInfo->CardReady = 1;
+	DEBUG("reg_ft1000_netdev returned\n");
 
+	pInfo->CardReady = 1;
 
 	return 0;
 }
 
 static int ft1000_reset(struct net_device *dev)
 {
-    ft1000_reset_card(dev);
-    return 0;
+	ft1000_reset_card(dev);
+	return 0;
 }
 
 //---------------------------------------------------------------------------
@@ -972,14 +902,14 @@ static int ft1000_reset(struct net_device *dev)
 static void ft1000_usb_transmit_complete(struct urb *urb)
 {
 
-    struct ft1000_device *ft1000dev = urb->context;
+	struct ft1000_device *ft1000dev = urb->context;
 
     //DEBUG("ft1000_usb_transmit_complete entered\n");
 
-    if (urb->status)
-        printk("%s: TX status %d\n", ft1000dev->net->name, urb->status);
+	if (urb->status)
+		pr_err("%s: TX status %d\n", ft1000dev->net->name, urb->status);
 
-    netif_wake_queue(ft1000dev->net);
+	netif_wake_queue(ft1000dev->net);
 
     //DEBUG("Return from ft1000_usb_transmit_complete\n");
 }
@@ -999,37 +929,31 @@ static void ft1000_usb_transmit_complete(struct urb *urb)
 //              SUCCESS
 //
 //---------------------------------------------------------------------------
-static int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len)
+static int ft1000_copy_down_pkt(struct net_device *netdev, u8 * packet, u16 len)
 {
 	struct ft1000_info *pInfo = netdev_priv(netdev);
-    struct ft1000_device *pFt1000Dev = pInfo->pFt1000Dev;
-
+	struct ft1000_device *pFt1000Dev = pInfo->pFt1000Dev;
 
 	int count, ret;
-    u8 *t;
+	u8 *t;
 	struct pseudo_hdr hdr;
 
-    if (!pInfo->CardReady)
-    {
-
-        DEBUG("ft1000_copy_down_pkt::Card Not Ready\n");
-	return -ENODEV;
-
-    }
-
+	if (!pInfo->CardReady) {
+		DEBUG("ft1000_copy_down_pkt::Card Not Ready\n");
+		return -ENODEV;
+	}
 
-    //DEBUG("ft1000_copy_down_pkt() entered, len = %d\n", len);
+	//DEBUG("ft1000_copy_down_pkt() entered, len = %d\n", len);
 
 	count = sizeof(struct pseudo_hdr) + len;
-    if(count > MAX_BUF_SIZE)
-    {
-        DEBUG("Error:ft1000_copy_down_pkt:Message Size Overflow!\n");
-    	DEBUG("size = %d\n", count);
-	return -EINVAL;
-    }
+	if (count > MAX_BUF_SIZE) {
+		DEBUG("Error:ft1000_copy_down_pkt:Message Size Overflow!\n");
+		DEBUG("size = %d\n", count);
+		return -EINVAL;
+	}
 
-    if ( count % 4)
-        count = count + (4- (count %4) );
+	if (count % 4)
+		count = count + (4 - (count % 4));
 
 	memset(&hdr, 0, sizeof(struct pseudo_hdr));
 
@@ -1042,46 +966,45 @@ static int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len)
 	hdr.control = 0x00;
 
 	hdr.checksum = hdr.length ^ hdr.source ^ hdr.destination ^
-			hdr.portdest ^ hdr.portsrc ^ hdr.sh_str_id ^
-			hdr.control;
+	    hdr.portdest ^ hdr.portsrc ^ hdr.sh_str_id ^ hdr.control;
 
 	memcpy(&pFt1000Dev->tx_buf[0], &hdr, sizeof(hdr));
 	memcpy(&(pFt1000Dev->tx_buf[sizeof(struct pseudo_hdr)]), packet, len);
 
-    netif_stop_queue(netdev);
+	netif_stop_queue(netdev);
 
-    //DEBUG ("ft1000_copy_down_pkt: count = %d\n", count);
+	//DEBUG ("ft1000_copy_down_pkt: count = %d\n", count);
 
-    usb_fill_bulk_urb(pFt1000Dev->tx_urb,
-                      pFt1000Dev->dev,
-                      usb_sndbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_out_endpointAddr),
-                      pFt1000Dev->tx_buf,
-                      count,
-                      ft1000_usb_transmit_complete,
-                      (void*)pFt1000Dev);
-
-    t = (u8 *)pFt1000Dev->tx_urb->transfer_buffer;
-    //DEBUG("transfer_length=%d\n", pFt1000Dev->tx_urb->transfer_buffer_length);
-    /*for (i=0; i<count; i++ )
-    {
-       DEBUG("%x    ", *t++ );
-    }*/
+	usb_fill_bulk_urb(pFt1000Dev->tx_urb,
+			  pFt1000Dev->dev,
+			  usb_sndbulkpipe(pFt1000Dev->dev,
+					  pFt1000Dev->bulk_out_endpointAddr),
+			  pFt1000Dev->tx_buf, count,
+			  ft1000_usb_transmit_complete, (void *)pFt1000Dev);
 
+	t = (u8 *) pFt1000Dev->tx_urb->transfer_buffer;
+	//DEBUG("transfer_length=%d\n", pFt1000Dev->tx_urb->transfer_buffer_length);
+	/*for (i=0; i<count; i++ )
+	   {
+	   DEBUG("%x    ", *t++ );
+	   } */
 
 	ret = usb_submit_urb(pFt1000Dev->tx_urb, GFP_ATOMIC);
+
 	if (ret) {
 		DEBUG("ft1000 failed tx_urb %d\n", ret);
 		return ret;
 	} else {
 		pInfo->stats.tx_packets++;
-		pInfo->stats.tx_bytes += (len+14);
+		pInfo->stats.tx_bytes += (len + 14);
 	}
 
-    //DEBUG("ft1000_copy_down_pkt() exit\n");
+	//DEBUG("ft1000_copy_down_pkt() exit\n");
 
 	return 0;
 }
 
+
 //---------------------------------------------------------------------------
 // Function:    ft1000_start_xmit
 //
@@ -1099,61 +1022,56 @@ static int ft1000_copy_down_pkt (struct net_device *netdev, u8 *packet, u16 len)
 static int ft1000_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ft1000_info *pInfo = netdev_priv(dev);
-    struct ft1000_device *pFt1000Dev= pInfo->pFt1000Dev;
-    u8 *pdata;
-    int maxlen, pipe;
-
+	struct ft1000_device *pFt1000Dev = pInfo->pFt1000Dev;
+	u8 *pdata;
+	int maxlen, pipe;
 
-    //DEBUG(" ft1000_start_xmit() entered\n");
-
-    if ( skb == NULL )
-    {
-        DEBUG ("ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n" );
-	return NETDEV_TX_OK;
-    }
-
-    if ( pFt1000Dev->status & FT1000_STATUS_CLOSING)
-    {
-        DEBUG("network driver is closed, return\n");
-	goto err;
-    }
-
-    //DEBUG("ft1000_start_xmit 1:length of packet = %d\n", skb->len);
-    pipe = usb_sndbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_out_endpointAddr);
-    maxlen = usb_maxpacket(pFt1000Dev->dev, pipe, usb_pipeout(pipe));
-    //DEBUG("ft1000_start_xmit 2: pipe=%d dev->maxpacket  = %d\n", pipe, maxlen);
-
-    pdata = (u8 *)skb->data;
-    /*for (i=0; i<skb->len; i++)
-        DEBUG("skb->data[%d]=%x    ", i, *(skb->data+i));
-
-    DEBUG("\n");*/
+	//DEBUG(" ft1000_start_xmit() entered\n");
 
+	if (skb == NULL) {
+		DEBUG("ft1000_hw: ft1000_start_xmit:skb == NULL!!!\n");
+		return NETDEV_TX_OK;
+	}
 
-    if (pInfo->mediastate == 0)
-    {
-        /* Drop packet is mediastate is down */
-        DEBUG("ft1000_hw:ft1000_start_xmit:mediastate is down\n");
-	goto err;
-    }
+	if (pFt1000Dev->status & FT1000_STATUS_CLOSING) {
+		DEBUG("network driver is closed, return\n");
+		goto err;
+	}
+	//DEBUG("ft1000_start_xmit 1:length of packet = %d\n", skb->len);
+	pipe =
+	    usb_sndbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_out_endpointAddr);
+	maxlen = usb_maxpacket(pFt1000Dev->dev, pipe, usb_pipeout(pipe));
+	//DEBUG("ft1000_start_xmit 2: pipe=%d dev->maxpacket  = %d\n", pipe, maxlen);
+
+	pdata = (u8 *) skb->data;
+	/*for (i=0; i<skb->len; i++)
+	   DEBUG("skb->data[%d]=%x    ", i, *(skb->data+i));
+
+	   DEBUG("\n"); */
+
+	if (pInfo->mediastate == 0) {
+		/* Drop packet is mediastate is down */
+		DEBUG("ft1000_hw:ft1000_start_xmit:mediastate is down\n");
+		goto err;
+	}
 
-    if ( (skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE) )
-    {
-        /* Drop packet which has invalid size */
-        DEBUG("ft1000_hw:ft1000_start_xmit:invalid ethernet length\n");
-	goto err;
-    }
+	if ((skb->len < ENET_HEADER_SIZE) || (skb->len > ENET_MAX_SIZE)) {
+		/* Drop packet which has invalid size */
+		DEBUG("ft1000_hw:ft1000_start_xmit:invalid ethernet length\n");
+		goto err;
+	}
 //mbelian
-	ft1000_copy_down_pkt(dev, (pdata+ENET_HEADER_SIZE-2),
-				skb->len - ENET_HEADER_SIZE + 2);
+	ft1000_copy_down_pkt(dev, (pdata + ENET_HEADER_SIZE - 2),
+			     skb->len - ENET_HEADER_SIZE + 2);
 
 err:
 	dev_kfree_skb(skb);
-    //DEBUG(" ft1000_start_xmit() exit\n");
+	//DEBUG(" ft1000_start_xmit() exit\n");
 
 	return NETDEV_TX_OK;
 }
 
+
 //---------------------------------------------------------------------------
 //
 // Function:   ft1000_copy_up_pkt
@@ -1167,109 +1085,100 @@ err:
 //              SUCCESS
 //
 //---------------------------------------------------------------------------
-static int ft1000_copy_up_pkt (struct urb *urb)
+static int ft1000_copy_up_pkt(struct urb *urb)
 {
 	struct ft1000_info *info = urb->context;
-    struct ft1000_device *ft1000dev = info->pFt1000Dev;
-    struct net_device *net = ft1000dev->net;
-
-    u16 tempword;
-    u16 len;
-    u16 lena; //mbelian
-    struct sk_buff *skb;
-    u16 i;
-    u8 *pbuffer=NULL;
-    u8 *ptemp=NULL;
-    u16 *chksum;
-
-
-    //DEBUG("ft1000_copy_up_pkt entered\n");
-
-    if ( ft1000dev->status & FT1000_STATUS_CLOSING)
-    {
-        DEBUG("network driver is closed, return\n");
-        return STATUS_SUCCESS;
-    }
-
-    // Read length
-    len = urb->transfer_buffer_length;
-    lena = urb->actual_length; //mbelian
-    //DEBUG("ft1000_copy_up_pkt: transfer_buffer_length=%d, actual_buffer_len=%d\n",
-      //       urb->transfer_buffer_length, urb->actual_length);
-
-    chksum = (u16 *)ft1000dev->rx_buf;
-
-    tempword = *chksum++;
-    for (i=1; i<7; i++)
-    {
-        tempword ^= *chksum++;
-    }
-
-    if  (tempword != *chksum)
-    {
-        info->stats.rx_errors ++;
-        ft1000_submit_rx_urb(info);
-        return STATUS_FAILURE;
-    }
-
-
-    //DEBUG("ft1000_copy_up_pkt: checksum is correct %x\n", *chksum);
-
-    skb = dev_alloc_skb(len+12+2);
-
-    if (skb == NULL)
-    {
-        DEBUG("ft1000_copy_up_pkt: No Network buffers available\n");
-        info->stats.rx_errors++;
-        ft1000_submit_rx_urb(info);
-        return STATUS_FAILURE;
-    }
-
-    pbuffer = (u8 *)skb_put(skb, len+12);
-
-    //subtract the number of bytes read already
-    ptemp = pbuffer;
-
-    // fake MAC address
-    *pbuffer++ = net->dev_addr[0];
-    *pbuffer++ = net->dev_addr[1];
-    *pbuffer++ = net->dev_addr[2];
-    *pbuffer++ = net->dev_addr[3];
-    *pbuffer++ = net->dev_addr[4];
-    *pbuffer++ = net->dev_addr[5];
-    *pbuffer++ = 0x00;
-    *pbuffer++ = 0x07;
-    *pbuffer++ = 0x35;
-    *pbuffer++ = 0xff;
-    *pbuffer++ = 0xff;
-    *pbuffer++ = 0xfe;
-
-
-
-
-	memcpy(pbuffer, ft1000dev->rx_buf+sizeof(struct pseudo_hdr), len-sizeof(struct pseudo_hdr));
-
-    //DEBUG("ft1000_copy_up_pkt: Data passed to Protocol layer\n");
-    /*for (i=0; i<len+12; i++)
-    {
-        DEBUG("ft1000_copy_up_pkt: Protocol Data: 0x%x\n ", *ptemp++);
-    }*/
+	struct ft1000_device *ft1000dev = info->pFt1000Dev;
+	struct net_device *net = ft1000dev->net;
+
+	u16 tempword;
+	u16 len;
+	u16 lena;		//mbelian
+	struct sk_buff *skb;
+	u16 i;
+	u8 *pbuffer = NULL;
+	u8 *ptemp = NULL;
+	u16 *chksum;
+
+	//DEBUG("ft1000_copy_up_pkt entered\n");
+
+	if (ft1000dev->status & FT1000_STATUS_CLOSING) {
+		DEBUG("network driver is closed, return\n");
+		return STATUS_SUCCESS;
+	}
+	// Read length
+	len = urb->transfer_buffer_length;
+	lena = urb->actual_length;	//mbelian
+	//DEBUG("ft1000_copy_up_pkt: transfer_buffer_length=%d, actual_buffer_len=%d\n",
+	//       urb->transfer_buffer_length, urb->actual_length);
+
+	chksum = (u16 *) ft1000dev->rx_buf;
+
+	tempword = *chksum++;
+	for (i = 1; i < 7; i++)
+		tempword ^= *chksum++;
+
+	if (tempword != *chksum) {
+		info->stats.rx_errors++;
+		ft1000_submit_rx_urb(info);
+		return STATUS_FAILURE;
+	}
 
-    skb->dev = net;
+	//DEBUG("ft1000_copy_up_pkt: checksum is correct %x\n", *chksum);
 
-    skb->protocol = eth_type_trans(skb, net);
-    skb->ip_summed = CHECKSUM_UNNECESSARY;
-    netif_rx(skb);
+	skb = dev_alloc_skb(len + 12 + 2);
 
-    info->stats.rx_packets++;
-    // Add on 12 bytes for MAC address which was removed
-    info->stats.rx_bytes += (lena+12); //mbelian
+	if (skb == NULL) {
+		DEBUG("ft1000_copy_up_pkt: No Network buffers available\n");
+		info->stats.rx_errors++;
+		ft1000_submit_rx_urb(info);
+		return STATUS_FAILURE;
+	}
 
-    ft1000_submit_rx_urb(info);
-    //DEBUG("ft1000_copy_up_pkt exited\n");
-    return SUCCESS;
+	pbuffer = (u8 *) skb_put(skb, len + 12);
+
+	/* subtract the number of bytes read already */
+	ptemp = pbuffer;
+
+	/* fake MAC address */
+	*pbuffer++ = net->dev_addr[0];
+	*pbuffer++ = net->dev_addr[1];
+	*pbuffer++ = net->dev_addr[2];
+	*pbuffer++ = net->dev_addr[3];
+	*pbuffer++ = net->dev_addr[4];
+	*pbuffer++ = net->dev_addr[5];
+	*pbuffer++ = 0x00;
+	*pbuffer++ = 0x07;
+	*pbuffer++ = 0x35;
+	*pbuffer++ = 0xff;
+	*pbuffer++ = 0xff;
+	*pbuffer++ = 0xfe;
+
+	memcpy(pbuffer, ft1000dev->rx_buf + sizeof(struct pseudo_hdr),
+	       len - sizeof(struct pseudo_hdr));
+
+	//DEBUG("ft1000_copy_up_pkt: Data passed to Protocol layer\n");
+	/*for (i=0; i<len+12; i++)
+	   {
+	   DEBUG("ft1000_copy_up_pkt: Protocol Data: 0x%x\n ", *ptemp++);
+	   } */
+
+	skb->dev = net;
+
+	skb->protocol = eth_type_trans(skb, net);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	netif_rx(skb);
+
+	info->stats.rx_packets++;
+	/* Add on 12 bytes for MAC address which was removed */
+	info->stats.rx_bytes += (lena + 12);	//mbelian
+
+	ft1000_submit_rx_urb(info);
+	//DEBUG("ft1000_copy_up_pkt exited\n");
+	return SUCCESS;
 }
 
+
 //---------------------------------------------------------------------------
 //
 // Function:   ft1000_submit_rx_urb
@@ -1285,38 +1194,36 @@ static int ft1000_copy_up_pkt (struct urb *urb)
 //---------------------------------------------------------------------------
 static int ft1000_submit_rx_urb(struct ft1000_info *info)
 {
-    int result;
-    struct ft1000_device *pFt1000Dev = info->pFt1000Dev;
-
-
-    //DEBUG ("ft1000_submit_rx_urb entered: sizeof rx_urb is %d\n", sizeof(*pFt1000Dev->rx_urb));
-    if ( pFt1000Dev->status & FT1000_STATUS_CLOSING)
-    {
-        DEBUG("network driver is closed, return\n");
-        //usb_kill_urb(pFt1000Dev->rx_urb); //mbelian
-	return -ENODEV;
-    }
-
-    usb_fill_bulk_urb(pFt1000Dev->rx_urb,
-            pFt1000Dev->dev,
-            usb_rcvbulkpipe(pFt1000Dev->dev, pFt1000Dev->bulk_in_endpointAddr),
-            pFt1000Dev->rx_buf,
-            MAX_BUF_SIZE,
-            (usb_complete_t)ft1000_copy_up_pkt,
-            info);
+	int result;
+	struct ft1000_device *pFt1000Dev = info->pFt1000Dev;
+
+	//DEBUG ("ft1000_submit_rx_urb entered: sizeof rx_urb is %d\n", sizeof(*pFt1000Dev->rx_urb));
+	if (pFt1000Dev->status & FT1000_STATUS_CLOSING) {
+		DEBUG("network driver is closed, return\n");
+		//usb_kill_urb(pFt1000Dev->rx_urb); //mbelian
+		return -ENODEV;
+	}
 
+	usb_fill_bulk_urb(pFt1000Dev->rx_urb,
+			  pFt1000Dev->dev,
+			  usb_rcvbulkpipe(pFt1000Dev->dev,
+					  pFt1000Dev->bulk_in_endpointAddr),
+			  pFt1000Dev->rx_buf, MAX_BUF_SIZE,
+			  (usb_complete_t) ft1000_copy_up_pkt, info);
 
-    if((result = usb_submit_urb(pFt1000Dev->rx_urb, GFP_ATOMIC)))
-    {
-        printk("ft1000_submit_rx_urb: submitting rx_urb %d failed\n", result);
-	return result;
-    }
+	result = usb_submit_urb(pFt1000Dev->rx_urb, GFP_ATOMIC);
 
-    //DEBUG("ft1000_submit_rx_urb exit: result=%d\n", result);
+	if (result) {
+		pr_err("ft1000_submit_rx_urb: submitting rx_urb %d failed\n",
+		       result);
+		return result;
+	}
+	//DEBUG("ft1000_submit_rx_urb exit: result=%d\n", result);
 
 	return 0;
 }
 
+
 //---------------------------------------------------------------------------
 // Function:    ft1000_open
 //
@@ -1331,27 +1238,26 @@ static int ft1000_submit_rx_urb(struct ft1000_info *info)
 // Notes:
 //
 //---------------------------------------------------------------------------
-static int ft1000_open (struct net_device *dev)
+static int ft1000_open(struct net_device *dev)
 {
 	struct ft1000_info *pInfo = netdev_priv(dev);
-    struct timeval tv; //mbelian
+	struct timeval tv;	//mbelian
 	int ret;
 
-    DEBUG("ft1000_open is called for card %d\n", pInfo->CardNumber);
-    //DEBUG("ft1000_open: dev->addr=%x, dev->addr_len=%d\n", dev->addr, dev->addr_len);
+	DEBUG("ft1000_open is called for card %d\n", pInfo->CardNumber);
+	//DEBUG("ft1000_open: dev->addr=%x, dev->addr_len=%d\n", dev->addr, dev->addr_len);
 
-	pInfo->stats.rx_bytes = 0; //mbelian
-	pInfo->stats.tx_bytes = 0; //mbelian
-	pInfo->stats.rx_packets = 0; //mbelian
-	pInfo->stats.tx_packets = 0; //mbelian
+	pInfo->stats.rx_bytes = 0;	//mbelian
+	pInfo->stats.tx_bytes = 0;	//mbelian
+	pInfo->stats.rx_packets = 0;	//mbelian
+	pInfo->stats.tx_packets = 0;	//mbelian
 	do_gettimeofday(&tv);
-    pInfo->ConTm = tv.tv_sec;
-	pInfo->ProgConStat = 0; //mbelian
-
+	pInfo->ConTm = tv.tv_sec;
+	pInfo->ProgConStat = 0;	//mbelian
 
-    netif_start_queue(dev);
+	netif_start_queue(dev);
 
-    netif_carrier_on(dev); //mbelian
+	netif_carrier_on(dev);	//mbelian
 
 	ret = ft1000_submit_rx_urb(pInfo);
 
@@ -1375,24 +1281,23 @@ static int ft1000_open (struct net_device *dev)
 int ft1000_close(struct net_device *net)
 {
 	struct ft1000_info *pInfo = netdev_priv(net);
-    struct ft1000_device *ft1000dev = pInfo->pFt1000Dev;
+	struct ft1000_device *ft1000dev = pInfo->pFt1000Dev;
 
-    //DEBUG ("ft1000_close: netdev->refcnt=%d\n", net->refcnt);
+	//DEBUG ("ft1000_close: netdev->refcnt=%d\n", net->refcnt);
 
-    ft1000dev->status |= FT1000_STATUS_CLOSING;
-    
-    //DEBUG("ft1000_close: calling usb_kill_urb \n");
+	ft1000dev->status |= FT1000_STATUS_CLOSING;
 
-    DEBUG("ft1000_close: pInfo=%p, ft1000dev=%p\n", pInfo, ft1000dev);
-    netif_carrier_off(net);//mbelian
-    netif_stop_queue(net);
-    //DEBUG("ft1000_close: netif_stop_queue called\n");
-    ft1000dev->status &= ~FT1000_STATUS_CLOSING;
+	//DEBUG("ft1000_close: calling usb_kill_urb \n");
 
-   pInfo->ProgConStat = 0xff; //mbelian
+	DEBUG("ft1000_close: pInfo=%p, ft1000dev=%p\n", pInfo, ft1000dev);
+	netif_carrier_off(net);	//mbelian
+	netif_stop_queue(net);
+	//DEBUG("ft1000_close: netif_stop_queue called\n");
+	ft1000dev->status &= ~FT1000_STATUS_CLOSING;
 
+	pInfo->ProgConStat = 0xff;	//mbelian
 
-    return 0;
+	return 0;
 }
 
 static struct net_device_stats *ft1000_netdev_stats(struct net_device *dev)
@@ -1420,40 +1325,41 @@ Jim
 //              TRUE  (device is present)
 //
 //---------------------------------------------------------------------------
-static int ft1000_chkcard (struct ft1000_device *dev) {
-    u16 tempword;
-    u16 status;
+static int ft1000_chkcard(struct ft1000_device *dev)
+{
+	u16 tempword;
+	u16 status;
 	struct ft1000_info *info = netdev_priv(dev->net);
 
-    if (info->fCondResetPend)
-    {
-        DEBUG("ft1000_hw:ft1000_chkcard:Card is being reset, return FALSE\n");
-        return TRUE;
-    }
-
-    // Mask register is used to check for device presence since it is never
-    // set to zero.
-    status = ft1000_read_register(dev, &tempword, FT1000_REG_SUP_IMASK);
-    //DEBUG("ft1000_hw:ft1000_chkcard: read FT1000_REG_SUP_IMASK = %x\n", tempword);
-    if (tempword == 0) {
-        DEBUG("ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
-        return FALSE;
-    }
-
-    // The system will return the value of 0xffff for the version register
-    // if the device is not present.
-    status = ft1000_read_register(dev, &tempword, FT1000_REG_ASIC_ID);
-    //DEBUG("ft1000_hw:ft1000_chkcard: read FT1000_REG_ASIC_ID = %x\n", tempword);
-    if (tempword != 0x1b01 ){
-	dev->status |= FT1000_STATUS_CLOSING; //mbelian
-        DEBUG("ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
-        return FALSE;
-    }
-    return TRUE;
+	if (info->fCondResetPend) {
+		DEBUG
+		    ("ft1000_hw:ft1000_chkcard:Card is being reset, return FALSE\n");
+		return TRUE;
+	}
+	/* Mask register is used to check for device presence since it is never
+	 * set to zero.
+	 */
+	status = ft1000_read_register(dev, &tempword, FT1000_REG_SUP_IMASK);
+	//DEBUG("ft1000_hw:ft1000_chkcard: read FT1000_REG_SUP_IMASK = %x\n", tempword);
+	if (tempword == 0) {
+		DEBUG
+		    ("ft1000_hw:ft1000_chkcard: IMASK = 0 Card not detected\n");
+		return FALSE;
+	}
+	/* The system will return the value of 0xffff for the version register
+	 * if the device is not present.
+	 */
+	status = ft1000_read_register(dev, &tempword, FT1000_REG_ASIC_ID);
+	//DEBUG("ft1000_hw:ft1000_chkcard: read FT1000_REG_ASIC_ID = %x\n", tempword);
+	if (tempword != 0x1b01) {
+		dev->status |= FT1000_STATUS_CLOSING;	//mbelian
+		DEBUG
+		    ("ft1000_hw:ft1000_chkcard: Version = 0xffff Card not detected\n");
+		return FALSE;
+	}
+	return TRUE;
 }
 
-
-
 //---------------------------------------------------------------------------
 //
 // Function:   ft1000_receive_cmd
@@ -1467,425 +1373,476 @@ static int ft1000_chkcard (struct ft1000_device *dev) {
 //          = 1 (successful)
 //
 //---------------------------------------------------------------------------
-static bool ft1000_receive_cmd (struct ft1000_device *dev, u16 *pbuffer, int maxsz, u16 *pnxtph) {
-    u16 size, ret;
-    u16 *ppseudohdr;
-    int i;
-    u16 tempword;
+static bool ft1000_receive_cmd(struct ft1000_device *dev, u16 *pbuffer,
+			       int maxsz, u16 *pnxtph)
+{
+	u16 size, ret;
+	u16 *ppseudohdr;
+	int i;
+	u16 tempword;
+
+	ret =
+	    ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (u8 *) &size,
+				FT1000_MAG_PH_LEN_INDX);
+	size = ntohs(size) + PSEUDOSZ;
+	if (size > maxsz) {
+		DEBUG("FT1000:ft1000_receive_cmd:Invalid command length = %d\n",
+		      size);
+		return FALSE;
+	} else {
+		ppseudohdr = (u16 *) pbuffer;
+		ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE,
+				      FT1000_REG_DPRAM_ADDR);
+		ret =
+		    ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
+		//DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer);
+		pbuffer++;
+		ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE + 1,
+				      FT1000_REG_DPRAM_ADDR);
+		for (i = 0; i <= (size >> 2); i++) {
+			ret =
+			    ft1000_read_register(dev, pbuffer,
+						 FT1000_REG_MAG_DPDATAL);
+			pbuffer++;
+			ret =
+			    ft1000_read_register(dev, pbuffer,
+						 FT1000_REG_MAG_DPDATAH);
+			pbuffer++;
+		}
+		/* copy odd aligned word */
+		ret =
+		    ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL);
+		//DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer);
+		pbuffer++;
+		ret =
+		    ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
+		//DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer);
+		pbuffer++;
+		if (size & 0x0001) {
+			/* copy odd byte from fifo */
+			ret =
+			    ft1000_read_register(dev, &tempword,
+						 FT1000_REG_DPRAM_DATA);
+			*pbuffer = ntohs(tempword);
+		}
+		/* Check if pseudo header checksum is good
+		 * Calculate pseudo header checksum
+		 */
+		tempword = *ppseudohdr++;
+		for (i = 1; i < 7; i++)
+			tempword ^= *ppseudohdr++;
 
-    ret = ft1000_read_dpram16(dev, FT1000_MAG_PH_LEN, (u8 *)&size, FT1000_MAG_PH_LEN_INDX);
-    size = ntohs(size) + PSEUDOSZ;
-    if (size > maxsz) {
-        DEBUG("FT1000:ft1000_receive_cmd:Invalid command length = %d\n", size);
-        return FALSE;
-    }
-    else {
-        ppseudohdr = (u16 *)pbuffer;
-        ft1000_write_register(dev, FT1000_DPRAM_MAG_RX_BASE, FT1000_REG_DPRAM_ADDR);
-        ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
-        //DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer);
-        pbuffer++;
-        ft1000_write_register(dev,  FT1000_DPRAM_MAG_RX_BASE+1, FT1000_REG_DPRAM_ADDR);
-        for (i=0; i<=(size>>2); i++) {
-            ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL);
-            pbuffer++;
-            ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
-            pbuffer++;
-        }
-        //copy odd aligned word
-        ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAL);
-        //DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer);
-        pbuffer++;
-        ret = ft1000_read_register(dev, pbuffer, FT1000_REG_MAG_DPDATAH);
-        //DEBUG("ft1000_hw:received data = 0x%x\n", *pbuffer);
-        pbuffer++;
-        if (size & 0x0001) {
-            //copy odd byte from fifo
-            ret = ft1000_read_register(dev, &tempword, FT1000_REG_DPRAM_DATA);
-            *pbuffer = ntohs(tempword);
-        }
+		if ((tempword != *ppseudohdr))
+			return FALSE;
 
-        // Check if pseudo header checksum is good
-        // Calculate pseudo header checksum
-        tempword = *ppseudohdr++;
-        for (i=1; i<7; i++) {
-            tempword ^= *ppseudohdr++;
-        }
-        if ( (tempword != *ppseudohdr) ) {
-            return FALSE;
-        }
-
-        return TRUE;
-    }
+		return TRUE;
+	}
 }
 
-
 static int ft1000_dsp_prov(void *arg)
 {
-    struct ft1000_device *dev = (struct ft1000_device *)arg;
+	struct ft1000_device *dev = (struct ft1000_device *)arg;
 	struct ft1000_info *info = netdev_priv(dev->net);
-    u16 tempword;
-    u16 len;
-    u16 i=0;
+	u16 tempword;
+	u16 len;
+	u16 i = 0;
 	struct prov_record *ptr;
 	struct pseudo_hdr *ppseudo_hdr;
-    u16 *pmsg;
-    u16 status;
-    u16 TempShortBuf [256];
-
-    DEBUG("*** DspProv Entered\n");
-
-    while (list_empty(&info->prov_list) == 0)
-    {
-	DEBUG("DSP Provisioning List Entry\n");
-
-        // Check if doorbell is available
-        DEBUG("check if doorbell is cleared\n");
-        status = ft1000_read_register (dev, &tempword, FT1000_REG_DOORBELL);
-        if (status)
-	{
-		DEBUG("ft1000_dsp_prov::ft1000_read_register error\n");
-            break;
-        }
-
-        while (tempword & FT1000_DB_DPRAM_TX) {
-            mdelay(10);
-            i++;
-            if (i==10) {
-               DEBUG("FT1000:ft1000_dsp_prov:message drop\n");
-               return STATUS_FAILURE;
-            }
-            ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
-        }
+	u16 *pmsg;
+	u16 status;
+	u16 TempShortBuf[256];
+
+	DEBUG("*** DspProv Entered\n");
+
+	while (list_empty(&info->prov_list) == 0) {
+		DEBUG("DSP Provisioning List Entry\n");
+
+		/* Check if doorbell is available */
+		DEBUG("check if doorbell is cleared\n");
+		status =
+		    ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
+		if (status) {
+			DEBUG("ft1000_dsp_prov::ft1000_read_register error\n");
+			break;
+		}
 
-        if ( !(tempword & FT1000_DB_DPRAM_TX) ) {
-            DEBUG("*** Provision Data Sent to DSP\n");
-
-            // Send provisioning data
-		ptr = list_entry(info->prov_list.next, struct prov_record, list);
-            len = *(u16 *)ptr->pprov_data;
-            len = htons(len);
-            len += PSEUDOSZ;
-
-            pmsg = (u16 *)ptr->pprov_data;
-		ppseudo_hdr = (struct pseudo_hdr *)pmsg;
-            // Insert slow queue sequence number
-            ppseudo_hdr->seq_num = info->squeseqnum++;
-            ppseudo_hdr->portsrc = 0;
-            // Calculate new checksum
-            ppseudo_hdr->checksum = *pmsg++;
-            //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
-            for (i=1; i<7; i++) {
-                ppseudo_hdr->checksum ^= *pmsg++;
-                //DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
-            }
+		while (tempword & FT1000_DB_DPRAM_TX) {
+			mdelay(10);
+			i++;
+			if (i == 10) {
+				DEBUG("FT1000:ft1000_dsp_prov:message drop\n");
+				return STATUS_FAILURE;
+			}
+			ft1000_read_register(dev, &tempword,
+					     FT1000_REG_DOORBELL);
+		}
 
-            TempShortBuf[0] = 0;
-            TempShortBuf[1] = htons (len);
-            memcpy(&TempShortBuf[2], ppseudo_hdr, len);
+		if (!(tempword & FT1000_DB_DPRAM_TX)) {
+			DEBUG("*** Provision Data Sent to DSP\n");
 
-            status = ft1000_write_dpram32 (dev, 0, (u8 *)&TempShortBuf[0], (unsigned short)(len+2));
-            status = ft1000_write_register (dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL);
+			/* Send provisioning data */
+			ptr =
+			    list_entry(info->prov_list.next, struct prov_record,
+				       list);
+			len = *(u16 *) ptr->pprov_data;
+			len = htons(len);
+			len += PSEUDOSZ;
 
-            list_del(&ptr->list);
-            kfree(ptr->pprov_data);
-            kfree(ptr);
-        }
-        msleep(10);
-    }
+			pmsg = (u16 *) ptr->pprov_data;
+			ppseudo_hdr = (struct pseudo_hdr *)pmsg;
+			/* Insert slow queue sequence number */
+			ppseudo_hdr->seq_num = info->squeseqnum++;
+			ppseudo_hdr->portsrc = 0;
+			/* Calculate new checksum */
+			ppseudo_hdr->checksum = *pmsg++;
+			//DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
+			for (i = 1; i < 7; i++) {
+				ppseudo_hdr->checksum ^= *pmsg++;
+				//DEBUG("checksum = 0x%x\n", ppseudo_hdr->checksum);
+			}
+
+			TempShortBuf[0] = 0;
+			TempShortBuf[1] = htons(len);
+			memcpy(&TempShortBuf[2], ppseudo_hdr, len);
+
+			status =
+			    ft1000_write_dpram32(dev, 0,
+						 (u8 *) &TempShortBuf[0],
+						 (unsigned short)(len + 2));
+			status =
+			    ft1000_write_register(dev, FT1000_DB_DPRAM_TX,
+						  FT1000_REG_DOORBELL);
+
+			list_del(&ptr->list);
+			kfree(ptr->pprov_data);
+			kfree(ptr);
+		}
+		msleep(10);
+	}
 
-    DEBUG("DSP Provisioning List Entry finished\n");
+	DEBUG("DSP Provisioning List Entry finished\n");
 
-    msleep(100);
+	msleep(100);
 
-    info->fProvComplete = 1;
-    info->CardReady = 1;
-    return STATUS_SUCCESS;
+	info->fProvComplete = 1;
+	info->CardReady = 1;
 
+	return STATUS_SUCCESS;
 }
 
-
-static int ft1000_proc_drvmsg (struct ft1000_device *dev, u16 size) {
+static int ft1000_proc_drvmsg(struct ft1000_device *dev, u16 size)
+{
 	struct ft1000_info *info = netdev_priv(dev->net);
-    u16 msgtype;
-    u16 tempword;
+	u16 msgtype;
+	u16 tempword;
 	struct media_msg *pmediamsg;
 	struct dsp_init_msg *pdspinitmsg;
 	struct drv_msg *pdrvmsg;
-    u16 i;
+	u16 i;
 	struct pseudo_hdr *ppseudo_hdr;
-    u16 *pmsg;
-    u16 status;
-    union {
-        u8  byte[2];
-        u16 wrd;
-    } convert;
-
-
-    char *cmdbuffer = kmalloc(1600, GFP_KERNEL);
-    if (!cmdbuffer)
-	return STATUS_FAILURE;
-
-    status = ft1000_read_dpram32(dev, 0x200, cmdbuffer, size);
+	u16 *pmsg;
+	u16 status;
+	union {
+		u8 byte[2];
+		u16 wrd;
+	} convert;
 
+	char *cmdbuffer = kmalloc(1600, GFP_KERNEL);
+	if (!cmdbuffer)
+		return STATUS_FAILURE;
 
+	status = ft1000_read_dpram32(dev, 0x200, cmdbuffer, size);
 
 #ifdef JDEBUG
-        DEBUG("ft1000_proc_drvmsg:cmdbuffer\n");
-        for(i = 0; i < size; i+=5)
-        {
-            if( (i + 5) < size )
-                DEBUG("0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", cmdbuffer[i], cmdbuffer[i+1], cmdbuffer[i+2], cmdbuffer[i+3], cmdbuffer[i+4]);
-            else
-            {
-                for (j = i; j < size; j++)
-                DEBUG("0x%x ", cmdbuffer[j]);
-                DEBUG("\n");
-                break;
-            }
-        }
+	DEBUG("ft1000_proc_drvmsg:cmdbuffer\n");
+	for (i = 0; i < size; i += 5) {
+		if ((i + 5) < size)
+			DEBUG("0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", cmdbuffer[i],
+			      cmdbuffer[i + 1], cmdbuffer[i + 2],
+			      cmdbuffer[i + 3], cmdbuffer[i + 4]);
+		else {
+			for (j = i; j < size; j++)
+				DEBUG("0x%x ", cmdbuffer[j]);
+			DEBUG("\n");
+			break;
+		}
+	}
 #endif
 	pdrvmsg = (struct drv_msg *)&cmdbuffer[2];
-        msgtype = ntohs(pdrvmsg->type);
-        DEBUG("ft1000_proc_drvmsg:Command message type = 0x%x\n", msgtype);
-        switch (msgtype) {
-            case MEDIA_STATE: {
-                DEBUG("ft1000_proc_drvmsg:Command message type = MEDIA_STATE");
-
-		pmediamsg = (struct media_msg *)&cmdbuffer[0];
-                if (info->ProgConStat != 0xFF) {
-                    if (pmediamsg->state) {
-                        DEBUG("Media is up\n");
-                        if (info->mediastate == 0) {
-                            if ( info->NetDevRegDone )
-                            {
-                                //netif_carrier_on(dev->net);//mbelian
-                                netif_wake_queue(dev->net);
-                            }
-                            info->mediastate = 1;
-                            /*do_gettimeofday(&tv);
-                            info->ConTm = tv.tv_sec;*/ //mbelian
-                        }
-                    }
-                    else {
-                        DEBUG("Media is down\n");
-                        if (info->mediastate == 1) {
-                            info->mediastate = 0;
-                            if ( info->NetDevRegDone )
-                            {
-                                //netif_carrier_off(dev->net); mbelian
-                                //netif_stop_queue(dev->net);
-                            }
-                            info->ConTm = 0;
-                        }
-                    }
-                }
-                else {
-                    DEBUG("Media is down\n");
-                    if (info->mediastate == 1) {
-                        info->mediastate = 0;
-                        if ( info->NetDevRegDone)
-                        {
-                            //netif_carrier_off(dev->net); //mbelian
-                            //netif_stop_queue(dev->net);
-                        }
-                        info->ConTm = 0;
-                    }
-                }
-                break;
-            }
-            case DSP_INIT_MSG: {
-                DEBUG("ft1000_proc_drvmsg:Command message type = DSP_INIT_MSG");
-
-		pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[2];
-                memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
-                DEBUG("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n", info->DspVer[0], info->DspVer[1], info->DspVer[2], info->DspVer[3]);
-                memcpy(info->HwSerNum, pdspinitmsg->HwSerNum, HWSERNUMSZ);
-                memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
-                memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
-                DEBUG("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n", info->eui64[0],info->eui64[1], info->eui64[2], info->eui64[3], info->eui64[4], info->eui64[5],info->eui64[6], info->eui64[7]);
-                dev->net->dev_addr[0] = info->eui64[0];
-                dev->net->dev_addr[1] = info->eui64[1];
-                dev->net->dev_addr[2] = info->eui64[2];
-                dev->net->dev_addr[3] = info->eui64[5];
-                dev->net->dev_addr[4] = info->eui64[6];
-                dev->net->dev_addr[5] = info->eui64[7];
-
-		if (ntohs(pdspinitmsg->length) == (sizeof(struct dsp_init_msg) - 20)) {
-                    memcpy(info->ProductMode, pdspinitmsg->ProductMode, MODESZ);
-                    memcpy(info->RfCalVer, pdspinitmsg->RfCalVer, CALVERSZ);
-                    memcpy(info->RfCalDate, pdspinitmsg->RfCalDate, CALDATESZ);
-                    DEBUG("RFCalVer = 0x%2x 0x%2x\n", info->RfCalVer[0], info->RfCalVer[1]);
-                }
-                break;
-            }
-            case DSP_PROVISION: {
-                DEBUG("ft1000_proc_drvmsg:Command message type = DSP_PROVISION\n");
-
-                // kick off dspprov routine to start provisioning
-                // Send provisioning data to DSP
-                if (list_empty(&info->prov_list) == 0)
-                {
-		    info->fProvComplete = 0;
-		    status = ft1000_dsp_prov(dev);
-		    if (status != STATUS_SUCCESS)
-		        goto out;
-                }
-                else {
-                    info->fProvComplete = 1;
-                    status = ft1000_write_register (dev, FT1000_DB_HB, FT1000_REG_DOORBELL);
-                    DEBUG("FT1000:drivermsg:No more DSP provisioning data in dsp image\n");
-                }
-                DEBUG("ft1000_proc_drvmsg:DSP PROVISION is done\n");
-                break;
-            }
-            case DSP_STORE_INFO: {
-                DEBUG("ft1000_proc_drvmsg:Command message type = DSP_STORE_INFO");
-
-                DEBUG("FT1000:drivermsg:Got DSP_STORE_INFO\n");
-                tempword = ntohs(pdrvmsg->length);
-                info->DSPInfoBlklen = tempword;
-                if (tempword < (MAX_DSP_SESS_REC-4) ) {
-                    pmsg = (u16 *)&pdrvmsg->data[0];
-                    for (i=0; i<((tempword+1)/2); i++) {
-                        DEBUG("FT1000:drivermsg:dsp info data = 0x%x\n", *pmsg);
-                        info->DSPInfoBlk[i+10] = *pmsg++;
-                    }
-                }
-                else {
-                    info->DSPInfoBlklen = 0;
-                }
-                break;
-            }
-            case DSP_GET_INFO: {
-                DEBUG("FT1000:drivermsg:Got DSP_GET_INFO\n");
-                // copy dsp info block to dsp
-                info->DrvMsgPend = 1;
-                // allow any outstanding ioctl to finish
-                mdelay(10);
-                status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
-                if (tempword & FT1000_DB_DPRAM_TX) {
-                    mdelay(10);
-                    status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
-                    if (tempword & FT1000_DB_DPRAM_TX) {
-                        mdelay(10);
-                            status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
-                            if (tempword & FT1000_DB_DPRAM_TX) {
-                                break;
-                            }
-                    }
-                }
-
-                // Put message into Slow Queue
-                // Form Pseudo header
-                pmsg = (u16 *)info->DSPInfoBlk;
-                *pmsg++ = 0;
-                *pmsg++ = htons(info->DSPInfoBlklen+20+info->DSPInfoBlklen);
-		ppseudo_hdr = (struct pseudo_hdr *)(u16 *)&info->DSPInfoBlk[2];
-                ppseudo_hdr->length = htons(info->DSPInfoBlklen+4+info->DSPInfoBlklen);
-                ppseudo_hdr->source = 0x10;
-                ppseudo_hdr->destination = 0x20;
-                ppseudo_hdr->portdest = 0;
-                ppseudo_hdr->portsrc = 0;
-                ppseudo_hdr->sh_str_id = 0;
-                ppseudo_hdr->control = 0;
-                ppseudo_hdr->rsvd1 = 0;
-                ppseudo_hdr->rsvd2 = 0;
-                ppseudo_hdr->qos_class = 0;
-                // Insert slow queue sequence number
-                ppseudo_hdr->seq_num = info->squeseqnum++;
-                // Insert application id
-                ppseudo_hdr->portsrc = 0;
-                // Calculate new checksum
-                ppseudo_hdr->checksum = *pmsg++;
-                for (i=1; i<7; i++) {
-                    ppseudo_hdr->checksum ^= *pmsg++;
-                }
-                info->DSPInfoBlk[10] = 0x7200;
-                info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen);
-                status = ft1000_write_dpram32 (dev, 0, (u8 *)&info->DSPInfoBlk[0], (unsigned short)(info->DSPInfoBlklen+22));
-                status = ft1000_write_register (dev, FT1000_DB_DPRAM_TX, FT1000_REG_DOORBELL);
-                info->DrvMsgPend = 0;
-
-                break;
-            }
+	msgtype = ntohs(pdrvmsg->type);
+	DEBUG("ft1000_proc_drvmsg:Command message type = 0x%x\n", msgtype);
+	switch (msgtype) {
+	case MEDIA_STATE:{
+			DEBUG
+			    ("ft1000_proc_drvmsg:Command message type = MEDIA_STATE");
+
+			pmediamsg = (struct media_msg *)&cmdbuffer[0];
+			if (info->ProgConStat != 0xFF) {
+				if (pmediamsg->state) {
+					DEBUG("Media is up\n");
+					if (info->mediastate == 0) {
+						if (info->NetDevRegDone) {
+							//netif_carrier_on(dev->net);//mbelian
+							netif_wake_queue(dev->
+									 net);
+						}
+						info->mediastate = 1;
+						/*do_gettimeofday(&tv);
+						   info->ConTm = tv.tv_sec; *///mbelian
+					}
+				} else {
+					DEBUG("Media is down\n");
+					if (info->mediastate == 1) {
+						info->mediastate = 0;
+						if (info->NetDevRegDone) {
+							//netif_carrier_off(dev->net); mbelian
+							//netif_stop_queue(dev->net);
+						}
+						info->ConTm = 0;
+					}
+				}
+			} else {
+				DEBUG("Media is down\n");
+				if (info->mediastate == 1) {
+					info->mediastate = 0;
+					if (info->NetDevRegDone) {
+						//netif_carrier_off(dev->net); //mbelian
+						//netif_stop_queue(dev->net);
+					}
+					info->ConTm = 0;
+				}
+			}
+			break;
+		}
+	case DSP_INIT_MSG:{
+			DEBUG
+			    ("ft1000_proc_drvmsg:Command message type = DSP_INIT_MSG");
+
+			pdspinitmsg = (struct dsp_init_msg *)&cmdbuffer[2];
+			memcpy(info->DspVer, pdspinitmsg->DspVer, DSPVERSZ);
+			DEBUG("DSPVER = 0x%2x 0x%2x 0x%2x 0x%2x\n",
+			      info->DspVer[0], info->DspVer[1], info->DspVer[2],
+			      info->DspVer[3]);
+			memcpy(info->HwSerNum, pdspinitmsg->HwSerNum,
+			       HWSERNUMSZ);
+			memcpy(info->Sku, pdspinitmsg->Sku, SKUSZ);
+			memcpy(info->eui64, pdspinitmsg->eui64, EUISZ);
+			DEBUG("EUI64=%2x.%2x.%2x.%2x.%2x.%2x.%2x.%2x\n",
+			      info->eui64[0], info->eui64[1], info->eui64[2],
+			      info->eui64[3], info->eui64[4], info->eui64[5],
+			      info->eui64[6], info->eui64[7]);
+			dev->net->dev_addr[0] = info->eui64[0];
+			dev->net->dev_addr[1] = info->eui64[1];
+			dev->net->dev_addr[2] = info->eui64[2];
+			dev->net->dev_addr[3] = info->eui64[5];
+			dev->net->dev_addr[4] = info->eui64[6];
+			dev->net->dev_addr[5] = info->eui64[7];
+
+			if (ntohs(pdspinitmsg->length) ==
+			    (sizeof(struct dsp_init_msg) - 20)) {
+				memcpy(info->ProductMode,
+				       pdspinitmsg->ProductMode, MODESZ);
+				memcpy(info->RfCalVer, pdspinitmsg->RfCalVer,
+				       CALVERSZ);
+				memcpy(info->RfCalDate, pdspinitmsg->RfCalDate,
+				       CALDATESZ);
+				DEBUG("RFCalVer = 0x%2x 0x%2x\n",
+				      info->RfCalVer[0], info->RfCalVer[1]);
+			}
+			break;
+		}
+	case DSP_PROVISION:{
+			DEBUG
+			    ("ft1000_proc_drvmsg:Command message type = DSP_PROVISION\n");
+
+			/* kick off dspprov routine to start provisioning
+			 * Send provisioning data to DSP
+			 */
+			if (list_empty(&info->prov_list) == 0) {
+				info->fProvComplete = 0;
+				status = ft1000_dsp_prov(dev);
+				if (status != STATUS_SUCCESS)
+					goto out;
+			} else {
+				info->fProvComplete = 1;
+				status =
+				    ft1000_write_register(dev, FT1000_DB_HB,
+							  FT1000_REG_DOORBELL);
+				DEBUG
+				    ("FT1000:drivermsg:No more DSP provisioning data in dsp image\n");
+			}
+			DEBUG("ft1000_proc_drvmsg:DSP PROVISION is done\n");
+			break;
+		}
+	case DSP_STORE_INFO:{
+			DEBUG
+			    ("ft1000_proc_drvmsg:Command message type = DSP_STORE_INFO");
+
+			DEBUG("FT1000:drivermsg:Got DSP_STORE_INFO\n");
+			tempword = ntohs(pdrvmsg->length);
+			info->DSPInfoBlklen = tempword;
+			if (tempword < (MAX_DSP_SESS_REC - 4)) {
+				pmsg = (u16 *) &pdrvmsg->data[0];
+				for (i = 0; i < ((tempword + 1) / 2); i++) {
+					DEBUG
+					    ("FT1000:drivermsg:dsp info data = 0x%x\n",
+					     *pmsg);
+					info->DSPInfoBlk[i + 10] = *pmsg++;
+				}
+			} else {
+				info->DSPInfoBlklen = 0;
+			}
+			break;
+		}
+	case DSP_GET_INFO:{
+			DEBUG("FT1000:drivermsg:Got DSP_GET_INFO\n");
+			/* copy dsp info block to dsp */
+			info->DrvMsgPend = 1;
+			/* allow any outstanding ioctl to finish */
+			mdelay(10);
+			status =
+			    ft1000_read_register(dev, &tempword,
+						 FT1000_REG_DOORBELL);
+			if (tempword & FT1000_DB_DPRAM_TX) {
+				mdelay(10);
+				status =
+				    ft1000_read_register(dev, &tempword,
+							 FT1000_REG_DOORBELL);
+				if (tempword & FT1000_DB_DPRAM_TX) {
+					mdelay(10);
+					status =
+					    ft1000_read_register(dev, &tempword,
+								 FT1000_REG_DOORBELL);
+					if (tempword & FT1000_DB_DPRAM_TX)
+						break;
+				}
+			}
+			/* Put message into Slow Queue
+			 * Form Pseudo header
+			 */
+			pmsg = (u16 *) info->DSPInfoBlk;
+			*pmsg++ = 0;
+			*pmsg++ =
+			    htons(info->DSPInfoBlklen + 20 +
+				  info->DSPInfoBlklen);
+			ppseudo_hdr =
+			    (struct pseudo_hdr *)(u16 *) &info->DSPInfoBlk[2];
+			ppseudo_hdr->length =
+			    htons(info->DSPInfoBlklen + 4 +
+				  info->DSPInfoBlklen);
+			ppseudo_hdr->source = 0x10;
+			ppseudo_hdr->destination = 0x20;
+			ppseudo_hdr->portdest = 0;
+			ppseudo_hdr->portsrc = 0;
+			ppseudo_hdr->sh_str_id = 0;
+			ppseudo_hdr->control = 0;
+			ppseudo_hdr->rsvd1 = 0;
+			ppseudo_hdr->rsvd2 = 0;
+			ppseudo_hdr->qos_class = 0;
+			/* Insert slow queue sequence number */
+			ppseudo_hdr->seq_num = info->squeseqnum++;
+			/* Insert application id */
+			ppseudo_hdr->portsrc = 0;
+			/* Calculate new checksum */
+			ppseudo_hdr->checksum = *pmsg++;
+			for (i = 1; i < 7; i++)
+				ppseudo_hdr->checksum ^= *pmsg++;
+
+			info->DSPInfoBlk[10] = 0x7200;
+			info->DSPInfoBlk[11] = htons(info->DSPInfoBlklen);
+			status =
+			    ft1000_write_dpram32(dev, 0,
+						 (u8 *) &info->DSPInfoBlk[0],
+						 (unsigned short)(info->
+								  DSPInfoBlklen
+								  + 22));
+			status =
+			    ft1000_write_register(dev, FT1000_DB_DPRAM_TX,
+						  FT1000_REG_DOORBELL);
+			info->DrvMsgPend = 0;
+
+			break;
+		}
 
-          case GET_DRV_ERR_RPT_MSG: {
-              DEBUG("FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
-              // copy driver error message to dsp
-              info->DrvMsgPend = 1;
-              // allow any outstanding ioctl to finish
-              mdelay(10);
-              status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
-              if (tempword & FT1000_DB_DPRAM_TX) {
-                  mdelay(10);
-                  status = ft1000_read_register(dev, &tempword, FT1000_REG_DOORBELL);
-                  if (tempword & FT1000_DB_DPRAM_TX) {
-                      mdelay(10);
-                  }
-              }
-
-              if ( (tempword & FT1000_DB_DPRAM_TX) == 0) {
-                  // Put message into Slow Queue
-                  // Form Pseudo header
-                  pmsg = (u16 *)&tempbuffer[0];
-			ppseudo_hdr = (struct pseudo_hdr *)pmsg;
-                  ppseudo_hdr->length = htons(0x0012);
-                  ppseudo_hdr->source = 0x10;
-                  ppseudo_hdr->destination = 0x20;
-                  ppseudo_hdr->portdest = 0;
-                  ppseudo_hdr->portsrc = 0;
-                  ppseudo_hdr->sh_str_id = 0;
-                  ppseudo_hdr->control = 0;
-                  ppseudo_hdr->rsvd1 = 0;
-                  ppseudo_hdr->rsvd2 = 0;
-                  ppseudo_hdr->qos_class = 0;
-                  // Insert slow queue sequence number
-                  ppseudo_hdr->seq_num = info->squeseqnum++;
-                  // Insert application id
-                  ppseudo_hdr->portsrc = 0;
-                  // Calculate new checksum
-                  ppseudo_hdr->checksum = *pmsg++;
-                  for (i=1; i<7; i++) {
-                      ppseudo_hdr->checksum ^= *pmsg++;
-                  }
-                  pmsg = (u16 *)&tempbuffer[16];
-                  *pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
-                  *pmsg++ = htons(0x000e);
-                  *pmsg++ = htons(info->DSP_TIME[0]);
-                  *pmsg++ = htons(info->DSP_TIME[1]);
-                  *pmsg++ = htons(info->DSP_TIME[2]);
-                  *pmsg++ = htons(info->DSP_TIME[3]);
-                  convert.byte[0] = info->DspVer[0];
-                  convert.byte[1] = info->DspVer[1];
-                  *pmsg++ = convert.wrd;
-                  convert.byte[0] = info->DspVer[2];
-                  convert.byte[1] = info->DspVer[3];
-                  *pmsg++ = convert.wrd;
-                  *pmsg++ = htons(info->DrvErrNum);
-
-                  CardSendCommand (dev, (unsigned char*)&tempbuffer[0], (u16)(0x0012 + PSEUDOSZ));
-                  info->DrvErrNum = 0;
-              }
-              info->DrvMsgPend = 0;
-
-          break;
-      }
-
-      default:
-          break;
-        }
+	case GET_DRV_ERR_RPT_MSG:{
+			DEBUG("FT1000:drivermsg:Got GET_DRV_ERR_RPT_MSG\n");
+			/* copy driver error message to dsp */
+			info->DrvMsgPend = 1;
+			/* allow any outstanding ioctl to finish */
+			mdelay(10);
+			status =
+			    ft1000_read_register(dev, &tempword,
+						 FT1000_REG_DOORBELL);
+			if (tempword & FT1000_DB_DPRAM_TX) {
+				mdelay(10);
+				status =
+				    ft1000_read_register(dev, &tempword,
+							 FT1000_REG_DOORBELL);
+				if (tempword & FT1000_DB_DPRAM_TX)
+					mdelay(10);
+			}
+
+			if ((tempword & FT1000_DB_DPRAM_TX) == 0) {
+				/* Put message into Slow Queue
+				 * Form Pseudo header
+				 */
+				pmsg = (u16 *) &tempbuffer[0];
+				ppseudo_hdr = (struct pseudo_hdr *)pmsg;
+				ppseudo_hdr->length = htons(0x0012);
+				ppseudo_hdr->source = 0x10;
+				ppseudo_hdr->destination = 0x20;
+				ppseudo_hdr->portdest = 0;
+				ppseudo_hdr->portsrc = 0;
+				ppseudo_hdr->sh_str_id = 0;
+				ppseudo_hdr->control = 0;
+				ppseudo_hdr->rsvd1 = 0;
+				ppseudo_hdr->rsvd2 = 0;
+				ppseudo_hdr->qos_class = 0;
+				/* Insert slow queue sequence number */
+				ppseudo_hdr->seq_num = info->squeseqnum++;
+				/* Insert application id */
+				ppseudo_hdr->portsrc = 0;
+				/* Calculate new checksum */
+				ppseudo_hdr->checksum = *pmsg++;
+				for (i = 1; i < 7; i++)
+					ppseudo_hdr->checksum ^= *pmsg++;
+
+				pmsg = (u16 *) &tempbuffer[16];
+				*pmsg++ = htons(RSP_DRV_ERR_RPT_MSG);
+				*pmsg++ = htons(0x000e);
+				*pmsg++ = htons(info->DSP_TIME[0]);
+				*pmsg++ = htons(info->DSP_TIME[1]);
+				*pmsg++ = htons(info->DSP_TIME[2]);
+				*pmsg++ = htons(info->DSP_TIME[3]);
+				convert.byte[0] = info->DspVer[0];
+				convert.byte[1] = info->DspVer[1];
+				*pmsg++ = convert.wrd;
+				convert.byte[0] = info->DspVer[2];
+				convert.byte[1] = info->DspVer[3];
+				*pmsg++ = convert.wrd;
+				*pmsg++ = htons(info->DrvErrNum);
+
+				card_send_command(dev,
+						 (unsigned char *)&tempbuffer[0],
+						 (u16) (0x0012 + PSEUDOSZ));
+				info->DrvErrNum = 0;
+			}
+			info->DrvMsgPend = 0;
+
+			break;
+		}
 
+	default:
+		break;
+	}
 
-    status = STATUS_SUCCESS;
+	status = STATUS_SUCCESS;
 out:
-    kfree(cmdbuffer);
-    DEBUG("return from ft1000_proc_drvmsg\n");
-    return status;
+	kfree(cmdbuffer);
+	DEBUG("return from ft1000_proc_drvmsg\n");
+	return status;
 }
 
-
-
 int ft1000_poll(void* dev_id) {
 
     struct ft1000_device *dev = (struct ft1000_device *)dev_id;
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h
deleted file mode 100644
index ab9312f..0000000
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.h
+++ /dev/null
@@ -1,10 +0,0 @@
-
-#ifndef _FT1000_HW_H_
-#define _FT1000_HW_H_
-
-#include "ft1000_usb.h"
-
-extern u16 ft1000_read_register(struct usb_device *dev, u16 *Data, u8 nRegIndx);
-extern u16 ft1000_write_register(struct usb_device *dev, u16 value, u8 nRegIndx);
-
-#endif
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
index b87542a..5ae3967 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_proc.c
@@ -51,7 +51,7 @@
 #define FTNET_PROC init_net.proc_net
 
 
-u16 ft1000_read_dpram16 (struct ft1000_device *ft1000dev, u16 indx,
+int ft1000_read_dpram16 (struct ft1000_device *ft1000dev, u16 indx,
 			 u8 *buffer, u8 highlow);
 
 
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
index a143e9c..e047c03 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
@@ -560,14 +560,14 @@ struct dpram_blk {
     u16 *pbuffer;
 } __attribute__ ((packed));
 
-u16 ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegIndx);
-u16 ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIndx);
-u16 ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt);
-u16 ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt);
-u16 ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u8 highlow);
-u16 ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow);
-u16 fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer);
-u16 fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer);
+int ft1000_read_register(struct ft1000_device *ft1000dev, u16* Data, u16 nRegIndx);
+int ft1000_write_register(struct ft1000_device *ft1000dev, u16 value, u16 nRegIndx);
+int ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt);
+int ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u16 cnt);
+int ft1000_read_dpram16(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer, u8 highlow);
+int ft1000_write_dpram16(struct ft1000_device *ft1000dev, u16 indx, u16 value, u8 highlow);
+int fix_ft1000_read_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer);
+int fix_ft1000_write_dpram32(struct ft1000_device *ft1000dev, u16 indx, u8 *buffer);
 
 extern void *pFileStart;
 extern size_t FileLength;
@@ -581,7 +581,7 @@ extern spinlock_t free_buff_lock;   // lock to arbitrate free buffer list for re
 
 int ft1000_create_dev(struct ft1000_device *dev);
 void ft1000_destroy_dev(struct net_device *dev);
-extern void CardSendCommand(struct ft1000_device *ft1000dev, void *ptempbuffer, int size);
+extern void card_send_command(struct ft1000_device *ft1000dev, void *ptempbuffer, int size);
 
 struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist);
 void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist);
@@ -589,7 +589,7 @@ void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist);
 char *getfw (char *fn, size_t *pimgsz);
 
 int dsp_reload(struct ft1000_device *ft1000dev);
-u16 init_ft1000_netdev(struct ft1000_device *ft1000dev);
+int init_ft1000_netdev(struct ft1000_device *ft1000dev);
 struct usb_interface;
 int reg_ft1000_netdev(struct ft1000_device *ft1000dev, struct usb_interface *intf);
 int ft1000_poll(void* dev_id);
diff --git a/drivers/staging/generic_serial/Kconfig b/drivers/staging/generic_serial/Kconfig
new file mode 100644
index 0000000..795daea
--- /dev/null
+++ b/drivers/staging/generic_serial/Kconfig
@@ -0,0 +1,45 @@
+config A2232
+	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && ZORRO && BROKEN
+	---help---
+	  This option supports the 2232 7-port serial card shipped with the
+	  Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
+	  a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
+	  each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
+	  ports were connected with 8 pin DIN connectors on the card bracket,
+	  for which 8 pin to DB25 adapters were supplied. The card also had
+	  jumpers internally to toggle various pinning configurations.
+
+	  This driver can be built as a module; but then "generic_serial"
+	  will also be built as a module. This has to be loaded before
+	  "ser_a2232". If you want to do this, answer M here.
+
+config SX
+	tristate "Specialix SX (and SI) card support"
+	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
+	help
+	  This is a driver for the SX and SI multiport serial cards.
+	  Please read the file <file:Documentation/serial/sx.txt> for details.
+
+	  This driver can only be built as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called sx. If you want to do that, say M here.
+
+config RIO
+	tristate "Specialix RIO system support"
+	depends on SERIAL_NONSTANDARD && BROKEN
+	help
+	  This is a driver for the Specialix RIO, a smart serial card which
+	  drives an outboard box that can support up to 128 ports.  Product
+	  information is at <http://www.perle.com/support/documentation.html#multiport>.
+	  There are both ISA and PCI versions.
+
+config RIO_OLDPCI
+	bool "Support really old RIO/PCI cards"
+	depends on RIO
+	help
+	  Older RIO PCI cards need some initialization-time configuration to
+	  determine the IRQ and some control addresses.  If you have a RIO and
+	  this doesn't seem to work, try setting this to Y.
+
+
diff --git a/drivers/staging/generic_serial/Makefile b/drivers/staging/generic_serial/Makefile
new file mode 100644
index 0000000..ffc90c8
--- /dev/null
+++ b/drivers/staging/generic_serial/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
+obj-$(CONFIG_MVME162_SCC)	+= generic_serial.o vme_scc.o
+obj-$(CONFIG_BVME6000_SCC)	+= generic_serial.o vme_scc.o
+obj-$(CONFIG_A2232)		+= ser_a2232.o generic_serial.o
+obj-$(CONFIG_SX)		+= sx.o generic_serial.o
+obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
diff --git a/drivers/staging/generic_serial/TODO b/drivers/staging/generic_serial/TODO
new file mode 100644
index 0000000..8875645
--- /dev/null
+++ b/drivers/staging/generic_serial/TODO
@@ -0,0 +1,6 @@
+These are a few tty/serial drivers that either do not build,
+or work if they do build, or if they seem to work, are for obsolete
+hardware, or are full of unfixable races and no one uses them anymore.
+
+If no one steps up to adopt any of these drivers, they will be removed
+in the 2.6.41 release.
diff --git a/drivers/staging/generic_serial/generic_serial.c b/drivers/staging/generic_serial/generic_serial.c
new file mode 100644
index 0000000..466988d
--- /dev/null
+++ b/drivers/staging/generic_serial/generic_serial.c
@@ -0,0 +1,844 @@
+/*
+ *  generic_serial.c
+ *
+ *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
+ *
+ *  written for the SX serial driver.
+ *     Contains the code that should be shared over all the serial drivers.
+ *
+ *  Credit for the idea to do it this way might go to Alan Cox. 
+ *
+ *
+ *  Version 0.1 -- December, 1998. Initial version.
+ *  Version 0.2 -- March, 1999.    Some more routines. Bugfixes. Etc.
+ *  Version 0.5 -- August, 1999.   Some more fixes. Reformat for Linus.
+ *
+ *  BitWizard is actively maintaining this file. We sometimes find
+ *  that someone submitted changes to this file. We really appreciate
+ *  your help, but please submit changes through us. We're doing our
+ *  best to be responsive.  -- REW
+ * */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/generic_serial.h>
+#include <linux/interrupt.h>
+#include <linux/tty_flip.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <asm/uaccess.h>
+
+#define DEBUG 
+
+static int gs_debug;
+
+#ifdef DEBUG
+#define gs_dprintk(f, str...) if (gs_debug & f) printk (str)
+#else
+#define gs_dprintk(f, str...) /* nothing */
+#endif
+
+#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__)
+#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __func__)
+
+#define RS_EVENT_WRITE_WAKEUP	1
+
+module_param(gs_debug, int, 0644);
+
+
+int gs_put_char(struct tty_struct * tty, unsigned char ch)
+{
+	struct gs_port *port;
+
+	func_enter (); 
+
+	port = tty->driver_data;
+
+	if (!port) return 0;
+
+	if (! (port->port.flags & ASYNC_INITIALIZED)) return 0;
+
+	/* Take a lock on the serial tranmit buffer! */
+	mutex_lock(& port->port_write_mutex);
+
+	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
+		mutex_unlock(&port->port_write_mutex);
+		return 0;
+	}
+
+	port->xmit_buf[port->xmit_head++] = ch;
+	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
+	port->xmit_cnt++;  /* Characters in buffer */
+
+	mutex_unlock(&port->port_write_mutex);
+	func_exit ();
+	return 1;
+}
+
+
+/*
+> Problems to take into account are:
+>       -1- Interrupts that empty part of the buffer.
+>       -2- page faults on the access to userspace. 
+>       -3- Other processes that are also trying to do a "write". 
+*/
+
+int gs_write(struct tty_struct * tty, 
+                    const unsigned char *buf, int count)
+{
+	struct gs_port *port;
+	int c, total = 0;
+	int t;
+
+	func_enter ();
+
+	port = tty->driver_data;
+
+	if (!port) return 0;
+
+	if (! (port->port.flags & ASYNC_INITIALIZED))
+		return 0;
+
+	/* get exclusive "write" access to this port (problem 3) */
+	/* This is not a spinlock because we can have a disk access (page 
+		 fault) in copy_from_user */
+	mutex_lock(& port->port_write_mutex);
+
+	while (1) {
+
+		c = count;
+ 
+		/* This is safe because we "OWN" the "head". Noone else can 
+		   change the "head": we own the port_write_mutex. */
+		/* Don't overrun the end of the buffer */
+		t = SERIAL_XMIT_SIZE - port->xmit_head;
+		if (t < c) c = t;
+ 
+		/* This is safe because the xmit_cnt can only decrease. This 
+		   would increase "t", so we might copy too little chars. */
+		/* Don't copy past the "head" of the buffer */
+		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
+		if (t < c) c = t;
+ 
+		/* Can't copy more? break out! */
+		if (c <= 0) break;
+
+		memcpy (port->xmit_buf + port->xmit_head, buf, c);
+
+		port -> xmit_cnt += c;
+		port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1);
+		buf += c;
+		count -= c;
+		total += c;
+	}
+	mutex_unlock(& port->port_write_mutex);
+
+	gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", 
+	            (port->port.flags & GS_TX_INTEN)?"enabled": "disabled");
+
+	if (port->xmit_cnt && 
+	    !tty->stopped && 
+	    !tty->hw_stopped &&
+	    !(port->port.flags & GS_TX_INTEN)) {
+		port->port.flags |= GS_TX_INTEN;
+		port->rd->enable_tx_interrupts (port);
+	}
+	func_exit ();
+	return total;
+}
+
+
+
+int gs_write_room(struct tty_struct * tty)
+{
+	struct gs_port *port = tty->driver_data;
+	int ret;
+
+	func_enter ();
+	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	func_exit ();
+	return ret;
+}
+
+
+int gs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct gs_port *port = tty->driver_data;
+	func_enter ();
+
+	func_exit ();
+	return port->xmit_cnt;
+}
+
+
+static int gs_real_chars_in_buffer(struct tty_struct *tty)
+{
+	struct gs_port *port;
+	func_enter ();
+
+	port = tty->driver_data;
+
+	if (!port->rd) return 0;
+	if (!port->rd->chars_in_buffer) return 0;
+
+	func_exit ();
+	return port->xmit_cnt + port->rd->chars_in_buffer (port);
+}
+
+
+static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) 
+{
+	struct gs_port *port = ptr;
+	unsigned long end_jiffies;
+	int jiffies_to_transmit, charsleft = 0, rv = 0;
+	int rcib;
+
+	func_enter();
+
+	gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port);
+	if (port) {
+		gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", 
+		port->xmit_cnt, port->xmit_buf, port->port.tty);
+	}
+
+	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
+		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
+		func_exit();
+		return -EINVAL;  /* This is an error which we don't know how to handle. */
+	}
+
+	rcib = gs_real_chars_in_buffer(port->port.tty);
+
+	if(rcib <= 0) {
+		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
+		func_exit();
+		return rv;
+	}
+	/* stop trying: now + twice the time it would normally take +  seconds */
+	if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT;
+	end_jiffies  = jiffies; 
+	if (timeout !=  MAX_SCHEDULE_TIMEOUT)
+		end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0;
+	end_jiffies += timeout;
+
+	gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", 
+		    jiffies, end_jiffies, end_jiffies-jiffies); 
+
+	/* the expression is actually jiffies < end_jiffies, but that won't
+	   work around the wraparound. Tricky eh? */
+	while ((charsleft = gs_real_chars_in_buffer (port->port.tty)) &&
+	        time_after (end_jiffies, jiffies)) {
+		/* Units check: 
+		   chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies!
+		   check! */
+
+		charsleft += 16; /* Allow 16 chars more to be transmitted ... */
+		jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0;
+		/*                                ^^^ Round up.... */
+		if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1;
+
+		gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies "
+			    "(%d chars).\n", jiffies_to_transmit, charsleft); 
+
+		msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit));
+		if (signal_pending (current)) {
+			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
+			rv = -EINTR;
+			break;
+		}
+	}
+
+	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
+	set_current_state (TASK_RUNNING);
+
+	func_exit();
+	return rv;
+}
+
+
+
+void gs_flush_buffer(struct tty_struct *tty)
+{
+	struct gs_port *port;
+	unsigned long flags;
+
+	func_enter ();
+
+	port = tty->driver_data;
+
+	if (!port) return;
+
+	/* XXX Would the write semaphore do? */
+	spin_lock_irqsave (&port->driver_lock, flags);
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	spin_unlock_irqrestore (&port->driver_lock, flags);
+
+	tty_wakeup(tty);
+	func_exit ();
+}
+
+
+void gs_flush_chars(struct tty_struct * tty)
+{
+	struct gs_port *port;
+
+	func_enter ();
+
+	port = tty->driver_data;
+
+	if (!port) return;
+
+	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !port->xmit_buf) {
+		func_exit ();
+		return;
+	}
+
+	/* Beats me -- REW */
+	port->port.flags |= GS_TX_INTEN;
+	port->rd->enable_tx_interrupts (port);
+	func_exit ();
+}
+
+
+void gs_stop(struct tty_struct * tty)
+{
+	struct gs_port *port;
+
+	func_enter ();
+
+	port = tty->driver_data;
+
+	if (!port) return;
+
+	if (port->xmit_cnt && 
+	    port->xmit_buf && 
+	    (port->port.flags & GS_TX_INTEN) ) {
+		port->port.flags &= ~GS_TX_INTEN;
+		port->rd->disable_tx_interrupts (port);
+	}
+	func_exit ();
+}
+
+
+void gs_start(struct tty_struct * tty)
+{
+	struct gs_port *port;
+
+	port = tty->driver_data;
+
+	if (!port) return;
+
+	if (port->xmit_cnt && 
+	    port->xmit_buf && 
+	    !(port->port.flags & GS_TX_INTEN) ) {
+		port->port.flags |= GS_TX_INTEN;
+		port->rd->enable_tx_interrupts (port);
+	}
+	func_exit ();
+}
+
+
+static void gs_shutdown_port (struct gs_port *port)
+{
+	unsigned long flags;
+
+	func_enter();
+	
+	if (!port) return;
+	
+	if (!(port->port.flags & ASYNC_INITIALIZED))
+		return;
+
+	spin_lock_irqsave(&port->driver_lock, flags);
+
+	if (port->xmit_buf) {
+		free_page((unsigned long) port->xmit_buf);
+		port->xmit_buf = NULL;
+	}
+
+	if (port->port.tty)
+		set_bit(TTY_IO_ERROR, &port->port.tty->flags);
+
+	port->rd->shutdown_port (port);
+
+	port->port.flags &= ~ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&port->driver_lock, flags);
+
+	func_exit();
+}
+
+
+void gs_hangup(struct tty_struct *tty)
+{
+	struct gs_port *port;
+	unsigned long flags;
+
+	func_enter ();
+
+	port = tty->driver_data;
+	tty = port->port.tty;
+	if (!tty) 
+		return;
+
+	gs_shutdown_port (port);
+	spin_lock_irqsave(&port->port.lock, flags);
+	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
+	port->port.tty = NULL;
+	port->port.count = 0;
+	spin_unlock_irqrestore(&port->port.lock, flags);
+
+	wake_up_interruptible(&port->port.open_wait);
+	func_exit ();
+}
+
+
+int gs_block_til_ready(void *port_, struct file * filp)
+{
+	struct gs_port *gp = port_;
+	struct tty_port *port = &gp->port;
+	DECLARE_WAITQUEUE(wait, current);
+	int    retval;
+	int    do_clocal = 0;
+	int    CD;
+	struct tty_struct *tty;
+	unsigned long flags;
+
+	func_enter ();
+
+	if (!port) return 0;
+
+	tty = port->tty;
+
+	gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+		interruptible_sleep_on(&port->close_wait);
+		if (port->flags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+	}
+
+	gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); 
+
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); 
+ 
+	if (C_CLOCAL(tty))
+		do_clocal = 1;
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, port->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+
+	add_wait_queue(&port->open_wait, &wait);
+
+	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
+	spin_lock_irqsave(&port->lock, flags);
+	if (!tty_hung_up_p(filp)) {
+		port->count--;
+	}
+	port->blocked_open++;
+	spin_unlock_irqrestore(&port->lock, flags);
+	while (1) {
+		CD = tty_port_carrier_raised(port);
+		gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
+		set_current_state (TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(port->flags & ASYNC_INITIALIZED)) {
+			if (port->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+			break;
+		}
+		if (!(port->flags & ASYNC_CLOSING) &&
+		    (do_clocal || CD))
+			break;
+		gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", 
+		(int)signal_pending (current), *(long*)(&current->blocked)); 
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		schedule();
+	}
+	gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
+		    port->blocked_open);
+	set_current_state (TASK_RUNNING);
+	remove_wait_queue(&port->open_wait, &wait);
+	
+	spin_lock_irqsave(&port->lock, flags);
+	if (!tty_hung_up_p(filp)) {
+		port->count++;
+	}
+	port->blocked_open--;
+	if (retval == 0)
+        	port->flags |= ASYNC_NORMAL_ACTIVE;
+	spin_unlock_irqrestore(&port->lock, flags);
+	func_exit ();
+	return retval;
+}			 
+
+
+void gs_close(struct tty_struct * tty, struct file * filp)
+{
+	unsigned long flags;
+	struct gs_port *port;
+	
+	func_enter ();
+
+	port = tty->driver_data;
+
+	if (!port) return;
+
+	if (!port->port.tty) {
+		/* This seems to happen when this is called from vhangup. */
+		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->port.tty is NULL\n");
+		port->port.tty = tty;
+	}
+
+	spin_lock_irqsave(&port->port.lock, flags);
+
+	if (tty_hung_up_p(filp)) {
+		spin_unlock_irqrestore(&port->port.lock, flags);
+		if (port->rd->hungup)
+			port->rd->hungup (port);
+		func_exit ();
+		return;
+	}
+
+	if ((tty->count == 1) && (port->port.count != 1)) {
+		printk(KERN_ERR "gs: gs_close port %p: bad port count;"
+		       " tty->count is 1, port count is %d\n", port, port->port.count);
+		port->port.count = 1;
+	}
+	if (--port->port.count < 0) {
+		printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->port.count);
+		port->port.count = 0;
+	}
+
+	if (port->port.count) {
+		gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
+		spin_unlock_irqrestore(&port->port.lock, flags);
+		func_exit ();
+		return;
+	}
+	port->port.flags |= ASYNC_CLOSING;
+
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	/* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+	   tty_wait_until_sent(tty, port->closing_wait); */
+
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+
+	spin_lock(&port->driver_lock);
+	port->rd->disable_rx_interrupts (port);
+	spin_unlock(&port->driver_lock);
+	spin_unlock_irqrestore(&port->port.lock, flags);
+
+	/* close has no way of returning "EINTR", so discard return value */
+	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		gs_wait_tx_flushed (port, port->closing_wait);
+
+	port->port.flags &= ~GS_ACTIVE;
+
+	gs_flush_buffer(tty);
+
+	tty_ldisc_flush(tty);
+	tty->closing = 0;
+
+	spin_lock_irqsave(&port->driver_lock, flags);
+	port->event = 0;
+	port->rd->close (port);
+	port->rd->shutdown_port (port);
+	spin_unlock_irqrestore(&port->driver_lock, flags);
+
+	spin_lock_irqsave(&port->port.lock, flags);
+	port->port.tty = NULL;
+
+	if (port->port.blocked_open) {
+		if (port->close_delay) {
+			spin_unlock_irqrestore(&port->port.lock, flags);
+			msleep_interruptible(jiffies_to_msecs(port->close_delay));
+			spin_lock_irqsave(&port->port.lock, flags);
+		}
+		wake_up_interruptible(&port->port.open_wait);
+	}
+	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
+	spin_unlock_irqrestore(&port->port.lock, flags);
+	wake_up_interruptible(&port->port.close_wait);
+
+	func_exit ();
+}
+
+
+void gs_set_termios (struct tty_struct * tty, 
+                     struct ktermios * old_termios)
+{
+	struct gs_port *port;
+	int baudrate, tmp, rv;
+	struct ktermios *tiosp;
+
+	func_enter();
+
+	port = tty->driver_data;
+
+	if (!port) return;
+	if (!port->port.tty) {
+		/* This seems to happen when this is called after gs_close. */
+		gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->port.tty is NULL\n");
+		port->port.tty = tty;
+	}
+
+
+	tiosp = tty->termios;
+
+	if (gs_debug & GS_DEBUG_TERMIOS) {
+		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
+	}
+
+	if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
+		if(tiosp->c_iflag != old_termios->c_iflag)  printk("c_iflag changed\n");
+		if(tiosp->c_oflag != old_termios->c_oflag)  printk("c_oflag changed\n");
+		if(tiosp->c_cflag != old_termios->c_cflag)  printk("c_cflag changed\n");
+		if(tiosp->c_lflag != old_termios->c_lflag)  printk("c_lflag changed\n");
+		if(tiosp->c_line  != old_termios->c_line)   printk("c_line changed\n");
+		if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
+	}
+
+	baudrate = tty_get_baud_rate(tty);
+
+	if ((tiosp->c_cflag & CBAUD) == B38400) {
+		if (     (port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			baudrate = 57600;
+		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			baudrate = 115200;
+		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			baudrate = 230400;
+		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			baudrate = 460800;
+		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
+			baudrate = (port->baud_base / port->custom_divisor);
+	}
+
+	/* I recommend using THIS instead of the mess in termios (and
+	   duplicating the above code). Next we should create a clean
+	   interface towards this variable. If your card supports arbitrary
+	   baud rates, (e.g. CD1400 or 16550 based cards) then everything
+	   will be very easy..... */
+	port->baud = baudrate;
+
+	/* Two timer ticks seems enough to wakeup something like SLIP driver */
+	/* Baudrate/10 is cps. Divide by HZ to get chars per tick. */
+	tmp = (baudrate / 10 / HZ) * 2;			 
+
+	if (tmp <                 0) tmp = 0;
+	if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1;
+
+	port->wakeup_chars = tmp;
+
+	/* We should really wait for the characters to be all sent before
+	   changing the settings. -- CAL */
+	rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
+	if (rv < 0) return /* rv */;
+
+	rv = port->rd->set_real_termios(port);
+	if (rv < 0) return /* rv */;
+
+	if ((!old_termios || 
+	     (old_termios->c_cflag & CRTSCTS)) &&
+	    !(      tiosp->c_cflag & CRTSCTS)) {
+		tty->stopped = 0;
+		gs_start(tty);
+	}
+
+#ifdef tytso_patch_94Nov25_1726
+	/* This "makes sense", Why is it commented out? */
+
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&port->gs.open_wait);
+#endif
+
+	func_exit();
+	return /* 0 */;
+}
+
+
+
+/* Must be called with interrupts enabled */
+int gs_init_port(struct gs_port *port)
+{
+	unsigned long flags;
+
+	func_enter ();
+
+	if (port->port.flags & ASYNC_INITIALIZED) {
+		func_exit ();
+		return 0;
+	}
+	if (!port->xmit_buf) {
+		/* We may sleep in get_zeroed_page() */
+		unsigned long tmp;
+
+		tmp = get_zeroed_page(GFP_KERNEL);
+		spin_lock_irqsave (&port->driver_lock, flags);
+		if (port->xmit_buf) 
+			free_page (tmp);
+		else
+			port->xmit_buf = (unsigned char *) tmp;
+		spin_unlock_irqrestore(&port->driver_lock, flags);
+		if (!port->xmit_buf) {
+			func_exit ();
+			return -ENOMEM;
+		}
+	}
+
+	spin_lock_irqsave (&port->driver_lock, flags);
+	if (port->port.tty)
+		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
+	mutex_init(&port->port_write_mutex);
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	spin_unlock_irqrestore(&port->driver_lock, flags);
+	gs_set_termios(port->port.tty, NULL);
+	spin_lock_irqsave (&port->driver_lock, flags);
+	port->port.flags |= ASYNC_INITIALIZED;
+	port->port.flags &= ~GS_TX_INTEN;
+
+	spin_unlock_irqrestore(&port->driver_lock, flags);
+	func_exit ();
+	return 0;
+}
+
+
+int gs_setserial(struct gs_port *port, struct serial_struct __user *sp)
+{
+	struct serial_struct sio;
+
+	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
+		return(-EFAULT);
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((sio.baud_base != port->baud_base) ||
+		    (sio.close_delay != port->close_delay) ||
+		    ((sio.flags & ~ASYNC_USR_MASK) !=
+		     (port->port.flags & ~ASYNC_USR_MASK)))
+			return(-EPERM);
+	} 
+
+	port->port.flags = (port->port.flags & ~ASYNC_USR_MASK) |
+		(sio.flags & ASYNC_USR_MASK);
+  
+	port->baud_base = sio.baud_base;
+	port->close_delay = sio.close_delay;
+	port->closing_wait = sio.closing_wait;
+	port->custom_divisor = sio.custom_divisor;
+
+	gs_set_termios (port->port.tty, NULL);
+
+	return 0;
+}
+
+
+/*****************************************************************************/
+
+/*
+ *      Generate the serial struct info.
+ */
+
+int gs_getserial(struct gs_port *port, struct serial_struct __user *sp)
+{
+	struct serial_struct    sio;
+
+	memset(&sio, 0, sizeof(struct serial_struct));
+	sio.flags = port->port.flags;
+	sio.baud_base = port->baud_base;
+	sio.close_delay = port->close_delay;
+	sio.closing_wait = port->closing_wait;
+	sio.custom_divisor = port->custom_divisor;
+	sio.hub6 = 0;
+
+	/* If you want you can override these. */
+	sio.type = PORT_UNKNOWN;
+	sio.xmit_fifo_size = -1;
+	sio.line = -1;
+	sio.port = -1;
+	sio.irq = -1;
+
+	if (port->rd->getserial)
+		port->rd->getserial (port, &sio);
+
+	if (copy_to_user(sp, &sio, sizeof(struct serial_struct)))
+		return -EFAULT;
+	return 0;
+
+}
+
+
+void gs_got_break(struct gs_port *port)
+{
+	func_enter ();
+
+	tty_insert_flip_char(port->port.tty, 0, TTY_BREAK);
+	tty_schedule_flip(port->port.tty);
+	if (port->port.flags & ASYNC_SAK) {
+		do_SAK (port->port.tty);
+	}
+
+	func_exit ();
+}
+
+
+EXPORT_SYMBOL(gs_put_char);
+EXPORT_SYMBOL(gs_write);
+EXPORT_SYMBOL(gs_write_room);
+EXPORT_SYMBOL(gs_chars_in_buffer);
+EXPORT_SYMBOL(gs_flush_buffer);
+EXPORT_SYMBOL(gs_flush_chars);
+EXPORT_SYMBOL(gs_stop);
+EXPORT_SYMBOL(gs_start);
+EXPORT_SYMBOL(gs_hangup);
+EXPORT_SYMBOL(gs_block_til_ready);
+EXPORT_SYMBOL(gs_close);
+EXPORT_SYMBOL(gs_set_termios);
+EXPORT_SYMBOL(gs_init_port);
+EXPORT_SYMBOL(gs_setserial);
+EXPORT_SYMBOL(gs_getserial);
+EXPORT_SYMBOL(gs_got_break);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/generic_serial/rio/Makefile b/drivers/staging/generic_serial/rio/Makefile
new file mode 100644
index 0000000..1661875
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux rio-subsystem.
+#
+# (C) R.E.Wolff@BitWizard.nl 
+# 
+# This file is GPL. See other files for the full Blurb. I'm lazy today. 
+#
+
+obj-$(CONFIG_RIO) += rio.o
+
+rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
+            rioparam.o rioroute.o riotable.o riotty.o
diff --git a/drivers/staging/generic_serial/rio/board.h b/drivers/staging/generic_serial/rio/board.h
new file mode 100644
index 0000000..bdea633
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/board.h
@@ -0,0 +1,132 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources. 
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: board.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:07
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)board.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_board_h__
+#define	__rio_board_h__
+
+/*
+** board.h contains the definitions for the *hardware* of the host cards.
+** It describes the memory overlay for the dual port RAM area.
+*/
+
+#define	DP_SRAM1_SIZE	0x7C00
+#define	DP_SRAM2_SIZE	0x0200
+#define	DP_SRAM3_SIZE	0x7000
+#define	DP_SCRATCH_SIZE	0x1000
+#define	DP_PARMMAP_ADDR	0x01FE	/* offset into SRAM2 */
+#define	DP_STARTUP_ADDR	0x01F8	/* offset into SRAM2 */
+
+/*
+**	The shape of the Host Control area, at offset 0x7C00, Write Only
+*/
+struct s_Ctrl {
+	u8 DpCtl;		/* 7C00 */
+	u8 Dp_Unused2_[127];
+	u8 DpIntSet;		/* 7C80 */
+	u8 Dp_Unused3_[127];
+	u8 DpTpuReset;	/* 7D00 */
+	u8 Dp_Unused4_[127];
+	u8 DpIntReset;	/* 7D80 */
+	u8 Dp_Unused5_[127];
+};
+
+/*
+** The PROM data area on the host (0x7C00), Read Only
+*/
+struct s_Prom {
+	u16 DpSlxCode[2];
+	u16 DpRev;
+	u16 Dp_Unused6_;
+	u16 DpUniq[4];
+	u16 DpJahre;
+	u16 DpWoche;
+	u16 DpHwFeature[5];
+	u16 DpOemId;
+	u16 DpSiggy[16];
+};
+
+/*
+** Union of the Ctrl and Prom areas
+*/
+union u_CtrlProm {		/* This is the control/PROM area (0x7C00) */
+	struct s_Ctrl DpCtrl;
+	struct s_Prom DpProm;
+};
+
+/*
+** The top end of memory!
+*/
+struct s_ParmMapS {		/* Area containing Parm Map Pointer */
+	u8 Dp_Unused8_[DP_PARMMAP_ADDR];
+	u16 DpParmMapAd;
+};
+
+struct s_StartUpS {
+	u8 Dp_Unused9_[DP_STARTUP_ADDR];
+	u8 Dp_LongJump[0x4];
+	u8 Dp_Unused10_[2];
+	u8 Dp_ShortJump[0x2];
+};
+
+union u_Sram2ParmMap {		/* This is the top of memory (0x7E00-0x7FFF) */
+	u8 DpSramMem[DP_SRAM2_SIZE];
+	struct s_ParmMapS DpParmMapS;
+	struct s_StartUpS DpStartUpS;
+};
+
+/*
+**	This is the DP RAM overlay.
+*/
+struct DpRam {
+	u8 DpSram1[DP_SRAM1_SIZE];	/* 0000 - 7BFF */
+	union u_CtrlProm DpCtrlProm;	/* 7C00 - 7DFF */
+	union u_Sram2ParmMap DpSram2ParmMap;	/* 7E00 - 7FFF */
+	u8 DpScratch[DP_SCRATCH_SIZE];	/* 8000 - 8FFF */
+	u8 DpSram3[DP_SRAM3_SIZE];	/* 9000 - FFFF */
+};
+
+#define	DpControl	DpCtrlProm.DpCtrl.DpCtl
+#define	DpSetInt	DpCtrlProm.DpCtrl.DpIntSet
+#define	DpResetTpu	DpCtrlProm.DpCtrl.DpTpuReset
+#define	DpResetInt	DpCtrlProm.DpCtrl.DpIntReset
+
+#define	DpSlx		DpCtrlProm.DpProm.DpSlxCode
+#define	DpRevision	DpCtrlProm.DpProm.DpRev
+#define	DpUnique	DpCtrlProm.DpProm.DpUniq
+#define	DpYear		DpCtrlProm.DpProm.DpJahre
+#define	DpWeek		DpCtrlProm.DpProm.DpWoche
+#define	DpSignature	DpCtrlProm.DpProm.DpSiggy
+
+#define	DpParmMapR	DpSram2ParmMap.DpParmMapS.DpParmMapAd
+#define	DpSram2		DpSram2ParmMap.DpSramMem
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/cirrus.h b/drivers/staging/generic_serial/rio/cirrus.h
new file mode 100644
index 0000000..5ab5167
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/cirrus.h
@@ -0,0 +1,210 @@
+/****************************************************************************
+ *******                                                              *******
+ *******		CIRRUS.H				      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Jeremy Rolls
+ Date    : 3 Aug 1990
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _cirrus_h
+#define _cirrus_h 1
+
+/* Bit fields for particular registers shared with driver */
+
+/* COR1 - driver and RTA */
+#define RIOC_COR1_ODD		0x80	/* Odd parity */
+#define RIOC_COR1_EVEN		0x00	/* Even parity */
+#define RIOC_COR1_NOP		0x00	/* No parity */
+#define RIOC_COR1_FORCE		0x20	/* Force parity */
+#define RIOC_COR1_NORMAL	0x40	/* With parity */
+#define RIOC_COR1_1STOP		0x00	/* 1 stop bit */
+#define RIOC_COR1_15STOP	0x04	/* 1.5 stop bits */
+#define RIOC_COR1_2STOP		0x08	/* 2 stop bits */
+#define RIOC_COR1_5BITS		0x00	/* 5 data bits */
+#define RIOC_COR1_6BITS		0x01	/* 6 data bits */
+#define RIOC_COR1_7BITS		0x02	/* 7 data bits */
+#define RIOC_COR1_8BITS		0x03	/* 8 data bits */
+
+#define RIOC_COR1_HOST		0xef	/* Safe host bits */
+
+/* RTA only */
+#define RIOC_COR1_CINPCK	0x00	/* Check parity of received characters */
+#define RIOC_COR1_CNINPCK	0x10	/* Don't check parity */
+
+/* COR2 bits for both RTA and driver use */
+#define RIOC_COR2_IXANY		0x80	/* IXANY - any character is XON */
+#define RIOC_COR2_IXON		0x40	/* IXON - enable tx soft flowcontrol */
+#define RIOC_COR2_RTSFLOW	0x02	/* Enable tx hardware flow control */
+
+/* Additional driver bits */
+#define RIOC_COR2_HUPCL		0x20	/* Hang up on close */
+#define RIOC_COR2_CTSFLOW	0x04	/* Enable rx hardware flow control */
+#define RIOC_COR2_IXOFF		0x01	/* Enable rx software flow control */
+#define RIOC_COR2_DTRFLOW	0x08	/* Enable tx hardware flow control */
+
+/* RTA use only */
+#define RIOC_COR2_ETC		0x20	/* Embedded transmit options */
+#define RIOC_COR2_LOCAL		0x10	/* Local loopback mode */
+#define RIOC_COR2_REMOTE	0x08	/* Remote loopback mode */
+#define RIOC_COR2_HOST		0xc2	/* Safe host bits */
+
+/* COR3 - RTA use only */
+#define RIOC_COR3_SCDRNG	0x80	/* Enable special char detect for range */
+#define RIOC_COR3_SCD34		0x40	/* Special character detect for SCHR's 3 + 4 */
+#define RIOC_COR3_FCT		0x20	/* Flow control transparency */
+#define RIOC_COR3_SCD12		0x10	/* Special character detect for SCHR's 1 + 2 */
+#define RIOC_COR3_FIFO12	0x0c	/* 12 chars for receive FIFO threshold */
+#define RIOC_COR3_FIFO10	0x0a	/* 10 chars for receive FIFO threshold */
+#define RIOC_COR3_FIFO8		0x08	/* 8 chars for receive FIFO threshold */
+#define RIOC_COR3_FIFO6		0x06	/* 6 chars for receive FIFO threshold */
+
+#define RIOC_COR3_THRESHOLD	RIOC_COR3_FIFO8	/* MUST BE LESS THAN MCOR_THRESHOLD */
+
+#define RIOC_COR3_DEFAULT	(RIOC_COR3_FCT | RIOC_COR3_THRESHOLD)
+				/* Default bits for COR3 */
+
+/* COR4 driver and RTA use */
+#define RIOC_COR4_IGNCR		0x80	/* Throw away CR's on input */
+#define RIOC_COR4_ICRNL		0x40	/* Map CR -> NL on input */
+#define RIOC_COR4_INLCR		0x20	/* Map NL -> CR on input */
+#define RIOC_COR4_IGNBRK	0x10	/* Ignore Break */
+#define RIOC_COR4_NBRKINT	0x08	/* No interrupt on break (-BRKINT) */
+#define RIOC_COR4_RAISEMOD	0x01	/* Raise modem output lines on non-zero baud */
+
+
+/* COR4 driver only */
+#define RIOC_COR4_IGNPAR	0x04	/* IGNPAR (ignore characters with errors) */
+#define RIOC_COR4_PARMRK	0x02	/* PARMRK */
+
+#define RIOC_COR4_HOST		0xf8	/* Safe host bits */
+
+/* COR4 RTA only */
+#define RIOC_COR4_CIGNPAR	0x02	/* Thrown away bad characters */
+#define RIOC_COR4_CPARMRK	0x04	/* PARMRK characters */
+#define RIOC_COR4_CNPARMRK	0x03	/* Don't PARMRK */
+
+/* COR5 driver and RTA use */
+#define RIOC_COR5_ISTRIP	0x80	/* Strip input chars to 7 bits */
+#define RIOC_COR5_LNE		0x40	/* Enable LNEXT processing */
+#define RIOC_COR5_CMOE		0x20	/* Match good and errored characters */
+#define RIOC_COR5_ONLCR		0x02	/* NL -> CR NL on output */
+#define RIOC_COR5_OCRNL		0x01	/* CR -> NL on output */
+
+/*
+** Spare bits - these are not used in the CIRRUS registers, so we use
+** them to set various other features.
+*/
+/*
+** tstop and tbusy indication
+*/
+#define RIOC_COR5_TSTATE_ON	0x08	/* Turn on monitoring of tbusy and tstop */
+#define RIOC_COR5_TSTATE_OFF	0x04	/* Turn off monitoring of tbusy and tstop */
+/*
+** TAB3
+*/
+#define RIOC_COR5_TAB3		0x10	/* TAB3 mode */
+
+#define RIOC_COR5_HOST		0xc3	/* Safe host bits */
+
+/* CCSR */
+#define RIOC_CCSR_TXFLOFF	0x04	/* Tx is xoffed */
+
+/* MSVR1 */
+/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
+   RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
+   serial option.
+*/
+#define RIOC_MSVR1_CD		0x80	/* CD (DSR on Cirrus) */
+#define RIOC_MSVR1_RTS		0x40	/* RTS (CTS on Cirrus) */
+#define RIOC_MSVR1_RI		0x20	/* RI */
+#define RIOC_MSVR1_DTR		0x10	/* DTR (CD on Cirrus) */
+#define RIOC_MSVR1_CTS		0x01	/* CTS output pin (RTS on Cirrus) */
+/* Next two used to indicate state of tbusy and tstop to driver */
+#define RIOC_MSVR1_TSTOP	0x08	/* Set if port flow controlled */
+#define RIOC_MSVR1_TEMPTY	0x04	/* Set if port tx buffer empty */
+
+#define RIOC_MSVR1_HOST		0xf3	/* The bits the host wants */
+
+/* Defines for the subscripts of a CONFIG packet */
+#define RIOC_CONFIG_COR1	1	/* Option register 1 */
+#define RIOC_CONFIG_COR2	2	/* Option register 2 */
+#define RIOC_CONFIG_COR4	3	/* Option register 4 */
+#define RIOC_CONFIG_COR5	4	/* Option register 5 */
+#define RIOC_CONFIG_TXXON	5	/* Tx XON character */
+#define RIOC_CONFIG_TXXOFF	6	/* Tx XOFF character */
+#define RIOC_CONFIG_RXXON	7	/* Rx XON character */
+#define RIOC_CONFIG_RXXOFF	8	/* Rx XOFF character */
+#define RIOC_CONFIG_LNEXT	9	/* LNEXT character */
+#define RIOC_CONFIG_TXBAUD	10	/* Tx baud rate */
+#define RIOC_CONFIG_RXBAUD	11	/* Rx baud rate */
+
+#define RIOC_PRE_EMPTIVE	0x80	/* Pre-emptive bit in command field */
+
+/* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
+   CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
+   be used 
+*/
+#define RIOC_OPEN		0x00	/* Open a port */
+#define RIOC_CONFIG		0x01	/* Configure a port */
+#define RIOC_MOPEN		0x02	/* Modem open (block for DCD) */
+#define RIOC_CLOSE		0x03	/* Close a port */
+#define RIOC_WFLUSH		(0x04 | RIOC_PRE_EMPTIVE)	/* Write flush */
+#define RIOC_RFLUSH		(0x05 | RIOC_PRE_EMPTIVE)	/* Read flush */
+#define RIOC_RESUME		(0x06 | RIOC_PRE_EMPTIVE)	/* Resume if xoffed */
+#define RIOC_SBREAK		0x07	/* Start break */
+#define RIOC_EBREAK		0x08	/* End break */
+#define RIOC_SUSPEND		(0x09 | RIOC_PRE_EMPTIVE)	/* Susp op (behave as tho xoffed) */
+#define RIOC_FCLOSE		(0x0a | RIOC_PRE_EMPTIVE)	/* Force close */
+#define RIOC_XPRINT		0x0b	/* Xprint packet */
+#define RIOC_MBIS		(0x0c | RIOC_PRE_EMPTIVE)	/* Set modem lines */
+#define RIOC_MBIC		(0x0d | RIOC_PRE_EMPTIVE)	/* Clear modem lines */
+#define RIOC_MSET		(0x0e | RIOC_PRE_EMPTIVE)	/* Set modem lines */
+#define RIOC_PCLOSE		0x0f	/* Pseudo close - Leaves rx/tx enabled */
+#define RIOC_MGET		(0x10 | RIOC_PRE_EMPTIVE)	/* Force update of modem status */
+#define RIOC_MEMDUMP		(0x11 | RIOC_PRE_EMPTIVE)	/* Send back mem from addr supplied */
+#define RIOC_READ_REGISTER	(0x12 | RIOC_PRE_EMPTIVE)	/* Read CD1400 register (debug) */
+
+/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
+   use data[4] / data[3] to indicate current state and modem status respectively
+*/
+
+#define RIOC_COMPLETE		(0x20 | RIOC_PRE_EMPTIVE)
+				/* Command complete */
+#define RIOC_BREAK_RECEIVED	(0x21 | RIOC_PRE_EMPTIVE)
+				/* Break received */
+#define RIOC_MODEM_STATUS	(0x22 | RIOC_PRE_EMPTIVE)
+				/* Change in modem status */
+
+/* "Command" packet that could go either way - handshake wake-up */
+#define RIOC_HANDSHAKE		(0x23 | RIOC_PRE_EMPTIVE)
+				/* Wake-up to HOST / RTA */
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/cmdblk.h b/drivers/staging/generic_serial/rio/cmdblk.h
new file mode 100644
index 0000000..9ed4f86
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/cmdblk.h
@@ -0,0 +1,53 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: cmdblk.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)cmdblk.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_cmdblk_h__
+#define __rio_cmdblk_h__
+
+/*
+** the structure of a command block, used to queue commands destined for
+** a rup.
+*/
+
+struct CmdBlk {
+	struct CmdBlk *NextP;	/* Pointer to next command block */
+	struct PKT Packet;	/* A packet, to copy to the rup */
+	/* The func to call to check if OK */
+	int (*PreFuncP) (unsigned long, struct CmdBlk *);
+	int PreArg;		/* The arg for the func */
+	/* The func to call when completed */
+	int (*PostFuncP) (unsigned long, struct CmdBlk *);
+	int PostArg;		/* The arg for the func */
+};
+
+#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
+#endif
diff --git a/drivers/staging/generic_serial/rio/cmdpkt.h b/drivers/staging/generic_serial/rio/cmdpkt.h
new file mode 100644
index 0000000..c1e7a27
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/cmdpkt.h
@@ -0,0 +1,177 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: cmdpkt.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:20
+**
+**  ident @(#)cmdpkt.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+#ifndef __rio_cmdpkt_h__
+#define __rio_cmdpkt_h__
+
+/*
+** overlays for the data area of a packet. Used in both directions
+** (to build a packet to send, and to interpret a packet that arrives)
+** and is very inconvenient for MIPS, so they appear as two separate
+** structures - those used for modifying/reading packets on the card
+** and those for modifying/reading packets in real memory, which have an _M
+** suffix.
+*/
+
+#define	RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2)
+
+/*
+** The boot information packet looks like this:
+** This structure overlays a PktCmd->CmdData structure, and so starts
+** at Data[2] in the actual pkt!
+*/
+struct BootSequence {
+	u16 NumPackets;
+	u16 LoadBase;
+	u16 CodeSize;
+};
+
+#define	BOOT_SEQUENCE_LEN	8
+
+struct SamTop {
+	u8 Unit;
+	u8 Link;
+};
+
+struct CmdHdr {
+	u8 PcCommand;
+	union {
+		u8 PcPhbNum;
+		u8 PcLinkNum;
+		u8 PcIDNum;
+	} U0;
+};
+
+
+struct PktCmd {
+	union {
+		struct {
+			struct CmdHdr CmdHdr;
+			struct BootSequence PcBootSequence;
+		} S1;
+		struct {
+			u16 PcSequence;
+			u8 PcBootData[RTA_BOOT_DATA_SIZE];
+		} S2;
+		struct {
+			u16 __crud__;
+			u8 PcUniqNum[4];	/* this is really a uint. */
+			u8 PcModuleTypes;	/* what modules are fitted */
+		} S3;
+		struct {
+			struct CmdHdr CmdHdr;
+			u8 __undefined__;
+			u8 PcModemStatus;
+			u8 PcPortStatus;
+			u8 PcSubCommand;	/* commands like mem or register dump */
+			u16 PcSubAddr;	/* Address for command */
+			u8 PcSubData[64];	/* Date area for command */
+		} S4;
+		struct {
+			struct CmdHdr CmdHdr;
+			u8 PcCommandText[1];
+			u8 __crud__[20];
+			u8 PcIDNum2;	/* It had to go somewhere! */
+		} S5;
+		struct {
+			struct CmdHdr CmdHdr;
+			struct SamTop Topology[LINKS_PER_UNIT];
+		} S6;
+	} U1;
+};
+
+struct PktCmd_M {
+	union {
+		struct {
+			struct {
+				u8 PcCommand;
+				union {
+					u8 PcPhbNum;
+					u8 PcLinkNum;
+					u8 PcIDNum;
+				} U0;
+			} CmdHdr;
+			struct {
+				u16 NumPackets;
+				u16 LoadBase;
+				u16 CodeSize;
+			} PcBootSequence;
+		} S1;
+		struct {
+			u16 PcSequence;
+			u8 PcBootData[RTA_BOOT_DATA_SIZE];
+		} S2;
+		struct {
+			u16 __crud__;
+			u8 PcUniqNum[4];	/* this is really a uint. */
+			u8 PcModuleTypes;	/* what modules are fitted */
+		} S3;
+		struct {
+			u16 __cmd_hdr__;
+			u8 __undefined__;
+			u8 PcModemStatus;
+			u8 PcPortStatus;
+			u8 PcSubCommand;
+			u16 PcSubAddr;
+			u8 PcSubData[64];
+		} S4;
+		struct {
+			u16 __cmd_hdr__;
+			u8 PcCommandText[1];
+			u8 __crud__[20];
+			u8 PcIDNum2;	/* Tacked on end */
+		} S5;
+		struct {
+			u16 __cmd_hdr__;
+			struct Top Topology[LINKS_PER_UNIT];
+		} S6;
+	} U1;
+};
+
+#define Command		U1.S1.CmdHdr.PcCommand
+#define PhbNum		U1.S1.CmdHdr.U0.PcPhbNum
+#define IDNum		U1.S1.CmdHdr.U0.PcIDNum
+#define IDNum2		U1.S5.PcIDNum2
+#define LinkNum		U1.S1.CmdHdr.U0.PcLinkNum
+#define Sequence	U1.S2.PcSequence
+#define BootData	U1.S2.PcBootData
+#define BootSequence	U1.S1.PcBootSequence
+#define UniqNum		U1.S3.PcUniqNum
+#define ModemStatus	U1.S4.PcModemStatus
+#define PortStatus	U1.S4.PcPortStatus
+#define SubCommand	U1.S4.PcSubCommand
+#define SubAddr		U1.S4.PcSubAddr
+#define SubData		U1.S4.PcSubData
+#define CommandText	U1.S5.PcCommandText
+#define RouteTopology	U1.S6.Topology
+#define ModuleTypes	U1.S3.PcModuleTypes
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/daemon.h b/drivers/staging/generic_serial/rio/daemon.h
new file mode 100644
index 0000000..4af9032
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/daemon.h
@@ -0,0 +1,307 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: daemon.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:09
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)daemon.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_daemon_h__
+#define	__rio_daemon_h__
+
+
+/*
+** structures used on /dev/rio
+*/
+
+struct Error {
+	unsigned int Error;
+	unsigned int Entry;
+	unsigned int Other;
+};
+
+struct DownLoad {
+	char __user *DataP;
+	unsigned int Count;
+	unsigned int ProductCode;
+};
+
+/*
+** A few constants....
+*/
+#ifndef MAX_VERSION_LEN
+#define	MAX_VERSION_LEN	256
+#endif
+
+#ifndef MAX_XP_CTRL_LEN
+#define	MAX_XP_CTRL_LEN 16	/* ALSO IN PORT.H */
+#endif
+
+struct PortSetup {
+	unsigned int From;		/* Set/Clear XP & IXANY Control from this port.... */
+	unsigned int To;		/* .... to this port */
+	unsigned int XpCps;		/* at this speed */
+	char XpOn[MAX_XP_CTRL_LEN];	/* this is the start string */
+	char XpOff[MAX_XP_CTRL_LEN];	/* this is the stop string */
+	u8 IxAny;			/* enable/disable IXANY */
+	u8 IxOn;			/* enable/disable IXON */
+	u8 Lock;			/* lock port params */
+	u8 Store;			/* store params across closes */
+	u8 Drain;			/* close only when drained */
+};
+
+struct LpbReq {
+	unsigned int Host;
+	unsigned int Link;
+	struct LPB __user *LpbP;
+};
+
+struct RupReq {
+	unsigned int HostNum;
+	unsigned int RupNum;
+	struct RUP __user *RupP;
+};
+
+struct PortReq {
+	unsigned int SysPort;
+	struct Port __user *PortP;
+};
+
+struct StreamInfo {
+	unsigned int SysPort;
+	int RQueue;
+	int WQueue;
+};
+
+struct HostReq {
+	unsigned int HostNum;
+	struct Host __user *HostP;
+};
+
+struct HostDpRam {
+	unsigned int HostNum;
+	struct DpRam __user *DpRamP;
+};
+
+struct DebugCtrl {
+	unsigned int SysPort;
+	unsigned int Debug;
+	unsigned int Wait;
+};
+
+struct MapInfo {
+	unsigned int FirstPort;		/* 8 ports, starting from this (tty) number */
+	unsigned int RtaUnique;		/* reside on this RTA (unique number) */
+};
+
+struct MapIn {
+	unsigned int NumEntries;	/* How many port sets are we mapping? */
+	struct MapInfo *MapInfoP;	/* Pointer to (user space) info */
+};
+
+struct SendPack {
+	unsigned int PortNum;
+	unsigned char Len;
+	unsigned char Data[PKT_MAX_DATA_LEN];
+};
+
+struct SpecialRupCmd {
+	struct PKT Packet;
+	unsigned short Host;
+	unsigned short RupNum;
+};
+
+struct IdentifyRta {
+	unsigned long RtaUnique;
+	u8 ID;
+};
+
+struct KillNeighbour {
+	unsigned long UniqueNum;
+	u8 Link;
+};
+
+struct rioVersion {
+	char version[MAX_VERSION_LEN];
+	char relid[MAX_VERSION_LEN];
+	int buildLevel;
+	char buildDate[MAX_VERSION_LEN];
+};
+
+
+/*
+**	RIOC commands are for the daemon type operations
+**
+** 09.12.1998 ARG - ESIL 0776 part fix
+** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a
+** #ifndef here first.
+** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now
+** allowed to be used by customers.
+*/
+#ifndef RIOC
+#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
+#endif
+
+/*
+** Boot stuff
+*/
+#define	RIO_GET_TABLE     (RIOC | 100)
+#define RIO_PUT_TABLE     (RIOC | 101)
+#define RIO_ASSIGN_RTA    (RIOC | 102)
+#define RIO_DELETE_RTA    (RIOC | 103)
+#define	RIO_HOST_FOAD	  (RIOC | 104)
+#define	RIO_QUICK_CHECK	  (RIOC | 105)
+#define RIO_SIGNALS_ON    (RIOC | 106)
+#define RIO_SIGNALS_OFF   (RIOC | 107)
+#define	RIO_CHANGE_NAME   (RIOC | 108)
+#define RIO_DOWNLOAD      (RIOC | 109)
+#define	RIO_GET_LOG	  (RIOC | 110)
+#define	RIO_SETUP_PORTS   (RIOC | 111)
+#define RIO_ALL_MODEM     (RIOC | 112)
+
+/*
+** card state, debug stuff
+*/
+#define	RIO_NUM_HOSTS	  (RIOC | 120)
+#define	RIO_HOST_LPB	  (RIOC | 121)
+#define	RIO_HOST_RUP	  (RIOC | 122)
+#define	RIO_HOST_PORT	  (RIOC | 123)
+#define	RIO_PARMS 	  (RIOC | 124)
+#define RIO_HOST_REQ	  (RIOC | 125)
+#define	RIO_READ_CONFIG	  (RIOC | 126)
+#define	RIO_SET_CONFIG	  (RIOC | 127)
+#define	RIO_VERSID	  (RIOC | 128)
+#define	RIO_FLAGS	  (RIOC | 129)
+#define	RIO_SETDEBUG	  (RIOC | 130)
+#define	RIO_GETDEBUG	  (RIOC | 131)
+#define	RIO_READ_LEVELS   (RIOC | 132)
+#define	RIO_SET_FAST_BUS  (RIOC | 133)
+#define	RIO_SET_SLOW_BUS  (RIOC | 134)
+#define	RIO_SET_BYTE_MODE (RIOC | 135)
+#define	RIO_SET_WORD_MODE (RIOC | 136)
+#define RIO_STREAM_INFO   (RIOC | 137)
+#define	RIO_START_POLLER  (RIOC | 138)
+#define	RIO_STOP_POLLER   (RIOC | 139)
+#define	RIO_LAST_ERROR    (RIOC | 140)
+#define	RIO_TICK	  (RIOC | 141)
+#define	RIO_TOCK	  (RIOC | 241)	/* I did this on purpose, you know. */
+#define	RIO_SEND_PACKET   (RIOC | 142)
+#define	RIO_SET_BUSY	  (RIOC | 143)
+#define	SPECIAL_RUP_CMD   (RIOC | 144)
+#define	RIO_FOAD_RTA      (RIOC | 145)
+#define	RIO_ZOMBIE_RTA    (RIOC | 146)
+#define RIO_IDENTIFY_RTA  (RIOC | 147)
+#define RIO_KILL_NEIGHBOUR (RIOC | 148)
+#define RIO_DEBUG_MEM     (RIOC | 149)
+/*
+** 150 - 167 used.....   See below
+*/
+#define RIO_GET_PORT_SETUP (RIOC | 168)
+#define RIO_RESUME        (RIOC | 169)
+#define	RIO_MESG	(RIOC | 170)
+#define	RIO_NO_MESG	(RIOC | 171)
+#define	RIO_WHAT_MESG	(RIOC | 172)
+#define RIO_HOST_DPRAM	(RIOC | 173)
+#define RIO_MAP_B50_TO_50	(RIOC | 174)
+#define RIO_MAP_B50_TO_57600	(RIOC | 175)
+#define RIO_MAP_B110_TO_110	(RIOC | 176)
+#define RIO_MAP_B110_TO_115200	(RIOC | 177)
+#define RIO_GET_PORT_PARAMS	(RIOC | 178)
+#define RIO_SET_PORT_PARAMS	(RIOC | 179)
+#define RIO_GET_PORT_TTY	(RIOC | 180)
+#define RIO_SET_PORT_TTY	(RIOC | 181)
+#define RIO_SYSLOG_ONLY	(RIOC | 182)
+#define RIO_SYSLOG_CONS	(RIOC | 183)
+#define RIO_CONS_ONLY	(RIOC | 184)
+#define RIO_BLOCK_OPENS	(RIOC | 185)
+
+/*
+** 02.03.1999 ARG - ESIL 0820 fix :
+** RIOBootMode is no longer use by the driver, so these ioctls
+** are now obsolete :
+**
+#define RIO_GET_BOOT_MODE	(RIOC | 186)
+#define RIO_SET_BOOT_MODE	(RIOC | 187)
+**
+*/
+
+#define RIO_MEM_DUMP	(RIOC | 189)
+#define RIO_READ_REGISTER	(RIOC | 190)
+#define RIO_GET_MODTYPE	(RIOC | 191)
+#define RIO_SET_TIMER	(RIOC | 192)
+#define RIO_READ_CHECK	(RIOC | 196)
+#define RIO_WAITING_FOR_RESTART	(RIOC | 197)
+#define RIO_BIND_RTA	(RIOC | 198)
+#define RIO_GET_BINDINGS	(RIOC | 199)
+#define RIO_PUT_BINDINGS	(RIOC | 200)
+
+#define	RIO_MAKE_DEV		(RIOC | 201)
+#define	RIO_MINOR		(RIOC | 202)
+
+#define	RIO_IDENTIFY_DRIVER	(RIOC | 203)
+#define	RIO_DISPLAY_HOST_CFG	(RIOC | 204)
+
+
+/*
+** MAKE_DEV / MINOR stuff
+*/
+#define	RIO_DEV_DIRECT		0x0000
+#define	RIO_DEV_MODEM		0x0200
+#define	RIO_DEV_XPRINT		0x0400
+#define	RIO_DEV_MASK		0x0600
+
+/*
+** port management, xprint stuff
+*/
+#define	rIOCN(N)	(RIOC|(N))
+#define	rIOCR(N,T)	(RIOC|(N))
+#define	rIOCW(N,T)	(RIOC|(N))
+
+#define	RIO_GET_XP_ON     rIOCR(150,char[16])	/* start xprint string */
+#define	RIO_SET_XP_ON     rIOCW(151,char[16])
+#define	RIO_GET_XP_OFF    rIOCR(152,char[16])	/* finish xprint string */
+#define	RIO_SET_XP_OFF    rIOCW(153,char[16])
+#define	RIO_GET_XP_CPS    rIOCR(154,int)	/* xprint CPS */
+#define	RIO_SET_XP_CPS    rIOCW(155,int)
+#define RIO_GET_IXANY     rIOCR(156,int)	/* ixany allowed? */
+#define RIO_SET_IXANY     rIOCW(157,int)
+#define RIO_SET_IXANY_ON  rIOCN(158)	/* allow ixany */
+#define RIO_SET_IXANY_OFF rIOCN(159)	/* disallow ixany */
+#define RIO_GET_MODEM     rIOCR(160,int)	/* port is modem/direct line? */
+#define RIO_SET_MODEM     rIOCW(161,int)
+#define RIO_SET_MODEM_ON  rIOCN(162)	/* port is a modem */
+#define RIO_SET_MODEM_OFF rIOCN(163)	/* port is direct */
+#define RIO_GET_IXON      rIOCR(164,int)	/* ixon allowed? */
+#define RIO_SET_IXON      rIOCW(165,int)
+#define RIO_SET_IXON_ON   rIOCN(166)	/* allow ixon */
+#define RIO_SET_IXON_OFF  rIOCN(167)	/* disallow ixon */
+
+#define RIO_GET_SIVIEW	  ((('s')<<8) | 106)	/* backwards compatible with SI */
+
+#define	RIO_IOCTL_UNKNOWN	-2
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/errors.h b/drivers/staging/generic_serial/rio/errors.h
new file mode 100644
index 0000000..bdb0523
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/errors.h
@@ -0,0 +1,98 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: errors.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)errors.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_errors_h__
+#define	__rio_errors_h__
+
+/*
+** error codes
+*/
+
+#define	NOTHING_WRONG_AT_ALL		0
+#define	BAD_CHARACTER_IN_NAME		1
+#define	TABLE_ENTRY_ISNT_PROPERLY_NULL	2
+#define	UNKNOWN_HOST_NUMBER		3
+#define	ZERO_RTA_ID			4
+#define	BAD_RTA_ID			5
+#define	DUPLICATED_RTA_ID		6
+#define	DUPLICATE_UNIQUE_NUMBER		7
+#define	BAD_TTY_NUMBER			8
+#define	TTY_NUMBER_IN_USE		9
+#define	NAME_USED_TWICE			10
+#define	HOST_ID_NOT_ZERO		11
+#define	BOOT_IN_PROGRESS		12
+#define	COPYIN_FAILED			13
+#define	HOST_FILE_TOO_LARGE		14
+#define	COPYOUT_FAILED			15
+#define	NOT_SUPER_USER			16
+#define	RIO_ALREADY_POLLING		17
+
+#define	ID_NUMBER_OUT_OF_RANGE		18
+#define PORT_NUMBER_OUT_OF_RANGE	19
+#define	HOST_NUMBER_OUT_OF_RANGE	20
+#define	RUP_NUMBER_OUT_OF_RANGE		21
+#define	TTY_NUMBER_OUT_OF_RANGE		22
+#define	LINK_NUMBER_OUT_OF_RANGE	23
+
+#define	HOST_NOT_RUNNING		24
+#define	IOCTL_COMMAND_UNKNOWN		25
+#define	RIO_SYSTEM_HALTED		26
+#define	WAIT_FOR_DRAIN_BROKEN		27
+#define	PORT_NOT_MAPPED_INTO_SYSTEM	28
+#define	EXCLUSIVE_USE_SET		29
+#define	WAIT_FOR_NOT_CLOSING_BROKEN	30
+#define	WAIT_FOR_PORT_TO_OPEN_BROKEN	31
+#define	WAIT_FOR_CARRIER_BROKEN		32
+#define	WAIT_FOR_NOT_IN_USE_BROKEN	33
+#define	WAIT_FOR_CAN_ADD_COMMAND_BROKEN	34
+#define	WAIT_FOR_ADD_COMMAND_BROKEN	35
+#define	WAIT_FOR_NOT_PARAM_BROKEN	36
+#define	WAIT_FOR_RETRY_BROKEN		37
+#define	HOST_HAS_ALREADY_BEEN_BOOTED	38
+#define	UNIT_IS_IN_USE			39
+#define	COULDNT_FIND_ENTRY		40
+#define	RTA_UNIQUE_NUMBER_ZERO		41
+#define	CLOSE_COMMAND_FAILED		42
+#define	WAIT_FOR_CLOSE_BROKEN		43
+#define	CPS_VALUE_OUT_OF_RANGE		44
+#define	ID_ALREADY_IN_USE		45
+#define	SIGNALS_ALREADY_SET		46
+#define	NOT_RECEIVING_PROCESS		47
+#define	RTA_NUMBER_WRONG		48
+#define NO_SUCH_PRODUCT			49
+#define	HOST_SYSPORT_BAD		50
+#define	ID_NOT_TENTATIVE		51
+#define XPRINT_CPS_OUT_OF_RANGE		52
+#define	NOT_ENOUGH_CORE_FOR_PCI_COPY	53
+
+
+#endif				/* __rio_errors_h__ */
diff --git a/drivers/staging/generic_serial/rio/func.h b/drivers/staging/generic_serial/rio/func.h
new file mode 100644
index 0000000..078d44f
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/func.h
@@ -0,0 +1,143 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: func.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)func.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __func_h_def
+#define __func_h_def
+
+#include <linux/kdev_t.h>
+
+/* rioboot.c */
+int RIOBootCodeRTA(struct rio_info *, struct DownLoad *);
+int RIOBootCodeHOST(struct rio_info *, struct DownLoad *);
+int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
+void msec_timeout(struct Host *);
+int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
+int RIOBootOk(struct rio_info *, struct Host *, unsigned long);
+int RIORtaBound(struct rio_info *, unsigned int);
+void rio_fill_host_slot(int, int, unsigned int, struct Host *);
+
+/* riocmd.c */
+int RIOFoadRta(struct Host *, struct Map *);
+int RIOZombieRta(struct Host *, struct Map *);
+int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *));
+int RIOIdentifyRta(struct rio_info *, void __user *);
+int RIOKillNeighbour(struct rio_info *, void __user *);
+int RIOSuspendBootRta(struct Host *, int, int);
+int RIOFoadWakeup(struct rio_info *);
+struct CmdBlk *RIOGetCmdBlk(void);
+void RIOFreeCmdBlk(struct CmdBlk *);
+int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *);
+void RIOPollHostCommands(struct rio_info *, struct Host *);
+int RIOWFlushMark(unsigned long, struct CmdBlk *);
+int RIORFlushEnable(unsigned long, struct CmdBlk *);
+int RIOUnUse(unsigned long, struct CmdBlk *);
+
+/* rioctrl.c */
+int riocontrol(struct rio_info *, dev_t, int, unsigned long, int);
+
+int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char);
+
+/* rioinit.c */
+void rioinit(struct rio_info *, struct RioHostInfo *);
+void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
+void RIOISAinit(struct rio_info *, int);
+int RIODoAT(struct rio_info *, int, int);
+caddr_t RIOCheckForATCard(int);
+int RIOAssignAT(struct rio_info *, int, void __iomem *, int);
+int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int);
+void RIOAllocDataStructs(struct rio_info *);
+void RIOSetupDataStructs(struct rio_info *);
+int RIODefaultName(struct rio_info *, struct Host *, unsigned int);
+struct rioVersion *RIOVersid(void);
+void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int);
+
+/* riointr.c */
+void RIOTxEnable(char *);
+void RIOServiceHost(struct rio_info *, struct Host *);
+int riotproc(struct rio_info *, struct ttystatics *, int, int);
+
+/* rioparam.c */
+int RIOParam(struct Port *, int, int, int);
+int RIODelay(struct Port *PortP, int);
+int RIODelay_ni(struct Port *PortP, int);
+void ms_timeout(struct Port *);
+int can_add_transmit(struct PKT __iomem **, struct Port *);
+void add_transmit(struct Port *);
+void put_free_end(struct Host *, struct PKT __iomem *);
+int can_remove_receive(struct PKT __iomem **, struct Port *);
+void remove_receive(struct Port *);
+
+/* rioroute.c */
+int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
+void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int);
+unsigned int GetUnitType(unsigned int);
+int RIOSetChange(struct rio_info *);
+int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *);
+
+
+/* riotty.c */
+
+int riotopen(struct tty_struct *tty, struct file *filp);
+int riotclose(void *ptr);
+int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t);
+void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
+
+/* riotable.c */
+int RIONewTable(struct rio_info *);
+int RIOApel(struct rio_info *);
+int RIODeleteRta(struct rio_info *, struct Map *);
+int RIOAssignRta(struct rio_info *, struct Map *);
+int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
+int RIOChangeName(struct rio_info *, struct Map *);
+
+#if 0
+/* riodrvr.c */
+struct rio_info *rio_install(struct RioHostInfo *);
+int rio_uninstall(struct rio_info *);
+int rio_open(struct rio_info *, int, struct file *);
+int rio_close(struct rio_info *, struct file *);
+int rio_read(struct rio_info *, struct file *, char *, int);
+int rio_write(struct rio_info *, struct file *f, char *, int);
+int rio_ioctl(struct rio_info *, struct file *, int, char *);
+int rio_select(struct rio_info *, struct file *f, int, struct sel *);
+int rio_intr(char *);
+int rio_isr_thread(char *);
+struct rio_info *rio_info_store(int cmd, struct rio_info *p);
+#endif
+
+extern void rio_copy_to_card(void *from, void __iomem *to, int len);
+extern int rio_minor(struct tty_struct *tty);
+extern int rio_ismodem(struct tty_struct *tty);
+
+extern void rio_start_card_running(struct Host *HostP);
+
+#endif				/* __func_h_def */
diff --git a/drivers/staging/generic_serial/rio/host.h b/drivers/staging/generic_serial/rio/host.h
new file mode 100644
index 0000000..78f2454
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/host.h
@@ -0,0 +1,123 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: host.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:10
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)host.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_host_h__
+#define __rio_host_h__
+
+/*
+** the host structure - one per host card in the system.
+*/
+
+#define	MAX_EXTRA_UNITS	64
+
+/*
+**    Host data structure. This is used for the software equiv. of
+**    the host.
+*/
+struct Host {
+	struct pci_dev *pdev;
+	unsigned char Type;		/* RIO_EISA, RIO_MCA, ... */
+	unsigned char Ivec;		/* POLLED or ivec number */
+	unsigned char Mode;		/* Control stuff */
+	unsigned char Slot;		/* Slot */
+	void  __iomem *Caddr;		/* KV address of DPRAM */
+	struct DpRam __iomem *CardP;	/* KV address of DPRAM, with overlay */
+	unsigned long PaddrP;		/* Phys. address of DPRAM */
+	char Name[MAX_NAME_LEN];	/* The name of the host */
+	unsigned int UniqueNum;		/* host unique number */
+	spinlock_t HostLock;	/* Lock structure for MPX */
+	unsigned int WorkToBeDone;	/* set to true each interrupt */
+	unsigned int InIntr;		/* Being serviced? */
+	unsigned int IntSrvDone;	/* host's interrupt has been serviced */
+	void (*Copy) (void *, void __iomem *, int);	/* copy func */
+	struct timer_list timer;
+	/*
+	 **               I M P O R T A N T !
+	 **
+	 ** The rest of this data structure is cleared to zero after
+	 ** a RIO_HOST_FOAD command.
+	 */
+
+	unsigned long Flags;			/* Whats going down */
+#define RC_WAITING            0
+#define RC_STARTUP            1
+#define RC_RUNNING            2
+#define RC_STUFFED            3
+#define RC_READY              7
+#define RUN_STATE             7
+/*
+** Boot mode applies to the way in which hosts in this system will
+** boot RTAs
+*/
+#define RC_BOOT_ALL           0x8		/* Boot all RTAs attached */
+#define RC_BOOT_OWN           0x10		/* Only boot RTAs bound to this system */
+#define RC_BOOT_NONE          0x20		/* Don't boot any RTAs (slave mode) */
+
+	struct Top Topology[LINKS_PER_UNIT];	/* one per link */
+	struct Map Mapping[MAX_RUP];		/* Mappings for host */
+	struct PHB __iomem *PhbP;		/* Pointer to the PHB array */
+	unsigned short __iomem *PhbNumP;	/* Ptr to Number of PHB's */
+	struct LPB __iomem *LinkStrP;		/* Link Structure Array */
+	struct RUP __iomem *RupP;		/* Sixteen real rups here */
+	struct PARM_MAP __iomem *ParmMapP;	/* points to the parmmap */
+	unsigned int ExtraUnits[MAX_EXTRA_UNITS];	/* unknown things */
+	unsigned int NumExtraBooted;		/* how many of the above */
+	/*
+	 ** Twenty logical rups.
+	 ** The first sixteen are the real Rup entries (above), the last four
+	 ** are the link RUPs.
+	 */
+	struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT];
+	int timeout_id;				/* For calling 100 ms delays */
+	int timeout_sem;			/* For calling 100 ms delays */
+	unsigned long locks;			/* long req'd for set_bit --RR */
+	char ____end_marker____;
+};
+#define Control      CardP->DpControl
+#define SetInt       CardP->DpSetInt
+#define ResetTpu     CardP->DpResetTpu
+#define ResetInt     CardP->DpResetInt
+#define Signature    CardP->DpSignature
+#define Sram1        CardP->DpSram1
+#define Sram2        CardP->DpSram2
+#define Sram3        CardP->DpSram3
+#define Scratch      CardP->DpScratch
+#define __ParmMapR   CardP->DpParmMapR
+#define SLX          CardP->DpSlx
+#define Revision     CardP->DpRevision
+#define Unique       CardP->DpUnique
+#define Year         CardP->DpYear
+#define Week         CardP->DpWeek
+
+#define RIO_DUMBPARM 0x0860	/* what not to expect */
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/link.h b/drivers/staging/generic_serial/rio/link.h
new file mode 100644
index 0000000..f3bf11a0
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/link.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                      L I N K
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _link_h
+#define _link_h 1
+
+/*************************************************
+ * Define the Link Status stuff
+ ************************************************/
+/* Boot request stuff */
+#define BOOT_REQUEST       ((ushort) 0)	/* Request for a boot */
+#define BOOT_ABORT         ((ushort) 1)	/* Abort a boot */
+#define BOOT_SEQUENCE      ((ushort) 2)	/* Packet with the number of packets
+					   and load address */
+#define BOOT_COMPLETED     ((ushort) 3)	/* Boot completed */
+
+
+struct LPB {
+	u16 link_number;	/* Link Number */
+	u16 in_ch;	/* Link In Channel */
+	u16 out_ch;	/* Link Out Channel */
+	u8 attached_serial[4];  /* Attached serial number */
+	u8 attached_host_serial[4];
+	/* Serial number of Host who
+	   booted the other end */
+	u16 descheduled;	/* Currently Descheduled */
+	u16 state;		/* Current state */
+	u16 send_poll;		/* Send a Poll Packet */
+	u16 ltt_p;	/* Process Descriptor */
+	u16 lrt_p;	/* Process Descriptor */
+	u16 lrt_status;		/* Current lrt status */
+	u16 ltt_status;		/* Current ltt status */
+	u16 timeout;		/* Timeout value */
+	u16 topology;		/* Topology bits */
+	u16 mon_ltt;
+	u16 mon_lrt;
+	u16 WaitNoBoot;	/* Secs to hold off booting */
+	u16 add_packet_list;	/* Add packets to here */
+	u16 remove_packet_list;	/* Send packets from here */
+
+	u16 lrt_fail_chan;	/* Lrt's failure channel */
+	u16 ltt_fail_chan;	/* Ltt's failure channel */
+
+	/* RUP structure for HOST to driver communications */
+	struct RUP rup;
+	struct RUP link_rup;	/* RUP for the link (POLL,
+				   topology etc.) */
+	u16 attached_link;	/* Number of attached link */
+	u16 csum_errors;	/* csum errors */
+	u16 num_disconnects;	/* number of disconnects */
+	u16 num_sync_rcvd;	/* # sync's received */
+	u16 num_sync_rqst;	/* # sync requests */
+	u16 num_tx;		/* Num pkts sent */
+	u16 num_rx;		/* Num pkts received */
+	u16 module_attached;	/* Module tpyes of attached */
+	u16 led_timeout;	/* LED timeout */
+	u16 first_port;		/* First port to service */
+	u16 last_port;		/* Last port to service */
+};
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/linux_compat.h b/drivers/staging/generic_serial/rio/linux_compat.h
new file mode 100644
index 0000000..34c0d28
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/linux_compat.h
@@ -0,0 +1,77 @@
+/*
+ * (C) 2000 R.E.Wolff@BitWizard.nl
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/interrupt.h>
+
+
+#define DEBUG_ALL
+
+struct ttystatics {
+	struct termios tm;
+};
+
+extern int rio_debug;
+
+#define RIO_DEBUG_INIT         0x000001
+#define RIO_DEBUG_BOOT         0x000002
+#define RIO_DEBUG_CMD          0x000004
+#define RIO_DEBUG_CTRL         0x000008
+#define RIO_DEBUG_INTR         0x000010
+#define RIO_DEBUG_PARAM        0x000020
+#define RIO_DEBUG_ROUTE        0x000040
+#define RIO_DEBUG_TABLE        0x000080
+#define RIO_DEBUG_TTY          0x000100
+#define RIO_DEBUG_FLOW         0x000200
+#define RIO_DEBUG_MODEMSIGNALS 0x000400
+#define RIO_DEBUG_PROBE        0x000800
+#define RIO_DEBUG_CLEANUP      0x001000
+#define RIO_DEBUG_IFLOW        0x002000
+#define RIO_DEBUG_PFE          0x004000
+#define RIO_DEBUG_REC          0x008000
+#define RIO_DEBUG_SPINLOCK     0x010000
+#define RIO_DEBUG_DELAY        0x020000
+#define RIO_DEBUG_MOD_COUNT    0x040000
+
+
+/* Copied over from riowinif.h . This is ugly. The winif file declares
+also much other stuff which is incompatible with the headers from
+the older driver. The older driver includes "brates.h" which shadows
+the definitions from Linux, and is incompatible... */
+
+/* RxBaud and TxBaud definitions... */
+#define	RIO_B0			0x00	/* RTS / DTR signals dropped */
+#define	RIO_B50			0x01	/* 50 baud */
+#define	RIO_B75			0x02	/* 75 baud */
+#define	RIO_B110		0x03	/* 110 baud */
+#define	RIO_B134		0x04	/* 134.5 baud */
+#define	RIO_B150		0x05	/* 150 baud */
+#define	RIO_B200		0x06	/* 200 baud */
+#define	RIO_B300		0x07	/* 300 baud */
+#define	RIO_B600		0x08	/* 600 baud */
+#define	RIO_B1200		0x09	/* 1200 baud */
+#define	RIO_B1800		0x0A	/* 1800 baud */
+#define	RIO_B2400		0x0B	/* 2400 baud */
+#define	RIO_B4800		0x0C	/* 4800 baud */
+#define	RIO_B9600		0x0D	/* 9600 baud */
+#define	RIO_B19200		0x0E	/* 19200 baud */
+#define	RIO_B38400		0x0F	/* 38400 baud */
+#define	RIO_B56000		0x10	/* 56000 baud */
+#define	RIO_B57600		0x11	/* 57600 baud */
+#define	RIO_B64000		0x12	/* 64000 baud */
+#define	RIO_B115200		0x13	/* 115200 baud */
+#define	RIO_B2000		0x14	/* 2000 baud */
diff --git a/drivers/staging/generic_serial/rio/map.h b/drivers/staging/generic_serial/rio/map.h
new file mode 100644
index 0000000..8366978
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/map.h
@@ -0,0 +1,98 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: map.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:11
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)map.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_map_h__
+#define __rio_map_h__
+
+/*
+** mapping structure passed to and from the config.rio program to
+** determine the current topology of the world
+*/
+
+#define MAX_MAP_ENTRY 17
+#define	TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
+#define	MAX_NAME_LEN 32
+
+struct Map {
+	unsigned int HostUniqueNum;	/* Supporting hosts unique number */
+	unsigned int RtaUniqueNum;	/* Unique number */
+	/*
+	 ** The next two IDs must be swapped on big-endian architectures
+	 ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
+	 ** upgrading for example).
+	 */
+	unsigned short ID;		/* ID used in the subnet */
+	unsigned short ID2;		/* ID of 2nd block of 8 for 16 port */
+	unsigned long Flags;		/* Booted, ID Given, Disconnected */
+	unsigned long SysPort;		/* First tty mapped to this port */
+	struct Top Topology[LINKS_PER_UNIT];	/* ID connected to each link */
+	char Name[MAX_NAME_LEN];	/* Cute name by which RTA is known */
+};
+
+/*
+** Flag values:
+*/
+#define	RTA_BOOTED		0x00000001
+#define RTA_NEWBOOT		0x00000010
+#define	MSG_DONE		0x00000020
+#define	RTA_INTERCONNECT	0x00000040
+#define	RTA16_SECOND_SLOT	0x00000080
+#define	BEEN_HERE		0x00000100
+#define SLOT_TENTATIVE		0x40000000
+#define SLOT_IN_USE		0x80000000
+
+/*
+** HostUniqueNum is the unique number from the host card that this RTA
+** is to be connected to.
+** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO
+** if the slot in the table is unused. If it is the same as the HostUniqueNum
+** then this slot represents a host card.
+** Flags contains current boot/route state info
+** SysPort is a value in the range 0-504, being the number of the first tty
+** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8.
+** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor
+** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256,
+** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511
+** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an
+** unused slot/unknown ID etc.
+** The Topology array contains the ID of the unit connected to each of the
+** four links on this unit. The entry will be 0xFFFF if NOTHING is connected
+** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link.
+** The Name field is a null-terminated string, upto 31 characters, containing
+** the 'cute' name that the sysadmin/users know the RTA by. It is permissible
+** for this string to contain any character in the range \040 to \176 inclusive.
+** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The
+** special character '%' IS allowable, and needs no special action.
+**
+*/
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/param.h b/drivers/staging/generic_serial/rio/param.h
new file mode 100644
index 0000000..7e9b628
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/param.h
@@ -0,0 +1,55 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: param.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)param.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_param_h__
+#define __rio_param_h__
+
+/*
+** the param command block, as used in OPEN and PARAM calls.
+*/
+
+struct phb_param {
+	u8 Cmd;			/* It is very important that these line up */
+	u8 Cor1;		/* with what is expected at the other end. */
+	u8 Cor2;		/* to confirm that you've got it right,    */
+	u8 Cor4;		/* check with cirrus/cirrus.h              */
+	u8 Cor5;
+	u8 TxXon;		/* Transmit X-On character */
+	u8 TxXoff;		/* Transmit X-Off character */
+	u8 RxXon;		/* Receive X-On character */
+	u8 RxXoff;		/* Receive X-Off character */
+	u8 LNext;		/* Literal-next character */
+	u8 TxBaud;		/* Transmit baudrate */
+	u8 RxBaud;		/* Receive baudrate */
+};
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/parmmap.h b/drivers/staging/generic_serial/rio/parmmap.h
new file mode 100644
index 0000000..acc8fa4
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/parmmap.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               H O S T   M E M O R Y  M A P
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+6/4/1991   jonb		     Made changes to accommodate Mips R3230 bus
+ ***************************************************************************/
+
+#ifndef _parmap_h
+#define _parmap_h
+
+typedef struct PARM_MAP PARM_MAP;
+
+struct PARM_MAP {
+	u16 phb_ptr;	/* Pointer to the PHB array */
+	u16 phb_num_ptr;	/* Ptr to Number of PHB's */
+	u16 free_list;	/* Free List pointer */
+	u16 free_list_end;	/* Free List End pointer */
+	u16 q_free_list_ptr;	/* Ptr to Q_BUF variable */
+	u16 unit_id_ptr;	/* Unit Id */
+	u16 link_str_ptr;	/* Link Structure Array */
+	u16 bootloader_1;	/* 1st Stage Boot Loader */
+	u16 bootloader_2;	/* 2nd Stage Boot Loader */
+	u16 port_route_map_ptr;	/* Port Route Map */
+	u16 route_ptr;		/* Unit Route Map */
+	u16 map_present;	/* Route Map present */
+	s16 pkt_num;		/* Total number of packets */
+	s16 q_num;		/* Total number of Q packets */
+	u16 buffers_per_port;	/* Number of buffers per port */
+	u16 heap_size;		/* Initial size of heap */
+	u16 heap_left;		/* Current Heap left */
+	u16 error;		/* Error code */
+	u16 tx_max;		/* Max number of tx pkts per phb */
+	u16 rx_max;		/* Max number of rx pkts per phb */
+	u16 rx_limit;		/* For high / low watermarks */
+	s16 links;		/* Links to use */
+	s16 timer;		/* Interrupts per second */
+	u16 rups;		/* Pointer to the RUPs */
+	u16 max_phb;		/* Mostly for debugging */
+	u16 living;		/* Just increments!! */
+	u16 init_done;		/* Initialisation over */
+	u16 booting_link;
+	u16 idle_count;		/* Idle time counter */
+	u16 busy_count;		/* Busy counter */
+	u16 idle_control;	/* Control Idle Process */
+	u16 tx_intr;		/* TX interrupt pending */
+	u16 rx_intr;		/* RX interrupt pending */
+	u16 rup_intr;		/* RUP interrupt pending */
+};
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/pci.h b/drivers/staging/generic_serial/rio/pci.h
new file mode 100644
index 0000000..6032f91
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/pci.h
@@ -0,0 +1,72 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: pci.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)pci.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_pci_h__
+#define	__rio_pci_h__
+
+/*
+** PCI stuff
+*/
+
+#define	PCITpFastClock		0x80
+#define	PCITpSlowClock		0x00
+#define	PCITpFastLinks	        0x40
+#define	PCITpSlowLinks	        0x00
+#define	PCITpIntEnable		0x04
+#define	PCITpIntDisable		0x00
+#define	PCITpBusEnable		0x02
+#define	PCITpBusDisable		0x00
+#define	PCITpBootFromRam	0x01
+#define	PCITpBootFromLink	0x00
+
+#define	RIO_PCI_VENDOR		0x11CB
+#define	RIO_PCI_DEVICE		0x8000
+#define	RIO_PCI_BASE_CLASS	0x02
+#define	RIO_PCI_SUB_CLASS	0x80
+#define	RIO_PCI_PROG_IFACE	0x00
+
+#define RIO_PCI_RID		0x0008
+#define RIO_PCI_BADR0		0x0010
+#define RIO_PCI_INTLN		0x003C
+#define RIO_PCI_INTPIN		0x003D
+
+#define	RIO_PCI_MEM_SIZE	65536
+
+#define	RIO_PCI_TURBO_TP	0x80
+#define	RIO_PCI_FAST_LINKS	0x40
+#define	RIO_PCI_INT_ENABLE	0x04
+#define	RIO_PCI_TP_BUS_ENABLE	0x02
+#define	RIO_PCI_BOOT_FROM_RAM	0x01
+
+#define	RIO_PCI_DEFAULT_MODE	0x05
+
+#endif				/* __rio_pci_h__ */
diff --git a/drivers/staging/generic_serial/rio/phb.h b/drivers/staging/generic_serial/rio/phb.h
new file mode 100644
index 0000000..a4c48ae
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/phb.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                 P H B     H E A D E R                        *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra, Jeremy Rolls
+ Date    : 
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _phb_h
+#define _phb_h 1
+
+/*************************************************
+ * Handshake asserted. Deasserted by the LTT(s)
+ ************************************************/
+#define PHB_HANDSHAKE_SET      ((ushort) 0x001)	/* Set by LRT */
+
+#define PHB_HANDSHAKE_RESET     ((ushort) 0x002)	/* Set by ISR / driver */
+
+#define PHB_HANDSHAKE_FLAGS     (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
+						/* Reset by ltt */
+
+
+/*************************************************
+ * Maximum number of PHB's
+ ************************************************/
+#define MAX_PHB               ((ushort) 128)	/* range 0-127 */
+
+/*************************************************
+ * Defines for the mode fields
+ ************************************************/
+#define TXPKT_INCOMPLETE        0x0001	/* Previous tx packet not completed */
+#define TXINTR_ENABLED          0x0002	/* Tx interrupt is enabled */
+#define TX_TAB3                 0x0004	/* TAB3 mode */
+#define TX_OCRNL                0x0008	/* OCRNL mode */
+#define TX_ONLCR                0x0010	/* ONLCR mode */
+#define TX_SENDSPACES           0x0020	/* Send n spaces command needs
+					   completing */
+#define TX_SENDNULL             0x0040	/* Escaping NULL needs completing */
+#define TX_SENDLF               0x0080	/* LF -> CR LF needs completing */
+#define TX_PARALLELBUG          0x0100	/* CD1400 LF -> CR LF bug on parallel
+					   port */
+#define TX_HANGOVER             (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
+#define TX_DTRFLOW		0x0200	/* DTR tx flow control */
+#define	TX_DTRFLOWED		0x0400	/* DTR is low - don't allow more data
+					   into the FIFO */
+#define	TX_DATAINFIFO		0x0800	/* There is data in the FIFO */
+#define	TX_BUSY			0x1000	/* Data in FIFO, shift or holding regs */
+
+#define RX_SPARE	        0x0001	/* SPARE */
+#define RXINTR_ENABLED          0x0002	/* Rx interrupt enabled */
+#define RX_ICRNL                0x0008	/* ICRNL mode */
+#define RX_INLCR                0x0010	/* INLCR mode */
+#define RX_IGNCR                0x0020	/* IGNCR mode */
+#define RX_CTSFLOW              0x0040	/* CTSFLOW enabled */
+#define RX_IXOFF                0x0080	/* IXOFF enabled */
+#define RX_CTSFLOWED            0x0100	/* CTSFLOW and CTS dropped */
+#define RX_IXOFFED              0x0200	/* IXOFF and xoff sent */
+#define RX_BUFFERED		0x0400	/* Try and pass on complete packets */
+
+#define PORT_ISOPEN             0x0001	/* Port open? */
+#define PORT_HUPCL              0x0002	/* Hangup on close? */
+#define PORT_MOPENPEND          0x0004	/* Modem open pending */
+#define PORT_ISPARALLEL         0x0008	/* Parallel port */
+#define PORT_BREAK              0x0010	/* Port on break */
+#define PORT_STATUSPEND		0x0020	/* Status packet pending */
+#define PORT_BREAKPEND          0x0040	/* Break packet pending */
+#define PORT_MODEMPEND          0x0080	/* Modem status packet pending */
+#define PORT_PARALLELBUG        0x0100	/* CD1400 LF -> CR LF bug on parallel
+					   port */
+#define PORT_FULLMODEM          0x0200	/* Full modem signals */
+#define PORT_RJ45               0x0400	/* RJ45 connector - no RI signal */
+#define PORT_RESTRICTED         0x0600	/* Restricted connector - no RI / DTR */
+
+#define PORT_MODEMBITS          0x0600	/* Mask for modem fields */
+
+#define PORT_WCLOSE             0x0800	/* Waiting for close */
+#define	PORT_HANDSHAKEFIX	0x1000	/* Port has H/W flow control fix */
+#define	PORT_WASPCLOSED		0x2000	/* Port closed with PCLOSE */
+#define	DUMPMODE		0x4000	/* Dump RTA mem */
+#define	READ_REG		0x8000	/* Read CD1400 register */
+
+
+
+/**************************************************************************
+ * PHB Structure
+ * A  few words.
+ *
+ * Normally Packets are added to the end of the list and removed from
+ * the start. The pointer tx_add points to a SPACE to put a Packet.
+ * The pointer tx_remove points to the next Packet to remove
+ *************************************************************************/
+
+struct PHB {
+	u8 source;
+	u8 handshake;
+	u8 status;
+	u16 timeout;		/* Maximum of 1.9 seconds */
+	u8 link;		/* Send down this link */
+	u8 destination;
+	u16 tx_start;
+	u16 tx_end;
+	u16 tx_add;
+	u16 tx_remove;
+
+	u16 rx_start;
+	u16 rx_end;
+	u16 rx_add;
+	u16 rx_remove;
+
+};
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/pkt.h b/drivers/staging/generic_serial/rio/pkt.h
new file mode 100644
index 0000000..a945816
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/pkt.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+ *******                                                              *******
+ *******            P A C K E T   H E A D E R   F I L E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _pkt_h
+#define _pkt_h 1
+
+#define PKT_CMD_BIT     ((ushort) 0x080)
+#define PKT_CMD_DATA    ((ushort) 0x080)
+
+#define PKT_ACK         ((ushort) 0x040)
+
+#define PKT_TGL         ((ushort) 0x020)
+
+#define PKT_LEN_MASK    ((ushort) 0x07f)
+
+#define DATA_WNDW       ((ushort) 0x10)
+#define PKT_TTL_MASK    ((ushort) 0x0f)
+
+#define PKT_MAX_DATA_LEN   72
+
+#define PKT_LENGTH         sizeof(struct PKT)
+#define SYNC_PKT_LENGTH    (PKT_LENGTH + 4)
+
+#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK
+#define CONTROL_PKT_CMD_BIT  PKT_CMD_BIT
+#define CONTROL_PKT_ACK (PKT_ACK << 8)
+#define CONTROL_PKT_TGL (PKT_TGL << 8)
+#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
+#define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
+
+struct PKT {
+	u8 dest_unit;		/* Destination Unit Id */
+	u8 dest_port;		/* Destination POrt */
+	u8 src_unit;		/* Source Unit Id */
+	u8 src_port;		/* Source POrt */
+	u8 len;
+	u8 control;
+	u8 data[PKT_MAX_DATA_LEN];
+	/* Actual data :-) */
+	u16 csum;		/* C-SUM */
+};
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/port.h b/drivers/staging/generic_serial/rio/port.h
new file mode 100644
index 0000000..49cf6d1
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/port.h
@@ -0,0 +1,179 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: port.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:12
+**	Retrieved	: 11/6/98 11:34:21
+**
+**  ident @(#)port.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_port_h__
+#define	__rio_port_h__
+
+/*
+**	Port data structure
+*/
+struct Port {
+	struct gs_port gs;
+	int PortNum;			/* RIO port no., 0-511 */
+	struct Host *HostP;
+	void __iomem *Caddr;
+	unsigned short HostPort;	/* Port number on host card */
+	unsigned char RupNum;		/* Number of RUP for port */
+	unsigned char ID2;		/* Second ID of RTA for port */
+	unsigned long State;		/* FLAGS for open & xopen */
+#define	RIO_LOPEN	0x00001		/* Local open */
+#define	RIO_MOPEN	0x00002		/* Modem open */
+#define	RIO_WOPEN	0x00004		/* Waiting for open */
+#define	RIO_CLOSING	0x00008		/* The port is being close */
+#define	RIO_XPBUSY	0x00010		/* Transparent printer busy */
+#define	RIO_BREAKING	0x00020		/* Break in progress */
+#define	RIO_DIRECT	0x00040		/* Doing Direct output */
+#define	RIO_EXCLUSIVE	0x00080		/* Stream open for exclusive use */
+#define	RIO_NDELAY	0x00100		/* Stream is open FNDELAY */
+#define	RIO_CARR_ON	0x00200		/* Stream has carrier present */
+#define	RIO_XPWANTR	0x00400		/* Stream wanted by Xprint */
+#define	RIO_RBLK	0x00800		/* Stream is read-blocked */
+#define	RIO_BUSY	0x01000		/* Stream is BUSY for write */
+#define	RIO_TIMEOUT	0x02000		/* Stream timeout in progress */
+#define	RIO_TXSTOP	0x04000		/* Stream output is stopped */
+#define	RIO_WAITFLUSH	0x08000		/* Stream waiting for flush */
+#define	RIO_DYNOROD	0x10000		/* Drain failed */
+#define	RIO_DELETED	0x20000		/* RTA has been deleted */
+#define RIO_ISSCANCODE	0x40000		/* This line is in scancode mode */
+#define	RIO_USING_EUC	0x100000	/* Using extended Unix chars */
+#define	RIO_CAN_COOK	0x200000	/* This line can do cooking */
+#define RIO_TRIAD_MODE  0x400000	/* Enable TRIAD special ops. */
+#define RIO_TRIAD_BLOCK 0x800000	/* Next read will block */
+#define RIO_TRIAD_FUNC  0x1000000	/* Seen a function key coming in */
+#define RIO_THROTTLE_RX 0x2000000	/* RX needs to be throttled. */
+
+	unsigned long Config;		/* FLAGS for NOREAD.... */
+#define	RIO_NOREAD	0x0001		/* Are not allowed to read port */
+#define	RIO_NOWRITE	0x0002		/* Are not allowed to write port */
+#define	RIO_NOXPRINT	0x0004		/* Are not allowed to xprint port */
+#define	RIO_NOMASK	0x0007		/* All not allowed things */
+#define RIO_IXANY	0x0008		/* Port is allowed ixany */
+#define	RIO_MODEM	0x0010		/* Stream is a modem device */
+#define	RIO_IXON	0x0020		/* Port is allowed ixon */
+#define RIO_WAITDRAIN	0x0040		/* Wait for port to completely drain */
+#define RIO_MAP_50_TO_50	0x0080	/* Map 50 baud to 50 baud */
+#define RIO_MAP_110_TO_110	0x0100	/* Map 110 baud to 110 baud */
+
+/*
+** 15.10.1998 ARG - ESIL 0761 prt fix
+** As LynxOS does not appear to support Hardware Flow Control .....
+** Define our own flow control flags in 'Config'.
+*/
+#define RIO_CTSFLOW	0x0200		/* RIO's own CTSFLOW flag */
+#define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
+
+
+	struct PHB __iomem *PhbP;	/* pointer to PHB for port */
+	u16 __iomem *TxAdd;		/* Add packets here */
+	u16 __iomem *TxStart;		/* Start of add array */
+	u16 __iomem *TxEnd;		/* End of add array */
+	u16 __iomem *RxRemove;		/* Remove packets here */
+	u16 __iomem *RxStart;		/* Start of remove array */
+	u16 __iomem *RxEnd;		/* End of remove array */
+	unsigned int RtaUniqueNum;	/* Unique number of RTA */
+	unsigned short PortState;	/* status of port */
+	unsigned short ModemState;	/* status of modem lines */
+	unsigned long ModemLines;	/* Modem bits sent to RTA */
+	unsigned char CookMode;		/* who expands CR/LF? */
+	unsigned char ParamSem;		/* Prevent write during param */
+	unsigned char Mapped;		/* if port mapped onto host */
+	unsigned char SecondBlock;	/* if port belongs to 2nd block
+				   		of 16 port RTA */
+	unsigned char InUse;		/* how many pre-emptive cmds */
+	unsigned char Lock;		/* if params locked */
+	unsigned char Store;		/* if params stored across closes */
+	unsigned char FirstOpen;	/* TRUE if first time port opened */
+	unsigned char FlushCmdBodge;	/* if doing a (non)flush */
+	unsigned char MagicFlags;	/* require intr processing */
+#define	MAGIC_FLUSH	0x01		/* mirror of WflushFlag */
+#define	MAGIC_REBOOT	0x02		/* RTA re-booted, re-open ports */
+#define	MORE_OUTPUT_EYGOR 0x04		/* riotproc failed to empty clists */
+	unsigned char WflushFlag;	/* 1 How many WFLUSHs active */
+/*
+** Transparent print stuff
+*/
+	struct Xprint {
+#ifndef MAX_XP_CTRL_LEN
+#define MAX_XP_CTRL_LEN		16	/* ALSO IN DAEMON.H */
+#endif
+		unsigned int XpCps;
+		char XpOn[MAX_XP_CTRL_LEN];
+		char XpOff[MAX_XP_CTRL_LEN];
+		unsigned short XpLen;	/* strlen(XpOn)+strlen(XpOff) */
+		unsigned char XpActive;
+		unsigned char XpLastTickOk;	/* TRUE if we can process */
+#define	XP_OPEN		00001
+#define	XP_RUNABLE	00002
+		struct ttystatics *XttyP;
+	} Xprint;
+	unsigned char RxDataStart;
+	unsigned char Cor2Copy;		/* copy of COR2 */
+	char *Name;			/* points to the Rta's name */
+	char *TxRingBuffer;
+	unsigned short TxBufferIn;	/* New data arrives here */
+	unsigned short TxBufferOut;	/* Intr removes data here */
+	unsigned short OldTxBufferOut;	/* Indicates if draining */
+	int TimeoutId;			/* Timeout ID */
+	unsigned int Debug;
+	unsigned char WaitUntilBooted;	/* True if open should block */
+	unsigned int statsGather;	/* True if gathering stats */
+	unsigned long txchars;		/* Chars transmitted */
+	unsigned long rxchars;		/* Chars received */
+	unsigned long opens;		/* port open count */
+	unsigned long closes;		/* port close count */
+	unsigned long ioctls;		/* ioctl count */
+	unsigned char LastRxTgl;	/* Last state of rx toggle bit */
+	spinlock_t portSem;		/* Lock using this sem */
+	int MonitorTstate;		/* Monitoring ? */
+	int timeout_id;			/* For calling 100 ms delays */
+	int timeout_sem;		/* For calling 100 ms delays */
+	int firstOpen;			/* First time open ? */
+	char *p;			/* save the global struc here .. */
+};
+
+struct ModuleInfo {
+	char *Name;
+	unsigned int Flags[4];		/* one per port on a module */
+};
+
+/*
+** This struct is required because trying to grab an entire Port structure
+** runs into problems with differing struct sizes between driver and config.
+*/
+struct PortParams {
+	unsigned int Port;
+	unsigned long Config;
+	unsigned long State;
+	struct ttystatics *TtyP;
+};
+
+#endif
diff --git a/drivers/staging/generic_serial/rio/protsts.h b/drivers/staging/generic_serial/rio/protsts.h
new file mode 100644
index 0000000..8ab7940
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/protsts.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+ *******                                                              *******
+ *******      P R O T O C O L    S T A T U S   S T R U C T U R E      *******
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _protsts_h
+#define _protsts_h 1
+
+/*************************************************
+ * ACK bit. Last Packet received OK. Set by
+ * rxpkt to indicate that the Packet has been
+ * received OK and that the LTT must set the ACK
+ * bit in the next outward bound Packet
+ * and re-set by LTT's after xmit.
+ *
+ * Gets shoved into rx_status
+ ************************************************/
+#define PHB_RX_LAST_PKT_ACKED    ((ushort) 0x080)
+
+/*******************************************************
+ * The Rx TOGGLE bit.
+ * Stuffed into rx_status by RXPKT
+ ******************************************************/
+#define PHB_RX_DATA_WNDW         ((ushort) 0x040)
+
+/*******************************************************
+ * The Rx TOGGLE bit. Matches the setting in PKT.H
+ * Stuffed into rx_status
+ ******************************************************/
+#define PHB_RX_TGL               ((ushort) 0x2000)
+
+
+/*************************************************
+ * This bit is set by the LRT to indicate that
+ * an ACK (packet) must be returned.
+ *
+ * Gets shoved into tx_status
+ ************************************************/
+#define PHB_TX_SEND_PKT_ACK      ((ushort) 0x08)
+
+/*************************************************
+ * Set by LTT to indicate that an ACK is required
+ *************************************************/
+#define PHB_TX_ACK_RQRD         ((ushort) 0x01)
+
+
+/*******************************************************
+ * The Tx TOGGLE bit.
+ * Stuffed into tx_status by RXPKT from the PKT WndW
+ * field. Looked by the LTT when the NEXT Packet
+ * is going to be sent.
+ ******************************************************/
+#define PHB_TX_DATA_WNDW         ((ushort) 0x04)
+
+
+/*******************************************************
+ * The Tx TOGGLE bit. Matches the setting in PKT.H
+ * Stuffed into tx_status
+ ******************************************************/
+#define PHB_TX_TGL               ((ushort) 0x02)
+
+/*******************************************************
+ * Request intr bit. Set when the queue has gone quiet
+ * and the PHB has requested an interrupt.
+ ******************************************************/
+#define PHB_TX_INTR             ((ushort) 0x100)
+
+/*******************************************************
+ * SET if the PHB cannot send any more data down the
+ * Link
+ ******************************************************/
+#define PHB_TX_HANDSHAKE         ((ushort) 0x010)
+
+
+#define RUP_SEND_WNDW		 ((ushort) 0x08) ;
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/rio.h b/drivers/staging/generic_serial/rio/rio.h
new file mode 100644
index 0000000..1bf3622
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rio.h
@@ -0,0 +1,208 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rio.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)rio.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rio_rio_h__
+#define	__rio_rio_h__
+
+/*
+**	Maximum numbers of things
+*/
+#define	RIO_SLOTS	4	/* number of configuration slots */
+#define	RIO_HOSTS	4	/* number of hosts that can be found */
+#define	PORTS_PER_HOST	128	/* number of ports per host */
+#define	LINKS_PER_UNIT	4	/* number of links from a host */
+#define	RIO_PORTS	(PORTS_PER_HOST * RIO_HOSTS)	/* max. no. of ports */
+#define	RTAS_PER_HOST	(MAX_RUP)	/* number of RTAs per host */
+#define	PORTS_PER_RTA	(PORTS_PER_HOST/RTAS_PER_HOST)	/* ports on a rta */
+#define	PORTS_PER_MODULE 4	/* number of ports on a plug-in module */
+				/* number of modules on an RTA */
+#define	MODULES_PER_RTA	 (PORTS_PER_RTA/PORTS_PER_MODULE)
+#define MAX_PRODUCT	16	/* numbr of different product codes */
+#define MAX_MODULE_TYPES 16	/* number of different types of module */
+
+#define RIO_CONTROL_DEV	128	/* minor number of host/control device */
+#define RIO_INVALID_MAJOR 0	/* test first host card's major no for validity */
+
+/*
+** number of RTAs that can be bound to a master
+*/
+#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS)
+
+/*
+**	Unit types
+*/
+#define PC_RTA16	0x90000000
+#define PC_RTA8		0xe0000000
+#define TYPE_HOST	0
+#define TYPE_RTA8	1
+#define TYPE_RTA16	2
+
+/*
+**	Flag values returned by functions
+*/
+
+#define	RIO_FAIL	-1
+
+/*
+** SysPort value for something that hasn't any ports
+*/
+#define	NO_PORT	0xFFFFFFFF
+
+/*
+** Unit ID Of all hosts
+*/
+#define	HOST_ID	0
+
+/*
+** Break bytes into nybles
+*/
+#define	LONYBLE(X)	((X) & 0xF)
+#define	HINYBLE(X)	(((X)>>4) & 0xF)
+
+/*
+** Flag values passed into some functions
+*/
+#define	DONT_SLEEP	0
+#define	OK_TO_SLEEP	1
+
+#define	DONT_PRINT	1
+#define	DO_PRINT	0
+
+#define PRINT_TO_LOG_CONS	0
+#define PRINT_TO_CONS	1
+#define PRINT_TO_LOG	2
+
+/*
+** Timeout has trouble with times of less than 3 ticks...
+*/
+#define	MIN_TIMEOUT	3
+
+/*
+**	Generally useful constants
+*/
+
+#define	HUNDRED_MS		((HZ/10)?(HZ/10):1)
+#define	ONE_MEG			0x100000
+#define	SIXTY_FOUR_K		0x10000
+
+#define	RIO_AT_MEM_SIZE		SIXTY_FOUR_K
+#define	RIO_EISA_MEM_SIZE	SIXTY_FOUR_K
+#define	RIO_MCA_MEM_SIZE	SIXTY_FOUR_K
+
+#define	COOK_WELL		0
+#define	COOK_MEDIUM		1
+#define	COOK_RAW		2
+
+/*
+**	Pointer manipulation stuff
+**	RIO_PTR takes hostp->Caddr and the offset into the DP RAM area
+**	and produces a UNIX caddr_t (pointer) to the object
+**	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
+**	returns the offset into the DP RAM area.
+*/
+#define	RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O)))
+#define	RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C))
+
+/*
+**	How to convert from various different device number formats:
+**	DEV is a dev number, as passed to open, close etc - NOT a minor
+**	number!
+**/
+
+#define	RIO_MODEM_MASK		0x1FF
+#define	RIO_MODEM_BIT		0x200
+#define	RIO_UNMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_MASK)
+#define	RIO_ISMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_BIT)
+#define RIO_PORT(DEV,FIRST_MAJ)	( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
+					+ MINOR(DEV)
+#define CSUM(pkt_ptr)  (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \
+			((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \
+			((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \
+			((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \
+			((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] )
+
+#define	RIO_LINK_ENABLE	0x80FF	/* FF is a hack, mainly for Mips, to        */
+			       /* prevent a really stupid race condition.  */
+
+#define	NOT_INITIALISED	0
+#define	INITIALISED	1
+
+#define	NOT_POLLING	0
+#define	POLLING		1
+
+#define	NOT_CHANGED	0
+#define	CHANGED		1
+
+#define	NOT_INUSE	0
+
+#define	DISCONNECT	0
+#define	CONNECT		1
+
+/* ------ Control Codes ------ */
+
+#define	CONTROL		'^'
+#define IFOAD		( CONTROL + 1 )
+#define	IDENTIFY	( CONTROL + 2 )
+#define	ZOMBIE		( CONTROL + 3 )
+#define	UFOAD		( CONTROL + 4 )
+#define IWAIT		( CONTROL + 5 )
+
+#define	IFOAD_MAGIC	0xF0AD	/* of course */
+#define	ZOMBIE_MAGIC	(~0xDEAD)	/* not dead -> zombie */
+#define	UFOAD_MAGIC	0xD1E	/* kill-your-neighbour */
+#define	IWAIT_MAGIC	0xB1DE	/* Bide your time */
+
+/* ------ Error Codes ------ */
+
+#define E_NO_ERROR                       ((ushort) 0)
+
+/* ------ Free Lists ------ */
+
+struct rio_free_list {
+	u16 next;
+	u16 prev;
+};
+
+/* NULL for card side linked lists */
+#define	TPNULL	((ushort)(0x8000))
+/* We can add another packet to a transmit queue if the packet pointer pointed
+ * to by the TxAdd pointer has PKT_IN_USE clear in its address. */
+#define PKT_IN_USE    0x1
+
+/* ------ Topology ------ */
+
+struct Top {
+	u8 Unit;
+	u8 Link;
+};
+
+#endif				/* __rio_h__ */
diff --git a/drivers/staging/generic_serial/rio/rio_linux.c b/drivers/staging/generic_serial/rio/rio_linux.c
new file mode 100644
index 0000000..5e33293
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rio_linux.c
@@ -0,0 +1,1204 @@
+
+/* rio_linux.c -- Linux driver for the Specialix RIO series cards. 
+ *
+ *
+ *   (C) 1999 R.E.Wolff@BitWizard.nl
+ *
+ * Specialix pays for the development and support of this driver.
+ * Please DO contact support@specialix.co.uk if you require
+ * support. But please read the documentation (rio.txt) first.
+ *
+ *
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be
+ *      useful, but WITHOUT ANY WARRANTY; without even the implied
+ *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *      PURPOSE.  See the GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public
+ *      License along with this program; if not, write to the Free
+ *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ *      USA.
+ *
+ * */
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+
+#include <linux/generic_serial.h>
+#include <asm/uaccess.h>
+
+#include "linux_compat.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "protsts.h"
+#include "rioboard.h"
+
+
+#include "rio_linux.h"
+
+/* I don't think that this driver can handle more than 512 ports on
+one machine.  Specialix specifies max 4 boards in one machine. I don't
+know why. If you want to try anyway you'll have to increase the number
+of boards in rio.h.  You'll have to allocate more majors if you need
+more than 512 ports.... */
+
+#ifndef RIO_NORMAL_MAJOR0
+/* This allows overriding on the compiler commandline, or in a "major.h" 
+   include or something like that */
+#define RIO_NORMAL_MAJOR0  154
+#define RIO_NORMAL_MAJOR1  156
+#endif
+
+#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
+#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
+#endif
+
+#ifndef RIO_WINDOW_LEN
+#define RIO_WINDOW_LEN 0x10000
+#endif
+
+
+/* Configurable options: 
+   (Don't be too sure that it'll work if you toggle them) */
+
+/* Am I paranoid or not ? ;-) */
+#undef RIO_PARANOIA_CHECK
+
+
+/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000
+   Hz, but it is user configurable. I don't recommend going above 1000
+   Hz. The interrupt ratelimit might trigger if the interrupt is
+   shared with a very active other device. 
+   undef this if you want to disable the check....
+*/
+#define IRQ_RATE_LIMIT 200
+
+
+/* These constants are derived from SCO Source */
+static DEFINE_MUTEX(rio_fw_mutex);
+static struct Conf
+ RIOConf = {
+	/* locator */ "RIO Config here",
+					/* startuptime */ HZ * 2,
+					/* how long to wait for card to run */
+				/* slowcook */ 0,
+				/* TRUE -> always use line disc. */
+				/* intrpolltime */ 1,
+				/* The frequency of OUR polls */
+				/* breakinterval */ 25,
+				/* x10 mS XXX: units seem to be 1ms not 10! -- REW */
+				/* timer */ 10,
+				/* mS */
+	/* RtaLoadBase */ 0x7000,
+	/* HostLoadBase */ 0x7C00,
+				/* XpHz */ 5,
+				/* number of Xprint hits per second */
+				/* XpCps */ 120,
+				/* Xprint characters per second */
+				/* XpOn */ "\033d#",
+				/* start Xprint for a wyse 60 */
+				/* XpOff */ "\024",
+				/* end Xprint for a wyse 60 */
+				/* MaxXpCps */ 2000,
+				/* highest Xprint speed */
+				/* MinXpCps */ 10,
+				/* slowest Xprint speed */
+				/* SpinCmds */ 1,
+				/* non-zero for mega fast boots */
+					/* First Addr */ 0x0A0000,
+					/* First address to look at */
+					/* Last Addr */ 0xFF0000,
+					/* Last address looked at */
+				/* BufferSize */ 1024,
+				/* Bytes per port of buffering */
+				/* LowWater */ 256,
+				/* how much data left before wakeup */
+				/* LineLength */ 80,
+				/* how wide is the console? */
+				/* CmdTimeout */ HZ,
+				/* how long a close command may take */
+};
+
+
+
+
+/* Function prototypes */
+
+static void rio_disable_tx_interrupts(void *ptr);
+static void rio_enable_tx_interrupts(void *ptr);
+static void rio_disable_rx_interrupts(void *ptr);
+static void rio_enable_rx_interrupts(void *ptr);
+static int rio_carrier_raised(struct tty_port *port);
+static void rio_shutdown_port(void *ptr);
+static int rio_set_real_termios(void *ptr);
+static void rio_hungup(void *ptr);
+static void rio_close(void *ptr);
+static int rio_chars_in_buffer(void *ptr);
+static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static int rio_init_drivers(void);
+
+static void my_hd(void *addr, int len);
+
+static struct tty_driver *rio_driver, *rio_driver2;
+
+/* The name "p" is a bit non-descript. But that's what the rio-lynxos
+sources use all over the place. */
+struct rio_info *p;
+
+int rio_debug;
+
+
+/* You can have the driver poll your card. 
+    - Set rio_poll to 1 to poll every timer tick (10ms on Intel). 
+      This is used when the card cannot use an interrupt for some reason.
+*/
+static int rio_poll = 1;
+
+
+/* These are the only open spaces in my computer. Yours may have more
+   or less.... */
+static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 };
+
+#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
+
+
+/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
+   Some architectures may need more. -- Changed to LONG to
+   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
+static long rio_irqmask = -1;
+
+MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");
+MODULE_DESCRIPTION("RIO driver");
+MODULE_LICENSE("GPL");
+module_param(rio_poll, int, 0);
+module_param(rio_debug, int, 0644);
+module_param(rio_irqmask, long, 0);
+
+static struct real_driver rio_real_driver = {
+	rio_disable_tx_interrupts,
+	rio_enable_tx_interrupts,
+	rio_disable_rx_interrupts,
+	rio_enable_rx_interrupts,
+	rio_shutdown_port,
+	rio_set_real_termios,
+	rio_chars_in_buffer,
+	rio_close,
+	rio_hungup,
+	NULL
+};
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static const struct file_operations rio_fw_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = rio_fw_ioctl,
+	.llseek = noop_llseek,
+};
+
+static struct miscdevice rio_fw_device = {
+	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops
+};
+
+
+
+
+
+#ifdef RIO_PARANOIA_CHECK
+
+/* This doesn't work. Who's paranoid around here? Not me! */
+
+static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine)
+{
+
+	static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
+	static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
+
+	if (!port) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (port->magic != RIO_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+
+	return 0;
+}
+#else
+#define rio_paranoia_check(a,b,c) 0
+#endif
+
+
+#ifdef DEBUG
+static void my_hd(void *ad, int len)
+{
+	int i, j, ch;
+	unsigned char *addr = ad;
+
+	for (i = 0; i < len; i += 16) {
+		rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i);
+		for (j = 0; j < 16; j++) {
+			rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : "");
+		}
+		for (j = 0; j < 16; j++) {
+			ch = addr[j + i];
+			rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch));
+		}
+		rio_dprintk(RIO_DEBUG_PARAM, "\n");
+	}
+}
+#else
+#define my_hd(ad,len) do{/* nothing*/ } while (0)
+#endif
+
+
+/* Delay a number of jiffies, allowing a signal to interrupt */
+int RIODelay(struct Port *PortP, int njiffies)
+{
+	func_enter();
+
+	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
+	msleep_interruptible(jiffies_to_msecs(njiffies));
+	func_exit();
+
+	if (signal_pending(current))
+		return RIO_FAIL;
+	else
+		return !RIO_FAIL;
+}
+
+
+/* Delay a number of jiffies, disallowing a signal to interrupt */
+int RIODelay_ni(struct Port *PortP, int njiffies)
+{
+	func_enter();
+
+	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
+	msleep(jiffies_to_msecs(njiffies));
+	func_exit();
+	return !RIO_FAIL;
+}
+
+void rio_copy_to_card(void *from, void __iomem *to, int len)
+{
+	rio_copy_toio(to, from, len);
+}
+
+int rio_minor(struct tty_struct *tty)
+{
+	return tty->index + ((tty->driver == rio_driver) ? 0 : 256);
+}
+
+static int rio_set_real_termios(void *ptr)
+{
+	return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1);
+}
+
+
+static void rio_reset_interrupt(struct Host *HostP)
+{
+	func_enter();
+
+	switch (HostP->Type) {
+	case RIO_AT:
+	case RIO_MCA:
+	case RIO_PCI:
+		writeb(0xFF, &HostP->ResetInt);
+	}
+
+	func_exit();
+}
+
+
+static irqreturn_t rio_interrupt(int irq, void *ptr)
+{
+	struct Host *HostP;
+	func_enter();
+
+	HostP = ptr;			/* &p->RIOHosts[(long)ptr]; */
+	rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
+
+	/* AAargh! The order in which to do these things is essential and
+	   not trivial.
+
+	   - hardware twiddling goes before "recursive". Otherwise when we
+	   poll the card, and a recursive interrupt happens, we won't
+	   ack the card, so it might keep on interrupting us. (especially
+	   level sensitive interrupt systems like PCI).
+
+	   - Rate limit goes before hardware twiddling. Otherwise we won't
+	   catch a card that has gone bonkers.
+
+	   - The "initialized" test goes after the hardware twiddling. Otherwise
+	   the card will stick us in the interrupt routine again.
+
+	   - The initialized test goes before recursive.
+	 */
+
+	rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
+	if (HostP->Ivec == irq) {
+		/* Tell the card we've noticed the interrupt. */
+		rio_reset_interrupt(HostP);
+	}
+
+	if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
+		return IRQ_HANDLED;
+
+	if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) {
+		printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec);
+		return IRQ_HANDLED;
+	}
+
+	RIOServiceHost(p, HostP);
+
+	rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type);
+
+	clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks);
+	rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
+	func_exit();
+	return IRQ_HANDLED;
+}
+
+
+static void rio_pollfunc(unsigned long data)
+{
+	func_enter();
+
+	rio_interrupt(0, &p->RIOHosts[data]);
+	mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll);
+
+	func_exit();
+}
+
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *              interface with the generic_serial driver                  *
+ * ********************************************************************** */
+
+/* Ehhm. I don't know how to fiddle with interrupts on the Specialix 
+   cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */
+
+static void rio_disable_tx_interrupts(void *ptr)
+{
+	func_enter();
+
+	/*  port->gs.port.flags &= ~GS_TX_INTEN; */
+
+	func_exit();
+}
+
+
+static void rio_enable_tx_interrupts(void *ptr)
+{
+	struct Port *PortP = ptr;
+	/* int hn; */
+
+	func_enter();
+
+	/* hn = PortP->HostP - p->RIOHosts;
+
+	   rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
+	   rio_interrupt (-1,(void *) hn, NULL); */
+
+	RIOTxEnable((char *) PortP);
+
+	/*
+	 * In general we cannot count on "tx empty" interrupts, although
+	 * the interrupt routine seems to be able to tell the difference.
+	 */
+	PortP->gs.port.flags &= ~GS_TX_INTEN;
+
+	func_exit();
+}
+
+
+static void rio_disable_rx_interrupts(void *ptr)
+{
+	func_enter();
+	func_exit();
+}
+
+static void rio_enable_rx_interrupts(void *ptr)
+{
+	/*  struct rio_port *port = ptr; */
+	func_enter();
+	func_exit();
+}
+
+
+/* Jeez. Isn't this simple?  */
+static int rio_carrier_raised(struct tty_port *port)
+{
+	struct Port *PortP = container_of(port, struct Port, gs.port);
+	int rv;
+
+	func_enter();
+	rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0;
+
+	rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
+
+	func_exit();
+	return rv;
+}
+
+
+/* Jeez. Isn't this simple? Actually, we can sync with the actual port
+   by just pushing stuff into the queue going to the port... */
+static int rio_chars_in_buffer(void *ptr)
+{
+	func_enter();
+
+	func_exit();
+	return 0;
+}
+
+
+/* Nothing special here... */
+static void rio_shutdown_port(void *ptr)
+{
+	struct Port *PortP;
+
+	func_enter();
+
+	PortP = (struct Port *) ptr;
+	PortP->gs.port.tty = NULL;
+	func_exit();
+}
+
+
+/* I haven't the foggiest why the decrement use count has to happen
+   here. The whole linux serial drivers stuff needs to be redesigned.
+   My guess is that this is a hack to minimize the impact of a bug
+   elsewhere. Thinking about it some more. (try it sometime) Try
+   running minicom on a serial port that is driven by a modularized
+   driver. Have the modem hangup. Then remove the driver module. Then
+   exit minicom.  I expect an "oops".  -- REW */
+static void rio_hungup(void *ptr)
+{
+	struct Port *PortP;
+
+	func_enter();
+
+	PortP = (struct Port *) ptr;
+	PortP->gs.port.tty = NULL;
+
+	func_exit();
+}
+
+
+/* The standard serial_close would become shorter if you'd wrap it like
+   this. 
+   rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
+ */
+static void rio_close(void *ptr)
+{
+	struct Port *PortP;
+
+	func_enter();
+
+	PortP = (struct Port *) ptr;
+
+	riotclose(ptr);
+
+	if (PortP->gs.port.count) {
+		printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.port.count);
+		PortP->gs.port.count = 0;
+	}
+
+	PortP->gs.port.tty = NULL;
+	func_exit();
+}
+
+
+
+static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	int rc = 0;
+	func_enter();
+
+	/* The "dev" argument isn't used. */
+	mutex_lock(&rio_fw_mutex);
+	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
+	mutex_unlock(&rio_fw_mutex);
+
+	func_exit();
+	return rc;
+}
+
+extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
+
+static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	int rc;
+	struct Port *PortP;
+	int ival;
+
+	func_enter();
+
+	PortP = (struct Port *) tty->driver_data;
+
+	rc = 0;
+	switch (cmd) {
+	case TIOCSSOFTCAR:
+		if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
+			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
+		}
+		break;
+	case TIOCGSERIAL:
+		rc = -EFAULT;
+		if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct)))
+			rc = gs_getserial(&PortP->gs, argp);
+		break;
+	case TCSBRK:
+		if (PortP->State & RIO_DELETED) {
+			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+			rc = -EIO;
+		} else {
+			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) ==
+					RIO_FAIL) {
+				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+				rc = -EIO;
+			}
+		}
+		break;
+	case TCSBRKP:
+		if (PortP->State & RIO_DELETED) {
+			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
+			rc = -EIO;
+		} else {
+			int l;
+			l = arg ? arg * 100 : 250;
+			if (l > 255)
+				l = 255;
+			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2,
+					arg ? arg * 100 : 250) == RIO_FAIL) {
+				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
+				rc = -EIO;
+			}
+		}
+		break;
+	case TIOCSSERIAL:
+		rc = -EFAULT;
+		if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct)))
+			rc = gs_setserial(&PortP->gs, argp);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	func_exit();
+	return rc;
+}
+
+
+/* The throttle/unthrottle scheme for the Specialix card is different
+ * from other drivers and deserves some explanation. 
+ * The Specialix hardware takes care of XON/XOFF
+ * and CTS/RTS flow control itself.  This means that all we have to
+ * do when signalled by the upper tty layer to throttle/unthrottle is
+ * to make a note of it here.  When we come to read characters from the
+ * rx buffers on the card (rio_receive_chars()) we look to see if the
+ * upper layer can accept more (as noted here in rio_rx_throt[]). 
+ * If it can't we simply don't remove chars from the cards buffer. 
+ * When the tty layer can accept chars, we again note that here and when
+ * rio_receive_chars() is called it will remove them from the cards buffer.
+ * The card will notice that a ports buffer has drained below some low
+ * water mark and will unflow control the line itself, using whatever
+ * flow control scheme is in use for that port. -- Simon Allen
+ */
+
+static void rio_throttle(struct tty_struct *tty)
+{
+	struct Port *port = (struct Port *) tty->driver_data;
+
+	func_enter();
+	/* If the port is using any type of input flow
+	 * control then throttle the port.
+	 */
+
+	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
+		port->State |= RIO_THROTTLE_RX;
+	}
+
+	func_exit();
+}
+
+
+static void rio_unthrottle(struct tty_struct *tty)
+{
+	struct Port *port = (struct Port *) tty->driver_data;
+
+	func_enter();
+	/* Always unthrottle even if flow control is not enabled on
+	 * this port in case we disabled flow control while the port
+	 * was throttled
+	 */
+
+	port->State &= ~RIO_THROTTLE_RX;
+
+	func_exit();
+	return;
+}
+
+
+
+
+
+/* ********************************************************************** *
+ *                    Here are the initialization routines.               *
+ * ********************************************************************** */
+
+
+static struct vpd_prom *get_VPD_PROM(struct Host *hp)
+{
+	static struct vpd_prom vpdp;
+	char *p;
+	int i;
+
+	func_enter();
+	rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM);
+
+	p = (char *) &vpdp;
+	for (i = 0; i < sizeof(struct vpd_prom); i++)
+		*p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2);
+	/* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
+
+	/* Terminate the identifier string.
+	 *** requires one extra byte in struct vpd_prom *** */
+	*p++ = 0;
+
+	if (rio_debug & RIO_DEBUG_PROBE)
+		my_hd((char *) &vpdp, 0x20);
+
+	func_exit();
+
+	return &vpdp;
+}
+
+static const struct tty_operations rio_ops = {
+	.open = riotopen,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = rio_ioctl,
+	.throttle = rio_throttle,
+	.unthrottle = rio_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
+
+static int rio_init_drivers(void)
+{
+	int error = -ENOMEM;
+
+	rio_driver = alloc_tty_driver(256);
+	if (!rio_driver)
+		goto out;
+	rio_driver2 = alloc_tty_driver(256);
+	if (!rio_driver2)
+		goto out1;
+
+	func_enter();
+
+	rio_driver->owner = THIS_MODULE;
+	rio_driver->driver_name = "specialix_rio";
+	rio_driver->name = "ttySR";
+	rio_driver->major = RIO_NORMAL_MAJOR0;
+	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	rio_driver->subtype = SERIAL_TYPE_NORMAL;
+	rio_driver->init_termios = tty_std_termios;
+	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rio_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rio_driver, &rio_ops);
+
+	rio_driver2->owner = THIS_MODULE;
+	rio_driver2->driver_name = "specialix_rio";
+	rio_driver2->name = "ttySR";
+	rio_driver2->major = RIO_NORMAL_MAJOR1;
+	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;
+	rio_driver2->subtype = SERIAL_TYPE_NORMAL;
+	rio_driver2->init_termios = tty_std_termios;
+	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rio_driver2->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(rio_driver2, &rio_ops);
+
+	rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
+
+	if ((error = tty_register_driver(rio_driver)))
+		goto out2;
+	if ((error = tty_register_driver(rio_driver2)))
+		goto out3;
+	func_exit();
+	return 0;
+      out3:
+	tty_unregister_driver(rio_driver);
+      out2:
+	put_tty_driver(rio_driver2);
+      out1:
+	put_tty_driver(rio_driver);
+      out:
+	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error);
+	return 1;
+}
+
+static const struct tty_port_operations rio_port_ops = {
+	.carrier_raised = rio_carrier_raised,
+};
+
+static int rio_init_datastructures(void)
+{
+	int i;
+	struct Port *port;
+	func_enter();
+
+	/* Many drivers statically allocate the maximum number of ports
+	   There is no reason not to allocate them dynamically. Is there? -- REW */
+	/* However, the RIO driver allows users to configure their first
+	   RTA as the ports numbered 504-511. We therefore need to allocate
+	   the whole range. :-(   -- REW */
+
+#define RI_SZ   sizeof(struct rio_info)
+#define HOST_SZ sizeof(struct Host)
+#define PORT_SZ sizeof(struct Port *)
+#define TMIO_SZ sizeof(struct termios *)
+	rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
+
+	if (!(p = kzalloc(RI_SZ, GFP_KERNEL)))
+		goto free0;
+	if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL)))
+		goto free1;
+	if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL)))
+		goto free2;
+	p->RIOConf = RIOConf;
+	rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
+
+#if 1
+	for (i = 0; i < RIO_PORTS; i++) {
+		port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL);
+		if (!port) {
+			goto free6;
+		}
+		rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
+		tty_port_init(&port->gs.port);
+		port->gs.port.ops = &rio_port_ops;
+		port->PortNum = i;
+		port->gs.magic = RIO_MAGIC;
+		port->gs.close_delay = HZ / 2;
+		port->gs.closing_wait = 30 * HZ;
+		port->gs.rd = &rio_real_driver;
+		spin_lock_init(&port->portSem);
+	}
+#else
+	/* We could postpone initializing them to when they are configured. */
+#endif
+
+
+
+	if (rio_debug & RIO_DEBUG_INIT) {
+		my_hd(&rio_real_driver, sizeof(rio_real_driver));
+	}
+
+
+	func_exit();
+	return 0;
+
+      free6:for (i--; i >= 0; i--)
+		kfree(p->RIOPortp[i]);
+/*free5:
+ free4:
+ free3:*/ kfree(p->RIOPortp);
+      free2:kfree(p->RIOHosts);
+      free1:
+	rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
+	kfree(p);
+      free0:
+	return -ENOMEM;
+}
+
+static void __exit rio_release_drivers(void)
+{
+	func_enter();
+	tty_unregister_driver(rio_driver2);
+	tty_unregister_driver(rio_driver);
+	put_tty_driver(rio_driver2);
+	put_tty_driver(rio_driver);
+	func_exit();
+}
+
+
+#ifdef CONFIG_PCI
+ /* This was written for SX, but applies to RIO too...
+    (including bugs....)
+
+    There is another bit besides Bit 17. Turning that bit off
+    (on boards shipped with the fix in the eeprom) results in a 
+    hang on the next access to the card. 
+  */
+
+ /******************************************************** 
+ * Setting bit 17 in the CNTRL register of the PLX 9050  * 
+ * chip forces a retry on writes while a read is pending.*
+ * This is to prevent the card locking up on Intel Xeon  *
+ * multiprocessor systems with the NX chipset.    -- NV  *
+ ********************************************************/
+
+/* Newer cards are produced with this bit set from the configuration
+   EEprom.  As the bit is read/write for the CPU, we can fix it here,
+   if we detect that it isn't set correctly. -- REW */
+
+static void fix_rio_pci(struct pci_dev *pdev)
+{
+	unsigned long hwbase;
+	unsigned char __iomem *rebase;
+	unsigned int t;
+
+#define CNTRL_REG_OFFSET        0x50
+#define CNTRL_REG_GOODVALUE     0x18260000
+
+	hwbase = pci_resource_start(pdev, 0);
+	rebase = ioremap(hwbase, 0x80);
+	t = readl(rebase + CNTRL_REG_OFFSET);
+	if (t != CNTRL_REG_GOODVALUE) {
+		printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
+		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
+	}
+	iounmap(rebase);
+}
+#endif
+
+
+static int __init rio_init(void)
+{
+	int found = 0;
+	int i;
+	struct Host *hp;
+	int retval;
+	struct vpd_prom *vpdp;
+	int okboard;
+
+#ifdef CONFIG_PCI
+	struct pci_dev *pdev = NULL;
+	unsigned short tshort;
+#endif
+
+	func_enter();
+	rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug);
+
+	if (abs((long) (&rio_debug) - rio_debug) < 0x10000) {
+		printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
+		rio_debug = -1;
+	}
+
+	if (misc_register(&rio_fw_device) < 0) {
+		printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
+		return -EIO;
+	}
+
+	retval = rio_init_datastructures();
+	if (retval < 0) {
+		misc_deregister(&rio_fw_device);
+		return retval;
+	}
+#ifdef CONFIG_PCI
+	/* First look for the JET devices: */
+	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) {
+		u32 tint;
+
+		if (pci_enable_device(pdev))
+			continue;
+
+		/* Specialix has a whole bunch of cards with
+		   0x2000 as the device ID. They say its because
+		   the standard requires it. Stupid standard. */
+		/* It seems that reading a word doesn't work reliably on 2.0.
+		   Also, reading a non-aligned dword doesn't work. So we read the
+		   whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
+		   ourselves */
+		pci_read_config_dword(pdev, 0x2c, &tint);
+		tshort = (tint >> 16) & 0xffff;
+		rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
+		if (tshort != 0x0100) {
+			rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort);
+			continue;
+		}
+		rio_dprintk(RIO_DEBUG_PROBE, "cp1\n");
+
+		hp = &p->RIOHosts[p->RIONumHosts];
+		hp->PaddrP = pci_resource_start(pdev, 2);
+		hp->Ivec = pdev->irq;
+		if (((1 << hp->Ivec) & rio_irqmask) == 0)
+			hp->Ivec = 0;
+		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
+		hp->Type = RIO_PCI;
+		hp->Copy = rio_copy_to_card;
+		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+		spin_lock_init(&hp->HostLock);
+		rio_reset_interrupt(hp);
+		rio_start_card_running(hp);
+
+		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
+		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
+			rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
+			p->RIOHosts[p->RIONumHosts].UniqueNum =
+			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
+			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
+			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+			fix_rio_pci(pdev);
+
+			p->RIOHosts[p->RIONumHosts].pdev = pdev;
+			pci_dev_get(pdev);
+
+			p->RIOLastPCISearch = 0;
+			p->RIONumHosts++;
+			found++;
+		} else {
+			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
+			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
+		}
+	}
+
+	/* Then look for the older PCI card.... : */
+
+	/* These older PCI cards have problems (only byte-mode access is
+	   supported), which makes them a bit awkward to support.
+	   They also have problems sharing interrupts. Be careful.
+	   (The driver now refuses to share interrupts for these
+	   cards. This should be sufficient).
+	 */
+
+	/* Then look for the older RIO/PCI devices: */
+	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) {
+		if (pci_enable_device(pdev))
+			continue;
+
+#ifdef CONFIG_RIO_OLDPCI
+		hp = &p->RIOHosts[p->RIONumHosts];
+		hp->PaddrP = pci_resource_start(pdev, 0);
+		hp->Ivec = pdev->irq;
+		if (((1 << hp->Ivec) & rio_irqmask) == 0)
+			hp->Ivec = 0;
+		hp->Ivec |= 0x8000;	/* Mark as non-sharable */
+		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
+		hp->Type = RIO_PCI;
+		hp->Copy = rio_copy_to_card;
+		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
+		spin_lock_init(&hp->HostLock);
+
+		rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+		rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+		rio_reset_interrupt(hp);
+		rio_start_card_running(hp);
+		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
+		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
+			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
+			p->RIOHosts[p->RIONumHosts].UniqueNum =
+			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
+			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
+			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+			p->RIOHosts[p->RIONumHosts].pdev = pdev;
+			pci_dev_get(pdev);
+
+			p->RIOLastPCISearch = 0;
+			p->RIONumHosts++;
+			found++;
+		} else {
+			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
+			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
+		}
+#else
+		printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
+#endif
+	}
+#endif				/* PCI */
+
+	/* Now probe for ISA cards... */
+	for (i = 0; i < NR_RIO_ADDRS; i++) {
+		hp = &p->RIOHosts[p->RIONumHosts];
+		hp->PaddrP = rio_probe_addrs[i];
+		/* There was something about the IRQs of these cards. 'Forget what.--REW */
+		hp->Ivec = 0;
+		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
+		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
+		hp->Type = RIO_AT;
+		hp->Copy = rio_copy_to_card;	/* AT card PCI???? - PVDL
+                                         * -- YES! this is now a normal copy. Only the
+					 * old PCI card uses the special PCI copy.
+					 * Moreover, the ISA card will work with the
+					 * special PCI copy anyway. -- REW */
+		hp->Mode = 0;
+		spin_lock_init(&hp->HostLock);
+
+		vpdp = get_VPD_PROM(hp);
+		rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n");
+		okboard = 0;
+		if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
+			/* Board is present... */
+			if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) {
+				/* ... and feeling fine!!!! */
+				rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
+				if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
+					rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum);
+					okboard++;
+					found++;
+				}
+			}
+
+			if (!okboard) {
+				iounmap(hp->Caddr);
+				hp->Caddr = NULL;
+			}
+		}
+	}
+
+
+	for (i = 0; i < p->RIONumHosts; i++) {
+		hp = &p->RIOHosts[i];
+		if (hp->Ivec) {
+			int mode = IRQF_SHARED;
+			if (hp->Ivec & 0x8000) {
+				mode = 0;
+				hp->Ivec &= 0x7fff;
+			}
+			rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode);
+			retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp);
+			rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+			if (retval) {
+				printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+				hp->Ivec = 0;
+			}
+			rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+			if (hp->Ivec != 0) {
+				rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
+				hp->Mode |= RIO_PCI_INT_ENABLE;
+			} else
+				hp->Mode &= ~RIO_PCI_INT_ENABLE;
+			rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+			rio_start_card_running(hp);
+		}
+		/* Init the timer "always" to make sure that it can safely be
+		   deleted when we unload... */
+
+		setup_timer(&hp->timer, rio_pollfunc, i);
+		if (!hp->Ivec) {
+			rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
+			mod_timer(&hp->timer, jiffies + rio_poll);
+		}
+	}
+
+	if (found) {
+		rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
+		rio_init_drivers();
+	} else {
+		/* deregister the misc device we created earlier */
+		misc_deregister(&rio_fw_device);
+	}
+
+	func_exit();
+	return found ? 0 : -EIO;
+}
+
+
+static void __exit rio_exit(void)
+{
+	int i;
+	struct Host *hp;
+
+	func_enter();
+
+	for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) {
+		RIOHostReset(hp->Type, hp->CardP, hp->Slot);
+		if (hp->Ivec) {
+			free_irq(hp->Ivec, hp);
+			rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
+		}
+		/* It is safe/allowed to del_timer a non-active timer */
+		del_timer_sync(&hp->timer);
+		if (hp->Caddr)
+			iounmap(hp->Caddr);
+		if (hp->Type == RIO_PCI)
+			pci_dev_put(hp->pdev);
+	}
+
+	if (misc_deregister(&rio_fw_device) < 0) {
+		printk(KERN_INFO "rio: couldn't deregister control-device\n");
+	}
+
+
+	rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
+
+	rio_release_drivers();
+
+	/* Release dynamically allocated memory */
+	kfree(p->RIOPortp);
+	kfree(p->RIOHosts);
+	kfree(p);
+
+	func_exit();
+}
+
+module_init(rio_init);
+module_exit(rio_exit);
diff --git a/drivers/staging/generic_serial/rio/rio_linux.h b/drivers/staging/generic_serial/rio/rio_linux.h
new file mode 100644
index 0000000..7f26cd7
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rio_linux.h
@@ -0,0 +1,197 @@
+
+/*
+ *  rio_linux.h
+ *
+ *  Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.nl
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  RIO serial driver.
+ *
+ *  Version 1.0 -- July, 1999. 
+ * 
+ */
+
+#define RIO_NBOARDS        4
+#define RIO_PORTSPERBOARD 128
+#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
+
+#define MODEM_SUPPORT
+
+#ifdef __KERNEL__
+
+#define RIO_MAGIC 0x12345678
+
+
+struct vpd_prom {
+	unsigned short id;
+	char hwrev;
+	char hwass;
+	int uniqid;
+	char myear;
+	char mweek;
+	char hw_feature[5];
+	char oem_id;
+	char identifier[16];
+};
+
+
+#define RIO_DEBUG_ALL           0xffffffff
+
+#define O_OTHER(tty)    \
+      ((O_OLCUC(tty))  ||\
+      (O_ONLCR(tty))   ||\
+      (O_OCRNL(tty))   ||\
+      (O_ONOCR(tty))   ||\
+      (O_ONLRET(tty))  ||\
+      (O_OFILL(tty))   ||\
+      (O_OFDEL(tty))   ||\
+      (O_NLDLY(tty))   ||\
+      (O_CRDLY(tty))   ||\
+      (O_TABDLY(tty))  ||\
+      (O_BSDLY(tty))   ||\
+      (O_VTDLY(tty))   ||\
+      (O_FFDLY(tty)))
+
+/* Same for input. */
+#define I_OTHER(tty)    \
+      ((I_INLCR(tty))  ||\
+      (I_IGNCR(tty))   ||\
+      (I_ICRNL(tty))   ||\
+      (I_IUCLC(tty))   ||\
+      (L_ISIG(tty)))
+
+
+#endif				/* __KERNEL__ */
+
+
+#define RIO_BOARD_INTR_LOCK  1
+
+
+#ifndef RIOCTL_MISC_MINOR
+/* Allow others to gather this into "major.h" or something like that */
+#define RIOCTL_MISC_MINOR    169
+#endif
+
+
+/* Allow us to debug "in the field" without requiring clients to
+   recompile.... */
+#if 1
+#define rio_spin_lock_irqsave(sem, flags) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \
+	                                sem, __FILE__, __LINE__);\
+	spin_lock_irqsave(sem, flags);\
+	} while (0)
+
+#define rio_spin_unlock_irqrestore(sem, flags) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\
+	                                sem, __FILE__, __LINE__);\
+	spin_unlock_irqrestore(sem, flags);\
+	} while (0)
+
+#define rio_spin_lock(sem) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\
+	                                sem, __FILE__, __LINE__);\
+	spin_lock(sem);\
+	} while (0)
+
+#define rio_spin_unlock(sem) do { \
+	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\
+	                                sem, __FILE__, __LINE__);\
+	spin_unlock(sem);\
+	} while (0)
+#else
+#define rio_spin_lock_irqsave(sem, flags) \
+            spin_lock_irqsave(sem, flags)
+
+#define rio_spin_unlock_irqrestore(sem, flags) \
+            spin_unlock_irqrestore(sem, flags)
+
+#define rio_spin_lock(sem) \
+            spin_lock(sem)
+
+#define rio_spin_unlock(sem) \
+            spin_unlock(sem)
+
+#endif
+
+
+
+#ifdef CONFIG_RIO_OLDPCI
+static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n)
+{
+	char __iomem *dst = dest;
+	char *src = source;
+
+	while (n--) {
+		writeb(*src++, dst++);
+		(void) readb(dummy);
+	}
+
+	return dest;
+}
+
+static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n)
+{
+	char __iomem *dst = dest;
+	char *src = source;
+
+	while (n--)
+		writeb(*src++, dst++);
+
+	return dest;
+}
+
+
+static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
+{
+	char *dst = dest;
+	char __iomem *src = source;
+
+	while (n--)
+		*dst++ = readb(src++);
+
+	return dest;
+}
+
+#else
+#define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
+#define rio_copy_toio   		       memcpy_toio
+#define rio_memcpy_fromio                      memcpy_fromio
+#endif
+
+#define DEBUG 1
+
+
+/* 
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile... 
+*/
+
+#ifdef DEBUG
+#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__)
+#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __func__)
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line)
+#else
+#define rio_dprintk(f, str...)	/* nothing */
+#define func_enter()
+#define func_exit()
+#define func_enter2()
+#endif
diff --git a/drivers/staging/generic_serial/rio/rioboard.h b/drivers/staging/generic_serial/rio/rioboard.h
new file mode 100644
index 0000000..2522300
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioboard.h
@@ -0,0 +1,275 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	RIO Host Card Hardware Definitions	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	26th April 1999				*/
+/*									*/
+/*	Version		:	1.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1999	*
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing the RIO board hardware	*/
+/*									*/
+/************************************************************************/
+
+#ifndef	_rioboard_h		/* If RIOBOARD.H not already defined */
+#define	_rioboard_h    1
+
+/*****************************************************************************
+***********************                                ***********************
+***********************   Hardware Control Registers   ***********************
+***********************                                ***********************
+*****************************************************************************/
+
+/* Hardware Registers... */
+
+#define	RIO_REG_BASE	0x7C00	/* Base of control registers */
+
+#define	RIO_CONFIG	RIO_REG_BASE + 0x0000	/* WRITE: Configuration Register */
+#define	RIO_INTSET	RIO_REG_BASE + 0x0080	/* WRITE: Interrupt Set */
+#define	RIO_RESET	RIO_REG_BASE + 0x0100	/* WRITE: Host Reset */
+#define	RIO_INTRESET	RIO_REG_BASE + 0x0180	/* WRITE: Interrupt Reset */
+
+#define	RIO_VPD_ROM	RIO_REG_BASE + 0x0000	/* READ: Vital Product Data ROM */
+#define	RIO_INTSTAT	RIO_REG_BASE + 0x0080	/* READ: Interrupt Status (Jet boards only) */
+#define	RIO_RESETSTAT	RIO_REG_BASE + 0x0100	/* READ: Reset Status (Jet boards only) */
+
+/* RIO_VPD_ROM definitions... */
+#define	VPD_SLX_ID1	0x00	/* READ: Specialix Identifier #1 */
+#define	VPD_SLX_ID2	0x01	/* READ: Specialix Identifier #2 */
+#define	VPD_HW_REV	0x02	/* READ: Hardware Revision */
+#define	VPD_HW_ASSEM	0x03	/* READ: Hardware Assembly Level */
+#define	VPD_UNIQUEID4	0x04	/* READ: Unique Identifier #4 */
+#define	VPD_UNIQUEID3	0x05	/* READ: Unique Identifier #3 */
+#define	VPD_UNIQUEID2	0x06	/* READ: Unique Identifier #2 */
+#define	VPD_UNIQUEID1	0x07	/* READ: Unique Identifier #1 */
+#define	VPD_MANU_YEAR	0x08	/* READ: Year Of Manufacture (0 = 1970) */
+#define	VPD_MANU_WEEK	0x09	/* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define	VPD_HWFEATURE1	0x0A	/* READ: Hardware Feature Byte 1 */
+#define	VPD_HWFEATURE2	0x0B	/* READ: Hardware Feature Byte 2 */
+#define	VPD_HWFEATURE3	0x0C	/* READ: Hardware Feature Byte 3 */
+#define	VPD_HWFEATURE4	0x0D	/* READ: Hardware Feature Byte 4 */
+#define	VPD_HWFEATURE5	0x0E	/* READ: Hardware Feature Byte 5 */
+#define	VPD_OEMID	0x0F	/* READ: OEM Identifier */
+#define	VPD_IDENT	0x10	/* READ: Identifier string (16 bytes) */
+#define	VPD_IDENT_LEN	0x10
+
+/* VPD ROM Definitions... */
+#define	SLX_ID1		0x4D
+#define	SLX_ID2		0x98
+
+#define	PRODUCT_ID(a)	((a>>4)&0xF)	/* Use to obtain Product ID from VPD_UNIQUEID1 */
+
+#define	ID_SX_ISA	0x2
+#define	ID_RIO_EISA	0x3
+#define	ID_SX_PCI	0x5
+#define	ID_SX_EISA	0x7
+#define	ID_RIO_RTA16	0x9
+#define	ID_RIO_ISA	0xA
+#define	ID_RIO_MCA	0xB
+#define	ID_RIO_SBUS	0xC
+#define	ID_RIO_PCI	0xD
+#define	ID_RIO_RTA8	0xE
+
+/* Transputer bootstrap definitions... */
+
+#define	BOOTLOADADDR		(0x8000 - 6)
+#define	BOOTINDICATE		(0x8000 - 2)
+
+/* Firmware load position... */
+
+#define	FIRMWARELOADADDR	0x7C00	/* Firmware is loaded _before_ this address */
+
+/*****************************************************************************
+*****************************                    *****************************
+*****************************   RIO (Rev1) ISA   *****************************
+*****************************                    *****************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_ISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
+#define	RIO_ISA_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_ISA_CFG_IRQMASK	0x30	/* Interrupt mask */
+#define	  RIO_ISA_CFG_IRQ12	0x10	/* Interrupt Level 12 */
+#define	  RIO_ISA_CFG_IRQ11	0x20	/* Interrupt Level 11 */
+#define	  RIO_ISA_CFG_IRQ9	0x30	/* Interrupt Level 9 */
+#define	RIO_ISA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
+#define	RIO_ISA_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
+
+/*****************************************************************************
+*****************************                    *****************************
+*****************************   RIO (Rev2) ISA   *****************************
+*****************************                    *****************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA2_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_ISA2_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
+#define	RIO_ISA2_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_ISA2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
+#define	RIO_ISA2_CFG_16BIT	0x08	/* 16bit mode, else 8bit */
+#define	RIO_ISA2_CFG_IRQMASK	0x30	/* Interrupt mask */
+#define	  RIO_ISA2_CFG_IRQ15	0x00	/* Interrupt Level 15 */
+#define	  RIO_ISA2_CFG_IRQ12	0x10	/* Interrupt Level 12 */
+#define	  RIO_ISA2_CFG_IRQ11	0x20	/* Interrupt Level 11 */
+#define	  RIO_ISA2_CFG_IRQ9	0x30	/* Interrupt Level 9 */
+#define	RIO_ISA2_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
+#define	RIO_ISA2_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
+
+/*****************************************************************************
+*****************************                   ******************************
+*****************************   RIO (Jet) ISA   ******************************
+*****************************                   ******************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_ISA3_IDENT	"JET HOST BY KEV#"
+
+#define	RIO_ISA3_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_ISA3_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
+#define	RIO_ISA32_CFG_IRQMASK	0xF30	/* Interrupt mask */
+#define	  RIO_ISA3_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
+#define	  RIO_ISA3_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
+#define	  RIO_ISA3_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
+#define	  RIO_ISA3_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
+#define	  RIO_ISA3_CFG_IRQ9	0x90	/* Interrupt Level 9 */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   RIO MCA   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_MCA_IDENT	"JBJGPGGHINSMJPJR"
+
+#define	RIO_MCA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
+#define	RIO_MCA_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_MCA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   RIO EISA   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* EISA Configuration Space Definitions... */
+#define	EISA_PRODUCT_ID1	0xC80
+#define	EISA_PRODUCT_ID2	0xC81
+#define	EISA_PRODUCT_NUMBER	0xC82
+#define	EISA_REVISION_NUMBER	0xC83
+#define	EISA_CARD_ENABLE	0xC84
+#define	EISA_VPD_UNIQUEID4	0xC88	/* READ: Unique Identifier #4 */
+#define	EISA_VPD_UNIQUEID3	0xC8A	/* READ: Unique Identifier #3 */
+#define	EISA_VPD_UNIQUEID2	0xC90	/* READ: Unique Identifier #2 */
+#define	EISA_VPD_UNIQUEID1	0xC92	/* READ: Unique Identifier #1 */
+#define	EISA_VPD_MANU_YEAR	0xC98	/* READ: Year Of Manufacture (0 = 1970) */
+#define	EISA_VPD_MANU_WEEK	0xC9A	/* READ: Week Of Manufacture (0 = week 1 Jan) */
+#define	EISA_MEM_ADDR_23_16	0xC00
+#define	EISA_MEM_ADDR_31_24	0xC01
+#define	EISA_RIO_CONFIG		0xC02	/* WRITE: Configuration Register */
+#define	EISA_RIO_INTSET		0xC03	/* WRITE: Interrupt Set */
+#define	EISA_RIO_INTRESET	0xC03	/* READ:  Interrupt Reset */
+
+/* Control Register Definitions... */
+#define	RIO_EISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
+#define	RIO_EISA_CFG_LINK20	0x02	/* 20Mbps link, else 10Mbps */
+#define	RIO_EISA_CFG_BUSENABLE	0x04	/* Enable processor bus */
+#define	RIO_EISA_CFG_PROCRUN	0x08	/* Processor running, else reset */
+#define	RIO_EISA_CFG_IRQMASK	0xF0	/* Interrupt mask */
+#define	  RIO_EISA_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
+#define	  RIO_EISA_CFG_IRQ14	0xE0	/* Interrupt Level 14 */
+#define	  RIO_EISA_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
+#define	  RIO_EISA_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
+#define	  RIO_EISA_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
+#define	  RIO_EISA_CFG_IRQ9	0x90	/* Interrupt Level 9 */
+#define	  RIO_EISA_CFG_IRQ7	0x70	/* Interrupt Level 7 */
+#define	  RIO_EISA_CFG_IRQ6	0x60	/* Interrupt Level 6 */
+#define	  RIO_EISA_CFG_IRQ5	0x50	/* Interrupt Level 5 */
+#define	  RIO_EISA_CFG_IRQ4	0x40	/* Interrupt Level 4 */
+#define	  RIO_EISA_CFG_IRQ3	0x30	/* Interrupt Level 3 */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   RIO SBus   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_SBUS_IDENT	"JBPGK#\0\0\0\0\0\0\0\0\0\0"
+
+#define	RIO_SBUS_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
+#define	RIO_SBUS_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_SBUS_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
+#define	RIO_SBUS_CFG_IRQMASK	0x38	/* Interrupt mask */
+#define	  RIO_SBUS_CFG_IRQNONE	0x00	/* No Interrupt */
+#define	  RIO_SBUS_CFG_IRQ7	0x38	/* Interrupt Level 7 */
+#define	  RIO_SBUS_CFG_IRQ6	0x30	/* Interrupt Level 6 */
+#define	  RIO_SBUS_CFG_IRQ5	0x28	/* Interrupt Level 5 */
+#define	  RIO_SBUS_CFG_IRQ4	0x20	/* Interrupt Level 4 */
+#define	  RIO_SBUS_CFG_IRQ3	0x18	/* Interrupt Level 3 */
+#define	  RIO_SBUS_CFG_IRQ2	0x10	/* Interrupt Level 2 */
+#define	  RIO_SBUS_CFG_IRQ1	0x08	/* Interrupt Level 1 */
+#define	RIO_SBUS_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
+#define	RIO_SBUS_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
+
+/*****************************************************************************
+*********************************             ********************************
+*********************************   RIO PCI   ********************************
+*********************************             ********************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_PCI_IDENT	"ECDDPGJGJHJRGSK#"
+
+#define	RIO_PCI_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
+#define	RIO_PCI_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_PCI_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
+#define	RIO_PCI_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
+#define	RIO_PCI_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
+
+/* PCI Definitions... */
+#define	SPX_VENDOR_ID		0x11CB	/* Assigned by the PCI SIG */
+#define	SPX_DEVICE_ID		0x8000	/* RIO bridge boards */
+#define	SPX_PLXDEVICE_ID	0x2000	/* PLX bridge boards */
+#define	SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
+#define	RIO_SUB_SYS_ID		0x0800	/* RIO PCI board */
+
+/*****************************************************************************
+*****************************                   ******************************
+*****************************   RIO (Jet) PCI   ******************************
+*****************************                   ******************************
+*****************************************************************************/
+
+/* Control Register Definitions... */
+#define	RIO_PCI2_IDENT	"JET HOST BY KEV#"
+
+#define	RIO_PCI2_CFG_BUSENABLE	0x02	/* Enable processor bus */
+#define	RIO_PCI2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
+
+/* PCI Definitions... */
+#define	RIO2_SUB_SYS_ID		0x0100	/* RIO (Jet) PCI board */
+
+#endif						/*_rioboard_h */
+
+/* End of RIOBOARD.H */
diff --git a/drivers/staging/generic_serial/rio/rioboot.c b/drivers/staging/generic_serial/rio/rioboot.c
new file mode 100644
index 0000000..d956dd3
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioboot.c
@@ -0,0 +1,1113 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioboot.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:36
+**	Retrieved	: 11/6/98 10:33:48
+**
+**  ident @(#)rioboot.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/termios.h>
+#include <linux/serial.h>
+#include <linux/vmalloc.h>
+#include <linux/generic_serial.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+
+static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP);
+
+static const unsigned char RIOAtVec2Ctrl[] = {
+	/* 0 */ INTERRUPT_DISABLE,
+	/* 1 */ INTERRUPT_DISABLE,
+	/* 2 */ INTERRUPT_DISABLE,
+	/* 3 */ INTERRUPT_DISABLE,
+	/* 4 */ INTERRUPT_DISABLE,
+	/* 5 */ INTERRUPT_DISABLE,
+	/* 6 */ INTERRUPT_DISABLE,
+	/* 7 */ INTERRUPT_DISABLE,
+	/* 8 */ INTERRUPT_DISABLE,
+	/* 9 */ IRQ_9 | INTERRUPT_ENABLE,
+	/* 10 */ INTERRUPT_DISABLE,
+	/* 11 */ IRQ_11 | INTERRUPT_ENABLE,
+	/* 12 */ IRQ_12 | INTERRUPT_ENABLE,
+	/* 13 */ INTERRUPT_DISABLE,
+	/* 14 */ INTERRUPT_DISABLE,
+	/* 15 */ IRQ_15 | INTERRUPT_ENABLE
+};
+
+/**
+ *	RIOBootCodeRTA		-	Load RTA boot code
+ *	@p: RIO to load
+ *	@rbp: Download descriptor
+ *
+ *	Called when the user process initiates booting of the card firmware.
+ *	Lads the firmware
+ */
+
+int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp)
+{
+	int offset;
+
+	func_enter();
+
+	rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP);
+
+	/*
+	 ** Check that we have set asside enough memory for this
+	 */
+	if (rbp->Count > SIXTY_FOUR_K) {
+		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n");
+		p->RIOError.Error = HOST_FILE_TOO_LARGE;
+		func_exit();
+		return -ENOMEM;
+	}
+
+	if (p->RIOBooting) {
+		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n");
+		p->RIOError.Error = BOOT_IN_PROGRESS;
+		func_exit();
+		return -EBUSY;
+	}
+
+	/*
+	 ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
+	 ** so calculate how far we have to move the data up the buffer
+	 ** to achieve this.
+	 */
+	offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE;
+
+	/*
+	 ** Be clean, and clear the 'unused' portion of the boot buffer,
+	 ** because it will (eventually) be part of the Rta run time environment
+	 ** and so should be zeroed.
+	 */
+	memset(p->RIOBootPackets, 0, offset);
+
+	/*
+	 ** Copy the data from user space into the array
+	 */
+
+	if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) {
+		rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n");
+		p->RIOError.Error = COPYIN_FAILED;
+		func_exit();
+		return -EFAULT;
+	}
+
+	/*
+	 ** Make sure that our copy of the size includes that offset we discussed
+	 ** earlier.
+	 */
+	p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE;
+	p->RIOBootCount = rbp->Count;
+
+	func_exit();
+	return 0;
+}
+
+/**
+ *	rio_start_card_running		-	host card start
+ *	@HostP: The RIO to kick off
+ *
+ *	Start a RIO processor unit running. Encapsulates the knowledge
+ *	of the card type.
+ */
+
+void rio_start_card_running(struct Host *HostP)
+{
+	switch (HostP->Type) {
+	case RIO_AT:
+		rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n");
+		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control);
+		break;
+	case RIO_PCI:
+		/*
+		 ** PCI is much the same as MCA. Everything is once again memory
+		 ** mapped, so we are writing to memory registers instead of io
+		 ** ports.
+		 */
+		rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n");
+		writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control);
+		break;
+	default:
+		rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type);
+		break;
+	}
+	return;
+}
+
+/*
+** Load in the host boot code - load it directly onto all halted hosts
+** of the correct type.
+**
+** Put your rubber pants on before messing with this code - even the magic
+** numbers have trouble understanding what they are doing here.
+*/
+
+int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp)
+{
+	struct Host *HostP;
+	u8 __iomem *Cad;
+	PARM_MAP __iomem *ParmMapP;
+	int RupN;
+	int PortN;
+	unsigned int host;
+	u8 __iomem *StartP;
+	u8 __iomem *DestP;
+	int wait_count;
+	u16 OldParmMap;
+	u16 offset;		/* It is very important that this is a u16 */
+	u8 *DownCode = NULL;
+	unsigned long flags;
+
+	HostP = NULL;		/* Assure the compiler we've initialized it */
+
+
+	/* Walk the hosts */
+	for (host = 0; host < p->RIONumHosts; host++) {
+		rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host);
+		HostP = &p->RIOHosts[host];
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
+
+		/* Don't boot hosts already running */
+		if ((HostP->Flags & RUN_STATE) != RC_WAITING) {
+			rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host);
+			continue;
+		}
+
+		/*
+		 ** Grab a pointer to the card (ioremapped)
+		 */
+		Cad = HostP->Caddr;
+
+		/*
+		 ** We are going to (try) and load in rbp->Count bytes.
+		 ** The last byte will reside at p->RIOConf.HostLoadBase-1;
+		 ** Therefore, we need to start copying at address
+		 ** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
+		 */
+		StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count];
+
+		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad);
+		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP);
+		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
+		rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count);
+
+		/* Make sure it fits */
+		if (p->RIOConf.HostLoadBase < rbp->Count) {
+			rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n");
+			p->RIOError.Error = HOST_FILE_TOO_LARGE;
+			func_exit();
+			return -EFBIG;
+		}
+		/*
+		 ** Ensure that the host really is stopped.
+		 ** Disable it's external bus & twang its reset line.
+		 */
+		RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot);
+
+		/*
+		 ** Copy the data directly from user space to the SRAM.
+		 ** This ain't going to be none too clever if the download
+		 ** code is bigger than this segment.
+		 */
+		rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n");
+
+		/* Buffer to local memory as we want to use I/O space and
+		   some cards only do 8 or 16 bit I/O */
+
+		DownCode = vmalloc(rbp->Count);
+		if (!DownCode) {
+			p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
+			func_exit();
+			return -ENOMEM;
+		}
+		if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) {
+			kfree(DownCode);
+			p->RIOError.Error = COPYIN_FAILED;
+			func_exit();
+			return -EFAULT;
+		}
+		HostP->Copy(DownCode, StartP, rbp->Count);
+		vfree(DownCode);
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n");
+
+		/*
+		 **                     S T O P !
+		 **
+		 ** Upto this point the code has been fairly rational, and possibly
+		 ** even straight forward. What follows is a pile of crud that will
+		 ** magically turn into six bytes of transputer assembler. Normally
+		 ** you would expect an array or something, but, being me, I have
+		 ** chosen [been told] to use a technique whereby the startup code
+		 ** will be correct if we change the loadbase for the code. Which
+		 ** brings us onto another issue - the loadbase is the *end* of the
+		 ** code, not the start.
+		 **
+		 ** If I were you I wouldn't start from here.
+		 */
+
+		/*
+		 ** We now need to insert a short boot section into
+		 ** the memory at the end of Sram2. This is normally (de)composed
+		 ** of the last eight bytes of the download code. The
+		 ** download has been assembled/compiled to expect to be
+		 ** loaded from 0x7FFF downwards. We have loaded it
+		 ** at some other address. The startup code goes into the small
+		 ** ram window at Sram2, in the last 8 bytes, which are really
+		 ** at addresses 0x7FF8-0x7FFF.
+		 **
+		 ** If the loadbase is, say, 0x7C00, then we need to branch to
+		 ** address 0x7BFE to run the host.bin startup code. We assemble
+		 ** this jump manually.
+		 **
+		 ** The two byte sequence 60 08 is loaded into memory at address
+		 ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
+		 ** which adds '0' to the .O register, complements .O, and then shifts
+		 ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
+		 ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
+		 ** location. Now, the branch starts from the value of .PC (or .IP or
+		 ** whatever the bloody register is called on this chip), and the .PC
+		 ** will be pointing to the location AFTER the branch, in this case
+		 ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
+		 **
+		 ** A long branch is coded at 0x7FF8. This consists of loading a four
+		 ** byte offset into .O using nfix (as above) and pfix operators. The
+		 ** pfix operates in exactly the same way as the nfix operator, but
+		 ** without the complement operation. The offset, of course, must be
+		 ** relative to the address of the byte AFTER the branch instruction,
+		 ** which will be (urm) 0x7FFC, so, our final destination of the branch
+		 ** (loadbase-2), has to be reached from here. Imagine that the loadbase
+		 ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
+		 ** is the first byte of the initial two byte short local branch of the
+		 ** download code).
+		 **
+		 ** To code a jump from 0x7FFC (which is where the branch will start
+		 ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
+		 ** 0x7BFE.
+		 ** This will be coded as four bytes:
+		 ** 60 2C 20 02
+		 ** being nfix .O+0
+		 **        pfix .O+C
+		 **        pfix .O+0
+		 **        jump .O+2
+		 **
+		 ** The nfix operator is used, so that the startup code will be
+		 ** compatible with the whole Tp family. (lies, damn lies, it'll never
+		 ** work in a month of Sundays).
+		 **
+		 ** The nfix nyble is the 1s complement of the nyble value you
+		 ** want to load - in this case we wanted 'F' so we nfix loaded '0'.
+		 */
+
+
+		/*
+		 ** Dest points to the top 8 bytes of Sram2. The Tp jumps
+		 ** to 0x7FFE at reset time, and starts executing. This is
+		 ** a short branch to 0x7FF8, where a long branch is coded.
+		 */
+
+		DestP = &Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
+
+#define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
+#define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
+#define	JUMP(N)	(0x00 | (N))	/* .PC =   .PC + .O      */
+
+		/*
+		 ** 0x7FFC is the address of the location following the last byte of
+		 ** the four byte jump instruction.
+		 ** READ THE ABOVE COMMENTS
+		 **
+		 ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
+		 ** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
+		 ** cos I don't understand 2's complement).
+		 */
+		offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC;
+
+		writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP);
+		writeb(PFIX((offset >> 8) & 0xF), DestP + 1);
+		writeb(PFIX((offset >> 4) & 0xF), DestP + 2);
+		writeb(JUMP(offset & 0xF), DestP + 3);
+
+		writeb(NFIX(0), DestP + 6);
+		writeb(JUMP(8), DestP + 7);
+
+		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
+		rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset);
+
+		/*
+		 ** Flag what is going on
+		 */
+		HostP->Flags &= ~RUN_STATE;
+		HostP->Flags |= RC_STARTUP;
+
+		/*
+		 ** Grab a copy of the current ParmMap pointer, so we
+		 ** can tell when it has changed.
+		 */
+		OldParmMap = readw(&HostP->__ParmMapR);
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap);
+
+		/*
+		 ** And start it running (I hope).
+		 ** As there is nothing dodgy or obscure about the
+		 ** above code, this is guaranteed to work every time.
+		 */
+		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
+
+		rio_start_card_running(HostP);
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n");
+
+		/*
+		 ** Now, wait for upto five seconds for the Tp to setup the parmmap
+		 ** pointer:
+		 */
+		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) {
+			rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR));
+			mdelay(100);
+
+		}
+
+		/*
+		 ** If the parmmap pointer is unchanged, then the host code
+		 ** has crashed & burned in a really spectacular way
+		 */
+		if (readw(&HostP->__ParmMapR) == OldParmMap) {
+			rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR));
+			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n");
+			HostP->Flags &= ~RUN_STATE;
+			HostP->Flags |= RC_STUFFED;
+			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
+			continue;
+		}
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR));
+
+		/*
+		 ** Well, the board thought it was OK, and setup its parmmap
+		 ** pointer. For the time being, we will pretend that this
+		 ** board is running, and check out what the error flag says.
+		 */
+
+		/*
+		 ** Grab a 32 bit pointer to the parmmap structure
+		 */
+		ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR));
+		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
+		ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR));
+		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
+
+		/*
+		 ** The links entry should be 0xFFFF; we set it up
+		 ** with a mask to say how many PHBs to use, and
+		 ** which links to use.
+		 */
+		if (readw(&ParmMapP->links) != 0xFFFF) {
+			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
+			rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links));
+			HostP->Flags &= ~RUN_STATE;
+			HostP->Flags |= RC_STUFFED;
+			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
+			continue;
+		}
+
+		writew(RIO_LINK_ENABLE, &ParmMapP->links);
+
+		/*
+		 ** now wait for the card to set all the parmmap->XXX stuff
+		 ** this is a wait of upto two seconds....
+		 */
+		rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime);
+		HostP->timeout_id = 0;
+		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) {
+			rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n");
+			mdelay(100);
+		}
+		rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n");
+
+		if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) {
+			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
+			rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n");
+			HostP->Flags &= ~RUN_STATE;
+			HostP->Flags |= RC_STUFFED;
+			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
+			continue;
+		}
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n");
+
+		/*
+		 ** It runs! It runs!
+		 */
+		rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum);
+
+		/*
+		 ** set the time period between interrupts.
+		 */
+		writew(p->RIOConf.Timer, &ParmMapP->timer);
+
+		/*
+		 ** Translate all the 16 bit pointers in the __ParmMapR into
+		 ** 32 bit pointers for the driver in ioremap space.
+		 */
+		HostP->ParmMapP = ParmMapP;
+		HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr));
+		HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups));
+		HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr));
+		HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr));
+
+		/*
+		 ** point the UnixRups at the real Rups
+		 */
+		for (RupN = 0; RupN < MAX_RUP; RupN++) {
+			HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN];
+			HostP->UnixRups[RupN].Id = RupN + 1;
+			HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
+			spin_lock_init(&HostP->UnixRups[RupN].RupLock);
+		}
+
+		for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) {
+			HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup;
+			HostP->UnixRups[RupN + MAX_RUP].Id = 0;
+			HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT;
+			spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock);
+		}
+
+		/*
+		 ** point the PortP->Phbs at the real Phbs
+		 */
+		for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) {
+			if (p->RIOPortp[PortN]->HostP == HostP) {
+				struct Port *PortP = p->RIOPortp[PortN];
+				struct PHB __iomem *PhbP;
+				/* int oldspl; */
+
+				if (!PortP->Mapped)
+					continue;
+
+				PhbP = &HostP->PhbP[PortP->HostPort];
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+				PortP->PhbP = PhbP;
+
+				PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add));
+				PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start));
+				PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end));
+				PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove));
+				PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start));
+				PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end));
+
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				/*
+				 ** point the UnixRup at the base SysPort
+				 */
+				if (!(PortN % PORTS_PER_RTA))
+					HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
+			}
+		}
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n");
+		/*
+		 ** last thing - show the world that everything is in place
+		 */
+		HostP->Flags &= ~RUN_STATE;
+		HostP->Flags |= RC_RUNNING;
+	}
+	/*
+	 ** MPX always uses a poller. This is actually patched into the system
+	 ** configuration and called directly from each clock tick.
+	 **
+	 */
+	p->RIOPolling = 1;
+
+	p->RIOSystemUp++;
+
+	rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec);
+	func_exit();
+	return 0;
+}
+
+
+
+/**
+ *	RIOBootRup		-	Boot an RTA
+ *	@p: rio we are working with
+ *	@Rup: Rup number
+ *	@HostP: host object
+ *	@PacketP: packet to use
+ *
+ *	If we have successfully processed this boot, then
+ *	return 1. If we havent, then return 0.
+ */
+
+int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP)
+{
+	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
+	struct PktCmd_M *PktReplyP;
+	struct CmdBlk *CmdBlkP;
+	unsigned int sequence;
+
+	/*
+	 ** If we haven't been told what to boot, we can't boot it.
+	 */
+	if (p->RIONumBootPkts == 0) {
+		rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n");
+		return 0;
+	}
+
+	/*
+	 ** Special case of boot completed - if we get one of these then we
+	 ** don't need a command block. For all other cases we do, so handle
+	 ** this first and then get a command block, then handle every other
+	 ** case, relinquishing the command block if disaster strikes!
+	 */
+	if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED))
+		return RIOBootComplete(p, HostP, Rup, PktCmdP);
+
+	/*
+	 ** Try to allocate a command block. This is in kernel space
+	 */
+	if (!(CmdBlkP = RIOGetCmdBlk())) {
+		rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n");
+		return 0;
+	}
+
+	/*
+	 ** Fill in the default info on the command block
+	 */
+	CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit = 0;
+	CmdBlkP->Packet.src_port = BOOT_RUP;
+
+	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
+
+	/*
+	 ** process COMMANDS on the boot rup!
+	 */
+	if (readb(&PacketP->len) & PKT_CMD_BIT) {
+		/*
+		 ** We only expect one type of command - a BOOT_REQUEST!
+		 */
+		if (readb(&PktCmdP->Command) != BOOT_REQUEST) {
+			rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts);
+			RIOFreeCmdBlk(CmdBlkP);
+			return 1;
+		}
+
+		/*
+		 ** Build a Boot Sequence command block
+		 **
+		 ** We no longer need to use "Boot Mode", we'll always allow
+		 ** boot requests - the boot will not complete if the device
+		 ** appears in the bindings table.
+		 **
+		 ** We'll just (always) set the command field in packet reply
+		 ** to allow an attempted boot sequence :
+		 */
+		PktReplyP->Command = BOOT_SEQUENCE;
+
+		PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
+		PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase;
+		PktReplyP->BootSequence.CodeSize = p->RIOBootCount;
+
+		CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
+
+		memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4);
+
+		rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase);
+
+		/*
+		 ** If this host is in slave mode, send the RTA an invalid boot
+		 ** sequence command block to force it to kill the boot. We wait
+		 ** for half a second before sending this packet to prevent the RTA
+		 ** attempting to boot too often. The master host should then grab
+		 ** the RTA and make it its own.
+		 */
+		p->RIOBooting++;
+		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+		return 1;
+	}
+
+	/*
+	 ** It is a request for boot data.
+	 */
+	sequence = readw(&PktCmdP->Sequence);
+
+	rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup);
+
+	if (sequence >= p->RIONumBootPkts) {
+		rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts);
+	}
+
+	PktReplyP->Sequence = sequence;
+	memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE);
+	CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
+	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+	return 1;
+}
+
+/**
+ *	RIOBootComplete		-	RTA boot is done
+ *	@p: RIO we are working with
+ *	@HostP: Host structure
+ *	@Rup: RUP being used
+ *	@PktCmdP: Packet command that was used
+ *
+ *	This function is called when an RTA been booted.
+ *	If booted by a host, HostP->HostUniqueNum is the booting host.
+ *	If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
+ *	RtaUniq is the booted RTA.
+ */
+
+static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP)
+{
+	struct Map *MapP = NULL;
+	struct Map *MapP2 = NULL;
+	int Flag;
+	int found;
+	int host, rta;
+	int EmptySlot = -1;
+	int entry, entry2;
+	char *MyType, *MyName;
+	unsigned int MyLink;
+	unsigned short RtaType;
+	u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
+
+	p->RIOBooting = 0;
+
+	rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting);
+
+	/*
+	 ** Determine type of unit (16/8 port RTA).
+	 */
+
+	RtaType = GetUnitType(RtaUniq);
+	if (Rup >= (unsigned short) MAX_RUP)
+		rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
+	else
+		rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
+
+	rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq);
+
+	if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) {
+		rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n");
+		return 1;
+	}
+
+	/*
+	 ** If this RTA has just booted an RTA which doesn't belong to this
+	 ** system, or the system is in slave mode, do not attempt to create
+	 ** a new table entry for it.
+	 */
+
+	if (!RIOBootOk(p, HostP, RtaUniq)) {
+		MyLink = readb(&PktCmdP->LinkNum);
+		if (Rup < (unsigned short) MAX_RUP) {
+			/*
+			 ** RtaUniq was clone booted (by this RTA). Instruct this RTA
+			 ** to hold off further attempts to boot on this link for 30
+			 ** seconds.
+			 */
+			if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) {
+				rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink);
+			}
+		} else
+			/*
+			 ** RtaUniq was booted by this host. Set the booting link
+			 ** to hold off for 30 seconds to give another unit a
+			 ** chance to boot it.
+			 */
+			writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot);
+		rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum);
+		return 1;
+	}
+
+	/*
+	 ** Check for a SLOT_IN_USE entry for this RTA attached to the
+	 ** current host card in the driver table.
+	 **
+	 ** If it exists, make a note that we have booted it. Other parts of
+	 ** the driver are interested in this information at a later date,
+	 ** in particular when the booting RTA asks for an ID for this unit,
+	 ** we must have set the BOOTED flag, and the NEWBOOT flag is used
+	 ** to force an open on any ports that where previously open on this
+	 ** unit.
+	 */
+	for (entry = 0; entry < MAX_RUP; entry++) {
+		unsigned int sysport;
+
+		if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
+			HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT;
+			if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) {
+				if (sysport < p->RIOFirstPortsBooted)
+					p->RIOFirstPortsBooted = sysport;
+				if (sysport > p->RIOLastPortsBooted)
+					p->RIOLastPortsBooted = sysport;
+				/*
+				 ** For a 16 port RTA, check the second bank of 8 ports
+				 */
+				if (RtaType == TYPE_RTA16) {
+					entry2 = HostP->Mapping[entry].ID2 - 1;
+					HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT;
+					sysport = HostP->Mapping[entry2].SysPort;
+					if (sysport < p->RIOFirstPortsBooted)
+						p->RIOFirstPortsBooted = sysport;
+					if (sysport > p->RIOLastPortsBooted)
+						p->RIOLastPortsBooted = sysport;
+				}
+			}
+			if (RtaType == TYPE_RTA16)
+				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1);
+			else
+				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1);
+			return 1;
+		}
+	}
+
+	rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n");
+
+	if (Rup >= (unsigned short) MAX_RUP) {
+		/*
+		 ** It was a host that did the booting
+		 */
+		MyType = "Host";
+		MyName = HostP->Name;
+	} else {
+		/*
+		 ** It was an RTA that did the booting
+		 */
+		MyType = "RTA";
+		MyName = HostP->Mapping[Rup].Name;
+	}
+	MyLink = readb(&PktCmdP->LinkNum);
+
+	/*
+	 ** There is no SLOT_IN_USE entry for this RTA attached to the current
+	 ** host card in the driver table.
+	 **
+	 ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
+	 ** current host card in the driver table.
+	 **
+	 ** If we find one, then we re-use that slot.
+	 */
+	for (entry = 0; entry < MAX_RUP; entry++) {
+		if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
+			if (RtaType == TYPE_RTA16) {
+				entry2 = HostP->Mapping[entry].ID2 - 1;
+				if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq))
+					rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2);
+				else
+					continue;
+			} else
+				rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry);
+			if (!p->RIONoMessage)
+				printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
+			return 1;
+		}
+	}
+
+	/*
+	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	 ** attached to the current host card in the driver table.
+	 **
+	 ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
+	 ** host for this RTA in the driver table.
+	 **
+	 ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
+	 ** entry from the other host and add it to this host (using some of
+	 ** the functions from table.c which do this).
+	 ** For a SLOT_TENTATIVE entry on another host, we must cope with the
+	 ** following scenario:
+	 **
+	 ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
+	 **   in table)
+	 ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
+	 **   entries)
+	 ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
+	 ** + Unplug RTA and plug back into host A.
+	 ** + Configure RTA on host A. We now have the same RTA configured
+	 **   with different ports on two different hosts.
+	 */
+	rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq);
+	found = 0;
+	Flag = 0;		/* Convince the compiler this variable is initialized */
+	for (host = 0; !found && (host < p->RIONumHosts); host++) {
+		for (rta = 0; rta < MAX_RUP; rta++) {
+			if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) {
+				Flag = p->RIOHosts[host].Mapping[rta].Flags;
+				MapP = &p->RIOHosts[host].Mapping[rta];
+				if (RtaType == TYPE_RTA16) {
+					MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
+					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name);
+				} else
+					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name);
+				found = 1;
+				break;
+			}
+		}
+	}
+
+	/*
+	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	 ** attached to the current host card in the driver table.
+	 **
+	 ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
+	 ** another host for this RTA in the driver table...
+	 **
+	 ** Check for a SLOT_IN_USE entry for this RTA in the config table.
+	 */
+	if (!MapP) {
+		rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq);
+		for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) {
+			rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum);
+
+			if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) {
+				MapP = &p->RIOSavedTable[rta];
+				Flag = p->RIOSavedTable[rta].Flags;
+				if (RtaType == TYPE_RTA16) {
+					for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) {
+						if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
+							break;
+					}
+					MapP2 = &p->RIOSavedTable[entry2];
+					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2);
+				} else
+					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta);
+				break;
+			}
+		}
+	}
+
+	/*
+	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	 ** attached to the current host card in the driver table.
+	 **
+	 ** We may have found a SLOT_IN_USE entry on another host for this
+	 ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
+	 ** on another host for this RTA in the driver table.
+	 **
+	 ** Check the driver table for room to fit this newly discovered RTA.
+	 ** RIOFindFreeID() first looks for free slots and if it does not
+	 ** find any free slots it will then attempt to oust any
+	 ** tentative entry in the table.
+	 */
+	EmptySlot = 1;
+	if (RtaType == TYPE_RTA16) {
+		if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) {
+			RIODefaultName(p, HostP, entry);
+			rio_fill_host_slot(entry, entry2, RtaUniq, HostP);
+			EmptySlot = 0;
+		}
+	} else {
+		if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) {
+			RIODefaultName(p, HostP, entry);
+			rio_fill_host_slot(entry, 0, RtaUniq, HostP);
+			EmptySlot = 0;
+		}
+	}
+
+	/*
+	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
+	 ** attached to the current host card in the driver table.
+	 **
+	 ** If we found a SLOT_IN_USE entry on another host for this
+	 ** RTA in the config or driver table, and there are enough free
+	 ** slots in the driver table, then we need to move it over and
+	 ** delete it from the other host.
+	 ** If we found a SLOT_TENTATIVE entry on another host for this
+	 ** RTA in the driver table, just delete the other host entry.
+	 */
+	if (EmptySlot == 0) {
+		if (MapP) {
+			if (Flag & SLOT_IN_USE) {
+				rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n");
+				HostP->Mapping[entry].SysPort = MapP->SysPort;
+				memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN);
+				HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
+				RIOReMapPorts(p, HostP, &HostP->Mapping[entry]);
+				if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted)
+					p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
+				if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted)
+					p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
+				rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name);
+			} else {
+				rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n");
+				HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
+			}
+			if (RtaType == TYPE_RTA16) {
+				if (Flag & SLOT_IN_USE) {
+					HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
+					HostP->Mapping[entry2].SysPort = MapP2->SysPort;
+					/*
+					 ** Map second block of ttys for 16 port RTA
+					 */
+					RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]);
+					if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
+						p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
+					if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
+						p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
+					rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name);
+				} else
+					HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
+				memset(MapP2, 0, sizeof(struct Map));
+			}
+			memset(MapP, 0, sizeof(struct Map));
+			if (!p->RIONoMessage)
+				printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A');
+		} else if (!p->RIONoMessage)
+			printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
+		RIOSetChange(p);
+		return 1;
+	}
+
+	/*
+	 ** There is no room in the driver table to make an entry for the
+	 ** booted RTA. Keep a note of its Uniq Num in the overflow table,
+	 ** so we can ignore it's ID requests.
+	 */
+	if (!p->RIONoMessage)
+		printk("The RTA connected to %s '%s' (%c) cannot be configured.  You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A');
+	for (entry = 0; entry < HostP->NumExtraBooted; entry++) {
+		if (HostP->ExtraUnits[entry] == RtaUniq) {
+			/*
+			 ** already got it!
+			 */
+			return 1;
+		}
+	}
+	/*
+	 ** If there is room, add the unit to the list of extras
+	 */
+	if (HostP->NumExtraBooted < MAX_EXTRA_UNITS)
+		HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
+	return 1;
+}
+
+
+/*
+** If the RTA or its host appears in the RIOBindTab[] structure then
+** we mustn't boot the RTA and should return 0.
+** This operation is slightly different from the other drivers for RIO
+** in that this is designed to work with the new utilities
+** not config.rio and is FAR SIMPLER.
+** We no longer support the RIOBootMode variable. It is all done from the
+** "boot/noboot" field in the rio.cf file.
+*/
+int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq)
+{
+	int Entry;
+	unsigned int HostUniq = HostP->UniqueNum;
+
+	/*
+	 ** Search bindings table for RTA or its parent.
+	 ** If it exists, return 0, else 1.
+	 */
+	for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) {
+		if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq))
+			return 0;
+	}
+	return 1;
+}
+
+/*
+** Make an empty slot tentative. If this is a 16 port RTA, make both
+** slots tentative, and the second one RTA_SECOND_SLOT as well.
+*/
+
+void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host)
+{
+	int link;
+
+	rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq);
+
+	host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
+	host->Mapping[entry].SysPort = NO_PORT;
+	host->Mapping[entry].RtaUniqueNum = rta_uniq;
+	host->Mapping[entry].HostUniqueNum = host->UniqueNum;
+	host->Mapping[entry].ID = entry + 1;
+	host->Mapping[entry].ID2 = 0;
+	if (entry2) {
+		host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT);
+		host->Mapping[entry2].SysPort = NO_PORT;
+		host->Mapping[entry2].RtaUniqueNum = rta_uniq;
+		host->Mapping[entry2].HostUniqueNum = host->UniqueNum;
+		host->Mapping[entry2].Name[0] = '\0';
+		host->Mapping[entry2].ID = entry2 + 1;
+		host->Mapping[entry2].ID2 = entry + 1;
+		host->Mapping[entry].ID2 = entry2 + 1;
+	}
+	/*
+	 ** Must set these up, so that utilities show
+	 ** topology of 16 port RTAs correctly
+	 */
+	for (link = 0; link < LINKS_PER_UNIT; link++) {
+		host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
+		host->Mapping[entry].Topology[link].Link = NO_LINK;
+		if (entry2) {
+			host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
+			host->Mapping[entry2].Topology[link].Link = NO_LINK;
+		}
+	}
+}
diff --git a/drivers/staging/generic_serial/rio/riocmd.c b/drivers/staging/generic_serial/rio/riocmd.c
new file mode 100644
index 0000000..f121357
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/riocmd.c
@@ -0,0 +1,939 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  ported from the existing SCO driver source
+**
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riocmd.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:41
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)riocmd.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+
+
+static struct IdentifyRta IdRta;
+static struct KillNeighbour KillUnit;
+
+int RIOFoadRta(struct Host *HostP, struct Map *MapP)
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if (!CmdBlkP) {
+		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = MapP->ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit = 0;
+	CmdBlkP->Packet.src_port = BOOT_RUP;
+	CmdBlkP->Packet.len = 0x84;
+	CmdBlkP->Packet.data[0] = IFOAD;
+	CmdBlkP->Packet.data[1] = 0;
+	CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
+
+	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+int RIOZombieRta(struct Host *HostP, struct Map *MapP)
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if (!CmdBlkP) {
+		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = MapP->ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit = 0;
+	CmdBlkP->Packet.src_port = BOOT_RUP;
+	CmdBlkP->Packet.len = 0x84;
+	CmdBlkP->Packet.data[0] = ZOMBIE;
+	CmdBlkP->Packet.data[1] = 0;
+	CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
+
+	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP))
+{
+	unsigned int Host;
+
+	rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func);
+
+	if (!RtaUnique)
+		return (0);
+
+	for (Host = 0; Host < p->RIONumHosts; Host++) {
+		unsigned int Rta;
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
+			struct Map *MapP = &HostP->Mapping[Rta];
+
+			if (MapP->RtaUniqueNum == RtaUnique) {
+				uint Link;
+
+				/*
+				 ** now, lets just check we have a route to it...
+				 ** IF the routing stuff is working, then one of the
+				 ** topology entries for this unit will have a legit
+				 ** route *somewhere*. We care not where - if its got
+				 ** any connections, we can get to it.
+				 */
+				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
+					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
+						/*
+						 ** Its worth trying the operation...
+						 */
+						return (*func) (HostP, MapP);
+					}
+				}
+			}
+		}
+	}
+	return -ENXIO;
+}
+
+
+int RIOIdentifyRta(struct rio_info *p, void __user * arg)
+{
+	unsigned int Host;
+
+	if (copy_from_user(&IdRta, arg, sizeof(IdRta))) {
+		rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
+		p->RIOError.Error = COPYIN_FAILED;
+		return -EFAULT;
+	}
+
+	for (Host = 0; Host < p->RIONumHosts; Host++) {
+		unsigned int Rta;
+		struct Host *HostP = &p->RIOHosts[Host];
+
+		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
+			struct Map *MapP = &HostP->Mapping[Rta];
+
+			if (MapP->RtaUniqueNum == IdRta.RtaUnique) {
+				uint Link;
+				/*
+				 ** now, lets just check we have a route to it...
+				 ** IF the routing stuff is working, then one of the
+				 ** topology entries for this unit will have a legit
+				 ** route *somewhere*. We care not where - if its got
+				 ** any connections, we can get to it.
+				 */
+				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
+					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
+						/*
+						 ** Its worth trying the operation...
+						 */
+						struct CmdBlk *CmdBlkP;
+
+						rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");
+
+						CmdBlkP = RIOGetCmdBlk();
+
+						if (!CmdBlkP) {
+							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
+							return -ENXIO;
+						}
+
+						CmdBlkP->Packet.dest_unit = MapP->ID;
+						CmdBlkP->Packet.dest_port = BOOT_RUP;
+						CmdBlkP->Packet.src_unit = 0;
+						CmdBlkP->Packet.src_port = BOOT_RUP;
+						CmdBlkP->Packet.len = 0x84;
+						CmdBlkP->Packet.data[0] = IDENTIFY;
+						CmdBlkP->Packet.data[1] = 0;
+						CmdBlkP->Packet.data[2] = IdRta.ID;
+
+						if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
+							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
+							return -EIO;
+						}
+						return 0;
+					}
+				}
+			}
+		}
+	}
+	return -ENOENT;
+}
+
+
+int RIOKillNeighbour(struct rio_info *p, void __user * arg)
+{
+	uint Host;
+	uint ID;
+	struct Host *HostP;
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
+
+	if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) {
+		rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
+		p->RIOError.Error = COPYIN_FAILED;
+		return -EFAULT;
+	}
+
+	if (KillUnit.Link > 3)
+		return -ENXIO;
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if (!CmdBlkP) {
+		rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = 0;
+	CmdBlkP->Packet.src_unit = 0;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_port = BOOT_RUP;
+	CmdBlkP->Packet.len = 0x84;
+	CmdBlkP->Packet.data[0] = UFOAD;
+	CmdBlkP->Packet.data[1] = KillUnit.Link;
+	CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
+
+	for (Host = 0; Host < p->RIONumHosts; Host++) {
+		ID = 0;
+		HostP = &p->RIOHosts[Host];
+
+		if (HostP->UniqueNum == KillUnit.UniqueNum) {
+			if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {
+				rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+				return -EIO;
+			}
+			return 0;
+		}
+
+		for (ID = 0; ID < RTAS_PER_HOST; ID++) {
+			if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {
+				CmdBlkP->Packet.dest_unit = ID + 1;
+				if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {
+					rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
+					return -EIO;
+				}
+				return 0;
+			}
+		}
+	}
+	RIOFreeCmdBlk(CmdBlkP);
+	return -ENXIO;
+}
+
+int RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
+{
+	struct CmdBlk *CmdBlkP;
+
+	rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
+
+	CmdBlkP = RIOGetCmdBlk();
+
+	if (!CmdBlkP) {
+		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
+		return -ENXIO;
+	}
+
+	CmdBlkP->Packet.dest_unit = ID;
+	CmdBlkP->Packet.dest_port = BOOT_RUP;
+	CmdBlkP->Packet.src_unit = 0;
+	CmdBlkP->Packet.src_port = BOOT_RUP;
+	CmdBlkP->Packet.len = 0x84;
+	CmdBlkP->Packet.data[0] = IWAIT;
+	CmdBlkP->Packet.data[1] = Link;
+	CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
+	CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
+
+	if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {
+		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+int RIOFoadWakeup(struct rio_info *p)
+{
+	int port;
+	struct Port *PortP;
+	unsigned long flags;
+
+	for (port = 0; port < RIO_PORTS; port++) {
+		PortP = p->RIOPortp[port];
+
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->Config = 0;
+		PortP->State = 0;
+		PortP->InUse = NOT_INUSE;
+		PortP->PortState = 0;
+		PortP->FlushCmdBodge = 0;
+		PortP->ModemLines = 0;
+		PortP->ModemState = 0;
+		PortP->CookMode = 0;
+		PortP->ParamSem = 0;
+		PortP->Mapped = 0;
+		PortP->WflushFlag = 0;
+		PortP->MagicFlags = 0;
+		PortP->RxDataStart = 0;
+		PortP->TxBufferIn = 0;
+		PortP->TxBufferOut = 0;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	}
+	return (0);
+}
+
+/*
+** Incoming command on the COMMAND_RUP to be processed.
+*/
+static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP)
+{
+	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data;
+	struct Port *PortP;
+	struct UnixRup *UnixRupP;
+	unsigned short SysPort;
+	unsigned short ReportedModemStatus;
+	unsigned short rup;
+	unsigned short subCommand;
+	unsigned long flags;
+
+	func_enter();
+
+	/*
+	 ** 16 port RTA note:
+	 ** Command rup packets coming from the RTA will have pkt->data[1] (which
+	 ** translates to PktCmdP->PhbNum) set to the host port number for the
+	 ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
+	 ** we can use PhbNum to get the rup number for the appropriate 8 port
+	 ** block (for the first block, this should be equal to 'Rup').
+	 */
+	rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA;
+	UnixRupP = &HostP->UnixRups[rup];
+	SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA);
+	rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
+
+	if (UnixRupP->BaseSysPort == NO_PORT) {
+		rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
+		rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
+		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
+		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);
+
+		if (Rup < (unsigned short) MAX_RUP) {
+			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
+		} else
+			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
+
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum));
+		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command));
+		return 1;
+	}
+	PortP = p->RIOPortp[SysPort];
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	switch (readb(&PktCmdP->Command)) {
+	case RIOC_BREAK_RECEIVED:
+		rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
+		/* If the current line disc. is not multi-threading and
+		   the current processor is not the default, reset rup_intr
+		   and return 0 to ensure that the command packet is
+		   not freed. */
+		/* Call tmgr HANGUP HERE */
+		/* Fix this later when every thing works !!!! RAMRAJ */
+		gs_got_break(&PortP->gs);
+		break;
+
+	case RIOC_COMPLETE:
+		rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts);
+		subCommand = 1;
+		switch (readb(&PktCmdP->SubCommand)) {
+		case RIOC_MEMDUMP:
+			rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr));
+			break;
+		case RIOC_READ_REGISTER:
+			rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr));
+			p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST);
+			break;
+		default:
+			subCommand = 0;
+			break;
+		}
+		if (subCommand)
+			break;
+		rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState);
+		if (PortP->PortState != readb(&PktCmdP->PortStatus)) {
+			rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");
+			PortP->PortState = readb(&PktCmdP->PortStatus);
+			/* What should we do here ...
+			   wakeup( &PortP->PortState );
+			 */
+		} else
+			rio_dprintk(RIO_DEBUG_CMD, "No change\n");
+
+		/* FALLTHROUGH */
+	case RIOC_MODEM_STATUS:
+		/*
+		 ** Knock out the tbusy and tstop bits, as these are not relevant
+		 ** to the check for modem status change (they're just there because
+		 ** it's a convenient place to put them!).
+		 */
+		ReportedModemStatus = readb(&PktCmdP->ModemStatus);
+		if ((PortP->ModemState & RIOC_MSVR1_HOST) ==
+				(ReportedModemStatus & RIOC_MSVR1_HOST)) {
+			rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
+			/*
+			 ** Update ModemState just in case tbusy or tstop states have
+			 ** changed.
+			 */
+			PortP->ModemState = ReportedModemStatus;
+		} else {
+			rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);
+			PortP->ModemState = ReportedModemStatus;
+#ifdef MODEM_SUPPORT
+			if (PortP->Mapped) {
+				/***********************************************************\
+				*************************************************************
+				***													   ***
+				***		  M O D E M   S T A T E   C H A N G E		  ***
+				***													   ***
+				*************************************************************
+				\***********************************************************/
+				/*
+				 ** If the device is a modem, then check the modem
+				 ** carrier.
+				 */
+				if (PortP->gs.port.tty == NULL)
+					break;
+				if (PortP->gs.port.tty->termios == NULL)
+					break;
+
+				if (!(PortP->gs.port.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) {
+
+					rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n");
+					/*
+					 ** Is there a carrier?
+					 */
+					if (PortP->ModemState & RIOC_MSVR1_CD) {
+						/*
+						 ** Has carrier just appeared?
+						 */
+						if (!(PortP->State & RIO_CARR_ON)) {
+							rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n");
+							PortP->State |= RIO_CARR_ON;
+							/*
+							 ** wakeup anyone in WOPEN
+							 */
+							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN))
+								wake_up_interruptible(&PortP->gs.port.open_wait);
+						}
+					} else {
+						/*
+						 ** Has carrier just dropped?
+						 */
+						if (PortP->State & RIO_CARR_ON) {
+							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN))
+								tty_hangup(PortP->gs.port.tty);
+							PortP->State &= ~RIO_CARR_ON;
+							rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n");
+						}
+					}
+				}
+			}
+#endif
+		}
+		break;
+
+	default:
+		rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts);
+		break;
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	func_exit();
+
+	return 1;
+}
+
+/*
+** The command mechanism:
+**	Each rup has a chain of commands associated with it.
+**	This chain is maintained by routines in this file.
+**	Periodically we are called and we run a quick check of all the
+**	active chains to determine if there is a command to be executed,
+**	and if the rup is ready to accept it.
+**
+*/
+
+/*
+** Allocate an empty command block.
+*/
+struct CmdBlk *RIOGetCmdBlk(void)
+{
+	struct CmdBlk *CmdBlkP;
+
+	CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
+	return CmdBlkP;
+}
+
+/*
+** Return a block to the head of the free list.
+*/
+void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
+{
+	kfree(CmdBlkP);
+}
+
+/*
+** attach a command block to the list of commands to be performed for
+** a given rup.
+*/
+int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
+{
+	struct CmdBlk **Base;
+	struct UnixRup *UnixRupP;
+	unsigned long flags;
+
+	if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) {
+		rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
+		RIOFreeCmdBlk(CmdBlkP);
+		return RIO_FAIL;
+	}
+
+	UnixRupP = &HostP->UnixRups[Rup];
+
+	rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+
+	/*
+	 ** If the RUP is currently inactive, then put the request
+	 ** straight on the RUP....
+	 */
+	if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
+																	     : 1)) {
+		rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]);
+
+		/*
+		 ** Whammy! blat that pack!
+		 */
+		HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
+
+		/*
+		 ** place command packet on the pending position.
+		 */
+		UnixRupP->CmdPendingP = CmdBlkP;
+
+		/*
+		 ** set the command register
+		 */
+		writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
+
+		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+
+		return 0;
+	}
+	rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n");
+
+	if (UnixRupP->CmdsWaitingP != NULL)
+		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n");
+	if (UnixRupP->CmdPendingP != NULL)
+		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n");
+	if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE)
+		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
+
+	Base = &UnixRupP->CmdsWaitingP;
+
+	rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base);
+
+	while (*Base) {
+		rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base);
+		Base = &((*Base)->NextP);
+		rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base);
+	}
+
+	rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base);
+
+	*Base = CmdBlkP;
+
+	CmdBlkP->NextP = NULL;
+
+	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+
+	return 0;
+}
+
+/*
+** Here we go - if there is an empty rup, fill it!
+** must be called at splrio() or higher.
+*/
+void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
+{
+	struct CmdBlk *CmdBlkP;
+	struct UnixRup *UnixRupP;
+	struct PKT __iomem *PacketP;
+	unsigned short Rup;
+	unsigned long flags;
+
+
+	Rup = MAX_RUP + LINKS_PER_UNIT;
+
+	do {			/* do this loop for each RUP */
+		/*
+		 ** locate the rup we are processing & lock it
+		 */
+		UnixRupP = &HostP->UnixRups[--Rup];
+
+		spin_lock_irqsave(&UnixRupP->RupLock, flags);
+
+		/*
+		 ** First check for incoming commands:
+		 */
+		if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
+			int FreeMe;
+
+			PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));
+
+			switch (readb(&PacketP->dest_port)) {
+			case BOOT_RUP:
+				rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0]));
+				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+				FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
+				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+				break;
+
+			case COMMAND_RUP:
+				/*
+				 ** Free the RUP lock as loss of carrier causes a
+				 ** ttyflush which will (eventually) call another
+				 ** routine that uses the RUP lock.
+				 */
+				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+				FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
+				if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) {
+					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
+					rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
+				}
+				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+				break;
+
+			case ROUTE_RUP:
+				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+				FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
+				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+				break;
+
+			default:
+				rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port));
+				FreeMe = 1;
+				break;
+			}
+
+			if (FreeMe) {
+				rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
+				put_free_end(HostP, PacketP);
+
+				writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol);
+
+				if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
+					rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
+					writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake);
+				}
+			}
+		}
+
+		/*
+		 ** IF a command was running on the port,
+		 ** and it has completed, then tidy it up.
+		 */
+		if ((CmdBlkP = UnixRupP->CmdPendingP) &&	/* ASSIGN! */
+		    (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+			/*
+			 ** we are idle.
+			 ** there is a command in pending.
+			 ** Therefore, this command has finished.
+			 ** So, wakeup whoever is waiting for it (and tell them
+			 ** what happened).
+			 */
+			if (CmdBlkP->Packet.dest_port == BOOT_RUP)
+				rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);
+
+			rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP);
+
+			/*
+			 ** Clear the Rup lock to prevent mutual exclusion.
+			 */
+			if (CmdBlkP->PostFuncP) {
+				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
+				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
+			}
+
+			/*
+			 ** ....clear the pending flag....
+			 */
+			UnixRupP->CmdPendingP = NULL;
+
+			/*
+			 ** ....and return the command block to the freelist.
+			 */
+			RIOFreeCmdBlk(CmdBlkP);
+		}
+
+		/*
+		 ** If there is a command for this rup, and the rup
+		 ** is idle, then process the command
+		 */
+		if ((CmdBlkP = UnixRupP->CmdsWaitingP) &&	/* ASSIGN! */
+		    (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
+			/*
+			 ** if the pre-function is non-zero, call it.
+			 ** If it returns RIO_FAIL then don't
+			 ** send this command yet!
+			 */
+			if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) {
+				rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP);
+			} else {
+				rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]);
+				/*
+				 ** Whammy! blat that pack!
+				 */
+				HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
+
+				/*
+				 ** remove the command from the rup command queue...
+				 */
+				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
+
+				/*
+				 ** ...and place it on the pending position.
+				 */
+				UnixRupP->CmdPendingP = CmdBlkP;
+
+				/*
+				 ** set the command register
+				 */
+				writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
+
+				/*
+				 ** the command block will be freed
+				 ** when the command has been processed.
+				 */
+			}
+		}
+		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
+	} while (Rup);
+}
+
+int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP)
+{
+	struct Port *PortP = (struct Port *) iPortP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	PortP->WflushFlag++;
+	PortP->MagicFlags |= MAGIC_FLUSH;
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return RIOUnUse(iPortP, CmdBlkP);
+}
+
+int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP)
+{
+	struct Port *PortP = (struct Port *) iPortP;
+	struct PKT __iomem *PacketP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	while (can_remove_receive(&PacketP, PortP)) {
+		remove_receive(PortP);
+		put_free_end(PortP->HostP, PacketP);
+	}
+
+	if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) {
+		/*
+		 ** MAGIC! (Basically, handshake the RX buffer, so that
+		 ** the RTAs upstream can be re-enabled.)
+		 */
+		rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
+		writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
+	}
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return RIOUnUse(iPortP, CmdBlkP);
+}
+
+int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP)
+{
+	struct Port *PortP = (struct Port *) iPortP;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
+
+	if (PortP->InUse) {
+		if (--PortP->InUse != NOT_INUSE) {
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return 0;
+		}
+	}
+	/*
+	 ** While PortP->InUse is set (i.e. a preemptive command has been sent to
+	 ** the RTA and is awaiting completion), any transmit data is prevented from
+	 ** being transferred from the write queue into the transmit packets
+	 ** (add_transmit) and no furthur transmit interrupt will be sent for that
+	 ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
+	 ** twice a second as a saftey measure). This was the case when kermit was
+	 ** used to send data into a RIO port. After each packet was sent, TCFLSH
+	 ** was called to flush the read queue preemptively. PortP->InUse was
+	 ** incremented, thereby blocking the 6 byte acknowledgement packet
+	 ** transmitted back. This acknowledgment hung around for 500ms before
+	 ** being sent, thus reducing input performance substantially!.
+	 ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
+	 ** hanging around in the transmit buffer is sent immediately.
+	 */
+	writew(1, &PortP->HostP->ParmMapP->tx_intr);
+	/* What to do here ..
+	   wakeup( (caddr_t)&(PortP->InUse) );
+	 */
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return 0;
+}
+
+/*
+** 
+** How to use this file:
+** 
+** To send a command down a rup, you need to allocate a command block, fill
+** in the packet information, fill in the command number, fill in the pre-
+** and post- functions and arguments, and then add the command block to the
+** queue of command blocks for the port in question. When the port is idle,
+** then the pre-function will be called. If this returns RIO_FAIL then the
+** command will be re-queued and tried again at a later date (probably in one
+** clock tick). If the pre-function returns NOT RIO_FAIL, then the command
+** packet will be queued on the RUP, and the txcontrol field set to the
+** command number. When the txcontrol field has changed from being the
+** command number, then the post-function will be called, with the argument
+** specified earlier, a pointer to the command block, and the value of
+** txcontrol.
+** 
+** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer
+** to the command block structure allocated, or NULL if there aren't any.
+** The block will have been zeroed for you.
+** 
+** The structure has the following fields:
+** 
+** struct CmdBlk
+** {
+**	 struct CmdBlk *NextP;		  ** Pointer to next command block   **
+**	 struct PKT	 Packet;		** A packet, to copy to the rup	**
+**			int	 (*PreFuncP)();  ** The func to call to check if OK **
+**			int	 PreArg;		** The arg for the func			**
+**			int	 (*PostFuncP)(); ** The func to call when completed **
+**			int	 PostArg;	   ** The arg for the func			**
+** };
+** 
+** You need to fill in ALL fields EXCEPT NextP, which is used to link the
+** blocks together either on the free list or on the Rup list.
+** 
+** Packet is an actual packet structure to be filled in with the packet
+** information associated with the command. You need to fill in everything,
+** as the command processor doesn't process the command packet in any way.
+** 
+** The PreFuncP is called before the packet is enqueued on the host rup.
+** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
+** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL
+** if the packet is NOT to be queued.
+** 
+** The PostFuncP is called when the command has completed. It is called
+** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected
+** to return a value. PostFuncP does NOT need to free the command block,
+** as this happens automatically after PostFuncP returns.
+** 
+** Once the command block has been filled in, it is attached to the correct
+** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is
+** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer
+** to it!), and CmdBlkP is the pointer to the command block allocated using
+** RIOGetCmdBlk().
+** 
+*/
diff --git a/drivers/staging/generic_serial/rio/rioctrl.c b/drivers/staging/generic_serial/rio/rioctrl.c
new file mode 100644
index 0000000..7805063
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioctrl.c
@@ -0,0 +1,1504 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioctrl.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:42
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)rioctrl.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+static struct LpbReq LpbReq;
+static struct RupReq RupReq;
+static struct PortReq PortReq;
+static struct HostReq HostReq;	/* oh really?  global?  and no locking? */
+static struct HostDpRam HostDpRam;
+static struct DebugCtrl DebugCtrl;
+static struct Map MapEnt;
+static struct PortSetup PortSetup;
+static struct DownLoad DownLoad;
+static struct SendPack SendPack;
+/* static struct StreamInfo	StreamInfo; */
+/* static char modemtable[RIO_PORTS]; */
+static struct SpecialRupCmd SpecialRupCmd;
+static struct PortParams PortParams;
+static struct portStats portStats;
+
+static struct SubCmdStruct {
+	ushort Host;
+	ushort Rup;
+	ushort Port;
+	ushort Addr;
+} SubCmd;
+
+struct PortTty {
+	uint port;
+	struct ttystatics Tty;
+};
+
+static struct PortTty PortTty;
+typedef struct ttystatics TERMIO;
+
+/*
+** This table is used when the config.rio downloads bin code to the
+** driver. We index the table using the product code, 0-F, and call
+** the function pointed to by the entry, passing the information
+** about the boot.
+** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
+** process to bog off.
+*/
+static int
+ (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
+					/* 0 */ RIOBootCodeHOST,
+					/* Host Card */
+					/* 1 */ RIOBootCodeRTA,
+					/* RTA */
+};
+
+#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
+
+static int copy_from_io(void __user *to, void __iomem *from, size_t size)
+{
+	void *buf = kmalloc(size, GFP_KERNEL);
+	int res = -ENOMEM;
+	if (buf) {
+		rio_memcpy_fromio(buf, from, size);
+		res = copy_to_user(to, buf, size);
+		kfree(buf);
+	}
+	return res;
+}
+
+int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su)
+{
+	uint Host;		/* leave me unsigned! */
+	uint port;		/* and me! */
+	struct Host *HostP;
+	ushort loop;
+	int Entry;
+	struct Port *PortP;
+	struct PKT __iomem *PacketP;
+	int retval = 0;
+	unsigned long flags;
+	void __user *argp = (void __user *)arg;
+
+	func_enter();
+
+	/* Confuse the compiler to think that we've initialized these */
+	Host = 0;
+	PortP = NULL;
+
+	rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp);
+
+	switch (cmd) {
+		/*
+		 ** RIO_SET_TIMER
+		 **
+		 ** Change the value of the host card interrupt timer.
+		 ** If the host card number is -1 then all host cards are changed
+		 ** otherwise just the specified host card will be changed.
+		 */
+	case RIO_SET_TIMER:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg);
+		{
+			int host, value;
+			host = (arg >> 16) & 0x0000FFFF;
+			value = arg & 0x0000ffff;
+			if (host == -1) {
+				for (host = 0; host < p->RIONumHosts; host++) {
+					if (p->RIOHosts[host].Flags == RC_RUNNING) {
+						writew(value, &p->RIOHosts[host].ParmMapP->timer);
+					}
+				}
+			} else if (host >= p->RIONumHosts) {
+				return -EINVAL;
+			} else {
+				if (p->RIOHosts[host].Flags == RC_RUNNING) {
+					writew(value, &p->RIOHosts[host].ParmMapP->timer);
+				}
+			}
+		}
+		return 0;
+
+	case RIO_FOAD_RTA:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
+		return RIOCommandRta(p, arg, RIOFoadRta);
+
+	case RIO_ZOMBIE_RTA:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
+		return RIOCommandRta(p, arg, RIOZombieRta);
+
+	case RIO_IDENTIFY_RTA:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
+		return RIOIdentifyRta(p, argp);
+
+	case RIO_KILL_NEIGHBOUR:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
+		return RIOKillNeighbour(p, argp);
+
+	case SPECIAL_RUP_CMD:
+		{
+			struct CmdBlk *CmdBlkP;
+
+			rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
+			if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) {
+				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
+				p->RIOError.Error = COPYIN_FAILED;
+				return -EFAULT;
+			}
+			CmdBlkP = RIOGetCmdBlk();
+			if (!CmdBlkP) {
+				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
+				return -ENXIO;
+			}
+			CmdBlkP->Packet = SpecialRupCmd.Packet;
+			if (SpecialRupCmd.Host >= p->RIONumHosts)
+				SpecialRupCmd.Host = 0;
+			rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
+			if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
+				printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n");
+			}
+			return 0;
+		}
+
+	case RIO_DEBUG_MEM:
+		return -EPERM;
+
+	case RIO_ALL_MODEM:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
+		p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+		return -EINVAL;
+
+	case RIO_GET_TABLE:
+		/*
+		 ** Read the routing table from the device driver to user space
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
+
+		if ((retval = RIOApel(p)) != 0)
+			return retval;
+
+		if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+
+		{
+			int entry;
+			rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
+			for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+				if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
+					continue;
+
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
+				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
+			}
+			rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
+		}
+		p->RIOQuickCheck = NOT_CHANGED;	/* a table has been gotten */
+		return 0;
+
+	case RIO_PUT_TABLE:
+		/*
+		 ** Write the routing table to the device driver from user space
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
+
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+/*
+***********************************
+				{
+					int entry;
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
+					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
+					{
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
+						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
+					}
+					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
+				}
+***********************************
+*/
+		return RIONewTable(p);
+
+	case RIO_GET_BINDINGS:
+		/*
+		 ** Send bindings table, containing unique numbers of RTAs owned
+		 ** by this system to user space
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
+
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+
+	case RIO_PUT_BINDINGS:
+		/*
+		 ** Receive a bindings table, containing unique numbers of RTAs owned
+		 ** by this system
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
+
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+
+	case RIO_BIND_RTA:
+		{
+			int EmptySlot = -1;
+			/*
+			 ** Bind this RTA to host, so that it will be booted by
+			 ** host in 'boot owned RTAs' mode.
+			 */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
+
+			if (!su) {
+				rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
+				p->RIOError.Error = NOT_SUPER_USER;
+				return -EPERM;
+			}
+			for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
+				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
+					EmptySlot = Entry;
+				else if (p->RIOBindTab[Entry] == arg) {
+					/*
+					 ** Already exists - delete
+					 */
+					p->RIOBindTab[Entry] = 0L;
+					rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg);
+					return 0;
+				}
+			}
+			/*
+			 ** Dosen't exist - add
+			 */
+			if (EmptySlot != -1) {
+				p->RIOBindTab[EmptySlot] = arg;
+				rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg);
+			} else {
+				rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg);
+				return -ENOMEM;
+			}
+			return 0;
+		}
+
+	case RIO_RESUME:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
+		port = arg;
+		if ((port < 0) || (port > 511)) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+		PortP = p->RIOPortp[port];
+		if (!PortP->Mapped) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
+			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+			return -EINVAL;
+		}
+		if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
+			return -EINVAL;
+		}
+
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) ==
+				RIO_FAIL) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return -EBUSY;
+		} else {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
+			PortP->State |= RIO_BUSY;
+		}
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_ASSIGN_RTA:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		return RIOAssignRta(p, &MapEnt);
+
+	case RIO_CHANGE_NAME:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		return RIOChangeName(p, &MapEnt);
+
+	case RIO_DELETE_RTA:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		return RIODeleteRta(p, &MapEnt);
+
+	case RIO_QUICK_CHECK:
+		if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+
+	case RIO_LAST_ERROR:
+		if (copy_to_user(argp, &p->RIOError, sizeof(struct Error)))
+			return -EFAULT;
+		return 0;
+
+	case RIO_GET_LOG:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
+		return -EINVAL;
+
+	case RIO_GET_MODTYPE:
+		if (copy_from_user(&port, argp, sizeof(unsigned int))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
+		if (port < 0 || port > 511) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+		PortP = (p->RIOPortp[port]);
+		if (!PortP->Mapped) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
+			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
+			return -EINVAL;
+		}
+		/*
+		 ** Return module type of port
+		 */
+		port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
+		if (copy_to_user(argp, &port, sizeof(unsigned int))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return (0);
+	case RIO_BLOCK_OPENS:
+		rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
+		for (Entry = 0; Entry < RIO_PORTS; Entry++) {
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			p->RIOPortp[Entry]->WaitUntilBooted = 1;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		}
+		return 0;
+
+	case RIO_SETUP_PORTS:
+		rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
+		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
+			return -EFAULT;
+		}
+		if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
+			return -ENXIO;
+		}
+		if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
+			p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
+			rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
+			return -EINVAL;
+		}
+		if (!p->RIOPortp) {
+			printk(KERN_ERR "rio: No p->RIOPortp array!\n");
+			rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
+			return -EIO;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
+		for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
+			rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
+		rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
+		return retval;
+
+	case RIO_GET_PORT_SETUP:
+		rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
+		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (PortSetup.From >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+
+		port = PortSetup.To = PortSetup.From;
+		PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
+		PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
+		PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
+		PortSetup.Store = p->RIOPortp[port]->Store;
+		PortSetup.Lock = p->RIOPortp[port]->Lock;
+		PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
+		memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN);
+		memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN);
+		PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
+		PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
+
+		if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_GET_PORT_PARAMS:
+		rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
+		if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (PortParams.Port >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		PortP = (p->RIOPortp[PortParams.Port]);
+		PortParams.Config = PortP->Config;
+		PortParams.State = PortP->State;
+		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
+
+		if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_GET_PORT_TTY:
+		rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
+		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (PortTty.port >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+
+		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
+		PortP = (p->RIOPortp[PortTty.port]);
+		if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_SET_PORT_TTY:
+		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
+		if (PortTty.port >= (ushort) RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		PortP = (p->RIOPortp[PortTty.port]);
+		RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM,
+				OK_TO_SLEEP);
+		return retval;
+
+	case RIO_SET_PORT_PARAMS:
+		rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
+		if (copy_from_user(&PortParams, argp, sizeof(PortParams))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (PortParams.Port >= (ushort) RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		PortP = (p->RIOPortp[PortParams.Port]);
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->Config = PortParams.Config;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_GET_PORT_STATS:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
+		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		PortP = (p->RIOPortp[portStats.port]);
+		portStats.gather = PortP->statsGather;
+		portStats.txchars = PortP->txchars;
+		portStats.rxchars = PortP->rxchars;
+		portStats.opens = PortP->opens;
+		portStats.closes = PortP->closes;
+		portStats.ioctls = PortP->ioctls;
+		if (copy_to_user(argp, &portStats, sizeof(struct portStats))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_RESET_PORT_STATS:
+		port = arg;
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
+		if (port >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		PortP = (p->RIOPortp[port]);
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->txchars = 0;
+		PortP->rxchars = 0;
+		PortP->opens = 0;
+		PortP->closes = 0;
+		PortP->ioctls = 0;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_GATHER_PORT_STATS:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
+		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		PortP = (p->RIOPortp[portStats.port]);
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->statsGather = portStats.gather;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_READ_CONFIG:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
+		if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_SET_CONFIG:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
+		if (!su) {
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		/*
+		 ** move a few value around
+		 */
+		for (Host = 0; Host < p->RIONumHosts; Host++)
+			if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
+				writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer);
+		return retval;
+
+	case RIO_START_POLLER:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
+		return -EINVAL;
+
+	case RIO_STOP_POLLER:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
+		if (!su) {
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		p->RIOPolling = NOT_POLLING;
+		return retval;
+
+	case RIO_SETDEBUG:
+	case RIO_GETDEBUG:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
+		if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (DebugCtrl.SysPort == NO_PORT) {
+			if (cmd == RIO_SETDEBUG) {
+				if (!su) {
+					p->RIOError.Error = NOT_SUPER_USER;
+					return -EPERM;
+				}
+				p->rio_debug = DebugCtrl.Debug;
+				p->RIODebugWait = DebugCtrl.Wait;
+				rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
+			} else {
+				rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
+				DebugCtrl.Debug = p->rio_debug;
+				DebugCtrl.Wait = p->RIODebugWait;
+				if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
+					rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
+					p->RIOError.Error = COPYOUT_FAILED;
+					return -EFAULT;
+				}
+			}
+		} else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		} else if (cmd == RIO_SETDEBUG) {
+			if (!su) {
+				p->RIOError.Error = NOT_SUPER_USER;
+				return -EPERM;
+			}
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
+		} else {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
+			DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
+			if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
+				rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
+				p->RIOError.Error = COPYOUT_FAILED;
+				return -EFAULT;
+			}
+		}
+		return retval;
+
+	case RIO_VERSID:
+		/*
+		 ** Enquire about the release and version.
+		 ** We return MAX_VERSION_LEN bytes, being a
+		 ** textual null terminated string.
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
+		if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_NUM_HOSTS:
+		/*
+		 ** Enquire as to the number of hosts located
+		 ** at init time.
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
+		if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_HOST_FOAD:
+		/*
+		 ** Kill host. This may not be in the final version...
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg);
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		p->RIOHalted = 1;
+		p->RIOSystemUp = 0;
+
+		for (Host = 0; Host < p->RIONumHosts; Host++) {
+			(void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
+			memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags));
+			p->RIOHosts[Host].Flags = RC_WAITING;
+		}
+		RIOFoadWakeup(p);
+		p->RIONumBootPkts = 0;
+		p->RIOBooting = 0;
+		printk("HEEEEELP!\n");
+
+		for (loop = 0; loop < RIO_PORTS; loop++) {
+			spin_lock_init(&p->RIOPortp[loop]->portSem);
+			p->RIOPortp[loop]->InUse = NOT_INUSE;
+		}
+
+		p->RIOSystemUp = 0;
+		return retval;
+
+	case RIO_DOWNLOAD:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
+		if (!su) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
+			p->RIOError.Error = NOT_SUPER_USER;
+			return -EPERM;
+		}
+		if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
+
+		/*
+		 ** It is important that the product code is an unsigned object!
+		 */
+		if (DownLoad.ProductCode >= MAX_PRODUCT) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
+			p->RIOError.Error = NO_SUCH_PRODUCT;
+			return -ENXIO;
+		}
+		/*
+		 ** do something!
+		 */
+		retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
+		/* <-- Panic */
+		p->RIOHalted = 0;
+		/*
+		 ** and go back, content with a job well completed.
+		 */
+		return retval;
+
+	case RIO_PARMS:
+		{
+			unsigned int host;
+
+			if (copy_from_user(&host, argp, sizeof(host))) {
+				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+				p->RIOError.Error = COPYIN_FAILED;
+				return -EFAULT;
+			}
+			/*
+			 ** Fetch the parmmap
+			 */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
+			if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
+				p->RIOError.Error = COPYOUT_FAILED;
+				rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
+				return -EFAULT;
+			}
+		}
+		return retval;
+
+	case RIO_HOST_REQ:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
+		if (copy_from_user(&HostReq, argp, sizeof(HostReq))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (HostReq.HostNum >= p->RIONumHosts) {
+			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
+			return -ENXIO;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
+
+		if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_HOST_DPRAM:
+		rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
+		if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (HostDpRam.HostNum >= p->RIONumHosts) {
+			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
+			return -ENXIO;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
+
+		if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
+			int off;
+			/* It's hardware like this that really gets on my tits. */
+			static unsigned char copy[sizeof(struct DpRam)];
+			for (off = 0; off < sizeof(struct DpRam); off++)
+				copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off);
+			if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {
+				p->RIOError.Error = COPYOUT_FAILED;
+				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+				return -EFAULT;
+			}
+		} else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_SET_BUSY:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
+		if (arg > 511) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		p->RIOPortp[arg]->State |= RIO_BUSY;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_HOST_PORT:
+		/*
+		 ** The daemon want port information
+		 ** (probably for debug reasons)
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
+		if (copy_from_user(&PortReq, argp, sizeof(PortReq))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+
+		if (PortReq.SysPort >= RIO_PORTS) {	/* SysPort is unsigned */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
+		if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_HOST_RUP:
+		/*
+		 ** The daemon want rup information
+		 ** (probably for debug reasons)
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
+		if (copy_from_user(&RupReq, argp, sizeof(RupReq))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (RupReq.HostNum >= p->RIONumHosts) {	/* host is unsigned */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
+			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) {	/* eek! */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
+			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+		HostP = &p->RIOHosts[RupReq.HostNum];
+
+		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
+			p->RIOError.Error = HOST_NOT_RUNNING;
+			return -EIO;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
+
+		if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
+			return -EFAULT;
+		}
+		return retval;
+
+	case RIO_HOST_LPB:
+		/*
+		 ** The daemon want lpb information
+		 ** (probably for debug reasons)
+		 */
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
+		if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (LpbReq.Host >= p->RIONumHosts) {	/* host is unsigned */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
+			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+		if (LpbReq.Link >= LINKS_PER_UNIT) {	/* eek! */
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
+			p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+		HostP = &p->RIOHosts[LpbReq.Host];
+
+		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
+			p->RIOError.Error = HOST_NOT_RUNNING;
+			return -EIO;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
+
+		if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return retval;
+
+		/*
+		 ** Here 3 IOCTL's that allow us to change the way in which
+		 ** rio logs errors. send them just to syslog or send them
+		 ** to both syslog and console or send them to just the console.
+		 **
+		 ** See RioStrBuf() in util.c for the other half.
+		 */
+	case RIO_SYSLOG_ONLY:
+		p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */
+		return 0;
+
+	case RIO_SYSLOG_CONS:
+		p->RIOPrintLogState = PRINT_TO_LOG_CONS;	/* syslog and console */
+		return 0;
+
+	case RIO_CONS_ONLY:
+		p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */
+		return 0;
+
+	case RIO_SIGNALS_ON:
+		if (p->RIOSignalProcess) {
+			p->RIOError.Error = SIGNALS_ALREADY_SET;
+			return -EBUSY;
+		}
+		/* FIXME: PID tracking */
+		p->RIOSignalProcess = current->pid;
+		p->RIOPrintDisabled = DONT_PRINT;
+		return retval;
+
+	case RIO_SIGNALS_OFF:
+		if (p->RIOSignalProcess != current->pid) {
+			p->RIOError.Error = NOT_RECEIVING_PROCESS;
+			return -EPERM;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
+		p->RIOSignalProcess = 0;
+		return retval;
+
+	case RIO_SET_BYTE_MODE:
+		for (Host = 0; Host < p->RIONumHosts; Host++)
+			if (p->RIOHosts[Host].Type == RIO_AT)
+				p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
+		return retval;
+
+	case RIO_SET_WORD_MODE:
+		for (Host = 0; Host < p->RIONumHosts; Host++)
+			if (p->RIOHosts[Host].Type == RIO_AT)
+				p->RIOHosts[Host].Mode |= WORD_OPERATION;
+		return retval;
+
+	case RIO_SET_FAST_BUS:
+		for (Host = 0; Host < p->RIONumHosts; Host++)
+			if (p->RIOHosts[Host].Type == RIO_AT)
+				p->RIOHosts[Host].Mode |= FAST_AT_BUS;
+		return retval;
+
+	case RIO_SET_SLOW_BUS:
+		for (Host = 0; Host < p->RIONumHosts; Host++)
+			if (p->RIOHosts[Host].Type == RIO_AT)
+				p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
+		return retval;
+
+	case RIO_MAP_B50_TO_50:
+	case RIO_MAP_B50_TO_57600:
+	case RIO_MAP_B110_TO_110:
+	case RIO_MAP_B110_TO_115200:
+		rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
+		port = arg;
+		if (port < 0 || port > 511) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		switch (cmd) {
+		case RIO_MAP_B50_TO_50:
+			p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
+			break;
+		case RIO_MAP_B50_TO_57600:
+			p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
+			break;
+		case RIO_MAP_B110_TO_110:
+			p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
+			break;
+		case RIO_MAP_B110_TO_115200:
+			p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
+			break;
+		}
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_STREAM_INFO:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
+		return -EINVAL;
+
+	case RIO_SEND_PACKET:
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
+		if (copy_from_user(&SendPack, argp, sizeof(SendPack))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		if (SendPack.PortNum >= 128) {
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -ENXIO;
+		}
+
+		PortP = p->RIOPortp[SendPack.PortNum];
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+		if (!can_add_transmit(&PacketP, PortP)) {
+			p->RIOError.Error = UNIT_IS_IN_USE;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return -ENOSPC;
+		}
+
+		for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
+			writeb(SendPack.Data[loop], &PacketP->data[loop]);
+
+		writeb(SendPack.Len, &PacketP->len);
+
+		add_transmit(PortP);
+		/*
+		 ** Count characters transmitted for port statistics reporting
+		 */
+		if (PortP->statsGather)
+			PortP->txchars += (SendPack.Len & 127);
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return retval;
+
+	case RIO_NO_MESG:
+		if (su)
+			p->RIONoMessage = 1;
+		return su ? 0 : -EPERM;
+
+	case RIO_MESG:
+		if (su)
+			p->RIONoMessage = 0;
+		return su ? 0 : -EPERM;
+
+	case RIO_WHAT_MESG:
+		if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+
+	case RIO_MEM_DUMP:
+		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
+
+		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
+			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+
+		if (SubCmd.Host >= p->RIONumHosts) {
+			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+
+		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
+
+		PortP = p->RIOPortp[port];
+
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+		if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return -EBUSY;
+		} else
+			PortP->State |= RIO_BUSY;
+
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+
+	case RIO_TICK:
+		if (arg >= p->RIONumHosts)
+			return -EINVAL;
+		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg);
+		writeb(0xFF, &p->RIOHosts[arg].SetInt);
+		return 0;
+
+	case RIO_TOCK:
+		if (arg >= p->RIONumHosts)
+			return -EINVAL;
+		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg);
+		writeb(0xFF, &p->RIOHosts[arg].ResetInt);
+		return 0;
+
+	case RIO_READ_CHECK:
+		/* Check reads for pkts with data[0] the same */
+		p->RIOReadCheck = !p->RIOReadCheck;
+		if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) {
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+
+	case RIO_READ_REGISTER:
+		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
+			p->RIOError.Error = COPYIN_FAILED;
+			return -EFAULT;
+		}
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
+
+		if (SubCmd.Port > 511) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
+			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+
+		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
+			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+
+		if (SubCmd.Host >= p->RIONumHosts) {
+			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
+			return -EINVAL;
+		}
+
+		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
+		PortP = p->RIOPortp[port];
+
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+		if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) ==
+				RIO_FAIL) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return -EBUSY;
+		} else
+			PortP->State |= RIO_BUSY;
+
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
+			p->RIOError.Error = COPYOUT_FAILED;
+			return -EFAULT;
+		}
+		return 0;
+		/*
+		 ** rio_make_dev: given port number (0-511) ORed with port type
+		 ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
+		 ** value to pass to mknod to create the correct device node.
+		 */
+	case RIO_MAKE_DEV:
+		{
+			unsigned int port = arg & RIO_MODEM_MASK;
+			unsigned int ret;
+
+			switch (arg & RIO_DEV_MASK) {
+			case RIO_DEV_DIRECT:
+				ret = drv_makedev(MAJOR(dev), port);
+				rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);
+				return ret;
+			case RIO_DEV_MODEM:
+				ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
+				rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret);
+				return ret;
+			case RIO_DEV_XPRINT:
+				ret = drv_makedev(MAJOR(dev), port);
+				rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret);
+				return ret;
+			}
+			rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
+			return -EINVAL;
+		}
+		/*
+		 ** rio_minor: given a dev_t from a stat() call, return
+		 ** the port number (0-511) ORed with the port type
+		 ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
+		 */
+	case RIO_MINOR:
+		{
+			dev_t dv;
+			int mino;
+			unsigned long ret;
+
+			dv = (dev_t) (arg);
+			mino = RIO_UNMODEM(dv);
+
+			if (RIO_ISMODEM(dv)) {
+				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
+				ret = mino | RIO_DEV_MODEM;
+			} else {
+				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
+				ret = mino | RIO_DEV_DIRECT;
+			}
+			return ret;
+		}
+	}
+	rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
+	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+
+	func_exit();
+	return -EINVAL;
+}
+
+/*
+** Pre-emptive commands go on RUPs and are only one byte long.
+*/
+int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
+{
+	struct CmdBlk *CmdBlkP;
+	struct PktCmd_M *PktCmdP;
+	int Ret;
+	ushort rup;
+	int port;
+
+	if (PortP->State & RIO_DELETED) {
+		rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
+		return RIO_FAIL;
+	}
+
+	if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
+			!(CmdBlkP = RIOGetCmdBlk())) {
+		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
+			"for command %d on port %d\n", Cmd, PortP->PortNum);
+		return RIO_FAIL;
+	}
+
+	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
+			CmdBlkP, PortP->InUse);
+
+	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
+
+	CmdBlkP->Packet.src_unit = 0;
+	if (PortP->SecondBlock)
+		rup = PortP->ID2;
+	else
+		rup = PortP->RupNum;
+	CmdBlkP->Packet.dest_unit = rup;
+	CmdBlkP->Packet.src_port = COMMAND_RUP;
+	CmdBlkP->Packet.dest_port = COMMAND_RUP;
+	CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
+	CmdBlkP->PostFuncP = RIOUnUse;
+	CmdBlkP->PostArg = (unsigned long) PortP;
+	PktCmdP->Command = Cmd;
+	port = PortP->HostPort % (ushort) PORTS_PER_RTA;
+	/*
+	 ** Index ports 8-15 for 2nd block of 16 port RTA.
+	 */
+	if (PortP->SecondBlock)
+		port += (ushort) PORTS_PER_RTA;
+	PktCmdP->PhbNum = port;
+
+	switch (Cmd) {
+	case RIOC_MEMDUMP:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
+				"(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
+		PktCmdP->SubCommand = RIOC_MEMDUMP;
+		PktCmdP->SubAddr = SubCmd.Addr;
+		break;
+	case RIOC_FCLOSE:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
+				CmdBlkP);
+		break;
+	case RIOC_READ_REGISTER:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
+				"command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
+		PktCmdP->SubCommand = RIOC_READ_REGISTER;
+		PktCmdP->SubAddr = SubCmd.Addr;
+		break;
+	case RIOC_RESUME:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
+				CmdBlkP);
+		break;
+	case RIOC_RFLUSH:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
+				CmdBlkP);
+		CmdBlkP->PostFuncP = RIORFlushEnable;
+		break;
+	case RIOC_SUSPEND:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
+				CmdBlkP);
+		break;
+
+	case RIOC_MGET:
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
+				CmdBlkP);
+		break;
+
+	case RIOC_MSET:
+	case RIOC_MBIC:
+	case RIOC_MBIS:
+		CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
+		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
+				"blk %p\n", CmdBlkP);
+		break;
+
+	case RIOC_WFLUSH:
+		/*
+		 ** If we have queued up the maximum number of Write flushes
+		 ** allowed then we should not bother sending any more to the
+		 ** RTA.
+		 */
+		if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
+			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
+					"WflushFlag about to wrap!");
+			RIOFreeCmdBlk(CmdBlkP);
+			return (RIO_FAIL);
+		} else {
+			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
+					"blk %p\n", CmdBlkP);
+			CmdBlkP->PostFuncP = RIOWFlushMark;
+		}
+		break;
+	}
+
+	PortP->InUse++;
+
+	Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
+
+	return Ret;
+}
diff --git a/drivers/staging/generic_serial/rio/riodrvr.h b/drivers/staging/generic_serial/rio/riodrvr.h
new file mode 100644
index 0000000..0907e71
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/riodrvr.h
@@ -0,0 +1,138 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riodrvr.h
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 09:22:46
+**	Retrieved	: 11/6/98 09:22:46
+**
+**  ident @(#)riodrvr.h	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __riodrvr_h
+#define __riodrvr_h
+
+#include <asm/param.h>		/* for HZ */
+
+#define MEMDUMP_SIZE	32
+#define	MOD_DISABLE	(RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT)
+
+
+struct rio_info {
+	int mode;		/* Intr or polled, word/byte */
+	spinlock_t RIOIntrSem;	/* Interrupt thread sem */
+	int current_chan;	/* current channel */
+	int RIOFailed;		/* Not initialised ? */
+	int RIOInstallAttempts;	/* no. of rio-install() calls */
+	int RIOLastPCISearch;	/* status of last search */
+	int RIONumHosts;	/* Number of RIO Hosts */
+	struct Host *RIOHosts;	/* RIO Host values */
+	struct Port **RIOPortp;	/* RIO port values */
+/*
+** 02.03.1999 ARG - ESIL 0820 fix
+** We no longer use RIOBootMode
+**
+	int			RIOBootMode;		* RIO boot mode *
+**
+*/
+	int RIOPrintDisabled;	/* RIO printing disabled ? */
+	int RIOPrintLogState;	/* RIO printing state ? */
+	int RIOPolling;		/* Polling ? */
+/*
+** 09.12.1998 ARG - ESIL 0776 part fix
+** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
+** The fix for this ESIL introduces another member (RIORtaDisCons) here to be
+** updated in RIOConCon() - to keep track of RTA connections/disconnections.
+** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
+*/
+	int RIOHalted;		/* halted ? */
+	int RIORtaDisCons;	/* RTA connections/disconnections */
+	unsigned int RIOReadCheck;	/* Rio read check */
+	unsigned int RIONoMessage;	/* To display message or not */
+	unsigned int RIONumBootPkts;	/* how many packets for an RTA */
+	unsigned int RIOBootCount;	/* size of RTA code */
+	unsigned int RIOBooting;	/* count of outstanding boots */
+	unsigned int RIOSystemUp;	/* Booted ?? */
+	unsigned int RIOCounting;	/* for counting interrupts */
+	unsigned int RIOIntCount;	/* # of intr since last check */
+	unsigned int RIOTxCount;	/* number of xmit intrs  */
+	unsigned int RIORxCount;	/* number of rx intrs */
+	unsigned int RIORupCount;	/* number of rup intrs */
+	int RIXTimer;
+	int RIOBufferSize;	/* Buffersize */
+	int RIOBufferMask;	/* Buffersize */
+
+	int RIOFirstMajor;	/* First host card's major no */
+
+	unsigned int RIOLastPortsMapped;	/* highest port number known */
+	unsigned int RIOFirstPortsMapped;	/* lowest port number known */
+
+	unsigned int RIOLastPortsBooted;	/* highest port number running */
+	unsigned int RIOFirstPortsBooted;	/* lowest port number running */
+
+	unsigned int RIOLastPortsOpened;	/* highest port number running */
+	unsigned int RIOFirstPortsOpened;	/* lowest port number running */
+
+	/* Flag to say that the topology information has been changed. */
+	unsigned int RIOQuickCheck;
+	unsigned int CdRegister;	/* ??? */
+	int RIOSignalProcess;	/* Signalling process */
+	int rio_debug;		/* To debug ... */
+	int RIODebugWait;	/* For what ??? */
+	int tpri;		/* Thread prio */
+	int tid;		/* Thread id */
+	unsigned int _RIO_Polled;	/* Counter for polling */
+	unsigned int _RIO_Interrupted;	/* Counter for interrupt */
+	int intr_tid;		/* iointset return value */
+	int TxEnSem;		/* TxEnable Semaphore */
+
+
+	struct Error RIOError;	/* to Identify what went wrong */
+	struct Conf RIOConf;	/* Configuration ??? */
+	struct ttystatics channel[RIO_PORTS];	/* channel information */
+	char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)]
+	    [RTA_BOOT_DATA_SIZE];
+	struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
+	struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
+
+	/* RTA to host binding table for master/slave operation */
+	unsigned long RIOBindTab[MAX_RTA_BINDINGS];
+	/* RTA memory dump variable */
+	unsigned char RIOMemDump[MEMDUMP_SIZE];
+	struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
+
+};
+
+
+#ifdef linux
+#define debug(x)        printk x
+#else
+#define debug(x)	kkprintf x
+#endif
+
+
+
+#define RIO_RESET_INT	0x7d80
+
+#endif				/* __riodrvr.h */
diff --git a/drivers/staging/generic_serial/rio/rioinfo.h b/drivers/staging/generic_serial/rio/rioinfo.h
new file mode 100644
index 0000000..42ff1e7
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioinfo.h
@@ -0,0 +1,92 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioinfo.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 14:07:49
+**	Retrieved	: 11/6/98 14:07:50
+**
+**  ident @(#)rioinfo.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rioinfo_h
+#define __rioinfo_h
+
+/*
+** Host card data structure
+*/
+struct RioHostInfo {
+	long location;		/* RIO Card Base I/O address */
+	long vector;		/* RIO Card IRQ vector */
+	int bus;		/* ISA/EISA/MCA/PCI */
+	int mode;		/* pointer to host mode - INTERRUPT / POLLED */
+	struct old_sgttyb
+	*Sg;			/* pointer to default term characteristics */
+};
+
+
+/* Mode in rio device info */
+#define INTERRUPTED_MODE	0x01	/* Interrupt is generated */
+#define POLLED_MODE		0x02	/* No interrupt */
+#define AUTO_MODE		0x03	/* Auto mode */
+
+#define WORD_ACCESS_MODE	0x10	/* Word Access Mode */
+#define BYTE_ACCESS_MODE	0x20	/* Byte Access Mode */
+
+
+/* Bus type that RIO supports */
+#define ISA_BUS			0x01	/* The card is ISA */
+#define EISA_BUS		0x02	/* The card is EISA */
+#define MCA_BUS			0x04	/* The card is MCA */
+#define PCI_BUS			0x08	/* The card is PCI */
+
+/*
+** 11.11.1998 ARG - ESIL ???? part fix
+** Moved definition for 'CHAN' here from rioinfo.c (it is now
+** called 'DEF_TERM_CHARACTERISTICS').
+*/
+
+#define DEF_TERM_CHARACTERISTICS \
+{ \
+	B19200, B19200,				/* input and output speed */ \
+	'H' - '@',				/* erase char */ \
+	-1,					/* 2nd erase char */ \
+	'U' - '@',				/* kill char */ \
+	ECHO | CRMOD,				/* mode */ \
+	'C' - '@',				/* interrupt character */ \
+	'\\' - '@',				/* quit char */ \
+	'Q' - '@',				/* start char */ \
+	'S' - '@',				/* stop char */ \
+	'D' - '@',				/* EOF */ \
+	-1,					/* brk */ \
+	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ \
+	'Z' - '@',				/* process stop */ \
+	'Y' - '@',				/* delayed stop */ \
+	'R' - '@',				/* reprint line */ \
+	'O' - '@',				/* flush output */ \
+	'W' - '@',				/* word erase */ \
+	'V' - '@'				/* literal next char */ \
+}
+
+#endif				/* __rioinfo_h */
diff --git a/drivers/staging/generic_serial/rio/rioinit.c b/drivers/staging/generic_serial/rio/rioinit.c
new file mode 100644
index 0000000..24a282b
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioinit.c
@@ -0,0 +1,421 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioinit.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:43
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)rioinit.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "rio_linux.h"
+
+int RIOPCIinit(struct rio_info *p, int Mode);
+
+static int RIOScrub(int, u8 __iomem *, int);
+
+
+/**
+** RIOAssignAT :
+**
+** Fill out the fields in the p->RIOHosts structure now we know we know
+** we have a board present.
+**
+** bits < 0 indicates 8 bit operation requested,
+** bits > 0 indicates 16 bit operation.
+*/
+
+int RIOAssignAT(struct rio_info *p, int	Base, void __iomem *virtAddr, int mode)
+{
+	int		bits;
+	struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr;
+
+	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
+		bits = BYTE_OPERATION;
+	else
+		bits = WORD_OPERATION;
+
+	/*
+	** Board has passed its scrub test. Fill in all the
+	** transient stuff.
+	*/
+	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
+	p->RIOHosts[p->RIONumHosts].CardP	= virtAddr;
+
+	/*
+	** Revision 01 AT host cards don't support WORD operations,
+	*/
+	if (readb(&cardp->DpRevision) == 01)
+		bits = BYTE_OPERATION;
+
+	p->RIOHosts[p->RIONumHosts].Type = RIO_AT;
+	p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card;
+											/* set this later */
+	p->RIOHosts[p->RIONumHosts].Slot = -1;
+	p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits;
+	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE ,
+		&p->RIOHosts[p->RIONumHosts].Control);
+	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
+	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE,
+		&p->RIOHosts[p->RIONumHosts].Control);
+	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
+	p->RIOHosts[p->RIONumHosts].UniqueNum =
+		((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
+		((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
+		((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
+		((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum);
+
+	p->RIONumHosts++;
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
+	return(1);
+}
+
+static	u8	val[] = {
+#ifdef VERY_LONG_TEST
+	  0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+	  0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 
+#endif
+	  0xff, 0x00, 0x00 };
+
+#define	TEST_END sizeof(val)
+
+/*
+** RAM test a board. 
+** Nothing too complicated, just enough to check it out.
+*/
+int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot)
+{
+	struct DpRam __iomem *DpRam = caddr;
+	void __iomem *ram[4];
+	int  size[4];
+	int  op, bank;
+	int  nbanks;
+
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n",
+			type, DpRam, slot);
+
+	RIOHostReset(type, DpRam, slot);
+
+	/*
+	** Scrub the memory. This comes in several banks:
+	** DPsram1	- 7000h bytes
+	** DPsram2	- 200h  bytes
+	** DPsram3	- 7000h bytes
+	** scratch	- 1000h bytes
+	*/
+
+	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n");
+
+	size[0] = DP_SRAM1_SIZE;
+	size[1] = DP_SRAM2_SIZE;
+	size[2] = DP_SRAM3_SIZE;
+	size[3] = DP_SCRATCH_SIZE;
+
+	ram[0] = DpRam->DpSram1;
+	ram[1] = DpRam->DpSram2;
+	ram[2] = DpRam->DpSram3;
+	nbanks = (type == RIO_PCI) ? 3 : 4;
+	if (nbanks == 4)
+		ram[3] = DpRam->DpScratch;
+
+
+	if (nbanks == 3) {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n",
+				ram[0], size[0], ram[1], size[1], ram[2], size[2]);
+	} else {
+		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n",
+				ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]);
+	}
+
+	/*
+	** This scrub operation will test for crosstalk between
+	** banks. TEST_END is a magic number, and relates to the offset
+	** within the 'val' array used by Scrub.
+	*/
+	for (op=0; op<TEST_END; op++) {
+		for (bank=0; bank<nbanks; bank++) {
+			if (RIOScrub(op, ram[bank], size[bank]) == RIO_FAIL) {
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 
+							bank, op);
+				return RIO_FAIL;
+			}
+		}
+	}
+
+	rio_dprintk (RIO_DEBUG_INIT, "Test completed\n");
+	return 0;
+}
+
+
+/*
+** Scrub an area of RAM.
+** Define PRETEST and POSTTEST for a more thorough checking of the
+** state of the memory.
+** Call with op set to an index into the above 'val' array to determine
+** which value will be written into memory.
+** Call with op set to zero means that the RAM will not be read and checked
+** before it is written.
+** Call with op not zero and the RAM will be read and compared with val[op-1]
+** to check that the data from the previous phase was retained.
+*/
+
+static int RIOScrub(int op, u8 __iomem *ram, int size)
+{
+	int off;
+	unsigned char	oldbyte;
+	unsigned char	newbyte;
+	unsigned char	invbyte;
+	unsigned short	oldword;
+	unsigned short	newword;
+	unsigned short	invword;
+	unsigned short	swapword;
+
+	if (op) {
+		oldbyte = val[op-1];
+		oldword = oldbyte | (oldbyte<<8);
+	} else
+	  oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */
+	newbyte = val[op];
+	newword = newbyte | (newbyte<<8);
+	invbyte = ~newbyte;
+	invword = invbyte | (invbyte<<8);
+
+	/*
+	** Check that the RAM contains the value that should have been left there
+	** by the previous test (not applicable for pass zero)
+	*/
+	if (op) {
+		for (off=0; off<size; off++) {
+			if (readb(ram + off) != oldbyte) {
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
+				return RIO_FAIL;
+			}
+		}
+		for (off=0; off<size; off+=2) {
+			if (readw(ram + off) != oldword) {
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword, readw(ram + off));
+				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
+				return RIO_FAIL;
+			}
+		}
+	}
+
+	/*
+	** Now write the INVERSE of the test data into every location, using
+	** BYTE write operations, first checking before each byte is written
+	** that the location contains the old value still, and checking after
+	** the write that the location contains the data specified - this is
+	** the BYTE read/write test.
+	*/
+	for (off=0; off<size; off++) {
+		if (op && (readb(ram + off) != oldbyte)) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
+			return RIO_FAIL;
+		}
+		writeb(invbyte, ram + off);
+		if (readb(ram + off) != invbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, readb(ram + off));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** now, use WORD operations to write the test value into every location,
+	** check as before that the location contains the previous test value
+	** before overwriting, and that it contains the data value written
+	** afterwards.
+	** This is the WORD operation test.
+	*/
+	for (off=0; off<size; off+=2) {
+		if (readw(ram + off) != invword) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, readw(ram + off));
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
+			return RIO_FAIL;
+		}
+
+		writew(newword, ram + off);
+		if ( readw(ram + off) != newword ) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** now run through the block of memory again, first in byte mode
+	** then in word mode, and check that all the locations contain the
+	** required test data.
+	*/
+	for (off=0; off<size; off++) {
+		if (readb(ram + off) != newbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
+			return RIO_FAIL;
+		}
+	}
+
+	for (off=0; off<size; off+=2) {
+		if (readw(ram + off) != newword ) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
+			return RIO_FAIL;
+		}
+	}
+
+	/*
+	** time to check out byte swapping errors
+	*/
+	swapword = invbyte | (newbyte << 8);
+
+	for (off=0; off<size; off+=2) {
+		writeb(invbyte, &ram[off]);
+		writeb(newbyte, &ram[off+1]);
+	}
+
+	for ( off=0; off<size; off+=2 ) {
+		if (readw(ram + off) != swapword) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, readw(ram + off));
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
+			return RIO_FAIL;
+		}
+		writew(~swapword, ram + off);
+	}
+
+	for (off=0; off<size; off+=2) {
+		if (readb(ram + off) != newbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
+			return RIO_FAIL;
+		}
+		if (readb(ram + off + 1) != invbyte) {
+			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, readb(ram + off + 1));
+			return RIO_FAIL;
+		}
+		writew(newword, ram + off);
+	}
+	return 0;
+}
+
+
+int RIODefaultName(struct rio_info *p, struct Host *HostP, unsigned int	UnitId)
+{
+	memcpy(HostP->Mapping[UnitId].Name, "UNKNOWN RTA X-XX", 17);
+	HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
+	if ((UnitId+1) > 9) {
+		HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10);
+		HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10);
+	}
+	else {
+		HostP->Mapping[UnitId].Name[14]='1'+UnitId;
+		HostP->Mapping[UnitId].Name[15]=0;
+	}
+	return 0;
+}
+
+#define RIO_RELEASE	"Linux"
+#define RELEASE_ID	"1.0"
+
+static struct rioVersion	stVersion;
+
+struct rioVersion *RIOVersid(void)
+{
+    strlcpy(stVersion.version, "RIO driver for linux V1.0",
+	    sizeof(stVersion.version));
+    strlcpy(stVersion.buildDate, __DATE__,
+	    sizeof(stVersion.buildDate));
+
+    return &stVersion;
+}
+
+void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot)
+{
+	/*
+	** Reset the Tpu
+	*/
+	rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: type 0x%x", Type);
+	switch ( Type ) {
+	case RIO_AT:
+		rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n");
+		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION |
+			SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
+		writeb(0xFF, &DpRamP->DpResetTpu);
+		udelay(3);
+			rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: Don't know if it worked. Try reset again\n");
+		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE |
+			BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
+		writeb(0xFF, &DpRamP->DpResetTpu);
+		udelay(3);
+		break;
+	case RIO_PCI:
+		rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
+		writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl);
+		writeb(0xFF, &DpRamP->DpResetInt);
+		writeb(0xFF, &DpRamP->DpResetTpu);
+		udelay(100);
+		break;
+	default:
+		rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
+		break;
+	}
+	return;
+}
diff --git a/drivers/staging/generic_serial/rio/riointr.c b/drivers/staging/generic_serial/rio/riointr.c
new file mode 100644
index 0000000..2e71aec
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/riointr.c
@@ -0,0 +1,645 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riointr.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:44
+**	Retrieved	: 11/6/98 10:33:49
+**
+**  ident @(#)riointr.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+#include <linux/delay.h>
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+
+
+static void RIOReceive(struct rio_info *, struct Port *);
+
+
+static char *firstchars(char *p, int nch)
+{
+	static char buf[2][128];
+	static int t = 0;
+	t = !t;
+	memcpy(buf[t], p, nch);
+	buf[t][nch] = 0;
+	return buf[t];
+}
+
+
+#define	INCR( P, I )	((P) = (((P)+(I)) & p->RIOBufferMask))
+/* Enable and start the transmission of packets */
+void RIOTxEnable(char *en)
+{
+	struct Port *PortP;
+	struct rio_info *p;
+	struct tty_struct *tty;
+	int c;
+	struct PKT __iomem *PacketP;
+	unsigned long flags;
+
+	PortP = (struct Port *) en;
+	p = (struct rio_info *) PortP->p;
+	tty = PortP->gs.port.tty;
+
+
+	rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
+
+	if (!PortP->gs.xmit_cnt)
+		return;
+
+
+	/* This routine is an order of magnitude simpler than the specialix
+	   version. One of the disadvantages is that this version will send
+	   an incomplete packet (usually 64 bytes instead of 72) once for
+	   every 4k worth of data. Let's just say that this won't influence
+	   performance significantly..... */
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	while (can_add_transmit(&PacketP, PortP)) {
+		c = PortP->gs.xmit_cnt;
+		if (c > PKT_MAX_DATA_LEN)
+			c = PKT_MAX_DATA_LEN;
+
+		/* Don't copy past the end of the source buffer */
+		if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
+			c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
+
+		{
+			int t;
+			t = (c > 10) ? 10 : c;
+
+			rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
+		}
+		/* If for one reason or another, we can't copy more data,
+		   we're done! */
+		if (c == 0)
+			break;
+
+		rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
+		/*    udelay (1); */
+
+		writeb(c, &(PacketP->len));
+		if (!(PortP->State & RIO_DELETED)) {
+			add_transmit(PortP);
+			/*
+			 ** Count chars tx'd for port statistics reporting
+			 */
+			if (PortP->statsGather)
+				PortP->txchars += c;
+		}
+		PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
+		PortP->gs.xmit_cnt -= c;
+	}
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN))
+		tty_wakeup(PortP->gs.port.tty);
+
+}
+
+
+/*
+** RIO Host Service routine. Does all the work traditionally associated with an
+** interrupt.
+*/
+static int RupIntr;
+static int RxIntr;
+static int TxIntr;
+
+void RIOServiceHost(struct rio_info *p, struct Host *HostP)
+{
+	rio_spin_lock(&HostP->HostLock);
+	if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+		static int t = 0;
+		rio_spin_unlock(&HostP->HostLock);
+		if ((t++ % 200) == 0)
+			rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
+		return;
+	}
+	rio_spin_unlock(&HostP->HostLock);
+
+	if (readw(&HostP->ParmMapP->rup_intr)) {
+		writew(0, &HostP->ParmMapP->rup_intr);
+		p->RIORupCount++;
+		RupIntr++;
+		rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts);
+		RIOPollHostCommands(p, HostP);
+	}
+
+	if (readw(&HostP->ParmMapP->rx_intr)) {
+		int port;
+
+		writew(0, &HostP->ParmMapP->rx_intr);
+		p->RIORxCount++;
+		RxIntr++;
+
+		rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts);
+		/*
+		 ** Loop through every port. If the port is mapped into
+		 ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
+		 ** worth checking. If the port isn't open, grab any packets
+		 ** hanging on its receive queue and stuff them on the free
+		 ** list; check for commands on the way.
+		 */
+		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
+			struct Port *PortP = p->RIOPortp[port];
+			struct tty_struct *ttyP;
+			struct PKT __iomem *PacketP;
+
+			/*
+			 ** not mapped in - most of the RIOPortp[] information
+			 ** has not been set up!
+			 ** Optimise: ports come in bundles of eight.
+			 */
+			if (!PortP->Mapped) {
+				port += 7;
+				continue;	/* with the next port */
+			}
+
+			/*
+			 ** If the host board isn't THIS host board, check the next one.
+			 ** optimise: ports come in bundles of eight.
+			 */
+			if (PortP->HostP != HostP) {
+				port += 7;
+				continue;
+			}
+
+			/*
+			 ** Let us see - is the port open? If not, then don't service it.
+			 */
+			if (!(PortP->PortState & PORT_ISOPEN)) {
+				continue;
+			}
+
+			/*
+			 ** find corresponding tty structure. The process of mapping
+			 ** the ports puts these here.
+			 */
+			ttyP = PortP->gs.port.tty;
+
+			/*
+			 ** Lock the port before we begin working on it.
+			 */
+			rio_spin_lock(&PortP->portSem);
+
+			/*
+			 ** Process received data if there is any.
+			 */
+			if (can_remove_receive(&PacketP, PortP))
+				RIOReceive(p, PortP);
+
+			/*
+			 ** If there is no data left to be read from the port, and
+			 ** it's handshake bit is set, then we must clear the handshake,
+			 ** so that that downstream RTA is re-enabled.
+			 */
+			if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
+				/*
+				 ** MAGIC! ( Basically, handshake the RX buffer, so that
+				 ** the RTAs upstream can be re-enabled. )
+				 */
+				rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
+				writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
+			}
+			rio_spin_unlock(&PortP->portSem);
+		}
+	}
+
+	if (readw(&HostP->ParmMapP->tx_intr)) {
+		int port;
+
+		writew(0, &HostP->ParmMapP->tx_intr);
+
+		p->RIOTxCount++;
+		TxIntr++;
+		rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts);
+
+		/*
+		 ** Loop through every port.
+		 ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
+		 ** associated ) then it is worth checking.
+		 */
+		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
+			struct Port *PortP = p->RIOPortp[port];
+			struct tty_struct *ttyP;
+			struct PKT __iomem *PacketP;
+
+			/*
+			 ** not mapped in - most of the RIOPortp[] information
+			 ** has not been set up!
+			 */
+			if (!PortP->Mapped) {
+				port += 7;
+				continue;	/* with the next port */
+			}
+
+			/*
+			 ** If the host board isn't running, then its data structures
+			 ** are no use to us - continue quietly.
+			 */
+			if (PortP->HostP != HostP) {
+				port += 7;
+				continue;	/* with the next port */
+			}
+
+			/*
+			 ** Let us see - is the port open? If not, then don't service it.
+			 */
+			if (!(PortP->PortState & PORT_ISOPEN)) {
+				continue;
+			}
+
+			rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
+			/*
+			 ** Lock the port before we begin working on it.
+			 */
+			rio_spin_lock(&PortP->portSem);
+
+			/*
+			 ** If we can't add anything to the transmit queue, then
+			 ** we need do none of this processing.
+			 */
+			if (!can_add_transmit(&PacketP, PortP)) {
+				rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
+				rio_spin_unlock(&PortP->portSem);
+				continue;
+			}
+
+			/*
+			 ** find corresponding tty structure. The process of mapping
+			 ** the ports puts these here.
+			 */
+			ttyP = PortP->gs.port.tty;
+			/* If ttyP is NULL, the port is getting closed. Forget about it. */
+			if (!ttyP) {
+				rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
+				rio_spin_unlock(&PortP->portSem);
+				continue;
+			}
+			/*
+			 ** If there is more room available we start up the transmit
+			 ** data process again. This can be direct I/O, if the cookmode
+			 ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
+			 ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
+			 ** characters via the line discipline. We must always call
+			 ** the line discipline,
+			 ** so that user input characters can be echoed correctly.
+			 **
+			 ** ++++ Update +++++
+			 ** With the advent of double buffering, we now see if
+			 ** TxBufferOut-In is non-zero. If so, then we copy a packet
+			 ** to the output place, and set it going. If this empties
+			 ** the buffer, then we must issue a wakeup( ) on OUT.
+			 ** If it frees space in the buffer then we must issue
+			 ** a wakeup( ) on IN.
+			 **
+			 ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
+			 ** have to send a WFLUSH command down the PHB, to mark the
+			 ** end point of a WFLUSH. We also need to clear out any
+			 ** data from the double buffer! ( note that WflushFlag is a
+			 ** *count* of the number of WFLUSH commands outstanding! )
+			 **
+			 ** ++++ And there's more!
+			 ** If an RTA is powered off, then on again, and rebooted,
+			 ** whilst it has ports open, then we need to re-open the ports.
+			 ** ( reasonable enough ). We can't do this when we spot the
+			 ** re-boot, in interrupt time, because the queue is probably
+			 ** full. So, when we come in here, we need to test if any
+			 ** ports are in this condition, and re-open the port before
+			 ** we try to send any more data to it. Now, the re-booted
+			 ** RTA will be discarding packets from the PHB until it
+			 ** receives this open packet, but don't worry tooo much
+			 ** about that. The one thing that is interesting is the
+			 ** combination of this effect and the WFLUSH effect!
+			 */
+			/* For now don't handle RTA reboots. -- REW.
+			   Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
+			if (PortP->MagicFlags) {
+				if (PortP->MagicFlags & MAGIC_REBOOT) {
+					/*
+					 ** well, the RTA has been rebooted, and there is room
+					 ** on its queue to add the open packet that is required.
+					 **
+					 ** The messy part of this line is trying to decide if
+					 ** we need to call the Param function as a tty or as
+					 ** a modem.
+					 ** DONT USE CLOCAL AS A TEST FOR THIS!
+					 **
+					 ** If we can't param the port, then move on to the
+					 ** next port.
+					 */
+					PortP->InUse = NOT_INUSE;
+
+					rio_spin_unlock(&PortP->portSem);
+					if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL)
+						continue;	/* with next port */
+					rio_spin_lock(&PortP->portSem);
+					PortP->MagicFlags &= ~MAGIC_REBOOT;
+				}
+
+				/*
+				 ** As mentioned above, this is a tacky hack to cope
+				 ** with WFLUSH
+				 */
+				if (PortP->WflushFlag) {
+					rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
+
+					if (PortP->InUse)
+						rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
+				}
+
+				while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
+					int p;
+					struct PktCmd __iomem *PktCmdP;
+
+					rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
+					/*
+					 ** make it look just like a WFLUSH command
+					 */
+					PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
+
+					writeb(RIOC_WFLUSH, &PktCmdP->Command);
+
+					p = PortP->HostPort % (u16) PORTS_PER_RTA;
+
+					/*
+					 ** If second block of ports for 16 port RTA, add 8
+					 ** to index 8-15.
+					 */
+					if (PortP->SecondBlock)
+						p += PORTS_PER_RTA;
+
+					writeb(p, &PktCmdP->PhbNum);
+
+					/*
+					 ** to make debuggery easier
+					 */
+					writeb('W', &PacketP->data[2]);
+					writeb('F', &PacketP->data[3]);
+					writeb('L', &PacketP->data[4]);
+					writeb('U', &PacketP->data[5]);
+					writeb('S', &PacketP->data[6]);
+					writeb('H', &PacketP->data[7]);
+					writeb(' ', &PacketP->data[8]);
+					writeb('0' + PortP->WflushFlag, &PacketP->data[9]);
+					writeb(' ', &PacketP->data[10]);
+					writeb(' ', &PacketP->data[11]);
+					writeb('\0', &PacketP->data[12]);
+
+					/*
+					 ** its two bytes long!
+					 */
+					writeb(PKT_CMD_BIT | 2, &PacketP->len);
+
+					/*
+					 ** queue it!
+					 */
+					if (!(PortP->State & RIO_DELETED)) {
+						add_transmit(PortP);
+						/*
+						 ** Count chars tx'd for port statistics reporting
+						 */
+						if (PortP->statsGather)
+							PortP->txchars += 2;
+					}
+
+					if (--(PortP->WflushFlag) == 0) {
+						PortP->MagicFlags &= ~MAGIC_FLUSH;
+					}
+
+					rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
+				}
+				if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
+					if (PortP->MagicFlags & MAGIC_FLUSH) {
+						PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
+					} else {
+						if (!can_add_transmit(&PacketP, PortP)) {
+							rio_spin_unlock(&PortP->portSem);
+							continue;
+						}
+						rio_spin_unlock(&PortP->portSem);
+						RIOTxEnable((char *) PortP);
+						rio_spin_lock(&PortP->portSem);
+						PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
+					}
+				}
+			}
+
+
+			/*
+			 ** If we can't add anything to the transmit queue, then
+			 ** we need do none of the remaining processing.
+			 */
+			if (!can_add_transmit(&PacketP, PortP)) {
+				rio_spin_unlock(&PortP->portSem);
+				continue;
+			}
+
+			rio_spin_unlock(&PortP->portSem);
+			RIOTxEnable((char *) PortP);
+		}
+	}
+}
+
+/*
+** Routine for handling received data for tty drivers
+*/
+static void RIOReceive(struct rio_info *p, struct Port *PortP)
+{
+	struct tty_struct *TtyP;
+	unsigned short transCount;
+	struct PKT __iomem *PacketP;
+	register unsigned int DataCnt;
+	unsigned char __iomem *ptr;
+	unsigned char *buf;
+	int copied = 0;
+
+	static int intCount, RxIntCnt;
+
+	/*
+	 ** The receive data process is to remove packets from the
+	 ** PHB until there aren't any more or the current cblock
+	 ** is full. When this occurs, there will be some left over
+	 ** data in the packet, that we must do something with.
+	 ** As we haven't unhooked the packet from the read list
+	 ** yet, we can just leave the packet there, having first
+	 ** made a note of how far we got. This means that we need
+	 ** a pointer per port saying where we start taking the
+	 ** data from - this will normally be zero, but when we
+	 ** run out of space it will be set to the offset of the
+	 ** next byte to copy from the packet data area. The packet
+	 ** length field is decremented by the number of bytes that
+	 ** we successfully removed from the packet. When this reaches
+	 ** zero, we reset the offset pointer to be zero, and free
+	 ** the packet from the front of the queue.
+	 */
+
+	intCount++;
+
+	TtyP = PortP->gs.port.tty;
+	if (!TtyP) {
+		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
+		return;
+	}
+
+	if (PortP->State & RIO_THROTTLE_RX) {
+		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
+		return;
+	}
+
+	if (PortP->State & RIO_DELETED) {
+		while (can_remove_receive(&PacketP, PortP)) {
+			remove_receive(PortP);
+			put_free_end(PortP->HostP, PacketP);
+		}
+	} else {
+		/*
+		 ** loop, just so long as:
+		 **   i ) there's some data ( i.e. can_remove_receive )
+		 **  ii ) we haven't been blocked
+		 ** iii ) there's somewhere to put the data
+		 **  iv ) we haven't outstayed our welcome
+		 */
+		transCount = 1;
+		while (can_remove_receive(&PacketP, PortP)
+		       && transCount) {
+			RxIntCnt++;
+
+			/*
+			 ** check that it is not a command!
+			 */
+			if (readb(&PacketP->len) & PKT_CMD_BIT) {
+				rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
+				/*      rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
+				rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit));
+				rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port));
+				rio_dprintk(RIO_DEBUG_INTR, " src_unit  = %d\n", readb(&PacketP->src_unit));
+				rio_dprintk(RIO_DEBUG_INTR, " src_port  = %d\n", readb(&PacketP->src_port));
+				rio_dprintk(RIO_DEBUG_INTR, " len	   = %d\n", readb(&PacketP->len));
+				rio_dprintk(RIO_DEBUG_INTR, " control   = %d\n", readb(&PacketP->control));
+				rio_dprintk(RIO_DEBUG_INTR, " csum	   = %d\n", readw(&PacketP->csum));
+				rio_dprintk(RIO_DEBUG_INTR, "	 data bytes: ");
+				for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
+					rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt]));
+				remove_receive(PortP);
+				put_free_end(PortP->HostP, PacketP);
+				continue;	/* with next packet */
+			}
+
+			/*
+			 ** How many characters can we move 'upstream' ?
+			 **
+			 ** Determine the minimum of the amount of data
+			 ** available and the amount of space in which to
+			 ** put it.
+			 **
+			 ** 1.        Get the packet length by masking 'len'
+			 **   for only the length bits.
+			 ** 2.        Available space is [buffer size] - [space used]
+			 **
+			 ** Transfer count is the minimum of packet length
+			 ** and available space.
+			 */
+
+			transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK);
+			rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
+			/*
+			 ** To use the following 'kkprintfs' for debugging - change the '#undef'
+			 ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
+			 ** driver).
+			 */
+			ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart;
+
+			tty_prepare_flip_string(TtyP, &buf, transCount);
+			rio_memcpy_fromio(buf, ptr, transCount);
+			PortP->RxDataStart += transCount;
+			writeb(readb(&PacketP->len)-transCount, &PacketP->len);
+			copied += transCount;
+
+
+
+			if (readb(&PacketP->len) == 0) {
+				/*
+				 ** If we have emptied the packet, then we can
+				 ** free it, and reset the start pointer for
+				 ** the next packet.
+				 */
+				remove_receive(PortP);
+				put_free_end(PortP->HostP, PacketP);
+				PortP->RxDataStart = 0;
+			}
+		}
+	}
+	if (copied) {
+		rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
+		tty_flip_buffer_push(TtyP);
+	}
+
+	return;
+}
+
diff --git a/drivers/staging/generic_serial/rio/rioioctl.h b/drivers/staging/generic_serial/rio/rioioctl.h
new file mode 100644
index 0000000..e8af5b3
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioioctl.h
@@ -0,0 +1,57 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioioctl.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)rioioctl.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef	__rioioctl_h__
+#define	__rioioctl_h__
+
+/*
+** RIO device driver - user ioctls and associated structures.
+*/
+
+struct portStats {
+	int port;
+	int gather;
+	unsigned long txchars;
+	unsigned long rxchars;
+	unsigned long opens;
+	unsigned long closes;
+	unsigned long ioctls;
+};
+
+#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
+
+#define	RIO_QUICK_CHECK	  	(RIOC | 105)
+#define RIO_GATHER_PORT_STATS	(RIOC | 193)
+#define RIO_RESET_PORT_STATS	(RIOC | 194)
+#define RIO_GET_PORT_STATS	(RIOC | 195)
+
+#endif				/* __rioioctl_h__ */
diff --git a/drivers/staging/generic_serial/rio/rioparam.c b/drivers/staging/generic_serial/rio/rioparam.c
new file mode 100644
index 0000000..6415f3f
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioparam.c
@@ -0,0 +1,663 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioparam.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:45
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)rioparam.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+
+
+
+/*
+** The Scam, based on email from jeremyr@bugs.specialix.co.uk....
+**
+** To send a command on a particular port, you put a packet with the
+** command bit set onto the port. The command bit is in the len field,
+** and gets ORed in with the actual byte count.
+**
+** When you send a packet with the command bit set the first
+** data byte (data[0]) is interpreted as the command to execute.
+** It also governs what data structure overlay should accompany the packet.
+** Commands are defined in cirrus/cirrus.h
+**
+** If you want the command to pre-emt data already on the queue for the
+** port, set the pre-emptive bit in conjunction with the command bit.
+** It is not defined what will happen if you set the preemptive bit
+** on a packet that is NOT a command.
+**
+** Pre-emptive commands should be queued at the head of the queue using
+** add_start(), whereas normal commands and data are enqueued using
+** add_end().
+**
+** Most commands do not use the remaining bytes in the data array. The
+** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
+** OPEN are currently analogous). With these three commands the following
+** 11 data bytes are all used to pass config information such as baud rate etc.
+** The fields are also defined in cirrus.h. Some contain straightforward
+** information such as the transmit XON character. Two contain the transmit and
+** receive baud rates respectively. For most baud rates there is a direct
+** mapping between the rates defined in <sys/termio.h> and the byte in the
+** packet. There are additional (non UNIX-standard) rates defined in
+** /u/dos/rio/cirrus/h/brates.h.
+**
+** The rest of the data fields contain approximations to the Cirrus registers
+** that are used to program number of bits etc. Each registers bit fields is
+** defined in cirrus.h.
+** 
+** NB. Only use those bits that are defined as being driver specific
+** or common to the RTA and the driver.
+** 
+** All commands going from RTA->Host will be dealt with by the Host code - you
+** will never see them. As with the SI there will be three fields to look out
+** for in each phb (not yet defined - needs defining a.s.a.p).
+** 
+** modem_status	- current state of handshake pins.
+**
+** port_status	 - current port status - equivalent to hi_stat for SI, indicates
+** if port is IDLE_OPEN, IDLE_CLOSED etc.
+**
+** break_status	- bit X set if break has been received.
+** 
+** Happy hacking.
+** 
+*/
+
+/* 
+** RIOParam is used to open or configure a port. You pass it a PortP,
+** which will have a tty struct attached to it. You also pass a command,
+** either OPEN or CONFIG. The port's setup is taken from the t_ fields
+** of the tty struct inside the PortP, and the port is either opened
+** or re-configured. You must also tell RIOParam if the device is a modem
+** device or not (i.e. top bit of minor number set or clear - take special
+** care when deciding on this!).
+** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
+**
+** RIOParam assumes it will be called at splrio(), and also assumes
+** that CookMode is set correctly in the port structure.
+**
+** NB. for MPX
+**	tty lock must NOT have been previously acquired.
+*/
+int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
+{
+	struct tty_struct *TtyP;
+	int retval;
+	struct phb_param __iomem *phb_param_ptr;
+	struct PKT __iomem *PacketP;
+	int res;
+	u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
+	u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
+	u8 LNext = 0, TxBaud = 0, RxBaud = 0;
+	int retries = 0xff;
+	unsigned long flags;
+
+	func_enter();
+
+	TtyP = PortP->gs.port.tty;
+
+	rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
+
+	if (!TtyP) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
+
+		func_exit();
+
+		return RIO_FAIL;
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	if (cmd == RIOC_OPEN) {
+		/*
+		 ** If the port is set to store or lock the parameters, and it is
+		 ** paramed with OPEN, we want to restore the saved port termio, but
+		 ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
+		 */
+	}
+
+	/*
+	 ** wait for space
+	 */
+	while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
+		if (retries-- <= 0) {
+			break;
+		}
+		if (PortP->InUse != NOT_INUSE) {
+			rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
+		}
+
+		if (!res) {
+			rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
+		}
+
+		if (SleepFlag != OK_TO_SLEEP) {
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			func_exit();
+
+			return RIO_FAIL;
+		}
+
+		rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		retval = RIODelay(PortP, HUNDRED_MS);
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		if (retval == RIO_FAIL) {
+			rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			func_exit();
+			return -EINTR;
+		}
+		if (PortP->State & RIO_DELETED) {
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			func_exit();
+			return 0;
+		}
+	}
+
+	if (!res) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		func_exit();
+
+		return RIO_FAIL;
+	}
+
+	rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
+	rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);
+
+	phb_param_ptr = (struct phb_param __iomem *) PacketP->data;
+
+
+	switch (TtyP->termios->c_cflag & CSIZE) {
+	case CS5:
+		{
+			rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
+			Cor1 |= RIOC_COR1_5BITS;
+			break;
+		}
+	case CS6:
+		{
+			rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
+			Cor1 |= RIOC_COR1_6BITS;
+			break;
+		}
+	case CS7:
+		{
+			rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
+			Cor1 |= RIOC_COR1_7BITS;
+			break;
+		}
+	case CS8:
+		{
+			rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
+			Cor1 |= RIOC_COR1_8BITS;
+			break;
+		}
+	}
+
+	if (TtyP->termios->c_cflag & CSTOPB) {
+		rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
+		Cor1 |= RIOC_COR1_2STOP;
+	} else {
+		rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
+		Cor1 |= RIOC_COR1_1STOP;
+	}
+
+	if (TtyP->termios->c_cflag & PARENB) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
+		Cor1 |= RIOC_COR1_NORMAL;
+	} else {
+		rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
+		Cor1 |= RIOC_COR1_NOP;
+	}
+	if (TtyP->termios->c_cflag & PARODD) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
+		Cor1 |= RIOC_COR1_ODD;
+	} else {
+		rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
+		Cor1 |= RIOC_COR1_EVEN;
+	}
+
+	/*
+	 ** COR 2
+	 */
+	if (TtyP->termios->c_iflag & IXON) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
+		Cor2 |= RIOC_COR2_IXON;
+	} else {
+		if (PortP->Config & RIO_IXON) {
+			rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
+			Cor2 |= RIOC_COR2_IXON;
+		} else
+			rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
+	}
+
+	if (TtyP->termios->c_iflag & IXANY) {
+		if (PortP->Config & RIO_IXANY) {
+			rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
+			Cor2 |= RIOC_COR2_IXANY;
+		} else
+			rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
+	}
+
+	if (TtyP->termios->c_iflag & IXOFF) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
+		Cor2 |= RIOC_COR2_IXOFF;
+	}
+
+	if (TtyP->termios->c_cflag & HUPCL) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
+		Cor2 |= RIOC_COR2_HUPCL;
+	}
+
+	if (C_CRTSCTS(TtyP)) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
+		Cor2 |= RIOC_COR2_CTSFLOW;
+		Cor2 |= RIOC_COR2_RTSFLOW;
+	} else {
+		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
+		Cor2 &= ~RIOC_COR2_CTSFLOW;
+		Cor2 &= ~RIOC_COR2_RTSFLOW;
+	}
+
+
+	if (TtyP->termios->c_cflag & CLOCAL) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
+	} else {
+		rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
+	}
+
+	/*
+	 ** COR 4 (there is no COR 3)
+	 */
+	if (TtyP->termios->c_iflag & IGNBRK) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
+		Cor4 |= RIOC_COR4_IGNBRK;
+	}
+	if (!(TtyP->termios->c_iflag & BRKINT)) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
+		Cor4 |= RIOC_COR4_NBRKINT;
+	} else {
+		rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on	break condition\n");
+	}
+
+	if (TtyP->termios->c_iflag & INLCR) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
+		Cor4 |= RIOC_COR4_INLCR;
+	}
+
+	if (TtyP->termios->c_iflag & IGNCR) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
+		Cor4 |= RIOC_COR4_IGNCR;
+	}
+
+	if (TtyP->termios->c_iflag & ICRNL) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
+		Cor4 |= RIOC_COR4_ICRNL;
+	}
+	if (TtyP->termios->c_iflag & IGNPAR) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
+		Cor4 |= RIOC_COR4_IGNPAR;
+	}
+	if (TtyP->termios->c_iflag & PARMRK) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
+		Cor4 |= RIOC_COR4_PARMRK;
+	}
+
+	/*
+	 ** Set the RAISEMOD flag to ensure that the modem lines are raised
+	 ** on reception of a config packet.
+	 ** The download code handles the zero baud condition.
+	 */
+	Cor4 |= RIOC_COR4_RAISEMOD;
+
+	/*
+	 ** COR 5
+	 */
+
+	Cor5 = RIOC_COR5_CMOE;
+
+	/*
+	 ** Set to monitor tbusy/tstop (or not).
+	 */
+
+	if (PortP->MonitorTstate)
+		Cor5 |= RIOC_COR5_TSTATE_ON;
+	else
+		Cor5 |= RIOC_COR5_TSTATE_OFF;
+
+	/*
+	 ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
+	 */
+	if (TtyP->termios->c_iflag & ISTRIP) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
+		if (!(PortP->State & RIO_TRIAD_MODE)) {
+			Cor5 |= RIOC_COR5_ISTRIP;
+		}
+	}
+
+	if (TtyP->termios->c_oflag & ONLCR) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
+		if (PortP->CookMode == COOK_MEDIUM)
+			Cor5 |= RIOC_COR5_ONLCR;
+	}
+	if (TtyP->termios->c_oflag & OCRNL) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
+		if (PortP->CookMode == COOK_MEDIUM)
+			Cor5 |= RIOC_COR5_OCRNL;
+	}
+	if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
+		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
+		if (PortP->CookMode == COOK_MEDIUM)
+			Cor5 |= RIOC_COR5_TAB3;
+	}
+
+	/*
+	 ** Flow control bytes.
+	 */
+	TxXon = TtyP->termios->c_cc[VSTART];
+	TxXoff = TtyP->termios->c_cc[VSTOP];
+	RxXon = TtyP->termios->c_cc[VSTART];
+	RxXoff = TtyP->termios->c_cc[VSTOP];
+	/*
+	 ** LNEXT byte
+	 */
+	LNext = 0;
+
+	/*
+	 ** Baud rate bytes
+	 */
+	rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);
+
+	switch (TtyP->termios->c_cflag & CBAUD) {
+#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
+		e(50);
+		e(75);
+		e(110);
+		e(134);
+		e(150);
+		e(200);
+		e(300);
+		e(600);
+		e(1200);
+		e(1800);
+		e(2400);
+		e(4800);
+		e(9600);
+		e(19200);
+		e(38400);
+		e(57600);
+		e(115200);	/* e(230400);e(460800); e(921600);  */
+	}
+
+	rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
+
+
+	/*
+	 ** Leftovers
+	 */
+	if (TtyP->termios->c_cflag & CREAD)
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
+#ifdef RCV1EN
+	if (TtyP->termios->c_cflag & RCV1EN)
+		rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
+#endif
+#ifdef XMT1EN
+	if (TtyP->termios->c_cflag & XMT1EN)
+		rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
+#endif
+	if (TtyP->termios->c_lflag & ISIG)
+		rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
+	if (TtyP->termios->c_lflag & ICANON)
+		rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
+	if (TtyP->termios->c_lflag & XCASE)
+		rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
+	if (TtyP->termios->c_lflag & ECHO)
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
+	if (TtyP->termios->c_lflag & ECHOE)
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
+	if (TtyP->termios->c_lflag & ECHOK)
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
+	if (TtyP->termios->c_lflag & ECHONL)
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
+	if (TtyP->termios->c_lflag & NOFLSH)
+		rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
+#ifdef TOSTOP
+	if (TtyP->termios->c_lflag & TOSTOP)
+		rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
+#endif
+#ifdef XCLUDE
+	if (TtyP->termios->c_lflag & XCLUDE)
+		rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
+#endif
+	if (TtyP->termios->c_iflag & IUCLC)
+		rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
+	if (TtyP->termios->c_oflag & OPOST)
+		rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
+	if (TtyP->termios->c_oflag & OLCUC)
+		rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
+	if (TtyP->termios->c_oflag & ONOCR)
+		rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
+	if (TtyP->termios->c_oflag & ONLRET)
+		rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
+	if (TtyP->termios->c_oflag & OFILL)
+		rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
+	if (TtyP->termios->c_oflag & OFDEL)
+		rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
+	if (TtyP->termios->c_oflag & NLDLY)
+		rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
+	if (TtyP->termios->c_oflag & CRDLY)
+		rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
+	if (TtyP->termios->c_oflag & TABDLY)
+		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
+	/*
+	 ** These things are kind of useful in a later life!
+	 */
+	PortP->Cor2Copy = Cor2;
+
+	if (PortP->State & RIO_DELETED) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		func_exit();
+
+		return RIO_FAIL;
+	}
+
+	/*
+	 ** Actually write the info into the packet to be sent
+	 */
+	writeb(cmd, &phb_param_ptr->Cmd);
+	writeb(Cor1, &phb_param_ptr->Cor1);
+	writeb(Cor2, &phb_param_ptr->Cor2);
+	writeb(Cor4, &phb_param_ptr->Cor4);
+	writeb(Cor5, &phb_param_ptr->Cor5);
+	writeb(TxXon, &phb_param_ptr->TxXon);
+	writeb(RxXon, &phb_param_ptr->RxXon);
+	writeb(TxXoff, &phb_param_ptr->TxXoff);
+	writeb(RxXoff, &phb_param_ptr->RxXoff);
+	writeb(LNext, &phb_param_ptr->LNext);
+	writeb(TxBaud, &phb_param_ptr->TxBaud);
+	writeb(RxBaud, &phb_param_ptr->RxBaud);
+
+	/*
+	 ** Set the length/command field
+	 */
+	writeb(12 | PKT_CMD_BIT, &PacketP->len);
+
+	/*
+	 ** The packet is formed - now, whack it off
+	 ** to its final destination:
+	 */
+	add_transmit(PortP);
+	/*
+	 ** Count characters transmitted for port statistics reporting
+	 */
+	if (PortP->statsGather)
+		PortP->txchars += 12;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
+	/*
+	 ** job done.
+	 */
+	func_exit();
+
+	return 0;
+}
+
+
+/*
+** We can add another packet to a transmit queue if the packet pointer pointed
+** to by the TxAdd pointer has PKT_IN_USE clear in its address.
+*/
+int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP)
+{
+	struct PKT __iomem *tp;
+
+	*PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));
+
+	return !((unsigned long) tp & PKT_IN_USE);
+}
+
+/*
+** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
+** and then move the TxAdd pointer along one position to point to the next
+** packet pointer. You must wrap the pointer from the end back to the start.
+*/
+void add_transmit(struct Port *PortP)
+{
+	if (readw(PortP->TxAdd) & PKT_IN_USE) {
+		rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
+	}
+	writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd);
+	PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1;
+	writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add);
+}
+
+/****************************************
+ * Put a packet onto the end of the
+ * free list
+ ****************************************/
+void put_free_end(struct Host *HostP, struct PKT __iomem *PktP)
+{
+	struct rio_free_list __iomem *tmp_pointer;
+	unsigned short old_end, new_end;
+	unsigned long flags;
+
+	rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+	 /*************************************************
+	* Put a packet back onto the back of the free list
+	*
+	************************************************/
+
+	rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP);
+
+	if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) {
+		new_end = RIO_OFF(HostP->Caddr, PktP);
+		tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end);
+		writew(new_end, &tmp_pointer->next);
+		writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev);
+		writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next);
+		writew(new_end, &HostP->ParmMapP->free_list_end);
+	} else {		/* First packet on the free list this should never happen! */
+		rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
+		writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end);
+		tmp_pointer = (struct rio_free_list __iomem *) PktP;
+		writew(TPNULL, &tmp_pointer->prev);
+		writew(TPNULL, &tmp_pointer->next);
+	}
+	rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
+	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+}
+
+/*
+** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
+** for the next packet on the queue. It will also set PktP to point to the
+** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
+** then can_remove_receive() returns 0.
+*/
+int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP)
+{
+	if (readw(PortP->RxRemove) & PKT_IN_USE) {
+		*PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+** To remove a packet from the receive queue you clear its PKT_IN_USE bit,
+** and then bump the pointers. Once the pointers get to the end, they must
+** be wrapped back to the start.
+*/
+void remove_receive(struct Port *PortP)
+{
+	writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove);
+	PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1;
+	writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove);
+}
diff --git a/drivers/staging/generic_serial/rio/rioroute.c b/drivers/staging/generic_serial/rio/rioroute.c
new file mode 100644
index 0000000..f9b936a
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rioroute.c
@@ -0,0 +1,1039 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: rioroute.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:46
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)rioroute.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+
+static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int);
+static int RIOIsolate(struct rio_info *, struct Host *, unsigned int);
+static int RIOCheck(struct Host *, unsigned int);
+static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int);
+
+
+/*
+** Incoming on the ROUTE_RUP
+** I wrote this while I was tired. Forgive me.
+*/
+int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
+{
+	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
+	struct PktCmd_M *PktReplyP;
+	struct CmdBlk *CmdBlkP;
+	struct Port *PortP;
+	struct Map *MapP;
+	struct Top *TopP;
+	int ThisLink, ThisLinkMin, ThisLinkMax;
+	int port;
+	int Mod, Mod1, Mod2;
+	unsigned short RtaType;
+	unsigned int RtaUniq;
+	unsigned int ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */
+	unsigned int OldUnit, NewUnit, OldLink, NewLink;
+	char *MyType, *MyName;
+	int Lies;
+	unsigned long flags;
+
+	/*
+	 ** Is this unit telling us it's current link topology?
+	 */
+	if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) {
+		MapP = HostP->Mapping;
+
+		/*
+		 ** The packet can be sent either by the host or by an RTA.
+		 ** If it comes from the host, then we need to fill in the
+		 ** Topology array in the host structure. If it came in
+		 ** from an RTA then we need to fill in the Mapping structure's
+		 ** Topology array for the unit.
+		 */
+		if (Rup >= (unsigned short) MAX_RUP) {
+			ThisUnit = HOST_ID;
+			TopP = HostP->Topology;
+			MyType = "Host";
+			MyName = HostP->Name;
+			ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
+		} else {
+			ThisUnit = Rup + 1;
+			TopP = HostP->Mapping[Rup].Topology;
+			MyType = "RTA";
+			MyName = HostP->Mapping[Rup].Name;
+			ThisLinkMin = 0;
+			ThisLinkMax = LINKS_PER_UNIT - 1;
+		}
+
+		/*
+		 ** Lies will not be tolerated.
+		 ** If any pair of links claim to be connected to the same
+		 ** place, then ignore this packet completely.
+		 */
+		Lies = 0;
+		for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
+			/*
+			 ** it won't lie about network interconnect, total disconnects
+			 ** and no-IDs. (or at least, it doesn't *matter* if it does)
+			 */
+			if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP)
+				continue;
+
+			for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
+				if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) {
+					Lies++;
+				}
+			}
+		}
+
+		if (Lies) {
+			rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
+			rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
+				    readb(&PktCmdP->RouteTopology[0].Unit),
+				    'A' + readb(&PktCmdP->RouteTopology[0].Link),
+				    readb(&PktCmdP->RouteTopology[1].Unit),
+				    'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link));
+			return 1;
+		}
+
+		/*
+		 ** now, process each link.
+		 */
+		for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
+			/*
+			 ** this is what it was connected to
+			 */
+			OldUnit = TopP[ThisLink].Unit;
+			OldLink = TopP[ThisLink].Link;
+
+			/*
+			 ** this is what it is now connected to
+			 */
+			NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit);
+			NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link);
+
+			if (OldUnit != NewUnit || OldLink != NewLink) {
+				/*
+				 ** something has changed!
+				 */
+
+				if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
+					rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
+				} else {
+					/*
+					 ** put the new values in
+					 */
+					TopP[ThisLink].Unit = NewUnit;
+					TopP[ThisLink].Link = NewLink;
+
+					RIOSetChange(p);
+
+					if (OldUnit <= MAX_RUP) {
+						/*
+						 ** If something has become bust, then re-enable them messages
+						 */
+						if (!p->RIONoMessage)
+							RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
+					}
+
+					if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
+						RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
+
+					if (NewUnit == ROUTE_NO_ID)
+						rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
+
+					if (NewUnit == ROUTE_INTERCONNECT) {
+						if (!p->RIONoMessage)
+							printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
+					}
+
+					/*
+					 ** perform an update for 'the other end', so that these messages
+					 ** only appears once. Only disconnect the other end if it is pointing
+					 ** at us!
+					 */
+					if (OldUnit == HOST_ID) {
+						if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
+							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
+							HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
+							HostP->Topology[OldLink].Link = NO_LINK;
+						} else {
+							rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
+						}
+					} else if (OldUnit <= MAX_RUP) {
+						if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
+							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
+							HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
+							HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
+						} else {
+							rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
+						}
+					}
+					if (NewUnit == HOST_ID) {
+						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
+						HostP->Topology[NewLink].Unit = ThisUnit;
+						HostP->Topology[NewLink].Link = ThisLink;
+					} else if (NewUnit <= MAX_RUP) {
+						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
+						HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
+						HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
+					}
+				}
+				RIOSetChange(p);
+				RIOCheckIsolated(p, HostP, OldUnit);
+			}
+		}
+		return 1;
+	}
+
+	/*
+	 ** The only other command we recognise is a route_request command
+	 */
+	if (readb(&PktCmdP->Command) != ROUTE_REQUEST) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP);
+		return 1;
+	}
+
+	RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
+
+	/*
+	 ** Determine if 8 or 16 port RTA
+	 */
+	RtaType = GetUnitType(RtaUniq);
+
+	rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
+
+	Mod = readb(&PktCmdP->ModuleTypes);
+	Mod1 = LONYBLE(Mod);
+	if (RtaType == TYPE_RTA16) {
+		/*
+		 ** Only one ident is set for a 16 port RTA. To make compatible
+		 ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
+		 */
+		Mod2 = Mod1;
+		rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
+	} else {
+		Mod2 = HINYBLE(Mod);
+		rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
+	}
+
+	/*
+	 ** try to unhook a command block from the command free list.
+	 */
+	if (!(CmdBlkP = RIOGetCmdBlk())) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
+		return 0;
+	}
+
+	/*
+	 ** Fill in the default info on the command block
+	 */
+	CmdBlkP->Packet.dest_unit = Rup;
+	CmdBlkP->Packet.dest_port = ROUTE_RUP;
+	CmdBlkP->Packet.src_unit = HOST_ID;
+	CmdBlkP->Packet.src_port = ROUTE_RUP;
+	CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
+	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
+	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
+
+	if (!RIOBootOk(p, HostP, RtaUniq)) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
+		PktReplyP->Command = ROUTE_FOAD;
+		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
+		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+		return 1;
+	}
+
+	/*
+	 ** Check to see if the RTA is configured for this host
+	 */
+	for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
+			    ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
+
+		/*
+		 ** We have an entry for it.
+		 */
+		if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
+			if (RtaType == TYPE_RTA16) {
+				ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
+				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
+			} else
+				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
+			/*
+			 ** If we have no knowledge of booting it, then the host has
+			 ** been re-booted, and so we must kill the RTA, so that it
+			 ** will be booted again (potentially with new bins)
+			 ** and it will then re-ask for an ID, which we will service.
+			 */
+			if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
+				if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
+					if (!p->RIONoMessage)
+						printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
+					HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
+				}
+				PktReplyP->Command = ROUTE_FOAD;
+				memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
+				RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+				return 1;
+			}
+
+			/*
+			 ** Send the ID (entry) to this RTA. The ID number is implicit as
+			 ** the offset into the table. It is worth noting at this stage
+			 ** that offset zero in the table contains the entries for the
+			 ** RTA with ID 1!!!!
+			 */
+			PktReplyP->Command = ROUTE_ALLOCATE;
+			PktReplyP->IDNum = ThisUnit + 1;
+			if (RtaType == TYPE_RTA16) {
+				if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
+					/*
+					 ** Adjust the phb and tx pkt dest_units for 2nd block of 8
+					 ** only if the RTA has ports associated (SLOT_IN_USE)
+					 */
+					RIOFixPhbs(p, HostP, ThisUnit2);
+				PktReplyP->IDNum2 = ThisUnit2 + 1;
+				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
+			} else {
+				PktReplyP->IDNum2 = ROUTE_NO_ID;
+				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
+			}
+			memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10);
+
+			RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+
+			/*
+			 ** If this is a freshly booted RTA, then we need to re-open
+			 ** the ports, if any where open, so that data may once more
+			 ** flow around the system!
+			 */
+			if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
+				/*
+				 ** look at the ports associated with this beast and
+				 ** see if any where open. If they was, then re-open
+				 ** them, using the info from the tty flags.
+				 */
+				for (port = 0; port < PORTS_PER_RTA; port++) {
+					PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
+					if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+						rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
+						rio_spin_lock_irqsave(&PortP->portSem, flags);
+						PortP->MagicFlags |= MAGIC_REBOOT;
+						rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					}
+				}
+				if (RtaType == TYPE_RTA16) {
+					for (port = 0; port < PORTS_PER_RTA; port++) {
+						PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
+						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+							rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
+							rio_spin_lock_irqsave(&PortP->portSem, flags);
+							PortP->MagicFlags |= MAGIC_REBOOT;
+							rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+						}
+					}
+				}
+			}
+
+			/*
+			 ** keep a copy of the module types!
+			 */
+			HostP->UnixRups[ThisUnit].ModTypes = Mod;
+			if (RtaType == TYPE_RTA16)
+				HostP->UnixRups[ThisUnit2].ModTypes = Mod;
+
+			/*
+			 ** If either of the modules on this unit is read-only or write-only
+			 ** or none-xprint, then we need to transfer that info over to the
+			 ** relevant ports.
+			 */
+			if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
+				for (port = 0; port < PORTS_PER_MODULE; port++) {
+					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
+					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+				}
+				if (RtaType == TYPE_RTA16) {
+					for (port = 0; port < PORTS_PER_MODULE; port++) {
+						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
+						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
+						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
+					}
+				}
+			}
+
+			/*
+			 ** Job done, get on with the interrupts!
+			 */
+			return 1;
+		}
+	}
+	/*
+	 ** There is no table entry for this RTA at all.
+	 **
+	 ** Lets check to see if we actually booted this unit - if not,
+	 ** then we reset it and it will go round the loop of being booted
+	 ** we can then worry about trying to fit it into the table.
+	 */
+	for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
+		if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
+			break;
+	if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
+		/*
+		 ** if the unit wasn't in the table, and the table wasn't full, then
+		 ** we reset the unit, because we didn't boot it.
+		 ** However, if the table is full, it could be that we did boot
+		 ** this unit, and so we won't reboot it, because it isn't really
+		 ** all that disasterous to keep the old bins in most cases. This
+		 ** is a rather tacky feature, but we are on the edge of reallity
+		 ** here, because the implication is that someone has connected
+		 ** 16+MAX_EXTRA_UNITS onto one host.
+		 */
+		static int UnknownMesgDone = 0;
+
+		if (!UnknownMesgDone) {
+			if (!p->RIONoMessage)
+				printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n");
+			UnknownMesgDone = 1;
+		}
+
+		PktReplyP->Command = ROUTE_FOAD;
+		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
+	} else {
+		/*
+		 ** we did boot it (as an extra), and there may now be a table
+		 ** slot free (because of a delete), so we will try to make
+		 ** a tentative entry for it, so that the configurator can see it
+		 ** and fill in the details for us.
+		 */
+		if (RtaType == TYPE_RTA16) {
+			if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
+				RIODefaultName(p, HostP, ThisUnit);
+				rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP);
+			}
+		} else {
+			if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
+				RIODefaultName(p, HostP, ThisUnit);
+				rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP);
+			}
+		}
+		PktReplyP->Command = ROUTE_USED;
+		memcpy(PktReplyP->CommandText, "RT_USED", 7);
+	}
+	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
+	return 1;
+}
+
+
+void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit)
+{
+	unsigned short link, port;
+	struct Port *PortP;
+	unsigned long flags;
+	int PortN = HostP->Mapping[unit].SysPort;
+
+	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
+
+	if (PortN != -1) {
+		unsigned short dest_unit = HostP->Mapping[unit].ID2;
+
+		/*
+		 ** Get the link number used for the 1st 8 phbs on this unit.
+		 */
+		PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
+
+		link = readw(&PortP->PhbP->link);
+
+		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
+			unsigned short dest_port = port + 8;
+			u16 __iomem *TxPktP;
+			struct PKT __iomem *Pkt;
+
+			PortP = p->RIOPortp[PortN];
+
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			/*
+			 ** If RTA is not powered on, the tx packets will be
+			 ** unset, so go no further.
+			 */
+			if (!PortP->TxStart) {
+				rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				break;
+			}
+
+			/*
+			 ** For the second slot of a 16 port RTA, the driver needs to
+			 ** sort out the phb to port mappings. The dest_unit for this
+			 ** group of 8 phbs is set to the dest_unit of the accompanying
+			 ** 8 port block. The dest_port of the second unit is set to
+			 ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
+			 ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
+			 ** (being the second map ID) will be sent to dest_unit 5, port
+			 ** 14. When this RTA is deleted, dest_unit for ID 6 will be
+			 ** restored, and the dest_port will be reduced by 8.
+			 ** Transmit packets also have a destination field which needs
+			 ** adjusting in the same manner.
+			 ** Note that the unit/port bytes in 'dest' are swapped.
+			 ** We also need to adjust the phb and rup link numbers for the
+			 ** second block of 8 ttys.
+			 */
+			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
+				/*
+				 ** *TxPktP is the pointer to the transmit packet on the host
+				 ** card. This needs to be translated into a 32 bit pointer
+				 ** so it can be accessed from the driver.
+				 */
+				Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));
+
+				/*
+				 ** If the packet is used, reset it.
+				 */
+				Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE);
+				writeb(dest_unit, &Pkt->dest_unit);
+				writeb(dest_port, &Pkt->dest_port);
+			}
+			rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
+			writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
+			writew(link, &PortP->PhbP->link);
+
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		}
+		/*
+		 ** Now make sure the range of ports to be serviced includes
+		 ** the 2nd 8 on this 16 port RTA.
+		 */
+		if (link > 3)
+			return;
+		if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) {
+			rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
+			writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port);
+		}
+	}
+}
+
+/*
+** Check to see if the new disconnection has isolated this unit.
+** If it has, then invalidate all its link information, and tell
+** the world about it. This is done to ensure that the configurator
+** only gets up-to-date information about what is going on.
+*/
+static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
+{
+	unsigned long flags;
+	rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+	if (RIOCheck(HostP, UnitId)) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
+		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+		return (0);
+	}
+
+	RIOIsolate(p, HostP, UnitId);
+	RIOSetChange(p);
+	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+	return 1;
+}
+
+/*
+** Invalidate all the link interconnectivity of this unit, and of
+** all the units attached to it. This will mean that the entire
+** subnet will re-introduce itself.
+*/
+static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
+{
+	unsigned int link, unit;
+
+	UnitId--;		/* this trick relies on the Unit Id being UNSIGNED! */
+
+	if (UnitId >= MAX_RUP)	/* dontcha just lurv unsigned maths! */
+		return (0);
+
+	if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
+		return (0);
+
+	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
+
+	if (p->RIOPrintDisabled == DO_PRINT)
+		rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
+
+	for (link = 0; link < LINKS_PER_UNIT; link++) {
+		unit = HostP->Mapping[UnitId].Topology[link].Unit;
+		HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
+		HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
+		RIOIsolate(p, HostP, unit);
+	}
+	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+	return 1;
+}
+
+static int RIOCheck(struct Host *HostP, unsigned int UnitId)
+{
+	unsigned char link;
+
+/* 	rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
+	rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
+
+	if (UnitId == HOST_ID) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
+		return 1;
+	}
+
+	UnitId--;
+
+	if (UnitId >= MAX_RUP) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
+		return 0;
+	}
+
+	for (link = 0; link < LINKS_PER_UNIT; link++) {
+		if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
+			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", 
+			   UnitId, 'A'+link)); */
+			return 1;
+		}
+	}
+
+	if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
+		return 0;
+	}
+
+	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
+
+	for (link = 0; link < LINKS_PER_UNIT; link++) {
+		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
+		if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
+			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
+			HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+			return 1;
+		}
+	}
+
+	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
+
+	/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
+
+	return 0;
+}
+
+/*
+** Returns the type of unit (host, 16/8 port RTA)
+*/
+
+unsigned int GetUnitType(unsigned int Uniq)
+{
+	switch ((Uniq >> 28) & 0xf) {
+	case RIO_AT:
+	case RIO_MCA:
+	case RIO_EISA:
+	case RIO_PCI:
+		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
+		return (TYPE_HOST);
+	case RIO_RTA_16:
+		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
+		return (TYPE_RTA16);
+	case RIO_RTA:
+		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
+		return (TYPE_RTA8);
+	default:
+		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
+		return (99);
+	}
+}
+
+int RIOSetChange(struct rio_info *p)
+{
+	if (p->RIOQuickCheck != NOT_CHANGED)
+		return (0);
+	p->RIOQuickCheck = CHANGED;
+	if (p->RIOSignalProcess) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
+		/*
+		   psignal( RIOSignalProcess, SIGHUP );
+		 */
+	}
+	return (0);
+}
+
+static void RIOConCon(struct rio_info *p,
+		      struct Host *HostP,
+		      unsigned int FromId,
+		      unsigned int FromLink,
+		      unsigned int ToId,
+		      unsigned int ToLink,
+		      int Change)
+{
+	char *FromName;
+	char *FromType;
+	char *ToName;
+	char *ToType;
+	unsigned int tp;
+
+/*
+** 15.10.1998 ARG - ESIL 0759
+** (Part) fix for port being trashed when opened whilst RTA "disconnected"
+**
+** What's this doing in here anyway ?
+** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected"
+**
+** 09.12.1998 ARG - ESIL 0776 - part fix
+** Okay, We've found out what this was all about now !
+** Someone had botched this to use RIOHalted to indicated the number of RTAs
+** 'disconnected'. The value in RIOHalted was then being used in the
+** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA
+** is 'disconnected'. The change was put in to satisfy a customer's needs.
+** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for
+** the customer.
+**
+    if (Change == CONNECT) {
+		if (p->RIOHalted) p->RIOHalted --;
+	 }
+	 else {
+		p->RIOHalted ++;
+	 }
+**
+** So - we need to implement it slightly differently - a new member of the
+** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
+** connections and disconnections. 
+*/
+	if (Change == CONNECT) {
+		if (p->RIORtaDisCons)
+			p->RIORtaDisCons--;
+	} else {
+		p->RIORtaDisCons++;
+	}
+
+	if (p->RIOPrintDisabled == DONT_PRINT)
+		return;
+
+	if (FromId > ToId) {
+		tp = FromId;
+		FromId = ToId;
+		ToId = tp;
+		tp = FromLink;
+		FromLink = ToLink;
+		ToLink = tp;
+	}
+
+	FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
+	FromType = FromId ? "RTA" : "HOST";
+	ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
+	ToType = ToId ? "RTA" : "HOST";
+
+	rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
+	printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
+}
+
+/*
+** RIORemoveFromSavedTable :
+**
+** Delete and RTA entry from the saved table given to us
+** by the configuration program.
+*/
+static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
+{
+	int entry;
+
+	/*
+	 ** We loop for all entries even after finding an entry and
+	 ** zeroing it because we may have two entries to delete if
+	 ** it's a 16 port RTA.
+	 */
+	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+		if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
+			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
+		}
+	}
+	return 0;
+}
+
+
+/*
+** RIOCheckDisconnected :
+**
+** Scan the unit links to and return zero if the unit is completely
+** disconnected.
+*/
+static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
+{
+	int link;
+
+
+	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
+	/*
+	 ** If the slot is tentative and does not belong to the
+	 ** second half of a 16 port RTA then scan to see if
+	 ** is disconnected.
+	 */
+	for (link = 0; link < LINKS_PER_UNIT; link++) {
+		if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
+			break;
+	}
+
+	/*
+	 ** If not all links are disconnected then we can forget about it.
+	 */
+	if (link < LINKS_PER_UNIT)
+		return 1;
+
+#ifdef NEED_TO_FIX_THIS
+	/* Ok so all the links are disconnected. But we may have only just
+	 ** made this slot tentative and not yet received a topology update.
+	 ** Lets check how long ago we made it tentative.
+	 */
+	rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
+	if (drv_getparm(LBOLT, (ulong_t *) & current_time))
+		rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
+
+	elapse_time = current_time - TentTime[unit];
+	rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
+	if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
+		return 1;
+	}
+#endif
+
+	/*
+	 ** We have found an usable slot.
+	 ** If it is half of a 16 port RTA then delete the other half.
+	 */
+	if (HostP->Mapping[unit].ID2 != 0) {
+		int nOther = (HostP->Mapping[unit].ID2) - 1;
+
+		rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
+		memset(&HostP->Mapping[nOther], 0, sizeof(struct Map));
+	}
+	RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
+
+	return 0;
+}
+
+
+/*
+** RIOFindFreeID :
+**
+** This function scans the given host table for either one
+** or two free unit ID's.
+*/
+
+int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2)
+{
+	int unit, tempID;
+
+	/*
+	 ** Initialise the ID's to MAX_RUP.
+	 ** We do this to make the loop for setting the ID's as simple as
+	 ** possible.
+	 */
+	*pID1 = MAX_RUP;
+	if (pID2 != NULL)
+		*pID2 = MAX_RUP;
+
+	/*
+	 ** Scan all entries of the host mapping table for free slots.
+	 ** We scan for free slots first and then if that is not successful
+	 ** we start all over again looking for tentative slots we can re-use.
+	 */
+	for (unit = 0; unit < MAX_RUP; unit++) {
+		rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
+		/*
+		 ** If the flags are zero then the slot is empty.
+		 */
+		if (HostP->Mapping[unit].Flags == 0) {
+			rio_dprintk(RIO_DEBUG_ROUTE, "      This slot is empty.\n");
+			/*
+			 ** If we haven't allocated the first ID then do it now.
+			 */
+			if (*pID1 == MAX_RUP) {
+				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
+				*pID1 = unit;
+
+				/*
+				 ** If the second ID is not needed then we can return
+				 ** now.
+				 */
+				if (pID2 == NULL)
+					return 0;
+			} else {
+				/*
+				 ** Allocate the second slot and return.
+				 */
+				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
+				*pID2 = unit;
+				return 0;
+			}
+		}
+	}
+
+	/*
+	 ** If we manage to come out of the free slot loop then we
+	 ** need to start all over again looking for tentative slots
+	 ** that we can re-use.
+	 */
+	rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
+	for (unit = 0; unit < MAX_RUP; unit++) {
+		if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
+			rio_dprintk(RIO_DEBUG_ROUTE, "    Slot %d looks promising.\n", unit);
+
+			if (unit == *pID1) {
+				rio_dprintk(RIO_DEBUG_ROUTE, "    No it isn't, its the 1st half\n");
+				continue;
+			}
+
+			/*
+			 ** Slot is Tentative or Empty, but not a tentative second
+			 ** slot of a 16 porter.
+			 ** Attempt to free up this slot (and its parnter if
+			 ** it is a 16 port slot. The second slot will become
+			 ** empty after a call to RIOFreeDisconnected so thats why
+			 ** we look for empty slots above  as well).
+			 */
+			if (HostP->Mapping[unit].Flags != 0)
+				if (RIOFreeDisconnected(p, HostP, unit) != 0)
+					continue;
+			/*
+			 ** If we haven't allocated the first ID then do it now.
+			 */
+			if (*pID1 == MAX_RUP) {
+				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
+				*pID1 = unit;
+
+				/*
+				 ** Clear out this slot now that we intend to use it.
+				 */
+				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
+
+				/*
+				 ** If the second ID is not needed then we can return
+				 ** now.
+				 */
+				if (pID2 == NULL)
+					return 0;
+			} else {
+				/*
+				 ** Allocate the second slot and return.
+				 */
+				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty  entry for second unit %d\n", unit);
+				*pID2 = unit;
+
+				/*
+				 ** Clear out this slot now that we intend to use it.
+				 */
+				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
+
+				/* At this point under the right(wrong?) conditions
+				 ** we may have a first unit ID being higher than the
+				 ** second unit ID. This is a bad idea if we are about
+				 ** to fill the slots with a 16 port RTA.
+				 ** Better check and swap them over.
+				 */
+
+				if (*pID1 > *pID2) {
+					rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
+					tempID = *pID1;
+					*pID1 = *pID2;
+					*pID2 = tempID;
+				}
+				return 0;
+			}
+		}
+	}
+
+	/*
+	 ** If we manage to get to the end of the second loop then we
+	 ** can give up and return a failure.
+	 */
+	return 1;
+}
+
+
+/*
+** The link switch scenario.
+**
+** Rta Wun (A) is connected to Tuw (A).
+** The tables are all up to date, and the system is OK.
+**
+** If Wun (A) is now moved to Wun (B) before Wun (A) can
+** become disconnected, then the follow happens:
+**
+** Tuw (A) spots the change of unit:link at the other end
+** of its link and Tuw sends a topology packet reflecting
+** the change: Tuw (A) now disconnected from Wun (A), and
+** this is closely followed by a packet indicating that 
+** Tuw (A) is now connected to Wun (B).
+**
+** Wun (B) will spot that it has now become connected, and
+** Wun will send a topology packet, which indicates that
+** both Wun (A) and Wun (B) is connected to Tuw (A).
+**
+** Eventually Wun (A) realises that it is now disconnected
+** and Wun will send out a topology packet indicating that
+** Wun (A) is now disconnected.
+*/
diff --git a/drivers/staging/generic_serial/rio/riospace.h b/drivers/staging/generic_serial/rio/riospace.h
new file mode 100644
index 0000000..ffb31d4
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/riospace.h
@@ -0,0 +1,154 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riospace.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:13
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)riospace.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_riospace_h__
+#define __rio_riospace_h__
+
+#define	RIO_LOCATOR_LEN	16
+#define	MAX_RIO_BOARDS	4
+
+/*
+** DONT change this file. At all. Unless you can rebuild the entire
+** device driver, which you probably can't, then the rest of the
+** driver won't see any changes you make here. So don't make any.
+** In particular, it won't be able to see changes to RIO_SLOTS
+*/
+
+struct Conf {
+	char Locator[24];
+	unsigned int StartupTime;
+	unsigned int SlowCook;
+	unsigned int IntrPollTime;
+	unsigned int BreakInterval;
+	unsigned int Timer;
+	unsigned int RtaLoadBase;
+	unsigned int HostLoadBase;
+	unsigned int XpHz;
+	unsigned int XpCps;
+	char *XpOn;
+	char *XpOff;
+	unsigned int MaxXpCps;
+	unsigned int MinXpCps;
+	unsigned int SpinCmds;
+	unsigned int FirstAddr;
+	unsigned int LastAddr;
+	unsigned int BufferSize;
+	unsigned int LowWater;
+	unsigned int LineLength;
+	unsigned int CmdTime;
+};
+
+/*
+**	Board types - these MUST correspond to product codes!
+*/
+#define	RIO_EMPTY	0x0
+#define	RIO_EISA	0x3
+#define	RIO_RTA_16	0x9
+#define	RIO_AT		0xA
+#define	RIO_MCA		0xB
+#define	RIO_PCI		0xD
+#define	RIO_RTA		0xE
+
+/*
+**	Board data structure. This is used for configuration info
+*/
+struct Brd {
+	unsigned char Type;	/* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
+	unsigned char Ivec;	/* POLLED or ivec number */
+	unsigned char Mode;	/* Control stuff, see below */
+};
+
+struct Board {
+	char Locator[RIO_LOCATOR_LEN];
+	int NumSlots;
+	struct Brd Boards[MAX_RIO_BOARDS];
+};
+
+#define	BOOT_FROM_LINK		0x00
+#define	BOOT_FROM_RAM		0x01
+#define	EXTERNAL_BUS_OFF	0x00
+#define	EXTERNAL_BUS_ON		0x02
+#define	INTERRUPT_DISABLE	0x00
+#define	INTERRUPT_ENABLE	0x04
+#define	BYTE_OPERATION		0x00
+#define	WORD_OPERATION		0x08
+#define	POLLED			INTERRUPT_DISABLE
+#define	IRQ_15			(0x00 | INTERRUPT_ENABLE)
+#define	IRQ_12			(0x10 | INTERRUPT_ENABLE)
+#define	IRQ_11			(0x20 | INTERRUPT_ENABLE)
+#define	IRQ_9			(0x30 | INTERRUPT_ENABLE)
+#define	SLOW_LINKS		0x00
+#define	FAST_LINKS		0x40
+#define	SLOW_AT_BUS		0x00
+#define	FAST_AT_BUS		0x80
+#define	SLOW_PCI_TP		0x00
+#define	FAST_PCI_TP		0x80
+/*
+**	Debug levels
+*/
+#define	DBG_NONE	0x00000000
+
+#define	DBG_INIT	0x00000001
+#define	DBG_OPEN	0x00000002
+#define	DBG_CLOSE	0x00000004
+#define	DBG_IOCTL	0x00000008
+
+#define	DBG_READ	0x00000010
+#define	DBG_WRITE	0x00000020
+#define	DBG_INTR	0x00000040
+#define	DBG_PROC	0x00000080
+
+#define	DBG_PARAM	0x00000100
+#define	DBG_CMD		0x00000200
+#define	DBG_XPRINT	0x00000400
+#define	DBG_POLL	0x00000800
+
+#define	DBG_DAEMON	0x00001000
+#define	DBG_FAIL	0x00002000
+#define DBG_MODEM	0x00004000
+#define	DBG_LIST	0x00008000
+
+#define	DBG_ROUTE	0x00010000
+#define DBG_UTIL        0x00020000
+#define DBG_BOOT	0x00040000
+#define DBG_BUFFER	0x00080000
+
+#define	DBG_MON		0x00100000
+#define DBG_SPECIAL     0x00200000
+#define	DBG_VPIX	0x00400000
+#define	DBG_FLUSH	0x00800000
+
+#define	DBG_QENABLE	0x01000000
+
+#define	DBG_ALWAYS	0x80000000
+
+#endif				/* __rio_riospace_h__ */
diff --git a/drivers/staging/generic_serial/rio/riotable.c b/drivers/staging/generic_serial/rio/riotable.c
new file mode 100644
index 0000000..3d15802
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/riotable.c
@@ -0,0 +1,941 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riotable.c
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 10:33:47
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)riotable.c	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+#include "protsts.h"
+
+/*
+** A configuration table has been loaded. It is now up to us
+** to sort it out and use the information contained therein.
+*/
+int RIONewTable(struct rio_info *p)
+{
+	int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
+	struct Map *MapP;
+	struct Map *HostMapP;
+	struct Host *HostP;
+
+	char *cptr;
+
+	/*
+	 ** We have been sent a new table to install. We need to break
+	 ** it down into little bits and spread it around a bit to see
+	 ** what we have got.
+	 */
+	/*
+	 ** Things to check:
+	 ** (things marked 'xx' aren't checked any more!)
+	 ** (1) That there are no booted Hosts/RTAs out there.
+	 ** (2) That the names are properly formed
+	 ** (3) That blank entries really are.
+	 ** xx (4)      That hosts mentioned in the table actually exist. xx
+	 ** (5) That the IDs are unique (per host).
+	 ** (6) That host IDs are zero
+	 ** (7) That port numbers are valid
+	 ** (8) That port numbers aren't duplicated
+	 ** (9) That names aren't duplicated
+	 ** xx (10) That hosts that actually exist are mentioned in the table. xx
+	 */
+	rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
+	if (p->RIOSystemUp) {	/* (1) */
+		p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
+		return -EBUSY;
+	}
+
+	p->RIOError.Error = NOTHING_WRONG_AT_ALL;
+	p->RIOError.Entry = -1;
+	p->RIOError.Other = -1;
+
+	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
+		MapP = &p->RIOConnectTable[Entry];
+		if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
+			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
+			cptr = MapP->Name;	/* (2) */
+			cptr[MAX_NAME_LEN - 1] = '\0';
+			if (cptr[0] == '\0') {
+				memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA	NN" : "HOST NN", 8);
+				MapP->Name[5] = '0' + Entry / 10;
+				MapP->Name[6] = '0' + Entry % 10;
+			}
+			while (*cptr) {
+				if (*cptr < ' ' || *cptr > '~') {
+					p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+					p->RIOError.Entry = Entry;
+					return -ENXIO;
+				}
+				cptr++;
+			}
+		}
+
+		/*
+		 ** If the entry saved was a tentative entry then just forget
+		 ** about it.
+		 */
+		if (MapP->Flags & SLOT_TENTATIVE) {
+			MapP->HostUniqueNum = 0;
+			MapP->RtaUniqueNum = 0;
+			continue;
+		}
+
+		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
+		if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) {	/* (3) */
+			if (MapP->ID || MapP->SysPort || MapP->Flags) {
+				rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
+				p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
+			continue;
+		}
+
+		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
+		for (Host = 0; Host < p->RIONumHosts; Host++) {	/* (4) */
+			if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
+				HostP = &p->RIOHosts[Host];
+				/*
+				 ** having done the lookup, we don't really want to do
+				 ** it again, so hang the host number in a safe place
+				 */
+				MapP->Topology[0].Unit = Host;
+				break;
+			}
+		}
+
+		if (Host >= p->RIONumHosts) {
+			rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
+			MapP->HostUniqueNum = 0;
+			/* MapP->RtaUniqueNum   = 0; */
+			/* MapP->ID                     = 0; */
+			/* MapP->Flags           = 0; */
+			/* MapP->SysPort                 = 0; */
+			/* MapP->Name[0]                 = 0; */
+			continue;
+		}
+
+		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
+		if (MapP->RtaUniqueNum) {	/* (5) */
+			if (!MapP->ID) {
+				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
+				p->RIOError.Error = ZERO_RTA_ID;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			if (MapP->ID > MAX_RUP) {
+				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
+				p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
+				if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
+					rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
+					p->RIOError.Error = DUPLICATED_RTA_ID;
+					p->RIOError.Entry = Entry;
+					p->RIOError.Other = SubEnt;
+					return -ENXIO;
+				}
+				/*
+				 ** If the RtaUniqueNum is the same, it may be looking at both
+				 ** entries for a 16 port RTA, so check the ids
+				 */
+				if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
+				    && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
+					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
+					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
+					p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
+					p->RIOError.Entry = Entry;
+					p->RIOError.Other = SubEnt;
+					return -ENXIO;
+				}
+			}
+			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
+			/* (7a) */
+			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
+				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
+				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
+			/* (7b) */
+			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
+				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
+				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
+				if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
+					continue;
+				if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
+					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
+					/* (8) */
+					if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
+						rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
+						p->RIOError.Error = TTY_NUMBER_IN_USE;
+						p->RIOError.Entry = Entry;
+						p->RIOError.Other = SubEnt;
+						return -ENXIO;
+					}
+					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
+					if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) {	/* (9) */
+						rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
+						p->RIOError.Error = NAME_USED_TWICE;
+						p->RIOError.Entry = Entry;
+						p->RIOError.Other = SubEnt;
+						return -ENXIO;
+					}
+				}
+			}
+		} else {	/* (6) */
+			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
+			if (MapP->ID) {
+				rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
+				p->RIOError.Error = HOST_ID_NOT_ZERO;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+			if (MapP->SysPort != NO_PORT) {
+				rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
+				p->RIOError.Error = HOST_SYSPORT_BAD;
+				p->RIOError.Entry = Entry;
+				return -ENXIO;
+			}
+		}
+	}
+
+	/*
+	 ** wow! if we get here then it's a goody!
+	 */
+
+	/*
+	 ** Zero the (old) entries for each host...
+	 */
+	for (Host = 0; Host < RIO_HOSTS; Host++) {
+		for (Entry = 0; Entry < MAX_RUP; Entry++) {
+			memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map));
+		}
+		memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name));
+	}
+
+	/*
+	 ** Copy in the new table entries
+	 */
+	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
+		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
+		MapP = &p->RIOConnectTable[Entry];
+
+		/*
+		 ** Now, if it is an empty slot ignore it!
+		 */
+		if (MapP->HostUniqueNum == 0)
+			continue;
+
+		/*
+		 ** we saved the host number earlier, so grab it back
+		 */
+		HostP = &p->RIOHosts[MapP->Topology[0].Unit];
+
+		/*
+		 ** If it is a host, then we only need to fill in the name field.
+		 */
+		if (MapP->ID == 0) {
+			rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
+			memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN);
+			continue;
+		}
+
+		/*
+		 ** Its an RTA entry, so fill in the host mapping entries for it
+		 ** and the port mapping entries. Notice that entry zero is for
+		 ** ID one.
+		 */
+		HostMapP = &HostP->Mapping[MapP->ID - 1];
+
+		if (MapP->Flags & SLOT_IN_USE) {
+			rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
+			/*
+			 ** structure assign, then sort out the bits we shouldn't have done
+			 */
+			*HostMapP = *MapP;
+
+			HostMapP->Flags = SLOT_IN_USE;
+			if (MapP->Flags & RTA16_SECOND_SLOT)
+				HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+			RIOReMapPorts(p, HostP, HostMapP);
+		} else {
+			rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
+		}
+	}
+
+	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
+		p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
+	}
+
+	for (Host = 0; Host < p->RIONumHosts; Host++) {
+		for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
+			p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
+			p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
+		}
+		for (Entry = 0; Entry < MAX_RUP; Entry++) {
+			for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
+				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
+				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
+			}
+		}
+		if (!p->RIOHosts[Host].Name[0]) {
+			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
+			p->RIOHosts[Host].Name[5] += Host;
+		}
+		/*
+		 ** Check that default name assigned is unique.
+		 */
+		Host1 = Host;
+		NameIsUnique = 0;
+		while (!NameIsUnique) {
+			NameIsUnique = 1;
+			for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
+				if (Host2 == Host)
+					continue;
+				if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
+				    == 0) {
+					NameIsUnique = 0;
+					Host1++;
+					if (Host1 >= p->RIONumHosts)
+						Host1 = 0;
+					p->RIOHosts[Host].Name[5] = '1' + Host1;
+				}
+			}
+		}
+		/*
+		 ** Rename host if name already used.
+		 */
+		if (Host1 != Host) {
+			rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
+			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
+			p->RIOHosts[Host].Name[5] += Host1;
+		}
+		rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
+	}
+	return 0;
+}
+
+/*
+** User process needs the config table - build it from first
+** principles.
+**
+*	FIXME: SMP locking
+*/
+int RIOApel(struct rio_info *p)
+{
+	int Host;
+	int link;
+	int Rup;
+	int Next = 0;
+	struct Map *MapP;
+	struct Host *HostP;
+	unsigned long flags;
+
+	rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
+
+	memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES);
+
+	for (Host = 0; Host < RIO_HOSTS; Host++) {
+		rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
+		HostP = &p->RIOHosts[Host];
+		rio_spin_lock_irqsave(&HostP->HostLock, flags);
+
+		MapP = &p->RIOConnectTable[Next++];
+		MapP->HostUniqueNum = HostP->UniqueNum;
+		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+			rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+			continue;
+		}
+		MapP->RtaUniqueNum = 0;
+		MapP->ID = 0;
+		MapP->Flags = SLOT_IN_USE;
+		MapP->SysPort = NO_PORT;
+		for (link = 0; link < LINKS_PER_UNIT; link++)
+			MapP->Topology[link] = HostP->Topology[link];
+		memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN);
+		for (Rup = 0; Rup < MAX_RUP; Rup++) {
+			if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
+				p->RIOConnectTable[Next] = HostP->Mapping[Rup];
+				if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
+					p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
+				if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
+					p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
+				if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
+					p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
+				Next++;
+			}
+		}
+		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
+	}
+	return 0;
+}
+
+/*
+** config.rio has taken a dislike to one of the gross maps entries.
+** if the entry is suitably inactive, then we can gob on it and remove
+** it from the table.
+*/
+int RIODeleteRta(struct rio_info *p, struct Map *MapP)
+{
+	int host, entry, port, link;
+	int SysPort;
+	struct Host *HostP;
+	struct Map *HostMapP;
+	struct Port *PortP;
+	int work_done = 0;
+	unsigned long lock_flags, sem_flags;
+
+	rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
+
+	for (host = 0; host < p->RIONumHosts; host++) {
+		HostP = &p->RIOHosts[host];
+
+		rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
+
+		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
+			rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
+			continue;
+		}
+
+		for (entry = 0; entry < MAX_RUP; entry++) {
+			if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
+				HostMapP = &HostP->Mapping[entry];
+				rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
+
+				/*
+				 ** Check all four links of the unit are disconnected
+				 */
+				for (link = 0; link < LINKS_PER_UNIT; link++) {
+					if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
+						rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
+						p->RIOError.Error = UNIT_IS_IN_USE;
+						rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
+						return -EBUSY;
+					}
+				}
+				/*
+				 ** Slot has been allocated, BUT not booted/routed/
+				 ** connected/selected or anything else-ed
+				 */
+				SysPort = HostMapP->SysPort;
+
+				if (SysPort != NO_PORT) {
+					for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
+						PortP = p->RIOPortp[port];
+						rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
+
+						rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
+
+						PortP->Mapped = 0;
+
+						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
+
+							rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
+							PortP->TxBufferIn = PortP->TxBufferOut = 0;
+							/* What should I do 
+							   wakeup( &PortP->TxBufferIn );
+							   wakeup( &PortP->TxBufferOut);
+							 */
+							PortP->InUse = NOT_INUSE;
+							/* What should I do 
+							   wakeup( &PortP->InUse );
+							   signal(PortP->TtyP->t_pgrp,SIGKILL);
+							   ttyflush(PortP->TtyP,(FREAD|FWRITE));
+							 */
+							PortP->State |= RIO_CLOSING | RIO_DELETED;
+						}
+
+						/*
+						 ** For the second slot of a 16 port RTA, the
+						 ** driver needs to reset the changes made to
+						 ** the phb to port mappings in RIORouteRup.
+						 */
+						if (PortP->SecondBlock) {
+							u16 dest_unit = HostMapP->ID;
+							u16 dest_port = port - SysPort;
+							u16 __iomem *TxPktP;
+							struct PKT __iomem *Pkt;
+
+							for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
+								/*
+								 ** *TxPktP is the pointer to the
+								 ** transmit packet on the host card.
+								 ** This needs to be translated into
+								 ** a 32 bit pointer so it can be
+								 ** accessed from the driver.
+								 */
+								Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
+								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port);
+								writew(dest_unit, &Pkt->dest_unit);
+								writew(dest_port, &Pkt->dest_port);
+							}
+							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
+							writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
+						}
+						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
+					}
+				}
+				rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
+				memset(HostMapP, 0, sizeof(struct Map));
+				work_done++;
+			}
+		}
+		rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
+	}
+
+	/* XXXXX lock me up */
+	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
+		if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
+			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
+			work_done++;
+		}
+		if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
+			memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map));
+			work_done++;
+		}
+	}
+	if (work_done)
+		return 0;
+
+	rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
+	p->RIOError.Error = COULDNT_FIND_ENTRY;
+	return -ENXIO;
+}
+
+int RIOAssignRta(struct rio_info *p, struct Map *MapP)
+{
+	int host;
+	struct Map *HostMapP;
+	char *sptr;
+	int link;
+
+
+	rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
+
+	if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
+		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+		return -EINVAL;
+	}
+	if (MapP->RtaUniqueNum == 0) {
+		rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
+		p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
+		return -EINVAL;
+	}
+	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
+		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
+		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+		return -EINVAL;
+	}
+	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
+		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
+		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
+		return -EINVAL;
+	}
+
+	/*
+	 ** Copy the name across to the map entry.
+	 */
+	MapP->Name[MAX_NAME_LEN - 1] = '\0';
+	sptr = MapP->Name;
+	while (*sptr) {
+		if (*sptr < ' ' || *sptr > '~') {
+			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+			return -EINVAL;
+		}
+		sptr++;
+	}
+
+	for (host = 0; host < p->RIONumHosts; host++) {
+		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
+			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
+				p->RIOError.Error = HOST_NOT_RUNNING;
+				return -ENXIO;
+			}
+
+			/*
+			 ** Now we have a host we need to allocate an ID
+			 ** if the entry does not already have one.
+			 */
+			if (MapP->ID == (u16) - 1) {
+				int nNewID;
+
+				rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
+				/*
+				 ** The idea here is to allow RTA's to be assigned
+				 ** before they actually appear on the network.
+				 ** This allows the addition of RTA's without having
+				 ** to plug them in.
+				 ** What we do is:
+				 **  - Find a free ID and allocate it to the RTA.
+				 **  - If this map entry is the second half of a
+				 **    16 port entry then find the other half and
+				 **    make sure the 2 cross reference each other.
+				 */
+				if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
+					p->RIOError.Error = COULDNT_FIND_ENTRY;
+					return -EBUSY;
+				}
+				MapP->ID = (u16) nNewID + 1;
+				rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
+				HostMapP = &p->RIOHosts[host].Mapping[nNewID];
+				HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
+				HostMapP->HostUniqueNum = MapP->HostUniqueNum;
+				HostMapP->ID = MapP->ID;
+				for (link = 0; link < LINKS_PER_UNIT; link++) {
+					HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
+					HostMapP->Topology[link].Link = NO_LINK;
+				}
+				if (MapP->Flags & RTA16_SECOND_SLOT) {
+					int unit;
+
+					for (unit = 0; unit < MAX_RUP; unit++)
+						if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
+							break;
+					if (unit == MAX_RUP) {
+						p->RIOError.Error = COULDNT_FIND_ENTRY;
+						return -EBUSY;
+					}
+					HostMapP->Flags |= RTA16_SECOND_SLOT;
+					HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
+					p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
+					rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
+				}
+			}
+
+			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
+
+			if (HostMapP->Flags & SLOT_IN_USE) {
+				rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
+				p->RIOError.Error = ID_ALREADY_IN_USE;
+				return -EBUSY;
+			}
+
+			/*
+			 ** Assign the sys ports and the name, and mark the slot as
+			 ** being in use.
+			 */
+			HostMapP->SysPort = MapP->SysPort;
+			if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
+				memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
+			HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
+#ifdef NEED_TO_FIX
+			RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
+#endif
+			if (MapP->Flags & RTA16_SECOND_SLOT)
+				HostMapP->Flags |= RTA16_SECOND_SLOT;
+
+			RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
+			/*
+			 ** Adjust 2nd block of 8 phbs
+			 */
+			if (MapP->Flags & RTA16_SECOND_SLOT)
+				RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
+
+			if (HostMapP->SysPort != NO_PORT) {
+				if (HostMapP->SysPort < p->RIOFirstPortsBooted)
+					p->RIOFirstPortsBooted = HostMapP->SysPort;
+				if (HostMapP->SysPort > p->RIOLastPortsBooted)
+					p->RIOLastPortsBooted = HostMapP->SysPort;
+			}
+			if (MapP->Flags & RTA16_SECOND_SLOT)
+				rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
+			else
+				rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
+			return 0;
+		}
+	}
+	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+	return -ENXIO;
+}
+
+
+int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP)
+{
+	struct Port *PortP;
+	unsigned int SubEnt;
+	unsigned int HostPort;
+	unsigned int SysPort;
+	u16 RtaType;
+	unsigned long flags;
+
+	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
+
+	/*
+	 ** We need to tell the UnixRups which sysport the rup corresponds to
+	 */
+	HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
+
+	if (HostMapP->SysPort == NO_PORT)
+		return (0);
+
+	RtaType = GetUnitType(HostMapP->RtaUniqueNum);
+	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
+
+	/*
+	 ** now map each of its eight ports
+	 */
+	for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
+		rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
+		SysPort = HostMapP->SysPort + SubEnt;	/* portnumber within system */
+		/* portnumber on host */
+
+		HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
+
+		rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
+		PortP = p->RIOPortp[SysPort];
+		rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
+
+		/*
+		 ** Point at all the real neat data structures
+		 */
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		PortP->HostP = HostP;
+		PortP->Caddr = HostP->Caddr;
+
+		/*
+		 ** The PhbP cannot be filled in yet
+		 ** unless the host has been booted
+		 */
+		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
+			struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
+			PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
+			PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
+			PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
+			PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
+			PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
+			PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
+		} else
+			PortP->PhbP = NULL;
+
+		/*
+		 ** port related flags
+		 */
+		PortP->HostPort = HostPort;
+		/*
+		 ** For each part of a 16 port RTA, RupNum is ID - 1.
+		 */
+		PortP->RupNum = HostMapP->ID - 1;
+		if (HostMapP->Flags & RTA16_SECOND_SLOT) {
+			PortP->ID2 = HostMapP->ID2 - 1;
+			PortP->SecondBlock = 1;
+		} else {
+			PortP->ID2 = 0;
+			PortP->SecondBlock = 0;
+		}
+		PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
+
+		/*
+		 ** If the port was already mapped then thats all we need to do.
+		 */
+		if (PortP->Mapped) {
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			continue;
+		} else
+			HostMapP->Flags &= ~RTA_NEWBOOT;
+
+		PortP->State = 0;
+		PortP->Config = 0;
+		/*
+		 ** Check out the module type - if it is special (read only etc.)
+		 ** then we need to set flags in the PortP->Config.
+		 ** Note: For 16 port RTA, all ports are of the same type.
+		 */
+		if (RtaType == TYPE_RTA16) {
+			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
+		} else {
+			if (SubEnt < PORTS_PER_MODULE)
+				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+			else
+				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
+		}
+
+		/*
+		 ** more port related flags
+		 */
+		PortP->PortState = 0;
+		PortP->ModemLines = 0;
+		PortP->ModemState = 0;
+		PortP->CookMode = COOK_WELL;
+		PortP->ParamSem = 0;
+		PortP->FlushCmdBodge = 0;
+		PortP->WflushFlag = 0;
+		PortP->MagicFlags = 0;
+		PortP->Lock = 0;
+		PortP->Store = 0;
+		PortP->FirstOpen = 1;
+
+		/*
+		 ** Buffers 'n things
+		 */
+		PortP->RxDataStart = 0;
+		PortP->Cor2Copy = 0;
+		PortP->Name = &HostMapP->Name[0];
+		PortP->statsGather = 0;
+		PortP->txchars = 0;
+		PortP->rxchars = 0;
+		PortP->opens = 0;
+		PortP->closes = 0;
+		PortP->ioctls = 0;
+		if (PortP->TxRingBuffer)
+			memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
+		else if (p->RIOBufferSize) {
+			PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL);
+		}
+		PortP->TxBufferOut = 0;
+		PortP->TxBufferIn = 0;
+		PortP->Debug = 0;
+		/*
+		 ** LastRxTgl stores the state of the rx toggle bit for this
+		 ** port, to be compared with the state of the next pkt received.
+		 ** If the same, we have received the same rx pkt from the RTA
+		 ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
+		 */
+		PortP->LastRxTgl = ~(u8) PHB_RX_TGL;
+
+		/*
+		 ** and mark the port as usable
+		 */
+		PortP->Mapped = 1;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	}
+	if (HostMapP->SysPort < p->RIOFirstPortsMapped)
+		p->RIOFirstPortsMapped = HostMapP->SysPort;
+	if (HostMapP->SysPort > p->RIOLastPortsMapped)
+		p->RIOLastPortsMapped = HostMapP->SysPort;
+
+	return 0;
+}
+
+int RIOChangeName(struct rio_info *p, struct Map *MapP)
+{
+	int host;
+	struct Map *HostMapP;
+	char *sptr;
+
+	rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
+
+	if (MapP->ID > MAX_RUP) {
+		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
+		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
+		return -EINVAL;
+	}
+
+	MapP->Name[MAX_NAME_LEN - 1] = '\0';
+	sptr = MapP->Name;
+
+	while (*sptr) {
+		if (*sptr < ' ' || *sptr > '~') {
+			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
+			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
+			return -EINVAL;
+		}
+		sptr++;
+	}
+
+	for (host = 0; host < p->RIONumHosts; host++) {
+		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
+			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
+				p->RIOError.Error = HOST_NOT_RUNNING;
+				return -ENXIO;
+			}
+			if (MapP->ID == 0) {
+				memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN);
+				return 0;
+			}
+
+			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
+
+			if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
+				p->RIOError.Error = RTA_NUMBER_WRONG;
+				return -ENXIO;
+			}
+			memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
+			return 0;
+		}
+	}
+	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
+	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
+	return -ENXIO;
+}
diff --git a/drivers/staging/generic_serial/rio/riotty.c b/drivers/staging/generic_serial/rio/riotty.c
new file mode 100644
index 0000000..8a90393
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/riotty.c
@@ -0,0 +1,654 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: riotty.c
+**	SID		: 1.3
+**	Last Modified	: 11/6/98 10:33:47
+**	Retrieved	: 11/6/98 10:33:50
+**
+**  ident @(#)riotty.c	1.3
+**
+** -----------------------------------------------------------------------------
+*/
+
+#define __EXPLICIT_DEF_H__
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/string.h>
+#include <asm/uaccess.h>
+
+#include <linux/termios.h>
+
+#include <linux/serial.h>
+
+#include <linux/generic_serial.h>
+
+
+#include "linux_compat.h"
+#include "rio_linux.h"
+#include "pkt.h"
+#include "daemon.h"
+#include "rio.h"
+#include "riospace.h"
+#include "cmdpkt.h"
+#include "map.h"
+#include "rup.h"
+#include "port.h"
+#include "riodrvr.h"
+#include "rioinfo.h"
+#include "func.h"
+#include "errors.h"
+#include "pci.h"
+
+#include "parmmap.h"
+#include "unixrup.h"
+#include "board.h"
+#include "host.h"
+#include "phb.h"
+#include "link.h"
+#include "cmdblk.h"
+#include "route.h"
+#include "cirrus.h"
+#include "rioioctl.h"
+#include "param.h"
+
+static void RIOClearUp(struct Port *PortP);
+
+/* Below belongs in func.h */
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
+
+
+extern struct rio_info *p;
+
+
+int riotopen(struct tty_struct *tty, struct file *filp)
+{
+	unsigned int SysPort;
+	int repeat_this = 250;
+	struct Port *PortP;	/* pointer to the port structure */
+	unsigned long flags;
+	int retval = 0;
+
+	func_enter();
+
+	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
+	   is going to oops.
+	 */
+	tty->driver_data = NULL;
+
+	SysPort = rio_minor(tty);
+
+	if (p->RIOFailed) {
+		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
+		func_exit();
+		return -ENXIO;
+	}
+
+	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped);
+
+	/*
+	 ** Validate that we have received a legitimate request.
+	 ** Currently, just check that we are opening a port on
+	 ** a host card that actually exists, and that the port
+	 ** has been mapped onto a host.
+	 */
+	if (SysPort >= RIO_PORTS) {	/* out of range ? */
+		rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
+		func_exit();
+		return -ENXIO;
+	}
+
+	/*
+	 ** Grab pointer to the port stucture
+	 */
+	PortP = p->RIOPortp[SysPort];	/* Get control struc */
+	rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
+	if (!PortP->Mapped) {	/* we aren't mapped yet! */
+		/*
+		 ** The system doesn't know which RTA this port
+		 ** corresponds to.
+		 */
+		rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
+		func_exit();
+		return -ENXIO;
+	}
+
+	tty->driver_data = PortP;
+
+	PortP->gs.port.tty = tty;
+	PortP->gs.port.count++;
+
+	rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);
+
+	retval = gs_init_port(&PortP->gs);
+	if (retval) {
+		PortP->gs.port.count--;
+		return -ENXIO;
+	}
+	/*
+	 ** If the host hasn't been booted yet, then
+	 ** fail
+	 */
+	if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
+		rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
+		func_exit();
+		return -ENXIO;
+	}
+
+	/*
+	 ** If the RTA has not booted yet and the user has choosen to block
+	 ** until the RTA is present then we must spin here waiting for
+	 ** the RTA to boot.
+	 */
+	/* I find the above code a bit hairy. I find the below code
+	   easier to read and shorter. Now, if it works too that would
+	   be great... -- REW 
+	 */
+	rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
+	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
+		if (!PortP->WaitUntilBooted) {
+			rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
+			func_exit();
+			return -ENXIO;
+		}
+
+		/* Under Linux you'd normally use a wait instead of this
+		   busy-waiting. I'll stick with the old implementation for
+		   now. --REW
+		 */
+		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+			rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
+			func_exit();
+			return -EINTR;
+		}
+		if (repeat_this-- <= 0) {
+			rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
+			func_exit();
+			return -EIO;
+		}
+	}
+	rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	if (p->RIOHalted) {
+		goto bombout;
+	}
+
+	/*
+	 ** If the port is in the final throws of being closed,
+	 ** we should wait here (politely), waiting
+	 ** for it to finish, so that it doesn't close us!
+	 */
+	while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
+		rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
+		if (repeat_this-- <= 0) {
+			rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+			RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+			retval = -EINTR;
+			goto bombout;
+		}
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+			retval = -EINTR;
+			goto bombout;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	if (!PortP->Mapped) {
+		rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		retval = -ENXIO;
+		func_exit();
+		return retval;
+	}
+
+	if (p->RIOHalted) {
+		goto bombout;
+	}
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
+** we need to make sure that the flags are clear when the port is opened.
+*/
+	/* Uh? Suppose I turn these on and then another process opens
+	   the port again? The flags get cleared! Not good. -- REW */
+	if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+		PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
+	}
+
+	if (!(PortP->firstOpen)) {	/* First time ? */
+		rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");
+
+
+		PortP->firstOpen++;
+		PortP->CookMode = 0;	/* XXX RIOCookMode(tp); */
+		PortP->InUse = NOT_INUSE;
+
+		/* Tentative fix for bug PR27. Didn't work. */
+		/* PortP->gs.xmit_cnt = 0; */
+
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+		/* Someone explain to me why this delay/config is
+		   here. If I read the docs correctly the "open"
+		   command piggybacks the parameters immediately.
+		   -- REW */
+		RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+		/*
+		 ** wait for the port to be not closed.
+		 */
+		while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
+			rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+				rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
+				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+				func_exit();
+				return -EINTR;
+			}
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		}
+
+		if (p->RIOHalted) {
+			retval = -EIO;
+		      bombout:
+			/*                    RIOClearUp( PortP ); */
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			return retval;
+		}
+		rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
+	}
+	rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
+	/*
+	 ** ACTION
+	 ** insert test for carrier here. -- ???
+	 ** I already see that test here. What's the deal? -- REW
+	 */
+	if ((PortP->gs.port.tty->termios->c_cflag & CLOCAL) ||
+			(PortP->ModemState & RIOC_MSVR1_CD)) {
+		rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
+		/*
+		   tp->tm.c_state |= CARR_ON;
+		   wakeup((caddr_t) &tp->tm.c_canq);
+		 */
+		PortP->State |= RIO_CARR_ON;
+		wake_up_interruptible(&PortP->gs.port.open_wait);
+	} else {	/* no carrier - wait for DCD */
+			/*
+		   while (!(PortP->gs.port.tty->termios->c_state & CARR_ON) &&
+		   !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
+		 */
+		while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
+				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
+			/*
+			   PortP->gs.port.tty->termios->c_state |= WOPEN;
+			 */
+			PortP->State |= RIO_WOPEN;
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				/*
+				 ** ACTION: verify that this is a good thing
+				 ** to do here. -- ???
+				 ** I think it's OK. -- REW
+				 */
+				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
+				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+				/*
+				   tp->tm.c_state &= ~WOPEN;
+				 */
+				PortP->State &= ~RIO_WOPEN;
+				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+				func_exit();
+				return -EINTR;
+			}
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		}
+		PortP->State &= ~RIO_WOPEN;
+	}
+	if (p->RIOHalted)
+		goto bombout;
+	rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
+	PortP->State |= RIO_MOPEN;
+
+	if (p->RIOHalted)
+		goto bombout;
+
+	rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");
+
+	/*
+	 ** Count opens for port statistics reporting
+	 */
+	if (PortP->statsGather)
+		PortP->opens++;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
+	func_exit();
+	return 0;
+}
+
+/*
+** RIOClose the port.
+** The operating system thinks that this is last close for the device.
+** As there are two interfaces to the port (Modem and tty), we need to
+** check that both are closed before we close the device.
+*/
+int riotclose(void *ptr)
+{
+	struct Port *PortP = ptr;	/* pointer to the port structure */
+	int deleted = 0;
+	int try = -1;		/* Disable the timeouts by setting them to -1 */
+	int repeat_this = -1;	/* Congrats to those having 15 years of
+				   uptime! (You get to break the driver.) */
+	unsigned long end_time;
+	struct tty_struct *tty;
+	unsigned long flags;
+	int rv = 0;
+
+	rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);
+
+	/* PortP = p->RIOPortp[SysPort]; */
+	rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP);
+	/* tp = PortP->TtyP; *//* Get tty */
+	tty = PortP->gs.port.tty;
+	rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty);
+
+	if (PortP->gs.closing_wait)
+		end_time = jiffies + PortP->gs.closing_wait;
+	else
+		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
+
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	/*
+	 ** Setting this flag will make any process trying to open
+	 ** this port block until we are complete closing it.
+	 */
+	PortP->State |= RIO_CLOSING;
+
+	if ((PortP->State & RIO_DELETED)) {
+		rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
+		deleted = 1;
+	}
+
+	if (p->RIOHalted) {
+		RIOClearUp(PortP);
+		rv = -EIO;
+		goto close_end;
+	}
+
+	rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
+	/*
+	 ** clear the open bits for this device
+	 */
+	PortP->State &= ~RIO_MOPEN;
+	PortP->State &= ~RIO_CARR_ON;
+	PortP->ModemState &= ~RIOC_MSVR1_CD;
+	/*
+	 ** If the device was open as both a Modem and a tty line
+	 ** then we need to wimp out here, as the port has not really
+	 ** been finally closed (gee, whizz!) The test here uses the
+	 ** bit for the OTHER mode of operation, to see if THAT is
+	 ** still active!
+	 */
+	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+		/*
+		 ** The port is still open for the other task -
+		 ** return, pretending that we are still active.
+		 */
+		rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
+		PortP->State &= ~RIO_CLOSING;
+		if (PortP->firstOpen)
+			PortP->firstOpen--;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return -EIO;
+	}
+
+	rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");
+
+	PortP->State &= ~RIO_DYNOROD;
+
+	/*
+	 ** This is where we wait for the port
+	 ** to drain down before closing. Bye-bye....
+	 ** (We never meant to do this)
+	 */
+	rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");
+
+	if (!deleted)
+		while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
+			if (repeat_this-- <= 0) {
+				rv = -EINTR;
+				rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
+				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+				goto close_end;
+			}
+			rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
+			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+			if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
+				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+				rv = -EINTR;
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				goto close_end;
+			}
+			rio_spin_lock_irqsave(&PortP->portSem, flags);
+		}
+
+	PortP->TxBufferIn = PortP->TxBufferOut = 0;
+	repeat_this = 0xff;
+
+	PortP->InUse = 0;
+	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
+		/*
+		 ** The port has been re-opened for the other task -
+		 ** return, pretending that we are still active.
+		 */
+		rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
+		PortP->State &= ~RIO_CLOSING;
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (PortP->firstOpen)
+			PortP->firstOpen--;
+		return -EIO;
+	}
+
+	if (p->RIOHalted) {
+		RIOClearUp(PortP);
+		goto close_end;
+	}
+
+	/* Can't call RIOShortCommand with the port locked. */
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+
+	if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) {
+		RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+		goto close_end;
+	}
+
+	if (!deleted)
+		while (try && (PortP->PortState & PORT_ISOPEN)) {
+			try--;
+			if (time_after(jiffies, end_time)) {
+				rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
+				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+				break;
+			}
+			rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
+
+			if (p->RIOHalted) {
+				RIOClearUp(PortP);
+				rio_spin_lock_irqsave(&PortP->portSem, flags);
+				goto close_end;
+			}
+			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
+				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
+				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
+				break;
+			}
+		}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+	rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
+
+	/* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
+
+/*
+** 15.10.1998 ARG - ESIL 0761 part fix
+** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
+*/
+	PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
+
+	/*
+	 ** Count opens for port statistics reporting
+	 */
+	if (PortP->statsGather)
+		PortP->closes++;
+
+close_end:
+	/* XXX: Why would a "DELETED" flag be reset here? I'd have
+	   thought that a "deleted" flag means that the port was
+	   permanently gone, but here we can make it reappear by it
+	   being in close during the "deletion".
+	 */
+	PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
+	if (PortP->firstOpen)
+		PortP->firstOpen--;
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
+	return rv;
+}
+
+
+
+static void RIOClearUp(struct Port *PortP)
+{
+	rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
+	PortP->Config = 0;	/* Direct semaphore */
+	PortP->PortState = 0;
+	PortP->firstOpen = 0;
+	PortP->FlushCmdBodge = 0;
+	PortP->ModemState = PortP->CookMode = 0;
+	PortP->Mapped = 0;
+	PortP->WflushFlag = 0;
+	PortP->MagicFlags = 0;
+	PortP->RxDataStart = 0;
+	PortP->TxBufferIn = 0;
+	PortP->TxBufferOut = 0;
+}
+
+/*
+** Put a command onto a port.
+** The PortPointer, command, length and arg are passed.
+** The len is the length *inclusive* of the command byte,
+** and so for a command that takes no data, len==1.
+** The arg is a single byte, and is only used if len==2.
+** Other values of len aren't allowed, and will cause
+** a panic.
+*/
+int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
+{
+	struct PKT __iomem *PacketP;
+	int retries = 20;	/* at 10 per second -> 2 seconds */
+	unsigned long flags;
+
+	rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
+
+	if (PortP->State & RIO_DELETED) {
+		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+		return RIO_FAIL;
+	}
+	rio_spin_lock_irqsave(&PortP->portSem, flags);
+
+	/*
+	 ** If the port is in use for pre-emptive command, then wait for it to
+	 ** be free again.
+	 */
+	while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
+		rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (retries-- <= 0) {
+			return RIO_FAIL;
+		}
+		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
+			return RIO_FAIL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+	if (PortP->State & RIO_DELETED) {
+		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
+		rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		if (retries-- <= 0) {
+			rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
+			return RIO_FAIL;
+		}
+		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
+			return RIO_FAIL;
+		}
+		rio_spin_lock_irqsave(&PortP->portSem, flags);
+	}
+
+	if (p->RIOHalted) {
+		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+		return RIO_FAIL;
+	}
+
+	/*
+	 ** set the command byte and the argument byte
+	 */
+	writeb(command, &PacketP->data[0]);
+
+	if (len == 2)
+		writeb(arg, &PacketP->data[1]);
+
+	/*
+	 ** set the length of the packet and set the command bit.
+	 */
+	writeb(PKT_CMD_BIT | len, &PacketP->len);
+
+	add_transmit(PortP);
+	/*
+	 ** Count characters transmitted for port statistics reporting
+	 */
+	if (PortP->statsGather)
+		PortP->txchars += len;
+
+	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
+}
+
+
diff --git a/drivers/staging/generic_serial/rio/route.h b/drivers/staging/generic_serial/rio/route.h
new file mode 100644
index 0000000..46e9637
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/route.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+ *******                                                              *******
+ *******                 R O U T E     H E A D E R
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra / Jeremy Rolls
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _route_h
+#define _route_h
+
+#define MAX_LINKS 4
+#define MAX_NODES 17		/* Maximum nodes in a subnet */
+#define NODE_BYTES ((MAX_NODES / 8) + 1)	/* Number of bytes needed for
+						   1 bit per node */
+#define ROUTE_DATA_SIZE  (NODE_BYTES + 2)	/* Number of bytes for complete
+						   info about cost etc. */
+#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
+					      /* Number of nodes we can squeeze
+					         into one packet */
+#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
+/************************************************
+ * Define the types of command for the ROUTE RUP.
+ ************************************************/
+#define ROUTE_REQUEST    0	/* Request an ID */
+#define ROUTE_FOAD       1	/* Kill the RTA */
+#define ROUTE_ALREADY    2	/* ID given already */
+#define ROUTE_USED       3	/* All ID's used */
+#define ROUTE_ALLOCATE   4	/* Here it is */
+#define ROUTE_REQ_TOP    5	/* I bet you didn't expect....
+				   the Topological Inquisition */
+#define ROUTE_TOPOLOGY   6	/* Topology request answered FD */
+/*******************************************************************
+ * Define the Route Map Structure
+ *
+ * The route map gives a pointer to a Link Structure to use.
+ * This allows Disconnected Links to be checked quickly
+ ******************************************************************/
+typedef struct COST_ROUTE COST_ROUTE;
+struct COST_ROUTE {
+	unsigned char cost;	/* Cost down this link */
+	unsigned char route[NODE_BYTES];	/* Nodes through this route */
+};
+
+typedef struct ROUTE_STR ROUTE_STR;
+struct ROUTE_STR {
+	COST_ROUTE cost_route[MAX_LINKS];
+	/* cost / route for this link */
+	ushort favoured;	/* favoured link */
+};
+
+
+#define NO_LINK            (short) 5	/* Link unattached */
+#define ROUTE_NO_ID        (short) 100	/* No Id */
+#define ROUTE_DISCONNECT   (ushort) 0xff	/* Not connected */
+#define ROUTE_INTERCONNECT (ushort) 0x40	/* Sub-net interconnect */
+
+
+#define SYNC_RUP         (ushort) 255
+#define COMMAND_RUP      (ushort) 254
+#define ERROR_RUP        (ushort) 253
+#define POLL_RUP         (ushort) 252
+#define BOOT_RUP         (ushort) 251
+#define ROUTE_RUP        (ushort) 250
+#define STATUS_RUP       (ushort) 249
+#define POWER_RUP        (ushort) 248
+
+#define HIGHEST_RUP      (ushort) 255	/* Set to Top one */
+#define LOWEST_RUP       (ushort) 248	/* Set to bottom one */
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/rup.h b/drivers/staging/generic_serial/rio/rup.h
new file mode 100644
index 0000000..4ae90cb
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/rup.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+ *******                                                              *******
+ *******               R U P   S T R U C T U R E
+ *******                                                              *******
+ ****************************************************************************
+
+ Author  : Ian Nandhra
+ Date    :
+
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Version : 0.01
+
+
+                            Mods
+ ----------------------------------------------------------------------------
+  Date     By                Description
+ ----------------------------------------------------------------------------
+
+ ***************************************************************************/
+
+#ifndef _rup_h
+#define _rup_h 1
+
+#define MAX_RUP          ((short) 16)
+#define PKTS_PER_RUP     ((short) 2)	/* They are always used in pairs */
+
+/*************************************************
+ * Define all the  packet request stuff
+ ************************************************/
+#define TX_RUP_INACTIVE          0	/* Nothing to transmit */
+#define TX_PACKET_READY          1	/* Transmit packet ready */
+#define TX_LOCK_RUP              2	/* Transmit side locked */
+
+#define RX_RUP_INACTIVE          0	/* Nothing received */
+#define RX_PACKET_READY          1	/* Packet received */
+
+#define RUP_NO_OWNER             0xff	/* RUP not owned by any process */
+
+struct RUP {
+	u16 txpkt;		/* Outgoing packet */
+	u16 rxpkt;		/* Incoming packet */
+	u16 link;		/* Which link to send down? */
+	u8 rup_dest_unit[2];	/* Destination unit */
+	u16 handshake;		/* For handshaking */
+	u16 timeout;		/* Timeout */
+	u16 status;		/* Status */
+	u16 txcontrol;		/* Transmit control */
+	u16 rxcontrol;		/* Receive control */
+};
+
+#endif
+
+/*********** end of file ***********/
diff --git a/drivers/staging/generic_serial/rio/unixrup.h b/drivers/staging/generic_serial/rio/unixrup.h
new file mode 100644
index 0000000..7abf0cb
--- /dev/null
+++ b/drivers/staging/generic_serial/rio/unixrup.h
@@ -0,0 +1,51 @@
+/*
+** -----------------------------------------------------------------------------
+**
+**  Perle Specialix driver for Linux
+**  Ported from existing RIO Driver for SCO sources.
+ *
+ *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**	Module		: unixrup.h
+**	SID		: 1.2
+**	Last Modified	: 11/6/98 11:34:20
+**	Retrieved	: 11/6/98 11:34:22
+**
+**  ident @(#)unixrup.h	1.2
+**
+** -----------------------------------------------------------------------------
+*/
+
+#ifndef __rio_unixrup_h__
+#define __rio_unixrup_h__
+
+/*
+**    UnixRup data structure. This contains pointers to actual RUPs on the
+**    host card, and all the command/boot control stuff.
+*/
+struct UnixRup {
+	struct CmdBlk *CmdsWaitingP;	/* Commands waiting to be done */
+	struct CmdBlk *CmdPendingP;	/* The command currently being sent */
+	struct RUP __iomem *RupP;	/* the Rup to send it to */
+	unsigned int Id;		/* Id number */
+	unsigned int BaseSysPort;	/* SysPort of first tty on this RTA */
+	unsigned int ModTypes;		/* Modules on this RTA */
+	spinlock_t RupLock;	/* Lock structure for MPX */
+	/*    struct lockb     RupLock;	*//* Lock structure for MPX */
+};
+
+#endif				/* __rio_unixrup_h__ */
diff --git a/drivers/staging/generic_serial/ser_a2232.c b/drivers/staging/generic_serial/ser_a2232.c
new file mode 100644
index 0000000..3f47c2e
--- /dev/null
+++ b/drivers/staging/generic_serial/ser_a2232.c
@@ -0,0 +1,831 @@
+/* drivers/char/ser_a2232.c */
+
+/* $Id: ser_a2232.c,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
+
+/* Linux serial driver for the Amiga A2232 board */
+
+/* This driver is MAINTAINED. Before applying any changes, please contact
+ * the author.
+ */
+
+/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
+ *                   alias The A2232 driver project <A2232@gmx.net>
+ * All rights reserved.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+/***************************** Documentation ************************/
+/*
+ * This driver is in EXPERIMENTAL state. That means I could not find
+ * someone with five A2232 boards with 35 ports running at 19200 bps
+ * at the same time and test the machine's behaviour.
+ * However, I know that you can performance-tweak this driver (see
+ * the source code).
+ * One thing to consider is the time this driver consumes during the
+ * Amiga's vertical blank interrupt. Everything that is to be done
+ * _IS DONE_ when entering the vertical blank interrupt handler of
+ * this driver.
+ * However, it would be more sane to only do the job for only ONE card
+ * instead of ALL cards at a time; or, more generally, to handle only
+ * SOME ports instead of ALL ports at a time.
+ * However, as long as no-one runs into problems I guess I shouldn't
+ * change the driver as it runs fine for me :) .
+ *
+ * Version history of this file:
+ * 0.4	Resolved licensing issues.
+ * 0.3	Inclusion in the Linux/m68k tree, small fixes.
+ * 0.2	Added documentation, minor typo fixes.
+ * 0.1	Initial release.
+ *
+ * TO DO:
+ * -	Handle incoming BREAK events. I guess "Stevens: Advanced
+ *	Programming in the UNIX(R) Environment" is a good reference
+ *	on what is to be done.
+ * -	When installing as a module, don't simply 'printk' text, but
+ *	send it to the TTY used by the user.
+ *
+ * THANKS TO:
+ * -	Jukka Marin (65EC02 code).
+ * -	The other NetBSD developers on whose A2232 driver I had a
+ *	pretty close look. However, I didn't copy any code so it
+ *	is okay to put my code under the GPL and include it into
+ *	Linux.
+ */
+/***************************** End of Documentation *****************/
+
+/***************************** Defines ******************************/
+/*
+ * Enables experimental 115200 (normal) 230400 (turbo) baud rate.
+ * The A2232 specification states it can only operate at speeds up to
+ * 19200 bits per second, and I was not able to send a file via
+ * "sz"/"rz" and a null-modem cable from one A2232 port to another
+ * at 115200 bits per second.
+ * However, this might work for you.
+ */
+#undef A2232_SPEEDHACK
+/*
+ * Default is not to use RTS/CTS so you could be talked to death.
+ */
+#define A2232_SUPPRESS_RTSCTS_WARNING
+/************************* End of Defines ***************************/
+
+/***************************** Includes *****************************/
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <asm/setup.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <linux/zorro.h>
+#include <asm/irq.h>
+#include <linux/mutex.h>
+
+#include <linux/delay.h>
+
+#include <linux/serial.h>
+#include <linux/generic_serial.h>
+#include <linux/tty_flip.h>
+
+#include "ser_a2232.h"
+#include "ser_a2232fw.h"
+/************************* End of Includes **************************/
+
+/***************************** Prototypes ***************************/
+/* The interrupt service routine */
+static irqreturn_t a2232_vbl_inter(int irq, void *data);
+/* Initialize the port structures */
+static void a2232_init_portstructs(void);
+/* Initialize and register TTY drivers. */
+/* returns 0 IFF successful */
+static int a2232_init_drivers(void); 
+
+/* BEGIN GENERIC_SERIAL PROTOTYPES */
+static void a2232_disable_tx_interrupts(void *ptr);
+static void a2232_enable_tx_interrupts(void *ptr);
+static void a2232_disable_rx_interrupts(void *ptr);
+static void a2232_enable_rx_interrupts(void *ptr);
+static int  a2232_carrier_raised(struct tty_port *port);
+static void a2232_shutdown_port(void *ptr);
+static int  a2232_set_real_termios(void *ptr);
+static int  a2232_chars_in_buffer(void *ptr);
+static void a2232_close(void *ptr);
+static void a2232_hungup(void *ptr);
+/* static void a2232_getserial (void *ptr, struct serial_struct *sp); */
+/* END GENERIC_SERIAL PROTOTYPES */
+
+/* Functions that the TTY driver struct expects */
+static int  a2232_ioctl(struct tty_struct *tty,
+				unsigned int cmd, unsigned long arg);
+static void a2232_throttle(struct tty_struct *tty);
+static void a2232_unthrottle(struct tty_struct *tty);
+static int  a2232_open(struct tty_struct * tty, struct file * filp);
+/************************* End of Prototypes ************************/
+
+/***************************** Global variables *********************/
+/*---------------------------------------------------------------------------
+ * Interface from generic_serial.c back here
+ *--------------------------------------------------------------------------*/
+static struct real_driver a2232_real_driver = {
+        a2232_disable_tx_interrupts,
+        a2232_enable_tx_interrupts,
+        a2232_disable_rx_interrupts,
+        a2232_enable_rx_interrupts,
+        a2232_shutdown_port,
+        a2232_set_real_termios,
+        a2232_chars_in_buffer,
+        a2232_close,
+        a2232_hungup,
+	NULL	/* a2232_getserial */
+};
+
+static void *a2232_driver_ID = &a2232_driver_ID; // Some memory address WE own.
+
+/* Ports structs */
+static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES];
+
+/* TTY driver structs */
+static struct tty_driver *a2232_driver;
+
+/* nr of cards completely (all ports) and correctly configured */
+static int nr_a2232; 
+
+/* zorro_dev structs for the A2232's */
+static struct zorro_dev *zd_a2232[MAX_A2232_BOARDS]; 
+/***************************** End of Global variables **************/
+
+/* Helper functions */
+
+static inline volatile struct a2232memory *a2232mem(unsigned int board)
+{
+	return (volatile struct a2232memory *)ZTWO_VADDR(zd_a2232[board]->resource.start);
+}
+
+static inline volatile struct a2232status *a2232stat(unsigned int board,
+						     unsigned int portonboard)
+{
+	volatile struct a2232memory *mem = a2232mem(board);
+	return &(mem->Status[portonboard]);
+}
+
+static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
+{
+/* 	Mostly stolen from other drivers.
+	Maybe one could implement a more efficient version by not only
+	transferring one character at a time.
+*/
+	struct tty_struct *tty = port->gs.port.tty;
+
+#if 0
+	switch(err) {
+	case TTY_BREAK:
+		break;
+	case TTY_PARITY:
+		break;
+	case TTY_OVERRUN:
+		break;
+	case TTY_FRAME:
+		break;
+	}
+#endif
+
+	tty_insert_flip_char(tty, ch, err);
+	tty_flip_buffer_push(tty);
+}
+
+/***************************** Functions ****************************/
+/*** BEGIN OF REAL_DRIVER FUNCTIONS ***/
+
+static void a2232_disable_tx_interrupts(void *ptr)
+{
+	struct a2232_port *port;
+	volatile struct a2232status *stat;
+	unsigned long flags;
+  
+	port = ptr;
+	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
+	stat->OutDisable = -1;
+
+	/* Does this here really have to be? */
+	local_irq_save(flags);
+	port->gs.port.flags &= ~GS_TX_INTEN;
+	local_irq_restore(flags);
+}
+
+static void a2232_enable_tx_interrupts(void *ptr)
+{
+	struct a2232_port *port;
+	volatile struct a2232status *stat;
+	unsigned long flags;
+
+	port = ptr;
+	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
+	stat->OutDisable = 0;
+
+	/* Does this here really have to be? */
+	local_irq_save(flags);
+	port->gs.port.flags |= GS_TX_INTEN;
+	local_irq_restore(flags);
+}
+
+static void a2232_disable_rx_interrupts(void *ptr)
+{
+	struct a2232_port *port;
+	port = ptr;
+	port->disable_rx = -1;
+}
+
+static void a2232_enable_rx_interrupts(void *ptr)
+{
+	struct a2232_port *port;
+	port = ptr;
+	port->disable_rx = 0;
+}
+
+static int  a2232_carrier_raised(struct tty_port *port)
+{
+	struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
+	return ap->cd_status;
+}
+
+static void a2232_shutdown_port(void *ptr)
+{
+	struct a2232_port *port;
+	volatile struct a2232status *stat;
+	unsigned long flags;
+
+	port = ptr;
+	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
+
+	local_irq_save(flags);
+
+	port->gs.port.flags &= ~GS_ACTIVE;
+	
+	if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
+		/* Set DTR and RTS to Low, flush output.
+		   The NetBSD driver "msc.c" does it this way. */
+		stat->Command = (	(stat->Command & ~A2232CMD_CMask) | 
+					A2232CMD_Close );
+		stat->OutFlush = -1;
+		stat->Setup = -1;
+	}
+
+	local_irq_restore(flags);
+	
+	/* After analyzing control flow, I think a2232_shutdown_port
+		is actually the last call from the system when at application
+		level someone issues a "echo Hello >>/dev/ttyY0".
+		Therefore I think the MOD_DEC_USE_COUNT should be here and
+		not in "a2232_close()". See the comment in "sx.c", too.
+		If you run into problems, compile this driver into the
+		kernel instead of compiling it as a module. */
+}
+
+static int  a2232_set_real_termios(void *ptr)
+{
+	unsigned int cflag, baud, chsize, stopb, parity, softflow;
+	int rate;
+	int a2232_param, a2232_cmd;
+	unsigned long flags;
+	unsigned int i;
+	struct a2232_port *port = ptr;
+	volatile struct a2232status *status;
+	volatile struct a2232memory *mem;
+
+	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
+
+	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
+	mem = a2232mem(port->which_a2232);
+	
+	a2232_param = a2232_cmd = 0;
+
+	// get baud rate
+	baud = port->gs.baud;
+	if (baud == 0) {
+		/* speed == 0 -> drop DTR, do nothing else */
+		local_irq_save(flags);
+		// Clear DTR (and RTS... mhhh).
+		status->Command = (	(status->Command & ~A2232CMD_CMask) |
+					A2232CMD_Close );
+		status->OutFlush = -1;
+		status->Setup = -1;
+		
+		local_irq_restore(flags);
+		return 0;
+	}
+	
+	rate = A2232_BAUD_TABLE_NOAVAIL;
+	for (i=0; i < A2232_BAUD_TABLE_NUM_RATES * 3; i += 3){
+		if (a2232_baud_table[i] == baud){
+			if (mem->Common.Crystal == A2232_TURBO) rate = a2232_baud_table[i+2];
+			else                                    rate = a2232_baud_table[i+1];
+		}
+	}
+	if (rate == A2232_BAUD_TABLE_NOAVAIL){
+		printk("a2232: Board %d Port %d unsupported baud rate: %d baud. Using another.\n",port->which_a2232,port->which_port_on_a2232,baud);
+		// This is useful for both (turbo or normal) Crystal versions.
+		rate = A2232PARAM_B9600;
+	}
+	a2232_param |= rate;
+
+	cflag  = port->gs.port.tty->termios->c_cflag;
+
+	// get character size
+	chsize = cflag & CSIZE;
+	switch (chsize){
+		case CS8: 	a2232_param |= A2232PARAM_8Bit; break;
+		case CS7: 	a2232_param |= A2232PARAM_7Bit; break;
+		case CS6: 	a2232_param |= A2232PARAM_6Bit; break;
+		case CS5: 	a2232_param |= A2232PARAM_5Bit; break;
+		default:	printk("a2232: Board %d Port %d unsupported character size: %d. Using 8 data bits.\n",
+					port->which_a2232,port->which_port_on_a2232,chsize);
+				a2232_param |= A2232PARAM_8Bit; break;
+	}
+
+	// get number of stop bits
+	stopb  = cflag & CSTOPB;
+	if (stopb){ // two stop bits instead of one
+		printk("a2232: Board %d Port %d 2 stop bits unsupported. Using 1 stop bit.\n",
+			port->which_a2232,port->which_port_on_a2232);
+	}
+
+	// Warn if RTS/CTS not wanted
+	if (!(cflag & CRTSCTS)){
+#ifndef A2232_SUPPRESS_RTSCTS_WARNING
+		printk("a2232: Board %d Port %d cannot switch off firmware-implemented RTS/CTS hardware flow control.\n",
+			port->which_a2232,port->which_port_on_a2232);
+#endif
+	}
+
+	/*	I think this is correct.
+		However, IXOFF means _input_ flow control and I wonder
+		if one should care about IXON _output_ flow control,
+		too. If this makes problems, one should turn the A2232
+		firmware XON/XOFF "SoftFlow" flow control off and use
+		the conventional way of inserting START/STOP characters
+		by hand in throttle()/unthrottle().
+	*/
+	softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF );
+
+	// get Parity (Enabled/Disabled? If Enabled, Odd or Even?)
+	parity = cflag & (PARENB | PARODD);
+	if (parity & PARENB){
+		if (parity & PARODD){
+			a2232_cmd |= A2232CMD_OddParity;
+		}
+		else{
+			a2232_cmd |= A2232CMD_EvenParity;
+		}
+	}
+	else a2232_cmd |= A2232CMD_NoParity;
+
+
+	/*	Hmm. Maybe an own a2232_port structure
+		member would be cleaner?	*/
+	if (cflag & CLOCAL)
+		port->gs.port.flags &= ~ASYNC_CHECK_CD;
+	else
+		port->gs.port.flags |= ASYNC_CHECK_CD;
+
+
+	/* Now we have all parameters and can go to set them: */
+	local_irq_save(flags);
+
+	status->Param = a2232_param | A2232PARAM_RcvBaud;
+	status->Command = a2232_cmd | A2232CMD_Open |  A2232CMD_Enable;
+	status->SoftFlow = softflow;
+	status->OutDisable = 0;
+	status->Setup = -1;
+
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int  a2232_chars_in_buffer(void *ptr)
+{
+	struct a2232_port *port;
+	volatile struct a2232status *status; 
+	unsigned char ret; /* we need modulo-256 arithmetics */
+	port = ptr;
+	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
+#if A2232_IOBUFLEN != 256
+#error "Re-Implement a2232_chars_in_buffer()!"
+#endif
+	ret = (status->OutHead - status->OutTail);
+	return ret;
+}
+
+static void a2232_close(void *ptr)
+{
+	a2232_disable_tx_interrupts(ptr);
+	a2232_disable_rx_interrupts(ptr);
+	/* see the comment in a2232_shutdown_port above. */
+}
+
+static void a2232_hungup(void *ptr)
+{
+	a2232_close(ptr);
+}
+/*** END   OF REAL_DRIVER FUNCTIONS ***/
+
+/*** BEGIN  FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
+static int a2232_ioctl(	struct tty_struct *tty,
+			unsigned int cmd, unsigned long arg)
+{
+	return -ENOIOCTLCMD;
+}
+
+static void a2232_throttle(struct tty_struct *tty)
+{
+/* Throttle: System cannot take another chars: Drop RTS or
+             send the STOP char or whatever.
+   The A2232 firmware does RTS/CTS anyway, and XON/XOFF
+   if switched on. So the only thing we can do at this
+   layer here is not taking any characters out of the
+   A2232 buffer any more. */
+	struct a2232_port *port = tty->driver_data;
+	port->throttle_input = -1;
+}
+
+static void a2232_unthrottle(struct tty_struct *tty)
+{
+/* Unthrottle: dual to "throttle()" above. */
+	struct a2232_port *port = tty->driver_data;
+	port->throttle_input = 0;
+}
+
+static int  a2232_open(struct tty_struct * tty, struct file * filp)
+{
+/* More or less stolen from other drivers. */
+	int line;
+	int retval;
+	struct a2232_port *port;
+
+	line = tty->index;
+	port = &a2232_ports[line];
+	
+	tty->driver_data = port;
+	port->gs.port.tty = tty;
+	port->gs.port.count++;
+	retval = gs_init_port(&port->gs);
+	if (retval) {
+		port->gs.port.count--;
+		return retval;
+	}
+	port->gs.port.flags |= GS_ACTIVE;
+	retval = gs_block_til_ready(port, filp);
+
+	if (retval) {
+		port->gs.port.count--;
+		return retval;
+	}
+
+	a2232_enable_rx_interrupts(port);
+	
+	return 0;
+}
+/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
+
+static irqreturn_t a2232_vbl_inter(int irq, void *data)
+{
+#if A2232_IOBUFLEN != 256
+#error "Re-Implement a2232_vbl_inter()!"
+#endif
+
+struct a2232_port *port;
+volatile struct a2232memory *mem;
+volatile struct a2232status *status;
+unsigned char newhead;
+unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */
+unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */
+volatile u_char *ibuf, *cbuf, *obuf;
+int ch, err, n, p;
+	for (n = 0; n < nr_a2232; n++){		/* for every completely initialized A2232 board */
+		mem = a2232mem(n);
+		for (p = 0; p < NUMLINES; p++){	/* for every port on this board */
+			err = 0;
+			port = &a2232_ports[n*NUMLINES+p];
+			if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */
+
+				status = a2232stat(n,p);
+
+				if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */
+					newhead = status->InHead;               /* 65EC02 write pointer */
+					bufpos = status->InTail;
+
+					/* check for input for this port */
+					if (newhead != bufpos) {
+						/* buffer for input chars/events */
+						ibuf = mem->InBuf[p];
+ 
+						/* data types of bytes in ibuf */
+						cbuf = mem->InCtl[p];
+ 
+						/* do for all chars */
+						while (bufpos != newhead) {
+							/* which type of input data? */
+							switch (cbuf[bufpos]) {
+								/* switch on input event (CD, BREAK, etc.) */
+							case A2232INCTL_EVENT:
+								switch (ibuf[bufpos++]) {
+								case A2232EVENT_Break:
+									/* TODO: Handle BREAK signal */
+									break;
+									/*	A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are
+										handled in a separate queue and should not occur here. */
+								case A2232EVENT_Sync:
+									printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring.");
+									break;
+								default:
+									printk("A2232: 65EC02 software broken, unknown event type %d occurred.\n",ibuf[bufpos-1]);
+								} /* event type switch */
+								break;
+ 							case A2232INCTL_CHAR:
+								/* Receive incoming char */
+								a2232_receive_char(port, ibuf[bufpos], err);
+								bufpos++;
+								break;
+ 							default:
+								printk("A2232: 65EC02 software broken, unknown data type %d occurred.\n",cbuf[bufpos]);
+								bufpos++;
+							} /* switch on input data type */
+						} /* while there's something in the buffer */
+
+						status->InTail = bufpos;            /* tell 65EC02 what we've read */
+						
+					} /* if there was something in the buffer */                          
+				} /* If input is not disabled */
+
+				/* Now check if there's something to output */
+				obuf = mem->OutBuf[p];
+				bufpos = status->OutHead;
+				while ( (port->gs.xmit_cnt > 0)		&&
+					(!port->gs.port.tty->stopped)	&&
+					(!port->gs.port.tty->hw_stopped) ){	/* While there are chars to transmit */
+					if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */
+						ch = port->gs.xmit_buf[port->gs.xmit_tail];					/* get the next char to transmit */
+						port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */
+						obuf[bufpos++] = ch;																/* put it into the A2232 buffer */
+						port->gs.xmit_cnt--;
+					}
+					else{																									/* If A2232 the buffer is full */
+						break;																							/* simply stop filling it. */
+					}													
+				}					
+				status->OutHead = bufpos;
+					
+				/* WakeUp if output buffer runs low */
+				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
+					tty_wakeup(port->gs.port.tty);
+				}
+			} // if the port is used
+		} // for every port on the board
+			
+		/* Now check the CD message queue */
+		newhead = mem->Common.CDHead;
+		bufpos = mem->Common.CDTail;
+		if (newhead != bufpos){				/* There are CD events in queue */
+			ocd = mem->Common.CDStatus; 		/* get old status bits */
+			while (newhead != bufpos){		/* read all events */
+				ncd = mem->CDBuf[bufpos++]; 	/* get one event */
+				ccd = ncd ^ ocd; 		/* mask of changed lines */
+				ocd = ncd; 			/* save new status bits */
+				for(p=0; p < NUMLINES; p++){	/* for all ports */
+					if (ccd & 1){		/* this one changed */
+
+						struct a2232_port *port = &a2232_ports[n*7+p];
+						port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */
+
+						if (!(port->gs.port.flags & ASYNC_CHECK_CD))
+							;	/* Don't report DCD changes */
+						else if (port->cd_status) { // if DCD on: DCD went UP!
+							
+							/* Are we blocking in open?*/
+							wake_up_interruptible(&port->gs.port.open_wait);
+						}
+						else { // if DCD off: DCD went DOWN!
+							if (port->gs.port.tty)
+								tty_hangup (port->gs.port.tty);
+						}
+						
+					} // if CD changed for this port
+					ccd >>= 1;
+					ncd >>= 1;									/* Shift bits for next line */
+				} // for every port
+			} // while CD events in queue
+			mem->Common.CDStatus = ocd; /* save new status */
+			mem->Common.CDTail = bufpos; /* remove events */
+		} // if events in CD queue
+		
+	} // for every completely initialized A2232 board
+	return IRQ_HANDLED;
+}
+
+static const struct tty_port_operations a2232_port_ops = {
+	.carrier_raised = a2232_carrier_raised,
+};
+
+static void a2232_init_portstructs(void)
+{
+	struct a2232_port *port;
+	int i;
+
+	for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
+		port = a2232_ports + i;
+		tty_port_init(&port->gs.port);
+		port->gs.port.ops = &a2232_port_ops;
+		port->which_a2232 = i/NUMLINES;
+		port->which_port_on_a2232 = i%NUMLINES;
+		port->disable_rx = port->throttle_input = port->cd_status = 0;
+		port->gs.magic = A2232_MAGIC;
+		port->gs.close_delay = HZ/2;
+		port->gs.closing_wait = 30 * HZ;
+		port->gs.rd = &a2232_real_driver;
+	}
+}
+
+static const struct tty_operations a2232_ops = {
+	.open = a2232_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = a2232_ioctl,
+	.throttle = a2232_throttle,
+	.unthrottle = a2232_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+};
+
+static int a2232_init_drivers(void)
+{
+	int error;
+
+	a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232);
+	if (!a2232_driver)
+		return -ENOMEM;
+	a2232_driver->owner = THIS_MODULE;
+	a2232_driver->driver_name = "commodore_a2232";
+	a2232_driver->name = "ttyY";
+	a2232_driver->major = A2232_NORMAL_MAJOR;
+	a2232_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	a2232_driver->subtype = SERIAL_TYPE_NORMAL;
+	a2232_driver->init_termios = tty_std_termios;
+	a2232_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	a2232_driver->init_termios.c_ispeed = 9600;
+	a2232_driver->init_termios.c_ospeed = 9600;
+	a2232_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(a2232_driver, &a2232_ops);
+	if ((error = tty_register_driver(a2232_driver))) {
+		printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n",
+		       error);
+		put_tty_driver(a2232_driver);
+		return 1;
+	}
+	return 0;
+}
+
+static int __init a2232board_init(void)
+{
+	struct zorro_dev *z;
+
+	unsigned int boardaddr;
+	int bcount;
+	short start;
+	u_char *from;
+	volatile u_char *to;
+	volatile struct a2232memory *mem;
+	int error, i;
+
+#ifdef CONFIG_SMP
+	return -ENODEV;	/* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
+#endif
+
+	if (!MACH_IS_AMIGA){
+		return -ENODEV;
+	}
+
+	printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */
+
+	z = NULL;
+	nr_a2232 = 0;
+	while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){
+		if (	(z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && 
+			(z->id != ZORRO_PROD_CBM_A2232)	){
+			continue;	// The board found was no A2232
+		}
+		if (!zorro_request_device(z,"A2232 driver"))
+			continue;
+
+		printk("Commodore A2232 found (#%d).\n",nr_a2232);
+
+		zd_a2232[nr_a2232] = z;
+
+		boardaddr = ZTWO_VADDR( z->resource.start );
+		printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start)));
+
+		mem = (volatile struct a2232memory *) boardaddr;
+
+		(void) mem->Enable6502Reset;   /* copy the code across to the board */
+		to = (u_char *)mem;  from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2;
+		start = *(short *)from;
+		from += sizeof(start);
+		to += start;
+		while(bcount--) *to++ = *from++;
+		printk("65EC02 software uploaded to the A2232 memory.\n");
+  
+		mem->Common.Crystal = A2232_UNKNOWN;  /* use automatic speed check */
+  
+		/* start 6502 running */
+		(void) mem->ResetBoard;
+		printk("A2232's 65EC02 CPU up and running.\n");
+  
+		/* wait until speed detector has finished */
+		for (bcount = 0; bcount < 2000; bcount++) {
+			udelay(1000);
+			if (mem->Common.Crystal)
+				break;
+		}
+		printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: "));
+		switch (mem->Common.Crystal){
+		case A2232_UNKNOWN:
+			printk("Unknown crystal.\n");
+			break;
+ 		case A2232_NORMAL:
+			printk ("Normal crystal.\n");
+			break;
+		case A2232_TURBO:
+			printk ("Turbo crystal.\n");
+			break;
+		default:
+			printk ("0x%x. Huh?\n",mem->Common.Crystal);
+		}
+
+		nr_a2232++;
+
+	}	
+
+	printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */
+
+	a2232_init_portstructs();
+
+	/*
+		a2232_init_drivers also registers the drivers. Must be here because all boards
+		have to be detected first.
+	*/
+	if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
+
+	error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
+			    "A2232 serial VBL", a2232_driver_ID);
+	if (error) {
+		for (i = 0; i < nr_a2232; i++)
+			zorro_release_device(zd_a2232[i]);
+		tty_unregister_driver(a2232_driver);
+		put_tty_driver(a2232_driver);
+	}
+	return error;
+}
+
+static void __exit a2232board_exit(void)
+{
+	int i;
+
+	for (i = 0; i < nr_a2232; i++) {
+		zorro_release_device(zd_a2232[i]);
+	}
+
+	tty_unregister_driver(a2232_driver);
+	put_tty_driver(a2232_driver);
+	free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID);
+}
+
+module_init(a2232board_init);
+module_exit(a2232board_exit);
+
+MODULE_AUTHOR("Enver Haase");
+MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/generic_serial/ser_a2232.h b/drivers/staging/generic_serial/ser_a2232.h
new file mode 100644
index 0000000..bc09eb9
--- /dev/null
+++ b/drivers/staging/generic_serial/ser_a2232.h
@@ -0,0 +1,202 @@
+/* drivers/char/ser_a2232.h */
+
+/* $Id: ser_a2232.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
+
+/* Linux serial driver for the Amiga A2232 board */
+
+/* This driver is MAINTAINED. Before applying any changes, please contact
+ * the author.
+ */
+   
+/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
+ *                   alias The A2232 driver project <A2232@gmx.net>
+ * All rights reserved.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  
+ */
+
+#ifndef _SER_A2232_H_
+#define _SER_A2232_H_
+
+/*
+	How many boards are to be supported at maximum;
+	"up to five A2232 Multiport Serial Cards may be installed in a
+	single Amiga 2000" states the A2232 User's Guide. If you have
+	more slots available, you might want to change the value below.
+*/
+#define MAX_A2232_BOARDS 5
+
+#ifndef A2232_NORMAL_MAJOR
+/* This allows overriding on the compiler commandline, or in a "major.h" 
+   include or something like that */
+#define A2232_NORMAL_MAJOR  224	/* /dev/ttyY* */
+#define A2232_CALLOUT_MAJOR 225	/* /dev/cuy*  */
+#endif
+
+/* Some magic is always good - Who knows :) */
+#define A2232_MAGIC 0x000a2232
+
+/* A2232 port structure to keep track of the
+   status of every single line used */
+struct a2232_port{
+	struct gs_port gs;
+	unsigned int which_a2232;
+	unsigned int which_port_on_a2232;
+	short disable_rx;
+	short throttle_input;
+	short cd_status;
+};
+
+#define	NUMLINES		7	/* number of lines per board */
+#define	A2232_IOBUFLEN		256	/* number of bytes per buffer */
+#define	A2232_IOBUFLENMASK	0xff	/* mask for maximum number of bytes */
+
+
+#define	A2232_UNKNOWN	0	/* crystal not known */
+#define	A2232_NORMAL	1	/* normal A2232 (1.8432 MHz oscillator) */
+#define	A2232_TURBO	2	/* turbo A2232 (3.6864 MHz oscillator) */
+
+
+struct a2232common {
+	char   Crystal;	/* normal (1) or turbo (2) board? */
+	u_char Pad_a;
+	u_char TimerH;	/* timer value after speed check */
+	u_char TimerL;
+	u_char CDHead;	/* head pointer for CD message queue */
+	u_char CDTail;	/* tail pointer for CD message queue */
+	u_char CDStatus;
+	u_char Pad_b;
+};
+
+struct a2232status {
+	u_char InHead;		/* input queue head */
+	u_char InTail;		/* input queue tail */
+	u_char OutDisable;	/* disables output */
+	u_char OutHead;		/* output queue head */
+	u_char OutTail;		/* output queue tail */
+	u_char OutCtrl;		/* soft flow control character to send */
+	u_char OutFlush;	/* flushes output buffer */
+	u_char Setup;		/* causes reconfiguration */
+	u_char Param;		/* parameter byte - see A2232PARAM */
+	u_char Command;		/* command byte - see A2232CMD */
+	u_char SoftFlow;	/* enables xon/xoff flow control */
+	/* private 65EC02 fields: */
+	u_char XonOff;		/* stores XON/XOFF enable/disable */
+};
+
+#define	A2232_MEMPAD1	\
+	(0x0200 - NUMLINES * sizeof(struct a2232status)	-	\
+	sizeof(struct a2232common))
+#define	A2232_MEMPAD2	(0x2000 - NUMLINES * A2232_IOBUFLEN - A2232_IOBUFLEN)
+
+struct a2232memory {
+	struct a2232status Status[NUMLINES];	/* 0x0000-0x006f status areas */
+	struct a2232common Common;		/* 0x0070-0x0077 common flags */
+	u_char Dummy1[A2232_MEMPAD1];		/* 0x00XX-0x01ff */
+	u_char OutBuf[NUMLINES][A2232_IOBUFLEN];/* 0x0200-0x08ff output bufs */
+	u_char InBuf[NUMLINES][A2232_IOBUFLEN];	/* 0x0900-0x0fff input bufs */
+	u_char InCtl[NUMLINES][A2232_IOBUFLEN];	/* 0x1000-0x16ff control data */
+	u_char CDBuf[A2232_IOBUFLEN];		/* 0x1700-0x17ff CD event buffer */
+	u_char Dummy2[A2232_MEMPAD2];		/* 0x1800-0x2fff */
+	u_char Code[0x1000];			/* 0x3000-0x3fff code area */
+	u_short InterruptAck;			/* 0x4000        intr ack */
+	u_char Dummy3[0x3ffe];			/* 0x4002-0x7fff */
+	u_short Enable6502Reset;		/* 0x8000 Stop board, */
+						/*  6502 RESET line held low */
+	u_char Dummy4[0x3ffe];			/* 0x8002-0xbfff */
+	u_short ResetBoard;			/* 0xc000 reset board & run, */
+						/*  6502 RESET line held high */
+};
+
+#undef A2232_MEMPAD1
+#undef A2232_MEMPAD2
+
+#define	A2232INCTL_CHAR		0	/* corresponding byte in InBuf is a character */
+#define	A2232INCTL_EVENT	1	/* corresponding byte in InBuf is an event */
+
+#define	A2232EVENT_Break	1	/* break set */
+#define	A2232EVENT_CarrierOn	2	/* carrier raised */
+#define	A2232EVENT_CarrierOff	3	/* carrier dropped */
+#define A2232EVENT_Sync		4	/* don't know, defined in 2232.ax */
+
+#define	A2232CMD_Enable		0x1	/* enable/DTR bit */
+#define	A2232CMD_Close		0x2	/* close the device */
+#define	A2232CMD_Open		0xb	/* open the device */
+#define	A2232CMD_CMask		0xf	/* command mask */
+#define	A2232CMD_RTSOff		0x0  	/* turn off RTS */
+#define	A2232CMD_RTSOn		0x8	/* turn on RTS */
+#define	A2232CMD_Break		0xd	/* transmit a break */
+#define	A2232CMD_RTSMask	0xc	/* mask for RTS stuff */
+#define	A2232CMD_NoParity	0x00	/* don't use parity */
+#define	A2232CMD_OddParity	0x20	/* odd parity */
+#define	A2232CMD_EvenParity	0x60	/* even parity */
+#define	A2232CMD_ParityMask	0xe0	/* parity mask */
+
+#define	A2232PARAM_B115200	0x0	/* baud rates */
+#define	A2232PARAM_B50		0x1
+#define	A2232PARAM_B75		0x2
+#define	A2232PARAM_B110		0x3
+#define	A2232PARAM_B134		0x4
+#define	A2232PARAM_B150		0x5
+#define	A2232PARAM_B300		0x6
+#define	A2232PARAM_B600		0x7
+#define	A2232PARAM_B1200	0x8
+#define	A2232PARAM_B1800	0x9
+#define	A2232PARAM_B2400	0xa
+#define	A2232PARAM_B3600	0xb
+#define	A2232PARAM_B4800	0xc
+#define	A2232PARAM_B7200	0xd
+#define	A2232PARAM_B9600	0xe
+#define	A2232PARAM_B19200	0xf
+#define	A2232PARAM_BaudMask	0xf	/* baud rate mask */
+#define	A2232PARAM_RcvBaud	0x10	/* enable receive baud rate */
+#define	A2232PARAM_8Bit		0x00	/* numbers of bits */
+#define	A2232PARAM_7Bit		0x20
+#define	A2232PARAM_6Bit		0x40
+#define	A2232PARAM_5Bit		0x60
+#define	A2232PARAM_BitMask	0x60	/* numbers of bits mask */
+
+
+/* Standard speeds tables, -1 means unavailable, -2 means 0 baud: switch off line */
+#define A2232_BAUD_TABLE_NOAVAIL -1
+#define A2232_BAUD_TABLE_NUM_RATES (18)
+static int a2232_baud_table[A2232_BAUD_TABLE_NUM_RATES*3] = {
+	//Baud	//Normal			//Turbo
+	50,	A2232PARAM_B50,			A2232_BAUD_TABLE_NOAVAIL,
+	75,	A2232PARAM_B75,			A2232_BAUD_TABLE_NOAVAIL,
+	110,	A2232PARAM_B110,		A2232_BAUD_TABLE_NOAVAIL,
+	134,	A2232PARAM_B134,		A2232_BAUD_TABLE_NOAVAIL,
+	150,	A2232PARAM_B150,		A2232PARAM_B75,
+	200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
+	300,	A2232PARAM_B300,		A2232PARAM_B150,
+	600,	A2232PARAM_B600,		A2232PARAM_B300,
+	1200,	A2232PARAM_B1200,		A2232PARAM_B600,
+	1800,	A2232PARAM_B1800,		A2232_BAUD_TABLE_NOAVAIL,
+	2400,	A2232PARAM_B2400,		A2232PARAM_B1200,
+	4800,	A2232PARAM_B4800,		A2232PARAM_B2400,
+	9600,	A2232PARAM_B9600,		A2232PARAM_B4800,
+	19200,	A2232PARAM_B19200,		A2232PARAM_B9600,
+	38400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B19200,
+	57600,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
+#ifdef A2232_SPEEDHACK
+	115200,	A2232PARAM_B115200,		A2232_BAUD_TABLE_NOAVAIL,
+	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B115200
+#else
+	115200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
+	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL
+#endif
+};
+#endif
diff --git a/drivers/staging/generic_serial/ser_a2232fw.ax b/drivers/staging/generic_serial/ser_a2232fw.ax
new file mode 100644
index 0000000..7364380
--- /dev/null
+++ b/drivers/staging/generic_serial/ser_a2232fw.ax
@@ -0,0 +1,529 @@
+;.lib "axm"
+;
+;begin
+;title "A2232 serial board driver"
+;
+;set modules "2232"
+;set executable "2232.bin"
+;
+;;;;set nolink
+;
+;set temporary directory "t:"
+;
+;set assembly options "-m6502 -l60:t:list"
+;set link options "bin"; loadadr"
+;;;bin2c 2232.bin msc6502.h msc6502code
+;end
+;
+;
+; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ###
+;
+; - Created 950501 by JM -
+;
+;
+; Serial board driver software.
+;
+;
+% Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
+% All rights reserved.
+%
+% Redistribution and use in source and binary forms, with or without
+% modification, are permitted provided that the following conditions
+% are met:
+% 1. Redistributions of source code must retain the above copyright
+%    notice, and the entire permission notice in its entirety,
+%    including the disclaimer of warranties.
+% 2. Redistributions in binary form must reproduce the above copyright
+%    notice, this list of conditions and the following disclaimer in the
+%    documentation and/or other materials provided with the distribution.
+% 3. The name of the author may not be used to endorse or promote
+%    products derived from this software without specific prior
+%    written permission.
+%
+% ALTERNATIVELY, this product may be distributed under the terms of
+% the GNU General Public License, in which case the provisions of the
+% GPL are required INSTEAD OF the above restrictions.  (This clause is
+% necessary due to a potential bad interaction between the GPL and
+% the restrictions contained in a BSD-style copyright.)
+%
+% THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
+% WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+% OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+% DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+% INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+% (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+% SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+% HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+% STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+% OF THE POSSIBILITY OF SUCH DAMAGE.
+;
+;
+; Bugs:
+;
+; - Can't send a break yet
+;
+;
+;
+; Edited:
+;
+; - 950501 by JM -> v0.1	- Created this file.
+; - 951029 by JM -> v1.3	- Carrier Detect events now queued in a separate
+;				  queue.
+;
+;
+
+
+CODE		equ	$3800		; start address for program code
+
+
+CTL_CHAR	equ	$00		; byte in ibuf is a character
+CTL_EVENT	equ	$01		; byte in ibuf is an event
+
+EVENT_BREAK	equ	$01
+EVENT_CDON	equ	$02
+EVENT_CDOFF	equ	$03
+EVENT_SYNC	equ	$04
+
+XON		equ	$11
+XOFF		equ	$13
+
+
+VARBASE		macro	*starting_address	; was VARINIT
+_varbase	set	\1
+		endm
+
+VARDEF		macro	*name space_needs
+\1		equ	_varbase
+_varbase	set	_varbase+\2
+		endm
+
+
+stz		macro	* address
+		 db	$64,\1
+		endm
+
+stzax		macro	* address
+		 db	$9e,<\1,>\1
+		endm
+
+
+biti		macro	* immediate value
+		db	$89,\1
+		endm
+
+smb0		macro	* address
+		db	$87,\1
+		endm
+smb1		macro	* address
+		db	$97,\1
+		endm
+smb2		macro	* address
+		db	$a7,\1
+		endm
+smb3		macro	* address
+		db	$b7,\1
+		endm
+smb4		macro	* address
+		db	$c7,\1
+		endm
+smb5		macro	* address
+		db	$d7,\1
+		endm
+smb6		macro	* address
+		db	$e7,\1
+		endm
+smb7		macro	* address
+		db	$f7,\1
+		endm
+
+
+
+;-----------------------------------------------------------------------;
+;									;
+; stuff common for all ports, non-critical (run once / loop)		;
+;									;
+DO_SLOW		macro	* port_number					;
+		.local			;				;
+		lda	CIA+C_PA	; check all CD inputs		;
+		cmp	CommonCDo	; changed from previous accptd?	;
+		beq	=over		; nope, do nothing else here	;
+					;				;
+		cmp	CommonCDb	; bouncing?			;
+		beq	=nobounce	; nope ->			;
+					;				;
+		sta	CommonCDb	; save current state		;
+		lda	#64		; reinitialize counter		;
+		sta	CommonCDc	;				;
+		jmp	=over		; skip CD save			;
+					;				;
+=nobounce	dec	CommonCDc	; no, decrement bounce counter	;
+		bpl	=over		; not done yet, so skip CD save	;
+					;				;
+=saveCD		ldx	CDHead		; get write index		;
+		sta	cdbuf,x		; save status in buffer		;
+		inx			;				;
+		cpx	CDTail		; buffer full?			;
+		.if	ne		; no: preserve status:		;
+		 stx	CDHead		; update index in RAM		;
+		 sta	CommonCDo	; save state for the next check	;
+		.end			;				;
+=over		.end	local						;
+		endm							;
+									;
+;-----------------------------------------------------------------------;
+
+
+; port specific stuff (no data transfer)
+
+DO_PORT		macro	* port_number
+		.local			;				;
+		lda	SetUp\1		; reconfiguration request?	;
+		.if	ne		; yes:				;
+		 lda	SoftFlow\1	; get XON/XOFF flag		;
+		 sta	XonOff\1	; save it			;
+		 lda	Param\1		; get parameter			;
+		 ora	#%00010000	; use baud generator for Rx	;
+		 sta	ACIA\1+A_CTRL	; store in control register	;
+		 stz	OutDisable\1	; enable transmit output	;
+		 stz	SetUp\1		; no reconfiguration no more	;
+		.end			;				;
+					;				;
+		lda	InHead\1	; get write index		;
+		sbc	InTail\1	; buffer full soon?		;
+		cmp	#200		; 200 chars or more in buffer?	;
+		lda	Command\1	; get Command reg value		;
+		and	#%11110011	; turn RTS OFF by default	;
+		.if	cc		; still room in buffer:		;
+		 ora	#%00001000	; turn RTS ON			;
+		.end			;				;
+		sta	ACIA\1+A_CMD	; set/clear RTS			;
+					;				;
+		lda	OutFlush\1	; request to flush output buffer;
+		.if	ne		; yessh!			;
+		 lda	OutHead\1	; get head			;
+		 sta	OutTail\1	; save as tail			;
+		 stz	OutDisable\1	; enable transmit output	;
+		 stz	OutFlush\1	; clear request			;
+		.end
+		.end	local
+		endm
+
+
+DO_DATA		macro	* port number
+		.local
+		lda	ACIA\1+A_SR	; read ACIA status register	;
+		biti	[1<<3]		; something received?		;
+		.if	ne		; yes:				;
+		 biti	[1<<1]		; framing error?		;
+		 .if	ne		; yes:				;
+		  lda	ACIA\1+A_DATA	; read received character	;
+		  bne	=SEND		; not break -> ignore it	;
+		  ldx	InHead\1	; get write pointer		;
+		  lda	#CTL_EVENT	; get type of byte		;
+		  sta	ictl\1,x	; save it in InCtl buffer	;
+		  lda	#EVENT_BREAK	; event code			;
+		  sta	ibuf\1,x	; save it as well		;
+		  inx			;				;
+		  cpx	InTail\1	; still room in buffer?		;
+		  .if	ne		; absolutely:			;
+		   stx	InHead\1	; update index in memory	;
+		  .end			;				;
+		  jmp	=SEND		; go check if anything to send	;
+		 .end			;				;
+		 			; normal char received:		;
+		 ldx	InHead\1	; get write index		;
+		 lda	ACIA\1+A_DATA	; read received character	;
+		 sta	ibuf\1,x	; save char in buffer		;
+		 stzax	ictl\1		; set type to CTL_CHAR		;
+		 inx			;				;
+		 cpx	InTail\1	; buffer full?			;
+		 .if	ne		; no: preserve character:	;
+		  stx	InHead\1	; update index in RAM		;
+		 .end			;				;
+		 and	#$7f		; mask off parity if any	;
+		 cmp	#XOFF		; XOFF from remote host?	;
+		 .if	eq		; yes:				;
+		  lda	XonOff\1	; if XON/XOFF handshaking..	;
+		  sta	OutDisable\1	; ..disable transmitter		;
+		 .end			;				;
+		.end			;				;
+					;				;
+					; BUFFER FULL CHECK WAS HERE	;
+					;				;
+=SEND		lda	ACIA\1+A_SR	; transmit register empty?	;
+		and	#[1<<4]		;				;
+		.if	ne		; yes:				;
+		 ldx	OutCtrl\1	; sending out XON/XOFF?		;
+		 .if	ne		; yes:				;
+		  lda	CIA+C_PB	; check CTS signal		;
+		  and	#[1<<\1]	; (for this port only)		;
+		  bne	=DONE		; not allowed to send -> done	;
+		  stx	ACIA\1+A_DATA	; transmit control char		;
+		  stz	OutCtrl\1	; clear flag			;
+		  jmp	=DONE		; and we're done		;
+		 .end			;				;
+					;				;
+		 ldx	OutTail\1	; anything to transmit?		;
+		 cpx	OutHead\1	;				;
+		 .if	ne		; yes:				;
+		  lda	OutDisable\1	; allowed to transmit?		;
+		  .if	eq		; yes:				;
+		   lda	CIA+C_PB	; check CTS signal		;
+		   and	#[1<<\1]	; (for this port only)		;
+		   bne	=DONE		; not allowed to send -> done	;
+		   lda	obuf\1,x	; get a char from buffer	;
+		   sta	ACIA\1+A_DATA	; send it away			;
+		   inc	OutTail\1	; update read index		;
+		  .end			;				;
+		 .end			;				;
+		.end			;				;
+=DONE		.end	local
+		endm
+
+
+
+PORTVAR		macro	* port number
+		VARDEF	InHead\1 1
+		VARDEF	InTail\1 1
+		VARDEF	OutDisable\1 1
+		VARDEF	OutHead\1 1
+		VARDEF	OutTail\1 1
+		VARDEF	OutCtrl\1 1
+		VARDEF	OutFlush\1 1
+		VARDEF	SetUp\1 1
+		VARDEF	Param\1 1
+		VARDEF	Command\1 1
+		VARDEF	SoftFlow\1 1
+		; private:
+		VARDEF	XonOff\1 1
+		endm
+
+
+ VARBASE 0	; start variables at address $0000
+ PORTVAR 0	; define variables for port 0
+ PORTVAR 1	; define variables for port 1
+ PORTVAR 2	; define variables for port 2
+ PORTVAR 3	; define variables for port 3
+ PORTVAR 4	; define variables for port 4
+ PORTVAR 5	; define variables for port 5
+ PORTVAR 6	; define variables for port 6
+
+
+
+ VARDEF	Crystal	1	; 0 = unknown, 1 = normal, 2 = turbo
+ VARDEF	Pad_a	1
+ VARDEF	TimerH	1
+ VARDEF	TimerL	1
+ VARDEF	CDHead	1
+ VARDEF	CDTail	1
+ VARDEF	CDStatus 1
+ VARDEF	Pad_b	1
+
+ VARDEF	CommonCDo 1	; for carrier detect optimization
+ VARDEF	CommonCDc 1	; for carrier detect debouncing
+ VARDEF	CommonCDb 1	; for carrier detect debouncing
+
+
+ VARBASE $0200
+ VARDEF	obuf0 256	; output data (characters only)
+ VARDEF	obuf1 256
+ VARDEF	obuf2 256
+ VARDEF	obuf3 256
+ VARDEF	obuf4 256
+ VARDEF	obuf5 256
+ VARDEF	obuf6 256
+
+ VARDEF	ibuf0 256	; input data (characters, events etc - see ictl)
+ VARDEF	ibuf1 256
+ VARDEF	ibuf2 256
+ VARDEF	ibuf3 256
+ VARDEF	ibuf4 256
+ VARDEF	ibuf5 256
+ VARDEF	ibuf6 256
+
+ VARDEF	ictl0 256	; input control information (type of data in ibuf)
+ VARDEF	ictl1 256
+ VARDEF	ictl2 256
+ VARDEF	ictl3 256
+ VARDEF	ictl4 256
+ VARDEF	ictl5 256
+ VARDEF	ictl6 256
+
+ VARDEF	cdbuf 256	; CD event queue
+
+
+ACIA0		equ	$4400
+ACIA1		equ	$4c00
+ACIA2		equ	$5400
+ACIA3		equ	$5c00
+ACIA4		equ	$6400
+ACIA5		equ	$6c00
+ACIA6		equ	$7400
+
+A_DATA		equ	$00
+A_SR		equ	$02
+A_CMD		equ	$04
+A_CTRL		equ	$06
+;  00	write transmit data	read received data
+;  02	reset ACIA		read status register
+;  04	write command register	read command register
+;  06	write control register	read control register
+
+CIA		equ	$7c00		; 8520 CIA
+C_PA		equ	$00		; port A data register
+C_PB		equ	$02		; port B data register
+C_DDRA		equ	$04		; data direction register for port A
+C_DDRB		equ	$06		; data direction register for port B
+C_TAL		equ	$08		; timer A
+C_TAH		equ	$0a
+C_TBL		equ	$0c		; timer B
+C_TBH		equ	$0e
+C_TODL		equ	$10		; TOD LSB
+C_TODM		equ	$12		; TOD middle byte
+C_TODH		equ	$14		; TOD MSB
+C_DATA		equ	$18		; serial data register
+C_INTCTRL	equ	$1a		; interrupt control register
+C_CTRLA		equ	$1c		; control register A
+C_CTRLB		equ	$1e		; control register B
+
+
+
+
+
+		section	main,code,CODE-2
+
+		db	>CODE,<CODE
+
+;-----------------------------------------------------------------------;
+; here's the initialization code:					;
+;									;
+R_RESET		ldx	#$ff						;
+		txs			; initialize stack pointer	;
+		cld			; in case a 6502 is used...	;
+		ldx	#0		;				;
+		lda	#0		;				;
+		ldy	#Crystal	; this many bytes to clear	;
+clr_loop	sta	0,x		; clear zero page variables	;
+		inx			;				;
+		dey			;				;
+		bne	clr_loop	;				;
+					;				;
+		stz	CommonCDo	; force CD test at boot		;
+		stz	CommonCDb	;				;
+		stz	CDHead		; clear queue			;
+		stz	CDTail		;				;
+					;				;
+		lda	#0		;				;
+		sta	Pad_a		;				;
+		lda	#170		; test cmp			;
+		cmp	#100		;				;
+		.if	cs		;				;
+		 inc	Pad_a		; C was set			;
+		.end			;				;
+									;
+;-----------------------------------------------------------------------;
+; Speed check								;
+;-----------------------------------------------------------------------;
+									;
+		lda	Crystal		; speed already set?		;
+		beq	DoSpeedy	;				;
+		jmp	LOOP		; yes, skip speed test		;
+					;				;
+DoSpeedy	lda	#%10011000	; 8N1, 1200/2400 bps		;
+		sta	ACIA0+A_CTRL	;				;
+		lda	#%00001011	; enable DTR			;
+		sta	ACIA0+A_CMD	;				;
+		lda	ACIA0+A_SR	; read status register		;
+					;				;
+		lda	#%10000000	; disable all ints (unnecessary);
+		sta	CIA+C_INTCTRL	;				;
+		lda	#255		; program the timer		;
+		sta	CIA+C_TAL	;				;
+		sta	CIA+C_TAH	;				;
+					;				;
+		ldx	#0		;				;
+		stx	ACIA0+A_DATA	; transmit a zero		;
+		nop			;				;
+		nop			;				;
+		lda	ACIA0+A_SR	; read status			;
+		nop			;				;
+		nop			;				;
+		stx	ACIA0+A_DATA	; transmit a zero		;
+Speedy1		lda	ACIA0+A_SR	; read status			;
+		and	#[1<<4]		; transmit data reg empty?	;
+		beq	Speedy1		; not yet, wait more		;
+					;				;
+		lda	#%00010001	; load & start the timer	;
+		stx	ACIA0+A_DATA	; transmit one more zero	;
+		sta	CIA+C_CTRLA	;				;
+Speedy2		lda	ACIA0+A_SR	; read status			;
+		and	#[1<<4]		; transmit data reg empty?	;
+		beq	Speedy2		; not yet, wait more		;
+		stx	CIA+C_CTRLA	; stop the timer		;
+					;				;
+		lda	CIA+C_TAL	; copy timer value for 68k	;
+		sta	TimerL		;				;
+		lda	CIA+C_TAH	;				;
+		sta	TimerH		;				;
+		cmp	#$d0		; turbo or normal?		;
+		.if	cs		;				;
+		 lda	#2		; turbo! :-)			;
+		.else			;				;
+		 lda	#1		; normal :-(			;
+		.end			;				;
+		sta	Crystal		;				;
+		lda	#0		;				;
+		sta	ACIA0+A_SR	;				;
+		sta	ACIA0+A_CTRL	; reset UART			;
+		sta	ACIA0+A_CMD	;				;
+									;
+		jmp	LOOP						;
+									;
+;									;
+;-----------------------------------------------------------------------;
+;									;
+; The Real Thing:							;
+;									;
+LOOP		DO_SLOW			; do non-critical things	;
+		jsr	do_input	; check for received data
+		DO_PORT	0
+		jsr	do_input
+		DO_PORT	1
+		jsr	do_input
+		DO_PORT	2
+		jsr	do_input
+		DO_PORT	3
+		jsr	do_input
+		DO_PORT	4
+		jsr	do_input
+		DO_PORT	5
+		jsr	do_input
+		DO_PORT	6
+		jsr	do_input
+		jmp	LOOP
+
+
+do_input	DO_DATA	0
+		DO_DATA	1
+		DO_DATA	2
+		DO_DATA	3
+		DO_DATA	4
+		DO_DATA	5
+		DO_DATA	6
+		rts
+
+
+;-----------------------------------------------------------------------;
+		section	vectors,data,$3ffa
+		dw	$d0d0
+		dw	R_RESET
+		dw	$c0ce
+;-----------------------------------------------------------------------;
+
+
+
+		end
+
+
+
diff --git a/drivers/staging/generic_serial/ser_a2232fw.h b/drivers/staging/generic_serial/ser_a2232fw.h
new file mode 100644
index 0000000..e09a30a
--- /dev/null
+++ b/drivers/staging/generic_serial/ser_a2232fw.h
@@ -0,0 +1,306 @@
+/* drivers/char/ser_a2232fw.h */
+
+/* $Id: ser_a2232fw.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
+
+/*
+ * Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, and the entire permission notice in its entirety,
+ *    including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ *    products derived from this software without specific prior
+ *    written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions.  (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+                                      
+/* This is the 65EC02 code by Jukka Marin that is executed by
+   the A2232's 65EC02 processor (base address: 0x3800)
+   Source file:	ser_a2232fw.ax
+   Version:	1.3 (951029)
+   Known Bugs:	Cannot send a break yet
+*/
+static unsigned char a2232_65EC02code[] = {
+	0x38, 0x00, 0xA2, 0xFF, 0x9A, 0xD8, 0xA2, 0x00, 
+	0xA9, 0x00, 0xA0, 0x54, 0x95, 0x00, 0xE8, 0x88, 
+	0xD0, 0xFA, 0x64, 0x5C, 0x64, 0x5E, 0x64, 0x58, 
+	0x64, 0x59, 0xA9, 0x00, 0x85, 0x55, 0xA9, 0xAA, 
+	0xC9, 0x64, 0x90, 0x02, 0xE6, 0x55, 0xA5, 0x54, 
+	0xF0, 0x03, 0x4C, 0x92, 0x38, 0xA9, 0x98, 0x8D, 
+	0x06, 0x44, 0xA9, 0x0B, 0x8D, 0x04, 0x44, 0xAD, 
+	0x02, 0x44, 0xA9, 0x80, 0x8D, 0x1A, 0x7C, 0xA9, 
+	0xFF, 0x8D, 0x08, 0x7C, 0x8D, 0x0A, 0x7C, 0xA2, 
+	0x00, 0x8E, 0x00, 0x44, 0xEA, 0xEA, 0xAD, 0x02, 
+	0x44, 0xEA, 0xEA, 0x8E, 0x00, 0x44, 0xAD, 0x02, 
+	0x44, 0x29, 0x10, 0xF0, 0xF9, 0xA9, 0x11, 0x8E, 
+	0x00, 0x44, 0x8D, 0x1C, 0x7C, 0xAD, 0x02, 0x44, 
+	0x29, 0x10, 0xF0, 0xF9, 0x8E, 0x1C, 0x7C, 0xAD, 
+	0x08, 0x7C, 0x85, 0x57, 0xAD, 0x0A, 0x7C, 0x85, 
+	0x56, 0xC9, 0xD0, 0x90, 0x05, 0xA9, 0x02, 0x4C, 
+	0x82, 0x38, 0xA9, 0x01, 0x85, 0x54, 0xA9, 0x00, 
+	0x8D, 0x02, 0x44, 0x8D, 0x06, 0x44, 0x8D, 0x04, 
+	0x44, 0x4C, 0x92, 0x38, 0xAD, 0x00, 0x7C, 0xC5, 
+	0x5C, 0xF0, 0x1F, 0xC5, 0x5E, 0xF0, 0x09, 0x85, 
+	0x5E, 0xA9, 0x40, 0x85, 0x5D, 0x4C, 0xB8, 0x38, 
+	0xC6, 0x5D, 0x10, 0x0E, 0xA6, 0x58, 0x9D, 0x00, 
+	0x17, 0xE8, 0xE4, 0x59, 0xF0, 0x04, 0x86, 0x58, 
+	0x85, 0x5C, 0x20, 0x23, 0x3A, 0xA5, 0x07, 0xF0, 
+	0x0F, 0xA5, 0x0A, 0x85, 0x0B, 0xA5, 0x08, 0x09, 
+	0x10, 0x8D, 0x06, 0x44, 0x64, 0x02, 0x64, 0x07, 
+	0xA5, 0x00, 0xE5, 0x01, 0xC9, 0xC8, 0xA5, 0x09, 
+	0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 
+	0x44, 0xA5, 0x06, 0xF0, 0x08, 0xA5, 0x03, 0x85, 
+	0x04, 0x64, 0x02, 0x64, 0x06, 0x20, 0x23, 0x3A, 
+	0xA5, 0x13, 0xF0, 0x0F, 0xA5, 0x16, 0x85, 0x17, 
+	0xA5, 0x14, 0x09, 0x10, 0x8D, 0x06, 0x4C, 0x64, 
+	0x0E, 0x64, 0x13, 0xA5, 0x0C, 0xE5, 0x0D, 0xC9, 
+	0xC8, 0xA5, 0x15, 0x29, 0xF3, 0xB0, 0x02, 0x09, 
+	0x08, 0x8D, 0x04, 0x4C, 0xA5, 0x12, 0xF0, 0x08, 
+	0xA5, 0x0F, 0x85, 0x10, 0x64, 0x0E, 0x64, 0x12, 
+	0x20, 0x23, 0x3A, 0xA5, 0x1F, 0xF0, 0x0F, 0xA5, 
+	0x22, 0x85, 0x23, 0xA5, 0x20, 0x09, 0x10, 0x8D, 
+	0x06, 0x54, 0x64, 0x1A, 0x64, 0x1F, 0xA5, 0x18, 
+	0xE5, 0x19, 0xC9, 0xC8, 0xA5, 0x21, 0x29, 0xF3, 
+	0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x54, 0xA5, 
+	0x1E, 0xF0, 0x08, 0xA5, 0x1B, 0x85, 0x1C, 0x64, 
+	0x1A, 0x64, 0x1E, 0x20, 0x23, 0x3A, 0xA5, 0x2B, 
+	0xF0, 0x0F, 0xA5, 0x2E, 0x85, 0x2F, 0xA5, 0x2C, 
+	0x09, 0x10, 0x8D, 0x06, 0x5C, 0x64, 0x26, 0x64, 
+	0x2B, 0xA5, 0x24, 0xE5, 0x25, 0xC9, 0xC8, 0xA5, 
+	0x2D, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 
+	0x04, 0x5C, 0xA5, 0x2A, 0xF0, 0x08, 0xA5, 0x27, 
+	0x85, 0x28, 0x64, 0x26, 0x64, 0x2A, 0x20, 0x23, 
+	0x3A, 0xA5, 0x37, 0xF0, 0x0F, 0xA5, 0x3A, 0x85, 
+	0x3B, 0xA5, 0x38, 0x09, 0x10, 0x8D, 0x06, 0x64, 
+	0x64, 0x32, 0x64, 0x37, 0xA5, 0x30, 0xE5, 0x31, 
+	0xC9, 0xC8, 0xA5, 0x39, 0x29, 0xF3, 0xB0, 0x02, 
+	0x09, 0x08, 0x8D, 0x04, 0x64, 0xA5, 0x36, 0xF0, 
+	0x08, 0xA5, 0x33, 0x85, 0x34, 0x64, 0x32, 0x64, 
+	0x36, 0x20, 0x23, 0x3A, 0xA5, 0x43, 0xF0, 0x0F, 
+	0xA5, 0x46, 0x85, 0x47, 0xA5, 0x44, 0x09, 0x10, 
+	0x8D, 0x06, 0x6C, 0x64, 0x3E, 0x64, 0x43, 0xA5, 
+	0x3C, 0xE5, 0x3D, 0xC9, 0xC8, 0xA5, 0x45, 0x29, 
+	0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x6C, 
+	0xA5, 0x42, 0xF0, 0x08, 0xA5, 0x3F, 0x85, 0x40, 
+	0x64, 0x3E, 0x64, 0x42, 0x20, 0x23, 0x3A, 0xA5, 
+	0x4F, 0xF0, 0x0F, 0xA5, 0x52, 0x85, 0x53, 0xA5, 
+	0x50, 0x09, 0x10, 0x8D, 0x06, 0x74, 0x64, 0x4A, 
+	0x64, 0x4F, 0xA5, 0x48, 0xE5, 0x49, 0xC9, 0xC8, 
+	0xA5, 0x51, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 
+	0x8D, 0x04, 0x74, 0xA5, 0x4E, 0xF0, 0x08, 0xA5, 
+	0x4B, 0x85, 0x4C, 0x64, 0x4A, 0x64, 0x4E, 0x20, 
+	0x23, 0x3A, 0x4C, 0x92, 0x38, 0xAD, 0x02, 0x44, 
+	0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 
+	0xAD, 0x00, 0x44, 0xD0, 0x32, 0xA6, 0x00, 0xA9, 
+	0x01, 0x9D, 0x00, 0x10, 0xA9, 0x01, 0x9D, 0x00, 
+	0x09, 0xE8, 0xE4, 0x01, 0xF0, 0x02, 0x86, 0x00, 
+	0x4C, 0x65, 0x3A, 0xA6, 0x00, 0xAD, 0x00, 0x44, 
+	0x9D, 0x00, 0x09, 0x9E, 0x00, 0x10, 0xE8, 0xE4, 
+	0x01, 0xF0, 0x02, 0x86, 0x00, 0x29, 0x7F, 0xC9, 
+	0x13, 0xD0, 0x04, 0xA5, 0x0B, 0x85, 0x02, 0xAD, 
+	0x02, 0x44, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x05, 
+	0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 0xD0, 
+	0x21, 0x8E, 0x00, 0x44, 0x64, 0x05, 0x4C, 0x98, 
+	0x3A, 0xA6, 0x04, 0xE4, 0x03, 0xF0, 0x13, 0xA5, 
+	0x02, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 
+	0xD0, 0x08, 0xBD, 0x00, 0x02, 0x8D, 0x00, 0x44, 
+	0xE6, 0x04, 0xAD, 0x02, 0x4C, 0x89, 0x08, 0xF0, 
+	0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x4C, 
+	0xD0, 0x32, 0xA6, 0x0C, 0xA9, 0x01, 0x9D, 0x00, 
+	0x11, 0xA9, 0x01, 0x9D, 0x00, 0x0A, 0xE8, 0xE4, 
+	0x0D, 0xF0, 0x02, 0x86, 0x0C, 0x4C, 0xDA, 0x3A, 
+	0xA6, 0x0C, 0xAD, 0x00, 0x4C, 0x9D, 0x00, 0x0A, 
+	0x9E, 0x00, 0x11, 0xE8, 0xE4, 0x0D, 0xF0, 0x02, 
+	0x86, 0x0C, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 
+	0xA5, 0x17, 0x85, 0x0E, 0xAD, 0x02, 0x4C, 0x29, 
+	0x10, 0xF0, 0x2C, 0xA6, 0x11, 0xF0, 0x0F, 0xAD, 
+	0x02, 0x7C, 0x29, 0x02, 0xD0, 0x21, 0x8E, 0x00, 
+	0x4C, 0x64, 0x11, 0x4C, 0x0D, 0x3B, 0xA6, 0x10, 
+	0xE4, 0x0F, 0xF0, 0x13, 0xA5, 0x0E, 0xD0, 0x0F, 
+	0xAD, 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x08, 0xBD, 
+	0x00, 0x03, 0x8D, 0x00, 0x4C, 0xE6, 0x10, 0xAD, 
+	0x02, 0x54, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 
+	0xF0, 0x1B, 0xAD, 0x00, 0x54, 0xD0, 0x32, 0xA6, 
+	0x18, 0xA9, 0x01, 0x9D, 0x00, 0x12, 0xA9, 0x01, 
+	0x9D, 0x00, 0x0B, 0xE8, 0xE4, 0x19, 0xF0, 0x02, 
+	0x86, 0x18, 0x4C, 0x4F, 0x3B, 0xA6, 0x18, 0xAD, 
+	0x00, 0x54, 0x9D, 0x00, 0x0B, 0x9E, 0x00, 0x12, 
+	0xE8, 0xE4, 0x19, 0xF0, 0x02, 0x86, 0x18, 0x29, 
+	0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x23, 0x85, 
+	0x1A, 0xAD, 0x02, 0x54, 0x29, 0x10, 0xF0, 0x2C, 
+	0xA6, 0x1D, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
+	0x04, 0xD0, 0x21, 0x8E, 0x00, 0x54, 0x64, 0x1D, 
+	0x4C, 0x82, 0x3B, 0xA6, 0x1C, 0xE4, 0x1B, 0xF0, 
+	0x13, 0xA5, 0x1A, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 
+	0x29, 0x04, 0xD0, 0x08, 0xBD, 0x00, 0x04, 0x8D, 
+	0x00, 0x54, 0xE6, 0x1C, 0xAD, 0x02, 0x5C, 0x89, 
+	0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 
+	0x00, 0x5C, 0xD0, 0x32, 0xA6, 0x24, 0xA9, 0x01, 
+	0x9D, 0x00, 0x13, 0xA9, 0x01, 0x9D, 0x00, 0x0C, 
+	0xE8, 0xE4, 0x25, 0xF0, 0x02, 0x86, 0x24, 0x4C, 
+	0xC4, 0x3B, 0xA6, 0x24, 0xAD, 0x00, 0x5C, 0x9D, 
+	0x00, 0x0C, 0x9E, 0x00, 0x13, 0xE8, 0xE4, 0x25, 
+	0xF0, 0x02, 0x86, 0x24, 0x29, 0x7F, 0xC9, 0x13, 
+	0xD0, 0x04, 0xA5, 0x2F, 0x85, 0x26, 0xAD, 0x02, 
+	0x5C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x29, 0xF0, 
+	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 0x21, 
+	0x8E, 0x00, 0x5C, 0x64, 0x29, 0x4C, 0xF7, 0x3B, 
+	0xA6, 0x28, 0xE4, 0x27, 0xF0, 0x13, 0xA5, 0x26, 
+	0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 
+	0x08, 0xBD, 0x00, 0x05, 0x8D, 0x00, 0x5C, 0xE6, 
+	0x28, 0xAD, 0x02, 0x64, 0x89, 0x08, 0xF0, 0x3B, 
+	0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x64, 0xD0, 
+	0x32, 0xA6, 0x30, 0xA9, 0x01, 0x9D, 0x00, 0x14, 
+	0xA9, 0x01, 0x9D, 0x00, 0x0D, 0xE8, 0xE4, 0x31, 
+	0xF0, 0x02, 0x86, 0x30, 0x4C, 0x39, 0x3C, 0xA6, 
+	0x30, 0xAD, 0x00, 0x64, 0x9D, 0x00, 0x0D, 0x9E, 
+	0x00, 0x14, 0xE8, 0xE4, 0x31, 0xF0, 0x02, 0x86, 
+	0x30, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 
+	0x3B, 0x85, 0x32, 0xAD, 0x02, 0x64, 0x29, 0x10, 
+	0xF0, 0x2C, 0xA6, 0x35, 0xF0, 0x0F, 0xAD, 0x02, 
+	0x7C, 0x29, 0x10, 0xD0, 0x21, 0x8E, 0x00, 0x64, 
+	0x64, 0x35, 0x4C, 0x6C, 0x3C, 0xA6, 0x34, 0xE4, 
+	0x33, 0xF0, 0x13, 0xA5, 0x32, 0xD0, 0x0F, 0xAD, 
+	0x02, 0x7C, 0x29, 0x10, 0xD0, 0x08, 0xBD, 0x00, 
+	0x06, 0x8D, 0x00, 0x64, 0xE6, 0x34, 0xAD, 0x02, 
+	0x6C, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 
+	0x1B, 0xAD, 0x00, 0x6C, 0xD0, 0x32, 0xA6, 0x3C, 
+	0xA9, 0x01, 0x9D, 0x00, 0x15, 0xA9, 0x01, 0x9D, 
+	0x00, 0x0E, 0xE8, 0xE4, 0x3D, 0xF0, 0x02, 0x86, 
+	0x3C, 0x4C, 0xAE, 0x3C, 0xA6, 0x3C, 0xAD, 0x00, 
+	0x6C, 0x9D, 0x00, 0x0E, 0x9E, 0x00, 0x15, 0xE8, 
+	0xE4, 0x3D, 0xF0, 0x02, 0x86, 0x3C, 0x29, 0x7F, 
+	0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x47, 0x85, 0x3E, 
+	0xAD, 0x02, 0x6C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 
+	0x41, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x20, 
+	0xD0, 0x21, 0x8E, 0x00, 0x6C, 0x64, 0x41, 0x4C, 
+	0xE1, 0x3C, 0xA6, 0x40, 0xE4, 0x3F, 0xF0, 0x13, 
+	0xA5, 0x3E, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
+	0x20, 0xD0, 0x08, 0xBD, 0x00, 0x07, 0x8D, 0x00, 
+	0x6C, 0xE6, 0x40, 0xAD, 0x02, 0x74, 0x89, 0x08, 
+	0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 
+	0x74, 0xD0, 0x32, 0xA6, 0x48, 0xA9, 0x01, 0x9D, 
+	0x00, 0x16, 0xA9, 0x01, 0x9D, 0x00, 0x0F, 0xE8, 
+	0xE4, 0x49, 0xF0, 0x02, 0x86, 0x48, 0x4C, 0x23, 
+	0x3D, 0xA6, 0x48, 0xAD, 0x00, 0x74, 0x9D, 0x00, 
+	0x0F, 0x9E, 0x00, 0x16, 0xE8, 0xE4, 0x49, 0xF0, 
+	0x02, 0x86, 0x48, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 
+	0x04, 0xA5, 0x53, 0x85, 0x4A, 0xAD, 0x02, 0x74, 
+	0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x4D, 0xF0, 0x0F, 
+	0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x21, 0x8E, 
+	0x00, 0x74, 0x64, 0x4D, 0x4C, 0x56, 0x3D, 0xA6, 
+	0x4C, 0xE4, 0x4B, 0xF0, 0x13, 0xA5, 0x4A, 0xD0, 
+	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x08, 
+	0xBD, 0x00, 0x08, 0x8D, 0x00, 0x74, 0xE6, 0x4C, 
+	0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
+	0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xD0, 0x00, 0x38, 
+	0xCE, 0xC0, 
+};
diff --git a/drivers/staging/generic_serial/sx.c b/drivers/staging/generic_serial/sx.c
new file mode 100644
index 0000000..1291462
--- /dev/null
+++ b/drivers/staging/generic_serial/sx.c
@@ -0,0 +1,2894 @@
+/* sx.c -- driver for the Specialix SX series cards. 
+ *
+ *  This driver will also support the older SI, and XIO cards.
+ *
+ *
+ *   (C) 1998 - 2004  R.E.Wolff@BitWizard.nl
+ *
+ *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
+ *  version of this driver. Some fragments may have been copied. (none
+ *  yet :-)
+ *
+ * Specialix pays for the development and support of this driver.
+ * Please DO contact support@specialix.co.uk if you require
+ * support. But please read the documentation (sx.txt) first.
+ *
+ *
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be
+ *      useful, but WITHOUT ANY WARRANTY; without even the implied
+ *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *      PURPOSE.  See the GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public
+ *      License along with this program; if not, write to the Free
+ *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ *      USA.
+ *
+ * Revision history:
+ * Revision 1.33  2000/03/09 10:00:00  pvdl,wolff
+ * - Fixed module and port counting
+ * - Fixed signal handling
+ * - Fixed an Ooops
+ * 
+ * Revision 1.32  2000/03/07 09:00:00  wolff,pvdl
+ * - Fixed some sx_dprintk typos
+ * - added detection for an invalid board/module configuration
+ *
+ * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
+ * - Added support for EISA
+ *
+ * Revision 1.30  2000/01/21 17:43:06  wolff
+ * - Added support for SX+
+ *
+ * Revision 1.26  1999/08/05 15:22:14  wolff
+ * - Port to 2.3.x
+ * - Reformatted to Linus' liking.
+ *
+ * Revision 1.25  1999/07/30 14:24:08  wolff
+ * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
+ *
+ * Revision 1.24  1999/07/28 09:41:52  wolff
+ * - I noticed the remark about use-count straying in sx.txt. I checked
+ *   sx_open, and found a few places where that could happen. I hope it's
+ *   fixed now.
+ *
+ * Revision 1.23  1999/07/28 08:56:06  wolff
+ * - Fixed crash when sx_firmware run twice.
+ * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
+ *   to change it from the default... )
+ * - Fixed a stupid editing problem I introduced in 1.22.
+ * - Fixed dropping characters on a termios change.
+ *
+ * Revision 1.22  1999/07/26 21:01:43  wolff
+ * Russell Brown noticed that I had overlooked 4 out of six modem control
+ * signals in sx_getsignals. Ooops.
+ *
+ * Revision 1.21  1999/07/23 09:11:33  wolff
+ * I forgot to free dynamically allocated memory when the driver is unloaded.
+ *
+ * Revision 1.20  1999/07/20 06:25:26  wolff
+ * The "closing wait" wasn't honoured. Thanks to James Griffiths for
+ * reporting this.
+ *
+ * Revision 1.19  1999/07/11 08:59:59  wolff
+ * Fixed an oops in close, when an open was pending. Changed the memtest
+ * a bit. Should also test the board in word-mode, however my card fails the
+ * memtest then. I still have to figure out what is wrong...
+ *
+ * Revision 1.18  1999/06/10 09:38:42  wolff
+ * Changed the format of the firmware revision from %04x to %x.%02x .
+ *
+ * Revision 1.17  1999/06/04 09:44:35  wolff
+ * fixed problem: reference to pci stuff when config_pci was off...
+ * Thanks to Jorge Novo for noticing this.
+ *
+ * Revision 1.16  1999/06/02 08:30:15  wolff
+ * added/removed the workaround for the DCD bug in the Firmware.
+ * A bit more debugging code to locate that...
+ *
+ * Revision 1.15  1999/06/01 11:35:30  wolff
+ * when DCD is left low (floating?), on TA's the firmware first tells us
+ * that DCD is high, but after a short while suddenly comes to the
+ * conclusion that it is low. All this would be fine, if it weren't that
+ * Unix requires us to send a "hangup" signal in that case. This usually
+ * all happens BEFORE the program has had a chance to ioctl the device
+ * into clocal mode..
+ *
+ * Revision 1.14  1999/05/25 11:18:59  wolff
+ * Added PCI-fix.
+ * Added checks for return code of sx_sendcommand.
+ * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
+ *
+ * Revision 1.13  1999/04/29 15:18:01  wolff
+ * Fixed an "oops" that showed on SuSE 6.0 systems.
+ * Activate DTR again after stty 0.
+ *
+ * Revision 1.12  1999/04/29 07:49:52  wolff
+ * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
+ *     the connection would be dropped anyway. That is not always the case,
+ *     and confuses people).
+ * Told the card to always monitor the modem signals.
+ * Added support for dynamic  gs_debug adjustments.
+ * Now tells the rest of the system the number of ports.
+ *
+ * Revision 1.11  1999/04/24 11:11:30  wolff
+ * Fixed two stupid typos in the memory test.
+ *
+ * Revision 1.10  1999/04/24 10:53:39  wolff
+ * Added some of Christian's suggestions.
+ * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
+ * card to send the signal to the process.....)
+ *
+ * Revision 1.9  1999/04/23 07:26:38  wolff
+ * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
+ *    assignment redesign.
+ * Cleanup of some other stuff.
+ *
+ * Revision 1.8  1999/04/16 13:05:30  wolff
+ * fixed a DCD change unnoticed bug.
+ *
+ * Revision 1.7  1999/04/14 22:19:51  wolff
+ * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
+ *
+ * Revision 1.6  1999/04/13 18:40:20  wolff
+ * changed misc-minor to 161, as assigned by HPA.
+ *
+ * Revision 1.5  1999/04/13 15:12:25  wolff
+ * Fixed use-count leak when "hangup" occurred.
+ * Added workaround for a stupid-PCIBIOS bug.
+ *
+ *
+ * Revision 1.4  1999/04/01 22:47:40  wolff
+ * Fixed < 1M linux-2.0 problem.
+ * (vremap isn't compatible with ioremap in that case)
+ *
+ * Revision 1.3  1999/03/31 13:45:45  wolff
+ * Firmware loading is now done through a separate IOCTL.
+ *
+ * Revision 1.2  1999/03/28 12:22:29  wolff
+ * rcs cleanup
+ *
+ * Revision 1.1  1999/03/28 12:10:34  wolff
+ * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). 
+ *
+ * Revision 0.12  1999/03/28 09:20:10  wolff
+ * Fixed problem in 0.11, continueing cleanup.
+ *
+ * Revision 0.11  1999/03/28 08:46:44  wolff
+ * cleanup. Not good.
+ *
+ * Revision 0.10  1999/03/28 08:09:43  wolff
+ * Fixed loosing characters on close.
+ *
+ * Revision 0.9  1999/03/21 22:52:01  wolff
+ * Ported back to 2.2.... (minor things)
+ *
+ * Revision 0.8  1999/03/21 22:40:33  wolff
+ * Port to 2.0
+ *
+ * Revision 0.7  1999/03/21 19:06:34  wolff
+ * Fixed hangup processing.
+ *
+ * Revision 0.6  1999/02/05 08:45:14  wolff
+ * fixed real_raw problems. Inclusion into kernel imminent.
+ *
+ * Revision 0.5  1998/12/21 23:51:06  wolff
+ * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
+ * shouldn't have. THATs why I want to have transmit interrupts even when
+ * the buffer is empty.
+ *
+ * Revision 0.4  1998/12/17 09:34:46  wolff
+ * PPP works. ioctl works. Basically works!
+ *
+ * Revision 0.3  1998/12/15 13:05:18  wolff
+ * It works! Wow! Gotta start implementing IOCTL and stuff....
+ *
+ * Revision 0.2  1998/12/01 08:33:53  wolff
+ * moved over to 2.1.130
+ *
+ * Revision 0.1  1998/11/03 21:23:51  wolff
+ * Initial revision. Detects SX card.
+ *
+ * */
+
+#define SX_VERSION	1.33
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/eisa.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+/* The 3.0.0 version of sxboards/sxwindow.h  uses BYTE and WORD.... */
+#define BYTE u8
+#define WORD u16
+
+/* .... but the 3.0.4 version uses _u8 and _u16. */
+#define _u8 u8
+#define _u16 u16
+
+#include "sxboards.h"
+#include "sxwindow.h"
+
+#include <linux/generic_serial.h>
+#include "sx.h"
+
+/* I don't think that this driver can handle more than 256 ports on
+   one machine. You'll have to increase the number of boards in sx.h
+   if you want more than 4 boards.  */
+
+#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
+#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
+#endif
+
+/* Configurable options: 
+   (Don't be too sure that it'll work if you toggle them) */
+
+/* Am I paranoid or not ? ;-) */
+#undef SX_PARANOIA_CHECK
+
+/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
+   Hz, but it is user configurable. I don't recommend going above 1000
+   Hz. The interrupt ratelimit might trigger if the interrupt is
+   shared with a very active other device. */
+#define IRQ_RATE_LIMIT 20
+
+/* Sharing interrupts is possible now. If the other device wants more
+   than 2000 interrupts per second, we'd gracefully decline further
+   interrupts. That's not what we want. On the other hand, if the
+   other device interrupts 2000 times a second, don't use the SX
+   interrupt. Use polling. */
+#undef IRQ_RATE_LIMIT
+
+#if 0
+/* Not implemented */
+/* 
+ * The following defines are mostly for testing purposes. But if you need
+ * some nice reporting in your syslog, you can define them also.
+ */
+#define SX_REPORT_FIFO
+#define SX_REPORT_OVERRUN
+#endif
+
+/* Function prototypes */
+static void sx_disable_tx_interrupts(void *ptr);
+static void sx_enable_tx_interrupts(void *ptr);
+static void sx_disable_rx_interrupts(void *ptr);
+static void sx_enable_rx_interrupts(void *ptr);
+static int sx_carrier_raised(struct tty_port *port);
+static void sx_shutdown_port(void *ptr);
+static int sx_set_real_termios(void *ptr);
+static void sx_close(void *ptr);
+static int sx_chars_in_buffer(void *ptr);
+static int sx_init_board(struct sx_board *board);
+static int sx_init_portstructs(int nboards, int nports);
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+						unsigned long arg);
+static int sx_init_drivers(void);
+
+static struct tty_driver *sx_driver;
+
+static DEFINE_MUTEX(sx_boards_lock);
+static struct sx_board boards[SX_NBOARDS];
+static struct sx_port *sx_ports;
+static int sx_initialized;
+static int sx_nports;
+static int sx_debug;
+
+/* You can have the driver poll your card. 
+    - Set sx_poll to 1 to poll every timer tick (10ms on Intel). 
+      This is used when the card cannot use an interrupt for some reason.
+
+    - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If 
+      the driver misses an interrupt (report this if it DOES happen to you!)
+      everything will continue to work.... 
+ */
+static int sx_poll = 1;
+static int sx_slowpoll;
+
+/* The card limits the number of interrupts per second. 
+   At 115k2 "100" should be sufficient. 
+   If you're using higher baudrates, you can increase this...
+ */
+
+static int sx_maxints = 100;
+
+#ifdef CONFIG_ISA
+
+/* These are the only open spaces in my computer. Yours may have more
+   or less.... -- REW 
+   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
+*/
+static int sx_probe_addrs[] = {
+	0xc0000, 0xd0000, 0xe0000,
+	0xc8000, 0xd8000, 0xe8000
+};
+static int si_probe_addrs[] = {
+	0xc0000, 0xd0000, 0xe0000,
+	0xc8000, 0xd8000, 0xe8000, 0xa0000
+};
+static int si1_probe_addrs[] = {
+	0xd0000
+};
+
+#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
+#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
+#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
+
+module_param_array(sx_probe_addrs, int, NULL, 0);
+module_param_array(si_probe_addrs, int, NULL, 0);
+#endif
+
+/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
+   Some architectures may need more. */
+static int sx_irqmask = -1;
+
+module_param(sx_poll, int, 0);
+module_param(sx_slowpoll, int, 0);
+module_param(sx_maxints, int, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_irqmask, int, 0);
+
+MODULE_LICENSE("GPL");
+
+static struct real_driver sx_real_driver = {
+	sx_disable_tx_interrupts,
+	sx_enable_tx_interrupts,
+	sx_disable_rx_interrupts,
+	sx_enable_rx_interrupts,
+	sx_shutdown_port,
+	sx_set_real_termios,
+	sx_chars_in_buffer,
+	sx_close,
+};
+
+/* 
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile... 
+*/
+#define DEBUG
+
+#ifdef DEBUG
+#define sx_dprintk(f, str...)	if (sx_debug & f) printk (str)
+#else
+#define sx_dprintk(f, str...)	/* nothing */
+#endif
+
+#define func_enter()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
+#define func_exit()	sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__func__)
+
+#define func_enter2()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
+				__func__, port->line)
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static const struct file_operations sx_fw_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = sx_fw_ioctl,
+	.llseek = noop_llseek,
+};
+
+static struct miscdevice sx_fw_device = {
+	SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
+};
+
+#ifdef SX_PARANOIA_CHECK
+
+/* This doesn't work. Who's paranoid around here? Not me! */
+
+static inline int sx_paranoia_check(struct sx_port const *port,
+				    char *name, const char *routine)
+{
+	static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
+			"number for device %s in %s\n";
+	static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
+			"device %s in %s\n";
+
+	if (!port) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (port->magic != SX_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+
+	return 0;
+}
+#else
+#define sx_paranoia_check(a,b,c) 0
+#endif
+
+/* The timeouts. First try 30 times as fast as possible. Then give
+   the card some time to breathe between accesses. (Otherwise the
+   processor on the card might not be able to access its OWN bus... */
+
+#define TIMEOUT_1 30
+#define TIMEOUT_2 1000000
+
+#ifdef DEBUG
+static void my_hd_io(void __iomem *p, int len)
+{
+	int i, j, ch;
+	unsigned char __iomem *addr = p;
+
+	for (i = 0; i < len; i += 16) {
+		printk("%p ", addr + i);
+		for (j = 0; j < 16; j++) {
+			printk("%02x %s", readb(addr + j + i),
+					(j == 7) ? " " : "");
+		}
+		for (j = 0; j < 16; j++) {
+			ch = readb(addr + j + i);
+			printk("%c", (ch < 0x20) ? '.' :
+					((ch > 0x7f) ? '.' : ch));
+		}
+		printk("\n");
+	}
+}
+static void my_hd(void *p, int len)
+{
+	int i, j, ch;
+	unsigned char *addr = p;
+
+	for (i = 0; i < len; i += 16) {
+		printk("%p ", addr + i);
+		for (j = 0; j < 16; j++) {
+			printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
+		}
+		for (j = 0; j < 16; j++) {
+			ch = addr[j + i];
+			printk("%c", (ch < 0x20) ? '.' :
+					((ch > 0x7f) ? '.' : ch));
+		}
+		printk("\n");
+	}
+}
+#endif
+
+/* This needs redoing for Alpha -- REW -- Done. */
+
+static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
+{
+	writeb(byte, board->base + offset);
+}
+
+static inline u8 read_sx_byte(struct sx_board *board, int offset)
+{
+	return readb(board->base + offset);
+}
+
+static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
+{
+	writew(word, board->base + offset);
+}
+
+static inline u16 read_sx_word(struct sx_board *board, int offset)
+{
+	return readw(board->base + offset);
+}
+
+static int sx_busy_wait_eq(struct sx_board *board,
+		int offset, int mask, int correctval)
+{
+	int i;
+
+	func_enter();
+
+	for (i = 0; i < TIMEOUT_1; i++)
+		if ((read_sx_byte(board, offset) & mask) == correctval) {
+			func_exit();
+			return 1;
+		}
+
+	for (i = 0; i < TIMEOUT_2; i++) {
+		if ((read_sx_byte(board, offset) & mask) == correctval) {
+			func_exit();
+			return 1;
+		}
+		udelay(1);
+	}
+
+	func_exit();
+	return 0;
+}
+
+static int sx_busy_wait_neq(struct sx_board *board,
+		int offset, int mask, int badval)
+{
+	int i;
+
+	func_enter();
+
+	for (i = 0; i < TIMEOUT_1; i++)
+		if ((read_sx_byte(board, offset) & mask) != badval) {
+			func_exit();
+			return 1;
+		}
+
+	for (i = 0; i < TIMEOUT_2; i++) {
+		if ((read_sx_byte(board, offset) & mask) != badval) {
+			func_exit();
+			return 1;
+		}
+		udelay(1);
+	}
+
+	func_exit();
+	return 0;
+}
+
+/* 5.6.4 of 6210028 r2.3 */
+static int sx_reset(struct sx_board *board)
+{
+	func_enter();
+
+	if (IS_SX_BOARD(board)) {
+
+		write_sx_byte(board, SX_CONFIG, 0);
+		write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
+
+		if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
+			printk(KERN_INFO "sx: Card doesn't respond to "
+					"reset...\n");
+			return 0;
+		}
+	} else if (IS_EISA_BOARD(board)) {
+		outb(board->irq << 4, board->eisa_base + 0xc02);
+	} else if (IS_SI1_BOARD(board)) {
+		write_sx_byte(board, SI1_ISA_RESET, 0);	/*value doesn't matter*/
+	} else {
+		/* Gory details of the SI/ISA board */
+		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
+		write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
+		write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
+		write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
+		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
+		write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
+	}
+
+	func_exit();
+	return 1;
+}
+
+/* This doesn't work on machines where "NULL" isn't 0 */
+/* If you have one of those, someone will need to write 
+   the equivalent of this, which will amount to about 3 lines. I don't
+   want to complicate this right now. -- REW
+   (See, I do write comments every now and then :-) */
+#define OFFSETOF(strct, elem)	((long)&(((struct strct *)NULL)->elem))
+
+#define CHAN_OFFSET(port,elem)	(port->ch_base + OFFSETOF (_SXCHANNEL, elem))
+#define MODU_OFFSET(board,addr,elem)	(addr + OFFSETOF (_SXMODULE, elem))
+#define  BRD_OFFSET(board,elem)	(OFFSETOF (_SXCARD, elem))
+
+#define sx_write_channel_byte(port, elem, val) \
+	write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
+
+#define sx_read_channel_byte(port, elem) \
+	read_sx_byte (port->board, CHAN_OFFSET (port, elem))
+
+#define sx_write_channel_word(port, elem, val) \
+	write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
+
+#define sx_read_channel_word(port, elem) \
+	read_sx_word (port->board, CHAN_OFFSET (port, elem))
+
+#define sx_write_module_byte(board, addr, elem, val) \
+	write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
+
+#define sx_read_module_byte(board, addr, elem) \
+	read_sx_byte (board, MODU_OFFSET (board, addr, elem))
+
+#define sx_write_module_word(board, addr, elem, val) \
+	write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
+
+#define sx_read_module_word(board, addr, elem) \
+	read_sx_word (board, MODU_OFFSET (board, addr, elem))
+
+#define sx_write_board_byte(board, elem, val) \
+	write_sx_byte (board, BRD_OFFSET (board, elem), val)
+
+#define sx_read_board_byte(board, elem) \
+	read_sx_byte (board, BRD_OFFSET (board, elem))
+
+#define sx_write_board_word(board, elem, val) \
+	write_sx_word (board, BRD_OFFSET (board, elem), val)
+
+#define sx_read_board_word(board, elem) \
+	read_sx_word (board, BRD_OFFSET (board, elem))
+
+static int sx_start_board(struct sx_board *board)
+{
+	if (IS_SX_BOARD(board)) {
+		write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
+	} else if (IS_EISA_BOARD(board)) {
+		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
+		outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
+	} else if (IS_SI1_BOARD(board)) {
+		write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
+		write_sx_byte(board, SI1_ISA_INTCL, 0);
+	} else {
+		/* Don't bug me about the clear_set. 
+		   I haven't the foggiest idea what it's about -- REW */
+		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
+		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+	}
+	return 1;
+}
+
+#define SX_IRQ_REG_VAL(board) \
+	((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
+
+/* Note. The SX register is write-only. Therefore, we have to enable the
+   bus too. This is a no-op, if you don't mess with this driver... */
+static int sx_start_interrupts(struct sx_board *board)
+{
+
+	/* Don't call this with board->irq == 0 */
+
+	if (IS_SX_BOARD(board)) {
+		write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
+				SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
+	} else if (IS_EISA_BOARD(board)) {
+		inb(board->eisa_base + 0xc03);
+	} else if (IS_SI1_BOARD(board)) {
+		write_sx_byte(board, SI1_ISA_INTCL, 0);
+		write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
+	} else {
+		switch (board->irq) {
+		case 11:
+			write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
+			break;
+		case 12:
+			write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
+			break;
+		case 15:
+			write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
+			break;
+		default:
+			printk(KERN_INFO "sx: SI/XIO card doesn't support "
+					"interrupt %d.\n", board->irq);
+			return 0;
+		}
+		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
+	}
+
+	return 1;
+}
+
+static int sx_send_command(struct sx_port *port,
+		int command, int mask, int newstat)
+{
+	func_enter2();
+	write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
+	func_exit();
+	return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
+			newstat);
+}
+
+static char *mod_type_s(int module_type)
+{
+	switch (module_type) {
+	case TA4:
+		return "TA4";
+	case TA8:
+		return "TA8";
+	case TA4_ASIC:
+		return "TA4_ASIC";
+	case TA8_ASIC:
+		return "TA8_ASIC";
+	case MTA_CD1400:
+		return "MTA_CD1400";
+	case SXDC:
+		return "SXDC";
+	default:
+		return "Unknown/invalid";
+	}
+}
+
+static char *pan_type_s(int pan_type)
+{
+	switch (pan_type) {
+	case MOD_RS232DB25:
+		return "MOD_RS232DB25";
+	case MOD_RS232RJ45:
+		return "MOD_RS232RJ45";
+	case MOD_RS422DB25:
+		return "MOD_RS422DB25";
+	case MOD_PARALLEL:
+		return "MOD_PARALLEL";
+	case MOD_2_RS232DB25:
+		return "MOD_2_RS232DB25";
+	case MOD_2_RS232RJ45:
+		return "MOD_2_RS232RJ45";
+	case MOD_2_RS422DB25:
+		return "MOD_2_RS422DB25";
+	case MOD_RS232DB25MALE:
+		return "MOD_RS232DB25MALE";
+	case MOD_2_PARALLEL:
+		return "MOD_2_PARALLEL";
+	case MOD_BLANK:
+		return "empty";
+	default:
+		return "invalid";
+	}
+}
+
+static int mod_compat_type(int module_type)
+{
+	return module_type >> 4;
+}
+
+static void sx_reconfigure_port(struct sx_port *port)
+{
+	if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
+		if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
+			printk(KERN_WARNING "sx: Sent reconfigure command, but "
+					"card didn't react.\n");
+		}
+	} else {
+		sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
+				"port isn't open (%02x).\n",
+				sx_read_channel_byte(port, hi_hstat));
+	}
+}
+
+static void sx_setsignals(struct sx_port *port, int dtr, int rts)
+{
+	int t;
+	func_enter2();
+
+	t = sx_read_channel_byte(port, hi_op);
+	if (dtr >= 0)
+		t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
+	if (rts >= 0)
+		t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
+	sx_write_channel_byte(port, hi_op, t);
+	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
+
+	func_exit();
+}
+
+static int sx_getsignals(struct sx_port *port)
+{
+	int i_stat, o_stat;
+
+	o_stat = sx_read_channel_byte(port, hi_op);
+	i_stat = sx_read_channel_byte(port, hi_ip);
+
+	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d  (%d/%d) "
+			"%02x/%02x\n",
+			(o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
+			port->c_dcd, tty_port_carrier_raised(&port->gs.port),
+			sx_read_channel_byte(port, hi_ip),
+			sx_read_channel_byte(port, hi_state));
+
+	return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
+		((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
+		((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
+		((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
+		((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
+		((i_stat & IP_RI) ? TIOCM_RNG : 0));
+}
+
+static void sx_set_baud(struct sx_port *port)
+{
+	int t;
+
+	if (port->board->ta_type == MOD_SXDC) {
+		switch (port->gs.baud) {
+			/* Save some typing work... */
+#define e(x) case x: t = BAUD_ ## x; break
+			e(50);
+			e(75);
+			e(110);
+			e(150);
+			e(200);
+			e(300);
+			e(600);
+			e(1200);
+			e(1800);
+			e(2000);
+			e(2400);
+			e(4800);
+			e(7200);
+			e(9600);
+			e(14400);
+			e(19200);
+			e(28800);
+			e(38400);
+			e(56000);
+			e(57600);
+			e(64000);
+			e(76800);
+			e(115200);
+			e(128000);
+			e(150000);
+			e(230400);
+			e(256000);
+			e(460800);
+			e(921600);
+		case 134:
+			t = BAUD_134_5;
+			break;
+		case 0:
+			t = -1;
+			break;
+		default:
+			/* Can I return "invalid"? */
+			t = BAUD_9600;
+			printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
+					port->gs.baud);
+			break;
+		}
+#undef e
+		if (t > 0) {
+/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
+			sx_setsignals(port, 1, -1);
+			/* XXX This is not TA & MTA compatible */
+			sx_write_channel_byte(port, hi_csr, 0xff);
+
+			sx_write_channel_byte(port, hi_txbaud, t);
+			sx_write_channel_byte(port, hi_rxbaud, t);
+		} else {
+			sx_setsignals(port, 0, -1);
+		}
+	} else {
+		switch (port->gs.baud) {
+#define e(x) case x: t = CSR_ ## x; break
+			e(75);
+			e(150);
+			e(300);
+			e(600);
+			e(1200);
+			e(2400);
+			e(4800);
+			e(1800);
+			e(9600);
+			e(19200);
+			e(57600);
+			e(38400);
+/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
+		case 110:
+			if (port->board->ta_type == MOD_TA) {
+				t = CSR_110;
+				break;
+			} else {
+				t = CSR_9600;
+				printk(KERN_INFO "sx: Unsupported baud rate: "
+						"%d.\n", port->gs.baud);
+				break;
+			}
+		case 115200:
+			if (port->board->ta_type == MOD_TA) {
+				t = CSR_9600;
+				printk(KERN_INFO "sx: Unsupported baud rate: "
+						"%d.\n", port->gs.baud);
+				break;
+			} else {
+				t = CSR_110;
+				break;
+			}
+		case 0:
+			t = -1;
+			break;
+		default:
+			t = CSR_9600;
+			printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
+					port->gs.baud);
+			break;
+		}
+#undef e
+		if (t >= 0) {
+			sx_setsignals(port, 1, -1);
+			sx_write_channel_byte(port, hi_csr, t * 0x11);
+		} else {
+			sx_setsignals(port, 0, -1);
+		}
+	}
+}
+
+/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
+   better. -- REW */
+
+static int sx_set_real_termios(void *ptr)
+{
+	struct sx_port *port = ptr;
+
+	func_enter2();
+
+	if (!port->gs.port.tty)
+		return 0;
+
+	/* What is this doing here? -- REW
+	   Ha! figured it out. It is to allow you to get DTR active again
+	   if you've dropped it with stty 0. Moved to set_baud, where it
+	   belongs (next to the drop dtr if baud == 0) -- REW */
+	/* sx_setsignals (port, 1, -1); */
+
+	sx_set_baud(port);
+
+#define CFLAG port->gs.port.tty->termios->c_cflag
+	sx_write_channel_byte(port, hi_mr1,
+			(C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
+			(C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
+			(C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
+			(((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
+			(((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
+			(((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
+			(((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
+
+	sx_write_channel_byte(port, hi_mr2,
+			(C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
+			(C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
+			MR2_1_STOP));
+
+	switch (CFLAG & CSIZE) {
+	case CS8:
+		sx_write_channel_byte(port, hi_mask, 0xff);
+		break;
+	case CS7:
+		sx_write_channel_byte(port, hi_mask, 0x7f);
+		break;
+	case CS6:
+		sx_write_channel_byte(port, hi_mask, 0x3f);
+		break;
+	case CS5:
+		sx_write_channel_byte(port, hi_mask, 0x1f);
+		break;
+	default:
+		printk(KERN_INFO "sx: Invalid wordsize: %u\n",
+			(unsigned int)CFLAG & CSIZE);
+		break;
+	}
+
+	sx_write_channel_byte(port, hi_prtcl,
+			(I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
+			(I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
+			(I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
+
+	sx_write_channel_byte(port, hi_break,
+			(I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
+			I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
+
+	sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
+	sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
+	sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
+	sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
+
+	sx_reconfigure_port(port);
+
+	/* Tell line discipline whether we will do input cooking */
+	if (I_OTHER(port->gs.port.tty)) {
+		clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
+	} else {
+		set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
+	}
+	sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
+			(unsigned int)port->gs.port.tty->termios->c_iflag,
+			I_OTHER(port->gs.port.tty));
+
+/* Tell line discipline whether we will do output cooking.
+ * If OPOST is set and no other output flags are set then we can do output
+ * processing.  Even if only *one* other flag in the O_OTHER group is set
+ * we do cooking in software.
+ */
+	if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
+		set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
+	} else {
+		clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
+	}
+	sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
+			(unsigned int)port->gs.port.tty->termios->c_oflag,
+			O_OTHER(port->gs.port.tty));
+	/* port->c_dcd = sx_get_CD (port); */
+	func_exit();
+	return 0;
+}
+
+/* ********************************************************************** *
+ *                   the interrupt related routines                       *
+ * ********************************************************************** */
+
+/* Note:
+   Other drivers use the macro "MIN" to calculate how much to copy.
+   This has the disadvantage that it will evaluate parts twice. That's
+   expensive when it's IO (and the compiler cannot optimize those away!).
+   Moreover, I'm not sure that you're race-free. 
+
+   I assign a value, and then only allow the value to decrease. This
+   is always safe. This makes the code a few lines longer, and you
+   know I'm dead against that, but I think it is required in this
+   case.  */
+
+static void sx_transmit_chars(struct sx_port *port)
+{
+	int c;
+	int tx_ip;
+	int txroom;
+
+	func_enter2();
+	sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
+			port, port->gs.xmit_cnt);
+
+	if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
+		return;
+	}
+
+	while (1) {
+		c = port->gs.xmit_cnt;
+
+		sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
+		tx_ip = sx_read_channel_byte(port, hi_txipos);
+
+		/* Took me 5 minutes to deduce this formula. 
+		   Luckily it is literally in the manual in section 6.5.4.3.5 */
+		txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
+				0xff;
+
+		/* Don't copy more bytes than there is room for in the buffer */
+		if (c > txroom)
+			c = txroom;
+		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
+
+		/* Don't copy past the end of the hardware transmit buffer */
+		if (c > 0x100 - tx_ip)
+			c = 0x100 - tx_ip;
+
+		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
+
+		/* Don't copy pas the end of the source buffer */
+		if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
+			c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
+
+		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
+				c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
+
+		/* If for one reason or another, we can't copy more data, we're
+		   done! */
+		if (c == 0)
+			break;
+
+		memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
+			tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
+
+		/* Update the pointer in the card */
+		sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
+
+		/* Update the kernel buffer end */
+		port->gs.xmit_tail = (port->gs.xmit_tail + c) &
+				(SERIAL_XMIT_SIZE - 1);
+
+		/* This one last. (this is essential)
+		   It would allow others to start putting more data into the
+		   buffer! */
+		port->gs.xmit_cnt -= c;
+	}
+
+	if (port->gs.xmit_cnt == 0) {
+		sx_disable_tx_interrupts(port);
+	}
+
+	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
+		tty_wakeup(port->gs.port.tty);
+		sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
+				port->gs.wakeup_chars);
+	}
+
+	clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
+	func_exit();
+}
+
+/* Note the symmetry between receiving chars and transmitting them!
+   Note: The kernel should have implemented both a receive buffer and
+   a transmit buffer. */
+
+/* Inlined: Called only once. Remove the inline when you add another call */
+static inline void sx_receive_chars(struct sx_port *port)
+{
+	int c;
+	int rx_op;
+	struct tty_struct *tty;
+	int copied = 0;
+	unsigned char *rp;
+
+	func_enter2();
+	tty = port->gs.port.tty;
+	while (1) {
+		rx_op = sx_read_channel_byte(port, hi_rxopos);
+		c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
+
+		sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
+
+		/* Don't copy past the end of the hardware receive buffer */
+		if (rx_op + c > 0x100)
+			c = 0x100 - rx_op;
+
+		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
+
+		/* Don't copy more bytes than there is room for in the buffer */
+
+		c = tty_prepare_flip_string(tty, &rp, c);
+
+		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
+
+		/* If for one reason or another, we can't copy more data, we're done! */
+		if (c == 0)
+			break;
+
+		sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
+				"%d at %lx\n", c, read_sx_byte(port->board,
+					CHAN_OFFSET(port, hi_rxbuf) + rx_op),
+				CHAN_OFFSET(port, hi_rxbuf));
+		memcpy_fromio(rp, port->board->base +
+				CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
+
+		/* This one last. ( Not essential.)
+		   It allows the card to start putting more data into the
+		   buffer!
+		   Update the pointer in the card */
+		sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
+
+		copied += c;
+	}
+	if (copied) {
+		struct timeval tv;
+
+		do_gettimeofday(&tv);
+		sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
+				"chars): %d.%06d  (%d/%d)\n", port->line,
+				copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
+				tty->raw, tty->real_raw);
+
+		/* Tell the rest of the system the news. Great news. New
+		   characters! */
+		tty_flip_buffer_push(tty);
+		/*    tty_schedule_flip (tty); */
+	}
+
+	func_exit();
+}
+
+/* Inlined: it is called only once. Remove the inline if you add another 
+   call */
+static inline void sx_check_modem_signals(struct sx_port *port)
+{
+	int hi_state;
+	int c_dcd;
+
+	hi_state = sx_read_channel_byte(port, hi_state);
+	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
+			port->c_dcd, tty_port_carrier_raised(&port->gs.port));
+
+	if (hi_state & ST_BREAK) {
+		hi_state &= ~ST_BREAK;
+		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
+		sx_write_channel_byte(port, hi_state, hi_state);
+		gs_got_break(&port->gs);
+	}
+	if (hi_state & ST_DCD) {
+		hi_state &= ~ST_DCD;
+		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
+		sx_write_channel_byte(port, hi_state, hi_state);
+		c_dcd = tty_port_carrier_raised(&port->gs.port);
+		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
+		if (c_dcd != port->c_dcd) {
+			port->c_dcd = c_dcd;
+			if (tty_port_carrier_raised(&port->gs.port)) {
+				/* DCD went UP */
+				if ((sx_read_channel_byte(port, hi_hstat) !=
+						HS_IDLE_CLOSED) &&
+						!(port->gs.port.tty->termios->
+							c_cflag & CLOCAL)) {
+					/* Are we blocking in open? */
+					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+						"active, unblocking open\n");
+					wake_up_interruptible(&port->gs.port.
+							open_wait);
+				} else {
+					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+						"raised. Ignoring.\n");
+				}
+			} else {
+				/* DCD went down! */
+				if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
+					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+						"dropped. hanging up....\n");
+					tty_hangup(port->gs.port.tty);
+				} else {
+					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
+						"dropped. ignoring.\n");
+				}
+			}
+		} else {
+			sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
+				"DCD changed, but it didn't.\n");
+		}
+	}
+}
+
+/* This is what an interrupt routine should look like. 
+ * Small, elegant, clear.
+ */
+
+static irqreturn_t sx_interrupt(int irq, void *ptr)
+{
+	struct sx_board *board = ptr;
+	struct sx_port *port;
+	int i;
+
+	func_enter();
+	sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
+			board->irq);
+
+	/* AAargh! The order in which to do these things is essential and
+	   not trivial. 
+
+	   - Rate limit goes before "recursive". Otherwise a series of
+	   recursive calls will hang the machine in the interrupt routine.
+
+	   - hardware twiddling goes before "recursive". Otherwise when we
+	   poll the card, and a recursive interrupt happens, we won't
+	   ack the card, so it might keep on interrupting us. (especially
+	   level sensitive interrupt systems like PCI).
+
+	   - Rate limit goes before hardware twiddling. Otherwise we won't
+	   catch a card that has gone bonkers.
+
+	   - The "initialized" test goes after the hardware twiddling. Otherwise
+	   the card will stick us in the interrupt routine again.
+
+	   - The initialized test goes before recursive. 
+	 */
+
+#ifdef IRQ_RATE_LIMIT
+	/* Aaargh! I'm ashamed. This costs more lines-of-code than the
+	   actual interrupt routine!. (Well, used to when I wrote that
+	   comment) */
+	{
+		static int lastjif;
+		static int nintr = 0;
+
+		if (lastjif == jiffies) {
+			if (++nintr > IRQ_RATE_LIMIT) {
+				free_irq(board->irq, board);
+				printk(KERN_ERR "sx: Too many interrupts. "
+						"Turning off interrupt %d.\n",
+						board->irq);
+			}
+		} else {
+			lastjif = jiffies;
+			nintr = 0;
+		}
+	}
+#endif
+
+	if (board->irq == irq) {
+		/* Tell the card we've noticed the interrupt. */
+
+		sx_write_board_word(board, cc_int_pending, 0);
+		if (IS_SX_BOARD(board)) {
+			write_sx_byte(board, SX_RESET_IRQ, 1);
+		} else if (IS_EISA_BOARD(board)) {
+			inb(board->eisa_base + 0xc03);
+			write_sx_word(board, 8, 0);
+		} else {
+			write_sx_byte(board, SI2_ISA_INTCLEAR,
+					SI2_ISA_INTCLEAR_CLEAR);
+			write_sx_byte(board, SI2_ISA_INTCLEAR,
+					SI2_ISA_INTCLEAR_SET);
+		}
+	}
+
+	if (!sx_initialized)
+		return IRQ_HANDLED;
+	if (!(board->flags & SX_BOARD_INITIALIZED))
+		return IRQ_HANDLED;
+
+	if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
+		printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
+		return IRQ_HANDLED;
+	}
+
+	for (i = 0; i < board->nports; i++) {
+		port = &board->ports[i];
+		if (port->gs.port.flags & GS_ACTIVE) {
+			if (sx_read_channel_byte(port, hi_state)) {
+				sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
+						"modem signal change?... \n",i);
+				sx_check_modem_signals(port);
+			}
+			if (port->gs.xmit_cnt) {
+				sx_transmit_chars(port);
+			}
+			if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
+				sx_receive_chars(port);
+			}
+		}
+	}
+
+	clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
+
+	sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
+			board->irq);
+	func_exit();
+	return IRQ_HANDLED;
+}
+
+static void sx_pollfunc(unsigned long data)
+{
+	struct sx_board *board = (struct sx_board *)data;
+
+	func_enter();
+
+	sx_interrupt(0, board);
+
+	mod_timer(&board->timer, jiffies + sx_poll);
+	func_exit();
+}
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *              interface with the generic_serial driver                  *
+ * ********************************************************************** */
+
+/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
+/* Hmm. Ok I figured it out. You don't.  */
+
+static void sx_disable_tx_interrupts(void *ptr)
+{
+	struct sx_port *port = ptr;
+	func_enter2();
+
+	port->gs.port.flags &= ~GS_TX_INTEN;
+
+	func_exit();
+}
+
+static void sx_enable_tx_interrupts(void *ptr)
+{
+	struct sx_port *port = ptr;
+	int data_in_buffer;
+	func_enter2();
+
+	/* First transmit the characters that we're supposed to */
+	sx_transmit_chars(port);
+
+	/* The sx card will never interrupt us if we don't fill the buffer
+	   past 25%. So we keep considering interrupts off if that's the case. */
+	data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
+			  sx_read_channel_byte(port, hi_txopos)) & 0xff;
+
+	/* XXX Must be "HIGH_WATER" for SI card according to doc. */
+	if (data_in_buffer < LOW_WATER)
+		port->gs.port.flags &= ~GS_TX_INTEN;
+
+	func_exit();
+}
+
+static void sx_disable_rx_interrupts(void *ptr)
+{
+	/*  struct sx_port *port = ptr; */
+	func_enter();
+
+	func_exit();
+}
+
+static void sx_enable_rx_interrupts(void *ptr)
+{
+	/*  struct sx_port *port = ptr; */
+	func_enter();
+
+	func_exit();
+}
+
+/* Jeez. Isn't this simple? */
+static int sx_carrier_raised(struct tty_port *port)
+{
+	struct sx_port *sp = container_of(port, struct sx_port, gs.port);
+	return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
+}
+
+/* Jeez. Isn't this simple? */
+static int sx_chars_in_buffer(void *ptr)
+{
+	struct sx_port *port = ptr;
+	func_enter2();
+
+	func_exit();
+	return ((sx_read_channel_byte(port, hi_txipos) -
+		 sx_read_channel_byte(port, hi_txopos)) & 0xff);
+}
+
+static void sx_shutdown_port(void *ptr)
+{
+	struct sx_port *port = ptr;
+
+	func_enter();
+
+	port->gs.port.flags &= ~GS_ACTIVE;
+	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
+		sx_setsignals(port, 0, 0);
+		sx_reconfigure_port(port);
+	}
+
+	func_exit();
+}
+
+/* ********************************************************************** *
+ *                Here are the routines that actually                     *
+ *               interface with the rest of the system                    *
+ * ********************************************************************** */
+
+static int sx_open(struct tty_struct *tty, struct file *filp)
+{
+	struct sx_port *port;
+	int retval, line;
+	unsigned long flags;
+
+	func_enter();
+
+	if (!sx_initialized) {
+		return -EIO;
+	}
+
+	line = tty->index;
+	sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
+			"np=%d)\n", task_pid_nr(current), line, tty,
+			current->signal->tty, sx_nports);
+
+	if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
+		return -ENODEV;
+
+	port = &sx_ports[line];
+	port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
+			    1 -> 0 transition. */
+
+	sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
+
+	spin_lock_irqsave(&port->gs.driver_lock, flags);
+
+	tty->driver_data = port;
+	port->gs.port.tty = tty;
+	port->gs.port.count++;
+	spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+
+	sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
+
+	/*
+	 * Start up serial port
+	 */
+	retval = gs_init_port(&port->gs);
+	sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
+	if (retval) {
+		port->gs.port.count--;
+		return retval;
+	}
+
+	port->gs.port.flags |= GS_ACTIVE;
+	if (port->gs.port.count <= 1)
+		sx_setsignals(port, 1, 1);
+
+#if 0
+	if (sx_debug & SX_DEBUG_OPEN)
+		my_hd(port, sizeof(*port));
+#else
+	if (sx_debug & SX_DEBUG_OPEN)
+		my_hd_io(port->board->base + port->ch_base, sizeof(*port));
+#endif
+
+	if (port->gs.port.count <= 1) {
+		if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
+			printk(KERN_ERR "sx: Card didn't respond to LOPEN "
+					"command.\n");
+			spin_lock_irqsave(&port->gs.driver_lock, flags);
+			port->gs.port.count--;
+			spin_unlock_irqrestore(&port->gs.driver_lock, flags);
+			return -EIO;
+		}
+	}
+
+	retval = gs_block_til_ready(port, filp);
+	sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
+			retval, port->gs.port.count);
+
+	if (retval) {
+/*
+ * Don't lower gs.port.count here because sx_close() will be called later
+ */
+
+		return retval;
+	}
+	/* tty->low_latency = 1; */
+
+	port->c_dcd = sx_carrier_raised(&port->gs.port);
+	sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
+
+	func_exit();
+	return 0;
+
+}
+
+static void sx_close(void *ptr)
+{
+	struct sx_port *port = ptr;
+	/* Give the port 5 seconds to close down. */
+	int to = 5 * HZ;
+
+	func_enter();
+
+	sx_setsignals(port, 0, 0);
+	sx_reconfigure_port(port);
+	sx_send_command(port, HS_CLOSE, 0, 0);
+
+	while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
+		if (msleep_interruptible(10))
+			break;
+	if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
+		if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
+				!= 1) {
+			printk(KERN_ERR "sx: sent the force_close command, but "
+					"card didn't react\n");
+		} else
+			sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
+					"command.\n");
+	}
+
+	sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
+			5 * HZ - to - 1, port->gs.port.count);
+
+	if (port->gs.port.count) {
+		sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
+				port->gs.port.count);
+		/*printk("%s SETTING port count to zero: %p count: %d\n",
+				__func__, port, port->gs.port.count);
+		port->gs.port.count = 0;*/
+	}
+
+	func_exit();
+}
+
+/* This is relatively thorough. But then again it is only 20 lines. */
+#define MARCHUP		for (i = min; i < max; i++)
+#define MARCHDOWN	for (i = max - 1; i >= min; i--)
+#define W0		write_sx_byte(board, i, 0x55)
+#define W1		write_sx_byte(board, i, 0xaa)
+#define R0		if (read_sx_byte(board, i) != 0x55) return 1
+#define R1		if (read_sx_byte(board, i) != 0xaa) return 1
+
+/* This memtest takes a human-noticable time. You normally only do it
+   once a boot, so I guess that it is worth it. */
+static int do_memtest(struct sx_board *board, int min, int max)
+{
+	int i;
+
+	/* This is a marchb. Theoretically, marchb catches much more than
+	   simpler tests. In practise, the longer test just catches more
+	   intermittent errors. -- REW
+	   (For the theory behind memory testing see: 
+	   Testing Semiconductor Memories by A.J. van de Goor.) */
+	MARCHUP {
+		W0;
+	}
+	MARCHUP {
+		R0;
+		W1;
+		R1;
+		W0;
+		R0;
+		W1;
+	}
+	MARCHUP {
+		R1;
+		W0;
+		W1;
+	}
+	MARCHDOWN {
+		R1;
+		W0;
+		W1;
+		W0;
+	}
+	MARCHDOWN {
+		R0;
+		W1;
+		W0;
+	}
+
+	return 0;
+}
+
+#undef MARCHUP
+#undef MARCHDOWN
+#undef W0
+#undef W1
+#undef R0
+#undef R1
+
+#define MARCHUP		for (i = min; i < max; i += 2)
+#define MARCHDOWN	for (i = max - 1; i >= min; i -= 2)
+#define W0		write_sx_word(board, i, 0x55aa)
+#define W1		write_sx_word(board, i, 0xaa55)
+#define R0		if (read_sx_word(board, i) != 0x55aa) return 1
+#define R1		if (read_sx_word(board, i) != 0xaa55) return 1
+
+#if 0
+/* This memtest takes a human-noticable time. You normally only do it
+   once a boot, so I guess that it is worth it. */
+static int do_memtest_w(struct sx_board *board, int min, int max)
+{
+	int i;
+
+	MARCHUP {
+		W0;
+	}
+	MARCHUP {
+		R0;
+		W1;
+		R1;
+		W0;
+		R0;
+		W1;
+	}
+	MARCHUP {
+		R1;
+		W0;
+		W1;
+	}
+	MARCHDOWN {
+		R1;
+		W0;
+		W1;
+		W0;
+	}
+	MARCHDOWN {
+		R0;
+		W1;
+		W0;
+	}
+
+	return 0;
+}
+#endif
+
+static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
+							unsigned long arg)
+{
+	long rc = 0;
+	int __user *descr = (int __user *)arg;
+	int i;
+	static struct sx_board *board = NULL;
+	int nbytes, offset;
+	unsigned long data;
+	char *tmp;
+
+	func_enter();
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	tty_lock();
+
+	sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
+
+	if (!board)
+		board = &boards[0];
+	if (board->flags & SX_BOARD_PRESENT) {
+		sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
+				board->flags);
+	} else {
+		sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
+				board->flags);
+		for (i = 0; i < SX_NBOARDS; i++)
+			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
+		sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
+		rc = -EIO;
+		goto out;
+	}
+
+	switch (cmd) {
+	case SXIO_SET_BOARD:
+		sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
+		rc = -EIO;
+		if (arg >= SX_NBOARDS)
+			break;
+		sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
+		if (!(boards[arg].flags & SX_BOARD_PRESENT))
+			break;
+		sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
+		board = &boards[arg];
+		rc = 0;
+		/* FIXME: And this does ... nothing?? */
+		break;
+	case SXIO_GET_TYPE:
+		rc = -ENOENT;	/* If we manage to miss one, return error. */
+		if (IS_SX_BOARD(board))
+			rc = SX_TYPE_SX;
+		if (IS_CF_BOARD(board))
+			rc = SX_TYPE_CF;
+		if (IS_SI_BOARD(board))
+			rc = SX_TYPE_SI;
+		if (IS_SI1_BOARD(board))
+			rc = SX_TYPE_SI;
+		if (IS_EISA_BOARD(board))
+			rc = SX_TYPE_SI;
+		sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
+		break;
+	case SXIO_DO_RAMTEST:
+		if (sx_initialized) {	/* Already initialized: better not ramtest the board.  */
+			rc = -EPERM;
+			break;
+		}
+		if (IS_SX_BOARD(board)) {
+			rc = do_memtest(board, 0, 0x7000);
+			if (!rc)
+				rc = do_memtest(board, 0, 0x7000);
+			/*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
+		} else {
+			rc = do_memtest(board, 0, 0x7ff8);
+			/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
+		}
+		sx_dprintk(SX_DEBUG_FIRMWARE,
+				"returning memtest result= %ld\n", rc);
+		break;
+	case SXIO_DOWNLOAD:
+		if (sx_initialized) {/* Already initialized */
+			rc = -EEXIST;
+			break;
+		}
+		if (!sx_reset(board)) {
+			rc = -EIO;
+			break;
+		}
+		sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
+
+		tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
+		if (!tmp) {
+			rc = -ENOMEM;
+			break;
+		}
+		/* FIXME: check returns */
+		get_user(nbytes, descr++);
+		get_user(offset, descr++);
+		get_user(data, descr++);
+		while (nbytes && data) {
+			for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
+				if (copy_from_user(tmp, (char __user *)data + i,
+						(i + SX_CHUNK_SIZE > nbytes) ?
+						nbytes - i : SX_CHUNK_SIZE)) {
+					kfree(tmp);
+					rc = -EFAULT;
+					goto out;
+				}
+				memcpy_toio(board->base2 + offset + i, tmp,
+						(i + SX_CHUNK_SIZE > nbytes) ?
+						nbytes - i : SX_CHUNK_SIZE);
+			}
+
+			get_user(nbytes, descr++);
+			get_user(offset, descr++);
+			get_user(data, descr++);
+		}
+		kfree(tmp);
+		sx_nports += sx_init_board(board);
+		rc = sx_nports;
+		break;
+	case SXIO_INIT:
+		if (sx_initialized) {	/* Already initialized */
+			rc = -EEXIST;
+			break;
+		}
+		/* This is not allowed until all boards are initialized... */
+		for (i = 0; i < SX_NBOARDS; i++) {
+			if ((boards[i].flags & SX_BOARD_PRESENT) &&
+				!(boards[i].flags & SX_BOARD_INITIALIZED)) {
+				rc = -EIO;
+				break;
+			}
+		}
+		for (i = 0; i < SX_NBOARDS; i++)
+			if (!(boards[i].flags & SX_BOARD_PRESENT))
+				break;
+
+		sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
+				"%d channels, first board: %d ports\n",
+				i, sx_nports, boards[0].nports);
+		rc = sx_init_portstructs(i, sx_nports);
+		sx_init_drivers();
+		if (rc >= 0)
+			sx_initialized++;
+		break;
+	case SXIO_SETDEBUG:
+		sx_debug = arg;
+		break;
+	case SXIO_GETDEBUG:
+		rc = sx_debug;
+		break;
+	case SXIO_GETGSDEBUG:
+	case SXIO_SETGSDEBUG:
+		rc = -EINVAL;
+		break;
+	case SXIO_GETNPORTS:
+		rc = sx_nports;
+		break;
+	default:
+		rc = -ENOTTY;
+		break;
+	}
+out:
+	tty_unlock();
+	func_exit();
+	return rc;
+}
+
+static int sx_break(struct tty_struct *tty, int flag)
+{
+	struct sx_port *port = tty->driver_data;
+	int rv;
+
+	func_enter();
+	tty_lock();
+
+	if (flag)
+		rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
+	else
+		rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
+	if (rv != 1)
+		printk(KERN_ERR "sx: couldn't send break (%x).\n",
+			read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
+	tty_unlock();
+	func_exit();
+	return 0;
+}
+
+static int sx_tiocmget(struct tty_struct *tty)
+{
+	struct sx_port *port = tty->driver_data;
+	return sx_getsignals(port);
+}
+
+static int sx_tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear)
+{
+	struct sx_port *port = tty->driver_data;
+	int rts = -1, dtr = -1;
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	sx_setsignals(port, dtr, rts);
+	sx_reconfigure_port(port);
+	return 0;
+}
+
+static int sx_ioctl(struct tty_struct *tty,
+		unsigned int cmd, unsigned long arg)
+{
+	int rc;
+	struct sx_port *port = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+
+	/* func_enter2(); */
+
+	rc = 0;
+	tty_lock();
+	switch (cmd) {
+	case TIOCGSERIAL:
+		rc = gs_getserial(&port->gs, argp);
+		break;
+	case TIOCSSERIAL:
+		rc = gs_setserial(&port->gs, argp);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	tty_unlock();
+
+	/* func_exit(); */
+	return rc;
+}
+
+/* The throttle/unthrottle scheme for the Specialix card is different
+ * from other drivers and deserves some explanation. 
+ * The Specialix hardware takes care of XON/XOFF
+ * and CTS/RTS flow control itself.  This means that all we have to
+ * do when signalled by the upper tty layer to throttle/unthrottle is
+ * to make a note of it here.  When we come to read characters from the
+ * rx buffers on the card (sx_receive_chars()) we look to see if the
+ * upper layer can accept more (as noted here in sx_rx_throt[]). 
+ * If it can't we simply don't remove chars from the cards buffer. 
+ * When the tty layer can accept chars, we again note that here and when
+ * sx_receive_chars() is called it will remove them from the cards buffer.
+ * The card will notice that a ports buffer has drained below some low
+ * water mark and will unflow control the line itself, using whatever
+ * flow control scheme is in use for that port. -- Simon Allen
+ */
+
+static void sx_throttle(struct tty_struct *tty)
+{
+	struct sx_port *port = tty->driver_data;
+
+	func_enter2();
+	/* If the port is using any type of input flow
+	 * control then throttle the port.
+	 */
+	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
+		port->gs.port.flags |= SX_RX_THROTTLE;
+	}
+	func_exit();
+}
+
+static void sx_unthrottle(struct tty_struct *tty)
+{
+	struct sx_port *port = tty->driver_data;
+
+	func_enter2();
+	/* Always unthrottle even if flow control is not enabled on
+	 * this port in case we disabled flow control while the port
+	 * was throttled
+	 */
+	port->gs.port.flags &= ~SX_RX_THROTTLE;
+	func_exit();
+	return;
+}
+
+/* ********************************************************************** *
+ *                    Here are the initialization routines.               *
+ * ********************************************************************** */
+
+static int sx_init_board(struct sx_board *board)
+{
+	int addr;
+	int chans;
+	int type;
+
+	func_enter();
+
+	/* This is preceded by downloading the download code. */
+
+	board->flags |= SX_BOARD_INITIALIZED;
+
+	if (read_sx_byte(board, 0))
+		/* CF boards may need this. */
+		write_sx_byte(board, 0, 0);
+
+	/* This resets the processor again, to make sure it didn't do any
+	   foolish things while we were downloading the image */
+	if (!sx_reset(board))
+		return 0;
+
+	sx_start_board(board);
+	udelay(10);
+	if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
+		printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
+		return 0;
+	}
+
+	/* Ok. So now the processor on the card is running. It gathered
+	   some info for us... */
+	sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
+	if (sx_debug & SX_DEBUG_INIT)
+		my_hd_io(board->base, 0x10);
+	sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
+	if (sx_debug & SX_DEBUG_INIT)
+		my_hd_io(board->base + 0x80, 0x30);
+
+	sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
+			"V%x.%02x,\n",
+			read_sx_byte(board, 0), read_sx_byte(board, 1),
+			read_sx_byte(board, 5), read_sx_byte(board, 4));
+
+	if (read_sx_byte(board, 0) == 0xff) {
+		printk(KERN_INFO "sx: No modules found. Sorry.\n");
+		board->nports = 0;
+		return 0;
+	}
+
+	chans = 0;
+
+	if (IS_SX_BOARD(board)) {
+		sx_write_board_word(board, cc_int_count, sx_maxints);
+	} else {
+		if (sx_maxints)
+			sx_write_board_word(board, cc_int_count,
+					SI_PROCESSOR_CLOCK / 8 / sx_maxints);
+	}
+
+	/* grab the first module type... */
+	/* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
+	board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
+				mc_chip));
+
+	/* XXX byteorder */
+	for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
+		type = sx_read_module_byte(board, addr, mc_chip);
+		sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
+				addr, read_sx_byte(board, addr + 2));
+
+		chans += sx_read_module_byte(board, addr, mc_type);
+
+		sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
+				"panels\n",
+				mod_type_s(type),
+				pan_type_s(sx_read_module_byte(board, addr,
+						mc_mods) & 0xf),
+				pan_type_s(sx_read_module_byte(board, addr,
+						mc_mods) >> 4));
+
+		sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
+			"version: %x\n",
+			sx_read_module_byte(board, addr, mc_rev1),
+			sx_read_module_byte(board, addr, mc_rev2),
+			sx_read_module_byte(board, addr, mc_mtaasic_rev));
+
+		/* The following combinations are illegal: It should theoretically
+		   work, but timing problems make the bus HANG. */
+
+		if (mod_compat_type(type) != board->ta_type) {
+			printk(KERN_ERR "sx: This is an invalid "
+				"configuration.\nDon't mix TA/MTA/SXDC on the "
+				"same hostadapter.\n");
+			chans = 0;
+			break;
+		}
+		if ((IS_EISA_BOARD(board) ||
+				IS_SI_BOARD(board)) &&
+				(mod_compat_type(type) == 4)) {
+			printk(KERN_ERR	"sx: This is an invalid "
+				"configuration.\nDon't use SXDCs on an SI/XIO "
+				"adapter.\n");
+			chans = 0;
+			break;
+		}
+#if 0				/* Problem fixed: firmware 3.05 */
+		if (IS_SX_BOARD(board) && (type == TA8)) {
+			/* There are some issues with the firmware and the DCD/RTS
+			   lines. It might work if you tie them together or something.
+			   It might also work if you get a newer sx_firmware.   Therefore
+			   this is just a warning. */
+			printk(KERN_WARNING
+			       "sx: The SX host doesn't work too well "
+			       "with the TA8 adapters.\nSpecialix is working on it.\n");
+		}
+#endif
+	}
+
+	if (chans) {
+		if (board->irq > 0) {
+			/* fixed irq, probably PCI */
+			if (sx_irqmask & (1 << board->irq)) {	/* may we use this irq? */
+				if (request_irq(board->irq, sx_interrupt,
+						IRQF_SHARED | IRQF_DISABLED,
+						"sx", board)) {
+					printk(KERN_ERR "sx: Cannot allocate "
+						"irq %d.\n", board->irq);
+					board->irq = 0;
+				}
+			} else
+				board->irq = 0;
+		} else if (board->irq < 0 && sx_irqmask) {
+			/* auto-allocate irq */
+			int irqnr;
+			int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
+					SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
+			for (irqnr = 15; irqnr > 0; irqnr--)
+				if (irqmask & (1 << irqnr))
+					if (!request_irq(irqnr, sx_interrupt,
+						IRQF_SHARED | IRQF_DISABLED,
+						"sx", board))
+						break;
+			if (!irqnr)
+				printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
+			board->irq = irqnr;
+		} else
+			board->irq = 0;
+
+		if (board->irq) {
+			/* Found a valid interrupt, start up interrupts! */
+			sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
+					board->irq);
+			sx_start_interrupts(board);
+			board->poll = sx_slowpoll;
+			board->flags |= SX_IRQ_ALLOCATED;
+		} else {
+			/* no irq: setup board for polled operation */
+			board->poll = sx_poll;
+			sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
+					board->poll);
+		}
+
+		/* The timer should be initialized anyway: That way we can
+		   safely del_timer it when the module is unloaded. */
+		setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
+
+		if (board->poll)
+			mod_timer(&board->timer, jiffies + board->poll);
+	} else {
+		board->irq = 0;
+	}
+
+	board->nports = chans;
+	sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
+
+	func_exit();
+	return chans;
+}
+
+static void __devinit printheader(void)
+{
+	static int header_printed;
+
+	if (!header_printed) {
+		printk(KERN_INFO "Specialix SX driver "
+			"(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
+		printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
+		header_printed = 1;
+	}
+}
+
+static int __devinit probe_sx(struct sx_board *board)
+{
+	struct vpd_prom vpdp;
+	char *p;
+	int i;
+
+	func_enter();
+
+	if (!IS_CF_BOARD(board)) {
+		sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
+				board->base + SX_VPD_ROM);
+
+		if (sx_debug & SX_DEBUG_PROBE)
+			my_hd_io(board->base + SX_VPD_ROM, 0x40);
+
+		p = (char *)&vpdp;
+		for (i = 0; i < sizeof(struct vpd_prom); i++)
+			*p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
+
+		if (sx_debug & SX_DEBUG_PROBE)
+			my_hd(&vpdp, 0x20);
+
+		sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
+
+		if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
+			sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
+					"'%s'\n", vpdp.identifier);
+			return 0;
+		}
+	}
+
+	printheader();
+
+	if (!IS_CF_BOARD(board)) {
+		printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
+			board->hw_base);
+		printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
+				"uniq ID:%08x, ",
+				vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
+		printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
+
+		if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
+				SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
+				SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
+			/* This might be a bit harsh. This was the primary
+			   reason the SX/ISA card didn't work at first... */
+			printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
+					"card. Sorry: giving up.\n");
+			return (0);
+		}
+
+		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
+				SX_ISA_UNIQUEID1) {
+			if (((unsigned long)board->hw_base) & 0x8000) {
+				printk(KERN_WARNING "sx: Warning: There may be "
+					"hardware problems with the card at "
+					"%lx.\n", board->hw_base);
+				printk(KERN_WARNING "sx: Read sx.txt for more "
+						"info.\n");
+			}
+		}
+	}
+
+	board->nports = -1;
+
+	/* This resets the processor, and keeps it off the bus. */
+	if (!sx_reset(board))
+		return 0;
+	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
+
+	func_exit();
+	return 1;
+}
+
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+
+/* Specialix probes for this card at 32k increments from 640k to 16M.
+   I consider machines with less than 16M unlikely nowadays, so I'm
+   not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
+   card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 
+   0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
+
+static int __devinit probe_si(struct sx_board *board)
+{
+	int i;
+
+	func_enter();
+	sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
+		"%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
+
+	if (sx_debug & SX_DEBUG_PROBE)
+		my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
+
+	if (!IS_EISA_BOARD(board)) {
+		if (IS_SI1_BOARD(board)) {
+			for (i = 0; i < 8; i++) {
+				write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
+			}
+		}
+		for (i = 0; i < 8; i++) {
+			if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
+					!= i) {
+				func_exit();
+				return 0;
+			}
+		}
+	}
+
+	/* Now we're pretty much convinced that there is an SI board here, 
+	   but to prevent trouble, we'd better double check that we don't
+	   have an SI1 board when we're probing for an SI2 board.... */
+
+	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
+	if (IS_SI1_BOARD(board)) {
+		/* This should be an SI1 board, which has this
+		   location writable... */
+		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
+			func_exit();
+			return 0;
+		}
+	} else {
+		/* This should be an SI2 board, which has the bottom
+		   3 bits non-writable... */
+		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
+			func_exit();
+			return 0;
+		}
+	}
+
+	/* Now we're pretty much convinced that there is an SI board here, 
+	   but to prevent trouble, we'd better double check that we don't
+	   have an SI1 board when we're probing for an SI2 board.... */
+
+	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
+	if (IS_SI1_BOARD(board)) {
+		/* This should be an SI1 board, which has this
+		   location writable... */
+		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
+			func_exit();
+			return 0;
+		}
+	} else {
+		/* This should be an SI2 board, which has the bottom
+		   3 bits non-writable... */
+		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
+			func_exit();
+			return 0;
+		}
+	}
+
+	printheader();
+
+	printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
+	/* Compared to the SX boards, it is a complete guess as to what
+	   this card is up to... */
+
+	board->nports = -1;
+
+	/* This resets the processor, and keeps it off the bus. */
+	if (!sx_reset(board))
+		return 0;
+	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
+
+	func_exit();
+	return 1;
+}
+#endif
+
+static const struct tty_operations sx_ops = {
+	.break_ctl = sx_break,
+	.open = sx_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = sx_ioctl,
+	.throttle = sx_throttle,
+	.unthrottle = sx_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+	.tiocmget = sx_tiocmget,
+	.tiocmset = sx_tiocmset,
+};
+
+static const struct tty_port_operations sx_port_ops = {
+	.carrier_raised = sx_carrier_raised,
+};
+
+static int sx_init_drivers(void)
+{
+	int error;
+
+	func_enter();
+
+	sx_driver = alloc_tty_driver(sx_nports);
+	if (!sx_driver)
+		return 1;
+	sx_driver->owner = THIS_MODULE;
+	sx_driver->driver_name = "specialix_sx";
+	sx_driver->name = "ttyX";
+	sx_driver->major = SX_NORMAL_MAJOR;
+	sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	sx_driver->subtype = SERIAL_TYPE_NORMAL;
+	sx_driver->init_termios = tty_std_termios;
+	sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	sx_driver->init_termios.c_ispeed = 9600;
+	sx_driver->init_termios.c_ospeed = 9600;
+	sx_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(sx_driver, &sx_ops);
+
+	if ((error = tty_register_driver(sx_driver))) {
+		put_tty_driver(sx_driver);
+		printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
+			error);
+		return 1;
+	}
+	func_exit();
+	return 0;
+}
+
+static int sx_init_portstructs(int nboards, int nports)
+{
+	struct sx_board *board;
+	struct sx_port *port;
+	int i, j;
+	int addr, chans;
+	int portno;
+
+	func_enter();
+
+	/* Many drivers statically allocate the maximum number of ports
+	   There is no reason not to allocate them dynamically.
+	   Is there? -- REW */
+	sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
+	if (!sx_ports)
+		return -ENOMEM;
+
+	port = sx_ports;
+	for (i = 0; i < nboards; i++) {
+		board = &boards[i];
+		board->ports = port;
+		for (j = 0; j < boards[i].nports; j++) {
+			sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
+			tty_port_init(&port->gs.port);
+			port->gs.port.ops = &sx_port_ops;
+			port->gs.magic = SX_MAGIC;
+			port->gs.close_delay = HZ / 2;
+			port->gs.closing_wait = 30 * HZ;
+			port->board = board;
+			port->gs.rd = &sx_real_driver;
+#ifdef NEW_WRITE_LOCKING
+			port->gs.port_write_mutex = MUTEX;
+#endif
+			spin_lock_init(&port->gs.driver_lock);
+			/*
+			 * Initializing wait queue
+			 */
+			port++;
+		}
+	}
+
+	port = sx_ports;
+	portno = 0;
+	for (i = 0; i < nboards; i++) {
+		board = &boards[i];
+		board->port_base = portno;
+		/* Possibly the configuration was rejected. */
+		sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
+				board->nports);
+		if (board->nports <= 0)
+			continue;
+		/* XXX byteorder ?? */
+		for (addr = 0x80; addr != 0;
+				addr = read_sx_word(board, addr) & 0x7fff) {
+			chans = sx_read_module_byte(board, addr, mc_type);
+			sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
+					"channels\n", addr, chans);
+			sx_dprintk(SX_DEBUG_PROBE, "Port at");
+			for (j = 0; j < chans; j++) {
+				/* The "sx-way" is the way it SHOULD be done.
+				   That way in the future, the firmware may for
+				   example pack the structures a bit more
+				   efficient. Neil tells me it isn't going to
+				   happen anytime soon though. */
+				if (IS_SX_BOARD(board))
+					port->ch_base = sx_read_module_word(
+							board, addr + j * 2,
+							mc_chan_pointer);
+				else
+					port->ch_base = addr + 0x100 + 0x300 *j;
+
+				sx_dprintk(SX_DEBUG_PROBE, " %x",
+						port->ch_base);
+				port->line = portno++;
+				port++;
+			}
+			sx_dprintk(SX_DEBUG_PROBE, "\n");
+		}
+		/* This has to be done earlier. */
+		/* board->flags |= SX_BOARD_INITIALIZED; */
+	}
+
+	func_exit();
+	return 0;
+}
+
+static unsigned int sx_find_free_board(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < SX_NBOARDS; i++)
+		if (!(boards[i].flags & SX_BOARD_PRESENT))
+			break;
+
+	return i;
+}
+
+static void __exit sx_release_drivers(void)
+{
+	func_enter();
+	tty_unregister_driver(sx_driver);
+	put_tty_driver(sx_driver);
+	func_exit();
+}
+
+static void __devexit sx_remove_card(struct sx_board *board,
+		struct pci_dev *pdev)
+{
+	if (board->flags & SX_BOARD_INITIALIZED) {
+		/* The board should stop messing with us. (actually I mean the
+		   interrupt) */
+		sx_reset(board);
+		if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
+			free_irq(board->irq, board);
+
+		/* It is safe/allowed to del_timer a non-active timer */
+		del_timer(&board->timer);
+		if (pdev) {
+#ifdef CONFIG_PCI
+			iounmap(board->base2);
+			pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
+#endif
+		} else {
+			iounmap(board->base);
+			release_region(board->hw_base, board->hw_len);
+		}
+
+		board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
+	}
+}
+
+#ifdef CONFIG_EISA
+
+static int __devinit sx_eisa_probe(struct device *dev)
+{
+	struct eisa_device *edev = to_eisa_device(dev);
+	struct sx_board *board;
+	unsigned long eisa_slot = edev->base_addr;
+	unsigned int i;
+	int retval = -EIO;
+
+	mutex_lock(&sx_boards_lock);
+	i = sx_find_free_board();
+	if (i == SX_NBOARDS) {
+		mutex_unlock(&sx_boards_lock);
+		goto err;
+	}
+	board = &boards[i];
+	board->flags |= SX_BOARD_PRESENT;
+	mutex_unlock(&sx_boards_lock);
+
+	dev_info(dev, "XIO : Signature found in EISA slot %lu, "
+		 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
+		 eisa_slot >> 12,
+		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
+		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
+
+	board->eisa_base = eisa_slot;
+	board->flags &= ~SX_BOARD_TYPE;
+	board->flags |= SI_EISA_BOARD;
+
+	board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
+			  inb(eisa_slot + 0xc00)) << 16;
+	board->hw_len = SI2_EISA_WINDOW_LEN;
+	if (!request_region(board->hw_base, board->hw_len, "sx")) {
+		dev_err(dev, "can't request region\n");
+		goto err_flag;
+	}
+	board->base2 =
+	board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
+	if (!board->base) {
+		dev_err(dev, "can't remap memory\n");
+		goto err_reg;
+	}
+
+	sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
+	sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
+	board->irq = inb(eisa_slot + 0xc02) >> 4;
+	sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
+
+	if (!probe_si(board))
+		goto err_unmap;
+
+	dev_set_drvdata(dev, board);
+
+	return 0;
+err_unmap:
+	iounmap(board->base);
+err_reg:
+	release_region(board->hw_base, board->hw_len);
+err_flag:
+	board->flags &= ~SX_BOARD_PRESENT;
+err:
+	return retval;
+}
+
+static int __devexit sx_eisa_remove(struct device *dev)
+{
+	struct sx_board *board = dev_get_drvdata(dev);
+
+	sx_remove_card(board, NULL);
+
+	return 0;
+}
+
+static struct eisa_device_id sx_eisa_tbl[] = {
+	{ "SLX" },
+	{ "" }
+};
+
+MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
+
+static struct eisa_driver sx_eisadriver = {
+	.id_table = sx_eisa_tbl,
+	.driver = {
+		.name = "sx",
+		.probe = sx_eisa_probe,
+		.remove = __devexit_p(sx_eisa_remove),
+	}
+};
+
+#endif
+
+#ifdef CONFIG_PCI
+ /******************************************************** 
+ * Setting bit 17 in the CNTRL register of the PLX 9050  * 
+ * chip forces a retry on writes while a read is pending.*
+ * This is to prevent the card locking up on Intel Xeon  *
+ * multiprocessor systems with the NX chipset.    -- NV  *
+ ********************************************************/
+
+/* Newer cards are produced with this bit set from the configuration
+   EEprom.  As the bit is read/write for the CPU, we can fix it here,
+   if we detect that it isn't set correctly. -- REW */
+
+static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
+{
+	unsigned int hwbase;
+	void __iomem *rebase;
+	unsigned int t;
+
+#define CNTRL_REG_OFFSET	0x50
+#define CNTRL_REG_GOODVALUE	0x18260000
+
+	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
+	hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
+	rebase = ioremap_nocache(hwbase, 0x80);
+	t = readl(rebase + CNTRL_REG_OFFSET);
+	if (t != CNTRL_REG_GOODVALUE) {
+		printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
+			"%08x\n", t, CNTRL_REG_GOODVALUE);
+		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
+	}
+	iounmap(rebase);
+}
+#endif
+
+static int __devinit sx_pci_probe(struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+#ifdef CONFIG_PCI
+	struct sx_board *board;
+	unsigned int i, reg;
+	int retval = -EIO;
+
+	mutex_lock(&sx_boards_lock);
+	i = sx_find_free_board();
+	if (i == SX_NBOARDS) {
+		mutex_unlock(&sx_boards_lock);
+		goto err;
+	}
+	board = &boards[i];
+	board->flags |= SX_BOARD_PRESENT;
+	mutex_unlock(&sx_boards_lock);
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err_flag;
+
+	board->flags &= ~SX_BOARD_TYPE;
+	board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
+		SX_CFPCI_BOARD;
+
+	/* CF boards use base address 3.... */
+	reg = IS_CF_BOARD(board) ? 3 : 2;
+	retval = pci_request_region(pdev, reg, "sx");
+	if (retval) {
+		dev_err(&pdev->dev, "can't request region\n");
+		goto err_flag;
+	}
+	board->hw_base = pci_resource_start(pdev, reg);
+	board->base2 =
+	board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
+	if (!board->base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		goto err_reg;
+	}
+
+	/* Most of the stuff on the CF board is offset by 0x18000 ....  */
+	if (IS_CF_BOARD(board))
+		board->base += 0x18000;
+
+	board->irq = pdev->irq;
+
+	dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
+		 board->irq, board->flags);
+
+	if (!probe_sx(board)) {
+		retval = -EIO;
+		goto err_unmap;
+	}
+
+	fix_sx_pci(pdev, board);
+
+	pci_set_drvdata(pdev, board);
+
+	return 0;
+err_unmap:
+	iounmap(board->base2);
+err_reg:
+	pci_release_region(pdev, reg);
+err_flag:
+	board->flags &= ~SX_BOARD_PRESENT;
+err:
+	return retval;
+#else
+	return -ENODEV;
+#endif
+}
+
+static void __devexit sx_pci_remove(struct pci_dev *pdev)
+{
+	struct sx_board *board = pci_get_drvdata(pdev);
+
+	sx_remove_card(board, pdev);
+}
+
+/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
+   its because the standard requires it. So check for SUBVENDOR_ID. */
+static struct pci_device_id sx_pci_tbl[] = {
+	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
+		.subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
+	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
+		.subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
+
+static struct pci_driver sx_pcidriver = {
+	.name = "sx",
+	.id_table = sx_pci_tbl,
+	.probe = sx_pci_probe,
+	.remove = __devexit_p(sx_pci_remove)
+};
+
+static int __init sx_init(void)
+{
+#ifdef CONFIG_EISA
+	int retval1;
+#endif
+#ifdef CONFIG_ISA
+	struct sx_board *board;
+	unsigned int i;
+#endif
+	unsigned int found = 0;
+	int retval;
+
+	func_enter();
+	sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
+			sx_debug);
+	if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
+		printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
+				"value. Assuming -1.\n(%p)\n", &sx_debug);
+		sx_debug = -1;
+	}
+
+	if (misc_register(&sx_fw_device) < 0) {
+		printk(KERN_ERR "SX: Unable to register firmware loader "
+				"driver.\n");
+		return -EIO;
+	}
+#ifdef CONFIG_ISA
+	for (i = 0; i < NR_SX_ADDRS; i++) {
+		board = &boards[found];
+		board->hw_base = sx_probe_addrs[i];
+		board->hw_len = SX_WINDOW_LEN;
+		if (!request_region(board->hw_base, board->hw_len, "sx"))
+			continue;
+		board->base2 =
+		board->base = ioremap_nocache(board->hw_base, board->hw_len);
+		if (!board->base)
+			goto err_sx_reg;
+		board->flags &= ~SX_BOARD_TYPE;
+		board->flags |= SX_ISA_BOARD;
+		board->irq = sx_irqmask ? -1 : 0;
+
+		if (probe_sx(board)) {
+			board->flags |= SX_BOARD_PRESENT;
+			found++;
+		} else {
+			iounmap(board->base);
+err_sx_reg:
+			release_region(board->hw_base, board->hw_len);
+		}
+	}
+
+	for (i = 0; i < NR_SI_ADDRS; i++) {
+		board = &boards[found];
+		board->hw_base = si_probe_addrs[i];
+		board->hw_len = SI2_ISA_WINDOW_LEN;
+		if (!request_region(board->hw_base, board->hw_len, "sx"))
+			continue;
+		board->base2 =
+		board->base = ioremap_nocache(board->hw_base, board->hw_len);
+		if (!board->base)
+			goto err_si_reg;
+		board->flags &= ~SX_BOARD_TYPE;
+		board->flags |= SI_ISA_BOARD;
+		board->irq = sx_irqmask ? -1 : 0;
+
+		if (probe_si(board)) {
+			board->flags |= SX_BOARD_PRESENT;
+			found++;
+		} else {
+			iounmap(board->base);
+err_si_reg:
+			release_region(board->hw_base, board->hw_len);
+		}
+	}
+	for (i = 0; i < NR_SI1_ADDRS; i++) {
+		board = &boards[found];
+		board->hw_base = si1_probe_addrs[i];
+		board->hw_len = SI1_ISA_WINDOW_LEN;
+		if (!request_region(board->hw_base, board->hw_len, "sx"))
+			continue;
+		board->base2 =
+		board->base = ioremap_nocache(board->hw_base, board->hw_len);
+		if (!board->base)
+			goto err_si1_reg;
+		board->flags &= ~SX_BOARD_TYPE;
+		board->flags |= SI1_ISA_BOARD;
+		board->irq = sx_irqmask ? -1 : 0;
+
+		if (probe_si(board)) {
+			board->flags |= SX_BOARD_PRESENT;
+			found++;
+		} else {
+			iounmap(board->base);
+err_si1_reg:
+			release_region(board->hw_base, board->hw_len);
+		}
+	}
+#endif
+#ifdef CONFIG_EISA
+	retval1 = eisa_driver_register(&sx_eisadriver);
+#endif
+	retval = pci_register_driver(&sx_pcidriver);
+
+	if (found) {
+		printk(KERN_INFO "sx: total of %d boards detected.\n", found);
+		retval = 0;
+	} else if (retval) {
+#ifdef CONFIG_EISA
+		retval = retval1;
+		if (retval1)
+#endif
+			misc_deregister(&sx_fw_device);
+	}
+
+	func_exit();
+	return retval;
+}
+
+static void __exit sx_exit(void)
+{
+	int i;
+
+	func_enter();
+#ifdef CONFIG_EISA
+	eisa_driver_unregister(&sx_eisadriver);
+#endif
+	pci_unregister_driver(&sx_pcidriver);
+
+	for (i = 0; i < SX_NBOARDS; i++)
+		sx_remove_card(&boards[i], NULL);
+
+	if (misc_deregister(&sx_fw_device) < 0) {
+		printk(KERN_INFO "sx: couldn't deregister firmware loader "
+				"device\n");
+	}
+	sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
+			sx_initialized);
+	if (sx_initialized)
+		sx_release_drivers();
+
+	kfree(sx_ports);
+	func_exit();
+}
+
+module_init(sx_init);
+module_exit(sx_exit);
diff --git a/drivers/staging/generic_serial/sx.h b/drivers/staging/generic_serial/sx.h
new file mode 100644
index 0000000..87c2def
--- /dev/null
+++ b/drivers/staging/generic_serial/sx.h
@@ -0,0 +1,201 @@
+
+/*
+ *  sx.h
+ *
+ *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
+ *
+ *  SX serial driver.
+ *  -- Supports SI, XIO and SX host cards. 
+ *  -- Supports TAs, MTAs and SXDCs.
+ *
+ *  Version 1.3 -- March, 1999. 
+ * 
+ */
+
+#define SX_NBOARDS        4
+#define SX_PORTSPERBOARD 32
+#define SX_NPORTS        (SX_NBOARDS * SX_PORTSPERBOARD)
+
+#ifdef __KERNEL__
+
+#define SX_MAGIC 0x12345678
+
+struct sx_port {
+  struct gs_port          gs;
+  struct wait_queue       *shutdown_wait;
+  int                     ch_base;
+  int                     c_dcd;
+  struct sx_board         *board;
+  int                     line;
+  unsigned long           locks;
+};
+
+struct sx_board {
+  int magic;
+  void __iomem *base;
+  void __iomem *base2;
+  unsigned long hw_base;
+  resource_size_t hw_len;
+  int eisa_base;
+  int port_base; /* Number of the first port */
+  struct sx_port *ports;
+  int nports;
+  int flags;
+  int irq;
+  int poll;
+  int ta_type;
+  struct timer_list       timer;
+  unsigned long           locks;
+};
+
+struct vpd_prom {
+  unsigned short id;
+  char hwrev;
+  char hwass;
+  int uniqid;
+  char myear;
+  char mweek;
+  char hw_feature[5];
+  char oem_id;
+  char identifier[16];
+};
+
+#ifndef MOD_RS232DB25MALE
+#define MOD_RS232DB25MALE 0x0a
+#endif
+
+#define SI_ISA_BOARD         0x00000001
+#define SX_ISA_BOARD         0x00000002
+#define SX_PCI_BOARD         0x00000004
+#define SX_CFPCI_BOARD       0x00000008
+#define SX_CFISA_BOARD       0x00000010
+#define SI_EISA_BOARD        0x00000020
+#define SI1_ISA_BOARD        0x00000040
+
+#define SX_BOARD_PRESENT     0x00001000
+#define SX_BOARD_INITIALIZED 0x00002000
+#define SX_IRQ_ALLOCATED     0x00004000
+
+#define SX_BOARD_TYPE        0x000000ff
+
+#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \
+                                            SX_ISA_BOARD | SX_CFISA_BOARD))
+
+#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
+#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD)
+
+#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
+
+#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
+
+/* The SI processor clock is required to calculate the cc_int_count register
+   value for the SI cards. */
+#define SI_PROCESSOR_CLOCK 25000000
+
+
+/* port flags */
+/* Make sure these don't clash with gs flags or async flags */
+#define SX_RX_THROTTLE        0x0000001
+
+
+
+#define SX_PORT_TRANSMIT_LOCK  0
+#define SX_BOARD_INTR_LOCK     0
+
+
+
+/* Debug flags. Add these together to get more debug info. */
+
+#define SX_DEBUG_OPEN          0x00000001
+#define SX_DEBUG_SETTING       0x00000002
+#define SX_DEBUG_FLOW          0x00000004
+#define SX_DEBUG_MODEMSIGNALS  0x00000008
+#define SX_DEBUG_TERMIOS       0x00000010
+#define SX_DEBUG_TRANSMIT      0x00000020
+#define SX_DEBUG_RECEIVE       0x00000040
+#define SX_DEBUG_INTERRUPTS    0x00000080
+#define SX_DEBUG_PROBE         0x00000100
+#define SX_DEBUG_INIT          0x00000200
+#define SX_DEBUG_CLEANUP       0x00000400
+#define SX_DEBUG_CLOSE         0x00000800
+#define SX_DEBUG_FIRMWARE      0x00001000
+#define SX_DEBUG_MEMTEST       0x00002000
+
+#define SX_DEBUG_ALL           0xffffffff
+
+
+#define O_OTHER(tty)    \
+      ((O_OLCUC(tty))  ||\
+      (O_ONLCR(tty))   ||\
+      (O_OCRNL(tty))   ||\
+      (O_ONOCR(tty))   ||\
+      (O_ONLRET(tty))  ||\
+      (O_OFILL(tty))   ||\
+      (O_OFDEL(tty))   ||\
+      (O_NLDLY(tty))   ||\
+      (O_CRDLY(tty))   ||\
+      (O_TABDLY(tty))  ||\
+      (O_BSDLY(tty))   ||\
+      (O_VTDLY(tty))   ||\
+      (O_FFDLY(tty)))
+
+/* Same for input. */
+#define I_OTHER(tty)    \
+      ((I_INLCR(tty))  ||\
+      (I_IGNCR(tty))   ||\
+      (I_ICRNL(tty))   ||\
+      (I_IUCLC(tty))   ||\
+      (L_ISIG(tty)))
+
+#define MOD_TA   (        TA>>4)
+#define MOD_MTA  (MTA_CD1400>>4)
+#define MOD_SXDC (      SXDC>>4)
+
+
+/* We copy the download code over to the card in chunks of ... bytes */
+#define SX_CHUNK_SIZE 128
+
+#endif /* __KERNEL__ */
+
+
+
+/* Specialix document 6210046-11 page 3 */
+#define SPX(X) (('S'<<24) | ('P' << 16) | (X))
+
+/* Specialix-Linux specific IOCTLS. */
+#define SPXL(X) (SPX(('L' << 8) | (X)))
+
+
+#define SXIO_SET_BOARD      SPXL(0x01)
+#define SXIO_GET_TYPE       SPXL(0x02)
+#define SXIO_DOWNLOAD       SPXL(0x03)
+#define SXIO_INIT           SPXL(0x04)
+#define SXIO_SETDEBUG       SPXL(0x05)
+#define SXIO_GETDEBUG       SPXL(0x06)
+#define SXIO_DO_RAMTEST     SPXL(0x07)
+#define SXIO_SETGSDEBUG     SPXL(0x08)
+#define SXIO_GETGSDEBUG     SPXL(0x09)
+#define SXIO_GETNPORTS      SPXL(0x0a)
+
+
+#ifndef SXCTL_MISC_MINOR 
+/* Allow others to gather this into "major.h" or something like that */
+#define SXCTL_MISC_MINOR    167
+#endif
+
+#ifndef SX_NORMAL_MAJOR
+/* This allows overriding on the compiler commandline, or in a "major.h" 
+   include or something like that */
+#define SX_NORMAL_MAJOR  32
+#define SX_CALLOUT_MAJOR 33
+#endif
+
+
+#define SX_TYPE_SX          0x01
+#define SX_TYPE_SI          0x02
+#define SX_TYPE_CF          0x03
+
+
+#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN)
+/*                         Need a #define for ^^^^^^^ !!! */
+
diff --git a/drivers/staging/generic_serial/sxboards.h b/drivers/staging/generic_serial/sxboards.h
new file mode 100644
index 0000000..427927d
--- /dev/null
+++ b/drivers/staging/generic_serial/sxboards.h
@@ -0,0 +1,206 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	SX/SI/XIO Board Hardware Definitions	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	16th March 1998				*/
+/*									*/
+/*	Version		:	3.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
+/*									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing the SX/SI/XIO board hardware	*/
+/*									*/
+/************************************************************************/
+
+/* History...
+
+3.0.0	16/03/98 NPV	Creation.
+
+*/
+
+#ifndef	_sxboards_h				/* If SXBOARDS.H not already defined */
+#define	_sxboards_h    1
+
+/*****************************************************************************
+*******************************                 ******************************
+*******************************   Board Types   ******************************
+*******************************                 ******************************
+*****************************************************************************/
+
+/* BUS types... */
+#define		BUS_ISA		0
+#define		BUS_MCA		1
+#define		BUS_EISA	2
+#define		BUS_PCI		3
+
+/* Board phases... */
+#define		SI1_Z280	1
+#define		SI2_Z280	2
+#define		SI3_T225	3
+
+/* Board types... */
+#define		CARD_TYPE(bus,phase)	(bus<<4|phase)
+#define		CARD_BUS(type)		((type>>4)&0xF)
+#define		CARD_PHASE(type)	(type&0xF)
+
+#define		TYPE_SI1_ISA		CARD_TYPE(BUS_ISA,SI1_Z280)
+#define		TYPE_SI2_ISA		CARD_TYPE(BUS_ISA,SI2_Z280)
+#define		TYPE_SI2_EISA		CARD_TYPE(BUS_EISA,SI2_Z280)
+#define		TYPE_SI2_PCI		CARD_TYPE(BUS_PCI,SI2_Z280)
+
+#define		TYPE_SX_ISA		CARD_TYPE(BUS_ISA,SI3_T225)
+#define		TYPE_SX_PCI		CARD_TYPE(BUS_PCI,SI3_T225)
+/*****************************************************************************
+******************************                  ******************************
+******************************   Phase 1 Z280   ******************************
+******************************                  ******************************
+*****************************************************************************/
+
+/* ISA board details... */
+#define		SI1_ISA_WINDOW_LEN	0x10000		/* 64 Kbyte shared memory window */
+//#define 	SI1_ISA_MEMORY_LEN	0x8000		/* Usable memory  - unused define*/
+//#define		SI1_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
+//#define		SI1_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
+//#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
+//#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
+
+/* ISA board, register definitions... */
+//#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
+#define		SI1_ISA_RESET		0x8000		/* WRITE: Host Reset */
+#define		SI1_ISA_RESET_CLEAR	0xc000		/* WRITE: Host Reset clear*/
+#define		SI1_ISA_WAIT	        0x9000		/* WRITE: Host wait */
+#define		SI1_ISA_WAIT_CLEAR	0xd000		/* WRITE: Host wait clear */
+#define		SI1_ISA_INTCL        	0xa000		/* WRITE: Host Reset */
+#define		SI1_ISA_INTCL_CLEAR	0xe000		/* WRITE: Host Reset */
+
+
+/*****************************************************************************
+******************************                  ******************************
+******************************   Phase 2 Z280   ******************************
+******************************                  ******************************
+*****************************************************************************/
+
+/* ISA board details... */
+#define		SI2_ISA_WINDOW_LEN	0x8000		/* 32 Kbyte shared memory window */
+#define 	SI2_ISA_MEMORY_LEN	0x7FF8		/* Usable memory */
+#define		SI2_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
+#define		SI2_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
+#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
+#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
+
+/* ISA board, register definitions... */
+#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
+#define		SI2_ISA_RESET		SI2_ISA_ID_BASE		/* WRITE: Host Reset */
+#define		SI2_ISA_IRQ11		(SI2_ISA_ID_BASE+1)	/* WRITE: Set IRQ11 */
+#define		SI2_ISA_IRQ12		(SI2_ISA_ID_BASE+2)	/* WRITE: Set IRQ12 */
+#define		SI2_ISA_IRQ15		(SI2_ISA_ID_BASE+3)	/* WRITE: Set IRQ15 */
+#define		SI2_ISA_IRQSET		(SI2_ISA_ID_BASE+4)	/* WRITE: Set Host Interrupt */
+#define		SI2_ISA_INTCLEAR	(SI2_ISA_ID_BASE+5)	/* WRITE: Enable Host Interrupt */
+
+#define		SI2_ISA_IRQ11_SET	0x10
+#define		SI2_ISA_IRQ11_CLEAR	0x00
+#define		SI2_ISA_IRQ12_SET	0x10
+#define		SI2_ISA_IRQ12_CLEAR	0x00
+#define		SI2_ISA_IRQ15_SET	0x10
+#define		SI2_ISA_IRQ15_CLEAR	0x00
+#define		SI2_ISA_INTCLEAR_SET	0x10
+#define		SI2_ISA_INTCLEAR_CLEAR	0x00
+#define		SI2_ISA_IRQSET_CLEAR	0x10
+#define		SI2_ISA_IRQSET_SET	0x00
+#define		SI2_ISA_RESET_SET	0x00
+#define		SI2_ISA_RESET_CLEAR	0x10
+
+/* PCI board details... */
+#define		SI2_PCI_WINDOW_LEN	0x100000	/* 1 Mbyte memory window */
+
+/* PCI board register definitions... */
+#define		SI2_PCI_SET_IRQ		0x40001		/* Set Host Interrupt  */
+#define		SI2_PCI_RESET		0xC0001		/* Host Reset */
+
+/*****************************************************************************
+******************************                  ******************************
+******************************   Phase 3 T225   ******************************
+******************************                  ******************************
+*****************************************************************************/
+
+/* General board details... */
+#define		SX_WINDOW_LEN		64*1024		/* 64 Kbyte memory window */
+
+/* ISA board details... */
+#define		SX_ISA_ADDR_LOW		0x0A0000	/* Lowest address = 640 Kbyte */
+#define		SX_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
+#define		SX_ISA_ADDR_STEP	SX_WINDOW_LEN	/* ISA board address step */
+#define		SX_ISA_IRQ_MASK		0x9E00		/* IRQs 15,12,11,10,9 */
+
+/* Hardware register definitions... */
+#define		SX_EVENT_STATUS		0x7800		/* READ:  T225 Event Status */
+#define		SX_EVENT_STROBE		0x7800		/* WRITE: T225 Event Strobe */
+#define		SX_EVENT_ENABLE		0x7880		/* WRITE: T225 Event Enable */
+#define		SX_VPD_ROM		0x7C00		/* READ:  Vital Product Data ROM */
+#define		SX_CONFIG		0x7C00		/* WRITE: Host Configuration Register */
+#define		SX_IRQ_STATUS		0x7C80		/* READ:  Host Interrupt Status */
+#define		SX_SET_IRQ		0x7C80		/* WRITE: Set Host Interrupt */
+#define		SX_RESET_STATUS		0x7D00		/* READ:  Host Reset Status */
+#define		SX_RESET		0x7D00		/* WRITE: Host Reset */
+#define		SX_RESET_IRQ		0x7D80		/* WRITE: Reset Host Interrupt */
+
+/* SX_VPD_ROM definitions... */
+#define		SX_VPD_SLX_ID1		0x00
+#define		SX_VPD_SLX_ID2		0x01
+#define		SX_VPD_HW_REV		0x02
+#define		SX_VPD_HW_ASSEM		0x03
+#define		SX_VPD_UNIQUEID4	0x04
+#define		SX_VPD_UNIQUEID3	0x05
+#define		SX_VPD_UNIQUEID2	0x06
+#define		SX_VPD_UNIQUEID1	0x07
+#define		SX_VPD_MANU_YEAR	0x08
+#define		SX_VPD_MANU_WEEK	0x09
+#define		SX_VPD_IDENT		0x10
+#define		SX_VPD_IDENT_STRING	"JET HOST BY KEV#"
+
+/* SX unique identifiers... */
+#define		SX_UNIQUEID_MASK	0xF0
+#define		SX_ISA_UNIQUEID1	0x20
+#define		SX_PCI_UNIQUEID1	0x50
+
+/* SX_CONFIG definitions... */
+#define		SX_CONF_BUSEN		0x02		/* Enable T225 memory and I/O */
+#define		SX_CONF_HOSTIRQ		0x04		/* Enable board to host interrupt */
+
+/* SX bootstrap... */
+#define		SX_BOOTSTRAP		"\x28\x20\x21\x02\x60\x0a"
+#define		SX_BOOTSTRAP_SIZE	6
+#define		SX_BOOTSTRAP_ADDR	(0x8000-SX_BOOTSTRAP_SIZE)
+
+/*****************************************************************************
+**********************************          **********************************
+**********************************   EISA   **********************************
+**********************************          **********************************
+*****************************************************************************/
+
+#define		SI2_EISA_OFF	 	0x42
+#define		SI2_EISA_VAL	 	0x01
+#define		SI2_EISA_WINDOW_LEN     0x10000
+
+/*****************************************************************************
+***********************************         **********************************
+***********************************   PCI   **********************************
+***********************************         **********************************
+*****************************************************************************/
+
+/* General definitions... */
+
+#define		SPX_VENDOR_ID		0x11CB		/* Assigned by the PCI SIG */
+#define		SPX_DEVICE_ID		0x4000		/* SI/XIO boards */
+#define		SPX_PLXDEVICE_ID	0x2000		/* SX boards */
+
+#define		SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
+#define		SI2_SUB_SYS_ID		0x400		/* Phase 2 (Z280) board */
+#define		SX_SUB_SYS_ID		0x200		/* Phase 3 (t225) board */
+
+#endif						/*_sxboards_h */
+
+/* End of SXBOARDS.H */
diff --git a/drivers/staging/generic_serial/sxwindow.h b/drivers/staging/generic_serial/sxwindow.h
new file mode 100644
index 0000000..cf01b66
--- /dev/null
+++ b/drivers/staging/generic_serial/sxwindow.h
@@ -0,0 +1,393 @@
+/************************************************************************/
+/*									*/
+/*	Title		:	SX Shared Memory Window Structure	*/
+/*									*/
+/*	Author		:	N.P.Vassallo				*/
+/*									*/
+/*	Creation	:	16th March 1998				*/
+/*									*/
+/*	Version		:	3.0.0					*/
+/*									*/
+/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
+/*									*/
+/*	Description	:	Prototypes, structures and definitions	*/
+/*				describing the SX/SI/XIO cards shared	*/
+/*				memory window structure:		*/
+/*					SXCARD				*/
+/*					SXMODULE			*/
+/*					SXCHANNEL			*/
+/*									*/
+/************************************************************************/
+
+/* History...
+
+3.0.0	16/03/98 NPV	Creation. (based on STRUCT.H)
+
+*/
+
+#ifndef	_sxwindow_h				/* If SXWINDOW.H not already defined */
+#define	_sxwindow_h    1
+
+/*****************************************************************************
+***************************                        ***************************
+***************************   Common Definitions   ***************************
+***************************                        ***************************
+*****************************************************************************/
+
+typedef	struct	_SXCARD		*PSXCARD;	/* SXCARD structure pointer */
+typedef	struct	_SXMODULE	*PMOD;		/* SXMODULE structure pointer */
+typedef	struct	_SXCHANNEL	*PCHAN;		/* SXCHANNEL structure pointer */
+
+/*****************************************************************************
+*********************************            *********************************
+*********************************   SXCARD   *********************************
+*********************************            *********************************
+*****************************************************************************/
+
+typedef	struct	_SXCARD
+{
+	BYTE	cc_init_status;			/* 0x00 Initialisation status */
+	BYTE	cc_mem_size;			/* 0x01 Size of memory on card */
+	WORD	cc_int_count;			/* 0x02 Interrupt count */
+	WORD	cc_revision;			/* 0x04 Download code revision */
+	BYTE	cc_isr_count;			/* 0x06 Count when ISR is run */
+	BYTE	cc_main_count;			/* 0x07 Count when main loop is run */
+	WORD	cc_int_pending;			/* 0x08 Interrupt pending */
+	WORD	cc_poll_count;			/* 0x0A Count when poll is run */
+	BYTE	cc_int_set_count;		/* 0x0C Count when host interrupt is set */
+	BYTE	cc_rfu[0x80 - 0x0D];		/* 0x0D Pad structure to 128 bytes (0x80) */
+
+} SXCARD;
+
+/* SXCARD.cc_init_status definitions... */
+#define 	ADAPTERS_FOUND		(BYTE)0x01
+#define 	NO_ADAPTERS_FOUND	(BYTE)0xFF
+
+/* SXCARD.cc_mem_size definitions... */
+#define 	SX_MEMORY_SIZE		(BYTE)0x40
+
+/* SXCARD.cc_int_count definitions... */
+#define 	INT_COUNT_DEFAULT	100	/* Hz */
+
+/*****************************************************************************
+********************************              ********************************
+********************************   SXMODULE   ********************************
+********************************              ********************************
+*****************************************************************************/
+
+#define	TOP_POINTER(a)		((a)|0x8000)	/* Sets top bit of word */
+#define UNTOP_POINTER(a)	((a)&~0x8000)	/* Clears top bit of word */
+
+typedef	struct	_SXMODULE
+{
+	WORD	mc_next;			/* 0x00 Next module "pointer" (ORed with 0x8000) */
+	BYTE	mc_type;			/* 0x02 Type of TA in terms of number of channels */
+	BYTE	mc_mod_no;			/* 0x03 Module number on SI bus cable (0 closest to card) */
+	BYTE	mc_dtr;				/* 0x04 Private DTR copy (TA only) */
+	BYTE	mc_rfu1;			/* 0x05 Reserved */
+	WORD	mc_uart;			/* 0x06 UART base address for this module */
+	BYTE	mc_chip;			/* 0x08 Chip type / number of ports */
+	BYTE	mc_current_uart;		/* 0x09 Current uart selected for this module */
+#ifdef	DOWNLOAD
+	PCHAN	mc_chan_pointer[8];		/* 0x0A Pointer to each channel structure */
+#else
+	WORD	mc_chan_pointer[8];		/* 0x0A Define as WORD if not compiling into download */
+#endif
+	WORD	mc_rfu2;			/* 0x1A Reserved */
+	BYTE	mc_opens1;			/* 0x1C Number of open ports on first four ports on MTA/SXDC */
+	BYTE	mc_opens2;			/* 0x1D Number of open ports on second four ports on MTA/SXDC */
+	BYTE	mc_mods;			/* 0x1E Types of connector module attached to MTA/SXDC */
+	BYTE	mc_rev1;			/* 0x1F Revision of first CD1400 on MTA/SXDC */
+	BYTE	mc_rev2;			/* 0x20 Revision of second CD1400 on MTA/SXDC */
+	BYTE	mc_mtaasic_rev;			/* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */
+	BYTE	mc_rfu3[0x100 - 0x22];		/* 0x22 Pad structure to 256 bytes (0x100) */
+
+} SXMODULE;
+
+/* SXMODULE.mc_type definitions... */
+#define		FOUR_PORTS	(BYTE)4
+#define 	EIGHT_PORTS	(BYTE)8
+
+/* SXMODULE.mc_chip definitions... */
+#define 	CHIP_MASK	0xF0
+#define		TA		(BYTE)0
+#define 	TA4		(TA | FOUR_PORTS)
+#define 	TA8		(TA | EIGHT_PORTS)
+#define		TA4_ASIC	(BYTE)0x0A
+#define		TA8_ASIC	(BYTE)0x0B
+#define 	MTA_CD1400	(BYTE)0x28
+#define 	SXDC		(BYTE)0x48
+
+/* SXMODULE.mc_mods definitions... */
+#define		MOD_RS232DB25	0x00		/* RS232 DB25 (socket/plug) */
+#define		MOD_RS232RJ45	0x01		/* RS232 RJ45 (shielded/opto-isolated) */
+#define		MOD_RESERVED_2	0x02		/* Reserved (RS485) */
+#define		MOD_RS422DB25	0x03		/* RS422 DB25 Socket */
+#define		MOD_RESERVED_4	0x04		/* Reserved */
+#define		MOD_PARALLEL	0x05		/* Parallel */
+#define		MOD_RESERVED_6	0x06		/* Reserved (RS423) */
+#define		MOD_RESERVED_7	0x07		/* Reserved */
+#define		MOD_2_RS232DB25	0x08		/* Rev 2.0 RS232 DB25 (socket/plug) */
+#define		MOD_2_RS232RJ45	0x09		/* Rev 2.0 RS232 RJ45 */
+#define		MOD_RESERVED_A	0x0A		/* Rev 2.0 Reserved */
+#define		MOD_2_RS422DB25	0x0B		/* Rev 2.0 RS422 DB25 */
+#define		MOD_RESERVED_C	0x0C		/* Rev 2.0 Reserved */
+#define		MOD_2_PARALLEL	0x0D		/* Rev 2.0 Parallel */
+#define		MOD_RESERVED_E	0x0E		/* Rev 2.0 Reserved */
+#define		MOD_BLANK	0x0F		/* Blank Panel */
+
+/*****************************************************************************
+********************************               *******************************
+********************************   SXCHANNEL   *******************************
+********************************               *******************************
+*****************************************************************************/
+
+#define		TX_BUFF_OFFSET		0x60	/* Transmit buffer offset in channel structure */
+#define		BUFF_POINTER(a)		(((a)+TX_BUFF_OFFSET)|0x8000)
+#define		UNBUFF_POINTER(a)	(jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) 
+#define 	BUFFER_SIZE		256
+#define 	HIGH_WATER		((BUFFER_SIZE / 4) * 3)
+#define 	LOW_WATER		(BUFFER_SIZE / 4)
+
+typedef	struct	_SXCHANNEL
+{
+	WORD	next_item;			/* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */
+	WORD 	addr_uart;			/* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */
+	WORD	module;				/* 0x04 Offset from window base of parent SXMODULE structure */
+	BYTE 	type;				/* 0x06 Chip type / number of ports (copy of mc_chip) */
+	BYTE	chan_number;			/* 0x07 Channel number on the TA/MTA/SXDC */
+	WORD	xc_status;			/* 0x08 Flow control and I/O status */
+	BYTE	hi_rxipos;			/* 0x0A Receive buffer input index */
+	BYTE	hi_rxopos;			/* 0x0B Receive buffer output index */
+	BYTE	hi_txopos;			/* 0x0C Transmit buffer output index */
+	BYTE	hi_txipos;			/* 0x0D Transmit buffer input index */
+	BYTE	hi_hstat;			/* 0x0E Command register */
+	BYTE	dtr_bit;			/* 0x0F INTERNAL DTR control byte (TA only) */
+	BYTE	txon;				/* 0x10 INTERNAL copy of hi_txon */
+	BYTE	txoff;				/* 0x11 INTERNAL copy of hi_txoff */
+	BYTE	rxon;				/* 0x12 INTERNAL copy of hi_rxon */
+	BYTE	rxoff;				/* 0x13 INTERNAL copy of hi_rxoff */
+	BYTE	hi_mr1;				/* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/
+	BYTE	hi_mr2;				/* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/
+	BYTE	hi_csr;				/* 0x16 Clock Select Register (baud rate) */
+	BYTE	hi_op;				/* 0x17 Modem Output Signal */
+	BYTE	hi_ip;				/* 0x18 Modem Input Signal */
+	BYTE	hi_state;			/* 0x19 Channel status */
+	BYTE	hi_prtcl;			/* 0x1A Channel protocol (flow control) */
+	BYTE	hi_txon;			/* 0x1B Transmit XON character */
+	BYTE	hi_txoff;			/* 0x1C Transmit XOFF character */
+	BYTE	hi_rxon;			/* 0x1D Receive XON character */
+	BYTE	hi_rxoff;			/* 0x1E Receive XOFF character */
+	BYTE	close_prev;			/* 0x1F INTERNAL channel previously closed flag */
+	BYTE	hi_break;			/* 0x20 Break and error control */
+	BYTE	break_state;			/* 0x21 INTERNAL copy of hi_break */
+	BYTE	hi_mask;			/* 0x22 Mask for received data */
+	BYTE	mask;				/* 0x23 INTERNAL copy of hi_mask */
+	BYTE	mod_type;			/* 0x24 MTA/SXDC hardware module type */
+	BYTE	ccr_state;			/* 0x25 INTERNAL MTA/SXDC state of CCR register */
+	BYTE	ip_mask;			/* 0x26 Input handshake mask */
+	BYTE	hi_parallel;			/* 0x27 Parallel port flag */
+	BYTE	par_error;			/* 0x28 Error code for parallel loopback test */
+	BYTE	any_sent;			/* 0x29 INTERNAL data sent flag */
+	BYTE	asic_txfifo_size;		/* 0x2A INTERNAL SXDC transmit FIFO size */
+	BYTE	rfu1[2];			/* 0x2B Reserved */
+	BYTE	csr;				/* 0x2D INTERNAL copy of hi_csr */
+#ifdef	DOWNLOAD
+	PCHAN	nextp;				/* 0x2E Offset from window base of next channel structure */
+#else
+	WORD	nextp;				/* 0x2E Define as WORD if not compiling into download */
+#endif
+	BYTE	prtcl;				/* 0x30 INTERNAL copy of hi_prtcl */
+	BYTE	mr1;				/* 0x31 INTERNAL copy of hi_mr1 */
+	BYTE	mr2;				/* 0x32 INTERNAL copy of hi_mr2 */
+	BYTE	hi_txbaud;			/* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */
+	BYTE	hi_rxbaud;			/* 0x34 Extended receive baud rate  (SXDC only if((hi_csr&0xF0)==0xF0) */
+	BYTE	txbreak_state;			/* 0x35 INTERNAL MTA/SXDC transmit break state */
+	BYTE	txbaud;				/* 0x36 INTERNAL copy of hi_txbaud */
+	BYTE	rxbaud;				/* 0x37 INTERNAL copy of hi_rxbaud */
+	WORD	err_framing;			/* 0x38 Count of receive framing errors */
+	WORD	err_parity;			/* 0x3A Count of receive parity errors */
+	WORD	err_overrun;			/* 0x3C Count of receive overrun errors */
+	WORD	err_overflow;			/* 0x3E Count of receive buffer overflow errors */
+	BYTE	rfu2[TX_BUFF_OFFSET - 0x40];	/* 0x40 Reserved until hi_txbuf */
+	BYTE	hi_txbuf[BUFFER_SIZE];		/* 0x060 Transmit buffer */
+	BYTE	hi_rxbuf[BUFFER_SIZE];		/* 0x160 Receive buffer */
+	BYTE	rfu3[0x300 - 0x260];		/* 0x260 Reserved until 768 bytes (0x300) */
+
+} SXCHANNEL;
+
+/* SXCHANNEL.addr_uart definitions... */
+#define		FASTPATH	0x1000		/* Set to indicate fast rx/tx processing (TA only) */
+
+/* SXCHANNEL.xc_status definitions... */
+#define		X_TANY		0x0001		/* XON is any character (TA only) */
+#define		X_TION		0x0001		/* Tx interrupts on (MTA only) */
+#define		X_TXEN		0x0002		/* Tx XON/XOFF enabled (TA only) */
+#define		X_RTSEN		0x0002		/* RTS FLOW enabled (MTA only) */
+#define		X_TXRC		0x0004		/* XOFF received (TA only) */
+#define		X_RTSLOW	0x0004		/* RTS dropped (MTA only) */
+#define		X_RXEN		0x0008		/* Rx XON/XOFF enabled */
+#define		X_ANYXO		0x0010		/* XOFF pending/sent or RTS dropped */
+#define		X_RXSE		0x0020		/* Rx XOFF sent */
+#define		X_NPEND		0x0040		/* Rx XON pending or XOFF pending */
+#define		X_FPEND		0x0080		/* Rx XOFF pending */
+#define		C_CRSE		0x0100		/* Carriage return sent (TA only) */
+#define		C_TEMR		0x0100		/* Tx empty requested (MTA only) */
+#define		C_TEMA		0x0200		/* Tx empty acked (MTA only) */
+#define		C_ANYP		0x0200		/* Any protocol bar tx XON/XOFF (TA only) */
+#define		C_EN		0x0400		/* Cooking enabled (on MTA means port is also || */
+#define		C_HIGH		0x0800		/* Buffer previously hit high water */
+#define		C_CTSEN		0x1000		/* CTS automatic flow-control enabled */
+#define		C_DCDEN		0x2000		/* DCD/DTR checking enabled */
+#define		C_BREAK		0x4000		/* Break detected */
+#define		C_RTSEN		0x8000		/* RTS automatic flow control enabled (MTA only) */
+#define		C_PARITY	0x8000		/* Parity checking enabled (TA only) */
+
+/* SXCHANNEL.hi_hstat definitions... */
+#define		HS_IDLE_OPEN	0x00		/* Channel open state */
+#define		HS_LOPEN	0x02		/* Local open command (no modem monitoring) */
+#define		HS_MOPEN	0x04		/* Modem open command (wait for DCD signal) */
+#define		HS_IDLE_MPEND	0x06		/* Waiting for DCD signal state */
+#define		HS_CONFIG	0x08		/* Configuration command */
+#define		HS_CLOSE	0x0A		/* Close command */
+#define		HS_START	0x0C		/* Start transmit break command */
+#define		HS_STOP		0x0E		/* Stop transmit break command */
+#define		HS_IDLE_CLOSED	0x10		/* Closed channel state */
+#define		HS_IDLE_BREAK	0x12		/* Transmit break state */
+#define		HS_FORCE_CLOSED	0x14		/* Force close command */
+#define		HS_RESUME	0x16		/* Clear pending XOFF command */
+#define		HS_WFLUSH	0x18		/* Flush transmit buffer command */
+#define		HS_RFLUSH	0x1A		/* Flush receive buffer command */
+#define		HS_SUSPEND	0x1C		/* Suspend output command (like XOFF received) */
+#define		PARALLEL	0x1E		/* Parallel port loopback test command (Diagnostics Only) */
+#define		ENABLE_RX_INTS	0x20		/* Enable receive interrupts command (Diagnostics Only) */
+#define		ENABLE_TX_INTS	0x22		/* Enable transmit interrupts command (Diagnostics Only) */
+#define		ENABLE_MDM_INTS	0x24		/* Enable modem interrupts command (Diagnostics Only) */
+#define		DISABLE_INTS	0x26		/* Disable interrupts command (Diagnostics Only) */
+
+/* SXCHANNEL.hi_mr1 definitions... */
+#define		MR1_BITS	0x03		/* Data bits mask */
+#define		MR1_5_BITS	0x00		/* 5 data bits */
+#define		MR1_6_BITS	0x01		/* 6 data bits */
+#define		MR1_7_BITS	0x02		/* 7 data bits */
+#define		MR1_8_BITS	0x03		/* 8 data bits */
+#define		MR1_PARITY	0x1C		/* Parity mask */
+#define		MR1_ODD		0x04		/* Odd parity */
+#define		MR1_EVEN	0x00		/* Even parity */
+#define		MR1_WITH	0x00		/* Parity enabled */
+#define		MR1_FORCE	0x08		/* Force parity */
+#define		MR1_NONE	0x10		/* No parity */
+#define		MR1_NOPARITY	MR1_NONE		/* No parity */
+#define		MR1_ODDPARITY	(MR1_WITH|MR1_ODD)	/* Odd parity */
+#define		MR1_EVENPARITY	(MR1_WITH|MR1_EVEN)	/* Even parity */
+#define		MR1_MARKPARITY	(MR1_FORCE|MR1_ODD)	/* Mark parity */
+#define		MR1_SPACEPARITY	(MR1_FORCE|MR1_EVEN)	/* Space parity */
+#define		MR1_RTS_RXFLOW	0x80		/* RTS receive flow control */
+
+/* SXCHANNEL.hi_mr2 definitions... */
+#define		MR2_STOP	0x0F		/* Stop bits mask */
+#define		MR2_1_STOP	0x07		/* 1 stop bit */
+#define		MR2_2_STOP	0x0F		/* 2 stop bits */
+#define		MR2_CTS_TXFLOW	0x10		/* CTS transmit flow control */
+#define		MR2_RTS_TOGGLE	0x20		/* RTS toggle on transmit */
+#define		MR2_NORMAL	0x00		/* Normal mode */
+#define		MR2_AUTO	0x40		/* Auto-echo mode (TA only) */
+#define		MR2_LOCAL	0x80		/* Local echo mode */
+#define		MR2_REMOTE	0xC0		/* Remote echo mode (TA only) */
+
+/* SXCHANNEL.hi_csr definitions... */
+#define		CSR_75		0x0		/*    75 baud */
+#define		CSR_110		0x1		/*   110 baud (TA), 115200 (MTA/SXDC) */
+#define		CSR_38400	0x2		/* 38400 baud */
+#define		CSR_150		0x3		/*   150 baud */
+#define		CSR_300		0x4		/*   300 baud */
+#define		CSR_600		0x5		/*   600 baud */
+#define		CSR_1200	0x6		/*  1200 baud */
+#define		CSR_2000	0x7		/*  2000 baud */
+#define		CSR_2400	0x8		/*  2400 baud */
+#define		CSR_4800	0x9		/*  4800 baud */
+#define		CSR_1800	0xA		/*  1800 baud */
+#define		CSR_9600	0xB		/*  9600 baud */
+#define		CSR_19200	0xC		/* 19200 baud */
+#define		CSR_57600	0xD		/* 57600 baud */
+#define		CSR_EXTBAUD	0xF		/* Extended baud rate (hi_txbaud/hi_rxbaud) */
+
+/* SXCHANNEL.hi_op definitions... */
+#define		OP_RTS		0x01		/* RTS modem output signal */
+#define		OP_DTR		0x02		/* DTR modem output signal */
+
+/* SXCHANNEL.hi_ip definitions... */
+#define		IP_CTS		0x02		/* CTS modem input signal */
+#define		IP_DCD		0x04		/* DCD modem input signal */
+#define		IP_DSR		0x20		/* DTR modem input signal */
+#define		IP_RI		0x40		/* RI modem input signal */
+
+/* SXCHANNEL.hi_state definitions... */
+#define		ST_BREAK	0x01		/* Break received (clear with config) */
+#define		ST_DCD		0x02		/* DCD signal changed state */
+
+/* SXCHANNEL.hi_prtcl definitions... */
+#define		SP_TANY		0x01		/* Transmit XON/XANY (if SP_TXEN enabled) */
+#define		SP_TXEN		0x02		/* Transmit XON/XOFF flow control */
+#define		SP_CEN		0x04		/* Cooking enabled */
+#define		SP_RXEN		0x08		/* Rx XON/XOFF enabled */
+#define		SP_DCEN		0x20		/* DCD / DTR check */
+#define		SP_DTR_RXFLOW	0x40		/* DTR receive flow control */
+#define		SP_PAEN		0x80		/* Parity checking enabled */
+
+/* SXCHANNEL.hi_break definitions... */
+#define		BR_IGN		0x01		/* Ignore any received breaks */
+#define		BR_INT		0x02		/* Interrupt on received break */
+#define		BR_PARMRK	0x04		/* Enable parmrk parity error processing */
+#define		BR_PARIGN	0x08		/* Ignore chars with parity errors */
+#define 	BR_ERRINT	0x80		/* Treat parity/framing/overrun errors as exceptions */
+
+/* SXCHANNEL.par_error definitions.. */
+#define		DIAG_IRQ_RX	0x01		/* Indicate serial receive interrupt (diags only) */
+#define		DIAG_IRQ_TX	0x02		/* Indicate serial transmit interrupt (diags only) */
+#define		DIAG_IRQ_MD	0x04		/* Indicate serial modem interrupt (diags only) */
+
+/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */
+#define		BAUD_75		0x00		/*     75 baud */
+#define		BAUD_115200	0x01		/* 115200 baud */
+#define		BAUD_38400	0x02		/*  38400 baud */
+#define		BAUD_150	0x03		/*    150 baud */
+#define		BAUD_300	0x04		/*    300 baud */
+#define		BAUD_600	0x05		/*    600 baud */
+#define		BAUD_1200	0x06		/*   1200 baud */
+#define		BAUD_2000	0x07		/*   2000 baud */
+#define		BAUD_2400	0x08		/*   2400 baud */
+#define		BAUD_4800	0x09		/*   4800 baud */
+#define		BAUD_1800	0x0A		/*   1800 baud */
+#define		BAUD_9600	0x0B		/*   9600 baud */
+#define		BAUD_19200	0x0C		/*  19200 baud */
+#define		BAUD_57600	0x0D		/*  57600 baud */
+#define		BAUD_230400	0x0E		/* 230400 baud */
+#define		BAUD_460800	0x0F		/* 460800 baud */
+#define		BAUD_921600	0x10		/* 921600 baud */
+#define		BAUD_50		0x11    	/*     50 baud */
+#define		BAUD_110	0x12		/*    110 baud */
+#define		BAUD_134_5	0x13		/*  134.5 baud */
+#define		BAUD_200	0x14		/*    200 baud */
+#define		BAUD_7200	0x15		/*   7200 baud */
+#define		BAUD_56000	0x16		/*  56000 baud */
+#define		BAUD_64000	0x17		/*  64000 baud */
+#define		BAUD_76800	0x18		/*  76800 baud */
+#define		BAUD_128000	0x19		/* 128000 baud */
+#define		BAUD_150000	0x1A		/* 150000 baud */
+#define		BAUD_14400	0x1B		/*  14400 baud */
+#define		BAUD_256000	0x1C		/* 256000 baud */
+#define		BAUD_28800	0x1D		/*  28800 baud */
+
+/* SXCHANNEL.txbreak_state definiions... */
+#define		TXBREAK_OFF	0		/* Not sending break */
+#define		TXBREAK_START	1		/* Begin sending break */
+#define		TXBREAK_START1	2		/* Begin sending break, part 1 */
+#define		TXBREAK_ON	3		/* Sending break */
+#define		TXBREAK_STOP	4		/* Stop sending break */
+#define		TXBREAK_STOP1	5		/* Stop sending break, part 1 */
+
+#endif						/* _sxwindow_h */
+
+/* End of SXWINDOW.H */
+
diff --git a/drivers/staging/generic_serial/vme_scc.c b/drivers/staging/generic_serial/vme_scc.c
new file mode 100644
index 0000000..9683864
--- /dev/null
+++ b/drivers/staging/generic_serial/vme_scc.c
@@ -0,0 +1,1145 @@
+/*
+ * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
+ * implementation.
+ * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
+ *
+ * Based on atari_SCC.c which was
+ *   Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kdev_t.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <asm/setup.h>
+#include <asm/bootinfo.h>
+
+#ifdef CONFIG_MVME147_SCC
+#include <asm/mvme147hw.h>
+#endif
+#ifdef CONFIG_MVME162_SCC
+#include <asm/mvme16xhw.h>
+#endif
+#ifdef CONFIG_BVME6000_SCC
+#include <asm/bvme6000hw.h>
+#endif
+
+#include <linux/generic_serial.h>
+#include "scc.h"
+
+
+#define CHANNEL_A	0
+#define CHANNEL_B	1
+
+#define SCC_MINOR_BASE	64
+
+/* Shadows for all SCC write registers */
+static unsigned char scc_shadow[2][16];
+
+/* Location to access for SCC register access delay */
+static volatile unsigned char *scc_del = NULL;
+
+/* To keep track of STATUS_REG state for detection of Ext/Status int source */
+static unsigned char scc_last_status_reg[2];
+
+/***************************** Prototypes *****************************/
+
+/* Function prototypes */
+static void scc_disable_tx_interrupts(void * ptr);
+static void scc_enable_tx_interrupts(void * ptr);
+static void scc_disable_rx_interrupts(void * ptr);
+static void scc_enable_rx_interrupts(void * ptr);
+static int  scc_carrier_raised(struct tty_port *port);
+static void scc_shutdown_port(void * ptr);
+static int scc_set_real_termios(void  *ptr);
+static void scc_hungup(void  *ptr);
+static void scc_close(void  *ptr);
+static int scc_chars_in_buffer(void * ptr);
+static int scc_open(struct tty_struct * tty, struct file * filp);
+static int scc_ioctl(struct tty_struct * tty,
+                     unsigned int cmd, unsigned long arg);
+static void scc_throttle(struct tty_struct *tty);
+static void scc_unthrottle(struct tty_struct *tty);
+static irqreturn_t scc_tx_int(int irq, void *data);
+static irqreturn_t scc_rx_int(int irq, void *data);
+static irqreturn_t scc_stat_int(int irq, void *data);
+static irqreturn_t scc_spcond_int(int irq, void *data);
+static void scc_setsignals(struct scc_port *port, int dtr, int rts);
+static int scc_break_ctl(struct tty_struct *tty, int break_state);
+
+static struct tty_driver *scc_driver;
+
+static struct scc_port scc_ports[2];
+
+/*---------------------------------------------------------------------------
+ * Interface from generic_serial.c back here
+ *--------------------------------------------------------------------------*/
+
+static struct real_driver scc_real_driver = {
+        scc_disable_tx_interrupts,
+        scc_enable_tx_interrupts,
+        scc_disable_rx_interrupts,
+        scc_enable_rx_interrupts,
+        scc_shutdown_port,
+        scc_set_real_termios,
+        scc_chars_in_buffer,
+        scc_close,
+        scc_hungup,
+        NULL
+};
+
+
+static const struct tty_operations scc_ops = {
+	.open	= scc_open,
+	.close = gs_close,
+	.write = gs_write,
+	.put_char = gs_put_char,
+	.flush_chars = gs_flush_chars,
+	.write_room = gs_write_room,
+	.chars_in_buffer = gs_chars_in_buffer,
+	.flush_buffer = gs_flush_buffer,
+	.ioctl = scc_ioctl,
+	.throttle = scc_throttle,
+	.unthrottle = scc_unthrottle,
+	.set_termios = gs_set_termios,
+	.stop = gs_stop,
+	.start = gs_start,
+	.hangup = gs_hangup,
+	.break_ctl = scc_break_ctl,
+};
+
+static const struct tty_port_operations scc_port_ops = {
+	.carrier_raised = scc_carrier_raised,
+};
+
+/*----------------------------------------------------------------------------
+ * vme_scc_init() and support functions
+ *---------------------------------------------------------------------------*/
+
+static int __init scc_init_drivers(void)
+{
+	int error;
+
+	scc_driver = alloc_tty_driver(2);
+	if (!scc_driver)
+		return -ENOMEM;
+	scc_driver->owner = THIS_MODULE;
+	scc_driver->driver_name = "scc";
+	scc_driver->name = "ttyS";
+	scc_driver->major = TTY_MAJOR;
+	scc_driver->minor_start = SCC_MINOR_BASE;
+	scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	scc_driver->subtype = SERIAL_TYPE_NORMAL;
+	scc_driver->init_termios = tty_std_termios;
+	scc_driver->init_termios.c_cflag =
+	  B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	scc_driver->init_termios.c_ispeed = 9600;
+	scc_driver->init_termios.c_ospeed = 9600;
+	scc_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(scc_driver, &scc_ops);
+
+	if ((error = tty_register_driver(scc_driver))) {
+		printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
+		       error);
+		put_tty_driver(scc_driver);
+		return 1;
+	}
+
+	return 0;
+}
+
+
+/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
+ */
+
+static void __init scc_init_portstructs(void)
+{
+	struct scc_port *port;
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		port = scc_ports + i;
+		tty_port_init(&port->gs.port);
+		port->gs.port.ops = &scc_port_ops;
+		port->gs.magic = SCC_MAGIC;
+		port->gs.close_delay = HZ/2;
+		port->gs.closing_wait = 30 * HZ;
+		port->gs.rd = &scc_real_driver;
+#ifdef NEW_WRITE_LOCKING
+		port->gs.port_write_mutex = MUTEX;
+#endif
+		init_waitqueue_head(&port->gs.port.open_wait);
+		init_waitqueue_head(&port->gs.port.close_wait);
+	}
+}
+
+
+#ifdef CONFIG_MVME147_SCC
+static int __init mvme147_scc_init(void)
+{
+	struct scc_port *port;
+	int error;
+
+	printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
+	/* Init channel A */
+	port = &scc_ports[0];
+	port->channel = CHANNEL_A;
+	port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
+	port->datap = port->ctrlp + 1;
+	port->port_a = &scc_ports[0];
+	port->port_b = &scc_ports[1];
+	error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+		            "SCC-A TX", port);
+	if (error)
+		goto fail;
+	error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+		            "SCC-A status", port);
+	if (error)
+		goto fail_free_a_tx;
+	error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+		            "SCC-A RX", port);
+	if (error)
+		goto fail_free_a_stat;
+	error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
+			    IRQF_DISABLED, "SCC-A special cond", port);
+	if (error)
+		goto fail_free_a_rx;
+
+	{
+		SCC_ACCESS_INIT(port);
+
+		/* disable interrupts for this channel */
+		SCCwrite(INT_AND_DMA_REG, 0);
+		/* Set the interrupt vector */
+		SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
+		/* Interrupt parameters: vector includes status, status low */
+		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
+		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
+	}
+
+	/* Init channel B */
+	port = &scc_ports[1];
+	port->channel = CHANNEL_B;
+	port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
+	port->datap = port->ctrlp + 1;
+	port->port_a = &scc_ports[0];
+	port->port_b = &scc_ports[1];
+	error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+		            "SCC-B TX", port);
+	if (error)
+		goto fail_free_a_spcond;
+	error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+		            "SCC-B status", port);
+	if (error)
+		goto fail_free_b_tx;
+	error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+		            "SCC-B RX", port);
+	if (error)
+		goto fail_free_b_stat;
+	error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
+			    IRQF_DISABLED, "SCC-B special cond", port);
+	if (error)
+		goto fail_free_b_rx;
+
+	{
+		SCC_ACCESS_INIT(port);
+
+		/* disable interrupts for this channel */
+		SCCwrite(INT_AND_DMA_REG, 0);
+	}
+
+        /* Ensure interrupts are enabled in the PCC chip */
+        m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
+
+	/* Initialise the tty driver structures and register */
+	scc_init_portstructs();
+	scc_init_drivers();
+
+	return 0;
+
+fail_free_b_rx:
+	free_irq(MVME147_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+	free_irq(MVME147_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+	free_irq(MVME147_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+	free_irq(MVME147_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+	free_irq(MVME147_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+	free_irq(MVME147_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+	free_irq(MVME147_IRQ_SCCA_TX, port);
+fail:
+	return error;
+}
+#endif
+
+
+#ifdef CONFIG_MVME162_SCC
+static int __init mvme162_scc_init(void)
+{
+	struct scc_port *port;
+	int error;
+
+	if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
+		return (-ENODEV);
+
+	printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
+	/* Init channel A */
+	port = &scc_ports[0];
+	port->channel = CHANNEL_A;
+	port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
+	port->datap = port->ctrlp + 2;
+	port->port_a = &scc_ports[0];
+	port->port_b = &scc_ports[1];
+	error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+		            "SCC-A TX", port);
+	if (error)
+		goto fail;
+	error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+		            "SCC-A status", port);
+	if (error)
+		goto fail_free_a_tx;
+	error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+		            "SCC-A RX", port);
+	if (error)
+		goto fail_free_a_stat;
+	error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
+			    IRQF_DISABLED, "SCC-A special cond", port);
+	if (error)
+		goto fail_free_a_rx;
+
+	{
+		SCC_ACCESS_INIT(port);
+
+		/* disable interrupts for this channel */
+		SCCwrite(INT_AND_DMA_REG, 0);
+		/* Set the interrupt vector */
+		SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
+		/* Interrupt parameters: vector includes status, status low */
+		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
+		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
+	}
+
+	/* Init channel B */
+	port = &scc_ports[1];
+	port->channel = CHANNEL_B;
+	port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
+	port->datap = port->ctrlp + 2;
+	port->port_a = &scc_ports[0];
+	port->port_b = &scc_ports[1];
+	error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+		            "SCC-B TX", port);
+	if (error)
+		goto fail_free_a_spcond;
+	error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+		            "SCC-B status", port);
+	if (error)
+		goto fail_free_b_tx;
+	error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+		            "SCC-B RX", port);
+	if (error)
+		goto fail_free_b_stat;
+	error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
+			    IRQF_DISABLED, "SCC-B special cond", port);
+	if (error)
+		goto fail_free_b_rx;
+
+	{
+		SCC_ACCESS_INIT(port);	/* Either channel will do */
+
+		/* disable interrupts for this channel */
+		SCCwrite(INT_AND_DMA_REG, 0);
+	}
+
+        /* Ensure interrupts are enabled in the MC2 chip */
+        *(volatile char *)0xfff4201d = 0x14;
+
+	/* Initialise the tty driver structures and register */
+	scc_init_portstructs();
+	scc_init_drivers();
+
+	return 0;
+
+fail_free_b_rx:
+	free_irq(MVME162_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+	free_irq(MVME162_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+	free_irq(MVME162_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+	free_irq(MVME162_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+	free_irq(MVME162_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+	free_irq(MVME162_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+	free_irq(MVME162_IRQ_SCCA_TX, port);
+fail:
+	return error;
+}
+#endif
+
+
+#ifdef CONFIG_BVME6000_SCC
+static int __init bvme6000_scc_init(void)
+{
+	struct scc_port *port;
+	int error;
+
+	printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
+	/* Init channel A */
+	port = &scc_ports[0];
+	port->channel = CHANNEL_A;
+	port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
+	port->datap = port->ctrlp + 4;
+	port->port_a = &scc_ports[0];
+	port->port_b = &scc_ports[1];
+	error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
+		            "SCC-A TX", port);
+	if (error)
+		goto fail;
+	error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
+		            "SCC-A status", port);
+	if (error)
+		goto fail_free_a_tx;
+	error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
+		            "SCC-A RX", port);
+	if (error)
+		goto fail_free_a_stat;
+	error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
+			    IRQF_DISABLED, "SCC-A special cond", port);
+	if (error)
+		goto fail_free_a_rx;
+
+	{
+		SCC_ACCESS_INIT(port);
+
+		/* disable interrupts for this channel */
+		SCCwrite(INT_AND_DMA_REG, 0);
+		/* Set the interrupt vector */
+		SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
+		/* Interrupt parameters: vector includes status, status low */
+		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
+		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
+	}
+
+	/* Init channel B */
+	port = &scc_ports[1];
+	port->channel = CHANNEL_B;
+	port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
+	port->datap = port->ctrlp + 4;
+	port->port_a = &scc_ports[0];
+	port->port_b = &scc_ports[1];
+	error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
+		            "SCC-B TX", port);
+	if (error)
+		goto fail_free_a_spcond;
+	error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
+		            "SCC-B status", port);
+	if (error)
+		goto fail_free_b_tx;
+	error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
+		            "SCC-B RX", port);
+	if (error)
+		goto fail_free_b_stat;
+	error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
+			    IRQF_DISABLED, "SCC-B special cond", port);
+	if (error)
+		goto fail_free_b_rx;
+
+	{
+		SCC_ACCESS_INIT(port);	/* Either channel will do */
+
+		/* disable interrupts for this channel */
+		SCCwrite(INT_AND_DMA_REG, 0);
+	}
+
+	/* Initialise the tty driver structures and register */
+	scc_init_portstructs();
+	scc_init_drivers();
+
+	return 0;
+
+fail:
+	free_irq(BVME_IRQ_SCCA_STAT, port);
+fail_free_a_tx:
+	free_irq(BVME_IRQ_SCCA_RX, port);
+fail_free_a_stat:
+	free_irq(BVME_IRQ_SCCA_SPCOND, port);
+fail_free_a_rx:
+	free_irq(BVME_IRQ_SCCB_TX, port);
+fail_free_a_spcond:
+	free_irq(BVME_IRQ_SCCB_STAT, port);
+fail_free_b_tx:
+	free_irq(BVME_IRQ_SCCB_RX, port);
+fail_free_b_stat:
+	free_irq(BVME_IRQ_SCCB_SPCOND, port);
+fail_free_b_rx:
+	return error;
+}
+#endif
+
+
+static int __init vme_scc_init(void)
+{
+	int res = -ENODEV;
+
+#ifdef CONFIG_MVME147_SCC
+	if (MACH_IS_MVME147)
+		res = mvme147_scc_init();
+#endif
+#ifdef CONFIG_MVME162_SCC
+	if (MACH_IS_MVME16x)
+		res = mvme162_scc_init();
+#endif
+#ifdef CONFIG_BVME6000_SCC
+	if (MACH_IS_BVME6000)
+		res = bvme6000_scc_init();
+#endif
+	return res;
+}
+
+module_init(vme_scc_init);
+
+
+/*---------------------------------------------------------------------------
+ * Interrupt handlers
+ *--------------------------------------------------------------------------*/
+
+static irqreturn_t scc_rx_int(int irq, void *data)
+{
+	unsigned char	ch;
+	struct scc_port *port = data;
+	struct tty_struct *tty = port->gs.port.tty;
+	SCC_ACCESS_INIT(port);
+
+	ch = SCCread_NB(RX_DATA_REG);
+	if (!tty) {
+		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
+		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+		return IRQ_HANDLED;
+	}
+	tty_insert_flip_char(tty, ch, 0);
+
+	/* Check if another character is already ready; in that case, the
+	 * spcond_int() function must be used, because this character may have an
+	 * error condition that isn't signalled by the interrupt vector used!
+	 */
+	if (SCCread(INT_PENDING_REG) &
+	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
+		scc_spcond_int (irq, data);
+		return IRQ_HANDLED;
+	}
+
+	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+
+	tty_flip_buffer_push(tty);
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t scc_spcond_int(int irq, void *data)
+{
+	struct scc_port *port = data;
+	struct tty_struct *tty = port->gs.port.tty;
+	unsigned char	stat, ch, err;
+	int		int_pending_mask = port->channel == CHANNEL_A ?
+			                   IPR_A_RX : IPR_B_RX;
+	SCC_ACCESS_INIT(port);
+	
+	if (!tty) {
+		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
+		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
+		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+		return IRQ_HANDLED;
+	}
+	do {
+		stat = SCCread(SPCOND_STATUS_REG);
+		ch = SCCread_NB(RX_DATA_REG);
+
+		if (stat & SCSR_RX_OVERRUN)
+			err = TTY_OVERRUN;
+		else if (stat & SCSR_PARITY_ERR)
+			err = TTY_PARITY;
+		else if (stat & SCSR_CRC_FRAME_ERR)
+			err = TTY_FRAME;
+		else
+			err = 0;
+
+		tty_insert_flip_char(tty, ch, err);
+
+		/* ++TeSche: *All* errors have to be cleared manually,
+		 * else the condition persists for the next chars
+		 */
+		if (err)
+		  SCCwrite(COMMAND_REG, CR_ERROR_RESET);
+
+	} while(SCCread(INT_PENDING_REG) & int_pending_mask);
+
+	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+
+	tty_flip_buffer_push(tty);
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t scc_tx_int(int irq, void *data)
+{
+	struct scc_port *port = data;
+	SCC_ACCESS_INIT(port);
+
+	if (!port->gs.port.tty) {
+		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
+		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
+		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+		return IRQ_HANDLED;
+	}
+	while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
+		if (port->x_char) {
+			SCCwrite(TX_DATA_REG, port->x_char);
+			port->x_char = 0;
+		}
+		else if ((port->gs.xmit_cnt <= 0) ||
+			 port->gs.port.tty->stopped ||
+			 port->gs.port.tty->hw_stopped)
+			break;
+		else {
+			SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
+			port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
+			if (--port->gs.xmit_cnt <= 0)
+				break;
+		}
+	}
+	if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
+	    port->gs.port.tty->hw_stopped) {
+		/* disable tx interrupts */
+		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
+		port->gs.port.flags &= ~GS_TX_INTEN;
+	}
+	if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
+		tty_wakeup(port->gs.port.tty);
+
+	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t scc_stat_int(int irq, void *data)
+{
+	struct scc_port *port = data;
+	unsigned channel = port->channel;
+	unsigned char	last_sr, sr, changed;
+	SCC_ACCESS_INIT(port);
+
+	last_sr = scc_last_status_reg[channel];
+	sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
+	changed = last_sr ^ sr;
+
+	if (changed & SR_DCD) {
+		port->c_dcd = !!(sr & SR_DCD);
+		if (!(port->gs.port.flags & ASYNC_CHECK_CD))
+			;	/* Don't report DCD changes */
+		else if (port->c_dcd) {
+			wake_up_interruptible(&port->gs.port.open_wait);
+		}
+		else {
+			if (port->gs.port.tty)
+				tty_hangup (port->gs.port.tty);
+		}
+	}
+	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
+	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+	return IRQ_HANDLED;
+}
+
+
+/*---------------------------------------------------------------------------
+ * generic_serial.c callback funtions
+ *--------------------------------------------------------------------------*/
+
+static void scc_disable_tx_interrupts(void *ptr)
+{
+	struct scc_port *port = ptr;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	local_irq_save(flags);
+	SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+	port->gs.port.flags &= ~GS_TX_INTEN;
+	local_irq_restore(flags);
+}
+
+
+static void scc_enable_tx_interrupts(void *ptr)
+{
+	struct scc_port *port = ptr;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	local_irq_save(flags);
+	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
+	/* restart the transmitter */
+	scc_tx_int (0, port);
+	local_irq_restore(flags);
+}
+
+
+static void scc_disable_rx_interrupts(void *ptr)
+{
+	struct scc_port *port = ptr;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	local_irq_save(flags);
+	SCCmod(INT_AND_DMA_REG,
+	    ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
+	local_irq_restore(flags);
+}
+
+
+static void scc_enable_rx_interrupts(void *ptr)
+{
+	struct scc_port *port = ptr;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	local_irq_save(flags);
+	SCCmod(INT_AND_DMA_REG, 0xff,
+		IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
+	local_irq_restore(flags);
+}
+
+
+static int scc_carrier_raised(struct tty_port *port)
+{
+	struct scc_port *sc = container_of(port, struct scc_port, gs.port);
+	unsigned channel = sc->channel;
+
+	return !!(scc_last_status_reg[channel] & SR_DCD);
+}
+
+
+static void scc_shutdown_port(void *ptr)
+{
+	struct scc_port *port = ptr;
+
+	port->gs.port.flags &= ~ GS_ACTIVE;
+	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
+		scc_setsignals (port, 0, 0);
+	}
+}
+
+
+static int scc_set_real_termios (void *ptr)
+{
+	/* the SCC has char sizes 5,7,6,8 in that order! */
+	static int chsize_map[4] = { 0, 2, 1, 3 };
+	unsigned cflag, baud, chsize, channel, brgval = 0;
+	unsigned long flags;
+	struct scc_port *port = ptr;
+	SCC_ACCESS_INIT(port);
+
+	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
+
+	channel = port->channel;
+
+	if (channel == CHANNEL_A)
+		return 0;		/* Settings controlled by boot PROM */
+
+	cflag  = port->gs.port.tty->termios->c_cflag;
+	baud = port->gs.baud;
+	chsize = (cflag & CSIZE) >> 4;
+
+	if (baud == 0) {
+		/* speed == 0 -> drop DTR */
+		local_irq_save(flags);
+		SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
+		local_irq_restore(flags);
+		return 0;
+	}
+	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
+		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
+		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
+		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
+		return 0;
+	}
+
+	if (cflag & CLOCAL)
+		port->gs.port.flags &= ~ASYNC_CHECK_CD;
+	else
+		port->gs.port.flags |= ASYNC_CHECK_CD;
+
+#ifdef CONFIG_MVME147_SCC
+	if (MACH_IS_MVME147)
+		brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
+#endif
+#ifdef CONFIG_MVME162_SCC
+	if (MACH_IS_MVME16x)
+		brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
+#endif
+#ifdef CONFIG_BVME6000_SCC
+	if (MACH_IS_BVME6000)
+		brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
+#endif
+	/* Now we have all parameters and can go to set them: */
+	local_irq_save(flags);
+
+	/* receiver's character size and auto-enables */
+	SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
+			(chsize_map[chsize] << 6) |
+			((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
+	/* parity and stop bits (both, Tx and Rx), clock mode never changes */
+	SCCmod (AUX1_CTRL_REG,
+		~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
+		((cflag & PARENB
+		  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
+		  : A1CR_PARITY_NONE)
+		 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
+	/* sender's character size, set DTR for valid baud rate */
+	SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
+	/* clock sources never change */
+	/* disable BRG before changing the value */
+	SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
+	/* BRG value */
+	SCCwrite(TIMER_LOW_REG, brgval & 0xff);
+	SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
+	/* BRG enable, and clock source never changes */
+	SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
+
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+
+static int scc_chars_in_buffer (void *ptr)
+{
+	struct scc_port *port = ptr;
+	SCC_ACCESS_INIT(port);
+
+	return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
+}
+
+
+/* Comment taken from sx.c (2.4.0):
+   I haven't the foggiest why the decrement use count has to happen
+   here. The whole linux serial drivers stuff needs to be redesigned.
+   My guess is that this is a hack to minimize the impact of a bug
+   elsewhere. Thinking about it some more. (try it sometime) Try
+   running minicom on a serial port that is driven by a modularized
+   driver. Have the modem hangup. Then remove the driver module. Then
+   exit minicom.  I expect an "oops".  -- REW */
+
+static void scc_hungup(void *ptr)
+{
+	scc_disable_tx_interrupts(ptr);
+	scc_disable_rx_interrupts(ptr);
+}
+
+
+static void scc_close(void *ptr)
+{
+	scc_disable_tx_interrupts(ptr);
+	scc_disable_rx_interrupts(ptr);
+}
+
+
+/*---------------------------------------------------------------------------
+ * Internal support functions
+ *--------------------------------------------------------------------------*/
+
+static void scc_setsignals(struct scc_port *port, int dtr, int rts)
+{
+	unsigned long flags;
+	unsigned char t;
+	SCC_ACCESS_INIT(port);
+
+	local_irq_save(flags);
+	t = SCCread(TX_CTRL_REG);
+	if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
+	if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
+	SCCwrite(TX_CTRL_REG, t);
+	local_irq_restore(flags);
+}
+
+
+static void scc_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct scc_port *port = tty->driver_data;
+
+	port->x_char = ch;
+	if (ch)
+		scc_enable_tx_interrupts(port);
+}
+
+
+/*---------------------------------------------------------------------------
+ * Driver entrypoints referenced from above
+ *--------------------------------------------------------------------------*/
+
+static int scc_open (struct tty_struct * tty, struct file * filp)
+{
+	int line = tty->index;
+	int retval;
+	struct scc_port *port = &scc_ports[line];
+	int i, channel = port->channel;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
+	static const struct {
+		unsigned reg, val;
+	} mvme_init_tab[] = {
+		/* Values for MVME162 and MVME147 */
+		/* no parity, 1 stop bit, async, 1:16 */
+		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
+		/* parity error is special cond, ints disabled, no DMA */
+		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
+		/* Rx 8 bits/char, no auto enable, Rx off */
+		{ RX_CTRL_REG, RCR_CHSIZE_8 },
+		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
+		{ TX_CTRL_REG, TCR_CHSIZE_8 },
+		/* special features off */
+		{ AUX2_CTRL_REG, 0 },
+		{ CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
+		{ DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
+		/* Start Rx */
+		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
+		/* Start Tx */
+		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
+		/* Ext/Stat ints: DCD only */
+		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
+		/* Reset Ext/Stat ints */
+		{ COMMAND_REG, CR_EXTSTAT_RESET },
+		/* ...again */
+		{ COMMAND_REG, CR_EXTSTAT_RESET },
+	};
+#endif
+#if defined(CONFIG_BVME6000_SCC)
+	static const struct {
+		unsigned reg, val;
+	} bvme_init_tab[] = {
+		/* Values for BVME6000 */
+		/* no parity, 1 stop bit, async, 1:16 */
+		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
+		/* parity error is special cond, ints disabled, no DMA */
+		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
+		/* Rx 8 bits/char, no auto enable, Rx off */
+		{ RX_CTRL_REG, RCR_CHSIZE_8 },
+		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
+		{ TX_CTRL_REG, TCR_CHSIZE_8 },
+		/* special features off */
+		{ AUX2_CTRL_REG, 0 },
+		{ CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
+		{ DPLL_CTRL_REG, DCR_BRG_ENAB },
+		/* Start Rx */
+		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
+		/* Start Tx */
+		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
+		/* Ext/Stat ints: DCD only */
+		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
+		/* Reset Ext/Stat ints */
+		{ COMMAND_REG, CR_EXTSTAT_RESET },
+		/* ...again */
+		{ COMMAND_REG, CR_EXTSTAT_RESET },
+	};
+#endif
+	if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
+		local_irq_save(flags);
+#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
+		if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
+			for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
+				SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
+		}
+#endif
+#if defined(CONFIG_BVME6000_SCC)
+		if (MACH_IS_BVME6000) {
+			for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
+				SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
+		}
+#endif
+
+		/* remember status register for detection of DCD and CTS changes */
+		scc_last_status_reg[channel] = SCCread(STATUS_REG);
+
+		port->c_dcd = 0;	/* Prevent initial 1->0 interrupt */
+		scc_setsignals (port, 1,1);
+		local_irq_restore(flags);
+	}
+
+	tty->driver_data = port;
+	port->gs.port.tty = tty;
+	port->gs.port.count++;
+	retval = gs_init_port(&port->gs);
+	if (retval) {
+		port->gs.port.count--;
+		return retval;
+	}
+	port->gs.port.flags |= GS_ACTIVE;
+	retval = gs_block_til_ready(port, filp);
+
+	if (retval) {
+		port->gs.port.count--;
+		return retval;
+	}
+
+	port->c_dcd = tty_port_carrier_raised(&port->gs.port);
+
+	scc_enable_rx_interrupts(port);
+
+	return 0;
+}
+
+
+static void scc_throttle (struct tty_struct * tty)
+{
+	struct scc_port *port = tty->driver_data;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	if (tty->termios->c_cflag & CRTSCTS) {
+		local_irq_save(flags);
+		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
+		local_irq_restore(flags);
+	}
+	if (I_IXOFF(tty))
+		scc_send_xchar(tty, STOP_CHAR(tty));
+}
+
+
+static void scc_unthrottle (struct tty_struct * tty)
+{
+	struct scc_port *port = tty->driver_data;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	if (tty->termios->c_cflag & CRTSCTS) {
+		local_irq_save(flags);
+		SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
+		local_irq_restore(flags);
+	}
+	if (I_IXOFF(tty))
+		scc_send_xchar(tty, START_CHAR(tty));
+}
+
+
+static int scc_ioctl(struct tty_struct *tty,
+		     unsigned int cmd, unsigned long arg)
+{
+	return -ENOIOCTLCMD;
+}
+
+
+static int scc_break_ctl(struct tty_struct *tty, int break_state)
+{
+	struct scc_port *port = tty->driver_data;
+	unsigned long	flags;
+	SCC_ACCESS_INIT(port);
+
+	local_irq_save(flags);
+	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 
+			break_state ? TCR_SEND_BREAK : 0);
+	local_irq_restore(flags);
+	return 0;
+}
+
+
+/*---------------------------------------------------------------------------
+ * Serial console stuff...
+ *--------------------------------------------------------------------------*/
+
+#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
+
+static void scc_ch_write (char ch)
+{
+	volatile char *p = NULL;
+	
+#ifdef CONFIG_MVME147_SCC
+	if (MACH_IS_MVME147)
+		p = (volatile char *)M147_SCC_A_ADDR;
+#endif
+#ifdef CONFIG_MVME162_SCC
+	if (MACH_IS_MVME16x)
+		p = (volatile char *)MVME_SCC_A_ADDR;
+#endif
+#ifdef CONFIG_BVME6000_SCC
+	if (MACH_IS_BVME6000)
+		p = (volatile char *)BVME_SCC_A_ADDR;
+#endif
+
+	do {
+		scc_delay();
+	}
+	while (!(*p & 4));
+	scc_delay();
+	*p = 8;
+	scc_delay();
+	*p = ch;
+}
+
+/* The console must be locked when we get here. */
+
+static void scc_console_write (struct console *co, const char *str, unsigned count)
+{
+	unsigned long	flags;
+
+	local_irq_save(flags);
+
+	while (count--)
+	{
+		if (*str == '\n')
+			scc_ch_write ('\r');
+		scc_ch_write (*str++);
+	}
+	local_irq_restore(flags);
+}
+
+static struct tty_driver *scc_console_device(struct console *c, int *index)
+{
+	*index = c->index;
+	return scc_driver;
+}
+
+static struct console sercons = {
+	.name		= "ttyS",
+	.write		= scc_console_write,
+	.device		= scc_console_device,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+};
+
+
+static int __init vme_scc_console_init(void)
+{
+	if (vme_brdtype == VME_TYPE_MVME147 ||
+			vme_brdtype == VME_TYPE_MVME162 ||
+			vme_brdtype == VME_TYPE_MVME172 ||
+			vme_brdtype == VME_TYPE_BVME4000 ||
+			vme_brdtype == VME_TYPE_BVME6000)
+		register_console(&sercons);
+	return 0;
+}
+console_initcall(vme_scc_console_init);
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
new file mode 100644
index 0000000..5501eb9
--- /dev/null
+++ b/drivers/staging/gma500/Kconfig
@@ -0,0 +1,12 @@
+config DRM_PSB
+	tristate "Intel GMA500 KMS Framebuffer"
+	depends on DRM && PCI
+	select FB_CFB_COPYAREA
+        select FB_CFB_FILLRECT
+        select FB_CFB_IMAGEBLIT
+        select DRM_KMS_HELPER
+        select DRM_TTM
+	help
+	  Say yes for an experimental KMS framebuffer driver for the
+	  Intel GMA500 ('Poulsbo') graphics support.
+
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
new file mode 100644
index 0000000..a52ba48
--- /dev/null
+++ b/drivers/staging/gma500/Makefile
@@ -0,0 +1,31 @@
+#
+#	KMS driver for the GMA500
+#
+ccflags-y += -Iinclude/drm
+
+psb_gfx-y += psb_bl.o \
+	  psb_drv.o \
+	  psb_fb.o \
+	  psb_2d.o \
+	  psb_gtt.o \
+	  psb_intel_bios.o \
+	  psb_intel_opregion.o \
+	  psb_intel_display.o \
+	  psb_intel_i2c.o \
+	  psb_intel_lvds.o \
+	  psb_intel_modes.o \
+	  psb_intel_sdvo.o \
+	  psb_reset.o \
+	  psb_sgx.o \
+	  psb_pvr_glue.o \
+	  psb_buffer.o \
+	  psb_fence.o \
+	  psb_mmu.o \
+	  psb_ttm_glue.o \
+	  psb_ttm_fence.o \
+	  psb_ttm_fence_user.o \
+	  psb_ttm_placement_user.o \
+	  psb_powermgmt.o \
+	  psb_irq.o
+
+obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO
new file mode 100644
index 0000000..f692ce1
--- /dev/null
+++ b/drivers/staging/gma500/TODO
@@ -0,0 +1,26 @@
+-	Test on more platforms
+-	Clean up the various chunks of unused code
+-	Sort out the power management side. Not important for Poulsbo but
+	matters for Moorestown
+-	Add Moorestown support (single pipe, no BIOS, no stolen memory,
+				some other differences)
+-	Sort out the bo and ttm code to support userframe buffers and DRM
+	interfaces rather than just faking it enough for a framebuffer
+-	Add 2D acceleration via console and DRM
+
+As per kernel policy and the in the interest of the safety of various
+kittens there is no support or plans to add hooks for the closed user space
+stuff.
+
+
+Why bother ?
+- Proper display configuration
+- Can be made to work on Moorestown where VESA won't
+- Works on systems where the VESA BIOS is bust or the tables are broken
+  without hacks
+- 2D acceleration
+
+Currently tested on
++	Dell Mini 10 100x600
+
+
diff --git a/drivers/staging/gma500/psb_2d.c b/drivers/staging/gma500/psb_2d.c
new file mode 100644
index 0000000..e4cae5d
--- /dev/null
+++ b/drivers/staging/gma500/psb_2d.c
@@ -0,0 +1,411 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_drv.h"
+#include "psb_fb.h"
+#include "psb_sgx.h"
+
+void psb_spank(struct drm_psb_private *dev_priv)
+{
+        PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET |
+		_PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET |
+		_PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET |
+		_PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET);
+	(void) PSB_RSGX32(PSB_CR_SOFT_RESET);
+
+	msleep(1);
+
+	PSB_WSGX32(0, PSB_CR_SOFT_RESET);
+	wmb();
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT,
+		   PSB_CR_BIF_CTRL);
+	wmb();
+	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+
+	msleep(1);
+	PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT,
+		   PSB_CR_BIF_CTRL);
+	(void) PSB_RSGX32(PSB_CR_BIF_CTRL);
+	PSB_WSGX32(dev_priv->pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+}
+
+static int psb_2d_wait_available(struct drm_psb_private *dev_priv,
+			  unsigned size)
+{
+	uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
+	unsigned long t = jiffies + HZ;
+
+	while(avail < size) {
+		avail = PSB_RSGX32(PSB_CR_2D_SOCIF);
+		if (time_after(jiffies, t)) {
+			psb_spank(dev_priv);
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* FIXME: Remember if we expose the 2D engine to the DRM we need to serialize
+   it with console use */
+
+static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf,
+	 	  	   unsigned size)
+{
+	int ret = 0;
+	int i;
+	unsigned submit_size;
+
+	while (size > 0) {
+		submit_size = (size < 0x60) ? size : 0x60;
+		size -= submit_size;
+		ret = psb_2d_wait_available(dev_priv, submit_size);
+		if (ret)
+			return ret;
+
+		submit_size <<= 2;
+		for (i = 0; i < submit_size; i += 4) {
+			PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
+		}
+		(void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
+	}
+	return 0;
+}
+
+static int psb_accel_2d_fillrect(struct drm_psb_private *dev_priv,
+				 uint32_t dst_offset, uint32_t dst_stride,
+				 uint32_t dst_format, uint16_t dst_x,
+				 uint16_t dst_y, uint16_t size_x,
+				 uint16_t size_y, uint32_t fill)
+{
+	uint32_t buffer[10];
+	uint32_t *buf;
+
+	buf = buffer;
+
+	*buf++ = PSB_2D_FENCE_BH;
+
+	*buf++ =
+	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
+					       PSB_2D_DST_STRIDE_SHIFT);
+	*buf++ = dst_offset;
+
+	*buf++ =
+	    PSB_2D_BLIT_BH |
+	    PSB_2D_ROT_NONE |
+	    PSB_2D_COPYORDER_TL2BR |
+	    PSB_2D_DSTCK_DISABLE |
+	    PSB_2D_SRCCK_DISABLE | PSB_2D_USE_FILL | PSB_2D_ROP3_PATCOPY;
+
+	*buf++ = fill << PSB_2D_FILLCOLOUR_SHIFT;
+	*buf++ =
+	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
+						  PSB_2D_DST_YSTART_SHIFT);
+	*buf++ =
+	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
+						  PSB_2D_DST_YSIZE_SHIFT);
+	*buf++ = PSB_2D_FLUSH_BH;
+
+	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
+}
+
+static void psbfb_fillrect_accel(struct fb_info *info,
+				 const struct fb_fillrect *r)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	uint32_t offset;
+	uint32_t stride;
+	uint32_t format;
+
+	if (!fb)
+		return;
+
+	offset = psbfb->offset;
+	stride = fb->pitch;
+
+	switch (fb->depth) {
+	case 8:
+		format = PSB_2D_DST_332RGB;
+		break;
+	case 15:
+		format = PSB_2D_DST_555RGB;
+		break;
+	case 16:
+		format = PSB_2D_DST_565RGB;
+		break;
+	case 24:
+	case 32:
+		/* this is wrong but since we don't do blending its okay */
+		format = PSB_2D_DST_8888ARGB;
+		break;
+	default:
+		/* software fallback */
+		cfb_fillrect(info, r);
+		return;
+	}
+
+	psb_accel_2d_fillrect(dev_priv,
+			      offset, stride, format,
+			      r->dx, r->dy, r->width, r->height, r->color);
+}
+
+void psbfb_fillrect(struct fb_info *info,
+			   const struct fb_fillrect *rect)
+{
+	if (unlikely(info->state != FBINFO_STATE_RUNNING))
+		return;
+
+	if (1 || (info->flags & FBINFO_HWACCEL_DISABLED))
+		return cfb_fillrect(info, rect);
+
+	/*psb_check_power_state(dev, PSB_DEVICE_SGX); */
+	psbfb_fillrect_accel(info, rect);
+	/* Drop power again here on MRST FIXMEAC */
+}
+
+static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
+{
+	if (xdir < 0)
+		return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
+                			PSB_2D_COPYORDER_TR2BL;
+	else
+		return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
+                			PSB_2D_COPYORDER_TL2BR;
+}
+
+/*
+ * @src_offset in bytes
+ * @src_stride in bytes
+ * @src_format psb 2D format defines
+ * @dst_offset in bytes
+ * @dst_stride in bytes
+ * @dst_format psb 2D format defines
+ * @src_x offset in pixels
+ * @src_y offset in pixels
+ * @dst_x offset in pixels
+ * @dst_y offset in pixels
+ * @size_x of the copied area
+ * @size_y of the copied area
+ */
+static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
+			     uint32_t src_offset, uint32_t src_stride,
+			     uint32_t src_format, uint32_t dst_offset,
+			     uint32_t dst_stride, uint32_t dst_format,
+			     uint16_t src_x, uint16_t src_y,
+			     uint16_t dst_x, uint16_t dst_y,
+			     uint16_t size_x, uint16_t size_y)
+{
+	uint32_t blit_cmd;
+	uint32_t buffer[10];
+	uint32_t *buf;
+	uint32_t direction;
+
+	buf = buffer;
+
+	direction =
+	    psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
+
+	if (direction == PSB_2D_COPYORDER_BR2TL ||
+	    direction == PSB_2D_COPYORDER_TR2BL) {
+		src_x += size_x - 1;
+		dst_x += size_x - 1;
+	}
+	if (direction == PSB_2D_COPYORDER_BR2TL ||
+	    direction == PSB_2D_COPYORDER_BL2TR) {
+		src_y += size_y - 1;
+		dst_y += size_y - 1;
+	}
+
+	blit_cmd =
+	    PSB_2D_BLIT_BH |
+	    PSB_2D_ROT_NONE |
+	    PSB_2D_DSTCK_DISABLE |
+	    PSB_2D_SRCCK_DISABLE |
+	    PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
+
+	*buf++ = PSB_2D_FENCE_BH;
+	*buf++ =
+	    PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
+					       PSB_2D_DST_STRIDE_SHIFT);
+	*buf++ = dst_offset;
+	*buf++ =
+	    PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
+					       PSB_2D_SRC_STRIDE_SHIFT);
+	*buf++ = src_offset;
+	*buf++ =
+	    PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
+	    (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
+	*buf++ = blit_cmd;
+	*buf++ =
+	    (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
+						  PSB_2D_DST_YSTART_SHIFT);
+	*buf++ =
+	    (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
+						  PSB_2D_DST_YSIZE_SHIFT);
+	*buf++ = PSB_2D_FLUSH_BH;
+
+	return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
+}
+
+static void psbfb_copyarea_accel(struct fb_info *info,
+				 const struct fb_copyarea *a)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	uint32_t offset;
+	uint32_t stride;
+	uint32_t src_format;
+	uint32_t dst_format;
+
+	if (!fb)
+		return;
+
+	offset = psbfb->offset;
+	stride = fb->pitch;
+
+	switch (fb->depth) {
+	case 8:
+		src_format = PSB_2D_SRC_332RGB;
+		dst_format = PSB_2D_DST_332RGB;
+		break;
+	case 15:
+		src_format = PSB_2D_SRC_555RGB;
+		dst_format = PSB_2D_DST_555RGB;
+		break;
+	case 16:
+		src_format = PSB_2D_SRC_565RGB;
+		dst_format = PSB_2D_DST_565RGB;
+		break;
+	case 24:
+	case 32:
+		/* this is wrong but since we don't do blending its okay */
+		src_format = PSB_2D_SRC_8888ARGB;
+		dst_format = PSB_2D_DST_8888ARGB;
+		break;
+	default:
+		/* software fallback */
+		cfb_copyarea(info, a);
+		return;
+	}
+
+	psb_accel_2d_copy(dev_priv,
+			  offset, stride, src_format,
+			  offset, stride, dst_format,
+			  a->sx, a->sy, a->dx, a->dy, a->width, a->height);
+}
+
+void psbfb_copyarea(struct fb_info *info,
+			   const struct fb_copyarea *region)
+{
+	if (unlikely(info->state != FBINFO_STATE_RUNNING))
+		return;
+
+	if (1 || (info->flags & FBINFO_HWACCEL_DISABLED))
+		return cfb_copyarea(info, region);
+
+	/* psb_check_power_state(dev, PSB_DEVICE_SGX); */
+	psbfb_copyarea_accel(info, region);
+	/* Need to power back off here for MRST FIXMEAC */
+}
+
+void psbfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+        /* For now */
+	cfb_imageblit(info, image);
+}
+
+int psbfb_sync(struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = fbdev->pfb;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned long _end = jiffies + DRM_HZ;
+	int busy = 0;
+
+#if 0
+        /* Just a way to quickly test if cmd issue explodes */
+	u32 test[2] = {
+	        PSB_2D_FENCE_BH,
+        };
+	psbfb_2d_submit(dev_priv, test, 1);
+#endif	
+	/*
+	 * First idle the 2D engine.
+	 */
+
+	if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
+	    ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
+		goto out;
+
+	do {
+		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+		cpu_relax();
+	} while (busy && !time_after_eq(jiffies, _end));
+
+	if (busy)
+		busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
+	if (busy)
+		goto out;
+
+	do {
+		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+						_PSB_C2B_STATUS_BUSY) != 0);
+		cpu_relax();
+	} while (busy && !time_after_eq(jiffies, _end));
+	if (busy)
+		busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
+					_PSB_C2B_STATUS_BUSY) != 0);
+
+out:
+	return (busy) ? -EBUSY : 0;
+}
+
+/*
+	info->fix.accel = FB_ACCEL_I830;
+	info->flags = FBINFO_DEFAULT;
+*/
diff --git a/drivers/staging/gma500/psb_bl.c b/drivers/staging/gma500/psb_bl.c
new file mode 100644
index 0000000..70c17b3
--- /dev/null
+++ b/drivers/staging/gma500/psb_bl.c
@@ -0,0 +1,169 @@
+/*
+ *  psb backlight interface
+ *
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Eric Knopp
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/version.h>
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_bios.h"
+#include "psb_powermgmt.h"
+
+#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
+#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
+#define BLC_PWM_FREQ_CALC_CONSTANT 32
+#define MHz 1000000
+#define BRIGHTNESS_MIN_LEVEL 1
+#define BRIGHTNESS_MAX_LEVEL 100
+#define BRIGHTNESS_MASK	0xFF
+#define BLC_POLARITY_NORMAL 0
+#define BLC_POLARITY_INVERSE 1
+#define BLC_ADJUSTMENT_MAX 100
+
+#define PSB_BLC_PWM_PRECISION_FACTOR    10
+#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
+#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
+
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+
+static int psb_brightness;
+static struct backlight_device *psb_backlight_device;
+static u8 blc_brightnesscmd;
+static u8 blc_pol;
+static u8 blc_type;
+
+int psb_set_brightness(struct backlight_device *bd)
+{
+	struct drm_device *dev = bl_get_data(psb_backlight_device);
+	int level = bd->props.brightness;
+
+	DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
+
+	/* Perform value bounds checking */
+	if (level < BRIGHTNESS_MIN_LEVEL)
+		level = BRIGHTNESS_MIN_LEVEL;
+
+	psb_intel_lvds_set_brightness(dev, level);
+	psb_brightness = level;
+	return 0;
+}
+
+int psb_get_brightness(struct backlight_device *bd)
+{
+	DRM_DEBUG_DRIVER("brightness = 0x%x\n", psb_brightness);
+
+	/* return locally cached var instead of HW read (due to DPST etc.) */
+	/* FIXME: ideally return actual value in case firmware fiddled with
+	   it */
+	return psb_brightness;
+}
+
+static const struct backlight_ops psb_ops = {
+	.get_brightness = psb_get_brightness,
+	.update_status  = psb_set_brightness,
+};
+
+static int device_backlight_init(struct drm_device *dev)
+{
+	unsigned long core_clock;
+	/* u32 bl_max_freq; */
+	/* unsigned long value; */
+	u16 bl_max_freq;
+	uint32_t value;
+	uint32_t blc_pwm_precision_factor;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/* get bl_max_freq and pol from dev_priv*/
+	if (!dev_priv->lvds_bl) {
+		DRM_ERROR("Has no valid LVDS backlight info\n");
+		return 1;
+	}
+	bl_max_freq = dev_priv->lvds_bl->freq;
+	blc_pol = dev_priv->lvds_bl->pol;
+	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
+	blc_brightnesscmd = dev_priv->lvds_bl->brightnesscmd;
+	blc_type = dev_priv->lvds_bl->type;
+
+	core_clock = dev_priv->core_freq;
+
+	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
+	value *= blc_pwm_precision_factor;
+	value /= bl_max_freq;
+	value /= blc_pwm_precision_factor;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+						OSPM_UHB_ONLY_IF_ON)) {
+		/* Check: may be MFLD only */
+		if (
+		 value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
+		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
+			return 2;
+		else {
+			value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
+			REG_WRITE(BLC_PWM_CTL,
+				(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
+				(value));
+		}
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+	return 0;
+}
+
+int psb_backlight_init(struct drm_device *dev)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	int ret = 0;
+
+	struct backlight_properties props;
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = BRIGHTNESS_MAX_LEVEL;
+
+	psb_backlight_device = backlight_device_register("psb-bl", NULL,
+						(void *)dev, &psb_ops, &props);
+	if (IS_ERR(psb_backlight_device))
+		return PTR_ERR(psb_backlight_device);
+
+	ret = device_backlight_init(dev);
+	if (ret < 0)
+		return ret;
+
+	psb_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
+	psb_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
+	backlight_update_status(psb_backlight_device);
+#endif
+	return 0;
+}
+
+void psb_backlight_exit(void)
+{
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	psb_backlight_device->props.brightness = 0;
+	backlight_update_status(psb_backlight_device);
+	backlight_device_unregister(psb_backlight_device);
+#endif
+}
+
+struct backlight_device *psb_get_backlight_device(void)
+{
+	return psb_backlight_device;
+}
diff --git a/drivers/staging/gma500/psb_buffer.c b/drivers/staging/gma500/psb_buffer.c
new file mode 100644
index 0000000..3077f6a
--- /dev/null
+++ b/drivers/staging/gma500/psb_buffer.c
@@ -0,0 +1,450 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ */
+#include "ttm/ttm_placement.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "psb_ttm_fence_api.h"
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+#define DRM_MEM_TTM       26
+
+struct drm_psb_ttm_backend {
+	struct ttm_backend base;
+	struct page **pages;
+	unsigned int desired_tile_stride;
+	unsigned int hw_tile_stride;
+	int mem_type;
+	unsigned long offset;
+	unsigned long num_pages;
+};
+
+/*
+ * MSVDX/TOPAZ GPU virtual space looks like this
+ * (We currently use only one MMU context).
+ * PSB_MEM_MMU_START: from 0x00000000~0xe000000, for generic buffers
+ * TTM_PL_CI: from 0xe0000000+half GTT space, for camear/video buffer sharing
+ * TTM_PL_RAR: from TTM_PL_CI+CI size, for RAR/video buffer sharing
+ * TTM_PL_TT: from TTM_PL_RAR+RAR size, for buffers need to mapping into GTT
+ */
+static int psb_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
+			     struct ttm_mem_type_manager *man)
+{
+
+	struct drm_psb_private *dev_priv =
+	    container_of(bdev, struct drm_psb_private, bdev);
+	struct psb_gtt *pg = dev_priv->pg;
+
+	switch (type) {
+	case TTM_PL_SYSTEM:
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+		man->available_caching = TTM_PL_FLAG_CACHED |
+		    TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_CACHED;
+		break;
+	case DRM_PSB_MEM_MMU:
+		man->func = &ttm_bo_manager_func;
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+		    TTM_MEMTYPE_FLAG_CMA;
+		man->gpu_offset = PSB_MEM_MMU_START;
+		man->available_caching = TTM_PL_FLAG_CACHED |
+		    TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_WC;
+		break;
+	case TTM_PL_CI:
+		man->func = &ttm_bo_manager_func;
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+			TTM_MEMTYPE_FLAG_FIXED;
+		man->gpu_offset = pg->mmu_gatt_start + (pg->ci_start);
+		man->available_caching = TTM_PL_FLAG_UNCACHED;
+		man->default_caching = TTM_PL_FLAG_UNCACHED;
+		break;
+	case TTM_PL_RAR:	/* Unmappable RAR memory */
+		man->func = &ttm_bo_manager_func;
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+			TTM_MEMTYPE_FLAG_FIXED;
+		man->available_caching = TTM_PL_FLAG_UNCACHED;
+		man->default_caching = TTM_PL_FLAG_UNCACHED;
+		man->gpu_offset = pg->mmu_gatt_start + (pg->rar_start);
+		break;
+	case TTM_PL_TT:	/* Mappable GATT memory */
+		man->func = &ttm_bo_manager_func;
+#ifdef PSB_WORKING_HOST_MMU_ACCESS
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
+#else
+		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
+		    TTM_MEMTYPE_FLAG_CMA;
+#endif
+		man->available_caching = TTM_PL_FLAG_CACHED |
+		    TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC;
+		man->default_caching = TTM_PL_FLAG_WC;
+		man->gpu_offset = pg->mmu_gatt_start +
+				(pg->rar_start + dev_priv->rar_region_size);
+		break;
+	default:
+		DRM_ERROR("Unsupported memory type %u\n", (unsigned) type);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+static void psb_evict_mask(struct ttm_buffer_object *bo,
+					struct ttm_placement *placement)
+{
+	static uint32_t cur_placement;
+
+	cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEM;
+	cur_placement |= TTM_PL_FLAG_SYSTEM;
+
+	placement->fpfn = 0;
+	placement->lpfn = 0;
+	placement->num_placement = 1;
+	placement->placement = &cur_placement;
+	placement->num_busy_placement = 0;
+	placement->busy_placement = NULL;
+
+	/* all buffers evicted to system memory */
+	/* return cur_placement | TTM_PL_FLAG_SYSTEM; */
+}
+
+static int psb_invalidate_caches(struct ttm_bo_device *bdev,
+				 uint32_t placement)
+{
+	return 0;
+}
+
+static int psb_move_blit(struct ttm_buffer_object *bo,
+			 bool evict, bool no_wait,
+			 struct ttm_mem_reg *new_mem)
+{
+	BUG();
+	return 0;
+}
+
+/*
+ * Flip destination ttm into GATT,
+ * then blit and subsequently move out again.
+ */
+
+static int psb_move_flip(struct ttm_buffer_object *bo,
+			 bool evict, bool interruptible, bool no_wait,
+			 struct ttm_mem_reg *new_mem)
+{
+	/*struct ttm_bo_device *bdev = bo->bdev;*/
+	struct ttm_mem_reg tmp_mem;
+	int ret;
+	struct ttm_placement placement;
+	uint32_t flags = TTM_PL_FLAG_TT;
+
+	tmp_mem = *new_mem;
+	tmp_mem.mm_node = NULL;
+
+	placement.fpfn = 0;
+	placement.lpfn = 0;
+	placement.num_placement = 1;
+	placement.placement = &flags;
+	placement.num_busy_placement = 0; /* FIXME */
+	placement.busy_placement = NULL;
+
+	ret = ttm_bo_mem_space(bo, &placement, &tmp_mem, interruptible,
+							false, no_wait);
+	if (ret)
+		return ret;
+	ret = ttm_tt_bind(bo->ttm, &tmp_mem);
+	if (ret)
+		goto out_cleanup;
+	ret = psb_move_blit(bo, true, no_wait, &tmp_mem);
+	if (ret)
+		goto out_cleanup;
+
+	ret = ttm_bo_move_ttm(bo, evict, false, no_wait, new_mem);
+out_cleanup:
+	if (tmp_mem.mm_node) {
+		drm_mm_put_block(tmp_mem.mm_node);
+		tmp_mem.mm_node = NULL;
+	}
+	return ret;
+}
+
+static int psb_move(struct ttm_buffer_object *bo,
+		    bool evict, bool interruptible, bool no_wait_reserve,
+		    bool no_wait, struct ttm_mem_reg *new_mem)
+{
+	struct ttm_mem_reg *old_mem = &bo->mem;
+
+	if ((old_mem->mem_type == TTM_PL_RAR) ||
+	    (new_mem->mem_type == TTM_PL_RAR)) {
+		if (old_mem->mm_node) {
+			spin_lock(&bo->glob->lru_lock);
+			drm_mm_put_block(old_mem->mm_node);
+			spin_unlock(&bo->glob->lru_lock);
+		}
+		old_mem->mm_node = NULL;
+		*old_mem = *new_mem;
+	} else if (old_mem->mem_type == TTM_PL_SYSTEM) {
+		return ttm_bo_move_memcpy(bo, evict, false, no_wait, new_mem);
+	} else if (new_mem->mem_type == TTM_PL_SYSTEM) {
+		int ret = psb_move_flip(bo, evict, interruptible,
+					no_wait, new_mem);
+		if (unlikely(ret != 0)) {
+			if (ret == -ERESTART)
+				return ret;
+			else
+				return ttm_bo_move_memcpy(bo, evict, false,
+						no_wait, new_mem);
+		}
+	} else {
+		if (psb_move_blit(bo, evict, no_wait, new_mem))
+			return ttm_bo_move_memcpy(bo, evict, false, no_wait,
+						  new_mem);
+	}
+	return 0;
+}
+
+static int drm_psb_tbe_populate(struct ttm_backend *backend,
+				unsigned long num_pages,
+				struct page **pages,
+				struct page *dummy_read_page,
+				dma_addr_t *dma_addrs)
+{
+	struct drm_psb_ttm_backend *psb_be =
+	    container_of(backend, struct drm_psb_ttm_backend, base);
+
+	psb_be->pages = pages;
+	return 0;
+}
+
+static int drm_psb_tbe_unbind(struct ttm_backend *backend)
+{
+	struct ttm_bo_device *bdev = backend->bdev;
+	struct drm_psb_private *dev_priv =
+	    container_of(bdev, struct drm_psb_private, bdev);
+	struct drm_psb_ttm_backend *psb_be =
+	    container_of(backend, struct drm_psb_ttm_backend, base);
+	struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu);
+	/* struct ttm_mem_type_manager *man = &bdev->man[psb_be->mem_type]; */
+
+	if (psb_be->mem_type == TTM_PL_TT) {
+		uint32_t gatt_p_offset =
+			(psb_be->offset - dev_priv->pg->mmu_gatt_start)
+								>> PAGE_SHIFT;
+
+		(void) psb_gtt_remove_pages(dev_priv->pg, gatt_p_offset,
+					    psb_be->num_pages,
+					    psb_be->desired_tile_stride,
+					    psb_be->hw_tile_stride, 0);
+	}
+
+	psb_mmu_remove_pages(pd, psb_be->offset,
+			     psb_be->num_pages,
+			     psb_be->desired_tile_stride,
+			     psb_be->hw_tile_stride);
+
+	return 0;
+}
+
+static int drm_psb_tbe_bind(struct ttm_backend *backend,
+			    struct ttm_mem_reg *bo_mem)
+{
+	struct ttm_bo_device *bdev = backend->bdev;
+	struct drm_psb_private *dev_priv =
+	    container_of(bdev, struct drm_psb_private, bdev);
+	struct drm_psb_ttm_backend *psb_be =
+	    container_of(backend, struct drm_psb_ttm_backend, base);
+	struct psb_mmu_pd *pd = psb_mmu_get_default_pd(dev_priv->mmu);
+	struct ttm_mem_type_manager *man = &bdev->man[bo_mem->mem_type];
+	struct drm_mm_node *mm_node = bo_mem->mm_node;
+	int type;
+	int ret = 0;
+
+	psb_be->mem_type = bo_mem->mem_type;
+	psb_be->num_pages = bo_mem->num_pages;
+	psb_be->desired_tile_stride = 0;
+	psb_be->hw_tile_stride = 0;
+	psb_be->offset = (mm_node->start << PAGE_SHIFT) +
+	    man->gpu_offset;
+
+	type =
+	    (bo_mem->
+	     placement & TTM_PL_FLAG_CACHED) ? PSB_MMU_CACHED_MEMORY : 0;
+
+	if (psb_be->mem_type == TTM_PL_TT) {
+		uint32_t gatt_p_offset =
+				(psb_be->offset - dev_priv->pg->mmu_gatt_start)
+								>> PAGE_SHIFT;
+
+		ret = psb_gtt_insert_pages(dev_priv->pg, psb_be->pages,
+					   gatt_p_offset,
+					   psb_be->num_pages,
+					   psb_be->desired_tile_stride,
+					   psb_be->hw_tile_stride, type);
+	}
+
+	ret = psb_mmu_insert_pages(pd, psb_be->pages,
+				   psb_be->offset, psb_be->num_pages,
+				   psb_be->desired_tile_stride,
+				   psb_be->hw_tile_stride, type);
+	if (ret)
+		goto out_err;
+
+	return 0;
+out_err:
+	drm_psb_tbe_unbind(backend);
+	return ret;
+
+}
+
+static void drm_psb_tbe_clear(struct ttm_backend *backend)
+{
+	struct drm_psb_ttm_backend *psb_be =
+	    container_of(backend, struct drm_psb_ttm_backend, base);
+
+	psb_be->pages = NULL;
+	return;
+}
+
+static void drm_psb_tbe_destroy(struct ttm_backend *backend)
+{
+	struct drm_psb_ttm_backend *psb_be =
+	    container_of(backend, struct drm_psb_ttm_backend, base);
+
+	if (backend)
+		kfree(psb_be);
+}
+
+static struct ttm_backend_func psb_ttm_backend = {
+	.populate = drm_psb_tbe_populate,
+	.clear = drm_psb_tbe_clear,
+	.bind = drm_psb_tbe_bind,
+	.unbind = drm_psb_tbe_unbind,
+	.destroy = drm_psb_tbe_destroy,
+};
+
+static struct ttm_backend *drm_psb_tbe_init(struct ttm_bo_device *bdev)
+{
+	struct drm_psb_ttm_backend *psb_be;
+
+	psb_be = kzalloc(sizeof(*psb_be), GFP_KERNEL);
+	if (!psb_be)
+		return NULL;
+	psb_be->pages = NULL;
+	psb_be->base.func = &psb_ttm_backend;
+	psb_be->base.bdev = bdev;
+	return &psb_be->base;
+}
+
+static int psb_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
+						struct ttm_mem_reg *mem)
+{
+	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
+	struct drm_psb_private *dev_priv =
+	    container_of(bdev, struct drm_psb_private, bdev);
+	struct psb_gtt *pg = dev_priv->pg;
+	struct drm_mm_node *mm_node = mem->mm_node;
+
+	mem->bus.addr = NULL;
+	mem->bus.offset = 0;
+	mem->bus.size = mem->num_pages << PAGE_SHIFT;
+	mem->bus.base = 0;
+	mem->bus.is_iomem = false;
+	if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
+		return -EINVAL;
+	switch (mem->mem_type) {
+	case TTM_PL_SYSTEM:
+		/* system memory */
+		return 0;
+	case TTM_PL_TT:
+		mem->bus.offset = mm_node->start << PAGE_SHIFT;
+		mem->bus.base = pg->gatt_start;
+		mem->bus.is_iomem = false;
+		/* Don't know whether it is IO_MEM, this flag
+						used in vm_fault handle */
+		break;
+	case DRM_PSB_MEM_MMU:
+		mem->bus.offset = mm_node->start << PAGE_SHIFT;
+		mem->bus.base = 0x00000000;
+		break;
+	case TTM_PL_CI:
+		mem->bus.offset = mm_node->start << PAGE_SHIFT;
+		mem->bus.base = dev_priv->ci_region_start;;
+		mem->bus.is_iomem = true;
+		break;
+	case TTM_PL_RAR:
+		mem->bus.offset = mm_node->start << PAGE_SHIFT;
+		mem->bus.base = dev_priv->rar_region_start;;
+		mem->bus.is_iomem = true;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void psb_ttm_io_mem_free(struct ttm_bo_device *bdev,
+						struct ttm_mem_reg *mem)
+{
+}
+
+/*
+ * Use this memory type priority if no eviction is needed.
+ */
+/*
+static uint32_t psb_mem_prios[] = {
+	TTM_PL_CI,
+	TTM_PL_RAR,
+	TTM_PL_TT,
+	DRM_PSB_MEM_MMU,
+	TTM_PL_SYSTEM
+};
+*/
+/*
+ * Use this memory type priority if need to evict.
+ */
+/*
+static uint32_t psb_busy_prios[] = {
+	TTM_PL_TT,
+	TTM_PL_CI,
+	TTM_PL_RAR,
+	DRM_PSB_MEM_MMU,
+	TTM_PL_SYSTEM
+};
+*/
+struct ttm_bo_driver psb_ttm_bo_driver = {
+/*
+	.mem_type_prio = psb_mem_prios,
+	.mem_busy_prio = psb_busy_prios,
+	.num_mem_type_prio = ARRAY_SIZE(psb_mem_prios),
+	.num_mem_busy_prio = ARRAY_SIZE(psb_busy_prios),
+*/
+	.create_ttm_backend_entry = &drm_psb_tbe_init,
+	.invalidate_caches = &psb_invalidate_caches,
+	.init_mem_type = &psb_init_mem_type,
+	.evict_flags = &psb_evict_mask,
+	.move = &psb_move,
+	.verify_access = &psb_verify_access,
+	.sync_obj_signaled = &ttm_fence_sync_obj_signaled,
+	.sync_obj_wait = &ttm_fence_sync_obj_wait,
+	.sync_obj_flush = &ttm_fence_sync_obj_flush,
+	.sync_obj_unref = &ttm_fence_sync_obj_unref,
+	.sync_obj_ref = &ttm_fence_sync_obj_ref,
+	.io_mem_reserve = &psb_ttm_io_mem_reserve,
+	.io_mem_free = &psb_ttm_io_mem_free
+};
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
new file mode 100644
index 0000000..fb9b424
--- /dev/null
+++ b/drivers/staging/gma500/psb_drm.h
@@ -0,0 +1,397 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRM_H_
+#define _PSB_DRM_H_
+
+#if defined(__linux__) && !defined(__KERNEL__)
+#include<stdint.h>
+#include <linux/types.h>
+#include "drm_mode.h"
+#endif
+
+#include "psb_ttm_fence_user.h"
+#include "psb_ttm_placement_user.h"
+
+#define DRM_PSB_SAREA_MAJOR 0
+#define DRM_PSB_SAREA_MINOR 2
+#define PSB_FIXED_SHIFT 16
+
+#define PSB_NUM_PIPE 3
+
+/*
+ * Public memory types.
+ */
+
+#define DRM_PSB_MEM_MMU 	TTM_PL_PRIV1
+#define DRM_PSB_FLAG_MEM_MMU	TTM_PL_FLAG_PRIV1
+
+#define TTM_PL_CI               TTM_PL_PRIV0
+#define TTM_PL_FLAG_CI          TTM_PL_FLAG_PRIV0
+
+#define TTM_PL_RAR              TTM_PL_PRIV2
+#define TTM_PL_FLAG_RAR         TTM_PL_FLAG_PRIV2
+
+typedef s32 psb_fixed;
+typedef u32 psb_ufixed;
+
+static inline s32 psb_int_to_fixed(int a)
+{
+	return a * (1 << PSB_FIXED_SHIFT);
+}
+
+static inline u32 psb_unsigned_to_ufixed(unsigned int a)
+{
+	return a << PSB_FIXED_SHIFT;
+}
+
+/*Status of the command sent to the gfx device.*/
+typedef enum {
+	DRM_CMD_SUCCESS,
+	DRM_CMD_FAILED,
+	DRM_CMD_HANG
+} drm_cmd_status_t;
+
+struct drm_psb_scanout {
+	u32 buffer_id;	/* DRM buffer object ID */
+	u32 rotation;	/* Rotation as in RR_rotation definitions */
+	u32 stride;	/* Buffer stride in bytes */
+	u32 depth;		/* Buffer depth in bits (NOT) bpp */
+	u32 width;		/* Buffer width in pixels */
+	u32 height;	/* Buffer height in lines */
+	s32 transform[3][3];	/* Buffer composite transform */
+	/* (scaling, rot, reflect) */
+};
+
+#define DRM_PSB_SAREA_OWNERS 16
+#define DRM_PSB_SAREA_OWNER_2D 0
+#define DRM_PSB_SAREA_OWNER_3D 1
+
+#define DRM_PSB_SAREA_SCANOUTS 3
+
+struct drm_psb_sarea {
+	/* Track changes of this data structure */
+
+	u32 major;
+	u32 minor;
+
+	/* Last context to touch part of hw */
+	u32 ctx_owners[DRM_PSB_SAREA_OWNERS];
+
+	/* Definition of front- and rotated buffers */
+	u32 num_scanouts;
+	struct drm_psb_scanout scanouts[DRM_PSB_SAREA_SCANOUTS];
+
+	int planeA_x;
+	int planeA_y;
+	int planeA_w;
+	int planeA_h;
+	int planeB_x;
+	int planeB_y;
+	int planeB_w;
+	int planeB_h;
+	/* Number of active scanouts */
+	u32 num_active_scanouts;
+};
+
+#define PSB_RELOC_MAGIC         0x67676767
+#define PSB_RELOC_SHIFT_MASK    0x0000FFFF
+#define PSB_RELOC_SHIFT_SHIFT   0
+#define PSB_RELOC_ALSHIFT_MASK  0xFFFF0000
+#define PSB_RELOC_ALSHIFT_SHIFT 16
+
+#define PSB_RELOC_OP_OFFSET     0	/* Offset of the indicated
+					 * buffer
+					 */
+
+struct drm_psb_reloc {
+	u32 reloc_op;
+	u32 where;		/* offset in destination buffer */
+	u32 buffer;	/* Buffer reloc applies to */
+	u32 mask;		/* Destination format: */
+	u32 shift;		/* Destination format: */
+	u32 pre_add;	/* Destination format: */
+	u32 background;	/* Destination add */
+	u32 dst_buffer;	/* Destination buffer. Index into buffer_list */
+	u32 arg0;		/* Reloc-op dependant */
+	u32 arg1;
+};
+
+
+#define PSB_GPU_ACCESS_READ         (1ULL << 32)
+#define PSB_GPU_ACCESS_WRITE        (1ULL << 33)
+#define PSB_GPU_ACCESS_MASK         (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)
+
+#define PSB_BO_FLAG_COMMAND         (1ULL << 52)
+
+#define PSB_ENGINE_2D 0
+#define PSB_ENGINE_VIDEO 1
+#define LNC_ENGINE_ENCODE 5
+
+/*
+ * For this fence class we have a couple of
+ * fence types.
+ */
+
+#define _PSB_FENCE_EXE_SHIFT           0
+#define _PSB_FENCE_FEEDBACK_SHIFT      4
+
+#define _PSB_FENCE_TYPE_EXE         (1 << _PSB_FENCE_EXE_SHIFT)
+#define _PSB_FENCE_TYPE_FEEDBACK    (1 << _PSB_FENCE_FEEDBACK_SHIFT)
+
+#define PSB_NUM_ENGINES 6
+
+
+#define PSB_FEEDBACK_OP_VISTEST (1 << 0)
+
+struct drm_psb_extension_rep {
+	s32 exists;
+	u32 driver_ioctl_offset;
+	u32 sarea_offset;
+	u32 major;
+	u32 minor;
+	u32 pl;
+};
+
+#define DRM_PSB_EXT_NAME_LEN 128
+
+union drm_psb_extension_arg {
+	char extension[DRM_PSB_EXT_NAME_LEN];
+	struct drm_psb_extension_rep rep;
+};
+
+struct psb_validate_req {
+	u64 set_flags;
+	u64 clear_flags;
+	u64 next;
+	u64 presumed_gpu_offset;
+	u32 buffer_handle;
+	u32 presumed_flags;
+	u32 group;
+	u32 pad64;
+};
+
+struct psb_validate_rep {
+	u64 gpu_offset;
+	u32 placement;
+	u32 fence_type_mask;
+};
+
+#define PSB_USE_PRESUMED     (1 << 0)
+
+struct psb_validate_arg {
+	int handled;
+	int ret;
+	union {
+		struct psb_validate_req req;
+		struct psb_validate_rep rep;
+	} d;
+};
+
+
+#define DRM_PSB_FENCE_NO_USER        (1 << 0)
+
+struct psb_ttm_fence_rep {
+	u32 handle;
+	u32 fence_class;
+	u32 fence_type;
+	u32 signaled_types;
+	u32 error;
+};
+
+/*
+ * Feedback components:
+ */
+
+struct drm_psb_sizes_arg {
+	u32 ta_mem_size;
+	u32 mmu_size;
+	u32 pds_size;
+	u32 rastgeom_size;
+	u32 tt_size;
+	u32 vram_size;
+};
+
+struct drm_psb_dpst_lut_arg {
+	uint8_t lut[256];
+	int output_id;
+};
+
+#define PSB_DC_CRTC_SAVE 0x01
+#define PSB_DC_CRTC_RESTORE 0x02
+#define PSB_DC_OUTPUT_SAVE 0x04
+#define PSB_DC_OUTPUT_RESTORE 0x08
+#define PSB_DC_CRTC_MASK 0x03
+#define PSB_DC_OUTPUT_MASK 0x0C
+
+struct drm_psb_dc_state_arg {
+	u32 flags;
+	u32 obj_id;
+};
+
+struct drm_psb_mode_operation_arg {
+	u32 obj_id;
+	u16 operation;
+	struct drm_mode_modeinfo mode;
+	void *data;
+};
+
+struct drm_psb_stolen_memory_arg {
+	u32 base;
+	u32 size;
+};
+
+/*Display Register Bits*/
+#define REGRWBITS_PFIT_CONTROLS			(1 << 0)
+#define REGRWBITS_PFIT_AUTOSCALE_RATIOS		(1 << 1)
+#define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS	(1 << 2)
+#define REGRWBITS_PIPEASRC			(1 << 3)
+#define REGRWBITS_PIPEBSRC			(1 << 4)
+#define REGRWBITS_VTOTAL_A			(1 << 5)
+#define REGRWBITS_VTOTAL_B			(1 << 6)
+#define REGRWBITS_DSPACNTR	(1 << 8)
+#define REGRWBITS_DSPBCNTR	(1 << 9)
+#define REGRWBITS_DSPCCNTR	(1 << 10)
+
+/*Overlay Register Bits*/
+#define OV_REGRWBITS_OVADD			(1 << 0)
+#define OV_REGRWBITS_OGAM_ALL			(1 << 1)
+
+#define OVC_REGRWBITS_OVADD                  (1 << 2)
+#define OVC_REGRWBITS_OGAM_ALL			(1 << 3)
+
+struct drm_psb_register_rw_arg {
+	u32 b_force_hw_on;
+
+	u32 display_read_mask;
+	u32 display_write_mask;
+
+	struct {
+		u32 pfit_controls;
+		u32 pfit_autoscale_ratios;
+		u32 pfit_programmed_scale_ratios;
+		u32 pipeasrc;
+		u32 pipebsrc;
+		u32 vtotal_a;
+		u32 vtotal_b;
+	} display;
+
+	u32 overlay_read_mask;
+	u32 overlay_write_mask;
+
+	struct {
+		u32 OVADD;
+		u32 OGAMC0;
+		u32 OGAMC1;
+		u32 OGAMC2;
+		u32 OGAMC3;
+		u32 OGAMC4;
+		u32 OGAMC5;
+        	u32 IEP_ENABLED;
+        	u32 IEP_BLE_MINMAX;
+        	u32 IEP_BSSCC_CONTROL;
+                u32 b_wait_vblank;
+	} overlay;
+
+	u32 sprite_enable_mask;
+	u32 sprite_disable_mask;
+
+	struct {
+		u32 dspa_control;
+		u32 dspa_key_value;
+		u32 dspa_key_mask;
+		u32 dspc_control;
+		u32 dspc_stride;
+		u32 dspc_position;
+		u32 dspc_linear_offset;
+		u32 dspc_size;
+		u32 dspc_surface;
+	} sprite;
+
+	u32 subpicture_enable_mask;
+	u32 subpicture_disable_mask;
+};
+
+struct psb_gtt_mapping_arg {
+	void *hKernelMemInfo;
+	u32 offset_pages;
+};
+
+struct drm_psb_getpageaddrs_arg {
+	u32 handle;
+	unsigned long *page_addrs;
+	unsigned long gtt_offset;
+};
+
+/* Controlling the kernel modesetting buffers */
+
+#define DRM_PSB_KMS_OFF		0x00
+#define DRM_PSB_KMS_ON		0x01
+#define DRM_PSB_VT_LEAVE        0x02
+#define DRM_PSB_VT_ENTER        0x03
+#define DRM_PSB_EXTENSION       0x06
+#define DRM_PSB_SIZES           0x07
+#define DRM_PSB_FUSE_REG	0x08
+#define DRM_PSB_VBT		0x09
+#define DRM_PSB_DC_STATE	0x0A
+#define DRM_PSB_ADB		0x0B
+#define DRM_PSB_MODE_OPERATION	0x0C
+#define DRM_PSB_STOLEN_MEMORY	0x0D
+#define DRM_PSB_REGISTER_RW	0x0E
+#define DRM_PSB_GTT_MAP         0x0F
+#define DRM_PSB_GTT_UNMAP       0x10
+#define DRM_PSB_GETPAGEADDRS	0x11
+/**
+ * NOTE: Add new commands here, but increment
+ * the values below and increment their
+ * corresponding defines where they're
+ * defined elsewhere.
+ */
+#define DRM_PVR_RESERVED1	0x12
+#define DRM_PVR_RESERVED2	0x13
+#define DRM_PVR_RESERVED3	0x14
+#define DRM_PVR_RESERVED4	0x15
+#define DRM_PVR_RESERVED5	0x16
+
+#define DRM_PSB_HIST_ENABLE	0x17
+#define DRM_PSB_HIST_STATUS	0x18
+#define DRM_PSB_UPDATE_GUARD	0x19
+#define DRM_PSB_INIT_COMM	0x1A
+#define DRM_PSB_DPST		0x1B
+#define DRM_PSB_GAMMA		0x1C
+#define DRM_PSB_DPST_BL		0x1D
+
+#define DRM_PVR_RESERVED6	0x1E
+
+#define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F
+
+#define PSB_MODE_OPERATION_MODE_VALID	0x01
+#define PSB_MODE_OPERATION_SET_DC_BASE  0x02
+
+struct drm_psb_get_pipe_from_crtc_id_arg {
+	/** ID of CRTC being requested **/
+	u32 crtc_id;
+
+	/** pipe of requested CRTC **/
+	u32 pipe;
+};
+
+#endif
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
new file mode 100644
index 0000000..44cd095
--- /dev/null
+++ b/drivers/staging/gma500/psb_drv.c
@@ -0,0 +1,1647 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_fb.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_bios.h"
+#include <drm/drm_pciids.h>
+#include "psb_powermgmt.h"
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
+#include <acpi/video.h>
+
+int drm_psb_debug;
+static int drm_psb_trap_pagefaults;
+
+int drm_psb_disable_vsync = 1;
+int drm_psb_no_fb;
+int gfxrtdelay = 2 * 1000;
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+
+MODULE_PARM_DESC(debug, "Enable debug output");
+MODULE_PARM_DESC(no_fb, "Disable FBdev");
+MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
+MODULE_PARM_DESC(disable_vsync, "Disable vsync interrupts");
+MODULE_PARM_DESC(force_pipeb, "Forces PIPEB to become primary fb");
+MODULE_PARM_DESC(ta_mem_size, "TA memory size in kiB");
+MODULE_PARM_DESC(ospm, "switch for ospm support");
+MODULE_PARM_DESC(rtpm, "Specifies Runtime PM delay for GFX");
+MODULE_PARM_DESC(hdmi_edid, "EDID info for HDMI monitor");
+module_param_named(debug, drm_psb_debug, int, 0600);
+module_param_named(no_fb, drm_psb_no_fb, int, 0600);
+module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
+module_param_named(rtpm, gfxrtdelay, int, 0600);
+
+
+static struct pci_device_id pciidlist[] = {
+	{ 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8108 },
+	{ 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PSB_8109 },
+	{ 0, 0, 0}
+};
+MODULE_DEVICE_TABLE(pci, pciidlist);
+
+/*
+ * Standard IOCTLs.
+ */
+
+#define DRM_IOCTL_PSB_KMS_OFF	\
+		DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_KMS_ON	\
+		DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_VT_LEAVE	\
+		DRM_IO(DRM_PSB_VT_LEAVE + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_VT_ENTER	\
+		DRM_IO(DRM_PSB_VT_ENTER + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_SIZES	\
+		DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
+			struct drm_psb_sizes_arg)
+#define DRM_IOCTL_PSB_FUSE_REG	\
+		DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_DC_STATE	\
+		DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
+			struct drm_psb_dc_state_arg)
+#define DRM_IOCTL_PSB_ADB	\
+		DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
+#define DRM_IOCTL_PSB_MODE_OPERATION	\
+		DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
+			 struct drm_psb_mode_operation_arg)
+#define DRM_IOCTL_PSB_STOLEN_MEMORY	\
+		DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
+			 struct drm_psb_stolen_memory_arg)
+#define DRM_IOCTL_PSB_REGISTER_RW	\
+		DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
+			 struct drm_psb_register_rw_arg)
+#define DRM_IOCTL_PSB_GTT_MAP	\
+		DRM_IOWR(DRM_PSB_GTT_MAP + DRM_COMMAND_BASE, \
+			 struct psb_gtt_mapping_arg)
+#define DRM_IOCTL_PSB_GTT_UNMAP	\
+		DRM_IOW(DRM_PSB_GTT_UNMAP + DRM_COMMAND_BASE, \
+			struct psb_gtt_mapping_arg)
+#define DRM_IOCTL_PSB_GETPAGEADDRS	\
+		DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_GETPAGEADDRS,\
+			 struct drm_psb_getpageaddrs_arg)
+#define DRM_IOCTL_PSB_UPDATE_GUARD	\
+		DRM_IOWR(DRM_PSB_UPDATE_GUARD + DRM_COMMAND_BASE, \
+			 uint32_t)
+#define DRM_IOCTL_PSB_DPST	\
+		DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
+			 uint32_t)
+#define DRM_IOCTL_PSB_GAMMA	\
+		DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
+			 struct drm_psb_dpst_lut_arg)
+#define DRM_IOCTL_PSB_DPST_BL	\
+		DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
+			 uint32_t)
+#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID	\
+		DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
+			 struct drm_psb_get_pipe_from_crtc_id_arg)
+
+/*
+ * TTM execbuf extension.
+ */
+
+#define DRM_PSB_CMDBUF		  0x23
+#define DRM_PSB_SCENE_UNREF	  0x24
+#define DRM_IOCTL_PSB_KMS_OFF	  DRM_IO(DRM_PSB_KMS_OFF + DRM_COMMAND_BASE)
+#define DRM_IOCTL_PSB_KMS_ON	  DRM_IO(DRM_PSB_KMS_ON + DRM_COMMAND_BASE)
+/*
+ * TTM placement user extension.
+ */
+
+#define DRM_PSB_PLACEMENT_OFFSET   (DRM_PSB_SCENE_UNREF + 1)
+
+#define DRM_PSB_TTM_PL_CREATE	 (TTM_PL_CREATE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_REFERENCE (TTM_PL_REFERENCE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_UNREF	 (TTM_PL_UNREF + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_SYNCCPU	 (TTM_PL_SYNCCPU + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_WAITIDLE  (TTM_PL_WAITIDLE + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_SETSTATUS (TTM_PL_SETSTATUS + DRM_PSB_PLACEMENT_OFFSET)
+#define DRM_PSB_TTM_PL_CREATE_UB (TTM_PL_CREATE_UB + DRM_PSB_PLACEMENT_OFFSET)
+
+/*
+ * TTM fence extension.
+ */
+
+#define DRM_PSB_FENCE_OFFSET	   (DRM_PSB_TTM_PL_CREATE_UB + 1)
+#define DRM_PSB_TTM_FENCE_SIGNALED (TTM_FENCE_SIGNALED + DRM_PSB_FENCE_OFFSET)
+#define DRM_PSB_TTM_FENCE_FINISH   (TTM_FENCE_FINISH + DRM_PSB_FENCE_OFFSET)
+#define DRM_PSB_TTM_FENCE_UNREF    (TTM_FENCE_UNREF + DRM_PSB_FENCE_OFFSET)
+
+#define DRM_PSB_FLIP	   (DRM_PSB_TTM_FENCE_UNREF + 1)	/*20*/
+
+#define DRM_IOCTL_PSB_TTM_PL_CREATE    \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE,\
+		 union ttm_pl_create_arg)
+#define DRM_IOCTL_PSB_TTM_PL_REFERENCE \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_REFERENCE,\
+		 union ttm_pl_reference_arg)
+#define DRM_IOCTL_PSB_TTM_PL_UNREF    \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_UNREF,\
+		struct ttm_pl_reference_req)
+#define DRM_IOCTL_PSB_TTM_PL_SYNCCPU	\
+	DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SYNCCPU,\
+		struct ttm_pl_synccpu_arg)
+#define DRM_IOCTL_PSB_TTM_PL_WAITIDLE	 \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_WAITIDLE,\
+		struct ttm_pl_waitidle_arg)
+#define DRM_IOCTL_PSB_TTM_PL_SETSTATUS \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_SETSTATUS,\
+		 union ttm_pl_setstatus_arg)
+#define DRM_IOCTL_PSB_TTM_PL_CREATE_UB    \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_PL_CREATE_UB,\
+		 union ttm_pl_create_ub_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_SIGNALED \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_SIGNALED,	\
+		  union ttm_fence_signaled_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_FINISH \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_FINISH,	\
+		 union ttm_fence_finish_arg)
+#define DRM_IOCTL_PSB_TTM_FENCE_UNREF \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_PSB_TTM_FENCE_UNREF,	\
+		 struct ttm_fence_unref_arg)
+
+static int psb_vt_leave_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+static int psb_vt_enter_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+			      struct drm_file *file_priv);
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv);
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv);
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv);
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv);
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv);
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv);
+
+#define PSB_IOCTL_DEF(ioctl, func, flags) \
+	[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
+
+static struct drm_ioctl_desc psb_ioctls[] = {
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_OFF, psbfb_kms_off_ioctl,
+		      DRM_ROOT_ONLY),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_KMS_ON,
+			psbfb_kms_on_ioctl,
+			DRM_ROOT_ONLY),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_LEAVE, psb_vt_leave_ioctl,
+		      DRM_ROOT_ONLY),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_VT_ENTER,
+			psb_vt_enter_ioctl,
+			DRM_ROOT_ONLY),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_MAP,
+			psb_gtt_map_meminfo_ioctl,
+			DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GTT_UNMAP,
+			psb_gtt_unmap_meminfo_ioctl,
+			DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GETPAGEADDRS,
+			psb_getpageaddrs_ioctl,
+			DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
+					psb_intel_get_pipe_from_crtc_id, 0),
+
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE, psb_pl_create_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_REFERENCE, psb_pl_reference_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_UNREF, psb_pl_unref_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SYNCCPU, psb_pl_synccpu_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_WAITIDLE, psb_pl_waitidle_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_SETSTATUS, psb_pl_setstatus_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_PL_CREATE_UB, psb_pl_ub_create_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_SIGNALED,
+		      psb_fence_signaled_ioctl, DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_FINISH, psb_fence_finish_ioctl,
+		      DRM_AUTH),
+	PSB_IOCTL_DEF(DRM_IOCTL_PSB_TTM_FENCE_UNREF, psb_fence_unref_ioctl,
+		      DRM_AUTH),
+};
+
+static void psb_set_uopt(struct drm_psb_uopt *uopt)
+{
+	return;
+}
+
+static void psb_lastclose(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+
+	return;
+
+	if (!dev->dev_private)
+		return;
+
+	mutex_lock(&dev_priv->cmdbuf_mutex);
+	if (dev_priv->context.buffers) {
+		vfree(dev_priv->context.buffers);
+		dev_priv->context.buffers = NULL;
+	}
+	mutex_unlock(&dev_priv->cmdbuf_mutex);
+}
+
+static void psb_do_takedown(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+
+
+	if (dev_priv->have_mem_mmu) {
+		ttm_bo_clean_mm(bdev, DRM_PSB_MEM_MMU);
+		dev_priv->have_mem_mmu = 0;
+	}
+
+	if (dev_priv->have_tt) {
+		ttm_bo_clean_mm(bdev, TTM_PL_TT);
+		dev_priv->have_tt = 0;
+	}
+
+	if (dev_priv->have_camera) {
+		ttm_bo_clean_mm(bdev, TTM_PL_CI);
+		dev_priv->have_camera = 0;
+	}
+	if (dev_priv->have_rar) {
+		ttm_bo_clean_mm(bdev, TTM_PL_RAR);
+		dev_priv->have_rar = 0;
+	}
+
+}
+
+static void psb_get_core_freq(struct drm_device *dev)
+{
+	uint32_t clock;
+	struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	/*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
+	/*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
+
+	pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
+	pci_read_config_dword(pci_root, 0xD4, &clock);
+	pci_dev_put(pci_root);
+
+	switch (clock & 0x07) {
+	case 0:
+		dev_priv->core_freq = 100;
+		break;
+	case 1:
+		dev_priv->core_freq = 133;
+		break;
+	case 2:
+		dev_priv->core_freq = 150;
+		break;
+	case 3:
+		dev_priv->core_freq = 178;
+		break;
+	case 4:
+		dev_priv->core_freq = 200;
+		break;
+	case 5:
+	case 6:
+	case 7:
+		dev_priv->core_freq = 266;
+	default:
+		dev_priv->core_freq = 0;
+	}
+}
+
+#define FB_REG06 0xD0810600
+#define FB_TOPAZ_DISABLE BIT0
+#define FB_MIPI_DISABLE  BIT11
+#define FB_REG09 0xD0810900
+#define FB_SKU_MASK  (BIT12|BIT13|BIT14)
+#define FB_SKU_SHIFT 12
+#define FB_SKU_100 0
+#define FB_SKU_100L 1
+#define FB_SKU_83 2
+
+bool mid_get_pci_revID(struct drm_psb_private *dev_priv)
+{
+	uint32_t platform_rev_id = 0;
+	struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
+
+	/*get the revison ID, B0:D2:F0;0x08 */
+	pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
+	dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
+	pci_dev_put(pci_gfx_root);
+	PSB_DEBUG_ENTRY("platform_rev_id is %x\n",
+					dev_priv->platform_rev_id);
+
+	return true;
+}
+
+static int psb_do_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	struct psb_gtt *pg = dev_priv->pg;
+
+	uint32_t stolen_gtt;
+	uint32_t tt_start;
+	uint32_t tt_pages;
+
+	int ret = -ENOMEM;
+
+
+	/*
+	 * Initialize sequence numbers for the different command
+	 * submission mechanisms.
+	 */
+
+	dev_priv->sequence[PSB_ENGINE_2D] = 0;
+	dev_priv->sequence[PSB_ENGINE_VIDEO] = 0;
+	dev_priv->sequence[LNC_ENGINE_ENCODE] = 0;
+
+	if (pg->mmu_gatt_start & 0x0FFFFFFF) {
+		DRM_ERROR("Gatt must be 256M aligned. This is a bug.\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+
+	stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4;
+	stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	stolen_gtt =
+	    (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages;
+
+	dev_priv->gatt_free_offset = pg->mmu_gatt_start +
+	    (stolen_gtt << PAGE_SHIFT) * 1024;
+
+	if (1 || drm_debug) {
+		uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID);
+		uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION);
+		DRM_INFO("SGX core id = 0x%08x\n", core_id);
+		DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n",
+			 (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >>
+			 _PSB_CC_REVISION_MAJOR_SHIFT,
+			 (core_rev & _PSB_CC_REVISION_MINOR_MASK) >>
+			 _PSB_CC_REVISION_MINOR_SHIFT);
+		DRM_INFO
+		    ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n",
+		     (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >>
+		     _PSB_CC_REVISION_MAINTENANCE_SHIFT,
+		     (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >>
+		     _PSB_CC_REVISION_DESIGNER_SHIFT);
+	}
+
+
+	spin_lock_init(&dev_priv->irqmask_lock);
+
+	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+	    pg->gatt_pages : PSB_TT_PRIV0_PLIMIT;
+	tt_start = dev_priv->gatt_free_offset - pg->mmu_gatt_start;
+	tt_pages -= tt_start >> PAGE_SHIFT;
+	dev_priv->sizes.ta_mem_size = 0;
+
+	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0);
+	PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1);
+	PSB_RSGX32(PSB_CR_BIF_BANK1);
+        PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK,
+							PSB_CR_BIF_CTRL);
+	psb_spank(dev_priv);
+       
+      	PSB_WSGX32(pg->mmu_gatt_start, PSB_CR_BIF_TWOD_REQ_BASE);
+
+	/* TT region managed by TTM. */
+	if (!ttm_bo_init_mm(bdev, TTM_PL_TT,
+			pg->gatt_pages -
+			(pg->ci_start >> PAGE_SHIFT) -
+			((dev_priv->ci_region_size + dev_priv->rar_region_size)
+			 >> PAGE_SHIFT))) {
+
+		dev_priv->have_tt = 1;
+		dev_priv->sizes.tt_size =
+			(tt_pages << PAGE_SHIFT) / (1024 * 1024) / 2;
+	}
+
+	if (!ttm_bo_init_mm(bdev,
+			DRM_PSB_MEM_MMU,
+			PSB_MEM_TT_START >> PAGE_SHIFT)) {
+		dev_priv->have_mem_mmu = 1;
+		dev_priv->sizes.mmu_size =
+			PSB_MEM_TT_START / (1024*1024);
+	}
+
+	PSB_DEBUG_INIT("Init MSVDX\n");
+	return 0;
+out_err:
+	psb_do_takedown(dev);
+	return ret;
+}
+
+static int psb_driver_unload(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+
+	/* Kill vblank etc here */
+
+	psb_backlight_exit(); /*writes minimum value to backlight HW reg */
+
+	if (drm_psb_no_fb == 0)
+		psb_modeset_cleanup(dev);
+
+	if (dev_priv) {
+		psb_lid_timer_takedown(dev_priv);
+
+		psb_do_takedown(dev);
+
+
+		if (dev_priv->pf_pd) {
+			psb_mmu_free_pagedir(dev_priv->pf_pd);
+			dev_priv->pf_pd = NULL;
+		}
+		if (dev_priv->mmu) {
+			struct psb_gtt *pg = dev_priv->pg;
+
+			down_read(&pg->sem);
+			psb_mmu_remove_pfn_sequence(
+					psb_mmu_get_default_pd
+					(dev_priv->mmu),
+					pg->mmu_gatt_start,
+					pg->vram_stolen_size >> PAGE_SHIFT);
+			if (pg->ci_stolen_size != 0)
+				psb_mmu_remove_pfn_sequence(
+					psb_mmu_get_default_pd
+					(dev_priv->mmu),
+					pg->ci_start,
+					pg->ci_stolen_size >> PAGE_SHIFT);
+			if (pg->rar_stolen_size != 0)
+				psb_mmu_remove_pfn_sequence(
+					psb_mmu_get_default_pd
+					(dev_priv->mmu),
+					pg->rar_start,
+					pg->rar_stolen_size >> PAGE_SHIFT);
+			up_read(&pg->sem);
+			psb_mmu_driver_takedown(dev_priv->mmu);
+			dev_priv->mmu = NULL;
+		}
+		psb_gtt_takedown(dev_priv->pg, 1);
+		if (dev_priv->scratch_page) {
+			__free_page(dev_priv->scratch_page);
+			dev_priv->scratch_page = NULL;
+		}
+		if (dev_priv->has_bo_device) {
+			ttm_bo_device_release(&dev_priv->bdev);
+			dev_priv->has_bo_device = 0;
+		}
+		if (dev_priv->has_fence_device) {
+			ttm_fence_device_release(&dev_priv->fdev);
+			dev_priv->has_fence_device = 0;
+		}
+		if (dev_priv->vdc_reg) {
+			iounmap(dev_priv->vdc_reg);
+			dev_priv->vdc_reg = NULL;
+		}
+		if (dev_priv->sgx_reg) {
+			iounmap(dev_priv->sgx_reg);
+			dev_priv->sgx_reg = NULL;
+		}
+
+		if (dev_priv->tdev)
+			ttm_object_device_release(&dev_priv->tdev);
+
+		if (dev_priv->has_global)
+			psb_ttm_global_release(dev_priv);
+
+		kfree(dev_priv);
+		dev->dev_private = NULL;
+
+		/*destory VBT data*/
+		psb_intel_destroy_bios(dev);
+	}
+
+	ospm_power_uninit();
+
+	return 0;
+}
+
+
+static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
+{
+	struct drm_psb_private *dev_priv;
+	struct ttm_bo_device *bdev;
+	unsigned long resource_start;
+	struct psb_gtt *pg;
+	unsigned long irqflags;
+	int ret = -ENOMEM;
+	uint32_t tt_pages;
+
+	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
+	if (dev_priv == NULL)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&dev_priv->video_ctx);
+
+	dev_priv->num_pipe = 2;
+
+
+	dev_priv->dev = dev;
+	bdev = &dev_priv->bdev;
+
+	ret = psb_ttm_global_init(dev_priv);
+	if (unlikely(ret != 0))
+		goto out_err;
+	dev_priv->has_global = 1;
+
+	dev_priv->tdev = ttm_object_device_init
+		(dev_priv->mem_global_ref.object, PSB_OBJECT_HASH_ORDER);
+	if (unlikely(dev_priv->tdev == NULL))
+		goto out_err;
+
+	mutex_init(&dev_priv->temp_mem);
+	mutex_init(&dev_priv->cmdbuf_mutex);
+	mutex_init(&dev_priv->reset_mutex);
+	INIT_LIST_HEAD(&dev_priv->context.validate_list);
+	INIT_LIST_HEAD(&dev_priv->context.kern_validate_list);
+
+/*	mutex_init(&dev_priv->dsr_mutex); */
+
+	spin_lock_init(&dev_priv->reloc_lock);
+
+	DRM_INIT_WAITQUEUE(&dev_priv->rel_mapped_queue);
+
+	dev->dev_private = (void *) dev_priv;
+	dev_priv->chipset = chipset;
+	psb_set_uopt(&dev_priv->uopt);
+
+	PSB_DEBUG_INIT("Mapping MMIO\n");
+	resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
+
+	dev_priv->vdc_reg =
+	    ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
+	if (!dev_priv->vdc_reg)
+		goto out_err;
+
+	dev_priv->sgx_reg = ioremap(resource_start + PSB_SGX_OFFSET,
+							PSB_SGX_SIZE);
+
+	if (!dev_priv->sgx_reg)
+		goto out_err;
+
+	psb_get_core_freq(dev);
+	psb_intel_opregion_init(dev);
+	psb_intel_init_bios(dev);
+
+	PSB_DEBUG_INIT("Init TTM fence and BO driver\n");
+
+	/* Init OSPM support */
+	ospm_power_init(dev);
+
+	ret = psb_ttm_fence_device_init(&dev_priv->fdev);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	dev_priv->has_fence_device = 1;
+	ret = ttm_bo_device_init(bdev,
+				 dev_priv->bo_global_ref.ref.object,
+				 &psb_ttm_bo_driver,
+				 DRM_PSB_FILE_PAGE_OFFSET, false);
+	if (unlikely(ret != 0))
+		goto out_err;
+	dev_priv->has_bo_device = 1;
+	ttm_lock_init(&dev_priv->ttm_lock);
+
+	ret = -ENOMEM;
+
+	dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
+	if (!dev_priv->scratch_page)
+		goto out_err;
+
+	set_pages_uc(dev_priv->scratch_page, 1);
+
+	dev_priv->pg = psb_gtt_alloc(dev);
+	if (!dev_priv->pg)
+		goto out_err;
+
+	ret = psb_gtt_init(dev_priv->pg, 0);
+	if (ret)
+		goto out_err;
+
+	ret = psb_gtt_mm_init(dev_priv->pg);
+	if (ret)
+		goto out_err;
+
+	dev_priv->mmu = psb_mmu_driver_init((void *)0,
+					drm_psb_trap_pagefaults, 0,
+					dev_priv);
+	if (!dev_priv->mmu)
+		goto out_err;
+
+	pg = dev_priv->pg;
+
+	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+		(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+	/* CI/RAR use the lower half of TT. */
+	pg->ci_start = (tt_pages / 2) << PAGE_SHIFT;
+	pg->rar_start = pg->ci_start + pg->ci_stolen_size;
+
+
+	/*
+	 * Make MSVDX/TOPAZ MMU aware of the CI stolen memory area.
+	 */
+	if (dev_priv->pg->ci_stolen_size != 0) {
+		down_read(&pg->sem);
+		ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd
+				(dev_priv->mmu),
+				dev_priv->ci_region_start >> PAGE_SHIFT,
+				pg->mmu_gatt_start + pg->ci_start,
+				pg->ci_stolen_size >> PAGE_SHIFT, 0);
+		up_read(&pg->sem);
+		if (ret)
+			goto out_err;
+	}
+
+	/*
+	 * Make MSVDX/TOPAZ MMU aware of the rar stolen memory area.
+	 */
+	if (dev_priv->pg->rar_stolen_size != 0) {
+		down_read(&pg->sem);
+		ret = psb_mmu_insert_pfn_sequence(
+				psb_mmu_get_default_pd(dev_priv->mmu),
+				dev_priv->rar_region_start >> PAGE_SHIFT,
+				pg->mmu_gatt_start + pg->rar_start,
+				pg->rar_stolen_size >> PAGE_SHIFT, 0);
+		up_read(&pg->sem);
+		if (ret)
+			goto out_err;
+	}
+
+	dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
+	if (!dev_priv->pf_pd)
+		goto out_err;
+
+	psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
+	psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
+
+	spin_lock_init(&dev_priv->sequence_lock);
+
+	PSB_DEBUG_INIT("Begin to init MSVDX/Topaz\n");
+
+	ret = psb_do_init(dev);
+	if (ret)
+		return ret;
+
+/*	igd_opregion_init(&dev_priv->opregion_dev); */
+	acpi_video_register();
+	if (dev_priv->lid_state)
+		psb_lid_timer_init(dev_priv);
+
+	ret = drm_vblank_init(dev, dev_priv->num_pipe);
+	if (ret)
+		goto out_err;
+
+	/*
+	 * Install interrupt handlers prior to powering off SGX or else we will
+	 * crash.
+	 */
+	dev_priv->vdc_irq_mask = 0;
+	dev_priv->pipestat[0] = 0;
+	dev_priv->pipestat[1] = 0;
+	dev_priv->pipestat[2] = 0;
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+	PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+	PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
+	PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_irq_install(dev);
+
+	dev->vblank_disable_allowed = 1;
+
+	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
+
+	dev->driver->get_vblank_counter = psb_get_vblank_counter;
+
+	if (drm_psb_no_fb == 0) {
+		psb_modeset_init(dev);
+		psb_fbdev_init(dev);
+		drm_kms_helper_poll_init(dev);
+	}
+
+	ret = psb_backlight_init(dev);
+	if (ret)
+		return ret;
+#if 0
+	/*enable runtime pm at last*/
+	pm_runtime_enable(&dev->pdev->dev);
+	pm_runtime_set_active(&dev->pdev->dev);
+#endif
+	/*Intel drm driver load is done, continue doing pvr load*/
+	DRM_DEBUG("Pvr driver load\n");
+
+/*	if (PVRCore_Init() < 0)
+		goto out_err; */
+/*	if (MRSTLFBInit(dev) < 0)
+		goto out_err;*/
+	return 0;
+out_err:
+	psb_driver_unload(dev);
+	return ret;
+}
+
+int psb_driver_device_is_agp(struct drm_device *dev)
+{
+	return 0;
+}
+
+
+static int psb_vt_leave_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct ttm_bo_device *bdev = &dev_priv->bdev;
+	struct ttm_mem_type_manager *man;
+	int ret;
+
+	ret = ttm_vt_lock(&dev_priv->ttm_lock, 1,
+			     psb_fpriv(file_priv)->tfile);
+	if (unlikely(ret != 0))
+		return ret;
+
+	ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_TT);
+	if (unlikely(ret != 0))
+		goto out_unlock;
+
+	man = &bdev->man[TTM_PL_TT];
+
+#if 0		/* What to do with this ? */
+	if (unlikely(!drm_mm_clean(&man->manager)))
+		DRM_INFO("Warning: GATT was not clean after VT switch.\n");
+#endif
+
+	ttm_bo_swapout_all(&dev_priv->bdev);
+
+	return 0;
+out_unlock:
+	(void) ttm_vt_unlock(&dev_priv->ttm_lock);
+	return ret;
+}
+
+static int psb_vt_enter_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	return ttm_vt_unlock(&dev_priv->ttm_lock);
+}
+
+static int psb_sizes_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct drm_psb_sizes_arg *arg =
+		(struct drm_psb_sizes_arg *) data;
+
+	*arg = dev_priv->sizes;
+	return 0;
+}
+
+static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
+				struct drm_file *file_priv)
+{
+	uint32_t flags;
+	uint32_t obj_id;
+	struct drm_mode_object *obj;
+	struct drm_connector *connector;
+	struct drm_crtc *crtc;
+	struct drm_psb_dc_state_arg *arg =
+		(struct drm_psb_dc_state_arg *)data;
+
+	flags = arg->flags;
+	obj_id = arg->obj_id;
+
+	if (flags & PSB_DC_CRTC_MASK) {
+		obj = drm_mode_object_find(dev, obj_id,
+				DRM_MODE_OBJECT_CRTC);
+		if (!obj) {
+			DRM_DEBUG("Invalid CRTC object.\n");
+			return -EINVAL;
+		}
+
+		crtc = obj_to_crtc(obj);
+
+		mutex_lock(&dev->mode_config.mutex);
+		if (drm_helper_crtc_in_use(crtc)) {
+			if (flags & PSB_DC_CRTC_SAVE)
+				crtc->funcs->save(crtc);
+			else
+				crtc->funcs->restore(crtc);
+		}
+		mutex_unlock(&dev->mode_config.mutex);
+
+		return 0;
+	} else if (flags & PSB_DC_OUTPUT_MASK) {
+		obj = drm_mode_object_find(dev, obj_id,
+				DRM_MODE_OBJECT_CONNECTOR);
+		if (!obj) {
+			DRM_DEBUG("Invalid connector id.\n");
+			return -EINVAL;
+		}
+
+		connector = obj_to_connector(obj);
+		if (flags & PSB_DC_OUTPUT_SAVE)
+			connector->funcs->save(connector);
+		else
+			connector->funcs->restore(connector);
+
+		return 0;
+	}
+
+	DRM_DEBUG("Bad flags 0x%x\n", flags);
+	return -EINVAL;
+}
+
+static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	uint32_t *arg = data;
+	struct backlight_device bd;
+	dev_priv->blc_adj2 = *arg;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	bd.props.brightness = psb_get_brightness(&bd);
+	psb_set_brightness(&bd);
+#endif
+	return 0;
+}
+
+static int psb_adb_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	uint32_t *arg = data;
+	struct backlight_device bd;
+	dev_priv->blc_adj1 = *arg;
+
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+	bd.props.brightness = psb_get_brightness(&bd);
+	psb_set_brightness(&bd);
+#endif
+	return 0;
+}
+
+/* return the current mode to the dpst module */
+static int psb_dpst_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	uint32_t *arg = data;
+	uint32_t x;
+	uint32_t y;
+	uint32_t reg;
+
+	if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON))
+		return 0;
+
+	reg = PSB_RVDC32(PIPEASRC);
+
+	ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+	/* horizontal is the left 16 bits */
+	x = reg >> 16;
+	/* vertical is the right 16 bits */
+	y = reg & 0x0000ffff;
+
+	/* the values are the image size minus one */
+	x++;
+	y++;
+
+	*arg = (x << 16) | y;
+
+	return 0;
+}
+static int psb_gamma_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	struct drm_psb_dpst_lut_arg *lut_arg = data;
+	struct drm_mode_object *obj;
+	struct drm_crtc *crtc;
+	struct drm_connector *connector;
+	struct psb_intel_crtc *psb_intel_crtc;
+	int i = 0;
+	int32_t obj_id;
+
+	obj_id = lut_arg->output_id;
+	obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR);
+	if (!obj) {
+		DRM_DEBUG("Invalid Connector object.\n");
+		return -EINVAL;
+	}
+
+	connector = obj_to_connector(obj);
+	crtc = connector->encoder->crtc;
+	psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+	for (i = 0; i < 256; i++)
+		psb_intel_crtc->lut_adj[i] = lut_arg->lut[i];
+
+	psb_intel_crtc_load_lut(crtc);
+
+	return 0;
+}
+
+static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	uint32_t obj_id;
+	uint16_t op;
+	struct drm_mode_modeinfo *umode;
+	struct drm_display_mode *mode = NULL;
+	struct drm_psb_mode_operation_arg *arg;
+	struct drm_mode_object *obj;
+	struct drm_connector *connector;
+	struct drm_framebuffer *drm_fb;
+	struct psb_framebuffer *psb_fb;
+	struct drm_connector_helper_funcs *connector_funcs;
+	int ret = 0;
+	int resp = MODE_OK;
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+
+	arg = (struct drm_psb_mode_operation_arg *)data;
+	obj_id = arg->obj_id;
+	op = arg->operation;
+
+	switch (op) {
+	case PSB_MODE_OPERATION_SET_DC_BASE:
+		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB);
+		if (!obj) {
+			DRM_ERROR("Invalid FB id %d\n", obj_id);
+			return -EINVAL;
+		}
+
+		drm_fb = obj_to_fb(obj);
+		psb_fb = to_psb_fb(drm_fb);
+
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+					      OSPM_UHB_ONLY_IF_ON)) {
+			REG_WRITE(DSPASURF, psb_fb->offset);
+			REG_READ(DSPASURF);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		} else {
+			dev_priv->saveDSPASURF = psb_fb->offset;
+		}
+
+		return 0;
+	case PSB_MODE_OPERATION_MODE_VALID:
+		umode = &arg->mode;
+
+		mutex_lock(&dev->mode_config.mutex);
+
+		obj = drm_mode_object_find(dev, obj_id,
+					DRM_MODE_OBJECT_CONNECTOR);
+		if (!obj) {
+			ret = -EINVAL;
+			goto mode_op_out;
+		}
+
+		connector = obj_to_connector(obj);
+
+		mode = drm_mode_create(dev);
+		if (!mode) {
+			ret = -ENOMEM;
+			goto mode_op_out;
+		}
+
+		/* drm_crtc_convert_umode(mode, umode); */
+		{
+			mode->clock = umode->clock;
+			mode->hdisplay = umode->hdisplay;
+			mode->hsync_start = umode->hsync_start;
+			mode->hsync_end = umode->hsync_end;
+			mode->htotal = umode->htotal;
+			mode->hskew = umode->hskew;
+			mode->vdisplay = umode->vdisplay;
+			mode->vsync_start = umode->vsync_start;
+			mode->vsync_end = umode->vsync_end;
+			mode->vtotal = umode->vtotal;
+			mode->vscan = umode->vscan;
+			mode->vrefresh = umode->vrefresh;
+			mode->flags = umode->flags;
+			mode->type = umode->type;
+			strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN);
+			mode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
+		}
+
+		connector_funcs = (struct drm_connector_helper_funcs *)
+				   connector->helper_private;
+
+		if (connector_funcs->mode_valid) {
+			resp = connector_funcs->mode_valid(connector, mode);
+			arg->data = (void *)resp;
+		}
+
+		/*do some clean up work*/
+		if (mode)
+			drm_mode_destroy(dev, mode);
+mode_op_out:
+		mutex_unlock(&dev->mode_config.mutex);
+		return ret;
+
+	default:
+		DRM_DEBUG("Unsupported psb mode operation");
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
+				   struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct drm_psb_stolen_memory_arg *arg = data;
+
+	arg->base = dev_priv->pg->stolen_base;
+	arg->size = dev_priv->pg->vram_stolen_size;
+
+	return 0;
+}
+
+static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct drm_psb_register_rw_arg *arg = data;
+	UHBUsage usage =
+	  arg->b_force_hw_on ? OSPM_UHB_FORCE_POWER_ON : OSPM_UHB_ONLY_IF_ON;
+
+	if (arg->display_write_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+				PSB_WVDC32(arg->display.pfit_controls,
+					   PFIT_CONTROL);
+			if (arg->display_write_mask &
+			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+				PSB_WVDC32(arg->display.pfit_autoscale_ratios,
+					   PFIT_AUTO_RATIOS);
+			if (arg->display_write_mask &
+			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+				PSB_WVDC32(
+				   arg->display.pfit_programmed_scale_ratios,
+				   PFIT_PGM_RATIOS);
+			if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+				PSB_WVDC32(arg->display.pipeasrc,
+					   PIPEASRC);
+			if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+				PSB_WVDC32(arg->display.pipebsrc,
+					   PIPEBSRC);
+			if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+				PSB_WVDC32(arg->display.vtotal_a,
+					   VTOTAL_A);
+			if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+				PSB_WVDC32(arg->display.vtotal_b,
+					   VTOTAL_B);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		} else {
+			if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS)
+				dev_priv->savePFIT_CONTROL =
+						arg->display.pfit_controls;
+			if (arg->display_write_mask &
+			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+				dev_priv->savePFIT_AUTO_RATIOS =
+					arg->display.pfit_autoscale_ratios;
+			if (arg->display_write_mask &
+			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+				dev_priv->savePFIT_PGM_RATIOS =
+				   arg->display.pfit_programmed_scale_ratios;
+			if (arg->display_write_mask & REGRWBITS_PIPEASRC)
+				dev_priv->savePIPEASRC = arg->display.pipeasrc;
+			if (arg->display_write_mask & REGRWBITS_PIPEBSRC)
+				dev_priv->savePIPEBSRC = arg->display.pipebsrc;
+			if (arg->display_write_mask & REGRWBITS_VTOTAL_A)
+				dev_priv->saveVTOTAL_A = arg->display.vtotal_a;
+			if (arg->display_write_mask & REGRWBITS_VTOTAL_B)
+				dev_priv->saveVTOTAL_B = arg->display.vtotal_b;
+		}
+	}
+
+	if (arg->display_read_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			if (arg->display_read_mask &
+			    REGRWBITS_PFIT_CONTROLS)
+				arg->display.pfit_controls =
+						PSB_RVDC32(PFIT_CONTROL);
+			if (arg->display_read_mask &
+			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+				arg->display.pfit_autoscale_ratios =
+						PSB_RVDC32(PFIT_AUTO_RATIOS);
+			if (arg->display_read_mask &
+			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+				arg->display.pfit_programmed_scale_ratios =
+						PSB_RVDC32(PFIT_PGM_RATIOS);
+			if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+				arg->display.pipeasrc = PSB_RVDC32(PIPEASRC);
+			if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+				arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC);
+			if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+				arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A);
+			if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+				arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		} else {
+			if (arg->display_read_mask &
+			    REGRWBITS_PFIT_CONTROLS)
+				arg->display.pfit_controls =
+						dev_priv->savePFIT_CONTROL;
+			if (arg->display_read_mask &
+			    REGRWBITS_PFIT_AUTOSCALE_RATIOS)
+				arg->display.pfit_autoscale_ratios =
+						dev_priv->savePFIT_AUTO_RATIOS;
+			if (arg->display_read_mask &
+			    REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS)
+				arg->display.pfit_programmed_scale_ratios =
+						dev_priv->savePFIT_PGM_RATIOS;
+			if (arg->display_read_mask & REGRWBITS_PIPEASRC)
+				arg->display.pipeasrc = dev_priv->savePIPEASRC;
+			if (arg->display_read_mask & REGRWBITS_PIPEBSRC)
+				arg->display.pipebsrc = dev_priv->savePIPEBSRC;
+			if (arg->display_read_mask & REGRWBITS_VTOTAL_A)
+				arg->display.vtotal_a = dev_priv->saveVTOTAL_A;
+			if (arg->display_read_mask & REGRWBITS_VTOTAL_B)
+				arg->display.vtotal_b = dev_priv->saveVTOTAL_B;
+		}
+	}
+
+	if (arg->overlay_write_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+				PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5);
+				PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4);
+				PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3);
+				PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2);
+				PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1);
+				PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0);
+			}
+			if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+				PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5);
+				PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4);
+				PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3);
+				PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2);
+				PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1);
+				PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0);
+			}
+
+			if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) {
+				PSB_WVDC32(arg->overlay.OVADD, OV_OVADD);
+
+				if (arg->overlay.b_wait_vblank) {
+					/* Wait for 20ms.*/
+					unsigned long vblank_timeout = jiffies
+								+ HZ/50;
+					uint32_t temp;
+					while (time_before_eq(jiffies,
+							vblank_timeout)) {
+						temp = PSB_RVDC32(OV_DOVASTA);
+						if ((temp & (0x1 << 31)) != 0)
+							break;
+						cpu_relax();
+					}
+				}
+			}
+			if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) {
+				PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD);
+				if (arg->overlay.b_wait_vblank) {
+					/* Wait for 20ms.*/
+					unsigned long vblank_timeout =
+							jiffies + HZ/50;
+					uint32_t temp;
+					while (time_before_eq(jiffies,
+							vblank_timeout)) {
+						temp = PSB_RVDC32(OVC_DOVCSTA);
+						if ((temp & (0x1 << 31)) != 0)
+							break;
+						cpu_relax();
+					}
+				}
+			}
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		} else {
+			if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) {
+				dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5;
+				dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4;
+				dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3;
+				dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2;
+				dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1;
+				dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0;
+			}
+			if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) {
+				dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5;
+				dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4;
+				dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3;
+				dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2;
+				dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1;
+				dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0;
+			}
+			if (arg->overlay_write_mask & OV_REGRWBITS_OVADD)
+				dev_priv->saveOV_OVADD = arg->overlay.OVADD;
+			if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD)
+				dev_priv->saveOVC_OVADD = arg->overlay.OVADD;
+		}
+	}
+
+	if (arg->overlay_read_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+				arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5);
+				arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4);
+				arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3);
+				arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2);
+				arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1);
+				arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0);
+			}
+			if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+				arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5);
+				arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4);
+				arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3);
+				arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2);
+				arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1);
+				arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0);
+			}
+			if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+				arg->overlay.OVADD = PSB_RVDC32(OV_OVADD);
+			if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+				arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		} else {
+			if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) {
+				arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5;
+				arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4;
+				arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3;
+				arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2;
+				arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1;
+				arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0;
+			}
+			if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) {
+				arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5;
+				arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4;
+				arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3;
+				arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2;
+				arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1;
+				arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0;
+			}
+			if (arg->overlay_read_mask & OV_REGRWBITS_OVADD)
+				arg->overlay.OVADD = dev_priv->saveOV_OVADD;
+			if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD)
+				arg->overlay.OVADD = dev_priv->saveOVC_OVADD;
+		}
+	}
+
+	if (arg->sprite_enable_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			PSB_WVDC32(0x1F3E, DSPARB);
+			PSB_WVDC32(arg->sprite.dspa_control
+					| PSB_RVDC32(DSPACNTR), DSPACNTR);
+			PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL);
+			PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK);
+			PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF);
+			PSB_RVDC32(DSPASURF);
+			PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR);
+			PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE);
+			PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS);
+			PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF);
+			PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE);
+			PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+			PSB_RVDC32(DSPCSURF);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+
+	if (arg->sprite_disable_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			PSB_WVDC32(0x3F3E, DSPARB);
+			PSB_WVDC32(0x0, DSPCCNTR);
+			PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF);
+			PSB_RVDC32(DSPCSURF);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+
+	if (arg->subpicture_enable_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			uint32_t temp;
+			if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) {
+				temp =  PSB_RVDC32(DSPACNTR);
+				temp &= ~DISPPLANE_PIXFORMAT_MASK;
+				temp &= ~DISPPLANE_BOTTOM;
+				temp |= DISPPLANE_32BPP;
+				PSB_WVDC32(temp, DSPACNTR);
+
+				temp =  PSB_RVDC32(DSPABASE);
+				PSB_WVDC32(temp, DSPABASE);
+				PSB_RVDC32(DSPABASE);
+				temp =  PSB_RVDC32(DSPASURF);
+				PSB_WVDC32(temp, DSPASURF);
+				PSB_RVDC32(DSPASURF);
+			}
+			if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) {
+				temp =  PSB_RVDC32(DSPBCNTR);
+				temp &= ~DISPPLANE_PIXFORMAT_MASK;
+				temp &= ~DISPPLANE_BOTTOM;
+				temp |= DISPPLANE_32BPP;
+				PSB_WVDC32(temp, DSPBCNTR);
+
+				temp =  PSB_RVDC32(DSPBBASE);
+				PSB_WVDC32(temp, DSPBBASE);
+				PSB_RVDC32(DSPBBASE);
+				temp =  PSB_RVDC32(DSPBSURF);
+				PSB_WVDC32(temp, DSPBSURF);
+				PSB_RVDC32(DSPBSURF);
+			}
+			if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) {
+				temp =  PSB_RVDC32(DSPCCNTR);
+				temp &= ~DISPPLANE_PIXFORMAT_MASK;
+				temp &= ~DISPPLANE_BOTTOM;
+				temp |= DISPPLANE_32BPP;
+				PSB_WVDC32(temp, DSPCCNTR);
+
+				temp =  PSB_RVDC32(DSPCBASE);
+				PSB_WVDC32(temp, DSPCBASE);
+				PSB_RVDC32(DSPCBASE);
+				temp =  PSB_RVDC32(DSPCSURF);
+				PSB_WVDC32(temp, DSPCSURF);
+				PSB_RVDC32(DSPCSURF);
+			}
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+
+	if (arg->subpicture_disable_mask != 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, usage)) {
+			uint32_t temp;
+			if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) {
+				temp =  PSB_RVDC32(DSPACNTR);
+				temp &= ~DISPPLANE_PIXFORMAT_MASK;
+				temp |= DISPPLANE_32BPP_NO_ALPHA;
+				PSB_WVDC32(temp, DSPACNTR);
+
+				temp =  PSB_RVDC32(DSPABASE);
+				PSB_WVDC32(temp, DSPABASE);
+				PSB_RVDC32(DSPABASE);
+				temp =  PSB_RVDC32(DSPASURF);
+				PSB_WVDC32(temp, DSPASURF);
+				PSB_RVDC32(DSPASURF);
+			}
+			if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) {
+				temp =  PSB_RVDC32(DSPBCNTR);
+				temp &= ~DISPPLANE_PIXFORMAT_MASK;
+				temp |= DISPPLANE_32BPP_NO_ALPHA;
+				PSB_WVDC32(temp, DSPBCNTR);
+
+				temp =  PSB_RVDC32(DSPBBASE);
+				PSB_WVDC32(temp, DSPBBASE);
+				PSB_RVDC32(DSPBBASE);
+				temp =  PSB_RVDC32(DSPBSURF);
+				PSB_WVDC32(temp, DSPBSURF);
+				PSB_RVDC32(DSPBSURF);
+			}
+			if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) {
+				temp =  PSB_RVDC32(DSPCCNTR);
+				temp &= ~DISPPLANE_PIXFORMAT_MASK;
+				temp |= DISPPLANE_32BPP_NO_ALPHA;
+				PSB_WVDC32(temp, DSPCCNTR);
+
+				temp =  PSB_RVDC32(DSPCBASE);
+				PSB_WVDC32(temp, DSPCBASE);
+				PSB_RVDC32(DSPCBASE);
+				temp =  PSB_RVDC32(DSPCSURF);
+				PSB_WVDC32(temp, DSPCSURF);
+				PSB_RVDC32(DSPCSURF);
+			}
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+
+	return 0;
+}
+
+/* always available as we are SIGIO'd */
+static unsigned int psb_poll(struct file *filp,
+			     struct poll_table_struct *wait)
+{
+	return POLLIN | POLLRDNORM;
+}
+
+/* Not sure what we will need yet - in the PVR driver this disappears into
+   a tangle of abstracted handlers and per process crap */
+
+struct psb_priv {
+	int dummy;
+};
+
+static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
+{
+	struct psb_priv *psb = kzalloc(sizeof(struct psb_priv), GFP_KERNEL);
+	if (psb == NULL)
+		return -ENOMEM;
+	priv->driver_priv = psb;
+	DRM_DEBUG("\n");
+	/*return PVRSRVOpen(dev, priv);*/
+	return 0;
+}
+
+static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
+{
+	kfree(priv->driver_priv);
+	priv->driver_priv = NULL;
+}
+
+static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct drm_file *file_priv = filp->private_data;
+	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	static unsigned int runtime_allowed;
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+
+	DRM_DEBUG("cmd = %x, nr = %x\n", cmd, nr);
+
+	if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
+		runtime_allowed++;
+		pm_runtime_allow(&dev->pdev->dev);
+		dev_priv->rpm_enabled = 1;
+	}
+	/*
+	 * The driver private ioctls and TTM ioctls should be
+	 * thread-safe.
+	 */
+
+	if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
+	     && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
+		struct drm_ioctl_desc *ioctl =
+					&psb_ioctls[nr - DRM_COMMAND_BASE];
+
+		if (unlikely(ioctl->cmd != cmd)) {
+			DRM_ERROR(
+				"Invalid drm cmnd %d ioctl->cmd %x, cmd %x\n",
+				nr - DRM_COMMAND_BASE, ioctl->cmd, cmd);
+			return -EINVAL;
+		}
+
+		return drm_ioctl(filp, cmd, arg);
+	}
+	/*
+	 * Not all old drm ioctls are thread-safe.
+	 */
+
+	return drm_ioctl(filp, cmd, arg);
+}
+
+
+/* When a client dies:
+ *    - Check for and clean up flipped page state
+ */
+void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
+{
+}
+
+static void psb_remove(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	drm_put_dev(dev);
+}
+
+
+static const struct dev_pm_ops psb_pm_ops = {
+	.runtime_suspend = psb_runtime_suspend,
+	.runtime_resume = psb_runtime_resume,
+	.runtime_idle = psb_runtime_idle,
+};
+
+static struct drm_driver driver = {
+	.driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
+			   DRIVER_IRQ_VBL | DRIVER_MODESET,
+	.load = psb_driver_load,
+	.unload = psb_driver_unload,
+
+	.ioctls = psb_ioctls,
+	.num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
+	.device_is_agp = psb_driver_device_is_agp,
+	.irq_preinstall = psb_irq_preinstall,
+	.irq_postinstall = psb_irq_postinstall,
+	.irq_uninstall = psb_irq_uninstall,
+	.irq_handler = psb_irq_handler,
+	.enable_vblank = psb_enable_vblank,
+	.disable_vblank = psb_disable_vblank,
+	.get_vblank_counter = psb_get_vblank_counter,
+	.firstopen = NULL,
+	.lastclose = psb_lastclose,
+	.open = psb_driver_open,
+	.postclose = psb_driver_close,
+#if 0	/* ACFIXME */
+	.get_map_ofs = drm_core_get_map_ofs,
+	.get_reg_ofs = drm_core_get_reg_ofs,
+	.proc_init = psb_proc_init,
+	.proc_cleanup = psb_proc_cleanup,
+#endif
+	.preclose = psb_driver_preclose,
+	.fops = {
+		 .owner = THIS_MODULE,
+		 .open = psb_open,
+		 .release = psb_release,
+		 .unlocked_ioctl = psb_unlocked_ioctl,
+		 .mmap = psb_mmap,
+		 .poll = psb_poll,
+		 .fasync = drm_fasync,
+		 .read = drm_read,
+		 },
+	.name = DRIVER_NAME,
+	.desc = DRIVER_DESC,
+	.date = PSB_DRM_DRIVER_DATE,
+	.major = PSB_DRM_DRIVER_MAJOR,
+	.minor = PSB_DRM_DRIVER_MINOR,
+	.patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
+};
+
+static struct pci_driver psb_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+	.resume = ospm_power_resume,
+	.suspend = ospm_power_suspend,
+	.probe = psb_probe,
+	.remove = psb_remove,
+#ifdef CONFIG_PM
+	.driver.pm = &psb_pm_ops,
+#endif
+};
+
+static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	/* MLD Added this from Inaky's patch */
+	if (pci_enable_msi(pdev))
+		DRM_ERROR("Enable MSI failed!\n");
+	return drm_get_pci_dev(pdev, ent, &driver);
+}
+
+static int __init psb_init(void)
+{
+	return drm_pci_init(&driver, &psb_pci_driver);
+}
+
+static void __exit psb_exit(void)
+{
+	drm_pci_exit(&driver, &psb_pci_driver);
+}
+
+late_initcall(psb_init);
+module_exit(psb_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
new file mode 100644
index 0000000..29a3605
--- /dev/null
+++ b/drivers/staging/gma500/psb_drv.h
@@ -0,0 +1,1151 @@
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_DRV_H_
+#define _PSB_DRV_H_
+
+#include <linux/version.h>
+
+#include <drm/drmP.h>
+#include "drm_global.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_gtt.h"
+#include "psb_powermgmt.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_driver.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_lock.h"
+
+/*Append new drm mode definition here, align with libdrm definition*/
+#define DRM_MODE_SCALE_NO_SCALE   2
+
+extern struct ttm_bo_driver psb_ttm_bo_driver;
+
+enum {
+	CHIP_PSB_8108 = 0,
+	CHIP_PSB_8109 = 1,
+};
+
+/*
+ *Hardware bugfixes
+ */
+
+#define DRIVER_NAME "pvrsrvkm"
+#define DRIVER_DESC "drm driver for the Intel GMA500"
+#define DRIVER_AUTHOR "Intel Corporation"
+#define OSPM_PROC_ENTRY "ospm"
+#define RTPM_PROC_ENTRY "rtpm"
+#define BLC_PROC_ENTRY "mrst_blc"
+#define DISPLAY_PROC_ENTRY "display_status"
+
+#define PSB_DRM_DRIVER_DATE "2009-03-10"
+#define PSB_DRM_DRIVER_MAJOR 8
+#define PSB_DRM_DRIVER_MINOR 1
+#define PSB_DRM_DRIVER_PATCHLEVEL 0
+
+/*
+ *TTM driver private offsets.
+ */
+
+#define DRM_PSB_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
+
+#define PSB_OBJECT_HASH_ORDER 13
+#define PSB_FILE_OBJECT_HASH_ORDER 12
+#define PSB_BO_HASH_ORDER 12
+
+#define PSB_VDC_OFFSET		 0x00000000
+#define PSB_VDC_SIZE		 0x000080000
+#define MRST_MMIO_SIZE		 0x0000C0000
+#define MDFLD_MMIO_SIZE          0x000100000
+#define PSB_SGX_SIZE		 0x8000
+#define PSB_SGX_OFFSET		 0x00040000
+#define MRST_SGX_OFFSET		 0x00080000
+#define PSB_MMIO_RESOURCE	 0
+#define PSB_GATT_RESOURCE	 2
+#define PSB_GTT_RESOURCE	 3
+#define PSB_GMCH_CTRL		 0x52
+#define PSB_BSM			 0x5C
+#define _PSB_GMCH_ENABLED	 0x4
+#define PSB_PGETBL_CTL		 0x2020
+#define _PSB_PGETBL_ENABLED	 0x00000001
+#define PSB_SGX_2D_SLAVE_PORT	 0x4000
+#define PSB_TT_PRIV0_LIMIT	 (256*1024*1024)
+#define PSB_TT_PRIV0_PLIMIT	 (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
+#define PSB_NUM_VALIDATE_BUFFERS 2048
+
+#define PSB_MEM_MMU_START       0x00000000
+#define PSB_MEM_TT_START        0xE0000000
+
+#define PSB_GL3_CACHE_CTL	0x2100
+#define PSB_GL3_CACHE_STAT	0x2108
+
+/*
+ *Flags for external memory type field.
+ */
+
+#define MRST_MSVDX_OFFSET	0x90000	/*MSVDX Base offset */
+#define PSB_MSVDX_OFFSET	0x50000	/*MSVDX Base offset */
+/* MSVDX MMIO region is 0x50000 - 0x57fff ==> 32KB */
+#define PSB_MSVDX_SIZE		0x10000
+
+#define LNC_TOPAZ_OFFSET	0xA0000
+#define PNW_TOPAZ_OFFSET	0xC0000
+#define PNW_GL3_OFFSET		0xB0000
+#define LNC_TOPAZ_SIZE		0x10000
+#define PNW_TOPAZ_SIZE		0x30000 /* PNW VXE285 has two cores */
+#define PSB_MMU_CACHED_MEMORY	  0x0001	/* Bind to MMU only */
+#define PSB_MMU_RO_MEMORY	  0x0002	/* MMU RO memory */
+#define PSB_MMU_WO_MEMORY	  0x0004	/* MMU WO memory */
+
+/*
+ *PTE's and PDE's
+ */
+
+#define PSB_PDE_MASK		  0x003FFFFF
+#define PSB_PDE_SHIFT		  22
+#define PSB_PTE_SHIFT		  12
+
+#define PSB_PTE_VALID		  0x0001	/* PTE / PDE valid */
+#define PSB_PTE_WO		  0x0002	/* Write only */
+#define PSB_PTE_RO		  0x0004	/* Read only */
+#define PSB_PTE_CACHED		  0x0008	/* CPU cache coherent */
+
+/*
+ *VDC registers and bits
+ */
+#define PSB_MSVDX_CLOCKGATING	  0x2064
+#define PSB_TOPAZ_CLOCKGATING	  0x2068
+#define PSB_HWSTAM		  0x2098
+#define PSB_INSTPM		  0x20C0
+#define PSB_INT_IDENTITY_R        0x20A4
+#define _MDFLD_PIPEC_EVENT_FLAG   (1<<2)
+#define _MDFLD_PIPEC_VBLANK_FLAG  (1<<3)
+#define _PSB_DPST_PIPEB_FLAG      (1<<4)
+#define _MDFLD_PIPEB_EVENT_FLAG   (1<<4)
+#define _PSB_VSYNC_PIPEB_FLAG	  (1<<5)
+#define _PSB_DPST_PIPEA_FLAG      (1<<6)
+#define _PSB_PIPEA_EVENT_FLAG     (1<<6)
+#define _PSB_VSYNC_PIPEA_FLAG	  (1<<7)
+#define _MDFLD_MIPIA_FLAG	  (1<<16)
+#define _MDFLD_MIPIC_FLAG	  (1<<17)
+#define _PSB_IRQ_SGX_FLAG	  (1<<18)
+#define _PSB_IRQ_MSVDX_FLAG	  (1<<19)
+#define _LNC_IRQ_TOPAZ_FLAG	  (1<<20)
+
+/* This flag includes all the display IRQ bits excepts the vblank irqs. */
+#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | _MDFLD_PIPEB_EVENT_FLAG | \
+        _PSB_PIPEA_EVENT_FLAG | _PSB_VSYNC_PIPEA_FLAG | _MDFLD_MIPIA_FLAG | _MDFLD_MIPIC_FLAG)
+#define PSB_INT_IDENTITY_R	  0x20A4
+#define PSB_INT_MASK_R		  0x20A8
+#define PSB_INT_ENABLE_R	  0x20A0
+
+#define _PSB_MMU_ER_MASK      0x0001FF00
+#define _PSB_MMU_ER_HOST      (1 << 16)
+#define GPIOA			0x5010
+#define GPIOB			0x5014
+#define GPIOC			0x5018
+#define GPIOD			0x501c
+#define GPIOE			0x5020
+#define GPIOF			0x5024
+#define GPIOG			0x5028
+#define GPIOH			0x502c
+#define GPIO_CLOCK_DIR_MASK		(1 << 0)
+#define GPIO_CLOCK_DIR_IN		(0 << 1)
+#define GPIO_CLOCK_DIR_OUT		(1 << 1)
+#define GPIO_CLOCK_VAL_MASK		(1 << 2)
+#define GPIO_CLOCK_VAL_OUT		(1 << 3)
+#define GPIO_CLOCK_VAL_IN		(1 << 4)
+#define GPIO_CLOCK_PULLUP_DISABLE	(1 << 5)
+#define GPIO_DATA_DIR_MASK		(1 << 8)
+#define GPIO_DATA_DIR_IN		(0 << 9)
+#define GPIO_DATA_DIR_OUT		(1 << 9)
+#define GPIO_DATA_VAL_MASK		(1 << 10)
+#define GPIO_DATA_VAL_OUT		(1 << 11)
+#define GPIO_DATA_VAL_IN		(1 << 12)
+#define GPIO_DATA_PULLUP_DISABLE	(1 << 13)
+
+#define VCLK_DIVISOR_VGA0   0x6000
+#define VCLK_DIVISOR_VGA1   0x6004
+#define VCLK_POST_DIV	    0x6010
+
+#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
+#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
+#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
+#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
+#define PSB_COMM_USER_IRQ (1024 >> 2)
+#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
+#define PSB_COMM_FW (2048 >> 2)
+
+#define PSB_UIRQ_VISTEST	       1
+#define PSB_UIRQ_OOM_REPLY	       2
+#define PSB_UIRQ_FIRE_TA_REPLY	       3
+#define PSB_UIRQ_FIRE_RASTER_REPLY     4
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+
+
+#define PSB_2D_SIZE (256*1024*1024)
+#define PSB_MAX_RELOC_PAGES 1024
+
+#define PSB_LOW_REG_OFFS 0x0204
+#define PSB_HIGH_REG_OFFS 0x0600
+
+#define PSB_NUM_VBLANKS 2
+#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
+#define PSB_LID_DELAY (DRM_HZ / 10)
+
+#define MDFLD_PNW_A0 0x00
+#define MDFLD_PNW_B0 0x04
+#define MDFLD_PNW_C0 0x08
+
+#define MDFLD_DSR_2D_3D_0 BIT0
+#define MDFLD_DSR_2D_3D_2 BIT1
+#define MDFLD_DSR_CURSOR_0 BIT2
+#define MDFLD_DSR_CURSOR_2 BIT3
+#define MDFLD_DSR_OVERLAY_0 BIT4
+#define MDFLD_DSR_OVERLAY_2 BIT5
+#define MDFLD_DSR_MIPI_CONTROL	BIT6
+#define MDFLD_DSR_2D_3D 	(MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
+
+#define MDFLD_DSR_RR 45
+#define MDFLD_DPU_ENABLE BIT31
+#define MDFLD_DSR_FULLSCREEN BIT30
+#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
+
+#define PSB_PWR_STATE_ON		1
+#define PSB_PWR_STATE_OFF		2
+
+#define PSB_PMPOLICY_NOPM		0
+#define PSB_PMPOLICY_CLOCKGATING	1
+#define PSB_PMPOLICY_POWERDOWN		2
+
+#define PSB_PMSTATE_POWERUP		0
+#define PSB_PMSTATE_CLOCKGATED		1
+#define PSB_PMSTATE_POWERDOWN		2
+#define PSB_PCIx_MSI_ADDR_LOC		0x94
+#define PSB_PCIx_MSI_DATA_LOC		0x98
+
+#define MDFLD_PLANE_MAX_WIDTH		2048
+#define MDFLD_PLANE_MAX_HEIGHT		2048
+
+struct opregion_header;
+struct opregion_acpi;
+struct opregion_swsci;
+struct opregion_asle;
+
+struct psb_intel_opregion {
+	struct opregion_header *header;
+	struct opregion_acpi *acpi;
+	struct opregion_swsci *swsci;
+	struct opregion_asle *asle;
+	int enabled;
+};
+
+/*
+ *User options.
+ */
+
+struct drm_psb_uopt {
+	int pad; /*keep it here in case we use it in future*/
+};
+
+/**
+ *struct psb_context
+ *
+ *@buffers:	 array of pre-allocated validate buffers.
+ *@used_buffers: number of buffers in @buffers array currently in use.
+ *@validate_buffer: buffers validated from user-space.
+ *@kern_validate_buffers : buffers validated from kernel-space.
+ *@fence_flags : Fence flags to be used for fence creation.
+ *
+ *This structure is used during execbuf validation.
+ */
+
+struct psb_context {
+	struct psb_validate_buffer *buffers;
+	uint32_t used_buffers;
+	struct list_head validate_list;
+	struct list_head kern_validate_list;
+	uint32_t fence_types;
+	uint32_t val_seq;
+};
+
+struct psb_validate_buffer;
+
+/* Currently defined profiles */
+enum VAProfile {
+	VAProfileMPEG2Simple		= 0,
+	VAProfileMPEG2Main		= 1,
+	VAProfileMPEG4Simple		= 2,
+	VAProfileMPEG4AdvancedSimple	= 3,
+	VAProfileMPEG4Main		= 4,
+	VAProfileH264Baseline		= 5,
+	VAProfileH264Main		= 6,
+	VAProfileH264High		= 7,
+	VAProfileVC1Simple		= 8,
+	VAProfileVC1Main		= 9,
+	VAProfileVC1Advanced		= 10,
+	VAProfileH263Baseline		= 11,
+	VAProfileJPEGBaseline           = 12,
+	VAProfileH264ConstrainedBaseline = 13
+};
+
+/* Currently defined entrypoints */
+enum VAEntrypoint {
+	VAEntrypointVLD		= 1,
+	VAEntrypointIZZ		= 2,
+	VAEntrypointIDCT	= 3,
+	VAEntrypointMoComp	= 4,
+	VAEntrypointDeblocking	= 5,
+	VAEntrypointEncSlice	= 6,	/* slice level encode */
+	VAEntrypointEncPicture 	= 7	/* pictuer encode, JPEG, etc */
+};
+
+
+struct psb_video_ctx {
+	struct list_head head;
+	struct file *filp; /* DRM device file pointer */
+	int ctx_type; /* profile<<8|entrypoint */
+	/* todo: more context specific data for multi-context support */
+};
+
+#define MODE_SETTING_IN_CRTC 	0x1
+#define MODE_SETTING_IN_ENCODER 0x2
+#define MODE_SETTING_ON_GOING 	0x3
+#define MODE_SETTING_IN_DSR 	0x4
+#define MODE_SETTING_ENCODER_DONE 0x8
+#define GCT_R10_HEADER_SIZE	16
+#define GCT_R10_DISPLAY_DESC_SIZE	28
+
+struct drm_psb_private {
+	/*
+	 * DSI info.
+	 */
+	void * dbi_dsr_info;
+	void * dsi_configs[2];
+
+	/*
+	 *TTM Glue.
+	 */
+
+	struct drm_global_reference mem_global_ref;
+	struct ttm_bo_global_ref bo_global_ref;
+	int has_global;
+
+	struct drm_device *dev;
+	struct ttm_object_device *tdev;
+	struct ttm_fence_device fdev;
+	struct ttm_bo_device bdev;
+	struct ttm_lock ttm_lock;
+	struct vm_operations_struct *ttm_vm_ops;
+	int has_fence_device;
+	int has_bo_device;
+
+	unsigned long chipset;
+
+	struct drm_psb_uopt uopt;
+
+	struct psb_gtt *pg;
+
+	/*GTT Memory manager*/
+	struct psb_gtt_mm *gtt_mm;
+
+	struct page *scratch_page;
+	uint32_t sequence[PSB_NUM_ENGINES];
+	uint32_t last_sequence[PSB_NUM_ENGINES];
+	uint32_t last_submitted_seq[PSB_NUM_ENGINES];
+
+	struct psb_mmu_driver *mmu;
+	struct psb_mmu_pd *pf_pd;
+
+	uint8_t *sgx_reg;
+	uint8_t *vdc_reg;
+	uint32_t gatt_free_offset;
+
+	/* IMG video context */
+	struct list_head video_ctx;
+
+
+
+	/*
+	 *Fencing / irq.
+	 */
+
+	uint32_t vdc_irq_mask;
+	uint32_t pipestat[PSB_NUM_PIPE];
+	bool vblanksEnabledForFlips;
+
+	spinlock_t irqmask_lock;
+	spinlock_t sequence_lock;
+
+	/*
+	 *Modesetting
+	 */
+	struct psb_intel_mode_device mode_dev;
+
+	struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
+	struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
+	uint32_t num_pipe;
+
+	/*
+	 * CI share buffer
+	 */
+	unsigned int ci_region_start;
+	unsigned int ci_region_size;
+
+	/*
+	 * RAR share buffer;
+	 */
+	unsigned int rar_region_start;
+	unsigned int rar_region_size;
+
+	/*
+	 *Memory managers
+	 */
+
+	int have_camera;
+	int have_rar;
+	int have_tt;
+	int have_mem_mmu;
+	struct mutex temp_mem;
+
+	/*
+	 *Relocation buffer mapping.
+	 */
+
+	spinlock_t reloc_lock;
+	unsigned int rel_mapped_pages;
+	wait_queue_head_t rel_mapped_queue;
+
+	/*
+	 *SAREA
+	 */
+	struct drm_psb_sarea *sarea_priv;
+
+	/*
+	*OSPM info
+	*/
+	uint32_t ospm_base;
+
+	/*
+	 * Sizes info
+	 */
+
+	struct drm_psb_sizes_arg sizes;
+
+	uint32_t fuse_reg_value;
+
+	/* pci revision id for B0:D2:F0 */
+	uint8_t platform_rev_id;
+
+	/*
+	 *LVDS info
+	 */
+	int backlight_duty_cycle;	/* restore backlight to this value */
+	bool panel_wants_dither;
+	struct drm_display_mode *panel_fixed_mode;
+	struct drm_display_mode *lfp_lvds_vbt_mode;
+	struct drm_display_mode *sdvo_lvds_vbt_mode;
+
+	struct bdb_lvds_backlight *lvds_bl; /*LVDS backlight info from VBT*/
+	struct psb_intel_i2c_chan *lvds_i2c_bus;
+
+	/* Feature bits from the VBIOS*/
+	unsigned int int_tv_support:1;
+	unsigned int lvds_dither:1;
+	unsigned int lvds_vbt:1;
+	unsigned int int_crt_support:1;
+	unsigned int lvds_use_ssc:1;
+	int lvds_ssc_freq;
+	bool is_lvds_on;
+
+	unsigned int core_freq;
+	uint32_t iLVDS_enable;
+
+	/*runtime PM state*/
+	int rpm_enabled;
+
+	/*
+	 *Register state
+	 */
+	uint32_t saveDSPACNTR;
+	uint32_t saveDSPBCNTR;
+	uint32_t savePIPEACONF;
+	uint32_t savePIPEBCONF;
+	uint32_t savePIPEASRC;
+	uint32_t savePIPEBSRC;
+	uint32_t saveFPA0;
+	uint32_t saveFPA1;
+	uint32_t saveDPLL_A;
+	uint32_t saveDPLL_A_MD;
+	uint32_t saveHTOTAL_A;
+	uint32_t saveHBLANK_A;
+	uint32_t saveHSYNC_A;
+	uint32_t saveVTOTAL_A;
+	uint32_t saveVBLANK_A;
+	uint32_t saveVSYNC_A;
+	uint32_t saveDSPASTRIDE;
+	uint32_t saveDSPASIZE;
+	uint32_t saveDSPAPOS;
+	uint32_t saveDSPABASE;
+	uint32_t saveDSPASURF;
+	uint32_t saveFPB0;
+	uint32_t saveFPB1;
+	uint32_t saveDPLL_B;
+	uint32_t saveDPLL_B_MD;
+	uint32_t saveHTOTAL_B;
+	uint32_t saveHBLANK_B;
+	uint32_t saveHSYNC_B;
+	uint32_t saveVTOTAL_B;
+	uint32_t saveVBLANK_B;
+	uint32_t saveVSYNC_B;
+	uint32_t saveDSPBSTRIDE;
+	uint32_t saveDSPBSIZE;
+	uint32_t saveDSPBPOS;
+	uint32_t saveDSPBBASE;
+	uint32_t saveDSPBSURF;
+	uint32_t saveVCLK_DIVISOR_VGA0;
+	uint32_t saveVCLK_DIVISOR_VGA1;
+	uint32_t saveVCLK_POST_DIV;
+	uint32_t saveVGACNTRL;
+	uint32_t saveADPA;
+	uint32_t saveLVDS;
+	uint32_t saveDVOA;
+	uint32_t saveDVOB;
+	uint32_t saveDVOC;
+	uint32_t savePP_ON;
+	uint32_t savePP_OFF;
+	uint32_t savePP_CONTROL;
+	uint32_t savePP_CYCLE;
+	uint32_t savePFIT_CONTROL;
+	uint32_t savePaletteA[256];
+	uint32_t savePaletteB[256];
+	uint32_t saveBLC_PWM_CTL2;
+	uint32_t saveBLC_PWM_CTL;
+	uint32_t saveCLOCKGATING;
+	uint32_t saveDSPARB;
+	uint32_t saveDSPATILEOFF;
+	uint32_t saveDSPBTILEOFF;
+	uint32_t saveDSPAADDR;
+	uint32_t saveDSPBADDR;
+	uint32_t savePFIT_AUTO_RATIOS;
+	uint32_t savePFIT_PGM_RATIOS;
+	uint32_t savePP_ON_DELAYS;
+	uint32_t savePP_OFF_DELAYS;
+	uint32_t savePP_DIVISOR;
+	uint32_t saveBSM;
+	uint32_t saveVBT;
+	uint32_t saveBCLRPAT_A;
+	uint32_t saveBCLRPAT_B;
+	uint32_t saveDSPALINOFF;
+	uint32_t saveDSPBLINOFF;
+	uint32_t savePERF_MODE;
+	uint32_t saveDSPFW1;
+	uint32_t saveDSPFW2;
+	uint32_t saveDSPFW3;
+	uint32_t saveDSPFW4;
+	uint32_t saveDSPFW5;
+	uint32_t saveDSPFW6;
+	uint32_t saveCHICKENBIT;
+	uint32_t saveDSPACURSOR_CTRL;
+	uint32_t saveDSPBCURSOR_CTRL;
+	uint32_t saveDSPACURSOR_BASE;
+	uint32_t saveDSPBCURSOR_BASE;
+	uint32_t saveDSPACURSOR_POS;
+	uint32_t saveDSPBCURSOR_POS;
+	uint32_t save_palette_a[256];
+	uint32_t save_palette_b[256];
+	uint32_t saveOV_OVADD;
+	uint32_t saveOV_OGAMC0;
+	uint32_t saveOV_OGAMC1;
+	uint32_t saveOV_OGAMC2;
+	uint32_t saveOV_OGAMC3;
+	uint32_t saveOV_OGAMC4;
+	uint32_t saveOV_OGAMC5;
+	uint32_t saveOVC_OVADD;
+	uint32_t saveOVC_OGAMC0;
+	uint32_t saveOVC_OGAMC1;
+	uint32_t saveOVC_OGAMC2;
+	uint32_t saveOVC_OGAMC3;
+	uint32_t saveOVC_OGAMC4;
+	uint32_t saveOVC_OGAMC5;
+
+	/*
+	 * extra MDFLD Register state
+	 */
+	uint32_t saveHDMIPHYMISCCTL;
+	uint32_t saveHDMIB_CONTROL;
+	uint32_t saveDSPCCNTR;
+	uint32_t savePIPECCONF;
+	uint32_t savePIPECSRC;
+	uint32_t saveHTOTAL_C;
+	uint32_t saveHBLANK_C;
+	uint32_t saveHSYNC_C;
+	uint32_t saveVTOTAL_C;
+	uint32_t saveVBLANK_C;
+	uint32_t saveVSYNC_C;
+	uint32_t saveDSPCSTRIDE;
+	uint32_t saveDSPCSIZE;
+	uint32_t saveDSPCPOS;
+	uint32_t saveDSPCSURF;
+	uint32_t saveDSPCLINOFF;
+	uint32_t saveDSPCTILEOFF;
+	uint32_t saveDSPCCURSOR_CTRL;
+	uint32_t saveDSPCCURSOR_BASE;
+	uint32_t saveDSPCCURSOR_POS;
+	uint32_t save_palette_c[256];
+	uint32_t saveOV_OVADD_C;
+	uint32_t saveOV_OGAMC0_C;
+	uint32_t saveOV_OGAMC1_C;
+	uint32_t saveOV_OGAMC2_C;
+	uint32_t saveOV_OGAMC3_C;
+	uint32_t saveOV_OGAMC4_C;
+	uint32_t saveOV_OGAMC5_C;
+
+	/* DSI reg save */
+	uint32_t saveDEVICE_READY_REG;
+	uint32_t saveINTR_EN_REG;
+	uint32_t saveDSI_FUNC_PRG_REG;
+	uint32_t saveHS_TX_TIMEOUT_REG;
+	uint32_t saveLP_RX_TIMEOUT_REG;
+	uint32_t saveTURN_AROUND_TIMEOUT_REG;
+	uint32_t saveDEVICE_RESET_REG;
+	uint32_t saveDPI_RESOLUTION_REG;
+	uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
+	uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
+	uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
+	uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
+	uint32_t saveVERT_SYNC_PAD_COUNT_REG;
+	uint32_t saveVERT_BACK_PORCH_COUNT_REG;
+	uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
+	uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
+	uint32_t saveINIT_COUNT_REG;
+	uint32_t saveMAX_RET_PAK_REG;
+	uint32_t saveVIDEO_FMT_REG;
+	uint32_t saveEOT_DISABLE_REG;
+	uint32_t saveLP_BYTECLK_REG;
+	uint32_t saveHS_LS_DBI_ENABLE_REG;
+	uint32_t saveTXCLKESC_REG;
+	uint32_t saveDPHY_PARAM_REG;
+	uint32_t saveMIPI_CONTROL_REG;
+	uint32_t saveMIPI;
+	uint32_t saveMIPI_C;
+	void (*init_drvIC)(struct drm_device *dev);
+	void (*dsi_prePowerState)(struct drm_device *dev);
+	void (*dsi_postPowerState)(struct drm_device *dev);
+
+	/* DPST Register Save */
+	uint32_t saveHISTOGRAM_INT_CONTROL_REG;
+	uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
+	uint32_t savePWM_CONTROL_LOGIC;
+
+	/* MSI reg save */
+
+	uint32_t msi_addr;
+	uint32_t msi_data;
+
+	/*
+	 *Scheduling.
+	 */
+
+	struct mutex reset_mutex;
+	struct mutex cmdbuf_mutex;
+	/*uint32_t ta_mem_pages;
+	struct psb_ta_mem *ta_mem;
+	int force_ta_mem_load;*/
+	atomic_t val_seq;
+
+	/*
+	 *TODO: change this to be per drm-context.
+	 */
+
+	struct psb_context context;
+
+	/*
+	 * LID-Switch
+	 */
+	spinlock_t lid_lock;
+	struct timer_list lid_timer;
+	struct psb_intel_opregion opregion;
+	u32 *lid_state;
+	u32 lid_last_state;
+
+	/*
+	 *Watchdog
+	 */
+
+	int timer_available;
+
+	uint32_t apm_reg;
+	uint16_t apm_base;
+
+	/*
+	 * Used for modifying backlight from
+	 * xrandr -- consider removing and using HAL instead
+	 */
+	struct drm_property *backlight_property;
+	uint32_t blc_adj1;
+	uint32_t blc_adj2;
+
+	void * fbdev;
+};
+
+
+struct psb_file_data {	/* TODO: Audit this, remove the indirection and set
+			   it up properly in open/postclose  ACFIXME */
+	void *priv;
+};
+
+struct psb_fpriv {
+	struct ttm_object_file *tfile;
+};
+
+struct psb_mmu_driver;
+
+extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
+extern int drm_pick_crtcs(struct drm_device *dev);
+
+static inline struct psb_fpriv *psb_fpriv(struct drm_file *file_priv)
+{
+	struct psb_file_data *pvr_file_priv
+			= (struct psb_file_data *)file_priv->driver_priv;
+	return (struct psb_fpriv *) pvr_file_priv->priv;
+}
+
+static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
+{
+	return (struct drm_psb_private *) dev->dev_private;
+}
+
+/*
+ *TTM glue. psb_ttm_glue.c
+ */
+
+extern int psb_open(struct inode *inode, struct file *filp);
+extern int psb_release(struct inode *inode, struct file *filp);
+extern int psb_mmap(struct file *filp, struct vm_area_struct *vma);
+
+extern int psb_fence_signaled_ioctl(struct drm_device *dev, void *data,
+				    struct drm_file *file_priv);
+extern int psb_verify_access(struct ttm_buffer_object *bo,
+			     struct file *filp);
+extern ssize_t psb_ttm_read(struct file *filp, char __user *buf,
+			    size_t count, loff_t *f_pos);
+extern ssize_t psb_ttm_write(struct file *filp, const char __user *buf,
+			    size_t count, loff_t *f_pos);
+extern int psb_fence_finish_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int psb_fence_unref_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv);
+extern int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data,
+				 struct drm_file *file_priv);
+extern int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+extern int psb_pl_unref_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+extern int psb_pl_reference_ioctl(struct drm_device *dev, void *data,
+				  struct drm_file *file_priv);
+extern int psb_pl_create_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+extern int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+extern int psb_extension_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+extern int psb_ttm_global_init(struct drm_psb_private *dev_priv);
+extern void psb_ttm_global_release(struct drm_psb_private *dev_priv);
+extern int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+/*
+ *MMU stuff.
+ */
+
+extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+					int trap_pagefaults,
+					int invalid_type,
+					struct drm_psb_private *dev_priv);
+extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
+extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
+						 *driver);
+extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
+			       uint32_t gtt_start, uint32_t gtt_pages);
+extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+					   int trap_pagefaults,
+					   int invalid_type);
+extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
+extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
+extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+					unsigned long address,
+					uint32_t num_pages);
+extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
+				       uint32_t start_pfn,
+				       unsigned long address,
+				       uint32_t num_pages, int type);
+extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+				  unsigned long *pfn);
+
+/*
+ *Enable / disable MMU for different requestors.
+ */
+
+
+extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
+extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+				unsigned long address, uint32_t num_pages,
+				uint32_t desired_tile_stride,
+				uint32_t hw_tile_stride, int type);
+extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
+				 unsigned long address, uint32_t num_pages,
+				 uint32_t desired_tile_stride,
+				 uint32_t hw_tile_stride);
+/*
+ *psb_sgx.c
+ */
+
+
+
+extern int psb_cmdbuf_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file_priv);
+extern int psb_reg_submit(struct drm_psb_private *dev_priv,
+			  uint32_t *regs, unsigned int cmds);
+
+
+extern void psb_fence_or_sync(struct drm_file *file_priv,
+			      uint32_t engine,
+			      uint32_t fence_types,
+			      uint32_t fence_flags,
+			      struct list_head *list,
+			      struct psb_ttm_fence_rep *fence_arg,
+			      struct ttm_fence_object **fence_p);
+extern int psb_validate_kernel_buffer(struct psb_context *context,
+				      struct ttm_buffer_object *bo,
+				      uint32_t fence_class,
+				      uint64_t set_flags,
+				      uint64_t clr_flags);
+
+/*
+ *psb_irq.c
+ */
+
+extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+extern int psb_irq_enable_dpst(struct drm_device *dev);
+extern int psb_irq_disable_dpst(struct drm_device *dev);
+extern void psb_irq_preinstall(struct drm_device *dev);
+extern int psb_irq_postinstall(struct drm_device *dev);
+extern void psb_irq_uninstall(struct drm_device *dev);
+extern void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands);
+extern int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands);
+extern void psb_irq_turn_on_dpst(struct drm_device *dev);
+extern void psb_irq_turn_off_dpst(struct drm_device *dev);
+
+extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
+extern int psb_vblank_wait2(struct drm_device *dev,unsigned int *sequence);
+extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
+extern int psb_enable_vblank(struct drm_device *dev, int crtc);
+extern void psb_disable_vblank(struct drm_device *dev, int crtc);
+void
+psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+
+void
+psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
+
+extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
+
+/*
+ *psb_fence.c
+ */
+
+extern void psb_fence_handler(struct drm_device *dev, uint32_t class);
+
+extern int psb_fence_emit_sequence(struct ttm_fence_device *fdev,
+				   uint32_t fence_class,
+				   uint32_t flags, uint32_t *sequence,
+				   unsigned long *timeout_jiffies);
+extern void psb_fence_error(struct drm_device *dev,
+			    uint32_t class,
+			    uint32_t sequence, uint32_t type, int error);
+extern int psb_ttm_fence_device_init(struct ttm_fence_device *fdev);
+
+/* MSVDX/Topaz stuff */
+extern int psb_remove_videoctx(struct drm_psb_private *dev_priv, struct file *filp);
+
+extern int lnc_video_frameskip(struct drm_device *dev,
+			       uint64_t user_pointer);
+extern int lnc_video_getparam(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+
+/*
+ * psb_opregion.c
+ */
+extern int psb_intel_opregion_init(struct drm_device *dev);
+
+/*
+ *psb_fb.c
+ */
+extern int psbfb_probed(struct drm_device *dev);
+extern int psbfb_remove(struct drm_device *dev,
+			struct drm_framebuffer *fb);
+extern int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv);
+extern int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
+			      struct drm_file *file_priv);
+extern void *psbfb_vdc_reg(struct drm_device* dev);
+
+/*
+ * psb_2d.c
+ */
+extern void psbfb_fillrect(struct fb_info *info,
+					const struct fb_fillrect *rect);
+extern void psbfb_copyarea(struct fb_info *info,
+					const struct fb_copyarea *region);
+extern void psbfb_imageblit(struct fb_info *info,
+					const struct fb_image *image);
+extern int psbfb_sync(struct fb_info *info);
+
+extern void psb_spank(struct drm_psb_private *dev_priv);
+
+/*
+ *psb_reset.c
+ */
+
+extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
+extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
+extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
+
+/* modesetting */
+extern void psb_modeset_init(struct drm_device *dev);
+extern void psb_modeset_cleanup(struct drm_device *dev);
+extern int psb_fbdev_init(struct drm_device * dev);
+
+/* psb_bl.c */
+int psb_backlight_init(struct drm_device *dev);
+void psb_backlight_exit(void);
+int psb_set_brightness(struct backlight_device *bd);
+int psb_get_brightness(struct backlight_device *bd);
+struct backlight_device * psb_get_backlight_device(void);
+
+/*
+ *Debug print bits setting
+ */
+#define PSB_D_GENERAL (1 << 0)
+#define PSB_D_INIT    (1 << 1)
+#define PSB_D_IRQ     (1 << 2)
+#define PSB_D_ENTRY   (1 << 3)
+/* debug the get H/V BP/FP count */
+#define PSB_D_HV      (1 << 4)
+#define PSB_D_DBI_BF  (1 << 5)
+#define PSB_D_PM      (1 << 6)
+#define PSB_D_RENDER  (1 << 7)
+#define PSB_D_REG     (1 << 8)
+#define PSB_D_MSVDX   (1 << 9)
+#define PSB_D_TOPAZ   (1 << 10)
+
+#ifndef DRM_DEBUG_CODE
+/* To enable debug printout, set drm_psb_debug in psb_drv.c
+ * to any combination of above print flags.
+ */
+/* #define DRM_DEBUG_CODE 2 */
+#endif
+
+extern int drm_psb_debug;
+extern int drm_psb_no_fb;
+extern int drm_psb_disable_vsync;
+extern int drm_idle_check_interval;
+
+#define PSB_DEBUG_GENERAL(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_GENERAL, _fmt, ##_arg)
+#define PSB_DEBUG_INIT(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_INIT, _fmt, ##_arg)
+#define PSB_DEBUG_IRQ(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_IRQ, _fmt, ##_arg)
+#define PSB_DEBUG_ENTRY(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_ENTRY, _fmt, ##_arg)
+#define PSB_DEBUG_HV(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_HV, _fmt, ##_arg)
+#define PSB_DEBUG_DBI_BF(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_DBI_BF, _fmt, ##_arg)
+#define PSB_DEBUG_PM(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_PM, _fmt, ##_arg)
+#define PSB_DEBUG_RENDER(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_RENDER, _fmt, ##_arg)
+#define PSB_DEBUG_REG(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_REG, _fmt, ##_arg)
+#define PSB_DEBUG_MSVDX(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_MSVDX, _fmt, ##_arg)
+#define PSB_DEBUG_TOPAZ(_fmt, _arg...) \
+	PSB_DEBUG(PSB_D_TOPAZ, _fmt, ##_arg)
+
+#if DRM_DEBUG_CODE
+#define PSB_DEBUG(_flag, _fmt, _arg...)					\
+	do {								\
+		if (unlikely((_flag) & drm_psb_debug))			\
+			printk(KERN_DEBUG				\
+			       "[psb:0x%02x:%s] " _fmt , _flag,		\
+			       __func__ , ##_arg);			\
+	} while (0)
+#else
+#define PSB_DEBUG(_fmt, _arg...)     do { } while (0)
+#endif
+
+/*
+ *Utilities
+ */
+#define DRM_DRIVER_PRIVATE_T struct drm_psb_private
+
+static inline u32 MRST_MSG_READ32(uint port, uint offset)
+{
+	int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
+	uint32_t ret_val = 0;
+	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+	pci_write_config_dword (pci_root, 0xD0, mcr);
+	pci_read_config_dword (pci_root, 0xD4, &ret_val);
+	pci_dev_put(pci_root);
+	return ret_val;
+}
+static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+	int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
+	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+	pci_write_config_dword (pci_root, 0xD4, value);
+	pci_write_config_dword (pci_root, 0xD0, mcr);
+	pci_dev_put(pci_root);
+}
+static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
+{
+	int mcr = (0x10<<24) | (port << 16) | (offset << 8);
+	uint32_t ret_val = 0;
+	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+	pci_write_config_dword (pci_root, 0xD0, mcr);
+	pci_read_config_dword (pci_root, 0xD4, &ret_val);
+	pci_dev_put(pci_root);
+	return ret_val;
+}
+static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
+{
+	int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
+	struct pci_dev *pci_root = pci_get_bus_and_slot (0, 0);
+	pci_write_config_dword (pci_root, 0xD4, value);
+	pci_write_config_dword (pci_root, 0xD0, mcr);
+	pci_dev_put(pci_root);
+}
+
+static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int reg_val = ioread32(dev_priv->vdc_reg + (reg));
+	PSB_DEBUG_REG("reg = 0x%x. reg_val = 0x%x. \n", reg, reg_val);
+	return reg_val;
+}
+
+#define REG_READ(reg)	       REGISTER_READ(dev, (reg))
+static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
+				      uint32_t val)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	if ((reg < 0x70084 || reg >0x70088) && (reg < 0xa000 || reg >0xa3ff))
+		PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+	iowrite32((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE(reg, val)	REGISTER_WRITE(dev, (reg), (val))
+
+static inline void REGISTER_WRITE16(struct drm_device *dev,
+					uint32_t reg, uint32_t val)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+	iowrite16((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE16(reg, val)	  REGISTER_WRITE16(dev, (reg), (val))
+
+static inline void REGISTER_WRITE8(struct drm_device *dev,
+				       uint32_t reg, uint32_t val)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	PSB_DEBUG_REG("reg = 0x%x, val = 0x%x. \n", reg, val);
+
+	iowrite8((val), dev_priv->vdc_reg + (reg));
+}
+
+#define REG_WRITE8(reg, val)	 REGISTER_WRITE8(dev, (reg), (val))
+
+#define PSB_ALIGN_TO(_val, _align) \
+  (((_val) + ((_align) - 1)) & ~((_align) - 1))
+#define PSB_WVDC32(_val, _offs) \
+  iowrite32(_val, dev_priv->vdc_reg + (_offs))
+#define PSB_RVDC32(_offs) \
+  ioread32(dev_priv->vdc_reg + (_offs))
+
+/* #define TRAP_SGX_PM_FAULT 1 */
+#ifdef TRAP_SGX_PM_FAULT
+#define PSB_RSGX32(_offs)					\
+({								\
+    if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) {		\
+	printk(KERN_ERR "access sgx when it's off!! (READ) %s, %d\n", \
+	       __FILE__, __LINE__);				\
+	mdelay(1000);						\
+    }								\
+    ioread32(dev_priv->sgx_reg + (_offs));			\
+})
+#else
+#define PSB_RSGX32(_offs)					\
+  ioread32(dev_priv->sgx_reg + (_offs))
+#endif
+#define PSB_WSGX32(_val, _offs) \
+  iowrite32(_val, dev_priv->sgx_reg + (_offs))
+
+#define MSVDX_REG_DUMP 0
+#if MSVDX_REG_DUMP
+
+#define PSB_WMSVDX32(_val, _offs) \
+  printk("MSVDX: write %08x to reg 0x%08x\n", (unsigned int)(_val), (unsigned int)(_offs));\
+  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs) \
+  ioread32(dev_priv->msvdx_reg + (_offs))
+
+#else
+
+#define PSB_WMSVDX32(_val, _offs) \
+  iowrite32(_val, dev_priv->msvdx_reg + (_offs))
+#define PSB_RMSVDX32(_offs) \
+  ioread32(dev_priv->msvdx_reg + (_offs))
+
+#endif
+
+#define PSB_ALPL(_val, _base)			\
+  (((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT))
+#define PSB_ALPLM(_val, _base)			\
+  ((((_val) >> (_base ## _ALIGNSHIFT)) << (_base ## _SHIFT)) & (_base ## _MASK))
+
+#endif
diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
new file mode 100644
index 0000000..f67f53b
--- /dev/null
+++ b/drivers/staging/gma500/psb_fb.c
@@ -0,0 +1,842 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include <drm/drm_crtc.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_drv.h"
+#include "psb_ttm_userobj_api.h"
+#include "psb_fb.h"
+#include "psb_sgx.h"
+#include "psb_pvr_glue.h"
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+					      struct drm_file *file_priv,
+					      unsigned int *handle);
+
+static const struct drm_framebuffer_funcs psb_fb_funcs = {
+	.destroy = psb_user_framebuffer_destroy,
+	.create_handle = psb_user_framebuffer_create_handle,
+};
+
+#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
+
+void *psbfb_vdc_reg(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv;
+	dev_priv = (struct drm_psb_private *) dev->dev_private;
+	return dev_priv->vdc_reg;
+}
+/*EXPORT_SYMBOL(psbfb_vdc_reg); */
+
+static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
+	uint32_t v;
+
+	if (!fb)
+		return -ENOMEM;
+
+	if (regno > 255)
+		return 1;
+
+	red = CMAP_TOHW(red, info->var.red.length);
+	blue = CMAP_TOHW(blue, info->var.blue.length);
+	green = CMAP_TOHW(green, info->var.green.length);
+	transp = CMAP_TOHW(transp, info->var.transp.length);
+
+	v = (red << info->var.red.offset) |
+	    (green << info->var.green.offset) |
+	    (blue << info->var.blue.offset) |
+	    (transp << info->var.transp.offset);
+
+	if (regno < 16) {
+		switch (fb->bits_per_pixel) {
+		case 16:
+			((uint32_t *) info->pseudo_palette)[regno] = v;
+			break;
+		case 24:
+		case 32:
+			((uint32_t *) info->pseudo_palette)[regno] = v;
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int psbfb_kms_off(struct drm_device *dev, int suspend)
+{
+	struct drm_framebuffer *fb = 0;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+	DRM_DEBUG("psbfb_kms_off_ioctl\n");
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		struct fb_info *info = psbfb->fbdev;
+
+		if (suspend) {
+			fb_set_suspend(info, 1);
+			drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
+		}
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+	return 0;
+}
+
+int psbfb_kms_off_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	int ret;
+
+	if (drm_psb_no_fb)
+		return 0;
+	console_lock();
+	ret = psbfb_kms_off(dev, 0);
+	console_unlock();
+
+	return ret;
+}
+
+static int psbfb_kms_on(struct drm_device *dev, int resume)
+{
+	struct drm_framebuffer *fb = 0;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	DRM_DEBUG("psbfb_kms_on_ioctl\n");
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+		struct fb_info *info = psbfb->fbdev;
+
+		if (resume) {
+			fb_set_suspend(info, 0);
+			drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
+		}
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+
+	return 0;
+}
+
+int psbfb_kms_on_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	int ret;
+
+	if (drm_psb_no_fb)
+		return 0;
+	console_lock();
+	ret = psbfb_kms_on(dev, 0);
+	console_unlock();
+	drm_helper_disable_unused_functions(dev);
+	return ret;
+}
+
+void psbfb_suspend(struct drm_device *dev)
+{
+	console_lock();
+	psbfb_kms_off(dev, 1);
+	console_unlock();
+}
+
+void psbfb_resume(struct drm_device *dev)
+{
+	console_lock();
+	psbfb_kms_on(dev, 1);
+	console_unlock();
+	drm_helper_disable_unused_functions(dev);
+}
+
+static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int page_num = 0;
+	int i;
+	unsigned long address = 0;
+	int ret;
+	unsigned long pfn;
+	struct psb_framebuffer *psbfb = vma->vm_private_data;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = dev_priv->pg;
+	unsigned long phys_addr = (unsigned long)pg->stolen_base;;
+
+	page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+
+	address = (unsigned long)vmf->virtual_address;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	for (i = 0; i < page_num; i++) {
+		pfn = (phys_addr >> PAGE_SHIFT); /* phys_to_pfn(phys_addr); */
+
+		ret = vm_insert_mixed(vma, address, pfn);
+		if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
+			break;
+		else if (unlikely(ret != 0)) {
+			ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
+			return ret;
+		}
+
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+	}
+
+	return VM_FAULT_NOPAGE;
+}
+
+static void psbfb_vm_open(struct vm_area_struct *vma)
+{
+	DRM_DEBUG("vm_open\n");
+}
+
+static void psbfb_vm_close(struct vm_area_struct *vma)
+{
+	DRM_DEBUG("vm_close\n");
+}
+
+static struct vm_operations_struct psbfb_vm_ops = {
+	.fault	= psbfb_vm_fault,
+	.open	= psbfb_vm_open,
+	.close	= psbfb_vm_close
+};
+
+static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	struct psb_fbdev *fbdev = info->par;
+	struct psb_framebuffer *psbfb = fbdev->pfb;
+	char *fb_screen_base = NULL;
+	struct drm_device *dev = psbfb->base.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = dev_priv->pg;
+
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+
+	if (!psbfb->addr_space)
+		psbfb->addr_space = vma->vm_file->f_mapping;
+
+	fb_screen_base = (char *)info->screen_base;
+
+	DRM_DEBUG("vm_pgoff 0x%lx, screen base %p vram_addr %p\n",
+				vma->vm_pgoff, fb_screen_base, pg->vram_addr);
+
+	/*if using stolen memory, */
+	if (fb_screen_base == pg->vram_addr) {
+		vma->vm_ops = &psbfb_vm_ops;
+		vma->vm_private_data = (void *)psbfb;
+		vma->vm_flags |= VM_RESERVED | VM_IO |
+						VM_MIXEDMAP | VM_DONTEXPAND;
+	} else {
+	/*using IMG meminfo, can I use pvrmmap to map it?*/
+
+	}
+
+	return 0;
+}
+
+
+static struct fb_ops psbfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = drm_fb_helper_check_var,
+	.fb_set_par = drm_fb_helper_set_par,
+	.fb_blank = drm_fb_helper_blank,
+	.fb_setcolreg = psbfb_setcolreg,
+	.fb_fillrect = psbfb_fillrect,
+	.fb_copyarea = psbfb_copyarea,
+	.fb_imageblit = psbfb_imageblit,
+	.fb_mmap = psbfb_mmap,
+	.fb_sync = psbfb_sync,
+};
+
+static struct drm_framebuffer *psb_framebuffer_create
+			(struct drm_device *dev, struct drm_mode_fb_cmd *r,
+			 void *mm_private)
+{
+	struct psb_framebuffer *fb;
+	int ret;
+
+	fb = kzalloc(sizeof(*fb), GFP_KERNEL);
+	if (!fb)
+		return NULL;
+
+	ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
+
+	if (ret)
+		goto err;
+
+	drm_helper_mode_fill_fb_struct(&fb->base, r);
+
+	fb->bo = mm_private;
+
+	return &fb->base;
+
+err:
+	kfree(fb);
+	return NULL;
+}
+
+static struct drm_framebuffer *psb_user_framebuffer_create
+			(struct drm_device *dev, struct drm_file *filp,
+			 struct drm_mode_fb_cmd *r)
+{
+	struct ttm_buffer_object *bo = NULL;
+	uint64_t size;
+
+	bo = ttm_buffer_object_lookup(psb_fpriv(filp)->tfile, r->handle);
+	if (!bo)
+		return NULL;
+
+	/* JB: TODO not drop, make smarter */
+	size = ((uint64_t) bo->num_pages) << PAGE_SHIFT;
+	if (size < r->width * r->height * 4)
+		return NULL;
+
+	/* JB: TODO not drop, refcount buffer */
+	return psb_framebuffer_create(dev, r, bo);
+
+#if 0
+	struct psb_framebuffer *psbfb;
+	struct drm_framebuffer *fb;
+	struct fb_info *info;
+	void *psKernelMemInfo = NULL;
+	void * hKernelMemInfo = (void *)r->handle;
+	struct drm_psb_private *dev_priv
+		= (struct drm_psb_private *)dev->dev_private;
+	struct psb_fbdev *fbdev = dev_priv->fbdev;
+	struct psb_gtt *pg = dev_priv->pg;
+	int ret;
+	uint32_t offset;
+	uint64_t size;
+
+	ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+	if (ret) {
+		DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
+						(u32)hKernelMemInfo);
+		return NULL;
+	}
+
+	DRM_DEBUG("Got Kernel MemInfo for handle %lx\n",
+		  (u32)hKernelMemInfo);
+
+	/* JB: TODO not drop, make smarter */
+	size = psKernelMemInfo->ui32AllocSize;
+	if (size < r->height * r->pitch)
+		return NULL;
+
+	/* JB: TODO not drop, refcount buffer */
+	/* return psb_framebuffer_create(dev, r, bo); */
+
+	fb = psb_framebuffer_create(dev, r, (void *)psKernelMemInfo);
+	if (!fb) {
+		DRM_ERROR("failed to allocate fb.\n");
+		return NULL;
+	}
+
+	psbfb = to_psb_fb(fb);
+	psbfb->size = size;
+	psbfb->hKernelMemInfo = hKernelMemInfo;
+
+	DRM_DEBUG("Mapping to gtt..., KernelMemInfo %p\n", psKernelMemInfo);
+
+	/*if not VRAM, map it into tt aperture*/
+	if (psKernelMemInfo->pvLinAddrKM != pg->vram_addr) {
+		ret = psb_gtt_map_meminfo(dev, hKernelMemInfo, &offset);
+		if (ret) {
+			DRM_ERROR("map meminfo for 0x%x failed\n",
+				  (u32)hKernelMemInfo);
+			return NULL;
+		}
+		psbfb->offset = (offset << PAGE_SHIFT);
+	} else {
+		psbfb->offset = 0;
+	}
+	info = framebuffer_alloc(0, &dev->pdev->dev);
+	if (!info)
+		return NULL;
+
+	strcpy(info->fix.id, "psbfb");
+
+	info->flags = FBINFO_DEFAULT;
+	info->fix.accel = FB_ACCEL_I830;	/*FIXMEAC*/
+	info->fbops = &psbfb_ops;
+
+	info->fix.smem_start = dev->mode_config.fb_base;
+	info->fix.smem_len = size;
+
+	info->screen_base = psKernelMemInfo->pvLinAddrKM;
+	info->screen_size = size;
+
+	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
+							fb->width, fb->height);
+
+	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+	info->pixmap.size = 64 * 1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+
+	psbfb->fbdev = info;
+	fbdev->pfb = psbfb;
+
+	fbdev->psb_fb_helper.fb = fb;
+	fbdev->psb_fb_helper.fbdev = info;
+	MRSTLFBHandleChangeFB(dev, psbfb);
+
+	return fb;
+#endif
+}
+
+static int psbfb_create(struct psb_fbdev *fbdev,
+				struct drm_fb_helper_surface_size *sizes)
+{
+	struct drm_device *dev = fbdev->psb_fb_helper.dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = dev_priv->pg;
+	struct fb_info *info;
+	struct drm_framebuffer *fb;
+	struct psb_framebuffer *psbfb;
+	struct drm_mode_fb_cmd mode_cmd;
+	struct device *device = &dev->pdev->dev;
+
+	struct ttm_buffer_object *fbo = NULL;
+	int size, aligned_size;
+	int ret;
+
+	mode_cmd.width = sizes->surface_width;
+	mode_cmd.height = sizes->surface_height;
+
+	mode_cmd.bpp = 32;
+	/* HW requires pitch to be 64 byte aligned */
+	mode_cmd.pitch =  ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64);
+	mode_cmd.depth = 24;
+
+	size = mode_cmd.pitch * mode_cmd.height;
+	aligned_size = ALIGN(size, PAGE_SIZE);
+
+	mutex_lock(&dev->struct_mutex);
+	fb = psb_framebuffer_create(dev, &mode_cmd, fbo);
+	if (!fb) {
+		DRM_ERROR("failed to allocate fb.\n");
+		ret = -ENOMEM;
+		goto out_err1;
+	}
+	psbfb = to_psb_fb(fb);
+	psbfb->size = size;
+
+	info = framebuffer_alloc(sizeof(struct psb_fbdev), device);
+	if (!info) {
+		ret = -ENOMEM;
+		goto out_err0;
+	}
+
+	info->par = fbdev;
+
+	psbfb->fbdev = info;
+
+	fbdev->psb_fb_helper.fb = fb;
+	fbdev->psb_fb_helper.fbdev = info;
+	fbdev->pfb = psbfb;
+
+	strcpy(info->fix.id, "psbfb");
+
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &psbfb_ops;
+	info->fix.smem_start = dev->mode_config.fb_base;
+	info->fix.smem_len = size;
+	info->screen_base = (char *)pg->vram_addr;
+	info->screen_size = size;
+	memset(info->screen_base, 0, size);
+
+	drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+	drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
+				sizes->fb_width, sizes->fb_height);
+
+	info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
+	info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
+
+	info->pixmap.size = 64 * 1024;
+	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 1;
+
+	DRM_DEBUG("fb depth is %d\n", fb->depth);
+	DRM_DEBUG("   pitch is %d\n", fb->pitch);
+
+	printk(KERN_INFO"allocated %dx%d fb\n",
+				psbfb->base.width, psbfb->base.height);
+
+	mutex_unlock(&dev->struct_mutex);
+
+	return 0;
+out_err0:
+	fb->funcs->destroy(fb);
+out_err1:
+	mutex_unlock(&dev->struct_mutex);
+	return ret;
+}
+
+static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+							u16 blue, int regno)
+{
+	DRM_DEBUG("%s\n", __func__);
+}
+
+static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
+					u16 *green, u16 *blue, int regno)
+{
+	DRM_DEBUG("%s\n", __func__);
+}
+
+static int psbfb_probe(struct drm_fb_helper *helper,
+				struct drm_fb_helper_surface_size *sizes)
+{
+	struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
+	int new_fb = 0;
+	int ret;
+
+	DRM_DEBUG("%s\n", __func__);
+
+	if (!helper->fb) {
+		ret = psbfb_create(psb_fbdev, sizes);
+		if (ret)
+			return ret;
+		new_fb = 1;
+	}
+	return new_fb;
+}
+
+struct drm_fb_helper_funcs psb_fb_helper_funcs = {
+	.gamma_set = psbfb_gamma_set,
+	.gamma_get = psbfb_gamma_get,
+	.fb_probe = psbfb_probe,
+};
+
+int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
+{
+	struct fb_info *info;
+	struct psb_framebuffer *psbfb = fbdev->pfb;
+
+	if (fbdev->psb_fb_helper.fbdev) {
+		info = fbdev->psb_fb_helper.fbdev;
+		unregister_framebuffer(info);
+		iounmap(info->screen_base);
+		framebuffer_release(info);
+	}
+
+	drm_fb_helper_fini(&fbdev->psb_fb_helper);
+
+	drm_framebuffer_cleanup(&psbfb->base);
+
+	return 0;
+}
+
+int psb_fbdev_init(struct drm_device *dev)
+{
+	struct psb_fbdev *fbdev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int num_crtc;
+
+	fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
+	if (!fbdev) {
+		DRM_ERROR("no memory\n");
+		return -ENOMEM;
+	}
+
+	dev_priv->fbdev = fbdev;
+	fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
+
+	num_crtc = 2;
+
+	drm_fb_helper_init(dev, &fbdev->psb_fb_helper, num_crtc,
+							INTELFB_CONN_LIMIT);
+
+	drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
+	drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
+	return 0;
+}
+
+void psb_fbdev_fini(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->fbdev)
+		return;
+
+	psb_fbdev_destroy(dev, dev_priv->fbdev);
+	kfree(dev_priv->fbdev);
+	dev_priv->fbdev = NULL;
+}
+
+
+static void psbfb_output_poll_changed(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
+	drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
+}
+
+int psbfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+	struct fb_info *info;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	if (drm_psb_no_fb)
+		return 0;
+
+	info = psbfb->fbdev;
+	psbfb->pvrBO = NULL;
+
+	if (info)
+		framebuffer_release(info);
+	return 0;
+}
+/*EXPORT_SYMBOL(psbfb_remove); */
+
+static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
+					      struct drm_file *file_priv,
+					      unsigned int *handle)
+{
+	/* JB: TODO currently we can't go from a bo to a handle with ttm */
+	(void) file_priv;
+	*handle = 0;
+	return 0;
+}
+
+static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = fb->dev;
+	struct psb_framebuffer *psbfb = to_psb_fb(fb);
+
+	/*ummap gtt pages*/
+	psb_gtt_unmap_meminfo(dev, psbfb->hKernelMemInfo);
+	if (psbfb->fbdev)
+		psbfb_remove(dev, fb);
+
+	/* JB: TODO not drop, refcount buffer */
+	drm_framebuffer_cleanup(fb);
+	kfree(fb);
+}
+
+static const struct drm_mode_config_funcs psb_mode_funcs = {
+	.fb_create = psb_user_framebuffer_create,
+	.output_poll_changed = psbfb_output_poll_changed,
+};
+
+static int psb_create_backlight_property(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv
+				= (struct drm_psb_private *) dev->dev_private;
+	struct drm_property *backlight;
+
+	if (dev_priv->backlight_property)
+		return 0;
+
+	backlight = drm_property_create(dev,
+					DRM_MODE_PROP_RANGE,
+					"backlight",
+					2);
+	backlight->values[0] = 0;
+	backlight->values[1] = 100;
+
+	dev_priv->backlight_property = backlight;
+
+	return 0;
+}
+
+static void psb_setup_outputs(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	struct drm_connector *connector;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	drm_mode_create_scaling_mode_property(dev);
+
+	psb_create_backlight_property(dev);
+
+	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
+	/* psb_intel_sdvo_init(dev, SDVOB); */
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+		struct drm_encoder *encoder = &psb_intel_output->enc;
+		int crtc_mask = 0, clone_mask = 0;
+
+		/* valid crtcs */
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_SDVO:
+			crtc_mask = ((1 << 0) | (1 << 1));
+			clone_mask = (1 << INTEL_OUTPUT_SDVO);
+			break;
+		case INTEL_OUTPUT_LVDS:
+			PSB_DEBUG_ENTRY("LVDS.\n");
+			crtc_mask = (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_LVDS);
+			break;
+		case INTEL_OUTPUT_MIPI:
+			PSB_DEBUG_ENTRY("MIPI.\n");
+			crtc_mask = (1 << 0);
+			clone_mask = (1 << INTEL_OUTPUT_MIPI);
+			break;
+		case INTEL_OUTPUT_MIPI2:
+			PSB_DEBUG_ENTRY("MIPI2.\n");
+			crtc_mask = (1 << 2);
+			clone_mask = (1 << INTEL_OUTPUT_MIPI2);
+			break;
+		case INTEL_OUTPUT_HDMI:
+			PSB_DEBUG_ENTRY("HDMI.\n");
+			crtc_mask = (1 << 1);
+			clone_mask = (1 << INTEL_OUTPUT_HDMI);
+			break;
+		}
+
+		encoder->possible_crtcs = crtc_mask;
+		encoder->possible_clones =
+		    psb_intel_connector_clones(dev, clone_mask);
+
+	}
+}
+
+static void *psb_bo_from_handle(struct drm_device *dev,
+				struct drm_file *file_priv,
+				unsigned int handle)
+{
+	void *psKernelMemInfo = NULL;
+	void * hKernelMemInfo = (void *)handle;
+	int ret;
+
+	ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+	if (ret) {
+		DRM_ERROR("Cannot get meminfo for handle 0x%x\n",
+			  (u32)hKernelMemInfo);
+		return NULL;
+	}
+
+	return (void *)psKernelMemInfo;
+}
+
+static size_t psb_bo_size(struct drm_device *dev, void *bof)
+{
+#if 0
+	void *psKernelMemInfo	= (void *)bof;
+	return (size_t)psKernelMemInfo->ui32AllocSize;
+#else
+	return 0;
+#endif
+}
+
+static size_t psb_bo_offset(struct drm_device *dev, void *bof)
+{
+	struct psb_framebuffer *psbfb
+		= (struct psb_framebuffer *)bof;
+
+	return (size_t)psbfb->offset;
+}
+
+static int psb_bo_pin_for_scanout(struct drm_device *dev, void *bo)
+{
+	 return 0;
+}
+
+static int psb_bo_unpin_for_scanout(struct drm_device *dev, void *bo)
+{
+	return 0;
+}
+
+void psb_modeset_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
+	int i;
+
+	PSB_DEBUG_ENTRY("\n");
+	/* Init mm functions */
+	mode_dev->bo_from_handle = psb_bo_from_handle;
+	mode_dev->bo_size = psb_bo_size;
+	mode_dev->bo_offset = psb_bo_offset;
+	mode_dev->bo_pin_for_scanout = psb_bo_pin_for_scanout;
+	mode_dev->bo_unpin_for_scanout = psb_bo_unpin_for_scanout;
+
+	drm_mode_config_init(dev);
+
+	dev->mode_config.min_width = 0;
+	dev->mode_config.min_height = 0;
+
+	dev->mode_config.funcs = (void *) &psb_mode_funcs;
+
+	/* set memory base */
+	/* MRST and PSB should use BAR 2*/
+	pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
+					&(dev->mode_config.fb_base));
+
+	/* num pipes is 2 for PSB but 1 for Mrst */
+	for (i = 0; i < dev_priv->num_pipe; i++)
+		psb_intel_crtc_init(dev, i, mode_dev);
+
+	dev->mode_config.max_width = 2048;
+	dev->mode_config.max_height = 2048;
+
+	psb_setup_outputs(dev);
+
+	/* setup fbs */
+	/* drm_initial_config(dev); */
+}
+
+void psb_modeset_cleanup(struct drm_device *dev)
+{
+	mutex_lock(&dev->struct_mutex);
+
+	drm_kms_helper_poll_fini(dev);
+	psb_fbdev_fini(dev);
+
+	drm_mode_config_cleanup(dev);
+
+	mutex_unlock(&dev->struct_mutex);
+}
diff --git a/drivers/staging/gma500/psb_fb.h b/drivers/staging/gma500/psb_fb.h
new file mode 100644
index 0000000..b4fab92
--- /dev/null
+++ b/drivers/staging/gma500/psb_fb.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *      Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _PSB_FB_H_
+#define _PSB_FB_H_
+
+#include <linux/version.h>
+#include <drm/drmP.h>
+#include <drm/drm_fb_helper.h>
+
+#include "psb_drv.h"
+
+/*IMG Headers*/
+/*#include "servicesint.h"*/
+
+struct psb_framebuffer {
+	struct drm_framebuffer base;
+	struct address_space *addr_space;
+	struct ttm_buffer_object *bo;
+	struct fb_info * fbdev;
+	/* struct ttm_bo_kmap_obj kmap; */
+	void *pvrBO;	/* FIXME: sort this out */
+	void * hKernelMemInfo;
+	uint32_t size;
+	uint32_t offset;
+};
+
+struct psb_fbdev {
+	struct drm_fb_helper psb_fb_helper;
+	struct psb_framebuffer * pfb;
+};
+
+
+#define to_psb_fb(x) container_of(x, struct psb_framebuffer, base)
+
+
+extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask);
+
+
+#endif
+
diff --git a/drivers/staging/gma500/psb_fence.c b/drivers/staging/gma500/psb_fence.c
new file mode 100644
index 0000000..a70aa64
--- /dev/null
+++ b/drivers/staging/gma500/psb_fence.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+
+
+static void psb_fence_poll(struct ttm_fence_device *fdev,
+			   uint32_t fence_class, uint32_t waiting_types)
+{
+	struct drm_psb_private *dev_priv =
+	    container_of(fdev, struct drm_psb_private, fdev);
+
+
+	if (unlikely(!dev_priv))
+		return;
+
+	if (waiting_types == 0)
+		return;
+
+	/* DRM_ERROR("Polling fence sequence, got 0x%08x\n", sequence); */
+	ttm_fence_handler(fdev, fence_class, 0 /* Sequence */,
+			_PSB_FENCE_TYPE_EXE, 0);
+}
+
+void psb_fence_error(struct drm_device *dev,
+		     uint32_t fence_class,
+		     uint32_t sequence, uint32_t type, int error)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct ttm_fence_device *fdev = &dev_priv->fdev;
+	unsigned long irq_flags;
+	struct ttm_fence_class_manager *fc =
+	    &fdev->fence_class[fence_class];
+
+	BUG_ON(fence_class >= PSB_NUM_ENGINES);
+	write_lock_irqsave(&fc->lock, irq_flags);
+	ttm_fence_handler(fdev, fence_class, sequence, type, error);
+	write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+int psb_fence_emit_sequence(struct ttm_fence_device *fdev,
+			    uint32_t fence_class,
+			    uint32_t flags, uint32_t *sequence,
+			    unsigned long *timeout_jiffies)
+{
+	struct drm_psb_private *dev_priv =
+	    container_of(fdev, struct drm_psb_private, fdev);
+
+	if (!dev_priv)
+		return -EINVAL;
+
+	if (fence_class >= PSB_NUM_ENGINES)
+		return -EINVAL;
+
+	DRM_ERROR("Unexpected fence class\n");
+	return -EINVAL;
+}
+
+static void psb_fence_lockup(struct ttm_fence_object *fence,
+			     uint32_t fence_types)
+{
+	DRM_ERROR("Unsupported fence class\n");
+}
+
+void psb_fence_handler(struct drm_device *dev, uint32_t fence_class)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct ttm_fence_device *fdev = &dev_priv->fdev;
+	struct ttm_fence_class_manager *fc =
+	    &fdev->fence_class[fence_class];
+	unsigned long irq_flags;
+
+	write_lock_irqsave(&fc->lock, irq_flags);
+	psb_fence_poll(fdev, fence_class, fc->waiting_types);
+	write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+
+static struct ttm_fence_driver psb_ttm_fence_driver = {
+	.has_irq = NULL,
+	.emit = psb_fence_emit_sequence,
+	.flush = NULL,
+	.poll = psb_fence_poll,
+	.needed_flush = NULL,
+	.wait = NULL,
+	.signaled = NULL,
+	.lockup = psb_fence_lockup,
+};
+
+int psb_ttm_fence_device_init(struct ttm_fence_device *fdev)
+{
+	struct drm_psb_private *dev_priv =
+		container_of(fdev, struct drm_psb_private, fdev);
+	struct ttm_fence_class_init fci = {.wrap_diff = (1 << 30),
+		.flush_diff = (1 << 29),
+		.sequence_mask = 0xFFFFFFFF
+	};
+
+	return ttm_fence_device_init(PSB_NUM_ENGINES,
+				     dev_priv->mem_global_ref.object,
+				     fdev, &fci, 1,
+				     &psb_ttm_fence_driver);
+}
diff --git a/drivers/staging/gma500/psb_gtt.c b/drivers/staging/gma500/psb_gtt.c
new file mode 100644
index 0000000..53c1e1e
--- /dev/null
+++ b/drivers/staging/gma500/psb_gtt.c
@@ -0,0 +1,1034 @@
+/*
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_pvr_glue.h"
+
+static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
+{
+	uint32_t mask = PSB_PTE_VALID;
+
+	if (type & PSB_MMU_CACHED_MEMORY)
+		mask |= PSB_PTE_CACHED;
+	if (type & PSB_MMU_RO_MEMORY)
+		mask |= PSB_PTE_RO;
+	if (type & PSB_MMU_WO_MEMORY)
+		mask |= PSB_PTE_WO;
+
+	return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_gtt *psb_gtt_alloc(struct drm_device *dev)
+{
+	struct psb_gtt *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+
+	if (!tmp)
+		return NULL;
+
+	init_rwsem(&tmp->sem);
+	tmp->dev = dev;
+
+	return tmp;
+}
+
+void psb_gtt_takedown(struct psb_gtt *pg, int free)
+{
+	struct drm_psb_private *dev_priv = pg->dev->dev_private;
+
+	if (!pg)
+		return;
+
+	if (pg->gtt_map) {
+		iounmap(pg->gtt_map);
+		pg->gtt_map = NULL;
+	}
+	if (pg->initialized) {
+		pci_write_config_word(pg->dev->pdev, PSB_GMCH_CTRL,
+				      pg->gmch_ctrl);
+		PSB_WVDC32(pg->pge_ctl, PSB_PGETBL_CTL);
+		(void) PSB_RVDC32(PSB_PGETBL_CTL);
+	}
+	if (free)
+		kfree(pg);
+}
+
+int psb_gtt_init(struct psb_gtt *pg, int resume)
+{
+	struct drm_device *dev = pg->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	unsigned gtt_pages;
+	unsigned long stolen_size, vram_stolen_size, ci_stolen_size;
+	unsigned long rar_stolen_size;
+	unsigned i, num_pages;
+	unsigned pfn_base;
+	uint32_t ci_pages, vram_pages;
+	uint32_t tt_pages;
+	uint32_t *ttm_gtt_map;
+	uint32_t dvmt_mode = 0;
+
+	int ret = 0;
+	uint32_t pte;
+
+	pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &pg->gmch_ctrl);
+	pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
+			      pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+	pg->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
+	PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+	(void) PSB_RVDC32(PSB_PGETBL_CTL);
+
+	pg->initialized = 1;
+
+	pg->gtt_phys_start = pg->pge_ctl & PAGE_MASK;
+
+	pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
+	/* fix me: video mmu has hw bug to access 0x0D0000000,
+	 * then make gatt start at 0x0e000,0000 */
+	pg->mmu_gatt_start = PSB_MEM_TT_START;
+	pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
+	gtt_pages =
+	    pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT;
+	pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
+	    >> PAGE_SHIFT;
+
+	pci_read_config_dword(dev->pdev, PSB_BSM, &pg->stolen_base);
+	vram_stolen_size = pg->gtt_phys_start - pg->stolen_base - PAGE_SIZE;
+
+	/* CI is not included in the stolen size since the TOPAZ MMU bug */
+	ci_stolen_size = dev_priv->ci_region_size;
+	/* Don't add CI & RAR share buffer space
+	 * managed by TTM to stolen_size */
+	stolen_size = vram_stolen_size;
+
+	rar_stolen_size = dev_priv->rar_region_size;
+
+	printk(KERN_INFO"GMMADR(region 0) start: 0x%08x (%dM).\n",
+		pg->gatt_start, pg->gatt_pages/256);
+	printk(KERN_INFO"GTTADR(region 3) start: 0x%08x (can map %dM RAM), and actual RAM base 0x%08x.\n",
+		pg->gtt_start, gtt_pages * 4, pg->gtt_phys_start);
+	printk(KERN_INFO "Stole memory information\n");
+	printk(KERN_INFO "      base in RAM: 0x%x\n", pg->stolen_base);
+	printk(KERN_INFO "      size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
+		vram_stolen_size/1024);
+	dvmt_mode = (pg->gmch_ctrl >> 4) & 0x7;
+	printk(KERN_INFO "      the correct size should be: %dM(dvmt mode=%d)\n",
+		(dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
+
+	if (ci_stolen_size > 0)
+		printk(KERN_INFO"CI Stole memory: RAM base = 0x%08x, size = %lu M\n",
+				dev_priv->ci_region_start,
+				ci_stolen_size / 1024 / 1024);
+	if (rar_stolen_size > 0)
+		printk(KERN_INFO "RAR Stole memory: RAM base = 0x%08x, size = %lu M\n",
+			dev_priv->rar_region_start,
+			rar_stolen_size / 1024 / 1024);
+
+	if (resume && (gtt_pages != pg->gtt_pages) &&
+	    (stolen_size != pg->stolen_size)) {
+		DRM_ERROR("GTT resume error.\n");
+		ret = -EINVAL;
+		goto out_err;
+	}
+
+	pg->gtt_pages = gtt_pages;
+	pg->stolen_size = stolen_size;
+	pg->vram_stolen_size = vram_stolen_size;
+	pg->ci_stolen_size = ci_stolen_size;
+	pg->rar_stolen_size = rar_stolen_size;
+	pg->gtt_map =
+	    ioremap_nocache(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT);
+	if (!pg->gtt_map) {
+		DRM_ERROR("Failure to map gtt.\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	pg->vram_addr = ioremap_wc(pg->stolen_base, stolen_size);
+	if (!pg->vram_addr) {
+		DRM_ERROR("Failure to map stolen base.\n");
+		ret = -ENOMEM;
+		goto out_err;
+	}
+
+	DRM_DEBUG("%s: vram kernel virtual address %p\n", pg->vram_addr);
+
+	tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+		(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+	ttm_gtt_map = pg->gtt_map + tt_pages / 2;
+
+	/*
+	 * insert vram stolen pages.
+	 */
+
+	pfn_base = pg->stolen_base >> PAGE_SHIFT;
+	vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
+	printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
+		num_pages, pfn_base, 0);
+	for (i = 0; i < num_pages; ++i) {
+		pte = psb_gtt_mask_pte(pfn_base + i, 0);
+		iowrite32(pte, pg->gtt_map + i);
+	}
+
+	/*
+	 * Init rest of gtt managed by IMG.
+	 */
+	pfn_base = page_to_pfn(dev_priv->scratch_page);
+	pte = psb_gtt_mask_pte(pfn_base, 0);
+	for (; i < tt_pages / 2 - 1; ++i)
+		iowrite32(pte, pg->gtt_map + i);
+
+	/*
+	 * insert CI stolen pages
+	 */
+
+	pfn_base = dev_priv->ci_region_start >> PAGE_SHIFT;
+	ci_pages = num_pages = ci_stolen_size >> PAGE_SHIFT;
+	printk(KERN_INFO"Set up %d CI stolen pages starting at 0x%08x, GTT offset %dK\n",
+	       num_pages, pfn_base, (ttm_gtt_map - pg->gtt_map) * 4);
+	for (i = 0; i < num_pages; ++i) {
+		pte = psb_gtt_mask_pte(pfn_base + i, 0);
+		iowrite32(pte, ttm_gtt_map + i);
+	}
+
+	/*
+	 * insert RAR stolen pages
+	 */
+	if (rar_stolen_size != 0) {
+		pfn_base = dev_priv->rar_region_start >> PAGE_SHIFT;
+		num_pages = rar_stolen_size >> PAGE_SHIFT;
+		printk(KERN_INFO"Set up %d RAR stolen pages starting at 0x%08x, GTT offset %dK\n",
+			num_pages, pfn_base,
+			(ttm_gtt_map - pg->gtt_map + i) * 4);
+		for (; i < num_pages + ci_pages; ++i) {
+			pte = psb_gtt_mask_pte(pfn_base + i - ci_pages, 0);
+			iowrite32(pte, ttm_gtt_map + i);
+		}
+	}
+	/*
+	 * Init rest of gtt managed by TTM.
+	 */
+
+	pfn_base = page_to_pfn(dev_priv->scratch_page);
+	pte = psb_gtt_mask_pte(pfn_base, 0);
+	PSB_DEBUG_INIT("Initializing the rest of a total "
+		       "of %d gtt pages.\n", pg->gatt_pages);
+
+	for (; i < pg->gatt_pages - tt_pages / 2; ++i)
+		iowrite32(pte, ttm_gtt_map + i);
+	(void) ioread32(pg->gtt_map + i - 1);
+
+	return 0;
+
+out_err:
+	psb_gtt_takedown(pg, 0);
+	return ret;
+}
+
+int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
+			 unsigned offset_pages, unsigned num_pages,
+			 unsigned desired_tile_stride,
+			 unsigned hw_tile_stride, int type)
+{
+	unsigned rows = 1;
+	unsigned add;
+	unsigned row_add;
+	unsigned i;
+	unsigned j;
+	uint32_t *cur_page = NULL;
+	uint32_t pte;
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride;
+	row_add = hw_tile_stride;
+
+	down_read(&pg->sem);
+	for (i = 0; i < rows; ++i) {
+		cur_page = pg->gtt_map + offset_pages;
+		for (j = 0; j < desired_tile_stride; ++j) {
+			pte =
+			    psb_gtt_mask_pte(page_to_pfn(*pages++), type);
+			iowrite32(pte, cur_page++);
+		}
+		offset_pages += add;
+	}
+	(void) ioread32(cur_page - 1);
+	up_read(&pg->sem);
+
+	return 0;
+}
+
+int psb_gtt_insert_phys_addresses(struct psb_gtt *pg, dma_addr_t *pPhysFrames,
+			unsigned offset_pages, unsigned num_pages, int type)
+{
+	unsigned j;
+	uint32_t *cur_page = NULL;
+	uint32_t pte;
+	u32 ba;
+
+	down_read(&pg->sem);
+	cur_page = pg->gtt_map + offset_pages;
+	for (j = 0; j < num_pages; ++j) {
+		ba = *pPhysFrames++;
+		pte =  psb_gtt_mask_pte(ba >> PAGE_SHIFT, type);
+		iowrite32(pte, cur_page++);
+	}
+	(void) ioread32(cur_page - 1);
+	up_read(&pg->sem);
+	return 0;
+}
+
+int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
+			 unsigned num_pages, unsigned desired_tile_stride,
+			 unsigned hw_tile_stride, int rc_prot)
+{
+	struct drm_psb_private *dev_priv = pg->dev->dev_private;
+	unsigned rows = 1;
+	unsigned add;
+	unsigned row_add;
+	unsigned i;
+	unsigned j;
+	uint32_t *cur_page = NULL;
+	unsigned pfn_base = page_to_pfn(dev_priv->scratch_page);
+	uint32_t pte = psb_gtt_mask_pte(pfn_base, 0);
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride;
+	row_add = hw_tile_stride;
+
+	if (rc_prot)
+		down_read(&pg->sem);
+	for (i = 0; i < rows; ++i) {
+		cur_page = pg->gtt_map + offset_pages;
+		for (j = 0; j < desired_tile_stride; ++j)
+			iowrite32(pte, cur_page++);
+
+		offset_pages += add;
+	}
+	(void) ioread32(cur_page - 1);
+	if (rc_prot)
+		up_read(&pg->sem);
+
+	return 0;
+}
+
+int psb_gtt_mm_init(struct psb_gtt *pg)
+{
+	struct psb_gtt_mm *gtt_mm;
+	struct drm_psb_private *dev_priv = pg->dev->dev_private;
+	struct drm_open_hash *ht;
+	struct drm_mm *mm;
+	int ret;
+	uint32_t tt_start;
+	uint32_t tt_size;
+
+	if (!pg || !pg->initialized) {
+		DRM_DEBUG("Invalid gtt struct\n");
+		return -EINVAL;
+	}
+
+	gtt_mm =  kzalloc(sizeof(struct psb_gtt_mm), GFP_KERNEL);
+	if (!gtt_mm)
+		return -ENOMEM;
+
+	spin_lock_init(&gtt_mm->lock);
+
+	ht = &gtt_mm->hash;
+	ret = drm_ht_create(ht, 20);
+	if (ret) {
+		DRM_DEBUG("Create hash table failed(%d)\n", ret);
+		goto err_free;
+	}
+
+	tt_start = (pg->stolen_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	tt_start = (tt_start < pg->gatt_pages) ? tt_start : pg->gatt_pages;
+	tt_size = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
+			(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
+
+	mm = &gtt_mm->base;
+
+	/*will use tt_start ~ 128M for IMG TT buffers*/
+	ret = drm_mm_init(mm, tt_start, ((tt_size / 2) - tt_start));
+	if (ret) {
+		DRM_DEBUG("drm_mm_int error(%d)\n", ret);
+		goto err_mm_init;
+	}
+
+	gtt_mm->count = 0;
+
+	dev_priv->gtt_mm = gtt_mm;
+
+	DRM_INFO("PSB GTT mem manager ready, tt_start %ld, tt_size %ld pages\n",
+		(unsigned long)tt_start,
+		(unsigned long)((tt_size / 2) - tt_start));
+	return 0;
+err_mm_init:
+	drm_ht_remove(ht);
+
+err_free:
+	kfree(gtt_mm);
+	return ret;
+}
+
+/**
+ * Delete all hash entries;
+ */
+void psb_gtt_mm_takedown(void)
+{
+	return;
+}
+
+static int psb_gtt_mm_get_ht_by_pid_locked(struct psb_gtt_mm *mm,
+				    u32 tgid,
+				    struct psb_gtt_hash_entry **hentry)
+{
+	struct drm_hash_item *entry;
+	struct psb_gtt_hash_entry *psb_entry;
+	int ret;
+
+	ret = drm_ht_find_item(&mm->hash, tgid, &entry);
+	if (ret) {
+		DRM_DEBUG("Cannot find entry pid=%ld\n", tgid);
+		return ret;
+	}
+
+	psb_entry = container_of(entry, struct psb_gtt_hash_entry, item);
+	if (!psb_entry) {
+		DRM_DEBUG("Invalid entry");
+		return -EINVAL;
+	}
+
+	*hentry = psb_entry;
+	return 0;
+}
+
+
+static int psb_gtt_mm_insert_ht_locked(struct psb_gtt_mm *mm,
+				       u32 tgid,
+				       struct psb_gtt_hash_entry *hentry)
+{
+	struct drm_hash_item *item;
+	int ret;
+
+	if (!hentry) {
+		DRM_DEBUG("Invalid parameters\n");
+		return -EINVAL;
+	}
+
+	item = &hentry->item;
+	item->key = tgid;
+
+	/**
+	 * NOTE: drm_ht_insert_item will perform such a check
+	ret = psb_gtt_mm_get_ht_by_pid(mm, tgid, &tmp);
+	if (!ret) {
+		DRM_DEBUG("Entry already exists for pid %ld\n", tgid);
+		return -EAGAIN;
+	}
+	*/
+
+	/*Insert the given entry*/
+	ret = drm_ht_insert_item(&mm->hash, item);
+	if (ret) {
+		DRM_DEBUG("Insert failure\n");
+		return ret;
+	}
+
+	mm->count++;
+
+	return 0;
+}
+
+static int psb_gtt_mm_alloc_insert_ht(struct psb_gtt_mm *mm,
+				      u32 tgid,
+				      struct psb_gtt_hash_entry **entry)
+{
+	struct psb_gtt_hash_entry *hentry;
+	int ret;
+
+	/*if the hentry for this tgid exists, just get it and return*/
+	spin_lock(&mm->lock);
+	ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
+	if (!ret) {
+		DRM_DEBUG("Entry for tgid %ld exist, hentry %p\n",
+			  tgid, hentry);
+		*entry = hentry;
+		spin_unlock(&mm->lock);
+		return 0;
+	}
+	spin_unlock(&mm->lock);
+
+	DRM_DEBUG("Entry for tgid %ld doesn't exist, will create it\n", tgid);
+
+	hentry = kzalloc(sizeof(struct psb_gtt_hash_entry), GFP_KERNEL);
+	if (!hentry) {
+		DRM_DEBUG("Kmalloc failled\n");
+		return -ENOMEM;
+	}
+
+	ret = drm_ht_create(&hentry->ht, 20);
+	if (ret) {
+		DRM_DEBUG("Create hash table failed\n");
+		return ret;
+	}
+
+	spin_lock(&mm->lock);
+	ret = psb_gtt_mm_insert_ht_locked(mm, tgid, hentry);
+	spin_unlock(&mm->lock);
+
+	if (!ret)
+		*entry = hentry;
+
+	return ret;
+}
+
+static struct psb_gtt_hash_entry *
+psb_gtt_mm_remove_ht_locked(struct psb_gtt_mm *mm, u32 tgid)
+{
+	struct psb_gtt_hash_entry *tmp;
+	int ret;
+
+	ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &tmp);
+	if (ret) {
+		DRM_DEBUG("Cannot find entry pid %ld\n", tgid);
+		return NULL;
+	}
+
+	/*remove it from ht*/
+	drm_ht_remove_item(&mm->hash, &tmp->item);
+
+	mm->count--;
+
+	return tmp;
+}
+
+static int psb_gtt_mm_remove_free_ht_locked(struct psb_gtt_mm *mm, u32 tgid)
+{
+	struct psb_gtt_hash_entry *entry;
+
+	entry = psb_gtt_mm_remove_ht_locked(mm, tgid);
+
+	if (!entry) {
+		DRM_DEBUG("Invalid entry");
+		return -EINVAL;
+	}
+
+	/*delete ht*/
+	drm_ht_remove(&entry->ht);
+
+	/*free this entry*/
+	kfree(entry);
+	return 0;
+}
+
+static int
+psb_gtt_mm_get_mem_mapping_locked(struct drm_open_hash *ht,
+			   u32 key,
+			   struct psb_gtt_mem_mapping **hentry)
+{
+	struct drm_hash_item *entry;
+	struct psb_gtt_mem_mapping *mapping;
+	int ret;
+
+	ret = drm_ht_find_item(ht, key, &entry);
+	if (ret) {
+		DRM_DEBUG("Cannot find key %ld\n", key);
+		return ret;
+	}
+
+	mapping =  container_of(entry, struct psb_gtt_mem_mapping, item);
+	if (!mapping) {
+		DRM_DEBUG("Invalid entry\n");
+		return -EINVAL;
+	}
+
+	*hentry = mapping;
+	return 0;
+}
+
+static int
+psb_gtt_mm_insert_mem_mapping_locked(struct drm_open_hash *ht,
+			      u32 key,
+			      struct psb_gtt_mem_mapping *hentry)
+{
+	struct drm_hash_item *item;
+	struct psb_gtt_hash_entry *entry;
+	int ret;
+
+	if (!hentry) {
+		DRM_DEBUG("hentry is NULL\n");
+		return -EINVAL;
+	}
+
+	item = &hentry->item;
+	item->key = key;
+
+	ret = drm_ht_insert_item(ht, item);
+	if (ret) {
+		DRM_DEBUG("insert_item failed\n");
+		return ret;
+	}
+
+	entry = container_of(ht, struct psb_gtt_hash_entry, ht);
+	if (entry)
+		entry->count++;
+
+	return 0;
+}
+
+static int
+psb_gtt_mm_alloc_insert_mem_mapping(struct psb_gtt_mm *mm,
+				    struct drm_open_hash *ht,
+				    u32 key,
+				    struct drm_mm_node *node,
+				    struct psb_gtt_mem_mapping **entry)
+{
+	struct psb_gtt_mem_mapping *mapping;
+	int ret;
+
+	if (!node || !ht) {
+		DRM_DEBUG("parameter error\n");
+		return -EINVAL;
+	}
+
+	/*try to get this mem_map */
+	spin_lock(&mm->lock);
+	ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &mapping);
+	if (!ret) {
+		DRM_DEBUG("mapping entry for key %ld exists, entry %p\n",
+			  key, mapping);
+		*entry = mapping;
+		spin_unlock(&mm->lock);
+		return 0;
+	}
+	spin_unlock(&mm->lock);
+
+	DRM_DEBUG("Mapping entry for key %ld doesn't exist, will create it\n",
+		  key);
+
+	mapping = kzalloc(sizeof(struct psb_gtt_mem_mapping), GFP_KERNEL);
+	if (!mapping) {
+		DRM_DEBUG("kmalloc failed\n");
+		return -ENOMEM;
+	}
+
+	mapping->node = node;
+
+	spin_lock(&mm->lock);
+	ret = psb_gtt_mm_insert_mem_mapping_locked(ht, key, mapping);
+	spin_unlock(&mm->lock);
+
+	if (!ret)
+		*entry = mapping;
+
+	return ret;
+}
+
+static struct psb_gtt_mem_mapping *
+psb_gtt_mm_remove_mem_mapping_locked(struct drm_open_hash *ht, u32 key)
+{
+	struct psb_gtt_mem_mapping *tmp;
+	struct psb_gtt_hash_entry *entry;
+	int ret;
+
+	ret = psb_gtt_mm_get_mem_mapping_locked(ht, key, &tmp);
+	if (ret) {
+		DRM_DEBUG("Cannot find key %ld\n", key);
+		return NULL;
+	}
+
+	drm_ht_remove_item(ht, &tmp->item);
+
+	entry = container_of(ht, struct psb_gtt_hash_entry, ht);
+	if (entry)
+		entry->count--;
+
+	return tmp;
+}
+
+static int psb_gtt_mm_remove_free_mem_mapping_locked(struct drm_open_hash *ht,
+					      u32 key,
+					      struct drm_mm_node **node)
+{
+	struct psb_gtt_mem_mapping *entry;
+
+	entry = psb_gtt_mm_remove_mem_mapping_locked(ht, key);
+	if (!entry) {
+		DRM_DEBUG("entry is NULL\n");
+		return -EINVAL;
+	}
+
+	*node = entry->node;
+
+	kfree(entry);
+	return 0;
+}
+
+static int psb_gtt_add_node(struct psb_gtt_mm *mm,
+			    u32 tgid,
+			    u32 key,
+			    struct drm_mm_node *node,
+			    struct psb_gtt_mem_mapping **entry)
+{
+	struct psb_gtt_hash_entry *hentry;
+	struct psb_gtt_mem_mapping *mapping;
+	int ret;
+
+	ret = psb_gtt_mm_alloc_insert_ht(mm, tgid, &hentry);
+	if (ret) {
+		DRM_DEBUG("alloc_insert failed\n");
+		return ret;
+	}
+
+	ret = psb_gtt_mm_alloc_insert_mem_mapping(mm,
+						  &hentry->ht,
+						  key,
+						  node,
+						  &mapping);
+	if (ret) {
+		DRM_DEBUG("mapping alloc_insert failed\n");
+		return ret;
+	}
+
+	*entry = mapping;
+
+	return 0;
+}
+
+static int psb_gtt_remove_node(struct psb_gtt_mm *mm,
+			       u32 tgid,
+			       u32 key,
+			       struct drm_mm_node **node)
+{
+	struct psb_gtt_hash_entry *hentry;
+	struct drm_mm_node *tmp;
+	int ret;
+
+	spin_lock(&mm->lock);
+	ret = psb_gtt_mm_get_ht_by_pid_locked(mm, tgid, &hentry);
+	if (ret) {
+		DRM_DEBUG("Cannot find entry for pid %ld\n", tgid);
+		spin_unlock(&mm->lock);
+		return ret;
+	}
+	spin_unlock(&mm->lock);
+
+	/*remove mapping entry*/
+	spin_lock(&mm->lock);
+	ret = psb_gtt_mm_remove_free_mem_mapping_locked(&hentry->ht,
+							key,
+							&tmp);
+	if (ret) {
+		DRM_DEBUG("remove_free failed\n");
+		spin_unlock(&mm->lock);
+		return ret;
+	}
+
+	*node = tmp;
+
+	/*check the count of mapping entry*/
+	if (!hentry->count) {
+		DRM_DEBUG("count of mapping entry is zero, tgid=%ld\n", tgid);
+		psb_gtt_mm_remove_free_ht_locked(mm, tgid);
+	}
+
+	spin_unlock(&mm->lock);
+
+	return 0;
+}
+
+static int psb_gtt_mm_alloc_mem(struct psb_gtt_mm *mm,
+				uint32_t pages,
+				uint32_t align,
+				struct drm_mm_node **node)
+{
+	struct drm_mm_node *tmp_node;
+	int ret;
+
+	do {
+		ret = drm_mm_pre_get(&mm->base);
+		if (unlikely(ret)) {
+			DRM_DEBUG("drm_mm_pre_get error\n");
+			return ret;
+		}
+
+		spin_lock(&mm->lock);
+		tmp_node = drm_mm_search_free(&mm->base, pages, align, 1);
+		if (unlikely(!tmp_node)) {
+			DRM_DEBUG("No free node found\n");
+			spin_unlock(&mm->lock);
+			break;
+		}
+
+		tmp_node = drm_mm_get_block_atomic(tmp_node, pages, align);
+		spin_unlock(&mm->lock);
+	} while (!tmp_node);
+
+	if (!tmp_node) {
+		DRM_DEBUG("Node allocation failed\n");
+		return -ENOMEM;
+	}
+
+	*node = tmp_node;
+	return 0;
+}
+
+static void psb_gtt_mm_free_mem(struct psb_gtt_mm *mm, struct drm_mm_node *node)
+{
+	spin_lock(&mm->lock);
+	drm_mm_put_block(node);
+	spin_unlock(&mm->lock);
+}
+
+int psb_gtt_map_meminfo(struct drm_device *dev,
+			void *hKernelMemInfo,
+			uint32_t *offset)
+{
+	return -EINVAL;
+	/* FIXMEAC */
+#if 0
+	struct drm_psb_private *dev_priv
+	       = (struct drm_psb_private *)dev->dev_private;
+	void *psKernelMemInfo;
+	struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+	struct psb_gtt *pg = dev_priv->pg;
+	uint32_t size, pages, offset_pages;
+	void *kmem;
+	struct drm_mm_node *node;
+	struct page **page_list;
+	struct psb_gtt_mem_mapping *mapping = NULL;
+	int ret;
+
+	ret = psb_get_meminfo_by_handle(hKernelMemInfo, &psKernelMemInfo);
+	if (ret) {
+		DRM_DEBUG("Cannot find kernelMemInfo handle %ld\n",
+			  hKernelMemInfo);
+		return -EINVAL;
+	}
+
+	DRM_DEBUG("Got psKernelMemInfo %p for handle %lx\n",
+		  psKernelMemInfo, (u32)hKernelMemInfo);
+	size = psKernelMemInfo->ui32AllocSize;
+	kmem = psKernelMemInfo->pvLinAddrKM;
+	pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	DRM_DEBUG("KerMemInfo size %ld, cpuVadr %lx, pages %ld, osMemHdl %lx\n",
+		  size, kmem, pages, psKernelMemInfo->sMemBlk.hOSMemHandle);
+
+	if (!kmem)
+		DRM_DEBUG("kmem is NULL");
+
+	/*get pages*/
+	ret = psb_get_pages_by_mem_handle(psKernelMemInfo->sMemBlk.hOSMemHandle,
+					  &page_list);
+	if (ret) {
+		DRM_DEBUG("get pages error\n");
+		return ret;
+	}
+
+	DRM_DEBUG("get %ld pages\n", pages);
+
+	/*alloc memory in TT apeture*/
+	ret = psb_gtt_mm_alloc_mem(mm, pages, 0, &node);
+	if (ret) {
+		DRM_DEBUG("alloc TT memory error\n");
+		goto failed_pages_alloc;
+	}
+
+	/*update psb_gtt_mm*/
+	ret = psb_gtt_add_node(mm,
+			       task_tgid_nr(current),
+			       (u32)hKernelMemInfo,
+			       node,
+			       &mapping);
+	if (ret) {
+		DRM_DEBUG("add_node failed");
+		goto failed_add_node;
+	}
+
+	node = mapping->node;
+	offset_pages = node->start;
+
+	DRM_DEBUG("get free node for %ld pages, offset %ld pages",
+		  pages, offset_pages);
+
+	/*update gtt*/
+	psb_gtt_insert_pages(pg, page_list,
+			     (unsigned)offset_pages,
+			     (unsigned)pages,
+			     0,
+			     0,
+			     0);
+
+	*offset = offset_pages;
+	return 0;
+
+failed_add_node:
+	psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+	kfree(page_list);
+	return ret;
+#endif
+}
+
+int psb_gtt_unmap_meminfo(struct drm_device *dev, void * hKernelMemInfo)
+{
+	struct drm_psb_private *dev_priv
+	       = (struct drm_psb_private *)dev->dev_private;
+	struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+	struct psb_gtt *pg = dev_priv->pg;
+	uint32_t pages, offset_pages;
+	struct drm_mm_node *node;
+	int ret;
+
+	ret = psb_gtt_remove_node(mm,
+			task_tgid_nr(current),
+			(u32)hKernelMemInfo,
+			&node);
+	if (ret) {
+		DRM_DEBUG("remove node failed\n");
+		return ret;
+	}
+
+	/*remove gtt entries*/
+	offset_pages = node->start;
+	pages = node->size;
+
+	psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+
+	/*free tt node*/
+
+	psb_gtt_mm_free_mem(mm, node);
+	return 0;
+}
+
+int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
+			       struct drm_file *file_priv)
+{
+	struct psb_gtt_mapping_arg *arg
+	       = (struct psb_gtt_mapping_arg *)data;
+	uint32_t *offset_pages = &arg->offset_pages;
+
+	DRM_DEBUG("\n");
+
+	return psb_gtt_map_meminfo(dev, arg->hKernelMemInfo, offset_pages);
+}
+
+int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+
+	struct psb_gtt_mapping_arg *arg
+	       = (struct psb_gtt_mapping_arg *)data;
+
+	DRM_DEBUG("\n");
+
+	return psb_gtt_unmap_meminfo(dev, arg->hKernelMemInfo);
+}
+
+int psb_gtt_map_pvr_memory(struct drm_device *dev,  unsigned int hHandle,
+			unsigned int ui32TaskId, dma_addr_t *pPages,
+			unsigned int ui32PagesNum, unsigned int *ui32Offset)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+	struct psb_gtt *pg = dev_priv->pg;
+	uint32_t size, pages, offset_pages;
+	struct drm_mm_node *node = NULL;
+	struct psb_gtt_mem_mapping *mapping = NULL;
+	int ret;
+
+	size = ui32PagesNum * PAGE_SIZE;
+	pages = 0;
+
+	/*alloc memory in TT apeture*/
+	ret = psb_gtt_mm_alloc_mem(mm, ui32PagesNum, 0, &node);
+	if (ret) {
+		DRM_DEBUG("alloc TT memory error\n");
+		goto failed_pages_alloc;
+	}
+
+   /*update psb_gtt_mm*/
+	ret = psb_gtt_add_node(mm,
+						   (u32)ui32TaskId,
+						   (u32)hHandle,
+						   node,
+						   &mapping);
+	if (ret) {
+		DRM_DEBUG("add_node failed");
+		goto failed_add_node;
+	}
+
+	node = mapping->node;
+	offset_pages = node->start;
+
+	DRM_DEBUG("get free node for %ld pages, offset %ld pages",
+							pages, offset_pages);
+
+	/*update gtt*/
+	psb_gtt_insert_phys_addresses(pg, pPages, (unsigned)offset_pages,
+						(unsigned)ui32PagesNum, 0);
+
+	*ui32Offset = offset_pages;
+	return 0;
+
+failed_add_node:
+	psb_gtt_mm_free_mem(mm, node);
+failed_pages_alloc:
+	return ret;
+}
+
+
+int psb_gtt_unmap_pvr_memory(struct drm_device *dev, unsigned int hHandle,
+						unsigned int ui32TaskId)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt_mm *mm = dev_priv->gtt_mm;
+	struct psb_gtt *pg = dev_priv->pg;
+	uint32_t pages, offset_pages;
+	struct drm_mm_node *node;
+	int ret;
+
+	ret = psb_gtt_remove_node(mm, (u32)ui32TaskId, (u32)hHandle, &node);
+	if (ret) {
+		printk(KERN_ERR "remove node failed\n");
+		return ret;
+	}
+
+	/*remove gtt entries*/
+	offset_pages = node->start;
+	pages = node->size;
+
+	psb_gtt_remove_pages(pg, offset_pages, pages, 0, 0, 1);
+
+	/*free tt node*/
+	psb_gtt_mm_free_mem(mm, node);
+	return 0;
+}
diff --git a/drivers/staging/gma500/psb_gtt.h b/drivers/staging/gma500/psb_gtt.h
new file mode 100644
index 0000000..0272f83
--- /dev/null
+++ b/drivers/staging/gma500/psb_gtt.h
@@ -0,0 +1,105 @@
+/**************************************************************************
+ * Copyright (c) 2007-2008, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#ifndef _PSB_GTT_H_
+#define _PSB_GTT_H_
+
+#include <drm/drmP.h>
+
+/*#include "img_types.h"*/
+
+struct psb_gtt {
+	struct drm_device *dev;
+	int initialized;
+	uint32_t gatt_start;
+	uint32_t mmu_gatt_start;
+	uint32_t ci_start;
+	uint32_t rar_start;
+	uint32_t gtt_start;
+	uint32_t gtt_phys_start;
+	unsigned gtt_pages;
+	unsigned gatt_pages;
+	uint32_t stolen_base;
+	void *vram_addr;
+	uint32_t pge_ctl;
+	u16 gmch_ctrl;
+	unsigned long stolen_size;
+	unsigned long vram_stolen_size;
+	unsigned long ci_stolen_size;
+	unsigned long rar_stolen_size;
+	uint32_t *gtt_map;
+	struct rw_semaphore sem;
+};
+
+struct psb_gtt_mm {
+	struct drm_mm base;
+	struct drm_open_hash hash;
+	uint32_t count;
+	spinlock_t lock;
+};
+
+struct psb_gtt_hash_entry {
+	struct drm_open_hash ht;
+	uint32_t count;
+	struct drm_hash_item item;
+};
+
+struct psb_gtt_mem_mapping {
+	struct drm_mm_node *node;
+	struct drm_hash_item item;
+};
+
+/*Exported functions*/
+extern int psb_gtt_init(struct psb_gtt *pg, int resume);
+extern int psb_gtt_insert_pages(struct psb_gtt *pg, struct page **pages,
+				unsigned offset_pages, unsigned num_pages,
+				unsigned desired_tile_stride,
+				unsigned hw_tile_stride, int type);
+extern int psb_gtt_remove_pages(struct psb_gtt *pg, unsigned offset_pages,
+				unsigned num_pages,
+				unsigned desired_tile_stride,
+				unsigned hw_tile_stride,
+				int rc_prot);
+
+extern struct psb_gtt *psb_gtt_alloc(struct drm_device *dev);
+extern void psb_gtt_takedown(struct psb_gtt *pg, int free);
+extern int psb_gtt_map_meminfo(struct drm_device *dev,
+				void * hKernelMemInfo,
+				uint32_t *offset);
+extern int psb_gtt_unmap_meminfo(struct drm_device *dev,
+				 void * hKernelMemInfo);
+extern int psb_gtt_map_meminfo_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv);
+extern int psb_gtt_unmap_meminfo_ioctl(struct drm_device *dev, void *data,
+				       struct drm_file *file_priv);
+extern int psb_gtt_mm_init(struct psb_gtt *pg);
+extern void psb_gtt_mm_takedown(void);
+
+extern int psb_gtt_map_pvr_memory(struct drm_device *dev,
+                                                                  unsigned int hHandle,
+                                                                  unsigned int ui32TaskId,
+                                                                  dma_addr_t *pPages,
+                                                                  unsigned int ui32PagesNum,
+                                                                  unsigned int *ui32Offset);
+
+extern int psb_gtt_unmap_pvr_memory(struct drm_device *dev,
+                                                                        unsigned int hHandle,
+                                                                        unsigned int ui32TaskId);
+
+#endif
diff --git a/drivers/staging/gma500/psb_intel_bios.c b/drivers/staging/gma500/psb_intel_bios.c
new file mode 100644
index 0000000..f5bcd11
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_bios.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2006 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+#include <drm/drmP.h>
+#include <drm/drm.h>
+#include "psb_drm.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_bios.h"
+
+
+static void *find_section(struct bdb_header *bdb, int section_id)
+{
+	u8 *base = (u8 *)bdb;
+	int index = 0;
+	u16 total, current_size;
+	u8 current_id;
+
+	/* skip to first section */
+	index += bdb->header_size;
+	total = bdb->bdb_size;
+
+	/* walk the sections looking for section_id */
+	while (index < total) {
+		current_id = *(base + index);
+		index++;
+		current_size = *((u16 *)(base + index));
+		index += 2;
+		if (current_id == section_id)
+			return base + index;
+		index += current_size;
+	}
+
+	return NULL;
+}
+
+static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
+			struct lvds_dvo_timing *dvo_timing)
+{
+	panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) |
+		dvo_timing->hactive_lo;
+	panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay +
+		((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo);
+	panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start +
+		dvo_timing->hsync_pulse_width;
+	panel_fixed_mode->htotal = panel_fixed_mode->hdisplay +
+		((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo);
+
+	panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) |
+		dvo_timing->vactive_lo;
+	panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay +
+		dvo_timing->vsync_off;
+	panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start +
+		dvo_timing->vsync_pulse_width;
+	panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay +
+		((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo);
+	panel_fixed_mode->clock = dvo_timing->clock * 10;
+	panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED;
+
+	/* Some VBTs have bogus h/vtotal values */
+	if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
+		panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
+	if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal)
+		panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1;
+
+	drm_mode_set_name(panel_fixed_mode);
+}
+
+static void parse_backlight_data(struct drm_psb_private *dev_priv,
+				struct bdb_header *bdb)
+{
+	struct bdb_lvds_backlight *vbt_lvds_bl = NULL;
+	struct bdb_lvds_backlight *lvds_bl;
+	u8 p_type = 0;
+	void *bl_start = NULL;
+	struct bdb_lvds_options *lvds_opts
+				= find_section(bdb, BDB_LVDS_OPTIONS);
+
+	dev_priv->lvds_bl = NULL;
+
+	if (lvds_opts) {
+		DRM_DEBUG("lvds_options found at %p\n", lvds_opts);
+		p_type = lvds_opts->panel_type;
+	} else {
+		DRM_DEBUG("no lvds_options\n");
+		return;
+	}
+
+	bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT);
+	vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type;
+
+	lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL);
+	if (!lvds_bl) {
+		DRM_DEBUG("No memory\n");
+		return;
+	}
+
+	memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl));
+
+	dev_priv->lvds_bl = lvds_bl;
+}
+
+/* Try to find integrated panel data */
+static void parse_lfp_panel_data(struct drm_psb_private *dev_priv,
+			    struct bdb_header *bdb)
+{
+	struct bdb_lvds_options *lvds_options;
+	struct bdb_lvds_lfp_data *lvds_lfp_data;
+	struct bdb_lvds_lfp_data_entry *entry;
+	struct lvds_dvo_timing *dvo_timing;
+	struct drm_display_mode *panel_fixed_mode;
+
+	/* Defaults if we can't find VBT info */
+	dev_priv->lvds_dither = 0;
+	dev_priv->lvds_vbt = 0;
+
+	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+	if (!lvds_options)
+		return;
+
+	dev_priv->lvds_dither = lvds_options->pixel_dither;
+	if (lvds_options->panel_type == 0xff)
+		return;
+
+	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+	if (!lvds_lfp_data)
+		return;
+
+	dev_priv->lvds_vbt = 1;
+
+	entry = &lvds_lfp_data->data[lvds_options->panel_type];
+	dvo_timing = &entry->dvo_timing;
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode),
+				      GFP_KERNEL);
+
+	fill_detail_timing_data(panel_fixed_mode, dvo_timing);
+
+	dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode;
+
+	DRM_DEBUG("Found panel mode in BIOS VBT tables:\n");
+	drm_mode_debug_printmodeline(panel_fixed_mode);
+
+	return;
+}
+
+/* Try to find sdvo panel data */
+static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv,
+		      struct bdb_header *bdb)
+{
+	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
+	struct lvds_dvo_timing *dvo_timing;
+	struct drm_display_mode *panel_fixed_mode;
+
+	dev_priv->sdvo_lvds_vbt_mode = NULL;
+
+	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+	if (!sdvo_lvds_options)
+		return;
+
+	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+	if (!dvo_timing)
+		return;
+
+	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
+
+	if (!panel_fixed_mode)
+		return;
+
+	fill_detail_timing_data(panel_fixed_mode,
+			dvo_timing + sdvo_lvds_options->panel_type);
+
+	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
+
+	return;
+}
+
+static void parse_general_features(struct drm_psb_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct bdb_general_features *general;
+
+	/* Set sensible defaults in case we can't find the general block */
+	dev_priv->int_tv_support = 1;
+	dev_priv->int_crt_support = 1;
+
+	general = find_section(bdb, BDB_GENERAL_FEATURES);
+	if (general) {
+		dev_priv->int_tv_support = general->int_tv_support;
+		dev_priv->int_crt_support = general->int_crt_support;
+		dev_priv->lvds_use_ssc = general->enable_ssc;
+
+		if (dev_priv->lvds_use_ssc) {
+			dev_priv->lvds_ssc_freq
+				= general->ssc_freq ? 100 : 96;
+		}
+	}
+}
+
+/**
+ * psb_intel_init_bios - initialize VBIOS settings & find VBT
+ * @dev: DRM device
+ *
+ * Loads the Video BIOS and checks that the VBT exists.  Sets scratch registers
+ * to appropriate values.
+ *
+ * VBT existence is a sanity check that is relied on by other i830_bios.c code.
+ * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may
+ * feed an updated VBT back through that, compared to what we'll fetch using
+ * this method of groping around in the BIOS data.
+ *
+ * Returns 0 on success, nonzero on failure.
+ */
+bool psb_intel_init_bios(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct pci_dev *pdev = dev->pdev;
+	struct vbt_header *vbt = NULL;
+	struct bdb_header *bdb;
+	u8 __iomem *bios;
+	size_t size;
+	int i;
+
+	bios = pci_map_rom(pdev, &size);
+	if (!bios)
+		return -1;
+
+	/* Scour memory looking for the VBT signature */
+	for (i = 0; i + 4 < size; i++) {
+		if (!memcmp(bios + i, "$VBT", 4)) {
+			vbt = (struct vbt_header *)(bios + i);
+			break;
+		}
+	}
+
+	if (!vbt) {
+		DRM_ERROR("VBT signature missing\n");
+		pci_unmap_rom(pdev, bios);
+		return -1;
+	}
+
+	bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset);
+
+	/* Grab useful general definitions */
+	parse_general_features(dev_priv, bdb);
+	parse_lfp_panel_data(dev_priv, bdb);
+	parse_sdvo_panel_data(dev_priv, bdb);
+	parse_backlight_data(dev_priv, bdb);
+
+	pci_unmap_rom(pdev, bios);
+
+	return 0;
+}
+
+/**
+ * Destory and free VBT data
+ */
+void psb_intel_destroy_bios(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_display_mode *sdvo_lvds_vbt_mode =
+				dev_priv->sdvo_lvds_vbt_mode;
+	struct drm_display_mode *lfp_lvds_vbt_mode =
+				dev_priv->lfp_lvds_vbt_mode;
+	struct bdb_lvds_backlight *lvds_bl =
+				dev_priv->lvds_bl;
+
+	/*free sdvo panel mode*/
+	if (sdvo_lvds_vbt_mode) {
+		dev_priv->sdvo_lvds_vbt_mode = NULL;
+		kfree(sdvo_lvds_vbt_mode);
+	}
+
+	if (lfp_lvds_vbt_mode) {
+		dev_priv->lfp_lvds_vbt_mode = NULL;
+		kfree(lfp_lvds_vbt_mode);
+	}
+
+	if (lvds_bl) {
+		dev_priv->lvds_bl = NULL;
+		kfree(lvds_bl);
+	}
+}
diff --git a/drivers/staging/gma500/psb_intel_bios.h b/drivers/staging/gma500/psb_intel_bios.h
new file mode 100644
index 0000000..70f1bf0
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_bios.h
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2006 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+#ifndef _I830_BIOS_H_
+#define _I830_BIOS_H_
+
+#include <drm/drmP.h>
+
+struct vbt_header {
+	u8 signature[20];		/**< Always starts with 'VBT$' */
+	u16 version;			/**< decimal */
+	u16 header_size;		/**< in bytes */
+	u16 vbt_size;			/**< in bytes */
+	u8 vbt_checksum;
+	u8 reserved0;
+	u32 bdb_offset;			/**< from beginning of VBT */
+	u32 aim_offset[4];		/**< from beginning of VBT */
+} __attribute__((packed));
+
+
+struct bdb_header {
+	u8 signature[16];		/**< Always 'BIOS_DATA_BLOCK' */
+	u16 version;			/**< decimal */
+	u16 header_size;		/**< in bytes */
+	u16 bdb_size;			/**< in bytes */
+};
+
+/* strictly speaking, this is a "skip" block, but it has interesting info */
+struct vbios_data {
+	u8 type; /* 0 == desktop, 1 == mobile */
+	u8 relstage;
+	u8 chipset;
+	u8 lvds_present:1;
+	u8 tv_present:1;
+	u8 rsvd2:6; /* finish byte */
+	u8 rsvd3[4];
+	u8 signon[155];
+	u8 copyright[61];
+	u16 code_segment;
+	u8 dos_boot_mode;
+	u8 bandwidth_percent;
+	u8 rsvd4; /* popup memory size */
+	u8 resize_pci_bios;
+	u8 rsvd5; /* is crt already on ddc2 */
+} __attribute__((packed));
+
+/*
+ * There are several types of BIOS data blocks (BDBs), each block has
+ * an ID and size in the first 3 bytes (ID in first, size in next 2).
+ * Known types are listed below.
+ */
+#define BDB_GENERAL_FEATURES	  1
+#define BDB_GENERAL_DEFINITIONS	  2
+#define BDB_OLD_TOGGLE_LIST	  3
+#define BDB_MODE_SUPPORT_LIST	  4
+#define BDB_GENERIC_MODE_TABLE	  5
+#define BDB_EXT_MMIO_REGS	  6
+#define BDB_SWF_IO		  7
+#define BDB_SWF_MMIO		  8
+#define BDB_DOT_CLOCK_TABLE	  9
+#define BDB_MODE_REMOVAL_TABLE	 10
+#define BDB_CHILD_DEVICE_TABLE	 11
+#define BDB_DRIVER_FEATURES	 12
+#define BDB_DRIVER_PERSISTENCE	 13
+#define BDB_EXT_TABLE_PTRS	 14
+#define BDB_DOT_CLOCK_OVERRIDE	 15
+#define BDB_DISPLAY_SELECT	 16
+/* 17 rsvd */
+#define BDB_DRIVER_ROTATION	 18
+#define BDB_DISPLAY_REMOVE	 19
+#define BDB_OEM_CUSTOM		 20
+#define BDB_EFP_LIST		 21 /* workarounds for VGA hsync/vsync */
+#define BDB_SDVO_LVDS_OPTIONS	 22
+#define BDB_SDVO_PANEL_DTDS	 23
+#define BDB_SDVO_LVDS_PNP_IDS	 24
+#define BDB_SDVO_LVDS_POWER_SEQ	 25
+#define BDB_TV_OPTIONS		 26
+#define BDB_LVDS_OPTIONS	 40
+#define BDB_LVDS_LFP_DATA_PTRS	 41
+#define BDB_LVDS_LFP_DATA	 42
+#define BDB_LVDS_BACKLIGHT	 43
+#define BDB_LVDS_POWER		 44
+#define BDB_SKIP		254 /* VBIOS private block, ignore */
+
+struct bdb_general_features {
+	/* bits 1 */
+	u8 panel_fitting:2;
+	u8 flexaim:1;
+	u8 msg_enable:1;
+	u8 clear_screen:3;
+	u8 color_flip:1;
+
+	/* bits 2 */
+	u8 download_ext_vbt:1;
+	u8 enable_ssc:1;
+	u8 ssc_freq:1;
+	u8 enable_lfp_on_override:1;
+	u8 disable_ssc_ddt:1;
+	u8 rsvd8:3; /* finish byte */
+
+	/* bits 3 */
+	u8 disable_smooth_vision:1;
+	u8 single_dvi:1;
+	u8 rsvd9:6; /* finish byte */
+
+	/* bits 4 */
+	u8 legacy_monitor_detect;
+
+	/* bits 5 */
+	u8 int_crt_support:1;
+	u8 int_tv_support:1;
+	u8 rsvd11:6; /* finish byte */
+} __attribute__((packed));
+
+struct bdb_general_definitions {
+	/* DDC GPIO */
+	u8 crt_ddc_gmbus_pin;
+
+	/* DPMS bits */
+	u8 dpms_acpi:1;
+	u8 skip_boot_crt_detect:1;
+	u8 dpms_aim:1;
+	u8 rsvd1:5; /* finish byte */
+
+	/* boot device bits */
+	u8 boot_display[2];
+	u8 child_dev_size;
+
+	/* device info */
+	u8 tv_or_lvds_info[33];
+	u8 dev1[33];
+	u8 dev2[33];
+	u8 dev3[33];
+	u8 dev4[33];
+	/* may be another device block here on some platforms */
+};
+
+struct bdb_lvds_options {
+	u8 panel_type;
+	u8 rsvd1;
+	/* LVDS capabilities, stored in a dword */
+	u8 pfit_mode:2;
+	u8 pfit_text_mode_enhanced:1;
+	u8 pfit_gfx_mode_enhanced:1;
+	u8 pfit_ratio_auto:1;
+	u8 pixel_dither:1;
+	u8 lvds_edid:1;
+	u8 rsvd2:1;
+	u8 rsvd4;
+} __attribute__((packed));
+
+struct bdb_lvds_backlight {
+	u8 type:2;
+	u8 pol:1;
+	u8 gpio:3;
+	u8 gmbus:2;
+	u16 freq;
+	u8 minbrightness;
+	u8 i2caddr;
+	u8 brightnesscmd;
+	/*FIXME: more...*/
+} __attribute__((packed));
+
+/* LFP pointer table contains entries to the struct below */
+struct bdb_lvds_lfp_data_ptr {
+	u16 fp_timing_offset; /* offsets are from start of bdb */
+	u8 fp_table_size;
+	u16 dvo_timing_offset;
+	u8 dvo_table_size;
+	u16 panel_pnp_id_offset;
+	u8 pnp_table_size;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data_ptrs {
+	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
+	struct bdb_lvds_lfp_data_ptr ptr[16];
+} __attribute__((packed));
+
+/* LFP data has 3 blocks per entry */
+struct lvds_fp_timing {
+	u16 x_res;
+	u16 y_res;
+	u32 lvds_reg;
+	u32 lvds_reg_val;
+	u32 pp_on_reg;
+	u32 pp_on_reg_val;
+	u32 pp_off_reg;
+	u32 pp_off_reg_val;
+	u32 pp_cycle_reg;
+	u32 pp_cycle_reg_val;
+	u32 pfit_reg;
+	u32 pfit_reg_val;
+	u16 terminator;
+} __attribute__((packed));
+
+struct lvds_dvo_timing {
+	u16 clock;		/**< In 10khz */
+	u8 hactive_lo;
+	u8 hblank_lo;
+	u8 hblank_hi:4;
+	u8 hactive_hi:4;
+	u8 vactive_lo;
+	u8 vblank_lo;
+	u8 vblank_hi:4;
+	u8 vactive_hi:4;
+	u8 hsync_off_lo;
+	u8 hsync_pulse_width;
+	u8 vsync_pulse_width:4;
+	u8 vsync_off:4;
+	u8 rsvd0:6;
+	u8 hsync_off_hi:2;
+	u8 h_image;
+	u8 v_image;
+	u8 max_hv;
+	u8 h_border;
+	u8 v_border;
+	u8 rsvd1:3;
+	u8 digital:2;
+	u8 vsync_positive:1;
+	u8 hsync_positive:1;
+	u8 rsvd2:1;
+} __attribute__((packed));
+
+struct lvds_pnp_id {
+	u16 mfg_name;
+	u16 product_code;
+	u32 serial;
+	u8 mfg_week;
+	u8 mfg_year;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data_entry {
+	struct lvds_fp_timing fp_timing;
+	struct lvds_dvo_timing dvo_timing;
+	struct lvds_pnp_id pnp_id;
+} __attribute__((packed));
+
+struct bdb_lvds_lfp_data {
+	struct bdb_lvds_lfp_data_entry data[16];
+} __attribute__((packed));
+
+struct aimdb_header {
+	char signature[16];
+	char oem_device[20];
+	u16 aimdb_version;
+	u16 aimdb_header_size;
+	u16 aimdb_size;
+} __attribute__((packed));
+
+struct aimdb_block {
+	u8 aimdb_id;
+	u16 aimdb_size;
+} __attribute__((packed));
+
+struct vch_panel_data {
+	u16 fp_timing_offset;
+	u8 fp_timing_size;
+	u16 dvo_timing_offset;
+	u8 dvo_timing_size;
+	u16 text_fitting_offset;
+	u8 text_fitting_size;
+	u16 graphics_fitting_offset;
+	u8 graphics_fitting_size;
+} __attribute__((packed));
+
+struct vch_bdb_22 {
+	struct aimdb_block aimdb_block;
+	struct vch_panel_data panels[16];
+} __attribute__((packed));
+
+struct bdb_sdvo_lvds_options {
+	u8 panel_backlight;
+	u8 h40_set_panel_type;
+	u8 panel_type;
+	u8 ssc_clk_freq;
+	u16 als_low_trip;
+	u16 als_high_trip;
+	u8 sclalarcoeff_tab_row_num;
+	u8 sclalarcoeff_tab_row_size;
+	u8 coefficient[8];
+	u8 panel_misc_bits_1;
+	u8 panel_misc_bits_2;
+	u8 panel_misc_bits_3;
+	u8 panel_misc_bits_4;
+} __attribute__((packed));
+
+
+extern bool psb_intel_init_bios(struct drm_device *dev);
+extern void psb_intel_destroy_bios(struct drm_device *dev);
+
+/*
+ * Driver<->VBIOS interaction occurs through scratch bits in
+ * GR18 & SWF*.
+ */
+
+/* GR18 bits are set on display switch and hotkey events */
+#define GR18_DRIVER_SWITCH_EN	(1<<7) /* 0: VBIOS control, 1: driver control */
+#define GR18_HOTKEY_MASK	0x78 /* See also SWF4 15:0 */
+#define   GR18_HK_NONE		(0x0<<3)
+#define   GR18_HK_LFP_STRETCH	(0x1<<3)
+#define   GR18_HK_TOGGLE_DISP	(0x2<<3)
+#define   GR18_HK_DISP_SWITCH	(0x4<<3) /* see SWF14 15:0 for what to enable */
+#define   GR18_HK_POPUP_DISABLED (0x6<<3)
+#define   GR18_HK_POPUP_ENABLED	(0x7<<3)
+#define   GR18_HK_PFIT		(0x8<<3)
+#define   GR18_HK_APM_CHANGE	(0xa<<3)
+#define   GR18_HK_MULTIPLE	(0xc<<3)
+#define GR18_USER_INT_EN	(1<<2)
+#define GR18_A0000_FLUSH_EN	(1<<1)
+#define GR18_SMM_EN		(1<<0)
+
+/* Set by driver, cleared by VBIOS */
+#define SWF00_YRES_SHIFT	16
+#define SWF00_XRES_SHIFT	0
+#define SWF00_RES_MASK		0xffff
+
+/* Set by VBIOS at boot time and driver at runtime */
+#define SWF01_TV2_FORMAT_SHIFT	8
+#define SWF01_TV1_FORMAT_SHIFT	0
+#define SWF01_TV_FORMAT_MASK	0xffff
+
+#define SWF10_VBIOS_BLC_I2C_EN	(1<<29)
+#define SWF10_GTT_OVERRIDE_EN	(1<<28)
+#define SWF10_LFP_DPMS_OVR	(1<<27) /* override DPMS on display switch */
+#define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24)
+#define   SWF10_OLD_TOGGLE	0x0
+#define   SWF10_TOGGLE_LIST_1	0x1
+#define   SWF10_TOGGLE_LIST_2	0x2
+#define   SWF10_TOGGLE_LIST_3	0x3
+#define   SWF10_TOGGLE_LIST_4	0x4
+#define SWF10_PANNING_EN	(1<<23)
+#define SWF10_DRIVER_LOADED	(1<<22)
+#define SWF10_EXTENDED_DESKTOP	(1<<21)
+#define SWF10_EXCLUSIVE_MODE	(1<<20)
+#define SWF10_OVERLAY_EN	(1<<19)
+#define SWF10_PLANEB_HOLDOFF	(1<<18)
+#define SWF10_PLANEA_HOLDOFF	(1<<17)
+#define SWF10_VGA_HOLDOFF	(1<<16)
+#define SWF10_ACTIVE_DISP_MASK	0xffff
+#define   SWF10_PIPEB_LFP2	(1<<15)
+#define   SWF10_PIPEB_EFP2	(1<<14)
+#define   SWF10_PIPEB_TV2	(1<<13)
+#define   SWF10_PIPEB_CRT2	(1<<12)
+#define   SWF10_PIPEB_LFP	(1<<11)
+#define   SWF10_PIPEB_EFP	(1<<10)
+#define   SWF10_PIPEB_TV	(1<<9)
+#define   SWF10_PIPEB_CRT	(1<<8)
+#define   SWF10_PIPEA_LFP2	(1<<7)
+#define   SWF10_PIPEA_EFP2	(1<<6)
+#define   SWF10_PIPEA_TV2	(1<<5)
+#define   SWF10_PIPEA_CRT2	(1<<4)
+#define   SWF10_PIPEA_LFP	(1<<3)
+#define   SWF10_PIPEA_EFP	(1<<2)
+#define   SWF10_PIPEA_TV	(1<<1)
+#define   SWF10_PIPEA_CRT	(1<<0)
+
+#define SWF11_MEMORY_SIZE_SHIFT	16
+#define SWF11_SV_TEST_EN	(1<<15)
+#define SWF11_IS_AGP		(1<<14)
+#define SWF11_DISPLAY_HOLDOFF	(1<<13)
+#define SWF11_DPMS_REDUCED	(1<<12)
+#define SWF11_IS_VBE_MODE	(1<<11)
+#define SWF11_PIPEB_ACCESS	(1<<10) /* 0 here means pipe a */
+#define SWF11_DPMS_MASK		0x07
+#define   SWF11_DPMS_OFF	(1<<2)
+#define   SWF11_DPMS_SUSPEND	(1<<1)
+#define   SWF11_DPMS_STANDBY	(1<<0)
+#define   SWF11_DPMS_ON		0
+
+#define SWF14_GFX_PFIT_EN	(1<<31)
+#define SWF14_TEXT_PFIT_EN	(1<<30)
+#define SWF14_LID_STATUS_CLOSED	(1<<29) /* 0 here means open */
+#define SWF14_POPUP_EN		(1<<28)
+#define SWF14_DISPLAY_HOLDOFF	(1<<27)
+#define SWF14_DISP_DETECT_EN	(1<<26)
+#define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */
+#define SWF14_DRIVER_STATUS	(1<<24)
+#define SWF14_OS_TYPE_WIN9X	(1<<23)
+#define SWF14_OS_TYPE_WINNT	(1<<22)
+/* 21:19 rsvd */
+#define SWF14_PM_TYPE_MASK	0x00070000
+#define   SWF14_PM_ACPI_VIDEO	(0x4 << 16)
+#define   SWF14_PM_ACPI		(0x3 << 16)
+#define   SWF14_PM_APM_12	(0x2 << 16)
+#define   SWF14_PM_APM_11	(0x1 << 16)
+#define SWF14_HK_REQUEST_MASK	0x0000ffff /* see GR18 6:3 for event type */
+	  /* if GR18 indicates a display switch */
+#define   SWF14_DS_PIPEB_LFP2_EN (1<<15)
+#define   SWF14_DS_PIPEB_EFP2_EN (1<<14)
+#define   SWF14_DS_PIPEB_TV2_EN  (1<<13)
+#define   SWF14_DS_PIPEB_CRT2_EN (1<<12)
+#define   SWF14_DS_PIPEB_LFP_EN  (1<<11)
+#define   SWF14_DS_PIPEB_EFP_EN  (1<<10)
+#define   SWF14_DS_PIPEB_TV_EN	 (1<<9)
+#define   SWF14_DS_PIPEB_CRT_EN  (1<<8)
+#define   SWF14_DS_PIPEA_LFP2_EN (1<<7)
+#define   SWF14_DS_PIPEA_EFP2_EN (1<<6)
+#define   SWF14_DS_PIPEA_TV2_EN  (1<<5)
+#define   SWF14_DS_PIPEA_CRT2_EN (1<<4)
+#define   SWF14_DS_PIPEA_LFP_EN  (1<<3)
+#define   SWF14_DS_PIPEA_EFP_EN  (1<<2)
+#define   SWF14_DS_PIPEA_TV_EN	 (1<<1)
+#define   SWF14_DS_PIPEA_CRT_EN  (1<<0)
+	  /* if GR18 indicates a panel fitting request */
+#define   SWF14_PFIT_EN		(1<<0) /* 0 means disable */
+	  /* if GR18 indicates an APM change request */
+#define   SWF14_APM_HIBERNATE	0x4
+#define   SWF14_APM_SUSPEND	0x3
+#define   SWF14_APM_STANDBY	0x1
+#define   SWF14_APM_RESTORE	0x0
+
+#endif /* _I830_BIOS_H_ */
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
new file mode 100644
index 0000000..80b37f4
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -0,0 +1,1489 @@
+/*
+ * Copyright ĂÂŠ 2006-2007 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+
+#include <drm/drmP.h>
+#include "psb_fb.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_display.h"
+#include "psb_powermgmt.h"
+
+
+struct psb_intel_clock_t {
+	/* given values */
+	int n;
+	int m1, m2;
+	int p1, p2;
+	/* derived values */
+	int dot;
+	int vco;
+	int m;
+	int p;
+};
+
+struct psb_intel_range_t {
+	int min, max;
+};
+
+struct psb_intel_p2_t {
+	int dot_limit;
+	int p2_slow, p2_fast;
+};
+
+#define INTEL_P2_NUM		      2
+
+struct psb_intel_limit_t {
+	struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1;
+	struct psb_intel_p2_t p2;
+};
+
+#define I8XX_DOT_MIN		  25000
+#define I8XX_DOT_MAX		 350000
+#define I8XX_VCO_MIN		 930000
+#define I8XX_VCO_MAX		1400000
+#define I8XX_N_MIN		      3
+#define I8XX_N_MAX		     16
+#define I8XX_M_MIN		     96
+#define I8XX_M_MAX		    140
+#define I8XX_M1_MIN		     18
+#define I8XX_M1_MAX		     26
+#define I8XX_M2_MIN		      6
+#define I8XX_M2_MAX		     16
+#define I8XX_P_MIN		      4
+#define I8XX_P_MAX		    128
+#define I8XX_P1_MIN		      2
+#define I8XX_P1_MAX		     33
+#define I8XX_P1_LVDS_MIN	      1
+#define I8XX_P1_LVDS_MAX	      6
+#define I8XX_P2_SLOW		      4
+#define I8XX_P2_FAST		      2
+#define I8XX_P2_LVDS_SLOW	      14
+#define I8XX_P2_LVDS_FAST	      14	/* No fast option */
+#define I8XX_P2_SLOW_LIMIT	 165000
+
+#define I9XX_DOT_MIN		  20000
+#define I9XX_DOT_MAX		 400000
+#define I9XX_VCO_MIN		1400000
+#define I9XX_VCO_MAX		2800000
+#define I9XX_N_MIN		      3
+#define I9XX_N_MAX		      8
+#define I9XX_M_MIN		     70
+#define I9XX_M_MAX		    120
+#define I9XX_M1_MIN		     10
+#define I9XX_M1_MAX		     20
+#define I9XX_M2_MIN		      5
+#define I9XX_M2_MAX		      9
+#define I9XX_P_SDVO_DAC_MIN	      5
+#define I9XX_P_SDVO_DAC_MAX	     80
+#define I9XX_P_LVDS_MIN		      7
+#define I9XX_P_LVDS_MAX		     98
+#define I9XX_P1_MIN		      1
+#define I9XX_P1_MAX		      8
+#define I9XX_P2_SDVO_DAC_SLOW		     10
+#define I9XX_P2_SDVO_DAC_FAST		      5
+#define I9XX_P2_SDVO_DAC_SLOW_LIMIT	 200000
+#define I9XX_P2_LVDS_SLOW		     14
+#define I9XX_P2_LVDS_FAST		      7
+#define I9XX_P2_LVDS_SLOW_LIMIT		 112000
+
+#define INTEL_LIMIT_I8XX_DVO_DAC    0
+#define INTEL_LIMIT_I8XX_LVDS	    1
+#define INTEL_LIMIT_I9XX_SDVO_DAC   2
+#define INTEL_LIMIT_I9XX_LVDS	    3
+
+static const struct psb_intel_limit_t psb_intel_limits[] = {
+	{			/* INTEL_LIMIT_I8XX_DVO_DAC */
+	 .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
+	 .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
+	 .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
+	 .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
+	 .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
+	 .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
+	 .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
+	 .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX},
+	 .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
+		.p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST},
+	 },
+	{			/* INTEL_LIMIT_I8XX_LVDS */
+	 .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX},
+	 .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX},
+	 .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX},
+	 .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX},
+	 .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX},
+	 .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX},
+	 .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX},
+	 .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX},
+	 .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT,
+		.p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST},
+	 },
+	{			/* INTEL_LIMIT_I9XX_SDVO_DAC */
+	 .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
+	 .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
+	 .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
+	 .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
+	 .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
+	 .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
+	 .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX},
+	 .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
+	 .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT,
+		.p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast =
+		I9XX_P2_SDVO_DAC_FAST},
+	 },
+	{			/* INTEL_LIMIT_I9XX_LVDS */
+	 .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX},
+	 .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX},
+	 .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX},
+	 .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX},
+	 .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX},
+	 .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX},
+	 .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX},
+	 .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX},
+	 /* The single-channel range is 25-112Mhz, and dual-channel
+	  * is 80-224Mhz.  Prefer single channel as much as possible.
+	  */
+	 .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT,
+		.p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST},
+	 },
+};
+
+static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc)
+{
+	const struct psb_intel_limit_t *limit;
+
+	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
+		limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS];
+	else
+		limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC];
+	return limit;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
+
+static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock)
+{
+	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+	clock->p = clock->p1 * clock->p2;
+	clock->vco = refclk * clock->m / (clock->n + 2);
+	clock->dot = clock->vco / clock->p;
+}
+
+/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
+
+static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock)
+{
+	clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
+	clock->p = clock->p1 * clock->p2;
+	clock->vco = refclk * clock->m / (clock->n + 2);
+	clock->dot = clock->vco / clock->p;
+}
+
+static void psb_intel_clock(struct drm_device *dev, int refclk,
+			struct psb_intel_clock_t *clock)
+{
+	return i9xx_clock(refclk, clock);
+}
+
+/**
+ * Returns whether any output on the specified pipe is of the specified type
+ */
+bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *l_entry;
+
+	list_for_each_entry(l_entry, &mode_config->connector_list, head) {
+		if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
+			struct psb_intel_output *psb_intel_output =
+			    to_psb_intel_output(l_entry);
+			if (psb_intel_output->type == type)
+				return true;
+		}
+	}
+	return false;
+}
+
+#define INTELPllInvalid(s)   { /* ErrorF (s) */; return false; }
+/**
+ * Returns whether the given set of divisors are valid for a given refclk with
+ * the given connectors.
+ */
+
+static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc,
+			       struct psb_intel_clock_t *clock)
+{
+	const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
+
+	if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
+		INTELPllInvalid("p1 out of range\n");
+	if (clock->p < limit->p.min || limit->p.max < clock->p)
+		INTELPllInvalid("p out of range\n");
+	if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2)
+		INTELPllInvalid("m2 out of range\n");
+	if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1)
+		INTELPllInvalid("m1 out of range\n");
+	if (clock->m1 <= clock->m2)
+		INTELPllInvalid("m1 <= m2\n");
+	if (clock->m < limit->m.min || limit->m.max < clock->m)
+		INTELPllInvalid("m out of range\n");
+	if (clock->n < limit->n.min || limit->n.max < clock->n)
+		INTELPllInvalid("n out of range\n");
+	if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
+		INTELPllInvalid("vco out of range\n");
+	/* XXX: We may need to be checking "Dot clock"
+	 * depending on the multiplier, connector, etc.,
+	 * rather than just a single range.
+	 */
+	if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
+		INTELPllInvalid("dot out of range\n");
+
+	return true;
+}
+
+/**
+ * Returns a set of divisors for the desired target clock with the given
+ * refclk, or FALSE.  The returned values represent the clock equation:
+ * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.
+ */
+static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target,
+				int refclk,
+				struct psb_intel_clock_t *best_clock)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_clock_t clock;
+	const struct psb_intel_limit_t *limit = psb_intel_limit(crtc);
+	int err = target;
+
+	if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
+	    (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
+		/*
+		 * For LVDS, if the panel is on, just rely on its current
+		 * settings for dual-channel.  We haven't figured out how to
+		 * reliably set up different single/dual channel state, if we
+		 * even can.
+		 */
+		if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
+		    LVDS_CLKB_POWER_UP)
+			clock.p2 = limit->p2.p2_fast;
+		else
+			clock.p2 = limit->p2.p2_slow;
+	} else {
+		if (target < limit->p2.dot_limit)
+			clock.p2 = limit->p2.p2_slow;
+		else
+			clock.p2 = limit->p2.p2_fast;
+	}
+
+	memset(best_clock, 0, sizeof(*best_clock));
+
+	for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max;
+	     clock.m1++) {
+		for (clock.m2 = limit->m2.min;
+		     clock.m2 < clock.m1 && clock.m2 <= limit->m2.max;
+		     clock.m2++) {
+			for (clock.n = limit->n.min;
+			     clock.n <= limit->n.max; clock.n++) {
+				for (clock.p1 = limit->p1.min;
+				     clock.p1 <= limit->p1.max;
+				     clock.p1++) {
+					int this_err;
+
+					psb_intel_clock(dev, refclk, &clock);
+
+					if (!psb_intel_PLL_is_valid
+					    (crtc, &clock))
+						continue;
+
+					this_err = abs(clock.dot - target);
+					if (this_err < err) {
+						*best_clock = clock;
+						err = this_err;
+					}
+				}
+			}
+		}
+	}
+
+	return err != target;
+}
+
+void psb_intel_wait_for_vblank(struct drm_device *dev)
+{
+	/* Wait for 20ms, i.e. one cycle at 50hz. */
+	udelay(20000);
+}
+
+int psb_intel_pipe_set_base(struct drm_crtc *crtc,
+			    int x, int y, struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_i915_master_private *master_priv; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
+	struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+	int pipe = psb_intel_crtc->pipe;
+	unsigned long Start, Offset;
+	int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
+	int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
+	int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	u32 dspcntr;
+	int ret = 0;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	/* no fb bound */
+	if (!crtc->fb) {
+		DRM_DEBUG("No FB bound\n");
+		return 0;
+	}
+
+	if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+				       OSPM_UHB_FORCE_POWER_ON))
+		return 0;
+
+	Start = mode_dev->bo_offset(dev, psbfb);
+	Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
+	REG_WRITE(dspstride, crtc->fb->pitch);
+
+	dspcntr = REG_READ(dspcntr_reg);
+	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
+
+	switch (crtc->fb->bits_per_pixel) {
+	case 8:
+		dspcntr |= DISPPLANE_8BPP;
+		break;
+	case 16:
+		if (crtc->fb->depth == 15)
+			dspcntr |= DISPPLANE_15_16BPP;
+		else
+			dspcntr |= DISPPLANE_16BPP;
+		break;
+	case 24:
+	case 32:
+		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
+		break;
+	default:
+		DRM_ERROR("Unknown color depth\n");
+		ret = -EINVAL;
+		goto psb_intel_pipe_set_base_exit;
+	}
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+	if (0 /* FIXMEAC - check what PSB needs */) {
+		REG_WRITE(dspbase, Offset);
+		REG_READ(dspbase);
+		REG_WRITE(dspsurf, Start);
+		REG_READ(dspsurf);
+	} else {
+		REG_WRITE(dspbase, Start + Offset);
+		REG_READ(dspbase);
+	}
+
+psb_intel_pipe_set_base_exit:
+
+	ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+	return ret;
+}
+
+/**
+ * Sets the power management mode of the pipe and plane.
+ *
+ * This code should probably grow support for turning the cursor off and back
+ * on appropriately at the same time as we're turning the pipe off/on.
+ */
+static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_i915_master_private *master_priv; */
+	/* struct drm_i915_private *dev_priv = dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	u32 temp;
+	bool enabled;
+
+	/* XXX: When our outputs are all unaware of DPMS modes other than off
+	 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
+	 */
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+	case DRM_MODE_DPMS_STANDBY:
+	case DRM_MODE_DPMS_SUSPEND:
+		/* Enable the DPLL */
+		temp = REG_READ(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) == 0) {
+			REG_WRITE(dpll_reg, temp);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+			REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+			/* Wait for the clocks to stabilize. */
+			udelay(150);
+		}
+
+		/* Enable the pipe */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) == 0)
+			REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
+
+		/* Enable the plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp | DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+		}
+
+		psb_intel_crtc_load_lut(crtc);
+
+		/* Give the overlay scaler a chance to enable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, true); TODO */
+		break;
+	case DRM_MODE_DPMS_OFF:
+		/* Give the overlay scaler a chance to disable
+		 * if it's on this pipe */
+		/* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
+
+		/* Disable the VGA plane that we never use */
+		REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
+
+		/* Disable display plane */
+		temp = REG_READ(dspcntr_reg);
+		if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
+			REG_WRITE(dspcntr_reg,
+				  temp & ~DISPLAY_PLANE_ENABLE);
+			/* Flush the plane changes */
+			REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
+			REG_READ(dspbase_reg);
+		}
+
+		/* Next, disable display pipes */
+		temp = REG_READ(pipeconf_reg);
+		if ((temp & PIPEACONF_ENABLE) != 0) {
+			REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
+			REG_READ(pipeconf_reg);
+		}
+
+		/* Wait for vblank for the disable to take effect. */
+		psb_intel_wait_for_vblank(dev);
+
+		temp = REG_READ(dpll_reg);
+		if ((temp & DPLL_VCO_ENABLE) != 0) {
+			REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
+			REG_READ(dpll_reg);
+		}
+
+		/* Wait for the clocks to turn off. */
+		udelay(150);
+		break;
+	}
+
+	enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
+
+	/*Set FIFO Watermarks*/
+	REG_WRITE(DSPARB, 0x3F3E);
+}
+
+static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+}
+
+static void psb_intel_crtc_commit(struct drm_crtc *crtc)
+{
+	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
+	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
+}
+
+void psb_intel_encoder_prepare(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs =
+	    encoder->helper_private;
+	/* lvds has its own version of prepare see psb_intel_lvds_prepare */
+	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+void psb_intel_encoder_commit(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs =
+	    encoder->helper_private;
+	/* lvds has its own version of commit see psb_intel_lvds_commit */
+	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+
+/**
+ * Return the pipe currently connected to the panel fitter,
+ * or -1 if the panel fitter is not present or not in use
+ */
+static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
+{
+	u32 pfit_control;
+
+	pfit_control = REG_READ(PFIT_CONTROL);
+
+	/* See if the panel fitter is in use */
+	if ((pfit_control & PFIT_ENABLE) == 0)
+		return -1;
+	/* Must be on PIPE 1 for PSB */
+	return 1;
+}
+
+static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
+			       struct drm_display_mode *mode,
+			       struct drm_display_mode *adjusted_mode,
+			       int x, int y,
+			       struct drm_framebuffer *old_fb)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	int fp_reg = (pipe == 0) ? FPA0 : FPB0;
+	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
+	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+	int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
+	int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
+	int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
+	int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
+	int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
+	int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
+	int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
+	int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
+	int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
+	int refclk;
+	struct psb_intel_clock_t clock;
+	u32 dpll = 0, fp = 0, dspcntr, pipeconf;
+	bool ok, is_sdvo = false, is_dvo = false;
+	bool is_crt = false, is_lvds = false, is_tv = false;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_connector *connector;
+
+	list_for_each_entry(connector, &mode_config->connector_list, head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+
+		if (!connector->encoder
+		    || connector->encoder->crtc != crtc)
+			continue;
+
+		switch (psb_intel_output->type) {
+		case INTEL_OUTPUT_LVDS:
+			is_lvds = true;
+			break;
+		case INTEL_OUTPUT_SDVO:
+			is_sdvo = true;
+			break;
+		case INTEL_OUTPUT_DVO:
+			is_dvo = true;
+			break;
+		case INTEL_OUTPUT_TVOUT:
+			is_tv = true;
+			break;
+		case INTEL_OUTPUT_ANALOG:
+			is_crt = true;
+			break;
+		}
+	}
+
+	refclk = 96000;
+
+	ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
+				 &clock);
+	if (!ok) {
+		DRM_ERROR("Couldn't find PLL settings for mode!\n");
+		return 0;
+	}
+
+	fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
+
+	dpll = DPLL_VGA_MODE_DIS;
+	if (is_lvds) {
+		dpll |= DPLLB_MODE_LVDS;
+		dpll |= DPLL_DVO_HIGH_SPEED;
+	} else
+		dpll |= DPLLB_MODE_DAC_SERIAL;
+	if (is_sdvo) {
+		int sdvo_pixel_multiply =
+			    adjusted_mode->clock / mode->clock;
+		dpll |= DPLL_DVO_HIGH_SPEED;
+		dpll |=
+		    (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
+	}
+
+	/* compute bitmask from p1 value */
+	dpll |= (1 << (clock.p1 - 1)) << 16;
+	switch (clock.p2) {
+	case 5:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5;
+		break;
+	case 7:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7;
+		break;
+	case 10:
+		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10;
+		break;
+	case 14:
+		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14;
+		break;
+	}
+
+	if (is_tv) {
+		/* XXX: just matching BIOS for now */
+/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */
+		dpll |= 3;
+	}
+	dpll |= PLL_REF_INPUT_DREFCLK;
+
+	/* setup pipeconf */
+	pipeconf = REG_READ(pipeconf_reg);
+
+	/* Set up the display plane register */
+	dspcntr = DISPPLANE_GAMMA_ENABLE;
+
+	if (pipe == 0)
+		dspcntr |= DISPPLANE_SEL_PIPE_A;
+	else
+		dspcntr |= DISPPLANE_SEL_PIPE_B;
+
+	dspcntr |= DISPLAY_PLANE_ENABLE;
+	pipeconf |= PIPEACONF_ENABLE;
+	dpll |= DPLL_VCO_ENABLE;
+
+
+	/* Disable the panel fitter if it was on our pipe */
+	if (psb_intel_panel_fitter_pipe(dev) == pipe)
+		REG_WRITE(PFIT_CONTROL, 0);
+
+	DRM_DEBUG("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
+	drm_mode_debug_printmodeline(mode);
+
+	if (dpll & DPLL_VCO_ENABLE) {
+		REG_WRITE(fp_reg, fp);
+		REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE);
+		REG_READ(dpll_reg);
+		udelay(150);
+	}
+
+	/* The LVDS pin pair needs to be on before the DPLLs are enabled.
+	 * This is an exception to the general rule that mode_set doesn't turn
+	 * things on.
+	 */
+	if (is_lvds) {
+		u32 lvds = REG_READ(LVDS);
+
+		lvds |=
+		    LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
+		    LVDS_PIPEB_SELECT;
+		/* Set the B0-B3 data pairs corresponding to
+		 * whether we're going to
+		 * set the DPLLs for dual-channel mode or not.
+		 */
+		if (clock.p2 == 7)
+			lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
+		else
+			lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
+
+		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
+		 * appropriately here, but we need to look more
+		 * thoroughly into how panels behave in the two modes.
+		 */
+
+		REG_WRITE(LVDS, lvds);
+		REG_READ(LVDS);
+	}
+
+	REG_WRITE(fp_reg, fp);
+	REG_WRITE(dpll_reg, dpll);
+	REG_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+	udelay(150);
+
+	/* write it again -- the BIOS does, after all */
+	REG_WRITE(dpll_reg, dpll);
+
+	REG_READ(dpll_reg);
+	/* Wait for the clocks to stabilize. */
+	udelay(150);
+
+	REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
+		  ((adjusted_mode->crtc_htotal - 1) << 16));
+	REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
+		  ((adjusted_mode->crtc_hblank_end - 1) << 16));
+	REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
+		  ((adjusted_mode->crtc_hsync_end - 1) << 16));
+	REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
+		  ((adjusted_mode->crtc_vtotal - 1) << 16));
+	REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
+		  ((adjusted_mode->crtc_vblank_end - 1) << 16));
+	REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
+		  ((adjusted_mode->crtc_vsync_end - 1) << 16));
+	/* pipesrc and dspsize control the size that is scaled from,
+	 * which should always be the user's requested size.
+	 */
+	REG_WRITE(dspsize_reg,
+		  ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
+	REG_WRITE(dsppos_reg, 0);
+	REG_WRITE(pipesrc_reg,
+		  ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
+	REG_WRITE(pipeconf_reg, pipeconf);
+	REG_READ(pipeconf_reg);
+
+	psb_intel_wait_for_vblank(dev);
+
+	REG_WRITE(dspcntr_reg, dspcntr);
+
+	/* Flush the plane changes */
+	{
+		struct drm_crtc_helper_funcs *crtc_funcs =
+		    crtc->helper_private;
+		crtc_funcs->mode_set_base(crtc, x, y, old_fb);
+	}
+
+	psb_intel_wait_for_vblank(dev);
+
+	return 0;
+}
+
+/** Loads the palette/gamma unit for the CRTC with the prepared values */
+void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv =
+				(struct drm_psb_private *)dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int palreg = PALETTE_A;
+	int i;
+
+	/* The clocks have to be on to load the palette. */
+	if (!crtc->enabled)
+		return;
+
+	switch (psb_intel_crtc->pipe) {
+	case 0:
+		break;
+	case 1:
+		palreg = PALETTE_B;
+		break;
+	case 2:
+		palreg = PALETTE_C;
+		break;
+	default:
+		DRM_ERROR("Illegal Pipe Number.\n");
+		return;
+	}
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+				      OSPM_UHB_ONLY_IF_ON)) {
+		for (i = 0; i < 256; i++) {
+			REG_WRITE(palreg + 4 * i,
+				  ((psb_intel_crtc->lut_r[i] +
+				  psb_intel_crtc->lut_adj[i]) << 16) |
+				  ((psb_intel_crtc->lut_g[i] +
+				  psb_intel_crtc->lut_adj[i]) << 8) |
+				  (psb_intel_crtc->lut_b[i] +
+				  psb_intel_crtc->lut_adj[i]));
+		}
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	} else {
+		for (i = 0; i < 256; i++) {
+			dev_priv->save_palette_a[i] =
+				  ((psb_intel_crtc->lut_r[i] +
+				  psb_intel_crtc->lut_adj[i]) << 16) |
+				  ((psb_intel_crtc->lut_g[i] +
+				  psb_intel_crtc->lut_adj[i]) << 8) |
+				  (psb_intel_crtc->lut_b[i] +
+				  psb_intel_crtc->lut_adj[i]);
+		}
+
+	}
+}
+
+/**
+ * Save HW states of giving crtc
+ */
+static void psb_intel_crtc_save(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_psb_private *dev_priv =
+			(struct drm_psb_private *)dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+	int pipeA = (psb_intel_crtc->pipe == 0);
+	uint32_t paletteReg;
+	int i;
+
+	DRM_DEBUG("\n");
+
+	if (!crtc_state) {
+		DRM_DEBUG("No CRTC state found\n");
+		return;
+	}
+
+	crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
+	crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
+	crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
+	crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
+	crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
+	crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
+	crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
+	crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
+	crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
+	crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
+	crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
+	crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
+	crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
+
+	/*NOTE: DSPSIZE DSPPOS only for psb*/
+	crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
+	crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
+
+	crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
+
+	DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+			crtc_state->saveDSPCNTR,
+			crtc_state->savePIPECONF,
+			crtc_state->savePIPESRC,
+			crtc_state->saveFP0,
+			crtc_state->saveFP1,
+			crtc_state->saveDPLL,
+			crtc_state->saveHTOTAL,
+			crtc_state->saveHBLANK,
+			crtc_state->saveHSYNC,
+			crtc_state->saveVTOTAL,
+			crtc_state->saveVBLANK,
+			crtc_state->saveVSYNC,
+			crtc_state->saveDSPSTRIDE,
+			crtc_state->saveDSPSIZE,
+			crtc_state->saveDSPPOS,
+			crtc_state->saveDSPBASE
+		);
+
+	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+	for (i = 0; i < 256; ++i)
+		crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
+}
+
+/**
+ * Restore HW states of giving crtc
+ */
+static void psb_intel_crtc_restore(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	/* struct drm_psb_private * dev_priv =
+				(struct drm_psb_private *)dev->dev_private; */
+	struct psb_intel_crtc *psb_intel_crtc =  to_psb_intel_crtc(crtc);
+	struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
+	/* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
+	int pipeA = (psb_intel_crtc->pipe == 0);
+	uint32_t paletteReg;
+	int i;
+
+	DRM_DEBUG("\n");
+
+	if (!crtc_state) {
+		DRM_DEBUG("No crtc state\n");
+		return;
+	}
+
+	DRM_DEBUG(
+		"current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+		REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
+		REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
+		REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
+		REG_READ(pipeA ? FPA0 : FPB0),
+		REG_READ(pipeA ? FPA1 : FPB1),
+		REG_READ(pipeA ? DPLL_A : DPLL_B),
+		REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
+		REG_READ(pipeA ? HBLANK_A : HBLANK_B),
+		REG_READ(pipeA ? HSYNC_A : HSYNC_B),
+		REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
+		REG_READ(pipeA ? VBLANK_A : VBLANK_B),
+		REG_READ(pipeA ? VSYNC_A : VSYNC_B),
+		REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
+		REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
+		REG_READ(pipeA ? DSPAPOS : DSPBPOS),
+		REG_READ(pipeA ? DSPABASE : DSPBBASE)
+		);
+
+	DRM_DEBUG(
+		"saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
+		crtc_state->saveDSPCNTR,
+		crtc_state->savePIPECONF,
+		crtc_state->savePIPESRC,
+		crtc_state->saveFP0,
+		crtc_state->saveFP1,
+		crtc_state->saveDPLL,
+		crtc_state->saveHTOTAL,
+		crtc_state->saveHBLANK,
+		crtc_state->saveHSYNC,
+		crtc_state->saveVTOTAL,
+		crtc_state->saveVBLANK,
+		crtc_state->saveVSYNC,
+		crtc_state->saveDSPSTRIDE,
+		crtc_state->saveDSPSIZE,
+		crtc_state->saveDSPPOS,
+		crtc_state->saveDSPBASE
+		);
+
+
+	if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
+		REG_WRITE(pipeA ? DPLL_A : DPLL_B,
+			crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
+		REG_READ(pipeA ? DPLL_A : DPLL_B);
+		DRM_DEBUG("write dpll: %x\n",
+				REG_READ(pipeA ? DPLL_A : DPLL_B));
+		udelay(150);
+	}
+
+	REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
+	REG_READ(pipeA ? FPA0 : FPB0);
+
+	REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
+	REG_READ(pipeA ? FPA1 : FPB1);
+
+	REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
+	REG_READ(pipeA ? DPLL_A : DPLL_B);
+	udelay(150);
+
+	REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
+	REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
+	REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
+	REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
+	REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
+	REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
+	REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
+
+	REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
+	REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
+
+	REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
+	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+	REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
+
+	psb_intel_wait_for_vblank(dev);
+
+	REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
+	REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
+
+	psb_intel_wait_for_vblank(dev);
+
+	paletteReg = pipeA ? PALETTE_A : PALETTE_B;
+	for (i = 0; i < 256; ++i)
+		REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
+}
+
+static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc,
+				 struct drm_file *file_priv,
+				 uint32_t handle,
+				 uint32_t width, uint32_t height)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_psb_private *dev_priv =
+				(struct drm_psb_private *)dev->dev_private;
+	struct psb_gtt *pg = dev_priv->pg;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_intel_mode_device *mode_dev = psb_intel_crtc->mode_dev;
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
+	uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
+	uint32_t temp;
+	size_t addr = 0;
+	uint32_t page_offset;
+	size_t size;
+	void *bo;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	/* if we want to turn of the cursor ignore width and height */
+	if (!handle) {
+		DRM_DEBUG("cursor off\n");
+		/* turn off the cursor */
+		temp = 0;
+		temp |= CURSOR_MODE_DISABLE;
+
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+					      OSPM_UHB_ONLY_IF_ON)) {
+			REG_WRITE(control, temp);
+			REG_WRITE(base, 0);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+
+		/* unpin the old bo */
+		if (psb_intel_crtc->cursor_bo) {
+			mode_dev->bo_unpin_for_scanout(dev,
+						       psb_intel_crtc->
+						       cursor_bo);
+			psb_intel_crtc->cursor_bo = NULL;
+		}
+
+		return 0;
+	}
+
+	/* Currently we only support 64x64 cursors */
+	if (width != 64 || height != 64) {
+		DRM_ERROR("we currently only support 64x64 cursors\n");
+		return -EINVAL;
+	}
+
+	bo = mode_dev->bo_from_handle(dev, file_priv, handle);
+	if (!bo)
+		return -ENOENT;
+
+	ret = mode_dev->bo_pin_for_scanout(dev, bo);
+	if (ret)
+		return ret;
+	size = mode_dev->bo_size(dev, bo);
+	if (size < width * height * 4) {
+		DRM_ERROR("buffer is to small\n");
+		return -ENOMEM;
+	}
+
+	/*insert this bo into gtt*/
+	DRM_DEBUG("%s: map meminfo for hw cursor. handle %x\n",
+						__func__, handle);
+
+	ret = psb_gtt_map_meminfo(dev, (void *)handle, &page_offset);
+	if (ret) {
+		DRM_ERROR("Can not map meminfo to GTT. handle 0x%x\n", handle);
+		return ret;
+	}
+
+	addr = page_offset << PAGE_SHIFT;
+
+	addr += pg->stolen_base;
+
+	psb_intel_crtc->cursor_addr = addr;
+
+	temp = 0;
+	/* set the pipe for the cursor */
+	temp |= (pipe << 28);
+	temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+				      OSPM_UHB_ONLY_IF_ON)) {
+		REG_WRITE(control, temp);
+		REG_WRITE(base, addr);
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+
+	/* unpin the old bo */
+	if (psb_intel_crtc->cursor_bo && psb_intel_crtc->cursor_bo != bo) {
+		mode_dev->bo_unpin_for_scanout(dev, psb_intel_crtc->cursor_bo);
+		psb_intel_crtc->cursor_bo = bo;
+	}
+
+	return 0;
+}
+
+static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
+{
+	struct drm_device *dev = crtc->dev;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	uint32_t temp = 0;
+	uint32_t adder;
+
+
+	if (x < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
+		x = -x;
+	}
+	if (y < 0) {
+		temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
+		y = -y;
+	}
+
+	temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
+	temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
+
+	adder = psb_intel_crtc->cursor_addr;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+				      OSPM_UHB_ONLY_IF_ON)) {
+		REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
+		REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+	return 0;
+}
+
+static void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
+			 u16 *green, u16 *blue, uint32_t type, uint32_t size)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int i;
+
+	if (size != 256)
+		return;
+
+	for (i = 0; i < 256; i++) {
+		psb_intel_crtc->lut_r[i] = red[i] >> 8;
+		psb_intel_crtc->lut_g[i] = green[i] >> 8;
+		psb_intel_crtc->lut_b[i] = blue[i] >> 8;
+	}
+
+	psb_intel_crtc_load_lut(crtc);
+}
+
+static int psb_crtc_set_config(struct drm_mode_set *set)
+{
+	int ret;
+	struct drm_device *dev = set->crtc->dev;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (!dev_priv->rpm_enabled)
+		return drm_crtc_helper_set_config(set);
+
+	pm_runtime_forbid(&dev->pdev->dev);
+	ret = drm_crtc_helper_set_config(set);
+	pm_runtime_allow(&dev->pdev->dev);
+	return ret;
+}
+
+/* Returns the clock of the currently programmed mode of the given pipe. */
+static int psb_intel_crtc_clock_get(struct drm_device *dev,
+				struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	u32 dpll;
+	u32 fp;
+	struct psb_intel_clock_t clock;
+	bool is_lvds;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+				      OSPM_UHB_ONLY_IF_ON)) {
+		dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
+		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+			fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
+		else
+			fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
+		is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	} else {
+		dpll = (pipe == 0) ?
+			dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
+
+		if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
+			fp = (pipe == 0) ?
+				dev_priv->saveFPA0 :
+				dev_priv->saveFPB0;
+		else
+			fp = (pipe == 0) ?
+				dev_priv->saveFPA1 :
+				dev_priv->saveFPB1;
+
+		is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
+	}
+
+	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
+	clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
+	clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
+
+	if (is_lvds) {
+		clock.p1 =
+		    ffs((dpll &
+			 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
+			DPLL_FPA01_P1_POST_DIV_SHIFT);
+		clock.p2 = 14;
+
+		if ((dpll & PLL_REF_INPUT_MASK) ==
+		    PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+			/* XXX: might not be 66MHz */
+			i8xx_clock(66000, &clock);
+		} else
+			i8xx_clock(48000, &clock);
+	} else {
+		if (dpll & PLL_P1_DIVIDE_BY_TWO)
+			clock.p1 = 2;
+		else {
+			clock.p1 =
+			    ((dpll &
+			      DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
+			     DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
+		}
+		if (dpll & PLL_P2_DIVIDE_BY_4)
+			clock.p2 = 4;
+		else
+			clock.p2 = 2;
+
+		i8xx_clock(48000, &clock);
+	}
+
+	/* XXX: It would be nice to validate the clocks, but we can't reuse
+	 * i830PllIsValid() because it relies on the xf86_config connector
+	 * configuration being accurate, which it isn't necessarily.
+	 */
+
+	return clock.dot;
+}
+
+/** Returns the currently programmed mode of the given pipe. */
+struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
+					     struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	int pipe = psb_intel_crtc->pipe;
+	struct drm_display_mode *mode;
+	int htot;
+	int hsync;
+	int vtot;
+	int vsync;
+	struct drm_psb_private *dev_priv = dev->dev_private;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+				      OSPM_UHB_ONLY_IF_ON)) {
+		htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
+		hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
+		vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
+		vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	} else {
+		htot = (pipe == 0) ?
+			dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
+		hsync = (pipe == 0) ?
+			dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
+		vtot = (pipe == 0) ?
+			dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
+		vsync = (pipe == 0) ?
+			dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
+	}
+
+	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
+	if (!mode)
+		return NULL;
+
+	mode->clock = psb_intel_crtc_clock_get(dev, crtc);
+	mode->hdisplay = (htot & 0xffff) + 1;
+	mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
+	mode->hsync_start = (hsync & 0xffff) + 1;
+	mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
+	mode->vdisplay = (vtot & 0xffff) + 1;
+	mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
+	mode->vsync_start = (vsync & 0xffff) + 1;
+	mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
+
+	drm_mode_set_name(mode);
+	drm_mode_set_crtcinfo(mode, 0);
+
+	return mode;
+}
+
+static void psb_intel_crtc_destroy(struct drm_crtc *crtc)
+{
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+
+	kfree(psb_intel_crtc->crtc_state);
+	drm_crtc_cleanup(crtc);
+	kfree(psb_intel_crtc);
+}
+
+static const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
+	.dpms = psb_intel_crtc_dpms,
+	.mode_fixup = psb_intel_crtc_mode_fixup,
+	.mode_set = psb_intel_crtc_mode_set,
+	.mode_set_base = psb_intel_pipe_set_base,
+	.prepare = psb_intel_crtc_prepare,
+	.commit = psb_intel_crtc_commit,
+};
+
+static const struct drm_crtc_helper_funcs mrst_helper_funcs;
+static const struct drm_crtc_helper_funcs mdfld_helper_funcs;
+const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
+
+const struct drm_crtc_funcs psb_intel_crtc_funcs = {
+	.save = psb_intel_crtc_save,
+	.restore = psb_intel_crtc_restore,
+	.cursor_set = psb_intel_crtc_cursor_set,
+	.cursor_move = psb_intel_crtc_cursor_move,
+	.gamma_set = psb_intel_crtc_gamma_set,
+	.set_config = psb_crtc_set_config,
+	.destroy = psb_intel_crtc_destroy,
+};
+
+void psb_intel_crtc_init(struct drm_device *dev, int pipe,
+		     struct psb_intel_mode_device *mode_dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_intel_crtc *psb_intel_crtc;
+	int i;
+	uint16_t *r_base, *g_base, *b_base;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	/* We allocate a extra array of drm_connector pointers
+	 * for fbdev after the crtc */
+	psb_intel_crtc =
+	    kzalloc(sizeof(struct psb_intel_crtc) +
+		    (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
+		    GFP_KERNEL);
+	if (psb_intel_crtc == NULL)
+		return;
+
+	psb_intel_crtc->crtc_state =
+		kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
+	if (!psb_intel_crtc->crtc_state) {
+		DRM_INFO("Crtc state error: No memory\n");
+		kfree(psb_intel_crtc);
+		return;
+	}
+
+	drm_crtc_init(dev, &psb_intel_crtc->base, &psb_intel_crtc_funcs);
+
+	drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
+	psb_intel_crtc->pipe = pipe;
+	psb_intel_crtc->plane = pipe;
+
+	r_base = psb_intel_crtc->base.gamma_store;
+	g_base = r_base + 256;
+	b_base = g_base + 256;
+	for (i = 0; i < 256; i++) {
+		psb_intel_crtc->lut_r[i] = i;
+		psb_intel_crtc->lut_g[i] = i;
+		psb_intel_crtc->lut_b[i] = i;
+		r_base[i] = i << 8;
+		g_base[i] = i << 8;
+		b_base[i] = i << 8;
+
+		psb_intel_crtc->lut_adj[i] = 0;
+	}
+
+	psb_intel_crtc->mode_dev = mode_dev;
+	psb_intel_crtc->cursor_addr = 0;
+
+	drm_crtc_helper_add(&psb_intel_crtc->base,
+				    &psb_intel_helper_funcs);
+
+	/* Setup the array of drm_connector pointer array */
+	psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
+	BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
+	       dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
+	dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] =
+							&psb_intel_crtc->base;
+	dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] =
+							&psb_intel_crtc->base;
+	psb_intel_crtc->mode_set.connectors =
+	    (struct drm_connector **) (psb_intel_crtc + 1);
+	psb_intel_crtc->mode_set.num_connectors = 0;
+}
+
+int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
+	struct drm_mode_object *drmmode_obj;
+	struct psb_intel_crtc *crtc;
+
+	if (!dev_priv) {
+		DRM_ERROR("called with no initialization\n");
+		return -EINVAL;
+	}
+
+	drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
+			DRM_MODE_OBJECT_CRTC);
+
+	if (!drmmode_obj) {
+		DRM_ERROR("no such CRTC id\n");
+		return -EINVAL;
+	}
+
+	crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
+	pipe_from_crtc_id->pipe = crtc->pipe;
+
+	return 0;
+}
+
+struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
+{
+	struct drm_crtc *crtc = NULL;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+		if (psb_intel_crtc->pipe == pipe)
+			break;
+	}
+	return crtc;
+}
+
+int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
+{
+	int index_mask = 0;
+	struct drm_connector *connector;
+	int entry = 0;
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    head) {
+		struct psb_intel_output *psb_intel_output =
+		    to_psb_intel_output(connector);
+		if (type_mask & (1 << psb_intel_output->type))
+			index_mask |= (1 << entry);
+		entry++;
+	}
+	return index_mask;
+}
+
+
+void psb_intel_modeset_cleanup(struct drm_device *dev)
+{
+	drm_mode_config_cleanup(dev);
+}
+
+
+/* current intel driver doesn't take advantage of encoders
+   always give back the encoder for the connector
+*/
+struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	return &psb_intel_output->enc;
+}
+
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h
new file mode 100644
index 0000000..3724b97
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_display.h
@@ -0,0 +1,25 @@
+/* copyright (c) 2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ */
+
+#ifndef _INTEL_DISPLAY_H_
+#define _INTEL_DISPLAY_H_
+
+bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
+
+#endif
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h
new file mode 100644
index 0000000..f6229c5
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef __INTEL_DRV_H__
+#define __INTEL_DRV_H__
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+#include <linux/gpio.h>
+
+/*
+ * MOORESTOWN defines
+ */
+#define DELAY_TIME1 2000 /* 1000 = 1ms */
+
+/*
+ * Display related stuff
+ */
+
+/* store information about an Ixxx DVO */
+/* The i830->i865 use multiple DVOs with multiple i2cs */
+/* the i915, i945 have a single sDVO i2c bus - which is different */
+#define MAX_OUTPUTS 6
+/* maximum connectors per crtcs in the mode set */
+#define INTELFB_CONN_LIMIT 4
+
+#define INTEL_I2C_BUS_DVO 1
+#define INTEL_I2C_BUS_SDVO 2
+
+/* these are outputs from the chip - integrated only
+ * external chips are via DVO or SDVO output */
+#define INTEL_OUTPUT_UNUSED 0
+#define INTEL_OUTPUT_ANALOG 1
+#define INTEL_OUTPUT_DVO 2
+#define INTEL_OUTPUT_SDVO 3
+#define INTEL_OUTPUT_LVDS 4
+#define INTEL_OUTPUT_TVOUT 5
+#define INTEL_OUTPUT_HDMI 6
+#define INTEL_OUTPUT_MIPI 7
+#define INTEL_OUTPUT_MIPI2 8
+
+#define INTEL_DVO_CHIP_NONE 0
+#define INTEL_DVO_CHIP_LVDS 1
+#define INTEL_DVO_CHIP_TMDS 2
+#define INTEL_DVO_CHIP_TVOUT 4
+
+enum mipi_panel_type {
+	NSC_800X480 = 1,
+	LGE_480X1024 = 2,
+	TPO_864X480 = 3
+};
+
+/**
+ * Hold information useally put on the device driver privates here,
+ * since it needs to be shared across multiple of devices drivers privates.
+*/
+struct psb_intel_mode_device {
+
+	/*
+	 * Abstracted memory manager operations
+	 */
+	void *(*bo_from_handle) (struct drm_device *dev,
+				 struct drm_file *file_priv,
+				 unsigned int handle);
+	 size_t(*bo_size) (struct drm_device *dev, void *bo);
+	 size_t(*bo_offset) (struct drm_device *dev, void *bo);
+	int (*bo_pin_for_scanout) (struct drm_device *dev, void *bo);
+	int (*bo_unpin_for_scanout) (struct drm_device *dev, void *bo);
+
+	/*
+	 * Cursor
+	 */
+	int cursor_needs_physical;
+
+	/*
+	 * LVDS info
+	 */
+	int backlight_duty_cycle;	/* restore backlight to this value */
+	bool panel_wants_dither;
+	struct drm_display_mode *panel_fixed_mode;
+	struct drm_display_mode *panel_fixed_mode2;
+	struct drm_display_mode *vbt_mode;	/* if any */
+
+	uint32_t saveBLC_PWM_CTL;
+};
+
+struct psb_intel_i2c_chan {
+	/* for getting at dev. private (mmio etc.) */
+	struct drm_device *drm_dev;
+	u32 reg;		/* GPIO reg */
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+	u8 slave_addr;
+};
+
+struct psb_intel_output {
+	struct drm_connector base;
+
+	struct drm_encoder enc;
+	int type;
+
+	struct psb_intel_i2c_chan *i2c_bus;	/* for control functions */
+	struct psb_intel_i2c_chan *ddc_bus;	/* for DDC only stuff */
+	bool load_detect_temp;
+	void *dev_priv;
+
+	struct psb_intel_mode_device *mode_dev;
+
+};
+
+struct psb_intel_crtc_state {
+	uint32_t saveDSPCNTR;
+	uint32_t savePIPECONF;
+	uint32_t savePIPESRC;
+	uint32_t saveDPLL;
+	uint32_t saveFP0;
+	uint32_t saveFP1;
+	uint32_t saveHTOTAL;
+	uint32_t saveHBLANK;
+	uint32_t saveHSYNC;
+	uint32_t saveVTOTAL;
+	uint32_t saveVBLANK;
+	uint32_t saveVSYNC;
+	uint32_t saveDSPSTRIDE;
+	uint32_t saveDSPSIZE;
+	uint32_t saveDSPPOS;
+	uint32_t saveDSPBASE;
+	uint32_t savePalette[256];
+};
+
+struct psb_intel_crtc {
+	struct drm_crtc base;
+	int pipe;
+	int plane;
+	uint32_t cursor_addr;
+	u8 lut_r[256], lut_g[256], lut_b[256];
+	u8 lut_adj[256];
+	struct psb_intel_framebuffer *fbdev_fb;
+	/* a mode_set for fbdev users on this crtc */
+	struct drm_mode_set mode_set;
+
+	/* current bo we scanout from */
+	void *scanout_bo;
+
+	/* current bo we cursor from */
+	void *cursor_bo;
+
+	struct drm_display_mode saved_mode;
+	struct drm_display_mode saved_adjusted_mode;
+
+	struct psb_intel_mode_device *mode_dev;
+
+	/*crtc mode setting flags*/
+	u32 mode_flags;
+
+	/* Saved Crtc HW states */
+	struct psb_intel_crtc_state *crtc_state;
+};
+
+#define to_psb_intel_crtc(x)	\
+		container_of(x, struct psb_intel_crtc, base)
+#define to_psb_intel_output(x)	\
+		container_of(x, struct psb_intel_output, base)
+#define enc_to_psb_intel_output(x)	\
+		container_of(x, struct psb_intel_output, enc)
+#define to_psb_intel_framebuffer(x)	\
+		container_of(x, struct psb_intel_framebuffer, base)
+
+struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
+					const u32 reg, const char *name);
+void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan);
+int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output);
+extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output);
+
+extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
+			    struct psb_intel_mode_device *mode_dev);
+extern void psb_intel_crt_init(struct drm_device *dev);
+extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device);
+extern void psb_intel_dvo_init(struct drm_device *dev);
+extern void psb_intel_tv_init(struct drm_device *dev);
+extern void psb_intel_lvds_init(struct drm_device *dev,
+			    struct psb_intel_mode_device *mode_dev);
+extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level);
+extern void mrst_lvds_init(struct drm_device *dev,
+			   struct psb_intel_mode_device *mode_dev);
+extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev);
+extern void mrst_dsi_init(struct drm_device *dev,
+			   struct psb_intel_mode_device *mode_dev);
+extern void mid_dsi_init(struct drm_device *dev,
+		    struct psb_intel_mode_device *mode_dev, int dsi_num);
+
+extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
+extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
+extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
+
+extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
+					      *connector);
+
+extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
+						    struct drm_crtc *crtc);
+extern void psb_intel_wait_for_vblank(struct drm_device *dev);
+extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
+				struct drm_file *file_priv);
+extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
+						 int pipe);
+extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
+					     int sdvoB);
+extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector);
+extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
+				   int enable);
+extern int intelfb_probe(struct drm_device *dev);
+extern int intelfb_remove(struct drm_device *dev,
+			  struct drm_framebuffer *fb);
+extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device
+							*dev, struct
+							drm_mode_fb_cmd
+							*mode_cmd,
+							void *mm_private);
+extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
+				      struct drm_display_mode *mode,
+				      struct drm_display_mode *adjusted_mode);
+extern int psb_intel_lvds_mode_valid(struct drm_connector *connector,
+				     struct drm_display_mode *mode);
+extern int psb_intel_lvds_set_property(struct drm_connector *connector,
+					struct drm_property *property,
+					uint64_t value);
+extern void psb_intel_lvds_destroy(struct drm_connector *connector);
+extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
+
+#endif				/* __INTEL_DRV_H__ */
diff --git a/drivers/staging/gma500/psb_intel_i2c.c b/drivers/staging/gma500/psb_intel_i2c.c
new file mode 100644
index 0000000..e33432d
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_i2c.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright ÂŠ 2006-2007 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+
+/*
+ * Intel GPIO access functions
+ */
+
+#define I2C_RISEFALL_TIME 20
+
+static int get_clock(void *data)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 val;
+
+	val = REG_READ(chan->reg);
+	return (val & GPIO_CLOCK_VAL_IN) != 0;
+}
+
+static int get_data(void *data)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 val;
+
+	val = REG_READ(chan->reg);
+	return (val & GPIO_DATA_VAL_IN) != 0;
+}
+
+static void set_clock(void *data, int state_high)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 reserved = 0, clock_bits;
+
+	/* On most chips, these bits must be preserved in software. */
+	reserved =
+		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+					   GPIO_CLOCK_PULLUP_DISABLE);
+
+	if (state_high)
+		clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
+	else
+		clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
+		    GPIO_CLOCK_VAL_MASK;
+	REG_WRITE(chan->reg, reserved | clock_bits);
+	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
+}
+
+static void set_data(void *data, int state_high)
+{
+	struct psb_intel_i2c_chan *chan = data;
+	struct drm_device *dev = chan->drm_dev;
+	u32 reserved = 0, data_bits;
+
+	/* On most chips, these bits must be preserved in software. */
+	reserved =
+		    REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
+					   GPIO_CLOCK_PULLUP_DISABLE);
+
+	if (state_high)
+		data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
+	else
+		data_bits =
+		    GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
+		    GPIO_DATA_VAL_MASK;
+
+	REG_WRITE(chan->reg, reserved | data_bits);
+	udelay(I2C_RISEFALL_TIME);	/* wait for the line to change state */
+}
+
+/**
+ * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
+ * @dev: DRM device
+ * @output: driver specific output device
+ * @reg: GPIO reg to use
+ * @name: name for this bus
+ *
+ * Creates and registers a new i2c bus with the Linux i2c layer, for use
+ * in output probing and control (e.g. DDC or SDVO control functions).
+ *
+ * Possible values for @reg include:
+ *   %GPIOA
+ *   %GPIOB
+ *   %GPIOC
+ *   %GPIOD
+ *   %GPIOE
+ *   %GPIOF
+ *   %GPIOG
+ *   %GPIOH
+ * see PRM for details on how these different busses are used.
+ */
+struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
+					const u32 reg, const char *name)
+{
+	struct psb_intel_i2c_chan *chan;
+
+	chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
+	if (!chan)
+		goto out_free;
+
+	chan->drm_dev = dev;
+	chan->reg = reg;
+	snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
+	chan->adapter.owner = THIS_MODULE;
+	chan->adapter.algo_data = &chan->algo;
+	chan->adapter.dev.parent = &dev->pdev->dev;
+	chan->algo.setsda = set_data;
+	chan->algo.setscl = set_clock;
+	chan->algo.getsda = get_data;
+	chan->algo.getscl = get_clock;
+	chan->algo.udelay = 20;
+	chan->algo.timeout = usecs_to_jiffies(2200);
+	chan->algo.data = chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	if (i2c_bit_add_bus(&chan->adapter))
+		goto out_free;
+
+	/* JJJ:  raise SCL and SDA? */
+	set_data(chan, 1);
+	set_clock(chan, 1);
+	udelay(20);
+
+	return chan;
+
+out_free:
+	kfree(chan);
+	return NULL;
+}
+
+/**
+ * psb_intel_i2c_destroy - unregister and free i2c bus resources
+ * @output: channel to free
+ *
+ * Unregister the adapter from the i2c layer, then free the structure.
+ */
+void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
+{
+	if (!chan)
+		return;
+
+	i2c_del_adapter(&chan->adapter);
+	kfree(chan);
+}
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c
new file mode 100644
index 0000000..d3d210a
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -0,0 +1,889 @@
+/*
+ * Copyright ÂŠ 2006-2007 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ *	Dave Airlie <airlied@linux.ie>
+ *	Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+/* #include <drm/drm_crtc.h> */
+/* #include <drm/drm_edid.h> */
+#include <drm/drmP.h>
+
+#include "psb_intel_bios.h"
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+#include <linux/pm_runtime.h>
+
+/* MRST defines start */
+uint8_t blc_freq;
+uint8_t blc_minbrightness;
+uint8_t blc_i2caddr;
+uint8_t blc_brightnesscmd;
+int lvds_backlight;		/* restore backlight to this value */
+
+u32 CoreClock;
+u32 PWMControlRegFreq;
+
+/**
+ * LVDS I2C backlight control macros
+ */
+#define BRIGHTNESS_MAX_LEVEL 100
+#define BRIGHTNESS_MASK 0xFF
+#define BLC_I2C_TYPE	0x01
+#define BLC_PWM_TYPT	0x02
+
+#define BLC_POLARITY_NORMAL 0
+#define BLC_POLARITY_INVERSE 1
+
+#define PSB_BLC_MAX_PWM_REG_FREQ       (0xFFFE)
+#define PSB_BLC_MIN_PWM_REG_FREQ	(0x2)
+#define PSB_BLC_PWM_PRECISION_FACTOR	(10)
+#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
+#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
+
+struct psb_intel_lvds_priv {
+	/**
+	 * Saved LVDO output states
+	 */
+	uint32_t savePP_ON;
+	uint32_t savePP_OFF;
+	uint32_t saveLVDS;
+	uint32_t savePP_CONTROL;
+	uint32_t savePP_CYCLE;
+	uint32_t savePFIT_CONTROL;
+	uint32_t savePFIT_PGM_RATIOS;
+	uint32_t saveBLC_PWM_CTL;
+};
+
+/* MRST defines end */
+
+/**
+ * Returns the maximum level of the backlight duty cycle field.
+ */
+static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 retVal;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+					OSPM_UHB_ONLY_IF_ON)) {
+		retVal = ((REG_READ(BLC_PWM_CTL) &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	} else
+		retVal = ((dev_priv->saveBLC_PWM_CTL &
+			  BACKLIGHT_MODULATION_FREQ_MASK) >>
+			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
+
+	return retVal;
+}
+
+/**
+ * Set LVDS backlight level by I2C command
+ */
+static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
+					unsigned int level)
+{
+	struct drm_psb_private *dev_priv =
+		(struct drm_psb_private *)dev->dev_private;
+
+	struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
+	u8 out_buf[2];
+	unsigned int blc_i2c_brightness;
+
+	struct i2c_msg msgs[] = {
+		{
+			.addr = lvds_i2c_bus->slave_addr,
+			.flags = 0,
+			.len = 2,
+			.buf = out_buf,
+		}
+	};
+
+	blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
+			     BRIGHTNESS_MASK /
+			     BRIGHTNESS_MAX_LEVEL);
+
+	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
+		blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
+
+	out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
+	out_buf[1] = (u8)blc_i2c_brightness;
+
+	if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
+		DRM_DEBUG("I2C set brightness.(command, value) (%d, %d)\n",
+			blc_brightnesscmd,
+			blc_i2c_brightness);
+		return 0;
+	}
+
+	DRM_ERROR("I2C transfer error\n");
+	return -1;
+}
+
+
+static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv =
+			(struct drm_psb_private *)dev->dev_private;
+
+	u32 max_pwm_blc;
+	u32 blc_pwm_duty_cycle;
+
+	max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);
+
+	/*BLC_PWM_CTL Should be initiated while backlight device init*/
+	BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
+
+	blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
+
+	if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
+		blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
+
+	blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
+	REG_WRITE(BLC_PWM_CTL,
+		  (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
+		  (blc_pwm_duty_cycle));
+
+	return 0;
+}
+
+/**
+ * Set LVDS backlight level either by I2C or PWM
+ */
+void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
+{
+	/*u32 blc_pwm_ctl;*/
+	struct drm_psb_private *dev_priv =
+			(struct drm_psb_private *)dev->dev_private;
+
+	DRM_DEBUG("backlight level is %d\n", level);
+
+	if (!dev_priv->lvds_bl) {
+		DRM_ERROR("NO LVDS Backlight Info\n");
+		return;
+	}
+
+	if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
+		psb_lvds_i2c_set_brightness(dev, level);
+	else
+		psb_lvds_pwm_set_brightness(dev, level);
+}
+
+/**
+ * Sets the backlight level.
+ *
+ * \param level backlight level, from 0 to psb_intel_lvds_get_max_backlight().
+ */
+static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	u32 blc_pwm_ctl;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+					OSPM_UHB_ONLY_IF_ON)) {
+		blc_pwm_ctl =
+			REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
+		REG_WRITE(BLC_PWM_CTL,
+				(blc_pwm_ctl |
+				(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	} else {
+		blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
+				~BACKLIGHT_DUTY_CYCLE_MASK;
+		dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
+					(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
+	}
+}
+
+/**
+ * Sets the power state for the panel.
+ */
+static void psb_intel_lvds_set_power(struct drm_device *dev,
+				 struct psb_intel_output *output, bool on)
+{
+	u32 pp_status;
+
+	if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+					OSPM_UHB_FORCE_POWER_ON))
+		return;
+
+	if (on) {
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
+			  POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while ((pp_status & PP_ON) == 0);
+
+		psb_intel_lvds_set_backlight(dev,
+					 output->
+					 mode_dev->backlight_duty_cycle);
+	} else {
+		psb_intel_lvds_set_backlight(dev, 0);
+
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
+			  ~POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while (pp_status & PP_ON);
+	}
+
+	ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+
+	if (mode == DRM_MODE_DPMS_ON)
+		psb_intel_lvds_set_power(dev, output, true);
+	else
+		psb_intel_lvds_set_power(dev, output, false);
+
+	/* XXX: We never power down the LVDS pairs. */
+}
+
+static void psb_intel_lvds_save(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_psb_private *dev_priv =
+		(struct drm_psb_private *)dev->dev_private;
+	struct psb_intel_output *psb_intel_output =
+		to_psb_intel_output(connector);
+	struct psb_intel_lvds_priv *lvds_priv =
+		(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
+
+	lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);
+	lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);
+	lvds_priv->saveLVDS = REG_READ(LVDS);
+	lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL);
+	lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE);
+	/*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/
+	lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+	lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL);
+	lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);
+
+	/*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/
+	dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
+						BACKLIGHT_DUTY_CYCLE_MASK);
+
+	/*
+	 * If the light is off at server startup,
+	 * just make it full brightness
+	 */
+	if (dev_priv->backlight_duty_cycle == 0)
+		dev_priv->backlight_duty_cycle =
+		psb_intel_lvds_get_max_backlight(dev);
+
+	DRM_DEBUG("(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+			lvds_priv->savePP_ON,
+			lvds_priv->savePP_OFF,
+			lvds_priv->saveLVDS,
+			lvds_priv->savePP_CONTROL,
+			lvds_priv->savePP_CYCLE,
+			lvds_priv->saveBLC_PWM_CTL);
+}
+
+static void psb_intel_lvds_restore(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	u32 pp_status;
+
+	/*struct drm_psb_private *dev_priv =
+				(struct drm_psb_private *)dev->dev_private;*/
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct psb_intel_lvds_priv *lvds_priv =
+		(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
+
+	DRM_DEBUG("(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
+			lvds_priv->savePP_ON,
+			lvds_priv->savePP_OFF,
+			lvds_priv->saveLVDS,
+			lvds_priv->savePP_CONTROL,
+			lvds_priv->savePP_CYCLE,
+			lvds_priv->saveBLC_PWM_CTL);
+
+	REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL);
+	REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL);
+	REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS);
+	REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON);
+	REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF);
+	/*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/
+	REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE);
+	REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL);
+	REG_WRITE(LVDS, lvds_priv->saveLVDS);
+
+	if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) {
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
+			POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while ((pp_status & PP_ON) == 0);
+	} else {
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
+			~POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while (pp_status & PP_ON);
+	}
+}
+
+int psb_intel_lvds_mode_valid(struct drm_connector *connector,
+				 struct drm_display_mode *mode)
+{
+	struct psb_intel_output *psb_intel_output =
+				to_psb_intel_output(connector);
+	struct drm_display_mode *fixed_mode =
+	    psb_intel_output->mode_dev->panel_fixed_mode;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
+		fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	/* just in case */
+	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+		return MODE_NO_INTERLACE;
+
+	if (fixed_mode) {
+		if (mode->hdisplay > fixed_mode->hdisplay)
+			return MODE_PANEL;
+		if (mode->vdisplay > fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+	return MODE_OK;
+}
+
+bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	struct psb_intel_mode_device *mode_dev =
+	    enc_to_psb_intel_output(encoder)->mode_dev;
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_crtc *psb_intel_crtc =
+				to_psb_intel_crtc(encoder->crtc);
+	struct drm_encoder *tmp_encoder;
+	struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
+	struct psb_intel_output *psb_intel_output =
+					enc_to_psb_intel_output(encoder);
+
+	PSB_DEBUG_ENTRY("type = 0x%x, pipe = %d.\n",
+			psb_intel_output->type, psb_intel_crtc->pipe);
+
+	if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
+		panel_fixed_mode = mode_dev->panel_fixed_mode2;
+
+	/* PSB doesn't appear to be GEN4 */
+	if (psb_intel_crtc->pipe == 0) {
+		printk(KERN_ERR "Can't support LVDS on pipe A\n");
+		return false;
+	}
+	/* Should never happen!! */
+	list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
+			    head) {
+		if (tmp_encoder != encoder
+		    && tmp_encoder->crtc == encoder->crtc) {
+			printk(KERN_ERR "Can't enable LVDS and another "
+			       "encoder on the same pipe\n");
+			return false;
+		}
+	}
+
+	/*
+	 * If we have timings from the BIOS for the panel, put them in
+	 * to the adjusted mode.  The CRTC will be set up for this mode,
+	 * with the panel scaling set up to source from the H/VDisplay
+	 * of the original mode.
+	 */
+	if (panel_fixed_mode != NULL) {
+		adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
+		adjusted_mode->htotal = panel_fixed_mode->htotal;
+		adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
+		adjusted_mode->vtotal = panel_fixed_mode->vtotal;
+		adjusted_mode->clock = panel_fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode,
+				      CRTC_INTERLACE_HALVE_V);
+	}
+
+	/*
+	 * XXX: It would be nice to support lower refresh rates on the
+	 * panels to reduce power consumption, and perhaps match the
+	 * user's requested refresh rate.
+	 */
+
+	return true;
+}
+
+static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+					OSPM_UHB_FORCE_POWER_ON))
+		return;
+
+	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
+	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
+					  BACKLIGHT_DUTY_CYCLE_MASK);
+
+	psb_intel_lvds_set_power(dev, output, false);
+
+	ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+}
+
+static void psb_intel_lvds_commit(struct drm_encoder *encoder)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
+	struct psb_intel_mode_device *mode_dev = output->mode_dev;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	if (mode_dev->backlight_duty_cycle == 0)
+		mode_dev->backlight_duty_cycle =
+		    psb_intel_lvds_get_max_backlight(dev);
+
+	psb_intel_lvds_set_power(dev, output, true);
+}
+
+static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct psb_intel_mode_device *mode_dev =
+	    enc_to_psb_intel_output(encoder)->mode_dev;
+	struct drm_device *dev = encoder->dev;
+	u32 pfit_control;
+
+	/*
+	 * The LVDS pin pair will already have been turned on in the
+	 * psb_intel_crtc_mode_set since it has a large impact on the DPLL
+	 * settings.
+	 */
+
+	/*
+	 * Enable automatic panel scaling so that non-native modes fill the
+	 * screen.  Should be enabled before the pipe is enabled, according to
+	 * register description and PRM.
+	 */
+	if (mode->hdisplay != adjusted_mode->hdisplay ||
+	    mode->vdisplay != adjusted_mode->vdisplay)
+		pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
+				HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
+				HORIZ_INTERP_BILINEAR);
+	else
+		pfit_control = 0;
+
+	if (mode_dev->panel_wants_dither)
+		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
+
+	REG_WRITE(PFIT_CONTROL, pfit_control);
+}
+
+/**
+ * Detect the LVDS connection.
+ *
+ * This always returns CONNECTOR_STATUS_CONNECTED.
+ * This connector should only have
+ * been set up if the LVDS was actually connected anyway.
+ */
+static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
+						   *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+/**
+ * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
+ */
+static int psb_intel_lvds_get_modes(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct psb_intel_mode_device *mode_dev =
+					psb_intel_output->mode_dev;
+	int ret = 0;
+
+	ret = psb_intel_ddc_get_modes(psb_intel_output);
+
+	if (ret)
+		return ret;
+
+	/* Didn't get an EDID, so
+	 * Set wide sync ranges so we get all modes
+	 * handed to valid_mode for checking
+	 */
+	connector->display_info.min_vfreq = 0;
+	connector->display_info.max_vfreq = 200;
+	connector->display_info.min_hfreq = 0;
+	connector->display_info.max_hfreq = 200;
+
+	if (mode_dev->panel_fixed_mode != NULL) {
+		struct drm_display_mode *mode =
+		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
+		drm_mode_probed_add(connector, mode);
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * psb_intel_lvds_destroy - unregister and free LVDS structures
+ * @connector: connector to free
+ *
+ * Unregister the DDC bus for this connector then free the driver private
+ * structure.
+ */
+void psb_intel_lvds_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
+int psb_intel_lvds_set_property(struct drm_connector *connector,
+				       struct drm_property *property,
+				       uint64_t value)
+{
+	struct drm_encoder *pEncoder = connector->encoder;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	if (!strcmp(property->name, "scaling mode") && pEncoder) {
+		struct psb_intel_crtc *pPsbCrtc =
+					to_psb_intel_crtc(pEncoder->crtc);
+		uint64_t curValue;
+
+		PSB_DEBUG_ENTRY("scaling mode\n");
+
+		if (!pPsbCrtc)
+			goto set_prop_error;
+
+		switch (value) {
+		case DRM_MODE_SCALE_FULLSCREEN:
+			break;
+		case DRM_MODE_SCALE_NO_SCALE:
+			break;
+		case DRM_MODE_SCALE_ASPECT:
+			break;
+		default:
+			goto set_prop_error;
+		}
+
+		if (drm_connector_property_get_value(connector,
+						     property,
+						     &curValue))
+			goto set_prop_error;
+
+		if (curValue == value)
+			goto set_prop_done;
+
+		if (drm_connector_property_set_value(connector,
+							property,
+							value))
+			goto set_prop_error;
+
+		if (pPsbCrtc->saved_mode.hdisplay != 0 &&
+		    pPsbCrtc->saved_mode.vdisplay != 0) {
+			if (!drm_crtc_helper_set_mode(pEncoder->crtc,
+						      &pPsbCrtc->saved_mode,
+						      pEncoder->crtc->x,
+						      pEncoder->crtc->y,
+						      pEncoder->crtc->fb))
+				goto set_prop_error;
+		}
+	} else if (!strcmp(property->name, "backlight") && pEncoder) {
+		PSB_DEBUG_ENTRY("backlight\n");
+
+		if (drm_connector_property_set_value(connector,
+							property,
+							value))
+			goto set_prop_error;
+		else {
+#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
+			struct backlight_device bd;
+			bd.props.brightness = value;
+			psb_set_brightness(&bd);
+#endif
+		}
+	} else if (!strcmp(property->name, "DPMS") && pEncoder) {
+		struct drm_encoder_helper_funcs *pEncHFuncs
+						= pEncoder->helper_private;
+		PSB_DEBUG_ENTRY("DPMS\n");
+		pEncHFuncs->dpms(pEncoder, value);
+	}
+
+set_prop_done:
+	return 0;
+set_prop_error:
+	return -1;
+}
+
+static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = {
+	.dpms = psb_intel_lvds_encoder_dpms,
+	.mode_fixup = psb_intel_lvds_mode_fixup,
+	.prepare = psb_intel_lvds_prepare,
+	.mode_set = psb_intel_lvds_mode_set,
+	.commit = psb_intel_lvds_commit,
+};
+
+static const struct drm_connector_helper_funcs
+				psb_intel_lvds_connector_helper_funcs = {
+	.get_modes = psb_intel_lvds_get_modes,
+	.mode_valid = psb_intel_lvds_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+static const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = psb_intel_lvds_save,
+	.restore = psb_intel_lvds_restore,
+	.detect = psb_intel_lvds_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = psb_intel_lvds_set_property,
+	.destroy = psb_intel_lvds_destroy,
+};
+
+
+static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
+	.destroy = psb_intel_lvds_enc_destroy,
+};
+
+
+
+/**
+ * psb_intel_lvds_init - setup LVDS connectors on this device
+ * @dev: drm device
+ *
+ * Create the connector, register the LVDS DDC bus, and try to figure out what
+ * modes we can display on the LVDS panel (if present).
+ */
+void psb_intel_lvds_init(struct drm_device *dev,
+		     struct psb_intel_mode_device *mode_dev)
+{
+	struct psb_intel_output *psb_intel_output;
+	struct psb_intel_lvds_priv *lvds_priv;
+	struct drm_connector *connector;
+	struct drm_encoder *encoder;
+	struct drm_display_mode *scan;	/* *modes, *bios_mode; */
+	struct drm_crtc *crtc;
+	struct drm_psb_private *dev_priv =
+				(struct drm_psb_private *)dev->dev_private;
+	u32 lvds;
+	int pipe;
+
+	psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
+	if (!lvds_priv) {
+		kfree(psb_intel_output);
+		DRM_DEBUG("LVDS private allocation error\n");
+		return;
+	}
+
+	psb_intel_output->dev_priv = lvds_priv;
+
+	psb_intel_output->mode_dev = mode_dev;
+	connector = &psb_intel_output->base;
+	encoder = &psb_intel_output->enc;
+	drm_connector_init(dev, &psb_intel_output->base,
+			   &psb_intel_lvds_connector_funcs,
+			   DRM_MODE_CONNECTOR_LVDS);
+
+	drm_encoder_init(dev, &psb_intel_output->enc,
+			 &psb_intel_lvds_enc_funcs,
+			 DRM_MODE_ENCODER_LVDS);
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+	psb_intel_output->type = INTEL_OUTPUT_LVDS;
+
+	drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);
+	drm_connector_helper_add(connector,
+				 &psb_intel_lvds_connector_helper_funcs);
+	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
+	connector->interlace_allowed = false;
+	connector->doublescan_allowed = false;
+
+	/*Attach connector properties*/
+	drm_connector_attach_property(connector,
+				      dev->mode_config.scaling_mode_property,
+				      DRM_MODE_SCALE_FULLSCREEN);
+	drm_connector_attach_property(connector,
+				      dev_priv->backlight_property,
+				      BRIGHTNESS_MAX_LEVEL);
+
+	/**
+	 * Set up I2C bus
+	 * FIXME: distroy i2c_bus when exit
+	 */
+	psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
+							 GPIOB,
+							 "LVDSBLC_B");
+	if (!psb_intel_output->i2c_bus) {
+		dev_printk(KERN_ERR,
+			&dev->pdev->dev, "I2C bus registration failed.\n");
+		goto failed_blc_i2c;
+	}
+	psb_intel_output->i2c_bus->slave_addr = 0x2C;
+	dev_priv->lvds_i2c_bus =  psb_intel_output->i2c_bus;
+
+	/*
+	 * LVDS discovery:
+	 * 1) check for EDID on DDC
+	 * 2) check for VBT data
+	 * 3) check to see if LVDS is already on
+	 *    if none of the above, no panel
+	 * 4) make sure lid is open
+	 *    if closed, act like it's not there for now
+	 */
+
+	/* Set up the DDC bus. */
+	psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
+							 GPIOC,
+							 "LVDSDDC_C");
+	if (!psb_intel_output->ddc_bus) {
+		dev_printk(KERN_ERR, &dev->pdev->dev,
+			   "DDC bus registration " "failed.\n");
+		goto failed_ddc;
+	}
+
+	/*
+	 * Attempt to get the fixed panel mode from DDC.  Assume that the
+	 * preferred mode is the right one.
+	 */
+	psb_intel_ddc_get_modes(psb_intel_output);
+	list_for_each_entry(scan, &connector->probed_modes, head) {
+		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
+			mode_dev->panel_fixed_mode =
+			    drm_mode_duplicate(dev, scan);
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+
+	/* Failed to get EDID, what about VBT? do we need this?*/
+	if (mode_dev->vbt_mode)
+		mode_dev->panel_fixed_mode =
+		    drm_mode_duplicate(dev, mode_dev->vbt_mode);
+
+	if (!mode_dev->panel_fixed_mode)
+		if (dev_priv->lfp_lvds_vbt_mode)
+			mode_dev->panel_fixed_mode =
+				drm_mode_duplicate(dev,
+					dev_priv->lfp_lvds_vbt_mode);
+
+	/*
+	 * If we didn't get EDID, try checking if the panel is already turned
+	 * on.	If so, assume that whatever is currently programmed is the
+	 * correct mode.
+	 */
+	lvds = REG_READ(LVDS);
+	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
+	crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
+
+	if (crtc && (lvds & LVDS_PORT_EN)) {
+		mode_dev->panel_fixed_mode =
+		    psb_intel_crtc_mode_get(dev, crtc);
+		if (mode_dev->panel_fixed_mode) {
+			mode_dev->panel_fixed_mode->type |=
+			    DRM_MODE_TYPE_PREFERRED;
+			goto out;	/* FIXME: check for quirks */
+		}
+	}
+
+	/* If we still don't have a mode after all that, give up. */
+	if (!mode_dev->panel_fixed_mode) {
+		DRM_DEBUG
+			("Found no modes on the lvds, ignoring the LVDS\n");
+		goto failed_find;
+	}
+
+	/*
+	 * Blacklist machines with BIOSes that list an LVDS panel without
+	 * actually having one.
+	 */
+out:
+	drm_sysfs_connector_add(connector);
+
+	PSB_DEBUG_ENTRY("hdisplay = %d\n",
+		 mode_dev->panel_fixed_mode->hdisplay);
+	PSB_DEBUG_ENTRY(" vdisplay = %d\n",
+		 mode_dev->panel_fixed_mode->vdisplay);
+	PSB_DEBUG_ENTRY(" hsync_start = %d\n",
+		 mode_dev->panel_fixed_mode->hsync_start);
+	PSB_DEBUG_ENTRY(" hsync_end = %d\n",
+		 mode_dev->panel_fixed_mode->hsync_end);
+	PSB_DEBUG_ENTRY(" htotal = %d\n",
+		 mode_dev->panel_fixed_mode->htotal);
+	PSB_DEBUG_ENTRY(" vsync_start = %d\n",
+		 mode_dev->panel_fixed_mode->vsync_start);
+	PSB_DEBUG_ENTRY(" vsync_end = %d\n",
+		 mode_dev->panel_fixed_mode->vsync_end);
+	PSB_DEBUG_ENTRY(" vtotal = %d\n",
+		 mode_dev->panel_fixed_mode->vtotal);
+	PSB_DEBUG_ENTRY(" clock = %d\n",
+		 mode_dev->panel_fixed_mode->clock);
+
+	return;
+
+failed_find:
+	if (psb_intel_output->ddc_bus)
+		psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
+failed_ddc:
+	if (psb_intel_output->i2c_bus)
+		psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
+failed_blc_i2c:
+	drm_encoder_cleanup(encoder);
+	drm_connector_cleanup(connector);
+	kfree(connector);
+}
+
diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c
new file mode 100644
index 0000000..bde1aff
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_modes.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authers: Jesse Barnes <jesse.barnes@intel.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <drm/drmP.h>
+#include "psb_intel_drv.h"
+
+/**
+ * psb_intel_ddc_probe
+ *
+ */
+bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output)
+{
+	u8 out_buf[] = { 0x0, 0x0 };
+	u8 buf[2];
+	int ret;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = 0x50,
+		 .flags = 0,
+		 .len = 1,
+		 .buf = out_buf,
+		 },
+		{
+		 .addr = 0x50,
+		 .flags = I2C_M_RD,
+		 .len = 1,
+		 .buf = buf,
+		 }
+	};
+
+	ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2);
+	if (ret == 2)
+		return true;
+
+	return false;
+}
+
+/**
+ * psb_intel_ddc_get_modes - get modelist from monitor
+ * @connector: DRM connector device to use
+ *
+ * Fetch the EDID information from @connector using the DDC bus.
+ */
+int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output)
+{
+	struct edid *edid;
+	int ret = 0;
+
+	edid =
+	    drm_get_edid(&psb_intel_output->base,
+			 &psb_intel_output->ddc_bus->adapter);
+	if (edid) {
+		drm_mode_connector_update_edid_property(&psb_intel_output->
+							base, edid);
+		ret = drm_add_edid_modes(&psb_intel_output->base, edid);
+		kfree(edid);
+	}
+	return ret;
+}
diff --git a/drivers/staging/gma500/psb_intel_opregion.c b/drivers/staging/gma500/psb_intel_opregion.c
new file mode 100644
index 0000000..65e3e9b
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_opregion.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "psb_drv.h"
+
+struct opregion_header {
+	u8 signature[16];
+	u32 size;
+	u32 opregion_ver;
+	u8 bios_ver[32];
+	u8 vbios_ver[16];
+	u8 driver_ver[16];
+	u32 mboxes;
+	u8 reserved[164];
+} __attribute__((packed));
+
+struct opregion_apci {
+	/*FIXME: add it later*/
+} __attribute__((packed));
+
+struct opregion_swsci {
+	/*FIXME: add it later*/
+} __attribute__((packed));
+
+struct opregion_acpi {
+	/*FIXME: add it later*/
+} __attribute__((packed));
+
+int psb_intel_opregion_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	/*struct psb_intel_opregion * opregion = &dev_priv->opregion;*/
+	u32 opregion_phy;
+	void *base;
+	u32 *lid_state;
+
+	dev_priv->lid_state = NULL;
+
+	pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
+	if (opregion_phy == 0) {
+		DRM_DEBUG("Opregion not supported, won't support lid-switch\n");
+		return -ENOTSUPP;
+	}
+	DRM_DEBUG("OpRegion detected at 0x%8x\n", opregion_phy);
+
+	base = ioremap(opregion_phy, 8*1024);
+	if (!base)
+		return -ENOMEM;
+
+	lid_state = base + 0x01ac;
+
+	DRM_DEBUG("Lid switch state 0x%08x\n", *lid_state);
+
+	dev_priv->lid_state = lid_state;
+	dev_priv->lid_last_state = *lid_state;
+	return 0;
+}
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h
new file mode 100644
index 0000000..1c28314
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_reg.h
@@ -0,0 +1,1137 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __PSB_INTEL_REG_H__
+#define __PSB_INTEL_REG_H__
+
+#define BLC_PWM_CTL		0x61254
+#define BLC_PWM_CTL2		0x61250
+#define BLC_PWM_CTL_C		0x62254
+#define BLC_PWM_CTL2_C		0x62250
+#define BACKLIGHT_MODULATION_FREQ_SHIFT		(17)
+/*
+ * This is the most significant 15 bits of the number of backlight cycles in a
+ * complete cycle of the modulated backlight control.
+ *
+ * The actual value is this field multiplied by two.
+ */
+#define BACKLIGHT_MODULATION_FREQ_MASK		(0x7fff << 17)
+#define BLM_LEGACY_MODE				(1 << 16)
+/*
+ * This is the number of cycles out of the backlight modulation cycle for which
+ * the backlight is on.
+ *
+ * This field must be no greater than the number of cycles in the complete
+ * backlight modulation cycle.
+ */
+#define BACKLIGHT_DUTY_CYCLE_SHIFT		(0)
+#define BACKLIGHT_DUTY_CYCLE_MASK		(0xffff)
+
+#define I915_GCFGC			0xf0
+#define I915_LOW_FREQUENCY_ENABLE		(1 << 7)
+#define I915_DISPLAY_CLOCK_190_200_MHZ		(0 << 4)
+#define I915_DISPLAY_CLOCK_333_MHZ		(4 << 4)
+#define I915_DISPLAY_CLOCK_MASK			(7 << 4)
+
+#define I855_HPLLCC			0xc0
+#define I855_CLOCK_CONTROL_MASK			(3 << 0)
+#define I855_CLOCK_133_200			(0 << 0)
+#define I855_CLOCK_100_200			(1 << 0)
+#define I855_CLOCK_100_133			(2 << 0)
+#define I855_CLOCK_166_250			(3 << 0)
+
+/* I830 CRTC registers */
+#define HTOTAL_A	0x60000
+#define HBLANK_A	0x60004
+#define HSYNC_A 	0x60008
+#define VTOTAL_A	0x6000c
+#define VBLANK_A	0x60010
+#define VSYNC_A 	0x60014
+#define PIPEASRC	0x6001c
+#define BCLRPAT_A	0x60020
+#define VSYNCSHIFT_A	0x60028
+
+#define HTOTAL_B	0x61000
+#define HBLANK_B	0x61004
+#define HSYNC_B 	0x61008
+#define VTOTAL_B	0x6100c
+#define VBLANK_B	0x61010
+#define VSYNC_B 	0x61014
+#define PIPEBSRC	0x6101c
+#define BCLRPAT_B	0x61020
+#define VSYNCSHIFT_B	0x61028
+
+#define HTOTAL_C	0x62000
+#define HBLANK_C	0x62004
+#define HSYNC_C 	0x62008
+#define VTOTAL_C	0x6200c
+#define VBLANK_C	0x62010
+#define VSYNC_C 	0x62014
+#define PIPECSRC	0x6201c
+#define BCLRPAT_C	0x62020
+#define VSYNCSHIFT_C	0x62028
+
+#define PP_STATUS	0x61200
+# define PP_ON					(1 << 31)
+/*
+ * Indicates that all dependencies of the panel are on:
+ *
+ * - PLL enabled
+ * - pipe enabled
+ * - LVDS/DVOB/DVOC on
+ */
+# define PP_READY				(1 << 30)
+# define PP_SEQUENCE_NONE			(0 << 28)
+# define PP_SEQUENCE_ON				(1 << 28)
+# define PP_SEQUENCE_OFF			(2 << 28)
+# define PP_SEQUENCE_MASK			0x30000000
+#define PP_CONTROL	0x61204
+# define POWER_TARGET_ON			(1 << 0)
+
+#define LVDSPP_ON       0x61208
+#define LVDSPP_OFF      0x6120c
+#define PP_CYCLE        0x61210
+
+#define PFIT_CONTROL	0x61230
+# define PFIT_ENABLE				(1 << 31)
+# define PFIT_PIPE_MASK				(3 << 29)
+# define PFIT_PIPE_SHIFT			29
+# define PFIT_SCALING_MODE_PILLARBOX            (1 << 27)
+# define PFIT_SCALING_MODE_LETTERBOX            (3 << 26)
+# define VERT_INTERP_DISABLE			(0 << 10)
+# define VERT_INTERP_BILINEAR			(1 << 10)
+# define VERT_INTERP_MASK			(3 << 10)
+# define VERT_AUTO_SCALE			(1 << 9)
+# define HORIZ_INTERP_DISABLE			(0 << 6)
+# define HORIZ_INTERP_BILINEAR			(1 << 6)
+# define HORIZ_INTERP_MASK			(3 << 6)
+# define HORIZ_AUTO_SCALE			(1 << 5)
+# define PANEL_8TO6_DITHER_ENABLE		(1 << 3)
+
+#define PFIT_PGM_RATIOS	0x61234
+# define PFIT_VERT_SCALE_MASK			0xfff00000
+# define PFIT_HORIZ_SCALE_MASK			0x0000fff0
+
+#define PFIT_AUTO_RATIOS	0x61238
+
+
+#define DPLL_A		0x06014
+#define DPLL_B		0x06018
+# define DPLL_VCO_ENABLE			(1 << 31)
+# define DPLL_DVO_HIGH_SPEED			(1 << 30)
+# define DPLL_SYNCLOCK_ENABLE			(1 << 29)
+# define DPLL_VGA_MODE_DIS			(1 << 28)
+# define DPLLB_MODE_DAC_SERIAL			(1 << 26)	/* i915 */
+# define DPLLB_MODE_LVDS			(2 << 26)	/* i915 */
+# define DPLL_MODE_MASK				(3 << 26)
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10	(0 << 24)	/* i915 */
+# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5		(1 << 24)	/* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_14		(0 << 24)	/* i915 */
+# define DPLLB_LVDS_P2_CLOCK_DIV_7		(1 << 24)	/* i915 */
+# define DPLL_P2_CLOCK_DIV_MASK			0x03000000	/* i915 */
+# define DPLL_FPA01_P1_POST_DIV_MASK		0x00ff0000	/* i915 */
+/*
+ *  The i830 generation, in DAC/serial mode, defines p1 as two plus this
+ * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set.
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000
+/*
+ * The i830 generation, in LVDS mode, defines P1 as the bit number set within
+ * this field (only one bit may be set).
+ */
+# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS	0x003f0000
+# define DPLL_FPA01_P1_POST_DIV_SHIFT		16
+# define PLL_P2_DIVIDE_BY_4		(1 << 23)	/* i830, required
+							 * in DVO non-gang */
+# define PLL_P1_DIVIDE_BY_TWO			(1 << 21)	/* i830 */
+# define PLL_REF_INPUT_DREFCLK			(0 << 13)
+# define PLL_REF_INPUT_TVCLKINA			(1 << 13)	/* i830 */
+# define PLL_REF_INPUT_TVCLKINBC		(2 << 13)	/* SDVO
+								 * TVCLKIN */
+# define PLLB_REF_INPUT_SPREADSPECTRUMIN	(3 << 13)
+# define PLL_REF_INPUT_MASK			(3 << 13)
+# define PLL_LOAD_PULSE_PHASE_SHIFT		9
+/*
+ * Parallel to Serial Load Pulse phase selection.
+ * Selects the phase for the 10X DPLL clock for the PCIe
+ * digital display port. The range is 4 to 13; 10 or more
+ * is just a flip delay. The default is 6
+ */
+# define PLL_LOAD_PULSE_PHASE_MASK	(0xf << PLL_LOAD_PULSE_PHASE_SHIFT)
+# define DISPLAY_RATE_SELECT_FPA1	(1 << 8)
+
+/*
+ * SDVO multiplier for 945G/GM. Not used on 965.
+ *
+ * DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+# define SDVO_MULTIPLIER_MASK			0x000000ff
+# define SDVO_MULTIPLIER_SHIFT_HIRES		4
+# define SDVO_MULTIPLIER_SHIFT_VGA		0
+
+/*
+ * PLL_MD
+ */
+/* Pipe A SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_A_MD		0x0601c
+/* Pipe B SDVO/UDI clock multiplier/divider register for G965. */
+#define DPLL_B_MD		0x06020
+/*
+ * UDI pixel divider, controlling how many pixels are stuffed into a packet.
+ *
+ * Value is pixels minus 1.  Must be set to 1 pixel for SDVO.
+ */
+# define DPLL_MD_UDI_DIVIDER_MASK		0x3f000000
+# define DPLL_MD_UDI_DIVIDER_SHIFT		24
+/* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
+# define DPLL_MD_VGA_UDI_DIVIDER_MASK		0x003f0000
+# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT		16
+/*
+ * SDVO/UDI pixel multiplier.
+ *
+ * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
+ * clock rate is 10 times the DPLL clock.  At low resolution/refresh rate
+ * modes, the bus rate would be below the limits, so SDVO allows for stuffing
+ * dummy bytes in the datastream at an increased clock rate, with both sides of
+ * the link knowing how many bytes are fill.
+ *
+ * So, for a mode with a dotclock of 65Mhz, we would want to double the clock
+ * rate to 130Mhz to get a bus rate of 1.30Ghz.  The DPLL clock rate would be
+ * set to 130Mhz, and the SDVO multiplier set to 2x in this register and
+ * through an SDVO command.
+ *
+ * This register field has values of multiplication factor minus 1, with
+ * a maximum multiplier of 5 for SDVO.
+ */
+# define DPLL_MD_UDI_MULTIPLIER_MASK		0x00003f00
+# define DPLL_MD_UDI_MULTIPLIER_SHIFT		8
+/*
+ * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK.
+ * This best be set to the default value (3) or the CRT won't work. No,
+ * I don't entirely understand what this does...
+ */
+# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
+# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
+
+#define DPLL_TEST		0x606c
+# define DPLLB_TEST_SDVO_DIV_1			(0 << 22)
+# define DPLLB_TEST_SDVO_DIV_2			(1 << 22)
+# define DPLLB_TEST_SDVO_DIV_4			(2 << 22)
+# define DPLLB_TEST_SDVO_DIV_MASK		(3 << 22)
+# define DPLLB_TEST_N_BYPASS			(1 << 19)
+# define DPLLB_TEST_M_BYPASS			(1 << 18)
+# define DPLLB_INPUT_BUFFER_ENABLE		(1 << 16)
+# define DPLLA_TEST_N_BYPASS			(1 << 3)
+# define DPLLA_TEST_M_BYPASS			(1 << 2)
+# define DPLLA_INPUT_BUFFER_ENABLE		(1 << 0)
+
+#define ADPA			0x61100
+#define ADPA_DAC_ENABLE 	(1<<31)
+#define ADPA_DAC_DISABLE	0
+#define ADPA_PIPE_SELECT_MASK	(1<<30)
+#define ADPA_PIPE_A_SELECT	0
+#define ADPA_PIPE_B_SELECT	(1<<30)
+#define ADPA_USE_VGA_HVPOLARITY (1<<15)
+#define ADPA_SETS_HVPOLARITY	0
+#define ADPA_VSYNC_CNTL_DISABLE (1<<11)
+#define ADPA_VSYNC_CNTL_ENABLE	0
+#define ADPA_HSYNC_CNTL_DISABLE (1<<10)
+#define ADPA_HSYNC_CNTL_ENABLE	0
+#define ADPA_VSYNC_ACTIVE_HIGH	(1<<4)
+#define ADPA_VSYNC_ACTIVE_LOW	0
+#define ADPA_HSYNC_ACTIVE_HIGH	(1<<3)
+#define ADPA_HSYNC_ACTIVE_LOW	0
+
+#define FPA0		0x06040
+#define FPA1		0x06044
+#define FPB0		0x06048
+#define FPB1		0x0604c
+# define FP_N_DIV_MASK				0x003f0000
+# define FP_N_DIV_SHIFT				16
+# define FP_M1_DIV_MASK				0x00003f00
+# define FP_M1_DIV_SHIFT			8
+# define FP_M2_DIV_MASK				0x0000003f
+# define FP_M2_DIV_SHIFT			0
+
+
+#define PORT_HOTPLUG_EN		0x61110
+# define SDVOB_HOTPLUG_INT_EN			(1 << 26)
+# define SDVOC_HOTPLUG_INT_EN			(1 << 25)
+# define TV_HOTPLUG_INT_EN			(1 << 18)
+# define CRT_HOTPLUG_INT_EN			(1 << 9)
+# define CRT_HOTPLUG_FORCE_DETECT		(1 << 3)
+
+#define PORT_HOTPLUG_STAT	0x61114
+# define CRT_HOTPLUG_INT_STATUS			(1 << 11)
+# define TV_HOTPLUG_INT_STATUS			(1 << 10)
+# define CRT_HOTPLUG_MONITOR_MASK		(3 << 8)
+# define CRT_HOTPLUG_MONITOR_COLOR		(3 << 8)
+# define CRT_HOTPLUG_MONITOR_MONO		(2 << 8)
+# define CRT_HOTPLUG_MONITOR_NONE		(0 << 8)
+# define SDVOC_HOTPLUG_INT_STATUS		(1 << 7)
+# define SDVOB_HOTPLUG_INT_STATUS		(1 << 6)
+
+#define 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)
+/**
+ * 915G/GM SDVO pixel multiplier.
+ *
+ * Programmed value is multiplier - 1, up to 5x.
+ *
+ * DPLL_MD_UDI_MULTIPLIER_MASK
+ */
+#define SDVO_PORT_MULTIPLY_MASK			(7 << 23)
+#define SDVO_PORT_MULTIPLY_SHIFT		23
+#define SDVO_PHASE_SELECT_MASK			(15 << 19)
+#define SDVO_PHASE_SELECT_DEFAULT		(6 << 19)
+#define SDVO_CLOCK_OUTPUT_INVERT		(1 << 18)
+#define SDVOC_GANG_MODE				(1 << 16)
+#define SDVO_BORDER_ENABLE			(1 << 7)
+#define SDVOB_PCIE_CONCURRENCY			(1 << 3)
+#define SDVO_DETECTED				(1 << 2)
+/* Bits to be preserved when writing */
+#define SDVOB_PRESERVE_MASK		((1 << 17) | (1 << 16) | (1 << 14))
+#define SDVOC_PRESERVE_MASK			(1 << 17)
+
+/*
+ * This register controls the LVDS output enable, pipe selection, and data
+ * format selection.
+ *
+ * All of the clock/data pairs are force powered down by power sequencing.
+ */
+#define LVDS			0x61180
+/*
+ * Enables the LVDS port.  This bit must be set before DPLLs are enabled, as
+ * the DPLL semantics change when the LVDS is assigned to that pipe.
+ */
+# define LVDS_PORT_EN			(1 << 31)
+/* Selects pipe B for LVDS data.  Must be set on pre-965. */
+# define LVDS_PIPEB_SELECT		(1 << 30)
+
+/* Turns on border drawing to allow centered display. */
+# define LVDS_BORDER_EN                 (1 << 15)
+
+/*
+ * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per
+ * pixel.
+ */
+# define LVDS_A0A2_CLKA_POWER_MASK	(3 << 8)
+# define LVDS_A0A2_CLKA_POWER_DOWN	(0 << 8)
+# define LVDS_A0A2_CLKA_POWER_UP	(3 << 8)
+/*
+ * Controls the A3 data pair, which contains the additional LSBs for 24 bit
+ * mode.  Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be
+ * on.
+ */
+# define LVDS_A3_POWER_MASK		(3 << 6)
+# define LVDS_A3_POWER_DOWN		(0 << 6)
+# define LVDS_A3_POWER_UP		(3 << 6)
+/*
+ * Controls the CLKB pair.  This should only be set when LVDS_B0B3_POWER_UP
+ * is set.
+ */
+# define LVDS_CLKB_POWER_MASK		(3 << 4)
+# define LVDS_CLKB_POWER_DOWN		(0 << 4)
+# define LVDS_CLKB_POWER_UP		(3 << 4)
+/*
+ * Controls the B0-B3 data pairs.  This must be set to match the DPLL p2
+ * setting for whether we are in dual-channel mode.  The B3 pair will
+ * additionally only be powered up when LVDS_A3_POWER_UP is set.
+ */
+# define LVDS_B0B3_POWER_MASK		(3 << 2)
+# define LVDS_B0B3_POWER_DOWN		(0 << 2)
+# define LVDS_B0B3_POWER_UP		(3 << 2)
+
+#define PIPEACONF 0x70008
+#define PIPEACONF_ENABLE	(1<<31)
+#define PIPEACONF_DISABLE	0
+#define PIPEACONF_DOUBLE_WIDE	(1<<30)
+#define PIPECONF_ACTIVE		(1<<30)
+#define I965_PIPECONF_ACTIVE	(1<<30)
+#define PIPECONF_DSIPLL_LOCK	(1<<29)
+#define PIPEACONF_SINGLE_WIDE	0
+#define PIPEACONF_PIPE_UNLOCKED 0
+#define PIPEACONF_DSR		(1<<26)
+#define PIPEACONF_PIPE_LOCKED	(1<<25)
+#define PIPEACONF_PALETTE	0
+#define PIPECONF_FORCE_BORDER	(1<<25)
+#define PIPEACONF_GAMMA 	(1<<24)
+#define PIPECONF_PROGRESSIVE	(0 << 21)
+#define PIPECONF_INTERLACE_W_FIELD_INDICATION	(6 << 21)
+#define PIPECONF_INTERLACE_FIELD_0_ONLY		(7 << 21)
+#define PIPECONF_PLANE_OFF 	(1<<19)
+#define PIPECONF_CURSOR_OFF 	(1<<18)
+
+
+#define PIPEBCONF 0x71008
+#define PIPEBCONF_ENABLE	(1<<31)
+#define PIPEBCONF_DISABLE	0
+#define PIPEBCONF_DOUBLE_WIDE	(1<<30)
+#define PIPEBCONF_DISABLE	0
+#define PIPEBCONF_GAMMA 	(1<<24)
+#define PIPEBCONF_PALETTE	0
+
+#define PIPECCONF 0x72008
+
+#define PIPEBGCMAXRED		0x71010
+#define PIPEBGCMAXGREEN		0x71014
+#define PIPEBGCMAXBLUE		0x71018
+
+#define PIPEASTAT               0x70024
+#define PIPEBSTAT		0x71024
+#define PIPECSTAT		0x72024
+#define PIPE_VBLANK_INTERRUPT_STATUS         (1UL<<1)
+#define PIPE_START_VBLANK_INTERRUPT_STATUS   (1UL<<2)
+#define PIPE_VBLANK_CLEAR                    (1 << 1)
+#define PIPE_VBLANK_STATUS                   (1 << 1)
+#define PIPE_TE_STATUS		             (1UL<<6)
+#define PIPE_DPST_EVENT_STATUS		     (1UL<<7)
+#define PIPE_VSYNC_CLEAR                     (1UL<<9)
+#define PIPE_VSYNC_STATUS                    (1UL<<9)
+#define PIPE_HDMI_AUDIO_UNDERRUN_STATUS      (1UL<<10)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS   (1UL<<11)
+#define PIPE_VBLANK_INTERRUPT_ENABLE         (1UL<<17)
+#define PIPE_START_VBLANK_INTERRUPT_ENABLE   (1UL<<18)
+#define PIPE_TE_ENABLE		             (1UL<<22)
+#define PIPE_DPST_EVENT_ENABLE               (1UL<<23)
+#define PIPE_VSYNC_ENABL                     (1UL<<25)
+#define PIPE_HDMI_AUDIO_UNDERRUN             (1UL<<26)
+#define PIPE_HDMI_AUDIO_BUFFER_DONE          (1UL<<27)
+#define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | PIPE_HDMI_AUDIO_BUFFER_DONE)
+#define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16))
+#define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17))
+#define HISTOGRAM_INT_CONTROL		0x61268
+#define HISTOGRAM_BIN_DATA		0X61264
+#define HISTOGRAM_LOGIC_CONTROL		0x61260
+#define PWM_CONTROL_LOGIC		0x61250
+#define PIPE_HOTPLUG_INTERRUPT_STATUS	(1UL<<10)
+#define HISTOGRAM_INTERRUPT_ENABLE	(1UL<<31)
+#define HISTOGRAM_LOGIC_ENABLE		(1UL<<31)
+#define PWM_LOGIC_ENABLE		(1UL<<31)
+#define PWM_PHASEIN_ENABLE		(1UL<<25)
+#define PWM_PHASEIN_INT_ENABLE		(1UL<<24)
+#define PWM_PHASEIN_VB_COUNT		0x00001f00
+#define PWM_PHASEIN_INC			0x0000001f
+#define HISTOGRAM_INT_CTRL_CLEAR	(1UL<<30)
+#define DPST_YUV_LUMA_MODE		0
+
+struct dpst_ie_histogram_control {
+	union {
+		uint32_t data;
+		struct {
+			uint32_t bin_reg_index:7;
+			uint32_t reserved:4;
+			uint32_t bin_reg_func_select:1;
+			uint32_t sync_to_phase_in:1;
+			uint32_t alt_enhancement_mode:2;
+			uint32_t reserved1:1;
+			uint32_t sync_to_phase_in_count:8;
+			uint32_t histogram_mode_select:1;
+			uint32_t reserved2:4;
+			uint32_t ie_pipe_assignment:1;
+			uint32_t ie_mode_table_enabled:1;
+			uint32_t ie_histogram_enable:1;
+		};
+	};
+};
+
+struct dpst_guardband {
+	union {
+		uint32_t data;
+		struct {
+			uint32_t guardband:22;
+			uint32_t guardband_interrupt_delay:8;
+			uint32_t interrupt_status:1;
+			uint32_t interrupt_enable:1;
+		};
+	};
+};
+
+#define PIPEAFRAMEHIGH		0x70040
+#define PIPEAFRAMEPIXEL		0x70044
+#define PIPEBFRAMEHIGH		0x71040
+#define PIPEBFRAMEPIXEL		0x71044
+#define PIPECFRAMEHIGH		0x72040
+#define PIPECFRAMEPIXEL		0x72044
+#define PIPE_FRAME_HIGH_MASK    0x0000ffff
+#define PIPE_FRAME_HIGH_SHIFT   0
+#define PIPE_FRAME_LOW_MASK     0xff000000
+#define PIPE_FRAME_LOW_SHIFT    24
+#define PIPE_PIXEL_MASK         0x00ffffff
+#define PIPE_PIXEL_SHIFT        0
+
+#define DSPARB			0x70030
+#define DSPFW1			0x70034
+#define DSPFW2			0x70038
+#define DSPFW3			0x7003c
+#define DSPFW4			0x70050
+#define DSPFW5			0x70054
+#define DSPFW6			0x70058
+#define DSPCHICKENBIT		0x70400
+#define DSPACNTR		0x70180
+#define DSPBCNTR		0x71180
+#define DSPCCNTR		0x72180
+#define DISPLAY_PLANE_ENABLE 			(1<<31)
+#define DISPLAY_PLANE_DISABLE			0
+#define DISPPLANE_GAMMA_ENABLE			(1<<30)
+#define DISPPLANE_GAMMA_DISABLE			0
+#define DISPPLANE_PIXFORMAT_MASK		(0xf<<26)
+#define DISPPLANE_8BPP				(0x2<<26)
+#define DISPPLANE_15_16BPP			(0x4<<26)
+#define DISPPLANE_16BPP				(0x5<<26)
+#define DISPPLANE_32BPP_NO_ALPHA 		(0x6<<26)
+#define DISPPLANE_32BPP				(0x7<<26)
+#define DISPPLANE_STEREO_ENABLE			(1<<25)
+#define DISPPLANE_STEREO_DISABLE		0
+#define DISPPLANE_SEL_PIPE_MASK			(1<<24)
+#define DISPPLANE_SEL_PIPE_POS			24
+#define DISPPLANE_SEL_PIPE_A			0
+#define DISPPLANE_SEL_PIPE_B			(1<<24)
+#define DISPPLANE_SRC_KEY_ENABLE		(1<<22)
+#define DISPPLANE_SRC_KEY_DISABLE		0
+#define DISPPLANE_LINE_DOUBLE			(1<<20)
+#define DISPPLANE_NO_LINE_DOUBLE		0
+#define DISPPLANE_STEREO_POLARITY_FIRST		0
+#define DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
+/* plane B only */
+#define DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
+#define DISPPLANE_ALPHA_TRANS_DISABLE		0
+#define DISPPLANE_SPRITE_ABOVE_DISPLAYA		0
+#define DISPPLANE_SPRITE_ABOVE_OVERLAY		(1)
+#define DISPPLANE_BOTTOM			(4)
+
+#define DSPABASE		0x70184
+#define DSPALINOFF		0x70184
+#define DSPASTRIDE		0x70188
+
+#define DSPBBASE		0x71184
+#define DSPBLINOFF		0X71184
+#define DSPBADDR		DSPBBASE
+#define DSPBSTRIDE		0x71188
+
+#define DSPCBASE		0x72184
+#define DSPCLINOFF		0x72184
+#define DSPCSTRIDE		0x72188
+
+#define DSPAKEYVAL		0x70194
+#define DSPAKEYMASK		0x70198
+
+#define DSPAPOS			0x7018C	/* reserved */
+#define DSPASIZE		0x70190
+#define DSPBPOS			0x7118C
+#define DSPBSIZE		0x71190
+#define DSPCPOS			0x7218C
+#define DSPCSIZE		0x72190
+
+#define DSPASURF		0x7019C
+#define DSPATILEOFF		0x701A4
+
+#define DSPBSURF		0x7119C
+#define DSPBTILEOFF		0x711A4
+
+#define DSPCSURF		0x7219C
+#define DSPCTILEOFF		0x721A4
+#define DSPCKEYMAXVAL 		0x721A0
+#define DSPCKEYMINVAL 		0x72194
+#define DSPCKEYMSK 		0x72198
+
+#define VGACNTRL		0x71400
+# define VGA_DISP_DISABLE			(1 << 31)
+# define VGA_2X_MODE				(1 << 30)
+# define VGA_PIPE_B_SELECT			(1 << 29)
+
+/*
+ * Overlay registers
+ */
+#define OV_C_OFFSET		0x08000
+#define OV_OVADD		0x30000
+#define OV_DOVASTA              0x30008
+# define OV_PIPE_SELECT				((1 << 6)|(1 << 7))
+# define OV_PIPE_SELECT_POS			6
+# define OV_PIPE_A				0
+# define OV_PIPE_C				1
+#define OV_OGAMC5		0x30010
+#define OV_OGAMC4		0x30014
+#define OV_OGAMC3		0x30018
+#define OV_OGAMC2		0x3001C
+#define OV_OGAMC1		0x30020
+#define OV_OGAMC0		0x30024
+#define OVC_OVADD		0x38000
+#define OVC_DOVCSTA             0x38008
+#define OVC_OGAMC5		0x38010
+#define OVC_OGAMC4		0x38014
+#define OVC_OGAMC3		0x38018
+#define OVC_OGAMC2		0x3801C
+#define OVC_OGAMC1		0x38020
+#define OVC_OGAMC0		0x38024
+
+/*
+ * Some BIOS scratch area registers.  The 845 (and 830?) store the amount
+ * of video memory available to the BIOS in SWF1.
+ */
+#define SWF0			0x71410
+#define SWF1			0x71414
+#define SWF2			0x71418
+#define SWF3			0x7141c
+#define SWF4			0x71420
+#define SWF5			0x71424
+#define SWF6			0x71428
+
+/*
+ * 855 scratch registers.
+ */
+#define SWF00			0x70410
+#define SWF01			0x70414
+#define SWF02			0x70418
+#define SWF03			0x7041c
+#define SWF04			0x70420
+#define SWF05			0x70424
+#define SWF06			0x70428
+
+#define SWF10			SWF0
+#define SWF11			SWF1
+#define SWF12			SWF2
+#define SWF13			SWF3
+#define SWF14			SWF4
+#define SWF15			SWF5
+#define SWF16			SWF6
+
+#define SWF30			0x72414
+#define SWF31			0x72418
+#define SWF32			0x7241c
+
+
+/*
+ * Palette registers
+ */
+#define PALETTE_A		0x0a000
+#define PALETTE_B		0x0a800
+#define PALETTE_C		0x0ac00
+
+/* Cursor A & B regs */
+#define CURACNTR		0x70080
+#define   CURSOR_MODE_DISABLE   0x00
+#define   CURSOR_MODE_64_32B_AX 0x07
+#define   CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX)
+#define   MCURSOR_GAMMA_ENABLE  (1 << 26)
+#define CURABASE		0x70084
+#define CURAPOS			0x70088
+#define   CURSOR_POS_MASK       0x007FF
+#define   CURSOR_POS_SIGN       0x8000
+#define   CURSOR_X_SHIFT        0
+#define   CURSOR_Y_SHIFT        16
+#define CURBCNTR		0x700c0
+#define CURBBASE		0x700c4
+#define CURBPOS			0x700c8
+#define CURCCNTR		0x700e0
+#define CURCBASE		0x700e4
+#define CURCPOS			0x700e8
+
+/*
+ * Interrupt Registers
+ */
+#define IER 0x020a0
+#define IIR 0x020a4
+#define IMR 0x020a8
+#define ISR 0x020ac
+
+/*
+ * MOORESTOWN delta registers
+ */
+#define MRST_DPLL_A		0x0f014
+#define MDFLD_DPLL_B		0x0f018
+#define MDFLD_INPUT_REF_SEL	(1 << 14)
+#define MDFLD_VCO_SEL		(1 << 16)
+#define DPLLA_MODE_LVDS		(2 << 26)	/* mrst */
+#define MDFLD_PLL_LATCHEN	(1 << 28)
+#define MDFLD_PWR_GATE_EN	(1 << 30)
+#define MDFLD_P1_MASK		(0x1FF << 17)
+#define MRST_FPA0		0x0f040
+#define MRST_FPA1		0x0f044
+#define MDFLD_DPLL_DIV0		0x0f048
+#define MDFLD_DPLL_DIV1		0x0f04c
+#define MRST_PERF_MODE		0x020f4
+
+/*
+ * MEDFIELD HDMI registers
+ */
+#define HDMIPHYMISCCTL   	0x61134
+# define HDMI_PHY_POWER_DOWN	0x7f
+#define HDMIB_CONTROL   	0x61140
+# define HDMIB_PORT_EN			(1 << 31)
+# define HDMIB_PIPE_B_SELECT		(1 << 30)
+# define HDMIB_NULL_PACKET		(1 << 9)
+#define HDMIB_HDCP_PORT (1 << 5)
+
+/* #define LVDS			0x61180 */
+# define MRST_PANEL_8TO6_DITHER_ENABLE		(1 << 25)
+# define MRST_PANEL_24_DOT_1_FORMAT		(1 << 24)
+# define LVDS_A3_POWER_UP_0_OUTPUT		(1 << 6)
+
+#define MIPI			0x61190
+#define MIPI_C			0x62190
+# define MIPI_PORT_EN			(1 << 31)
+/* Turns on border drawing to allow centered display. */
+# define SEL_FLOPPED_HSTX		(1 << 23)
+# define PASS_FROM_SPHY_TO_AFE 		(1 << 16)
+# define MIPI_BORDER_EN			(1 << 15)
+# define MIPIA_3LANE_MIPIC_1LANE	0x1
+# define MIPIA_2LANE_MIPIC_2LANE	0x2
+# define TE_TRIGGER_DSI_PROTOCOL	(1 << 2)
+# define TE_TRIGGER_GPIO_PIN		(1 << 3)
+#define MIPI_TE_COUNT			0x61194
+
+/* #define PP_CONTROL	0x61204 */
+# define POWER_DOWN_ON_RESET		(1 << 1)
+
+/* #define PFIT_CONTROL	0x61230 */
+# define PFIT_PIPE_SELECT				(3 << 29)
+# define PFIT_PIPE_SELECT_SHIFT			(29)
+
+/* #define BLC_PWM_CTL		0x61254 */
+#define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT		(16)
+#define MRST_BACKLIGHT_MODULATION_FREQ_MASK		(0xffff << 16)
+
+/* #define PIPEACONF 0x70008 */
+#define PIPEACONF_PIPE_STATE	(1<<30)
+/* #define DSPACNTR		0x70180 */
+
+#define MRST_DSPABASE		0x7019c
+#define MRST_DSPBBASE		0x7119c
+#define MDFLD_DSPCBASE		0x7219c
+
+/*
+ * Moorestown registers.
+ */
+
+/*
+ *	MIPI IP registers
+ */
+#define MIPIC_REG_OFFSET             0x800
+#define DEVICE_READY_REG             0xb000
+#define LP_OUTPUT_HOLD               (1 << 16)
+#define EXIT_ULPS_DEV_READY          0x3
+#define LP_OUTPUT_HOLD_RELEASE       0x810000
+# define ENTERING_ULPS		(2 << 1)
+# define EXITING_ULPS		(1 << 1)
+# define ULPS_MASK		(3 << 1)
+# define BUS_POSSESSION		(1 << 3)
+#define INTR_STAT_REG                0xb004
+#define RX_SOT_ERROR (1 << 0)
+#define RX_SOT_SYNC_ERROR (1 << 1)
+#define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3)
+#define RX_LP_TX_SYNC_ERROR (1 << 4)
+#define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5)
+#define RX_FALSE_CONTROL_ERROR (1 << 6)
+#define RX_ECC_SINGLE_BIT_ERROR (1 << 7)
+#define RX_ECC_MULTI_BIT_ERROR (1 << 8)
+#define RX_CHECKSUM_ERROR (1 << 9)
+#define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10)
+#define RX_DSI_VC_ID_INVALID (1 << 11)
+#define TX_FALSE_CONTROL_ERROR (1 << 12)
+#define TX_ECC_SINGLE_BIT_ERROR (1 << 13)
+#define TX_ECC_MULTI_BIT_ERROR (1 << 14)
+#define TX_CHECKSUM_ERROR (1 << 15)
+#define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16)
+#define TX_DSI_VC_ID_INVALID (1 << 17)
+#define HIGH_CONTENTION (1 << 18)
+#define LOW_CONTENTION (1 << 19)
+#define DPI_FIFO_UNDER_RUN (1 << 20)
+#define HS_TX_TIMEOUT (1 << 21)
+#define LP_RX_TIMEOUT (1 << 22)
+#define TURN_AROUND_ACK_TIMEOUT (1 << 23)
+#define ACK_WITH_NO_ERROR (1 << 24)
+#define HS_GENERIC_WR_FIFO_FULL (1 << 27)
+#define LP_GENERIC_WR_FIFO_FULL (1 << 28)
+#define SPL_PKT_SENT			(1 << 30)
+#define INTR_EN_REG                  0xb008
+#define DSI_FUNC_PRG_REG             0xb00c
+#define DPI_CHANNEL_NUMBER_POS   0x03
+#define DBI_CHANNEL_NUMBER_POS   0x05
+#define FMT_DPI_POS              0x07
+#define FMT_DBI_POS              0x0A
+#define DBI_DATA_WIDTH_POS       0x0D
+/* DPI PIXEL FORMATS */
+#define RGB_565_FMT		     0x01	/* RGB 565 FORMAT */
+#define RGB_666_FMT		     0x02	/* RGB 666 FORMAT */
+#define LRGB_666_FMT		     0x03	/* RGB LOOSELY PACKED
+						 * 666 FORMAT
+						 */
+#define RGB_888_FMT		     0x04	/* RGB 888 FORMAT */
+#define VIRTUAL_CHANNEL_NUMBER_0	0x00	/* Virtual channel 0 */
+#define VIRTUAL_CHANNEL_NUMBER_1	0x01	/* Virtual channel 1 */
+#define VIRTUAL_CHANNEL_NUMBER_2	0x02	/* Virtual channel 2 */
+#define VIRTUAL_CHANNEL_NUMBER_3	0x03	/* Virtual channel 3 */
+#define DBI_NOT_SUPPORTED		0x00	/* command mode
+						 * is not supported
+						 */
+#define DBI_DATA_WIDTH_16BIT		0x01	/* 16 bit data */
+#define DBI_DATA_WIDTH_9BIT			0x02	/* 9 bit data */
+#define DBI_DATA_WIDTH_8BIT			0x03	/* 8 bit data */
+#define DBI_DATA_WIDTH_OPT1		0x04	/* option 1 */
+#define DBI_DATA_WIDTH_OPT2		0x05	/* option 2 */
+#define HS_TX_TIMEOUT_REG            0xb010
+#define LP_RX_TIMEOUT_REG            0xb014
+#define TURN_AROUND_TIMEOUT_REG      0xb018
+#define DEVICE_RESET_REG             0xb01C
+#define DPI_RESOLUTION_REG           0xb020
+#define RES_V_POS                0x10
+#define DBI_RESOLUTION_REG           0xb024 /* Reserved for MDFLD */
+#define HORIZ_SYNC_PAD_COUNT_REG     0xb028
+#define HORIZ_BACK_PORCH_COUNT_REG   0xb02C
+#define HORIZ_FRONT_PORCH_COUNT_REG  0xb030
+#define HORIZ_ACTIVE_AREA_COUNT_REG  0xb034
+#define VERT_SYNC_PAD_COUNT_REG      0xb038
+#define VERT_BACK_PORCH_COUNT_REG    0xb03c
+#define VERT_FRONT_PORCH_COUNT_REG   0xb040
+#define HIGH_LOW_SWITCH_COUNT_REG    0xb044
+#define DPI_CONTROL_REG              0xb048
+#define DPI_SHUT_DOWN            (1 << 0)
+#define DPI_TURN_ON              (1 << 1)
+#define DPI_COLOR_MODE_ON        (1 << 2)
+#define DPI_COLOR_MODE_OFF       (1 << 3)
+#define DPI_BACK_LIGHT_ON        (1 << 4)
+#define DPI_BACK_LIGHT_OFF       (1 << 5)
+#define DPI_LP                   (1 << 6)
+#define DPI_DATA_REG                 0xb04c
+#define DPI_BACK_LIGHT_ON_DATA   0x07
+#define DPI_BACK_LIGHT_OFF_DATA  0x17
+#define INIT_COUNT_REG               0xb050
+#define MAX_RET_PAK_REG              0xb054
+#define VIDEO_FMT_REG                0xb058
+#define COMPLETE_LAST_PCKT       (1 << 2)
+#define EOT_DISABLE_REG              0xb05c
+#define ENABLE_CLOCK_STOPPING    (1 << 1)
+#define LP_BYTECLK_REG               0xb060
+#define LP_GEN_DATA_REG              0xb064
+#define HS_GEN_DATA_REG              0xb068
+#define LP_GEN_CTRL_REG              0xb06C
+#define HS_GEN_CTRL_REG              0xb070
+#define DCS_CHANNEL_NUMBER_POS   0x06
+#define MCS_COMMANDS_POS	0x8
+#define WORD_COUNTS_POS		0x8
+#define MCS_PARAMETER_POS	0x10
+#define GEN_FIFO_STAT_REG            0xb074
+#define HS_DATA_FIFO_FULL        (1 << 0)
+#define HS_DATA_FIFO_HALF_EMPTY  (1 << 1)
+#define HS_DATA_FIFO_EMPTY       (1 << 2)
+#define LP_DATA_FIFO_FULL        (1 << 8)
+#define LP_DATA_FIFO_HALF_EMPTY  (1 << 9)
+#define LP_DATA_FIFO_EMPTY       (1 << 10)
+#define HS_CTRL_FIFO_FULL        (1 << 16)
+#define HS_CTRL_FIFO_HALF_EMPTY  (1 << 17)
+#define HS_CTRL_FIFO_EMPTY       (1 << 18)
+#define LP_CTRL_FIFO_FULL        (1 << 24)
+#define LP_CTRL_FIFO_HALF_EMPTY  (1 << 25)
+#define LP_CTRL_FIFO_EMPTY       (1 << 26)
+#define DBI_FIFO_EMPTY           (1 << 27)
+#define DPI_FIFO_EMPTY           (1 << 28)
+#define HS_LS_DBI_ENABLE_REG         0xb078
+#define TXCLKESC_REG		     0xb07c
+#define DPHY_PARAM_REG               0xb080
+#define DBI_BW_CTRL_REG              0xb084
+#define CLK_LANE_SWT_REG             0xb088
+
+/*
+ * MIPI Adapter registers
+ */
+#define MIPI_CONTROL_REG             0xb104
+#define MIPI_2X_CLOCK_BITS       ((1 << 0) | (1 << 1))
+#define MIPI_DATA_ADDRESS_REG        0xb108
+#define MIPI_DATA_LENGTH_REG         0xb10C
+#define MIPI_COMMAND_ADDRESS_REG     0xb110
+#define MIPI_COMMAND_LENGTH_REG      0xb114
+#define MIPI_READ_DATA_RETURN_REG0   0xb118
+#define MIPI_READ_DATA_RETURN_REG1   0xb11C
+#define MIPI_READ_DATA_RETURN_REG2   0xb120
+#define MIPI_READ_DATA_RETURN_REG3   0xb124
+#define MIPI_READ_DATA_RETURN_REG4   0xb128
+#define MIPI_READ_DATA_RETURN_REG5   0xb12C
+#define MIPI_READ_DATA_RETURN_REG6   0xb130
+#define MIPI_READ_DATA_RETURN_REG7   0xb134
+#define MIPI_READ_DATA_VALID_REG     0xb138
+/* DBI COMMANDS */
+#define soft_reset                   0x01
+/*
+ *	The display module performs a software reset.
+ *	Registers are written with their SW Reset default values.
+ */
+#define get_power_mode               0x0a
+/*
+ *	The display module returns the current power mode
+ */
+#define get_address_mode             0x0b
+/*
+ *	The display module returns the current status.
+ */
+#define get_pixel_format             0x0c
+/*
+ *	This command gets the pixel format for the RGB image data
+ *	used by the interface.
+ */
+#define get_display_mode             0x0d
+/*
+ *	The display module returns the Display Image Mode status.
+ */
+#define get_signal_mode              0x0e
+/*
+ *	The display module returns the Display Signal Mode.
+ */
+#define get_diagnostic_result        0x0f
+/*
+ *	The display module returns the self-diagnostic results following
+ *	a Sleep Out command.
+ */
+#define enter_sleep_mode             0x10
+/*
+ *	This command causes the display module to enter the Sleep mode.
+ *	In this mode, all unnecessary blocks inside the display module are
+ *	disabled except interface communication. This is the lowest power
+ *	mode the display module supports.
+ */
+#define exit_sleep_mode              0x11
+/*
+ *	This command causes the display module to exit Sleep mode.
+ *	All blocks inside the display module are enabled.
+ */
+#define enter_partial_mode           0x12
+/*
+ *	This command causes the display module to enter the Partial Display
+ *	Mode. The Partial Display Mode window is described by the
+ *	set_partial_area command.
+ */
+#define enter_normal_mode            0x13
+/*
+ *	This command causes the display module to enter the Normal mode.
+ *	Normal Mode is defined as Partial Display mode and Scroll mode are off
+ */
+#define exit_invert_mode             0x20
+/*
+ *	This command causes the display module to stop inverting the image
+ *	data on the display device. The frame memory contents remain unchanged.
+ *	No status bits are changed.
+ */
+#define enter_invert_mode            0x21
+/*
+ *	This command causes the display module to invert the image data only on
+ *	the display device. The frame memory contents remain unchanged.
+ *	No status bits are changed.
+ */
+#define set_gamma_curve              0x26
+/*
+ *	This command selects the desired gamma curve for the display device.
+ *	Four fixed gamma curves are defined in section DCS spec.
+ */
+#define set_display_off              0x28
+/* ************************************************************************* *\
+This command causes the display module to stop displaying the image data
+on the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_display_on               0x29
+/* ************************************************************************* *\
+This command causes the display module to start displaying the image data
+on the display device. The frame memory contents remain unchanged.
+No status bits are changed.
+\* ************************************************************************* */
+#define set_column_address           0x2a
+/*
+ *	This command defines the column extent of the frame memory accessed by
+ *	the hostprocessor with the read_memory_continue and
+ *	write_memory_continue commands.
+ *	No status bits are changed.
+ */
+#define set_page_addr             0x2b
+/*
+ *	This command defines the page extent of the frame memory accessed by
+ *	the host processor with the write_memory_continue and
+ *	read_memory_continue command. 
+ *	No status bits are changed.
+ */
+#define write_mem_start              0x2c
+/*
+ *	This command transfers image data from the host processor to the
+ *	display module s frame memory starting at the pixel location specified
+ *	by preceding set_column_address and set_page_address commands.
+ */
+#define set_partial_area             0x30
+/*
+ *	This command defines the Partial Display mode s display area.
+ *	There are two parameters associated with this command, the first
+ *	defines the Start Row (SR) and the second the End Row (ER). SR and ER
+ *	refer to the Frame Memory Line Pointer.
+ */
+#define set_scroll_area              0x33
+/*
+ *	This command defines the display modules Vertical Scrolling Area.
+ */
+#define set_tear_off                 0x34
+/*
+ *	This command turns off the display modules Tearing Effect output
+ *	signal on the TE signal line.
+ */
+#define set_tear_on                  0x35
+/*
+ *	This command turns on the display modules Tearing Effect output signal
+ *	on the TE signal line.
+ */
+#define set_address_mode             0x36
+/*
+ *	This command sets the data order for transfers from the host processor
+ *	to display modules frame memory,bits B[7:5] and B3, and from the
+ *	display modules frame memory to the display device, bits B[2:0] and B4.
+ */
+#define set_scroll_start             0x37
+/*
+ *	This command sets the start of the vertical scrolling area in the frame
+ *	memory. The vertical scrolling area is fully defined when this command
+ *	is used with the set_scroll_area command The set_scroll_start command
+ *	has one parameter, the Vertical Scroll Pointer. The VSP defines the
+ *	line in the frame memory that is written to the display device as the
+ *	first line of the vertical scroll area.
+ */
+#define exit_idle_mode               0x38
+/*
+ *	This command causes the display module to exit Idle mode.
+ */
+#define enter_idle_mode              0x39
+/*
+ *	This command causes the display module to enter Idle Mode.
+ *	In Idle Mode, color expression is reduced. Colors are shown on the
+ *	display device using the MSB of each of the R, G and B color
+ *	components in the frame memory
+ */
+#define set_pixel_format             0x3a
+/*
+ *	This command sets the pixel format for the RGB image data used by the
+ *	interface.
+ *	Bits D[6:4]  DPI Pixel Format Definition
+ *	Bits D[2:0]  DBI Pixel Format Definition
+ *	Bits D7 and D3 are not used.
+ */
+  #define DCS_PIXEL_FORMAT_3bbp	 	0x1
+  #define DCS_PIXEL_FORMAT_8bbp 	0x2
+  #define DCS_PIXEL_FORMAT_12bbp 	0x3
+  #define DCS_PIXEL_FORMAT_16bbp	0x5
+  #define DCS_PIXEL_FORMAT_18bbp	0x6
+  #define DCS_PIXEL_FORMAT_24bbp 	0x7
+#define write_mem_cont               0x3c
+/*
+ *	This command transfers image data from the host processor to the
+ *	display module's frame memory continuing from the pixel location
+ *	following the previous write_memory_continue or write_memory_start
+ *	command.
+ */
+#define set_tear_scanline            0x44
+/*
+ *	This command turns on the display modules Tearing Effect output signal
+ *	on the TE signal line when the display module reaches line N.
+ */
+#define get_scanline                 0x45
+/*
+ *	The display module returns the current scanline, N, used to update the
+ *	 display device. The total number of scanlines on a display device is
+ *	defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as
+ *	the first line of V Sync and is denoted as Line 0.
+ *	When in Sleep Mode, the value returned by get_scanline is undefined.
+ */
+
+/* MCS or Generic COMMANDS */
+/* MCS/generic data type */
+#define GEN_SHORT_WRITE_0	0x03  /* generic short write, no parameters */
+#define GEN_SHORT_WRITE_1	0x13  /* generic short write, 1 parameters */
+#define GEN_SHORT_WRITE_2	0x23  /* generic short write, 2 parameters */
+#define GEN_READ_0		0x04  /* generic read, no parameters */
+#define GEN_READ_1		0x14  /* generic read, 1 parameters */
+#define GEN_READ_2		0x24  /* generic read, 2 parameters */
+#define GEN_LONG_WRITE		0x29  /* generic long write */
+#define MCS_SHORT_WRITE_0	0x05  /* MCS short write, no parameters */
+#define MCS_SHORT_WRITE_1	0x15  /* MCS short write, 1 parameters */
+#define MCS_READ		0x06  /* MCS read, no parameters */
+#define MCS_LONG_WRITE		0x39  /* MCS long write */
+/* MCS/generic commands */
+/* TPO MCS */
+#define write_display_profile		0x50
+#define write_display_brightness	0x51
+#define write_ctrl_display		0x53
+#define write_ctrl_cabc			0x55
+  #define UI_IMAGE		0x01
+  #define STILL_IMAGE		0x02
+  #define MOVING_IMAGE		0x03
+#define write_hysteresis		0x57
+#define write_gamma_setting		0x58
+#define write_cabc_min_bright		0x5e
+#define write_kbbc_profile		0x60
+/* TMD MCS */
+#define tmd_write_display_brightness 0x8c
+
+/*
+ *	This command is used to control ambient light, panel backlight
+ *	brightness and gamma settings.
+ */
+#define BRIGHT_CNTL_BLOCK_ON	(1 << 5)
+#define AMBIENT_LIGHT_SENSE_ON	(1 << 4)
+#define DISPLAY_DIMMING_ON	(1 << 3)
+#define BACKLIGHT_ON		(1 << 2)
+#define DISPLAY_BRIGHTNESS_AUTO	(1 << 1)
+#define GAMMA_AUTO		(1 << 0)
+
+/* DCS Interface Pixel Formats */
+#define DCS_PIXEL_FORMAT_3BPP         0x1
+#define DCS_PIXEL_FORMAT_8BPP         0x2
+#define DCS_PIXEL_FORMAT_12BPP        0x3
+#define DCS_PIXEL_FORMAT_16BPP        0x5
+#define DCS_PIXEL_FORMAT_18BPP        0x6
+#define DCS_PIXEL_FORMAT_24BPP        0x7
+/* ONE PARAMETER READ DATA */
+#define addr_mode_data           0xfc
+#define diag_res_data            0x00
+#define disp_mode_data           0x23
+#define pxl_fmt_data             0x77
+#define pwr_mode_data            0x74
+#define sig_mode_data            0x00
+/* TWO PARAMETERS READ DATA */
+#define scanline_data1           0xff
+#define scanline_data2           0xff
+#define NON_BURST_MODE_SYNC_PULSE	0x01	/* Non Burst Mode
+						 * with Sync Pulse
+						 */
+#define NON_BURST_MODE_SYNC_EVENTS	0x02	/* Non Burst Mode
+						 * with Sync events
+						 */
+#define BURST_MODE			0x03	/* Burst Mode */
+#define DBI_COMMAND_BUFFER_SIZE		0x240  /* 0x32 */    /* 0x120 */	/* Allocate at least
+						 * 0x100 Byte with 32
+						 * byte alignment
+						 */
+#define DBI_DATA_BUFFER_SIZE		0x120	/* Allocate at least
+						 * 0x100 Byte with 32
+						 * byte alignment
+						 */
+#define DBI_CB_TIME_OUT 0xFFFF
+
+#define GEN_FB_TIME_OUT 2000 
+#define ALIGNMENT_32BYTE_MASK		(~((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)))
+#define SKU_83 						0x01
+#define SKU_100 					0x02
+#define SKU_100L 					0x04
+#define SKU_BYPASS 					0x08
+
+#endif
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c
new file mode 100644
index 0000000..731a5a2
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_sdvo.c
@@ -0,0 +1,1298 @@
+/*
+ * Copyright (c) 2006-2007 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#include <linux/i2c.h>
+#include <linux/delay.h>
+/* #include <drm/drm_crtc.h> */
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_intel_drv.h"
+#include "psb_intel_reg.h"
+#include "psb_intel_sdvo_regs.h"
+
+struct psb_intel_sdvo_priv {
+	struct psb_intel_i2c_chan *i2c_bus;
+	int slaveaddr;
+	int output_device;
+
+	u16 active_outputs;
+
+	struct psb_intel_sdvo_caps caps;
+	int pixel_clock_min, pixel_clock_max;
+
+	int save_sdvo_mult;
+	u16 save_active_outputs;
+	struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
+	struct psb_intel_sdvo_dtd save_output_dtd[16];
+	u32 save_SDVOX;
+	u8 in_out_map[4];
+
+	u8 by_input_wiring;
+	u32 active_device;
+};
+
+/**
+ * Writes the SDVOB or SDVOC with the given value, but always writes both
+ * SDVOB and SDVOC to work around apparent hardware issues (according to
+ * comments in the BIOS).
+ */
+void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output,
+				u32 val)
+{
+	struct drm_device *dev = psb_intel_output->base.dev;
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	u32 bval = val, cval = val;
+	int i;
+
+	if (sdvo_priv->output_device == SDVOB)
+		cval = REG_READ(SDVOC);
+	else
+		bval = REG_READ(SDVOB);
+	/*
+	 * Write the registers twice for luck. Sometimes,
+	 * writing them only once doesn't appear to 'stick'.
+	 * The BIOS does this too. Yay, magic
+	 */
+	for (i = 0; i < 2; i++) {
+		REG_WRITE(SDVOB, bval);
+		REG_READ(SDVOB);
+		REG_WRITE(SDVOC, cval);
+		REG_READ(SDVOC);
+	}
+}
+
+static bool psb_intel_sdvo_read_byte(
+				struct psb_intel_output *psb_intel_output,
+				u8 addr, u8 *ch)
+{
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	u8 out_buf[2];
+	u8 buf[2];
+	int ret;
+
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = sdvo_priv->i2c_bus->slave_addr,
+		 .flags = 0,
+		 .len = 1,
+		 .buf = out_buf,
+		 },
+		{
+		 .addr = sdvo_priv->i2c_bus->slave_addr,
+		 .flags = I2C_M_RD,
+		 .len = 1,
+		 .buf = buf,
+		 }
+	};
+
+	out_buf[0] = addr;
+	out_buf[1] = 0;
+
+	ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2);
+	if (ret == 2) {
+		/* DRM_DEBUG("got back from addr %02X = %02x\n",
+		 * out_buf[0], buf[0]);
+		 */
+		*ch = buf[0];
+		return true;
+	}
+
+	DRM_DEBUG("i2c transfer returned %d\n", ret);
+	return false;
+}
+
+static bool psb_intel_sdvo_write_byte(
+			struct psb_intel_output *psb_intel_output,
+			int addr, u8 ch)
+{
+	u8 out_buf[2];
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = psb_intel_output->i2c_bus->slave_addr,
+		 .flags = 0,
+		 .len = 2,
+		 .buf = out_buf,
+		 }
+	};
+
+	out_buf[0] = addr;
+	out_buf[1] = ch;
+
+	if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1)
+		return true;
+	return false;
+}
+
+#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
+/** Mapping of command numbers to names, for debug output */
+static const struct _sdvo_cmd_name {
+	u8 cmd;
+	char *name;
+} sdvo_cmd_names[] = {
+SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+	    SDVO_CMD_NAME_ENTRY
+	    (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
+	    SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),};
+
+#define SDVO_NAME(dev_priv) \
+		 ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
+#define SDVO_PRIV(output)   ((struct psb_intel_sdvo_priv *) (output)->dev_priv)
+
+static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output,
+				     u8 cmd,
+				     void *args,
+				     int args_len)
+{
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	int i;
+
+	if (1) {
+		DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd);
+		for (i = 0; i < args_len; i++)
+			printk(KERN_INFO"%02X ", ((u8 *) args)[i]);
+		for (; i < 8; i++)
+			printk("   ");
+		for (i = 0;
+		     i <
+		     sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]);
+		     i++) {
+			if (cmd == sdvo_cmd_names[i].cmd) {
+				printk("(%s)", sdvo_cmd_names[i].name);
+				break;
+			}
+		}
+		if (i ==
+		    sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]))
+			printk("(%02X)", cmd);
+		printk("\n");
+	}
+
+	for (i = 0; i < args_len; i++) {
+		psb_intel_sdvo_write_byte(psb_intel_output,
+					SDVO_I2C_ARG_0 - i,
+					((u8 *) args)[i]);
+	}
+
+	psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd);
+}
+
+static const char *const cmd_status_names[] = {
+	"Power on",
+	"Success",
+	"Not supported",
+	"Invalid arg",
+	"Pending",
+	"Target not specified",
+	"Scaling not supported"
+};
+
+static u8 psb_intel_sdvo_read_response(
+				struct psb_intel_output *psb_intel_output,
+				void *response, int response_len)
+{
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	int i;
+	u8 status;
+	u8 retry = 50;
+
+	while (retry--) {
+		/* Read the command response */
+		for (i = 0; i < response_len; i++) {
+			psb_intel_sdvo_read_byte(psb_intel_output,
+					     SDVO_I2C_RETURN_0 + i,
+					     &((u8 *) response)[i]);
+		}
+
+		/* read the return status */
+		psb_intel_sdvo_read_byte(psb_intel_output,
+					 SDVO_I2C_CMD_STATUS,
+					 &status);
+
+		if (1) {
+			DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv));
+			for (i = 0; i < response_len; i++)
+				printk(KERN_INFO"%02X ", ((u8 *) response)[i]);
+			for (; i < 8; i++)
+				printk("   ");
+			if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP)
+				printk(KERN_INFO"(%s)",
+					 cmd_status_names[status]);
+			else
+				printk(KERN_INFO"(??? %d)", status);
+			printk("\n");
+		}
+
+		if (status != SDVO_CMD_STATUS_PENDING)
+			return status;
+
+		mdelay(50);
+	}
+
+	return status;
+}
+
+int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
+{
+	if (mode->clock >= 100000)
+		return 1;
+	else if (mode->clock >= 50000)
+		return 2;
+	else
+		return 4;
+}
+
+/**
+ * Don't check status code from this as it switches the bus back to the
+ * SDVO chips which defeats the purpose of doing a bus switch in the first
+ * place.
+ */
+void psb_intel_sdvo_set_control_bus_switch(
+				struct psb_intel_output *psb_intel_output,
+				u8 target)
+{
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_SET_CONTROL_BUS_SWITCH,
+				 &target,
+				 1);
+}
+
+static bool psb_intel_sdvo_set_target_input(
+				struct psb_intel_output *psb_intel_output,
+				bool target_0, bool target_1)
+{
+	struct psb_intel_sdvo_set_target_input_args targets = { 0 };
+	u8 status;
+
+	if (target_0 && target_1)
+		return SDVO_CMD_STATUS_NOTSUPP;
+
+	if (target_1)
+		targets.target_1 = 1;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT,
+			     &targets, sizeof(targets));
+
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+
+	return status == SDVO_CMD_STATUS_SUCCESS;
+}
+
+/**
+ * Return whether each input is trained.
+ *
+ * This function is making an assumption about the layout of the response,
+ * which should be checked against the docs.
+ */
+static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output
+					  *psb_intel_output, bool *input_1,
+					  bool *input_2)
+{
+	struct psb_intel_sdvo_get_trained_inputs_response response;
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS,
+			     NULL, 0);
+	status =
+	    psb_intel_sdvo_read_response(psb_intel_output, &response,
+				     sizeof(response));
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	*input_1 = response.input0_trained;
+	*input_2 = response.input1_trained;
+	return true;
+}
+
+static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output
+					  *psb_intel_output, u16 *outputs)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS,
+			     NULL, 0);
+	status =
+	    psb_intel_sdvo_read_response(psb_intel_output, outputs,
+				     sizeof(*outputs));
+
+	return status == SDVO_CMD_STATUS_SUCCESS;
+}
+
+static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output
+					  *psb_intel_output, u16 outputs)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS,
+			     &outputs, sizeof(outputs));
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+	return status == SDVO_CMD_STATUS_SUCCESS;
+}
+
+static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output
+					       *psb_intel_output, int mode)
+{
+	u8 status, state = SDVO_ENCODER_STATE_ON;
+
+	switch (mode) {
+	case DRM_MODE_DPMS_ON:
+		state = SDVO_ENCODER_STATE_ON;
+		break;
+	case DRM_MODE_DPMS_STANDBY:
+		state = SDVO_ENCODER_STATE_STANDBY;
+		break;
+	case DRM_MODE_DPMS_SUSPEND:
+		state = SDVO_ENCODER_STATE_SUSPEND;
+		break;
+	case DRM_MODE_DPMS_OFF:
+		state = SDVO_ENCODER_STATE_OFF;
+		break;
+	}
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+			     SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
+			     sizeof(state));
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+
+	return status == SDVO_CMD_STATUS_SUCCESS;
+}
+
+static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output
+						   *psb_intel_output,
+						   int *clock_min,
+						   int *clock_max)
+{
+	struct psb_intel_sdvo_pixel_clock_range clocks;
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+			     SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL,
+			     0);
+
+	status =
+	    psb_intel_sdvo_read_response(psb_intel_output, &clocks,
+				     sizeof(clocks));
+
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	/* Convert the values from units of 10 kHz to kHz. */
+	*clock_min = clocks.min * 10;
+	*clock_max = clocks.max * 10;
+
+	return true;
+}
+
+static bool psb_intel_sdvo_set_target_output(
+				struct psb_intel_output *psb_intel_output,
+				u16 outputs)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT,
+			     &outputs, sizeof(outputs));
+
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+	return status == SDVO_CMD_STATUS_SUCCESS;
+}
+
+static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output,
+				  u8 cmd, struct psb_intel_sdvo_dtd *dtd)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0);
+	status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1,
+					  sizeof(dtd->part1));
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0);
+	status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2,
+					  sizeof(dtd->part2));
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	return true;
+}
+
+static bool psb_intel_sdvo_get_input_timing(
+				struct psb_intel_output *psb_intel_output,
+				struct psb_intel_sdvo_dtd *dtd)
+{
+	return psb_intel_sdvo_get_timing(psb_intel_output,
+				     SDVO_CMD_GET_INPUT_TIMINGS_PART1,
+				     dtd);
+}
+
+static bool psb_intel_sdvo_set_timing(
+				struct psb_intel_output *psb_intel_output,
+				u8 cmd,
+				struct psb_intel_sdvo_dtd *dtd)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1,
+			     sizeof(dtd->part1));
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2,
+			     sizeof(dtd->part2));
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	return true;
+}
+
+static bool psb_intel_sdvo_set_input_timing(
+				struct psb_intel_output *psb_intel_output,
+				struct psb_intel_sdvo_dtd *dtd)
+{
+	return psb_intel_sdvo_set_timing(psb_intel_output,
+				     SDVO_CMD_SET_INPUT_TIMINGS_PART1,
+				     dtd);
+}
+
+static bool psb_intel_sdvo_set_output_timing(
+				struct psb_intel_output *psb_intel_output,
+				struct psb_intel_sdvo_dtd *dtd)
+{
+	return psb_intel_sdvo_set_timing(psb_intel_output,
+				     SDVO_CMD_SET_OUTPUT_TIMINGS_PART1,
+				     dtd);
+}
+
+static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output
+						*psb_intel_output)
+{
+	u8 response, status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_GET_CLOCK_RATE_MULT,
+				 NULL,
+				 0);
+
+	status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1);
+
+	if (status != SDVO_CMD_STATUS_SUCCESS) {
+		DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n");
+		return SDVO_CLOCK_RATE_MULT_1X;
+	} else {
+		DRM_DEBUG("Current clock rate multiplier: %d\n", response);
+	}
+
+	return response;
+}
+
+static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output
+						*psb_intel_output, u8 val)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				SDVO_CMD_SET_CLOCK_RATE_MULT,
+				&val,
+				1);
+
+	status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	return true;
+}
+
+static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output,
+					  u32 in0outputmask,
+					  u32 in1outputmask)
+{
+	u8 byArgs[4];
+	u8 status;
+	int i;
+	struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv;
+
+	/* Make all fields of the  args/ret to zero */
+	memset(byArgs, 0, sizeof(byArgs));
+
+	/* Fill up the arguement values; */
+	byArgs[0] = (u8) (in0outputmask & 0xFF);
+	byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF);
+	byArgs[2] = (u8) (in1outputmask & 0xFF);
+	byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF);
+
+
+	/*save inoutmap arg here*/
+	for (i = 0; i < 4; i++)
+		sdvo_priv->in_out_map[i] = byArgs[0];
+
+	psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4);
+	status = psb_intel_sdvo_read_response(output, NULL, 0);
+
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+	return true;
+}
+
+
+static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output)
+{
+	u32 dwCurrentSDVOIn0 = 0;
+	u32 dwCurrentSDVOIn1 = 0;
+	u32 dwDevMask = 0;
+
+
+	struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv;
+
+	/* Please DO NOT change the following code. */
+	/* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */
+	/* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */
+	if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) {
+		switch (sdvo_priv->active_device) {
+		case SDVO_DEVICE_LVDS:
+			dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1;
+			break;
+		case SDVO_DEVICE_TMDS:
+			dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1;
+			break;
+		case SDVO_DEVICE_TV:
+			dwDevMask =
+			SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 |
+			SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 |
+			SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 |
+			SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1;
+			break;
+		case SDVO_DEVICE_CRT:
+			dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1;
+			break;
+		}
+		dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask);
+	} else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) {
+		switch (sdvo_priv->active_device) {
+		case SDVO_DEVICE_LVDS:
+			dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1;
+			break;
+		case SDVO_DEVICE_TMDS:
+			dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1;
+			break;
+		case SDVO_DEVICE_TV:
+			dwDevMask =
+			SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 |
+			SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 |
+			SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 |
+			SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1;
+			break;
+		case SDVO_DEVICE_CRT:
+			dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1;
+			break;
+		}
+		dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask);
+	}
+
+	psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0,
+					  dwCurrentSDVOIn1);
+}
+
+
+static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
+				  struct drm_display_mode *mode,
+				  struct drm_display_mode *adjusted_mode)
+{
+	/* Make the CRTC code factor in the SDVO pixel multiplier.  The SDVO
+	 * device will be told of the multiplier during mode_set.
+	 */
+	adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode);
+	return true;
+}
+
+static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
+				struct drm_display_mode *mode,
+				struct drm_display_mode *adjusted_mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct drm_crtc *crtc = encoder->crtc;
+	struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
+	struct psb_intel_output *psb_intel_output =
+					enc_to_psb_intel_output(encoder);
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	u16 width, height;
+	u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
+	u16 h_sync_offset, v_sync_offset;
+	u32 sdvox;
+	struct psb_intel_sdvo_dtd output_dtd;
+	int sdvo_pixel_multiply;
+
+	if (!mode)
+		return;
+
+	psb_intel_sdvo_set_target_output(psb_intel_output, 0);
+
+	width = mode->crtc_hdisplay;
+	height = mode->crtc_vdisplay;
+
+	/* do some mode translations */
+	h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start;
+	h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
+
+	v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start;
+	v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
+
+	h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
+	v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
+
+	output_dtd.part1.clock = mode->clock / 10;
+	output_dtd.part1.h_active = width & 0xff;
+	output_dtd.part1.h_blank = h_blank_len & 0xff;
+	output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) |
+	    ((h_blank_len >> 8) & 0xf);
+	output_dtd.part1.v_active = height & 0xff;
+	output_dtd.part1.v_blank = v_blank_len & 0xff;
+	output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) |
+	    ((v_blank_len >> 8) & 0xf);
+
+	output_dtd.part2.h_sync_off = h_sync_offset;
+	output_dtd.part2.h_sync_width = h_sync_len & 0xff;
+	output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 |
+	    (v_sync_len & 0xf);
+	output_dtd.part2.sync_off_width_high =
+	    ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) |
+	    ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4);
+
+	output_dtd.part2.dtd_flags = 0x18;
+	if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+		output_dtd.part2.dtd_flags |= 0x2;
+	if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+		output_dtd.part2.dtd_flags |= 0x4;
+
+	output_dtd.part2.sdvo_flags = 0;
+	output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0;
+	output_dtd.part2.reserved = 0;
+
+	/* Set the output timing to the screen */
+	psb_intel_sdvo_set_target_output(psb_intel_output,
+				     sdvo_priv->active_outputs);
+
+	/* Set the input timing to the screen. Assume always input 0. */
+	psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
+
+	psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd);
+
+	/* We would like to use i830_sdvo_create_preferred_input_timing() to
+	 * provide the device with a timing it can support, if it supports that
+	 * feature.  However, presumably we would need to adjust the CRTC to
+	 * output the preferred timing, and we don't support that currently.
+	 */
+	psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd);
+
+	switch (psb_intel_sdvo_get_pixel_multiplier(mode)) {
+	case 1:
+		psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
+					       SDVO_CLOCK_RATE_MULT_1X);
+		break;
+	case 2:
+		psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
+					       SDVO_CLOCK_RATE_MULT_2X);
+		break;
+	case 4:
+		psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
+					       SDVO_CLOCK_RATE_MULT_4X);
+		break;
+	}
+
+	/* Set the SDVO control regs. */
+	sdvox = REG_READ(sdvo_priv->output_device);
+	switch (sdvo_priv->output_device) {
+	case SDVOB:
+		sdvox &= SDVOB_PRESERVE_MASK;
+		break;
+	case SDVOC:
+		sdvox &= SDVOC_PRESERVE_MASK;
+		break;
+	}
+	sdvox |= (9 << 19) | SDVO_BORDER_ENABLE;
+	if (psb_intel_crtc->pipe == 1)
+		sdvox |= SDVO_PIPE_B_SELECT;
+
+	sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode);
+
+	psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox);
+
+	 psb_intel_sdvo_set_iomap(psb_intel_output);
+}
+
+static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct drm_device *dev = encoder->dev;
+	struct psb_intel_output *psb_intel_output =
+					enc_to_psb_intel_output(encoder);
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	u32 temp;
+
+	if (mode != DRM_MODE_DPMS_ON) {
+		psb_intel_sdvo_set_active_outputs(psb_intel_output, 0);
+		if (0)
+			psb_intel_sdvo_set_encoder_power_state(
+							psb_intel_output,
+							mode);
+
+		if (mode == DRM_MODE_DPMS_OFF) {
+			temp = REG_READ(sdvo_priv->output_device);
+			if ((temp & SDVO_ENABLE) != 0) {
+				psb_intel_sdvo_write_sdvox(psb_intel_output,
+						       temp &
+						       ~SDVO_ENABLE);
+			}
+		}
+	} else {
+		bool input1, input2;
+		int i;
+		u8 status;
+
+		temp = REG_READ(sdvo_priv->output_device);
+		if ((temp & SDVO_ENABLE) == 0)
+			psb_intel_sdvo_write_sdvox(psb_intel_output,
+					       temp | SDVO_ENABLE);
+		for (i = 0; i < 2; i++)
+			psb_intel_wait_for_vblank(dev);
+
+		status =
+		    psb_intel_sdvo_get_trained_inputs(psb_intel_output,
+							&input1,
+							&input2);
+
+
+		/* Warn if the device reported failure to sync.
+		 * A lot of SDVO devices fail to notify of sync, but it's
+		 * a given it the status is a success, we succeeded.
+		 */
+		if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
+			DRM_DEBUG
+			    ("First %s output reported failure to sync\n",
+			     SDVO_NAME(sdvo_priv));
+		}
+
+		if (0)
+			psb_intel_sdvo_set_encoder_power_state(
+							psb_intel_output,
+							mode);
+		psb_intel_sdvo_set_active_outputs(psb_intel_output,
+					      sdvo_priv->active_outputs);
+	}
+	return;
+}
+
+static void psb_intel_sdvo_save(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	/*int o;*/
+
+	sdvo_priv->save_sdvo_mult =
+	    psb_intel_sdvo_get_clock_rate_mult(psb_intel_output);
+	psb_intel_sdvo_get_active_outputs(psb_intel_output,
+				      &sdvo_priv->save_active_outputs);
+
+	if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
+		psb_intel_sdvo_set_target_input(psb_intel_output,
+						true,
+						false);
+		psb_intel_sdvo_get_input_timing(psb_intel_output,
+					    &sdvo_priv->save_input_dtd_1);
+	}
+
+	if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
+		psb_intel_sdvo_set_target_input(psb_intel_output,
+						false,
+						true);
+		psb_intel_sdvo_get_input_timing(psb_intel_output,
+					    &sdvo_priv->save_input_dtd_2);
+	}
+	sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device);
+
+	/*TODO: save the in_out_map state*/
+}
+
+static void psb_intel_sdvo_restore(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+	/*int o;*/
+	int i;
+	bool input1, input2;
+	u8 status;
+
+	psb_intel_sdvo_set_active_outputs(psb_intel_output, 0);
+
+	if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
+		psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
+		psb_intel_sdvo_set_input_timing(psb_intel_output,
+					    &sdvo_priv->save_input_dtd_1);
+	}
+
+	if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
+		psb_intel_sdvo_set_target_input(psb_intel_output, false, true);
+		psb_intel_sdvo_set_input_timing(psb_intel_output,
+					    &sdvo_priv->save_input_dtd_2);
+	}
+
+	psb_intel_sdvo_set_clock_rate_mult(psb_intel_output,
+				       sdvo_priv->save_sdvo_mult);
+
+	REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX);
+
+	if (sdvo_priv->save_SDVOX & SDVO_ENABLE) {
+		for (i = 0; i < 2; i++)
+			psb_intel_wait_for_vblank(dev);
+		status =
+		    psb_intel_sdvo_get_trained_inputs(psb_intel_output,
+							&input1,
+							&input2);
+		if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
+			DRM_DEBUG
+			    ("First %s output reported failure to sync\n",
+			     SDVO_NAME(sdvo_priv));
+	}
+
+	psb_intel_sdvo_set_active_outputs(psb_intel_output,
+				      sdvo_priv->save_active_outputs);
+
+	/*TODO: restore in_out_map*/
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_SET_IN_OUT_MAP,
+				 sdvo_priv->in_out_map,
+				 4);
+
+	psb_intel_sdvo_read_response(psb_intel_output, NULL, 0);
+}
+
+static int psb_intel_sdvo_mode_valid(struct drm_connector *connector,
+				 struct drm_display_mode *mode)
+{
+	struct psb_intel_output *psb_intel_output =
+				to_psb_intel_output(connector);
+	struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv;
+
+	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+		return MODE_NO_DBLESCAN;
+
+	if (sdvo_priv->pixel_clock_min > mode->clock)
+		return MODE_CLOCK_LOW;
+
+	if (sdvo_priv->pixel_clock_max < mode->clock)
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static bool psb_intel_sdvo_get_capabilities(
+				struct psb_intel_output *psb_intel_output,
+				struct psb_intel_sdvo_caps *caps)
+{
+	u8 status;
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_GET_DEVICE_CAPS,
+				 NULL,
+				 0);
+	status = psb_intel_sdvo_read_response(psb_intel_output,
+						caps,
+						sizeof(*caps));
+	if (status != SDVO_CMD_STATUS_SUCCESS)
+		return false;
+
+	return true;
+}
+
+struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB)
+{
+	struct drm_connector *connector = NULL;
+	struct psb_intel_output *iout = NULL;
+	struct psb_intel_sdvo_priv *sdvo;
+
+	/* find the sdvo connector */
+	list_for_each_entry(connector, &dev->mode_config.connector_list,
+			    head) {
+		iout = to_psb_intel_output(connector);
+
+		if (iout->type != INTEL_OUTPUT_SDVO)
+			continue;
+
+		sdvo = iout->dev_priv;
+
+		if (sdvo->output_device == SDVOB && sdvoB)
+			return connector;
+
+		if (sdvo->output_device == SDVOC && !sdvoB)
+			return connector;
+
+	}
+
+	return NULL;
+}
+
+int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector)
+{
+	u8 response[2];
+	u8 status;
+	struct psb_intel_output *psb_intel_output;
+	DRM_DEBUG("\n");
+
+	if (!connector)
+		return 0;
+
+	psb_intel_output = to_psb_intel_output(connector);
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_GET_HOT_PLUG_SUPPORT,
+				 NULL,
+				 0);
+	status = psb_intel_sdvo_read_response(psb_intel_output,
+						&response,
+						2);
+
+	if (response[0] != 0)
+		return 1;
+
+	return 0;
+}
+
+void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
+{
+	u8 response[2];
+	u8 status;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_GET_ACTIVE_HOT_PLUG,
+				 NULL,
+				 0);
+	psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
+
+	if (on) {
+		psb_intel_sdvo_write_cmd(psb_intel_output,
+				     SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL,
+				     0);
+		status = psb_intel_sdvo_read_response(psb_intel_output,
+						      &response,
+						      2);
+
+		psb_intel_sdvo_write_cmd(psb_intel_output,
+				     SDVO_CMD_SET_ACTIVE_HOT_PLUG,
+				     &response, 2);
+	} else {
+		response[0] = 0;
+		response[1] = 0;
+		psb_intel_sdvo_write_cmd(psb_intel_output,
+				     SDVO_CMD_SET_ACTIVE_HOT_PLUG,
+				     &response, 2);
+	}
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_GET_ACTIVE_HOT_PLUG,
+				 NULL,
+				 0);
+	psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
+}
+
+static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector
+						   *connector, bool force)
+{
+	u8 response[2];
+	u8 status;
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	psb_intel_sdvo_write_cmd(psb_intel_output,
+				 SDVO_CMD_GET_ATTACHED_DISPLAYS,
+				 NULL,
+				 0);
+	status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2);
+
+	DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
+	if ((response[0] != 0) || (response[1] != 0))
+		return connector_status_connected;
+	else
+		return connector_status_disconnected;
+}
+
+static int psb_intel_sdvo_get_modes(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+					to_psb_intel_output(connector);
+
+	/* set the bus switch and get the modes */
+	psb_intel_sdvo_set_control_bus_switch(psb_intel_output,
+					  SDVO_CONTROL_BUS_DDC2);
+	psb_intel_ddc_get_modes(psb_intel_output);
+
+	if (list_empty(&connector->probed_modes))
+		return 0;
+	return 1;
+}
+
+static void psb_intel_sdvo_destroy(struct drm_connector *connector)
+{
+	struct psb_intel_output *psb_intel_output =
+				to_psb_intel_output(connector);
+
+	if (psb_intel_output->i2c_bus)
+		psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+	kfree(psb_intel_output);
+}
+
+static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = {
+	.dpms = psb_intel_sdvo_dpms,
+	.mode_fixup = psb_intel_sdvo_mode_fixup,
+	.prepare = psb_intel_encoder_prepare,
+	.mode_set = psb_intel_sdvo_mode_set,
+	.commit = psb_intel_encoder_commit,
+};
+
+static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.save = psb_intel_sdvo_save,
+	.restore = psb_intel_sdvo_restore,
+	.detect = psb_intel_sdvo_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = psb_intel_sdvo_destroy,
+};
+
+static const struct drm_connector_helper_funcs
+				psb_intel_sdvo_connector_helper_funcs = {
+	.get_modes = psb_intel_sdvo_get_modes,
+	.mode_valid = psb_intel_sdvo_mode_valid,
+	.best_encoder = psb_intel_best_encoder,
+};
+
+void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
+{
+	drm_encoder_cleanup(encoder);
+}
+
+static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = {
+	.destroy = psb_intel_sdvo_enc_destroy,
+};
+
+
+void psb_intel_sdvo_init(struct drm_device *dev, int output_device)
+{
+	struct drm_connector *connector;
+	struct psb_intel_output *psb_intel_output;
+	struct psb_intel_sdvo_priv *sdvo_priv;
+	struct psb_intel_i2c_chan *i2cbus = NULL;
+	int connector_type;
+	u8 ch[0x40];
+	int i;
+	int encoder_type, output_id;
+
+	psb_intel_output =
+	    kcalloc(sizeof(struct psb_intel_output) +
+		    sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL);
+	if (!psb_intel_output)
+		return;
+
+	connector = &psb_intel_output->base;
+
+	drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs,
+			   DRM_MODE_CONNECTOR_Unknown);
+	drm_connector_helper_add(connector,
+				 &psb_intel_sdvo_connector_helper_funcs);
+	sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1);
+	psb_intel_output->type = INTEL_OUTPUT_SDVO;
+
+	connector->interlace_allowed = 0;
+	connector->doublescan_allowed = 0;
+
+	/* setup the DDC bus. */
+	if (output_device == SDVOB)
+		i2cbus =
+		    psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB");
+	else
+		i2cbus =
+		    psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
+
+	if (!i2cbus)
+		goto err_connector;
+
+	sdvo_priv->i2c_bus = i2cbus;
+
+	if (output_device == SDVOB) {
+		output_id = 1;
+		sdvo_priv->by_input_wiring = SDVOB_IN0;
+		sdvo_priv->i2c_bus->slave_addr = 0x38;
+	} else {
+		output_id = 2;
+		sdvo_priv->i2c_bus->slave_addr = 0x39;
+	}
+
+	sdvo_priv->output_device = output_device;
+	psb_intel_output->i2c_bus = i2cbus;
+	psb_intel_output->dev_priv = sdvo_priv;
+
+
+	/* Read the regs to test if we can talk to the device */
+	for (i = 0; i < 0x40; i++) {
+		if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) {
+			DRM_DEBUG("No SDVO device found on SDVO%c\n",
+				  output_device == SDVOB ? 'B' : 'C');
+			goto err_i2c;
+		}
+	}
+
+	psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps);
+
+	memset(&sdvo_priv->active_outputs, 0,
+	       sizeof(sdvo_priv->active_outputs));
+
+	/* TODO, CVBS, SVID, YPRPB & SCART outputs. */
+	if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) {
+		sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
+		sdvo_priv->active_device = SDVO_DEVICE_CRT;
+		connector->display_info.subpixel_order =
+		    SubPixelHorizontalRGB;
+		encoder_type = DRM_MODE_ENCODER_DAC;
+		connector_type = DRM_MODE_CONNECTOR_VGA;
+	} else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) {
+		sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
+		sdvo_priv->active_outputs = SDVO_DEVICE_CRT;
+		connector->display_info.subpixel_order =
+		    SubPixelHorizontalRGB;
+		encoder_type = DRM_MODE_ENCODER_DAC;
+		connector_type = DRM_MODE_CONNECTOR_VGA;
+	} else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) {
+		sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0;
+		sdvo_priv->active_device = SDVO_DEVICE_TMDS;
+		connector->display_info.subpixel_order =
+		    SubPixelHorizontalRGB;
+		encoder_type = DRM_MODE_ENCODER_TMDS;
+		connector_type = DRM_MODE_CONNECTOR_DVID;
+	} else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) {
+		sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1;
+		sdvo_priv->active_device = SDVO_DEVICE_TMDS;
+		connector->display_info.subpixel_order =
+		    SubPixelHorizontalRGB;
+		encoder_type = DRM_MODE_ENCODER_TMDS;
+		connector_type = DRM_MODE_CONNECTOR_DVID;
+	} else {
+		unsigned char bytes[2];
+
+		memcpy(bytes, &sdvo_priv->caps.output_flags, 2);
+		DRM_DEBUG
+		    ("%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
+		     SDVO_NAME(sdvo_priv), bytes[0], bytes[1]);
+		goto err_i2c;
+	}
+
+	drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs,
+			 encoder_type);
+	drm_encoder_helper_add(&psb_intel_output->enc,
+			       &psb_intel_sdvo_helper_funcs);
+	connector->connector_type = connector_type;
+
+	drm_mode_connector_attach_encoder(&psb_intel_output->base,
+					  &psb_intel_output->enc);
+	drm_sysfs_connector_add(connector);
+
+	/* Set the input timing to the screen. Assume always input 0. */
+	psb_intel_sdvo_set_target_input(psb_intel_output, true, false);
+
+	psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output,
+					       &sdvo_priv->pixel_clock_min,
+					       &sdvo_priv->
+					       pixel_clock_max);
+
+
+	DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, "
+		  "clock range %dMHz - %dMHz, "
+		  "input 1: %c, input 2: %c, "
+		  "output 1: %c, output 2: %c\n",
+		  SDVO_NAME(sdvo_priv),
+		  sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id,
+		  sdvo_priv->caps.device_rev_id,
+		  sdvo_priv->pixel_clock_min / 1000,
+		  sdvo_priv->pixel_clock_max / 1000,
+		  (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
+		  (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
+		  /* check currently supported outputs */
+		  sdvo_priv->caps.output_flags &
+		  (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
+		  sdvo_priv->caps.output_flags &
+		  (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
+
+	psb_intel_output->ddc_bus = i2cbus;
+
+	return;
+
+err_i2c:
+	psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
+err_connector:
+	drm_connector_cleanup(connector);
+	kfree(psb_intel_output);
+
+	return;
+}
diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h
new file mode 100644
index 0000000..a1d1475
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_sdvo_regs.h
@@ -0,0 +1,338 @@
+/*
+ * SDVO command definitions and structures.
+ *
+ * Copyright (c) 2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *	Eric Anholt <eric@anholt.net>
+ */
+
+#define SDVO_OUTPUT_FIRST   (0)
+#define SDVO_OUTPUT_TMDS0   (1 << 0)
+#define SDVO_OUTPUT_RGB0    (1 << 1)
+#define SDVO_OUTPUT_CVBS0   (1 << 2)
+#define SDVO_OUTPUT_SVID0   (1 << 3)
+#define SDVO_OUTPUT_YPRPB0  (1 << 4)
+#define SDVO_OUTPUT_SCART0  (1 << 5)
+#define SDVO_OUTPUT_LVDS0   (1 << 6)
+#define SDVO_OUTPUT_TMDS1   (1 << 8)
+#define SDVO_OUTPUT_RGB1    (1 << 9)
+#define SDVO_OUTPUT_CVBS1   (1 << 10)
+#define SDVO_OUTPUT_SVID1   (1 << 11)
+#define SDVO_OUTPUT_YPRPB1  (1 << 12)
+#define SDVO_OUTPUT_SCART1  (1 << 13)
+#define SDVO_OUTPUT_LVDS1   (1 << 14)
+#define SDVO_OUTPUT_LAST    (14)
+
+struct psb_intel_sdvo_caps {
+	u8 vendor_id;
+	u8 device_id;
+	u8 device_rev_id;
+	u8 sdvo_version_major;
+	u8 sdvo_version_minor;
+	unsigned int sdvo_inputs_mask:2;
+	unsigned int smooth_scaling:1;
+	unsigned int sharp_scaling:1;
+	unsigned int up_scaling:1;
+	unsigned int down_scaling:1;
+	unsigned int stall_support:1;
+	unsigned int pad:1;
+	u16 output_flags;
+} __attribute__ ((packed));
+
+/** This matches the EDID DTD structure, more or less */
+struct psb_intel_sdvo_dtd {
+	struct {
+		u16 clock;	/**< pixel clock, in 10kHz units */
+		u8 h_active;	/**< lower 8 bits (pixels) */
+		u8 h_blank;	/**< lower 8 bits (pixels) */
+		u8 h_high;	/**< upper 4 bits each h_active, h_blank */
+		u8 v_active;	/**< lower 8 bits (lines) */
+		u8 v_blank;	/**< lower 8 bits (lines) */
+		u8 v_high;	/**< upper 4 bits each v_active, v_blank */
+	} part1;
+
+	struct {
+		u8 h_sync_off;
+			/**< lower 8 bits, from hblank start */
+		u8 h_sync_width;/**< lower 8 bits (pixels) */
+	/** lower 4 bits each vsync offset, vsync width */
+		u8 v_sync_off_width;
+	/**
+	 * 2 high bits of hsync offset, 2 high bits of hsync width,
+	 * bits 4-5 of vsync offset, and 2 high bits of vsync width.
+	 */
+		u8 sync_off_width_high;
+		u8 dtd_flags;
+		u8 sdvo_flags;
+	/** bits 6-7 of vsync offset at bits 6-7 */
+		u8 v_sync_off_high;
+		u8 reserved;
+	} part2;
+} __attribute__ ((packed));
+
+struct psb_intel_sdvo_pixel_clock_range {
+	u16 min;		/**< pixel clock, in 10kHz units */
+	u16 max;		/**< pixel clock, in 10kHz units */
+} __attribute__ ((packed));
+
+struct psb_intel_sdvo_preferred_input_timing_args {
+	u16 clock;
+	u16 width;
+	u16 height;
+} __attribute__ ((packed));
+
+/* I2C registers for SDVO */
+#define SDVO_I2C_ARG_0				0x07
+#define SDVO_I2C_ARG_1				0x06
+#define SDVO_I2C_ARG_2				0x05
+#define SDVO_I2C_ARG_3				0x04
+#define SDVO_I2C_ARG_4				0x03
+#define SDVO_I2C_ARG_5				0x02
+#define SDVO_I2C_ARG_6				0x01
+#define SDVO_I2C_ARG_7				0x00
+#define SDVO_I2C_OPCODE				0x08
+#define SDVO_I2C_CMD_STATUS			0x09
+#define SDVO_I2C_RETURN_0			0x0a
+#define SDVO_I2C_RETURN_1			0x0b
+#define SDVO_I2C_RETURN_2			0x0c
+#define SDVO_I2C_RETURN_3			0x0d
+#define SDVO_I2C_RETURN_4			0x0e
+#define SDVO_I2C_RETURN_5			0x0f
+#define SDVO_I2C_RETURN_6			0x10
+#define SDVO_I2C_RETURN_7			0x11
+#define SDVO_I2C_VENDOR_BEGIN			0x20
+
+/* Status results */
+#define SDVO_CMD_STATUS_POWER_ON		0x0
+#define SDVO_CMD_STATUS_SUCCESS			0x1
+#define SDVO_CMD_STATUS_NOTSUPP			0x2
+#define SDVO_CMD_STATUS_INVALID_ARG		0x3
+#define SDVO_CMD_STATUS_PENDING			0x4
+#define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED	0x5
+#define SDVO_CMD_STATUS_SCALING_NOT_SUPP	0x6
+
+/* SDVO commands, argument/result registers */
+
+#define SDVO_CMD_RESET					0x01
+
+/** Returns a struct psb_intel_sdvo_caps */
+#define SDVO_CMD_GET_DEVICE_CAPS			0x02
+
+#define SDVO_CMD_GET_FIRMWARE_REV			0x86
+# define SDVO_DEVICE_FIRMWARE_MINOR			SDVO_I2C_RETURN_0
+# define SDVO_DEVICE_FIRMWARE_MAJOR			SDVO_I2C_RETURN_1
+# define SDVO_DEVICE_FIRMWARE_PATCH			SDVO_I2C_RETURN_2
+
+/**
+ * Reports which inputs are trained (managed to sync).
+ *
+ * Devices must have trained within 2 vsyncs of a mode change.
+ */
+#define SDVO_CMD_GET_TRAINED_INPUTS			0x03
+struct psb_intel_sdvo_get_trained_inputs_response {
+	unsigned int input0_trained:1;
+	unsigned int input1_trained:1;
+	unsigned int pad:6;
+} __attribute__ ((packed));
+
+/** Returns a struct psb_intel_sdvo_output_flags of active outputs. */
+#define SDVO_CMD_GET_ACTIVE_OUTPUTS			0x04
+
+/**
+ * Sets the current set of active outputs.
+ *
+ * Takes a struct psb_intel_sdvo_output_flags.
+ * Must be preceded by a SET_IN_OUT_MAP
+ * on multi-output devices.
+ */
+#define SDVO_CMD_SET_ACTIVE_OUTPUTS			0x05
+
+/**
+ * Returns the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Returns two struct psb_intel_sdvo_output_flags structures.
+ */
+#define SDVO_CMD_GET_IN_OUT_MAP				0x06
+
+/**
+ * Sets the current mapping of SDVO inputs to outputs on the device.
+ *
+ * Takes two struct i380_sdvo_output_flags structures.
+ */
+#define SDVO_CMD_SET_IN_OUT_MAP				0x07
+
+/**
+ * Returns a struct psb_intel_sdvo_output_flags of attached displays.
+ */
+#define SDVO_CMD_GET_ATTACHED_DISPLAYS			0x0b
+
+/**
+ * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging.
+ */
+#define SDVO_CMD_GET_HOT_PLUG_SUPPORT			0x0c
+
+/**
+ * Takes a struct psb_intel_sdvo_output_flags.
+ */
+#define SDVO_CMD_SET_ACTIVE_HOT_PLUG			0x0d
+
+/**
+ * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug
+ * interrupts enabled.
+ */
+#define SDVO_CMD_GET_ACTIVE_HOT_PLUG			0x0e
+
+#define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f
+struct psb_intel_sdvo_get_interrupt_event_source_response {
+	u16 interrupt_status;
+	unsigned int ambient_light_interrupt:1;
+	unsigned int pad:7;
+} __attribute__ ((packed));
+
+/**
+ * Selects which input is affected by future input commands.
+ *
+ * Commands affected include SET_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12],
+ * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS.
+ */
+#define SDVO_CMD_SET_TARGET_INPUT			0x10
+struct psb_intel_sdvo_set_target_input_args {
+	unsigned int target_1:1;
+	unsigned int pad:7;
+} __attribute__ ((packed));
+
+/**
+ * Takes a struct psb_intel_sdvo_output_flags of which outputs are targetted by
+ * future output commands.
+ *
+ * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
+ * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE.
+ */
+#define SDVO_CMD_SET_TARGET_OUTPUT			0x11
+
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART1		0x12
+#define SDVO_CMD_GET_INPUT_TIMINGS_PART2		0x13
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART1		0x14
+#define SDVO_CMD_SET_INPUT_TIMINGS_PART2		0x15
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1		0x16
+#define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2		0x17
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1		0x18
+#define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2		0x19
+/* Part 1 */
+# define SDVO_DTD_CLOCK_LOW				SDVO_I2C_ARG_0
+# define SDVO_DTD_CLOCK_HIGH				SDVO_I2C_ARG_1
+# define SDVO_DTD_H_ACTIVE				SDVO_I2C_ARG_2
+# define SDVO_DTD_H_BLANK				SDVO_I2C_ARG_3
+# define SDVO_DTD_H_HIGH				SDVO_I2C_ARG_4
+# define SDVO_DTD_V_ACTIVE				SDVO_I2C_ARG_5
+# define SDVO_DTD_V_BLANK				SDVO_I2C_ARG_6
+# define SDVO_DTD_V_HIGH				SDVO_I2C_ARG_7
+/* Part 2 */
+# define SDVO_DTD_HSYNC_OFF				SDVO_I2C_ARG_0
+# define SDVO_DTD_HSYNC_WIDTH				SDVO_I2C_ARG_1
+# define SDVO_DTD_VSYNC_OFF_WIDTH			SDVO_I2C_ARG_2
+# define SDVO_DTD_SYNC_OFF_WIDTH_HIGH			SDVO_I2C_ARG_3
+# define SDVO_DTD_DTD_FLAGS				SDVO_I2C_ARG_4
+# define SDVO_DTD_DTD_FLAG_INTERLACED				(1 << 7)
+# define SDVO_DTD_DTD_FLAG_STEREO_MASK				(3 << 5)
+# define SDVO_DTD_DTD_FLAG_INPUT_MASK				(3 << 3)
+# define SDVO_DTD_DTD_FLAG_SYNC_MASK				(3 << 1)
+# define SDVO_DTD_SDVO_FLAS				SDVO_I2C_ARG_5
+# define SDVO_DTD_SDVO_FLAG_STALL				(1 << 7)
+# define SDVO_DTD_SDVO_FLAG_CENTERED				(0 << 6)
+# define SDVO_DTD_SDVO_FLAG_UPPER_LEFT				(1 << 6)
+# define SDVO_DTD_SDVO_FLAG_SCALING_MASK			(3 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_NONE			(0 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SHARP			(1 << 4)
+# define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH			(2 << 4)
+# define SDVO_DTD_VSYNC_OFF_HIGH			SDVO_I2C_ARG_6
+
+/**
+ * Generates a DTD based on the given width, height, and flags.
+ *
+ * This will be supported by any device supporting scaling or interlaced
+ * modes.
+ */
+#define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING		0x1a
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW		SDVO_I2C_ARG_0
+# define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH		SDVO_I2C_ARG_1
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW		SDVO_I2C_ARG_2
+# define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH		SDVO_I2C_ARG_3
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW		SDVO_I2C_ARG_4
+# define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH	SDVO_I2C_ARG_5
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS		SDVO_I2C_ARG_6
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED		(1 << 0)
+# define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED		(1 << 1)
+
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1	0x1b
+#define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2	0x1c
+
+/** Returns a struct psb_intel_sdvo_pixel_clock_range */
+#define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE		0x1d
+/** Returns a struct psb_intel_sdvo_pixel_clock_range */
+#define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE		0x1e
+
+/** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */
+#define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS		0x1f
+
+/** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
+#define SDVO_CMD_GET_CLOCK_RATE_MULT			0x20
+/** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */
+#define SDVO_CMD_SET_CLOCK_RATE_MULT			0x21
+# define SDVO_CLOCK_RATE_MULT_1X				(1 << 0)
+# define SDVO_CLOCK_RATE_MULT_2X				(1 << 1)
+# define SDVO_CLOCK_RATE_MULT_4X				(1 << 3)
+
+#define SDVO_CMD_GET_SUPPORTED_TV_FORMATS		0x27
+
+#define SDVO_CMD_GET_TV_FORMAT				0x28
+
+#define SDVO_CMD_SET_TV_FORMAT				0x29
+
+#define SDVO_CMD_GET_SUPPORTED_POWER_STATES		0x2a
+#define SDVO_CMD_GET_ENCODER_POWER_STATE		0x2b
+#define SDVO_CMD_SET_ENCODER_POWER_STATE		0x2c
+# define SDVO_ENCODER_STATE_ON					(1 << 0)
+# define SDVO_ENCODER_STATE_STANDBY				(1 << 1)
+# define SDVO_ENCODER_STATE_SUSPEND				(1 << 2)
+# define SDVO_ENCODER_STATE_OFF					(1 << 3)
+
+#define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT		0x93
+
+#define SDVO_CMD_SET_CONTROL_BUS_SWITCH			0x7a
+# define SDVO_CONTROL_BUS_PROM				0x0
+# define SDVO_CONTROL_BUS_DDC1				0x1
+# define SDVO_CONTROL_BUS_DDC2				0x2
+# define SDVO_CONTROL_BUS_DDC3				0x3
+
+/* SDVO Bus & SDVO Inputs wiring details*/
+/* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/
+/* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/
+/* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/
+/* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/
+#define SDVOB_IN0 0x01
+#define SDVOB_IN1 0x02
+#define SDVOC_IN0 0x04
+#define SDVOC_IN1 0x08
+
+#define SDVO_DEVICE_NONE 0x00
+#define        SDVO_DEVICE_CRT 0x01
+#define        SDVO_DEVICE_TV 0x02
+#define        SDVO_DEVICE_LVDS 0x04
+#define        SDVO_DEVICE_TMDS 0x08
+
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c
new file mode 100644
index 0000000..4597c88
--- /dev/null
+++ b/drivers/staging/gma500/psb_irq.c
@@ -0,0 +1,639 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
+ * develop this driver.
+ *
+ **************************************************************************/
+/*
+ */
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+
+/*
+ * inline functions
+ */
+
+static inline u32
+psb_pipestat(int pipe)
+{
+	if (pipe == 0)
+		return PIPEASTAT;
+	if (pipe == 1)
+		return PIPEBSTAT;
+	if (pipe == 2)
+		return PIPECSTAT;
+	BUG();
+}
+
+static inline u32
+mid_pipe_event(int pipe)
+{
+	if (pipe == 0)
+		return _PSB_PIPEA_EVENT_FLAG;
+	if (pipe == 1)
+		return _MDFLD_PIPEB_EVENT_FLAG;
+	if (pipe == 2)
+		return _MDFLD_PIPEC_EVENT_FLAG;
+	BUG();
+}
+
+static inline u32
+mid_pipe_vsync(int pipe)
+{
+	if (pipe == 0)
+		return _PSB_VSYNC_PIPEA_FLAG;
+	if (pipe == 1)
+		return _PSB_VSYNC_PIPEB_FLAG;
+	if (pipe == 2)
+		return _MDFLD_PIPEC_VBLANK_FLAG;
+	BUG();
+}
+
+static inline u32
+mid_pipeconf(int pipe)
+{
+	if (pipe == 0)
+		return PIPEACONF;
+	if (pipe == 1)
+		return PIPEBCONF;
+	if (pipe == 2)
+		return PIPECCONF;
+	BUG();
+}
+
+void
+psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+	if ((dev_priv->pipestat[pipe] & mask) != mask) {
+		u32 reg = psb_pipestat(pipe);
+		dev_priv->pipestat[pipe] |= mask;
+		/* Enable the interrupt, clear any pending status */
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+			u32 writeVal = PSB_RVDC32(reg);
+			writeVal |= (mask | (mask >> 16));
+			PSB_WVDC32(writeVal, reg);
+			(void) PSB_RVDC32(reg);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+}
+
+void
+psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
+{
+	if ((dev_priv->pipestat[pipe] & mask) != 0) {
+		u32 reg = psb_pipestat(pipe);
+		dev_priv->pipestat[pipe] &= ~mask;
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+			u32 writeVal = PSB_RVDC32(reg);
+			writeVal &= ~mask;
+			PSB_WVDC32(writeVal, reg);
+			(void) PSB_RVDC32(reg);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+}
+
+void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+		u32 pipe_event = mid_pipe_event(pipe);
+		dev_priv->vdc_irq_mask |= pipe_event;
+		PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+		PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+}
+
+void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
+{
+	if (dev_priv->pipestat[pipe] == 0) {
+		if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+			u32 pipe_event = mid_pipe_event(pipe);
+			dev_priv->vdc_irq_mask &= ~pipe_event;
+			PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+			PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+			ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+		}
+	}
+}
+
+/**
+ * Display controller interrupt handler for vsync/vblank.
+ *
+ */
+static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
+{
+	drm_handle_vblank(dev, pipe);
+}
+
+
+/**
+ * Display controller interrupt handler for pipe event.
+ *
+ */
+#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
+static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+
+	uint32_t pipe_stat_val = 0;
+	uint32_t pipe_stat_reg = psb_pipestat(pipe);
+	uint32_t pipe_enable = dev_priv->pipestat[pipe];
+	uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
+	uint32_t i = 0;
+
+	spin_lock(&dev_priv->irqmask_lock);
+
+	pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
+	pipe_stat_val &= pipe_enable | pipe_status;
+	pipe_stat_val &= pipe_stat_val >> 16;
+
+	spin_unlock(&dev_priv->irqmask_lock);
+
+	/* clear the 2nd level interrupt status bits */
+	/**
+	* FIXME: shouldn't use while loop here. However, the interrupt
+	* status 'sticky' bits cannot be cleared by setting '1' to that
+	* bit once...
+	*/
+	for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) {
+		PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
+		(void) PSB_RVDC32(pipe_stat_reg);
+
+		if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
+			break;
+	}
+
+	if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
+		DRM_ERROR("%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
+			__func__, PSB_RVDC32(pipe_stat_reg));
+
+	if (pipe_stat_val & PIPE_VBLANK_STATUS)
+		mid_vblank_handler(dev, pipe);
+
+	if (pipe_stat_val & PIPE_TE_STATUS)
+		drm_handle_vblank(dev, pipe);
+}
+
+/*
+ * Display controller interrupt handler.
+ */
+static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
+{
+	if (vdc_stat & _PSB_PIPEA_EVENT_FLAG)
+		mid_pipe_event_handler(dev, 0);
+}
+
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *) arg;
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+
+	uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
+	int handled = 0;
+
+	spin_lock(&dev_priv->irqmask_lock);
+
+	vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
+
+	if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) {
+		PSB_DEBUG_IRQ("Got DISP interrupt\n");
+		dsp_int = 1;
+	}
+
+	if (vdc_stat & _PSB_IRQ_SGX_FLAG) {
+		PSB_DEBUG_IRQ("Got SGX interrupt\n");
+		sgx_int = 1;
+	}
+	if (vdc_stat & _PSB_IRQ_MSVDX_FLAG)
+		PSB_DEBUG_IRQ("Got MSVDX interrupt\n");
+
+	if (vdc_stat & _LNC_IRQ_TOPAZ_FLAG)
+		PSB_DEBUG_IRQ("Got TOPAZ interrupt\n");
+
+
+	vdc_stat &= dev_priv->vdc_irq_mask;
+	spin_unlock(&dev_priv->irqmask_lock);
+
+	if (dsp_int && ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+		psb_vdc_interrupt(dev, vdc_stat);
+		handled = 1;
+	}
+
+	if (sgx_int) {
+		/* Not expected - we have it masked, shut it up */
+		u32 s, s2;
+		s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
+		s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
+		PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
+		PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
+		/* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
+		   we may as well poll even if we add that ! */
+		handled = 1;
+	}
+
+	PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
+	(void) PSB_RVDC32(PSB_INT_IDENTITY_R);
+	DRM_READMEMORYBARRIER();
+
+	if (!handled)
+		return IRQ_NONE;
+
+	return IRQ_HANDLED;
+}
+
+void psb_irq_preinstall(struct drm_device *dev)
+{
+	psb_irq_preinstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+/**
+ * FIXME: should I remove display irq enable here??
+ */
+void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	if (hw_islands & OSPM_DISPLAY_ISLAND) {
+		if (ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+			PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+			if (dev->vblank_enabled[0])
+				dev_priv->vdc_irq_mask |=
+						_PSB_PIPEA_EVENT_FLAG;
+			if (dev->vblank_enabled[1])
+				dev_priv->vdc_irq_mask |=
+						_MDFLD_PIPEB_EVENT_FLAG;
+			if (dev->vblank_enabled[2])
+				dev_priv->vdc_irq_mask |=
+						_MDFLD_PIPEC_EVENT_FLAG;
+		}
+	}
+/* NO I DONT WANT ANY IRQS GRRR FIXMEAC */
+	if (hw_islands & OSPM_GRAPHICS_ISLAND)
+		dev_priv->vdc_irq_mask |= _PSB_IRQ_SGX_FLAG;
+/* */
+	/*This register is safe even if display island is off*/
+	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+int psb_irq_postinstall(struct drm_device *dev)
+{
+	return psb_irq_postinstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+int psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands)
+{
+
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	/*This register is safe even if display island is off*/
+	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+	if (hw_islands & OSPM_DISPLAY_ISLAND) {
+		if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) {
+			PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+
+			if (dev->vblank_enabled[0])
+				psb_enable_pipestat(dev_priv, 0,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+			else
+				psb_disable_pipestat(dev_priv, 0,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+			if (dev->vblank_enabled[1])
+					psb_enable_pipestat(dev_priv, 1,
+					    PIPE_VBLANK_INTERRUPT_ENABLE);
+			else
+				psb_disable_pipestat(dev_priv, 1,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+			if (dev->vblank_enabled[2])
+				psb_enable_pipestat(dev_priv, 2,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+			else
+				psb_disable_pipestat(dev_priv, 2,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+		}
+	}
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+	return 0;
+}
+
+void psb_irq_uninstall(struct drm_device *dev)
+{
+	psb_irq_uninstall_islands(dev, OSPM_ALL_ISLANDS);
+}
+
+void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	if (hw_islands & OSPM_DISPLAY_ISLAND) {
+		if (true/*powermgmt_is_hw_on(dev->pdev, PSB_DISPLAY_ISLAND)*/) {
+			PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
+
+			if (dev->vblank_enabled[0])
+				psb_disable_pipestat(dev_priv, 0,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+			if (dev->vblank_enabled[1])
+				psb_disable_pipestat(dev_priv, 1,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+
+			if (dev->vblank_enabled[2])
+				psb_disable_pipestat(dev_priv, 2,
+				    PIPE_VBLANK_INTERRUPT_ENABLE);
+		}
+		dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
+					  _PSB_IRQ_MSVDX_FLAG |
+					  _LNC_IRQ_TOPAZ_FLAG;
+	}
+	/*TODO: remove following code*/
+	if (hw_islands & OSPM_GRAPHICS_ISLAND)
+		dev_priv->vdc_irq_mask &= ~_PSB_IRQ_SGX_FLAG;
+
+	/*These two registers are safe even if display island is off*/
+	PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
+	PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
+
+	wmb();
+
+	/*This register is safe even if display island is off*/
+	PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+void psb_irq_turn_on_dpst(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+		(struct drm_psb_private *) dev->dev_private;
+	u32 hist_reg;
+	u32 pwm_reg;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+		PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL);
+		hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
+		PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL);
+		hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+		PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
+		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+		PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE
+						| PWM_PHASEIN_INT_ENABLE,
+							   PWM_CONTROL_LOGIC);
+		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+		psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+		hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+		PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR,
+							HISTOGRAM_INT_CONTROL);
+		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+		PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
+							PWM_CONTROL_LOGIC);
+
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+}
+
+int psb_irq_enable_dpst(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+		(struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	/* enable DPST */
+	mid_enable_pipe_event(dev_priv, 0);
+	psb_irq_turn_on_dpst(dev);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+	return 0;
+}
+
+void psb_irq_turn_off_dpst(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	u32 hist_reg;
+	u32 pwm_reg;
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+		PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
+		hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+
+		psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
+
+		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+		PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE),
+							PWM_CONTROL_LOGIC);
+		pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
+
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+}
+
+int psb_irq_disable_dpst(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	mid_disable_pipe_event(dev_priv, 0);
+	psb_irq_turn_off_dpst(dev);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+	return 0;
+}
+
+#ifdef PSB_FIXME
+static int psb_vblank_do_wait(struct drm_device *dev,
+			      unsigned int *sequence, atomic_t *counter)
+{
+	unsigned int cur_vblank;
+	int ret = 0;
+	DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
+		    (((cur_vblank = atomic_read(counter))
+		      - *sequence) <= (1 << 23)));
+	*sequence = cur_vblank;
+
+	return ret;
+}
+#endif
+
+/*
+ * It is used to enable VBLANK interrupt
+ */
+int psb_enable_vblank(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+	uint32_t reg_val = 0;
+	uint32_t pipeconf_reg = mid_pipeconf(pipe);
+
+	PSB_DEBUG_ENTRY("\n");
+
+	if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND,
+							OSPM_UHB_ONLY_IF_ON)) {
+		reg_val = REG_READ(pipeconf_reg);
+		ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+	}
+
+	if (!(reg_val & PIPEACONF_ENABLE))
+		return -EINVAL;
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	drm_psb_disable_vsync = 0;
+	mid_enable_pipe_event(dev_priv, pipe);
+	psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+
+	return 0;
+}
+
+/*
+ * It is used to disable VBLANK interrupt
+ */
+void psb_disable_vblank(struct drm_device *dev, int pipe)
+{
+	struct drm_psb_private *dev_priv =
+	    (struct drm_psb_private *) dev->dev_private;
+	unsigned long irqflags;
+
+	PSB_DEBUG_ENTRY("\n");
+
+	spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
+
+	drm_psb_disable_vsync = 1;
+	mid_disable_pipe_event(dev_priv, pipe);
+	psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
+
+	spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
+}
+
+/* Called from drm generic code, passed a 'crtc', which
+ * we use as a pipe index
+ */
+u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
+{
+	uint32_t high_frame = PIPEAFRAMEHIGH;
+	uint32_t low_frame = PIPEAFRAMEPIXEL;
+	uint32_t pipeconf_reg = PIPEACONF;
+	uint32_t reg_val = 0;
+	uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
+
+	switch (pipe) {
+	case 0:
+		break;
+	case 1:
+		high_frame = PIPEBFRAMEHIGH;
+		low_frame = PIPEBFRAMEPIXEL;
+		pipeconf_reg = PIPEBCONF;
+		break;
+	case 2:
+		high_frame = PIPECFRAMEHIGH;
+		low_frame = PIPECFRAMEPIXEL;
+		pipeconf_reg = PIPECCONF;
+		break;
+	default:
+		DRM_ERROR("%s, invalded pipe.\n", __func__);
+		return 0;
+	}
+
+	if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, false))
+		return 0;
+
+	reg_val = REG_READ(pipeconf_reg);
+
+	if (!(reg_val & PIPEACONF_ENABLE)) {
+		DRM_ERROR("trying to get vblank count for disabled pipe %d\n",
+								pipe);
+		goto psb_get_vblank_counter_exit;
+	}
+
+	/*
+	 * High & low register fields aren't synchronized, so make sure
+	 * we get a low value that's stable across two reads of the high
+	 * register.
+	 */
+	do {
+		high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+			 PIPE_FRAME_HIGH_SHIFT);
+		low =  ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
+			PIPE_FRAME_LOW_SHIFT);
+		high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
+			 PIPE_FRAME_HIGH_SHIFT);
+	} while (high1 != high2);
+
+	count = (high1 << 8) | low;
+
+psb_get_vblank_counter_exit:
+
+	ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND);
+
+	return count;
+}
+
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h
new file mode 100644
index 0000000..3e56f33
--- /dev/null
+++ b/drivers/staging/gma500/psb_irq.h
@@ -0,0 +1,49 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ **************************************************************************/
+
+#ifndef _SYSIRQ_H_
+#define _SYSIRQ_H_
+
+#include <drm/drmP.h>
+
+bool sysirq_init(struct drm_device *dev);
+void sysirq_uninit(struct drm_device *dev);
+
+void psb_irq_preinstall(struct drm_device *dev);
+int  psb_irq_postinstall(struct drm_device *dev);
+void psb_irq_uninstall(struct drm_device *dev);
+irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
+
+void psb_irq_preinstall_islands(struct drm_device *dev, int hw_islands);
+int  psb_irq_postinstall_islands(struct drm_device *dev, int hw_islands);
+void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
+
+int psb_irq_enable_dpst(struct drm_device *dev);
+int psb_irq_disable_dpst(struct drm_device *dev);
+void psb_irq_turn_on_dpst(struct drm_device *dev);
+void psb_irq_turn_off_dpst(struct drm_device *dev);
+int  psb_enable_vblank(struct drm_device *dev, int pipe);
+void psb_disable_vblank(struct drm_device *dev, int pipe);
+u32  psb_get_vblank_counter(struct drm_device *dev, int pipe);
+
+#endif //_SYSIRQ_H_
diff --git a/drivers/staging/gma500/psb_mmu.c b/drivers/staging/gma500/psb_mmu.c
new file mode 100644
index 0000000..edd0d49
--- /dev/null
+++ b/drivers/staging/gma500/psb_mmu.c
@@ -0,0 +1,919 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+
+/*
+ * Code for the SGX MMU:
+ */
+
+/*
+ * clflush on one processor only:
+ * clflush should apparently flush the cache line on all processors in an
+ * SMP system.
+ */
+
+/*
+ * kmap atomic:
+ * The usage of the slots must be completely encapsulated within a spinlock, and
+ * no other functions that may be using the locks for other purposed may be
+ * called from within the locked region.
+ * Since the slots are per processor, this will guarantee that we are the only
+ * user.
+ */
+
+/*
+ * TODO: Inserting ptes from an interrupt handler:
+ * This may be desirable for some SGX functionality where the GPU can fault in
+ * needed pages. For that, we need to make an atomic insert_pages function, that
+ * may fail.
+ * If it fails, the caller need to insert the page using a workqueue function,
+ * but on average it should be fast.
+ */
+
+struct psb_mmu_driver {
+	/* protects driver- and pd structures. Always take in read mode
+	 * before taking the page table spinlock.
+	 */
+	struct rw_semaphore sem;
+
+	/* protects page tables, directory tables and pt tables.
+	 * and pt structures.
+	 */
+	spinlock_t lock;
+
+	atomic_t needs_tlbflush;
+
+	uint8_t __iomem *register_map;
+	struct psb_mmu_pd *default_pd;
+	/*uint32_t bif_ctrl;*/
+	int has_clflush;
+	int clflush_add;
+	unsigned long clflush_mask;
+
+	struct drm_psb_private *dev_priv;
+};
+
+struct psb_mmu_pd;
+
+struct psb_mmu_pt {
+	struct psb_mmu_pd *pd;
+	uint32_t index;
+	uint32_t count;
+	struct page *p;
+	uint32_t *v;
+};
+
+struct psb_mmu_pd {
+	struct psb_mmu_driver *driver;
+	int hw_context;
+	struct psb_mmu_pt **tables;
+	struct page *p;
+	struct page *dummy_pt;
+	struct page *dummy_page;
+	uint32_t pd_mask;
+	uint32_t invalid_pde;
+	uint32_t invalid_pte;
+};
+
+static inline uint32_t psb_mmu_pt_index(uint32_t offset)
+{
+	return (offset >> PSB_PTE_SHIFT) & 0x3FF;
+}
+
+static inline uint32_t psb_mmu_pd_index(uint32_t offset)
+{
+	return offset >> PSB_PDE_SHIFT;
+}
+
+static inline void psb_clflush(void *addr)
+{
+	__asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
+}
+
+static inline void psb_mmu_clflush(struct psb_mmu_driver *driver,
+				   void *addr)
+{
+	if (!driver->has_clflush)
+		return;
+
+	mb();
+	psb_clflush(addr);
+	mb();
+}
+
+static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page)
+{
+	uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT;
+	uint32_t clflush_count = PAGE_SIZE / clflush_add;
+	int i;
+	uint8_t *clf;
+
+	clf = kmap_atomic(page, KM_USER0);
+	mb();
+	for (i = 0; i < clflush_count; ++i) {
+		psb_clflush(clf);
+		clf += clflush_add;
+	}
+	mb();
+	kunmap_atomic(clf, KM_USER0);
+}
+
+static void psb_pages_clflush(struct psb_mmu_driver *driver,
+				struct page *page[], unsigned long num_pages)
+{
+	int i;
+
+	if (!driver->has_clflush)
+		return ;
+
+	for (i = 0; i < num_pages; i++)
+		psb_page_clflush(driver, *page++);
+}
+
+static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
+				    int force)
+{
+	atomic_set(&driver->needs_tlbflush, 0);
+}
+
+static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force)
+{
+	down_write(&driver->sem);
+	psb_mmu_flush_pd_locked(driver, force);
+	up_write(&driver->sem);
+}
+
+void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot)
+{
+	if (rc_prot)
+		down_write(&driver->sem);
+	if (rc_prot)
+		up_write(&driver->sem);
+}
+
+void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context)
+{
+	/*ttm_tt_cache_flush(&pd->p, 1);*/
+	psb_pages_clflush(pd->driver, &pd->p, 1);
+	down_write(&pd->driver->sem);
+	wmb();
+	psb_mmu_flush_pd_locked(pd->driver, 1);
+	pd->hw_context = hw_context;
+	up_write(&pd->driver->sem);
+
+}
+
+static inline unsigned long psb_pd_addr_end(unsigned long addr,
+					    unsigned long end)
+{
+
+	addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK;
+	return (addr < end) ? addr : end;
+}
+
+static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type)
+{
+	uint32_t mask = PSB_PTE_VALID;
+
+	if (type & PSB_MMU_CACHED_MEMORY)
+		mask |= PSB_PTE_CACHED;
+	if (type & PSB_MMU_RO_MEMORY)
+		mask |= PSB_PTE_RO;
+	if (type & PSB_MMU_WO_MEMORY)
+		mask |= PSB_PTE_WO;
+
+	return (pfn << PAGE_SHIFT) | mask;
+}
+
+struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
+				    int trap_pagefaults, int invalid_type)
+{
+	struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL);
+	uint32_t *v;
+	int i;
+
+	if (!pd)
+		return NULL;
+
+	pd->p = alloc_page(GFP_DMA32);
+	if (!pd->p)
+		goto out_err1;
+	pd->dummy_pt = alloc_page(GFP_DMA32);
+	if (!pd->dummy_pt)
+		goto out_err2;
+	pd->dummy_page = alloc_page(GFP_DMA32);
+	if (!pd->dummy_page)
+		goto out_err3;
+
+	if (!trap_pagefaults) {
+		pd->invalid_pde =
+		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt),
+				     invalid_type);
+		pd->invalid_pte =
+		    psb_mmu_mask_pte(page_to_pfn(pd->dummy_page),
+				     invalid_type);
+	} else {
+		pd->invalid_pde = 0;
+		pd->invalid_pte = 0;
+	}
+
+	v = kmap(pd->dummy_pt);
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		v[i] = pd->invalid_pte;
+
+	kunmap(pd->dummy_pt);
+
+	v = kmap(pd->p);
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		v[i] = pd->invalid_pde;
+
+	kunmap(pd->p);
+
+	clear_page(kmap(pd->dummy_page));
+	kunmap(pd->dummy_page);
+
+	pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024);
+	if (!pd->tables)
+		goto out_err4;
+
+	pd->hw_context = -1;
+	pd->pd_mask = PSB_PTE_VALID;
+	pd->driver = driver;
+
+	return pd;
+
+out_err4:
+	__free_page(pd->dummy_page);
+out_err3:
+	__free_page(pd->dummy_pt);
+out_err2:
+	__free_page(pd->p);
+out_err1:
+	kfree(pd);
+	return NULL;
+}
+
+void psb_mmu_free_pt(struct psb_mmu_pt *pt)
+{
+	__free_page(pt->p);
+	kfree(pt);
+}
+
+void psb_mmu_free_pagedir(struct psb_mmu_pd *pd)
+{
+	struct psb_mmu_driver *driver = pd->driver;
+	struct psb_mmu_pt *pt;
+	int i;
+
+	down_write(&driver->sem);
+	if (pd->hw_context != -1)
+		psb_mmu_flush_pd_locked(driver, 1);
+
+	/* Should take the spinlock here, but we don't need to do that
+	   since we have the semaphore in write mode. */
+
+	for (i = 0; i < 1024; ++i) {
+		pt = pd->tables[i];
+		if (pt)
+			psb_mmu_free_pt(pt);
+	}
+
+	vfree(pd->tables);
+	__free_page(pd->dummy_page);
+	__free_page(pd->dummy_pt);
+	__free_page(pd->p);
+	kfree(pd);
+	up_write(&driver->sem);
+}
+
+static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
+{
+	struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL);
+	void *v;
+	uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT;
+	uint32_t clflush_count = PAGE_SIZE / clflush_add;
+	spinlock_t *lock = &pd->driver->lock;
+	uint8_t *clf;
+	uint32_t *ptes;
+	int i;
+
+	if (!pt)
+		return NULL;
+
+	pt->p = alloc_page(GFP_DMA32);
+	if (!pt->p) {
+		kfree(pt);
+		return NULL;
+	}
+
+	spin_lock(lock);
+
+	v = kmap_atomic(pt->p, KM_USER0);
+	clf = (uint8_t *) v;
+	ptes = (uint32_t *) v;
+	for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i)
+		*ptes++ = pd->invalid_pte;
+
+
+	if (pd->driver->has_clflush && pd->hw_context != -1) {
+		mb();
+		for (i = 0; i < clflush_count; ++i) {
+			psb_clflush(clf);
+			clf += clflush_add;
+		}
+		mb();
+	}
+
+	kunmap_atomic(v, KM_USER0);
+	spin_unlock(lock);
+
+	pt->count = 0;
+	pt->pd = pd;
+	pt->index = 0;
+
+	return pt;
+}
+
+struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
+					     unsigned long addr)
+{
+	uint32_t index = psb_mmu_pd_index(addr);
+	struct psb_mmu_pt *pt;
+	uint32_t *v;
+	spinlock_t *lock = &pd->driver->lock;
+
+	spin_lock(lock);
+	pt = pd->tables[index];
+	while (!pt) {
+		spin_unlock(lock);
+		pt = psb_mmu_alloc_pt(pd);
+		if (!pt)
+			return NULL;
+		spin_lock(lock);
+
+		if (pd->tables[index]) {
+			spin_unlock(lock);
+			psb_mmu_free_pt(pt);
+			spin_lock(lock);
+			pt = pd->tables[index];
+			continue;
+		}
+
+		v = kmap_atomic(pd->p, KM_USER0);
+		pd->tables[index] = pt;
+		v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask;
+		pt->index = index;
+		kunmap_atomic((void *) v, KM_USER0);
+
+		if (pd->hw_context != -1) {
+			psb_mmu_clflush(pd->driver, (void *) &v[index]);
+			atomic_set(&pd->driver->needs_tlbflush, 1);
+		}
+	}
+	pt->v = kmap_atomic(pt->p, KM_USER0);
+	return pt;
+}
+
+static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd,
+					      unsigned long addr)
+{
+	uint32_t index = psb_mmu_pd_index(addr);
+	struct psb_mmu_pt *pt;
+	spinlock_t *lock = &pd->driver->lock;
+
+	spin_lock(lock);
+	pt = pd->tables[index];
+	if (!pt) {
+		spin_unlock(lock);
+		return NULL;
+	}
+	pt->v = kmap_atomic(pt->p, KM_USER0);
+	return pt;
+}
+
+static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt)
+{
+	struct psb_mmu_pd *pd = pt->pd;
+	uint32_t *v;
+
+	kunmap_atomic(pt->v, KM_USER0);
+	if (pt->count == 0) {
+		v = kmap_atomic(pd->p, KM_USER0);
+		v[pt->index] = pd->invalid_pde;
+		pd->tables[pt->index] = NULL;
+
+		if (pd->hw_context != -1) {
+			psb_mmu_clflush(pd->driver,
+					(void *) &v[pt->index]);
+			atomic_set(&pd->driver->needs_tlbflush, 1);
+		}
+		kunmap_atomic(pt->v, KM_USER0);
+		spin_unlock(&pd->driver->lock);
+		psb_mmu_free_pt(pt);
+		return;
+	}
+	spin_unlock(&pd->driver->lock);
+}
+
+static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt,
+				   unsigned long addr, uint32_t pte)
+{
+	pt->v[psb_mmu_pt_index(addr)] = pte;
+}
+
+static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt,
+					  unsigned long addr)
+{
+	pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte;
+}
+
+#if 0
+static uint32_t psb_mmu_check_pte_locked(struct psb_mmu_pd *pd,
+					 uint32_t mmu_offset)
+{
+	uint32_t *v;
+	uint32_t pfn;
+
+	v = kmap_atomic(pd->p, KM_USER0);
+	if (!v) {
+		printk(KERN_INFO "Could not kmap pde page.\n");
+		return 0;
+	}
+	pfn = v[psb_mmu_pd_index(mmu_offset)];
+	/*      printk(KERN_INFO "pde is 0x%08x\n",pfn); */
+	kunmap_atomic(v, KM_USER0);
+	if (((pfn & 0x0F) != PSB_PTE_VALID)) {
+		printk(KERN_INFO "Strange pde at 0x%08x: 0x%08x.\n",
+		       mmu_offset, pfn);
+	}
+	v = ioremap(pfn & 0xFFFFF000, 4096);
+	if (!v) {
+		printk(KERN_INFO "Could not kmap pte page.\n");
+		return 0;
+	}
+	pfn = v[psb_mmu_pt_index(mmu_offset)];
+	/* printk(KERN_INFO "pte is 0x%08x\n",pfn); */
+	iounmap(v);
+	if (((pfn & 0x0F) != PSB_PTE_VALID)) {
+		printk(KERN_INFO "Strange pte at 0x%08x: 0x%08x.\n",
+		       mmu_offset, pfn);
+	}
+	return pfn >> PAGE_SHIFT;
+}
+
+static void psb_mmu_check_mirrored_gtt(struct psb_mmu_pd *pd,
+				       uint32_t mmu_offset,
+				       uint32_t gtt_pages)
+{
+	uint32_t start;
+	uint32_t next;
+
+	printk(KERN_INFO "Checking mirrored gtt 0x%08x %d\n",
+	       mmu_offset, gtt_pages);
+	down_read(&pd->driver->sem);
+	start = psb_mmu_check_pte_locked(pd, mmu_offset);
+	mmu_offset += PAGE_SIZE;
+	gtt_pages -= 1;
+	while (gtt_pages--) {
+		next = psb_mmu_check_pte_locked(pd, mmu_offset);
+		if (next != start + 1) {
+			printk(KERN_INFO
+			       "Ptes out of order: 0x%08x, 0x%08x.\n",
+			       start, next);
+		}
+		start = next;
+		mmu_offset += PAGE_SIZE;
+	}
+	up_read(&pd->driver->sem);
+}
+
+#endif
+
+void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd,
+			uint32_t mmu_offset, uint32_t gtt_start,
+			uint32_t gtt_pages)
+{
+	uint32_t *v;
+	uint32_t start = psb_mmu_pd_index(mmu_offset);
+	struct psb_mmu_driver *driver = pd->driver;
+	int num_pages = gtt_pages;
+
+	down_read(&driver->sem);
+	spin_lock(&driver->lock);
+
+	v = kmap_atomic(pd->p, KM_USER0);
+	v += start;
+
+	while (gtt_pages--) {
+		*v++ = gtt_start | pd->pd_mask;
+		gtt_start += PAGE_SIZE;
+	}
+
+	/*ttm_tt_cache_flush(&pd->p, num_pages);*/
+	psb_pages_clflush(pd->driver, &pd->p, num_pages);
+	kunmap_atomic(v, KM_USER0);
+	spin_unlock(&driver->lock);
+
+	if (pd->hw_context != -1)
+		atomic_set(&pd->driver->needs_tlbflush, 1);
+
+	up_read(&pd->driver->sem);
+	psb_mmu_flush_pd(pd->driver, 0);
+}
+
+struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
+{
+	struct psb_mmu_pd *pd;
+
+	/* down_read(&driver->sem); */
+	pd = driver->default_pd;
+	/* up_read(&driver->sem); */
+
+	return pd;
+}
+
+/* Returns the physical address of the PD shared by sgx/msvdx */
+uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
+{
+	struct psb_mmu_pd *pd;
+
+	pd = psb_mmu_get_default_pd(driver);
+	return page_to_pfn(pd->p) << PAGE_SHIFT;
+}
+
+void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
+{
+	psb_mmu_free_pagedir(driver->default_pd);
+	kfree(driver);
+}
+
+struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
+					int trap_pagefaults,
+					int invalid_type,
+					struct drm_psb_private *dev_priv)
+{
+	struct psb_mmu_driver *driver;
+
+	driver = kmalloc(sizeof(*driver), GFP_KERNEL);
+
+	if (!driver)
+		return NULL;
+	driver->dev_priv = dev_priv;
+
+	driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults,
+					      invalid_type);
+	if (!driver->default_pd)
+		goto out_err1;
+
+	spin_lock_init(&driver->lock);
+	init_rwsem(&driver->sem);
+	down_write(&driver->sem);
+	driver->register_map = registers;
+	atomic_set(&driver->needs_tlbflush, 1);
+
+	driver->has_clflush = 0;
+
+	if (boot_cpu_has(X86_FEATURE_CLFLSH)) {
+		uint32_t tfms, misc, cap0, cap4, clflush_size;
+
+		/*
+		 * clflush size is determined at kernel setup for x86_64
+		 *  but not for i386. We have to do it here.
+		 */
+
+		cpuid(0x00000001, &tfms, &misc, &cap0, &cap4);
+		clflush_size = ((misc >> 8) & 0xff) * 8;
+		driver->has_clflush = 1;
+		driver->clflush_add =
+		    PAGE_SIZE * clflush_size / sizeof(uint32_t);
+		driver->clflush_mask = driver->clflush_add - 1;
+		driver->clflush_mask = ~driver->clflush_mask;
+	}
+
+	up_write(&driver->sem);
+	return driver;
+
+out_err1:
+	kfree(driver);
+	return NULL;
+}
+
+static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd,
+			       unsigned long address, uint32_t num_pages,
+			       uint32_t desired_tile_stride,
+			       uint32_t hw_tile_stride)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long clflush_add = pd->driver->clflush_add;
+	unsigned long clflush_mask = pd->driver->clflush_mask;
+
+	if (!pd->driver->has_clflush) {
+		/*ttm_tt_cache_flush(&pd->p, num_pages);*/
+		psb_pages_clflush(pd->driver, &pd->p, num_pages);
+		return;
+	}
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+	mb();
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_map_lock(pd, addr);
+			if (!pt)
+				continue;
+			do {
+				psb_clflush(&pt->v
+					    [psb_mmu_pt_index(addr)]);
+			} while (addr +=
+				 clflush_add,
+				 (addr & clflush_mask) < next);
+
+			psb_mmu_pt_unmap_unlock(pt);
+		} while (addr = next, next != end);
+		address += row_add;
+	}
+	mb();
+}
+
+void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
+				 unsigned long address, uint32_t num_pages)
+{
+	struct psb_mmu_pt *pt;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long f_address = address;
+
+	down_read(&pd->driver->sem);
+
+	addr = address;
+	end = addr + (num_pages << PAGE_SHIFT);
+
+	do {
+		next = psb_pd_addr_end(addr, end);
+		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+		if (!pt)
+			goto out;
+		do {
+			psb_mmu_invalidate_pte(pt, addr);
+			--pt->count;
+		} while (addr += PAGE_SIZE, addr < next);
+		psb_mmu_pt_unmap_unlock(pt);
+
+	} while (addr = next, next != end);
+
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 0);
+
+	return;
+}
+
+void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address,
+			  uint32_t num_pages, uint32_t desired_tile_stride,
+			  uint32_t hw_tile_stride)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long f_address = address;
+
+	if (hw_tile_stride)
+		rows = num_pages / desired_tile_stride;
+	else
+		desired_tile_stride = num_pages;
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+
+	/* down_read(&pd->driver->sem); */
+
+	/* Make sure we only need to flush this processor's cache */
+
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_map_lock(pd, addr);
+			if (!pt)
+				continue;
+			do {
+				psb_mmu_invalidate_pte(pt, addr);
+				--pt->count;
+
+			} while (addr += PAGE_SIZE, addr < next);
+			psb_mmu_pt_unmap_unlock(pt);
+
+		} while (addr = next, next != end);
+		address += row_add;
+	}
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages,
+				   desired_tile_stride, hw_tile_stride);
+
+	/* up_read(&pd->driver->sem); */
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 0);
+}
+
+int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn,
+				unsigned long address, uint32_t num_pages,
+				int type)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t pte;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long f_address = address;
+	int ret = 0;
+
+	down_read(&pd->driver->sem);
+
+	addr = address;
+	end = addr + (num_pages << PAGE_SHIFT);
+
+	do {
+		next = psb_pd_addr_end(addr, end);
+		pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+		if (!pt) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		do {
+			pte = psb_mmu_mask_pte(start_pfn++, type);
+			psb_mmu_set_pte(pt, addr, pte);
+			pt->count++;
+		} while (addr += PAGE_SIZE, addr < next);
+		psb_mmu_pt_unmap_unlock(pt);
+
+	} while (addr = next, next != end);
+
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 1);
+
+	return ret;
+}
+
+int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
+			 unsigned long address, uint32_t num_pages,
+			 uint32_t desired_tile_stride,
+			 uint32_t hw_tile_stride, int type)
+{
+	struct psb_mmu_pt *pt;
+	uint32_t rows = 1;
+	uint32_t i;
+	uint32_t pte;
+	unsigned long addr;
+	unsigned long end;
+	unsigned long next;
+	unsigned long add;
+	unsigned long row_add;
+	unsigned long f_address = address;
+	int ret = 0;
+
+	if (hw_tile_stride) {
+		if (num_pages % desired_tile_stride != 0)
+			return -EINVAL;
+		rows = num_pages / desired_tile_stride;
+	} else {
+		desired_tile_stride = num_pages;
+	}
+
+	add = desired_tile_stride << PAGE_SHIFT;
+	row_add = hw_tile_stride << PAGE_SHIFT;
+
+	down_read(&pd->driver->sem);
+
+	for (i = 0; i < rows; ++i) {
+
+		addr = address;
+		end = addr + add;
+
+		do {
+			next = psb_pd_addr_end(addr, end);
+			pt = psb_mmu_pt_alloc_map_lock(pd, addr);
+			if (!pt) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			do {
+				pte =
+				    psb_mmu_mask_pte(page_to_pfn(*pages++),
+						     type);
+				psb_mmu_set_pte(pt, addr, pte);
+				pt->count++;
+			} while (addr += PAGE_SIZE, addr < next);
+			psb_mmu_pt_unmap_unlock(pt);
+
+		} while (addr = next, next != end);
+
+		address += row_add;
+	}
+out:
+	if (pd->hw_context != -1)
+		psb_mmu_flush_ptes(pd, f_address, num_pages,
+				   desired_tile_stride, hw_tile_stride);
+
+	up_read(&pd->driver->sem);
+
+	if (pd->hw_context != -1)
+		psb_mmu_flush(pd->driver, 1);
+
+	return ret;
+}
+
+int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
+			   unsigned long *pfn)
+{
+	int ret;
+	struct psb_mmu_pt *pt;
+	uint32_t tmp;
+	spinlock_t *lock = &pd->driver->lock;
+
+	down_read(&pd->driver->sem);
+	pt = psb_mmu_pt_map_lock(pd, virtual);
+	if (!pt) {
+		uint32_t *v;
+
+		spin_lock(lock);
+		v = kmap_atomic(pd->p, KM_USER0);
+		tmp = v[psb_mmu_pd_index(virtual)];
+		kunmap_atomic(v, KM_USER0);
+		spin_unlock(lock);
+
+		if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) ||
+		    !(pd->invalid_pte & PSB_PTE_VALID)) {
+			ret = -EINVAL;
+			goto out;
+		}
+		ret = 0;
+		*pfn = pd->invalid_pte >> PAGE_SHIFT;
+		goto out;
+	}
+	tmp = pt->v[psb_mmu_pt_index(virtual)];
+	if (!(tmp & PSB_PTE_VALID)) {
+		ret = -EINVAL;
+	} else {
+		ret = 0;
+		*pfn = tmp >> PAGE_SHIFT;
+	}
+	psb_mmu_pt_unmap_unlock(pt);
+out:
+	up_read(&pd->driver->sem);
+	return ret;
+}
diff --git a/drivers/staging/gma500/psb_powermgmt.c b/drivers/staging/gma500/psb_powermgmt.c
new file mode 100644
index 0000000..7deb1ba
--- /dev/null
+++ b/drivers/staging/gma500/psb_powermgmt.c
@@ -0,0 +1,792 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#include "psb_powermgmt.h"
+#include "psb_drv.h"
+#include "psb_intel_reg.h"
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+
+#undef OSPM_GFX_DPK
+
+extern u32 gui32SGXDeviceID;
+extern u32 gui32MRSTDisplayDeviceID;
+extern u32 gui32MRSTMSVDXDeviceID;
+extern u32 gui32MRSTTOPAZDeviceID;
+
+struct drm_device *gpDrmDevice = NULL;
+static struct mutex power_mutex;
+static bool gbSuspendInProgress = false;
+static bool gbResumeInProgress = false;
+static int g_hw_power_status_mask;
+static atomic_t g_display_access_count;
+static atomic_t g_graphics_access_count;
+static atomic_t g_videoenc_access_count;
+static atomic_t g_videodec_access_count;
+int allow_runtime_pm = 0;
+
+void ospm_power_island_up(int hw_islands);
+void ospm_power_island_down(int hw_islands);
+static bool gbSuspended = false;
+bool gbgfxsuspended = false;
+
+/*
+ * ospm_power_init
+ *
+ * Description: Initialize this ospm power management module
+ */
+void ospm_power_init(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private;
+
+	gpDrmDevice = dev;
+
+	dev_priv->apm_base = dev_priv->apm_reg & 0xffff;
+	dev_priv->ospm_base &= 0xffff;
+
+	mutex_init(&power_mutex);
+	g_hw_power_status_mask = OSPM_ALL_ISLANDS;
+	atomic_set(&g_display_access_count, 0);
+	atomic_set(&g_graphics_access_count, 0);
+	atomic_set(&g_videoenc_access_count, 0);
+	atomic_set(&g_videodec_access_count, 0);
+}
+
+/*
+ * ospm_power_uninit
+ *
+ * Description: Uninitialize this ospm power management module
+ */
+void ospm_power_uninit(void)
+{
+	mutex_destroy(&power_mutex);
+    	pm_runtime_disable(&gpDrmDevice->pdev->dev);
+	pm_runtime_set_suspended(&gpDrmDevice->pdev->dev);
+}
+
+
+/*
+ * save_display_registers
+ *
+ * Description: We are going to suspend so save current display
+ * register state.
+ */
+static int save_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc * crtc;
+	struct drm_connector * connector;
+
+	/* Display arbitration control + watermarks */
+	dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
+	dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
+	dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
+	dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
+	dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
+	dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
+	dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
+	dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
+
+	/*save crtc and output state*/
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if(drm_helper_crtc_in_use(crtc)) {
+			crtc->funcs->save(crtc);
+		}
+	}
+
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		connector->funcs->save(connector);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+
+	/* Interrupt state */
+	/*
+	 * Handled in psb_irq.c
+	 */
+
+	return 0;
+}
+
+/*
+ * restore_display_registers
+ *
+ * Description: We are going to resume so restore display register state.
+ */
+static int restore_display_registers(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct drm_crtc * crtc;
+	struct drm_connector * connector;
+
+	/* Display arbitration + watermarks */
+	PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
+	PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
+	PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
+	PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
+	PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
+	PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
+	PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
+	PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
+
+	/*make sure VGA plane is off. it initializes to on after reset!*/
+	PSB_WVDC32(0x80000000, VGACNTRL);
+
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if(drm_helper_crtc_in_use(crtc))
+			crtc->funcs->restore(crtc);
+	}
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+		connector->funcs->restore(connector);
+	}
+	mutex_unlock(&dev->mode_config.mutex);
+
+	/*Interrupt state*/
+	/*
+	 * Handled in psb_irq.c
+	 */
+
+	return 0;
+}
+/*
+ * powermgmt_suspend_display
+ *
+ * Description: Suspend the display hardware saving state and disabling
+ * as necessary.
+ */
+void ospm_suspend_display(struct drm_device *dev)
+{
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int pp_stat, ret=0;
+
+	printk(KERN_ALERT "%s \n", __func__);
+
+#ifdef OSPM_GFX_DPK
+	printk(KERN_ALERT "%s \n", __func__);
+#endif
+	if (!(g_hw_power_status_mask & OSPM_DISPLAY_ISLAND))
+		return;
+
+	save_display_registers(dev);
+
+	if (dev_priv->iLVDS_enable) {
+		/*shutdown the panel*/
+		PSB_WVDC32(0, PP_CONTROL);
+
+		do {
+			pp_stat = PSB_RVDC32(PP_STATUS);
+		} while (pp_stat & 0x80000000);
+
+		/*turn off the plane*/
+		PSB_WVDC32(0x58000000, DSPACNTR);
+		PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
+		/*wait ~4 ticks*/
+		msleep(4);
+
+		/*turn off pipe*/
+		PSB_WVDC32(0x0, PIPEACONF);
+		/*wait ~8 ticks*/
+		msleep(8);
+
+		/*turn off PLLs*/
+		PSB_WVDC32(0, MRST_DPLL_A);
+	} else {
+		PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
+		PSB_WVDC32(0x0, PIPEACONF);
+		PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
+		while (REG_READ(0x70008) & 0x40000000);
+		while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
+			!= DPI_FIFO_EMPTY);
+		PSB_WVDC32(0, DEVICE_READY_REG);
+			/* turn off panel power */
+		ret = 0;
+	}
+	ospm_power_island_down(OSPM_DISPLAY_ISLAND);
+}
+
+/*
+ * ospm_resume_display
+ *
+ * Description: Resume the display hardware restoring state and enabling
+ * as necessary.
+ */
+void ospm_resume_display(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	struct psb_gtt *pg = dev_priv->pg;
+
+	printk(KERN_ALERT "%s \n", __func__);
+
+#ifdef OSPM_GFX_DPK
+	printk(KERN_ALERT "%s \n", __func__);
+#endif
+	if (g_hw_power_status_mask & OSPM_DISPLAY_ISLAND)
+		return;
+
+	/* turn on the display power island */
+	ospm_power_island_up(OSPM_DISPLAY_ISLAND);
+
+	PSB_WVDC32(pg->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
+	pci_write_config_word(pdev, PSB_GMCH_CTRL,
+			pg->gmch_ctrl | _PSB_GMCH_ENABLED);
+
+	/* Don't reinitialize the GTT as it is unnecessary.  The gtt is
+	 * stored in memory so it will automatically be restored.  All
+	 * we need to do is restore the PGETBL_CTL which we already do
+	 * above.
+	 */
+	/*psb_gtt_init(dev_priv->pg, 1);*/
+
+	restore_display_registers(dev);
+}
+
+#if 1
+/*
+ * ospm_suspend_pci
+ *
+ * Description: Suspend the pci device saving state and disabling
+ * as necessary.
+ */
+static void ospm_suspend_pci(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int bsm, vbt;
+
+	if (gbSuspended)
+		return;
+
+#ifdef OSPM_GFX_DPK
+	printk(KERN_ALERT "ospm_suspend_pci\n");
+#endif
+
+	pci_save_state(pdev);
+	pci_read_config_dword(pdev, 0x5C, &bsm);
+	dev_priv->saveBSM = bsm;
+	pci_read_config_dword(pdev, 0xFC, &vbt);
+	dev_priv->saveVBT = vbt;
+	pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
+	pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	gbSuspended = true;
+	gbgfxsuspended = true;
+}
+
+/*
+ * ospm_resume_pci
+ *
+ * Description: Resume the pci device restoring state and enabling
+ * as necessary.
+ */
+static bool ospm_resume_pci(struct pci_dev *pdev)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct drm_psb_private *dev_priv = dev->dev_private;
+	int ret = 0;
+
+	if (!gbSuspended)
+		return true;
+
+#ifdef OSPM_GFX_DPK
+	printk(KERN_ALERT "ospm_resume_pci\n");
+#endif
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
+	pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
+	/* retoring MSI address and data in PCIx space */
+	pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
+	pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
+	ret = pci_enable_device(pdev);
+
+	if (ret != 0)
+		printk(KERN_ALERT "ospm_resume_pci: pci_enable_device failed: %d\n", ret);
+	else
+		gbSuspended = false;
+
+	return !gbSuspended;
+}
+#endif
+/*
+ * ospm_power_suspend
+ *
+ * Description: OSPM is telling our driver to suspend so save state
+ * and power down all hardware.
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+        int ret = 0;
+        int graphics_access_count;
+        int videoenc_access_count;
+        int videodec_access_count;
+        int display_access_count;
+    	bool suspend_pci = true;
+
+	if(gbSuspendInProgress || gbResumeInProgress)
+        {
+#ifdef OSPM_GFX_DPK
+                printk(KERN_ALERT "OSPM_GFX_DPK: %s system BUSY \n", __func__);
+#endif
+                return  -EBUSY;
+        }
+
+        mutex_lock(&power_mutex);
+
+        if (!gbSuspended) {
+                graphics_access_count = atomic_read(&g_graphics_access_count);
+                videoenc_access_count = atomic_read(&g_videoenc_access_count);
+                videodec_access_count = atomic_read(&g_videodec_access_count);
+                display_access_count = atomic_read(&g_display_access_count);
+
+                if (graphics_access_count ||
+			videoenc_access_count ||
+			videodec_access_count ||
+			display_access_count)
+                        ret = -EBUSY;
+
+                if (!ret) {
+                        gbSuspendInProgress = true;
+
+                        psb_irq_uninstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+                        ospm_suspend_display(gpDrmDevice);
+                        if (suspend_pci == true) {
+				ospm_suspend_pci(pdev);
+                        }
+                        gbSuspendInProgress = false;
+                } else {
+                        printk(KERN_ALERT "ospm_power_suspend: device busy: graphics %d videoenc %d videodec %d display %d\n", graphics_access_count, videoenc_access_count, videodec_access_count, display_access_count);
+                }
+        }
+
+
+        mutex_unlock(&power_mutex);
+        return ret;
+}
+
+/*
+ * ospm_power_island_up
+ *
+ * Description: Restore power to the specified island(s) (powergating)
+ */
+void ospm_power_island_up(int hw_islands)
+{
+	u32 pwr_cnt = 0;
+	u32 pwr_sts = 0;
+	u32 pwr_mask = 0;
+
+	struct drm_psb_private *dev_priv =
+		(struct drm_psb_private *) gpDrmDevice->dev_private;
+
+
+	if (hw_islands & OSPM_DISPLAY_ISLAND) {
+		pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+
+		pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+		pwr_cnt &= ~pwr_mask;
+		outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
+
+		while (true) {
+			pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+			if ((pwr_sts & pwr_mask) == 0)
+				break;
+			else
+				udelay(10);
+		}
+	}
+
+	g_hw_power_status_mask |= hw_islands;
+}
+
+/*
+ * ospm_power_resume
+ */
+int ospm_power_resume(struct pci_dev *pdev)
+{
+	if(gbSuspendInProgress || gbResumeInProgress)
+        {
+#ifdef OSPM_GFX_DPK
+                printk(KERN_ALERT "OSPM_GFX_DPK: %s hw_island: Suspend || gbResumeInProgress!!!! \n", __func__);
+#endif
+                return 0;
+        }
+
+        mutex_lock(&power_mutex);
+
+#ifdef OSPM_GFX_DPK
+	printk(KERN_ALERT "OSPM_GFX_DPK: ospm_power_resume \n");
+#endif
+
+  	gbResumeInProgress = true;
+
+        ospm_resume_pci(pdev);
+
+	ospm_resume_display(gpDrmDevice->pdev);
+        psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+        psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+
+	gbResumeInProgress = false;
+
+        mutex_unlock(&power_mutex);
+
+	return 0;
+}
+
+
+/*
+ * ospm_power_island_down
+ *
+ * Description: Cut power to the specified island(s) (powergating)
+ */
+void ospm_power_island_down(int islands)
+{
+#if 0
+	u32 pwr_cnt = 0;
+	u32 pwr_mask = 0;
+	u32 pwr_sts = 0;
+
+	struct drm_psb_private *dev_priv =
+		(struct drm_psb_private *) gpDrmDevice->dev_private;
+
+	g_hw_power_status_mask &= ~islands;
+
+	if (islands & OSPM_GRAPHICS_ISLAND) {
+		pwr_cnt |= PSB_PWRGT_GFX_MASK;
+		pwr_mask |= PSB_PWRGT_GFX_MASK;
+		if (dev_priv->graphics_state == PSB_PWR_STATE_ON) {
+			dev_priv->gfx_on_time += (jiffies - dev_priv->gfx_last_mode_change) * 1000 / HZ;
+			dev_priv->gfx_last_mode_change = jiffies;
+			dev_priv->graphics_state = PSB_PWR_STATE_OFF;
+			dev_priv->gfx_off_cnt++;
+		}
+	}
+	if (islands & OSPM_VIDEO_ENC_ISLAND) {
+		pwr_cnt |= PSB_PWRGT_VID_ENC_MASK;
+		pwr_mask |= PSB_PWRGT_VID_ENC_MASK;
+	}
+	if (islands & OSPM_VIDEO_DEC_ISLAND) {
+		pwr_cnt |= PSB_PWRGT_VID_DEC_MASK;
+		pwr_mask |= PSB_PWRGT_VID_DEC_MASK;
+	}
+	if (pwr_cnt) {
+		pwr_cnt |= inl(dev_priv->apm_base);
+		outl(pwr_cnt, dev_priv->apm_base  + PSB_APM_CMD);
+		while (true) {
+			pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
+
+			if ((pwr_sts & pwr_mask) == pwr_mask)
+				break;
+			else
+				udelay(10);
+		}
+	}
+
+	if (islands & OSPM_DISPLAY_ISLAND) {
+		pwr_mask = PSB_PWRGT_DISPLAY_MASK;
+
+		outl(pwr_mask, (dev_priv->ospm_base + PSB_PM_SSC));
+
+		while (true) {
+			pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
+			if ((pwr_sts & pwr_mask) == pwr_mask)
+				break;
+			else
+				udelay(10);
+		}
+	}
+#endif
+}
+
+
+/*
+ * ospm_power_is_hw_on
+ *
+ * Description: do an instantaneous check for if the specified islands
+ * are on.  Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall.  Otherwise, use
+ * ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands)
+{
+	return ((g_hw_power_status_mask & hw_islands) == hw_islands) ? true:false;
+}
+
+/*
+ * ospm_power_using_hw_begin
+ *
+ * Description: Notify PowerMgmt module that you will be accessing the
+ * specified island's hw so don't power it off.  If force_on is true,
+ * this will power on the specified island if it is off.
+ * Otherwise, this will return false and the caller is expected to not
+ * access the hw.
+ *
+ * NOTE *** If this is called from and interrupt handler or other atomic
+ * context, then it will return false if we are in the middle of a
+ * power state transition and the caller will be expected to handle that
+ * even if force_on is set to true.
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage)
+{
+        return 1;	/*FIXMEAC */
+#if 0
+	bool ret = true;
+	bool island_is_off = false;
+	bool b_atomic = (in_interrupt() || in_atomic());
+	bool locked = true;
+	struct pci_dev *pdev = gpDrmDevice->pdev;
+	u32 deviceID = 0;
+	bool force_on = usage ? true: false;
+	/*quick path, not 100% race safe, but should be enough comapre to current other code in this file */
+	if (!force_on) {
+		if (hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask))
+			return false;
+		else {
+			locked = false;
+#ifdef CONFIG_PM_RUNTIME
+			/* increment pm_runtime_refcount */
+			pm_runtime_get(&pdev->dev);
+#endif
+			goto increase_count;
+		}
+	}
+
+
+	if (!b_atomic)
+		mutex_lock(&power_mutex);
+
+	island_is_off = hw_island & (OSPM_ALL_ISLANDS & ~g_hw_power_status_mask);
+
+	if (b_atomic && (gbSuspendInProgress || gbResumeInProgress || gbSuspended) && force_on && island_is_off)
+		ret = false;
+
+	if (ret && island_is_off && !force_on)
+		ret = false;
+
+	if (ret && island_is_off && force_on) {
+		gbResumeInProgress = true;
+
+		ret = ospm_resume_pci(pdev);
+
+		if (ret) {
+			switch(hw_island)
+			{
+			case OSPM_DISPLAY_ISLAND:
+				deviceID = gui32MRSTDisplayDeviceID;
+				ospm_resume_display(pdev);
+				psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+				psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+				break;
+			case OSPM_GRAPHICS_ISLAND:
+				deviceID = gui32SGXDeviceID;
+				ospm_power_island_up(OSPM_GRAPHICS_ISLAND);
+				psb_irq_preinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+				psb_irq_postinstall_islands(gpDrmDevice, OSPM_GRAPHICS_ISLAND);
+				break;
+#if 1
+			case OSPM_VIDEO_DEC_ISLAND:
+				if(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+					//printk(KERN_ALERT "%s power on display for video decode use\n", __func__);
+					deviceID = gui32MRSTDisplayDeviceID;
+					ospm_resume_display(pdev);
+					psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+					psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+				}
+				else{
+					//printk(KERN_ALERT "%s display is already on for video decode use\n", __func__);
+				}
+
+				if(!ospm_power_is_hw_on(OSPM_VIDEO_DEC_ISLAND)) {
+					//printk(KERN_ALERT "%s power on video decode\n", __func__);
+					deviceID = gui32MRSTMSVDXDeviceID;
+					ospm_power_island_up(OSPM_VIDEO_DEC_ISLAND);
+					psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+					psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_DEC_ISLAND);
+				}
+				else{
+					//printk(KERN_ALERT "%s video decode is already on\n", __func__);
+				}
+
+				break;
+			case OSPM_VIDEO_ENC_ISLAND:
+				if(!ospm_power_is_hw_on(OSPM_DISPLAY_ISLAND)) {
+					//printk(KERN_ALERT "%s power on display for video encode\n", __func__);
+					deviceID = gui32MRSTDisplayDeviceID;
+					ospm_resume_display(pdev);
+					psb_irq_preinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+					psb_irq_postinstall_islands(gpDrmDevice, OSPM_DISPLAY_ISLAND);
+				}
+				else{
+					//printk(KERN_ALERT "%s display is already on for video encode use\n", __func__);
+				}
+
+				if(!ospm_power_is_hw_on(OSPM_VIDEO_ENC_ISLAND)) {
+					//printk(KERN_ALERT "%s power on video encode\n", __func__);
+					deviceID = gui32MRSTTOPAZDeviceID;
+					ospm_power_island_up(OSPM_VIDEO_ENC_ISLAND);
+					psb_irq_preinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+					psb_irq_postinstall_islands(gpDrmDevice, OSPM_VIDEO_ENC_ISLAND);
+				}
+				else{
+					//printk(KERN_ALERT "%s video decode is already on\n", __func__);
+				}
+#endif
+				break;
+
+			default:
+				printk(KERN_ALERT "%s unknown island !!!! \n", __func__);
+				break;
+			}
+
+		}
+
+		if (!ret)
+			printk(KERN_ALERT "ospm_power_using_hw_begin: forcing on %d failed\n", hw_island);
+
+		gbResumeInProgress = false;
+	}
+increase_count:
+	if (ret) {
+		switch(hw_island)
+		{
+		case OSPM_GRAPHICS_ISLAND:
+			atomic_inc(&g_graphics_access_count);
+			break;
+		case OSPM_VIDEO_ENC_ISLAND:
+			atomic_inc(&g_videoenc_access_count);
+			break;
+		case OSPM_VIDEO_DEC_ISLAND:
+			atomic_inc(&g_videodec_access_count);
+			break;
+		case OSPM_DISPLAY_ISLAND:
+			atomic_inc(&g_display_access_count);
+			break;
+		}
+	}
+
+	if (!b_atomic && locked)
+		mutex_unlock(&power_mutex);
+
+	return ret;
+#endif
+}
+
+
+/*
+ * ospm_power_using_hw_end
+ *
+ * Description: Notify PowerMgmt module that you are done accessing the
+ * specified island's hw so feel free to power it off.  Note that this
+ * function doesn't actually power off the islands.
+ */
+void ospm_power_using_hw_end(int hw_island)
+{
+#if 0 /* FIXMEAC */
+	switch(hw_island)
+	{
+	case OSPM_GRAPHICS_ISLAND:
+		atomic_dec(&g_graphics_access_count);
+		break;
+	case OSPM_VIDEO_ENC_ISLAND:
+		atomic_dec(&g_videoenc_access_count);
+		break;
+	case OSPM_VIDEO_DEC_ISLAND:
+		atomic_dec(&g_videodec_access_count);
+		break;
+	case OSPM_DISPLAY_ISLAND:
+		atomic_dec(&g_display_access_count);
+		break;
+	}
+
+	//decrement runtime pm ref count
+	pm_runtime_put(&gpDrmDevice->pdev->dev);
+
+	WARN_ON(atomic_read(&g_graphics_access_count) < 0);
+	WARN_ON(atomic_read(&g_videoenc_access_count) < 0);
+	WARN_ON(atomic_read(&g_videodec_access_count) < 0);
+	WARN_ON(atomic_read(&g_display_access_count) < 0);
+#endif
+}
+
+int ospm_runtime_pm_allow(struct drm_device * dev)
+{
+	return 0;
+}
+
+void ospm_runtime_pm_forbid(struct drm_device * dev)
+{
+	struct drm_psb_private * dev_priv = dev->dev_private;
+
+	DRM_INFO("%s\n", __FUNCTION__);
+
+	pm_runtime_forbid(&dev->pdev->dev);
+	dev_priv->rpm_enabled = 0;
+}
+
+int psb_runtime_suspend(struct device *dev)
+{
+	pm_message_t state;
+	int ret = 0;
+	state.event = 0;
+
+#ifdef OSPM_GFX_DPK
+	printk(KERN_ALERT "OSPM_GFX_DPK: %s \n", __func__);
+#endif
+        if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+		|| atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count)){
+#ifdef OSPM_GFX_DPK
+                printk(KERN_ALERT "OSPM_GFX_DPK: GFX: %d VEC: %d VED: %d DC: %d DSR: %d \n", atomic_read(&g_graphics_access_count),
+			atomic_read(&g_videoenc_access_count), atomic_read(&g_videodec_access_count), atomic_read(&g_display_access_count));
+#endif
+                return -EBUSY;
+        }
+        else
+		ret = ospm_power_suspend(gpDrmDevice->pdev, state);
+
+	return ret;
+}
+
+int psb_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+int psb_runtime_idle(struct device *dev)
+{
+	/*printk (KERN_ALERT "lvds:%d,mipi:%d\n", dev_priv->is_lvds_on, dev_priv->is_mipi_on);*/
+	if (atomic_read(&g_graphics_access_count) || atomic_read(&g_videoenc_access_count)
+		|| atomic_read(&g_videodec_access_count) || atomic_read(&g_display_access_count))
+		return 1;
+	else
+		return 0;
+}
+
diff --git a/drivers/staging/gma500/psb_powermgmt.h b/drivers/staging/gma500/psb_powermgmt.h
new file mode 100644
index 0000000..bf6f27a
--- /dev/null
+++ b/drivers/staging/gma500/psb_powermgmt.h
@@ -0,0 +1,96 @@
+/**************************************************************************
+ * Copyright (c) 2009, Intel Corporation.
+ * All Rights Reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Benjamin Defnet <benjamin.r.defnet@intel.com>
+ *    Rajesh Poornachandran <rajesh.poornachandran@intel.com>
+ *
+ */
+#ifndef _PSB_POWERMGMT_H_
+#define _PSB_POWERMGMT_H_
+
+#include <linux/pci.h>
+#include <drm/drmP.h>
+
+#define OSPM_GRAPHICS_ISLAND	0x1
+#define OSPM_VIDEO_ENC_ISLAND	0x2
+#define OSPM_VIDEO_DEC_ISLAND	0x4
+#define OSPM_DISPLAY_ISLAND	0x8
+#define OSPM_GL3_CACHE_ISLAND	0x10
+#define OSPM_ALL_ISLANDS	0x1f
+
+/* IPC message and command defines used to enable/disable mipi panel voltages */
+#define IPC_MSG_PANEL_ON_OFF    0xE9
+#define IPC_CMD_PANEL_ON        1
+#define IPC_CMD_PANEL_OFF       0
+
+typedef enum _UHBUsage
+{
+    OSPM_UHB_ONLY_IF_ON = 0,
+    OSPM_UHB_FORCE_POWER_ON,
+} UHBUsage;
+
+/* Use these functions to power down video HW for D0i3 purpose  */
+
+void ospm_power_init(struct drm_device *dev);
+void ospm_power_uninit(void);
+
+
+/*
+ * OSPM will call these functions
+ */
+int ospm_power_suspend(struct pci_dev *pdev, pm_message_t state);
+int ospm_power_resume(struct pci_dev *pdev);
+
+/*
+ * These are the functions the driver should use to wrap all hw access
+ * (i.e. register reads and writes)
+ */
+bool ospm_power_using_hw_begin(int hw_island, UHBUsage usage);
+void ospm_power_using_hw_end(int hw_island);
+
+/*
+ * Use this function to do an instantaneous check for if the hw is on.
+ * Only use this in cases where you know the g_state_change_mutex
+ * is already held such as in irq install/uninstall and you need to
+ * prevent a deadlock situation.  Otherwise use ospm_power_using_hw_begin().
+ */
+bool ospm_power_is_hw_on(int hw_islands);
+
+/*
+ * Power up/down different hw component rails/islands
+ */
+void ospm_power_island_down(int hw_islands);
+void ospm_power_island_up(int hw_islands);
+void ospm_suspend_graphics(void);
+/*
+ * GFX-Runtime PM callbacks
+ */
+int psb_runtime_suspend(struct device *dev);
+int psb_runtime_resume(struct device *dev);
+int psb_runtime_idle(struct device *dev);
+int ospm_runtime_pm_allow(struct drm_device * dev);
+void ospm_runtime_pm_forbid(struct drm_device * dev);
+
+
+#endif /*_PSB_POWERMGMT_H_*/
diff --git a/drivers/staging/gma500/psb_pvr_glue.c b/drivers/staging/gma500/psb_pvr_glue.c
new file mode 100644
index 0000000..da78946
--- /dev/null
+++ b/drivers/staging/gma500/psb_pvr_glue.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "psb_pvr_glue.h"
+
+/**
+ * FIXME: should NOT use these file under env/linux directly
+ */
+
+int psb_get_meminfo_by_handle(void *hKernelMemInfo,
+				void **ppsKernelMemInfo)
+{
+	return -EINVAL;
+#if 0
+	void *psKernelMemInfo = IMG_NULL;
+	PVRSRV_PER_PROCESS_DATA *psPerProc = IMG_NULL;
+	PVRSRV_ERROR eError;
+
+	psPerProc = PVRSRVPerProcessData(task_tgid_nr(current));
+	eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+				    (IMG_VOID *)&psKernelMemInfo,
+				    hKernelMemInfo,
+				    PVRSRV_HANDLE_TYPE_MEM_INFO);
+	if (eError != PVRSRV_OK) {
+		DRM_ERROR("Cannot find kernel meminfo for handle 0x%x\n",
+			  (u32)hKernelMemInfo);
+		return -EINVAL;
+	}
+
+	*ppsKernelMemInfo = psKernelMemInfo;
+
+	DRM_DEBUG("Got Kernel MemInfo for handle %lx\n",
+		  (u32)hKernelMemInfo);
+	return 0;
+#endif
+}
+
+int psb_get_pages_by_mem_handle(void *hOSMemHandle, struct page ***pages)
+{
+	return -EINVAL;
+#if 0
+	LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+	struct page **page_list;
+	if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_ALLOC_PAGES) {
+		DRM_ERROR("MemArea type is not LINUX_MEM_AREA_ALLOC_PAGES\n");
+		return -EINVAL;
+	}
+
+	page_list = psLinuxMemArea->uData.sPageList.pvPageList;
+	if (!page_list) {
+		DRM_DEBUG("Page List is NULL\n");
+		return -ENOMEM;
+	}
+
+	*pages = page_list;
+	return 0;
+#endif
+}
diff --git a/drivers/staging/gma500/psb_pvr_glue.h b/drivers/staging/gma500/psb_pvr_glue.h
new file mode 100644
index 0000000..dee8cb2
--- /dev/null
+++ b/drivers/staging/gma500/psb_pvr_glue.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2009, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include "psb_drv.h"
+
+extern int psb_get_meminfo_by_handle(void * hKernelMemInfo,
+				void **ppsKernelMemInfo);
+extern u32 psb_get_tgid(void);
+extern int psb_get_pages_by_mem_handle(void * hOSMemHandle,
+					struct page ***pages);
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
new file mode 100644
index 0000000..9ad4989
--- /dev/null
+++ b/drivers/staging/gma500/psb_reg.h
@@ -0,0 +1,588 @@
+/**************************************************************************
+ *
+ * Copyright (c) (2005-2007) Imagination Technologies Limited.
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA..
+ *
+ **************************************************************************/
+
+#ifndef _PSB_REG_H_
+#define _PSB_REG_H_
+
+#define PSB_CR_CLKGATECTL                0x0000
+#define _PSB_C_CLKGATECTL_AUTO_MAN_REG   (1 << 24)
+#define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20)
+#define _PSB_C_CLKGATECTL_USE_CLKG_MASK  (0x3 << 20)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16)
+#define _PSB_C_CLKGATECTL_DPM_CLKG_MASK  (0x3 << 16)
+#define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT  (12)
+#define _PSB_C_CLKGATECTL_TA_CLKG_MASK   (0x3 << 12)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8)
+#define _PSB_C_CLKGATECTL_TSP_CLKG_MASK  (0x3 << 8)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4)
+#define _PSB_C_CLKGATECTL_ISP_CLKG_MASK  (0x3 << 4)
+#define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT  (0)
+#define _PSB_C_CLKGATECTL_2D_CLKG_MASK   (0x3 << 0)
+#define _PSB_C_CLKGATECTL_CLKG_ENABLED   (0)
+#define _PSB_C_CLKGATECTL_CLKG_DISABLED  (1)
+#define _PSB_C_CLKGATECTL_CLKG_AUTO      (2)
+
+#define PSB_CR_CORE_ID                   0x0010
+#define _PSB_CC_ID_ID_SHIFT              (16)
+#define _PSB_CC_ID_ID_MASK               (0xFFFF << 16)
+#define _PSB_CC_ID_CONFIG_SHIFT          (0)
+#define _PSB_CC_ID_CONFIG_MASK           (0xFFFF << 0)
+
+#define PSB_CR_CORE_REVISION               0x0014
+#define _PSB_CC_REVISION_DESIGNER_SHIFT    (24)
+#define _PSB_CC_REVISION_DESIGNER_MASK     (0xFF << 24)
+#define _PSB_CC_REVISION_MAJOR_SHIFT       (16)
+#define _PSB_CC_REVISION_MAJOR_MASK        (0xFF << 16)
+#define _PSB_CC_REVISION_MINOR_SHIFT       (8)
+#define _PSB_CC_REVISION_MINOR_MASK        (0xFF << 8)
+#define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0)
+#define _PSB_CC_REVISION_MAINTENANCE_MASK  (0xFF << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD1       0x0018
+
+#define PSB_CR_SOFT_RESET                0x0080
+#define _PSB_CS_RESET_TSP_RESET          (1 << 6)
+#define _PSB_CS_RESET_ISP_RESET          (1 << 5)
+#define _PSB_CS_RESET_USE_RESET          (1 << 4)
+#define _PSB_CS_RESET_TA_RESET           (1 << 3)
+#define _PSB_CS_RESET_DPM_RESET          (1 << 2)
+#define _PSB_CS_RESET_TWOD_RESET         (1 << 1)
+#define _PSB_CS_RESET_BIF_RESET          (1 << 0)
+
+#define PSB_CR_DESIGNER_REV_FIELD2       0x001C
+
+#define PSB_CR_EVENT_HOST_ENABLE2        0x0110
+
+#define PSB_CR_EVENT_STATUS2             0x0118
+
+#define PSB_CR_EVENT_HOST_CLEAR2         0x0114
+#define _PSB_CE2_BIF_REQUESTER_FAULT     (1 << 4)
+
+#define PSB_CR_EVENT_STATUS              0x012C
+
+#define PSB_CR_EVENT_HOST_ENABLE         0x0130
+
+#define PSB_CR_EVENT_HOST_CLEAR          0x0134
+#define _PSB_CE_MASTER_INTERRUPT         (1 << 31)
+#define _PSB_CE_TA_DPM_FAULT             (1 << 28)
+#define _PSB_CE_TWOD_COMPLETE            (1 << 27)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS    (1 << 25)
+#define _PSB_CE_DPM_TA_MEM_FREE          (1 << 24)
+#define _PSB_CE_PIXELBE_END_RENDER       (1 << 18)
+#define _PSB_CE_SW_EVENT                 (1 << 14)
+#define _PSB_CE_TA_FINISHED              (1 << 13)
+#define _PSB_CE_TA_TERMINATE             (1 << 12)
+#define _PSB_CE_DPM_REACHED_MEM_THRESH   (1 << 3)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_GBL    (1 << 2)
+#define _PSB_CE_DPM_OUT_OF_MEMORY_MT     (1 << 1)
+#define _PSB_CE_DPM_3D_MEM_FREE          (1 << 0)
+
+
+#define PSB_USE_OFFSET_MASK              0x0007FFFF
+#define PSB_USE_OFFSET_SIZE              (PSB_USE_OFFSET_MASK + 1)
+#define PSB_CR_USE_CODE_BASE0            0x0A0C
+#define PSB_CR_USE_CODE_BASE1            0x0A10
+#define PSB_CR_USE_CODE_BASE2            0x0A14
+#define PSB_CR_USE_CODE_BASE3            0x0A18
+#define PSB_CR_USE_CODE_BASE4            0x0A1C
+#define PSB_CR_USE_CODE_BASE5            0x0A20
+#define PSB_CR_USE_CODE_BASE6            0x0A24
+#define PSB_CR_USE_CODE_BASE7            0x0A28
+#define PSB_CR_USE_CODE_BASE8            0x0A2C
+#define PSB_CR_USE_CODE_BASE9            0x0A30
+#define PSB_CR_USE_CODE_BASE10           0x0A34
+#define PSB_CR_USE_CODE_BASE11           0x0A38
+#define PSB_CR_USE_CODE_BASE12           0x0A3C
+#define PSB_CR_USE_CODE_BASE13           0x0A40
+#define PSB_CR_USE_CODE_BASE14           0x0A44
+#define PSB_CR_USE_CODE_BASE15           0x0A48
+#define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2))
+#define _PSB_CUC_BASE_DM_SHIFT           (25)
+#define _PSB_CUC_BASE_DM_MASK            (0x3 << 25)
+#define _PSB_CUC_BASE_ADDR_SHIFT         (0)	/* 1024-bit aligned address? */
+#define _PSB_CUC_BASE_ADDR_ALIGNSHIFT    (7)
+#define _PSB_CUC_BASE_ADDR_MASK          (0x1FFFFFF << 0)
+#define _PSB_CUC_DM_VERTEX		 (0)
+#define _PSB_CUC_DM_PIXEL		 (1)
+#define _PSB_CUC_DM_RESERVED		 (2)
+#define _PSB_CUC_DM_EDM	                 (3)
+
+#define PSB_CR_PDS_EXEC_BASE             0x0AB8
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20)	/* 1MB aligned address */
+#define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20)
+
+#define PSB_CR_EVENT_KICKER              0x0AC4
+#define _PSB_CE_KICKER_ADDRESS_SHIFT     (4)	/* 128-bit aligned address */
+
+#define PSB_CR_EVENT_KICK                0x0AC8
+#define _PSB_CE_KICK_NOW                 (1 << 0)
+
+
+#define PSB_CR_BIF_DIR_LIST_BASE1        0x0C38
+
+#define PSB_CR_BIF_CTRL                  0x0C00
+#define _PSB_CB_CTRL_CLEAR_FAULT         (1 << 4)
+#define _PSB_CB_CTRL_INVALDC             (1 << 3)
+#define _PSB_CB_CTRL_FLUSH               (1 << 2)
+
+#define PSB_CR_BIF_INT_STAT              0x0C04
+
+#define PSB_CR_BIF_FAULT                 0x0C08
+#define _PSB_CBI_STAT_PF_N_RW            (1 << 14)
+#define _PSB_CBI_STAT_FAULT_SHIFT        (0)
+#define _PSB_CBI_STAT_FAULT_MASK         (0x3FFF << 0)
+#define _PSB_CBI_STAT_FAULT_CACHE        (1 << 1)
+#define _PSB_CBI_STAT_FAULT_TA           (1 << 2)
+#define _PSB_CBI_STAT_FAULT_VDM          (1 << 3)
+#define _PSB_CBI_STAT_FAULT_2D           (1 << 4)
+#define _PSB_CBI_STAT_FAULT_PBE          (1 << 5)
+#define _PSB_CBI_STAT_FAULT_TSP          (1 << 6)
+#define _PSB_CBI_STAT_FAULT_ISP          (1 << 7)
+#define _PSB_CBI_STAT_FAULT_USSEPDS      (1 << 8)
+#define _PSB_CBI_STAT_FAULT_HOST         (1 << 9)
+
+#define PSB_CR_BIF_BANK0                 0x0C78
+
+#define PSB_CR_BIF_BANK1                 0x0C7C
+
+#define PSB_CR_BIF_DIR_LIST_BASE0        0x0C84
+
+#define PSB_CR_BIF_TWOD_REQ_BASE         0x0C88
+#define PSB_CR_BIF_3D_REQ_BASE           0x0CAC
+
+#define PSB_CR_2D_SOCIF                  0x0E18
+#define _PSB_C2_SOCIF_FREESPACE_SHIFT    (0)
+#define _PSB_C2_SOCIF_FREESPACE_MASK     (0xFF << 0)
+#define _PSB_C2_SOCIF_EMPTY              (0x80 << 0)
+
+#define PSB_CR_2D_BLIT_STATUS            0x0E04
+#define _PSB_C2B_STATUS_BUSY             (1 << 24)
+#define _PSB_C2B_STATUS_COMPLETE_SHIFT   (0)
+#define _PSB_C2B_STATUS_COMPLETE_MASK    (0xFFFFFF << 0)
+
+/*
+ * 2D defs.
+ */
+
+/*
+ * 2D Slave Port Data : Block Header's Object Type
+ */
+
+#define	PSB_2D_CLIP_BH                   (0x00000000)
+#define	PSB_2D_PAT_BH                    (0x10000000)
+#define	PSB_2D_CTRL_BH                   (0x20000000)
+#define	PSB_2D_SRC_OFF_BH                (0x30000000)
+#define	PSB_2D_MASK_OFF_BH               (0x40000000)
+#define	PSB_2D_RESERVED1_BH              (0x50000000)
+#define	PSB_2D_RESERVED2_BH              (0x60000000)
+#define	PSB_2D_FENCE_BH                  (0x70000000)
+#define	PSB_2D_BLIT_BH                   (0x80000000)
+#define	PSB_2D_SRC_SURF_BH               (0x90000000)
+#define	PSB_2D_DST_SURF_BH               (0xA0000000)
+#define	PSB_2D_PAT_SURF_BH               (0xB0000000)
+#define	PSB_2D_SRC_PAL_BH                (0xC0000000)
+#define	PSB_2D_PAT_PAL_BH                (0xD0000000)
+#define	PSB_2D_MASK_SURF_BH              (0xE0000000)
+#define	PSB_2D_FLUSH_BH                  (0xF0000000)
+
+/*
+ * Clip Definition block (PSB_2D_CLIP_BH)
+ */
+#define PSB_2D_CLIPCOUNT_MAX             (1)
+#define PSB_2D_CLIPCOUNT_MASK            (0x00000000)
+#define PSB_2D_CLIPCOUNT_CLRMASK         (0xFFFFFFFF)
+#define PSB_2D_CLIPCOUNT_SHIFT           (0)
+/* clip rectangle min & max */
+#define PSB_2D_CLIP_XMAX_MASK            (0x00FFF000)
+#define PSB_2D_CLIP_XMAX_CLRMASK         (0xFF000FFF)
+#define PSB_2D_CLIP_XMAX_SHIFT           (12)
+#define PSB_2D_CLIP_XMIN_MASK            (0x00000FFF)
+#define PSB_2D_CLIP_XMIN_CLRMASK         (0x00FFF000)
+#define PSB_2D_CLIP_XMIN_SHIFT           (0)
+/* clip rectangle offset */
+#define PSB_2D_CLIP_YMAX_MASK            (0x00FFF000)
+#define PSB_2D_CLIP_YMAX_CLRMASK         (0xFF000FFF)
+#define PSB_2D_CLIP_YMAX_SHIFT           (12)
+#define PSB_2D_CLIP_YMIN_MASK            (0x00000FFF)
+#define PSB_2D_CLIP_YMIN_CLRMASK         (0x00FFF000)
+#define PSB_2D_CLIP_YMIN_SHIFT           (0)
+
+/*
+ * Pattern Control (PSB_2D_PAT_BH)
+ */
+#define PSB_2D_PAT_HEIGHT_MASK           (0x0000001F)
+#define PSB_2D_PAT_HEIGHT_SHIFT          (0)
+#define PSB_2D_PAT_WIDTH_MASK            (0x000003E0)
+#define PSB_2D_PAT_WIDTH_SHIFT           (5)
+#define PSB_2D_PAT_YSTART_MASK           (0x00007C00)
+#define PSB_2D_PAT_YSTART_SHIFT          (10)
+#define PSB_2D_PAT_XSTART_MASK           (0x000F8000)
+#define PSB_2D_PAT_XSTART_SHIFT          (15)
+
+/*
+ * 2D Control block (PSB_2D_CTRL_BH)
+ */
+/* Present Flags */
+#define PSB_2D_SRCCK_CTRL                (0x00000001)
+#define PSB_2D_DSTCK_CTRL                (0x00000002)
+#define PSB_2D_ALPHA_CTRL                (0x00000004)
+/* Colour Key Colour (SRC/DST)*/
+#define PSB_2D_CK_COL_MASK               (0xFFFFFFFF)
+#define PSB_2D_CK_COL_CLRMASK            (0x00000000)
+#define PSB_2D_CK_COL_SHIFT              (0)
+/* Colour Key Mask (SRC/DST)*/
+#define PSB_2D_CK_MASK_MASK              (0xFFFFFFFF)
+#define PSB_2D_CK_MASK_CLRMASK           (0x00000000)
+#define PSB_2D_CK_MASK_SHIFT             (0)
+/* Alpha Control (Alpha/RGB)*/
+#define PSB_2D_GBLALPHA_MASK             (0x000FF000)
+#define PSB_2D_GBLALPHA_CLRMASK          (0xFFF00FFF)
+#define PSB_2D_GBLALPHA_SHIFT            (12)
+#define PSB_2D_SRCALPHA_OP_MASK          (0x00700000)
+#define PSB_2D_SRCALPHA_OP_CLRMASK       (0xFF8FFFFF)
+#define PSB_2D_SRCALPHA_OP_SHIFT         (20)
+#define PSB_2D_SRCALPHA_OP_ONE           (0x00000000)
+#define PSB_2D_SRCALPHA_OP_SRC           (0x00100000)
+#define PSB_2D_SRCALPHA_OP_DST           (0x00200000)
+#define PSB_2D_SRCALPHA_OP_SG            (0x00300000)
+#define PSB_2D_SRCALPHA_OP_DG            (0x00400000)
+#define PSB_2D_SRCALPHA_OP_GBL           (0x00500000)
+#define PSB_2D_SRCALPHA_OP_ZERO          (0x00600000)
+#define PSB_2D_SRCALPHA_INVERT           (0x00800000)
+#define PSB_2D_SRCALPHA_INVERT_CLR       (0xFF7FFFFF)
+#define PSB_2D_DSTALPHA_OP_MASK          (0x07000000)
+#define PSB_2D_DSTALPHA_OP_CLRMASK       (0xF8FFFFFF)
+#define PSB_2D_DSTALPHA_OP_SHIFT         (24)
+#define PSB_2D_DSTALPHA_OP_ONE           (0x00000000)
+#define PSB_2D_DSTALPHA_OP_SRC           (0x01000000)
+#define PSB_2D_DSTALPHA_OP_DST           (0x02000000)
+#define PSB_2D_DSTALPHA_OP_SG            (0x03000000)
+#define PSB_2D_DSTALPHA_OP_DG            (0x04000000)
+#define PSB_2D_DSTALPHA_OP_GBL           (0x05000000)
+#define PSB_2D_DSTALPHA_OP_ZERO          (0x06000000)
+#define PSB_2D_DSTALPHA_INVERT           (0x08000000)
+#define PSB_2D_DSTALPHA_INVERT_CLR       (0xF7FFFFFF)
+
+#define PSB_2D_PRE_MULTIPLICATION_ENABLE  (0x10000000)
+#define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF)
+#define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE   (0x20000000)
+#define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK  (0xDFFFFFFF)
+
+/*
+ *Source Offset (PSB_2D_SRC_OFF_BH)
+ */
+#define PSB_2D_SRCOFF_XSTART_MASK        ((0x00000FFF) << 12)
+#define PSB_2D_SRCOFF_XSTART_SHIFT       (12)
+#define PSB_2D_SRCOFF_YSTART_MASK        (0x00000FFF)
+#define PSB_2D_SRCOFF_YSTART_SHIFT       (0)
+
+/*
+ * Mask Offset (PSB_2D_MASK_OFF_BH)
+ */
+#define PSB_2D_MASKOFF_XSTART_MASK       ((0x00000FFF) << 12)
+#define PSB_2D_MASKOFF_XSTART_SHIFT      (12)
+#define PSB_2D_MASKOFF_YSTART_MASK       (0x00000FFF)
+#define PSB_2D_MASKOFF_YSTART_SHIFT      (0)
+
+/*
+ * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored
+ */
+
+/*
+ *Blit Rectangle (PSB_2D_BLIT_BH)
+ */
+
+#define PSB_2D_ROT_MASK                  (3<<25)
+#define PSB_2D_ROT_CLRMASK               (~PSB_2D_ROT_MASK)
+#define PSB_2D_ROT_NONE                  (0<<25)
+#define PSB_2D_ROT_90DEGS                (1<<25)
+#define PSB_2D_ROT_180DEGS               (2<<25)
+#define PSB_2D_ROT_270DEGS               (3<<25)
+
+#define PSB_2D_COPYORDER_MASK            (3<<23)
+#define PSB_2D_COPYORDER_CLRMASK         (~PSB_2D_COPYORDER_MASK)
+#define PSB_2D_COPYORDER_TL2BR           (0<<23)
+#define PSB_2D_COPYORDER_BR2TL           (1<<23)
+#define PSB_2D_COPYORDER_TR2BL           (2<<23)
+#define PSB_2D_COPYORDER_BL2TR           (3<<23)
+
+#define PSB_2D_DSTCK_CLRMASK             (0xFF9FFFFF)
+#define PSB_2D_DSTCK_DISABLE             (0x00000000)
+#define PSB_2D_DSTCK_PASS                (0x00200000)
+#define PSB_2D_DSTCK_REJECT              (0x00400000)
+
+#define PSB_2D_SRCCK_CLRMASK             (0xFFE7FFFF)
+#define PSB_2D_SRCCK_DISABLE             (0x00000000)
+#define PSB_2D_SRCCK_PASS                (0x00080000)
+#define PSB_2D_SRCCK_REJECT              (0x00100000)
+
+#define PSB_2D_CLIP_ENABLE               (0x00040000)
+
+#define PSB_2D_ALPHA_ENABLE              (0x00020000)
+
+#define PSB_2D_PAT_CLRMASK               (0xFFFEFFFF)
+#define PSB_2D_PAT_MASK                  (0x00010000)
+#define PSB_2D_USE_PAT                   (0x00010000)
+#define PSB_2D_USE_FILL                  (0x00000000)
+/*
+ * Tungsten Graphics note on rop codes: If rop A and rop B are
+ * identical, the mask surface will not be read and need not be
+ * set up.
+ */
+
+#define PSB_2D_ROP3B_MASK                (0x0000FF00)
+#define PSB_2D_ROP3B_CLRMASK             (0xFFFF00FF)
+#define PSB_2D_ROP3B_SHIFT               (8)
+/* rop code A */
+#define PSB_2D_ROP3A_MASK                (0x000000FF)
+#define PSB_2D_ROP3A_CLRMASK             (0xFFFFFF00)
+#define PSB_2D_ROP3A_SHIFT               (0)
+
+#define PSB_2D_ROP4_MASK                 (0x0000FFFF)
+/*
+ *	DWORD0:	(Only pass if Pattern control == Use Fill Colour)
+ *	Fill Colour RGBA8888
+ */
+#define PSB_2D_FILLCOLOUR_MASK           (0xFFFFFFFF)
+#define PSB_2D_FILLCOLOUR_SHIFT          (0)
+/*
+ *	DWORD1: (Always Present)
+ *	X Start (Dest)
+ *	Y Start (Dest)
+ */
+#define PSB_2D_DST_XSTART_MASK           (0x00FFF000)
+#define PSB_2D_DST_XSTART_CLRMASK        (0xFF000FFF)
+#define PSB_2D_DST_XSTART_SHIFT          (12)
+#define PSB_2D_DST_YSTART_MASK           (0x00000FFF)
+#define PSB_2D_DST_YSTART_CLRMASK        (0xFFFFF000)
+#define PSB_2D_DST_YSTART_SHIFT          (0)
+/*
+ *	DWORD2: (Always Present)
+ *	X Size (Dest)
+ *	Y Size (Dest)
+ */
+#define PSB_2D_DST_XSIZE_MASK            (0x00FFF000)
+#define PSB_2D_DST_XSIZE_CLRMASK         (0xFF000FFF)
+#define PSB_2D_DST_XSIZE_SHIFT           (12)
+#define PSB_2D_DST_YSIZE_MASK            (0x00000FFF)
+#define PSB_2D_DST_YSIZE_CLRMASK         (0xFFFFF000)
+#define PSB_2D_DST_YSIZE_SHIFT           (0)
+
+/*
+ * Source Surface (PSB_2D_SRC_SURF_BH)
+ */
+/*
+ *      WORD 0
+ */
+
+#define PSB_2D_SRC_FORMAT_MASK           (0x00078000)
+#define PSB_2D_SRC_1_PAL                 (0x00000000)
+#define PSB_2D_SRC_2_PAL                 (0x00008000)
+#define PSB_2D_SRC_4_PAL                 (0x00010000)
+#define PSB_2D_SRC_8_PAL                 (0x00018000)
+#define PSB_2D_SRC_8_ALPHA               (0x00020000)
+#define PSB_2D_SRC_4_ALPHA               (0x00028000)
+#define PSB_2D_SRC_332RGB                (0x00030000)
+#define PSB_2D_SRC_4444ARGB              (0x00038000)
+#define PSB_2D_SRC_555RGB                (0x00040000)
+#define PSB_2D_SRC_1555ARGB              (0x00048000)
+#define PSB_2D_SRC_565RGB                (0x00050000)
+#define PSB_2D_SRC_0888ARGB              (0x00058000)
+#define PSB_2D_SRC_8888ARGB              (0x00060000)
+#define PSB_2D_SRC_8888UYVY              (0x00068000)
+#define PSB_2D_SRC_RESERVED              (0x00070000)
+#define PSB_2D_SRC_1555ARGB_LOOKUP       (0x00078000)
+
+
+#define PSB_2D_SRC_STRIDE_MASK           (0x00007FFF)
+#define PSB_2D_SRC_STRIDE_CLRMASK        (0xFFFF8000)
+#define PSB_2D_SRC_STRIDE_SHIFT          (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_SRC_ADDR_MASK             (0x0FFFFFFC)
+#define PSB_2D_SRC_ADDR_CLRMASK          (0x00000003)
+#define PSB_2D_SRC_ADDR_SHIFT            (2)
+#define PSB_2D_SRC_ADDR_ALIGNSHIFT       (2)
+
+/*
+ * Pattern Surface (PSB_2D_PAT_SURF_BH)
+ */
+/*
+ *  WORD 0
+ */
+
+#define PSB_2D_PAT_FORMAT_MASK           (0x00078000)
+#define PSB_2D_PAT_1_PAL                 (0x00000000)
+#define PSB_2D_PAT_2_PAL                 (0x00008000)
+#define PSB_2D_PAT_4_PAL                 (0x00010000)
+#define PSB_2D_PAT_8_PAL                 (0x00018000)
+#define PSB_2D_PAT_8_ALPHA               (0x00020000)
+#define PSB_2D_PAT_4_ALPHA               (0x00028000)
+#define PSB_2D_PAT_332RGB                (0x00030000)
+#define PSB_2D_PAT_4444ARGB              (0x00038000)
+#define PSB_2D_PAT_555RGB                (0x00040000)
+#define PSB_2D_PAT_1555ARGB              (0x00048000)
+#define PSB_2D_PAT_565RGB                (0x00050000)
+#define PSB_2D_PAT_0888ARGB              (0x00058000)
+#define PSB_2D_PAT_8888ARGB              (0x00060000)
+
+#define PSB_2D_PAT_STRIDE_MASK           (0x00007FFF)
+#define PSB_2D_PAT_STRIDE_CLRMASK        (0xFFFF8000)
+#define PSB_2D_PAT_STRIDE_SHIFT          (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_PAT_ADDR_MASK             (0x0FFFFFFC)
+#define PSB_2D_PAT_ADDR_CLRMASK          (0x00000003)
+#define PSB_2D_PAT_ADDR_SHIFT            (2)
+#define PSB_2D_PAT_ADDR_ALIGNSHIFT       (2)
+
+/*
+ * Destination Surface (PSB_2D_DST_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+
+#define PSB_2D_DST_FORMAT_MASK           (0x00078000)
+#define PSB_2D_DST_332RGB                (0x00030000)
+#define PSB_2D_DST_4444ARGB              (0x00038000)
+#define PSB_2D_DST_555RGB                (0x00040000)
+#define PSB_2D_DST_1555ARGB              (0x00048000)
+#define PSB_2D_DST_565RGB                (0x00050000)
+#define PSB_2D_DST_0888ARGB              (0x00058000)
+#define PSB_2D_DST_8888ARGB              (0x00060000)
+#define PSB_2D_DST_8888AYUV              (0x00070000)
+
+#define PSB_2D_DST_STRIDE_MASK           (0x00007FFF)
+#define PSB_2D_DST_STRIDE_CLRMASK        (0xFFFF8000)
+#define PSB_2D_DST_STRIDE_SHIFT          (0)
+/*
+ * WORD 1 - Base Address
+ */
+#define PSB_2D_DST_ADDR_MASK             (0x0FFFFFFC)
+#define PSB_2D_DST_ADDR_CLRMASK          (0x00000003)
+#define PSB_2D_DST_ADDR_SHIFT            (2)
+#define PSB_2D_DST_ADDR_ALIGNSHIFT       (2)
+
+/*
+ * Mask Surface (PSB_2D_MASK_SURF_BH)
+ */
+/*
+ * WORD 0
+ */
+#define PSB_2D_MASK_STRIDE_MASK          (0x00007FFF)
+#define PSB_2D_MASK_STRIDE_CLRMASK       (0xFFFF8000)
+#define PSB_2D_MASK_STRIDE_SHIFT         (0)
+/*
+ *  WORD 1 - Base Address
+ */
+#define PSB_2D_MASK_ADDR_MASK            (0x0FFFFFFC)
+#define PSB_2D_MASK_ADDR_CLRMASK         (0x00000003)
+#define PSB_2D_MASK_ADDR_SHIFT           (2)
+#define PSB_2D_MASK_ADDR_ALIGNSHIFT      (2)
+
+/*
+ * Source Palette (PSB_2D_SRC_PAL_BH)
+ */
+
+#define PSB_2D_SRCPAL_ADDR_SHIFT         (0)
+#define PSB_2D_SRCPAL_ADDR_CLRMASK       (0xF0000007)
+#define PSB_2D_SRCPAL_ADDR_MASK          (0x0FFFFFF8)
+#define PSB_2D_SRCPAL_BYTEALIGN          (1024)
+
+/*
+ * Pattern Palette (PSB_2D_PAT_PAL_BH)
+ */
+
+#define PSB_2D_PATPAL_ADDR_SHIFT         (0)
+#define PSB_2D_PATPAL_ADDR_CLRMASK       (0xF0000007)
+#define PSB_2D_PATPAL_ADDR_MASK          (0x0FFFFFF8)
+#define PSB_2D_PATPAL_BYTEALIGN          (1024)
+
+/*
+ * Rop3 Codes (2 LS bytes)
+ */
+
+#define PSB_2D_ROP3_SRCCOPY              (0xCCCC)
+#define PSB_2D_ROP3_PATCOPY              (0xF0F0)
+#define PSB_2D_ROP3_WHITENESS            (0xFFFF)
+#define PSB_2D_ROP3_BLACKNESS            (0x0000)
+#define PSB_2D_ROP3_SRC                  (0xCC)
+#define PSB_2D_ROP3_PAT                  (0xF0)
+#define PSB_2D_ROP3_DST                  (0xAA)
+
+
+/*
+ * Sizes.
+ */
+
+#define PSB_SCENE_HW_COOKIE_SIZE 16
+#define PSB_TA_MEM_HW_COOKIE_SIZE 16
+
+/*
+ * Scene stuff.
+ */
+
+#define PSB_NUM_HW_SCENES          2
+
+/*
+ * Scheduler completion actions.
+ */
+
+#define PSB_RASTER_BLOCK 0
+#define PSB_RASTER       1
+#define PSB_RETURN       2
+#define PSB_TA       3
+
+
+/*Power management*/
+#define PSB_PUNIT_PORT		    0x04
+#define PSB_OSPMBA		    0x78
+#define PSB_APMBA		    0x7a
+#define PSB_APM_CMD		    0x0
+#define PSB_APM_STS		    0x04
+#define PSB_PWRGT_VID_ENC_MASK	    0x30
+#define PSB_PWRGT_VID_DEC_MASK	    0xc
+#define PSB_PWRGT_GL3_MASK	    0xc0
+
+#define PSB_PM_SSC		    0x20
+#define PSB_PM_SSS		    0x30
+#define PSB_PWRGT_DISPLAY_MASK	    0xc /*on a different BA than video/gfx*/
+#define MDFLD_PWRGT_DISPLAY_A_CNTR  0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_CNTR  0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_CNTR  0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_CNTR  0x000c0000
+#define MDFLD_PWRGT_DISPLAY_CNTR    (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR)// 0x000fc00c
+// Display SSS register bits are different in A0 vs. B0
+#define PSB_PWRGT_GFX_MASK	    0x3
+#define MDFLD_PWRGT_DISPLAY_A_STS  		0x000000c0
+#define MDFLD_PWRGT_DISPLAY_B_STS  		0x00000300
+#define MDFLD_PWRGT_DISPLAY_C_STS  		0x00000c00
+#define PSB_PWRGT_GFX_MASK_B0	   		0xc3
+#define MDFLD_PWRGT_DISPLAY_A_STS_B0	0x0000000c
+#define MDFLD_PWRGT_DISPLAY_B_STS_B0  	0x0000c000
+#define MDFLD_PWRGT_DISPLAY_C_STS_B0  	0x00030000
+#define MDFLD_PWRGT_DISP_MIPI_STS  0x000c0000
+#define MDFLD_PWRGT_DISPLAY_STS_A0    (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#define MDFLD_PWRGT_DISPLAY_STS_B0    (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS)// 0x000fc00c
+#endif
diff --git a/drivers/staging/gma500/psb_reset.c b/drivers/staging/gma500/psb_reset.c
new file mode 100644
index 0000000..21fd202
--- /dev/null
+++ b/drivers/staging/gma500/psb_reset.c
@@ -0,0 +1,90 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_reg.h"
+#include "psb_intel_reg.h"
+#include <linux/spinlock.h>
+
+static void psb_lid_timer_func(unsigned long data)
+{
+	struct drm_psb_private * dev_priv = (struct drm_psb_private *)data;
+	struct drm_device *dev = (struct drm_device *)dev_priv->dev;
+	struct timer_list *lid_timer = &dev_priv->lid_timer;
+	unsigned long irq_flags;
+	u32 *lid_state = dev_priv->lid_state;
+	u32 pp_status;
+
+	if (*lid_state == dev_priv->lid_last_state)
+		goto lid_timer_schedule;
+
+	if ((*lid_state) & 0x01) {
+		/*lid state is open*/
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while ((pp_status & PP_ON) == 0);
+
+		/*FIXME: should be backlight level before*/
+		psb_intel_lvds_set_brightness(dev, 100);
+	} else {
+		psb_intel_lvds_set_brightness(dev, 0);
+
+		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
+		do {
+			pp_status = REG_READ(PP_STATUS);
+		} while ((pp_status & PP_ON) == 0);
+	}
+		/* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */
+
+	dev_priv->lid_last_state =  *lid_state;
+
+lid_timer_schedule:
+	spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
+	if (!timer_pending(lid_timer)) {
+		lid_timer->expires = jiffies + PSB_LID_DELAY;
+		add_timer(lid_timer);
+	}
+	spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
+}
+
+void psb_lid_timer_init(struct drm_psb_private *dev_priv)
+{
+	struct timer_list *lid_timer = &dev_priv->lid_timer;
+	unsigned long irq_flags;
+
+	spin_lock_init(&dev_priv->lid_lock);
+	spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
+
+	init_timer(lid_timer);
+
+	lid_timer->data = (unsigned long)dev_priv;
+	lid_timer->function = psb_lid_timer_func;
+	lid_timer->expires = jiffies + PSB_LID_DELAY;
+
+	add_timer(lid_timer);
+	spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
+}
+
+void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
+{
+	del_timer_sync(&dev_priv->lid_timer);
+}
+
diff --git a/drivers/staging/gma500/psb_sgx.c b/drivers/staging/gma500/psb_sgx.c
new file mode 100644
index 0000000..973134b
--- /dev/null
+++ b/drivers/staging/gma500/psb_sgx.c
@@ -0,0 +1,238 @@
+/**************************************************************************
+ * Copyright (c) 2007, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX. USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_drm.h"
+#include "psb_reg.h"
+#include "ttm/ttm_bo_api.h"
+#include "ttm/ttm_execbuf_util.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_placement.h"
+#include "psb_sgx.h"
+#include "psb_intel_reg.h"
+#include "psb_powermgmt.h"
+
+
+static inline int psb_same_page(unsigned long offset,
+				unsigned long offset2)
+{
+	return (offset & PAGE_MASK) == (offset2 & PAGE_MASK);
+}
+
+static inline unsigned long psb_offset_end(unsigned long offset,
+					      unsigned long end)
+{
+	offset = (offset + PAGE_SIZE) & PAGE_MASK;
+	return (end < offset) ? end : offset;
+}
+
+struct psb_dstbuf_cache {
+	unsigned int dst;
+	struct ttm_buffer_object *dst_buf;
+	unsigned long dst_offset;
+	uint32_t *dst_page;
+	unsigned int dst_page_offset;
+	struct ttm_bo_kmap_obj dst_kmap;
+	bool dst_is_iomem;
+};
+
+struct psb_validate_buffer {
+	struct ttm_validate_buffer base;
+	struct psb_validate_req req;
+	int ret;
+	struct psb_validate_arg __user *user_val_arg;
+	uint32_t flags;
+	uint32_t offset;
+	int po_correct;
+};
+static int
+psb_placement_fence_type(struct ttm_buffer_object *bo,
+			 uint64_t set_val_flags,
+			 uint64_t clr_val_flags,
+			 uint32_t new_fence_class,
+			 uint32_t *new_fence_type)
+{
+	int ret;
+	uint32_t n_fence_type;
+	/*
+	uint32_t set_flags = set_val_flags & 0xFFFFFFFF;
+	uint32_t clr_flags = clr_val_flags & 0xFFFFFFFF;
+	*/
+	struct ttm_fence_object *old_fence;
+	uint32_t old_fence_type;
+	struct ttm_placement placement;
+
+	if (unlikely
+	    (!(set_val_flags &
+	       (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE)))) {
+		DRM_ERROR
+		    ("GPU access type (read / write) is not indicated.\n");
+		return -EINVAL;
+	}
+
+	/* User space driver doesn't set any TTM placement flags in
+					set_val_flags or clr_val_flags */
+	placement.num_placement = 0;/* FIXME  */
+	placement.num_busy_placement = 0;
+	placement.fpfn = 0;
+	placement.lpfn = 0;
+	ret = psb_ttm_bo_check_placement(bo, &placement);
+	if (unlikely(ret != 0))
+		return ret;
+
+	switch (new_fence_class) {
+	default:
+		n_fence_type = _PSB_FENCE_TYPE_EXE;
+	}
+
+	*new_fence_type = n_fence_type;
+	old_fence = (struct ttm_fence_object *) bo->sync_obj;
+	old_fence_type = (uint32_t) (unsigned long) bo->sync_obj_arg;
+
+	if (old_fence && ((new_fence_class != old_fence->fence_class) ||
+			  ((n_fence_type ^ old_fence_type) &
+			   old_fence_type))) {
+		ret = ttm_bo_wait(bo, 0, 1, 0);
+		if (unlikely(ret != 0))
+			return ret;
+	}
+	/*
+	bo->proposed_flags = (bo->proposed_flags | set_flags)
+		& ~clr_flags & TTM_PL_MASK_MEMTYPE;
+	*/
+	return 0;
+}
+
+int psb_validate_kernel_buffer(struct psb_context *context,
+			       struct ttm_buffer_object *bo,
+			       uint32_t fence_class,
+			       uint64_t set_flags, uint64_t clr_flags)
+{
+	struct psb_validate_buffer *item;
+	uint32_t cur_fence_type;
+	int ret;
+
+	if (unlikely(context->used_buffers >= PSB_NUM_VALIDATE_BUFFERS)) {
+		DRM_ERROR("Out of free validation buffer entries for "
+			  "kernel buffer validation.\n");
+		return -ENOMEM;
+	}
+
+	item = &context->buffers[context->used_buffers];
+	item->user_val_arg = NULL;
+	item->base.reserved = 0;
+
+	ret = ttm_bo_reserve(bo, 1, 0, 1, context->val_seq);
+	if (unlikely(ret != 0))
+	        return ret;
+
+	ret = psb_placement_fence_type(bo, set_flags, clr_flags, fence_class,
+				       &cur_fence_type);
+	if (unlikely(ret != 0)) {
+		ttm_bo_unreserve(bo);
+		return ret;
+	}
+
+	item->base.bo = ttm_bo_reference(bo);
+	item->base.new_sync_obj_arg = (void *) (unsigned long) cur_fence_type;
+	item->base.reserved = 1;
+
+	/* Internal locking ??? FIXMEAC */
+	list_add_tail(&item->base.head, &context->kern_validate_list);
+	context->used_buffers++;
+	/*
+	ret = ttm_bo_validate(bo, 1, 0, 0);
+	if (unlikely(ret != 0))
+		goto out_unlock;
+	*/
+	item->offset = bo->offset;
+	item->flags = bo->mem.placement;
+	context->fence_types |= cur_fence_type;
+
+	return ret;
+}
+
+void psb_fence_or_sync(struct drm_file *file_priv,
+		       uint32_t engine,
+		       uint32_t fence_types,
+		       uint32_t fence_flags,
+		       struct list_head *list,
+		       struct psb_ttm_fence_rep *fence_arg,
+		       struct ttm_fence_object **fence_p)
+{
+	struct drm_device *dev = file_priv->minor->dev;
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+	struct ttm_fence_device *fdev = &dev_priv->fdev;
+	int ret;
+	struct ttm_fence_object *fence;
+	struct ttm_object_file *tfile = psb_fpriv(file_priv)->tfile;
+	uint32_t handle;
+
+	ret = ttm_fence_user_create(fdev, tfile,
+				    engine, fence_types,
+				    TTM_FENCE_FLAG_EMIT, &fence, &handle);
+	if (ret) {
+
+		/*
+		 * Fence creation failed.
+		 * Fall back to synchronous operation and idle the engine.
+		 */
+
+		if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) {
+
+			/*
+			 * Communicate to user-space that
+			 * fence creation has failed and that
+			 * the engine is idle.
+			 */
+
+			fence_arg->handle = ~0;
+			fence_arg->error = ret;
+		}
+
+		ttm_eu_backoff_reservation(list);
+		if (fence_p)
+			*fence_p = NULL;
+		return;
+	}
+
+	ttm_eu_fence_buffer_objects(list, fence);
+	if (!(fence_flags & DRM_PSB_FENCE_NO_USER)) {
+		struct ttm_fence_info info = ttm_fence_get_info(fence);
+		fence_arg->handle = handle;
+		fence_arg->fence_class = ttm_fence_class(fence);
+		fence_arg->fence_type = ttm_fence_types(fence);
+		fence_arg->signaled_types = info.signaled_types;
+		fence_arg->error = 0;
+	} else {
+		ret =
+		    ttm_ref_object_base_unref(tfile, handle,
+					      ttm_fence_type);
+		BUG_ON(ret);
+	}
+
+	if (fence_p)
+		*fence_p = fence;
+	else if (fence)
+		ttm_fence_object_unref(&fence);
+}
+
diff --git a/drivers/staging/gma500/psb_sgx.h b/drivers/staging/gma500/psb_sgx.h
new file mode 100644
index 0000000..9300e2d
--- /dev/null
+++ b/drivers/staging/gma500/psb_sgx.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2008, Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ **/
+#ifndef _PSB_SGX_H_
+#define _PSB_SGX_H_
+
+extern int psb_submit_video_cmdbuf(struct drm_device *dev,
+			       struct ttm_buffer_object *cmd_buffer,
+			       unsigned long cmd_offset,
+			       unsigned long cmd_size,
+			       struct ttm_fence_object *fence);
+
+extern int drm_idle_check_interval;
+
+#endif
diff --git a/drivers/staging/gma500/psb_ttm_fence.c b/drivers/staging/gma500/psb_ttm_fence.c
new file mode 100644
index 0000000..d1c3590
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_fence.c
@@ -0,0 +1,605 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "psb_ttm_fence_api.h"
+#include "psb_ttm_fence_driver.h"
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include <drm/drmP.h>
+
+/*
+ * Simple implementation for now.
+ */
+
+static void ttm_fence_lockup(struct ttm_fence_object *fence, uint32_t mask)
+{
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+
+	printk(KERN_ERR "GPU lockup dectected on engine %u "
+	       "fence type 0x%08x\n",
+	       (unsigned int)fence->fence_class, (unsigned int)mask);
+	/*
+	 * Give engines some time to idle?
+	 */
+
+	write_lock(&fc->lock);
+	ttm_fence_handler(fence->fdev, fence->fence_class,
+			  fence->sequence, mask, -EBUSY);
+	write_unlock(&fc->lock);
+}
+
+/*
+ * Convenience function to be called by fence::wait methods that
+ * need polling.
+ */
+
+int ttm_fence_wait_polling(struct ttm_fence_object *fence, bool lazy,
+			   bool interruptible, uint32_t mask)
+{
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+	uint32_t count = 0;
+	int ret;
+	unsigned long end_jiffies = fence->timeout_jiffies;
+
+	DECLARE_WAITQUEUE(entry, current);
+	add_wait_queue(&fc->fence_queue, &entry);
+
+	ret = 0;
+
+	for (;;) {
+		__set_current_state((interruptible) ?
+				    TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+		if (ttm_fence_object_signaled(fence, mask))
+			break;
+		if (time_after_eq(jiffies, end_jiffies)) {
+			if (driver->lockup)
+				driver->lockup(fence, mask);
+			else
+				ttm_fence_lockup(fence, mask);
+			continue;
+		}
+		if (lazy)
+			schedule_timeout(1);
+		else if ((++count & 0x0F) == 0) {
+			__set_current_state(TASK_RUNNING);
+			schedule();
+			__set_current_state((interruptible) ?
+					    TASK_INTERRUPTIBLE :
+					    TASK_UNINTERRUPTIBLE);
+		}
+		if (interruptible && signal_pending(current)) {
+			ret = -ERESTART;
+			break;
+		}
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&fc->fence_queue, &entry);
+	return ret;
+}
+
+/*
+ * Typically called by the IRQ handler.
+ */
+
+void ttm_fence_handler(struct ttm_fence_device *fdev, uint32_t fence_class,
+		       uint32_t sequence, uint32_t type, uint32_t error)
+{
+	int wake = 0;
+	uint32_t diff;
+	uint32_t relevant_type;
+	uint32_t new_type;
+	struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class];
+	const struct ttm_fence_driver *driver = ttm_fence_driver_from_dev(fdev);
+	struct list_head *head;
+	struct ttm_fence_object *fence, *next;
+	bool found = false;
+
+	if (list_empty(&fc->ring))
+		return;
+
+	list_for_each_entry(fence, &fc->ring, ring) {
+		diff = (sequence - fence->sequence) & fc->sequence_mask;
+		if (diff > fc->wrap_diff) {
+			found = true;
+			break;
+		}
+	}
+
+	fc->waiting_types &= ~type;
+	head = (found) ? &fence->ring : &fc->ring;
+
+	list_for_each_entry_safe_reverse(fence, next, head, ring) {
+		if (&fence->ring == &fc->ring)
+			break;
+
+		DRM_DEBUG("Fence 0x%08lx, sequence 0x%08x, type 0x%08x\n",
+			  (unsigned long)fence, fence->sequence,
+			  fence->fence_type);
+
+		if (error) {
+			fence->info.error = error;
+			fence->info.signaled_types = fence->fence_type;
+			list_del_init(&fence->ring);
+			wake = 1;
+			break;
+		}
+
+		relevant_type = type & fence->fence_type;
+		new_type = (fence->info.signaled_types | relevant_type) ^
+		    fence->info.signaled_types;
+
+		if (new_type) {
+			fence->info.signaled_types |= new_type;
+			DRM_DEBUG("Fence 0x%08lx signaled 0x%08x\n",
+				  (unsigned long)fence,
+				  fence->info.signaled_types);
+
+			if (unlikely(driver->signaled))
+				driver->signaled(fence);
+
+			if (driver->needed_flush)
+				fc->pending_flush |=
+				    driver->needed_flush(fence);
+
+			if (new_type & fence->waiting_types)
+				wake = 1;
+		}
+
+		fc->waiting_types |=
+		    fence->waiting_types & ~fence->info.signaled_types;
+
+		if (!(fence->fence_type & ~fence->info.signaled_types)) {
+			DRM_DEBUG("Fence completely signaled 0x%08lx\n",
+				  (unsigned long)fence);
+			list_del_init(&fence->ring);
+		}
+	}
+
+	/*
+	 * Reinstate lost waiting types.
+	 */
+
+	if ((fc->waiting_types & type) != type) {
+		head = head->prev;
+		list_for_each_entry(fence, head, ring) {
+			if (&fence->ring == &fc->ring)
+				break;
+			diff =
+			    (fc->highest_waiting_sequence -
+			     fence->sequence) & fc->sequence_mask;
+			if (diff > fc->wrap_diff)
+				break;
+
+			fc->waiting_types |=
+			    fence->waiting_types & ~fence->info.signaled_types;
+		}
+	}
+
+	if (wake)
+		wake_up_all(&fc->fence_queue);
+}
+
+static void ttm_fence_unring(struct ttm_fence_object *fence)
+{
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	unsigned long irq_flags;
+
+	write_lock_irqsave(&fc->lock, irq_flags);
+	list_del_init(&fence->ring);
+	write_unlock_irqrestore(&fc->lock, irq_flags);
+}
+
+bool ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask)
+{
+	unsigned long flags;
+	bool signaled;
+	const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+
+	mask &= fence->fence_type;
+	read_lock_irqsave(&fc->lock, flags);
+	signaled = (mask & fence->info.signaled_types) == mask;
+	read_unlock_irqrestore(&fc->lock, flags);
+	if (!signaled && driver->poll) {
+		write_lock_irqsave(&fc->lock, flags);
+		driver->poll(fence->fdev, fence->fence_class, mask);
+		signaled = (mask & fence->info.signaled_types) == mask;
+		write_unlock_irqrestore(&fc->lock, flags);
+	}
+	return signaled;
+}
+
+int ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t type)
+{
+	const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	unsigned long irq_flags;
+	uint32_t saved_pending_flush;
+	uint32_t diff;
+	bool call_flush;
+
+	if (type & ~fence->fence_type) {
+		DRM_ERROR("Flush trying to extend fence type, "
+			  "0x%x, 0x%x\n", type, fence->fence_type);
+		return -EINVAL;
+	}
+
+	write_lock_irqsave(&fc->lock, irq_flags);
+	fence->waiting_types |= type;
+	fc->waiting_types |= fence->waiting_types;
+	diff = (fence->sequence - fc->highest_waiting_sequence) &
+	    fc->sequence_mask;
+
+	if (diff < fc->wrap_diff)
+		fc->highest_waiting_sequence = fence->sequence;
+
+	/*
+	 * fence->waiting_types has changed. Determine whether
+	 * we need to initiate some kind of flush as a result of this.
+	 */
+
+	saved_pending_flush = fc->pending_flush;
+	if (driver->needed_flush)
+		fc->pending_flush |= driver->needed_flush(fence);
+
+	if (driver->poll)
+		driver->poll(fence->fdev, fence->fence_class,
+			     fence->waiting_types);
+
+	call_flush = (fc->pending_flush != 0);
+	write_unlock_irqrestore(&fc->lock, irq_flags);
+
+	if (call_flush && driver->flush)
+		driver->flush(fence->fdev, fence->fence_class);
+
+	return 0;
+}
+
+/*
+ * Make sure old fence objects are signaled before their fence sequences are
+ * wrapped around and reused.
+ */
+
+void ttm_fence_flush_old(struct ttm_fence_device *fdev,
+			 uint32_t fence_class, uint32_t sequence)
+{
+	struct ttm_fence_class_manager *fc = &fdev->fence_class[fence_class];
+	struct ttm_fence_object *fence;
+	unsigned long irq_flags;
+	const struct ttm_fence_driver *driver = fdev->driver;
+	bool call_flush;
+
+	uint32_t diff;
+
+	write_lock_irqsave(&fc->lock, irq_flags);
+
+	list_for_each_entry_reverse(fence, &fc->ring, ring) {
+		diff = (sequence - fence->sequence) & fc->sequence_mask;
+		if (diff <= fc->flush_diff)
+			break;
+
+		fence->waiting_types = fence->fence_type;
+		fc->waiting_types |= fence->fence_type;
+
+		if (driver->needed_flush)
+			fc->pending_flush |= driver->needed_flush(fence);
+	}
+
+	if (driver->poll)
+		driver->poll(fdev, fence_class, fc->waiting_types);
+
+	call_flush = (fc->pending_flush != 0);
+	write_unlock_irqrestore(&fc->lock, irq_flags);
+
+	if (call_flush && driver->flush)
+		driver->flush(fdev, fence->fence_class);
+
+	/*
+	 * FIXME: Shold we implement a wait here for really old fences?
+	 */
+
+}
+
+int ttm_fence_object_wait(struct ttm_fence_object *fence,
+			  bool lazy, bool interruptible, uint32_t mask)
+{
+	const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	int ret = 0;
+	unsigned long timeout;
+	unsigned long cur_jiffies;
+	unsigned long to_jiffies;
+
+	if (mask & ~fence->fence_type) {
+		DRM_ERROR("Wait trying to extend fence type"
+			  " 0x%08x 0x%08x\n", mask, fence->fence_type);
+		BUG();
+		return -EINVAL;
+	}
+
+	if (driver->wait)
+		return driver->wait(fence, lazy, interruptible, mask);
+
+	ttm_fence_object_flush(fence, mask);
+retry:
+	if (!driver->has_irq ||
+	    driver->has_irq(fence->fdev, fence->fence_class, mask)) {
+
+		cur_jiffies = jiffies;
+		to_jiffies = fence->timeout_jiffies;
+
+		timeout = (time_after(to_jiffies, cur_jiffies)) ?
+		    to_jiffies - cur_jiffies : 1;
+
+		if (interruptible)
+			ret = wait_event_interruptible_timeout
+			    (fc->fence_queue,
+			     ttm_fence_object_signaled(fence, mask), timeout);
+		else
+			ret = wait_event_timeout
+			    (fc->fence_queue,
+			     ttm_fence_object_signaled(fence, mask), timeout);
+
+		if (unlikely(ret == -ERESTARTSYS))
+			return -ERESTART;
+
+		if (unlikely(ret == 0)) {
+			if (driver->lockup)
+				driver->lockup(fence, mask);
+			else
+				ttm_fence_lockup(fence, mask);
+			goto retry;
+		}
+
+		return 0;
+	}
+
+	return ttm_fence_wait_polling(fence, lazy, interruptible, mask);
+}
+
+int ttm_fence_object_emit(struct ttm_fence_object *fence, uint32_t fence_flags,
+			  uint32_t fence_class, uint32_t type)
+{
+	const struct ttm_fence_driver *driver = ttm_fence_driver(fence);
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	unsigned long flags;
+	uint32_t sequence;
+	unsigned long timeout;
+	int ret;
+
+	ttm_fence_unring(fence);
+	ret = driver->emit(fence->fdev,
+			   fence_class, fence_flags, &sequence, &timeout);
+	if (ret)
+		return ret;
+
+	write_lock_irqsave(&fc->lock, flags);
+	fence->fence_class = fence_class;
+	fence->fence_type = type;
+	fence->waiting_types = 0;
+	fence->info.signaled_types = 0;
+	fence->info.error = 0;
+	fence->sequence = sequence;
+	fence->timeout_jiffies = timeout;
+	if (list_empty(&fc->ring))
+		fc->highest_waiting_sequence = sequence - 1;
+	list_add_tail(&fence->ring, &fc->ring);
+	fc->latest_queued_sequence = sequence;
+	write_unlock_irqrestore(&fc->lock, flags);
+	return 0;
+}
+
+int ttm_fence_object_init(struct ttm_fence_device *fdev,
+			  uint32_t fence_class,
+			  uint32_t type,
+			  uint32_t create_flags,
+			  void (*destroy) (struct ttm_fence_object *),
+			  struct ttm_fence_object *fence)
+{
+	int ret = 0;
+
+	kref_init(&fence->kref);
+	fence->fence_class = fence_class;
+	fence->fence_type = type;
+	fence->info.signaled_types = 0;
+	fence->waiting_types = 0;
+	fence->sequence = 0;
+	fence->info.error = 0;
+	fence->fdev = fdev;
+	fence->destroy = destroy;
+	INIT_LIST_HEAD(&fence->ring);
+	atomic_inc(&fdev->count);
+
+	if (create_flags & TTM_FENCE_FLAG_EMIT) {
+		ret = ttm_fence_object_emit(fence, create_flags,
+					    fence->fence_class, type);
+	}
+
+	return ret;
+}
+
+int ttm_fence_object_create(struct ttm_fence_device *fdev,
+			    uint32_t fence_class,
+			    uint32_t type,
+			    uint32_t create_flags,
+			    struct ttm_fence_object **c_fence)
+{
+	struct ttm_fence_object *fence;
+	int ret;
+
+	ret = ttm_mem_global_alloc(fdev->mem_glob,
+				   sizeof(*fence),
+				   false,
+				   false);
+	if (unlikely(ret != 0)) {
+		printk(KERN_ERR "Out of memory creating fence object\n");
+		return ret;
+	}
+
+	fence = kmalloc(sizeof(*fence), GFP_KERNEL);
+	if (!fence) {
+		printk(KERN_ERR "Out of memory creating fence object\n");
+		ttm_mem_global_free(fdev->mem_glob, sizeof(*fence));
+		return -ENOMEM;
+	}
+
+	ret = ttm_fence_object_init(fdev, fence_class, type,
+				    create_flags, NULL, fence);
+	if (ret) {
+		ttm_fence_object_unref(&fence);
+		return ret;
+	}
+	*c_fence = fence;
+
+	return 0;
+}
+
+static void ttm_fence_object_destroy(struct kref *kref)
+{
+	struct ttm_fence_object *fence =
+	    container_of(kref, struct ttm_fence_object, kref);
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	unsigned long irq_flags;
+
+	write_lock_irqsave(&fc->lock, irq_flags);
+	list_del_init(&fence->ring);
+	write_unlock_irqrestore(&fc->lock, irq_flags);
+
+	atomic_dec(&fence->fdev->count);
+	if (fence->destroy)
+		fence->destroy(fence);
+	else {
+		ttm_mem_global_free(fence->fdev->mem_glob,
+				    sizeof(*fence));
+		kfree(fence);
+	}
+}
+
+void ttm_fence_device_release(struct ttm_fence_device *fdev)
+{
+	kfree(fdev->fence_class);
+}
+
+int
+ttm_fence_device_init(int num_classes,
+		      struct ttm_mem_global *mem_glob,
+		      struct ttm_fence_device *fdev,
+		      const struct ttm_fence_class_init *init,
+		      bool replicate_init,
+		      const struct ttm_fence_driver *driver)
+{
+	struct ttm_fence_class_manager *fc;
+	const struct ttm_fence_class_init *fci;
+	int i;
+
+	fdev->mem_glob = mem_glob;
+	fdev->fence_class = kzalloc(num_classes *
+				    sizeof(*fdev->fence_class), GFP_KERNEL);
+
+	if (unlikely(!fdev->fence_class))
+		return -ENOMEM;
+
+	fdev->num_classes = num_classes;
+	atomic_set(&fdev->count, 0);
+	fdev->driver = driver;
+
+	for (i = 0; i < fdev->num_classes; ++i) {
+		fc = &fdev->fence_class[i];
+		fci = &init[(replicate_init) ? 0 : i];
+
+		fc->wrap_diff = fci->wrap_diff;
+		fc->flush_diff = fci->flush_diff;
+		fc->sequence_mask = fci->sequence_mask;
+
+		rwlock_init(&fc->lock);
+		INIT_LIST_HEAD(&fc->ring);
+		init_waitqueue_head(&fc->fence_queue);
+	}
+
+	return 0;
+}
+
+struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence)
+{
+	struct ttm_fence_class_manager *fc = ttm_fence_fc(fence);
+	struct ttm_fence_info tmp;
+	unsigned long irq_flags;
+
+	read_lock_irqsave(&fc->lock, irq_flags);
+	tmp = fence->info;
+	read_unlock_irqrestore(&fc->lock, irq_flags);
+
+	return tmp;
+}
+
+void ttm_fence_object_unref(struct ttm_fence_object **p_fence)
+{
+	struct ttm_fence_object *fence = *p_fence;
+
+	*p_fence = NULL;
+	(void)kref_put(&fence->kref, &ttm_fence_object_destroy);
+}
+
+/*
+ * Placement / BO sync object glue.
+ */
+
+bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg)
+{
+	struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+	uint32_t fence_types = (uint32_t) (unsigned long)sync_arg;
+
+	return ttm_fence_object_signaled(fence, fence_types);
+}
+
+int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg,
+			    bool lazy, bool interruptible)
+{
+	struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+	uint32_t fence_types = (uint32_t) (unsigned long)sync_arg;
+
+	return ttm_fence_object_wait(fence, lazy, interruptible, fence_types);
+}
+
+int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg)
+{
+	struct ttm_fence_object *fence = (struct ttm_fence_object *)sync_obj;
+	uint32_t fence_types = (uint32_t) (unsigned long)sync_arg;
+
+	return ttm_fence_object_flush(fence, fence_types);
+}
+
+void ttm_fence_sync_obj_unref(void **sync_obj)
+{
+	ttm_fence_object_unref((struct ttm_fence_object **)sync_obj);
+}
+
+void *ttm_fence_sync_obj_ref(void *sync_obj)
+{
+	return (void *)
+	    ttm_fence_object_ref((struct ttm_fence_object *)sync_obj);
+}
diff --git a/drivers/staging/gma500/psb_ttm_fence_api.h b/drivers/staging/gma500/psb_ttm_fence_api.h
new file mode 100644
index 0000000..b14a427
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_fence_api.h
@@ -0,0 +1,272 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+#ifndef _TTM_FENCE_API_H_
+#define _TTM_FENCE_API_H_
+
+#include <linux/list.h>
+#include <linux/kref.h>
+
+#define TTM_FENCE_FLAG_EMIT (1 << 0)
+#define TTM_FENCE_TYPE_EXE  (1 << 0)
+
+struct ttm_fence_device;
+
+/**
+ * struct ttm_fence_info
+ *
+ * @fence_class:    The fence class.
+ * @fence_type:     Bitfield indicating types for this fence.
+ * @signaled_types: Bitfield indicating which types are signaled.
+ * @error:          Last error reported from the device.
+ *
+ * Used as output from the ttm_fence_get_info
+ */
+
+struct ttm_fence_info {
+	uint32_t signaled_types;
+	uint32_t error;
+};
+
+/**
+ * struct ttm_fence_object
+ *
+ * @fdev:            Pointer to the fence device struct.
+ * @kref:            Holds the reference count of this fence object.
+ * @ring:            List head used for the circular list of not-completely
+ *                   signaled fences.
+ * @info:            Data for fast retrieval using the ttm_fence_get_info()
+ * function.
+ * @timeout_jiffies: Absolute jiffies value indicating when this fence
+ *                   object times out and, if waited on, calls ttm_fence_lockup
+ *                   to check for and resolve a GPU lockup.
+ * @sequence:        Fence sequence number.
+ * @waiting_types:   Types currently waited on.
+ * @destroy:         Called to free the fence object, when its refcount has
+ *                   reached zero. If NULL, kfree is used.
+ *
+ * This struct is provided in the driver interface so that drivers can
+ * derive from it and create their own fence implementation. All members
+ * are private to the fence implementation and the fence driver callbacks.
+ * Otherwise a driver may access the derived object using container_of().
+ */
+
+struct ttm_fence_object {
+	struct ttm_fence_device *fdev;
+	struct kref kref;
+	uint32_t fence_class;
+	uint32_t fence_type;
+
+	/*
+	 * The below fields are protected by the fence class
+	 * manager spinlock.
+	 */
+
+	struct list_head ring;
+	struct ttm_fence_info info;
+	unsigned long timeout_jiffies;
+	uint32_t sequence;
+	uint32_t waiting_types;
+	void (*destroy) (struct ttm_fence_object *);
+};
+
+/**
+ * ttm_fence_object_init
+ *
+ * @fdev: Pointer to a struct ttm_fence_device.
+ * @fence_class: Fence class for this fence.
+ * @type: Fence type for this fence.
+ * @create_flags: Flags indicating varios actions at init time. At this point
+ * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to
+ * the command stream.
+ * @destroy: Destroy function. If NULL, kfree() is used.
+ * @fence: The struct ttm_fence_object to initialize.
+ *
+ * Initialize a pre-allocated fence object. This function, together with the
+ * destroy function makes it possible to derive driver-specific fence objects.
+ */
+
+extern int
+ttm_fence_object_init(struct ttm_fence_device *fdev,
+		      uint32_t fence_class,
+		      uint32_t type,
+		      uint32_t create_flags,
+		      void (*destroy) (struct ttm_fence_object *fence),
+		      struct ttm_fence_object *fence);
+
+/**
+ * ttm_fence_object_create
+ *
+ * @fdev: Pointer to a struct ttm_fence_device.
+ * @fence_class: Fence class for this fence.
+ * @type: Fence type for this fence.
+ * @create_flags: Flags indicating varios actions at init time. At this point
+ * there's only TTM_FENCE_FLAG_EMIT, which triggers a sequence emission to
+ * the command stream.
+ * @c_fence: On successful termination, *(@c_fence) will point to the created
+ * fence object.
+ *
+ * Create and initialize a struct ttm_fence_object. The destroy function will
+ * be set to kfree().
+ */
+
+extern int
+ttm_fence_object_create(struct ttm_fence_device *fdev,
+			uint32_t fence_class,
+			uint32_t type,
+			uint32_t create_flags,
+			struct ttm_fence_object **c_fence);
+
+/**
+ * ttm_fence_object_wait
+ *
+ * @fence: The fence object to wait on.
+ * @lazy: Allow sleeps to reduce the cpu-usage if polling.
+ * @interruptible: Sleep interruptible when waiting.
+ * @type_mask: Wait for the given type_mask to signal.
+ *
+ * Wait for a fence to signal the given type_mask. The function will
+ * perform a fence_flush using type_mask. (See ttm_fence_object_flush).
+ *
+ * Returns
+ * -ERESTART if interrupted by a signal.
+ * May return driver-specific error codes if timed-out.
+ */
+
+extern int
+ttm_fence_object_wait(struct ttm_fence_object *fence,
+		      bool lazy, bool interruptible, uint32_t type_mask);
+
+/**
+ * ttm_fence_object_flush
+ *
+ * @fence: The fence object to flush.
+ * @flush_mask: Fence types to flush.
+ *
+ * Make sure that the given fence eventually signals the
+ * types indicated by @flush_mask. Note that this may or may not
+ * map to a CPU or GPU flush.
+ */
+
+extern int
+ttm_fence_object_flush(struct ttm_fence_object *fence, uint32_t flush_mask);
+
+/**
+ * ttm_fence_get_info
+ *
+ * @fence: The fence object.
+ *
+ * Copy the info block from the fence while holding relevant locks.
+ */
+
+struct ttm_fence_info ttm_fence_get_info(struct ttm_fence_object *fence);
+
+/**
+ * ttm_fence_object_ref
+ *
+ * @fence: The fence object.
+ *
+ * Return a ref-counted pointer to the fence object indicated by @fence.
+ */
+
+static inline struct ttm_fence_object *ttm_fence_object_ref(struct
+							    ttm_fence_object
+							    *fence)
+{
+	kref_get(&fence->kref);
+	return fence;
+}
+
+/**
+ * ttm_fence_object_unref
+ *
+ * @p_fence: Pointer to a ref-counted pinter to a struct ttm_fence_object.
+ *
+ * Unreference the fence object pointed to by *(@p_fence), clearing
+ * *(p_fence).
+ */
+
+extern void ttm_fence_object_unref(struct ttm_fence_object **p_fence);
+
+/**
+ * ttm_fence_object_signaled
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ * @mask: Type mask to check whether signaled.
+ *
+ * This function checks (without waiting) whether the fence object
+ * pointed to by @fence has signaled the types indicated by @mask,
+ * and returns 1 if true, 0 if false. This function does NOT perform
+ * an implicit fence flush.
+ */
+
+extern bool
+ttm_fence_object_signaled(struct ttm_fence_object *fence, uint32_t mask);
+
+/**
+ * ttm_fence_class
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ *
+ * Convenience function that returns the fence class of a
+ * struct ttm_fence_object.
+ */
+
+static inline uint32_t ttm_fence_class(const struct ttm_fence_object *fence)
+{
+	return fence->fence_class;
+}
+
+/**
+ * ttm_fence_types
+ *
+ * @fence: Pointer to the struct ttm_fence_object.
+ *
+ * Convenience function that returns the fence types of a
+ * struct ttm_fence_object.
+ */
+
+static inline uint32_t ttm_fence_types(const struct ttm_fence_object *fence)
+{
+	return fence->fence_type;
+}
+
+/*
+ * The functions below are wrappers to the above functions, with
+ * similar names but with sync_obj omitted. These wrappers are intended
+ * to be plugged directly into the buffer object driver's sync object
+ * API, if the driver chooses to use ttm_fence_objects as buffer object
+ * sync objects. In the prototypes below, a sync_obj is cast to a
+ * struct ttm_fence_object, whereas a sync_arg is cast to an
+ * uint32_t representing a fence_type argument.
+ */
+
+extern bool ttm_fence_sync_obj_signaled(void *sync_obj, void *sync_arg);
+extern int ttm_fence_sync_obj_wait(void *sync_obj, void *sync_arg,
+				   bool lazy, bool interruptible);
+extern int ttm_fence_sync_obj_flush(void *sync_obj, void *sync_arg);
+extern void ttm_fence_sync_obj_unref(void **sync_obj);
+extern void *ttm_fence_sync_obj_ref(void *sync_obj);
+
+#endif
diff --git a/drivers/staging/gma500/psb_ttm_fence_driver.h b/drivers/staging/gma500/psb_ttm_fence_driver.h
new file mode 100644
index 0000000..c35c569
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_fence_driver.h
@@ -0,0 +1,302 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+#ifndef _TTM_FENCE_DRIVER_H_
+#define _TTM_FENCE_DRIVER_H_
+
+#include <linux/kref.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include "psb_ttm_fence_api.h"
+#include "ttm/ttm_memory.h"
+
+/** @file ttm_fence_driver.h
+ *
+ * Definitions needed for a driver implementing the
+ * ttm_fence subsystem.
+ */
+
+/**
+ * struct ttm_fence_class_manager:
+ *
+ * @wrap_diff: Sequence difference to catch 32-bit wrapping.
+ * if (seqa - seqb) > @wrap_diff, then seqa < seqb.
+ * @flush_diff: Sequence difference to trigger fence flush.
+ * if (cur_seq - seqa) > @flush_diff, then consider fence object with
+ * seqa as old an needing a flush.
+ * @sequence_mask: Mask of valid bits in a fence sequence.
+ * @lock: Lock protecting this struct as well as fence objects
+ * associated with this struct.
+ * @ring: Circular sequence-ordered list of fence objects.
+ * @pending_flush: Fence types currently needing a flush.
+ * @waiting_types: Fence types that are currently waited for.
+ * @fence_queue: Queue of waiters on fences belonging to this fence class.
+ * @highest_waiting_sequence: Sequence number of the fence with highest
+ * sequence number and that is waited for.
+ * @latest_queued_sequence: Sequence number of the fence latest queued
+ * on the ring.
+ */
+
+struct ttm_fence_class_manager {
+
+	/*
+	 * Unprotected constant members.
+	 */
+
+	uint32_t wrap_diff;
+	uint32_t flush_diff;
+	uint32_t sequence_mask;
+
+	/*
+	 * The rwlock protects this structure as well as
+	 * the data in all fence objects belonging to this
+	 * class. This should be OK as most fence objects are
+	 * only read from once they're created.
+	 */
+
+	rwlock_t lock;
+	struct list_head ring;
+	uint32_t pending_flush;
+	uint32_t waiting_types;
+	wait_queue_head_t fence_queue;
+	uint32_t highest_waiting_sequence;
+	uint32_t latest_queued_sequence;
+};
+
+/**
+ * struct ttm_fence_device
+ *
+ * @fence_class:  Array of fence class managers.
+ * @num_classes:  Array dimension of @fence_class.
+ * @count:        Current number of fence objects for statistics.
+ * @driver:       Driver struct.
+ *
+ * Provided in the driver interface so that the driver can derive
+ * from this struct for its driver_private, and accordingly
+ * access the driver_private from the fence driver callbacks.
+ *
+ * All members except "count" are initialized at creation and
+ * never touched after that. No protection needed.
+ *
+ * This struct is private to the fence implementation and to the fence
+ * driver callbacks, and may otherwise be used by drivers only to
+ * obtain the derived device_private object using container_of().
+ */
+
+struct ttm_fence_device {
+	struct ttm_mem_global *mem_glob;
+	struct ttm_fence_class_manager *fence_class;
+	uint32_t num_classes;
+	atomic_t count;
+	const struct ttm_fence_driver *driver;
+};
+
+/**
+ * struct ttm_fence_class_init
+ *
+ * @wrap_diff:    Fence sequence number wrap indicator. If
+ * (sequence1 - sequence2) > @wrap_diff, then sequence1 is
+ * considered to be older than sequence2.
+ * @flush_diff:   Fence sequence number flush indicator.
+ * If a non-completely-signaled fence has a fence sequence number
+ * sequence1 and (sequence1 - current_emit_sequence) > @flush_diff,
+ * the fence is considered too old and it will be flushed upon the
+ * next call of ttm_fence_flush_old(), to make sure no fences with
+ * stale sequence numbers remains unsignaled. @flush_diff should
+ * be sufficiently less than @wrap_diff.
+ * @sequence_mask: Mask with valid bits of the fence sequence
+ * number set to 1.
+ *
+ * This struct is used as input to ttm_fence_device_init.
+ */
+
+struct ttm_fence_class_init {
+	uint32_t wrap_diff;
+	uint32_t flush_diff;
+	uint32_t sequence_mask;
+};
+
+/**
+ * struct ttm_fence_driver
+ *
+ * @has_irq: Called by a potential waiter. Should return 1 if a
+ * fence object with indicated parameters is expected to signal
+ * automatically, and 0 if the fence implementation needs to
+ * repeatedly call @poll to make it signal.
+ * @emit:    Make sure a fence with the given parameters is
+ * present in the indicated command stream. Return its sequence number
+ * in "breadcrumb".
+ * @poll:    Check and report sequences of the given "fence_class"
+ *           that have signaled "types"
+ * @flush:   Make sure that the types indicated by the bitfield
+ *           ttm_fence_class_manager::pending_flush will eventually
+ *           signal. These bits have been put together using the
+ *           result from the needed_flush function described below.
+ * @needed_flush: Given the fence_class and fence_types indicated by
+ *           "fence", and the last received fence sequence of this
+ *           fence class, indicate what types need a fence flush to
+ *           signal. Return as a bitfield.
+ * @wait:    Set to non-NULL if the driver wants to override the fence
+ *           wait implementation. Return 0 on success, -EBUSY on failure,
+ *           and -ERESTART if interruptible and a signal is pending.
+ * @signaled:  Driver callback that is called whenever a
+ *           ttm_fence_object::signaled_types has changed status.
+ *           This function is called from atomic context,
+ *           with the ttm_fence_class_manager::lock held in write mode.
+ * @lockup:  Driver callback that is called whenever a wait has exceeded
+ *           the lifetime of a fence object.
+ *           If there is a GPU lockup,
+ *           this function should, if possible, reset the GPU,
+ *           call the ttm_fence_handler with an error status, and
+ *           return. If no lockup was detected, simply extend the
+ *           fence timeout_jiffies and return. The driver might
+ *           want to protect the lockup check with a mutex and cache a
+ *           non-locked-up status for a while to avoid an excessive
+ *           amount of lockup checks from every waiting thread.
+ */
+
+struct ttm_fence_driver {
+	bool (*has_irq) (struct ttm_fence_device *fdev,
+			uint32_t fence_class, uint32_t flags);
+	int (*emit) (struct ttm_fence_device *fdev,
+		     uint32_t fence_class,
+		     uint32_t flags,
+		     uint32_t *breadcrumb, unsigned long *timeout_jiffies);
+	void (*flush) (struct ttm_fence_device *fdev, uint32_t fence_class);
+	void (*poll) (struct ttm_fence_device *fdev,
+		      uint32_t fence_class, uint32_t types);
+	 uint32_t(*needed_flush)
+	 (struct ttm_fence_object *fence);
+	int (*wait) (struct ttm_fence_object *fence, bool lazy,
+		     bool interruptible, uint32_t mask);
+	void (*signaled) (struct ttm_fence_object *fence);
+	void (*lockup) (struct ttm_fence_object *fence, uint32_t fence_types);
+};
+
+/**
+ * function ttm_fence_device_init
+ *
+ * @num_classes:      Number of fence classes for this fence implementation.
+ * @mem_global:       Pointer to the global memory accounting info.
+ * @fdev:             Pointer to an uninitialised struct ttm_fence_device.
+ * @init:             Array of initialization info for each fence class.
+ * @replicate_init:   Use the first @init initialization info for all classes.
+ * @driver:           Driver callbacks.
+ *
+ * Initialize a struct ttm_fence_driver structure. Returns -ENOMEM if
+ * out-of-memory. Otherwise returns 0.
+ */
+extern int
+ttm_fence_device_init(int num_classes,
+		      struct ttm_mem_global *mem_glob,
+		      struct ttm_fence_device *fdev,
+		      const struct ttm_fence_class_init *init,
+		      bool replicate_init,
+		      const struct ttm_fence_driver *driver);
+
+/**
+ * function ttm_fence_device_release
+ *
+ * @fdev:             Pointer to the fence device.
+ *
+ * Release all resources held by a fence device. Note that before
+ * this function is called, the caller must have made sure all fence
+ * objects belonging to this fence device are completely signaled.
+ */
+
+extern void ttm_fence_device_release(struct ttm_fence_device *fdev);
+
+/**
+ * ttm_fence_handler - the fence handler.
+ *
+ * @fdev:        Pointer to the fence device.
+ * @fence_class: Fence class that signals.
+ * @sequence:    Signaled sequence.
+ * @type:        Types that signal.
+ * @error:       Error from the engine.
+ *
+ * This function signals all fences with a sequence previous to the
+ * @sequence argument, and belonging to @fence_class. The signaled fence
+ * types are provided in @type. If error is non-zero, the error member
+ * of the fence with sequence = @sequence is set to @error. This value
+ * may be reported back to user-space, indicating, for example an illegal
+ * 3D command or illegal mpeg data.
+ *
+ * This function is typically called from the driver::poll method when the
+ * command sequence preceding the fence marker has executed. It should be
+ * called with the ttm_fence_class_manager::lock held in write mode and
+ * may be called from interrupt context.
+ */
+
+extern void
+ttm_fence_handler(struct ttm_fence_device *fdev,
+		  uint32_t fence_class,
+		  uint32_t sequence, uint32_t type, uint32_t error);
+
+/**
+ * ttm_fence_driver_from_dev
+ *
+ * @fdev:        The ttm fence device.
+ *
+ * Returns a pointer to the fence driver struct.
+ */
+
+static inline const struct ttm_fence_driver *ttm_fence_driver_from_dev(
+						struct ttm_fence_device *fdev)
+{
+	return fdev->driver;
+}
+
+/**
+ * ttm_fence_driver
+ *
+ * @fence:        Pointer to a ttm fence object.
+ *
+ * Returns a pointer to the fence driver struct.
+ */
+
+static inline const struct ttm_fence_driver *ttm_fence_driver(struct
+							      ttm_fence_object
+							      *fence)
+{
+	return ttm_fence_driver_from_dev(fence->fdev);
+}
+
+/**
+ * ttm_fence_fc
+ *
+ * @fence:        Pointer to a ttm fence object.
+ *
+ * Returns a pointer to the struct ttm_fence_class_manager for the
+ * fence class of @fence.
+ */
+
+static inline struct ttm_fence_class_manager *ttm_fence_fc(struct
+							   ttm_fence_object
+							   *fence)
+{
+	return &fence->fdev->fence_class[fence->fence_class];
+}
+
+#endif
diff --git a/drivers/staging/gma500/psb_ttm_fence_user.c b/drivers/staging/gma500/psb_ttm_fence_user.c
new file mode 100644
index 0000000..36f974f
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_fence_user.c
@@ -0,0 +1,237 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include <drm/drmP.h>
+#include "psb_ttm_fence_user.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_driver.h"
+#include "psb_ttm_userobj_api.h"
+
+/**
+ * struct ttm_fence_user_object
+ *
+ * @base:    The base object used for user-space visibility and refcounting.
+ *
+ * @fence:   The fence object itself.
+ *
+ */
+
+struct ttm_fence_user_object {
+	struct ttm_base_object base;
+	struct ttm_fence_object fence;
+};
+
+static struct ttm_fence_user_object *ttm_fence_user_object_lookup(
+					struct ttm_object_file *tfile,
+					uint32_t handle)
+{
+	struct ttm_base_object *base;
+
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Invalid fence handle 0x%08lx\n",
+		       (unsigned long)handle);
+		return NULL;
+	}
+
+	if (unlikely(base->object_type != ttm_fence_type)) {
+		ttm_base_object_unref(&base);
+		printk(KERN_ERR "Invalid fence handle 0x%08lx\n",
+		       (unsigned long)handle);
+		return NULL;
+	}
+
+	return container_of(base, struct ttm_fence_user_object, base);
+}
+
+/*
+ * The fence object destructor.
+ */
+
+static void ttm_fence_user_destroy(struct ttm_fence_object *fence)
+{
+	struct ttm_fence_user_object *ufence =
+	    container_of(fence, struct ttm_fence_user_object, fence);
+
+	ttm_mem_global_free(fence->fdev->mem_glob, sizeof(*ufence));
+	kfree(ufence);
+}
+
+/*
+ * The base object destructor. We basically unly unreference the
+ * attached fence object.
+ */
+
+static void ttm_fence_user_release(struct ttm_base_object **p_base)
+{
+	struct ttm_fence_user_object *ufence;
+	struct ttm_base_object *base = *p_base;
+	struct ttm_fence_object *fence;
+
+	*p_base = NULL;
+
+	if (unlikely(base == NULL))
+		return;
+
+	ufence = container_of(base, struct ttm_fence_user_object, base);
+	fence = &ufence->fence;
+	ttm_fence_object_unref(&fence);
+}
+
+int
+ttm_fence_user_create(struct ttm_fence_device *fdev,
+		      struct ttm_object_file *tfile,
+		      uint32_t fence_class,
+		      uint32_t fence_types,
+		      uint32_t create_flags,
+		      struct ttm_fence_object **fence,
+		      uint32_t *user_handle)
+{
+	int ret;
+	struct ttm_fence_object *tmp;
+	struct ttm_fence_user_object *ufence;
+
+	ret = ttm_mem_global_alloc(fdev->mem_glob,
+				   sizeof(*ufence),
+				   false,
+				   false);
+	if (unlikely(ret != 0))
+		return -ENOMEM;
+
+	ufence = kmalloc(sizeof(*ufence), GFP_KERNEL);
+	if (unlikely(ufence == NULL)) {
+		ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence));
+		return -ENOMEM;
+	}
+
+	ret = ttm_fence_object_init(fdev,
+				    fence_class,
+				    fence_types, create_flags,
+				    &ttm_fence_user_destroy, &ufence->fence);
+
+	if (unlikely(ret != 0))
+		goto out_err0;
+
+	/*
+	 * One fence ref is held by the fence ptr we return.
+	 * The other one by the base object. Need to up the
+	 * fence refcount before we publish this object to
+	 * user-space.
+	 */
+
+	tmp = ttm_fence_object_ref(&ufence->fence);
+	ret = ttm_base_object_init(tfile, &ufence->base,
+				   false, ttm_fence_type,
+				   &ttm_fence_user_release, NULL);
+
+	if (unlikely(ret != 0))
+		goto out_err1;
+
+	*fence = &ufence->fence;
+	*user_handle = ufence->base.hash.key;
+
+	return 0;
+out_err1:
+	ttm_fence_object_unref(&tmp);
+	tmp = &ufence->fence;
+	ttm_fence_object_unref(&tmp);
+	return ret;
+out_err0:
+	ttm_mem_global_free(fdev->mem_glob, sizeof(*ufence));
+	kfree(ufence);
+	return ret;
+}
+
+int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	int ret;
+	union ttm_fence_signaled_arg *arg = data;
+	struct ttm_fence_object *fence;
+	struct ttm_fence_info info;
+	struct ttm_fence_user_object *ufence;
+	struct ttm_base_object *base;
+	ret = 0;
+
+	ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle);
+	if (unlikely(ufence == NULL))
+		return -EINVAL;
+
+	fence = &ufence->fence;
+
+	if (arg->req.flush) {
+		ret = ttm_fence_object_flush(fence, arg->req.fence_type);
+		if (unlikely(ret != 0))
+			goto out;
+	}
+
+	info = ttm_fence_get_info(fence);
+	arg->rep.signaled_types = info.signaled_types;
+	arg->rep.fence_error = info.error;
+
+out:
+	base = &ufence->base;
+	ttm_base_object_unref(&base);
+	return ret;
+}
+
+int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	int ret;
+	union ttm_fence_finish_arg *arg = data;
+	struct ttm_fence_user_object *ufence;
+	struct ttm_base_object *base;
+	struct ttm_fence_object *fence;
+	ret = 0;
+
+	ufence = ttm_fence_user_object_lookup(tfile, arg->req.handle);
+	if (unlikely(ufence == NULL))
+		return -EINVAL;
+
+	fence = &ufence->fence;
+
+	ret = ttm_fence_object_wait(fence,
+				    arg->req.mode & TTM_FENCE_FINISH_MODE_LAZY,
+				    true, arg->req.fence_type);
+	if (likely(ret == 0)) {
+		struct ttm_fence_info info = ttm_fence_get_info(fence);
+
+		arg->rep.signaled_types = info.signaled_types;
+		arg->rep.fence_error = info.error;
+	}
+
+	base = &ufence->base;
+	ttm_base_object_unref(&base);
+
+	return ret;
+}
+
+int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	struct ttm_fence_unref_arg *arg = data;
+	int ret = 0;
+
+	ret = ttm_ref_object_base_unref(tfile, arg->handle, ttm_fence_type);
+	return ret;
+}
diff --git a/drivers/staging/gma500/psb_ttm_fence_user.h b/drivers/staging/gma500/psb_ttm_fence_user.h
new file mode 100644
index 0000000..fc13f89
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_fence_user.h
@@ -0,0 +1,140 @@
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors
+ * Thomas HellstrĂśm <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef TTM_FENCE_USER_H
+#define TTM_FENCE_USER_H
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#endif
+
+#define TTM_FENCE_MAJOR 0
+#define TTM_FENCE_MINOR 1
+#define TTM_FENCE_PL    0
+#define TTM_FENCE_DATE  "080819"
+
+/**
+ * struct ttm_fence_signaled_req
+ *
+ * @handle: Handle to the fence object. Input.
+ *
+ * @fence_type: Fence types we want to flush. Input.
+ *
+ * @flush: Boolean. Flush the indicated fence_types. Input.
+ *
+ * Argument to the TTM_FENCE_SIGNALED ioctl.
+ */
+
+struct ttm_fence_signaled_req {
+	uint32_t handle;
+	uint32_t fence_type;
+	int32_t flush;
+	uint32_t pad64;
+};
+
+/**
+ * struct ttm_fence_rep
+ *
+ * @signaled_types: Fence type that has signaled.
+ *
+ * @fence_error: Command execution error.
+ * Hardware errors that are consequences of the execution
+ * of the command stream preceding the fence are reported
+ * here.
+ *
+ * Output argument to the TTM_FENCE_SIGNALED and
+ * TTM_FENCE_FINISH ioctls.
+ */
+
+struct ttm_fence_rep {
+	uint32_t signaled_types;
+	uint32_t fence_error;
+};
+
+union ttm_fence_signaled_arg {
+	struct ttm_fence_signaled_req req;
+	struct ttm_fence_rep rep;
+};
+
+/*
+ * Waiting mode flags for the TTM_FENCE_FINISH ioctl.
+ *
+ * TTM_FENCE_FINISH_MODE_LAZY: Allow for sleeps during polling
+ * wait.
+ *
+ * TTM_FENCE_FINISH_MODE_NO_BLOCK: Don't block waiting for GPU,
+ * but return -EBUSY if the buffer is busy.
+ */
+
+#define TTM_FENCE_FINISH_MODE_LAZY     (1 << 0)
+#define TTM_FENCE_FINISH_MODE_NO_BLOCK (1 << 1)
+
+/**
+ * struct ttm_fence_finish_req
+ *
+ * @handle: Handle to the fence object. Input.
+ *
+ * @fence_type: Fence types we want to finish.
+ *
+ * @mode: Wait mode.
+ *
+ * Input to the TTM_FENCE_FINISH ioctl.
+ */
+
+struct ttm_fence_finish_req {
+	uint32_t handle;
+	uint32_t fence_type;
+	uint32_t mode;
+	uint32_t pad64;
+};
+
+union ttm_fence_finish_arg {
+	struct ttm_fence_finish_req req;
+	struct ttm_fence_rep rep;
+};
+
+/**
+ * struct ttm_fence_unref_arg
+ *
+ * @handle: Handle to the fence object.
+ *
+ * Argument to the TTM_FENCE_UNREF ioctl.
+ */
+
+struct ttm_fence_unref_arg {
+	uint32_t handle;
+	uint32_t pad64;
+};
+
+/*
+ * Ioctl offsets frome extenstion start.
+ */
+
+#define TTM_FENCE_SIGNALED 0x01
+#define TTM_FENCE_FINISH   0x02
+#define TTM_FENCE_UNREF    0x03
+
+#endif
diff --git a/drivers/staging/gma500/psb_ttm_glue.c b/drivers/staging/gma500/psb_ttm_glue.c
new file mode 100644
index 0000000..d1d965e
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_glue.c
@@ -0,0 +1,349 @@
+/**************************************************************************
+ * Copyright (c) 2008, Intel Corporation.
+ * All Rights Reserved.
+ * Copyright (c) 2008, Tungsten Graphics Inc.  Cedar Park, TX., USA.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+
+
+#include <drm/drmP.h>
+#include "psb_drv.h"
+#include "psb_ttm_userobj_api.h"
+#include <linux/io.h>
+
+
+static struct vm_operations_struct psb_ttm_vm_ops;
+
+/**
+ * NOTE: driver_private of drm_file is now a struct psb_file_data struct
+ * pPriv in struct psb_file_data contains the original psb_fpriv;
+ */
+int psb_open(struct inode *inode, struct file *filp)
+{
+	struct drm_file *file_priv;
+	struct drm_psb_private *dev_priv;
+	struct psb_fpriv *psb_fp;
+	struct psb_file_data *pvr_file_priv;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	ret = drm_open(inode, filp);
+	if (unlikely(ret))
+		return ret;
+
+	psb_fp = kzalloc(sizeof(*psb_fp), GFP_KERNEL);
+
+	if (unlikely(psb_fp == NULL))
+		goto out_err0;
+
+	file_priv = (struct drm_file *) filp->private_data;
+	dev_priv = psb_priv(file_priv->minor->dev);
+
+	DRM_DEBUG("is_master %d\n", file_priv->is_master ? 1 : 0);
+
+	psb_fp->tfile = ttm_object_file_init(dev_priv->tdev,
+					     PSB_FILE_OBJECT_HASH_ORDER);
+	if (unlikely(psb_fp->tfile == NULL))
+		goto out_err1;
+
+	pvr_file_priv = (struct psb_file_data *)file_priv->driver_priv;
+	if (!pvr_file_priv) {
+		DRM_ERROR("drm file private is NULL\n");
+		goto out_err1;
+	}
+
+	pvr_file_priv->priv = psb_fp;
+	if (unlikely(dev_priv->bdev.dev_mapping == NULL))
+		dev_priv->bdev.dev_mapping = dev_priv->dev->dev_mapping;
+
+	return 0;
+
+out_err1:
+	kfree(psb_fp);
+out_err0:
+	(void) drm_release(inode, filp);
+	return ret;
+}
+
+int psb_release(struct inode *inode, struct file *filp)
+{
+	struct drm_file *file_priv;
+	struct psb_fpriv *psb_fp;
+	struct drm_psb_private *dev_priv;
+	int ret;
+	file_priv = (struct drm_file *) filp->private_data;
+	psb_fp = psb_fpriv(file_priv);
+	dev_priv = psb_priv(file_priv->minor->dev);
+
+	ttm_object_file_release(&psb_fp->tfile);
+	kfree(psb_fp);
+
+	ret = drm_release(inode, filp);
+
+	return ret;
+}
+
+int psb_fence_signaled_ioctl(struct drm_device *dev, void *data,
+			     struct drm_file *file_priv)
+{
+
+	return ttm_fence_signaled_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_fence_finish_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	return ttm_fence_finish_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_fence_unref_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	return ttm_fence_unref_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_waitidle_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *file_priv)
+{
+	return ttm_pl_waitidle_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_setstatus_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	return ttm_pl_setstatus_ioctl(psb_fpriv(file_priv)->tfile,
+				      &psb_priv(dev)->ttm_lock, data);
+
+}
+
+int psb_pl_synccpu_ioctl(struct drm_device *dev, void *data,
+			 struct drm_file *file_priv)
+{
+	return ttm_pl_synccpu_ioctl(psb_fpriv(file_priv)->tfile, data);
+}
+
+int psb_pl_unref_ioctl(struct drm_device *dev, void *data,
+		       struct drm_file *file_priv)
+{
+	return ttm_pl_unref_ioctl(psb_fpriv(file_priv)->tfile, data);
+
+}
+
+int psb_pl_reference_ioctl(struct drm_device *dev, void *data,
+			   struct drm_file *file_priv)
+{
+	return  ttm_pl_reference_ioctl(psb_fpriv(file_priv)->tfile, data);
+
+}
+
+int psb_pl_create_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+
+	return ttm_pl_create_ioctl(psb_fpriv(file_priv)->tfile,
+				   &dev_priv->bdev, &dev_priv->ttm_lock, data);
+
+}
+
+int psb_pl_ub_create_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file_priv)
+{
+	struct drm_psb_private *dev_priv = psb_priv(dev);
+
+	return ttm_pl_ub_create_ioctl(psb_fpriv(file_priv)->tfile,
+				   &dev_priv->bdev, &dev_priv->ttm_lock, data);
+
+}
+/**
+ * psb_ttm_fault - Wrapper around the ttm fault method.
+ *
+ * @vma: The struct vm_area_struct as in the vm fault() method.
+ * @vmf: The struct vm_fault as in the vm fault() method.
+ *
+ * Since ttm_fault() will reserve buffers while faulting,
+ * we need to take the ttm read lock around it, as this driver
+ * relies on the ttm_lock in write mode to exclude all threads from
+ * reserving and thus validating buffers in aperture- and memory shortage
+ * situations.
+ */
+
+static int psb_ttm_fault(struct vm_area_struct *vma,
+			 struct vm_fault *vmf)
+{
+	struct ttm_buffer_object *bo = (struct ttm_buffer_object *)
+		vma->vm_private_data;
+	struct drm_psb_private *dev_priv =
+		container_of(bo->bdev, struct drm_psb_private, bdev);
+	int ret;
+
+	ret = ttm_read_lock(&dev_priv->ttm_lock, true);
+	if (unlikely(ret != 0))
+		return VM_FAULT_NOPAGE;
+
+	ret = dev_priv->ttm_vm_ops->fault(vma, vmf);
+
+	ttm_read_unlock(&dev_priv->ttm_lock);
+	return ret;
+}
+
+/**
+ * if vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET call directly to
+ * PVRMMap
+ */
+int psb_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct drm_file *file_priv;
+	struct drm_psb_private *dev_priv;
+	int ret;
+
+	if (vma->vm_pgoff < DRM_PSB_FILE_PAGE_OFFSET ||
+	    vma->vm_pgoff > 2 * DRM_PSB_FILE_PAGE_OFFSET)
+#if 0		/* FIXMEAC */
+		return PVRMMap(filp, vma);
+#else
+		return -EINVAL;
+#endif
+
+	file_priv = (struct drm_file *) filp->private_data;
+	dev_priv = psb_priv(file_priv->minor->dev);
+
+	ret = ttm_bo_mmap(filp, vma, &dev_priv->bdev);
+	if (unlikely(ret != 0))
+		return ret;
+
+	if (unlikely(dev_priv->ttm_vm_ops == NULL)) {
+		dev_priv->ttm_vm_ops = (struct vm_operations_struct *)
+								vma->vm_ops;
+		psb_ttm_vm_ops = *vma->vm_ops;
+		psb_ttm_vm_ops.fault = &psb_ttm_fault;
+	}
+
+	vma->vm_ops = &psb_ttm_vm_ops;
+
+	return 0;
+}
+/*
+ssize_t psb_ttm_write(struct file *filp, const char __user *buf,
+		      size_t count, loff_t *f_pos)
+{
+	struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+	struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev);
+
+	return ttm_bo_io(&dev_priv->bdev, filp, buf, NULL, count, f_pos, 1);
+}
+
+ssize_t psb_ttm_read(struct file *filp, char __user *buf,
+		     size_t count, loff_t *f_pos)
+{
+	struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+	struct drm_psb_private *dev_priv = psb_priv(file_priv->minor->dev);
+
+	return ttm_bo_io(&dev_priv->bdev, filp, NULL, buf, count, f_pos, 1);
+}
+*/
+int psb_verify_access(struct ttm_buffer_object *bo,
+		      struct file *filp)
+{
+	struct drm_file *file_priv = (struct drm_file *)filp->private_data;
+
+	if (capable(CAP_SYS_ADMIN))
+		return 0;
+
+	if (unlikely(!file_priv->authenticated))
+		return -EPERM;
+
+	return ttm_pl_verify_access(bo, psb_fpriv(file_priv)->tfile);
+}
+
+static int psb_ttm_mem_global_init(struct drm_global_reference *ref)
+{
+	return ttm_mem_global_init(ref->object);
+}
+
+static void psb_ttm_mem_global_release(struct drm_global_reference *ref)
+{
+	ttm_mem_global_release(ref->object);
+}
+
+int psb_ttm_global_init(struct drm_psb_private *dev_priv)
+{
+	struct drm_global_reference *global_ref;
+	int ret;
+
+	global_ref = &dev_priv->mem_global_ref;
+	global_ref->global_type = DRM_GLOBAL_TTM_MEM;
+	global_ref->size = sizeof(struct ttm_mem_global);
+	global_ref->init = &psb_ttm_mem_global_init;
+	global_ref->release = &psb_ttm_mem_global_release;
+
+	ret = drm_global_item_ref(global_ref);
+	if (unlikely(ret != 0)) {
+		DRM_ERROR("Failed referencing a global TTM memory object.\n");
+		return ret;
+	}
+
+	dev_priv->bo_global_ref.mem_glob = dev_priv->mem_global_ref.object;
+	global_ref = &dev_priv->bo_global_ref.ref;
+	global_ref->global_type = DRM_GLOBAL_TTM_BO;
+	global_ref->size = sizeof(struct ttm_bo_global);
+	global_ref->init = &ttm_bo_global_init;
+	global_ref->release = &ttm_bo_global_release;
+	ret = drm_global_item_ref(global_ref);
+	if (ret != 0) {
+		DRM_ERROR("Failed setting up TTM BO subsystem.\n");
+		drm_global_item_unref(global_ref);
+		return ret;
+	}
+	return 0;
+}
+
+void psb_ttm_global_release(struct drm_psb_private *dev_priv)
+{
+	drm_global_item_unref(&dev_priv->mem_global_ref);
+}
+
+int psb_getpageaddrs_ioctl(struct drm_device *dev, void *data,
+		struct drm_file *file_priv)
+{
+	struct drm_psb_getpageaddrs_arg *arg = data;
+	struct ttm_buffer_object *bo;
+	struct ttm_tt *ttm;
+	struct page **tt_pages;
+	unsigned long i, num_pages;
+	unsigned long *p = arg->page_addrs;
+	int ret = 0;
+
+	bo = ttm_buffer_object_lookup(psb_fpriv(file_priv)->tfile,
+					arg->handle);
+	if (unlikely(bo == NULL)) {
+		printk(KERN_ERR
+			"Could not find buffer object for getpageaddrs.\n");
+		return -EINVAL;
+	}
+
+	arg->gtt_offset = bo->offset;
+	ttm = bo->ttm;
+	num_pages = ttm->num_pages;
+	tt_pages = ttm->pages;
+
+	for (i = 0; i < num_pages; i++)
+		p[i] = (unsigned long)page_to_phys(tt_pages[i]);
+
+	return ret;
+}
diff --git a/drivers/staging/gma500/psb_ttm_placement_user.c b/drivers/staging/gma500/psb_ttm_placement_user.c
new file mode 100644
index 0000000..272b397
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_placement_user.c
@@ -0,0 +1,628 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#include "psb_ttm_placement_user.h"
+#include "ttm/ttm_bo_driver.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_userobj_api.h"
+#include "ttm/ttm_lock.h"
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+struct ttm_bo_user_object {
+	struct ttm_base_object base;
+	struct ttm_buffer_object bo;
+};
+
+static size_t pl_bo_size;
+
+static uint32_t psb_busy_prios[] = {
+	TTM_PL_TT,
+	TTM_PL_PRIV0, /* CI */
+	TTM_PL_PRIV2, /* RAR */
+	TTM_PL_PRIV1, /* DRM_PSB_MEM_MMU */
+	TTM_PL_SYSTEM
+};
+
+static const struct ttm_placement default_placement = {
+				0, 0, 0, NULL, 5, psb_busy_prios
+};
+
+static size_t ttm_pl_size(struct ttm_bo_device *bdev, unsigned long num_pages)
+{
+	size_t page_array_size =
+	    (num_pages * sizeof(void *) + PAGE_SIZE - 1) & PAGE_MASK;
+
+	if (unlikely(pl_bo_size == 0)) {
+		pl_bo_size = bdev->glob->ttm_bo_extra_size +
+		    ttm_round_pot(sizeof(struct ttm_bo_user_object));
+	}
+
+	return bdev->glob->ttm_bo_size + 2 * page_array_size;
+}
+
+static struct ttm_bo_user_object *ttm_bo_user_lookup(struct ttm_object_file
+						     *tfile, uint32_t handle)
+{
+	struct ttm_base_object *base;
+
+	base = ttm_base_object_lookup(tfile, handle);
+	if (unlikely(base == NULL)) {
+		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return NULL;
+	}
+
+	if (unlikely(base->object_type != ttm_buffer_type)) {
+		ttm_base_object_unref(&base);
+		printk(KERN_ERR "Invalid buffer object handle 0x%08lx.\n",
+		       (unsigned long)handle);
+		return NULL;
+	}
+
+	return container_of(base, struct ttm_bo_user_object, base);
+}
+
+struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
+						   *tfile, uint32_t handle)
+{
+	struct ttm_bo_user_object *user_bo;
+	struct ttm_base_object *base;
+
+	user_bo = ttm_bo_user_lookup(tfile, handle);
+	if (unlikely(user_bo == NULL))
+		return NULL;
+
+	(void)ttm_bo_reference(&user_bo->bo);
+	base = &user_bo->base;
+	ttm_base_object_unref(&base);
+	return &user_bo->bo;
+}
+
+static void ttm_bo_user_destroy(struct ttm_buffer_object *bo)
+{
+	struct ttm_bo_user_object *user_bo =
+	    container_of(bo, struct ttm_bo_user_object, bo);
+
+	ttm_mem_global_free(bo->glob->mem_glob, bo->acc_size);
+	kfree(user_bo);
+}
+
+static void ttm_bo_user_release(struct ttm_base_object **p_base)
+{
+	struct ttm_bo_user_object *user_bo;
+	struct ttm_base_object *base = *p_base;
+	struct ttm_buffer_object *bo;
+
+	*p_base = NULL;
+
+	if (unlikely(base == NULL))
+		return;
+
+	user_bo = container_of(base, struct ttm_bo_user_object, base);
+	bo = &user_bo->bo;
+	ttm_bo_unref(&bo);
+}
+
+static void ttm_bo_user_ref_release(struct ttm_base_object *base,
+				    enum ttm_ref_type ref_type)
+{
+	struct ttm_bo_user_object *user_bo =
+	    container_of(base, struct ttm_bo_user_object, base);
+	struct ttm_buffer_object *bo = &user_bo->bo;
+
+	switch (ref_type) {
+	case TTM_REF_SYNCCPU_WRITE:
+		ttm_bo_synccpu_write_release(bo);
+		break;
+	default:
+		BUG();
+	}
+}
+
+static void ttm_pl_fill_rep(struct ttm_buffer_object *bo,
+			    struct ttm_pl_rep *rep)
+{
+	struct ttm_bo_user_object *user_bo =
+	    container_of(bo, struct ttm_bo_user_object, bo);
+
+	rep->gpu_offset = bo->offset;
+	rep->bo_size = bo->num_pages << PAGE_SHIFT;
+	rep->map_handle = bo->addr_space_offset;
+	rep->placement = bo->mem.placement;
+	rep->handle = user_bo->base.hash.key;
+	rep->sync_object_arg = (uint32_t) (unsigned long)bo->sync_obj_arg;
+}
+
+/* FIXME Copy from upstream TTM */
+static inline size_t ttm_bo_size(struct ttm_bo_global *glob,
+				 unsigned long num_pages)
+{
+	size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) &
+	    PAGE_MASK;
+
+	return glob->ttm_bo_size + 2 * page_array_size;
+}
+
+/* FIXME Copy from upstream TTM "ttm_bo_create", upstream TTM does not
+   export this, so copy it here */
+static int ttm_bo_create_private(struct ttm_bo_device *bdev,
+			unsigned long size,
+			enum ttm_bo_type type,
+			struct ttm_placement *placement,
+			uint32_t page_alignment,
+			unsigned long buffer_start,
+			bool interruptible,
+			struct file *persistant_swap_storage,
+			struct ttm_buffer_object **p_bo)
+{
+	struct ttm_buffer_object *bo;
+	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+	int ret;
+
+	size_t acc_size =
+	    ttm_bo_size(bdev->glob, (size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
+
+	if (unlikely(bo == NULL)) {
+		ttm_mem_global_free(mem_glob, acc_size);
+		return -ENOMEM;
+	}
+
+	ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
+				buffer_start, interruptible,
+				persistant_swap_storage, acc_size, NULL);
+	if (likely(ret == 0))
+		*p_bo = bo;
+
+	return ret;
+}
+
+int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo,
+				struct ttm_placement *placement)
+{
+	int i;
+
+	for (i = 0; i < placement->num_placement; i++) {
+		if (!capable(CAP_SYS_ADMIN)) {
+			if (placement->placement[i] & TTM_PL_FLAG_NO_EVICT) {
+				printk(KERN_ERR TTM_PFX "Need to be root to "
+					"modify NO_EVICT status.\n");
+				return -EINVAL;
+			}
+		}
+	}
+	for (i = 0; i < placement->num_busy_placement; i++) {
+		if (!capable(CAP_SYS_ADMIN)) {
+			if (placement->busy_placement[i]
+						& TTM_PL_FLAG_NO_EVICT) {
+				printk(KERN_ERR TTM_PFX "Need to be root to modify NO_EVICT status.\n");
+				return -EINVAL;
+			}
+		}
+	}
+	return 0;
+}
+
+int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+			unsigned long size,
+			enum ttm_bo_type type,
+			uint32_t flags,
+			uint32_t page_alignment,
+			unsigned long buffer_start,
+			bool interruptible,
+			struct file *persistant_swap_storage,
+			struct ttm_buffer_object **p_bo)
+{
+	struct ttm_placement placement = default_placement;
+	int ret;
+
+	if ((flags & TTM_PL_MASK_CACHING) == 0)
+		flags |= TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+
+	placement.num_placement = 1;
+	placement.placement = &flags;
+
+	ret = ttm_bo_create_private(bdev,
+			size,
+			type,
+			&placement,
+			page_alignment,
+			buffer_start,
+			interruptible,
+			persistant_swap_storage,
+			p_bo);
+
+	return ret;
+}
+
+
+int ttm_pl_create_ioctl(struct ttm_object_file *tfile,
+			struct ttm_bo_device *bdev,
+			struct ttm_lock *lock, void *data)
+{
+	union ttm_pl_create_arg *arg = data;
+	struct ttm_pl_create_req *req = &arg->req;
+	struct ttm_pl_rep *rep = &arg->rep;
+	struct ttm_buffer_object *bo;
+	struct ttm_buffer_object *tmp;
+	struct ttm_bo_user_object *user_bo;
+	uint32_t flags;
+	int ret = 0;
+	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+	struct ttm_placement placement = default_placement;
+	size_t acc_size =
+	    ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	flags = req->placement;
+	user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+	if (unlikely(user_bo == NULL)) {
+		ttm_mem_global_free(mem_glob, acc_size);
+		return -ENOMEM;
+	}
+
+	bo = &user_bo->bo;
+	ret = ttm_read_lock(lock, true);
+	if (unlikely(ret != 0)) {
+		ttm_mem_global_free(mem_glob, acc_size);
+		kfree(user_bo);
+		return ret;
+	}
+
+	placement.num_placement = 1;
+	placement.placement = &flags;
+
+	if ((flags & TTM_PL_MASK_CACHING) == 0)
+		flags |=  TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
+
+	ret = ttm_bo_init(bdev, bo, req->size,
+				     ttm_bo_type_device, &placement,
+				     req->page_alignment, 0, true,
+				     NULL, acc_size, &ttm_bo_user_destroy);
+	ttm_read_unlock(lock);
+
+	/*
+	 * Note that the ttm_buffer_object_init function
+	 * would've called the destroy function on failure!!
+	 */
+
+	if (unlikely(ret != 0))
+		goto out;
+
+	tmp = ttm_bo_reference(bo);
+	ret = ttm_base_object_init(tfile, &user_bo->base,
+				   flags & TTM_PL_FLAG_SHARED,
+				   ttm_buffer_type,
+				   &ttm_bo_user_release,
+				   &ttm_bo_user_ref_release);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	ttm_pl_fill_rep(bo, rep);
+	ttm_bo_unref(&bo);
+out:
+	return 0;
+out_err:
+	ttm_bo_unref(&tmp);
+	ttm_bo_unref(&bo);
+	return ret;
+}
+
+int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile,
+			   struct ttm_bo_device *bdev,
+			   struct ttm_lock *lock, void *data)
+{
+	union ttm_pl_create_ub_arg *arg = data;
+	struct ttm_pl_create_ub_req *req = &arg->req;
+	struct ttm_pl_rep *rep = &arg->rep;
+	struct ttm_buffer_object *bo;
+	struct ttm_buffer_object *tmp;
+	struct ttm_bo_user_object *user_bo;
+	uint32_t flags;
+	int ret = 0;
+	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
+	struct ttm_placement placement = default_placement;
+	size_t acc_size =
+	    ttm_pl_size(bdev, (req->size + PAGE_SIZE - 1) >> PAGE_SHIFT);
+	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
+	if (unlikely(ret != 0))
+		return ret;
+
+	flags = req->placement;
+	user_bo = kzalloc(sizeof(*user_bo), GFP_KERNEL);
+	if (unlikely(user_bo == NULL)) {
+		ttm_mem_global_free(mem_glob, acc_size);
+		return -ENOMEM;
+	}
+	ret = ttm_read_lock(lock, true);
+	if (unlikely(ret != 0)) {
+		ttm_mem_global_free(mem_glob, acc_size);
+		kfree(user_bo);
+		return ret;
+	}
+	bo = &user_bo->bo;
+
+	placement.num_placement = 1;
+	placement.placement = &flags;
+
+	ret = ttm_bo_init(bdev,
+					bo,
+					req->size,
+					ttm_bo_type_user,
+					&placement,
+					req->page_alignment,
+					req->user_address,
+					true,
+					NULL,
+					acc_size,
+					&ttm_bo_user_destroy);
+
+	/*
+	 * Note that the ttm_buffer_object_init function
+	 * would've called the destroy function on failure!!
+	 */
+	ttm_read_unlock(lock);
+	if (unlikely(ret != 0))
+		goto out;
+
+	tmp = ttm_bo_reference(bo);
+	ret = ttm_base_object_init(tfile, &user_bo->base,
+				   flags & TTM_PL_FLAG_SHARED,
+				   ttm_buffer_type,
+				   &ttm_bo_user_release,
+				   &ttm_bo_user_ref_release);
+	if (unlikely(ret != 0))
+		goto out_err;
+
+	ttm_pl_fill_rep(bo, rep);
+	ttm_bo_unref(&bo);
+out:
+	return 0;
+out_err:
+	ttm_bo_unref(&tmp);
+	ttm_bo_unref(&bo);
+	return ret;
+}
+
+int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	union ttm_pl_reference_arg *arg = data;
+	struct ttm_pl_rep *rep = &arg->rep;
+	struct ttm_bo_user_object *user_bo;
+	struct ttm_buffer_object *bo;
+	struct ttm_base_object *base;
+	int ret;
+
+	user_bo = ttm_bo_user_lookup(tfile, arg->req.handle);
+	if (unlikely(user_bo == NULL)) {
+		printk(KERN_ERR "Could not reference buffer object.\n");
+		return -EINVAL;
+	}
+
+	bo = &user_bo->bo;
+	ret = ttm_ref_object_add(tfile, &user_bo->base, TTM_REF_USAGE, NULL);
+	if (unlikely(ret != 0)) {
+		printk(KERN_ERR
+		       "Could not add a reference to buffer object.\n");
+		goto out;
+	}
+
+	ttm_pl_fill_rep(bo, rep);
+
+out:
+	base = &user_bo->base;
+	ttm_base_object_unref(&base);
+	return ret;
+}
+
+int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	struct ttm_pl_reference_req *arg = data;
+
+	return ttm_ref_object_base_unref(tfile, arg->handle, TTM_REF_USAGE);
+}
+
+int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	struct ttm_pl_synccpu_arg *arg = data;
+	struct ttm_bo_user_object *user_bo;
+	struct ttm_buffer_object *bo;
+	struct ttm_base_object *base;
+	bool existed;
+	int ret;
+
+	switch (arg->op) {
+	case TTM_PL_SYNCCPU_OP_GRAB:
+		user_bo = ttm_bo_user_lookup(tfile, arg->handle);
+		if (unlikely(user_bo == NULL)) {
+			printk(KERN_ERR
+			       "Could not find buffer object for synccpu.\n");
+			return -EINVAL;
+		}
+		bo = &user_bo->bo;
+		base = &user_bo->base;
+		ret = ttm_bo_synccpu_write_grab(bo,
+						arg->access_mode &
+						TTM_PL_SYNCCPU_MODE_NO_BLOCK);
+		if (unlikely(ret != 0)) {
+			ttm_base_object_unref(&base);
+			goto out;
+		}
+		ret = ttm_ref_object_add(tfile, &user_bo->base,
+					 TTM_REF_SYNCCPU_WRITE, &existed);
+		if (existed || ret != 0)
+			ttm_bo_synccpu_write_release(bo);
+		ttm_base_object_unref(&base);
+		break;
+	case TTM_PL_SYNCCPU_OP_RELEASE:
+		ret = ttm_ref_object_base_unref(tfile, arg->handle,
+						TTM_REF_SYNCCPU_WRITE);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+out:
+	return ret;
+}
+
+int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile,
+			   struct ttm_lock *lock, void *data)
+{
+	union ttm_pl_setstatus_arg *arg = data;
+	struct ttm_pl_setstatus_req *req = &arg->req;
+	struct ttm_pl_rep *rep = &arg->rep;
+	struct ttm_buffer_object *bo;
+	struct ttm_bo_device *bdev;
+	struct ttm_placement placement = default_placement;
+	uint32_t flags[2];
+	int ret;
+
+	bo = ttm_buffer_object_lookup(tfile, req->handle);
+	if (unlikely(bo == NULL)) {
+		printk(KERN_ERR
+		       "Could not find buffer object for setstatus.\n");
+		return -EINVAL;
+	}
+
+	bdev = bo->bdev;
+
+	ret = ttm_read_lock(lock, true);
+	if (unlikely(ret != 0))
+		goto out_err0;
+
+	ret = ttm_bo_reserve(bo, true, false, false, 0);
+	if (unlikely(ret != 0))
+		goto out_err1;
+
+	ret = ttm_bo_wait_cpu(bo, false);
+	if (unlikely(ret != 0))
+		goto out_err2;
+
+	flags[0] = req->set_placement;
+	flags[1] = req->clr_placement;
+
+	placement.num_placement = 2;
+	placement.placement = flags;
+
+	/* Review internal locking ? FIXMEAC */
+	ret = psb_ttm_bo_check_placement(bo, &placement);
+	if (unlikely(ret != 0))
+		goto out_err2;
+
+	placement.num_placement = 1;
+	flags[0] = (req->set_placement | bo->mem.placement)
+						& ~req->clr_placement;
+
+	ret = ttm_bo_validate(bo, &placement, true, false, false);
+	if (unlikely(ret != 0))
+		goto out_err2;
+
+	ttm_pl_fill_rep(bo, rep);
+out_err2:
+	ttm_bo_unreserve(bo);
+out_err1:
+	ttm_read_unlock(lock);
+out_err0:
+	ttm_bo_unref(&bo);
+	return ret;
+}
+
+static int psb_ttm_bo_block_reservation(struct ttm_buffer_object *bo,
+				bool interruptible, bool no_wait)
+{
+	int ret;
+
+	while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) {
+		if (no_wait)
+			return -EBUSY;
+		else if (interruptible) {
+			ret = wait_event_interruptible(bo->event_queue,
+					atomic_read(&bo->reserved) == 0);
+			if (unlikely(ret != 0))
+				return -ERESTART;
+		} else {
+			wait_event(bo->event_queue,
+				atomic_read(&bo->reserved) == 0);
+		}
+	}
+	return 0;
+}
+
+static void psb_ttm_bo_unblock_reservation(struct ttm_buffer_object *bo)
+{
+	atomic_set(&bo->reserved, 0);
+	wake_up_all(&bo->event_queue);
+}
+
+int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data)
+{
+	struct ttm_pl_waitidle_arg *arg = data;
+	struct ttm_buffer_object *bo;
+	int ret;
+
+	bo = ttm_buffer_object_lookup(tfile, arg->handle);
+	if (unlikely(bo == NULL)) {
+		printk(KERN_ERR "Could not find buffer object for waitidle.\n");
+		return -EINVAL;
+	}
+
+	ret =
+	    psb_ttm_bo_block_reservation(bo, true,
+				     arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK);
+	if (unlikely(ret != 0))
+		goto out;
+	ret = ttm_bo_wait(bo,
+			  arg->mode & TTM_PL_WAITIDLE_MODE_LAZY,
+			  true, arg->mode & TTM_PL_WAITIDLE_MODE_NO_BLOCK);
+	psb_ttm_bo_unblock_reservation(bo);
+out:
+	ttm_bo_unref(&bo);
+	return ret;
+}
+
+int ttm_pl_verify_access(struct ttm_buffer_object *bo,
+			 struct ttm_object_file *tfile)
+{
+	struct ttm_bo_user_object *ubo;
+
+	/*
+	 * Check bo subclass.
+	 */
+
+	if (unlikely(bo->destroy != &ttm_bo_user_destroy))
+		return -EPERM;
+
+	ubo = container_of(bo, struct ttm_bo_user_object, bo);
+	if (likely(ubo->base.shareable || ubo->base.tfile == tfile))
+		return 0;
+
+	return -EPERM;
+}
diff --git a/drivers/staging/gma500/psb_ttm_placement_user.h b/drivers/staging/gma500/psb_ttm_placement_user.h
new file mode 100644
index 0000000..8b7068b
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_placement_user.h
@@ -0,0 +1,252 @@
+/**************************************************************************
+ *
+ * Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors
+ * Thomas HellstrĂśm <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _TTM_PLACEMENT_USER_H_
+#define _TTM_PLACEMENT_USER_H_
+
+#if !defined(__KERNEL__) && !defined(_KERNEL)
+#include <stdint.h>
+#else
+#include <linux/kernel.h>
+#endif
+
+#include "ttm/ttm_placement.h"
+
+#define TTM_PLACEMENT_MAJOR 0
+#define TTM_PLACEMENT_MINOR 1
+#define TTM_PLACEMENT_PL    0
+#define TTM_PLACEMENT_DATE  "080819"
+
+/**
+ * struct ttm_pl_create_req
+ *
+ * @size: The buffer object size.
+ * @placement: Flags that indicate initial acceptable
+ *  placement.
+ * @page_alignment: Required alignment in pages.
+ *
+ * Input to the TTM_BO_CREATE ioctl.
+ */
+
+struct ttm_pl_create_req {
+	uint64_t size;
+	uint32_t placement;
+	uint32_t page_alignment;
+};
+
+/**
+ * struct ttm_pl_create_ub_req
+ *
+ * @size: The buffer object size.
+ * @user_address: User-space address of the memory area that
+ * should be used to back the buffer object cast to 64-bit.
+ * @placement: Flags that indicate initial acceptable
+ *  placement.
+ * @page_alignment: Required alignment in pages.
+ *
+ * Input to the TTM_BO_CREATE_UB ioctl.
+ */
+
+struct ttm_pl_create_ub_req {
+	uint64_t size;
+	uint64_t user_address;
+	uint32_t placement;
+	uint32_t page_alignment;
+};
+
+/**
+ * struct ttm_pl_rep
+ *
+ * @gpu_offset: The current offset into the memory region used.
+ * This can be used directly by the GPU if there are no
+ * additional GPU mapping procedures used by the driver.
+ *
+ * @bo_size: Actual buffer object size.
+ *
+ * @map_handle: Offset into the device address space.
+ * Used for map, seek, read, write. This will never change
+ * during the lifetime of an object.
+ *
+ * @placement: Flag indicating the placement status of
+ * the buffer object using the TTM_PL flags above.
+ *
+ * @sync_object_arg: Used for user-space synchronization and
+ * depends on the synchronization model used. If fences are
+ * used, this is the buffer_object::fence_type_mask
+ *
+ * Output from the TTM_PL_CREATE and TTM_PL_REFERENCE, and
+ * TTM_PL_SETSTATUS ioctls.
+ */
+
+struct ttm_pl_rep {
+	uint64_t gpu_offset;
+	uint64_t bo_size;
+	uint64_t map_handle;
+	uint32_t placement;
+	uint32_t handle;
+	uint32_t sync_object_arg;
+	uint32_t pad64;
+};
+
+/**
+ * struct ttm_pl_setstatus_req
+ *
+ * @set_placement: Placement flags to set.
+ *
+ * @clr_placement: Placement flags to clear.
+ *
+ * @handle: The object handle
+ *
+ * Input to the TTM_PL_SETSTATUS ioctl.
+ */
+
+struct ttm_pl_setstatus_req {
+	uint32_t set_placement;
+	uint32_t clr_placement;
+	uint32_t handle;
+	uint32_t pad64;
+};
+
+/**
+ * struct ttm_pl_reference_req
+ *
+ * @handle: The object to put a reference on.
+ *
+ * Input to the TTM_PL_REFERENCE and the TTM_PL_UNREFERENCE ioctls.
+ */
+
+struct ttm_pl_reference_req {
+	uint32_t handle;
+	uint32_t pad64;
+};
+
+/*
+ * ACCESS mode flags for SYNCCPU.
+ *
+ * TTM_SYNCCPU_MODE_READ will guarantee that the GPU is not
+ * writing to the buffer.
+ *
+ * TTM_SYNCCPU_MODE_WRITE will guarantee that the GPU is not
+ * accessing the buffer.
+ *
+ * TTM_SYNCCPU_MODE_NO_BLOCK makes sure the call does not wait
+ * for GPU accesses to finish but return -EBUSY.
+ *
+ * TTM_SYNCCPU_MODE_TRYCACHED Try to place the buffer in cacheable
+ * memory while synchronized for CPU.
+ */
+
+#define TTM_PL_SYNCCPU_MODE_READ      TTM_ACCESS_READ
+#define TTM_PL_SYNCCPU_MODE_WRITE     TTM_ACCESS_WRITE
+#define TTM_PL_SYNCCPU_MODE_NO_BLOCK  (1 << 2)
+#define TTM_PL_SYNCCPU_MODE_TRYCACHED (1 << 3)
+
+/**
+ * struct ttm_pl_synccpu_arg
+ *
+ * @handle: The object to synchronize.
+ *
+ * @access_mode: access mode indicated by the
+ * TTM_SYNCCPU_MODE flags.
+ *
+ * @op: indicates whether to grab or release the
+ * buffer for cpu usage.
+ *
+ * Input to the TTM_PL_SYNCCPU ioctl.
+ */
+
+struct ttm_pl_synccpu_arg {
+	uint32_t handle;
+	uint32_t access_mode;
+	enum {
+		TTM_PL_SYNCCPU_OP_GRAB,
+		TTM_PL_SYNCCPU_OP_RELEASE
+	} op;
+	uint32_t pad64;
+};
+
+/*
+ * Waiting mode flags for the TTM_BO_WAITIDLE ioctl.
+ *
+ * TTM_WAITIDLE_MODE_LAZY: Allow for sleeps during polling
+ * wait.
+ *
+ * TTM_WAITIDLE_MODE_NO_BLOCK: Don't block waiting for GPU,
+ * but return -EBUSY if the buffer is busy.
+ */
+
+#define TTM_PL_WAITIDLE_MODE_LAZY     (1 << 0)
+#define TTM_PL_WAITIDLE_MODE_NO_BLOCK (1 << 1)
+
+/**
+ * struct ttm_waitidle_arg
+ *
+ * @handle: The object to synchronize.
+ *
+ * @mode: wait mode indicated by the
+ * TTM_SYNCCPU_MODE flags.
+ *
+ * Argument to the TTM_BO_WAITIDLE ioctl.
+ */
+
+struct ttm_pl_waitidle_arg {
+	uint32_t handle;
+	uint32_t mode;
+};
+
+union ttm_pl_create_arg {
+	struct ttm_pl_create_req req;
+	struct ttm_pl_rep rep;
+};
+
+union ttm_pl_reference_arg {
+	struct ttm_pl_reference_req req;
+	struct ttm_pl_rep rep;
+};
+
+union ttm_pl_setstatus_arg {
+	struct ttm_pl_setstatus_req req;
+	struct ttm_pl_rep rep;
+};
+
+union ttm_pl_create_ub_arg {
+	struct ttm_pl_create_ub_req req;
+	struct ttm_pl_rep rep;
+};
+
+/*
+ * Ioctl offsets.
+ */
+
+#define TTM_PL_CREATE      0x00
+#define TTM_PL_REFERENCE   0x01
+#define TTM_PL_UNREF       0x02
+#define TTM_PL_SYNCCPU     0x03
+#define TTM_PL_WAITIDLE    0x04
+#define TTM_PL_SETSTATUS   0x05
+#define TTM_PL_CREATE_UB   0x06
+
+#endif
diff --git a/drivers/staging/gma500/psb_ttm_userobj_api.h b/drivers/staging/gma500/psb_ttm_userobj_api.h
new file mode 100644
index 0000000..6a8f7c4
--- /dev/null
+++ b/drivers/staging/gma500/psb_ttm_userobj_api.h
@@ -0,0 +1,85 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
+ * All Rights Reserved.
+ * Copyright (c) 2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+ */
+
+#ifndef _TTM_USEROBJ_API_H_
+#define _TTM_USEROBJ_API_H_
+
+#include "psb_ttm_placement_user.h"
+#include "psb_ttm_fence_user.h"
+#include "ttm/ttm_object.h"
+#include "psb_ttm_fence_api.h"
+#include "ttm/ttm_bo_api.h"
+
+struct ttm_lock;
+
+/*
+ * User ioctls.
+ */
+
+extern int ttm_pl_create_ioctl(struct ttm_object_file *tfile,
+			       struct ttm_bo_device *bdev,
+			       struct ttm_lock *lock, void *data);
+extern int ttm_pl_ub_create_ioctl(struct ttm_object_file *tfile,
+				  struct ttm_bo_device *bdev,
+				  struct ttm_lock *lock, void *data);
+extern int ttm_pl_reference_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_unref_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_synccpu_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_pl_setstatus_ioctl(struct ttm_object_file *tfile,
+				  struct ttm_lock *lock, void *data);
+extern int ttm_pl_waitidle_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_signaled_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_finish_ioctl(struct ttm_object_file *tfile, void *data);
+extern int ttm_fence_unref_ioctl(struct ttm_object_file *tfile, void *data);
+
+extern int
+ttm_fence_user_create(struct ttm_fence_device *fdev,
+		      struct ttm_object_file *tfile,
+		      uint32_t fence_class,
+		      uint32_t fence_types,
+		      uint32_t create_flags,
+		      struct ttm_fence_object **fence, uint32_t * user_handle);
+
+extern struct ttm_buffer_object *ttm_buffer_object_lookup(struct ttm_object_file
+							  *tfile,
+							  uint32_t handle);
+
+extern int
+ttm_pl_verify_access(struct ttm_buffer_object *bo,
+		     struct ttm_object_file *tfile);
+
+extern int ttm_buffer_object_create(struct ttm_bo_device *bdev,
+			unsigned long size,
+			enum ttm_bo_type type,
+			uint32_t flags,
+			uint32_t page_alignment,
+			unsigned long buffer_start,
+			bool interruptible,
+			struct file *persistant_swap_storage,
+			struct ttm_buffer_object **p_bo);
+
+extern int psb_ttm_bo_check_placement(struct ttm_buffer_object *bo,
+				struct ttm_placement *placement);
+#endif
diff --git a/drivers/staging/go7007/Kconfig b/drivers/staging/go7007/Kconfig
index 1da57df..7dfb281 100644
--- a/drivers/staging/go7007/Kconfig
+++ b/drivers/staging/go7007/Kconfig
@@ -1,7 +1,6 @@
 config VIDEO_GO7007
 	tristate "WIS GO7007 MPEG encoder support"
 	depends on VIDEO_DEV && PCI && I2C
-	depends on BKL # please fix
 	depends on SND
 	select VIDEOBUF_DMA_SG
 	depends on RC_CORE
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index bea9f4d..3db3b0a 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -1247,15 +1247,13 @@ static void go7007_usb_disconnect(struct usb_interface *intf)
 		vurb = usb->video_urbs[i];
 		if (vurb) {
 			usb_kill_urb(vurb);
-			if (vurb->transfer_buffer)
-				kfree(vurb->transfer_buffer);
+			kfree(vurb->transfer_buffer);
 			usb_free_urb(vurb);
 		}
 		aurb = usb->audio_urbs[i];
 		if (aurb) {
 			usb_kill_urb(aurb);
-			if (aurb->transfer_buffer)
-				kfree(aurb->transfer_buffer);
+			kfree(aurb->transfer_buffer);
 			usb_free_urb(aurb);
 		}
 	}
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c
index 7547a8f..4e13251 100644
--- a/drivers/staging/go7007/s2250-loader.c
+++ b/drivers/staging/go7007/s2250-loader.c
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <dvb-usb.h>
 
@@ -142,11 +141,9 @@ static void s2250loader_disconnect(struct usb_interface *interface)
 {
 	pdevice_extension_t s;
 	printk(KERN_INFO "s2250: disconnect\n");
-	lock_kernel();
 	s = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 	kref_put(&(s->kref), s2250loader_delete);
-	unlock_kernel();
 }
 
 static const struct usb_device_id s2250loader_ids[] = {
diff --git a/drivers/staging/hv/Kconfig b/drivers/staging/hv/Kconfig
index 7455c80..d41f380 100644
--- a/drivers/staging/hv/Kconfig
+++ b/drivers/staging/hv/Kconfig
@@ -31,8 +31,16 @@ config HYPERV_NET
 
 config HYPERV_UTILS
 	tristate "Microsoft Hyper-V Utilities driver"
+	depends on CONNECTOR
 	default HYPERV
 	help
 	  Select this option to enable the Hyper-V Utilities.
 
+config HYPERV_MOUSE
+	tristate "Microsoft Hyper-V mouse driver"
+	depends on HID
+	default HYPERV
+	help
+	  Select this option to enable the Hyper-V mouse driver.
+
 endif
diff --git a/drivers/staging/hv/Makefile b/drivers/staging/hv/Makefile
index acd39bd..abeb2f7 100644
--- a/drivers/staging/hv/Makefile
+++ b/drivers/staging/hv/Makefile
@@ -3,10 +3,12 @@ obj-$(CONFIG_HYPERV_STORAGE)	+= hv_storvsc.o
 obj-$(CONFIG_HYPERV_BLOCK)	+= hv_blkvsc.o
 obj-$(CONFIG_HYPERV_NET)	+= hv_netvsc.o
 obj-$(CONFIG_HYPERV_UTILS)	+= hv_utils.o
+obj-$(CONFIG_HYPERV_MOUSE)	+= hv_mouse.o
 
-hv_vmbus-y := vmbus_drv.o osd.o \
+hv_vmbus-y := vmbus_drv.o \
 		 hv.o connection.o channel.o \
 		 channel_mgmt.o ring_buffer.o
 hv_storvsc-y := storvsc_drv.o storvsc.o
 hv_blkvsc-y := blkvsc_drv.o blkvsc.o
 hv_netvsc-y := netvsc_drv.o netvsc.o rndis_filter.o
+hv_utils-y := hv_util.o hv_kvp.o
diff --git a/drivers/staging/hv/blkvsc.c b/drivers/staging/hv/blkvsc.c
index bc16d91..7c8729b 100644
--- a/drivers/staging/hv/blkvsc.c
+++ b/drivers/staging/hv/blkvsc.c
@@ -22,7 +22,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "storvsc.c"
 
 static const char *g_blk_driver_name = "blkvsc";
@@ -51,13 +51,13 @@ static int blk_vsc_on_device_add(struct hv_device *device, void *additional_info
 	 * id. For IDE devices, the device instance id is formatted as
 	 * <bus id> * - <device id> - 8899 - 000000000000.
 	 */
-	device_info->path_id = device->deviceInstance.data[3] << 24 |
-			     device->deviceInstance.data[2] << 16 |
-			     device->deviceInstance.data[1] << 8  |
-			     device->deviceInstance.data[0];
+	device_info->path_id = device->dev_instance.data[3] << 24 |
+			     device->dev_instance.data[2] << 16 |
+			     device->dev_instance.data[1] << 8  |
+			     device->dev_instance.data[0];
 
-	device_info->target_id = device->deviceInstance.data[5] << 8 |
-			       device->deviceInstance.data[4];
+	device_info->target_id = device->dev_instance.data[5] << 8 |
+			       device->dev_instance.data[4];
 
 	return ret;
 }
@@ -73,7 +73,7 @@ int blk_vsc_initialize(struct hv_driver *driver)
 	/* ASSERT(stor_driver->RingBufferSize >= (PAGE_SIZE << 1)); */
 
 	driver->name = g_blk_driver_name;
-	memcpy(&driver->deviceType, &g_blk_device_type, sizeof(struct hv_guid));
+	memcpy(&driver->dev_type, &g_blk_device_type, sizeof(struct hv_guid));
 
 	stor_driver->request_ext_size = sizeof(struct storvsc_request_extension);
 
@@ -85,7 +85,7 @@ int blk_vsc_initialize(struct hv_driver *driver)
 	 */
 	stor_driver->max_outstanding_req_per_channel =
 		((stor_driver->ring_buffer_size - PAGE_SIZE) /
-		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
+		  ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
 			   sizeof(struct vstor_packet) + sizeof(u64),
 			   sizeof(u64)));
 
@@ -93,9 +93,9 @@ int blk_vsc_initialize(struct hv_driver *driver)
 		    stor_driver->max_outstanding_req_per_channel);
 
 	/* Setup the dispatch table */
-	stor_driver->base.OnDeviceAdd = blk_vsc_on_device_add;
-	stor_driver->base.OnDeviceRemove = stor_vsc_on_device_remove;
-	stor_driver->base.OnCleanup = stor_vsc_on_cleanup;
+	stor_driver->base.dev_add = blk_vsc_on_device_add;
+	stor_driver->base.dev_rm = stor_vsc_on_device_remove;
+	stor_driver->base.cleanup = stor_vsc_on_cleanup;
 	stor_driver->on_io_request = stor_vsc_on_io_request;
 
 	return ret;
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 4fb8094..6e02f1b 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -31,7 +31,7 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dbg.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "version_info.h"
 #include "vmbus.h"
@@ -95,7 +95,7 @@ struct blkvsc_request {
 /* Per device structure */
 struct block_device_context {
 	/* point back to our device context */
-	struct vm_device *device_ctx;
+	struct hv_device *device_ctx;
 	struct kmem_cache *request_pool;
 	spinlock_t lock;
 	struct gendisk *gd;
@@ -115,13 +115,6 @@ struct block_device_context {
 	int users;
 };
 
-/* Per driver */
-struct blkvsc_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* FIXME this is a bug! */
-	struct driver_context drv_ctx;
-	struct storvsc_driver_object drv_obj;
-};
 
 /* Static decl */
 static DEFINE_MUTEX(blkvsc_mutex);
@@ -156,7 +149,7 @@ module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (in bytes)");
 
 /* The one and only one */
-static struct blkvsc_driver_context g_blkvsc_drv;
+static  struct storvsc_driver_object g_blkvsc_drv;
 
 static const struct block_device_operations block_ops = {
 	.owner = THIS_MODULE,
@@ -173,25 +166,25 @@ static const struct block_device_operations block_ops = {
  */
 static int blkvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 {
-	struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
+	struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv;
+	struct hv_driver *drv = &g_blkvsc_drv.base;
 	int ret;
 
 	storvsc_drv_obj->ring_buffer_size = blkvsc_ringbuffer_size;
 
+	drv->priv = storvsc_drv_obj;
+
 	/* Callback to client driver to complete the initialization */
 	drv_init(&storvsc_drv_obj->base);
 
-	drv_ctx->driver.name = storvsc_drv_obj->base.name;
-	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->base.deviceType,
-	       sizeof(struct hv_guid));
+	drv->driver.name = storvsc_drv_obj->base.name;
 
-	drv_ctx->probe = blkvsc_probe;
-	drv_ctx->remove = blkvsc_remove;
-	drv_ctx->shutdown = blkvsc_shutdown;
+	drv->driver.probe = blkvsc_probe;
+	drv->driver.remove = blkvsc_remove;
+	drv->driver.shutdown = blkvsc_shutdown;
 
 	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(drv_ctx);
+	ret = vmbus_child_driver_register(&drv->driver);
 
 	return ret;
 }
@@ -205,8 +198,8 @@ static int blkvsc_drv_exit_cb(struct device *dev, void *data)
 
 static void blkvsc_drv_exit(void)
 {
-	struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_blkvsc_drv.drv_ctx;
+	struct storvsc_driver_object *storvsc_drv_obj = &g_blkvsc_drv;
+	struct hv_driver *drv = &g_blkvsc_drv.base;
 	struct device *current_dev;
 	int ret;
 
@@ -214,7 +207,7 @@ static void blkvsc_drv_exit(void)
 		current_dev = NULL;
 
 		/* Get the device */
-		ret = driver_for_each_device(&drv_ctx->driver, NULL,
+		ret = driver_for_each_device(&drv->driver, NULL,
 					     (void *) &current_dev,
 					     blkvsc_drv_exit_cb);
 
@@ -230,10 +223,10 @@ static void blkvsc_drv_exit(void)
 		device_unregister(current_dev);
 	}
 
-	if (storvsc_drv_obj->base.OnCleanup)
-		storvsc_drv_obj->base.OnCleanup(&storvsc_drv_obj->base);
+	if (storvsc_drv_obj->base.cleanup)
+		storvsc_drv_obj->base.cleanup(&storvsc_drv_obj->base);
 
-	vmbus_child_driver_unregister(drv_ctx);
+	vmbus_child_driver_unregister(&drv->driver);
 
 	return;
 }
@@ -243,14 +236,11 @@ static void blkvsc_drv_exit(void)
  */
 static int blkvsc_probe(struct device *device)
 {
-	struct driver_context *driver_ctx =
-				driver_to_driver_context(device->driver);
-	struct blkvsc_driver_context *blkvsc_drv_ctx =
-				(struct blkvsc_driver_context *)driver_ctx;
+	struct hv_driver *drv =
+				drv_to_hv_drv(device->driver);
 	struct storvsc_driver_object *storvsc_drv_obj =
-				&blkvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
+				drv->priv;
+	struct hv_device *device_obj = device_to_hv_device(device);
 
 	struct block_device_context *blkdev = NULL;
 	struct storvsc_device_info device_info;
@@ -262,7 +252,7 @@ static int blkvsc_probe(struct device *device)
 
 	DPRINT_DBG(BLKVSC_DRV, "blkvsc_probe - enter");
 
-	if (!storvsc_drv_obj->base.OnDeviceAdd) {
+	if (!storvsc_drv_obj->base.dev_add) {
 		DPRINT_ERR(BLKVSC_DRV, "OnDeviceAdd() not set");
 		ret = -1;
 		goto Cleanup;
@@ -282,7 +272,7 @@ static int blkvsc_probe(struct device *device)
 	/* ASSERT(sizeof(struct blkvsc_request_group) <= */
 	/* 	sizeof(struct blkvsc_request)); */
 
-	blkdev->request_pool = kmem_cache_create(dev_name(&device_ctx->device),
+	blkdev->request_pool = kmem_cache_create(dev_name(&device_obj->device),
 					sizeof(struct blkvsc_request) +
 					storvsc_drv_obj->request_ext_size, 0,
 					SLAB_HWCACHE_ALIGN, NULL);
@@ -293,13 +283,13 @@ static int blkvsc_probe(struct device *device)
 
 
 	/* Call to the vsc driver to add the device */
-	ret = storvsc_drv_obj->base.OnDeviceAdd(device_obj, &device_info);
+	ret = storvsc_drv_obj->base.dev_add(device_obj, &device_info);
 	if (ret != 0) {
 		DPRINT_ERR(BLKVSC_DRV, "unable to add blkvsc device");
 		goto Cleanup;
 	}
 
-	blkdev->device_ctx = device_ctx;
+	blkdev->device_ctx = device_obj;
 	/* this identified the device 0 or 1 */
 	blkdev->target = device_info.target_id;
 	/* this identified the ide ctrl 0 or 1 */
@@ -392,7 +382,7 @@ static int blkvsc_probe(struct device *device)
 	return ret;
 
 Remove:
-	storvsc_drv_obj->base.OnDeviceRemove(device_obj);
+	storvsc_drv_obj->base.dev_rm(device_obj);
 
 Cleanup:
 	if (blkdev) {
@@ -460,9 +450,9 @@ static int blkvsc_do_flush(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.data_buffer.PfnArray[0] = 0;
-	blkvsc_req->request.data_buffer.Offset = 0;
-	blkvsc_req->request.data_buffer.Length = 0;
+	blkvsc_req->request.data_buffer.pfn_array[0] = 0;
+	blkvsc_req->request.data_buffer.offset = 0;
+	blkvsc_req->request.data_buffer.len = 0;
 
 	blkvsc_req->cmnd[0] = SYNCHRONIZE_CACHE;
 	blkvsc_req->cmd_len = 10;
@@ -507,9 +497,9 @@ static int blkvsc_do_inquiry(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.data_buffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.data_buffer.Offset = 0;
-	blkvsc_req->request.data_buffer.Length = 64;
+	blkvsc_req->request.data_buffer.pfn_array[0] = page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.offset = 0;
+	blkvsc_req->request.data_buffer.len = 64;
 
 	blkvsc_req->cmnd[0] = INQUIRY;
 	blkvsc_req->cmnd[1] = 0x1;		/* Get product data */
@@ -594,9 +584,9 @@ static int blkvsc_do_read_capacity(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.data_buffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.data_buffer.Offset = 0;
-	blkvsc_req->request.data_buffer.Length = 8;
+	blkvsc_req->request.data_buffer.pfn_array[0] = page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.offset = 0;
+	blkvsc_req->request.data_buffer.len = 8;
 
 	blkvsc_req->cmnd[0] = READ_CAPACITY;
 	blkvsc_req->cmd_len = 16;
@@ -671,9 +661,9 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
 	blkvsc_req->req = NULL;
 	blkvsc_req->write = 0;
 
-	blkvsc_req->request.data_buffer.PfnArray[0] = page_to_pfn(page_buf);
-	blkvsc_req->request.data_buffer.Offset = 0;
-	blkvsc_req->request.data_buffer.Length = 12;
+	blkvsc_req->request.data_buffer.pfn_array[0] = page_to_pfn(page_buf);
+	blkvsc_req->request.data_buffer.offset = 0;
+	blkvsc_req->request.data_buffer.len = 12;
 
 	blkvsc_req->cmnd[0] = 0x9E; /* READ_CAPACITY16; */
 	blkvsc_req->cmd_len = 16;
@@ -728,28 +718,25 @@ static int blkvsc_do_read_capacity16(struct block_device_context *blkdev)
  */
 static int blkvsc_remove(struct device *device)
 {
-	struct driver_context *driver_ctx =
-				driver_to_driver_context(device->driver);
-	struct blkvsc_driver_context *blkvsc_drv_ctx =
-				(struct blkvsc_driver_context *)driver_ctx;
+	struct hv_driver *drv =
+				drv_to_hv_drv(device->driver);
 	struct storvsc_driver_object *storvsc_drv_obj =
-				&blkvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
+				drv->priv;
+	struct hv_device *device_obj = device_to_hv_device(device);
 	struct block_device_context *blkdev = dev_get_drvdata(device);
 	unsigned long flags;
 	int ret;
 
 	DPRINT_DBG(BLKVSC_DRV, "blkvsc_remove()\n");
 
-	if (!storvsc_drv_obj->base.OnDeviceRemove)
+	if (!storvsc_drv_obj->base.dev_rm)
 		return -1;
 
 	/*
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = storvsc_drv_obj->base.OnDeviceRemove(device_obj);
+	ret = storvsc_drv_obj->base.dev_rm(device_obj);
 	if (ret != 0) {
 		/* TODO: */
 		DPRINT_ERR(BLKVSC_DRV,
@@ -850,13 +837,11 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
 			void (*request_completion)(struct hv_storvsc_request *))
 {
 	struct block_device_context *blkdev = blkvsc_req->dev;
-	struct vm_device *device_ctx = blkdev->device_ctx;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(device_ctx->device.driver);
-	struct blkvsc_driver_context *blkvsc_drv_ctx =
-			(struct blkvsc_driver_context *)driver_ctx;
+	struct hv_device *device_ctx = blkdev->device_ctx;
+	struct hv_driver *drv =
+			drv_to_hv_drv(device_ctx->device.driver);
 	struct storvsc_driver_object *storvsc_drv_obj =
-			&blkvsc_drv_ctx->drv_obj;
+			drv->priv;
 	struct hv_storvsc_request *storvsc_req;
 	int ret;
 
@@ -866,14 +851,14 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
 		   (blkvsc_req->write) ? "WRITE" : "READ",
 		   (unsigned long) blkvsc_req->sector_start,
 		   blkvsc_req->sector_count,
-		   blkvsc_req->request.data_buffer.Offset,
-		   blkvsc_req->request.data_buffer.Length);
+		   blkvsc_req->request.data_buffer.offset,
+		   blkvsc_req->request.data_buffer.len);
 #if 0
-	for (i = 0; i < (blkvsc_req->request.data_buffer.Length >> 12); i++) {
+	for (i = 0; i < (blkvsc_req->request.data_buffer.len >> 12); i++) {
 		DPRINT_DBG(BLKVSC_DRV, "blkvsc_submit_request() - "
 			   "req %p pfn[%d] %llx\n",
 			   blkvsc_req, i,
-			   blkvsc_req->request.data_buffer.PfnArray[i]);
+			   blkvsc_req->request.data_buffer.pfn_array[i]);
 	}
 #endif
 
@@ -897,7 +882,7 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
 	storvsc_req->sense_buffer = blkvsc_req->sense_buffer;
 	storvsc_req->sense_buffer_size = SCSI_SENSE_BUFFERSIZE;
 
-	ret = storvsc_drv_obj->on_io_request(&blkdev->device_ctx->device_obj,
+	ret = storvsc_drv_obj->on_io_request(blkdev->device_ctx,
 					   &blkvsc_req->request);
 	if (ret == 0)
 		blkdev->num_outstanding_reqs++;
@@ -993,9 +978,9 @@ static int blkvsc_do_request(struct block_device_context *blkdev,
 
 					blkvsc_req->dev = blkdev;
 					blkvsc_req->req = req;
-					blkvsc_req->request.data_buffer.Offset
+					blkvsc_req->request.data_buffer.offset
 						= bvec->bv_offset;
-					blkvsc_req->request.data_buffer.Length
+					blkvsc_req->request.data_buffer.len
 						= 0;
 
 					/* Add to the group */
@@ -1011,9 +996,9 @@ static int blkvsc_do_request(struct block_device_context *blkdev,
 
 				/* Add the curr bvec/segment to the curr blkvsc_req */
 				blkvsc_req->request.data_buffer.
-					PfnArray[databuf_idx]
+					pfn_array[databuf_idx]
 						= page_to_pfn(bvec->bv_page);
-				blkvsc_req->request.data_buffer.Length
+				blkvsc_req->request.data_buffer.len
 					+= bvec->bv_len;
 
 				prev_bvec = bvec;
@@ -1116,7 +1101,7 @@ static void blkvsc_request_completion(struct hv_storvsc_request *request)
 		   (blkvsc_req->write) ? "WRITE" : "READ",
 		   (unsigned long)blkvsc_req->sector_start,
 		   blkvsc_req->sector_count,
-		   blkvsc_req->request.data_buffer.Length,
+		   blkvsc_req->request.data_buffer.len,
 		   blkvsc_req->group->outstanding,
 		   blkdev->num_outstanding_reqs);
 
diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c
index 45a627d..775a52a 100644
--- a/drivers/staging/hv/channel.c
+++ b/drivers/staging/hv/channel.c
@@ -19,13 +19,18 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "vmbus_private.h"
 
+#define NUM_PAGES_SPANNED(addr, len) \
+((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
+
 /* Internal routines */
 static int create_gpadl_header(
 	void *kbuffer,	/* must be phys and virt contiguous */
@@ -77,10 +82,10 @@ static void vmbus_setevent(struct vmbus_channel *channel)
 	if (channel->offermsg.monitor_allocated) {
 		/* Each u32 represents 32 channels */
 		set_bit(channel->offermsg.child_relid & 31,
-			(unsigned long *) gVmbusConnection.SendInterruptPage +
+			(unsigned long *) vmbus_connection.send_int_page +
 			(channel->offermsg.child_relid >> 5));
 
-		monitorpage = gVmbusConnection.MonitorPages;
+		monitorpage = vmbus_connection.monitor_pages;
 		monitorpage++; /* Get the child to parent monitor page */
 
 		set_bit(channel->monitor_bit,
@@ -88,7 +93,7 @@ static void vmbus_setevent(struct vmbus_channel *channel)
 					[channel->monitor_grp].pending);
 
 	} else {
-		VmbusSetEvent(channel->offermsg.child_relid);
+		vmbus_set_event(channel->offermsg.child_relid);
 	}
 }
 
@@ -100,11 +105,11 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)
 	if (Channel->offermsg.monitor_allocated) {
 		/* Each u32 represents 32 channels */
 		clear_bit(Channel->offermsg.child_relid & 31,
-			  (unsigned long *)gVmbusConnection.SendInterruptPage +
+			  (unsigned long *)vmbus_connection.send_int_page +
 			  (Channel->offermsg.child_relid >> 5));
 
-		monitorPage =
-			(struct hv_monitor_page *)gVmbusConnection.MonitorPages;
+		monitorPage = (struct hv_monitor_page *)
+			vmbus_connection.monitor_pages;
 		monitorPage++; /* Get the child to parent monitor page */
 
 		clear_bit(Channel->monitor_bit,
@@ -128,12 +133,12 @@ void vmbus_get_debug_info(struct vmbus_channel *channel,
 	debuginfo->relid = channel->offermsg.child_relid;
 	debuginfo->state = channel->state;
 	memcpy(&debuginfo->interfacetype,
-	       &channel->offermsg.offer.InterfaceType, sizeof(struct hv_guid));
+	       &channel->offermsg.offer.if_type, sizeof(struct hv_guid));
 	memcpy(&debuginfo->interface_instance,
-	       &channel->offermsg.offer.InterfaceInstance,
+	       &channel->offermsg.offer.if_instance,
 	       sizeof(struct hv_guid));
 
-	monitorpage = (struct hv_monitor_page *)gVmbusConnection.MonitorPages;
+	monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
 
 	debuginfo->monitorid = channel->offermsg.monitorid;
 
@@ -180,8 +185,9 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 	newchannel->channel_callback_context = context;
 
 	/* Allocate the ring buffer */
-	out = osd_page_alloc((send_ringbuffer_size + recv_ringbuffer_size)
-			     >> PAGE_SHIFT);
+	out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
+
 	if (!out)
 		return -ENOMEM;
 
@@ -242,11 +248,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 		goto errorout;
 	}
 
-	openInfo->waitevent = osd_waitevent_create();
-	if (!openInfo->waitevent) {
-		err = -ENOMEM;
-		goto errorout;
-	}
+	init_waitqueue_head(&openInfo->waitevent);
 
 	openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
 	openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
@@ -265,22 +267,29 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 	if (userdatalen)
 		memcpy(openMsg->userdata, userdata, userdatalen);
 
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_add_tail(&openInfo->msglistentry,
-		      &gVmbusConnection.ChannelMsgList);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
 	DPRINT_DBG(VMBUS, "Sending channel open msg...");
 
-	ret = VmbusPostMessage(openMsg,
+	ret = vmbus_post_msg(openMsg,
 			       sizeof(struct vmbus_channel_open_channel));
 	if (ret != 0) {
 		DPRINT_ERR(VMBUS, "unable to open channel - %d", ret);
 		goto Cleanup;
 	}
 
-	/* FIXME: Need to time-out here */
-	osd_waitevent_wait(openInfo->waitevent);
+	openInfo->wait_condition = 0;
+	wait_event_timeout(openInfo->waitevent,
+			openInfo->wait_condition,
+			msecs_to_jiffies(1000));
+	if (openInfo->wait_condition == 0) {
+		err = -ETIMEDOUT;
+		goto errorout;
+	}
+
 
 	if (openInfo->response.open_result.status == 0)
 		DPRINT_INFO(VMBUS, "channel <%p> open success!!", newchannel);
@@ -289,19 +298,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 			    newchannel, openInfo->response.open_result.status);
 
 Cleanup:
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&openInfo->msglistentry);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
-	kfree(openInfo->waitevent);
 	kfree(openInfo);
 	return 0;
 
 errorout:
 	ringbuffer_cleanup(&newchannel->outbound);
 	ringbuffer_cleanup(&newchannel->inbound);
-	osd_page_free(out, (send_ringbuffer_size + recv_ringbuffer_size)
-		     >> PAGE_SHIFT);
+	free_pages((unsigned long)out,
+		get_order(send_ringbuffer_size + recv_ringbuffer_size));
 	kfree(openInfo);
 	return err;
 }
@@ -338,16 +346,16 @@ static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl)
 		   "gpadl header - relid %d, range count %d, range buflen %d",
 		   gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen);
 	for (i = 0; i < gpadl->rangecount; i++) {
-		pagecount = gpadl->range[i].ByteCount >> PAGE_SHIFT;
+		pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT;
 		pagecount = (pagecount > 26) ? 26 : pagecount;
 
 		DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
-			   "page count %d", i, gpadl->range[i].ByteCount,
-			   gpadl->range[i].ByteOffset, pagecount);
+			   "page count %d", i, gpadl->range[i].byte_count,
+			   gpadl->range[i].byte_offset, pagecount);
 
 		for (j = 0; j < pagecount; j++)
 			DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
-				   gpadl->range[i].PfnArray[j]);
+				   gpadl->range[i].pfn_array[j]);
 	}
 }
 
@@ -399,10 +407,10 @@ static int create_gpadl_header(void *kbuffer, u32 size,
 		gpadl_header->rangecount = 1;
 		gpadl_header->range_buflen = sizeof(struct gpa_range) +
 					 pagecount * sizeof(u64);
-		gpadl_header->range[0].ByteOffset = 0;
-		gpadl_header->range[0].ByteCount = size;
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
 		for (i = 0; i < pfncount; i++)
-			gpadl_header->range[0].PfnArray[i] = pfn+i;
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
 		*msginfo = msgheader;
 		*messagecount = 1;
 
@@ -463,10 +471,10 @@ static int create_gpadl_header(void *kbuffer, u32 size,
 		gpadl_header->rangecount = 1;
 		gpadl_header->range_buflen = sizeof(struct gpa_range) +
 					 pagecount * sizeof(u64);
-		gpadl_header->range[0].ByteOffset = 0;
-		gpadl_header->range[0].ByteCount = size;
+		gpadl_header->range[0].byte_offset = 0;
+		gpadl_header->range[0].byte_count = size;
 		for (i = 0; i < pagecount; i++)
-			gpadl_header->range[0].PfnArray[i] = pfn+i;
+			gpadl_header->range[0].pfn_array[i] = pfn+i;
 
 		*msginfo = msgheader;
 		*messagecount = 1;
@@ -501,18 +509,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 	unsigned long flags;
 	int ret = 0;
 
-	next_gpadl_handle = atomic_read(&gVmbusConnection.NextGpadlHandle);
-	atomic_inc(&gVmbusConnection.NextGpadlHandle);
+	next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
+	atomic_inc(&vmbus_connection.next_gpadl_handle);
 
 	ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
 	if (ret)
 		return ret;
 
-	msginfo->waitevent = osd_waitevent_create();
-	if (!msginfo->waitevent) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
+	init_waitqueue_head(&msginfo->waitevent);
 
 	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
 	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
@@ -521,18 +525,19 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 
 	dump_gpadl_header(gpadlmsg);
 
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_add_tail(&msginfo->msglistentry,
-		      &gVmbusConnection.ChannelMsgList);
+		      &vmbus_connection.chn_msg_list);
 
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 	DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d",
 		   kbuffer, size, msgcount);
 
 	DPRINT_DBG(VMBUS, "Sending GPADL Header - len %zd",
 		   msginfo->msgsize - sizeof(*msginfo));
 
-	ret = VmbusPostMessage(gpadlmsg, msginfo->msgsize -
+	msginfo->wait_condition = 0;
+	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
 			       sizeof(*msginfo));
 	if (ret != 0) {
 		DPRINT_ERR(VMBUS, "Unable to open channel - %d", ret);
@@ -557,7 +562,7 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 
 			dump_gpadl_body(gpadl_body, submsginfo->msgsize -
 				      sizeof(*submsginfo));
-			ret = VmbusPostMessage(gpadl_body,
+			ret = vmbus_post_msg(gpadl_body,
 					       submsginfo->msgsize -
 					       sizeof(*submsginfo));
 			if (ret != 0)
@@ -565,7 +570,11 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 
 		}
 	}
-	osd_waitevent_wait(msginfo->waitevent);
+	wait_event_timeout(msginfo->waitevent,
+				msginfo->wait_condition,
+				msecs_to_jiffies(1000));
+	BUG_ON(msginfo->wait_condition == 0);
+
 
 	/* At this point, we received the gpadl created msg */
 	DPRINT_DBG(VMBUS, "Received GPADL created "
@@ -577,11 +586,10 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
 	*gpadl_handle = gpadlmsg->gpadl;
 
 Cleanup:
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&msginfo->msglistentry);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
-	kfree(msginfo->waitevent);
 	kfree(msginfo);
 	return ret;
 }
@@ -604,11 +612,7 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 	if (!info)
 		return -ENOMEM;
 
-	info->waitevent = osd_waitevent_create();
-	if (!info->waitevent) {
-		kfree(info);
-		return -ENOMEM;
-	}
+	init_waitqueue_head(&info->waitevent);
 
 	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
 
@@ -616,26 +620,24 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
 	msg->child_relid = channel->offermsg.child_relid;
 	msg->gpadl = gpadl_handle;
 
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_add_tail(&info->msglistentry,
-		      &gVmbusConnection.ChannelMsgList);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
-
-	ret = VmbusPostMessage(msg,
+		      &vmbus_connection.chn_msg_list);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+	info->wait_condition = 0;
+	ret = vmbus_post_msg(msg,
 			       sizeof(struct vmbus_channel_gpadl_teardown));
-	if (ret != 0) {
-		/* TODO: */
-		/* something... */
-	}
 
-	osd_waitevent_wait(info->waitevent);
+	BUG_ON(ret != 0);
+	wait_event_timeout(info->waitevent,
+			info->wait_condition, msecs_to_jiffies(1000));
+	BUG_ON(info->wait_condition == 0);
 
 	/* Received a torndown response */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 	list_del(&info->msglistentry);
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
-	kfree(info->waitevent);
 	kfree(info);
 	return ret;
 }
@@ -663,18 +665,14 @@ void vmbus_close(struct vmbus_channel *channel)
 	if (!info)
 		return;
 
-	/* info->waitEvent = osd_waitevent_create(); */
 
 	msg = (struct vmbus_channel_close_channel *)info->msg;
 	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
 	msg->child_relid = channel->offermsg.child_relid;
 
-	ret = VmbusPostMessage(msg, sizeof(struct vmbus_channel_close_channel));
-	if (ret != 0) {
-		/* TODO: */
-		/* something... */
-	}
+	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
 
+	BUG_ON(ret != 0);
 	/* Tear down the gpadl for the channel's ring buffer */
 	if (channel->ringbuffer_gpadlhandle)
 		vmbus_teardown_gpadl(channel,
@@ -686,7 +684,8 @@ void vmbus_close(struct vmbus_channel *channel)
 	ringbuffer_cleanup(&channel->outbound);
 	ringbuffer_cleanup(&channel->inbound);
 
-	osd_page_free(channel->ringbuffer_pages, channel->ringbuffer_pagecount);
+	free_pages((unsigned long)channel->ringbuffer_pages,
+		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
 	kfree(info);
 
@@ -697,9 +696,9 @@ void vmbus_close(struct vmbus_channel *channel)
 	 */
 
 	if (channel->state == CHANNEL_OPEN_STATE) {
-		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 		list_del(&channel->listentry);
-		spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 
 		free_channel(channel);
 	}
@@ -726,7 +725,7 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
 {
 	struct vmpacket_descriptor desc;
 	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
-	u32 packetlen_aligned = ALIGN_UP(packetlen, sizeof(u64));
+	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
 	struct scatterlist bufferlist[3];
 	u64 aligned_data = 0;
 	int ret;
@@ -739,12 +738,12 @@ int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
 	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
 
 	/* Setup the descriptor */
-	desc.Type = type; /* VmbusPacketTypeDataInBand; */
-	desc.Flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
+	desc.type = type; /* VmbusPacketTypeDataInBand; */
+	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
 	/* in 8-bytes granularity */
-	desc.DataOffset8 = sizeof(struct vmpacket_descriptor) >> 3;
-	desc.Length8 = (u16)(packetlen_aligned >> 3);
-	desc.TransactionId = requestid;
+	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
+	desc.len8 = (u16)(packetlen_aligned >> 3);
+	desc.trans_id = requestid;
 
 	sg_init_table(bufferlist, 3);
 	sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
@@ -793,12 +792,12 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
 			  sizeof(struct hv_page_buffer));
 	packetlen = descsize + bufferlen;
-	packetlen_aligned = ALIGN_UP(packetlen, sizeof(u64));
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
 
 	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
 
 	/* Setup the descriptor */
-	desc.type = VmbusPacketTypeDataUsingGpaDirect;
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
 	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
 	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
 	desc.length8 = (u16)(packetlen_aligned >> 3);
@@ -806,9 +805,9 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
 	desc.rangecount = pagecount;
 
 	for (i = 0; i < pagecount; i++) {
-		desc.range[i].Length = pagebuffers[i].Length;
-		desc.range[i].Offset = pagebuffers[i].Offset;
-		desc.range[i].Pfn	 = pagebuffers[i].Pfn;
+		desc.range[i].len = pagebuffers[i].len;
+		desc.range[i].offset = pagebuffers[i].offset;
+		desc.range[i].pfn	 = pagebuffers[i].pfn;
 	}
 
 	sg_init_table(bufferlist, 3);
@@ -842,14 +841,14 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
 	u32 packetlen_aligned;
 	struct scatterlist bufferlist[3];
 	u64 aligned_data = 0;
-	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->Offset,
-					 multi_pagebuffer->Length);
+	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
+					 multi_pagebuffer->len);
 
 	dump_vmbus_channel(channel);
 
 	DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u",
-		multi_pagebuffer->Offset,
-		multi_pagebuffer->Length, pfncount);
+		multi_pagebuffer->offset,
+		multi_pagebuffer->len, pfncount);
 
 	if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
 		return -EINVAL;
@@ -862,22 +861,22 @@ int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
 			  ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
 			  sizeof(u64));
 	packetlen = descsize + bufferlen;
-	packetlen_aligned = ALIGN_UP(packetlen, sizeof(u64));
+	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
 
 	/* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
 
 	/* Setup the descriptor */
-	desc.type = VmbusPacketTypeDataUsingGpaDirect;
+	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
 	desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
 	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
 	desc.length8 = (u16)(packetlen_aligned >> 3);
 	desc.transactionid = requestid;
 	desc.rangecount = 1;
 
-	desc.range.Length = multi_pagebuffer->Length;
-	desc.range.Offset = multi_pagebuffer->Offset;
+	desc.range.len = multi_pagebuffer->len;
+	desc.range.offset = multi_pagebuffer->offset;
 
-	memcpy(desc.range.PfnArray, multi_pagebuffer->PfnArray,
+	memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
 	       pfncount * sizeof(u64));
 
 	sg_init_table(bufferlist, 3);
@@ -934,14 +933,14 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
 
 	/* VmbusChannelClearEvent(Channel); */
 
-	packetlen = desc.Length8 << 3;
-	userlen = packetlen - (desc.DataOffset8 << 3);
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
 	/* ASSERT(userLen > 0); */
 
 	DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
 		   "flag %d tid %llx pktlen %d datalen %d> ",
-		   channel, channel->offermsg.child_relid, desc.Type,
-		   desc.Flags, desc.TransactionId, packetlen, userlen);
+		   channel, channel->offermsg.child_relid, desc.type,
+		   desc.flags, desc.trans_id, packetlen, userlen);
 
 	*buffer_actual_len = userlen;
 
@@ -953,11 +952,11 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
 		return -1;
 	}
 
-	*requestid = desc.TransactionId;
+	*requestid = desc.trans_id;
 
 	/* Copy over the packet to the user buffer */
 	ret = ringbuffer_read(&channel->inbound, buffer, userlen,
-			     (desc.DataOffset8 << 3));
+			     (desc.offset8 << 3));
 
 	spin_unlock_irqrestore(&channel->inbound_lock, flags);
 
@@ -994,13 +993,13 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
 
 	/* VmbusChannelClearEvent(Channel); */
 
-	packetlen = desc.Length8 << 3;
-	userlen = packetlen - (desc.DataOffset8 << 3);
+	packetlen = desc.len8 << 3;
+	userlen = packetlen - (desc.offset8 << 3);
 
 	DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
 		   "flag %d tid %llx pktlen %d datalen %d> ",
-		   channel, channel->offermsg.child_relid, desc.Type,
-		   desc.Flags, desc.TransactionId, packetlen, userlen);
+		   channel, channel->offermsg.child_relid, desc.type,
+		   desc.flags, desc.trans_id, packetlen, userlen);
 
 	*buffer_actual_len = packetlen;
 
@@ -1012,7 +1011,7 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
 		return -2;
 	}
 
-	*requestid = desc.TransactionId;
+	*requestid = desc.trans_id;
 
 	/* Copy over the entire packet to the user buffer */
 	ret = ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
diff --git a/drivers/staging/hv/channel.h b/drivers/staging/hv/channel.h
index 7997056..de4f867 100644
--- a/drivers/staging/hv/channel.h
+++ b/drivers/staging/hv/channel.h
@@ -37,7 +37,7 @@ struct vmbus_channel_packet_page_buffer {
 	u32 reserved;
 	u32 rangecount;
 	struct hv_page_buffer range[MAX_PAGE_BUFFER_COUNT];
-} __attribute__((packed));
+} __packed;
 
 /* The format must be the same as struct vmdata_gpa_direct */
 struct vmbus_channel_packet_multipage_buffer {
@@ -49,7 +49,7 @@ struct vmbus_channel_packet_multipage_buffer {
 	u32 reserved;
 	u32 rangecount;		/* Always 1 in this case */
 	struct hv_multipage_buffer range;
-} __attribute__((packed));
+} __packed;
 
 
 extern int vmbus_open(struct vmbus_channel *channel,
diff --git a/drivers/staging/hv/channel_mgmt.c b/drivers/staging/hv/channel_mgmt.c
index d44d5c3..bc0393a 100644
--- a/drivers/staging/hv/channel_mgmt.c
+++ b/drivers/staging/hv/channel_mgmt.c
@@ -19,12 +19,14 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/completion.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "vmbus_private.h"
 #include "utils.h"
@@ -34,8 +36,8 @@ struct vmbus_channel_message_table_entry {
 	void (*messageHandler)(struct vmbus_channel_message_header *msg);
 };
 
-#define MAX_MSG_TYPES                    3
-#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 7
+#define MAX_MSG_TYPES                    4
+#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
 
 static const struct hv_guid
 	gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
@@ -98,6 +100,15 @@ static const struct hv_guid
 			0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
 		}
 	},
+	/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+	/* KVP */
+	{
+		.data = {
+			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
+	}
+	},
+
 };
 
 
@@ -185,7 +196,7 @@ void chn_cb_negotiate(void *context)
 
 		vmbus_sendpacket(channel, buf,
 				       recvlen, requestid,
-				       VmbusPacketTypeDataInBand, 0);
+				       VM_PKT_DATA_INBAND, 0);
 	}
 
 	kfree(buf);
@@ -231,6 +242,16 @@ struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
 		.callback = chn_cb_negotiate,
 		.log_msg = "Heartbeat channel functionality initialized"
 	},
+	/* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
+	/* KVP */
+	{
+		.data = {
+			0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
+			0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
+		},
+		.callback = chn_cb_negotiate,
+		.log_msg = "KVP channel functionality initialized"
+	},
 };
 EXPORT_SYMBOL(hv_cb_utils);
 
@@ -289,7 +310,7 @@ void free_channel(struct vmbus_channel *channel)
 	 * ie we can't destroy ourselves.
 	 */
 	INIT_WORK(&channel->work, release_channel);
-	queue_work(gVmbusConnection.WorkQueue, &channel->work);
+	queue_work(vmbus_connection.work_queue, &channel->work);
 }
 
 
@@ -304,10 +325,10 @@ static void count_hv_channel(void)
 	static int counter;
 	unsigned long flags;
 
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 	if (++counter == MAX_MSG_TYPES)
 		complete(&hv_channel_ready);
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 }
 
 /*
@@ -342,14 +363,14 @@ static void vmbus_process_offer(struct work_struct *work)
 	INIT_WORK(&newchannel->work, vmbus_process_rescind_offer);
 
 	/* Make sure this is a new offer */
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 
-	list_for_each_entry(channel, &gVmbusConnection.ChannelList, listentry) {
-		if (!memcmp(&channel->offermsg.offer.InterfaceType,
-			    &newchannel->offermsg.offer.InterfaceType,
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (!memcmp(&channel->offermsg.offer.if_type,
+			    &newchannel->offermsg.offer.if_type,
 			    sizeof(struct hv_guid)) &&
-		    !memcmp(&channel->offermsg.offer.InterfaceInstance,
-			    &newchannel->offermsg.offer.InterfaceInstance,
+		    !memcmp(&channel->offermsg.offer.if_instance,
+			    &newchannel->offermsg.offer.if_instance,
 			    sizeof(struct hv_guid))) {
 			fnew = false;
 			break;
@@ -358,9 +379,9 @@ static void vmbus_process_offer(struct work_struct *work)
 
 	if (fnew)
 		list_add_tail(&newchannel->listentry,
-			      &gVmbusConnection.ChannelList);
+			      &vmbus_connection.chn_list);
 
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 
 	if (!fnew) {
 		DPRINT_DBG(VMBUS, "Ignoring duplicate offer for relid (%d)",
@@ -372,11 +393,11 @@ static void vmbus_process_offer(struct work_struct *work)
 	/*
 	 * Start the process of binding this offer to the driver
 	 * We need to set the DeviceObject field before calling
-	 * VmbusChildDeviceAdd()
+	 * vmbus_child_dev_add()
 	 */
 	newchannel->device_obj = vmbus_child_device_create(
-		&newchannel->offermsg.offer.InterfaceType,
-		&newchannel->offermsg.offer.InterfaceInstance,
+		&newchannel->offermsg.offer.if_type,
+		&newchannel->offermsg.offer.if_instance,
 		newchannel);
 
 	DPRINT_DBG(VMBUS, "child device object allocated - %p",
@@ -387,15 +408,15 @@ static void vmbus_process_offer(struct work_struct *work)
 	 * binding which eventually invokes the device driver's AddDevice()
 	 * method.
 	 */
-	ret = VmbusChildDeviceAdd(newchannel->device_obj);
+	ret = vmbus_child_device_register(newchannel->device_obj);
 	if (ret != 0) {
 		DPRINT_ERR(VMBUS,
 			   "unable to add child device object (relid %d)",
 			   newchannel->offermsg.child_relid);
 
-		spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+		spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 		list_del(&newchannel->listentry);
-		spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+		spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 
 		free_channel(newchannel);
 	} else {
@@ -408,7 +429,7 @@ static void vmbus_process_offer(struct work_struct *work)
 
 		/* Open IC channels */
 		for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
-			if (memcmp(&newchannel->offermsg.offer.InterfaceType,
+			if (memcmp(&newchannel->offermsg.offer.if_type,
 				   &hv_cb_utils[cnt].data,
 				   sizeof(struct hv_guid)) == 0 &&
 				vmbus_open(newchannel, 2 * PAGE_SIZE,
@@ -442,7 +463,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
 
 	offer = (struct vmbus_channel_offer_channel *)hdr;
 	for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
-		if (memcmp(&offer->offer.InterfaceType,
+		if (memcmp(&offer->offer.if_type,
 		    &gSupportedDeviceClasses[i], sizeof(struct hv_guid)) == 0) {
 			fsupported = 1;
 			break;
@@ -455,8 +476,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
 		return;
 	}
 
-	guidtype = &offer->offer.InterfaceType;
-	guidinstance = &offer->offer.InterfaceInstance;
+	guidtype = &offer->offer.if_type;
+	guidinstance = &offer->offer.if_instance;
 
 	DPRINT_INFO(VMBUS, "Channel offer notification - "
 		    "child relid %d monitor id %d allocated %d, "
@@ -513,7 +534,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
 	struct vmbus_channel *channel;
 
 	rescind = (struct vmbus_channel_rescind_offer *)hdr;
-	channel = GetChannelFromRelId(rescind->child_relid);
+	channel = relid2channel(rescind->child_relid);
 	if (channel == NULL) {
 		DPRINT_DBG(VMBUS, "channel not found for relId %d",
 			   rescind->child_relid);
@@ -546,7 +567,6 @@ static void vmbus_onoffers_delivered(
 static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
 {
 	struct vmbus_channel_open_result *result;
-	struct list_head *curr;
 	struct vmbus_channel_msginfo *msginfo;
 	struct vmbus_channel_message_header *requestheader;
 	struct vmbus_channel_open_channel *openmsg;
@@ -558,11 +578,10 @@ static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
 	/*
 	 * Find the open msg, copy the result and signal/unblock the wait event
 	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msginfo = (struct vmbus_channel_msginfo *)curr;
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
 		requestheader =
 			(struct vmbus_channel_message_header *)msginfo->msg;
 
@@ -574,12 +593,13 @@ static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
 				memcpy(&msginfo->response.open_result,
 				       result,
 				       sizeof(struct vmbus_channel_open_result));
-				osd_waitevent_set(msginfo->waitevent);
+				msginfo->wait_condition = 1;
+				wake_up(&msginfo->waitevent);
 				break;
 			}
 		}
 	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 }
 
 /*
@@ -592,7 +612,6 @@ static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
 static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
 {
 	struct vmbus_channel_gpadl_created *gpadlcreated;
-	struct list_head *curr;
 	struct vmbus_channel_msginfo *msginfo;
 	struct vmbus_channel_message_header *requestheader;
 	struct vmbus_channel_gpadl_header *gpadlheader;
@@ -606,11 +625,10 @@ static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
 	 * Find the establish msg, copy the result and signal/unblock the wait
 	 * event
 	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msginfo = (struct vmbus_channel_msginfo *)curr;
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
 		requestheader =
 			(struct vmbus_channel_message_header *)msginfo->msg;
 
@@ -624,12 +642,13 @@ static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
 				memcpy(&msginfo->response.gpadl_created,
 				       gpadlcreated,
 				       sizeof(struct vmbus_channel_gpadl_created));
-				osd_waitevent_set(msginfo->waitevent);
+				msginfo->wait_condition = 1;
+				wake_up(&msginfo->waitevent);
 				break;
 			}
 		}
 	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 }
 
 /*
@@ -643,7 +662,6 @@ static void vmbus_ongpadl_torndown(
 			struct vmbus_channel_message_header *hdr)
 {
 	struct vmbus_channel_gpadl_torndown *gpadl_torndown;
-	struct list_head *curr;
 	struct vmbus_channel_msginfo *msginfo;
 	struct vmbus_channel_message_header *requestheader;
 	struct vmbus_channel_gpadl_teardown *gpadl_teardown;
@@ -654,11 +672,10 @@ static void vmbus_ongpadl_torndown(
 	/*
 	 * Find the open msg, copy the result and signal/unblock the wait event
 	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msginfo = (struct vmbus_channel_msginfo *)curr;
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
 		requestheader =
 			(struct vmbus_channel_message_header *)msginfo->msg;
 
@@ -670,12 +687,13 @@ static void vmbus_ongpadl_torndown(
 				memcpy(&msginfo->response.gpadl_torndown,
 				       gpadl_torndown,
 				       sizeof(struct vmbus_channel_gpadl_torndown));
-				osd_waitevent_set(msginfo->waitevent);
+				msginfo->wait_condition = 1;
+				wake_up(&msginfo->waitevent);
 				break;
 			}
 		}
 	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 }
 
 /*
@@ -688,7 +706,6 @@ static void vmbus_ongpadl_torndown(
 static void vmbus_onversion_response(
 		struct vmbus_channel_message_header *hdr)
 {
-	struct list_head *curr;
 	struct vmbus_channel_msginfo *msginfo;
 	struct vmbus_channel_message_header *requestheader;
 	struct vmbus_channel_initiate_contact *initiate;
@@ -696,11 +713,10 @@ static void vmbus_onversion_response(
 	unsigned long flags;
 
 	version_response = (struct vmbus_channel_version_response *)hdr;
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
 
-	list_for_each(curr, &gVmbusConnection.ChannelMsgList) {
-/* FIXME: this should probably use list_entry() instead */
-		msginfo = (struct vmbus_channel_msginfo *)curr;
+	list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
+				msglistentry) {
 		requestheader =
 			(struct vmbus_channel_message_header *)msginfo->msg;
 
@@ -711,10 +727,11 @@ static void vmbus_onversion_response(
 			memcpy(&msginfo->response.version_response,
 			      version_response,
 			      sizeof(struct vmbus_channel_version_response));
-			osd_waitevent_set(msginfo->waitevent);
+			msginfo->wait_condition = 1;
+			wake_up(&msginfo->waitevent);
 		}
 	}
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 }
 
 /* Channel message dispatch table */
@@ -786,44 +803,33 @@ int vmbus_request_offers(void)
 	if (!msginfo)
 		return -ENOMEM;
 
-	msginfo->waitevent = osd_waitevent_create();
-	if (!msginfo->waitevent) {
-		kfree(msginfo);
-		return -ENOMEM;
-	}
+	init_waitqueue_head(&msginfo->waitevent);
 
 	msg = (struct vmbus_channel_message_header *)msginfo->msg;
 
 	msg->msgtype = CHANNELMSG_REQUESTOFFERS;
 
-	/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
-	INSERT_TAIL_LIST(&gVmbusConnection.channelMsgList,
-			 &msgInfo->msgListEntry);
-	SpinlockRelease(gVmbusConnection.channelMsgLock);*/
 
-	ret = VmbusPostMessage(msg,
+	ret = vmbus_post_msg(msg,
 			       sizeof(struct vmbus_channel_message_header));
 	if (ret != 0) {
 		DPRINT_ERR(VMBUS, "Unable to request offers - %d", ret);
 
-		/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
-		REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
-		SpinlockRelease(gVmbusConnection.channelMsgLock);*/
+		goto cleanup;
+	}
 
-		goto Cleanup;
+	msginfo->wait_condition = 0;
+	wait_event_timeout(msginfo->waitevent, msginfo->wait_condition,
+			msecs_to_jiffies(1000));
+	if (msginfo->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
 	}
-	/* osd_waitevent_wait(msgInfo->waitEvent); */
 
-	/*SpinlockAcquire(gVmbusConnection.channelMsgLock);
-	REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
-	SpinlockRelease(gVmbusConnection.channelMsgLock);*/
 
 
-Cleanup:
-	if (msginfo) {
-		kfree(msginfo->waitevent);
-		kfree(msginfo);
-	}
+cleanup:
+	kfree(msginfo);
 
 	return ret;
 }
@@ -838,14 +844,14 @@ void vmbus_release_unattached_channels(void)
 	struct vmbus_channel *start = NULL;
 	unsigned long flags;
 
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
 
-	list_for_each_entry_safe(channel, pos, &gVmbusConnection.ChannelList,
+	list_for_each_entry_safe(channel, pos, &vmbus_connection.chn_list,
 				 listentry) {
 		if (channel == start)
 			break;
 
-		if (!channel->device_obj->Driver) {
+		if (!channel->device_obj->drv) {
 			list_del(&channel->listentry);
 			DPRINT_INFO(VMBUS,
 				    "Releasing unattached device object %p",
@@ -859,7 +865,7 @@ void vmbus_release_unattached_channels(void)
 		}
 	}
 
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 }
 
 /* eof */
diff --git a/drivers/staging/hv/channel_mgmt.h b/drivers/staging/hv/channel_mgmt.h
index de6b2a0..96f74e2 100644
--- a/drivers/staging/hv/channel_mgmt.h
+++ b/drivers/staging/hv/channel_mgmt.h
@@ -27,6 +27,7 @@
 
 #include <linux/list.h>
 #include <linux/timer.h>
+#include <linux/workqueue.h>
 #include "ring_buffer.h"
 #include "vmbus_channel_interface.h"
 #include "vmbus_packet_format.h"
@@ -60,19 +61,19 @@ enum vmbus_channel_message_type {
 struct vmbus_channel_message_header {
 	enum vmbus_channel_message_type msgtype;
 	u32 padding;
-} __attribute__((packed));
+} __packed;
 
 /* Query VMBus Version parameters */
 struct vmbus_channel_query_vmbus_version {
 	struct vmbus_channel_message_header header;
 	u32 version;
-} __attribute__((packed));
+} __packed;
 
 /* VMBus Version Supported parameters */
 struct vmbus_channel_version_supported {
 	struct vmbus_channel_message_header header;
 	bool version_supported;
-} __attribute__((packed));
+} __packed;
 
 /* Offer Channel parameters */
 struct vmbus_channel_offer_channel {
@@ -81,13 +82,13 @@ struct vmbus_channel_offer_channel {
 	u32 child_relid;
 	u8 monitorid;
 	bool monitor_allocated;
-} __attribute__((packed));
+} __packed;
 
 /* Rescind Offer parameters */
 struct vmbus_channel_rescind_offer {
 	struct vmbus_channel_message_header header;
 	u32 child_relid;
-} __attribute__((packed));
+} __packed;
 
 /*
  * Request Offer -- no parameters, SynIC message contains the partition ID
@@ -123,7 +124,7 @@ struct vmbus_channel_open_channel {
 
 	/* User-specific data to be passed along to the server endpoint. */
 	unsigned char userdata[MAX_USER_DEFINED_BYTES];
-} __attribute__((packed));
+} __packed;
 
 /* Open Channel Result parameters */
 struct vmbus_channel_open_result {
@@ -131,13 +132,13 @@ struct vmbus_channel_open_result {
 	u32 child_relid;
 	u32 openid;
 	u32 status;
-} __attribute__((packed));
+} __packed;
 
 /* Close channel parameters; */
 struct vmbus_channel_close_channel {
 	struct vmbus_channel_message_header header;
 	u32 child_relid;
-} __attribute__((packed));
+} __packed;
 
 /* Channel Message GPADL */
 #define GPADL_TYPE_RING_BUFFER		1
@@ -157,7 +158,7 @@ struct vmbus_channel_gpadl_header {
 	u16 range_buflen;
 	u16 rangecount;
 	struct gpa_range range[0];
-} __attribute__((packed));
+} __packed;
 
 /* This is the followup packet that contains more PFNs. */
 struct vmbus_channel_gpadl_body {
@@ -165,25 +166,25 @@ struct vmbus_channel_gpadl_body {
 	u32 msgnumber;
 	u32 gpadl;
 	u64 pfn[0];
-} __attribute__((packed));
+} __packed;
 
 struct vmbus_channel_gpadl_created {
 	struct vmbus_channel_message_header header;
 	u32 child_relid;
 	u32 gpadl;
 	u32 creation_status;
-} __attribute__((packed));
+} __packed;
 
 struct vmbus_channel_gpadl_teardown {
 	struct vmbus_channel_message_header header;
 	u32 child_relid;
 	u32 gpadl;
-} __attribute__((packed));
+} __packed;
 
 struct vmbus_channel_gpadl_torndown {
 	struct vmbus_channel_message_header header;
 	u32 gpadl;
-} __attribute__((packed));
+} __packed;
 
 #ifdef VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
 struct vmbus_channel_view_range_add {
@@ -191,19 +192,19 @@ struct vmbus_channel_view_range_add {
 	PHYSICAL_ADDRESS viewrange_base;
 	u64 viewrange_length;
 	u32 child_relid;
-} __attribute__((packed));
+} __packed;
 
 struct vmbus_channel_view_range_remove {
 	struct vmbus_channel_message_header header;
 	PHYSICAL_ADDRESS viewrange_base;
 	u32 child_relid;
-} __attribute__((packed));
+} __packed;
 #endif
 
 struct vmbus_channel_relid_released {
 	struct vmbus_channel_message_header header;
 	u32 child_relid;
-} __attribute__((packed));
+} __packed;
 
 struct vmbus_channel_initiate_contact {
 	struct vmbus_channel_message_header header;
@@ -212,12 +213,12 @@ struct vmbus_channel_initiate_contact {
 	u64 interrupt_page;
 	u64 monitor_page1;
 	u64 monitor_page2;
-} __attribute__((packed));
+} __packed;
 
 struct vmbus_channel_version_response {
 	struct vmbus_channel_message_header header;
 	bool version_supported;
-} __attribute__((packed));
+} __packed;
 
 enum vmbus_channel_state {
 	CHANNEL_OFFER_STATE,
@@ -289,8 +290,8 @@ struct vmbus_channel_msginfo {
 	struct list_head submsglist;
 
 	/* Synchronize the request/response if needed */
-	struct osd_waitevent *waitevent;
-
+	int wait_condition;
+	wait_queue_head_t waitevent;
 	union {
 		struct vmbus_channel_version_supported version_supported;
 		struct vmbus_channel_open_result open_result;
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
index c2e298f..44b203b 100644
--- a/drivers/staging/hv/connection.c
+++ b/drivers/staging/hv/connection.c
@@ -21,127 +21,143 @@
  *
  */
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "vmbus_private.h"
 
 
-struct VMBUS_CONNECTION gVmbusConnection = {
-	.ConnectState		= Disconnected,
-	.NextGpadlHandle	= ATOMIC_INIT(0xE1E10),
+struct vmbus_connection vmbus_connection = {
+	.conn_state		= DISCONNECTED,
+	.next_gpadl_handle	= ATOMIC_INIT(0xE1E10),
 };
 
 /*
- * VmbusConnect - Sends a connect request on the partition service connection
+ * vmbus_connect - Sends a connect request on the partition service connection
  */
-int VmbusConnect(void)
+int vmbus_connect(void)
 {
 	int ret = 0;
-	struct vmbus_channel_msginfo *msgInfo = NULL;
+	struct vmbus_channel_msginfo *msginfo = NULL;
 	struct vmbus_channel_initiate_contact *msg;
 	unsigned long flags;
 
 	/* Make sure we are not connecting or connected */
-	if (gVmbusConnection.ConnectState != Disconnected)
+	if (vmbus_connection.conn_state != DISCONNECTED)
 		return -1;
 
 	/* Initialize the vmbus connection */
-	gVmbusConnection.ConnectState = Connecting;
-	gVmbusConnection.WorkQueue = create_workqueue("hv_vmbus_con");
-	if (!gVmbusConnection.WorkQueue) {
+	vmbus_connection.conn_state = CONNECTING;
+	vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
+	if (!vmbus_connection.work_queue) {
 		ret = -1;
 		goto Cleanup;
 	}
 
-	INIT_LIST_HEAD(&gVmbusConnection.ChannelMsgList);
-	spin_lock_init(&gVmbusConnection.channelmsg_lock);
+	INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
+	spin_lock_init(&vmbus_connection.channelmsg_lock);
 
-	INIT_LIST_HEAD(&gVmbusConnection.ChannelList);
-	spin_lock_init(&gVmbusConnection.channel_lock);
+	INIT_LIST_HEAD(&vmbus_connection.chn_list);
+	spin_lock_init(&vmbus_connection.channel_lock);
 
 	/*
 	 * Setup the vmbus event connection for channel interrupt
 	 * abstraction stuff
 	 */
-	gVmbusConnection.InterruptPage = osd_page_alloc(1);
-	if (gVmbusConnection.InterruptPage == NULL) {
+	vmbus_connection.int_page =
+	(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
+	if (vmbus_connection.int_page == NULL) {
 		ret = -1;
 		goto Cleanup;
 	}
 
-	gVmbusConnection.RecvInterruptPage = gVmbusConnection.InterruptPage;
-	gVmbusConnection.SendInterruptPage =
-		(void *)((unsigned long)gVmbusConnection.InterruptPage +
+	vmbus_connection.recv_int_page = vmbus_connection.int_page;
+	vmbus_connection.send_int_page =
+		(void *)((unsigned long)vmbus_connection.int_page +
 			(PAGE_SIZE >> 1));
 
 	/*
 	 * Setup the monitor notification facility. The 1st page for
 	 * parent->child and the 2nd page for child->parent
 	 */
-	gVmbusConnection.MonitorPages = osd_page_alloc(2);
-	if (gVmbusConnection.MonitorPages == NULL) {
+	vmbus_connection.monitor_pages =
+	(void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
+	if (vmbus_connection.monitor_pages == NULL) {
 		ret = -1;
 		goto Cleanup;
 	}
 
-	msgInfo = kzalloc(sizeof(*msgInfo) +
+	msginfo = kzalloc(sizeof(*msginfo) +
 			  sizeof(struct vmbus_channel_initiate_contact),
 			  GFP_KERNEL);
-	if (msgInfo == NULL) {
+	if (msginfo == NULL) {
 		ret = -ENOMEM;
 		goto Cleanup;
 	}
 
-	msgInfo->waitevent = osd_waitevent_create();
-	if (!msgInfo->waitevent) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
+	init_waitqueue_head(&msginfo->waitevent);
 
-	msg = (struct vmbus_channel_initiate_contact *)msgInfo->msg;
+	msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
 
 	msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
 	msg->vmbus_version_requested = VMBUS_REVISION_NUMBER;
-	msg->interrupt_page = virt_to_phys(gVmbusConnection.InterruptPage);
-	msg->monitor_page1 = virt_to_phys(gVmbusConnection.MonitorPages);
+	msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
+	msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
 	msg->monitor_page2 = virt_to_phys(
-			(void *)((unsigned long)gVmbusConnection.MonitorPages +
+			(void *)((unsigned long)vmbus_connection.monitor_pages +
 				 PAGE_SIZE));
 
 	/*
 	 * Add to list before we send the request since we may
 	 * receive the response before returning from this routine
 	 */
-	spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
-	list_add_tail(&msgInfo->msglistentry,
-		      &gVmbusConnection.ChannelMsgList);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_add_tail(&msginfo->msglistentry,
+		      &vmbus_connection.chn_msg_list);
 
-	spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
 	DPRINT_DBG(VMBUS, "Vmbus connection - interrupt pfn %llx, "
 		   "monitor1 pfn %llx,, monitor2 pfn %llx",
 		   msg->interrupt_page, msg->monitor_page1, msg->monitor_page2);
 
 	DPRINT_DBG(VMBUS, "Sending channel initiate msg...");
-	ret = VmbusPostMessage(msg,
+	ret = vmbus_post_msg(msg,
 			       sizeof(struct vmbus_channel_initiate_contact));
 	if (ret != 0) {
-		list_del(&msgInfo->msglistentry);
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
 		goto Cleanup;
 	}
 
 	/* Wait for the connection response */
-	osd_waitevent_wait(msgInfo->waitevent);
+	msginfo->wait_condition = 0;
+	wait_event_timeout(msginfo->waitevent, msginfo->wait_condition,
+			msecs_to_jiffies(1000));
+	if (msginfo->wait_condition == 0) {
+		spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
+				flags);
+		list_del(&msginfo->msglistentry);
+		spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
+					flags);
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
 
-	list_del(&msgInfo->msglistentry);
+	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+	list_del(&msginfo->msglistentry);
+	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
 
 	/* Check if successful */
-	if (msgInfo->response.version_response.version_supported) {
+	if (msginfo->response.version_response.version_supported) {
 		DPRINT_INFO(VMBUS, "Vmbus connected!!");
-		gVmbusConnection.ConnectState = Connected;
+		vmbus_connection.conn_state = CONNECTED;
 
 	} else {
 		DPRINT_ERR(VMBUS, "Vmbus connection failed!!..."
@@ -151,44 +167,41 @@ int VmbusConnect(void)
 		goto Cleanup;
 	}
 
-	kfree(msgInfo->waitevent);
-	kfree(msgInfo);
+	kfree(msginfo);
 	return 0;
 
 Cleanup:
-	gVmbusConnection.ConnectState = Disconnected;
+	vmbus_connection.conn_state = DISCONNECTED;
 
-	if (gVmbusConnection.WorkQueue)
-		destroy_workqueue(gVmbusConnection.WorkQueue);
+	if (vmbus_connection.work_queue)
+		destroy_workqueue(vmbus_connection.work_queue);
 
-	if (gVmbusConnection.InterruptPage) {
-		osd_page_free(gVmbusConnection.InterruptPage, 1);
-		gVmbusConnection.InterruptPage = NULL;
+	if (vmbus_connection.int_page) {
+		free_pages((unsigned long)vmbus_connection.int_page, 0);
+		vmbus_connection.int_page = NULL;
 	}
 
-	if (gVmbusConnection.MonitorPages) {
-		osd_page_free(gVmbusConnection.MonitorPages, 2);
-		gVmbusConnection.MonitorPages = NULL;
+	if (vmbus_connection.monitor_pages) {
+		free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
+		vmbus_connection.monitor_pages = NULL;
 	}
 
-	if (msgInfo) {
-		kfree(msgInfo->waitevent);
-		kfree(msgInfo);
-	}
+	kfree(msginfo);
 
 	return ret;
 }
 
 /*
- * VmbusDisconnect - Sends a disconnect request on the partition service connection
+ * vmbus_disconnect -
+ * Sends a disconnect request on the partition service connection
  */
-int VmbusDisconnect(void)
+int vmbus_disconnect(void)
 {
 	int ret = 0;
 	struct vmbus_channel_message_header *msg;
 
 	/* Make sure we are connected */
-	if (gVmbusConnection.ConnectState != Connected)
+	if (vmbus_connection.conn_state != CONNECTED)
 		return -1;
 
 	msg = kzalloc(sizeof(struct vmbus_channel_message_header), GFP_KERNEL);
@@ -197,17 +210,18 @@ int VmbusDisconnect(void)
 
 	msg->msgtype = CHANNELMSG_UNLOAD;
 
-	ret = VmbusPostMessage(msg,
+	ret = vmbus_post_msg(msg,
 			       sizeof(struct vmbus_channel_message_header));
 	if (ret != 0)
 		goto Cleanup;
 
-	osd_page_free(gVmbusConnection.InterruptPage, 1);
+	free_pages((unsigned long)vmbus_connection.int_page, 0);
+	free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
 
 	/* TODO: iterate thru the msg list and free up */
-	destroy_workqueue(gVmbusConnection.WorkQueue);
+	destroy_workqueue(vmbus_connection.work_queue);
 
-	gVmbusConnection.ConnectState = Disconnected;
+	vmbus_connection.conn_state = DISCONNECTED;
 
 	DPRINT_INFO(VMBUS, "Vmbus disconnected!!");
 
@@ -217,33 +231,34 @@ Cleanup:
 }
 
 /*
- * GetChannelFromRelId - Get the channel object given its child relative id (ie channel id)
+ * relid2channel - Get the channel object given its
+ * child relative id (ie channel id)
  */
-struct vmbus_channel *GetChannelFromRelId(u32 relId)
+struct vmbus_channel *relid2channel(u32 relid)
 {
 	struct vmbus_channel *channel;
-	struct vmbus_channel *foundChannel  = NULL;
+	struct vmbus_channel *found_channel  = NULL;
 	unsigned long flags;
 
-	spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
-	list_for_each_entry(channel, &gVmbusConnection.ChannelList, listentry) {
-		if (channel->offermsg.child_relid == relId) {
-			foundChannel = channel;
+	spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
+	list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
+		if (channel->offermsg.child_relid == relid) {
+			found_channel = channel;
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
+	spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
 
-	return foundChannel;
+	return found_channel;
 }
 
 /*
- * VmbusProcessChannelEvent - Process a channel event notification
+ * process_chn_event - Process a channel event notification
  */
-static void VmbusProcessChannelEvent(void *context)
+static void process_chn_event(void *context)
 {
 	struct vmbus_channel *channel;
-	u32 relId = (u32)(unsigned long)context;
+	u32 relid = (u32)(unsigned long)context;
 
 	/* ASSERT(relId > 0); */
 
@@ -251,7 +266,7 @@ static void VmbusProcessChannelEvent(void *context)
 	 * Find the channel based on this relid and invokes the
 	 * channel callback to process the event
 	 */
-	channel = GetChannelFromRelId(relId);
+	channel = relid2channel(relid);
 
 	if (channel) {
 		vmbus_onchannel_event(channel);
@@ -261,27 +276,29 @@ static void VmbusProcessChannelEvent(void *context)
 		 *			  (void*)channel);
 		 */
 	} else {
-		DPRINT_ERR(VMBUS, "channel not found for relid - %d.", relId);
+		DPRINT_ERR(VMBUS, "channel not found for relid - %d.", relid);
 	}
 }
 
 /*
- * VmbusOnEvents - Handler for events
+ * vmbus_on_event - Handler for events
  */
-void VmbusOnEvents(void)
+void vmbus_on_event(unsigned long data)
 {
 	int dword;
 	int maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
 	int bit;
 	int relid;
-	u32 *recvInterruptPage = gVmbusConnection.RecvInterruptPage;
+	u32 *recv_int_page = vmbus_connection.recv_int_page;
 
 	/* Check events */
-	if (recvInterruptPage) {
+	if (recv_int_page) {
 		for (dword = 0; dword < maxdword; dword++) {
-			if (recvInterruptPage[dword]) {
+			if (recv_int_page[dword]) {
 				for (bit = 0; bit < 32; bit++) {
-					if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) {
+					if (test_and_clear_bit(bit,
+						(unsigned long *)
+						&recv_int_page[dword])) {
 						relid = (dword << 5) + bit;
 						DPRINT_DBG(VMBUS, "event detected for relid - %d", relid);
 
@@ -292,7 +309,8 @@ void VmbusOnEvents(void)
 						} else {
 							/* QueueWorkItem(VmbusProcessEvent, (void*)relid); */
 							/* ret = WorkQueueQueueWorkItem(gVmbusConnection.workQueue, VmbusProcessChannelEvent, (void*)relid); */
-							VmbusProcessChannelEvent((void *)(unsigned long)relid);
+						process_chn_event((void *)
+						(unsigned long)relid);
 						}
 					}
 				}
@@ -303,26 +321,26 @@ void VmbusOnEvents(void)
 }
 
 /*
- * VmbusPostMessage - Send a msg on the vmbus's message connection
+ * vmbus_post_msg - Send a msg on the vmbus's message connection
  */
-int VmbusPostMessage(void *buffer, size_t bufferLen)
+int vmbus_post_msg(void *buffer, size_t buflen)
 {
-	union hv_connection_id connId;
+	union hv_connection_id conn_id;
 
-	connId.asu32 = 0;
-	connId.u.id = VMBUS_MESSAGE_CONNECTION_ID;
-	return hv_post_message(connId, 1, buffer, bufferLen);
+	conn_id.asu32 = 0;
+	conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
+	return hv_post_message(conn_id, 1, buffer, buflen);
 }
 
 /*
- * VmbusSetEvent - Send an event notification to the parent
+ * vmbus_set_event - Send an event notification to the parent
  */
-int VmbusSetEvent(u32 childRelId)
+int vmbus_set_event(u32 child_relid)
 {
 	/* Each u32 represents 32 channels */
-	set_bit(childRelId & 31,
-		(unsigned long *)gVmbusConnection.SendInterruptPage +
-		(childRelId >> 5));
+	set_bit(child_relid & 31,
+		(unsigned long *)vmbus_connection.send_int_page +
+		(child_relid >> 5));
 
 	return hv_signal_event();
 }
diff --git a/drivers/staging/hv/hv.c b/drivers/staging/hv/hv.c
index a34d713..2d492ad 100644
--- a/drivers/staging/hv/hv.c
+++ b/drivers/staging/hv/hv.c
@@ -23,7 +23,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "vmbus_private.h"
 
@@ -230,7 +230,7 @@ int hv_init(void)
 	* Allocate the hypercall page memory
 	* virtaddr = osd_page_alloc(1);
 	*/
-	virtaddr = osd_virtual_alloc_exec(PAGE_SIZE);
+	virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC);
 
 	if (!virtaddr) {
 		DPRINT_ERR(VMBUS,
@@ -267,7 +267,7 @@ int hv_init(void)
 
 	hv_context.signal_event_param =
 		(struct hv_input_signal_event *)
-			(ALIGN_UP((unsigned long)
+			(ALIGN((unsigned long)
 				  hv_context.signal_event_buffer,
 				  HV_HYPERCALL_PARAM_ALIGN));
 	hv_context.signal_event_param->connectionid.asu32 = 0;
@@ -338,7 +338,7 @@ u16 hv_post_message(union hv_connection_id connection_id,
 		return -1;
 
 	aligned_msg = (struct hv_input_post_message *)
-			(ALIGN_UP(addr, HV_HYPERCALL_PARAM_ALIGN));
+			(ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
 
 	aligned_msg->connectionid = connection_id;
 	aligned_msg->message_type = message_type;
@@ -462,10 +462,10 @@ void hv_synic_init(void *irqarg)
 
 Cleanup:
 	if (hv_context.synic_event_page[cpu])
-		osd_page_free(hv_context.synic_event_page[cpu], 1);
+		free_page((unsigned long)hv_context.synic_event_page[cpu]);
 
 	if (hv_context.synic_message_page[cpu])
-		osd_page_free(hv_context.synic_message_page[cpu], 1);
+		free_page((unsigned long)hv_context.synic_message_page[cpu]);
 	return;
 }
 
@@ -502,6 +502,6 @@ void hv_synic_cleanup(void *arg)
 
 	wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64);
 
-	osd_page_free(hv_context.synic_message_page[cpu], 1);
-	osd_page_free(hv_context.synic_event_page[cpu], 1);
+	free_page((unsigned long)hv_context.synic_message_page[cpu]);
+	free_page((unsigned long)hv_context.synic_event_page[cpu]);
 }
diff --git a/drivers/staging/hv/hv_api.h b/drivers/staging/hv/hv_api.h
index 70e863a..7114fce 100644
--- a/drivers/staging/hv/hv_api.h
+++ b/drivers/staging/hv/hv_api.h
@@ -23,6 +23,11 @@
 #ifndef __HV_API_H
 #define __HV_API_H
 
+struct hv_guid {
+	unsigned char data[16];
+};
+
+
 
 /* Status codes for hypervisor operations. */
 
diff --git a/drivers/staging/hv/hv_kvp.c b/drivers/staging/hv/hv_kvp.c
new file mode 100644
index 0000000..faf692e
--- /dev/null
+++ b/drivers/staging/hv/hv_kvp.c
@@ -0,0 +1,346 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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.
+ *
+ * You should have 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/net.h>
+#include <linux/nls.h>
+#include <linux/connector.h>
+#include <linux/workqueue.h>
+
+#include "logging.h"
+#include "hv_api.h"
+#include "vmbus.h"
+#include "vmbus_packet_format.h"
+#include "vmbus_channel_interface.h"
+#include "version_info.h"
+#include "channel.h"
+#include "vmbus_private.h"
+#include "vmbus_api.h"
+#include "utils.h"
+#include "hv_kvp.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. */
+} kvp_transaction;
+
+static int kvp_send_key(int index);
+
+static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_work_func(struct work_struct *dummy);
+static void kvp_register(void);
+
+static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
+
+static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
+static const char kvp_name[] = "kvp_kernel_module";
+static int timeout_fired;
+static u8 *recv_buffer;
+/*
+ * Register the kernel component with the user-level daemon.
+ * As part of this registration, pass the LIC version number.
+ */
+
+static void
+kvp_register(void)
+{
+
+	struct cn_msg *msg;
+
+	msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_REGISTER;
+		strcpy(msg->data, HV_DRV_VERSION);
+		msg->len = strlen(HV_DRV_VERSION) + 1;
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+	}
+}
+static void
+kvp_work_func(struct work_struct *dummy)
+{
+	/*
+	 * If the timer fires, the user-mode component has not responded;
+	 * process the pending transaction.
+	 */
+	kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired);
+	timeout_fired = 1;
+}
+
+/*
+ * Callback when data is received from user mode.
+ */
+
+static void
+kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
+{
+	struct hv_ku_msg *message;
+
+	message = (struct hv_ku_msg *)msg->data;
+	if (msg->seq == KVP_REGISTER) {
+		printk(KERN_INFO "KVP: user-mode registering done.\n");
+		kvp_register();
+	}
+
+	if (msg->seq == KVP_USER_SET) {
+		/*
+		 * Complete the transaction by forwarding the key value
+		 * to the host. But first, cancel the timeout.
+		 */
+		if (cancel_delayed_work_sync(&kvp_work))
+			kvp_respond_to_host(message->kvp_key,
+						message->kvp_value,
+						!strlen(message->kvp_key));
+	}
+}
+
+static int
+kvp_send_key(int index)
+{
+	struct cn_msg *msg;
+
+	msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
+
+	if (msg) {
+		msg->id.idx =  CN_KVP_IDX;
+		msg->id.val = CN_KVP_VAL;
+		msg->seq = KVP_KERNEL_GET;
+		((struct hv_ku_msg *)msg->data)->kvp_index = index;
+		msg->len = sizeof(struct hv_ku_msg);
+		cn_netlink_send(msg, 0, GFP_ATOMIC);
+		kfree(msg);
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * Send a response back to the host.
+ */
+
+static void
+kvp_respond_to_host(char *key, char *value, int error)
+{
+	struct hv_kvp_msg  *kvp_msg;
+	struct hv_kvp_msg_enumerate  *kvp_data;
+	char	*key_name;
+	struct icmsg_hdr *icmsghdrp;
+	int	keylen, valuelen;
+	u32	buf_len;
+	struct vmbus_channel *channel;
+	u64	req_id;
+
+	/*
+	 * If a transaction is not active; log and return.
+	 */
+
+	if (!kvp_transaction.active) {
+		/*
+		 * This is a spurious call!
+		 */
+		printk(KERN_WARNING "KVP: 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 = kvp_transaction.recv_len;
+	channel = kvp_transaction.recv_channel;
+	req_id = kvp_transaction.recv_req_id;
+
+	icmsghdrp = (struct icmsg_hdr *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr)];
+	kvp_msg = (struct hv_kvp_msg *)
+			&recv_buffer[sizeof(struct vmbuspipe_hdr) +
+			sizeof(struct icmsg_hdr)];
+	kvp_data = &kvp_msg->kvp_data;
+	key_name = key;
+
+	/*
+	 * If the error parameter is set, terminate the host's enumeration.
+	 */
+	if (error) {
+		/*
+		 * We don't support this index or the we have timedout;
+		 * terminate the host-side iteration by returning an error.
+		 */
+		icmsghdrp->status = HV_E_FAIL;
+		goto response_done;
+	}
+
+	/*
+	 * The windows host expects the key/value pair to be encoded
+	 * in utf16.
+	 */
+	keylen = utf8s_to_utf16s(key_name, strlen(key_name),
+				(wchar_t *)kvp_data->data.key);
+	kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
+	valuelen = utf8s_to_utf16s(value, strlen(value),
+				(wchar_t *)kvp_data->data.value);
+	kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
+
+	kvp_data->data.value_type = REG_SZ; /* all our values are strings */
+	icmsghdrp->status = HV_S_OK;
+
+response_done:
+	icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
+
+	vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
+				VM_PKT_DATA_INBAND, 0);
+
+	kvp_transaction.active = false;
+}
+
+/*
+ * This callback is invoked when we get a KVP message from the host.
+ * The host ensures that only one KVP transaction can be active at a time.
+ * KVP implementation in Linux needs to forward the key to a user-mde
+ * component to retrive the corresponding value. Consequently, we cannot
+ * respond to the host in the conext of this callback. Since the host
+ * guarantees that at most only one transaction can be active at a time,
+ * we stash away the transaction state in a set of global variables.
+ */
+
+void hv_kvp_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+
+	struct hv_kvp_msg *kvp_msg;
+	struct hv_kvp_msg_enumerate *kvp_data;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+
+	if (kvp_transaction.active)
+		return;
+
+
+	vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		DPRINT_DBG(VMBUS, "KVP packet: len=%d, requestid=%lld",
+			   recvlen, requestid);
+
+		icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			prep_negotiate_resp(icmsghdrp, negop, recv_buffer);
+		} else {
+			kvp_msg = (struct hv_kvp_msg *)&recv_buffer[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+
+			kvp_data = &kvp_msg->kvp_data;
+
+			/*
+			 * We only support the "get" operation on
+			 * "KVP_POOL_AUTO" pool.
+			 */
+
+			if ((kvp_msg->kvp_hdr.pool != KVP_POOL_AUTO) ||
+				(kvp_msg->kvp_hdr.operation !=
+				KVP_OP_ENUMERATE)) {
+				icmsghdrp->status = HV_E_FAIL;
+				goto callback_done;
+			}
+
+			/*
+			 * Stash away this global state for completing the
+			 * transaction; note transactions are serialized.
+			 */
+			kvp_transaction.recv_len = recvlen;
+			kvp_transaction.recv_channel = channel;
+			kvp_transaction.recv_req_id = requestid;
+			kvp_transaction.active = true;
+
+			/*
+			 * Get the information from the
+			 * user-mode component.
+			 * component. This transaction will be
+			 * completed when we get the value from
+			 * the user-mode component.
+			 * Set a timeout to deal with
+			 * user-mode not responding.
+			 */
+			kvp_send_key(kvp_data->index);
+			schedule_delayed_work(&kvp_work, 100);
+
+			return;
+
+		}
+
+callback_done:
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, recv_buffer,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+}
+
+int
+hv_kvp_init(void)
+{
+	int err;
+
+	err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback);
+	if (err)
+		return err;
+	recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!recv_buffer)
+		return -ENOMEM;
+
+	return 0;
+}
+
+void hv_kvp_deinit(void)
+{
+	cn_del_callback(&kvp_id);
+	cancel_delayed_work_sync(&kvp_work);
+	kfree(recv_buffer);
+}
diff --git a/drivers/staging/hv/hv_kvp.h b/drivers/staging/hv/hv_kvp.h
new file mode 100644
index 0000000..e069f59
--- /dev/null
+++ b/drivers/staging/hv/hv_kvp.h
@@ -0,0 +1,184 @@
+/*
+ * An implementation of HyperV key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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.
+ *
+ * You should have 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	_KVP_H
+#define	_KVP_H_
+
+/*
+ * Maximum value size - used for both key names and value data, and includes
+ * any applicable NULL terminators.
+ *
+ * Note:  This limit is somewhat arbitrary, but falls easily within what is
+ * supported for all native guests (back to Win 2000) and what is reasonable
+ * for the IC KVP exchange functionality.  Note that Windows Me/98/95 are
+ * limited to 255 character key names.
+ *
+ * MSDN recommends not storing data values larger than 2048 bytes in the
+ * registry.
+ *
+ * Note:  This value is used in defining the KVP exchange message - this value
+ * cannot be modified without affecting the message size and compatability.
+ */
+
+/*
+ * bytes, including any null terminators
+ */
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE          (2048)
+
+
+/*
+ * Maximum key size - the registry limit for the length of an entry name
+ * is 256 characters, including the null terminator
+ */
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE            (512)
+
+/*
+ * In Linux, we implement the KVP functionality in two components:
+ * 1) The kernel component which is packaged as part of the hv_utils driver
+ * is responsible for communicating with the host and responsible for
+ * implementing the host/guest protocol. 2) A user level daemon that is
+ * responsible for data gathering.
+ *
+ * Host/Guest Protocol: The host iterates over an index and expects the guest
+ * to assign a key name to the index and also return the value corresponding to
+ * the key. The host will have atmost one KVP transaction outstanding at any
+ * given point in time. The host side iteration stops when the guest returns
+ * an error. Microsoft has specified the following mapping of key names to
+ * host specified index:
+ *
+ *	Index		Key Name
+ *	0		FullyQualifiedDomainName
+ *	1		IntegrationServicesVersion
+ *	2		NetworkAddressIPv4
+ *	3		NetworkAddressIPv6
+ *	4		OSBuildNumber
+ *	5		OSName
+ *	6		OSMajorVersion
+ *	7		OSMinorVersion
+ *	8		OSVersion
+ *	9		ProcessorArchitecture
+ *
+ * The Windows host expects the Key Name and Key Value to be encoded in utf16.
+ *
+ * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the
+ * data gathering functionality in a user mode daemon. The user level daemon
+ * is also responsible for binding the key name to the index as well. The
+ * kernel and user-level daemon communicate using a connector channel.
+ *
+ * The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ *
+ * The kernel component simply acts as a conduit for communication between the
+ * Windows host and the user-level daemon. The kernel component passes up the
+ * index received from the Host to the user-level daemon. If the index is
+ * valid (supported), the corresponding key as well as its
+ * value (both are strings) is returned. If the index is invalid
+ * (not supported), a NULL key string is returned.
+ */
+
+/*
+ *
+ * The following definitions are shared with the user-mode component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP user-mode component.
+ */
+
+#define CN_KVP_VAL             0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL       0x2 /* This supports queries from the user */
+
+enum hv_ku_op {
+	KVP_REGISTER = 0, /* Register the user mode component */
+	KVP_KERNEL_GET, /* Kernel is requesting the value */
+	KVP_KERNEL_SET, /* Kernel is providing the value */
+	KVP_USER_GET,  /* User is requesting the value */
+	KVP_USER_SET  /* User is providing the value */
+};
+
+struct hv_ku_msg {
+	__u32 kvp_index; /* Key index */
+	__u8  kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+	__u8  kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key  value */
+};
+
+
+
+
+#ifdef __KERNEL__
+
+/*
+ * Registry value types.
+ */
+
+#define REG_SZ 1
+
+enum hv_kvp_exchg_op {
+	KVP_OP_GET = 0,
+	KVP_OP_SET,
+	KVP_OP_DELETE,
+	KVP_OP_ENUMERATE,
+	KVP_OP_COUNT /* Number of operations, must be last. */
+};
+
+enum hv_kvp_exchg_pool {
+	KVP_POOL_EXTERNAL = 0,
+	KVP_POOL_GUEST,
+	KVP_POOL_AUTO,
+	KVP_POOL_AUTO_EXTERNAL,
+	KVP_POOL_AUTO_INTERNAL,
+	KVP_POOL_COUNT /* Number of pools, must be last. */
+};
+
+struct hv_kvp_hdr {
+	u8 operation;
+	u8 pool;
+};
+
+struct hv_kvp_exchg_msg_value {
+	u32 value_type;
+	u32 key_size;
+	u32 value_size;
+	u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
+	u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
+};
+
+struct hv_kvp_msg_enumerate {
+	u32 index;
+	struct hv_kvp_exchg_msg_value data;
+};
+
+struct hv_kvp_msg {
+	struct hv_kvp_hdr	kvp_hdr;
+	struct hv_kvp_msg_enumerate	kvp_data;
+};
+
+int hv_kvp_init(void);
+void hv_kvp_deinit(void);
+void hv_kvp_onchannelcallback(void *);
+
+#endif /* __KERNEL__ */
+#endif	/* _KVP_H */
+
diff --git a/drivers/staging/hv/hv_mouse.c b/drivers/staging/hv/hv_mouse.c
new file mode 100644
index 0000000..50147f8
--- /dev/null
+++ b/drivers/staging/hv/hv_mouse.c
@@ -0,0 +1,1046 @@
+/*
+ *  Copyright (c) 2009, Citrix Systems, Inc.
+ *  Copyright (c) 2010, Microsoft Corporation.
+ *  Copyright (c) 2011, Novell 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,
+ *  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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/hiddev.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
+
+#include "hv_api.h"
+#include "logging.h"
+#include "version_info.h"
+#include "vmbus.h"
+#include "vmbus_api.h"
+#include "channel.h"
+#include "vmbus_packet_format.h"
+
+
+/*
+ * Data types
+ */
+struct hv_input_dev_info {
+	unsigned short vendor;
+	unsigned short product;
+	unsigned short version;
+	char name[128];
+};
+
+/* Represents the input vsc driver */
+/* FIXME - can be removed entirely */
+struct mousevsc_drv_obj {
+	struct hv_driver Base;
+};
+
+
+/* The maximum size of a synthetic input message. */
+#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
+
+/*
+ * Current version
+ *
+ * History:
+ * Beta, RC < 2008/1/22        1,0
+ * RC > 2008/1/22              2,0
+ */
+#define SYNTHHID_INPUT_VERSION_MAJOR	2
+#define SYNTHHID_INPUT_VERSION_MINOR	0
+#define SYNTHHID_INPUT_VERSION		(SYNTHHID_INPUT_VERSION_MINOR | \
+					 (SYNTHHID_INPUT_VERSION_MAJOR << 16))
+
+
+#pragma pack(push,1)
+/*
+ * Message types in the synthetic input protocol
+ */
+enum synthhid_msg_type {
+	SynthHidProtocolRequest,
+	SynthHidProtocolResponse,
+	SynthHidInitialDeviceInfo,
+	SynthHidInitialDeviceInfoAck,
+	SynthHidInputReport,
+	SynthHidMax
+};
+
+/*
+ * Basic message structures.
+ */
+struct synthhid_msg_hdr {
+	enum synthhid_msg_type type;
+	u32 size;
+};
+
+struct synthhid_msg {
+	struct synthhid_msg_hdr header;
+	char data[1]; /* Enclosed message */
+};
+
+union synthhid_version {
+	struct {
+		u16 minor_version;
+		u16 major_version;
+	};
+	u32 version;
+};
+
+/*
+ * Protocol messages
+ */
+struct synthhid_protocol_request {
+	struct synthhid_msg_hdr header;
+	union synthhid_version version_requested;
+};
+
+struct synthhid_protocol_response {
+	struct synthhid_msg_hdr header;
+	union synthhid_version version_requested;
+	unsigned char approved;
+};
+
+struct synthhid_device_info {
+	struct synthhid_msg_hdr header;
+	struct hv_input_dev_info hid_dev_info;
+	struct hid_descriptor hid_descriptor;
+};
+
+struct synthhid_device_info_ack {
+	struct synthhid_msg_hdr header;
+	unsigned char reserved;
+};
+
+struct synthhid_input_report {
+	struct synthhid_msg_hdr header;
+	char buffer[1];
+};
+
+#pragma pack(pop)
+
+#define INPUTVSC_SEND_RING_BUFFER_SIZE		10*PAGE_SIZE
+#define INPUTVSC_RECV_RING_BUFFER_SIZE		10*PAGE_SIZE
+
+#define NBITS(x) (((x)/BITS_PER_LONG)+1)
+
+enum pipe_prot_msg_type {
+	PipeMessageInvalid = 0,
+	PipeMessageData,
+	PipeMessageMaximum
+};
+
+
+struct pipe_prt_msg {
+	enum pipe_prot_msg_type type;
+	u32 size;
+	char data[1];
+};
+
+/*
+ * Data types
+ */
+struct  mousevsc_prt_msg {
+	enum pipe_prot_msg_type type;
+	u32 size;
+	union {
+		struct synthhid_protocol_request request;
+		struct synthhid_protocol_response response;
+		struct synthhid_device_info_ack ack;
+	};
+};
+
+/*
+ * Represents an mousevsc device
+ */
+struct mousevsc_dev {
+	struct hv_device	*Device;
+	/* 0 indicates the device is being destroyed */
+	atomic_t		RefCount;
+	int			NumOutstandingRequests;
+	unsigned char		bInitializeComplete;
+	struct mousevsc_prt_msg	ProtocolReq;
+	struct mousevsc_prt_msg	ProtocolResp;
+	/* Synchronize the request/response if needed */
+	wait_queue_head_t	ProtocolWaitEvent;
+	wait_queue_head_t	DeviceInfoWaitEvent;
+	int			protocol_wait_condition;
+	int			device_wait_condition;
+	int			DeviceInfoStatus;
+
+	struct hid_descriptor	*HidDesc;
+	unsigned char		*ReportDesc;
+	u32			ReportDescSize;
+	struct hv_input_dev_info hid_dev_info;
+};
+
+
+static const char *driver_name = "mousevsc";
+
+/* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
+static const struct hv_guid mouse_guid = {
+	.data = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
+		 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A}
+};
+
+static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info);
+static void inputreport_callback(struct hv_device *dev, void *packet, u32 len);
+static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len);
+
+static struct mousevsc_dev *AllocInputDevice(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = kzalloc(sizeof(struct mousevsc_dev), GFP_KERNEL);
+
+	if (!inputDevice)
+		return NULL;
+
+	/*
+	 * Set to 2 to allow both inbound and outbound traffics
+	 * (ie GetInputDevice() and MustGetInputDevice()) to proceed.
+	 */
+	atomic_cmpxchg(&inputDevice->RefCount, 0, 2);
+
+	inputDevice->Device = Device;
+	Device->ext = inputDevice;
+
+	return inputDevice;
+}
+
+static void FreeInputDevice(struct mousevsc_dev *Device)
+{
+	WARN_ON(atomic_read(&Device->RefCount) == 0);
+	kfree(Device);
+}
+
+/*
+ * Get the inputdevice object if exists and its refcount > 1
+ */
+static struct mousevsc_dev *GetInputDevice(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = (struct mousevsc_dev *)Device->ext;
+
+/*
+ *	FIXME
+ *	This sure isn't a valid thing to print for debugging, no matter
+ *	what the intention is...
+ *
+ *	printk(KERN_ERR "-------------------------> REFCOUNT = %d",
+ *	       inputDevice->RefCount);
+ */
+
+	if (inputDevice && atomic_read(&inputDevice->RefCount) > 1)
+		atomic_inc(&inputDevice->RefCount);
+	else
+		inputDevice = NULL;
+
+	return inputDevice;
+}
+
+/*
+ * Get the inputdevice object iff exists and its refcount > 0
+ */
+static struct mousevsc_dev *MustGetInputDevice(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = (struct mousevsc_dev *)Device->ext;
+
+	if (inputDevice && atomic_read(&inputDevice->RefCount))
+		atomic_inc(&inputDevice->RefCount);
+	else
+		inputDevice = NULL;
+
+	return inputDevice;
+}
+
+static void PutInputDevice(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = (struct mousevsc_dev *)Device->ext;
+
+	atomic_dec(&inputDevice->RefCount);
+}
+
+/*
+ * Drop ref count to 1 to effectively disable GetInputDevice()
+ */
+static struct mousevsc_dev *ReleaseInputDevice(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = (struct mousevsc_dev *)Device->ext;
+
+	/* Busy wait until the ref drop to 2, then set it to 1  */
+	while (atomic_cmpxchg(&inputDevice->RefCount, 2, 1) != 2)
+		udelay(100);
+
+	return inputDevice;
+}
+
+/*
+ * Drop ref count to 0. No one can use InputDevice object.
+ */
+static struct mousevsc_dev *FinalReleaseInputDevice(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = (struct mousevsc_dev *)Device->ext;
+
+	/* Busy wait until the ref drop to 1, then set it to 0  */
+	while (atomic_cmpxchg(&inputDevice->RefCount, 1, 0) != 1)
+		udelay(100);
+
+	Device->ext = NULL;
+	return inputDevice;
+}
+
+static void MousevscOnSendCompletion(struct hv_device *Device, struct vmpacket_descriptor *Packet)
+{
+	struct mousevsc_dev *inputDevice;
+	void *request;
+
+	inputDevice = MustGetInputDevice(Device);
+	if (!inputDevice) {
+		pr_err("unable to get input device...device being destroyed?");
+		return;
+	}
+
+	request = (void *)(unsigned long)Packet->trans_id;
+
+	if (request == &inputDevice->ProtocolReq) {
+		/* FIXME */
+		/* Shouldn't we be doing something here? */
+	}
+
+	PutInputDevice(Device);
+}
+
+static void MousevscOnReceiveDeviceInfo(struct mousevsc_dev *InputDevice, struct synthhid_device_info *DeviceInfo)
+{
+	int ret = 0;
+	struct hid_descriptor *desc;
+	struct mousevsc_prt_msg ack;
+
+	/* Assume success for now */
+	InputDevice->DeviceInfoStatus = 0;
+
+	/* Save the device attr */
+	memcpy(&InputDevice->hid_dev_info, &DeviceInfo->hid_dev_info, sizeof(struct hv_input_dev_info));
+
+	/* Save the hid desc */
+	desc = &DeviceInfo->hid_descriptor;
+	WARN_ON(desc->bLength > 0);
+
+	InputDevice->HidDesc = kzalloc(desc->bLength, GFP_KERNEL);
+
+	if (!InputDevice->HidDesc) {
+		pr_err("unable to allocate hid descriptor - size %d", desc->bLength);
+		goto Cleanup;
+	}
+
+	memcpy(InputDevice->HidDesc, desc, desc->bLength);
+
+	/* Save the report desc */
+	InputDevice->ReportDescSize = desc->desc[0].wDescriptorLength;
+	InputDevice->ReportDesc = kzalloc(InputDevice->ReportDescSize,
+					  GFP_KERNEL);
+
+	if (!InputDevice->ReportDesc) {
+		pr_err("unable to allocate report descriptor - size %d",
+			   InputDevice->ReportDescSize);
+		goto Cleanup;
+	}
+
+	memcpy(InputDevice->ReportDesc,
+	       ((unsigned char *)desc) + desc->bLength,
+	       desc->desc[0].wDescriptorLength);
+
+	/* Send the ack */
+	memset(&ack, sizeof(struct mousevsc_prt_msg), 0);
+
+	ack.type = PipeMessageData;
+	ack.size = sizeof(struct synthhid_device_info_ack);
+
+	ack.ack.header.type = SynthHidInitialDeviceInfoAck;
+	ack.ack.header.size = 1;
+	ack.ack.reserved = 0;
+
+	ret = vmbus_sendpacket(InputDevice->Device->channel,
+			&ack,
+			sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
+			sizeof(struct synthhid_device_info_ack),
+			(unsigned long)&ack,
+			VM_PKT_DATA_INBAND,
+			VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0) {
+		pr_err("unable to send synthhid device info ack - ret %d",
+			   ret);
+		goto Cleanup;
+	}
+
+	InputDevice->device_wait_condition = 1;
+	wake_up(&InputDevice->DeviceInfoWaitEvent);
+
+	return;
+
+Cleanup:
+	kfree(InputDevice->HidDesc);
+	InputDevice->HidDesc = NULL;
+
+	kfree(InputDevice->ReportDesc);
+	InputDevice->ReportDesc = NULL;
+
+	InputDevice->DeviceInfoStatus = -1;
+	InputDevice->device_wait_condition = 1;
+	wake_up(&InputDevice->DeviceInfoWaitEvent);
+}
+
+static void MousevscOnReceiveInputReport(struct mousevsc_dev *InputDevice, struct synthhid_input_report *InputReport)
+{
+	struct mousevsc_drv_obj *inputDriver;
+
+	if (!InputDevice->bInitializeComplete) {
+		pr_info("Initialization incomplete...ignoring InputReport msg");
+		return;
+	}
+
+	inputDriver = (struct mousevsc_drv_obj *)InputDevice->Device->drv;
+
+	inputreport_callback(InputDevice->Device,
+			     InputReport->buffer,
+			     InputReport->header.size);
+}
+
+static void MousevscOnReceive(struct hv_device *Device, struct vmpacket_descriptor *Packet)
+{
+	struct pipe_prt_msg *pipeMsg;
+	struct synthhid_msg *hidMsg;
+	struct mousevsc_dev *inputDevice;
+
+	inputDevice = MustGetInputDevice(Device);
+	if (!inputDevice) {
+		pr_err("unable to get input device...device being destroyed?");
+		return;
+	}
+
+	pipeMsg = (struct pipe_prt_msg *)((unsigned long)Packet + (Packet->offset8 << 3));
+
+	if (pipeMsg->type != PipeMessageData) {
+		pr_err("unknown pipe msg type - type %d len %d",
+			   pipeMsg->type, pipeMsg->size);
+		PutInputDevice(Device);
+		return ;
+	}
+
+	hidMsg = (struct synthhid_msg *)&pipeMsg->data[0];
+
+	switch (hidMsg->header.type) {
+	case SynthHidProtocolResponse:
+		memcpy(&inputDevice->ProtocolResp, pipeMsg,
+		       pipeMsg->size + sizeof(struct pipe_prt_msg) -
+		       sizeof(unsigned char));
+		inputDevice->protocol_wait_condition = 1;
+		wake_up(&inputDevice->ProtocolWaitEvent);
+		break;
+
+	case SynthHidInitialDeviceInfo:
+		WARN_ON(pipeMsg->size >= sizeof(struct hv_input_dev_info));
+
+		/*
+		 * Parse out the device info into device attr,
+		 * hid desc and report desc
+		 */
+		MousevscOnReceiveDeviceInfo(inputDevice,
+					    (struct synthhid_device_info *)&pipeMsg->data[0]);
+		break;
+	case SynthHidInputReport:
+		MousevscOnReceiveInputReport(inputDevice,
+					     (struct synthhid_input_report *)&pipeMsg->data[0]);
+
+		break;
+	default:
+		pr_err("unsupported hid msg type - type %d len %d",
+		       hidMsg->header.type, hidMsg->header.size);
+		break;
+	}
+
+	PutInputDevice(Device);
+}
+
+static void MousevscOnChannelCallback(void *Context)
+{
+	const int packetSize = 0x100;
+	int ret = 0;
+	struct hv_device *device = (struct hv_device *)Context;
+	struct mousevsc_dev *inputDevice;
+
+	u32 bytesRecvd;
+	u64 requestId;
+	unsigned char packet[packetSize];
+	struct vmpacket_descriptor *desc;
+	unsigned char	*buffer = packet;
+	int	bufferlen = packetSize;
+
+	inputDevice = MustGetInputDevice(device);
+
+	if (!inputDevice) {
+		pr_err("unable to get input device...device being destroyed?");
+		return;
+	}
+
+	do {
+		ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen, &bytesRecvd, &requestId);
+
+		if (ret == 0) {
+			if (bytesRecvd > 0) {
+				desc = (struct vmpacket_descriptor *)buffer;
+
+				switch (desc->type) {
+					case VM_PKT_COMP:
+						MousevscOnSendCompletion(device,
+									 desc);
+						break;
+
+					case VM_PKT_DATA_INBAND:
+						MousevscOnReceive(device, desc);
+						break;
+
+					default:
+						pr_err("unhandled packet type %d, tid %llx len %d\n",
+							   desc->type,
+							   requestId,
+							   bytesRecvd);
+						break;
+				}
+
+				/* reset */
+				if (bufferlen > packetSize) {
+					kfree(buffer);
+
+					buffer = packet;
+					bufferlen = packetSize;
+				}
+			} else {
+				/*
+				 * pr_debug("nothing else to read...");
+				 * reset
+				 */
+				if (bufferlen > packetSize) {
+					kfree(buffer);
+
+					buffer = packet;
+					bufferlen = packetSize;
+				}
+				break;
+			}
+		} else if (ret == -2) {
+			/* Handle large packet */
+			bufferlen = bytesRecvd;
+			buffer = kzalloc(bytesRecvd, GFP_KERNEL);
+
+			if (buffer == NULL) {
+				buffer = packet;
+				bufferlen = packetSize;
+
+				/* Try again next time around */
+				pr_err("unable to allocate buffer of size %d!",
+				       bytesRecvd);
+				break;
+			}
+		}
+	} while (1);
+
+	PutInputDevice(device);
+
+	return;
+}
+
+static int MousevscConnectToVsp(struct hv_device *Device)
+{
+	int ret = 0;
+	struct mousevsc_dev *inputDevice;
+	struct mousevsc_prt_msg *request;
+	struct mousevsc_prt_msg *response;
+
+	inputDevice = GetInputDevice(Device);
+
+	if (!inputDevice) {
+		pr_err("unable to get input device...device being destroyed?");
+		return -1;
+	}
+
+	init_waitqueue_head(&inputDevice->ProtocolWaitEvent);
+	init_waitqueue_head(&inputDevice->DeviceInfoWaitEvent);
+
+	request = &inputDevice->ProtocolReq;
+
+	/*
+	 * Now, initiate the vsc/vsp initialization protocol on the open channel
+	 */
+	memset(request, sizeof(struct mousevsc_prt_msg), 0);
+
+	request->type = PipeMessageData;
+	request->size = sizeof(struct synthhid_protocol_request);
+
+	request->request.header.type = SynthHidProtocolRequest;
+	request->request.header.size = sizeof(unsigned long);
+	request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
+
+	pr_info("synthhid protocol request...");
+
+	ret = vmbus_sendpacket(Device->channel, request,
+					sizeof(struct pipe_prt_msg) -
+					sizeof(unsigned char) +
+					sizeof(struct synthhid_protocol_request),
+					(unsigned long)request,
+					VM_PKT_DATA_INBAND,
+					VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
+	if (ret != 0) {
+		pr_err("unable to send synthhid protocol request.");
+		goto Cleanup;
+	}
+
+	inputDevice->protocol_wait_condition = 0;
+	wait_event_timeout(inputDevice->ProtocolWaitEvent, inputDevice->protocol_wait_condition, msecs_to_jiffies(1000));
+	if (inputDevice->protocol_wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
+
+	response = &inputDevice->ProtocolResp;
+
+	if (!response->response.approved) {
+		pr_err("synthhid protocol request failed (version %d)",
+		       SYNTHHID_INPUT_VERSION);
+		ret = -1;
+		goto Cleanup;
+	}
+
+	inputDevice->device_wait_condition = 0;
+	wait_event_timeout(inputDevice->DeviceInfoWaitEvent, inputDevice->device_wait_condition, msecs_to_jiffies(1000));
+	if (inputDevice->device_wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
+
+	/*
+	 * We should have gotten the device attr, hid desc and report
+	 * desc at this point
+	 */
+	if (!inputDevice->DeviceInfoStatus)
+		pr_info("**** input channel up and running!! ****");
+	else
+		ret = -1;
+
+Cleanup:
+	PutInputDevice(Device);
+
+	return ret;
+}
+
+static int MousevscOnDeviceAdd(struct hv_device *Device, void *AdditionalInfo)
+{
+	int ret = 0;
+	struct mousevsc_dev *inputDevice;
+	struct mousevsc_drv_obj *inputDriver;
+	struct hv_input_dev_info dev_info;
+
+	inputDevice = AllocInputDevice(Device);
+
+	if (!inputDevice) {
+		ret = -1;
+		goto Cleanup;
+	}
+
+	inputDevice->bInitializeComplete = false;
+
+	/* Open the channel */
+	ret = vmbus_open(Device->channel,
+		INPUTVSC_SEND_RING_BUFFER_SIZE,
+		INPUTVSC_RECV_RING_BUFFER_SIZE,
+		NULL,
+		0,
+		MousevscOnChannelCallback,
+		Device
+		);
+
+	if (ret != 0) {
+		pr_err("unable to open channel: %d", ret);
+		FreeInputDevice(inputDevice);
+		return -1;
+	}
+
+	pr_info("InputVsc channel open: %d", ret);
+
+	ret = MousevscConnectToVsp(Device);
+
+	if (ret != 0) {
+		pr_err("unable to connect channel: %d", ret);
+
+		vmbus_close(Device->channel);
+		FreeInputDevice(inputDevice);
+		return ret;
+	}
+
+	inputDriver = (struct mousevsc_drv_obj *)inputDevice->Device->drv;
+
+	dev_info.vendor = inputDevice->hid_dev_info.vendor;
+	dev_info.product = inputDevice->hid_dev_info.product;
+	dev_info.version = inputDevice->hid_dev_info.version;
+	strcpy(dev_info.name, "Microsoft Vmbus HID-compliant Mouse");
+
+	/* Send the device info back up */
+	deviceinfo_callback(Device, &dev_info);
+
+	/* Send the report desc back up */
+	/* workaround SA-167 */
+	if (inputDevice->ReportDesc[14] == 0x25)
+		inputDevice->ReportDesc[14] = 0x29;
+
+	reportdesc_callback(Device, inputDevice->ReportDesc,
+			    inputDevice->ReportDescSize);
+
+	inputDevice->bInitializeComplete = true;
+
+Cleanup:
+	return ret;
+}
+
+static int MousevscOnDeviceRemove(struct hv_device *Device)
+{
+	struct mousevsc_dev *inputDevice;
+	int ret = 0;
+
+	pr_info("disabling input device (%p)...",
+		    Device->ext);
+
+	inputDevice = ReleaseInputDevice(Device);
+
+
+	/*
+	 * At this point, all outbound traffic should be disable. We only
+	 * allow inbound traffic (responses) to proceed
+	 *
+	 * so that outstanding requests can be completed.
+	 */
+	while (inputDevice->NumOutstandingRequests) {
+		pr_info("waiting for %d requests to complete...", inputDevice->NumOutstandingRequests);
+
+		udelay(100);
+	}
+
+	pr_info("removing input device (%p)...", Device->ext);
+
+	inputDevice = FinalReleaseInputDevice(Device);
+
+	pr_info("input device (%p) safe to remove", inputDevice);
+
+	/* Close the channel */
+	vmbus_close(Device->channel);
+
+	FreeInputDevice(inputDevice);
+
+	return ret;
+}
+
+static void MousevscOnCleanup(struct hv_driver *drv)
+{
+}
+
+/*
+ * Data types
+ */
+struct input_device_context {
+	struct hv_device	*device_ctx;
+	struct hid_device	*hid_device;
+	struct hv_input_dev_info device_info;
+	int			connected;
+};
+
+
+static struct  mousevsc_drv_obj g_mousevsc_drv;
+
+static void deviceinfo_callback(struct hv_device *dev, struct hv_input_dev_info *info)
+{
+	struct input_device_context *input_device_ctx =
+		dev_get_drvdata(&dev->device);
+
+	memcpy(&input_device_ctx->device_info, info,
+	       sizeof(struct hv_input_dev_info));
+
+	DPRINT_INFO(INPUTVSC_DRV, "%s", __func__);
+}
+
+static void inputreport_callback(struct hv_device *dev, void *packet, u32 len)
+{
+	int ret = 0;
+
+	struct input_device_context *input_dev_ctx =
+		dev_get_drvdata(&dev->device);
+
+	ret = hid_input_report(input_dev_ctx->hid_device,
+			      HID_INPUT_REPORT, packet, len, 1);
+
+	DPRINT_DBG(INPUTVSC_DRV, "hid_input_report (ret %d)", ret);
+}
+
+static int mousevsc_hid_open(struct hid_device *hid)
+{
+	return 0;
+}
+
+static void mousevsc_hid_close(struct hid_device *hid)
+{
+}
+
+static int mousevsc_probe(struct device *device)
+{
+	int ret = 0;
+
+	struct hv_driver *drv =
+		drv_to_hv_drv(device->driver);
+	struct mousevsc_drv_obj *mousevsc_drv_obj = drv->priv;
+
+	struct hv_device *device_obj = device_to_hv_device(device);
+	struct input_device_context *input_dev_ctx;
+
+	input_dev_ctx = kmalloc(sizeof(struct input_device_context),
+				GFP_KERNEL);
+
+	dev_set_drvdata(device, input_dev_ctx);
+
+	/* Call to the vsc driver to add the device */
+	ret = mousevsc_drv_obj->Base.dev_add(device_obj, NULL);
+
+	if (ret != 0) {
+		DPRINT_ERR(INPUTVSC_DRV, "unable to add input vsc device");
+
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mousevsc_remove(struct device *device)
+{
+	int ret = 0;
+
+	struct hv_driver *drv =
+		drv_to_hv_drv(device->driver);
+	struct mousevsc_drv_obj *mousevsc_drv_obj = drv->priv;
+
+	struct hv_device *device_obj = device_to_hv_device(device);
+	struct input_device_context *input_dev_ctx;
+
+	input_dev_ctx = kmalloc(sizeof(struct input_device_context),
+				GFP_KERNEL);
+
+	dev_set_drvdata(device, input_dev_ctx);
+
+	if (input_dev_ctx->connected) {
+		hidinput_disconnect(input_dev_ctx->hid_device);
+		input_dev_ctx->connected = 0;
+	}
+
+	if (!mousevsc_drv_obj->Base.dev_rm)
+		return -1;
+
+	/*
+	 * Call to the vsc driver to let it know that the device
+	 * is being removed
+	 */
+	ret = mousevsc_drv_obj->Base.dev_rm(device_obj);
+
+	if (ret != 0) {
+		DPRINT_ERR(INPUTVSC_DRV,
+			   "unable to remove vsc device (ret %d)", ret);
+	}
+
+	kfree(input_dev_ctx);
+
+	return ret;
+}
+
+static void reportdesc_callback(struct hv_device *dev, void *packet, u32 len)
+{
+	struct input_device_context *input_device_ctx =
+		dev_get_drvdata(&dev->device);
+	struct hid_device *hid_dev;
+
+	/* hid_debug = -1; */
+	hid_dev = kmalloc(sizeof(struct hid_device), GFP_KERNEL);
+
+	if (hid_parse_report(hid_dev, packet, len)) {
+		DPRINT_INFO(INPUTVSC_DRV, "Unable to call hd_parse_report");
+		return;
+	}
+
+	if (hid_dev) {
+		DPRINT_INFO(INPUTVSC_DRV, "hid_device created");
+
+		hid_dev->ll_driver->open  = mousevsc_hid_open;
+		hid_dev->ll_driver->close = mousevsc_hid_close;
+
+		hid_dev->bus = BUS_VIRTUAL;
+		hid_dev->vendor = input_device_ctx->device_info.vendor;
+		hid_dev->product = input_device_ctx->device_info.product;
+		hid_dev->version = input_device_ctx->device_info.version;
+		hid_dev->dev = dev->device;
+
+		sprintf(hid_dev->name, "%s",
+			input_device_ctx->device_info.name);
+
+		/*
+		 * HJ Do we want to call it with a 0
+		 */
+		if (!hidinput_connect(hid_dev, 0)) {
+			hid_dev->claimed |= HID_CLAIMED_INPUT;
+
+			input_device_ctx->connected = 1;
+
+			DPRINT_INFO(INPUTVSC_DRV,
+				     "HID device claimed by input\n");
+		}
+
+		if (!hid_dev->claimed) {
+			DPRINT_ERR(INPUTVSC_DRV,
+				    "HID device not claimed by "
+				    "input or hiddev\n");
+		}
+
+		input_device_ctx->hid_device = hid_dev;
+	}
+
+	kfree(hid_dev);
+}
+
+static int mousevsc_drv_exit_cb(struct device *dev, void *data)
+{
+	struct device **curr = (struct device **)data;
+	*curr = dev;
+
+	return 1;
+}
+
+static void mousevsc_drv_exit(void)
+{
+	struct mousevsc_drv_obj *mousevsc_drv_obj = &g_mousevsc_drv;
+	struct hv_driver *drv = &g_mousevsc_drv.Base;
+	int ret;
+
+	struct device *current_dev = NULL;
+
+	while (1) {
+		current_dev = NULL;
+
+		/* Get the device */
+		ret = driver_for_each_device(&drv->driver, NULL,
+					     (void *)&current_dev,
+					     mousevsc_drv_exit_cb);
+		if (ret)
+			printk(KERN_ERR "Can't find mouse device!\n");
+
+		if (current_dev == NULL)
+			break;
+
+		/* Initiate removal from the top-down */
+		device_unregister(current_dev);
+	}
+
+	if (mousevsc_drv_obj->Base.cleanup)
+		mousevsc_drv_obj->Base.cleanup(&mousevsc_drv_obj->Base);
+
+	vmbus_child_driver_unregister(&drv->driver);
+
+	return;
+}
+
+static int mouse_vsc_initialize(struct hv_driver *Driver)
+{
+	struct mousevsc_drv_obj *inputDriver =
+		(struct mousevsc_drv_obj *)Driver;
+	int ret = 0;
+
+	Driver->name = driver_name;
+	memcpy(&Driver->dev_type, &mouse_guid,
+	       sizeof(struct hv_guid));
+
+	/* Setup the dispatch table */
+	inputDriver->Base.dev_add = MousevscOnDeviceAdd;
+	inputDriver->Base.dev_rm = MousevscOnDeviceRemove;
+	inputDriver->Base.cleanup = MousevscOnCleanup;
+
+	return ret;
+}
+
+
+static int __init mousevsc_init(void)
+{
+	struct mousevsc_drv_obj *input_drv_obj = &g_mousevsc_drv;
+	struct hv_driver *drv = &g_mousevsc_drv.Base;
+
+	DPRINT_INFO(INPUTVSC_DRV, "Hyper-V Mouse driver initializing.");
+
+	/* Callback to client driver to complete the initialization */
+	mouse_vsc_initialize(&input_drv_obj->Base);
+
+	drv->driver.name = input_drv_obj->Base.name;
+	drv->priv = input_drv_obj;
+
+	drv->driver.probe = mousevsc_probe;
+	drv->driver.remove = mousevsc_remove;
+
+	/* The driver belongs to vmbus */
+	vmbus_child_driver_register(&drv->driver);
+
+	return 0;
+}
+
+static void __exit mousevsc_exit(void)
+{
+	mousevsc_drv_exit();
+}
+
+/*
+ * We don't want to automatically load this driver just yet, it's quite
+ * broken.  It's safe if you want to load it yourself manually, but
+ * don't inflict it on unsuspecting users, that's just mean.
+ */
+#if 0
+
+/*
+ * We use a PCI table to determine if we should autoload this driver  This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured.  We don't do anything else with the table, but
+ * it needs to be present.
+ */
+const static struct pci_device_id microsoft_hv_pci_table[] = {
+	{ PCI_DEVICE(0x1414, 0x5353) },	/* VGA compatible controller */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
+module_init(mousevsc_init);
+module_exit(mousevsc_exit);
+
diff --git a/drivers/staging/hv/hv_util.c b/drivers/staging/hv/hv_util.c
new file mode 100644
index 0000000..4792f2c
--- /dev/null
+++ b/drivers/staging/hv/hv_util.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2010, Microsoft Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Authors:
+ *   Haiyang Zhang <haiyangz@microsoft.com>
+ *   Hank Janssen  <hjanssen@microsoft.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/reboot.h>
+#include <linux/dmi.h>
+#include <linux/pci.h>
+
+#include "logging.h"
+#include "hv_api.h"
+#include "vmbus.h"
+#include "vmbus_packet_format.h"
+#include "vmbus_channel_interface.h"
+#include "version_info.h"
+#include "channel.h"
+#include "vmbus_private.h"
+#include "vmbus_api.h"
+#include "utils.h"
+#include "hv_kvp.h"
+
+static u8 *shut_txf_buf;
+static u8 *time_txf_buf;
+static u8 *hbeat_txf_buf;
+
+static void shutdown_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	u8  execute_shutdown = false;
+
+	struct shutdown_msg_data *shutdown_msg;
+
+	struct icmsg_hdr *icmsghdrp;
+	struct icmsg_negotiate *negop = NULL;
+
+	vmbus_recvpacket(channel, shut_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
+			   recvlen, requestid);
+
+		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
+			sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
+		} else {
+			shutdown_msg =
+				(struct shutdown_msg_data *)&shut_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
+
+			switch (shutdown_msg->flags) {
+			case 0:
+			case 1:
+				icmsghdrp->status = HV_S_OK;
+				execute_shutdown = true;
+
+				DPRINT_INFO(VMBUS, "Shutdown request received -"
+					    " gracefull shutdown initiated");
+				break;
+			default:
+				icmsghdrp->status = HV_E_FAIL;
+				execute_shutdown = false;
+
+				DPRINT_INFO(VMBUS, "Shutdown request received -"
+					    " Invalid request");
+				break;
+			};
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, shut_txf_buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+
+	if (execute_shutdown == true)
+		orderly_poweroff(false);
+}
+
+/*
+ * Set guest time to host UTC time.
+ */
+static inline void do_adj_guesttime(u64 hosttime)
+{
+	s64 host_tns;
+	struct timespec host_ts;
+
+	host_tns = (hosttime - WLTIMEDELTA) * 100;
+	host_ts = ns_to_timespec(host_tns);
+
+	do_settimeofday(&host_ts);
+}
+
+/*
+ * Synchronize time with host after reboot, restore, etc.
+ *
+ * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
+ * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
+ * message after the timesync channel is opened. Since the hv_utils module is
+ * loaded after hv_vmbus, the first message is usually missed. The other
+ * thing is, systime is automatically set to emulated hardware clock which may
+ * not be UTC time or in the same time zone. So, to override these effects, we
+ * use the first 50 time samples for initial system time setting.
+ */
+static inline void adj_guesttime(u64 hosttime, u8 flags)
+{
+	static s32 scnt = 50;
+
+	if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
+		do_adj_guesttime(hosttime);
+		return;
+	}
+
+	if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
+		scnt--;
+		do_adj_guesttime(hosttime);
+	}
+}
+
+/*
+ * Time Sync Channel message handler.
+ */
+static void timesync_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct icmsg_hdr *icmsghdrp;
+	struct ictimesync_data *timedatap;
+
+	vmbus_recvpacket(channel, time_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
+			recvlen, requestid);
+
+		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
+				sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
+		} else {
+			timedatap = (struct ictimesync_data *)&time_txf_buf[
+				sizeof(struct vmbuspipe_hdr) +
+				sizeof(struct icmsg_hdr)];
+			adj_guesttime(timedatap->parenttime, timedatap->flags);
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, time_txf_buf,
+				recvlen, requestid,
+				VM_PKT_DATA_INBAND, 0);
+	}
+}
+
+/*
+ * Heartbeat functionality.
+ * Every two seconds, Hyper-V send us a heartbeat request message.
+ * we respond to this message, and Hyper-V knows we are alive.
+ */
+static void heartbeat_onchannelcallback(void *context)
+{
+	struct vmbus_channel *channel = context;
+	u32 recvlen;
+	u64 requestid;
+	struct icmsg_hdr *icmsghdrp;
+	struct heartbeat_msg_data *heartbeat_msg;
+
+	vmbus_recvpacket(channel, hbeat_txf_buf,
+			 PAGE_SIZE, &recvlen, &requestid);
+
+	if (recvlen > 0) {
+		DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
+			   recvlen, requestid);
+
+		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
+				sizeof(struct vmbuspipe_hdr)];
+
+		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
+			prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
+		} else {
+			heartbeat_msg =
+				(struct heartbeat_msg_data *)&hbeat_txf_buf[
+					sizeof(struct vmbuspipe_hdr) +
+					sizeof(struct icmsg_hdr)];
+
+			DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
+				   heartbeat_msg->seq_num);
+
+			heartbeat_msg->seq_num += 1;
+		}
+
+		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
+			| ICMSGHDRFLAG_RESPONSE;
+
+		vmbus_sendpacket(channel, hbeat_txf_buf,
+				       recvlen, requestid,
+				       VM_PKT_DATA_INBAND, 0);
+	}
+}
+
+static const struct pci_device_id __initconst
+hv_utils_pci_table[] __maybe_unused = {
+	{ PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
+
+
+static const struct dmi_system_id __initconst
+hv_utils_dmi_table[] __maybe_unused  = {
+	{
+		.ident = "Hyper-V",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+		},
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
+
+
+static int __init init_hyperv_utils(void)
+{
+	printk(KERN_INFO "Registering HyperV Utility Driver\n");
+
+	if (hv_kvp_init())
+		return -ENODEV;
+
+
+	if (!dmi_check_system(hv_utils_dmi_table))
+		return -ENODEV;
+
+	shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+	if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
+		printk(KERN_INFO
+		       "Unable to allocate memory for receive buffer\n");
+		kfree(shut_txf_buf);
+		kfree(time_txf_buf);
+		kfree(hbeat_txf_buf);
+		return -ENOMEM;
+	}
+
+	hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
+		&shutdown_onchannelcallback;
+	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
+
+	hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
+		&timesync_onchannelcallback;
+	hv_cb_utils[HV_TIMESYNC_MSG].callback = &timesync_onchannelcallback;
+
+	hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
+		&heartbeat_onchannelcallback;
+	hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
+
+	hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
+		&hv_kvp_onchannelcallback;
+
+
+
+	return 0;
+}
+
+static void exit_hyperv_utils(void)
+{
+	printk(KERN_INFO "De-Registered HyperV Utility Driver\n");
+
+	hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
+		&chn_cb_negotiate;
+	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
+
+	hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
+		&chn_cb_negotiate;
+	hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
+
+	hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
+		&chn_cb_negotiate;
+	hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
+
+	hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback =
+		&chn_cb_negotiate;
+	hv_kvp_deinit();
+
+	kfree(shut_txf_buf);
+	kfree(time_txf_buf);
+	kfree(hbeat_txf_buf);
+}
+
+module_init(init_hyperv_utils);
+module_exit(exit_hyperv_utils);
+
+MODULE_DESCRIPTION("Hyper-V Utilities");
+MODULE_VERSION(HV_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/hv/hv_utils.c b/drivers/staging/hv/hv_utils.c
deleted file mode 100644
index 0074581..0000000
--- a/drivers/staging/hv/hv_utils.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) 2010, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/sysctl.h>
-#include <linux/reboot.h>
-#include <linux/dmi.h>
-#include <linux/pci.h>
-
-#include "logging.h"
-#include "osd.h"
-#include "vmbus.h"
-#include "vmbus_packet_format.h"
-#include "vmbus_channel_interface.h"
-#include "version_info.h"
-#include "channel.h"
-#include "vmbus_private.h"
-#include "vmbus_api.h"
-#include "utils.h"
-
-static u8 *shut_txf_buf;
-static u8 *time_txf_buf;
-static u8 *hbeat_txf_buf;
-
-static void shutdown_onchannelcallback(void *context)
-{
-	struct vmbus_channel *channel = context;
-	u32 recvlen;
-	u64 requestid;
-	u8  execute_shutdown = false;
-
-	struct shutdown_msg_data *shutdown_msg;
-
-	struct icmsg_hdr *icmsghdrp;
-	struct icmsg_negotiate *negop = NULL;
-
-	vmbus_recvpacket(channel, shut_txf_buf,
-			 PAGE_SIZE, &recvlen, &requestid);
-
-	if (recvlen > 0) {
-		DPRINT_DBG(VMBUS, "shutdown packet: len=%d, requestid=%lld",
-			   recvlen, requestid);
-
-		icmsghdrp = (struct icmsg_hdr *)&shut_txf_buf[
-			sizeof(struct vmbuspipe_hdr)];
-
-		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-			prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf);
-		} else {
-			shutdown_msg =
-				(struct shutdown_msg_data *)&shut_txf_buf[
-					sizeof(struct vmbuspipe_hdr) +
-					sizeof(struct icmsg_hdr)];
-
-			switch (shutdown_msg->flags) {
-			case 0:
-			case 1:
-				icmsghdrp->status = HV_S_OK;
-				execute_shutdown = true;
-
-				DPRINT_INFO(VMBUS, "Shutdown request received -"
-					    " gracefull shutdown initiated");
-				break;
-			default:
-				icmsghdrp->status = HV_E_FAIL;
-				execute_shutdown = false;
-
-				DPRINT_INFO(VMBUS, "Shutdown request received -"
-					    " Invalid request");
-				break;
-			};
-		}
-
-		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
-			| ICMSGHDRFLAG_RESPONSE;
-
-		vmbus_sendpacket(channel, shut_txf_buf,
-				       recvlen, requestid,
-				       VmbusPacketTypeDataInBand, 0);
-	}
-
-	if (execute_shutdown == true)
-		orderly_poweroff(false);
-}
-
-/*
- * Set guest time to host UTC time.
- */
-static inline void do_adj_guesttime(u64 hosttime)
-{
-	s64 host_tns;
-	struct timespec host_ts;
-
-	host_tns = (hosttime - WLTIMEDELTA) * 100;
-	host_ts = ns_to_timespec(host_tns);
-
-	do_settimeofday(&host_ts);
-}
-
-/*
- * Synchronize time with host after reboot, restore, etc.
- *
- * ICTIMESYNCFLAG_SYNC flag bit indicates reboot, restore events of the VM.
- * After reboot the flag ICTIMESYNCFLAG_SYNC is included in the first time
- * message after the timesync channel is opened. Since the hv_utils module is
- * loaded after hv_vmbus, the first message is usually missed. The other
- * thing is, systime is automatically set to emulated hardware clock which may
- * not be UTC time or in the same time zone. So, to override these effects, we
- * use the first 50 time samples for initial system time setting.
- */
-static inline void adj_guesttime(u64 hosttime, u8 flags)
-{
-	static s32 scnt = 50;
-
-	if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
-		do_adj_guesttime(hosttime);
-		return;
-	}
-
-	if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
-		scnt--;
-		do_adj_guesttime(hosttime);
-	}
-}
-
-/*
- * Time Sync Channel message handler.
- */
-static void timesync_onchannelcallback(void *context)
-{
-	struct vmbus_channel *channel = context;
-	u32 recvlen;
-	u64 requestid;
-	struct icmsg_hdr *icmsghdrp;
-	struct ictimesync_data *timedatap;
-
-	vmbus_recvpacket(channel, time_txf_buf,
-			 PAGE_SIZE, &recvlen, &requestid);
-
-	if (recvlen > 0) {
-		DPRINT_DBG(VMBUS, "timesync packet: recvlen=%d, requestid=%lld",
-			recvlen, requestid);
-
-		icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
-				sizeof(struct vmbuspipe_hdr)];
-
-		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-			prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf);
-		} else {
-			timedatap = (struct ictimesync_data *)&time_txf_buf[
-				sizeof(struct vmbuspipe_hdr) +
-				sizeof(struct icmsg_hdr)];
-			adj_guesttime(timedatap->parenttime, timedatap->flags);
-		}
-
-		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
-			| ICMSGHDRFLAG_RESPONSE;
-
-		vmbus_sendpacket(channel, time_txf_buf,
-				recvlen, requestid,
-				VmbusPacketTypeDataInBand, 0);
-	}
-}
-
-/*
- * Heartbeat functionality.
- * Every two seconds, Hyper-V send us a heartbeat request message.
- * we respond to this message, and Hyper-V knows we are alive.
- */
-static void heartbeat_onchannelcallback(void *context)
-{
-	struct vmbus_channel *channel = context;
-	u32 recvlen;
-	u64 requestid;
-	struct icmsg_hdr *icmsghdrp;
-	struct heartbeat_msg_data *heartbeat_msg;
-
-	vmbus_recvpacket(channel, hbeat_txf_buf,
-			 PAGE_SIZE, &recvlen, &requestid);
-
-	if (recvlen > 0) {
-		DPRINT_DBG(VMBUS, "heartbeat packet: len=%d, requestid=%lld",
-			   recvlen, requestid);
-
-		icmsghdrp = (struct icmsg_hdr *)&hbeat_txf_buf[
-				sizeof(struct vmbuspipe_hdr)];
-
-		if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
-			prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf);
-		} else {
-			heartbeat_msg =
-				(struct heartbeat_msg_data *)&hbeat_txf_buf[
-					sizeof(struct vmbuspipe_hdr) +
-					sizeof(struct icmsg_hdr)];
-
-			DPRINT_DBG(VMBUS, "heartbeat seq = %lld",
-				   heartbeat_msg->seq_num);
-
-			heartbeat_msg->seq_num += 1;
-		}
-
-		icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
-			| ICMSGHDRFLAG_RESPONSE;
-
-		vmbus_sendpacket(channel, hbeat_txf_buf,
-				       recvlen, requestid,
-				       VmbusPacketTypeDataInBand, 0);
-	}
-}
-
-static const struct pci_device_id __initconst
-hv_utils_pci_table[] __maybe_unused = {
-	{ PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, hv_utils_pci_table);
-
-
-static const struct dmi_system_id __initconst
-hv_utils_dmi_table[] __maybe_unused  = {
-	{
-		.ident = "Hyper-V",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
-			DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
-		},
-	},
-	{ },
-};
-MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table);
-
-
-static int __init init_hyperv_utils(void)
-{
-	printk(KERN_INFO "Registering HyperV Utility Driver\n");
-
-	if (!dmi_check_system(hv_utils_dmi_table))
-		return -ENODEV;
-
-	shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-
-	if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) {
-		printk(KERN_INFO
-		       "Unable to allocate memory for receive buffer\n");
-		kfree(shut_txf_buf);
-		kfree(time_txf_buf);
-		kfree(hbeat_txf_buf);
-		return -ENOMEM;
-	}
-
-	hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
-		&shutdown_onchannelcallback;
-	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback;
-
-	hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
-		&timesync_onchannelcallback;
-	hv_cb_utils[HV_TIMESYNC_MSG].callback = &timesync_onchannelcallback;
-
-	hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
-		&heartbeat_onchannelcallback;
-	hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback;
-
-	return 0;
-}
-
-static void exit_hyperv_utils(void)
-{
-	printk(KERN_INFO "De-Registered HyperV Utility Driver\n");
-
-	hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback =
-		&chn_cb_negotiate;
-	hv_cb_utils[HV_SHUTDOWN_MSG].callback = &chn_cb_negotiate;
-
-	hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback =
-		&chn_cb_negotiate;
-	hv_cb_utils[HV_TIMESYNC_MSG].callback = &chn_cb_negotiate;
-
-	hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback =
-		&chn_cb_negotiate;
-	hv_cb_utils[HV_HEARTBEAT_MSG].callback = &chn_cb_negotiate;
-
-	kfree(shut_txf_buf);
-	kfree(time_txf_buf);
-	kfree(hbeat_txf_buf);
-}
-
-module_init(init_hyperv_utils);
-module_exit(exit_hyperv_utils);
-
-MODULE_DESCRIPTION("Hyper-V Utilities");
-MODULE_VERSION(HV_DRV_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/hv/logging.h b/drivers/staging/hv/logging.h
index 20d4d12..1799951 100644
--- a/drivers/staging/hv/logging.h
+++ b/drivers/staging/hv/logging.h
@@ -25,6 +25,9 @@
 #ifndef _LOGGING_H_
 #define _LOGGING_H_
 
+#define LOWORD(dw) ((unsigned short)(dw))
+#define HIWORD(dw) ((unsigned short)(((unsigned int) (dw) >> 16) & 0xFFFF))
+
 /* #include <linux/init.h> */
 /* #include <linux/module.h> */
 
diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c
index 0edbe74..20b15977 100644
--- a/drivers/staging/hv/netvsc.c
+++ b/drivers/staging/hv/netvsc.c
@@ -19,11 +19,13 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "netvsc.h"
 #include "rndis_filter.h"
@@ -86,15 +88,15 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
 	atomic_cmpxchg(&net_device->refcnt, 0, 2);
 
 	net_device->dev = device;
-	device->Extension = net_device;
+	device->ext = net_device;
 
 	return net_device;
 }
 
 static void free_net_device(struct netvsc_device *device)
 {
-	WARN_ON(atomic_read(&device->refcnt) == 0);
-	device->dev->Extension = NULL;
+	WARN_ON(atomic_read(&device->refcnt) != 0);
+	device->dev->ext = NULL;
 	kfree(device);
 }
 
@@ -104,7 +106,7 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
 
-	net_device = device->Extension;
+	net_device = device->ext;
 	if (net_device && atomic_read(&net_device->refcnt) > 1)
 		atomic_inc(&net_device->refcnt);
 	else
@@ -118,7 +120,7 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
 
-	net_device = device->Extension;
+	net_device = device->ext;
 	if (net_device && atomic_read(&net_device->refcnt))
 		atomic_inc(&net_device->refcnt);
 	else
@@ -131,8 +133,7 @@ static void put_net_device(struct hv_device *device)
 {
 	struct netvsc_device *net_device;
 
-	net_device = device->Extension;
-	/* ASSERT(netDevice); */
+	net_device = device->ext;
 
 	atomic_dec(&net_device->refcnt);
 }
@@ -142,7 +143,7 @@ static struct netvsc_device *release_outbound_net_device(
 {
 	struct netvsc_device *net_device;
 
-	net_device = device->Extension;
+	net_device = device->ext;
 	if (net_device == NULL)
 		return NULL;
 
@@ -158,7 +159,7 @@ static struct netvsc_device *release_inbound_net_device(
 {
 	struct netvsc_device *net_device;
 
-	net_device = device->Extension;
+	net_device = device->ext;
 	if (net_device == NULL)
 		return NULL;
 
@@ -166,7 +167,7 @@ static struct netvsc_device *release_inbound_net_device(
 	while (atomic_cmpxchg(&net_device->refcnt, 1, 0) != 1)
 		udelay(100);
 
-	device->Extension = NULL;
+	device->ext = NULL;
 	return net_device;
 }
 
@@ -184,21 +185,13 @@ int netvsc_initialize(struct hv_driver *drv)
 		   sizeof(struct nvsp_message),
 		   sizeof(struct vmtransfer_page_packet_header));
 
-	/* Make sure we are at least 2 pages since 1 page is used for control */
-	/* ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1)); */
-
 	drv->name = driver_name;
-	memcpy(&drv->deviceType, &netvsc_device_type, sizeof(struct hv_guid));
-
-	/* Make sure it is set by the caller */
-	/* FIXME: These probably should still be tested in some way */
-	/* ASSERT(driver->OnReceiveCallback); */
-	/* ASSERT(driver->OnLinkStatusChanged); */
+	memcpy(&drv->dev_type, &netvsc_device_type, sizeof(struct hv_guid));
 
 	/* Setup the dispatch table */
-	driver->base.OnDeviceAdd	= netvsc_device_add;
-	driver->base.OnDeviceRemove	= netvsc_device_remove;
-	driver->base.OnCleanup		= netvsc_cleanup;
+	driver->base.dev_add	= netvsc_device_add;
+	driver->base.dev_rm	= netvsc_device_remove;
+	driver->base.cleanup		= netvsc_cleanup;
 
 	driver->send			= netvsc_send;
 
@@ -218,22 +211,17 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 			   "device being destroyed?");
 		return -1;
 	}
-	/* ASSERT(netDevice->ReceiveBufferSize > 0); */
-	/* page-size grandularity */
-	/* ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE - 1)) == 0); */
 
 	net_device->recv_buf =
-		osd_page_alloc(net_device->recv_buf_size >> PAGE_SHIFT);
+		(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+				get_order(net_device->recv_buf_size));
 	if (!net_device->recv_buf) {
 		DPRINT_ERR(NETVSC,
 			   "unable to allocate receive buffer of size %d",
 			   net_device->recv_buf_size);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
-	/* page-aligned buffer */
-	/* ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE - 1)) == */
-	/* 	0); */
 
 	DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
 
@@ -248,10 +236,9 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC,
 			   "unable to establish receive buffer's gpadl");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	/* osd_waitevent_wait(ext->ChannelInitEvent); */
 
 	/* Notify the NetVsp of the gpadl handle */
 	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
@@ -267,18 +254,23 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 		send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
 
 	/* Send the gpadl notification request */
+	net_device->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, init_packet,
 			       sizeof(struct nvsp_message),
 			       (unsigned long)init_packet,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC,
 			   "unable to send receive buffer's gpadl to netvsp");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(net_device->channel_init_event);
+	wait_event_timeout(net_device->channel_init_wait,
+			net_device->wait_condition,
+			msecs_to_jiffies(1000));
+	BUG_ON(net_device->wait_condition == 0);
+
 
 	/* Check the response */
 	if (init_packet->msg.v1_msg.
@@ -288,12 +280,10 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 			   init_packet->msg.v1_msg.
 			   send_recv_buf_complete.status);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	/* Parse the response */
-	/* ASSERT(netDevice->ReceiveSectionCount == 0); */
-	/* ASSERT(netDevice->ReceiveSections == NULL); */
 
 	net_device->recv_section_cnt = init_packet->msg.
 		v1_msg.send_recv_buf_complete.num_sections;
@@ -302,7 +292,7 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 		* sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL);
 	if (net_device->recv_section == NULL) {
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	memcpy(net_device->recv_section,
@@ -326,15 +316,15 @@ static int netvsc_init_recv_buf(struct hv_device *device)
 	if (net_device->recv_section_cnt != 1 ||
 	    net_device->recv_section->offset != 0) {
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	goto Exit;
+	goto exit;
 
-Cleanup:
+cleanup:
 	netvsc_destroy_recv_buf(net_device);
 
-Exit:
+exit:
 	put_net_device(device);
 	return ret;
 }
@@ -353,22 +343,18 @@ static int netvsc_init_send_buf(struct hv_device *device)
 	}
 	if (net_device->send_buf_size <= 0) {
 		ret = -EINVAL;
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	/* page-size grandularity */
-	/* ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0); */
-
 	net_device->send_buf =
-		osd_page_alloc(net_device->send_buf_size >> PAGE_SHIFT);
+		(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
+				get_order(net_device->send_buf_size));
 	if (!net_device->send_buf) {
 		DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d",
 			   net_device->send_buf_size);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
-	/* page-aligned buffer */
-	/* ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE - 1)) == 0); */
 
 	DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
 
@@ -382,11 +368,9 @@ static int netvsc_init_send_buf(struct hv_device *device)
 				    &net_device->send_buf_gpadl_handle);
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	/* osd_waitevent_wait(ext->ChannelInitEvent); */
-
 	/* Notify the NetVsp of the gpadl handle */
 	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
 
@@ -401,18 +385,22 @@ static int netvsc_init_send_buf(struct hv_device *device)
 		NETVSC_SEND_BUFFER_ID;
 
 	/* Send the gpadl notification request */
+	net_device->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, init_packet,
 			       sizeof(struct nvsp_message),
 			       (unsigned long)init_packet,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC,
 			   "unable to send receive buffer's gpadl to netvsp");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(net_device->channel_init_event);
+	wait_event_timeout(net_device->channel_init_wait,
+			net_device->wait_condition,
+			msecs_to_jiffies(1000));
+	BUG_ON(net_device->wait_condition == 0);
 
 	/* Check the response */
 	if (init_packet->msg.v1_msg.
@@ -422,18 +410,18 @@ static int netvsc_init_send_buf(struct hv_device *device)
 			   init_packet->msg.v1_msg.
 			   send_send_buf_complete.status);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	net_device->send_section_size = init_packet->
 	msg.v1_msg.send_send_buf_complete.section_size;
 
-	goto Exit;
+	goto exit;
 
-Cleanup:
+cleanup:
 	netvsc_destroy_send_buf(net_device);
 
-Exit:
+exit:
 	put_net_device(device);
 	return ret;
 }
@@ -466,7 +454,7 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
 				       revoke_packet,
 				       sizeof(struct nvsp_message),
 				       (unsigned long)revoke_packet,
-				       VmbusPacketTypeDataInBand, 0);
+				       VM_PKT_DATA_INBAND, 0);
 		/*
 		 * If we failed here, we might as well return and
 		 * have a leak rather than continue and a bugchk
@@ -498,8 +486,8 @@ static int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
 		DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
 
 		/* Free up the receive buffer */
-		osd_page_free(net_device->recv_buf,
-			     net_device->recv_buf_size >> PAGE_SHIFT);
+		free_pages((unsigned long)net_device->recv_buf,
+			get_order(net_device->recv_buf_size));
 		net_device->recv_buf = NULL;
 	}
 
@@ -540,7 +528,7 @@ static int netvsc_destroy_send_buf(struct netvsc_device *net_device)
 				       revoke_packet,
 				       sizeof(struct nvsp_message),
 				       (unsigned long)revoke_packet,
-				       VmbusPacketTypeDataInBand, 0);
+				       VM_PKT_DATA_INBAND, 0);
 		/*
 		 * If we failed here, we might as well return and have a leak
 		 * rather than continue and a bugchk
@@ -574,8 +562,8 @@ static int netvsc_destroy_send_buf(struct netvsc_device *net_device)
 		DPRINT_INFO(NETVSC, "Freeing up send buffer...");
 
 		/* Free up the receive buffer */
-		osd_page_free(net_device->send_buf,
-			     net_device->send_buf_size >> PAGE_SHIFT);
+		free_pages((unsigned long)net_device->send_buf,
+				get_order(net_device->send_buf_size));
 		net_device->send_buf = NULL;
 	}
 
@@ -609,21 +597,26 @@ static int netvsc_connect_vsp(struct hv_device *device)
 	DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
 
 	/* Send the init request */
+	net_device->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, init_packet,
 			       sizeof(struct nvsp_message),
 			       (unsigned long)init_packet,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(net_device->channel_init_event);
+	wait_event_timeout(net_device->channel_init_wait,
+			net_device->wait_condition,
+			msecs_to_jiffies(1000));
+	if (net_device->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
 
-	/* Now, check the response */
-	/* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
 	DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
 		init_packet->msg.init_msg.init_complete.status,
 		init_packet->msg.init_msg.
@@ -635,7 +628,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
 			"unable to initialize with netvsp (status 0x%x)",
 			init_packet->msg.init_msg.init_complete.status);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	if (init_packet->msg.init_msg.init_complete.
@@ -645,7 +638,7 @@ static int netvsc_connect_vsp(struct hv_device *device)
 			   init_packet->msg.init_msg.
 			   init_complete.negotiated_protocol_ver);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 	DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
 
@@ -664,29 +657,22 @@ static int netvsc_connect_vsp(struct hv_device *device)
 
 	/* Send the init request */
 	ret = vmbus_sendpacket(device->channel, init_packet,
-			       sizeof(struct nvsp_message),
-			       (unsigned long)init_packet,
-			       VmbusPacketTypeDataInBand, 0);
+				sizeof(struct nvsp_message),
+				(unsigned long)init_packet,
+				VM_PKT_DATA_INBAND, 0);
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC,
 			   "unable to send NvspMessage1TypeSendNdisVersion");
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
-	/*
-	 * BUGBUG - We have to wait for the above msg since the
-	 * netvsp uses KMCL which acknowledges packet (completion
-	 * packet) since our Vmbus always set the
-	 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
-	 */
-	 /* osd_waitevent_wait(NetVscChannel->ChannelInitEvent); */
 
 	/* Post the big receive buffer to NetVSP */
 	ret = netvsc_init_recv_buf(device);
 	if (ret == 0)
 		ret = netvsc_init_send_buf(device);
 
-Cleanup:
+cleanup:
 	put_net_device(device);
 	return ret;
 }
@@ -708,12 +694,12 @@ static int netvsc_device_add(struct hv_device *device, void *additional_info)
 	struct netvsc_device *net_device;
 	struct hv_netvsc_packet *packet, *pos;
 	struct netvsc_driver *net_driver =
-				(struct netvsc_driver *)device->Driver;
+				(struct netvsc_driver *)device->drv;
 
 	net_device = alloc_net_device(device);
 	if (!net_device) {
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", net_device);
@@ -739,11 +725,7 @@ static int netvsc_device_add(struct hv_device *device, void *additional_info)
 		list_add_tail(&packet->list_ent,
 			      &net_device->recv_pkt_list);
 	}
-	net_device->channel_init_event = osd_waitevent_create();
-	if (!net_device->channel_init_event) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
+	init_waitqueue_head(&net_device->channel_init_wait);
 
 	/* Open the channel */
 	ret = vmbus_open(device->channel, net_driver->ring_buf_size,
@@ -753,7 +735,7 @@ static int netvsc_device_add(struct hv_device *device, void *additional_info)
 	if (ret != 0) {
 		DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	/* Channel is opened */
@@ -776,11 +758,9 @@ close:
 	/* Now, we can close the channel safely */
 	vmbus_close(device->channel);
 
-Cleanup:
+cleanup:
 
 	if (net_device) {
-		kfree(net_device->channel_init_event);
-
 		list_for_each_entry_safe(packet, pos,
 					 &net_device->recv_pkt_list,
 					 list_ent) {
@@ -806,7 +786,7 @@ static int netvsc_device_remove(struct hv_device *device)
 	struct hv_netvsc_packet *netvsc_packet, *pos;
 
 	DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...",
-		    device->Extension);
+		    device->ext);
 
 	/* Stop outbound traffic ie sends and receives completions */
 	net_device = release_outbound_net_device(device);
@@ -827,7 +807,7 @@ static int netvsc_device_remove(struct hv_device *device)
 	NetVscDisconnectFromVsp(net_device);
 
 	DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...",
-		    device->Extension);
+		    device->ext);
 
 	/* Stop inbound traffic ie receives and sends completions */
 	net_device = release_inbound_net_device(device);
@@ -845,7 +825,6 @@ static int netvsc_device_remove(struct hv_device *device)
 		kfree(netvsc_packet);
 	}
 
-	kfree(net_device->channel_init_event);
 	free_net_device(net_device);
 	return 0;
 }
@@ -872,7 +851,7 @@ static void netvsc_send_completion(struct hv_device *device,
 	}
 
 	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
-			(packet->DataOffset8 << 3));
+			(packet->offset8 << 3));
 
 	DPRINT_DBG(NETVSC, "send completion packet - type %d",
 		   nvsp_packet->hdr.msg_type);
@@ -885,13 +864,13 @@ static void netvsc_send_completion(struct hv_device *device,
 		/* Copy the response back */
 		memcpy(&net_device->channel_init_pkt, nvsp_packet,
 		       sizeof(struct nvsp_message));
-		osd_waitevent_set(net_device->channel_init_event);
+		net_device->wait_condition = 1;
+		wake_up(&net_device->channel_init_wait);
 	} else if (nvsp_packet->hdr.msg_type ==
 		   NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
 		/* Get the send context */
 		nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
-			packet->TransactionId;
-		/* ASSERT(nvscPacket); */
+			packet->trans_id;
 
 		/* Notify the layer above us */
 		nvsc_packet->completion.send.send_completion(
@@ -946,7 +925,7 @@ static int netvsc_send(struct hv_device *device,
 		ret = vmbus_sendpacket(device->channel, &sendMessage,
 				       sizeof(struct nvsp_message),
 				       (unsigned long)packet,
-				       VmbusPacketTypeDataInBand,
+				       VM_PKT_DATA_INBAND,
 				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 
 	}
@@ -987,15 +966,15 @@ static void netvsc_receive(struct hv_device *device,
 	 * All inbound packets other than send completion should be xfer page
 	 * packet
 	 */
-	if (packet->Type != VmbusPacketTypeDataUsingTransferPages) {
+	if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) {
 		DPRINT_ERR(NETVSC, "Unknown packet type received - %d",
-			   packet->Type);
+			   packet->type);
 		put_net_device(device);
 		return;
 	}
 
 	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
-			(packet->DataOffset8 << 3));
+			(packet->offset8 << 3));
 
 	/* Make sure this is a valid nvsp packet */
 	if (nvsp_packet->hdr.msg_type !=
@@ -1011,16 +990,16 @@ static void netvsc_receive(struct hv_device *device,
 
 	vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet;
 
-	if (vmxferpage_packet->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID) {
+	if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) {
 		DPRINT_ERR(NETVSC, "Invalid xfer page set id - "
 			   "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID,
-			   vmxferpage_packet->TransferPageSetId);
+			   vmxferpage_packet->xfer_pageset_id);
 		put_net_device(device);
 		return;
 	}
 
 	DPRINT_DBG(NETVSC, "xfer page - range count %d",
-		   vmxferpage_packet->RangeCount);
+		   vmxferpage_packet->range_cnt);
 
 	/*
 	 * Grab free packets (range count + 1) to represent this xfer
@@ -1031,7 +1010,7 @@ static void netvsc_receive(struct hv_device *device,
 	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
 	while (!list_empty(&net_device->recv_pkt_list)) {
 		list_move_tail(net_device->recv_pkt_list.next, &listHead);
-		if (++count == vmxferpage_packet->RangeCount + 1)
+		if (++count == vmxferpage_packet->range_cnt + 1)
 			break;
 	}
 	spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
@@ -1044,7 +1023,7 @@ static void netvsc_receive(struct hv_device *device,
 	if (count < 2) {
 		DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. "
 			   "Dropping this xfer page packet completely!",
-			   count, vmxferpage_packet->RangeCount + 1);
+			   count, vmxferpage_packet->range_cnt + 1);
 
 		/* Return it to the freelist */
 		spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
@@ -1056,7 +1035,7 @@ static void netvsc_receive(struct hv_device *device,
 				       flags);
 
 		netvsc_send_recv_completion(device,
-					    vmxferpage_packet->d.TransactionId);
+					    vmxferpage_packet->d.trans_id);
 
 		put_net_device(device);
 		return;
@@ -1068,12 +1047,10 @@ static void netvsc_receive(struct hv_device *device,
 
 	/* This is how much we can satisfy */
 	xferpage_packet->count = count - 1;
-	/* ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= */
-	/* 	vmxferpagePacket->RangeCount); */
 
-	if (xferpage_packet->count != vmxferpage_packet->RangeCount) {
+	if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
 		DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer "
-			    "page...got %d", vmxferpage_packet->RangeCount,
+			    "page...got %d", vmxferpage_packet->range_cnt,
 			    xferpage_packet->count);
 	}
 
@@ -1091,78 +1068,71 @@ static void netvsc_receive(struct hv_device *device,
 		netvsc_packet->device = device;
 		/* Save this so that we can send it back */
 		netvsc_packet->completion.recv.recv_completion_tid =
-					vmxferpage_packet->d.TransactionId;
+					vmxferpage_packet->d.trans_id;
 
 		netvsc_packet->total_data_buflen =
-					vmxferpage_packet->Ranges[i].ByteCount;
+					vmxferpage_packet->ranges[i].byte_count;
 		netvsc_packet->page_buf_cnt = 1;
 
-		/* ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + */
-		/* 	vmxferpagePacket->Ranges[i].ByteCount < */
-		/* 	netDevice->ReceiveBufferSize); */
-
-		netvsc_packet->page_buf[0].Length =
-					vmxferpage_packet->Ranges[i].ByteCount;
+		netvsc_packet->page_buf[0].len =
+					vmxferpage_packet->ranges[i].byte_count;
 
 		start = virt_to_phys((void *)((unsigned long)net_device->
-		recv_buf + vmxferpage_packet->Ranges[i].ByteOffset));
+		recv_buf + vmxferpage_packet->ranges[i].byte_offset));
 
-		netvsc_packet->page_buf[0].Pfn = start >> PAGE_SHIFT;
+		netvsc_packet->page_buf[0].pfn = start >> PAGE_SHIFT;
 		end_virtual = (unsigned long)net_device->recv_buf
-		    + vmxferpage_packet->Ranges[i].ByteOffset
-		    + vmxferpage_packet->Ranges[i].ByteCount - 1;
+		    + vmxferpage_packet->ranges[i].byte_offset
+		    + vmxferpage_packet->ranges[i].byte_count - 1;
 		end = virt_to_phys((void *)end_virtual);
 
 		/* Calculate the page relative offset */
-		netvsc_packet->page_buf[0].Offset =
-			vmxferpage_packet->Ranges[i].ByteOffset &
+		netvsc_packet->page_buf[0].offset =
+			vmxferpage_packet->ranges[i].byte_offset &
 			(PAGE_SIZE - 1);
 		if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
 			/* Handle frame across multiple pages: */
-			netvsc_packet->page_buf[0].Length =
-				(netvsc_packet->page_buf[0].Pfn <<
+			netvsc_packet->page_buf[0].len =
+				(netvsc_packet->page_buf[0].pfn <<
 				 PAGE_SHIFT)
 				+ PAGE_SIZE - start;
 			bytes_remain = netvsc_packet->total_data_buflen -
-					netvsc_packet->page_buf[0].Length;
+					netvsc_packet->page_buf[0].len;
 			for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
-				netvsc_packet->page_buf[j].Offset = 0;
+				netvsc_packet->page_buf[j].offset = 0;
 				if (bytes_remain <= PAGE_SIZE) {
-					netvsc_packet->page_buf[j].Length =
+					netvsc_packet->page_buf[j].len =
 						bytes_remain;
 					bytes_remain = 0;
 				} else {
-					netvsc_packet->page_buf[j].Length =
+					netvsc_packet->page_buf[j].len =
 						PAGE_SIZE;
 					bytes_remain -= PAGE_SIZE;
 				}
-				netvsc_packet->page_buf[j].Pfn =
+				netvsc_packet->page_buf[j].pfn =
 				    virt_to_phys((void *)(end_virtual -
 						bytes_remain)) >> PAGE_SHIFT;
 				netvsc_packet->page_buf_cnt++;
 				if (bytes_remain == 0)
 					break;
 			}
-			/* ASSERT(bytesRemain == 0); */
 		}
 		DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => "
 			   "(pfn %llx, offset %u, len %u)", i,
-			   vmxferpage_packet->Ranges[i].ByteOffset,
-			   vmxferpage_packet->Ranges[i].ByteCount,
-			   netvsc_packet->page_buf[0].Pfn,
-			   netvsc_packet->page_buf[0].Offset,
-			   netvsc_packet->page_buf[0].Length);
+			   vmxferpage_packet->ranges[i].byte_offset,
+			   vmxferpage_packet->ranges[i].byte_count,
+			   netvsc_packet->page_buf[0].pfn,
+			   netvsc_packet->page_buf[0].offset,
+			   netvsc_packet->page_buf[0].len);
 
 		/* Pass it to the upper layer */
-		((struct netvsc_driver *)device->Driver)->
+		((struct netvsc_driver *)device->drv)->
 			recv_cb(device, netvsc_packet);
 
 		netvsc_receive_completion(netvsc_packet->
 				completion.recv.recv_completion_ctx);
 	}
 
-	/* ASSERT(list_empty(&listHead)); */
-
 	put_net_device(device);
 }
 
@@ -1187,7 +1157,7 @@ retry_send_cmplt:
 	/* Send the completion */
 	ret = vmbus_sendpacket(device->channel, &recvcompMessage,
 			       sizeof(struct nvsp_message), transaction_id,
-			       VmbusPacketTypeCompletion, 0);
+			       VM_PKT_COMP, 0);
 	if (ret == 0) {
 		/* success */
 		/* no-op */
@@ -1221,8 +1191,6 @@ static void netvsc_receive_completion(void *context)
 	bool fsend_receive_comp = false;
 	unsigned long flags;
 
-	/* ASSERT(packet->XferPagePacket); */
-
 	/*
 	 * Even though it seems logical to do a GetOutboundNetDevice() here to
 	 * send out receive completion, we are using GetInboundNetDevice()
@@ -1238,7 +1206,6 @@ static void netvsc_receive_completion(void *context)
 	/* Overloading use of the lock. */
 	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
 
-	/* ASSERT(packet->XferPagePacket->Count > 0); */
 	packet->xfer_page_pkt->count--;
 
 	/*
@@ -1276,8 +1243,6 @@ static void netvsc_channel_cb(void *context)
 	unsigned char *buffer;
 	int bufferlen = NETVSC_PACKET_SIZE;
 
-	/* ASSERT(device); */
-
 	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
 			 GFP_ATOMIC);
 	if (!packet)
@@ -1300,12 +1265,12 @@ static void netvsc_channel_cb(void *context)
 					   bytes_recvd, request_id);
 
 				desc = (struct vmpacket_descriptor *)buffer;
-				switch (desc->Type) {
-				case VmbusPacketTypeCompletion:
+				switch (desc->type) {
+				case VM_PKT_COMP:
 					netvsc_send_completion(device, desc);
 					break;
 
-				case VmbusPacketTypeDataUsingTransferPages:
+				case VM_PKT_DATA_USING_XFER_PAGES:
 					netvsc_receive(device, desc);
 					break;
 
@@ -1313,7 +1278,7 @@ static void netvsc_channel_cb(void *context)
 					DPRINT_ERR(NETVSC,
 						   "unhandled packet type %d, "
 						   "tid %llx len %d\n",
-						   desc->Type, request_id,
+						   desc->type, request_id,
 						   bytes_recvd);
 					break;
 				}
diff --git a/drivers/staging/hv/netvsc.h b/drivers/staging/hv/netvsc.h
index 932a77c..45d24b9 100644
--- a/drivers/staging/hv/netvsc.h
+++ b/drivers/staging/hv/netvsc.h
@@ -92,7 +92,7 @@ struct nvsp_message_header {
 struct nvsp_message_init {
 	u32 min_protocol_ver;
 	u32 max_protocol_ver;
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is used by the VSP to complete the initialization of the
@@ -103,12 +103,12 @@ struct nvsp_message_init_complete {
 	u32 negotiated_protocol_ver;
 	u32 max_mdl_chain_len;
 	u32 status;
-} __attribute__((packed));
+} __packed;
 
 union nvsp_message_init_uber {
 	struct nvsp_message_init init;
 	struct nvsp_message_init_complete init_complete;
-} __attribute__((packed));
+} __packed;
 
 /* Version 1 Messages */
 
@@ -119,7 +119,7 @@ union nvsp_message_init_uber {
 struct nvsp_1_message_send_ndis_version {
 	u32 ndis_major_ver;
 	u32 ndis_minor_ver;
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is used by the VSC to send a receive buffer to the VSP. The VSP
@@ -128,14 +128,14 @@ struct nvsp_1_message_send_ndis_version {
 struct nvsp_1_message_send_receive_buffer {
 	u32 gpadl_handle;
 	u16 id;
-} __attribute__((packed));
+} __packed;
 
 struct nvsp_1_receive_buffer_section {
 	u32 offset;
 	u32 sub_alloc_size;
 	u32 num_sub_allocs;
 	u32 end_offset;
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is used by the VSP to acknowledge a receive buffer send by the
@@ -166,7 +166,7 @@ struct nvsp_1_message_send_receive_buffer_complete {
 	 */
 
 	struct nvsp_1_receive_buffer_section sections[1];
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is sent by the VSC to revoke the receive buffer.  After the VSP
@@ -184,7 +184,7 @@ struct nvsp_1_message_revoke_receive_buffer {
 struct nvsp_1_message_send_send_buffer {
 	u32 gpadl_handle;
 	u16 id;
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is used by the VSP to acknowledge a send buffer sent by the
@@ -201,7 +201,7 @@ struct nvsp_1_message_send_send_buffer_complete {
 	 * decreases.
 	 */
 	u32 section_size;
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is sent by the VSC to revoke the send buffer.  After the VSP
@@ -231,7 +231,7 @@ struct nvsp_1_message_send_rndis_packet {
 	 */
 	u32 send_buf_section_index;
 	u32 send_buf_section_size;
-} __attribute__((packed));
+} __packed;
 
 /*
  * This message is used by both the VSP and the VSC to complete a RNDIS message
@@ -257,18 +257,18 @@ union nvsp_1_message_uber {
 	struct nvsp_1_message_send_rndis_packet send_rndis_pkt;
 	struct nvsp_1_message_send_rndis_packet_complete
 						send_rndis_pkt_complete;
-} __attribute__((packed));
+} __packed;
 
 union nvsp_all_messages {
 	union nvsp_message_init_uber init_msg;
 	union nvsp_1_message_uber v1_msg;
-} __attribute__((packed));
+} __packed;
 
 /* ALL Messages */
 struct nvsp_message {
 	struct nvsp_message_header hdr;
 	union nvsp_all_messages msg;
-} __attribute__((packed));
+} __packed;
 
 
 
@@ -318,7 +318,8 @@ struct netvsc_device {
 	struct nvsp_1_receive_buffer_section *recv_section;
 
 	/* Used for NetVSP initialization protocol */
-	struct osd_waitevent *channel_init_event;
+	int wait_condition;
+	wait_queue_head_t channel_init_wait;
 	struct nvsp_message channel_init_pkt;
 
 	struct nvsp_message revoke_packet;
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index b41c964..2d40f5f 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -36,7 +36,7 @@
 #include <net/route.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "version_info.h"
 #include "vmbus.h"
@@ -44,16 +44,10 @@
 
 struct net_device_context {
 	/* point back to our device context */
-	struct vm_device *device_ctx;
+	struct hv_device *device_ctx;
 	unsigned long avail;
 };
 
-struct netvsc_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* Which is a bug FIXME! */
-	struct driver_context drv_ctx;
-	struct netvsc_driver drv_obj;
-};
 
 #define PACKET_PAGES_LOWATER  8
 /* Need this many pages to handle worst case fragmented packet */
@@ -64,7 +58,7 @@ module_param(ring_size, int, S_IRUGO);
 MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
 
 /* The one and only one */
-static struct netvsc_driver_context g_netvsc_drv;
+static struct  netvsc_driver g_netvsc_drv;
 
 /* no-op so the netdev core doesn't return -EINVAL when modifying the the
  * multicast address list in SIOCADDMULTI. hv is setup to get all multicast
@@ -76,7 +70,7 @@ static void netvsc_set_multicast_list(struct net_device *net)
 static int netvsc_open(struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
+	struct hv_device *device_obj = net_device_ctx->device_ctx;
 	int ret = 0;
 
 	if (netif_carrier_ok(net)) {
@@ -99,7 +93,7 @@ static int netvsc_open(struct net_device *net)
 static int netvsc_close(struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
+	struct hv_device *device_obj = net_device_ctx->device_ctx;
 	int ret;
 
 	netif_stop_queue(net);
@@ -126,7 +120,8 @@ static void netvsc_xmit_completion(void *context)
 
 		dev_kfree_skb_any(skb);
 
-		if ((net_device_ctx->avail += num_pages) >= PACKET_PAGES_HIWATER)
+		net_device_ctx->avail += num_pages;
+		if (net_device_ctx->avail >= PACKET_PAGES_HIWATER)
  			netif_wake_queue(net);
 	}
 }
@@ -134,11 +129,9 @@ static void netvsc_xmit_completion(void *context)
 static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	struct net_device_context *net_device_ctx = netdev_priv(net);
-	struct driver_context *driver_ctx =
-	    driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
+	struct hv_driver *drv =
+	    drv_to_hv_drv(net_device_ctx->device_ctx->device.driver);
+	struct netvsc_driver *net_drv_obj = drv->priv;
 	struct hv_netvsc_packet *packet;
 	int ret;
 	unsigned int i, num_pages;
@@ -178,18 +171,18 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 	packet->total_data_buflen	= skb->len;
 
 	/* Start filling in the page buffers starting after RNDIS buffer. */
-	packet->page_buf[1].Pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
-	packet->page_buf[1].Offset
+	packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT;
+	packet->page_buf[1].offset
 		= (unsigned long)skb->data & (PAGE_SIZE - 1);
-	packet->page_buf[1].Length = skb_headlen(skb);
+	packet->page_buf[1].len = skb_headlen(skb);
 
 	/* Additional fragments are after SKB data */
 	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 		skb_frag_t *f = &skb_shinfo(skb)->frags[i];
 
-		packet->page_buf[i+2].Pfn = page_to_pfn(f->page);
-		packet->page_buf[i+2].Offset = f->page_offset;
-		packet->page_buf[i+2].Length = f->size;
+		packet->page_buf[i+2].pfn = page_to_pfn(f->page);
+		packet->page_buf[i+2].offset = f->page_offset;
+		packet->page_buf[i+2].len = f->size;
 	}
 
 	/* Set the completion routine */
@@ -197,7 +190,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 	packet->completion.send.send_completion_ctx = packet;
 	packet->completion.send.send_completion_tid = (unsigned long)skb;
 
-	ret = net_drv_obj->send(&net_device_ctx->device_ctx->device_obj,
+	ret = net_drv_obj->send(net_device_ctx->device_ctx,
 				  packet);
 	if (ret == 0) {
 		net->stats.tx_bytes += skb->len;
@@ -207,7 +200,8 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 			   net->stats.tx_packets,
 			   net->stats.tx_bytes);
 
-		if ((net_device_ctx->avail -= num_pages) < PACKET_PAGES_LOWATER)
+		net_device_ctx->avail -= num_pages;
+		if (net_device_ctx->avail < PACKET_PAGES_LOWATER)
 			netif_stop_queue(net);
 	} else {
 		/* we are shutting down or bus overloaded, just drop packet */
@@ -224,8 +218,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 static void netvsc_linkstatus_callback(struct hv_device *device_obj,
 				       unsigned int status)
 {
-	struct vm_device *device_ctx = to_vm_device(device_obj);
-	struct net_device *net = dev_get_drvdata(&device_ctx->device);
+	struct net_device *net = dev_get_drvdata(&device_obj->device);
 
 	if (!net) {
 		DPRINT_ERR(NETVSC_DRV, "got link status but net device "
@@ -250,8 +243,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
 static int netvsc_recv_callback(struct hv_device *device_obj,
 				struct hv_netvsc_packet *packet)
 {
-	struct vm_device *device_ctx = to_vm_device(device_obj);
-	struct net_device *net = dev_get_drvdata(&device_ctx->device);
+	struct net_device *net = dev_get_drvdata(&device_obj->device);
 	struct sk_buff *skb;
 	void *data;
 	int i;
@@ -278,16 +270,16 @@ static int netvsc_recv_callback(struct hv_device *device_obj,
 	 * hv_netvsc_packet cannot be deallocated
 	 */
 	for (i = 0; i < packet->page_buf_cnt; i++) {
-		data = kmap_atomic(pfn_to_page(packet->page_buf[i].Pfn),
+		data = kmap_atomic(pfn_to_page(packet->page_buf[i].pfn),
 					       KM_IRQ1);
 		data = (void *)(unsigned long)data +
-				packet->page_buf[i].Offset;
+				packet->page_buf[i].offset;
 
-		memcpy(skb_put(skb, packet->page_buf[i].Length), data,
-		       packet->page_buf[i].Length);
+		memcpy(skb_put(skb, packet->page_buf[i].len), data,
+		       packet->page_buf[i].len);
 
 		kunmap_atomic((void *)((unsigned long)data -
-				       packet->page_buf[i].Offset), KM_IRQ1);
+				       packet->page_buf[i].offset), KM_IRQ1);
 	}
 
 	local_irq_restore(flags);
@@ -338,19 +330,16 @@ static const struct net_device_ops device_ops = {
 
 static int netvsc_probe(struct device *device)
 {
-	struct driver_context *driver_ctx =
-		driver_to_driver_context(device->driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
+	struct hv_driver *drv =
+		drv_to_hv_drv(device->driver);
+	struct netvsc_driver *net_drv_obj = drv->priv;
+	struct hv_device *device_obj = device_to_hv_device(device);
 	struct net_device *net = NULL;
 	struct net_device_context *net_device_ctx;
 	struct netvsc_device_info device_info;
 	int ret;
 
-	if (!net_drv_obj->base.OnDeviceAdd)
+	if (!net_drv_obj->base.dev_add)
 		return -1;
 
 	net = alloc_etherdev(sizeof(struct net_device_context));
@@ -361,12 +350,12 @@ static int netvsc_probe(struct device *device)
 	netif_carrier_off(net);
 
 	net_device_ctx = netdev_priv(net);
-	net_device_ctx->device_ctx = device_ctx;
+	net_device_ctx->device_ctx = device_obj;
 	net_device_ctx->avail = ring_size;
 	dev_set_drvdata(device, net);
 
 	/* Notify the netvsc driver of the new device */
-	ret = net_drv_obj->base.OnDeviceAdd(device_obj, &device_info);
+	ret = net_drv_obj->base.dev_add(device_obj, &device_info);
 	if (ret != 0) {
 		free_netdev(net);
 		dev_set_drvdata(device, NULL);
@@ -401,7 +390,7 @@ static int netvsc_probe(struct device *device)
 	ret = register_netdev(net);
 	if (ret != 0) {
 		/* Remove the device and release the resource */
-		net_drv_obj->base.OnDeviceRemove(device_obj);
+		net_drv_obj->base.dev_rm(device_obj);
 		free_netdev(net);
 	}
 
@@ -410,14 +399,11 @@ static int netvsc_probe(struct device *device)
 
 static int netvsc_remove(struct device *device)
 {
-	struct driver_context *driver_ctx =
-		driver_to_driver_context(device->driver);
-	struct netvsc_driver_context *net_drv_ctx =
-		(struct netvsc_driver_context *)driver_ctx;
-	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct net_device *net = dev_get_drvdata(&device_ctx->device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
+	struct hv_driver *drv =
+		drv_to_hv_drv(device->driver);
+	struct netvsc_driver *net_drv_obj = drv->priv;
+	struct hv_device *device_obj = device_to_hv_device(device);
+	struct net_device *net = dev_get_drvdata(&device_obj->device);
 	int ret;
 
 	if (net == NULL) {
@@ -425,7 +411,7 @@ static int netvsc_remove(struct device *device)
 		return 0;
 	}
 
-	if (!net_drv_obj->base.OnDeviceRemove)
+	if (!net_drv_obj->base.dev_rm)
 		return -1;
 
 	/* Stop outbound asap */
@@ -438,7 +424,7 @@ static int netvsc_remove(struct device *device)
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = net_drv_obj->base.OnDeviceRemove(device_obj);
+	ret = net_drv_obj->base.dev_rm(device_obj);
 	if (ret != 0) {
 		/* TODO: */
 		DPRINT_ERR(NETVSC, "unable to remove vsc device (ret %d)", ret);
@@ -459,8 +445,8 @@ static int netvsc_drv_exit_cb(struct device *dev, void *data)
 
 static void netvsc_drv_exit(void)
 {
-	struct netvsc_driver *netvsc_drv_obj = &g_netvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_netvsc_drv.drv_ctx;
+	struct netvsc_driver *netvsc_drv_obj = &g_netvsc_drv;
+	struct hv_driver *drv = &g_netvsc_drv.base;
 	struct device *current_dev;
 	int ret;
 
@@ -468,7 +454,7 @@ static void netvsc_drv_exit(void)
 		current_dev = NULL;
 
 		/* Get the device */
-		ret = driver_for_each_device(&drv_ctx->driver, NULL,
+		ret = driver_for_each_device(&drv->driver, NULL,
 					     &current_dev, netvsc_drv_exit_cb);
 		if (ret)
 			DPRINT_WARN(NETVSC_DRV,
@@ -484,36 +470,35 @@ static void netvsc_drv_exit(void)
 		device_unregister(current_dev);
 	}
 
-	if (netvsc_drv_obj->base.OnCleanup)
-		netvsc_drv_obj->base.OnCleanup(&netvsc_drv_obj->base);
+	if (netvsc_drv_obj->base.cleanup)
+		netvsc_drv_obj->base.cleanup(&netvsc_drv_obj->base);
 
-	vmbus_child_driver_unregister(drv_ctx);
+	vmbus_child_driver_unregister(&drv->driver);
 
 	return;
 }
 
 static int netvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 {
-	struct netvsc_driver *net_drv_obj = &g_netvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_netvsc_drv.drv_ctx;
+	struct netvsc_driver *net_drv_obj = &g_netvsc_drv;
+	struct hv_driver *drv = &g_netvsc_drv.base;
 	int ret;
 
 	net_drv_obj->ring_buf_size = ring_size * PAGE_SIZE;
 	net_drv_obj->recv_cb = netvsc_recv_callback;
 	net_drv_obj->link_status_change = netvsc_linkstatus_callback;
+	drv->priv = net_drv_obj;
 
 	/* Callback to client driver to complete the initialization */
 	drv_init(&net_drv_obj->base);
 
-	drv_ctx->driver.name = net_drv_obj->base.name;
-	memcpy(&drv_ctx->class_id, &net_drv_obj->base.deviceType,
-	       sizeof(struct hv_guid));
+	drv->driver.name = net_drv_obj->base.name;
 
-	drv_ctx->probe = netvsc_probe;
-	drv_ctx->remove = netvsc_remove;
+	drv->driver.probe = netvsc_probe;
+	drv->driver.remove = netvsc_remove;
 
 	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(drv_ctx);
+	ret = vmbus_child_driver_register(&drv->driver);
 
 	return ret;
 }
diff --git a/drivers/staging/hv/osd.c b/drivers/staging/hv/osd.c
deleted file mode 100644
index b5a3940..0000000
--- a/drivers/staging/hv/osd.c
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/vmalloc.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include "osd.h"
-
-void *osd_virtual_alloc_exec(unsigned int size)
-{
-#ifdef __x86_64__
-	return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL_EXEC);
-#else
-	return __vmalloc(size, GFP_KERNEL,
-			 __pgprot(__PAGE_KERNEL & (~_PAGE_NX)));
-#endif
-}
-
-/**
- * osd_page_alloc() - Allocate pages
- * @count:      Total number of Kernel pages you want to allocate
- *
- * Tries to allocate @count number of consecutive free kernel pages.
- * And if successful, it will set the pages to 0 before returning.
- * If successfull it will return pointer to the @count pages.
- * Mainly used by Hyper-V drivers.
- */
-void *osd_page_alloc(unsigned int count)
-{
-	void *p;
-
-	p = (void *)__get_free_pages(GFP_KERNEL, get_order(count * PAGE_SIZE));
-	if (p)
-		memset(p, 0, count * PAGE_SIZE);
-	return p;
-
-	/* struct page* page = alloc_page(GFP_KERNEL|__GFP_ZERO); */
-	/* void *p; */
-
-	/* BUGBUG: We need to use kmap in case we are in HIMEM region */
-	/* p = page_address(page); */
-	/* if (p) memset(p, 0, PAGE_SIZE); */
-	/* return p; */
-}
-EXPORT_SYMBOL_GPL(osd_page_alloc);
-
-/**
- * osd_page_free() - Free pages
- * @page:       Pointer to the first page to be freed
- * @count:      Total number of Kernel pages you free
- *
- * Frees the pages allocated by osd_page_alloc()
- * Mainly used by Hyper-V drivers.
- */
-void osd_page_free(void *page, unsigned int count)
-{
-	free_pages((unsigned long)page, get_order(count * PAGE_SIZE));
-	/*struct page* p = virt_to_page(page);
-	__free_page(p);*/
-}
-EXPORT_SYMBOL_GPL(osd_page_free);
-
-/**
- * osd_waitevent_create() - Create the event queue
- *
- * Allocates memory for a &struct osd_waitevent. And then calls
- * init_waitqueue_head to set up the wait queue for the event.
- * This structure is usually part of a another structure that contains
- * the actual Hyper-V device driver structure.
- *
- * Returns pointer to &struct osd_waitevent
- * Mainly used by Hyper-V drivers.
- */
-struct osd_waitevent *osd_waitevent_create(void)
-{
-	struct osd_waitevent *wait = kmalloc(sizeof(struct osd_waitevent),
-					     GFP_KERNEL);
-	if (!wait)
-		return NULL;
-
-	wait->condition = 0;
-	init_waitqueue_head(&wait->event);
-	return wait;
-}
-EXPORT_SYMBOL_GPL(osd_waitevent_create);
-
-
-/**
- * osd_waitevent_set() - Wake up the process
- * @wait_event: Structure to event to be woken up
- *
- * @wait_event is of type &struct osd_waitevent
- *
- * Wake up the sleeping process so it can do some work.
- * And set condition indicator in &struct osd_waitevent to indicate
- * the process is in a woken state.
- *
- * Only used by Network and Storage Hyper-V drivers.
- */
-void osd_waitevent_set(struct osd_waitevent *wait_event)
-{
-	wait_event->condition = 1;
-	wake_up_interruptible(&wait_event->event);
-}
-EXPORT_SYMBOL_GPL(osd_waitevent_set);
-
-/**
- * osd_waitevent_wait() - Wait for event till condition is true
- * @wait_event: Structure to event to be put to sleep
- *
- * @wait_event is of type &struct osd_waitevent
- *
- * Set up the process to sleep until waitEvent->condition get true.
- * And set condition indicator in &struct osd_waitevent to indicate
- * the process is in a sleeping state.
- *
- * Returns the status of 'wait_event_interruptible()' system call
- *
- * Mainly used by Hyper-V drivers.
- */
-int osd_waitevent_wait(struct osd_waitevent *wait_event)
-{
-	int ret = 0;
-
-	ret = wait_event_interruptible(wait_event->event,
-				       wait_event->condition);
-	wait_event->condition = 0;
-	return ret;
-}
-EXPORT_SYMBOL_GPL(osd_waitevent_wait);
-
-/**
- * osd_waitevent_waitex() - Wait for event or timeout for process wakeup
- * @wait_event: Structure to event to be put to sleep
- * @timeout_in_ms:       Total number of Milliseconds to wait before waking up
- *
- * @wait_event is of type &struct osd_waitevent
- * Set up the process to sleep until @waitEvent->condition get true or
- * @timeout_in_ms (Time out in Milliseconds) has been reached.
- * And set condition indicator in &struct osd_waitevent to indicate
- * the process is in a sleeping state.
- *
- * Returns the status of 'wait_event_interruptible_timeout()' system call
- *
- * Mainly used by Hyper-V drivers.
- */
-int osd_waitevent_waitex(struct osd_waitevent *wait_event, u32 timeout_in_ms)
-{
-	int ret = 0;
-
-	ret = wait_event_interruptible_timeout(wait_event->event,
-					       wait_event->condition,
-					       msecs_to_jiffies(timeout_in_ms));
-	wait_event->condition = 0;
-	return ret;
-}
-EXPORT_SYMBOL_GPL(osd_waitevent_waitex);
diff --git a/drivers/staging/hv/osd.h b/drivers/staging/hv/osd.h
deleted file mode 100644
index 870ef07..0000000
--- a/drivers/staging/hv/osd.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *
- * Copyright (c) 2009, Microsoft Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- * Authors:
- *   Haiyang Zhang <haiyangz@microsoft.com>
- *   Hank Janssen  <hjanssen@microsoft.com>
- *
- */
-
-
-#ifndef _OSD_H_
-#define _OSD_H_
-
-#include <linux/workqueue.h>
-
-/* Defines */
-#define ALIGN_UP(value, align)	(((value) & (align-1)) ?		\
-				 (((value) + (align-1)) & ~(align-1)) :	\
-				 (value))
-#define ALIGN_DOWN(value, align)	((value) & ~(align-1))
-#define NUM_PAGES_SPANNED(addr, len)	((ALIGN_UP(addr+len, PAGE_SIZE) - \
-					 ALIGN_DOWN(addr, PAGE_SIZE)) >>  \
-					 PAGE_SHIFT)
-
-#define LOWORD(dw)	((unsigned short)(dw))
-#define HIWORD(dw)	((unsigned short)(((unsigned int) (dw) >> 16) & 0xFFFF))
-
-struct hv_guid {
-	unsigned char data[16];
-};
-
-struct osd_waitevent {
-	int condition;
-	wait_queue_head_t event;
-};
-
-/* Osd routines */
-
-extern void *osd_virtual_alloc_exec(unsigned int size);
-
-extern void *osd_page_alloc(unsigned int count);
-extern void osd_page_free(void *page, unsigned int count);
-
-extern struct osd_waitevent *osd_waitevent_create(void);
-extern void osd_waitevent_set(struct osd_waitevent *wait_event);
-extern int osd_waitevent_wait(struct osd_waitevent *wait_event);
-
-/* If >0, wait_event got signaled. If ==0, timeout. If < 0, error */
-extern int osd_waitevent_waitex(struct osd_waitevent *wait_event,
-			       u32 timeout_in_ms);
-
-#endif /* _OSD_H_ */
diff --git a/drivers/staging/hv/ring_buffer.c b/drivers/staging/hv/ring_buffer.c
index 4d53392..66688fb 100644
--- a/drivers/staging/hv/ring_buffer.c
+++ b/drivers/staging/hv/ring_buffer.c
@@ -23,7 +23,6 @@
 
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include "osd.h"
 #include "logging.h"
 #include "ring_buffer.h"
 
diff --git a/drivers/staging/hv/ring_buffer.h b/drivers/staging/hv/ring_buffer.h
index 7bd6ecf..7bf20d6 100644
--- a/drivers/staging/hv/ring_buffer.h
+++ b/drivers/staging/hv/ring_buffer.h
@@ -51,7 +51,7 @@ struct hv_ring_buffer {
 	 * !!! DO NOT place any fields below this !!!
 	 */
 	u8 buffer[0];
-} __attribute__((packed));
+} __packed;
 
 struct hv_ring_buffer_info {
 	struct hv_ring_buffer *ring_buffer;
diff --git a/drivers/staging/hv/rndis_filter.c b/drivers/staging/hv/rndis_filter.c
index 53676dc..e7189cd 100644
--- a/drivers/staging/hv/rndis_filter.c
+++ b/drivers/staging/hv/rndis_filter.c
@@ -19,13 +19,15 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/highmem.h>
 #include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/if_ether.h>
 
-#include "osd.h"
 #include "logging.h"
+#include "hv_api.h"
 #include "netvsc_api.h"
 #include "rndis_filter.h"
 
@@ -57,7 +59,8 @@ struct rndis_device {
 
 struct rndis_request {
 	struct list_head list_ent;
-	struct osd_waitevent *waitevent;
+	int wait_condition;
+	wait_queue_head_t wait_event;
 
 	/*
 	 * FIXME: We assumed a fixed size response here. If we do ever need to
@@ -129,11 +132,7 @@ static struct rndis_request *get_rndis_request(struct rndis_device *dev,
 	if (!request)
 		return NULL;
 
-	request->waitevent = osd_waitevent_create();
-	if (!request->waitevent) {
-		kfree(request);
-		return NULL;
-	}
+	init_waitqueue_head(&request->wait_event);
 
 	rndis_msg = &request->request_msg;
 	rndis_msg->ndis_msg_type = msg_type;
@@ -164,7 +163,6 @@ static void put_rndis_request(struct rndis_device *dev,
 	list_del(&req->list_ent);
 	spin_unlock_irqrestore(&dev->request_lock, flags);
 
-	kfree(req->waitevent);
 	kfree(req);
 }
 
@@ -255,10 +253,10 @@ static int rndis_filter_send_request(struct rndis_device *dev,
 	packet->total_data_buflen = req->request_msg.msg_len;
 	packet->page_buf_cnt = 1;
 
-	packet->page_buf[0].Pfn = virt_to_phys(&req->request_msg) >>
+	packet->page_buf[0].pfn = virt_to_phys(&req->request_msg) >>
 					PAGE_SHIFT;
-	packet->page_buf[0].Length = req->request_msg.msg_len;
-	packet->page_buf[0].Offset =
+	packet->page_buf[0].len = req->request_msg.msg_len;
+	packet->page_buf[0].offset =
 		(unsigned long)&req->request_msg & (PAGE_SIZE - 1);
 
 	packet->completion.send.send_completion_ctx = req;/* packet; */
@@ -321,7 +319,8 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
 			}
 		}
 
-		osd_waitevent_set(request->waitevent);
+		request->wait_condition = 1;
+		wake_up(&request->wait_event);
 	} else {
 		DPRINT_ERR(NETVSC, "no rndis request found for this response "
 			   "(id 0x%x res type 0x%x)",
@@ -356,10 +355,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
 	struct rndis_packet *rndis_pkt;
 	u32 data_offset;
 
-	/* empty ethernet frame ?? */
-	/* ASSERT(Packet->PageBuffers[0].Length > */
-	/* 	RNDIS_MESSAGE_SIZE(struct rndis_packet)); */
-
 	rndis_pkt = &msg->msg.pkt;
 
 	/*
@@ -371,8 +366,8 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
 	data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
 
 	pkt->total_data_buflen -= data_offset;
-	pkt->page_buf[0].Offset += data_offset;
-	pkt->page_buf[0].Length -= data_offset;
+	pkt->page_buf[0].offset += data_offset;
+	pkt->page_buf[0].len -= data_offset;
 
 	pkt->is_data_pkt = true;
 
@@ -383,7 +378,7 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
 static int rndis_filter_receive(struct hv_device *dev,
 				struct hv_netvsc_packet	*pkt)
 {
-	struct netvsc_device *net_dev = dev->Extension;
+	struct netvsc_device *net_dev = dev->ext;
 	struct rndis_device *rndis_dev;
 	struct rndis_message rndis_msg;
 	struct rndis_message *rndis_hdr;
@@ -406,10 +401,10 @@ static int rndis_filter_receive(struct hv_device *dev,
 	}
 
 	rndis_hdr = (struct rndis_message *)kmap_atomic(
-			pfn_to_page(pkt->page_buf[0].Pfn), KM_IRQ0);
+			pfn_to_page(pkt->page_buf[0].pfn), KM_IRQ0);
 
 	rndis_hdr = (void *)((unsigned long)rndis_hdr +
-			pkt->page_buf[0].Offset);
+			pkt->page_buf[0].offset);
 
 	/* Make sure we got a valid rndis message */
 	/*
@@ -419,7 +414,7 @@ static int rndis_filter_receive(struct hv_device *dev,
 	 * */
 #if 0
 	if (pkt->total_data_buflen != rndis_hdr->msg_len) {
-		kunmap_atomic(rndis_hdr - pkt->page_buf[0].Offset,
+		kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset,
 			      KM_IRQ0);
 
 		DPRINT_ERR(NETVSC, "invalid rndis message? (expected %u "
@@ -443,7 +438,7 @@ static int rndis_filter_receive(struct hv_device *dev,
 			sizeof(struct rndis_message) :
 			rndis_hdr->msg_len);
 
-	kunmap_atomic(rndis_hdr - pkt->page_buf[0].Offset, KM_IRQ0);
+	kunmap_atomic(rndis_hdr - pkt->page_buf[0].offset, KM_IRQ0);
 
 	dump_rndis_message(&rndis_msg);
 
@@ -456,8 +451,6 @@ static int rndis_filter_receive(struct hv_device *dev,
 	case REMOTE_NDIS_INITIALIZE_CMPLT:
 	case REMOTE_NDIS_QUERY_CMPLT:
 	case REMOTE_NDIS_SET_CMPLT:
-	/* case REMOTE_NDIS_RESET_CMPLT: */
-	/* case REMOTE_NDIS_KEEPALIVE_CMPLT: */
 		/* completion msgs */
 		rndis_filter_receive_response(rndis_dev, &rndis_msg);
 		break;
@@ -503,11 +496,17 @@ static int rndis_filter_query_device(struct rndis_device *dev, u32 oid,
 	query->info_buflen = 0;
 	query->dev_vc_handle = 0;
 
+	request->wait_condition = 0;
 	ret = rndis_filter_send_request(dev, request);
 	if (ret != 0)
 		goto Cleanup;
 
-	osd_waitevent_wait(request->waitevent);
+	wait_event_timeout(request->wait_event, request->wait_condition,
+				msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
 
 	/* Copy the response back */
 	query_complete = &request->response_msg.msg.query_complete;
@@ -558,9 +557,6 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
 	u32 status;
 	int ret;
 
-	/* ASSERT(RNDIS_MESSAGE_SIZE(struct rndis_set_request) + sizeof(u32) <= */
-	/* 	sizeof(struct rndis_message)); */
-
 	request = get_rndis_request(dev, REMOTE_NDIS_SET_MSG,
 			RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
 			sizeof(u32));
@@ -578,12 +574,14 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
 	memcpy((void *)(unsigned long)set + sizeof(struct rndis_set_request),
 	       &new_filter, sizeof(u32));
 
+	request->wait_condition = 0;
 	ret = rndis_filter_send_request(dev, request);
 	if (ret != 0)
 		goto Cleanup;
 
-	ret = osd_waitevent_waitex(request->waitevent, 2000/*2sec*/);
-	if (!ret) {
+	wait_event_timeout(request->wait_event, request->wait_condition,
+		msecs_to_jiffies(2000));
+	if (request->wait_condition == 0) {
 		ret = -1;
 		DPRINT_ERR(NETVSC, "timeout before we got a set response...");
 		/*
@@ -622,24 +620,21 @@ int rndis_filter_init(struct netvsc_driver *drv)
 	rndisDriver->OnLinkStatusChanged = Driver->OnLinkStatusChanged;*/
 
 	/* Save the original dispatch handlers before we override it */
-	rndis_filter.inner_drv.base.OnDeviceAdd = drv->base.OnDeviceAdd;
-	rndis_filter.inner_drv.base.OnDeviceRemove =
-					drv->base.OnDeviceRemove;
-	rndis_filter.inner_drv.base.OnCleanup = drv->base.OnCleanup;
+	rndis_filter.inner_drv.base.dev_add = drv->base.dev_add;
+	rndis_filter.inner_drv.base.dev_rm =
+					drv->base.dev_rm;
+	rndis_filter.inner_drv.base.cleanup = drv->base.cleanup;
 
-	/* ASSERT(Driver->OnSend); */
-	/* ASSERT(Driver->OnReceiveCallback); */
 	rndis_filter.inner_drv.send = drv->send;
 	rndis_filter.inner_drv.recv_cb = drv->recv_cb;
 	rndis_filter.inner_drv.link_status_change =
 					drv->link_status_change;
 
 	/* Override */
-	drv->base.OnDeviceAdd = rndis_filte_device_add;
-	drv->base.OnDeviceRemove = rndis_filter_device_remove;
-	drv->base.OnCleanup = rndis_filter_cleanup;
+	drv->base.dev_add = rndis_filte_device_add;
+	drv->base.dev_rm = rndis_filter_device_remove;
+	drv->base.cleanup = rndis_filter_cleanup;
 	drv->send = rndis_filter_send;
-	/* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
 	drv->recv_cb = rndis_filter_receive;
 
 	return 0;
@@ -669,13 +664,20 @@ static int rndis_filter_init_device(struct rndis_device *dev)
 
 	dev->state = RNDIS_DEV_INITIALIZING;
 
+	request->wait_condition = 0;
 	ret = rndis_filter_send_request(dev, request);
 	if (ret != 0) {
 		dev->state = RNDIS_DEV_UNINITIALIZED;
 		goto Cleanup;
 	}
 
-	osd_waitevent_wait(request->waitevent);
+
+	wait_event_timeout(request->wait_event, request->wait_condition,
+		msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto Cleanup;
+	}
 
 	init_complete = &request->response_msg.msg.init_complete;
 	status = init_complete->status;
@@ -770,7 +772,7 @@ static int rndis_filte_device_add(struct hv_device *dev,
 	 * NOTE! Once the channel is created, we may get a receive callback
 	 * (RndisFilterOnReceive()) before this call is completed
 	 */
-	ret = rndis_filter.inner_drv.base.OnDeviceAdd(dev, additional_info);
+	ret = rndis_filter.inner_drv.base.dev_add(dev, additional_info);
 	if (ret != 0) {
 		kfree(rndisDevice);
 		return ret;
@@ -778,9 +780,7 @@ static int rndis_filte_device_add(struct hv_device *dev,
 
 
 	/* Initialize the rndis device */
-	netDevice = dev->Extension;
-	/* ASSERT(netDevice); */
-	/* ASSERT(netDevice->Device); */
+	netDevice = dev->ext;
 
 	netDevice->extension = rndisDevice;
 	rndisDevice->net_dev = netDevice;
@@ -818,7 +818,7 @@ static int rndis_filte_device_add(struct hv_device *dev,
 
 static int rndis_filter_device_remove(struct hv_device *dev)
 {
-	struct netvsc_device *net_dev = dev->Extension;
+	struct netvsc_device *net_dev = dev->ext;
 	struct rndis_device *rndis_dev = net_dev->extension;
 
 	/* Halt and release the rndis device */
@@ -828,7 +828,7 @@ static int rndis_filter_device_remove(struct hv_device *dev)
 	net_dev->extension = NULL;
 
 	/* Pass control to inner driver to remove the device */
-	rndis_filter.inner_drv.base.OnDeviceRemove(dev);
+	rndis_filter.inner_drv.base.dev_rm(dev);
 
 	return 0;
 }
@@ -839,7 +839,7 @@ static void rndis_filter_cleanup(struct hv_driver *drv)
 
 int rndis_filter_open(struct hv_device *dev)
 {
-	struct netvsc_device *netDevice = dev->Extension;
+	struct netvsc_device *netDevice = dev->ext;
 
 	if (!netDevice)
 		return -EINVAL;
@@ -849,7 +849,7 @@ int rndis_filter_open(struct hv_device *dev)
 
 int rndis_filter_close(struct hv_device *dev)
 {
-	struct netvsc_device *netDevice = dev->Extension;
+	struct netvsc_device *netDevice = dev->ext;
 
 	if (!netDevice)
 		return -EINVAL;
@@ -868,7 +868,6 @@ static int rndis_filter_send(struct hv_device *dev,
 
 	/* Add the rndis header */
 	filterPacket = (struct rndis_filter_packet *)pkt->extension;
-	/* ASSERT(filterPacket); */
 
 	memset(filterPacket, 0, sizeof(struct rndis_filter_packet));
 
@@ -884,10 +883,10 @@ static int rndis_filter_send(struct hv_device *dev,
 	rndisPacket->data_len = pkt->total_data_buflen;
 
 	pkt->is_data_pkt = true;
-	pkt->page_buf[0].Pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
-	pkt->page_buf[0].Offset =
+	pkt->page_buf[0].pfn = virt_to_phys(rndisMessage) >> PAGE_SHIFT;
+	pkt->page_buf[0].offset =
 			(unsigned long)rndisMessage & (PAGE_SIZE-1);
-	pkt->page_buf[0].Length = rndisMessageSize;
+	pkt->page_buf[0].len = rndisMessageSize;
 
 	/* Save the packet send completion and context */
 	filterPacket->completion = pkt->completion.send.send_completion;
diff --git a/drivers/staging/hv/storvsc.c b/drivers/staging/hv/storvsc.c
index 9295113..e2ad729 100644
--- a/drivers/staging/hv/storvsc.c
+++ b/drivers/staging/hv/storvsc.c
@@ -19,11 +19,13 @@
  *   Hank Janssen  <hjanssen@microsoft.com>
  */
 #include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "storvsc_api.h"
 #include "vmbus_packet_format.h"
@@ -38,7 +40,8 @@ struct storvsc_request_extension {
 	struct hv_device *device;
 
 	/* Synchronize the request/response if needed */
-	struct osd_waitevent *wait_event;
+	int wait_condition;
+	wait_queue_head_t wait_event;
 
 	struct vstor_packet vstor_packet;
 };
@@ -94,7 +97,7 @@ static inline struct storvsc_device *alloc_stor_device(struct hv_device *device)
 	atomic_cmpxchg(&stor_device->ref_count, 0, 2);
 
 	stor_device->device = device;
-	device->Extension = stor_device;
+	device->ext = stor_device;
 
 	return stor_device;
 }
@@ -110,7 +113,7 @@ static inline struct storvsc_device *get_stor_device(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = (struct storvsc_device *)device->Extension;
+	stor_device = (struct storvsc_device *)device->ext;
 	if (stor_device && atomic_read(&stor_device->ref_count) > 1)
 		atomic_inc(&stor_device->ref_count);
 	else
@@ -125,7 +128,7 @@ static inline struct storvsc_device *must_get_stor_device(
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = (struct storvsc_device *)device->Extension;
+	stor_device = (struct storvsc_device *)device->ext;
 	if (stor_device && atomic_read(&stor_device->ref_count))
 		atomic_inc(&stor_device->ref_count);
 	else
@@ -138,7 +141,7 @@ static inline void put_stor_device(struct hv_device *device)
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = (struct storvsc_device *)device->Extension;
+	stor_device = (struct storvsc_device *)device->ext;
 	/* ASSERT(stor_device); */
 
 	atomic_dec(&stor_device->ref_count);
@@ -151,7 +154,7 @@ static inline struct storvsc_device *release_stor_device(
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = (struct storvsc_device *)device->Extension;
+	stor_device = (struct storvsc_device *)device->ext;
 	/* ASSERT(stor_device); */
 
 	/* Busy wait until the ref drop to 2, then set it to 1 */
@@ -167,14 +170,14 @@ static inline struct storvsc_device *final_release_stor_device(
 {
 	struct storvsc_device *stor_device;
 
-	stor_device = (struct storvsc_device *)device->Extension;
+	stor_device = (struct storvsc_device *)device->ext;
 	/* ASSERT(stor_device); */
 
 	/* Busy wait until the ref drop to 1, then set it to 0 */
 	while (atomic_cmpxchg(&stor_device->ref_count, 1, 0) != 1)
 		udelay(100);
 
-	device->Extension = NULL;
+	device->ext = NULL;
 	return stor_device;
 }
 
@@ -200,40 +203,38 @@ static int stor_vsc_channel_init(struct hv_device *device)
 	 * channel
 	 */
 	memset(request, 0, sizeof(struct storvsc_request_extension));
-	request->wait_event = osd_waitevent_create();
-	if (!request->wait_event) {
-		ret = -ENOMEM;
-		goto nomem;
-	}
-
+	init_waitqueue_head(&request->wait_event);
 	vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
 	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 
-	/*SpinlockAcquire(gDriverExt.packetListLock);
-	INSERT_TAIL_LIST(&gDriverExt.packetList, &packet->listEntry.entry);
-	SpinlockRelease(gDriverExt.packetListLock);*/
-
 	DPRINT_INFO(STORVSC, "BEGIN_INITIALIZATION_OPERATION...");
 
+	request->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, vstor_packet,
 			       sizeof(struct vstor_packet),
 			       (unsigned long)request,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC,
 			   "unable to send BEGIN_INITIALIZATION_OPERATION");
-		goto Cleanup;
+		goto cleanup;
+	}
+
+	wait_event_timeout(request->wait_event, request->wait_condition,
+			msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(request->wait_event);
 
 	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 	    vstor_packet->status != 0) {
 		DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed "
 			   "(op %d status 0x%x)",
 			   vstor_packet->operation, vstor_packet->status);
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION...");
@@ -246,18 +247,24 @@ static int stor_vsc_channel_init(struct hv_device *device)
 	vstor_packet->version.major_minor = VMSTOR_PROTOCOL_VERSION_CURRENT;
 	FILL_VMSTOR_REVISION(vstor_packet->version.revision);
 
+	request->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, vstor_packet,
 			       sizeof(struct vstor_packet),
 			       (unsigned long)request,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC,
 			   "unable to send BEGIN_INITIALIZATION_OPERATION");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(request->wait_event);
+	wait_event_timeout(request->wait_event, request->wait_condition,
+			msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
 
 	/* TODO: Check returned version */
 	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
@@ -265,7 +272,7 @@ static int stor_vsc_channel_init(struct hv_device *device)
 		DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed "
 			   "(op %d status 0x%x)",
 			   vstor_packet->operation, vstor_packet->status);
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	/* Query channel properties */
@@ -277,19 +284,25 @@ static int stor_vsc_channel_init(struct hv_device *device)
 	vstor_packet->storage_channel_properties.port_number =
 					stor_device->port_number;
 
+	request->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, vstor_packet,
 			       sizeof(struct vstor_packet),
 			       (unsigned long)request,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC,
 			   "unable to send QUERY_PROPERTIES_OPERATION");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(request->wait_event);
+	wait_event_timeout(request->wait_event, request->wait_condition,
+			msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
 
 	/* TODO: Check returned version */
 	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
@@ -297,7 +310,7 @@ static int stor_vsc_channel_init(struct hv_device *device)
 		DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed "
 			   "(op %d status 0x%x)",
 			   vstor_packet->operation, vstor_packet->status);
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	stor_device->path_id = vstor_packet->storage_channel_properties.path_id;
@@ -314,34 +327,37 @@ static int stor_vsc_channel_init(struct hv_device *device)
 	vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
 	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 
+	request->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, vstor_packet,
 			       sizeof(struct vstor_packet),
 			       (unsigned long)request,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC,
 			   "unable to send END_INITIALIZATION_OPERATION");
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	osd_waitevent_wait(request->wait_event);
+	wait_event_timeout(request->wait_event, request->wait_condition,
+			msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
 
 	if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
 	    vstor_packet->status != 0) {
 		DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed "
 			   "(op %d status 0x%x)",
 			   vstor_packet->operation, vstor_packet->status);
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	DPRINT_INFO(STORVSC, "**** storage channel up and running!! ****");
 
-Cleanup:
-	kfree(request->wait_event);
-	request->wait_event = NULL;
-nomem:
+cleanup:
 	put_stor_device(device);
 	return ret;
 }
@@ -437,7 +453,7 @@ static void stor_vsc_on_channel_callback(void *context)
 	struct storvsc_device *stor_device;
 	u32 bytes_recvd;
 	u64 request_id;
-	unsigned char packet[ALIGN_UP(sizeof(struct vstor_packet), 8)];
+	unsigned char packet[ALIGN(sizeof(struct vstor_packet), 8)];
 	struct storvsc_request_extension *request;
 	int ret;
 
@@ -452,7 +468,7 @@ static void stor_vsc_on_channel_callback(void *context)
 
 	do {
 		ret = vmbus_recvpacket(device->channel, packet,
-				       ALIGN_UP(sizeof(struct vstor_packet), 8),
+				       ALIGN(sizeof(struct vstor_packet), 8),
 				       &bytes_recvd, &request_id);
 		if (ret == 0 && bytes_recvd > 0) {
 			DPRINT_DBG(STORVSC, "receive %d bytes - tid %llx",
@@ -476,8 +492,8 @@ static void stor_vsc_on_channel_callback(void *context)
 
 				memcpy(&request->vstor_packet, packet,
 				       sizeof(struct vstor_packet));
-
-				osd_waitevent_set(request->wait_event);
+				request->wait_condition = 1;
+				wake_up(&request->wait_event);
 			} else {
 				stor_vsc_on_receive(device,
 						(struct vstor_packet *)packet,
@@ -499,7 +515,7 @@ static int stor_vsc_connect_to_vsp(struct hv_device *device)
 	struct storvsc_driver_object *stor_driver;
 	int ret;
 
-	stor_driver = (struct storvsc_driver_object *)device->Driver;
+	stor_driver = (struct storvsc_driver_object *)device->drv;
 	memset(&props, 0, sizeof(struct vmstorage_channel_properties));
 
 	/* Open the channel */
@@ -539,7 +555,7 @@ static int stor_vsc_on_device_add(struct hv_device *device,
 	stor_device = alloc_stor_device(device);
 	if (!stor_device) {
 		ret = -1;
-		goto Cleanup;
+		goto cleanup;
 	}
 
 	/* Save the channel properties to our storvsc channel */
@@ -569,7 +585,7 @@ static int stor_vsc_on_device_add(struct hv_device *device,
 		   stor_device->port_number, stor_device->path_id,
 		   stor_device->target_id);
 
-Cleanup:
+cleanup:
 	return ret;
 }
 
@@ -581,7 +597,7 @@ static int stor_vsc_on_device_remove(struct hv_device *device)
 	struct storvsc_device *stor_device;
 
 	DPRINT_INFO(STORVSC, "disabling storage device (%p)...",
-		    device->Extension);
+		    device->ext);
 
 	stor_device = release_stor_device(device);
 
@@ -597,7 +613,7 @@ static int stor_vsc_on_device_remove(struct hv_device *device)
 	}
 
 	DPRINT_INFO(STORVSC, "removing storage device (%p)...",
-		    device->Extension);
+		    device->ext);
 
 	stor_device = final_release_stor_device(device);
 
@@ -629,31 +645,31 @@ int stor_vsc_on_host_reset(struct hv_device *device)
 	request = &stor_device->reset_request;
 	vstor_packet = &request->vstor_packet;
 
-	request->wait_event = osd_waitevent_create();
-	if (!request->wait_event) {
-		ret = -ENOMEM;
-		goto Cleanup;
-	}
+	init_waitqueue_head(&request->wait_event);
 
 	vstor_packet->operation = VSTOR_OPERATION_RESET_BUS;
 	vstor_packet->flags = REQUEST_COMPLETION_FLAG;
 	vstor_packet->vm_srb.path_id = stor_device->path_id;
 
+	request->wait_condition = 0;
 	ret = vmbus_sendpacket(device->channel, vstor_packet,
 			       sizeof(struct vstor_packet),
 			       (unsigned long)&stor_device->reset_request,
-			       VmbusPacketTypeDataInBand,
+			       VM_PKT_DATA_INBAND,
 			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC, "Unable to send reset packet %p ret %d",
 			   vstor_packet, ret);
-		goto Cleanup;
+		goto cleanup;
 	}
 
-	/* FIXME: Add a timeout */
-	osd_waitevent_wait(request->wait_event);
+	wait_event_timeout(request->wait_event, request->wait_condition,
+			msecs_to_jiffies(1000));
+	if (request->wait_condition == 0) {
+		ret = -ETIMEDOUT;
+		goto cleanup;
+	}
 
-	kfree(request->wait_event);
 	DPRINT_INFO(STORVSC, "host adapter reset completed");
 
 	/*
@@ -661,7 +677,7 @@ int stor_vsc_on_host_reset(struct hv_device *device)
 	 * should have been flushed out and return to us
 	 */
 
-Cleanup:
+cleanup:
 	put_stor_device(device);
 	return ret;
 }
@@ -687,7 +703,7 @@ static int stor_vsc_on_io_request(struct hv_device *device,
 		   request_extension);
 
 	DPRINT_DBG(STORVSC, "req %p len %d bus %d, target %d, lun %d cdblen %d",
-		   request, request->data_buffer.Length, request->bus,
+		   request, request->data_buffer.len, request->bus,
 		   request->target_id, request->lun_id, request->cdb_len);
 
 	if (!stor_device) {
@@ -720,7 +736,7 @@ static int stor_vsc_on_io_request(struct hv_device *device,
 	memcpy(&vstor_packet->vm_srb.cdb, request->cdb, request->cdb_len);
 
 	vstor_packet->vm_srb.data_in = request->type;
-	vstor_packet->vm_srb.data_transfer_length = request->data_buffer.Length;
+	vstor_packet->vm_srb.data_transfer_length = request->data_buffer.len;
 
 	vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB;
 
@@ -734,7 +750,7 @@ static int stor_vsc_on_io_request(struct hv_device *device,
 		   vstor_packet->vm_srb.sense_info_length,
 		   vstor_packet->vm_srb.cdb_length);
 
-	if (request_extension->request->data_buffer.Length) {
+	if (request_extension->request->data_buffer.len) {
 		ret = vmbus_sendpacket_multipagebuffer(device->channel,
 				&request_extension->request->data_buffer,
 				vstor_packet,
@@ -744,7 +760,7 @@ static int stor_vsc_on_io_request(struct hv_device *device,
 		ret = vmbus_sendpacket(device->channel, vstor_packet,
 				       sizeof(struct vstor_packet),
 				       (unsigned long)request_extension,
-				       VmbusPacketTypeDataInBand,
+				       VM_PKT_DATA_INBAND,
 				       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	}
 
@@ -788,7 +804,7 @@ int stor_vsc_initialize(struct hv_driver *driver)
 	/* ASSERT(stor_driver->RingBufferSize >= (PAGE_SIZE << 1)); */
 
 	driver->name = g_driver_name;
-	memcpy(&driver->deviceType, &gStorVscDeviceType,
+	memcpy(&driver->dev_type, &gStorVscDeviceType,
 	       sizeof(struct hv_guid));
 
 	stor_driver->request_ext_size =
@@ -802,7 +818,7 @@ int stor_vsc_initialize(struct hv_driver *driver)
 	 */
 	stor_driver->max_outstanding_req_per_channel =
 		((stor_driver->ring_buffer_size - PAGE_SIZE) /
-		  ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET +
+		  ALIGN(MAX_MULTIPAGE_BUFFER_PACKET +
 			   sizeof(struct vstor_packet) + sizeof(u64),
 			   sizeof(u64)));
 
@@ -811,9 +827,9 @@ int stor_vsc_initialize(struct hv_driver *driver)
 		    STORVSC_MAX_IO_REQUESTS);
 
 	/* Setup the dispatch table */
-	stor_driver->base.OnDeviceAdd	= stor_vsc_on_device_add;
-	stor_driver->base.OnDeviceRemove	= stor_vsc_on_device_remove;
-	stor_driver->base.OnCleanup	= stor_vsc_on_cleanup;
+	stor_driver->base.dev_add	= stor_vsc_on_device_add;
+	stor_driver->base.dev_rm	= stor_vsc_on_device_remove;
+	stor_driver->base.cleanup	= stor_vsc_on_cleanup;
 
 	stor_driver->on_io_request	= stor_vsc_on_io_request;
 
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index 17f1b34..e6462a2 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -31,7 +31,7 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_dbg.h>
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "version_info.h"
 #include "vmbus.h"
@@ -42,7 +42,7 @@ struct host_device_context {
 	/* must be 1st field
 	 * FIXME this is a bug */
 	/* point back to our device context */
-	struct vm_device *device_ctx;
+	struct hv_device *device_ctx;
 	struct kmem_cache *request_pool;
 	unsigned int port;
 	unsigned char path;
@@ -63,12 +63,6 @@ struct storvsc_cmd_request {
 	 * Which sounds like a very bad design... */
 };
 
-struct storvsc_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* FIXME this is a bug... */
-	struct driver_context drv_ctx;
-	struct storvsc_driver_object drv_obj;
-};
 
 /* Static decl */
 static int storvsc_probe(struct device *dev);
@@ -100,7 +94,7 @@ module_param(storvsc_ringbuffer_size, int, S_IRUGO);
 MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
 
 /* The one and only one */
-static struct storvsc_driver_context g_storvsc_drv;
+static struct storvsc_driver_object g_storvsc_drv;
 
 /* Scsi driver */
 static struct scsi_host_template scsi_driver = {
@@ -137,14 +131,16 @@ static struct scsi_host_template scsi_driver = {
 static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 {
 	int ret;
-	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_storvsc_drv.drv_ctx;
+	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv;
+	struct hv_driver *drv = &g_storvsc_drv.base;
 
 	storvsc_drv_obj->ring_buffer_size = storvsc_ringbuffer_size;
 
 	/* Callback to client driver to complete the initialization */
 	drv_init(&storvsc_drv_obj->base);
 
+	drv->priv = storvsc_drv_obj;
+
 	DPRINT_INFO(STORVSC_DRV,
 		    "request extension size %u, max outstanding reqs %u",
 		    storvsc_drv_obj->request_ext_size,
@@ -160,15 +156,13 @@ static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
 		return -1;
 	}
 
-	drv_ctx->driver.name = storvsc_drv_obj->base.name;
-	memcpy(&drv_ctx->class_id, &storvsc_drv_obj->base.deviceType,
-	       sizeof(struct hv_guid));
+	drv->driver.name = storvsc_drv_obj->base.name;
 
-	drv_ctx->probe = storvsc_probe;
-	drv_ctx->remove = storvsc_remove;
+	drv->driver.probe = storvsc_probe;
+	drv->driver.remove = storvsc_remove;
 
 	/* The driver belongs to vmbus */
-	ret = vmbus_child_driver_register(drv_ctx);
+	ret = vmbus_child_driver_register(&drv->driver);
 
 	return ret;
 }
@@ -182,8 +176,8 @@ static int storvsc_drv_exit_cb(struct device *dev, void *data)
 
 static void storvsc_drv_exit(void)
 {
-	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv.drv_obj;
-	struct driver_context *drv_ctx = &g_storvsc_drv.drv_ctx;
+	struct storvsc_driver_object *storvsc_drv_obj = &g_storvsc_drv;
+	struct hv_driver *drv = &g_storvsc_drv.base;
 	struct device *current_dev = NULL;
 	int ret;
 
@@ -191,7 +185,7 @@ static void storvsc_drv_exit(void)
 		current_dev = NULL;
 
 		/* Get the device */
-		ret = driver_for_each_device(&drv_ctx->driver, NULL,
+		ret = driver_for_each_device(&drv->driver, NULL,
 					     (void *) &current_dev,
 					     storvsc_drv_exit_cb);
 
@@ -206,10 +200,10 @@ static void storvsc_drv_exit(void)
 		device_unregister(current_dev);
 	}
 
-	if (storvsc_drv_obj->base.OnCleanup)
-		storvsc_drv_obj->base.OnCleanup(&storvsc_drv_obj->base);
+	if (storvsc_drv_obj->base.cleanup)
+		storvsc_drv_obj->base.cleanup(&storvsc_drv_obj->base);
 
-	vmbus_child_driver_unregister(drv_ctx);
+	vmbus_child_driver_unregister(&drv->driver);
 	return;
 }
 
@@ -219,19 +213,15 @@ static void storvsc_drv_exit(void)
 static int storvsc_probe(struct device *device)
 {
 	int ret;
-	struct driver_context *driver_ctx =
-				driver_to_driver_context(device->driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-				(struct storvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-				&storvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
+	struct hv_driver *drv =
+				drv_to_hv_drv(device->driver);
+	struct storvsc_driver_object *storvsc_drv_obj = drv->priv;
+	struct hv_device *device_obj = device_to_hv_device(device);
 	struct Scsi_Host *host;
 	struct host_device_context *host_device_ctx;
 	struct storvsc_device_info device_info;
 
-	if (!storvsc_drv_obj->base.OnDeviceAdd)
+	if (!storvsc_drv_obj->base.dev_add)
 		return -1;
 
 	host = scsi_host_alloc(&scsi_driver,
@@ -247,10 +237,10 @@ static int storvsc_probe(struct device *device)
 	memset(host_device_ctx, 0, sizeof(struct host_device_context));
 
 	host_device_ctx->port = host->host_no;
-	host_device_ctx->device_ctx = device_ctx;
+	host_device_ctx->device_ctx = device_obj;
 
 	host_device_ctx->request_pool =
-				kmem_cache_create(dev_name(&device_ctx->device),
+				kmem_cache_create(dev_name(&device_obj->device),
 					sizeof(struct storvsc_cmd_request) +
 					storvsc_drv_obj->request_ext_size, 0,
 					SLAB_HWCACHE_ALIGN, NULL);
@@ -262,7 +252,7 @@ static int storvsc_probe(struct device *device)
 
 	device_info.port_number = host->host_no;
 	/* Call to the vsc driver to add the device */
-	ret = storvsc_drv_obj->base.OnDeviceAdd(device_obj,
+	ret = storvsc_drv_obj->base.dev_add(device_obj,
 						(void *)&device_info);
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC_DRV, "unable to add scsi vsc device");
@@ -287,7 +277,7 @@ static int storvsc_probe(struct device *device)
 	if (ret != 0) {
 		DPRINT_ERR(STORVSC_DRV, "unable to add scsi host device");
 
-		storvsc_drv_obj->base.OnDeviceRemove(device_obj);
+		storvsc_drv_obj->base.dev_rm(device_obj);
 
 		kmem_cache_destroy(host_device_ctx->request_pool);
 		scsi_host_put(host);
@@ -304,27 +294,23 @@ static int storvsc_probe(struct device *device)
 static int storvsc_remove(struct device *device)
 {
 	int ret;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(device->driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-			(struct storvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-			&storvsc_drv_ctx->drv_obj;
-	struct vm_device *device_ctx = device_to_vm_device(device);
-	struct hv_device *device_obj = &device_ctx->device_obj;
+	struct hv_driver *drv =
+			drv_to_hv_drv(device->driver);
+	struct storvsc_driver_object *storvsc_drv_obj = drv->priv;
+	struct hv_device *device_obj = device_to_hv_device(device);
 	struct Scsi_Host *host = dev_get_drvdata(device);
 	struct host_device_context *host_device_ctx =
 			(struct host_device_context *)host->hostdata;
 
 
-	if (!storvsc_drv_obj->base.OnDeviceRemove)
+	if (!storvsc_drv_obj->base.dev_rm)
 		return -1;
 
 	/*
 	 * Call to the vsc driver to let it know that the device is being
 	 * removed
 	 */
-	ret = storvsc_drv_obj->base.OnDeviceRemove(device_obj);
+	ret = storvsc_drv_obj->base.dev_rm(device_obj);
 	if (ret != 0) {
 		/* TODO: */
 		DPRINT_ERR(STORVSC, "unable to remove vsc device (ret %d)",
@@ -385,7 +371,7 @@ static void storvsc_commmand_completion(struct hv_storvsc_request *request)
 
 	/* ASSERT(request->BytesXfer <= request->data_buffer.Length); */
 	scsi_set_resid(scmnd,
-		request->data_buffer.Length - request->bytes_xfer);
+		request->data_buffer.len - request->bytes_xfer);
 
 	scsi_done_fn = scmnd->scsi_done;
 
@@ -434,7 +420,7 @@ static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
 	struct scatterlist *bounce_sgl;
 	struct page *page_buf;
 
-	num_pages = ALIGN_UP(len, PAGE_SIZE) >> PAGE_SHIFT;
+	num_pages = ALIGN(len, PAGE_SIZE) >> PAGE_SHIFT;
 
 	bounce_sgl = kcalloc(num_pages, sizeof(struct scatterlist), GFP_ATOMIC);
 	if (!bounce_sgl)
@@ -601,13 +587,10 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 	int ret;
 	struct host_device_context *host_device_ctx =
 		(struct host_device_context *)scmnd->device->host->hostdata;
-	struct vm_device *device_ctx = host_device_ctx->device_ctx;
-	struct driver_context *driver_ctx =
-		driver_to_driver_context(device_ctx->device.driver);
-	struct storvsc_driver_context *storvsc_drv_ctx =
-		(struct storvsc_driver_context *)driver_ctx;
-	struct storvsc_driver_object *storvsc_drv_obj =
-		&storvsc_drv_ctx->drv_obj;
+	struct hv_device *device_ctx = host_device_ctx->device_ctx;
+	struct hv_driver *drv =
+		drv_to_hv_drv(device_ctx->device.driver);
+	struct storvsc_driver_object *storvsc_drv_obj = drv->priv;
 	struct hv_storvsc_request *request;
 	struct storvsc_cmd_request *cmd_request;
 	unsigned int request_size = 0;
@@ -693,7 +676,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 	request->sense_buffer_size = SCSI_SENSE_BUFFERSIZE;
 
 
-	request->data_buffer.Length = scsi_bufflen(scmnd);
+	request->data_buffer.len = scsi_bufflen(scmnd);
 	if (scsi_sg_count(scmnd)) {
 		sgl = (struct scatterlist *)scsi_sglist(scmnd);
 		sg_count = scsi_sg_count(scmnd);
@@ -720,7 +703,7 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 			}
 
 			cmd_request->bounce_sgl_count =
-				ALIGN_UP(scsi_bufflen(scmnd), PAGE_SIZE) >>
+				ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >>
 					PAGE_SHIFT;
 
 			/*
@@ -734,25 +717,25 @@ static int storvsc_queuecommand_lck(struct scsi_cmnd *scmnd,
 			sg_count = cmd_request->bounce_sgl_count;
 		}
 
-		request->data_buffer.Offset = sgl[0].offset;
+		request->data_buffer.offset = sgl[0].offset;
 
 		for (i = 0; i < sg_count; i++) {
 			DPRINT_DBG(STORVSC_DRV, "sgl[%d] len %d offset %d\n",
 				   i, sgl[i].length, sgl[i].offset);
-			request->data_buffer.PfnArray[i] =
+			request->data_buffer.pfn_array[i] =
 				page_to_pfn(sg_page((&sgl[i])));
 		}
 	} else if (scsi_sglist(scmnd)) {
 		/* ASSERT(scsi_bufflen(scmnd) <= PAGE_SIZE); */
-		request->data_buffer.Offset =
+		request->data_buffer.offset =
 			virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1);
-		request->data_buffer.PfnArray[0] =
+		request->data_buffer.pfn_array[0] =
 			virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT;
 	}
 
 retry_request:
 	/* Invokes the vsc to start an IO */
-	ret = storvsc_drv_obj->on_io_request(&device_ctx->device_obj,
+	ret = storvsc_drv_obj->on_io_request(device_ctx,
 					   &cmd_request->request);
 	if (ret == -1) {
 		/* no more space */
@@ -839,18 +822,18 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
 	int ret;
 	struct host_device_context *host_device_ctx =
 		(struct host_device_context *)scmnd->device->host->hostdata;
-	struct vm_device *device_ctx = host_device_ctx->device_ctx;
+	struct hv_device *device_ctx = host_device_ctx->device_ctx;
 
 	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host resetting...",
-		    scmnd->device, &device_ctx->device_obj);
+		    scmnd->device, device_ctx);
 
 	/* Invokes the vsc to reset the host/bus */
-	ret = stor_vsc_on_host_reset(&device_ctx->device_obj);
+	ret = stor_vsc_on_host_reset(device_ctx);
 	if (ret != 0)
 		return ret;
 
 	DPRINT_INFO(STORVSC_DRV, "sdev (%p) dev obj (%p) - host reseted",
-		    scmnd->device, &device_ctx->device_obj);
+		    scmnd->device, device_ctx);
 
 	return ret;
 }
diff --git a/drivers/staging/hv/tools/hv_kvp_daemon.c b/drivers/staging/hv/tools/hv_kvp_daemon.c
new file mode 100644
index 0000000..f5a2dd6
--- /dev/null
+++ b/drivers/staging/hv/tools/hv_kvp_daemon.c
@@ -0,0 +1,470 @@
+/*
+ * An implementation of key value pair (KVP) functionality for Linux.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan <ksrinivasan@novell.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.
+ *
+ * You should have 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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/utsname.h>
+#include <linux/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <linux/connector.h>
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <ifaddrs.h>
+#include <netdb.h>
+#include <syslog.h>
+
+/*
+ * KYS: TODO. Need to register these in the kernel.
+ *
+ * The following definitions are shared with the in-kernel component; do not
+ * change any of this without making the corresponding changes in
+ * the KVP kernel component.
+ */
+#define CN_KVP_IDX		0x9     /* MSFT KVP functionality */
+#define CN_KVP_VAL		0x1 /* This supports queries from the kernel */
+#define CN_KVP_USER_VAL		0x2 /* This supports queries from the user  */
+
+/*
+ * KVP protocol: The user mode component first registers with the
+ * the kernel component. Subsequently, the kernel component requests, data
+ * for the specified keys. In response to this message the user mode component
+ * fills in the value corresponding to the specified key. We overload the
+ * sequence field in the cn_msg header to define our KVP message types.
+ *
+ * We use this infrastructure for also supporting queries from user mode
+ * application for state that may be maintained in the KVP kernel component.
+ *
+ * XXXKYS: Have a shared header file between the user and kernel (TODO)
+ */
+
+enum kvp_op {
+	KVP_REGISTER = 0, /* Register the user mode component*/
+	KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/
+	KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/
+	KVP_USER_GET, /*User is requesting the value for the specified key*/
+	KVP_USER_SET /*User is providing the value for the specified key*/
+};
+
+#define HV_KVP_EXCHANGE_MAX_KEY_SIZE	512
+#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE	2048
+
+struct hv_ku_msg {
+	__u32	kvp_index;
+	__u8  kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */
+	__u8  kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key  value */
+};
+
+enum key_index {
+	FullyQualifiedDomainName = 0,
+	IntegrationServicesVersion, /*This key is serviced in the kernel*/
+	NetworkAddressIPv4,
+	NetworkAddressIPv6,
+	OSBuildNumber,
+	OSName,
+	OSMajorVersion,
+	OSMinorVersion,
+	OSVersion,
+	ProcessorArchitecture
+};
+
+/*
+ * End of shared definitions.
+ */
+
+static char kvp_send_buffer[4096];
+static char kvp_recv_buffer[4096];
+static struct sockaddr_nl addr;
+
+static char os_name[100];
+static char os_major[50];
+static char os_minor[50];
+static char processor_arch[50];
+static char os_build[100];
+static char *lic_version;
+
+void kvp_get_os_info(void)
+{
+	FILE	*file;
+	char	*eol;
+	struct utsname buf;
+
+	uname(&buf);
+	strcpy(os_build, buf.release);
+	strcpy(processor_arch, buf.machine);
+
+	file = fopen("/etc/SuSE-release", "r");
+	if (file != NULL)
+		goto kvp_osinfo_found;
+	file  = fopen("/etc/redhat-release", "r");
+	if (file != NULL)
+		goto kvp_osinfo_found;
+	/*
+	 * Add code for other supported platforms.
+	 */
+
+	/*
+	 * We don't have information about the os.
+	 */
+	strcpy(os_name, "Linux");
+	strcpy(os_major, "0");
+	strcpy(os_minor, "0");
+	return;
+
+kvp_osinfo_found:
+	fgets(os_name, 99, file);
+	eol = index(os_name, '\n');
+	*eol = '\0';
+	fgets(os_major, 49, file);
+	eol = index(os_major, '\n');
+	*eol = '\0';
+	fgets(os_minor, 49, file);
+	eol = index(os_minor, '\n');
+	*eol = '\0';
+	fclose(file);
+	return;
+}
+
+static int
+kvp_get_ip_address(int family, char *buffer, int length)
+{
+	struct ifaddrs *ifap;
+	struct ifaddrs *curp;
+	int ipv4_len = strlen("255.255.255.255") + 1;
+	int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
+	int offset = 0;
+	const char *str;
+	char tmp[50];
+	int error = 0;
+
+	/*
+	 * On entry into this function, the buffer is capable of holding the
+	 * maximum key value (2048 bytes).
+	 */
+
+	if (getifaddrs(&ifap)) {
+		strcpy(buffer, "getifaddrs failed\n");
+		return 1;
+	}
+
+	curp = ifap;
+	while (curp != NULL) {
+		if ((curp->ifa_addr != NULL) &&
+		   (curp->ifa_addr->sa_family == family)) {
+			if (family == AF_INET) {
+				struct sockaddr_in *addr =
+				(struct sockaddr_in *) curp->ifa_addr;
+
+				str = inet_ntop(family, &addr->sin_addr,
+						tmp, 50);
+				if (str == NULL) {
+					strcpy(buffer, "inet_ntop failed\n");
+					error = 1;
+					goto getaddr_done;
+				}
+				if (offset == 0)
+					strcpy(buffer, tmp);
+				else
+					strcat(buffer, tmp);
+				strcat(buffer, ";");
+
+				offset += strlen(str) + 1;
+				if ((length - offset) < (ipv4_len + 1))
+					goto getaddr_done;
+
+			} else {
+
+			/*
+			 * We only support AF_INET and AF_INET6
+			 * and the list of addresses is seperated by a ";".
+			 */
+				struct sockaddr_in6 *addr =
+				(struct sockaddr_in6 *) curp->ifa_addr;
+
+				str = inet_ntop(family,
+					&addr->sin6_addr.s6_addr,
+					tmp, 50);
+				if (str == NULL) {
+					strcpy(buffer, "inet_ntop failed\n");
+					error = 1;
+					goto getaddr_done;
+				}
+				if (offset == 0)
+					strcpy(buffer, tmp);
+				else
+					strcat(buffer, tmp);
+				strcat(buffer, ";");
+				offset += strlen(str) + 1;
+				if ((length - offset) < (ipv6_len + 1))
+					goto getaddr_done;
+
+			}
+
+		}
+		curp = curp->ifa_next;
+	}
+
+getaddr_done:
+	freeifaddrs(ifap);
+	return error;
+}
+
+
+static int
+kvp_get_domain_name(char *buffer, int length)
+{
+	struct addrinfo	hints, *info ;
+	gethostname(buffer, length);
+	int error = 0;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = AF_INET; /*Get only ipv4 addrinfo. */
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_CANONNAME;
+
+	error = getaddrinfo(buffer, "http", &hints, &info);
+	if (error != 0) {
+		strcpy(buffer, "getaddrinfo failed\n");
+		error = 1;
+		goto get_domain_done;
+	}
+	strcpy(buffer, info->ai_canonname);
+get_domain_done:
+	freeaddrinfo(info);
+	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);
+}
+
+main(void)
+{
+	int fd, len, sock_opt;
+	int error;
+	struct cn_msg *message;
+	struct pollfd pfd;
+	struct nlmsghdr *incoming_msg;
+	struct cn_msg	*incoming_cn_msg;
+	char	*key_value;
+	char	*key_name;
+	int	 key_index;
+
+	daemon(1, 0);
+	openlog("KVP", 0, LOG_USER);
+	syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
+	/*
+	 * Retrieve OS release information.
+	 */
+	kvp_get_os_info();
+
+	fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR);
+	if (fd < 0) {
+		syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd);
+		exit(-1);
+	}
+	addr.nl_family = AF_NETLINK;
+	addr.nl_pad = 0;
+	addr.nl_pid = 0;
+	addr.nl_groups = CN_KVP_IDX;
+
+
+	error = bind(fd, (struct sockaddr *)&addr, sizeof(addr));
+	if (error < 0) {
+		syslog(LOG_ERR, "bind failed; error:%d", error);
+		close(fd);
+		exit(-1);
+	}
+	sock_opt = addr.nl_groups;
+	setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt));
+	/*
+	 * Register ourselves with the kernel.
+	 */
+	message = (struct cn_msg *)kvp_send_buffer;
+	message->id.idx = CN_KVP_IDX;
+	message->id.val = CN_KVP_VAL;
+	message->seq = KVP_REGISTER;
+	message->ack = 0;
+	message->len = 0;
+
+	len = netlink_send(fd, message);
+	if (len < 0) {
+		syslog(LOG_ERR, "netlink_send failed; error:%d", len);
+		close(fd);
+		exit(-1);
+	}
+
+	pfd.fd = fd;
+
+	while (1) {
+		pfd.events = POLLIN;
+		pfd.revents = 0;
+		poll(&pfd, 1, -1);
+
+		len = recv(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0);
+
+		if (len < 0) {
+			syslog(LOG_ERR, "recv failed; error:%d", len);
+			close(fd);
+			return -1;
+		}
+
+		incoming_msg = (struct nlmsghdr *)kvp_recv_buffer;
+		incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
+
+		switch (incoming_cn_msg->seq) {
+		case KVP_REGISTER:
+			/*
+			 * Driver is registering with us; stash away the version
+			 * information.
+			 */
+			lic_version = malloc(strlen(incoming_cn_msg->data) + 1);
+			if (lic_version) {
+				strcpy(lic_version, incoming_cn_msg->data);
+				syslog(LOG_INFO, "KVP LIC Version: %s",
+					lic_version);
+			} else {
+				syslog(LOG_ERR, "malloc failed");
+			}
+			continue;
+
+		case KVP_KERNEL_GET:
+			break;
+		default:
+			continue;
+		}
+
+		key_index =
+		((struct hv_ku_msg *)incoming_cn_msg->data)->kvp_index;
+		key_name =
+		((struct hv_ku_msg *)incoming_cn_msg->data)->kvp_key;
+		key_value =
+		((struct hv_ku_msg *)incoming_cn_msg->data)->kvp_value;
+
+		switch (key_index) {
+		case FullyQualifiedDomainName:
+			kvp_get_domain_name(key_value,
+					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_name, "FullyQualifiedDomainName");
+			break;
+		case IntegrationServicesVersion:
+			strcpy(key_name, "IntegrationServicesVersion");
+			strcpy(key_value, lic_version);
+			break;
+		case NetworkAddressIPv4:
+			kvp_get_ip_address(AF_INET, key_value,
+					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_name, "NetworkAddressIPv4");
+			break;
+		case NetworkAddressIPv6:
+			kvp_get_ip_address(AF_INET6, key_value,
+					HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+			strcpy(key_name, "NetworkAddressIPv6");
+			break;
+		case OSBuildNumber:
+			strcpy(key_value, os_build);
+			strcpy(key_name, "OSBuildNumber");
+			break;
+		case OSName:
+			strcpy(key_value, os_name);
+			strcpy(key_name, "OSName");
+			break;
+		case OSMajorVersion:
+			strcpy(key_value, os_major);
+			strcpy(key_name, "OSMajorVersion");
+			break;
+		case OSMinorVersion:
+			strcpy(key_value, os_minor);
+			strcpy(key_name, "OSMinorVersion");
+			break;
+		case OSVersion:
+			strcpy(key_value, os_build);
+			strcpy(key_name, "OSVersion");
+			break;
+		case ProcessorArchitecture:
+			strcpy(key_value, processor_arch);
+			strcpy(key_name, "ProcessorArchitecture");
+			break;
+		default:
+			strcpy(key_value, "Unknown Key");
+			/*
+			 * We use a null key name to terminate enumeration.
+			 */
+			strcpy(key_name, "");
+			break;
+		}
+		/*
+		 * Send the value back to the kernel. The response is
+		 * already in the receive buffer. Update the cn_msg header to
+		 * reflect the key value that has been added to the message
+		 */
+
+		incoming_cn_msg->id.idx = CN_KVP_IDX;
+		incoming_cn_msg->id.val = CN_KVP_VAL;
+		incoming_cn_msg->seq = KVP_USER_SET;
+		incoming_cn_msg->ack = 0;
+		incoming_cn_msg->len = sizeof(struct hv_ku_msg);
+
+		len = netlink_send(fd, incoming_cn_msg);
+		if (len < 0) {
+			syslog(LOG_ERR, "net_link send failed; error:%d", len);
+			exit(-1);
+		}
+	}
+
+}
diff --git a/drivers/staging/hv/utils.h b/drivers/staging/hv/utils.h
index 7c07499..acebbbf 100644
--- a/drivers/staging/hv/utils.h
+++ b/drivers/staging/hv/utils.h
@@ -43,12 +43,12 @@
 struct vmbuspipe_hdr {
 	u32 flags;
 	u32 msgsize;
-} __attribute__((packed));
+} __packed;
 
 struct ic_version {
 	u16 major;
 	u16 minor;
-} __attribute__((packed));
+} __packed;
 
 struct icmsg_hdr {
 	struct ic_version icverframe;
@@ -59,26 +59,26 @@ struct icmsg_hdr {
 	u8 ictransaction_id;
 	u8 icflags;
 	u8 reserved[2];
-} __attribute__((packed));
+} __packed;
 
 struct icmsg_negotiate {
 	u16 icframe_vercnt;
 	u16 icmsg_vercnt;
 	u32 reserved;
 	struct ic_version icversion_data[1]; /* any size array */
-} __attribute__((packed));
+} __packed;
 
 struct shutdown_msg_data {
 	u32 reason_code;
 	u32 timeout_seconds;
 	u32 flags;
 	u8  display_message[2048];
-} __attribute__((packed));
+} __packed;
 
 struct heartbeat_msg_data {
 	u64 seq_num;
 	u32 reserved[8];
-} __attribute__((packed));
+} __packed;
 
 /* Time Sync IC defs */
 #define ICTIMESYNCFLAG_PROBE	0
@@ -96,12 +96,13 @@ struct ictimesync_data{
 	u64 childtime;
 	u64 roundtriptime;
 	u8 flags;
-} __attribute__((packed));
+} __packed;
 
 /* Index for each IC struct in array hv_cb_utils[] */
 #define HV_SHUTDOWN_MSG		0
 #define HV_TIMESYNC_MSG		1
 #define HV_HEARTBEAT_MSG	2
+#define HV_KVP_MSG		3
 
 struct hyperv_service_callback {
 	u8 msg_type;
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
index 42f2adb..73087f2 100644
--- a/drivers/staging/hv/vmbus.h
+++ b/drivers/staging/hv/vmbus.h
@@ -28,49 +28,23 @@
 #include <linux/device.h>
 #include "vmbus_api.h"
 
-struct driver_context {
-	struct hv_guid class_id;
 
-	struct device_driver driver;
 
-	/*
-	 * Use these methods instead of the struct device_driver so 2.6 kernel
-	 * stops complaining
-	 * TODO - fix this!
-	 */
-	int (*probe)(struct device *);
-	int (*remove)(struct device *);
-	void (*shutdown)(struct device *);
-};
 
-struct vm_device {
-	struct work_struct probe_failed_work_item;
-	struct hv_guid class_id;
-	struct hv_guid device_id;
-	int probe_error;
-	struct hv_device device_obj;
-	struct device device;
-};
-
-static inline struct vm_device *to_vm_device(struct hv_device *d)
-{
-	return container_of(d, struct vm_device, device_obj);
-}
-
-static inline struct vm_device *device_to_vm_device(struct device *d)
+static inline struct hv_device *device_to_hv_device(struct device *d)
 {
-	return container_of(d, struct vm_device, device);
+	return container_of(d, struct hv_device, device);
 }
 
-static inline struct driver_context *driver_to_driver_context(struct device_driver *d)
+static inline struct hv_driver *drv_to_hv_drv(struct device_driver *d)
 {
-	return container_of(d, struct driver_context, driver);
+	return container_of(d, struct hv_driver, driver);
 }
 
 
 /* Vmbus interface */
-int vmbus_child_driver_register(struct driver_context *driver_ctx);
-void vmbus_child_driver_unregister(struct driver_context *driver_ctx);
+int vmbus_child_driver_register(struct device_driver *drv);
+void vmbus_child_driver_unregister(struct device_driver *drv);
 
 extern struct completion hv_channel_ready;
 
diff --git a/drivers/staging/hv/vmbus_api.h b/drivers/staging/hv/vmbus_api.h
index 2da3f52..f0d96eb 100644
--- a/drivers/staging/hv/vmbus_api.h
+++ b/drivers/staging/hv/vmbus_api.h
@@ -25,6 +25,9 @@
 #ifndef _VMBUS_API_H_
 #define _VMBUS_API_H_
 
+#include <linux/device.h>
+#include <linux/workqueue.h>
+
 #define MAX_PAGE_BUFFER_COUNT				16
 #define MAX_MULTIPAGE_BUFFER_COUNT			32 /* 128K */
 
@@ -32,17 +35,17 @@
 
 /* Single-page buffer */
 struct hv_page_buffer {
-	u32 Length;
-	u32 Offset;
-	u64 Pfn;
+	u32 len;
+	u32 offset;
+	u64 pfn;
 };
 
 /* Multiple-page buffer */
 struct hv_multipage_buffer {
 	/* Length and Offset determines the # of pfns in the array */
-	u32 Length;
-	u32 Offset;
-	u64 PfnArray[MAX_MULTIPAGE_BUFFER_COUNT];
+	u32 len;
+	u32 offset;
+	u64 pfn_array[MAX_MULTIPAGE_BUFFER_COUNT];
 };
 
 /* 0x18 includes the proprietary packet header */
@@ -59,29 +62,29 @@ struct hv_driver;
 struct hv_device;
 
 struct hv_dev_port_info {
-	u32 InterruptMask;
-	u32 ReadIndex;
-	u32 WriteIndex;
-	u32 BytesAvailToRead;
-	u32 BytesAvailToWrite;
+	u32 int_mask;
+	u32 read_idx;
+	u32 write_idx;
+	u32 bytes_avail_toread;
+	u32 bytes_avail_towrite;
 };
 
 struct hv_device_info {
-	u32 ChannelId;
-	u32 ChannelState;
-	struct hv_guid ChannelType;
-	struct hv_guid ChannelInstance;
-
-	u32 MonitorId;
-	u32 ServerMonitorPending;
-	u32 ServerMonitorLatency;
-	u32 ServerMonitorConnectionId;
-	u32 ClientMonitorPending;
-	u32 ClientMonitorLatency;
-	u32 ClientMonitorConnectionId;
-
-	struct hv_dev_port_info Inbound;
-	struct hv_dev_port_info Outbound;
+	u32 chn_id;
+	u32 chn_state;
+	struct hv_guid chn_type;
+	struct hv_guid chn_instance;
+
+	u32 monitor_id;
+	u32 server_monitor_pending;
+	u32 server_monitor_latency;
+	u32 server_monitor_conn_id;
+	u32 client_monitor_pending;
+	u32 client_monitor_latency;
+	u32 client_monitor_conn_id;
+
+	struct hv_dev_port_info inbound;
+	struct hv_dev_port_info outbound;
 };
 
 /* Base driver object */
@@ -89,30 +92,48 @@ struct hv_driver {
 	const char *name;
 
 	/* the device type supported by this driver */
-	struct hv_guid deviceType;
-
-	int (*OnDeviceAdd)(struct hv_device *device, void *data);
-	int (*OnDeviceRemove)(struct hv_device *device);
-	void (*OnCleanup)(struct hv_driver *driver);
+	struct hv_guid dev_type;
+
+	/*
+	 * Device type specific drivers (net, blk etc.)
+	 * need a mechanism to get a pointer to
+	 * device type specific driver structure given
+	 * a pointer to the base hyperv driver structure.
+	 * The current code solves this problem using
+	 * a hack. Support this need explicitly
+	 */
+	void *priv;
+
+	struct device_driver driver;
+
+	int (*dev_add)(struct hv_device *device, void *data);
+	int (*dev_rm)(struct hv_device *device);
+	void (*cleanup)(struct hv_driver *driver);
 };
 
 /* Base device object */
 struct hv_device {
 	/* the driver for this device */
-	struct hv_driver *Driver;
+	struct hv_driver *drv;
 
 	char name[64];
 
+	struct work_struct probe_failed_work_item;
+
+	int probe_error;
+
 	/* the device type id of this device */
-	struct hv_guid deviceType;
+	struct hv_guid dev_type;
 
 	/* the device instance id of this device */
-	struct hv_guid deviceInstance;
+	struct hv_guid dev_instance;
+
+	struct device device;
 
 	struct vmbus_channel *channel;
 
 	/* Device extension; */
-	void *Extension;
+	void *ext;
 };
 
 #endif /* _VMBUS_API_H_ */
diff --git a/drivers/staging/hv/vmbus_channel_interface.h b/drivers/staging/hv/vmbus_channel_interface.h
index 2674282..20ae258 100644
--- a/drivers/staging/hv/vmbus_channel_interface.h
+++ b/drivers/staging/hv/vmbus_channel_interface.h
@@ -48,19 +48,19 @@
  * struct contains the fundamental information about an offer.
  */
 struct vmbus_channel_offer {
-	struct hv_guid InterfaceType;
-	struct hv_guid InterfaceInstance;
-	u64 InterruptLatencyIn100nsUnits;
-	u32 InterfaceRevision;
-	u32 ServerContextAreaSize;	/* in bytes */
-	u16 ChannelFlags;
-	u16 MmioMegabytes;		/* in bytes * 1024 * 1024 */
+	struct hv_guid if_type;
+	struct hv_guid if_instance;
+	u64 int_latency; /* in 100ns units */
+	u32 if_revision;
+	u32 server_ctx_size;	/* in bytes */
+	u16 chn_flags;
+	u16 mmio_megabytes;		/* in bytes * 1024 * 1024 */
 
 	union {
 		/* Non-pipes: The user has MAX_USER_DEFINED_BYTES bytes. */
 		struct {
-			unsigned char UserDefined[MAX_USER_DEFINED_BYTES];
-		} Standard;
+			unsigned char user_def[MAX_USER_DEFINED_BYTES];
+		} std;
 
 		/*
 		 * Pipes:
@@ -70,12 +70,12 @@ struct vmbus_channel_offer {
 		 * use.
 		 */
 		struct {
-			u32  PipeMode;
-			unsigned char UserDefined[MAX_PIPE_USER_DEFINED_BYTES];
-		} Pipe;
+			u32  pipe_mode;
+			unsigned char user_def[MAX_PIPE_USER_DEFINED_BYTES];
+		} pipe;
 	} u;
-	u32 Padding;
-} __attribute__((packed));
+	u32 padding;
+} __packed;
 
 /* Server Flags */
 #define VMBUS_CHANNEL_ENUMERATE_DEVICE_INTERFACE	1
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 84fdb64..b473f46 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -29,7 +29,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include "version_info.h"
-#include "osd.h"
+#include "hv_api.h"
 #include "logging.h"
 #include "vmbus.h"
 #include "channel.h"
@@ -42,19 +42,13 @@
 
 /* Main vmbus driver data structure */
 struct vmbus_driver_context {
-	/* !! These must be the first 2 fields !! */
-	/* FIXME, this is a bug */
-	/* The driver field is not used in here. Instead, the bus field is */
-	/* used to represent the driver */
-	struct driver_context drv_ctx;
-	struct hv_driver drv_obj;
 
 	struct bus_type bus;
 	struct tasklet_struct msg_dpc;
 	struct tasklet_struct event_dpc;
 
 	/* The bus root device */
-	struct vm_device device_ctx;
+	struct hv_device device_ctx;
 };
 
 static int vmbus_match(struct device *device, struct device_driver *driver);
@@ -62,8 +56,6 @@ static int vmbus_probe(struct device *device);
 static int vmbus_remove(struct device *device);
 static void vmbus_shutdown(struct device *device);
 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env);
-static void vmbus_msg_dpc(unsigned long data);
-static void vmbus_event_dpc(unsigned long data);
 
 static irqreturn_t vmbus_isr(int irq, void *dev_id);
 
@@ -113,7 +105,7 @@ static struct device_attribute vmbus_device_attrs[] = {
 };
 
 /* The one and only one */
-static struct vmbus_driver_context g_vmbus_drv = {
+static struct vmbus_driver_context vmbus_drv = {
 	.bus.name =		"vmbus",
 	.bus.match =		vmbus_match,
 	.bus.shutdown =		vmbus_shutdown,
@@ -123,14 +115,14 @@ static struct vmbus_driver_context g_vmbus_drv = {
 	.bus.dev_attrs =	vmbus_device_attrs,
 };
 
-static const char *gDriverName = "hyperv";
+static const char *driver_name = "hyperv";
 
 /*
  * Windows vmbus does not defined this.
  * We defined this to be consistent with other devices
  */
 /* {c5295816-f63a-4d5f-8d1a-4daf999ca185} */
-static const struct hv_guid gVmbusDeviceType = {
+static const struct hv_guid device_type = {
 	.data = {
 		0x16, 0x58, 0x29, 0xc5, 0x3a, 0xf6, 0x5f, 0x4d,
 		0x8d, 0x1a, 0x4d, 0xaf, 0x99, 0x9c, 0xa1, 0x85
@@ -138,35 +130,28 @@ static const struct hv_guid gVmbusDeviceType = {
 };
 
 /* {ac3760fc-9adf-40aa-9427-a70ed6de95c5} */
-static const struct hv_guid gVmbusDeviceId = {
+static const struct hv_guid device_id = {
 	.data = {
 		0xfc, 0x60, 0x37, 0xac, 0xdf, 0x9a, 0xaa, 0x40,
 		0x94, 0x27, 0xa7, 0x0e, 0xd6, 0xde, 0x95, 0xc5
 	}
 };
 
-static struct hv_device *gDevice; /* vmbus root device */
+static struct hv_device *vmbus_device; /* vmbus root device */
 
-/*
- * VmbusChildDeviceAdd - Registers the child device with the vmbus
- */
-int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
-{
-	return vmbus_child_device_register(gDevice, ChildDevice);
-}
 
 /*
- * VmbusOnDeviceAdd - Callback when the root bus device is added
+ * vmbus_dev_add - Callback when the root bus device is added
  */
-static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
+static int vmbus_dev_add(struct hv_device *dev, void *info)
 {
-	u32 *irqvector = AdditionalInfo;
+	u32 *irqvector = info;
 	int ret;
 
-	gDevice = dev;
+	vmbus_device = dev;
 
-	memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
-	memcpy(&gDevice->deviceInstance, &gVmbusDeviceId,
+	memcpy(&vmbus_device->dev_type, &device_type, sizeof(struct hv_guid));
+	memcpy(&vmbus_device->dev_instance, &device_id,
 	       sizeof(struct hv_guid));
 
 	/* strcpy(dev->name, "vmbus"); */
@@ -174,34 +159,12 @@ static int VmbusOnDeviceAdd(struct hv_device *dev, void *AdditionalInfo)
 	on_each_cpu(hv_synic_init, (void *)irqvector, 1);
 
 	/* Connect to VMBus in the root partition */
-	ret = VmbusConnect();
+	ret = vmbus_connect();
 
 	/* VmbusSendEvent(device->localPortId+1); */
 	return ret;
 }
 
-/*
- * VmbusOnDeviceRemove - Callback when the root bus device is removed
- */
-static int VmbusOnDeviceRemove(struct hv_device *dev)
-{
-	int ret = 0;
-
-	vmbus_release_unattached_channels();
-	VmbusDisconnect();
-	on_each_cpu(hv_synic_cleanup, NULL, 1);
-	return ret;
-}
-
-/*
- * VmbusOnCleanup - Perform any cleanup when the driver is removed
- */
-static void VmbusOnCleanup(struct hv_driver *drv)
-{
-	/* struct vmbus_driver *driver = (struct vmbus_driver *)drv; */
-
-	hv_cleanup();
-}
 
 struct onmessage_work_context {
 	struct work_struct work;
@@ -221,7 +184,7 @@ static void vmbus_onmessage_work(struct work_struct *work)
 /*
  * vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior
  */
-static void vmbus_on_msg_dpc(struct hv_driver *drv)
+static void vmbus_on_msg_dpc(unsigned long data)
 {
 	int cpu = smp_processor_id();
 	void *page_addr = hv_context.synic_message_page[cpu];
@@ -239,7 +202,7 @@ static void vmbus_on_msg_dpc(struct hv_driver *drv)
 				continue;
 			INIT_WORK(&ctx->work, vmbus_onmessage_work);
 			memcpy(&ctx->msg, msg, sizeof(*msg));
-			queue_work(gVmbusConnection.WorkQueue, &ctx->work);
+			queue_work(vmbus_connection.work_queue, &ctx->work);
 		}
 
 		msg->header.message_type = HVMSG_NONE;
@@ -267,7 +230,7 @@ static void vmbus_on_msg_dpc(struct hv_driver *drv)
 /*
  * vmbus_on_isr - ISR routine
  */
-static int vmbus_on_isr(struct hv_driver *drv)
+static int vmbus_on_isr(void)
 {
 	int ret = 0;
 	int cpu = smp_processor_id();
@@ -309,37 +272,38 @@ static void get_channel_info(struct hv_device *device,
 
 	vmbus_get_debug_info(device->channel, &debug_info);
 
-	info->ChannelId = debug_info.relid;
-	info->ChannelState = debug_info.state;
-	memcpy(&info->ChannelType, &debug_info.interfacetype,
+	info->chn_id = debug_info.relid;
+	info->chn_state = debug_info.state;
+	memcpy(&info->chn_type, &debug_info.interfacetype,
 	       sizeof(struct hv_guid));
-	memcpy(&info->ChannelInstance, &debug_info.interface_instance,
+	memcpy(&info->chn_instance, &debug_info.interface_instance,
 	       sizeof(struct hv_guid));
 
-	info->MonitorId = debug_info.monitorid;
+	info->monitor_id = debug_info.monitorid;
 
-	info->ServerMonitorPending = debug_info.servermonitor_pending;
-	info->ServerMonitorLatency = debug_info.servermonitor_latency;
-	info->ServerMonitorConnectionId = debug_info.servermonitor_connectionid;
+	info->server_monitor_pending = debug_info.servermonitor_pending;
+	info->server_monitor_latency = debug_info.servermonitor_latency;
+	info->server_monitor_conn_id = debug_info.servermonitor_connectionid;
 
-	info->ClientMonitorPending = debug_info.clientmonitor_pending;
-	info->ClientMonitorLatency = debug_info.clientmonitor_latency;
-	info->ClientMonitorConnectionId = debug_info.clientmonitor_connectionid;
+	info->client_monitor_pending = debug_info.clientmonitor_pending;
+	info->client_monitor_latency = debug_info.clientmonitor_latency;
+	info->client_monitor_conn_id = debug_info.clientmonitor_connectionid;
 
-	info->Inbound.InterruptMask = debug_info.inbound.current_interrupt_mask;
-	info->Inbound.ReadIndex = debug_info.inbound.current_read_index;
-	info->Inbound.WriteIndex = debug_info.inbound.current_write_index;
-	info->Inbound.BytesAvailToRead = debug_info.inbound.bytes_avail_toread;
-	info->Inbound.BytesAvailToWrite =
+	info->inbound.int_mask = debug_info.inbound.current_interrupt_mask;
+	info->inbound.read_idx = debug_info.inbound.current_read_index;
+	info->inbound.write_idx = debug_info.inbound.current_write_index;
+	info->inbound.bytes_avail_toread =
+		debug_info.inbound.bytes_avail_toread;
+	info->inbound.bytes_avail_towrite =
 		debug_info.inbound.bytes_avail_towrite;
 
-	info->Outbound.InterruptMask =
+	info->outbound.int_mask =
 		debug_info.outbound.current_interrupt_mask;
-	info->Outbound.ReadIndex = debug_info.outbound.current_read_index;
-	info->Outbound.WriteIndex = debug_info.outbound.current_write_index;
-	info->Outbound.BytesAvailToRead =
+	info->outbound.read_idx = debug_info.outbound.current_read_index;
+	info->outbound.write_idx = debug_info.outbound.current_write_index;
+	info->outbound.bytes_avail_toread =
 		debug_info.outbound.bytes_avail_toread;
-	info->Outbound.BytesAvailToWrite =
+	info->outbound.bytes_avail_towrite =
 		debug_info.outbound.bytes_avail_towrite;
 }
 
@@ -353,95 +317,95 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
 				      struct device_attribute *dev_attr,
 				      char *buf)
 {
-	struct vm_device *device_ctx = device_to_vm_device(dev);
+	struct hv_device *device_ctx = device_to_hv_device(dev);
 	struct hv_device_info device_info;
 
 	memset(&device_info, 0, sizeof(struct hv_device_info));
 
-	get_channel_info(&device_ctx->device_obj, &device_info);
+	get_channel_info(device_ctx, &device_info);
 
 	if (!strcmp(dev_attr->attr.name, "class_id")) {
 		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
-			       device_info.ChannelType.data[3],
-			       device_info.ChannelType.data[2],
-			       device_info.ChannelType.data[1],
-			       device_info.ChannelType.data[0],
-			       device_info.ChannelType.data[5],
-			       device_info.ChannelType.data[4],
-			       device_info.ChannelType.data[7],
-			       device_info.ChannelType.data[6],
-			       device_info.ChannelType.data[8],
-			       device_info.ChannelType.data[9],
-			       device_info.ChannelType.data[10],
-			       device_info.ChannelType.data[11],
-			       device_info.ChannelType.data[12],
-			       device_info.ChannelType.data[13],
-			       device_info.ChannelType.data[14],
-			       device_info.ChannelType.data[15]);
+			       device_info.chn_type.data[3],
+			       device_info.chn_type.data[2],
+			       device_info.chn_type.data[1],
+			       device_info.chn_type.data[0],
+			       device_info.chn_type.data[5],
+			       device_info.chn_type.data[4],
+			       device_info.chn_type.data[7],
+			       device_info.chn_type.data[6],
+			       device_info.chn_type.data[8],
+			       device_info.chn_type.data[9],
+			       device_info.chn_type.data[10],
+			       device_info.chn_type.data[11],
+			       device_info.chn_type.data[12],
+			       device_info.chn_type.data[13],
+			       device_info.chn_type.data[14],
+			       device_info.chn_type.data[15]);
 	} else if (!strcmp(dev_attr->attr.name, "device_id")) {
 		return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 			       "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
-			       device_info.ChannelInstance.data[3],
-			       device_info.ChannelInstance.data[2],
-			       device_info.ChannelInstance.data[1],
-			       device_info.ChannelInstance.data[0],
-			       device_info.ChannelInstance.data[5],
-			       device_info.ChannelInstance.data[4],
-			       device_info.ChannelInstance.data[7],
-			       device_info.ChannelInstance.data[6],
-			       device_info.ChannelInstance.data[8],
-			       device_info.ChannelInstance.data[9],
-			       device_info.ChannelInstance.data[10],
-			       device_info.ChannelInstance.data[11],
-			       device_info.ChannelInstance.data[12],
-			       device_info.ChannelInstance.data[13],
-			       device_info.ChannelInstance.data[14],
-			       device_info.ChannelInstance.data[15]);
+			       device_info.chn_instance.data[3],
+			       device_info.chn_instance.data[2],
+			       device_info.chn_instance.data[1],
+			       device_info.chn_instance.data[0],
+			       device_info.chn_instance.data[5],
+			       device_info.chn_instance.data[4],
+			       device_info.chn_instance.data[7],
+			       device_info.chn_instance.data[6],
+			       device_info.chn_instance.data[8],
+			       device_info.chn_instance.data[9],
+			       device_info.chn_instance.data[10],
+			       device_info.chn_instance.data[11],
+			       device_info.chn_instance.data[12],
+			       device_info.chn_instance.data[13],
+			       device_info.chn_instance.data[14],
+			       device_info.chn_instance.data[15]);
 	} else if (!strcmp(dev_attr->attr.name, "state")) {
-		return sprintf(buf, "%d\n", device_info.ChannelState);
+		return sprintf(buf, "%d\n", device_info.chn_state);
 	} else if (!strcmp(dev_attr->attr.name, "id")) {
-		return sprintf(buf, "%d\n", device_info.ChannelId);
+		return sprintf(buf, "%d\n", device_info.chn_id);
 	} else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) {
-		return sprintf(buf, "%d\n", device_info.Outbound.InterruptMask);
+		return sprintf(buf, "%d\n", device_info.outbound.int_mask);
 	} else if (!strcmp(dev_attr->attr.name, "out_read_index")) {
-		return sprintf(buf, "%d\n", device_info.Outbound.ReadIndex);
+		return sprintf(buf, "%d\n", device_info.outbound.read_idx);
 	} else if (!strcmp(dev_attr->attr.name, "out_write_index")) {
-		return sprintf(buf, "%d\n", device_info.Outbound.WriteIndex);
+		return sprintf(buf, "%d\n", device_info.outbound.write_idx);
 	} else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) {
 		return sprintf(buf, "%d\n",
-			       device_info.Outbound.BytesAvailToRead);
+			       device_info.outbound.bytes_avail_toread);
 	} else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) {
 		return sprintf(buf, "%d\n",
-			       device_info.Outbound.BytesAvailToWrite);
+			       device_info.outbound.bytes_avail_towrite);
 	} else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) {
-		return sprintf(buf, "%d\n", device_info.Inbound.InterruptMask);
+		return sprintf(buf, "%d\n", device_info.inbound.int_mask);
 	} else if (!strcmp(dev_attr->attr.name, "in_read_index")) {
-		return sprintf(buf, "%d\n", device_info.Inbound.ReadIndex);
+		return sprintf(buf, "%d\n", device_info.inbound.read_idx);
 	} else if (!strcmp(dev_attr->attr.name, "in_write_index")) {
-		return sprintf(buf, "%d\n", device_info.Inbound.WriteIndex);
+		return sprintf(buf, "%d\n", device_info.inbound.write_idx);
 	} else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) {
 		return sprintf(buf, "%d\n",
-			       device_info.Inbound.BytesAvailToRead);
+			       device_info.inbound.bytes_avail_toread);
 	} else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) {
 		return sprintf(buf, "%d\n",
-			       device_info.Inbound.BytesAvailToWrite);
+			       device_info.inbound.bytes_avail_towrite);
 	} else if (!strcmp(dev_attr->attr.name, "monitor_id")) {
-		return sprintf(buf, "%d\n", device_info.MonitorId);
+		return sprintf(buf, "%d\n", device_info.monitor_id);
 	} else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) {
-		return sprintf(buf, "%d\n", device_info.ServerMonitorPending);
+		return sprintf(buf, "%d\n", device_info.server_monitor_pending);
 	} else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) {
-		return sprintf(buf, "%d\n", device_info.ServerMonitorLatency);
+		return sprintf(buf, "%d\n", device_info.server_monitor_latency);
 	} else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) {
 		return sprintf(buf, "%d\n",
-			       device_info.ServerMonitorConnectionId);
+			       device_info.server_monitor_conn_id);
 	} else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) {
-		return sprintf(buf, "%d\n", device_info.ClientMonitorPending);
+		return sprintf(buf, "%d\n", device_info.client_monitor_pending);
 	} else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) {
-		return sprintf(buf, "%d\n", device_info.ClientMonitorLatency);
+		return sprintf(buf, "%d\n", device_info.client_monitor_latency);
 	} else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) {
 		return sprintf(buf, "%d\n",
-			       device_info.ClientMonitorConnectionId);
+			       device_info.client_monitor_conn_id);
 	} else {
 		return 0;
 	}
@@ -461,9 +425,8 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
  */
 static int vmbus_bus_init(void)
 {
-	struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
-	struct hv_driver *driver = &g_vmbus_drv.drv_obj;
-	struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
+	struct vmbus_driver_context *vmbus_drv_ctx = &vmbus_drv;
+	struct hv_device *dev_ctx = &vmbus_drv.device_ctx;
 	int ret;
 	unsigned int vector;
 
@@ -478,13 +441,6 @@ static int vmbus_bus_init(void)
 			sizeof(struct vmbus_channel_packet_page_buffer),
 			sizeof(struct vmbus_channel_packet_multipage_buffer));
 
-	driver->name = gDriverName;
-	memcpy(&driver->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
-
-	/* Setup dispatch table */
-	driver->OnDeviceAdd	= VmbusOnDeviceAdd;
-	driver->OnDeviceRemove	= VmbusOnDeviceRemove;
-	driver->OnCleanup	= VmbusOnCleanup;
 
 	/* Hypervisor initialization...setup hypercall page..etc */
 	ret = hv_init();
@@ -494,22 +450,16 @@ static int vmbus_bus_init(void)
 		goto cleanup;
 	}
 
-	/* Sanity checks */
-	if (!driver->OnDeviceAdd) {
-		DPRINT_ERR(VMBUS_DRV, "OnDeviceAdd() routine not set");
-		ret = -1;
-		goto cleanup;
-	}
 
-	vmbus_drv_ctx->bus.name = driver->name;
+	vmbus_drv_ctx->bus.name = driver_name;
 
 	/* Initialize the bus context */
-	tasklet_init(&vmbus_drv_ctx->msg_dpc, vmbus_msg_dpc,
-		     (unsigned long)driver);
-	tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_event_dpc,
-		     (unsigned long)driver);
+	tasklet_init(&vmbus_drv_ctx->msg_dpc, vmbus_on_msg_dpc,
+		     (unsigned long)NULL);
+	tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_on_event,
+		     (unsigned long)NULL);
 
-	/* Now, register the bus driver with LDM */
+	/* Now, register the bus  with LDM */
 	ret = bus_register(&vmbus_drv_ctx->bus);
 	if (ret) {
 		ret = -1;
@@ -518,7 +468,7 @@ static int vmbus_bus_init(void)
 
 	/* Get the interrupt resource */
 	ret = request_irq(vmbus_irq, vmbus_isr, IRQF_SAMPLE_RANDOM,
-			  driver->name, NULL);
+			  driver_name, NULL);
 
 	if (ret != 0) {
 		DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to request IRQ %d",
@@ -533,10 +483,10 @@ static int vmbus_bus_init(void)
 
 	DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
 
-	/* Call to bus driver to add the root device */
-	memset(dev_ctx, 0, sizeof(struct vm_device));
+	/* Add the root device */
+	memset(dev_ctx, 0, sizeof(struct hv_device));
 
-	ret = driver->OnDeviceAdd(&dev_ctx->device_obj, &vector);
+	ret = vmbus_dev_add(dev_ctx, &vector);
 	if (ret != 0) {
 		DPRINT_ERR(VMBUS_DRV,
 			   "ERROR - Unable to add vmbus root device");
@@ -550,10 +500,6 @@ static int vmbus_bus_init(void)
 	}
 	/* strcpy(dev_ctx->device.bus_id, dev_ctx->device_obj.name); */
 	dev_set_name(&dev_ctx->device, "vmbus_0_0");
-	memcpy(&dev_ctx->class_id, &dev_ctx->device_obj.deviceType,
-		sizeof(struct hv_guid));
-	memcpy(&dev_ctx->device_id, &dev_ctx->device_obj.deviceInstance,
-		sizeof(struct hv_guid));
 
 	/* No need to bind a driver to the root device. */
 	dev_ctx->device.parent = NULL;
@@ -563,7 +509,7 @@ static int vmbus_bus_init(void)
 	/* Setup the device dispatch table */
 	dev_ctx->device.release = vmbus_bus_release;
 
-	/* Setup the bus as root device */
+	/* register the  root device */
 	ret = device_register(&dev_ctx->device);
 	if (ret) {
 		DPRINT_ERR(VMBUS_DRV,
@@ -590,17 +536,15 @@ cleanup:
  */
 static void vmbus_bus_exit(void)
 {
-	struct hv_driver *driver = &g_vmbus_drv.drv_obj;
-	struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
+	struct vmbus_driver_context *vmbus_drv_ctx = &vmbus_drv;
 
-	struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
+	struct hv_device *dev_ctx = &vmbus_drv.device_ctx;
 
-	/* Remove the root device */
-	if (driver->OnDeviceRemove)
-		driver->OnDeviceRemove(&dev_ctx->device_obj);
+	vmbus_release_unattached_channels();
+	vmbus_disconnect();
+	on_each_cpu(hv_synic_cleanup, NULL, 1);
 
-	if (driver->OnCleanup)
-		driver->OnCleanup(driver);
+	hv_cleanup();
 
 	/* Unregister the root bus device */
 	device_unregister(&dev_ctx->device);
@@ -616,9 +560,8 @@ static void vmbus_bus_exit(void)
 
 /**
  * vmbus_child_driver_register() - Register a vmbus's child driver
- * @driver_ctx:        Pointer to driver structure you want to register
+ * @drv:        Pointer to driver structure you want to register
  *
- * @driver_ctx is of type &struct driver_context
  *
  * Registers the given driver with Linux through the 'driver_register()' call
  * And sets up the hyper-v vmbus handling for this driver.
@@ -626,17 +569,17 @@ static void vmbus_bus_exit(void)
  *
  * Mainly used by Hyper-V drivers.
  */
-int vmbus_child_driver_register(struct driver_context *driver_ctx)
+int vmbus_child_driver_register(struct device_driver *drv)
 {
 	int ret;
 
 	DPRINT_INFO(VMBUS_DRV, "child driver (%p) registering - name %s",
-		    driver_ctx, driver_ctx->driver.name);
+		    drv, drv->name);
 
 	/* The child driver on this vmbus */
-	driver_ctx->driver.bus = &g_vmbus_drv.bus;
+	drv->bus = &vmbus_drv.bus;
 
-	ret = driver_register(&driver_ctx->driver);
+	ret = driver_register(drv);
 
 	vmbus_request_offers();
 
@@ -646,23 +589,22 @@ EXPORT_SYMBOL(vmbus_child_driver_register);
 
 /**
  * vmbus_child_driver_unregister() - Unregister a vmbus's child driver
- * @driver_ctx:        Pointer to driver structure you want to un-register
+ * @drv:        Pointer to driver structure you want to un-register
  *
- * @driver_ctx is of type &struct driver_context
  *
  * Un-register the given driver with Linux through the 'driver_unregister()'
  * call. And ungegisters the driver from the Hyper-V vmbus handler.
  *
  * Mainly used by Hyper-V drivers.
  */
-void vmbus_child_driver_unregister(struct driver_context *driver_ctx)
+void vmbus_child_driver_unregister(struct device_driver *drv)
 {
 	DPRINT_INFO(VMBUS_DRV, "child driver (%p) unregistering - name %s",
-		    driver_ctx, driver_ctx->driver.name);
+		    drv, drv->name);
 
-	driver_unregister(&driver_ctx->driver);
+	driver_unregister(drv);
 
-	driver_ctx->driver.bus = NULL;
+	drv->bus = NULL;
 }
 EXPORT_SYMBOL(vmbus_child_driver_unregister);
 
@@ -674,12 +616,11 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
 					    struct hv_guid *instance,
 					    struct vmbus_channel *channel)
 {
-	struct vm_device *child_device_ctx;
 	struct hv_device *child_device_obj;
 
 	/* Allocate the new child device */
-	child_device_ctx = kzalloc(sizeof(struct vm_device), GFP_KERNEL);
-	if (!child_device_ctx) {
+	child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL);
+	if (!child_device_obj) {
 		DPRINT_ERR(VMBUS_DRV,
 			"unable to allocate device_context for child device");
 		return NULL;
@@ -690,7 +631,7 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
 		"%02x%02x%02x%02x%02x%02x%02x%02x},"
 		"id {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 		"%02x%02x%02x%02x%02x%02x%02x%02x}",
-		&child_device_ctx->device,
+		&child_device_obj->device,
 		type->data[3], type->data[2], type->data[1], type->data[0],
 		type->data[5], type->data[4], type->data[7], type->data[6],
 		type->data[8], type->data[9], type->data[10], type->data[11],
@@ -704,58 +645,51 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type,
 		instance->data[12], instance->data[13],
 		instance->data[14], instance->data[15]);
 
-	child_device_obj = &child_device_ctx->device_obj;
 	child_device_obj->channel = channel;
-	memcpy(&child_device_obj->deviceType, type, sizeof(struct hv_guid));
-	memcpy(&child_device_obj->deviceInstance, instance,
+	memcpy(&child_device_obj->dev_type, type, sizeof(struct hv_guid));
+	memcpy(&child_device_obj->dev_instance, instance,
 	       sizeof(struct hv_guid));
 
-	memcpy(&child_device_ctx->class_id, type, sizeof(struct hv_guid));
-	memcpy(&child_device_ctx->device_id, instance, sizeof(struct hv_guid));
 
 	return child_device_obj;
 }
 
 /*
- * vmbus_child_device_register - Register the child device on the specified bus
+ * vmbus_child_device_register - Register the child device
  */
-int vmbus_child_device_register(struct hv_device *root_device_obj,
-				struct hv_device *child_device_obj)
+int vmbus_child_device_register(struct hv_device *child_device_obj)
 {
 	int ret = 0;
-	struct vm_device *root_device_ctx =
-				to_vm_device(root_device_obj);
-	struct vm_device *child_device_ctx =
-				to_vm_device(child_device_obj);
+
 	static atomic_t device_num = ATOMIC_INIT(0);
 
 	DPRINT_DBG(VMBUS_DRV, "child device (%p) registering",
-		   child_device_ctx);
+		   child_device_obj);
 
 	/* Set the device name. Otherwise, device_register() will fail. */
-	dev_set_name(&child_device_ctx->device, "vmbus_0_%d",
+	dev_set_name(&child_device_obj->device, "vmbus_0_%d",
 		     atomic_inc_return(&device_num));
 
 	/* The new device belongs to this bus */
-	child_device_ctx->device.bus = &g_vmbus_drv.bus; /* device->dev.bus; */
-	child_device_ctx->device.parent = &root_device_ctx->device;
-	child_device_ctx->device.release = vmbus_device_release;
+	child_device_obj->device.bus = &vmbus_drv.bus; /* device->dev.bus; */
+	child_device_obj->device.parent = &vmbus_device->device;
+	child_device_obj->device.release = vmbus_device_release;
 
 	/*
 	 * Register with the LDM. This will kick off the driver/device
 	 * binding...which will eventually call vmbus_match() and vmbus_probe()
 	 */
-	ret = device_register(&child_device_ctx->device);
+	ret = device_register(&child_device_obj->device);
 
 	/* vmbus_probe() error does not get propergate to device_register(). */
-	ret = child_device_ctx->probe_error;
+	ret = child_device_obj->probe_error;
 
 	if (ret)
 		DPRINT_ERR(VMBUS_DRV, "unable to register child device (%p)",
-			   &child_device_ctx->device);
+			   &child_device_obj->device);
 	else
 		DPRINT_INFO(VMBUS_DRV, "child device (%p) registered",
-			    &child_device_ctx->device);
+			    &child_device_obj->device);
 
 	return ret;
 }
@@ -766,19 +700,18 @@ int vmbus_child_device_register(struct hv_device *root_device_obj,
  */
 void vmbus_child_device_unregister(struct hv_device *device_obj)
 {
-	struct vm_device *device_ctx = to_vm_device(device_obj);
 
 	DPRINT_INFO(VMBUS_DRV, "unregistering child device (%p)",
-		    &device_ctx->device);
+		    &device_obj->device);
 
 	/*
 	 * Kick off the process of unregistering the device.
 	 * This will call vmbus_remove() and eventually vmbus_device_release()
 	 */
-	device_unregister(&device_ctx->device);
+	device_unregister(&device_obj->device);
 
 	DPRINT_INFO(VMBUS_DRV, "child device (%p) unregistered",
-		    &device_ctx->device);
+		    &device_obj->device);
 }
 
 /*
@@ -790,43 +723,43 @@ void vmbus_child_device_unregister(struct hv_device *device_obj)
  */
 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
 {
-	struct vm_device *device_ctx = device_to_vm_device(device);
+	struct hv_device *dev = device_to_hv_device(device);
 	int ret;
 
 	DPRINT_INFO(VMBUS_DRV, "generating uevent - VMBUS_DEVICE_CLASS_GUID={"
 		    "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 		    "%02x%02x%02x%02x%02x%02x%02x%02x}",
-		    device_ctx->class_id.data[3], device_ctx->class_id.data[2],
-		    device_ctx->class_id.data[1], device_ctx->class_id.data[0],
-		    device_ctx->class_id.data[5], device_ctx->class_id.data[4],
-		    device_ctx->class_id.data[7], device_ctx->class_id.data[6],
-		    device_ctx->class_id.data[8], device_ctx->class_id.data[9],
-		    device_ctx->class_id.data[10],
-		    device_ctx->class_id.data[11],
-		    device_ctx->class_id.data[12],
-		    device_ctx->class_id.data[13],
-		    device_ctx->class_id.data[14],
-		    device_ctx->class_id.data[15]);
+		    dev->dev_type.data[3], dev->dev_type.data[2],
+		    dev->dev_type.data[1], dev->dev_type.data[0],
+		    dev->dev_type.data[5], dev->dev_type.data[4],
+		    dev->dev_type.data[7], dev->dev_type.data[6],
+		    dev->dev_type.data[8], dev->dev_type.data[9],
+		    dev->dev_type.data[10],
+		    dev->dev_type.data[11],
+		    dev->dev_type.data[12],
+		    dev->dev_type.data[13],
+		    dev->dev_type.data[14],
+		    dev->dev_type.data[15]);
 
 	ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={"
 			     "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 			     "%02x%02x%02x%02x%02x%02x%02x%02x}",
-			     device_ctx->class_id.data[3],
-			     device_ctx->class_id.data[2],
-			     device_ctx->class_id.data[1],
-			     device_ctx->class_id.data[0],
-			     device_ctx->class_id.data[5],
-			     device_ctx->class_id.data[4],
-			     device_ctx->class_id.data[7],
-			     device_ctx->class_id.data[6],
-			     device_ctx->class_id.data[8],
-			     device_ctx->class_id.data[9],
-			     device_ctx->class_id.data[10],
-			     device_ctx->class_id.data[11],
-			     device_ctx->class_id.data[12],
-			     device_ctx->class_id.data[13],
-			     device_ctx->class_id.data[14],
-			     device_ctx->class_id.data[15]);
+			     dev->dev_type.data[3],
+			     dev->dev_type.data[2],
+			     dev->dev_type.data[1],
+			     dev->dev_type.data[0],
+			     dev->dev_type.data[5],
+			     dev->dev_type.data[4],
+			     dev->dev_type.data[7],
+			     dev->dev_type.data[6],
+			     dev->dev_type.data[8],
+			     dev->dev_type.data[9],
+			     dev->dev_type.data[10],
+			     dev->dev_type.data[11],
+			     dev->dev_type.data[12],
+			     dev->dev_type.data[13],
+			     dev->dev_type.data[14],
+			     dev->dev_type.data[15]);
 
 	if (ret)
 		return ret;
@@ -834,22 +767,22 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
 	ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={"
 			     "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
 			     "%02x%02x%02x%02x%02x%02x%02x%02x}",
-			     device_ctx->device_id.data[3],
-			     device_ctx->device_id.data[2],
-			     device_ctx->device_id.data[1],
-			     device_ctx->device_id.data[0],
-			     device_ctx->device_id.data[5],
-			     device_ctx->device_id.data[4],
-			     device_ctx->device_id.data[7],
-			     device_ctx->device_id.data[6],
-			     device_ctx->device_id.data[8],
-			     device_ctx->device_id.data[9],
-			     device_ctx->device_id.data[10],
-			     device_ctx->device_id.data[11],
-			     device_ctx->device_id.data[12],
-			     device_ctx->device_id.data[13],
-			     device_ctx->device_id.data[14],
-			     device_ctx->device_id.data[15]);
+			     dev->dev_instance.data[3],
+			     dev->dev_instance.data[2],
+			     dev->dev_instance.data[1],
+			     dev->dev_instance.data[0],
+			     dev->dev_instance.data[5],
+			     dev->dev_instance.data[4],
+			     dev->dev_instance.data[7],
+			     dev->dev_instance.data[6],
+			     dev->dev_instance.data[8],
+			     dev->dev_instance.data[9],
+			     dev->dev_instance.data[10],
+			     dev->dev_instance.data[11],
+			     dev->dev_instance.data[12],
+			     dev->dev_instance.data[13],
+			     dev->dev_instance.data[14],
+			     dev->dev_instance.data[15]);
 	if (ret)
 		return ret;
 
@@ -862,24 +795,18 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
 static int vmbus_match(struct device *device, struct device_driver *driver)
 {
 	int match = 0;
-	struct driver_context *driver_ctx = driver_to_driver_context(driver);
-	struct vm_device *device_ctx = device_to_vm_device(device);
+	struct hv_driver *drv = drv_to_hv_drv(driver);
+	struct hv_device *device_ctx = device_to_hv_device(device);
 
 	/* We found our driver ? */
-	if (memcmp(&device_ctx->class_id, &driver_ctx->class_id,
+	if (memcmp(&device_ctx->dev_type, &drv->dev_type,
 		   sizeof(struct hv_guid)) == 0) {
-		/*
-		 * !! NOTE: The driver_ctx is not a vmbus_drv_ctx. We typecast
-		 * it here to access the struct hv_driver field
-		 */
-		struct vmbus_driver_context *vmbus_drv_ctx =
-			(struct vmbus_driver_context *)driver_ctx;
 
-		device_ctx->device_obj.Driver = &vmbus_drv_ctx->drv_obj;
+		device_ctx->drv = drv->priv;
 		DPRINT_INFO(VMBUS_DRV,
 			    "device object (%p) set to driver object (%p)",
-			    &device_ctx->device_obj,
-			    device_ctx->device_obj.Driver);
+			    &device_ctx,
+			    device_ctx->drv);
 
 		match = 1;
 	}
@@ -895,7 +822,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
  */
 static void vmbus_probe_failed_cb(struct work_struct *context)
 {
-	struct vm_device *device_ctx = (struct vm_device *)context;
+	struct hv_device *device_ctx = (struct hv_device *)context;
 
 	/*
 	 * Kick off the process of unregistering the device.
@@ -912,23 +839,23 @@ static void vmbus_probe_failed_cb(struct work_struct *context)
 static int vmbus_probe(struct device *child_device)
 {
 	int ret = 0;
-	struct driver_context *driver_ctx =
-			driver_to_driver_context(child_device->driver);
-	struct vm_device *device_ctx =
-			device_to_vm_device(child_device);
+	struct hv_driver *drv =
+			drv_to_hv_drv(child_device->driver);
+	struct hv_device *dev = device_to_hv_device(child_device);
 
 	/* Let the specific open-source driver handles the probe if it can */
-	if (driver_ctx->probe) {
-		ret = device_ctx->probe_error = driver_ctx->probe(child_device);
+	if (drv->driver.probe) {
+		ret = dev->probe_error =
+		drv->driver.probe(child_device);
 		if (ret != 0) {
 			DPRINT_ERR(VMBUS_DRV, "probe() failed for device %s "
 				   "(%p) on driver %s (%d)...",
 				   dev_name(child_device), child_device,
 				   child_device->driver->name, ret);
 
-			INIT_WORK(&device_ctx->probe_failed_work_item,
+			INIT_WORK(&dev->probe_failed_work_item,
 				  vmbus_probe_failed_cb);
-			schedule_work(&device_ctx->probe_failed_work_item);
+			schedule_work(&dev->probe_failed_work_item);
 		}
 	} else {
 		DPRINT_ERR(VMBUS_DRV, "probe() method not set for driver - %s",
@@ -944,7 +871,7 @@ static int vmbus_probe(struct device *child_device)
 static int vmbus_remove(struct device *child_device)
 {
 	int ret;
-	struct driver_context *driver_ctx;
+	struct hv_driver *drv;
 
 	/* Special case root bus device */
 	if (child_device->parent == NULL) {
@@ -956,14 +883,14 @@ static int vmbus_remove(struct device *child_device)
 	}
 
 	if (child_device->driver) {
-		driver_ctx = driver_to_driver_context(child_device->driver);
+		drv = drv_to_hv_drv(child_device->driver);
 
 		/*
 		 * Let the specific open-source driver handles the removal if
 		 * it can
 		 */
-		if (driver_ctx->remove) {
-			ret = driver_ctx->remove(child_device);
+		if (drv->driver.remove) {
+			ret = drv->driver.remove(child_device);
 		} else {
 			DPRINT_ERR(VMBUS_DRV,
 				   "remove() method not set for driver - %s",
@@ -980,7 +907,7 @@ static int vmbus_remove(struct device *child_device)
  */
 static void vmbus_shutdown(struct device *child_device)
 {
-	struct driver_context *driver_ctx;
+	struct hv_driver *drv;
 
 	/* Special case root bus device */
 	if (child_device->parent == NULL) {
@@ -995,11 +922,11 @@ static void vmbus_shutdown(struct device *child_device)
 	if (!child_device->driver)
 		return;
 
-	driver_ctx = driver_to_driver_context(child_device->driver);
+	drv = drv_to_hv_drv(child_device->driver);
 
 	/* Let the specific open-source driver handles the removal if it can */
-	if (driver_ctx->shutdown)
-		driver_ctx->shutdown(child_device);
+	if (drv->driver.shutdown)
+		drv->driver.shutdown(child_device);
 
 	return;
 }
@@ -1021,48 +948,28 @@ static void vmbus_bus_release(struct device *device)
  */
 static void vmbus_device_release(struct device *device)
 {
-	struct vm_device *device_ctx = device_to_vm_device(device);
+	struct hv_device *device_ctx = device_to_hv_device(device);
 
 	kfree(device_ctx);
 
 	/* !!DO NOT REFERENCE device_ctx anymore at this point!! */
 }
 
-/*
- * vmbus_msg_dpc - Tasklet routine to handle hypervisor messages
- */
-static void vmbus_msg_dpc(unsigned long data)
-{
-	struct hv_driver *driver = (struct hv_driver *)data;
-
-	/* Call to bus driver to handle interrupt */
-	vmbus_on_msg_dpc(driver);
-}
 
-/*
- * vmbus_event_dpc - Tasklet routine to handle hypervisor events
- */
-static void vmbus_event_dpc(unsigned long data)
-{
-	/* Call to bus driver to handle interrupt */
-	VmbusOnEvents();
-}
 
 static irqreturn_t vmbus_isr(int irq, void *dev_id)
 {
-	struct hv_driver *driver = &g_vmbus_drv.drv_obj;
 	int ret;
 
-	/* Call to bus driver to handle interrupt */
-	ret = vmbus_on_isr(driver);
+	ret = vmbus_on_isr();
 
 	/* Schedules a dpc if necessary */
 	if (ret > 0) {
 		if (test_bit(0, (unsigned long *)&ret))
-			tasklet_schedule(&g_vmbus_drv.msg_dpc);
+			tasklet_schedule(&vmbus_drv.msg_dpc);
 
 		if (test_bit(1, (unsigned long *)&ret))
-			tasklet_schedule(&g_vmbus_drv.event_dpc);
+			tasklet_schedule(&vmbus_drv.event_dpc);
 
 		return IRQ_HANDLED;
 	} else {
diff --git a/drivers/staging/hv/vmbus_packet_format.h b/drivers/staging/hv/vmbus_packet_format.h
index f9f6b4b..c0b2c2b 100644
--- a/drivers/staging/hv/vmbus_packet_format.h
+++ b/drivers/staging/hv/vmbus_packet_format.h
@@ -25,53 +25,53 @@
 #define _VMBUSPACKETFORMAT_H_
 
 struct vmpacket_descriptor {
-	u16 Type;
-	u16 DataOffset8;
-	u16 Length8;
-	u16 Flags;
-	u64 TransactionId;
-} __attribute__((packed));
+	u16 type;
+	u16 offset8;
+	u16 len8;
+	u16 flags;
+	u64 trans_id;
+} __packed;
 
 struct vmpacket_header {
-	u32 PreviousPacketStartOffset;
-	struct vmpacket_descriptor Descriptor;
-} __attribute__((packed));
+	u32 prev_pkt_start_offset;
+	struct vmpacket_descriptor descriptor;
+} __packed;
 
 struct vmtransfer_page_range {
-	u32 ByteCount;
-	u32 ByteOffset;
-} __attribute__((packed));
+	u32 byte_count;
+	u32 byte_offset;
+} __packed;
 
 struct vmtransfer_page_packet_header {
 	struct vmpacket_descriptor d;
-	u16 TransferPageSetId;
-	bool SenderOwnsSet;
-	u8 Reserved;
-	u32 RangeCount;
-	struct vmtransfer_page_range Ranges[1];
-} __attribute__((packed));
+	u16 xfer_pageset_id;
+	bool sender_owns_set;
+	u8 reserved;
+	u32 range_cnt;
+	struct vmtransfer_page_range ranges[1];
+} __packed;
 
 struct vmgpadl_packet_header {
 	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u32 Reserved;
-} __attribute__((packed));
+	u32 gpadl;
+	u32 reserved;
+} __packed;
 
 struct vmadd_remove_transfer_page_set {
 	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u16 TransferPageSetId;
-	u16 Reserved;
-} __attribute__((packed));
+	u32 gpadl;
+	u16 xfer_pageset_id;
+	u16 reserved;
+} __packed;
 
 /*
  * This structure defines a range in guest physical space that can be made to
  * look virtually contiguous.
  */
 struct gpa_range {
-	u32 ByteCount;
-	u32 ByteOffset;
-	u64 PfnArray[0];
+	u32 byte_count;
+	u32 byte_offset;
+	u64 pfn_array[0];
 };
 
 /*
@@ -83,10 +83,10 @@ struct gpa_range {
  */
 struct vmestablish_gpadl {
 	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u32 RangeCount;
-	struct gpa_range Range[1];
-} __attribute__((packed));
+	u32 gpadl;
+	u32 range_cnt;
+	struct gpa_range range[1];
+} __packed;
 
 /*
  * This is the format for a Teardown Gpadl packet, which indicates that the
@@ -94,9 +94,9 @@ struct vmestablish_gpadl {
  */
 struct vmteardown_gpadl {
 	struct vmpacket_descriptor d;
-	u32 Gpadl;
-	u32 Reserved;	/* for alignment to a 8-byte boundary */
-} __attribute__((packed));
+	u32 gpadl;
+	u32 reserved;	/* for alignment to a 8-byte boundary */
+} __packed;
 
 /*
  * This is the format for a GPA-Direct packet, which contains a set of GPA
@@ -104,56 +104,56 @@ struct vmteardown_gpadl {
  */
 struct vmdata_gpa_direct {
 	struct vmpacket_descriptor d;
-	u32 Reserved;
-	u32 RangeCount;
-	struct gpa_range Range[1];
-} __attribute__((packed));
+	u32 reserved;
+	u32 range_cnt;
+	struct gpa_range range[1];
+} __packed;
 
 /* This is the format for a Additional Data Packet. */
 struct vmadditional_data {
 	struct vmpacket_descriptor d;
-	u64 TotalBytes;
-	u32 ByteOffset;
-	u32 ByteCount;
-	unsigned char Data[1];
-} __attribute__((packed));
+	u64 total_bytes;
+	u32 offset;
+	u32 byte_cnt;
+	unsigned char data[1];
+} __packed;
 
 union vmpacket_largest_possible_header {
-	struct vmpacket_descriptor SimpleHeader;
-	struct vmtransfer_page_packet_header TransferPageHeader;
-	struct vmgpadl_packet_header GpadlHeader;
-	struct vmadd_remove_transfer_page_set AddRemoveTransferPageHeader;
-	struct vmestablish_gpadl EstablishGpadlHeader;
-	struct vmteardown_gpadl TeardownGpadlHeader;
-	struct vmdata_gpa_direct DataGpaDirectHeader;
+	struct vmpacket_descriptor simple_hdr;
+	struct vmtransfer_page_packet_header xfer_page_hdr;
+	struct vmgpadl_packet_header gpadl_hdr;
+	struct vmadd_remove_transfer_page_set add_rm_xfer_page_hdr;
+	struct vmestablish_gpadl establish_gpadl_hdr;
+	struct vmteardown_gpadl teardown_gpadl_hdr;
+	struct vmdata_gpa_direct data_gpa_direct_hdr;
 };
 
 #define VMPACKET_DATA_START_ADDRESS(__packet)	\
 	(void *)(((unsigned char *)__packet) +	\
-	 ((struct vmpacket_descriptor)__packet)->DataOffset8 * 8)
+	 ((struct vmpacket_descriptor)__packet)->offset8 * 8)
 
 #define VMPACKET_DATA_LENGTH(__packet)		\
-	((((struct vmpacket_descriptor)__packet)->Length8 -	\
-	  ((struct vmpacket_descriptor)__packet)->DataOffset8) * 8)
+	((((struct vmpacket_descriptor)__packet)->len8 -	\
+	  ((struct vmpacket_descriptor)__packet)->offset8) * 8)
 
 #define VMPACKET_TRANSFER_MODE(__packet)	\
-	(((struct IMPACT)__packet)->Type)
+	(((struct IMPACT)__packet)->type)
 
 enum vmbus_packet_type {
-	VmbusPacketTypeInvalid				= 0x0,
-	VmbusPacketTypeSynch				= 0x1,
-	VmbusPacketTypeAddTransferPageSet		= 0x2,
-	VmbusPacketTypeRemoveTransferPageSet		= 0x3,
-	VmbusPacketTypeEstablishGpadl			= 0x4,
-	VmbusPacketTypeTearDownGpadl			= 0x5,
-	VmbusPacketTypeDataInBand			= 0x6,
-	VmbusPacketTypeDataUsingTransferPages		= 0x7,
-	VmbusPacketTypeDataUsingGpadl			= 0x8,
-	VmbusPacketTypeDataUsingGpaDirect		= 0x9,
-	VmbusPacketTypeCancelRequest			= 0xa,
-	VmbusPacketTypeCompletion			= 0xb,
-	VmbusPacketTypeDataUsingAdditionalPackets	= 0xc,
-	VmbusPacketTypeAdditionalData			= 0xd
+	VM_PKT_INVALID				= 0x0,
+	VM_PKT_SYNCH				= 0x1,
+	VM_PKT_ADD_XFER_PAGESET			= 0x2,
+	VM_PKT_RM_XFER_PAGESET			= 0x3,
+	VM_PKT_ESTABLISH_GPADL			= 0x4,
+	VM_PKT_TEARDOWN_GPADL			= 0x5,
+	VM_PKT_DATA_INBAND			= 0x6,
+	VM_PKT_DATA_USING_XFER_PAGES		= 0x7,
+	VM_PKT_DATA_USING_GPADL			= 0x8,
+	VM_PKT_DATA_USING_GPA_DIRECT		= 0x9,
+	VM_PKT_CANCEL_REQUEST			= 0xa,
+	VM_PKT_COMP				= 0xb,
+	VM_PKT_DATA_USING_ADDITIONAL_PKT	= 0xc,
+	VM_PKT_ADDITIONAL_DATA			= 0xd
 };
 
 #define VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED	1
diff --git a/drivers/staging/hv/vmbus_private.h b/drivers/staging/hv/vmbus_private.h
index 07f6d22..ca050a4 100644
--- a/drivers/staging/hv/vmbus_private.h
+++ b/drivers/staging/hv/vmbus_private.h
@@ -45,19 +45,19 @@
 #define MAX_NUM_CHANNELS_SUPPORTED	256
 
 
-enum VMBUS_CONNECT_STATE {
-	Disconnected,
-	Connecting,
-	Connected,
-	Disconnecting
+enum vmbus_connect_state {
+	DISCONNECTED,
+	CONNECTING,
+	CONNECTED,
+	DISCONNECTING
 };
 
 #define MAX_SIZE_CHANNEL_MESSAGE	HV_MESSAGE_PAYLOAD_BYTE_COUNT
 
-struct VMBUS_CONNECTION {
-	enum VMBUS_CONNECT_STATE ConnectState;
+struct vmbus_connection {
+	enum vmbus_connect_state conn_state;
 
-	atomic_t NextGpadlHandle;
+	atomic_t next_gpadl_handle;
 
 	/*
 	 * Represents channel interrupts. Each bit position represents a
@@ -66,69 +66,68 @@ struct VMBUS_CONNECTION {
 	 * event. The other end receives the port event and parse the
 	 * recvInterruptPage to see which bit is set
 	 */
-	void *InterruptPage;
-	void *SendInterruptPage;
-	void *RecvInterruptPage;
+	void *int_page;
+	void *send_int_page;
+	void *recv_int_page;
 
 	/*
 	 * 2 pages - 1st page for parent->child notification and 2nd
 	 * is child->parent notification
 	 */
-	void *MonitorPages;
-	struct list_head ChannelMsgList;
+	void *monitor_pages;
+	struct list_head chn_msg_list;
 	spinlock_t channelmsg_lock;
 
 	/* List of channels */
-	struct list_head ChannelList;
+	struct list_head chn_list;
 	spinlock_t channel_lock;
 
-	struct workqueue_struct *WorkQueue;
+	struct workqueue_struct *work_queue;
 };
 
 
-struct VMBUS_MSGINFO {
+struct vmbus_msginfo {
 	/* Bookkeeping stuff */
-	struct list_head MsgListEntry;
+	struct list_head msglist_entry;
 
 	/* Synchronize the request/response if needed */
-	struct osd_waitevent *WaitEvent;
+	int wait_condition;
+	wait_queue_head_t  wait_event;
 
 	/* The message itself */
-	unsigned char Msg[0];
+	unsigned char msg[0];
 };
 
 
-extern struct VMBUS_CONNECTION gVmbusConnection;
+extern struct vmbus_connection vmbus_connection;
 
 /* General vmbus interface */
 
-struct hv_device *vmbus_child_device_create(struct hv_guid *deviceType,
-					 struct hv_guid *deviceInstance,
+struct hv_device *vmbus_child_device_create(struct hv_guid *type,
+					 struct hv_guid *instance,
 					 struct vmbus_channel *channel);
 
-int VmbusChildDeviceAdd(struct hv_device *Device);
-int vmbus_child_device_register(struct hv_device *root_device_obj,
-				struct hv_device *child_device_obj);
+int vmbus_child_device_register(struct hv_device *child_device_obj);
 void vmbus_child_device_unregister(struct hv_device *device_obj);
 
 /* static void */
 /* VmbusChildDeviceDestroy( */
 /* struct hv_device *); */
 
-struct vmbus_channel *GetChannelFromRelId(u32 relId);
+struct vmbus_channel *relid2channel(u32 relid);
 
 
 /* Connection interface */
 
-int VmbusConnect(void);
+int vmbus_connect(void);
 
-int VmbusDisconnect(void);
+int vmbus_disconnect(void);
 
-int VmbusPostMessage(void *buffer, size_t bufSize);
+int vmbus_post_msg(void *buffer, size_t buflen);
 
-int VmbusSetEvent(u32 childRelId);
+int vmbus_set_event(u32 child_relid);
 
-void VmbusOnEvents(void);
+void vmbus_on_event(unsigned long data);
 
 
 #endif /* _VMBUS_PRIVATE_H_ */
diff --git a/drivers/staging/hv/vstorage.h b/drivers/staging/hv/vstorage.h
index ae8be84..ebb4d67 100644
--- a/drivers/staging/hv/vstorage.h
+++ b/drivers/staging/hv/vstorage.h
@@ -135,7 +135,7 @@ struct vmstorage_channel_properties {
 	/*  This id is unique for each channel and will correspond with */
 	/*  vendor specific data in the inquirydata */
 	unsigned long long unique_id;
-} __attribute__((packed));
+} __packed;
 
 /*  This structure is sent during the storage protocol negotiations. */
 struct vmstorage_protocol_version {
@@ -149,7 +149,7 @@ struct vmstorage_protocol_version {
 	 * builds.
 	 */
 	unsigned short revision;
-} __attribute__((packed));
+} __packed;
 
 /* Channel Property Flags */
 #define STORAGE_CHANNEL_REMOVABLE_FLAG		0x1
@@ -179,7 +179,7 @@ struct vstor_packet {
 		/* Used during version negotiations. */
 		struct vmstorage_protocol_version version;
 	};
-} __attribute__((packed));
+} __packed;
 
 /* Packet flags */
 /*
diff --git a/drivers/staging/iio/Documentation/dac/max517 b/drivers/staging/iio/Documentation/dac/max517
new file mode 100644
index 0000000..e60ec2f
--- /dev/null
+++ b/drivers/staging/iio/Documentation/dac/max517
@@ -0,0 +1,41 @@
+Kernel driver max517
+====================
+
+Supported chips:
+  * Maxim MAX517, MAX518, MAX519
+    Prefix: 'max517'
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/
+
+Author:
+        Roland Stigge <stigge@antcom.de>
+
+Description
+-----------
+
+The Maxim MAX517/518/519 is an 8-bit DAC on the I2C bus. The following table
+shows the different feature sets of the variants MAX517, MAX518 and MAX519:
+
+Feature                              MAX517 MAX518 MAX519
+--------------------------------------------------------------------------
+One output channel                   X
+Two output channels                         X      X
+Simultaneous output updates                 X      X
+Supply voltage as reference                 X
+Separate reference input             X
+Reference input for each DAC                       X
+
+Via the iio sysfs interface, there are three attributes available: out1_raw,
+out2_raw and out12_raw. With out1_raw and out2_raw, the current output values
+(0..255) of the DACs can be written to the device. out12_raw can be used to set
+both output channel values simultaneously.
+
+With MAX517, only out1_raw is available.
+
+Via out1_scale (and where appropriate, out2_scale), the current scaling factor
+in mV can be read.
+
+When the operating system goes to a power down state, the Power Down function
+of the chip is activated, reducing the supply current to 4uA.
+
+On power-up, the device is in 0V-output state.
diff --git a/drivers/staging/iio/Documentation/generic_buffer.c b/drivers/staging/iio/Documentation/generic_buffer.c
index df23aeb..3cc18ab 100644
--- a/drivers/staging/iio/Documentation/generic_buffer.c
+++ b/drivers/staging/iio/Documentation/generic_buffer.c
@@ -26,11 +26,9 @@
 #include <sys/stat.h>
 #include <sys/dir.h>
 #include <linux/types.h>
+#include <string.h>
 #include "iio_utils.h"
 
-const int buf_len = 128;
-const int num_loops = 2;
-
 /**
  * size_from_channelarray() - calculate the storage size of a scan
  * @channels: the channel info array
@@ -118,6 +116,11 @@ void process_scan(char *data,
 
 int main(int argc, char **argv)
 {
+	unsigned long num_loops = 2;
+	unsigned long timedelay = 1000000;
+	unsigned long buf_len = 128;
+
+
 	int ret, c, i, j, toread;
 
 	FILE *fp_ev;
@@ -134,10 +137,12 @@ int main(int argc, char **argv)
 	int dev_num, trig_num;
 	char *buffer_access, *buffer_event;
 	int scan_size;
+	int noevents = 0;
+	char *dummy;
 
 	struct iio_channel_info *infoarray;
 
-	while ((c = getopt(argc, argv, "t:n:")) != -1) {
+	while ((c = getopt(argc, argv, "l:w:c:et:n:")) != -1) {
 		switch (c) {
 		case 'n':
 			device_name = optarg;
@@ -146,11 +151,26 @@ int main(int argc, char **argv)
 			trigger_name = optarg;
 			datardytrigger = 0;
 			break;
+		case 'e':
+			noevents = 1;
+			break;
+		case 'c':
+			num_loops = strtoul(optarg, &dummy, 10);
+			break;
+		case 'w':
+			timedelay = strtoul(optarg, &dummy, 10);
+			break;
+		case 'l':
+			buf_len = strtoul(optarg, &dummy, 10);
+			break;
 		case '?':
 			return -1;
 		}
 	}
 
+	if (device_name == NULL)
+		return -1;
+
 	/* Find the device requested */
 	dev_num = find_type_by_name(device_name, "device");
 	if (dev_num < 0) {
@@ -260,22 +280,30 @@ int main(int argc, char **argv)
 
 	/* Wait for events 10 times */
 	for (j = 0; j < num_loops; j++) {
-		read_size = fread(&dat, 1, sizeof(struct iio_event_data),
-				  fp_ev);
-		switch (dat.id) {
-		case IIO_EVENT_CODE_RING_100_FULL:
-			toread = buf_len;
-			break;
-		case IIO_EVENT_CODE_RING_75_FULL:
-			toread = buf_len*3/4;
-			break;
-		case IIO_EVENT_CODE_RING_50_FULL:
-			toread = buf_len/2;
-			break;
-		default:
-			printf("Unexpecteded event code\n");
-			continue;
+		if (!noevents) {
+			read_size = fread(&dat,
+					1,
+					sizeof(struct iio_event_data),
+					fp_ev);
+			switch (dat.id) {
+			case IIO_EVENT_CODE_RING_100_FULL:
+				toread = buf_len;
+				break;
+			case IIO_EVENT_CODE_RING_75_FULL:
+				toread = buf_len*3/4;
+				break;
+			case IIO_EVENT_CODE_RING_50_FULL:
+				toread = buf_len/2;
+				break;
+			default:
+				printf("Unexpecteded event code\n");
+				continue;
+			}
+		} else {
+			usleep(timedelay);
+			toread = 64;
 		}
+
 		read_size = read(fp,
 				 data,
 				 toread*scan_size);
diff --git a/drivers/staging/iio/Documentation/iio_utils.h b/drivers/staging/iio/Documentation/iio_utils.h
index 0372424..8095727 100644
--- a/drivers/staging/iio/Documentation/iio_utils.h
+++ b/drivers/staging/iio/Documentation/iio_utils.h
@@ -51,7 +51,7 @@ static int iioutils_break_up_name(const char *full_name,
 	w = working;
 	r = working;
 
-	while(*r != '\0') {
+	while (*r != '\0') {
 		if (!isdigit(*r)) {
 			*w = *r;
 			w++;
@@ -113,7 +113,7 @@ inline int iioutils_get_type(unsigned *is_signed,
 	DIR *dp;
 	char *scan_el_dir, *builtname, *builtname_generic, *filename = 0;
 	char signchar;
-	unsigned sizeint, padint;
+	unsigned padint;
 	const struct dirent *ent;
 
 	ret = asprintf(&scan_el_dir, FORMAT_SCAN_ELEMENTS_DIR, device_dir);
@@ -159,7 +159,7 @@ inline int iioutils_get_type(unsigned *is_signed,
 			fscanf(sysfsfp,
 			       "%c%u/%u", &signchar, bits_used, &padint);
 			*bytes = padint / 8;
-			if (sizeint == 64)
+			if (*bits_used == 64)
 				*mask = ~0;
 			else
 				*mask = (1 << *bits_used) - 1;
@@ -242,6 +242,26 @@ error_ret:
 	return ret;
 }
 
+/**
+ * bsort_channel_array_by_index() - reorder so that the array is in index order
+ *
+ **/
+
+inline void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
+					 int cnt)
+{
+
+	struct iio_channel_info temp;
+	int x, y;
+
+	for (x = 0; x < cnt; x++)
+		for (y = 0; y < (cnt - 1); y++)
+			if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
+				temp = (*ci_array)[y + 1];
+				(*ci_array)[y + 1] = (*ci_array)[y];
+				(*ci_array)[y] = temp;
+			}
+}
 
 /**
  * build_channel_array() - function to figure out what channels are present
@@ -254,7 +274,7 @@ inline int build_channel_array(const char *device_dir,
 {
 	DIR *dp;
 	FILE *sysfsfp;
-	int count = 0, temp, i;
+	int count, temp, i;
 	struct iio_channel_info *current;
 	int ret;
 	const struct dirent *ent;
@@ -293,12 +313,13 @@ inline int build_channel_array(const char *device_dir,
 			fclose(sysfsfp);
 			free(filename);
 		}
-	*ci_array = malloc(sizeof(**ci_array)*(*counter));
+	*ci_array = malloc(sizeof(**ci_array) * (*counter));
 	if (*ci_array == NULL) {
 		ret = -ENOMEM;
 		goto error_close_dir;
 	}
 	seekdir(dp, 0);
+	count = 0;
 	while (ent = readdir(dp), ent != NULL) {
 		if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
 			   "_en") == 0) {
@@ -319,7 +340,13 @@ inline int build_channel_array(const char *device_dir,
 			}
 			fscanf(sysfsfp, "%u", &current->enabled);
 			fclose(sysfsfp);
-			free(filename);
+
+			if (!current->enabled) {
+				free(filename);
+				count--;
+				continue;
+			}
+
 			current->scale = 1.0;
 			current->offset = 0;
 			current->name = strndup(ent->d_name,
@@ -374,31 +401,15 @@ inline int build_channel_array(const char *device_dir,
 						current->generic_name);
 		}
 	}
-	/* reorder so that the array is in index order*/
-	current = malloc(sizeof(**ci_array)**counter);
-	if (current == NULL) {
-		ret = -ENOMEM;
-		goto error_cleanup_array;
-	}
+
 	closedir(dp);
-	count = 0;
-	temp = 0;
-	while (count < *counter)
-		for (i = 0; i < *counter; i++)
-			if ((*ci_array)[i].index == temp) {
-				memcpy(&current[count++],
-				       &(*ci_array)[i],
-				       sizeof(*current));
-				temp++;
-				break;
-			}
-	free(*ci_array);
-	*ci_array = current;
+	/* reorder so that the array is in index order */
+	bsort_channel_array_by_index(ci_array, *counter);
 
 	return 0;
 
 error_cleanup_array:
-	for (i = count - 1;  i >= 0; i++)
+	for (i = count - 1;  i >= 0; i--)
 		free((*ci_array)[i].name);
 	free(*ci_array);
 error_close_dir:
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio b/drivers/staging/iio/Documentation/sysfs-bus-iio
index 2dde97d..4915aee 100644
--- a/drivers/staging/iio/Documentation/sysfs-bus-iio
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio
@@ -53,6 +53,31 @@ Description:
 		When the internal sampling clock can only take a small
 		discrete set of values, this file lists those available.
 
+What:		/sys/bus/iio/devices/deviceX/range
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware dependent ADC Full Scale Range in mVolt.
+
+What:		/sys/bus/iio/devices/deviceX/range_available
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware dependent supported vales for ADC Full Scale Range.
+
+What:		/sys/bus/iio/devices/deviceX/oversampling_ratio
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware dependent ADC oversampling. Controls the sampling ratio
+		of the digital filter if available.
+
+What:		/sys/bus/iio/devices/deviceX/oversampling_ratio_available
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Hardware dependent values supported by the oversampling filter.
+
 What:		/sys/bus/iio/devices/deviceX/inY_raw
 What:		/sys/bus/iio/devices/deviceX/inY_supply_raw
 KernelVersion:	2.6.35
@@ -86,6 +111,12 @@ Description:
 		sensor is associated with one part of a compound device (e.g.
 		a gyroscope axis).
 
+What:		/sys/bus/iio/devices/deviceX/tempX_input
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Scaled temperature measurement in milli degrees Celsius.
+
 What:		/sys/bus/iio/devices/deviceX/accel_x_raw
 What:		/sys/bus/iio/devices/deviceX/accel_y_raw
 What:		/sys/bus/iio/devices/deviceX/accel_z_raw
@@ -168,6 +199,7 @@ Description:
 What:		/sys/bus/iio/devices/deviceX/inY_scale
 What:		/sys/bus/iio/devices/deviceX/inY_supply_scale
 What:		/sys/bus/iio/devices/deviceX/in_scale
+What:		/sys/bus/iio/devices/deviceX/outY_scale
 What:		/sys/bus/iio/devices/deviceX/accel_scale
 What:		/sys/bus/iio/devices/deviceX/accel_peak_scale
 What:		/sys/bus/iio/devices/deviceX/gyro_scale
@@ -222,6 +254,55 @@ Description:
 		If a discrete set of scale values are available, they
 		are listed in this attribute.
 
+What:		/sys/bus/iio/devices/deviceX/outY_raw
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw (unscaled, no bias etc.) output voltage for
+		channel Y.  The number must always be specified and
+		unique if the output corresponds to a single channel.
+
+What:		/sys/bus/iio/devices/deviceX/outY&Z_raw
+KernelVersion:	2.6.37
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Raw (unscaled, no bias etc.) output voltage for an aggregate of
+		channel Y, channel Z, etc.  This interface is available in cases
+		where a single output sets the value for multiple channels
+		simultaneously.
+
+What:		/sys/bus/iio/devices/deviceX/outY_powerdown_mode
+What:		/sys/bus/iio/devices/deviceX/out_powerdown_mode
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Specifies the output powerdown mode.
+		DAC output stage is disconnected from the amplifier and
+		1kohm_to_gnd: connected to ground via an 1kOhm resistor
+		100kohm_to_gnd: connected to ground via an 100kOhm resistor
+		three_state: left floating
+		For a list of available output power down options read
+		outX_powerdown_mode_available. If Y is not present the
+		mode is shared across all outputs.
+
+What:		/sys/bus/iio/devices/deviceX/outY_powerdown_mode_available
+What:		/sys/bus/iio/devices/deviceX/out_powerdown_mode_available
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Lists all available output power down modes.
+		If Y is not present the mode is shared across all outputs.
+
+What:		/sys/bus/iio/devices/deviceX/outY_powerdown
+What:		/sys/bus/iio/devices/deviceX/out_powerdown
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Writing 1 causes output Y to enter the power down mode specified
+		by the corresponding outY_powerdown_mode. Clearing returns to
+		normal operation. Y may be suppressed if all outputs are
+		controlled together.
+
 What:		/sys/bus/iio/devices/deviceX/deviceX:eventY
 KernelVersion:	2.6.35
 Contact:	linux-iio@vger.kernel.org
diff --git a/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs b/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs
new file mode 100644
index 0000000..5235e6c
--- /dev/null
+++ b/drivers/staging/iio/Documentation/sysfs-bus-iio-trigger-sysfs
@@ -0,0 +1,11 @@
+What:		/sys/bus/iio/devices/triggerX/trigger_now
+KernelVersion:	2.6.38
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This file is provided by the iio-trig-sysfs stand-alone trigger
+		driver. Writing this file with any value triggers an event
+		driven driver, associated with this trigger, to capture data
+		into an in kernel buffer. This approach can be valuable during
+		automated testing or in situations, where other trigger methods
+		are not applicable. For example no RTC or spare GPIOs.
+		X is the IIO index of the trigger.
diff --git a/drivers/staging/iio/Kconfig b/drivers/staging/iio/Kconfig
index e2ac07d..6775bf9 100644
--- a/drivers/staging/iio/Kconfig
+++ b/drivers/staging/iio/Kconfig
@@ -29,6 +29,15 @@ config IIO_SW_RING
 	  with the intention that some devices would be able to write
 	  in interrupt context.
 
+config IIO_KFIFO_BUF
+	select IIO_TRIGGER
+	tristate "Industrial I/O buffering based on kfifo"
+	help
+	  A simple fifo based on kfifo.  Use this if you want a fifo
+	  rather than a ring buffer. Note that this currently provides
+	  no buffer events so it is up to userspace to work out how
+	  often to read from the buffer.
+
 endif # IIO_RINGBUFFER
 
 config IIO_TRIGGER
diff --git a/drivers/staging/iio/Makefile b/drivers/staging/iio/Makefile
index f9b5fb2..bb5c95c 100644
--- a/drivers/staging/iio/Makefile
+++ b/drivers/staging/iio/Makefile
@@ -8,6 +8,7 @@ industrialio-$(CONFIG_IIO_RING_BUFFER) += industrialio-ring.o
 industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
 
 obj-$(CONFIG_IIO_SW_RING) += ring_sw.o
+obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
 
 obj-y += accel/
 obj-y += adc/
diff --git a/drivers/staging/iio/accel/Kconfig b/drivers/staging/iio/accel/Kconfig
index a34f1d3..81a33b6 100644
--- a/drivers/staging/iio/accel/Kconfig
+++ b/drivers/staging/iio/accel/Kconfig
@@ -66,12 +66,33 @@ config LIS3L02DQ
 	tristate "ST Microelectronics LIS3L02DQ Accelerometer Driver"
 	depends on SPI
 	select IIO_TRIGGER if IIO_RING_BUFFER
-	select IIO_SW_RING if IIO_RING_BUFFER
+	depends on !IIO_RING_BUFFER || IIO_KFIFO_BUF || IIO_SW_RING
 	help
 	  Say yes here to build SPI support for the ST microelectronics
 	  accelerometer. The driver supplies direct access via sysfs files
 	  and an event interface via a character device.
 
+choice
+	prompt "Buffer type"
+       	depends on LIS3L02DQ && IIO_RING_BUFFER
+
+config LIS3L02DQ_BUF_KFIFO
+       depends on IIO_KFIFO_BUF
+       bool "Simple FIFO"
+       help
+         Kfifo based FIFO.  Does not provide any events so it is up
+	 to userspace to ensure it reads often enough that data is not
+	 lost.
+
+config LIS3L02DQ_BUF_RING_SW
+       depends on IIO_SW_RING
+       bool "IIO Software Ring"
+       help
+         Original IIO ring buffer implementation.  Provides simple
+	 buffer events, half full etc.
+
+endchoice
+
 config SCA3000
 	depends on IIO_RING_BUFFER
 	depends on SPI
diff --git a/drivers/staging/iio/accel/lis3l02dq.h b/drivers/staging/iio/accel/lis3l02dq.h
index 6e73055..579b3a2 100644
--- a/drivers/staging/iio/accel/lis3l02dq.h
+++ b/drivers/staging/iio/accel/lis3l02dq.h
@@ -196,6 +196,16 @@ ssize_t lis3l02dq_read_accel_from_ring(struct device *dev,
 int lis3l02dq_configure_ring(struct iio_dev *indio_dev);
 void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev);
 
+#ifdef CONFIG_LIS3L02DQ_BUF_RING_SW
+#define lis3l02dq_free_buf iio_sw_rb_free
+#define lis3l02dq_alloc_buf iio_sw_rb_allocate
+#define lis3l02dq_register_buf_funcs iio_ring_sw_register_funcs
+#endif
+#ifdef CONFIG_LIS3L02DQ_BUF_KFIFO
+#define lis3l02dq_free_buf iio_kfifo_free
+#define lis3l02dq_alloc_buf iio_kfifo_allocate
+#define lis3l02dq_register_buf_funcs iio_kfifo_register_funcs
+#endif
 #else /* CONFIG_IIO_RING_BUFFER */
 
 static inline void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
diff --git a/drivers/staging/iio/accel/lis3l02dq_ring.c b/drivers/staging/iio/accel/lis3l02dq_ring.c
index 1fd088a..2c461a3 100644
--- a/drivers/staging/iio/accel/lis3l02dq_ring.c
+++ b/drivers/staging/iio/accel/lis3l02dq_ring.c
@@ -13,6 +13,7 @@
 #include "../iio.h"
 #include "../sysfs.h"
 #include "../ring_sw.h"
+#include "../kfifo_buf.h"
 #include "accel.h"
 #include "../trigger.h"
 #include "lis3l02dq.h"
@@ -484,7 +485,7 @@ void lis3l02dq_remove_trigger(struct iio_dev *indio_dev)
 void lis3l02dq_unconfigure_ring(struct iio_dev *indio_dev)
 {
 	kfree(indio_dev->pollfunc);
-	iio_sw_rb_free(indio_dev->ring);
+	lis3l02dq_free_buf(indio_dev->ring);
 }
 
 int lis3l02dq_configure_ring(struct iio_dev *indio_dev)
@@ -495,13 +496,13 @@ int lis3l02dq_configure_ring(struct iio_dev *indio_dev)
 	INIT_WORK(&h->work_trigger_to_ring, lis3l02dq_trigger_bh_to_ring);
 	h->get_ring_element = &lis3l02dq_get_ring_element;
 
-	ring = iio_sw_rb_allocate(indio_dev);
+	ring = lis3l02dq_alloc_buf(indio_dev);
 	if (!ring)
 		return -ENOMEM;
 
 	indio_dev->ring = ring;
 	/* Effectively select the ring buffer implementation */
-	iio_ring_sw_register_funcs(&ring->access);
+	lis3l02dq_register_buf_funcs(&ring->access);
 	ring->bpe = 2;
 	ring->scan_el_attrs = &lis3l02dq_scan_el_group;
 	ring->scan_timestamp = true;
@@ -522,6 +523,6 @@ int lis3l02dq_configure_ring(struct iio_dev *indio_dev)
 	return 0;
 
 error_iio_sw_rb_free:
-	iio_sw_rb_free(indio_dev->ring);
+	lis3l02dq_free_buf(indio_dev->ring);
 	return ret;
 }
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
index 86869cd..6692a3d 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
@@ -49,11 +49,14 @@ config AD7291
 	  temperature sensors.
 
 config AD7298
-	tristate "Analog Devices AD7298 temperature sensor and ADC driver"
+	tristate "Analog Devices AD7298 ADC driver"
 	depends on SPI
 	help
 	  Say yes here to build support for Analog Devices AD7298
-	  temperature sensors and ADC.
+	  8 Channel ADC with temperature sensor.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7298.
 
 config AD7314
 	tristate "Analog Devices AD7314 temperature sensor driver"
@@ -62,6 +65,34 @@ config AD7314
 	  Say yes here to build support for Analog Devices AD7314
 	  temperature sensors.
 
+config AD7606
+	tristate "Analog Devices AD7606 ADC driver"
+	depends on GPIOLIB
+	select IIO_RING_BUFFER
+	select IIO_TRIGGER
+	select IIO_SW_RING
+	help
+	  Say yes here to build support for Analog Devices:
+	  ad7606, ad7606-6, ad7606-4 analog to digital convertors (ADC).
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad7606.
+
+config AD7606_IFACE_PARALLEL
+	tristate "parallel interface support"
+	depends on AD7606
+	help
+	  Say yes here to include parallel interface support on the AD7606
+	  ADC driver.
+
+config AD7606_IFACE_SPI
+	tristate "spi interface support"
+	depends on AD7606
+	depends on SPI
+	help
+	  Say yes here to include parallel interface support on the AD7606
+	  ADC driver.
+
 config AD799X
 	tristate "Analog Devices AD799x ADC driver"
 	depends on I2C
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
index 6f231a2..31067de 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
@@ -7,6 +7,12 @@ max1363-y += max1363_ring.o
 
 obj-$(CONFIG_MAX1363) += max1363.o
 
+ad7606-y := ad7606_core.o
+ad7606-$(CONFIG_IIO_RING_BUFFER) += ad7606_ring.o
+ad7606-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
+ad7606-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
+obj-$(CONFIG_AD7606) += ad7606.o
+
 ad799x-y := ad799x_core.o
 ad799x-$(CONFIG_AD799X_RING_BUFFER) += ad799x_ring.o
 obj-$(CONFIG_AD799X) += ad799x.o
@@ -19,10 +25,13 @@ ad7887-y := ad7887_core.o
 ad7887-$(CONFIG_IIO_RING_BUFFER) += ad7887_ring.o
 obj-$(CONFIG_AD7887) += ad7887.o
 
+ad7298-y := ad7298_core.o
+ad7298-$(CONFIG_IIO_RING_BUFFER) += ad7298_ring.o
+obj-$(CONFIG_AD7298) += ad7298.o
+
 obj-$(CONFIG_AD7150) += ad7150.o
 obj-$(CONFIG_AD7152) += ad7152.o
 obj-$(CONFIG_AD7291) += ad7291.o
-obj-$(CONFIG_AD7298) += ad7298.o
 obj-$(CONFIG_AD7314) += ad7314.o
 obj-$(CONFIG_AD7745) += ad7745.o
 obj-$(CONFIG_AD7816) += ad7816.o
diff --git a/drivers/staging/iio/adc/ad7298.c b/drivers/staging/iio/adc/ad7298.c
deleted file mode 100644
index 1a080c9..0000000
--- a/drivers/staging/iio/adc/ad7298.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * AD7298 digital temperature sensor driver supporting AD7298
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/gpio.h>
-#include <linux/workqueue.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/spi/spi.h>
-#include <linux/rtc.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-
-/*
- * AD7298 command
- */
-#define AD7298_PD			0x1
-#define AD7298_T_AVG_MASK		0x2
-#define AD7298_EXT_REF			0x4
-#define AD7298_T_SENSE_MASK		0x20
-#define AD7298_VOLTAGE_MASK		0x3fc0
-#define AD7298_VOLTAGE_OFFSET		0x6
-#define AD7298_VOLTAGE_LIMIT_COUNT	8
-#define AD7298_REPEAT			0x40
-#define AD7298_WRITE			0x80
-
-/*
- * AD7298 value masks
- */
-#define AD7298_CHANNEL_MASK		0xf000
-#define AD7298_VALUE_MASK		0xfff
-#define AD7298_T_VALUE_SIGN		0x400
-#define AD7298_T_VALUE_FLOAT_OFFSET	2
-#define AD7298_T_VALUE_FLOAT_MASK	0x2
-
-/*
- * struct ad7298_chip_info - chip specifc information
- */
-
-struct ad7298_chip_info {
-	const char *name;
-	struct spi_device *spi_dev;
-	struct iio_dev *indio_dev;
-	u16 command;
-	u16 busy_pin;
-	u8  channels;	/* Active voltage channels */
-};
-
-/*
- * ad7298 register access by SPI
- */
-static int ad7298_spi_write(struct ad7298_chip_info *chip, u16 data)
-{
-	struct spi_device *spi_dev = chip->spi_dev;
-	int ret = 0;
-
-	data |= AD7298_WRITE;
-	data = cpu_to_be16(data);
-	ret = spi_write(spi_dev, (u8 *)&data, sizeof(data));
-	if (ret < 0)
-		dev_err(&spi_dev->dev, "SPI write error\n");
-
-	return ret;
-}
-
-static int ad7298_spi_read(struct ad7298_chip_info *chip, u16 mask, u16 *data)
-{
-	struct spi_device *spi_dev = chip->spi_dev;
-	int ret = 0;
-	u8 count = chip->channels;
-	u16 command;
-	int i;
-
-	if (mask & AD7298_T_SENSE_MASK) {
-		command = chip->command & ~(AD7298_T_AVG_MASK | AD7298_VOLTAGE_MASK);
-		command |= AD7298_T_SENSE_MASK;
-		count = 1;
-	} else if (mask & AD7298_T_AVG_MASK) {
-		command = chip->command & ~AD7298_VOLTAGE_MASK;
-		command |= AD7298_T_SENSE_MASK | AD7298_T_AVG_MASK;
-		count = 2;
-	} else if (mask & AD7298_VOLTAGE_MASK) {
-		command = chip->command & ~(AD7298_T_AVG_MASK | AD7298_T_SENSE_MASK);
-		count = chip->channels;
-	}
-
-	ret = ad7298_spi_write(chip, chip->command);
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI write command error\n");
-		return ret;
-	}
-
-	ret = spi_read(spi_dev, (u8 *)&command, sizeof(command));
-	if (ret < 0) {
-		dev_err(&spi_dev->dev, "SPI read error\n");
-		return ret;
-	}
-
-	i = 10000;
-	while (i && gpio_get_value(chip->busy_pin)) {
-		cpu_relax();
-		i--;
-	}
-	if (!i) {
-		dev_err(&spi_dev->dev, "Always in busy convertion.\n");
-		return -EBUSY;
-	}
-
-	for (i = 0; i < count; i++) {
-		ret = spi_read(spi_dev, (u8 *)&data[i], sizeof(data[i]));
-		if (ret < 0) {
-			dev_err(&spi_dev->dev, "SPI read error\n");
-			return ret;
-		}
-		*data = be16_to_cpu(data[i]);
-	}
-
-	return 0;
-}
-
-static ssize_t ad7298_show_mode(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-
-	if (chip->command & AD7298_REPEAT)
-		return sprintf(buf, "repeat\n");
-	else
-		return sprintf(buf, "normal\n");
-}
-
-static ssize_t ad7298_store_mode(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-
-	if (strcmp(buf, "repeat"))
-		chip->command |= AD7298_REPEAT;
-	else
-		chip->command &= (~AD7298_REPEAT);
-
-	return 1;
-}
-
-static IIO_DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
-		ad7298_show_mode,
-		ad7298_store_mode,
-		0);
-
-static ssize_t ad7298_show_available_modes(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return sprintf(buf, "normal\nrepeat\n");
-}
-
-static IIO_DEVICE_ATTR(available_modes, S_IRUGO, ad7298_show_available_modes, NULL, 0);
-
-static ssize_t ad7298_store_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	u16 command;
-	int ret;
-
-	command = chip->command & ~AD7298_PD;
-
-	ret = ad7298_spi_write(chip, command);
-	if (ret)
-		return -EIO;
-
-	command = chip->command | AD7298_PD;
-
-	ret = ad7298_spi_write(chip, command);
-	if (ret)
-		return -EIO;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(reset, S_IWUSR,
-		NULL,
-		ad7298_store_reset,
-		0);
-
-static ssize_t ad7298_show_ext_ref(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-
-	return sprintf(buf, "%d\n", !!(chip->command & AD7298_EXT_REF));
-}
-
-static ssize_t ad7298_store_ext_ref(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	u16 command;
-	int ret;
-
-	command = chip->command & (~AD7298_EXT_REF);
-	if (strcmp(buf, "1"))
-		command |= AD7298_EXT_REF;
-
-	ret = ad7298_spi_write(chip, command);
-	if (ret)
-		return -EIO;
-
-	chip->command = command;
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(ext_ref, S_IRUGO | S_IWUSR,
-		ad7298_show_ext_ref,
-		ad7298_store_ext_ref,
-		0);
-
-static ssize_t ad7298_show_t_sense(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	u16 data;
-	char sign = ' ';
-	int ret;
-
-	ret = ad7298_spi_read(chip, AD7298_T_SENSE_MASK, &data);
-	if (ret)
-		return -EIO;
-
-	if (data & AD7298_T_VALUE_SIGN) {
-		/* convert supplement to positive value */
-		data = (AD7298_T_VALUE_SIGN << 1) - data;
-		sign = '-';
-	}
-
-	return sprintf(buf, "%c%d.%.2d\n", sign,
-		(data >> AD7298_T_VALUE_FLOAT_OFFSET),
-		(data & AD7298_T_VALUE_FLOAT_MASK) * 25);
-}
-
-static IIO_DEVICE_ATTR(t_sense, S_IRUGO, ad7298_show_t_sense, NULL, 0);
-
-static ssize_t ad7298_show_t_average(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	u16 data[2];
-	char sign = ' ';
-	int ret;
-
-	ret = ad7298_spi_read(chip, AD7298_T_AVG_MASK, data);
-	if (ret)
-		return -EIO;
-
-	if (data[1] & AD7298_T_VALUE_SIGN) {
-		/* convert supplement to positive value */
-		data[1] = (AD7298_T_VALUE_SIGN << 1) - data[1];
-		sign = '-';
-	}
-
-	return sprintf(buf, "%c%d.%.2d\n", sign,
-		(data[1] >> AD7298_T_VALUE_FLOAT_OFFSET),
-		(data[1] & AD7298_T_VALUE_FLOAT_MASK) * 25);
-}
-
-static IIO_DEVICE_ATTR(t_average, S_IRUGO, ad7298_show_t_average, NULL, 0);
-
-static ssize_t ad7298_show_voltage(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	u16 data[AD7298_VOLTAGE_LIMIT_COUNT];
-	int i, size, ret;
-
-	ret = ad7298_spi_read(chip, AD7298_VOLTAGE_MASK, data);
-	if (ret)
-		return -EIO;
-
-	for (i = 0; i < AD7298_VOLTAGE_LIMIT_COUNT; i++) {
-		if (chip->command & (AD7298_T_SENSE_MASK << i)) {
-			ret = sprintf(buf, "channel[%d]=%d\n", i,
-					data[i] & AD7298_VALUE_MASK);
-			if (ret < 0)
-				break;
-			buf += ret;
-			size += ret;
-		}
-	}
-
-	return size;
-}
-
-static IIO_DEVICE_ATTR(voltage, S_IRUGO, ad7298_show_voltage, NULL, 0);
-
-static ssize_t ad7298_show_channel_mask(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-
-	return sprintf(buf, "0x%x\n", (chip->command & AD7298_VOLTAGE_MASK) >>
-			AD7298_VOLTAGE_OFFSET);
-}
-
-static ssize_t ad7298_store_channel_mask(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	unsigned long data;
-	int i, ret;
-
-	ret = strict_strtoul(buf, 16, &data);
-	if (ret || data > 0xff)
-		return -EINVAL;
-
-	chip->command &= (~AD7298_VOLTAGE_MASK);
-	chip->command |= data << AD7298_VOLTAGE_OFFSET;
-
-	for (i = 0, chip->channels = 0; i < AD7298_VOLTAGE_LIMIT_COUNT; i++) {
-		if (chip->command & (AD7298_T_SENSE_MASK << i))
-			chip->channels++;
-	}
-
-	return ret;
-}
-
-static IIO_DEVICE_ATTR(channel_mask, S_IRUGO | S_IWUSR,
-		ad7298_show_channel_mask,
-		ad7298_store_channel_mask,
-		0);
-
-static ssize_t ad7298_show_name(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *dev_info = dev_get_drvdata(dev);
-	struct ad7298_chip_info *chip = dev_info->dev_data;
-	return sprintf(buf, "%s\n", chip->name);
-}
-
-static IIO_DEVICE_ATTR(name, S_IRUGO, ad7298_show_name, NULL, 0);
-
-static struct attribute *ad7298_attributes[] = {
-	&iio_dev_attr_available_modes.dev_attr.attr,
-	&iio_dev_attr_mode.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
-	&iio_dev_attr_ext_ref.dev_attr.attr,
-	&iio_dev_attr_t_sense.dev_attr.attr,
-	&iio_dev_attr_t_average.dev_attr.attr,
-	&iio_dev_attr_voltage.dev_attr.attr,
-	&iio_dev_attr_channel_mask.dev_attr.attr,
-	&iio_dev_attr_name.dev_attr.attr,
-	NULL,
-};
-
-static const struct attribute_group ad7298_attribute_group = {
-	.attrs = ad7298_attributes,
-};
-
-/*
- * device probe and remove
- */
-static int __devinit ad7298_probe(struct spi_device *spi_dev)
-{
-	struct ad7298_chip_info *chip;
-	unsigned short *pins = spi_dev->dev.platform_data;
-	int ret = 0;
-
-	chip = kzalloc(sizeof(struct ad7298_chip_info), GFP_KERNEL);
-
-	if (chip == NULL)
-		return -ENOMEM;
-
-	/* this is only used for device removal purposes */
-	dev_set_drvdata(&spi_dev->dev, chip);
-
-	chip->spi_dev = spi_dev;
-	chip->name = spi_dev->modalias;
-	chip->busy_pin = pins[0];
-
-	ret = gpio_request(chip->busy_pin, chip->name);
-	if (ret) {
-		dev_err(&spi_dev->dev, "Fail to request busy gpio PIN %d.\n",
-			chip->busy_pin);
-		goto error_free_chip;
-	}
-	gpio_direction_input(chip->busy_pin);
-
-	chip->indio_dev = iio_allocate_device();
-	if (chip->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_gpio;
-	}
-
-	chip->indio_dev->dev.parent = &spi_dev->dev;
-	chip->indio_dev->attrs = &ad7298_attribute_group;
-	chip->indio_dev->dev_data = (void *)chip;
-	chip->indio_dev->driver_module = THIS_MODULE;
-	chip->indio_dev->modes = INDIO_DIRECT_MODE;
-
-	ret = iio_device_register(chip->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
-	dev_info(&spi_dev->dev, "%s temperature sensor and ADC registered.\n",
-			 chip->name);
-
-	return 0;
-
-error_free_dev:
-	iio_free_device(chip->indio_dev);
-error_free_gpio:
-	gpio_free(chip->busy_pin);
-error_free_chip:
-	kfree(chip);
-
-	return ret;
-}
-
-static int __devexit ad7298_remove(struct spi_device *spi_dev)
-{
-	struct ad7298_chip_info *chip = dev_get_drvdata(&spi_dev->dev);
-	struct iio_dev *indio_dev = chip->indio_dev;
-
-	dev_set_drvdata(&spi_dev->dev, NULL);
-	iio_device_unregister(indio_dev);
-	iio_free_device(chip->indio_dev);
-	gpio_free(chip->busy_pin);
-	kfree(chip);
-
-	return 0;
-}
-
-static const struct spi_device_id ad7298_id[] = {
-	{ "ad7298", 0 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(spi, ad7298_id);
-
-static struct spi_driver ad7298_driver = {
-	.driver = {
-		.name = "ad7298",
-		.bus = &spi_bus_type,
-		.owner = THIS_MODULE,
-	},
-	.probe = ad7298_probe,
-	.remove = __devexit_p(ad7298_remove),
-	.id_table = ad7298_id,
-};
-
-static __init int ad7298_init(void)
-{
-	return spi_register_driver(&ad7298_driver);
-}
-
-static __exit void ad7298_exit(void)
-{
-	spi_unregister_driver(&ad7298_driver);
-}
-
-MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
-MODULE_DESCRIPTION("Analog Devices AD7298 digital"
-			" temperature sensor and ADC driver");
-MODULE_LICENSE("GPL v2");
-
-module_init(ad7298_init);
-module_exit(ad7298_exit);
diff --git a/drivers/staging/iio/adc/ad7298.h b/drivers/staging/iio/adc/ad7298.h
new file mode 100644
index 0000000..fe7ed77
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7298.h
@@ -0,0 +1,80 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef IIO_ADC_AD7298_H_
+#define IIO_ADC_AD7298_H_
+
+#define AD7298_WRITE	(1 << 15) /* write to the control register */
+#define AD7298_REPEAT	(1 << 14) /* repeated conversion enable */
+#define AD7298_CH(x)	(1 << (13 - (x))) /* channel select */
+#define AD7298_TSENSE	(1 << 5) /* temperature conversion enable */
+#define AD7298_EXTREF	(1 << 2) /* external reference enable */
+#define AD7298_TAVG	(1 << 1) /* temperature sensor averaging enable */
+#define AD7298_PDD	(1 << 0) /* partial power down enable */
+
+#define AD7298_CH_MASK	(AD7298_CH0 | AD7298_CH1 | AD7298_CH2 | AD7298_CH3 | \
+			AD7298_CH4 | AD7298_CH5 | AD7298_CH6 | AD7298_CH7)
+
+#define AD7298_MAX_CHAN		8
+#define AD7298_BITS		12
+#define AD7298_STORAGE_BITS	16
+#define AD7298_INTREF_mV	2500
+
+#define RES_MASK(bits)	((1 << (bits)) - 1)
+
+/*
+ * TODO: struct ad7298_platform_data needs to go into include/linux/iio
+ */
+
+struct ad7298_platform_data {
+	/* External Vref voltage applied */
+	u16				vref_mv;
+};
+
+struct ad7298_state {
+	struct iio_dev			*indio_dev;
+	struct spi_device		*spi;
+	struct regulator		*reg;
+	struct work_struct		poll_work;
+	atomic_t			protect_ring;
+	size_t				d_size;
+	u16				int_vref_mv;
+	unsigned			ext_ref;
+	struct spi_transfer		ring_xfer[10];
+	struct spi_transfer		scan_single_xfer[3];
+	struct spi_message		ring_msg;
+	struct spi_message		scan_single_msg;
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	unsigned short			rx_buf[8] ____cacheline_aligned;
+	unsigned short			tx_buf[2];
+};
+
+#ifdef CONFIG_IIO_RING_BUFFER
+int ad7298_scan_from_ring(struct ad7298_state *st, long ch);
+int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev);
+void ad7298_ring_cleanup(struct iio_dev *indio_dev);
+#else /* CONFIG_IIO_RING_BUFFER */
+static inline int ad7298_scan_from_ring(struct ad7298_state *st, long ch)
+{
+	return 0;
+}
+
+static inline int
+ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+	return 0;
+}
+
+static inline void ad7298_ring_cleanup(struct iio_dev *indio_dev)
+{
+}
+#endif /* CONFIG_IIO_RING_BUFFER */
+#endif /* IIO_ADC_AD7298_H_ */
diff --git a/drivers/staging/iio/adc/ad7298_core.c b/drivers/staging/iio/adc/ad7298_core.c
new file mode 100644
index 0000000..2e9154e
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7298_core.c
@@ -0,0 +1,287 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "adc.h"
+
+#include "ad7298.h"
+
+static int ad7298_scan_direct(struct ad7298_state *st, unsigned ch)
+{
+	int ret;
+	st->tx_buf[0] = cpu_to_be16(AD7298_WRITE | st->ext_ref |
+				   (AD7298_CH(0) >> ch));
+
+	ret = spi_sync(st->spi, &st->scan_single_msg);
+	if (ret)
+		return ret;
+
+	return be16_to_cpu(st->rx_buf[0]);
+}
+
+static ssize_t ad7298_scan(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7298_state *st = dev_info->dev_data;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	int ret;
+
+	mutex_lock(&dev_info->mlock);
+	if (iio_ring_enabled(dev_info))
+		ret = ad7298_scan_from_ring(st, this_attr->address);
+	else
+		ret = ad7298_scan_direct(st, this_attr->address);
+	mutex_unlock(&dev_info->mlock);
+
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", ret & RES_MASK(AD7298_BITS));
+}
+
+static IIO_DEV_ATTR_IN_RAW(0, ad7298_scan, 0);
+static IIO_DEV_ATTR_IN_RAW(1, ad7298_scan, 1);
+static IIO_DEV_ATTR_IN_RAW(2, ad7298_scan, 2);
+static IIO_DEV_ATTR_IN_RAW(3, ad7298_scan, 3);
+static IIO_DEV_ATTR_IN_RAW(4, ad7298_scan, 4);
+static IIO_DEV_ATTR_IN_RAW(5, ad7298_scan, 5);
+static IIO_DEV_ATTR_IN_RAW(6, ad7298_scan, 6);
+static IIO_DEV_ATTR_IN_RAW(7, ad7298_scan, 7);
+
+static ssize_t ad7298_show_temp(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7298_state *st = iio_dev_get_devdata(dev_info);
+	int tmp;
+
+	tmp = cpu_to_be16(AD7298_WRITE | AD7298_TSENSE |
+			  AD7298_TAVG | st->ext_ref);
+
+	mutex_lock(&dev_info->mlock);
+	spi_write(st->spi, (u8 *)&tmp, 2);
+	tmp = 0;
+	spi_write(st->spi, (u8 *)&tmp, 2);
+	usleep_range(101, 1000); /* sleep > 100us */
+	spi_read(st->spi, (u8 *)&tmp, 2);
+	mutex_unlock(&dev_info->mlock);
+
+	tmp = be16_to_cpu(tmp) & RES_MASK(AD7298_BITS);
+
+	/*
+	 * One LSB of the ADC corresponds to 0.25 deg C.
+	 * The temperature reading is in 12-bit twos complement format
+	 */
+
+	if (tmp & (1 << (AD7298_BITS - 1))) {
+		tmp = (4096 - tmp) * 250;
+		tmp -= (2 * tmp);
+
+	} else {
+		tmp *= 250; /* temperature in milli degrees Celsius */
+	}
+
+	return sprintf(buf, "%d\n", tmp);
+}
+
+static IIO_DEVICE_ATTR(temp0_input, S_IRUGO, ad7298_show_temp, NULL, 0);
+
+static ssize_t ad7298_show_scale(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7298_state *st = iio_dev_get_devdata(dev_info);
+	/* Corresponds to Vref / 2^(bits) */
+	unsigned int scale_uv = (st->int_vref_mv * 1000) >> AD7298_BITS;
+
+	return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
+}
+static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7298_show_scale, NULL, 0);
+
+static ssize_t ad7298_show_name(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7298_state *st = iio_dev_get_devdata(dev_info);
+
+	return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
+}
+static IIO_DEVICE_ATTR(name, S_IRUGO, ad7298_show_name, NULL, 0);
+
+static struct attribute *ad7298_attributes[] = {
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
+	&iio_dev_attr_in2_raw.dev_attr.attr,
+	&iio_dev_attr_in3_raw.dev_attr.attr,
+	&iio_dev_attr_in4_raw.dev_attr.attr,
+	&iio_dev_attr_in5_raw.dev_attr.attr,
+	&iio_dev_attr_in6_raw.dev_attr.attr,
+	&iio_dev_attr_in7_raw.dev_attr.attr,
+	&iio_dev_attr_in_scale.dev_attr.attr,
+	&iio_dev_attr_temp0_input.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group ad7298_attribute_group = {
+	.attrs = ad7298_attributes,
+};
+
+static int __devinit ad7298_probe(struct spi_device *spi)
+{
+	struct ad7298_platform_data *pdata = spi->dev.platform_data;
+	struct ad7298_state *st;
+	int ret;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	st->reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(st->reg)) {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+	}
+
+	spi_set_drvdata(spi, st);
+
+	atomic_set(&st->protect_ring, 0);
+	st->spi = spi;
+
+	st->indio_dev = iio_allocate_device();
+	if (st->indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_disable_reg;
+	}
+
+	st->indio_dev->dev.parent = &spi->dev;
+	st->indio_dev->attrs = &ad7298_attribute_group;
+	st->indio_dev->dev_data = (void *)(st);
+	st->indio_dev->driver_module = THIS_MODULE;
+	st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+	/* 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].tx_buf = &st->tx_buf[1];
+	st->scan_single_xfer[1].len = 2;
+	st->scan_single_xfer[1].cs_change = 1;
+	st->scan_single_xfer[2].rx_buf = &st->rx_buf[0];
+	st->scan_single_xfer[2].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);
+	spi_message_add_tail(&st->scan_single_xfer[2], &st->scan_single_msg);
+
+	if (pdata && pdata->vref_mv) {
+		st->int_vref_mv = pdata->vref_mv;
+		st->ext_ref = AD7298_EXTREF;
+	} else {
+		st->int_vref_mv = AD7298_INTREF_mV;
+	}
+
+	ret = ad7298_register_ring_funcs_and_init(st->indio_dev);
+	if (ret)
+		goto error_free_device;
+
+	ret = iio_device_register(st->indio_dev);
+	if (ret)
+		goto error_free_device;
+
+	ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+	if (ret)
+		goto error_cleanup_ring;
+	return 0;
+
+error_cleanup_ring:
+	ad7298_ring_cleanup(st->indio_dev);
+	iio_device_unregister(st->indio_dev);
+error_free_device:
+	iio_free_device(st->indio_dev);
+error_disable_reg:
+	if (!IS_ERR(st->reg))
+		regulator_disable(st->reg);
+error_put_reg:
+	if (!IS_ERR(st->reg))
+		regulator_put(st->reg);
+	kfree(st);
+error_ret:
+	return ret;
+}
+
+static int __devexit ad7298_remove(struct spi_device *spi)
+{
+	struct ad7298_state *st = spi_get_drvdata(spi);
+	struct iio_dev *indio_dev = st->indio_dev;
+
+	iio_ring_buffer_unregister(indio_dev->ring);
+	ad7298_ring_cleanup(indio_dev);
+	iio_device_unregister(indio_dev);
+	if (!IS_ERR(st->reg)) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+	kfree(st);
+	return 0;
+}
+
+static const struct spi_device_id ad7298_id[] = {
+	{"ad7298", 0},
+	{}
+};
+
+static struct spi_driver ad7298_driver = {
+	.driver = {
+		.name	= "ad7298",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ad7298_probe,
+	.remove		= __devexit_p(ad7298_remove),
+	.id_table	= ad7298_id,
+};
+
+static int __init ad7298_init(void)
+{
+	return spi_register_driver(&ad7298_driver);
+}
+module_init(ad7298_init);
+
+static void __exit ad7298_exit(void)
+{
+	spi_unregister_driver(&ad7298_driver);
+}
+module_exit(ad7298_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7298 ADC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad7298");
diff --git a/drivers/staging/iio/adc/ad7298_ring.c b/drivers/staging/iio/adc/ad7298_ring.c
new file mode 100644
index 0000000..19d1ace
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7298_ring.c
@@ -0,0 +1,258 @@
+/*
+ * AD7298 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/spi/spi.h>
+
+#include "../iio.h"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+#include "../trigger.h"
+#include "../sysfs.h"
+
+#include "ad7298.h"
+
+static IIO_SCAN_EL_C(in0, 0, 0, NULL);
+static IIO_SCAN_EL_C(in1, 1, 0, NULL);
+static IIO_SCAN_EL_C(in2, 2, 0, NULL);
+static IIO_SCAN_EL_C(in3, 3, 0, NULL);
+static IIO_SCAN_EL_C(in4, 4, 0, NULL);
+static IIO_SCAN_EL_C(in5, 5, 0, NULL);
+static IIO_SCAN_EL_C(in6, 6, 0, NULL);
+static IIO_SCAN_EL_C(in7, 7, 0, NULL);
+
+static IIO_SCAN_EL_TIMESTAMP(8);
+static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
+
+static IIO_CONST_ATTR(in_type, "u12/16") ;
+
+static struct attribute *ad7298_scan_el_attrs[] = {
+	&iio_scan_el_in0.dev_attr.attr,
+	&iio_const_attr_in0_index.dev_attr.attr,
+	&iio_scan_el_in1.dev_attr.attr,
+	&iio_const_attr_in1_index.dev_attr.attr,
+	&iio_scan_el_in2.dev_attr.attr,
+	&iio_const_attr_in2_index.dev_attr.attr,
+	&iio_scan_el_in3.dev_attr.attr,
+	&iio_const_attr_in3_index.dev_attr.attr,
+	&iio_scan_el_in4.dev_attr.attr,
+	&iio_const_attr_in4_index.dev_attr.attr,
+	&iio_scan_el_in5.dev_attr.attr,
+	&iio_const_attr_in5_index.dev_attr.attr,
+	&iio_scan_el_in6.dev_attr.attr,
+	&iio_const_attr_in6_index.dev_attr.attr,
+	&iio_scan_el_in7.dev_attr.attr,
+	&iio_const_attr_in7_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
+	&iio_const_attr_in_type.dev_attr.attr,
+	NULL,
+};
+
+static struct attribute_group ad7298_scan_el_group = {
+	.name = "scan_elements",
+	.attrs = ad7298_scan_el_attrs,
+};
+
+int ad7298_scan_from_ring(struct ad7298_state *st, long ch)
+{
+	struct iio_ring_buffer *ring = st->indio_dev->ring;
+	int ret;
+	u16 *ring_data;
+
+	if (!(ring->scan_mask & (1 << ch))) {
+		ret = -EBUSY;
+		goto error_ret;
+	}
+
+	ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+	if (ring_data == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	ret = ring->access.read_last(ring, (u8 *) ring_data);
+	if (ret)
+		goto error_free_ring_data;
+
+	ret = be16_to_cpu(ring_data[ch]);
+
+error_free_ring_data:
+	kfree(ring_data);
+error_ret:
+	return ret;
+}
+
+/**
+ * ad7298_ring_preenable() setup the parameters of the ring before enabling
+ *
+ * The complex nature of the setting of the number of bytes per datum is due
+ * to this driver currently ensuring that the timestamp is stored at an 8
+ * byte boundary.
+ **/
+static int ad7298_ring_preenable(struct iio_dev *indio_dev)
+{
+	struct ad7298_state *st = indio_dev->dev_data;
+	struct iio_ring_buffer *ring = indio_dev->ring;
+	size_t d_size;
+	int i, m;
+	unsigned short command;
+
+	d_size = ring->scan_count * (AD7298_STORAGE_BITS / 8);
+
+	if (ring->scan_timestamp) {
+		d_size += sizeof(s64);
+
+		if (d_size % sizeof(s64))
+			d_size += sizeof(s64) - (d_size % sizeof(s64));
+	}
+
+	if (ring->access.set_bytes_per_datum)
+		ring->access.set_bytes_per_datum(ring, d_size);
+
+	st->d_size = d_size;
+
+	command = AD7298_WRITE | st->ext_ref;
+
+	for (i = 0, m = AD7298_CH(0); i < AD7298_MAX_CHAN; i++, m >>= 1)
+		if (ring->scan_mask & (1 << i))
+			command |= m;
+
+	st->tx_buf[0] = cpu_to_be16(command);
+
+	/* build spi ring message */
+	st->ring_xfer[0].tx_buf = &st->tx_buf[0];
+	st->ring_xfer[0].len = 2;
+	st->ring_xfer[0].cs_change = 1;
+	st->ring_xfer[1].tx_buf = &st->tx_buf[1];
+	st->ring_xfer[1].len = 2;
+	st->ring_xfer[1].cs_change = 1;
+
+	spi_message_init(&st->ring_msg);
+	spi_message_add_tail(&st->ring_xfer[0], &st->ring_msg);
+	spi_message_add_tail(&st->ring_xfer[1], &st->ring_msg);
+
+	for (i = 0; i < ring->scan_count; i++) {
+		st->ring_xfer[i + 2].rx_buf = &st->rx_buf[i];
+		st->ring_xfer[i + 2].len = 2;
+		st->ring_xfer[i + 2].cs_change = 1;
+		spi_message_add_tail(&st->ring_xfer[i + 2], &st->ring_msg);
+	}
+	/* make sure last transfer cs_change is not set */
+	st->ring_xfer[i + 1].cs_change = 0;
+
+	return 0;
+}
+
+/**
+ * ad7298_poll_func_th() th of trigger launched polling to ring buffer
+ *
+ * As sampling only occurs on spi comms occuring, leave timestamping until
+ * then.  Some triggers will generate their own time stamp.  Currently
+ * there is no way of notifying them when no one cares.
+ **/
+static void ad7298_poll_func_th(struct iio_dev *indio_dev, s64 time)
+{
+	struct ad7298_state *st = indio_dev->dev_data;
+
+	schedule_work(&st->poll_work);
+	return;
+}
+
+/**
+ * ad7298_poll_bh_to_ring() bh of trigger launched polling to ring buffer
+ * @work_s:	the work struct through which this was scheduled
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ * I think the one copy of this at a time was to avoid problems if the
+ * trigger was set far too high and the reads then locked up the computer.
+ **/
+static void ad7298_poll_bh_to_ring(struct work_struct *work_s)
+{
+	struct ad7298_state *st = container_of(work_s, struct ad7298_state,
+						  poll_work);
+	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+	struct iio_ring_buffer *ring = indio_dev->ring;
+	s64 time_ns;
+	__u16 buf[16];
+	int b_sent, i;
+
+	/* Ensure only one copy of this function running at a time */
+	if (atomic_inc_return(&st->protect_ring) > 1)
+		return;
+
+	b_sent = spi_sync(st->spi, &st->ring_msg);
+	if (b_sent)
+		goto done;
+
+	if (ring->scan_timestamp) {
+		time_ns = iio_get_time_ns();
+		memcpy((u8 *)buf + st->d_size - sizeof(s64),
+			&time_ns, sizeof(time_ns));
+	}
+
+	for (i = 0; i < ring->scan_count; i++)
+		buf[i] = be16_to_cpu(st->rx_buf[i]);
+
+	indio_dev->ring->access.store_to(&sw_ring->buf, (u8 *)buf, time_ns);
+done:
+	atomic_dec(&st->protect_ring);
+}
+
+int ad7298_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+	struct ad7298_state *st = indio_dev->dev_data;
+	int ret;
+
+	indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+	if (!indio_dev->ring) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	/* Effectively select the ring buffer implementation */
+	iio_ring_sw_register_funcs(&indio_dev->ring->access);
+	ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7298_poll_func_th);
+	if (ret)
+		goto error_deallocate_sw_rb;
+
+	/* Ring buffer functions - here trigger setup related */
+
+	indio_dev->ring->preenable = &ad7298_ring_preenable;
+	indio_dev->ring->postenable = &iio_triggered_ring_postenable;
+	indio_dev->ring->predisable = &iio_triggered_ring_predisable;
+	indio_dev->ring->scan_el_attrs = &ad7298_scan_el_group;
+	indio_dev->ring->scan_timestamp = true;
+
+	INIT_WORK(&st->poll_work, &ad7298_poll_bh_to_ring);
+
+	/* Flag that polled ring buffering is possible */
+	indio_dev->modes |= INDIO_RING_TRIGGERED;
+	return 0;
+error_deallocate_sw_rb:
+	iio_sw_rb_free(indio_dev->ring);
+error_ret:
+	return ret;
+}
+
+void ad7298_ring_cleanup(struct iio_dev *indio_dev)
+{
+	if (indio_dev->trig) {
+		iio_put_trigger(indio_dev->trig);
+		iio_trigger_dettach_poll_func(indio_dev->trig,
+					      indio_dev->pollfunc);
+	}
+	kfree(indio_dev->pollfunc);
+	iio_sw_rb_free(indio_dev->ring);
+}
diff --git a/drivers/staging/iio/adc/ad7476.h b/drivers/staging/iio/adc/ad7476.h
index b51b49e..f917e9c 100644
--- a/drivers/staging/iio/adc/ad7476.h
+++ b/drivers/staging/iio/adc/ad7476.h
@@ -33,6 +33,7 @@ struct ad7476_state {
 	struct regulator		*reg;
 	struct work_struct		poll_work;
 	atomic_t			protect_ring;
+	size_t				d_size;
 	u16				int_vref_mv;
 	struct spi_transfer		xfer;
 	struct spi_message		msg;
diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c
index b8b54da..d263904 100644
--- a/drivers/staging/iio/adc/ad7476_core.c
+++ b/drivers/staging/iio/adc/ad7476_core.c
@@ -190,7 +190,7 @@ static int __devinit ad7476_probe(struct spi_device *spi)
 		goto error_disable_reg;
 	}
 
-	/* Estabilish that the iio_dev is a child of the i2c device */
+	/* Establish that the iio_dev is a child of the spi device */
 	st->indio_dev->dev.parent = &spi->dev;
 	st->indio_dev->attrs = &ad7476_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
diff --git a/drivers/staging/iio/adc/ad7476_ring.c b/drivers/staging/iio/adc/ad7476_ring.c
index 85de142..1d654c8 100644
--- a/drivers/staging/iio/adc/ad7476_ring.c
+++ b/drivers/staging/iio/adc/ad7476_ring.c
@@ -26,6 +26,8 @@
 #include "ad7476.h"
 
 static IIO_SCAN_EL_C(in0, 0, 0, NULL);
+static IIO_SCAN_EL_TIMESTAMP(1);
+static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
 
 static ssize_t ad7476_show_type(struct device *dev,
 				struct device_attribute *attr,
@@ -44,6 +46,9 @@ static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad7476_show_type, NULL, 0);
 static struct attribute *ad7476_scan_el_attrs[] = {
 	&iio_scan_el_in0.dev_attr.attr,
 	&iio_const_attr_in0_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
 	&iio_dev_attr_in_type.dev_attr.attr,
 	NULL,
 };
@@ -86,16 +91,21 @@ error_ret:
 static int ad7476_ring_preenable(struct iio_dev *indio_dev)
 {
 	struct ad7476_state *st = indio_dev->dev_data;
-	size_t d_size;
+	struct iio_ring_buffer *ring = indio_dev->ring;
 
-	if (indio_dev->ring->access.set_bytes_per_datum) {
-		d_size = st->chip_info->storagebits / 8 + sizeof(s64);
-		if (d_size % 8)
-			d_size += 8 - (d_size % 8);
-		indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
-							    d_size);
+	st->d_size = ring->scan_count * st->chip_info->storagebits / 8;
+
+	if (ring->scan_timestamp) {
+		st->d_size += sizeof(s64);
+
+		if (st->d_size % sizeof(s64))
+			st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
 	}
 
+	if (indio_dev->ring->access.set_bytes_per_datum)
+		indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+							    st->d_size);
+
 	return 0;
 }
 
@@ -131,18 +141,12 @@ static void ad7476_poll_bh_to_ring(struct work_struct *work_s)
 	s64 time_ns;
 	__u8 *rxbuf;
 	int b_sent;
-	size_t d_size;
-
-	/* Ensure the timestamp is 8 byte aligned */
-	d_size = st->chip_info->storagebits / 8 + sizeof(s64);
-	if (d_size % sizeof(s64))
-		d_size += sizeof(s64) - (d_size % sizeof(s64));
 
 	/* Ensure only one copy of this function running at a time */
 	if (atomic_inc_return(&st->protect_ring) > 1)
 		return;
 
-	rxbuf = kzalloc(d_size,	GFP_KERNEL);
+	rxbuf = kzalloc(st->d_size, GFP_KERNEL);
 	if (rxbuf == NULL)
 		return;
 
@@ -152,7 +156,9 @@ static void ad7476_poll_bh_to_ring(struct work_struct *work_s)
 
 	time_ns = iio_get_time_ns();
 
-	memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+	if (indio_dev->ring->scan_timestamp)
+		memcpy(rxbuf + st->d_size - sizeof(s64),
+			&time_ns, sizeof(time_ns));
 
 	indio_dev->ring->access.store_to(&sw_ring->buf, rxbuf, time_ns);
 done:
@@ -182,6 +188,7 @@ int ad7476_register_ring_funcs_and_init(struct iio_dev *indio_dev)
 	indio_dev->ring->postenable = &iio_triggered_ring_postenable;
 	indio_dev->ring->predisable = &iio_triggered_ring_predisable;
 	indio_dev->ring->scan_el_attrs = &ad7476_scan_el_group;
+	indio_dev->ring->scan_timestamp = true;
 
 	INIT_WORK(&st->poll_work, &ad7476_poll_bh_to_ring);
 
diff --git a/drivers/staging/iio/adc/ad7606.h b/drivers/staging/iio/adc/ad7606.h
new file mode 100644
index 0000000..338bade
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7606.h
@@ -0,0 +1,117 @@
+/*
+ * AD7606 ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#ifndef IIO_ADC_AD7606_H_
+#define IIO_ADC_AD7606_H_
+
+/*
+ * TODO: struct ad7606_platform_data needs to go into include/linux/iio
+ */
+
+/**
+ * struct ad7606_platform_data - platform/board specifc information
+ * @default_os:		default oversampling value {0, 2, 4, 8, 16, 32, 64}
+ * @default_range:	default range +/-{5000, 10000} mVolt
+ * @gpio_convst:	number of gpio connected to the CONVST pin
+ * @gpio_reset:		gpio connected to the RESET pin, if not used set to -1
+ * @gpio_range:		gpio connected to the RANGE pin, if not used set to -1
+ * @gpio_os0:		gpio connected to the OS0 pin, if not used set to -1
+ * @gpio_os1:		gpio connected to the OS1 pin, if not used set to -1
+ * @gpio_os2:		gpio connected to the OS2 pin, if not used set to -1
+ * @gpio_frstdata:	gpio connected to the FRSTDAT pin, if not used set to -1
+ * @gpio_stby:		gpio connected to the STBY pin, if not used set to -1
+ */
+
+struct ad7606_platform_data {
+	unsigned			default_os;
+	unsigned			default_range;
+	unsigned			gpio_convst;
+	unsigned			gpio_reset;
+	unsigned			gpio_range;
+	unsigned			gpio_os0;
+	unsigned			gpio_os1;
+	unsigned			gpio_os2;
+	unsigned			gpio_frstdata;
+	unsigned			gpio_stby;
+};
+
+/**
+ * struct ad7606_chip_info - chip specifc information
+ * @name:		indentification string for chip
+ * @bits:		accuracy of the adc in bits
+ * @bits:		output coding [s]igned or [u]nsigned
+ * @int_vref_mv:	the internal reference voltage
+ * @num_channels:	number of physical inputs on chip
+ */
+
+struct ad7606_chip_info {
+	char				name[10];
+	u8				bits;
+	char				sign;
+	u16				int_vref_mv;
+	unsigned			num_channels;
+};
+
+/**
+ * struct ad7606_state - driver instance specific data
+ */
+
+struct ad7606_state {
+	struct iio_dev			*indio_dev;
+	struct device			*dev;
+	const struct ad7606_chip_info	*chip_info;
+	struct ad7606_platform_data	*pdata;
+	struct regulator		*reg;
+	struct work_struct		poll_work;
+	wait_queue_head_t		wq_data_avail;
+	atomic_t			protect_ring;
+	size_t				d_size;
+	const struct ad7606_bus_ops	*bops;
+	int				irq;
+	unsigned			id;
+	unsigned			range;
+	unsigned			oversampling;
+	bool				done;
+	bool				have_frstdata;
+	bool				have_os;
+	bool				have_stby;
+	bool				have_reset;
+	bool				have_range;
+	void __iomem			*base_address;
+
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+
+	unsigned short			data[8] ____cacheline_aligned;
+};
+
+struct ad7606_bus_ops {
+	/* more methods added in future? */
+	int (*read_block)(struct device *, int, void *);
+};
+
+void ad7606_suspend(struct ad7606_state *st);
+void ad7606_resume(struct ad7606_state *st);
+struct ad7606_state *ad7606_probe(struct device *dev, int irq,
+			      void __iomem *base_address, unsigned id,
+			      const struct ad7606_bus_ops *bops);
+int ad7606_remove(struct ad7606_state *st);
+int ad7606_reset(struct ad7606_state *st);
+
+enum ad7606_supported_device_ids {
+	ID_AD7606_8,
+	ID_AD7606_6,
+	ID_AD7606_4
+};
+
+int ad7606_scan_from_ring(struct ad7606_state *st, unsigned ch);
+int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev);
+void ad7606_ring_cleanup(struct iio_dev *indio_dev);
+#endif /* IIO_ADC_AD7606_H_ */
diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c
new file mode 100644
index 0000000..4c700f0
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7606_core.c
@@ -0,0 +1,556 @@
+/*
+ * AD7606 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/list.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+
+#include "../iio.h"
+#include "../sysfs.h"
+#include "../ring_generic.h"
+#include "adc.h"
+
+#include "ad7606.h"
+
+int ad7606_reset(struct ad7606_state *st)
+{
+	if (st->have_reset) {
+		gpio_set_value(st->pdata->gpio_reset, 1);
+		ndelay(100); /* t_reset >= 100ns */
+		gpio_set_value(st->pdata->gpio_reset, 0);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static int ad7606_scan_direct(struct ad7606_state *st, unsigned ch)
+{
+	int ret;
+
+	st->done = false;
+	gpio_set_value(st->pdata->gpio_convst, 1);
+
+	ret = wait_event_interruptible(st->wq_data_avail, st->done);
+	if (ret)
+		goto error_ret;
+
+	if (st->have_frstdata) {
+		ret = st->bops->read_block(st->dev, 1, st->data);
+		if (ret)
+			goto error_ret;
+		if (!gpio_get_value(st->pdata->gpio_frstdata)) {
+			/* This should never happen */
+			ad7606_reset(st);
+			ret = -EIO;
+			goto error_ret;
+		}
+		ret = st->bops->read_block(st->dev,
+			st->chip_info->num_channels - 1, &st->data[1]);
+		if (ret)
+			goto error_ret;
+	} else {
+		ret = st->bops->read_block(st->dev,
+			st->chip_info->num_channels, st->data);
+		if (ret)
+			goto error_ret;
+	}
+
+	ret = st->data[ch];
+
+error_ret:
+	gpio_set_value(st->pdata->gpio_convst, 0);
+
+	return ret;
+}
+
+static ssize_t ad7606_scan(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = dev_info->dev_data;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
+	int ret;
+
+	mutex_lock(&dev_info->mlock);
+	if (iio_ring_enabled(dev_info))
+		ret = ad7606_scan_from_ring(st, this_attr->address);
+	else
+		ret = ad7606_scan_direct(st, this_attr->address);
+	mutex_unlock(&dev_info->mlock);
+
+	if (ret < 0)
+		return ret;
+
+	return sprintf(buf, "%d\n", (short) ret);
+}
+
+static IIO_DEV_ATTR_IN_RAW(0, ad7606_scan, 0);
+static IIO_DEV_ATTR_IN_RAW(1, ad7606_scan, 1);
+static IIO_DEV_ATTR_IN_RAW(2, ad7606_scan, 2);
+static IIO_DEV_ATTR_IN_RAW(3, ad7606_scan, 3);
+static IIO_DEV_ATTR_IN_RAW(4, ad7606_scan, 4);
+static IIO_DEV_ATTR_IN_RAW(5, ad7606_scan, 5);
+static IIO_DEV_ATTR_IN_RAW(6, ad7606_scan, 6);
+static IIO_DEV_ATTR_IN_RAW(7, ad7606_scan, 7);
+
+static ssize_t ad7606_show_scale(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	/* Driver currently only support internal vref */
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+	unsigned int scale_uv = (st->range * 1000 * 2) >> st->chip_info->bits;
+
+	return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
+}
+static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7606_show_scale, NULL, 0);
+
+static ssize_t ad7606_show_name(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+
+	return sprintf(buf, "%s\n", st->chip_info->name);
+}
+
+static IIO_DEVICE_ATTR(name, S_IRUGO, ad7606_show_name, NULL, 0);
+
+static ssize_t ad7606_show_range(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+
+	return sprintf(buf, "%u\n", st->range);
+}
+
+static ssize_t ad7606_store_range(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+	unsigned long lval;
+
+	if (strict_strtoul(buf, 10, &lval))
+		return -EINVAL;
+	if (!(lval == 5000 || lval == 10000)) {
+		dev_err(dev, "range is not supported\n");
+		return -EINVAL;
+	}
+	mutex_lock(&dev_info->mlock);
+	gpio_set_value(st->pdata->gpio_range, lval == 10000);
+	st->range = lval;
+	mutex_unlock(&dev_info->mlock);
+
+	return count;
+}
+
+static IIO_DEVICE_ATTR(range, S_IRUGO | S_IWUSR, \
+		       ad7606_show_range, ad7606_store_range, 0);
+static IIO_CONST_ATTR(range_available, "5000 10000");
+
+static ssize_t ad7606_show_oversampling_ratio(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+
+	return sprintf(buf, "%u\n", st->oversampling);
+}
+
+static int ad7606_oversampling_get_index(unsigned val)
+{
+	unsigned char supported[] = {0, 2, 4, 8, 16, 32, 64};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(supported); i++)
+		if (val == supported[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static ssize_t ad7606_store_oversampling_ratio(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+	unsigned long lval;
+	int ret;
+
+	if (strict_strtoul(buf, 10, &lval))
+		return -EINVAL;
+
+	ret = ad7606_oversampling_get_index(lval);
+	if (ret < 0) {
+		dev_err(dev, "oversampling %lu is not supported\n", lval);
+		return ret;
+	}
+
+	mutex_lock(&dev_info->mlock);
+	gpio_set_value(st->pdata->gpio_os0, (ret >> 0) & 1);
+	gpio_set_value(st->pdata->gpio_os1, (ret >> 1) & 1);
+	gpio_set_value(st->pdata->gpio_os1, (ret >> 2) & 1);
+	st->oversampling = lval;
+	mutex_unlock(&dev_info->mlock);
+
+	return count;
+}
+
+static IIO_DEVICE_ATTR(oversampling_ratio, S_IRUGO | S_IWUSR,
+		       ad7606_show_oversampling_ratio,
+		       ad7606_store_oversampling_ratio, 0);
+static IIO_CONST_ATTR(oversampling_ratio_available, "0 2 4 8 16 32 64");
+
+static struct attribute *ad7606_attributes[] = {
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
+	&iio_dev_attr_in2_raw.dev_attr.attr,
+	&iio_dev_attr_in3_raw.dev_attr.attr,
+	&iio_dev_attr_in4_raw.dev_attr.attr,
+	&iio_dev_attr_in5_raw.dev_attr.attr,
+	&iio_dev_attr_in6_raw.dev_attr.attr,
+	&iio_dev_attr_in7_raw.dev_attr.attr,
+	&iio_dev_attr_in_scale.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
+	&iio_dev_attr_range.dev_attr.attr,
+	&iio_const_attr_range_available.dev_attr.attr,
+	&iio_dev_attr_oversampling_ratio.dev_attr.attr,
+	&iio_const_attr_oversampling_ratio_available.dev_attr.attr,
+	NULL,
+};
+
+static mode_t ad7606_attr_is_visible(struct kobject *kobj,
+				     struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad7606_state *st = iio_dev_get_devdata(dev_info);
+
+	mode_t mode = attr->mode;
+
+	if (st->chip_info->num_channels <= 6 &&
+		(attr == &iio_dev_attr_in7_raw.dev_attr.attr ||
+		attr == &iio_dev_attr_in6_raw.dev_attr.attr))
+		mode = 0;
+	else if (st->chip_info->num_channels <= 4 &&
+		(attr == &iio_dev_attr_in5_raw.dev_attr.attr ||
+		attr == &iio_dev_attr_in4_raw.dev_attr.attr))
+		mode = 0;
+	else if (!st->have_os &&
+		(attr == &iio_dev_attr_oversampling_ratio.dev_attr.attr ||
+		attr ==
+		&iio_const_attr_oversampling_ratio_available.dev_attr.attr))
+		mode = 0;
+	else if (!st->have_range &&
+		(attr == &iio_dev_attr_range.dev_attr.attr ||
+		attr == &iio_const_attr_range_available.dev_attr.attr))
+			mode = 0;
+
+	return mode;
+}
+
+static const struct attribute_group ad7606_attribute_group = {
+	.attrs = ad7606_attributes,
+	.is_visible = ad7606_attr_is_visible,
+};
+
+static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
+	/*
+	 * More devices added in future
+	 */
+	[ID_AD7606_8] = {
+		.name = "ad7606",
+		.bits = 16,
+		.sign = IIO_SCAN_EL_TYPE_SIGNED,
+		.int_vref_mv = 2500,
+		.num_channels = 8,
+	},
+	[ID_AD7606_6] = {
+		.name = "ad7606-6",
+		.bits = 16,
+		.sign = IIO_SCAN_EL_TYPE_SIGNED,
+		.int_vref_mv = 2500,
+		.num_channels = 6,
+	},
+	[ID_AD7606_4] = {
+		.name = "ad7606-4",
+		.bits = 16,
+		.sign = IIO_SCAN_EL_TYPE_SIGNED,
+		.int_vref_mv = 2500,
+		.num_channels = 4,
+	},
+};
+
+static int ad7606_request_gpios(struct ad7606_state *st)
+{
+	struct gpio gpio_array[3] = {
+		[0] = {
+			.gpio =  st->pdata->gpio_os0,
+			.flags = GPIOF_DIR_OUT | ((st->oversampling & 1) ?
+				 GPIOF_INIT_HIGH : GPIOF_INIT_LOW),
+			.label = "AD7606_OS0",
+		},
+		[1] = {
+			.gpio =  st->pdata->gpio_os1,
+			.flags = GPIOF_DIR_OUT | ((st->oversampling & 2) ?
+				 GPIOF_INIT_HIGH : GPIOF_INIT_LOW),
+			.label = "AD7606_OS1",
+		},
+		[2] = {
+			.gpio =  st->pdata->gpio_os2,
+			.flags = GPIOF_DIR_OUT | ((st->oversampling & 4) ?
+				 GPIOF_INIT_HIGH : GPIOF_INIT_LOW),
+			.label = "AD7606_OS2",
+		},
+	};
+	int ret;
+
+	ret = gpio_request_one(st->pdata->gpio_convst, GPIOF_OUT_INIT_LOW,
+			       "AD7606_CONVST");
+	if (ret) {
+		dev_err(st->dev, "failed to request GPIO CONVST\n");
+		return ret;
+	}
+
+	ret = gpio_request_array(gpio_array, ARRAY_SIZE(gpio_array));
+	if (!ret) {
+		st->have_os = true;
+	}
+
+	ret = gpio_request_one(st->pdata->gpio_reset, GPIOF_OUT_INIT_LOW,
+			       "AD7606_RESET");
+	if (!ret)
+		st->have_reset = true;
+
+	ret = gpio_request_one(st->pdata->gpio_range, GPIOF_DIR_OUT |
+			       ((st->range == 10000) ? GPIOF_INIT_HIGH :
+			       	GPIOF_INIT_LOW), "AD7606_RANGE");
+	if (!ret)
+		st->have_range = true;
+
+	ret = gpio_request_one(st->pdata->gpio_stby, GPIOF_OUT_INIT_HIGH,
+			       "AD7606_STBY");
+	if (!ret)
+		st->have_stby = true;
+
+	if (gpio_is_valid(st->pdata->gpio_frstdata)) {
+		ret = gpio_request_one(st->pdata->gpio_frstdata, GPIOF_IN,
+				       "AD7606_FRSTDATA");
+		if (!ret)
+			st->have_frstdata = true;
+	}
+
+	return 0;
+}
+
+static void ad7606_free_gpios(struct ad7606_state *st)
+{
+	if (st->have_range)
+		gpio_free(st->pdata->gpio_range);
+
+	if (st->have_stby)
+		gpio_free(st->pdata->gpio_stby);
+
+	if (st->have_os) {
+		gpio_free(st->pdata->gpio_os0);
+		gpio_free(st->pdata->gpio_os1);
+		gpio_free(st->pdata->gpio_os2);
+	}
+
+	if (st->have_reset)
+		gpio_free(st->pdata->gpio_reset);
+
+	if (st->have_frstdata)
+		gpio_free(st->pdata->gpio_frstdata);
+
+	gpio_free(st->pdata->gpio_convst);
+}
+
+/**
+ *  Interrupt handler
+ */
+static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
+{
+	struct ad7606_state *st = dev_id;
+
+	if (iio_ring_enabled(st->indio_dev)) {
+		if (!work_pending(&st->poll_work))
+			schedule_work(&st->poll_work);
+	} else {
+		st->done = true;
+		wake_up_interruptible(&st->wq_data_avail);
+	}
+
+	return IRQ_HANDLED;
+};
+
+struct ad7606_state *ad7606_probe(struct device *dev, int irq,
+			      void __iomem *base_address,
+			      unsigned id,
+			      const struct ad7606_bus_ops *bops)
+{
+	struct ad7606_platform_data *pdata = dev->platform_data;
+	struct ad7606_state *st;
+	int ret;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	st->dev = dev;
+	st->id = id;
+	st->irq = irq;
+	st->bops = bops;
+	st->base_address = base_address;
+	st->range = pdata->default_range == 10000 ? 10000 : 5000;
+
+	ret = ad7606_oversampling_get_index(pdata->default_os);
+	if (ret < 0) {
+		dev_warn(dev, "oversampling %d is not supported\n",
+			 pdata->default_os);
+		st->oversampling = 0;
+	} else {
+		st->oversampling = pdata->default_os;
+	}
+
+	st->reg = regulator_get(dev, "vcc");
+	if (!IS_ERR(st->reg)) {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+	}
+
+	st->pdata = pdata;
+	st->chip_info = &ad7606_chip_info_tbl[id];
+
+	atomic_set(&st->protect_ring, 0);
+
+	st->indio_dev = iio_allocate_device();
+	if (st->indio_dev == NULL) {
+		ret = -ENOMEM;
+		goto error_disable_reg;
+	}
+
+	st->indio_dev->dev.parent = dev;
+	st->indio_dev->attrs = &ad7606_attribute_group;
+	st->indio_dev->dev_data = (void *)(st);
+	st->indio_dev->driver_module = THIS_MODULE;
+	st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+	init_waitqueue_head(&st->wq_data_avail);
+
+	ret = ad7606_request_gpios(st);
+	if (ret)
+		goto error_free_device;
+
+	ret = ad7606_reset(st);
+	if (ret)
+		dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
+
+	ret = request_irq(st->irq, ad7606_interrupt,
+		IRQF_TRIGGER_FALLING, st->chip_info->name, st);
+	if (ret)
+		goto error_free_gpios;
+
+	ret = ad7606_register_ring_funcs_and_init(st->indio_dev);
+	if (ret)
+		goto error_free_irq;
+
+	ret = iio_device_register(st->indio_dev);
+	if (ret)
+		goto error_free_irq;
+
+	ret = iio_ring_buffer_register(st->indio_dev->ring, 0);
+	if (ret)
+		goto error_cleanup_ring;
+
+	return st;
+
+error_cleanup_ring:
+	ad7606_ring_cleanup(st->indio_dev);
+	iio_device_unregister(st->indio_dev);
+
+error_free_irq:
+	free_irq(st->irq, st);
+
+error_free_gpios:
+	ad7606_free_gpios(st);
+
+error_free_device:
+	iio_free_device(st->indio_dev);
+
+error_disable_reg:
+	if (!IS_ERR(st->reg))
+		regulator_disable(st->reg);
+error_put_reg:
+	if (!IS_ERR(st->reg))
+		regulator_put(st->reg);
+	kfree(st);
+error_ret:
+	return ERR_PTR(ret);
+}
+
+int ad7606_remove(struct ad7606_state *st)
+{
+	struct iio_dev *indio_dev = st->indio_dev;
+	iio_ring_buffer_unregister(indio_dev->ring);
+	ad7606_ring_cleanup(indio_dev);
+	iio_device_unregister(indio_dev);
+	free_irq(st->irq, st);
+	if (!IS_ERR(st->reg)) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+
+	ad7606_free_gpios(st);
+
+	kfree(st);
+	return 0;
+}
+
+void ad7606_suspend(struct ad7606_state *st)
+{
+	if (st->have_stby) {
+		if (st->have_range)
+			gpio_set_value(st->pdata->gpio_range, 1);
+		gpio_set_value(st->pdata->gpio_stby, 0);
+	}
+}
+
+void ad7606_resume(struct ad7606_state *st)
+{
+	if (st->have_stby) {
+		if (st->have_range)
+			gpio_set_value(st->pdata->gpio_range,
+					st->range == 10000);
+
+		gpio_set_value(st->pdata->gpio_stby, 1);
+		ad7606_reset(st);
+	}
+}
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/ad7606_par.c b/drivers/staging/iio/adc/ad7606_par.c
new file mode 100644
index 0000000..43a554c
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7606_par.c
@@ -0,0 +1,188 @@
+/*
+ * AD7606 Parallel Interface ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include "ad7606.h"
+
+static int ad7606_par16_read_block(struct device *dev,
+				 int count, void *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ad7606_state *st = platform_get_drvdata(pdev);
+
+	insw((unsigned long) st->base_address, buf, count);
+
+	return 0;
+}
+
+static const struct ad7606_bus_ops ad7606_par16_bops = {
+	.read_block	= ad7606_par16_read_block,
+};
+
+static int ad7606_par8_read_block(struct device *dev,
+				 int count, void *buf)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ad7606_state *st = platform_get_drvdata(pdev);
+
+	insb((unsigned long) st->base_address, buf, count * 2);
+
+	return 0;
+}
+
+static const struct ad7606_bus_ops ad7606_par8_bops = {
+	.read_block	= ad7606_par8_read_block,
+};
+
+static int __devinit ad7606_par_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct ad7606_state *st;
+	void __iomem *addr;
+	resource_size_t remap_size;
+	int ret, irq;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq\n");
+		return -ENODEV;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	remap_size = resource_size(res);
+
+	/* Request the regions */
+	if (!request_mem_region(res->start, remap_size, "iio-ad7606")) {
+		ret = -EBUSY;
+		goto out1;
+	}
+	addr = ioremap(res->start, remap_size);
+	if (!addr) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	st = ad7606_probe(&pdev->dev, irq, addr,
+			  platform_get_device_id(pdev)->driver_data,
+			  remap_size > 1 ? &ad7606_par16_bops :
+			  &ad7606_par8_bops);
+
+	if (IS_ERR(st))  {
+		ret = PTR_ERR(st);
+		goto out2;
+	}
+
+	platform_set_drvdata(pdev, st);
+
+	return 0;
+
+out2:
+	iounmap(addr);
+out1:
+	release_mem_region(res->start, remap_size);
+
+	return ret;
+}
+
+static int __devexit ad7606_par_remove(struct platform_device *pdev)
+{
+	struct ad7606_state *st = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	ad7606_remove(st);
+
+	iounmap(st->base_address);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ad7606_par_suspend(struct device *dev)
+{
+	struct ad7606_state *st = dev_get_drvdata(dev);
+
+	ad7606_suspend(st);
+
+	return 0;
+}
+
+static int ad7606_par_resume(struct device *dev)
+{
+	struct ad7606_state *st = dev_get_drvdata(dev);
+
+	ad7606_resume(st);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ad7606_pm_ops = {
+	.suspend = ad7606_par_suspend,
+	.resume  = ad7606_par_resume,
+};
+#define AD7606_PAR_PM_OPS (&ad7606_pm_ops)
+
+#else
+#define AD7606_PAR_PM_OPS NULL
+#endif  /* CONFIG_PM */
+
+static struct platform_device_id ad7606_driver_ids[] = {
+	{
+		.name		= "ad7606-8",
+		.driver_data	= ID_AD7606_8,
+	}, {
+		.name		= "ad7606-6",
+		.driver_data	= ID_AD7606_6,
+	}, {
+		.name		= "ad7606-4",
+		.driver_data	= ID_AD7606_4,
+	},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
+
+static struct platform_driver ad7606_driver = {
+	.probe = ad7606_par_probe,
+	.remove	= __devexit_p(ad7606_par_remove),
+	.id_table = ad7606_driver_ids,
+	.driver = {
+		.name	 = "ad7606",
+		.owner	= THIS_MODULE,
+		.pm    = AD7606_PAR_PM_OPS,
+	},
+};
+
+static int __init ad7606_init(void)
+{
+	return platform_driver_register(&ad7606_driver);
+}
+
+static void __exit ad7606_cleanup(void)
+{
+	platform_driver_unregister(&ad7606_driver);
+}
+
+module_init(ad7606_init);
+module_exit(ad7606_cleanup);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ad7606_par");
diff --git a/drivers/staging/iio/adc/ad7606_ring.c b/drivers/staging/iio/adc/ad7606_ring.c
new file mode 100644
index 0000000..b32cb0d
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7606_ring.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include "../iio.h"
+#include "../ring_generic.h"
+#include "../ring_sw.h"
+#include "../trigger.h"
+#include "../sysfs.h"
+
+#include "ad7606.h"
+
+static IIO_SCAN_EL_C(in0, 0, 0, NULL);
+static IIO_SCAN_EL_C(in1, 1, 0, NULL);
+static IIO_SCAN_EL_C(in2, 2, 0, NULL);
+static IIO_SCAN_EL_C(in3, 3, 0, NULL);
+static IIO_SCAN_EL_C(in4, 4, 0, NULL);
+static IIO_SCAN_EL_C(in5, 5, 0, NULL);
+static IIO_SCAN_EL_C(in6, 6, 0, NULL);
+static IIO_SCAN_EL_C(in7, 7, 0, NULL);
+
+static IIO_SCAN_EL_TIMESTAMP(8);
+static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
+
+static ssize_t ad7606_show_type(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = ring->indio_dev;
+	struct ad7606_state *st = indio_dev->dev_data;
+
+	return sprintf(buf, "%c%d/%d\n", st->chip_info->sign,
+		       st->chip_info->bits, st->chip_info->bits);
+}
+static IIO_DEVICE_ATTR(in_type, S_IRUGO, ad7606_show_type, NULL, 0);
+
+static struct attribute *ad7606_scan_el_attrs[] = {
+	&iio_scan_el_in0.dev_attr.attr,
+	&iio_const_attr_in0_index.dev_attr.attr,
+	&iio_scan_el_in1.dev_attr.attr,
+	&iio_const_attr_in1_index.dev_attr.attr,
+	&iio_scan_el_in2.dev_attr.attr,
+	&iio_const_attr_in2_index.dev_attr.attr,
+	&iio_scan_el_in3.dev_attr.attr,
+	&iio_const_attr_in3_index.dev_attr.attr,
+	&iio_scan_el_in4.dev_attr.attr,
+	&iio_const_attr_in4_index.dev_attr.attr,
+	&iio_scan_el_in5.dev_attr.attr,
+	&iio_const_attr_in5_index.dev_attr.attr,
+	&iio_scan_el_in6.dev_attr.attr,
+	&iio_const_attr_in6_index.dev_attr.attr,
+	&iio_scan_el_in7.dev_attr.attr,
+	&iio_const_attr_in7_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
+	&iio_dev_attr_in_type.dev_attr.attr,
+	NULL,
+};
+
+static mode_t ad7606_scan_el_attr_is_visible(struct kobject *kobj,
+				     struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct iio_ring_buffer *ring = dev_get_drvdata(dev);
+	struct iio_dev *indio_dev = ring->indio_dev;
+	struct ad7606_state *st = indio_dev->dev_data;
+
+	mode_t mode = attr->mode;
+
+	if (st->chip_info->num_channels <= 6 &&
+		(attr == &iio_scan_el_in7.dev_attr.attr ||
+		attr == &iio_const_attr_in7_index.dev_attr.attr ||
+		attr == &iio_scan_el_in6.dev_attr.attr ||
+		attr == &iio_const_attr_in6_index.dev_attr.attr))
+		mode = 0;
+	else if (st->chip_info->num_channels <= 4 &&
+		(attr == &iio_scan_el_in5.dev_attr.attr ||
+		attr == &iio_const_attr_in5_index.dev_attr.attr ||
+		attr == &iio_scan_el_in4.dev_attr.attr ||
+		attr == &iio_const_attr_in4_index.dev_attr.attr))
+		mode = 0;
+
+	return mode;
+}
+
+static struct attribute_group ad7606_scan_el_group = {
+	.name = "scan_elements",
+	.attrs = ad7606_scan_el_attrs,
+	.is_visible = ad7606_scan_el_attr_is_visible,
+};
+
+int ad7606_scan_from_ring(struct ad7606_state *st, unsigned ch)
+{
+	struct iio_ring_buffer *ring = st->indio_dev->ring;
+	int ret;
+	u16 *ring_data;
+
+	ring_data = kmalloc(ring->access.get_bytes_per_datum(ring), GFP_KERNEL);
+	if (ring_data == NULL) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+	ret = ring->access.read_last(ring, (u8 *) ring_data);
+	if (ret)
+		goto error_free_ring_data;
+
+	ret = ring_data[ch];
+
+error_free_ring_data:
+	kfree(ring_data);
+error_ret:
+	return ret;
+}
+
+/**
+ * ad7606_ring_preenable() setup the parameters of the ring before enabling
+ *
+ * The complex nature of the setting of the nuber of bytes per datum is due
+ * to this driver currently ensuring that the timestamp is stored at an 8
+ * byte boundary.
+ **/
+static int ad7606_ring_preenable(struct iio_dev *indio_dev)
+{
+	struct ad7606_state *st = indio_dev->dev_data;
+	struct iio_ring_buffer *ring = indio_dev->ring;
+	size_t d_size;
+
+	d_size = st->chip_info->num_channels *
+		 st->chip_info->bits / 8;
+
+	if (ring->scan_timestamp) {
+		d_size += sizeof(s64);
+
+		if (d_size % sizeof(s64))
+			d_size += sizeof(s64) - (d_size % sizeof(s64));
+	}
+
+	if (ring->access.set_bytes_per_datum)
+		ring->access.set_bytes_per_datum(ring, d_size);
+
+	st->d_size = d_size;
+
+	return 0;
+}
+
+/**
+ * ad7606_poll_func_th() th of trigger launched polling to ring buffer
+ *
+ **/
+static void ad7606_poll_func_th(struct iio_dev *indio_dev, s64 time)
+{
+	struct ad7606_state *st = indio_dev->dev_data;
+	gpio_set_value(st->pdata->gpio_convst, 1);
+
+	return;
+}
+/**
+ * ad7606_poll_bh_to_ring() bh of trigger launched polling to ring buffer
+ * @work_s:	the work struct through which this was scheduled
+ *
+ * Currently there is no option in this driver to disable the saving of
+ * timestamps within the ring.
+ * I think the one copy of this at a time was to avoid problems if the
+ * trigger was set far too high and the reads then locked up the computer.
+ **/
+static void ad7606_poll_bh_to_ring(struct work_struct *work_s)
+{
+	struct ad7606_state *st = container_of(work_s, struct ad7606_state,
+						poll_work);
+	struct iio_dev *indio_dev = st->indio_dev;
+	struct iio_sw_ring_buffer *sw_ring = iio_to_sw_ring(indio_dev->ring);
+	struct iio_ring_buffer *ring = indio_dev->ring;
+	s64 time_ns;
+	__u8 *buf;
+	int ret;
+
+	/* Ensure only one copy of this function running at a time */
+	if (atomic_inc_return(&st->protect_ring) > 1)
+		return;
+
+	buf = kzalloc(st->d_size, GFP_KERNEL);
+	if (buf == NULL)
+		return;
+
+	if (st->have_frstdata) {
+		ret = st->bops->read_block(st->dev, 1, buf);
+		if (ret)
+			goto done;
+		if (!gpio_get_value(st->pdata->gpio_frstdata)) {
+			/* This should never happen. However
+			 * some signal glitch caused by bad PCB desgin or
+			 * electrostatic discharge, could cause an extra read
+			 * or clock. This allows recovery.
+			 */
+			ad7606_reset(st);
+			goto done;
+		}
+		ret = st->bops->read_block(st->dev,
+			st->chip_info->num_channels - 1, buf + 2);
+		if (ret)
+			goto done;
+	} else {
+		ret = st->bops->read_block(st->dev,
+			st->chip_info->num_channels, buf);
+		if (ret)
+			goto done;
+	}
+
+	time_ns = iio_get_time_ns();
+
+	if (ring->scan_timestamp)
+		memcpy(buf + st->d_size - sizeof(s64),
+			&time_ns, sizeof(time_ns));
+
+	ring->access.store_to(&sw_ring->buf, buf, time_ns);
+done:
+	gpio_set_value(st->pdata->gpio_convst, 0);
+	kfree(buf);
+	atomic_dec(&st->protect_ring);
+}
+
+int ad7606_register_ring_funcs_and_init(struct iio_dev *indio_dev)
+{
+	struct ad7606_state *st = indio_dev->dev_data;
+	int ret;
+
+	indio_dev->ring = iio_sw_rb_allocate(indio_dev);
+	if (!indio_dev->ring) {
+		ret = -ENOMEM;
+		goto error_ret;
+	}
+
+	/* Effectively select the ring buffer implementation */
+	iio_ring_sw_register_funcs(&indio_dev->ring->access);
+	ret = iio_alloc_pollfunc(indio_dev, NULL, &ad7606_poll_func_th);
+	if (ret)
+		goto error_deallocate_sw_rb;
+
+	/* Ring buffer functions - here trigger setup related */
+
+	indio_dev->ring->preenable = &ad7606_ring_preenable;
+	indio_dev->ring->postenable = &iio_triggered_ring_postenable;
+	indio_dev->ring->predisable = &iio_triggered_ring_predisable;
+	indio_dev->ring->scan_el_attrs = &ad7606_scan_el_group;
+	indio_dev->ring->scan_timestamp = true ;
+
+	INIT_WORK(&st->poll_work, &ad7606_poll_bh_to_ring);
+
+	/* Flag that polled ring buffering is possible */
+	indio_dev->modes |= INDIO_RING_TRIGGERED;
+	return 0;
+error_deallocate_sw_rb:
+	iio_sw_rb_free(indio_dev->ring);
+error_ret:
+	return ret;
+}
+
+void ad7606_ring_cleanup(struct iio_dev *indio_dev)
+{
+	if (indio_dev->trig) {
+		iio_put_trigger(indio_dev->trig);
+		iio_trigger_dettach_poll_func(indio_dev->trig,
+					      indio_dev->pollfunc);
+	}
+	kfree(indio_dev->pollfunc);
+	iio_sw_rb_free(indio_dev->ring);
+}
diff --git a/drivers/staging/iio/adc/ad7606_spi.c b/drivers/staging/iio/adc/ad7606_spi.c
new file mode 100644
index 0000000..d738491
--- /dev/null
+++ b/drivers/staging/iio/adc/ad7606_spi.c
@@ -0,0 +1,126 @@
+/*
+ * AD7606 SPI ADC driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include "ad7606.h"
+
+#define MAX_SPI_FREQ_HZ		23500000	/* VDRIVE above 4.75 V */
+
+static int ad7606_spi_read_block(struct device *dev,
+				 int count, void *buf)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int i, ret;
+	unsigned short *data = buf;
+
+	ret = spi_read(spi, (u8 *)buf, count * 2);
+	if (ret < 0) {
+		dev_err(&spi->dev, "SPI read error\n");
+		return ret;
+	}
+
+	for (i = 0; i < count; i++)
+		data[i] = be16_to_cpu(data[i]);
+
+	return 0;
+}
+
+static const struct ad7606_bus_ops ad7606_spi_bops = {
+	.read_block	= ad7606_spi_read_block,
+};
+
+static int __devinit ad7606_spi_probe(struct spi_device *spi)
+{
+	struct ad7606_state *st;
+
+	st = ad7606_probe(&spi->dev, spi->irq, NULL,
+			   spi_get_device_id(spi)->driver_data,
+			   &ad7606_spi_bops);
+
+	if (IS_ERR(st))
+		return PTR_ERR(st);
+
+	spi_set_drvdata(spi, st);
+
+	return 0;
+}
+
+static int __devexit ad7606_spi_remove(struct spi_device *spi)
+{
+	struct ad7606_state *st = dev_get_drvdata(&spi->dev);
+
+	return ad7606_remove(st);
+}
+
+#ifdef CONFIG_PM
+static int ad7606_spi_suspend(struct device *dev)
+{
+	struct ad7606_state *st = dev_get_drvdata(dev);
+
+	ad7606_suspend(st);
+
+	return 0;
+}
+
+static int ad7606_spi_resume(struct device *dev)
+{
+	struct ad7606_state *st = dev_get_drvdata(dev);
+
+	ad7606_resume(st);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ad7606_pm_ops = {
+	.suspend = ad7606_spi_suspend,
+	.resume  = ad7606_spi_resume,
+};
+#define AD7606_SPI_PM_OPS (&ad7606_pm_ops)
+
+#else
+#define AD7606_SPI_PM_OPS NULL
+#endif
+
+static const struct spi_device_id ad7606_id[] = {
+	{"ad7606-8", ID_AD7606_8},
+	{"ad7606-6", ID_AD7606_6},
+	{"ad7606-4", ID_AD7606_4},
+	{}
+};
+
+static struct spi_driver ad7606_driver = {
+	.driver = {
+		.name = "ad7606",
+		.bus = &spi_bus_type,
+		.owner = THIS_MODULE,
+		.pm    = AD7606_SPI_PM_OPS,
+	},
+	.probe = ad7606_spi_probe,
+	.remove = __devexit_p(ad7606_spi_remove),
+	.id_table = ad7606_id,
+};
+
+static int __init ad7606_spi_init(void)
+{
+	return spi_register_driver(&ad7606_driver);
+}
+module_init(ad7606_spi_init);
+
+static void __exit ad7606_spi_exit(void)
+{
+	spi_unregister_driver(&ad7606_driver);
+}
+module_exit(ad7606_spi_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad7606_spi");
diff --git a/drivers/staging/iio/adc/ad7887.h b/drivers/staging/iio/adc/ad7887.h
index 8c2a218..439c802 100644
--- a/drivers/staging/iio/adc/ad7887.h
+++ b/drivers/staging/iio/adc/ad7887.h
@@ -63,6 +63,7 @@ struct ad7887_state {
 	struct regulator		*reg;
 	struct work_struct		poll_work;
 	atomic_t			protect_ring;
+	size_t				d_size;
 	u16				int_vref_mv;
 	bool				en_dual;
 	struct spi_transfer		xfer[4];
diff --git a/drivers/staging/iio/adc/ad7887_ring.c b/drivers/staging/iio/adc/ad7887_ring.c
index 6b9cb1f..2d7fe65 100644
--- a/drivers/staging/iio/adc/ad7887_ring.c
+++ b/drivers/staging/iio/adc/ad7887_ring.c
@@ -27,6 +27,8 @@
 
 static IIO_SCAN_EL_C(in0, 0, 0, NULL);
 static IIO_SCAN_EL_C(in1, 1, 0, NULL);
+static IIO_SCAN_EL_TIMESTAMP(2);
+static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64);
 
 static ssize_t ad7887_show_type(struct device *dev,
 				struct device_attribute *attr,
@@ -47,6 +49,9 @@ static struct attribute *ad7887_scan_el_attrs[] = {
 	&iio_const_attr_in0_index.dev_attr.attr,
 	&iio_scan_el_in1.dev_attr.attr,
 	&iio_const_attr_in1_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
 	&iio_dev_attr_in_type.dev_attr.attr,
 	NULL,
 };
@@ -118,16 +123,20 @@ static int ad7887_ring_preenable(struct iio_dev *indio_dev)
 {
 	struct ad7887_state *st = indio_dev->dev_data;
 	struct iio_ring_buffer *ring = indio_dev->ring;
-	size_t d_size;
 
-	if (indio_dev->ring->access.set_bytes_per_datum) {
-		d_size = st->chip_info->storagebits / 8 + sizeof(s64);
-		if (d_size % 8)
-			d_size += 8 - (d_size % 8);
-		indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
-							    d_size);
+	st->d_size = ring->scan_count * st->chip_info->storagebits / 8;
+
+	if (ring->scan_timestamp) {
+		st->d_size += sizeof(s64);
+
+		if (st->d_size % sizeof(s64))
+			st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
 	}
 
+	if (indio_dev->ring->access.set_bytes_per_datum)
+		indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+							    st->d_size);
+
 	switch (ring->scan_mask) {
 	case (1 << 0):
 		st->ring_msg = &st->msg[AD7887_CH0];
@@ -186,20 +195,14 @@ static void ad7887_poll_bh_to_ring(struct work_struct *work_s)
 	s64 time_ns;
 	__u8 *buf;
 	int b_sent;
-	size_t d_size;
 
 	unsigned int bytes = ring->scan_count * st->chip_info->storagebits / 8;
 
-	/* Ensure the timestamp is 8 byte aligned */
-	d_size = bytes + sizeof(s64);
-	if (d_size % sizeof(s64))
-		d_size += sizeof(s64) - (d_size % sizeof(s64));
-
 	/* Ensure only one copy of this function running at a time */
 	if (atomic_inc_return(&st->protect_ring) > 1)
 		return;
 
-	buf = kzalloc(d_size, GFP_KERNEL);
+	buf = kzalloc(st->d_size, GFP_KERNEL);
 	if (buf == NULL)
 		return;
 
@@ -210,7 +213,9 @@ static void ad7887_poll_bh_to_ring(struct work_struct *work_s)
 	time_ns = iio_get_time_ns();
 
 	memcpy(buf, st->data, bytes);
-	memcpy(buf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+	if (ring->scan_timestamp)
+		memcpy(buf + st->d_size - sizeof(s64),
+			&time_ns, sizeof(time_ns));
 
 	indio_dev->ring->access.store_to(&sw_ring->buf, buf, time_ns);
 done:
@@ -241,6 +246,7 @@ int ad7887_register_ring_funcs_and_init(struct iio_dev *indio_dev)
 	indio_dev->ring->predisable = &iio_triggered_ring_predisable;
 	indio_dev->ring->postdisable = &ad7887_ring_postdisable;
 	indio_dev->ring->scan_el_attrs = &ad7887_scan_el_group;
+	indio_dev->ring->scan_timestamp = true;
 
 	INIT_WORK(&st->poll_work, &ad7887_poll_bh_to_ring);
 
diff --git a/drivers/staging/iio/adc/ad799x.h b/drivers/staging/iio/adc/ad799x.h
index 81a20d5..a421362 100644
--- a/drivers/staging/iio/adc/ad799x.h
+++ b/drivers/staging/iio/adc/ad799x.h
@@ -116,6 +116,7 @@ struct ad799x_state {
 	struct work_struct		poll_work;
 	struct work_struct		work_thresh;
 	atomic_t			protect_ring;
+	size_t				d_size;
 	struct iio_trigger		*trig;
 	struct regulator		*reg;
 	s64				last_timestamp;
diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c
index 89ccf37..e50841b 100644
--- a/drivers/staging/iio/adc/ad799x_core.c
+++ b/drivers/staging/iio/adc/ad799x_core.c
@@ -123,6 +123,9 @@ static AD799X_SCAN_EL(5);
 static AD799X_SCAN_EL(6);
 static AD799X_SCAN_EL(7);
 
+static IIO_SCAN_EL_TIMESTAMP(8);
+static IIO_CONST_ATTR_SCAN_EL_TYPE(timestamp, s, 64, 64)
+
 static ssize_t ad799x_show_type(struct device *dev,
 				struct device_attribute *attr,
 				char *buf)
@@ -471,6 +474,9 @@ static struct attribute *ad7991_5_9_3_4_scan_el_attrs[] = {
 	&iio_const_attr_in2_index.dev_attr.attr,
 	&iio_scan_el_in3.dev_attr.attr,
 	&iio_const_attr_in3_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
 	&iio_dev_attr_in_type.dev_attr.attr,
 	NULL,
 };
@@ -497,6 +503,9 @@ static struct attribute *ad7992_scan_el_attrs[] = {
 	&iio_const_attr_in0_index.dev_attr.attr,
 	&iio_scan_el_in1.dev_attr.attr,
 	&iio_const_attr_in1_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
 	&iio_dev_attr_in_type.dev_attr.attr,
 	NULL,
 };
@@ -541,6 +550,9 @@ static struct attribute *ad7997_8_scan_el_attrs[] = {
 	&iio_const_attr_in6_index.dev_attr.attr,
 	&iio_scan_el_in7.dev_attr.attr,
 	&iio_const_attr_in7_index.dev_attr.attr,
+	&iio_const_attr_timestamp_index.dev_attr.attr,
+	&iio_scan_el_timestamp.dev_attr.attr,
+	&iio_const_attr_timestamp_type.dev_attr.attr,
 	&iio_dev_attr_in_type.dev_attr.attr,
 	NULL,
 };
diff --git a/drivers/staging/iio/adc/ad799x_ring.c b/drivers/staging/iio/adc/ad799x_ring.c
index 975cdcb..56abc39 100644
--- a/drivers/staging/iio/adc/ad799x_ring.c
+++ b/drivers/staging/iio/adc/ad799x_ring.c
@@ -73,8 +73,6 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
 {
 	struct iio_ring_buffer *ring = indio_dev->ring;
 	struct ad799x_state *st = indio_dev->dev_data;
-	size_t d_size;
-	unsigned long numvals;
 
 	/*
 	 * Need to figure out the current mode based upon the requested
@@ -84,15 +82,19 @@ static int ad799x_ring_preenable(struct iio_dev *indio_dev)
 	if (st->id == ad7997 || st->id == ad7998)
 		ad799x_set_scan_mode(st, ring->scan_mask);
 
-	numvals = ring->scan_count;
+	st->d_size = ring->scan_count * 2;
 
-	if (ring->access.set_bytes_per_datum) {
-		d_size = numvals*2 + sizeof(s64);
-		if (d_size % 8)
-			d_size += 8 - (d_size % 8);
-		ring->access.set_bytes_per_datum(ring, d_size);
+	if (ring->scan_timestamp) {
+		st->d_size += sizeof(s64);
+
+		if (st->d_size % sizeof(s64))
+			st->d_size += sizeof(s64) - (st->d_size % sizeof(s64));
 	}
 
+	if (indio_dev->ring->access.set_bytes_per_datum)
+		indio_dev->ring->access.set_bytes_per_datum(indio_dev->ring,
+							    st->d_size);
+
 	return 0;
 }
 
@@ -130,29 +132,13 @@ static void ad799x_poll_bh_to_ring(struct work_struct *work_s)
 	s64 time_ns;
 	__u8 *rxbuf;
 	int b_sent;
-	size_t d_size;
 	u8 cmd;
 
-	unsigned long numvals = ring->scan_count;
-
-	/* Ensure the timestamp is 8 byte aligned */
-	d_size = numvals*2 + sizeof(s64);
-
-	if (d_size % sizeof(s64))
-		d_size += sizeof(s64) - (d_size % sizeof(s64));
-
 	/* Ensure only one copy of this function running at a time */
 	if (atomic_inc_return(&st->protect_ring) > 1)
 		return;
 
-	/* Monitor mode prevents reading. Whilst not currently implemented
-	 * might as well have this test in here in the meantime as it does
-	 * no harm.
-	 */
-	if (numvals == 0)
-		return;
-
-	rxbuf = kmalloc(d_size,	GFP_KERNEL);
+	rxbuf = kmalloc(st->d_size, GFP_KERNEL);
 	if (rxbuf == NULL)
 		return;
 
@@ -177,13 +163,15 @@ static void ad799x_poll_bh_to_ring(struct work_struct *work_s)
 	}
 
 	b_sent = i2c_smbus_read_i2c_block_data(st->client,
-			cmd, numvals*2, rxbuf);
+			cmd, ring->scan_count * 2, rxbuf);
 	if (b_sent < 0)
 		goto done;
 
 	time_ns = iio_get_time_ns();
 
-	memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
+	if (ring->scan_timestamp)
+		memcpy(rxbuf + st->d_size - sizeof(s64),
+			&time_ns, sizeof(time_ns));
 
 	ring->access.store_to(&ring_sw->buf, rxbuf, time_ns);
 done:
@@ -213,6 +201,7 @@ int ad799x_register_ring_funcs_and_init(struct iio_dev *indio_dev)
 	indio_dev->ring->preenable = &ad799x_ring_preenable;
 	indio_dev->ring->postenable = &iio_triggered_ring_postenable;
 	indio_dev->ring->predisable = &iio_triggered_ring_predisable;
+	indio_dev->ring->scan_timestamp = true;
 
 	INIT_WORK(&st->poll_work, &ad799x_poll_bh_to_ring);
 
diff --git a/drivers/staging/iio/dac/Kconfig b/drivers/staging/iio/dac/Kconfig
index 9191bd2..67defcb 100644
--- a/drivers/staging/iio/dac/Kconfig
+++ b/drivers/staging/iio/dac/Kconfig
@@ -11,11 +11,22 @@ config AD5624R_SPI
 	  AD5664R convertors (DAC). This driver uses the common SPI interface.
 
 config AD5446
-	tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5541A/12A DAC SPI driver"
+	tristate "Analog Devices AD5444/6, AD5620/40/60 and AD5542A/12A DAC SPI driver"
 	depends on SPI
 	help
 	  Say yes here to build support for Analog Devices AD5444, AD5446,
-	  AD5620, AD5640, AD5660 and AD5541A, AD5512A DACs.
+	  AD5512A, AD5542A, AD5543, AD5553, AD5601, AD5611, AD5620, AD5621,
+	  AD5640, AD5660 DACs.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad5446.
+
+config MAX517
+	tristate "Maxim MAX517/518/519 DAC driver"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Maxim chips MAX517,
+	  MAX518 and MAX519 (I2C 8-Bit DACs with rail-to-rail outputs).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called max517.
diff --git a/drivers/staging/iio/dac/Makefile b/drivers/staging/iio/dac/Makefile
index 7cf331b..1197aef 100644
--- a/drivers/staging/iio/dac/Makefile
+++ b/drivers/staging/iio/dac/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_AD5624R_SPI) += ad5624r_spi.o
 obj-$(CONFIG_AD5446) += ad5446.o
+obj-$(CONFIG_MAX517) += max517.o
diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c
index 0f87eca..8623a72 100644
--- a/drivers/staging/iio/dac/ad5446.c
+++ b/drivers/staging/iio/dac/ad5446.c
@@ -48,6 +48,20 @@ static void ad5660_store_sample(struct ad5446_state *st, unsigned val)
 	st->data.d24[2] = val & 0xFF;
 }
 
+static void ad5620_store_pwr_down(struct ad5446_state *st, unsigned mode)
+{
+	st->data.d16 = cpu_to_be16(mode << 14);
+}
+
+static void ad5660_store_pwr_down(struct ad5446_state *st, unsigned mode)
+{
+	unsigned val = mode << 16;
+
+	st->data.d24[0] = (val >> 16) & 0xFF;
+	st->data.d24[1] = (val >> 8) & 0xFF;
+	st->data.d24[2] = val & 0xFF;
+}
+
 static ssize_t ad5446_write(struct device *dev,
 		struct device_attribute *attr,
 		const char *buf,
@@ -68,6 +82,7 @@ static ssize_t ad5446_write(struct device *dev,
 	}
 
 	mutex_lock(&dev_info->mlock);
+	st->cached_val = val;
 	st->chip_info->store_sample(st, val);
 	ret = spi_sync(st->spi, &st->msg);
 	mutex_unlock(&dev_info->mlock);
@@ -102,15 +117,119 @@ static ssize_t ad5446_show_name(struct device *dev,
 }
 static IIO_DEVICE_ATTR(name, S_IRUGO, ad5446_show_name, NULL, 0);
 
+static ssize_t ad5446_write_powerdown_mode(struct device *dev,
+				       struct device_attribute *attr,
+				       const char *buf, size_t len)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad5446_state *st = dev_info->dev_data;
+
+	if (sysfs_streq(buf, "1kohm_to_gnd"))
+		st->pwr_down_mode = MODE_PWRDWN_1k;
+	else if (sysfs_streq(buf, "100kohm_to_gnd"))
+		st->pwr_down_mode = MODE_PWRDWN_100k;
+	else if (sysfs_streq(buf, "three_state"))
+		st->pwr_down_mode = MODE_PWRDWN_TRISTATE;
+	else
+		return -EINVAL;
+
+	return len;
+}
+
+static ssize_t ad5446_read_powerdown_mode(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad5446_state *st = dev_info->dev_data;
+
+	char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
+
+	return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
+}
+
+static ssize_t ad5446_read_dac_powerdown(struct device *dev,
+					   struct device_attribute *attr,
+					   char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad5446_state *st = dev_info->dev_data;
+
+	return sprintf(buf, "%d\n", st->pwr_down);
+}
+
+static ssize_t ad5446_write_dac_powerdown(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t len)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad5446_state *st = dev_info->dev_data;
+	unsigned long readin;
+	int ret;
+
+	ret = strict_strtol(buf, 10, &readin);
+	if (ret)
+		return ret;
+
+	if (readin > 1)
+		ret = -EINVAL;
+
+	mutex_lock(&dev_info->mlock);
+	st->pwr_down = readin;
+
+	if (st->pwr_down)
+		st->chip_info->store_pwr_down(st, st->pwr_down_mode);
+	else
+		st->chip_info->store_sample(st, st->cached_val);
+
+	ret = spi_sync(st->spi, &st->msg);
+	mutex_unlock(&dev_info->mlock);
+
+	return ret ? ret : len;
+}
+
+static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO | S_IWUSR,
+			ad5446_read_powerdown_mode,
+			ad5446_write_powerdown_mode, 0);
+
+static IIO_CONST_ATTR(out_powerdown_mode_available,
+			"1kohm_to_gnd 100kohm_to_gnd three_state");
+
+static IIO_DEVICE_ATTR(out0_powerdown, S_IRUGO | S_IWUSR,
+			ad5446_read_dac_powerdown,
+			ad5446_write_dac_powerdown, 0);
+
 static struct attribute *ad5446_attributes[] = {
 	&iio_dev_attr_out0_raw.dev_attr.attr,
 	&iio_dev_attr_out_scale.dev_attr.attr,
+	&iio_dev_attr_out0_powerdown.dev_attr.attr,
+	&iio_dev_attr_out_powerdown_mode.dev_attr.attr,
+	&iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
 	&iio_dev_attr_name.dev_attr.attr,
 	NULL,
 };
 
+static mode_t ad5446_attr_is_visible(struct kobject *kobj,
+				     struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad5446_state *st = iio_dev_get_devdata(dev_info);
+
+	mode_t mode = attr->mode;
+
+	if (!st->chip_info->store_pwr_down &&
+		(attr == &iio_dev_attr_out0_powerdown.dev_attr.attr ||
+		attr == &iio_dev_attr_out_powerdown_mode.dev_attr.attr ||
+		attr ==
+		&iio_const_attr_out_powerdown_mode_available.dev_attr.attr))
+		mode = 0;
+
+	return mode;
+}
+
 static const struct attribute_group ad5446_attribute_group = {
 	.attrs = ad5446_attributes,
+	.is_visible = ad5446_attr_is_visible,
 };
 
 static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
@@ -132,18 +251,52 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 		.left_shift = 0,
 		.store_sample = ad5542_store_sample,
 	},
+	[ID_AD5543] = {
+		.bits = 16,
+		.storagebits = 16,
+		.left_shift = 0,
+		.store_sample = ad5542_store_sample,
+	},
 	[ID_AD5512A] = {
 		.bits = 12,
 		.storagebits = 16,
 		.left_shift = 4,
 		.store_sample = ad5542_store_sample,
 	},
+	[ID_AD5553] = {
+		.bits = 14,
+		.storagebits = 16,
+		.left_shift = 0,
+		.store_sample = ad5542_store_sample,
+	},
+	[ID_AD5601] = {
+		.bits = 8,
+		.storagebits = 16,
+		.left_shift = 6,
+		.store_sample = ad5542_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
+	},
+	[ID_AD5611] = {
+		.bits = 10,
+		.storagebits = 16,
+		.left_shift = 4,
+		.store_sample = ad5542_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
+	},
+	[ID_AD5621] = {
+		.bits = 12,
+		.storagebits = 16,
+		.left_shift = 2,
+		.store_sample = ad5542_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
+	},
 	[ID_AD5620_2500] = {
 		.bits = 12,
 		.storagebits = 16,
 		.left_shift = 2,
 		.int_vref_mv = 2500,
 		.store_sample = ad5620_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
 	},
 	[ID_AD5620_1250] = {
 		.bits = 12,
@@ -151,6 +304,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 		.left_shift = 2,
 		.int_vref_mv = 1250,
 		.store_sample = ad5620_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
 	},
 	[ID_AD5640_2500] = {
 		.bits = 14,
@@ -158,6 +312,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 		.left_shift = 0,
 		.int_vref_mv = 2500,
 		.store_sample = ad5620_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
 	},
 	[ID_AD5640_1250] = {
 		.bits = 14,
@@ -165,6 +320,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 		.left_shift = 0,
 		.int_vref_mv = 1250,
 		.store_sample = ad5620_store_sample,
+		.store_pwr_down = ad5620_store_pwr_down,
 	},
 	[ID_AD5660_2500] = {
 		.bits = 16,
@@ -172,6 +328,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 		.left_shift = 0,
 		.int_vref_mv = 2500,
 		.store_sample = ad5660_store_sample,
+		.store_pwr_down = ad5660_store_pwr_down,
 	},
 	[ID_AD5660_1250] = {
 		.bits = 16,
@@ -179,6 +336,7 @@ static const struct ad5446_chip_info ad5446_chip_info_tbl[] = {
 		.left_shift = 0,
 		.int_vref_mv = 1250,
 		.store_sample = ad5660_store_sample,
+		.store_pwr_down = ad5660_store_pwr_down,
 	},
 };
 
@@ -231,20 +389,20 @@ static int __devinit ad5446_probe(struct spi_device *spi)
 	spi_message_add_tail(&st->xfer, &st->msg);
 
 	switch (spi_get_device_id(spi)->driver_data) {
-		case ID_AD5620_2500:
-		case ID_AD5620_1250:
-		case ID_AD5640_2500:
-		case ID_AD5640_1250:
-		case ID_AD5660_2500:
-		case ID_AD5660_1250:
-			st->vref_mv = st->chip_info->int_vref_mv;
-			break;
-		default:
-			if (voltage_uv)
-				st->vref_mv = voltage_uv / 1000;
-			else
-				dev_warn(&spi->dev,
-					 "reference voltage unspecified\n");
+	case ID_AD5620_2500:
+	case ID_AD5620_1250:
+	case ID_AD5640_2500:
+	case ID_AD5640_1250:
+	case ID_AD5660_2500:
+	case ID_AD5660_1250:
+		st->vref_mv = st->chip_info->int_vref_mv;
+		break;
+	default:
+		if (voltage_uv)
+			st->vref_mv = voltage_uv / 1000;
+		else
+			dev_warn(&spi->dev,
+				 "reference voltage unspecified\n");
 	}
 
 	ret = iio_device_register(st->indio_dev);
@@ -283,8 +441,13 @@ static int ad5446_remove(struct spi_device *spi)
 static const struct spi_device_id ad5446_id[] = {
 	{"ad5444", ID_AD5444},
 	{"ad5446", ID_AD5446},
-	{"ad5542a", ID_AD5542A},
 	{"ad5512a", ID_AD5512A},
+	{"ad5542a", ID_AD5542A},
+	{"ad5543", ID_AD5543},
+	{"ad5553", ID_AD5553},
+	{"ad5601", ID_AD5601},
+	{"ad5611", ID_AD5611},
+	{"ad5621", ID_AD5621},
 	{"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
 	{"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
 	{"ad5640-2500", ID_AD5640_2500},
diff --git a/drivers/staging/iio/dac/ad5446.h b/drivers/staging/iio/dac/ad5446.h
index 902542e..7ac63ab8a 100644
--- a/drivers/staging/iio/dac/ad5446.h
+++ b/drivers/staging/iio/dac/ad5446.h
@@ -27,6 +27,10 @@
 
 #define RES_MASK(bits)	((1 << (bits)) - 1)
 
+#define MODE_PWRDWN_1k		0x1
+#define MODE_PWRDWN_100k	0x2
+#define MODE_PWRDWN_TRISTATE	0x3
+
 /**
  * struct ad5446_state - driver instance specific data
  * @indio_dev:		the industrial I/O device
@@ -47,6 +51,9 @@ struct ad5446_state {
 	struct regulator		*reg;
 	struct work_struct		poll_work;
 	unsigned short			vref_mv;
+	unsigned			cached_val;
+	unsigned			pwr_down_mode;
+	unsigned			pwr_down;
 	struct spi_transfer		xfer;
 	struct spi_message		msg;
 	union {
@@ -62,14 +69,16 @@ struct ad5446_state {
  * @left_shift:		number of bits the datum must be shifted
  * @int_vref_mv:	AD5620/40/60: the internal reference voltage
  * @store_sample:	chip specific helper function to store the datum
+ * @store_sample:	chip specific helper function to store the powerpown cmd
  */
 
 struct ad5446_chip_info {
-	u8				bits;
-	u8				storagebits;
-	u8				left_shift;
-	u16				int_vref_mv;
-	void (*store_sample)		(struct ad5446_state *st, unsigned val);
+	u8			bits;
+	u8			storagebits;
+	u8			left_shift;
+	u16			int_vref_mv;
+	void (*store_sample)	(struct ad5446_state *st, unsigned val);
+	void (*store_pwr_down)	(struct ad5446_state *st, unsigned mode);
 };
 
 /**
@@ -84,7 +93,12 @@ enum ad5446_supported_device_ids {
 	ID_AD5444,
 	ID_AD5446,
 	ID_AD5542A,
+	ID_AD5543,
 	ID_AD5512A,
+	ID_AD5553,
+	ID_AD5601,
+	ID_AD5611,
+	ID_AD5621,
 	ID_AD5620_2500,
 	ID_AD5620_1250,
 	ID_AD5640_2500,
diff --git a/drivers/staging/iio/dac/ad5624r.h b/drivers/staging/iio/dac/ad5624r.h
index ce518be..c16df4e 100644
--- a/drivers/staging/iio/dac/ad5624r.h
+++ b/drivers/staging/iio/dac/ad5624r.h
@@ -1,21 +1,80 @@
+/*
+ * AD5624R SPI DAC driver
+ *
+ * Copyright 2010-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ */
 #ifndef SPI_AD5624R_H_
 #define SPI_AD5624R_H_
 
-#define AD5624R_DAC_CHANNELS	4
+#define AD5624R_DAC_CHANNELS			4
 
-#define AD5624R_ADDR_DAC0	0x0
-#define AD5624R_ADDR_DAC1	0x1
-#define AD5624R_ADDR_DAC2	0x2
-#define AD5624R_ADDR_DAC3	0x3
-#define AD5624R_ADDR_ALL_DAC	0x7
+#define AD5624R_ADDR_DAC0			0x0
+#define AD5624R_ADDR_DAC1			0x1
+#define AD5624R_ADDR_DAC2			0x2
+#define AD5624R_ADDR_DAC3			0x3
+#define AD5624R_ADDR_ALL_DAC			0x7
 
-#define AD5624R_CMD_WRITE_INPUT_N             0x0
-#define AD5624R_CMD_UPDATE_DAC_N              0x1
-#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_ALL  0x2
-#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_N    0x3
-#define AD5624R_CMD_POWERDOWN_DAC             0x4
-#define AD5624R_CMD_RESET                     0x5
-#define AD5624R_CMD_LDAC_SETUP                0x6
-#define AD5624R_CMD_INTERNAL_REFER_SETUP      0x7
+#define AD5624R_CMD_WRITE_INPUT_N		0x0
+#define AD5624R_CMD_UPDATE_DAC_N		0x1
+#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_ALL	0x2
+#define AD5624R_CMD_WRITE_INPUT_N_UPDATE_N	0x3
+#define AD5624R_CMD_POWERDOWN_DAC		0x4
+#define AD5624R_CMD_RESET			0x5
+#define AD5624R_CMD_LDAC_SETUP			0x6
+#define AD5624R_CMD_INTERNAL_REFER_SETUP	0x7
 
-#endif
+#define AD5624R_LDAC_PWRDN_NONE			0x0
+#define AD5624R_LDAC_PWRDN_1K			0x1
+#define AD5624R_LDAC_PWRDN_100K			0x2
+#define AD5624R_LDAC_PWRDN_3STATE		0x3
+
+/**
+ * struct ad5624r_chip_info - chip specific information
+ * @bits:		accuracy of the DAC in bits
+ * @int_vref_mv:	AD5620/40/60: the internal reference voltage
+ */
+
+struct ad5624r_chip_info {
+	u8				bits;
+	u16				int_vref_mv;
+};
+
+/**
+ * struct ad5446_state - driver instance specific data
+ * @indio_dev:		the industrial I/O device
+ * @us:			spi_device
+ * @chip_info:		chip model specific constants, available modes etc
+ * @reg:		supply regulator
+ * @vref_mv:		actual reference voltage used
+ * @pwr_down_mask	power down mask
+ * @pwr_down_mode	current power down mode
+ */
+
+struct ad5624r_state {
+	struct iio_dev			*indio_dev;
+	struct spi_device		*us;
+	const struct ad5624r_chip_info	*chip_info;
+	struct regulator		*reg;
+	unsigned short			vref_mv;
+	unsigned			pwr_down_mask;
+	unsigned			pwr_down_mode;
+};
+
+/**
+ * ad5624r_supported_device_ids:
+ * The AD5624/44/64 parts are available in different
+ * fixed internal reference voltage options.
+ */
+
+enum ad5624r_supported_device_ids {
+	ID_AD5624R3,
+	ID_AD5644R3,
+	ID_AD5664R3,
+	ID_AD5624R5,
+	ID_AD5644R5,
+	ID_AD5664R5,
+};
+
+#endif /* SPI_AD5624R_H_ */
diff --git a/drivers/staging/iio/dac/ad5624r_spi.c b/drivers/staging/iio/dac/ad5624r_spi.c
index 2b1c6dd..a945b18 100644
--- a/drivers/staging/iio/dac/ad5624r_spi.c
+++ b/drivers/staging/iio/dac/ad5624r_spi.c
@@ -1,9 +1,9 @@
 /*
  * AD5624R, AD5644R, AD5664R Digital to analog convertors spi driver
  *
- * Copyright 2010 Analog Devices Inc.
+ * Copyright 2010-2011 Analog Devices Inc.
  *
- * Licensed under the GPL-2 or later.
+ * Licensed under the GPL-2.
  */
 
 #include <linux/interrupt.h>
@@ -14,25 +14,38 @@
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
-#include <linux/delay.h>
+#include <linux/regulator/consumer.h>
 
 #include "../iio.h"
 #include "../sysfs.h"
 #include "dac.h"
 #include "ad5624r.h"
 
-/**
- * struct ad5624r_state - device related storage
- * @indio_dev:	associated industrial IO device
- * @us:		spi device
- **/
-struct ad5624r_state {
-	struct iio_dev *indio_dev;
-	struct spi_device *us;
-	int data_len;
-	int ldac_mode;
-	int dac_power_mode[AD5624R_DAC_CHANNELS];
-	int internal_ref;
+static const struct ad5624r_chip_info ad5624r_chip_info_tbl[] = {
+	[ID_AD5624R3] = {
+		.bits = 12,
+		.int_vref_mv = 1250,
+	},
+	[ID_AD5644R3] = {
+		.bits = 14,
+		.int_vref_mv = 1250,
+	},
+	[ID_AD5664R3] = {
+		.bits = 16,
+		.int_vref_mv = 1250,
+	},
+	[ID_AD5624R5] = {
+		.bits = 12,
+		.int_vref_mv = 2500,
+	},
+	[ID_AD5644R5] = {
+		.bits = 14,
+		.int_vref_mv = 2500,
+	},
+	[ID_AD5664R5] = {
+		.bits = 16,
+		.int_vref_mv = 2500,
+	},
 };
 
 static int ad5624r_spi_write(struct spi_device *spi,
@@ -42,11 +55,12 @@ static int ad5624r_spi_write(struct spi_device *spi,
 	u8 msg[3];
 
 	/*
-	 * The input shift register is 24 bits wide. The first two bits are don't care bits.
-	 * The next three are the command bits, C2 to C0, followed by the 3-bit DAC address,
-	 * A2 to A0, and then the 16-, 14-, 12-bit data-word. The data-word comprises the 16-,
-	 * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits, for the AD5664R,
-	 * AD5644R, and AD5624R, respectively.
+	 * The input shift register is 24 bits wide. The first two bits are
+	 * don't care bits. The next three are the command bits, C2 to C0,
+	 * followed by the 3-bit DAC address, A2 to A0, and then the
+	 * 16-, 14-, 12-bit data-word. The data-word comprises the 16-,
+	 * 14-, 12-bit input code followed by 0, 2, or 4 don't care bits,
+	 * for the AD5664R, AD5644R, and AD5624R, respectively.
 	 */
 	data = (0 << 22) | (cmd << 19) | (addr << 16) | (val << (16 - len));
 	msg[0] = data >> 16;
@@ -63,7 +77,7 @@ static ssize_t ad5624r_write_dac(struct device *dev,
 	long readin;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = strict_strtol(buf, 10, &readin);
@@ -71,138 +85,144 @@ static ssize_t ad5624r_write_dac(struct device *dev,
 		return ret;
 
 	ret = ad5624r_spi_write(st->us, AD5624R_CMD_WRITE_INPUT_N_UPDATE_N,
-				this_attr->address, readin, st->data_len);
+				this_attr->address, readin,
+				st->chip_info->bits);
 	return ret ? ret : len;
 }
 
-static ssize_t ad5624r_read_ldac_mode(struct device *dev,
+static ssize_t ad5624r_read_powerdown_mode(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
 
-	return sprintf(buf, "%x\n", st->ldac_mode);
+	char mode[][15] = {"", "1kohm_to_gnd", "100kohm_to_gnd", "three_state"};
+
+	return sprintf(buf, "%s\n", mode[st->pwr_down_mode]);
 }
 
-static ssize_t ad5624r_write_ldac_mode(struct device *dev,
+static ssize_t ad5624r_write_powerdown_mode(struct device *dev,
 				       struct device_attribute *attr,
 				       const char *buf, size_t len)
 {
-	long readin;
-	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
-
-	ret = strict_strtol(buf, 16, &readin);
-	if (ret)
-		return ret;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	int ret;
 
-	ret = ad5624r_spi_write(st->us, AD5624R_CMD_LDAC_SETUP, 0,
-				readin & 0xF, 16);
-	st->ldac_mode = readin & 0xF;
+	if (sysfs_streq(buf, "1kohm_to_gnd"))
+		st->pwr_down_mode = AD5624R_LDAC_PWRDN_1K;
+	else if (sysfs_streq(buf, "100kohm_to_gnd"))
+		st->pwr_down_mode = AD5624R_LDAC_PWRDN_100K;
+	else if (sysfs_streq(buf, "three_state"))
+		st->pwr_down_mode = AD5624R_LDAC_PWRDN_3STATE;
+	else
+		ret = -EINVAL;
 
 	return ret ? ret : len;
 }
 
-static ssize_t ad5624r_read_dac_power_mode(struct device *dev,
+static ssize_t ad5624r_read_dac_powerdown(struct device *dev,
 					   struct device_attribute *attr,
 					   char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
-	return sprintf(buf, "%d\n", st->dac_power_mode[this_attr->address]);
+	return sprintf(buf, "%d\n",
+			!!(st->pwr_down_mask & (1 << this_attr->address)));
 }
 
-static ssize_t ad5624r_write_dac_power_mode(struct device *dev,
+static ssize_t ad5624r_write_dac_powerdown(struct device *dev,
 					    struct device_attribute *attr,
 					    const char *buf, size_t len)
 {
 	long readin;
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = strict_strtol(buf, 10, &readin);
 	if (ret)
 		return ret;
 
-	ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0,
-				((readin & 0x3) << 4) |
-				(1 << this_attr->address), 16);
+	if (readin == 1)
+		st->pwr_down_mask |= (1 << this_attr->address);
+	else if (!readin)
+		st->pwr_down_mask &= ~(1 << this_attr->address);
+	else
+		ret = -EINVAL;
 
-	st->dac_power_mode[this_attr->address] = readin & 0x3;
+	ret = ad5624r_spi_write(st->us, AD5624R_CMD_POWERDOWN_DAC, 0,
+				(st->pwr_down_mode << 4) |
+				st->pwr_down_mask, 16);
 
 	return ret ? ret : len;
 }
 
-static ssize_t ad5624r_read_internal_ref_mode(struct device *dev,
-					      struct device_attribute *attr,
-					      char *buf)
+static ssize_t ad5624r_show_scale(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
+	/* Corresponds to Vref / 2^(bits) */
+	unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits;
 
-	return sprintf(buf, "%d\n", st->internal_ref);
+	return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
 }
+static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5624r_show_scale, NULL, 0);
 
-static ssize_t ad5624r_write_internal_ref_mode(struct device *dev,
-					       struct device_attribute *attr,
-					       const char *buf, size_t len)
+static ssize_t ad5624r_show_name(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
 {
-	long readin;
-	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct ad5624r_state *st = indio_dev->dev_data;
-
-	ret = strict_strtol(buf, 10, &readin);
-	if (ret)
-		return ret;
+	struct ad5624r_state *st = iio_dev_get_devdata(indio_dev);
 
-	ret = ad5624r_spi_write(st->us, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
-				!!readin, 16);
-
-	st->internal_ref = !!readin;
-
-	return ret ? ret : len;
+	return sprintf(buf, "%s\n", spi_get_device_id(st->us)->name);
 }
+static IIO_DEVICE_ATTR(name, S_IRUGO, ad5624r_show_name, NULL, 0);
 
 static IIO_DEV_ATTR_OUT_RAW(0, ad5624r_write_dac, AD5624R_ADDR_DAC0);
 static IIO_DEV_ATTR_OUT_RAW(1, ad5624r_write_dac, AD5624R_ADDR_DAC1);
 static IIO_DEV_ATTR_OUT_RAW(2, ad5624r_write_dac, AD5624R_ADDR_DAC2);
 static IIO_DEV_ATTR_OUT_RAW(3, ad5624r_write_dac, AD5624R_ADDR_DAC3);
 
-static IIO_DEVICE_ATTR(ldac_mode, S_IRUGO | S_IWUSR, ad5624r_read_ldac_mode,
-		       ad5624r_write_ldac_mode, 0);
-static IIO_DEVICE_ATTR(internal_ref, S_IRUGO | S_IWUSR,
-		       ad5624r_read_internal_ref_mode,
-		       ad5624r_write_internal_ref_mode, 0);
+static IIO_DEVICE_ATTR(out_powerdown_mode, S_IRUGO |
+			S_IWUSR, ad5624r_read_powerdown_mode,
+			ad5624r_write_powerdown_mode, 0);
+
+static IIO_CONST_ATTR(out_powerdown_mode_available,
+			"1kohm_to_gnd 100kohm_to_gnd three_state");
 
-#define IIO_DEV_ATTR_DAC_POWER_MODE(_num, _show, _store, _addr)			\
-	IIO_DEVICE_ATTR(dac_power_mode_##_num, S_IRUGO | S_IWUSR, _show, _store, _addr)
+#define IIO_DEV_ATTR_DAC_POWERDOWN(_num, _show, _store, _addr)		\
+	IIO_DEVICE_ATTR(out##_num##_powerdown,				\
+			S_IRUGO | S_IWUSR, _show, _store, _addr)
 
-static IIO_DEV_ATTR_DAC_POWER_MODE(0, ad5624r_read_dac_power_mode,
-				   ad5624r_write_dac_power_mode, 0);
-static IIO_DEV_ATTR_DAC_POWER_MODE(1, ad5624r_read_dac_power_mode,
-				   ad5624r_write_dac_power_mode, 1);
-static IIO_DEV_ATTR_DAC_POWER_MODE(2, ad5624r_read_dac_power_mode,
-				   ad5624r_write_dac_power_mode, 2);
-static IIO_DEV_ATTR_DAC_POWER_MODE(3, ad5624r_read_dac_power_mode,
-				   ad5624r_write_dac_power_mode, 3);
+static IIO_DEV_ATTR_DAC_POWERDOWN(0, ad5624r_read_dac_powerdown,
+				   ad5624r_write_dac_powerdown, 0);
+static IIO_DEV_ATTR_DAC_POWERDOWN(1, ad5624r_read_dac_powerdown,
+				   ad5624r_write_dac_powerdown, 1);
+static IIO_DEV_ATTR_DAC_POWERDOWN(2, ad5624r_read_dac_powerdown,
+				   ad5624r_write_dac_powerdown, 2);
+static IIO_DEV_ATTR_DAC_POWERDOWN(3, ad5624r_read_dac_powerdown,
+				   ad5624r_write_dac_powerdown, 3);
 
 static struct attribute *ad5624r_attributes[] = {
 	&iio_dev_attr_out0_raw.dev_attr.attr,
 	&iio_dev_attr_out1_raw.dev_attr.attr,
 	&iio_dev_attr_out2_raw.dev_attr.attr,
 	&iio_dev_attr_out3_raw.dev_attr.attr,
-	&iio_dev_attr_dac_power_mode_0.dev_attr.attr,
-	&iio_dev_attr_dac_power_mode_1.dev_attr.attr,
-	&iio_dev_attr_dac_power_mode_2.dev_attr.attr,
-	&iio_dev_attr_dac_power_mode_3.dev_attr.attr,
-	&iio_dev_attr_ldac_mode.dev_attr.attr,
-	&iio_dev_attr_internal_ref.dev_attr.attr,
+	&iio_dev_attr_out0_powerdown.dev_attr.attr,
+	&iio_dev_attr_out1_powerdown.dev_attr.attr,
+	&iio_dev_attr_out2_powerdown.dev_attr.attr,
+	&iio_dev_attr_out3_powerdown.dev_attr.attr,
+	&iio_dev_attr_out_powerdown_mode.dev_attr.attr,
+	&iio_const_attr_out_powerdown_mode_available.dev_attr.attr,
+	&iio_dev_attr_out_scale.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
 	NULL,
 };
 
@@ -213,7 +233,7 @@ static const struct attribute_group ad5624r_attribute_group = {
 static int __devinit ad5624r_probe(struct spi_device *spi)
 {
 	struct ad5624r_state *st;
-	int ret = 0;
+	int ret, voltage_uv = 0;
 
 	st = kzalloc(sizeof(*st), GFP_KERNEL);
 	if (st == NULL) {
@@ -222,18 +242,30 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
 	}
 	spi_set_drvdata(spi, st);
 
-	st->data_len = spi_get_device_id(spi)->driver_data;
+	st->reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(st->reg)) {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+
+		voltage_uv = regulator_get_voltage(st->reg);
+	}
+
+	st->chip_info =
+		&ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
+
+	if (voltage_uv)
+		st->vref_mv = voltage_uv / 1000;
+	else
+		st->vref_mv = st->chip_info->int_vref_mv;
 
 	st->us = spi;
 	st->indio_dev = iio_allocate_device();
 	if (st->indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_st;
+		goto error_disable_reg;
 	}
 	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 0;
-	st->indio_dev->event_attrs = NULL;
-
 	st->indio_dev->attrs = &ad5624r_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
@@ -243,14 +275,22 @@ static int __devinit ad5624r_probe(struct spi_device *spi)
 	if (ret)
 		goto error_free_dev;
 
-	spi->mode = SPI_MODE_0;
-	spi_setup(spi);
+	ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
+				!!voltage_uv, 16);
+	if (ret)
+		goto error_free_dev;
 
 	return 0;
 
 error_free_dev:
 	iio_free_device(st->indio_dev);
-error_free_st:
+error_disable_reg:
+	if (!IS_ERR(st->reg))
+		regulator_disable(st->reg);
+error_put_reg:
+	if (!IS_ERR(st->reg))
+		regulator_put(st->reg);
+
 	kfree(st);
 error_ret:
 	return ret;
@@ -261,15 +301,24 @@ static int __devexit ad5624r_remove(struct spi_device *spi)
 	struct ad5624r_state *st = spi_get_drvdata(spi);
 
 	iio_device_unregister(st->indio_dev);
+
+	if (!IS_ERR(st->reg)) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
+
 	kfree(st);
 
 	return 0;
 }
 
 static const struct spi_device_id ad5624r_id[] = {
-	{"ad5624r", 12},
-	{"ad5644r", 14},
-	{"ad5664r", 16},
+	{"ad5624r3", ID_AD5624R3},
+	{"ad5644r3", ID_AD5644R3},
+	{"ad5664r3", ID_AD5664R3},
+	{"ad5624r5", ID_AD5624R5},
+	{"ad5644r5", ID_AD5644R5},
+	{"ad5664r5", ID_AD5664R5},
 	{}
 };
 
diff --git a/drivers/staging/iio/dac/max517.c b/drivers/staging/iio/dac/max517.c
new file mode 100644
index 0000000..7071f71
--- /dev/null
+++ b/drivers/staging/iio/dac/max517.c
@@ -0,0 +1,298 @@
+/*
+ *  max517.c - Support for Maxim MAX517, MAX518 and MAX519
+ *
+ *  Copyright (C) 2010, 2011 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 as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/i2c.h>
+#include <linux/err.h>
+
+#include "../iio.h"
+#include "dac.h"
+
+#include "max517.h"
+
+#define MAX517_DRV_NAME	"max517"
+
+/* Commands */
+#define COMMAND_CHANNEL0	0x00
+#define COMMAND_CHANNEL1	0x01 /* for MAX518 and MAX519 */
+#define COMMAND_PD		0x08 /* Power Down */
+
+enum max517_device_ids {
+	ID_MAX517,
+	ID_MAX518,
+	ID_MAX519,
+};
+
+struct max517_data {
+	struct iio_dev		*indio_dev;
+	struct i2c_client	*client;
+	unsigned short		vref_mv[2];
+};
+
+/*
+ * channel: bit 0: channel 1
+ *          bit 1: channel 2
+ * (this way, it's possible to set both channels at once)
+ */
+static ssize_t max517_set_value(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count, int channel)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct max517_data *data = iio_dev_get_devdata(dev_info);
+	struct i2c_client *client = data->client;
+	u8 outbuf[4]; /* 1x or 2x command + value */
+	int outbuf_size = 0;
+	int res;
+	long val;
+
+	res = strict_strtol(buf, 10, &val);
+
+	if (res)
+		return res;
+
+	if (val < 0 || val > 255)
+		return -EINVAL;
+
+	if (channel & 1) {
+		outbuf[outbuf_size++] = COMMAND_CHANNEL0;
+		outbuf[outbuf_size++] = val;
+	}
+	if (channel & 2) {
+		outbuf[outbuf_size++] = COMMAND_CHANNEL1;
+		outbuf[outbuf_size++] = val;
+	}
+
+	/*
+	 * At this point, there are always 1 or 2 two-byte commands in
+	 * outbuf. With 2 commands, the device can set two outputs
+	 * simultaneously, latching the values upon the end of the I2C
+	 * transfer.
+	 */
+
+	res = i2c_master_send(client, outbuf, outbuf_size);
+	if (res < 0)
+		return res;
+
+	return count;
+}
+
+static ssize_t max517_set_value_1(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	return max517_set_value(dev, attr, buf, count, 1);
+}
+static IIO_DEV_ATTR_OUT_RAW(1, max517_set_value_1, 0);
+
+static ssize_t max517_set_value_2(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	return max517_set_value(dev, attr, buf, count, 2);
+}
+static IIO_DEV_ATTR_OUT_RAW(2, max517_set_value_2, 1);
+
+static ssize_t max517_set_value_both(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	return max517_set_value(dev, attr, buf, count, 3);
+}
+static IIO_DEVICE_ATTR_NAMED(out1and2_raw, out1&2_raw, S_IWUSR, NULL,
+		max517_set_value_both, -1);
+
+static ssize_t max517_show_scale(struct device *dev,
+				struct device_attribute *attr,
+				char *buf, int channel)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct max517_data *data = iio_dev_get_devdata(dev_info);
+	/* Corresponds to Vref / 2^(bits) */
+	unsigned int scale_uv = (data->vref_mv[channel - 1] * 1000) >> 8;
+
+	return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000);
+}
+
+static ssize_t max517_show_scale1(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return max517_show_scale(dev, attr, buf, 1);
+}
+static IIO_DEVICE_ATTR(out1_scale, S_IRUGO, max517_show_scale1, NULL, 0);
+
+static ssize_t max517_show_scale2(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return max517_show_scale(dev, attr, buf, 2);
+}
+static IIO_DEVICE_ATTR(out2_scale, S_IRUGO, max517_show_scale2, NULL, 0);
+
+/* On MAX517 variant, we have one output */
+static struct attribute *max517_attributes[] = {
+	&iio_dev_attr_out1_raw.dev_attr.attr,
+	&iio_dev_attr_out1_scale.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group max517_attribute_group = {
+	.attrs = max517_attributes,
+};
+
+/* On MAX518 and MAX519 variant, we have two outputs */
+static struct attribute *max518_attributes[] = {
+	&iio_dev_attr_out1_raw.dev_attr.attr,
+	&iio_dev_attr_out1_scale.dev_attr.attr,
+	&iio_dev_attr_out2_raw.dev_attr.attr,
+	&iio_dev_attr_out2_scale.dev_attr.attr,
+	&iio_dev_attr_out1and2_raw.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group max518_attribute_group = {
+	.attrs = max518_attributes,
+};
+
+static int max517_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	u8 outbuf = COMMAND_PD;
+
+	return i2c_master_send(client, &outbuf, 1);
+}
+
+static int max517_resume(struct i2c_client *client)
+{
+	u8 outbuf = 0;
+
+	return i2c_master_send(client, &outbuf, 1);
+}
+
+static int max517_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct max517_data *data;
+	struct max517_platform_data *platform_data = client->dev.platform_data;
+	int err;
+
+	data = kzalloc(sizeof(struct max517_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_set_clientdata(client, data);
+
+	data->client = client;
+
+	data->indio_dev = iio_allocate_device();
+	if (data->indio_dev == NULL) {
+		err = -ENOMEM;
+		goto exit_free_data;
+	}
+
+	/* establish that the iio_dev is a child of the i2c device */
+	data->indio_dev->dev.parent = &client->dev;
+
+	/* reduced attribute set for MAX517 */
+	if (id->driver_data == ID_MAX517)
+		data->indio_dev->attrs = &max517_attribute_group;
+	else
+		data->indio_dev->attrs = &max518_attribute_group;
+	data->indio_dev->dev_data = (void *)(data);
+	data->indio_dev->driver_module = THIS_MODULE;
+	data->indio_dev->modes = INDIO_DIRECT_MODE;
+
+	/*
+	 * Reference voltage on MAX518 and default is 5V, else take vref_mv
+	 * from platform_data
+	 */
+	if (id->driver_data == ID_MAX518 || !platform_data) {
+		data->vref_mv[0] = data->vref_mv[1] = 5000; /* mV */
+	} else {
+		data->vref_mv[0] = platform_data->vref_mv[0];
+		data->vref_mv[1] = platform_data->vref_mv[1];
+	}
+
+	err = iio_device_register(data->indio_dev);
+	if (err)
+		goto exit_free_device;
+
+	dev_info(&client->dev, "DAC registered\n");
+
+	return 0;
+
+exit_free_device:
+	iio_free_device(data->indio_dev);
+exit_free_data:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int max517_remove(struct i2c_client *client)
+{
+	struct max517_data *data = i2c_get_clientdata(client);
+
+	iio_free_device(data->indio_dev);
+	kfree(data);
+
+	return 0;
+}
+
+static const struct i2c_device_id max517_id[] = {
+	{ "max517", ID_MAX517 },
+	{ "max518", ID_MAX518 },
+	{ "max519", ID_MAX519 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max517_id);
+
+static struct i2c_driver max517_driver = {
+	.driver = {
+		.name	= MAX517_DRV_NAME,
+	},
+	.probe		= max517_probe,
+	.remove		= max517_remove,
+	.suspend	= max517_suspend,
+	.resume		= max517_resume,
+	.id_table	= max517_id,
+};
+
+static int __init max517_init(void)
+{
+	return i2c_add_driver(&max517_driver);
+}
+
+static void __exit max517_exit(void)
+{
+	i2c_del_driver(&max517_driver);
+}
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("MAX517/MAX518/MAX519 8-bit DAC");
+MODULE_LICENSE("GPL");
+
+module_init(max517_init);
+module_exit(max517_exit);
diff --git a/drivers/staging/iio/dac/max517.h b/drivers/staging/iio/dac/max517.h
new file mode 100644
index 0000000..8106cf2
--- /dev/null
+++ b/drivers/staging/iio/dac/max517.h
@@ -0,0 +1,19 @@
+/*
+ * MAX517 DAC driver
+ *
+ * Copyright 2011 Roland Stigge <stigge@antcom.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#ifndef IIO_DAC_MAX517_H_
+#define IIO_DAC_MAX517_H_
+
+/*
+ * TODO: struct max517_platform_data needs to go into include/linux/iio
+ */
+
+struct max517_platform_data {
+	u16				vref_mv[2];
+};
+
+#endif /* IIO_DAC_MAX517_H_ */
diff --git a/drivers/staging/iio/dds/Kconfig b/drivers/staging/iio/dds/Kconfig
index a047da6..06b6f3a 100644
--- a/drivers/staging/iio/dds/Kconfig
+++ b/drivers/staging/iio/dds/Kconfig
@@ -15,7 +15,10 @@ config AD9832
 	depends on SPI
 	help
 	  Say yes here to build support for Analog Devices DDS chip
-	  ad9832 and ad9835, provides direct access via sysfs.
+	  AD9832 and AD9835, provides direct access via sysfs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ad9832.
 
 config AD9834
 	tristate "Analog Devices ad9833/4/ driver"
diff --git a/drivers/staging/iio/dds/ad9832.c b/drivers/staging/iio/dds/ad9832.c
index e911893..3e8491f 100644
--- a/drivers/staging/iio/dds/ad9832.c
+++ b/drivers/staging/iio/dds/ad9832.c
@@ -1,228 +1,336 @@
 /*
- * Driver for ADI Direct Digital Synthesis ad9832
+ * AD9832 SPI DDS driver
  *
- * Copyright (c) 2010 Analog Devices Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
+ * Copyright 2011 Analog Devices Inc.
  *
+ * Licensed under the GPL-2.
  */
-#include <linux/types.h>
-#include <linux/mutex.h>
+
 #include <linux/device.h>
-#include <linux/spi/spi.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 <asm/div64.h>
 
 #include "../iio.h"
 #include "../sysfs.h"
+#include "dds.h"
 
-#define DRV_NAME "ad9832"
-
-#define value_mask (u16)0xf000
-#define cmd_shift 12
-#define add_shift 8
-#define AD9832_SYNC (1 << 13)
-#define AD9832_SELSRC (1 << 12)
-#define AD9832_SLEEP (1 << 13)
-#define AD9832_RESET (1 << 12)
-#define AD9832_CLR (1 << 11)
-
-#define ADD_FREQ0LL 0x0
-#define ADD_FREQ0HL 0x1
-#define ADD_FREQ0LM 0x2
-#define ADD_FREQ0HM 0x3
-#define ADD_FREQ1LL 0x4
-#define ADD_FREQ1HL 0x5
-#define ADD_FREQ1LM 0x6
-#define ADD_FREQ1HM 0x7
-#define ADD_PHASE0L 0x8
-#define ADD_PHASE0H 0x9
-#define ADD_PHASE1L 0xa
-#define ADD_PHASE1H 0xb
-#define ADD_PHASE2L 0xc
-#define ADD_PHASE2H 0xd
-#define ADD_PHASE3L 0xe
-#define ADD_PHASE3H 0xf
-
-#define CMD_PHA8BITSW 0x1
-#define CMD_PHA16BITSW 0x0
-#define CMD_FRE8BITSW 0x3
-#define CMD_FRE16BITSW 0x2
-#define CMD_SELBITSCTL 0x6
-
-struct ad9832_setting {
-	u16 freq0[4];
-	u16 freq1[4];
-	u16 phase0[2];
-	u16 phase1[2];
-	u16 phase2[2];
-	u16 phase3[2];
-};
+#include "ad9832.h"
 
-struct ad9832_state {
-	struct mutex lock;
-	struct iio_dev *idev;
-	struct spi_device *sdev;
-};
-
-static ssize_t ad9832_set_parameter(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf,
-					size_t len)
+static unsigned long ad9832_calc_freqreg(unsigned long mclk, unsigned long fout)
 {
-	struct spi_message msg;
-	struct spi_transfer xfer;
-	int ret;
-	struct ad9832_setting config;
-	struct iio_dev *idev = dev_get_drvdata(dev);
-	struct ad9832_state *st = idev->dev_data;
-
-	config.freq0[0] = (CMD_FRE8BITSW << add_shift | ADD_FREQ0LL << add_shift | buf[0]);
-	config.freq0[1] = (CMD_FRE16BITSW << add_shift | ADD_FREQ0HL << add_shift | buf[1]);
-	config.freq0[2] = (CMD_FRE8BITSW << add_shift | ADD_FREQ0LM << add_shift | buf[2]);
-	config.freq0[3] = (CMD_FRE16BITSW << add_shift | ADD_FREQ0HM << add_shift | buf[3]);
-	config.freq1[0] = (CMD_FRE8BITSW << add_shift | ADD_FREQ1LL << add_shift | buf[4]);
-	config.freq1[1] = (CMD_FRE16BITSW << add_shift | ADD_FREQ1HL << add_shift | buf[5]);
-	config.freq1[2] = (CMD_FRE8BITSW << add_shift | ADD_FREQ1LM << add_shift | buf[6]);
-	config.freq1[3] = (CMD_FRE16BITSW << add_shift | ADD_FREQ1HM << add_shift | buf[7]);
-
-	config.phase0[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE0L << add_shift | buf[9]);
-	config.phase0[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE0H << add_shift | buf[10]);
-	config.phase1[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE1L << add_shift | buf[11]);
-	config.phase1[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE1H << add_shift | buf[12]);
-	config.phase2[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE2L << add_shift | buf[13]);
-	config.phase2[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE2H << add_shift | buf[14]);
-	config.phase3[0] = (CMD_PHA8BITSW << add_shift | ADD_PHASE3L << add_shift | buf[15]);
-	config.phase3[1] = (CMD_PHA16BITSW << add_shift | ADD_PHASE3H << add_shift | buf[16]);
-
-	xfer.len = 2 * len;
-	xfer.tx_buf = &config;
-	mutex_lock(&st->lock);
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-error_ret:
-	mutex_unlock(&st->lock);
+	unsigned long long freqreg = (u64) fout *
+				     (u64) ((u64) 1L << AD9832_FREQ_BITS);
+	do_div(freqreg, mclk);
+	return freqreg;
+}
 
-	return ret ? ret : len;
+static int ad9832_write_frequency(struct ad9832_state *st,
+				  unsigned addr, unsigned long fout)
+{
+	unsigned long regval;
+
+	if (fout > (st->mclk / 2))
+		return -EINVAL;
+
+	regval = ad9832_calc_freqreg(st->mclk, fout);
+
+	st->freq_data[0] = cpu_to_be16((AD9832_CMD_FRE8BITSW << CMD_SHIFT) |
+					(addr << ADD_SHIFT) |
+					((regval >> 24) & 0xFF));
+	st->freq_data[1] = cpu_to_be16((AD9832_CMD_FRE16BITSW << CMD_SHIFT) |
+					((addr - 1) << ADD_SHIFT) |
+					((regval >> 16) & 0xFF));
+	st->freq_data[2] = cpu_to_be16((AD9832_CMD_FRE8BITSW << CMD_SHIFT) |
+					((addr - 2) << ADD_SHIFT) |
+					((regval >> 8) & 0xFF));
+	st->freq_data[3] = cpu_to_be16((AD9832_CMD_FRE16BITSW << CMD_SHIFT) |
+					((addr - 3) << ADD_SHIFT) |
+					((regval >> 0) & 0xFF));
+
+	return spi_sync(st->spi, &st->freq_msg);;
 }
 
-static IIO_DEVICE_ATTR(dds, S_IWUSR, NULL, ad9832_set_parameter, 0);
+static int ad9832_write_phase(struct ad9832_state *st,
+				  unsigned long addr, unsigned long phase)
+{
+	if (phase > (1 << AD9832_PHASE_BITS))
+		return -EINVAL;
 
-static struct attribute *ad9832_attributes[] = {
-	&iio_dev_attr_dds.dev_attr.attr,
-	NULL,
-};
+	st->phase_data[0] = cpu_to_be16((AD9832_CMD_PHA8BITSW << CMD_SHIFT) |
+					(addr << ADD_SHIFT) |
+					((phase >> 8) & 0xFF));
+	st->phase_data[1] = cpu_to_be16((AD9832_CMD_PHA16BITSW << CMD_SHIFT) |
+					((addr - 1) << ADD_SHIFT) |
+					(phase & 0xFF));
 
-static const struct attribute_group ad9832_attribute_group = {
-	.name = DRV_NAME,
-	.attrs = ad9832_attributes,
-};
+	return spi_sync(st->spi, &st->phase_msg);
+}
 
-static void ad9832_init(struct ad9832_state *st)
+static ssize_t ad9832_write(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf,
+		size_t len)
 {
-	struct spi_message msg;
-	struct spi_transfer xfer;
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad9832_state *st = dev_info->dev_data;
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	int ret;
-	u16 config = 0;
-
-	config = 0x3 << 14 | AD9832_SLEEP | AD9832_RESET | AD9832_CLR;
+	long val;
 
-	mutex_lock(&st->lock);
-
-	xfer.len = 2;
-	xfer.tx_buf = &config;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
+	ret = strict_strtoul(buf, 10, &val);
 	if (ret)
 		goto error_ret;
 
-	config = 0x2 << 14 | AD9832_SYNC | AD9832_SELSRC;
-	xfer.len = 2;
-	xfer.tx_buf = &config;
+	mutex_lock(&dev_info->mlock);
+	switch (this_attr->address) {
+	case AD9832_FREQ0HM:
+	case AD9832_FREQ1HM:
+		ret = ad9832_write_frequency(st, this_attr->address, val);
+		break;
+	case AD9832_PHASE0H:
+	case AD9832_PHASE1H:
+	case AD9832_PHASE2H:
+	case AD9832_PHASE3H:
+		ret = ad9832_write_phase(st, this_attr->address, val);
+		break;
+	case AD9832_PINCTRL_EN:
+		if (val)
+			st->ctrl_ss &= ~AD9832_SELSRC;
+		else
+			st->ctrl_ss |= AD9832_SELSRC;
+		st->data = cpu_to_be16((AD9832_CMD_SYNCSELSRC << CMD_SHIFT) |
+					st->ctrl_ss);
+		ret = spi_sync(st->spi, &st->msg);
+		break;
+	case AD9832_FREQ_SYM:
+		if (val == 1)
+			st->ctrl_fp |= AD9832_FREQ;
+		else if (val == 0)
+			st->ctrl_fp &= ~AD9832_FREQ;
+		else {
+			ret = -EINVAL;
+			break;
+		}
+		st->data = cpu_to_be16((AD9832_CMD_FPSELECT << CMD_SHIFT) |
+					st->ctrl_fp);
+		ret = spi_sync(st->spi, &st->msg);
+		break;
+	case AD9832_PHASE_SYM:
+		if (val < 0 || val > 3) {
+			ret = -EINVAL;
+			break;
+		}
+
+		st->ctrl_fp &= ~AD9832_PHASE(3);
+		st->ctrl_fp |= AD9832_PHASE(val);
+
+		st->data = cpu_to_be16((AD9832_CMD_FPSELECT << CMD_SHIFT) |
+					st->ctrl_fp);
+		ret = spi_sync(st->spi, &st->msg);
+		break;
+	case AD9832_OUTPUT_EN:
+		if (val)
+			st->ctrl_src &= ~(AD9832_RESET | AD9832_SLEEP |
+					AD9832_CLR);
+		else
+			st->ctrl_src |= AD9832_RESET;
+
+		st->data = cpu_to_be16((AD9832_CMD_SLEEPRESCLR << CMD_SHIFT) |
+					st->ctrl_src);
+		ret = spi_sync(st->spi, &st->msg);
+		break;
+	default:
+		ret = -ENODEV;
+	}
+	mutex_unlock(&dev_info->mlock);
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
+error_ret:
+	return ret ? ret : len;
+}
 
-	config = CMD_SELBITSCTL << cmd_shift;
-	xfer.len = 2;
-	xfer.tx_buf = &config;
+static ssize_t ad9832_show_name(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_dev *dev_info = dev_get_drvdata(dev);
+	struct ad9832_state *st = iio_dev_get_devdata(dev_info);
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
+	return sprintf(buf, "%s\n", spi_get_device_id(st->spi)->name);
+}
+static IIO_DEVICE_ATTR(name, S_IRUGO, ad9832_show_name, NULL, 0);
 
-	config = 0x3 << 14;
+/**
+ * see dds.h for further information
+ */
 
-	xfer.len = 2;
-	xfer.tx_buf = &config;
+static IIO_DEV_ATTR_FREQ(0, 0, S_IWUSR, NULL, ad9832_write, AD9832_FREQ0HM);
+static IIO_DEV_ATTR_FREQ(0, 1, S_IWUSR, NULL, ad9832_write, AD9832_FREQ1HM);
+static IIO_DEV_ATTR_FREQSYMBOL(0, S_IWUSR, NULL, ad9832_write, AD9832_FREQ_SYM);
+static IIO_CONST_ATTR_FREQ_SCALE(0, "1"); /* 1Hz */
 
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfer, &msg);
-	ret = spi_sync(st->sdev, &msg);
-	if (ret)
-		goto error_ret;
-error_ret:
-	mutex_unlock(&st->lock);
+static IIO_DEV_ATTR_PHASE(0, 0, S_IWUSR, NULL, ad9832_write, AD9832_PHASE0H);
+static IIO_DEV_ATTR_PHASE(0, 1, S_IWUSR, NULL, ad9832_write, AD9832_PHASE1H);
+static IIO_DEV_ATTR_PHASE(0, 2, S_IWUSR, NULL, ad9832_write, AD9832_PHASE2H);
+static IIO_DEV_ATTR_PHASE(0, 3, S_IWUSR, NULL, ad9832_write, AD9832_PHASE3H);
+static IIO_DEV_ATTR_PHASESYMBOL(0, S_IWUSR, NULL,
+				ad9832_write, AD9832_PHASE_SYM);
+static IIO_CONST_ATTR_PHASE_SCALE(0, "0.0015339808"); /* 2PI/2^12 rad*/
 
+static IIO_DEV_ATTR_PINCONTROL_EN(0, S_IWUSR, NULL,
+				ad9832_write, AD9832_PINCTRL_EN);
+static IIO_DEV_ATTR_OUT_ENABLE(0, S_IWUSR, NULL,
+				ad9832_write, AD9832_OUTPUT_EN);
 
+static struct attribute *ad9832_attributes[] = {
+	&iio_dev_attr_dds0_freq0.dev_attr.attr,
+	&iio_dev_attr_dds0_freq1.dev_attr.attr,
+	&iio_const_attr_dds0_freq_scale.dev_attr.attr,
+	&iio_dev_attr_dds0_phase0.dev_attr.attr,
+	&iio_dev_attr_dds0_phase1.dev_attr.attr,
+	&iio_dev_attr_dds0_phase2.dev_attr.attr,
+	&iio_dev_attr_dds0_phase3.dev_attr.attr,
+	&iio_const_attr_dds0_phase_scale.dev_attr.attr,
+	&iio_dev_attr_dds0_pincontrol_en.dev_attr.attr,
+	&iio_dev_attr_dds0_freqsymbol.dev_attr.attr,
+	&iio_dev_attr_dds0_phasesymbol.dev_attr.attr,
+	&iio_dev_attr_dds0_out_enable.dev_attr.attr,
+	&iio_dev_attr_name.dev_attr.attr,
+	NULL,
+};
 
-}
+static const struct attribute_group ad9832_attribute_group = {
+	.attrs = ad9832_attributes,
+};
 
 static int __devinit ad9832_probe(struct spi_device *spi)
 {
+	struct ad9832_platform_data *pdata = spi->dev.platform_data;
 	struct ad9832_state *st;
-	int ret = 0;
+	int ret;
+
+	if (!pdata) {
+		dev_dbg(&spi->dev, "no platform data?\n");
+		return -ENODEV;
+	}
 
 	st = kzalloc(sizeof(*st), GFP_KERNEL);
 	if (st == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	spi_set_drvdata(spi, st);
 
-	mutex_init(&st->lock);
-	st->sdev = spi;
+	st->reg = regulator_get(&spi->dev, "vcc");
+	if (!IS_ERR(st->reg)) {
+		ret = regulator_enable(st->reg);
+		if (ret)
+			goto error_put_reg;
+	}
+
+	st->mclk = pdata->mclk;
+
+	spi_set_drvdata(spi, st);
+	st->spi = spi;
 
-	st->idev = iio_allocate_device();
-	if (st->idev == NULL) {
+	st->indio_dev = iio_allocate_device();
+	if (st->indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_st;
+		goto error_disable_reg;
 	}
-	st->idev->dev.parent = &spi->dev;
-	st->idev->num_interrupt_lines = 0;
-	st->idev->event_attrs = NULL;
 
-	st->idev->attrs = &ad9832_attribute_group;
-	st->idev->dev_data = (void *)(st);
-	st->idev->driver_module = THIS_MODULE;
-	st->idev->modes = INDIO_DIRECT_MODE;
+	st->indio_dev->dev.parent = &spi->dev;
+	st->indio_dev->attrs = &ad9832_attribute_group;
+	st->indio_dev->dev_data = (void *) st;
+	st->indio_dev->driver_module = THIS_MODULE;
+	st->indio_dev->modes = INDIO_DIRECT_MODE;
+
+	/* Setup default messages */
+
+	st->xfer.tx_buf = &st->data;
+	st->xfer.len = 2;
+
+	spi_message_init(&st->msg);
+	spi_message_add_tail(&st->xfer, &st->msg);
+
+	st->freq_xfer[0].tx_buf = &st->freq_data[0];
+	st->freq_xfer[0].len = 2;
+	st->freq_xfer[0].cs_change = 1;
+	st->freq_xfer[1].tx_buf = &st->freq_data[1];
+	st->freq_xfer[1].len = 2;
+	st->freq_xfer[1].cs_change = 1;
+	st->freq_xfer[2].tx_buf = &st->freq_data[2];
+	st->freq_xfer[2].len = 2;
+	st->freq_xfer[2].cs_change = 1;
+	st->freq_xfer[3].tx_buf = &st->freq_data[3];
+	st->freq_xfer[3].len = 2;
+
+	spi_message_init(&st->freq_msg);
+	spi_message_add_tail(&st->freq_xfer[0], &st->freq_msg);
+	spi_message_add_tail(&st->freq_xfer[1], &st->freq_msg);
+	spi_message_add_tail(&st->freq_xfer[2], &st->freq_msg);
+	spi_message_add_tail(&st->freq_xfer[3], &st->freq_msg);
+
+	st->phase_xfer[0].tx_buf = &st->phase_data[0];
+	st->phase_xfer[0].len = 2;
+	st->phase_xfer[0].cs_change = 1;
+	st->phase_xfer[1].tx_buf = &st->phase_data[1];
+	st->phase_xfer[1].len = 2;
+
+	spi_message_init(&st->phase_msg);
+	spi_message_add_tail(&st->phase_xfer[0], &st->phase_msg);
+	spi_message_add_tail(&st->phase_xfer[1], &st->phase_msg);
+
+	st->ctrl_src = AD9832_SLEEP | AD9832_RESET | AD9832_CLR;
+	st->data = cpu_to_be16((AD9832_CMD_SLEEPRESCLR << CMD_SHIFT) |
+					st->ctrl_src);
+	ret = spi_sync(st->spi, &st->msg);
+	if (ret) {
+		dev_err(&spi->dev, "device init failed\n");
+		goto error_free_device;
+	}
+
+	ret = ad9832_write_frequency(st, AD9832_FREQ0HM, pdata->freq0);
+	if (ret)
+		goto error_free_device;
+
+	ret = ad9832_write_frequency(st, AD9832_FREQ1HM, pdata->freq1);
+	if (ret)
+		goto error_free_device;
+
+	ret = ad9832_write_phase(st, AD9832_PHASE0H, pdata->phase0);
+	if (ret)
+		goto error_free_device;
+
+	ret = ad9832_write_phase(st, AD9832_PHASE1H, pdata->phase1);
+	if (ret)
+		goto error_free_device;
 
-	ret = iio_device_register(st->idev);
+	ret = ad9832_write_phase(st, AD9832_PHASE2H, pdata->phase2);
 	if (ret)
-		goto error_free_dev;
-	spi->max_speed_hz = 2000000;
-	spi->mode = SPI_MODE_3;
-	spi->bits_per_word = 16;
-	spi_setup(spi);
-	ad9832_init(st);
+		goto error_free_device;
+
+	ret = ad9832_write_phase(st, AD9832_PHASE3H, pdata->phase3);
+	if (ret)
+		goto error_free_device;
+
+	ret = iio_device_register(st->indio_dev);
+	if (ret)
+		goto error_free_device;
+
 	return 0;
 
-error_free_dev:
-	iio_free_device(st->idev);
-error_free_st:
+error_free_device:
+	iio_free_device(st->indio_dev);
+error_disable_reg:
+	if (!IS_ERR(st->reg))
+		regulator_disable(st->reg);
+error_put_reg:
+	if (!IS_ERR(st->reg))
+		regulator_put(st->reg);
 	kfree(st);
 error_ret:
 	return ret;
@@ -232,33 +340,45 @@ static int __devexit ad9832_remove(struct spi_device *spi)
 {
 	struct ad9832_state *st = spi_get_drvdata(spi);
 
-	iio_device_unregister(st->idev);
+	iio_device_unregister(st->indio_dev);
+	if (!IS_ERR(st->reg)) {
+		regulator_disable(st->reg);
+		regulator_put(st->reg);
+	}
 	kfree(st);
-
 	return 0;
 }
 
+static const struct spi_device_id ad9832_id[] = {
+	{"ad9832", 0},
+	{"ad9835", 0},
+	{}
+};
+
 static struct spi_driver ad9832_driver = {
 	.driver = {
-		.name = DRV_NAME,
-		.owner = THIS_MODULE,
+		.name	= "ad9832",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
 	},
-	.probe = ad9832_probe,
-	.remove = __devexit_p(ad9832_remove),
+	.probe		= ad9832_probe,
+	.remove		= __devexit_p(ad9832_remove),
+	.id_table	= ad9832_id,
 };
 
-static __init int ad9832_spi_init(void)
+static int __init ad9832_init(void)
 {
 	return spi_register_driver(&ad9832_driver);
 }
-module_init(ad9832_spi_init);
+module_init(ad9832_init);
 
-static __exit void ad9832_spi_exit(void)
+static void __exit ad9832_exit(void)
 {
 	spi_unregister_driver(&ad9832_driver);
 }
-module_exit(ad9832_spi_exit);
+module_exit(ad9832_exit);
 
-MODULE_AUTHOR("Cliff Cai");
-MODULE_DESCRIPTION("Analog Devices ad9832 driver");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Analog Devices AD9832/AD9835 DDS");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("spi:ad9832");
diff --git a/drivers/staging/iio/dds/ad9832.h b/drivers/staging/iio/dds/ad9832.h
new file mode 100644
index 0000000..5d47454
--- /dev/null
+++ b/drivers/staging/iio/dds/ad9832.h
@@ -0,0 +1,128 @@
+/*
+ * AD9832 SPI DDS driver
+ *
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+#ifndef IIO_DDS_AD9832_H_
+#define IIO_DDS_AD9832_H_
+
+/* Registers */
+
+#define AD9832_FREQ0LL		0x0
+#define AD9832_FREQ0HL		0x1
+#define AD9832_FREQ0LM		0x2
+#define AD9832_FREQ0HM		0x3
+#define AD9832_FREQ1LL		0x4
+#define AD9832_FREQ1HL		0x5
+#define AD9832_FREQ1LM		0x6
+#define AD9832_FREQ1HM		0x7
+#define AD9832_PHASE0L		0x8
+#define AD9832_PHASE0H		0x9
+#define AD9832_PHASE1L		0xA
+#define AD9832_PHASE1H		0xB
+#define AD9832_PHASE2L		0xC
+#define AD9832_PHASE2H		0xD
+#define AD9832_PHASE3L		0xE
+#define AD9832_PHASE3H		0xF
+
+#define AD9832_PHASE_SYM	0x10
+#define AD9832_FREQ_SYM		0x11
+#define AD9832_PINCTRL_EN	0x12
+#define AD9832_OUTPUT_EN	0x13
+
+/* Command Control Bits */
+
+#define AD9832_CMD_PHA8BITSW	0x1
+#define AD9832_CMD_PHA16BITSW	0x0
+#define AD9832_CMD_FRE8BITSW	0x3
+#define AD9832_CMD_FRE16BITSW	0x2
+#define AD9832_CMD_FPSELECT	0x6
+#define AD9832_CMD_SYNCSELSRC	0x8
+#define AD9832_CMD_SLEEPRESCLR	0xC
+
+#define AD9832_FREQ		(1 << 11)
+#define AD9832_PHASE(x)		(((x) & 3) << 9)
+#define AD9832_SYNC		(1 << 13)
+#define AD9832_SELSRC		(1 << 12)
+#define AD9832_SLEEP		(1 << 13)
+#define AD9832_RESET		(1 << 12)
+#define AD9832_CLR		(1 << 11)
+#define CMD_SHIFT		12
+#define ADD_SHIFT		8
+#define AD9832_FREQ_BITS	32
+#define AD9832_PHASE_BITS	12
+#define RES_MASK(bits)		((1 << (bits)) - 1)
+
+/**
+ * struct ad9832_state - driver instance specific data
+ * @indio_dev:		the industrial I/O device
+ * @spi:		spi_device
+ * @reg:		supply regulator
+ * @mclk:		external master clock
+ * @ctrl_fp:		cached frequency/phase control word
+ * @ctrl_ss:		cached sync/selsrc control word
+ * @ctrl_src:		cached sleep/reset/clr word
+ * @xfer:		default spi transfer
+ * @msg:		default spi message
+ * @freq_xfer:		tuning word spi transfer
+ * @freq_msg:		tuning word spi message
+ * @phase_xfer:		tuning word spi transfer
+ * @phase_msg:		tuning word spi message
+ * @data:		spi transmit buffer
+ * @phase_data:		tuning word spi transmit buffer
+ * @freq_data:		tuning word spi transmit buffer
+ */
+
+struct ad9832_state {
+	struct iio_dev			*indio_dev;
+	struct spi_device		*spi;
+	struct regulator		*reg;
+	unsigned long			mclk;
+	unsigned short			ctrl_fp;
+	unsigned short			ctrl_ss;
+	unsigned short			ctrl_src;
+	struct spi_transfer		xfer;
+	struct spi_message		msg;
+	struct spi_transfer		freq_xfer[4];
+	struct spi_message		freq_msg;
+	struct spi_transfer		phase_xfer[2];
+	struct spi_message		phase_msg;
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	union {
+		unsigned short		freq_data[4]____cacheline_aligned;
+		unsigned short		phase_data[2];
+		unsigned short		data;
+	};
+};
+
+/*
+ * TODO: struct ad9832_platform_data needs to go into include/linux/iio
+ */
+
+/**
+ * struct ad9832_platform_data - platform specific information
+ * @mclk:		master clock in Hz
+ * @freq0:		power up freq0 tuning word in Hz
+ * @freq1:		power up freq1 tuning word in Hz
+ * @phase0:		power up phase0 value [0..4095] correlates with 0..2PI
+ * @phase1:		power up phase1 value [0..4095] correlates with 0..2PI
+ * @phase2:		power up phase2 value [0..4095] correlates with 0..2PI
+ * @phase3:		power up phase3 value [0..4095] correlates with 0..2PI
+ */
+
+struct ad9832_platform_data {
+	unsigned long		mclk;
+	unsigned long		freq0;
+	unsigned long		freq1;
+	unsigned short		phase0;
+	unsigned short		phase1;
+	unsigned short		phase2;
+	unsigned short		phase3;
+};
+
+#endif /* IIO_DDS_AD9832_H_ */
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig
index 236f15f..8b78fa0 100644
--- a/drivers/staging/iio/gyro/Kconfig
+++ b/drivers/staging/iio/gyro/Kconfig
@@ -25,23 +25,13 @@ config ADIS16130
 	  Angular Rate Sensor driver.
 
 config ADIS16260
-	tristate "Analog Devices ADIS16260 ADIS16265 Digital Gyroscope Sensor SPI driver"
+	tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
 	depends on SPI
 	select IIO_TRIGGER if IIO_RING_BUFFER
 	select IIO_SW_RING if IIO_RING_BUFFER
 	help
 	  Say yes here to build support for Analog Devices ADIS16260 ADIS16265
-	  programmable digital gyroscope sensor.
+	  ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called adis16260.
-
-config ADIS16251
-	tristate "Analog Devices ADIS16251 Digital Gyroscope Sensor SPI driver"
-	depends on SPI
-	help
-	  Say yes here to build support for Analog Devices adis16261 programmable
-	  digital gyroscope sensor.
-
-	  This driver can also be built as a module.  If so, the module
-	  will be called adis16251.
diff --git a/drivers/staging/iio/gyro/adis16060.h b/drivers/staging/iio/gyro/adis16060.h
deleted file mode 100644
index 5c00e53..0000000
--- a/drivers/staging/iio/gyro/adis16060.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef SPI_ADIS16060_H_
-#define SPI_ADIS16060_H_
-
-#define ADIS16060_GYRO       0x20 /* Measure Angular Rate (Gyro) */
-#define ADIS16060_SUPPLY_OUT 0x10 /* Measure Temperature */
-#define ADIS16060_AIN2       0x80 /* Measure AIN2 */
-#define ADIS16060_AIN1       0x40 /* Measure AIN1 */
-#define ADIS16060_TEMP_OUT   0x22 /* Set Positive Self-Test and Output for Angular Rate */
-#define ADIS16060_ANGL_OUT   0x21 /* Set Negative Self-Test and Output for Angular Rate */
-
-#define ADIS16060_MAX_TX     3
-#define ADIS16060_MAX_RX     3
-
-/**
- * struct adis16060_state - device instance specific data
- * @us_w:			actual spi_device to write data
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
- * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			recieve buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16060_state {
-	struct spi_device		*us_w;
-	struct spi_device		*us_r;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
-};
-
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum adis16060_scan {
-	ADIS16060_SCAN_GYRO,
-	ADIS16060_SCAN_TEMP,
-	ADIS16060_SCAN_ADC_1,
-	ADIS16060_SCAN_ADC_2,
-};
-
-void adis16060_remove_trigger(struct iio_dev *indio_dev);
-int adis16060_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16060_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int adis16060_configure_ring(struct iio_dev *indio_dev);
-void adis16060_unconfigure_ring(struct iio_dev *indio_dev);
-
-int adis16060_initialize_ring(struct iio_ring_buffer *ring);
-void adis16060_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16060_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16060_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16060_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16060_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16060_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16060_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-
-static inline void adis16060_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_RING_BUFFER */
-#endif /* SPI_ADIS16060_H_ */
diff --git a/drivers/staging/iio/gyro/adis16060_core.c b/drivers/staging/iio/gyro/adis16060_core.c
index fc48aca..700eb39 100644
--- a/drivers/staging/iio/gyro/adis16060_core.c
+++ b/drivers/staging/iio/gyro/adis16060_core.c
@@ -6,9 +6,6 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
@@ -16,20 +13,38 @@
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
-#include <linux/list.h>
+
 
 #include "../iio.h"
 #include "../sysfs.h"
 #include "gyro.h"
 #include "../adc/adc.h"
 
-#include "adis16060.h"
-
-#define DRIVER_NAME		"adis16060"
+#define ADIS16060_GYRO		0x20 /* Measure Angular Rate (Gyro) */
+#define ADIS16060_TEMP_OUT	0x10 /* Measure Temperature */
+#define ADIS16060_AIN2		0x80 /* Measure AIN2 */
+#define ADIS16060_AIN1		0x40 /* Measure AIN1 */
+
+/**
+ * struct adis16060_state - device instance specific data
+ * @us_w:		actual spi_device to write config
+ * @us_r:		actual spi_device to read back data
+ * @indio_dev:		industrial I/O device structure
+ * @buf:		transmit or recieve buffer
+ * @buf_lock:		mutex to protect tx and rx
+ **/
+struct adis16060_state {
+	struct spi_device		*us_w;
+	struct spi_device		*us_r;
+	struct iio_dev			*indio_dev;
+	struct mutex			buf_lock;
+
+	u8 buf[3] ____cacheline_aligned;
+};
 
-struct adis16060_state *adis16060_st;
+static struct adis16060_state *adis16060_st;
 
-int adis16060_spi_write(struct device *dev,
+static int adis16060_spi_write(struct device *dev,
 		u8 val)
 {
 	int ret;
@@ -37,17 +52,14 @@ int adis16060_spi_write(struct device *dev,
 	struct adis16060_state *st = iio_dev_get_devdata(indio_dev);
 
 	mutex_lock(&st->buf_lock);
-	st->tx[0] = 0;
-	st->tx[1] = 0;
-	st->tx[2] = val; /* The last 8 bits clocked in are latched */
-
-	ret = spi_write(st->us_w, st->tx, 3);
+	st->buf[2] = val; /* The last 8 bits clocked in are latched */
+	ret = spi_write(st->us_w, st->buf, 3);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
 }
 
-int adis16060_spi_read(struct device *dev,
+static int adis16060_spi_read(struct device *dev,
 		u16 *val)
 {
 	int ret;
@@ -56,14 +68,17 @@ int adis16060_spi_read(struct device *dev,
 
 	mutex_lock(&st->buf_lock);
 
-	ret = spi_read(st->us_r, st->rx, 3);
+	ret = spi_read(st->us_r, st->buf, 3);
 
-	/* The internal successive approximation ADC begins the conversion process
-	 * on the falling edge of MSEL1 and starts to place data MSB first on the
-	 * DOUT line at the 6th falling edge of SCLK
+	/* The internal successive approximation ADC begins the
+	 * conversion process on the falling edge of MSEL1 and
+	 * starts to place data MSB first on the DOUT line at
+	 * the 6th falling edge of SCLK
 	 */
 	if (ret == 0)
-		*val = ((st->rx[0] & 0x3) << 12) | (st->rx[1] << 4) | ((st->rx[2] >> 4) & 0xF);
+		*val = ((st->buf[0] & 0x3) << 12) |
+			(st->buf[1] << 4) |
+			((st->buf[2] >> 4) & 0xF);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
@@ -73,13 +88,19 @@ static ssize_t adis16060_read(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	u16 val;
+	u16 val = 0;
 	ssize_t ret;
 
 	/* Take the iio_dev status lock */
 	mutex_lock(&indio_dev->mlock);
-	ret =  adis16060_spi_read(dev, &val);
+
+	ret = adis16060_spi_write(dev, this_attr->address);
+	if (ret < 0)
+		goto error_ret;
+	ret = adis16060_spi_read(dev, &val);
+error_ret:
 	mutex_unlock(&indio_dev->mlock);
 
 	if (ret == 0)
@@ -88,45 +109,22 @@ static ssize_t adis16060_read(struct device *dev,
 		return ret;
 }
 
-static ssize_t adis16060_write(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	int ret;
-	long val;
-
-	ret = strict_strtol(buf, 16, &val);
-	if (ret)
-		goto error_ret;
-	ret = adis16060_spi_write(dev, val);
-
-error_ret:
-	return ret ? ret : len;
-}
-
-#define IIO_DEV_ATTR_IN(_show)				\
-	IIO_DEVICE_ATTR(in, S_IRUGO, _show, NULL, 0)
-
-#define IIO_DEV_ATTR_OUT(_store)				\
-	IIO_DEVICE_ATTR(out, S_IRUGO, NULL, _store, 0)
-
-static IIO_DEV_ATTR_IN(adis16060_read);
-static IIO_DEV_ATTR_OUT(adis16060_write);
-
+static IIO_DEV_ATTR_GYRO_Z(adis16060_read, ADIS16060_GYRO);
+static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16060_read, NULL,
+		       ADIS16060_TEMP_OUT);
+static IIO_CONST_ATTR_TEMP_SCALE("34"); /* Milli degrees C */
+static IIO_CONST_ATTR_TEMP_OFFSET("-7461.117"); /* Milli degrees C */
+static IIO_DEV_ATTR_IN_RAW(0, adis16060_read, ADIS16060_AIN1);
+static IIO_DEV_ATTR_IN_RAW(1, adis16060_read, ADIS16060_AIN2);
 static IIO_CONST_ATTR(name, "adis16060");
 
-static struct attribute *adis16060_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group adis16060_event_attribute_group = {
-	.attrs = adis16060_event_attributes,
-};
-
 static struct attribute *adis16060_attributes[] = {
-	&iio_dev_attr_in.dev_attr.attr,
-	&iio_dev_attr_out.dev_attr.attr,
+	&iio_dev_attr_gyro_z_raw.dev_attr.attr,
+	&iio_dev_attr_temp_raw.dev_attr.attr,
+	&iio_const_attr_temp_scale.dev_attr.attr,
+	&iio_const_attr_temp_offset.dev_attr.attr,
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
 	&iio_const_attr_name.dev_attr.attr,
 	NULL
 };
@@ -146,82 +144,34 @@ static int __devinit adis16060_r_probe(struct spi_device *spi)
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, st);
 
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16060_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16060_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us_r = spi;
 	mutex_init(&st->buf_lock);
 	/* setup the industrialio driver allocated elements */
 	st->indio_dev = iio_allocate_device();
 	if (st->indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_tx;
+		goto error_free_st;
 	}
 
 	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &adis16060_event_attribute_group;
 	st->indio_dev->attrs = &adis16060_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16060_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
+		goto error_free_dev;
 	regdone = 1;
 
-	ret = adis16060_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_RISING,
-				"adis16060");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = adis16060_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
-
 	adis16060_st = st;
 	return 0;
 
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	adis16060_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	adis16060_unconfigure_ring(st->indio_dev);
 error_free_dev:
 	if (regdone)
 		iio_device_unregister(st->indio_dev);
 	else
 		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
 error_free_st:
 	kfree(st);
 error_ret:
@@ -234,17 +184,7 @@ static int adis16060_r_remove(struct spi_device *spi)
 	struct adis16060_state *st = spi_get_drvdata(spi);
 	struct iio_dev *indio_dev = st->indio_dev;
 
-	flush_scheduled_work();
-
-	adis16060_remove_trigger(indio_dev);
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	adis16060_uninitialize_ring(indio_dev->ring);
-	adis16060_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
 	kfree(st);
 
 	return 0;
@@ -315,5 +255,5 @@ static __exit void adis16060_exit(void)
 module_exit(adis16060_exit);
 
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16060 Yaw Rate Gyroscope with SPI driver");
+MODULE_DESCRIPTION("Analog Devices ADIS16060 Yaw Rate Gyroscope Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/gyro/adis16080.h b/drivers/staging/iio/gyro/adis16080.h
deleted file mode 100644
index 3fcbe67..0000000
--- a/drivers/staging/iio/gyro/adis16080.h
+++ /dev/null
@@ -1,102 +0,0 @@
-#ifndef SPI_ADIS16080_H_
-#define SPI_ADIS16080_H_
-
-#define ADIS16080_DIN_CODE   4 /* Output data format setting. 0: Twos complement. 1: Offset binary. */
-#define ADIS16080_DIN_GYRO   (0 << 10) /* Gyroscope output */
-#define ADIS16080_DIN_TEMP   (1 << 10) /* Temperature output */
-#define ADIS16080_DIN_AIN1   (2 << 10)
-#define ADIS16080_DIN_AIN2   (3 << 10)
-#define ADIS16080_DIN_WRITE  (1 << 15) /* 1: Write contents on DIN to control register.
-					* 0: No changes to control register.
-					*/
-
-#define ADIS16080_MAX_TX     2
-#define ADIS16080_MAX_RX     2
-
-/**
- * struct adis16080_state - device instance specific data
- * @us:			actual spi_device to write data
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
- * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			recieve buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16080_state {
-	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
-};
-
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum adis16080_scan {
-	ADIS16080_SCAN_GYRO,
-	ADIS16080_SCAN_TEMP,
-	ADIS16080_SCAN_ADC_1,
-	ADIS16080_SCAN_ADC_2,
-};
-
-void adis16080_remove_trigger(struct iio_dev *indio_dev);
-int adis16080_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16080_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int adis16080_configure_ring(struct iio_dev *indio_dev);
-void adis16080_unconfigure_ring(struct iio_dev *indio_dev);
-
-int adis16080_initialize_ring(struct iio_ring_buffer *ring);
-void adis16080_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16080_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16080_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16080_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16080_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16080_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16080_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-
-static inline void adis16080_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_RING_BUFFER */
-#endif /* SPI_ADIS16080_H_ */
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index 0efb768..fb4336c 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -5,9 +5,6 @@
  *
  * Licensed under the GPL-2 or later.
  */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
@@ -16,20 +13,40 @@
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/sysfs.h>
-#include <linux/list.h>
 
 #include "../iio.h"
 #include "../sysfs.h"
 #include "gyro.h"
 #include "../adc/adc.h"
 
-#include "adis16080.h"
+#define ADIS16080_DIN_GYRO   (0 << 10) /* Gyroscope output */
+#define ADIS16080_DIN_TEMP   (1 << 10) /* Temperature output */
+#define ADIS16080_DIN_AIN1   (2 << 10)
+#define ADIS16080_DIN_AIN2   (3 << 10)
 
-#define DRIVER_NAME		"adis16080"
+/*
+ * 1: Write contents on DIN to control register.
+ * 0: No changes to control register.
+ */
 
-struct adis16080_state *adis16080_st;
+#define ADIS16080_DIN_WRITE  (1 << 15)
+
+/**
+ * struct adis16080_state - device instance specific data
+ * @us:			actual spi_device to write data
+ * @indio_dev:		industrial I/O device structure
+ * @buf:		transmit or recieve buffer
+ * @buf_lock:		mutex to protect tx and rx
+ **/
+struct adis16080_state {
+	struct spi_device		*us;
+	struct iio_dev			*indio_dev;
+	struct mutex			buf_lock;
+
+	u8 buf[2] ____cacheline_aligned;
+};
 
-int adis16080_spi_write(struct device *dev,
+static int adis16080_spi_write(struct device *dev,
 		u16 val)
 {
 	int ret;
@@ -37,16 +54,16 @@ int adis16080_spi_write(struct device *dev,
 	struct adis16080_state *st = iio_dev_get_devdata(indio_dev);
 
 	mutex_lock(&st->buf_lock);
-	st->tx[0] = val >> 8;
-	st->tx[1] = val;
+	st->buf[0] = val >> 8;
+	st->buf[1] = val;
 
-	ret = spi_write(st->us, st->tx, 2);
+	ret = spi_write(st->us, st->buf, 2);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
 }
 
-int adis16080_spi_read(struct device *dev,
+static int adis16080_spi_read(struct device *dev,
 		u16 *val)
 {
 	int ret;
@@ -55,10 +72,10 @@ int adis16080_spi_read(struct device *dev,
 
 	mutex_lock(&st->buf_lock);
 
-	ret = spi_read(st->us, st->rx, 2);
+	ret = spi_read(st->us, st->buf, 2);
 
 	if (ret == 0)
-		*val = ((st->rx[0] & 0xF) << 8) | st->rx[1];
+		*val = ((st->buf[0] & 0xF) << 8) | st->buf[1];
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
@@ -68,13 +85,19 @@ static ssize_t adis16080_read(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	u16 val;
+	u16 val = 0;
 	ssize_t ret;
 
 	/* Take the iio_dev status lock */
 	mutex_lock(&indio_dev->mlock);
+	ret = adis16080_spi_write(dev,
+				  this_attr->address | ADIS16080_DIN_WRITE);
+	if (ret < 0)
+		goto error_ret;
 	ret =  adis16080_spi_read(dev, &val);
+error_ret:
 	mutex_unlock(&indio_dev->mlock);
 
 	if (ret == 0)
@@ -82,46 +105,18 @@ static ssize_t adis16080_read(struct device *dev,
 	else
 		return ret;
 }
-
-static ssize_t adis16080_write(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	int ret;
-	long val;
-
-	ret = strict_strtol(buf, 16, &val);
-	if (ret)
-		goto error_ret;
-	ret = adis16080_spi_write(dev, val);
-
-error_ret:
-	return ret ? ret : len;
-}
-
-#define IIO_DEV_ATTR_IN(_show)				\
-	IIO_DEVICE_ATTR(in, S_IRUGO, _show, NULL, 0)
-
-#define IIO_DEV_ATTR_OUT(_store)				\
-	IIO_DEVICE_ATTR(out, S_IRUGO, NULL, _store, 0)
-
-static IIO_DEV_ATTR_IN(adis16080_read);
-static IIO_DEV_ATTR_OUT(adis16080_write);
-
+static IIO_DEV_ATTR_GYRO_Z(adis16080_read, ADIS16080_DIN_GYRO);
+static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16080_read, NULL,
+		       ADIS16080_DIN_TEMP);
+static IIO_DEV_ATTR_IN_RAW(0, adis16080_read, ADIS16080_DIN_AIN1);
+static IIO_DEV_ATTR_IN_RAW(1, adis16080_read, ADIS16080_DIN_AIN2);
 static IIO_CONST_ATTR(name, "adis16080");
 
-static struct attribute *adis16080_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group adis16080_event_attribute_group = {
-	.attrs = adis16080_event_attributes,
-};
-
 static struct attribute *adis16080_attributes[] = {
-	&iio_dev_attr_in.dev_attr.attr,
-	&iio_dev_attr_out.dev_attr.attr,
+	&iio_dev_attr_gyro_z_raw.dev_attr.attr,
+	&iio_dev_attr_temp_raw.dev_attr.attr,
+	&iio_dev_attr_in0_raw.dev_attr.attr,
+	&iio_dev_attr_in1_raw.dev_attr.attr,
 	&iio_const_attr_name.dev_attr.attr,
 	NULL
 };
@@ -142,81 +137,33 @@ static int __devinit adis16080_probe(struct spi_device *spi)
 	spi_set_drvdata(spi, st);
 
 	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16080_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16080_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us = spi;
 	mutex_init(&st->buf_lock);
 	/* setup the industrialio driver allocated elements */
 	st->indio_dev = iio_allocate_device();
 	if (st->indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_tx;
+		goto error_free_st;
 	}
 
 	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &adis16080_event_attribute_group;
 	st->indio_dev->attrs = &adis16080_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = adis16080_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
+		goto error_free_dev;
 	regdone = 1;
 
-	ret = adis16080_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_RISING,
-				"adis16080");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = adis16080_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
-
-	adis16080_st = st;
 	return 0;
 
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	adis16080_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	adis16080_unconfigure_ring(st->indio_dev);
 error_free_dev:
 	if (regdone)
 		iio_device_unregister(st->indio_dev);
 	else
 		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
 error_free_st:
 	kfree(st);
 error_ret:
@@ -229,17 +176,7 @@ static int adis16080_remove(struct spi_device *spi)
 	struct adis16080_state *st = spi_get_drvdata(spi);
 	struct iio_dev *indio_dev = st->indio_dev;
 
-	flush_scheduled_work();
-
-	adis16080_remove_trigger(indio_dev);
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	adis16080_uninitialize_ring(indio_dev->ring);
-	adis16080_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
 	kfree(st);
 
 	return 0;
@@ -267,5 +204,5 @@ static __exit void adis16080_exit(void)
 module_exit(adis16080_exit);
 
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope with SPI driver");
+MODULE_DESCRIPTION("Analog Devices ADIS16080/100 Yaw Rate Gyroscope Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/gyro/adis16130.h b/drivers/staging/iio/gyro/adis16130.h
deleted file mode 100644
index ab80ef6..0000000
--- a/drivers/staging/iio/gyro/adis16130.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef SPI_ADIS16130_H_
-#define SPI_ADIS16130_H_
-
-#define ADIS16130_CON         0x0
-#define ADIS16130_CON_RD      (1 << 6)
-#define ADIS16130_IOP         0x1
-#define ADIS16130_IOP_ALL_RDY (1 << 3) /* 1 = data-ready signal low when unread data on all channels; */
-#define ADIS16130_IOP_SYNC    (1 << 0) /* 1 = synchronization enabled */
-#define ADIS16130_RATEDATA    0x8 /* Gyroscope output, rate of rotation */
-#define ADIS16130_TEMPDATA    0xA /* Temperature output */
-#define ADIS16130_RATECS      0x28 /* Gyroscope channel setup */
-#define ADIS16130_RATECS_EN   (1 << 3) /* 1 = channel enable; */
-#define ADIS16130_TEMPCS      0x2A /* Temperature channel setup */
-#define ADIS16130_TEMPCS_EN   (1 << 3)
-#define ADIS16130_RATECONV    0x30
-#define ADIS16130_TEMPCONV    0x32
-#define ADIS16130_MODE        0x38
-#define ADIS16130_MODE_24BIT  (1 << 1) /* 1 = 24-bit resolution; */
-
-#define ADIS16130_MAX_TX     4
-#define ADIS16130_MAX_RX     4
-
-/**
- * struct adis16130_state - device instance specific data
- * @us:			actual spi_device to write data
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
- * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			recieve buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16130_state {
-	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	u32                             mode; /* 1: 24bits mode 0:16bits mode */
-	struct mutex			buf_lock;
-};
-
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum adis16130_scan {
-	ADIS16130_SCAN_GYRO,
-	ADIS16130_SCAN_TEMP,
-};
-
-void adis16130_remove_trigger(struct iio_dev *indio_dev);
-int adis16130_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16130_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int adis16130_configure_ring(struct iio_dev *indio_dev);
-void adis16130_unconfigure_ring(struct iio_dev *indio_dev);
-
-int adis16130_initialize_ring(struct iio_ring_buffer *ring);
-void adis16130_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16130_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16130_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16130_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16130_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16130_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16130_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-
-static inline void adis16130_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_RING_BUFFER */
-#endif /* SPI_ADIS16130_H_ */
diff --git a/drivers/staging/iio/gyro/adis16130_core.c b/drivers/staging/iio/gyro/adis16130_core.c
index 49ffc7b..70e2831 100644
--- a/drivers/staging/iio/gyro/adis16130_core.c
+++ b/drivers/staging/iio/gyro/adis16130_core.c
@@ -6,9 +6,6 @@
  * Licensed under the GPL-2 or later.
  */
 
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <linux/device.h>
@@ -23,13 +20,41 @@
 #include "gyro.h"
 #include "../adc/adc.h"
 
-#include "adis16130.h"
-
-#define DRIVER_NAME		"adis16130"
-
-struct adis16130_state *adis16130_st;
+#define ADIS16130_CON         0x0
+#define ADIS16130_CON_RD      (1 << 6)
+#define ADIS16130_IOP         0x1
+
+/* 1 = data-ready signal low when unread data on all channels; */
+#define ADIS16130_IOP_ALL_RDY (1 << 3)
+#define ADIS16130_IOP_SYNC    (1 << 0) /* 1 = synchronization enabled */
+#define ADIS16130_RATEDATA    0x8 /* Gyroscope output, rate of rotation */
+#define ADIS16130_TEMPDATA    0xA /* Temperature output */
+#define ADIS16130_RATECS      0x28 /* Gyroscope channel setup */
+#define ADIS16130_RATECS_EN   (1 << 3) /* 1 = channel enable; */
+#define ADIS16130_TEMPCS      0x2A /* Temperature channel setup */
+#define ADIS16130_TEMPCS_EN   (1 << 3)
+#define ADIS16130_RATECONV    0x30
+#define ADIS16130_TEMPCONV    0x32
+#define ADIS16130_MODE        0x38
+#define ADIS16130_MODE_24BIT  (1 << 1) /* 1 = 24-bit resolution; */
+
+/**
+ * struct adis16130_state - device instance specific data
+ * @us:			actual spi_device to write data
+ * @indio_dev:		industrial I/O device structure
+ * @mode:		24 bits (1) or 16 bits (0)
+ * @buf_lock:		mutex to protect tx and rx
+ * @buf:		unified tx/rx buffer
+ **/
+struct adis16130_state {
+	struct spi_device		*us;
+	struct iio_dev			*indio_dev;
+	u32                             mode;
+	struct mutex			buf_lock;
+	u8				buf[4] ____cacheline_aligned;
+};
 
-int adis16130_spi_write(struct device *dev, u8 reg_addr,
+static int adis16130_spi_write(struct device *dev, u8 reg_addr,
 		u8 val)
 {
 	int ret;
@@ -37,16 +62,16 @@ int adis16130_spi_write(struct device *dev, u8 reg_addr,
 	struct adis16130_state *st = iio_dev_get_devdata(indio_dev);
 
 	mutex_lock(&st->buf_lock);
-	st->tx[0] = reg_addr;
-	st->tx[1] = val;
+	st->buf[0] = reg_addr;
+	st->buf[1] = val;
 
-	ret = spi_write(st->us, st->tx, 2);
+	ret = spi_write(st->us, st->buf, 2);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
 }
 
-int adis16130_spi_read(struct device *dev, u8 reg_addr,
+static int adis16130_spi_read(struct device *dev, u8 reg_addr,
 		u32 *val)
 {
 	int ret;
@@ -55,17 +80,19 @@ int adis16130_spi_read(struct device *dev, u8 reg_addr,
 
 	mutex_lock(&st->buf_lock);
 
-	st->tx[0] = ADIS16130_CON_RD | reg_addr;
+	st->buf[0] = ADIS16130_CON_RD | reg_addr;
 	if (st->mode)
-		ret = spi_read(st->us, st->rx, 4);
+		ret = spi_read(st->us, st->buf, 4);
 	else
-		ret = spi_read(st->us, st->rx, 3);
+		ret = spi_read(st->us, st->buf, 3);
 
 	if (ret == 0) {
 		if (st->mode)
-			*val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
+			*val = (st->buf[1] << 16) |
+				(st->buf[2] << 8) |
+				st->buf[3];
 		else
-			*val = (st->rx[1] << 8) | st->rx[2];
+			*val = (st->buf[1] << 8) | st->buf[2];
 	}
 
 	mutex_unlock(&st->buf_lock);
@@ -73,36 +100,18 @@ int adis16130_spi_read(struct device *dev, u8 reg_addr,
 	return ret;
 }
 
-static ssize_t adis16130_gyro_read(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	u32 val;
-	ssize_t ret;
-
-	/* Take the iio_dev status lock */
-	mutex_lock(&indio_dev->mlock);
-	ret =  adis16130_spi_read(dev, ADIS16130_RATEDATA, &val);
-	mutex_unlock(&indio_dev->mlock);
-
-	if (ret == 0)
-		return sprintf(buf, "%d\n", val);
-	else
-		return ret;
-}
-
-static ssize_t adis16130_temp_read(struct device *dev,
+static ssize_t adis16130_val_read(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
+	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	u32 val;
 	ssize_t ret;
 
 	/* Take the iio_dev status lock */
 	mutex_lock(&indio_dev->mlock);
-	ret =  adis16130_spi_read(dev, ADIS16130_TEMPDATA, &val);
+	ret =  adis16130_spi_read(dev, this_attr->address, &val);
 	mutex_unlock(&indio_dev->mlock);
 
 	if (ret == 0)
@@ -118,7 +127,10 @@ static ssize_t adis16130_bitsmode_read(struct device *dev,
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct adis16130_state *st = iio_dev_get_devdata(indio_dev);
 
-	return sprintf(buf, "%d\n", st->mode);
+	if (st->mode == 1)
+		return sprintf(buf, "s24\n");
+	else
+		return sprintf(buf, "s16\n");
 }
 
 static ssize_t adis16130_bitsmode_write(struct device *dev,
@@ -127,43 +139,38 @@ static ssize_t adis16130_bitsmode_write(struct device *dev,
 		size_t len)
 {
 	int ret;
-	long val;
+	u8 val;
 
-	ret = strict_strtol(buf, 16, &val);
-	if (ret)
-		goto error_ret;
-	ret = adis16130_spi_write(dev, ADIS16130_MODE, !!val);
+	if (sysfs_streq(buf, "s16"))
+		val = 0;
+	else if (sysfs_streq(buf, "s24"))
+		val = 1;
+	else
+		return -EINVAL;
+
+	ret = adis16130_spi_write(dev, ADIS16130_MODE, val);
 
-error_ret:
 	return ret ? ret : len;
 }
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16130_temp_read);
+static IIO_DEVICE_ATTR(temp_raw, S_IRUGO, adis16130_val_read, NULL,
+		      ADIS16130_TEMPDATA);
 
 static IIO_CONST_ATTR(name, "adis16130");
 
-static IIO_DEV_ATTR_GYRO(adis16130_gyro_read,
-		ADIS16130_RATEDATA);
-
-#define IIO_DEV_ATTR_BITS_MODE(_mode, _show, _store, _addr)	\
-	IIO_DEVICE_ATTR(bits_mode, _mode, _show, _store, _addr)
+static IIO_DEV_ATTR_GYRO_Z(adis16130_val_read, ADIS16130_RATEDATA);
 
-static IIO_DEV_ATTR_BITS_MODE(S_IWUSR | S_IRUGO, adis16130_bitsmode_read, adis16130_bitsmode_write,
+static IIO_DEVICE_ATTR(gyro_z_type, S_IWUSR | S_IRUGO, adis16130_bitsmode_read,
+			adis16130_bitsmode_write,
 			ADIS16130_MODE);
 
-static struct attribute *adis16130_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group adis16130_event_attribute_group = {
-	.attrs = adis16130_event_attributes,
-};
+static IIO_CONST_ATTR(gyro_z_type_available, "s16 s24");
 
 static struct attribute *adis16130_attributes[] = {
 	&iio_dev_attr_temp_raw.dev_attr.attr,
 	&iio_const_attr_name.dev_attr.attr,
-	&iio_dev_attr_gyro_raw.dev_attr.attr,
-	&iio_dev_attr_bits_mode.dev_attr.attr,
+	&iio_dev_attr_gyro_z_raw.dev_attr.attr,
+	&iio_dev_attr_gyro_z_type.dev_attr.attr,
+	&iio_const_attr_gyro_z_type_available.dev_attr.attr,
 	NULL
 };
 
@@ -173,7 +180,7 @@ static const struct attribute_group adis16130_attribute_group = {
 
 static int __devinit adis16130_probe(struct spi_device *spi)
 {
-	int ret, regdone = 0;
+	int ret;
 	struct adis16130_state *st = kzalloc(sizeof *st, GFP_KERNEL);
 	if (!st) {
 		ret =  -ENOMEM;
@@ -181,84 +188,30 @@ static int __devinit adis16130_probe(struct spi_device *spi)
 	}
 	/* this is only used for removal purposes */
 	spi_set_drvdata(spi, st);
-
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16130_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16130_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
 	st->us = spi;
 	mutex_init(&st->buf_lock);
 	/* setup the industrialio driver allocated elements */
 	st->indio_dev = iio_allocate_device();
 	if (st->indio_dev == NULL) {
 		ret = -ENOMEM;
-		goto error_free_tx;
+		goto error_free_st;
 	}
 
 	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &adis16130_event_attribute_group;
 	st->indio_dev->attrs = &adis16130_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 	st->mode = 1;
 
-	ret = adis16130_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
-	regdone = 1;
-
-	ret = adis16130_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_RISING,
-				"adis16130");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = adis16130_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
+		goto error_free_dev;
 
-	adis16130_st = st;
 	return 0;
 
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	adis16130_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	adis16130_unconfigure_ring(st->indio_dev);
 error_free_dev:
-	if (regdone)
-		iio_device_unregister(st->indio_dev);
-	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
+	iio_free_device(st->indio_dev);
 error_free_st:
 	kfree(st);
 error_ret:
@@ -271,17 +224,7 @@ static int adis16130_remove(struct spi_device *spi)
 	struct adis16130_state *st = spi_get_drvdata(spi);
 	struct iio_dev *indio_dev = st->indio_dev;
 
-	flush_scheduled_work();
-
-	adis16130_remove_trigger(indio_dev);
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	adis16130_uninitialize_ring(indio_dev->ring);
-	adis16130_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
 	kfree(st);
 
 	return 0;
@@ -309,5 +252,5 @@ static __exit void adis16130_exit(void)
 module_exit(adis16130_exit);
 
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate Sensor driver");
+MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/gyro/adis16251.h b/drivers/staging/iio/gyro/adis16251.h
deleted file mode 100644
index d23852c..0000000
--- a/drivers/staging/iio/gyro/adis16251.h
+++ /dev/null
@@ -1,185 +0,0 @@
-#ifndef SPI_ADIS16251_H_
-#define SPI_ADIS16251_H_
-
-#define ADIS16251_STARTUP_DELAY	220 /* ms */
-
-#define ADIS16251_READ_REG(a)    a
-#define ADIS16251_WRITE_REG(a) ((a) | 0x80)
-
-#define ADIS16251_ENDURANCE  0x00 /* Flash memory write count */
-#define ADIS16251_SUPPLY_OUT 0x02 /* Power supply measurement */
-#define ADIS16251_GYRO_OUT   0x04 /* X-axis gyroscope output */
-#define ADIS16251_AUX_ADC    0x0A /* analog input channel measurement */
-#define ADIS16251_TEMP_OUT   0x0C /* internal temperature measurement */
-#define ADIS16251_ANGL_OUT   0x0E /* angle displacement */
-#define ADIS16251_GYRO_OFF   0x14 /* Calibration, offset/bias adjustment */
-#define ADIS16251_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
-#define ADIS16251_ALM_MAG1   0x20 /* Alarm 1 magnitude/polarity setting */
-#define ADIS16251_ALM_MAG2   0x22 /* Alarm 2 magnitude/polarity setting */
-#define ADIS16251_ALM_SMPL1  0x24 /* Alarm 1 dynamic rate of change setting */
-#define ADIS16251_ALM_SMPL2  0x26 /* Alarm 2 dynamic rate of change setting */
-#define ADIS16251_ALM_CTRL   0x28 /* Alarm control */
-#define ADIS16251_AUX_DAC    0x30 /* Auxiliary DAC data */
-#define ADIS16251_GPIO_CTRL  0x32 /* Control, digital I/O line */
-#define ADIS16251_MSC_CTRL   0x34 /* Control, data ready, self-test settings */
-#define ADIS16251_SMPL_PRD   0x36 /* Control, internal sample rate */
-#define ADIS16251_SENS_AVG   0x38 /* Control, dynamic range, filtering */
-#define ADIS16251_SLP_CNT    0x3A /* Control, sleep mode initiation */
-#define ADIS16251_DIAG_STAT  0x3C /* Diagnostic, error flags */
-#define ADIS16251_GLOB_CMD   0x3E /* Control, global commands */
-
-#define ADIS16251_ERROR_ACTIVE			(1<<14)
-#define ADIS16251_NEW_DATA			(1<<14)
-
-/* MSC_CTRL */
-#define ADIS16251_MSC_CTRL_INT_SELF_TEST	(1<<10) /* Internal self-test enable */
-#define ADIS16251_MSC_CTRL_NEG_SELF_TEST	(1<<9)
-#define ADIS16251_MSC_CTRL_POS_SELF_TEST	(1<<8)
-#define ADIS16251_MSC_CTRL_DATA_RDY_EN		(1<<2)
-#define ADIS16251_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
-#define ADIS16251_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
-
-/* SMPL_PRD */
-#define ADIS16251_SMPL_PRD_TIME_BASE	(1<<7) /* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
-#define ADIS16251_SMPL_PRD_DIV_MASK	0x7F
-
-/* SLP_CNT */
-#define ADIS16251_SLP_CNT_POWER_OFF     0x80
-
-/* DIAG_STAT */
-#define ADIS16251_DIAG_STAT_ALARM2	(1<<9)
-#define ADIS16251_DIAG_STAT_ALARM1	(1<<8)
-#define ADIS16251_DIAG_STAT_SELF_TEST	(1<<5)
-#define ADIS16251_DIAG_STAT_OVERFLOW	(1<<4)
-#define ADIS16251_DIAG_STAT_SPI_FAIL	(1<<3)
-#define ADIS16251_DIAG_STAT_FLASH_UPT	(1<<2)
-#define ADIS16251_DIAG_STAT_POWER_HIGH	(1<<1)
-#define ADIS16251_DIAG_STAT_POWER_LOW	(1<<0)
-
-#define ADIS16251_DIAG_STAT_ERR_MASK (ADIS16251_DIAG_STAT_ALARM2 | \
-				      ADIS16251_DIAG_STAT_ALARM1 | \
-				      ADIS16251_DIAG_STAT_SELF_TEST | \
-				      ADIS16251_DIAG_STAT_OVERFLOW | \
-				      ADIS16251_DIAG_STAT_SPI_FAIL | \
-				      ADIS16251_DIAG_STAT_FLASH_UPT | \
-				      ADIS16251_DIAG_STAT_POWER_HIGH | \
-				      ADIS16251_DIAG_STAT_POWER_LOW)
-
-/* GLOB_CMD */
-#define ADIS16251_GLOB_CMD_SW_RESET	(1<<7)
-#define ADIS16251_GLOB_CMD_FLASH_UPD	(1<<3)
-#define ADIS16251_GLOB_CMD_DAC_LATCH	(1<<2)
-#define ADIS16251_GLOB_CMD_FAC_CALIB	(1<<1)
-#define ADIS16251_GLOB_CMD_AUTO_NULL	(1<<0)
-
-#define ADIS16251_MAX_TX 24
-#define ADIS16251_MAX_RX 24
-
-#define ADIS16251_SPI_SLOW	(u32)(300 * 1000)
-#define ADIS16251_SPI_BURST	(u32)(1000 * 1000)
-#define ADIS16251_SPI_FAST	(u32)(2000 * 1000)
-
-/**
- * struct adis16251_state - device instance specific data
- * @us:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
- * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
- * @tx:			transmit buffer
- * @rx:			recieve buffer
- * @buf_lock:		mutex to protect tx and rx
- **/
-struct adis16251_state {
-	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
-	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
-	u8				*tx;
-	u8				*rx;
-	struct mutex			buf_lock;
-};
-
-int adis16251_spi_write_reg_8(struct device *dev,
-			      u8 reg_address,
-			      u8 val);
-
-int adis16251_spi_read_burst(struct device *dev, u8 *rx);
-
-int adis16251_spi_read_sequence(struct device *dev,
-				      u8 *tx, u8 *rx, int num);
-
-int adis16251_set_irq(struct device *dev, bool enable);
-
-int adis16251_reset(struct device *dev);
-
-int adis16251_stop_device(struct device *dev);
-
-int adis16251_check_status(struct device *dev);
-
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum adis16251_scan {
-	ADIS16251_SCAN_SUPPLY,
-	ADIS16251_SCAN_GYRO,
-	ADIS16251_SCAN_TEMP,
-	ADIS16251_SCAN_ADC_0,
-};
-
-void adis16251_remove_trigger(struct iio_dev *indio_dev);
-int adis16251_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t adis16251_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int adis16251_configure_ring(struct iio_dev *indio_dev);
-void adis16251_unconfigure_ring(struct iio_dev *indio_dev);
-
-int adis16251_initialize_ring(struct iio_ring_buffer *ring);
-void adis16251_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void adis16251_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16251_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-adis16251_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int adis16251_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void adis16251_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-
-static inline int adis16251_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-
-static inline void adis16251_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-
-#endif /* CONFIG_IIO_RING_BUFFER */
-#endif /* SPI_ADIS16251_H_ */
diff --git a/drivers/staging/iio/gyro/adis16251_core.c b/drivers/staging/iio/gyro/adis16251_core.c
deleted file mode 100644
index a0d400f..0000000
--- a/drivers/staging/iio/gyro/adis16251_core.c
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- * ADIS16251 Programmable Digital Gyroscope Sensor Driver
- *
- * Copyright 2010 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/spi/spi.h>
-#include <linux/slab.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-
-#include "../iio.h"
-#include "../sysfs.h"
-#include "gyro.h"
-#include "../adc/adc.h"
-
-#include "adis16251.h"
-
-#define DRIVER_NAME		"adis16251"
-
-/* At the moment the spi framework doesn't allow global setting of cs_change.
- * It's in the likely to be added comment at the top of spi.h.
- * This means that use cannot be made of spi_write etc.
- */
-
-/**
- * adis16251_spi_write_reg_8() - write single byte to a register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the register to be written
- * @val: the value to write
- **/
-int adis16251_spi_write_reg_8(struct device *dev,
-		u8 reg_address,
-		u8 val)
-{
-	int ret;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16251_state *st = iio_dev_get_devdata(indio_dev);
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16251_WRITE_REG(reg_address);
-	st->tx[1] = val;
-
-	ret = spi_write(st->us, st->tx, 2);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16251_spi_write_reg_16() - write 2 bytes to a pair of registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: value to be written
- **/
-static int adis16251_spi_write_reg_16(struct device *dev,
-		u8 lower_reg_address,
-		u16 value)
-{
-	int ret;
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16251_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		}, {
-			.tx_buf = st->tx + 2,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16251_WRITE_REG(lower_reg_address);
-	st->tx[1] = value & 0xFF;
-	st->tx[2] = ADIS16251_WRITE_REG(lower_reg_address + 1);
-	st->tx[3] = (value >> 8) & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	mutex_unlock(&st->buf_lock);
-
-	return ret;
-}
-
-/**
- * adis16251_spi_read_reg_16() - read 2 bytes from a 16-bit register
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @reg_address: the address of the lower of the two registers. Second register
- *               is assumed to have address one greater.
- * @val: somewhere to pass back the value read
- **/
-static int adis16251_spi_read_reg_16(struct device *dev,
-		u8 lower_reg_address,
-		u16 *val)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16251_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		}, {
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 1,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16251_READ_REG(lower_reg_address);
-	st->tx[1] = 0;
-	st->tx[2] = 0;
-	st->tx[3] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
-		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				lower_reg_address);
-		goto error_ret;
-	}
-	*val = (st->rx[0] << 8) | st->rx[1];
-
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-/**
- * adis16251_spi_read_burst() - read all data registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @rx: somewhere to pass back the value read (min size is 24 bytes)
- **/
-int adis16251_spi_read_burst(struct device *dev, u8 *rx)
-{
-	struct spi_message msg;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16251_state *st = iio_dev_get_devdata(indio_dev);
-	u32 old_speed_hz = st->us->max_speed_hz;
-	int ret;
-
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 2,
-			.cs_change = 0,
-		}, {
-			.rx_buf = rx,
-			.bits_per_word = 8,
-			.len = 24,
-			.cs_change = 1,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADIS16251_READ_REG(ADIS16251_GLOB_CMD);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(&xfers[0], &msg);
-	spi_message_add_tail(&xfers[1], &msg);
-
-	st->us->max_speed_hz = min(ADIS16251_SPI_BURST, old_speed_hz);
-	spi_setup(st->us);
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when burst reading");
-
-	st->us->max_speed_hz = old_speed_hz;
-	spi_setup(st->us);
-	mutex_unlock(&st->buf_lock);
-	return ret;
-}
-
-/**
- * adis16251_spi_read_sequence() - read a sequence of 16-bit registers
- * @dev: device associated with child of actual device (iio_dev or iio_trig)
- * @tx: register addresses in bytes 0,2,4,6... (min size is 2*num bytes)
- * @rx: somewhere to pass back the value read (min size is 2*num bytes)
- **/
-int adis16251_spi_read_sequence(struct device *dev,
-		u8 *tx, u8 *rx, int num)
-{
-	struct spi_message msg;
-	struct spi_transfer *xfers;
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16251_state *st = iio_dev_get_devdata(indio_dev);
-	int ret, i;
-
-	xfers = kzalloc(num + 1, GFP_KERNEL);
-	if (xfers == NULL) {
-		dev_err(&st->us->dev, "memory alloc failed");
-		ret = -ENOMEM;
-		goto error_ret;
-	}
-
-	/* tx: |add1|addr2|addr3|...|addrN |zero|
-	 * rx: |zero|res1 |res2 |...|resN-1|resN| */
-	spi_message_init(&msg);
-	for (i = 0; i < num + 1; i++) {
-		if (i > 0)
-			xfers[i].rx_buf = st->rx + 2*(i - 1);
-		if (i < num)
-			xfers[i].tx_buf = st->tx + 2*i;
-		xfers[i].bits_per_word = 8;
-		xfers[i].len = 2;
-		xfers[i].cs_change = 1;
-		spi_message_add_tail(&xfers[i], &msg);
-	}
-
-	mutex_lock(&st->buf_lock);
-
-	ret = spi_sync(st->us, &msg);
-	if (ret)
-		dev_err(&st->us->dev, "problem when reading sequence");
-
-	mutex_unlock(&st->buf_lock);
-	kfree(xfers);
-
-error_ret:
-	return ret;
-}
-
-static ssize_t adis16251_spi_read_signed(struct device *dev,
-		struct device_attribute *attr,
-		char *buf,
-		unsigned bits)
-{
-	int ret;
-	s16 val = 0;
-	unsigned shift = 16 - bits;
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
-	ret = adis16251_spi_read_reg_16(dev, this_attr->address, (u16 *)&val);
-	if (ret)
-		return ret;
-
-	if (val & ADIS16251_ERROR_ACTIVE)
-		adis16251_check_status(dev);
-	val = ((s16)(val << shift) >> shift);
-	return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t adis16251_read_12bit_unsigned(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	int ret;
-	u16 val = 0;
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-
-	ret = adis16251_spi_read_reg_16(dev, this_attr->address, &val);
-	if (ret)
-		return ret;
-
-	if (val & ADIS16251_ERROR_ACTIVE)
-		adis16251_check_status(dev);
-
-	return sprintf(buf, "%u\n", val & 0x0FFF);
-}
-
-static ssize_t adis16251_read_14bit_signed(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	ssize_t ret;
-
-	/* Take the iio_dev status lock */
-	mutex_lock(&indio_dev->mlock);
-	ret =  adis16251_spi_read_signed(dev, attr, buf, 14);
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret;
-}
-
-static ssize_t adis16251_read_12bit_signed(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	ssize_t ret;
-
-	/* Take the iio_dev status lock */
-	mutex_lock(&indio_dev->mlock);
-	ret =  adis16251_spi_read_signed(dev, attr, buf, 12);
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret;
-}
-
-static ssize_t adis16251_write_16bit(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
-	int ret;
-	long val;
-
-	ret = strict_strtol(buf, 10, &val);
-	if (ret)
-		goto error_ret;
-	ret = adis16251_spi_write_reg_16(dev, this_attr->address, val);
-
-error_ret:
-	return ret ? ret : len;
-}
-
-static ssize_t adis16251_read_frequency(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	int ret, len = 0;
-	u16 t;
-	int sps;
-	ret = adis16251_spi_read_reg_16(dev,
-			ADIS16251_SMPL_PRD,
-			&t);
-	if (ret)
-		return ret;
-	sps =  (t & ADIS16251_SMPL_PRD_TIME_BASE) ? 8 : 256;
-	sps /= (t & ADIS16251_SMPL_PRD_DIV_MASK) + 1;
-	len = sprintf(buf, "%d SPS\n", sps);
-	return len;
-}
-
-static ssize_t adis16251_write_frequency(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf,
-		size_t len)
-{
-	struct iio_dev *indio_dev = dev_get_drvdata(dev);
-	struct adis16251_state *st = iio_dev_get_devdata(indio_dev);
-	long val;
-	int ret;
-	u8 t;
-
-	ret = strict_strtol(buf, 10, &val);
-	if (ret)
-		return ret;
-
-	mutex_lock(&indio_dev->mlock);
-
-	t = (256 / val);
-	if (t > 0)
-		t--;
-	t &= ADIS16251_SMPL_PRD_DIV_MASK;
-	if ((t & ADIS16251_SMPL_PRD_DIV_MASK) >= 0x0A)
-		st->us->max_speed_hz = ADIS16251_SPI_SLOW;
-	else
-		st->us->max_speed_hz = ADIS16251_SPI_FAST;
-
-	ret = adis16251_spi_write_reg_8(dev,
-			ADIS16251_SMPL_PRD,
-			t);
-
-	mutex_unlock(&indio_dev->mlock);
-
-	return ret ? ret : len;
-}
-
-static ssize_t adis16251_write_reset(struct device *dev,
-		struct device_attribute *attr,
-		const char *buf, size_t len)
-{
-	if (len < 1)
-		return -1;
-	switch (buf[0]) {
-	case '1':
-	case 'y':
-	case 'Y':
-		return adis16251_reset(dev);
-	}
-	return -1;
-}
-
-
-
-int adis16251_set_irq(struct device *dev, bool enable)
-{
-	int ret;
-	u16 msc;
-	ret = adis16251_spi_read_reg_16(dev, ADIS16251_MSC_CTRL, &msc);
-	if (ret)
-		goto error_ret;
-
-	msc |= ADIS16251_MSC_CTRL_DATA_RDY_POL_HIGH;
-	if (enable)
-		msc |= ADIS16251_MSC_CTRL_DATA_RDY_EN;
-	else
-		msc &= ~ADIS16251_MSC_CTRL_DATA_RDY_EN;
-
-	ret = adis16251_spi_write_reg_16(dev, ADIS16251_MSC_CTRL, msc);
-	if (ret)
-		goto error_ret;
-
-error_ret:
-	return ret;
-}
-
-int adis16251_reset(struct device *dev)
-{
-	int ret;
-	ret = adis16251_spi_write_reg_8(dev,
-			ADIS16251_GLOB_CMD,
-			ADIS16251_GLOB_CMD_SW_RESET);
-	if (ret)
-		dev_err(dev, "problem resetting device");
-
-	return ret;
-}
-
-/* Power down the device */
-int adis16251_stop_device(struct device *dev)
-{
-	int ret;
-	u16 val = ADIS16251_SLP_CNT_POWER_OFF;
-
-	ret = adis16251_spi_write_reg_16(dev, ADIS16251_SLP_CNT, val);
-	if (ret)
-		dev_err(dev, "problem with turning device off: SLP_CNT");
-
-	return ret;
-}
-
-static int adis16251_self_test(struct device *dev)
-{
-	int ret;
-
-	ret = adis16251_spi_write_reg_16(dev,
-			ADIS16251_MSC_CTRL,
-			ADIS16251_MSC_CTRL_INT_SELF_TEST);
-	if (ret) {
-		dev_err(dev, "problem starting self test");
-		goto err_ret;
-	}
-
-	adis16251_check_status(dev);
-
-err_ret:
-	return ret;
-}
-
-int adis16251_check_status(struct device *dev)
-{
-	u16 status;
-	int ret;
-
-	ret = adis16251_spi_read_reg_16(dev, ADIS16251_DIAG_STAT, &status);
-
-	if (ret < 0) {
-		dev_err(dev, "Reading status failed\n");
-		goto error_ret;
-	}
-
-	if (!(status & ADIS16251_DIAG_STAT_ERR_MASK)) {
-		ret = 0;
-		goto error_ret;
-	}
-
-	ret = -EFAULT;
-
-	if (status & ADIS16251_DIAG_STAT_ALARM2)
-		dev_err(dev, "Alarm 2 active\n");
-	if (status & ADIS16251_DIAG_STAT_ALARM1)
-		dev_err(dev, "Alarm 1 active\n");
-	if (status & ADIS16251_DIAG_STAT_SELF_TEST)
-		dev_err(dev, "Self test error\n");
-	if (status & ADIS16251_DIAG_STAT_OVERFLOW)
-		dev_err(dev, "Sensor overrange\n");
-	if (status & ADIS16251_DIAG_STAT_SPI_FAIL)
-		dev_err(dev, "SPI failure\n");
-	if (status & ADIS16251_DIAG_STAT_FLASH_UPT)
-		dev_err(dev, "Flash update failed\n");
-	if (status & ADIS16251_DIAG_STAT_POWER_HIGH)
-		dev_err(dev, "Power supply above 5.25V\n");
-	if (status & ADIS16251_DIAG_STAT_POWER_LOW)
-		dev_err(dev, "Power supply below 4.75V\n");
-
-error_ret:
-	return ret;
-}
-
-static int adis16251_initial_setup(struct adis16251_state *st)
-{
-	int ret;
-	u16 smp_prd;
-	struct device *dev = &st->indio_dev->dev;
-
-	/* use low spi speed for init */
-	st->us->max_speed_hz = ADIS16251_SPI_SLOW;
-	st->us->mode = SPI_MODE_3;
-	spi_setup(st->us);
-
-	/* Disable IRQ */
-	ret = adis16251_set_irq(dev, false);
-	if (ret) {
-		dev_err(dev, "disable irq failed");
-		goto err_ret;
-	}
-
-	/* Do self test */
-
-	/* Read status register to check the result */
-	ret = adis16251_check_status(dev);
-	if (ret) {
-		adis16251_reset(dev);
-		dev_err(dev, "device not playing ball -> reset");
-		msleep(ADIS16251_STARTUP_DELAY);
-		ret = adis16251_check_status(dev);
-		if (ret) {
-			dev_err(dev, "giving up");
-			goto err_ret;
-		}
-	}
-
-	printk(KERN_INFO DRIVER_NAME ": at CS%d (irq %d)\n",
-			st->us->chip_select, st->us->irq);
-
-	/* use high spi speed if possible */
-	ret = adis16251_spi_read_reg_16(dev, ADIS16251_SMPL_PRD, &smp_prd);
-	if (!ret && (smp_prd & ADIS16251_SMPL_PRD_DIV_MASK) < 0x0A) {
-		st->us->max_speed_hz = ADIS16251_SPI_SLOW;
-		spi_setup(st->us);
-	}
-
-err_ret:
-	return ret;
-}
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16251_read_12bit_signed,
-		ADIS16251_SUPPLY_OUT);
-static IIO_CONST_ATTR(in0_supply_scale, "0.0018315");
-
-static IIO_DEV_ATTR_GYRO(adis16251_read_14bit_signed,
-		ADIS16251_GYRO_OUT);
-static IIO_DEV_ATTR_GYRO_SCALE(S_IWUSR | S_IRUGO,
-		adis16251_read_12bit_signed,
-		adis16251_write_16bit,
-		ADIS16251_GYRO_SCALE);
-static IIO_DEV_ATTR_GYRO_OFFSET(S_IWUSR | S_IRUGO,
-		adis16251_read_12bit_signed,
-		adis16251_write_16bit,
-		ADIS16251_GYRO_OFF);
-
-static IIO_DEV_ATTR_TEMP_RAW(adis16251_read_12bit_signed);
-static IIO_CONST_ATTR(temp_offset, "25 K");
-static IIO_CONST_ATTR(temp_scale, "0.1453 K");
-
-static IIO_DEV_ATTR_IN_NAMED_RAW(1, aux, adis16251_read_12bit_unsigned,
-		ADIS16251_AUX_ADC);
-static IIO_CONST_ATTR(in1_aux_scale, "0.0006105");
-
-static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
-		adis16251_read_frequency,
-		adis16251_write_frequency);
-static IIO_DEV_ATTR_ANGL(adis16251_read_14bit_signed,
-		ADIS16251_ANGL_OUT);
-
-static IIO_DEV_ATTR_RESET(adis16251_write_reset);
-
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("0.129 ~ 256");
-
-static IIO_CONST_ATTR(name, "adis16251");
-
-static struct attribute *adis16251_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group adis16251_event_attribute_group = {
-	.attrs = adis16251_event_attributes,
-};
-
-static struct attribute *adis16251_attributes[] = {
-	&iio_dev_attr_in0_supply_raw.dev_attr.attr,
-	&iio_const_attr_in0_supply_scale.dev_attr.attr,
-	&iio_dev_attr_gyro_raw.dev_attr.attr,
-	&iio_dev_attr_gyro_scale.dev_attr.attr,
-	&iio_dev_attr_gyro_offset.dev_attr.attr,
-	&iio_dev_attr_angl_raw.dev_attr.attr,
-	&iio_dev_attr_temp_raw.dev_attr.attr,
-	&iio_const_attr_temp_offset.dev_attr.attr,
-	&iio_const_attr_temp_scale.dev_attr.attr,
-	&iio_dev_attr_in1_aux_raw.dev_attr.attr,
-	&iio_const_attr_in1_aux_scale.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency.dev_attr.attr,
-	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
-	&iio_dev_attr_reset.dev_attr.attr,
-	&iio_const_attr_name.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group adis16251_attribute_group = {
-	.attrs = adis16251_attributes,
-};
-
-static int __devinit adis16251_probe(struct spi_device *spi)
-{
-	int ret, regdone = 0;
-	struct adis16251_state *st = kzalloc(sizeof *st, GFP_KERNEL);
-	if (!st) {
-		ret =  -ENOMEM;
-		goto error_ret;
-	}
-	/* this is only used for removal purposes */
-	spi_set_drvdata(spi, st);
-
-	/* Allocate the comms buffers */
-	st->rx = kzalloc(sizeof(*st->rx)*ADIS16251_MAX_RX, GFP_KERNEL);
-	if (st->rx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_st;
-	}
-	st->tx = kzalloc(sizeof(*st->tx)*ADIS16251_MAX_TX, GFP_KERNEL);
-	if (st->tx == NULL) {
-		ret = -ENOMEM;
-		goto error_free_rx;
-	}
-	st->us = spi;
-	mutex_init(&st->buf_lock);
-	/* setup the industrialio driver allocated elements */
-	st->indio_dev = iio_allocate_device();
-	if (st->indio_dev == NULL) {
-		ret = -ENOMEM;
-		goto error_free_tx;
-	}
-
-	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &adis16251_event_attribute_group;
-	st->indio_dev->attrs = &adis16251_attribute_group;
-	st->indio_dev->dev_data = (void *)(st);
-	st->indio_dev->driver_module = THIS_MODULE;
-	st->indio_dev->modes = INDIO_DIRECT_MODE;
-
-	ret = adis16251_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
-	ret = iio_device_register(st->indio_dev);
-	if (ret)
-		goto error_unreg_ring_funcs;
-	regdone = 1;
-
-	ret = adis16251_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_RISING,
-				"adis16251");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = adis16251_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
-
-	/* Get the device into a sane initial state */
-	ret = adis16251_initial_setup(st);
-	if (ret)
-		goto error_remove_trigger;
-	return 0;
-
-error_remove_trigger:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		adis16251_remove_trigger(st->indio_dev);
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	adis16251_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	adis16251_unconfigure_ring(st->indio_dev);
-error_free_dev:
-	if (regdone)
-		iio_device_unregister(st->indio_dev);
-	else
-		iio_free_device(st->indio_dev);
-error_free_tx:
-	kfree(st->tx);
-error_free_rx:
-	kfree(st->rx);
-error_free_st:
-	kfree(st);
-error_ret:
-	return ret;
-}
-
-/* fixme, confirm ordering in this function */
-static int adis16251_remove(struct spi_device *spi)
-{
-	int ret;
-	struct adis16251_state *st = spi_get_drvdata(spi);
-	struct iio_dev *indio_dev = st->indio_dev;
-
-	ret = adis16251_stop_device(&(indio_dev->dev));
-	if (ret)
-		goto err_ret;
-
-	flush_scheduled_work();
-
-	adis16251_remove_trigger(indio_dev);
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	adis16251_uninitialize_ring(indio_dev->ring);
-	adis16251_unconfigure_ring(indio_dev);
-	iio_device_unregister(indio_dev);
-	kfree(st->tx);
-	kfree(st->rx);
-	kfree(st);
-
-	return 0;
-
-err_ret:
-	return ret;
-}
-
-static struct spi_driver adis16251_driver = {
-	.driver = {
-		.name = "adis16251",
-		.owner = THIS_MODULE,
-	},
-	.probe = adis16251_probe,
-	.remove = __devexit_p(adis16251_remove),
-};
-
-static __init int adis16251_init(void)
-{
-	return spi_register_driver(&adis16251_driver);
-}
-module_init(adis16251_init);
-
-static __exit void adis16251_exit(void)
-{
-	spi_unregister_driver(&adis16251_driver);
-}
-module_exit(adis16251_exit);
-
-MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADIS16251 Digital Gyroscope Sensor SPI driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/gyro/adis16260_core.c b/drivers/staging/iio/gyro/adis16260_core.c
index 045e27d..69a29ec 100644
--- a/drivers/staging/iio/gyro/adis16260_core.c
+++ b/drivers/staging/iio/gyro/adis16260_core.c
@@ -238,10 +238,24 @@ error_ret:
 	return ret ? ret : len;
 }
 
+static ssize_t adis16260_read_frequency_available(struct device *dev,
+						  struct device_attribute *attr,
+						  char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
+	if (spi_get_device_id(st->us)->driver_data)
+		return sprintf(buf, "%s\n", "0.129 ~ 256");
+	else
+		return sprintf(buf, "%s\n", "256 2048");
+}
+
 static ssize_t adis16260_read_frequency(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct adis16260_state *st = iio_dev_get_devdata(indio_dev);
 	int ret, len = 0;
 	u16 t;
 	int sps;
@@ -250,7 +264,11 @@ static ssize_t adis16260_read_frequency(struct device *dev,
 			&t);
 	if (ret)
 		return ret;
-	sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
+
+	if (spi_get_device_id(st->us)->driver_data) /* If an adis16251 */
+		sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256;
+	else
+		sps =  (t & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048;
 	sps /= (t & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
 	len = sprintf(buf, "%d SPS\n", sps);
 	return len;
@@ -272,16 +290,21 @@ static ssize_t adis16260_write_frequency(struct device *dev,
 		return ret;
 
 	mutex_lock(&indio_dev->mlock);
-
-	t = (2048 / val);
-	if (t > 0)
-		t--;
-	t &= ADIS16260_SMPL_PRD_DIV_MASK;
+	if (spi_get_device_id(st->us)) {
+		t = (256 / val);
+		if (t > 0)
+			t--;
+		t &= ADIS16260_SMPL_PRD_DIV_MASK;
+	} else {
+		t = (2048 / val);
+		if (t > 0)
+			t--;
+		t &= ADIS16260_SMPL_PRD_DIV_MASK;
+	}
 	if ((t & ADIS16260_SMPL_PRD_DIV_MASK) >= 0x0A)
 		st->us->max_speed_hz = ADIS16260_SPI_SLOW;
 	else
 		st->us->max_speed_hz = ADIS16260_SPI_FAST;
-
 	ret = adis16260_spi_write_reg_8(dev,
 			ADIS16260_SMPL_PRD,
 			t);
@@ -302,7 +325,10 @@ static ssize_t adis16260_read_gyro_scale(struct device *dev,
 	if (st->negate)
 		ret = sprintf(buf, "-");
 	/* Take the iio_dev status lock */
-	ret += sprintf(buf + ret, "%s\n", "0.00127862821");
+	if (spi_get_device_id(st->us)->driver_data)
+		ret += sprintf(buf + ret, "%s\n", "0.00031974432");
+	else
+		ret += sprintf(buf + ret, "%s\n", "0.00127862821");
 
 	return ret;
 }
@@ -475,7 +501,9 @@ static IIO_DEV_ATTR_SAMP_FREQ(S_IWUSR | S_IRUGO,
 
 static IIO_DEVICE_ATTR(reset, S_IWUSR, NULL, adis16260_write_reset, 0);
 
-static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("256 2048");
+
+static IIO_DEVICE_ATTR(sampling_frequency_available,
+		       S_IRUGO, adis16260_read_frequency_available, NULL, 0);
 
 static IIO_CONST_ATTR_NAME("adis16260");
 
@@ -525,7 +553,7 @@ static ADIS16260_GYRO_ATTR_SET(_Z);
 		&iio_dev_attr_in1_raw.dev_attr.attr,			\
 		&iio_const_attr_in1_scale.dev_attr.attr,		\
 		&iio_dev_attr_sampling_frequency.dev_attr.attr,		\
-		&iio_const_attr_sampling_frequency_available.dev_attr.attr, \
+		&iio_dev_attr_sampling_frequency_available.dev_attr.attr, \
 		&iio_dev_attr_reset.dev_attr.attr,			\
 		&iio_const_attr_name.dev_attr.attr,			\
 		NULL							\
@@ -693,6 +721,7 @@ static const struct spi_device_id adis16260_id[] = {
 	{"adis16265", 0},
 	{"adis16250", 0},
 	{"adis16255", 0},
+	{"adis16251", 1},
 	{}
 };
 
diff --git a/drivers/staging/iio/industrialio-ring.c b/drivers/staging/iio/industrialio-ring.c
index 9a98fcd..bd4373a 100644
--- a/drivers/staging/iio/industrialio-ring.c
+++ b/drivers/staging/iio/industrialio-ring.c
@@ -16,7 +16,6 @@
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/fs.h>
-#include <linux/poll.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
 
@@ -98,31 +97,13 @@ static ssize_t iio_ring_rip_outer(struct file *filp, char __user *buf,
 				  size_t count, loff_t *f_ps)
 {
 	struct iio_ring_buffer *rb = filp->private_data;
-	int ret, dead_offset, copied;
-	u8 *data;
+	int ret, dead_offset;
+
 	/* rip lots must exist. */
 	if (!rb->access.rip_lots)
 		return -EINVAL;
-	copied = rb->access.rip_lots(rb, count, &data, &dead_offset);
+	ret = rb->access.rip_lots(rb, count, buf, &dead_offset);
 
-	if (copied <= 0) {
-		ret = copied;
-		goto error_ret;
-	}
-	if (copy_to_user(buf, data + dead_offset, copied))  {
-		ret =  -EFAULT;
-		goto error_free_data_cpy;
-	}
-	/* In clever ring buffer designs this may not need to be freed.
-	 * When such a design exists I'll add this to ring access funcs.
-	 */
-	kfree(data);
-
-	return copied;
-
-error_free_data_cpy:
-	kfree(data);
-error_ret:
 	return ret;
 }
 
diff --git a/drivers/staging/iio/kfifo_buf.c b/drivers/staging/iio/kfifo_buf.c
new file mode 100644
index 0000000..a56c0cb
--- /dev/null
+++ b/drivers/staging/iio/kfifo_buf.c
@@ -0,0 +1,196 @@
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/kfifo.h>
+#include <linux/mutex.h>
+
+#include "kfifo_buf.h"
+
+static inline int __iio_allocate_kfifo(struct iio_kfifo *buf,
+				int bytes_per_datum, int length)
+{
+	if ((length == 0) || (bytes_per_datum == 0))
+		return -EINVAL;
+
+	__iio_update_ring_buffer(&buf->ring, bytes_per_datum, length);
+	return kfifo_alloc(&buf->kf, bytes_per_datum*length, GFP_KERNEL);
+}
+
+int iio_request_update_kfifo(struct iio_ring_buffer *r)
+{
+	int ret = 0;
+	struct iio_kfifo *buf = iio_to_kfifo(r);
+
+	mutex_lock(&buf->use_lock);
+	if (!buf->update_needed)
+		goto error_ret;
+	if (buf->use_count) {
+		ret = -EAGAIN;
+		goto error_ret;
+	}
+	kfifo_free(&buf->kf);
+	ret = __iio_allocate_kfifo(buf, buf->ring.bytes_per_datum,
+				buf->ring.length);
+error_ret:
+	mutex_unlock(&buf->use_lock);
+	return ret;
+}
+EXPORT_SYMBOL(iio_request_update_kfifo);
+
+void iio_mark_kfifo_in_use(struct iio_ring_buffer *r)
+{
+	struct iio_kfifo *buf = iio_to_kfifo(r);
+	mutex_lock(&buf->use_lock);
+	buf->use_count++;
+	mutex_unlock(&buf->use_lock);
+}
+EXPORT_SYMBOL(iio_mark_kfifo_in_use);
+
+void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r)
+{
+	struct iio_kfifo *buf = iio_to_kfifo(r);
+	mutex_lock(&buf->use_lock);
+	buf->use_count--;
+	mutex_unlock(&buf->use_lock);
+}
+EXPORT_SYMBOL(iio_unmark_kfifo_in_use);
+
+int iio_get_length_kfifo(struct iio_ring_buffer *r)
+{
+	return r->length;
+}
+EXPORT_SYMBOL(iio_get_length_kfifo);
+
+static inline void __iio_init_kfifo(struct iio_kfifo *kf)
+{
+	mutex_init(&kf->use_lock);
+}
+
+static IIO_RING_ENABLE_ATTR;
+static IIO_RING_BYTES_PER_DATUM_ATTR;
+static IIO_RING_LENGTH_ATTR;
+
+static struct attribute *iio_kfifo_attributes[] = {
+	&dev_attr_length.attr,
+	&dev_attr_bytes_per_datum.attr,
+	&dev_attr_enable.attr,
+	NULL,
+};
+
+static struct attribute_group iio_kfifo_attribute_group = {
+	.attrs = iio_kfifo_attributes,
+};
+
+static const struct attribute_group *iio_kfifo_attribute_groups[] = {
+	&iio_kfifo_attribute_group,
+	NULL
+};
+
+static void iio_kfifo_release(struct device *dev)
+{
+	struct iio_ring_buffer *r = to_iio_ring_buffer(dev);
+	struct iio_kfifo *kf = iio_to_kfifo(r);
+	kfifo_free(&kf->kf);
+	kfree(kf);
+}
+
+static struct device_type iio_kfifo_type = {
+	.release = iio_kfifo_release,
+	.groups = iio_kfifo_attribute_groups,
+};
+
+struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
+{
+	struct iio_kfifo *kf;
+
+	kf = kzalloc(sizeof *kf, GFP_KERNEL);
+	if (!kf)
+		return NULL;
+	iio_ring_buffer_init(&kf->ring, indio_dev);
+	__iio_init_kfifo(kf);
+	kf->ring.dev.type = &iio_kfifo_type;
+	device_initialize(&kf->ring.dev);
+	kf->ring.dev.parent = &indio_dev->dev;
+	kf->ring.dev.bus = &iio_bus_type;
+	dev_set_drvdata(&kf->ring.dev, (void *)&(kf->ring));
+
+	return &kf->ring;
+}
+EXPORT_SYMBOL(iio_kfifo_allocate);
+
+int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r)
+{
+	return r->bytes_per_datum;
+}
+EXPORT_SYMBOL(iio_get_bytes_per_datum_kfifo);
+
+int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd)
+{
+	if (r->bytes_per_datum != bpd) {
+		r->bytes_per_datum = bpd;
+		if (r->access.mark_param_change)
+			r->access.mark_param_change(r);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iio_set_bytes_per_datum_kfifo);
+
+int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r)
+{
+	struct iio_kfifo *kf = iio_to_kfifo(r);
+	kf->update_needed = true;
+	return 0;
+}
+EXPORT_SYMBOL(iio_mark_update_needed_kfifo);
+
+int iio_set_length_kfifo(struct iio_ring_buffer *r, int length)
+{
+	if (r->length != length) {
+		r->length = length;
+		if (r->access.mark_param_change)
+			r->access.mark_param_change(r);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iio_set_length_kfifo);
+
+void iio_kfifo_free(struct iio_ring_buffer *r)
+{
+	if (r)
+		iio_put_ring_buffer(r);
+}
+EXPORT_SYMBOL(iio_kfifo_free);
+
+int iio_store_to_kfifo(struct iio_ring_buffer *r, u8 *data, s64 timestamp)
+{
+	int ret;
+	struct iio_kfifo *kf = iio_to_kfifo(r);
+	u8 *datal = kmalloc(r->bytes_per_datum, GFP_KERNEL);
+	memcpy(datal, data, r->bytes_per_datum - sizeof(timestamp));
+	memcpy(datal + r->bytes_per_datum - sizeof(timestamp),
+		&timestamp, sizeof(timestamp));
+	ret = kfifo_in(&kf->kf, data, r->bytes_per_datum);
+	if (ret != r->bytes_per_datum) {
+		kfree(datal);
+		return -EBUSY;
+	}
+	kfree(datal);
+	return 0;
+}
+EXPORT_SYMBOL(iio_store_to_kfifo);
+
+int iio_rip_kfifo(struct iio_ring_buffer *r,
+		size_t count, char __user *buf, int *deadoffset)
+{
+	int ret, copied;
+	struct iio_kfifo *kf = iio_to_kfifo(r);
+
+	*deadoffset = 0;
+	ret = kfifo_to_user(&kf->kf, buf, r->bytes_per_datum*count, &copied);
+
+	return copied;
+}
+EXPORT_SYMBOL(iio_rip_kfifo);
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/kfifo_buf.h b/drivers/staging/iio/kfifo_buf.h
new file mode 100644
index 0000000..8064383
--- /dev/null
+++ b/drivers/staging/iio/kfifo_buf.h
@@ -0,0 +1,56 @@
+
+#include <linux/kfifo.h>
+#include "iio.h"
+#include "ring_generic.h"
+
+struct iio_kfifo {
+	struct iio_ring_buffer ring;
+	struct kfifo kf;
+	int use_count;
+	int update_needed;
+	struct mutex use_lock;
+};
+
+#define iio_to_kfifo(r) container_of(r, struct iio_kfifo, ring)
+
+int iio_create_kfifo(struct iio_ring_buffer **r);
+int iio_init_kfifo(struct iio_ring_buffer *r, struct iio_dev *indio_dev);
+void iio_exit_kfifo(struct iio_ring_buffer *r);
+void iio_free_kfifo(struct iio_ring_buffer *r);
+void iio_mark_kfifo_in_use(struct iio_ring_buffer *r);
+void iio_unmark_kfifo_in_use(struct iio_ring_buffer *r);
+
+int iio_store_to_kfifo(struct iio_ring_buffer *r, u8 *data, s64 timestamp);
+int iio_rip_kfifo(struct iio_ring_buffer *r,
+		size_t count,
+		char __user *buf,
+		int *dead_offset);
+
+int iio_request_update_kfifo(struct iio_ring_buffer *r);
+int iio_mark_update_needed_kfifo(struct iio_ring_buffer *r);
+
+int iio_get_bytes_per_datum_kfifo(struct iio_ring_buffer *r);
+int iio_set_bytes_per_datum_kfifo(struct iio_ring_buffer *r, size_t bpd);
+int iio_get_length_kfifo(struct iio_ring_buffer *r);
+int iio_set_length_kfifo(struct iio_ring_buffer *r, int length);
+
+static inline void iio_kfifo_register_funcs(struct iio_ring_access_funcs *ra)
+{
+	ra->mark_in_use = &iio_mark_kfifo_in_use;
+	ra->unmark_in_use = &iio_unmark_kfifo_in_use;
+
+	ra->store_to = &iio_store_to_kfifo;
+	ra->rip_lots = &iio_rip_kfifo;
+
+	ra->mark_param_change = &iio_mark_update_needed_kfifo;
+	ra->request_update = &iio_request_update_kfifo;
+
+	ra->get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo;
+	ra->set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo;
+	ra->get_length = &iio_get_length_kfifo;
+	ra->set_length = &iio_set_length_kfifo;
+};
+
+struct iio_ring_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev);
+void iio_kfifo_free(struct iio_ring_buffer *r);
+
diff --git a/drivers/staging/iio/meter/ade7753.c b/drivers/staging/iio/meter/ade7753.c
index e72afbd..8b86d82 100644
--- a/drivers/staging/iio/meter/ade7753.c
+++ b/drivers/staging/iio/meter/ade7753.c
@@ -1,5 +1,5 @@
 /*
- * ADE7753 Single-Phase Multifunction Metering IC with di/dt Sensor Interface Driver
+ * ADE7753 Single-Phase Multifunction Metering IC with di/dt Sensor Interface
  *
  * Copyright 2010 Analog Devices Inc.
  *
@@ -23,9 +23,9 @@
 #include "meter.h"
 #include "ade7753.h"
 
-int ade7753_spi_write_reg_8(struct device *dev,
-		u8 reg_address,
-		u8 val)
+static int ade7753_spi_write_reg_8(struct device *dev,
+				   u8 reg_address,
+				   u8 val)
 {
 	int ret;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
@@ -46,25 +46,14 @@ static int ade7753_spi_write_reg_16(struct device *dev,
 		u16 value)
 {
 	int ret;
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 3,
-		}
-	};
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7753_WRITE_REG(reg_address);
 	st->tx[1] = (value >> 8) & 0xFF;
 	st->tx[2] = value & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_write(st->us, st->tx, 3);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
@@ -74,73 +63,40 @@ static int ade7753_spi_read_reg_8(struct device *dev,
 		u8 reg_address,
 		u8 *val)
 {
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7753_READ_REG(reg_address);
-	st->tx[1] = 0;
+	ssize_t ret;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
+	ret = spi_w8r8(st->us, ADE7753_READ_REG(reg_address));
+	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
 				reg_address);
-		goto error_ret;
+		return ret;
 	}
-	*val = st->rx[1];
+	*val = ret;
 
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
+	return 0;
 }
 
 static int ade7753_spi_read_reg_16(struct device *dev,
 		u8 reg_address,
 		u16 *val)
 {
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7753_state *st = iio_dev_get_devdata(indio_dev);
-	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 3,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7753_READ_REG(reg_address);
-	st->tx[1] = 0;
-	st->tx[2] = 0;
+	ssize_t ret;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
+	ret = spi_w8r16(st->us, ADE7753_READ_REG(reg_address));
+	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				reg_address);
-		goto error_ret;
+			reg_address);
+		return ret;
 	}
-	*val = (st->rx[1] << 8) | st->rx[2];
 
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
+	*val = ret;
+	*val = be16_to_cpup(val);
+
+	return 0;
 }
 
 static int ade7753_spi_read_reg_24(struct device *dev,
@@ -154,27 +110,28 @@ static int ade7753_spi_read_reg_24(struct device *dev,
 	struct spi_transfer xfers[] = {
 		{
 			.tx_buf = st->tx,
-			.rx_buf = st->rx,
 			.bits_per_word = 8,
-			.len = 4,
-		},
+			.len = 1,
+		}, {
+			.rx_buf = st->tx,
+			.bits_per_word = 8,
+			.len = 3,
+		}
 	};
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7753_READ_REG(reg_address);
-	st->tx[1] = 0;
-	st->tx[2] = 0;
-	st->tx[3] = 0;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
 	ret = spi_sync(st->us, &msg);
 	if (ret) {
 		dev_err(&st->us->dev, "problem when reading 24 bit register 0x%02X",
 				reg_address);
 		goto error_ret;
 	}
-	*val = (st->rx[1] << 16) | (st->rx[2] << 8) | st->rx[3];
+	*val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
 
 error_ret:
 	mutex_unlock(&st->buf_lock);
@@ -186,7 +143,7 @@ static ssize_t ade7753_read_8bit(struct device *dev,
 		char *buf)
 {
 	int ret;
-	u8 val = 0;
+	u8 val;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = ade7753_spi_read_reg_8(dev, this_attr->address, &val);
@@ -201,7 +158,7 @@ static ssize_t ade7753_read_16bit(struct device *dev,
 		char *buf)
 {
 	int ret;
-	u16 val = 0;
+	u16 val;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = ade7753_spi_read_reg_16(dev, this_attr->address, &val);
@@ -216,14 +173,14 @@ static ssize_t ade7753_read_24bit(struct device *dev,
 		char *buf)
 {
 	int ret;
-	u32 val = 0;
+	u32 val;
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
 
 	ret = ade7753_spi_read_reg_24(dev, this_attr->address, &val);
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%u\n", val & 0xFFFFFF);
+	return sprintf(buf, "%u\n", val);
 }
 
 static ssize_t ade7753_write_8bit(struct device *dev,
@@ -264,17 +221,12 @@ error_ret:
 
 static int ade7753_reset(struct device *dev)
 {
-	int ret;
 	u16 val;
-	ade7753_spi_read_reg_16(dev,
-			ADE7753_MODE,
-			&val);
+
+	ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val);
 	val |= 1 << 6; /* Software Chip Reset */
-	ret = ade7753_spi_write_reg_16(dev,
-			ADE7753_MODE,
-			val);
 
-	return ret;
+	return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val);
 }
 
 static ssize_t ade7753_write_reset(struct device *dev,
@@ -401,27 +353,20 @@ static int ade7753_set_irq(struct device *dev, bool enable)
 		irqen &= ~(1 << 3);
 
 	ret = ade7753_spi_write_reg_8(dev, ADE7753_IRQEN, irqen);
-	if (ret)
-		goto error_ret;
 
 error_ret:
 	return ret;
 }
 
 /* Power down the device */
-int ade7753_stop_device(struct device *dev)
+static int ade7753_stop_device(struct device *dev)
 {
-	int ret;
 	u16 val;
-	ade7753_spi_read_reg_16(dev,
-			ADE7753_MODE,
-			&val);
+
+	ade7753_spi_read_reg_16(dev, ADE7753_MODE, &val);
 	val |= 1 << 4;  /* AD converters can be turned off */
-	ret = ade7753_spi_write_reg_16(dev,
-			ADE7753_MODE,
-			val);
 
-	return ret;
+	return ade7753_spi_write_reg_16(dev, ADE7753_MODE, val);
 }
 
 static int ade7753_initial_setup(struct ade7753_state *st)
@@ -454,16 +399,14 @@ static ssize_t ade7753_read_frequency(struct device *dev,
 	int ret, len = 0;
 	u8 t;
 	int sps;
-	ret = ade7753_spi_read_reg_8(dev,
-			ADE7753_MODE,
-			&t);
+	ret = ade7753_spi_read_reg_8(dev, ADE7753_MODE,	&t);
 	if (ret)
 		return ret;
 
 	t = (t >> 11) & 0x3;
 	sps = 27900 / (1 + t);
 
-	len = sprintf(buf, "%d SPS\n", sps);
+	len = sprintf(buf, "%d\n", sps);
 	return len;
 }
 
@@ -493,24 +436,21 @@ static ssize_t ade7753_write_frequency(struct device *dev,
 	else
 		st->us->max_speed_hz = ADE7753_SPI_FAST;
 
-	ret = ade7753_spi_read_reg_16(dev,
-			ADE7753_MODE,
-			&reg);
+	ret = ade7753_spi_read_reg_16(dev, ADE7753_MODE, &reg);
 	if (ret)
 		goto out;
 
 	reg &= ~(3 << 11);
 	reg |= t << 11;
 
-	ret = ade7753_spi_write_reg_16(dev,
-			ADE7753_MODE,
-			reg);
+	ret = ade7753_spi_write_reg_16(dev, ADE7753_MODE, reg);
 
 out:
 	mutex_unlock(&indio_dev->mlock);
 
 	return ret ? ret : len;
 }
+
 static IIO_DEV_ATTR_TEMP_RAW(ade7753_read_8bit);
 static IIO_CONST_ATTR(temp_offset, "-25 C");
 static IIO_CONST_ATTR(temp_scale, "0.67 C");
@@ -525,14 +465,6 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
 
 static IIO_CONST_ATTR(name, "ade7753");
 
-static struct attribute *ade7753_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group ade7753_event_attribute_group = {
-	.attrs = ade7753_event_attributes,
-};
-
 static struct attribute *ade7753_attributes[] = {
 	&iio_dev_attr_temp_raw.dev_attr.attr,
 	&iio_const_attr_temp_offset.dev_attr.attr,
@@ -607,58 +539,22 @@ static int __devinit ade7753_probe(struct spi_device *spi)
 	}
 
 	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &ade7753_event_attribute_group;
 	st->indio_dev->attrs = &ade7753_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = ade7753_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
+		goto error_free_dev;
 	regdone = 1;
 
-	ret = ade7753_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_FALLING,
-				"ade7753");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = ade7753_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
-
 	/* Get the device into a sane initial state */
 	ret = ade7753_initial_setup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_free_dev;
 	return 0;
 
-error_remove_trigger:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		ade7753_remove_trigger(st->indio_dev);
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	ade7753_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	ade7753_unconfigure_ring(st->indio_dev);
 error_free_dev:
 	if (regdone)
 		iio_device_unregister(st->indio_dev);
@@ -685,14 +581,6 @@ static int ade7753_remove(struct spi_device *spi)
 	if (ret)
 		goto err_ret;
 
-	flush_scheduled_work();
-
-	ade7753_remove_trigger(indio_dev);
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	ade7753_uninitialize_ring(indio_dev->ring);
-	ade7753_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
 	kfree(st->tx);
 	kfree(st->rx);
@@ -726,5 +614,5 @@ static __exit void ade7753_exit(void)
 module_exit(ade7753_exit);
 
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Metering IC Driver");
+MODULE_DESCRIPTION("Analog Devices ADE7753/6 Single-Phase Multifunction Meter");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/meter/ade7753.h b/drivers/staging/iio/meter/ade7753.h
index a3722b8..70dabae 100644
--- a/drivers/staging/iio/meter/ade7753.h
+++ b/drivers/staging/iio/meter/ade7753.h
@@ -60,81 +60,17 @@
 /**
  * struct ade7753_state - device instance specific data
  * @us:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
  * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			recieve buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7753_state {
 	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
 	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
 	u8				*tx;
 	u8				*rx;
 	struct mutex			buf_lock;
 };
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum ade7753_scan {
-	ADE7753_SCAN_ACTIVE_POWER,
-	ADE7753_SCAN_CH1,
-	ADE7753_SCAN_CH2,
-};
-
-void ade7753_remove_trigger(struct iio_dev *indio_dev);
-int ade7753_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t ade7753_read_data_from_ring(struct device *dev,
-		struct device_attribute *attr,
-		char *buf);
-
-
-int ade7753_configure_ring(struct iio_dev *indio_dev);
-void ade7753_unconfigure_ring(struct iio_dev *indio_dev);
-
-int ade7753_initialize_ring(struct iio_ring_buffer *ring);
-void ade7753_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void ade7753_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7753_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-ade7753_read_data_from_ring(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return 0;
-}
-
-static int ade7753_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-static inline void ade7753_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7753_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-static inline void ade7753_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-#endif /* CONFIG_IIO_RING_BUFFER */
 
 #endif
diff --git a/drivers/staging/iio/meter/ade7754.c b/drivers/staging/iio/meter/ade7754.c
index 23dedfa..4272818 100644
--- a/drivers/staging/iio/meter/ade7754.c
+++ b/drivers/staging/iio/meter/ade7754.c
@@ -46,25 +46,14 @@ static int ade7754_spi_write_reg_16(struct device *dev,
 		u16 value)
 {
 	int ret;
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 3,
-		}
-	};
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7754_WRITE_REG(reg_address);
 	st->tx[1] = (value >> 8) & 0xFF;
 	st->tx[2] = value & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_write(st->us, st->tx, 3);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
@@ -74,73 +63,40 @@ static int ade7754_spi_read_reg_8(struct device *dev,
 		u8 reg_address,
 		u8 *val)
 {
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
 	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-		},
-	};
-
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7754_READ_REG(reg_address);
-	st->tx[1] = 0;
 
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
+	ret = spi_w8r8(st->us, ADE7754_READ_REG(reg_address));
+	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
 				reg_address);
-		goto error_ret;
+		return ret;
 	}
-	*val = st->rx[1];
+	*val = ret;
 
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
+	return 0;
 }
 
 static int ade7754_spi_read_reg_16(struct device *dev,
 		u8 reg_address,
 		u16 *val)
 {
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7754_state *st = iio_dev_get_devdata(indio_dev);
 	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 3,
-		},
-	};
 
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7754_READ_REG(reg_address);
-	st->tx[1] = 0;
-	st->tx[2] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
+	ret = spi_w8r16(st->us, ADE7754_READ_REG(reg_address));
+	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				reg_address);
-		goto error_ret;
+			reg_address);
+		return ret;
 	}
-	*val = (st->rx[1] << 8) | st->rx[2];
 
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
+	*val = ret;
+	*val = be16_to_cpup(val);
+
+	return 0;
 }
 
 static int ade7754_spi_read_reg_24(struct device *dev,
@@ -264,17 +220,11 @@ error_ret:
 
 static int ade7754_reset(struct device *dev)
 {
-	int ret;
 	u8 val;
-	ade7754_spi_read_reg_8(dev,
-			ADE7754_OPMODE,
-			&val);
-	val |= 1 << 6; /* Software Chip Reset */
-	ret = ade7754_spi_write_reg_8(dev,
-			ADE7754_OPMODE,
-			val);
 
-	return ret;
+	ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val);
+	val |= 1 << 6; /* Software Chip Reset */
+	return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
 }
 
 
@@ -431,17 +381,11 @@ error_ret:
 /* Power down the device */
 static int ade7754_stop_device(struct device *dev)
 {
-	int ret;
 	u8 val;
-	ade7754_spi_read_reg_8(dev,
-			ADE7754_OPMODE,
-			&val);
-	val |= 7 << 3;  /* ADE7754 powered down */
-	ret = ade7754_spi_write_reg_8(dev,
-			ADE7754_OPMODE,
-			val);
 
-	return ret;
+	ade7754_spi_read_reg_8(dev, ADE7754_OPMODE, &val);
+	val |= 7 << 3;  /* ADE7754 powered down */
+	return ade7754_spi_write_reg_8(dev, ADE7754_OPMODE, val);
 }
 
 static int ade7754_initial_setup(struct ade7754_state *st)
@@ -471,7 +415,7 @@ static ssize_t ade7754_read_frequency(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	int ret, len = 0;
+	int ret;
 	u8 t;
 	int sps;
 	ret = ade7754_spi_read_reg_8(dev,
@@ -483,8 +427,7 @@ static ssize_t ade7754_read_frequency(struct device *dev,
 	t = (t >> 3) & 0x3;
 	sps = 26000 / (1 + t);
 
-	len = sprintf(buf, "%d SPS\n", sps);
-	return len;
+	return sprintf(buf, "%d\n", sps);
 }
 
 static ssize_t ade7754_write_frequency(struct device *dev,
@@ -513,18 +456,14 @@ static ssize_t ade7754_write_frequency(struct device *dev,
 	else
 		st->us->max_speed_hz = ADE7754_SPI_FAST;
 
-	ret = ade7754_spi_read_reg_8(dev,
-			ADE7754_WAVMODE,
-			&reg);
+	ret = ade7754_spi_read_reg_8(dev, ADE7754_WAVMODE, &reg);
 	if (ret)
 		goto out;
 
 	reg &= ~(3 << 3);
 	reg |= t << 3;
 
-	ret = ade7754_spi_write_reg_8(dev,
-			ADE7754_WAVMODE,
-			reg);
+	ret = ade7754_spi_write_reg_8(dev, ADE7754_WAVMODE, reg);
 
 out:
 	mutex_unlock(&indio_dev->mlock);
@@ -545,14 +484,6 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("26000 13000 65000 33000");
 
 static IIO_CONST_ATTR(name, "ade7754");
 
-static struct attribute *ade7754_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group ade7754_event_attribute_group = {
-	.attrs = ade7754_event_attributes,
-};
-
 static struct attribute *ade7754_attributes[] = {
 	&iio_dev_attr_temp_raw.dev_attr.attr,
 	&iio_const_attr_temp_offset.dev_attr.attr,
@@ -633,58 +564,22 @@ static int __devinit ade7754_probe(struct spi_device *spi)
 	}
 
 	st->indio_dev->dev.parent = &spi->dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &ade7754_event_attribute_group;
 	st->indio_dev->attrs = &ade7754_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = ade7754_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
+		goto error_free_dev;
 	regdone = 1;
 
-	ret = ade7754_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_FALLING,
-				"ade7754");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = ade7754_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
-
 	/* Get the device into a sane initial state */
 	ret = ade7754_initial_setup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_free_dev;
 	return 0;
 
-error_remove_trigger:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		ade7754_remove_trigger(st->indio_dev);
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	ade7754_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	ade7754_unconfigure_ring(st->indio_dev);
 error_free_dev:
 	if (regdone)
 		iio_device_unregister(st->indio_dev);
@@ -711,14 +606,6 @@ static int ade7754_remove(struct spi_device *spi)
 	if (ret)
 		goto err_ret;
 
-	flush_scheduled_work();
-
-	ade7754_remove_trigger(indio_dev);
-	if (spi->irq)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	ade7754_uninitialize_ring(indio_dev->ring);
-	ade7754_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
 	kfree(st->tx);
 	kfree(st->rx);
diff --git a/drivers/staging/iio/meter/ade7754.h b/drivers/staging/iio/meter/ade7754.h
index f6a3e4b..8faa9b3 100644
--- a/drivers/staging/iio/meter/ade7754.h
+++ b/drivers/staging/iio/meter/ade7754.h
@@ -78,84 +78,17 @@
 /**
  * struct ade7754_state - device instance specific data
  * @us:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
  * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			recieve buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7754_state {
 	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
 	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
 	u8				*tx;
 	u8				*rx;
 	struct mutex			buf_lock;
 };
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum ade7754_scan {
-	ADE7754_SCAN_PHA_V,
-	ADE7754_SCAN_PHB_V,
-	ADE7754_SCAN_PHC_V,
-	ADE7754_SCAN_PHA_I,
-	ADE7754_SCAN_PHB_I,
-	ADE7754_SCAN_PHC_I,
-};
-
-void ade7754_remove_trigger(struct iio_dev *indio_dev);
-int ade7754_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t ade7754_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int ade7754_configure_ring(struct iio_dev *indio_dev);
-void ade7754_unconfigure_ring(struct iio_dev *indio_dev);
-
-int ade7754_initialize_ring(struct iio_ring_buffer *ring);
-void ade7754_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void ade7754_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7754_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-ade7754_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static int ade7754_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-static inline void ade7754_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7754_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-static inline void ade7754_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-#endif /* CONFIG_IIO_RING_BUFFER */
 
 #endif
diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c
index fafc3c1..a9d3203 100644
--- a/drivers/staging/iio/meter/ade7759.c
+++ b/drivers/staging/iio/meter/ade7759.c
@@ -23,7 +23,7 @@
 #include "meter.h"
 #include "ade7759.h"
 
-int ade7759_spi_write_reg_8(struct device *dev,
+static int ade7759_spi_write_reg_8(struct device *dev,
 		u8 reg_address,
 		u8 val)
 {
@@ -46,25 +46,14 @@ static int ade7759_spi_write_reg_16(struct device *dev,
 		u16 value)
 {
 	int ret;
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 3,
-		}
-	};
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7759_WRITE_REG(reg_address);
 	st->tx[1] = (value >> 8) & 0xFF;
 	st->tx[2] = value & 0xFF;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
+	ret = spi_write(st->us, st->tx, 3);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
@@ -74,73 +63,40 @@ static int ade7759_spi_read_reg_8(struct device *dev,
 		u8 reg_address,
 		u8 *val)
 {
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
 	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 2,
-		},
-	};
 
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7759_READ_REG(reg_address);
-	st->tx[1] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
+	ret = spi_w8r8(st->us, ADE7759_READ_REG(reg_address));
+	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 8 bit register 0x%02X",
 				reg_address);
-		goto error_ret;
+		return ret;
 	}
-	*val = st->rx[1];
+	*val = ret;
 
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
+	return 0;
 }
 
 static int ade7759_spi_read_reg_16(struct device *dev,
 		u8 reg_address,
 		u16 *val)
 {
-	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7759_state *st = iio_dev_get_devdata(indio_dev);
 	int ret;
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.rx_buf = st->rx,
-			.bits_per_word = 8,
-			.len = 3,
-		},
-	};
 
-	mutex_lock(&st->buf_lock);
-	st->tx[0] = ADE7759_READ_REG(reg_address);
-	st->tx[1] = 0;
-	st->tx[2] = 0;
-
-	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
-	ret = spi_sync(st->us, &msg);
-	if (ret) {
+	ret = spi_w8r16(st->us, ADE7759_READ_REG(reg_address));
+	if (ret < 0) {
 		dev_err(&st->us->dev, "problem when reading 16 bit register 0x%02X",
-				reg_address);
-		goto error_ret;
+			reg_address);
+		return ret;
 	}
-	*val = (st->rx[1] << 8) | st->rx[2];
 
-error_ret:
-	mutex_unlock(&st->buf_lock);
-	return ret;
+	*val = ret;
+	*val = be16_to_cpup(val);
+
+	return 0;
 }
 
 static int ade7759_spi_read_reg_40(struct device *dev,
@@ -354,27 +310,22 @@ static int ade7759_set_irq(struct device *dev, bool enable)
 		irqen &= ~(1 << 3);
 
 	ret = ade7759_spi_write_reg_8(dev, ADE7759_IRQEN, irqen);
-	if (ret)
-		goto error_ret;
 
 error_ret:
 	return ret;
 }
 
 /* Power down the device */
-int ade7759_stop_device(struct device *dev)
+static int ade7759_stop_device(struct device *dev)
 {
-	int ret;
 	u16 val;
+
 	ade7759_spi_read_reg_16(dev,
 			ADE7759_MODE,
 			&val);
 	val |= 1 << 4;  /* AD converters can be turned off */
-	ret = ade7759_spi_write_reg_16(dev,
-			ADE7759_MODE,
-			val);
 
-	return ret;
+	return ade7759_spi_write_reg_16(dev, ADE7759_MODE, val);
 }
 
 static int ade7759_initial_setup(struct ade7759_state *st)
@@ -404,7 +355,7 @@ static ssize_t ade7759_read_frequency(struct device *dev,
 		struct device_attribute *attr,
 		char *buf)
 {
-	int ret, len = 0;
+	int ret;
 	u16 t;
 	int sps;
 	ret = ade7759_spi_read_reg_16(dev,
@@ -416,8 +367,7 @@ static ssize_t ade7759_read_frequency(struct device *dev,
 	t = (t >> 3) & 0x3;
 	sps = 27900 / (1 + t);
 
-	len = sprintf(buf, "%d SPS\n", sps);
-	return len;
+	return sprintf(buf, "%d\n", sps);
 }
 
 static ssize_t ade7759_write_frequency(struct device *dev,
@@ -446,18 +396,14 @@ static ssize_t ade7759_write_frequency(struct device *dev,
 	else
 		st->us->max_speed_hz = ADE7759_SPI_FAST;
 
-	ret = ade7759_spi_read_reg_16(dev,
-			ADE7759_MODE,
-			&reg);
+	ret = ade7759_spi_read_reg_16(dev, ADE7759_MODE, &reg);
 	if (ret)
 		goto out;
 
 	reg &= ~(3 << 13);
 	reg |= t << 13;
 
-	ret = ade7759_spi_write_reg_16(dev,
-			ADE7759_MODE,
-			reg);
+	ret = ade7759_spi_write_reg_16(dev, ADE7759_MODE, reg);
 
 out:
 	mutex_unlock(&indio_dev->mlock);
@@ -478,14 +424,6 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("27900 14000 7000 3500");
 
 static IIO_CONST_ATTR(name, "ade7759");
 
-static struct attribute *ade7759_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group ade7759_event_attribute_group = {
-	.attrs = ade7759_event_attributes,
-};
-
 static struct attribute *ade7759_attributes[] = {
 	&iio_dev_attr_temp_raw.dev_attr.attr,
 	&iio_const_attr_temp_offset.dev_attr.attr,
@@ -517,7 +455,7 @@ static const struct attribute_group ade7759_attribute_group = {
 
 static int __devinit ade7759_probe(struct spi_device *spi)
 {
-	int ret, regdone = 0;
+	int ret;
 	struct ade7759_state *st = kzalloc(sizeof *st, GFP_KERNEL);
 	if (!st) {
 		ret =  -ENOMEM;
@@ -548,62 +486,27 @@ static int __devinit ade7759_probe(struct spi_device *spi)
 
 	st->indio_dev->dev.parent = &spi->dev;
 	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &ade7759_event_attribute_group;
+
 	st->indio_dev->attrs = &ade7759_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = ade7759_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
-	regdone = 1;
-
-	ret = ade7759_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
-
-	if (spi->irq) {
-		ret = iio_register_interrupt_line(spi->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_FALLING,
-				"ade7759");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = ade7759_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
+		goto error_free_dev;
 
 	/* Get the device into a sane initial state */
 	ret = ade7759_initial_setup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_unreg_dev;
 	return 0;
 
-error_remove_trigger:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		ade7759_remove_trigger(st->indio_dev);
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	ade7759_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	ade7759_unconfigure_ring(st->indio_dev);
+
+error_unreg_dev:
+	iio_device_unregister(st->indio_dev);
 error_free_dev:
-	if (regdone)
-		iio_device_unregister(st->indio_dev);
-	else
-		iio_free_device(st->indio_dev);
+	iio_free_device(st->indio_dev);
 error_free_tx:
 	kfree(st->tx);
 error_free_rx:
@@ -625,14 +528,6 @@ static int ade7759_remove(struct spi_device *spi)
 	if (ret)
 		goto err_ret;
 
-	flush_scheduled_work();
-
-	ade7759_remove_trigger(indio_dev);
-	if (spi->irq && gpio_is_valid(irq_to_gpio(spi->irq)) > 0)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	ade7759_uninitialize_ring(indio_dev->ring);
-	ade7759_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
 	kfree(st->tx);
 	kfree(st->rx);
diff --git a/drivers/staging/iio/meter/ade7759.h b/drivers/staging/iio/meter/ade7759.h
index 813dea2..e9d1c43 100644
--- a/drivers/staging/iio/meter/ade7759.h
+++ b/drivers/staging/iio/meter/ade7759.h
@@ -41,82 +41,17 @@
 /**
  * struct ade7759_state - device instance specific data
  * @us:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
  * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			recieve buffer
  * @buf_lock:		mutex to protect tx and rx
  **/
 struct ade7759_state {
 	struct spi_device		*us;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
 	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
 	u8				*tx;
 	u8				*rx;
 	struct mutex			buf_lock;
 };
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum ade7759_scan {
-	ADE7759_SCAN_ACTIVE_POWER,
-	ADE7759_SCAN_CH1_CH2,
-	ADE7759_SCAN_CH1,
-	ADE7759_SCAN_CH2,
-};
-
-void ade7759_remove_trigger(struct iio_dev *indio_dev);
-int ade7759_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t ade7759_read_data_from_ring(struct device *dev,
-		struct device_attribute *attr,
-		char *buf);
-
-
-int ade7759_configure_ring(struct iio_dev *indio_dev);
-void ade7759_unconfigure_ring(struct iio_dev *indio_dev);
-
-int ade7759_initialize_ring(struct iio_ring_buffer *ring);
-void ade7759_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void ade7759_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7759_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-ade7759_read_data_from_ring(struct device *dev,
-		struct device_attribute *attr,
-		char *buf)
-{
-	return 0;
-}
-
-static int ade7759_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-static inline void ade7759_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7759_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-static inline void ade7759_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-#endif /* CONFIG_IIO_RING_BUFFER */
 
 #endif
diff --git a/drivers/staging/iio/meter/ade7854-spi.c b/drivers/staging/iio/meter/ade7854-spi.c
index fe58103e..84da8fb 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -22,12 +22,10 @@ static int ade7854_spi_write_reg_8(struct device *dev,
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 4,
-		}
+	struct spi_transfer xfer = {
+		.tx_buf = st->tx,
+		.bits_per_word = 8,
+		.len = 4,
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -37,7 +35,7 @@ static int ade7854_spi_write_reg_8(struct device *dev,
 	st->tx[3] = value & 0xFF;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfer, &msg);
 	ret = spi_sync(st->spi, &msg);
 	mutex_unlock(&st->buf_lock);
 
@@ -52,12 +50,10 @@ static int ade7854_spi_write_reg_16(struct device *dev,
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 5,
-		}
+	struct spi_transfer xfer = {
+		.tx_buf = st->tx,
+		.bits_per_word = 8,
+		.len = 5,
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -68,7 +64,7 @@ static int ade7854_spi_write_reg_16(struct device *dev,
 	st->tx[4] = value & 0xFF;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfer, &msg);
 	ret = spi_sync(st->spi, &msg);
 	mutex_unlock(&st->buf_lock);
 
@@ -83,12 +79,10 @@ static int ade7854_spi_write_reg_24(struct device *dev,
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 6,
-		}
+	struct spi_transfer xfer = {
+		.tx_buf = st->tx,
+		.bits_per_word = 8,
+		.len = 6,
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -100,7 +94,7 @@ static int ade7854_spi_write_reg_24(struct device *dev,
 	st->tx[5] = value & 0xFF;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfer, &msg);
 	ret = spi_sync(st->spi, &msg);
 	mutex_unlock(&st->buf_lock);
 
@@ -115,12 +109,10 @@ static int ade7854_spi_write_reg_32(struct device *dev,
 	struct spi_message msg;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-	struct spi_transfer xfers[] = {
-		{
-			.tx_buf = st->tx,
-			.bits_per_word = 8,
-			.len = 7,
-		}
+	struct spi_transfer xfer = {
+		.tx_buf = st->tx,
+		.bits_per_word = 8,
+		.len = 7,
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -133,7 +125,7 @@ static int ade7854_spi_write_reg_32(struct device *dev,
 	st->tx[6] = value & 0xFF;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfer, &msg);
 	ret = spi_sync(st->spi, &msg);
 	mutex_unlock(&st->buf_lock);
 
@@ -152,8 +144,12 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 		{
 			.tx_buf = st->tx,
 			.bits_per_word = 8,
-			.len = 4,
-		},
+			.len = 3,
+		}, {
+			.rx_buf = st->rx,
+			.bits_per_word = 8,
+			.len = 1,
+		}
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -161,17 +157,17 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 	st->tx[0] = ADE7854_READ_REG;
 	st->tx[1] = (reg_address >> 8) & 0xFF;
 	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
 	ret = spi_sync(st->spi, &msg);
 	if (ret) {
 		dev_err(&st->spi->dev, "problem when reading 8 bit register 0x%02X",
 				reg_address);
 		goto error_ret;
 	}
-	*val = st->rx[3];
+	*val = st->rx[0];
 
 error_ret:
 	mutex_unlock(&st->buf_lock);
@@ -190,26 +186,29 @@ static int ade7854_spi_read_reg_16(struct device *dev,
 		{
 			.tx_buf = st->tx,
 			.bits_per_word = 8,
-			.len = 5,
-		},
+			.len = 3,
+		}, {
+			.rx_buf = st->rx,
+			.bits_per_word = 8,
+			.len = 2,
+		}
 	};
 
 	mutex_lock(&st->buf_lock);
 	st->tx[0] = ADE7854_READ_REG;
 	st->tx[1] = (reg_address >> 8) & 0xFF;
 	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
-	st->tx[4] = 0;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
 	ret = spi_sync(st->spi, &msg);
 	if (ret) {
 		dev_err(&st->spi->dev, "problem when reading 16 bit register 0x%02X",
 				reg_address);
 		goto error_ret;
 	}
-	*val = (st->rx[3] << 8) | st->rx[4];
+	*val = be16_to_cpup((const __be16 *)st->rx);
 
 error_ret:
 	mutex_unlock(&st->buf_lock);
@@ -228,8 +227,12 @@ static int ade7854_spi_read_reg_24(struct device *dev,
 		{
 			.tx_buf = st->tx,
 			.bits_per_word = 8,
-			.len = 6,
-		},
+			.len = 3,
+		}, {
+			.rx_buf = st->rx,
+			.bits_per_word = 8,
+			.len = 3,
+		}
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -237,19 +240,17 @@ static int ade7854_spi_read_reg_24(struct device *dev,
 	st->tx[0] = ADE7854_READ_REG;
 	st->tx[1] = (reg_address >> 8) & 0xFF;
 	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
-	st->tx[4] = 0;
-	st->tx[5] = 0;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
 	ret = spi_sync(st->spi, &msg);
 	if (ret) {
 		dev_err(&st->spi->dev, "problem when reading 24 bit register 0x%02X",
 				reg_address);
 		goto error_ret;
 	}
-	*val = (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5];
+	*val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
 
 error_ret:
 	mutex_unlock(&st->buf_lock);
@@ -268,8 +269,12 @@ static int ade7854_spi_read_reg_32(struct device *dev,
 		{
 			.tx_buf = st->tx,
 			.bits_per_word = 8,
-			.len = 7,
-		},
+			.len = 3,
+		}, {
+			.rx_buf = st->rx,
+			.bits_per_word = 8,
+			.len = 4,
+		}
 	};
 
 	mutex_lock(&st->buf_lock);
@@ -277,20 +282,17 @@ static int ade7854_spi_read_reg_32(struct device *dev,
 	st->tx[0] = ADE7854_READ_REG;
 	st->tx[1] = (reg_address >> 8) & 0xFF;
 	st->tx[2] = reg_address & 0xFF;
-	st->tx[3] = 0;
-	st->tx[4] = 0;
-	st->tx[5] = 0;
-	st->tx[6] = 0;
 
 	spi_message_init(&msg);
-	spi_message_add_tail(xfers, &msg);
+	spi_message_add_tail(&xfers[0], &msg);
+	spi_message_add_tail(&xfers[1], &msg);
 	ret = spi_sync(st->spi, &msg);
 	if (ret) {
 		dev_err(&st->spi->dev, "problem when reading 32 bit register 0x%02X",
 				reg_address);
 		goto error_ret;
 	}
-	*val = (st->rx[3] << 24) | (st->rx[4] << 16) | (st->rx[5] << 8) | st->rx[6];
+	*val = be32_to_cpup((const __be32 *)st->rx);
 
 error_ret:
 	mutex_unlock(&st->buf_lock);
@@ -333,6 +335,13 @@ static int ade7854_spi_remove(struct spi_device *spi)
 
 	return 0;
 }
+static const struct spi_device_id ade7854_id[] = {
+	{ "ade7854", 0 },
+	{ "ade7858", 0 },
+	{ "ade7868", 0 },
+	{ "ade7878", 0 },
+	{ }
+};
 
 static struct spi_driver ade7854_driver = {
 	.driver = {
@@ -341,6 +350,7 @@ static struct spi_driver ade7854_driver = {
 	},
 	.probe = ade7854_spi_probe,
 	.remove = __devexit_p(ade7854_spi_remove),
+	.id_table = ade7854_id,
 };
 
 static __init int ade7854_init(void)
@@ -356,5 +366,5 @@ static __exit void ade7854_exit(void)
 module_exit(ade7854_exit);
 
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC SPI Driver");
+MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 SPI Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/meter/ade7854.c b/drivers/staging/iio/meter/ade7854.c
index a13d504..866e585 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -61,7 +61,7 @@ static ssize_t ade7854_read_24bit(struct device *dev,
 		char *buf)
 {
 	int ret;
-	u32 val = 0;
+	u32 val;
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
 	struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
@@ -70,7 +70,7 @@ static ssize_t ade7854_read_24bit(struct device *dev,
 	if (ret)
 		return ret;
 
-	return sprintf(buf, "%u\n", val & 0xFFFFFF);
+	return sprintf(buf, "%u\n", val);
 }
 
 static ssize_t ade7854_read_32bit(struct device *dev,
@@ -178,15 +178,12 @@ static int ade7854_reset(struct device *dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
 	struct ade7854_state *st = iio_dev_get_devdata(indio_dev);
-
-	int ret;
 	u16 val;
 
 	st->read_reg_16(dev, ADE7854_CONFIG, &val);
 	val |= 1 << 7; /* Software Chip Reset */
-	ret = st->write_reg_16(dev, ADE7854_CONFIG, val);
 
-	return ret;
+	return st->write_reg_16(dev, ADE7854_CONFIG, val);
 }
 
 
@@ -477,14 +474,6 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000");
 
 static IIO_CONST_ATTR(name, "ade7854");
 
-static struct attribute *ade7854_event_attributes[] = {
-	NULL
-};
-
-static struct attribute_group ade7854_event_attribute_group = {
-	.attrs = ade7854_event_attributes,
-};
-
 static struct attribute *ade7854_attributes[] = {
 	&iio_dev_attr_aigain.dev_attr.attr,
 	&iio_dev_attr_bigain.dev_attr.attr,
@@ -564,7 +553,7 @@ static const struct attribute_group ade7854_attribute_group = {
 
 int ade7854_probe(struct ade7854_state *st, struct device *dev)
 {
-	int ret, regdone = 0;
+	int ret;
 
 	/* Allocate the comms buffers */
 	st->rx = kzalloc(sizeof(*st->rx)*ADE7854_MAX_RX, GFP_KERNEL);
@@ -586,71 +575,34 @@ int ade7854_probe(struct ade7854_state *st, struct device *dev)
 	}
 
 	st->indio_dev->dev.parent = dev;
-	st->indio_dev->num_interrupt_lines = 1;
-	st->indio_dev->event_attrs = &ade7854_event_attribute_group;
 	st->indio_dev->attrs = &ade7854_attribute_group;
 	st->indio_dev->dev_data = (void *)(st);
 	st->indio_dev->driver_module = THIS_MODULE;
 	st->indio_dev->modes = INDIO_DIRECT_MODE;
 
-	ret = ade7854_configure_ring(st->indio_dev);
-	if (ret)
-		goto error_free_dev;
-
 	ret = iio_device_register(st->indio_dev);
 	if (ret)
-		goto error_unreg_ring_funcs;
-	regdone = 1;
-
-	ret = ade7854_initialize_ring(st->indio_dev->ring);
-	if (ret) {
-		printk(KERN_ERR "failed to initialize the ring\n");
-		goto error_unreg_ring_funcs;
-	}
+		goto error_free_dev;
 
-	if (st->irq) {
-		ret = iio_register_interrupt_line(st->irq,
-				st->indio_dev,
-				0,
-				IRQF_TRIGGER_FALLING,
-				"ade7854");
-		if (ret)
-			goto error_uninitialize_ring;
-
-		ret = ade7854_probe_trigger(st->indio_dev);
-		if (ret)
-			goto error_unregister_line;
-	}
 	/* Get the device into a sane initial state */
 	ret = ade7854_initial_setup(st);
 	if (ret)
-		goto error_remove_trigger;
+		goto error_unreg_dev;
 
 	return 0;
 
-error_remove_trigger:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		ade7854_remove_trigger(st->indio_dev);
-error_unregister_line:
-	if (st->indio_dev->modes & INDIO_RING_TRIGGERED)
-		iio_unregister_interrupt_line(st->indio_dev, 0);
-error_uninitialize_ring:
-	ade7854_uninitialize_ring(st->indio_dev->ring);
-error_unreg_ring_funcs:
-	ade7854_unconfigure_ring(st->indio_dev);
+error_unreg_dev:
+	iio_device_unregister(st->indio_dev);
 error_free_dev:
-	if (regdone)
-		iio_device_unregister(st->indio_dev);
-	else
-		iio_free_device(st->indio_dev);
+	iio_free_device(st->indio_dev);
 error_free_tx:
 	kfree(st->tx);
 error_free_rx:
 	kfree(st->rx);
 error_free_st:
 	kfree(st);
-	return ret;
 
+	return ret;
 }
 EXPORT_SYMBOL(ade7854_probe);
 
@@ -658,14 +610,6 @@ int ade7854_remove(struct ade7854_state *st)
 {
 	struct iio_dev *indio_dev = st->indio_dev;
 
-	flush_scheduled_work();
-
-	ade7854_remove_trigger(indio_dev);
-	if (st->irq)
-		iio_unregister_interrupt_line(indio_dev, 0);
-
-	ade7854_uninitialize_ring(indio_dev->ring);
-	ade7854_unconfigure_ring(indio_dev);
 	iio_device_unregister(indio_dev);
 	kfree(st->tx);
 	kfree(st->rx);
@@ -676,5 +620,5 @@ int ade7854_remove(struct ade7854_state *st)
 EXPORT_SYMBOL(ade7854_remove);
 
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
-MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Multifunction Energy Metering IC Driver");
+MODULE_DESCRIPTION("Analog Devices ADE7854/58/68/78 Polyphase Energy Meter");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h
index 47690e5..4ad84a3 100644
--- a/drivers/staging/iio/meter/ade7854.h
+++ b/drivers/staging/iio/meter/ade7854.h
@@ -147,11 +147,7 @@
 /**
  * struct ade7854_state - device instance specific data
  * @spi:			actual spi_device
- * @work_trigger_to_ring: bh for triggered event handling
- * @inter:		used to check if new interrupt has been triggered
- * @last_timestamp:	passing timestamp from th to bh of interrupt handler
  * @indio_dev:		industrial I/O device structure
- * @trig:		data ready trigger registered with iio
  * @tx:			transmit buffer
  * @rx:			recieve buffer
  * @buf_lock:		mutex to protect tx and rx
@@ -159,10 +155,7 @@
 struct ade7854_state {
 	struct spi_device		*spi;
 	struct i2c_client               *i2c;
-	struct work_struct		work_trigger_to_ring;
-	s64				last_timestamp;
 	struct iio_dev			*indio_dev;
-	struct iio_trigger		*trig;
 	u8				*tx;
 	u8				*rx;
 	int				(*read_reg_8) (struct device *, u16, u8 *);
@@ -180,66 +173,4 @@ struct ade7854_state {
 extern int ade7854_probe(struct ade7854_state *st, struct device *dev);
 extern int ade7854_remove(struct ade7854_state *st);
 
-#if defined(CONFIG_IIO_RING_BUFFER) && defined(THIS_HAS_RING_BUFFER_SUPPORT)
-/* At the moment triggers are only used for ring buffer
- * filling. This may change!
- */
-
-enum ade7854_scan {
-	ADE7854_SCAN_PHA_V,
-	ADE7854_SCAN_PHB_V,
-	ADE7854_SCAN_PHC_V,
-	ADE7854_SCAN_PHA_I,
-	ADE7854_SCAN_PHB_I,
-	ADE7854_SCAN_PHC_I,
-};
-
-void ade7854_remove_trigger(struct iio_dev *indio_dev);
-int ade7854_probe_trigger(struct iio_dev *indio_dev);
-
-ssize_t ade7854_read_data_from_ring(struct device *dev,
-				      struct device_attribute *attr,
-				      char *buf);
-
-
-int ade7854_configure_ring(struct iio_dev *indio_dev);
-void ade7854_unconfigure_ring(struct iio_dev *indio_dev);
-
-int ade7854_initialize_ring(struct iio_ring_buffer *ring);
-void ade7854_uninitialize_ring(struct iio_ring_buffer *ring);
-#else /* CONFIG_IIO_RING_BUFFER */
-
-static inline void ade7854_remove_trigger(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7854_probe_trigger(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline ssize_t
-ade7854_read_data_from_ring(struct device *dev,
-			      struct device_attribute *attr,
-			      char *buf)
-{
-	return 0;
-}
-
-static inline int ade7854_configure_ring(struct iio_dev *indio_dev)
-{
-	return 0;
-}
-
-static inline void ade7854_unconfigure_ring(struct iio_dev *indio_dev)
-{
-}
-static inline int ade7854_initialize_ring(struct iio_ring_buffer *ring)
-{
-	return 0;
-}
-static inline void ade7854_uninitialize_ring(struct iio_ring_buffer *ring)
-{
-}
-#endif /* CONFIG_IIO_RING_BUFFER */
-
 #endif
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index 8ecb189..f21ac09 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -73,7 +73,7 @@ struct iio_ring_access_funcs {
 	int (*read_last)(struct iio_ring_buffer *ring, u8 *data);
 	int (*rip_lots)(struct iio_ring_buffer *ring,
 			size_t count,
-			u8 **data,
+			char __user *buf,
 			int *dead_offset);
 
 	int (*mark_param_change)(struct iio_ring_buffer *ring);
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index 52624ac..b71ce39 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/workqueue.h>
+#include <linux/poll.h>
 #include "ring_sw.h"
 #include "trigger.h"
 
@@ -152,11 +153,12 @@ error_ret:
 }
 
 int iio_rip_sw_rb(struct iio_ring_buffer *r,
-		  size_t count, u8 **data, int *dead_offset)
+		  size_t count, char __user *buf, int *dead_offset)
 {
 	struct iio_sw_ring_buffer *ring = iio_to_sw_ring(r);
 
 	u8 *initial_read_p, *initial_write_p, *current_read_p, *end_read_p;
+	u8 *data;
 	int ret, max_copied;
 	int bytes_to_rip;
 
@@ -174,8 +176,8 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
 	/* Limit size to whole of ring buffer */
 	bytes_to_rip = min((size_t)(ring->buf.bytes_per_datum*ring->buf.length), count);
 
-	*data = kmalloc(bytes_to_rip, GFP_KERNEL);
-	if (*data == NULL) {
+	data = kmalloc(bytes_to_rip, GFP_KERNEL);
+	if (data == NULL) {
 		ret = -ENOMEM;
 		goto error_ret;
 	}
@@ -204,30 +206,30 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
 	if (initial_write_p >= initial_read_p + bytes_to_rip) {
 		/* write_p is greater than necessary, all is easy */
 		max_copied = bytes_to_rip;
-		memcpy(*data, initial_read_p, max_copied);
+		memcpy(data, initial_read_p, max_copied);
 		end_read_p = initial_read_p + max_copied;
 	} else if (initial_write_p > initial_read_p) {
 		/*not enough data to cpy */
 		max_copied = initial_write_p - initial_read_p;
-		memcpy(*data, initial_read_p, max_copied);
+		memcpy(data, initial_read_p, max_copied);
 		end_read_p = initial_write_p;
 	} else {
 		/* going through 'end' of ring buffer */
 		max_copied = ring->data
 			+ ring->buf.length*ring->buf.bytes_per_datum - initial_read_p;
-		memcpy(*data, initial_read_p, max_copied);
+		memcpy(data, initial_read_p, max_copied);
 		/* possible we are done if we align precisely with end */
 		if (max_copied == bytes_to_rip)
 			end_read_p = ring->data;
 		else if (initial_write_p
 			 > ring->data + bytes_to_rip - max_copied) {
 			/* enough data to finish */
-			memcpy(*data + max_copied, ring->data,
+			memcpy(data + max_copied, ring->data,
 			       bytes_to_rip - max_copied);
 			max_copied = bytes_to_rip;
 			end_read_p = ring->data + (bytes_to_rip - max_copied);
 		} else {  /* not enough data */
-			memcpy(*data + max_copied, ring->data,
+			memcpy(data + max_copied, ring->data,
 			       initial_write_p - ring->data);
 			max_copied += initial_write_p - ring->data;
 			end_read_p = initial_write_p;
@@ -264,11 +266,16 @@ int iio_rip_sw_rb(struct iio_ring_buffer *r,
 	while (ring->read_p != end_read_p)
 		ring->read_p = end_read_p;
 
-	return max_copied - *dead_offset;
+	ret = max_copied - *dead_offset;
 
+	if (copy_to_user(buf, data + *dead_offset, ret))  {
+		ret =  -EFAULT;
+		goto error_free_data_cpy;
+	}
 error_free_data_cpy:
-	kfree(*data);
+	kfree(data);
 error_ret:
+
 	return ret;
 }
 EXPORT_SYMBOL(iio_rip_sw_rb);
diff --git a/drivers/staging/iio/ring_sw.h b/drivers/staging/iio/ring_sw.h
index ad03d83..13341c1e 100644
--- a/drivers/staging/iio/ring_sw.h
+++ b/drivers/staging/iio/ring_sw.h
@@ -96,13 +96,13 @@ int iio_store_to_sw_rb(struct iio_ring_buffer *r, u8 *data, s64 timestamp);
  * iio_rip_sw_rb() - attempt to read data from the ring buffer
  * @r:			ring buffer instance
  * @count:		number of datum's to try and read
- * @data:		where the data will be stored.
+ * @buf:		userspace buffer into which data is copied
  * @dead_offset:	how much of the stored data was possibly invalidated by
  *			the end of the copy.
  **/
 int iio_rip_sw_rb(struct iio_ring_buffer *r,
 		  size_t count,
-		  u8 **data,
+		  char __user *buf,
 		  int *dead_offset);
 
 /**
diff --git a/drivers/staging/iio/trigger/Kconfig b/drivers/staging/iio/trigger/Kconfig
index d842a58..c33777e 100644
--- a/drivers/staging/iio/trigger/Kconfig
+++ b/drivers/staging/iio/trigger/Kconfig
@@ -18,4 +18,24 @@ config IIO_GPIO_TRIGGER
 	help
 	  Provides support for using GPIO pins as IIO triggers.
 
+config IIO_SYSFS_TRIGGER
+	tristate "SYSFS trigger"
+	depends on SYSFS
+	help
+	  Provides support for using SYSFS entry as IIO triggers.
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iio-trig-sysfs.
+
+config IIO_BFIN_TMR_TRIGGER
+	tristate "Blackfin TIMER trigger"
+	depends on BLACKFIN
+	help
+	  Provides support for using a Blackfin timer as IIO triggers.
+	  If unsure, say N (but it's safe to say "Y").
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called iio-trig-bfin-timer.
+
 endif # IIO_TRIGGER
diff --git a/drivers/staging/iio/trigger/Makefile b/drivers/staging/iio/trigger/Makefile
index 10aeca5..b088b57 100644
--- a/drivers/staging/iio/trigger/Makefile
+++ b/drivers/staging/iio/trigger/Makefile
@@ -4,3 +4,5 @@
 
 obj-$(CONFIG_IIO_PERIODIC_RTC_TRIGGER) += iio-trig-periodic-rtc.o
 obj-$(CONFIG_IIO_GPIO_TRIGGER) += iio-trig-gpio.o
+obj-$(CONFIG_IIO_SYSFS_TRIGGER) += iio-trig-sysfs.o
+obj-$(CONFIG_IIO_BFIN_TMR_TRIGGER) += iio-trig-bfin-timer.o
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
new file mode 100644
index 0000000..583bef0
--- /dev/null
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+
+#include <asm/gptimers.h>
+
+#include "../iio.h"
+#include "../trigger.h"
+
+struct bfin_timer {
+	unsigned short id, bit;
+	unsigned long irqbit;
+	int irq;
+};
+
+/*
+ * this covers all hardware timer configurations on
+ * all Blackfin derivatives out there today
+ */
+
+static struct bfin_timer iio_bfin_timer_code[MAX_BLACKFIN_GPTIMERS] = {
+	{TIMER0_id,  TIMER0bit,  TIMER_STATUS_TIMIL0,  IRQ_TIMER0},
+	{TIMER1_id,  TIMER1bit,  TIMER_STATUS_TIMIL1,  IRQ_TIMER1},
+	{TIMER2_id,  TIMER2bit,  TIMER_STATUS_TIMIL2,  IRQ_TIMER2},
+#if (MAX_BLACKFIN_GPTIMERS > 3)
+	{TIMER3_id,  TIMER3bit,  TIMER_STATUS_TIMIL3,  IRQ_TIMER3},
+	{TIMER4_id,  TIMER4bit,  TIMER_STATUS_TIMIL4,  IRQ_TIMER4},
+	{TIMER5_id,  TIMER5bit,  TIMER_STATUS_TIMIL5,  IRQ_TIMER5},
+	{TIMER6_id,  TIMER6bit,  TIMER_STATUS_TIMIL6,  IRQ_TIMER6},
+	{TIMER7_id,  TIMER7bit,  TIMER_STATUS_TIMIL7,  IRQ_TIMER7},
+#endif
+#if (MAX_BLACKFIN_GPTIMERS > 8)
+	{TIMER8_id,  TIMER8bit,  TIMER_STATUS_TIMIL8,  IRQ_TIMER8},
+	{TIMER9_id,  TIMER9bit,  TIMER_STATUS_TIMIL9,  IRQ_TIMER9},
+	{TIMER10_id, TIMER10bit, TIMER_STATUS_TIMIL10, IRQ_TIMER10},
+#if (MAX_BLACKFIN_GPTIMERS > 11)
+	{TIMER11_id, TIMER11bit, TIMER_STATUS_TIMIL11, IRQ_TIMER11},
+#endif
+#endif
+};
+
+struct bfin_tmr_state {
+	struct iio_trigger *trig;
+	struct bfin_timer *t;
+	unsigned timer_num;
+	int irq;
+};
+
+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 = dev_get_drvdata(dev);
+	struct bfin_tmr_state *st = trig->private_data;
+	long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 10, &val);
+	if (ret)
+		goto error_ret;
+
+	if (val > 100000) {
+		ret = -EINVAL;
+		goto error_ret;
+	}
+
+	disable_gptimers(st->t->bit);
+
+	if (!val)
+		goto error_ret;
+
+	val = get_sclk() / val;
+	if (val <= 4) {
+		ret = -EINVAL;
+		goto error_ret;
+	}
+
+	set_gptimer_period(st->t->id, val);
+	set_gptimer_pwidth(st->t->id, 1);
+	enable_gptimers(st->t->bit);
+
+error_ret:
+	return ret ? ret : count;
+}
+
+static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct iio_trigger *trig = dev_get_drvdata(dev);
+	struct bfin_tmr_state *st = trig->private_data;
+
+	return sprintf(buf, "%lu\n",
+			get_sclk() / get_gptimer_period(st->t->id));
+}
+
+static DEVICE_ATTR(frequency, S_IRUGO | S_IWUSR, iio_bfin_tmr_frequency_show,
+		   iio_bfin_tmr_frequency_store);
+static IIO_TRIGGER_NAME_ATTR;
+
+static struct attribute *iio_bfin_tmr_trigger_attrs[] = {
+	&dev_attr_frequency.attr,
+	&dev_attr_name.attr,
+	NULL,
+};
+
+static const struct attribute_group iio_bfin_tmr_trigger_attr_group = {
+	.attrs = iio_bfin_tmr_trigger_attrs,
+};
+
+
+static irqreturn_t iio_bfin_tmr_trigger_isr(int irq, void *devid)
+{
+	struct bfin_tmr_state *st = devid;
+
+	clear_gptimer_intr(st->t->id);
+	iio_trigger_poll(st->trig, 0);
+
+	return IRQ_HANDLED;
+}
+
+static int iio_bfin_tmr_get_number(int irq)
+{
+	int i;
+
+	for (i = 0; i < MAX_BLACKFIN_GPTIMERS; i++)
+		if (iio_bfin_timer_code[i].irq == irq)
+			return i;
+
+	return -ENODEV;
+}
+
+static int __devinit iio_bfin_tmr_trigger_probe(struct platform_device *pdev)
+{
+	struct bfin_tmr_state *st;
+	int ret;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	st->irq = platform_get_irq(pdev, 0);
+	if (!st->irq) {
+		dev_err(&pdev->dev, "No IRQs specified");
+		ret = -ENODEV;
+		goto out1;
+	}
+
+	ret = iio_bfin_tmr_get_number(st->irq);
+	if (ret < 0)
+		goto out1;
+
+	st->timer_num = ret;
+	st->t = &iio_bfin_timer_code[st->timer_num];
+
+	st->trig = iio_allocate_trigger();
+	if (!st->trig) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	st->trig->private_data = st;
+	st->trig->control_attrs = &iio_bfin_tmr_trigger_attr_group;
+	st->trig->owner = THIS_MODULE;
+	st->trig->name = kasprintf(GFP_KERNEL, "bfintmr%d", st->timer_num);
+	if (st->trig->name == NULL) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	ret = iio_trigger_register(st->trig);
+	if (ret)
+		goto out3;
+
+	ret = request_irq(st->irq, iio_bfin_tmr_trigger_isr,
+			  0, st->trig->name, st);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"request IRQ-%d failed", st->irq);
+		goto out4;
+	}
+
+	set_gptimer_config(st->t->id, OUT_DIS | PWM_OUT | PERIOD_CNT | IRQ_ENA);
+
+	dev_info(&pdev->dev, "iio trigger Blackfin TMR%d, IRQ-%d",
+		 st->timer_num, st->irq);
+	platform_set_drvdata(pdev, st);
+
+	return 0;
+out4:
+	iio_trigger_unregister(st->trig);
+out3:
+	kfree(st->trig->name);
+out2:
+	iio_put_trigger(st->trig);
+out1:
+	kfree(st);
+out:
+	return ret;
+}
+
+static int __devexit iio_bfin_tmr_trigger_remove(struct platform_device *pdev)
+{
+	struct bfin_tmr_state *st = platform_get_drvdata(pdev);
+
+	disable_gptimers(st->t->bit);
+	free_irq(st->irq, st);
+	iio_trigger_unregister(st->trig);
+	kfree(st->trig->name);
+	iio_put_trigger(st->trig);
+	kfree(st);
+
+	return 0;
+}
+
+static struct platform_driver iio_bfin_tmr_trigger_driver = {
+	.driver = {
+		.name = "iio_bfin_tmr_trigger",
+		.owner = THIS_MODULE,
+	},
+	.probe = iio_bfin_tmr_trigger_probe,
+	.remove = __devexit_p(iio_bfin_tmr_trigger_remove),
+};
+
+static int __init iio_bfin_tmr_trig_init(void)
+{
+	return platform_driver_register(&iio_bfin_tmr_trigger_driver);
+}
+module_init(iio_bfin_tmr_trig_init);
+
+static void __exit iio_bfin_tmr_trig_exit(void)
+{
+	platform_driver_unregister(&iio_bfin_tmr_trigger_driver);
+}
+module_exit(iio_bfin_tmr_trig_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Blackfin system timer based trigger for the iio subsystem");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:iio-trig-bfin-timer");
diff --git a/drivers/staging/iio/trigger/iio-trig-sysfs.c b/drivers/staging/iio/trigger/iio-trig-sysfs.c
new file mode 100644
index 0000000..127a2a3
--- /dev/null
+++ b/drivers/staging/iio/trigger/iio-trig-sysfs.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "../iio.h"
+#include "../trigger.h"
+
+static ssize_t iio_sysfs_trigger_poll(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct iio_trigger *trig = dev_get_drvdata(dev);
+	iio_trigger_poll(trig, 0);
+
+	return count;
+}
+
+static DEVICE_ATTR(trigger_now, S_IWUSR, NULL, iio_sysfs_trigger_poll);
+static IIO_TRIGGER_NAME_ATTR;
+
+static struct attribute *iio_sysfs_trigger_attrs[] = {
+	&dev_attr_trigger_now.attr,
+	&dev_attr_name.attr,
+	NULL,
+};
+
+static const struct attribute_group iio_sysfs_trigger_attr_group = {
+	.attrs = iio_sysfs_trigger_attrs,
+};
+
+static int __devinit iio_sysfs_trigger_probe(struct platform_device *pdev)
+{
+	struct iio_trigger *trig;
+	int ret;
+
+	trig = iio_allocate_trigger();
+	if (!trig) {
+		ret = -ENOMEM;
+		goto out1;
+	}
+
+	trig->control_attrs = &iio_sysfs_trigger_attr_group;
+	trig->owner = THIS_MODULE;
+	trig->name = kasprintf(GFP_KERNEL, "sysfstrig%d", pdev->id);
+	if (trig->name == NULL) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	ret = iio_trigger_register(trig);
+	if (ret)
+		goto out3;
+
+	platform_set_drvdata(pdev, trig);
+
+	return 0;
+out3:
+	kfree(trig->name);
+out2:
+	iio_put_trigger(trig);
+out1:
+
+	return ret;
+}
+
+static int __devexit iio_sysfs_trigger_remove(struct platform_device *pdev)
+{
+	struct iio_trigger *trig = platform_get_drvdata(pdev);
+
+	iio_trigger_unregister(trig);
+	kfree(trig->name);
+	iio_put_trigger(trig);
+
+	return 0;
+}
+
+static struct platform_driver iio_sysfs_trigger_driver = {
+	.driver = {
+		.name = "iio_sysfs_trigger",
+		.owner = THIS_MODULE,
+	},
+	.probe = iio_sysfs_trigger_probe,
+	.remove = __devexit_p(iio_sysfs_trigger_remove),
+};
+
+static int __init iio_sysfs_trig_init(void)
+{
+	return platform_driver_register(&iio_sysfs_trigger_driver);
+}
+module_init(iio_sysfs_trig_init);
+
+static void __exit iio_sysfs_trig_exit(void)
+{
+	platform_driver_unregister(&iio_sysfs_trigger_driver);
+}
+module_exit(iio_sysfs_trig_exit);
+
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("Sysfs based trigger for the iio subsystem");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:iio-trig-sysfs");
diff --git a/drivers/staging/intel_sst/intel_sst_stream_encoded.c b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
index 85789ba..29753c7 100644
--- a/drivers/staging/intel_sst/intel_sst_stream_encoded.c
+++ b/drivers/staging/intel_sst/intel_sst_stream_encoded.c
@@ -171,7 +171,7 @@ int sst_set_stream_param(int str_id, struct snd_sst_params *str_param)
 }
 
 /**
-* sst_get_vol - This fuction allows to get the premix gain or gain of a stream
+* sst_get_vol - This function allows to get the premix gain or gain of a stream
 *
 * @get_vol: this is an output param through which the volume
 *	structure is passed back to user
@@ -221,7 +221,7 @@ int sst_get_vol(struct snd_sst_vol *get_vol)
 }
 
 /**
-* sst_set_vol - This fuction allows to set the premix gain or gain of a stream
+* sst_set_vol - This function allows to set the premix gain or gain of a stream
 *
 * @set_vol:	this holds the volume structure that needs to be set
 *
@@ -263,7 +263,7 @@ int sst_set_vol(struct snd_sst_vol *set_vol)
 }
 
 /**
-* sst_set_mute - This fuction sets premix mute or soft mute of a stream
+* sst_set_mute - This function sets premix mute or soft mute of a stream
 *
 * @set_mute:	this holds the mute structure that needs to be set
 *
@@ -450,7 +450,7 @@ err:
 }
 
 /**
- * sst_target_device_select - This fuction sets the target device configurations
+ * sst_target_device_select - This function sets the target device configurations
  *
  * @target: this parameter holds the configurations to be set
  *
diff --git a/drivers/staging/intel_sst/intelmid.h b/drivers/staging/intel_sst/intelmid.h
index 0ce1031..ca881b7 100644
--- a/drivers/staging/intel_sst/intelmid.h
+++ b/drivers/staging/intel_sst/intelmid.h
@@ -94,8 +94,8 @@ struct mad_jack_msg_wq {
  * @irq: interrupt number detected
  * @pmic_status: Device status of sound card
  * @int_base: ptr to MMIO interrupt region
- * @output_sel: device slected as o/p
- * @input_sel: device slected as i/p
+ * @output_sel: device selected as o/p
+ * @input_sel: device selected as i/p
  * @master_mute: master mute status
  * @jack: jack status
  * @playback_cnt: active pb streams
diff --git a/drivers/staging/intel_sst/intelmid_v0_control.c b/drivers/staging/intel_sst/intelmid_v0_control.c
index 7859225..7756f8f 100644
--- a/drivers/staging/intel_sst/intelmid_v0_control.c
+++ b/drivers/staging/intel_sst/intelmid_v0_control.c
@@ -68,7 +68,7 @@ int rev_id = 0x20;
 /****
  * fs_init_card - initialize the sound card
  *
- * This initilizes the audio paths to know values in case of this sound card
+ * This initializes the audio paths to know values in case of this sound card
  */
 static int fs_init_card(void)
 {
diff --git a/drivers/staging/intel_sst/intelmid_v1_control.c b/drivers/staging/intel_sst/intelmid_v1_control.c
index 478cfec..9cc15c1 100644
--- a/drivers/staging/intel_sst/intelmid_v1_control.c
+++ b/drivers/staging/intel_sst/intelmid_v1_control.c
@@ -72,9 +72,9 @@ enum _reg_v2 {
 
 };
 /**
- * mx_init_card - initilize the sound card
+ * mx_init_card - initialize the sound card
  *
- * This initilizes the audio paths to know values in case of this sound card
+ * This initializes the audio paths to know values in case of this sound card
  */
 static int mx_init_card(void)
 {
diff --git a/drivers/staging/intel_sst/intelmid_v2_control.c b/drivers/staging/intel_sst/intelmid_v2_control.c
index e2f6d6a..26d815a 100644
--- a/drivers/staging/intel_sst/intelmid_v2_control.c
+++ b/drivers/staging/intel_sst/intelmid_v2_control.c
@@ -84,9 +84,9 @@ enum reg_v3 {
 };
 
 /****
- * nc_init_card - initilize the sound card
+ * nc_init_card - initialize the sound card
  *
- * This initilizes the audio paths to know values in case of this sound card
+ * This initializes the audio paths to know values in case of this sound card
  */
 static int nc_init_card(void)
 {
diff --git a/drivers/staging/keucr/Kconfig b/drivers/staging/keucr/Kconfig
index b595bdb..e397fad 100644
--- a/drivers/staging/keucr/Kconfig
+++ b/drivers/staging/keucr/Kconfig
@@ -1,8 +1,9 @@
 config USB_ENESTORAGE
-	tristate "USB ENE card reader support"
+	tristate "USB ENE SM/MS card reader support"
 	depends on USB && SCSI && m
 	---help---
-	  Say Y here if you wish to control a ENE Card reader.
+	  Say Y here if you wish to control a ENE SM/MS Card reader.
+	  To use SD card, please build driver/usb/storage/ums-eneub6250.ko
 
 	  This option depends on 'SCSI' support being enabled, but you
 	  probably also need 'SCSI device support: SCSI disk support'
diff --git a/drivers/staging/keucr/Makefile b/drivers/staging/keucr/Makefile
index 5c19b7b..ae928f9 100644
--- a/drivers/staging/keucr/Makefile
+++ b/drivers/staging/keucr/Makefile
@@ -7,7 +7,6 @@ keucr-y :=			\
 		scsiglue.o	\
 		transport.o	\
 		init.o		\
-		sdscsi.o	\
 		msscsi.o	\
 		ms.o		\
 		smscsi.o	\
diff --git a/drivers/staging/keucr/TODO b/drivers/staging/keucr/TODO
index 29f1b10..1c48e40 100644
--- a/drivers/staging/keucr/TODO
+++ b/drivers/staging/keucr/TODO
@@ -6,9 +6,7 @@ TODO:
 	  be merged into the drivers/usb/storage/ directory and
 	  infrastructure instead.
 	- review by the USB developer community
-	- common.h: use kernel swap, le, & be functions
-	- smcommon.h & smilsub.c: use kernel hweight8(), hweight16(),
-		strcmp(), & strcpy()
+	- smcommon.h & smilsub.c: use kernel hweight8(), hweight16()
 
 Please send any patches for this driver to Al Cho <acho@novell.com> and
 Greg Kroah-Hartman <gregkh@suse.de>.
diff --git a/drivers/staging/keucr/common.h b/drivers/staging/keucr/common.h
index 8693c54..b87dc7a 100644
--- a/drivers/staging/keucr/common.h
+++ b/drivers/staging/keucr/common.h
@@ -1,7 +1,6 @@
 #ifndef COMMON_INCD
 #define COMMON_INCD
 
-typedef void VOID;
 typedef u8 BOOLEAN;
 typedef u8 BYTE;
 typedef u8 *PBYTE;
@@ -10,17 +9,5 @@ typedef u16 *PWORD;
 typedef u32 DWORD;
 typedef u32 *PDWORD;
 
-#define swapWORD(w)	((((unsigned short)(w) << 8) & 0xff00) |	\
-			 (((unsigned short)(w) >> 8) & 0x00ff))
-#define swapDWORD(dw)	((((unsigned long)(dw) << 24) & 0xff000000) |	\
-			 (((unsigned long)(dw) <<  8) & 0x00ff0000) |	\
-			 (((unsigned long)(dw) >>  8) & 0x0000ff00) |	\
-			 (((unsigned long)(dw) >> 24) & 0x000000ff))
-
-#define LittleEndianWORD(w)	(w)
-#define LittleEndianDWORD(dw)	(dw)
-#define BigEndianWORD(w)	swapWORD(w)
-#define BigEndianDWORD(dw)	swapDWORD(dw)
-
 #endif
 
diff --git a/drivers/staging/keucr/init.c b/drivers/staging/keucr/init.c
index 515e448..5c01f28 100644
--- a/drivers/staging/keucr/init.c
+++ b/drivers/staging/keucr/init.c
@@ -30,14 +30,6 @@ int ENE_InitMedia(struct us_data *us)
 	}
 	printk(KERN_INFO "MiscReg03 = %x\n", MiscReg03);
 
-	if (MiscReg03 & 0x01) {
-		if (!us->SD_Status.Ready) {
-			result = ENE_SDInit(us);
-			if (result != USB_STOR_XFER_GOOD)
-				return USB_STOR_TRANSPORT_ERROR;
-		}
-	}
-
 	if (MiscReg03 & 0x02) {
 		if (!us->SM_Status.Ready && !us->MS_Status.Ready) {
 			result = ENE_SMInit(us);
@@ -73,69 +65,6 @@ int ENE_Read_BYTE(struct us_data *us, WORD index, void *buf)
 }
 
 /*
- * ENE_SDInit():
- */
-int ENE_SDInit(struct us_data *us)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int	result;
-	BYTE	buf[0x200];
-
-	printk(KERN_INFO "transport --- ENE_SDInit\n");
-	/* SD Init Part-1 */
-	result = ENE_LoadBinCode(us, SD_INIT1_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		printk(KERN_ERR "Load SD Init Code Part-1 Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->Flags = 0x80;
-	bcb->CDB[0] = 0xF2;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, NULL, 0);
-	if (result != USB_STOR_XFER_GOOD) {
-		printk(KERN_ERR "Exection SD Init Code Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	/* SD Init Part-2 */
-	result = ENE_LoadBinCode(us, SD_INIT2_PATTERN);
-	if (result != USB_STOR_XFER_GOOD) {
-		printk(KERN_ERR "Load SD Init Code Part-2 Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength	= 0x200;
-	bcb->Flags			= 0x80;
-	bcb->CDB[0]			= 0xF1;
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, &buf, 0);
-	if (result != USB_STOR_XFER_GOOD) {
-		printk(KERN_ERR "Exection SD Init Code Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	us->SD_Status =  *(PSD_STATUS)&buf[0];
-	if (us->SD_Status.Insert && us->SD_Status.Ready) {
-		ENE_ReadSDReg(us, (PBYTE)&buf);
-		printk(KERN_INFO "Insert     = %x\n", us->SD_Status.Insert);
-		printk(KERN_INFO "Ready      = %x\n", us->SD_Status.Ready);
-		printk(KERN_INFO "IsMMC      = %x\n", us->SD_Status.IsMMC);
-		printk(KERN_INFO "HiCapacity = %x\n", us->SD_Status.HiCapacity);
-		printk(KERN_INFO "HiSpeed    = %x\n", us->SD_Status.HiSpeed);
-		printk(KERN_INFO "WtP        = %x\n", us->SD_Status.WtP);
-	} else {
-		printk(KERN_ERR "SD Card Not Ready --- %x\n", buf[0]);
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
  * ENE_MSInit():
  */
 int ENE_MSInit(struct us_data *us)
@@ -242,38 +171,6 @@ int ENE_SMInit(struct us_data *us)
 }
 
 /*
- * ENE_ReadSDReg()
- */
-int ENE_ReadSDReg(struct us_data *us, u8 *RdBuf)
-{
-	WORD	tmpreg;
-	DWORD	reg4b;
-
-	/* printk(KERN_INFO "transport --- ENE_ReadSDReg\n"); */
-	reg4b = *(PDWORD)&RdBuf[0x18];
-	us->SD_READ_BL_LEN = (BYTE)((reg4b >> 8) & 0x0f);
-
-	tmpreg = (WORD) reg4b;
-	reg4b = *(PDWORD)(&RdBuf[0x14]);
-	if (us->SD_Status.HiCapacity && !us->SD_Status.IsMMC)
-		us->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
-
-	us->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (WORD)(reg4b >> 22);
-	us->SD_C_SIZE_MULT = (BYTE)(reg4b >> 7)  & 0x07;
-	if (us->SD_Status.HiCapacity && us->SD_Status.IsMMC)
-		us->HC_C_SIZE = *(PDWORD)(&RdBuf[0x100]);
-
-	if (us->SD_READ_BL_LEN > SD_BLOCK_LEN) {
-		us->SD_Block_Mult =
-			1 << (us->SD_READ_BL_LEN - SD_BLOCK_LEN);
-		us->SD_READ_BL_LEN = SD_BLOCK_LEN;
-	} else {
-		us->SD_Block_Mult = 1;
-	}
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-/*
  * ENE_LoadBinCode()
  */
 int ENE_LoadBinCode(struct us_data *us, BYTE flag)
@@ -291,19 +188,6 @@ int ENE_LoadBinCode(struct us_data *us, BYTE flag)
 	if (buf == NULL)
 		return USB_STOR_TRANSPORT_ERROR;
 	switch (flag) {
-	/* For SD */
-	case SD_INIT1_PATTERN:
-		printk(KERN_INFO "SD_INIT1_PATTERN\n");
-		memcpy(buf, SD_Init1, 0x800);
-		break;
-	case SD_INIT2_PATTERN:
-		printk(KERN_INFO "SD_INIT2_PATTERN\n");
-		memcpy(buf, SD_Init2, 0x800);
-		break;
-	case SD_RW_PATTERN:
-		printk(KERN_INFO "SD_RW_PATTERN\n");
-		memcpy(buf, SD_Rdwr, 0x800);
-		break;
 	/* For MS */
 	case MS_INIT_PATTERN:
 		printk(KERN_INFO "MS_INIT_PATTERN\n");
@@ -412,8 +296,9 @@ int ENE_SendScsiCmd(struct us_data *us, BYTE fDir, void *buf, int use_sg)
 	 */
 	if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
 		residue = min(residue, transfer_length);
-		scsi_set_resid(us->srb, max(scsi_get_resid(us->srb),
-							(int) residue));
+		if (us->srb)
+			scsi_set_resid(us->srb, max(scsi_get_resid(us->srb),
+					(int) residue));
 	}
 
 	if (bcs->Status != US_BULK_STAT_OK)
@@ -558,4 +443,3 @@ void usb_stor_print_cmd(struct scsi_cmnd *srb)
 	blen = 0;
 }
 
-
diff --git a/drivers/staging/keucr/init.h b/drivers/staging/keucr/init.h
index 5223132..953a31e 100644
--- a/drivers/staging/keucr/init.h
+++ b/drivers/staging/keucr/init.h
@@ -3,779 +3,6 @@
 extern DWORD MediaChange;
 extern int Check_D_MediaFmt(struct us_data *);
 
-BYTE SD_Init1[] = {
-0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90,
-0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09,
-0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0,
-0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x0A, 0xC2,
-0x0F, 0xD2, 0x10, 0xC2, 0x17, 0xC3, 0x02, 0xE3,
-0x13, 0x7F, 0x03, 0x12, 0x2F, 0xCB, 0x7E, 0x00,
-0x7F, 0x10, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x07,
-0xE0, 0x54, 0xBA, 0xF0, 0x75, 0x16, 0x00, 0x75,
-0x17, 0x00, 0x90, 0xFE, 0x05, 0x74, 0x80, 0xF0,
-0x90, 0xFE, 0x07, 0x74, 0x80, 0xF0, 0x7F, 0x32,
-0x7E, 0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x05,
-0xE0, 0x44, 0x01, 0xF0, 0xE0, 0x44, 0x08, 0xF0,
-0x7F, 0x32, 0x7E, 0x00, 0x12, 0xE3, 0xFA, 0x90,
-0xFE, 0x05, 0xE0, 0x54, 0xF7, 0xF0, 0x7F, 0x32,
-0x7E, 0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFF, 0x81,
-0xE0, 0xC2, 0xE3, 0xF0, 0xE0, 0x54, 0xCF, 0x44,
-0x20, 0xD2, 0xE3, 0xF0, 0x90, 0xFF, 0x84, 0xE0,
-0x54, 0x1F, 0x44, 0x40, 0xF0, 0x90, 0xFE, 0x05,
-0xE0, 0xD2, 0xE0, 0xF0, 0xE0, 0x30, 0xE0, 0xF8,
-0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90,
-0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
-0xD3, 0x80, 0x01, 0xC3, 0x90, 0xFE, 0x05, 0xE0,
-0x44, 0x30, 0xF0, 0x90, 0xFE, 0x06, 0x74, 0x70,
-0xF0, 0x74, 0xFF, 0x90, 0xFE, 0x08, 0xF0, 0x74,
-0xFF, 0x90, 0xFE, 0x09, 0xF0, 0x90, 0xFE, 0x04,
-0xE0, 0x44, 0x06, 0xF0, 0xE4, 0x90, 0xFE, 0x0C,
-0xF0, 0x90, 0xFE, 0x0D, 0xF0, 0x90, 0xFE, 0x0E,
-0xF0, 0xC2, 0x12, 0xE4, 0x90, 0xEB, 0xF9, 0xF0,
-0x90, 0xEB, 0xFA, 0xF0, 0x90, 0xFF, 0x81, 0xE0,
-0x54, 0x8F, 0x44, 0x7F, 0xF0, 0x7F, 0x32, 0x7E,
-0x00, 0x12, 0xE3, 0xFA, 0x90, 0xFE, 0x05, 0xE0,
-0x54, 0xBF, 0xF0, 0x75, 0xF0, 0xFF, 0xD2, 0x17,
-0xC2, 0x13, 0xE5, 0xF0, 0x14, 0xF5, 0xF0, 0x70,
-0x03, 0x02, 0xE2, 0xFC, 0x90, 0xFF, 0x83, 0xE0,
-0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x03, 0x02,
-0xE2, 0xFC, 0xE4, 0xFE, 0x74, 0xFF, 0xFF, 0x78,
-0x00, 0x79, 0x08, 0x12, 0xE3, 0x22, 0x20, 0x13,
-0x24, 0x30, 0x17, 0x21, 0x90, 0xFF, 0x83, 0xE0,
-0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x03, 0x02,
-0xE2, 0xFC, 0x78, 0x08, 0x79, 0x28, 0x7D, 0xAA,
-0x7C, 0x01, 0x7B, 0x00, 0x7A, 0x00, 0x12, 0xE3,
-0x22, 0x50, 0x02, 0x21, 0xED, 0x90, 0xFF, 0x83,
-0xE0, 0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x03,
-0x02, 0xE2, 0xFC, 0x30, 0x13, 0x02, 0x80, 0x17,
-0x78, 0x37, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00,
-0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50,
-0x02, 0x80, 0x7A, 0x78, 0x69, 0x80, 0x02, 0x78,
-0x01, 0x79, 0x2A, 0x7A, 0x80, 0x30, 0x17, 0x02,
-0x7A, 0x40, 0x7B, 0x70, 0x7C, 0x00, 0x7D, 0x00,
-0x12, 0xE3, 0x22, 0x50, 0x16, 0x90, 0xFE, 0x04,
-0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30,
-0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01,
-0xC3, 0x80, 0x4A, 0x90, 0xFE, 0x20, 0xE0, 0x54,
-0x00, 0xB4, 0x00, 0x23, 0x90, 0xFE, 0x21, 0xE0,
-0x54, 0x00, 0xB4, 0x00, 0x1A, 0x90, 0xFE, 0x22,
-0xE0, 0x54, 0x70, 0xB4, 0x70, 0x11, 0x90, 0xFE,
-0x23, 0xE0, 0x30, 0xE7, 0x0A, 0x30, 0x17, 0x05,
-0x20, 0xE6, 0x02, 0xC2, 0x17, 0x41, 0x02, 0xC3,
-0xEF, 0x94, 0x01, 0xFF, 0xEE, 0x94, 0x00, 0xFE,
-0xC0, 0x06, 0xC0, 0x07, 0x7F, 0x64, 0x7E, 0x00,
-0x12, 0xE3, 0xFA, 0xD0, 0x07, 0xD0, 0x06, 0xEE,
-0x4F, 0x60, 0x02, 0x21, 0x4D, 0x7F, 0x64, 0x7E,
-0x00, 0x12, 0xE3, 0xFA, 0xB2, 0x17, 0x30, 0x17,
-0x07, 0xB2, 0x13, 0x20, 0x13, 0x02, 0x01, 0xFE,
-0x21, 0x0C, 0x78, 0x02, 0x79, 0x2D, 0x12, 0xE3,
-0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x7B, 0x0F,
-0x7C, 0xFE, 0x7D, 0x20, 0x7E, 0xEA, 0x7F, 0x1A,
-0x12, 0xE3, 0xD3, 0x78, 0x03, 0x20, 0x13, 0x02,
-0x78, 0x03, 0x79, 0x28, 0x90, 0xEB, 0xFA, 0xE0,
-0xFA, 0x90, 0xEB, 0xF9, 0xE0, 0xFB, 0x7C, 0x00,
-0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02,
-0xE2, 0xFC, 0x90, 0xFE, 0x22, 0xE0, 0x90, 0xEB,
-0xF9, 0xF0, 0x90, 0xFE, 0x23, 0xE0, 0x90, 0xEB,
-0xFA, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xC2, 0xE3,
-0xF0, 0x30, 0x13, 0x11, 0x90, 0xFF, 0x85, 0xE0,
-0x54, 0xCF, 0x44, 0x20, 0xF0, 0x90, 0xFF, 0x81,
-0x74, 0x94, 0xF0, 0x80, 0x0F, 0x90, 0xFF, 0x85,
-0xE0, 0x54, 0xCF, 0x44, 0x30, 0xF0, 0x90, 0xFF,
-0x81, 0x74, 0x94, 0xF0, 0x90, 0xFF, 0x81, 0xE0,
-0xD2, 0xE3, 0xF0, 0x7F, 0x32, 0x7E, 0x00, 0x12,
-0xE3, 0xFA, 0x78, 0x09, 0x79, 0x4D, 0x90, 0xEB,
-0xFA, 0xE0, 0xFA, 0x90, 0xEB, 0xF9, 0xE0, 0xFB,
-0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE3, 0x22, 0x50,
-0x03, 0x02, 0xE2, 0xFC, 0x12, 0xE3, 0x91, 0x78,
-0x87, 0x79, 0x50, 0x90, 0xEB, 0xFA, 0xE0, 0xFA,
-0x90, 0xEB, 0xF9, 0xE0, 0xFB, 0x7C, 0x00, 0x7D,
-0x00, 0x12, 0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2,
-0xFC, 0x30, 0x13, 0x09, 0x90, 0xFE, 0x05, 0xE0,
-0x54, 0xBF, 0xF0, 0x80, 0x35, 0x78, 0x37, 0x79,
-0x50, 0x90, 0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB,
-0xF9, 0xE0, 0xFB, 0x7C, 0x00, 0x7D, 0x00, 0x12,
-0xE3, 0x22, 0x50, 0x03, 0x02, 0xE2, 0xFC, 0x78,
-0x46, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C,
-0x00, 0x7D, 0x02, 0x12, 0xE3, 0x22, 0x50, 0x03,
-0x02, 0xE2, 0xFC, 0x90, 0xFE, 0x05, 0xE0, 0x44,
-0x40, 0xF0, 0xD3, 0x22, 0x30, 0x14, 0x14, 0x90,
-0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE,
-0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3,
-0x80, 0x01, 0xC3, 0x90, 0xFE, 0xD8, 0x74, 0x01,
-0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0,
-0xC3, 0x22, 0xE8, 0x90, 0xFE, 0x15, 0xF0, 0xE9,
-0x90, 0xFE, 0x14, 0xF0, 0xED, 0x90, 0xFE, 0x18,
-0xF0, 0xEC, 0x90, 0xFE, 0x19, 0xF0, 0xEB, 0x90,
-0xFE, 0x1A, 0xF0, 0xEA, 0x90, 0xFE, 0x1B, 0xF0,
-0x74, 0xFF, 0x90, 0xFE, 0x10, 0xF0, 0x90, 0xFE,
-0x11, 0xF0, 0x90, 0xFE, 0x12, 0xF0, 0xE8, 0x54,
-0x80, 0xFE, 0x90, 0xFE, 0x04, 0x74, 0x01, 0xF0,
-0x30, 0x14, 0x08, 0x90, 0xFE, 0x10, 0xE0, 0x54,
-0x05, 0x60, 0x02, 0xD3, 0x22, 0x90, 0xFE, 0x11,
-0xE0, 0x30, 0xE0, 0xEC, 0xBE, 0x80, 0x03, 0x30,
-0xE1, 0xE6, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05,
-0x70, 0xE9, 0xC3, 0x22, 0x30, 0x13, 0x02, 0xC3,
-0x22, 0x90, 0xFE, 0x22, 0xE0, 0x70, 0x06, 0x90,
-0xFE, 0x23, 0xE0, 0x60, 0x02, 0xD3, 0x22, 0xC3,
-0x22, 0x7B, 0x0F, 0x7C, 0xFE, 0x7D, 0x20, 0x7E,
-0xEA, 0x7F, 0x29, 0x12, 0xE3, 0xD3, 0x30, 0x13,
-0x1B, 0x90, 0xFE, 0x20, 0xE0, 0x54, 0x30, 0x64,
-0x30, 0x70, 0x02, 0xD2, 0x11, 0x30, 0x13, 0x0C,
-0x90, 0xFE, 0x2E, 0xE0, 0x54, 0x3C, 0x64, 0x10,
-0x70, 0x02, 0xD2, 0x12, 0x30, 0x17, 0x03, 0x02,
-0xE3, 0xC4, 0x80, 0x03, 0x20, 0x13, 0x00, 0xC2,
-0x11, 0x90, 0xFE, 0x13, 0xE0, 0x30, 0xE2, 0x02,
-0xD2, 0x11, 0x22, 0xC0, 0x04, 0xC0, 0x05, 0x8E,
-0x83, 0x8F, 0x82, 0xEB, 0x60, 0x17, 0xC0, 0x82,
-0xC0, 0x83, 0x8C, 0x83, 0x8D, 0x82, 0xE0, 0xA3,
-0xAC, 0x83, 0xAD, 0x82, 0xD0, 0x83, 0xD0, 0x82,
-0xF0, 0xA3, 0x1B, 0x80, 0xE6, 0xD0, 0x05, 0xD0,
-0x04, 0x22, 0x75, 0x8A, 0x00, 0x75, 0x8C, 0xCE,
-0xC2, 0x8D, 0x90, 0xEA, 0x65, 0xE4, 0xF0, 0xA3,
-0xF0, 0xD2, 0x8C, 0x90, 0xEA, 0x65, 0xE0, 0xFC,
-0xA3, 0xE0, 0xFD, 0xEC, 0xC3, 0x9E, 0x40, 0xF3,
-0x70, 0x05, 0xED, 0xC3, 0x9F, 0x40, 0xEC, 0xC2,
-0x8C, 0x22, 0xF5, 0xD3, 0xE0, 0x64, 0x01, 0x70,
-0x02, 0xD2, 0x3F, 0x75, 0x17, 0x00, 0x75, 0x18,
-0x00, 0x85, 0x14, 0x19, 0x75, 0x1B, 0x01, 0x12,
-0x2F, 0x8C, 0x40, 0x03, 0x02, 0xE4, 0x45, 0x90,
-0xEA, 0x49, 0xE5, 0x14, 0xF0, 0x05, 0x14, 0x02,
-0xE2, 0xDC, 0xD2, 0x22, 0x90, 0xEA, 0x49, 0xE0,
-0x64, 0xFF, 0x70, 0x02, 0x80, 0x02, 0x80, 0x12,
-0x90, 0xFE, 0x44, 0x74, 0x02, 0xF0, 0x30, 0x25,
-0x04, 0xE0, 0x20, 0xE1, 0xF9, 0x12, 0x2F, 0x9E,
-0xC3, 0x22, 0x30, 0x3F, 0x36, 0x74, 0x88, 0x90,
-0xEA, 0x44, 0xF0, 0x75, 0x17, 0x00, 0x79, 0x00,
-0x7A, 0x00, 0x7B, 0x10, 0x7C, 0x02, 0x7D, 0x02,
-0x12, 0x2F, 0xA7, 0x7F, 0x80, 0x12, 0x2F, 0xC5,
-0x90, 0xFE, 0x45, 0xE0, 0x54, 0xFE, 0xF0, 0x90,
-0xFE, 0x45, 0xE0, 0x44, 0x04, 0xF0, 0x90, 0xFE,
-0x44, 0x74, 0x02, 0xF0, 0x30, 0x25, 0x04, 0xE0,
-0x20, 0xE1, 0xF9, 0xD3, 0x22, 0x75, 0x8A, 0x00,
-0x75, 0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA, 0x65,
-0xE4, 0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA,
-0x65, 0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xC3,
-0x9E, 0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F,
-0x40, 0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x53, 0x44, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x31,
-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
-
-BYTE SD_Init2[] = {
-0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90,
-0xFF, 0x23, 0x74, 0x80, 0xF0, 0x90, 0xFF, 0x09,
-0xE0, 0x30, 0xE5, 0xFC, 0x90, 0xFF, 0x83, 0xE0,
-0xA2, 0xE0, 0x92, 0x14, 0x20, 0x14, 0x0A, 0xC2,
-0x0F, 0xD2, 0x10, 0xC2, 0x17, 0xC3, 0x02, 0xE0,
-0xA0, 0x20, 0x13, 0x05, 0x12, 0xE3, 0x8D, 0x80,
-0x03, 0x12, 0xE1, 0x1F, 0xD2, 0x0F, 0xC2, 0x10,
-0xD3, 0x90, 0xF3, 0xFF, 0x75, 0xF0, 0xFF, 0x74,
-0x00, 0xA3, 0xF0, 0xD5, 0xF0, 0xFB, 0x7B, 0x0F,
-0x7C, 0xEA, 0x7D, 0x29, 0x7E, 0xF4, 0x7F, 0x10,
-0x12, 0xE5, 0x5D, 0x90, 0xF4, 0x00, 0xE4, 0xA2,
-0x14, 0x92, 0xE0, 0xA2, 0x0F, 0x92, 0xE1, 0xA2,
-0x10, 0x92, 0xE2, 0xA2, 0x13, 0x92, 0xE3, 0xA2,
-0x17, 0x92, 0xE4, 0xA2, 0x12, 0x92, 0xE5, 0xA2,
-0x11, 0x92, 0xE6, 0xF0, 0xF0, 0x74, 0xFF, 0xA3,
-0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0x90, 0xFF, 0x2A,
-0x74, 0x02, 0xF0, 0xA3, 0x74, 0x00, 0xF0, 0xD3,
-0x22, 0x30, 0x14, 0x14, 0x90, 0xFE, 0x04, 0xE0,
-0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14,
-0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3,
-0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0x90, 0xFE,
-0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x02, 0xE0, 0x39,
-0xE8, 0x90, 0xFE, 0x15, 0xF0, 0xE9, 0x90, 0xFE,
-0x14, 0xF0, 0xED, 0x90, 0xFE, 0x18, 0xF0, 0xEC,
-0x90, 0xFE, 0x19, 0xF0, 0xEB, 0x90, 0xFE, 0x1A,
-0xF0, 0xEA, 0x90, 0xFE, 0x1B, 0xF0, 0x74, 0xFF,
-0x90, 0xFE, 0x10, 0xF0, 0x90, 0xFE, 0x11, 0xF0,
-0x90, 0xFE, 0x12, 0xF0, 0xE8, 0x54, 0x80, 0xFE,
-0x90, 0xFE, 0x04, 0x74, 0x01, 0xF0, 0x30, 0x14,
-0x08, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05, 0x60,
-0x02, 0xD3, 0x22, 0x90, 0xFE, 0x11, 0xE0, 0x30,
-0xE0, 0xEC, 0xBE, 0x80, 0x03, 0x30, 0xE1, 0xE6,
-0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05, 0x70, 0xE9,
-0xC3, 0x22, 0x30, 0x13, 0x02, 0xC3, 0x22, 0x90,
-0xFE, 0x22, 0xE0, 0x70, 0x06, 0x90, 0xFE, 0x23,
-0xE0, 0x60, 0x02, 0xD3, 0x22, 0xC3, 0x22, 0x20,
-0x12, 0x03, 0x02, 0xE3, 0x17, 0x90, 0xFE, 0x1C,
-0x74, 0xFF, 0xF0, 0x90, 0xFE, 0x1D, 0x74, 0x01,
-0xF0, 0x74, 0x00, 0x90, 0xFE, 0x1E, 0xF0, 0x90,
-0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x54,
-0x7F, 0xF0, 0x90, 0xFE, 0x06, 0xE0, 0x54, 0xF0,
-0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0, 0xA3,
-0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC6, 0x74, 0x01,
-0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0xFE, 0xC5,
-0xE4, 0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x04, 0xF0,
-0x78, 0x10, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00,
-0x7C, 0x02, 0x7D, 0x00, 0x12, 0xE0, 0xB0, 0x50,
-0x03, 0x02, 0xE3, 0x17, 0x78, 0x08, 0x79, 0xE8,
-0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE3, 0x17,
-0x90, 0xFE, 0xC8, 0xE0, 0xF0, 0x90, 0xFE, 0xC4,
-0xE0, 0x44, 0x01, 0xF0, 0x30, 0x14, 0x10, 0x90,
-0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60, 0x11, 0x90,
-0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90,
-0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3, 0x80, 0x01,
-0xD3, 0x40, 0x03, 0x02, 0xE3, 0x17, 0x20, 0x17,
-0x02, 0x80, 0x39, 0xC3, 0x90, 0xF4, 0xD4, 0xE0,
-0x90, 0xF5, 0x00, 0xF0, 0x90, 0xEB, 0xF8, 0x94,
-0x01, 0xF0, 0x90, 0xF4, 0xD5, 0xE0, 0x90, 0xF5,
-0x01, 0xF0, 0x90, 0xEB, 0xF7, 0x94, 0x00, 0xF0,
-0x90, 0xF4, 0xD6, 0xE0, 0x90, 0xF5, 0x02, 0xF0,
-0x90, 0xEB, 0xF6, 0x94, 0x00, 0xF0, 0x90, 0xF4,
-0xD7, 0xE0, 0x90, 0xF5, 0x03, 0xF0, 0x90, 0xEB,
-0xF5, 0x94, 0x00, 0xF0, 0x90, 0xF4, 0x00, 0x43,
-0x82, 0xC4, 0xE0, 0x54, 0x03, 0xF5, 0x09, 0x90,
-0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x90, 0xFE,
-0x06, 0xE0, 0x54, 0x3F, 0x44, 0x00, 0xF0, 0x90,
-0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE,
-0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3,
-0x80, 0x01, 0xC3, 0x74, 0x03, 0x90, 0xFE, 0x1C,
-0xF0, 0x74, 0x00, 0x90, 0xFE, 0x1D, 0xF0, 0x90,
-0xFE, 0x1E, 0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x78,
-0x10, 0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C,
-0x00, 0x7D, 0x04, 0x12, 0xE0, 0xB0, 0x50, 0x03,
-0x02, 0xE3, 0x17, 0x90, 0xFE, 0x07, 0xE0, 0xC2,
-0xE6, 0xF0, 0x90, 0xFE, 0x07, 0xE0, 0xD2, 0xE0,
-0xF0, 0x90, 0xFE, 0x05, 0xE0, 0xD2, 0xE7, 0xF0,
-0x7B, 0x55, 0x7C, 0xAA, 0x7D, 0xAA, 0x7E, 0x55,
-0x12, 0xE3, 0x35, 0x50, 0x05, 0x75, 0x08, 0x02,
-0x41, 0xB0, 0x90, 0xFE, 0x07, 0xE0, 0x54, 0xBE,
-0xF0, 0x90, 0xFE, 0x05, 0xE0, 0x44, 0x40, 0xF0,
-0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90,
-0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
-0xD3, 0x80, 0x01, 0xC3, 0x7B, 0x5A, 0x7C, 0x5A,
-0x7D, 0xA5, 0x7E, 0x00, 0x12, 0xE3, 0x35, 0x50,
-0x05, 0x75, 0x08, 0x01, 0x41, 0xB0, 0x90, 0xFE,
-0x05, 0xE0, 0x54, 0xBF, 0xF0, 0x02, 0xE3, 0x17,
-0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90,
-0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
-0xD3, 0x80, 0x01, 0xC3, 0xE5, 0x08, 0x78, 0x86,
-0x79, 0x50, 0x7A, 0x03, 0x7B, 0xB7, 0xFC, 0x7D,
-0x00, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE3,
-0x17, 0x78, 0x86, 0x79, 0x50, 0x7A, 0x03, 0x7B,
-0xB9, 0x7C, 0x01, 0x7D, 0x00, 0x12, 0xE0, 0xB0,
-0x40, 0xBC, 0xE5, 0x09, 0x20, 0xE1, 0x04, 0x74,
-0x94, 0x80, 0x02, 0x74, 0x84, 0x90, 0xFF, 0x81,
-0xF0, 0x90, 0xFE, 0x07, 0xE0, 0xD2, 0xE6, 0xF0,
-0x90, 0xFF, 0x85, 0xE0, 0x54, 0xCF, 0x44, 0x30,
-0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xD2, 0xE3, 0xF0,
-0x7F, 0x32, 0x7E, 0x00, 0x12, 0xE5, 0x84, 0x90,
-0xFE, 0x06, 0xE0, 0x54, 0x3F, 0x44, 0x40, 0xF0,
-0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90,
-0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA,
-0xD3, 0x80, 0x01, 0xC3, 0x22, 0xC0, 0x05, 0xC0,
-0x06, 0x78, 0x13, 0x79, 0x68, 0x12, 0xE0, 0xB0,
-0x50, 0x03, 0x02, 0xE3, 0x8B, 0xEB, 0x90, 0xFE,
-0x00, 0xF0, 0xEC, 0xF0, 0x90, 0xFE, 0x12, 0xE0,
-0x30, 0xE1, 0xF9, 0x90, 0xFE, 0x04, 0xE0, 0x44,
-0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06,
-0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x78,
-0x0E, 0x79, 0xE8, 0x12, 0xE0, 0xB0, 0x50, 0x03,
-0x02, 0xE3, 0x8B, 0x90, 0xFE, 0x12, 0xE0, 0x20,
-0xE1, 0xF9, 0xD0, 0x06, 0xD0, 0x05, 0x90, 0xFE,
-0x00, 0xE0, 0x6D, 0x70, 0x06, 0xE0, 0x6E, 0x70,
-0x02, 0xD3, 0x22, 0xC3, 0x22, 0x90, 0xFE, 0x06,
-0xE0, 0x54, 0x3F, 0x44, 0x00, 0xF0, 0x90, 0xFE,
-0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04,
-0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80,
-0x01, 0xC3, 0x74, 0x07, 0x90, 0xFE, 0x1C, 0xF0,
-0x74, 0x00, 0x90, 0xFE, 0x1D, 0xF0, 0x90, 0xFE,
-0x1E, 0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x78, 0x10,
-0x79, 0x50, 0x7A, 0x00, 0x7B, 0x00, 0x30, 0x17,
-0x06, 0x7C, 0x02, 0x7D, 0x00, 0x80, 0x04, 0x7C,
-0x00, 0x7D, 0x08, 0x12, 0xE0, 0xB0, 0x50, 0x03,
-0x02, 0xE4, 0x39, 0x78, 0x37, 0x79, 0x50, 0x90,
-0xEB, 0xFA, 0xE0, 0xFA, 0x90, 0xEB, 0xF9, 0xE0,
-0xFB, 0x7C, 0x00, 0x7D, 0x00, 0x12, 0xE0, 0xB0,
-0x50, 0x03, 0x02, 0xE4, 0x39, 0x78, 0x73, 0x79,
-0xE8, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D,
-0x00, 0x12, 0xE0, 0xB0, 0x50, 0x03, 0x02, 0xE4,
-0x39, 0x90, 0xFE, 0x12, 0xE0, 0x20, 0xE1, 0xF9,
-0x78, 0x08, 0x90, 0xEA, 0x3F, 0xC0, 0x83, 0xC0,
-0x82, 0x90, 0xFE, 0x00, 0xE0, 0xD0, 0x82, 0xD0,
-0x83, 0xF0, 0xC3, 0xE5, 0x82, 0x24, 0xFF, 0xF5,
-0x82, 0xE5, 0x83, 0x34, 0xFF, 0xF5, 0x83, 0xD8,
-0xE4, 0x90, 0xEA, 0x3F, 0xE0, 0x54, 0x0F, 0x70,
-0x25, 0x90, 0xFE, 0x07, 0xE0, 0xC2, 0xE6, 0xF0,
-0x90, 0xFE, 0x06, 0xE0, 0x54, 0x3F, 0x44, 0x40,
-0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0,
-0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70,
-0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x22, 0x90, 0xFE,
-0x06, 0xE0, 0x54, 0x3F, 0x44, 0x40, 0xF0, 0x90,
-0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE,
-0x04, 0x30, 0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3,
-0x80, 0x01, 0xC3, 0x7E, 0x00, 0x12, 0xE4, 0xBF,
-0x40, 0x03, 0x02, 0xE4, 0xBE, 0x7E, 0x80, 0x12,
-0xE4, 0xBF, 0x40, 0x03, 0x02, 0xE4, 0xBE, 0x90,
-0xFF, 0x81, 0xE0, 0xC2, 0xE3, 0xF0, 0x90, 0xFF,
-0x81, 0x74, 0x84, 0xF0, 0x90, 0xFE, 0x07, 0xE0,
-0xD2, 0xE6, 0xF0, 0x90, 0xFF, 0x81, 0xE0, 0xD2,
-0xE3, 0xF0, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06,
-0xF0, 0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0,
-0x70, 0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x22, 0x90,
-0xFE, 0x1C, 0x74, 0x3F, 0xF0, 0x90, 0xFE, 0x1D,
-0x74, 0x00, 0xF0, 0x74, 0x00, 0x90, 0xFE, 0x1E,
-0xF0, 0x90, 0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0xCC,
-0xE0, 0x54, 0x7F, 0xF0, 0x90, 0xFE, 0x06, 0xE0,
-0x54, 0xF0, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF4,
-0xF0, 0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC6,
-0x74, 0x00, 0xF0, 0xA3, 0x74, 0x3F, 0xF0, 0x90,
-0xFE, 0xC5, 0xE4, 0xF0, 0x90, 0xFE, 0xC4, 0x74,
-0x04, 0xF0, 0x78, 0x06, 0x79, 0xE8, 0xAA, 0x06,
-0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0x01, 0x12, 0xE0,
-0xB0, 0x50, 0x03, 0x02, 0xE5, 0x5B, 0x90, 0xFE,
-0xC8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xC4, 0xE0,
-0x44, 0x01, 0xF0, 0x30, 0x14, 0x10, 0x90, 0xFE,
-0xC8, 0xE0, 0x64, 0x01, 0x60, 0x11, 0x90, 0xFE,
-0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90, 0xFE,
-0xD8, 0x74, 0x01, 0xF0, 0xC3, 0x80, 0x01, 0xD3,
-0x40, 0x03, 0x02, 0xE5, 0x5B, 0x90, 0xFE, 0xCC,
-0xE0, 0x44, 0x80, 0xF0, 0x90, 0xF4, 0x0D, 0xE0,
-0x90, 0xF4, 0x10, 0xE0, 0x64, 0x0F, 0x60, 0x03,
-0xD3, 0x80, 0x01, 0xC3, 0x22, 0xC0, 0x04, 0xC0,
-0x05, 0x8E, 0x83, 0x8F, 0x82, 0xEB, 0x60, 0x17,
-0xC0, 0x82, 0xC0, 0x83, 0x8C, 0x83, 0x8D, 0x82,
-0xE0, 0xA3, 0xAC, 0x83, 0xAD, 0x82, 0xD0, 0x83,
-0xD0, 0x82, 0xF0, 0xA3, 0x1B, 0x80, 0xE6, 0xD0,
-0x05, 0xD0, 0x04, 0x22, 0x75, 0x8A, 0x00, 0x75,
-0x8C, 0xCE, 0xC2, 0x8D, 0x90, 0xEA, 0x65, 0xE4,
-0xF0, 0xA3, 0xF0, 0xD2, 0x8C, 0x90, 0xEA, 0x65,
-0xE0, 0xFC, 0xA3, 0xE0, 0xFD, 0xEC, 0xC3, 0x9E,
-0x40, 0xF3, 0x70, 0x05, 0xED, 0xC3, 0x9F, 0x40,
-0xEC, 0xC2, 0x8C, 0x22, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x53, 0x44, 0x2D, 0x49, 0x6E, 0x69, 0x74, 0x32,
-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
-
-BYTE SD_Rdwr[] = {
-0x90, 0xF0, 0x11, 0xE0, 0x90, 0xEB, 0x2A, 0xF0,
-0x90, 0xF0, 0x12, 0xE0, 0x90, 0xEB, 0x2B, 0xF0,
-0x90, 0xF0, 0x13, 0xE0, 0x90, 0xEB, 0x2C, 0xF0,
-0x90, 0xF0, 0x14, 0xE0, 0x90, 0xEB, 0x2D, 0xF0,
-0x90, 0xFF, 0x83, 0xE0, 0xA2, 0xE0, 0x92, 0x14,
-0x30, 0x14, 0x3E, 0x30, 0x0F, 0x3B, 0x90, 0xEB,
-0x2A, 0xE0, 0xF5, 0x10, 0xA3, 0xE0, 0xF5, 0x11,
-0xA3, 0xE0, 0xF5, 0x12, 0xA3, 0xE0, 0xF5, 0x13,
-0xC3, 0xE5, 0x3D, 0x13, 0xF5, 0x14, 0xE5, 0x3E,
-0x13, 0xF5, 0x15, 0x85, 0x14, 0x16, 0x85, 0x15,
-0x17, 0x90, 0xF0, 0x0C, 0xE0, 0x54, 0x80, 0x70,
-0x12, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06,
-0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0, 0x02, 0xE2,
-0x31, 0xC3, 0x22, 0x90, 0xFF, 0x09, 0xE0, 0x30,
-0xE1, 0x06, 0x90, 0xFF, 0x23, 0x74, 0x80, 0xF0,
-0xE5, 0x15, 0x24, 0xFF, 0x90, 0xFE, 0x1E, 0xF0,
-0xE5, 0x14, 0x34, 0xFF, 0x90, 0xFE, 0x1F, 0xF0,
-0x90, 0xFE, 0x1C, 0x74, 0xFF, 0xF0, 0x90, 0xFE,
-0x1D, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0,
-0x54, 0x7F, 0xF0, 0x90, 0xFE, 0x06, 0xE0, 0x54,
-0xF0, 0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF4, 0xF0,
-0xA3, 0x74, 0x00, 0xF0, 0x90, 0xFE, 0xC6, 0x74,
-0x01, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0xFE,
-0xC5, 0xE4, 0xF0, 0x90, 0xFE, 0xC4, 0x74, 0x04,
-0xF0, 0x78, 0x10, 0x79, 0x50, 0x7A, 0x00, 0x7B,
-0x00, 0x7C, 0x02, 0x7D, 0x00, 0x12, 0xE3, 0xEA,
-0x50, 0x03, 0x02, 0xE1, 0xFA, 0x12, 0xE4, 0x44,
-0x50, 0x03, 0x02, 0xE1, 0xFA, 0xAD, 0x13, 0xAC,
-0x12, 0xAB, 0x11, 0xAA, 0x10, 0x80, 0x00, 0xE5,
-0x15, 0x64, 0x01, 0x45, 0x14, 0x70, 0x0E, 0x78,
-0x11, 0x79, 0xE8, 0x12, 0xE3, 0xEA, 0x50, 0x03,
-0x02, 0xE1, 0xFA, 0x80, 0x0C, 0x78, 0x12, 0x79,
-0xE8, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE1,
-0xFA, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE1,
-0xFA, 0x30, 0x14, 0x07, 0x90, 0xFE, 0x12, 0xE0,
-0x30, 0xE4, 0xF6, 0x20, 0x14, 0x03, 0x02, 0xE1,
-0xFA, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5, 0xFC,
-0x90, 0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90, 0xFE,
-0xC4, 0xE0, 0x44, 0x01, 0xF0, 0xC3, 0xE5, 0x17,
-0x94, 0x01, 0xF5, 0x17, 0xE5, 0x16, 0x94, 0x00,
-0xF5, 0x16, 0x45, 0x17, 0x60, 0x42, 0x30, 0x14,
-0x10, 0x90, 0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60,
-0x11, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60,
-0xED, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3,
-0x80, 0x01, 0xD3, 0x40, 0x03, 0x02, 0xE1, 0xFA,
-0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0, 0xA3, 0x74,
-0x00, 0xF0, 0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE5,
-0xFC, 0x90, 0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90,
-0xFE, 0xC4, 0xE0, 0x44, 0x01, 0xF0, 0x80, 0xAD,
-0x30, 0x14, 0x10, 0x90, 0xFE, 0xC8, 0xE0, 0x64,
-0x01, 0x60, 0x11, 0x90, 0xFE, 0x10, 0xE0, 0x54,
-0x0A, 0x60, 0xED, 0x90, 0xFE, 0xD8, 0x74, 0x01,
-0xF0, 0xC3, 0x80, 0x01, 0xD3, 0x40, 0x03, 0x02,
-0xE1, 0xFA, 0x90, 0xFF, 0x2A, 0x74, 0x02, 0xF0,
-0xA3, 0x74, 0x00, 0xF0, 0xE5, 0x15, 0x64, 0x01,
-0x45, 0x14, 0x60, 0x29, 0x90, 0xFF, 0x09, 0xE0,
-0x30, 0xE5, 0xFC, 0x78, 0x8C, 0x79, 0x50, 0x12,
-0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE1, 0xFA, 0x12,
-0xE4, 0x44, 0x50, 0x11, 0x90, 0xFE, 0x22, 0xE0,
-0x70, 0x20, 0x90, 0xFE, 0x23, 0xE0, 0x64, 0x80,
-0x60, 0x03, 0x02, 0xE1, 0xFA, 0x90, 0xFE, 0xCC,
-0xE0, 0x44, 0x80, 0xF0, 0x75, 0x3C, 0x00, 0x75,
-0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00,
-0xD3, 0x22, 0x30, 0x14, 0x14, 0x90, 0xFE, 0x04,
-0xE0, 0x44, 0x06, 0xF0, 0x90, 0xFE, 0x04, 0x30,
-0x14, 0x06, 0xE0, 0x70, 0xFA, 0xD3, 0x80, 0x01,
-0xC3, 0x90, 0xFE, 0xD8, 0x74, 0x01, 0xF0, 0x90,
-0xFE, 0xCC, 0xE0, 0x44, 0x80, 0xF0, 0x75, 0x3F,
-0x00, 0xC3, 0xE5, 0x17, 0x33, 0xF5, 0x3E, 0xE5,
-0x16, 0x33, 0xF5, 0x3D, 0x75, 0x3C, 0x00, 0xC3,
-0x22, 0xE5, 0x3E, 0x54, 0x01, 0x45, 0x3F, 0x60,
-0x03, 0x02, 0xE0, 0x69, 0xE5, 0x15, 0x24, 0xFF,
-0x90, 0xFE, 0x1E, 0xF0, 0xE5, 0x14, 0x34, 0xFF,
-0x90, 0xFE, 0x1F, 0xF0, 0x90, 0xFE, 0x1C, 0x74,
-0xFF, 0xF0, 0x90, 0xFE, 0x1D, 0x74, 0x01, 0xF0,
-0x90, 0xFE, 0x06, 0xE0, 0x54, 0xF0, 0x44, 0x0F,
-0xF0, 0x90, 0xFE, 0xC0, 0x74, 0xF0, 0xF0, 0xA3,
-0x74, 0x00, 0xF0, 0xE5, 0x4D, 0x24, 0xFF, 0xFF,
-0xE5, 0x4C, 0x34, 0xFF, 0x90, 0xFE, 0xC6, 0xF0,
-0xA3, 0xEF, 0xF0, 0xE4, 0x90, 0xFE, 0xC5, 0xF0,
-0x74, 0x06, 0x90, 0xFE, 0xC4, 0xF0, 0x90, 0xFE,
-0xCC, 0xE0, 0x54, 0x7F, 0xF0, 0x78, 0x10, 0x79,
-0x50, 0x7A, 0x00, 0x7B, 0x00, 0x7C, 0x02, 0x7D,
-0x00, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE3,
-0x9E, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE3,
-0x9E, 0xAD, 0x13, 0xAC, 0x12, 0xAB, 0x11, 0xAA,
-0x10, 0x80, 0x10, 0x74, 0x00, 0xFD, 0xC3, 0xE5,
-0x13, 0x33, 0xFC, 0xE5, 0x12, 0x33, 0xFB, 0xE5,
-0x11, 0x33, 0xFA, 0xE5, 0x15, 0x64, 0x01, 0x45,
-0x14, 0x70, 0x0E, 0x78, 0x18, 0x79, 0x68, 0x12,
-0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE3, 0x9E, 0x80,
-0x0C, 0x78, 0x19, 0x79, 0x68, 0x12, 0xE3, 0xEA,
-0x50, 0x03, 0x02, 0xE3, 0x9E, 0x12, 0xE4, 0x44,
-0x50, 0x03, 0x02, 0xE3, 0x9E, 0x75, 0x1F, 0x01,
-0x20, 0x2D, 0x03, 0x75, 0x1F, 0x08, 0xE5, 0x16,
-0x45, 0x17, 0x70, 0x03, 0x02, 0xE3, 0x6B, 0x85,
-0x1F, 0x1E, 0x30, 0x14, 0x3C, 0x90, 0xFF, 0x09,
-0x30, 0x14, 0x04, 0xE0, 0x30, 0xE1, 0xF9, 0x90,
-0xFE, 0xC8, 0x74, 0x01, 0xF0, 0x90, 0xFE, 0xC4,
-0xE0, 0x44, 0x01, 0xF0, 0x30, 0x14, 0x10, 0x90,
-0xFE, 0xC8, 0xE0, 0x64, 0x01, 0x60, 0x11, 0x90,
-0xFE, 0x10, 0xE0, 0x54, 0x0A, 0x60, 0xED, 0x90,
-0xFE, 0xD8, 0x74, 0x01, 0xF0, 0xC3, 0x80, 0x01,
-0xD3, 0x40, 0x03, 0x02, 0xE3, 0x9E, 0x90, 0xFE,
-0x12, 0x30, 0x14, 0x2A, 0xE0, 0x30, 0xE1, 0xF9,
-0x90, 0xFF, 0x09, 0xE0, 0x30, 0xE1, 0x06, 0x90,
-0xFF, 0x23, 0x74, 0x80, 0xF0, 0x15, 0x1E, 0xE5,
-0x1E, 0x70, 0xA7, 0xC3, 0xE5, 0x17, 0x94, 0x01,
-0xF5, 0x17, 0xE5, 0x16, 0x94, 0x00, 0xF5, 0x16,
-0x02, 0xE2, 0xF6, 0x90, 0xFE, 0x12, 0x30, 0x14,
-0x2D, 0xE0, 0x20, 0xE4, 0xF9, 0xE5, 0x15, 0x64,
-0x01, 0x45, 0x14, 0x60, 0x58, 0x78, 0x8C, 0x79,
-0x50, 0x12, 0xE3, 0xEA, 0x50, 0x03, 0x02, 0xE3,
-0x9E, 0x12, 0xE4, 0x44, 0x50, 0x03, 0x02, 0xE3,
-0x9E, 0x30, 0x14, 0x41, 0x90, 0xFE, 0x12, 0xE0,
-0x20, 0xE4, 0xF6, 0x02, 0xE3, 0xD5, 0x30, 0x14,
-0x14, 0x90, 0xFE, 0x04, 0xE0, 0x44, 0x06, 0xF0,
-0x90, 0xFE, 0x04, 0x30, 0x14, 0x06, 0xE0, 0x70,
-0xFA, 0xD3, 0x80, 0x01, 0xC3, 0x90, 0xFE, 0xD8,
-0x74, 0x01, 0xF0, 0x90, 0xFE, 0xCC, 0xE0, 0x44,
-0x80, 0xF0, 0x75, 0x3F, 0x00, 0xC3, 0xE5, 0x17,
-0x33, 0xF5, 0x3E, 0xE5, 0x16, 0x33, 0xF5, 0x3D,
-0x75, 0x3C, 0x00, 0xC3, 0x22, 0x90, 0xFE, 0xCC,
-0xE0, 0x44, 0x80, 0xF0, 0x75, 0x3C, 0x00, 0x75,
-0x3D, 0x00, 0x75, 0x3E, 0x00, 0x75, 0x3F, 0x00,
-0xD3, 0x22, 0xE8, 0x90, 0xFE, 0x15, 0xF0, 0xE9,
-0x90, 0xFE, 0x14, 0xF0, 0xED, 0x90, 0xFE, 0x18,
-0xF0, 0xEC, 0x90, 0xFE, 0x19, 0xF0, 0xEB, 0x90,
-0xFE, 0x1A, 0xF0, 0xEA, 0x90, 0xFE, 0x1B, 0xF0,
-0x74, 0xFF, 0x90, 0xFE, 0x10, 0xF0, 0x90, 0xFE,
-0x11, 0xF0, 0x90, 0xFE, 0x12, 0xF0, 0xE8, 0x54,
-0x80, 0xFE, 0x90, 0xFE, 0x04, 0x74, 0x01, 0xF0,
-0x30, 0x14, 0x08, 0x90, 0xFE, 0x10, 0xE0, 0x54,
-0x05, 0x60, 0x02, 0xD3, 0x22, 0x90, 0xFE, 0x11,
-0xE0, 0x30, 0xE0, 0xEC, 0xBE, 0x80, 0x03, 0x30,
-0xE1, 0xE6, 0x90, 0xFE, 0x10, 0xE0, 0x54, 0x05,
-0x70, 0xE9, 0xC3, 0x22, 0x30, 0x13, 0x02, 0xC3,
-0x22, 0x90, 0xFE, 0x22, 0xE0, 0x70, 0x06, 0x90,
-0xFE, 0x23, 0xE0, 0x60, 0x02, 0xD3, 0x22, 0xC3,
-0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x53, 0x44, 0x2D, 0x52, 0x57, 0x20, 0x20, 0x20,
-0x20, 0x20, 0x20, 0x31, 0x30, 0x30, 0x30, 0x31 };
 
 BYTE MS_Init[] = {
 0x90, 0xF0, 0x15, 0xE0, 0xF5, 0x1C, 0x11, 0x2C,
diff --git a/drivers/staging/keucr/ms.c b/drivers/staging/keucr/ms.c
index 452ea8f..a713721 100644
--- a/drivers/staging/keucr/ms.c
+++ b/drivers/staging/keucr/ms.c
@@ -1,4 +1,6 @@
 #include <linux/slab.h>
+#include <asm/byteorder.h>
+
 #include "usb.h"
 #include "scsiglue.h"
 #include "transport.h"
@@ -166,8 +168,8 @@ int MS_CardInit(struct us_data *us)
 			continue;
 
 		if (((extdat.mngflg & MS_REG_MNG_SYSFLG) == MS_REG_MNG_SYSFLG_USER) ||
-			(BigEndianWORD(((MemStickBootBlockPage0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
-			(BigEndianWORD(((MemStickBootBlockPage0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
+			(be16_to_cpu(((MemStickBootBlockPage0 *)PageBuffer0)->header.wBlockID) != MS_BOOT_BLOCK_ID) ||
+			(be16_to_cpu(((MemStickBootBlockPage0 *)PageBuffer0)->header.wFormatVersion) != MS_BOOT_BLOCK_FORMAT_VERSION) ||
 			(((MemStickBootBlockPage0 *)PageBuffer0)->header.bNumberOfDataEntry != MS_BOOT_BLOCK_DATA_ENTRIES))
 				continue;
 
@@ -242,8 +244,8 @@ int MS_CardInit(struct us_data *us)
 	result = MS_STATUS_SUCCESS;
 
 exit:
-	if (PageBuffer1)		kfree(PageBuffer1);
-    	if (PageBuffer0)		kfree(PageBuffer0);
+	kfree(PageBuffer1);
+    	kfree(PageBuffer0);
 
 	printk("MS_CardInit end\n");
 	return result;
@@ -266,7 +268,7 @@ int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
 	MS_ReaderReadPage(us, PhyBlock, 1, (DWORD *)PageBuf, &extdat);
 	do
 	{
-		blk = BigEndianWORD(PageBuf[index]);
+		blk = be16_to_cpu(PageBuf[index]);
 		if (blk == MS_LB_NOT_USED)
 			break;
 		if (blk == us->MS_Lib.Log2PhyMap[0])
@@ -278,7 +280,7 @@ int MS_LibCheckDisableBlock(struct us_data *us, WORD PhyBlock)
 	} while(1);
 
 exit:
-	if (PageBuf)	kfree(PageBuf);
+	kfree(PageBuf);
 	return result;
 }
 
@@ -322,17 +324,11 @@ void MS_LibFreeWriteBuf(struct us_data *us)
 //----- MS_LibFreeLogicalMap() ---------------------------------------
 int MS_LibFreeLogicalMap(struct us_data *us)
 {
-	if (us->MS_Lib.Phy2LogMap)
-	{
-		kfree(us->MS_Lib.Phy2LogMap);
-		us->MS_Lib.Phy2LogMap = NULL;
-	}
+	kfree(us->MS_Lib.Phy2LogMap);
+	us->MS_Lib.Phy2LogMap = NULL;
 
-	if (us->MS_Lib.Log2PhyMap)
-	{
-		kfree(us->MS_Lib.Log2PhyMap);
-		us->MS_Lib.Log2PhyMap = NULL;
-	}
+	kfree(us->MS_Lib.Log2PhyMap);
+	us->MS_Lib.Log2PhyMap = NULL;
 
     return 0;
 }
@@ -355,7 +351,7 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
 	SysInfo= &(((MemStickBootBlockPage0 *)PageData)->sysinf);
 
 	if ((SysInfo->bMsClass != MS_SYSINF_MSCLASS_TYPE_1)                                   ||
-		(BigEndianWORD(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE)                       ||
+		(be16_to_cpu(SysInfo->wPageSize) != MS_SYSINF_PAGE_SIZE)                       ||
 		((SysInfo->bSecuritySupport & MS_SYSINF_SECURITY) == MS_SYSINF_SECURITY_SUPPORT) ||
 		(SysInfo->bReserved1 != MS_SYSINF_RESERVED1)                                     ||
 		(SysInfo->bReserved2 != MS_SYSINF_RESERVED2)                                     ||
@@ -376,12 +372,12 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
 			goto exit;
 	}
 
-	us->MS_Lib.blockSize        = BigEndianWORD(SysInfo->wBlockSize);
-	us->MS_Lib.NumberOfPhyBlock = BigEndianWORD(SysInfo->wBlockNumber);
-	us->MS_Lib.NumberOfLogBlock = BigEndianWORD(SysInfo->wTotalBlockNumber)- 2;
+	us->MS_Lib.blockSize        = be16_to_cpu(SysInfo->wBlockSize);
+	us->MS_Lib.NumberOfPhyBlock = be16_to_cpu(SysInfo->wBlockNumber);
+	us->MS_Lib.NumberOfLogBlock = be16_to_cpu(SysInfo->wTotalBlockNumber) - 2;
 	us->MS_Lib.PagesPerBlock    = us->MS_Lib.blockSize * SIZE_OF_KIRO / MS_BYTES_PER_PAGE;
 	us->MS_Lib.NumberOfSegment  = us->MS_Lib.NumberOfPhyBlock / MS_PHYSICAL_BLOCKS_PER_SEGMENT;
-	us->MS_Model                = BigEndianWORD(SysInfo->wMemorySize);
+	us->MS_Model                = be16_to_cpu(SysInfo->wMemorySize);
 
 	if (MS_LibAllocLogicalMap(us))			//Allocate to all number of logicalblock and physicalblock
 		goto exit;
@@ -394,10 +390,10 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
 	{
 		DWORD  EntryOffset, EntrySize;
 
-		if ((EntryOffset = BigEndianDWORD(SysEntry->entry[i].dwStart)) == 0xffffff)
+		if ((EntryOffset = be32_to_cpu(SysEntry->entry[i].dwStart)) == 0xffffff)
 			continue;
 
-		if ((EntrySize = BigEndianDWORD(SysEntry->entry[i].dwSize)) == 0)
+		if ((EntrySize = be32_to_cpu(SysEntry->entry[i].dwSize)) == 0)
 			continue;
 
 		if (EntryOffset + MS_BYTES_PER_PAGE + EntrySize > us->MS_Lib.blockSize * (DWORD)SIZE_OF_KIRO)
@@ -429,7 +425,7 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
 					PrevPageNumber = PageNumber;
 				}
 
-				if ((phyblk = BigEndianWORD(*(WORD *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))) < 0x0fff)
+				if ((phyblk = be16_to_cpu(*(WORD *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))) < 0x0fff)
 					MS_LibSetInitialErrorBlock(us, phyblk);
 
 				EntryOffset += 2;
@@ -455,10 +451,10 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
 			}
 
 			idi = &((MemStickBootBlockCIS_IDI *)(PageBuffer + (EntryOffset % MS_BYTES_PER_PAGE)))->idi.idi;
-			if (LittleEndianWORD(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
+			if (le16_to_cpu(idi->wIDIgeneralConfiguration) != MS_IDI_GENERAL_CONF)
 				goto exit;
 
-			us->MS_Lib.BytesPerSector = LittleEndianWORD(idi->wIDIbytesPerSector);
+			us->MS_Lib.BytesPerSector = le16_to_cpu(idi->wIDIbytesPerSector);
 			if (us->MS_Lib.BytesPerSector != MS_BYTES_PER_PAGE)
 				goto exit;
 		}
@@ -468,7 +464,7 @@ int MS_LibProcessBootBlock(struct us_data *us, WORD PhyBlock, BYTE *PageData)
 
 exit:
 	if (result)		MS_LibFreeLogicalMap(us);
-	if (PageBuffer)	kfree(PageBuffer);
+	kfree(PageBuffer);
 
 	result = 0;
 	return result;
diff --git a/drivers/staging/keucr/sdscsi.c b/drivers/staging/keucr/sdscsi.c
deleted file mode 100644
index d646507..0000000
--- a/drivers/staging/keucr/sdscsi.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_device.h>
-
-#include "usb.h"
-#include "scsiglue.h"
-#include "transport.h"
-
-int SD_SCSI_Test_Unit_Ready (struct us_data *us, struct scsi_cmnd *srb);
-int SD_SCSI_Inquiry         (struct us_data *us, struct scsi_cmnd *srb);
-int SD_SCSI_Mode_Sense      (struct us_data *us, struct scsi_cmnd *srb);
-int SD_SCSI_Start_Stop      (struct us_data *us, struct scsi_cmnd *srb);
-int SD_SCSI_Read_Capacity   (struct us_data *us, struct scsi_cmnd *srb);
-int SD_SCSI_Read            (struct us_data *us, struct scsi_cmnd *srb);
-int SD_SCSI_Write           (struct us_data *us, struct scsi_cmnd *srb);
-
-//----- SD_SCSIIrp() --------------------------------------------------
-int SD_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb)
-{
-	int    result;
-
-	us->SrbStatus = SS_SUCCESS;
-	switch (srb->cmnd[0])
-	{
-		case TEST_UNIT_READY :  result = SD_SCSI_Test_Unit_Ready (us, srb);  break; //0x00
-		case INQUIRY         :  result = SD_SCSI_Inquiry         (us, srb);  break; //0x12
-		case MODE_SENSE      :  result = SD_SCSI_Mode_Sense      (us, srb);  break; //0x1A
-//		case START_STOP      :  result = SD_SCSI_Start_Stop      (us, srb);  break; //0x1B
-		case READ_CAPACITY   :  result = SD_SCSI_Read_Capacity   (us, srb);  break; //0x25
-		case READ_10         :  result = SD_SCSI_Read            (us, srb);  break; //0x28
-		case WRITE_10        :  result = SD_SCSI_Write           (us, srb);  break; //0x2A
-
-		default:
-			us->SrbStatus = SS_ILLEGAL_REQUEST;
-			result = USB_STOR_TRANSPORT_FAILED;
-			break;
-	}
-	return result;
-}
-
-//----- SD_SCSI_Test_Unit_Ready() --------------------------------------------------
-int SD_SCSI_Test_Unit_Ready(struct us_data *us, struct scsi_cmnd *srb)
-{
-	//printk("SD_SCSI_Test_Unit_Ready\n");
-	if (us->SD_Status.Insert && us->SD_Status.Ready)
-		return USB_STOR_TRANSPORT_GOOD;
-	else
-	{
-		ENE_SDInit(us);
-		return USB_STOR_TRANSPORT_GOOD;
-	}
-		
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-//----- SD_SCSI_Inquiry() --------------------------------------------------
-int SD_SCSI_Inquiry(struct us_data *us, struct scsi_cmnd *srb)
-{
-	//printk("SD_SCSI_Inquiry\n");
-	BYTE data_ptr[36] = {0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55, 0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61, 0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30};
-
-	usb_stor_set_xfer_buf(us, data_ptr, 36, srb, TO_XFER_BUF);
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-
-//----- SD_SCSI_Mode_Sense() --------------------------------------------------
-int SD_SCSI_Mode_Sense(struct us_data *us, struct scsi_cmnd *srb)
-{
-	BYTE	mediaNoWP[12] = {0x0b,0x00,0x00,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
-	BYTE	mediaWP[12]   = {0x0b,0x00,0x80,0x08,0x00,0x00,0x71,0xc0,0x00,0x00,0x02,0x00};
-
-	if (us->SD_Status.WtP)
-		usb_stor_set_xfer_buf(us, mediaWP, 12, srb, TO_XFER_BUF);
-	else
-		usb_stor_set_xfer_buf(us, mediaNoWP, 12, srb, TO_XFER_BUF);
-
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-//----- SD_SCSI_Read_Capacity() --------------------------------------------------
-int SD_SCSI_Read_Capacity(struct us_data *us, struct scsi_cmnd *srb)
-{
-	unsigned int offset = 0;
-	struct scatterlist *sg = NULL;
-	DWORD   bl_num;
-	WORD    bl_len;
-	BYTE    buf[8];
-
-	printk("SD_SCSI_Read_Capacity\n");
-	if ( us->SD_Status.HiCapacity )
-	{
-		bl_len = 0x200;
-		if (us->SD_Status.IsMMC)
-			bl_num = us->HC_C_SIZE-1;
-		else
-			bl_num = (us->HC_C_SIZE + 1) * 1024 - 1;
-	}
-	else
-	{
-		bl_len = 1<<(us->SD_READ_BL_LEN);
-		bl_num = us->SD_Block_Mult*(us->SD_C_SIZE+1)*(1<<(us->SD_C_SIZE_MULT+2)) - 1;
-	}
-	us->bl_num = bl_num;
-	printk("bl_len = %x\n", bl_len);
-	printk("bl_num = %x\n", bl_num);
-
-	//srb->request_bufflen = 8;
-	buf[0] = (bl_num>>24) & 0xff;
-	buf[1] = (bl_num>>16) & 0xff;
-	buf[2] = (bl_num>> 8) & 0xff;
-	buf[3] = (bl_num>> 0) & 0xff;
-	buf[4] = (bl_len>>24) & 0xff;
-	buf[5] = (bl_len>>16) & 0xff;
-	buf[6] = (bl_len>> 8) & 0xff;
-	buf[7] = (bl_len>> 0) & 0xff;
-	
-	usb_stor_access_xfer_buf(us, buf, 8, srb, &sg, &offset, TO_XFER_BUF);
-	//usb_stor_set_xfer_buf(us, buf, srb->request_bufflen, srb, TO_XFER_BUF);
-
-	return USB_STOR_TRANSPORT_GOOD;
-}
-
-//----- SD_SCSI_Read() --------------------------------------------------
-int SD_SCSI_Read(struct us_data *us, struct scsi_cmnd *srb)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result;
-	PBYTE	Cdb = srb->cmnd;
-	DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
-                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
-	WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
-	DWORD bnByte = bn * 0x200;
-	DWORD	blenByte = blen * 0x200;
-
-	if (bn > us->bl_num)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	result = ENE_LoadBinCode(us, SD_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD)
-	{
-		printk("Load SD RW pattern Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	if ( us->SD_Status.HiCapacity )
-		bnByte = bn;
-		
-	// set up the command wrapper
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = blenByte;
-	bcb->Flags  = 0x80;
-	bcb->CDB[0] = 0xF1;
-	bcb->CDB[5] = (BYTE)(bnByte);
-	bcb->CDB[4] = (BYTE)(bnByte>>8);
-	bcb->CDB[3] = (BYTE)(bnByte>>16);
-	bcb->CDB[2] = (BYTE)(bnByte>>24);
-
-	result = ENE_SendScsiCmd(us, FDIR_READ, scsi_sglist(srb), 1);
-	return result;
-}
-
-//----- SD_SCSI_Write() --------------------------------------------------
-int SD_SCSI_Write(struct us_data *us, struct scsi_cmnd *srb)
-{
-	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
-	int result;
-	PBYTE	Cdb = srb->cmnd;
-	DWORD bn  =  ((Cdb[2]<<24) & 0xff000000) | ((Cdb[3]<<16) & 0x00ff0000) |
-                   ((Cdb[4]<< 8) & 0x0000ff00) | ((Cdb[5]<< 0) & 0x000000ff);
-	WORD  blen = ((Cdb[7]<< 8) & 0xff00)     | ((Cdb[8]<< 0) & 0x00ff);
-	DWORD bnByte = bn * 0x200;
-	DWORD	blenByte = blen * 0x200;
-
-	if (bn > us->bl_num)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	result = ENE_LoadBinCode(us, SD_RW_PATTERN);
-	if (result != USB_STOR_XFER_GOOD)
-	{
-		printk("Load SD RW pattern Fail !!\n");
-		return USB_STOR_TRANSPORT_ERROR;
-	}
-
-	if ( us->SD_Status.HiCapacity )
-		bnByte = bn;
-
-	// set up the command wrapper
-	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
-	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-	bcb->DataTransferLength = blenByte;
-	bcb->Flags  = 0x00;
-	bcb->CDB[0] = 0xF0;
-	bcb->CDB[5] = (BYTE)(bnByte);
-	bcb->CDB[4] = (BYTE)(bnByte>>8);
-	bcb->CDB[3] = (BYTE)(bnByte>>16);
-	bcb->CDB[2] = (BYTE)(bnByte>>24);
-
-	result = ENE_SendScsiCmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
-	return result;
-}
-
-
-
diff --git a/drivers/staging/keucr/smcommon.h b/drivers/staging/keucr/smcommon.h
index 1694605..00064ca 100644
--- a/drivers/staging/keucr/smcommon.h
+++ b/drivers/staging/keucr/smcommon.h
@@ -25,8 +25,6 @@ Define Difinetion
 #define ERR_NoSmartMedia    0x003A /* Medium Not Present */
 
 /***************************************************************************/
-char Bit_D_Count(BYTE);
-char Bit_D_CountWord(WORD);
 void StringCopy(char *, char *, int);
 int  StringCmp(char *, char *, int);
 
diff --git a/drivers/staging/keucr/smilecc.c b/drivers/staging/keucr/smilecc.c
index daf322a..5659dea 100644
--- a/drivers/staging/keucr/smilecc.c
+++ b/drivers/staging/keucr/smilecc.c
@@ -182,13 +182,17 @@ BYTE *buf;
 BYTE *redundant_ecc;
 BYTE *calculate_ecc;
 {
-    DWORD err;
+	DWORD err;
 
-    err=correct_data(buf,redundant_ecc,*(calculate_ecc+1),*(calculate_ecc),*(calculate_ecc+2));
-    if (err==1) StringCopy(calculate_ecc,redundant_ecc,3);
-        if (err==0 || err==1 || err==2)
-            return(0);
-    return(-1);
+	err = correct_data(buf, redundant_ecc, *(calculate_ecc + 1),
+			   *(calculate_ecc), *(calculate_ecc + 2));
+	if (err == 1)
+		memcpy(calculate_ecc, redundant_ecc, 3);
+
+	if (err == 0 || err == 1 || err == 2)
+		return 0;
+
+	return -1;
 }
 
 void _Calculate_D_SwECC(buf,ecc)
diff --git a/drivers/staging/keucr/smilsub.c b/drivers/staging/keucr/smilsub.c
index ce10cf2..80da61c 100644
--- a/drivers/staging/keucr/smilsub.c
+++ b/drivers/staging/keucr/smilsub.c
@@ -79,7 +79,7 @@ int Check_D_FailBlock(BYTE *redundant)
 		return(SUCCESS);
 	if (!*redundant)
 		return(ERROR);
-	if (Bit_D_Count(*redundant)<7)
+	if (hweight8(*redundant)<7)
 		return(ERROR);
 
 	return(SUCCESS);
@@ -100,7 +100,7 @@ int Check_D_DataStatus(BYTE *redundant)
 	else
 		ErrXDCode = NO_ERROR;
 
-	if (Bit_D_Count(*redundant)<5)
+	if (hweight8(*redundant)<5)
 		return(ERROR);
 
 	return(SUCCESS);
@@ -120,14 +120,14 @@ int Load_D_LogBlockAddr(BYTE *redundant)
 		if ((addr1 &0xF000)==0x1000)
 		{ Media.LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); }
 
-	if (Bit_D_CountWord((WORD)(addr1^addr2))!=0x01) return(ERROR);
+	if (hweight16((WORD)(addr1^addr2))!=0x01) return(ERROR);
 
 	if ((addr1 &0xF000)==0x1000)
-		if (!(Bit_D_CountWord(addr1) &0x01))
+		if (!(hweight16(addr1) &0x01))
 		{ Media.LogBlock=(addr1 &0x0FFF)/2; return(SUCCESS); }
 
 	if ((addr2 &0xF000)==0x1000)
-		if (!(Bit_D_CountWord(addr2) &0x01))
+		if (!(hweight16(addr2) &0x01))
 		{ Media.LogBlock=(addr2 &0x0FFF)/2; return(SUCCESS); }
 
 	return(ERROR);
@@ -151,7 +151,7 @@ void Set_D_LogBlockAddr(BYTE *redundant)
 	*(redundant+REDT_DATA) =0xFF;
 	addr=Media.LogBlock*2+0x1000;
 
-	if ((Bit_D_CountWord(addr)%2))
+	if ((hweight16(addr)%2))
 		addr++;
 
 	*(redundant+REDT_ADDR1H)=*(redundant+REDT_ADDR2H)=(BYTE)(addr/0x0100);
@@ -1482,54 +1482,40 @@ BYTE _Check_D_DevCode(BYTE dcode)
 //----- Check_D_ReadError() ----------------------------------------------
 int Check_D_ReadError(BYTE *redundant)
 {
-    // Driver ¤Ł°ľ ECC Check
-    return(SUCCESS);
-    if (!StringCmp((char *)(redundant+0x0D),(char *)EccBuf,3))
-        if (!StringCmp((char *)(redundant+0x08),(char *)(EccBuf+0x03),3))
-            return(SUCCESS);
-
-    return(ERROR);
+	return SUCCESS;
 }
 
 //----- Check_D_Correct() ----------------------------------------------
 int Check_D_Correct(BYTE *buf,BYTE *redundant)
 {
-    // Driver ¤Ł°ľ ECC Check
-    return(SUCCESS);
-    if (StringCmp((char *)(redundant+0x0D),(char *)EccBuf,3))
-        if (_Correct_D_SwECC(buf,redundant+0x0D,EccBuf))
-            return(ERROR);
-
-    buf+=0x100;
-    if (StringCmp((char *)(redundant+0x08),(char *)(EccBuf+0x03),3))
-        if (_Correct_D_SwECC(buf,redundant+0x08,EccBuf+0x03))
-            return(ERROR);
-
-    return(SUCCESS);
+	return SUCCESS;
 }
 
 //----- Check_D_CISdata() ----------------------------------------------
 int Check_D_CISdata(BYTE *buf, BYTE *redundant)
 {
-    BYTE cis[]={0x01,0x03,0xD9,0x01,0xFF,0x18,0x02,0xDF,0x01,0x20};
+	BYTE cis[] = {0x01, 0x03, 0xD9, 0x01, 0xFF, 0x18, 0x02,
+		      0xDF, 0x01, 0x20};
 
-    if (!IsSSFDCCompliance && !IsXDCompliance)
-        return(SUCCESS);             // ĽŘŤeŹ°ąj¨î SUCCESS [Arnold 02-08-23] SSFDC ´ú¸Ő, ¤ŁŻŕąj¨î SUCCESS
+	int cis_len = sizeof(cis);
 
-    if (!StringCmp((char *)(redundant+0x0D),(char *)EccBuf,3))
-        return(StringCmp((char *)buf,(char *)cis,10));
+	if (!IsSSFDCCompliance && !IsXDCompliance)
+		return SUCCESS;
 
-    if (!_Correct_D_SwECC(buf,redundant+0x0D,EccBuf))
-        return(StringCmp((char *)buf,(char *)cis,10));
+	if (!memcmp(redundant + 0x0D, EccBuf, 3))
+		return memcmp(buf, cis, cis_len);
 
-    buf+=0x100;
-    if (!StringCmp((char *)(redundant+0x08),(char *)(EccBuf+0x03),3))
-        return(StringCmp((char *)buf,(char *)cis,10));
+	if (!_Correct_D_SwECC(buf, redundant + 0x0D, EccBuf))
+		return memcmp(buf, cis, cis_len);
 
-    if (!_Correct_D_SwECC(buf,redundant+0x08,EccBuf+0x03))
-        return(StringCmp((char *)buf,(char *)cis,10));
+	buf += 0x100;
+	if (!memcmp(redundant + 0x08, EccBuf + 0x03, 3))
+		return memcmp(buf, cis, cis_len);
 
-    return(ERROR);
+	if (!_Correct_D_SwECC(buf, redundant + 0x08, EccBuf + 0x03))
+		return memcmp(buf, cis, cis_len);
+
+	return ERROR;
 }
 
 //----- Set_D_RightECC() ----------------------------------------------
@@ -1563,51 +1549,7 @@ void Set_D_RightECC(BYTE *redundant)
 //    StringCopy((char *)(redundant+0x08),(char *)(EccBuf+0x03),3);
 //}
 */
-//Common Subroutine
-char Bit_D_Count(BYTE cdata)
-{
-    WORD bitcount=0;
-
-    while(cdata) {
-        bitcount+=(WORD)(cdata &0x01);
-        cdata /=2;
-    }
-
-    return((char)bitcount);
-}
 
-//-----
-char Bit_D_CountWord(WORD cdata)
-{
-    WORD bitcount=0;
-
-    while(cdata) {
-        bitcount+=(cdata &0x01);
-        cdata /=2;
-    }
-
-    return((char)bitcount);
-}
-
-void StringCopy(char *stringA, char *stringB, int count)
-{
-    int i;
-
-    for(i=0; i<count; i++)
-        *stringA++ = *stringB++;
-}
-
-//-----
-int StringCmp(char *stringA, char *stringB, int count)
-{
-    int i;
-
-    for (i=0;i<count;i++)
-        if (*stringA++ != *stringB++)
-            return(ERROR);
-
-    return(SUCCESS);
-}
 /*
 //----- SM_ReadBlock() ---------------------------------------------
 int SM_ReadBlock(PFDO_DEVICE_EXTENSION fdoExt, BYTE *buf,BYTE *redundant)
diff --git a/drivers/staging/keucr/transport.c b/drivers/staging/keucr/transport.c
index 111160c..a53402f 100644
--- a/drivers/staging/keucr/transport.c
+++ b/drivers/staging/keucr/transport.c
@@ -413,7 +413,7 @@ void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 	usb_stor_print_cmd(srb);
 	/* send the command to the transport layer */
 	scsi_set_resid(srb, 0);
-	if ( !(us->SD_Status.Ready || us->MS_Status.Ready || us->SM_Status.Ready) )
+	if (!(us->MS_Status.Ready || us->SM_Status.Ready))
 		result = ENE_InitMedia(us);
 	
 	if (us->Power_IsResum == true) {
@@ -421,7 +421,6 @@ void ENE_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
 		us->Power_IsResum = false;		
 	}	
 	
-	if (us->SD_Status.Ready)	result = SD_SCSIIrp(us, srb);
 	if (us->MS_Status.Ready)	result = MS_SCSIIrp(us, srb);
 	if (us->SM_Status.Ready)	result = SM_SCSIIrp(us, srb);
 
diff --git a/drivers/staging/keucr/transport.h b/drivers/staging/keucr/transport.h
index ae9b5ee..565d98c 100644
--- a/drivers/staging/keucr/transport.h
+++ b/drivers/staging/keucr/transport.h
@@ -92,10 +92,8 @@ extern void usb_stor_set_xfer_buf(struct us_data*, unsigned char *buffer, unsign
 // ENE scsi function
 extern void ENE_stor_invoke_transport(struct scsi_cmnd *, struct us_data*);
 extern int ENE_InitMedia(struct us_data*);
-extern int ENE_SDInit(struct us_data*);
 extern int ENE_MSInit(struct us_data*);
 extern int ENE_SMInit(struct us_data*);
-extern int ENE_ReadSDReg(struct us_data*, u8*);
 extern int ENE_SendScsiCmd(struct us_data*, BYTE, void*, int);
 extern int ENE_LoadBinCode(struct us_data*, BYTE);
 extern int ENE_Read_BYTE(struct us_data*, WORD index, void *buf);
@@ -104,7 +102,6 @@ extern int ENE_Write_Data(struct us_data*, void *buf, unsigned int length);
 extern void BuildSenseBuffer(struct scsi_cmnd *, int);
 
 // ENE scsi function
-extern int SD_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
 extern int MS_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
 extern int SM_SCSIIrp(struct us_data *us, struct scsi_cmnd *srb);
 
diff --git a/drivers/staging/keucr/usb.c b/drivers/staging/keucr/usb.c
index c65b988..8c2332e 100644
--- a/drivers/staging/keucr/usb.c
+++ b/drivers/staging/keucr/usb.c
@@ -74,7 +74,6 @@ int eucr_resume(struct usb_interface *iface)
          us->Power_IsResum = true;
 	//
 	//us->SD_Status.Ready = 0; //??
-	us->SD_Status = *(PSD_STATUS)&tmp;
     	us->MS_Status = *(PMS_STATUS)&tmp;
     	us->SM_Status = *(PSM_STATUS)&tmp;
     	
@@ -98,7 +97,6 @@ int eucr_reset_resume(struct usb_interface *iface)
  	us->Power_IsResum = true;
 	//
 	//us->SD_Status.Ready = 0; //??
-	us->SD_Status = *(PSD_STATUS)&tmp;
     	us->MS_Status = *(PMS_STATUS)&tmp;
     	us->SM_Status = *(PSM_STATUS)&tmp;
 	return 0;
@@ -582,6 +580,7 @@ static int eucr_probe(struct usb_interface *intf, const struct usb_device_id *id
 	struct Scsi_Host *host;
 	struct us_data *us;
 	int result;
+	BYTE	MiscReg03 = 0;
 	struct task_struct *th;
 
       printk("usb --- eucr_probe\n");
@@ -647,6 +646,24 @@ static int eucr_probe(struct usb_interface *intf, const struct usb_device_id *id
 		goto BadDevice;
 	}
 	wake_up_process(th);
+
+	/* probe card type */
+	result = ENE_Read_BYTE(us, REG_CARD_STATUS, &MiscReg03);
+	if (result != USB_STOR_XFER_GOOD) {
+		result = USB_STOR_TRANSPORT_ERROR;
+		quiesce_and_remove_host(us);
+		goto BadDevice;
+	}
+
+	if (!(MiscReg03 & 0x02)) {
+		result = -ENODEV;
+		quiesce_and_remove_host(us);
+		printk(KERN_NOTICE "keucr: The driver only supports SM/MS card.\
+			To use SD card, \
+			please build driver/usb/storage/ums-eneub6250.ko\n");
+		goto BadDevice;
+	}
+
 	return 0;
 
 	/* We come here if there are any problems */
diff --git a/drivers/staging/line6/pcm.c b/drivers/staging/line6/pcm.c
index b9c55f9..9d4c8a6 100644
--- a/drivers/staging/line6/pcm.c
+++ b/drivers/staging/line6/pcm.c
@@ -189,8 +189,7 @@ int line6_pcm_stop(struct snd_line6_pcm *line6pcm, int channels)
 		line6pcm->buffer_out = NULL;
 	}
 #if LINE6_BACKUP_MONITOR_SIGNAL
-	if (line6pcm->prev_fbuf != NULL)
-		kfree(line6pcm->prev_fbuf);
+	kfree(line6pcm->prev_fbuf);
 #endif
 
 	return 0;
diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c
index 3a9c098..832522c 100644
--- a/drivers/staging/lirc/lirc_parallel.c
+++ b/drivers/staging/lirc/lirc_parallel.c
@@ -42,6 +42,7 @@
 
 #include <linux/poll.h>
 #include <linux/parport.h>
+#include <linux/platform_device.h>
 
 #include <media/lirc.h>
 #include <media/lirc_dev.h>
@@ -295,7 +296,7 @@ static void irq_handler(void *blah)
 	} while (lirc_get_signal());
 
 	if (signal != 0) {
-		/* ajust value to usecs */
+		/* adjust value to usecs */
 		__u64 helper;
 
 		helper = ((__u64) signal)*1000000;
@@ -580,6 +581,40 @@ static struct lirc_driver driver = {
        .owner		= THIS_MODULE,
 };
 
+static struct platform_device *lirc_parallel_dev;
+
+static int __devinit lirc_parallel_probe(struct platform_device *dev)
+{
+	return 0;
+}
+
+static int __devexit lirc_parallel_remove(struct platform_device *dev)
+{
+	return 0;
+}
+
+static int lirc_parallel_suspend(struct platform_device *dev,
+                                 pm_message_t state)
+{
+	return 0;
+}
+
+static int lirc_parallel_resume(struct platform_device *dev)
+{
+	return 0;
+}
+
+static struct platform_driver lirc_parallel_driver = {
+	.probe	= lirc_parallel_probe,
+	.remove	= __devexit_p(lirc_parallel_remove),
+	.suspend	= lirc_parallel_suspend,
+	.resume	= lirc_parallel_resume,
+	.driver	= {
+		.name	= LIRC_DRIVER_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
 static int pf(void *handle);
 static void kf(void *handle);
 
@@ -608,11 +643,30 @@ static void kf(void *handle)
 
 static int __init lirc_parallel_init(void)
 {
+	int result;
+
+	result = platform_driver_register(&lirc_parallel_driver);
+	if (result) {
+		printk("platform_driver_register returned %d\n", result);
+		return result;
+	}
+
+	lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0);
+	if (!lirc_parallel_dev) {
+		result = -ENOMEM;
+		goto exit_driver_unregister;
+	}
+
+	result = platform_device_add(lirc_parallel_dev);
+	if (result)
+		goto exit_device_put;
+
 	pport = parport_find_base(io);
 	if (pport == NULL) {
 		printk(KERN_NOTICE "%s: no port at %x found\n",
 		       LIRC_DRIVER_NAME, io);
-		return -ENXIO;
+		result = -ENXIO;
+		goto exit_device_put;
 	}
 	ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME,
 					   pf, kf, irq_handler, 0, NULL);
@@ -620,7 +674,8 @@ static int __init lirc_parallel_init(void)
 	if (ppdevice == NULL) {
 		printk(KERN_NOTICE "%s: parport_register_device() failed\n",
 		       LIRC_DRIVER_NAME);
-		return -ENXIO;
+		result = -ENXIO;
+		goto exit_device_put;
 	}
 	if (parport_claim(ppdevice) != 0)
 		goto skip_init;
@@ -638,7 +693,8 @@ static int __init lirc_parallel_init(void)
 		is_claimed = 0;
 		parport_release(pport);
 		parport_unregister_device(ppdevice);
-		return -EIO;
+		result = -EIO;
+		goto exit_device_put;
 	}
 
 #endif
@@ -649,16 +705,24 @@ static int __init lirc_parallel_init(void)
 	is_claimed = 0;
 	parport_release(ppdevice);
  skip_init:
+	driver.dev = &lirc_parallel_dev->dev;
 	driver.minor = lirc_register_driver(&driver);
 	if (driver.minor < 0) {
 		printk(KERN_NOTICE "%s: register_chrdev() failed\n",
 		       LIRC_DRIVER_NAME);
 		parport_unregister_device(ppdevice);
-		return -EIO;
+		result = -EIO;
+		goto exit_device_put;
 	}
 	printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n",
 	       LIRC_DRIVER_NAME, io, irq);
 	return 0;
+
+exit_device_put:
+	platform_device_put(lirc_parallel_dev);
+exit_driver_unregister:
+	platform_driver_unregister(&lirc_parallel_driver);
+	return result;
 }
 
 static void __exit lirc_parallel_exit(void)
diff --git a/drivers/staging/msm/lcdc.c b/drivers/staging/msm/lcdc.c
index 735280a..8183394 100644
--- a/drivers/staging/msm/lcdc.c
+++ b/drivers/staging/msm/lcdc.c
@@ -224,12 +224,12 @@ static int __init lcdc_driver_init(void)
 	mdp_lcdc_pclk_clk = clk_get(NULL, "mdp_lcdc_pclk_clk");
 	if (IS_ERR(mdp_lcdc_pclk_clk)) {
 		printk(KERN_ERR "error: can't get mdp_lcdc_pclk_clk!\n");
-		return IS_ERR(mdp_lcdc_pclk_clk);
+		return PTR_ERR(mdp_lcdc_pclk_clk);
 	}
 	mdp_lcdc_pad_pclk_clk = clk_get(NULL, "mdp_lcdc_pad_pclk_clk");
 	if (IS_ERR(mdp_lcdc_pad_pclk_clk)) {
 		printk(KERN_ERR "error: can't get mdp_lcdc_pad_pclk_clk!\n");
-		return IS_ERR(mdp_lcdc_pad_pclk_clk);
+		return PTR_ERR(mdp_lcdc_pad_pclk_clk);
 	}
 //	pm_qos_add_requirement(PM_QOS_SYSTEM_BUS_FREQ , "lcdc",
 //				PM_QOS_DEFAULT_VALUE);
diff --git a/drivers/staging/msm/mddi_toshiba.h b/drivers/staging/msm/mddi_toshiba.h
index 2d22b9a..cbeea0a 100644
--- a/drivers/staging/msm/mddi_toshiba.h
+++ b/drivers/staging/msm/mddi_toshiba.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MDDI_TOSHIBA_H
diff --git a/drivers/staging/msm/mddihost.h b/drivers/staging/msm/mddihost.h
index c46f24a..8f532d0 100644
--- a/drivers/staging/msm/mddihost.h
+++ b/drivers/staging/msm/mddihost.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MDDIHOST_H
diff --git a/drivers/staging/msm/mddihosti.h b/drivers/staging/msm/mddihosti.h
index 7b26a42..79eb399 100644
--- a/drivers/staging/msm/mddihosti.h
+++ b/drivers/staging/msm/mddihosti.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MDDIHOSTI_H
diff --git a/drivers/staging/msm/mdp.h b/drivers/staging/msm/mdp.h
index 0a5d6ac..44b1147 100644
--- a/drivers/staging/msm/mdp.h
+++ b/drivers/staging/msm/mdp.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2010, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MDP_H
diff --git a/drivers/staging/msm/mdp4.h b/drivers/staging/msm/mdp4.h
index 26ec8f1..96997d9 100644
--- a/drivers/staging/msm/mdp4.h
+++ b/drivers/staging/msm/mdp4.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MDP4_H
diff --git a/drivers/staging/msm/mdp_ppp_dq.h b/drivers/staging/msm/mdp_ppp_dq.h
index 03e4e9a..759abc2 100644
--- a/drivers/staging/msm/mdp_ppp_dq.h
+++ b/drivers/staging/msm/mdp_ppp_dq.h
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009-2010, Code Aurora Forum. 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 of Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MDP_PPP_DQ_H
diff --git a/drivers/staging/msm/msm_fb.h b/drivers/staging/msm/msm_fb.h
index f939138..4bca6d2 100644
--- a/drivers/staging/msm/msm_fb.h
+++ b/drivers/staging/msm/msm_fb.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MSM_FB_H
diff --git a/drivers/staging/msm/msm_fb_def.h b/drivers/staging/msm/msm_fb_def.h
index c5f9e9e..bc7f256 100644
--- a/drivers/staging/msm/msm_fb_def.h
+++ b/drivers/staging/msm/msm_fb_def.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MSM_FB_DEF_H
diff --git a/drivers/staging/msm/msm_fb_panel.h b/drivers/staging/msm/msm_fb_panel.h
index ab45831..6375976 100644
--- a/drivers/staging/msm/msm_fb_panel.h
+++ b/drivers/staging/msm/msm_fb_panel.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef MSM_FB_PANEL_H
diff --git a/drivers/staging/msm/tvenc.h b/drivers/staging/msm/tvenc.h
index a682dbe..6bb375d 100644
--- a/drivers/staging/msm/tvenc.h
+++ b/drivers/staging/msm/tvenc.h
@@ -1,29 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 of Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 
 #ifndef TVENC_H
diff --git a/drivers/staging/octeon/cvmx-cmd-queue.h b/drivers/staging/octeon/cvmx-cmd-queue.h
index f0cb20f..59d2214 100644
--- a/drivers/staging/octeon/cvmx-cmd-queue.h
+++ b/drivers/staging/octeon/cvmx-cmd-queue.h
@@ -110,7 +110,7 @@ typedef enum {
 } cvmx_cmd_queue_id_t;
 
 /**
- * Command write operations can fail if the comamnd queue needs
+ * Command write operations can fail if the command queue needs
  * a new buffer and the associated FPA pool is empty. It can also
  * fail if the number of queued command words reaches the maximum
  * set at initialization.
@@ -136,12 +136,12 @@ typedef struct {
 	uint64_t unused2:6;
 	/* FPA buffer size in 64bit words minus 1 */
 	uint64_t pool_size_m1:13;
-	/* Number of comamnds already used in buffer */
+	/* Number of commands already used in buffer */
 	uint64_t index:13;
 } __cvmx_cmd_queue_state_t;
 
 /**
- * This structure contains the global state of all comamnd queues.
+ * This structure contains the global state of all command queues.
  * It is stored in a bootmem named block and shared by all
  * applications running on Octeon. Tickets are stored in a differnet
  * cahce line that queue information to reduce the contention on the
@@ -308,7 +308,7 @@ static inline __cvmx_cmd_queue_state_t
 
 /**
  * Write an arbitrary number of command words to a command queue.
- * This is a generic function; the fixed number of comamnd word
+ * This is a generic function; the fixed number of command word
  * functions yield higher performance.
  *
  * @queue_id:  Hardware command queue to write to
@@ -317,7 +317,7 @@ static inline __cvmx_cmd_queue_state_t
  *                  updates. If you don't use this locking you must ensure
  *                  exclusivity some other way. Locking is strongly recommended.
  * @cmd_count: Number of command words to write
- * @cmds:      Array of comamnds to write
+ * @cmds:      Array of commands to write
  *
  * Returns CVMX_CMD_QUEUE_SUCCESS or a failure code
  */
@@ -363,7 +363,7 @@ static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write(cvmx_cmd_queue_id_t
 		uint64_t *ptr;
 		int count;
 		/*
-		 * We need a new comamnd buffer. Fail if there isn't
+		 * We need a new command buffer. Fail if there isn't
 		 * one available.
 		 */
 		uint64_t *new_buffer =
@@ -466,7 +466,7 @@ static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write2(cvmx_cmd_queue_id_t
 		 */
 		int count = qptr->pool_size_m1 - qptr->index;
 		/*
-		 * We need a new comamnd buffer. Fail if there isn't
+		 * We need a new command buffer. Fail if there isn't
 		 * one available.
 		 */
 		uint64_t *new_buffer =
@@ -568,7 +568,7 @@ static inline cvmx_cmd_queue_result_t cvmx_cmd_queue_write3(cvmx_cmd_queue_id_t
 		 */
 		int count = qptr->pool_size_m1 - qptr->index;
 		/*
-		 * We need a new comamnd buffer. Fail if there isn't
+		 * We need a new command buffer. Fail if there isn't
 		 * one available
 		 */
 		uint64_t *new_buffer =
diff --git a/drivers/staging/octeon/cvmx-pko.c b/drivers/staging/octeon/cvmx-pko.c
index 00db915..50a2c9b 100644
--- a/drivers/staging/octeon/cvmx-pko.c
+++ b/drivers/staging/octeon/cvmx-pko.c
@@ -54,7 +54,7 @@ void cvmx_pko_initialize_global(void)
 	/*
 	 * Set the size of the PKO command buffers to an odd number of
 	 * 64bit words. This allows the normal two word send to stay
-	 * aligned and never span a comamnd word buffer.
+	 * aligned and never span a command word buffer.
 	 */
 	config.u64 = 0;
 	config.s.pool = CVMX_FPA_OUTPUT_BUFFER_POOL;
diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig
index 8be8716..f1082f5 100644
--- a/drivers/staging/olpc_dcon/Kconfig
+++ b/drivers/staging/olpc_dcon/Kconfig
@@ -1,8 +1,28 @@
 config FB_OLPC_DCON
 	tristate "One Laptop Per Child Display CONtroller support"
-	depends on OLPC && BROKEN
+	depends on OLPC && FB
 	select I2C
 	---help---
 	  Add support for the OLPC XO DCON controller.  This controller is
 	  only available on OLPC platforms.   Unless you have one of these
 	  platforms, you will want to say 'N'.
+
+config FB_OLPC_DCON_1
+	bool "OLPC XO-1 DCON support"
+	depends on FB_OLPC_DCON
+	default y
+	---help---
+	  Enable support for the DCON in XO-1 model laptops.  The kernel
+	  communicates with the DCON using model-specific code.  If you
+	  have an XO-1 (or if you're unsure what model you have), you should
+	  say 'Y'.
+
+config FB_OLPC_DCON_1_5
+	bool "OLPC XO-1.5 DCON support"
+	depends on FB_OLPC_DCON && ACPI
+	default y
+	---help---
+	  Enable support for the DCON in XO-1.5 model laptops.  The kernel
+	  communicates with the DCON using model-specific code.  If you
+	  have an XO-1.5 (or if you're unsure what model you have), you
+	  should say 'Y'.
diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile
index cd8f289..36c7e67 100644
--- a/drivers/staging/olpc_dcon/Makefile
+++ b/drivers/staging/olpc_dcon/Makefile
@@ -1 +1,6 @@
-obj-$(CONFIG_FB_OLPC_DCON)	+= olpc_dcon.o
+olpc-dcon-objs += olpc_dcon.o
+olpc-dcon-$(CONFIG_FB_OLPC_DCON_1)	+= olpc_dcon_xo_1.o
+olpc-dcon-$(CONFIG_FB_OLPC_DCON_1_5)	+= olpc_dcon_xo_1_5.o
+obj-$(CONFIG_FB_OLPC_DCON)	+= olpc-dcon.o
+
+
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
index 56a283d..750fe50 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon.c
@@ -4,7 +4,7 @@
  * Copyright ÂŠ 2006-2007  Red Hat, Inc.
  * Copyright ÂŠ 2006-2007  Advanced Micro Devices, Inc.
  * Copyright ÂŠ 2009       VIA Technology, Inc.
- * Copyright (c) 2010  Andres Salomon <dilinger@queued.net>
+ * Copyright (c) 2010-2011  Andres Salomon <dilinger@queued.net>
  *
  * This program is free software.  You can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -23,8 +23,7 @@
 #include <linux/delay.h>
 #include <linux/backlight.h>
 #include <linux/device.h>
-#include <linux/notifier.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/reboot.h>
 #include <asm/tsc.h>
@@ -44,65 +43,32 @@ module_param(noinit, int, 0444);
 static int useaa = 1;
 module_param(useaa, int, 0444);
 
-struct dcon_platform_data {
-	int (*init)(void);
-	void (*bus_stabilize_wiggle)(void);
-	void (*set_dconload)(int);
-	u8 (*read_status)(void);
-};
-
 static struct dcon_platform_data *pdata;
 
 /* I2C structures */
 
-static struct i2c_driver dcon_driver;
-static struct i2c_client *dcon_client;
-
 /* Platform devices */
 static struct platform_device *dcon_device;
 
-/* Backlight device */
-static struct backlight_device *dcon_bl_dev;
-
-static struct fb_info *fbinfo;
-
-/* set this to 1 while controlling fb blank state from this driver */
-static int ignore_fb_events = 0;
-
-/* Current source, initialized at probe time */
-static int dcon_source;
-
-/* Desired source */
-static int dcon_pending;
-
-/* Current output type */
-static int dcon_output = DCON_OUTPUT_COLOR;
-
-/* Current sleep status (not yet implemented) */
-static int dcon_sleep_val = DCON_ACTIVE;
-
-/* Shadow register for the DCON_REG_MODE register */
-static unsigned short dcon_disp_mode;
-
-/* Variables used during switches */
-static int dcon_switched;
-static struct timespec dcon_irq_time;
-static struct timespec dcon_load_time; 
-
 static DECLARE_WAIT_QUEUE_HEAD(dcon_wait_queue);
 
 static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
 
-#define dcon_write(reg,val) i2c_smbus_write_word_data(dcon_client,reg,val)
-#define dcon_read(reg) i2c_smbus_read_word_data(dcon_client,reg)
+static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
+{
+	return i2c_smbus_write_word_data(dcon->client, reg, val);
+}
 
-/* The current backlight value - this saves us some smbus traffic */
-static int bl_val = -1;
+static s32 dcon_read(struct dcon_priv *dcon, u8 reg)
+{
+	return i2c_smbus_read_word_data(dcon->client, reg);
+}
 
 /* ===== API functions - these are called by a variety of users ==== */
 
-static int dcon_hw_init(struct i2c_client *client, int is_init)
+static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
 {
+	struct i2c_client *client = dcon->client;
 	uint16_t ver;
 	int rc = 0;
 
@@ -117,7 +83,8 @@ static int dcon_hw_init(struct i2c_client *client, int is_init)
 	if (is_init) {
 		printk(KERN_INFO "olpc-dcon:  Discovered DCON version %x\n",
 				ver & 0xFF);
-		if ((rc = pdata->init()) != 0) {
+		rc = pdata->init(dcon);
+		if (rc != 0) {
 			printk(KERN_ERR "olpc-dcon:  Unable to init.\n");
 			goto err;
 		}
@@ -133,14 +100,13 @@ static int dcon_hw_init(struct i2c_client *client, int is_init)
 		i2c_smbus_write_word_data(client, 0x0b, 0x007a);
 		i2c_smbus_write_word_data(client, 0x36, 0x025c);
 		i2c_smbus_write_word_data(client, 0x37, 0x025e);
-		
+
 		/* Initialise SDRAM */
 
 		i2c_smbus_write_word_data(client, 0x3b, 0x002b);
 		i2c_smbus_write_word_data(client, 0x41, 0x0101);
 		i2c_smbus_write_word_data(client, 0x42, 0x0101);
-	}
-	else if (!noinit) {
+	} else if (!noinit) {
 		/* SDRAM setup/hold time */
 		i2c_smbus_write_word_data(client, 0x3a, 0xc040);
 		i2c_smbus_write_word_data(client, 0x41, 0x0000);
@@ -150,11 +116,12 @@ static int dcon_hw_init(struct i2c_client *client, int is_init)
 
 	/* Colour swizzle, AA, no passthrough, backlight */
 	if (is_init) {
-		dcon_disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE | MODE_CSWIZZLE;
+		dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
+				MODE_CSWIZZLE;
 		if (useaa)
-			dcon_disp_mode |= MODE_COL_AA;
+			dcon->disp_mode |= MODE_COL_AA;
 	}
-	i2c_smbus_write_word_data(client, DCON_REG_MODE, dcon_disp_mode);
+	i2c_smbus_write_word_data(client, DCON_REG_MODE, dcon->disp_mode);
 
 
 	/* Set the scanline to interrupt on during resume */
@@ -173,7 +140,7 @@ err:
  * smbus.  For newer models, we simply BUG(); we want to know if this
  * still happens despite the power fixes that have been made!
  */
-static int dcon_bus_stabilize(struct i2c_client *client, int is_powered_down)
+static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down)
 {
 	unsigned long timeout;
 	int x;
@@ -181,19 +148,20 @@ static int dcon_bus_stabilize(struct i2c_client *client, int is_powered_down)
 power_up:
 	if (is_powered_down) {
 		x = 1;
-		if ((x = olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0))) {
+		x = olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0);
+		if (x) {
 			printk(KERN_WARNING "olpc-dcon:  unable to force dcon "
 					"to power up: %d!\n", x);
 			return x;
 		}
 		msleep(10); /* we'll be conservative */
 	}
-	
+
 	pdata->bus_stabilize_wiggle();
 
 	for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
 		msleep(1);
-		x = dcon_read(DCON_REG_ID);
+		x = dcon_read(dcon, DCON_REG_ID);
 	}
 	if (x < 0) {
 		printk(KERN_ERR "olpc-dcon:  unable to stabilize dcon's "
@@ -207,69 +175,44 @@ power_up:
 	}
 
 	if (is_powered_down)
-		return dcon_hw_init(client, 0);
+		return dcon_hw_init(dcon, 0);
 	return 0;
 }
 
-static int dcon_get_backlight(void)
+static void dcon_set_backlight(struct dcon_priv *dcon, u8 level)
 {
-	if (dcon_client == NULL)
-		return 0;
-
-	if (bl_val == -1)
-		bl_val = dcon_read(DCON_REG_BRIGHT) & 0x0F;
-
-	return bl_val;
-}
-
-
-static void dcon_set_backlight_hw(int level)
-{
-	bl_val = level & 0x0F;
-	dcon_write(DCON_REG_BRIGHT, bl_val);
+	dcon->bl_val = level;
+	dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val);
 
 	/* Purposely turn off the backlight when we go to level 0 */
-	if (bl_val == 0) {
-		dcon_disp_mode &= ~MODE_BL_ENABLE;
-		dcon_write(DCON_REG_MODE, dcon_disp_mode);
-	} else if (!(dcon_disp_mode & MODE_BL_ENABLE)) {
-		dcon_disp_mode |= MODE_BL_ENABLE;
-		dcon_write(DCON_REG_MODE, dcon_disp_mode);
+	if (dcon->bl_val == 0) {
+		dcon->disp_mode &= ~MODE_BL_ENABLE;
+		dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
+	} else if (!(dcon->disp_mode & MODE_BL_ENABLE)) {
+		dcon->disp_mode |= MODE_BL_ENABLE;
+		dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
 	}
 }
 
-static void dcon_set_backlight(int level)
-{
-	if (dcon_client == NULL)
-		return;
-
-	if (bl_val == (level & 0x0F))
-		return;
-
-	dcon_set_backlight_hw(level);
-}
-
 /* Set the output type to either color or mono */
-
-static int dcon_set_output(int arg)
+static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
 {
-	if (dcon_output == arg)
+	if (dcon->mono == enable_mono)
 		return 0;
 
-	dcon_output = arg;
+	dcon->mono = enable_mono;
 
-	if (arg == DCON_OUTPUT_MONO) {
-		dcon_disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA);
-		dcon_disp_mode |= MODE_MONO_LUMA;
-	}
-	else {
-		dcon_disp_mode &= ~(MODE_MONO_LUMA);
-		dcon_disp_mode |= MODE_CSWIZZLE;
+	if (enable_mono) {
+		dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA);
+		dcon->disp_mode |= MODE_MONO_LUMA;
+	} else {
+		dcon->disp_mode &= ~(MODE_MONO_LUMA);
+		dcon->disp_mode |= MODE_CSWIZZLE;
 		if (useaa)
-			dcon_disp_mode |= MODE_COL_AA;
+			dcon->disp_mode |= MODE_COL_AA;
 	}
 
-	dcon_write(DCON_REG_MODE, dcon_disp_mode);
+	dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
 	return 0;
 }
 
@@ -277,55 +220,55 @@ static int dcon_set_output(int arg)
  * DCONLOAD works in a sleep and account for it accordingly
  */
 
-static void dcon_sleep(int state)
+static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
 {
 	int x;
 
 	/* Turn off the backlight and put the DCON to sleep */
 
-	if (state == dcon_sleep_val)
+	if (dcon->asleep == sleep)
 		return;
 
 	if (!olpc_board_at_least(olpc_board(0xc2)))
 		return;
 
-	if (state == DCON_SLEEP) {
+	if (sleep) {
 		x = 0;
-		if ((x = olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0)))
+		x = olpc_ec_cmd(0x26, (unsigned char *) &x, 1, NULL, 0);
+		if (x)
 			printk(KERN_WARNING "olpc-dcon:  unable to force dcon "
 					"to power down: %d!\n", x);
 		else
-			dcon_sleep_val = state;
-	}
-	else {
+			dcon->asleep = sleep;
+	} else {
 		/* Only re-enable the backlight if the backlight value is set */
-		if (bl_val != 0)
-			dcon_disp_mode |= MODE_BL_ENABLE;
-
-		if ((x=dcon_bus_stabilize(dcon_client, 1)))
+		if (dcon->bl_val != 0)
+			dcon->disp_mode |= MODE_BL_ENABLE;
+		x = dcon_bus_stabilize(dcon, 1);
+		if (x)
 			printk(KERN_WARNING "olpc-dcon:  unable to reinit dcon"
 					" hardware: %d!\n", x);
 		else
-			dcon_sleep_val = state;
+			dcon->asleep = sleep;
 
 		/* Restore backlight */
-		dcon_set_backlight_hw(bl_val);
+		dcon_set_backlight(dcon, dcon->bl_val);
 	}
 
 	/* We should turn off some stuff in the framebuffer - but what? */
 }
 
 /* the DCON seems to get confused if we change DCONLOAD too
- * frequently -- i.e., approximately faster than frame time. 
+ * frequently -- i.e., approximately faster than frame time.
  * normally we don't change it this fast, so in general we won't
  * delay here.
  */
-void dcon_load_holdoff(void)
+static void dcon_load_holdoff(struct dcon_priv *dcon)
 {
 	struct timespec delta_t, now;
-	while(1) {
+	while (1) {
 		getnstimeofday(&now);
-		delta_t = timespec_sub(now, dcon_load_time);
+		delta_t = timespec_sub(now, dcon->load_time);
 		if (delta_t.tv_sec != 0 ||
 			delta_t.tv_nsec > NSEC_PER_MSEC * 20) {
 			break;
@@ -333,36 +276,65 @@ void dcon_load_holdoff(void)
 		mdelay(4);
 	}
 }
-/* Set the source of the display (CPU or DCON) */
 
+static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank)
+{
+	int err;
+
+	if (!lock_fb_info(dcon->fbinfo)) {
+		dev_err(&dcon->client->dev, "unable to lock framebuffer\n");
+		return false;
+	}
+	console_lock();
+	dcon->ignore_fb_events = true;
+	err = fb_blank(dcon->fbinfo,
+			blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
+	dcon->ignore_fb_events = false;
+	console_unlock();
+	unlock_fb_info(dcon->fbinfo);
+
+	if (err) {
+		dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n",
+				blank ? "" : "un");
+		return false;
+	}
+	return true;
+}
+
+/* Set the source of the display (CPU or DCON) */
 static void dcon_source_switch(struct work_struct *work)
 {
+	struct dcon_priv *dcon = container_of(work, struct dcon_priv,
+			switch_source);
 	DECLARE_WAITQUEUE(wait, current);
-	int source = dcon_pending;
+	int source = dcon->pending_src;
 
-	if (dcon_source == source)
+	if (dcon->curr_src == source)
 		return;
 
-	dcon_load_holdoff();
+	dcon_load_holdoff(dcon);
 
-	dcon_switched = 0;
+	dcon->switched = false;
 
 	switch (source) {
 	case DCON_SOURCE_CPU:
 		printk("dcon_source_switch to CPU\n");
 		/* Enable the scanline interrupt bit */
-		if (dcon_write(DCON_REG_MODE, dcon_disp_mode | MODE_SCAN_INT))
-			printk(KERN_ERR "olpc-dcon:  couldn't enable scanline interrupt!\n");
+		if (dcon_write(dcon, DCON_REG_MODE,
+				dcon->disp_mode | MODE_SCAN_INT))
+			printk(KERN_ERR
+			       "olpc-dcon:  couldn't enable scanline interrupt!\n");
 		else {
 			/* Wait up to one second for the scanline interrupt */
-			wait_event_timeout(dcon_wait_queue, dcon_switched == 1, HZ);
+			wait_event_timeout(dcon_wait_queue,
+					   dcon->switched == true, HZ);
 		}
 
-		if (!dcon_switched)
+		if (!dcon->switched)
 			printk(KERN_ERR "olpc-dcon:  Timeout entering CPU mode; expect a screen glitch.\n");
 
 		/* Turn off the scanline interrupt */
-		if (dcon_write(DCON_REG_MODE, dcon_disp_mode))
+		if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode))
 			printk(KERN_ERR "olpc-dcon:  couldn't disable scanline interrupt!\n");
 
 		/*
@@ -373,21 +345,15 @@ static void dcon_source_switch(struct work_struct *work)
 		 *
 		 * For now, we just hope..
 		 */
-		console_lock();
-		ignore_fb_events = 1;
-		if (fb_blank(fbinfo, FB_BLANK_UNBLANK)) {
-			ignore_fb_events = 0;
-			console_unlock();
+		if (!dcon_blank_fb(dcon, false)) {
 			printk(KERN_ERR "olpc-dcon:  Failed to enter CPU mode\n");
-			dcon_pending = DCON_SOURCE_DCON;
+			dcon->pending_src = DCON_SOURCE_DCON;
 			return;
 		}
-		ignore_fb_events = 0;
-		console_unlock();
 
 		/* And turn off the DCON */
 		pdata->set_dconload(1);
-		getnstimeofday(&dcon_load_time);
+		getnstimeofday(&dcon->load_time);
 
 		printk(KERN_INFO "olpc-dcon: The CPU has control\n");
 		break;
@@ -396,20 +362,20 @@ static void dcon_source_switch(struct work_struct *work)
 		int t;
 		struct timespec delta_t;
 
-		printk("dcon_source_switch to DCON\n");
+		printk(KERN_INFO "dcon_source_switch to DCON\n");
 
 		add_wait_queue(&dcon_wait_queue, &wait);
 		set_current_state(TASK_UNINTERRUPTIBLE);
 
 		/* Clear DCONLOAD - this implies that the DCON is in control */
 		pdata->set_dconload(0);
-		getnstimeofday(&dcon_load_time);
+		getnstimeofday(&dcon->load_time);
 
 		t = schedule_timeout(HZ/2);
 		remove_wait_queue(&dcon_wait_queue, &wait);
 		set_current_state(TASK_RUNNING);
 
-		if (!dcon_switched) {
+		if (!dcon->switched) {
 			printk(KERN_ERR "olpc-dcon: Timeout entering DCON mode; expect a screen glitch.\n");
 		} else {
 			/* sometimes the DCON doesn't follow its own rules,
@@ -420,28 +386,22 @@ static void dcon_source_switch(struct work_struct *work)
 			 * the time between asserting DCONLOAD and the IRQ --
 			 * if it's less than 20msec, then the DCON couldn't
 			 * have seen two VSYNC pulses.  in that case we
-			 * deassert and reassert, and hope for the best. 
+			 * deassert and reassert, and hope for the best.
 			 * see http://dev.laptop.org/ticket/9664
 			 */
-			delta_t = timespec_sub(dcon_irq_time, dcon_load_time);
-			if (dcon_switched && delta_t.tv_sec == 0 &&
+			delta_t = timespec_sub(dcon->irq_time, dcon->load_time);
+			if (dcon->switched && delta_t.tv_sec == 0 &&
 					delta_t.tv_nsec < NSEC_PER_MSEC * 20) {
 				printk(KERN_ERR "olpc-dcon: missed loading, retrying\n");
 				pdata->set_dconload(1);
 				mdelay(41);
 				pdata->set_dconload(0);
-				getnstimeofday(&dcon_load_time);
+				getnstimeofday(&dcon->load_time);
 				mdelay(41);
 			}
 		}
 
-		console_lock();
-		ignore_fb_events = 1;
-		if (fb_blank(fbinfo, FB_BLANK_POWERDOWN))
-			printk(KERN_ERR "olpc-dcon:  couldn't blank fb!\n");
-		ignore_fb_events = 0;
-		console_unlock();
-
+		dcon_blank_fb(dcon, true);
 		printk(KERN_INFO "olpc-dcon: The DCON has control\n");
 		break;
 	}
@@ -449,66 +409,53 @@ static void dcon_source_switch(struct work_struct *work)
 		BUG();
 	}
 
-	dcon_source = source;
+	dcon->curr_src = source;
 }
 
-static DECLARE_WORK(dcon_work, dcon_source_switch);
-
-static void dcon_set_source(int arg)
+static void dcon_set_source(struct dcon_priv *dcon, int arg)
 {
-	if (dcon_pending == arg)
+	if (dcon->pending_src == arg)
 		return;
 
-	dcon_pending = arg;
+	dcon->pending_src = arg;
 
-	if ((dcon_source != arg) && !work_pending(&dcon_work))
-		schedule_work(&dcon_work);
+	if ((dcon->curr_src != arg) && !work_pending(&dcon->switch_source))
+		schedule_work(&dcon->switch_source);
 }
 
-static void dcon_set_source_sync(int arg)
+static void dcon_set_source_sync(struct dcon_priv *dcon, int arg)
 {
-	dcon_set_source(arg);
+	dcon_set_source(dcon, arg);
 	flush_scheduled_work();
 }
 
-static int dconbl_set(struct backlight_device *dev) {
-
-	int level = dev->props.brightness;
-
-	if (dev->props.power != FB_BLANK_UNBLANK)
-		level = 0;
-
-	dcon_set_backlight(level);
-	return 0;
-}
-
-static int dconbl_get(struct backlight_device *dev) {
-	return dcon_get_backlight();
-}
-
 static ssize_t dcon_mode_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%4.4X\n", dcon_disp_mode);
+	struct dcon_priv *dcon = dev_get_drvdata(dev);
+	return sprintf(buf, "%4.4X\n", dcon->disp_mode);
 }
 
 static ssize_t dcon_sleep_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 
-	return sprintf(buf, "%d\n", dcon_sleep_val);
+	struct dcon_priv *dcon = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", dcon->asleep);
 }
 
 static ssize_t dcon_freeze_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", dcon_source == DCON_SOURCE_DCON ? 1 : 0);
+	struct dcon_priv *dcon = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0);
 }
 
-static ssize_t dcon_output_show(struct device *dev,
+static ssize_t dcon_mono_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return sprintf(buf, "%d\n", dcon_output);
+	struct dcon_priv *dcon = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", dcon->mono);
 }
 
 static ssize_t dcon_resumeline_show(struct device *dev,
@@ -517,59 +464,43 @@ static ssize_t dcon_resumeline_show(struct device *dev,
 	return sprintf(buf, "%d\n", resumeline);
 }
 
-static int _strtoul(const char *buf, int len, unsigned int *val)
-{
-
-	char *endp;
-	unsigned int output = simple_strtoul(buf, &endp, 0);
-	int size = endp - buf;
-
-	if (*endp && isspace(*endp))
-		size++;
-
-	if (size != len)
-		return -EINVAL;
-
-	*val = output;
-	return 0;
-}
-
-static ssize_t dcon_output_store(struct device *dev,
+static ssize_t dcon_mono_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	int output;
-	int rc = -EINVAL;
+	unsigned long enable_mono;
+	int rc;
 
-	if (_strtoul(buf, count, &output))
-		return -EINVAL;
+	rc = strict_strtoul(buf, 10, &enable_mono);
+	if (rc)
+		return rc;
 
-	if (output == DCON_OUTPUT_COLOR || output == DCON_OUTPUT_MONO) {
-		dcon_set_output(output);
-		rc = count;
-	}
+	dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false);
 
-	return rc;
+	return count;
 }
 
 static ssize_t dcon_freeze_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	int output;
+	struct dcon_priv *dcon = dev_get_drvdata(dev);
+	unsigned long output;
+	int ret;
 
-	if (_strtoul(buf, count, &output))
-		return -EINVAL;
+	ret = strict_strtoul(buf, 10, &output);
+	if (ret)
+		return ret;
 
-	printk("dcon_freeze_store: %d\n", output);
+	printk(KERN_INFO "dcon_freeze_store: %lu\n", output);
 
 	switch (output) {
 	case 0:
-		dcon_set_source(DCON_SOURCE_CPU);
+		dcon_set_source(dcon, DCON_SOURCE_CPU);
 		break;
 	case 1:
-		dcon_set_source_sync(DCON_SOURCE_DCON);
+		dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
 		break;
-	case 2:  // normally unused
-		dcon_set_source(DCON_SOURCE_DCON);
+	case 2:  /* normally unused */
+		dcon_set_source(dcon, DCON_SOURCE_DCON);
 		break;
 	default:
 		return -EINVAL;
@@ -581,28 +512,30 @@ static ssize_t dcon_freeze_store(struct device *dev,
 static ssize_t dcon_resumeline_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	int rl;
-	int rc = -EINVAL;
+	unsigned long rl;
+	int rc;
 
-	if (_strtoul(buf, count, &rl))
+	rc = strict_strtoul(buf, 10, &rl);
+	if (rc)
 		return rc;
 
 	resumeline = rl;
-	dcon_write(DCON_REG_SCAN_INT, resumeline);
-	rc = count;
+	dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline);
 
-	return rc;
+	return count;
 }
 
 static ssize_t dcon_sleep_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	int output;
+	unsigned long output;
+	int ret;
 
-	if (_strtoul(buf, count, &output))
-		return -EINVAL;
+	ret = strict_strtoul(buf, 10, &output);
+	if (ret)
+		return ret;
 
-	dcon_sleep(output ? DCON_SLEEP : DCON_ACTIVE);
+	dcon_sleep(dev_get_drvdata(dev), output ? true : false);
 	return count;
 }
 
@@ -610,33 +543,57 @@ static struct device_attribute dcon_device_files[] = {
 	__ATTR(mode, 0444, dcon_mode_show, NULL),
 	__ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store),
 	__ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store),
-	__ATTR(output, 0644, dcon_output_show, dcon_output_store),
+	__ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store),
 	__ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store),
 };
 
+static int dcon_bl_update(struct backlight_device *dev)
+{
+	struct dcon_priv *dcon = bl_get_data(dev);
+	u8 level = dev->props.brightness & 0x0F;
+
+	if (dev->props.power != FB_BLANK_UNBLANK)
+		level = 0;
+
+	if (level != dcon->bl_val)
+		dcon_set_backlight(dcon, level);
+
+	return 0;
+}
+
+static int dcon_bl_get(struct backlight_device *dev)
+{
+	struct dcon_priv *dcon = bl_get_data(dev);
+	return dcon->bl_val;
+}
+
 static const struct backlight_ops dcon_bl_ops = {
-	.get_brightness = dconbl_get,
-	.update_status = dconbl_set
+	.update_status = dcon_bl_update,
+	.get_brightness = dcon_bl_get,
 };
 
+static struct backlight_properties dcon_bl_props = {
+	.max_brightness = 15,
+	.type = BACKLIGHT_RAW,
+	.power = FB_BLANK_UNBLANK,
+};
 
-static int dcon_reboot_notify(struct notifier_block *nb, unsigned long foo, void *bar)
+static int dcon_reboot_notify(struct notifier_block *nb,
+			      unsigned long foo, void *bar)
 {
-	if (dcon_client == NULL)
+	struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb);
+
+	if (!dcon || !dcon->client)
 		return 0;
 
 	/* Turn off the DCON. Entirely. */
-	dcon_write(DCON_REG_MODE, 0x39);
-	dcon_write(DCON_REG_MODE, 0x32);
+	dcon_write(dcon, DCON_REG_MODE, 0x39);
+	dcon_write(dcon, DCON_REG_MODE, 0x32);
 	return 0;
 }
 
-static struct notifier_block dcon_nb = {
-	.notifier_call = dcon_reboot_notify,
-	.priority = -1,
-};
-
-static int unfreeze_on_panic(struct notifier_block *nb, unsigned long e, void *p)
+static int unfreeze_on_panic(struct notifier_block *nb,
+			     unsigned long e, void *p)
 {
 	pdata->set_dconload(1);
 	return NOTIFY_DONE;
@@ -650,21 +607,20 @@ static struct notifier_block dcon_panic_nb = {
  * When the framebuffer sleeps due to external sources (e.g. user idle), power
  * down the DCON as well.  Power it back up when the fb comes back to life.
  */
-static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data)
+static int dcon_fb_notifier(struct notifier_block *self,
+				unsigned long event, void *data)
 {
 	struct fb_event *evdata = data;
+	struct dcon_priv *dcon = container_of(self, struct dcon_priv,
+			fbevent_nb);
 	int *blank = (int *) evdata->data;
 	if (((event != FB_EVENT_BLANK) && (event != FB_EVENT_CONBLANK)) ||
-			ignore_fb_events)
+			dcon->ignore_fb_events)
 		return 0;
-	dcon_sleep((*blank) ? DCON_SLEEP : DCON_ACTIVE);
+	dcon_sleep(dcon, *blank ? true : false);
 	return 0;
 }
 
-static struct notifier_block fb_nb = {
-	.notifier_call = fb_notifier_callback,
-};
-
 static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
 {
 	strlcpy(info->type, "olpc_dcon", I2C_NAME_SIZE);
@@ -674,12 +630,32 @@ static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
 
 static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	int rc, i;
+	struct dcon_priv *dcon;
+	int rc, i, j;
+
+	if (!pdata)
+		return -ENXIO;
 
-	if (num_registered_fb >= 1)
-		fbinfo = registered_fb[0];
+	dcon = kzalloc(sizeof(*dcon), GFP_KERNEL);
+	if (!dcon)
+		return -ENOMEM;
 
-	rc = dcon_hw_init(client, 1);
+	dcon->client = client;
+	INIT_WORK(&dcon->switch_source, dcon_source_switch);
+	dcon->reboot_nb.notifier_call = dcon_reboot_notify;
+	dcon->reboot_nb.priority = -1;
+	dcon->fbevent_nb.notifier_call = dcon_fb_notifier;
+
+	i2c_set_clientdata(client, dcon);
+
+	if (num_registered_fb < 1) {
+		dev_err(&client->dev, "DCON driver requires a registered fb\n");
+		rc = -EIO;
+		goto einit;
+	}
+	dcon->fbinfo = registered_fb[0];
+
+	rc = dcon_hw_init(dcon, 1);
 	if (rc)
 		goto einit;
 
@@ -688,71 +664,79 @@ static int dcon_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	dcon_device = platform_device_alloc("dcon", -1);
 
 	if (dcon_device == NULL) {
-		printk("dcon:  Unable to create the DCON device\n");
+		printk(KERN_ERR "dcon:  Unable to create the DCON device\n");
 		rc = -ENOMEM;
 		goto eirq;
 	}
-	/* Place holder...*/
-	i2c_set_clientdata(client, dcon_device);
+	rc = platform_device_add(dcon_device);
+	platform_set_drvdata(dcon_device, dcon);
 
-	if ((rc = platform_device_add(dcon_device))) {
-		printk("dcon:  Unable to add the DCON device\n");
+	if (rc) {
+		printk(KERN_ERR "dcon:  Unable to add the DCON device\n");
 		goto edev;
 	}
 
-	for(i = 0; i < ARRAY_SIZE(dcon_device_files); i++)
-		device_create_file(&dcon_device->dev, &dcon_device_files[i]);
-
-	/* Add the backlight device for the DCON */
-
-	dcon_client = client;
-
-	dcon_bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev,
-		NULL, &dcon_bl_ops, NULL);
-
-	if (IS_ERR(dcon_bl_dev)) {
-		printk("Could not register the backlight device for the DCON (%ld)\n", PTR_ERR(dcon_bl_dev));
-		dcon_bl_dev = NULL;
+	for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) {
+		rc = device_create_file(&dcon_device->dev,
+					&dcon_device_files[i]);
+		if (rc) {
+			dev_err(&dcon_device->dev, "Cannot create sysfs file\n");
+			goto ecreate;
+		}
 	}
-	else {
-		dcon_bl_dev->props.max_brightness = 15;
-		dcon_bl_dev->props.power = FB_BLANK_UNBLANK;
-		dcon_bl_dev->props.brightness = dcon_get_backlight();
 
-		backlight_update_status(dcon_bl_dev);
+	dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F;
+
+	/* Add the backlight device for the DCON */
+	dcon_bl_props.brightness = dcon->bl_val;
+	dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev,
+		dcon, &dcon_bl_ops, &dcon_bl_props);
+	if (IS_ERR(dcon->bl_dev)) {
+		dev_err(&client->dev, "cannot register backlight dev (%ld)\n",
+				PTR_ERR(dcon->bl_dev));
+		dcon->bl_dev = NULL;
 	}
 
-	register_reboot_notifier(&dcon_nb);
+	register_reboot_notifier(&dcon->reboot_nb);
 	atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb);
-	fb_register_client(&fb_nb);
+	fb_register_client(&dcon->fbevent_nb);
 
 	return 0;
 
+ ecreate:
+	for (j = 0; j < i; j++)
+		device_remove_file(&dcon_device->dev, &dcon_device_files[j]);
  edev:
 	platform_device_unregister(dcon_device);
 	dcon_device = NULL;
  eirq:
-	free_irq(DCON_IRQ, &dcon_driver);
+	free_irq(DCON_IRQ, dcon);
  einit:
+	i2c_set_clientdata(client, NULL);
+	kfree(dcon);
 	return rc;
 }
 
 static int dcon_remove(struct i2c_client *client)
 {
-	dcon_client = NULL;
+	struct dcon_priv *dcon = i2c_get_clientdata(client);
+
+	i2c_set_clientdata(client, NULL);
 
-	fb_unregister_client(&fb_nb);
-	unregister_reboot_notifier(&dcon_nb);
+	fb_unregister_client(&dcon->fbevent_nb);
+	unregister_reboot_notifier(&dcon->reboot_nb);
 	atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
 
-	free_irq(DCON_IRQ, &dcon_driver);
+	free_irq(DCON_IRQ, dcon);
 
-	if (dcon_bl_dev != NULL)
-		backlight_device_unregister(dcon_bl_dev);
+	if (dcon->bl_dev)
+		backlight_device_unregister(dcon->bl_dev);
 
 	if (dcon_device != NULL)
 		platform_device_unregister(dcon_device);
-	cancel_work_sync(&dcon_work);
+	cancel_work_sync(&dcon->switch_source);
+
+	kfree(dcon);
 
 	return 0;
 }
@@ -760,9 +744,11 @@ static int dcon_remove(struct i2c_client *client)
 #ifdef CONFIG_PM
 static int dcon_suspend(struct i2c_client *client, pm_message_t state)
 {
-	if (dcon_sleep_val == DCON_ACTIVE) {
+	struct dcon_priv *dcon = i2c_get_clientdata(client);
+
+	if (!dcon->asleep) {
 		/* Set up the DCON to have the source */
-		dcon_set_source_sync(DCON_SOURCE_DCON);
+		dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
 	}
 
 	return 0;
@@ -770,9 +756,11 @@ static int dcon_suspend(struct i2c_client *client, pm_message_t state)
 
 static int dcon_resume(struct i2c_client *client)
 {
-	if (dcon_sleep_val == DCON_ACTIVE) {
-		dcon_bus_stabilize(client, 0);
-		dcon_set_source(DCON_SOURCE_CPU);
+	struct dcon_priv *dcon = i2c_get_clientdata(client);
+
+	if (!dcon->asleep) {
+		dcon_bus_stabilize(dcon, 0);
+		dcon_set_source(dcon, DCON_SOURCE_CPU);
 	}
 
 	return 0;
@@ -781,8 +769,9 @@ static int dcon_resume(struct i2c_client *client)
 #endif
 
 
-static irqreturn_t dcon_interrupt(int irq, void *id)
+irqreturn_t dcon_interrupt(int irq, void *id)
 {
+	struct dcon_priv *dcon = id;
 	int status = pdata->read_status();
 
 	if (status == -1)
@@ -795,8 +784,8 @@ static irqreturn_t dcon_interrupt(int irq, void *id)
 
 	case 2:	/* switch to DCON mode */
 	case 1: /* switch to CPU mode */
-		dcon_switched = 1;
-		getnstimeofday(&dcon_irq_time);
+		dcon->switched = true;
+		getnstimeofday(&dcon->irq_time);
 		wake_up(&dcon_wait_queue);
 		break;
 
@@ -808,9 +797,9 @@ static irqreturn_t dcon_interrupt(int irq, void *id)
 		 * of the DCON happened long before this point.
 		 * see http://dev.laptop.org/ticket/9869
 		 */
-		if (dcon_source != dcon_pending && !dcon_switched) {
-			dcon_switched = 1;
-			getnstimeofday(&dcon_irq_time);
+		if (dcon->curr_src != dcon->pending_src && !dcon->switched) {
+			dcon->switched = true;
+			getnstimeofday(&dcon->irq_time);
 			wake_up(&dcon_wait_queue);
 			printk(KERN_DEBUG "olpc-dcon: switching w/ status 0/0\n");
 		} else {
@@ -821,14 +810,14 @@ static irqreturn_t dcon_interrupt(int irq, void *id)
 	return IRQ_HANDLED;
 }
 
-static struct i2c_device_id dcon_idtable[] = {
+static const struct i2c_device_id dcon_idtable[] = {
 	{ "olpc_dcon",  0 },
 	{ }
 };
 
 MODULE_DEVICE_TABLE(i2c, dcon_idtable);
 
-static struct i2c_driver dcon_driver = {
+struct i2c_driver dcon_driver = {
 	.driver = {
 		.name	= "olpc_dcon",
 	},
@@ -844,14 +833,19 @@ static struct i2c_driver dcon_driver = {
 #endif
 };
 
-#include "olpc_dcon_xo_1.c"
-
 static int __init olpc_dcon_init(void)
 {
-	pdata = &dcon_pdata_xo_1;
+#ifdef CONFIG_FB_OLPC_DCON_1_5
+	/* XO-1.5 */
+	if (olpc_board_at_least(olpc_board(0xd0)))
+		pdata = &dcon_pdata_xo_1_5;
+#endif
+#ifdef CONFIG_FB_OLPC_DCON_1
+	if (!pdata)
+		pdata = &dcon_pdata_xo_1;
+#endif
 
-	i2c_add_driver(&dcon_driver);
-	return 0;
+	return i2c_add_driver(&dcon_driver);
 }
 
 static void __exit olpc_dcon_exit(void)
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
index e566d21..0264c94 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ b/drivers/staging/olpc_dcon/olpc_dcon.h
@@ -1,6 +1,9 @@
 #ifndef OLPC_DCON_H_
 #define OLPC_DCON_H_
 
+#include <linux/notifier.h>
+#include <linux/workqueue.h>
+
 /* DCON registers */
 
 #define DCON_REG_ID		 0
@@ -41,15 +44,59 @@
 #define DCON_SOURCE_DCON        0
 #define DCON_SOURCE_CPU         1
 
-/* Output values */
-#define DCON_OUTPUT_COLOR       0
-#define DCON_OUTPUT_MONO        1
-
-/* Sleep values */
-#define DCON_ACTIVE             0
-#define DCON_SLEEP              1
-
 /* Interrupt */
 #define DCON_IRQ                6
 
+struct dcon_priv {
+	struct i2c_client *client;
+	struct fb_info *fbinfo;
+	struct backlight_device *bl_dev;
+
+	struct work_struct switch_source;
+	struct notifier_block reboot_nb;
+	struct notifier_block fbevent_nb;
+
+	/* Shadow register for the DCON_REG_MODE register */
+	u8 disp_mode;
+
+	/* The current backlight value - this saves us some smbus traffic */
+	u8 bl_val;
+
+	/* Current source, initialized at probe time */
+	int curr_src;
+
+	/* Desired source */
+	int pending_src;
+
+	/* Variables used during switches */
+	bool switched;
+	struct timespec irq_time;
+	struct timespec load_time;
+
+	/* Current output type; true == mono, false == color */
+	bool mono;
+	bool asleep;
+	/* This get set while controlling fb blank state from the driver */
+	bool ignore_fb_events;
+};
+
+struct dcon_platform_data {
+	int (*init)(struct dcon_priv *);
+	void (*bus_stabilize_wiggle)(void);
+	void (*set_dconload)(int);
+	u8 (*read_status)(void);
+};
+
+#include <linux/interrupt.h>
+
+extern irqreturn_t dcon_interrupt(int irq, void *id);
+
+#ifdef CONFIG_FB_OLPC_DCON_1
+extern struct dcon_platform_data dcon_pdata_xo_1;
+#endif
+
+#ifdef CONFIG_FB_OLPC_DCON_1_5
+extern struct dcon_platform_data dcon_pdata_xo_1_5;
+#endif
+
 #endif
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
index 043198d..b154be7 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
@@ -16,7 +16,7 @@
 
 #include "olpc_dcon.h"
 
-static int dcon_init_xo_1(void)
+static int dcon_init_xo_1(struct dcon_priv *dcon)
 {
 	unsigned char lob;
 
@@ -54,10 +54,10 @@ static int dcon_init_xo_1(void)
 	 * then a value is set.  So, future readings of the pin can use
 	 * READ_BACK, but the first one cannot.  Awesome, huh?
 	 */
-	dcon_source = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
+	dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
 		? DCON_SOURCE_CPU
 		: DCON_SOURCE_DCON;
-	dcon_pending = dcon_source;
+	dcon->pending_src = dcon->curr_src;
 
 	/* Set the directions for the GPIO pins */
 	gpio_direction_input(OLPC_GPIO_DCON_STAT0);
@@ -65,7 +65,7 @@ static int dcon_init_xo_1(void)
 	gpio_direction_input(OLPC_GPIO_DCON_IRQ);
 	gpio_direction_input(OLPC_GPIO_DCON_BLANK);
 	gpio_direction_output(OLPC_GPIO_DCON_LOAD,
-			dcon_source == DCON_SOURCE_CPU);
+			dcon->curr_src == DCON_SOURCE_CPU);
 
 	/* Set up the interrupt mappings */
 
@@ -81,7 +81,7 @@ static int dcon_init_xo_1(void)
 	outb(lob, 0x4d0);
 
 	/* Register the interupt handler */
-	if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", &dcon_driver)) {
+	if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) {
 		printk(KERN_ERR "olpc-dcon: failed to request DCON's irq\n");
 		goto err_req_irq;
 	}
@@ -195,7 +195,7 @@ static u8 dcon_read_status_xo_1(void)
 	return status;
 }
 
-static struct dcon_platform_data dcon_pdata_xo_1 = {
+struct dcon_platform_data dcon_pdata_xo_1 = {
 	.init = dcon_init_xo_1,
 	.bus_stabilize_wiggle = dcon_wiggle_xo_1,
 	.set_dconload = dcon_set_dconload_1,
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
index 4f56098..e213b63 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
+++ b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
@@ -7,22 +7,32 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+#include <asm/olpc.h>
+
+/* TODO: this eventually belongs in linux/vx855.h */
+#define NR_VX855_GPI    14
+#define NR_VX855_GPO    13
+#define NR_VX855_GPIO   15
+
+#define VX855_GPI(n)    (n)
+#define VX855_GPO(n)    (NR_VX855_GPI + (n))
+#define VX855_GPIO(n)   (NR_VX855_GPI + NR_VX855_GPO + (n))
+
+#include "olpc_dcon.h"
 
 /* Hardware setup on the XO 1.5:
  * 	DCONLOAD connects to
- *		VX855_GPO12 (not nCR_PWOFF)   (rev A)
- *		VX855_GPIO1 (not SMBCK2)      (rev B)
+ *		VX855_GPIO1 (not SMBCK2)
  * 	DCONBLANK connects to VX855_GPIO8 (not SSPICLK)  unused in driver
  *	DCONSTAT0 connects to VX855_GPI10 (not SSPISDI)
  *	DCONSTAT1 connects to VX855_GPI11 (not nSSPISS)
- *	DCONIRQ connects to VX855_GPIO12 (on B3.  on B2, it goes to
- *		SMBALRT, which doesn't work.)
+ *	DCONIRQ connects to VX855_GPIO12
  *	DCONSMBDATA connects to VX855 graphics CRTSPD
  *	DCONSMBCLK connects to VX855 graphics CRTSPCLK
  */
 
-#define TEST_B2 0   // define to test B3 paths on a modded B2 board
-
 #define VX855_GENL_PURPOSE_OUTPUT 0x44c // PMIO_Rx4c-4f
 #define VX855_GPI_STATUS_CHG 0x450  // PMIO_Rx50
 #define VX855_GPI_SCI_SMI 0x452  // PMIO_Rx52
@@ -30,39 +40,24 @@
 
 #define PREFIX "OLPC DCON:"
 
-/*
-  there is no support here for DCONIRQ on 1.5 boards earlier than
-  B3.  the issue is that the DCONIRQ signal on earlier boards is
-  routed to SMBALRT, which turns out to to be a level sensitive
-  interrupt.  the DCONIRQ signal is far too short (11usec) to
-  be detected reliably in that case.  including support for
-  DCONIRQ functions no better than none at all.
-*/
-
-static struct dcon_platform_data dcon_pdata_xo_1_5;
-
 static void dcon_clear_irq(void)
 {
-	if (TEST_B2 || olpc_board_at_least(olpc_board(BOARD_XO_1_5_B3))) {
-		// irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12
-		outb(BIT_GPIO12, VX855_GPI_STATUS_CHG);
-	}
+	/* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */
+	outb(BIT_GPIO12, VX855_GPI_STATUS_CHG);
 }
 
 static int dcon_was_irq(void)
 {
 	u_int8_t tmp;
 
-	if (TEST_B2 || olpc_board_at_least(olpc_board(BOARD_XO_1_5_B3))) {
-		// irq status will appear in PMIO_Rx50[6] on gpio12
-		tmp = inb(VX855_GPI_STATUS_CHG);
-		return !!(tmp & BIT_GPIO12);
-	}
+	/* irq status will appear in PMIO_Rx50[6] on gpio12 */
+	tmp = inb(VX855_GPI_STATUS_CHG);
+	return !!(tmp & BIT_GPIO12);
 
 	return 0;
 }
 
-static int dcon_init_xo_1_5(void)
+static int dcon_init_xo_1_5(struct dcon_priv *dcon)
 {
 	unsigned int irq;
 	u_int8_t tmp;
@@ -76,14 +71,8 @@ static int dcon_init_xo_1_5(void)
 		return 1;
 	}
 
-	if (olpc_board_at_least(olpc_board(BOARD_XO_1_5_B1))) {
-		pci_read_config_byte(pdev, 0x95, &tmp);
-		pci_write_config_byte(pdev, 0x95, tmp|0x0c);
-	} else {
-		/* Set GPO12 to GPO mode, not nCR_PWOFF */
-		pci_read_config_byte(pdev, 0x9b, &tmp);
-		pci_write_config_byte(pdev, 0x9b, tmp|0x01);
-	}
+	pci_read_config_byte(pdev, 0x95, &tmp);
+	pci_write_config_byte(pdev, 0x95, tmp|0x0c);
 
 	/* Set GPIO8 to GPIO mode, not SSPICLK */
 	pci_read_config_byte(pdev, 0xe3, &tmp);
@@ -93,43 +82,33 @@ static int dcon_init_xo_1_5(void)
 	pci_read_config_byte(pdev, 0xe4, &tmp);
 	pci_write_config_byte(pdev, 0xe4, tmp|0x08);
 
-	if (TEST_B2 || olpc_board_at_least(olpc_board(BOARD_XO_1_5_B3))) {
-		// clear PMU_RxE1[6] to select SCI on GPIO12
-		// clear PMU_RxE0[6] to choose falling edge
-		pci_read_config_byte(pdev, 0xe1, &tmp);
-		pci_write_config_byte(pdev, 0xe1, tmp & ~BIT_GPIO12);
-		pci_read_config_byte(pdev, 0xe0, &tmp);
-		pci_write_config_byte(pdev, 0xe0, tmp & ~BIT_GPIO12);
+	/* clear PMU_RxE1[6] to select SCI on GPIO12 */
+	/* clear PMU_RxE0[6] to choose falling edge */
+	pci_read_config_byte(pdev, 0xe1, &tmp);
+	pci_write_config_byte(pdev, 0xe1, tmp & ~BIT_GPIO12);
+	pci_read_config_byte(pdev, 0xe0, &tmp);
+	pci_write_config_byte(pdev, 0xe0, tmp & ~BIT_GPIO12);
 
-		dcon_clear_irq();
+	dcon_clear_irq();
 
-		// set   PMIO_Rx52[6] to enable SCI/SMI on gpio12
-		outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI);
-
-	}
+	/* set   PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
+	outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI);
 
 	/* Determine the current state of DCONLOAD, likely set by firmware */
-	if (olpc_board_at_least(olpc_board(BOARD_XO_1_5_B1))) {
-		// GPIO1
-		dcon_source = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
-			DCON_SOURCE_CPU : DCON_SOURCE_DCON;
-	} else {
-		// GPO12
-		dcon_source = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x04000000) ?
+	/* GPIO1 */
+	dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
 			DCON_SOURCE_CPU : DCON_SOURCE_DCON;
-	}
-	dcon_pending = dcon_source;
+	dcon->pending_src = dcon->curr_src;
 
 	pci_dev_put(pdev);
 
 	/* we're sharing the IRQ with ACPI */
 	irq = acpi_gbl_FADT.sci_interrupt;
-	if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", &dcon_driver)) {
+	if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
 		printk(KERN_ERR PREFIX "DCON (IRQ%d) allocation failed\n", irq);
 		return 1;
 	}
 
-
 	return 0;
 }
 
@@ -180,19 +159,13 @@ static void dcon_wiggle_xo_1_5(void)
 	}
 	udelay(5);
 
-	if (TEST_B2 || olpc_board_at_least(olpc_board(BOARD_XO_1_5_B3))) {
-		// set   PMIO_Rx52[6] to enable SCI/SMI on gpio12
-		outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI);
-	}
+	/* set   PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
+	outb(inb(VX855_GPI_SCI_SMI)|BIT_GPIO12, VX855_GPI_SCI_SMI);
 }
 
 static void dcon_set_dconload_xo_1_5(int val)
 {
-	if (olpc_board_at_least(olpc_board(BOARD_XO_1_5_B1))) {
-		gpio_set_value(VX855_GPIO(1), val);
-	} else {
-		gpio_set_value(VX855_GPO(12), val);
-	}
+	gpio_set_value(VX855_GPIO(1), val);
 }
 
 static u8 dcon_read_status_xo_1_5(void)
@@ -211,7 +184,7 @@ static u8 dcon_read_status_xo_1_5(void)
 	return status;
 }
 
-static struct dcon_platform_data dcon_pdata_xo_1_5 = {
+struct dcon_platform_data dcon_pdata_xo_1_5 = {
 	.init = dcon_init_xo_1_5,
 	.bus_stabilize_wiggle = dcon_wiggle_xo_1_5,
 	.set_dconload = dcon_set_dconload_xo_1_5,
diff --git a/drivers/staging/pohmelfs/config.c b/drivers/staging/pohmelfs/config.c
index 89279ba..b6c42cb 100644
--- a/drivers/staging/pohmelfs/config.c
+++ b/drivers/staging/pohmelfs/config.c
@@ -134,7 +134,7 @@ int pohmelfs_copy_config(struct pohmelfs_sb *psb)
 		goto out_unlock;
 
 	/*
-	 * Run over all entries in given config group and try to crate and
+	 * Run over all entries in given config group and try to create and
 	 * initialize those, which do not exist in superblock list.
 	 * Skip all existing entries.
 	 */
@@ -525,7 +525,7 @@ static void pohmelfs_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *n
 {
 	int err;
 
-	if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+	if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
 		return;
 
 	switch (msg->flags) {
@@ -601,11 +601,9 @@ void pohmelfs_config_exit(void)
 
 		list_del(&g->group_entry);
 
-		if (g->hash_string)
-			kfree(g->hash_string);
+		kfree(g->hash_string);
 
-		if (g->cipher_string)
-			kfree(g->cipher_string);
+		kfree(g->cipher_string);
 
 		kfree(g);
 	}
diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c
index 059e9d2..9732a96 100644
--- a/drivers/staging/pohmelfs/dir.c
+++ b/drivers/staging/pohmelfs/dir.c
@@ -1082,7 +1082,6 @@ err_out_exit:
 
 	clear_bit(NETFS_INODE_REMOTE_SYNCED, &pi->state);
 
-	mutex_unlock(&inode->i_mutex);
 	return err;
 }
 
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 56d3a4e..c93ef207 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -834,7 +834,7 @@ static void pohmelfs_i_callback(struct rcu_head *head)
 }
 
 /*
- * ->detroy_inode() callback. Deletes inode from the caches
+ * ->destroy_inode() callback. Deletes inode from the caches
  *  and frees private data.
  */
 static void pohmelfs_destroy_inode(struct inode *inode)
@@ -1127,18 +1127,18 @@ static ssize_t pohmelfs_getxattr(struct dentry *dentry, const char *name,
 
 		/*
 		 * This loop is a bit ugly, since it waits until reference counter
-		 * hits 1 and then put object here. Main goal is to prevent race with
-		 * network thread, when it can start processing given request, i.e.
+		 * hits 1 and then puts the object here. Main goal is to prevent race with
+		 * the network thread, when it can start processing the given request, i.e.
 		 * increase its reference counter but yet not complete it, while
 		 * we will exit from ->getxattr() with timeout, and although request
 		 * will not be freed (its reference counter was increased by network
 		 * thread), data pointer provided by user may be released, so we will
-		 * overwrite already freed area in network thread.
+		 * overwrite an already freed area in the network thread.
 		 *
 		 * Now after timeout we remove request from the cache, so it can not be
 		 * found by network thread, and wait for its reference counter to hit 1,
 		 * i.e. if network thread already started to process this request, we wait
-		 * it to finish, and then free object locally. If reference counter is
+		 * for it to finish, and then free object locally. If reference counter is
 		 * already 1, i.e. request is not used by anyone else, we can free it without
 		 * problem.
 		 */
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
index 63391d2..985b6b7 100644
--- a/drivers/staging/pohmelfs/netfs.h
+++ b/drivers/staging/pohmelfs/netfs.h
@@ -191,7 +191,7 @@ enum {
 /*
  * POHMELFS capabilities: information about supported
  * crypto operations (hash/cipher, modes, key sizes and so on),
- * root informaion (used/available size, number of objects, permissions)
+ * root information (used/available size, number of objects, permissions)
  */
 enum pohmelfs_capabilities {
 	POHMELFS_CRYPTO_CAPABILITIES = 0,
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
index ed58f48..c45b09e 100644
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ b/drivers/staging/quatech_usb2/quatech_usb2.c
@@ -852,7 +852,7 @@ static int qt2_chars_in_buffer(struct tty_struct *tty)
  * TIOCMGET and TIOCMSET are filtered off to their own methods before they get
  * here, so we don't have to handle them.
  */
-static int qt2_ioctl(struct tty_struct *tty, struct file *file,
+static int qt2_ioctl(struct tty_struct *tty,
 		     unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -1078,7 +1078,7 @@ static void qt2_set_termios(struct tty_struct *tty,
 	}
 }
 
-static int qt2_tiocmget(struct tty_struct *tty, struct file *file)
+static int qt2_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
@@ -1121,7 +1121,7 @@ static int qt2_tiocmget(struct tty_struct *tty, struct file *file)
 	}
 }
 
-static int qt2_tiocmset(struct tty_struct *tty, struct file *file,
+static int qt2_tiocmset(struct tty_struct *tty,
 		       unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -1221,7 +1221,7 @@ static void qt2_throttle(struct tty_struct *tty)
 	}
 	/* Send command to box to stop receiving stuff. This will stop this
 	 * particular UART from filling the endpoint - in the multiport case the
-	 * FPGA UART will handle any flow control implmented, but for the single
+	 * FPGA UART will handle any flow control implemented, but for the single
 	 * port it's handed differently and we just quit submitting urbs
 	 */
 	if (serial->dev->descriptor.idProduct != QUATECH_SSU2_100)
diff --git a/drivers/staging/quickstart/quickstart.c b/drivers/staging/quickstart/quickstart.c
index d83bec8..c60911c 100644
--- a/drivers/staging/quickstart/quickstart.c
+++ b/drivers/staging/quickstart/quickstart.c
@@ -5,7 +5,7 @@
  *  Copyright (C) 2007-2010 Angelo Arrifano <miknix@gmail.com>
  *
  *  Information gathered from disassebled dsdt and from here:
- *  <http://www.microsoft.com/whdc/system/platform/firmware/DirAppLaunch.mspx> 
+ *  <http://www.microsoft.com/whdc/system/platform/firmware/DirAppLaunch.mspx>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -141,7 +141,8 @@ static ssize_t pressed_button_show(struct device *dev,
 					char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%s\n",
-		(quickstart_data.pressed?quickstart_data.pressed->name:"none"));
+			(quickstart_data.pressed ?
+			 quickstart_data.pressed->name : "none"));
 }
 
 
diff --git a/drivers/staging/rt2860/common/ba_action.c b/drivers/staging/rt2860/common/ba_action.c
index b046c2b..62f6f6b 100644
--- a/drivers/staging/rt2860/common/ba_action.c
+++ b/drivers/staging/rt2860/common/ba_action.c
@@ -107,7 +107,7 @@ void Announce_Reordering_Packet(struct rt_rtmp_adapter *pAd,
 
 	if (mpdu->bAMSDU) {
 		ASSERT(0);
-		BA_Reorder_AMSDU_Annnounce(pAd, pPacket);
+		BA_Reorder_AMSDU_Announce(pAd, pPacket);
 	} else {
 		/* */
 		/* pass this 802.3 packet to upper layer or forward this packet to WM directly */
diff --git a/drivers/staging/rt2860/common/cmm_data.c b/drivers/staging/rt2860/common/cmm_data.c
index 2204c2b..f6c193c 100644
--- a/drivers/staging/rt2860/common/cmm_data.c
+++ b/drivers/staging/rt2860/common/cmm_data.c
@@ -1481,7 +1481,7 @@ u32 deaggregate_AMSDU_announce(struct rt_rtmp_adapter *pAd,
 	return nMSDU;
 }
 
-u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket)
+u32 BA_Reorder_AMSDU_Announce(struct rt_rtmp_adapter *pAd, void *pPacket)
 {
 	u8 *pData;
 	u16 DataSize;
diff --git a/drivers/staging/rt2860/common/cmm_mac_pci.c b/drivers/staging/rt2860/common/cmm_mac_pci.c
index 850f0fb..21eed25 100644
--- a/drivers/staging/rt2860/common/cmm_mac_pci.c
+++ b/drivers/staging/rt2860/common/cmm_mac_pci.c
@@ -753,7 +753,7 @@ BOOLEAN AsicCheckCommanOk(struct rt_rtmp_adapter *pAd, u8 Command)
 
 	/* This command's status is at the same position as command. So AND command position's bitmask to read status. */
 	if (i < 200) {
-		/* If Status is 1, the comamnd is success. */
+		/* If Status is 1, the command is success. */
 		if (((CmdStatus & ThisCIDMask) == 0x1)
 		    || ((CmdStatus & ThisCIDMask) == 0x100)
 		    || ((CmdStatus & ThisCIDMask) == 0x10000)
diff --git a/drivers/staging/rt2860/common/spectrum.c b/drivers/staging/rt2860/common/spectrum.c
index 1dfb802..c0d2f42 100644
--- a/drivers/staging/rt2860/common/spectrum.c
+++ b/drivers/staging/rt2860/common/spectrum.c
@@ -416,8 +416,7 @@ void MeasureReqTabExit(struct rt_rtmp_adapter *pAd)
 {
 	NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock);
 
-	if (pAd->CommonCfg.pMeasureReqTab)
-		kfree(pAd->CommonCfg.pMeasureReqTab);
+	kfree(pAd->CommonCfg.pMeasureReqTab);
 	pAd->CommonCfg.pMeasureReqTab = NULL;
 
 	return;
@@ -614,8 +613,7 @@ void TpcReqTabExit(struct rt_rtmp_adapter *pAd)
 {
 	NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock);
 
-	if (pAd->CommonCfg.pTpcReqTab)
-		kfree(pAd->CommonCfg.pTpcReqTab);
+	kfree(pAd->CommonCfg.pTpcReqTab);
 	pAd->CommonCfg.pTpcReqTab = NULL;
 
 	return;
diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
index 728864e..e5b0427 100644
--- a/drivers/staging/rt2860/rt_linux.c
+++ b/drivers/staging/rt2860/rt_linux.c
@@ -118,8 +118,7 @@ void RTMP_OS_Mod_Timer(struct timer_list *pTimer,
 	mod_timer(pTimer, jiffies + timeout);
 }
 
-void RTMP_OS_Del_Timer(struct timer_list *pTimer,
-		       OUT BOOLEAN * pCancelled)
+void RTMP_OS_Del_Timer(struct timer_list *pTimer, OUT BOOLEAN *pCancelled)
 {
 	if (timer_pending(pTimer)) {
 		*pCancelled = del_timer_sync(pTimer);
@@ -242,8 +241,7 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
 
 	os_cookie = (struct os_cookie *)pAd->OS_Cookie;
 
-	if (pAd->BeaconBuf)
-		kfree(pAd->BeaconBuf);
+	kfree(pAd->BeaconBuf);
 
 	NdisFreeSpinLock(&pAd->MgmtRingLock);
 
@@ -265,8 +263,7 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
 	release_firmware(pAd->firmware);
 
 	vfree(pAd);		/* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
-	if (os_cookie)
-		kfree(os_cookie);
+	kfree(os_cookie);
 }
 
 BOOLEAN OS_Need_Clone_Packet(void)
diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h
index 92ff543..3efb88f 100644
--- a/drivers/staging/rt2860/rt_linux.h
+++ b/drivers/staging/rt2860/rt_linux.h
@@ -102,8 +102,8 @@ extern const struct iw_handler_def rt28xx_iw_handler_def;
 /***********************************************************************************
  *	OS Specific definitions and data structures
  ***********************************************************************************/
-typedef int (*HARD_START_XMIT_FUNC) (struct sk_buff * skb,
-				     struct net_device * net_dev);
+typedef int (*HARD_START_XMIT_FUNC) (struct sk_buff *skb,
+				     struct net_device *net_dev);
 
 #ifdef RTMP_MAC_PCI
 #ifndef PCI_DEVICE
@@ -366,7 +366,7 @@ typedef void (*TIMER_FUNCTION) (unsigned long);
 
 #define ONE_TICK 1
 
-static inline void NdisGetSystemUpTime(unsigned long * time)
+static inline void NdisGetSystemUpTime(unsigned long *time)
 {
 	*time = jiffies;
 }
@@ -815,7 +815,7 @@ void linux_pci_unmap_single(struct rt_rtmp_adapter *pAd, dma_addr_t dma_addr,
 /***********************************************************************************
  *	Other function prototypes definitions
  ***********************************************************************************/
-void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time);
+void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time);
 int rt28xx_packet_xmit(struct sk_buff *skb);
 
 #ifdef RTMP_MAC_PCI
@@ -827,8 +827,8 @@ IRQ_HANDLE_TYPE rt2860_interrupt(int irq, void *dev_instance);
 
 int rt28xx_sta_ioctl(struct net_device *net_dev, IN OUT struct ifreq *rq, int cmd);
 
-extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char * buf);
-extern int ra_mtd_read(int num, loff_t from, size_t len, u_char * buf);
+extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf);
+extern int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf);
 
 #define GET_PAD_FROM_NET_DEV(_pAd, _net_dev)	(_pAd) = (struct rt_rtmp_adapter *)(_net_dev)->ml_priv;
 
diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h
index 70daaa4..d16b06a 100644
--- a/drivers/staging/rt2860/rtmp.h
+++ b/drivers/staging/rt2860/rtmp.h
@@ -3611,7 +3611,7 @@ struct rt_rtmp_sg_list *rt_get_sg_list_from_packet(void *pPacket,
 
 void announce_802_3_packet(struct rt_rtmp_adapter *pAd, void *pPacket);
 
-u32 BA_Reorder_AMSDU_Annnounce(struct rt_rtmp_adapter *pAd, void *pPacket);
+u32 BA_Reorder_AMSDU_Announce(struct rt_rtmp_adapter *pAd, void *pPacket);
 
 struct net_device *get_netdev_from_bssid(struct rt_rtmp_adapter *pAd, u8 FromWhichBSSID);
 
diff --git a/drivers/staging/rt2860/wpa.h b/drivers/staging/rt2860/wpa.h
index 116fc2c..a7796d3 100644
--- a/drivers/staging/rt2860/wpa.h
+++ b/drivers/staging/rt2860/wpa.h
@@ -369,19 +369,15 @@ struct PACKED rt_rsn_capability {
 /*========================================
 	The prototype is defined in cmm_wpa.c
   ========================================*/
-BOOLEAN WpaMsgTypeSubst(u8 EAPType, int * MsgType);
+BOOLEAN WpaMsgTypeSubst(u8 EAPType, int *MsgType);
 
-void PRF(u8 * key,
-	 int key_len,
-	 u8 * prefix,
-	 int prefix_len,
-	 u8 * data, int data_len, u8 * output, int len);
+void PRF(u8 *key, int key_len, u8 *prefix, int prefix_len,
+	 u8 *data, int data_len, u8 *output, int len);
 
 int PasswordHash(char *password,
 		 unsigned char *ssid, int ssidlength, unsigned char *output);
 
-u8 *GetSuiteFromRSNIE(u8 *rsnie,
-			 u32 rsnie_len, u8 type, u8 * count);
+u8 *GetSuiteFromRSNIE(u8 *rsnie, u32 rsnie_len, u8 type, u8 *count);
 
 void WpaShowAllsuite(u8 *rsnie, u32 rsnie_len);
 
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index 652d879..771e019 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -1435,8 +1435,9 @@ static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
 
 		if(*(t++) == MFIE_TYPE_CHALLENGE){
 			*chlen = *(t++);
-			*challenge = kmalloc(*chlen, GFP_ATOMIC);
-			memcpy(*challenge, t, *chlen);
+			*challenge = kmemdup(t, *chlen, GFP_ATOMIC);
+			if (!*challenge)
+				return -ENOMEM;
 		}
 	}
 
@@ -2604,8 +2605,7 @@ void ieee80211_softmac_free(struct ieee80211_device *ieee)
 	cancel_delayed_work(&ieee->GPIOChangeRFWorkItem);
 
 	destroy_workqueue(ieee->wq);
-	if(NULL != ieee->pDot11dInfo)
-		kfree(ieee->pDot11dInfo);
+	kfree(ieee->pDot11dInfo);
 	up(&ieee->wx_sem);
 }
 
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
index 07d8dbc..ca414a9 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
@@ -735,7 +735,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
 		ieee->wpa_ie_len = len;
 	}
 	else{
-		if (ieee->wpa_ie)
 		kfree(ieee->wpa_ie);
 		ieee->wpa_ie = NULL;
 		ieee->wpa_ie_len = 0;
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 3bec1a4..106ebcf 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -41,16 +41,11 @@ typedef struct _RT_DOT11D_INFO {
 	DOT11D_STATE State;
 } RT_DOT11D_INFO, *PRT_DOT11D_INFO;
 
-static inline bool eqMacAddr(u8 *a, u8 *b)
+static inline void cpMacAddr(unsigned char *des, unsigned char *src)
 {
-	return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] &&
-	       a[3] == b[3] && a[4] == b[4] && a[5] == b[5];
+	memcpy(des, src, 6);
 }
 
-#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], \
-			(des)[2] = (src)[2], (des)[3] = (src)[3], \
-			(des)[4] = (src)[4], (des)[5] = (src)[5])
-
 #define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO) \
 			((__pIeeeDev)->pDot11dInfo))
 
diff --git a/drivers/staging/rtl8192e/ieee80211.h b/drivers/staging/rtl8192e/ieee80211.h
deleted file mode 100644
index 16298e0..0000000
--- a/drivers/staging/rtl8192e/ieee80211.h
+++ /dev/null
@@ -1,2683 +0,0 @@
-/*
- * Merged with mainline ieee80211.h in Aug 2004.  Original ieee802_11
- * remains copyright by the original authors
- *
- * Portions of the merged code are based on Host AP (software wireless
- * LAN access point) driver for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- * Copyright (c) 2004, Intel Corporation
- *
- * Modified for Realtek's wi-fi cards by Andrea Merello
- * <andreamrl@tiscali.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. See README and COPYING for
- * more details.
- */
-#ifndef IEEE80211_H
-#define IEEE80211_H
-#include <linux/if_ether.h> /* ETH_ALEN */
-#include <linux/kernel.h>   /* ARRAY_SIZE */
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-
-#include <linux/delay.h>
-#include <linux/wireless.h>
-
-#include "ieee80211/rtl819x_HT.h"
-#include "ieee80211/rtl819x_BA.h"
-#include "ieee80211/rtl819x_TS.h"
-
-#ifndef IW_MODE_MONITOR
-#define IW_MODE_MONITOR 6
-#endif
-
-#ifndef IWEVCUSTOM
-#define IWEVCUSTOM 0x8c02
-#endif
-
-#ifndef container_of
-/**
- * container_of - cast a member of a structure out to the containing structure
- *
- * @ptr:        the pointer to the member.
- * @type:       the type of the container struct this is embedded in.
- * @member:     the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({                      \
-        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-        (type *)( (char *)__mptr - offsetof(type,member) );})
-#endif
-
-#define KEY_TYPE_NA		0x0
-#define KEY_TYPE_WEP40 		0x1
-#define KEY_TYPE_TKIP		0x2
-#define KEY_TYPE_CCMP		0x4
-#define KEY_TYPE_WEP104		0x5
-
-/* added for rtl819x tx procedure */
-#define MAX_QUEUE_SIZE		0x10
-
-//
-// 8190 queue mapping
-//
-#define BK_QUEUE                               0
-#define BE_QUEUE                               1
-#define VI_QUEUE                               2
-#define VO_QUEUE                               3
-#define HCCA_QUEUE                             4
-#define TXCMD_QUEUE                            5
-#define MGNT_QUEUE                             6
-#define HIGH_QUEUE                             7
-#define BEACON_QUEUE                           8
-
-#define LOW_QUEUE                              BE_QUEUE
-#define NORMAL_QUEUE                           MGNT_QUEUE
-
-//added by amy for ps
-#define SWRF_TIMEOUT				50
-
-//added by amy for LEAP related
-#define IE_CISCO_FLAG_POSITION		0x08	// Flag byte: byte 8, numbered from 0.
-#define SUPPORT_CKIP_MIC			0x08	// bit3
-#define SUPPORT_CKIP_PK			0x10	// bit4
-/* defined for skb cb field */
-/* At most 28 byte */
-typedef struct cb_desc {
-        /* Tx Desc Related flags (8-9) */
-	u8 bLastIniPkt:1;
-	u8 bCmdOrInit:1;
-        u8 bFirstSeg:1;
-        u8 bLastSeg:1;
-        u8 bEncrypt:1;
-        u8 bTxDisableRateFallBack:1;
-        u8 bTxUseDriverAssingedRate:1;
-        u8 bHwSec:1; //indicate whether use Hw security. WB
-
-        u8 reserved1;
-
-        /* Tx Firmware Relaged flags (10-11)*/
-        u8 bCTSEnable:1;
-        u8 bRTSEnable:1;
-        u8 bUseShortGI:1;
-        u8 bUseShortPreamble:1;
-        u8 bTxEnableFwCalcDur:1;
-        u8 bAMPDUEnable:1;
-        u8 bRTSSTBC:1;
-        u8 RTSSC:1;
-
-        u8 bRTSBW:1;
-        u8 bPacketBW:1;
-	u8 bRTSUseShortPreamble:1;
-	u8 bRTSUseShortGI:1;
-	u8 bMulticast:1;
-	u8 bBroadcast:1;
-        //u8 reserved2:2;
-        u8 drv_agg_enable:1;
-        u8 reserved2:1;
-
-        /* Tx Desc related element(12-19) */
-        u8 rata_index;
-        u8 queue_index;
-        //u8 reserved3;
-        //u8 reserved4;
-        u16 txbuf_size;
-        //u8 reserved5;
-	u8 RATRIndex;
-        u8 reserved6;
-        u8 reserved7;
-        u8 reserved8;
-
-        /* Tx firmware related element(20-27) */
-        u8 data_rate;
-        u8 rts_rate;
-        u8 ampdu_factor;
-        u8 ampdu_density;
-        //u8 reserved9;
-        //u8 reserved10;
-        //u8 reserved11;
-        u8 DrvAggrNum;
-	u16 pkt_size;
-        u8 reserved12;
-}cb_desc, *pcb_desc;
-
-/*--------------------------Define -------------------------------------------*/
-#define MGN_1M                  0x02
-#define MGN_2M                  0x04
-#define MGN_5_5M                0x0b
-#define MGN_11M                 0x16
-
-#define MGN_6M                  0x0c
-#define MGN_9M                  0x12
-#define MGN_12M                 0x18
-#define MGN_18M                 0x24
-#define MGN_24M                 0x30
-#define MGN_36M                 0x48
-#define MGN_48M                 0x60
-#define MGN_54M                 0x6c
-
-#define MGN_MCS0                0x80
-#define MGN_MCS1                0x81
-#define MGN_MCS2                0x82
-#define MGN_MCS3                0x83
-#define MGN_MCS4                0x84
-#define MGN_MCS5                0x85
-#define MGN_MCS6                0x86
-#define MGN_MCS7                0x87
-#define MGN_MCS8                0x88
-#define MGN_MCS9                0x89
-#define MGN_MCS10               0x8a
-#define MGN_MCS11               0x8b
-#define MGN_MCS12               0x8c
-#define MGN_MCS13               0x8d
-#define MGN_MCS14               0x8e
-#define MGN_MCS15               0x8f
-
-//----------------------------------------------------------------------------
-//		802.11 Management frame Reason Code field
-//----------------------------------------------------------------------------
-enum	_ReasonCode{
-	unspec_reason	= 0x1,
-	auth_not_valid	= 0x2,
-	deauth_lv_ss	= 0x3,
-	inactivity		= 0x4,
-	ap_overload 	= 0x5,
-	class2_err		= 0x6,
-	class3_err		= 0x7,
-	disas_lv_ss 	= 0x8,
-	asoc_not_auth	= 0x9,
-
-	//----MIC_CHECK
-	mic_failure 	= 0xe,
-	//----END MIC_CHECK
-
-	// Reason code defined in 802.11i D10.0 p.28.
-	invalid_IE		= 0x0d,
-	four_way_tmout	= 0x0f,
-	two_way_tmout	= 0x10,
-	IE_dismatch 	= 0x11,
-	invalid_Gcipher = 0x12,
-	invalid_Pcipher = 0x13,
-	invalid_AKMP	= 0x14,
-	unsup_RSNIEver = 0x15,
-	invalid_RSNIE	= 0x16,
-	auth_802_1x_fail= 0x17,
-	ciper_reject		= 0x18,
-
-	// Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, 2005-11-15.
-	QoS_unspec		= 0x20, // 32
-	QAP_bandwidth	= 0x21, // 33
-	poor_condition	= 0x22, // 34
-	no_facility 	= 0x23, // 35
-							// Where is 36???
-	req_declined	= 0x25, // 37
-	invalid_param	= 0x26, // 38
-	req_not_honored= 0x27,	// 39
-	TS_not_created	= 0x2F, // 47
-	DL_not_allowed	= 0x30, // 48
-	dest_not_exist	= 0x31, // 49
-	dest_not_QSTA	= 0x32, // 50
-};
-
-
-
-#define aSifsTime	 (((priv->ieee80211->current_network.mode == IEEE_A)||(priv->ieee80211->current_network.mode == IEEE_N_24G)||(priv->ieee80211->current_network.mode == IEEE_N_5G))? 16 : 10)
-
-#define MGMT_QUEUE_NUM 5
-
-#define IEEE_CMD_SET_WPA_PARAM			1
-#define	IEEE_CMD_SET_WPA_IE			2
-#define IEEE_CMD_SET_ENCRYPTION			3
-#define IEEE_CMD_MLME				4
-
-#define IEEE_PARAM_WPA_ENABLED			1
-#define IEEE_PARAM_TKIP_COUNTERMEASURES		2
-#define IEEE_PARAM_DROP_UNENCRYPTED		3
-#define IEEE_PARAM_PRIVACY_INVOKED		4
-#define IEEE_PARAM_AUTH_ALGS			5
-#define IEEE_PARAM_IEEE_802_1X			6
-//It should consistent with the driver_XXX.c
-//   David, 2006.9.26
-#define IEEE_PARAM_WPAX_SELECT			7
-//Added for notify the encryption type selection
-//   David, 2006.9.26
-#define IEEE_PROTO_WPA				1
-#define IEEE_PROTO_RSN				2
-//Added for notify the encryption type selection
-//   David, 2006.9.26
-#define IEEE_WPAX_USEGROUP			0
-#define IEEE_WPAX_WEP40				1
-#define IEEE_WPAX_TKIP				2
-#define IEEE_WPAX_WRAP   			3
-#define IEEE_WPAX_CCMP				4
-#define IEEE_WPAX_WEP104			5
-
-#define IEEE_KEY_MGMT_IEEE8021X			1
-#define IEEE_KEY_MGMT_PSK			2
-
-#define IEEE_MLME_STA_DEAUTH			1
-#define IEEE_MLME_STA_DISASSOC			2
-
-
-#define IEEE_CRYPT_ERR_UNKNOWN_ALG		2
-#define IEEE_CRYPT_ERR_UNKNOWN_ADDR		3
-#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED	4
-#define IEEE_CRYPT_ERR_KEY_SET_FAILED		5
-#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED	6
-#define IEEE_CRYPT_ERR_CARD_CONF_FAILED		7
-
-
-#define	IEEE_CRYPT_ALG_NAME_LEN			16
-
-#define MAX_IE_LEN  0xff
-
-// added for kernel conflict
-#define ieee80211_crypt_deinit_entries 	ieee80211_crypt_deinit_entries_rsl
-#define ieee80211_crypt_deinit_handler 	ieee80211_crypt_deinit_handler_rsl
-#define ieee80211_crypt_delayed_deinit 	ieee80211_crypt_delayed_deinit_rsl
-#define ieee80211_register_crypto_ops  	ieee80211_register_crypto_ops_rsl
-#define ieee80211_unregister_crypto_ops ieee80211_unregister_crypto_ops_rsl
-#define ieee80211_get_crypto_ops 	ieee80211_get_crypto_ops_rsl
-
-#define ieee80211_ccmp_null		ieee80211_ccmp_null_rsl
-
-#define ieee80211_tkip_null		ieee80211_tkip_null_rsl
-
-#define ieee80211_wep_null		ieee80211_wep_null_rsl
-
-#define free_ieee80211          	free_ieee80211_rsl
-#define alloc_ieee80211        		alloc_ieee80211_rsl
-
-#define ieee80211_rx 			ieee80211_rx_rsl
-#define ieee80211_rx_mgt		ieee80211_rx_mgt_rsl
-
-#define ieee80211_get_beacon		ieee80211_get_beacon_rsl
-#define ieee80211_rtl_wake_queue		ieee80211_rtl_wake_queue_rsl
-#define ieee80211_rtl_stop_queue		ieee80211_rtl_stop_queue_rsl
-#define ieee80211_reset_queue		ieee80211_reset_queue_rsl
-#define ieee80211_softmac_stop_protocol	ieee80211_softmac_stop_protocol_rsl
-#define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl
-#define ieee80211_is_shortslot		ieee80211_is_shortslot_rsl
-#define ieee80211_is_54g		ieee80211_is_54g_rsl
-#define ieee80211_wpa_supplicant_ioctl	ieee80211_wpa_supplicant_ioctl_rsl
-#define ieee80211_ps_tx_ack		ieee80211_ps_tx_ack_rsl
-#define ieee80211_softmac_xmit		ieee80211_softmac_xmit_rsl
-#define ieee80211_stop_send_beacons	ieee80211_stop_send_beacons_rsl
-#define notify_wx_assoc_event		notify_wx_assoc_event_rsl
-#define SendDisassociation		SendDisassociation_rsl
-#define ieee80211_disassociate		ieee80211_disassociate_rsl
-#define ieee80211_start_send_beacons	ieee80211_start_send_beacons_rsl
-#define ieee80211_stop_scan		ieee80211_stop_scan_rsl
-#define ieee80211_send_probe_requests	ieee80211_send_probe_requests_rsl
-#define ieee80211_softmac_scan_syncro	ieee80211_softmac_scan_syncro_rsl
-#define ieee80211_start_scan_syncro	ieee80211_start_scan_syncro_rsl
-
-#define ieee80211_wx_get_essid		ieee80211_wx_get_essid_rsl
-#define ieee80211_wx_set_essid		ieee80211_wx_set_essid_rsl
-#define ieee80211_wx_set_rate		ieee80211_wx_set_rate_rsl
-#define ieee80211_wx_get_rate		ieee80211_wx_get_rate_rsl
-#define ieee80211_wx_set_wap		ieee80211_wx_set_wap_rsl
-#define ieee80211_wx_get_wap		ieee80211_wx_get_wap_rsl
-#define ieee80211_wx_set_mode		ieee80211_wx_set_mode_rsl
-#define ieee80211_wx_get_mode		ieee80211_wx_get_mode_rsl
-#define ieee80211_wx_set_scan		ieee80211_wx_set_scan_rsl
-#define ieee80211_wx_get_freq		ieee80211_wx_get_freq_rsl
-#define ieee80211_wx_set_freq		ieee80211_wx_set_freq_rsl
-#define ieee80211_wx_set_rawtx		ieee80211_wx_set_rawtx_rsl
-#define ieee80211_wx_get_name		ieee80211_wx_get_name_rsl
-#define ieee80211_wx_set_power		ieee80211_wx_set_power_rsl
-#define ieee80211_wx_get_power		ieee80211_wx_get_power_rsl
-#define ieee80211_wlan_frequencies	ieee80211_wlan_frequencies_rsl
-#define ieee80211_wx_set_rts		ieee80211_wx_set_rts_rsl
-#define ieee80211_wx_get_rts		ieee80211_wx_get_rts_rsl
-
-#define ieee80211_txb_free		ieee80211_txb_free_rsl
-
-#define ieee80211_wx_set_gen_ie		ieee80211_wx_set_gen_ie_rsl
-#define ieee80211_wx_get_scan		ieee80211_wx_get_scan_rsl
-#define ieee80211_wx_set_encode		ieee80211_wx_set_encode_rsl
-#define ieee80211_wx_get_encode		ieee80211_wx_get_encode_rsl
-#if WIRELESS_EXT >= 18
-#define ieee80211_wx_set_mlme		ieee80211_wx_set_mlme_rsl
-#define ieee80211_wx_set_auth		ieee80211_wx_set_auth_rsl
-#define ieee80211_wx_set_encode_ext	ieee80211_wx_set_encode_ext_rsl
-#define ieee80211_wx_get_encode_ext	ieee80211_wx_get_encode_ext_rsl
-#endif
-
-
-typedef struct ieee_param {
-	u32 cmd;
-	u8 sta_addr[ETH_ALEN];
-        union {
-		struct {
-			u8 name;
-			u32 value;
-		} wpa_param;
-		struct {
-			u32 len;
-			u8 reserved[32];
-			u8 data[0];
-		} wpa_ie;
-	        struct{
-			int command;
-    			int reason_code;
-		} mlme;
-		struct {
-			u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
-			u8 set_tx;
-			u32 err;
-			u8 idx;
-			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
-			u16 key_len;
-			u8 key[0];
-		} crypt;
-	} u;
-}ieee_param;
-
-
-#if WIRELESS_EXT < 17
-#define IW_QUAL_QUAL_INVALID   0x10
-#define IW_QUAL_LEVEL_INVALID  0x20
-#define IW_QUAL_NOISE_INVALID  0x40
-#define IW_QUAL_QUAL_UPDATED   0x1
-#define IW_QUAL_LEVEL_UPDATED  0x2
-#define IW_QUAL_NOISE_UPDATED  0x4
-#endif
-
-#define MSECS(t) msecs_to_jiffies(t)
-#define msleep_interruptible_rsl  msleep_interruptible
-
-#define IEEE80211_DATA_LEN		2304
-/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
-   6.2.1.1.2.
-
-   The figure in section 7.1.2 suggests a body size of up to 2312
-   bytes is allowed, which is a bit confusing, I suspect this
-   represents the 2304 bytes of real data, plus a possible 8 bytes of
-   WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
-#define IEEE80211_1ADDR_LEN 10
-#define IEEE80211_2ADDR_LEN 16
-#define IEEE80211_3ADDR_LEN 24
-#define IEEE80211_4ADDR_LEN 30
-#define IEEE80211_FCS_LEN    4
-#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
-#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-#define IEEE80211_MGMT_HDR_LEN 24
-#define IEEE80211_DATA_HDR3_LEN 24
-#define IEEE80211_DATA_HDR4_LEN 30
-
-#define MIN_FRAG_THRESHOLD     256U
-#define MAX_FRAG_THRESHOLD     2346U
-
-
-/* Frame control field constants */
-#define IEEE80211_FCTL_VERS		0x0003
-#define IEEE80211_FCTL_FTYPE		0x000c
-#define IEEE80211_FCTL_STYPE		0x00f0
-#define IEEE80211_FCTL_FRAMETYPE	0x00fc
-#define IEEE80211_FCTL_TODS		0x0100
-#define IEEE80211_FCTL_FROMDS		0x0200
-#define IEEE80211_FCTL_DSTODS		0x0300 //added by david
-#define IEEE80211_FCTL_MOREFRAGS	0x0400
-#define IEEE80211_FCTL_RETRY		0x0800
-#define IEEE80211_FCTL_PM		0x1000
-#define IEEE80211_FCTL_MOREDATA		0x2000
-#define IEEE80211_FCTL_WEP		0x4000
-#define IEEE80211_FCTL_ORDER		0x8000
-
-#define IEEE80211_FTYPE_MGMT		0x0000
-#define IEEE80211_FTYPE_CTL		0x0004
-#define IEEE80211_FTYPE_DATA		0x0008
-
-/* management */
-#define IEEE80211_STYPE_ASSOC_REQ	0x0000
-#define IEEE80211_STYPE_ASSOC_RESP 	0x0010
-#define IEEE80211_STYPE_REASSOC_REQ	0x0020
-#define IEEE80211_STYPE_REASSOC_RESP	0x0030
-#define IEEE80211_STYPE_PROBE_REQ	0x0040
-#define IEEE80211_STYPE_PROBE_RESP	0x0050
-#define IEEE80211_STYPE_BEACON		0x0080
-#define IEEE80211_STYPE_ATIM		0x0090
-#define IEEE80211_STYPE_DISASSOC	0x00A0
-#define IEEE80211_STYPE_AUTH		0x00B0
-#define IEEE80211_STYPE_DEAUTH		0x00C0
-#define IEEE80211_STYPE_MANAGE_ACT	0x00D0
-
-/* control */
-#define IEEE80211_STYPE_PSPOLL		0x00A0
-#define IEEE80211_STYPE_RTS		0x00B0
-#define IEEE80211_STYPE_CTS		0x00C0
-#define IEEE80211_STYPE_ACK		0x00D0
-#define IEEE80211_STYPE_CFEND		0x00E0
-#define IEEE80211_STYPE_CFENDACK	0x00F0
-#define IEEE80211_STYPE_BLOCKACK   0x0094
-
-/* data */
-#define IEEE80211_STYPE_DATA		0x0000
-#define IEEE80211_STYPE_DATA_CFACK	0x0010
-#define IEEE80211_STYPE_DATA_CFPOLL	0x0020
-#define IEEE80211_STYPE_DATA_CFACKPOLL	0x0030
-#define IEEE80211_STYPE_NULLFUNC	0x0040
-#define IEEE80211_STYPE_CFACK		0x0050
-#define IEEE80211_STYPE_CFPOLL		0x0060
-#define IEEE80211_STYPE_CFACKPOLL	0x0070
-#define IEEE80211_STYPE_QOS_DATA	0x0080 //added for WMM 2006/8/2
-#define IEEE80211_STYPE_QOS_NULL	0x00C0
-
-#define IEEE80211_SCTL_FRAG		0x000F
-#define IEEE80211_SCTL_SEQ		0xFFF0
-
-/* QOS control */
-#define IEEE80211_QCTL_TID              0x000F
-
-#define	FC_QOS_BIT					BIT7
-#define IsDataFrame(pdu)			( ((pdu[0] & 0x0C)==0x08) ? true : false )
-#define	IsLegacyDataFrame(pdu)	(IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) )
-//added by wb. Is this right?
-#define IsQoSDataFrame(pframe)  ((*(u16*)pframe&(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) == (IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA))
-#define Frame_Order(pframe)     (*(u16*)pframe&IEEE80211_FCTL_ORDER)
-#define SN_LESS(a, b)		(((a-b)&0x800)!=0)
-#define SN_EQUAL(a, b)	(a == b)
-#define MAX_DEV_ADDR_SIZE 8
-typedef enum _ACT_CATEGORY{
-        ACT_CAT_QOS = 1,
-        ACT_CAT_DLS = 2,
-        ACT_CAT_BA  = 3,
-        ACT_CAT_HT  = 7,
-        ACT_CAT_WMM = 17,
-} ACT_CATEGORY, *PACT_CATEGORY;
-
-typedef enum _TS_ACTION{
-        ACT_ADDTSREQ = 0,
-        ACT_ADDTSRSP = 1,
-        ACT_DELTS    = 2,
-        ACT_SCHEDULE = 3,
-} TS_ACTION, *PTS_ACTION;
-
-typedef enum _BA_ACTION{
-        ACT_ADDBAREQ = 0,
-        ACT_ADDBARSP = 1,
-        ACT_DELBA    = 2,
-} BA_ACTION, *PBA_ACTION;
-
-typedef enum _InitialGainOpType{
-	IG_Backup=0,
-	IG_Restore,
-	IG_Max
-}InitialGainOpType;
-
-/* debug macros */
-#define CONFIG_IEEE80211_DEBUG
-#ifdef CONFIG_IEEE80211_DEBUG
-extern u32 ieee80211_debug_level;
-#define IEEE80211_DEBUG(level, fmt, args...) \
-do { if (ieee80211_debug_level & (level)) \
-  printk(KERN_DEBUG "ieee80211: " fmt, ## args); } while (0)
-//wb added to debug out data buf
-//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA
-#define IEEE80211_DEBUG_DATA(level, data, datalen)	\
-	do{ if ((ieee80211_debug_level & (level)) == (level))	\
-		{ 	\
-			int i;					\
-			u8* pdata = (u8*) data;			\
-			printk(KERN_DEBUG "ieee80211: %s()\n", __FUNCTION__);	\
-			for(i=0; i<(int)(datalen); i++)			\
-			{						\
-				printk("%2x ", pdata[i]);		\
-				if ((i+1)%16 == 0) printk("\n");	\
-			}				\
-			printk("\n");			\
-		}					\
-	} while (0)
-#else
-#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
-#define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0)
-#endif	/* CONFIG_IEEE80211_DEBUG */
-
-/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
-
-/*
- * To use the debug system;
- *
- * If you are defining a new debug classification, simply add it to the #define
- * list here in the form of:
- *
- * #define IEEE80211_DL_xxxx VALUE
- *
- * shifting value to the left one bit from the previous entry.  xxxx should be
- * the name of the classification (for example, WEP)
- *
- * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your
- * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want
- * to send output to that classification.
- *
- * To add your debug level to the list of levels seen when you perform
- *
- * % cat /proc/net/ipw/debug_level
- *
- * you simply need to add your entry to the ipw_debug_levels array.
- *
- * If you do not see debug_level in /proc/net/ipw then you do not have
- * CONFIG_IEEE80211_DEBUG defined in your kernel configuration
- *
- */
-
-#define IEEE80211_DL_INFO          (1<<0)
-#define IEEE80211_DL_WX            (1<<1)
-#define IEEE80211_DL_SCAN          (1<<2)
-#define IEEE80211_DL_STATE         (1<<3)
-#define IEEE80211_DL_MGMT          (1<<4)
-#define IEEE80211_DL_FRAG          (1<<5)
-#define IEEE80211_DL_EAP           (1<<6)
-#define IEEE80211_DL_DROP          (1<<7)
-
-#define IEEE80211_DL_TX            (1<<8)
-#define IEEE80211_DL_RX            (1<<9)
-
-#define IEEE80211_DL_HT		   (1<<10)  //HT
-#define IEEE80211_DL_BA		   (1<<11)  //ba
-#define IEEE80211_DL_TS		   (1<<12)  //TS
-#define IEEE80211_DL_QOS           (1<<13)
-#define IEEE80211_DL_REORDER	   (1<<14)
-#define IEEE80211_DL_IOT	   (1<<15)
-#define IEEE80211_DL_IPS	   (1<<16)
-#define IEEE80211_DL_TRACE	   (1<<29)  //trace function, need to user net_ratelimit() together in order not to print too much to the screen
-#define IEEE80211_DL_DATA	   (1<<30)   //use this flag to control whether print data buf out.
-#define IEEE80211_DL_ERR	   (1<<31)   //always open
-#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a)
-#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a)
-#define IEEE80211_DEBUG_INFO(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a)
-
-#define IEEE80211_DEBUG_WX(f, a...)     IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a)
-#define IEEE80211_DEBUG_SCAN(f, a...)   IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a)
-#define IEEE80211_DEBUG_STATE(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a)
-#define IEEE80211_DEBUG_MGMT(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a)
-#define IEEE80211_DEBUG_FRAG(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a)
-#define IEEE80211_DEBUG_EAP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a)
-#define IEEE80211_DEBUG_DROP(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a)
-#define IEEE80211_DEBUG_TX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a)
-#define IEEE80211_DEBUG_RX(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a)
-#define IEEE80211_DEBUG_QOS(f, a...)  IEEE80211_DEBUG(IEEE80211_DL_QOS, f, ## a)
-
-#ifdef CONFIG_IEEE80211_DEBUG
-/* Added by Annie, 2005-11-22. */
-#define MAX_STR_LEN     64
-/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/
-#define PRINTABLE(_ch)  (_ch>'!' && _ch<'~')
-#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)                            	\
-                        if((_Comp) & level)   							\
-                        {                                                                       \
-                                int             __i;                                            \
-                                u8  buffer[MAX_STR_LEN];                                    	\
-                                int length = (_Len<MAX_STR_LEN)? _Len : (MAX_STR_LEN-1) ;  	\
-                                memset(buffer, 0, MAX_STR_LEN);                      		\
-                                memcpy(buffer, (u8 *)_Ptr, length );            		\
-                                for( __i=0; __i<MAX_STR_LEN; __i++ )                            \
-                                {                                                               \
-                                     if( !PRINTABLE(buffer[__i]) )   buffer[__i] = '?';     	\
-                                }                                                               \
-                                buffer[length] = '\0';                                          \
-                                printk("Rtl819x: ");                                         	\
-                                printk(_TitleString);                                         \
-                                printk(": %d, <%s>\n", _Len, buffer);                         \
-                        }
-#else
-#define IEEE80211_PRINT_STR(_Comp, _TitleString, _Ptr, _Len)  do {} while (0)
-#endif
-
-#include <linux/netdevice.h>
-#include <linux/if_arp.h> /* ARPHRD_ETHER */
-
-#ifndef WIRELESS_SPY
-#define WIRELESS_SPY		// enable iwspy support
-#endif
-#include <net/iw_handler.h>	// new driver API
-
-#ifndef ETH_P_PAE
-#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
-#endif /* ETH_P_PAE */
-
-#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
-
-#ifndef ETH_P_80211_RAW
-#define ETH_P_80211_RAW (ETH_P_ECONET + 1)
-#endif
-
-/* IEEE 802.11 defines */
-
-#define P80211_OUI_LEN 3
-
-struct ieee80211_snap_hdr {
-
-        u8    dsap;   /* always 0xAA */
-        u8    ssap;   /* always 0xAA */
-        u8    ctrl;   /* always 0x03 */
-        u8    oui[P80211_OUI_LEN];    /* organizational universal id */
-
-} __attribute__ ((packed));
-
-#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-
-#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
-#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
-
-#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE)
-#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
-#define WLAN_GET_SEQ_SEQ(seq)  (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-
-/* Authentication algorithms */
-#define WLAN_AUTH_OPEN 0
-#define WLAN_AUTH_SHARED_KEY 1
-#define WLAN_AUTH_LEAP 2
-
-#define WLAN_AUTH_CHALLENGE_LEN 128
-
-#define WLAN_CAPABILITY_BSS (1<<0)
-#define WLAN_CAPABILITY_IBSS (1<<1)
-#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
-#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
-#define WLAN_CAPABILITY_PRIVACY (1<<4)
-#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
-#define WLAN_CAPABILITY_PBCC (1<<6)
-#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
-#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
-#define WLAN_CAPABILITY_QOS (1<<9)
-#define WLAN_CAPABILITY_SHORT_SLOT (1<<10)
-#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
-
-/* 802.11g ERP information element */
-#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
-#define WLAN_ERP_USE_PROTECTION (1<<1)
-#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
-
-/* Status codes */
-enum ieee80211_statuscode {
-        WLAN_STATUS_SUCCESS = 0,
-        WLAN_STATUS_UNSPECIFIED_FAILURE = 1,
-        WLAN_STATUS_CAPS_UNSUPPORTED = 10,
-        WLAN_STATUS_REASSOC_NO_ASSOC = 11,
-        WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12,
-        WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13,
-        WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14,
-        WLAN_STATUS_CHALLENGE_FAIL = 15,
-        WLAN_STATUS_AUTH_TIMEOUT = 16,
-        WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17,
-        WLAN_STATUS_ASSOC_DENIED_RATES = 18,
-        /* 802.11b */
-        WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19,
-        WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20,
-        WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21,
-        /* 802.11h */
-        WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22,
-        WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23,
-        WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24,
-        /* 802.11g */
-        WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25,
-        WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26,
-        /* 802.11i */
-        WLAN_STATUS_INVALID_IE = 40,
-        WLAN_STATUS_INVALID_GROUP_CIPHER = 41,
-        WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42,
-        WLAN_STATUS_INVALID_AKMP = 43,
-        WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
-        WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
-        WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
-};
-
-/* Reason codes */
-enum ieee80211_reasoncode {
-        WLAN_REASON_UNSPECIFIED = 1,
-        WLAN_REASON_PREV_AUTH_NOT_VALID = 2,
-        WLAN_REASON_DEAUTH_LEAVING = 3,
-        WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4,
-        WLAN_REASON_DISASSOC_AP_BUSY = 5,
-        WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6,
-        WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7,
-        WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8,
-        WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9,
-        /* 802.11h */
-        WLAN_REASON_DISASSOC_BAD_POWER = 10,
-        WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11,
-        /* 802.11i */
-        WLAN_REASON_INVALID_IE = 13,
-        WLAN_REASON_MIC_FAILURE = 14,
-        WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
-        WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16,
-        WLAN_REASON_IE_DIFFERENT = 17,
-        WLAN_REASON_INVALID_GROUP_CIPHER = 18,
-        WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19,
-        WLAN_REASON_INVALID_AKMP = 20,
-        WLAN_REASON_UNSUPP_RSN_VERSION = 21,
-        WLAN_REASON_INVALID_RSN_IE_CAP = 22,
-        WLAN_REASON_IEEE8021X_FAILED = 23,
-        WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
-};
-
-#define IEEE80211_STATMASK_SIGNAL (1<<0)
-#define IEEE80211_STATMASK_RSSI (1<<1)
-#define IEEE80211_STATMASK_NOISE (1<<2)
-#define IEEE80211_STATMASK_RATE (1<<3)
-#define IEEE80211_STATMASK_WEMASK 0x7
-
-#define IEEE80211_CCK_MODULATION    (1<<0)
-#define IEEE80211_OFDM_MODULATION   (1<<1)
-
-#define IEEE80211_24GHZ_BAND     (1<<0)
-#define IEEE80211_52GHZ_BAND     (1<<1)
-
-#define IEEE80211_CCK_RATE_LEN  		4
-#define IEEE80211_CCK_RATE_1MB		        0x02
-#define IEEE80211_CCK_RATE_2MB		        0x04
-#define IEEE80211_CCK_RATE_5MB		        0x0B
-#define IEEE80211_CCK_RATE_11MB		        0x16
-#define IEEE80211_OFDM_RATE_LEN 		8
-#define IEEE80211_OFDM_RATE_6MB		        0x0C
-#define IEEE80211_OFDM_RATE_9MB		        0x12
-#define IEEE80211_OFDM_RATE_12MB		0x18
-#define IEEE80211_OFDM_RATE_18MB		0x24
-#define IEEE80211_OFDM_RATE_24MB		0x30
-#define IEEE80211_OFDM_RATE_36MB		0x48
-#define IEEE80211_OFDM_RATE_48MB		0x60
-#define IEEE80211_OFDM_RATE_54MB		0x6C
-#define IEEE80211_BASIC_RATE_MASK		0x80
-
-#define IEEE80211_CCK_RATE_1MB_MASK		(1<<0)
-#define IEEE80211_CCK_RATE_2MB_MASK		(1<<1)
-#define IEEE80211_CCK_RATE_5MB_MASK		(1<<2)
-#define IEEE80211_CCK_RATE_11MB_MASK		(1<<3)
-#define IEEE80211_OFDM_RATE_6MB_MASK		(1<<4)
-#define IEEE80211_OFDM_RATE_9MB_MASK		(1<<5)
-#define IEEE80211_OFDM_RATE_12MB_MASK		(1<<6)
-#define IEEE80211_OFDM_RATE_18MB_MASK		(1<<7)
-#define IEEE80211_OFDM_RATE_24MB_MASK		(1<<8)
-#define IEEE80211_OFDM_RATE_36MB_MASK		(1<<9)
-#define IEEE80211_OFDM_RATE_48MB_MASK		(1<<10)
-#define IEEE80211_OFDM_RATE_54MB_MASK		(1<<11)
-
-#define IEEE80211_CCK_RATES_MASK	        0x0000000F
-#define IEEE80211_CCK_BASIC_RATES_MASK	(IEEE80211_CCK_RATE_1MB_MASK | \
-	IEEE80211_CCK_RATE_2MB_MASK)
-#define IEEE80211_CCK_DEFAULT_RATES_MASK	(IEEE80211_CCK_BASIC_RATES_MASK | \
-        IEEE80211_CCK_RATE_5MB_MASK | \
-        IEEE80211_CCK_RATE_11MB_MASK)
-
-#define IEEE80211_OFDM_RATES_MASK		0x00000FF0
-#define IEEE80211_OFDM_BASIC_RATES_MASK	(IEEE80211_OFDM_RATE_6MB_MASK | \
-	IEEE80211_OFDM_RATE_12MB_MASK | \
-	IEEE80211_OFDM_RATE_24MB_MASK)
-#define IEEE80211_OFDM_DEFAULT_RATES_MASK	(IEEE80211_OFDM_BASIC_RATES_MASK | \
-	IEEE80211_OFDM_RATE_9MB_MASK  | \
-	IEEE80211_OFDM_RATE_18MB_MASK | \
-	IEEE80211_OFDM_RATE_36MB_MASK | \
-	IEEE80211_OFDM_RATE_48MB_MASK | \
-	IEEE80211_OFDM_RATE_54MB_MASK)
-#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \
-                                IEEE80211_CCK_DEFAULT_RATES_MASK)
-
-#define IEEE80211_NUM_OFDM_RATES	    8
-#define IEEE80211_NUM_CCK_RATES	            4
-#define IEEE80211_OFDM_SHIFT_MASK_A         4
-
-
-/* this is stolen and modified from the madwifi driver*/
-#define IEEE80211_FC0_TYPE_MASK		0x0c
-#define IEEE80211_FC0_TYPE_DATA		0x08
-#define IEEE80211_FC0_SUBTYPE_MASK	0xB0
-#define IEEE80211_FC0_SUBTYPE_QOS	0x80
-
-#define IEEE80211_QOS_HAS_SEQ(fc) \
-	(((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \
-	 (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS))
-
-/* this is stolen from ipw2200 driver */
-#define IEEE_IBSS_MAC_HASH_SIZE 31
-struct ieee_ibss_seq {
-	u8 mac[ETH_ALEN];
-	u16 seq_num[17];
-	u16 frag_num[17];
-	unsigned long packet_time[17];
-	struct list_head list;
-};
-
-/* NOTE: This data is for statistical purposes; not all hardware provides this
- *       information for frames received.  Not setting these will not cause
- *       any adverse affects. */
-struct ieee80211_rx_stats {
-#if 1
-	u32 mac_time[2];
-	s8 rssi;
-	u8 signal;
-	u8 noise;
-	u16 rate; /* in 100 kbps */
-	u8 received_channel;
-	u8 control;
-	u8 mask;
-	u8 freq;
-	u16 len;
-	u64 tsf;
-	u32 beacon_time;
-	u8 nic_type;
-	u16       Length;
-	//      u8        DataRate;      // In 0.5 Mbps
-	u8        SignalQuality; // in 0-100 index.
-	s32       RecvSignalPower; // Real power in dBm for this packet, no beautification and aggregation.
-	s8        RxPower; // in dBm Translate from PWdB
-	u8        SignalStrength; // in 0-100 index.
-	u16       bHwError:1;
-	u16       bCRC:1;
-	u16       bICV:1;
-	u16       bShortPreamble:1;
-	u16       Antenna:1;      //for rtl8185
-	u16       Decrypted:1;    //for rtl8185, rtl8187
-	u16       Wakeup:1;       //for rtl8185
-	u16       Reserved0:1;    //for rtl8185
-	u8        AGC;
-	u32       TimeStampLow;
-	u32       TimeStampHigh;
-	bool      bShift;
-	bool      bIsQosData;             // Added by Annie, 2005-12-22.
-	u8        UserPriority;
-
-	//1!!!!!!!!!!!!!!!!!!!!!!!!!!!
-	//1Attention Please!!!<11n or 8190 specific code should be put below this line>
-	//1!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-	u8        RxDrvInfoSize;
-	u8        RxBufShift;
-	bool      bIsAMPDU;
-	bool      bFirstMPDU;
-	bool      bContainHTC;
-	bool      RxIs40MHzPacket;
-	u32       RxPWDBAll;
-	u8        RxMIMOSignalStrength[4];        // in 0~100 index
-	s8        RxMIMOSignalQuality[2];
-	bool      bPacketMatchBSSID;
-	bool      bIsCCK;
-	bool      bPacketToSelf;
-	//added by amy
-	u8*       virtual_address;
-	u16          packetlength;              // Total packet length: Must equal to sum of all FragLength
-	u16          fraglength;                        // FragLength should equal to PacketLength in non-fragment case
-	u16          fragoffset;                        // Data offset for this fragment
-	u16          ntotalfrag;
-	bool      	  bisrxaggrsubframe;
-	bool		  bPacketBeacon;	//cosa add for rssi
-	bool		  bToSelfBA;		//cosa add for rssi
-	char 	  cck_adc_pwdb[4];	//cosa add for rx path selection
-	u16		  Seq_Num;
-#endif
-
-};
-
-/* IEEE 802.11 requires that STA supports concurrent reception of at least
- * three fragmented frames. This define can be increased to support more
- * concurrent frames, but it should be noted that each entry can consume about
- * 2 kB of RAM and increasing cache size will slow down frame reassembly. */
-#define IEEE80211_FRAG_CACHE_LEN 4
-
-struct ieee80211_frag_entry {
-	unsigned long first_frag_time;
-	unsigned int seq;
-	unsigned int last_frag;
-	struct sk_buff *skb;
-	u8 src_addr[ETH_ALEN];
-	u8 dst_addr[ETH_ALEN];
-};
-
-struct ieee80211_stats {
-	unsigned int tx_unicast_frames;
-	unsigned int tx_multicast_frames;
-	unsigned int tx_fragments;
-	unsigned int tx_unicast_octets;
-	unsigned int tx_multicast_octets;
-	unsigned int tx_deferred_transmissions;
-	unsigned int tx_single_retry_frames;
-	unsigned int tx_multiple_retry_frames;
-	unsigned int tx_retry_limit_exceeded;
-	unsigned int tx_discards;
-	unsigned int rx_unicast_frames;
-	unsigned int rx_multicast_frames;
-	unsigned int rx_fragments;
-	unsigned int rx_unicast_octets;
-	unsigned int rx_multicast_octets;
-	unsigned int rx_fcs_errors;
-	unsigned int rx_discards_no_buffer;
-	unsigned int tx_discards_wrong_sa;
-	unsigned int rx_discards_undecryptable;
-	unsigned int rx_message_in_msg_fragments;
-	unsigned int rx_message_in_bad_msg_fragments;
-};
-
-struct ieee80211_device;
-
-#include "ieee80211_crypt.h"
-
-#define SEC_KEY_1         (1<<0)
-#define SEC_KEY_2         (1<<1)
-#define SEC_KEY_3         (1<<2)
-#define SEC_KEY_4         (1<<3)
-#define SEC_ACTIVE_KEY    (1<<4)
-#define SEC_AUTH_MODE     (1<<5)
-#define SEC_UNICAST_GROUP (1<<6)
-#define SEC_LEVEL         (1<<7)
-#define SEC_ENABLED       (1<<8)
-#define SEC_ENCRYPT       (1<<9)
-
-#define SEC_LEVEL_0      0 /* None */
-#define SEC_LEVEL_1      1 /* WEP 40 and 104 bit */
-#define SEC_LEVEL_2      2 /* Level 1 + TKIP */
-#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */
-#define SEC_LEVEL_3      4 /* Level 2 + CCMP */
-
-#define SEC_ALG_NONE            0
-#define SEC_ALG_WEP             1
-#define SEC_ALG_TKIP            2
-#define SEC_ALG_CCMP            3
-
-#define WEP_KEYS 		4
-#define WEP_KEY_LEN		13
-#define SCM_KEY_LEN             32
-#define SCM_TEMPORAL_KEY_LENGTH 16
-
-struct ieee80211_security {
-	u16 active_key:2,
-            enabled:1,
-	    auth_mode:2,
-            auth_algo:4,
-            unicast_uses_group:1,
-	    encrypt:1;
-	u8 key_sizes[WEP_KEYS];
-	u8 keys[WEP_KEYS][SCM_KEY_LEN];
-	u8 level;
-	u16 flags;
-} __attribute__ ((packed));
-
-
-/*
- 802.11 data frame from AP
-      ,-------------------------------------------------------------------.
-Bytes |  2   |  2   |    6    |    6    |    6    |  2   | 0..2312 |   4  |
-      |------|------|---------|---------|---------|------|---------|------|
-Desc. | ctrl | dura |  DA/RA  |   TA    |    SA   | Sequ |  frame  |  fcs |
-      |      | tion | (BSSID) |         |         | ence |  data   |      |
-      `-------------------------------------------------------------------'
-Total: 28-2340 bytes
-*/
-
-/* Management Frame Information Element Types */
-enum ieee80211_mfie {
-        MFIE_TYPE_SSID = 0,
-        MFIE_TYPE_RATES = 1,
-        MFIE_TYPE_FH_SET = 2,
-        MFIE_TYPE_DS_SET = 3,
-        MFIE_TYPE_CF_SET = 4,
-        MFIE_TYPE_TIM = 5,
-        MFIE_TYPE_IBSS_SET = 6,
-        MFIE_TYPE_COUNTRY = 7,
-        MFIE_TYPE_HOP_PARAMS = 8,
-        MFIE_TYPE_HOP_TABLE = 9,
-        MFIE_TYPE_REQUEST = 10,
-        MFIE_TYPE_CHALLENGE = 16,
-        MFIE_TYPE_POWER_CONSTRAINT = 32,
-        MFIE_TYPE_POWER_CAPABILITY = 33,
-        MFIE_TYPE_TPC_REQUEST = 34,
-        MFIE_TYPE_TPC_REPORT = 35,
-        MFIE_TYPE_SUPP_CHANNELS = 36,
-        MFIE_TYPE_CSA = 37,
-        MFIE_TYPE_MEASURE_REQUEST = 38,
-        MFIE_TYPE_MEASURE_REPORT = 39,
-        MFIE_TYPE_QUIET = 40,
-        MFIE_TYPE_IBSS_DFS = 41,
-        MFIE_TYPE_ERP = 42,
-        MFIE_TYPE_RSN = 48,
-        MFIE_TYPE_RATES_EX = 50,
-        MFIE_TYPE_HT_CAP= 45,
-	 MFIE_TYPE_HT_INFO= 61,
-	 MFIE_TYPE_AIRONET=133,
-        MFIE_TYPE_GENERIC = 221,
-        MFIE_TYPE_QOS_PARAMETER = 222,
-};
-
-/* Minimal header; can be used for passing 802.11 frames with sufficient
- * information to determine what type of underlying data type is actually
- * stored in the data. */
-struct ieee80211_hdr {
-        __le16 frame_ctl;
-        __le16 duration_id;
-        u8 payload[0];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_1addr {
-        __le16 frame_ctl;
-        __le16 duration_id;
-        u8 addr1[ETH_ALEN];
-        u8 payload[0];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_2addr {
-        __le16 frame_ctl;
-        __le16 duration_id;
-        u8 addr1[ETH_ALEN];
-        u8 addr2[ETH_ALEN];
-        u8 payload[0];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-        u8 payload[0];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_4addr {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-        u8 payload[0];
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_3addrqos {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-        u8 payload[0];
-	__le16 qos_ctl;
-} __attribute__ ((packed));
-
-struct ieee80211_hdr_4addrqos {
-	__le16 frame_ctl;
-	__le16 duration_id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-        u8 payload[0];
-	__le16 qos_ctl;
-} __attribute__ ((packed));
-
-struct ieee80211_info_element {
-	u8 id;
-	u8 len;
-	u8 data[0];
-} __attribute__ ((packed));
-
-struct ieee80211_authentication {
-	struct ieee80211_hdr_3addr header;
-	__le16 algorithm;
-	__le16 transaction;
-	__le16 status;
-	/*challenge*/
-	struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
-
-struct ieee80211_disassoc {
-        struct ieee80211_hdr_3addr header;
-        __le16 reason;
-} __attribute__ ((packed));
-
-struct ieee80211_probe_request {
-	struct ieee80211_hdr_3addr header;
-	/* SSID, supported rates */
-        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
-
-struct ieee80211_probe_response {
-	struct ieee80211_hdr_3addr header;
-	u32 time_stamp[2];
-	__le16 beacon_interval;
-	__le16 capability;
-        /* SSID, supported rates, FH params, DS params,
-         * CF params, IBSS params, TIM (if beacon), RSN */
-        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
-
-/* Alias beacon for probe_response */
-#define ieee80211_beacon ieee80211_probe_response
-
-struct ieee80211_assoc_request_frame {
-	struct ieee80211_hdr_3addr header;
-	__le16 capability;
-	__le16 listen_interval;
-	/* SSID, supported rates, RSN */
-        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
-
-struct ieee80211_reassoc_request_frame {
-	struct ieee80211_hdr_3addr header;
-	__le16 capability;
-	__le16 listen_interval;
-	u8 current_ap[ETH_ALEN];
-	/* SSID, supported rates, RSN */
-        struct ieee80211_info_element info_element[0];
-} __attribute__ ((packed));
-
-struct ieee80211_assoc_response_frame {
-	struct ieee80211_hdr_3addr header;
-	__le16 capability;
-	__le16 status;
-	__le16 aid;
-	struct ieee80211_info_element info_element[0]; /* supported rates */
-} __attribute__ ((packed));
-
-struct ieee80211_txb {
-	u8 nr_frags;
-	u8 encrypted;
-	u8 queue_index;
-	u8 rts_included;
-	u16 reserved;
-	__le16 frag_size;
-	__le16 payload_size;
-	struct sk_buff *fragments[0];
-};
-
-#define MAX_TX_AGG_COUNT		  16
-struct ieee80211_drv_agg_txb {
-	u8 nr_drv_agg_frames;
-	struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT];
-}__attribute__((packed));
-
-#define MAX_SUBFRAME_COUNT 		  64
-struct ieee80211_rxb {
-	u8 nr_subframes;
-	struct sk_buff *subframes[MAX_SUBFRAME_COUNT];
-	u8 dst[ETH_ALEN];
-	u8 src[ETH_ALEN];
-}__attribute__((packed));
-
-typedef union _frameqos {
-	u16 shortdata;
-	u8  chardata[2];
-	struct {
-		u16 tid:4;
-		u16 eosp:1;
-		u16 ack_policy:2;
-		u16 reserved:1;
-		u16 txop:8;
-	}field;
-}frameqos,*pframeqos;
-
-/* SWEEP TABLE ENTRIES NUMBER*/
-#define MAX_SWEEP_TAB_ENTRIES		  42
-#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET  7
-/* MAX_RATES_LENGTH needs to be 12.  The spec says 8, and many APs
- * only use 8, and then use extended rates for the remaining supported
- * rates.  Other APs, however, stick all of their supported rates on the
- * main rates information element... */
-#define MAX_RATES_LENGTH                  ((u8)12)
-#define MAX_RATES_EX_LENGTH               ((u8)16)
-#define MAX_NETWORK_COUNT                  128
-
-#define MAX_CHANNEL_NUMBER                 161
-#define IEEE80211_SOFTMAC_SCAN_TIME	   100
-//(HZ / 2)
-#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2)
-
-#define CRC_LENGTH                 4U
-
-#define MAX_WPA_IE_LEN 64
-
-#define NETWORK_EMPTY_ESSID (1<<0)
-#define NETWORK_HAS_OFDM    (1<<1)
-#define NETWORK_HAS_CCK     (1<<2)
-
-/* QoS structure */
-#define NETWORK_HAS_QOS_PARAMETERS      (1<<3)
-#define NETWORK_HAS_QOS_INFORMATION     (1<<4)
-#define NETWORK_HAS_QOS_MASK            (NETWORK_HAS_QOS_PARAMETERS | \
-                                         NETWORK_HAS_QOS_INFORMATION)
-/* 802.11h */
-#define NETWORK_HAS_POWER_CONSTRAINT    (1<<5)
-#define NETWORK_HAS_CSA                 (1<<6)
-#define NETWORK_HAS_QUIET               (1<<7)
-#define NETWORK_HAS_IBSS_DFS            (1<<8)
-#define NETWORK_HAS_TPC_REPORT          (1<<9)
-
-#define NETWORK_HAS_ERP_VALUE           (1<<10)
-
-#define QOS_QUEUE_NUM                   4
-#define QOS_OUI_LEN                     3
-#define QOS_OUI_TYPE                    2
-#define QOS_ELEMENT_ID                  221
-#define QOS_OUI_INFO_SUB_TYPE           0
-#define QOS_OUI_PARAM_SUB_TYPE          1
-#define QOS_VERSION_1                   1
-#define QOS_AIFSN_MIN_VALUE             2
-#if 1
-struct ieee80211_qos_information_element {
-        u8 elementID;
-        u8 length;
-        u8 qui[QOS_OUI_LEN];
-        u8 qui_type;
-        u8 qui_subtype;
-        u8 version;
-        u8 ac_info;
-} __attribute__ ((packed));
-
-struct ieee80211_qos_ac_parameter {
-        u8 aci_aifsn;
-        u8 ecw_min_max;
-        __le16 tx_op_limit;
-} __attribute__ ((packed));
-
-struct ieee80211_qos_parameter_info {
-        struct ieee80211_qos_information_element info_element;
-        u8 reserved;
-        struct ieee80211_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM];
-} __attribute__ ((packed));
-
-struct ieee80211_qos_parameters {
-        __le16 cw_min[QOS_QUEUE_NUM];
-        __le16 cw_max[QOS_QUEUE_NUM];
-        u8 aifs[QOS_QUEUE_NUM];
-        u8 flag[QOS_QUEUE_NUM];
-        __le16 tx_op_limit[QOS_QUEUE_NUM];
-} __attribute__ ((packed));
-
-struct ieee80211_qos_data {
-        struct ieee80211_qos_parameters parameters;
-        int active;
-        int supported;
-        u8 param_count;
-        u8 old_param_count;
-};
-
-struct ieee80211_tim_parameters {
-        u8 tim_count;
-        u8 tim_period;
-} __attribute__ ((packed));
-
-//#else
-struct ieee80211_wmm_ac_param {
-	u8 ac_aci_acm_aifsn;
-	u8 ac_ecwmin_ecwmax;
-	u16 ac_txop_limit;
-};
-
-struct ieee80211_wmm_ts_info {
-	u8 ac_dir_tid;
-	u8 ac_up_psb;
-	u8 reserved;
-} __attribute__ ((packed));
-
-struct ieee80211_wmm_tspec_elem {
-	struct ieee80211_wmm_ts_info ts_info;
-	u16 norm_msdu_size;
-	u16 max_msdu_size;
-	u32 min_serv_inter;
-	u32 max_serv_inter;
-	u32 inact_inter;
-	u32 suspen_inter;
-	u32 serv_start_time;
-	u32 min_data_rate;
-	u32 mean_data_rate;
-	u32 peak_data_rate;
-	u32 max_burst_size;
-	u32 delay_bound;
-	u32 min_phy_rate;
-	u16 surp_band_allow;
-	u16 medium_time;
-}__attribute__((packed));
-#endif
-enum eap_type {
-	EAP_PACKET = 0,
-	EAPOL_START,
-	EAPOL_LOGOFF,
-	EAPOL_KEY,
-	EAPOL_ENCAP_ASF_ALERT
-};
-
-static const char *eap_types[] = {
-	[EAP_PACKET]		= "EAP-Packet",
-	[EAPOL_START]		= "EAPOL-Start",
-	[EAPOL_LOGOFF]		= "EAPOL-Logoff",
-	[EAPOL_KEY]		= "EAPOL-Key",
-	[EAPOL_ENCAP_ASF_ALERT]	= "EAPOL-Encap-ASF-Alert"
-};
-
-static inline const char *eap_get_type(int type)
-{
-	return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type];
-}
-//added by amy for reorder
-static inline u8 Frame_QoSTID(u8* buf)
-{
-	struct ieee80211_hdr_3addr *hdr;
-	u16 fc;
-	hdr = (struct ieee80211_hdr_3addr *)buf;
-	fc = le16_to_cpu(hdr->frame_ctl);
-	return (u8)((frameqos*)(buf + (((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24)))->field.tid;
-}
-
-//added by amy for reorder
-
-struct eapol {
-	u8 snap[6];
-	u16 ethertype;
-	u8 version;
-	u8 type;
-	u16 length;
-} __attribute__ ((packed));
-
-struct ieee80211_softmac_stats{
-	unsigned int rx_ass_ok;
-	unsigned int rx_ass_err;
-	unsigned int rx_probe_rq;
-	unsigned int tx_probe_rs;
-	unsigned int tx_beacons;
-	unsigned int rx_auth_rq;
-	unsigned int rx_auth_rs_ok;
-	unsigned int rx_auth_rs_err;
-	unsigned int tx_auth_rq;
-	unsigned int no_auth_rs;
-	unsigned int no_ass_rs;
-	unsigned int tx_ass_rq;
-	unsigned int rx_ass_rq;
-	unsigned int tx_probe_rq;
-	unsigned int reassoc;
-	unsigned int swtxstop;
-	unsigned int swtxawake;
-	unsigned char CurrentShowTxate;
-	unsigned char last_packet_rate;
-	unsigned int txretrycount;
-};
-
-#define BEACON_PROBE_SSID_ID_POSITION 12
-
-struct ieee80211_info_element_hdr {
-	u8 id;
-	u8 len;
-} __attribute__ ((packed));
-
-/*
- * These are the data types that can make up management packets
- *
-	u16 auth_algorithm;
-	u16 auth_sequence;
-	u16 beacon_interval;
-	u16 capability;
-	u8 current_ap[ETH_ALEN];
-	u16 listen_interval;
-	struct {
-		u16 association_id:14, reserved:2;
-	} __attribute__ ((packed));
-	u32 time_stamp[2];
-	u16 reason;
-	u16 status;
-*/
-
-#define IEEE80211_DEFAULT_TX_ESSID "Penguin"
-#define IEEE80211_DEFAULT_BASIC_RATE 2 //1Mbps
-
-enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
-#define MAX_SP_Len  (WMM_all_frame << 4)
-#define IEEE80211_QOS_TID 0x0f
-#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5)
-
-#define IEEE80211_DTIM_MBCAST 4
-#define IEEE80211_DTIM_UCAST 2
-#define IEEE80211_DTIM_VALID 1
-#define IEEE80211_DTIM_INVALID 0
-
-#define IEEE80211_PS_DISABLED 0
-#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST
-#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST
-
-//added by David for QoS 2006/6/30
-//#define WMM_Hang_8187
-#ifdef WMM_Hang_8187
-#undef WMM_Hang_8187
-#endif
-
-#define WME_AC_BK   0x00
-#define WME_AC_BE   0x01
-#define WME_AC_VI   0x02
-#define WME_AC_VO   0x03
-#define WME_ACI_MASK 0x03
-#define WME_AIFSN_MASK 0x03
-#define WME_AC_PRAM_LEN 16
-
-#define MAX_RECEIVE_BUFFER_SIZE 9100
-
-//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
-//#define UP2AC(up)	((up<3) ? ((up==0)?1:0) : (up>>1))
-#if 1
-#define UP2AC(up) (		   \
-	((up) < 1) ? WME_AC_BE : \
-	((up) < 3) ? WME_AC_BK : \
-	((up) < 4) ? WME_AC_BE : \
-	((up) < 6) ? WME_AC_VI : \
-	WME_AC_VO)
-#endif
-//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue
-#define AC2UP(_ac)	(       \
-	((_ac) == WME_AC_VO) ? 6 : \
-	((_ac) == WME_AC_VI) ? 5 : \
-	((_ac) == WME_AC_BK) ? 1 : \
-	0)
-
-#define	ETHER_ADDR_LEN		6	/* length of an Ethernet address */
-#define ETHERNET_HEADER_SIZE    14      /* length of two Ethernet address plus ether type*/
-
-struct	ether_header {
-	u8 ether_dhost[ETHER_ADDR_LEN];
-	u8 ether_shost[ETHER_ADDR_LEN];
-	u16 ether_type;
-} __attribute__((packed));
-
-#ifndef ETHERTYPE_PAE
-#define	ETHERTYPE_PAE	0x888e		/* EAPOL PAE/802.1x */
-#endif
-#ifndef ETHERTYPE_IP
-#define	ETHERTYPE_IP	0x0800		/* IP protocol */
-#endif
-
-typedef struct _bss_ht{
-
-	bool				support_ht;
-
-	// HT related elements
-	u8					ht_cap_buf[32];
-	u16					ht_cap_len;
-	u8					ht_info_buf[32];
-	u16					ht_info_len;
-
-	HT_SPEC_VER			ht_spec_ver;
-	//HT_CAPABILITY_ELE			bdHTCapEle;
-	//HT_INFORMATION_ELE		bdHTInfoEle;
-
-	bool				aggregation;
-	bool				long_slot_time;
-}bss_ht, *pbss_ht;
-
-typedef enum _erp_t{
-	ERP_NonERPpresent	= 0x01,
-	ERP_UseProtection	= 0x02,
-	ERP_BarkerPreambleMode = 0x04,
-} erp_t;
-
-
-struct ieee80211_network {
-	/* These entries are used to identify a unique network */
-	u8 bssid[ETH_ALEN];
-	u8 channel;
-	/* Ensure null-terminated for any debug msgs */
-	u8 ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 ssid_len;
-#if 1
-        struct ieee80211_qos_data qos_data;
-#else
-       // Qos related. Added by Annie, 2005-11-01.
-        BSS_QOS   BssQos;
-#endif
-
-	//added by amy for LEAP
-	bool	bWithAironetIE;
-	bool	bCkipSupported;
-	bool	bCcxRmEnable;
-	u16 	CcxRmState[2];
-	// CCXv4 S59, MBSSID.
-	bool	bMBssidValid;
-	u8	MBssidMask;
-	u8	MBssid[6];
-	// CCX 2 S38, WLAN Device Version Number element. Annie, 2006-08-20.
-	bool	bWithCcxVerNum;
-	u8	BssCcxVerNumber;
-	/* These are network statistics */
-	struct ieee80211_rx_stats stats;
-	u16 capability;
-	u8  rates[MAX_RATES_LENGTH];
-	u8  rates_len;
-	u8  rates_ex[MAX_RATES_EX_LENGTH];
-	u8  rates_ex_len;
-	unsigned long last_scanned;
-	u8  mode;
-	u32 flags;
-	u32 last_associate;
-	u32 time_stamp[2];
-	u16 beacon_interval;
-	u16 listen_interval;
-	u16 atim_window;
-	u8  erp_value;
-	u8  wpa_ie[MAX_WPA_IE_LEN];
-	size_t wpa_ie_len;
-	u8  rsn_ie[MAX_WPA_IE_LEN];
-	size_t rsn_ie_len;
-
-        struct ieee80211_tim_parameters tim;
-	u8  dtim_period;
-	u8  dtim_data;
-	u32 last_dtim_sta_time[2];
-
-        //appeded for QoS
-        u8 wmm_info;
-        struct ieee80211_wmm_ac_param wmm_param[4];
-        u8 QoS_Enable;
-#ifdef THOMAS_TURBO
-	u8 Turbo_Enable;//enable turbo mode, added by thomas
-#endif
-#ifdef ENABLE_DOT11D
-	u16 CountryIeLen;
-	u8 CountryIeBuf[MAX_IE_LEN];
-#endif
-        // HT Related, by amy, 2008.04.29
-	BSS_HT	bssht;
-	// Add to handle broadcom AP management frame CCK rate.
-	bool broadcom_cap_exist;
-	bool ralink_cap_exist;
-	bool atheros_cap_exist;
-        bool cisco_cap_exist;
-        bool unknown_cap_exist;
-//	u8	berp_info;
-	bool	berp_info_valid;
-	bool buseprotection;
-	//put at the end of the structure.
-	struct list_head list;
-};
-
-#if 1
-enum ieee80211_state {
-
-	/* the card is not linked at all */
-	IEEE80211_NOLINK = 0,
-
-	/* IEEE80211_ASSOCIATING* are for BSS client mode
-	 * the driver shall not perform RX filtering unless
-	 * the state is LINKED.
-	 * The driver shall just check for the state LINKED and
-	 * defaults to NOLINK for ALL the other states (including
-	 * LINKED_SCANNING)
-	 */
-
-	/* the association procedure will start (wq scheduling)*/
-	IEEE80211_ASSOCIATING,
-	IEEE80211_ASSOCIATING_RETRY,
-
-	/* the association procedure is sending AUTH request*/
-	IEEE80211_ASSOCIATING_AUTHENTICATING,
-
-	/* the association procedure has successfully authentcated
-	 * and is sending association request
-	 */
-	IEEE80211_ASSOCIATING_AUTHENTICATED,
-
-	/* the link is ok. the card associated to a BSS or linked
-	 * to a ibss cell or acting as an AP and creating the bss
-	 */
-	IEEE80211_LINKED,
-
-	/* same as LINKED, but the driver shall apply RX filter
-	 * rules as we are in NO_LINK mode. As the card is still
-	 * logically linked, but it is doing a syncro site survey
-	 * then it will be back to LINKED state.
-	 */
-	IEEE80211_LINKED_SCANNING,
-
-};
-#else
-enum ieee80211_state {
-        IEEE80211_UNINITIALIZED = 0,
-        IEEE80211_INITIALIZED,
-        IEEE80211_ASSOCIATING,
-        IEEE80211_ASSOCIATED,
-        IEEE80211_AUTHENTICATING,
-        IEEE80211_AUTHENTICATED,
-        IEEE80211_SHUTDOWN
-};
-#endif
-
-#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
-#define DEFAULT_FTS 2346
-
-#define CFG_IEEE80211_RESERVE_FCS (1<<0)
-#define CFG_IEEE80211_COMPUTE_FCS (1<<1)
-#define CFG_IEEE80211_RTS (1<<2)
-
-#define IEEE80211_24GHZ_MIN_CHANNEL 1
-#define IEEE80211_24GHZ_MAX_CHANNEL 14
-#define IEEE80211_24GHZ_CHANNELS (IEEE80211_24GHZ_MAX_CHANNEL - \
-                                  IEEE80211_24GHZ_MIN_CHANNEL + 1)
-
-#define IEEE80211_52GHZ_MIN_CHANNEL 34
-#define IEEE80211_52GHZ_MAX_CHANNEL 165
-#define IEEE80211_52GHZ_CHANNELS (IEEE80211_52GHZ_MAX_CHANNEL - \
-                                  IEEE80211_52GHZ_MIN_CHANNEL + 1)
-
-typedef struct tx_pending_t{
-	int frag;
-	struct ieee80211_txb *txb;
-}tx_pending_t;
-
-typedef struct _bandwidth_autoswitch
-{
-	long threshold_20Mhzto40Mhz;
-	long	threshold_40Mhzto20Mhz;
-	bool bforced_tx20Mhz;
-	bool bautoswitch_enable;
-}bandwidth_autoswitch,*pbandwidth_autoswitch;
-
-
-//added by amy for order
-
-#define REORDER_WIN_SIZE	128
-#define REORDER_ENTRY_NUM	128
-typedef struct _RX_REORDER_ENTRY
-{
-	struct list_head	List;
-	u16			SeqNum;
-	struct ieee80211_rxb* prxb;
-} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY;
-//added by amy for order
-typedef enum _Fsync_State{
-	Default_Fsync,
-	HW_Fsync,
-	SW_Fsync
-}Fsync_State;
-
-// Power save mode configured.
-typedef	enum _RT_PS_MODE
-{
-	eActive,	// Active/Continuous access.
-	eMaxPs,		// Max power save mode.
-	eFastPs		// Fast power save mode.
-}RT_PS_MODE;
-
-typedef enum _IPS_CALLBACK_FUNCION
-{
-	IPS_CALLBACK_NONE = 0,
-	IPS_CALLBACK_MGNT_LINK_REQUEST = 1,
-	IPS_CALLBACK_JOIN_REQUEST = 2,
-}IPS_CALLBACK_FUNCION;
-
-typedef enum _RT_JOIN_ACTION{
-	RT_JOIN_INFRA   = 1,
-	RT_JOIN_IBSS  = 2,
-	RT_START_IBSS = 3,
-	RT_NO_ACTION  = 4,
-}RT_JOIN_ACTION;
-
-typedef struct _IbssParms{
-	u16   atimWin;
-}IbssParms, *PIbssParms;
-#define MAX_NUM_RATES	264 // Max num of support rates element: 8,  Max num of ext. support rate: 255. 061122, by rcnjko.
-
-// RF state.
-typedef	enum _RT_RF_POWER_STATE
-{
-	eRfOn,
-	eRfSleep,
-	eRfOff
-}RT_RF_POWER_STATE;
-
-typedef struct _RT_POWER_SAVE_CONTROL
-{
-
-	//
-	// Inactive Power Save(IPS) : Disable RF when disconnected
-	//
-	bool				bInactivePs;
-	bool				bIPSModeBackup;
-	bool				bSwRfProcessing;
-	RT_RF_POWER_STATE	eInactivePowerState;
-	struct work_struct 	InactivePsWorkItem;
-	struct timer_list	InactivePsTimer;
-
-	// Return point for join action
-	IPS_CALLBACK_FUNCION	ReturnPoint;
-
-	// Recored Parameters for rescheduled JoinRequest
-	bool				bTmpBssDesc;
-	RT_JOIN_ACTION		tmpJoinAction;
-	struct ieee80211_network tmpBssDesc;
-
-	// Recored Parameters for rescheduled MgntLinkRequest
-	bool				bTmpScanOnly;
-	bool				bTmpActiveScan;
-	bool				bTmpFilterHiddenAP;
-	bool				bTmpUpdateParms;
-	u8					tmpSsidBuf[33];
-	OCTET_STRING			tmpSsid2Scan;
-	bool				bTmpSsid2Scan;
-	u8					tmpNetworkType;
-	u8					tmpChannelNumber;
-	u16					tmpBcnPeriod;
-	u8					tmpDtimPeriod;
-	u16					tmpmCap;
-	OCTET_STRING			tmpSuppRateSet;
-	u8					tmpSuppRateBuf[MAX_NUM_RATES];
-	bool				bTmpSuppRate;
-	IbssParms				tmpIbpm;
-	bool				bTmpIbpm;
-
-	//
-	// Leisre Poswer Save : Disable RF if connected but traffic is not busy
-	//
-	bool				bLeisurePs;
-
-}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL;
-
-typedef u32 RT_RF_CHANGE_SOURCE;
-#define RF_CHANGE_BY_SW BIT31
-#define RF_CHANGE_BY_HW BIT30
-#define RF_CHANGE_BY_PS BIT29
-#define RF_CHANGE_BY_IPS BIT28
-#define RF_CHANGE_BY_INIT	0	// Do not change the RFOff reason. Defined by Bruce, 2008-01-17.
-
-#ifdef ENABLE_DOT11D
-typedef enum
-{
-	COUNTRY_CODE_FCC = 0,
-	COUNTRY_CODE_IC = 1,
-	COUNTRY_CODE_ETSI = 2,
-	COUNTRY_CODE_SPAIN = 3,
-	COUNTRY_CODE_FRANCE = 4,
-	COUNTRY_CODE_MKK = 5,
-	COUNTRY_CODE_MKK1 = 6,
-	COUNTRY_CODE_ISRAEL = 7,
-	COUNTRY_CODE_TELEC,
-	COUNTRY_CODE_MIC,
-	COUNTRY_CODE_GLOBAL_DOMAIN
-}country_code_type_t;
-#endif
-
-#define RT_MAX_LD_SLOT_NUM	10
-typedef struct _RT_LINK_DETECT_T{
-
-	u32				NumRecvBcnInPeriod;
-	u32				NumRecvDataInPeriod;
-
-	u32				RxBcnNum[RT_MAX_LD_SLOT_NUM];	// number of Rx beacon / CheckForHang_period  to determine link status
-	u32				RxDataNum[RT_MAX_LD_SLOT_NUM];	// number of Rx data / CheckForHang_period  to determine link status
-	u16				SlotNum;	// number of CheckForHang period to determine link status
-	u16				SlotIndex;
-
-	u32				NumTxOkInPeriod;
-	u32				NumRxOkInPeriod;
-	bool				bBusyTraffic;
-}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
-
-
-struct ieee80211_device {
-	struct net_device *dev;
-        struct ieee80211_security sec;
-
-	//hw security related
-//	u8 hwsec_support; //support?
-	u8 hwsec_active;  //hw security active.
-	bool is_silent_reset;
-	bool is_roaming;
-	bool ieee_up;
-	//added by amy
-	bool bSupportRemoteWakeUp;
-	RT_PS_MODE	dot11PowerSaveMode; // Power save mode configured.
-	bool actscanning;
-	bool beinretry;
-	RT_RF_POWER_STATE		eRFPowerState;
-	RT_RF_CHANGE_SOURCE	RfOffReason;
-	bool is_set_key;
-	//11n spec related I wonder if These info structure need to be moved out of ieee80211_device
-
-	//11n HT below
-	PRT_HIGH_THROUGHPUT	pHTInfo;
-	//struct timer_list		SwBwTimer;
-//	spinlock_t chnlop_spinlock;
-	spinlock_t bw_spinlock;
-
-	spinlock_t reorder_spinlock;
-	// for HT operation rate set.  we use this one for HT data rate to separate different descriptors
-	//the way fill this is the same as in the IE
-	u8	Regdot11HTOperationalRateSet[16];		//use RATR format
-	u8	dot11HTOperationalRateSet[16];		//use RATR format
-	u8	RegHTSuppRateSet[16];
-	u8				HTCurrentOperaRate;
-	u8				HTHighestOperaRate;
-	//wb added for rate operation mode to firmware
-	u8	bTxDisableRateFallBack;
-	u8 	bTxUseDriverAssingedRate;
-	atomic_t	atm_chnlop;
-	atomic_t	atm_swbw;
-//	u8	HTHighestOperaRate;
-//	u8 	HTCurrentOperaRate;
-
-	// 802.11e and WMM Traffic Stream Info (TX)
-	struct list_head		Tx_TS_Admit_List;
-	struct list_head		Tx_TS_Pending_List;
-	struct list_head		Tx_TS_Unused_List;
-	TX_TS_RECORD		TxTsRecord[TOTAL_TS_NUM];
-	// 802.11e and WMM Traffic Stream Info (RX)
-	struct list_head		Rx_TS_Admit_List;
-	struct list_head		Rx_TS_Pending_List;
-	struct list_head		Rx_TS_Unused_List;
-	RX_TS_RECORD		RxTsRecord[TOTAL_TS_NUM];
-//#ifdef TO_DO_LIST
-	RX_REORDER_ENTRY	RxReorderEntry[128];
-	struct list_head		RxReorder_Unused_List;
-//#endif
-	// Qos related. Added by Annie, 2005-11-01.
-//	PSTA_QOS			pStaQos;
-	u8				ForcedPriority;		// Force per-packet priority 1~7. (default: 0, not to force it.)
-
-
-	/* Bookkeeping structures */
-	struct net_device_stats stats;
-	struct ieee80211_stats ieee_stats;
-	struct ieee80211_softmac_stats softmac_stats;
-
-	/* Probe / Beacon management */
-	struct list_head network_free_list;
-	struct list_head network_list;
-	struct ieee80211_network *networks;
-	int scans;
-	int scan_age;
-
-	int iw_mode; /* operating mode (IW_MODE_*) */
-	struct iw_spy_data spy_data;
-
-	spinlock_t lock;
-	spinlock_t wpax_suitlist_lock;
-
-	int tx_headroom; /* Set to size of any additional room needed at front
-			  * of allocated Tx SKBs */
-	u32 config;
-
-	/* WEP and other encryption related settings at the device level */
-	int open_wep; /* Set to 1 to allow unencrypted frames */
-	int auth_mode;
-	int reset_on_keychange; /* Set to 1 if the HW needs to be reset on
-				 * WEP key changes */
-
-	/* If the host performs {en,de}cryption, then set to 1 */
-	int host_encrypt;
-	int host_encrypt_msdu;
-	int host_decrypt;
-        /* host performs multicast decryption */
-        int host_mc_decrypt;
-
-        /* host should strip IV and ICV from protected frames */
-        /* meaningful only when hardware decryption is being used */
-        int host_strip_iv_icv;
-
-        int host_open_frag;
-        int host_build_iv;
-	int ieee802_1x; /* is IEEE 802.1X used */
-
-	/* WPA data */
-	bool bHalfWirelessN24GMode;
-	int wpa_enabled;
-	int drop_unencrypted;
-	int tkip_countermeasures;
-	int privacy_invoked;
-	size_t wpa_ie_len;
-	u8 *wpa_ie;
-	u8 ap_mac_addr[6];
-	u16 pairwise_key_type;
-	u16 group_key_type;
-	struct list_head crypt_deinit_list;
-	struct ieee80211_crypt_data *crypt[WEP_KEYS];
-	int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
-	struct timer_list crypt_deinit_timer;
-        int crypt_quiesced;
-
-	int bcrx_sta_key; /* use individual keys to override default keys even
-			   * with RX of broad/multicast frames */
-
-	/* Fragmentation structures */
-	// each streaming contain a entry
-	struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN];
-	unsigned int frag_next_idx[17];
-	u16 fts; /* Fragmentation Threshold */
-#define DEFAULT_RTS_THRESHOLD 2346U
-#define MIN_RTS_THRESHOLD 1
-#define MAX_RTS_THRESHOLD 2346U
-        u16 rts; /* RTS threshold */
-
-        /* Association info */
-        u8 bssid[ETH_ALEN];
-
-	/* This stores infos for the current network.
-	 * Either the network we are associated in INFRASTRUCTURE
-	 * or the network that we are creating in MASTER mode.
-	 * ad-hoc is a mixture ;-).
-	 * Note that in infrastructure mode, even when not associated,
-	 * fields bssid and essid may be valid (if wpa_set and essid_set
-	 * are true) as thy carry the value set by the user via iwconfig
-	 */
-	struct ieee80211_network current_network;
-
-	enum ieee80211_state state;
-
-	int short_slot;
-	int reg_mode;
-	int mode;       /* A, B, G */
-	int modulation; /* CCK, OFDM */
-	int freq_band;  /* 2.4Ghz, 5.2Ghz, Mixed */
-	int abg_true;   /* ABG flag              */
-
-	/* used for forcing the ibss workqueue to terminate
-	 * without wait for the syncro scan to terminate
-	 */
-	short sync_scan_hurryup;
-
-        int perfect_rssi;
-        int worst_rssi;
-
-        u16 prev_seq_ctl;       /* used to drop duplicate frames */
-
-	/* map of allowed channels. 0 is dummy */
-	// FIXME: remeber to default to a basic channel plan depending of the PHY type
-#ifdef ENABLE_DOT11D
-	void* pDot11dInfo;
-	bool bGlobalDomain;
-#else
-	int channel_map[MAX_CHANNEL_NUMBER+1];
-#endif
-	int rate;       /* current rate */
-	int basic_rate;
-	//FIXME: pleace callback, see if redundant with softmac_features
-	short active_scan;
-
-	/* this contains flags for selectively enable softmac support */
-	u16 softmac_features;
-
-	/* if the sequence control field is not filled by HW */
-	u16 seq_ctrl[5];
-
-	/* association procedure transaction sequence number */
-	u16 associate_seq;
-
-	/* AID for RTXed association responses */
-	u16 assoc_id;
-
-	/* power save mode related*/
-	u8 ack_tx_to_ieee;
-	short ps;
-	short sta_sleep;
-	int ps_timeout;
-	int ps_period;
-	struct tasklet_struct ps_task;
-	u32 ps_th;
-	u32 ps_tl;
-
-	short raw_tx;
-	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
-	short queue_stop;
-	short scanning;
-	short proto_started;
-
-	struct semaphore wx_sem;
-	struct semaphore scan_sem;
-
-	spinlock_t mgmt_tx_lock;
-	spinlock_t beacon_lock;
-
-	short beacon_txing;
-
-	short wap_set;
-	short ssid_set;
-
-	u8  wpax_type_set;    //{added by David, 2006.9.28}
-	u32 wpax_type_notify; //{added by David, 2006.9.26}
-
-	/* QoS related flag */
-	char init_wmmparam_flag;
-	/* set on initialization */
-	u8  qos_support;
-
-	/* for discarding duplicated packets in IBSS */
-	struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE];
-
-	/* for discarding duplicated packets in BSS */
-	u16 last_rxseq_num[17]; /* rx seq previous per-tid */
-	u16 last_rxfrag_num[17];/* tx frag previous per-tid */
-	unsigned long last_packet_time[17];
-
-	/* for PS mode */
-	unsigned long last_rx_ps_time;
-
-	/* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
-	struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
-	int mgmt_queue_head;
-	int mgmt_queue_tail;
-//{ added for rtl819x
-#define IEEE80211_QUEUE_LIMIT 128
-	u8 AsocRetryCount;
-	unsigned int hw_header;
-	struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE];
-	struct sk_buff_head  skb_aggQ[MAX_QUEUE_SIZE];
-	struct sk_buff_head  skb_drv_aggQ[MAX_QUEUE_SIZE];
-	u32	sta_edca_param[4];
-	bool aggregation;
-	// Enable/Disable Rx immediate BA capability.
-	bool enable_rx_imm_BA;
-	bool bibsscoordinator;
-
-	//+by amy for DM ,080515
-	//Dynamic Tx power for near/far range enable/Disable  , by amy , 2008-05-15
-	bool	bdynamic_txpower_enable;
-
-	bool bCTSToSelfEnable;
-	u8 	CTSToSelfTH;
-
-	u32 	fsync_time_interval;
-	u32	fsync_rate_bitmap;
-	u8	fsync_rssi_threshold;
-	bool	bfsync_enable;
-
-	u8	fsync_multiple_timeinterval;		// FsyncMultipleTimeInterval * FsyncTimeInterval
-	u32	fsync_firstdiff_ratethreshold;		// low threshold
-	u32	fsync_seconddiff_ratethreshold;	 // decrease threshold
-	Fsync_State			fsync_state;
-	bool		bis_any_nonbepkts;
-	//20Mhz 40Mhz AutoSwitch Threshold
-	bandwidth_autoswitch bandwidth_auto_switch;
-	//for txpower tracking
-	bool FwRWRF;
-
-	//added by amy for AP roaming
-	RT_LINK_DETECT_T	LinkDetectInfo;
-        //added by amy for ps
-	RT_POWER_SAVE_CONTROL	PowerSaveControl;
-//}
-	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
-	struct  tx_pending_t tx_pending;
-
-	/* used if IEEE_SOFTMAC_ASSOCIATE is set */
-	struct timer_list associate_timer;
-
-	/* used if IEEE_SOFTMAC_BEACONS is set */
-	struct timer_list beacon_timer;
-
-        struct work_struct associate_complete_wq;
-        struct work_struct associate_procedure_wq;
-        struct delayed_work softmac_scan_wq;
-        struct delayed_work associate_retry_wq;
-	 struct delayed_work start_ibss_wq;
-	 struct delayed_work hw_wakeup_wq;
-	struct delayed_work hw_sleep_wq;
-        struct work_struct wx_sync_scan_wq;
-        struct workqueue_struct *wq;
-        // Qos related. Added by Annie, 2005-11-01.
-        //STA_QOS  StaQos;
-
-        //u32 STA_EDCA_PARAM[4];
-	//CHANNEL_ACCESS_SETTING ChannelAccessSetting;
-
-
-	/* Callback functions */
-	void (*set_security)(struct net_device *dev,
-			     struct ieee80211_security *sec);
-
-	/* Used to TX data frame by using txb structs.
-	 * this is not used if in the softmac_features
-	 * is set the flag IEEE_SOFTMAC_TX_QUEUE
-	 */
-	int (*hard_start_xmit)(struct ieee80211_txb *txb,
-			       struct net_device *dev);
-
-	int (*reset_port)(struct net_device *dev);
-        int (*is_queue_full) (struct net_device * dev, int pri);
-
-        int (*handle_management) (struct net_device * dev,
-                                  struct ieee80211_network * network, u16 type);
-        int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
-
-	/* Softmac-generated frames (mamagement) are TXed via this
-	 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
-	 * not set. As some cards may have different HW queues that
-	 * one might want to use for data and management frames
-	 * the option to have two callbacks might be useful.
-	 * This fucntion can't sleep.
-	 */
-	int (*softmac_hard_start_xmit)(struct sk_buff *skb,
-			       struct net_device *dev);
-
-	/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
-	 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
-	 * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set
-	 * then also management frames are sent via this callback.
-	 * This function can't sleep.
-	 */
-	void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
-			       struct net_device *dev,int rate);
-
-	/* stops the HW queue for DATA frames. Useful to avoid
-	 * waste time to TX data frame when we are reassociating
-	 * This function can sleep.
-	 */
-	void (*data_hard_stop)(struct net_device *dev);
-
-	/* OK this is complementar to data_poll_hard_stop */
-	void (*data_hard_resume)(struct net_device *dev);
-
-	/* ask to the driver to retune the radio .
-	 * This function can sleep. the driver should ensure
-	 * the radio has been swithced before return.
-	 */
-	void (*set_chan)(struct net_device *dev,short ch);
-
-	/* These are not used if the ieee stack takes care of
-	 * scanning (IEEE_SOFTMAC_SCAN feature set).
-	 * In this case only the set_chan is used.
-	 *
-	 * The syncro version is similar to the start_scan but
-	 * does not return until all channels has been scanned.
-	 * this is called in user context and should sleep,
-	 * it is called in a work_queue when swithcing to ad-hoc mode
-	 * or in behalf of iwlist scan when the card is associated
-	 * and root user ask for a scan.
-	 * the fucntion stop_scan should stop both the syncro and
-	 * background scanning and can sleep.
-	 * The fucntion start_scan should initiate the background
-	 * scanning and can't sleep.
-	 */
-	void (*scan_syncro)(struct net_device *dev);
-	void (*start_scan)(struct net_device *dev);
-	void (*stop_scan)(struct net_device *dev);
-
-	/* indicate the driver that the link state is changed
-	 * for example it may indicate the card is associated now.
-	 * Driver might be interested in this to apply RX filter
-	 * rules or simply light the LINK led
-	 */
-	void (*link_change)(struct net_device *dev);
-
-	/* these two function indicates to the HW when to start
-	 * and stop to send beacons. This is used when the
-	 * IEEE_SOFTMAC_BEACONS is not set. For now the
-	 * stop_send_bacons is NOT guaranteed to be called only
-	 * after start_send_beacons.
-	 */
-	void (*start_send_beacons) (struct net_device *dev);
-	void (*stop_send_beacons) (struct net_device *dev);
-
-	/* power save mode related */
-	void (*sta_wake_up) (struct net_device *dev);
-//	void (*ps_request_tx_ack) (struct net_device *dev);
-	void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl);
-	short (*ps_is_queue_empty) (struct net_device *dev);
-#if 0
-	/* Typical STA methods */
-        int (*handle_auth) (struct net_device * dev,
-                            struct ieee80211_auth * auth);
-        int (*handle_deauth) (struct net_device * dev,
-                              struct ieee80211_deauth * auth);
-        int (*handle_action) (struct net_device * dev,
-                              struct ieee80211_action * action,
-                              struct ieee80211_rx_stats * stats);
-        int (*handle_disassoc) (struct net_device * dev,
-                                struct ieee80211_disassoc * assoc);
-#endif
-        int (*handle_beacon) (struct net_device * dev, struct ieee80211_beacon * beacon, struct ieee80211_network * network);
-#if 0
-        int (*handle_probe_response) (struct net_device * dev,
-                                      struct ieee80211_probe_response * resp,
-                                      struct ieee80211_network * network);
-        int (*handle_probe_request) (struct net_device * dev,
-                                     struct ieee80211_probe_request * req,
-                                     struct ieee80211_rx_stats * stats);
-#endif
-        int (*handle_assoc_response) (struct net_device * dev, struct ieee80211_assoc_response_frame * resp, struct ieee80211_network * network);
-
-#if 0
-        /* Typical AP methods */
-        int (*handle_assoc_request) (struct net_device * dev);
-        int (*handle_reassoc_request) (struct net_device * dev,
-                                       struct ieee80211_reassoc_request * req);
-#endif
-
-	/* check whether Tx hw resouce available */
-	short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
-	//added by wb for HT related
-//	void (*SwChnlByTimerHandler)(struct net_device *dev, int channel);
-	void (*SetBWModeHandler)(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
-//	void (*UpdateHalRATRTableHandler)(struct net_device* dev, u8* pMcsRate);
-	bool (*GetNmodeSupportBySecCfg)(struct net_device* dev);
-	void (*SetWirelessMode)(struct net_device* dev, u8 wireless_mode);
-	bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device* dev);
-	void (*InitialGainHandler)(struct net_device *dev, u8 Operation);
-
-	/* This must be the last item so that it points to the data
-	 * allocated beyond this structure by alloc_ieee80211 */
-	u8 priv[0];
-};
-
-#define IEEE_A            (1<<0)
-#define IEEE_B            (1<<1)
-#define IEEE_G            (1<<2)
-#define IEEE_N_24G 		  (1<<4)
-#define	IEEE_N_5G		  (1<<5)
-#define IEEE_MODE_MASK    (IEEE_A|IEEE_B|IEEE_G)
-
-/* Generate a 802.11 header */
-
-/* Uses the channel change callback directly
- * instead of [start/stop] scan callbacks
- */
-#define IEEE_SOFTMAC_SCAN (1<<2)
-
-/* Perform authentication and association handshake */
-#define IEEE_SOFTMAC_ASSOCIATE (1<<3)
-
-/* Generate probe requests */
-#define IEEE_SOFTMAC_PROBERQ (1<<4)
-
-/* Generate respones to probe requests */
-#define IEEE_SOFTMAC_PROBERS (1<<5)
-
-/* The ieee802.11 stack will manages the netif queue
- * wake/stop for the driver, taking care of 802.11
- * fragmentation. See softmac.c for details. */
-#define IEEE_SOFTMAC_TX_QUEUE (1<<7)
-
-/* Uses only the softmac_data_hard_start_xmit
- * even for TX management frames.
- */
-#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8)
-
-/* Generate beacons.  The stack will enqueue beacons
- * to the card
- */
-#define IEEE_SOFTMAC_BEACONS (1<<6)
-
-static inline void *ieee80211_priv(struct net_device *dev)
-{
-	return ((struct ieee80211_device *)netdev_priv(dev))->priv;
-}
-
-extern inline int ieee80211_is_empty_essid(const char *essid, int essid_len)
-{
-	/* Single white space is for Linksys APs */
-	if (essid_len == 1 && essid[0] == ' ')
-		return 1;
-
-	/* Otherwise, if the entire essid is 0, we assume it is hidden */
-	while (essid_len) {
-		essid_len--;
-		if (essid[essid_len] != '\0')
-			return 0;
-	}
-
-	return 1;
-}
-
-extern inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, int mode)
-{
-	/*
-	 * It is possible for both access points and our device to support
-	 * combinations of modes, so as long as there is one valid combination
-	 * of ap/device supported modes, then return success
-	 *
-	 */
-	if ((mode & IEEE_A) &&
-	    (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
-	    (ieee->freq_band & IEEE80211_52GHZ_BAND))
-		return 1;
-
-	if ((mode & IEEE_G) &&
-	    (ieee->modulation & IEEE80211_OFDM_MODULATION) &&
-	    (ieee->freq_band & IEEE80211_24GHZ_BAND))
-		return 1;
-
-	if ((mode & IEEE_B) &&
-	    (ieee->modulation & IEEE80211_CCK_MODULATION) &&
-	    (ieee->freq_band & IEEE80211_24GHZ_BAND))
-		return 1;
-
-	return 0;
-}
-
-extern inline int ieee80211_get_hdrlen(u16 fc)
-{
-	int hdrlen = IEEE80211_3ADDR_LEN;
-
-	switch (WLAN_FC_GET_TYPE(fc)) {
-	case IEEE80211_FTYPE_DATA:
-		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
-			hdrlen = IEEE80211_4ADDR_LEN; /* Addr4 */
-		if(IEEE80211_QOS_HAS_SEQ(fc))
-			hdrlen += 2; /* QOS ctrl*/
-		break;
-	case IEEE80211_FTYPE_CTL:
-		switch (WLAN_FC_GET_STYPE(fc)) {
-		case IEEE80211_STYPE_CTS:
-		case IEEE80211_STYPE_ACK:
-			hdrlen = IEEE80211_1ADDR_LEN;
-			break;
-		default:
-			hdrlen = IEEE80211_2ADDR_LEN;
-			break;
-		}
-		break;
-	}
-
-	return hdrlen;
-}
-
-static inline u8 *ieee80211_get_payload(struct ieee80211_hdr *hdr)
-{
-        switch (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) {
-        case IEEE80211_1ADDR_LEN:
-                return ((struct ieee80211_hdr_1addr *)hdr)->payload;
-        case IEEE80211_2ADDR_LEN:
-                return ((struct ieee80211_hdr_2addr *)hdr)->payload;
-        case IEEE80211_3ADDR_LEN:
-                return ((struct ieee80211_hdr_3addr *)hdr)->payload;
-        case IEEE80211_4ADDR_LEN:
-                return ((struct ieee80211_hdr_4addr *)hdr)->payload;
-        }
-        return NULL;
-}
-
-static inline int ieee80211_is_ofdm_rate(u8 rate)
-{
-        switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
-        case IEEE80211_OFDM_RATE_6MB:
-        case IEEE80211_OFDM_RATE_9MB:
-        case IEEE80211_OFDM_RATE_12MB:
-        case IEEE80211_OFDM_RATE_18MB:
-        case IEEE80211_OFDM_RATE_24MB:
-        case IEEE80211_OFDM_RATE_36MB:
-        case IEEE80211_OFDM_RATE_48MB:
-        case IEEE80211_OFDM_RATE_54MB:
-                return 1;
-        }
-        return 0;
-}
-
-static inline int ieee80211_is_cck_rate(u8 rate)
-{
-        switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
-        case IEEE80211_CCK_RATE_1MB:
-        case IEEE80211_CCK_RATE_2MB:
-        case IEEE80211_CCK_RATE_5MB:
-        case IEEE80211_CCK_RATE_11MB:
-                return 1;
-        }
-        return 0;
-}
-
-
-/* ieee80211.c */
-void free_ieee80211(struct net_device *dev);
-struct net_device *alloc_ieee80211(int sizeof_priv);
-
-int ieee80211_set_encryption(struct ieee80211_device *ieee);
-
-/* ieee80211_tx.c */
-
-int ieee80211_encrypt_fragment(
-	struct ieee80211_device *ieee,
-	struct sk_buff *frag,
-	int hdr_len);
-
-int ieee80211_rtl_xmit(struct sk_buff *skb,
-			  struct net_device *dev);
-void ieee80211_txb_free(struct ieee80211_txb *);
-
-
-/* ieee80211_rx.c */
-int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
-			struct ieee80211_rx_stats *rx_stats);
-void ieee80211_rx_mgt(struct ieee80211_device *ieee,
-			     struct ieee80211_hdr_4addr *header,
-			     struct ieee80211_rx_stats *stats);
-
-/* ieee80211_wx.c */
-int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *key);
-int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
-				   struct iw_request_info *info,
-				   union iwreq_data *wrqu, char *key);
-int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
-				   struct iw_request_info *info,
-				   union iwreq_data *wrqu, char *key);
-#if WIRELESS_EXT >= 18
-int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data* wrqu, char *extra);
-int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
-                            struct iw_request_info *info,
-                            union iwreq_data* wrqu, char *extra);
-int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
-                               struct iw_request_info *info,
-                               struct iw_param *data, char *extra);
-int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
-                               struct iw_request_info *info,
-                               union iwreq_data *wrqu, char *extra);
-#endif
-int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
-
-/* ieee80211_softmac.c */
-short ieee80211_is_54g(struct ieee80211_network net);
-short ieee80211_is_shortslot(struct ieee80211_network net);
-int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
-			struct ieee80211_rx_stats *rx_stats, u16 type,
-			u16 stype);
-void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
-
-void SendDisassociation(struct ieee80211_device *ieee, u8* asSta, u8 asRsn);
-void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
-
-void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-void notify_wx_assoc_event(struct ieee80211_device *ieee);
-void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
-void ieee80211_start_bss(struct ieee80211_device *ieee);
-void ieee80211_start_master_bss(struct ieee80211_device *ieee);
-void ieee80211_start_ibss(struct ieee80211_device *ieee);
-void ieee80211_softmac_init(struct ieee80211_device *ieee);
-void ieee80211_softmac_free(struct ieee80211_device *ieee);
-void ieee80211_associate_abort(struct ieee80211_device *ieee);
-void ieee80211_disassociate(struct ieee80211_device *ieee);
-void ieee80211_stop_scan(struct ieee80211_device *ieee);
-void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
-void ieee80211_check_all_nets(struct ieee80211_device *ieee);
-void ieee80211_start_protocol(struct ieee80211_device *ieee);
-void ieee80211_stop_protocol(struct ieee80211_device *ieee);
-void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
-void ieee80211_reset_queue(struct ieee80211_device *ieee);
-void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
-void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
-struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
-void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
-void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
-void notify_wx_assoc_event(struct ieee80211_device *ieee);
-void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
-
-void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
-
-/* ieee80211_crypt_ccmp&tkip&wep.c */
-void ieee80211_tkip_null(void);
-void ieee80211_wep_null(void);
-void ieee80211_ccmp_null(void);
-
-/* ieee80211_softmac_wx.c */
-
-int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
-			    struct iw_request_info *info,
-			    union iwreq_data *wrqu, char *ext);
-
-int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
-			 struct iw_request_info *info,
-			 union iwreq_data *awrq,
-			 char *extra);
-
-int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
-
-int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b);
-
-int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b);
-
-int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
-			      struct iw_request_info *a,
-			      union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b);
-
-int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b);
-
-int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
-			     union iwreq_data *wrqu, char *b);
-
-void ieee80211_wx_sync_scan_wq(struct work_struct *work);
-
-
-int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
-			       struct iw_request_info *info,
-			       union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_get_name(struct ieee80211_device *ieee,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_set_power(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_get_power(struct ieee80211_device *ieee,
-				 struct iw_request_info *info,
-				 union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra);
-
-int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
-			     struct iw_request_info *info,
-			     union iwreq_data *wrqu, char *extra);
-//HT
-#define MAX_RECEIVE_BUFFER_SIZE 9100  //
-void HTDebugHTCapability(u8* CapIE, u8* TitleString );
-void HTDebugHTInfo(u8*  InfoIE, u8* TitleString);
-
-void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET    Offset);
-void HTUpdateDefaultSetting(struct ieee80211_device* ieee);
-void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt);
-void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 isEncrypt);
-void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len);
-void HTOnAssocRsp(struct ieee80211_device *ieee);
-void HTInitializeHTInfo(struct ieee80211_device* ieee);
-void HTInitializeBssDesc(PBSS_HT pBssHT);
-void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork);
-void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee,   struct ieee80211_network * pNetwork);
-u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter);
-extern u8 MCS_FILTER_ALL[];
-extern u16 MCS_DATA_RATE[2][2][77] ;
-u8 HTCCheck(struct ieee80211_device* ieee, u8*   pFrame);
-//extern void HTSetConnectBwModeCallback(unsigned long data);
-void HTResetIOTSetting(PRT_HIGH_THROUGHPUT  pHTInfo);
-bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee);
-u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee,  u8      nMcsRate);
-u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate);
-u16  TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate);
-//function in BAPROC.c
-int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb);
-int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb);
-int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb);
-void TsInitAddBA( struct ieee80211_device* ieee, PTX_TS_RECORD   pTS, u8 Policy, u8 bOverwritePending);
-void TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
-void BaSetupTimeOut(unsigned long data);
-void TxBaInactTimeout(unsigned long data);
-void RxBaInactTimeout(unsigned long data);
-void ResetBaEntry( PBA_RECORD pBA);
-//function in TS.c
-bool GetTs(
-        struct ieee80211_device*        ieee,
-        PTS_COMMON_INFO                 *ppTS,
-        u8*                             Addr,
-        u8                              TID,
-        TR_SELECT                       TxRxSelect,  //Rx:1, Tx:0
-        bool                            bAddNewTs
-        );
-void TSInitialize(struct ieee80211_device *ieee);
-void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD   pTxTS);
-void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr);
-void RemoveAllTS(struct ieee80211_device* ieee);
-void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee);
-
-extern const long ieee80211_wlan_frequencies[];
-
-extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee)
-{
-	ieee->scans++;
-}
-
-extern inline int ieee80211_get_scans(struct ieee80211_device *ieee)
-{
-	return ieee->scans;
-}
-
-static inline const char *escape_essid(const char *essid, u8 essid_len) {
-	static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
-	const char *s = essid;
-	char *d = escaped;
-
-	if (ieee80211_is_empty_essid(essid, essid_len)) {
-		memcpy(escaped, "<hidden>", sizeof("<hidden>"));
-		return escaped;
-	}
-
-	essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE);
-	while (essid_len--) {
-		if (*s == '\0') {
-			*d++ = '\\';
-			*d++ = '0';
-			s++;
-		} else {
-			*d++ = *s++;
-		}
-	}
-	*d = '\0';
-	return escaped;
-}
-
-/* For the function is more related to hardware setting, it's better to use the
- * ieee handler to refer to it.
- */
-short check_nic_enough_desc(struct net_device *dev, int queue_index);
-int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
-int ieee80211_parse_info_param(struct ieee80211_device *ieee,
-		struct ieee80211_info_element *info_element,
-		u16 length,
-		struct ieee80211_network *network,
-		struct ieee80211_rx_stats *stats);
-
-void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8  index);
-#define RT_ASOC_RETRY_LIMIT	5
-#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192e/ieee80211/dot11d.c b/drivers/staging/rtl8192e/ieee80211/dot11d.c
index 6bbf091..98e4648 100644
--- a/drivers/staging/rtl8192e/ieee80211/dot11d.c
+++ b/drivers/staging/rtl8192e/ieee80211/dot11d.c
@@ -53,8 +53,6 @@ Dot11d_Reset(struct ieee80211_device *ieee)
 	pDot11dInfo->State = DOT11D_STATE_NONE;
 	pDot11dInfo->CountryIeLen = 0;
 	RESET_CIE_WATCHDOG(ieee);
-
-	//printk("Dot11d_Reset()\n");
 }
 
 //
@@ -109,7 +107,6 @@ Dot11d_UpdateCountryIe(
 		pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
 	}
 #if 1
-	//printk("Dot11d_UpdateCountryIe(): Channel List:\n");
 	printk("Channel List:");
 	for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
 		if(pDot11dInfo->channel_map[i] > 0)
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
index dda6719..3ca3881 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -47,25 +47,6 @@
 #define IWEVCUSTOM 0x8c02
 #endif
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#ifndef __bitwise
-#define __bitwise __attribute__((bitwise))
-#endif
-typedef __u16  __le16;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27))
-struct iw_spy_data{
-	/* --- Standard spy support --- */
-	int 			spy_number;
-	u_char 			spy_address[IW_MAX_SPY][ETH_ALEN];
-	struct iw_quality	spy_stat[IW_MAX_SPY];
-	/* --- Enhanced spy support (event) */
-	struct iw_quality	spy_thr_low; /* Low threshold */
-	struct iw_quality	spy_thr_high; /* High threshold */
-	u_char			spy_thr_under[IW_MAX_SPY];
-};
-#endif
-#endif
-
 #ifndef container_of
 /**
  * container_of - cast a member of a structure out to the containing structure
@@ -370,12 +351,10 @@ enum	_ReasonCode{
 #define ieee80211_wx_get_scan		ieee80211_wx_get_scan_rsl
 #define ieee80211_wx_set_encode		ieee80211_wx_set_encode_rsl
 #define ieee80211_wx_get_encode		ieee80211_wx_get_encode_rsl
-#if WIRELESS_EXT >= 18
 #define ieee80211_wx_set_mlme		ieee80211_wx_set_mlme_rsl
 #define ieee80211_wx_set_auth		ieee80211_wx_set_auth_rsl
 #define ieee80211_wx_set_encode_ext	ieee80211_wx_set_encode_ext_rsl
 #define ieee80211_wx_get_encode_ext	ieee80211_wx_get_encode_ext_rsl
-#endif
 
 
 typedef struct ieee_param {
@@ -408,15 +387,6 @@ typedef struct ieee_param {
 }ieee_param;
 
 
-#if WIRELESS_EXT < 17
-#define IW_QUAL_QUAL_INVALID   0x10
-#define IW_QUAL_LEVEL_INVALID  0x20
-#define IW_QUAL_NOISE_INVALID  0x40
-#define IW_QUAL_QUAL_UPDATED   0x1
-#define IW_QUAL_LEVEL_UPDATED  0x2
-#define IW_QUAL_NOISE_UPDATED  0x4
-#endif
-
 // linux under 2.6.9 release may not support it, so modify it for common use
 #define MSECS(t) msecs_to_jiffies(t)
 #define msleep_interruptible_rsl  msleep_interruptible
@@ -880,7 +850,6 @@ struct ieee_ibss_seq {
  *       information for frames received.  Not setting these will not cause
  *       any adverse affects. */
 struct ieee80211_rx_stats {
-#if 1
 	u32 mac_time[2];
 	s8 rssi;
 	u8 signal;
@@ -895,7 +864,6 @@ struct ieee80211_rx_stats {
 	u32 beacon_time;
 	u8 nic_type;
 	u16       Length;
-	//      u8        DataRate;      // In 0.5 Mbps
 	u8        SignalQuality; // in 0-100 index.
 	s32       RecvSignalPower; // Real power in dBm for this packet, no beautification and aggregation.
 	s8        RxPower; // in dBm Translate from PWdB
@@ -924,26 +892,16 @@ struct ieee80211_rx_stats {
 	bool      bIsAMPDU;
 	bool      bFirstMPDU;
 	bool      bContainHTC;
-	bool      RxIs40MHzPacket;
 	u32       RxPWDBAll;
 	u8        RxMIMOSignalStrength[4];        // in 0~100 index
 	s8        RxMIMOSignalQuality[2];
 	bool      bPacketMatchBSSID;
 	bool      bIsCCK;
 	bool      bPacketToSelf;
-	//added by amy
 	u8*       virtual_address;
-	u16          packetlength;              // Total packet length: Must equal to sum of all FragLength
-	u16          fraglength;                        // FragLength should equal to PacketLength in non-fragment case
-	u16          fragoffset;                        // Data offset for this fragment
-	u16          ntotalfrag;
-	bool      	  bisrxaggrsubframe;
 	bool		  bPacketBeacon;	//cosa add for rssi
 	bool		  bToSelfBA;		//cosa add for rssi
 	char 	  cck_adc_pwdb[4];	//cosa add for rx path selection
-	u16		  Seq_Num;
-#endif
-
 };
 
 /* IEEE 802.11 requires that STA supports concurrent reception of at least
@@ -1298,7 +1256,7 @@ typedef union _frameqos {
 #define QOS_OUI_PARAM_SUB_TYPE          1
 #define QOS_VERSION_1                   1
 #define QOS_AIFSN_MIN_VALUE             2
-#if 1
+
 struct ieee80211_qos_information_element {
         u8 elementID;
         u8 length;
@@ -1373,7 +1331,7 @@ struct ieee80211_wmm_tspec_elem {
 	u16 surp_band_allow;
 	u16 medium_time;
 }__attribute__((packed));
-#endif
+
 enum eap_type {
 	EAP_PACKET = 0,
 	EAPOL_START,
@@ -1495,15 +1453,13 @@ enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame};
 #define MAX_RECEIVE_BUFFER_SIZE 9100
 
 //UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP
-//#define UP2AC(up)	((up<3) ? ((up==0)?1:0) : (up>>1))
-#if 1
 #define UP2AC(up) (		   \
 	((up) < 1) ? WME_AC_BE : \
 	((up) < 3) ? WME_AC_BK : \
 	((up) < 4) ? WME_AC_BE : \
 	((up) < 6) ? WME_AC_VI : \
 	WME_AC_VO)
-#endif
+
 //AC Mapping to UP, using in Tx part for selecting the corresponding TX queue
 #define AC2UP(_ac)	(       \
 	((_ac) == WME_AC_VO) ? 6 : \
@@ -1538,8 +1494,6 @@ typedef struct _bss_ht{
 	u16					ht_info_len;
 
 	HT_SPEC_VER			ht_spec_ver;
-	//HT_CAPABILITY_ELE			bdHTCapEle;
-	//HT_INFORMATION_ELE		bdHTInfoEle;
 
 	bool				aggregation;
 	bool				long_slot_time;
@@ -1559,12 +1513,7 @@ struct ieee80211_network {
 	/* Ensure null-terminated for any debug msgs */
 	u8 ssid[IW_ESSID_MAX_SIZE + 1];
 	u8 ssid_len;
-#if 1
         struct ieee80211_qos_data qos_data;
-#else
-       // Qos related. Added by Annie, 2005-11-01.
-        BSS_QOS   BssQos;
-#endif
 
 	//added by amy for LEAP
 	bool	bWithAironetIE;
@@ -1631,7 +1580,6 @@ struct ieee80211_network {
 	struct list_head list;
 };
 
-#if 1
 enum ieee80211_state {
 
 	/* the card is not linked at all */
@@ -1670,17 +1618,6 @@ enum ieee80211_state {
 	IEEE80211_LINKED_SCANNING,
 
 };
-#else
-enum ieee80211_state {
-        IEEE80211_UNINITIALIZED = 0,
-        IEEE80211_INITIALIZED,
-        IEEE80211_ASSOCIATING,
-        IEEE80211_ASSOCIATED,
-        IEEE80211_AUTHENTICATING,
-        IEEE80211_AUTHENTICATED,
-        IEEE80211_SHUTDOWN
-};
-#endif
 
 #define DEFAULT_MAX_SCAN_AGE (15 * HZ)
 #define DEFAULT_FTS 2346
@@ -1730,108 +1667,11 @@ typedef enum _Fsync_State{
 	SW_Fsync
 }Fsync_State;
 
-// Power save mode configured.
-typedef	enum _RT_PS_MODE
-{
-	eActive,	// Active/Continuous access.
-	eMaxPs,		// Max power save mode.
-	eFastPs		// Fast power save mode.
-}RT_PS_MODE;
-
-typedef enum _IPS_CALLBACK_FUNCION
-{
-	IPS_CALLBACK_NONE = 0,
-	IPS_CALLBACK_MGNT_LINK_REQUEST = 1,
-	IPS_CALLBACK_JOIN_REQUEST = 2,
-}IPS_CALLBACK_FUNCION;
-
-typedef enum _RT_JOIN_ACTION{
-	RT_JOIN_INFRA   = 1,
-	RT_JOIN_IBSS  = 2,
-	RT_START_IBSS = 3,
-	RT_NO_ACTION  = 4,
-}RT_JOIN_ACTION;
-
 typedef struct _IbssParms{
 	u16   atimWin;
 }IbssParms, *PIbssParms;
 #define MAX_NUM_RATES	264 // Max num of support rates element: 8,  Max num of ext. support rate: 255. 061122, by rcnjko.
 
-// RF state.
-typedef	enum _RT_RF_POWER_STATE
-{
-	eRfOn,
-	eRfSleep,
-	eRfOff
-}RT_RF_POWER_STATE;
-
-typedef struct _RT_POWER_SAVE_CONTROL
-{
-
-	//
-	// Inactive Power Save(IPS) : Disable RF when disconnected
-	//
-	bool				bInactivePs;
-	bool				bIPSModeBackup;
-	bool				bSwRfProcessing;
-	RT_RF_POWER_STATE	eInactivePowerState;
-	struct work_struct 	InactivePsWorkItem;
-	struct timer_list	InactivePsTimer;
-
-	// Return point for join action
-	IPS_CALLBACK_FUNCION	ReturnPoint;
-
-	// Recored Parameters for rescheduled JoinRequest
-	bool				bTmpBssDesc;
-	RT_JOIN_ACTION		tmpJoinAction;
-	struct ieee80211_network tmpBssDesc;
-
-	// Recored Parameters for rescheduled MgntLinkRequest
-	bool				bTmpScanOnly;
-	bool				bTmpActiveScan;
-	bool				bTmpFilterHiddenAP;
-	bool				bTmpUpdateParms;
-	u8					tmpSsidBuf[33];
-	OCTET_STRING			tmpSsid2Scan;
-	bool				bTmpSsid2Scan;
-	u8					tmpNetworkType;
-	u8					tmpChannelNumber;
-	u16					tmpBcnPeriod;
-	u8					tmpDtimPeriod;
-	u16					tmpmCap;
-	OCTET_STRING			tmpSuppRateSet;
-	u8					tmpSuppRateBuf[MAX_NUM_RATES];
-	bool				bTmpSuppRate;
-	IbssParms				tmpIbpm;
-	bool				bTmpIbpm;
-
-	//
-	// Leisre Poswer Save : Disable RF if connected but traffic is not busy
-	//
-	bool				bLeisurePs;
-	u32				PowerProfile;
-	u8				LpsIdleCount;
-	u8				RegMaxLPSAwakeIntvl;
-	u8				LPSAwakeIntvl;
-
-	u32				CurPsLevel;
-	u32				RegRfPsLevel;
-
-	bool				bFwCtrlLPS;
-	u8				FWCtrlPSMode;
-
-	bool				LinkReqInIPSRFOffPgs;
-	bool				BufConnectinfoBefore;
-
-}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL;
-
-typedef u32 RT_RF_CHANGE_SOURCE;
-#define RF_CHANGE_BY_SW BIT31
-#define RF_CHANGE_BY_HW BIT30
-#define RF_CHANGE_BY_PS BIT29
-#define RF_CHANGE_BY_IPS BIT28
-#define RF_CHANGE_BY_INIT	0	// Do not change the RFOff reason. Defined by Bruce, 2008-01-17.
-
 #ifdef ENABLE_DOT11D
 typedef enum
 {
@@ -1919,7 +1759,7 @@ typedef 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,			// Set lookback mode, 2008.06.11. added by Roger.
 	// Set HW related setting for 11N AES bug.
 	HW_VAR_AES_11N_FIX,
@@ -1963,7 +1803,7 @@ struct ieee80211_device {
 	u8  LPSDelayCnt;
 	bool bIsAggregateFrame;
 	bool polling;
-	void (*LeisurePSLeave)(struct net_device *dev);
+	void (*LeisurePSLeave)(struct ieee80211_device *ieee);
 #endif
 
 #ifdef ENABLE_IPS
@@ -1971,32 +1811,25 @@ struct ieee80211_device {
 	bool wx_set_enc;
 	struct semaphore ips_sem;
 	struct work_struct ips_leave_wq;
-        void (*ieee80211_ips_leave_wq) (struct net_device *dev);
-        void (*ieee80211_ips_leave)(struct net_device *dev);
+        void (*ieee80211_ips_leave_wq) (struct ieee80211_device *ieee);
+        void (*ieee80211_ips_leave)(struct ieee80211_device *ieee);
 #endif
-	void (*SetHwRegHandler)(struct net_device *dev,u8 variable,u8* val);
+	void (*SetHwRegHandler)(struct ieee80211_device *ieee, u8 variable, u8 *val);
 	u8   (*rtllib_ap_sec_type)(struct ieee80211_device *ieee);
 
 	//hw security related
-//	u8 hwsec_support; //support?
 	u8 hwsec_active;  //hw security active.
 	bool is_silent_reset;
 	bool is_roaming;
 	bool ieee_up;
-	//added by amy
 	bool bSupportRemoteWakeUp;
-	RT_PS_MODE	dot11PowerSaveMode; // Power save mode configured.
 	bool actscanning;
 	bool beinretry;
-	RT_RF_POWER_STATE		eRFPowerState;
-	RT_RF_CHANGE_SOURCE	RfOffReason;
 	bool is_set_key;
 	//11n spec related I wonder if These info structure need to be moved out of ieee80211_device
 
 	//11n HT below
 	PRT_HIGH_THROUGHPUT	pHTInfo;
-	//struct timer_list		SwBwTimer;
-//	spinlock_t chnlop_spinlock;
 	spinlock_t bw_spinlock;
 
 	spinlock_t reorder_spinlock;
@@ -2012,8 +1845,6 @@ struct ieee80211_device {
 	u8 	bTxUseDriverAssingedRate;
 	atomic_t	atm_chnlop;
 	atomic_t	atm_swbw;
-//	u8	HTHighestOperaRate;
-//	u8 	HTCurrentOperaRate;
 
 	// 802.11e and WMM Traffic Stream Info (TX)
 	struct list_head		Tx_TS_Admit_List;
@@ -2025,12 +1856,8 @@ struct ieee80211_device {
 	struct list_head		Rx_TS_Pending_List;
 	struct list_head		Rx_TS_Unused_List;
 	RX_TS_RECORD		RxTsRecord[TOTAL_TS_NUM];
-//#ifdef TO_DO_LIST
 	RX_REORDER_ENTRY	RxReorderEntry[128];
 	struct list_head		RxReorder_Unused_List;
-//#endif
-	// Qos related. Added by Annie, 2005-11-01.
-//	PSTA_QOS			pStaQos;
 	u8				ForcedPriority;		// Force per-packet priority 1~7. (default: 0, not to force it.)
 
 
@@ -2209,12 +2036,13 @@ struct ieee80211_device {
 
 	/* for PS mode */
 	unsigned long last_rx_ps_time;
+	u8 LPSAwakeIntvl;
+	u8 RegMaxLPSAwakeIntvl;
 
 	/* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */
 	struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM];
 	int mgmt_queue_head;
 	int mgmt_queue_tail;
-//{ added for rtl819x
 #define IEEE80211_QUEUE_LIMIT 128
 	u8 AsocRetryCount;
 	unsigned int hw_header;
@@ -2251,9 +2079,7 @@ struct ieee80211_device {
 
 	//added by amy for AP roaming
 	RT_LINK_DETECT_T	LinkDetectInfo;
-        //added by amy for ps
-	RT_POWER_SAVE_CONTROL	PowerSaveControl;
-//}
+
 	/* used if IEEE_SOFTMAC_TX_QUEUE is set */
 	struct  tx_pending_t tx_pending;
 
@@ -2268,19 +2094,12 @@ struct ieee80211_device {
         struct delayed_work associate_retry_wq;
 	 struct delayed_work start_ibss_wq;
 	 struct delayed_work hw_wakeup_wq;
-	struct delayed_work hw_sleep_wq;
 
         struct work_struct wx_sync_scan_wq;
         struct workqueue_struct *wq;
-        // Qos related. Added by Annie, 2005-11-01.
-        //STA_QOS  StaQos;
-
-        //u32 STA_EDCA_PARAM[4];
-	//CHANNEL_ACCESS_SETTING ChannelAccessSetting;
-
 
 	/* Callback functions */
-	void (*set_security)(struct net_device *dev,
+	void (*set_security)(struct ieee80211_device *ieee,
 			     struct ieee80211_security *sec);
 
 	/* Used to TX data frame by using txb structs.
@@ -2288,14 +2107,14 @@ struct ieee80211_device {
 	 * is set the flag IEEE_SOFTMAC_TX_QUEUE
 	 */
 	int (*hard_start_xmit)(struct ieee80211_txb *txb,
-			       struct net_device *dev);
+			       struct ieee80211_device *ieee);
 
-	int (*reset_port)(struct net_device *dev);
-        int (*is_queue_full) (struct net_device * dev, int pri);
+	int (*reset_port)(struct ieee80211_device *ieee);
+        int (*is_queue_full) (struct ieee80211_device *ieee, int pri);
 
-        int (*handle_management) (struct net_device * dev,
+        int (*handle_management) (struct ieee80211_device *ieee,
                                   struct ieee80211_network * network, u16 type);
-        int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
+        int (*is_qos_active) (struct ieee80211_device *ieee, struct sk_buff *skb);
 
 	/* Softmac-generated frames (mamagement) are TXed via this
 	 * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is
@@ -2305,7 +2124,7 @@ struct ieee80211_device {
 	 * This fucntion can't sleep.
 	 */
 	int (*softmac_hard_start_xmit)(struct sk_buff *skb,
-			       struct net_device *dev);
+			       struct ieee80211_device *ieee80211);
 
 	/* used instead of hard_start_xmit (not softmac_hard_start_xmit)
 	 * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data
@@ -2314,22 +2133,22 @@ struct ieee80211_device {
 	 * This function can't sleep.
 	 */
 	void (*softmac_data_hard_start_xmit)(struct sk_buff *skb,
-			       struct net_device *dev,int rate);
+			       struct ieee80211_device *ieee80211, int rate);
 
 	/* stops the HW queue for DATA frames. Useful to avoid
 	 * waste time to TX data frame when we are reassociating
 	 * This function can sleep.
 	 */
-	void (*data_hard_stop)(struct net_device *dev);
+	void (*data_hard_stop)(struct ieee80211_device *ieee80211);
 
 	/* OK this is complementar to data_poll_hard_stop */
-	void (*data_hard_resume)(struct net_device *dev);
+	void (*data_hard_resume)(struct ieee80211_device *ieee80211);
 
 	/* ask to the driver to retune the radio .
 	 * This function can sleep. the driver should ensure
 	 * the radio has been swithced before return.
 	 */
-	void (*set_chan)(struct net_device *dev,short ch);
+	void (*set_chan)(struct ieee80211_device *ieee80211, short ch);
 
 	/* These are not used if the ieee stack takes care of
 	 * scanning (IEEE_SOFTMAC_SCAN feature set).
@@ -2346,16 +2165,16 @@ struct ieee80211_device {
 	 * The fucntion start_scan should initiate the background
 	 * scanning and can't sleep.
 	 */
-	void (*scan_syncro)(struct net_device *dev);
-	void (*start_scan)(struct net_device *dev);
-	void (*stop_scan)(struct net_device *dev);
+	void (*scan_syncro)(struct ieee80211_device *ieee80211);
+	void (*start_scan)(struct ieee80211_device *ieee80211);
+	void (*stop_scan)(struct ieee80211_device *ieee80211);
 
 	/* indicate the driver that the link state is changed
 	 * for example it may indicate the card is associated now.
 	 * Driver might be interested in this to apply RX filter
 	 * rules or simply light the LINK led
 	 */
-	void (*link_change)(struct net_device *dev);
+	void (*link_change)(struct ieee80211_device *ieee80211);
 
 	/* these two function indicates to the HW when to start
 	 * and stop to send beacons. This is used when the
@@ -2363,54 +2182,24 @@ struct ieee80211_device {
 	 * stop_send_bacons is NOT guaranteed to be called only
 	 * after start_send_beacons.
 	 */
-	void (*start_send_beacons) (struct net_device *dev);
-	void (*stop_send_beacons) (struct net_device *dev);
+	void (*start_send_beacons) (struct ieee80211_device *dev);
+	void (*stop_send_beacons) (struct ieee80211_device *dev);
 
 	/* power save mode related */
-	void (*sta_wake_up) (struct net_device *dev);
-//	void (*ps_request_tx_ack) (struct net_device *dev);
-	void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl);
-	short (*ps_is_queue_empty) (struct net_device *dev);
-#if 0
-	/* Typical STA methods */
-        int (*handle_auth) (struct net_device * dev,
-                            struct ieee80211_auth * auth);
-        int (*handle_deauth) (struct net_device * dev,
-                              struct ieee80211_deauth * auth);
-        int (*handle_action) (struct net_device * dev,
-                              struct ieee80211_action * action,
-                              struct ieee80211_rx_stats * stats);
-        int (*handle_disassoc) (struct net_device * dev,
-                                struct ieee80211_disassoc * assoc);
-#endif
-        int (*handle_beacon) (struct net_device * dev, struct ieee80211_beacon * beacon, struct ieee80211_network * network);
-#if 0
-        int (*handle_probe_response) (struct net_device * dev,
-                                      struct ieee80211_probe_response * resp,
-                                      struct ieee80211_network * network);
-        int (*handle_probe_request) (struct net_device * dev,
-                                     struct ieee80211_probe_request * req,
-                                     struct ieee80211_rx_stats * stats);
-#endif
-        int (*handle_assoc_response) (struct net_device * dev, struct ieee80211_assoc_response_frame * resp, struct ieee80211_network * network);
-
-#if 0
-        /* Typical AP methods */
-        int (*handle_assoc_request) (struct net_device * dev);
-        int (*handle_reassoc_request) (struct net_device * dev,
-                                       struct ieee80211_reassoc_request * req);
-#endif
+	void (*sta_wake_up) (struct ieee80211_device *ieee80211);
+	void (*enter_sleep_state) (struct ieee80211_device *ieee80211, u32 th, u32 tl);
+	short (*ps_is_queue_empty) (struct ieee80211_device *ieee80211);
+        int (*handle_beacon) (struct ieee80211_device *ieee80211, struct ieee80211_beacon *beacon, struct ieee80211_network *network);
+        int (*handle_assoc_response) (struct ieee80211_device *ieee80211, struct ieee80211_assoc_response_frame *resp, struct ieee80211_network *network);
 
 	/* check whether Tx hw resouce available */
-	short (*check_nic_enough_desc)(struct net_device *dev, int queue_index);
+	short (*check_nic_enough_desc)(struct ieee80211_device *ieee80211, int queue_index);
 	//added by wb for HT related
-//	void (*SwChnlByTimerHandler)(struct net_device *dev, int channel);
-	void (*SetBWModeHandler)(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
-//	void (*UpdateHalRATRTableHandler)(struct net_device* dev, u8* pMcsRate);
-	bool (*GetNmodeSupportBySecCfg)(struct net_device* dev);
-	void (*SetWirelessMode)(struct net_device* dev, u8 wireless_mode);
-	bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device* dev);
-	void (*InitialGainHandler)(struct net_device *dev, u8 Operation);
+	void (*SetBWModeHandler)(struct ieee80211_device *ieee80211, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+	bool (*GetNmodeSupportBySecCfg)(struct ieee80211_device *ieee80211);
+	void (*SetWirelessMode)(struct ieee80211_device *ieee80211, u8 wireless_mode);
+	bool (*GetHalfNmodeSupportByAPsHandler)(struct ieee80211_device *ieee80211);
+	void (*InitialGainHandler)(struct ieee80211_device *ieee80211, u8 Operation);
 
 	/* This must be the last item so that it points to the data
 	 * allocated beyond this structure by alloc_ieee80211 */
@@ -2587,205 +2376,200 @@ static inline int ieee80211_is_cck_rate(u8 rate)
 
 
 /* ieee80211.c */
-extern void free_ieee80211(struct net_device *dev);
-extern struct net_device *alloc_ieee80211(int sizeof_priv);
+void free_ieee80211(struct net_device *dev);
+struct net_device *alloc_ieee80211(int sizeof_priv);
 
-extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
+int ieee80211_set_encryption(struct ieee80211_device *ieee);
 
 /* ieee80211_tx.c */
 
-extern int ieee80211_encrypt_fragment(
+int ieee80211_encrypt_fragment(
 	struct ieee80211_device *ieee,
 	struct sk_buff *frag,
 	int hdr_len);
 
-extern int ieee80211_rtl_xmit(struct sk_buff *skb,
+int ieee80211_rtl_xmit(struct sk_buff *skb,
 			  struct net_device *dev);
-extern void ieee80211_txb_free(struct ieee80211_txb *);
+void ieee80211_txb_free(struct ieee80211_txb *);
 
 
 /* ieee80211_rx.c */
-extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats);
-extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+void ieee80211_rx_mgt(struct ieee80211_device *ieee,
 			     struct ieee80211_hdr_4addr *header,
 			     struct ieee80211_rx_stats *stats);
 
 /* ieee80211_wx.c */
-extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
 				 struct iw_request_info *info,
 				 union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
+int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 				   struct iw_request_info *info,
 				   union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
+int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
 				   struct iw_request_info *info,
 				   union iwreq_data *wrqu, char *key);
-#if WIRELESS_EXT >= 18
-extern int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
+int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
                             struct iw_request_info *info,
                             union iwreq_data* wrqu, char *extra);
-extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
+int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                             struct iw_request_info *info,
                             union iwreq_data* wrqu, char *extra);
-extern int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
+int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
                                struct iw_request_info *info,
                                struct iw_param *data, char *extra);
-extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
+int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
                                struct iw_request_info *info,
                                union iwreq_data *wrqu, char *extra);
-#endif
-extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
+int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
 
 /* ieee80211_softmac.c */
-extern short ieee80211_is_54g(struct ieee80211_network net);
-extern short ieee80211_is_shortslot(struct ieee80211_network net);
-extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
+short ieee80211_is_54g(struct ieee80211_network net);
+short ieee80211_is_shortslot(struct ieee80211_network net);
+int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 			struct ieee80211_rx_stats *rx_stats, u16 type,
 			u16 stype);
-extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
+void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
 
 void SendDisassociation(struct ieee80211_device *ieee, u8* asSta, u8 asRsn);
-extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
-
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_master_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_ibss(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_init(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_free(struct ieee80211_device *ieee);
-extern void ieee80211_associate_abort(struct ieee80211_device *ieee);
-extern void ieee80211_disassociate(struct ieee80211_device *ieee);
-extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
-extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
-extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
-extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
-extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
-extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
-extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
-
-extern void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
+void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
+
+void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+void notify_wx_assoc_event(struct ieee80211_device *ieee);
+void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
+void ieee80211_start_bss(struct ieee80211_device *ieee);
+void ieee80211_start_master_bss(struct ieee80211_device *ieee);
+void ieee80211_start_ibss(struct ieee80211_device *ieee);
+void ieee80211_softmac_init(struct ieee80211_device *ieee);
+void ieee80211_softmac_free(struct ieee80211_device *ieee);
+void ieee80211_associate_abort(struct ieee80211_device *ieee);
+void ieee80211_disassociate(struct ieee80211_device *ieee);
+void ieee80211_stop_scan(struct ieee80211_device *ieee);
+void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
+void ieee80211_check_all_nets(struct ieee80211_device *ieee);
+void ieee80211_start_protocol(struct ieee80211_device *ieee);
+void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
+void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
+void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
+void ieee80211_reset_queue(struct ieee80211_device *ieee);
+void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
+void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
+struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
+void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
+void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
+void notify_wx_assoc_event(struct ieee80211_device *ieee);
+void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
+
+void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
 
 /* ieee80211_crypt_ccmp&tkip&wep.c */
-extern void ieee80211_tkip_null(void);
-extern void ieee80211_wep_null(void);
-extern void ieee80211_ccmp_null(void);
+void ieee80211_tkip_null(void);
+void ieee80211_wep_null(void);
+void ieee80211_ccmp_null(void);
 
 /* ieee80211_softmac_wx.c */
 
-extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
+int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
 			    struct iw_request_info *info,
 			    union iwreq_data *wrqu, char *ext);
 
-extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
+int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
 			 struct iw_request_info *info,
 			 union iwreq_data *awrq,
 			 char *extra);
 
-extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
+int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
 
-extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
+int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
 			     struct iw_request_info *info,
 			     union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
+int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
 			     struct iw_request_info *info,
 			     union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
+int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
+int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
+int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
 			      struct iw_request_info *a,
 			      union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
+int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
+int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b);
 
-extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
+int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
 			     union iwreq_data *wrqu, char *b);
 
-//extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee);
-extern void ieee80211_wx_sync_scan_wq(struct work_struct *work);
-
+void ieee80211_wx_sync_scan_wq(struct work_struct *work);
 
-extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
+int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
 			       struct iw_request_info *info,
 			       union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_name(struct ieee80211_device *ieee,
+int ieee80211_wx_get_name(struct ieee80211_device *ieee,
 			     struct iw_request_info *info,
 			     union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_set_power(struct ieee80211_device *ieee,
+int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 				 struct iw_request_info *info,
 				 union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_power(struct ieee80211_device *ieee,
+int ieee80211_wx_get_power(struct ieee80211_device *ieee,
 				 struct iw_request_info *info,
 				 union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
+int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
 			     struct iw_request_info *info,
 			     union iwreq_data *wrqu, char *extra);
 
-extern int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
+int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
 			     struct iw_request_info *info,
 			     union iwreq_data *wrqu, char *extra);
 //HT
-#define MAX_RECEIVE_BUFFER_SIZE 9100  //
-extern void HTDebugHTCapability(u8* CapIE, u8* TitleString );
-extern void HTDebugHTInfo(u8*  InfoIE, u8* TitleString);
-
-void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET    Offset);
-extern void HTUpdateDefaultSetting(struct ieee80211_device* ieee);
-extern void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt);
-extern void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* len, u8 isEncrypt);
-extern void HTConstructRT2RTAggElement(struct ieee80211_device* ieee, u8* posRT2RTAgg, u8* len);
-extern void HTOnAssocRsp(struct ieee80211_device *ieee);
-extern void HTInitializeHTInfo(struct ieee80211_device* ieee);
-extern void HTInitializeBssDesc(PBSS_HT pBssHT);
-extern void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80211_network * pNetwork);
-extern void HTUpdateSelfAndPeerSetting(struct ieee80211_device* ieee,   struct ieee80211_network * pNetwork);
-extern u8 HTGetHighestMCSRate(struct ieee80211_device* ieee, u8* pMCSRateSet, u8* pMCSFilter);
+#define MAX_RECEIVE_BUFFER_SIZE 9100
+void HTDebugHTCapability(u8 *CapIE, u8 *TitleString );
+void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
+
+void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
+void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u8 *len, u8 isEncrypt);
+void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *len, u8 isEncrypt);
+void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg, u8 *len);
+void HTOnAssocRsp(struct ieee80211_device *ieee);
+void HTInitializeHTInfo(struct ieee80211_device *ieee);
+void HTInitializeBssDesc(PBSS_HT pBssHT);
+void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
+void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
+u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSFilter);
 extern u8 MCS_FILTER_ALL[];
 extern u16 MCS_DATA_RATE[2][2][77] ;
-extern u8 HTCCheck(struct ieee80211_device* ieee, u8*   pFrame);
-//extern void HTSetConnectBwModeCallback(unsigned long data);
-extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT  pHTInfo);
-extern bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee);
-extern u16 HTHalfMcsToDataRate(struct ieee80211_device* ieee,  u8      nMcsRate);
-extern u16 HTMcsToDataRate( struct ieee80211_device* ieee, u8 nMcsRate);
-extern u16  TxCountToDataRate( struct ieee80211_device* ieee, u8 nDataRate);
-//function in BAPROC.c
-extern int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb);
-extern int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb);
-extern int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb);
-extern void TsInitAddBA( struct ieee80211_device* ieee, PTX_TS_RECORD   pTS, u8 Policy, u8 bOverwritePending);
-extern void TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
-extern void BaSetupTimeOut(unsigned long data);
-extern void TxBaInactTimeout(unsigned long data);
-extern void RxBaInactTimeout(unsigned long data);
-extern void ResetBaEntry( PBA_RECORD pBA);
+
+u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
+void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo);
+bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
+u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
+u16 HTMcsToDataRate( struct ieee80211_device *ieee, u8 nMcsRate);
+u16  TxCountToDataRate( struct ieee80211_device *ieee, u8 nDataRate);
+int ieee80211_rx_ADDBAReq( struct ieee80211_device *ieee, struct sk_buff *skb);
+int ieee80211_rx_ADDBARsp( struct ieee80211_device *ieee, struct sk_buff *skb);
+int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb);
+void TsInitAddBA( struct ieee80211_device *ieee, PTX_TS_RECORD pTS, u8 Policy, u8 bOverwritePending);
+void TsInitDelBA( struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
+void BaSetupTimeOut(unsigned long data);
+void TxBaInactTimeout(unsigned long data);
+void RxBaInactTimeout(unsigned long data);
+void ResetBaEntry( PBA_RECORD pBA);
 //function in TS.c
-extern bool GetTs(
+bool GetTs(
         struct ieee80211_device*        ieee,
         PTS_COMMON_INFO                 *ppTS,
         u8*                             Addr,
@@ -2793,10 +2577,10 @@ extern bool GetTs(
         TR_SELECT                       TxRxSelect,  //Rx:1, Tx:0
         bool                            bAddNewTs
         );
-extern void TSInitialize(struct ieee80211_device *ieee);
-extern  void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD   pTxTS);
-extern void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr);
-extern void RemoveAllTS(struct ieee80211_device* ieee);
+void TSInitialize(struct ieee80211_device *ieee);
+void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS);
+void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
+void RemoveAllTS(struct ieee80211_device *ieee);
 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee);
 
 extern const long ieee80211_wlan_frequencies[];
@@ -2838,9 +2622,8 @@ static inline const char *escape_essid(const char *essid, u8 essid_len) {
 /* For the function is more related to hardware setting, it's better to use the
  * ieee handler to refer to it.
  */
-extern short check_nic_enough_desc(struct net_device *dev, int queue_index);
-extern int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
-extern int ieee80211_parse_info_param(struct ieee80211_device *ieee,
+int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
+int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 		struct ieee80211_info_element *info_element,
 		u16 length,
 		struct ieee80211_network *network,
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
index a4e21cb..9b8533f 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -319,11 +319,6 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	pos += 8;
 
 	if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
-		if (net_ratelimit()) {
-			//printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
-			//       " previous PN %pm received PN %pm\n",
-			//       hdr->addr2, key->rx_pn, pn);
-		}
 		key->dot11RSNAStatsCCMPReplays++;
 		return -4;
 	}
@@ -456,7 +451,6 @@ static char * ieee80211_ccmp_print_stats(char *p, void *priv)
 
 void ieee80211_ccmp_null(void)
 {
-//    printk("============>%s()\n", __FUNCTION__);
 	return;
 }
 
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
index 14ca610..b32b7e6 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
@@ -324,18 +324,6 @@ static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv)
 
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 
-#if 0
-printk("@@ tkey\n");
-printk("%x|", ((u32*)tkey->key)[0]);
-printk("%x|", ((u32*)tkey->key)[1]);
-printk("%x|", ((u32*)tkey->key)[2]);
-printk("%x|", ((u32*)tkey->key)[3]);
-printk("%x|", ((u32*)tkey->key)[4]);
-printk("%x|", ((u32*)tkey->key)[5]);
-printk("%x|", ((u32*)tkey->key)[6]);
-printk("%x\n", ((u32*)tkey->key)[7]);
-#endif
-
 	if (!tcb_desc->bHwSec)
 	{
 		if (!tkey->tx_phase1_done) {
@@ -512,18 +500,6 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
 	skb_pull(skb, 8);
 	skb_trim(skb, skb->len - 4);
 
-//john's test
-#ifdef JOHN_DUMP
-if( ((u16*)skb->data)[0] & 0x4000){
-        printk("@@ rx decrypted skb->data");
-        int i;
-        for(i=0;i<skb->len;i++){
-                if( (i%24)==0 ) printk("\n");
-                printk("%2x ", ((u8*)skb->data)[i]);
-        }
-        printk("\n");
-}
-#endif /*JOHN_DUMP*/
 	return keyidx;
 }
 
@@ -829,7 +805,6 @@ void ieee80211_crypto_tkip_exit(void)
 
 void ieee80211_tkip_null(void)
 {
-//    printk("============>%s()\n", __FUNCTION__);
         return;
 }
 
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
index 5dc9764..e626472 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_wep.c
@@ -9,7 +9,6 @@
  * more details.
  */
 
-//#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
index 08bfdb1..663b0b8 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
@@ -195,11 +195,8 @@ void free_ieee80211(struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	int i;
-	if (ieee->pHTInfo != NULL)
-	{
-		kfree(ieee->pHTInfo);
-		ieee->pHTInfo = NULL;
-	}
+	kfree(ieee->pHTInfo);
+	ieee->pHTInfo = NULL;
 	RemoveAllTS(ieee);
 	ieee80211_softmac_free(ieee);
 	del_timer_sync(&ieee->crypt_deinit_timer);
@@ -222,7 +219,7 @@ void free_ieee80211(struct net_device *dev)
 #ifdef CONFIG_IEEE80211_DEBUG
 
 u32 ieee80211_debug_level = 0;
-static int debug = \
+static int debug =
 	/* IEEE80211_DL_INFO	| */
 	/* IEEE80211_DL_WX	| */
 	/* IEEE80211_DL_SCAN	| */
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
index 9318695..add015e 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -22,7 +22,6 @@
 
 
 #include <linux/compiler.h>
-//#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -225,7 +224,6 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 
 	rx_stats->len = skb->len;
 	ieee80211_rx_mgt(ieee,(struct ieee80211_hdr_4addr *)skb->data,rx_stats);
-        //if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN)))
         if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))//use ADDR1 to perform address matching for Management frames
         {
                 dev_kfree_skb_any(skb);
@@ -243,9 +241,6 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 		printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
 		       ieee->dev->name);
 		return 0;
-/*
-  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
-  skb->data);*/
 	}
 
 	if (ieee->hostapd && type == IEEE80211_TYPE_MGMT) {
@@ -308,7 +303,6 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
 	if (skb->len < 24)
 		return 0;
 
-#if 1
         if (ieee->hwsec_active)
         {
                 cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
@@ -317,7 +311,6 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
                 if(ieee->need_sw_enc)
                         tcb_desc->bHwSec = 0;
         }
-#endif
 
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	fc = le16_to_cpu(hdr->frame_ctl);
@@ -339,7 +332,6 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
 		return 0;
 
 	/* check for port access entity Ethernet type */
-//	pos = skb->data + 24;
 	pos = skb->data + hdrlen;
 	ethertype = (pos[6] << 8) | pos[7];
 	if (ethertype == ETH_P_PAE)
@@ -358,13 +350,13 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
 
 	if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
 		return 0;
-#if 1
+
 	if (ieee->hwsec_active)
 	{
 		cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
 		tcb_desc->bHwSec = 1;
 	}
-#endif
+
 	hdr = (struct ieee80211_hdr_4addr *) skb->data;
 	hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 
@@ -474,14 +466,13 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
 		struct ieee_ibss_seq *entry = NULL;
 		u8 *mac = header->addr2;
 		int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
-		//for (pos = (head)->next; pos != (head); pos = pos->next)
-		//__list_for_each(p, &ieee->ibss_mac_hash[index]) {
+
 		list_for_each(p, &ieee->ibss_mac_hash[index]) {
 			entry = list_entry(p, struct ieee_ibss_seq, list);
 			if (!memcmp(entry->mac, mac, ETH_ALEN))
 				break;
 		}
-	//	if (memcmp(entry->mac, mac, ETH_ALEN)){
+
 		if (p == &ieee->ibss_mac_hash[index]) {
 			entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
 			if (!entry) {
@@ -511,19 +502,14 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
 		return 0;
 	}
 
-//	if(tid != 0) {
-//		printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
-//	}
 	if ((*last_seq == seq) &&
 	    time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
 		if (*last_frag == frag){
-			//printk(KERN_WARNING "[1] go drop!\n");
 			goto drop;
 
 		}
 		if (*last_frag + 1 != frag)
 			/* out-of-order fragment */
-			//printk(KERN_WARNING "[2] go drop!\n");
 			goto drop;
 	} else
 		*last_seq = seq;
@@ -533,9 +519,6 @@ static int is_duplicate_packet(struct ieee80211_device *ieee,
 	return 0;
 
 drop:
-//	BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
-//	printk("DUP\n");
-
 	return 1;
 }
 bool
@@ -545,7 +528,7 @@ AddReorderEntry(
 	)
 {
 	struct list_head *pList = &pTS->RxPendingPktList;
-#if  1
+
 	while(pList->next != &pTS->RxPendingPktList)
 	{
 		if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
@@ -561,7 +544,7 @@ AddReorderEntry(
 			break;
 		}
 	}
-#endif
+
 	pReorderEntry->List.next = pList->next;
 	pReorderEntry->List.next->prev = &pReorderEntry->List;
 	pReorderEntry->List.prev = pList;
@@ -574,8 +557,7 @@ void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_
 {
 	u8 i = 0 , j=0;
 	u16 ethertype;
-//	if(index > 1)
-//		IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__FUNCTION__,index);
+
 	for(j = 0; j<index; j++)
 	{
 //added by amy for reorder
@@ -602,19 +584,14 @@ void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_
 				memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
 				memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
 			}
-			//stats->rx_packets++;
-			//stats->rx_bytes += sub_skb->len;
 
 		/* Indicat the packets to upper layer */
 			if (sub_skb) {
-				//printk("0skb_len(%d)\n", skb->len);
 				sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
 				memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
 				sub_skb->dev = ieee->dev;
 				sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
-				//skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */
 				ieee->last_rx_ps_time = jiffies;
-				//printk("1skb_len(%d)\n", skb->len);
 				netif_rx(sub_skb);
 			}
 		}
@@ -637,10 +614,7 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 	u8			index = 0;
 	bool			bMatchWinStart = false, bPktInBuf = false;
 	IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize);
-#if 0
-	if(!list_empty(&ieee->RxReorder_Unused_List))
-		IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): ieee->RxReorder_Unused_List is nut NULL\n");
-#endif
+
 	/* Rx Reorder initialize condition.*/
 	if(pTS->RxIndicateSeq == 0xffff) {
 		pTS->RxIndicateSeq = SeqNum;
@@ -693,11 +667,9 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 		IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\
 				pTS->RxIndicateSeq, SeqNum);
 		prxbIndicateArray[0] = prxb;
-//		printk("========================>%s(): SeqNum is %d\n",__FUNCTION__,SeqNum);
 		index = 1;
 	} else {
 		/* Current packet is going to be inserted into pending list.*/
-		//IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to orderd list\n",__FUNCTION__);
 		if(!list_empty(&ieee->RxReorder_Unused_List)) {
 			pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List);
 			list_del_init(&pReorderEntry->List);
@@ -705,9 +677,7 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 			/* Make a reorder entry and insert into a the packet list.*/
 			pReorderEntry->SeqNum = SeqNum;
 			pReorderEntry->prxb = prxb;
-	//		IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__FUNCTION__,pReorderEntry->SeqNum);
 
-#if 1
 			if(!AddReorderEntry(pTS, pReorderEntry)) {
 				IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
 					__FUNCTION__, pTS->RxIndicateSeq, SeqNum);
@@ -724,7 +694,6 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 				IEEE80211_DEBUG(IEEE80211_DL_REORDER,
 					 "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
 			}
-#endif
 		}
 		else {
 			/*
@@ -766,7 +735,6 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 
 			IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
 			prxbIndicateArray[index] = pReorderEntry->prxb;
-		//	printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__FUNCTION__,pReorderEntry->SeqNum);
 			index++;
 
 			list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
@@ -793,21 +761,13 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 		bPktInBuf = false;
 	}
 
-#if 1
 	if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
 		// Set new pending timer.
 		IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__);
 		pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
-#if 0
-		if(timer_pending(&pTS->RxPktPendingTimer))
-			del_timer_sync(&pTS->RxPktPendingTimer);
-		pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime);
-		add_timer(&pTS->RxPktPendingTimer);
-#else
+
 		mod_timer(&pTS->RxPktPendingTimer,  jiffies + MSECS(pHTInfo->RxReorderPendingTime));
-#endif
 	}
-#endif
 }
 
 u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
@@ -841,7 +801,6 @@ u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
 	if(rx_stats->bContainHTC) {
 		LLCOffset += sHTCLng;
 	}
-	//printk("ChkLength = %d\n", LLCOffset);
 	// Null packet, don't indicate it to upper layer
 	ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/
 
@@ -875,11 +834,6 @@ u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
 			nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8);
 
 			if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
-#if 0//cosa
-				RT_ASSERT(
-						(nRemain_Length>=(ETHERNET_HEADER_SIZE + nSubframe_Length)),
-						("ParseSubframe(): A-MSDU subframe parse error!! Subframe Length: %d\n", nSubframe_Length) );
-#endif
 				printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
 						__FUNCTION__,rxb->nr_subframes);
 				printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length);
@@ -925,9 +879,6 @@ u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
 #ifdef JOHN_NOCPY
 		dev_kfree_skb(skb);
 #endif
-		//{just for debug added by david
-		//printk("AMSDU::rxb->nr_subframes = %d\n",rxb->nr_subframes);
-		//}
 		return rxb->nr_subframes;
 	}
 }
@@ -940,7 +891,6 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 {
 	struct net_device *dev = ieee->dev;
 	struct ieee80211_hdr_4addr *hdr;
-	//struct ieee80211_hdr_3addrqos *hdr;
 
 	size_t hdrlen;
 	u16 fc, type, stype, sc;
@@ -953,7 +903,6 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	u16	SeqNum = 0;
 	PRX_TS_RECORD pTS = NULL;
 	bool unicast_packet = false;
-	//bool bIsAggregateFrame = false;
 	//added by amy for reorder
 #ifdef NOT_YET
 	struct net_device *wds = NULL;
@@ -963,7 +912,6 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	int from_assoc_ap = 0;
 	void *sta = NULL;
 #endif
-//	u16 qos_ctl = 0;
 	u8 dst[ETH_ALEN];
 	u8 src[ETH_ALEN];
 	u8 bssid[ETH_ALEN];
@@ -998,7 +946,6 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 		rx_stats->bContainHTC = 1;
 	}
 
-	//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
 #ifdef NOT_YET
 #if WIRELESS_EXT > 15
 	/* Put this code here so that we avoid duplicating it in all
@@ -1077,19 +1024,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	else
 	{
 		PRX_TS_RECORD pRxTS = NULL;
-	#if 0
-		struct ieee80211_hdr_3addr *hdr;
-		u16 fc;
-		hdr = (struct ieee80211_hdr_3addr *)skb->data;
-		fc = le16_to_cpu(hdr->frame_ctl);
-		u8 tmp = (fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS);
-
-		u8 tid = (*((u8*)skb->data + (((fc& IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))?30:24)))&0xf;
-		printk("====================>fc:%x, tid:%d, tmp:%d\n", fc, tid, tmp);
-		//u8 tid =  (u8)((frameqos*)(buf + ((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24))->field.tid;
-	#endif
-			//IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__FUNCTION__, tid);
-#if 1
+
 		if(GetTs(
 				ieee,
 				(PTS_COMMON_INFO*) &pRxTS,
@@ -1099,7 +1034,6 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 				true))
 		{
 
-		//	IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->RxLastFragNum is %d,frag is %d,pRxTS->RxLastSeqNum is %d,seq is %d\n",__FUNCTION__,pRxTS->RxLastFragNum,frag,pRxTS->RxLastSeqNum,WLAN_GET_SEQ_SEQ(sc));
 			if( 	(fc & (1<<11))  &&
 					(frag == pRxTS->RxLastFragNum) &&
 					(WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum)	)
@@ -1118,24 +1052,9 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			goto rx_dropped;
 		}
 	}
-#endif
-	if (type == IEEE80211_FTYPE_MGMT) {
 
-	#if 0
-		if ( stype == IEEE80211_STYPE_AUTH &&
-		    fc & IEEE80211_FCTL_WEP && ieee->host_decrypt &&
-		    (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0)
-		{
-			printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
-			       "from %pM\n", dev->name,
-			       hdr->addr2);
-			/* TODO: could inform hostapd about this so that it
-			 * could send auth failure report */
-			goto rx_dropped;
-		}
-	#endif
+	if (type == IEEE80211_FTYPE_MGMT) {
 
-	//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
 		if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
 			goto rx_dropped;
 		else
@@ -1208,7 +1127,6 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 		}
 	}
 #endif
-	//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
 	/* Nullfunc frames may have PS-bit set, so they must be passed to
 	 * hostap_handle_sta_rx() before being dropped here. */
 	if (stype != IEEE80211_STYPE_DATA &&
@@ -1370,13 +1288,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			hdr->addr2);
 		goto rx_dropped;
 	}
-/*
-	if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
-		printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
-	}
-*/
 //added by amy for reorder
-#if 1
 	if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
 		&& !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
 	{
@@ -1388,11 +1300,11 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 			ieee->bis_any_nonbepkts = true;
 		}
 	}
-#endif
+
 //added by amy for reorder
 	/* skb: hdr + (possible reassembled) full plaintext payload */
 	payload = skb->data + hdrlen;
-	//ethertype = (payload[6] << 8) | payload[7];
+
 	rxb = kmalloc(sizeof(struct ieee80211_rxb), GFP_ATOMIC);
 	if(rxb == NULL)
 	{
@@ -1423,14 +1335,13 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 					ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
 
 				// 2009.03.03 Leave DC mode immediately when detect high traffic
-				// DbgPrint("ending Seq %d\n", Frame_SeqNum(pduOS));
 				if((ieee->state == IEEE80211_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
 				{
 					if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
 						(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
 					{
 						if(ieee->LeisurePSLeave)
-							ieee->LeisurePSLeave(dev);
+							ieee->LeisurePSLeave(ieee);
 					}
 				}
 			}
@@ -1472,13 +1383,10 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 				}
 
 				/* Indicat the packets to upper layer */
-				//printk("0skb_len(%d)\n", skb->len);
 				sub_skb->protocol = eth_type_trans(sub_skb, dev);
 				memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
 				sub_skb->dev = dev;
 				sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
-				//skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */
-				//printk("1skb_len(%d)\n", skb->len);
 				netif_rx(sub_skb);
 			}
 		}
@@ -1503,11 +1411,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	return 1;
 
  rx_dropped:
-	if (rxb != NULL)
-	{
-		kfree(rxb);
-		rxb = NULL;
-	}
+	kfree(rxb);
+	rxb = NULL;
 	stats->rx_dropped++;
 
 	/* Returning 0 indicates to caller that we have not handled the SKB--
@@ -1611,8 +1516,6 @@ static int ieee80211_qos_convert_ac_to_parameters(struct
         int i;
         struct ieee80211_qos_ac_parameter *ac_params;
 	u8 aci;
-        //u8 cw_min;
-        //u8 cw_max;
 
         for (i = 0; i < QOS_QUEUE_NUM; i++) {
                 ac_params = &(param_elm->ac_params_record[i]);
@@ -1763,7 +1666,6 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 	u16	tmp_htinfo_len=0;
 	u16 ht_realtek_agg_len=0;
 	u8  ht_realtek_agg_buf[MAX_IE_LEN];
-//	u16 broadcom_len = 0;
 #ifdef CONFIG_IEEE80211_DEBUG
 	char rates_str[64];
 	char *p;
@@ -1880,12 +1782,8 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
                         network->dtim_period = info_element->data[1];
                         if(ieee->state != IEEE80211_LINKED)
                                 break;
-#if 0
-                        network->last_dtim_sta_time[0] = stats->mac_time[0];
-#else
 			//we use jiffies for legacy Power save
 			network->last_dtim_sta_time[0] = jiffies;
-#endif
                         network->last_dtim_sta_time[1] = stats->mac_time[1];
 
                         network->dtim_data = IEEE80211_DTIM_VALID;
@@ -1898,8 +1796,6 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 
                         offset = (info_element->data[2] >> 1)*2;
 
-                        //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
-
                         if(ieee->assoc_id < 8*offset ||
                                 ieee->assoc_id > 8*(offset + info_element->len -3))
 
@@ -1910,7 +1806,6 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
                         if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
                                 network->dtim_data |= IEEE80211_DTIM_UCAST;
 
-			//IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
 			break;
 
 		case MFIE_TYPE_ERP:
@@ -2025,8 +1920,6 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 
 			}
 
-			//if(tmp_htcap_len !=0  ||  tmp_htinfo_len != 0)
-			{
 				if((info_element->len >= 3 &&
 					 info_element->data[0] == 0x00 &&
 					 info_element->data[1] == 0x05 &&
@@ -2043,17 +1936,7 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 						network->broadcom_cap_exist = true;
 
 				}
-			}
-#if 0
-			if (tmp_htcap_len !=0)
-				{
-					u16 cap_ext = ((PHT_CAPABILITY_ELE)&info_element->data[0])->ExtHTCapInfo;
-					if ((cap_ext & 0x0c00) == 0x0c00)
-						{
-							network->ralink_cap_exist = true;
-						}
-				}
-#endif
+
 			if(info_element->len >= 3 &&
 				info_element->data[0] == 0x00 &&
 				info_element->data[1] == 0x0c &&
@@ -2073,7 +1956,6 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 				info_element->data[1] == 0x13 &&
 				info_element->data[2] == 0x74))
 			{
-				//printk("========>%s(): athros AP is exist\n",__FUNCTION__);
 				network->atheros_cap_exist = true;
 			}
 			else
@@ -2085,7 +1967,6 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 						info_element->data[2] == 0x43) )
 			{
 				network->marvell_cap_exist = true;
-				//printk("========>%s(): marvel AP is exist\n",__FUNCTION__);
 			}
 
 
@@ -2231,49 +2112,10 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
 		case MFIE_TYPE_COUNTRY:
 			IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
 					     info_element->len);
-			//printk("=====>Receive <%s> Country IE\n",network->ssid);
 			ieee80211_extract_country_ie(ieee, info_element, network, network->bssid);//addr2 is same as addr3 when from an AP
 			break;
 #endif
-/* TODO */
-#if 0
-			/* 802.11h */
-		case MFIE_TYPE_POWER_CONSTRAINT:
-			network->power_constraint = info_element->data[0];
-			network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
-			break;
-
-		case MFIE_TYPE_CSA:
-			network->power_constraint = info_element->data[0];
-			network->flags |= NETWORK_HAS_CSA;
-			break;
-
-		case MFIE_TYPE_QUIET:
-			network->quiet.count = info_element->data[0];
-			network->quiet.period = info_element->data[1];
-			network->quiet.duration = info_element->data[2];
-			network->quiet.offset = info_element->data[3];
-			network->flags |= NETWORK_HAS_QUIET;
-			break;
 
-		case MFIE_TYPE_IBSS_DFS:
-			if (network->ibss_dfs)
-				break;
-			network->ibss_dfs = kmemdup(info_element->data,
-						    info_element->len,
-						    GFP_ATOMIC);
-			if (!network->ibss_dfs)
-				return 1;
-			network->flags |= NETWORK_HAS_IBSS_DFS;
-			break;
-
-		case MFIE_TYPE_TPC_REPORT:
-			network->tpc_report.transmit_power =
-			    info_element->data[0];
-			network->tpc_report.link_margin = info_element->data[1];
-			network->flags |= NETWORK_HAS_TPC_REPORT;
-			break;
-#endif
 		default:
 			IEEE80211_DEBUG_MGMT
 			    ("Unsupported info element: %s (%d)\n",
@@ -2348,11 +2190,6 @@ static inline u8 ieee80211_SignalStrengthTranslate(
 	{
 		RetSS = CurrSS;
 	}
-	//RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
-
-	// Step 2. Smoothing.
-
-	//RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
 
 	return RetSS;
 }
@@ -2374,11 +2211,6 @@ static inline int ieee80211_network_init(
 	struct ieee80211_network *network,
 	struct ieee80211_rx_stats *stats)
 {
-#ifdef CONFIG_IEEE80211_DEBUG
-	//char rates_str[64];
-	//char *p;
-#endif
-
         network->qos_data.active = 0;
         network->qos_data.supported = 0;
         network->qos_data.param_count = 0;
@@ -2415,7 +2247,6 @@ static inline int ieee80211_network_init(
 	memset(network->CountryIeBuf, 0, MAX_IE_LEN);
 #endif
 //Initialize HT parameters
-	//ieee80211_ht_initialize(&network->bssht);
 	HTInitializeBssDesc(&network->bssht);
 	if (stats->freq == IEEE80211_52GHZ_BAND) {
 		/* for A band (No DS info) */
@@ -2458,11 +2289,8 @@ static inline int ieee80211_network_init(
 	if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
 		network->flags |= NETWORK_EMPTY_ESSID;
 
-#if 1
 	stats->signal = 30 + (stats->SignalStrength * 70) / 100;
-	//stats->signal = ieee80211_SignalStrengthTranslate(stats->signal);
 	stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25;
-#endif
 
 	memcpy(&network->stats, stats, sizeof(network->stats));
 
@@ -2476,11 +2304,9 @@ static inline int is_same_network(struct ieee80211_network *src,
 	 * and the capability field (in particular IBSS and BSS) all match.
 	 * We treat all <hidden> with the same BSSID and channel
 	 * as one network */
-	return //((src->ssid_len == dst->ssid_len) &&
-		(((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
+	return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
 		(src->channel == dst->channel) &&
 		!memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
-		//!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
 		(!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
 		((src->capability & WLAN_CAPABILITY_IBSS) ==
 		(dst->capability & WLAN_CAPABILITY_IBSS)) &&
@@ -2545,15 +2371,10 @@ static inline void update_network(struct ieee80211_network *dst,
 
 	dst->last_scanned = jiffies;
 	/* qos related parameters */
-	//qos_active = src->qos_data.active;
 	qos_active = dst->qos_data.active;
-	//old_param = dst->qos_data.old_param_count;
 	old_param = dst->qos_data.param_count;
 	if(dst->flags & NETWORK_HAS_QOS_MASK){
         //not update QOS paramter in beacon, as most AP will set all these parameter to 0.//WB
-	//	printk("====>%s(), aifs:%x, %x\n", __FUNCTION__, dst->qos_data.parameters.aifs[0], src->qos_data.parameters.aifs[0]);
-	//	memcpy(&dst->qos_data, &src->qos_data,
-	//		sizeof(struct ieee80211_qos_data));
 	}
 	else {
 		dst->qos_data.supported = src->qos_data.supported;
@@ -2574,7 +2395,6 @@ static inline void update_network(struct ieee80211_network *dst,
 	dst->qos_data.old_param_count = old_param;
 
 	/* dst->last_associate is not overwritten */
-#if 1
 	dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
 	if(src->wmm_param[0].ac_aci_acm_aifsn|| \
 	   src->wmm_param[1].ac_aci_acm_aifsn|| \
@@ -2582,10 +2402,6 @@ static inline void update_network(struct ieee80211_network *dst,
 	   src->wmm_param[3].ac_aci_acm_aifsn) {
 	  memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
 	}
-	//dst->QoS_Enable = src->QoS_Enable;
-#else
-	dst->QoS_Enable = 1;//for Rtl8187 simulation
-#endif
 #ifdef THOMAS_TURBO
 	dst->Turbo_Enable = src->Turbo_Enable;
 #endif
@@ -2626,7 +2442,6 @@ static inline void ieee80211_process_probe_response(
 #endif
 	unsigned long flags;
 	short renew;
-	//u8 wmm_info;
 
 	memset(&network, 0, sizeof(struct ieee80211_network));
 	IEEE80211_DEBUG_SCAN(
@@ -2806,8 +2621,6 @@ static inline void ieee80211_process_probe_response(
 		//YJ,add,080819,for hidden ap
 		if(is_beacon(beacon->header.frame_ctl) == 0)
 			network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
-		//if(strncmp(network.ssid, "linksys-c",9) == 0)
-		//	printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
 		if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
 		    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
 		    ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
@@ -2821,7 +2634,7 @@ static inline void ieee80211_process_probe_response(
 	if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
 		(ieee->state == IEEE80211_LINKED)) {
 		if(ieee->handle_beacon != NULL) {
-			ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
+			ieee->handle_beacon(ieee, beacon, &ieee->current_network);
 		}
 	}
 }
@@ -2830,15 +2643,6 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
 		      struct ieee80211_hdr_4addr *header,
 		      struct ieee80211_rx_stats *stats)
 {
-#if 0
-	if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
-				ieee->iw_mode == IW_MODE_INFRA &&
-				ieee->state == IEEE80211_LINKED))
-	{
-		tasklet_schedule(&ieee->ps_task);
-	}
-#endif
-
 	if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
 		WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
 		ieee->last_rx_ps_time = jiffies;
@@ -2852,7 +2656,6 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
 		ieee80211_process_probe_response(
 			ieee, (struct ieee80211_probe_response *)header, stats);
 
-		//printk("----------->%s()\n", __func__);
 		if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
 					ieee->iw_mode == IW_MODE_INFRA &&
 					ieee->state == IEEE80211_LINKED))
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
index 54c9c24..f6922d4 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -163,8 +163,6 @@ void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
  */
 	ieee->mgmt_queue_head = nh;
 	ieee->mgmt_queue_ring[nh] = skb;
-
-	//return 0;
 }
 
 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
@@ -208,16 +206,6 @@ u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
 			rate = 0x02;
 	}
 
-	/*
-	// Data rate of ProbeReq is already decided. Annie, 2005-03-31
-	if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
-	{
-	if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
-	rate = 0x0c;
-	else
-	rate = 0x02;
-	}
-	 */
 	return rate;
 }
 
@@ -255,15 +243,13 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
 				ieee->seq_ctrl[0]++;
 
 			/* avoid watchdog triggers */
-	//		ieee->dev->trans_start = jiffies;
-			ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
-			//dev_kfree_skb_any(skb);//edit by thomas
+			ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
 		}
 
 		spin_unlock_irqrestore(&ieee->lock, flags);
 	}else{
 		spin_unlock_irqrestore(&ieee->lock, flags);
-		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
+		spin_lock(&ieee->mgmt_tx_lock);
 
 		header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
 
@@ -273,21 +259,18 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
 			ieee->seq_ctrl[0]++;
 
 		/* check wether the managed packet queued greater than 5 */
-		if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
-				(skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
+		if(!ieee->check_nic_enough_desc(ieee, tcb_desc->queue_index)||
+				(skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||
 				(ieee->queue_stop) ) {
 			/* insert the skb packet to the management queue */
 			/* as for the completion function, it does not need
 			 * to check it any more.
 			 * */
-			//printk("%s():insert to waitqueue!\n",__FUNCTION__);
 			skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
 		} else {
-			//printk("TX packet!\n");
-			ieee->softmac_hard_start_xmit(skb,ieee->dev);
-			//dev_kfree_skb_any(skb);//edit by thomas
+			ieee->softmac_hard_start_xmit(skb, ieee);
 		}
-		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
+		spin_unlock(&ieee->mgmt_tx_lock);
 	}
 }
 
@@ -304,7 +287,6 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
 	tcb_desc->RATRIndex = 7;
 	tcb_desc->bTxDisableRateFallBack = 1;
 	tcb_desc->bTxUseDriverAssingedRate = 1;
-	//printk("=============>%s()\n", __FUNCTION__);
 	if(single){
 
 		header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
@@ -315,8 +297,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
 			ieee->seq_ctrl[0]++;
 
 		/* avoid watchdog triggers */
-	//	ieee->dev->trans_start = jiffies;
-		ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
+		ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
 
 	}else{
 
@@ -327,10 +308,9 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
 		else
 			ieee->seq_ctrl[0]++;
 
-		ieee->softmac_hard_start_xmit(skb,ieee->dev);
+		ieee->softmac_hard_start_xmit(skb, ieee);
 
 	}
-	//dev_kfree_skb_any(skb);//edit by thomas
 }
 
 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
@@ -377,24 +357,17 @@ void ieee80211_send_beacon(struct ieee80211_device *ieee)
 	struct sk_buff *skb;
 	if(!ieee->ieee_up)
 		return;
-	//unsigned long flags;
+
 	skb = ieee80211_get_beacon_(ieee);
 
 	if (skb){
 		softmac_mgmt_xmit(skb, ieee);
 		ieee->softmac_stats.tx_beacons++;
-		//dev_kfree_skb_any(skb);//edit by thomas
 	}
-//	ieee->beacon_timer.expires = jiffies +
-//		(MSECS( ieee->current_network.beacon_interval -5));
 
-	//spin_lock_irqsave(&ieee->beacon_lock,flags);
 	if(ieee->beacon_txing && ieee->ieee_up){
-//		if(!timer_pending(&ieee->beacon_timer))
-//			add_timer(&ieee->beacon_timer);
 		mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
 	}
-	//spin_unlock_irqrestore(&ieee->beacon_lock,flags);
 }
 
 
@@ -418,7 +391,6 @@ void ieee80211_send_probe(struct ieee80211_device *ieee)
 	if (skb){
 		softmac_mgmt_xmit(skb, ieee);
 		ieee->softmac_stats.tx_probe_rq++;
-		//dev_kfree_skb_any(skb);//edit by thomas
 	}
 }
 
@@ -476,7 +448,7 @@ void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
 
 		if (ieee->state == IEEE80211_LINKED)
 			goto out;
-		ieee->set_chan(ieee->dev, ch);
+		ieee->set_chan(ieee, ch);
 #ifdef ENABLE_DOT11D
 		if(channel_map[ch] == 1)
 #endif
@@ -545,7 +517,7 @@ void ieee80211_softmac_scan_wq(struct work_struct *work)
 #endif
 	if (ieee->scanning == 0 )
 		goto out;
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
+	ieee->set_chan(ieee, ieee->current_network.channel);
 #ifdef ENABLE_DOT11D
 	if(channel_map[ieee->current_network.channel] == 1)
 #endif
@@ -596,7 +568,7 @@ void ieee80211_beacons_stop(struct ieee80211_device *ieee)
 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
 {
 	if(ieee->stop_send_beacons)
-		ieee->stop_send_beacons(ieee->dev);
+		ieee->stop_send_beacons(ieee);
 	if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
 		ieee80211_beacons_stop(ieee);
 }
@@ -605,7 +577,7 @@ void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
 {
 	if(ieee->start_send_beacons)
-		ieee->start_send_beacons(ieee->dev);
+		ieee->start_send_beacons(ieee);
 	if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
 		ieee80211_beacons_start(ieee);
 }
@@ -613,12 +585,7 @@ void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
 
 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
 {
-//	unsigned long flags;
-
-	//ieee->sync_scan_hurryup = 1;
-
 	down(&ieee->scan_sem);
-//	spin_lock_irqsave(&ieee->lock, flags);
 
 	if (ieee->scanning == 1){
 		ieee->scanning = 0;
@@ -626,7 +593,6 @@ void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
 		cancel_delayed_work(&ieee->softmac_scan_wq);
 	}
 
-//	spin_unlock_irqrestore(&ieee->lock, flags);
 	up(&ieee->scan_sem);
 }
 
@@ -635,7 +601,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
 	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
 		ieee80211_softmac_stop_scan(ieee);
 	else
-		ieee->stop_scan(ieee->dev);
+		ieee->stop_scan(ieee);
 }
 
 /* called with ieee->lock held */
@@ -643,7 +609,7 @@ void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 {
 #ifdef ENABLE_IPS
 	if(ieee->ieee80211_ips_leave_wq != NULL)
-		ieee->ieee80211_ips_leave_wq(ieee->dev);
+		ieee->ieee80211_ips_leave_wq(ieee);
 #endif
 
 #ifdef ENABLE_DOT11D
@@ -661,7 +627,7 @@ void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
 			queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
 		}
 	}else
-		ieee->start_scan(ieee->dev);
+		ieee->start_scan(ieee);
 
 }
 
@@ -681,7 +647,7 @@ void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
 	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
 		ieee80211_softmac_scan_syncro(ieee);
 	else
-		ieee->scan_syncro(ieee->dev);
+		ieee->scan_syncro(ieee);
 
 }
 
@@ -709,7 +675,6 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be
 	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 	memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
 
-	//auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
 	if(ieee->auth_mode == 0)
 		auth->algorithm = WLAN_AUTH_OPEN;
 	else if(ieee->auth_mode == 1)
@@ -759,23 +724,10 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 	else
 		atim_len = 0;
 
-#if 1
 	if(ieee80211_is_54g(ieee->current_network))
 		erp_len = 3;
 	else
 		erp_len = 0;
-#else
-      if((ieee->current_network.mode == IEEE_G)
-	  	||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
-	  	erp_len = 3;
-		erpinfo_content = 0;
-		if(ieee->current_network.buseprotection)
-			erpinfo_content |= ERP_UseProtection;
-      	}
-	else
-		erp_len = 0;
-#endif
-
 
 	crypt = ieee->crypt[ieee->tx_keyidx];
 
@@ -783,7 +735,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 	encrypt = ieee->host_encrypt && crypt && crypt->ops &&
 		((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
 	//HT ralated element
-#if 1
+
 	tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
 	tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
 	tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
@@ -798,8 +750,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
 		HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
         }
-//	printk("===============>tmp_ht_cap_len is %d,tmp_ht_info_len is %d, tmp_generic_ie_len is %d\n",tmp_ht_cap_len,tmp_ht_info_len,tmp_generic_ie_len);
-#endif
+
 	beacon_size = sizeof(struct ieee80211_probe_response)+2+
 		ssid_len
 		+3 //channel
@@ -808,10 +759,6 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		+atim_len
 		+erp_len
                 +wpa_ie_len
-	//	+tmp_ht_cap_len
-	//	+tmp_ht_info_len
-	//	+tmp_generic_ie_len
-//		+wmm_len+2
 		+ieee->tx_headroom;
 	skb = dev_alloc_skb(beacon_size);
 	if (!skb)
@@ -834,10 +781,6 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
 
 	crypt = ieee->crypt[ieee->tx_keyidx];
-#if 0
-	encrypt = ieee->host_encrypt && crypt && crypt->ops &&
-		(0 == strcmp(crypt->ops->name, "WEP"));
-#endif
 	if (encrypt)
 		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
 
@@ -865,7 +808,6 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 	u16 val16;
 		*(tag++) = MFIE_TYPE_IBSS_SET;
 		*(tag++) = 2;
-		//*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
 		 val16 = cpu_to_le16(ieee->current_network.atim_window);
 		memcpy((u8 *)tag, (u8 *)&val16, 2);
 		tag+=2;
@@ -876,14 +818,6 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		*(tag++) = 1;
 		*(tag++) = erpinfo_content;
 	}
-#if 0
-	//Include High Throuput capability
-
-	*(tag++) = MFIE_TYPE_HT_CAP;
-	*(tag++) = tmp_ht_cap_len - 2;
-	memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);
-	tag += tmp_ht_cap_len - 2;
-#endif
 	if(rate_ex_len){
 		*(tag++) = MFIE_TYPE_RATES_EX;
 		*(tag++) = rate_ex_len-2;
@@ -891,14 +825,6 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		tag+=rate_ex_len-2;
 	}
 
-#if 0
-	//Include High Throuput info
-
-	*(tag++) = MFIE_TYPE_HT_INFO;
-	*(tag++) = tmp_ht_info_len - 2;
-	memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
-	tag += tmp_ht_info_len - 2;
-#endif
 	if (wpa_ie_len)
 	{
 		if (ieee->iw_mode == IW_MODE_ADHOC)
@@ -909,29 +835,6 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
 		tag += wpa_ie_len;
 	}
 
-#if 0
-	//
-	// Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
-	//
-	if(pHTInfo->bRegRT2RTAggregation)
-	{
-		(*tag++) = 0xdd;
-		(*tag++) = tmp_generic_ie_len - 2;
-		memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
-		tag += tmp_generic_ie_len -2;
-
-	}
-#endif
-#if 0
-	if(ieee->qos_support)
-	{
-		(*tag++) = 0xdd;
-		(*tag++) = wmm_len;
-		memcpy(tag,QosOui,wmm_len);
-		tag += wmm_len;
-	}
-#endif
-	//skb->dev = ieee->dev;
 	return skb;
 }
 
@@ -1110,16 +1013,8 @@ void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
 {
 	struct sk_buff *skb;
-	//unsigned long flags;
-
 	struct ieee80211_assoc_request_frame *hdr;
-	u8 *tag;//,*rsn_ie;
-	//short info_addr = 0;
-	//int i;
-	//u16 suite_count = 0;
-	//u8 suit_select = 0;
-	//unsigned int wpa_len = beacon->wpa_ie_len;
-	//for HT
+	u8 *tag;
 	u8* ht_cap_buf = NULL;
 	u8 ht_cap_len=0;
 	u8* realtek_ie_buf=NULL;
@@ -1344,8 +1239,6 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
 			memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
 		}
 	}
-//	printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
-//	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
 	return skb;
 }
 
@@ -1399,14 +1292,12 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee)
 	else{
 		ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
 		IEEE80211_DEBUG_MGMT("Sending authentication request\n");
-		//printk(KERN_WARNING "Sending authentication request\n");
 		softmac_mgmt_xmit(skb, ieee);
 		//BUGON when you try to add_timer twice, using mod_timer may be better, john0709
 		if(!timer_pending(&ieee->associate_timer)){
 			ieee->associate_timer.expires = jiffies + (HZ / 2);
 			add_timer(&ieee->associate_timer);
 		}
-		//dev_kfree_skb_any(skb);//edit by thomas
 	}
 }
 
@@ -1415,7 +1306,6 @@ void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge,
 	u8 *c;
 	struct sk_buff *skb;
 	struct ieee80211_network *beacon = &ieee->current_network;
-//	int hlen = sizeof(struct ieee80211_authentication);
 
 	ieee->associate_seq++;
 	ieee->softmac_stats.tx_auth_rq++;
@@ -1435,11 +1325,6 @@ void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge,
 
 		softmac_mgmt_xmit(skb, ieee);
 		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
-#if 0
-		ieee->associate_timer.expires = jiffies + (HZ / 2);
-		add_timer(&ieee->associate_timer);
-#endif
-		//dev_kfree_skb_any(skb);//edit by thomas
 	}
 	kfree(challenge);
 }
@@ -1460,11 +1345,6 @@ void ieee80211_associate_step2(struct ieee80211_device *ieee)
 	else{
 		softmac_mgmt_xmit(skb, ieee);
 		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
-#if 0
-		ieee->associate_timer.expires = jiffies + (HZ / 2);
-		add_timer(&ieee->associate_timer);
-#endif
-		//dev_kfree_skb_any(skb);//edit by thomas
 	}
 }
 void ieee80211_associate_complete_wq(struct work_struct *work)
@@ -1490,7 +1370,6 @@ void ieee80211_associate_complete_wq(struct work_struct *work)
 	{
 		printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
 		memset(ieee->dot11HTOperationalRateSet, 0, 16);
-		//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 	}
 	ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
 	// To prevent the immediately calling watch_dog after association.
@@ -1499,7 +1378,7 @@ void ieee80211_associate_complete_wq(struct work_struct *work)
 		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
 		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
 	}
-	ieee->link_change(ieee->dev);
+	ieee->link_change(ieee);
 	if(ieee->is_silent_reset == 0){
 		printk("============>normal associate\n");
 	notify_wx_assoc_event(ieee);
@@ -1511,36 +1390,15 @@ void ieee80211_associate_complete_wq(struct work_struct *work)
 	}
 
 	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
+		ieee->data_hard_resume(ieee);
 	netif_carrier_on(ieee->dev);
 }
 
 void ieee80211_associate_complete(struct ieee80211_device *ieee)
 {
-//	int i;
-//	struct net_device* dev = ieee->dev;
 	del_timer_sync(&ieee->associate_timer);
 
-#if 0
-	for(i = 0; i < 6; i++) {
-	  ieee->seq_ctrl[i] = 0;
-	}
-#endif
 	ieee->state = IEEE80211_LINKED;
-#if 0
-	if (ieee->pHTInfo->bCurrentHTSupport)
-	{
-		printk("Successfully associated, ht enabled\n");
-		queue_work(ieee->wq, &ieee->ht_onAssRsp);
-	}
-	else
-	{
-		printk("Successfully associated, ht not enabled\n");
-		memset(ieee->dot11HTOperationalRateSet, 0, 16);
-		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
-	}
-#endif
-	//ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
 	queue_work(ieee->wq, &ieee->associate_complete_wq);
 }
 
@@ -1550,30 +1408,18 @@ void ieee80211_associate_procedure_wq(struct work_struct *work)
 	ieee->sync_scan_hurryup = 1;
 #ifdef ENABLE_IPS
 	if(ieee->ieee80211_ips_leave != NULL)
-        	ieee->ieee80211_ips_leave(ieee->dev);
+		ieee->ieee80211_ips_leave(ieee);
 #endif
 
 	down(&ieee->wx_sem);
 
 	if (ieee->data_hard_stop)
-		ieee->data_hard_stop(ieee->dev);
+		ieee->data_hard_stop(ieee);
 
 	ieee80211_stop_scan(ieee);
 	printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
-	//ieee->set_chan(ieee->dev, ieee->current_network.channel);
 	HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 
-#ifdef ENABLE_IPS
-	if(ieee->eRFPowerState == eRfOff)
-	{
-		if(ieee->ieee80211_ips_leave_wq != NULL)
-			ieee->ieee80211_ips_leave_wq(ieee->dev);
-
-		up(&ieee->wx_sem);
-		return;
-	}
-#endif
-
 	ieee->associate_seq = 1;
 	ieee80211_associate_step1(ieee);
 
@@ -1605,8 +1451,8 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
 		 * This could be obtained by beacons or, if the network does not
 		 * broadcast it, it can be put manually.
 		 */
-		apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
-		ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
+		apset = ieee->wap_set;
+		ssidset = ieee->ssid_set;
 		ssidbroad =  !(net->ssid_len == 0 || net->ssid[0]== '\0');
 		apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
 		ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
@@ -1640,18 +1486,15 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
 				}
 				printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
 
-				//ieee->pHTInfo->IOTAction = 0;
 				HTResetIOTSetting(ieee->pHTInfo);
 				if (ieee->iw_mode == IW_MODE_INFRA){
 					/* Join the network for the first time */
 					ieee->AsocRetryCount = 0;
 					//for HT by amy 080514
 					if((ieee->current_network.qos_data.supported == 1) &&
-					  // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
 					   ieee->current_network.bssht.bdSupportHT)
 /*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
 					{
-					//	ieee->pHTInfo->bCurrentHTSupport = true;
 						HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
 					}
 					else
@@ -1665,15 +1508,14 @@ inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee
 					if(ieee80211_is_54g(ieee->current_network) &&
 						(ieee->modulation & IEEE80211_OFDM_MODULATION)){
 						ieee->rate = 108;
-						ieee->SetWirelessMode(ieee->dev, IEEE_G);
+						ieee->SetWirelessMode(ieee, IEEE_G);
 						printk(KERN_INFO"Using G rates\n");
 					}else{
 						ieee->rate = 22;
-						ieee->SetWirelessMode(ieee->dev, IEEE_B);
+						ieee->SetWirelessMode(ieee, IEEE_B);
 						printk(KERN_INFO"Using B rates\n");
 					}
 					memset(ieee->dot11HTOperationalRateSet, 0, 16);
-					//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 					ieee->state = IEEE80211_LINKED;
 				}
 
@@ -1722,8 +1564,9 @@ static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
 
 		if(*(t++) == MFIE_TYPE_CHALLENGE){
 			*chlen = *(t++);
-			*challenge = kmalloc(*chlen, GFP_ATOMIC);
-			memcpy(*challenge, t, *chlen);
+			*challenge = kmemdup(t, *chlen, GFP_ATOMIC);
+			if (!*challenge)
+				return -ENOMEM;
 		}
 	}
 
@@ -1780,7 +1623,6 @@ static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb,
 		tag++; /* point to the next tag */
 	}
 
-	//IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
 	if (ssidlen == 0) return 1;
 
 	if (!ssid) return 1; /* ssid not found in tagged param */
@@ -1838,11 +1680,8 @@ ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
 {
 	u8 dest[ETH_ALEN];
 
-	//IEEE80211DMESG("Rx probe");
 	ieee->softmac_stats.rx_probe_rq++;
-	//DMESG("Dest is "MACSTR, MAC2STR(dest));
 	if (probe_rq_parse(ieee, skb, dest)){
-		//IEEE80211DMESG("Was for me!");
 		ieee->softmac_stats.tx_probe_rs++;
 		ieee80211_resp_to_probe(ieee, dest);
 	}
@@ -1853,23 +1692,18 @@ ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
 {
 	u8 dest[ETH_ALEN];
 	int status;
-	//IEEE80211DMESG("Rx probe");
 	ieee->softmac_stats.rx_auth_rq++;
 
 	status = auth_rq_parse(skb, dest);
 	if (status != -1) {
 		ieee80211_resp_to_auth(ieee, status, dest);
 	}
-	//DMESG("Dest is "MACSTR, MAC2STR(dest));
-
 }
 
 static inline void
 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
 {
-
 	u8 dest[ETH_ALEN];
-	//unsigned long flags;
 
 	ieee->softmac_stats.rx_ass_rq++;
 	if (assoc_rq_parse(skb,dest) != -1){
@@ -1877,12 +1711,6 @@ ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
 	}
 
 	printk(KERN_INFO"New client associated: %pM\n", dest);
-	//FIXME
-	#if 0
-	spin_lock_irqsave(&ieee->lock,flags);
-	add_associate(ieee,dest);
-	spin_unlock_irqrestore(&ieee->lock,flags);
-	#endif
 }
 
 
@@ -1911,32 +1739,26 @@ short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *ti
 {
 	int timeout = ieee->ps_timeout;
 	u8 dtim;
-	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
 
 	if(ieee->LPSDelayCnt)
 	{
-		//printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
 		ieee->LPSDelayCnt --;
 		return 0;
 	}
 
 	dtim = ieee->current_network.dtim_data;
-//	printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
 	if(!(dtim & IEEE80211_DTIM_VALID))
 		return 0;
 	timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
-	//printk("VALID\n");
 	ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
 	/* there's no need to nofity AP that I find you buffered with broadcast packet */
 	if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
 		return 2;
 
 	if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
-//		printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
 		return 0;
 	}
 	if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
-//		printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
 		return 0;
 	}
 	if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
@@ -1945,42 +1767,39 @@ short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *ti
 
 	if(time_l){
 		if(ieee->bAwakePktSent == true) {
-			pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
+			ieee->LPSAwakeIntvl = 1;//tx wake one beacon
 		} else {
 			u8		MaxPeriod = 1;
 
-			if(pPSC->LPSAwakeIntvl == 0)
-				pPSC->LPSAwakeIntvl = 1;
-			//pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
-			if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
+			if(ieee->LPSAwakeIntvl == 0)
+				ieee->LPSAwakeIntvl = 1;
+			if(ieee->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
 				MaxPeriod = 1; // 1 Beacon interval
-			else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
+			else if(ieee->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
 				MaxPeriod = ieee->current_network.dtim_period;
 			else
-				MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
-			pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
+				MaxPeriod = ieee->RegMaxLPSAwakeIntvl;
+			ieee->LPSAwakeIntvl = (ieee->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (ieee->LPSAwakeIntvl + 1);
 		}
 		{
 			u8 LPSAwakeIntvl_tmp = 0;
 			u8 period = ieee->current_network.dtim_period;
 			u8 count = ieee->current_network.tim.tim_count;
 			if(count == 0 ) {
-				if(pPSC->LPSAwakeIntvl > period)
-					LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
+				if(ieee->LPSAwakeIntvl > period)
+					LPSAwakeIntvl_tmp = period + (ieee->LPSAwakeIntvl - period) -((ieee->LPSAwakeIntvl-period)%period);
 				else
-					LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+					LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
 
 			} else {
-				if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
-					LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
+				if(ieee->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
+					LPSAwakeIntvl_tmp = count + (ieee->LPSAwakeIntvl - count) -((ieee->LPSAwakeIntvl-count)%period);
 				else
-					LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
+					LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
 			}
-			//printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
 
 		*time_l = ieee->current_network.last_dtim_sta_time[0]
 			+ MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
-		//	* ieee->current_network.dtim_period) * 1000;
 	}
 	}
 
@@ -2000,8 +1819,7 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
 
 	u32 th,tl;
 	short sleep;
-
-	unsigned long flags,flags2;
+	unsigned long flags;
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
@@ -2012,53 +1830,46 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
 	//	#warning CHECK_LOCK_HERE
 		printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
 			__FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
-		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+		spin_lock(&ieee->mgmt_tx_lock);
 
 		ieee80211_sta_wakeup(ieee, 1);
 
-		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+		spin_unlock(&ieee->mgmt_tx_lock);
 	}
 
 	sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
 	/* 2 wake, 1 sleep, 0 do nothing */
 	if(sleep == 0)//it is not time out or dtim is not valid
 	{
-		//printk("===========>sleep is 0,do nothing\n");
 		goto out;
 	}
 	if(sleep == 1){
-		//printk("===========>sleep is 1,to sleep\n");
 		if(ieee->sta_sleep == 1){
-			//printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
-			ieee->enter_sleep_state(ieee->dev,th,tl);
+			ieee->enter_sleep_state(ieee, th, tl);
 		}
 
 		else if(ieee->sta_sleep == 0){
-		//	printk("send null 1\n");
-			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+			spin_lock(&ieee->mgmt_tx_lock);
 
-			if(ieee->ps_is_queue_empty(ieee->dev)){
+			if (ieee->ps_is_queue_empty(ieee)) {
 				ieee->sta_sleep = 2;
 				ieee->ack_tx_to_ieee = 1;
-				//printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
 				ieee80211_sta_ps_send_null_frame(ieee,1);
 				ieee->ps_th = th;
 				ieee->ps_tl = tl;
 			}
-			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+			spin_unlock(&ieee->mgmt_tx_lock);
 
 		}
 
 		ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
 
 	}else if(sleep == 2){
-		//printk("==========>sleep is 2,to wakeup\n");
-		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+		spin_lock(&ieee->mgmt_tx_lock);
 
-		//printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
 		ieee80211_sta_wakeup(ieee,1);
 
-		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+		spin_unlock(&ieee->mgmt_tx_lock);
 	}
 
 out:
@@ -2072,15 +1883,12 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
 		if(nl){
 			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
 			{
-				//printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
-				//printk("Warning: driver is probably failing to report TX ps error\n");
 				ieee->ack_tx_to_ieee = 1;
 				ieee80211_sta_ps_send_null_frame(ieee, 0);
 			}
 			else
 			{
 				ieee->ack_tx_to_ieee = 1;
-				//printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
 				ieee80211_sta_ps_send_pspoll_frame(ieee);
 			}
 		}
@@ -2089,13 +1897,11 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
 	}
 
 	if(ieee->sta_sleep == 1)
-		ieee->sta_wake_up(ieee->dev);
+		ieee->sta_wake_up(ieee);
 	if(nl){
 
 			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
 			{
-				//printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
-				//printk("Warning: driver is probably failing to report TX ps error\n");
 				ieee->ack_tx_to_ieee = 1;
 				ieee80211_sta_ps_send_null_frame(ieee, 0);
 			}
@@ -2103,7 +1909,6 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
 			{
 				ieee->ack_tx_to_ieee = 1;
 			ieee->polling = true;
-				//printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
 				//ieee80211_sta_ps_send_null_frame(ieee, 0);
 				ieee80211_sta_ps_send_pspoll_frame(ieee);
 			}
@@ -2116,7 +1921,7 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
 
 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
 {
-	unsigned long flags,flags2;
+	unsigned long flags;
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
@@ -2124,25 +1929,22 @@ void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
 		/* Null frame with PS bit set */
 		if(success){
 			ieee->sta_sleep = 1;
-			//printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
-			ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
+			ieee->enter_sleep_state(ieee, ieee->ps_th, ieee->ps_tl);
 		}
 	} else {/* 21112005 - tx again null without PS bit if lost */
 
 		if((ieee->sta_sleep == 0) && !success){
-			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+			spin_lock(&ieee->mgmt_tx_lock);
 			//ieee80211_sta_ps_send_null_frame(ieee, 0);
 			if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
 			{
-				//printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
 				ieee80211_sta_ps_send_null_frame(ieee, 0);
 			}
 			else
 			{
-				//printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
 				ieee80211_sta_ps_send_pspoll_frame(ieee);
 			}
-			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
+			spin_unlock(&ieee->mgmt_tx_lock);
 		}
 	}
 	spin_unlock_irqrestore(&ieee->lock, flags);
@@ -2153,7 +1955,7 @@ void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb
 	struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
 	u8* act = ieee80211_get_payload(header);
 	u8 tmp = 0;
-//	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
+
 	if (act == NULL)
 	{
 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
@@ -2172,8 +1974,6 @@ void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb
 			ieee80211_rx_DELBA(ieee, skb);
 			break;
 		default:
-//			if (net_ratelimit())
-//			IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
 			break;
 	}
 	return;
@@ -2190,23 +1990,10 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 	int chlen=0;
 	int aid;
 	struct ieee80211_assoc_response_frame *assoc_resp;
-//	struct ieee80211_info_element *info_element;
 	bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
 
 	if(!ieee->proto_started)
 		return 0;
-#if 0
-	printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
-	if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
-		ieee->iw_mode == IW_MODE_INFRA &&
-		ieee->state == IEEE80211_LINKED))
-
-		tasklet_schedule(&ieee->ps_task);
-
-	if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
-		WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
-		ieee->last_rx_ps_time = jiffies;
-#endif
 
 	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
 
@@ -2241,7 +2028,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 							memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
 						}
 						if (ieee->handle_assoc_response != NULL)
-							ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
+							ieee->handle_assoc_response(ieee, (struct ieee80211_assoc_response_frame*)header, network);
 					}
 					ieee80211_associate_complete(ieee);
 				} else {
@@ -2285,7 +2072,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 								ieee->softmac_stats.rx_auth_rs_ok++;
 								if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
 								{
-									if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
+									if (!ieee->GetNmodeSupportBySecCfg(ieee))
 									{
 										// WEP or TKIP encryption
 										if(IsHTHalfNmodeAPs(ieee))
@@ -2304,12 +2091,12 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 								/* Dummy wirless mode setting to avoid encryption issue */
 								if(bSupportNmode) {
 									//N mode setting
-									ieee->SetWirelessMode(ieee->dev, \
+									ieee->SetWirelessMode(ieee,
 											ieee->current_network.mode);
 								}else{
 									//b/g mode setting
 									/*TODO*/
-									ieee->SetWirelessMode(ieee->dev, IEEE_G);
+									ieee->SetWirelessMode(ieee, IEEE_G);
 								}
 
 								if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
@@ -2361,8 +2148,6 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 				ieee->softmac_stats.reassoc++;
 				ieee->is_roaming = true;
 				ieee80211_disassociate(ieee);
-			//	notify_wx_assoc_event(ieee);
-				//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 				RemovePeerTS(ieee, header->addr2);
 				queue_work(ieee->wq, &ieee->associate_procedure_wq);
 			}
@@ -2375,7 +2160,6 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
 			break;
 	}
 
-	//dev_kfree_skb_any(skb);
 	return 0;
 }
 
@@ -2411,13 +2195,11 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
 	ieee80211_sta_wakeup(ieee,0);
 
 	/* update the tx status */
-//	ieee->stats.tx_bytes += txb->payload_size;
-//	ieee->stats.tx_packets++;
 	tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
 	if(tcb_desc->bMulticast) {
 		ieee->stats.multicast++;
 	}
-#if 1
+
 	/* if xmit available, just xmit it immediately, else just insert it to the wait queue */
 	for(i = 0; i < txb->nr_frags; i++) {
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
@@ -2425,14 +2207,12 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
 #else
 		if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
 #endif
-		(!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
+		(!ieee->check_nic_enough_desc(ieee, queue_index))||
 		     (ieee->queue_stop)) {
 			/* insert the skb packet to the wait queue */
 			/* as for the completion function, it does not need
 			 * to check it any more.
 			 * */
-			//printk("error:no descriptor left@queue_index %d\n", queue_index);
-			//ieee80211_rtl_stop_queue(ieee);
 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
 			skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
 #else
@@ -2441,16 +2221,12 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
 		}else{
 			ieee->softmac_data_hard_start_xmit(
 					txb->fragments[i],
-					ieee->dev,ieee->rate);
-			//ieee->stats.tx_packets++;
-			//ieee->stats.tx_bytes += txb->fragments[i]->len;
-			//ieee->dev->trans_start = jiffies;
+					ieee, ieee->rate);
 		}
 	}
-#endif
+
 	ieee80211_txb_free(txb);
 
-//exit:
 	spin_unlock_irqrestore(&ieee->lock,flags);
 
 }
@@ -2468,10 +2244,8 @@ void ieee80211_resume_tx(struct ieee80211_device *ieee)
 
 			ieee->softmac_data_hard_start_xmit(
 				ieee->tx_pending.txb->fragments[i],
-				ieee->dev,ieee->rate);
-				//(i+1)<ieee->tx_pending.txb->nr_frags);
+				ieee, ieee->rate);
 			ieee->stats.tx_packets++;
-		//	ieee->dev->trans_start = jiffies;
 		}
 	}
 
@@ -2520,8 +2294,7 @@ void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
 			else
 				ieee->seq_ctrl[0]++;
 
-			ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
-			//dev_kfree_skb_any(skb);//edit by thomas
+			ieee->softmac_data_hard_start_xmit(skb, ieee, ieee->basic_rate);
 		}
 	}
 	if (!ieee->queue_stop && ieee->tx_pending.txb)
@@ -2539,16 +2312,11 @@ exit :
 
 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
 {
-	//unsigned long flags;
-	//spin_lock_irqsave(&ieee->lock,flags);
-
 	if (! netif_queue_stopped(ieee->dev)){
 		netif_stop_queue(ieee->dev);
 		ieee->softmac_stats.swtxstop++;
 	}
 	ieee->queue_stop = 1;
-	//spin_unlock_irqrestore(&ieee->lock,flags);
-
 }
 
 
@@ -2580,13 +2348,13 @@ void ieee80211_start_master_bss(struct ieee80211_device *ieee)
 
 	memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
 
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
+	ieee->set_chan(ieee, ieee->current_network.channel);
 	ieee->state = IEEE80211_LINKED;
-	ieee->link_change(ieee->dev);
+	ieee->link_change(ieee);
 	notify_wx_assoc_event(ieee);
 
 	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
+		ieee->data_hard_resume(ieee);
 
 	netif_carrier_on(ieee->dev);
 }
@@ -2596,7 +2364,7 @@ void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
 	if(ieee->raw_tx){
 
 		if (ieee->data_hard_resume)
-			ieee->data_hard_resume(ieee->dev);
+			ieee->data_hard_resume(ieee);
 
 		netif_carrier_on(ieee->dev);
 	}
@@ -2631,7 +2399,6 @@ void ieee80211_start_ibss_wq(struct work_struct *work)
 
 
 #ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d.
-//	if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
 	if (ieee->state == IEEE80211_NOLINK)
 		ieee->current_network.channel = 6;
 #endif
@@ -2690,7 +2457,7 @@ void ieee80211_start_ibss_wq(struct work_struct *work)
 
 		// By default, WMM function will be disabled in IBSS mode
 		ieee->current_network.QoS_Enable = 0;
-		ieee->SetWirelessMode(ieee->dev, IEEE_G);
+		ieee->SetWirelessMode(ieee, IEEE_G);
 		ieee->current_network.atim_window = 0;
 		ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
 		if(ieee->short_slot)
@@ -2700,15 +2467,15 @@ void ieee80211_start_ibss_wq(struct work_struct *work)
 
 	ieee->state = IEEE80211_LINKED;
 
-	ieee->set_chan(ieee->dev, ieee->current_network.channel);
-	ieee->link_change(ieee->dev);
+	ieee->set_chan(ieee, ieee->current_network.channel);
+	ieee->link_change(ieee);
 
 	notify_wx_assoc_event(ieee);
 
 	ieee80211_start_send_beacons(ieee);
 
 	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
+		ieee->data_hard_resume(ieee);
 	netif_carrier_on(ieee->dev);
 
 	up(&ieee->wx_sem);
@@ -2755,7 +2522,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
 	if (ieee->state == IEEE80211_NOLINK){
 #ifdef ENABLE_IPS
 		if(ieee->ieee80211_ips_leave_wq != NULL)
-			ieee->ieee80211_ips_leave_wq(ieee->dev);
+			ieee->ieee80211_ips_leave_wq(ieee);
 #endif
 		ieee->actscanning = true;
 		ieee80211_rtl_start_scan(ieee);
@@ -2773,14 +2540,13 @@ void ieee80211_disassociate(struct ieee80211_device *ieee)
 			ieee80211_reset_queue(ieee);
 
 	if (ieee->data_hard_stop)
-			ieee->data_hard_stop(ieee->dev);
+		ieee->data_hard_stop(ieee);
 #ifdef ENABLE_DOT11D
 	if(IS_DOT11D_ENABLE(ieee))
 		Dot11d_Reset(ieee);
 #endif
 	ieee->is_set_key = false;
-	ieee->link_change(ieee->dev);
-	//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+	ieee->link_change(ieee);
 	if (ieee->state == IEEE80211_LINKED ||
 	    ieee->state == IEEE80211_ASSOCIATING) {
 		ieee->state = IEEE80211_NOLINK;
@@ -2937,8 +2703,6 @@ void ieee80211_start_protocol(struct ieee80211_device *ieee)
 
 	if (ieee->current_network.beacon_interval == 0)
 		ieee->current_network.beacon_interval = 100;
-//	printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
-//	ieee->set_chan(ieee->dev,ieee->current_network.channel);
 
        	for(i = 0; i < 17; i++) {
 	  ieee->last_rxseq_num[i] = -1;
@@ -3027,11 +2791,7 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
 	ieee->beacon_timer.data = (unsigned long) ieee;
 	ieee->beacon_timer.function = ieee80211_send_beacon_cb;
 
-#ifdef PF_SYNCTHREAD
-	ieee->wq = create_workqueue(DRV_NAME,0);
-#else
 	ieee->wq = create_workqueue(DRV_NAME);
-#endif
 
         INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
         INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
@@ -3058,11 +2818,8 @@ void ieee80211_softmac_free(struct ieee80211_device *ieee)
 {
 	down(&ieee->wx_sem);
 #ifdef ENABLE_DOT11D
-	if(NULL != ieee->pDot11dInfo)
-	{
-		kfree(ieee->pDot11dInfo);
-		ieee->pDot11dInfo = NULL;
-	}
+	kfree(ieee->pDot11dInfo);
+	ieee->pDot11dInfo = NULL;
 #endif
 	del_timer_sync(&ieee->associate_timer);
 
@@ -3176,9 +2933,7 @@ static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
 
 
 	if (ieee->set_security)
-		ieee->set_security(ieee->dev, &sec);
-	//else
-	//	ret = -EOPNOTSUPP;
+		ieee->set_security(ieee, &sec);
 
 	return ret;
 }
@@ -3226,7 +2981,7 @@ static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 v
 			sec.level = SEC_LEVEL_1;
 		}
 		if (ieee->set_security)
-			ieee->set_security(ieee->dev, &sec);
+			ieee->set_security(ieee, &sec);
 		break;
 	}
 
@@ -3392,7 +3147,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
 	}
  done:
 	if (ieee->set_security)
-		ieee->set_security(ieee->dev, &sec);
+		ieee->set_security(ieee, &sec);
 
 	/* Do not reset port if card is in Managed mode since resetting will
 	 * generate new IEEE 802.11 authentication which may end up in looping
@@ -3402,7 +3157,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
 	if (ieee->reset_on_keychange &&
 	    ieee->iw_mode != IW_MODE_INFRA &&
 	    ieee->reset_port &&
-	    ieee->reset_port(ieee->dev)) {
+	    ieee->reset_port(ieee)) {
 		printk("reset_port failed\n");
 		param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
 		return -EINVAL;
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
index d0a1080..d8a068e 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
@@ -70,7 +70,7 @@ int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info
 		}
 #endif
 		ieee->current_network.channel = fwrq->m;
-		ieee->set_chan(ieee->dev, ieee->current_network.channel);
+		ieee->set_chan(ieee, ieee->current_network.channel);
 
 		if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
 			if(ieee->state == IEEE80211_LINKED){
@@ -98,8 +98,6 @@ int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
 	//NM 0.7.0 will not accept channel any more.
 	fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000;
 	fwrq->e = 1;
-//	fwrq->m = ieee->current_network.channel;
-//	fwrq->e = 0;
 
 	return 0;
 }
@@ -233,23 +231,8 @@ int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
 			     union iwreq_data *wrqu, char *extra)
 {
 	u32 tmp_rate;
-#if 0
-	printk("===>mode:%d, halfNmode:%d\n", ieee->mode, ieee->bHalfWirelessN24GMode);
-	if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G))
-		tmp_rate = ieee->rate;
-	else if (ieee->mode & IEEE_N_5G)
-		tmp_rate = 580;
-	else if (ieee->mode & IEEE_N_24G)
-	{
-		if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
-			tmp_rate = HTHalfMcsToDataRate(ieee, 15);
-		else
-			tmp_rate = HTMcsToDataRate(ieee, 15);
-	}
-#else
 	tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate);
 
-#endif
 	wrqu->bitrate.value = tmp_rate * 500000;
 
 	return 0;
@@ -324,7 +307,7 @@ void ieee80211_wx_sync_scan_wq(struct work_struct *work)
 
 #ifdef ENABLE_LPS
 	if (ieee->LeisurePSLeave) {
-		ieee->LeisurePSLeave(ieee->dev);
+		ieee->LeisurePSLeave(ieee);
 	}
 
 	/* notify AP to be in PS mode */
@@ -333,37 +316,37 @@ void ieee80211_wx_sync_scan_wq(struct work_struct *work)
 #endif
 
 	if (ieee->data_hard_stop)
-		ieee->data_hard_stop(ieee->dev);
+		ieee->data_hard_stop(ieee);
 
 	ieee80211_stop_send_beacons(ieee);
 
 	ieee->state = IEEE80211_LINKED_SCANNING;
-	ieee->link_change(ieee->dev);
-	ieee->InitialGainHandler(ieee->dev,IG_Backup);
+	ieee->link_change(ieee);
+	ieee->InitialGainHandler(ieee, IG_Backup);
 	if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) {
 		b40M = 1;
 		chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset;
 		bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz;
 		printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth);
-		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+		ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 		}
 	ieee80211_start_scan_syncro(ieee);
 	if (b40M) {
 		printk("Scan in 20M, back to 40M\n");
 		if (chan_offset == HT_EXTCHNL_OFFSET_UPPER)
-			ieee->set_chan(ieee->dev, chan + 2);
+			ieee->set_chan(ieee, chan + 2);
 		else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER)
-			ieee->set_chan(ieee->dev, chan - 2);
+			ieee->set_chan(ieee, chan - 2);
 		else
-			ieee->set_chan(ieee->dev, chan);
-		ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset);
+			ieee->set_chan(ieee, chan);
+		ieee->SetBWModeHandler(ieee, bandwidth, chan_offset);
 	} else {
-		ieee->set_chan(ieee->dev, chan);
+		ieee->set_chan(ieee, chan);
 	}
 
-	ieee->InitialGainHandler(ieee->dev,IG_Restore);
+	ieee->InitialGainHandler(ieee, IG_Restore);
 	ieee->state = IEEE80211_LINKED;
-	ieee->link_change(ieee->dev);
+	ieee->link_change(ieee);
 
 #ifdef ENABLE_LPS
 	/* Notify AP that I wake up again */
@@ -377,7 +360,7 @@ void ieee80211_wx_sync_scan_wq(struct work_struct *work)
 		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
 	}
 	if (ieee->data_hard_resume)
-		ieee->data_hard_resume(ieee->dev);
+		ieee->data_hard_resume(ieee);
 
 	if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER)
 		ieee80211_start_send_beacons(ieee);
@@ -496,7 +479,7 @@ out:
 	{
 		if(prev == 0 && ieee->raw_tx){
 			if (ieee->data_hard_resume)
-				ieee->data_hard_resume(ieee->dev);
+				ieee->data_hard_resume(ieee);
 
 			netif_carrier_on(ieee->dev);
 		}
@@ -531,18 +514,15 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 				 union iwreq_data *wrqu, char *extra)
 {
 	int ret = 0;
-#if 1
+
 	if(
 		(!ieee->sta_wake_up) ||
-	//	(!ieee->ps_request_tx_ack) ||
 		(!ieee->enter_sleep_state) ||
 		(!ieee->ps_is_queue_empty)){
 
-	//	printk("ERROR. PS mode is tryied to be use but driver missed a callback\n\n");
-
 		return -1;
 	}
-#endif
+
 	down(&ieee->wx_sem);
 
 	if (wrqu->power.disabled){
@@ -550,16 +530,11 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 		goto exit;
 	}
 	if (wrqu->power.flags & IW_POWER_TIMEOUT) {
-		//ieee->ps_period = wrqu->power.value / 1000;
 		ieee->ps_timeout = wrqu->power.value / 1000;
 	}
 
 	if (wrqu->power.flags & IW_POWER_PERIOD) {
-
-		//ieee->ps_timeout = wrqu->power.value / 1000;
 		ieee->ps_period = wrqu->power.value / 1000;
-		//wrq->value / 1024;
-
 	}
 	switch (wrqu->power.flags & IW_POWER_MODE) {
 	case IW_POWER_UNICAST_R:
@@ -573,7 +548,6 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
 		break;
 
 	case IW_POWER_ON:
-	//	ieee->ps = IEEE80211_PS_DISABLED;
 		break;
 
 	default:
@@ -607,11 +581,8 @@ int ieee80211_wx_get_power(struct ieee80211_device *ieee,
 		wrqu->power.flags = IW_POWER_TIMEOUT;
 		wrqu->power.value = ieee->ps_timeout * 1000;
 	} else {
-//		ret = -EOPNOTSUPP;
-//		goto exit;
 		wrqu->power.flags = IW_POWER_PERIOD;
 		wrqu->power.value = ieee->ps_period * 1000;
-//ieee->current_network.dtim_period * ieee->current_network.beacon_interval * 1024;
 	}
 
        if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST))
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
index b26b5a8..995346d 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -32,7 +32,6 @@
 ******************************************************************************/
 
 #include <linux/compiler.h>
-//#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in6.h>
@@ -232,14 +231,8 @@ int ieee80211_encrypt_fragment(
 
 
 void ieee80211_txb_free(struct ieee80211_txb *txb) {
-	//int i;
 	if (unlikely(!txb))
 		return;
-#if 0
-	for (i = 0; i < txb->nr_frags; i++)
-		if (txb->fragments[i])
-			dev_kfree_skb_any(txb->fragments[i]);
-#endif
 	kfree(txb);
 }
 
@@ -337,7 +330,7 @@ void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* s
 
 
 #if 1
-	if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
+	if (!ieee->GetNmodeSupportBySecCfg(ieee))
 	{
 		return;
 	}
@@ -678,22 +671,11 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 				const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
 				if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17.
 					struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
-					//if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) ||
-					///   ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) {
 					if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
 							((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
 						// 68 : UDP BOOTP client
 						// 67 : UDP BOOTP server
 						printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
-						// Use low rate to send DHCP packet.
-						//if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
-						//{
-						//      tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
-						//      tcb_desc->bTxDisableRateFallBack = false;
-						//}
-						//else
-						//pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate;
-						//RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
 
 						bdhcp = true;
 #ifdef _RTL8192_EXT_PATCH_
@@ -708,15 +690,6 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 					bdhcp = true;
 					ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
 
-					//if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
-					//{
-					//      tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m
-					//      tcb_desc->bTxDisableRateFallBack = FALSE;
-					//}
-					//else
-					//      tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate;
-					//RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
-
 				}
 			}
 
@@ -736,7 +709,6 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 
                         fc = IEEE80211_FTYPE_DATA;
 
-		//if(ieee->current_network.QoS_Enable)
 		if(qos_actived)
 			fc |= IEEE80211_STYPE_QOS_DATA;
 		else
@@ -771,7 +743,6 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 			qos_ctl = 0;
 		}
 
-		//if (ieee->current_network.QoS_Enable)
 		if(qos_actived)
 		{
 			hdr_len = IEEE80211_3ADDR_LEN + 2;
@@ -817,7 +788,6 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 		txb->encrypted = encrypt;
 		txb->payload_size = bytes;
 
-		//if (ieee->current_network.QoS_Enable)
 		if(qos_actived)
 		{
 			txb->queue_index = UP2AC(skb->priority);
@@ -864,7 +834,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 				/* The last fragment takes the remaining length */
 				bytes = bytes_last_frag;
 			}
-			//if(ieee->current_network.QoS_Enable)
+
 			if(qos_actived)
 			{
 				// add 1 only indicate to corresponding seq number control 2006/7/12
@@ -930,7 +900,6 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 //WB add to fill data tcb_desc here. only first fragment is considered, need to change, and you may remove to other place.
 	if (txb)
 	{
-#if 1
 		cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
 		tcb_desc->bTxEnableFwCalcDur = 1;
 		if (is_multicast_ether_addr(header.addr1))
@@ -941,20 +910,11 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 		if ( tcb_desc->bMulticast ||  tcb_desc->bBroadcast)
 			tcb_desc->data_rate = ieee->basic_rate;
 		else
-			//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
 			tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
 
 		if(bdhcp == true){
-			// Use low rate to send DHCP packet.
-			//if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) {
-			//	tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
-			//	tcb_desc->bTxDisableRateFallBack = false;
-			//}
-			//else
-			{
 				tcb_desc->data_rate = MGN_1M;
 				tcb_desc->bTxDisableRateFallBack = 1;
-			}
 
 			tcb_desc->RATRIndex = 7;
 			tcb_desc->bTxUseDriverAssingedRate = 1;
@@ -968,9 +928,6 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 		ieee80211_query_BandwidthMode(ieee, tcb_desc);
 		ieee80211_query_protectionmode(ieee, tcb_desc, txb->fragments[0]);
 		ieee80211_query_seqnum(ieee, txb->fragments[0], header.addr1);
-//		IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, txb->fragments[0]->data, txb->fragments[0]->len);
-		//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, tcb_desc, sizeof(cb_desc));
-#endif
 	}
 	spin_unlock_irqrestore(&ieee->lock, flags);
 	dev_kfree_skb_any(skb);
@@ -978,7 +935,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
 			ieee80211_softmac_xmit(txb, ieee);
 		}else{
-			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
+			if ((*ieee->hard_start_xmit)(txb, ieee) == 0) {
 				stats->tx_packets++;
 				stats->tx_bytes += txb->payload_size;
 				return 0;
@@ -997,4 +954,3 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
 
 }
 
-//EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
index b74491c..6530d9b 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
@@ -36,11 +36,7 @@
 #include <linux/module.h>
 
 #include "ieee80211.h"
-#if 0
-static const char *ieee80211_modes[] = {
-	"?", "a", "b", "ab", "g", "ag", "bg", "abg"
-};
-#endif
+
 struct modes_unit {
 	char *mode_string;
 	int mode_size;
@@ -203,7 +199,6 @@ static inline char *rtl819x_translate_scan(struct ieee80211_device *ieee,
 #if (WIRELESS_EXT < 18)
 	if (ieee->wpa_enabled && network->wpa_ie_len){
 		char buf[MAX_WPA_IE_LEN * 2 + 30];
-	//	printk("WPA IE\n");
 		u8 *p = buf;
 		p += sprintf(p, "wpa_ie=");
 		for (i = 0; i < network->wpa_ie_len; i++) {
@@ -468,7 +463,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 	sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
 
 	if (ieee->set_security)
-		ieee->set_security(dev, &sec);
+		ieee->set_security(ieee, &sec);
 
 	/* Do not reset port if card is in Managed mode since resetting will
 	 * generate new IEEE 802.11 authentication which may end up in looping
@@ -477,7 +472,7 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
 	 * the callbacks structures used to initialize the 802.11 stack. */
 	if (ieee->reset_on_keychange &&
 	    ieee->iw_mode != IW_MODE_INFRA &&
-	    ieee->reset_port && ieee->reset_port(dev)) {
+	    ieee->reset_port && ieee->reset_port(ieee)) {
 		printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
 		return -EINVAL;
 	}
@@ -552,7 +547,6 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
         struct ieee80211_security sec = {
                 .flags = 0,
         };
-	//printk("======>encoding flag:%x,ext flag:%x, ext alg:%d\n", encoding->flags,ext->ext_flags, ext->alg);
         idx = encoding->flags & IW_ENCODE_INDEX;
         if (idx) {
                 if (idx < 1 || idx > WEP_KEYS)
@@ -568,7 +562,6 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                 group_key = 1;
         } else {
                 /* some Cisco APs use idx>0 for unicast in dynamic WEP */
-		//printk("not group key, flags:%x, ext->alg:%d\n", ext->ext_flags, ext->alg);
                 if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
                         return -EINVAL;
                 if (ieee->iw_mode == IW_MODE_INFRA)
@@ -597,7 +590,6 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                         sec.level = SEC_LEVEL_0;
                         sec.flags |= SEC_LEVEL;
                 }
-		//printk("disabled: flag:%x\n", encoding->flags);
                 goto done;
         }
 
@@ -674,8 +666,6 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
                 goto done;
         }
 #if 1
- //skip_host_crypt:
-	//printk("skip_host_crypt:ext_flags:%x\n", ext->ext_flags);
         if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
                 ieee->tx_keyidx = idx;
                 sec.active_key = idx;
@@ -706,11 +696,11 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
 #endif
 done:
         if (ieee->set_security)
-                ieee->set_security(ieee->dev, &sec);
+		ieee->set_security(ieee, &sec);
 
 	 if (ieee->reset_on_keychange &&
             ieee->iw_mode != IW_MODE_INFRA &&
-            ieee->reset_port && ieee->reset_port(dev)) {
+            ieee->reset_port && ieee->reset_port(ieee)) {
                 IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
                 return -EINVAL;
         }
@@ -795,7 +785,6 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
 	switch (data->flags & IW_AUTH_INDEX) {
         case IW_AUTH_WPA_VERSION:
 	     /*need to support wpa2 here*/
-		//printk("wpa version:%x\n", data->value);
 		break;
         case IW_AUTH_CIPHER_PAIRWISE:
         case IW_AUTH_CIPHER_GROUP:
@@ -813,8 +802,6 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
 		break;
 
 	case IW_AUTH_80211_AUTH_ALG:
-		//printk("======>%s():data->value is %d\n",__FUNCTION__,data->value);
-	//	ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM)?1:0;
 		if(data->value & IW_AUTH_ALG_SHARED_KEY){
 			ieee->open_wep = 0;
 			ieee->auth_mode = 1;
@@ -826,17 +813,14 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
 		else if(data->value & IW_AUTH_ALG_LEAP){
 			ieee->open_wep = 1;
 			ieee->auth_mode = 2;
-			//printk("hahahaa:LEAP\n");
 		}
 		else
 			return -EINVAL;
-		//printk("open_wep:%d\n", ieee->open_wep);
 		break;
 
 #if 1
 	case IW_AUTH_WPA_ENABLED:
 		ieee->wpa_enabled = (data->value)?1:0;
-		//printk("enable wpa:%d\n", ieee->wpa_enabled);
 		break;
 
 #endif
@@ -859,7 +843,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
 
 	if (len>MAX_WPA_IE_LEN || (len && ie == NULL))
 	{
-	//	printk("return error out, len:%d\n", len);
 	return -EINVAL;
 	}
 
@@ -879,7 +862,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
 		ieee->wpa_ie_len = len;
 	}
 	else{
-		if (ieee->wpa_ie)
 		kfree(ieee->wpa_ie);
 		ieee->wpa_ie = NULL;
 		ieee->wpa_ie_len = 0;
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
index ae0e5b9..b690cbc 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
@@ -1,18 +1,16 @@
-/********************************************************************************************************************************
- * This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
- * related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send
- * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
- * WB 2008-05-27
- * *****************************************************************************************************************************/
+/*
+ * This file is created to process BA Action Frame. According to 802.11 spec,
+ * there are 3 BA action types at all. And as BA is related to TS, this part
+ * need some struture defined in QOS side code. Also TX RX is going to be
+ * resturctured, so how to send ADDBAREQ ADDBARSP and DELBA packet is still
+ * on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
+ */
 #include "ieee80211.h"
 #include "rtl819x_BA.h"
 
-/********************************************************************************************************************
- *function:  Activate BA entry. And if Time is nozero, start timer.
- *   input:  PBA_RECORD 		pBA  //BA entry to be enabled
- *   	     u16 			Time //indicate time delay.
- *  output:  none
-********************************************************************************************************************/
+/*
+ * Activate BA entry. And if Time is nozero, start timer.
+ */
 void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
 {
 	pBA->bValid = true;
@@ -20,23 +18,18 @@ void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
 		mod_timer(&pBA->Timer, jiffies + MSECS(Time));
 }
 
-/********************************************************************************************************************
- *function:  deactivate BA entry, including its timer.
- *   input:  PBA_RECORD 		pBA  //BA entry to be disabled
- *  output:  none
-********************************************************************************************************************/
+/*
+ * deactivate BA entry, including its timer.
+ */
 void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
 {
 	pBA->bValid = false;
 	del_timer_sync(&pBA->Timer);
 }
-/********************************************************************************************************************
- *function: deactivete BA entry in Tx Ts, and send DELBA.
- *   input:
- *   	     PTX_TS_RECORD		pTxTs //Tx Ts which is to deactivate BA entry.
- *  output:  none
- *  notice:  As PTX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME
-********************************************************************************************************************/
+
+/*
+ * deactivete BA entry in Tx Ts, and send DELBA.
+ */
 u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD	pTxTs)
 {
 	PBA_RECORD		pAdmittedBa = &pTxTs->TxAdmittedBARecord;  //These two BA entries must exist in TS structure
@@ -60,13 +53,9 @@ u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD	pTxTs)
 	return bSendDELBA;
 }
 
-/********************************************************************************************************************
- *function: deactivete BA entry in Tx Ts, and send DELBA.
- *   input:
- *   	     PRX_TS_RECORD		pRxTs //Rx Ts which is to deactivate BA entry.
- *  output:  none
- *  notice:  As PRX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME, same with above
-********************************************************************************************************************/
+/*
+ * deactivete BA entry in Tx Ts, and send DELBA.
+ */
 u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD	pRxTs)
 {
 	PBA_RECORD		pBa = &pRxTs->RxAdmittedBARecord;
@@ -81,12 +70,9 @@ u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD	pRxTs)
 	return bSendDELBA;
 }
 
-/********************************************************************************************************************
- *function: reset BA entry
- *   input:
- *   	     PBA_RECORD		pBA //entry to be reset
- *  output:  none
-********************************************************************************************************************/
+/*
+ * reset BA entry
+ */
 void ResetBaEntry( PBA_RECORD pBA)
 {
 	pBA->bValid			= false;
@@ -95,16 +81,11 @@ void ResetBaEntry( PBA_RECORD pBA)
 	pBA->DialogToken		= 0;
 	pBA->BaStartSeqCtrl.ShortData	= 0;
 }
-//These functions need porting here or not?
-/*******************************************************************************************************************************
- *function:  construct ADDBAREQ and ADDBARSP frame here together.
- *   input:  u8* 		Dst 	//ADDBA frame's destination
- *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA.
- *   	     u16 		StatusCode  //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
- *   	     u8			type	//indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
- *  output:  none
- *  return:  sk_buff* 		skb     //return constructed skb to xmit
-*******************************************************************************************************************************/
+
+/*
+ * construct ADDBAREQ and ADDBARSP frame here together.
+ * return constructed skb to xmit
+ */
 static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
 {
 	struct sk_buff *skb = NULL;
@@ -174,58 +155,9 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P
 	//return NULL;
 }
 
-#if 0 //I try to merge ADDBA_REQ and ADDBA_RSP frames together..
-/********************************************************************************************************************
- *function:  construct ADDBAREQ frame
- *   input:  u8* 		dst 	//ADDBARsp frame's destination
- *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA_RSP.
- *   	     u16 		StatusCode  //status code.
- *  output:  none
- *  return:  sk_buff* 		skb     //return constructed skb to xmit
-********************************************************************************************************************/
-static struct sk_buff* ieee80211_ADDBA_Rsp( IN	struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
-{
-	OCTET_STRING	osADDBAFrame, tmp;
-
-	FillOctetString(osADDBAFrame, Buffer, 0);
-	*pLength = 0;
-
-	ConstructMaFrameHdr(
-					Adapter,
-					Addr,
-					ACT_CAT_BA,
-					ACT_ADDBARSP,
-					&osADDBAFrame	);
-
-	// Dialog Token
-	FillOctetString(tmp, &pBA->DialogToken, 1);
-	PacketAppendData(&osADDBAFrame, tmp);
-
-	// Status Code
-	FillOctetString(tmp, &StatusCode, 2);
-	PacketAppendData(&osADDBAFrame, tmp);
-
-	// BA Parameter Set
-	FillOctetString(tmp, &pBA->BaParamSet, 2);
-	PacketAppendData(&osADDBAFrame, tmp);
-
-	// BA Timeout Value
-	FillOctetString(tmp, &pBA->BaTimeoutValue, 2);
-	PacketAppendData(&osADDBAFrame, tmp);
-
-	*pLength = osADDBAFrame.Length;
-}
-#endif
-
-/********************************************************************************************************************
- *function:  construct DELBA frame
- *   input:  u8* 		dst 	//DELBA frame's destination
- *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
- *   	     TR_SELECT	        TxRxSelect  //TX RX direction
- *   	     u16 		ReasonCode  //status code.
- *  output:  none
- *  return:  sk_buff* 		skb     //return constructed skb to xmit
-********************************************************************************************************************/
+/*
+ * construct DELBA frame
+ */
 static struct sk_buff* ieee80211_DELBA(
 	struct ieee80211_device* ieee,
 	u8*		         dst,
@@ -286,13 +218,11 @@ static struct sk_buff* ieee80211_DELBA(
 	return skb;
 }
 
-/********************************************************************************************************************
- *function: send ADDBAReq frame out
- *   input:  u8* 		dst 	//ADDBAReq frame's destination
- *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
- *  output:  none
- *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
-********************************************************************************************************************/
+/*
+ * send ADDBAReq frame out
+ * If any possible, please hide pBA in ieee.
+ * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
+ */
 void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8*	dst, PBA_RECORD	pBA)
 {
 	struct sk_buff *skb = NULL;
@@ -309,17 +239,13 @@ void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8*	dst, PBA_RECORD
 	{
 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
 	}
-	return;
 }
 
-/********************************************************************************************************************
- *function: send ADDBARSP frame out
- *   input:  u8* 		dst 	//DELBA frame's destination
- *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
- *   	     u16		StatusCode //RSP StatusCode
- *  output:  none
- *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
-********************************************************************************************************************/
+/*
+ * send ADDBARSP frame out
+ *  If any possible, please hide pBA in ieee.
+ * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
+ */
 void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
 {
 	struct sk_buff *skb = NULL;
@@ -333,20 +259,13 @@ void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD
 	{
 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
 	}
-
-	return;
-
 }
-/********************************************************************************************************************
- *function: send ADDBARSP frame out
- *   input:  u8* 		dst 	//DELBA frame's destination
- *   	     PBA_RECORD 	pBA	//BA_RECORD entry which stores the necessary information for BA
- *   	     TR_SELECT          TxRxSelect //TX or RX
- *   	     u16		ReasonCode //DEL ReasonCode
- *  output:  none
- *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
-********************************************************************************************************************/
 
+/*
+ * send ADDBARSP frame out
+ * If any possible, please hide pBA in ieee.
+ * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
+ */
 void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
 {
 	struct sk_buff *skb = NULL;
@@ -363,12 +282,6 @@ void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA
 	return ;
 }
 
-/********************************************************************************************************************
- *function: RX ADDBAReq
- *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
- *  return:  0(pass), other(fail)
- *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
-********************************************************************************************************************/
 int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
 {
 	 struct ieee80211_hdr_3addr* req = NULL;
@@ -440,7 +353,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
 	pBA->BaTimeoutValue = *pBaTimeoutVal;
 	pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
 	//for half N mode we only aggregate 1 frame
-	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
 	pBA->BaParamSet.field.BufferSize = 1;
 	else
 	pBA->BaParamSet.field.BufferSize = 32;
@@ -463,12 +376,6 @@ OnADDBAReq_Fail:
 
 }
 
-/********************************************************************************************************************
- *function: RX ADDBARSP
- *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
- *  return:  0(pass), other(fail)
- *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
-********************************************************************************************************************/
 int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
 {
 	 struct ieee80211_hdr_3addr* rsp = NULL;
@@ -596,12 +503,6 @@ OnADDBARsp_Reject:
 
 }
 
-/********************************************************************************************************************
- *function: RX DELBA
- *   input:  struct sk_buff *   skb	//incoming ADDBAReq skb.
- *  return:  0(pass), other(fail)
- *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
-********************************************************************************************************************/
 int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
 {
 	 struct ieee80211_hdr_3addr* delba = NULL;
@@ -673,9 +574,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
 	return 0;
 }
 
-//
-// ADDBA initiate. This can only be called by TX side.
-//
+/* ADDBA initiate. This can only be called by TX side. */
 void
 TsInitAddBA(
 	struct ieee80211_device* ieee,
@@ -734,12 +633,11 @@ TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SE
 				DELBA_REASON_END_BA	);
 	}
 }
-/********************************************************************************************************************
- *function:  BA setup timer
- *   input:  unsigned long	 data		//acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
- *  return:  NULL
- *  notice:
-********************************************************************************************************************/
+
+/*
+ *  BA setup timer
+ *  acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
+ */
 void BaSetupTimeOut(unsigned long data)
 {
 	PTX_TS_RECORD	pTxTs = (PTX_TS_RECORD)data;
@@ -774,6 +672,5 @@ void RxBaInactTimeout(unsigned long data)
 		&pRxTs->RxAdmittedBARecord,
 		RX_DIR,
 		DELBA_REASON_TIMEOUT);
-	return ;
 }
 
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
index b0c9c78..a2a4fe9 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
@@ -29,18 +29,18 @@ u16 MCS_DATA_RATE[2][2][77] =
 			660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990}	}	// Short GI, 40MHz
 	};
 
-static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
-static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
-static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
+static const u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
+static const u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
+static const u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
 //static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
-static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};	//cosa 03202008
-static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
-static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
-static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
-static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
-static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
-static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
-static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
+static const u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f};
+static const u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
+static const u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
+static const u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
+static const u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
+static const u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
+static const u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
+static const u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
 
 // 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
 // code in other place??
@@ -55,10 +55,7 @@ static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
 void HTUpdateDefaultSetting(struct ieee80211_device* ieee)
 {
 	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
-	//const typeof( ((struct ieee80211_device *)0)->pHTInfo ) *__mptr = &pHTInfo;
 
-	//printk("pHTinfo:%p, &pHTinfo:%p, mptr:%p,  offsetof:%x\n", pHTInfo, &pHTInfo, __mptr, offsetof(struct ieee80211_device, pHTInfo));
-	//printk("===>ieee:%p,\n", ieee);
 	// ShortGI support
 	pHTInfo->bRegShortGI20MHz= 1;
 	pHTInfo->bRegShortGI40MHz= 1;
@@ -148,8 +145,6 @@ void HTDebugHTCapability(u8* CapIE, u8* TitleString )
 	IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tMPDU Density = %d\n", pCapELE->MPDUDensity);
 	IEEE80211_DEBUG(IEEE80211_DL_HT,  "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\
 				pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]);
-	return;
-
 }
 /********************************************************************************************************************
  *function:  This function print out each field on HT Information IE mainly from (Beacon/ProbeRsp)
@@ -214,7 +209,6 @@ void HTDebugHTInfo(u8*	InfoIE, u8* TitleString)
 
 	IEEE80211_DEBUG(IEEE80211_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\
 				pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]);
-	return;
 }
 
 /*
@@ -229,7 +223,7 @@ bool IsHTHalfNmode40Bandwidth(struct ieee80211_device* ieee)
 		retValue = false;
 	else if(pHTInfo->bRegBW40MHz == false)	// station supports 40 bw
 		retValue = false;
-	else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) 	// station in half n mode
+	else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee))	// station in half n mode
 		retValue = false;
 	else if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) // ap support 40 bw
 		retValue = true;
@@ -246,7 +240,7 @@ bool IsHTHalfNmodeSGI(struct ieee80211_device* ieee, bool is40MHz)
 
 	if(pHTInfo->bCurrentHTSupport == false )	// wireless is n mode
 		retValue = false;
-	else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) 	// station in half n mode
+	else if (!ieee->GetHalfNmodeSupportByAPsHandler(ieee))	// station in half n mode
 		retValue = false;
 	else if(is40MHz) // ap support 40 bw
 	{
@@ -658,7 +652,7 @@ void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u
 
 	//HT capability info
 	pCapELE->AdvCoding 		= 0; // This feature is not supported now!!
-	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
 	{
 		pCapELE->ChlWidth = 0;
 	}
@@ -711,7 +705,7 @@ void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u
 
 	// 2008.06.12
 	// For RTL819X, if pairwisekey = wep/tkip, ap is ralink, we support only MCS0~7.
-	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
 	{
 		int i;
 		for(i = 1; i< 16; i++)
@@ -732,15 +726,6 @@ void HTConstructCapabilityElement(struct ieee80211_device* ieee, u8* posHTCap, u
 		*len = 30 + 2;
 	else
 		*len = 26 + 2;
-
-
-
-//	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, posHTCap, *len -2);
-
-	//Print each field in detail. Driver should not print out this message by default
-//	HTDebugHTCapability(posHTCap, (u8*)"HTConstructCapability()");
-	return;
-
 }
 /********************************************************************************************************************
  *function:  Construct  Information Element in Beacon... if HTEnable is turned on
@@ -792,9 +777,6 @@ void HTConstructInfoElement(struct ieee80211_device* ieee, u8* posHTInfo, u8* le
 		//STA should not generate High Throughput Information Element
 		*len = 0;
 	}
-	//IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA | IEEE80211_DL_HT, posHTInfo, *len - 2);
-	//HTDebugHTInfo(posHTInfo, "HTConstructInforElement");
-	return;
 }
 
 /*
@@ -1011,7 +993,7 @@ u8 HTFilterMCSRate( struct ieee80211_device* ieee, u8* pSupportMCS, u8* pOperate
 	HT_PickMCSRate(ieee, pOperateMCS);
 
 	// For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
-	if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
+	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
 		pOperateMCS[1] = 0;
 
 	//
@@ -1651,7 +1633,6 @@ void HTUseDefaultSetting(struct ieee80211_device* ieee)
 	{
 		pHTInfo->bCurrentHTSupport = false;
 	}
-	return;
 }
 /********************************************************************************************************************
  *function:  check whether HT control field exists
@@ -1698,7 +1679,7 @@ void HTSetConnectBwMode(struct ieee80211_device* ieee, HT_CHANNEL_WIDTH	Bandwidt
 		return;
 	}
 	//if in half N mode, set to 20M bandwidth please 09.08.2008 WB.
-	if(Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)))
+	if (Bandwidth==HT_CHANNEL_WIDTH_20_40 && (!ieee->GetHalfNmodeSupportByAPsHandler(ieee)))
 	 {
 	 		// Handle Illegal extention channel offset!!
 		if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER)
@@ -1735,16 +1716,16 @@ void HTSetConnectBwModeCallback(struct ieee80211_device* ieee)
 	if(pHTInfo->bCurBW40MHz)
 	{
 		if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_UPPER)
-			ieee->set_chan(ieee->dev, ieee->current_network.channel+2);
+			ieee->set_chan(ieee, ieee->current_network.channel+2);
 		else if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_LOWER)
-			ieee->set_chan(ieee->dev, ieee->current_network.channel-2);
+			ieee->set_chan(ieee, ieee->current_network.channel-2);
 		else
-			ieee->set_chan(ieee->dev, ieee->current_network.channel);
+			ieee->set_chan(ieee, ieee->current_network.channel);
 
-		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
+		ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset);
 	} else {
-		ieee->set_chan(ieee->dev, ieee->current_network.channel);
-		ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+		ieee->set_chan(ieee, ieee->current_network.channel);
+		ieee->SetBWModeHandler(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
 	}
 
 	pHTInfo->bSwBwInProgress = false;
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
index 5876b4d..29eecf0 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
@@ -293,7 +293,6 @@ PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8*	Addr, u8
 				if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
 					if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
 					{
-	//					printk("Bingo! got it\n");
 						break;
 					}
 
diff --git a/drivers/staging/rtl8192e/ieee80211_crypt.h b/drivers/staging/rtl8192e/ieee80211_crypt.h
deleted file mode 100644
index b58a3bc..0000000
--- a/drivers/staging/rtl8192e/ieee80211_crypt.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Original code based on Host AP (software wireless LAN access point) driver
- * for Intersil Prism2/2.5/3.
- *
- * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
- * <jkmaline@cc.hut.fi>
- * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
- *
- * Adaption to a generic IEEE 802.11 stack by James Ketrenos
- * <jketreno@linux.intel.com>
- *
- * Copyright (c) 2004, Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation. See README and COPYING for
- * more details.
- */
-
-/*
- * This file defines the interface to the ieee80211 crypto module.
- */
-#ifndef IEEE80211_CRYPT_H
-#define IEEE80211_CRYPT_H
-
-#include <linux/skbuff.h>
-
-struct ieee80211_crypto_ops {
-	const char *name;
-
-	/* init new crypto context (e.g., allocate private data space,
-	 * select IV, etc.); returns NULL on failure or pointer to allocated
-	 * private data on success */
-	void * (*init)(int keyidx);
-
-	/* deinitialize crypto context and free allocated private data */
-	void (*deinit)(void *priv);
-
-	/* encrypt/decrypt return < 0 on error or >= 0 on success. The return
-	 * value from decrypt_mpdu is passed as the keyidx value for
-	 * decrypt_msdu. skb must have enough head and tail room for the
-	 * encryption; if not, error will be returned; these functions are
-	 * called for all MPDUs (i.e., fragments).
-	 */
-	int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv);
-
-	/* These functions are called for full MSDUs, i.e. full frames.
-	 * These can be NULL if full MSDU operations are not needed. */
-	int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv);
-	int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len,
-			    void *priv);
-
-	int (*set_key)(void *key, int len, u8 *seq, void *priv);
-	int (*get_key)(void *key, int len, u8 *seq, void *priv);
-
-	/* procfs handler for printing out key information and possible
-	 * statistics */
-	char * (*print_stats)(char *p, void *priv);
-
-	/* maximum number of bytes added by encryption; encrypt buf is
-	 * allocated with extra_prefix_len bytes, copy of in_buf, and
-	 * extra_postfix_len; encrypt need not use all this space, but
-	 * the result must start at the beginning of the buffer and correct
-	 * length must be returned */
-	int extra_prefix_len, extra_postfix_len;
-
-	struct module *owner;
-};
-
-struct ieee80211_crypt_data {
-	struct list_head list; /* delayed deletion list */
-	struct ieee80211_crypto_ops *ops;
-	void *priv;
-	atomic_t refcnt;
-};
-
-int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops);
-int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops);
-struct ieee80211_crypto_ops * ieee80211_get_crypto_ops(const char *name);
-void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int);
-void ieee80211_crypt_deinit_handler(unsigned long);
-void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee,
-				    struct ieee80211_crypt_data **crypt);
-
-#endif
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.c b/drivers/staging/rtl8192e/r8180_93cx6.c
index c38dd17..55d4f56 100644
--- a/drivers/staging/rtl8192e/r8180_93cx6.c
+++ b/drivers/staging/rtl8192e/r8180_93cx6.c
@@ -20,49 +20,49 @@
 
 #include "r8180_93cx6.h"
 
-static void eprom_cs(struct net_device *dev, short bit)
+static void eprom_cs(struct r8192_priv *priv, short bit)
 {
 	if (bit)
-		write_nic_byte(dev, EPROM_CMD,
+		write_nic_byte(priv, EPROM_CMD,
 			       (1<<EPROM_CS_SHIFT) |
-			       read_nic_byte(dev, EPROM_CMD)); //enable EPROM
+			       read_nic_byte(priv, EPROM_CMD)); //enable EPROM
 	else
-		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
+		write_nic_byte(priv, EPROM_CMD, read_nic_byte(priv, EPROM_CMD)
 			       &~(1<<EPROM_CS_SHIFT)); //disable EPROM
 
 	udelay(EPROM_DELAY);
 }
 
 
-static void eprom_ck_cycle(struct net_device *dev)
+static void eprom_ck_cycle(struct r8192_priv *priv)
 {
-	write_nic_byte(dev, EPROM_CMD,
-		       (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
+	write_nic_byte(priv, EPROM_CMD,
+		       (1<<EPROM_CK_SHIFT) | read_nic_byte(priv, EPROM_CMD));
 	udelay(EPROM_DELAY);
-	write_nic_byte(dev, EPROM_CMD,
-		       read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
+	write_nic_byte(priv, EPROM_CMD,
+		       read_nic_byte(priv, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
 	udelay(EPROM_DELAY);
 }
 
 
-static void eprom_w(struct net_device *dev, short bit)
+static void eprom_w(struct r8192_priv *priv, short bit)
 {
 	if (bit)
-		write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) |
-			       read_nic_byte(dev, EPROM_CMD));
+		write_nic_byte(priv, EPROM_CMD, (1<<EPROM_W_SHIFT) |
+			       read_nic_byte(priv, EPROM_CMD));
 	else
-		write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
+		write_nic_byte(priv, EPROM_CMD, read_nic_byte(priv, EPROM_CMD)
 			       &~(1<<EPROM_W_SHIFT));
 
 	udelay(EPROM_DELAY);
 }
 
 
-static short eprom_r(struct net_device *dev)
+static short eprom_r(struct r8192_priv *priv)
 {
 	short bit;
 
-	bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
+	bit = (read_nic_byte(priv, EPROM_CMD) & (1<<EPROM_R_SHIFT));
 	udelay(EPROM_DELAY);
 
 	if (bit)
@@ -71,20 +71,19 @@ static short eprom_r(struct net_device *dev)
 }
 
 
-static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
+static void eprom_send_bits_string(struct r8192_priv *priv, short b[], int len)
 {
 	int i;
 
 	for (i = 0; i < len; i++) {
-		eprom_w(dev, b[i]);
-		eprom_ck_cycle(dev);
+		eprom_w(priv, b[i]);
+		eprom_ck_cycle(priv);
 	}
 }
 
 
-u32 eprom_read(struct net_device *dev, u32 addr)
+u32 eprom_read(struct r8192_priv *priv, u32 addr)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	short read_cmd[] = {1, 1, 0};
 	short addr_str[8];
 	int i;
@@ -93,7 +92,7 @@ u32 eprom_read(struct net_device *dev, u32 addr)
 
 	ret = 0;
         //enable EPROM programming
-	write_nic_byte(dev, EPROM_CMD,
+	write_nic_byte(priv, EPROM_CMD,
 		       (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
 	udelay(EPROM_DELAY);
 
@@ -116,27 +115,27 @@ u32 eprom_read(struct net_device *dev, u32 addr)
 		addr_str[0] = addr & (1<<5);
 		addr_len = 6;
 	}
-	eprom_cs(dev, 1);
-	eprom_ck_cycle(dev);
-	eprom_send_bits_string(dev, read_cmd, 3);
-	eprom_send_bits_string(dev, addr_str, addr_len);
+	eprom_cs(priv, 1);
+	eprom_ck_cycle(priv);
+	eprom_send_bits_string(priv, read_cmd, 3);
+	eprom_send_bits_string(priv, addr_str, addr_len);
 
 	//keep chip pin D to low state while reading.
 	//I'm unsure if it is necessary, but anyway shouldn't hurt
-	eprom_w(dev, 0);
+	eprom_w(priv, 0);
 
 	for (i = 0; i < 16; i++) {
 		//eeprom needs a clk cycle between writing opcode&adr
 		//and reading data. (eeprom outs a dummy 0)
-		eprom_ck_cycle(dev);
-		ret |= (eprom_r(dev)<<(15-i));
+		eprom_ck_cycle(priv);
+		ret |= (eprom_r(priv)<<(15-i));
 	}
 
-	eprom_cs(dev, 0);
-	eprom_ck_cycle(dev);
+	eprom_cs(priv, 0);
+	eprom_ck_cycle(priv);
 
 	//disable EPROM programming
-	write_nic_byte(dev, EPROM_CMD,
+	write_nic_byte(priv, EPROM_CMD,
 		       (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
 	return ret;
 }
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.h b/drivers/staging/rtl8192e/r8180_93cx6.h
index 4c3f675..55d2054 100644
--- a/drivers/staging/rtl8192e/r8180_93cx6.h
+++ b/drivers/staging/rtl8192e/r8180_93cx6.h
@@ -38,4 +38,4 @@
 #define EPROM_TXPW1 0x3d
 
 /* Reads a 16 bits word. */
-u32 eprom_read(struct net_device *dev, u32 addr);
+u32 eprom_read(struct r8192_priv *priv, u32 addr);
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.c b/drivers/staging/rtl8192e/r8190_rtl8256.c
index e2abfd7..286462c 100644
--- a/drivers/staging/rtl8192e/r8190_rtl8256.c
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.c
@@ -23,15 +23,14 @@
  * Return:      NONE
  * Note:	8226 support both 20M  and 40 MHz
  *---------------------------------------------------------------------------*/
-void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth)	//20M or 40M
+void PHY_SetRF8256Bandwidth(struct r8192_priv *priv, HT_CHANNEL_WIDTH Bandwidth)	//20M or 40M
 {
 	u8	eRFPath;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	//for(eRFPath = RF90_PATH_A; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
 	for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
 	{
-		if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+		if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
 				continue;
 
 		switch(Bandwidth)
@@ -39,9 +38,9 @@ void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth)
 			case HT_CHANNEL_WIDTH_20:
 				if(priv->card_8192_version == VERSION_8190_BD || priv->card_8192_version == VERSION_8190_BE)// 8256 D-cut, E-cut, xiong: consider it later!
 				{
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7);
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021);
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x100); //phy para:1ba
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3d7);
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x021);
 
 					//cosa add for sd3's request 01/23/2008
 					//rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
@@ -55,17 +54,10 @@ void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth)
 			case HT_CHANNEL_WIDTH_20_40:
 				if(priv->card_8192_version == VERSION_8190_BD ||priv->card_8192_version == VERSION_8190_BE)// 8256 D-cut, E-cut, xiong: consider it later!
 				{
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3ff);
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0e1);
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0b, bMask12Bits, 0x300); //phy para:3ba
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x2c, bMask12Bits, 0x3ff);
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, 0x0e, bMask12Bits, 0x0e1);
 
-					//cosa add for sd3's request 01/23/2008
-					#if 0
-					if(priv->chan == 3 || priv->chan == 9) //I need to set priv->chan whenever current channel changes
-						rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x59b);
-					else
-						rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x14, bMask12Bits, 0x5ab);
-					#endif
 				}
 				else
 				{
@@ -87,78 +79,75 @@ void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth)
  * Output:      NONE
  * Return:      NONE
  *---------------------------------------------------------------------------*/
-RT_STATUS PHY_RF8256_Config(struct net_device* dev)
+RT_STATUS PHY_RF8256_Config(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	// Initialize general global value
 	//
 	RT_STATUS rtStatus = RT_STATUS_SUCCESS;
 	// TODO: Extend RF_PATH_C and RF_PATH_D in the future
 	priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
 	// Config BB and RF
-	rtStatus = phy_RF8256_Config_ParaFile(dev);
+	rtStatus = phy_RF8256_Config_ParaFile(priv);
 
 	return rtStatus;
 }
+
 /*--------------------------------------------------------------------------
  * Overview:    Interface to config 8256
  * Input:       struct net_device*	dev
  * Output:      NONE
  * Return:      NONE
  *---------------------------------------------------------------------------*/
-RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev)
+RT_STATUS phy_RF8256_Config_ParaFile(struct r8192_priv *priv)
 {
 	u32 	u4RegValue = 0;
 	u8 	eRFPath;
 	RT_STATUS				rtStatus = RT_STATUS_SUCCESS;
 	BB_REGISTER_DEFINITION_T	*pPhyReg;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32	RegOffSetToBeCheck = 0x3;
 	u32 	RegValueToBeCheck = 0x7f1;
 	u32	RF3_Final_Value = 0;
 	u8	ConstRetryTimes = 5, RetryTimes = 5;
 	u8 ret = 0;
+
 	//3//-----------------------------------------------------------------
 	//3// <2> Initialize RF
 	//3//-----------------------------------------------------------------
 	for(eRFPath = (RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath <priv->NumTotalRFPath; eRFPath++)
 	{
-		if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+		if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
 				continue;
 
 		pPhyReg = &priv->PHYRegDef[eRFPath];
 
-		// Joseph test for shorten RF config
-	//	pHalData->RfReg0Value[eRFPath] =  rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rGlobalCtrl, bMaskDWord);
-
 		/*----Store original RFENV control type----*/
 		switch(eRFPath)
 		{
 		case RF90_PATH_A:
 		case RF90_PATH_C:
-			u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV);
+			u4RegValue = rtl8192_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV);
 			break;
 		case RF90_PATH_B :
 		case RF90_PATH_D:
-			u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16);
+			u4RegValue = rtl8192_QueryBBReg(priv, pPhyReg->rfintfs, bRFSI_RFENV<<16);
 			break;
 		}
 
 		/*----Set RF_ENV enable----*/
-		rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
+		rtl8192_setBBreg(priv, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
 
 		/*----Set RF_ENV output high----*/
-		rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+		rtl8192_setBBreg(priv, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
 
 		/* Set bit number of Address and Data for RF register */
-		rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); 	// Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258
-		rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0);	// Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ???
+		rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); 	// Set 0 to 4 bits for Z-serial and set 1 to 6 bits for 8258
+		rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0);	// Set 0 to 12 bits for Z-serial and 8258, and set 1 to 14 bits for ???
 
-		rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf);
+		rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E) eRFPath, 0x0, bMask12Bits, 0xbf);
 
 		/*----Check RF block (for FPGA platform only)----*/
 		// TODO: this function should be removed on ASIC , Emily 2007.2.2
-		rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath);
+		rtStatus = rtl8192_phy_checkBBAndRF(priv, HW90_BLOCK_RF, (RF90_RADIO_PATH_E)eRFPath);
 		if(rtStatus!= RT_STATUS_SUCCESS)
 		{
 			RT_TRACE(COMP_ERR, "PHY_RF8256_Config():Check Radio[%d] Fail!!\n", eRFPath);
@@ -173,8 +162,8 @@ RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev)
 		case RF90_PATH_A:
 			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
 			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
-				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
+				RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
@@ -182,8 +171,8 @@ RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev)
 		case RF90_PATH_B:
 			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
 			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
-				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
+				RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
@@ -191,8 +180,8 @@ RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev)
 		case RF90_PATH_C:
 			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
 			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
-				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
+				RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
@@ -200,8 +189,8 @@ RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev)
 		case RF90_PATH_D:
 			while(RF3_Final_Value!=RegValueToBeCheck && RetryTimes!=0)
 			{
-				ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath);
-				RF3_Final_Value = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
+				ret = rtl8192_phy_ConfigRFWithHeaderFile(priv,(RF90_RADIO_PATH_E)eRFPath);
+				RF3_Final_Value = rtl8192_phy_QueryRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, RegOffSetToBeCheck, bMask12Bits);
 				RT_TRACE(COMP_RF, "RF %d %d register final value: %x\n", eRFPath, RegOffSetToBeCheck, RF3_Final_Value);
 				RetryTimes--;
 			}
@@ -213,11 +202,11 @@ RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev)
 		{
 		case RF90_PATH_A:
 		case RF90_PATH_C:
-			rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
+			rtl8192_setBBreg(priv, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue);
 			break;
 		case RF90_PATH_B :
 		case RF90_PATH_D:
-			rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
+			rtl8192_setBBreg(priv, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue);
 			break;
 		}
 
@@ -237,45 +226,9 @@ phy_RF8256_Config_ParaFile_Fail:
 }
 
 
-void PHY_SetRF8256CCKTxPower(struct net_device*	dev, u8	powerlevel)
+void PHY_SetRF8256CCKTxPower(struct r8192_priv *priv, u8 powerlevel)
 {
 	u32	TxAGC=0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
-	u8				byte0, byte1;
-
-	TxAGC |= ((powerlevel<<8)|powerlevel);
-	TxAGC += priv->CCKTxPowerLevelOriginalOffset;
-
-	if(priv->bDynamicTxLowPower == true  //cosa 04282008 for cck long range
-		/*pMgntInfo->bScanInProgress == TRUE*/ ) //cosa 05/22/2008 for scan
-	{
-		if(priv->CustomerID == RT_CID_819x_Netcore)
-			TxAGC = 0x2222;
-		else
-		TxAGC += ((priv->CckPwEnl<<8)|priv->CckPwEnl);
-	}
-
-	byte0 = (u8)(TxAGC & 0xff);
-	byte1 = (u8)((TxAGC & 0xff00)>>8);
-	if(byte0 > 0x24)
-		byte0 = 0x24;
-	if(byte1 > 0x24)
-		byte1 = 0x24;
-	if(priv->rf_type == RF_2T4R)	//Only 2T4R you have to care the Antenna Tx Power offset
-	{	// check antenna C over the max index 0x24
-			if(priv->RF_C_TxPwDiff > 0)
-			{
-				if( (byte0 + (u8)priv->RF_C_TxPwDiff) > 0x24)
-					byte0 = 0x24 - priv->RF_C_TxPwDiff;
-				if( (byte1 + (u8)priv->RF_C_TxPwDiff) > 0x24)
-					byte1 = 0x24 - priv->RF_C_TxPwDiff;
-			}
-		}
-	TxAGC = (byte1<<8) |byte0;
-	write_nic_dword(dev, CCK_TXAGC, TxAGC);
-#else
-	#ifdef RTL8192E
 
 	TxAGC = powerlevel;
 	if(priv->bDynamicTxLowPower == true)//cosa 04282008 for cck long range
@@ -287,87 +240,13 @@ void PHY_SetRF8256CCKTxPower(struct net_device*	dev, u8	powerlevel)
 	}
 	if(TxAGC > 0x24)
 		TxAGC = 0x24;
-	rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
-	#endif
-#endif
+	rtl8192_setBBreg(priv, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
 }
 
 
-void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel)
+void PHY_SetRF8256OFDMTxPower(struct r8192_priv *priv, u8 powerlevel)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	//Joseph TxPower for 8192 testing
-#ifdef RTL8190P
-	u32				TxAGC1=0, TxAGC2=0, TxAGC2_tmp = 0;
-	u8				i, byteVal1[4], byteVal2[4], byteVal3[4];
-
-	if(priv->bDynamicTxHighPower == true)     //Add by Jacken 2008/03/06
-	{
-		TxAGC1 |= ((powerlevel<<24)|(powerlevel<<16)|(powerlevel<<8)|powerlevel);
-		//for tx power track
-		TxAGC2_tmp = TxAGC1;
-
-		TxAGC1 += priv->MCSTxPowerLevelOriginalOffset[0];
-		TxAGC2 =0x03030303;
-
-		//for tx power track
-		TxAGC2_tmp += priv->MCSTxPowerLevelOriginalOffset[1];
-	}
-	else
-	{
-		TxAGC1 |= ((powerlevel<<24)|(powerlevel<<16)|(powerlevel<<8)|powerlevel);
-		TxAGC2 = TxAGC1;
-
-		TxAGC1 += priv->MCSTxPowerLevelOriginalOffset[0];
-		TxAGC2 += priv->MCSTxPowerLevelOriginalOffset[1];
 
-		TxAGC2_tmp = TxAGC2;
-
-	}
-	for(i=0; i<4; i++)
-	{
-		byteVal1[i] = (u8)(  (TxAGC1 & (0xff<<(i*8))) >>(i*8) );
-		if(byteVal1[i] > 0x24)
-			byteVal1[i] = 0x24;
-		byteVal2[i] = (u8)(  (TxAGC2 & (0xff<<(i*8))) >>(i*8) );
-		if(byteVal2[i] > 0x24)
-			byteVal2[i] = 0x24;
-
-		//for tx power track
-		byteVal3[i] = (u8)(  (TxAGC2_tmp & (0xff<<(i*8))) >>(i*8) );
-		if(byteVal3[i] > 0x24)
-			byteVal3[i] = 0x24;
-	}
-
-	if(priv->rf_type == RF_2T4R)	//Only 2T4R you have to care the Antenna Tx Power offset
-	{	// check antenna C over the max index 0x24
-		if(priv->RF_C_TxPwDiff > 0)
-		{
-			for(i=0; i<4; i++)
-			{
-				if( (byteVal1[i] + (u8)priv->RF_C_TxPwDiff) > 0x24)
-					byteVal1[i] = 0x24 - priv->RF_C_TxPwDiff;
-				if( (byteVal2[i] + (u8)priv->RF_C_TxPwDiff) > 0x24)
-					byteVal2[i] = 0x24 - priv->RF_C_TxPwDiff;
-				if( (byteVal3[i] + (u8)priv->RF_C_TxPwDiff) > 0x24)
-					byteVal3[i] = 0x24 - priv->RF_C_TxPwDiff;
-			}
-		}
-	}
-
-	TxAGC1 = (byteVal1[3]<<24) | (byteVal1[2]<<16) |(byteVal1[1]<<8) |byteVal1[0];
-	TxAGC2 = (byteVal2[3]<<24) | (byteVal2[2]<<16) |(byteVal2[1]<<8) |byteVal2[0];
-
-	//for tx power track
-	TxAGC2_tmp = (byteVal3[3]<<24) | (byteVal3[2]<<16) |(byteVal3[1]<<8) |byteVal3[0];
-	priv->Pwr_Track = TxAGC2_tmp;
-	//DbgPrint("TxAGC2_tmp = 0x%x\n", TxAGC2_tmp);
-
-	//DbgPrint("TxAGC1/TxAGC2 = 0x%x/0x%x\n", TxAGC1, TxAGC2);
-	write_nic_dword(dev, MCS_TXAGC, TxAGC1);
-	write_nic_dword(dev, MCS_TXAGC+4, TxAGC2);
-#else
-#ifdef RTL8192E
 	u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
 	u8 index = 0;
 	u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
@@ -408,386 +287,163 @@ void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel)
 		{
 			writeVal = (byte3<<24) | (byte2<<16) |(byte1<<8) |byte0;
 		}
-		rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+		rtl8192_setBBreg(priv, RegOffset[index], 0x7f7f7f7f, writeVal);
 	}
-
-#endif
-#endif
 }
 
 #define MAX_DOZE_WAITING_TIMES_9x 64
-static bool
-SetRFPowerState8190(
-	struct net_device* dev,
-	RT_RF_POWER_STATE	eRFPowerState
-	)
+static void r8192e_drain_tx_queues(struct r8192_priv *priv)
+{
+	u8 i, QueueID;
+
+	for (QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
+	{
+		struct rtl8192_tx_ring *ring = &priv->tx_ring[QueueID];
+
+		if(skb_queue_len(&ring->queue) == 0)
+		{
+			QueueID++;
+			continue;
+		}
+
+		udelay(10);
+		i++;
+
+		if (i >= MAX_DOZE_WAITING_TIMES_9x)
+		{
+			RT_TRACE(COMP_POWER, "r8192e_drain_tx_queues() timeout queue %d\n", QueueID);
+			break;
+		}
+	}
+}
+
+static bool SetRFPowerState8190(struct r8192_priv *priv,
+				RT_RF_POWER_STATE eRFPowerState)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 	bool bResult = true;
-	//u8 eRFPath;
-	u8	i = 0, QueueID = 0;
-	//ptx_ring	head=NULL,tail=NULL;
-	struct rtl8192_tx_ring  *ring = NULL;
 
-	if(priv->SetRFPowerStateInProgress == true)
-		return false;
-	//RT_TRACE(COMP_PS, "===========> SetRFPowerState8190()!\n");
-	priv->SetRFPowerStateInProgress = true;
+	if (eRFPowerState == priv->eRFPowerState &&
+	    priv->bHwRfOffAction == 0) {
+		bResult = false;
+		goto out;
+	}
 
-	switch(priv->rf_chip)
+	switch( eRFPowerState )
 	{
-		case RF_8256:
-		switch( eRFPowerState )
+	case eRfOn:
+
+		// turn on RF
+		if ((priv->eRFPowerState == eRfOff) &&
+		    RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
 		{
-			case eRfOn:
-				//RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOn !\n");
-						//RXTX enable control: On
-					//for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
-					//	PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
-#ifdef RTL8190P
-				if(priv->rf_type == RF_2T4R)
-				{
-					//enable RF-Chip A/B
-					rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1); // 0x860[4]
-					//enable RF-Chip C/D
-					rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x1); // 0x868[4]
-					//analog to digital on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf);// 0x88c[11:8]
-					//digital to analog on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e0, 0xf); // 0x880[8:5]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0xf);// 0xc04[3:0]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0xf);// 0xd04[3:0]
-					//analog to digital part2 on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e00, 0xf); // 0x880[12:9]
-				}
-				else if(priv->rf_type == RF_1T2R)	//RF-C, RF-D
-				{
-					//enable RF-Chip C/D
-					rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x1); // 0x868[4]
-					//analog to digital on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xc00, 0x3);// 0x88c[11:10]
-					//digital to analog on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x180, 0x3); // 0x880[8:7]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xc, 0x3);// 0xc04[3:2]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xc, 0x3);// 0xd04[3:2]
-					//analog to digital part2 on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1800, 0x3); // 0x880[12:11]
-				}
-				else if(priv->rf_type == RF_1T1R)	//RF-C
-				{
-					//enable RF-Chip C/D
-					rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x1); // 0x868[4]
-					//analog to digital on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x400, 0x1);// 0x88c[10]
-					//digital to analog on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x80, 0x1); // 0x880[7]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x4, 0x1);// 0xc04[2]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x4, 0x1);// 0xd04[2]
-					//analog to digital part2 on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x800, 0x1); // 0x880[11]
-				}
+			/*
+			 * The current RF state is OFF and the RF OFF level
+			 * is halting the NIC, re-initialize the NIC.
+			 */
+			if (!NicIFEnableNIC(priv)) {
+				RT_TRACE(COMP_ERR, "%s(): NicIFEnableNIC failed\n",__FUNCTION__);
+				bResult = false;
+				goto out;
+			}
 
-#elif defined RTL8192E
-				// turn on RF
-				if((priv->ieee80211->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
-				{ // The current RF state is OFF and the RF OFF level is halting the NIC, re-initialize the NIC.
-					bool rtstatus = true;
-					u32 InitializeCount = 3;
-					do
-					{
-						InitializeCount--;
-						priv->RegRfOff = false;
-						rtstatus = NicIFEnableNIC(dev);
-					}while( (rtstatus != true) &&(InitializeCount >0) );
-
-					if(rtstatus != true)
-					{
-						RT_TRACE(COMP_ERR,"%s():Initialize Adapter fail,return\n",__FUNCTION__);
-						priv->SetRFPowerStateInProgress = false;
-						return false;
-					}
-
-					RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
-				} else {
-					write_nic_byte(dev, ANAPAR, 0x37);//160MHz
-					//write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
-					mdelay(1);
-					//enable clock 80/88 MHz
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
-					priv->bHwRfOffAction = 0;
-					//}
-
-					//RF-A, RF-B
-					//enable RF-Chip A/B
-					rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);		// 0x860[4]
-					//analog to digital on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
-					//digital to analog on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
-					//rx antenna on
-					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
-					//analog to digital part2 on
-					rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3); 	// 0x880[6:5]
-
-					// Baseband reset 2008.09.30 add
-					//write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
-
-				//2 	AFE
-					// 2008.09.30 add
-					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
-					//analog to digital part2 on
-					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3);		// 0x880[6:5]
-
-
-					//digital to analog on
-					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
-					//analog to digital on
-					//rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
-					//rx antenna on
-					//PHY_SetBBReg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
-					//rx antenna on 2008.09.30 mark
-					//PHY_SetBBReg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
-
-				//2 	RF
-					//enable RF-Chip A/B
-					//rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);		// 0x860[4]
-					//rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1);		// 0x864[4]
+			RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			write_nic_byte(priv, ANAPAR, 0x37);//160MHz
+			mdelay(1);
+			//enable clock 80/88 MHz
+			rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
+			priv->bHwRfOffAction = 0;
+
+			//RF-A, RF-B
+			//enable RF-Chip A/B
+			rtl8192_setBBreg(priv, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1);		// 0x860[4]
+			//analog to digital on
+			rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
+			//digital to analog on
+			rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
+			//rx antenna on
+			rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+			//rx antenna on
+			rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+			//analog to digital part2 on
+			rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x60, 0x3); 	// 0x880[6:5]
 
-				}
+		}
 
-				#endif
-						break;
+		break;
 
-				//
-				// In current solution, RFSleep=RFOff in order to save power under 802.11 power save.
-				// By Bruce, 2008-01-16.
-				//
-			case eRfSleep:
-			{
-				// HW setting had been configured with deeper mode.
-				if(priv->ieee80211->eRFPowerState == eRfOff)
-					break;
+	//
+	// In current solution, RFSleep=RFOff in order to save power under 802.11 power save.
+	// By Bruce, 2008-01-16.
+	//
+	case eRfSleep:
 
-				// Update current RF state variable.
-				//priv->ieee80211->eRFPowerState = eRFPowerState;
+		// HW setting had been configured with deeper mode.
+		if(priv->eRFPowerState == eRfOff)
+			break;
 
-				//if (pPSC->bLeisurePs)
-				{
-					for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
-					{
-							ring = &priv->tx_ring[QueueID];
-
-							if(skb_queue_len(&ring->queue) == 0)
-							{
-								QueueID++;
-								continue;
-							}
-							else
-							{
-								RT_TRACE((COMP_POWER|COMP_RF), "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
-								udelay(10);
-								i++;
-							}
-
-							if(i >= MAX_DOZE_WAITING_TIMES_9x)
-							{
-								RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
-								break;
-							}
-						}
-				}
+		r8192e_drain_tx_queues(priv);
 
-				//if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
-#ifdef RTL8190P
-				{
-					PHY_SetRtl8190pRfOff(dev);
-				}
-				//else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
-#elif defined RTL8192E
-				{
-					PHY_SetRtl8192eRfOff(dev);
-				}
-#endif
-			}
-								break;
+		PHY_SetRtl8192eRfOff(priv);
 
-			case eRfOff:
-				//RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOff/Sleep !\n");
+		break;
 
-				// Update current RF state variable.
-				//priv->ieee80211->eRFPowerState = eRFPowerState;
+	case eRfOff:
 
-				//
-				// Disconnect with Any AP or STA.
-				//
-				for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
-				{
-					ring = &priv->tx_ring[QueueID];
-
-					if(skb_queue_len(&ring->queue) == 0)
-						{
-							QueueID++;
-							continue;
-						}
-						else
-						{
-							RT_TRACE(COMP_POWER,
-							"eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
-							udelay(10);
-							i++;
-						}
-
-						if(i >= MAX_DOZE_WAITING_TIMES_9x)
-						{
-							RT_TRACE(COMP_POWER, "\n\n\n SetZebraRFPowerState8185B(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
-							break;
-						}
-					}
-
-				//if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
-#if defined RTL8190P
-				{
-					PHY_SetRtl8190pRfOff(dev);
-				}
-				//else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
-#elif defined RTL8192E
-				{
-					//if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC) && priv->ieee80211->RfOffReason > RF_CHANGE_BY_PS)
-					if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
-					{ // Disable all components.
-						//
-						// Note:
-						//	NicIFSetLinkStatus is a big problem when we indicate the status to OS,
-						//	the OS(XP) will reset. But now, we cnnot find why the NIC is hard to receive
-						//	packets after RF ON. Just keep this function here and still work to find out the root couse.
-						//	By Bruce, 2009-05-01.
-						//
-						//NicIFSetLinkStatus( Adapter, RT_MEDIA_DISCONNECT );
-						//if HW radio of , need to indicate scan complete first for not be reset.
-						//if(MgntScanInProgress(pMgntInfo))
-						//	MgntResetScanProcess( Adapter );
-
-						// <1> Disable Interrupt
-						//rtl8192_irq_disable(dev);
-						// <2> Stop all timer
-						//MgntCancelAllTimer(Adapter);
-						// <3> Disable Adapter
-						//NicIFHaltAdapter(Adapter, false);
-						NicIFDisableNIC(dev);
-						RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
-					}
-					else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
-					{ // Normal case.
-				  		// IPS should go to this.
-						PHY_SetRtl8192eRfOff(dev);
-					}
-				}
-#else
-				else
-				{
-					RT_TRACE(COMP_DBG,DBG_TRACE,("It is not 8190Pci and 8192PciE \n"));
-				}
-				#endif
+		//
+		// Disconnect with Any AP or STA.
+		//
+		r8192e_drain_tx_queues(priv);
 
-					break;
 
-			default:
-					bResult = false;
-					RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
-					break;
+		if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+		{
+			/* Disable all components. */
+			NicIFDisableNIC(priv);
+			RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+		}
+		else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
+		{
+			/* Normal case - IPS should go to this. */
+			PHY_SetRtl8192eRfOff(priv);
 		}
-
 		break;
 
-		default:
-			RT_TRACE(COMP_ERR, "SetRFPowerState8190(): Unknown RF type\n");
-			break;
+	default:
+		bResult = false;
+		RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
+		break;
 	}
 
 	if(bResult)
 	{
 		// Update current RF state variable.
-		priv->ieee80211->eRFPowerState = eRFPowerState;
+		priv->eRFPowerState = eRFPowerState;
 	}
 
-	//printk("%s()priv->ieee80211->eRFPowerState:%s\n" ,__func__,priv->ieee80211->eRFPowerState == eRfOn ? "On" : "Off");
-	priv->SetRFPowerStateInProgress = false;
-	//RT_TRACE(COMP_PS, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
+out:
 	return bResult;
 }
 
 
 
-//
-//	Description:
-//		Change RF power state.
-//
-//	Assumption:
-//		This function must be executed in re-schdulable context,
-//		ie. PASSIVE_LEVEL.
-//
-//	050823, by rcnjko.
-//
-static bool
-SetRFPowerState(
-	struct net_device* dev,
-	RT_RF_POWER_STATE	eRFPowerState
-	)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
-	bool bResult = false;
-
-	RT_TRACE(COMP_RF,"---------> SetRFPowerState(): eRFPowerState(%d)\n", eRFPowerState);
-#ifdef RTL8192E
-	if(eRFPowerState == priv->ieee80211->eRFPowerState && priv->bHwRfOffAction == 0)
-#else
-	if(eRFPowerState == priv->ieee80211->eRFPowerState)
-#endif
-	{
-		RT_TRACE(COMP_POWER, "<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n", eRFPowerState);
-		return bResult;
-	}
-
-	bResult = SetRFPowerState8190(dev, eRFPowerState);
-
-	RT_TRACE(COMP_POWER, "<--------- SetRFPowerState(): bResult(%d)\n", bResult);
 
-	return bResult;
-}
 
-static void
-MgntDisconnectIBSS(
-	struct net_device* dev
-)
+static void MgntDisconnectIBSS(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	//RT_OP_MODE	OpMode;
 	u8			i;
 	bool	bFilterOutNonAssociatedBSSID = false;
 
-	//IEEE80211_DEBUG(IEEE80211_DL_TRACE, "XXXXXXXXXX MgntDisconnect IBSS\n");
-
 	priv->ieee80211->state = IEEE80211_NOLINK;
 
-//	PlatformZeroMemory( pMgntInfo->Bssid, 6 );
 	for(i=0;i<6;i++)  priv->ieee80211->current_network.bssid[i]= 0x55;
 	priv->OpMode = RT_OP_MODE_NO_LINK;
-	write_nic_word(dev, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
-	write_nic_dword(dev, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
+	write_nic_word(priv, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
+	write_nic_dword(priv, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
 	{
 			RT_OP_MODE	OpMode = priv->OpMode;
-			//LED_CTL_MODE	LedAction = LED_CTL_NO_LINK;
-			u8	btMsr = read_nic_byte(dev, MSR);
+			u8	btMsr = read_nic_byte(priv, MSR);
 
 			btMsr &= 0xfc;
 
@@ -795,7 +451,6 @@ MgntDisconnectIBSS(
 			{
 			case RT_OP_MODE_INFRASTRUCTURE:
 				btMsr |= MSR_LINK_MANAGED;
-				//LedAction = LED_CTL_LINK;
 				break;
 
 			case RT_OP_MODE_IBSS:
@@ -805,7 +460,6 @@ MgntDisconnectIBSS(
 
 			case RT_OP_MODE_AP:
 				btMsr |= MSR_LINK_MASTER;
-				//LedAction = LED_CTL_LINK;
 				break;
 
 			default:
@@ -813,10 +467,7 @@ MgntDisconnectIBSS(
 				break;
 			}
 
-			write_nic_byte(dev, MSR, btMsr);
-
-			// LED control
-			//Adapter->HalFunc.LedControlHandler(Adapter, LedAction);
+			write_nic_byte(priv, MSR, btMsr);
 	}
 	ieee80211_stop_send_beacons(priv->ieee80211);
 
@@ -825,7 +476,7 @@ MgntDisconnectIBSS(
 	{
 			u32 RegRCR, Type;
 			Type = bFilterOutNonAssociatedBSSID;
-			RegRCR = read_nic_dword(dev,RCR);
+			RegRCR = read_nic_dword(priv, RCR);
 			priv->ReceiveConfig = RegRCR;
 			if (Type == true)
 				RegRCR |= (RCR_CBSSID);
@@ -833,24 +484,18 @@ MgntDisconnectIBSS(
 				RegRCR &= (~RCR_CBSSID);
 
 			{
-				write_nic_dword(dev, RCR,RegRCR);
+				write_nic_dword(priv, RCR, RegRCR);
 				priv->ReceiveConfig = RegRCR;
 			}
 
 		}
-	//MgntIndicateMediaStatus( Adapter, RT_MEDIA_DISCONNECT, GENERAL_INDICATE );
 	notify_wx_assoc_event(priv->ieee80211);
 
 }
 
-static void
-MlmeDisassociateRequest(
-	struct net_device* dev,
-	u8* 		asSta,
-	u8			asRsn
-	)
+static void MlmeDisassociateRequest(struct r8192_priv *priv, u8 *asSta,
+				    u8 asRsn)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 i;
 
 	RemovePeerTS(priv->ieee80211, asSta);
@@ -862,15 +507,11 @@ MlmeDisassociateRequest(
 		//ShuChen TODO: change media status.
 		//ShuChen TODO: What to do when disassociate.
 		priv->ieee80211->state = IEEE80211_NOLINK;
-		//pMgntInfo->AsocTimestamp = 0;
 		for(i=0;i<6;i++)  priv->ieee80211->current_network.bssid[i] = 0x22;
-//		pMgntInfo->mBrates.Length = 0;
-//		Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_BASIC_RATE, (pu1Byte)(&pMgntInfo->mBrates) );
 		priv->OpMode = RT_OP_MODE_NO_LINK;
 		{
 			RT_OP_MODE	OpMode = priv->OpMode;
-			//LED_CTL_MODE	LedAction = LED_CTL_NO_LINK;
-			u8 btMsr = read_nic_byte(dev, MSR);
+			u8 btMsr = read_nic_byte(priv, MSR);
 
 			btMsr &= 0xfc;
 
@@ -878,7 +519,6 @@ MlmeDisassociateRequest(
 			{
 			case RT_OP_MODE_INFRASTRUCTURE:
 				btMsr |= MSR_LINK_MANAGED;
-				//LedAction = LED_CTL_LINK;
 				break;
 
 			case RT_OP_MODE_IBSS:
@@ -888,7 +528,6 @@ MlmeDisassociateRequest(
 
 			case RT_OP_MODE_AP:
 				btMsr |= MSR_LINK_MASTER;
-				//LedAction = LED_CTL_LINK;
 				break;
 
 			default:
@@ -896,116 +535,52 @@ MlmeDisassociateRequest(
 				break;
 			}
 
-			write_nic_byte(dev, MSR, btMsr);
-
-			// LED control
-			//Adapter->HalFunc.LedControlHandler(Adapter, LedAction);
+			write_nic_byte(priv, MSR, btMsr);
 		}
 		ieee80211_disassociate(priv->ieee80211);
 
-		write_nic_word(dev, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
-		write_nic_dword(dev, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
+		write_nic_word(priv, BSSIDR, ((u16*)priv->ieee80211->current_network.bssid)[0]);
+		write_nic_dword(priv, BSSIDR+2, ((u32*)(priv->ieee80211->current_network.bssid+2))[0]);
 
 	}
 
 }
 
 
-static void
-MgntDisconnectAP(
-	struct net_device* dev,
-	u8 asRsn
-)
+static void MgntDisconnectAP(struct r8192_priv *priv, u8 asRsn)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	bool bFilterOutNonAssociatedBSSID = false;
+	u32 RegRCR, Type;
 
-//
-// Commented out by rcnjko, 2005.01.27:
-// I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
-//
-//	//2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
-//	SecClearAllKeys(Adapter);
-
-	// In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
-#ifdef TO_DO
-	if(   pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch ||
-		(pMgntInfo->bAPSuportCCKM && pMgntInfo->bCCX8021xenable) )	// In CCKM mode will Clear key
-	{
-		SecClearAllKeys(Adapter);
-		RT_TRACE(COMP_SEC, DBG_LOUD,("======>CCKM clear key..."))
-	}
-#endif
-	// If disconnect, clear RCR CBSSID bit
+	/* If disconnect, clear RCR CBSSID bit */
 	bFilterOutNonAssociatedBSSID = false;
-	{
-			u32 RegRCR, Type;
 
-			Type = bFilterOutNonAssociatedBSSID;
-			//Adapter->HalFunc.GetHwRegHandler(Adapter, HW_VAR_RCR, (pu1Byte)(&RegRCR));
-			RegRCR = read_nic_dword(dev,RCR);
-			priv->ReceiveConfig = RegRCR;
+	Type = bFilterOutNonAssociatedBSSID;
+	RegRCR = read_nic_dword(priv, RCR);
+	priv->ReceiveConfig = RegRCR;
 
-			if (Type == true)
-				RegRCR |= (RCR_CBSSID);
-			else if (Type == false)
-				RegRCR &= (~RCR_CBSSID);
-
-			write_nic_dword(dev, RCR,RegRCR);
-			priv->ReceiveConfig = RegRCR;
+	if (Type == true)
+		RegRCR |= (RCR_CBSSID);
+	else if (Type == false)
+		RegRCR &= (~RCR_CBSSID);
 
+	write_nic_dword(priv, RCR, RegRCR);
+	priv->ReceiveConfig = RegRCR;
 
-	}
-	// 2004.10.11, by rcnjko.
-	//MlmeDisassociateRequest( Adapter, pMgntInfo->Bssid, disas_lv_ss );
-	MlmeDisassociateRequest( dev, priv->ieee80211->current_network.bssid, asRsn );
+	MlmeDisassociateRequest(priv, priv->ieee80211->current_network.bssid, asRsn);
 
 	priv->ieee80211->state = IEEE80211_NOLINK;
-	//pMgntInfo->AsocTimestamp = 0;
 }
 
 
-static bool
-MgntDisconnect(
-	struct net_device* dev,
-	u8 asRsn
-)
+static bool MgntDisconnect(struct r8192_priv *priv, u8 asRsn)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
-	//
-	// Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
-	//
-#ifdef TO_DO
-	if(pMgntInfo->mPss != eAwake)
-	{
-		//
-		// Using AwkaeTimer to prevent mismatch ps state.
-		// In the timer the state will be changed according to the RF is being awoke or not. By Bruce, 2007-10-31.
-		//
-		// PlatformScheduleWorkItem( &(pMgntInfo->AwakeWorkItem) );
-		PlatformSetTimer( Adapter, &(pMgntInfo->AwakeTimer), 0 );
-	}
-#endif
-	// Follow 8180 AP mode, 2005.05.30, by rcnjko.
-#ifdef TO_DO
-	if(pMgntInfo->mActingAsAp)
-	{
-		RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> AP_DisassociateAllStation\n"));
-		AP_DisassociateAllStation(Adapter, unspec_reason);
-		return TRUE;
-	}
-#endif
-	// Indication of disassociation event.
-	//DrvIFIndicateDisassociation(Adapter, asRsn);
-
 	// In adhoc mode, update beacon frame.
 	if( priv->ieee80211->state == IEEE80211_LINKED )
 	{
 		if( priv->ieee80211->iw_mode == IW_MODE_ADHOC )
 		{
-			//RT_TRACE(COMP_MLME, "MgntDisconnect() ===> MgntDisconnectIBSS\n");
-			MgntDisconnectIBSS(dev);
+			MgntDisconnectIBSS(priv);
 		}
 		if( priv->ieee80211->iw_mode == IW_MODE_INFRA )
 		{
@@ -1014,12 +589,8 @@ MgntDisconnect(
 			// e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
 			// used to handle disassociation related things to AP, e.g. send Disassoc
 			// frame to AP.  2005.01.27, by rcnjko.
-			//IEEE80211_DEBUG(IEEE80211_DL_TRACE,"MgntDisconnect() ===> MgntDisconnectAP\n");
-			MgntDisconnectAP(dev, asRsn);
+			MgntDisconnectAP(priv, asRsn);
 		}
-
-		// Inidicate Disconnect, 2005.02.23, by rcnjko.
-		//MgntIndicateMediaStatus( Adapter, RT_MEDIA_DISCONNECT, GENERAL_INDICATE);
 	}
 
 	return true;
@@ -1033,73 +604,27 @@ MgntDisconnect(
 //	Assumption:
 //		PASSIVE LEVEL.
 //
-bool
-MgntActSet_RF_State(
-	struct net_device* dev,
-	RT_RF_POWER_STATE	StateToSet,
-	RT_RF_CHANGE_SOURCE ChangeSource
-	)
+bool MgntActSet_RF_State(struct r8192_priv *priv, RT_RF_POWER_STATE StateToSet,
+			 RT_RF_CHANGE_SOURCE ChangeSource)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	bool 			bActionAllowed = false;
 	bool 			bConnectBySSID = false;
 	RT_RF_POWER_STATE	rtState;
-	u16					RFWaitCounter = 0;
-	unsigned long flag;
-	RT_TRACE(COMP_POWER, "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet);
-
-	//1//
-	//1//<1>Prevent the race condition of RF state change.
-	//1//
-	// Only one thread can change the RF state at one time, and others should wait to be executed. By Bruce, 2007-11-28.
 
-	while(true)
-	{
-		spin_lock_irqsave(&priv->rf_ps_lock,flag);
-		if(priv->RFChangeInProgress)
-		{
-			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
-			RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet);
-
-			// Set RF after the previous action is done.
-			while(priv->RFChangeInProgress)
-			{
-				RFWaitCounter ++;
-				RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", RFWaitCounter);
-				udelay(1000); // 1 ms
+	RT_TRACE(COMP_POWER, "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet);
 
-				// Wait too long, return FALSE to avoid to be stuck here.
-				if(RFWaitCounter > 100)
-				{
-					RT_TRACE(COMP_ERR, "MgntActSet_RF_State(): Wait too logn to set RF\n");
-					// TODO: Reset RF state?
-					return false;
-				}
-			}
-		}
-		else
-		{
-			priv->RFChangeInProgress = true;
-			spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
-			break;
-		}
-	}
+	spin_lock(&priv->rf_ps_lock);
 
-	rtState = priv->ieee80211->eRFPowerState;
+	rtState = priv->eRFPowerState;
 
 	switch(StateToSet)
 	{
 	case eRfOn:
-		//
-		// Turn On RF no matter the IPS setting because we need to update the RF state to Ndis under Vista, or
-		// the Windows does not allow the driver to perform site survey any more. By Bruce, 2007-10-02.
-		//
-
-		priv->ieee80211->RfOffReason &= (~ChangeSource);
+		priv->RfOffReason &= (~ChangeSource);
 
-		if(! priv->ieee80211->RfOffReason)
+		if (!priv->RfOffReason)
 		{
-			priv->ieee80211->RfOffReason = 0;
+			priv->RfOffReason = 0;
 			bActionAllowed = true;
 
 
@@ -1109,70 +634,41 @@ MgntActSet_RF_State(
 			}
 		}
 		else
-			RT_TRACE(COMP_POWER, "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->ieee80211->RfOffReason, ChangeSource);
+			RT_TRACE(COMP_POWER, "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->RfOffReason, ChangeSource);
 
 		break;
 
 	case eRfOff:
 
-			if (priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
-			{
-				//
-				// 060808, Annie:
-				// Disconnect to current BSS when radio off. Asked by QuanTa.
-				//
-				// Set all link status falg, by Bruce, 2007-06-26.
-				//MgntActSet_802_11_DISASSOCIATE( Adapter, disas_lv_ss );
-				MgntDisconnect(dev, disas_lv_ss);
-
-				// Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI.
-				// 2007.05.28, by shien chang.
-
-			}
-
+		if (priv->RfOffReason > RF_CHANGE_BY_IPS)
+		{
+			// Disconnect to current BSS when radio off. Asked by QuanTa.
+			MgntDisconnect(priv, disas_lv_ss);
+		}
 
-		priv->ieee80211->RfOffReason |= ChangeSource;
+		priv->RfOffReason |= ChangeSource;
 		bActionAllowed = true;
 		break;
 
 	case eRfSleep:
-		priv->ieee80211->RfOffReason |= ChangeSource;
+		priv->RfOffReason |= ChangeSource;
 		bActionAllowed = true;
 		break;
-
-	default:
-		break;
 	}
 
-	if(bActionAllowed)
+	if (bActionAllowed)
 	{
-		RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->ieee80211->RfOffReason);
-				// Config HW to the specified mode.
-		SetRFPowerState(dev, StateToSet);
-		// Turn on RF.
-		if(StateToSet == eRfOn)
-		{
-			//Adapter->HalFunc.HalEnableRxHandler(Adapter);
-			if(bConnectBySSID)
-			{
-				//MgntActSet_802_11_SSID(Adapter, Adapter->MgntInfo.Ssid.Octet, Adapter->MgntInfo.Ssid.Length, TRUE );
-			}
-		}
-		// Turn off RF.
-		else if(StateToSet == eRfOff)
-		{
-			//Adapter->HalFunc.HalDisableRxHandler(Adapter);
-		}
+		RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->RfOffReason);
+		// Config HW to the specified mode.
+		SetRFPowerState8190(priv, StateToSet);
 	}
 	else
 	{
-		RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->ieee80211->RfOffReason);
+		RT_TRACE(COMP_POWER, "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->RfOffReason);
 	}
 
 	// Release RF spinlock
-	spin_lock_irqsave(&priv->rf_ps_lock,flag);
-	priv->RFChangeInProgress = false;
-	spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
+	spin_unlock(&priv->rf_ps_lock);
 
 	RT_TRACE(COMP_POWER, "<===MgntActSet_RF_State()\n");
 	return bActionAllowed;
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.h b/drivers/staging/rtl8192e/r8190_rtl8256.h
index a50b140..58f9290 100644
--- a/drivers/staging/rtl8192e/r8190_rtl8256.h
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.h
@@ -10,24 +10,20 @@
 #ifndef RTL8225_H
 #define RTL8225_H
 
-#ifdef RTL8190P
-#define RTL819X_TOTAL_RF_PATH 4
-#else
 #define RTL819X_TOTAL_RF_PATH 2 /* for 8192E */
-#endif
 
-void PHY_SetRF8256Bandwidth(struct net_device *dev,
+void PHY_SetRF8256Bandwidth(struct r8192_priv *priv,
 				   HT_CHANNEL_WIDTH Bandwidth);
 
-RT_STATUS PHY_RF8256_Config(struct net_device *dev);
+RT_STATUS PHY_RF8256_Config(struct r8192_priv *priv);
 
-RT_STATUS phy_RF8256_Config_ParaFile(struct net_device *dev);
+RT_STATUS phy_RF8256_Config_ParaFile(struct r8192_priv *priv);
 
-void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
-void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+void PHY_SetRF8256CCKTxPower(struct r8192_priv *priv, u8 powerlevel);
+void PHY_SetRF8256OFDMTxPower(struct r8192_priv *priv, u8 powerlevel);
 
-bool MgntActSet_RF_State(struct net_device *dev,
-				RT_RF_POWER_STATE StateToSet,
-				RT_RF_CHANGE_SOURCE ChangeSource);
+bool MgntActSet_RF_State(struct r8192_priv *priv,
+			 RT_RF_POWER_STATE StateToSet,
+			 RT_RF_CHANGE_SOURCE ChangeSource);
 
 #endif /* RTL8225_H */
diff --git a/drivers/staging/rtl8192e/r8192E.h b/drivers/staging/rtl8192e/r8192E.h
index 4a83958..0229031 100644
--- a/drivers/staging/rtl8192e/r8192E.h
+++ b/drivers/staging/rtl8192e/r8192E.h
@@ -20,7 +20,6 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-//#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
@@ -28,7 +27,6 @@
 #include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/pci.h>
-//#include <linux/usb.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
 #include <linux/rtnetlink.h>	//for rtnl_lock()
@@ -39,13 +37,14 @@
 #include <linux/random.h>
 #include <linux/version.h>
 #include <asm/io.h>
+#include "ieee80211/rtl819x_HT.h"
 #include "ieee80211/ieee80211.h"
 
 
 
 
 #define RTL819xE_MODULE_NAME "rtl819xE"
-//added for HW security, john.0629
+
 #define FALSE 0
 #define TRUE 1
 #define MAX_KEY_LEN     61
@@ -94,16 +93,12 @@
 
 #if 0 //we need to use RT_TRACE instead DMESG as RT_TRACE will clearly show debug level wb.
 #define DMESG(x,a...) printk(KERN_INFO RTL819xE_MODULE_NAME ": " x "\n", ## a)
-#define DMESGW(x,a...) printk(KERN_WARNING RTL819xE_MODULE_NAME ": WW:" x "\n", ## a)
-#define DMESGE(x,a...) printk(KERN_WARNING RTL819xE_MODULE_NAME ": EE:" x "\n", ## a)
 #else
 #define DMESG(x,a...)
-#define DMESGW(x,a...)
-#define DMESGE(x,a...)
 extern u32 rt_global_debug_component;
 #define RT_TRACE(component, x, args...) \
 do { if(rt_global_debug_component & component) \
-	printk(KERN_DEBUG RTL819xE_MODULE_NAME ":" x "\n" , \
+	printk(KERN_DEBUG RTL819xE_MODULE_NAME ":" x , \
 	       ##args);\
 }while(0);
 
@@ -134,9 +129,9 @@ do { if(rt_global_debug_component & component) \
 #define COMP_EVENTS			        BIT19	// Event handling
 
 #define COMP_RF					BIT20	// For RF.
-//1!!!!!!!!!!!!!!!!!!!!!!!!!!!
-//1//1Attention Please!!!<11n or 8190 specific code should be put below this line>
-//1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+/* 11n or 8190 specific code should be put below this line */
+
 
 #define COMP_FIRMWARE			        BIT21	//for firmware downloading
 #define COMP_HT					BIT22	// For 802.11n HT related information. by Emily 2006-8-11
@@ -150,34 +145,6 @@ do { if(rt_global_debug_component & component) \
 #define COMP_ERR				BIT31  // for error out, always on
 #endif
 
-#define RTL819x_DEBUG
-#ifdef RTL819x_DEBUG
-#define assert(expr) \
-        if (!(expr)) {                                  \
-                printk( "Assertion failed! %s,%s,%s,line=%d\n", \
-                #expr,__FILE__,__FUNCTION__,__LINE__);          \
-        }
-//wb added to debug out data buf
-//if you want print DATA buffer related BA, please set ieee80211_debug_level to DATA|BA
-#define RT_DEBUG_DATA(level, data, datalen)      \
-        do{ if ((rt_global_debug_component & (level)) == (level))   \
-                {       \
-                        int i;                                  \
-                        u8* pdata = (u8*) data;                 \
-                        printk(KERN_DEBUG RTL819xE_MODULE_NAME ": %s()\n", __FUNCTION__);   \
-                        for(i=0; i<(int)(datalen); i++)                 \
-                        {                                               \
-                                printk("%2x ", pdata[i]);               \
-                                if ((i+1)%16 == 0) printk("\n");        \
-                        }                               \
-                        printk("\n");                   \
-                }                                       \
-        } while (0)
-#else
-#define assert(expr) do {} while (0)
-#define RT_DEBUG_DATA(level, data, datalen) do {} while(0)
-#endif /* RTL8169_DEBUG */
-
 
 //
 // Queue Select Value in TxDesc
@@ -225,6 +192,87 @@ do { if(rt_global_debug_component & component) \
 #define EEPROM_Default_LegacyHTTxPowerDiff	0x4
 #define IEEE80211_WATCH_DOG_TIME    2000
 
+typedef u32 RT_RF_CHANGE_SOURCE;
+#define RF_CHANGE_BY_SW BIT31
+#define RF_CHANGE_BY_HW BIT30
+#define RF_CHANGE_BY_PS BIT29
+#define RF_CHANGE_BY_IPS BIT28
+#define RF_CHANGE_BY_INIT	0	// Do not change the RFOff reason. Defined by Bruce, 2008-01-17.
+
+// RF state.
+typedef	enum _RT_RF_POWER_STATE {
+	eRfOn,
+	eRfSleep,
+	eRfOff
+} RT_RF_POWER_STATE;
+
+typedef enum _RT_JOIN_ACTION {
+	RT_JOIN_INFRA = 1,
+	RT_JOIN_IBSS  = 2,
+	RT_START_IBSS = 3,
+	RT_NO_ACTION  = 4,
+} RT_JOIN_ACTION;
+
+typedef enum _IPS_CALLBACK_FUNCION {
+	IPS_CALLBACK_NONE = 0,
+	IPS_CALLBACK_MGNT_LINK_REQUEST = 1,
+	IPS_CALLBACK_JOIN_REQUEST = 2,
+} IPS_CALLBACK_FUNCION;
+
+typedef struct _RT_POWER_SAVE_CONTROL {
+	/* Inactive Power Save(IPS) : Disable RF when disconnected */
+	bool			bInactivePs;
+	bool			bIPSModeBackup;
+	bool			bSwRfProcessing;
+	RT_RF_POWER_STATE	eInactivePowerState;
+	struct work_struct 	InactivePsWorkItem;
+	struct timer_list	InactivePsTimer;
+
+	/* Return point for join action */
+	IPS_CALLBACK_FUNCION	ReturnPoint;
+
+	/* Recored Parameters for rescheduled JoinRequest */
+	bool			bTmpBssDesc;
+	RT_JOIN_ACTION		tmpJoinAction;
+	struct ieee80211_network tmpBssDesc;
+
+	/* Recored Parameters for rescheduled MgntLinkRequest */
+	bool			bTmpScanOnly;
+	bool			bTmpActiveScan;
+	bool			bTmpFilterHiddenAP;
+	bool			bTmpUpdateParms;
+	u8			tmpSsidBuf[33];
+	OCTET_STRING		tmpSsid2Scan;
+	bool			bTmpSsid2Scan;
+	u8			tmpNetworkType;
+	u8			tmpChannelNumber;
+	u16			tmpBcnPeriod;
+	u8			tmpDtimPeriod;
+	u16			tmpmCap;
+	OCTET_STRING		tmpSuppRateSet;
+	u8			tmpSuppRateBuf[MAX_NUM_RATES];
+	bool			bTmpSuppRate;
+	IbssParms		tmpIbpm;
+	bool			bTmpIbpm;
+
+	/*
+	 * Leisure Power Save:
+	 * Disable RF if connected but traffic is not busy
+	 */
+	bool			bLeisurePs;
+	u32			PowerProfile;
+	u8			LpsIdleCount;
+
+	u32			CurPsLevel;
+	u32			RegRfPsLevel;
+
+	bool			bFwCtrlLPS;
+	u8			FWCtrlPSMode;
+
+	bool			LinkReqInIPSRFOffPgs;
+	bool			BufConnectinfoBefore;
+} RT_POWER_SAVE_CONTROL, *PRT_POWER_SAVE_CONTROL;
+
 /* For rtl819x */
 typedef struct _tx_desc_819x_pci {
         //DWORD 0
@@ -329,11 +377,6 @@ typedef struct _tx_fwinfo_819x_pci {
         //u32                Reserved;
 }tx_fwinfo_819x_pci, *ptx_fwinfo_819x_pci;
 
-typedef struct rtl8192_rx_info {
-	struct urb *urb;
-	struct net_device *dev;
-	u8 out_pipe;
-}rtl8192_rx_info ;
 typedef struct _rx_desc_819x_pci{
 	//DOWRD 0
 	u16			Length:14;
@@ -386,8 +429,6 @@ typedef struct _rx_fwinfo_819x_pci{
 #define MAX_FIRMWARE_INFORMATION_SIZE   32 /*2006/04/30 by Emily forRTL8190*/
 #define MAX_802_11_HEADER_LENGTH        (40 + MAX_FIRMWARE_INFORMATION_SIZE)
 #define ENCRYPTION_MAX_OVERHEAD		128
-//#define	USB_HWDESC_HEADER_LEN		sizeof(tx_desc_819x_usb)
-//#define TX_PACKET_SHIFT_BYTES 	  	(USB_HWDESC_HEADER_LEN + sizeof(tx_fwinfo_819x_usb))
 #define MAX_FRAGMENT_COUNT		8
 #define MAX_TRANSMIT_BUFFER_SIZE  	(1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT)
 
@@ -406,11 +447,6 @@ typedef enum _desc_packet_type_e{
 	DESC_PACKET_TYPE_NORMAL = 1,
 }desc_packet_type_e;
 
-typedef enum _firmware_source{
-	FW_SOURCE_IMG_FILE = 0,
-	FW_SOURCE_HEADER_FILE = 1,		//from header file
-}firmware_source_e, *pfirmware_source_e;
-
 typedef enum _firmware_status{
 	FW_STATUS_0_INIT = 0,
 	FW_STATUS_1_MOVE_BOOT_CODE = 1,
@@ -420,11 +456,6 @@ typedef enum _firmware_status{
 	FW_STATUS_5_READY = 5,
 }firmware_status_e;
 
-typedef struct _rt_firmare_seg_container {
-	u16	seg_size;
-	u8	*seg_ptr;
-}fw_seg_container, *pfw_seg_container;
-
 typedef struct _rt_firmware{
 	firmware_status_e firmware_status;
 	u16		  cmdpacket_frag_thresold;
@@ -433,7 +464,7 @@ typedef struct _rt_firmware{
 	u8		  firmware_buf[MAX_FW_INIT_STEP][RTL8190_MAX_FIRMWARE_CODE_SIZE];
 	u16		  firmware_buf_size[MAX_FW_INIT_STEP];
 }rt_firmware, *prt_firmware;
-//+by amy 080507
+
 #define MAX_RECEIVE_BUFFER_SIZE	9100	// Add this to 9100 bytes to receive A-MSDU from RT-AP
 
 /* Firmware Queue Layout */
@@ -459,67 +490,21 @@ typedef struct _rt_firmware{
 #define RSVD_FW_QUEUE_PAGE_BCN_SHIFT	0x00
 #define RSVD_FW_QUEUE_PAGE_PUB_SHIFT	0x08
 
-//8187B Security
-//#define RWCAM                   0xA0                    // Software read/write CAM config
-//#define WCAMI                   0xA4                    // Software write CAM input content
-//#define RCAMO                   0xA8                    // Output value from CAM according to 0xa0 setting
 #define DCAM                    0xAC                    // Debug CAM Interface
 #define AESMSK_FC               0xB2    // AES Mask register for frame control (0xB2~0xB3). Added by Annie, 2006-03-06.
 
 
 #define CAM_CONTENT_COUNT       8
-//#define CFG_DEFAULT_KEY         BIT5
 #define CFG_VALID               BIT15
-#if 0
-//----------------------------------------------------------------------------
-//       8187B WPA Config Register (offset 0xb0, 1 byte)
-//----------------------------------------------------------------------------
-#define SCR_UseDK                       0x01
-#define SCR_TxSecEnable                 0x02
-#define SCR_RxSecEnable                 0x04
-
-//----------------------------------------------------------------------------
-//       8187B CAM Config Setting (offset 0xb0, 1 byte)
-//----------------------------------------------------------------------------
-#define CAM_VALID                               0x8000
-#define CAM_NOTVALID                    0x0000
-#define CAM_USEDK                               0x0020
-
-
-#define CAM_NONE                                0x0
-#define CAM_WEP40                               0x01
-#define CAM_TKIP                                0x02
-#define CAM_AES                                 0x04
-#define CAM_WEP104                              0x05
-
-//#define CAM_SIZE                              16
-#define TOTAL_CAM_ENTRY         16
-#define CAM_ENTRY_LEN_IN_DW     6       // 6, unit: in u4byte. Added by Annie, 2006-05-25.
-#define CAM_ENTRY_LEN_IN_BYTE   (CAM_ENTRY_LEN_IN_DW*sizeof(u32))    // 24, unit: in u1byte. Added by Annie, 2006-05-25.
-
-#define CAM_CONFIG_USEDK                1
-#define CAM_CONFIG_NO_USEDK             0
-
-#define CAM_WRITE                               0x00010000
-#define CAM_READ                                0x00000000
-#define CAM_POLLINIG                    0x80000000
-
-//=================================================================
-//=================================================================
-
-#endif
 #define EPROM_93c46 0
 #define EPROM_93c56 1
 
 #define DEFAULT_FRAG_THRESHOLD 2342U
 #define MIN_FRAG_THRESHOLD     256U
 #define DEFAULT_BEACONINTERVAL 0x64U
-#define DEFAULT_BEACON_ESSID "Rtl819xU"
 
-#define DEFAULT_SSID ""
 #define DEFAULT_RETRY_RTS 7
 #define DEFAULT_RETRY_DATA 7
-#define PRISM_HDR_SIZE 64
 
 #define		PHY_RSSI_SLID_WIN_MAX				100
 
@@ -544,28 +529,6 @@ typedef struct buffer
 
 } buffer;
 
-typedef struct rtl_reg_debug{
-        unsigned int  cmd;
-        struct {
-                unsigned char type;
-                unsigned char addr;
-                unsigned char page;
-                unsigned char length;
-        } head;
-        unsigned char buf[0xff];
-}rtl_reg_debug;
-
-#if 0
-
-typedef struct tx_pendingbuf
-{
-	struct ieee80211_txb *txb;
-	short ispending;
-	short descfrag;
-} tx_pendigbuf;
-
-#endif
-
 typedef struct _rt_9x_tx_rate_history {
 	u32             cck[4];
 	u32             ofdm[8];
@@ -595,108 +558,36 @@ typedef enum _tag_TxCmd_Config_Index{
 
 typedef struct Stats
 {
-	unsigned long txrdu;
 	unsigned long rxrdu;
-	//unsigned long rxnolast;
-	//unsigned long rxnodata;
-//	unsigned long rxreset;
-//	unsigned long rxnopointer;
 	unsigned long rxok;
-	unsigned long rxframgment;
-	unsigned long rxcmdpkt[4];		//08/05/08 amy rx cmd element txfeedback/bcn report/cfg set/query
-	unsigned long rxurberr;
-	unsigned long rxstaterr;
-	unsigned long rxcrcerrmin;//crc error (0-500)
-	unsigned long rxcrcerrmid;//crc error (500-1000)
-	unsigned long rxcrcerrmax;//crc error (>1000)
-	unsigned long received_rate_histogram[4][32];	//0: Total, 1:OK, 2:CRC, 3:ICV, 2007 07 03 cosa
-	unsigned long received_preamble_GI[2][32];		//0: Long preamble/GI, 1:Short preamble/GI
-	unsigned long	rx_AMPDUsize_histogram[5]; // level: (<4K), (4K~8K), (8K~16K), (16K~32K), (32K~64K)
-	unsigned long rx_AMPDUnum_histogram[5]; // level: (<5), (5~10), (10~20), (20~40), (>40)
-	unsigned long numpacket_matchbssid;	// debug use only.
-	unsigned long numpacket_toself;		// debug use only.
-	unsigned long num_process_phyinfo;		// debug use only.
-	unsigned long numqry_phystatus;
-	unsigned long numqry_phystatusCCK;
-	unsigned long numqry_phystatusHT;
-	unsigned long received_bwtype[5];              //0: 20M, 1: funn40M, 2: upper20M, 3: lower20M, 4: duplicate
-	unsigned long txnperr;
-	unsigned long txnpdrop;
-	unsigned long txresumed;
-//	unsigned long rxerr;
+	unsigned long received_rate_histogram[4][32];	//0: Total, 1:OK, 2:CRC, 3:ICV
 	unsigned long rxoverflow;
 	unsigned long rxint;
-	unsigned long txnpokint;
-//	unsigned long txhpokint;
-//	unsigned long txhperr;
-	unsigned long ints;
-	unsigned long shints;
 	unsigned long txoverflow;
-//	unsigned long rxdmafail;
-//	unsigned long txbeacon;
-//	unsigned long txbeaconerr;
-	unsigned long txlpokint;
-	unsigned long txlpdrop;
-	unsigned long txlperr;
 	unsigned long txbeokint;
-	unsigned long txbedrop;
-	unsigned long txbeerr;
 	unsigned long txbkokint;
-	unsigned long txbkdrop;
-	unsigned long txbkerr;
 	unsigned long txviokint;
-	unsigned long txvidrop;
-	unsigned long txvierr;
 	unsigned long txvookint;
-	unsigned long txvodrop;
-	unsigned long txvoerr;
 	unsigned long txbeaconokint;
-	unsigned long txbeacondrop;
 	unsigned long txbeaconerr;
 	unsigned long txmanageokint;
-	unsigned long txmanagedrop;
-	unsigned long txmanageerr;
 	unsigned long txcmdpktokint;
-	unsigned long txdatapkt;
 	unsigned long txfeedback;
 	unsigned long txfeedbackok;
 	unsigned long txoktotal;
-	unsigned long txokbytestotal;
-	unsigned long txokinperiod;
-	unsigned long txmulticast;
-	unsigned long txbytesmulticast;
-	unsigned long txbroadcast;
-	unsigned long txbytesbroadcast;
-	unsigned long txunicast;
 	unsigned long txbytesunicast;
 	unsigned long rxbytesunicast;
-	unsigned long txfeedbackfail;
-	unsigned long txerrtotal;
-	unsigned long txerrbytestotal;
-	unsigned long txerrmulticast;
-	unsigned long txerrbroadcast;
-	unsigned long txerrunicast;
-	unsigned long txretrycount;
-	unsigned long txfeedbackretry;
-	u8			last_packet_rate;
+
 	unsigned long slide_signal_strength[100];
 	unsigned long slide_evm[100];
 	unsigned long	slide_rssi_total;	// For recording sliding window's RSSI value
 	unsigned long slide_evm_total;	// For recording sliding window's EVM value
 	long signal_strength; // Transformed, in dbm. Beautified signal strength for UI, not correct.
-	long signal_quality;
-	long last_signal_strength_inpercent;
-	long	recv_signal_power;	// Correct smoothed ss in Dbm, only used in driver to report real power now.
 	u8 rx_rssi_percentage[4];
 	u8 rx_evm_percentage[2];
-	long rxSNRdB[4];
-	rt_tx_rahis_t txrate;
-	u32 Slide_Beacon_pwdb[100];	//cosa add for beacon rssi
-	u32 Slide_Beacon_Total;		//cosa add for beacon rssi
+	u32 Slide_Beacon_pwdb[100];
+	u32 Slide_Beacon_Total;
 	RT_SMOOTH_DATA_4RF		cck_adc_pwdb;
-	u32	CurrentShowTxate;
-
-
 } Stats;
 
 
@@ -705,8 +596,6 @@ typedef struct Stats
 #define HAL_PRIME_CHNL_OFFSET_LOWER			1
 #define HAL_PRIME_CHNL_OFFSET_UPPER			2
 
-//+by amy 080507
-
 typedef struct 	ChnlAccessSetting {
 	u16 SIFS_Timer;
 	u16 DIFS_Timer;
@@ -736,15 +625,6 @@ typedef struct _BB_REGISTER_DEFINITION{
 	u32 rfLSSIReadBack; 	//LSSI RF readback data //		0x8a0~0x8af [16 bytes]
 }BB_REGISTER_DEFINITION_T, *PBB_REGISTER_DEFINITION_T;
 
-typedef enum _RT_RF_TYPE_819xU{
-        RF_TYPE_MIN = 0,
-        RF_8225,
-        RF_8256,
-        RF_8258,
-        RF_PSEUDO_11N = 4,
-}RT_RF_TYPE_819xU, *PRT_RF_TYPE_819xU;
-
-
 typedef struct _rate_adaptive
 {
 	u8				rate_adaptive_disabled;
@@ -827,9 +707,7 @@ typedef enum _RT_CUSTOMER_ID
 	RT_CID_COREGA = 14,
 }RT_CUSTOMER_ID, *PRT_CUSTOMER_ID;
 
-//================================================================================
-// LED customization.
-//================================================================================
+/* LED customization. */
 
 typedef	enum _LED_STRATEGY_8190{
 	SW_LED_MODE0, // SW control 1 LED via GPIO0. It is default option.
@@ -990,18 +868,17 @@ struct rtl8192_tx_ring {
 typedef struct r8192_priv
 {
 	struct pci_dev *pdev;
-	//added for maintain info from eeprom
+	u8 *mem_start;
+
+	/* maintain info from eeprom */
 	short epromtype;
 	u16 eeprom_vid;
 	u16 eeprom_did;
 	u8  eeprom_CustomerID;
 	u16  eeprom_ChannelPlan;
 	RT_CUSTOMER_ID CustomerID;
-	LED_STRATEGY_8190	LedStrategy;
-	//bool bDcut;
 	u8	IC_Cut;
 	int irq;
-	short irq_enabled;
 	struct ieee80211_device *ieee80211;
 #ifdef ENABLE_LPS
 	bool ps_force;
@@ -1010,30 +887,14 @@ typedef struct r8192_priv
 #endif
 	bool being_init_adapter;
 	u8 Rf_Mode;
-	short card_8192; /* O: rtl8192, 1:rtl8185 V B/C, 2:rtl8185 V D */
 	u8 card_8192_version; /* if TCR reports card V B/C this discriminates */
-//	short phy_ver; /* meaningful for rtl8225 1:A 2:B 3:C */
-	short enable_gpio0;
-	enum card_type {PCI,MINIPCI,CARDBUS,USB/*rtl8187*/}card_type;
-	short hw_plcp_len;
-	short plcp_preamble_mode;
-	u8 ScanDelay;
-	spinlock_t irq_lock;
 	spinlock_t irq_th_lock;
-	spinlock_t tx_lock;
 	spinlock_t rf_ps_lock;
         struct mutex mutex;
-	spinlock_t rf_lock; //used to lock rf write operation added by wb
-	spinlock_t ps_lock;
 
-	u32 irq_mask;
-//	short irq_enabled;
-//	struct net_device *dev; //comment this out.
 	short chan;
 	short sens;
-	short max_sens;
-	u32 rx_prevlen;
-/*RX stuff*/
+	/* RX stuff */
         rx_desc_819x_pci *rx_ring;
         dma_addr_t rx_ring_dma;
         unsigned int rx_idx;
@@ -1041,158 +902,50 @@ typedef struct r8192_priv
 	int rxringcount;
 	u16 rxbuffersize;
 
-
-	struct sk_buff *rx_skb;
-	u32 *rxring;
-	u32 *rxringtail;
-	dma_addr_t rxringdma;
-	struct buffer *rxbuffer;
-	struct buffer *rxbufferhead;
-	short rx_skb_complete;
-/*TX stuff*/
+	/* TX stuff */
         struct rtl8192_tx_ring tx_ring[MAX_TX_QUEUE_COUNT];
 	int txringcount;
-//{
-	int txbuffsize;
-	int txfwbuffersize;
-	//struct tx_pendingbuf txnp_pending;
-	//struct tasklet_struct irq_tx_tasklet;
+
 	struct tasklet_struct irq_rx_tasklet;
 	struct tasklet_struct irq_tx_tasklet;
         struct tasklet_struct irq_prepare_beacon_tasklet;
-	struct buffer *txmapbufs;
-	struct buffer *txbkpbufs;
-	struct buffer *txbepbufs;
-	struct buffer *txvipbufs;
-	struct buffer *txvopbufs;
-	struct buffer *txcmdbufs;
-	struct buffer *txmapbufstail;
-	struct buffer *txbkpbufstail;
-	struct buffer *txbepbufstail;
-	struct buffer *txvipbufstail;
-	struct buffer *txvopbufstail;
-	struct buffer *txcmdbufstail;
-	/* adhoc/master mode stuff */
-	ptx_ring txbeaconringtail;
-	dma_addr_t txbeaconringdma;
-	ptx_ring txbeaconring;
-	int txbeaconcount;
-	struct buffer *txbeaconbufs;
-	struct buffer *txbeaconbufstail;
-	ptx_ring txmapring;
-	ptx_ring txbkpring;
-	ptx_ring txbepring;
-	ptx_ring txvipring;
-	ptx_ring txvopring;
-	ptx_ring txcmdring;
-	ptx_ring txmapringtail;
-	ptx_ring txbkpringtail;
-	ptx_ring txbepringtail;
-	ptx_ring txvipringtail;
-	ptx_ring txvopringtail;
-	ptx_ring txcmdringtail;
-	ptx_ring txmapringhead;
-	ptx_ring txbkpringhead;
-	ptx_ring txbepringhead;
-	ptx_ring txvipringhead;
-	ptx_ring txvopringhead;
-	ptx_ring txcmdringhead;
-	dma_addr_t txmapringdma;
-	dma_addr_t txbkpringdma;
-	dma_addr_t txbepringdma;
-	dma_addr_t txvipringdma;
-	dma_addr_t txvopringdma;
-	dma_addr_t txcmdringdma;
-	//	u8 chtxpwr[15]; //channels from 1 to 14, 0 not used
-//	u8 chtxpwr_ofdm[15]; //channels from 1 to 14, 0 not used
-//	u8 cck_txpwr_base;
-//	u8 ofdm_txpwr_base;
-//	u8 challow[15]; //channels from 1 to 14, 0 not used
+
 	short up;
 	short crcmon; //if 1 allow bad crc frame reception in monitor mode
-//	short prism_hdr;
-
-//	struct timer_list scan_timer;
-	/*short scanpending;
-	short stopscan;*/
-//	spinlock_t scan_lock;
-//	u8 active_probe;
-	//u8 active_scan_num;
 	struct semaphore wx_sem;
 	struct semaphore rf_sem; //used to lock rf write operation added by wb, modified by david
-//	short hw_wep;
-
-//	short digphy;
-//	short antb;
-//	short diversity;
-//	u8 cs_treshold;
-//	short rcr_csense;
-	u8 rf_type; //0 means 1T2R, 1 means 2T4R
-	RT_RF_TYPE_819xU rf_chip;
-
-//	u32 key0[4];
-	short (*rf_set_sens)(struct net_device *dev,short sens);
-	u8 (*rf_set_chan)(struct net_device *dev,u8 ch);
-	void (*rf_close)(struct net_device *dev);
-	void (*rf_init)(struct net_device *dev);
-	//short rate;
+	u8 rf_type; /* 0 means 1T2R, 1 means 2T4R */
+
+	short (*rf_set_sens)(struct net_device *dev, short sens);
+	u8 (*rf_set_chan)(struct ieee80211_device *ieee80211, u8 ch);
 	short promisc;
-	/*stats*/
+	/* stats */
 	struct Stats stats;
 	struct iw_statistics wstats;
 	struct proc_dir_entry *dir_dev;
+	struct ieee80211_rx_stats previous_stats;
 
-	/*RX stuff*/
-//	u32 *rxring;
-//	u32 *rxringtail;
-//	dma_addr_t rxringdma;
-
-#ifdef THOMAS_BEACON
-	u32 *oldaddr;
-#endif
-#ifdef THOMAS_TASKLET
-	atomic_t irt_counter;//count for irq_rx_tasklet
-#endif
-#ifdef JACKSON_NEW_RX
-        struct sk_buff **pp_rxskb;
-        int     rx_inx;
-#endif
-
-/* modified by davad for Rx process */
-       struct sk_buff_head rx_queue;
-       struct sk_buff_head skb_queue;
-       struct work_struct qos_activate;
-	short  tx_urb_index;
-	atomic_t tx_pending[0x10];//UART_PRIORITY+1
-
-	struct urb *rxurb_task;
+	/* RX stuff */
+	struct sk_buff_head skb_queue;
+	struct work_struct qos_activate;
 
 	//2 Tx Related variables
 	u16	ShortRetryLimit;
 	u16	LongRetryLimit;
-	u32	TransmitConfig;
-	u8	RegCWinMin;		// For turbo mode CW adaptive. Added by Annie, 2005-10-27.
 
 	u32     LastRxDescTSFHigh;
 	u32     LastRxDescTSFLow;
 
 
 	//2 Rx Related variables
-	u16	EarlyRxThreshold;
 	u32	ReceiveConfig;
-	u8	AcmControl;
-
-	u8	RFProgType;
 
 	u8 retry_data;
 	u8 retry_rts;
-	u16 rts;
-
-	struct 	ChnlAccessSetting  ChannelAccessSetting;
 
 	struct work_struct reset_wq;
+	u8	rx_chk_cnt;
 
-/**********************************************************/
 //for rtl819xPci
 	// Data Rate Config. Added by Annie, 2006-04-13.
 	u16	basic_rate;
@@ -1204,30 +957,23 @@ typedef struct r8192_priv
 /*Firmware*/
 	prt_firmware		pFirmware;
 	rtl819x_loopback_e	LoopbackMode;
-	firmware_source_e	firmware_source;
 	bool AutoloadFailFlag;
-	u16 EEPROMTxPowerDiff;
 	u16 EEPROMAntPwDiff;		// Antenna gain offset from B/C/D to A
 	u8 EEPROMThermalMeter;
-	u8 EEPROMPwDiff;
 	u8 EEPROMCrystalCap;
-	u8 EEPROM_Def_Ver;
 	u8 EEPROMTxPowerLevelCCK[14];// CCK channel 1~14
 	// The following definition is for eeprom 93c56
 	u8 EEPROMRfACCKChnl1TxPwLevel[3];	//RF-A CCK Tx Power Level at channel 7
 	u8 EEPROMRfAOfdmChnlTxPwLevel[3];//RF-A CCK Tx Power Level at [0],[1],[2] = channel 1,7,13
 	u8 EEPROMRfCCCKChnl1TxPwLevel[3];	//RF-C CCK Tx Power Level at channel 7
 	u8 EEPROMRfCOfdmChnlTxPwLevel[3];//RF-C CCK Tx Power Level at [0],[1],[2] = channel 1,7,13
-	u8 EEPROMTxPowerLevelCCK_V1[3];
 	u8 EEPROMTxPowerLevelOFDM24G[14]; // OFDM 2.4G channel 1~14
-	u8 EEPROMTxPowerLevelOFDM5G[24];	// OFDM 5G
 	u8 EEPROMLegacyHTTxPowerDiff;	// Legacy to HT rate power diff
 	bool bTXPowerDataReadFromEEPORM;
 /*channel plan*/
 	u16 RegChannelPlan; // Channel Plan specifed by user, 15: following setting of EEPROM, 0-14: default channel plan index specified by user.
 	u16 ChannelPlan;
 /*PS related*/
-	bool RegRfOff;
 	// Rf off action for power save
 	u8	bHwRfOffAction;	//0:No action, 1:By GPIO, 2:By Disable
 /*PHY related*/
@@ -1243,8 +989,6 @@ typedef struct r8192_priv
 	u8	TxPowerLevelOFDM24G_A[14];	// RF-A, OFDM 2.4G channel 1~14
 	u8	TxPowerLevelOFDM24G_C[14];	// RF-C, OFDM 2.4G channel 1~14
 	u8	LegacyHTTxPowerDiff;			// Legacy to HT rate power diff
-	u8	TxPowerDiff;
-	char	RF_C_TxPwDiff;					// Antenna gain offset, rf-c to rf-a
 	u8	AntennaTxPwDiff[3];				// Antenna gain offset, index 0 for B, 1 for C, and 2 for D
 	u8	CrystalCap;						// CrystalCap.
 	u8	ThermalMeter[2];				// ThermalMeter, index 0 for RFIC0, and 1 for RFIC1
@@ -1257,6 +1001,9 @@ typedef struct r8192_priv
 	char				CCKPresentAttentuation_difference;
 	char				CCKPresentAttentuation;
 	// Use to calculate PWBD.
+	RT_RF_POWER_STATE		eRFPowerState;
+	RT_RF_CHANGE_SOURCE	RfOffReason;
+	RT_POWER_SAVE_CONTROL	PowerSaveControl;
 	u8	bCckHighPower;
 	long	undecorated_smoothed_pwdb;
 	long	undecorated_smoothed_cck_adc_pwdb[4];
@@ -1278,22 +1025,25 @@ typedef struct r8192_priv
 	bool 				brfpath_rxenable[4];
 //+by amy 080507
 	struct timer_list watch_dog_timer;
+	u8 watchdog_last_time;
+	u8 watchdog_check_reset_cnt;
 
 //+by amy 080515 for dynamic mechenism
 	//Add by amy Tx Power Control for Near/Far Range 2008/05/15
-	bool	bdynamic_txpower;  //bDynamicTxPower
 	bool	bDynamicTxHighPower;  // Tx high power state
 	bool	bDynamicTxLowPower;  // Tx low power state
 	bool	bLastDTPFlag_High;
 	bool	bLastDTPFlag_Low;
 
-	bool	bstore_last_dtpflag;
-	bool	bstart_txctrl_bydtp;   //Define to discriminate on High power State or on sitesuvey to change Tx gain index
+	/* OFDM RSSI. For high power or not */
+	u8	phy_check_reg824;
+	u32	phy_reg824_bit9;
+
 	//Add by amy for Rate Adaptive
 	rate_adaptive rate_adaptive;
 	//Add by amy for TX power tracking
 	//2008/05/15  Mars OPEN/CLOSE TX POWER TRACKING
-       txbbgain_struct txbbgain_table[TxBBGainTableLength];
+	const txbbgain_struct * txbbgain_table;
 	u8			   txpower_count;//For 6 sec do tracking again
 	bool			   btxpower_trackingInit;
 	u8			   OFDM_index;
@@ -1301,8 +1051,8 @@ typedef struct r8192_priv
 	u8			   Record_CCK_20Mindex;
 	u8			   Record_CCK_40Mindex;
 	//2007/09/10 Mars Add CCK TX Power Tracking
-	ccktxbbgain_struct	cck_txbbgain_table[CCKTxBBGainTableLength];
-	ccktxbbgain_struct	cck_txbbgain_ch14_table[CCKTxBBGainTableLength];
+	const ccktxbbgain_struct *cck_txbbgain_table;
+	const ccktxbbgain_struct *cck_txbbgain_ch14_table;
 	u8 rfa_txpowertrackingindex;
 	u8 rfa_txpowertrackingindex_real;
 	u8 rfa_txpowertracking_default;
@@ -1321,7 +1071,6 @@ typedef struct r8192_priv
 
 	bool		bis_cur_rdlstate;
 	struct timer_list fsync_timer;
-	bool bfsync_processing;	// 500ms Fsync timer is active or not
 	u32 	rate_record;
 	u32 	rateCountDiffRecord;
 	u32	ContiuneDiffCount;
@@ -1330,32 +1079,13 @@ typedef struct r8192_priv
 	u8	framesync;
 	u32 	framesyncC34;
 	u8   	framesyncMonitor;
-        	//Added by amy 080516  for RX related
-	u16 	nrxAMPDU_size;
-	u8 	nrxAMPDU_aggr_num;
-
-	/*Last RxDesc TSF value*/
-	u32 last_rxdesc_tsf_high;
-	u32 last_rxdesc_tsf_low;
 
 	//by amy for gpio
 	bool bHwRadioOff;
 	//by amy for ps
-	bool RFChangeInProgress; // RF Chnage in progress, by Bruce, 2007-10-30
-	bool SetRFPowerStateInProgress;
 	RT_OP_MODE OpMode;
 	//by amy for reset_count
 	u32 reset_count;
-	bool bpbc_pressed;
-	//by amy for debug
-	u32 txpower_checkcnt;
-	u32 txpower_tracking_callback_cnt;
-	u8 thermal_read_val[40];
-	u8 thermal_readback_index;
-	u32 ccktxpower_adjustcnt_not_ch14;
-	u32 ccktxpower_adjustcnt_ch14;
-	u8 tx_fwinfo_force_subcarriermode;
-	u8 tx_fwinfo_force_subcarrierval;
 
 	//by amy for silent reset
 	RESET_TYPE	ResetProgress;
@@ -1378,154 +1108,41 @@ typedef struct r8192_priv
 	struct workqueue_struct *priv_wq;
 }r8192_priv;
 
-// for rtl8187
-// now mirging to rtl8187B
-/*
-typedef enum{
-	LOW_PRIORITY = 0x02,
-	NORM_PRIORITY
-	} priority_t;
-*/
-//for rtl8187B
-#if 0
-typedef enum{
-	BULK_PRIORITY = 0x01,
-	//RSVD0,
-	//RSVD1,
-	LOW_PRIORITY,
-	NORM_PRIORITY,
-	VO_PRIORITY,
-	VI_PRIORITY, //0x05
-	BE_PRIORITY,
-	BK_PRIORITY,
-	CMD_PRIORITY,//0x8
-	RSVD3,
-	BEACON_PRIORITY, //0x0A
-	HIGH_PRIORITY,
-	MANAGE_PRIORITY,
-	RSVD4,
-	RSVD5,
-	UART_PRIORITY //0x0F
-} priority_t;
-#endif
-typedef enum{
-	NIC_8192E = 1,
-	} nic_t;
-
-
-#if 0 //defined in Qos.h
-//typedef u32 AC_CODING;
-#define AC0_BE	0		// ACI: 0x00	// Best Effort
-#define AC1_BK	1		// ACI: 0x01	// Background
-#define AC2_VI	2		// ACI: 0x10	// Video
-#define AC3_VO	3		// ACI: 0x11	// Voice
-#define AC_MAX	4		// Max: define total number; Should not to be used as a real enum.
-
-//
-// ECWmin/ECWmax field.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.13.
-//
-typedef	union _ECW{
-	u8	charData;
-	struct
-	{
-		u8	ECWmin:4;
-		u8	ECWmax:4;
-	}f;	// Field
-}ECW, *PECW;
-
-//
-// ACI/AIFSN Field.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
-//
-typedef	union _ACI_AIFSN{
-	u8	charData;
-
-	struct
-	{
-		u8	AIFSN:4;
-		u8	ACM:1;
-		u8	ACI:2;
-		u8	Reserved:1;
-	}f;	// Field
-}ACI_AIFSN, *PACI_AIFSN;
+bool init_firmware(struct r8192_priv *priv);
+u32 read_cam(struct r8192_priv *priv, u8 addr);
+void write_cam(struct r8192_priv *priv, u8 addr, u32 data);
+u8 read_nic_byte(struct r8192_priv *priv, int x);
+u32 read_nic_dword(struct r8192_priv *priv, int x);
+u16 read_nic_word(struct r8192_priv *priv, int x) ;
+void write_nic_byte(struct r8192_priv *priv, int x,u8 y);
+void write_nic_word(struct r8192_priv *priv, int x,u16 y);
+void write_nic_dword(struct r8192_priv *priv, int x,u32 y);
 
-//
-// AC Parameters Record Format.
-// Ref: WMM spec 2.2.2: WME Parameter Element, p.12.
-//
-typedef	union _AC_PARAM{
-	u32	longData;
-	u8	charData[4];
-
-	struct
-	{
-		ACI_AIFSN	AciAifsn;
-		ECW		Ecw;
-		u16		TXOPLimit;
-	}f;	// Field
-}AC_PARAM, *PAC_PARAM;
-
-#endif
-bool init_firmware(struct net_device *dev);
-short rtl8192_tx(struct net_device *dev, struct sk_buff* skb);
-u32 read_cam(struct net_device *dev, u8 addr);
-void write_cam(struct net_device *dev, u8 addr, u32 data);
-u8 read_nic_byte(struct net_device *dev, int x);
-u8 read_nic_byte_E(struct net_device *dev, int x);
-u32 read_nic_dword(struct net_device *dev, int x);
-u16 read_nic_word(struct net_device *dev, int x) ;
-void write_nic_byte(struct net_device *dev, int x,u8 y);
-void write_nic_byte_E(struct net_device *dev, int x,u8 y);
-void write_nic_word(struct net_device *dev, int x,u16 y);
-void write_nic_dword(struct net_device *dev, int x,u32 y);
-
-void rtl8192_halt_adapter(struct net_device *dev, bool reset);
-void rtl8192_rx_enable(struct net_device *);
-void rtl8192_tx_enable(struct net_device *);
-
-void rtl8192_disassociate(struct net_device *dev);
-//void fix_rx_fifo(struct net_device *dev);
-void rtl8185_set_rf_pins_enable(struct net_device *dev,u32 a);
-
-void rtl8192_set_anaparam(struct net_device *dev,u32 a);
-void rtl8185_set_anaparam2(struct net_device *dev,u32 a);
-void rtl8192_update_msr(struct net_device *dev);
 int rtl8192_down(struct net_device *dev);
 int rtl8192_up(struct net_device *dev);
-void rtl8192_commit(struct net_device *dev);
-void rtl8192_set_chan(struct net_device *dev,short ch);
+void rtl8192_commit(struct r8192_priv *priv);
 void write_phy(struct net_device *dev, u8 adr, u8 data);
-void write_phy_cck(struct net_device *dev, u8 adr, u32 data);
-void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
-void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
-void rtl8187_set_rxconf(struct net_device *dev);
-//short check_nic_enough_desc(struct net_device *dev, priority_t priority);
-void CamResetAllEntry(struct net_device* dev);
-void EnableHWSecurityConfig8192(struct net_device *dev);
-void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent );
-void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
-void firmware_init_param(struct net_device *dev);
-RT_STATUS cmpk_message_handle_tx(struct net_device *dev, u8* codevirtualaddress, u32 packettype, u32 buffer_len);
-void rtl8192_hw_wakeup_wq (struct work_struct *work);
-
-short rtl8192_is_tx_queue_empty(struct net_device *dev);
+void CamResetAllEntry(struct r8192_priv *priv);
+void EnableHWSecurityConfig8192(struct r8192_priv *priv);
+void setKey(struct r8192_priv *priv, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+	    const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
+void firmware_init_param(struct r8192_priv *priv);
+RT_STATUS cmpk_message_handle_tx(struct r8192_priv *priv, u8 *codevirtualaddress, u32 packettype, u32 buffer_len);
+
 #ifdef ENABLE_IPS
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
-void InactivePsWorkItemCallback(struct net_device *dev);
-void IPSLeave_wq(void *data);
-void ieee80211_ips_leave_wq(struct net_device *dev);
-void ieee80211_ips_leave(struct net_device *dev);
+void IPSEnter(struct r8192_priv *priv);
+void IPSLeave(struct r8192_priv *priv);
+void IPSLeave_wq(struct work_struct *work);
+void ieee80211_ips_leave_wq(struct ieee80211_device *ieee80211);
+void ieee80211_ips_leave(struct ieee80211_device *ieee80211);
 #endif
 #ifdef ENABLE_LPS
-void LeisurePSEnter(struct net_device *dev);
-void LeisurePSLeave(struct net_device *dev);
+void LeisurePSEnter(struct ieee80211_device *ieee80211);
+void LeisurePSLeave(struct ieee80211_device *ieee80211);
 #endif
 
-bool NicIFEnableNIC(struct net_device* dev);
-bool NicIFDisableNIC(struct net_device* dev);
+bool NicIFEnableNIC(struct r8192_priv *priv);
+bool NicIFDisableNIC(struct r8192_priv *priv);
 
-void rtl8192_irq_disable(struct net_device *dev);
-void PHY_SetRtl8192eRfOff(struct net_device* dev);
+void PHY_SetRtl8192eRfOff(struct r8192_priv *priv);
 #endif
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index fac4eee..58d800f 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -1,6 +1,6 @@
 /******************************************************************************
  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8190P / RTL8192E
+ * Linux device driver for RTL8192E
  *
  * Based on the r8180 driver, which is:
  * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
@@ -25,26 +25,6 @@
  */
 
 
-#undef RX_DONT_PASS_UL
-#undef DEBUG_EPROM
-#undef DEBUG_RX_VERBOSE
-#undef DUMMY_RX
-#undef DEBUG_ZERO_RX
-#undef DEBUG_RX_SKB
-#undef DEBUG_TX_FRAG
-#undef DEBUG_RX_FRAG
-#undef DEBUG_TX_FILLDESC
-#undef DEBUG_TX
-#undef DEBUG_IRQ
-#undef DEBUG_RX
-#undef DEBUG_RXALLOC
-#undef DEBUG_REGISTERS
-#undef DEBUG_RING
-#undef DEBUG_IRQ_TASKLET
-#undef DEBUG_TX_ALLOC
-#undef DEBUG_TX_DESC
-
-//#define CONFIG_RTL8192_IO_MAP
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
@@ -67,44 +47,15 @@
 #endif
 
 //set here to open your trace code. //WB
-u32 rt_global_debug_component =
-		//		COMP_INIT    	|
-			//	COMP_EPROM   	|
-		//		COMP_PHY	|
-		//		COMP_RF		|
-//				COMP_FIRMWARE	|
-			//	COMP_TRACE	|
-		//		COMP_DOWN	|
-		//		COMP_SWBW	|
-		//		COMP_SEC	|
-//				COMP_QOS	|
-//				COMP_RATE	|
-		//		COMP_RECV	|
-		//		COMP_SEND	|
-		//		COMP_POWER	|
-			//	COMP_EVENTS	|
-			//	COMP_RESET	|
-			//	COMP_CMDPKT	|
-			//	COMP_POWER_TRACKING	|
-                        // 	COMP_INTR       |
-				COMP_ERR ; //always open err flags on
+u32 rt_global_debug_component = COMP_ERR ; //always open err flags on
 
 static DEFINE_PCI_DEVICE_TABLE(rtl8192_pci_id_tbl) = {
-#ifdef RTL8190P
-	/* Realtek */
-	/* Dlink */
-	{ PCI_DEVICE(0x10ec, 0x8190) },
-	/* Corega */
-	{ PCI_DEVICE(0x07aa, 0x0045) },
-	{ PCI_DEVICE(0x07aa, 0x0046) },
-#else
 	/* Realtek */
 	{ PCI_DEVICE(0x10ec, 0x8192) },
 
 	/* Corega */
 	{ PCI_DEVICE(0x07aa, 0x0044) },
 	{ PCI_DEVICE(0x07aa, 0x0047) },
-#endif
 	{}
 };
 
@@ -145,20 +96,20 @@ static struct pci_driver rtl8192_pci_driver = {
 #endif
 };
 
-static void rtl8192_start_beacon(struct net_device *dev);
-static void rtl8192_stop_beacon(struct net_device *dev);
+static void rtl8192_start_beacon(struct ieee80211_device *ieee80211);
+static void rtl8192_stop_beacon(struct ieee80211_device *ieee80211);
 static void rtl819x_watchdog_wqcallback(struct work_struct *work);
-static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
-static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
-static void rtl8192_prepare_beacon(struct r8192_priv *priv);
-static irqreturn_t rtl8192_interrupt(int irq, void *netdev);
-static void rtl8192_try_wake_queue(struct net_device *dev, int pri);
-static void rtl819xE_tx_cmd(struct net_device *dev, struct sk_buff *skb);
-static void rtl8192_update_ratr_table(struct net_device* dev);
+static void rtl8192_irq_rx_tasklet(unsigned long arg);
+static void rtl8192_irq_tx_tasklet(unsigned long arg);
+static void rtl8192_prepare_beacon(unsigned long arg);
+static irqreturn_t rtl8192_interrupt(int irq, void *param);
+static void rtl819xE_tx_cmd(struct r8192_priv *priv, struct sk_buff *skb);
+static void rtl8192_update_ratr_table(struct r8192_priv *priv);
 static void rtl8192_restart(struct work_struct *work);
 static void watch_dog_timer_callback(unsigned long data);
-static int _rtl8192_up(struct net_device *dev);
+static int _rtl8192_up(struct r8192_priv *priv);
 static void rtl8192_cancel_deferred_work(struct r8192_priv* priv);
+static short rtl8192_tx(struct r8192_priv *priv, struct sk_buff* skb);
 
 #ifdef ENABLE_DOT11D
 
@@ -202,15 +153,9 @@ static void rtl819x_set_channel_map(u8 channel_plan, struct r8192_priv* priv)
 			Dot11d_Init(ieee);
 			ieee->bGlobalDomain = false;
                         //acturally 8225 & 8256 rf chip only support B,G,24N mode
-                        if ((priv->rf_chip == RF_8225) || (priv->rf_chip == RF_8256))
-			{
-				min_chan = 1;
-				max_chan = 14;
-			}
-			else
-			{
-				RT_TRACE(COMP_ERR, "unknown rf chip, can't set channel map in function:%s()\n", __FUNCTION__);
-			}
+			min_chan = 1;
+			max_chan = 14;
+
 			if (ChannelPlan[channel_plan].Len != 0){
 				// Clear old channel map
 				memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map));
@@ -246,92 +191,56 @@ static inline bool rx_hal_is_cck_rate(prx_fwinfo_819x_pci pdrvinfo)
 		!pdrvinfo->RxHT;
 }
 
-void CamResetAllEntry(struct net_device *dev)
-{
-	write_nic_dword(dev, RWCAM, BIT31|BIT30);
-}
-
-
-void write_cam(struct net_device *dev, u8 addr, u32 data)
-{
-        write_nic_dword(dev, WCAMI, data);
-        write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) );
-}
-u32 read_cam(struct net_device *dev, u8 addr)
-{
-        write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) );
-        return read_nic_dword(dev, 0xa8);
-}
-
-#ifdef CONFIG_RTL8180_IO_MAP
-
-u8 read_nic_byte(struct net_device *dev, int x)
-{
-        return 0xff&inb(dev->base_addr +x);
-}
-
-u32 read_nic_dword(struct net_device *dev, int x)
-{
-        return inl(dev->base_addr +x);
-}
-
-u16 read_nic_word(struct net_device *dev, int x)
-{
-        return inw(dev->base_addr +x);
-}
-
-void write_nic_byte(struct net_device *dev, int x,u8 y)
+void CamResetAllEntry(struct r8192_priv* priv)
 {
-        outb(y&0xff,dev->base_addr +x);
+	write_nic_dword(priv, RWCAM, BIT31|BIT30);
 }
 
-void write_nic_word(struct net_device *dev, int x,u16 y)
+void write_cam(struct r8192_priv *priv, u8 addr, u32 data)
 {
-        outw(y,dev->base_addr +x);
+        write_nic_dword(priv, WCAMI, data);
+        write_nic_dword(priv, RWCAM, BIT31|BIT16|(addr&0xff) );
 }
 
-void write_nic_dword(struct net_device *dev, int x,u32 y)
+u32 read_cam(struct r8192_priv *priv, u8 addr)
 {
-        outl(y,dev->base_addr +x);
+        write_nic_dword(priv, RWCAM, 0x80000000|(addr&0xff) );
+        return read_nic_dword(priv, 0xa8);
 }
 
-#else /* RTL_IO_MAP */
-
-u8 read_nic_byte(struct net_device *dev, int x)
+u8 read_nic_byte(struct r8192_priv *priv, int x)
 {
-        return 0xff&readb((u8*)dev->mem_start +x);
+        return 0xff & readb(priv->mem_start + x);
 }
 
-u32 read_nic_dword(struct net_device *dev, int x)
+u32 read_nic_dword(struct r8192_priv *priv, int x)
 {
-        return readl((u8*)dev->mem_start +x);
+        return readl(priv->mem_start + x);
 }
 
-u16 read_nic_word(struct net_device *dev, int x)
+u16 read_nic_word(struct r8192_priv *priv, int x)
 {
-        return readw((u8*)dev->mem_start +x);
+        return readw(priv->mem_start + x);
 }
 
-void write_nic_byte(struct net_device *dev, int x,u8 y)
+void write_nic_byte(struct r8192_priv *priv, int x,u8 y)
 {
-        writeb(y,(u8*)dev->mem_start +x);
+        writeb(y, priv->mem_start + x);
 	udelay(20);
 }
 
-void write_nic_dword(struct net_device *dev, int x,u32 y)
+void write_nic_dword(struct r8192_priv *priv, int x,u32 y)
 {
-        writel(y,(u8*)dev->mem_start +x);
+        writel(y, priv->mem_start + x);
 	udelay(20);
 }
 
-void write_nic_word(struct net_device *dev, int x,u16 y)
+void write_nic_word(struct r8192_priv *priv, int x,u16 y)
 {
-        writew(y,(u8*)dev->mem_start +x);
+        writew(y, priv->mem_start + x);
 	udelay(20);
 }
 
-#endif /* RTL_IO_MAP */
-
 u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
 {
 	static const u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
@@ -362,23 +271,22 @@ u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
 	}
 }
 
-void
-rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
+void rtl8192e_SetHwReg(struct ieee80211_device *ieee80211, u8 variable, u8 *val)
 {
-	struct r8192_priv* priv = ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
 
 	switch(variable)
 	{
 
 		case HW_VAR_BSSID:
-			write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]);
-			write_nic_word(dev, BSSIDR+2, ((u16*)(val+2))[0]);
+			write_nic_dword(priv, BSSIDR, ((u32*)(val))[0]);
+			write_nic_word(priv, BSSIDR+2, ((u16*)(val+2))[0]);
 		break;
 
 		case HW_VAR_MEDIA_STATUS:
 		{
 			RT_OP_MODE	OpMode = *((RT_OP_MODE *)(val));
-			u8		btMsr = read_nic_byte(dev, MSR);
+			u8		btMsr = read_nic_byte(priv, MSR);
 
 			btMsr &= 0xfc;
 
@@ -401,16 +309,16 @@ rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
 				break;
 			}
 
-			write_nic_byte(dev, MSR, btMsr);
+			write_nic_byte(priv, MSR, btMsr);
 		}
 		break;
 
-		case HW_VAR_CECHK_BSSID:
+		case HW_VAR_CHECK_BSSID:
 		{
 			u32	RegRCR, Type;
 
 			Type = ((u8*)(val))[0];
-			RegRCR = read_nic_dword(dev,RCR);
+			RegRCR = read_nic_dword(priv, RCR);
 			priv->ReceiveConfig = RegRCR;
 
 			if (Type == true)
@@ -418,7 +326,7 @@ rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
 			else if (Type == false)
 				RegRCR &= (~RCR_CBSSID);
 
-			write_nic_dword(dev, RCR,RegRCR);
+			write_nic_dword(priv, RCR,RegRCR);
 			priv->ReceiveConfig = RegRCR;
 
 		}
@@ -427,7 +335,7 @@ rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
 		case HW_VAR_SLOT_TIME:
 		{
 			priv->slot_time = val[0];
-			write_nic_byte(dev, SLOT_TIME, val[0]);
+			write_nic_byte(priv, SLOT_TIME, val[0]);
 
 		}
 		break;
@@ -439,12 +347,12 @@ rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
 			regTmp = priv->basic_rate;
 			if (priv->short_preamble)
 				regTmp |= BRSR_AckShortPmb;
-			write_nic_dword(dev, RRSR, regTmp);
+			write_nic_dword(priv, RRSR, regTmp);
 		}
 		break;
 
 		case HW_VAR_CPU_RST:
-			write_nic_dword(dev, CPU_GEN, ((u32*)(val))[0]);
+			write_nic_dword(priv, CPU_GEN, ((u32*)(val))[0]);
 		break;
 
 		default:
@@ -459,8 +367,7 @@ static int proc_get_stats_ap(char *page, char **start,
 			  off_t offset, int count,
 			  int *eof, void *data)
 {
-	struct net_device *dev = data;
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = data;
 	struct ieee80211_device *ieee = priv->ieee80211;
 	struct ieee80211_network *target;
 	int len = 0;
@@ -489,7 +396,7 @@ static int proc_get_registers(char *page, char **start,
 			  off_t offset, int count,
 			  int *eof, void *data)
 {
-	struct net_device *dev = data;
+	struct r8192_priv *priv = data;
 	int len = 0;
 	int i,n;
 	int max=0xff;
@@ -505,7 +412,7 @@ static int proc_get_registers(char *page, char **start,
 
 		for(i=0;i<16 && n<=max;i++,n++)
 		len += snprintf(page + len, count - len,
-			"%2x ",read_nic_byte(dev,n));
+			"%2x ",read_nic_byte(priv,n));
 	}
 	len += snprintf(page + len, count - len,"\n");
 	len += snprintf(page + len, count - len,
@@ -517,7 +424,7 @@ static int proc_get_registers(char *page, char **start,
 
                 for(i=0;i<16 && n<=max;i++,n++)
                 len += snprintf(page + len, count - len,
-                        "%2x ",read_nic_byte(dev,0x100|n));
+                        "%2x ",read_nic_byte(priv,0x100|n));
         }
 
 	len += snprintf(page + len, count - len,
@@ -529,7 +436,7 @@ static int proc_get_registers(char *page, char **start,
 
                 for(i=0;i<16 && n<=max;i++,n++)
                 len += snprintf(page + len, count - len,
-                        "%2x ",read_nic_byte(dev,0x300|n));
+                        "%2x ",read_nic_byte(priv,0x300|n));
         }
 
 	*eof = 1;
@@ -541,78 +448,35 @@ static int proc_get_stats_tx(char *page, char **start,
 			  off_t offset, int count,
 			  int *eof, void *data)
 {
-	struct net_device *dev = data;
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = data;
 
 	int len = 0;
 
 	len += snprintf(page + len, count - len,
 		"TX VI priority ok int: %lu\n"
-//		"TX VI priority error int: %lu\n"
 		"TX VO priority ok int: %lu\n"
-//		"TX VO priority error int: %lu\n"
 		"TX BE priority ok int: %lu\n"
-//		"TX BE priority error int: %lu\n"
 		"TX BK priority ok int: %lu\n"
-//		"TX BK priority error int: %lu\n"
 		"TX MANAGE priority ok int: %lu\n"
-//		"TX MANAGE priority error int: %lu\n"
 		"TX BEACON priority ok int: %lu\n"
 		"TX BEACON priority error int: %lu\n"
 		"TX CMDPKT priority ok int: %lu\n"
-//		"TX high priority ok int: %lu\n"
-//		"TX high priority failed error int: %lu\n"
-//		"TX queue resume: %lu\n"
 		"TX queue stopped?: %d\n"
 		"TX fifo overflow: %lu\n"
-//		"TX beacon: %lu\n"
-//		"TX VI queue: %d\n"
-//		"TX VO queue: %d\n"
-//		"TX BE queue: %d\n"
-//		"TX BK queue: %d\n"
-//		"TX HW queue: %d\n"
-//		"TX VI dropped: %lu\n"
-//		"TX VO dropped: %lu\n"
-//		"TX BE dropped: %lu\n"
-//		"TX BK dropped: %lu\n"
 		"TX total data packets %lu\n"
 		"TX total data bytes :%lu\n",
-//		"TX beacon aborted: %lu\n",
 		priv->stats.txviokint,
-//		priv->stats.txvierr,
 		priv->stats.txvookint,
-//		priv->stats.txvoerr,
 		priv->stats.txbeokint,
-//		priv->stats.txbeerr,
 		priv->stats.txbkokint,
-//		priv->stats.txbkerr,
 		priv->stats.txmanageokint,
-//		priv->stats.txmanageerr,
 		priv->stats.txbeaconokint,
 		priv->stats.txbeaconerr,
 		priv->stats.txcmdpktokint,
-//		priv->stats.txhpokint,
-//		priv->stats.txhperr,
-//		priv->stats.txresumed,
-		netif_queue_stopped(dev),
+		netif_queue_stopped(priv->ieee80211->dev),
 		priv->stats.txoverflow,
-//		priv->stats.txbeacon,
-//		atomic_read(&(priv->tx_pending[VI_QUEUE])),
-//		atomic_read(&(priv->tx_pending[VO_QUEUE])),
-//		atomic_read(&(priv->tx_pending[BE_QUEUE])),
-//		atomic_read(&(priv->tx_pending[BK_QUEUE])),
-//		read_nic_byte(dev, TXFIFOCOUNT),
-//		priv->stats.txvidrop,
-//		priv->stats.txvodrop,
 		priv->ieee80211->stats.tx_packets,
-		priv->ieee80211->stats.tx_bytes
-
-
-//		priv->stats.txbedrop,
-//		priv->stats.txbkdrop
-			//	priv->stats.txdatapkt
-//		priv->stats.txbeaconerr
-		);
+		priv->ieee80211->stats.tx_bytes);
 
 	*eof = 1;
 	return len;
@@ -624,20 +488,16 @@ static int proc_get_stats_rx(char *page, char **start,
 			  off_t offset, int count,
 			  int *eof, void *data)
 {
-	struct net_device *dev = data;
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-
+	struct r8192_priv *priv = data;
 	int len = 0;
 
 	len += snprintf(page + len, count - len,
 		"RX packets: %lu\n"
 		"RX desc err: %lu\n"
-		"RX rx overflow error: %lu\n"
-		"RX invalid urb error: %lu\n",
+		"RX rx overflow error: %lu\n",
 		priv->stats.rxint,
 		priv->stats.rxrdu,
-		priv->stats.rxoverflow,
-		priv->stats.rxurberr);
+		priv->stats.rxoverflow);
 
 	*eof = 1;
 	return len;
@@ -645,7 +505,7 @@ static int proc_get_stats_rx(char *page, char **start,
 
 static void rtl8192_proc_module_init(void)
 {
-	RT_TRACE(COMP_INIT, "Initializing proc filesystem");
+	RT_TRACE(COMP_INIT, "Initializing proc filesystem\n");
 	rtl8192_proc=create_proc_entry(RTL819xE_MODULE_NAME, S_IFDIR, init_net.proc_net);
 }
 
@@ -656,32 +516,28 @@ static void rtl8192_proc_module_remove(void)
 }
 
 
-static void rtl8192_proc_remove_one(struct net_device *dev)
+static void rtl8192_proc_remove_one(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct net_device *dev = priv->ieee80211->dev;
 
 	printk("dev name=======> %s\n",dev->name);
 
 	if (priv->dir_dev) {
-	//	remove_proc_entry("stats-hw", priv->dir_dev);
 		remove_proc_entry("stats-tx", priv->dir_dev);
 		remove_proc_entry("stats-rx", priv->dir_dev);
-	//	remove_proc_entry("stats-ieee", priv->dir_dev);
 		remove_proc_entry("stats-ap", priv->dir_dev);
 		remove_proc_entry("registers", priv->dir_dev);
-	//	remove_proc_entry("cck-registers",priv->dir_dev);
-	//	remove_proc_entry("ofdm-registers",priv->dir_dev);
-		//remove_proc_entry(dev->name, rtl8192_proc);
 		remove_proc_entry("wlan0", rtl8192_proc);
 		priv->dir_dev = NULL;
 	}
 }
 
 
-static void rtl8192_proc_init_one(struct net_device *dev)
+static void rtl8192_proc_init_one(struct r8192_priv *priv)
 {
+	struct net_device *dev = priv->ieee80211->dev;
 	struct proc_dir_entry *e;
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+
 	priv->dir_dev = create_proc_entry(dev->name,
 					  S_IFDIR | S_IRUGO | S_IXUGO,
 					  rtl8192_proc);
@@ -691,7 +547,7 @@ static void rtl8192_proc_init_one(struct net_device *dev)
 		return;
 	}
 	e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_rx, dev);
+				   priv->dir_dev, proc_get_stats_rx, priv);
 
 	if (!e) {
 		RT_TRACE(COMP_ERR,"Unable to initialize "
@@ -701,7 +557,7 @@ static void rtl8192_proc_init_one(struct net_device *dev)
 
 
 	e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_tx, dev);
+				   priv->dir_dev, proc_get_stats_tx, priv);
 
 	if (!e) {
 		RT_TRACE(COMP_ERR, "Unable to initialize "
@@ -710,7 +566,7 @@ static void rtl8192_proc_init_one(struct net_device *dev)
 	}
 
 	e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_stats_ap, dev);
+				   priv->dir_dev, proc_get_stats_ap, priv);
 
 	if (!e) {
 		RT_TRACE(COMP_ERR, "Unable to initialize "
@@ -719,7 +575,7 @@ static void rtl8192_proc_init_one(struct net_device *dev)
 	}
 
 	e = create_proc_read_entry("registers", S_IFREG | S_IRUGO,
-				   priv->dir_dev, proc_get_registers, dev);
+				   priv->dir_dev, proc_get_registers, priv);
 	if (!e) {
 		RT_TRACE(COMP_ERR, "Unable to initialize "
 		      "/proc/net/rtl8192/%s/registers\n",
@@ -727,9 +583,9 @@ static void rtl8192_proc_init_one(struct net_device *dev)
 	}
 }
 
-short check_nic_enough_desc(struct net_device *dev, int prio)
+static short check_nic_enough_desc(struct ieee80211_device *ieee, int prio)
 {
-    struct r8192_priv *priv = ieee80211_priv(dev);
+    struct r8192_priv *priv = ieee80211_priv(ieee->dev);
     struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
 
     /* for now we reserve two free descriptor as a safety boundary
@@ -746,27 +602,29 @@ static void tx_timeout(struct net_device *dev)
 	printk("TXTIMEOUT");
 }
 
-static void rtl8192_irq_enable(struct net_device *dev)
+static void rtl8192_irq_enable(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-	priv->irq_enabled = 1;
-	write_nic_dword(dev,INTA_MASK, priv->irq_mask);
+	u32 mask;
+
+	mask = IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK |
+	       IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK |
+	       IMR_BDOK | IMR_RXCMDOK | IMR_TIMEOUT0 | IMR_RDU | IMR_RXFOVW |
+	       IMR_TXFOVW | IMR_BcnInt | IMR_TBDOK | IMR_TBDER;
+
+	write_nic_dword(priv, INTA_MASK, mask);
 }
 
-void rtl8192_irq_disable(struct net_device *dev)
+static void rtl8192_irq_disable(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-
-	write_nic_dword(dev,INTA_MASK,0);
-	priv->irq_enabled = 0;
+	write_nic_dword(priv, INTA_MASK, 0);
+	synchronize_irq(priv->irq);
 }
 
-void rtl8192_update_msr(struct net_device *dev)
+static void rtl8192_update_msr(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 msr;
 
-	msr  = read_nic_byte(dev, MSR);
+	msr  = read_nic_byte(priv, MSR);
 	msr &= ~ MSR_LINK_MASK;
 
 	/* do not change in link_state != WLAN_LINK_ASSOCIATED.
@@ -786,26 +644,24 @@ void rtl8192_update_msr(struct net_device *dev)
 	}else
 		msr |= (MSR_LINK_NONE<<MSR_LINK_SHIFT);
 
-	write_nic_byte(dev, MSR, msr);
+	write_nic_byte(priv, MSR, msr);
 }
 
-void rtl8192_set_chan(struct net_device *dev,short ch)
+static void rtl8192_set_chan(struct ieee80211_device *ieee80211, short ch)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
 
 	priv->chan = ch;
 
 	/* need to implement rf set channel here WB */
 
 	if (priv->rf_set_chan)
-		priv->rf_set_chan(dev, priv->chan);
+		priv->rf_set_chan(ieee80211, priv->chan);
 }
 
-void rtl8192_rx_enable(struct net_device *dev)
+static void rtl8192_rx_enable(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-
-	write_nic_dword(dev, RDQDA,priv->rx_ring_dma);
+	write_nic_dword(priv, RDQDA, priv->rx_ring_dma);
 }
 
 /* the TX_DESC_BASE setting is according to the following queue index
@@ -820,21 +676,19 @@ void rtl8192_rx_enable(struct net_device *dev)
  *  BEACON_QUEUE   ===>                        8
  *  */
 static const u32 TX_DESC_BASE[] = {BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA};
-void rtl8192_tx_enable(struct net_device *dev)
+static void rtl8192_tx_enable(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	u32 i;
 
 	for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
-		write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
+		write_nic_dword(priv, TX_DESC_BASE[i], priv->tx_ring[i].dma);
 
 	ieee80211_reset_queue(priv->ieee80211);
 }
 
 
-static void rtl8192_free_rx_ring(struct net_device *dev)
+static void rtl8192_free_rx_ring(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	int i;
 
 	for (i = 0; i < priv->rxringcount; i++) {
@@ -853,9 +707,8 @@ static void rtl8192_free_rx_ring(struct net_device *dev)
 	priv->rx_ring = NULL;
 }
 
-static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
+static void rtl8192_free_tx_ring(struct r8192_priv *priv, unsigned int prio)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
 
 	while (skb_queue_len(&ring->queue)) {
@@ -873,42 +726,40 @@ static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
 	ring->desc = NULL;
 }
 
-void PHY_SetRtl8192eRfOff(struct net_device* dev)
+void PHY_SetRtl8192eRfOff(struct r8192_priv *priv)
 {
 	//disable RF-Chip A/B
-	rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+	rtl8192_setBBreg(priv, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
 	//analog to digital off, for power save
-	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x0);
 	//digital to analog off, for power save
-	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x18, 0x0);
 	//rx antenna off
-	rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+	rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0xf, 0x0);
 	//rx antenna off
-	rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+	rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0xf, 0x0);
 	//analog to digital part2 off, for power save
-	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
-	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x60, 0x0);
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x4, 0x0);
 	// Analog parameter!!Change bias and Lbus control.
-	write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
-
+	write_nic_byte(priv, ANAPAR_FOR_8192PciE, 0x07);
 }
 
-void rtl8192_halt_adapter(struct net_device *dev, bool reset)
+static void rtl8192_halt_adapter(struct r8192_priv *priv, bool reset)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	int i;
 	u8 OpMode;
 	u32 ulRegRead;
 
 	OpMode = RT_OP_MODE_NO_LINK;
-	priv->ieee80211->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
+	priv->ieee80211->SetHwRegHandler(priv->ieee80211, HW_VAR_MEDIA_STATUS, &OpMode);
 
 	if (!priv->ieee80211->bSupportRemoteWakeUp) {
 		/*
 		 * disable tx/rx. In 8185 we write 0x10 (Reset bit),
 		 * but here we make reference to WMAC and wirte 0x0
 		 */
-		write_nic_byte(dev, CMDR, 0);
+		write_nic_byte(priv, CMDR, 0);
 	}
 
 	mdelay(20);
@@ -916,29 +767,27 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset)
 	if (!reset) {
 		mdelay(150);
 
-#ifdef RTL8192E
 		priv->bHwRfOffAction = 2;
-#endif
 
 		/*
 		 * Call MgntActSet_RF_State instead to
 		 * prevent RF config race condition.
 		 */
 		if (!priv->ieee80211->bSupportRemoteWakeUp) {
-			PHY_SetRtl8192eRfOff(dev);
-			ulRegRead = read_nic_dword(dev,CPU_GEN);
+			PHY_SetRtl8192eRfOff(priv);
+			ulRegRead = read_nic_dword(priv, CPU_GEN);
 			ulRegRead |= CPU_GEN_SYSTEM_RESET;
-			write_nic_dword(dev,CPU_GEN, ulRegRead);
+			write_nic_dword(priv,CPU_GEN, ulRegRead);
 		} else {
 			/* for WOL */
-			write_nic_dword(dev, WFCRC0, 0xffffffff);
-			write_nic_dword(dev, WFCRC1, 0xffffffff);
-			write_nic_dword(dev, WFCRC2, 0xffffffff);
+			write_nic_dword(priv, WFCRC0, 0xffffffff);
+			write_nic_dword(priv, WFCRC1, 0xffffffff);
+			write_nic_dword(priv, WFCRC2, 0xffffffff);
 
 			/* Write PMR register */
-			write_nic_byte(dev, PMR, 0x5);
+			write_nic_byte(priv, PMR, 0x5);
 			/* Disable tx, enanble rx */
-			write_nic_byte(dev, MacBlkCtrl, 0xa);
+			write_nic_byte(priv, MacBlkCtrl, 0xa);
 		}
 	}
 
@@ -952,18 +801,11 @@ void rtl8192_halt_adapter(struct net_device *dev, bool reset)
 	skb_queue_purge(&priv->skb_queue);
 }
 
-static const u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
-inline u16 rtl8192_rate2rate(short rate)
-{
-	if (rate >11) return 0;
-	return rtl_rate[rate];
-}
-
-static void rtl8192_data_hard_stop(struct net_device *dev)
+static void rtl8192_data_hard_stop(struct ieee80211_device *ieee80211)
 {
 }
 
-static void rtl8192_data_hard_resume(struct net_device *dev)
+static void rtl8192_data_hard_resume(struct ieee80211_device *ieee80211)
 {
 }
 
@@ -971,15 +813,16 @@ static void rtl8192_data_hard_resume(struct net_device *dev)
  * this function TX data frames when the ieee80211 stack requires this.
  * It checks also if we need to stop the ieee tx queue, eventually do it
  */
-static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate)
+static void rtl8192_hard_data_xmit(struct sk_buff *skb,
+				   struct ieee80211_device *ieee80211, int rate)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
 	int ret;
 	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 	u8 queue_index = tcb_desc->queue_index;
 
 	/* shall not be referred by command packet */
-	assert(queue_index != TXCMD_QUEUE);
+	BUG_ON(queue_index == TXCMD_QUEUE);
 
 	if (priv->bHwRadioOff || (!priv->up))
 	{
@@ -987,10 +830,8 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
 		return;
 	}
 
-	memcpy(skb->cb, &dev, sizeof(dev));
-
 	skb_push(skb, priv->ieee80211->tx_headroom);
-	ret = rtl8192_tx(dev, skb);
+	ret = rtl8192_tx(priv, skb);
 	if (ret != 0) {
 		kfree_skb(skb);
 	}
@@ -1007,9 +848,9 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
  * If the ring is full packet are dropped (for data frame the queue
  * is stopped before this can happen).
  */
-static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
+static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct ieee80211_device *ieee80211)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
 	int ret;
         cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
         u8 queue_index = tcb_desc->queue_index;
@@ -1022,9 +863,8 @@ static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
 		}
         }
 
-        memcpy(skb->cb, &dev, sizeof(dev));
 	if (queue_index == TXCMD_QUEUE) {
-		rtl819xE_tx_cmd(dev, skb);
+		rtl819xE_tx_cmd(priv, skb);
 		ret = 0;
 		return ret;
 	} else {
@@ -1032,8 +872,8 @@ static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
 		tcb_desc->bTxDisableRateFallBack = 1;
 		tcb_desc->bTxUseDriverAssingedRate = 1;
 		tcb_desc->bTxEnableFwCalcDur = 1;
-		skb_push(skb, priv->ieee80211->tx_headroom);
-		ret = rtl8192_tx(dev, skb);
+		skb_push(skb, ieee80211->tx_headroom);
+		ret = rtl8192_tx(priv, skb);
 		if (ret != 0) {
 			kfree_skb(skb);
 		}
@@ -1043,9 +883,8 @@ static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
 }
 
 
-static void rtl8192_tx_isr(struct net_device *dev, int prio)
+static void rtl8192_tx_isr(struct r8192_priv *priv, int prio)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	struct rtl8192_tx_ring *ring = &priv->tx_ring[prio];
 
 	while (skb_queue_len(&ring->queue)) {
@@ -1068,14 +907,6 @@ static void rtl8192_tx_isr(struct net_device *dev, int prio)
 
 		kfree_skb(skb);
 	}
-	if (prio == MGNT_QUEUE) {
-		if (priv->ieee80211->ack_tx_to_ieee) {
-			if (rtl8192_is_tx_queue_empty(dev)) {
-				priv->ieee80211->ack_tx_to_ieee = 0;
-				ieee80211_ps_tx_ack(priv->ieee80211, 1);
-			}
-		}
-	}
 
 	if (prio != BEACON_QUEUE) {
 		/* try to deal with the pending packets  */
@@ -1083,13 +914,12 @@ static void rtl8192_tx_isr(struct net_device *dev, int prio)
 	}
 }
 
-static void rtl8192_stop_beacon(struct net_device *dev)
+static void rtl8192_stop_beacon(struct ieee80211_device *ieee80211)
 {
 }
 
-static void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
+static void rtl8192_config_rate(struct r8192_priv *priv, u16* rate_config)
 {
-	 struct r8192_priv *priv = ieee80211_priv(dev);
 	 struct ieee80211_network *net;
 	 u8 i=0, basic_rate = 0;
 	 net = & priv->ieee80211->current_network;
@@ -1138,16 +968,16 @@ static void rtl8192_config_rate(struct net_device* dev, u16* rate_config)
 #define SHORT_SLOT_TIME 9
 #define NON_SHORT_SLOT_TIME 20
 
-static void rtl8192_update_cap(struct net_device* dev, u16 cap)
+static void rtl8192_update_cap(struct r8192_priv *priv, u16 cap)
 {
 	u32 tmp = 0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_network *net = &priv->ieee80211->current_network;
+
 	priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE;
 	tmp = priv->basic_rate;
 	if (priv->short_preamble)
 		tmp |= BRSR_AckShortPmb;
-	write_nic_dword(dev, RRSR, tmp);
+	write_nic_dword(priv, RRSR, tmp);
 
 	if (net->mode & (IEEE_G|IEEE_N_24G))
 	{
@@ -1159,21 +989,20 @@ static void rtl8192_update_cap(struct net_device* dev, u16 cap)
 		else //long slot time
 			slot_time = NON_SHORT_SLOT_TIME;
 		priv->slot_time = slot_time;
-		write_nic_byte(dev, SLOT_TIME, slot_time);
+		write_nic_byte(priv, SLOT_TIME, slot_time);
 	}
 
 }
 
-static void rtl8192_net_update(struct net_device *dev)
+static void rtl8192_net_update(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_network *net;
 	u16 BcnTimeCfg = 0, BcnCW = 6, BcnIFS = 0xf;
 	u16 rate_config = 0;
 	net = &priv->ieee80211->current_network;
 
 	/* update Basic rate: RR, BRSR */
-	rtl8192_config_rate(dev, &rate_config);
+	rtl8192_config_rate(priv, &rate_config);
 
 	/*
 	 * Select RRSR (in Legacy-OFDM and CCK)
@@ -1184,31 +1013,30 @@ static void rtl8192_net_update(struct net_device *dev)
 	priv->basic_rate = rate_config &= 0x15f;
 
 	/* BSSID */
-	write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
-	write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+	write_nic_dword(priv, BSSIDR, ((u32 *)net->bssid)[0]);
+	write_nic_word(priv, BSSIDR+4, ((u16 *)net->bssid)[2]);
 
 	if (priv->ieee80211->iw_mode == IW_MODE_ADHOC)
 	{
-		write_nic_word(dev, ATIMWND, 2);
-		write_nic_word(dev, BCN_DMATIME, 256);
-		write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
+		write_nic_word(priv, ATIMWND, 2);
+		write_nic_word(priv, BCN_DMATIME, 256);
+		write_nic_word(priv, BCN_INTERVAL, net->beacon_interval);
 		/*
 		 * BIT15 of BCN_DRV_EARLY_INT will indicate
 		 * whether software beacon or hw beacon is applied.
 		 */
-		write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
-		write_nic_byte(dev, BCN_ERR_THRESH, 100);
+		write_nic_word(priv, BCN_DRV_EARLY_INT, 10);
+		write_nic_byte(priv, BCN_ERR_THRESH, 100);
 
 		BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
 		/* TODO: BcnIFS may required to be changed on ASIC */
 		BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
-		write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+		write_nic_word(priv, BCN_TCFG, BcnTimeCfg);
 	}
 }
 
-void rtl819xE_tx_cmd(struct net_device *dev, struct sk_buff *skb)
+static void rtl819xE_tx_cmd(struct r8192_priv *priv, struct sk_buff *skb)
 {
-    struct r8192_priv *priv = ieee80211_priv(dev);
     struct rtl8192_tx_ring *ring;
     tx_desc_819x_pci *entry;
     unsigned int idx;
@@ -1242,20 +1070,10 @@ void rtl819xE_tx_cmd(struct net_device *dev, struct sk_buff *skb)
     entry->TxBuffAddr = cpu_to_le32(mapping);
     entry->OWN = 1;
 
-#ifdef JOHN_DUMP_TXDESC
-    {       int i;
-        tx_desc_819x_pci *entry1 =  &ring->desc[0];
-        unsigned int *ptr= (unsigned int *)entry1;
-        printk("<Tx descriptor>:\n");
-        for (i = 0; i < 8; i++)
-            printk("%8x ", ptr[i]);
-        printk("\n");
-    }
-#endif
     __skb_queue_tail(&ring->queue, skb);
     spin_unlock_irqrestore(&priv->irq_th_lock,flags);
 
-    write_nic_byte(dev, TPPoll, TPPoll_CQ);
+    write_nic_byte(priv, TPPoll, TPPoll_CQ);
 
     return;
 }
@@ -1365,9 +1183,8 @@ static u8 QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc)
  * skb->cb will contain all the following information,
  * priority, morefrag, rate, &dev.
  */
-short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
+static short rtl8192_tx(struct r8192_priv *priv, struct sk_buff* skb)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct rtl8192_tx_ring *ring;
 	unsigned long flags;
 	cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
@@ -1401,10 +1218,6 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
 
 	if (uni_addr)
 		priv->stats.txbytesunicast += (u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
-	else if (multi_addr)
-		priv->stats.txbytesmulticast += (u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
-	else
-		priv->stats.txbytesbroadcast += (u8)(skb->len) - sizeof(TX_FWINFO_8190PCI);
 
 	/* fill tx firmware */
 	pTxFwInfo = (PTX_FWINFO_8190PCI)skb->data;
@@ -1439,12 +1252,8 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
 	if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) {
 		if (tcb_desc->bPacketBW) {
 			pTxFwInfo->TxBandwidth = 1;
-#ifdef RTL8190P
-			pTxFwInfo->TxSubCarrier = 3;
-#else
 			/* use duplicated mode */
 			pTxFwInfo->TxSubCarrier = 0;
-#endif
 		} else {
 			pTxFwInfo->TxBandwidth = 0;
 			pTxFwInfo->TxSubCarrier = priv->nCur40MhzPrimeSC;
@@ -1463,7 +1272,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
 
 	pdesc = &ring->desc[idx];
 	if ((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
-		RT_TRACE(COMP_ERR, "No more TX desc@%d, ring->idx = %d,idx = %d,%x",
+		RT_TRACE(COMP_ERR, "No more TX desc@%d, ring->idx = %d,idx = %d,%x\n",
 			 tcb_desc->queue_index, ring->idx, idx, skb->len);
 		spin_unlock_irqrestore(&priv->irq_th_lock, flags);
 		return skb->len;
@@ -1523,14 +1332,13 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
 	__skb_queue_tail(&ring->queue, skb);
 	pdesc->OWN = 1;
 	spin_unlock_irqrestore(&priv->irq_th_lock, flags);
-	dev->trans_start = jiffies;
-	write_nic_word(dev, TPPoll, 0x01<<tcb_desc->queue_index);
+	priv->ieee80211->dev->trans_start = jiffies;
+	write_nic_word(priv, TPPoll, 0x01<<tcb_desc->queue_index);
 	return 0;
 }
 
-static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
+static short rtl8192_alloc_rx_desc_ring(struct r8192_priv *priv)
 {
-    struct r8192_priv *priv = ieee80211_priv(dev);
     rx_desc_819x_pci *entry = NULL;
     int i;
 
@@ -1566,10 +1374,9 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
     return 0;
 }
 
-static int rtl8192_alloc_tx_desc_ring(struct net_device *dev,
+static int rtl8192_alloc_tx_desc_ring(struct r8192_priv *priv,
         unsigned int prio, unsigned int entries)
 {
-    struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
     tx_desc_819x_pci *ring;
     dma_addr_t dma;
     int i;
@@ -1594,19 +1401,18 @@ static int rtl8192_alloc_tx_desc_ring(struct net_device *dev,
     return 0;
 }
 
-static short rtl8192_pci_initdescring(struct net_device *dev)
+static short rtl8192_pci_initdescring(struct r8192_priv *priv)
 {
 	u32 ret;
 	int i;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
-	ret = rtl8192_alloc_rx_desc_ring(dev);
+	ret = rtl8192_alloc_rx_desc_ring(priv);
 	if (ret)
 		return ret;
 
 	/* general process for other queue */
 	for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
-		ret = rtl8192_alloc_tx_desc_ring(dev, i, priv->txringcount);
+		ret = rtl8192_alloc_tx_desc_ring(priv, i, priv->txringcount);
 		if (ret)
 			goto err_free_rings;
 	}
@@ -1614,16 +1420,15 @@ static short rtl8192_pci_initdescring(struct net_device *dev)
 	return 0;
 
 err_free_rings:
-	rtl8192_free_rx_ring(dev);
+	rtl8192_free_rx_ring(priv);
 	for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
 		if (priv->tx_ring[i].desc)
-			rtl8192_free_tx_ring(dev, i);
+			rtl8192_free_tx_ring(priv, i);
 	return 1;
 }
 
-static void rtl8192_pci_resetdescring(struct net_device *dev)
+static void rtl8192_pci_resetdescring(struct r8192_priv *priv)
 {
-    struct r8192_priv *priv = ieee80211_priv(dev);
     int i;
 
     /* force the rx_idx to the first one */
@@ -1656,41 +1461,37 @@ static void rtl8192_pci_resetdescring(struct net_device *dev)
     }
 }
 
-static void rtl8192_link_change(struct net_device *dev)
+static void rtl8192_link_change(struct ieee80211_device *ieee)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device* ieee = priv->ieee80211;
-	//write_nic_word(dev, BCN_INTR_ITV, net->beacon_interval);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
+
 	if (ieee->state == IEEE80211_LINKED)
 	{
-		rtl8192_net_update(dev);
-		rtl8192_update_ratr_table(dev);
-#if 1
+		rtl8192_net_update(priv);
+		rtl8192_update_ratr_table(priv);
+
 		//add this as in pure N mode, wep encryption will use software way, but there is no chance to set this as wep will not set group key in wext. WB.2008.07.08
 		if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type))
-		EnableHWSecurityConfig8192(dev);
-#endif
+		EnableHWSecurityConfig8192(priv);
 	}
 	else
 	{
-		write_nic_byte(dev, 0x173, 0);
+		write_nic_byte(priv, 0x173, 0);
 	}
-	/*update timing params*/
-	//rtl8192_set_chan(dev, priv->chan);
-	//MSR
-	rtl8192_update_msr(dev);
+
+	rtl8192_update_msr(priv);
 
 	// 2007/10/16 MH MAC Will update TSF according to all received beacon, so we have
 	//	// To set CBSSID bit when link with any AP or STA.
 	if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC)
 	{
 		u32 reg = 0;
-		reg = read_nic_dword(dev, RCR);
+		reg = read_nic_dword(priv, RCR);
 		if (priv->ieee80211->state == IEEE80211_LINKED)
 			priv->ReceiveConfig = reg |= RCR_CBSSID;
 		else
 			priv->ReceiveConfig = reg &= ~RCR_CBSSID;
-		write_nic_dword(dev, RCR, reg);
+		write_nic_dword(priv, RCR, reg);
 	}
 }
 
@@ -1706,14 +1507,13 @@ static const struct ieee80211_qos_parameters def_qos_parameters = {
 static void rtl8192_update_beacon(struct work_struct * work)
 {
         struct r8192_priv *priv = container_of(work, struct r8192_priv, update_beacon_wq.work);
-        struct net_device *dev = priv->ieee80211->dev;
  	struct ieee80211_device* ieee = priv->ieee80211;
 	struct ieee80211_network* net = &ieee->current_network;
 
 	if (ieee->pHTInfo->bCurrentHTSupport)
 		HTUpdateSelfAndPeerSetting(ieee, net);
 	ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime;
-	rtl8192_update_cap(dev, net->capability);
+	rtl8192_update_cap(priv, net->capability);
 }
 
 /*
@@ -1723,7 +1523,6 @@ static const int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_
 static void rtl8192_qos_activate(struct work_struct * work)
 {
         struct r8192_priv *priv = container_of(work, struct r8192_priv, qos_activate);
-        struct net_device *dev = priv->ieee80211->dev;
         struct ieee80211_qos_parameters *qos_parameters = &priv->ieee80211->current_network.qos_data.parameters;
         u8 mode = priv->ieee80211->current_network.mode;
 	u8  u1bAIFS;
@@ -1744,9 +1543,7 @@ static void rtl8192_qos_activate(struct work_struct * work)
 				(((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
 				(((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
 				((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
-		//printk("===>u4bAcParam:%x, ", u4bAcParam);
-		write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
-		//write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
+		write_nic_dword(priv, WDCAPARA_ADD[i], u4bAcParam);
 	}
 
 success:
@@ -1787,7 +1584,7 @@ static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
 
 		if ((network->qos_data.active == 1) && (active_network == 1)) {
 			queue_work(priv->priv_wq, &priv->qos_activate);
-			RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n");
+			RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate\n");
 		}
 		network->qos_data.active = 0;
 		network->qos_data.supported = 0;
@@ -1797,11 +1594,11 @@ static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv,
 }
 
 /* handle manage frame frame beacon and probe response */
-static int rtl8192_handle_beacon(struct net_device * dev,
+static int rtl8192_handle_beacon(struct ieee80211_device *ieee,
                               struct ieee80211_beacon * beacon,
                               struct ieee80211_network * network)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
 
 	rtl8192_qos_handle_probe_response(priv,1,network);
 
@@ -1863,26 +1660,25 @@ static int rtl8192_qos_association_resp(struct r8192_priv *priv,
 }
 
 
-static int rtl8192_handle_assoc_response(struct net_device *dev,
+static int rtl8192_handle_assoc_response(struct ieee80211_device *ieee,
                                      struct ieee80211_assoc_response_frame *resp,
                                      struct ieee80211_network *network)
 {
-        struct r8192_priv *priv = ieee80211_priv(dev);
+        struct r8192_priv *priv = ieee80211_priv(ieee->dev);
         rtl8192_qos_association_resp(priv, network);
         return 0;
 }
 
 
 /* updateRATRTabel for MCS only. Basic rate is not implemented. */
-static void rtl8192_update_ratr_table(struct net_device* dev)
+static void rtl8192_update_ratr_table(struct r8192_priv* priv)
 {
-	struct r8192_priv* priv = ieee80211_priv(dev);
 	struct ieee80211_device* ieee = priv->ieee80211;
 	u8* pMcsRate = ieee->dot11HTOperationalRateSet;
 	u32 ratr_value = 0;
 	u8 rate_index = 0;
 
-	rtl8192_config_rate(dev, (u16*)(&ratr_value));
+	rtl8192_config_rate(priv, (u16*)(&ratr_value));
 	ratr_value |= (*(u16*)(pMcsRate)) << 12;
 
 	switch (ieee->mode)
@@ -1916,15 +1712,12 @@ static void rtl8192_update_ratr_table(struct net_device* dev)
 	}else if(!ieee->pHTInfo->bCurTxBW40MHz && ieee->pHTInfo->bCurShortGI20MHz){
 		ratr_value |= 0x80000000;
 	}
-	write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
-	write_nic_byte(dev, UFWP, 1);
+	write_nic_dword(priv, RATR0+rate_index*4, ratr_value);
+	write_nic_byte(priv, UFWP, 1);
 }
 
-static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
+static bool GetNmodeSupportBySecCfg8190Pci(struct ieee80211_device *ieee)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	struct ieee80211_device *ieee = priv->ieee80211;
-
 	return !(ieee->rtllib_ap_sec_type &&
 		 (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP)));
 }
@@ -1936,40 +1729,21 @@ static void rtl8192_refresh_supportrate(struct r8192_priv* priv)
 	if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G)
 	{
 		memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16);
-		//RT_DEBUG_DATA(COMP_INIT, ieee->RegHTSuppRateSet, 16);
-		//RT_DEBUG_DATA(COMP_INIT, ieee->Regdot11HTOperationalRateSet, 16);
 	}
 	else
 		memset(ieee->Regdot11HTOperationalRateSet, 0, 16);
 }
 
-static u8 rtl8192_getSupportedWireleeMode(struct net_device*dev)
+static u8 rtl8192_getSupportedWireleeMode(void)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 ret = 0;
-	switch(priv->rf_chip)
-	{
-		case RF_8225:
-		case RF_8256:
-		case RF_PSEUDO_11N:
-			ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
-			break;
-		case RF_8258:
-			ret = (WIRELESS_MODE_A|WIRELESS_MODE_N_5G);
-			break;
-		default:
-			ret = WIRELESS_MODE_B;
-			break;
-	}
-	return ret;
+	return (WIRELESS_MODE_N_24G|WIRELESS_MODE_G|WIRELESS_MODE_B);
 }
 
-static void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
+static void rtl8192_SetWirelessMode(struct ieee80211_device *ieee, u8 wireless_mode)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
+	u8 bSupportMode = rtl8192_getSupportedWireleeMode();
 
-#if 1
 	if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode&bSupportMode)==0))
 	{
 		if(bSupportMode & WIRELESS_MODE_N_24G)
@@ -1997,9 +1771,6 @@ static void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
 			wireless_mode = WIRELESS_MODE_B;
 		}
 	}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
-	ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
-#endif
 	priv->ieee80211->mode = wireless_mode;
 
 	if ((wireless_mode == WIRELESS_MODE_N_24G) ||  (wireless_mode == WIRELESS_MODE_N_5G))
@@ -2008,22 +1779,18 @@ static void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
 		priv->ieee80211->pHTInfo->bEnableHT = 0;
 	RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode);
 	rtl8192_refresh_supportrate(priv);
-#endif
-
 }
 
-static bool GetHalfNmodeSupportByAPs819xPci(struct net_device* dev)
+static bool GetHalfNmodeSupportByAPs819xPci(struct ieee80211_device* ieee)
 {
-	struct r8192_priv* priv = ieee80211_priv(dev);
-	struct ieee80211_device* ieee = priv->ieee80211;
-
 	return ieee->bHalfWirelessN24GMode;
 }
 
-short rtl8192_is_tx_queue_empty(struct net_device *dev)
+static short rtl8192_is_tx_queue_empty(struct ieee80211_device *ieee)
 {
 	int i=0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
+
 	for (i=0; i<=MGNT_QUEUE; i++)
 	{
 		if ((i== TXCMD_QUEUE) || (i == HCCA_QUEUE) )
@@ -2036,69 +1803,32 @@ short rtl8192_is_tx_queue_empty(struct net_device *dev)
 	return 1;
 }
 
-static void rtl8192_hw_sleep_down(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	unsigned long flags = 0;
-
-	spin_lock_irqsave(&priv->rf_ps_lock,flags);
-	if (priv->RFChangeInProgress) {
-		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
-		RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n");
-		printk("rtl8192_hw_sleep_down(): RF Change in progress!\n");
-		return;
-	}
-	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
-
-	MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
-}
-
-static void rtl8192_hw_sleep_wq (struct work_struct *work)
+static void rtl8192_hw_sleep_down(struct r8192_priv *priv)
 {
-        struct delayed_work *dwork = container_of(work,struct delayed_work,work);
-        struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_sleep_wq);
-        struct net_device *dev = ieee->dev;
-
-        rtl8192_hw_sleep_down(dev);
+	MgntActSet_RF_State(priv, eRfSleep, RF_CHANGE_BY_PS);
 }
 
-static void rtl8192_hw_wakeup(struct net_device* dev)
+static void rtl8192_hw_wakeup(struct ieee80211_device *ieee)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	unsigned long flags = 0;
-
-	spin_lock_irqsave(&priv->rf_ps_lock,flags);
-	if (priv->RFChangeInProgress) {
-		spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
-		RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n");
-		printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n");
-		queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->hw_wakeup_wq,MSECS(10));//PowerSave is not supported if kernel version is below 2.6.20
-		return;
-	}
-	spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
-
-	MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
+	MgntActSet_RF_State(priv, eRfOn, RF_CHANGE_BY_PS);
 }
 
-void rtl8192_hw_wakeup_wq (struct work_struct *work)
+static void rtl8192_hw_wakeup_wq (struct work_struct *work)
 {
 	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
 	struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_wakeup_wq);
-	struct net_device *dev = ieee->dev;
-	rtl8192_hw_wakeup(dev);
 
+	rtl8192_hw_wakeup(ieee);
 }
 
 #define MIN_SLEEP_TIME 50
 #define MAX_SLEEP_TIME 10000
-static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
+static void rtl8192_hw_to_sleep(struct ieee80211_device *ieee, u32 th, u32 tl)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
+	u32 tmp;
 	u32 rb = jiffies;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->ps_lock,flags);
 
 	// Writing HW register with 0 equals to disable
 	// the timer, that is not really what we want
@@ -2111,7 +1841,6 @@ static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
 	//
 	if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
 			||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
-		spin_unlock_irqrestore(&priv->ps_lock,flags);
 		printk("too short to sleep::%x, %x, %lx\n",tl, rb,  MSECS(MIN_SLEEP_TIME));
 		return;
 	}
@@ -2120,26 +1849,20 @@ static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
 			((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
 			((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
 		printk("========>too long to sleep:%x, %x, %lx\n", tl, rb,  MSECS(MAX_SLEEP_TIME));
-		spin_unlock_irqrestore(&priv->ps_lock,flags);
 		return;
 	}
-	{
-		u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
-		queue_delayed_work(priv->ieee80211->wq,
-				&priv->ieee80211->hw_wakeup_wq,tmp);
-		//PowerSave not supported when kernel version less 2.6.20
-	}
+
+	tmp = (tl>rb)?(tl-rb):(rb-tl);
 	queue_delayed_work(priv->ieee80211->wq,
-			(void *)&priv->ieee80211->hw_sleep_wq,0);
-	spin_unlock_irqrestore(&priv->ps_lock,flags);
+			   &priv->ieee80211->hw_wakeup_wq,tmp);
 
+        rtl8192_hw_sleep_down(priv);
 }
 
-static void rtl8192_init_priv_variable(struct net_device* dev)
+static void rtl8192_init_priv_variable(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 i;
-	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 
 	// Default Halt the NIC if RF is OFF.
 	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
@@ -2147,27 +1870,16 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 	pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
 	pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
 	pPSC->bLeisurePs = true;
-	pPSC->RegMaxLPSAwakeIntvl = 5;
+	priv->ieee80211->RegMaxLPSAwakeIntvl = 5;
 	priv->bHwRadioOff = false;
 
 	priv->being_init_adapter = false;
-	priv->txbuffsize = 1600;//1024;
-	priv->txfwbuffersize = 4096;
 	priv->txringcount = 64;//32;
-	//priv->txbeaconcount = priv->txringcount;
-	priv->txbeaconcount = 2;
 	priv->rxbuffersize = 9100;//2048;//1024;
 	priv->rxringcount = MAX_RX_COUNT;//64;
-	priv->irq_enabled=0;
-	priv->card_8192 = NIC_8192E;
-	priv->rx_skb_complete = 1;
 	priv->chan = 1; //set to channel 1
 	priv->RegWirelessMode = WIRELESS_MODE_AUTO;
 	priv->RegChannelPlan = 0xf;
-	priv->nrxAMPDU_size = 0;
-	priv->nrxAMPDU_aggr_num = 0;
-	priv->last_rxdesc_tsf_high = 0;
-	priv->last_rxdesc_tsf_low = 0;
 	priv->ieee80211->mode = WIRELESS_MODE_AUTO; //SET AUTO
 	priv->ieee80211->iw_mode = IW_MODE_INFRA;
 	priv->ieee80211->ieee_up=0;
@@ -2176,33 +1888,22 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 	priv->ieee80211->rts = DEFAULT_RTS_THRESHOLD;
 	priv->ieee80211->rate = 110; //11 mbps
 	priv->ieee80211->short_slot = 1;
-	priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
+	priv->promisc = (priv->ieee80211->dev->flags & IFF_PROMISC) ? 1:0;
 	priv->bcck_in_ch14 = false;
-	priv->bfsync_processing  = false;
 	priv->CCKPresentAttentuation = 0;
 	priv->rfa_txpowertrackingindex = 0;
 	priv->rfc_txpowertrackingindex = 0;
 	priv->CckPwEnl = 6;
-	priv->ScanDelay = 50;//for Scan TODO
 	//added by amy for silent reset
 	priv->ResetProgress = RESET_TYPE_NORESET;
 	priv->bForcedSilentReset = 0;
 	priv->bDisableNormalResetCheck = false;
 	priv->force_reset = false;
 	//added by amy for power save
-	priv->RegRfOff = 0;
-	priv->ieee80211->RfOffReason = 0;
-	priv->RFChangeInProgress = false;
+	priv->RfOffReason = 0;
 	priv->bHwRfOffAction = 0;
-	priv->SetRFPowerStateInProgress = false;
-	priv->ieee80211->PowerSaveControl.bInactivePs = true;
-	priv->ieee80211->PowerSaveControl.bIPSModeBackup = false;
-	//just for debug
-	priv->txpower_checkcnt = 0;
-	priv->thermal_readback_index =0;
-	priv->txpower_tracking_callback_cnt = 0;
-	priv->ccktxpower_adjustcnt_ch14 = 0;
-	priv->ccktxpower_adjustcnt_not_ch14 = 0;
+	priv->PowerSaveControl.bInactivePs = true;
+	priv->PowerSaveControl.bIPSModeBackup = false;
 
 	priv->ieee80211->current_network.beacon_interval = DEFAULT_BEACONINTERVAL;
 	priv->ieee80211->iw_mode = IW_MODE_INFRA;
@@ -2215,10 +1916,8 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 	priv->ieee80211->modulation = IEEE80211_CCK_MODULATION | IEEE80211_OFDM_MODULATION;
 	priv->ieee80211->host_encrypt = 1;
 	priv->ieee80211->host_decrypt = 1;
-	//priv->ieee80211->start_send_beacons = NULL;//rtl819xusb_beacon_tx;//-by amy 080604
-	//priv->ieee80211->stop_send_beacons = NULL;//rtl8192_beacon_stop;//-by amy 080604
-	priv->ieee80211->start_send_beacons = rtl8192_start_beacon;//+by david 081107
-	priv->ieee80211->stop_send_beacons = rtl8192_stop_beacon;//+by david 081107
+	priv->ieee80211->start_send_beacons = rtl8192_start_beacon;
+	priv->ieee80211->stop_send_beacons = rtl8192_stop_beacon;
 	priv->ieee80211->softmac_hard_start_xmit = rtl8192_hard_start_xmit;
 	priv->ieee80211->set_chan = rtl8192_set_chan;
 	priv->ieee80211->link_change = rtl8192_link_change;
@@ -2230,23 +1929,17 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 	priv->ieee80211->check_nic_enough_desc = check_nic_enough_desc;
 	priv->ieee80211->tx_headroom = sizeof(TX_FWINFO_8190PCI);
 	priv->ieee80211->qos_support = 1;
-	priv->ieee80211->dot11PowerSaveMode = 0;
-	//added by WB
-//	priv->ieee80211->SwChnlByTimerHandler = rtl8192_phy_SwChnl;
 	priv->ieee80211->SetBWModeHandler = rtl8192_SetBWMode;
 	priv->ieee80211->handle_assoc_response = rtl8192_handle_assoc_response;
 	priv->ieee80211->handle_beacon = rtl8192_handle_beacon;
 
 	priv->ieee80211->sta_wake_up = rtl8192_hw_wakeup;
-//	priv->ieee80211->ps_request_tx_ack = rtl8192_rq_tx_ack;
 	priv->ieee80211->enter_sleep_state = rtl8192_hw_to_sleep;
 	priv->ieee80211->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
-	//added by david
 	priv->ieee80211->GetNmodeSupportBySecCfg = GetNmodeSupportBySecCfg8190Pci;
 	priv->ieee80211->SetWirelessMode = rtl8192_SetWirelessMode;
 	priv->ieee80211->GetHalfNmodeSupportByAPsHandler = GetHalfNmodeSupportByAPs819xPci;
 
-	//added by amy
 	priv->ieee80211->InitialGainHandler = InitialGain819xPci;
 
 #ifdef ENABLE_IPS
@@ -2260,15 +1953,8 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 	priv->ieee80211->SetHwRegHandler = rtl8192e_SetHwReg;
 	priv->ieee80211->rtllib_ap_sec_type = rtl8192e_ap_sec_type;
 
-	priv->card_type = USB;
-	{
-		priv->ShortRetryLimit = 0x30;
-		priv->LongRetryLimit = 0x30;
-	}
-	priv->EarlyRxThreshold = 7;
-	priv->enable_gpio0 = 0;
-
-	priv->TransmitConfig = 0;
+	priv->ShortRetryLimit = 0x30;
+	priv->LongRetryLimit = 0x30;
 
 	priv->ReceiveConfig = RCR_ADD3	|
 		RCR_AMF | RCR_ADF |		//accept management/data
@@ -2277,16 +1963,9 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 		RCR_AAP | ((u32)7<<RCR_MXDMA_OFFSET) |
 		((u32)7 << RCR_FIFO_OFFSET) | RCR_ONLYERLPKT;
 
-	priv->irq_mask = 	(u32)(IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK |
-				IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK |
-				IMR_BDOK | IMR_RXCMDOK | IMR_TIMEOUT0 | IMR_RDU | IMR_RXFOVW |
-				IMR_TXFOVW | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
-
-	priv->AcmControl = 0;
 	priv->pFirmware = vzalloc(sizeof(rt_firmware));
 
 	/* rx related queue */
-        skb_queue_head_init(&priv->rx_queue);
 	skb_queue_head_init(&priv->skb_queue);
 
 	/* Tx related queue */
@@ -2301,12 +1980,8 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
 
 static void rtl8192_init_priv_lock(struct r8192_priv* priv)
 {
-	spin_lock_init(&priv->tx_lock);
-	spin_lock_init(&priv->irq_lock);//added by thomas
 	spin_lock_init(&priv->irq_th_lock);
 	spin_lock_init(&priv->rf_ps_lock);
-	spin_lock_init(&priv->ps_lock);
-	//spin_lock_init(&priv->rf_lock);
 	sema_init(&priv->wx_sem,1);
 	sema_init(&priv->rf_sem,1);
 	mutex_init(&priv->mutex);
@@ -2314,50 +1989,35 @@ static void rtl8192_init_priv_lock(struct r8192_priv* priv)
 
 /* init tasklet and wait_queue here */
 #define DRV_NAME "wlan0"
-static void rtl8192_init_priv_task(struct net_device* dev)
+static void rtl8192_init_priv_task(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
-#ifdef PF_SYNCTHREAD
-	priv->priv_wq = create_workqueue(DRV_NAME,0);
-#else
 	priv->priv_wq = create_workqueue(DRV_NAME);
-#endif
 
 #ifdef ENABLE_IPS
-	INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq);
+	INIT_WORK(&priv->ieee80211->ips_leave_wq, IPSLeave_wq);
 #endif
 
-//	INIT_WORK(&priv->reset_wq, (void(*)(void*)) rtl8192_restart);
 	INIT_WORK(&priv->reset_wq,  rtl8192_restart);
-//	INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
 	INIT_DELAYED_WORK(&priv->watch_dog_wq, rtl819x_watchdog_wqcallback);
 	INIT_DELAYED_WORK(&priv->txpower_tracking_wq,  dm_txpower_trackingcallback);
 	INIT_DELAYED_WORK(&priv->rfpath_check_wq,  dm_rf_pathcheck_workitemcallback);
 	INIT_DELAYED_WORK(&priv->update_beacon_wq, rtl8192_update_beacon);
-	//INIT_WORK(&priv->SwChnlWorkItem,  rtl8192_SwChnl_WorkItem);
-	//INIT_WORK(&priv->SetBWModeWorkItem,  rtl8192_SetBWModeWorkItem);
 	INIT_WORK(&priv->qos_activate, rtl8192_qos_activate);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,(void*) rtl8192_hw_wakeup_wq);
-	INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,(void*) rtl8192_hw_sleep_wq);
+	INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq, rtl8192_hw_wakeup_wq);
 
-	tasklet_init(&priv->irq_rx_tasklet,
-	     (void(*)(unsigned long))rtl8192_irq_rx_tasklet,
-	     (unsigned long)priv);
-	tasklet_init(&priv->irq_tx_tasklet,
-	     (void(*)(unsigned long))rtl8192_irq_tx_tasklet,
-	     (unsigned long)priv);
-        tasklet_init(&priv->irq_prepare_beacon_tasklet,
-                (void(*)(unsigned long))rtl8192_prepare_beacon,
-                (unsigned long)priv);
+	tasklet_init(&priv->irq_rx_tasklet, rtl8192_irq_rx_tasklet,
+		     (unsigned long) priv);
+	tasklet_init(&priv->irq_tx_tasklet, rtl8192_irq_tx_tasklet,
+		     (unsigned long) priv);
+        tasklet_init(&priv->irq_prepare_beacon_tasklet, rtl8192_prepare_beacon,
+		     (unsigned long) priv);
 }
 
-static void rtl8192_get_eeprom_size(struct net_device* dev)
+static void rtl8192_get_eeprom_size(struct r8192_priv *priv)
 {
 	u16 curCR = 0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	RT_TRACE(COMP_INIT, "===========>%s()\n", __FUNCTION__);
-	curCR = read_nic_dword(dev, EPROM_CMD);
+	curCR = read_nic_dword(priv, EPROM_CMD);
 	RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD, curCR);
 	//whether need I consider BIT5?
 	priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EPROM_93c56 : EPROM_93c46;
@@ -2365,34 +2025,16 @@ static void rtl8192_get_eeprom_size(struct net_device* dev)
 }
 
 /*
- * used to swap endian. as ntohl & htonl are not
- * neccessary to swap endian, so use this instead.
- */
-static inline u16 endian_swap(u16* data)
-{
-	u16 tmp = *data;
-	*data = (tmp >> 8) | (tmp << 8);
-	return *data;
-}
-
-/*
  * Adapter->EEPROMAddressSize should be set before this function call.
  *  EEPROM address size can be got through GetEEPROMSize8185()
  */
-static void rtl8192_read_eeprom_info(struct net_device* dev)
+static void rtl8192_read_eeprom_info(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
+	struct net_device *dev = priv->ieee80211->dev;
 	u8			tempval;
-#ifdef RTL8192E
 	u8			ICVer8192, ICVer8256;
-#endif
 	u16			i,usValue, IC_Version;
 	u16			EEPROMId;
-#ifdef RTL8190P
-   	u8			offset;
-    	u8      		EepromTxPower[100];
-#endif
 	u8 bMac_Tmp_Addr[6] = {0x00, 0xe0, 0x4c, 0x00, 0x00, 0x01};
 	RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n");
 
@@ -2400,7 +2042,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 	// TODO: I don't know if we need to apply EF function to EEPROM read function
 
 	//2 Read EEPROM ID to make sure autoload is success
-	EEPROMId = eprom_read(dev, 0);
+	EEPROMId = eprom_read(priv, 0);
 	if( EEPROMId != RTL8190_EEPROM_ID )
 	{
 		RT_TRACE(COMP_ERR, "EEPROM ID is invalid:%x, %x\n", EEPROMId, RTL8190_EEPROM_ID);
@@ -2418,30 +2060,25 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 	if(!priv->AutoloadFailFlag)
 	{
 		// VID, PID
-		priv->eeprom_vid = eprom_read(dev, (EEPROM_VID >> 1));
-		priv->eeprom_did = eprom_read(dev, (EEPROM_DID >> 1));
+		priv->eeprom_vid = eprom_read(priv, (EEPROM_VID >> 1));
+		priv->eeprom_did = eprom_read(priv, (EEPROM_DID >> 1));
 
-		usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8 ;
+		usValue = eprom_read(priv, (u16)(EEPROM_Customer_ID>>1)) >> 8 ;
 		priv->eeprom_CustomerID = (u8)( usValue & 0xff);
-		usValue = eprom_read(dev, (EEPROM_ICVersion_ChannelPlan>>1));
+		usValue = eprom_read(priv, (EEPROM_ICVersion_ChannelPlan>>1));
 		priv->eeprom_ChannelPlan = usValue&0xff;
 		IC_Version = ((usValue&0xff00)>>8);
 
-#ifdef RTL8190P
-		priv->card_8192_version = (VERSION_8190)(IC_Version);
-#else
-	#ifdef RTL8192E
 		ICVer8192 = (IC_Version&0xf);		//bit0~3; 1:A cut, 2:B cut, 3:C cut...
 		ICVer8256 = ((IC_Version&0xf0)>>4);//bit4~6, bit7 reserved for other RF chip; 1:A cut, 2:B cut, 3:C cut...
-		RT_TRACE(COMP_INIT, "\nICVer8192 = 0x%x\n", ICVer8192);
-		RT_TRACE(COMP_INIT, "\nICVer8256 = 0x%x\n", ICVer8256);
+		RT_TRACE(COMP_INIT, "ICVer8192 = 0x%x\n", ICVer8192);
+		RT_TRACE(COMP_INIT, "ICVer8256 = 0x%x\n", ICVer8256);
 		if(ICVer8192 == 0x2)	//B-cut
 		{
 			if(ICVer8256 == 0x5) //E-cut
 				priv->card_8192_version= VERSION_8190_BE;
 		}
-	#endif
-#endif
+
 		switch(priv->card_8192_version)
 		{
 			case VERSION_8190_BD:
@@ -2460,7 +2097,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		priv->eeprom_did = 0;
 		priv->eeprom_CustomerID = 0;
 		priv->eeprom_ChannelPlan = 0;
-		RT_TRACE(COMP_INIT, "\nIC Version = 0x%x\n", 0xff);
+		RT_TRACE(COMP_INIT, "IC Version = 0x%x\n", 0xff);
 	}
 
 	RT_TRACE(COMP_INIT, "EEPROM VID = 0x%4x\n", priv->eeprom_vid);
@@ -2472,7 +2109,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 	{
 		for(i = 0; i < 6; i += 2)
 		{
-			usValue = eprom_read(dev, (u16) ((EEPROM_NODE_ADDRESS_BYTE_0+i)>>1));
+			usValue = eprom_read(priv, (u16) ((EEPROM_NODE_ADDRESS_BYTE_0+i)>>1));
 			*(u16*)(&dev->dev_addr[i]) = usValue;
 		}
 	} else {
@@ -2498,7 +2135,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		// Read RF-indication and Tx Power gain index diff of legacy to HT OFDM rate.
 		if(!priv->AutoloadFailFlag)
 		{
-			tempval = (eprom_read(dev, (EEPROM_RFInd_PowerDiff>>1))) & 0xff;
+			tempval = (eprom_read(priv, (EEPROM_RFInd_PowerDiff>>1))) & 0xff;
 			priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf;	// bit[3:0]
 
 			if (tempval&0x80)	//RF-indication, bit[7]
@@ -2516,7 +2153,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		// Read ThermalMeter from EEPROM
 		if(!priv->AutoloadFailFlag)
 		{
-			priv->EEPROMThermalMeter = (u8)(((eprom_read(dev, (EEPROM_ThermalMeter>>1))) & 0xff00)>>8);
+			priv->EEPROMThermalMeter = (u8)(((eprom_read(priv, (EEPROM_ThermalMeter>>1))) & 0xff00)>>8);
 		}
 		else
 		{
@@ -2531,7 +2168,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		// Read antenna tx power offset of B/C/D to A and CrystalCap from EEPROM
 		if(!priv->AutoloadFailFlag)
 		{
-				usValue = eprom_read(dev, (EEPROM_TxPwDiff_CrystalCap>>1));
+				usValue = eprom_read(priv, (EEPROM_TxPwDiff_CrystalCap>>1));
 				priv->EEPROMAntPwDiff = (usValue&0x0fff);
 				priv->EEPROMCrystalCap = (u8)((usValue&0xf000)>>12);
 		}
@@ -2550,7 +2187,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		{
 			if(!priv->AutoloadFailFlag)
 			{
-				usValue = eprom_read(dev, (u16) ((EEPROM_TxPwIndex_CCK+i)>>1) );
+				usValue = eprom_read(priv, (u16) ((EEPROM_TxPwIndex_CCK+i)>>1) );
 			}
 			else
 			{
@@ -2564,7 +2201,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		{
 			if(!priv->AutoloadFailFlag)
 			{
-				usValue = eprom_read(dev, (u16) ((EEPROM_TxPwIndex_OFDM_24G+i)>>1) );
+				usValue = eprom_read(priv, (u16) ((EEPROM_TxPwIndex_OFDM_24G+i)>>1) );
 			}
 			else
 			{
@@ -2575,82 +2212,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 			RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Power Level, Index %d = 0x%02x\n", i+1, priv->EEPROMTxPowerLevelOFDM24G[i+1]);
 		}
 		}
-		else if(priv->epromtype== EPROM_93c56)
-		{
-		#ifdef RTL8190P
-			// Read CrystalCap from EEPROM
-			if(!priv->AutoloadFailFlag)
-			{
-				priv->EEPROMAntPwDiff = EEPROM_Default_AntTxPowerDiff;
-				priv->EEPROMCrystalCap = (u8)(((eprom_read(dev, (EEPROM_C56_CrystalCap>>1))) & 0xf000)>>12);
-			}
-			else
-			{
-				priv->EEPROMAntPwDiff = EEPROM_Default_AntTxPowerDiff;
-				priv->EEPROMCrystalCap = EEPROM_Default_TxPwDiff_CrystalCap;
-			}
-			RT_TRACE(COMP_INIT,"EEPROMAntPwDiff = %d\n", priv->EEPROMAntPwDiff);
-			RT_TRACE(COMP_INIT, "EEPROMCrystalCap = %d\n", priv->EEPROMCrystalCap);
-
-			// Get Tx Power Level by Channel
-			if(!priv->AutoloadFailFlag)
-			{
-				    // Read Tx power of Channel 1 ~ 14 from EEPROM.
-			       for(i = 0; i < 12; i+=2)
-				{
-					if (i <6)
-						offset = EEPROM_C56_RfA_CCK_Chnl1_TxPwIndex + i;
-					else
-						offset = EEPROM_C56_RfC_CCK_Chnl1_TxPwIndex + i - 6;
-					usValue = eprom_read(dev, (offset>>1));
-				       *((u16*)(&EepromTxPower[i])) = usValue;
-				}
 
-			       for(i = 0; i < 12; i++)
-			       	{
-			       		if (i <= 2)
-						priv->EEPROMRfACCKChnl1TxPwLevel[i] = EepromTxPower[i];
-					else if ((i >=3 )&&(i <= 5))
-						priv->EEPROMRfAOfdmChnlTxPwLevel[i-3] = EepromTxPower[i];
-					else if ((i >=6 )&&(i <= 8))
-						priv->EEPROMRfCCCKChnl1TxPwLevel[i-6] = EepromTxPower[i];
-					else
-						priv->EEPROMRfCOfdmChnlTxPwLevel[i-9] = EepromTxPower[i];
-				}
-			}
-			else
-			{
-				priv->EEPROMRfACCKChnl1TxPwLevel[0] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfACCKChnl1TxPwLevel[1] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfACCKChnl1TxPwLevel[2] = EEPROM_Default_TxPowerLevel;
-
-				priv->EEPROMRfAOfdmChnlTxPwLevel[0] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfAOfdmChnlTxPwLevel[1] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfAOfdmChnlTxPwLevel[2] = EEPROM_Default_TxPowerLevel;
-
-				priv->EEPROMRfCCCKChnl1TxPwLevel[0] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfCCCKChnl1TxPwLevel[1] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfCCCKChnl1TxPwLevel[2] = EEPROM_Default_TxPowerLevel;
-
-				priv->EEPROMRfCOfdmChnlTxPwLevel[0] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfCOfdmChnlTxPwLevel[1] = EEPROM_Default_TxPowerLevel;
-				priv->EEPROMRfCOfdmChnlTxPwLevel[2] = EEPROM_Default_TxPowerLevel;
-			}
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfACCKChnl1TxPwLevel[0] = 0x%x\n", priv->EEPROMRfACCKChnl1TxPwLevel[0]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfACCKChnl1TxPwLevel[1] = 0x%x\n", priv->EEPROMRfACCKChnl1TxPwLevel[1]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfACCKChnl1TxPwLevel[2] = 0x%x\n", priv->EEPROMRfACCKChnl1TxPwLevel[2]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfAOfdmChnlTxPwLevel[0] = 0x%x\n", priv->EEPROMRfAOfdmChnlTxPwLevel[0]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfAOfdmChnlTxPwLevel[1] = 0x%x\n", priv->EEPROMRfAOfdmChnlTxPwLevel[1]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfAOfdmChnlTxPwLevel[2] = 0x%x\n", priv->EEPROMRfAOfdmChnlTxPwLevel[2]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfCCCKChnl1TxPwLevel[0] = 0x%x\n", priv->EEPROMRfCCCKChnl1TxPwLevel[0]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfCCCKChnl1TxPwLevel[1] = 0x%x\n", priv->EEPROMRfCCCKChnl1TxPwLevel[1]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfCCCKChnl1TxPwLevel[2] = 0x%x\n", priv->EEPROMRfCCCKChnl1TxPwLevel[2]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfCOfdmChnlTxPwLevel[0] = 0x%x\n", priv->EEPROMRfCOfdmChnlTxPwLevel[0]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfCOfdmChnlTxPwLevel[1] = 0x%x\n", priv->EEPROMRfCOfdmChnlTxPwLevel[1]);
-			RT_TRACE(COMP_INIT, "priv->EEPROMRfCOfdmChnlTxPwLevel[2] = 0x%x\n", priv->EEPROMRfCOfdmChnlTxPwLevel[2]);
-#endif
-
-		}
 		//
 		// Update HAL variables.
 		//
@@ -2676,10 +2238,6 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 		}
 		else if(priv->epromtype == EPROM_93c56)
 		{
-			//char	cck_pwr_diff_a=0, cck_pwr_diff_c=0;
-
-			//cck_pwr_diff_a = pHalData->EEPROMRfACCKChnl7TxPwLevel - pHalData->EEPROMRfAOfdmChnlTxPwLevel[1];
-			//cck_pwr_diff_c = pHalData->EEPROMRfCCCKChnl7TxPwLevel - pHalData->EEPROMRfCOfdmChnlTxPwLevel[1];
 			for(i=0; i<3; i++)	// channel 1~3 use the same Tx Power Level.
 			{
 				priv->TxPowerLevelCCK_A[i]  = priv->EEPROMRfACCKChnl1TxPwLevel[0];
@@ -2722,21 +2280,19 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 
 	if(priv->rf_type == RF_1T2R)
 	{
-		RT_TRACE(COMP_INIT, "\n1T2R config\n");
+		RT_TRACE(COMP_INIT, "1T2R config\n");
 	}
 	else if (priv->rf_type == RF_2T4R)
 	{
-		RT_TRACE(COMP_INIT, "\n2T4R config\n");
+		RT_TRACE(COMP_INIT, "2T4R config\n");
 	}
 
 	// 2008/01/16 MH We can only know RF type in the function. So we have to init
 	// DIG RATR table again.
-	init_rate_adaptive(dev);
+	init_rate_adaptive(priv);
 
 	//1 Make a copy for following variables and we can change them if we want
 
-	priv->rf_chip= RF_8256;
-
 	if(priv->RegChannelPlan == 0xf)
 	{
 		priv->ChannelPlan = priv->eeprom_ChannelPlan;
@@ -2778,7 +2334,6 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 				priv->ChannelPlan);
 			break;
 		case EEPROM_CID_Nettronix:
-			priv->ScanDelay = 100;	//cosa add for scan
 			priv->CustomerID = RT_CID_Nettronix;
 			break;
 		case EEPROM_CID_Pronet:
@@ -2789,15 +2344,6 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 			break;
 
 		case EEPROM_CID_WHQL:
-			//Adapter->bInHctTest = TRUE;//do not supported
-
-			//priv->bSupportTurboMode = FALSE;
-			//priv->bAutoTurboBy8186 = FALSE;
-
-			//pMgntInfo->PowerSaveControl.bInactivePs = FALSE;
-			//pMgntInfo->PowerSaveControl.bIPSModeBackup = FALSE;
-			//pMgntInfo->PowerSaveControl.bLeisurePs = FALSE;
-
 			break;
 		default:
 			// value from RegCustomerID
@@ -2808,54 +2354,6 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 	if(priv->ChannelPlan > CHANNEL_PLAN_LEN - 1)
 		priv->ChannelPlan = 0; //FCC
 
-	switch(priv->CustomerID)
-	{
-		case RT_CID_DEFAULT:
-		#ifdef RTL8190P
-			priv->LedStrategy = HW_LED;
-		#else
-			#ifdef RTL8192E
-			priv->LedStrategy = SW_LED_MODE1;
-			#endif
-		#endif
-			break;
-
-		case RT_CID_819x_CAMEO:
-			priv->LedStrategy = SW_LED_MODE2;
-			break;
-
-		case RT_CID_819x_RUNTOP:
-			priv->LedStrategy = SW_LED_MODE3;
-			break;
-
-		case RT_CID_819x_Netcore:
-			priv->LedStrategy = SW_LED_MODE4;
-			break;
-
-		case RT_CID_Nettronix:
-			priv->LedStrategy = SW_LED_MODE5;
-			break;
-
-		case RT_CID_PRONET:
-			priv->LedStrategy = SW_LED_MODE6;
-			break;
-
-		case RT_CID_TOSHIBA:   //Modify by Jacken 2008/01/31
-			// Do nothing.
-			//break;
-
-		default:
-		#ifdef RTL8190P
-			priv->LedStrategy = HW_LED;
-		#else
-			#ifdef RTL8192E
-			priv->LedStrategy = SW_LED_MODE1;
-			#endif
-		#endif
-			break;
-	}
-
-
 	if( priv->eeprom_vid == 0x1186 &&  priv->eeprom_did == 0x3304)
 		priv->ieee80211->bSupportRemoteWakeUp = true;
 	else
@@ -2863,17 +2361,13 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
 
 
 	RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
-	RT_TRACE(COMP_INIT, "ChannelPlan = %d \n", priv->ChannelPlan);
-	RT_TRACE(COMP_INIT, "LedStrategy = %d \n", priv->LedStrategy);
+	RT_TRACE(COMP_INIT, "ChannelPlan = %d\n", priv->ChannelPlan);
 	RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n");
-
-	return ;
 }
 
 
-static short rtl8192_get_channel_map(struct net_device * dev)
+static short rtl8192_get_channel_map(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 #ifdef ENABLE_DOT11D
 	if(priv->ChannelPlan> COUNTRY_CODE_GLOBAL_DOMAIN){
 		printk("rtl8180_init:Error channel plan! Set to default.\n");
@@ -2900,38 +2394,33 @@ static short rtl8192_get_channel_map(struct net_device * dev)
 	return 0;
 }
 
-static short rtl8192_init(struct net_device *dev)
+static short rtl8192_init(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct net_device *dev = priv->ieee80211->dev;
+
 	memset(&(priv->stats),0,sizeof(struct Stats));
-	rtl8192_init_priv_variable(dev);
+	rtl8192_init_priv_variable(priv);
 	rtl8192_init_priv_lock(priv);
-	rtl8192_init_priv_task(dev);
-	rtl8192_get_eeprom_size(dev);
-	rtl8192_read_eeprom_info(dev);
-	rtl8192_get_channel_map(dev);
-	init_hal_dm(dev);
+	rtl8192_init_priv_task(priv);
+	rtl8192_get_eeprom_size(priv);
+	rtl8192_read_eeprom_info(priv);
+	rtl8192_get_channel_map(priv);
+	init_hal_dm(priv);
 	init_timer(&priv->watch_dog_timer);
-	priv->watch_dog_timer.data = (unsigned long)dev;
+	priv->watch_dog_timer.data = (unsigned long)priv;
 	priv->watch_dog_timer.function = watch_dog_timer_callback;
-#if defined(IRQF_SHARED)
-        if(request_irq(dev->irq, (void*)rtl8192_interrupt, IRQF_SHARED, dev->name, dev)){
-#else
-        if(request_irq(dev->irq, (void *)rtl8192_interrupt, SA_SHIRQ, dev->name, dev)){
-#endif
+        if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED, dev->name, priv)) {
 		printk("Error allocating IRQ %d",dev->irq);
 		return -1;
 	}else{
 		priv->irq=dev->irq;
 		printk("IRQ %d",dev->irq);
 	}
-	if(rtl8192_pci_initdescring(dev)!=0){
+	if (rtl8192_pci_initdescring(priv) != 0){
 		printk("Endopoints initialization failed");
 		return -1;
 	}
 
-	//rtl8192_rx_enable(dev);
-	//rtl8192_adapter_start(dev);
 	return 0;
 }
 
@@ -2940,15 +2429,14 @@ static short rtl8192_init(struct net_device *dev)
  *  not to do all the hw config as its name says
  * This part need to modified according to the rate set we filtered
  */
-static void rtl8192_hwconfig(struct net_device* dev)
+static void rtl8192_hwconfig(struct r8192_priv *priv)
 {
 	u32 regRATR = 0, regRRSR = 0;
 	u8 regBwOpMode = 0, regTmp = 0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 // Set RRSR, RATR, and BW_OPMODE registers
 	//
-	switch(priv->ieee80211->mode)
+	switch (priv->ieee80211->mode)
 	{
 	case WIRELESS_MODE_B:
 		regBwOpMode = BW_OPMODE_20MHZ;
@@ -2980,7 +2468,7 @@ static void rtl8192_hwconfig(struct net_device* dev)
 		break;
 	}
 
-	write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+	write_nic_byte(priv, BW_OPMODE, regBwOpMode);
 	{
 		u32 ratr_value = 0;
 		ratr_value = regRATR;
@@ -2988,17 +2476,17 @@ static void rtl8192_hwconfig(struct net_device* dev)
 		{
 			ratr_value &= ~(RATE_ALL_OFDM_2SS);
 		}
-		write_nic_dword(dev, RATR0, ratr_value);
-		write_nic_byte(dev, UFWP, 1);
+		write_nic_dword(priv, RATR0, ratr_value);
+		write_nic_byte(priv, UFWP, 1);
 	}
-	regTmp = read_nic_byte(dev, 0x313);
+	regTmp = read_nic_byte(priv, 0x313);
 	regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
-	write_nic_dword(dev, RRSR, regRRSR);
+	write_nic_dword(priv, RRSR, regRRSR);
 
 	//
 	// Set Retry Limit here
 	//
-	write_nic_word(dev, RETRY_LIMIT,
+	write_nic_word(priv, RETRY_LIMIT,
 			priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
 			priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
 	// Set Contention Window here
@@ -3013,52 +2501,41 @@ static void rtl8192_hwconfig(struct net_device* dev)
 }
 
 
-static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
+static RT_STATUS rtl8192_adapter_start(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-//	struct ieee80211_device *ieee = priv->ieee80211;
+	struct net_device *dev = priv->ieee80211->dev;
 	u32 ulRegRead;
 	RT_STATUS rtStatus = RT_STATUS_SUCCESS;
-	//u8 eRFPath;
 	u8 tmpvalue;
-#ifdef RTL8192E
 	u8 ICVersion,SwitchingRegulatorOutput;
-#endif
 	bool bfirmwareok = true;
-#ifdef RTL8190P
-	u8 ucRegRead;
-#endif
 	u32	tmpRegA, tmpRegC, TempCCk;
 	int	i =0;
 
 	RT_TRACE(COMP_INIT, "====>%s()\n", __FUNCTION__);
 	priv->being_init_adapter = true;
-        rtl8192_pci_resetdescring(dev);
+        rtl8192_pci_resetdescring(priv);
 	// 2007/11/02 MH Before initalizing RF. We can not use FW to do RF-R/W.
 	priv->Rf_Mode = RF_OP_By_SW_3wire;
-#ifdef RTL8192E
+
         //dPLL on
         if(priv->ResetProgress == RESET_TYPE_NORESET)
         {
-            write_nic_byte(dev, ANAPAR, 0x37);
+            write_nic_byte(priv, ANAPAR, 0x37);
             // Accordign to designer's explain, LBUS active will never > 10ms. We delay 10ms
             // Joseph increae the time to prevent firmware download fail
             mdelay(500);
         }
-#endif
+
 	//PlatformSleepUs(10000);
 	// For any kind of InitializeAdapter process, we shall use system now!!
 	priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
 
-	// Set to eRfoff in order not to count receive count.
-	if(priv->RegRfOff == TRUE)
-		priv->ieee80211->eRFPowerState = eRfOff;
-
 	//
 	//3 //Config CPUReset Register
 	//3//
 	//3 Firmware Reset Or Not
-	ulRegRead = read_nic_dword(dev, CPU_GEN);
+	ulRegRead = read_nic_dword(priv, CPU_GEN);
 	if(priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
 	{	//called from MPInitialized. do nothing
 		ulRegRead |= CPU_GEN_SYSTEM_RESET;
@@ -3067,42 +2544,32 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 	else
 		RT_TRACE(COMP_ERR, "ERROR in %s(): undefined firmware state(%d)\n", __FUNCTION__,   priv->pFirmware->firmware_status);
 
-#ifdef RTL8190P
-	//2008.06.03, for WOL 90 hw bug
-	ulRegRead &= (~(CPU_GEN_GPIO_UART));
-#endif
-
-	write_nic_dword(dev, CPU_GEN, ulRegRead);
-	//mdelay(100);
-
-#ifdef RTL8192E
+	write_nic_dword(priv, CPU_GEN, ulRegRead);
 
 	//3//
 	//3 //Fix the issue of E-cut high temperature issue
 	//3//
 	// TODO: E cut only
-	ICVersion = read_nic_byte(dev, IC_VERRSION);
+	ICVersion = read_nic_byte(priv, IC_VERRSION);
 	if(ICVersion >= 0x4) //E-cut only
 	{
 		// HW SD suggest that we should not wirte this register too often, so driver
 		// should readback this register. This register will be modified only when
 		// power on reset
-		SwitchingRegulatorOutput = read_nic_byte(dev, SWREGULATOR);
+		SwitchingRegulatorOutput = read_nic_byte(priv, SWREGULATOR);
 		if(SwitchingRegulatorOutput  != 0xb8)
 		{
-			write_nic_byte(dev, SWREGULATOR, 0xa8);
+			write_nic_byte(priv, SWREGULATOR, 0xa8);
 			mdelay(1);
-			write_nic_byte(dev, SWREGULATOR, 0xb8);
+			write_nic_byte(priv, SWREGULATOR, 0xb8);
 		}
 	}
-#endif
-
 
 	//3//
 	//3// Initialize BB before MAC
 	//3//
 	RT_TRACE(COMP_INIT, "BB Config Start!\n");
-	rtStatus = rtl8192_BBConfig(dev);
+	rtStatus = rtl8192_BBConfig(priv);
 	if(rtStatus != RT_STATUS_SUCCESS)
 	{
 		RT_TRACE(COMP_ERR, "BB Config failed\n");
@@ -3116,10 +2583,9 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 	//	because setting of System_Reset bit reset MAC to default transmission mode.
 		//Loopback mode or not
 	priv->LoopbackMode = RTL819X_NO_LOOPBACK;
-	//priv->LoopbackMode = RTL819X_MAC_LOOPBACK;
 	if(priv->ResetProgress == RESET_TYPE_NORESET)
 	{
-	ulRegRead = read_nic_dword(dev, CPU_GEN);
+	ulRegRead = read_nic_dword(priv, CPU_GEN);
 	if(priv->LoopbackMode == RTL819X_NO_LOOPBACK)
 	{
 		ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) | CPU_GEN_NO_LOOPBACK_SET);
@@ -3135,116 +2601,92 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 
 	//2008.06.03, for WOL
 	//ulRegRead &= (~(CPU_GEN_GPIO_UART));
-	write_nic_dword(dev, CPU_GEN, ulRegRead);
+	write_nic_dword(priv, CPU_GEN, ulRegRead);
 
 	// 2006.11.29. After reset cpu, we sholud wait for a second, otherwise, it may fail to write registers. Emily
 	udelay(500);
 	}
 	//3Set Hardware(Do nothing now)
-	rtl8192_hwconfig(dev);
+	rtl8192_hwconfig(priv);
 	//2=======================================================
 	// Common Setting for all of the FPGA platform. (part 1)
 	//2=======================================================
 	// If there is changes, please make sure it applies to all of the FPGA version
 	//3 Turn on Tx/Rx
-	write_nic_byte(dev, CMDR, CR_RE|CR_TE);
+	write_nic_byte(priv, CMDR, CR_RE|CR_TE);
 
 	//2Set Tx dma burst
-#ifdef RTL8190P
-	write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
-			(MXDMA2_NoLimit<<MXDMA2_TX_SHIFT) |
-			(1<<MULRW_SHIFT)));
-#else
-	#ifdef RTL8192E
-	write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
+	write_nic_byte(priv, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
 				   (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT) ));
-	#endif
-#endif
+
 	//set IDR0 here
-	write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
-	write_nic_word(dev, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
+	write_nic_dword(priv, MAC0, ((u32*)dev->dev_addr)[0]);
+	write_nic_word(priv, MAC4, ((u16*)(dev->dev_addr + 4))[0]);
 	//set RCR
-	write_nic_dword(dev, RCR, priv->ReceiveConfig);
+	write_nic_dword(priv, RCR, priv->ReceiveConfig);
 
 	//3 Initialize Number of Reserved Pages in Firmware Queue
-	#ifdef TO_DO_LIST
-	if(priv->bInHctTest)
-	{
-		PlatformEFIOWrite4Byte(Adapter, RQPN1,  NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM << RSVD_FW_QUEUE_PAGE_BK_SHIFT |
-					NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
-					NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
-					NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
-		PlatformEFIOWrite4Byte(Adapter, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
-		PlatformEFIOWrite4Byte(Adapter, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
-					NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
-					NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
-	}
-	else
-	#endif
-	{
-		write_nic_dword(dev, RQPN1,  NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |
+		write_nic_dword(priv, RQPN1,  NUM_OF_PAGE_IN_FW_QUEUE_BK << RSVD_FW_QUEUE_PAGE_BK_SHIFT |
 					NUM_OF_PAGE_IN_FW_QUEUE_BE << RSVD_FW_QUEUE_PAGE_BE_SHIFT |
 					NUM_OF_PAGE_IN_FW_QUEUE_VI << RSVD_FW_QUEUE_PAGE_VI_SHIFT |
 					NUM_OF_PAGE_IN_FW_QUEUE_VO <<RSVD_FW_QUEUE_PAGE_VO_SHIFT);
-		write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
-		write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
+		write_nic_dword(priv, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT << RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
+		write_nic_dword(priv, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW|
 					NUM_OF_PAGE_IN_FW_QUEUE_BCN<<RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
 					NUM_OF_PAGE_IN_FW_QUEUE_PUB<<RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
-	}
 
-	rtl8192_tx_enable(dev);
-	rtl8192_rx_enable(dev);
+	rtl8192_tx_enable(priv);
+	rtl8192_rx_enable(priv);
 	//3Set Response Rate Setting Register
 	// CCK rate is supported by default.
 	// CCK rate will be filtered out only when associated AP does not support it.
-	ulRegRead = (0xFFF00000 & read_nic_dword(dev, RRSR))  | RATE_ALL_OFDM_AG | RATE_ALL_CCK;
-	write_nic_dword(dev, RRSR, ulRegRead);
-	write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
+	ulRegRead = (0xFFF00000 & read_nic_dword(priv, RRSR))  | RATE_ALL_OFDM_AG | RATE_ALL_CCK;
+	write_nic_dword(priv, RRSR, ulRegRead);
+	write_nic_dword(priv, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
 
 	//2Set AckTimeout
 	// TODO: (it value is only for FPGA version). need to be changed!!2006.12.18, by Emily
-	write_nic_byte(dev, ACK_TIMEOUT, 0x30);
+	write_nic_byte(priv, ACK_TIMEOUT, 0x30);
 
-	//rtl8192_actset_wirelessmode(dev,priv->RegWirelessMode);
 	if(priv->ResetProgress == RESET_TYPE_NORESET)
-	rtl8192_SetWirelessMode(dev, priv->ieee80211->mode);
+	rtl8192_SetWirelessMode(priv->ieee80211, priv->ieee80211->mode);
 	//-----------------------------------------------------------------------------
 	// Set up security related. 070106, by rcnjko:
 	// 1. Clear all H/W keys.
 	// 2. Enable H/W encryption/decryption.
 	//-----------------------------------------------------------------------------
-	CamResetAllEntry(dev);
+	CamResetAllEntry(priv);
 	{
 		u8 SECR_value = 0x0;
 		SECR_value |= SCR_TxEncEnable;
 		SECR_value |= SCR_RxDecEnable;
 		SECR_value |= SCR_NoSKMC;
-		write_nic_byte(dev, SECR, SECR_value);
+		write_nic_byte(priv, SECR, SECR_value);
 	}
 	//3Beacon related
-	write_nic_word(dev, ATIMWND, 2);
-	write_nic_word(dev, BCN_INTERVAL, 100);
+	write_nic_word(priv, ATIMWND, 2);
+	write_nic_word(priv, BCN_INTERVAL, 100);
 	for (i=0; i<QOS_QUEUE_NUM; i++)
-		write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
+		write_nic_dword(priv, WDCAPARA_ADD[i], 0x005e4332);
 	//
 	// Switching regulator controller: This is set temporarily.
 	// It's not sure if this can be removed in the future.
 	// PJ advised to leave it by default.
 	//
-	write_nic_byte(dev, 0xbe, 0xc0);
+	write_nic_byte(priv, 0xbe, 0xc0);
 
 	//2=======================================================
 	// Set PHY related configuration defined in MAC register bank
 	//2=======================================================
-	rtl8192_phy_configmac(dev);
+	rtl8192_phy_configmac(priv);
 
 	if (priv->card_8192_version > (u8) VERSION_8190_BD) {
-		rtl8192_phy_getTxPower(dev);
-		rtl8192_phy_setTxPower(dev, priv->chan);
+		rtl8192_phy_getTxPower(priv);
+		rtl8192_phy_setTxPower(priv, priv->chan);
 	}
 
 	//if D or C cut
-		tmpvalue = read_nic_byte(dev, IC_VERRSION);
+		tmpvalue = read_nic_byte(priv, IC_VERRSION);
 		priv->IC_Cut = tmpvalue;
 		RT_TRACE(COMP_INIT, "priv->IC_Cut = 0x%x\n", priv->IC_Cut);
 		if(priv->IC_Cut >= IC_VersionCut_D)
@@ -3266,21 +2708,20 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 			RT_TRACE(COMP_INIT, "Before C-cut\n");
 		}
 
-#if 1
 	//Firmware download
 	RT_TRACE(COMP_INIT, "Load Firmware!\n");
-	bfirmwareok = init_firmware(dev);
+	bfirmwareok = init_firmware(priv);
 	if(bfirmwareok != true) {
 		rtStatus = RT_STATUS_FAILURE;
 		return rtStatus;
 	}
 	RT_TRACE(COMP_INIT, "Load Firmware finished!\n");
-#endif
+
 	//RF config
 	if(priv->ResetProgress == RESET_TYPE_NORESET)
 	{
 	RT_TRACE(COMP_INIT, "RF Config Started!\n");
-	rtStatus = rtl8192_phy_RFConfig(dev);
+	rtStatus = rtl8192_phy_RFConfig(priv);
 	if(rtStatus != RT_STATUS_SUCCESS)
 	{
 		RT_TRACE(COMP_ERR, "RF Config failed\n");
@@ -3288,26 +2729,14 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 	}
 	RT_TRACE(COMP_INIT, "RF Config Finished!\n");
 	}
-	rtl8192_phy_updateInitGain(dev);
+	rtl8192_phy_updateInitGain(priv);
 
 	/*---- Set CCK and OFDM Block "ON"----*/
-	rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
-	rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
+	rtl8192_setBBreg(priv, rFPGA0_RFMOD, bCCKEn, 0x1);
+	rtl8192_setBBreg(priv, rFPGA0_RFMOD, bOFDMEn, 0x1);
 
-#ifdef RTL8192E
 	//Enable Led
-	write_nic_byte(dev, 0x87, 0x0);
-#endif
-#ifdef RTL8190P
-	//2008.06.03, for WOL
-	ucRegRead = read_nic_byte(dev, GPE);
-	ucRegRead |= BIT0;
-	write_nic_byte(dev, GPE, ucRegRead);
-
-	ucRegRead = read_nic_byte(dev, GPO);
-	ucRegRead &= ~BIT0;
-	write_nic_byte(dev, GPO, ucRegRead);
-#endif
+	write_nic_byte(priv, 0x87, 0x0);
 
 	//2=======================================================
 	// RF Power Save
@@ -3315,129 +2744,50 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 #ifdef ENABLE_IPS
 
 {
-	if(priv->RegRfOff == TRUE)
-	{ // User disable RF via registry.
-		RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RegRfOff ----------\n",__FUNCTION__);
-		MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW);
-#if 0//cosa, ask SD3 willis and he doesn't know what is this for
-		// Those action will be discard in MgntActSet_RF_State because off the same state
-	for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
-		PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0);
-#endif
-	}
-	else if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_PS)
+	if(priv->RfOffReason > RF_CHANGE_BY_PS)
 	{ // H/W or S/W RF OFF before sleep.
-		RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d) ----------\n", __FUNCTION__,priv->ieee80211->RfOffReason);
-		MgntActSet_RF_State(dev, eRfOff, priv->ieee80211->RfOffReason);
+		RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d)\n", __FUNCTION__,priv->RfOffReason);
+		MgntActSet_RF_State(priv, eRfOff, priv->RfOffReason);
 	}
-	else if(priv->ieee80211->RfOffReason >= RF_CHANGE_BY_IPS)
+	else if(priv->RfOffReason >= RF_CHANGE_BY_IPS)
 	{ // H/W or S/W RF OFF before sleep.
-		RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d) ----------\n", __FUNCTION__,priv->ieee80211->RfOffReason);
-		MgntActSet_RF_State(dev, eRfOff, priv->ieee80211->RfOffReason);
+		RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): Turn off RF for RfOffReason(%d)\n",  __FUNCTION__, priv->RfOffReason);
+		MgntActSet_RF_State(priv, eRfOff, priv->RfOffReason);
 	}
 	else
 	{
 		RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON \n",__FUNCTION__);
-		priv->ieee80211->eRFPowerState = eRfOn;
-		priv->ieee80211->RfOffReason = 0;
-		//DrvIFIndicateCurrentPhyStatus(Adapter);
-	// LED control
-	//Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_ON);
-
-	//
-	// If inactive power mode is enabled, disable rf while in disconnected state.
-	// But we should still tell upper layer we are in rf on state.
-	// 2007.07.16, by shien chang.
-	//
-		//if(!Adapter->bInHctTest)
-	//IPSEnter(Adapter);
-
+		priv->eRFPowerState = eRfOn;
+		priv->RfOffReason = 0;
 	}
 }
 #endif
-	if(1){
-#ifdef RTL8192E
-			// We can force firmware to do RF-R/W
-			if(priv->ieee80211->FwRWRF)
-				priv->Rf_Mode = RF_OP_By_FW;
-			else
-				priv->Rf_Mode = RF_OP_By_SW_3wire;
-#else
-			priv->Rf_Mode = RF_OP_By_SW_3wire;
-#endif
-	}
-#ifdef RTL8190P
+	// We can force firmware to do RF-R/W
+	if(priv->ieee80211->FwRWRF)
+		priv->Rf_Mode = RF_OP_By_FW;
+	else
+		priv->Rf_Mode = RF_OP_By_SW_3wire;
+
 	if(priv->ResetProgress == RESET_TYPE_NORESET)
 	{
-		dm_initialize_txpower_tracking(dev);
-
-		tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
-		tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
+		dm_initialize_txpower_tracking(priv);
 
-		if(priv->rf_type == RF_2T4R){
-		for(i = 0; i<TxBBGainTableLength; i++)
+		if(priv->IC_Cut >= IC_VersionCut_D)
 		{
-			if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
+			tmpRegA = rtl8192_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord);
+			tmpRegC = rtl8192_QueryBBReg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord);
+			for(i = 0; i<TxBBGainTableLength; i++)
 			{
-				priv->rfa_txpowertrackingindex= (u8)i;
-				priv->rfa_txpowertrackingindex_real= (u8)i;
-				priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
-				break;
-			}
-		}
-		}
-		for(i = 0; i<TxBBGainTableLength; i++)
-		{
-			if(tmpRegC == priv->txbbgain_table[i].txbbgain_value)
-			{
-				priv->rfc_txpowertrackingindex= (u8)i;
-				priv->rfc_txpowertrackingindex_real= (u8)i;
-				priv->rfc_txpowertracking_default = priv->rfc_txpowertrackingindex;
-				break;
-			}
-		}
-		TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
-
-		for(i=0 ; i<CCKTxBBGainTableLength ; i++)
-		{
-			if(TempCCk == priv->cck_txbbgain_table[i].ccktxbb_valuearray[0])
-			{
-				priv->CCKPresentAttentuation_20Mdefault =(u8) i;
-				break;
-			}
-		}
-		priv->CCKPresentAttentuation_40Mdefault = 0;
-		priv->CCKPresentAttentuation_difference = 0;
-		priv->CCKPresentAttentuation = priv->CCKPresentAttentuation_20Mdefault;
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_initial = %d\n", priv->rfa_txpowertrackingindex);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real__initial = %d\n", priv->rfa_txpowertrackingindex_real);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_initial = %d\n", priv->rfc_txpowertrackingindex);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real_initial = %d\n", priv->rfc_txpowertrackingindex_real);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference_initial = %d\n", priv->CCKPresentAttentuation_difference);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_initial = %d\n", priv->CCKPresentAttentuation);
-	}
-#else
-	#ifdef RTL8192E
-	if(priv->ResetProgress == RESET_TYPE_NORESET)
-	{
-		dm_initialize_txpower_tracking(dev);
-
-		if(priv->IC_Cut >= IC_VersionCut_D)
-		{
-			tmpRegA= rtl8192_QueryBBReg(dev,rOFDM0_XATxIQImbalance,bMaskDWord);
-			tmpRegC= rtl8192_QueryBBReg(dev,rOFDM0_XCTxIQImbalance,bMaskDWord);
-			for(i = 0; i<TxBBGainTableLength; i++)
-			{
-				if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
-				{
-					priv->rfa_txpowertrackingindex= (u8)i;
-					priv->rfa_txpowertrackingindex_real= (u8)i;
-					priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
-					break;
-				}
+				if(tmpRegA == priv->txbbgain_table[i].txbbgain_value)
+				{
+					priv->rfa_txpowertrackingindex= (u8)i;
+					priv->rfa_txpowertrackingindex_real= (u8)i;
+					priv->rfa_txpowertracking_default = priv->rfa_txpowertrackingindex;
+					break;
+				}
 			}
 
-		TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
+		TempCCk = rtl8192_QueryBBReg(priv, rCCK0_TxFilter1, bMaskByte2);
 
 		for(i=0 ; i<CCKTxBBGainTableLength ; i++)
 		{
@@ -3457,23 +2807,21 @@ static RT_STATUS rtl8192_adapter_start(struct net_device *dev)
 			priv->btxpower_tracking = FALSE;//TEMPLY DISABLE
 		}
 	}
-	#endif
-#endif
-	rtl8192_irq_enable(dev);
+
+	rtl8192_irq_enable(priv);
 	priv->being_init_adapter = false;
 	return rtStatus;
 
 }
 
-static void rtl8192_prepare_beacon(struct r8192_priv *priv)
+static void rtl8192_prepare_beacon(unsigned long arg)
 {
+	struct r8192_priv *priv = (struct r8192_priv*) arg;
 	struct sk_buff *skb;
-	//unsigned long flags;
 	cb_desc *tcb_desc;
 
 	skb = ieee80211_get_beacon(priv->ieee80211);
 	tcb_desc = (cb_desc *)(skb->cb + 8);
-	//spin_lock_irqsave(&priv->tx_lock,flags);
 	/* prepare misc info for the beacon xmit */
 	tcb_desc->queue_index = BEACON_QUEUE;
 	/* IBSS does not support HT yet, use 1M defaultly */
@@ -3484,9 +2832,8 @@ static void rtl8192_prepare_beacon(struct r8192_priv *priv)
 
 	skb_push(skb, priv->ieee80211->tx_headroom);
 	if(skb){
-		rtl8192_tx(priv->ieee80211->dev,skb);
+		rtl8192_tx(priv, skb);
 	}
-	//spin_unlock_irqrestore (&priv->tx_lock, flags);
 }
 
 
@@ -3495,220 +2842,102 @@ static void rtl8192_prepare_beacon(struct r8192_priv *priv)
  * rtl8192_beacon_tx_enable(). rtl8192_beacon_tx_disable() might
  * be used to stop beacon transmission
  */
-static void rtl8192_start_beacon(struct net_device *dev)
+static void rtl8192_start_beacon(struct ieee80211_device *ieee80211)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
 	struct ieee80211_network *net = &priv->ieee80211->current_network;
 	u16 BcnTimeCfg = 0;
         u16 BcnCW = 6;
         u16 BcnIFS = 0xf;
 
 	DMESG("Enabling beacon TX");
-	//rtl8192_prepare_beacon(dev);
-	rtl8192_irq_disable(dev);
+	rtl8192_irq_disable(priv);
 	//rtl8192_beacon_tx_enable(dev);
 
 	/* ATIM window */
-	write_nic_word(dev, ATIMWND, 2);
+	write_nic_word(priv, ATIMWND, 2);
 
 	/* Beacon interval (in unit of TU) */
-	write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
+	write_nic_word(priv, BCN_INTERVAL, net->beacon_interval);
 
 	/*
 	 * DrvErlyInt (in unit of TU).
 	 * (Time to send interrupt to notify driver to c
 	 * hange beacon content)
 	 * */
-	write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
+	write_nic_word(priv, BCN_DRV_EARLY_INT, 10);
 
 	/*
 	 * BcnDMATIM(in unit of us).
 	 * Indicates the time before TBTT to perform beacon queue DMA
 	 * */
-	write_nic_word(dev, BCN_DMATIME, 256);
+	write_nic_word(priv, BCN_DMATIME, 256);
 
 	/*
 	 * Force beacon frame transmission even after receiving
 	 * beacon frame from other ad hoc STA
 	 * */
-	write_nic_byte(dev, BCN_ERR_THRESH, 100);
+	write_nic_byte(priv, BCN_ERR_THRESH, 100);
 
 	/* Set CW and IFS */
 	BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
 	BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
-	write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+	write_nic_word(priv, BCN_TCFG, BcnTimeCfg);
 
 
 	/* enable the interrupt for ad-hoc process */
-	rtl8192_irq_enable(dev);
+	rtl8192_irq_enable(priv);
 }
 
-static bool HalTxCheckStuck8190Pci(struct net_device *dev)
+static bool HalRxCheckStuck8190Pci(struct r8192_priv *priv)
 {
-	u16 				RegTxCounter = read_nic_word(dev, 0x128);
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	u16 RegRxCounter = read_nic_word(priv, 0x130);
 	bool				bStuck = FALSE;
-	RT_TRACE(COMP_RESET,"%s():RegTxCounter is %d,TxCounter is %d\n",__FUNCTION__,RegTxCounter,priv->TxCounter);
-	if(priv->TxCounter==RegTxCounter)
-		bStuck = TRUE;
-
-	priv->TxCounter = RegTxCounter;
-
-	return bStuck;
-}
-
-/*
- * Assumption: RT_TX_SPINLOCK is acquired.
- */
-static RESET_TYPE
-TxCheckStuck(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8			QueueID;
-	ptx_ring		head=NULL,tail=NULL,txring = NULL;
-	u8			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
-	bool			bCheckFwTxCnt = false;
-
-	//
-	// Decide Stuch threshold according to current power save mode
-	//
-	switch (priv->ieee80211->dot11PowerSaveMode)
-	{
-		// The threshold value  may required to be adjusted .
-		case eActive:		// Active/Continuous access.
-			ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL;
-			break;
-		case eMaxPs:		// Max power save mode.
-			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
-			break;
-		case eFastPs:	// Fast power save mode.
-			ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE;
-			break;
-	}
-
-	//
-	// Check whether specific tcb has been queued for a specific time
-	//
-	for(QueueID = 0; QueueID < MAX_TX_QUEUE; QueueID++)
-	{
-
-
-		if(QueueID == TXCMD_QUEUE)
-			continue;
-
-		switch(QueueID) {
-		case MGNT_QUEUE:
-			tail=priv->txmapringtail;
-			head=priv->txmapringhead;
-			break;
-
-		case BK_QUEUE:
-			tail=priv->txbkpringtail;
-			head=priv->txbkpringhead;
-			break;
-
-		case BE_QUEUE:
-			tail=priv->txbepringtail;
-			head=priv->txbepringhead;
-			break;
-
-		case VI_QUEUE:
-			tail=priv->txvipringtail;
-			head=priv->txvipringhead;
-			break;
-
-		case VO_QUEUE:
-			tail=priv->txvopringtail;
-			head=priv->txvopringhead;
-			break;
-
-		default:
-			tail=head=NULL;
-			break;
-		}
-
-		if(tail == head)
-			continue;
-		else
-		{
-			txring = head;
-			if(txring == NULL)
-			{
-				RT_TRACE(COMP_ERR,"%s():txring is NULL , BUG!\n",__FUNCTION__);
-				continue;
-			}
-			txring->nStuckCount++;
-			bCheckFwTxCnt = TRUE;
-		}
-	}
-#if 1
-	if(bCheckFwTxCnt)
-	{
-		if(HalTxCheckStuck8190Pci(dev))
-		{
-			RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n");
-			return RESET_TYPE_SILENT;
-		}
-	}
-#endif
-	return RESET_TYPE_NORESET;
-}
-
 
-static bool HalRxCheckStuck8190Pci(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u16 				RegRxCounter = read_nic_word(dev, 0x130);
-	bool				bStuck = FALSE;
-	static u8			rx_chk_cnt = 0;
 	RT_TRACE(COMP_RESET,"%s(): RegRxCounter is %d,RxCounter is %d\n",__FUNCTION__,RegRxCounter,priv->RxCounter);
 	// If rssi is small, we should check rx for long time because of bad rx.
 	// or maybe it will continuous silent reset every 2 seconds.
-	rx_chk_cnt++;
+	priv->rx_chk_cnt++;
 	if(priv->undecorated_smoothed_pwdb >= (RateAdaptiveTH_High+5))
 	{
-		rx_chk_cnt = 0;	//high rssi, check rx stuck right now.
+		priv->rx_chk_cnt = 0;	/* high rssi, check rx stuck right now. */
 	}
 	else if(priv->undecorated_smoothed_pwdb < (RateAdaptiveTH_High+5) &&
 		((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_40M) ||
 		(priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb>=RateAdaptiveTH_Low_20M)) )
 
 	{
-		if(rx_chk_cnt < 2)
+		if(priv->rx_chk_cnt < 2)
 		{
 			return bStuck;
 		}
 		else
 		{
-			rx_chk_cnt = 0;
+			priv->rx_chk_cnt = 0;
 		}
 	}
 	else if(((priv->CurrentChannelBW!=HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_40M) ||
 		(priv->CurrentChannelBW==HT_CHANNEL_WIDTH_20&&priv->undecorated_smoothed_pwdb<RateAdaptiveTH_Low_20M)) &&
 		priv->undecorated_smoothed_pwdb >= VeryLowRSSI)
 	{
-		if(rx_chk_cnt < 4)
+		if(priv->rx_chk_cnt < 4)
 		{
-			//DbgPrint("RSSI < %d && RSSI >= %d, no check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
 			return bStuck;
 		}
 		else
 		{
-			rx_chk_cnt = 0;
-			//DbgPrint("RSSI < %d && RSSI >= %d, check this time \n", RateAdaptiveTH_Low, VeryLowRSSI);
+			priv->rx_chk_cnt = 0;
 		}
 	}
 	else
 	{
-		if(rx_chk_cnt < 8)
+		if(priv->rx_chk_cnt < 8)
 		{
-			//DbgPrint("RSSI <= %d, no check this time \n", VeryLowRSSI);
 			return bStuck;
 		}
 		else
 		{
-			rx_chk_cnt = 0;
-			//DbgPrint("RSSI <= %d, check this time \n", VeryLowRSSI);
+			priv->rx_chk_cnt = 0;
 		}
 	}
 	if(priv->RxCounter==RegRxCounter)
@@ -3719,10 +2948,10 @@ static bool HalRxCheckStuck8190Pci(struct net_device *dev)
 	return bStuck;
 }
 
-static RESET_TYPE RxCheckStuck(struct net_device *dev)
+static RESET_TYPE RxCheckStuck(struct r8192_priv *priv)
 {
 
-	if(HalRxCheckStuck8190Pci(dev))
+	if(HalRxCheckStuck8190Pci(priv))
 	{
 		RT_TRACE(COMP_RESET, "RxStuck Condition\n");
 		return RESET_TYPE_SILENT;
@@ -3731,319 +2960,39 @@ static RESET_TYPE RxCheckStuck(struct net_device *dev)
 	return RESET_TYPE_NORESET;
 }
 
-static RESET_TYPE
-rtl819x_ifcheck_resetornot(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	RESET_TYPE	TxResetType = RESET_TYPE_NORESET;
-	RESET_TYPE	RxResetType = RESET_TYPE_NORESET;
-	RT_RF_POWER_STATE 	rfState;
-
-	rfState = priv->ieee80211->eRFPowerState;
-
-	TxResetType = TxCheckStuck(dev);
-#if 1
-	if( rfState != eRfOff &&
-		/*ADAPTER_TEST_STATUS_FLAG(Adapter, ADAPTER_STATUS_FW_DOWNLOAD_FAILURE)) &&*/
-		(priv->ieee80211->iw_mode != IW_MODE_ADHOC))
-	{
-		// If driver is in the status of firmware download failure , driver skips RF initialization and RF is
-		// in turned off state. Driver should check whether Rx stuck and do silent reset. And
-		// if driver is in firmware download failure status, driver should initialize RF in the following
-		// silent reset procedure Emily, 2008.01.21
-
-		// Driver should not check RX stuck in IBSS mode because it is required to
-		// set Check BSSID in order to send beacon, however, if check BSSID is
-		// set, STA cannot hear any packet a all. Emily, 2008.04.12
-		RxResetType = RxCheckStuck(dev);
-	}
-#endif
-
-	RT_TRACE(COMP_RESET,"%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType);
-	if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL)
-		return RESET_TYPE_NORMAL;
-	else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT)
-		return RESET_TYPE_SILENT;
-	else
-		return RESET_TYPE_NORESET;
-
-}
-
-
-static void CamRestoreAllEntry(struct net_device *dev)
+static RESET_TYPE rtl819x_check_reset(struct r8192_priv *priv)
 {
-	u8 EntryId = 0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	const u8*	MacAddr = priv->ieee80211->current_network.bssid;
-
-	static const 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 const u8	CAM_CONST_BROAD[] =
-		{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-	RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n");
+	RESET_TYPE RxResetType = RESET_TYPE_NORESET;
+	RT_RF_POWER_STATE rfState;
 
+	rfState = priv->eRFPowerState;
 
-	if ((priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP40)||
-	    (priv->ieee80211->pairwise_key_type == KEY_TYPE_WEP104))
-	{
-
-		for(EntryId=0; EntryId<4; EntryId++)
-		{
-			{
-				MacAddr = CAM_CONST_ADDR[EntryId];
-				setKey(dev,
-						EntryId ,
-						EntryId,
-						priv->ieee80211->pairwise_key_type,
-						MacAddr,
-						0,
-						NULL);
-			}
-		}
-
-	}
-	else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_TKIP)
-	{
-
-		{
-			if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-				setKey(dev,
-						4,
-						0,
-						priv->ieee80211->pairwise_key_type,
-						(u8*)dev->dev_addr,
-						0,
-						NULL);
-			else
-				setKey(dev,
-						4,
-						0,
-						priv->ieee80211->pairwise_key_type,
-						MacAddr,
-						0,
-						NULL);
-		}
-	}
-	else if(priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP)
-	{
-
-		{
-			if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-				setKey(dev,
-						4,
-						0,
-						priv->ieee80211->pairwise_key_type,
-						(u8*)dev->dev_addr,
-						0,
-						NULL);
-			else
-				setKey(dev,
-						4,
-						0,
-						priv->ieee80211->pairwise_key_type,
-						MacAddr,
-						0,
-						NULL);
-		}
+	if (rfState != eRfOff && (priv->ieee80211->iw_mode != IW_MODE_ADHOC)) {
+		/*
+		 * If driver is in the status of firmware download failure,
+		 * driver skips RF initialization and RF is in turned off state.
+		 * Driver should check whether Rx stuck and do silent reset. And
+		 * if driver is in firmware download failure status, driver
+		 * should initialize RF in the following silent reset procedure
+		 *
+		 * Driver should not check RX stuck in IBSS mode because it is
+		 * required to set Check BSSID in order to send beacon, however,
+		 * if check BSSID is set, STA cannot hear any packet a all.
+		 */
+		RxResetType = RxCheckStuck(priv);
 	}
 
+	RT_TRACE(COMP_RESET, "%s():  RxResetType is %d\n", __FUNCTION__, RxResetType);
 
-
-	if(priv->ieee80211->group_key_type == KEY_TYPE_TKIP)
-	{
-		MacAddr = CAM_CONST_BROAD;
-		for(EntryId=1 ; EntryId<4 ; EntryId++)
-		{
-			{
-				setKey(dev,
-						EntryId,
-						EntryId,
-						priv->ieee80211->group_key_type,
-						MacAddr,
-						0,
-						NULL);
-			}
-		}
-		if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-				setKey(dev,
-						0,
-						0,
-						priv->ieee80211->group_key_type,
-						CAM_CONST_ADDR[0],
-						0,
-						NULL);
-	}
-	else if(priv->ieee80211->group_key_type == KEY_TYPE_CCMP)
-	{
-		MacAddr = CAM_CONST_BROAD;
-		for(EntryId=1; EntryId<4 ; EntryId++)
-		{
-			{
-				setKey(dev,
-						EntryId ,
-						EntryId,
-						priv->ieee80211->group_key_type,
-						MacAddr,
-						0,
-						NULL);
-			}
-		}
-
-		if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
-				setKey(dev,
-						0 ,
-						0,
-						priv->ieee80211->group_key_type,
-						CAM_CONST_ADDR[0],
-						0,
-						NULL);
-	}
-}
-
-/*
- * This function is used to fix Tx/Rx stop bug temporarily.
- * This function will do "system reset" to NIC when Tx or Rx is stuck.
- * The method checking Tx/Rx stuck of this function is supported by FW,
- * which reports Tx and Rx counter to register 0x128 and 0x130.
- */
-static void rtl819x_ifsilentreset(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8	reset_times = 0;
-	int reset_status = 0;
-	struct ieee80211_device *ieee = priv->ieee80211;
-
-
-	return;
-
-	// 2007.07.20. If we need to check CCK stop, please uncomment this line.
-	//bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
-
-	if(priv->ResetProgress==RESET_TYPE_NORESET)
-	{
-RESET_START:
-#ifdef ENABLE_LPS
-                //LZM for PS-Poll AID issue. 090429
-                if(priv->ieee80211->state == IEEE80211_LINKED)
-                    LeisurePSLeave(dev);
-#endif
-
-		RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
-
-		// Set the variable for reset.
-		priv->ResetProgress = RESET_TYPE_SILENT;
-//		rtl8192_close(dev);
-#if 1
-		down(&priv->wx_sem);
-		if(priv->up == 0)
-		{
-			RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__);
-			up(&priv->wx_sem);
-			return ;
-		}
-		priv->up = 0;
-		RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__);
-		if(!netif_queue_stopped(dev))
-			netif_stop_queue(dev);
-
-		dm_backup_dynamic_mechanism_state(dev);
-
-		rtl8192_irq_disable(dev);
-		rtl8192_cancel_deferred_work(priv);
-		deinit_hal_dm(dev);
-		del_timer_sync(&priv->watch_dog_timer);
-		ieee->sync_scan_hurryup = 1;
-		if(ieee->state == IEEE80211_LINKED)
-		{
-			down(&ieee->wx_sem);
-			printk("ieee->state is IEEE80211_LINKED\n");
-			ieee80211_stop_send_beacons(priv->ieee80211);
-			del_timer_sync(&ieee->associate_timer);
-                        cancel_delayed_work(&ieee->associate_retry_wq);
-			ieee80211_stop_scan(ieee);
-			up(&ieee->wx_sem);
-		}
-		else{
-			printk("ieee->state is NOT LINKED\n");
-			ieee80211_softmac_stop_protocol(priv->ieee80211,true);
-		}
-		rtl8192_halt_adapter(dev, true);
-		up(&priv->wx_sem);
-		RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
-		RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
-		reset_status = _rtl8192_up(dev);
-
-		RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__);
-		if(reset_status == -1)
-		{
-			if(reset_times < 3)
-			{
-				reset_times++;
-				goto RESET_START;
-			}
-			else
-			{
-				RT_TRACE(COMP_ERR," ERR!!! %s():  Reset Failed!!\n",__FUNCTION__);
-			}
-		}
-#endif
-		ieee->is_silent_reset = 1;
-#if 1
-		EnableHWSecurityConfig8192(dev);
-#if 1
-		if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
-		{
-			ieee->set_chan(ieee->dev, ieee->current_network.channel);
-
-#if 1
-			queue_work(ieee->wq, &ieee->associate_complete_wq);
-#endif
-
-		}
-		else if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_ADHOC)
-		{
-			ieee->set_chan(ieee->dev, ieee->current_network.channel);
-			ieee->link_change(ieee->dev);
-
-		//	notify_wx_assoc_event(ieee);
-
-			ieee80211_start_send_beacons(ieee);
-
-			if (ieee->data_hard_resume)
-				ieee->data_hard_resume(ieee->dev);
-			netif_carrier_on(ieee->dev);
-		}
-#endif
-
-		CamRestoreAllEntry(dev);
-
-		// Restore the previous setting for all dynamic mechanism
-		dm_restore_dynamic_mechanism_state(dev);
-
-		priv->ResetProgress = RESET_TYPE_NORESET;
-		priv->reset_count++;
-
-		priv->bForcedSilentReset =false;
-		priv->bResetInProgress = false;
-
-		// For test --> force write UFWP.
-		write_nic_byte(dev, UFWP, 1);
-		RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count);
-#endif
-	}
+	return RxResetType;
 }
 
 #ifdef ENABLE_IPS
-void InactivePsWorkItemCallback(struct net_device *dev)
+static void InactivePsWorkItemCallback(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 
-	RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() ---------> \n");
+	RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() --------->\n");
 	//
 	// This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
 	// is really scheduled.
@@ -4058,20 +3007,19 @@ void InactivePsWorkItemCallback(struct net_device *dev)
 			pPSC->eInactivePowerState == eRfOff?"OFF":"ON");
 
 
-	MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
+	MgntActSet_RF_State(priv, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
 
 	//
 	// To solve CAM values miss in RF OFF, rewrite CAM values after RF ON. By Bruce, 2007-09-20.
 	//
 	pPSC->bSwRfProcessing = FALSE;
-	RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <--------- \n");
+	RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <---------\n");
 }
 
 #ifdef ENABLE_LPS
 /* Change current and default preamble mode. */
-bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,	u8 rtPsMode)
+bool MgntActSet_802_11_PowerSaveMode(struct r8192_priv *priv, u8 rtPsMode)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	// Currently, we do not change power save mode on IBSS mode.
 	if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
@@ -4097,31 +3045,24 @@ bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev,	u8 rtPsMode)
 	// Awake immediately
 	if(priv->ieee80211->sta_sleep != 0 && rtPsMode == IEEE80211_PS_DISABLED)
 	{
-                unsigned long flags;
-
-		//PlatformSetTimer(Adapter, &(pMgntInfo->AwakeTimer), 0);
 		// Notify the AP we awke.
-		rtl8192_hw_wakeup(dev);
+		rtl8192_hw_wakeup(priv->ieee80211);
 		priv->ieee80211->sta_sleep = 0;
 
-                spin_lock_irqsave(&(priv->ieee80211->mgmt_tx_lock), flags);
+                spin_lock(&priv->ieee80211->mgmt_tx_lock);
 		printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
 		ieee80211_sta_ps_send_null_frame(priv->ieee80211, 0);
-                spin_unlock_irqrestore(&(priv->ieee80211->mgmt_tx_lock), flags);
+                spin_unlock(&priv->ieee80211->mgmt_tx_lock);
 	}
 
 	return true;
 }
 
 /* Enter the leisure power save mode. */
-void LeisurePSEnter(struct net_device *dev)
+void LeisurePSEnter(struct ieee80211_device *ieee80211)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
-
-	//RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
-	//RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
-	//	pPSC->bLeisurePs, priv->ieee80211->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 
 	if(!((priv->ieee80211->iw_mode == IW_MODE_INFRA) &&
 		(priv->ieee80211->state == IEEE80211_LINKED)) ||
@@ -4137,9 +3078,7 @@ void LeisurePSEnter(struct net_device *dev)
 
 			if(priv->ieee80211->ps == IEEE80211_PS_DISABLED)
 			{
-
-				//RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n");
-				MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
+				MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
 
 			}
 		}
@@ -4150,18 +3089,17 @@ void LeisurePSEnter(struct net_device *dev)
 
 
 /* Leave leisure power save mode. */
-void LeisurePSLeave(struct net_device *dev)
+void LeisurePSLeave(struct ieee80211_device *ieee80211)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 
 	if (pPSC->bLeisurePs)
 	{
 		if(priv->ieee80211->ps != IEEE80211_PS_DISABLED)
 		{
 			// move to lps_wakecomplete()
-			//RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
-			MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_DISABLED);
+			MgntActSet_802_11_PowerSaveMode(priv, IEEE80211_PS_DISABLED);
 
 		}
 	}
@@ -4170,16 +3108,14 @@ void LeisurePSLeave(struct net_device *dev)
 
 
 /* Enter the inactive power save mode. RF will be off */
-void
-IPSEnter(struct net_device *dev)
+void IPSEnter(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL		pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 	RT_RF_POWER_STATE 			rtState;
 
 	if (pPSC->bInactivePs)
 	{
-		rtState = priv->ieee80211->eRFPowerState;
+		rtState = priv->eRFPowerState;
 		//
 		// Added by Bruce, 2007-12-25.
 		// Do not enter IPS in the following conditions:
@@ -4193,10 +3129,9 @@ IPSEnter(struct net_device *dev)
 			&& (priv->ieee80211->state != IEEE80211_LINKED) )
 		{
 			RT_TRACE(COMP_RF,"IPSEnter(): Turn off RF.\n");
-			//printk("IPSEnter(): Turn off RF.\n");
 			pPSC->eInactivePowerState = eRfOff;
 //			queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
-			InactivePsWorkItemCallback(dev);
+			InactivePsWorkItemCallback(priv);
 		}
 	}
 }
@@ -4206,47 +3141,43 @@ IPSEnter(struct net_device *dev)
 //		Leave the inactive power save mode, RF will be on.
 //	2007.08.17, by shien chang.
 //
-void
-IPSLeave(struct net_device *dev)
+void IPSLeave(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL	pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 	RT_RF_POWER_STATE 	rtState;
 
 	if (pPSC->bInactivePs)
 	{
-		rtState = priv->ieee80211->eRFPowerState;
-		if (rtState != eRfOn  && !pPSC->bSwRfProcessing && priv->ieee80211->RfOffReason <= RF_CHANGE_BY_IPS)
+		rtState = priv->eRFPowerState;
+		if (rtState != eRfOn && !pPSC->bSwRfProcessing && priv->RfOffReason <= RF_CHANGE_BY_IPS)
 		{
 			RT_TRACE(COMP_POWER, "IPSLeave(): Turn on RF.\n");
-			//printk("IPSLeave(): Turn on RF.\n");
 			pPSC->eInactivePowerState = eRfOn;
-//			queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
-			InactivePsWorkItemCallback(dev);
+			InactivePsWorkItemCallback(priv);
 		}
 	}
 }
 
-void IPSLeave_wq(void *data)
+void IPSLeave_wq(struct work_struct *work)
 {
-	struct ieee80211_device *ieee = container_of(data,struct ieee80211_device,ips_leave_wq);
+	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, ips_leave_wq);
 	struct net_device *dev = ieee->dev;
 
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	down(&priv->ieee80211->ips_sem);
-	IPSLeave(dev);
+	IPSLeave(priv);
 	up(&priv->ieee80211->ips_sem);
 }
 
-void ieee80211_ips_leave_wq(struct net_device *dev)
+void ieee80211_ips_leave_wq(struct ieee80211_device *ieee80211)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
 	RT_RF_POWER_STATE	rtState;
-	rtState = priv->ieee80211->eRFPowerState;
+	rtState = priv->eRFPowerState;
 
-	if(priv->ieee80211->PowerSaveControl.bInactivePs){
+	if (priv->PowerSaveControl.bInactivePs){
 		if(rtState == eRfOff){
-			if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+			if(priv->RfOffReason > RF_CHANGE_BY_IPS)
 			{
 				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
 				return;
@@ -4259,12 +3190,12 @@ void ieee80211_ips_leave_wq(struct net_device *dev)
 	}
 }
 //added by amy 090331 end
-void ieee80211_ips_leave(struct net_device *dev)
+void ieee80211_ips_leave(struct ieee80211_device *ieee80211)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-	down(&priv->ieee80211->ips_sem);
-	IPSLeave(dev);
-	up(&priv->ieee80211->ips_sem);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
+	down(&ieee80211->ips_sem);
+	IPSLeave(priv);
+	up(&ieee80211->ips_sem);
 }
 #endif
 
@@ -4294,13 +3225,9 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 {
 	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
        struct r8192_priv *priv = container_of(dwork,struct r8192_priv,watch_dog_wq);
-       struct net_device *dev = priv->ieee80211->dev;
 	struct ieee80211_device* ieee = priv->ieee80211;
 	RESET_TYPE	ResetType = RESET_TYPE_NORESET;
-      	static u8	check_reset_cnt=0;
-	unsigned long flags;
 	bool bBusyTraffic = false;
-	static u8 last_time = 0;
 	bool bEnterPS = false;
 
 	if ((!priv->up) || priv->bHwRadioOff)
@@ -4308,18 +3235,14 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 
 	if(!priv->up)
 		return;
-	hal_dm_watchdog(dev);
+	hal_dm_watchdog(priv);
 #ifdef ENABLE_IPS
-//	printk("watch_dog ENABLE_IPS\n");
 	if(ieee->actscanning == false){
-		//printk("%d,%d,%d,%d\n", ieee->eRFPowerState, ieee->is_set_key, ieee->proto_stoppping, ieee->wx_set_enc);
 		if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_NOLINK) &&
-		    (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&
+		    (priv->eRFPowerState == eRfOn) && !ieee->is_set_key &&
 		    (!ieee->proto_stoppping) && !ieee->wx_set_enc){
-			if(ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
-				//printk("====================>haha:IPSEnter()\n");
-				IPSEnter(dev);
-				//ieee80211_stop_scan(priv->ieee80211);
+			if (priv->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
+				IPSEnter(priv);
 			}
 		}
 	}
@@ -4337,8 +3260,6 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 			if(	((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
 				(ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
 			{
-				//printk("ieee->LinkDetectInfo.NumRxUnicastOkInPeriod is %d,ieee->LinkDetectInfo.NumTxOkInPeriod is %d\n",
-				//	ieee->LinkDetectInfo.NumRxUnicastOkInPeriod,ieee->LinkDetectInfo.NumTxOkInPeriod);
 				bEnterPS= false;
 			}
 			else
@@ -4346,15 +3267,14 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 				bEnterPS= true;
 			}
 
-			//printk("***bEnterPS = %d\n", bEnterPS);
 			// LeisurePS only work in infra mode.
 			if(bEnterPS)
 			{
-				LeisurePSEnter(dev);
+				LeisurePSEnter(priv->ieee80211);
 			}
 			else
 			{
-				LeisurePSLeave(dev);
+				LeisurePSLeave(priv->ieee80211);
 			}
 #endif
 
@@ -4362,8 +3282,7 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 		else
 		{
 #ifdef ENABLE_LPS
-			//RT_TRACE(COMP_LPS,"====>no link LPS leave\n");
-			LeisurePSLeave(dev);
+			LeisurePSLeave(priv->ieee80211);
 #endif
 		}
 
@@ -4375,8 +3294,6 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 
 
 	//added by amy for AP roaming
-	if (1)
-	{
 		if(ieee->state == IEEE80211_LINKED && ieee->iw_mode == IW_MODE_INFRA)
 		{
 			u32	TotalRxBcnNum = 0;
@@ -4385,7 +3302,7 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 			rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum);
 			if((TotalRxBcnNum+TotalRxDataNum) == 0)
 			{
-				if( ieee->eRFPowerState == eRfOff)
+				if (priv->eRFPowerState == eRfOff)
 					RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
 				printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
 				//		Dot11d_Reset(dev);
@@ -4394,23 +3311,20 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 				RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
 				ieee->is_roaming = true;
 				ieee->is_set_key = false;
-				ieee->link_change(dev);
+				ieee->link_change(ieee);
 				queue_work(ieee->wq, &ieee->associate_procedure_wq);
 			}
 		}
 	      ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
               ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
 
-	}
 	//check if reset the driver
-	spin_lock_irqsave(&priv->tx_lock,flags);
-	if(check_reset_cnt++ >= 3 && !ieee->is_roaming && (last_time != 1))
+	if (priv->watchdog_check_reset_cnt++ >= 3 && !ieee->is_roaming && 
+	    priv->watchdog_last_time != 1)
 	{
-    		ResetType = rtl819x_ifcheck_resetornot(dev);
-		check_reset_cnt = 3;
-		//DbgPrint("Start to check silent reset\n");
+		ResetType = rtl819x_check_reset(priv);
+		priv->watchdog_check_reset_cnt = 3;
 	}
-	spin_unlock_irqrestore(&priv->tx_lock,flags);
 	if(!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_NORMAL)
 	{
 		priv->ResetProgress = RESET_TYPE_NORMAL;
@@ -4418,15 +3332,14 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 		return;
 	}
 	/* disable silent reset temply 2008.9.11*/
-#if 1
+
 	if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) // This is control by OID set in Pomelo
 	{
-		last_time = 1;
-		rtl819x_ifsilentreset(dev);
+		priv->watchdog_last_time = 1;
 	}
 	else
-		last_time = 0;
-#endif
+		priv->watchdog_last_time = 0;
+
 	priv->force_reset = false;
 	priv->bForcedSilentReset = false;
 	priv->bResetInProgress = false;
@@ -4436,37 +3349,37 @@ static void rtl819x_watchdog_wqcallback(struct work_struct *work)
 
 void watch_dog_timer_callback(unsigned long data)
 {
-	struct r8192_priv *priv = ieee80211_priv((struct net_device *) data);
+	struct r8192_priv *priv = (struct r8192_priv *) data;
 	queue_delayed_work(priv->priv_wq,&priv->watch_dog_wq,0);
 	mod_timer(&priv->watch_dog_timer, jiffies + MSECS(IEEE80211_WATCH_DOG_TIME));
 
 }
 
-static int _rtl8192_up(struct net_device *dev)
+static int _rtl8192_up(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	//int i;
 	RT_STATUS init_status = RT_STATUS_SUCCESS;
+	struct net_device *dev = priv->ieee80211->dev;
+
 	priv->up=1;
 	priv->ieee80211->ieee_up=1;
 	priv->bdisable_nic = false;  //YJ,add,091111
-	RT_TRACE(COMP_INIT, "Bringing up iface");
+	RT_TRACE(COMP_INIT, "Bringing up iface\n");
 
-	init_status = rtl8192_adapter_start(dev);
+	init_status = rtl8192_adapter_start(priv);
 	if(init_status != RT_STATUS_SUCCESS)
 	{
 		RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
 		return -1;
 	}
 	RT_TRACE(COMP_INIT, "start adapter finished\n");
-#ifdef RTL8192E
-	if(priv->ieee80211->eRFPowerState!=eRfOn)
-		MgntActSet_RF_State(dev, eRfOn, priv->ieee80211->RfOffReason);
-#endif
+
+	if (priv->eRFPowerState != eRfOn)
+		MgntActSet_RF_State(priv, eRfOn, priv->RfOffReason);
+
 	if(priv->ieee80211->state != IEEE80211_LINKED)
 	ieee80211_softmac_start_protocol(priv->ieee80211);
 	ieee80211_reset_queue(priv->ieee80211);
-	watch_dog_timer_callback((unsigned long) dev);
+	watch_dog_timer_callback((unsigned long) priv);
 	if(!netif_queue_stopped(dev))
 		netif_start_queue(dev);
 	else
@@ -4495,7 +3408,7 @@ int rtl8192_up(struct net_device *dev)
 
 	if (priv->up == 1) return -1;
 
-	return _rtl8192_up(dev);
+	return _rtl8192_up(priv);
 }
 
 
@@ -4523,7 +3436,7 @@ int rtl8192_down(struct net_device *dev)
 #ifdef ENABLE_LPS
 	//LZM for PS-Poll AID issue. 090429
 	if(priv->ieee80211->state == IEEE80211_LINKED)
-		LeisurePSLeave(dev);
+		LeisurePSLeave(priv->ieee80211);
 #endif
 
 	priv->up=0;
@@ -4533,14 +3446,14 @@ int rtl8192_down(struct net_device *dev)
 	if (!netif_queue_stopped(dev))
 		netif_stop_queue(dev);
 
-	rtl8192_irq_disable(dev);
+	rtl8192_irq_disable(priv);
 	rtl8192_cancel_deferred_work(priv);
-	deinit_hal_dm(dev);
+	deinit_hal_dm(priv);
 	del_timer_sync(&priv->watch_dog_timer);
 
 	ieee80211_softmac_stop_protocol(priv->ieee80211,true);
 
-	rtl8192_halt_adapter(dev,false);
+	rtl8192_halt_adapter(priv, false);
 	memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
 
 	RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
@@ -4549,28 +3462,25 @@ int rtl8192_down(struct net_device *dev)
 }
 
 
-void rtl8192_commit(struct net_device *dev)
+void rtl8192_commit(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	if (priv->up == 0) return ;
 
 
 	ieee80211_softmac_stop_protocol(priv->ieee80211,true);
 
-	rtl8192_irq_disable(dev);
-	rtl8192_halt_adapter(dev,true);
-	_rtl8192_up(dev);
+	rtl8192_irq_disable(priv);
+	rtl8192_halt_adapter(priv, true);
+	_rtl8192_up(priv);
 }
 
 static void rtl8192_restart(struct work_struct *work)
 {
         struct r8192_priv *priv = container_of(work, struct r8192_priv, reset_wq);
-        struct net_device *dev = priv->ieee80211->dev;
 
 	down(&priv->wx_sem);
 
-	rtl8192_commit(dev);
+	rtl8192_commit(priv);
 
 	up(&priv->wx_sem);
 }
@@ -4578,23 +3488,8 @@ static void rtl8192_restart(struct work_struct *work)
 static void r8192_set_multicast(struct net_device *dev)
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
-	short promisc;
-
-	//down(&priv->wx_sem);
 
-	/* FIXME FIXME */
-
-	promisc = (dev->flags & IFF_PROMISC) ? 1:0;
-
-	if (promisc != priv->promisc) {
-		;
-	//	rtl8192_commit(dev);
-	}
-
-	priv->promisc = promisc;
-
-	//schedule_work(&priv->reset_wq);
-	//up(&priv->wx_sem);
+	priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
 }
 
 
@@ -4613,15 +3508,74 @@ static int r8192_set_mac_adr(struct net_device *dev, void *mac)
 	return 0;
 }
 
+static void r8192e_set_hw_key(struct r8192_priv *priv, struct ieee_param *ipw)
+{
+	struct ieee80211_device *ieee = priv->ieee80211;
+	u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u32 key[4];
+
+	if (ipw->u.crypt.set_tx) {
+		if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
+			ieee->pairwise_key_type = KEY_TYPE_CCMP;
+		else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
+			ieee->pairwise_key_type = KEY_TYPE_TKIP;
+		else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
+			if (ipw->u.crypt.key_len == 13)
+				ieee->pairwise_key_type = KEY_TYPE_WEP104;
+			else if (ipw->u.crypt.key_len == 5)
+				ieee->pairwise_key_type = KEY_TYPE_WEP40;
+		} else
+			ieee->pairwise_key_type = KEY_TYPE_NA;
+
+		if (ieee->pairwise_key_type) {
+			memcpy(key, ipw->u.crypt.key, 16);
+			EnableHWSecurityConfig8192(priv);
+			/*
+			 * We fill both index entry and 4th entry for pairwise
+			 * key as in IPW interface, adhoc will only get here,
+			 * so we need index entry for its default key serching!
+			 */
+			setKey(priv, 4, ipw->u.crypt.idx,
+			       ieee->pairwise_key_type,
+			       (u8*)ieee->ap_mac_addr, 0, key);
+
+			/* LEAP WEP will never set this. */
+			if (ieee->auth_mode != 2)
+				setKey(priv, ipw->u.crypt.idx, ipw->u.crypt.idx,
+				       ieee->pairwise_key_type,
+				       (u8*)ieee->ap_mac_addr, 0, key);
+		}
+		if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) &&
+		    ieee->pHTInfo->bCurrentHTSupport) {
+			write_nic_byte(priv, 0x173, 1); /* fix aes bug */
+		}
+	} else {
+		memcpy(key, ipw->u.crypt.key, 16);
+		if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
+			ieee->group_key_type= KEY_TYPE_CCMP;
+		else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
+			ieee->group_key_type = KEY_TYPE_TKIP;
+		else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) {
+			if (ipw->u.crypt.key_len == 13)
+				ieee->group_key_type = KEY_TYPE_WEP104;
+			else if (ipw->u.crypt.key_len == 5)
+				ieee->group_key_type = KEY_TYPE_WEP40;
+		} else
+			ieee->group_key_type = KEY_TYPE_NA;
+
+		if (ieee->group_key_type) {
+			setKey(priv, ipw->u.crypt.idx, ipw->u.crypt.idx,
+			       ieee->group_key_type, broadcast_addr, 0, key);
+		}
+	}
+}
+
 /* based on ipw2200 driver */
 static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	struct iwreq *wrq = (struct iwreq *)rq;
 	int ret=-1;
-	struct ieee80211_device *ieee = priv->ieee80211;
-	u32 key[4];
-	u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
 	struct iw_point *p = &wrq->u.data;
 	struct ieee_param *ipw = NULL;//(struct ieee_param *)wrq->u.data.pointer;
 
@@ -4645,86 +3599,14 @@ static int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
      }
 
 	switch (cmd) {
-	    case RTL_IOCTL_WPA_SUPPLICANT:
-		//parse here for HW security
-			if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
-			{
-				if (ipw->u.crypt.set_tx)
-				{
-					if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
-						ieee->pairwise_key_type = KEY_TYPE_CCMP;
-					else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
-						ieee->pairwise_key_type = KEY_TYPE_TKIP;
-					else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
-					{
-						if (ipw->u.crypt.key_len == 13)
-							ieee->pairwise_key_type = KEY_TYPE_WEP104;
-						else if (ipw->u.crypt.key_len == 5)
-							ieee->pairwise_key_type = KEY_TYPE_WEP40;
-					}
-					else
-						ieee->pairwise_key_type = KEY_TYPE_NA;
-
-					if (ieee->pairwise_key_type)
-					{
-						memcpy((u8*)key, ipw->u.crypt.key, 16);
-						EnableHWSecurityConfig8192(dev);
-					//we fill both index entry and 4th entry for pairwise key as in IPW interface, adhoc will only get here, so we need index entry for its default key serching!
-					//added by WB.
-						setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
-						if (ieee->auth_mode != 2)  //LEAP WEP will never set this.
-						setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key);
-					}
-					if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
-							write_nic_byte(dev, 0x173, 1); //fix aes bug
-						}
-
-				}
-				else //if (ipw->u.crypt.idx) //group key use idx > 0
-				{
-					memcpy((u8*)key, ipw->u.crypt.key, 16);
-					if (strcmp(ipw->u.crypt.alg, "CCMP") == 0)
-						ieee->group_key_type= KEY_TYPE_CCMP;
-					else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0)
-						ieee->group_key_type = KEY_TYPE_TKIP;
-					else if (strcmp(ipw->u.crypt.alg, "WEP") == 0)
-					{
-						if (ipw->u.crypt.key_len == 13)
-							ieee->group_key_type = KEY_TYPE_WEP104;
-						else if (ipw->u.crypt.key_len == 5)
-							ieee->group_key_type = KEY_TYPE_WEP40;
-					}
-					else
-						ieee->group_key_type = KEY_TYPE_NA;
-
-					if (ieee->group_key_type)
-					{
-							setKey(	dev,
-								ipw->u.crypt.idx,
-								ipw->u.crypt.idx,		//KeyIndex
-						     		ieee->group_key_type,	//KeyType
-						            	broadcast_addr,	//MacAddr
-								0,		//DefaultKey
-							      	key);		//KeyContent
-					}
-				}
-			}
-#ifdef JOHN_DEBUG
-		//john's test 0711
-	{
-		int i;
-		printk("@@ wrq->u pointer = ");
-		for(i=0;i<wrq->u.data.length;i++){
-			if(i%10==0) printk("\n");
-			printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] );
-		}
-		printk("\n");
-	}
-#endif /*JOHN_DEBUG*/
+	case RTL_IOCTL_WPA_SUPPLICANT:
+		/* parse here for HW security */
+		if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION)
+			r8192e_set_hw_key(priv, ipw);
 		ret = ieee80211_wpa_supplicant_ioctl(priv->ieee80211, &wrq->u.data);
 		break;
 
-	    default:
+	default:
 		ret = -EOPNOTSUPP;
 		break;
 	}
@@ -4790,9 +3672,8 @@ static u8 HwRateToMRate90(bool bIsHT, u8 rate)
 }
 
 /* Record the TSF time stamp when receiving a packet */
-static void UpdateRxPktTimeStamp8190 (struct net_device *dev, struct ieee80211_rx_stats *stats)
+static void UpdateRxPktTimeStamp8190(struct r8192_priv *priv, struct ieee80211_rx_stats *stats)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 
 	if(stats->bIsAMPDU && !stats->bFirstMPDU) {
 		stats->mac_time[0] = priv->LastRxDescTSFLow;
@@ -4814,102 +3695,6 @@ static long rtl819x_translate_todbm(u8 signal_strength_index)// 0-100 index.
 	return signal_power;
 }
 
-/*
- * Update Rx signal related information in the packet reeived
- * to RxStats. User application can query RxStats to realize
- * current Rx signal status.
- *
- * In normal operation, user only care about the information of the BSS
- * and we shall invoke this function if the packet received is from the BSS.
- */
-static void
-rtl819x_update_rxsignalstatistics8190pci(
-	struct r8192_priv * priv,
-	struct ieee80211_rx_stats * pprevious_stats
-	)
-{
-	int weighting = 0;
-
-	//2 <ToDo> Update Rx Statistics (such as signal strength and signal quality).
-
-	// Initila state
-	if(priv->stats.recv_signal_power == 0)
-		priv->stats.recv_signal_power = pprevious_stats->RecvSignalPower;
-
-	// To avoid the past result restricting the statistics sensitivity, weight the current power (5/6) to speed up the
-	// reaction of smoothed Signal Power.
-	if(pprevious_stats->RecvSignalPower > priv->stats.recv_signal_power)
-		weighting = 5;
-	else if(pprevious_stats->RecvSignalPower < priv->stats.recv_signal_power)
-		weighting = (-5);
-	//
-	// We need more correct power of received packets and the  "SignalStrength" of RxStats have been beautified or translated,
-	// so we record the correct power in Dbm here. By Bruce, 2008-03-07.
-	//
-	priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + pprevious_stats->RecvSignalPower + weighting) / 6;
-}
-
-static void
-rtl8190_process_cck_rxpathsel(
-	struct r8192_priv * priv,
-	struct ieee80211_rx_stats * pprevious_stats
-	)
-{
-#ifdef RTL8190P	//Only 90P 2T4R need to check
-	char				last_cck_adc_pwdb[4]={0,0,0,0};
-	u8				i;
-//cosa add for Rx path selection
-		if(priv->rf_type == RF_2T4R && DM_RxPathSelTable.Enable)
-		{
-			if(pprevious_stats->bIsCCK &&
-				(pprevious_stats->bPacketToSelf ||pprevious_stats->bPacketBeacon))
-			{
-				/* record the cck adc_pwdb to the sliding window. */
-				if(priv->stats.cck_adc_pwdb.TotalNum++ >= PHY_RSSI_SLID_WIN_MAX)
-				{
-					priv->stats.cck_adc_pwdb.TotalNum = PHY_RSSI_SLID_WIN_MAX;
-					for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
-					{
-						last_cck_adc_pwdb[i] = priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index];
-						priv->stats.cck_adc_pwdb.TotalVal[i] -= last_cck_adc_pwdb[i];
-					}
-				}
-				for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
-				{
-					priv->stats.cck_adc_pwdb.TotalVal[i] += pprevious_stats->cck_adc_pwdb[i];
-					priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index] = pprevious_stats->cck_adc_pwdb[i];
-				}
-				priv->stats.cck_adc_pwdb.index++;
-				if(priv->stats.cck_adc_pwdb.index >= PHY_RSSI_SLID_WIN_MAX)
-					priv->stats.cck_adc_pwdb.index = 0;
-
-				for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
-				{
-					DM_RxPathSelTable.cck_pwdb_sta[i] = priv->stats.cck_adc_pwdb.TotalVal[i]/priv->stats.cck_adc_pwdb.TotalNum;
-				}
-
-				for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
-				{
-					if(pprevious_stats->cck_adc_pwdb[i]  > (char)priv->undecorated_smoothed_cck_adc_pwdb[i])
-					{
-						priv->undecorated_smoothed_cck_adc_pwdb[i] =
-							( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) +
-							(pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor);
-						priv->undecorated_smoothed_cck_adc_pwdb[i] = priv->undecorated_smoothed_cck_adc_pwdb[i] + 1;
-					}
-					else
-					{
-						priv->undecorated_smoothed_cck_adc_pwdb[i] =
-							( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) +
-							(pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor);
-					}
-				}
-			}
-		}
-#endif
-}
-
-
 /* 2008/01/22 MH We can not delcare RSSI/EVM total value of sliding window to
 	be a local static. Otherwise, it may increase when we return from S3/S4. The
 	value will be kept in memory or disk. We must delcare the value in adapter
@@ -4919,13 +3704,9 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 	bool bcheck = false;
 	u8	rfpath;
 	u32 nspatial_stream, tmp_val;
-	//u8	i;
 	static u32 slide_rssi_index=0, slide_rssi_statistics=0;
 	static u32 slide_evm_index=0, slide_evm_statistics=0;
 	static u32 last_rssi=0, last_evm=0;
-	//cosa add for rx path selection
-//	static long slide_cck_adc_pwdb_index=0, slide_cck_adc_pwdb_statistics=0;
-//	static char last_cck_adc_pwdb[4]={0,0,0,0};
 	//cosa add for beacon rssi smoothing
 	static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0;
 	static u32 last_beacon_adc_pwdb=0;
@@ -4937,8 +3718,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 	sc = le16_to_cpu(hdr->seq_ctl);
 	frag = WLAN_GET_SEQ_FRAG(sc);
 	seq = WLAN_GET_SEQ_SEQ(sc);
-	//cosa add 04292008 to record the sequence number
-	pcurrent_stats->Seq_Num = seq;
+
 	//
 	// Check whether we should take the previous packet into accounting
 	//
@@ -4946,17 +3726,6 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 	{
 		// if previous packet is not aggregated packet
 		bcheck = true;
-	}else
-	{
-//remve for that we don't use AMPDU to calculate PWDB,because the reported PWDB of some AP is fault.
-#if 0
-		// if previous packet is aggregated packet, and current packet
-		//	(1) is not AMPDU
-		//	(2) is the first packet of one AMPDU
-		// that means the previous packet is the last one aggregated packet
-		if( !pcurrent_stats->bIsAMPDU || pcurrent_stats->bFirstMPDU)
-			bcheck = true;
-#endif
 	}
 
 	if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
@@ -4987,45 +3756,19 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 	if(!bcheck)
 		return;
 
-	rtl8190_process_cck_rxpathsel(priv,pprevious_stats);
-
-	//
-	// Check RSSI
-	//
-	priv->stats.num_process_phyinfo++;
-#if 0
-	/* record the general signal strength to the sliding window. */
-	if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX)
-	{
-		slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX;
-		last_rssi = priv->stats.slide_signal_strength[slide_rssi_index];
-		priv->stats.slide_rssi_total -= last_rssi;
-	}
-	priv->stats.slide_rssi_total += pprevious_stats->SignalStrength;
-
-	priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength;
-	if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX)
-		slide_rssi_index = 0;
-
-	// <1> Showed on UI for user, in dbm
-	tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
-	priv->stats.signal_strength = rtl819x_translate_todbm((u8)tmp_val);
-
-#endif
 	// <2> Showed on UI for engineering
 	// hardware does not provide rssi information for each rf path in CCK
 	if(!pprevious_stats->bIsCCK && pprevious_stats->bPacketToSelf)
 	{
 		for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++)
 		{
-			if (!rtl8192_phy_CheckIsLegalRFPath(priv->ieee80211->dev, rfpath))
+			if (!rtl8192_phy_CheckIsLegalRFPath(priv, rfpath))
 				continue;
-			RT_TRACE(COMP_DBG,"Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath]  = %d \n" ,pprevious_stats->RxMIMOSignalStrength[rfpath] );
+			RT_TRACE(COMP_DBG, "pPreviousstats->RxMIMOSignalStrength[rfpath] = %d\n", pprevious_stats->RxMIMOSignalStrength[rfpath]);
 			//Fixed by Jacken 2008-03-20
 			if(priv->stats.rx_rssi_percentage[rfpath] == 0)
 			{
 				priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath];
-				//DbgPrint("MIMO RSSI initialize \n");
 			}
 			if(pprevious_stats->RxMIMOSignalStrength[rfpath]  > priv->stats.rx_rssi_percentage[rfpath])
 			{
@@ -5040,7 +3783,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 					( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) +
 					(pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor);
 			}
-			RT_TRACE(COMP_DBG,"Jacken -> priv->RxStats.RxRSSIPercentage[rfPath]  = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] );
+			RT_TRACE(COMP_DBG, "priv->RxStats.RxRSSIPercentage[rfPath] = %d \n" , priv->stats.rx_rssi_percentage[rfpath]);
 		}
 	}
 
@@ -5057,12 +3800,10 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 			slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX;
 			last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index];
 			priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb;
-			//DbgPrint("slide_beacon_adc_pwdb_index = %d, last_beacon_adc_pwdb = %d, Adapter->RxStats.Slide_Beacon_Total = %d\n",
 			//	slide_beacon_adc_pwdb_index, last_beacon_adc_pwdb, Adapter->RxStats.Slide_Beacon_Total);
 		}
 		priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll;
 		priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll;
-		//DbgPrint("slide_beacon_adc_pwdb_index = %d, pPreviousRfd->Status.RxPWDBAll = %d\n", slide_beacon_adc_pwdb_index, pPreviousRfd->Status.RxPWDBAll);
 		slide_beacon_adc_pwdb_index++;
 		if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX)
 			slide_beacon_adc_pwdb_index = 0;
@@ -5080,9 +3821,8 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 		if(priv->undecorated_smoothed_pwdb < 0)	// initialize
 		{
 			priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll;
-			//DbgPrint("First pwdb initialize \n");
 		}
-#if 1
+
 		if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb)
 		{
 			priv->undecorated_smoothed_pwdb =
@@ -5096,21 +3836,6 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 					( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) +
 					(pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor);
 		}
-#else
-		//Fixed by Jacken 2008-03-20
-		if(pPreviousRfd->Status.RxPWDBAll > (u32)pHalData->UndecoratedSmoothedPWDB)
-		{
-			pHalData->UndecoratedSmoothedPWDB =
-					( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
-			pHalData->UndecoratedSmoothedPWDB = pHalData->UndecoratedSmoothedPWDB + 1;
-		}
-		else
-		{
-			pHalData->UndecoratedSmoothedPWDB =
-					( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6;
-		}
-#endif
-		rtl819x_update_rxsignalstatistics8190pci(priv,pprevious_stats);
 	}
 
 	//
@@ -5137,9 +3862,7 @@ static void rtl8192_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct
 
 			// <1> Showed on UI for user, in percentage.
 			tmp_val = priv->stats.slide_evm_total/slide_evm_statistics;
-			priv->stats.signal_quality = tmp_val;
 			//cosa add 10/11/2007, Showed on UI for user in Windows Vista, for Link quality.
-			priv->stats.last_signal_strength_inpercent = tmp_val;
 		}
 
 		// <2> Showed on UI for engineering
@@ -5279,12 +4002,6 @@ static void rtl8192_query_rxphystatus(
 	u8				is_cck_rate=0;
 	u8				rf_rx_num = 0;
 
-	/* 2007/07/04 MH For OFDM RSSI. For high power or not. */
-	static	u8		check_reg824 = 0;
-	static	u32		reg824_bit9 = 0;
-
-	priv->stats.numqry_phystatus++;
-
 	is_cck_rate = rx_hal_is_cck_rate(pdrvinfo);
 
 	// Record it for next packet processing
@@ -5295,10 +4012,10 @@ static void rtl8192_query_rxphystatus(
 	pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
 	pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
 	/*2007.08.30 requested by SD3 Jerry */
-	if(check_reg824 == 0)
+	if (priv->phy_check_reg824 == 0)
 	{
-		reg824_bit9 = rtl8192_QueryBBReg(priv->ieee80211->dev, rFPGA0_XA_HSSIParameter2, 0x200);
-		check_reg824 = 1;
+		priv->phy_reg824_bit9 = rtl8192_QueryBBReg(priv, rFPGA0_XA_HSSIParameter2, 0x200);
+		priv->phy_check_reg824 = 1;
 	}
 
 
@@ -5326,27 +4043,8 @@ static void rtl8192_query_rxphystatus(
 		// (2)PWDB, Average PWDB cacluated by hardware (for rate adaptive)
 		//
 		u8 report;//, cck_agc_rpt;
-#ifdef RTL8190P
-		u8 tmp_pwdb;
-		char cck_adc_pwdb[4];
-#endif
-		priv->stats.numqry_phystatusCCK++;
 
-#ifdef RTL8190P	//Only 90P 2T4R need to check
-		if(priv->rf_type == RF_2T4R && DM_RxPathSelTable.Enable && bpacket_match_bssid)
-		{
-			for(i=RF90_PATH_A; i<RF90_PATH_MAX; i++)
-			{
-				tmp_pwdb = pcck_buf->adc_pwdb_X[i];
-				cck_adc_pwdb[i] = (char)tmp_pwdb;
-				cck_adc_pwdb[i] /= 2;
-				pstats->cck_adc_pwdb[i] = precord_stats->cck_adc_pwdb[i] = cck_adc_pwdb[i];
-				//DbgPrint("RF-%d tmp_pwdb = 0x%x, cck_adc_pwdb = %d", i, tmp_pwdb, cck_adc_pwdb[i]);
-			}
-		}
-#endif
-
-		if(!reg824_bit9)
+		if (!priv->phy_reg824_bit9)
 		{
 			report = pcck_buf->cck_agc_rpt & 0xc0;
 			report = report>>6;
@@ -5422,7 +4120,6 @@ static void rtl8192_query_rxphystatus(
 	}
 	else
 	{
-		priv->stats.numqry_phystatusHT++;
 		//
 		// (1)Get RSSI for HT rate
 		//
@@ -5436,17 +4133,12 @@ static void rtl8192_query_rxphystatus(
 
 			//Fixed by Jacken from Bryant 2008-03-20
 			//Original value is 106
-#ifdef RTL8190P	   //Modify by Jacken 2008/03/31
-			rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 106;
-#else
 			rx_pwr[i] = ((pofdm_buf->trsw_gain_X[i]&0x3F)*2) - 110;
-#endif
 
 			//Get Rx snr value in DB
 			tmp_rxsnr = pofdm_buf->rxsnr_X[i];
 			rx_snrX = (char)(tmp_rxsnr);
 			rx_snrX /= 2;
-			priv->stats.rxSNRdB[i] = (long)rx_snrX;
 
 			/* Translate DBM to percentage. */
 			RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
@@ -5493,9 +4185,6 @@ static void rtl8192_query_rxphystatus(
 			rx_evmX /= 2;	//dbm
 
 			evm = rtl819x_evm_dbtopercentage(rx_evmX);
-#if 0
-			EVM = SignalScaleMapping(EVM);//make it good looking, from 0~100
-#endif
 			if(bpacket_match_bssid)
 			{
 				if(i==0) // Fill value in RFD, Get the first spatial stream only
@@ -5508,10 +4197,6 @@ static void rtl8192_query_rxphystatus(
 		/* record rx statistics for debug */
 		rxsc_sgien_exflg = pofdm_buf->rxsc_sgien_exflg;
 		prxsc = (phy_ofdm_rx_status_rxsc_sgien_exintfflag *)&rxsc_sgien_exflg;
-		if(pdrvinfo->BW)	//40M channel
-			priv->stats.received_bwtype[1+prxsc->rxsc]++;
-		else				//20M channel
-			priv->stats.received_bwtype[0]++;
 	}
 
 	//UI BSS List signal strength(in percentage), make it good looking, from 0~100.
@@ -5538,22 +4223,19 @@ rtl8192_record_rxdesc_forlateruse(
 {
 	ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
 	ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
-	//ptarget_stats->Seq_Num = psrc_stats->Seq_Num;
 }
 
 
 
-static void TranslateRxSignalStuff819xpci(struct net_device *dev,
+static void TranslateRxSignalStuff819xpci(struct r8192_priv *priv,
         struct sk_buff *skb,
         struct ieee80211_rx_stats * pstats,
         prx_desc_819x_pci pdesc,
         prx_fwinfo_819x_pci pdrvinfo)
 {
     // TODO: We must only check packet for current MAC address. Not finish
-    struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
     bool bpacket_match_bssid, bpacket_toself;
     bool bPacketBeacon=false, bToSelfBA=false;
-    static struct ieee80211_rx_stats  previous_stats;
     struct ieee80211_hdr_3addr *hdr;
     u16 fc,type;
 
@@ -5572,79 +4254,77 @@ static void TranslateRxSignalStuff819xpci(struct net_device *dev,
 
     /* Check if the received packet is acceptabe. */
     bpacket_match_bssid = ((IEEE80211_FTYPE_CTL != type) &&
-            (eqMacAddr(priv->ieee80211->current_network.bssid,	(fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
+            (!compare_ether_addr(priv->ieee80211->current_network.bssid,	(fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
             && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV));
-    bpacket_toself =  bpacket_match_bssid & (eqMacAddr(praddr, priv->ieee80211->dev->dev_addr));
-#if 1//cosa
+    bpacket_toself =  bpacket_match_bssid & (!compare_ether_addr(praddr, priv->ieee80211->dev->dev_addr));
+
     if(WLAN_FC_GET_FRAMETYPE(fc)== IEEE80211_STYPE_BEACON)
     {
         bPacketBeacon = true;
-        //DbgPrint("Beacon 2, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
     }
     if(WLAN_FC_GET_FRAMETYPE(fc) == IEEE80211_STYPE_BLOCKACK)
     {
-        if((eqMacAddr(praddr,dev->dev_addr)))
+        if (!compare_ether_addr(praddr, priv->ieee80211->dev->dev_addr))
             bToSelfBA = true;
-        //DbgPrint("BlockAck, MatchBSSID = %d, ToSelf = %d \n", bPacketMatchBSSID, bPacketToSelf);
     }
 
-#endif
-    if(bpacket_match_bssid)
-    {
-        priv->stats.numpacket_matchbssid++;
-    }
-    if(bpacket_toself){
-        priv->stats.numpacket_toself++;
-    }
     //
     // Process PHY information for previous packet (RSSI/PWDB/EVM)
     //
     // Because phy information is contained in the last packet of AMPDU only, so driver
     // should process phy information of previous packet
-    rtl8192_process_phyinfo(priv, tmp_buf,&previous_stats, pstats);
-    rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &previous_stats, bpacket_match_bssid,
+    rtl8192_process_phyinfo(priv, tmp_buf, &priv->previous_stats, pstats);
+    rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &priv->previous_stats, bpacket_match_bssid,
             bpacket_toself ,bPacketBeacon, bToSelfBA);
-    rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
+    rtl8192_record_rxdesc_forlateruse(pstats, &priv->previous_stats);
 
 }
 
 
-static void rtl8192_tx_resume(struct net_device *dev)
+static void rtl8192_tx_resume(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	struct ieee80211_device *ieee = priv->ieee80211;
 	struct sk_buff *skb;
-	int queue_index;
+	int i;
 
-	for(queue_index = BK_QUEUE; queue_index < TXCMD_QUEUE;queue_index++) {
-		while((!skb_queue_empty(&ieee->skb_waitQ[queue_index]))&&
-				(priv->ieee80211->check_nic_enough_desc(dev,queue_index) > 0)) {
+	for (i = BK_QUEUE; i < TXCMD_QUEUE; i++) {
+		while ((!skb_queue_empty(&ieee->skb_waitQ[i])) &&
+		       (priv->ieee80211->check_nic_enough_desc(ieee, i) > 0)) {
 			/* 1. dequeue the packet from the wait queue */
-			skb = skb_dequeue(&ieee->skb_waitQ[queue_index]);
+			skb = skb_dequeue(&ieee->skb_waitQ[i]);
 			/* 2. tx the packet directly */
-			ieee->softmac_data_hard_start_xmit(skb,dev,0/* rate useless now*/);
-			#if 0
-			if(queue_index!=MGNT_QUEUE) {
-				ieee->stats.tx_packets++;
-				ieee->stats.tx_bytes += skb->len;
-			}
-			#endif
+			ieee->softmac_data_hard_start_xmit(skb, ieee, 0);
 		}
 	}
 }
 
-static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
+static void rtl8192_irq_tx_tasklet(unsigned long arg)
 {
-       rtl8192_tx_resume(priv->ieee80211->dev);
+	struct r8192_priv *priv = (struct r8192_priv*) arg;
+	struct rtl8192_tx_ring *mgnt_ring = &priv->tx_ring[MGNT_QUEUE];
+	unsigned long flags;
+
+	/* check if we need to report that the management queue is drained */
+	spin_lock_irqsave(&priv->irq_th_lock, flags);
+
+	if (!skb_queue_len(&mgnt_ring->queue) &&
+	    priv->ieee80211->ack_tx_to_ieee &&
+	    rtl8192_is_tx_queue_empty(priv->ieee80211)) {
+		priv->ieee80211->ack_tx_to_ieee = 0;
+		ieee80211_ps_tx_ack(priv->ieee80211, 1);
+	}
+
+	spin_unlock_irqrestore(&priv->irq_th_lock, flags);
+
+	rtl8192_tx_resume(priv);
 }
 
 /* Record the received data rate */
 static void UpdateReceivedRateHistogramStatistics8190(
-	struct net_device *dev,
+	struct r8192_priv *priv,
 	struct ieee80211_rx_stats* pstats
 	)
 {
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	u32 rcvType=1;   //0: Total, 1:OK, 2:CRC, 3:ICV
 	u32 rateIndex;
 	u32 preamble_guardinterval;  //1: short preamble/GI, 0: long preamble/GI
@@ -5700,14 +4380,12 @@ static void UpdateReceivedRateHistogramStatistics8190(
 	    	case MGN_MCS15: rateIndex = 27; break;
 		default:        rateIndex = 28; break;
 	}
-	priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++;
 	priv->stats.received_rate_histogram[0][rateIndex]++; //total
 	priv->stats.received_rate_histogram[rcvType][rateIndex]++;
 }
 
-static void rtl8192_rx(struct net_device *dev)
+static void rtl8192_rx(struct r8192_priv *priv)
 {
-    struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
     struct ieee80211_hdr_1addr *ieee80211_hdr = NULL;
     bool unicast_packet = false;
     struct ieee80211_rx_stats stats = {
@@ -5717,17 +4395,17 @@ static void rtl8192_rx(struct net_device *dev)
         .freq = IEEE80211_24GHZ_BAND,
     };
     unsigned int count = priv->rxringcount;
-
-    stats.nic_type = NIC_8192E;
+    prx_fwinfo_819x_pci pDrvInfo = NULL;
+    struct sk_buff *new_skb;
 
     while (count--) {
         rx_desc_819x_pci *pdesc = &priv->rx_ring[priv->rx_idx];//rx descriptor
         struct sk_buff *skb = priv->rx_buf[priv->rx_idx];//rx pkt
 
-        if (pdesc->OWN){
+        if (pdesc->OWN)
             /* wait data to be filled by hardware */
             return;
-        } else {
+
             stats.bICV = pdesc->ICV;
             stats.bCRC = pdesc->CRC32;
             stats.bHwError = pdesc->CRC32 | pdesc->ICV;
@@ -5738,23 +4416,13 @@ static void rtl8192_rx(struct net_device *dev)
 
             if(stats.bHwError) {
                 stats.bShift = false;
-
-                if(pdesc->CRC32) {
-                    if (pdesc->Length <500)
-                        priv->stats.rxcrcerrmin++;
-                    else if (pdesc->Length >1000)
-                        priv->stats.rxcrcerrmax++;
-                    else
-                        priv->stats.rxcrcerrmid++;
-                }
                 goto done;
-            } else {
-                prx_fwinfo_819x_pci pDrvInfo = NULL;
-                struct sk_buff *new_skb = dev_alloc_skb(priv->rxbuffersize);
+            }
+                pDrvInfo = NULL;
+                new_skb = dev_alloc_skb(priv->rxbuffersize);
 
-                if (unlikely(!new_skb)) {
+                if (unlikely(!new_skb))
                     goto done;
-                }
 
                 stats.RxDrvInfoSize = pdesc->RxDrvInfoSize;
                 stats.RxBufShift = ((pdesc->Shift)&0x03);
@@ -5774,15 +4442,15 @@ static void rtl8192_rx(struct net_device *dev)
                 /* it is debug only. It should be disabled in released driver.
                  * 2007.1.11 by Emily
                  * */
-                UpdateReceivedRateHistogramStatistics8190(dev, &stats);
+                UpdateReceivedRateHistogramStatistics8190(priv, &stats);
 
                 stats.bIsAMPDU = (pDrvInfo->PartAggr==1);
                 stats.bFirstMPDU = (pDrvInfo->PartAggr==1) && (pDrvInfo->FirstAGGR==1);
 
                 stats.TimeStampLow = pDrvInfo->TSFL;
-                stats.TimeStampHigh = read_nic_dword(dev, TSFR+4);
+                stats.TimeStampHigh = read_nic_dword(priv, TSFR+4);
 
-                UpdateRxPktTimeStamp8190(dev, &stats);
+                UpdateRxPktTimeStamp8190(priv, &stats);
 
                 //
                 // Get Total offset of MPDU Frame Body
@@ -5790,10 +4458,8 @@ static void rtl8192_rx(struct net_device *dev)
                 if((stats.RxBufShift + stats.RxDrvInfoSize) > 0)
                     stats.bShift = 1;
 
-                stats.RxIs40MHzPacket = pDrvInfo->BW;
-
                 /* ???? */
-                TranslateRxSignalStuff819xpci(dev,skb, &stats, pdesc, pDrvInfo);
+                TranslateRxSignalStuff819xpci(priv, skb, &stats, pdesc, pDrvInfo);
 
                 /* Rx A-MPDU */
                 if(pDrvInfo->FirstAGGR==1 || pDrvInfo->PartAggr == 1)
@@ -5813,11 +4479,6 @@ static void rtl8192_rx(struct net_device *dev)
                     unicast_packet = true;
                 }
 
-                stats.packetlength = stats.Length-4;
-                stats.fraglength = stats.packetlength;
-                stats.fragoffset = 0;
-                stats.ntotalfrag = 1;
-
                 if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){
                     dev_kfree_skb_any(skb);
                 } else {
@@ -5833,9 +4494,7 @@ static void rtl8192_rx(struct net_device *dev)
                 skb = new_skb;
                 priv->rx_buf[priv->rx_idx] = skb;
                 *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
-            }
 
-        }
 done:
         pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
         pdesc->OWN = 1;
@@ -5847,11 +4506,12 @@ done:
 
 }
 
-static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
+static void rtl8192_irq_rx_tasklet(unsigned long arg)
 {
-       rtl8192_rx(priv->ieee80211->dev);
+	struct r8192_priv *priv = (struct r8192_priv*) arg;
+	rtl8192_rx(priv);
 	/* unmask RDU */
-       write_nic_dword(priv->ieee80211->dev, INTA_MASK,read_nic_dword(priv->ieee80211->dev, INTA_MASK) | IMR_RDU);
+       write_nic_dword(priv, INTA_MASK, read_nic_dword(priv, INTA_MASK) | IMR_RDU);
 }
 
 static const struct net_device_ops rtl8192_netdev_ops = {
@@ -5867,19 +4527,13 @@ static const struct net_device_ops rtl8192_netdev_ops = {
 static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
 			 const struct pci_device_id *id)
 {
-	unsigned long ioaddr = 0;
 	struct net_device *dev = NULL;
 	struct r8192_priv *priv= NULL;
 	u8 unit = 0;
 	int ret = -ENODEV;
-
-#ifdef CONFIG_RTL8192_IO_MAP
-	unsigned long pio_start, pio_len, pio_flags;
-#else
 	unsigned long pmem_start, pmem_len, pmem_flags;
-#endif //end #ifdef RTL_IO_MAP
 
-	RT_TRACE(COMP_INIT,"Configuring chip resources");
+	RT_TRACE(COMP_INIT,"Configuring chip resources\n");
 
 	if( pci_enable_device (pdev) ){
 		RT_TRACE(COMP_ERR,"Failed to enable PCI device");
@@ -5908,55 +4562,30 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
 		priv->ieee80211->bSupportRemoteWakeUp = 0;
 	}
 
-#ifdef CONFIG_RTL8192_IO_MAP
-
-	pio_start = (unsigned long)pci_resource_start (pdev, 0);
-	pio_len = (unsigned long)pci_resource_len (pdev, 0);
-	pio_flags = (unsigned long)pci_resource_flags (pdev, 0);
-
-      	if (!(pio_flags & IORESOURCE_IO)) {
-		RT_TRACE(COMP_ERR,"region #0 not a PIO resource, aborting");
-		goto fail;
-	}
-
-	//DMESG("IO space @ 0x%08lx", pio_start );
-	if( ! request_region( pio_start, pio_len, RTL819xE_MODULE_NAME ) ){
-		RT_TRACE(COMP_ERR,"request_region failed!");
-		goto fail;
-	}
-
-	ioaddr = pio_start;
-	dev->base_addr = ioaddr; // device I/O address
-
-#else
-
 	pmem_start = pci_resource_start(pdev, 1);
 	pmem_len = pci_resource_len(pdev, 1);
 	pmem_flags = pci_resource_flags (pdev, 1);
 
 	if (!(pmem_flags & IORESOURCE_MEM)) {
-		RT_TRACE(COMP_ERR,"region #1 not a MMIO resource, aborting");
+		RT_TRACE(COMP_ERR, "region #1 not a MMIO resource, aborting\n");
 		goto fail;
 	}
 
 	//DMESG("Memory mapped space @ 0x%08lx ", pmem_start);
 	if( ! request_mem_region(pmem_start, pmem_len, RTL819xE_MODULE_NAME)) {
-		RT_TRACE(COMP_ERR,"request_mem_region failed!");
+		RT_TRACE(COMP_ERR,"request_mem_region failed!\n");
 		goto fail;
 	}
 
-
-	ioaddr = (unsigned long)ioremap_nocache( pmem_start, pmem_len);
-	if( ioaddr == (unsigned long)NULL ){
-		RT_TRACE(COMP_ERR,"ioremap failed!");
-	       // release_mem_region( pmem_start, pmem_len );
+	priv->mem_start = ioremap_nocache(pmem_start, pmem_len);
+	if (!priv->mem_start) {
+		RT_TRACE(COMP_ERR,"ioremap failed!\n");
 		goto fail1;
 	}
 
-	dev->mem_start = ioaddr; // shared mem start
-	dev->mem_end = ioaddr + pci_resource_len(pdev, 0); // shared mem end
-
-#endif //end #ifdef RTL_IO_MAP
+	dev->mem_start = (unsigned long) priv->mem_start;
+	dev->mem_end = (unsigned long) (priv->mem_start +
+					pci_resource_len(pdev, 0));
 
         /* We disable the RETRY_TIMEOUT register (0x41) to keep
          * PCI Tx retries from interfering with C3 CPU state */
@@ -5970,28 +4599,11 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
 	priv->irq = 0;
 
 	dev->netdev_ops = &rtl8192_netdev_ops;
-#if 0
-	dev->open = rtl8192_open;
-	dev->stop = rtl8192_close;
-	//dev->hard_start_xmit = rtl8192_8023_hard_start_xmit;
-	dev->tx_timeout = tx_timeout;
-	//dev->wireless_handlers = &r8192_wx_handlers_def;
-	dev->do_ioctl = rtl8192_ioctl;
-	dev->set_multicast_list = r8192_set_multicast;
-	dev->set_mac_address = r8192_set_mac_adr;
-#endif
 
-         //DMESG("Oops: i'm coming\n");
-#if WIRELESS_EXT >= 12
-#if WIRELESS_EXT < 17
-        dev->get_wireless_stats = r8192_get_wireless_stats;
-#endif
-        dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def;
-#endif
-       //dev->get_wireless_stats = r8192_get_wireless_stats;
+	dev->wireless_handlers = &r8192_wx_handlers_def;
 	dev->type=ARPHRD_ETHER;
 
-	dev->watchdog_timeo = HZ*3;	//modified by john, 0805
+	dev->watchdog_timeo = HZ*3;
 
 	if (dev_alloc_name(dev, ifname) < 0){
                 RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n");
@@ -6000,17 +4612,14 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
         }
 
 	RT_TRACE(COMP_INIT, "Driver probe completed1\n");
-	if(rtl8192_init(dev)!=0){
-		RT_TRACE(COMP_ERR, "Initialization failed");
+	if (rtl8192_init(priv)!=0) {
+		RT_TRACE(COMP_ERR, "Initialization failed\n");
 		goto fail;
 	}
 
-	netif_carrier_off(dev);
-	netif_stop_queue(dev);
-
 	register_netdev(dev);
 	RT_TRACE(COMP_INIT, "dev name=======> %s\n",dev->name);
-	rtl8192_proc_init_one(dev);
+	rtl8192_proc_init_one(priv);
 
 
 	RT_TRACE(COMP_INIT, "Driver probe completed\n");
@@ -6018,27 +4627,18 @@ static int __devinit rtl8192_pci_probe(struct pci_dev *pdev,
 
 fail1:
 
-#ifdef CONFIG_RTL8180_IO_MAP
-
-	if( dev->base_addr != 0 ){
-
-		release_region(dev->base_addr,
-	       pci_resource_len(pdev, 0) );
-	}
-#else
-	if( dev->mem_start != (unsigned long)NULL ){
-		iounmap( (void *)dev->mem_start );
+	if (priv->mem_start) {
+		iounmap(priv->mem_start);
 		release_mem_region( pci_resource_start(pdev, 1),
 				    pci_resource_len(pdev, 1) );
 	}
-#endif //end #ifdef RTL_IO_MAP
 
 fail:
 	if(dev){
 
 		if (priv->irq) {
-			free_irq(dev->irq, dev);
-			dev->irq=0;
+			free_irq(priv->irq, priv);
+			priv->irq = 0;
 		}
 		free_ieee80211(dev);
 	}
@@ -6065,15 +4665,9 @@ static void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
 	cancel_delayed_work(&priv->watch_dog_wq);
 	cancel_delayed_work(&priv->update_beacon_wq);
 	cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq);
-	cancel_delayed_work(&priv->ieee80211->hw_sleep_wq);
-#ifdef RTL8192E
 	cancel_delayed_work(&priv->gpio_change_rf_wq);
-#endif
 	cancel_work_sync(&priv->reset_wq);
 	cancel_work_sync(&priv->qos_activate);
-	//cancel_work_sync(&priv->SetBWModeWorkItem);
-	//cancel_work_sync(&priv->SwChnlWorkItem);
-
 }
 
 
@@ -6081,14 +4675,15 @@ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct r8192_priv *priv ;
+	u32 i;
 
- 	if(dev){
+	if (dev) {
 
 		unregister_netdev(dev);
 
-		priv=ieee80211_priv(dev);
+		priv = ieee80211_priv(dev);
 
-		rtl8192_proc_remove_one(dev);
+		rtl8192_proc_remove_one(priv);
 
 		rtl8192_down(dev);
 		if (priv->pFirmware)
@@ -6096,49 +4691,26 @@ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev)
 			vfree(priv->pFirmware);
 			priv->pFirmware = NULL;
 		}
-	//	priv->rf_close(dev);
-	//	rtl8192_usb_deleteendpoints(dev);
 		destroy_workqueue(priv->priv_wq);
-                /* redundant with rtl8192_down */
-               // rtl8192_irq_disable(dev);
-               // rtl8192_reset(dev);
-               // mdelay(10);
-                {
-                    u32 i;
-                    /* free tx/rx rings */
-                    rtl8192_free_rx_ring(dev);
-                    for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) {
-                        rtl8192_free_tx_ring(dev, i);
-                    }
-                }
-		if(priv->irq){
 
-			printk("Freeing irq %d\n",dev->irq);
-			free_irq(dev->irq, dev);
-			priv->irq=0;
+		/* free tx/rx rings */
+		rtl8192_free_rx_ring(priv);
+		for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
+			rtl8192_free_tx_ring(priv, i);
 
+		if (priv->irq) {
+			printk("Freeing irq %d\n", priv->irq);
+			free_irq(priv->irq, priv);
+			priv->irq = 0;
 		}
 
-
-
-	//	free_beacon_desc_ring(dev,priv->txbeaconcount);
-
-#ifdef CONFIG_RTL8180_IO_MAP
-
-		if( dev->base_addr != 0 ){
-
-			release_region(dev->base_addr,
-				       pci_resource_len(pdev, 0) );
-		}
-#else
-		if( dev->mem_start != (unsigned long)NULL ){
-			iounmap( (void *)dev->mem_start );
+		if (priv->mem_start) {
+			iounmap(priv->mem_start);
 			release_mem_region( pci_resource_start(pdev, 1),
 					    pci_resource_len(pdev, 1) );
 		}
-#endif /*end #ifdef RTL_IO_MAP*/
-		free_ieee80211(dev);
 
+		free_ieee80211(dev);
 	}
 
 	pci_disable_device(pdev);
@@ -6158,8 +4730,7 @@ static int __init rtl8192_pci_module_init(void)
 
 	printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n");
 	printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan\n");
-	RT_TRACE(COMP_INIT, "Initializing module");
-	RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT);
+	RT_TRACE(COMP_INIT, "Initializing module\n");
 	rtl8192_proc_module_init();
       if(0!=pci_register_driver(&rtl8192_pci_driver))
 	{
@@ -6175,168 +4746,133 @@ static void __exit rtl8192_pci_module_exit(void)
 {
 	pci_unregister_driver(&rtl8192_pci_driver);
 
-	RT_TRACE(COMP_DOWN, "Exiting");
+	RT_TRACE(COMP_DOWN, "Exiting\n");
 	rtl8192_proc_module_remove();
 	ieee80211_rtl_exit();
 }
 
-//warning message WB
-static irqreturn_t rtl8192_interrupt(int irq, void *netdev)
+static irqreturn_t rtl8192_interrupt(int irq, void *param)
 {
-    struct net_device *dev = (struct net_device *) netdev;
-    struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
-    unsigned long flags;
-    u32 inta;
-    /* We should return IRQ_NONE, but for now let me keep this */
-    if(priv->irq_enabled == 0){
-        return IRQ_HANDLED;
-    }
-
-    spin_lock_irqsave(&priv->irq_th_lock,flags);
-
-    //ISR: 4bytes
-
-    inta = read_nic_dword(dev, ISR);// & priv->IntrMask;
-    write_nic_dword(dev,ISR,inta); // reset int situation
-
-    priv->stats.shints++;
-    //DMESG("Enter interrupt, ISR value = 0x%08x", inta);
-    if(!inta){
-        spin_unlock_irqrestore(&priv->irq_th_lock,flags);
-        return IRQ_HANDLED;
-        /*
-           most probably we can safely return IRQ_NONE,
-           but for now is better to avoid problems
-           */
-    }
-
-    if(inta == 0xffff){
-        /* HW disappared */
-        spin_unlock_irqrestore(&priv->irq_th_lock,flags);
-        return IRQ_HANDLED;
-    }
+	struct r8192_priv *priv = param;
+	struct net_device *dev = priv->ieee80211->dev;
+	unsigned long flags;
+	u32 inta;
+	irqreturn_t ret = IRQ_HANDLED;
 
-    priv->stats.ints++;
-#ifdef DEBUG_IRQ
-    DMESG("NIC irq %x",inta);
-#endif
-    //priv->irqpending = inta;
+	spin_lock_irqsave(&priv->irq_th_lock, flags);
 
+	/* ISR: 4bytes */
 
-    if(!netif_running(dev)) {
-        spin_unlock_irqrestore(&priv->irq_th_lock,flags);
-        return IRQ_HANDLED;
-    }
+	inta = read_nic_dword(priv, ISR); /* & priv->IntrMask; */
+	write_nic_dword(priv, ISR, inta); /* reset int situation */
 
-    if(inta & IMR_TIMEOUT0){
-        //		write_nic_dword(dev, TimerInt, 0);
-        //DMESG("=================>waking up");
-        //		rtl8180_hw_wakeup(dev);
-    }
+	if (!inta) {
+		/*
+		 * most probably we can safely return IRQ_NONE,
+		 * but for now is better to avoid problems
+		 */
+		goto out_unlock;
+	}
 
-    if(inta & IMR_TBDOK){
-        RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
-        rtl8192_tx_isr(dev, BEACON_QUEUE);
-        priv->stats.txbeaconokint++;
-    }
+	if (inta == 0xffff) {
+		/* HW disappared */
+		goto out_unlock;
+	}
 
-    if(inta & IMR_TBDER){
-        RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
-        rtl8192_tx_isr(dev, BEACON_QUEUE);
-        priv->stats.txbeaconerr++;
-    }
+	if (!netif_running(dev))
+		goto out_unlock;
 
-    if(inta  & IMR_MGNTDOK ) {
-        RT_TRACE(COMP_INTR, "Manage ok interrupt!\n");
-        priv->stats.txmanageokint++;
-        rtl8192_tx_isr(dev,MGNT_QUEUE);
+	if (inta & IMR_TBDOK) {
+		RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+		rtl8192_tx_isr(priv, BEACON_QUEUE);
+		priv->stats.txbeaconokint++;
+	}
 
-    }
+	if (inta & IMR_TBDER) {
+		RT_TRACE(COMP_INTR, "beacon ok interrupt!\n");
+		rtl8192_tx_isr(priv, BEACON_QUEUE);
+		priv->stats.txbeaconerr++;
+	}
 
-    if(inta & IMR_COMDOK)
-    {
-        priv->stats.txcmdpktokint++;
-        rtl8192_tx_isr(dev,TXCMD_QUEUE);
-    }
+	if (inta & IMR_MGNTDOK ) {
+		RT_TRACE(COMP_INTR, "Manage ok interrupt!\n");
+		priv->stats.txmanageokint++;
+		rtl8192_tx_isr(priv, MGNT_QUEUE);
+	}
 
-    if(inta & IMR_ROK){
-#ifdef DEBUG_RX
-        DMESG("Frame arrived !");
-#endif
-        priv->stats.rxint++;
-        tasklet_schedule(&priv->irq_rx_tasklet);
-    }
+	if (inta & IMR_COMDOK)
+	{
+		priv->stats.txcmdpktokint++;
+		rtl8192_tx_isr(priv, TXCMD_QUEUE);
+	}
 
-    if(inta & IMR_BcnInt) {
-        RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n");
-        tasklet_schedule(&priv->irq_prepare_beacon_tasklet);
-    }
+	if (inta & IMR_ROK) {
+		priv->stats.rxint++;
+		tasklet_schedule(&priv->irq_rx_tasklet);
+	}
 
-    if(inta & IMR_RDU){
-        RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
-        priv->stats.rxrdu++;
-        /* reset int situation */
-        write_nic_dword(dev,INTA_MASK,read_nic_dword(dev, INTA_MASK) & ~IMR_RDU);
-        tasklet_schedule(&priv->irq_rx_tasklet);
-    }
+	if (inta & IMR_BcnInt) {
+		RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n");
+		tasklet_schedule(&priv->irq_prepare_beacon_tasklet);
+	}
 
-    if(inta & IMR_RXFOVW){
-        RT_TRACE(COMP_INTR, "rx overflow !\n");
-        priv->stats.rxoverflow++;
-        tasklet_schedule(&priv->irq_rx_tasklet);
-    }
+	if (inta & IMR_RDU) {
+		RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
+		priv->stats.rxrdu++;
+		/* reset int situation */
+		write_nic_dword(priv, INTA_MASK, read_nic_dword(priv, INTA_MASK) & ~IMR_RDU);
+		tasklet_schedule(&priv->irq_rx_tasklet);
+	}
 
-    if(inta & IMR_TXFOVW) priv->stats.txoverflow++;
+	if (inta & IMR_RXFOVW) {
+		RT_TRACE(COMP_INTR, "rx overflow !\n");
+		priv->stats.rxoverflow++;
+		tasklet_schedule(&priv->irq_rx_tasklet);
+	}
 
-    if(inta & IMR_BKDOK){
-        RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n");
-        priv->stats.txbkokint++;
-        priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
-        rtl8192_tx_isr(dev,BK_QUEUE);
-        rtl8192_try_wake_queue(dev, BK_QUEUE);
-    }
+	if (inta & IMR_TXFOVW)
+		priv->stats.txoverflow++;
 
-    if(inta & IMR_BEDOK){
-        RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n");
-        priv->stats.txbeokint++;
-        priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
-        rtl8192_tx_isr(dev,BE_QUEUE);
-        rtl8192_try_wake_queue(dev, BE_QUEUE);
-    }
+	if (inta & IMR_BKDOK) {
+		RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n");
+		priv->stats.txbkokint++;
+		priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(priv, BK_QUEUE);
+	}
 
-    if(inta & IMR_VIDOK){
-        RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n");
-        priv->stats.txviokint++;
-        priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
-        rtl8192_tx_isr(dev,VI_QUEUE);
-        rtl8192_try_wake_queue(dev, VI_QUEUE);
-    }
+	if (inta & IMR_BEDOK) {
+		RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n");
+		priv->stats.txbeokint++;
+		priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(priv, BE_QUEUE);
+	}
 
-    if(inta & IMR_VODOK){
-        priv->stats.txvookint++;
-        priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
-        rtl8192_tx_isr(dev,VO_QUEUE);
-        rtl8192_try_wake_queue(dev, VO_QUEUE);
-    }
+	if (inta & IMR_VIDOK) {
+		RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n");
+		priv->stats.txviokint++;
+		priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(priv, VI_QUEUE);
+	}
 
-    spin_unlock_irqrestore(&priv->irq_th_lock,flags);
+	if (inta & IMR_VODOK) {
+		priv->stats.txvookint++;
+		priv->ieee80211->LinkDetectInfo.NumTxOkInPeriod++;
+		rtl8192_tx_isr(priv, VO_QUEUE);
+	}
 
-    return IRQ_HANDLED;
-}
+out_unlock:
+	spin_unlock_irqrestore(&priv->irq_th_lock, flags);
 
-static void rtl8192_try_wake_queue(struct net_device *dev, int pri)
-{
+	return ret;
 }
 
-
-void EnableHWSecurityConfig8192(struct net_device *dev)
+void EnableHWSecurityConfig8192(struct r8192_priv *priv)
 {
         u8 SECR_value = 0x0;
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	struct ieee80211_device* ieee = priv->ieee80211;
 
 	SECR_value = SCR_TxEncEnable | SCR_RxDecEnable;
-#if 1
+
 	if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->ieee80211->auth_mode != 2))
 	{
 		SECR_value |= SCR_RxUseDK;
@@ -6348,8 +4884,6 @@ void EnableHWSecurityConfig8192(struct net_device *dev)
 		SECR_value |= SCR_TxUseDK;
 	}
 
-#endif
-
         //add HWSec active enable here.
 //default using hwsec. when peer AP is in N mode only and pairwise_key_type is none_aes(which HT_IOT_ACT_PURE_N_MODE indicates it), use software security. when peer AP is in b,g,n mode mixed and pairwise_key_type is none_aes, use g mode hw security. WB on 2008.7.4
 	ieee->hwsec_active = 1;
@@ -6363,31 +4897,26 @@ void EnableHWSecurityConfig8192(struct net_device *dev)
 	RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__,
 			ieee->hwsec_active, ieee->pairwise_key_type, SECR_value);
 	{
-                write_nic_byte(dev, SECR,  SECR_value);//SECR_value |  SCR_UseDK );
+                write_nic_byte(priv, SECR,  SECR_value);//SECR_value |  SCR_UseDK );
         }
 
 }
 #define TOTAL_CAM_ENTRY 32
 //#define CAM_CONTENT_COUNT 8
-void setKey(	struct net_device *dev,
-		u8 EntryNo,
-		u8 KeyIndex,
-		u16 KeyType,
-		const u8 *MacAddr,
-		u8 DefaultKey,
-		u32 *KeyContent )
+void setKey(struct r8192_priv *priv, u8 EntryNo, u8 KeyIndex, u16 KeyType,
+	    const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
 {
 	u32 TargetCommand = 0;
 	u32 TargetContent = 0;
 	u16 usConfig = 0;
 	u8 i;
 #ifdef ENABLE_IPS
-	struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
 	RT_RF_POWER_STATE	rtState;
-	rtState = priv->ieee80211->eRFPowerState;
-	if(priv->ieee80211->PowerSaveControl.bInactivePs){
+
+	rtState = priv->eRFPowerState;
+	if (priv->PowerSaveControl.bInactivePs){
 		if(rtState == eRfOff){
-			if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+			if(priv->RfOffReason > RF_CHANGE_BY_IPS)
 			{
 				RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
 				//up(&priv->wx_sem);
@@ -6395,7 +4924,7 @@ void setKey(	struct net_device *dev,
 			}
 			else{
 				down(&priv->ieee80211->ips_sem);
-				IPSLeave(dev);
+				IPSLeave(priv);
 				up(&priv->ieee80211->ips_sem);
 			}
 		}
@@ -6405,7 +4934,7 @@ void setKey(	struct net_device *dev,
 	if (EntryNo >= TOTAL_CAM_ENTRY)
 		RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
 
-	RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
+	RT_TRACE(COMP_SEC, "====>to setKey(), priv:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", priv, EntryNo, KeyIndex, KeyType, MacAddr);
 
 	if (DefaultKey)
 		usConfig |= BIT15 | (KeyType<<2);
@@ -6423,34 +4952,32 @@ void setKey(	struct net_device *dev,
 					(u32)(*(MacAddr+1)) << 24|
 					(u32)usConfig;
 
-			write_nic_dword(dev, WCAMI, TargetContent);
-			write_nic_dword(dev, RWCAM, TargetCommand);
-	//		printk("setkey cam =%8x\n", read_cam(dev, i+6*EntryNo));
+			write_nic_dword(priv, WCAMI, TargetContent);
+			write_nic_dword(priv, RWCAM, TargetCommand);
 		}
 		else if(i==1){//MAC
                         TargetContent = (u32)(*(MacAddr+2)) 	 |
                                         (u32)(*(MacAddr+3)) <<  8|
                                         (u32)(*(MacAddr+4)) << 16|
                                         (u32)(*(MacAddr+5)) << 24;
-			write_nic_dword(dev, WCAMI, TargetContent);
-			write_nic_dword(dev, RWCAM, TargetCommand);
+			write_nic_dword(priv, WCAMI, TargetContent);
+			write_nic_dword(priv, RWCAM, TargetCommand);
 		}
 		else {	//Key Material
 			if(KeyContent != NULL)
 			{
-			write_nic_dword(dev, WCAMI, (u32)(*(KeyContent+i-2)) );
-			write_nic_dword(dev, RWCAM, TargetCommand);
+			write_nic_dword(priv, WCAMI, (u32)(*(KeyContent+i-2)) );
+			write_nic_dword(priv, RWCAM, TargetCommand);
 		}
 	}
 	}
 	RT_TRACE(COMP_SEC,"=========>after set key, usconfig:%x\n", usConfig);
 }
 
-bool NicIFEnableNIC(struct net_device* dev)
+bool NicIFEnableNIC(struct r8192_priv *priv)
 {
 	RT_STATUS init_status = RT_STATUS_SUCCESS;
-	struct r8192_priv* priv = ieee80211_priv(dev);
-	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 
 	//YJ,add,091109
 	if (priv->up == 0){
@@ -6463,27 +4990,25 @@ bool NicIFEnableNIC(struct net_device* dev)
 
 	// <2> Enable Adapter
 	//priv->bfirst_init = true;
-	init_status = rtl8192_adapter_start(dev);
+	init_status = rtl8192_adapter_start(priv);
 	if (init_status != RT_STATUS_SUCCESS) {
 		RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
 		priv->bdisable_nic = false;  //YJ,add,091111
 		return -1;
 	}
-	//printk("start adapter finished\n");
 	RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
 	//priv->bfirst_init = false;
 
 	// <3> Enable Interrupt
-	rtl8192_irq_enable(dev);
+	rtl8192_irq_enable(priv);
 	priv->bdisable_nic = false;
 
 	return (init_status == RT_STATUS_SUCCESS);
 }
 
-bool NicIFDisableNIC(struct net_device* dev)
+bool NicIFDisableNIC(struct r8192_priv *priv)
 {
 	bool	status = true;
-	struct r8192_priv* priv = ieee80211_priv(dev);
 	u8 tmp_state = 0;
 	// <1> Disable Interrupt
 
@@ -6494,11 +5019,11 @@ bool NicIFDisableNIC(struct net_device* dev)
 
 	priv->ieee80211->state = tmp_state;
 	rtl8192_cancel_deferred_work(priv);
-	rtl8192_irq_disable(dev);
+	rtl8192_irq_disable(priv);
 	// <2> Stop all timer
 
 	// <3> Disable Adapter
-	rtl8192_halt_adapter(dev, false);
+	rtl8192_halt_adapter(priv, false);
 //	priv->bdisable_nic = true;
 
 	return status;
diff --git a/drivers/staging/rtl8192e/r8192E_dm.c b/drivers/staging/rtl8192e/r8192E_dm.c
index 0f7bc52..688d29b 100644
--- a/drivers/staging/rtl8192e/r8192E_dm.c
+++ b/drivers/staging/rtl8192e/r8192E_dm.c
@@ -25,24 +25,10 @@ Major Change History:
 //
 // Indicate different AP vendor for IOT issue.
 //
-#ifdef  RTL8190P
-static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0x5e4322, 	0x5e4322,  	0x604322, 	0xa44f, 	0x5e4322,	0x5e4322};
-static const u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0xa44f, 	0x5e4322,  	0x604322, 	0x5e4322, 	0x5e4322,	0x5e4322};
-#else
-#ifdef RTL8192E
 static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
 { 0x5e4322, 	0x5e4322, 	0x5e4322, 	0x604322, 	0xa44f, 	0x5e4322,	0x5e4322};
 static const u32 edca_setting_UL[HT_IOT_PEER_MAX] =
 { 0x5e4322, 	0xa44f,		0x5e4322,  	0x604322, 	0x5e4322, 	0x5e4322, 	0x5e4322};
-#else
-static const u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0x5e4322, 	0x5e4322, 	0x604322, 	0xa44f, 	0x5ea44f, 	0x5e4322};
-static const u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 	0xa44f, 	0x5e4322, 	0x604322, 	0x5ea44f, 	0x5ea44f, 	0x5e4322};
-#endif
-#endif
 
 #define RTK_UL_EDCA 0xa44f
 #define RTK_DL_EDCA 0x5e4322
@@ -52,241 +38,108 @@ dig_t	dm_digtable;
 // For Dynamic Rx Path Selection by Signal Strength
 DRxPathSel	DM_RxPathSelTable;
 
-
-/*--------------------Define export function prototype-----------------------*/
-extern	void	init_hal_dm(struct net_device *dev);
-extern	void deinit_hal_dm(struct net_device *dev);
-
-extern void hal_dm_watchdog(struct net_device *dev);
-
-
-extern	void	init_rate_adaptive(struct net_device *dev);
-extern	void	dm_txpower_trackingcallback(struct work_struct *work);
-
-extern	void	dm_cck_txpower_adjust(struct net_device *dev,bool  binch14);
-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_ChangeFsyncSetting(struct net_device *dev,
-												s32		DM_Type,
-												s32		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_check_fsync(struct net_device *dev);
-extern	void dm_initialize_txpower_tracking(struct net_device *dev);
-
-#ifdef RTL8192E
-extern  void    dm_gpio_change_rf_callback(struct work_struct *work);
-#endif
-
+void dm_gpio_change_rf_callback(struct work_struct *work);
 
 // DM --> Rate Adaptive
-static	void	dm_check_rate_adaptive(struct net_device *dev);
+static void dm_check_rate_adaptive(struct r8192_priv *priv);
 
 // DM --> Bandwidth switch
-static	void	dm_init_bandwidth_autoswitch(struct net_device *dev);
-static	void	dm_bandwidth_autoswitch(	struct net_device *dev);
+static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv);
+static void dm_bandwidth_autoswitch(struct r8192_priv *priv);
 
 // DM --> TX power control
-static	void	dm_check_txpower_tracking(struct net_device *dev);
-
-// DM --> BB init gain restore
-#ifndef RTL8192U
-static	void	dm_bb_initialgain_restore(struct net_device *dev);
-
-// DM --> BB init gain backup
-static	void	dm_bb_initialgain_backup(struct net_device *dev);
-#endif
+static void dm_check_txpower_tracking(struct r8192_priv *priv);
 
 // DM --> Dynamic Init Gain by RSSI
-static	void	dm_dig_init(struct net_device *dev);
-static	void	dm_ctrl_initgain_byrssi(struct net_device *dev);
-static	void	dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev);
-static	void	dm_ctrl_initgain_byrssi_by_driverrssi(	struct net_device *dev);
-static	void	dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev);
-static	void	dm_initial_gain(struct net_device *dev);
-static	void	dm_pd_th(struct net_device *dev);
-static	void	dm_cs_ratio(struct net_device *dev);
-
-static	void dm_init_ctstoself(struct net_device *dev);
+static void dm_dig_init(struct r8192_priv *priv);
+static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv);
+static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv);
+static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv);
+static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv);
+static void dm_initial_gain(struct r8192_priv *priv);
+static void dm_pd_th(struct r8192_priv *priv);
+static void dm_cs_ratio(struct r8192_priv *priv);
+
+static void dm_init_ctstoself(struct r8192_priv *priv);
 // DM --> EDCA turboe mode control
-static	void	dm_check_edca_turbo(struct net_device *dev);
+static void dm_check_edca_turbo(struct r8192_priv *priv);
+static void dm_init_edca_turbo(struct r8192_priv *priv);
 
 // DM --> HW RF control
-static	void	dm_check_rfctrl_gpio(struct net_device *dev);
-
-// DM --> Check PBC
-static	void dm_check_pbc_gpio(struct net_device *dev);
+static void dm_check_rfctrl_gpio(struct r8192_priv *priv);
 
 // DM --> Check current RX RF path state
-static	void	dm_check_rx_path_selection(struct net_device *dev);
-static 	void dm_init_rxpath_selection(struct net_device *dev);
-static	void dm_rxpath_sel_byrssi(struct net_device *dev);
+static void dm_check_rx_path_selection(struct r8192_priv *priv);
+static void dm_init_rxpath_selection(struct r8192_priv *priv);
+static void dm_rxpath_sel_byrssi(struct r8192_priv *priv);
 
 // DM --> Fsync for broadcom ap
-static void dm_init_fsync(struct net_device *dev);
-static void dm_deInit_fsync(struct net_device *dev);
+static void dm_init_fsync(struct r8192_priv *priv);
+static void dm_deInit_fsync(struct r8192_priv *priv);
 
-static	void	dm_check_txrateandretrycount(struct net_device *dev);
+static void dm_check_txrateandretrycount(struct r8192_priv *priv);
+static void dm_check_fsync(struct r8192_priv *priv);
 
 
 /*---------------------Define of Tx Power Control For Near/Far Range --------*/   //Add by Jacken 2008/02/18
-static	void	dm_init_dynamic_txpower(struct net_device *dev);
-static	void	dm_dynamic_txpower(struct net_device *dev);
+static void dm_init_dynamic_txpower(struct r8192_priv *priv);
+static void dm_dynamic_txpower(struct r8192_priv *priv);
 
 // DM --> For rate adaptive and DIG, we must send RSSI to firmware
-static	void dm_send_rssi_tofw(struct net_device *dev);
-static	void	dm_ctstoself(struct net_device *dev);
+static void dm_send_rssi_tofw(struct r8192_priv *priv);
+static void dm_ctstoself(struct r8192_priv *priv);
+
+static void dm_fsync_timer_callback(unsigned long data);
 
 /*
  * Prepare SW resource for HW dynamic mechanism.
  * This function is only invoked at driver intialization once.
  */
-void init_hal_dm(struct net_device *dev)
+void init_hal_dm(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	// Undecorated Smoothed Signal Strength, it can utilized to dynamic mechanism.
 	priv->undecorated_smoothed_pwdb = -1;
 
 	//Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
-	dm_init_dynamic_txpower(dev);
-	init_rate_adaptive(dev);
+	dm_init_dynamic_txpower(priv);
+	init_rate_adaptive(priv);
 	//dm_initialize_txpower_tracking(dev);
-	dm_dig_init(dev);
-	dm_init_edca_turbo(dev);
-	dm_init_bandwidth_autoswitch(dev);
-	dm_init_fsync(dev);
-	dm_init_rxpath_selection(dev);
-	dm_init_ctstoself(dev);
-#ifdef RTL8192E
+	dm_dig_init(priv);
+	dm_init_edca_turbo(priv);
+	dm_init_bandwidth_autoswitch(priv);
+	dm_init_fsync(priv);
+	dm_init_rxpath_selection(priv);
+	dm_init_ctstoself(priv);
 	INIT_DELAYED_WORK(&priv->gpio_change_rf_wq,  dm_gpio_change_rf_callback);
-#endif
 
 }
 
-void deinit_hal_dm(struct net_device *dev)
+void deinit_hal_dm(struct r8192_priv *priv)
 {
-
-	dm_deInit_fsync(dev);
-
-}
-
-
-#ifdef USB_RX_AGGREGATION_SUPPORT
-void dm_CheckRxAggregation(struct net_device *dev) {
-	struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
-	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
-	static unsigned long	lastTxOkCnt = 0;
-	static unsigned long	lastRxOkCnt = 0;
-	unsigned long		curTxOkCnt = 0;
-	unsigned long		curRxOkCnt = 0;
-
-/*
-	if (pHalData->bForcedUsbRxAggr) {
-		if (pHalData->ForcedUsbRxAggrInfo == 0) {
-			if (pHalData->bCurrentRxAggrEnable) {
-				Adapter->HalFunc.HalUsbRxAggrHandler(Adapter, FALSE);
-			}
-		} else {
-			if (!pHalData->bCurrentRxAggrEnable || (pHalData->ForcedUsbRxAggrInfo != pHalData->LastUsbRxAggrInfoSetting)) {
-				Adapter->HalFunc.HalUsbRxAggrHandler(Adapter, TRUE);
-			}
-		}
-		return;
-	}
-
-*/
-	curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt;
-	curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt;
-
-	if((curTxOkCnt + curRxOkCnt) < 15000000) {
-		return;
-	}
-
-	if(curTxOkCnt > 4*curRxOkCnt) {
-		if (priv->bCurrentRxAggrEnable) {
-			write_nic_dword(dev, 0x1a8, 0);
-			priv->bCurrentRxAggrEnable = false;
-		}
-	}else{
-		if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) {
-			u32 ulValue;
-			ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) |
-				(pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout);
-			/*
-			 * If usb rx firmware aggregation is enabled,
-			 * when anyone of three threshold conditions above is reached,
-			 * firmware will send aggregated packet to driver.
-			 */
-			write_nic_dword(dev, 0x1a8, ulValue);
-			priv->bCurrentRxAggrEnable = true;
-		}
-	}
-
-	lastTxOkCnt = priv->stats.txbytesunicast;
-	lastRxOkCnt = priv->stats.rxbytesunicast;
-}
-#endif
-
-
-// call the script file to enable
-void dm_check_ac_dc_power(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
-	char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL};
-	static char *envp[] = {"HOME=/",
-			"TERM=linux",
-			"PATH=/usr/bin:/bin",
-			 NULL};
-
-	if(priv->ResetProgress == RESET_TYPE_SILENT)
-	{
-		RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
-		return;
-	}
-
-	if(priv->ieee80211->state != IEEE80211_LINKED) {
-		return;
-	}
-	call_usermodehelper(ac_dc_check_script_path,argv,envp,1);
+	dm_deInit_fsync(priv);
 }
 
-void hal_dm_watchdog(struct net_device *dev)
+void hal_dm_watchdog(struct r8192_priv *priv)
 {
-	dm_check_ac_dc_power(dev);
 
 	/*Add by amy 2008/05/15 ,porting from windows code.*/
-	dm_check_rate_adaptive(dev);
-	dm_dynamic_txpower(dev);
-	dm_check_txrateandretrycount(dev);
+	dm_check_rate_adaptive(priv);
+	dm_dynamic_txpower(priv);
+	dm_check_txrateandretrycount(priv);
 
-	dm_check_txpower_tracking(dev);
+	dm_check_txpower_tracking(priv);
 
-	dm_ctrl_initgain_byrssi(dev);
-	dm_check_edca_turbo(dev);
-	dm_bandwidth_autoswitch(dev);
+	dm_ctrl_initgain_byrssi(priv);
+	dm_check_edca_turbo(priv);
+	dm_bandwidth_autoswitch(priv);
 
-	dm_check_rfctrl_gpio(dev);
-	dm_check_rx_path_selection(dev);
-	dm_check_fsync(dev);
+	dm_check_rfctrl_gpio(priv);
+	dm_check_rx_path_selection(priv);
+	dm_check_fsync(priv);
 
 	// Add by amy 2008-05-15 porting from windows code.
-	dm_check_pbc_gpio(dev);
-	dm_send_rssi_tofw(dev);
-	dm_ctstoself(dev);
-
-#ifdef USB_RX_AGGREGATION_SUPPORT
-	dm_CheckRxAggregation(dev);
-#endif
+	dm_send_rssi_tofw(priv);
+	dm_ctstoself(priv);
 }
 
 
@@ -296,11 +149,9 @@ void hal_dm_watchdog(struct net_device *dev)
   *	01/16/2008	MHC		RF_Type is assigned in ReadAdapterInfo(). We must call
   *						the function after making sure RF_Type.
   */
-void init_rate_adaptive(struct net_device * dev)
+void init_rate_adaptive(struct r8192_priv *priv)
 {
-
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	prate_adaptive			pra = (prate_adaptive)&priv->rate_adaptive;
+	prate_adaptive pra = &priv->rate_adaptive;
 
 	pra->ratr_state = DM_RATR_STA_MAX;
 	pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High;
@@ -342,9 +193,8 @@ void init_rate_adaptive(struct net_device * dev)
 }
 
 
-static void dm_check_rate_adaptive(struct net_device * dev)
+static void dm_check_rate_adaptive(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
 	prate_adaptive			pra = (prate_adaptive)&priv->rate_adaptive;
 	u32						currentRATR, targetRATR = 0;
@@ -421,20 +271,16 @@ static void dm_check_rate_adaptive(struct net_device * dev)
 					(pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M);
 		}
 
-		//DbgPrint("[DM] Thresh H/L=%d/%d\n\r", RATR.HighRSSIThreshForRA, RATR.LowRSSIThreshForRA);
 		if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA)
 		{
-			//DbgPrint("[DM] RSSI=%d STA=HIGH\n\r", pHalData->UndecoratedSmoothedPWDB);
 			pra->ratr_state = DM_RATR_STA_HIGH;
 			targetRATR = pra->upper_rssi_threshold_ratr;
 		}else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA)
 		{
-			//DbgPrint("[DM] RSSI=%d STA=Middle\n\r", pHalData->UndecoratedSmoothedPWDB);
 			pra->ratr_state = DM_RATR_STA_MIDDLE;
 			targetRATR = pra->middle_rssi_threshold_ratr;
 		}else
 		{
-			//DbgPrint("[DM] RSSI=%d STA=LOW\n\r", pHalData->UndecoratedSmoothedPWDB);
 			pra->ratr_state = DM_RATR_STA_LOW;
 			targetRATR = pra->low_rssi_threshold_ratr;
 		}
@@ -448,32 +294,25 @@ static void dm_check_rate_adaptive(struct net_device * dev)
 				if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) ||
 					ping_rssi_state )
 				{
-					//DbgPrint("TestRSSI = %d, set RATR to 0x%x \n", pHalData->UndecoratedSmoothedPWDB, pRA->TestRSSIRATR);
 					pra->ratr_state = DM_RATR_STA_LOW;
 					targetRATR = pra->ping_rssi_ratr;
 					ping_rssi_state = 1;
 				}
-				//else
-				//	DbgPrint("TestRSSI is between the range. \n");
 			}
 			else
 			{
-				//DbgPrint("TestRSSI Recover to 0x%x \n", targetRATR);
 				ping_rssi_state = 0;
 			}
 		}
 
-		// 2008.04.01
-#if 1
 		// For RTL819X, if pairwisekey = wep/tkip, we support only MCS0~7.
-		if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(dev))
+		if(priv->ieee80211->GetHalfNmodeSupportByAPsHandler(priv->ieee80211))
 			targetRATR &=  0xf00fffff;
-#endif
 
 		//
 		// Check whether updating of RATR0 is required
 		//
-		currentRATR = read_nic_dword(dev, RATR0);
+		currentRATR = read_nic_dword(priv, RATR0);
 		if( targetRATR !=  currentRATR )
 		{
 			u32 ratr_value;
@@ -483,8 +322,8 @@ static void dm_check_rate_adaptive(struct net_device * dev)
 			{
 				ratr_value &= ~(RATE_ALL_OFDM_2SS);
 			}
-			write_nic_dword(dev, RATR0, ratr_value);
-			write_nic_byte(dev, UFWP, 1);
+			write_nic_dword(priv, RATR0, ratr_value);
+			write_nic_byte(priv, UFWP, 1);
 
 			pra->last_ratr = targetRATR;
 		}
@@ -498,10 +337,8 @@ static void dm_check_rate_adaptive(struct net_device * dev)
 }
 
 
-static void dm_init_bandwidth_autoswitch(struct net_device * dev)
+static void dm_init_bandwidth_autoswitch(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	priv->ieee80211->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH;
 	priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW;
 	priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = false;
@@ -510,10 +347,8 @@ static void dm_init_bandwidth_autoswitch(struct net_device * dev)
 }
 
 
-static void dm_bandwidth_autoswitch(struct net_device * dev)
+static void dm_bandwidth_autoswitch(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable){
 		return;
 	}else{
@@ -529,7 +364,6 @@ static void dm_bandwidth_autoswitch(struct net_device * dev)
 }
 
 //OFDM default at 0db, index=6.
-#ifndef RTL8190P
 static const u32 OFDMSwingTable[OFDM_Table_Length] = {
 	0x7f8001fe,	// 0, +6db
 	0x71c001c7,	// 1, +5db
@@ -580,15 +414,14 @@ static const u8 CCKSwingTable_Ch14[CCK_Table_length][8] = {
 	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},	// 10, -10db
 	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}	// 11, -11db
 };
-#endif
+
 #define		Pw_Track_Flag				0x11d
 #define		Tssi_Mea_Value				0x13c
 #define		Tssi_Report_Value1			0x134
 #define		Tssi_Report_Value2			0x13e
 #define		FW_Busy_Flag				0x13f
-static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
-	{
-	struct r8192_priv *priv = ieee80211_priv(dev);
+static void dm_TXPowerTrackingCallback_TSSI(struct r8192_priv *priv)
+{
 	bool						bHighpowerstate, viviflag = FALSE;
 	DCMD_TXCMD_T			tx_cmd;
 	u8					powerlevelOFDM24G;
@@ -597,15 +430,12 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 	u32						Value;
 	u8						Pwr_Flag;
 	u16					Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0;
-#ifdef RTL8192U
-	RT_STATUS 				rtStatus = RT_STATUS_SUCCESS;
-#endif
 //	bool rtStatus = true;
 	u32						delta=0;
 	RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
-//	write_nic_byte(dev, 0x1ba, 0);
-	write_nic_byte(dev, Pw_Track_Flag, 0);
-	write_nic_byte(dev, FW_Busy_Flag, 0);
+//	write_nic_byte(priv, 0x1ba, 0);
+	write_nic_byte(priv, Pw_Track_Flag, 0);
+	write_nic_byte(priv, FW_Busy_Flag, 0);
 	priv->ieee80211->bdynamic_txpower_enable = false;
 	bHighpowerstate = priv->bDynamicTxHighPower;
 
@@ -621,20 +451,12 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 	tx_cmd.Op		= TXCMD_SET_TX_PWR_TRACKING;
 	tx_cmd.Length	= 4;
 	tx_cmd.Value		= Value;
-#ifdef RTL8192U
-	rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12);
-	if (rtStatus == RT_STATUS_FAILURE)
-	{
-		RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n");
-	}
-#else
-	cmpk_message_handle_tx(dev, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
-#endif
+	cmpk_message_handle_tx(priv, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
 	mdelay(1);
-	//DbgPrint("hi, vivi, strange\n");
+
 	for(i = 0;i <= 30; i++)
 	{
-		Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag);
+		Pwr_Flag = read_nic_byte(priv, Pw_Track_Flag);
 
 		if (Pwr_Flag == 0)
 		{
@@ -642,21 +464,21 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 			continue;
 		}
 
-		Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value);
+		Avg_TSSI_Meas = read_nic_word(priv, Tssi_Mea_Value);
 
 		if(Avg_TSSI_Meas == 0)
 		{
-			write_nic_byte(dev, Pw_Track_Flag, 0);
-			write_nic_byte(dev, FW_Busy_Flag, 0);
+			write_nic_byte(priv, Pw_Track_Flag, 0);
+			write_nic_byte(priv, FW_Busy_Flag, 0);
 			return;
 		}
 
 		for(k = 0;k < 5; k++)
 		{
 			if(k !=4)
-				tmp_report[k] = read_nic_byte(dev, Tssi_Report_Value1+k);
+				tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value1+k);
 			else
-				tmp_report[k] = read_nic_byte(dev, Tssi_Report_Value2);
+				tmp_report[k] = read_nic_byte(priv, Tssi_Report_Value2);
 
 			RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]);
 		}
@@ -672,7 +494,7 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 		}
 		if(viviflag ==TRUE)
 		{
-			write_nic_byte(dev, Pw_Track_Flag, 0);
+			write_nic_byte(priv, Pw_Track_Flag, 0);
 			viviflag = FALSE;
 			RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n");
 			for(k = 0;k < 5; k++)
@@ -700,15 +522,11 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 		if(delta <= E_FOR_TX_POWER_TRACK)
 		{
 			priv->ieee80211->bdynamic_txpower_enable = TRUE;
-			write_nic_byte(dev, Pw_Track_Flag, 0);
-			write_nic_byte(dev, FW_Busy_Flag, 0);
+			write_nic_byte(priv, Pw_Track_Flag, 0);
+			write_nic_byte(priv, FW_Busy_Flag, 0);
 			RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n");
 			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
 			RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
-#ifdef RTL8190P
-			RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
-			RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
-#endif
 			RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
 			RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
 			return;
@@ -726,20 +544,20 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 					if(priv->rfa_txpowertrackingindex_real > 4)
 					{
 						priv->rfa_txpowertrackingindex_real--;
-						rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+						rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
 					}
 
 					priv->rfc_txpowertrackingindex--;
 					if(priv->rfc_txpowertrackingindex_real > 4)
 					{
 						priv->rfc_txpowertrackingindex_real--;
-						rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+						rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 					}
 						}
 						else
 						{
-								rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
-								rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+								rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+								rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
 				}
 			}
 			else
@@ -750,11 +568,11 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 							if(priv->rfc_txpowertrackingindex_real > 4)
 							{
 								priv->rfc_txpowertrackingindex_real--;
-								rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+								rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 							}
 						}
 						else
-							rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
+							rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value);
 				}
 			}
 			else
@@ -765,15 +583,15 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 				{
 					priv->rfa_txpowertrackingindex++;
 					priv->rfa_txpowertrackingindex_real++;
-					rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
+					rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value);
 					priv->rfc_txpowertrackingindex++;
 					priv->rfc_txpowertrackingindex_real++;
-					rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+					rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 				}
 					else
 					{
-						rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
-						rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+						rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+						rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
 			}
 				}
 				else
@@ -782,10 +600,10 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 					{
 							priv->rfc_txpowertrackingindex++;
 							priv->rfc_txpowertrackingindex_real++;
-							rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
+							rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value);
 					}
 					else
-							rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
+							rtl8192_setBBreg(priv, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value);
 				}
 			}
 			if (RF_Type == RF_2T4R)
@@ -812,52 +630,47 @@ static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev)
 				if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
 				{
 					priv->bcck_in_ch14 = TRUE;
-					dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+					dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 				}
 				else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
 				{
 					priv->bcck_in_ch14 = FALSE;
-					dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+					dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 				}
 				else
-					dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+					dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 			}
 		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex);
 		RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real);
-#ifdef RTL8190P
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex);
-		RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real);
-#endif
 		RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference);
 		RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation);
 
 		if (priv->CCKPresentAttentuation_difference <= -12||priv->CCKPresentAttentuation_difference >= 24)
 		{
 			priv->ieee80211->bdynamic_txpower_enable = TRUE;
-			write_nic_byte(dev, Pw_Track_Flag, 0);
-			write_nic_byte(dev, FW_Busy_Flag, 0);
+			write_nic_byte(priv, Pw_Track_Flag, 0);
+			write_nic_byte(priv, FW_Busy_Flag, 0);
 			RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n");
 			return;
 		}
 
 
 	}
-		write_nic_byte(dev, Pw_Track_Flag, 0);
+		write_nic_byte(priv, Pw_Track_Flag, 0);
 		Avg_TSSI_Meas_from_driver = 0;
 		for(k = 0;k < 5; k++)
 			tmp_report[k] = 0;
 		break;
 	}
-	write_nic_byte(dev, FW_Busy_Flag, 0);
+	write_nic_byte(priv, FW_Busy_Flag, 0);
 }
 		priv->ieee80211->bdynamic_txpower_enable = TRUE;
-		write_nic_byte(dev, Pw_Track_Flag, 0);
+		write_nic_byte(priv, Pw_Track_Flag, 0);
 }
-#ifndef RTL8190P
-static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
+
+static void dm_TXPowerTrackingCallback_ThermalMeter(struct r8192_priv *priv)
 {
 #define ThermalMeterVal	9
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32 tmpRegA, TempCCk;
 	u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval;
 	int i =0, CCKSwingNeedUpdate=0;
@@ -865,7 +678,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
 	if(!priv->btxpower_trackingInit)
 	{
 		//Query OFDM default setting
-		tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord);
+		tmpRegA = rtl8192_QueryBBReg(priv, rOFDM0_XATxIQImbalance, bMaskDWord);
 		for(i=0; i<OFDM_Table_Length; i++)	//find the index
 		{
 			if(tmpRegA == OFDMSwingTable[i])
@@ -877,7 +690,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
 		}
 
 		//Query CCK default setting From 0xa22
-		TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
+		TempCCk = rtl8192_QueryBBReg(priv, rCCK0_TxFilter1, bMaskByte2);
 		for(i=0 ; i<CCK_Table_length ; i++)
 		{
 			if(TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0])
@@ -894,13 +707,13 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
 	}
 
 	// read and filter out unreasonable value
-	tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);	// 0x12: RF Reg[10:7]
-	RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA);
+	tmpRegA = rtl8192_phy_QueryRFReg(priv, RF90_PATH_A, 0x12, 0x078);	// 0x12: RF Reg[10:7]
+	RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
 	if(tmpRegA < 3 || tmpRegA > 13)
 		return;
 	if(tmpRegA >= 12)	// if over 12, TP will be bad when high temperature
 		tmpRegA = 12;
-	RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA);
+	RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d\n", tmpRegA);
 	priv->ThermalMeter[0] = ThermalMeterVal;	//We use fixed value by Bryant's suggestion
 	priv->ThermalMeter[1] = ThermalMeterVal;	//We use fixed value by Bryant's suggestion
 
@@ -925,9 +738,7 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
 			tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval;
 		tmpCCK40Mindex = 0;
 	}
-	//DbgPrint("%ddb, tmpOFDMindex = %d, tmpCCK20Mindex = %d, tmpCCK40Mindex = %d",
-		//((u1Byte)tmpRegA - pHalData->ThermalMeter[0]),
-		//tmpOFDMindex, tmpCCK20Mindex, tmpCCK40Mindex);
+
 	if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)	//40M
 		tmpCCKindex = tmpCCK40Mindex;
 	else
@@ -958,546 +769,144 @@ static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev)
 
 	if(CCKSwingNeedUpdate)
 	{
-		//DbgPrint("Update CCK Swing, CCK_index = %d\n", pHalData->CCK_index);
-		dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+		dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 	}
 	if(priv->OFDM_index != tmpOFDMindex)
 	{
 		priv->OFDM_index = tmpOFDMindex;
-		rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);
+		rtl8192_setBBreg(priv, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index]);
 		RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
 			priv->OFDM_index, OFDMSwingTable[priv->OFDM_index]);
 	}
 	priv->txpower_count = 0;
 }
-#endif
+
 void dm_txpower_trackingcallback(struct work_struct *work)
 {
 	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
-       struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
-       struct net_device *dev = priv->ieee80211->dev;
+	struct r8192_priv *priv = container_of(dwork,struct r8192_priv,txpower_tracking_wq);
 
-#ifdef RTL8190P
-	dm_TXPowerTrackingCallback_TSSI(dev);
-#else
-	//if(priv->bDcut == TRUE)
 	if(priv->IC_Cut >= IC_VersionCut_D)
-		dm_TXPowerTrackingCallback_TSSI(dev);
+		dm_TXPowerTrackingCallback_TSSI(priv);
 	else
-		dm_TXPowerTrackingCallback_ThermalMeter(dev);
-#endif
+		dm_TXPowerTrackingCallback_ThermalMeter(priv);
 }
 
 
-static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev)
-{
+static const txbbgain_struct rtl8192_txbbgain_table[] = {
+	{ 12,	0x7f8001fe },
+	{ 11,	0x788001e2 },
+	{ 10,	0x71c001c7 },
+	{ 9,	0x6b8001ae },
+	{ 8,	0x65400195 },
+	{ 7,	0x5fc0017f },
+	{ 6,	0x5a400169 },
+	{ 5,	0x55400155 },
+	{ 4,	0x50800142 },
+	{ 3,	0x4c000130 },
+	{ 2,	0x47c0011f },
+	{ 1,	0x43c0010f },
+	{ 0,	0x40000100 },
+	{ -1,	0x3c8000f2 },
+	{ -2,	0x390000e4 },
+	{ -3,	0x35c000d7 },
+	{ -4,	0x32c000cb },
+	{ -5,	0x300000c0 },
+	{ -6,	0x2d4000b5 },
+	{ -7,	0x2ac000ab },
+	{ -8,	0x288000a2 },
+	{ -9,	0x26000098 },
+	{ -10,	0x24000090 },
+	{ -11,	0x22000088 },
+	{ -12,	0x20000080 },
+	{ -13,	0x1a00006c },
+	{ -14,	0x1c800072 },
+	{ -15,	0x18000060 },
+	{ -16,	0x19800066 },
+	{ -17,	0x15800056 },
+	{ -18,	0x26c0005b },
+	{ -19,	0x14400051 },
+	{ -20,	0x24400051 },
+	{ -21,	0x1300004c },
+	{ -22,	0x12000048 },
+	{ -23,	0x11000044 },
+	{ -24,	0x10000040 },
+};
 
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
-	//Initial the Tx BB index and mapping value
-	priv->txbbgain_table[0].txbb_iq_amplifygain = 	 		12;
-	priv->txbbgain_table[0].txbbgain_value=0x7f8001fe;
-	priv->txbbgain_table[1].txbb_iq_amplifygain = 	 		11;
-	priv->txbbgain_table[1].txbbgain_value=0x788001e2;
-	priv->txbbgain_table[2].txbb_iq_amplifygain = 	 		10;
-	priv->txbbgain_table[2].txbbgain_value=0x71c001c7;
-	priv->txbbgain_table[3].txbb_iq_amplifygain = 	 		9;
-	priv->txbbgain_table[3].txbbgain_value=0x6b8001ae;
-	priv->txbbgain_table[4].txbb_iq_amplifygain = 		       8;
-	priv->txbbgain_table[4].txbbgain_value=0x65400195;
-	priv->txbbgain_table[5].txbb_iq_amplifygain = 		       7;
-	priv->txbbgain_table[5].txbbgain_value=0x5fc0017f;
-	priv->txbbgain_table[6].txbb_iq_amplifygain = 		       6;
-	priv->txbbgain_table[6].txbbgain_value=0x5a400169;
-	priv->txbbgain_table[7].txbb_iq_amplifygain = 		       5;
-	priv->txbbgain_table[7].txbbgain_value=0x55400155;
-	priv->txbbgain_table[8].txbb_iq_amplifygain = 		       4;
-	priv->txbbgain_table[8].txbbgain_value=0x50800142;
-	priv->txbbgain_table[9].txbb_iq_amplifygain = 		       3;
-	priv->txbbgain_table[9].txbbgain_value=0x4c000130;
-	priv->txbbgain_table[10].txbb_iq_amplifygain = 		       2;
-	priv->txbbgain_table[10].txbbgain_value=0x47c0011f;
-	priv->txbbgain_table[11].txbb_iq_amplifygain = 		       1;
-	priv->txbbgain_table[11].txbbgain_value=0x43c0010f;
-	priv->txbbgain_table[12].txbb_iq_amplifygain = 		       0;
-	priv->txbbgain_table[12].txbbgain_value=0x40000100;
-	priv->txbbgain_table[13].txbb_iq_amplifygain = 		       -1;
-	priv->txbbgain_table[13].txbbgain_value=0x3c8000f2;
-	priv->txbbgain_table[14].txbb_iq_amplifygain = 		     -2;
-	priv->txbbgain_table[14].txbbgain_value=0x390000e4;
-	priv->txbbgain_table[15].txbb_iq_amplifygain = 		     -3;
-	priv->txbbgain_table[15].txbbgain_value=0x35c000d7;
-	priv->txbbgain_table[16].txbb_iq_amplifygain = 		     -4;
-	priv->txbbgain_table[16].txbbgain_value=0x32c000cb;
-	priv->txbbgain_table[17].txbb_iq_amplifygain = 		     -5;
-	priv->txbbgain_table[17].txbbgain_value=0x300000c0;
-	priv->txbbgain_table[18].txbb_iq_amplifygain = 		 	    -6;
-	priv->txbbgain_table[18].txbbgain_value=0x2d4000b5;
-	priv->txbbgain_table[19].txbb_iq_amplifygain = 		     -7;
-	priv->txbbgain_table[19].txbbgain_value=0x2ac000ab;
-	priv->txbbgain_table[20].txbb_iq_amplifygain = 		     -8;
-	priv->txbbgain_table[20].txbbgain_value=0x288000a2;
-	priv->txbbgain_table[21].txbb_iq_amplifygain = 		     -9;
-	priv->txbbgain_table[21].txbbgain_value=0x26000098;
-	priv->txbbgain_table[22].txbb_iq_amplifygain = 		     -10;
-	priv->txbbgain_table[22].txbbgain_value=0x24000090;
-	priv->txbbgain_table[23].txbb_iq_amplifygain = 		     -11;
-	priv->txbbgain_table[23].txbbgain_value=0x22000088;
-	priv->txbbgain_table[24].txbb_iq_amplifygain = 		     -12;
-	priv->txbbgain_table[24].txbbgain_value=0x20000080;
-	priv->txbbgain_table[25].txbb_iq_amplifygain = 		     -13;
-	priv->txbbgain_table[25].txbbgain_value=0x1a00006c;
-	priv->txbbgain_table[26].txbb_iq_amplifygain = 		     -14;
-	priv->txbbgain_table[26].txbbgain_value=0x1c800072;
-	priv->txbbgain_table[27].txbb_iq_amplifygain = 		     -15;
-	priv->txbbgain_table[27].txbbgain_value=0x18000060;
-	priv->txbbgain_table[28].txbb_iq_amplifygain = 		     -16;
-	priv->txbbgain_table[28].txbbgain_value=0x19800066;
-	priv->txbbgain_table[29].txbb_iq_amplifygain = 		     -17;
-	priv->txbbgain_table[29].txbbgain_value=0x15800056;
-	priv->txbbgain_table[30].txbb_iq_amplifygain = 		     -18;
-	priv->txbbgain_table[30].txbbgain_value=0x26c0005b;
-	priv->txbbgain_table[31].txbb_iq_amplifygain = 		     -19;
-	priv->txbbgain_table[31].txbbgain_value=0x14400051;
-	priv->txbbgain_table[32].txbb_iq_amplifygain = 		     -20;
-	priv->txbbgain_table[32].txbbgain_value=0x24400051;
-	priv->txbbgain_table[33].txbb_iq_amplifygain = 		     -21;
-	priv->txbbgain_table[33].txbbgain_value=0x1300004c;
-	priv->txbbgain_table[34].txbb_iq_amplifygain = 		     -22;
-	priv->txbbgain_table[34].txbbgain_value=0x12000048;
-	priv->txbbgain_table[35].txbb_iq_amplifygain = 		     -23;
-	priv->txbbgain_table[35].txbbgain_value=0x11000044;
-	priv->txbbgain_table[36].txbb_iq_amplifygain = 		     -24;
-	priv->txbbgain_table[36].txbbgain_value=0x10000040;
-
-	//ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
-	//This Table is for CH1~CH13
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[3] = 0x25;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[4] = 0x1c;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[5] = 0x12;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[6] = 0x09;
-	priv->cck_txbbgain_table[0].ccktxbb_valuearray[7] = 0x04;
-
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[0] = 0x33;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[1] = 0x32;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[2] = 0x2b;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[3] = 0x23;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[4] = 0x1a;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[5] = 0x11;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[6] = 0x08;
-	priv->cck_txbbgain_table[1].ccktxbb_valuearray[7] = 0x04;
-
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[0] = 0x30;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[1] = 0x2f;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[2] = 0x29;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[3] = 0x21;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[4] = 0x19;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[5] = 0x10;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[6] = 0x08;
-	priv->cck_txbbgain_table[2].ccktxbb_valuearray[7] = 0x03;
-
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[0] = 0x2d;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[1] = 0x2d;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[2] = 0x27;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[3] = 0x1f;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[4] = 0x18;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[5] = 0x0f;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[6] = 0x08;
-	priv->cck_txbbgain_table[3].ccktxbb_valuearray[7] = 0x03;
-
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[0] = 0x2b;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[1] = 0x2a;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[2] = 0x25;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[3] = 0x1e;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[4] = 0x16;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[5] = 0x0e;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[6] = 0x07;
-	priv->cck_txbbgain_table[4].ccktxbb_valuearray[7] = 0x03;
-
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[0] = 0x28;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[1] = 0x28;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[2] = 0x22;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[3] = 0x1c;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[4] = 0x15;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[5] = 0x0d;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[6] = 0x07;
-	priv->cck_txbbgain_table[5].ccktxbb_valuearray[7] = 0x03;
-
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[0] = 0x26;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[1] = 0x25;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[2] = 0x21;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[3] = 0x1b;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[4] = 0x14;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[5] = 0x0d;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[6] = 0x06;
-	priv->cck_txbbgain_table[6].ccktxbb_valuearray[7] = 0x03;
-
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[0] = 0x24;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[1] = 0x23;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[2] = 0x1f;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[3] = 0x19;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[4] = 0x13;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[5] = 0x0c;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[6] = 0x06;
-	priv->cck_txbbgain_table[7].ccktxbb_valuearray[7] = 0x03;
-
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[0] = 0x22;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[1] = 0x21;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[2] = 0x1d;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[3] = 0x18;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[4] = 0x11;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[5] = 0x0b;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[6] = 0x06;
-	priv->cck_txbbgain_table[8].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[0] = 0x20;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[1] = 0x20;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[2] = 0x1b;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[3] = 0x16;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[4] = 0x11;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[5] = 0x08;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[6] = 0x05;
-	priv->cck_txbbgain_table[9].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[0] = 0x1f;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[1] = 0x1e;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[2] = 0x1a;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[3] = 0x15;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[4] = 0x10;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[5] = 0x0a;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[6] = 0x05;
-	priv->cck_txbbgain_table[10].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[0] = 0x1d;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[1] = 0x1c;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[2] = 0x18;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[3] = 0x14;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[4] = 0x0f;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[5] = 0x0a;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[6] = 0x05;
-	priv->cck_txbbgain_table[11].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[0] = 0x1b;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[1] = 0x1a;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[2] = 0x17;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[3] = 0x13;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[4] = 0x0e;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[5] = 0x09;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[6] = 0x04;
-	priv->cck_txbbgain_table[12].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[0] = 0x1a;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[1] = 0x19;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[2] = 0x16;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[3] = 0x12;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[4] = 0x0d;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[5] = 0x09;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[6] = 0x04;
-	priv->cck_txbbgain_table[13].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[0] = 0x18;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[1] = 0x17;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[2] = 0x15;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[3] = 0x11;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[4] = 0x0c;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[5] = 0x08;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[6] = 0x04;
-	priv->cck_txbbgain_table[14].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[0] = 0x17;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[1] = 0x16;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[2] = 0x13;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[3] = 0x10;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[4] = 0x0c;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[5] = 0x08;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[6] = 0x04;
-	priv->cck_txbbgain_table[15].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[0] = 0x16;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[1] = 0x15;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[2] = 0x12;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[3] = 0x0f;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[4] = 0x0b;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[5] = 0x07;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[6] = 0x04;
-	priv->cck_txbbgain_table[16].ccktxbb_valuearray[7] = 0x01;
-
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[0] = 0x14;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[1] = 0x14;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[2] = 0x11;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[3] = 0x0e;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[4] = 0x0b;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[5] = 0x07;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[6] = 0x03;
-	priv->cck_txbbgain_table[17].ccktxbb_valuearray[7] = 0x02;
-
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[0] = 0x13;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[1] = 0x13;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[2] = 0x10;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[3] = 0x0d;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[4] = 0x0a;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[5] = 0x06;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[6] = 0x03;
-	priv->cck_txbbgain_table[18].ccktxbb_valuearray[7] = 0x01;
-
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[0] = 0x12;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[1] = 0x12;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[2] = 0x0f;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[3] = 0x0c;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[4] = 0x09;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[5] = 0x06;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[6] = 0x03;
-	priv->cck_txbbgain_table[19].ccktxbb_valuearray[7] = 0x01;
-
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[0] = 0x11;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[1] = 0x11;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[2] = 0x0f;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[3] = 0x0c;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[4] = 0x09;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[5] = 0x06;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[6] = 0x03;
-	priv->cck_txbbgain_table[20].ccktxbb_valuearray[7] = 0x01;
-
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[0] = 0x10;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[1] = 0x10;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[2] = 0x0e;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[3] = 0x0b;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[4] = 0x08;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[5] = 0x05;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[6] = 0x03;
-	priv->cck_txbbgain_table[21].ccktxbb_valuearray[7] = 0x01;
-
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[0] = 0x0f;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[1] = 0x0f;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[2] = 0x0d;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[3] = 0x0b;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[4] = 0x08;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[5] = 0x05;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03;
-	priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01;
-
-	//ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
-	//This Table is for CH14
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[3] = 0x1b;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[0] = 0x33;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[1] = 0x32;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[2] = 0x2b;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[3] = 0x19;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[0] = 0x30;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[1] = 0x2f;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[2] = 0x29;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[3] = 0x18;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[0] = 0x2d;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[1] = 0x2d;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[2] = 0x27;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[3] = 0x17;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[0] = 0x2b;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[1] = 0x2a;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[2] = 0x25;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[3] = 0x15;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[0] = 0x28;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[1] = 0x28;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[2] = 0x22;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[3] = 0x14;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[0] = 0x26;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[1] = 0x25;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[2] = 0x21;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[3] = 0x13;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[0] = 0x24;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[1] = 0x23;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[2] = 0x1f;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[3] = 0x12;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[0] = 0x22;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[1] = 0x21;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[2] = 0x1d;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[3] = 0x11;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[0] = 0x20;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[1] = 0x20;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[2] = 0x1b;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[3] = 0x10;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[0] = 0x1f;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[1] = 0x1e;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[2] = 0x1a;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[3] = 0x0f;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[0] = 0x1d;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[1] = 0x1c;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[2] = 0x18;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[3] = 0x0e;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[0] = 0x1b;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[1] = 0x1a;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[2] = 0x17;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[3] = 0x0e;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[0] = 0x1a;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[1] = 0x19;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[2] = 0x16;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[3] = 0x0d;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[0] = 0x18;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[1] = 0x17;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[2] = 0x15;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[3] = 0x0c;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[0] = 0x17;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[1] = 0x16;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[2] = 0x13;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[3] = 0x0b;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[0] = 0x16;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[1] = 0x15;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[2] = 0x12;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[3] = 0x0b;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[0] = 0x14;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[1] = 0x14;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[2] = 0x11;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[3] = 0x0a;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[0] = 0x13;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[1] = 0x13;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[2] = 0x10;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[3] = 0x0a;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[0] = 0x12;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[1] = 0x12;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[2] = 0x0f;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[3] = 0x09;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[0] = 0x11;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[1] = 0x11;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[2] = 0x0f;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[3] = 0x09;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[0] = 0x10;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[1] = 0x10;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[2] = 0x0e;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[3] = 0x08;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[7] = 0x00;
-
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[0] = 0x0f;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[1] = 0x0f;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[2] = 0x0d;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[3] = 0x08;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[4] = 0x00;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[5] = 0x00;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00;
-	priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00;
+/*
+ * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
+ * This Table is for CH1~CH13
+ */
+static const ccktxbbgain_struct rtl8192_cck_txbbgain_table[] = {
+	{{ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 }},
+	{{ 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 }},
+	{{ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03 }},
+	{{ 0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03 }},
+	{{ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 }},
+	{{ 0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03 }},
+	{{ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }},
+	{{ 0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03 }},
+	{{ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02 }},
+	{{ 0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02 }},
+	{{ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02 }},
+	{{ 0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02 }},
+	{{ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02 }},
+	{{ 0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02 }},
+	{{ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02 }},
+	{{ 0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02 }},
+	{{ 0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01 }},
+	{{ 0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02 }},
+	{{ 0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01 }},
+	{{ 0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
+	{{ 0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01 }},
+	{{ 0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
+	{{ 0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01 }},
+};
+
+/*
+ * ccktxbb_valuearray[0] is 0xA22 [1] is 0xA24 ...[7] is 0xA29
+ * This Table is for CH14
+ */
+static const ccktxbbgain_struct rtl8192_cck_txbbgain_ch14_table[] = {
+	{{ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x2d, 0x2d, 0x27, 0x17, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x28, 0x28, 0x22, 0x14, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00 }},
+	{{ 0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00 }},
+};
+
+static void dm_InitializeTXPowerTracking_TSSI(struct r8192_priv *priv)
+{
+	priv->txbbgain_table = rtl8192_txbbgain_table;
+	priv->cck_txbbgain_table = rtl8192_cck_txbbgain_table;
+	priv->cck_txbbgain_ch14_table = rtl8192_cck_txbbgain_ch14_table;
 
 	priv->btxpower_tracking = TRUE;
 	priv->txpower_count       = 0;
 	priv->btxpower_trackingInit = FALSE;
 
 }
-#ifndef RTL8190P
-static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
+static void dm_InitializeTXPowerTracking_ThermalMeter(struct r8192_priv *priv)
+{
 	// Tx Power tracking by Theremal Meter require Firmware R/W 3-wire. This mechanism
 	// can be enabled only when Firmware R/W 3-wire is enabled. Otherwise, frequent r/w
 	// 3-wire by driver cause RF goes into wrong state.
@@ -1508,30 +917,21 @@ static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev)
 	priv->txpower_count       = 0;
 	priv->btxpower_trackingInit = FALSE;
 }
-#endif
 
-void dm_initialize_txpower_tracking(struct net_device *dev)
+void dm_initialize_txpower_tracking(struct r8192_priv *priv)
 {
-#ifndef RTL8190P
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#endif
-#ifdef RTL8190P
-	dm_InitializeTXPowerTracking_TSSI(dev);
-#else
 	if(priv->IC_Cut >= IC_VersionCut_D)
-		dm_InitializeTXPowerTracking_TSSI(dev);
+		dm_InitializeTXPowerTracking_TSSI(priv);
 	else
-		dm_InitializeTXPowerTracking_ThermalMeter(dev);
-#endif
+		dm_InitializeTXPowerTracking_ThermalMeter(priv);
 }
 
 
-static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
+static void dm_CheckTXPowerTracking_TSSI(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	static u32 tx_power_track_counter = 0;
 	RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__);
-	if(read_nic_byte(dev, 0x11e) ==1)
+	if(read_nic_byte(priv, 0x11e) ==1)
 		return;
 	if(!priv->btxpower_tracking)
 		return;
@@ -1543,13 +943,10 @@ static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev)
 	}
 }
 
-#ifndef RTL8190P
-static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
+static void dm_CheckTXPowerTracking_ThermalMeter(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	static u8 	TM_Trigger=0;
 
-	//DbgPrint("dm_CheckTXPowerTracking() \n");
 	if(!priv->btxpower_tracking)
 		return;
 	else
@@ -1565,45 +962,31 @@ static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev)
 	{
 		//Attention!! You have to wirte all 12bits data to RF, or it may cause RF to crash
 		//actually write reg0x02 bit1=0, then bit1=1.
-		//DbgPrint("Trigger ThermalMeter, write RF reg0x2 = 0x4d to 0x4f\n");
-		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
-		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
-		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
-		rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+		rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+		rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+		rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+		rtl8192_phy_SetRFReg(priv, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
 		TM_Trigger = 1;
 		return;
 	}
 	else {
-		//DbgPrint("Schedule TxPowerTrackingWorkItem\n");
-			queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
+		queue_delayed_work(priv->priv_wq,&priv->txpower_tracking_wq,0);
 		TM_Trigger = 0;
 	}
 }
-#endif
 
-static void dm_check_txpower_tracking(struct net_device *dev)
+static void dm_check_txpower_tracking(struct r8192_priv *priv)
 {
-#ifndef RTL8190P
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	//static u32 tx_power_track_counter = 0;
-#endif
-#ifdef  RTL8190P
-	dm_CheckTXPowerTracking_TSSI(dev);
-#else
-	//if(priv->bDcut == TRUE)
 	if(priv->IC_Cut >= IC_VersionCut_D)
-		dm_CheckTXPowerTracking_TSSI(dev);
+		dm_CheckTXPowerTracking_TSSI(priv);
 	else
-		dm_CheckTXPowerTracking_ThermalMeter(dev);
-#endif
-
+		dm_CheckTXPowerTracking_ThermalMeter(priv);
 }
 
 
-static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
+static void dm_CCKTxPowerAdjust_TSSI(struct r8192_priv *priv, bool bInCH14)
 {
 	u32 TempVal;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	//Write 0xa22 0xa23
 	TempVal = 0;
 	if(!bInCH14){
@@ -1611,49 +994,49 @@ static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool  bInCH14)
 		TempVal = 	(u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
 					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
 
-		rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
 		//Write 0xa24 ~ 0xa27
 		TempVal = 0;
 		TempVal = 	(u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
 					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
 					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
 					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
-		rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
 		//Write 0xa28  0xa29
 		TempVal = 0;
 		TempVal = 	(u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
 					(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
 
-		rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
 	}
 	else
 	{
 		TempVal = 	(u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] +
 					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ;
 
-		rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
 		//Write 0xa24 ~ 0xa27
 		TempVal = 0;
 		TempVal = 	(u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] +
 					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) +
 					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+
 					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24));
-		rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
 		//Write 0xa28  0xa29
 		TempVal = 0;
 		TempVal = 	(u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] +
 					(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ;
 
-		rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
 	}
 
 
 }
-#ifndef RTL8190P
-static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH14)
+
+static void dm_CCKTxPowerAdjust_ThermalMeter(struct r8192_priv *priv,
+					     bool bInCH14)
 {
 	u32 TempVal;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	TempVal = 0;
 	if(!bInCH14)
@@ -1661,7 +1044,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH
 		//Write 0xa22 0xa23
 		TempVal = 	CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
 					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ;
-		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
 		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
 			rCCK0_TxFilter1, TempVal);
 		//Write 0xa24 ~ 0xa27
@@ -1670,7 +1053,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH
 					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) +
 					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+
 					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24);
-		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
 		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
 			rCCK0_TxFilter2, TempVal);
 		//Write 0xa28  0xa29
@@ -1678,7 +1061,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH
 		TempVal = 	CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
 					(CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ;
 
-		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
 		RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n",
 			rCCK0_DebugPort, TempVal);
 	}
@@ -1689,7 +1072,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH
 		TempVal = 	CCKSwingTable_Ch14[priv->CCK_index][0] +
 					(CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ;
 
-		rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter1, bMaskHWord, TempVal);
 		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
 			rCCK0_TxFilter1, TempVal);
 		//Write 0xa24 ~ 0xa27
@@ -1698,7 +1081,7 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH
 					(CCKSwingTable_Ch14[priv->CCK_index][3]<<8) +
 					(CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+
 					(CCKSwingTable_Ch14[priv->CCK_index][5]<<24);
-		rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_TxFilter2, bMaskDWord, TempVal);
 		RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
 			rCCK0_TxFilter2, TempVal);
 		//Write 0xa28  0xa29
@@ -1706,241 +1089,23 @@ static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev,	bool  bInCH
 		TempVal = 	CCKSwingTable_Ch14[priv->CCK_index][6] +
 					(CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ;
 
-		rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+		rtl8192_setBBreg(priv, rCCK0_DebugPort, bMaskLWord, TempVal);
 		RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n",
 			rCCK0_DebugPort, TempVal);
 	}
 }
-#endif
 
-
-void dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
+void dm_cck_txpower_adjust(struct r8192_priv *priv, bool binch14)
 {
-#ifndef RTL8190P
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#endif
-#ifdef RTL8190P
-	dm_CCKTxPowerAdjust_TSSI(dev, binch14);
-#else
 	if(priv->IC_Cut >= IC_VersionCut_D)
-		dm_CCKTxPowerAdjust_TSSI(dev, binch14);
+		dm_CCKTxPowerAdjust_TSSI(priv, binch14);
 	else
-		dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14);
-#endif
-}
-
-
-#ifndef  RTL8192U
-static void dm_txpower_reset_recovery(
-	struct net_device *dev
-)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
-	RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n");
-	rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",priv->rfa_txpowertrackingindex);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",priv->CCKPresentAttentuation);
-	dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
-
-	rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex);
-	RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain);
-
-}
-
-void dm_restore_dynamic_mechanism_state(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u32 	reg_ratr = priv->rate_adaptive.last_ratr;
-
-	if(!priv->up)
-	{
-		RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
-		return;
-	}
-
-	//
-	// Restore previous state for rate adaptive
-	//
-	if(priv->rate_adaptive.rate_adaptive_disabled)
-		return;
-	// TODO: Only 11n mode is implemented currently,
-	if( !(priv->ieee80211->mode==WIRELESS_MODE_N_24G ||
-		 priv->ieee80211->mode==WIRELESS_MODE_N_5G))
-		 return;
-	{
-			/* 2007/11/15 MH Copy from 8190PCI. */
-			u32 ratr_value;
-			ratr_value = reg_ratr;
-			if(priv->rf_type == RF_1T2R)	// 1T2R, Spatial Stream 2 should be disabled
-			{
-				ratr_value &=~ (RATE_ALL_OFDM_2SS);
-				//DbgPrint("HW_VAR_TATR_0 from 0x%x ==> 0x%x\n", ((pu4Byte)(val))[0], ratr_value);
-			}
-			//DbgPrint("set HW_VAR_TATR_0 = 0x%x\n", ratr_value);
-			//cosa PlatformEFIOWrite4Byte(Adapter, RATR0, ((pu4Byte)(val))[0]);
-			write_nic_dword(dev, RATR0, ratr_value);
-			write_nic_byte(dev, UFWP, 1);
-	}
-	//Resore TX Power Tracking Index
-	if(priv->btxpower_trackingInit && priv->btxpower_tracking){
-		dm_txpower_reset_recovery(dev);
-	}
-
-	//
-	//Restore BB Initial Gain
-	//
-	dm_bb_initialgain_restore(dev);
-
+		dm_CCKTxPowerAdjust_ThermalMeter(priv, binch14);
 }
 
-static void dm_bb_initialgain_restore(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u32 bit_mask = 0x7f; //Bit0~ Bit6
-
-	if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
-		return;
-
-	//Disable Initial Gain
-	//PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);
-	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	// Only clear byte 1 and rewrite.
-	rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1);
-	rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1);
-	rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1);
-	rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, (u32)priv->initgain_backup.xdagccore1);
-	bit_mask  = bMaskByte2;
-	rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca);
-
-	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
-	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
-	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1);
-	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
-	RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca);
-	//Enable Initial Gain
-	//PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x100);
-	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	// Only clear byte 1 and rewrite.
-
-}
-
-
-void dm_backup_dynamic_mechanism_state(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
-	// Fsync to avoid reset
-	priv->bswitch_fsync  = false;
-	priv->bfsync_processing = false;
-	//Backup BB InitialGain
-	dm_bb_initialgain_backup(dev);
-
-}
-
-
-static void dm_bb_initialgain_backup(struct net_device *dev)
-{
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u32 bit_mask = bMaskByte0; //Bit0~ Bit6
-
-	if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
-		return;
-
-	//PHY_SetBBReg(Adapter, UFWP, bMaskLWord, 0x800);
-	rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	// Only clear byte 1 and rewrite.
-	priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask);
-	priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask);
-	priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask);
-	priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask);
-	bit_mask  = bMaskByte2;
-	priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask);
-
-	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
-	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
-	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1);
-	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
-	RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca);
-
-}
-
-#endif
-
-void dm_change_dynamic_initgain_thresh(struct net_device *dev, u32 dm_type, u32	dm_value)
-{
-	if (dm_type == DIG_TYPE_THRESH_HIGH)
-	{
-		dm_digtable.rssi_high_thresh = dm_value;
-	}
-	else if (dm_type == DIG_TYPE_THRESH_LOW)
-	{
-		dm_digtable.rssi_low_thresh = dm_value;
-	}
-	else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
-	{
-		dm_digtable.rssi_high_power_highthresh = dm_value;
-	}
-	else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH)
-	{
-		dm_digtable.rssi_high_power_highthresh = dm_value;
-	}
-	else if (dm_type == DIG_TYPE_ENABLE)
-	{
-		dm_digtable.dig_state		= DM_STA_DIG_MAX;
-		dm_digtable.dig_enable_flag	= true;
-	}
-	else if (dm_type == DIG_TYPE_DISABLE)
-	{
-		dm_digtable.dig_state		= DM_STA_DIG_MAX;
-		dm_digtable.dig_enable_flag	= false;
-	}
-	else if (dm_type == DIG_TYPE_DBG_MODE)
-	{
-		if(dm_value >= DM_DBG_MAX)
-			dm_value = DM_DBG_OFF;
-		dm_digtable.dbg_mode		= (u8)dm_value;
-	}
-	else if (dm_type == DIG_TYPE_RSSI)
-	{
-		if(dm_value > 100)
-			dm_value = 30;
-		dm_digtable.rssi_val			= (long)dm_value;
-	}
-	else if (dm_type == DIG_TYPE_ALGORITHM)
-	{
-		if (dm_value >= DIG_ALGO_MAX)
-			dm_value = DIG_ALGO_BY_FALSE_ALARM;
-		if(dm_digtable.dig_algorithm != (u8)dm_value)
-			dm_digtable.dig_algorithm_switch = 1;
-		dm_digtable.dig_algorithm	= (u8)dm_value;
-	}
-	else if (dm_type == DIG_TYPE_BACKOFF)
-	{
-		if(dm_value > 30)
-			dm_value = 30;
-		dm_digtable.backoff_val		= (u8)dm_value;
-	}
-	else if(dm_type == DIG_TYPE_RX_GAIN_MIN)
-	{
-		if(dm_value == 0)
-			dm_value = 0x1;
-		dm_digtable.rx_gain_range_min = (u8)dm_value;
-	}
-	else if(dm_type == DIG_TYPE_RX_GAIN_MAX)
-	{
-		if(dm_value > 0x50)
-			dm_value = 0x50;
-		dm_digtable.rx_gain_range_max = (u8)dm_value;
-	}
-}
-
-
 /* Set DIG scheme init value. */
-static void dm_dig_init(struct net_device *dev)
+static void dm_dig_init(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	/* 2007/10/05 MH Disable DIG scheme now. Not tested. */
 	dm_digtable.dig_enable_flag	= true;
 	dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI;
@@ -1974,36 +1139,32 @@ static void dm_dig_init(struct net_device *dev)
  * gain according to different threshold. BB team provide the
  * suggested solution.
  */
-static void dm_ctrl_initgain_byrssi(struct net_device *dev)
+static void dm_ctrl_initgain_byrssi(struct r8192_priv *priv)
 {
-
 	if (dm_digtable.dig_enable_flag == false)
 		return;
 
 	if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
-		dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev);
+		dm_ctrl_initgain_byrssi_by_fwfalse_alarm(priv);
 	else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
-		dm_ctrl_initgain_byrssi_by_driverrssi(dev);
+		dm_ctrl_initgain_byrssi_by_driverrssi(priv);
 }
 
 
-static void dm_ctrl_initgain_byrssi_by_driverrssi(
-	struct net_device *dev)
+static void dm_ctrl_initgain_byrssi_by_driverrssi(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 i;
 	static u8 	fw_dig=0;
 
 	if (dm_digtable.dig_enable_flag == false)
 		return;
 
-	//DbgPrint("Dig by Sw Rssi \n");
 	if(dm_digtable.dig_algorithm_switch)	// if swithed algorithm, we have to disable FW Dig.
 		fw_dig = 0;
 	if(fw_dig <= 3)	// execute several times to make sure the FW Dig is disabled
 	{// FW DIG Off
 		for(i=0; i<3; i++)
-			rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	// Only clear byte 1 and rewrite.
+			rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8);	// Only clear byte 1 and rewrite.
 		fw_dig++;
 		dm_digtable.dig_state = DM_STA_DIG_OFF;	//fw dig off.
 	}
@@ -2013,25 +1174,20 @@ static void dm_ctrl_initgain_byrssi_by_driverrssi(
 	else
 		dm_digtable.cur_connect_state = DIG_DISCONNECT;
 
-	//DbgPrint("DM_DigTable.PreConnectState = %d, DM_DigTable.CurConnectState = %d \n",
-		//DM_DigTable.PreConnectState, DM_DigTable.CurConnectState);
-
 	if(dm_digtable.dbg_mode == DM_DBG_OFF)
 		dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb;
-	//DbgPrint("DM_DigTable.Rssi_val = %d \n", DM_DigTable.Rssi_val);
-	dm_initial_gain(dev);
-	dm_pd_th(dev);
-	dm_cs_ratio(dev);
+
+	dm_initial_gain(priv);
+	dm_pd_th(priv);
+	dm_cs_ratio(priv);
 	if(dm_digtable.dig_algorithm_switch)
 		dm_digtable.dig_algorithm_switch = 0;
 	dm_digtable.pre_connect_state = dm_digtable.cur_connect_state;
 
 }
 
-static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
-	struct net_device *dev)
+static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	static u32 reset_cnt = 0;
 	u8 i;
 
@@ -2043,7 +1199,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
 		dm_digtable.dig_state = DM_STA_DIG_MAX;
 		// Fw DIG On.
 		for(i=0; i<3; i++)
-			rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	// Only clear byte 1 and rewrite.
+			rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1);	// Only clear byte 1 and rewrite.
 		dm_digtable.dig_algorithm_switch = 0;
 	}
 
@@ -2056,11 +1212,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
 	{
 		return;
 	}
-	//DbgPrint("Dig by Fw False Alarm\n");
-	//if (DM_DigTable.Dig_State == DM_STA_DIG_OFF)
-	/*DbgPrint("DIG Check\n\r RSSI=%d LOW=%d HIGH=%d STATE=%d",
-	pHalData->UndecoratedSmoothedPWDB, DM_DigTable.RssiLowThresh,
-	DM_DigTable.RssiHighThresh, DM_DigTable.Dig_State);*/
+
 	/* 1. When RSSI decrease, We have to judge if it is smaller than a threshold
 		  and then execute below step. */
 	if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh))
@@ -2082,38 +1234,26 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
 		dm_digtable.dig_state = DM_STA_DIG_OFF;
 
 		// 1.1 DIG Off.
-		rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	// Only clear byte 1 and rewrite.
+		rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8);	// Only clear byte 1 and rewrite.
 
 		// 1.2 Set initial gain.
-		write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17);
-		write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17);
-		write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17);
-		write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17);
+		write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x17);
+		write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x17);
+		write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x17);
+		write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x17);
 
 		// 1.3 Lower PD_TH for OFDM.
 		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 		{
 			/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 			// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-			#ifdef RTL8190P
-			write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
-			#else
-				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
-				#endif
-			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-				write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40);
-			*/
-			//else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E)
-
-
-			//else
-				//PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x40);
+			write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
 		}
 		else
-			write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+			write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
 
 		// 1.4 Lower CS ratio for CCK.
-		write_nic_byte(dev, 0xa0a, 0x08);
+		write_nic_byte(priv, 0xa0a, 0x08);
 
 		// 1.5 Higher EDCCA.
 		//PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x325);
@@ -2130,7 +1270,7 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
 		if (dm_digtable.dig_state == DM_STA_DIG_ON &&
 			(priv->reset_count == reset_cnt))
 		{
-			dm_ctrl_initgain_byrssi_highpwr(dev);
+			dm_ctrl_initgain_byrssi_highpwr(priv);
 			return;
 		}
 		else
@@ -2142,23 +1282,22 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
 		}
 
 		dm_digtable.dig_state = DM_STA_DIG_ON;
-		//DbgPrint("DIG ON\n\r");
 
 		// 2.1 Set initial gain.
 		// 2008/02/26 MH SD3-Jerry suggest to prevent dirty environment.
 		if (reset_flag == 1)
 		{
-			write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c);
-			write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c);
-			write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c);
-			write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c);
+			write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x2c);
+			write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x2c);
+			write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x2c);
+			write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x2c);
 		}
 		else
 		{
-		write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20);
-		write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20);
-		write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20);
-		write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20);
+			write_nic_byte(priv, rOFDM0_XAAGCCore1, 0x20);
+			write_nic_byte(priv, rOFDM0_XBAGCCore1, 0x20);
+			write_nic_byte(priv, rOFDM0_XCAGCCore1, 0x20);
+			write_nic_byte(priv, rOFDM0_XDAGCCore1, 0x20);
 		}
 
 		// 2.2 Higher PD_TH for OFDM.
@@ -2166,43 +1305,29 @@ static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(
 		{
 			/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 			// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-			#ifdef RTL8190P
-			write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-			#else
-				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
-				#endif
-			/*
-			else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-			*/
-			//else if (pAdapter->HardwareType == HARDWARE_TYPE_RTL8192E)
-
-			//else
-				//PlatformEFIOWrite1Byte(pAdapter, rOFDM0_RxDetector1, 0x42);
+			write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
 		}
 		else
-			write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+			write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
 
 		// 2.3 Higher CS ratio for CCK.
-		write_nic_byte(dev, 0xa0a, 0xcd);
+		write_nic_byte(priv, 0xa0a, 0xcd);
 
 		// 2.4 Lower EDCCA.
 		/* 2008/01/11 MH 90/92 series are the same. */
 		//PlatformEFIOWrite4Byte(pAdapter, rOFDM0_ECCAThreshold, 0x346);
 
 		// 2.5 DIG On.
-		rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	// Only clear byte 1 and rewrite.
+		rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1);	// Only clear byte 1 and rewrite.
 
 	}
 
-	dm_ctrl_initgain_byrssi_highpwr(dev);
+	dm_ctrl_initgain_byrssi_highpwr(priv);
 
 }
 
-static void dm_ctrl_initgain_byrssi_highpwr(
-	struct net_device * dev)
+static void dm_ctrl_initgain_byrssi_highpwr(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	static u32 reset_cnt_highpwr = 0;
 
 	// For smooth, we can not change high power DIG state in the range.
@@ -2226,19 +1351,10 @@ static void dm_ctrl_initgain_byrssi_highpwr(
 		// 3.1 Higher PD_TH for OFDM for high power state.
 		if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 		{
-			#ifdef RTL8190P
-			write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
-			#else
-				write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
-				#endif
-
-			/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
-			*/
-
+			write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
 		}
 		else
-			write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+			write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
 	}
 	else
 	{
@@ -2254,18 +1370,10 @@ static void dm_ctrl_initgain_byrssi_highpwr(
 			// 3.2 Recover PD_TH for OFDM for normal power region.
 			if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 			{
-				#ifdef RTL8190P
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-				#else
-					write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
-					#endif
-				/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-				*/
-
+				write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
 			}
 			else
-				write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+				write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
 		}
 	}
 
@@ -2274,10 +1382,8 @@ static void dm_ctrl_initgain_byrssi_highpwr(
 }
 
 
-static void dm_initial_gain(
-	struct net_device * dev)
+static void dm_initial_gain(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8					initial_gain=0;
 	static u8				initialized=0, force_write=0;
 	static u32			reset_cnt=0;
@@ -2312,7 +1418,6 @@ static void dm_initial_gain(
 		dm_digtable.cur_ig_value = priv->DefaultInitialGain[0];
 		dm_digtable.pre_ig_value = 0;
 	}
-	//DbgPrint("DM_DigTable.CurIGValue = 0x%x, DM_DigTable.PreIGValue = 0x%x\n", DM_DigTable.CurIGValue, DM_DigTable.PreIGValue);
 
 	// if silent reset happened, we should rewrite the values back
 	if(priv->reset_count != reset_cnt)
@@ -2321,7 +1426,7 @@ static void dm_initial_gain(
 		reset_cnt = priv->reset_count;
 	}
 
-	if(dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1))
+	if(dm_digtable.pre_ig_value != read_nic_byte(priv, rOFDM0_XAAGCCore1))
 		force_write = 1;
 
 	{
@@ -2329,12 +1434,11 @@ static void dm_initial_gain(
 			|| !initialized || force_write)
 		{
 			initial_gain = (u8)dm_digtable.cur_ig_value;
-			//DbgPrint("Write initial gain = 0x%x\n", initial_gain);
 			// Set initial gain.
-			write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
-			write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
-			write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
-			write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+			write_nic_byte(priv, rOFDM0_XAAGCCore1, initial_gain);
+			write_nic_byte(priv, rOFDM0_XBAGCCore1, initial_gain);
+			write_nic_byte(priv, rOFDM0_XCAGCCore1, initial_gain);
+			write_nic_byte(priv, rOFDM0_XDAGCCore1, initial_gain);
 			dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
 			initialized = 1;
 			force_write = 0;
@@ -2342,10 +1446,8 @@ static void dm_initial_gain(
 	}
 }
 
-static void dm_pd_th(
-	struct net_device * dev)
+static void dm_pd_th(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	static u8				initialized=0, force_write=0;
 	static u32			reset_cnt = 0;
 
@@ -2390,7 +1492,6 @@ static void dm_pd_th(
 		if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) ||
 			(initialized<=3) || force_write)
 		{
-			//DbgPrint("Write PD_TH state = %d\n", DM_DigTable.CurPD_THState);
 			if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER)
 			{
 				// Lower PD_TH for OFDM.
@@ -2398,17 +1499,10 @@ static void dm_pd_th(
 				{
 					/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 					// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-					#ifdef RTL8190P
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
-					#else
-						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
-						#endif
-					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-						write_nic_byte(dev, rOFDM0_RxDetector1, 0x40);
-					*/
+					write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x00);
 				}
 				else
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+					write_nic_byte(priv, rOFDM0_RxDetector1, 0x42);
 			}
 			else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER)
 			{
@@ -2417,34 +1511,20 @@ static void dm_pd_th(
 				{
 					/* 2008/01/11 MH 40MHZ 90/92 register are not the same. */
 					// 2008/02/05 MH SD3-Jerry 92U/92E PD_TH are the same.
-					#ifdef RTL8190P
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-					#else
-						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
-						#endif
-					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-						write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
-					*/
+					write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x20);
 				}
 				else
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+					write_nic_byte(priv, rOFDM0_RxDetector1, 0x44);
 			}
 			else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER)
 			{
 				// Higher PD_TH for OFDM for high power state.
 				if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
 				{
-					#ifdef RTL8190P
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
-					#else
-						write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
-						#endif
-					/*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P)
-						write_nic_byte(dev, rOFDM0_RxDetector1, 0x41);
-					*/
+					write_nic_byte(priv, (rOFDM0_XATxAFE+3), 0x10);
 				}
 				else
-					write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+					write_nic_byte(priv, rOFDM0_RxDetector1, 0x43);
 			}
 			dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
 			if(initialized <= 3)
@@ -2454,10 +1534,8 @@ static void dm_pd_th(
 	}
 }
 
-static	void dm_cs_ratio(
-	struct net_device * dev)
+static void dm_cs_ratio(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	static u8				initialized=0,force_write=0;
 	static u32			reset_cnt = 0;
 
@@ -2499,16 +1577,15 @@ static	void dm_cs_ratio(
 	if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
 		!initialized || force_write)
 	{
-		//DbgPrint("Write CS_ratio state = %d\n", DM_DigTable.CurCS_ratioState);
 		if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
 		{
 			// Lower CS ratio for CCK.
-			write_nic_byte(dev, 0xa0a, 0x08);
+			write_nic_byte(priv, 0xa0a, 0x08);
 		}
 		else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
 		{
 			// Higher CS ratio for CCK.
-			write_nic_byte(dev, 0xa0a, 0xcd);
+			write_nic_byte(priv, 0xa0a, 0xcd);
 		}
 		dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
 		initialized = 1;
@@ -2516,20 +1593,16 @@ static	void dm_cs_ratio(
 	}
 }
 
-void dm_init_edca_turbo(struct net_device *dev)
+void dm_init_edca_turbo(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	priv->bcurrent_turbo_EDCA = false;
 	priv->ieee80211->bis_any_nonbepkts = false;
 	priv->bis_cur_rdlstate = false;
 }
 
-#if 1
-static void dm_check_edca_turbo(
-	struct net_device * dev)
+static void dm_check_edca_turbo(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
 	//PSTA_QOS			pStaQos = pMgntInfo->pStaQos;
 
@@ -2543,15 +1616,12 @@ static void dm_check_edca_turbo(
 	// Do not be Turbo if it's under WiFi config and Qos Enabled, because the EDCA parameters
 	// should follow the settings from QAP. By Bruce, 2007-12-07.
 	//
-	#if 1
 	if(priv->ieee80211->state != IEEE80211_LINKED)
 		goto dm_CheckEdcaTurbo_EXIT;
-	#endif
 	// We do not turn on EDCA turbo mode for some AP that has IOT issue
 	if(priv->ieee80211->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO)
 		goto dm_CheckEdcaTurbo_EXIT;
 
-//	printk("========>%s():bis_any_nonbepkts is %d\n",__FUNCTION__,priv->bis_any_nonbepkts);
 	// Check the status for current condition.
 	if(!priv->ieee80211->bis_any_nonbepkts)
 	{
@@ -2560,20 +1630,17 @@ static void dm_check_edca_turbo(
 		// For RT-AP, we needs to turn it on when Rx>Tx
 		if(curRxOkCnt > 4*curTxOkCnt)
 		{
-			//printk("%s():curRxOkCnt > 4*curTxOkCnt\n");
 			if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
 			{
-				write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
+				write_nic_dword(priv, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]);
 				priv->bis_cur_rdlstate = true;
 			}
 		}
 		else
 		{
-
-			//printk("%s():curRxOkCnt < 4*curTxOkCnt\n");
 			if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA)
 			{
-				write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
+				write_nic_dword(priv, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]);
 				priv->bis_cur_rdlstate = false;
 			}
 
@@ -2597,7 +1664,7 @@ static void dm_check_edca_turbo(
 				u8 mode = priv->ieee80211->mode;
 
 			// For Each time updating EDCA parameter, reset EDCA turbo mode status.
-				dm_init_edca_turbo(dev);
+				dm_init_edca_turbo(priv);
 				u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime;
 				u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)|
 					(((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)|
@@ -2605,7 +1672,7 @@ static void dm_check_edca_turbo(
 					((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
 				printk("===>u4bAcParam:%x, ", u4bAcParam);
 			//write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
-				write_nic_dword(dev, EDCAPARA_BE,  u4bAcParam);
+				write_nic_dword(priv, EDCAPARA_BE,  u4bAcParam);
 
 			// Check ACM bit.
 			// If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
@@ -2613,7 +1680,7 @@ static void dm_check_edca_turbo(
 			// TODO:  Modified this part and try to set acm control in only 1 IO processing!!
 
 					PACI_AIFSN	pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]);
-					u8		AcmCtrl = read_nic_byte( dev, AcmHwCtrl );
+					u8		AcmCtrl = read_nic_byte(priv, AcmHwCtrl );
 					if( pAciAifsn->f.ACM )
 					{ // ACM bit is 1.
 						AcmCtrl |= AcmHw_BeqEn;
@@ -2624,7 +1691,7 @@ static void dm_check_edca_turbo(
 					}
 
 					RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ;
-					write_nic_byte(dev, AcmHwCtrl, AcmCtrl );
+					write_nic_byte(priv, AcmHwCtrl, AcmCtrl );
 				}
 			}
 			priv->bcurrent_turbo_EDCA = false;
@@ -2638,19 +1705,15 @@ dm_CheckEdcaTurbo_EXIT:
 	lastTxOkCnt = priv->stats.txbytesunicast;
 	lastRxOkCnt = priv->stats.rxbytesunicast;
 }
-#endif
 
-static void dm_init_ctstoself(struct net_device * dev)
+static void dm_init_ctstoself(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
-
 	priv->ieee80211->bCTSToSelfEnable = TRUE;
 	priv->ieee80211->CTSToSelfTH = CTSToSelfTHVal;
 }
 
-static void dm_ctstoself(struct net_device *dev)
+static void dm_ctstoself(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv((struct net_device *)dev);
 	PRT_HIGH_THROUGHPUT	pHTInfo = priv->ieee80211->pHTInfo;
 	static unsigned long				lastTxOkCnt = 0;
 	static unsigned long				lastRxOkCnt = 0;
@@ -2675,24 +1738,10 @@ static void dm_ctstoself(struct net_device *dev)
 		if(curRxOkCnt > 4*curTxOkCnt)	//downlink, disable CTS to self
 		{
 			pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
-			//DbgPrint("dm_CTSToSelf() ==> CTS to self disabled -- downlink\n");
 		}
 		else	//uplink
 		{
-		#if 1
 			pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
-		#else
-			if(priv->undecorated_smoothed_pwdb < priv->ieee80211->CTSToSelfTH)	// disable CTS to self
-			{
-				pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF;
-				//DbgPrint("dm_CTSToSelf() ==> CTS to self disabled\n");
-			}
-			else if(priv->undecorated_smoothed_pwdb >= (priv->ieee80211->CTSToSelfTH+5))	// enable CTS to self
-			{
-				pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
-				//DbgPrint("dm_CTSToSelf() ==> CTS to self enabled\n");
-			}
-		#endif
 		}
 
 		lastTxOkCnt = priv->stats.txbytesunicast;
@@ -2703,62 +1752,22 @@ static void dm_ctstoself(struct net_device *dev)
 
 
 /* Copy 8187B template for 9xseries */
-#if 1
-static void dm_check_rfctrl_gpio(struct net_device * dev)
+static void dm_check_rfctrl_gpio(struct r8192_priv *priv)
 {
-#ifdef RTL8192E
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#endif
 
 	// Walk around for DTM test, we will not enable HW - radio on/off because r/w
 	// page 1 register before Lextra bus is enabled cause system fails when resuming
 	// from S4. 20080218, Emily
 
 	// Stop to execute workitem to prevent S3/S4 bug.
-#ifdef RTL8190P
-	return;
-#endif
-#ifdef RTL8192U
-	return;
-#endif
-#ifdef RTL8192E
-		queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
-#endif
-
+	queue_delayed_work(priv->priv_wq,&priv->gpio_change_rf_wq,0);
 }
 
-#endif
-/* Check if PBC button is pressed. */
-static	void	dm_check_pbc_gpio(struct net_device *dev)
-{
-#ifdef RTL8192U
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	u8 tmp1byte;
-
-
-	tmp1byte = read_nic_byte(dev,GPI);
-	if(tmp1byte == 0xff)
-		return;
-
-	if (tmp1byte&BIT6 || tmp1byte&BIT0)
-	{
-		// Here we only set bPbcPressed to TRUE
-		// After trigger PBC, the variable will be set to FALSE
-		RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n");
-		priv->bpbc_pressed = true;
-	}
-#endif
-
-}
-
-#ifdef RTL8192E
-
 /* PCI will not support workitem call back HW radio on-off control. */
 void dm_gpio_change_rf_callback(struct work_struct *work)
 {
 	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
 	struct r8192_priv *priv = container_of(dwork,struct r8192_priv,gpio_change_rf_wq);
-	struct net_device *dev = priv->ieee80211->dev;
 	u8 tmp1byte;
 	RT_RF_POWER_STATE	eRfPowerStateToSet;
 	bool bActuallySet = false;
@@ -2768,7 +1777,7 @@ void dm_gpio_change_rf_callback(struct work_struct *work)
 	} else {
 		// 0x108 GPIO input register is read only
 		//set 0x108 B1= 1: RF-ON; 0: RF-OFF.
-		tmp1byte = read_nic_byte(dev,GPI);
+		tmp1byte = read_nic_byte(priv, GPI);
 
 		eRfPowerStateToSet = (tmp1byte&BIT1) ?  eRfOn : eRfOff;
 
@@ -2785,7 +1794,7 @@ void dm_gpio_change_rf_callback(struct work_struct *work)
 
 		if (bActuallySet) {
 			priv->bHwRfOffAction = 1;
-			MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
+			MgntActSet_RF_State(priv, eRfPowerStateToSet, RF_CHANGE_BY_HW);
 			//DrvIFIndicateCurrentPhyStatus(pAdapter);
 		} else {
 			msleep(2000);
@@ -2793,21 +1802,17 @@ void dm_gpio_change_rf_callback(struct work_struct *work)
 	}
 }
 
-#endif
-
 /* Check if Current RF RX path is enabled */
 void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
 {
 	struct delayed_work *dwork = container_of(work,struct delayed_work,work);
 	struct r8192_priv *priv = container_of(dwork,struct r8192_priv,rfpath_check_wq);
-	struct net_device *dev =priv->ieee80211->dev;
-	//bool bactually_set = false;
 	u8 rfpath = 0, i;
 
 
 	/* 2008/01/30 MH After discussing with SD3 Jerry, 0xc04/0xd04 register will
 	   always be the same. We only read 0xc04 now. */
-	rfpath = read_nic_byte(dev, 0xc04);
+	rfpath = read_nic_byte(priv, 0xc04);
 
 	// Check Bit 0-3, it means if RF A-D is enabled.
 	for (i = 0; i < RF90_PATH_MAX; i++)
@@ -2820,13 +1825,13 @@ void dm_rf_pathcheck_workitemcallback(struct work_struct *work)
 	if(!DM_RxPathSelTable.Enable)
 		return;
 
-	dm_rxpath_sel_byrssi(dev);
+	dm_rxpath_sel_byrssi(priv);
 }
 
-static void dm_init_rxpath_selection(struct net_device * dev)
+static void dm_init_rxpath_selection(struct r8192_priv *priv)
 {
 	u8 i;
-	struct r8192_priv *priv = ieee80211_priv(dev);
+
 	DM_RxPathSelTable.Enable = 1;	//default enabled
 	DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low;
 	DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH;
@@ -2844,9 +1849,8 @@ static void dm_init_rxpath_selection(struct net_device * dev)
 	}
 }
 
-static void dm_rxpath_sel_byrssi(struct net_device * dev)
+static void dm_rxpath_sel_byrssi(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8				i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0;
 	u8				tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0;
 	u8				cck_default_Rx=0x2;	//RF-C
@@ -2863,17 +1867,16 @@ static void dm_rxpath_sel_byrssi(struct net_device * dev)
 
 	if(!cck_Rx_Path_initialized)
 	{
-		DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf);
+		DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(priv, 0xa07)&0xf);
 		cck_Rx_Path_initialized = 1;
 	}
 
 	DM_RxPathSelTable.disabledRF = 0xf;
-	DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(dev, 0xc04));
+	DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(priv, 0xc04));
 
 	if(priv->ieee80211->mode == WIRELESS_MODE_B)
 	{
 		DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;	//pure B mode, fixed cck version2
-		//DbgPrint("Pure B mode, use cck rx version2 \n");
 	}
 
 	//decide max/sec/min rssi index
@@ -3067,8 +2070,8 @@ static void dm_rxpath_sel_byrssi(struct net_device * dev)
 			//record the enabled rssi threshold
 			DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5;
 			//disable the BB Rx path, OFDM
-			rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	// 0xc04[3:0]
-			rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	// 0xd04[3:0]
+			rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	// 0xc04[3:0]
+			rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x1<<min_rssi_index, 0x0);	// 0xd04[3:0]
 			disabled_rf_cnt++;
 		}
 		if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_1)
@@ -3083,7 +2086,7 @@ static void dm_rxpath_sel_byrssi(struct net_device * dev)
 	if(update_cck_rx_path)
 	{
 		DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2)|(cck_optional_Rx);
-		rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
+		rtl8192_setBBreg(priv, rCCK0_AFESetting, 0x0f000000, DM_RxPathSelTable.cck_Rx_path);
 	}
 
 	if(DM_RxPathSelTable.disabledRF)
@@ -3095,9 +2098,8 @@ static void dm_rxpath_sel_byrssi(struct net_device * dev)
 				if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i])
 				{
 					//enable the BB Rx path
-					//DbgPrint("RF-%d is enabled. \n", 0x1<<i);
-					rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<<i, 0x1);	// 0xc04[3:0]
-					rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x1<<i, 0x1);	// 0xd04[3:0]
+					rtl8192_setBBreg(priv, rOFDM0_TRxPathEnable, 0x1<<i, 0x1);	// 0xc04[3:0]
+					rtl8192_setBBreg(priv, rOFDM1_TRxPathEnable, 0x1<<i, 0x1);	// 0xd04[3:0]
 					DM_RxPathSelTable.rf_enable_rssi_th[i] = 100;
 					disabled_rf_cnt--;
 				}
@@ -3109,24 +2111,17 @@ static void dm_rxpath_sel_byrssi(struct net_device * dev)
 /*
  * Call a workitem to check current RXRF path and Rx Path selection by RSSI.
  */
-static void dm_check_rx_path_selection(struct net_device *dev)
+static void dm_check_rx_path_selection(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	queue_delayed_work(priv->priv_wq,&priv->rfpath_check_wq,0);
 }
 
-static void dm_init_fsync (struct net_device *dev)
+static void dm_init_fsync(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	priv->ieee80211->fsync_time_interval = 500;
 	priv->ieee80211->fsync_rate_bitmap = 0x0f000800;
 	priv->ieee80211->fsync_rssi_threshold = 30;
-#ifdef RTL8190P
-	priv->ieee80211->bfsync_enable = true;
-#else
 	priv->ieee80211->bfsync_enable = false;
-#endif
 	priv->ieee80211->fsync_multiple_timeinterval = 3;
 	priv->ieee80211->fsync_firstdiff_ratethreshold= 100;
 	priv->ieee80211->fsync_seconddiff_ratethreshold= 200;
@@ -3134,21 +2129,19 @@ static void dm_init_fsync (struct net_device *dev)
 	priv->framesyncMonitor = 1;	// current default 0xc38 monitor on
 
 	init_timer(&priv->fsync_timer);
-	priv->fsync_timer.data = (unsigned long)dev;
+	priv->fsync_timer.data = (unsigned long)priv;
 	priv->fsync_timer.function = dm_fsync_timer_callback;
 }
 
 
-static void dm_deInit_fsync(struct net_device *dev)
+static void dm_deInit_fsync(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	del_timer_sync(&priv->fsync_timer);
 }
 
-void dm_fsync_timer_callback(unsigned long data)
+static void dm_fsync_timer_callback(unsigned long data)
 {
-	struct net_device *dev = (struct net_device *)data;
-	struct r8192_priv *priv = ieee80211_priv((struct net_device *)data);
+	struct r8192_priv *priv = (struct r8192_priv *)data;
 	u32 rate_index, rate_count = 0, rate_count_diff=0;
 	bool		bSwitchFromCountDiff = false;
 	bool		bDoubleTimeInterval = false;
@@ -3209,21 +2202,13 @@ void dm_fsync_timer_callback(unsigned long data)
 			priv->bswitch_fsync = !priv->bswitch_fsync;
 			if(priv->bswitch_fsync)
 			{
-			#ifdef RTL8190P
-				write_nic_byte(dev,0xC36, 0x00);
-			#else
-				write_nic_byte(dev,0xC36, 0x1c);
-			#endif
-				write_nic_byte(dev, 0xC3e, 0x90);
+				write_nic_byte(priv,0xC36, 0x1c);
+				write_nic_byte(priv, 0xC3e, 0x90);
 			}
 			else
 			{
-			#ifdef RTL8190P
-				write_nic_byte(dev, 0xC36, 0x40);
-			#else
-				write_nic_byte(dev, 0xC36, 0x5c);
-			#endif
-				write_nic_byte(dev, 0xC3e, 0x96);
+				write_nic_byte(priv, 0xC36, 0x5c);
+				write_nic_byte(priv, 0xC3e, 0x96);
 			}
 		}
 		else if(priv->undecorated_smoothed_pwdb <= priv->ieee80211->fsync_rssi_threshold)
@@ -3231,12 +2216,8 @@ void dm_fsync_timer_callback(unsigned long data)
 			if(priv->bswitch_fsync)
 			{
 				priv->bswitch_fsync  = false;
-			#ifdef RTL8190P
-				write_nic_byte(dev, 0xC36, 0x40);
-			#else
-				write_nic_byte(dev, 0xC36, 0x5c);
-			#endif
-				write_nic_byte(dev, 0xC3e, 0x96);
+				write_nic_byte(priv, 0xC36, 0x5c);
+				write_nic_byte(priv, 0xC3e, 0x96);
 			}
 		}
 		if(bDoubleTimeInterval){
@@ -3258,35 +2239,25 @@ void dm_fsync_timer_callback(unsigned long data)
 		if(priv->bswitch_fsync)
 		{
 			priv->bswitch_fsync  = false;
-		#ifdef RTL8190P
-			write_nic_byte(dev, 0xC36, 0x40);
-		#else
-			write_nic_byte(dev, 0xC36, 0x5c);
-		#endif
-			write_nic_byte(dev, 0xC3e, 0x96);
+			write_nic_byte(priv, 0xC36, 0x5c);
+			write_nic_byte(priv, 0xC3e, 0x96);
 		}
 		priv->ContiuneDiffCount = 0;
-	#ifdef RTL8190P
-		write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd);
-	#else
-		write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
-	#endif
+		write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
 	}
 	RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount);
 	RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync);
 }
 
-static void dm_StartHWFsync(struct net_device *dev)
+static void dm_StartHWFsync(struct r8192_priv *priv)
 {
 	RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
-	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf);
-	write_nic_byte(dev, 0xc3b, 0x41);
+	write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cf);
+	write_nic_byte(priv, 0xc3b, 0x41);
 }
 
-static void dm_EndSWFsync(struct net_device *dev)
+static void dm_EndSWFsync(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__);
 	del_timer_sync(&(priv->fsync_timer));
 
@@ -3295,25 +2266,18 @@ static void dm_EndSWFsync(struct net_device *dev)
 	{
 		priv->bswitch_fsync  = false;
 
-		#ifdef RTL8190P
-			write_nic_byte(dev, 0xC36, 0x40);
-		#else
-		write_nic_byte(dev, 0xC36, 0x5c);
-#endif
+		write_nic_byte(priv, 0xC36, 0x40);
 
-		write_nic_byte(dev, 0xC3e, 0x96);
+		write_nic_byte(priv, 0xC3e, 0x96);
 	}
 
 	priv->ContiuneDiffCount = 0;
-#ifndef RTL8190P
-	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
-#endif
 
+	write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
 }
 
-static void dm_StartSWFsync(struct net_device *dev)
+static void dm_StartSWFsync(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32 			rateIndex;
 	u32 			rateBitmap;
 
@@ -3346,26 +2310,21 @@ static void dm_StartSWFsync(struct net_device *dev)
 	priv->fsync_timer.expires = jiffies + MSECS(priv->ieee80211->fsync_time_interval);
 	add_timer(&priv->fsync_timer);
 
-#ifndef RTL8190P
-	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
-#endif
-
+	write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c12cd);
 }
 
-static void dm_EndHWFsync(struct net_device *dev)
+static void dm_EndHWFsync(struct r8192_priv *priv)
 {
 	RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__);
-	write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
-	write_nic_byte(dev, 0xc3b, 0x49);
-
+	write_nic_dword(priv, rOFDM0_RxDetector2, 0x465c52cd);
+	write_nic_byte(priv, 0xc3b, 0x49);
 }
 
-void dm_check_fsync(struct net_device *dev)
+static void dm_check_fsync(struct r8192_priv *priv)
 {
 #define	RegC38_Default				0
 #define	RegC38_NonFsync_Other_AP	1
 #define	RegC38_Fsync_AP_BCM		2
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	//u32 			framesyncC34;
 	static u8		reg_c38_State=RegC38_Default;
 	static u32	reset_cnt=0;
@@ -3381,12 +2340,12 @@ void dm_check_fsync(struct net_device *dev)
 			switch(priv->ieee80211->fsync_state)
 			{
 				case Default_Fsync:
-					dm_StartHWFsync(dev);
+					dm_StartHWFsync(priv);
 					priv->ieee80211->fsync_state = HW_Fsync;
 					break;
 				case SW_Fsync:
-					dm_EndSWFsync(dev);
-					dm_StartHWFsync(dev);
+					dm_EndSWFsync(priv);
+					dm_StartHWFsync(priv);
 					priv->ieee80211->fsync_state = HW_Fsync;
 					break;
 				case HW_Fsync:
@@ -3399,12 +2358,12 @@ void dm_check_fsync(struct net_device *dev)
 			switch(priv->ieee80211->fsync_state)
 			{
 				case Default_Fsync:
-					dm_StartSWFsync(dev);
+					dm_StartSWFsync(priv);
 					priv->ieee80211->fsync_state = SW_Fsync;
 					break;
 				case HW_Fsync:
-					dm_EndHWFsync(dev);
-					dm_StartSWFsync(dev);
+					dm_EndHWFsync(priv);
+					dm_StartSWFsync(priv);
 					priv->ieee80211->fsync_state = SW_Fsync;
 					break;
 				case SW_Fsync:
@@ -3417,11 +2376,7 @@ void dm_check_fsync(struct net_device *dev)
 		{
 			if(reg_c38_State != RegC38_Fsync_AP_BCM)
 			{	//For broadcom AP we write different default value
-				#ifdef RTL8190P
-					write_nic_byte(dev, rOFDM0_RxDetector3, 0x15);
-				#else
-					write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
-				#endif
+				write_nic_byte(priv, rOFDM0_RxDetector3, 0x95);
 
 				reg_c38_State = RegC38_Fsync_AP_BCM;
 			}
@@ -3432,11 +2387,11 @@ void dm_check_fsync(struct net_device *dev)
 		switch(priv->ieee80211->fsync_state)
 		{
 			case HW_Fsync:
-				dm_EndHWFsync(dev);
+				dm_EndHWFsync(priv);
 				priv->ieee80211->fsync_state = Default_Fsync;
 				break;
 			case SW_Fsync:
-				dm_EndSWFsync(dev);
+				dm_EndSWFsync(priv);
 				priv->ieee80211->fsync_state = Default_Fsync;
 				break;
 			case Default_Fsync:
@@ -3452,28 +2407,17 @@ void dm_check_fsync(struct net_device *dev)
 				{
 					if(reg_c38_State != RegC38_NonFsync_Other_AP)
 					{
-						#ifdef RTL8190P
-							write_nic_byte(dev, rOFDM0_RxDetector3, 0x10);
-						#else
-							write_nic_byte(dev, rOFDM0_RxDetector3, 0x90);
-						#endif
+						write_nic_byte(priv, rOFDM0_RxDetector3, 0x90);
 
 						reg_c38_State = RegC38_NonFsync_Other_AP;
-					#if 0//cosa
-						if (Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
-							DbgPrint("Fsync is idle, rssi<=35, write 0xc38 = 0x%x \n", 0x10);
-						else
-							DbgPrint("Fsync is idle, rssi<=35, write 0xc38 = 0x%x \n", 0x90);
-					#endif
 					}
 				}
 				else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5))
 				{
 					if(reg_c38_State)
 					{
-						write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+						write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
 						reg_c38_State = RegC38_Default;
-						//DbgPrint("Fsync is idle, rssi>=40, write 0xc38 = 0x%x \n", pHalData->framesync);
 					}
 				}
 			}
@@ -3481,9 +2425,8 @@ void dm_check_fsync(struct net_device *dev)
 			{
 				if(reg_c38_State)
 				{
-					write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+					write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
 					reg_c38_State = RegC38_Default;
-					//DbgPrint("Fsync is idle, not connected, write 0xc38 = 0x%x \n", pHalData->framesync);
 				}
 			}
 		}
@@ -3492,19 +2435,17 @@ void dm_check_fsync(struct net_device *dev)
 	{
 		if(priv->reset_count != reset_cnt)
 		{	//After silent reset, the reg_c38_State will be returned to default value
-			write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+			write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
 			reg_c38_State = RegC38_Default;
 			reset_cnt = priv->reset_count;
-			//DbgPrint("reg_c38_State = 0 for silent reset. \n");
 		}
 	}
 	else
 	{
 		if(reg_c38_State)
 		{
-			write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync);
+			write_nic_byte(priv, rOFDM0_RxDetector3, priv->framesync);
 			reg_c38_State = RegC38_Default;
-			//DbgPrint("framesync no monitor, write 0xc38 = 0x%x \n", pHalData->framesync);
 		}
 	}
 }
@@ -3513,10 +2454,8 @@ void dm_check_fsync(struct net_device *dev)
  * Detect Signal strength to control TX Registry
  * Tx Power Control For Near/Far Range
  */
-static void dm_init_dynamic_txpower(struct net_device *dev)
+static void dm_init_dynamic_txpower(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	//Initial TX Power Control for near/far range , add by amy 2008/05/15, porting from windows code.
 	priv->ieee80211->bdynamic_txpower_enable = true;    //Default to enable Tx Power Control
 	priv->bLastDTPFlag_High = false;
@@ -3525,9 +2464,8 @@ static void dm_init_dynamic_txpower(struct net_device *dev)
 	priv->bDynamicTxLowPower = false;
 }
 
-static void dm_dynamic_txpower(struct net_device *dev)
+static void dm_dynamic_txpower(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	unsigned int txhipower_threshhold=0;
         unsigned int txlowpower_threshold=0;
 	if(priv->ieee80211->bdynamic_txpower_enable != true)
@@ -3536,7 +2474,6 @@ static void dm_dynamic_txpower(struct net_device *dev)
 		priv->bDynamicTxLowPower = false;
 		return;
 	}
-	//printk("priv->ieee80211->current_network.unknown_cap_exist is %d ,priv->ieee80211->current_network.broadcom_cap_exist is %d\n",priv->ieee80211->current_network.unknown_cap_exist,priv->ieee80211->current_network.broadcom_cap_exist);
         if((priv->ieee80211->current_network.atheros_cap_exist ) && (priv->ieee80211->mode == IEEE_G)){
 		txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH;
 		txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW;
@@ -3547,9 +2484,7 @@ static void dm_dynamic_txpower(struct net_device *dev)
 		txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW;
 	}
 
-//	printk("=======>%s(): txhipower_threshhold is %d,txlowpower_threshold is %d\n",__FUNCTION__,txhipower_threshhold,txlowpower_threshold);
-
-	RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb);
+	RT_TRACE(COMP_TXAGC, "priv->undecorated_smoothed_pwdb = %ld\n" , priv->undecorated_smoothed_pwdb);
 
 	if(priv->ieee80211->state == IEEE80211_LINKED)
 	{
@@ -3586,10 +2521,10 @@ static void dm_dynamic_txpower(struct net_device *dev)
 	if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) ||
 		(priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) )
 	{
-		RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190()  channel = %d \n" , priv->ieee80211->current_network.channel);
+		RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n", priv->ieee80211->current_network.channel);
 
 
-		rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel);
+		rtl8192_phy_setTxPower(priv, priv->ieee80211->current_network.channel);
 
 	}
 	priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
@@ -3598,39 +2533,22 @@ static void dm_dynamic_txpower(struct net_device *dev)
 }
 
 //added by vivi, for read tx rate and retrycount
-static void dm_check_txrateandretrycount(struct net_device * dev)
+static void dm_check_txrateandretrycount(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device* ieee = priv->ieee80211;
-	//for 11n tx rate
-//	priv->stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg);
-	ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg);
-	//printk("=============>tx_rate_reg:%x\n", ieee->softmac_stats.CurrentShowTxate);
+
 	//for initial tx rate
-//	priv->stats.last_packet_rate = read_nic_byte(dev, Initial_Tx_Rate_Reg);
-	ieee->softmac_stats.last_packet_rate = read_nic_byte(dev ,Initial_Tx_Rate_Reg);
+	ieee->softmac_stats.last_packet_rate = read_nic_byte(priv ,Initial_Tx_Rate_Reg);
 	//for tx tx retry count
-//	priv->stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg);
-	ieee->softmac_stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg);
+	ieee->softmac_stats.txretrycount = read_nic_dword(priv, Tx_Retry_Count_Reg);
 }
 
-static void dm_send_rssi_tofw(struct net_device *dev)
+static void dm_send_rssi_tofw(struct r8192_priv *priv)
 {
-	DCMD_TXCMD_T			tx_cmd;
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	// If we test chariot, we should stop the TX command ?
 	// Because 92E will always silent reset when we send tx command. We use register
 	// 0x1e0(byte) to botify driver.
-	write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
+	write_nic_byte(priv, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
 	return;
-#if 1
-	tx_cmd.Op		= TXCMD_SET_RX_RSSI;
-	tx_cmd.Length	= 4;
-	tx_cmd.Value		= priv->undecorated_smoothed_pwdb;
-
-	cmpk_message_handle_tx(dev, (u8*)&tx_cmd,
-								DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T));
-#endif
 }
 
diff --git a/drivers/staging/rtl8192e/r8192E_dm.h b/drivers/staging/rtl8192e/r8192E_dm.h
index 237c30d..b5b34ea 100644
--- a/drivers/staging/rtl8192e/r8192E_dm.h
+++ b/drivers/staging/rtl8192e/r8192E_dm.h
@@ -16,12 +16,10 @@
  *	10/04/2007  MHC    	Create initial version.
  *
  *****************************************************************************/
- /* Check to see if the file has been included already.  */
+
 #ifndef	__R8192UDM_H__
 #define __R8192UDM_H__
 
-
-/*--------------------------Define Parameters-------------------------------*/
 #define 		OFDM_Table_Length	19
 #define		CCK_Table_length	12
 
@@ -65,54 +63,7 @@
 #define 		Initial_Tx_Rate_Reg         0x1e1 //0x1b9
 #define 		Tx_Retry_Count_Reg         0x1ac
 #define		RegC38_TH				 20
-#if 0
-//----------------------------------------------------------------------------
-//       8190 Rate Adaptive Table Register	(offset 0x320, 4 byte)
-//----------------------------------------------------------------------------
-
-//CCK
-#define	RATR_1M					0x00000001
-#define	RATR_2M					0x00000002
-#define	RATR_55M					0x00000004
-#define	RATR_11M					0x00000008
-//OFDM
-#define	RATR_6M					0x00000010
-#define	RATR_9M					0x00000020
-#define	RATR_12M					0x00000040
-#define	RATR_18M					0x00000080
-#define	RATR_24M					0x00000100
-#define	RATR_36M					0x00000200
-#define	RATR_48M					0x00000400
-#define	RATR_54M					0x00000800
-//MCS 1 Spatial Stream
-#define	RATR_MCS0					0x00001000
-#define	RATR_MCS1					0x00002000
-#define	RATR_MCS2					0x00004000
-#define	RATR_MCS3					0x00008000
-#define	RATR_MCS4					0x00010000
-#define	RATR_MCS5					0x00020000
-#define	RATR_MCS6					0x00040000
-#define	RATR_MCS7					0x00080000
-//MCS 2 Spatial Stream
-#define	RATR_MCS8					0x00100000
-#define	RATR_MCS9					0x00200000
-#define	RATR_MCS10					0x00400000
-#define	RATR_MCS11					0x00800000
-#define	RATR_MCS12					0x01000000
-#define	RATR_MCS13					0x02000000
-#define	RATR_MCS14					0x04000000
-#define	RATR_MCS15					0x08000000
-// ALL CCK Rate
-#define RATE_ALL_CCK				RATR_1M|RATR_2M|RATR_55M|RATR_11M
-#define RATE_ALL_OFDM_AG			RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M\
-									|RATR_36M|RATR_48M|RATR_54M
-#define RATE_ALL_OFDM_2SS			RATR_MCS8|RATR_MCS9	|RATR_MCS10|RATR_MCS11| \
-									RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15
-#endif
-/*--------------------------Define Parameters-------------------------------*/
-
-
-/*------------------------------Define structure----------------------------*/
+
 /* 2007/10/04 MH Define upper and lower threshold of DIG enable or disable. */
 typedef struct _dynamic_initial_gain_threshold_
 {
@@ -256,55 +207,22 @@ typedef struct tag_Tx_Config_Cmd_Format
 	u32	Length;									/* Command packet length. */
 	u32	Value;
 }DCMD_TXCMD_T, *PDCMD_TXCMD_T;
-/*------------------------------Define structure----------------------------*/
-
-
-/*------------------------Export global variable----------------------------*/
-extern	dig_t	dm_digtable;
-extern DRxPathSel      DM_RxPathSelTable;
-/*------------------------Export global variable----------------------------*/
 
 
-/*------------------------Export Marco Definition---------------------------*/
+extern dig_t dm_digtable;
+extern DRxPathSel DM_RxPathSelTable;
 
-/*------------------------Export Marco Definition---------------------------*/
+void init_hal_dm(struct r8192_priv *priv);
+void deinit_hal_dm(struct r8192_priv *priv);
 
+void hal_dm_watchdog(struct r8192_priv *priv);
 
-/*--------------------------Exported Function prototype---------------------*/
-/*--------------------------Exported Function prototype---------------------*/
-extern  void    init_hal_dm(struct net_device *dev);
-extern  void deinit_hal_dm(struct net_device *dev);
-
-extern void hal_dm_watchdog(struct net_device *dev);
-
-
-extern  void    init_rate_adaptive(struct net_device *dev);
-extern  void    dm_txpower_trackingcallback(struct work_struct *work);
-
-extern  void    dm_cck_txpower_adjust(struct net_device *dev,bool  binch14);
-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_ChangeFsyncSetting(struct net_device *dev,
-                                                                                                s32             DM_Type,
-                                                                                                s32             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);
-#if 0
-extern  bool    dm_check_lbus_status(struct net_device *dev);
-#endif
-extern  void dm_check_fsync(struct net_device *dev);
-extern  void dm_initialize_txpower_tracking(struct net_device *dev);
+void init_rate_adaptive(struct r8192_priv *priv);
+void dm_txpower_trackingcallback(struct work_struct *work);
+void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
+void dm_initialize_txpower_tracking(struct r8192_priv *priv);
+void dm_cck_txpower_adjust(struct r8192_priv *priv, bool binch14);
 
 
 #endif	/*__R8192UDM_H__ */
 
-
-/* End of r8192U_dm.h */
diff --git a/drivers/staging/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/r8192E_hw.h
index 346bfb1..24e7303 100644
--- a/drivers/staging/rtl8192e/r8192E_hw.h
+++ b/drivers/staging/rtl8192e/r8192E_hw.h
@@ -21,7 +21,6 @@
 #define R8180_HW
 
 typedef enum _VERSION_8190{
-	// RTL8190
 	VERSION_8190_BD=0x3,
 	VERSION_8190_BE
 }VERSION_8190,*PVERSION_8190;
@@ -38,15 +37,7 @@ typedef enum _BaseBand_Config_Type{
 	BaseBand_Config_PHY_REG = 0,			//Radio Path A
 	BaseBand_Config_AGC_TAB = 1,			//Radio Path B
 }BaseBand_Config_Type, *PBaseBand_Config_Type;
-#if 0
-typedef enum _RT_RF_TYPE_819xU{
-	RF_TYPE_MIN = 0,
-	RF_8225,
-	RF_8256,
-	RF_8258,
-	RF_PSEUDO_11N = 4,
-}RT_RF_TYPE_819xU, *PRT_RF_TYPE_819xU;
-#endif
+
 #define	RTL8187_REQT_READ	0xc0
 #define	RTL8187_REQT_WRITE	0x40
 #define	RTL8187_REQ_GET_REGS	0x05
@@ -55,8 +46,6 @@ typedef enum _RT_RF_TYPE_819xU{
 #define R8180_MAX_RETRY 255
 #define MAX_TX_URB 5
 #define MAX_RX_URB 16
-//#define MAX_RX_NORMAL_URB 3
-//#define MAX_RX_COMMAND_URB 2
 #define RX_URB_SIZE 9100
 
 #define BB_ANTATTEN_CHAN14	0x0c
@@ -68,7 +57,6 @@ typedef enum _RT_RF_TYPE_819xU{
 #define BB_HOST_BANG_RW (1<<3)
 #define BB_HOST_BANG_DATA	 1
 
-//#if (RTL819X_FPGA_VER & RTL819X_FPGA_VIVI_070920)
 #define RTL8190_EEPROM_ID	0x8129
 #define EEPROM_VID		0x02
 #define EEPROM_DID		0x04
@@ -95,29 +83,15 @@ typedef enum _RT_RF_TYPE_819xU{
 #define EEPROM_Default_TxPower			0x1010
 #define EEPROM_ICVersion_ChannelPlan	0x7C	//0x7C:ChannelPlan, 0x7D:IC_Version
 #define EEPROM_Customer_ID			0x7B	//0x7B:CustomerID
-#ifdef RTL8190P
-#define EEPROM_RFInd_PowerDiff			0x14
-#define EEPROM_ThermalMeter			0x15
-#define EEPROM_TxPwDiff_CrystalCap		0x16
-#define EEPROM_TxPwIndex_CCK			0x18	//0x18~0x25
-#define EEPROM_TxPwIndex_OFDM_24G	0x26	//0x26~0x33
-#define EEPROM_TxPwIndex_OFDM_5G		0x34	//0x34~0x7B
-#define EEPROM_C56_CrystalCap			0x17	//0x17
-#define EEPROM_C56_RfA_CCK_Chnl1_TxPwIndex	0x80	//0x80
-#define EEPROM_C56_RfA_HT_OFDM_TxPwIndex	0x81	//0x81~0x83
-#define EEPROM_C56_RfC_CCK_Chnl1_TxPwIndex	0xbc	//0xb8
-#define EEPROM_C56_RfC_HT_OFDM_TxPwIndex	0xb9	//0xb9~0xbb
-#else
-#ifdef RTL8192E
+
 #define EEPROM_RFInd_PowerDiff			0x28
 #define EEPROM_ThermalMeter			0x29
 #define EEPROM_TxPwDiff_CrystalCap		0x2A	//0x2A~0x2B
 #define EEPROM_TxPwIndex_CCK			0x2C	//0x23
 #define EEPROM_TxPwIndex_OFDM_24G	0x3A	//0x24~0x26
-#endif
-#endif
+
 #define EEPROM_Default_TxPowerLevel		0x10
-//#define EEPROM_ChannelPlan			0x7c	//0x7C
+
 #define EEPROM_IC_VER				0x7d	//0x7D
 #define EEPROM_CRC				0x7e	//0x7E~0x7F
 
@@ -131,7 +105,7 @@ typedef enum _RT_RF_TYPE_819xU{
 #define EEPROM_CID_Pronet				0x7
 #define EEPROM_CID_DLINK				0x8
 #define EEPROM_CID_WHQL 				0xFE  //added by sherry for dtm, 20080728
-//#endif
+
 enum _RTL8192Pci_HW {
 	MAC0 			= 0x000,
 	MAC1 			= 0x001,
@@ -499,311 +473,9 @@ enum _RTL8192Pci_HW {
 	DRIVER_RSSI		= 0x32c,	// Driver tell Firmware current RSSI
 	MCS_TXAGC		= 0x340, // MCS AGC
 	CCK_TXAGC		= 0x348, // CCK AGC
-//	IMR			= 0x354, // Interrupt Mask Register
-//	IMR_POLL		= 0x360,
 	MacBlkCtrl		= 0x403, // Mac block on/off control register
 
-	//Cmd9346CR		= 0x00e,
-//#define Cmd9346CR_9356SEL	(1<<4)
-#if 0
-/* 0x0006 - 0x0007 - reserved */
-	RXFIFOCOUNT 		= 0x010,
-	TXFIFOCOUNT 		= 0x012,
-	BQREQ 			= 0x013,
-/* 0x0010 - 0x0017 - reserved */
-	TSFTR 			= 0x018,
-	TLPDA 			= 0x020,
-	TNPDA 			= 0x024,
-	THPDA 			= 0x028,
-	BSSID 			= 0x02E,
-	RESP_RATE 		= 0x034,
-	CMD 			= 0x037,
-#define CMD_RST_SHIFT 4
-#define CMD_RESERVED_MASK ((1<<1) | (1<<5) | (1<<6) | (1<<7))
-#define CMD_RX_ENABLE_SHIFT 3
-#define CMD_TX_ENABLE_SHIFT 2
-#define CR_RST      ((1<< 4))
-#define CR_RE       ((1<< 3))
-#define CR_TE       ((1<< 2))
-#define CR_MulRW    ((1<< 0))
-
-	INTA 			= 0x03e,
-#endif
-
-///////////////////
-//////////////////
-#if 0
-	TX_CONF 		= 0x040,
-#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30
-#define TX_LOOPBACK_SHIFT 17
-#define TX_LOOPBACK_MAC 1
-#define TX_LOOPBACK_BASEBAND 2
-#define TX_LOOPBACK_NONE 0
-#define TX_LOOPBACK_CONTINUE 3
-#define TX_LOOPBACK_MASK ((1<<17)|(1<<18))
-#define TX_LRLRETRY_SHIFT 0
-#define TX_SRLRETRY_SHIFT 8
-#define TX_NOICV_SHIFT 19
-#define TX_NOCRC_SHIFT 16
-#define TCR_DurProcMode  ((1<<30))
-#define TCR_DISReqQsize  ((1<<28))
-#define TCR_HWVERID_MASK ((1<<27)|(1<<26)|(1<<25))
-#define TCR_HWVERID_SHIFT 25
-#define TCR_SWPLCPLEN     ((1<<24))
-#define TCR_PLCP_LEN TCR_SAT // rtl8180
-#define TCR_MXDMA_MASK   ((1<<23)|(1<<22)|(1<<21))
-#define TCR_MXDMA_1024 6
-#define TCR_MXDMA_2048 7
-#define TCR_MXDMA_SHIFT  21
-#define TCR_DISCW   ((1<<20))
-#define TCR_ICV     ((1<<19))
-#define TCR_LBK     ((1<<18)|(1<<17))
-#define TCR_LBK1    ((1<<18))
-#define TCR_LBK0    ((1<<17))
-#define TCR_CRC     ((1<<16))
-#define TCR_SRL_MASK   ((1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8))
-#define TCR_LRL_MASK   ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7))
-#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 //rtl8185
-
-	RX_CONF 		= 0x044,
-#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \
-(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23))
-#define RX_CHECK_BSSID_SHIFT 23
-#define ACCEPT_PWR_FRAME_SHIFT 22
-#define ACCEPT_MNG_FRAME_SHIFT 20
-#define ACCEPT_CTL_FRAME_SHIFT 19
-#define ACCEPT_DATA_FRAME_SHIFT 18
-#define ACCEPT_ICVERR_FRAME_SHIFT 12
-#define ACCEPT_CRCERR_FRAME_SHIFT 5
-#define ACCEPT_BCAST_FRAME_SHIFT 3
-#define ACCEPT_MCAST_FRAME_SHIFT 2
-#define ACCEPT_ALLMAC_FRAME_SHIFT 0
-#define ACCEPT_NICMAC_FRAME_SHIFT 1
-#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15))
-#define RX_FIFO_THRESHOLD_SHIFT 13
-#define RX_FIFO_THRESHOLD_128 3
-#define RX_FIFO_THRESHOLD_256 4
-#define RX_FIFO_THRESHOLD_512 5
-#define RX_FIFO_THRESHOLD_1024 6
-#define RX_FIFO_THRESHOLD_NONE 7
-#define RX_AUTORESETPHY_SHIFT 28
-#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10))
-#define MAX_RX_DMA_2048 7
-#define MAX_RX_DMA_1024	6
-#define MAX_RX_DMA_SHIFT 10
-#define RCR_ONLYERLPKT ((1<<31))
-#define RCR_CS_SHIFT   29
-#define RCR_CS_MASK    ((1<<30) | (1<<29))
-#define RCR_ENMARP     ((1<<28))
-#define RCR_CBSSID     ((1<<23))
-#define RCR_APWRMGT    ((1<<22))
-#define RCR_ADD3       ((1<<21))
-#define RCR_AMF        ((1<<20))
-#define RCR_ACF        ((1<<19))
-#define RCR_ADF        ((1<<18))
-#define RCR_RXFTH      ((1<<15)|(1<<14)|(1<<13))
-#define RCR_RXFTH2     ((1<<15))
-#define RCR_RXFTH1     ((1<<14))
-#define RCR_RXFTH0     ((1<<13))
-#define RCR_AICV       ((1<<12))
-#define RCR_MXDMA      ((1<<10)|(1<< 9)|(1<< 8))
-#define RCR_MXDMA2     ((1<<10))
-#define RCR_MXDMA1     ((1<< 9))
-#define RCR_MXDMA0     ((1<< 8))
-#define RCR_9356SEL    ((1<< 6))
-#define RCR_ACRC32     ((1<< 5))
-#define RCR_AB         ((1<< 3))
-#define RCR_AM         ((1<< 2))
-#define RCR_APM        ((1<< 1))
-#define RCR_AAP        ((1<< 0))
-
-	INT_TIMEOUT 		= 0x048,
-
-	TX_BEACON_RING_ADDR 	= 0x04c,
-
-#endif
-#if 0
-	CONFIG0 		= 0x051,
-#define CONFIG0_WEP104     ((1<<6))
-#define CONFIG0_LEDGPO_En  ((1<<4))
-#define CONFIG0_Aux_Status ((1<<3))
-#define CONFIG0_GL         ((1<<1)|(1<<0))
-#define CONFIG0_GL1        ((1<<1))
-#define CONFIG0_GL0        ((1<<0))
-	CONFIG1 		= 0x052,
-#define CONFIG1_LEDS       ((1<<7)|(1<<6))
-#define CONFIG1_LEDS1      ((1<<7))
-#define CONFIG1_LEDS0      ((1<<6))
-#define CONFIG1_LWACT      ((1<<4))
-#define CONFIG1_MEMMAP     ((1<<3))
-#define CONFIG1_IOMAP      ((1<<2))
-#define CONFIG1_VPD        ((1<<1))
-#define CONFIG1_PMEn       ((1<<0))
-	CONFIG2 		= 0x053,
-#define CONFIG2_LCK        ((1<<7))
-#define CONFIG2_ANT        ((1<<6))
-#define CONFIG2_DPS        ((1<<3))
-#define CONFIG2_PAPE_sign  ((1<<2))
-#define CONFIG2_PAPE_time  ((1<<1)|(1<<0))
-#define CONFIG2_PAPE_time1 ((1<<1))
-#define CONFIG2_PAPE_time0 ((1<<0))
-	ANA_PARAM 		= 0x054,
-	CONFIG3 		= 0x059,
-#define CONFIG3_GNTSel     ((1<<7))
-#define CONFIG3_PARM_En    ((1<<6))
-#define CONFIG3_Magic      ((1<<5))
-#define CONFIG3_CardB_En   ((1<<3))
-#define CONFIG3_CLKRUN_En  ((1<<2))
-#define CONFIG3_FuncRegEn  ((1<<1))
-#define CONFIG3_FBtbEn     ((1<<0))
-#define CONFIG3_CLKRUN_SHIFT 2
-#define CONFIG3_ANAPARAM_W_SHIFT 6
-	CONFIG4 		= 0x05a,
-#define CONFIG4_VCOPDN     ((1<<7))
-#define CONFIG4_PWROFF     ((1<<6))
-#define CONFIG4_PWRMGT     ((1<<5))
-#define CONFIG4_LWPME      ((1<<4))
-#define CONFIG4_LWPTN      ((1<<2))
-#define CONFIG4_RFTYPE     ((1<<1)|(1<<0))
-#define CONFIG4_RFTYPE1    ((1<<1))
-#define CONFIG4_RFTYPE0    ((1<<0))
-	TESTR 			= 0x05b,
-#define TFPC_AC  0x05C
-
-#define SCR 0x05F
-	PGSELECT 		= 0x05e,
-#define PGSELECT_PG_SHIFT 0
-	SECURITY 		= 0x05f,
-#define SECURITY_WEP_TX_ENABLE_SHIFT 1
-#define SECURITY_WEP_RX_ENABLE_SHIFT 0
-#define SECURITY_ENCRYP_104 1
-#define SECURITY_ENCRYP_SHIFT 4
-#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5))
-
-	ANA_PARAM2 		= 0x060,
-	BEACON_INTERVAL 	= 0x070,
-#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \
-(1<<6)|(1<<7)|(1<<8)|(1<<9))
-
-	ATIM_WND 		= 0x072,
-#define ATIM_WND_MASK      (0x01FF)
-
-	BCN_INTR_ITV 		= 0x074,
-#define BCN_INTR_ITV_MASK  (0x01FF)
-
-	ATIM_INTR_ITV		= 0x076,
-#define ATIM_INTR_ITV_MASK  (0x01FF)
-
-	AckTimeOutReg      	= 0x079, //ACK timeout register, in unit of 4 us.
-	PHY_ADR 		= 0x07c,
-	PHY_READ 		= 0x07e,
-	RFPinsOutput 		= 0x080,
-	RFPinsEnable 		= 0x082,
-//Page 0
-	RFPinsSelect 		= 0x084,
-#define SW_CONTROL_GPIO 0x400
-	RFPinsInput 		= 0x086,
-	RF_PARA 		= 0x088,
-	RF_TIMING 		= 0x08c,
-	GP_ENABLE 		= 0x090,
-	GPIO 			= 0x091,
-	TX_AGC_CTL 		= 0x09c,
-#define TX_AGC_CTL_PER_PACKET_TXAGC	0x01
-#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0
-#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1
-#define TX_AGC_CTL_FEEDBACK_ANT 2
-#define TXAGC_CTL_PER_PACKET_ANT_SEL 0x02
-	OFDM_TXAGC 		= 0x09e,
-	ANTSEL 			= 0x09f,
-
-
-
-	SIFS 			= 0x0b4,
-	DIFS 			= 0x0b5,
-	SLOT 			= 0x0b6,
-	CW_CONF 		= 0x0bc,
-#define CW_CONF_PERPACKET_RETRY_LIMIT 0x02
-#define CW_CONF_PERPACKET_CW 0x01
-#define CW_CONF_PERPACKET_RETRY_SHIFT 1
-#define CW_CONF_PERPACKET_CW_SHIFT 0
-	CW_VAL 			= 0x0bd,
-	RATE_FALLBACK 		= 0x0be,
-#define MAX_RESP_RATE_SHIFT 4
-#define MIN_RESP_RATE_SHIFT 0
-#define RATE_FALLBACK_CTL_ENABLE  0x80
-#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00
-	ACM_CONTROL             = 0x0BF,      // ACM Control Registe
-//----------------------------------------------------------------------------
-//       8187B ACM_CONTROL bits						(Offset 0xBF, 1 Byte)
-//----------------------------------------------------------------------------
-#define VOQ_ACM_EN				(0x01 << 7) //BIT7
-#define VIQ_ACM_EN				(0x01 << 6) //BIT6
-#define BEQ_ACM_EN				(0x01 << 5) //BIT5
-#define ACM_HW_EN				(0x01 << 4) //BIT4
-#define TXOPSEL					(0x01 << 3) //BIT3
-#define VOQ_ACM_CTL				(0x01 << 2) //BIT2 // Set to 1 when AC_VO used time reaches or exceeds the admitted time
-#define VIQ_ACM_CTL				(0x01 << 1) //BIT1 // Set to 1 when AC_VI used time reaches or exceeds the admitted time
-#define BEQ_ACM_CTL				(0x01 << 0) //BIT0 // Set to 1 when AC_BE used time reaches or exceeds the admitted time
-	CONFIG5 		= 0x0D8,
-#define CONFIG5_TX_FIFO_OK ((1<<7))
-#define CONFIG5_RX_FIFO_OK ((1<<6))
-#define CONFIG5_CALON      ((1<<5))
-#define CONFIG5_EACPI      ((1<<2))
-#define CONFIG5_LANWake    ((1<<1))
-#define CONFIG5_PME_STS    ((1<<0))
-	TX_DMA_POLLING 		= 0x0fd,
-#define TX_DMA_POLLING_BEACON_SHIFT 7
-#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6
-#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5
-#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4
-#define TX_DMA_STOP_BEACON_SHIFT 3
-#define TX_DMA_STOP_HIPRIORITY_SHIFT 2
-#define TX_DMA_STOP_NORMPRIORITY_SHIFT 1
-#define TX_DMA_STOP_LOWPRIORITY_SHIFT 0
-	CWR 			= 0x0DC,
-	RetryCTR 		= 0x0DE,
-	INT_MIG                 = 0x0E2,      // Interrupt Migration (0xE2 ~ 0xE3)
-	TID_AC_MAP         	= 0x0E8,     // TID to AC Mapping Register
-	ANA_PARAM3 		= 0x0EE,
-
-
-//page 1
-	Wakeup0 		= 0x084,
-	Wakeup1 		= 0x08C,
-	Wakeup2LD 		= 0x094,
-	Wakeup2HD 		= 0x09C,
-	Wakeup3LD 		= 0x0A4,
-	Wakeup3HD 		= 0x0AC,
-	Wakeup4LD 		= 0x0B4,
-	Wakeup4HD 		= 0x0BC,
-	CRC0 			= 0x0C4,
-	CRC1 			= 0x0C6,
-	CRC2 			= 0x0C8,
-	CRC3 			= 0x0CA,
-	CRC4 			= 0x0CC,
-/* 0x00CE - 0x00D3 - reserved */
-
-	RFSW_CTRL               = 0x272,   // 0x272-0x273.
-
-/**************************************************************************/
-	FER 			= 0x0F0,
-	FEMR 			= 0x0F4,
-	FPSR 			= 0x0F8,
-	FFER 			= 0x0FC,
-
-	AC_VO_PARAM             = 0x0F0,      // AC_VO Parameters Record
-	AC_VI_PARAM             = 0x0F4,      // AC_VI Parameters Record
-	AC_BE_PARAM             = 0x0F8,      // AC_BE Parameters Record
-	AC_BK_PARAM             = 0x0FC,      // AC_BK Parameters Record
-	TALLY_SEL 		= 0x0fc,
-#endif
-}
-;
-//----------------------------------------------------------------------------
-//       818xB AnaParm & AnaParm2 Register
-//----------------------------------------------------------------------------
-//#define ANAPARM_ASIC_ON    0x45090658
-//#define ANAPARM2_ASIC_ON   0x727f3f52
+};
 
 #define GPI 0x108
 #define GPO 0x109
diff --git a/drivers/staging/rtl8192e/r8192E_wx.c b/drivers/staging/rtl8192e/r8192E_wx.c
index 5ae6516..adad91b 100644
--- a/drivers/staging/rtl8192e/r8192E_wx.c
+++ b/drivers/staging/rtl8192e/r8192E_wx.c
@@ -215,14 +215,14 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
 	if (priv->bHwRadioOff)
 		return 0;
 
-	rtState = priv->ieee80211->eRFPowerState;
+	rtState = priv->eRFPowerState;
 	down(&priv->wx_sem);
 #ifdef ENABLE_IPS
 	if(wrqu->mode == IW_MODE_ADHOC){
 
-		if(priv->ieee80211->PowerSaveControl.bInactivePs){
+		if (priv->PowerSaveControl.bInactivePs) {
 			if(rtState == eRfOff){
-				if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+				if(priv->RfOffReason > RF_CHANGE_BY_IPS)
 				{
 					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
 					up(&priv->wx_sem);
@@ -231,7 +231,7 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
 				else{
 					RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
 					down(&priv->ieee80211->ips_sem);
-					IPSLeave(dev);
+					IPSLeave(priv);
 					up(&priv->ieee80211->ips_sem);
 				}
 			}
@@ -301,8 +301,6 @@ static int rtl8180_wx_get_range(struct net_device *dev,
 //	range->old_num_channels;
 //	range->old_num_frequency;
 //	range->old_freq[6]; /* Filler to keep "version" at the same offset */
-	if(priv->rf_set_sens != NULL)
-		range->sensitivity = priv->max_sens;	/* signal level threshold range */
 
 	range->max_qual.qual = 100;
 	/* TODO: Find real max RSSI and stick here */
@@ -366,10 +364,10 @@ static int rtl8180_wx_get_range(struct net_device *dev,
 	}
 	range->num_frequency = val;
 	range->num_channels = val;
-#if WIRELESS_EXT > 17
+
 	range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
 			  IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
-#endif
+
 	tmp->scan_capa = 0x01;
 	return 0;
 }
@@ -386,7 +384,7 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
 	if (priv->bHwRadioOff)
 		return 0;
 
-	rtState = priv->ieee80211->eRFPowerState;
+	rtState = priv->eRFPowerState;
 
 	if(!priv->up) return -ENETDOWN;
 	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
@@ -408,9 +406,9 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
 #ifdef ENABLE_IPS
 	priv->ieee80211->actscanning = true;
 	if(priv->ieee80211->state != IEEE80211_LINKED){
-		if(priv->ieee80211->PowerSaveControl.bInactivePs){
+		if (priv->PowerSaveControl.bInactivePs) {
 			if(rtState == eRfOff){
-				if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+				if(priv->RfOffReason > RF_CHANGE_BY_IPS)
 				{
 					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
 					up(&priv->wx_sem);
@@ -419,7 +417,7 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
 				else{
 					//RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
 					down(&priv->ieee80211->ips_sem);
-					IPSLeave(dev);
+					IPSLeave(priv);
 					up(&priv->ieee80211->ips_sem);
 				}
 			}
@@ -477,12 +475,12 @@ static int r8192_wx_set_essid(struct net_device *dev,
 	if (priv->bHwRadioOff)
 		return 0;
 
-	rtState = priv->ieee80211->eRFPowerState;
+	rtState = priv->eRFPowerState;
 	down(&priv->wx_sem);
 
 #ifdef ENABLE_IPS
         down(&priv->ieee80211->ips_sem);
-        IPSLeave(dev);
+        IPSLeave(priv);
         up(&priv->ieee80211->ips_sem);
 #endif
 	ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
@@ -592,7 +590,7 @@ static int r8192_wx_set_wap(struct net_device *dev,
 
 #ifdef ENABLE_IPS
         down(&priv->ieee80211->ips_sem);
-        IPSLeave(dev);
+        IPSLeave(priv);
         up(&priv->ieee80211->ips_sem);
 #endif
 	ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
@@ -649,13 +647,13 @@ static int r8192_wx_set_enc(struct net_device *dev,
         priv->ieee80211->wx_set_enc = 1;
 #ifdef ENABLE_IPS
         down(&priv->ieee80211->ips_sem);
-        IPSLeave(dev);
+        IPSLeave(priv);
         up(&priv->ieee80211->ips_sem);
 #endif
 
 	down(&priv->wx_sem);
 
-	RT_TRACE(COMP_SEC, "Setting SW wep key");
+	RT_TRACE(COMP_SEC, "Setting SW wep key\n");
 	ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
 
 	up(&priv->wx_sem);
@@ -687,78 +685,20 @@ static int r8192_wx_set_enc(struct net_device *dev,
 		//printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
 		if(wrqu->encoding.length==0x5){
 		ieee->pairwise_key_type = KEY_TYPE_WEP40;
-			EnableHWSecurityConfig8192(dev);
-			setKey( dev,
-				key_idx,                //EntryNo
-				key_idx,                //KeyIndex
-				KEY_TYPE_WEP40,         //KeyType
-				zero_addr[key_idx],
-				0,                      //DefaultKey
-				hwkey);                 //KeyContent
-
-#if 0
-			if(key_idx == 0){
-
-				//write_nic_byte(dev, SECR, 7);
-				setKey( dev,
-					4,                      //EntryNo
-					key_idx,                      //KeyIndex
-					KEY_TYPE_WEP40,        //KeyType
-					broadcast_addr,         //addr
-					0,                      //DefaultKey
-					hwkey);                 //KeyContent
-			}
-#endif
+			EnableHWSecurityConfig8192(priv);
+			setKey(priv, key_idx, key_idx, KEY_TYPE_WEP40,
+			       zero_addr[key_idx], 0, hwkey);
 		}
 
 		else if(wrqu->encoding.length==0xd){
 			ieee->pairwise_key_type = KEY_TYPE_WEP104;
-				EnableHWSecurityConfig8192(dev);
-			setKey( dev,
-				key_idx,                //EntryNo
-				key_idx,                //KeyIndex
-				KEY_TYPE_WEP104,        //KeyType
-				zero_addr[key_idx],
-				0,                      //DefaultKey
-				hwkey);                 //KeyContent
-#if 0
-			if(key_idx == 0){
-
-				//write_nic_byte(dev, SECR, 7);
-				setKey( dev,
-					4,                      //EntryNo
-					key_idx,                      //KeyIndex
-					KEY_TYPE_WEP104,        //KeyType
-					broadcast_addr,         //addr
-					0,                      //DefaultKey
-					hwkey);                 //KeyContent
-			}
-#endif
+				EnableHWSecurityConfig8192(priv);
+			setKey(priv, key_idx, key_idx, KEY_TYPE_WEP104,
+			       zero_addr[key_idx], 0, hwkey);
 		}
 		else printk("wrong type in WEP, not WEP40 and WEP104\n");
-
-
 	}
 
-#if 0
-	//consider the setting different key index situation
-	//wrqu->encoding.flags = 801 means that we set key with index "1"
-	if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
-		printk("===>1\n");
-		//write_nic_byte(dev, SECR, 7);
-		EnableHWSecurityConfig8192(dev);
-		//copy wpa config from default key(key0~key3) to broadcast key(key5)
-		//
-		key_idx = (wrqu->encoding.flags & 0xf)-1 ;
-		write_cam(dev, (4*6),   0xffff0000|read_cam(dev, key_idx*6) );
-		write_cam(dev, (4*6)+1, 0xffffffff);
-		write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
-		write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
-		write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
-		write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
-	}
-#endif
-
 	priv->ieee80211->wx_set_enc = 0;
 
 	return ret;
@@ -820,7 +760,7 @@ static int r8192_wx_set_retry(struct net_device *dev,
 	 * I'm unsure if whole reset is really needed
 	 */
 
- 	rtl8192_commit(dev);
+	rtl8192_commit(priv);
 	/*
 	if(priv->up){
 		rtl8180_rtx_disable(dev);
@@ -902,7 +842,6 @@ exit:
 	return err;
 }
 
-#if (WIRELESS_EXT >= 18)
 static int r8192_wx_set_enc_ext(struct net_device *dev,
                                         struct iw_request_info *info,
                                         union iwreq_data *wrqu, char *extra)
@@ -920,7 +859,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
 
 #ifdef ENABLE_IPS
         down(&priv->ieee80211->ips_sem);
-        IPSLeave(dev);
+        IPSLeave(priv);
         up(&priv->ieee80211->ips_sem);
 #endif
 
@@ -932,19 +871,13 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
 		u32 key[4] = {0};
 		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
 		struct iw_point *encoding = &wrqu->encoding;
-#if 0
-		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}};
-#endif
 		u8 idx = 0, alg = 0, group = 0;
+
 		if ((encoding->flags & IW_ENCODE_DISABLED) ||
 		ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
 		{
 			ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
-			CamResetAllEntry(dev);
+			CamResetAllEntry(priv);
 			goto end_hw_sec;
 		}
 		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4;
@@ -958,7 +891,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
 			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
 				alg = KEY_TYPE_WEP104;
 			ieee->pairwise_key_type = alg;
-			EnableHWSecurityConfig8192(dev);
+			EnableHWSecurityConfig8192(priv);
 		}
 		memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
 
@@ -966,37 +899,20 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
 		{
 			if (ext->key_len == 13)
 				ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
-			setKey( dev,
-					idx,//EntryNo
-					idx, //KeyIndex
-					alg,  //KeyType
-					zero, //MacAddr
-					0,              //DefaultKey
-					key);           //KeyContent
+			setKey(priv, idx, idx, alg, zero, 0, key);
 		}
 		else if (group)
 		{
 			ieee->group_key_type = alg;
-			setKey( dev,
-					idx,//EntryNo
-					idx, //KeyIndex
-					alg,  //KeyType
-					broadcast_addr, //MacAddr
-					0,              //DefaultKey
-					key);           //KeyContent
+			setKey(priv, idx, idx, alg, broadcast_addr, 0, key);
 		}
 		else //pairwise key
 		{
 			if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
-							write_nic_byte(dev, 0x173, 1); //fix aes bug
+							write_nic_byte(priv, 0x173, 1); //fix aes bug
 			}
-			setKey( dev,
-					4,//EntryNo
-					idx, //KeyIndex
-					alg,  //KeyType
-					(u8*)ieee->ap_mac_addr, //MacAddr
-					0,              //DefaultKey
-					key);           //KeyContent
+			setKey(priv, 4, idx, alg,
+			       (u8*)ieee->ap_mac_addr, 0, key);
 		}
 
 
@@ -1042,7 +958,7 @@ static int r8192_wx_set_mlme(struct net_device *dev,
 	up(&priv->wx_sem);
 	return ret;
 }
-#endif
+
 static int r8192_wx_set_gen_ie(struct net_device *dev,
                                         struct iw_request_info *info,
                                         union iwreq_data *data, char *extra)
@@ -1074,7 +990,7 @@ static int r8192_wx_adapter_power_status(struct net_device *dev,
 {
 	struct r8192_priv *priv = ieee80211_priv(dev);
 #ifdef ENABLE_LPS
-	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+	PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
 	struct ieee80211_device* ieee = priv->ieee80211;
 #endif
 	down(&priv->wx_sem);
@@ -1090,7 +1006,7 @@ static int r8192_wx_adapter_power_status(struct net_device *dev,
 	} else {
 		//LZM for PS-Poll AID issue. 090429
 		if(priv->ieee80211->state == IEEE80211_LINKED)
-			LeisurePSLeave(dev);
+			LeisurePSLeave(priv->ieee80211);
 
 		priv->ps_force = true;
 		pPSC->bLeisurePs = false;
@@ -1128,11 +1044,7 @@ static iw_handler r8192_wx_handlers[] =
         NULL,                     /* SIOCWIWTHRSPY */
         r8192_wx_set_wap,      	  /* SIOCSIWAP */
         r8192_wx_get_wap,         /* SIOCGIWAP */
-#if (WIRELESS_EXT >= 18)
-        r8192_wx_set_mlme,                     /* MLME-- */
-#else
-	 NULL,
-#endif
+	r8192_wx_set_mlme,        /* MLME-- */
         dummy,                     /* SIOCGIWAPLIST -- depricated */
         r8192_wx_set_scan,        /* SIOCSIWSCAN */
         r8192_wx_get_scan,        /* SIOCGIWSCAN */
@@ -1160,15 +1072,9 @@ static iw_handler r8192_wx_handlers[] =
 	NULL, 			/*---hole---*/
 	r8192_wx_set_gen_ie,//NULL, 			/* SIOCSIWGENIE */
 	NULL, 			/* SIOCSIWGENIE */
-#if (WIRELESS_EXT >= 18)
 	r8192_wx_set_auth,//NULL, 			/* SIOCSIWAUTH */
 	NULL,//r8192_wx_get_auth,//NULL, 			/* SIOCSIWAUTH */
 	r8192_wx_set_enc_ext, 			/* SIOCSIWENCODEEXT */
-#else
-	NULL,
-	NULL,
-	NULL,
-#endif
 	NULL,//r8192_wx_get_enc_ext,//NULL, 			/* SIOCSIWENCODEEXT */
 	NULL, 			/* SIOCSIWPMKSA */
 	NULL, 			 /*---hole---*/
@@ -1216,8 +1122,7 @@ static iw_handler r8192_private_handler[] = {
 	r8192_wx_adapter_power_status,
 };
 
-//#if WIRELESS_EXT >= 17
-struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
 {
        struct r8192_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_device* ieee = priv->ieee80211;
@@ -1245,7 +1150,6 @@ struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
 	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
 	return wstats;
 }
-//#endif
 
 
 struct iw_handler_def  r8192_wx_handlers_def={
@@ -1254,8 +1158,6 @@ struct iw_handler_def  r8192_wx_handlers_def={
 	.private = r8192_private_handler,
 	.num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
  	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
-#if WIRELESS_EXT >= 17
 	.get_wireless_stats = r8192_get_wireless_stats,
-#endif
 	.private_args = (struct iw_priv_args *)r8192_private_args,
 };
diff --git a/drivers/staging/rtl8192e/r8192E_wx.h b/drivers/staging/rtl8192e/r8192E_wx.h
index 291cb6a..25f06c1 100644
--- a/drivers/staging/rtl8192e/r8192E_wx.h
+++ b/drivers/staging/rtl8192e/r8192E_wx.h
@@ -14,8 +14,5 @@
 
 #ifndef R8180_WX_H
 #define R8180_WX_H
-//#include <linux/wireless.h>
 extern struct iw_handler_def r8192_wx_handlers_def;
-/* Enable  the rtl819x_core.c to share this function, david 2008.9.22 */
-struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
 #endif
diff --git a/drivers/staging/rtl8192e/r8192_pm.c b/drivers/staging/rtl8192e/r8192_pm.c
index c691bc9..7bcc4a3 100644
--- a/drivers/staging/rtl8192e/r8192_pm.c
+++ b/drivers/staging/rtl8192e/r8192_pm.c
@@ -25,9 +25,6 @@ int rtl8192E_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
-	u8	ucRegRead;
-#endif
 	u32	ulRegRead;
 
         RT_TRACE(COMP_POWER, "============> r8192E suspend call.\n");
@@ -36,64 +33,23 @@ int rtl8192E_suspend (struct pci_dev *pdev, pm_message_t state)
 
 	if (dev->netdev_ops->ndo_stop)
 		dev->netdev_ops->ndo_stop(dev);
-//	dev->stop(dev);
-#if 0
 
-	netif_carrier_off(dev);
-
-	ieee80211_softmac_stop_protocol(priv->ieee80211);
-
-	write_nic_byte(dev,MSR,(read_nic_byte(dev,MSR)&0xfc)|MSR_LINK_NONE);
-	if(!priv->ieee80211->bSupportRemoteWakeUp) {
-		/* disable tx/rx. In 8185 we write 0x10 (Reset bit),
-		 * but here we make reference to WMAC and wirte 0x0.
-		 * 2006.11.21 Emily
-		 */
-		write_nic_byte(dev, CMDR, 0);
-	}
-	//disable interrupt
-	write_nic_dword(dev,INTA_MASK,0);
-	priv->irq_enabled = 0;
-        write_nic_dword(dev,ISR,read_nic_dword(dev, ISR));
-
-	/* need to  free DM related functions */
-	cancel_work_sync(&priv->reset_wq);
-	del_timer_sync(&priv->fsync_timer);
-	del_timer_sync(&priv->watch_dog_timer);
-	cancel_delayed_work(&priv->watch_dog_wq);
-	cancel_delayed_work(&priv->update_beacon_wq);
-	cancel_work_sync(&priv->qos_activate);
-
-	/* TODO
-#if ((DEV_BUS_TYPE == PCI_INTERFACE) && (HAL_CODE_BASE == RTL8192))
-pHalData->bHwRfOffAction = 2;
-#endif
-*/
-#endif
 	// Call MgntActSet_RF_State instead to prevent RF config race condition.
-	// By Bruce, 2008-01-17.
-	//
 	if(!priv->ieee80211->bSupportRemoteWakeUp) {
-		MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT);
+		MgntActSet_RF_State(priv, eRfOff, RF_CHANGE_BY_INIT);
 		// 2006.11.30. System reset bit
-		ulRegRead = read_nic_dword(dev, CPU_GEN);
+		ulRegRead = read_nic_dword(priv, CPU_GEN);
 		ulRegRead|=CPU_GEN_SYSTEM_RESET;
-		write_nic_dword(dev, CPU_GEN, ulRegRead);
+		write_nic_dword(priv, CPU_GEN, ulRegRead);
 	} else {
 		//2008.06.03 for WOL
-		write_nic_dword(dev, WFCRC0, 0xffffffff);
-		write_nic_dword(dev, WFCRC1, 0xffffffff);
-		write_nic_dword(dev, WFCRC2, 0xffffffff);
-#ifdef RTL8190P
-		//GPIO 0 = TRUE
-		ucRegRead = read_nic_byte(dev, GPO);
-		ucRegRead |= BIT0;
-		write_nic_byte(dev, GPO, ucRegRead);
-#endif
+		write_nic_dword(priv, WFCRC0, 0xffffffff);
+		write_nic_dword(priv, WFCRC1, 0xffffffff);
+		write_nic_dword(priv, WFCRC2, 0xffffffff);
 		//Write PMR register
-		write_nic_byte(dev, PMR, 0x5);
+		write_nic_byte(priv, PMR, 0x5);
 		//Disable tx, enanble rx
-		write_nic_byte(dev, MacBlkCtrl, 0xa);
+		write_nic_byte(priv, MacBlkCtrl, 0xa);
 	}
 
 out_pci_suspend:
@@ -114,12 +70,10 @@ out_pci_suspend:
 int rtl8192E_resume (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	//struct r8192_priv *priv = ieee80211_priv(dev);
-	//union iwreq_data wrqu;
 	int err;
 	u32 val;
 
-        RT_TRACE(COMP_POWER, "================>r8192E resume call.");
+        RT_TRACE(COMP_POWER, "================>r8192E resume call.\n");
 
 	pci_set_power_state(pdev, PCI_D0);
 
@@ -155,7 +109,6 @@ int rtl8192E_resume (struct pci_dev *pdev)
 	if (dev->netdev_ops->ndo_open)
 		dev->netdev_ops->ndo_open(dev);
 
-//	dev->open(dev);
 out:
         RT_TRACE(COMP_POWER, "<================r8192E resume call.\n");
 	return 0;
diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.c b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
index 135439d..756e066 100644
--- a/drivers/staging/rtl8192e/r819xE_cmdpkt.c
+++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
@@ -33,17 +33,12 @@
  * run time. We do not support message more than one segment now.
  */
 RT_STATUS cmpk_message_handle_tx(
-	struct net_device *dev,
+	struct r8192_priv *priv,
 	u8*	code_virtual_address,
 	u32	packettype,
 	u32	buffer_len)
 {
-
 	RT_STATUS 	    rt_status = RT_STATUS_SUCCESS;
-#ifdef RTL8192U
-	return rt_status;
-#else
-	struct r8192_priv   *priv = ieee80211_priv(dev);
 	u16		    frag_threshold;
 	u16		    frag_length = 0, frag_offset = 0;
 	rt_firmware	    *pfirmware = priv->pFirmware;
@@ -55,9 +50,8 @@ RT_STATUS cmpk_message_handle_tx(
 	PTX_FWINFO_8190PCI      pTxFwInfo = NULL;
         int i;
 
-	//spin_lock_irqsave(&priv->tx_lock,flags);
 	RT_TRACE(COMP_CMDPKT,"%s(),buffer_len is %d\n",__FUNCTION__,buffer_len);
-	firmware_init_param(dev);
+	firmware_init_param(priv);
 	//Fragmentation might be required
 	frag_threshold = pfirmware->cmdpacket_frag_thresold;
         do {
@@ -74,27 +68,18 @@ RT_STATUS cmpk_message_handle_tx(
             /* Allocate skb buffer to contain firmware info and tx descriptor info
              * add 4 to avoid packet appending overflow.
              * */
-#ifdef RTL8192U
-            skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
-#else
             skb  = dev_alloc_skb(frag_length + priv->ieee80211->tx_headroom + 4);
-#endif
             if(skb == NULL) {
                 rt_status = RT_STATUS_FAILURE;
                 goto Failed;
             }
 
-            memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
             tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
             tcb_desc->queue_index = TXCMD_QUEUE;
             tcb_desc->bCmdOrInit = packettype;
             tcb_desc->bLastIniPkt = bLastIniPkt;
             tcb_desc->pkt_size = frag_length;
 
-#ifdef RTL8192U
-            skb_reserve(skb, USB_HWDESC_HEADER_LEN);
-#endif
-
             //seg_ptr = skb_put(skb, frag_length + priv->ieee80211->tx_headroom);
             seg_ptr = skb_put(skb, priv->ieee80211->tx_headroom);
 
@@ -116,7 +101,7 @@ RT_STATUS cmpk_message_handle_tx(
                 *seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0;
             }
             skb_put(skb, i);
-            priv->ieee80211->softmac_hard_start_xmit(skb,dev);
+            priv->ieee80211->softmac_hard_start_xmit(skb, priv->ieee80211);
 
             code_virtual_address += frag_length;
             frag_offset += frag_length;
@@ -124,19 +109,11 @@ RT_STATUS cmpk_message_handle_tx(
         }while(frag_offset < buffer_len);
 
 Failed:
-	//spin_unlock_irqrestore(&priv->tx_lock,flags);
 	return rt_status;
-
-
-#endif
 }
 
-static void
-cmpk_count_txstatistic(
-	struct net_device *dev,
-	cmpk_txfb_t	*pstx_fb)
+static void cmpk_count_txstatistic(struct r8192_priv *priv, cmpk_txfb_t *pstx_fb)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 #ifdef ENABLE_PS
 	RT_RF_POWER_STATE	rtState;
 
@@ -160,52 +137,14 @@ cmpk_count_txstatistic(
 	   feedback info. */
 	if (pstx_fb->tok)
 	{
-		priv->stats.txfeedbackok++;
 		priv->stats.txoktotal++;
-		priv->stats.txokbytestotal += pstx_fb->pkt_length;
-		priv->stats.txokinperiod++;
 
 		/* We can not make sure broadcast/multicast or unicast mode. */
-		if (pstx_fb->pkt_type == PACKET_MULTICAST)
-		{
-			priv->stats.txmulticast++;
-			priv->stats.txbytesmulticast += pstx_fb->pkt_length;
-		}
-		else if (pstx_fb->pkt_type == PACKET_BROADCAST)
-		{
-			priv->stats.txbroadcast++;
-			priv->stats.txbytesbroadcast += pstx_fb->pkt_length;
-		}
-		else
-		{
-			priv->stats.txunicast++;
+		if (pstx_fb->pkt_type != PACKET_MULTICAST &&
+		    pstx_fb->pkt_type != PACKET_BROADCAST) {
 			priv->stats.txbytesunicast += pstx_fb->pkt_length;
 		}
 	}
-	else
-	{
-		priv->stats.txfeedbackfail++;
-		priv->stats.txerrtotal++;
-		priv->stats.txerrbytestotal += pstx_fb->pkt_length;
-
-		/* We can not make sure broadcast/multicast or unicast mode. */
-		if (pstx_fb->pkt_type == PACKET_MULTICAST)
-		{
-			priv->stats.txerrmulticast++;
-		}
-		else if (pstx_fb->pkt_type == PACKET_BROADCAST)
-		{
-			priv->stats.txerrbroadcast++;
-		}
-		else
-		{
-			priv->stats.txerrunicast++;
-		}
-	}
-
-	priv->stats.txretrycount += pstx_fb->retry_cnt;
-	priv->stats.txfeedbackretry += pstx_fb->retry_cnt;
-
 }
 
 
@@ -217,65 +156,15 @@ cmpk_count_txstatistic(
  * refer to chapter "TX Feedback Element". We have to read 20 bytes
  * in the command packet.
  */
-static void
-cmpk_handle_tx_feedback(
-	struct net_device *dev,
-	u8	*	pmsg)
+static void cmpk_handle_tx_feedback(struct r8192_priv *priv, u8 *pmsg)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	cmpk_txfb_t		rx_tx_fb;	/* */
 
 	priv->stats.txfeedback++;
 
-	/* 0. Display received message. */
-	//cmpk_Display_Message(CMPK_RX_TX_FB_SIZE, pMsg);
-
-	/* 1. Extract TX feedback info from RFD to temp structure buffer. */
-	/* It seems that FW use big endian(MIPS) and DRV use little endian in
-	   windows OS. So we have to read the content byte by byte or transfer
-	   endian type before copy the message copy. */
-#if 0		// The TX FEEDBACK packet element address
-	//rx_tx_fb.Element_ID 	= pMsg[0];
-	//rx_tx_fb.Length 		= pMsg[1];
-	rx_tx_fb.TOK 			= pMsg[2]>>7;
-	rx_tx_fb.Fail_Reason 	= (pMsg[2] & 0x70) >> 4;
-	rx_tx_fb.TID 			= (pMsg[2] & 0x0F);
-	rx_tx_fb.Qos_Pkt 		= pMsg[3] >> 7;
-	rx_tx_fb.Bandwidth 		= (pMsg[3] & 0x40) >> 6;
-	rx_tx_fb.Retry_Cnt 		= pMsg[5];
-	rx_tx_fb.Pkt_ID 		= (pMsg[6] << 8) | pMsg[7];
-	rx_tx_fb.Seq_Num 		= (pMsg[8] << 8) | pMsg[9];
-	rx_tx_fb.S_Rate 		= pMsg[10];
-	rx_tx_fb.F_Rate 		= pMsg[11];
-	rx_tx_fb.S_RTS_Rate 	= pMsg[12];
-	rx_tx_fb.F_RTS_Rate 	= pMsg[13];
-	rx_tx_fb.pkt_length	= (pMsg[14] << 8) | pMsg[15];
-#endif
-	/* 2007/07/05 MH Use pointer to transfer structure memory. */
-	//memcpy((UINT8 *)&rx_tx_fb, pMsg, sizeof(CMPK_TXFB_T));
 	memcpy((u8*)&rx_tx_fb, pmsg, sizeof(cmpk_txfb_t));
-	/* 2. Use tx feedback info to count TX statistics. */
-	cmpk_count_txstatistic(dev, &rx_tx_fb);
-#if 0
-	/* 2007/07/11 MH Assign current operate rate.  */
-	if (pAdapter->RegWirelessMode == WIRELESS_MODE_A ||
-		pAdapter->RegWirelessMode == WIRELESS_MODE_B ||
-		pAdapter->RegWirelessMode == WIRELESS_MODE_G)
-	{
-		pMgntInfo->CurrentOperaRate = (rx_tx_fb.F_Rate & 0x7F);
-	}
-	else if (pAdapter->RegWirelessMode == WIRELESS_MODE_N_24G ||
-		 	 pAdapter->RegWirelessMode == WIRELESS_MODE_N_5G)
-	{
-		pMgntInfo->HTCurrentOperaRate = (rx_tx_fb.F_Rate & 0x8F);
-	}
-#endif
-	/* 2007/01/17 MH Comment previous method for TX statistic function. */
-	/* Collect info TX feedback packet to fill TCB. */
-	/* We can not know the packet length and transmit type: broadcast or uni
-	   or multicast. */
-	//CountTxStatistics( pAdapter, &tcb );
-
+	/* Use tx feedback info to count TX statistics. */
+	cmpk_count_txstatistic(priv, &rx_tx_fb);
 }
 
 
@@ -285,19 +174,12 @@ cmpk_handle_tx_feedback(
  * ws-07-0063-v06-rtl819x-command-packet-specification-070315.doc.
  * Please refer to chapter "Interrupt Status Element".
  */
-static	void
-cmpk_handle_interrupt_status(
-	struct net_device *dev,
-	u8*	pmsg)
+static void cmpk_handle_interrupt_status(struct r8192_priv *priv, u8 *pmsg)
 {
 	cmpk_intr_sta_t		rx_intr_status;	/* */
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 	DMESG("---> cmpk_Handle_Interrupt_Status()\n");
 
-	/* 0. Display received message. */
-	//cmpk_Display_Message(CMPK_RX_BEACON_STATE_SIZE, pMsg);
-
 	/* 1. Extract TX feedback info from RFD to temp structure buffer. */
 	/* It seems that FW use big endian(MIPS) and DRV use little endian in
 	   windows OS. So we have to read the content byte by byte or transfer
@@ -347,10 +229,7 @@ cmpk_handle_interrupt_status(
  * ws-06-0063-rtl8190-command-packet-specification. Please
  * refer to chapter "Beacon State Element".
  */
-static	void
-cmpk_handle_query_config_rx(
-	struct net_device *dev,
-	u8*	   pmsg)
+static void cmpk_handle_query_config_rx(struct r8192_priv *priv, u8 *pmsg)
 {
 	cmpk_query_cfg_t	rx_query_cfg;	/* */
 
@@ -380,10 +259,8 @@ cmpk_handle_query_config_rx(
  * Count aggregated tx status from firmwar of one type rx command
  * packet element id = RX_TX_STATUS.
  */
-static	void	cmpk_count_tx_status(	struct net_device *dev,
-									cmpk_tx_status_t 	*pstx_status)
+static void cmpk_count_tx_status(struct r8192_priv *priv, cmpk_tx_status_t *pstx_status)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 
 #ifdef ENABLE_PS
 
@@ -403,29 +280,7 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
 	priv->stats.txfeedbackok	+= pstx_status->txok;
 	priv->stats.txoktotal		+= pstx_status->txok;
 
-	priv->stats.txfeedbackfail	+= pstx_status->txfail;
-	priv->stats.txerrtotal		+= pstx_status->txfail;
-
-	priv->stats.txretrycount		+= pstx_status->txretry;
-	priv->stats.txfeedbackretry	+= pstx_status->txretry;
-
-	//pAdapter->TxStats.NumTxOkBytesTotal += psTx_FB->pkt_length;
-	//pAdapter->TxStats.NumTxErrBytesTotal += psTx_FB->pkt_length;
-	//pAdapter->MgntInfo.LinkDetectInfo.NumTxOkInPeriod++;
-
-	priv->stats.txmulticast	+= pstx_status->txmcok;
-	priv->stats.txbroadcast	+= pstx_status->txbcok;
-	priv->stats.txunicast		+= pstx_status->txucok;
-
-	priv->stats.txerrmulticast	+= pstx_status->txmcfail;
-	priv->stats.txerrbroadcast	+= pstx_status->txbcfail;
-	priv->stats.txerrunicast	+= pstx_status->txucfail;
-
-	priv->stats.txbytesmulticast	+= pstx_status->txmclength;
-	priv->stats.txbytesbroadcast	+= pstx_status->txbclength;
 	priv->stats.txbytesunicast		+= pstx_status->txuclength;
-
-	priv->stats.last_packet_rate		= pstx_status->rate;
 }
 
 
@@ -434,33 +289,23 @@ static	void	cmpk_count_tx_status(	struct net_device *dev,
  * Firmware add a new tx feedback status to reduce rx command
  * packet buffer operation load.
  */
-static	void
-cmpk_handle_tx_status(
-	struct net_device *dev,
-	u8*	   pmsg)
+static void cmpk_handle_tx_status(struct r8192_priv *priv, u8 *pmsg)
 {
 	cmpk_tx_status_t	rx_tx_sts;	/* */
 
 	memcpy((void*)&rx_tx_sts, (void*)pmsg, sizeof(cmpk_tx_status_t));
 	/* 2. Use tx feedback info to count TX statistics. */
-	cmpk_count_tx_status(dev, &rx_tx_sts);
+	cmpk_count_tx_status(priv, &rx_tx_sts);
 
 }
 
 
 /* Firmware add a new tx rate history */
-static	void
-cmpk_handle_tx_rate_history(
-	struct net_device *dev,
-	u8*	   pmsg)
+static void cmpk_handle_tx_rate_history(struct r8192_priv *priv, u8 *pmsg)
 {
-	cmpk_tx_rahis_t	*ptxrate;
-//	RT_RF_POWER_STATE	rtState;
-	u8				i, j;
+	u8				i;
 	u16				length = sizeof(cmpk_tx_rahis_t);
 	u32				*ptemp;
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 
 #ifdef ENABLE_PS
 	pAdapter->HalFunc.GetHwRegHandler(pAdapter, HW_VAR_RF_STATE, (pu1Byte)(&rtState));
@@ -488,28 +333,6 @@ cmpk_handle_tx_rate_history(
 		temp2 = ptemp[i]>>16;
 		ptemp[i] = (temp1<<16)|temp2;
 	}
-
-	ptxrate = (cmpk_tx_rahis_t *)pmsg;
-
-	if (ptxrate == NULL )
-	{
-		return;
-	}
-
-	for (i = 0; i < 16; i++)
-	{
-		// Collect CCK rate packet num
-		if (i < 4)
-			priv->stats.txrate.cck[i] += ptxrate->cck[i];
-
-		// Collect OFDM rate packet num
-		if (i< 8)
-			priv->stats.txrate.ofdm[i] += ptxrate->ofdm[i];
-
-		for (j = 0; j < 4; j++)
-			priv->stats.txrate.ht_mcs[j][i] += ptxrate->ht_mcs[j][i];
-	}
-
 }
 
 
@@ -520,10 +343,9 @@ cmpk_handle_tx_rate_history(
  * command packet now. Please refer to document
  * ws-06-0063-rtl8190-command-packet-specification.
  */
-u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *pstats)
+u32 cmpk_message_handle_rx(struct r8192_priv *priv, struct ieee80211_rx_stats *pstats)
 {
 //	u32			debug_level = DBG_LOUD;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	int			total_length;
 	u8			cmd_length, exe_cnt = 0;
 	u8			element_id;
@@ -566,28 +388,28 @@ u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *ps
 			case RX_TX_FEEDBACK:
 
         			RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_FEEDBACK\n");
-				cmpk_handle_tx_feedback (dev, pcmd_buff);
+				cmpk_handle_tx_feedback(priv, pcmd_buff);
 				cmd_length = CMPK_RX_TX_FB_SIZE;
 				break;
 
 			case RX_INTERRUPT_STATUS:
 
 			        RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_INTERRUPT_STATUS\n");
-				cmpk_handle_interrupt_status(dev, pcmd_buff);
+				cmpk_handle_interrupt_status(priv, pcmd_buff);
 				cmd_length = sizeof(cmpk_intr_sta_t);
 				break;
 
 			case BOTH_QUERY_CONFIG:
 
 			        RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():BOTH_QUERY_CONFIG\n");
-				cmpk_handle_query_config_rx(dev, pcmd_buff);
+				cmpk_handle_query_config_rx(priv, pcmd_buff);
 				cmd_length = CMPK_BOTH_QUERY_CONFIG_SIZE;
 				break;
 
 			case RX_TX_STATUS:
 
 			        RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_STATUS\n");
-				cmpk_handle_tx_status(dev, pcmd_buff);
+				cmpk_handle_tx_status(priv, pcmd_buff);
 				cmd_length = CMPK_RX_TX_STS_SIZE;
 				break;
 
@@ -603,7 +425,7 @@ u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *ps
 				//DbgPrint(" rx tx rate history\r\n");
 
 			        RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():RX_TX_HISTORY\n");
-				cmpk_handle_tx_rate_history(dev, pcmd_buff);
+				cmpk_handle_tx_rate_history(priv, pcmd_buff);
 				cmd_length = CMPK_TX_RAHIS_SIZE;
 				break;
 
@@ -612,14 +434,6 @@ u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats *ps
 			        RT_TRACE(COMP_EVENTS, "---->cmpk_message_handle_rx():unknown CMD Element\n");
 				return 1;	/* This is a command packet. */
 		}
-		// 2007/01/22 MH Display received rx command packet info.
-		//cmpk_Display_Message(cmd_length, pcmd_buff);
-
-		// 2007/01/22 MH Add to display tx statistic.
-		//cmpk_DisplayTxStatistic(pAdapter);
-
-		/* 2007/03/09 MH Collect sidderent cmd element pkt num. */
-		priv->stats.rxcmdpkt[element_id]++;
 
 		total_length -= cmd_length;
 		pcmd_buff    += cmd_length;
diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.h b/drivers/staging/rtl8192e/r819xE_cmdpkt.h
index 8d705ce..312e4f8 100644
--- a/drivers/staging/rtl8192e/r819xE_cmdpkt.h
+++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.h
@@ -201,7 +201,7 @@ typedef enum tag_command_packet_directories
     RX_CMD_ELE_MAX
 }cmpk_element_e;
 
-u32 cmpk_message_handle_rx(struct net_device *dev, struct ieee80211_rx_stats * pstats);
+u32 cmpk_message_handle_rx(struct r8192_priv *priv, struct ieee80211_rx_stats *pstats);
 
 
 #endif
diff --git a/drivers/staging/rtl8192e/r819xE_firmware.c b/drivers/staging/rtl8192e/r819xE_firmware.c
index 5c3da46..d9e8b5a 100644
--- a/drivers/staging/rtl8192e/r819xE_firmware.c
+++ b/drivers/staging/rtl8192e/r819xE_firmware.c
@@ -25,9 +25,8 @@ enum opt_rst_type {
 	OPT_FIRMWARE_RESET = 1,
 };
 
-void firmware_init_param(struct net_device *dev)
+void firmware_init_param(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	rt_firmware *pfirmware = priv->pFirmware;
 
 	pfirmware->cmdpacket_frag_thresold =
@@ -37,10 +36,9 @@ void firmware_init_param(struct net_device *dev)
 /*
  * segment the img and use the ptr and length to remember info on each segment
  */
-static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
+static bool fw_download_code(struct r8192_priv *priv, u8 *code_virtual_address,
 			     u32 buffer_len)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	bool rt_status = true;
 	u16 frag_threshold;
 	u16 frag_length, frag_offset = 0;
@@ -52,7 +50,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 	cb_desc *tcb_desc;
 	u8 bLastIniPkt;
 
-	firmware_init_param(dev);
+	firmware_init_param(priv);
 
 	/* Fragmentation might be required */
 	frag_threshold = pfirmware->cmdpacket_frag_thresold;
@@ -70,7 +68,6 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 		 * descriptor info add 4 to avoid packet appending overflow.
 		 */
 		skb  = dev_alloc_skb(frag_length + 4);
-		memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
 		tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
 		tcb_desc->queue_index = TXCMD_QUEUE;
 		tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
@@ -96,7 +93,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
 		}
 		tcb_desc->txbuf_size = (u16)i;
 		skb_put(skb, i);
-		priv->ieee80211->softmac_hard_start_xmit(skb, dev);
+		priv->ieee80211->softmac_hard_start_xmit(skb, priv->ieee80211);
 
 		code_virtual_address += frag_length;
 		frag_offset += frag_length;
@@ -113,7 +110,7 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
  * register.  Switch to CPU register in the begin and switch
  * back before return
  */
-static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
+static bool CPUcheck_maincodeok_turnonCPU(struct r8192_priv *priv)
 {
 	unsigned long timeout;
 	bool rt_status = true;
@@ -122,7 +119,7 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 	/* Check whether put code OK */
 	timeout = jiffies + msecs_to_jiffies(20);
 	while (time_before(jiffies, timeout)) {
-		CPU_status = read_nic_dword(dev, CPU_GEN);
+		CPU_status = read_nic_dword(priv, CPU_GEN);
 
 		if (CPU_status & CPU_GEN_PUT_CODE_OK)
 			break;
@@ -137,15 +134,15 @@ static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
 	}
 
 	/* Turn On CPU */
-	CPU_status = read_nic_dword(dev, CPU_GEN);
-	write_nic_byte(dev, CPU_GEN,
+	CPU_status = read_nic_dword(priv, CPU_GEN);
+	write_nic_byte(priv, CPU_GEN,
 		       (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
 	mdelay(1);
 
 	/* Check whether CPU boot OK */
 	timeout = jiffies + msecs_to_jiffies(20);
 	while (time_before(jiffies, timeout)) {
-		CPU_status = read_nic_dword(dev, CPU_GEN);
+		CPU_status = read_nic_dword(priv, CPU_GEN);
 
 		if (CPU_status & CPU_GEN_BOOT_RDY)
 			break;
@@ -165,7 +162,7 @@ CPUCheckMainCodeOKAndTurnOnCPU_Fail:
 	return rt_status;
 }
 
-static bool CPUcheck_firmware_ready(struct net_device *dev)
+static bool CPUcheck_firmware_ready(struct r8192_priv *priv)
 {
 	unsigned long timeout;
 	bool rt_status = true;
@@ -174,7 +171,7 @@ static bool CPUcheck_firmware_ready(struct net_device *dev)
 	/* Check Firmware Ready */
 	timeout = jiffies + msecs_to_jiffies(20);
 	while (time_before(jiffies, timeout)) {
-		CPU_status = read_nic_dword(dev, CPU_GEN);
+		CPU_status = read_nic_dword(priv, CPU_GEN);
 
 		if (CPU_status & CPU_GEN_FIRM_RDY)
 			break;
@@ -195,9 +192,8 @@ CPUCheckFirmwareReady_Fail:
 
 }
 
-bool init_firmware(struct net_device *dev)
+bool init_firmware(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	bool rt_status = true;
 	u32 file_length = 0;
 	u8 *mapped_file = NULL;
@@ -287,7 +283,7 @@ bool init_firmware(struct net_device *dev)
 		 * 3. each skb_buff packet data content will already include
 		 *    the firmware info and Tx descriptor info
 		 */
-		rt_status = fw_download_code(dev, mapped_file, file_length);
+		rt_status = fw_download_code(priv, mapped_file, file_length);
 		if (rt_status != TRUE)
 			goto download_firmware_fail;
 
@@ -312,7 +308,7 @@ bool init_firmware(struct net_device *dev)
 			pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
 
 			/* Check Put Code OK and Turn On CPU */
-			rt_status = CPUcheck_maincodeok_turnonCPU(dev);
+			rt_status = CPUcheck_maincodeok_turnonCPU(priv);
 			if (rt_status != TRUE) {
 				RT_TRACE(COMP_FIRMWARE,
 					"CPUcheck_maincodeok_turnonCPU fail!\n");
@@ -327,7 +323,7 @@ bool init_firmware(struct net_device *dev)
 			pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
 			mdelay(1);
 
-			rt_status = CPUcheck_firmware_ready(dev);
+			rt_status = CPUcheck_firmware_ready(priv);
 			if (rt_status != TRUE) {
 				RT_TRACE(COMP_FIRMWARE,
 					"CPUcheck_firmware_ready fail(%d)!\n",
@@ -345,7 +341,7 @@ bool init_firmware(struct net_device *dev)
 	return rt_status;
 
 download_firmware_fail:
-	RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
+	RT_TRACE(COMP_ERR, "ERR in %s() step %d\n", __func__, init_step);
 	rt_status = false;
 	return rt_status;
 }
diff --git a/drivers/staging/rtl8192e/r819xE_phy.c b/drivers/staging/rtl8192e/r819xE_phy.c
index 50cd0e5..dfa4e11 100644
--- a/drivers/staging/rtl8192e/r819xE_phy.c
+++ b/drivers/staging/rtl8192e/r819xE_phy.c
@@ -24,839 +24,7 @@ static const u32 RF_CHANNEL_TABLE_ZEBRA[] = {
 	0x0e5c, //2472 13
 	0x0f72, //2484
 };
-#ifdef RTL8190P
-u32 Rtl8190PciMACPHY_Array[] = {
-0x03c,0xffff0000,0x00000f0f,
-0x340,0xffffffff,0x161a1a1a,
-0x344,0xffffffff,0x12121416,
-0x348,0x0000ffff,0x00001818,
-0x12c,0xffffffff,0x04000802,
-0x318,0x00000fff,0x00000800,
-};
-u32 Rtl8190PciMACPHY_Array_PG[] = {
-0x03c,0xffff0000,0x00000f0f,
-0x340,0xffffffff,0x0a0c0d0f,
-0x344,0xffffffff,0x06070809,
-0x344,0xffffffff,0x06070809,
-0x348,0x0000ffff,0x00000000,
-0x12c,0xffffffff,0x04000802,
-0x318,0x00000fff,0x00000800,
-};
-
-u32 Rtl8190PciAGCTAB_Array[AGCTAB_ArrayLength] = {
-0xc78,0x7d000001,
-0xc78,0x7d010001,
-0xc78,0x7d020001,
-0xc78,0x7d030001,
-0xc78,0x7c040001,
-0xc78,0x7b050001,
-0xc78,0x7a060001,
-0xc78,0x79070001,
-0xc78,0x78080001,
-0xc78,0x77090001,
-0xc78,0x760a0001,
-0xc78,0x750b0001,
-0xc78,0x740c0001,
-0xc78,0x730d0001,
-0xc78,0x720e0001,
-0xc78,0x710f0001,
-0xc78,0x70100001,
-0xc78,0x6f110001,
-0xc78,0x6e120001,
-0xc78,0x6d130001,
-0xc78,0x6c140001,
-0xc78,0x6b150001,
-0xc78,0x6a160001,
-0xc78,0x69170001,
-0xc78,0x68180001,
-0xc78,0x67190001,
-0xc78,0x661a0001,
-0xc78,0x651b0001,
-0xc78,0x641c0001,
-0xc78,0x491d0001,
-0xc78,0x481e0001,
-0xc78,0x471f0001,
-0xc78,0x46200001,
-0xc78,0x45210001,
-0xc78,0x44220001,
-0xc78,0x43230001,
-0xc78,0x28240001,
-0xc78,0x27250001,
-0xc78,0x26260001,
-0xc78,0x25270001,
-0xc78,0x24280001,
-0xc78,0x23290001,
-0xc78,0x222a0001,
-0xc78,0x212b0001,
-0xc78,0x202c0001,
-0xc78,0x0a2d0001,
-0xc78,0x082e0001,
-0xc78,0x062f0001,
-0xc78,0x05300001,
-0xc78,0x04310001,
-0xc78,0x03320001,
-0xc78,0x02330001,
-0xc78,0x01340001,
-0xc78,0x00350001,
-0xc78,0x00360001,
-0xc78,0x00370001,
-0xc78,0x00380001,
-0xc78,0x00390001,
-0xc78,0x003a0001,
-0xc78,0x003b0001,
-0xc78,0x003c0001,
-0xc78,0x003d0001,
-0xc78,0x003e0001,
-0xc78,0x003f0001,
-0xc78,0x7d400001,
-0xc78,0x7d410001,
-0xc78,0x7d420001,
-0xc78,0x7d430001,
-0xc78,0x7c440001,
-0xc78,0x7b450001,
-0xc78,0x7a460001,
-0xc78,0x79470001,
-0xc78,0x78480001,
-0xc78,0x77490001,
-0xc78,0x764a0001,
-0xc78,0x754b0001,
-0xc78,0x744c0001,
-0xc78,0x734d0001,
-0xc78,0x724e0001,
-0xc78,0x714f0001,
-0xc78,0x70500001,
-0xc78,0x6f510001,
-0xc78,0x6e520001,
-0xc78,0x6d530001,
-0xc78,0x6c540001,
-0xc78,0x6b550001,
-0xc78,0x6a560001,
-0xc78,0x69570001,
-0xc78,0x68580001,
-0xc78,0x67590001,
-0xc78,0x665a0001,
-0xc78,0x655b0001,
-0xc78,0x645c0001,
-0xc78,0x495d0001,
-0xc78,0x485e0001,
-0xc78,0x475f0001,
-0xc78,0x46600001,
-0xc78,0x45610001,
-0xc78,0x44620001,
-0xc78,0x43630001,
-0xc78,0x28640001,
-0xc78,0x27650001,
-0xc78,0x26660001,
-0xc78,0x25670001,
-0xc78,0x24680001,
-0xc78,0x23690001,
-0xc78,0x226a0001,
-0xc78,0x216b0001,
-0xc78,0x206c0001,
-0xc78,0x0a6d0001,
-0xc78,0x086e0001,
-0xc78,0x066f0001,
-0xc78,0x05700001,
-0xc78,0x04710001,
-0xc78,0x03720001,
-0xc78,0x02730001,
-0xc78,0x01740001,
-0xc78,0x00750001,
-0xc78,0x00760001,
-0xc78,0x00770001,
-0xc78,0x00780001,
-0xc78,0x00790001,
-0xc78,0x007a0001,
-0xc78,0x007b0001,
-0xc78,0x007c0001,
-0xc78,0x007d0001,
-0xc78,0x007e0001,
-0xc78,0x007f0001,
-0xc78,0x3600001e,
-0xc78,0x3601001e,
-0xc78,0x3602001e,
-0xc78,0x3603001e,
-0xc78,0x3604001e,
-0xc78,0x3605001e,
-0xc78,0x3a06001e,
-0xc78,0x3c07001e,
-0xc78,0x3e08001e,
-0xc78,0x4209001e,
-0xc78,0x430a001e,
-0xc78,0x450b001e,
-0xc78,0x470c001e,
-0xc78,0x480d001e,
-0xc78,0x490e001e,
-0xc78,0x4b0f001e,
-0xc78,0x4c10001e,
-0xc78,0x4d11001e,
-0xc78,0x4d12001e,
-0xc78,0x4e13001e,
-0xc78,0x4f14001e,
-0xc78,0x5015001e,
-0xc78,0x5116001e,
-0xc78,0x5117001e,
-0xc78,0x5218001e,
-0xc78,0x5219001e,
-0xc78,0x531a001e,
-0xc78,0x541b001e,
-0xc78,0x541c001e,
-0xc78,0x551d001e,
-0xc78,0x561e001e,
-0xc78,0x561f001e,
-0xc78,0x5720001e,
-0xc78,0x5821001e,
-0xc78,0x5822001e,
-0xc78,0x5923001e,
-0xc78,0x5924001e,
-0xc78,0x5a25001e,
-0xc78,0x5b26001e,
-0xc78,0x5b27001e,
-0xc78,0x5c28001e,
-0xc78,0x5c29001e,
-0xc78,0x5d2a001e,
-0xc78,0x5d2b001e,
-0xc78,0x5e2c001e,
-0xc78,0x5e2d001e,
-0xc78,0x5f2e001e,
-0xc78,0x602f001e,
-0xc78,0x6030001e,
-0xc78,0x6131001e,
-0xc78,0x6132001e,
-0xc78,0x6233001e,
-0xc78,0x6234001e,
-0xc78,0x6335001e,
-0xc78,0x6336001e,
-0xc78,0x6437001e,
-0xc78,0x6538001e,
-0xc78,0x6639001e,
-0xc78,0x663a001e,
-0xc78,0x673b001e,
-0xc78,0x683c001e,
-0xc78,0x693d001e,
-0xc78,0x6a3e001e,
-0xc78,0x6b3f001e,
-};
-
-u32 Rtl8190PciPHY_REGArray[PHY_REGArrayLength] = {
-0x800,0x00050060,
-0x804,0x00000005,
-0x808,0x0000fc00,
-0x80c,0x0000001c,
-0x810,0x801010aa,
-0x814,0x000908c0,
-0x818,0x00000000,
-0x81c,0x00000000,
-0x820,0x00000004,
-0x824,0x00690000,
-0x828,0x00000004,
-0x82c,0x00e90000,
-0x830,0x00000004,
-0x834,0x00690000,
-0x838,0x00000004,
-0x83c,0x00e90000,
-0x840,0x00000000,
-0x844,0x00000000,
-0x848,0x00000000,
-0x84c,0x00000000,
-0x850,0x00000000,
-0x854,0x00000000,
-0x858,0x65a965a9,
-0x85c,0x65a965a9,
-0x860,0x001f0010,
-0x864,0x007f0010,
-0x868,0x001f0010,
-0x86c,0x007f0010,
-0x870,0x0f100f70,
-0x874,0x0f100f70,
-0x878,0x00000000,
-0x87c,0x00000000,
-0x880,0x5c385eb8,
-0x884,0x6357060d,
-0x888,0x0460c341,
-0x88c,0x0000ff00,
-0x890,0x00000000,
-0x894,0xfffffffe,
-0x898,0x4c42382f,
-0x89c,0x00656056,
-0x8b0,0x00000000,
-0x8e0,0x00000000,
-0x8e4,0x00000000,
-0x900,0x00000000,
-0x904,0x00000023,
-0x908,0x00000000,
-0x90c,0x35541545,
-0xa00,0x00d0c7d8,
-0xa04,0xab1f0008,
-0xa08,0x80cd8300,
-0xa0c,0x2e62740f,
-0xa10,0x95009b78,
-0xa14,0x11145008,
-0xa18,0x00881117,
-0xa1c,0x89140fa0,
-0xa20,0x1a1b0000,
-0xa24,0x090e1317,
-0xa28,0x00000204,
-0xa2c,0x00000000,
-0xc00,0x00000040,
-0xc04,0x0000500f,
-0xc08,0x000000e4,
-0xc0c,0x6c6c6c6c,
-0xc10,0x08000000,
-0xc14,0x40000100,
-0xc18,0x08000000,
-0xc1c,0x40000100,
-0xc20,0x08000000,
-0xc24,0x40000100,
-0xc28,0x08000000,
-0xc2c,0x40000100,
-0xc30,0x6de9ac44,
-0xc34,0x164052cd,
-0xc38,0x00070a14,
-0xc3c,0x0a969764,
-0xc40,0x1f7c403f,
-0xc44,0x000100b7,
-0xc48,0xec020000,
-0xc4c,0x00000300,
-0xc50,0x69543420,
-0xc54,0x433c0094,
-0xc58,0x69543420,
-0xc5c,0x433c0094,
-0xc60,0x69543420,
-0xc64,0x433c0094,
-0xc68,0x69543420,
-0xc6c,0x433c0094,
-0xc70,0x2c7f000d,
-0xc74,0x0186175b,
-0xc78,0x0000001f,
-0xc7c,0x00b91612,
-0xc80,0x40000100,
-0xc84,0x00000000,
-0xc88,0x40000100,
-0xc8c,0x08000000,
-0xc90,0x40000100,
-0xc94,0x00000000,
-0xc98,0x40000100,
-0xc9c,0x00000000,
-0xca0,0x00492492,
-0xca4,0x00000000,
-0xca8,0x00000000,
-0xcac,0x00000000,
-0xcb0,0x00000000,
-0xcb4,0x00000000,
-0xcb8,0x00000000,
-0xcbc,0x00492492,
-0xcc0,0x00000000,
-0xcc4,0x00000000,
-0xcc8,0x00000000,
-0xccc,0x00000000,
-0xcd0,0x00000000,
-0xcd4,0x00000000,
-0xcd8,0x64b22427,
-0xcdc,0x00766932,
-0xce0,0x00222222,
-0xd00,0x00000740,
-0xd04,0x0000040f,
-0xd08,0x0000803f,
-0xd0c,0x00000001,
-0xd10,0xa0633333,
-0xd14,0x33333c63,
-0xd18,0x6a8f5b6b,
-0xd1c,0x00000000,
-0xd20,0x00000000,
-0xd24,0x00000000,
-0xd28,0x00000000,
-0xd2c,0xcc979975,
-0xd30,0x00000000,
-0xd34,0x00000000,
-0xd38,0x00000000,
-0xd3c,0x00027293,
-0xd40,0x00000000,
-0xd44,0x00000000,
-0xd48,0x00000000,
-0xd4c,0x00000000,
-0xd50,0x6437140a,
-0xd54,0x024dbd02,
-0xd58,0x00000000,
-0xd5c,0x14032064,
-};
-u32 Rtl8190PciPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = {
-0x800,0x00050060,
-0x804,0x00000004,
-0x808,0x0000fc00,
-0x80c,0x0000001c,
-0x810,0x801010aa,
-0x814,0x000908c0,
-0x818,0x00000000,
-0x81c,0x00000000,
-0x820,0x00000004,
-0x824,0x00690000,
-0x828,0x00000004,
-0x82c,0x00e90000,
-0x830,0x00000004,
-0x834,0x00690000,
-0x838,0x00000004,
-0x83c,0x00e90000,
-0x840,0x00000000,
-0x844,0x00000000,
-0x848,0x00000000,
-0x84c,0x00000000,
-0x850,0x00000000,
-0x854,0x00000000,
-0x858,0x65a965a9,
-0x85c,0x65a965a9,
-0x860,0x001f0000,
-0x864,0x007f0000,
-0x868,0x001f0010,
-0x86c,0x007f0010,
-0x870,0x0f100f70,
-0x874,0x0f100f70,
-0x878,0x00000000,
-0x87c,0x00000000,
-0x880,0x5c385898,
-0x884,0x6357060d,
-0x888,0x0460c341,
-0x88c,0x0000fc00,
-0x890,0x00000000,
-0x894,0xfffffffe,
-0x898,0x4c42382f,
-0x89c,0x00656056,
-0x8b0,0x00000000,
-0x8e0,0x00000000,
-0x8e4,0x00000000,
-0x900,0x00000000,
-0x904,0x00000023,
-0x908,0x00000000,
-0x90c,0x34441444,
-0xa00,0x00d0c7d8,
-0xa04,0x2b1f0008,
-0xa08,0x80cd8300,
-0xa0c,0x2e62740f,
-0xa10,0x95009b78,
-0xa14,0x11145008,
-0xa18,0x00881117,
-0xa1c,0x89140fa0,
-0xa20,0x1a1b0000,
-0xa24,0x090e1317,
-0xa28,0x00000204,
-0xa2c,0x00000000,
-0xc00,0x00000040,
-0xc04,0x0000500c,
-0xc08,0x000000e4,
-0xc0c,0x6c6c6c6c,
-0xc10,0x08000000,
-0xc14,0x40000100,
-0xc18,0x08000000,
-0xc1c,0x40000100,
-0xc20,0x08000000,
-0xc24,0x40000100,
-0xc28,0x08000000,
-0xc2c,0x40000100,
-0xc30,0x6de9ac44,
-0xc34,0x164052cd,
-0xc38,0x00070a14,
-0xc3c,0x0a969764,
-0xc40,0x1f7c403f,
-0xc44,0x000100b7,
-0xc48,0xec020000,
-0xc4c,0x00000300,
-0xc50,0x69543420,
-0xc54,0x433c0094,
-0xc58,0x69543420,
-0xc5c,0x433c0094,
-0xc60,0x69543420,
-0xc64,0x433c0094,
-0xc68,0x69543420,
-0xc6c,0x433c0094,
-0xc70,0x2c7f000d,
-0xc74,0x0186175b,
-0xc78,0x0000001f,
-0xc7c,0x00b91612,
-0xc80,0x40000100,
-0xc84,0x00000000,
-0xc88,0x40000100,
-0xc8c,0x08000000,
-0xc90,0x40000100,
-0xc94,0x00000000,
-0xc98,0x40000100,
-0xc9c,0x00000000,
-0xca0,0x00492492,
-0xca4,0x00000000,
-0xca8,0x00000000,
-0xcac,0x00000000,
-0xcb0,0x00000000,
-0xcb4,0x00000000,
-0xcb8,0x00000000,
-0xcbc,0x00492492,
-0xcc0,0x00000000,
-0xcc4,0x00000000,
-0xcc8,0x00000000,
-0xccc,0x00000000,
-0xcd0,0x00000000,
-0xcd4,0x00000000,
-0xcd8,0x64b22427,
-0xcdc,0x00766932,
-0xce0,0x00222222,
-0xd00,0x00000740,
-0xd04,0x0000040c,
-0xd08,0x0000803f,
-0xd0c,0x00000001,
-0xd10,0xa0633333,
-0xd14,0x33333c63,
-0xd18,0x6a8f5b6b,
-0xd1c,0x00000000,
-0xd20,0x00000000,
-0xd24,0x00000000,
-0xd28,0x00000000,
-0xd2c,0xcc979975,
-0xd30,0x00000000,
-0xd34,0x00000000,
-0xd38,0x00000000,
-0xd3c,0x00027293,
-0xd40,0x00000000,
-0xd44,0x00000000,
-0xd48,0x00000000,
-0xd4c,0x00000000,
-0xd50,0x6437140a,
-0xd54,0x024dbd02,
-0xd58,0x00000000,
-0xd5c,0x14032064,
-};
-
-u32 Rtl8190PciRadioA_Array[RadioA_ArrayLength] = {
-0x019,0x00000003,
-0x000,0x000000bf,
-0x001,0x00000ee0,
-0x002,0x0000004c,
-0x003,0x000007f1,
-0x004,0x00000975,
-0x005,0x00000c58,
-0x006,0x00000ae6,
-0x007,0x000000ca,
-0x008,0x00000e1c,
-0x009,0x000007f0,
-0x00a,0x000009d0,
-0x00b,0x000001ba,
-0x00c,0x00000240,
-0x00e,0x00000020,
-0x00f,0x00000990,
-0x012,0x00000806,
-0x014,0x000005ab,
-0x015,0x00000f80,
-0x016,0x00000020,
-0x017,0x00000597,
-0x018,0x0000050a,
-0x01a,0x00000f80,
-0x01b,0x00000f5e,
-0x01c,0x00000008,
-0x01d,0x00000607,
-0x01e,0x000006cc,
-0x01f,0x00000000,
-0x020,0x000001a5,
-0x01f,0x00000001,
-0x020,0x00000165,
-0x01f,0x00000002,
-0x020,0x000000c6,
-0x01f,0x00000003,
-0x020,0x00000086,
-0x01f,0x00000004,
-0x020,0x00000046,
-0x01f,0x00000005,
-0x020,0x000001e6,
-0x01f,0x00000006,
-0x020,0x000001a6,
-0x01f,0x00000007,
-0x020,0x00000166,
-0x01f,0x00000008,
-0x020,0x000000c7,
-0x01f,0x00000009,
-0x020,0x00000087,
-0x01f,0x0000000a,
-0x020,0x000000f7,
-0x01f,0x0000000b,
-0x020,0x000000d7,
-0x01f,0x0000000c,
-0x020,0x000000b7,
-0x01f,0x0000000d,
-0x020,0x00000097,
-0x01f,0x0000000e,
-0x020,0x00000077,
-0x01f,0x0000000f,
-0x020,0x00000057,
-0x01f,0x00000010,
-0x020,0x00000037,
-0x01f,0x00000011,
-0x020,0x000000fb,
-0x01f,0x00000012,
-0x020,0x000000db,
-0x01f,0x00000013,
-0x020,0x000000bb,
-0x01f,0x00000014,
-0x020,0x000000ff,
-0x01f,0x00000015,
-0x020,0x000000e3,
-0x01f,0x00000016,
-0x020,0x000000c3,
-0x01f,0x00000017,
-0x020,0x000000a3,
-0x01f,0x00000018,
-0x020,0x00000083,
-0x01f,0x00000019,
-0x020,0x00000063,
-0x01f,0x0000001a,
-0x020,0x00000043,
-0x01f,0x0000001b,
-0x020,0x00000023,
-0x01f,0x0000001c,
-0x020,0x00000003,
-0x01f,0x0000001d,
-0x020,0x000001e3,
-0x01f,0x0000001e,
-0x020,0x000001c3,
-0x01f,0x0000001f,
-0x020,0x000001a3,
-0x01f,0x00000020,
-0x020,0x00000183,
-0x01f,0x00000021,
-0x020,0x00000163,
-0x01f,0x00000022,
-0x020,0x00000143,
-0x01f,0x00000023,
-0x020,0x00000123,
-0x01f,0x00000024,
-0x020,0x00000103,
-0x023,0x00000203,
-0x024,0x00000200,
-0x00b,0x000001ba,
-0x02c,0x000003d7,
-0x02d,0x00000ff0,
-0x000,0x00000037,
-0x004,0x00000160,
-0x007,0x00000080,
-0x002,0x0000088d,
-0x0fe,0x00000000,
-0x0fe,0x00000000,
-0x016,0x00000200,
-0x016,0x00000380,
-0x016,0x00000020,
-0x016,0x000001a0,
-0x000,0x000000bf,
-0x00d,0x0000001f,
-0x00d,0x00000c9f,
-0x002,0x0000004d,
-0x000,0x00000cbf,
-0x004,0x00000975,
-0x007,0x00000700,
-};
-u32 Rtl8190PciRadioB_Array[RadioB_ArrayLength] = {
-0x019,0x00000003,
-0x000,0x000000bf,
-0x001,0x000006e0,
-0x002,0x0000004c,
-0x003,0x000007f1,
-0x004,0x00000975,
-0x005,0x00000c58,
-0x006,0x00000ae6,
-0x007,0x000000ca,
-0x008,0x00000e1c,
-0x000,0x000000b7,
-0x00a,0x00000850,
-0x000,0x000000bf,
-0x00b,0x000001ba,
-0x00c,0x00000240,
-0x00e,0x00000020,
-0x015,0x00000f80,
-0x016,0x00000020,
-0x017,0x00000597,
-0x018,0x0000050a,
-0x01a,0x00000e00,
-0x01b,0x00000f5e,
-0x01d,0x00000607,
-0x01e,0x000006cc,
-0x00b,0x000001ba,
-0x023,0x00000203,
-0x024,0x00000200,
-0x000,0x00000037,
-0x004,0x00000160,
-0x016,0x00000200,
-0x016,0x00000380,
-0x016,0x00000020,
-0x016,0x000001a0,
-0x00d,0x00000ccc,
-0x000,0x000000bf,
-0x002,0x0000004d,
-0x000,0x00000cbf,
-0x004,0x00000975,
-0x007,0x00000700,
-};
-u32 Rtl8190PciRadioC_Array[RadioC_ArrayLength] = {
-0x019,0x00000003,
-0x000,0x000000bf,
-0x001,0x00000ee0,
-0x002,0x0000004c,
-0x003,0x000007f1,
-0x004,0x00000975,
-0x005,0x00000c58,
-0x006,0x00000ae6,
-0x007,0x000000ca,
-0x008,0x00000e1c,
-0x009,0x000007f0,
-0x00a,0x000009d0,
-0x00b,0x000001ba,
-0x00c,0x00000240,
-0x00e,0x00000020,
-0x00f,0x00000990,
-0x012,0x00000806,
-0x014,0x000005ab,
-0x015,0x00000f80,
-0x016,0x00000020,
-0x017,0x00000597,
-0x018,0x0000050a,
-0x01a,0x00000f80,
-0x01b,0x00000f5e,
-0x01c,0x00000008,
-0x01d,0x00000607,
-0x01e,0x000006cc,
-0x01f,0x00000000,
-0x020,0x000001a5,
-0x01f,0x00000001,
-0x020,0x00000165,
-0x01f,0x00000002,
-0x020,0x000000c6,
-0x01f,0x00000003,
-0x020,0x00000086,
-0x01f,0x00000004,
-0x020,0x00000046,
-0x01f,0x00000005,
-0x020,0x000001e6,
-0x01f,0x00000006,
-0x020,0x000001a6,
-0x01f,0x00000007,
-0x020,0x00000166,
-0x01f,0x00000008,
-0x020,0x000000c7,
-0x01f,0x00000009,
-0x020,0x00000087,
-0x01f,0x0000000a,
-0x020,0x000000f7,
-0x01f,0x0000000b,
-0x020,0x000000d7,
-0x01f,0x0000000c,
-0x020,0x000000b7,
-0x01f,0x0000000d,
-0x020,0x00000097,
-0x01f,0x0000000e,
-0x020,0x00000077,
-0x01f,0x0000000f,
-0x020,0x00000057,
-0x01f,0x00000010,
-0x020,0x00000037,
-0x01f,0x00000011,
-0x020,0x000000fb,
-0x01f,0x00000012,
-0x020,0x000000db,
-0x01f,0x00000013,
-0x020,0x000000bb,
-0x01f,0x00000014,
-0x020,0x000000ff,
-0x01f,0x00000015,
-0x020,0x000000e3,
-0x01f,0x00000016,
-0x020,0x000000c3,
-0x01f,0x00000017,
-0x020,0x000000a3,
-0x01f,0x00000018,
-0x020,0x00000083,
-0x01f,0x00000019,
-0x020,0x00000063,
-0x01f,0x0000001a,
-0x020,0x00000043,
-0x01f,0x0000001b,
-0x020,0x00000023,
-0x01f,0x0000001c,
-0x020,0x00000003,
-0x01f,0x0000001d,
-0x020,0x000001e3,
-0x01f,0x0000001e,
-0x020,0x000001c3,
-0x01f,0x0000001f,
-0x020,0x000001a3,
-0x01f,0x00000020,
-0x020,0x00000183,
-0x01f,0x00000021,
-0x020,0x00000163,
-0x01f,0x00000022,
-0x020,0x00000143,
-0x01f,0x00000023,
-0x020,0x00000123,
-0x01f,0x00000024,
-0x020,0x00000103,
-0x023,0x00000203,
-0x024,0x00000200,
-0x00b,0x000001ba,
-0x02c,0x000003d7,
-0x02d,0x00000ff0,
-0x000,0x00000037,
-0x004,0x00000160,
-0x007,0x00000080,
-0x002,0x0000088d,
-0x0fe,0x00000000,
-0x0fe,0x00000000,
-0x016,0x00000200,
-0x016,0x00000380,
-0x016,0x00000020,
-0x016,0x000001a0,
-0x000,0x000000bf,
-0x00d,0x0000001f,
-0x00d,0x00000c9f,
-0x002,0x0000004d,
-0x000,0x00000cbf,
-0x004,0x00000975,
-0x007,0x00000700,
-};
-u32 Rtl8190PciRadioD_Array[RadioD_ArrayLength] = {
-0x019,0x00000003,
-0x000,0x000000bf,
-0x001,0x000006e0,
-0x002,0x0000004c,
-0x003,0x000007f1,
-0x004,0x00000975,
-0x005,0x00000c58,
-0x006,0x00000ae6,
-0x007,0x000000ca,
-0x008,0x00000e1c,
-0x000,0x000000b7,
-0x00a,0x00000850,
-0x000,0x000000bf,
-0x00b,0x000001ba,
-0x00c,0x00000240,
-0x00e,0x00000020,
-0x015,0x00000f80,
-0x016,0x00000020,
-0x017,0x00000597,
-0x018,0x0000050a,
-0x01a,0x00000e00,
-0x01b,0x00000f5e,
-0x01d,0x00000607,
-0x01e,0x000006cc,
-0x00b,0x000001ba,
-0x023,0x00000203,
-0x024,0x00000200,
-0x000,0x00000037,
-0x004,0x00000160,
-0x016,0x00000200,
-0x016,0x00000380,
-0x016,0x00000020,
-0x016,0x000001a0,
-0x00d,0x00000ccc,
-0x000,0x000000bf,
-0x002,0x0000004d,
-0x000,0x00000cbf,
-0x004,0x00000975,
-0x007,0x00000700,
-};
-#endif
-#ifdef RTL8192E
+
 static u32 Rtl8192PciEMACPHY_Array[] = {
 0x03c,0xffff0000,0x00000f0f,
 0x340,0xffffffff,0x161a1a1a,
@@ -1393,12 +561,12 @@ static u32 Rtl8192PciERadioC_Array[RadioC_ArrayLength] = {
 0x0,  };
 static u32 Rtl8192PciERadioD_Array[RadioD_ArrayLength] = {
 0x0, };
-#endif
 
 /*************************Define local function prototype**********************/
 
-static u32 phy_FwRFSerialRead(struct net_device* dev,RF90_RADIO_PATH_E	eRFPath,u32 Offset);
-static void phy_FwRFSerialWrite(struct net_device* dev,RF90_RADIO_PATH_E eRFPath,u32 Offset,u32	Data);
+static u32 phy_FwRFSerialRead(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath, u32 Offset);
+static void phy_FwRFSerialWrite(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
+
 /*************************Define local function prototype**********************/
 /******************************************************************************
  *function:  This function read BB parameters from Header file we gen,
@@ -1423,24 +591,10 @@ static u32 rtl8192_CalculateBitShift(u32 dwBitMask)
  *  output:  none
  *  return:  0(illegal, false), 1(legal,true)
  * ***************************************************************************/
-u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath)
+u8 rtl8192_phy_CheckIsLegalRFPath(struct r8192_priv *priv, u32 eRFPath)
 {
 	u8 ret = 1;
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
-	if(priv->rf_type == RF_2T4R)
-	{
-		ret= 1;
-	}
-	else if (priv->rf_type == RF_1T2R)
-	{
-		if(eRFPath == RF90_PATH_A || eRFPath == RF90_PATH_B)
-			ret = 0;
-		else if(eRFPath == RF90_PATH_C || eRFPath == RF90_PATH_D)
-			ret =  1;
-	}
-#else
-	#ifdef RTL8192E
+
 	if (priv->rf_type == RF_2T4R)
 		ret = 0;
 	else if (priv->rf_type == RF_1T2R)
@@ -1450,8 +604,7 @@ u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath)
 		else if (eRFPath == RF90_PATH_C || eRFPath == RF90_PATH_D)
 			ret = 0;
 	}
-	#endif
-#endif
+
 	return ret;
 }
 /******************************************************************************
@@ -1464,19 +617,18 @@ u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath)
  *  return:  none
  *  notice:
  * ****************************************************************************/
-void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData)
+void rtl8192_setBBreg(struct r8192_priv *priv, u32 dwRegAddr, u32 dwBitMask, u32 dwData)
 {
-
 	u32 OriginalValue, BitShift, NewValue;
 
 	if(dwBitMask!= bMaskDWord)
 	{//if not "double word" write
-		OriginalValue = read_nic_dword(dev, dwRegAddr);
+		OriginalValue = read_nic_dword(priv, dwRegAddr);
 		BitShift = rtl8192_CalculateBitShift(dwBitMask);
             	NewValue = (((OriginalValue) & (~dwBitMask)) | (dwData << BitShift));
-		write_nic_dword(dev, dwRegAddr, NewValue);
+		write_nic_dword(priv, dwRegAddr, NewValue);
 	}else
-		write_nic_dword(dev, dwRegAddr, dwData);
+		write_nic_dword(priv, dwRegAddr, dwData);
 }
 /******************************************************************************
  *function:  This function reads specific bits from BB register
@@ -1487,11 +639,11 @@ void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32
  *  return:  u32	Data	//the readback register value
  *  notice:
  * ****************************************************************************/
-u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask)
+u32 rtl8192_QueryBBReg(struct r8192_priv *priv, u32 dwRegAddr, u32 dwBitMask)
 {
 	u32 OriginalValue, BitShift;
 
-	OriginalValue = read_nic_dword(dev, dwRegAddr);
+	OriginalValue = read_nic_dword(priv, dwRegAddr);
 	BitShift = rtl8192_CalculateBitShift(dwBitMask);
 	return (OriginalValue & dwBitMask) >> BitShift;
 }
@@ -1504,9 +656,9 @@ u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask)
  *  return:  u32 	readback value
  *  notice:  There are three types of serial operations:(1) Software serial write.(2)Hardware LSSI-Low Speed Serial Interface.(3)Hardware HSSI-High speed serial write. Driver here need to implement (1) and (2)---need more spec for this information.
  * ****************************************************************************/
-static u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset)
+static u32 rtl8192_phy_RFSerialRead(struct r8192_priv *priv,
+				    RF90_RADIO_PATH_E eRFPath, u32 Offset)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32 ret = 0;
 	u32 NewOffset = 0;
 	BB_REGISTER_DEFINITION_T* pPhyReg = &priv->PHYRegDef[eRFPath];
@@ -1515,89 +667,55 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eR
 	Offset &= 0x3f;
 
 	//switch page for 8256 RF IC
-	if (priv->rf_chip == RF_8256)
+	//analog to digital off, for protection
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
+	if (Offset >= 31)
 	{
-#ifdef RTL8190P
-		//analog to digital off, for protection
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-#else
-	#ifdef RTL8192E
-		//analog to digital off, for protection
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-	#endif
-#endif
-		if (Offset >= 31)
-		{
-			priv->RfReg0Value[eRFPath] |= 0x140;
-			//Switch to Reg_Mode2 for Reg 31-45
-			rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) );
-			//modify offset
-			NewOffset = Offset -30;
-		}
-		else if (Offset >= 16)
-		{
-			priv->RfReg0Value[eRFPath] |= 0x100;
-			priv->RfReg0Value[eRFPath] &= (~0x40);
-			//Switch to Reg_Mode 1 for Reg16-30
-			rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) );
+		priv->RfReg0Value[eRFPath] |= 0x140;
+		//Switch to Reg_Mode2 for Reg 31-45
+		rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) );
+		//modify offset
+		NewOffset = Offset -30;
+	}
+	else if (Offset >= 16)
+	{
+		priv->RfReg0Value[eRFPath] |= 0x100;
+		priv->RfReg0Value[eRFPath] &= (~0x40);
+		//Switch to Reg_Mode 1 for Reg16-30
+		rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16) );
 
-			NewOffset = Offset - 15;
-		}
-		else
-			NewOffset = Offset;
+		NewOffset = Offset - 15;
 	}
 	else
-	{
-		RT_TRACE((COMP_PHY|COMP_ERR), "check RF type here, need to be 8256\n");
 		NewOffset = Offset;
-	}
+
 	//put desired read addr to LSSI control Register
-	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, NewOffset);
+	rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2, bLSSIReadAddress, NewOffset);
 	//Issue a posedge trigger
 	//
-	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x0);
-	rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x1);
+	rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x0);
+	rtl8192_setBBreg(priv, pPhyReg->rfHSSIPara2,  bLSSIReadEdge, 0x1);
 
 
 	// TODO: we should not delay such a  long time. Ask help from SD3
 	msleep(1);
 
-	ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
+	ret = rtl8192_QueryBBReg(priv, pPhyReg->rfLSSIReadBack, bLSSIReadBackData);
 
 
 	// Switch back to Reg_Mode0;
-	if(priv->rf_chip == RF_8256)
-	{
-		priv->RfReg0Value[eRFPath] &= 0xebf;
+	priv->RfReg0Value[eRFPath] &= 0xebf;
 
-		rtl8192_setBBreg(
-			dev,
-			pPhyReg->rf3wireOffset,
-			bMaskDWord,
-			(priv->RfReg0Value[eRFPath] << 16));
-
-#ifdef RTL8190P
-		if(priv->rf_type == RF_2T4R)
-		{
-			//analog to digital on
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf);// 0x88c[11:8]
-		}
-		else if(priv->rf_type == RF_1T2R)
-		{
-			//analog to digital on
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xc00, 0x3);// 0x88c[11:10]
-		}
-#else
-	#ifdef RTL8192E
-		//analog to digital on
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
-	#endif
-#endif
-	}
+	rtl8192_setBBreg(
+		priv,
+		pPhyReg->rf3wireOffset,
+		bMaskDWord,
+		(priv->RfReg0Value[eRFPath] << 16));
 
+	//analog to digital on
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
 
 	return ret;
-
 }
 
 /******************************************************************************
@@ -1620,94 +738,61 @@ static u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eR
  * Reg_Mode2	1		1			Reg 31 ~ 45(0x1 ~ 0xf)
  *------------------------------------------------------------------
  * ****************************************************************************/
-static void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data)
+static void rtl8192_phy_RFSerialWrite(struct r8192_priv *priv,
+				      RF90_RADIO_PATH_E eRFPath, u32 Offset,
+				      u32 Data)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32 DataAndAddr = 0, NewOffset = 0;
 	BB_REGISTER_DEFINITION_T	*pPhyReg = &priv->PHYRegDef[eRFPath];
 
 	Offset &= 0x3f;
-	if (priv->rf_chip == RF_8256)
-	{
 
-#ifdef RTL8190P
-		//analog to digital off, for protection
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-#else
-	#ifdef RTL8192E
-		//analog to digital off, for protection
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
-	#endif
-#endif
+	//analog to digital off, for protection
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
 
-		if (Offset >= 31)
-		{
-			priv->RfReg0Value[eRFPath] |= 0x140;
-			rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath] << 16));
-			NewOffset = Offset - 30;
-		}
-		else if (Offset >= 16)
-		{
-			priv->RfReg0Value[eRFPath] |= 0x100;
-			priv->RfReg0Value[eRFPath] &= (~0x40);
-			rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16));
-			NewOffset = Offset - 15;
-		}
-		else
-			NewOffset = Offset;
+	if (Offset >= 31)
+	{
+		priv->RfReg0Value[eRFPath] |= 0x140;
+		rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath] << 16));
+		NewOffset = Offset - 30;
 	}
-	else
+	else if (Offset >= 16)
 	{
-		RT_TRACE((COMP_PHY|COMP_ERR), "check RF type here, need to be 8256\n");
-		NewOffset = Offset;
+		priv->RfReg0Value[eRFPath] |= 0x100;
+		priv->RfReg0Value[eRFPath] &= (~0x40);
+		rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, (priv->RfReg0Value[eRFPath]<<16));
+		NewOffset = Offset - 15;
 	}
+	else
+		NewOffset = Offset;
 
 	// Put write addr in [5:0]  and write data in [31:16]
 	DataAndAddr = (Data<<16) | (NewOffset&0x3f);
 
 	// Write Operation
-	rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+	rtl8192_setBBreg(priv, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
 
 
 	if(Offset==0x0)
 		priv->RfReg0Value[eRFPath] = Data;
 
 	// Switch back to Reg_Mode0;
- 	if(priv->rf_chip == RF_8256)
+	if(Offset != 0)
 	{
-		if(Offset != 0)
-		{
-			priv->RfReg0Value[eRFPath] &= 0xebf;
-			rtl8192_setBBreg(
-				dev,
-				pPhyReg->rf3wireOffset,
-				bMaskDWord,
-				(priv->RfReg0Value[eRFPath] << 16));
-		}
-#ifdef RTL8190P
-		if(priv->rf_type == RF_2T4R)
-		{
-			//analog to digital on
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf);// 0x88c[11:8]
-		}
-		else if(priv->rf_type == RF_1T2R)
-		{
-			//analog to digital on
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xc00, 0x3);// 0x88c[11:10]
-		}
-#else
-	#ifdef RTL8192E
-		//analog to digital on
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
-	#endif
-#endif
+		priv->RfReg0Value[eRFPath] &= 0xebf;
+		rtl8192_setBBreg(
+			priv,
+			pPhyReg->rf3wireOffset,
+			bMaskDWord,
+			(priv->RfReg0Value[eRFPath] << 16));
 	}
+	//analog to digital on
+	rtl8192_setBBreg(priv, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
 }
 
 /******************************************************************************
  *function:  This function set specific bits to RF register
- *   input:  net_device dev
- *   	     RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D
+ *   input:  RF90_RADIO_PATH_E eRFPath //radio path of A/B/C/D
  *           u32	RegAddr  //target addr to be modified
  *           u32	BitMask  //taget bit pos in the addr to be modified
  *           u32	Data     //value to be write
@@ -1715,19 +800,16 @@ static void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E
  *  return:  none
  *  notice:
  * ****************************************************************************/
-void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
+void rtl8192_phy_SetRFReg(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath,
+			  u32 RegAddr, u32 BitMask, u32 Data)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32 Original_Value, BitShift, New_Value;
 //	u8	time = 0;
 
-	if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+	if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
 		return;
-#ifdef RTL8192E
-	if(priv->ieee80211->eRFPowerState != eRfOn && !priv->being_init_adapter)
+	if (priv->eRFPowerState != eRfOn && !priv->being_init_adapter)
 		return;
-#endif
-	//spin_lock_irqsave(&priv->rf_lock, flags);
 	//down(&priv->rf_sem);
 
 	RT_TRACE(COMP_PHY, "FW RF CTRL is not ready now\n");
@@ -1735,13 +817,13 @@ void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32
 	{
 		if (BitMask != bMask12Bits) // RF data is 12 bits only
 		{
-			Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr);
+			Original_Value = phy_FwRFSerialRead(priv, eRFPath, RegAddr);
 			BitShift =  rtl8192_CalculateBitShift(BitMask);
 			New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift));
 
-			phy_FwRFSerialWrite(dev, eRFPath, RegAddr, New_Value);
+			phy_FwRFSerialWrite(priv, eRFPath, RegAddr, New_Value);
 		}else
-			phy_FwRFSerialWrite(dev, eRFPath, RegAddr, Data);
+			phy_FwRFSerialWrite(priv, eRFPath, RegAddr, Data);
 		udelay(200);
 
 	}
@@ -1749,15 +831,14 @@ void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32
 	{
 		if (BitMask != bMask12Bits) // RF data is 12 bits only
    	        {
-			Original_Value = rtl8192_phy_RFSerialRead(dev, eRFPath, RegAddr);
+			Original_Value = rtl8192_phy_RFSerialRead(priv, eRFPath, RegAddr);
       			BitShift =  rtl8192_CalculateBitShift(BitMask);
       			New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift));
 
-			rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr, New_Value);
+			rtl8192_phy_RFSerialWrite(priv, eRFPath, RegAddr, New_Value);
 	        }else
-			rtl8192_phy_RFSerialWrite(dev, eRFPath, RegAddr, Data);
+			rtl8192_phy_RFSerialWrite(priv, eRFPath, RegAddr, Data);
 	}
-	//spin_unlock_irqrestore(&priv->rf_lock, flags);
 	//up(&priv->rf_sem);
 }
 
@@ -1770,25 +851,24 @@ void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32
  *  return:  u32	Data	//the readback register value
  *  notice:
  * ****************************************************************************/
-u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask)
+u32 rtl8192_phy_QueryRFReg(struct r8192_priv *priv, RF90_RADIO_PATH_E eRFPath,
+			   u32 RegAddr, u32 BitMask)
 {
 	u32 Original_Value, Readback_Value, BitShift;
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+
+	if (!rtl8192_phy_CheckIsLegalRFPath(priv, eRFPath))
 		return 0;
-#ifdef RTL8192E
-	if(priv->ieee80211->eRFPowerState != eRfOn && !priv->being_init_adapter)
+	if (priv->eRFPowerState != eRfOn && !priv->being_init_adapter)
 		return	0;
-#endif
 	down(&priv->rf_sem);
 	if (priv->Rf_Mode == RF_OP_By_FW)
 	{
-		Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr);
+		Original_Value = phy_FwRFSerialRead(priv, eRFPath, RegAddr);
 		udelay(200);
 	}
 	else
 	{
-		Original_Value = rtl8192_phy_RFSerialRead(dev, eRFPath, RegAddr);
+		Original_Value = rtl8192_phy_RFSerialRead(priv, eRFPath, RegAddr);
 
 	}
 	BitShift =  rtl8192_CalculateBitShift(BitMask);
@@ -1805,10 +885,8 @@ u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u3
  *  return:  none
  *  notice:
  * ***************************************************************************/
-static u32 phy_FwRFSerialRead(
-	struct net_device* dev,
-	RF90_RADIO_PATH_E	eRFPath,
-	u32				Offset	)
+static u32 phy_FwRFSerialRead(struct r8192_priv *priv,
+			      RF90_RADIO_PATH_E eRFPath, u32 Offset)
 {
 	u32		Data = 0;
 	u8		time = 0;
@@ -1827,7 +905,7 @@ static u32 phy_FwRFSerialRead(
 	// 5. Trigger Fw to operate the command. bit 31
 	Data |= 0x80000000;
 	// 6. We can not execute read operation if bit 31 is 1.
-	while (read_nic_dword(dev, QPNR)&0x80000000)
+	while (read_nic_dword(priv, QPNR)&0x80000000)
 	{
 		// If FW can not finish RF-R/W for more than ?? times. We must reset FW.
 		if (time++ < 100)
@@ -1839,9 +917,9 @@ static u32 phy_FwRFSerialRead(
 			break;
 	}
 	// 7. Execute read operation.
-	write_nic_dword(dev, QPNR, Data);
+	write_nic_dword(priv, QPNR, Data);
 	// 8. Check if firmawre send back RF content.
-	while (read_nic_dword(dev, QPNR)&0x80000000)
+	while (read_nic_dword(priv, QPNR)&0x80000000)
 	{
 		// If FW can not finish RF-R/W for more than ?? times. We must reset FW.
 		if (time++ < 100)
@@ -1852,7 +930,7 @@ static u32 phy_FwRFSerialRead(
 		else
 			return 0;
 	}
-	return read_nic_dword(dev, RF_DATA);
+	return read_nic_dword(priv, RF_DATA);
 }
 
 /******************************************************************************
@@ -1862,12 +940,8 @@ static u32 phy_FwRFSerialRead(
  *  return:  none
  *  notice:
  * ***************************************************************************/
-static void
-phy_FwRFSerialWrite(
-		struct net_device* dev,
-		RF90_RADIO_PATH_E	eRFPath,
-		u32				Offset,
-		u32				Data	)
+static void phy_FwRFSerialWrite(struct r8192_priv *priv,
+				RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data)
 {
 	u8	time = 0;
 
@@ -1888,7 +962,7 @@ phy_FwRFSerialWrite(
 	Data |= 0x80000000;
 
 	// 6. Write operation. We can not write if bit 31 is 1.
-	while (read_nic_dword(dev, QPNR)&0x80000000)
+	while (read_nic_dword(priv, QPNR)&0x80000000)
 	{
 		// If FW can not finish RF-R/W for more than ?? times. We must reset FW.
 		if (time++ < 100)
@@ -1901,7 +975,7 @@ phy_FwRFSerialWrite(
 	}
 	// 7. No matter check bit. We always force the write. Because FW will
 	//    not accept the command.
-	write_nic_dword(dev, QPNR, Data);
+	write_nic_dword(priv, QPNR, Data);
 	/* 2007/11/02 MH Acoording to test, we must delay 20us to wait firmware
 	   to finish RF write operation. */
 	/* 2008/01/17 MH We support delay in firmware side now. */
@@ -1919,11 +993,10 @@ phy_FwRFSerialWrite(
  *  notice:  BB parameters may change all the time, so please make
  *           sure it has been synced with the newest.
  * ***************************************************************************/
-void rtl8192_phy_configmac(struct net_device* dev)
+void rtl8192_phy_configmac(struct r8192_priv *priv)
 {
 	u32 dwArrayLen = 0, i = 0;
 	u32* pdwArray = NULL;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 #ifdef TO_DO_LIST
 if(Adapter->bInHctTest)
 	{
@@ -1955,7 +1028,7 @@ if(Adapter->bInHctTest)
 			//DbgPrint("ptrArray[i], ptrArray[i+1], ptrArray[i+2] = %x, %x, %x\n",
 			//	ptrArray[i], ptrArray[i+1], ptrArray[i+2]);
 		}
-		rtl8192_setBBreg(dev, pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
+		rtl8192_setBBreg(priv, pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
 	}
 }
 
@@ -1968,14 +1041,13 @@ if(Adapter->bInHctTest)
  *           sure it has been synced with the newest.
  * ***************************************************************************/
 
-void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType)
+void rtl8192_phyConfigBB(struct r8192_priv *priv, u8 ConfigType)
 {
 	int i;
 	//u8 ArrayLength;
 	u32*	Rtl819XPHY_REGArray_Table = NULL;
 	u32*	Rtl819XAGCTAB_Array_Table = NULL;
 	u16	AGCTAB_ArrayLen, PHY_REGArrayLen = 0;
-	struct r8192_priv *priv = ieee80211_priv(dev);
 #ifdef TO_DO_LIST
 	u32 *rtl8192PhyRegArrayTable = NULL, *rtl8192AgcTabArrayTable = NULL;
 	if(Adapter->bInHctTest)
@@ -2015,16 +1087,16 @@ void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType)
 	{
 		for (i=0; i<PHY_REGArrayLen; i+=2)
 		{
-			rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table[i], bMaskDWord, Rtl819XPHY_REGArray_Table[i+1]);
-			RT_TRACE(COMP_DBG, "i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x \n",i, Rtl819XPHY_REGArray_Table[i], Rtl819XPHY_REGArray_Table[i+1]);
+			rtl8192_setBBreg(priv, Rtl819XPHY_REGArray_Table[i], bMaskDWord, Rtl819XPHY_REGArray_Table[i+1]);
+			RT_TRACE(COMP_DBG, "i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x\n",i, Rtl819XPHY_REGArray_Table[i], Rtl819XPHY_REGArray_Table[i+1]);
 		}
 	}
 	else if (ConfigType == BaseBand_Config_AGC_TAB)
 	{
 		for (i=0; i<AGCTAB_ArrayLen; i+=2)
 		{
-			rtl8192_setBBreg(dev, Rtl819XAGCTAB_Array_Table[i], bMaskDWord, Rtl819XAGCTAB_Array_Table[i+1]);
-			RT_TRACE(COMP_DBG, "i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x \n",i, Rtl819XAGCTAB_Array_Table[i], Rtl819XAGCTAB_Array_Table[i+1]);
+			rtl8192_setBBreg(priv, Rtl819XAGCTAB_Array_Table[i], bMaskDWord, Rtl819XAGCTAB_Array_Table[i+1]);
+			RT_TRACE(COMP_DBG, "i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x\n",i, Rtl819XAGCTAB_Array_Table[i], Rtl819XAGCTAB_Array_Table[i+1]);
 		}
 	}
 }
@@ -2036,9 +1108,8 @@ void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType)
  *  return:  none
  *  notice:  Initialization value here is constant and it should never be changed
  * ***************************************************************************/
-static void rtl8192_InitBBRFRegDef(struct net_device* dev)
+static void rtl8192_InitBBRFRegDef(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 // RF Interface Sowrtware Control
 	priv->PHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 LSBs if read 32-bit from 0x870
 	priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; // 16 MSBs if read 32-bit from 0x870 (16-bit for 0x872)
@@ -2151,9 +1222,10 @@ static void rtl8192_InitBBRFRegDef(struct net_device* dev)
  *  return:  return whether BB and RF is ok(0:OK; 1:Fail)
  *  notice:  This function may be removed in the ASIC
  * ***************************************************************************/
-RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath)
+RT_STATUS rtl8192_phy_checkBBAndRF(struct r8192_priv *priv,
+				   HW90_BLOCK_E CheckBlock,
+				   RF90_RADIO_PATH_E eRFPath)
 {
-	//struct r8192_priv *priv = ieee80211_priv(dev);
 //	BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath];
 	RT_STATUS ret = RT_STATUS_SUCCESS;
 	u32 i, CheckTimes = 4, dwRegRead = 0;
@@ -2174,21 +1246,21 @@ RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlo
 		switch(CheckBlock)
 		{
 		case HW90_BLOCK_MAC:
-			RT_TRACE(COMP_ERR, "PHY_CheckBBRFOK(): Never Write 0x100 here!");
+			RT_TRACE(COMP_ERR, "PHY_CheckBBRFOK(): Never Write 0x100 here!\n");
 			break;
 
 		case HW90_BLOCK_PHY0:
 		case HW90_BLOCK_PHY1:
-			write_nic_dword(dev, WriteAddr[CheckBlock], WriteData[i]);
-			dwRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]);
+			write_nic_dword(priv, WriteAddr[CheckBlock], WriteData[i]);
+			dwRegRead = read_nic_dword(priv, WriteAddr[CheckBlock]);
 			break;
 
 		case HW90_BLOCK_RF:
 			WriteData[i] &= 0xfff;
-			rtl8192_phy_SetRFReg(dev, eRFPath, WriteAddr[HW90_BLOCK_RF], bMask12Bits, WriteData[i]);
+			rtl8192_phy_SetRFReg(priv, eRFPath, WriteAddr[HW90_BLOCK_RF], bMask12Bits, WriteData[i]);
 			// TODO: we should not delay for such a long time. Ask SD3
 			mdelay(10);
-			dwRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath, WriteAddr[HW90_BLOCK_RF], bMaskDWord);
+			dwRegRead = rtl8192_phy_QueryRFReg(priv, eRFPath, WriteAddr[HW90_BLOCK_RF], bMaskDWord);
 			mdelay(10);
 			break;
 
@@ -2203,7 +1275,7 @@ RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlo
 		//
 		if(dwRegRead != WriteData[i])
 		{
-			RT_TRACE(COMP_ERR, "====>error=====dwRegRead: %x, WriteData: %x \n", dwRegRead, WriteData[i]);
+			RT_TRACE(COMP_ERR, "====>error=====dwRegRead: %x, WriteData: %x\n", dwRegRead, WriteData[i]);
 			ret = RT_STATUS_FAILURE;
 			break;
 		}
@@ -2221,10 +1293,10 @@ RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlo
  *  notice:  Initialization value may change all the time, so please make
  *           sure it has been synced with the newest.
  * ***************************************************************************/
-static RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev)
+static RT_STATUS rtl8192_BB_Config_ParaFile(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	RT_STATUS rtStatus = RT_STATUS_SUCCESS;
+
 	u8 bRegValue = 0, eCheckItem = 0;
 	u32 dwRegValue = 0;
 	/**************************************
@@ -2232,18 +1304,18 @@ static RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev)
 	**************************************/
 
 	/*--set BB Global Reset--*/
-	bRegValue = read_nic_byte(dev, BB_GLOBAL_RESET);
-	write_nic_byte(dev, BB_GLOBAL_RESET,(bRegValue|BB_GLOBAL_RESET_BIT));
+	bRegValue = read_nic_byte(priv, BB_GLOBAL_RESET);
+	write_nic_byte(priv, BB_GLOBAL_RESET,(bRegValue|BB_GLOBAL_RESET_BIT));
 
 	/*---set BB reset Active---*/
-	dwRegValue = read_nic_dword(dev, CPU_GEN);
-	write_nic_dword(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
+	dwRegValue = read_nic_dword(priv, CPU_GEN);
+	write_nic_dword(priv, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
 
 	/*----Ckeck FPGAPHY0 and PHY1 board is OK----*/
 	// TODO: this function should be removed on ASIC , Emily 2007.2.2
 	for(eCheckItem=(HW90_BLOCK_E)HW90_BLOCK_PHY0; eCheckItem<=HW90_BLOCK_PHY1; eCheckItem++)
 	{
-		rtStatus  = rtl8192_phy_checkBBAndRF(dev, (HW90_BLOCK_E)eCheckItem, (RF90_RADIO_PATH_E)0); //don't care RF path
+		rtStatus  = rtl8192_phy_checkBBAndRF(priv, (HW90_BLOCK_E)eCheckItem, (RF90_RADIO_PATH_E)0); //don't care RF path
 		if(rtStatus != RT_STATUS_SUCCESS)
 		{
 			RT_TRACE((COMP_ERR | COMP_PHY), "PHY_RF8256_Config():Check PHY%d Fail!!\n", eCheckItem-1);
@@ -2251,18 +1323,18 @@ static RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev)
 		}
 	}
 	/*---- Set CCK and OFDM Block "OFF"----*/
-	rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
+	rtl8192_setBBreg(priv, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
 	/*----BB Register Initilazation----*/
 	//==m==>Set PHY REG From Header<==m==
-	rtl8192_phyConfigBB(dev, BaseBand_Config_PHY_REG);
+	rtl8192_phyConfigBB(priv, BaseBand_Config_PHY_REG);
 
 	/*----Set BB reset de-Active----*/
-	dwRegValue = read_nic_dword(dev, CPU_GEN);
-	write_nic_dword(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
+	dwRegValue = read_nic_dword(priv, CPU_GEN);
+	write_nic_dword(priv, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
 
  	/*----BB AGC table Initialization----*/
 	//==m==>Set PHY REG From Header<==m==
-	rtl8192_phyConfigBB(dev, BaseBand_Config_AGC_TAB);
+	rtl8192_phyConfigBB(priv, BaseBand_Config_AGC_TAB);
 
 	if (priv->card_8192_version  > VERSION_8190_BD)
 	{
@@ -2275,23 +1347,13 @@ static RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev)
 		}
 		else
 			dwRegValue = 0x0;	//Antenna gain offset doesn't make sense in RF 1T2R.
-		rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
+		rtl8192_setBBreg(priv, rFPGA0_TxGainStage,
 			(bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
 
 
 		//XSTALLCap
-#ifdef RTL8190P
-	dwRegValue = priv->CrystalCap & 0x3;	// bit0~1 of crystal cap
-	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap01, dwRegValue);
-	dwRegValue = ((priv->CrystalCap & 0xc)>>2);	// bit2~3 of crystal cap
-	rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, bXtalCap23, dwRegValue);
-#else
-	#ifdef RTL8192E
 		dwRegValue = priv->CrystalCap;
-		rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, dwRegValue);
-	#endif
-#endif
-
+		rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, bXtalCap92x, dwRegValue);
 	}
 
 	// Check if the CCK HighPower is turned ON.
@@ -2307,12 +1369,12 @@ static RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev)
  *  notice:  Initialization value may change all the time, so please make
  *           sure it has been synced with the newest.
  * ***************************************************************************/
-RT_STATUS rtl8192_BBConfig(struct net_device* dev)
+RT_STATUS rtl8192_BBConfig(struct r8192_priv *priv)
 {
-	rtl8192_InitBBRFRegDef(dev);
+	rtl8192_InitBBRFRegDef(priv);
 	//config BB&RF. As hardCode based initialization has not been well
 	//implemented, so use file first.FIXME:should implement it for hardcode?
-	return rtl8192_BB_Config_ParaFile(dev);
+	return rtl8192_BB_Config_ParaFile(priv);
 }
 
 /******************************************************************************
@@ -2321,49 +1383,37 @@ RT_STATUS rtl8192_BBConfig(struct net_device* dev)
  *  output:  none
  *  return:  none
  * ***************************************************************************/
-void rtl8192_phy_getTxPower(struct net_device* dev)
+void rtl8192_phy_getTxPower(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#ifdef RTL8190P
-	priv->MCSTxPowerLevelOriginalOffset[0] =
-		read_nic_dword(dev, MCS_TXAGC);
-	priv->MCSTxPowerLevelOriginalOffset[1] =
-		read_nic_dword(dev, (MCS_TXAGC+4));
-	priv->CCKTxPowerLevelOriginalOffset =
-		read_nic_dword(dev, CCK_TXAGC);
-#else
-	#ifdef RTL8192E
 	priv->MCSTxPowerLevelOriginalOffset[0] =
-		read_nic_dword(dev, rTxAGC_Rate18_06);
+		read_nic_dword(priv, rTxAGC_Rate18_06);
 	priv->MCSTxPowerLevelOriginalOffset[1] =
-		read_nic_dword(dev, rTxAGC_Rate54_24);
+		read_nic_dword(priv, rTxAGC_Rate54_24);
 	priv->MCSTxPowerLevelOriginalOffset[2] =
-		read_nic_dword(dev, rTxAGC_Mcs03_Mcs00);
+		read_nic_dword(priv, rTxAGC_Mcs03_Mcs00);
 	priv->MCSTxPowerLevelOriginalOffset[3] =
-		read_nic_dword(dev, rTxAGC_Mcs07_Mcs04);
+		read_nic_dword(priv, rTxAGC_Mcs07_Mcs04);
 	priv->MCSTxPowerLevelOriginalOffset[4] =
-		read_nic_dword(dev, rTxAGC_Mcs11_Mcs08);
+		read_nic_dword(priv, rTxAGC_Mcs11_Mcs08);
 	priv->MCSTxPowerLevelOriginalOffset[5] =
-		read_nic_dword(dev, rTxAGC_Mcs15_Mcs12);
-	#endif
-#endif
+		read_nic_dword(priv, rTxAGC_Mcs15_Mcs12);
 
 	// read rx initial gain
-	priv->DefaultInitialGain[0] = read_nic_byte(dev, rOFDM0_XAAGCCore1);
-	priv->DefaultInitialGain[1] = read_nic_byte(dev, rOFDM0_XBAGCCore1);
-	priv->DefaultInitialGain[2] = read_nic_byte(dev, rOFDM0_XCAGCCore1);
-	priv->DefaultInitialGain[3] = read_nic_byte(dev, rOFDM0_XDAGCCore1);
-	RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x) \n",
+	priv->DefaultInitialGain[0] = read_nic_byte(priv, rOFDM0_XAAGCCore1);
+	priv->DefaultInitialGain[1] = read_nic_byte(priv, rOFDM0_XBAGCCore1);
+	priv->DefaultInitialGain[2] = read_nic_byte(priv, rOFDM0_XCAGCCore1);
+	priv->DefaultInitialGain[3] = read_nic_byte(priv, rOFDM0_XDAGCCore1);
+	RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
 		priv->DefaultInitialGain[0], priv->DefaultInitialGain[1],
 		priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]);
 
 	// read framesync
-	priv->framesync = read_nic_byte(dev, rOFDM0_RxDetector3);
-	priv->framesyncC34 = read_nic_dword(dev, rOFDM0_RxDetector2);
-	RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x \n",
+	priv->framesync = read_nic_byte(priv, rOFDM0_RxDetector3);
+	priv->framesyncC34 = read_nic_dword(priv, rOFDM0_RxDetector2);
+	RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
 		rOFDM0_RxDetector3, priv->framesync);
 	// read SIFS (save the value read fome MACPHY_REG.txt)
-	priv->SifsTime = read_nic_word(dev, SIFS);
+	priv->SifsTime = read_nic_word(priv, SIFS);
 }
 
 /******************************************************************************
@@ -2372,9 +1422,8 @@ void rtl8192_phy_getTxPower(struct net_device* dev)
  *  output:  none
  *  return:  none
  * ***************************************************************************/
-void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel)
+void rtl8192_phy_setTxPower(struct r8192_priv *priv, u8 channel)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8	powerlevel = 0,powerlevelOFDM24G = 0;
 	char ant_pwr_diff;
 	u32	u4RegValue;
@@ -2402,8 +1451,6 @@ void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel)
 			ant_pwr_diff = priv->TxPowerLevelOFDM24G_C[channel-1]
 						-priv->TxPowerLevelOFDM24G_A[channel-1];
 			ant_pwr_diff &= 0xf;
-			//DbgPrint(" ant_pwr_diff = 0x%x", (u8)(ant_pwr_diff));
-			priv->RF_C_TxPwDiff = ant_pwr_diff;
 
 			priv->AntennaTxPwDiff[2] = 0;// RF-D, don't care
 			priv->AntennaTxPwDiff[1] = (u8)(ant_pwr_diff);// RF-C
@@ -2414,7 +1461,7 @@ void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel)
 						priv->AntennaTxPwDiff[1]<<4 |
 						priv->AntennaTxPwDiff[0]);
 
-			rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
+			rtl8192_setBBreg(priv, rFPGA0_TxGainStage,
 			(bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
 		}
 	}
@@ -2469,22 +1516,8 @@ void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel)
 	pHalData->CurrentCckTxPwrIdx = powerlevel;
 	pHalData->CurrentOfdm24GTxPwrIdx = powerlevelOFDM24G;
 #endif
-	switch(priv->rf_chip)
-	{
-	case RF_8225:
-	//	PHY_SetRF8225CckTxPower(Adapter, powerlevel);
-	//	PHY_SetRF8225OfdmTxPower(Adapter, powerlevelOFDM24G);
-		break;
-	case RF_8256:
-		PHY_SetRF8256CCKTxPower(dev, powerlevel); //need further implement
-		PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
-		break;
-	case RF_8258:
-		break;
-	default:
-		RT_TRACE(COMP_ERR, "unknown rf chip in funtion %s()\n", __FUNCTION__);
-		break;
-	}
+	PHY_SetRF8256CCKTxPower(priv, powerlevel); //need further implement
+	PHY_SetRF8256OFDMTxPower(priv, powerlevelOFDM24G);
 }
 
 /******************************************************************************
@@ -2493,30 +1526,9 @@ void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel)
  *  output:  none
  *  return:  only 8256 is supported
  * ***************************************************************************/
-RT_STATUS rtl8192_phy_RFConfig(struct net_device* dev)
+RT_STATUS rtl8192_phy_RFConfig(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-	RT_STATUS rtStatus = RT_STATUS_SUCCESS;
-	switch(priv->rf_chip)
-	{
-		case RF_8225:
-//			rtStatus = PHY_RF8225_Config(Adapter);
-			break;
-		case RF_8256:
-			rtStatus = PHY_RF8256_Config(dev);
-			break;
-
-		case RF_8258:
-			break;
-		case RF_PSEUDO_11N:
-		//rtStatus = PHY_RF8225_Config(Adapter);
-		break;
-
-		default:
-			RT_TRACE(COMP_ERR, "error chip id\n");
-			break;
-	}
-	return rtStatus;
+	return PHY_RF8256_Config(priv);
 }
 
 /******************************************************************************
@@ -2525,7 +1537,7 @@ RT_STATUS rtl8192_phy_RFConfig(struct net_device* dev)
  *  output:  none
  *  return:  As Windows has not implemented this, wait for complement
  * ***************************************************************************/
-void rtl8192_phy_updateInitGain(struct net_device* dev)
+void rtl8192_phy_updateInitGain(struct r8192_priv *priv)
 {
 }
 
@@ -2536,7 +1548,8 @@ void rtl8192_phy_updateInitGain(struct net_device* dev)
  *  return:  return code show if RF configuration is successful(0:pass, 1:fail)
  *    Note:  Delay may be required for RF configuration
  * ***************************************************************************/
-u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E	eRFPath)
+u8 rtl8192_phy_ConfigRFWithHeaderFile(struct r8192_priv *priv,
+				      RF90_RADIO_PATH_E eRFPath)
 {
 
 	int i;
@@ -2551,7 +1564,7 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E
 						msleep(100);
 						continue;
 				}
-				rtl8192_phy_SetRFReg(dev, eRFPath, Rtl819XRadioA_Array[i], bMask12Bits, Rtl819XRadioA_Array[i+1]);
+				rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioA_Array[i], bMask12Bits, Rtl819XRadioA_Array[i+1]);
 				//msleep(1);
 
 			}
@@ -2563,7 +1576,7 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E
 						msleep(100);
 						continue;
 				}
-				rtl8192_phy_SetRFReg(dev, eRFPath, Rtl819XRadioB_Array[i], bMask12Bits, Rtl819XRadioB_Array[i+1]);
+				rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioB_Array[i], bMask12Bits, Rtl819XRadioB_Array[i+1]);
 				//msleep(1);
 
 			}
@@ -2575,7 +1588,7 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E
 						msleep(100);
 						continue;
 				}
-				rtl8192_phy_SetRFReg(dev, eRFPath, Rtl819XRadioC_Array[i], bMask12Bits, Rtl819XRadioC_Array[i+1]);
+				rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioC_Array[i], bMask12Bits, Rtl819XRadioC_Array[i+1]);
 				//msleep(1);
 
 			}
@@ -2587,7 +1600,7 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E
 						msleep(100);
 						continue;
 				}
-				rtl8192_phy_SetRFReg(dev, eRFPath, Rtl819XRadioD_Array[i], bMask12Bits, Rtl819XRadioD_Array[i+1]);
+				rtl8192_phy_SetRFReg(priv, eRFPath, Rtl819XRadioD_Array[i], bMask12Bits, Rtl819XRadioD_Array[i+1]);
 				//msleep(1);
 
 			}
@@ -2607,33 +1620,15 @@ u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E
  *  return:  none
  *    Note:
  * ***************************************************************************/
-static void rtl8192_SetTxPowerLevel(struct net_device *dev, u8 channel)
+static void rtl8192_SetTxPowerLevel(struct r8192_priv *priv, u8 channel)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8	powerlevel = priv->TxPowerLevelCCK[channel-1];
 	u8	powerlevelOFDM24G = priv->TxPowerLevelOFDM24G[channel-1];
 
-	switch(priv->rf_chip)
-	{
-	case RF_8225:
-#ifdef TO_DO_LIST
-		PHY_SetRF8225CckTxPower(Adapter, powerlevel);
-		PHY_SetRF8225OfdmTxPower(Adapter, powerlevelOFDM24G);
-#endif
-		break;
-
-	case RF_8256:
-		PHY_SetRF8256CCKTxPower(dev, powerlevel);
-		PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
-		break;
-
-	case RF_8258:
-		break;
-	default:
-		RT_TRACE(COMP_ERR, "unknown rf chip ID in rtl8192_SetTxPowerLevel()\n");
-		break;
-	}
+	PHY_SetRF8256CCKTxPower(priv, powerlevel);
+	PHY_SetRF8256OFDMTxPower(priv, powerlevelOFDM24G);
 }
+
 /****************************************************************************************
  *function:  This function set command table variable(struct SwChnlCmd).
  *   input:  SwChnlCmd*		CmdTable 	//table to be set.
@@ -2690,9 +1685,9 @@ static u8 rtl8192_phy_SetSwChnlCmdArray(
  *  return:  true if finished, false otherwise
  *    Note:  Wait for simpler function to replace it //wb
  * ***************************************************************************/
-static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8* stage, u8* step, u32* delay)
+static u8 rtl8192_phy_SwChnlStepByStep(struct r8192_priv *priv, u8 channel,
+				       u8* stage, u8* step, u32* delay)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 //	PCHANNEL_ACCESS_SETTING	pChnlAccessSetting;
 	SwChnlCmd				PreCommonCmd[MAX_PRECMD_CNT];
 	u32					PreCommonCmdCnt;
@@ -2737,42 +1732,17 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8* s
 
 		// <3> Fill up RF dependent command.
 		RfDependCmdCnt = 0;
-		switch( priv->rf_chip )
-		{
-		case RF_8225:
-			if (!(channel >= 1 && channel <= 14))
-			{
-				RT_TRACE(COMP_ERR, "illegal channel for Zebra 8225: %d\n", channel);
-				return false;
-			}
-			rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
-				CmdID_RF_WriteReg, rZebra1_Channel, RF_CHANNEL_TABLE_ZEBRA[channel], 10);
-			rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
-				CmdID_End, 0, 0, 0);
-			break;
-
-		case RF_8256:
-			// TEST!! This is not the table for 8256!!
-			if (!(channel >= 1 && channel <= 14))
-			{
-				RT_TRACE(COMP_ERR, "illegal channel for Zebra 8256: %d\n", channel);
-				return false;
-			}
-			rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
-				CmdID_RF_WriteReg, rZebra1_Channel, channel, 10);
-			rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
-			CmdID_End, 0, 0, 0);
-			break;
-
-		case RF_8258:
-			break;
 
-		default:
-			RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip);
+		// TEST!! This is not the table for 8256!!
+		if (!(channel >= 1 && channel <= 14))
+		{
+			RT_TRACE(COMP_ERR, "illegal channel for Zebra 8256: %d\n", channel);
 			return false;
-			break;
 		}
-
+		rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
+			CmdID_RF_WriteReg, rZebra1_Channel, channel, 10);
+		rtl8192_phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT,
+		CmdID_End, 0, 0, 0);
 
 		do{
 			switch(*stage)
@@ -2806,20 +1776,20 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8* s
 			{
 			case CmdID_SetTxPowerLevel:
 				if(priv->card_8192_version > (u8)VERSION_8190_BD) //xiong: consider it later!
-					rtl8192_SetTxPowerLevel(dev,channel);
+					rtl8192_SetTxPowerLevel(priv, channel);
 				break;
 			case CmdID_WritePortUlong:
-				write_nic_dword(dev, CurrentCmd->Para1, CurrentCmd->Para2);
+				write_nic_dword(priv, CurrentCmd->Para1, CurrentCmd->Para2);
 				break;
 			case CmdID_WritePortUshort:
-				write_nic_word(dev, CurrentCmd->Para1, (u16)CurrentCmd->Para2);
+				write_nic_word(priv, CurrentCmd->Para1, (u16)CurrentCmd->Para2);
 				break;
 			case CmdID_WritePortUchar:
-				write_nic_byte(dev, CurrentCmd->Para1, (u8)CurrentCmd->Para2);
+				write_nic_byte(priv, CurrentCmd->Para1, (u8)CurrentCmd->Para2);
 				break;
 			case CmdID_RF_WriteReg:
 				for(eRFPath = 0; eRFPath <priv->NumTotalRFPath; eRFPath++)
-					rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bMask12Bits, CurrentCmd->Para2<<7);
+					rtl8192_phy_SetRFReg(priv, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bMask12Bits, CurrentCmd->Para2<<7);
 				break;
 			default:
 				break;
@@ -2842,12 +1812,11 @@ static u8 rtl8192_phy_SwChnlStepByStep(struct net_device *dev, u8 channel, u8* s
  *  return:  noin
  *    Note:  We should not call this function directly
  * ***************************************************************************/
-static void rtl8192_phy_FinishSwChnlNow(struct net_device *dev, u8 channel)
+static void rtl8192_phy_FinishSwChnlNow(struct r8192_priv *priv, u8 channel)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u32	delay = 0;
 
-	while(!rtl8192_phy_SwChnlStepByStep(dev,channel,&priv->SwChnlStage,&priv->SwChnlStep,&delay))
+	while (!rtl8192_phy_SwChnlStepByStep(priv, channel, &priv->SwChnlStage, &priv->SwChnlStep, &delay))
 	{
 		if(delay>0)
 			msleep(delay);//or mdelay? need further consideration
@@ -2862,16 +1831,13 @@ static void rtl8192_phy_FinishSwChnlNow(struct net_device *dev, u8 channel)
  *  output:  none
  *  return:  noin
  * ***************************************************************************/
-void rtl8192_SwChnl_WorkItem(struct net_device *dev)
+void rtl8192_SwChnl_WorkItem(struct r8192_priv *priv)
 {
-
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	RT_TRACE(COMP_TRACE, "==> SwChnlCallback819xUsbWorkItem()\n");
 
 	RT_TRACE(COMP_TRACE, "=====>--%s(), set chan:%d, priv:%p\n", __FUNCTION__, priv->chan, priv);
 
-	rtl8192_phy_FinishSwChnlNow(dev , priv->chan);
+	rtl8192_phy_FinishSwChnlNow(priv, priv->chan);
 
 	RT_TRACE(COMP_TRACE, "<== SwChnlCallback819xUsbWorkItem()\n");
 }
@@ -2884,9 +1850,10 @@ void rtl8192_SwChnl_WorkItem(struct net_device *dev)
  *  return:  return code show if workitem is scheduled(1:pass, 0:fail)
  *    Note:  Delay may be required for RF configuration
  * ***************************************************************************/
-u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel)
+u8 rtl8192_phy_SwChnl(struct ieee80211_device *ieee80211, u8 channel)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee80211->dev);
+
 	RT_TRACE(COMP_PHY, "=====>%s()\n", __FUNCTION__);
         if(!priv->up)
 		return false;
@@ -2902,20 +1869,20 @@ u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel)
 	case WIRELESS_MODE_A:
 	case WIRELESS_MODE_N_5G:
 		if (channel<=14){
-			RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14");
+			RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14\n");
 			return false;
 		}
 		break;
 	case WIRELESS_MODE_B:
 		if (channel>14){
-			RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14");
+			RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14\n");
 			return false;
 		}
 		break;
 	case WIRELESS_MODE_G:
 	case WIRELESS_MODE_N_24G:
 		if (channel>14){
-			RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14");
+			RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14\n");
 			return false;
 		}
 		break;
@@ -2930,20 +1897,15 @@ u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel)
 
 	priv->SwChnlStage=0;
 	priv->SwChnlStep=0;
-//	schedule_work(&(priv->SwChnlWorkItem));
-//	rtl8192_SwChnl_WorkItem(dev);
-	if(priv->up) {
-//		queue_work(priv->priv_wq,&(priv->SwChnlWorkItem));
-	rtl8192_SwChnl_WorkItem(dev);
-	}
+	if (priv->up)
+		rtl8192_SwChnl_WorkItem(priv);
+
         priv->SwChnlInProgress = false;
 	return true;
 }
 
-static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev	)
+static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	switch(priv->CurrentChannelBW)
 	{
 		/* 20 MHz channel*/
@@ -2962,15 +1924,15 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev	)
 			if(priv->ieee80211->current_network.channel== 14 && !priv->bcck_in_ch14)
 			{
 				priv->bcck_in_ch14 = TRUE;
-				dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 			}
 			else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
 			{
 				priv->bcck_in_ch14 = FALSE;
-				dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 			}
 			else
-				dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 		break;
 
 		/* 40 MHz channel*/
@@ -2988,24 +1950,21 @@ static void CCK_Tx_Power_Track_BW_Switch_TSSI(struct net_device *dev	)
 			if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
 			{
 				priv->bcck_in_ch14 = TRUE;
-				dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 			}
 			else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
 			{
 				priv->bcck_in_ch14 = FALSE;
-				dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 			}
 			else
-				dm_cck_txpower_adjust(dev,priv->bcck_in_ch14);
+				dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 		break;
 	}
 }
 
-#ifndef RTL8190P
-static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct net_device *dev)
+static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct r8192_priv *priv)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
-
 	if(priv->ieee80211->current_network.channel == 14 && !priv->bcck_in_ch14)
 		priv->bcck_in_ch14 = TRUE;
 	else if(priv->ieee80211->current_network.channel != 14 && priv->bcck_in_ch14)
@@ -3028,25 +1987,17 @@ static void CCK_Tx_Power_Track_BW_Switch_ThermalMeter(struct net_device *dev)
 			RT_TRACE(COMP_POWER_TRACKING, "40MHz, CCK_Tx_Power_Track_BW_Switch_ThermalMeter(), CCK_index = %d\n", priv->CCK_index);
 		break;
 	}
-	dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+	dm_cck_txpower_adjust(priv, priv->bcck_in_ch14);
 }
-#endif
 
-static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev)
+static void CCK_Tx_Power_Track_BW_Switch(struct r8192_priv *priv)
 {
-#ifdef RTL8192E
-	struct r8192_priv *priv = ieee80211_priv(dev);
-#endif
 
-#ifdef RTL8190P
-	CCK_Tx_Power_Track_BW_Switch_TSSI(dev);
-#else
 	//if(pHalData->bDcut == TRUE)
 	if(priv->IC_Cut >= IC_VersionCut_D)
-		CCK_Tx_Power_Track_BW_Switch_TSSI(dev);
+		CCK_Tx_Power_Track_BW_Switch_TSSI(priv);
 	else
-		CCK_Tx_Power_Track_BW_Switch_ThermalMeter(dev);
-#endif
+		CCK_Tx_Power_Track_BW_Switch_ThermalMeter(priv);
 }
 
 
@@ -3061,41 +2012,34 @@ static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev)
  *    Note:  I doubt whether SetBWModeInProgress flag is necessary as we can
  *    	     test whether current work in the queue or not.//do I?
  * ***************************************************************************/
-void rtl8192_SetBWModeWorkItem(struct net_device *dev)
+void rtl8192_SetBWModeWorkItem(struct r8192_priv *priv)
 {
-
-	struct r8192_priv *priv = ieee80211_priv(dev);
 	u8 regBwOpMode;
 
 	RT_TRACE(COMP_SWBW, "==>rtl8192_SetBWModeWorkItem()  Switch to %s bandwidth\n",
 					priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20?"20MHz":"40MHz")
 
 
-	if(priv->rf_chip== RF_PSEUDO_11N)
-	{
-		priv->SetBWModeInProgress= false;
-		return;
-	}
 	if(!priv->up)
 	{
 		priv->SetBWModeInProgress= false;
 		return;
 	}
 	//<1>Set MAC register
-	regBwOpMode = read_nic_byte(dev, BW_OPMODE);
+	regBwOpMode = read_nic_byte(priv, BW_OPMODE);
 
 	switch(priv->CurrentChannelBW)
 	{
 		case HT_CHANNEL_WIDTH_20:
 			regBwOpMode |= BW_OPMODE_20MHZ;
 		       // 2007/02/07 Mark by Emily becasue we have not verify whether this register works
-			write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+			write_nic_byte(priv, BW_OPMODE, regBwOpMode);
 			break;
 
 		case HT_CHANNEL_WIDTH_20_40:
 			regBwOpMode &= ~BW_OPMODE_20MHZ;
         		// 2007/02/07 Mark by Emily becasue we have not verify whether this register works
-			write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+			write_nic_byte(priv, BW_OPMODE, regBwOpMode);
 			break;
 
 		default:
@@ -3108,8 +2052,8 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
 	{
 		case HT_CHANNEL_WIDTH_20:
 			// Add by Vivi 20071119
-			rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
-			rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
+			rtl8192_setBBreg(priv, rFPGA0_RFMOD, bRFMOD, 0x0);
+			rtl8192_setBBreg(priv, rFPGA1_RFMOD, bRFMOD, 0x0);
 //			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
 
 			// Correct the tx power for CCK rate in 20M. Suggest by YN, 20071207
@@ -3118,27 +2062,19 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
 //			write_nic_dword(dev, rCCK0_DebugPort, 0x00000204);
 			if(!priv->btxpower_tracking)
 			{
-				write_nic_dword(dev, rCCK0_TxFilter1, 0x1a1b0000);
-				write_nic_dword(dev, rCCK0_TxFilter2, 0x090e1317);
-				write_nic_dword(dev, rCCK0_DebugPort, 0x00000204);
+				write_nic_dword(priv, rCCK0_TxFilter1, 0x1a1b0000);
+				write_nic_dword(priv, rCCK0_TxFilter2, 0x090e1317);
+				write_nic_dword(priv, rCCK0_DebugPort, 0x00000204);
 			}
 			else
-				CCK_Tx_Power_Track_BW_Switch(dev);
-
-#ifdef RTL8190P
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bADClkPhase, 1);
-			rtl8192_setBBreg(dev, rOFDM0_RxDetector1, bMaskByte0, 0x44); 	// 0xc30 is for 8190 only, Emily
-#else
-	#ifdef RTL8192E
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
-	#endif
-#endif
+				CCK_Tx_Power_Track_BW_Switch(priv);
 
+			rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x00100000, 1);
 			break;
 		case HT_CHANNEL_WIDTH_20_40:
 			// Add by Vivi 20071119
-			rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
-			rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
+			rtl8192_setBBreg(priv, rFPGA0_RFMOD, bRFMOD, 0x1);
+			rtl8192_setBBreg(priv, rFPGA1_RFMOD, bRFMOD, 0x1);
 			//rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1));
                     //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
 			//rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC);
@@ -3149,37 +2085,19 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
 			//write_nic_dword(dev, rCCK0_DebugPort, 0x00000409);
 			if(!priv->btxpower_tracking)
 			{
-				write_nic_dword(dev, rCCK0_TxFilter1, 0x35360000);
-				write_nic_dword(dev, rCCK0_TxFilter2, 0x121c252e);
-				write_nic_dword(dev, rCCK0_DebugPort, 0x00000409);
+				write_nic_dword(priv, rCCK0_TxFilter1, 0x35360000);
+				write_nic_dword(priv, rCCK0_TxFilter2, 0x121c252e);
+				write_nic_dword(priv, rCCK0_DebugPort, 0x00000409);
 			}
 			else
-				CCK_Tx_Power_Track_BW_Switch(dev);
+				CCK_Tx_Power_Track_BW_Switch(priv);
 
 			// Set Control channel to upper or lower. These settings are required only for 40MHz
-			rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1));
-			rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC);
+			rtl8192_setBBreg(priv, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1));
+			rtl8192_setBBreg(priv, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC);
 
 
-#ifdef RTL8190P
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bADClkPhase, 0);
-			rtl8192_setBBreg(dev, rOFDM0_RxDetector1, bMaskByte0, 0x42);	// 0xc30 is for 8190 only, Emily
-
-			// Set whether CCK should be sent in upper or lower channel. Suggest by YN. 20071207
-			// It is set in Tx descriptor for 8192x series
-			if(priv->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER)
-			{
-				rtl8192_setBBreg(dev, rFPGA0_RFMOD, (BIT6|BIT5), 0x01);
-			}else if(priv->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER)
-			{
-				rtl8192_setBBreg(dev, rFPGA0_RFMOD, (BIT6|BIT5), 0x02);
-			}
-
-#else
-	#ifdef RTL8192E
-			rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
-	#endif
-#endif
+			rtl8192_setBBreg(priv, rFPGA0_AnalogParameter1, 0x00100000, 0);
 			break;
 		default:
 			RT_TRACE(COMP_ERR, "SetChannelBandwidth819xUsb(): unknown Bandwidth: %#X\n" ,priv->CurrentChannelBW);
@@ -3188,37 +2106,13 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
 	}
 	//Skip over setting of J-mode in BB register here. Default value is "None J mode". Emily 20070315
 
-#if 1
 	//<3>Set RF related register
-	switch( priv->rf_chip )
-	{
-		case RF_8225:
-#ifdef TO_DO_LIST
-			PHY_SetRF8225Bandwidth(Adapter, pHalData->CurrentChannelBW);
-#endif
-			break;
-
-		case RF_8256:
-			PHY_SetRF8256Bandwidth(dev, priv->CurrentChannelBW);
-			break;
+	PHY_SetRF8256Bandwidth(priv, priv->CurrentChannelBW);
 
-		case RF_8258:
-			// PHY_SetRF8258Bandwidth();
-			break;
-
-		case RF_PSEUDO_11N:
-			// Do Nothing
-			break;
-
-		default:
-			RT_TRACE(COMP_ERR, "Unknown RFChipID: %d\n", priv->rf_chip);
-			break;
-	}
-#endif
 	atomic_dec(&(priv->ieee80211->atm_swbw));
 	priv->SetBWModeInProgress= false;
 
-	RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()");
+	RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()\n");
 }
 
 /******************************************************************************
@@ -3231,9 +2125,9 @@ void rtl8192_SetBWModeWorkItem(struct net_device *dev)
  *    Note:  I doubt whether SetBWModeInProgress flag is necessary as we can
  *    	     test whether current work in the queue or not.//do I?
  * ***************************************************************************/
-void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH	Bandwidth, HT_EXTCHNL_OFFSET Offset)
+void rtl8192_SetBWMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset)
 {
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
 
 
 	if(priv->SetBWModeInProgress)
@@ -3253,16 +2147,16 @@ void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH	Bandwidth, HT_EX
 
 	//queue_work(priv->priv_wq, &(priv->SetBWModeWorkItem));
 	//	schedule_work(&(priv->SetBWModeWorkItem));
-	rtl8192_SetBWModeWorkItem(dev);
+	rtl8192_SetBWModeWorkItem(priv);
 
 }
 
 
-void InitialGain819xPci(struct net_device *dev, u8 Operation)
+void InitialGain819xPci(struct ieee80211_device *ieee, u8 Operation)
 {
 #define SCAN_RX_INITIAL_GAIN	0x17
 #define POWER_DETECTION_TH	0x08
-	struct r8192_priv *priv = ieee80211_priv(dev);
+	struct r8192_priv *priv = ieee80211_priv(ieee->dev);
 	u32					BitMask;
 	u8					initial_gain;
 
@@ -3275,13 +2169,13 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
 				initial_gain = SCAN_RX_INITIAL_GAIN;//pHalData->DefaultInitialGain[0];//
 				BitMask = bMaskByte0;
 				if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
-					rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	// FW DIG OFF
-				priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, BitMask);
-				priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, BitMask);
-				priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, BitMask);
-				priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, BitMask);
+					rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8);	// FW DIG OFF
+				priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XAAGCCore1, BitMask);
+				priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XBAGCCore1, BitMask);
+				priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XCAGCCore1, BitMask);
+				priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(priv, rOFDM0_XDAGCCore1, BitMask);
 				BitMask  = bMaskByte2;
-				priv->initgain_backup.cca		= (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, BitMask);
+				priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(priv, rCCK0_CCA, BitMask);
 
 			RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
 			RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
@@ -3290,25 +2184,25 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
 			RT_TRACE(COMP_SCAN, "Scan InitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca);
 
 			RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x \n", initial_gain);
-				write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
-				write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
-				write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
-				write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+				write_nic_byte(priv, rOFDM0_XAAGCCore1, initial_gain);
+				write_nic_byte(priv, rOFDM0_XBAGCCore1, initial_gain);
+				write_nic_byte(priv, rOFDM0_XCAGCCore1, initial_gain);
+				write_nic_byte(priv, rOFDM0_XDAGCCore1, initial_gain);
 				RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x \n", POWER_DETECTION_TH);
-				write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH);
+				write_nic_byte(priv, 0xa0a, POWER_DETECTION_TH);
 				break;
 			case IG_Restore:
 			RT_TRACE(COMP_SCAN, "IG_Restore, restore the initial gain.\n");
 				BitMask = 0x7f; //Bit0~ Bit6
 				if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
-					rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);	// FW DIG OFF
+					rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x8);	// FW DIG OFF
 
-				rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, BitMask, (u32)priv->initgain_backup.xaagccore1);
-				rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, BitMask, (u32)priv->initgain_backup.xbagccore1);
-				rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, BitMask, (u32)priv->initgain_backup.xcagccore1);
-				rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, BitMask, (u32)priv->initgain_backup.xdagccore1);
+				rtl8192_setBBreg(priv, rOFDM0_XAAGCCore1, BitMask, (u32)priv->initgain_backup.xaagccore1);
+				rtl8192_setBBreg(priv, rOFDM0_XBAGCCore1, BitMask, (u32)priv->initgain_backup.xbagccore1);
+				rtl8192_setBBreg(priv, rOFDM0_XCAGCCore1, BitMask, (u32)priv->initgain_backup.xcagccore1);
+				rtl8192_setBBreg(priv, rOFDM0_XDAGCCore1, BitMask, (u32)priv->initgain_backup.xdagccore1);
 				BitMask  = bMaskByte2;
-				rtl8192_setBBreg(dev, rCCK0_CCA, BitMask, (u32)priv->initgain_backup.cca);
+				rtl8192_setBBreg(priv, rCCK0_CCA, BitMask, (u32)priv->initgain_backup.cca);
 
 			RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1);
 			RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1);
@@ -3316,14 +2210,14 @@ void InitialGain819xPci(struct net_device *dev, u8 Operation)
 			RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1);
 			RT_TRACE(COMP_SCAN, "Scan BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca);
 
-				rtl8192_phy_setTxPower(dev,priv->ieee80211->current_network.channel);
+				rtl8192_phy_setTxPower(priv, priv->ieee80211->current_network.channel);
 
 
 				if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
-					rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);	// FW DIG ON
+					rtl8192_setBBreg(priv, UFWP, bMaskByte1, 0x1);	// FW DIG ON
 				break;
 			default:
-			RT_TRACE(COMP_SCAN, "Unknown IG Operation. \n");
+			RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n");
 				break;
 		}
 	}
diff --git a/drivers/staging/rtl8192e/r819xE_phy.h b/drivers/staging/rtl8192e/r819xE_phy.h
index 95a509f..496e76f 100644
--- a/drivers/staging/rtl8192e/r819xE_phy.h
+++ b/drivers/staging/rtl8192e/r819xE_phy.h
@@ -6,25 +6,6 @@
 #define MAX_RFDEPENDCMD_CNT 16
 #define MAX_POSTCMD_CNT 16
 
-#ifdef RTL8190P
-#define MACPHY_Array_PGLength 21
-#define Rtl819XMACPHY_Array_PG Rtl8190PciMACPHY_Array_PG
-#define Rtl819XMACPHY_Array Rtl8190PciMACPHY_Array
-#define RadioC_ArrayLength 246
-#define RadioD_ArrayLength 78
-#define Rtl819XRadioA_Array Rtl8190PciRadioA_Array
-#define Rtl819XRadioB_Array Rtl8190PciRadioB_Array
-#define Rtl819XRadioC_Array Rtl8190PciRadioC_Array
-#define Rtl819XRadioD_Array Rtl8190PciRadioD_Array
-#define Rtl819XAGCTAB_Array Rtl8190PciAGCTAB_Array
-#define PHY_REGArrayLength 280
-#define Rtl819XPHY_REGArray Rtl8190PciPHY_REGArray
-#define PHY_REG_1T2RArrayLength 280
-#define Rtl819XPHY_REG_1T2RArray Rtl8190PciPHY_REG_1T2RArray
-#endif
-
-
-#ifdef RTL8192E
 #define MACPHY_Array_PGLength 30
 #define Rtl819XMACPHY_Array_PG Rtl8192PciEMACPHY_Array_PG
 #define Rtl819XMACPHY_Array Rtl8192PciEMACPHY_Array
@@ -39,7 +20,6 @@
 #define Rtl819XPHY_REGArray Rtl8192PciEPHY_REGArray
 #define PHY_REG_1T2RArrayLength 296
 #define Rtl819XPHY_REG_1T2RArray Rtl8192PciEPHY_REG_1T2RArray
-#endif
 
 #define AGCTAB_ArrayLength 384
 #define MACPHY_ArrayLength 18
@@ -102,50 +82,50 @@ typedef enum _RF90_RADIO_PATH {
 #define bMaskLWord 0x0000ffff
 #define bMaskDWord 0xffffffff
 
-u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
+u8 rtl8192_phy_CheckIsLegalRFPath(struct r8192_priv *priv, u32 eRFPath);
 
-void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr,
+void rtl8192_setBBreg(struct r8192_priv *priv, u32 dwRegAddr,
 			     u32 dwBitMask, u32 dwData);
 
-u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr,
+u32 rtl8192_QueryBBReg(struct r8192_priv *priv, u32 dwRegAddr,
 			     u32 dwBitMask);
 
-void rtl8192_phy_SetRFReg(struct net_device *dev,
+void rtl8192_phy_SetRFReg(struct r8192_priv *priv,
 		RF90_RADIO_PATH_E eRFPath, u32 RegAddr,
 		u32 BitMask, u32 Data);
 
-u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
+u32 rtl8192_phy_QueryRFReg(struct r8192_priv *priv,
 		RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
 
-void rtl8192_phy_configmac(struct net_device *dev);
+void rtl8192_phy_configmac(struct r8192_priv *priv);
 
-void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
+void rtl8192_phyConfigBB(struct r8192_priv *priv, u8 ConfigType);
 
-RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device *dev,
+RT_STATUS rtl8192_phy_checkBBAndRF(struct r8192_priv *priv,
 		HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
 
-RT_STATUS rtl8192_BBConfig(struct net_device *dev);
+RT_STATUS rtl8192_BBConfig(struct r8192_priv *priv);
 
-void rtl8192_phy_getTxPower(struct net_device *dev);
+void rtl8192_phy_getTxPower(struct r8192_priv *priv);
 
-void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
+void rtl8192_phy_setTxPower(struct r8192_priv *priv, u8 channel);
 
-RT_STATUS rtl8192_phy_RFConfig(struct net_device* dev);
+RT_STATUS rtl8192_phy_RFConfig(struct r8192_priv *priv);
 
-void rtl8192_phy_updateInitGain(struct net_device* dev);
+void rtl8192_phy_updateInitGain(struct r8192_priv *priv);
 
-u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+u8 rtl8192_phy_ConfigRFWithHeaderFile(struct r8192_priv *priv,
 					RF90_RADIO_PATH_E eRFPath);
 
-u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
+u8 rtl8192_phy_SwChnl(struct ieee80211_device *ieee80211, u8 channel);
 
-void rtl8192_SetBWMode(struct net_device *dev,
+void rtl8192_SetBWMode(struct ieee80211_device *ieee80211,
 		HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
 
-void rtl8192_SwChnl_WorkItem(struct net_device *dev);
+void rtl8192_SwChnl_WorkItem(struct r8192_priv *priv);
 
-void rtl8192_SetBWModeWorkItem(struct net_device *dev);
+void rtl8192_SetBWModeWorkItem(struct r8192_priv *priv);
 
-void InitialGain819xPci(struct net_device *dev, u8 Operation);
+void InitialGain819xPci(struct ieee80211_device *ieee, u8 Operation);
 
 #endif /* _R819XU_PHY_H */
diff --git a/drivers/staging/rtl8192u/ieee80211/cipher.c b/drivers/staging/rtl8192u/ieee80211/cipher.c
index 0b9e8a4..69dcc31 100644
--- a/drivers/staging/rtl8192u/ieee80211/cipher.c
+++ b/drivers/staging/rtl8192u/ieee80211/cipher.c
@@ -294,6 +294,5 @@ out:
 
 void crypto_exit_cipher_ops(struct crypto_tfm *tfm)
 {
-	if (tfm->crt_cipher.cit_iv)
-		kfree(tfm->crt_cipher.cit_iv);
+	kfree(tfm->crt_cipher.cit_iv);
 }
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index 7455264..fe978f3 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -198,11 +198,8 @@ void free_ieee80211(struct net_device *dev)
 	int i;
 	//struct list_head *p, *q;
 //	del_timer_sync(&ieee->SwBwTimer);
-	if (ieee->pHTInfo != NULL)
-	{
-		kfree(ieee->pHTInfo);
-		ieee->pHTInfo = NULL;
-	}
+	kfree(ieee->pHTInfo);
+	ieee->pHTInfo = NULL;
 	RemoveAllTS(ieee);
 	ieee80211_softmac_free(ieee);
 	del_timer_sync(&ieee->crypt_deinit_timer);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 1ea8da3..498b520 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -1384,11 +1384,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 	return 1;
 
  rx_dropped:
-	if (rxb != NULL)
-	{
-		kfree(rxb);
-		rxb = NULL;
-	}
+	kfree(rxb);
+	rxb = NULL;
 	stats->rx_dropped++;
 
 	/* Returning 0 indicates to caller that we have not handled the SKB--
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 20f8c34..4992d63 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -2755,11 +2755,8 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
 void ieee80211_softmac_free(struct ieee80211_device *ieee)
 {
 	down(&ieee->wx_sem);
-	if(NULL != ieee->pDot11dInfo)
-	{
-		kfree(ieee->pDot11dInfo);
-		ieee->pDot11dInfo = NULL;
-	}
+	kfree(ieee->pDot11dInfo);
+	ieee->pDot11dInfo = NULL;
 	del_timer_sync(&ieee->associate_timer);
 
 	cancel_delayed_work(&ieee->associate_retry_wq);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
index d6f55c2..f0ba7f4 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
@@ -855,7 +855,6 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len)
 		ieee->wpa_ie_len = len;
 	}
 	else{
-		if (ieee->wpa_ie)
 		kfree(ieee->wpa_ie);
 		ieee->wpa_ie = NULL;
 		ieee->wpa_ie_len = 0;
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index 6206f92..0205079 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -461,11 +461,6 @@ typedef enum _desc_packet_type_e{
 	DESC_PACKET_TYPE_NORMAL = 1,
 }desc_packet_type_e;
 
-typedef enum _firmware_source{
-	FW_SOURCE_IMG_FILE = 0,
-	FW_SOURCE_HEADER_FILE = 1,		//from header file
-}firmware_source_e, *pfirmware_source_e;
-
 typedef enum _firmware_status{
 	FW_STATUS_0_INIT = 0,
 	FW_STATUS_1_MOVE_BOOT_CODE = 1,
@@ -1026,7 +1021,6 @@ typedef struct r8192_priv
 	u8 Rf_Mode; //add for Firmware RF -R/W switch
 	prt_firmware		pFirmware;
 	rtl819xUsb_loopback_e	LoopbackMode;
-	firmware_source_e	firmware_source;
 	u16 EEPROMTxPowerDiff;
 	u8 EEPROMThermalMeter;
 	u8 EEPROMPwDiff;
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index ae4f2b9..da612e6 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -2242,12 +2242,8 @@ short rtl8192_usb_initendpoints(struct net_device *dev)
 
 
 destroy:
-	if (priv->pp_rxskb) {
-		kfree(priv->pp_rxskb);
-	}
-	if (priv->rx_urb) {
-		kfree(priv->rx_urb);
-	}
+	kfree(priv->pp_rxskb);
+	kfree(priv->rx_urb);
 
 	priv->pp_rxskb = NULL;
 	priv->rx_urb = NULL;
@@ -2276,10 +2272,8 @@ void rtl8192_usb_deleteendpoints(struct net_device *dev)
 		kfree(priv->rx_urb);
 		priv->rx_urb = NULL;
 	}
-	if(priv->oldaddr){
-		kfree(priv->oldaddr);
-		priv->oldaddr = NULL;
-	}
+	kfree(priv->oldaddr);
+	priv->oldaddr = NULL;
 	if (priv->pp_rxskb) {
 		kfree(priv->pp_rxskb);
 		priv->pp_rxskb = 0;
@@ -2304,14 +2298,10 @@ void rtl8192_usb_deleteendpoints(struct net_device *dev)
 
 	}
 #else
-	if(priv->rx_urb){
-		kfree(priv->rx_urb);
-		priv->rx_urb = NULL;
-	}
-	if(priv->oldaddr){
-		kfree(priv->oldaddr);
-		priv->oldaddr = NULL;
-	}
+	kfree(priv->rx_urb);
+	priv->rx_urb = NULL;
+	kfree(priv->oldaddr);
+	priv->oldaddr = NULL;
 	if (priv->pp_rxskb) {
 		kfree(priv->pp_rxskb);
 		priv->pp_rxskb = 0;
@@ -5828,10 +5818,8 @@ static int __devinit rtl8192_usb_probe(struct usb_interface *intf,
 
 fail2:
 	rtl8192_down(dev);
-	if (priv->pFirmware) {
-		kfree(priv->pFirmware);
-		priv->pFirmware = NULL;
-	}
+	kfree(priv->pFirmware);
+	priv->pFirmware = NULL;
 	rtl8192_usb_deleteendpoints(dev);
 	destroy_workqueue(priv->priv_wq);
 	mdelay(10);
@@ -5869,11 +5857,8 @@ static void __devexit rtl8192_usb_disconnect(struct usb_interface *intf)
 		rtl8192_proc_remove_one(dev);
 
 			rtl8192_down(dev);
-		if (priv->pFirmware)
-		{
-			kfree(priv->pFirmware);
-			priv->pFirmware = NULL;
-		}
+		kfree(priv->pFirmware);
+		priv->pFirmware = NULL;
 	//	priv->rf_close(dev);
 //		rtl8192_SetRFPowerState(dev, eRfOff);
 		rtl8192_usb_deleteendpoints(dev);
diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index 49ae170..6766f46 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -244,13 +244,6 @@ bool init_firmware(struct net_device *dev)
 	struct r8192_priv 	*priv = ieee80211_priv(dev);
 	bool			rt_status = TRUE;
 
-	u8			*firmware_img_buf[3] = { &rtl8190_fwboot_array[0],
-							 &rtl8190_fwmain_array[0],
-							 &rtl8190_fwdata_array[0]};
-
-	u32			firmware_img_len[3] = { sizeof(rtl8190_fwboot_array),
-							sizeof(rtl8190_fwmain_array),
-							sizeof(rtl8190_fwdata_array)};
 	u32			file_length = 0;
 	u8			*mapped_file = NULL;
 	u32			init_step = 0;
@@ -284,59 +277,40 @@ bool init_firmware(struct net_device *dev)
 	 * Download boot, main, and data image for System reset.
 	 * Download data image for firmware reseta
 	 */
-	priv->firmware_source = FW_SOURCE_IMG_FILE;
 	for(init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
 		/*
 		 * Open Image file, and map file to contineous memory if open file success.
 		 * or read image file from array. Default load from IMG file
 		 */
 		if(rst_opt == OPT_SYSTEM_RESET) {
-			switch(priv->firmware_source) {
-				case FW_SOURCE_IMG_FILE:
-					rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
-					if(rc < 0 ) {
-						RT_TRACE(COMP_ERR, "request firmware fail!\n");
-						goto download_firmware_fail;
-					}
-
-					if(fw_entry->size > sizeof(pfirmware->firmware_buf)) {
-						RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
-						goto download_firmware_fail;
-					}
-
-					if(init_step != FW_INIT_STEP1_MAIN) {
-						memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
-						mapped_file = pfirmware->firmware_buf;
-						file_length = fw_entry->size;
-					} else {
-					#ifdef RTL8190P
-						memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
-						mapped_file = pfirmware->firmware_buf;
-						file_length = fw_entry->size;
-					#else
-						memset(pfirmware->firmware_buf,0,128);
-						memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
-						mapped_file = pfirmware->firmware_buf;
-						file_length = fw_entry->size + 128;
-					#endif
-					}
-					pfirmware->firmware_buf_size = file_length;
-					break;
-
-				case FW_SOURCE_HEADER_FILE:
-					mapped_file =  firmware_img_buf[init_step];
-					file_length  = firmware_img_len[init_step];
-					if(init_step == FW_INIT_STEP2_DATA) {
-						memcpy(pfirmware->firmware_buf, mapped_file, file_length);
-						pfirmware->firmware_buf_size = file_length;
-					}
-					break;
-
-				default:
-					break;
+			rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
+			if(rc < 0 ) {
+				RT_TRACE(COMP_ERR, "request firmware fail!\n");
+				goto download_firmware_fail;
 			}
 
+			if(fw_entry->size > sizeof(pfirmware->firmware_buf)) {
+				RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
+				goto download_firmware_fail;
+			}
 
+			if(init_step != FW_INIT_STEP1_MAIN) {
+				memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
+				mapped_file = pfirmware->firmware_buf;
+				file_length = fw_entry->size;
+			} else {
+#ifdef RTL8190P
+				memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
+				mapped_file = pfirmware->firmware_buf;
+				file_length = fw_entry->size;
+#else
+				memset(pfirmware->firmware_buf,0,128);
+				memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
+				mapped_file = pfirmware->firmware_buf;
+				file_length = fw_entry->size + 128;
+#endif
+			}
+			pfirmware->firmware_buf_size = file_length;
 		}else if(rst_opt == OPT_FIRMWARE_RESET ) {
 			/* we only need to download data.img here */
 			mapped_file = pfirmware->firmware_buf;
diff --git a/drivers/staging/rtl8192u/r819xU_firmware_img.c b/drivers/staging/rtl8192u/r819xU_firmware_img.c
index 29b656d..df0f9d1 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware_img.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware_img.c
@@ -1,2906 +1,6 @@
 /*Created on  2008/ 7/16,  5:31*/
 #include <linux/types.h>
 
-u8 rtl8190_fwboot_array[] = {
-0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x3c,0x08,0xbf,0xc0,0x25,0x08,0x00,0x08,
-0x3c,0x09,0xb0,0x03,0xad,0x28,0x00,0x20,0x40,0x80,0x68,0x00,0x00,0x00,0x00,0x00,
-0x3c,0x0a,0xd0,0x00,0x40,0x8a,0x60,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x01,
-0x25,0x08,0xb0,0x50,0x24,0x09,0x00,0x01,0x3c,0x01,0x7f,0xff,0x34,0x21,0xff,0xff,
-0x01,0x01,0x50,0x24,0x00,0x09,0x48,0x40,0x35,0x29,0x00,0x01,0x01,0x2a,0x10,0x2b,
-0x14,0x40,0xff,0xfc,0x00,0x00,0x00,0x00,0x3c,0x0a,0x00,0x00,0x25,0x4a,0x00,0x00,
-0x4c,0x8a,0x00,0x00,0x4c,0x89,0x08,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x01,
-0x25,0x08,0xb0,0x50,0x3c,0x01,0x80,0x00,0x01,0x21,0x48,0x25,0x3c,0x0a,0xbf,0xc0,
-0x25,0x4a,0x00,0x7c,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0xad,0x00,0x00,0x00,
-0x21,0x08,0x00,0x04,0x01,0x09,0x10,0x2b,0x14,0x40,0xff,0xf8,0x00,0x00,0x00,0x00,
-0x3c,0x08,0x80,0x01,0x25,0x08,0x7f,0xff,0x24,0x09,0x00,0x01,0x3c,0x01,0x7f,0xff,
-0x34,0x21,0xff,0xff,0x01,0x01,0x50,0x24,0x00,0x09,0x48,0x40,0x35,0x29,0x00,0x01,
-0x01,0x2a,0x10,0x2b,0x14,0x40,0xff,0xfc,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x01,
-0x25,0x4a,0x00,0x00,0x3c,0x01,0x7f,0xff,0x34,0x21,0xff,0xff,0x01,0x41,0x50,0x24,
-0x3c,0x09,0x00,0x01,0x35,0x29,0x7f,0xff,0x4c,0x8a,0x20,0x00,0x4c,0x89,0x28,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x08,0x04,0x10,
-0x00,0x00,0x00,0x00,0x40,0x88,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x3c,0x08,0xbf,0xc0,0x00,0x00,0x00,0x00,0x8d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,
-0x3c,0x0a,0xbf,0xc0,0x25,0x4a,0x01,0x20,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,
-0x3c,0x08,0xb0,0x03,0x8d,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x35,0x29,0x00,0x10,
-0xad,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x08,0x80,0x00,0x25,0x08,0x4b,0x84,
-0x01,0x00,0x00,0x08,0x00,0x00,0x00,0x00,};
-
-u8 rtl8190_fwmain_array[] = {
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x40,0x04,0x68,0x00,0x40,0x05,0x70,0x00,0x40,0x06,0x40,0x00,0x0c,0x00,0x12,0x94,
-0x00,0x00,0x00,0x00,0x40,0x1a,0x68,0x00,0x33,0x5b,0x00,0x3c,0x17,0x60,0x00,0x09,
-0x00,0x00,0x00,0x00,0x40,0x1b,0x60,0x00,0x00,0x00,0x00,0x00,0x03,0x5b,0xd0,0x24,
-0x40,0x1a,0x70,0x00,0x03,0x40,0x00,0x08,0x42,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff,0x34,0x42,0xff,0xff,0x8c,0x43,0x00,0x00,
-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x00,0xd0,
-0xac,0x62,0x00,0x00,0x00,0x00,0x20,0x21,0x27,0x85,0x8b,0x60,0x00,0x85,0x18,0x21,
-0x24,0x84,0x00,0x01,0x28,0x82,0x00,0x0a,0x14,0x40,0xff,0xfc,0xa0,0x60,0x00,0x00,
-0x27,0x82,0x8b,0x6a,0x24,0x04,0x00,0x06,0x24,0x84,0xff,0xff,0xa4,0x40,0x00,0x00,
-0x04,0x81,0xff,0xfd,0x24,0x42,0x00,0x02,0x24,0x02,0x00,0x03,0xa3,0x82,0x8b,0x60,
-0x24,0x02,0x09,0xc4,0x24,0x03,0x01,0x00,0xa7,0x82,0x8b,0x76,0x24,0x02,0x04,0x00,
-0xaf,0x83,0x8b,0x78,0xaf,0x82,0x8b,0x7c,0x24,0x03,0x00,0x0a,0x24,0x02,0x00,0x04,
-0x24,0x05,0x00,0x02,0x24,0x04,0x00,0x01,0xa3,0x83,0x8b,0x62,0xa3,0x82,0x8b,0x68,
-0x24,0x03,0x00,0x01,0x24,0x02,0x02,0x00,0xa3,0x84,0x8b,0x66,0xa3,0x85,0x8b,0x69,
-0xa7,0x82,0x8b,0x6a,0xa7,0x83,0x8b,0x6c,0xa3,0x84,0x8b,0x61,0xa3,0x80,0x8b,0x63,
-0xa3,0x80,0x8b,0x64,0xa3,0x80,0x8b,0x65,0xa3,0x85,0x8b,0x67,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x01,0x84,
-0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x27,0x84,0x8b,0x88,0x00,0x00,0x10,0x21,
-0x24,0x42,0x00,0x01,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03,0x28,0x43,0x00,0x03,
-0xac,0x80,0xff,0xfc,0xa0,0x80,0x00,0x00,0x14,0x60,0xff,0xf9,0x24,0x84,0x00,0x0c,
-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x34,0x63,0x00,0x20,0x24,0x42,0x01,0xc8,0x3c,0x08,0xb0,0x03,0xac,0x62,0x00,0x00,
-0x35,0x08,0x00,0x70,0x8d,0x02,0x00,0x00,0x00,0xa0,0x48,0x21,0x00,0x04,0x26,0x00,
-0x00,0x02,0x2a,0x43,0x00,0x06,0x36,0x00,0x00,0x07,0x3e,0x00,0x00,0x02,0x12,0x03,
-0x29,0x23,0x00,0x03,0x00,0x04,0x56,0x03,0x00,0x06,0x36,0x03,0x00,0x07,0x3e,0x03,
-0x30,0x48,0x00,0x01,0x10,0x60,0x00,0x11,0x30,0xa5,0x00,0x07,0x24,0x02,0x00,0x02,
-0x00,0x49,0x10,0x23,0x00,0x45,0x10,0x07,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x66,
-0x00,0x00,0x00,0x00,0x8f,0xa2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x02,0x21,0x43,
-0x11,0x00,0x00,0x10,0x00,0x07,0x20,0x0b,0x15,0x20,0x00,0x06,0x24,0x02,0x00,0x01,
-0x3c,0x02,0xb0,0x05,0x34,0x42,0x01,0x20,0xa4,0x44,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x11,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,
-0x08,0x00,0x00,0x96,0x34,0x42,0x01,0x24,0x3c,0x02,0xb0,0x05,0x08,0x00,0x00,0x96,
-0x34,0x42,0x01,0x22,0x15,0x20,0x00,0x54,0x24,0x02,0x00,0x01,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0x74,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0x84,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x70,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x6b,0x00,0x08,0x11,0x60,0x00,0x18,0x00,0x09,0x28,0x40,0x00,0x00,0x40,0x21,
-0x27,0x85,0x8b,0x80,0x8c,0xa3,0x00,0x00,0x8c,0xa2,0x00,0x04,0x00,0x00,0x00,0x00,
-0x00,0x62,0x38,0x23,0x00,0x43,0x10,0x2a,0x10,0x40,0x00,0x3d,0x00,0x00,0x00,0x00,
-0xac,0xa7,0x00,0x00,0x25,0x02,0x00,0x01,0x00,0x02,0x16,0x00,0x00,0x02,0x46,0x03,
-0x29,0x03,0x00,0x03,0x14,0x60,0xff,0xf3,0x24,0xa5,0x00,0x0c,0x3c,0x03,0xb0,0x03,
-0x34,0x63,0x00,0x70,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4b,0x10,0x23,
-0xa0,0x62,0x00,0x00,0x00,0x09,0x28,0x40,0x00,0xa9,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x8b,0x88,0x00,0x0a,0x20,0x0b,0x00,0x43,0x18,0x21,0x10,0xc0,0x00,0x05,
-0x00,0x00,0x38,0x21,0x80,0x62,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05,
-0x00,0x00,0x00,0x00,0x80,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,
-0x00,0xa9,0x10,0x21,0x24,0x07,0x00,0x01,0x00,0xa9,0x10,0x21,0x00,0x02,0x30,0x80,
-0x27,0x82,0x8b,0x88,0xa0,0x67,0x00,0x01,0x00,0xc2,0x38,0x21,0x80,0xe3,0x00,0x01,
-0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x07,0x00,0x00,0x00,0x00,0x27,0x83,0x8b,0x80,
-0x00,0xc3,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x21,
-0xac,0x62,0x00,0x00,0x27,0x85,0x8b,0x84,0x27,0x82,0x8b,0x80,0x00,0xc5,0x28,0x21,
-0x00,0xc2,0x10,0x21,0x8c,0x43,0x00,0x00,0x8c,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x64,0x18,0x2a,0x14,0x60,0x00,0x03,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,
-0xa0,0xe2,0x00,0x00,0xa0,0xe0,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x00,0x00,0xb9,0xac,0xa0,0x00,0x00,0x11,0x22,0x00,0x08,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x7c,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,
-0xaf,0x83,0x8b,0x9c,0x08,0x00,0x00,0xa9,0x3c,0x02,0xb0,0x03,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0x78,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x83,0x8b,0x90,
-0x08,0x00,0x00,0xa9,0x3c,0x02,0xb0,0x03,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x34,0x63,0x00,0x20,0x24,0x42,0x04,0x18,0x3c,0x05,0xb0,0x03,0xac,0x62,0x00,0x00,
-0x34,0xa5,0x00,0x70,0x8c,0xa2,0x00,0x00,0x90,0x84,0x00,0x08,0x3c,0x06,0xb0,0x03,
-0x00,0x02,0x16,0x00,0x2c,0x83,0x00,0x03,0x34,0xc6,0x00,0x72,0x24,0x07,0x00,0x01,
-0x10,0x60,0x00,0x11,0x00,0x02,0x2f,0xc2,0x90,0xc2,0x00,0x00,0x00,0x00,0x18,0x21,
-0x00,0x02,0x16,0x00,0x10,0xa7,0x00,0x09,0x00,0x02,0x16,0x03,0x14,0x80,0x00,0x0c,
-0x30,0x43,0x00,0x03,0x83,0x82,0x8b,0x88,0x00,0x00,0x00,0x00,0x00,0x02,0x10,0x80,
-0x00,0x43,0x10,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x1e,0x03,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0x72,0xa0,0x43,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x30,0x45,0x00,0x05,0x10,0x87,0x00,0x04,0x30,0x43,0x00,0x06,0x93,0x82,0x8b,0xa0,
-0x08,0x00,0x01,0x21,0x00,0x43,0x10,0x21,0x83,0x82,0x8b,0x94,0x00,0x00,0x00,0x00,
-0x00,0x02,0x10,0x40,0x08,0x00,0x01,0x21,0x00,0x45,0x10,0x21,0x10,0x80,0x00,0x05,
-0x00,0x00,0x18,0x21,0x24,0x63,0x00,0x01,0x00,0x64,0x10,0x2b,0x14,0x40,0xff,0xfd,
-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,
-0x3c,0x02,0x80,0x00,0x24,0x42,0x04,0xec,0x3c,0x04,0xb0,0x02,0x34,0x63,0x00,0x20,
-0xac,0x62,0x00,0x00,0x34,0x84,0x00,0x08,0x24,0x02,0x00,0x01,0xaf,0x84,0x8b,0xb0,
-0xa3,0x82,0x8b,0xc0,0xa7,0x80,0x8b,0xb4,0xa7,0x80,0x8b,0xb6,0xaf,0x80,0x8b,0xb8,
-0xaf,0x80,0x8b,0xbc,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,
-0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x05,0x2c,0x3c,0x04,0xb0,0x03,
-0xac,0x62,0x00,0x00,0x34,0x84,0x00,0xac,0x80,0xa2,0x00,0x15,0x8c,0x83,0x00,0x00,
-0x27,0xbd,0xff,0xf0,0x00,0x43,0x10,0x21,0xac,0x82,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x10,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0x34,0x42,0x00,0x20,
-0x24,0x63,0x05,0x64,0x27,0xbd,0xff,0xe0,0xac,0x43,0x00,0x00,0xaf,0xb1,0x00,0x14,
-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x18,0x8f,0x90,0x8b,0xb0,0x0c,0x00,0x02,0x9a,
-0x00,0x80,0x88,0x21,0x14,0x40,0x00,0x2a,0x3c,0x02,0x00,0x80,0x16,0x20,0x00,0x02,
-0x34,0x42,0x02,0x01,0x24,0x02,0x02,0x01,0xae,0x02,0x00,0x00,0x97,0x84,0x8b,0xb4,
-0x97,0x82,0x8b,0xb6,0x3c,0x03,0xb0,0x02,0x00,0x83,0x20,0x21,0x24,0x42,0x00,0x04,
-0xa7,0x82,0x8b,0xb6,0xa4,0x82,0x00,0x00,0x8f,0x84,0x8b,0xb8,0x8f,0x82,0x8b,0xb0,
-0x93,0x85,0x8b,0x62,0x24,0x84,0x00,0x01,0x24,0x42,0x00,0x04,0x24,0x03,0x8f,0xff,
-0x3c,0x07,0xb0,0x06,0x3c,0x06,0xb0,0x03,0x00,0x43,0x10,0x24,0x00,0x85,0x28,0x2a,
-0x34,0xe7,0x80,0x18,0xaf,0x82,0x8b,0xb0,0xaf,0x84,0x8b,0xb8,0x10,0xa0,0x00,0x08,
-0x34,0xc6,0x01,0x08,0x8f,0x83,0x8b,0xbc,0x8f,0x84,0x8b,0x7c,0x8c,0xc2,0x00,0x00,
-0x00,0x64,0x18,0x21,0x00,0x43,0x10,0x2b,0x14,0x40,0x00,0x09,0x00,0x00,0x00,0x00,
-0x8c,0xe2,0x00,0x00,0x3c,0x03,0x0f,0x00,0x3c,0x04,0x04,0x00,0x00,0x43,0x10,0x24,
-0x10,0x44,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,
-0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,
-0x27,0xbd,0xff,0xd8,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0x24,0x63,0x06,0x50,
-0xaf,0xb0,0x00,0x10,0x34,0x42,0x00,0x20,0x8f,0x90,0x8b,0xb0,0xac,0x43,0x00,0x00,
-0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,
-0x00,0x80,0x88,0x21,0x00,0xa0,0x90,0x21,0x0c,0x00,0x02,0x9a,0x00,0xc0,0x98,0x21,
-0x24,0x07,0x8f,0xff,0x14,0x40,0x00,0x19,0x26,0x03,0x00,0x04,0x24,0x02,0x0e,0x03,
-0xae,0x02,0x00,0x00,0x00,0x67,0x80,0x24,0x26,0x02,0x00,0x04,0xae,0x11,0x00,0x00,
-0x00,0x47,0x80,0x24,0x97,0x86,0x8b,0xb4,0x26,0x03,0x00,0x04,0xae,0x12,0x00,0x00,
-0x00,0x67,0x80,0x24,0xae,0x13,0x00,0x00,0x8f,0x84,0x8b,0xb0,0x3c,0x02,0xb0,0x02,
-0x97,0x85,0x8b,0xb6,0x00,0xc2,0x30,0x21,0x8f,0x82,0x8b,0xb8,0x24,0x84,0x00,0x10,
-0x24,0xa5,0x00,0x10,0x00,0x87,0x20,0x24,0x24,0x42,0x00,0x01,0xa7,0x85,0x8b,0xb6,
-0xaf,0x84,0x8b,0xb0,0xaf,0x82,0x8b,0xb8,0xa4,0xc5,0x00,0x00,0x8f,0xbf,0x00,0x20,
-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,
-0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x94,0x82,0x00,0x04,0x00,0x00,0x00,0x00,
-0x30,0x42,0xe0,0x00,0x14,0x40,0x00,0x14,0x00,0x00,0x00,0x00,0x90,0x82,0x00,0x02,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfc,0x00,0x82,0x28,0x21,0x8c,0xa4,0x00,0x00,
-0x3c,0x02,0x00,0x70,0x8c,0xa6,0x00,0x08,0x00,0x82,0x10,0x21,0x2c,0x43,0x00,0x06,
-0x10,0x60,0x00,0x09,0x3c,0x03,0x80,0x01,0x00,0x02,0x10,0x80,0x24,0x63,0x01,0xe8,
-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,
-0x00,0x00,0x00,0x00,0xaf,0x86,0x80,0x14,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x8c,0xa4,0x00,0x00,0x0c,0x00,0x17,0xb3,
-0x00,0x00,0x00,0x00,0x08,0x00,0x01,0xde,0x00,0x00,0x00,0x00,0x0c,0x00,0x24,0xaa,
-0x00,0xc0,0x20,0x21,0x08,0x00,0x01,0xde,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x82,0x80,0x18,0x3c,0x03,0x00,0x0f,
-0x34,0x63,0x42,0x40,0x00,0x43,0x10,0x21,0x00,0x82,0x20,0x2b,0x10,0x80,0x00,0x09,
-0x24,0x03,0x00,0x05,0x8f,0x82,0x83,0x30,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,
-0xaf,0x82,0x83,0x30,0x10,0x43,0x00,0x03,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x8c,0x63,0x01,0x08,0x24,0x02,0x00,0x01,
-0xa3,0x82,0x80,0x11,0xaf,0x80,0x83,0x30,0xaf,0x83,0x80,0x18,0x08,0x00,0x01,0xfb,
-0x00,0x00,0x00,0x00,0x30,0x84,0x00,0xff,0x14,0x80,0x00,0x2f,0x00,0x00,0x00,0x00,
-0x8f,0x82,0x80,0x14,0xa3,0x85,0x83,0x63,0x10,0x40,0x00,0x2b,0x2c,0xa2,0x00,0x04,
-0x14,0x40,0x00,0x06,0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xfc,0x2c,0x42,0x00,0x08,
-0x10,0x40,0x00,0x09,0x24,0xa2,0xff,0xf0,0x00,0x05,0x10,0x40,0x27,0x84,0x83,0x6c,
-0x00,0x44,0x10,0x21,0x94,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,
-0x03,0xe0,0x00,0x08,0xa4,0x43,0x00,0x00,0x2c,0x42,0x00,0x10,0x14,0x40,0x00,0x0a,
-0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xe0,0x2c,0x42,0x00,0x10,0x14,0x40,0x00,0x06,
-0x00,0x05,0x10,0x40,0x24,0xa2,0xff,0xd0,0x2c,0x42,0x00,0x10,0x10,0x40,0x00,0x09,
-0x24,0xa2,0xff,0xc0,0x00,0x05,0x10,0x40,0x27,0x84,0x83,0x6c,0x00,0x44,0x10,0x21,
-0x94,0x43,0xff,0xf8,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0x03,0xe0,0x00,0x08,
-0xa4,0x43,0xff,0xf8,0x2c,0x42,0x00,0x10,0x10,0x40,0x00,0x07,0x00,0x05,0x10,0x40,
-0x27,0x84,0x83,0x6c,0x00,0x44,0x10,0x21,0x94,0x43,0xff,0xf8,0x00,0x00,0x00,0x00,
-0x24,0x63,0x00,0x01,0xa4,0x43,0xff,0xf8,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x8f,0x86,0x8b,0xb0,0x8f,0x82,0x80,0x14,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,
-0x10,0x40,0x00,0x2a,0x00,0xc0,0x38,0x21,0x24,0x02,0x00,0x07,0x24,0x03,0xff,0x9c,
-0xa3,0x82,0x83,0x6b,0xa3,0x83,0x83,0x6a,0x27,0x8a,0x83,0x68,0x00,0x00,0x20,0x21,
-0x24,0x09,0x8f,0xff,0x00,0x04,0x10,0x80,0x00,0x4a,0x28,0x21,0x8c,0xa2,0x00,0x00,
-0x24,0xe3,0x00,0x04,0x24,0x88,0x00,0x01,0xac,0xe2,0x00,0x00,0x10,0x80,0x00,0x02,
-0x00,0x69,0x38,0x24,0xac,0xa0,0x00,0x00,0x31,0x04,0x00,0xff,0x2c,0x82,0x00,0x27,
-0x14,0x40,0xff,0xf5,0x00,0x04,0x10,0x80,0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,
-0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x9c,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,
-0xa7,0x83,0x8b,0xb6,0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,
-0x24,0x02,0x8f,0xff,0x24,0xc6,0x00,0x9c,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24,
-0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xb0,0x10,0xa2,0x00,0x03,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x10,
-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x8f,0x86,0x8b,0xb0,
-0x27,0xbd,0xff,0xc8,0x24,0x02,0x00,0x08,0x24,0x03,0x00,0x20,0xaf,0xbf,0x00,0x30,
-0xa3,0xa2,0x00,0x13,0xa3,0xa3,0x00,0x12,0xa7,0xa4,0x00,0x10,0x00,0xc0,0x28,0x21,
-0x27,0xa9,0x00,0x10,0x00,0x00,0x38,0x21,0x24,0x08,0x8f,0xff,0x00,0x07,0x10,0x80,
-0x00,0x49,0x10,0x21,0x8c,0x44,0x00,0x00,0x24,0xe3,0x00,0x01,0x30,0x67,0x00,0xff,
-0x24,0xa2,0x00,0x04,0x2c,0xe3,0x00,0x08,0xac,0xa4,0x00,0x00,0x14,0x60,0xff,0xf7,
-0x00,0x48,0x28,0x24,0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,0x3c,0x02,0xb0,0x02,
-0x24,0x63,0x00,0x20,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xb6,
-0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,
-0x24,0xc6,0x00,0x20,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24,
-0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xb0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x30,0x00,0x00,0x00,0x00,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0x93,0x82,0x8b,0xc0,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x11,0x24,0x06,0x00,0x01,0x8f,0x82,0x8b,0xb8,0x3c,0x05,0xb0,0x06,
-0x3c,0x04,0xb0,0x03,0x34,0xa5,0x80,0x18,0x34,0x84,0x01,0x08,0x14,0x40,0x00,0x09,
-0x00,0x00,0x30,0x21,0x97,0x82,0x8b,0xb4,0x8c,0x84,0x00,0x00,0x3c,0x03,0xb0,0x02,
-0x00,0x43,0x10,0x21,0xaf,0x84,0x8b,0xbc,0xa7,0x80,0x8b,0xb6,0xac,0x40,0x00,0x00,
-0xac,0x40,0x00,0x04,0x8c,0xa2,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0xc0,0x10,0x21,
-0x8f,0x86,0x8b,0xb0,0x8f,0x82,0x8b,0xb8,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,
-0x00,0xc0,0x40,0x21,0x14,0x40,0x00,0x0a,0x00,0x40,0x50,0x21,0x00,0x00,0x38,0x21,
-0x27,0x89,0x83,0x38,0x24,0xe2,0x00,0x01,0x00,0x07,0x18,0x80,0x30,0x47,0x00,0xff,
-0x00,0x69,0x18,0x21,0x2c,0xe2,0x00,0x0a,0x14,0x40,0xff,0xfa,0xac,0x60,0x00,0x00,
-0x3c,0x02,0x00,0x80,0x10,0x82,0x00,0x6f,0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x3e,
-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x3e,0x90,0xa3,0x00,0x15,
-0x97,0x82,0x83,0x40,0x00,0x03,0x1e,0x00,0x00,0x03,0x1e,0x03,0x00,0x43,0x10,0x21,
-0xa7,0x82,0x83,0x40,0x8c,0xa4,0x00,0x20,0x3c,0x02,0x00,0x60,0x3c,0x03,0x00,0x20,
-0x00,0x82,0x20,0x24,0x10,0x83,0x00,0x54,0x00,0x00,0x00,0x00,0x14,0x80,0x00,0x47,
-0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x44,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,
-0xa7,0x82,0x83,0x44,0x84,0xa3,0x00,0x06,0x8f,0x82,0x83,0x54,0x00,0x00,0x00,0x00,
-0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x54,0x25,0x42,0x00,0x01,0x28,0x43,0x27,0x10,
-0xaf,0x82,0x8b,0xb8,0x10,0x60,0x00,0x09,0x24,0x02,0x00,0x04,0x93,0x83,0x80,0x11,
-0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x05,0x24,0x02,0x00,0x04,0x8f,0xbf,0x00,0x10,
-0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x24,0x03,0x00,0x28,
-0xa3,0x83,0x83,0x3a,0xa3,0x82,0x83,0x3b,0x90,0xa2,0x00,0x18,0x93,0x83,0x83,0x63,
-0x00,0x00,0x38,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03,0xa7,0x82,0x83,0x4e,
-0xa3,0x83,0x83,0x5c,0x27,0x89,0x83,0x38,0x24,0x05,0x8f,0xff,0x00,0x07,0x10,0x80,
-0x00,0x49,0x10,0x21,0x8c,0x44,0x00,0x00,0x24,0xe3,0x00,0x01,0x30,0x67,0x00,0xff,
-0x25,0x02,0x00,0x04,0x2c,0xe3,0x00,0x0a,0xad,0x04,0x00,0x00,0x14,0x60,0xff,0xf7,
-0x00,0x45,0x40,0x24,0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,0x3c,0x02,0xb0,0x02,
-0x24,0x63,0x00,0x28,0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xb6,
-0x34,0x84,0x80,0x18,0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,
-0x24,0xc6,0x00,0x28,0x3c,0x03,0x0f,0x00,0x00,0xc2,0x30,0x24,0x00,0xa3,0x28,0x24,
-0x3c,0x02,0x04,0x00,0xaf,0x86,0x8b,0xb0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x0c,0x00,0x02,0x38,0x00,0x00,0x00,0x00,
-0xa3,0x80,0x80,0x11,0x08,0x00,0x02,0xe7,0x00,0x00,0x00,0x00,0x97,0x82,0x83,0x46,
-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x46,0x84,0xa3,0x00,0x06,
-0x8f,0x82,0x83,0x58,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x58,
-0x08,0x00,0x02,0xdf,0x25,0x42,0x00,0x01,0x97,0x82,0x83,0x42,0x00,0x00,0x00,0x00,
-0x24,0x42,0x00,0x01,0xa7,0x82,0x83,0x42,0x84,0xa3,0x00,0x06,0x8f,0x82,0x83,0x50,
-0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xaf,0x82,0x83,0x50,0x08,0x00,0x02,0xdf,
-0x25,0x42,0x00,0x01,0x97,0x82,0x83,0x3c,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,
-0xa7,0x82,0x83,0x3c,0x08,0x00,0x02,0xc7,0x00,0x00,0x00,0x00,0x27,0xbd,0xff,0xd0,
-0xaf,0xbf,0x00,0x28,0x8c,0xa3,0x00,0x20,0x8f,0x8a,0x8b,0xb0,0x3c,0x02,0x00,0x10,
-0x00,0x62,0x10,0x24,0x00,0xa0,0x38,0x21,0x01,0x40,0x48,0x21,0x10,0x40,0x00,0x3d,
-0x00,0x80,0x28,0x21,0x8c,0xe4,0x00,0x1c,0x34,0xa5,0x12,0x06,0xaf,0xa5,0x00,0x10,
-0x8c,0x82,0x00,0x08,0x00,0x03,0x1c,0x42,0x30,0x63,0x00,0x30,0x00,0x02,0x13,0x02,
-0x30,0x42,0x00,0x40,0x00,0x43,0x10,0x25,0x90,0xe6,0x00,0x10,0x90,0xe4,0x00,0x13,
-0x94,0xe8,0x00,0x0c,0x94,0xe3,0x00,0x1a,0x00,0x02,0x16,0x00,0x90,0xe7,0x00,0x12,
-0x00,0xa2,0x28,0x25,0x24,0x02,0x12,0x34,0xa7,0xa2,0x00,0x1c,0x24,0x02,0x56,0x78,
-0xaf,0xa5,0x00,0x10,0xa3,0xa6,0x00,0x18,0xa3,0xa7,0x00,0x1f,0xa7,0xa3,0x00,0x1a,
-0xa3,0xa4,0x00,0x19,0xa7,0xa8,0x00,0x20,0xa7,0xa2,0x00,0x22,0x00,0x00,0x28,0x21,
-0x27,0xa7,0x00,0x10,0x24,0x06,0x8f,0xff,0x00,0x05,0x10,0x80,0x00,0x47,0x10,0x21,
-0x8c,0x44,0x00,0x00,0x24,0xa3,0x00,0x01,0x30,0x65,0x00,0xff,0x25,0x22,0x00,0x04,
-0x2c,0xa3,0x00,0x05,0xad,0x24,0x00,0x00,0x14,0x60,0xff,0xf7,0x00,0x46,0x48,0x24,
-0x97,0x83,0x8b,0xb6,0x97,0x85,0x8b,0xb4,0x3c,0x02,0xb0,0x02,0x24,0x63,0x00,0x14,
-0x00,0xa2,0x28,0x21,0x3c,0x04,0xb0,0x06,0xa7,0x83,0x8b,0xb6,0x34,0x84,0x80,0x18,
-0xa4,0xa3,0x00,0x00,0x8c,0x85,0x00,0x00,0x24,0x02,0x8f,0xff,0x25,0x46,0x00,0x14,
-0x3c,0x03,0x0f,0x00,0x00,0xc2,0x50,0x24,0x00,0xa3,0x28,0x24,0x3c,0x02,0x04,0x00,
-0xaf,0x8a,0x8b,0xb0,0x10,0xa2,0x00,0x03,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0x98,
-0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x28,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x30,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8,
-0x00,0x04,0x22,0x00,0x34,0xa5,0x00,0x20,0x24,0x42,0x0e,0x04,0x3c,0x03,0xb0,0x00,
-0xaf,0xb5,0x00,0x24,0xaf,0xb4,0x00,0x20,0xaf,0xb2,0x00,0x18,0xaf,0xb0,0x00,0x10,
-0xaf,0xbf,0x00,0x30,0x00,0x83,0x80,0x21,0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28,
-0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14,0xac,0xa2,0x00,0x00,0x8e,0x09,0x00,0x00,
-0x00,0x00,0x90,0x21,0x26,0x10,0x00,0x08,0x00,0x09,0xa6,0x02,0x12,0x80,0x00,0x13,
-0x00,0x00,0xa8,0x21,0x24,0x13,0x00,0x02,0x3c,0x16,0x00,0xff,0x3c,0x17,0xff,0x00,
-0x8e,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x12,0x02,0x24,0x42,0x00,0x02,
-0x31,0x25,0x00,0xff,0x10,0xb3,0x00,0x76,0x30,0x51,0x00,0xff,0x24,0x02,0x00,0x03,
-0x10,0xa2,0x00,0x18,0x00,0x00,0x00,0x00,0x02,0x51,0x10,0x21,0x30,0x52,0xff,0xff,
-0x02,0x54,0x18,0x2b,0x14,0x60,0xff,0xf2,0x02,0x11,0x80,0x21,0x12,0xa0,0x00,0x0a,
-0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18,0x8c,0x43,0x00,0x00,0x3c,0x04,0x0f,0x00,
-0x3c,0x02,0x04,0x00,0x00,0x64,0x18,0x24,0x10,0x62,0x00,0x03,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x04,0x98,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x30,0x7b,0xb6,0x01,0x7c,
-0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x38,0x8e,0x09,0x00,0x04,0x24,0x15,0x00,0x01,0x8e,0x06,0x00,0x0c,
-0x00,0x09,0x11,0x42,0x00,0x09,0x18,0xc2,0x30,0x48,0x00,0x03,0x00,0x09,0x14,0x02,
-0x30,0x6c,0x00,0x03,0x00,0x09,0x26,0x02,0x11,0x15,0x00,0x45,0x30,0x43,0x00,0x0f,
-0x29,0x02,0x00,0x02,0x14,0x40,0x00,0x26,0x00,0x00,0x00,0x00,0x11,0x13,0x00,0x0f,
-0x00,0x00,0x38,0x21,0x00,0x07,0x22,0x02,0x30,0x84,0xff,0x00,0x3c,0x03,0x00,0xff,
-0x00,0x07,0x2e,0x02,0x00,0x07,0x12,0x00,0x00,0x43,0x10,0x24,0x00,0xa4,0x28,0x25,
-0x00,0xa2,0x28,0x25,0x00,0x07,0x1e,0x00,0x00,0xa3,0x28,0x25,0x0c,0x00,0x01,0x94,
-0x01,0x20,0x20,0x21,0x08,0x00,0x03,0xa7,0x02,0x51,0x10,0x21,0x11,0x95,0x00,0x0f,
-0x00,0x00,0x00,0x00,0x11,0x88,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x80,
-0x27,0x83,0x8b,0x60,0x00,0x43,0x10,0x21,0x8c,0x47,0x00,0x18,0x08,0x00,0x03,0xce,
-0x00,0x07,0x22,0x02,0x00,0x04,0x10,0x40,0x27,0x83,0x8b,0x68,0x00,0x43,0x10,0x21,
-0x94,0x47,0x00,0x02,0x08,0x00,0x03,0xce,0x00,0x07,0x22,0x02,0x27,0x82,0x8b,0x60,
-0x00,0x82,0x10,0x21,0x90,0x47,0x00,0x00,0x08,0x00,0x03,0xce,0x00,0x07,0x22,0x02,
-0x15,0x00,0xff,0xdc,0x00,0x00,0x38,0x21,0x10,0x75,0x00,0x05,0x00,0x80,0x38,0x21,
-0x00,0x65,0x18,0x26,0x24,0x82,0x01,0x00,0x00,0x00,0x38,0x21,0x00,0x43,0x38,0x0a,
-0x24,0x02,0x00,0x01,0x11,0x82,0x00,0x0e,0x3c,0x02,0xb0,0x03,0x24,0x02,0x00,0x02,
-0x11,0x82,0x00,0x06,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x00,0xe2,0x10,0x21,
-0x8c,0x47,0x00,0x00,0x08,0x00,0x03,0xce,0x00,0x07,0x22,0x02,0x3c,0x02,0xb0,0x03,
-0x00,0xe2,0x10,0x21,0x94,0x43,0x00,0x00,0x08,0x00,0x03,0xcd,0x30,0x67,0xff,0xff,
-0x00,0xe2,0x10,0x21,0x90,0x43,0x00,0x00,0x08,0x00,0x03,0xcd,0x30,0x67,0x00,0xff,
-0x30,0x62,0x00,0x03,0x00,0x02,0x12,0x00,0x11,0x95,0x00,0x07,0x00,0x44,0x38,0x21,
-0x11,0x93,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x03,0xff,0x3c,0x02,0xb0,0x0a,
-0x08,0x00,0x04,0x04,0x3c,0x02,0xb0,0x0a,0x08,0x00,0x04,0x08,0x3c,0x02,0xb0,0x0a,
-0x8e,0x09,0x00,0x04,0x8e,0x02,0x00,0x08,0x8e,0x03,0x00,0x0c,0x00,0x09,0x41,0x42,
-0x00,0x02,0x22,0x02,0x00,0x03,0x3a,0x02,0x30,0x84,0xff,0x00,0x30,0xe7,0xff,0x00,
-0x00,0x02,0x5e,0x02,0x00,0x02,0x32,0x00,0x00,0x03,0x56,0x02,0x00,0x03,0x2a,0x00,
-0x01,0x64,0x58,0x25,0x00,0xd6,0x30,0x24,0x01,0x47,0x50,0x25,0x00,0x02,0x16,0x00,
-0x00,0xb6,0x28,0x24,0x00,0x03,0x1e,0x00,0x01,0x66,0x58,0x25,0x01,0x45,0x50,0x25,
-0x00,0x57,0x10,0x24,0x00,0x77,0x18,0x24,0x01,0x62,0x38,0x25,0x01,0x43,0x30,0x25,
-0x00,0x09,0x10,0xc2,0x00,0x09,0x1c,0x02,0x31,0x08,0x00,0x03,0x30,0x4c,0x00,0x03,
-0x30,0x63,0x00,0x0f,0x00,0x09,0x26,0x02,0x00,0xe0,0x58,0x21,0x15,0x00,0x00,0x28,
-0x00,0xc0,0x50,0x21,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x06,0x00,0x80,0x28,0x21,
-0x24,0x02,0x00,0x03,0x14,0x62,0xff,0x69,0x02,0x51,0x10,0x21,0x24,0x85,0x01,0x00,
-0x24,0x02,0x00,0x01,0x11,0x82,0x00,0x15,0x24,0x02,0x00,0x02,0x11,0x82,0x00,0x0a,
-0x3c,0x03,0xb0,0x03,0x00,0xa3,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x0a,0x20,0x27,
-0x01,0x6a,0x28,0x24,0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0xac,0x62,0x00,0x00,
-0x08,0x00,0x03,0xa7,0x02,0x51,0x10,0x21,0x00,0xa3,0x18,0x21,0x94,0x62,0x00,0x00,
-0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24,0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,
-0xa4,0x62,0x00,0x00,0x08,0x00,0x03,0xa7,0x02,0x51,0x10,0x21,0x3c,0x03,0xb0,0x03,
-0x00,0xa3,0x18,0x21,0x90,0x62,0x00,0x00,0x00,0x0a,0x20,0x27,0x01,0x6a,0x28,0x24,
-0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa6,0xa0,0x62,0x00,0x00,
-0x24,0x02,0x00,0x01,0x11,0x02,0x00,0x21,0x00,0x00,0x00,0x00,0x15,0x13,0xff,0x42,
-0x00,0x00,0x00,0x00,0x11,0x82,0x00,0x17,0x00,0x00,0x00,0x00,0x11,0x88,0x00,0x0b,
-0x00,0x00,0x00,0x00,0x27,0x83,0x8b,0x60,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,
-0x8c,0x82,0x00,0x18,0x00,0x06,0x18,0x27,0x00,0xe6,0x28,0x24,0x00,0x43,0x10,0x24,
-0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa6,0xac,0x82,0x00,0x18,0x27,0x83,0x8b,0x68,
-0x00,0x04,0x20,0x40,0x00,0x83,0x20,0x21,0x94,0x82,0x00,0x02,0x00,0x06,0x18,0x27,
-0x00,0xe6,0x28,0x24,0x00,0x43,0x10,0x24,0x00,0x45,0x10,0x25,0x08,0x00,0x03,0xa6,
-0xa4,0x82,0x00,0x02,0x27,0x83,0x8b,0x60,0x00,0x83,0x18,0x21,0x90,0x62,0x00,0x00,
-0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x5c,0x00,0xe6,0x28,0x24,0x30,0x62,0x00,0x07,
-0x00,0x02,0x12,0x00,0x11,0x88,0x00,0x0f,0x00,0x44,0x10,0x21,0x11,0x93,0x00,0x07,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x0a,0x00,0x43,0x18,0x21,0x8c,0x62,0x00,0x00,
-0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x49,0x00,0xe6,0x28,0x24,0x3c,0x03,0xb0,0x0a,
-0x00,0x43,0x18,0x21,0x94,0x62,0x00,0x00,0x00,0x06,0x20,0x27,0x08,0x00,0x04,0x52,
-0x00,0xe6,0x28,0x24,0x3c,0x03,0xb0,0x0a,0x08,0x00,0x04,0x7f,0x00,0x43,0x18,0x21,
-0x97,0x85,0x8b,0xb4,0x3c,0x07,0xb0,0x02,0x3c,0x04,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x00,0xa7,0x28,0x21,0x34,0x84,0x00,0x20,0x24,0x42,0x12,0x60,0x24,0x03,0xff,0x80,
-0xac,0x82,0x00,0x00,0xa0,0xa3,0x00,0x07,0x97,0x82,0x8b,0xb6,0x97,0x85,0x8b,0xb4,
-0x3c,0x06,0xb0,0x06,0x30,0x42,0xff,0xf8,0x24,0x42,0x00,0x10,0x00,0xa2,0x10,0x21,
-0x30,0x42,0x0f,0xff,0x24,0x44,0x00,0x08,0x30,0x84,0x0f,0xff,0x00,0x05,0x28,0xc2,
-0x3c,0x03,0x00,0x40,0x00,0xa3,0x28,0x25,0x00,0x87,0x20,0x21,0x34,0xc6,0x80,0x18,
-0xac,0xc5,0x00,0x00,0xaf,0x84,0x8b,0xb0,0xa7,0x82,0x8b,0xb4,0xa7,0x80,0x8b,0xb6,
-0xaf,0x80,0x8b,0xb8,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,
-0x30,0x84,0x00,0xff,0x24,0x02,0x00,0x01,0x00,0xe0,0x48,0x21,0x30,0xc6,0x00,0xff,
-0x8f,0xa7,0x00,0x10,0x10,0x82,0x00,0x07,0x00,0xa0,0x40,0x21,0x24,0x02,0x00,0x03,
-0x10,0x82,0x00,0x03,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x24,0xa8,0x01,0x00,0x3c,0x03,0xb0,0x03,0x24,0x02,0x00,0x01,0x00,0x07,0x20,0x27,
-0x01,0x27,0x28,0x24,0x10,0xc2,0x00,0x14,0x01,0x03,0x18,0x21,0x24,0x02,0x00,0x02,
-0x10,0xc2,0x00,0x09,0x00,0x07,0x50,0x27,0x3c,0x03,0xb0,0x03,0x01,0x03,0x18,0x21,
-0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x45,0x10,0x25,
-0x08,0x00,0x04,0xe3,0xac,0x62,0x00,0x00,0x3c,0x03,0xb0,0x03,0x01,0x03,0x18,0x21,
-0x94,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x45,0x10,0x25,
-0x03,0xe0,0x00,0x08,0xa4,0x62,0x00,0x00,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x44,0x10,0x24,0x00,0x45,0x10,0x25,0xa0,0x62,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x30,0x84,0x00,0x07,0x00,0x04,0x22,0x00,0x30,0xa5,0x00,0xff,
-0x00,0x85,0x28,0x21,0x3c,0x02,0xb0,0x0a,0x00,0xa2,0x40,0x21,0x30,0xc6,0x00,0xff,
-0x24,0x02,0x00,0x01,0x8f,0xa4,0x00,0x10,0x10,0xc2,0x00,0x14,0x24,0x02,0x00,0x02,
-0x00,0x04,0x50,0x27,0x10,0xc2,0x00,0x09,0x00,0xe4,0x48,0x24,0x3c,0x03,0xb0,0x0a,
-0x00,0xa3,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,
-0x00,0x49,0x10,0x25,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x3c,0x03,0xb0,0x0a,
-0x00,0xa3,0x18,0x21,0x94,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,
-0x00,0x49,0x10,0x25,0x03,0xe0,0x00,0x08,0xa4,0x62,0x00,0x00,0x91,0x02,0x00,0x00,
-0x00,0x04,0x18,0x27,0x00,0xe4,0x20,0x24,0x00,0x43,0x10,0x24,0x00,0x44,0x10,0x25,
-0x03,0xe0,0x00,0x08,0xa1,0x02,0x00,0x00,0x30,0xa9,0x00,0xff,0x27,0x83,0x8b,0x60,
-0x30,0x85,0x00,0xff,0x24,0x02,0x00,0x01,0x00,0x07,0x50,0x27,0x00,0xc7,0x40,0x24,
-0x11,0x22,0x00,0x17,0x00,0xa3,0x18,0x21,0x00,0x05,0x20,0x40,0x27,0x82,0x8b,0x60,
-0x00,0x05,0x28,0x80,0x27,0x83,0x8b,0x68,0x00,0x83,0x50,0x21,0x00,0xa2,0x20,0x21,
-0x24,0x02,0x00,0x02,0x00,0x07,0x40,0x27,0x11,0x22,0x00,0x07,0x00,0xc7,0x28,0x24,
-0x8c,0x82,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x48,0x10,0x24,0x00,0x45,0x10,0x25,
-0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x18,0x95,0x42,0x00,0x02,0x00,0x00,0x00,0x00,
-0x00,0x48,0x10,0x24,0x00,0x45,0x10,0x25,0x03,0xe0,0x00,0x08,0xa5,0x42,0x00,0x02,
-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x10,0x24,0x00,0x48,0x10,0x25,
-0x03,0xe0,0x00,0x08,0xa0,0x62,0x00,0x00,0x00,0x04,0x32,0x02,0x30,0xc6,0xff,0x00,
-0x00,0x04,0x16,0x02,0x00,0x04,0x1a,0x00,0x3c,0x05,0x00,0xff,0x00,0x65,0x18,0x24,
-0x00,0x46,0x10,0x25,0x00,0x43,0x10,0x25,0x00,0x04,0x26,0x00,0x03,0xe0,0x00,0x08,
-0x00,0x44,0x10,0x25,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xe8,
-0x34,0x63,0x00,0x20,0x24,0x42,0x14,0xe4,0x3c,0x04,0xb0,0x03,0xaf,0xbf,0x00,0x14,
-0xac,0x62,0x00,0x00,0xaf,0xb0,0x00,0x10,0x34,0x84,0x00,0x2c,0x8c,0x83,0x00,0x00,
-0xa7,0x80,0xbb,0xf0,0x00,0x03,0x12,0x02,0x00,0x03,0x2d,0x02,0x30,0x42,0x0f,0xff,
-0xa3,0x83,0xbb,0xf8,0xa7,0x85,0xbb,0xfc,0xa7,0x82,0xbb,0xfa,0xa7,0x80,0xbb,0xf2,
-0xa7,0x80,0xbb,0xf4,0xa7,0x80,0xbb,0xf6,0x0c,0x00,0x06,0xce,0x24,0x04,0x05,0x00,
-0x3c,0x05,0x08,0x00,0x00,0x45,0x28,0x25,0x24,0x04,0x05,0x00,0x0c,0x00,0x06,0xc1,
-0x00,0x40,0x80,0x21,0x3c,0x02,0xf7,0xff,0x34,0x42,0xff,0xff,0x02,0x02,0x80,0x24,
-0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x05,0x00,0x3c,0x02,0xb0,0x03,
-0x3c,0x03,0xb0,0x03,0x34,0x42,0x01,0x08,0x34,0x63,0x01,0x18,0x8c,0x45,0x00,0x00,
-0x8c,0x64,0x00,0x00,0x3c,0x02,0x00,0x0f,0x3c,0x03,0x00,0x4c,0x30,0x84,0x02,0x00,
-0x34,0x63,0x4b,0x40,0xaf,0x85,0xbc,0x00,0x10,0x80,0x00,0x06,0x34,0x42,0x42,0x40,
-0xaf,0x83,0xbc,0x04,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x18,0xaf,0x82,0xbc,0x04,0x08,0x00,0x05,0x69,0x00,0x00,0x00,0x00,
-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8,0x34,0x63,0x00,0x20,
-0x24,0x42,0x15,0xc0,0x30,0x84,0x00,0xff,0xaf,0xbf,0x00,0x30,0xaf,0xb7,0x00,0x2c,
-0xaf,0xb6,0x00,0x28,0xaf,0xb5,0x00,0x24,0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,
-0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xac,0x62,0x00,0x00,
-0x10,0x80,0x00,0x1c,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x08,0x00,0x00,0x00,0x00,
-0x8f,0xbf,0x00,0x30,0x7b,0xb6,0x01,0x7c,0x7b,0xb4,0x01,0x3c,0x7b,0xb2,0x00,0xfc,
-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,0xa7,0x80,0xbb,0xf0,
-0xa7,0x80,0xbb,0xf2,0xa7,0x80,0xbb,0xf4,0xa7,0x80,0xbb,0xf6,0x0c,0x00,0x06,0xce,
-0x24,0x04,0x05,0x00,0x3c,0x05,0x08,0x00,0x00,0x45,0x28,0x25,0x24,0x04,0x05,0x00,
-0x0c,0x00,0x06,0xc1,0x00,0x40,0x80,0x21,0x3c,0x05,0xf7,0xff,0x34,0xa5,0xff,0xff,
-0x02,0x05,0x28,0x24,0x0c,0x00,0x06,0xc1,0x24,0x04,0x05,0x00,0x08,0x00,0x05,0x84,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x05,0xa0,0x24,0x04,0x05,0xa4,
-0x0c,0x00,0x06,0xce,0x00,0x02,0xbc,0x02,0x24,0x04,0x05,0xa8,0x00,0x02,0xb4,0x02,
-0x0c,0x00,0x06,0xce,0x30,0x55,0xff,0xff,0x00,0x40,0x80,0x21,0x97,0x84,0xbb,0xf0,
-0x97,0x82,0xbb,0xf2,0x97,0x83,0xbb,0xf6,0x02,0xe4,0x20,0x23,0x02,0xa2,0x10,0x23,
-0x00,0x82,0x20,0x21,0x97,0x82,0xbb,0xf4,0x32,0x14,0xff,0xff,0x02,0x83,0x18,0x23,
-0x02,0xc2,0x10,0x23,0x00,0x82,0x20,0x21,0x93,0x82,0xbb,0xf8,0x00,0x83,0x20,0x21,
-0x30,0x84,0xff,0xff,0x00,0x82,0x10,0x2b,0x14,0x40,0x00,0xaa,0x00,0x00,0x00,0x00,
-0x97,0x82,0xbb,0xfc,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x2b,0x14,0x40,0x00,0x7f,
-0x00,0x00,0x00,0x00,0x97,0x82,0xbb,0xfa,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x2b,
-0x10,0x40,0x00,0x3a,0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x50,
-0x30,0x51,0x00,0x7f,0x00,0x40,0x80,0x21,0x2e,0x22,0x00,0x32,0x10,0x40,0x00,0x13,
-0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x17,0x24,0x02,0xff,0x80,0x02,0x02,0x10,0x24,
-0x26,0x31,0x00,0x01,0x00,0x51,0x80,0x25,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,
-0x24,0x04,0x04,0x50,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x58,
-0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x60,0x02,0x00,0x28,0x21,
-0x24,0x04,0x04,0x68,0x0c,0x00,0x06,0xc1,0x00,0x00,0x00,0x00,0xa7,0x97,0xbb,0xf0,
-0xa7,0x95,0xbb,0xf2,0xa7,0x96,0xbb,0xf4,0xa7,0x94,0xbb,0xf6,0x08,0x00,0x05,0x84,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,
-0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x03,
-0x10,0x43,0x00,0x07,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,
-0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08,
-0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff,
-0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,
-0x24,0x04,0x02,0x2c,0x08,0x00,0x05,0xcb,0x24,0x02,0xff,0x80,0x0c,0x00,0x06,0xce,
-0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f,0x24,0x02,0x00,0x20,0x16,0x22,0xff,0xdb,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x34,0x52,0x40,0x00,
-0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xce,
-0x24,0x04,0x02,0x58,0x24,0x04,0x02,0x5c,0x0c,0x00,0x06,0xce,0x00,0x02,0x9e,0x02,
-0x30,0x43,0x00,0xff,0x00,0x13,0x12,0x00,0x00,0x43,0x10,0x25,0x2c,0x43,0x00,0x04,
-0x14,0x60,0x00,0x1d,0x2c,0x42,0x00,0x11,0x10,0x40,0x00,0x0b,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,
-0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xc1,0x36,0x52,0x80,0x00,0x02,0x40,0x28,0x21,
-0x08,0x00,0x05,0xd9,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08,
-0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,0x00,0x02,0x15,0x82,
-0x24,0x03,0x00,0x02,0x14,0x43,0xff,0xee,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,
-0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08,
-0x08,0x00,0x06,0x15,0x3c,0x02,0xff,0xff,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08,
-0x00,0x40,0x28,0x21,0x00,0x02,0x15,0x82,0x30,0x42,0x00,0x03,0x24,0x03,0x00,0x03,
-0x14,0x43,0xff,0xdf,0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,
-0x3c,0x03,0x00,0x80,0x08,0x00,0x06,0x2a,0x00,0x43,0x28,0x25,0x0c,0x00,0x06,0xce,
-0x24,0x04,0x04,0x50,0x30,0x51,0x00,0x7f,0x00,0x40,0x80,0x21,0x2e,0x22,0x00,0x32,
-0x10,0x40,0xff,0x9a,0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x04,0x24,0x02,0xff,0x80,
-0x02,0x02,0x10,0x24,0x08,0x00,0x05,0xcd,0x26,0x31,0x00,0x02,0x0c,0x00,0x06,0xce,
-0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,
-0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x03,0x10,0x43,0x00,0x07,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,
-0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,
-0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff,0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,
-0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x2c,0x08,0x00,0x06,0x44,
-0x24,0x02,0xff,0x80,0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x50,0x00,0x40,0x80,0x21,
-0x30,0x51,0x00,0x7f,0x24,0x02,0x00,0x20,0x12,0x22,0x00,0x1d,0x2e,0x22,0x00,0x21,
-0x14,0x40,0xff,0x72,0x24,0x02,0xff,0x80,0x02,0x02,0x10,0x24,0x26,0x31,0xff,0xff,
-0x00,0x51,0x80,0x25,0x24,0x04,0x04,0x50,0x0c,0x00,0x06,0xc1,0x02,0x00,0x28,0x21,
-0x24,0x04,0x04,0x58,0x0c,0x00,0x06,0xc1,0x02,0x00,0x28,0x21,0x24,0x04,0x04,0x60,
-0x0c,0x00,0x06,0xc1,0x02,0x00,0x28,0x21,0x02,0x00,0x28,0x21,0x0c,0x00,0x06,0xc1,
-0x24,0x04,0x04,0x68,0x24,0x02,0x00,0x20,0x16,0x22,0xff,0x60,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x00,0x40,0x90,0x21,0x3c,0x02,0xff,0xff,
-0x34,0x42,0x3f,0xff,0x02,0x42,0x10,0x24,0x08,0x00,0x06,0x1b,0x34,0x52,0x80,0x00,
-0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x2c,0x34,0x52,0x40,0x00,0x02,0x40,0x28,0x21,
-0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x2c,0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x58,
-0x24,0x04,0x02,0x5c,0x0c,0x00,0x06,0xce,0x00,0x02,0x9e,0x02,0x30,0x43,0x00,0xff,
-0x00,0x13,0x12,0x00,0x00,0x43,0x10,0x25,0x2c,0x43,0x00,0x04,0x14,0x60,0x00,0x20,
-0x2c,0x42,0x00,0x11,0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0xff,
-0x34,0x42,0x3f,0xff,0x02,0x42,0x90,0x24,0x02,0x40,0x28,0x21,0x24,0x04,0x02,0x2c,
-0x0c,0x00,0x06,0xc1,0x36,0x52,0x80,0x00,0x02,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,
-0x24,0x04,0x02,0x2c,0x08,0x00,0x06,0x68,0x2e,0x22,0x00,0x21,0x0c,0x00,0x06,0xce,
-0x24,0x04,0x02,0x08,0x3c,0x04,0x00,0xc0,0x00,0x40,0x28,0x21,0x00,0x44,0x10,0x24,
-0x00,0x02,0x15,0x82,0x24,0x03,0x00,0x02,0x14,0x43,0xff,0xec,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x00,0x44,0x28,0x25,
-0x0c,0x00,0x06,0xc1,0x24,0x04,0x02,0x08,0x08,0x00,0x06,0x98,0x3c,0x02,0xff,0xff,
-0x0c,0x00,0x06,0xce,0x24,0x04,0x02,0x08,0x00,0x40,0x28,0x21,0x00,0x02,0x15,0x82,
-0x30,0x42,0x00,0x03,0x24,0x03,0x00,0x03,0x14,0x43,0xff,0xdc,0x3c,0x03,0x00,0x80,
-0x3c,0x02,0xff,0x3f,0x34,0x42,0xff,0xff,0x00,0xa2,0x10,0x24,0x08,0x00,0x06,0xb0,
-0x00,0x43,0x28,0x25,0x30,0x83,0x00,0x03,0x00,0x04,0x20,0x40,0x00,0x83,0x20,0x23,
-0x3c,0x02,0xb0,0x0a,0x00,0x82,0x20,0x21,0xac,0x85,0x00,0x00,0x00,0x00,0x18,0x21,
-0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x0a,0x14,0x40,0xff,0xfe,0x24,0x63,0x00,0x01,
-0x03,0xe0,0x00,0x08,0x24,0x63,0xff,0xff,0x30,0x86,0x00,0x03,0x00,0x04,0x28,0x40,
-0x3c,0x03,0xb0,0x0a,0x00,0xa6,0x10,0x23,0x00,0x43,0x10,0x21,0x24,0x04,0xff,0xff,
-0xac,0x44,0x10,0x00,0x00,0x00,0x18,0x21,0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x0a,
-0x14,0x40,0xff,0xfe,0x24,0x63,0x00,0x01,0x24,0x63,0xff,0xff,0x00,0xa6,0x18,0x23,
-0x3c,0x02,0xb0,0x0a,0x00,0x62,0x18,0x21,0x8c,0x62,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x1b,0x84,
-0x24,0x03,0x00,0x01,0x34,0xa5,0x00,0x20,0x3c,0x06,0xb0,0x03,0xac,0xa2,0x00,0x00,
-0x34,0xc6,0x01,0x04,0xa0,0x83,0x00,0x48,0xa0,0x80,0x00,0x04,0xa0,0x80,0x00,0x05,
-0xa0,0x80,0x00,0x06,0xa0,0x80,0x00,0x07,0xa0,0x80,0x00,0x08,0xa0,0x80,0x00,0x09,
-0xa0,0x80,0x00,0x0a,0xa0,0x80,0x00,0x11,0xa0,0x80,0x00,0x13,0xa0,0x80,0x00,0x49,
-0x94,0xc2,0x00,0x00,0xac,0x80,0x00,0x00,0xa0,0x80,0x00,0x4e,0x00,0x02,0x14,0x00,
-0x00,0x02,0x14,0x03,0x30,0x43,0x00,0xff,0x30,0x42,0xff,0x00,0xa4,0x82,0x00,0x44,
-0xa4,0x83,0x00,0x46,0xac,0x80,0x00,0x24,0xac,0x80,0x00,0x28,0xac,0x80,0x00,0x2c,
-0xac,0x80,0x00,0x30,0xac,0x80,0x00,0x34,0xac,0x80,0x00,0x38,0xac,0x80,0x00,0x3c,
-0x03,0xe0,0x00,0x08,0xac,0x80,0x00,0x40,0x84,0x83,0x00,0x0c,0x3c,0x07,0xb0,0x03,
-0x34,0xe7,0x00,0x20,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x48,0x00,0x18,0x3c,0x02,0x80,0x00,
-0x24,0x42,0x1c,0x18,0xac,0xe2,0x00,0x00,0x8d,0x03,0x00,0x08,0x80,0x82,0x00,0x13,
-0x00,0x05,0x2c,0x00,0x00,0x03,0x1e,0x02,0x00,0x02,0x12,0x00,0x30,0x63,0x00,0x7e,
-0x00,0x62,0x18,0x21,0x00,0x65,0x18,0x21,0x3c,0x02,0xc0,0x00,0x3c,0x05,0xb0,0x05,
-0x34,0x42,0x04,0x00,0x24,0x63,0x00,0x01,0x3c,0x07,0xb0,0x05,0x3c,0x08,0xb0,0x05,
-0x34,0xa5,0x04,0x20,0xac,0xa3,0x00,0x00,0x00,0xc2,0x30,0x21,0x34,0xe7,0x04,0x24,
-0x35,0x08,0x02,0x28,0x24,0x02,0x00,0x01,0x24,0x03,0x00,0x20,0xac,0xe6,0x00,0x00,
-0xac,0x82,0x00,0x3c,0x03,0xe0,0x00,0x08,0xa1,0x03,0x00,0x00,0x27,0xbd,0xff,0xa8,
-0x00,0x07,0x60,0x80,0x27,0x82,0xb3,0xf0,0xaf,0xbe,0x00,0x50,0xaf,0xb7,0x00,0x4c,
-0xaf,0xb5,0x00,0x44,0xaf,0xb4,0x00,0x40,0xaf,0xbf,0x00,0x54,0xaf,0xb6,0x00,0x48,
-0xaf,0xb3,0x00,0x3c,0xaf,0xb2,0x00,0x38,0xaf,0xb1,0x00,0x34,0xaf,0xb0,0x00,0x30,
-0x01,0x82,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0xe0,0x70,0x21,0x3c,0x02,0x80,0x00,
-0x94,0x73,0x00,0x14,0x3c,0x07,0xb0,0x03,0x34,0xe7,0x00,0x20,0x24,0x42,0x1c,0xac,
-0x3c,0x03,0xb0,0x05,0xac,0xe2,0x00,0x00,0x34,0x63,0x01,0x28,0x90,0x67,0x00,0x00,
-0x00,0x13,0xa8,0xc0,0x02,0xb3,0x18,0x21,0x27,0x82,0x8f,0xf4,0x00,0x03,0x18,0x80,
-0x00,0x62,0x18,0x21,0x00,0x05,0x2c,0x00,0x00,0x07,0x3e,0x00,0x28,0xc2,0x00,0x03,
-0x00,0xc0,0xa0,0x21,0x00,0x80,0x78,0x21,0x00,0x05,0xbc,0x03,0x8c,0x68,0x00,0x18,
-0x02,0xa0,0x58,0x21,0x10,0x40,0x01,0x81,0x00,0x07,0xf6,0x03,0x00,0xde,0x10,0x07,
-0x30,0x5e,0x00,0x01,0x01,0x73,0x10,0x21,0x27,0x83,0x8f,0xf8,0x00,0x02,0x10,0x80,
-0x00,0x43,0x10,0x21,0x80,0x4d,0x00,0x06,0x8d,0x03,0x00,0x00,0x8d,0x02,0x00,0x04,
-0x8d,0x0a,0x00,0x08,0x8d,0x03,0x00,0x0c,0xaf,0xa2,0x00,0x20,0x11,0xa0,0x01,0x71,
-0xaf,0xa3,0x00,0x18,0x27,0x82,0xb3,0xf0,0x01,0x82,0x10,0x21,0x8c,0x44,0x00,0x00,
-0x00,0x00,0x00,0x00,0x90,0x83,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x04,
-0x14,0x60,0x00,0x12,0x00,0x00,0xb0,0x21,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x46,
-0x90,0x43,0x00,0x00,0x2a,0x84,0x00,0x04,0x10,0x80,0x01,0x56,0x30,0x65,0x00,0x01,
-0x91,0xe2,0x00,0x09,0x00,0x00,0x00,0x00,0x12,0x82,0x00,0x02,0x00,0x00,0x00,0x00,
-0x00,0x00,0x28,0x21,0x14,0xa0,0x00,0x03,0x00,0x00,0x38,0x21,0x13,0xc0,0x00,0x03,
-0x38,0xf6,0x00,0x01,0x24,0x07,0x00,0x01,0x38,0xf6,0x00,0x01,0x01,0x73,0x10,0x21,
-0x00,0x02,0x30,0x80,0x27,0x83,0x90,0x00,0x00,0xc3,0x48,0x21,0x91,0x25,0x00,0x00,
-0x8f,0xa4,0x00,0x20,0x2c,0xa3,0x00,0x04,0x00,0x04,0x11,0xc3,0x30,0x42,0x00,0x01,
-0x00,0x03,0xb0,0x0b,0x12,0xc0,0x00,0xd8,0xaf,0xa2,0x00,0x24,0x93,0x90,0xbb,0xda,
-0x00,0x0a,0x16,0x42,0x30,0x52,0x00,0x3f,0x2e,0x06,0x00,0x0c,0x10,0xc0,0x00,0xc0,
-0x00,0xa0,0x20,0x21,0x2c,0xa2,0x00,0x10,0x14,0x40,0x00,0x04,0x00,0x90,0x10,0x2b,
-0x30,0xa2,0x00,0x07,0x24,0x44,0x00,0x04,0x00,0x90,0x10,0x2b,0x10,0x40,0x00,0x0b,
-0x01,0x73,0x10,0x21,0x27,0x85,0xbb,0x0c,0x00,0x10,0x10,0x40,0x00,0x50,0x10,0x21,
-0x00,0x45,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x18,0x2b,
-0x14,0x60,0xff,0xfa,0x00,0x10,0x10,0x40,0x01,0x73,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x8f,0xf8,0x00,0x43,0x10,0x21,0x31,0xa4,0x00,0x01,0x10,0x80,0x00,0xa5,
-0xa0,0x50,0x00,0x07,0x3c,0x04,0xb0,0x05,0x34,0x84,0x00,0x08,0x24,0x02,0x00,0x01,
-0x3c,0x03,0x80,0x00,0xa1,0xe2,0x00,0x4e,0xac,0x83,0x00,0x00,0x8c,0x85,0x00,0x00,
-0x3c,0x02,0x00,0xf0,0x3c,0x03,0x40,0xf0,0x34,0x42,0xf0,0x00,0x34,0x63,0xf0,0x00,
-0x24,0x17,0x00,0x0e,0x24,0x13,0x01,0x06,0xac,0x82,0x00,0x00,0xac,0x83,0x00,0x00,
-0x27,0x82,0xb3,0xf0,0x01,0x82,0x10,0x21,0x8c,0x43,0x00,0x00,0x24,0x05,0x00,0x01,
-0xaf,0xa5,0x00,0x1c,0x90,0x62,0x00,0x16,0x00,0x13,0xa8,0xc0,0x32,0x51,0x00,0x02,
-0x34,0x42,0x00,0x04,0xa0,0x62,0x00,0x16,0x8f,0xa3,0x00,0x20,0x8f,0xa4,0x00,0x18,
-0x00,0x03,0x13,0x43,0x00,0x04,0x1a,0x02,0x30,0x47,0x00,0x01,0x12,0x20,0x00,0x04,
-0x30,0x64,0x07,0xff,0x2e,0x03,0x00,0x04,0x32,0x42,0x00,0x33,0x00,0x43,0x90,0x0b,
-0x8f,0xa5,0x00,0x24,0x8f,0xa6,0x00,0x1c,0x00,0x12,0x10,0x40,0x00,0x05,0x19,0xc0,
-0x00,0x47,0x10,0x21,0x00,0x06,0x2a,0x80,0x00,0x43,0x10,0x21,0x00,0x10,0x32,0x00,
-0x00,0x04,0x24,0x80,0x02,0x65,0x28,0x21,0x00,0xa4,0x28,0x21,0x00,0x46,0x10,0x21,
-0x00,0x17,0x1c,0x00,0x3c,0x04,0xc0,0x00,0x00,0x43,0x30,0x21,0x16,0x80,0x00,0x29,
-0x00,0xa4,0x28,0x21,0x3c,0x02,0xb0,0x05,0x34,0x42,0x04,0x00,0x3c,0x03,0xb0,0x05,
-0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x04,0x34,0x84,0x02,0x28,
-0x24,0x02,0x00,0x01,0xac,0x65,0x00,0x00,0xa0,0x82,0x00,0x00,0x3c,0x02,0xb0,0x09,
-0x34,0x42,0x01,0x46,0x90,0x44,0x00,0x00,0x91,0xe3,0x00,0x09,0x30,0x86,0x00,0x01,
-0x02,0x83,0x18,0x26,0x00,0x03,0x30,0x0b,0x14,0xc0,0x00,0x03,0x00,0x00,0x28,0x21,
-0x13,0xc0,0x00,0x03,0x02,0xb3,0x10,0x21,0x24,0x05,0x00,0x01,0x02,0xb3,0x10,0x21,
-0x27,0x83,0x8f,0xf8,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x84,0x48,0x00,0x04,
-0x00,0xa0,0x30,0x21,0x00,0xe0,0x20,0x21,0x02,0x80,0x28,0x21,0x02,0xc0,0x38,0x21,
-0x0c,0x00,0x00,0x72,0xaf,0xa8,0x00,0x10,0x7b,0xbe,0x02,0xbc,0x7b,0xb6,0x02,0x7c,
-0x7b,0xb4,0x02,0x3c,0x7b,0xb2,0x01,0xfc,0x7b,0xb0,0x01,0xbc,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x58,0x24,0x02,0x00,0x01,0x12,0x82,0x00,0x3d,0x3c,0x02,0xb0,0x05,
-0x24,0x02,0x00,0x02,0x12,0x82,0x00,0x31,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x03,
-0x12,0x82,0x00,0x25,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x10,0x12,0x82,0x00,0x19,
-0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x11,0x12,0x82,0x00,0x0d,0x3c,0x02,0xb0,0x05,
-0x24,0x02,0x00,0x12,0x16,0x82,0xff,0xd1,0x3c,0x02,0xb0,0x05,0x3c,0x03,0xb0,0x05,
-0x34,0x42,0x04,0x20,0x3c,0x04,0xb0,0x05,0x34,0x63,0x04,0x24,0xac,0x46,0x00,0x00,
-0x34,0x84,0x02,0x28,0xac,0x65,0x00,0x00,0x08,0x00,0x07,0xe2,0x24,0x02,0x00,0x20,
-0x34,0x42,0x04,0x40,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,
-0x34,0x63,0x04,0x44,0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x40,0x08,0x00,0x07,0xe2,
-0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x28,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,
-0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x2c,0x34,0x84,0x02,0x28,0x24,0x02,0xff,0x80,
-0x08,0x00,0x07,0xe2,0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x18,0x3c,0x03,0xb0,0x05,
-0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x1c,0x34,0x84,0x02,0x28,
-0x24,0x02,0x00,0x08,0x08,0x00,0x07,0xe2,0xac,0x65,0x00,0x00,0x34,0x42,0x04,0x10,
-0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,0x34,0x63,0x04,0x14,
-0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x04,0x08,0x00,0x07,0xe2,0xac,0x65,0x00,0x00,
-0x34,0x42,0x04,0x08,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,0xac,0x46,0x00,0x00,
-0x34,0x63,0x04,0x0c,0x34,0x84,0x02,0x28,0x24,0x02,0x00,0x02,0x08,0x00,0x07,0xe2,
-0xac,0x65,0x00,0x00,0x24,0x17,0x00,0x14,0x08,0x00,0x07,0xb4,0x24,0x13,0x01,0x02,
-0x30,0xa2,0x00,0x07,0x24,0x44,0x00,0x0c,0x00,0x90,0x18,0x2b,0x10,0x60,0x00,0x0c,
-0x26,0x02,0x00,0x04,0x27,0x85,0xbb,0x0c,0x00,0x10,0x10,0x40,0x00,0x50,0x10,0x21,
-0x00,0x45,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x18,0x2b,
-0x14,0x60,0xff,0xfa,0x00,0x10,0x10,0x40,0x2e,0x06,0x00,0x0c,0x26,0x02,0x00,0x04,
-0x08,0x00,0x07,0x9e,0x00,0x46,0x80,0x0a,0x27,0x82,0xb3,0xf0,0x01,0x82,0x20,0x21,
-0x8c,0x87,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0xe2,0x00,0x19,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x27,0x82,0x90,0x10,0x00,0xc2,0x10,0x21,
-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x60,0x00,0x14,0x00,0x00,0x00,0x00,
-0x90,0xe3,0x00,0x16,0x27,0x82,0x8f,0xf8,0x00,0xc2,0x10,0x21,0x34,0x63,0x00,0x20,
-0x90,0x50,0x00,0x07,0xa0,0xe3,0x00,0x16,0x8c,0x84,0x00,0x00,0x00,0x0a,0x1e,0x42,
-0x24,0x06,0x00,0x01,0x90,0x82,0x00,0x16,0x30,0x71,0x00,0x02,0x30,0x72,0x00,0x3f,
-0x30,0x42,0x00,0xfb,0x24,0x17,0x00,0x18,0x24,0x13,0x01,0x03,0x24,0x15,0x08,0x18,
-0xaf,0xa6,0x00,0x1c,0x08,0x00,0x07,0xbe,0xa0,0x82,0x00,0x16,0x8d,0x02,0x00,0x04,
-0x00,0x0a,0x1c,0x42,0x30,0x42,0x00,0x10,0x14,0x40,0x00,0x15,0x30,0x72,0x00,0x3f,
-0x81,0x22,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x11,0x30,0x72,0x00,0x3e,
-0x27,0x83,0x90,0x08,0x00,0xc3,0x18,0x21,0x80,0x64,0x00,0x00,0x27,0x83,0xb5,0x68,
-0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x05,0x90,0x43,0x00,0x04,
-0x00,0x00,0x00,0x00,0x00,0x64,0x18,0x24,0x30,0x63,0x00,0x01,0x02,0x43,0x90,0x25,
-0x27,0x85,0xb3,0xf0,0x01,0x85,0x28,0x21,0x8c,0xa6,0x00,0x00,0x01,0x73,0x10,0x21,
-0x27,0x83,0x90,0x00,0x90,0xc4,0x00,0x16,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,
-0x30,0x84,0x00,0xdf,0x90,0x50,0x00,0x00,0xa0,0xc4,0x00,0x16,0x80,0xc6,0x00,0x12,
-0x8c,0xa3,0x00,0x00,0x2d,0xc4,0x00,0x02,0xaf,0xa6,0x00,0x1c,0x90,0x62,0x00,0x16,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfb,0x14,0x80,0x00,0x06,0xa0,0x62,0x00,0x16,
-0x24,0x02,0x00,0x06,0x11,0xc2,0x00,0x03,0x24,0x02,0x00,0x04,0x15,0xc2,0xff,0x0e,
-0x32,0x51,0x00,0x02,0x32,0x51,0x00,0x02,0x2e,0x02,0x00,0x0c,0x14,0x40,0x00,0x0f,
-0x00,0x11,0x18,0x2b,0x32,0x02,0x00,0x0f,0x34,0x42,0x00,0x10,0x00,0x03,0x19,0x00,
-0x00,0x43,0x18,0x21,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xb8,0xa0,0x43,0x00,0x00,
-0x00,0x00,0x20,0x21,0x02,0x00,0x28,0x21,0x0c,0x00,0x02,0x05,0xaf,0xaf,0x00,0x28,
-0x8f,0xaf,0x00,0x28,0x08,0x00,0x07,0xbe,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0xb9,
-0x32,0x03,0x00,0xff,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x42,0x90,0x62,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x0f,0x14,0x40,0xfe,0xaa,0x00,0x00,0x00,0x00,
-0x91,0xe2,0x00,0x09,0x00,0x00,0x00,0x00,0x02,0x82,0x10,0x26,0x08,0x00,0x07,0x75,
-0x00,0x02,0x28,0x0b,0x08,0x00,0x07,0x7b,0x00,0x00,0xb0,0x21,0x24,0x02,0x00,0x10,
-0x10,0xc2,0x00,0x08,0x24,0x02,0x00,0x11,0x10,0xc2,0xfe,0x7d,0x00,0x07,0x17,0x83,
-0x24,0x02,0x00,0x12,0x14,0xc2,0xfe,0x7b,0x00,0x07,0x17,0x43,0x08,0x00,0x07,0x55,
-0x30,0x5e,0x00,0x01,0x08,0x00,0x07,0x55,0x00,0x07,0xf7,0xc2,0x00,0x04,0x10,0x40,
-0x27,0x83,0x80,0x1c,0x00,0x43,0x10,0x21,0x00,0x80,0x40,0x21,0x94,0x44,0x00,0x00,
-0x2d,0x07,0x00,0x04,0x24,0xc2,0x00,0x03,0x00,0x47,0x30,0x0a,0x00,0x86,0x00,0x18,
-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x23,0x7c,
-0xac,0x62,0x00,0x00,0x2d,0x06,0x00,0x10,0x00,0x00,0x20,0x12,0x00,0x04,0x22,0x42,
-0x24,0x84,0x00,0x01,0x24,0x83,0x00,0xc0,0x10,0xe0,0x00,0x0b,0x24,0x82,0x00,0x60,
-0x00,0x40,0x20,0x21,0x00,0x65,0x20,0x0a,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x00,
-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x00,0x44,0x20,0x04,
-0x03,0xe0,0x00,0x08,0x00,0x80,0x10,0x21,0x24,0x85,0x00,0x28,0x24,0x83,0x00,0x24,
-0x31,0x02,0x00,0x08,0x14,0xc0,0xff,0xf4,0x24,0x84,0x00,0x14,0x00,0x60,0x20,0x21,
-0x08,0x00,0x08,0xf6,0x00,0xa2,0x20,0x0b,0x27,0xbd,0xff,0xe0,0x3c,0x03,0xb0,0x03,
-0x3c,0x02,0x80,0x00,0xaf,0xb0,0x00,0x10,0x24,0x42,0x24,0x18,0x00,0x80,0x80,0x21,
-0x34,0x63,0x00,0x20,0x3c,0x04,0xb0,0x03,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,
-0xaf,0xbf,0x00,0x1c,0x83,0xb1,0x00,0x33,0x83,0xa8,0x00,0x37,0x34,0x84,0x01,0x10,
-0xac,0x62,0x00,0x00,0x2e,0x02,0x00,0x10,0x00,0xe0,0x90,0x21,0x8c,0x87,0x00,0x00,
-0x14,0x40,0x00,0x0c,0x2e,0x02,0x00,0x0c,0x3c,0x02,0x00,0x0f,0x34,0x42,0xf0,0x00,
-0x00,0xe2,0x10,0x24,0x14,0x40,0x00,0x37,0x32,0x02,0x00,0x08,0x32,0x02,0x00,0x07,
-0x27,0x83,0x80,0xcc,0x00,0x43,0x10,0x21,0x90,0x50,0x00,0x00,0x00,0x00,0x00,0x00,
-0x2e,0x02,0x00,0x0c,0x14,0x40,0x00,0x03,0x02,0x00,0x20,0x21,0x32,0x02,0x00,0x0f,
-0x24,0x44,0x00,0x0c,0x00,0x87,0x10,0x06,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x07,
-0x2c,0x82,0x00,0x0c,0x00,0x04,0x10,0x80,0x27,0x83,0xb4,0x40,0x00,0x43,0x10,0x21,
-0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x82,0x00,0x0c,0x14,0x40,0x00,0x05,
-0x00,0x05,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0x82,0x10,0x21,
-0x24,0x44,0x00,0x04,0x15,0x00,0x00,0x02,0x24,0x06,0x00,0x20,0x24,0x06,0x00,0x0e,
-0x0c,0x00,0x08,0xdf,0x00,0x00,0x00,0x00,0x00,0x40,0x30,0x21,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x01,0x00,0x90,0x43,0x00,0x00,0x2e,0x04,0x00,0x04,0x24,0x02,0x00,0x10,
-0x24,0x05,0x00,0x0a,0x00,0x44,0x28,0x0a,0x30,0x63,0x00,0x01,0x14,0x60,0x00,0x02,
-0x00,0x05,0x10,0x40,0x00,0xa0,0x10,0x21,0x30,0x45,0x00,0xff,0x00,0xc5,0x10,0x21,
-0x24,0x46,0x00,0x46,0x02,0x26,0x18,0x04,0xa6,0x43,0x00,0x00,0x8f,0xbf,0x00,0x1c,
-0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x00,0xc0,0x10,0x21,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x20,0x10,0x40,0xff,0xcf,0x2e,0x02,0x00,0x0c,0x32,0x02,0x00,0x07,
-0x27,0x83,0x80,0xc4,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x00,0x08,0x00,0x09,0x24,
-0x02,0x04,0x80,0x23,0x27,0xbd,0xff,0xb8,0x00,0x05,0x38,0x80,0x27,0x82,0xb3,0xf0,
-0xaf,0xbe,0x00,0x40,0xaf,0xb6,0x00,0x38,0xaf,0xb3,0x00,0x2c,0xaf,0xbf,0x00,0x44,
-0xaf,0xb7,0x00,0x3c,0xaf,0xb5,0x00,0x34,0xaf,0xb4,0x00,0x30,0xaf,0xb2,0x00,0x28,
-0xaf,0xb1,0x00,0x24,0xaf,0xb0,0x00,0x20,0x00,0xe2,0x38,0x21,0x8c,0xe6,0x00,0x00,
-0xaf,0xa5,0x00,0x4c,0x3c,0x02,0x80,0x00,0x3c,0x05,0xb0,0x03,0x34,0xa5,0x00,0x20,
-0x24,0x42,0x25,0x74,0x24,0x03,0x00,0x01,0xac,0xa2,0x00,0x00,0xa0,0xc3,0x00,0x12,
-0x8c,0xe5,0x00,0x00,0x94,0xc3,0x00,0x06,0x90,0xa2,0x00,0x16,0xa4,0xc3,0x00,0x14,
-0x27,0x83,0x8f,0xf0,0x34,0x42,0x00,0x08,0xa0,0xa2,0x00,0x16,0x8c,0xe8,0x00,0x00,
-0xaf,0xa4,0x00,0x48,0x27,0x82,0x8f,0xf4,0x95,0x11,0x00,0x14,0x00,0x00,0x00,0x00,
-0x00,0x11,0x98,0xc0,0x02,0x71,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x82,0x10,0x21,
-0x8c,0x52,0x00,0x18,0x00,0x83,0x18,0x21,0x84,0x75,0x00,0x06,0x8e,0x45,0x00,0x08,
-0x8e,0x46,0x00,0x04,0x8e,0x47,0x00,0x04,0x00,0x05,0x1c,0x82,0x00,0x06,0x31,0x42,
-0x27,0x82,0x90,0x00,0x30,0x63,0x00,0x01,0x30,0xc6,0x00,0x01,0x00,0x82,0x20,0x21,
-0xa5,0x15,0x00,0x1a,0x00,0x05,0x14,0x42,0xaf,0xa3,0x00,0x18,0xaf,0xa6,0x00,0x1c,
-0x30,0xe7,0x00,0x10,0x30,0x56,0x00,0x01,0x80,0x97,0x00,0x06,0x14,0xe0,0x00,0x47,
-0x00,0x05,0xf7,0xc2,0x80,0x82,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x44,
-0x02,0x71,0x10,0x21,0x93,0x90,0xbb,0xd9,0x00,0x00,0x00,0x00,0x2e,0x02,0x00,0x0c,
-0x14,0x40,0x00,0x06,0x02,0x00,0x20,0x21,0x00,0x16,0x10,0x40,0x00,0x43,0x10,0x21,
-0x00,0x02,0x11,0x00,0x02,0x02,0x10,0x21,0x24,0x44,0x00,0x04,0x02,0x71,0x10,0x21,
-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x00,0x80,0x80,0x21,
-0xa0,0x44,0x00,0x03,0xa0,0x44,0x00,0x00,0x02,0x00,0x20,0x21,0x02,0xc0,0x28,0x21,
-0x0c,0x00,0x08,0xdf,0x02,0xa0,0x30,0x21,0x02,0x71,0x18,0x21,0x00,0x03,0x88,0x80,
-0x00,0x40,0xa0,0x21,0x27,0x82,0x90,0x10,0x02,0x22,0x10,0x21,0x8c,0x44,0x00,0x00,
-0x26,0xe3,0x00,0x02,0x00,0x03,0x17,0xc2,0x00,0x62,0x18,0x21,0x00,0x04,0x25,0xc2,
-0x00,0x03,0x18,0x43,0x30,0x84,0x00,0x01,0x00,0x03,0x18,0x40,0x03,0xc4,0x20,0x24,
-0x14,0x80,0x00,0x15,0x02,0x43,0x38,0x21,0x3c,0x08,0xb0,0x03,0x35,0x08,0x00,0x28,
-0x8d,0x03,0x00,0x00,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x48,0x27,0x82,0x8f,0xf8,
-0x02,0x22,0x10,0x21,0x24,0x63,0x00,0x01,0x02,0xa0,0x28,0x21,0xa4,0x54,0x00,0x04,
-0x00,0xc0,0x38,0x21,0x0c,0x00,0x07,0x2b,0xad,0x03,0x00,0x00,0x7b,0xbe,0x02,0x3c,
-0x7b,0xb6,0x01,0xfc,0x7b,0xb4,0x01,0xbc,0x7b,0xb2,0x01,0x7c,0x7b,0xb0,0x01,0x3c,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x48,0x8f,0xa2,0x00,0x1c,0x8f,0xa6,0x00,0x18,
-0x02,0x00,0x20,0x21,0x02,0xc0,0x28,0x21,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0x06,
-0xaf,0xa0,0x00,0x14,0x08,0x00,0x09,0xc2,0x02,0x82,0xa0,0x21,0x02,0x71,0x10,0x21,
-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x90,0x50,0x00,0x00,
-0x08,0x00,0x09,0xae,0xa0,0x50,0x00,0x03,0x27,0xbd,0xff,0xb8,0xaf,0xb1,0x00,0x24,
-0x8f,0xb1,0x00,0x5c,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,
-0x24,0x42,0x27,0x98,0xaf,0xbe,0x00,0x40,0xaf,0xb7,0x00,0x3c,0xaf,0xb6,0x00,0x38,
-0xaf,0xb5,0x00,0x34,0xaf,0xb4,0x00,0x30,0xaf,0xa5,0x00,0x4c,0x8f,0xb5,0x00,0x58,
-0xaf,0xbf,0x00,0x44,0xaf,0xb3,0x00,0x2c,0xaf,0xb2,0x00,0x28,0xaf,0xb0,0x00,0x20,
-0x00,0xe0,0xb0,0x21,0xac,0x62,0x00,0x00,0x00,0x80,0xf0,0x21,0x00,0x00,0xb8,0x21,
-0x16,0x20,0x00,0x2b,0x00,0x00,0xa0,0x21,0x27,0x85,0xb3,0xf0,0x00,0x07,0x10,0x80,
-0x00,0x45,0x10,0x21,0x8c,0x53,0x00,0x00,0x00,0x15,0x18,0x80,0x00,0x65,0x18,0x21,
-0x92,0x62,0x00,0x16,0x8c,0x72,0x00,0x00,0x30,0x42,0x00,0x03,0x14,0x40,0x00,0x2d,
-0x00,0x00,0x00,0x00,0x92,0x42,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x03,
-0x14,0x40,0x00,0x28,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x34,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x18,0x02,0x20,0x10,0x21,0x8c,0x82,0x00,0x38,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x14,0x02,0x20,0x10,0x21,0x8c,0x82,0x00,0x3c,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x0f,0x3c,0x03,0xb0,0x09,0x3c,0x05,0xb0,0x05,0x34,0x63,0x01,0x44,
-0x34,0xa5,0x02,0x52,0x94,0x66,0x00,0x00,0x90,0xa2,0x00,0x00,0x8f,0xa3,0x00,0x4c,
-0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x06,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x04,
-0x30,0xc6,0xff,0xff,0x2c,0xc2,0x00,0x41,0x10,0x40,0x00,0x09,0x24,0x05,0x00,0x14,
-0x02,0x20,0x10,0x21,0x7b,0xbe,0x02,0x3c,0x7b,0xb6,0x01,0xfc,0x7b,0xb4,0x01,0xbc,
-0x7b,0xb2,0x01,0x7c,0x7b,0xb0,0x01,0x3c,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x48,
-0x0c,0x00,0x07,0x06,0x24,0x06,0x01,0x07,0x24,0x02,0x00,0x01,0x08,0x00,0x0a,0x28,
-0xa3,0xc2,0x00,0x11,0x10,0xc0,0x00,0x1c,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x17,
-0x00,0xc0,0x88,0x21,0x96,0x54,0x00,0x1a,0x02,0xa0,0xb8,0x21,0x12,0x20,0xff,0xed,
-0x02,0x20,0x10,0x21,0x27,0x83,0xb3,0xf0,0x00,0x17,0x10,0x80,0x00,0x43,0x10,0x21,
-0x8c,0x44,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x28,0x80,0x86,0x00,0x12,
-0x8c,0x62,0x00,0x00,0x00,0x14,0x2c,0x00,0x00,0x05,0x2c,0x03,0x00,0x46,0x10,0x21,
-0x8f,0xa6,0x00,0x4c,0x02,0xe0,0x38,0x21,0x03,0xc0,0x20,0x21,0x0c,0x00,0x07,0x2b,
-0xac,0x62,0x00,0x00,0x08,0x00,0x0a,0x28,0xaf,0xd1,0x00,0x40,0x96,0x74,0x00,0x1a,
-0x08,0x00,0x0a,0x3b,0x02,0xc0,0xb8,0x21,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,
-0x8c,0x50,0x00,0x00,0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x11,0x02,0x00,0x28,0x21,
-0x30,0x42,0x00,0xff,0x02,0x00,0x28,0x21,0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x11,
-0xaf,0xa2,0x00,0x18,0x8f,0xa4,0x00,0x18,0x00,0x00,0x00,0x00,0x10,0x80,0x00,0xed,
-0x30,0x50,0x00,0xff,0x12,0x00,0x00,0x18,0x24,0x11,0x00,0x01,0x96,0x63,0x00,0x14,
-0x96,0x44,0x00,0x14,0x27,0x85,0x8f,0xf0,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x00,0x04,0x18,0xc0,0x8c,0x46,0x00,0x08,
-0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x65,0x18,0x21,0x00,0x06,0x17,0x02,
-0x24,0x04,0x00,0xff,0x8c,0x63,0x00,0x08,0x10,0x44,0x00,0xd6,0x00,0x03,0x17,0x02,
-0x10,0x44,0x00,0xd5,0x3c,0x02,0x80,0x00,0x00,0x66,0x18,0x2b,0x24,0x11,0x00,0x02,
-0x24,0x02,0x00,0x01,0x00,0x43,0x88,0x0a,0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x5a,
-0x24,0x02,0x00,0x02,0x16,0x22,0xff,0xbd,0x00,0x00,0x00,0x00,0x96,0x49,0x00,0x14,
-0x27,0x82,0x8f,0xf4,0x02,0xa0,0xb8,0x21,0x00,0x09,0x50,0xc0,0x01,0x49,0x18,0x21,
-0x00,0x03,0x40,0x80,0x01,0x02,0x10,0x21,0x8c,0x43,0x00,0x18,0x00,0x00,0x00,0x00,
-0x8c,0x65,0x00,0x08,0x8c,0x62,0x00,0x0c,0x8c,0x62,0x00,0x04,0x00,0x05,0x24,0x42,
-0x00,0x05,0x1c,0x82,0x30,0x42,0x00,0x10,0x30,0x66,0x00,0x01,0x14,0x40,0x00,0x41,
-0x30,0x87,0x00,0x01,0x27,0x82,0x90,0x08,0x01,0x02,0x10,0x21,0x80,0x44,0x00,0x00,
-0x27,0x82,0xb5,0x68,0x00,0x04,0x19,0x00,0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,
-0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x90,0x45,0x00,0x05,
-0x27,0x84,0xb4,0x90,0x00,0x64,0x18,0x21,0x90,0x63,0x00,0x00,0x10,0xa0,0x00,0x2b,
-0x2c,0x64,0x00,0x0c,0x14,0x80,0x00,0x04,0x00,0x60,0x10,0x21,0x00,0x06,0x11,0x00,
-0x00,0x62,0x10,0x21,0x24,0x42,0x00,0x24,0x3c,0x01,0xb0,0x03,0xa0,0x22,0x00,0xb9,
-0x14,0x80,0x00,0x06,0x00,0x60,0x28,0x21,0x00,0x07,0x10,0x40,0x00,0x46,0x10,0x21,
-0x00,0x02,0x11,0x00,0x00,0x62,0x10,0x21,0x24,0x45,0x00,0x04,0x01,0x49,0x10,0x21,
-0x27,0x83,0x90,0x00,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0xa0,0x18,0x21,
-0xa0,0x45,0x00,0x03,0xa0,0x45,0x00,0x00,0x24,0x02,0x00,0x08,0x12,0x02,0x00,0x0b,
-0x24,0x02,0x00,0x01,0x00,0x60,0x28,0x21,0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x8d,
-0xaf,0xa2,0x00,0x10,0x30,0x54,0xff,0xff,0x92,0x42,0x00,0x16,0x00,0x00,0x00,0x00,
-0x02,0x02,0x10,0x25,0x08,0x00,0x0a,0x3b,0xa2,0x42,0x00,0x16,0x00,0x60,0x28,0x21,
-0x02,0x40,0x20,0x21,0x0c,0x00,0x1f,0x3e,0xaf,0xa0,0x00,0x10,0x08,0x00,0x0a,0xbe,
-0x30,0x54,0xff,0xff,0x08,0x00,0x0a,0xa6,0x00,0x60,0x10,0x21,0x14,0x80,0xff,0xfd,
-0x00,0x00,0x00,0x00,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,0x08,0x00,0x0a,0xa6,
-0x24,0x42,0x00,0x04,0x27,0x82,0x90,0x00,0x01,0x02,0x10,0x21,0x90,0x43,0x00,0x00,
-0x08,0x00,0x0a,0xb6,0xa0,0x43,0x00,0x03,0x96,0x69,0x00,0x14,0x02,0xc0,0xb8,0x21,
-0x24,0x0b,0x00,0x01,0x00,0x09,0x10,0xc0,0x00,0x49,0x18,0x21,0x00,0x03,0x40,0x80,
-0x00,0x40,0x50,0x21,0x27,0x82,0x8f,0xf4,0x01,0x02,0x10,0x21,0x8c,0x43,0x00,0x18,
-0x00,0x00,0x00,0x00,0x8c,0x65,0x00,0x08,0x8c,0x62,0x00,0x0c,0x8c,0x62,0x00,0x04,
-0x00,0x05,0x24,0x42,0x00,0x05,0x1c,0x82,0x30,0x42,0x00,0x10,0x30,0x66,0x00,0x01,
-0x10,0x40,0x00,0x0d,0x30,0x87,0x00,0x01,0x27,0x82,0x90,0x08,0x01,0x02,0x10,0x21,
-0x80,0x43,0x00,0x00,0x00,0x00,0x58,0x21,0x00,0x03,0x11,0x00,0x00,0x43,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x23,0x00,0x02,0x10,0x80,0x27,0x83,0xb5,0x60,
-0x00,0x43,0x10,0x21,0xa0,0x40,0x00,0x04,0x11,0x60,0x00,0x4f,0x00,0x00,0x00,0x00,
-0x01,0x49,0x10,0x21,0x00,0x02,0x20,0x80,0x27,0x85,0x90,0x00,0x00,0x85,0x10,0x21,
-0x80,0x43,0x00,0x05,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x42,0x01,0x49,0x10,0x21,
-0x27,0x82,0x90,0x08,0x00,0x82,0x10,0x21,0x80,0x44,0x00,0x00,0x27,0x82,0xb5,0x68,
-0x00,0x04,0x19,0x00,0x00,0x64,0x18,0x23,0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x23,
-0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x90,0x45,0x00,0x05,0x27,0x84,0xb4,0x90,
-0x00,0x64,0x18,0x21,0x90,0x63,0x00,0x00,0x10,0xa0,0x00,0x2c,0x2c,0x64,0x00,0x0c,
-0x14,0x80,0x00,0x04,0x00,0x60,0x10,0x21,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,
-0x24,0x42,0x00,0x24,0x3c,0x01,0xb0,0x03,0xa0,0x22,0x00,0xb9,0x14,0x80,0x00,0x06,
-0x00,0x60,0x28,0x21,0x00,0x07,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00,
-0x00,0x62,0x10,0x21,0x24,0x45,0x00,0x04,0x01,0x49,0x10,0x21,0x27,0x83,0x90,0x00,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0xa0,0x18,0x21,0xa0,0x45,0x00,0x03,
-0xa0,0x45,0x00,0x00,0x8f,0xa4,0x00,0x18,0x24,0x02,0x00,0x08,0x10,0x82,0x00,0x0c,
-0x00,0x60,0x28,0x21,0x24,0x02,0x00,0x01,0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x8d,
-0xaf,0xa2,0x00,0x10,0x8f,0xa3,0x00,0x18,0x30,0x54,0xff,0xff,0x92,0x62,0x00,0x16,
-0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x25,0x08,0x00,0x0a,0x3b,0xa2,0x62,0x00,0x16,
-0x02,0x60,0x20,0x21,0x0c,0x00,0x1f,0x3e,0xaf,0xa0,0x00,0x10,0x08,0x00,0x0b,0x2d,
-0x00,0x00,0x00,0x00,0x08,0x00,0x0b,0x15,0x00,0x60,0x10,0x21,0x14,0x80,0xff,0xfd,
-0x00,0x00,0x00,0x00,0x00,0x06,0x11,0x00,0x00,0x62,0x10,0x21,0x08,0x00,0x0b,0x15,
-0x24,0x42,0x00,0x04,0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x90,0x43,0x00,0x00,
-0x08,0x00,0x0b,0x25,0xa0,0x43,0x00,0x03,0x27,0x85,0x90,0x00,0x08,0x00,0x0b,0x41,
-0x01,0x49,0x10,0x21,0x3c,0x02,0x80,0x00,0x00,0x62,0x18,0x26,0x08,0x00,0x0a,0x76,
-0x00,0xc2,0x30,0x26,0x12,0x00,0xff,0x2d,0x24,0x02,0x00,0x01,0x08,0x00,0x0a,0x7b,
-0x24,0x11,0x00,0x02,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd0,
-0x24,0x42,0x2d,0x44,0x34,0x63,0x00,0x20,0x3c,0x05,0xb0,0x05,0xaf,0xb3,0x00,0x24,
-0xaf,0xb2,0x00,0x20,0xaf,0xb1,0x00,0x1c,0xaf,0xbf,0x00,0x28,0xaf,0xb0,0x00,0x18,
-0xac,0x62,0x00,0x00,0x34,0xa5,0x02,0x42,0x90,0xa2,0x00,0x00,0x00,0x80,0x90,0x21,
-0x24,0x11,0x00,0x10,0x30,0x53,0x00,0xff,0x24,0x02,0x00,0x10,0x12,0x22,0x00,0xcf,
-0x00,0x00,0x18,0x21,0x24,0x02,0x00,0x11,0x12,0x22,0x00,0xc1,0x24,0x02,0x00,0x12,
-0x12,0x22,0x00,0xb4,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0xad,0xae,0x43,0x00,0x40,
-0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,0x8c,0x44,0x00,0x00,0x3c,0x03,0x00,0x02,
-0x34,0x63,0x00,0xff,0x00,0x83,0x80,0x24,0x00,0x10,0x14,0x43,0x10,0x40,0x00,0x05,
-0x00,0x00,0x00,0x00,0x8e,0x42,0x00,0x34,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x92,
-0x00,0x00,0x00,0x00,0x93,0x83,0x8b,0x61,0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x02,
-0x10,0x40,0x00,0x04,0x32,0x10,0x00,0xff,0x00,0x10,0x11,0xc3,0x14,0x40,0x00,0x86,
-0x00,0x00,0x00,0x00,0x16,0x00,0x00,0x15,0x02,0x00,0x10,0x21,0x26,0x22,0x00,0x01,
-0x30,0x51,0x00,0xff,0x2e,0x23,0x00,0x13,0x14,0x60,0xff,0xdb,0x24,0x03,0x00,0x02,
-0x12,0x63,0x00,0x73,0x24,0x02,0x00,0x05,0x2a,0x62,0x00,0x03,0x10,0x40,0x00,0x58,
-0x24,0x02,0x00,0x04,0x24,0x02,0x00,0x01,0x12,0x62,0x00,0x4b,0x02,0x40,0x20,0x21,
-0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x70,0x00,0xff,0x12,0x00,0x00,0x06,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x28,
-0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30,
-0x92,0x46,0x00,0x04,0x8e,0x43,0x00,0x24,0x24,0x02,0x00,0x07,0x02,0x40,0x20,0x21,
-0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x06,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6,
-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x24,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c,
-0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xec,0x02,0x00,0x10,0x21,
-0x92,0x46,0x00,0x05,0x8e,0x43,0x00,0x28,0x24,0x02,0x00,0x05,0x02,0x40,0x20,0x21,
-0x24,0x05,0x00,0x01,0x24,0x07,0x00,0x04,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6,
-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x28,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c,
-0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xdc,0x02,0x00,0x10,0x21,
-0x92,0x46,0x00,0x06,0x8e,0x43,0x00,0x2c,0x24,0x02,0x00,0x03,0x02,0x40,0x20,0x21,
-0x24,0x05,0x00,0x02,0x00,0x00,0x38,0x21,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6,
-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x2c,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c,
-0x00,0x00,0x00,0x00,0x30,0x50,0x00,0xff,0x16,0x00,0xff,0xcc,0x02,0x00,0x10,0x21,
-0x92,0x46,0x00,0x07,0x8e,0x43,0x00,0x30,0x24,0x02,0x00,0x02,0x02,0x40,0x20,0x21,
-0x24,0x05,0x00,0x03,0x24,0x07,0x00,0x01,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6,
-0xaf,0xa3,0x00,0x14,0xae,0x42,0x00,0x30,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x02,0x2c,
-0x08,0x00,0x0b,0x97,0x30,0x42,0x00,0xff,0x92,0x46,0x00,0x04,0x8e,0x43,0x00,0x24,
-0x24,0x02,0x00,0x07,0x00,0x00,0x28,0x21,0x24,0x07,0x00,0x06,0xaf,0xa2,0x00,0x10,
-0x0c,0x00,0x09,0xe6,0xaf,0xa3,0x00,0x14,0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x24,
-0x12,0x62,0x00,0x0d,0x24,0x02,0x00,0x03,0x24,0x02,0x00,0x08,0x16,0x62,0xff,0xa8,
-0x02,0x40,0x20,0x21,0x92,0x46,0x00,0x07,0x8e,0x42,0x00,0x30,0x24,0x05,0x00,0x03,
-0x24,0x07,0x00,0x01,0xaf,0xa3,0x00,0x10,0x0c,0x00,0x09,0xe6,0xaf,0xa2,0x00,0x14,
-0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x30,0x92,0x46,0x00,0x06,0x8e,0x43,0x00,0x2c,
-0x02,0x40,0x20,0x21,0x24,0x05,0x00,0x02,0x00,0x00,0x38,0x21,0xaf,0xa2,0x00,0x10,
-0x0c,0x00,0x09,0xe6,0xaf,0xa3,0x00,0x14,0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x2c,
-0x92,0x46,0x00,0x05,0x8e,0x43,0x00,0x28,0x02,0x40,0x20,0x21,0x24,0x05,0x00,0x01,
-0x24,0x07,0x00,0x04,0xaf,0xa2,0x00,0x10,0x0c,0x00,0x09,0xe6,0xaf,0xa3,0x00,0x14,
-0x08,0x00,0x0b,0x90,0xae,0x42,0x00,0x28,0x0c,0x00,0x01,0x59,0x24,0x04,0x00,0x01,
-0x08,0x00,0x0b,0x81,0x00,0x00,0x00,0x00,0x8f,0x84,0xb4,0x30,0xae,0x40,0x00,0x34,
-0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x84,0x00,0x00,0x00,0x00,0x93,0x83,0x8b,0x61,
-0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x02,0x10,0x40,0xff,0x69,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x01,0x59,0x00,0x00,0x20,0x21,0x08,0x00,0x0b,0x79,0x00,0x00,0x00,0x00,
-0x02,0x40,0x20,0x21,0x0c,0x00,0x09,0x5d,0x02,0x20,0x28,0x21,0x08,0x00,0x0b,0x6d,
-0x3c,0x02,0xb0,0x05,0x8e,0x42,0x00,0x3c,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x4a,
-0x00,0x00,0x00,0x00,0x8f,0x82,0xb4,0x38,0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,
-0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x2b,0x08,0x00,0x0b,0x6a,0xae,0x43,0x00,0x3c,
-0x8e,0x42,0x00,0x38,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x3d,0x24,0x02,0x00,0x12,
-0x8f,0x82,0xb4,0x34,0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,0x00,0x00,0x00,0x00,
-0x00,0x02,0x18,0x2b,0x08,0x00,0x0b,0x6a,0xae,0x43,0x00,0x38,0x8e,0x42,0x00,0x34,
-0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x30,0x24,0x02,0x00,0x11,0x8f,0x82,0xb4,0x30,
-0x00,0x00,0x00,0x00,0x90,0x42,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0x2b,
-0x08,0x00,0x0b,0x6a,0xae,0x43,0x00,0x34,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x27,0xbd,0xff,0xe0,0x34,0x63,0x00,0x20,0x24,0x42,0x30,0xf8,0x3c,0x08,0xb0,0x03,
-0xaf,0xb1,0x00,0x14,0xac,0x62,0x00,0x00,0x35,0x08,0x01,0x00,0xaf,0xbf,0x00,0x18,
-0xaf,0xb0,0x00,0x10,0x91,0x03,0x00,0x00,0x00,0xa0,0x48,0x21,0x24,0x11,0x00,0x0a,
-0x2c,0xa5,0x00,0x04,0x24,0x02,0x00,0x10,0x00,0x45,0x88,0x0a,0x30,0x63,0x00,0x01,
-0x00,0xc0,0x28,0x21,0x14,0x60,0x00,0x02,0x00,0x11,0x40,0x40,0x02,0x20,0x40,0x21,
-0x84,0x83,0x00,0x0c,0x31,0x11,0x00,0xff,0x01,0x20,0x20,0x21,0x00,0x03,0x10,0xc0,
-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x8f,0xf8,0x00,0x43,0x10,0x21,
-0x84,0x43,0x00,0x04,0x24,0x06,0x00,0x0e,0x10,0xe0,0x00,0x06,0x02,0x23,0x80,0x21,
-0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x20,0x0c,0x00,0x08,0xdf,0x00,0x00,0x00,0x00,0x02,0x11,0x18,0x21,
-0x08,0x00,0x0c,0x60,0x00,0x62,0x80,0x21,0x27,0xbd,0xff,0xd0,0xaf,0xbf,0x00,0x28,
-0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0xaf,0xb5,0x00,0x24,
-0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x84,0x82,0x00,0x0c,0x3c,0x06,0xb0,0x03,
-0x34,0xc6,0x00,0x20,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80,
-0x27,0x82,0x8f,0xf4,0x00,0x62,0x10,0x21,0x8c,0x55,0x00,0x18,0x3c,0x02,0x80,0x00,
-0x24,0x42,0x31,0xa8,0xac,0xc2,0x00,0x00,0x8e,0xb0,0x00,0x08,0x27,0x82,0x8f,0xf8,
-0x00,0x62,0x18,0x21,0x90,0x71,0x00,0x07,0x00,0x10,0x86,0x43,0x32,0x10,0x00,0x01,
-0x00,0xa0,0x38,0x21,0x02,0x00,0x30,0x21,0x00,0xa0,0x98,0x21,0x02,0x20,0x28,0x21,
-0x0c,0x00,0x0c,0x3e,0x00,0x80,0x90,0x21,0x02,0x20,0x20,0x21,0x02,0x00,0x28,0x21,
-0x24,0x06,0x00,0x14,0x0c,0x00,0x08,0xdf,0x00,0x40,0xa0,0x21,0x86,0x43,0x00,0x0c,
-0x3c,0x09,0xb0,0x09,0x3c,0x08,0xb0,0x09,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x80,0x43,0x00,0x06,
-0x3c,0x07,0xb0,0x09,0x3c,0x05,0xb0,0x09,0x28,0x62,0x00,0x00,0x24,0x64,0x00,0x03,
-0x00,0x82,0x18,0x0b,0x00,0x03,0x18,0x83,0x3c,0x02,0xb0,0x09,0x00,0x03,0x18,0x80,
-0x34,0x42,0x01,0x02,0x35,0x29,0x01,0x10,0x35,0x08,0x01,0x14,0x34,0xe7,0x01,0x20,
-0x34,0xa5,0x01,0x24,0xa4,0x54,0x00,0x00,0x12,0x60,0x00,0x11,0x02,0xa3,0xa8,0x21,
-0x8e,0xa2,0x00,0x0c,0x8e,0xa3,0x00,0x08,0x00,0x02,0x14,0x00,0x00,0x03,0x1c,0x02,
-0x00,0x43,0x10,0x21,0xad,0x22,0x00,0x00,0x8e,0xa3,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x00,0x03,0x1c,0x02,0xa5,0x03,0x00,0x00,0x8f,0xbf,0x00,0x28,0x7b,0xb4,0x01,0x3c,
-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30,
-0x8e,0xa2,0x00,0x04,0x00,0x00,0x00,0x00,0xad,0x22,0x00,0x00,0x8e,0xa4,0x00,0x08,
-0x00,0x00,0x00,0x00,0xa5,0x04,0x00,0x00,0x7a,0xa2,0x00,0x7c,0x00,0x00,0x00,0x00,
-0x00,0x03,0x1c,0x00,0x00,0x02,0x14,0x02,0x00,0x62,0x18,0x21,0xac,0xe3,0x00,0x00,
-0x8e,0xa2,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x02,0x14,0x02,0x08,0x00,0x0c,0xb2,
-0xa4,0xa2,0x00,0x00,0x27,0xbd,0xff,0xe0,0xaf,0xb2,0x00,0x18,0xaf,0xb0,0x00,0x10,
-0xaf,0xbf,0x00,0x1c,0xaf,0xb1,0x00,0x14,0x84,0x82,0x00,0x0c,0x00,0x80,0x90,0x21,
-0x3c,0x05,0xb0,0x03,0x00,0x02,0x20,0xc0,0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80,
-0x27,0x82,0x8f,0xf4,0x00,0x82,0x10,0x21,0x8c,0x51,0x00,0x18,0x3c,0x02,0x80,0x00,
-0x34,0xa5,0x00,0x20,0x24,0x42,0x33,0x24,0x27,0x83,0x8f,0xf8,0xac,0xa2,0x00,0x00,
-0x00,0x83,0x20,0x21,0x3c,0x02,0xb0,0x03,0x90,0x86,0x00,0x07,0x34,0x42,0x01,0x00,
-0x8e,0x23,0x00,0x08,0x90,0x44,0x00,0x00,0x2c,0xc5,0x00,0x04,0x24,0x02,0x00,0x10,
-0x24,0x10,0x00,0x0a,0x00,0x45,0x80,0x0a,0x00,0x03,0x1e,0x43,0x30,0x84,0x00,0x01,
-0x30,0x65,0x00,0x01,0x14,0x80,0x00,0x02,0x00,0x10,0x10,0x40,0x02,0x00,0x10,0x21,
-0x00,0xc0,0x20,0x21,0x24,0x06,0x00,0x20,0x0c,0x00,0x08,0xdf,0x30,0x50,0x00,0xff,
-0x86,0x44,0x00,0x0c,0x27,0x85,0x90,0x00,0x3c,0x06,0xb0,0x09,0x00,0x04,0x18,0xc0,
-0x00,0x64,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x65,0x18,0x21,0x80,0x64,0x00,0x06,
-0x00,0x50,0x10,0x21,0x34,0xc6,0x01,0x02,0x24,0x85,0x00,0x03,0x28,0x83,0x00,0x00,
-0x00,0xa3,0x20,0x0b,0x00,0x04,0x20,0x83,0x00,0x04,0x20,0x80,0xa4,0xc2,0x00,0x00,
-0x02,0x24,0x20,0x21,0x8c,0x83,0x00,0x04,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x10,
-0xac,0x43,0x00,0x00,0x8c,0x86,0x00,0x08,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x14,
-0xa4,0x46,0x00,0x00,0x8c,0x85,0x00,0x0c,0x8c,0x82,0x00,0x08,0x3c,0x06,0xb0,0x09,
-0x00,0x05,0x2c,0x00,0x00,0x02,0x14,0x02,0x00,0xa2,0x28,0x21,0x34,0xc6,0x01,0x20,
-0xac,0xc5,0x00,0x00,0x8c,0x83,0x00,0x0c,0x3c,0x05,0xb0,0x09,0x34,0xa5,0x01,0x24,
-0x00,0x03,0x1c,0x02,0xa4,0xa3,0x00,0x00,0x92,0x42,0x00,0x0a,0x3c,0x03,0xb0,0x09,
-0x34,0x63,0x01,0x30,0x00,0x02,0x13,0x00,0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff,
-0xa4,0x62,0x00,0x00,0x86,0x44,0x00,0x0c,0x27,0x83,0x90,0x08,0x8f,0xbf,0x00,0x1c,
-0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,
-0x94,0x44,0x00,0x02,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x3c,0x05,0xb0,0x09,
-0x34,0xa5,0x01,0x32,0xa4,0xa4,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,
-0x27,0xbd,0xff,0xe0,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,0xaf,0xb0,0x00,0x10,
-0x34,0x42,0x00,0x20,0x00,0xa0,0x80,0x21,0x24,0x63,0x34,0xb0,0x00,0x05,0x2c,0x43,
-0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x18,0xac,0x43,0x00,0x00,0x10,0xa0,0x00,0x05,
-0x00,0x80,0x88,0x21,0x8c,0x82,0x00,0x34,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0xb6,
-0x00,0x00,0x00,0x00,0x32,0x10,0x00,0xff,0x12,0x00,0x00,0x4c,0x00,0x00,0x10,0x21,
-0x24,0x02,0x00,0x08,0x12,0x02,0x00,0xa3,0x2a,0x02,0x00,0x09,0x10,0x40,0x00,0x89,
-0x24,0x02,0x00,0x40,0x24,0x04,0x00,0x02,0x12,0x04,0x00,0x79,0x2a,0x02,0x00,0x03,
-0x10,0x40,0x00,0x69,0x24,0x02,0x00,0x04,0x24,0x02,0x00,0x01,0x12,0x02,0x00,0x5a,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x00,0x08,0x3c,0x03,0x80,0x00,
-0xa2,0x20,0x00,0x4e,0xac,0x43,0x00,0x00,0x82,0x24,0x00,0x11,0x92,0x27,0x00,0x11,
-0x10,0x80,0x00,0x4e,0x00,0x00,0x00,0x00,0x92,0x26,0x00,0x0a,0x24,0x02,0x00,0x12,
-0x10,0x46,0x00,0x09,0x30,0xc2,0x00,0xff,0x27,0x83,0xb3,0xf0,0x00,0x02,0x10,0x80,
-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0x83,0x00,0x14,
-0x00,0x00,0x00,0x00,0xa6,0x23,0x00,0x0c,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x40,
-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x03,0xa2,0x23,0x00,0x10,
-0x14,0x60,0x00,0x2b,0x30,0x65,0x00,0x01,0x30,0xc2,0x00,0xff,0x27,0x83,0xb3,0xf0,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x82,0x23,0x00,0x12,
-0x90,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x00,0x02,0x11,0x42,0x30,0x42,0x00,0x01,
-0x00,0x62,0x18,0x21,0x00,0x03,0x26,0x00,0x14,0x80,0x00,0x18,0xa2,0x23,0x00,0x12,
-0x00,0x07,0x16,0x00,0x14,0x40,0x00,0x11,0x24,0x02,0x00,0x01,0x96,0x23,0x00,0x0c,
-0x27,0x84,0x90,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x44,0x10,0x21,0x80,0x45,0x00,0x06,0x00,0x03,0x1a,0x00,0x3c,0x02,0xb0,0x00,
-0x00,0x65,0x18,0x21,0x00,0x62,0x18,0x21,0x90,0x64,0x00,0x00,0x90,0x62,0x00,0x04,
-0xa2,0x20,0x00,0x15,0xa3,0x80,0x8b,0xc4,0x24,0x02,0x00,0x01,0x8f,0xbf,0x00,0x18,
-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x0c,0x00,0x0c,0xc9,
-0x02,0x20,0x20,0x21,0x92,0x27,0x00,0x11,0x08,0x00,0x0d,0x79,0x00,0x07,0x16,0x00,
-0x0c,0x00,0x0c,0x6a,0x02,0x20,0x20,0x21,0x86,0x23,0x00,0x0c,0x27,0x84,0x8f,0xf8,
-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x44,0x20,0x21,
-0x90,0x85,0x00,0x07,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0xa2,0x25,0x00,0x13,
-0x90,0x83,0x00,0x07,0x08,0x00,0x0d,0x91,0xa0,0x43,0x00,0x02,0x92,0x26,0x00,0x0a,
-0x08,0x00,0x0d,0x5a,0x30,0xc2,0x00,0xff,0x8e,0x22,0x00,0x24,0x00,0x00,0x00,0x00,
-0x10,0x50,0x00,0x07,0xa2,0x20,0x00,0x08,0x24,0x02,0x00,0x07,0xa2,0x22,0x00,0x0a,
-0x92,0x22,0x00,0x27,0xae,0x20,0x00,0x24,0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x04,
-0x08,0x00,0x0d,0xab,0x24,0x02,0x00,0x06,0x16,0x02,0xff,0x9b,0x3c,0x02,0xb0,0x05,
-0x8e,0x23,0x00,0x2c,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x07,0xa2,0x24,0x00,0x08,
-0x24,0x02,0x00,0x03,0xa2,0x22,0x00,0x0a,0x92,0x22,0x00,0x2f,0xae,0x20,0x00,0x2c,
-0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x06,0x08,0x00,0x0d,0xba,0xa2,0x20,0x00,0x0a,
-0x8e,0x22,0x00,0x28,0x24,0x03,0x00,0x01,0x24,0x04,0x00,0x01,0x10,0x44,0x00,0x07,
-0xa2,0x23,0x00,0x08,0x24,0x02,0x00,0x05,0xa2,0x22,0x00,0x0a,0x92,0x22,0x00,0x2b,
-0xae,0x20,0x00,0x28,0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x05,0x08,0x00,0x0d,0xc6,
-0x24,0x02,0x00,0x04,0x12,0x02,0x00,0x12,0x2a,0x02,0x00,0x41,0x10,0x40,0x00,0x09,
-0x24,0x02,0x00,0x80,0x24,0x02,0x00,0x20,0x16,0x02,0xff,0x7b,0x3c,0x02,0xb0,0x05,
-0x24,0x02,0x00,0x12,0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x4d,
-0xae,0x20,0x00,0x3c,0x16,0x02,0xff,0x74,0x3c,0x02,0xb0,0x05,0x24,0x02,0x00,0x10,
-0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x4d,0xae,0x20,0x00,0x34,
-0x24,0x02,0x00,0x11,0xa2,0x22,0x00,0x0a,0xa2,0x22,0x00,0x08,0x08,0x00,0x0d,0x4d,
-0xae,0x20,0x00,0x38,0x8e,0x24,0x00,0x30,0x24,0x02,0x00,0x03,0x24,0x03,0x00,0x01,
-0x10,0x83,0x00,0x07,0xa2,0x22,0x00,0x08,0x24,0x02,0x00,0x02,0xa2,0x22,0x00,0x0a,
-0x92,0x22,0x00,0x33,0xae,0x20,0x00,0x30,0x08,0x00,0x0d,0x4d,0xa2,0x22,0x00,0x07,
-0x08,0x00,0x0d,0xec,0xa2,0x24,0x00,0x0a,0x8f,0x84,0xb4,0x30,0xae,0x20,0x00,0x34,
-0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x84,0x32,0x10,0x00,0xff,0x08,0x00,0x0d,0x3e,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x37,0xe4,
-0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x80,0xa2,0x00,0x15,0x3c,0x06,0xb0,0x05,
-0x10,0x40,0x00,0x0a,0x34,0xc6,0x02,0x54,0x83,0x83,0x8b,0xc4,0x00,0x00,0x00,0x00,
-0xac,0x83,0x00,0x24,0x8c,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x42,
-0x30,0x42,0x00,0x01,0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x28,0x8c,0x82,0x00,0x2c,
-0x3c,0x06,0xb0,0x05,0x34,0xc6,0x04,0x50,0x00,0x02,0x18,0x43,0x30,0x63,0x00,0x01,
-0x10,0x40,0x00,0x04,0x30,0x45,0x00,0x01,0xac,0x83,0x00,0x28,0x03,0xe0,0x00,0x08,
-0xac,0x85,0x00,0x24,0x90,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,
-0x30,0x43,0x00,0x02,0x30,0x42,0x00,0x01,0xac,0x83,0x00,0x28,0x03,0xe0,0x00,0x08,
-0xac,0x82,0x00,0x24,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd8,
-0x34,0x63,0x00,0x20,0x24,0x42,0x38,0x74,0xac,0x62,0x00,0x00,0xaf,0xb1,0x00,0x1c,
-0xaf,0xbf,0x00,0x20,0xaf,0xb0,0x00,0x18,0x90,0xa6,0x00,0x0a,0x27,0x83,0xb3,0xf0,
-0x00,0xa0,0x88,0x21,0x00,0x06,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x50,0x00,0x00,
-0x80,0xa5,0x00,0x11,0x92,0x03,0x00,0x12,0x10,0xa0,0x00,0x04,0xa2,0x20,0x00,0x15,
-0x24,0x02,0x00,0x12,0x10,0xc2,0x00,0xda,0x00,0x00,0x00,0x00,0x82,0x22,0x00,0x12,
-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x67,0x00,0x00,0x00,0x00,0xa2,0x20,0x00,0x12,
-0xa2,0x00,0x00,0x19,0x86,0x23,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,
-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,0x00,0x43,0x10,0x21,
-0xa0,0x40,0x00,0x00,0x92,0x03,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0xdf,
-0xa2,0x03,0x00,0x16,0x82,0x02,0x00,0x12,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x20,
-0x00,0x00,0x00,0x00,0x92,0x23,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x45,
-0x24,0x02,0x00,0x01,0xa2,0x20,0x00,0x04,0x92,0x08,0x00,0x04,0x00,0x00,0x00,0x00,
-0x15,0x00,0x00,0x1e,0x24,0x02,0x00,0x01,0x92,0x07,0x00,0x0a,0xa2,0x02,0x00,0x17,
-0x92,0x02,0x00,0x16,0x30,0xe3,0x00,0xff,0x30,0x42,0x00,0xe4,0x10,0x60,0x00,0x03,
-0xa2,0x02,0x00,0x16,0x34,0x42,0x00,0x01,0xa2,0x02,0x00,0x16,0x11,0x00,0x00,0x05,
-0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02,
-0xa2,0x02,0x00,0x16,0x92,0x02,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x08,
-0x00,0x00,0x00,0x00,0x96,0x02,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x02,0x00,0x14,
-0x8f,0xbf,0x00,0x20,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,
-0x96,0x02,0x00,0x00,0x08,0x00,0x0e,0x68,0xa6,0x02,0x00,0x14,0x92,0x07,0x00,0x0a,
-0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x0e,0x54,
-0xa2,0x00,0x00,0x17,0x96,0x04,0x00,0x00,0x96,0x05,0x00,0x06,0x27,0x86,0x8f,0xf0,
-0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,
-0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21,
-0x8c,0x66,0x00,0x08,0x8c,0x45,0x00,0x08,0x3c,0x03,0x80,0x00,0x00,0xc3,0x20,0x24,
-0x10,0x80,0x00,0x08,0x00,0xa3,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21,
-0x10,0x80,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0xa6,0x18,0x2b,0x08,0x00,0x0e,0x54,
-0xa2,0x03,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0xa6,0x18,0x2b,0x08,0x00,0x0e,0x88,
-0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x05,
-0x24,0x02,0x00,0x03,0x14,0x62,0xff,0xb8,0x00,0x00,0x00,0x00,0x08,0x00,0x0e,0x4e,
-0xa2,0x20,0x00,0x07,0x08,0x00,0x0e,0x4e,0xa2,0x20,0x00,0x06,0x08,0x00,0x0e,0x4e,
-0xa2,0x20,0x00,0x05,0x82,0x22,0x00,0x10,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x69,
-0x2c,0x62,0x00,0x02,0x10,0x40,0x00,0x49,0x3c,0x02,0xb0,0x09,0x92,0x25,0x00,0x08,
-0x00,0x00,0x00,0x00,0x30,0xa6,0x00,0xff,0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x3b,
-0x2c,0xc2,0x00,0x10,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,
-0x24,0x02,0x00,0x01,0x00,0xc2,0x10,0x04,0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,
-0xa0,0x83,0x00,0x00,0x86,0x23,0x00,0x0c,0x96,0x26,0x00,0x0c,0x00,0x03,0x10,0xc0,
-0x00,0x43,0x10,0x21,0x00,0x02,0x28,0x80,0x27,0x83,0x8f,0xf4,0x00,0xa3,0x18,0x21,
-0x8c,0x64,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0x10,0x10,0x40,0x00,0x18,0x24,0x07,0x00,0x01,0x93,0x82,0x8b,0x61,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x0a,0x24,0x05,0x00,0x24,
-0x00,0x06,0x2c,0x00,0x00,0x05,0x2c,0x03,0x0c,0x00,0x1b,0x84,0x02,0x00,0x20,0x21,
-0x92,0x02,0x00,0x16,0xa2,0x00,0x00,0x12,0x30,0x42,0x00,0xe7,0x08,0x00,0x0e,0x45,
-0xa2,0x02,0x00,0x16,0xf0,0xc5,0x00,0x06,0x00,0x00,0x28,0x12,0x27,0x82,0x8f,0xf0,
-0x00,0xa2,0x28,0x21,0x0c,0x00,0x01,0x4b,0x3c,0x04,0x00,0x80,0x96,0x26,0x00,0x0c,
-0x08,0x00,0x0e,0xc5,0x00,0x06,0x2c,0x00,0x27,0x83,0x90,0x00,0x27,0x82,0x90,0x08,
-0x00,0xa2,0x10,0x21,0x00,0xa3,0x18,0x21,0x90,0x44,0x00,0x00,0x90,0x65,0x00,0x05,
-0x93,0x82,0x80,0x10,0x00,0x00,0x30,0x21,0x0c,0x00,0x21,0xf5,0xaf,0xa2,0x00,0x10,
-0x96,0x26,0x00,0x0c,0x08,0x00,0x0e,0xbf,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xcd,
-0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x30,0xa5,0x00,0x0f,
-0x24,0x02,0x00,0x80,0x08,0x00,0x0e,0xae,0x00,0xa2,0x10,0x07,0x86,0x26,0x00,0x0c,
-0x3c,0x03,0xb0,0x09,0x34,0x42,0x01,0x72,0x34,0x63,0x01,0x78,0x94,0x47,0x00,0x00,
-0x8c,0x65,0x00,0x00,0x00,0x06,0x10,0xc0,0x00,0x46,0x10,0x21,0x3c,0x04,0xb0,0x09,
-0xae,0x25,0x00,0x1c,0x34,0x84,0x01,0x7c,0x27,0x83,0x8f,0xf4,0x00,0x02,0x10,0x80,
-0x8c,0x85,0x00,0x00,0x00,0x43,0x10,0x21,0x8c,0x43,0x00,0x18,0xae,0x25,0x00,0x20,
-0xa6,0x27,0x00,0x18,0x8c,0x66,0x00,0x08,0x02,0x20,0x20,0x21,0x0c,0x00,0x0f,0x15,
-0x00,0x00,0x28,0x21,0x86,0x25,0x00,0x18,0x8e,0x26,0x00,0x1c,0x8e,0x27,0x00,0x20,
-0x02,0x20,0x20,0x21,0x0c,0x00,0x1c,0x86,0xaf,0xa2,0x00,0x10,0x08,0x00,0x0e,0x45,
-0xa2,0x02,0x00,0x12,0x92,0x22,0x00,0x08,0x08,0x00,0x0e,0x45,0xa2,0x22,0x00,0x09,
-0xa2,0x20,0x00,0x11,0x80,0x82,0x00,0x50,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x03,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0xac,0x40,0x00,0x00,0x08,0x00,0x0e,0x45,
-0xa0,0x80,0x00,0x50,0x94,0x8a,0x00,0x0c,0x24,0x03,0x00,0x24,0x00,0x80,0x70,0x21,
-0x3c,0x02,0x80,0x00,0x3c,0x04,0xb0,0x03,0x24,0x42,0x3c,0x54,0xf1,0x43,0x00,0x06,
-0x34,0x84,0x00,0x20,0x00,0x00,0x18,0x12,0x00,0xa0,0x68,0x21,0xac,0x82,0x00,0x00,
-0x27,0x85,0x90,0x00,0x27,0x82,0x8f,0xff,0x27,0xbd,0xff,0xf8,0x00,0x62,0x60,0x21,
-0x00,0x65,0x58,0x21,0x00,0x00,0xc0,0x21,0x11,0xa0,0x00,0xcc,0x00,0x00,0x78,0x21,
-0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x45,0x10,0x21,0x91,0x87,0x00,0x00,0x80,0x48,0x00,0x04,
-0x03,0xa0,0x60,0x21,0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,
-0x00,0x43,0x10,0x21,0x00,0x02,0x48,0x80,0x27,0x83,0x8f,0xf4,0xa3,0xa7,0x00,0x00,
-0x01,0x23,0x18,0x21,0x8c,0x64,0x00,0x18,0x25,0x02,0xff,0xff,0x00,0x48,0x40,0x0b,
-0x8c,0x83,0x00,0x04,0x2d,0x05,0x00,0x07,0x24,0x02,0x00,0x06,0x30,0x63,0x00,0x08,
-0x14,0x60,0x00,0x35,0x00,0x45,0x40,0x0a,0x93,0xa7,0x00,0x00,0x27,0x82,0x90,0x08,
-0x01,0x22,0x10,0x21,0x30,0xe3,0x00,0xf0,0x38,0x63,0x00,0x50,0x30,0xe5,0x00,0xff,
-0x00,0x05,0x20,0x2b,0x00,0x03,0x18,0x2b,0x00,0x64,0x18,0x24,0x90,0x49,0x00,0x00,
-0x10,0x60,0x00,0x16,0x30,0xe4,0x00,0x0f,0x24,0x02,0x00,0x04,0x10,0xa2,0x00,0x9d,
-0x00,0x00,0x00,0x00,0x11,0xa0,0x00,0x3a,0x2c,0xa2,0x00,0x0c,0x10,0x40,0x00,0x02,
-0x24,0x84,0x00,0x0c,0x00,0xe0,0x20,0x21,0x30,0x84,0x00,0xff,0x00,0x04,0x10,0x40,
-0x27,0x83,0xbb,0x0c,0x00,0x44,0x10,0x21,0x00,0x43,0x10,0x21,0x90,0x47,0x00,0x00,
-0x00,0x00,0x00,0x00,0x2c,0xe3,0x00,0x0c,0xa3,0xa7,0x00,0x00,0x10,0x60,0x00,0x02,
-0x24,0xe2,0x00,0x04,0x00,0xe0,0x10,0x21,0xa3,0xa2,0x00,0x00,0x91,0x65,0x00,0x00,
-0x91,0x82,0x00,0x00,0x30,0xa3,0x00,0xff,0x00,0x62,0x10,0x2b,0x10,0x40,0x00,0x0e,
-0x2c,0x62,0x00,0x0c,0x14,0x40,0x00,0x03,0x00,0x60,0x20,0x21,0x30,0xa2,0x00,0x0f,
-0x24,0x44,0x00,0x0c,0x00,0x04,0x10,0x40,0x00,0x44,0x20,0x21,0x27,0x83,0xbb,0x0c,
-0x00,0x83,0x18,0x21,0x90,0x62,0x00,0x02,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x05,
-0x00,0x09,0x11,0x00,0xa1,0x85,0x00,0x00,0x93,0xa2,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x08,0x00,0x49,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x27,0x83,0xb4,0x98,0x00,0x43,0x10,0x21,
-0x90,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x83,0x00,0x0c,0x14,0x60,0x00,0x06,
-0x00,0x80,0x10,0x21,0x00,0x18,0x10,0x40,0x00,0x4f,0x10,0x21,0x00,0x02,0x11,0x00,
-0x00,0x82,0x10,0x21,0x24,0x42,0x00,0x04,0x08,0x00,0x0f,0x76,0xa1,0x82,0x00,0x00,
-0x8f,0x8d,0x81,0x5c,0x00,0x00,0x00,0x00,0x01,0xa8,0x10,0x21,0x90,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0x10,0x60,0xff,0xd1,0x00,0x00,0x28,0x21,0x00,0x06,0x74,0x82,
-0x30,0xe2,0x00,0xff,0x2c,0x42,0x00,0x0c,0x14,0x40,0x00,0x03,0x00,0xe0,0x10,0x21,
-0x30,0xe2,0x00,0x0f,0x24,0x42,0x00,0x0c,0x30,0x44,0x00,0xff,0xa3,0xa2,0x00,0x00,
-0x24,0x02,0x00,0x0c,0x10,0x82,0x00,0x0d,0x00,0x09,0x11,0x00,0x00,0x49,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x04,0x18,0x40,0x00,0x49,0x10,0x23,0x00,0x64,0x18,0x21,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x27,0x84,0xb4,0x98,0x00,0x44,0x10,0x21,
-0x90,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xa7,0x00,0x00,0x00,0x0a,0x1c,0x00,
-0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x00,0x00,0x00,
-0x8c,0x83,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,0x14,0x60,0x00,0x33,
-0x00,0x06,0x14,0x42,0x00,0x09,0x11,0x00,0x00,0x49,0x10,0x23,0x00,0x02,0x10,0x80,
-0x00,0x49,0x10,0x23,0x27,0x83,0xb5,0x68,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,
-0x90,0x44,0x00,0x04,0x90,0x43,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x64,0xc0,0x24,
-0x93,0xa7,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xe2,0x00,0x0f,0x10,0x40,0x00,0x0f,
-0x31,0xcf,0x00,0x01,0x00,0x0a,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,
-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x84,0x8f,0xf0,0x00,0x44,0x10,0x21,
-0x84,0x43,0x00,0x06,0x00,0x00,0x00,0x00,0x28,0x63,0x06,0x41,0x14,0x60,0x00,0x04,
-0x30,0xe2,0x00,0xff,0x24,0x07,0x00,0x0f,0xa3,0xa7,0x00,0x00,0x30,0xe2,0x00,0xff,
-0x2c,0x42,0x00,0x0c,0x14,0x40,0x00,0x06,0x00,0xe0,0x10,0x21,0x00,0x18,0x10,0x40,
-0x00,0x4f,0x10,0x21,0x00,0x02,0x11,0x00,0x00,0x47,0x10,0x21,0x24,0x42,0x00,0x04,
-0xa3,0xa2,0x00,0x00,0x00,0x40,0x38,0x21,0x01,0xa8,0x10,0x21,0x90,0x43,0x00,0x00,
-0x24,0xa4,0x00,0x01,0x30,0x85,0xff,0xff,0x00,0xa3,0x18,0x2b,0x14,0x60,0xff,0xad,
-0x30,0xe2,0x00,0xff,0x08,0x00,0x0f,0x63,0x00,0x00,0x00,0x00,0x08,0x00,0x0f,0xc4,
-0x30,0x58,0x00,0x01,0x81,0xc2,0x00,0x48,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x73,
-0x00,0x00,0x00,0x00,0x08,0x00,0x0f,0x51,0x00,0x00,0x00,0x00,0x00,0x0a,0x1c,0x00,
-0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x45,0x10,0x21,0x80,0x48,0x00,0x05,0x91,0x67,0x00,0x00,0x08,0x00,0x0f,0x31,
-0x03,0xa0,0x58,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,
-0x24,0x42,0x3f,0xf4,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x27,0xbd,0xff,0xc0,
-0xaf,0xb7,0x00,0x34,0xaf,0xb6,0x00,0x30,0xaf,0xb5,0x00,0x2c,0xaf,0xb4,0x00,0x28,
-0xaf,0xb3,0x00,0x24,0xaf,0xb2,0x00,0x20,0xaf,0xbf,0x00,0x3c,0xaf,0xbe,0x00,0x38,
-0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,0x84,0x82,0x00,0x0c,0x27,0x93,0x8f,0xf4,
-0x3c,0x05,0xb0,0x03,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x80,
-0x00,0x73,0x10,0x21,0x8c,0x5e,0x00,0x18,0x3c,0x02,0x80,0x00,0x34,0xa5,0x00,0x20,
-0x24,0x42,0x40,0x0c,0xac,0xa2,0x00,0x00,0x8f,0xd0,0x00,0x08,0x27,0x95,0x90,0x00,
-0x00,0x75,0x18,0x21,0x00,0x00,0x28,0x21,0x02,0x00,0x30,0x21,0x90,0x71,0x00,0x00,
-0x0c,0x00,0x0f,0x15,0x00,0x80,0xb0,0x21,0x00,0x40,0x90,0x21,0x00,0x10,0x14,0x42,
-0x30,0x54,0x00,0x01,0x02,0x40,0x20,0x21,0x00,0x10,0x14,0x82,0x02,0x80,0x28,0x21,
-0x12,0x51,0x00,0x23,0x00,0x10,0xbf,0xc2,0x86,0xc3,0x00,0x0c,0x30,0x50,0x00,0x01,
-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x55,0x10,0x21,
-0xa0,0x52,0x00,0x00,0x86,0xc3,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,
-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x53,0x30,0x21,0x8c,0xc7,0x00,0x18,
-0x27,0x83,0x8f,0xf0,0x00,0x43,0x10,0x21,0x8c,0xe3,0x00,0x04,0x84,0x46,0x00,0x06,
-0x00,0x03,0x19,0x42,0x0c,0x00,0x08,0xdf,0x30,0x73,0x00,0x01,0x00,0x40,0x88,0x21,
-0x02,0x40,0x20,0x21,0x02,0x80,0x28,0x21,0x16,0xe0,0x00,0x10,0x02,0x00,0x30,0x21,
-0x86,0xc2,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,
-0x00,0x03,0x18,0x80,0x27,0x82,0x8f,0xf8,0x00,0x62,0x18,0x21,0xa4,0x71,0x00,0x04,
-0x7b,0xbe,0x01,0xfc,0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c,
-0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,0x86,0xc3,0x00,0x0c,
-0xaf,0xb3,0x00,0x10,0xaf,0xa0,0x00,0x14,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x55,0x10,0x21,0x80,0x47,0x00,0x06,0x00,0x00,0x00,0x00,
-0x24,0xe7,0x00,0x02,0x00,0x07,0x17,0xc2,0x00,0xe2,0x38,0x21,0x00,0x07,0x38,0x43,
-0x00,0x07,0x38,0x40,0x0c,0x00,0x09,0x06,0x03,0xc7,0x38,0x21,0x08,0x00,0x10,0x44,
-0x02,0x22,0x88,0x21,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xd0,
-0x34,0x63,0x00,0x20,0x24,0x42,0x41,0x94,0xaf,0xb2,0x00,0x20,0xac,0x62,0x00,0x00,
-0xaf,0xbf,0x00,0x28,0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,
-0x3c,0x02,0xb0,0x03,0x90,0x83,0x00,0x0a,0x34,0x42,0x01,0x04,0x94,0x45,0x00,0x00,
-0x00,0x03,0x18,0x80,0x27,0x82,0xb3,0xf0,0x00,0x62,0x18,0x21,0x30,0xa6,0xff,0xff,
-0x8c,0x71,0x00,0x00,0x80,0x85,0x00,0x12,0x30,0xc9,0x00,0xff,0x00,0x06,0x32,0x02,
-0xa4,0x86,0x00,0x44,0xa4,0x89,0x00,0x46,0x82,0x22,0x00,0x12,0x00,0x80,0x90,0x21,
-0x10,0xa0,0x00,0x1b,0xa0,0x80,0x00,0x15,0x00,0xc5,0x10,0x2a,0x10,0x40,0x00,0x14,
-0x00,0x00,0x00,0x00,0xa2,0x20,0x00,0x19,0x84,0x83,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x10,
-0x00,0x43,0x10,0x21,0xa0,0x40,0x00,0x00,0xa0,0x80,0x00,0x12,0x92,0x22,0x00,0x16,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xdf,0xa2,0x22,0x00,0x16,0x8f,0xbf,0x00,0x28,
-0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x30,
-0x0c,0x00,0x0f,0xfd,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x93,0x00,0x00,0x00,0x00,
-0x28,0x42,0x00,0x02,0x10,0x40,0x01,0x76,0x00,0x00,0x28,0x21,0x94,0x87,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0xe0,0x10,0x21,0x00,0x02,0x14,0x00,0x00,0x02,0x14,0x03,
-0x00,0x07,0x24,0x00,0x00,0x04,0x24,0x03,0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,
-0x00,0x04,0x28,0xc0,0x00,0xa4,0x28,0x21,0x27,0x82,0x90,0x10,0x00,0x03,0x18,0x80,
-0x00,0x62,0x18,0x21,0x00,0x05,0x28,0x80,0x27,0x82,0x8f,0xf8,0x00,0xa2,0x10,0x21,
-0x8c,0x68,0x00,0x00,0x80,0x44,0x00,0x06,0x27,0x82,0x90,0x00,0x00,0x08,0x1d,0x02,
-0x00,0xa2,0x28,0x21,0x38,0x84,0x00,0x00,0x30,0x63,0x00,0x01,0x01,0x24,0x30,0x0b,
-0x80,0xaa,0x00,0x04,0x80,0xa9,0x00,0x05,0x10,0x60,0x00,0x02,0x00,0x08,0x14,0x02,
-0x30,0x46,0x00,0x0f,0x15,0x20,0x00,0x28,0x01,0x49,0x10,0x21,0x15,0x40,0x00,0x11,
-0x30,0xe3,0xff,0xff,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa8,0x00,0xff,
-0x2d,0x02,0x00,0x04,0x10,0x40,0x01,0x46,0x2d,0x02,0x00,0x10,0x3c,0x04,0xb0,0x05,
-0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,0x01,0x02,0x10,0x04,
-0x00,0x62,0x18,0x25,0xa0,0x83,0x00,0x00,0x96,0x47,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x30,0xe3,0xff,0xff,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x27,0x84,0x90,0x00,
-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x80,0x45,0x00,0x06,0x00,0x03,0x1a,0x00,
-0x3c,0x04,0xb0,0x00,0x00,0x65,0x18,0x21,0x00,0x64,0x20,0x21,0x94,0x82,0x00,0x00,
-0x82,0x43,0x00,0x10,0x00,0x02,0x14,0x00,0x14,0x60,0x00,0x06,0x00,0x02,0x3c,0x03,
-0x30,0xe2,0x00,0x04,0x14,0x40,0x00,0x04,0x01,0x49,0x10,0x21,0x34,0xe2,0x08,0x00,
-0xa4,0x82,0x00,0x00,0x01,0x49,0x10,0x21,0x00,0x02,0x16,0x00,0x00,0x02,0x16,0x03,
-0x00,0x46,0x10,0x2a,0x10,0x40,0x00,0x7c,0x00,0x00,0x00,0x00,0x82,0x42,0x00,0x10,
-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x86,0x43,0x00,0x0c,
-0x25,0x44,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0xa0,0x44,0x00,0x04,0x92,0x23,0x00,0x16,
-0x02,0x40,0x20,0x21,0x30,0x63,0x00,0xfb,0x08,0x00,0x10,0x98,0xa2,0x23,0x00,0x16,
-0x86,0x43,0x00,0x0c,0x25,0x24,0x00,0x01,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0xa0,0x44,0x00,0x05,
-0x86,0x45,0x00,0x0c,0x0c,0x00,0x1f,0x08,0x02,0x20,0x20,0x21,0x10,0x40,0x00,0x5a,
-0x00,0x00,0x00,0x00,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa6,0x00,0xff,
-0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x4c,0x2c,0xc2,0x00,0x10,0x3c,0x04,0xb0,0x05,
-0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,0x00,0xc2,0x10,0x04,
-0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,0xa0,0x83,0x00,0x00,0x92,0x45,0x00,0x08,
-0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x14,0xa0,0x00,0x33,0x24,0x02,0x00,0x01,
-0xa2,0x40,0x00,0x04,0x92,0x22,0x00,0x04,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x0c,
-0x24,0x02,0x00,0x01,0xa2,0x22,0x00,0x17,0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x96,0x22,0x00,0x06,0x08,0x00,0x10,0x93,
-0xa6,0x22,0x00,0x14,0x96,0x22,0x00,0x00,0x08,0x00,0x10,0x93,0xa6,0x22,0x00,0x14,
-0x92,0x22,0x00,0x0a,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0x11,0x22,0xa2,0x20,0x00,0x17,0x96,0x24,0x00,0x00,0x96,0x25,0x00,0x06,
-0x27,0x86,0x8f,0xf0,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,
-0x00,0x45,0x10,0x21,0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,
-0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08,0x8c,0x44,0x00,0x08,0x3c,0x03,0x80,0x00,
-0x00,0xa3,0x30,0x24,0x10,0xc0,0x00,0x08,0x00,0x83,0x10,0x24,0x10,0x40,0x00,0x04,
-0x00,0x00,0x18,0x21,0x10,0xc0,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,
-0x08,0x00,0x11,0x22,0xa2,0x23,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,
-0x08,0x00,0x11,0x45,0x00,0x00,0x00,0x00,0x10,0xa2,0x00,0x09,0x24,0x02,0x00,0x02,
-0x10,0xa2,0x00,0x05,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xca,0x00,0x00,0x00,0x00,
-0x08,0x00,0x11,0x1d,0xa2,0x40,0x00,0x07,0x08,0x00,0x11,0x1d,0xa2,0x40,0x00,0x06,
-0x08,0x00,0x11,0x1d,0xa2,0x40,0x00,0x05,0x14,0x40,0xff,0xbe,0x3c,0x04,0xb0,0x05,
-0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,
-0x08,0x00,0x11,0x14,0x00,0xa2,0x10,0x07,0x0c,0x00,0x10,0x03,0x02,0x40,0x20,0x21,
-0x08,0x00,0x10,0x93,0x00,0x00,0x00,0x00,0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,
-0x30,0xa6,0x00,0xff,0x2c,0xc2,0x00,0x04,0x10,0x40,0x00,0x99,0x2c,0xc2,0x00,0x10,
-0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,0x24,0x02,0x00,0x01,
-0x00,0xc2,0x10,0x04,0x00,0x02,0x10,0x27,0x00,0x62,0x18,0x24,0xa0,0x83,0x00,0x00,
-0x92,0x45,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xa5,0x00,0xff,0x14,0xa0,0x00,0x80,
-0x24,0x02,0x00,0x01,0xa2,0x40,0x00,0x04,0x86,0x43,0x00,0x0c,0x27,0x93,0x8f,0xf4,
-0x96,0x47,0x00,0x0c,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,0x00,0x02,0x28,0x80,
-0x00,0xb3,0x18,0x21,0x8c,0x64,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x10,0x10,0x40,0x00,0x64,0x00,0x00,0x30,0x21,
-0x00,0x07,0x1c,0x00,0x00,0x03,0x1c,0x03,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x53,0x10,0x21,0x8c,0x43,0x00,0x18,0x93,0x82,0x8b,0x61,
-0x8c,0x64,0x00,0x04,0x30,0x42,0x00,0x01,0x00,0x04,0x21,0x42,0x14,0x40,0x00,0x4d,
-0x30,0x90,0x00,0x01,0x00,0x07,0x2c,0x00,0x00,0x05,0x2c,0x03,0x0c,0x00,0x1b,0x84,
-0x02,0x20,0x20,0x21,0x96,0x26,0x00,0x06,0x12,0x00,0x00,0x14,0x30,0xc5,0xff,0xff,
-0x02,0x60,0x90,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x52,0x18,0x21,0x92,0x22,0x00,0x0a,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0b,
-0x02,0x20,0x20,0x21,0x8c,0x63,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x62,0x00,0x04,
-0x00,0x00,0x00,0x00,0x00,0x02,0x11,0x42,0x0c,0x00,0x1b,0x84,0x30,0x50,0x00,0x01,
-0x96,0x26,0x00,0x06,0x16,0x00,0xff,0xef,0x30,0xc5,0xff,0xff,0x92,0x22,0x00,0x04,
-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x0d,0x24,0x02,0x00,0x01,0xa2,0x22,0x00,0x17,
-0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x05,0x00,0x00,0x00,0x00,
-0xa6,0x26,0x00,0x14,0x92,0x22,0x00,0x16,0x08,0x00,0x10,0x92,0x30,0x42,0x00,0xc3,
-0x96,0x22,0x00,0x00,0x08,0x00,0x11,0xb9,0xa6,0x22,0x00,0x14,0x92,0x22,0x00,0x0a,
-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x11,0xb4,
-0xa2,0x20,0x00,0x17,0x96,0x24,0x00,0x00,0x30,0xc5,0xff,0xff,0x00,0x05,0x18,0xc0,
-0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x65,0x18,0x21,0x27,0x84,0x8f,0xf0,
-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,0x00,0x03,0x18,0x80,0x8c,0x45,0x00,0x08,
-0x00,0x64,0x18,0x21,0x8c,0x64,0x00,0x08,0x3c,0x02,0x80,0x00,0x00,0xa2,0x38,0x24,
-0x10,0xe0,0x00,0x08,0x00,0x82,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21,
-0x10,0xe0,0x00,0x02,0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,0x08,0x00,0x11,0xb4,
-0xa2,0x23,0x00,0x17,0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,0x08,0x00,0x11,0xd8,
-0x00,0x00,0x00,0x00,0x24,0x05,0x00,0x24,0xf0,0xe5,0x00,0x06,0x00,0x00,0x28,0x12,
-0x27,0x82,0x8f,0xf0,0x00,0xa2,0x28,0x21,0x0c,0x00,0x01,0x4b,0x00,0x00,0x20,0x21,
-0x96,0x47,0x00,0x0c,0x08,0x00,0x11,0x96,0x00,0x07,0x2c,0x00,0x27,0x83,0x90,0x00,
-0x27,0x82,0x90,0x08,0x00,0xa2,0x10,0x21,0x00,0xa3,0x18,0x21,0x90,0x44,0x00,0x00,
-0x90,0x65,0x00,0x05,0x93,0x82,0x80,0x10,0x24,0x07,0x00,0x01,0x0c,0x00,0x21,0xf5,
-0xaf,0xa2,0x00,0x10,0x96,0x47,0x00,0x0c,0x08,0x00,0x11,0x89,0x00,0x07,0x1c,0x00,
-0x10,0xa2,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x05,0x24,0x02,0x00,0x03,
-0x14,0xa2,0xff,0x7d,0x00,0x00,0x00,0x00,0x08,0x00,0x11,0x7a,0xa2,0x40,0x00,0x07,
-0x08,0x00,0x11,0x7a,0xa2,0x40,0x00,0x06,0x08,0x00,0x11,0x7a,0xa2,0x40,0x00,0x05,
-0x14,0x40,0xff,0x71,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,
-0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,0x08,0x00,0x11,0x71,0x00,0xa2,0x10,0x07,
-0x14,0x40,0xfe,0xc3,0x3c,0x04,0xb0,0x05,0x34,0x84,0x02,0x29,0x90,0x83,0x00,0x00,
-0x30,0xa5,0x00,0x0f,0x24,0x02,0x00,0x80,0x08,0x00,0x10,0xcc,0x00,0xa2,0x10,0x07,
-0x84,0x83,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x47,0x00,0x18,
-0x00,0x00,0x00,0x00,0x8c,0xe6,0x00,0x08,0x0c,0x00,0x0f,0x15,0x00,0x00,0x00,0x00,
-0x02,0x40,0x20,0x21,0x00,0x00,0x28,0x21,0x00,0x00,0x30,0x21,0x00,0x00,0x38,0x21,
-0x0c,0x00,0x1c,0x86,0xaf,0xa2,0x00,0x10,0x00,0x02,0x1e,0x00,0x14,0x60,0xfe,0x6b,
-0xa2,0x22,0x00,0x12,0x92,0x43,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x40,
-0x24,0x02,0x00,0x01,0xa2,0x40,0x00,0x04,0x92,0x28,0x00,0x04,0x00,0x00,0x00,0x00,
-0x15,0x00,0x00,0x19,0x24,0x02,0x00,0x01,0x92,0x27,0x00,0x0a,0xa2,0x22,0x00,0x17,
-0x92,0x22,0x00,0x17,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x10,0x00,0x00,0x00,0x00,
-0x96,0x22,0x00,0x06,0x00,0x00,0x00,0x00,0xa6,0x22,0x00,0x14,0x92,0x22,0x00,0x16,
-0x30,0xe3,0x00,0xff,0x30,0x42,0x00,0xc0,0x10,0x60,0x00,0x03,0xa2,0x22,0x00,0x16,
-0x34,0x42,0x00,0x01,0xa2,0x22,0x00,0x16,0x11,0x00,0xfe,0x50,0x00,0x00,0x00,0x00,
-0x92,0x22,0x00,0x16,0x08,0x00,0x10,0x92,0x34,0x42,0x00,0x02,0x96,0x22,0x00,0x00,
-0x08,0x00,0x12,0x3b,0xa6,0x22,0x00,0x14,0x92,0x27,0x00,0x0a,0x00,0x00,0x00,0x00,
-0x14,0xe0,0x00,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0x12,0x34,0xa2,0x20,0x00,0x17,
-0x96,0x24,0x00,0x00,0x96,0x25,0x00,0x06,0x27,0x86,0x8f,0xf0,0x00,0x04,0x18,0xc0,
-0x00,0x64,0x18,0x21,0x00,0x05,0x10,0xc0,0x00,0x45,0x10,0x21,0x00,0x03,0x18,0x80,
-0x00,0x66,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08,
-0x8c,0x44,0x00,0x08,0x3c,0x03,0x80,0x00,0x00,0xa3,0x30,0x24,0x10,0xc0,0x00,0x08,
-0x00,0x83,0x10,0x24,0x10,0x40,0x00,0x04,0x00,0x00,0x18,0x21,0x10,0xc0,0x00,0x02,
-0x24,0x03,0x00,0x01,0x00,0x85,0x18,0x2b,0x08,0x00,0x12,0x34,0xa2,0x23,0x00,0x17,
-0x10,0x40,0xff,0xfd,0x00,0x85,0x18,0x2b,0x08,0x00,0x12,0x63,0x00,0x00,0x00,0x00,
-0x10,0x62,0x00,0x09,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x05,0x24,0x02,0x00,0x03,
-0x14,0x62,0xff,0xbd,0x00,0x00,0x00,0x00,0x08,0x00,0x12,0x2e,0xa2,0x40,0x00,0x07,
-0x08,0x00,0x12,0x2e,0xa2,0x40,0x00,0x06,0x08,0x00,0x12,0x2e,0xa2,0x40,0x00,0x05,
-0x3c,0x02,0x80,0x00,0x00,0x82,0x30,0x24,0x10,0xc0,0x00,0x08,0x00,0xa2,0x18,0x24,
-0x10,0x60,0x00,0x04,0x00,0x00,0x10,0x21,0x10,0xc0,0x00,0x02,0x24,0x02,0x00,0x01,
-0x00,0xa4,0x10,0x2b,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x60,0xff,0xfd,
-0x00,0xa4,0x10,0x2b,0x08,0x00,0x12,0x7e,0x00,0x00,0x00,0x00,0x30,0x82,0xff,0xff,
-0x00,0x02,0x18,0xc0,0x00,0x62,0x18,0x21,0x27,0x84,0x90,0x00,0x00,0x03,0x18,0x80,
-0x00,0x64,0x18,0x21,0x80,0x66,0x00,0x06,0x00,0x02,0x12,0x00,0x3c,0x03,0xb0,0x00,
-0x00,0x46,0x10,0x21,0x00,0x45,0x10,0x21,0x03,0xe0,0x00,0x08,0x00,0x43,0x10,0x21,
-0x27,0xbd,0xff,0xe0,0x30,0x82,0x00,0x7c,0x30,0x84,0xff,0x00,0xaf,0xbf,0x00,0x1c,
-0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x14,0x40,0x00,0x41,
-0x00,0x04,0x22,0x03,0x24,0x02,0x00,0x04,0x3c,0x10,0xb0,0x03,0x8e,0x10,0x00,0x00,
-0x10,0x82,0x00,0x32,0x24,0x02,0x00,0x08,0x10,0x82,0x00,0x03,0x32,0x02,0x00,0x20,
-0x08,0x00,0x12,0xa4,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x17,0x3c,0x02,0xb0,0x06,
-0x34,0x42,0x80,0x24,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x67,0x00,0xff,
-0x10,0xe0,0x00,0x23,0x00,0x00,0x88,0x21,0x8f,0x85,0x8f,0xd0,0x00,0x40,0x30,0x21,
-0x94,0xa2,0x00,0x08,0x8c,0xc3,0x00,0x00,0x26,0x31,0x00,0x01,0x24,0x42,0x00,0x02,
-0x30,0x42,0x01,0xff,0x34,0x63,0x01,0x00,0x02,0x27,0x20,0x2a,0xa4,0xa2,0x00,0x08,
-0x14,0x80,0xff,0xf7,0xac,0xc3,0x00,0x00,0x84,0xa3,0x00,0x08,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0x30,0xac,0x43,0x00,0x00,0x27,0x92,0xb3,0xf0,0x24,0x11,0x00,0x12,
-0x8e,0x44,0x00,0x00,0x26,0x31,0xff,0xff,0x90,0x82,0x00,0x10,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x03,0x26,0x52,0x00,0x04,0x0c,0x00,0x20,0xd0,0x00,0x00,0x00,0x00,
-0x06,0x21,0xff,0xf7,0x24,0x02,0xff,0xdf,0x02,0x02,0x80,0x24,0x3c,0x01,0xb0,0x03,
-0x0c,0x00,0x13,0x18,0xac,0x30,0x00,0x00,0x08,0x00,0x12,0xa4,0x00,0x00,0x00,0x00,
-0x8f,0x85,0x8f,0xd0,0x08,0x00,0x12,0xba,0x00,0x00,0x00,0x00,0x24,0x02,0xff,0x95,
-0x3c,0x03,0xb0,0x03,0x02,0x02,0x80,0x24,0x34,0x63,0x00,0x30,0x3c,0x01,0xb0,0x03,
-0xac,0x30,0x00,0x00,0x0c,0x00,0x12,0xe1,0xac,0x60,0x00,0x00,0x08,0x00,0x12,0xa4,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x50,0x08,0x00,0x12,0xa4,
-0xac,0x46,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4b,0x84,0x3c,0x0b,0xb0,0x03,
-0xad,0x6a,0x00,0x20,0x3c,0x08,0x80,0x01,0x25,0x08,0x00,0x00,0x3c,0x09,0x80,0x01,
-0x25,0x29,0x03,0x1c,0x11,0x09,0x00,0x10,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,
-0x25,0x4a,0x4b,0xac,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0x3c,0x08,0xb0,0x06,
-0x35,0x08,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8d,0x09,0x00,0x00,
-0x00,0x00,0x00,0x00,0x31,0x29,0x00,0x01,0x00,0x00,0x00,0x00,0x24,0x01,0x00,0x01,
-0x15,0x21,0xff,0xf2,0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4b,0xe8,
-0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,0x3c,0x02,0xb0,0x03,0x8c,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0x34,0x63,0x00,0x40,0x00,0x00,0x00,0x00,0xac,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0x14,0x3c,0x0b,0xb0,0x03,
-0xad,0x6a,0x00,0x20,0x3c,0x02,0x80,0x01,0x24,0x42,0x00,0x00,0x3c,0x03,0x80,0x01,
-0x24,0x63,0x03,0x1c,0x3c,0x04,0xb0,0x00,0x8c,0x85,0x00,0x00,0x00,0x00,0x00,0x00,
-0xac,0x45,0x00,0x00,0x24,0x42,0x00,0x04,0x24,0x84,0x00,0x04,0x00,0x43,0x08,0x2a,
-0x14,0x20,0xff,0xf9,0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0x18,0x00,0x00,0x00,0x00,
-0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0x60,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,
-0x3c,0x02,0x80,0x01,0x24,0x42,0x03,0x20,0x3c,0x03,0x80,0x01,0x24,0x63,0x3f,0x14,
-0xac,0x40,0x00,0x00,0xac,0x40,0x00,0x04,0xac,0x40,0x00,0x08,0xac,0x40,0x00,0x0c,
-0x24,0x42,0x00,0x10,0x00,0x43,0x08,0x2a,0x14,0x20,0xff,0xf9,0x00,0x00,0x00,0x00,
-0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0xa0,0x3c,0x0b,0xb0,0x03,0xad,0x6a,0x00,0x20,
-0x3c,0x1c,0x80,0x01,0x27,0x9c,0x7f,0xf0,0x27,0x9d,0x8b,0xd0,0x00,0x00,0x00,0x00,
-0x27,0x9d,0x8f,0xb8,0x3c,0x0a,0x80,0x00,0x25,0x4a,0x4c,0xc4,0x3c,0x0b,0xb0,0x03,
-0xad,0x6a,0x00,0x20,0x40,0x80,0x68,0x00,0x40,0x08,0x60,0x00,0x00,0x00,0x00,0x00,
-0x35,0x08,0xff,0x01,0x40,0x88,0x60,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x15,0x65,
-0x00,0x00,0x00,0x00,0x24,0x84,0xf8,0x00,0x30,0x87,0x00,0x03,0x00,0x04,0x30,0x40,
-0x00,0xc7,0x20,0x23,0x3c,0x02,0xb0,0x0a,0x27,0xbd,0xff,0xe0,0x24,0x03,0xff,0xff,
-0x00,0x82,0x20,0x21,0xaf,0xb1,0x00,0x14,0xac,0x83,0x10,0x00,0xaf,0xbf,0x00,0x18,
-0xaf,0xb0,0x00,0x10,0x00,0xa0,0x88,0x21,0x24,0x03,0x00,0x01,0x8c,0x82,0x10,0x00,
-0x00,0x00,0x00,0x00,0x14,0x43,0xff,0xfd,0x00,0xc7,0x10,0x23,0x3c,0x03,0xb0,0x0a,
-0x00,0x43,0x10,0x21,0x8c,0x50,0x00,0x00,0x0c,0x00,0x13,0x95,0x02,0x20,0x20,0x21,
-0x02,0x11,0x80,0x24,0x00,0x50,0x80,0x06,0x02,0x00,0x10,0x21,0x8f,0xbf,0x00,0x18,
-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x27,0xbd,0xff,0xd8,
-0xaf,0xb2,0x00,0x18,0x00,0xa0,0x90,0x21,0x24,0x05,0xff,0xff,0xaf,0xb3,0x00,0x1c,
-0xaf,0xbf,0x00,0x20,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x00,0xc0,0x98,0x21,
-0x12,0x45,0x00,0x23,0x24,0x84,0xf8,0x00,0x30,0x83,0x00,0x03,0x00,0x04,0x10,0x40,
-0x00,0x40,0x88,0x21,0x00,0x60,0x20,0x21,0x00,0x43,0x10,0x23,0x3c,0x03,0xb0,0x0a,
-0x00,0x43,0x10,0x21,0xac,0x45,0x10,0x00,0x00,0x40,0x18,0x21,0x24,0x05,0x00,0x01,
-0x8c,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x14,0x45,0xff,0xfd,0x3c,0x02,0xb0,0x0a,
-0x02,0x24,0x88,0x23,0x02,0x22,0x88,0x21,0x8e,0x30,0x00,0x00,0x0c,0x00,0x13,0x95,
-0x02,0x40,0x20,0x21,0x00,0x12,0x18,0x27,0x02,0x03,0x80,0x24,0x00,0x53,0x10,0x04,
-0x02,0x02,0x80,0x25,0xae,0x30,0x00,0x00,0x24,0x03,0x00,0x01,0x8e,0x22,0x10,0x00,
-0x00,0x00,0x00,0x00,0x14,0x43,0xff,0xfd,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x20,
-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,
-0x30,0x82,0x00,0x03,0x00,0x04,0x18,0x40,0x00,0x62,0x18,0x23,0x3c,0x04,0xb0,0x0a,
-0x00,0x64,0x18,0x21,0xac,0x66,0x00,0x00,0x24,0x04,0x00,0x01,0x8c,0x62,0x10,0x00,
-0x00,0x00,0x00,0x00,0x14,0x44,0xff,0xfd,0x00,0x00,0x00,0x00,0x08,0x00,0x13,0x83,
-0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x21,0x00,0x64,0x10,0x06,0x30,0x42,0x00,0x01,
-0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x24,0x63,0x00,0x01,0x2c,0x62,0x00,0x20,
-0x14,0x40,0xff,0xf9,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,
-0x27,0xbd,0xff,0xe0,0x3c,0x03,0xb0,0x05,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,
-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x1c,0x00,0x80,0x90,0x21,0x00,0xa0,0x80,0x21,
-0x00,0xc0,0x88,0x21,0x34,0x63,0x02,0x2e,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0x01,0x14,0x40,0xff,0xfc,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0xc0,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0xc0,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x3c,0x02,0xc0,0x00,0x00,0x10,0x1c,0x00,
-0x34,0x42,0x04,0x00,0x3c,0x04,0xb0,0x05,0x3c,0x05,0xb0,0x05,0x24,0x63,0x16,0x09,
-0x02,0x22,0x10,0x21,0x34,0x84,0x04,0x20,0x34,0xa5,0x04,0x24,0x3c,0x06,0xb0,0x05,
-0xac,0x83,0x00,0x00,0x24,0x07,0x00,0x01,0xac,0xa2,0x00,0x00,0x34,0xc6,0x02,0x28,
-0x24,0x02,0x00,0x20,0xae,0x47,0x00,0x3c,0x24,0x04,0x08,0x24,0xa0,0xc2,0x00,0x00,
-0x3c,0x05,0x00,0xc0,0xa2,0x47,0x00,0x11,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,
-0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0xc0,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,
-0x8f,0xbf,0x00,0x1c,0x8f,0xb2,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x20,0x24,0x02,0x00,0x06,0xac,0x82,0x00,0x0c,0xa0,0x80,0x00,0x50,
-0xac,0x80,0x00,0x00,0xac,0x80,0x00,0x04,0xac,0x80,0x00,0x08,0xac,0x80,0x00,0x14,
-0xac,0x80,0x00,0x18,0xac,0x80,0x00,0x1c,0xa4,0x80,0x00,0x20,0xac,0x80,0x00,0x24,
-0xac,0x80,0x00,0x28,0xac,0x80,0x00,0x2c,0xa0,0x80,0x00,0x30,0xa0,0x80,0x00,0x31,
-0xac,0x80,0x00,0x34,0xac,0x80,0x00,0x38,0xa0,0x80,0x00,0x3c,0xac,0x82,0x00,0x10,
-0xa0,0x80,0x00,0x44,0xac,0x80,0x00,0x48,0x03,0xe0,0x00,0x08,0xac,0x80,0x00,0x4c,
-0x3c,0x04,0xb0,0x06,0x34,0x84,0x80,0x00,0x8c,0x83,0x00,0x00,0x3c,0x02,0x12,0x00,
-0x3c,0x05,0xb0,0x03,0x00,0x62,0x18,0x25,0x34,0xa5,0x00,0x8b,0x24,0x02,0xff,0x80,
-0xac,0x83,0x00,0x00,0x03,0xe0,0x00,0x08,0xa0,0xa2,0x00,0x00,0x3c,0x04,0xb0,0x03,
-0x34,0x84,0x00,0x0b,0x24,0x02,0x00,0x22,0x3c,0x05,0xb0,0x01,0x3c,0x06,0x45,0x67,
-0x3c,0x0a,0xb0,0x09,0xa0,0x82,0x00,0x00,0x34,0xa5,0x00,0x04,0x34,0xc6,0x89,0xaa,
-0x35,0x4a,0x00,0x04,0x24,0x02,0x01,0x23,0x3c,0x0b,0xb0,0x09,0x3c,0x07,0x01,0x23,
-0x3c,0x0c,0xb0,0x09,0x3c,0x01,0xb0,0x01,0xac,0x20,0x00,0x00,0x27,0xbd,0xff,0xe0,
-0xac,0xa0,0x00,0x00,0x35,0x6b,0x00,0x08,0x3c,0x01,0xb0,0x09,0xac,0x26,0x00,0x00,
-0x34,0xe7,0x45,0x66,0xa5,0x42,0x00,0x00,0x35,0x8c,0x00,0x0c,0x24,0x02,0xcd,0xef,
-0x3c,0x0d,0xb0,0x09,0x3c,0x08,0xcd,0xef,0x3c,0x0e,0xb0,0x09,0xad,0x67,0x00,0x00,
-0xaf,0xb7,0x00,0x1c,0xa5,0x82,0x00,0x00,0xaf,0xb6,0x00,0x18,0xaf,0xb5,0x00,0x14,
-0xaf,0xb4,0x00,0x10,0xaf,0xb3,0x00,0x0c,0xaf,0xb2,0x00,0x08,0xaf,0xb1,0x00,0x04,
-0xaf,0xb0,0x00,0x00,0x35,0xad,0x00,0x10,0x35,0x08,0x01,0x22,0x35,0xce,0x00,0x14,
-0x24,0x02,0x89,0xab,0x3c,0x0f,0xb0,0x09,0x3c,0x09,0x89,0xab,0x3c,0x10,0xb0,0x09,
-0x3c,0x11,0xb0,0x09,0x3c,0x12,0xb0,0x09,0x3c,0x13,0xb0,0x09,0x3c,0x14,0xb0,0x09,
-0x3c,0x15,0xb0,0x09,0x3c,0x16,0xb0,0x09,0x3c,0x17,0xb0,0x09,0xad,0xa8,0x00,0x00,
-0x24,0x03,0xff,0xff,0xa5,0xc2,0x00,0x00,0x35,0xef,0x00,0x18,0x35,0x29,0xcd,0xee,
-0x36,0x10,0x00,0x1c,0x36,0x31,0x00,0x20,0x36,0x52,0x00,0x24,0x36,0x73,0x00,0x28,
-0x36,0x94,0x00,0x2c,0x36,0xb5,0x00,0x30,0x36,0xd6,0x00,0x34,0x36,0xf7,0x00,0x38,
-0x24,0x02,0x45,0x67,0xad,0xe9,0x00,0x00,0xa6,0x02,0x00,0x00,0xae,0x23,0x00,0x00,
-0x8f,0xb0,0x00,0x00,0xa6,0x43,0x00,0x00,0x8f,0xb1,0x00,0x04,0xae,0x63,0x00,0x00,
-0x8f,0xb2,0x00,0x08,0xa6,0x83,0x00,0x00,0x8f,0xb3,0x00,0x0c,0xae,0xa3,0x00,0x00,
-0x8f,0xb4,0x00,0x10,0xa6,0xc3,0x00,0x00,0x8f,0xb5,0x00,0x14,0xae,0xe3,0x00,0x00,
-0x7b,0xb6,0x00,0xfc,0x3c,0x18,0xb0,0x09,0x37,0x18,0x00,0x3c,0xa7,0x03,0x00,0x00,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x34,0x63,0x00,0x20,0x24,0x42,0x51,0x38,0xac,0x62,0x00,0x00,0x8c,0x83,0x00,0x34,
-0x34,0x02,0xff,0xff,0x00,0x43,0x10,0x2a,0x14,0x40,0x01,0x0b,0x00,0x80,0x30,0x21,
-0x8c,0x84,0x00,0x08,0x24,0x02,0x00,0x03,0x10,0x82,0x00,0xfe,0x00,0x00,0x00,0x00,
-0x8c,0xc2,0x00,0x2c,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x47,0x24,0x02,0x00,0x06,
-0x3c,0x03,0xb0,0x05,0x34,0x63,0x04,0x50,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xff,0x14,0x40,0x00,0xe4,0xac,0xc2,0x00,0x2c,0x24,0x02,0x00,0x01,
-0x10,0x82,0x00,0xe3,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0xd1,
-0x00,0x00,0x00,0x00,0x8c,0xc7,0x00,0x04,0x24,0x02,0x00,0x02,0x10,0xe2,0x00,0xc7,
-0x00,0x00,0x00,0x00,0x8c,0xc2,0x00,0x14,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x09,
-0x24,0x02,0x00,0x01,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0x10,0x40,0x00,0x05,0xac,0xc2,0x00,0x14,
-0x24,0x02,0x00,0x01,0xac,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0xac,0xc0,0x00,0x14,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,
-0x04,0x61,0x00,0x16,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2e,0x90,0x62,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x10,0x3c,0x02,0xb0,0x05,
-0x34,0x42,0x02,0x42,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x0b,
-0x00,0x00,0x00,0x00,0x80,0xc2,0x00,0x50,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x07,
-0x00,0x00,0x00,0x00,0x14,0x80,0x00,0x05,0x24,0x02,0x00,0x0e,0x24,0x03,0x00,0x01,
-0xac,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0xa0,0xc3,0x00,0x50,0x80,0xc2,0x00,0x31,
-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0a,0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18,
-0x8c,0x43,0x00,0x00,0x3c,0x04,0xf0,0x00,0x3c,0x02,0x80,0x00,0x00,0x64,0x18,0x24,
-0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x09,0x03,0xe0,0x00,0x08,0xac,0xc2,0x00,0x00,
-0x8c,0xc2,0x00,0x40,0x00,0x00,0x00,0x00,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,
-0x10,0x60,0x00,0x09,0x3c,0x03,0xb0,0x03,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2c,
-0x8c,0x43,0x00,0x00,0x3c,0x04,0x00,0x02,0x00,0x64,0x18,0x24,0x14,0x60,0xff,0xf2,
-0x24,0x02,0x00,0x10,0x3c,0x03,0xb0,0x03,0x34,0x63,0x02,0x01,0x90,0x62,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x80,0x10,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,
-0x8c,0xc3,0x00,0x0c,0x00,0x00,0x00,0x00,0xac,0xc3,0x00,0x10,0x3c,0x02,0xb0,0x03,
-0x90,0x42,0x02,0x01,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x0f,0xac,0xc2,0x00,0x0c,
-0x90,0xc3,0x00,0x0f,0x24,0x02,0x00,0x0d,0x3c,0x01,0xb0,0x03,0x08,0x00,0x14,0xa6,
-0xa0,0x23,0x02,0x01,0x3c,0x02,0xb0,0x09,0x34,0x42,0x01,0x80,0x90,0x44,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x04,0x1e,0x00,0x00,0x03,0x1e,0x03,0x10,0x60,0x00,0x15,
-0xa0,0xc4,0x00,0x44,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x0b,0x24,0x02,0x00,0x02,
-0x10,0x62,0x00,0x03,0x24,0x03,0x00,0x0d,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x8c,0xc2,0x00,0x0c,0xac,0xc3,0x00,0x00,0x24,0x03,0x00,0x04,0xac,0xc2,0x00,0x10,
-0x03,0xe0,0x00,0x08,0xac,0xc3,0x00,0x0c,0x24,0x02,0x00,0x0d,0xac,0xc2,0x00,0x00,
-0x24,0x03,0x00,0x04,0x24,0x02,0x00,0x06,0xac,0xc3,0x00,0x10,0x03,0xe0,0x00,0x08,
-0xac,0xc2,0x00,0x0c,0x8c,0xc3,0x00,0x38,0x00,0x00,0x00,0x00,0x2c,0x62,0x00,0x06,
-0x10,0x40,0x00,0x2e,0x00,0x03,0x10,0x80,0x3c,0x03,0x80,0x01,0x24,0x63,0x02,0x00,
-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x06,0x24,0x02,0x00,0x03,
-0x8c,0xa2,0x02,0xbc,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x06,0x3c,0x03,0xb0,0x06,
-0x24,0x02,0x00,0x02,0xac,0xc2,0x00,0x00,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,
-0xac,0xc2,0x00,0x38,0x34,0x63,0x80,0x24,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xff,0x10,0x40,0x00,0x05,0xac,0xc2,0x00,0x18,0x24,0x02,0x00,0x02,
-0xac,0xc2,0x00,0x00,0x08,0x00,0x14,0xfa,0xac,0xc0,0x00,0x18,0x08,0x00,0x14,0xfa,
-0xac,0xc0,0x00,0x00,0x24,0x02,0x00,0x02,0x24,0x03,0x00,0x0b,0xac,0xc2,0x00,0x38,
-0x03,0xe0,0x00,0x08,0xac,0xc3,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x05,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x0c,0xac,0xc2,0x00,0x00,0x08,0x00,0x14,0xfb,
-0x24,0x02,0x00,0x04,0x08,0x00,0x15,0x12,0x24,0x02,0x00,0x03,0xac,0xc0,0x00,0x38,
-0x03,0xe0,0x00,0x08,0xac,0xc0,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xe2,0x00,0x05,
-0x24,0x02,0x00,0x03,0x80,0xc2,0x00,0x30,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x08,
-0x24,0x02,0x00,0x04,0xac,0xc2,0x00,0x00,0x93,0x82,0x86,0x3c,0x00,0x00,0x00,0x00,
-0x14,0x40,0xff,0xd6,0x24,0x02,0x00,0x05,0x03,0xe0,0x00,0x08,0xac,0xc0,0x00,0x38,
-0x08,0x00,0x15,0x22,0xac,0xc0,0x00,0x00,0x3c,0x02,0xb0,0x06,0x34,0x42,0x80,0x18,
-0x8c,0x43,0x00,0x00,0x3c,0x04,0xf0,0x00,0x3c,0x02,0x80,0x00,0x00,0x64,0x18,0x24,
-0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x09,0x08,0x00,0x15,0x26,0xac,0xc2,0x00,0x00,
-0x24,0x02,0x00,0x05,0x08,0x00,0x15,0x18,0xac,0xc2,0x00,0x38,0x80,0xc2,0x00,0x30,
-0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x37,0x24,0x02,0x00,0x04,0x08,0x00,0x14,0xa6,
-0x00,0x00,0x00,0x00,0x84,0xc2,0x00,0x20,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x66,
-0x24,0x02,0x00,0x06,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21,
-0x14,0x40,0xff,0x24,0xa4,0xc3,0x00,0x20,0x08,0x00,0x14,0xa6,0x24,0x02,0x00,0x06,
-0x8c,0xc2,0x00,0x1c,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0x57,0x24,0x02,0x00,0x05,
-0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xff,0x10,0x40,0xff,0x14,0xac,0xc2,0x00,0x1c,0x08,0x00,0x14,0xa6,
-0x24,0x02,0x00,0x05,0x3c,0x02,0xb0,0x05,0x8c,0x42,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x02,0x17,0x42,0x30,0x42,0x00,0x01,0x14,0x40,0xff,0x47,0x24,0x02,0x00,0x06,
-0x08,0x00,0x14,0x5c,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x0a,0x03,0xe0,0x00,0x08,
-0xac,0x82,0x00,0x00,0x27,0xbd,0xff,0xd8,0xaf,0xb0,0x00,0x10,0x27,0x90,0x86,0x48,
-0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb2,0x00,0x18,0x0c,0x00,0x2b,0xe8,
-0xaf,0xb1,0x00,0x14,0xaf,0x90,0x8f,0xd0,0x48,0x02,0x00,0x00,0x0c,0x00,0x13,0xec,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x18,0x4e,0x02,0x00,0x20,0x21,0x0c,0x00,0x00,0x34,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x13,0xf7,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,
-0x0c,0x00,0x27,0xc1,0x00,0x00,0x00,0x00,0x93,0x84,0x80,0x10,0x0c,0x00,0x21,0x9a,
-0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x08,0x0c,0x00,0x06,0xe1,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x01,0x3b,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,0x0c,0x00,0x13,0xd5,
-0x00,0x00,0x00,0x00,0x27,0x82,0x89,0x3c,0xaf,0x82,0x84,0x50,0x0c,0x00,0x00,0x61,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x08,0x3c,0x04,0xb0,0x09,
-0x3c,0x05,0xb0,0x09,0x8c,0x66,0x00,0x00,0x34,0x84,0x01,0x68,0x24,0x02,0xc8,0x80,
-0x34,0xa5,0x01,0x40,0x24,0x03,0x00,0x0a,0xa4,0x82,0x00,0x00,0xa4,0xa3,0x00,0x00,
-0x3c,0x04,0xb0,0x03,0x8c,0x82,0x00,0x00,0x8f,0x87,0x84,0x10,0xaf,0x86,0x84,0x08,
-0x34,0x42,0x00,0x20,0xac,0x82,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0x58,
-0x8c,0x43,0x00,0x00,0x2c,0xe4,0x00,0x11,0x34,0x63,0x01,0x00,0xac,0x43,0x00,0x00,
-0x10,0x80,0xff,0xfa,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x00,0x07,0x10,0x80,
-0x24,0x63,0x02,0x18,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,0x0c,0x00,0x26,0xe5,
-0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,0x27,0x85,0x86,0x48,0x0c,0x00,0x14,0x4e,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x07,0x3c,0x03,0xb0,0x06,
-0x90,0x44,0x00,0x00,0x34,0x63,0x80,0x18,0x8c,0x65,0x00,0x00,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0xec,0x3c,0x03,0xb0,0x03,0x30,0x86,0x00,0xff,0xa0,0x46,0x00,0x00,
-0x00,0x05,0x2f,0x02,0x34,0x63,0x00,0xed,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x2c,
-0xa0,0x65,0x00,0x00,0xa3,0x80,0x81,0x58,0x93,0x83,0x81,0xf1,0x24,0x02,0x00,0x01,
-0x10,0x62,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0x87,0x84,0x10,0x8f,0x82,0x84,0x44,
-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x01,0xaf,0x82,0x84,0x44,0x08,0x00,0x15,0x9b,
-0x3c,0x02,0xb0,0x03,0x8f,0x87,0x84,0x10,0x00,0x00,0x00,0x00,0x24,0xe2,0xff,0xfc,
-0x2c,0x42,0x00,0x03,0x14,0x40,0x00,0x0a,0x3c,0x03,0xb0,0x06,0x93,0x82,0x86,0x3c,
-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x07,0x34,0x63,0x80,0x18,0x27,0x84,0x84,0x68,
-0x0c,0x00,0x27,0x75,0x00,0x00,0x00,0x00,0x8f,0x87,0x84,0x10,0x3c,0x03,0xb0,0x06,
-0x34,0x63,0x80,0x18,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02,
-0x10,0x40,0xff,0xe6,0x00,0x00,0x00,0x00,0x8f,0x82,0xbc,0x10,0x8f,0x84,0xbc,0x18,
-0x3c,0x05,0xb0,0x01,0x00,0x45,0x10,0x21,0xac,0x44,0x00,0x00,0x8f,0x83,0xbc,0x10,
-0x8f,0x82,0xbc,0x14,0x00,0x65,0x18,0x21,0x08,0x00,0x15,0xc7,0xac,0x62,0x00,0x04,
-0x14,0xa0,0xff,0xd4,0x3c,0x02,0xb0,0x03,0x93,0x83,0x81,0x58,0x34,0x42,0x00,0xee,
-0x24,0x63,0x00,0x01,0x30,0x64,0x00,0xff,0x2c,0x84,0x00,0xf1,0xa0,0x43,0x00,0x00,
-0xa3,0x83,0x81,0x58,0x14,0x80,0xff,0xcc,0x00,0x00,0x00,0x00,0xaf,0x86,0x84,0x24,
-0xa3,0x86,0x86,0x23,0x08,0x00,0x15,0xc1,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,
-0x0c,0x00,0x29,0x6e,0x00,0x00,0x00,0x00,0xa3,0x82,0x84,0x41,0x8f,0x82,0x84,0x44,
-0xaf,0x80,0x84,0x10,0x24,0x42,0x00,0x01,0xaf,0x82,0x84,0x44,0x08,0x00,0x15,0x9a,
-0x00,0x00,0x38,0x21,0x27,0x84,0x86,0x48,0x0c,0x00,0x19,0x19,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xff,0x14,0x40,0x00,0x05,0x3c,0x03,0xb0,0x05,0xaf,0x80,0x84,0x10,
-0xaf,0x80,0x84,0x14,0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x34,0x63,0x04,0x50,
-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x3c,
-0x14,0x40,0x00,0x20,0x24,0x02,0x00,0x01,0x8f,0x84,0x84,0x18,0x00,0x00,0x00,0x00,
-0x10,0x82,0x00,0x20,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,0x90,0x62,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x24,0x14,0x40,0x00,0x15,
-0x24,0x02,0x00,0x01,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x07,0x00,0x00,0x00,0x00,
-0x24,0x07,0x00,0x03,0x24,0x02,0x00,0x01,0xaf,0x82,0x84,0x14,0xaf,0x87,0x84,0x10,
-0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,
-0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,
-0x00,0x60,0x10,0x21,0xa7,0x83,0x84,0x30,0x14,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0xaf,0x82,0x84,0x14,0xaf,0x80,0x84,0x10,0x08,0x00,0x15,0xc6,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x05,0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x2c,0x14,0x40,0xff,0xf5,
-0x24,0x02,0x00,0x01,0x08,0x00,0x16,0x1a,0x3c,0x03,0xb0,0x09,0x27,0x84,0x86,0x48,
-0x0c,0x00,0x1a,0xde,0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x40,0x00,0x00,0x00,0x00,
-0x14,0x40,0xff,0xec,0x24,0x02,0x00,0x02,0x3c,0x03,0xb0,0x05,0x34,0x63,0x04,0x50,
-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,0xaf,0x82,0x84,0x3c,
-0x14,0x40,0xff,0xe4,0x24,0x02,0x00,0x02,0x8f,0x84,0x84,0x18,0x24,0x02,0x00,0x01,
-0x10,0x82,0x00,0x12,0x24,0x02,0x00,0x02,0x10,0x82,0x00,0x04,0x00,0x00,0x00,0x00,
-0x24,0x07,0x00,0x04,0x08,0x00,0x16,0x26,0x24,0x02,0x00,0x02,0x3c,0x02,0xb0,0x05,
-0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,
-0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21,0xa7,0x83,0x84,0x30,0x14,0x40,0xff,0xf4,
-0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x35,0x24,0x02,0x00,0x02,0x3c,0x03,0xb0,0x05,
-0x34,0x63,0x02,0x2c,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xff,
-0xaf,0x82,0x84,0x2c,0x14,0x40,0xff,0xf7,0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x56,
-0x24,0x02,0x00,0x02,0x27,0x84,0x89,0x08,0x0c,0x00,0x0b,0x51,0x00,0x00,0x00,0x00,
-0x8f,0x83,0x84,0x14,0xaf,0x82,0x84,0x2c,0x38,0x64,0x00,0x02,0x00,0x04,0x18,0x0a,
-0xaf,0x83,0x84,0x14,0x14,0x40,0xff,0xad,0x24,0x07,0x00,0x05,0x8f,0x82,0x89,0x48,
-0xaf,0x80,0x84,0x10,0x10,0x40,0x00,0x02,0x24,0x04,0x00,0x01,0xaf,0x84,0x84,0x18,
-0x93,0x82,0x89,0x56,0x00,0x00,0x00,0x00,0x10,0x40,0xff,0x43,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x05,0x34,0x42,0x00,0x08,0x8c,0x43,0x00,0x00,0x3c,0x04,0x20,0x00,
-0x00,0x64,0x18,0x24,0x10,0x60,0xff,0x3c,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0xa0,0x8c,0x43,0x00,0x00,0x3c,0x04,0x80,0x00,0xaf,0x80,0x89,0x30,
-0x24,0x63,0x00,0x01,0xac,0x43,0x00,0x00,0x3c,0x01,0xb0,0x05,0xac,0x24,0x00,0x08,
-0xaf,0x80,0x89,0x2c,0xaf,0x80,0x89,0x34,0xaf,0x80,0x89,0x38,0xaf,0x80,0x89,0x44,
-0xaf,0x80,0x89,0x3c,0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x60,
-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x02,0x24,0x02,0x00,0x20,0xaf,0x82,0x84,0x2c,
-0x8f,0x85,0x84,0x2c,0x27,0x84,0x89,0x08,0x0c,0x00,0x0d,0x2c,0x00,0x00,0x00,0x00,
-0x00,0x02,0x1e,0x00,0xa3,0x82,0x84,0x40,0xaf,0x80,0x84,0x2c,0x10,0x60,0xff,0x8e,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x05,0x34,0x42,0x02,0x2e,0x90,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x01,0x30,0x63,0x00,0xff,0x00,0x60,0x10,0x21,
-0xa7,0x83,0x84,0x30,0x10,0x40,0x00,0x04,0x24,0x04,0x00,0x02,0xaf,0x84,0x84,0x18,
-0x08,0x00,0x16,0x36,0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x27,0x24,0x07,0x00,0x06,
-0x27,0x84,0x84,0x10,0x27,0x85,0x89,0x08,0x0c,0x00,0x0d,0xf9,0x00,0x00,0x00,0x00,
-0x8f,0x82,0x84,0x34,0xaf,0x80,0x84,0x3c,0x14,0x40,0x00,0x19,0x00,0x40,0x18,0x21,
-0x8f,0x82,0x84,0x38,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x15,0x24,0x02,0x00,0x02,
-0x8f,0x83,0x84,0x18,0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x0b,0x3c,0x02,0x40,0x00,
-0x8f,0x83,0x84,0x14,0x24,0x02,0x00,0x01,0x10,0x62,0x00,0x02,0x24,0x07,0x00,0x03,
-0x24,0x07,0x00,0x06,0xaf,0x87,0x84,0x10,0x24,0x04,0x00,0x03,0xaf,0x84,0x84,0x18,
-0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x14,0x3c,0x01,0xb0,0x05,
-0xac,0x22,0x00,0x00,0xaf,0x80,0x84,0x10,0x08,0x00,0x16,0xcf,0x24,0x04,0x00,0x03,
-0x10,0x60,0x00,0x10,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,0x27,0x85,0x89,0x08,
-0x0c,0x00,0x0e,0x1d,0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x14,0x24,0x02,0x00,0x01,
-0xa3,0x80,0x84,0x40,0xaf,0x80,0x84,0x18,0x10,0x62,0x00,0x02,0x24,0x07,0x00,0x03,
-0x24,0x07,0x00,0x04,0xaf,0x87,0x84,0x10,0xaf,0x80,0x84,0x34,0x08,0x00,0x15,0xc6,
-0x00,0x00,0x00,0x00,0x83,0x82,0x84,0x60,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x04,
-0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x08,0x0c,0x00,0x10,0x65,0x00,0x00,0x00,0x00,
-0x8f,0x82,0x84,0x14,0xa3,0x80,0x84,0x40,0xaf,0x80,0x84,0x10,0xaf,0x80,0x84,0x18,
-0x14,0x40,0x00,0x03,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0xaf,0x82,0x84,0x14,
-0xaf,0x80,0x84,0x38,0x08,0x00,0x15,0xc6,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,
-0x27,0x85,0x89,0x08,0x0c,0x00,0x0e,0x1d,0x00,0x00,0x00,0x00,0x8f,0x82,0x84,0x14,
-0xa3,0x80,0x84,0x40,0xaf,0x80,0x84,0x10,0xaf,0x80,0x84,0x18,0x14,0x40,0xfe,0xc2,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0xaf,0x82,0x84,0x14,0x08,0x00,0x15,0xc6,
-0x00,0x00,0x00,0x00,0x27,0x84,0x89,0x08,0x0c,0x00,0x10,0x65,0x00,0x00,0x00,0x00,
-0x08,0x00,0x16,0xff,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,0x0c,0x00,0x2a,0x96,
-0x00,0x00,0x00,0x00,0x08,0x00,0x15,0xfe,0x00,0x00,0x00,0x00,0x0c,0x00,0x24,0x66,
-0x00,0x00,0x00,0x00,0x0c,0x00,0x27,0x56,0x00,0x00,0x00,0x00,0x0c,0x00,0x18,0x40,
-0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x68,0x0c,0x00,0x27,0x64,0x00,0x00,0x00,0x00,
-0x93,0x83,0xbc,0x08,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x2b,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x83,0xbc,0x00,0x8f,0x82,0xbc,0x04,
-0x00,0x83,0x18,0x23,0x00,0x43,0x10,0x2b,0x10,0x40,0x00,0x23,0x3c,0x02,0xb0,0x03,
-0x24,0x04,0x05,0xa0,0x34,0x42,0x01,0x18,0x8c,0x42,0x00,0x00,0x0c,0x00,0x06,0xce,
-0x00,0x00,0x00,0x00,0x24,0x04,0x05,0xa4,0x0c,0x00,0x06,0xce,0x00,0x02,0x84,0x02,
-0x30,0x51,0xff,0xff,0x24,0x04,0x05,0xa8,0x00,0x02,0x94,0x02,0x0c,0x00,0x06,0xce,
-0x3a,0x10,0xff,0xff,0x3a,0x31,0xff,0xff,0x30,0x42,0xff,0xff,0x2e,0x10,0x00,0x01,
-0x2e,0x31,0x00,0x01,0x3a,0x52,0xff,0xff,0x02,0x11,0x80,0x25,0x2e,0x52,0x00,0x01,
-0x38,0x42,0xff,0xff,0x02,0x12,0x80,0x25,0x2c,0x42,0x00,0x01,0x02,0x02,0x80,0x25,
-0x16,0x00,0x00,0x02,0x24,0x04,0x00,0x02,0x00,0x00,0x20,0x21,0x0c,0x00,0x05,0x70,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0xaf,0x83,0xbc,0x00,0x0c,0x00,0x01,0xeb,0x00,0x00,0x00,0x00,
-0xaf,0x80,0x84,0x10,0xaf,0x80,0x84,0x44,0x08,0x00,0x15,0x9a,0x00,0x00,0x38,0x21,
-0x27,0x90,0xb3,0xf0,0x24,0x11,0x00,0x12,0x8e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
-0x90,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x03,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x20,0xd0,0x00,0x00,0x00,0x00,0x26,0x31,0xff,0xff,0x06,0x21,0xff,0xf6,
-0x26,0x10,0x00,0x04,0xaf,0x80,0x84,0x10,0x08,0x00,0x15,0xc7,0x00,0x00,0x38,0x21,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x08,0x8c,0x44,0x00,0x00,0x8f,0x82,0x84,0x08,
-0x00,0x04,0x19,0xc2,0x00,0x02,0x11,0xc2,0x10,0x62,0xff,0xf6,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x02,0x90,0x43,0x00,0x00,0x3c,0x12,0xb0,0x05,
-0xaf,0x84,0x84,0x08,0x30,0x63,0x00,0xff,0x00,0x03,0x11,0x40,0x00,0x43,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x00,0x02,0x99,0x00,0x00,0x00,0x88,0x21,
-0x36,0x52,0x02,0x2c,0x27,0x90,0xb3,0xf0,0x8e,0x04,0x00,0x00,0x00,0x00,0x00,0x00,
-0x90,0x83,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x62,0x00,0x03,0x10,0x40,0x00,0x06,
-0x30,0x62,0x00,0x1c,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0x8f,0x85,0x84,0x08,
-0x0c,0x00,0x1e,0xb2,0x02,0x60,0x30,0x21,0x8e,0x42,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xff,0x14,0x40,0xff,0xd7,0x00,0x00,0x00,0x00,0x26,0x31,0x00,0x01,
-0x2a,0x22,0x00,0x13,0x14,0x40,0xff,0xec,0x26,0x10,0x00,0x04,0x08,0x00,0x17,0x5d,
-0x00,0x00,0x00,0x00,0x8f,0x84,0x84,0x1c,0x27,0x85,0x89,0x08,0x0c,0x00,0x17,0xd3,
-0x00,0x00,0x00,0x00,0x8f,0x83,0x84,0x1c,0x24,0x02,0x00,0x04,0x14,0x62,0xfe,0xa2,
-0x00,0x00,0x00,0x00,0x08,0x00,0x16,0x27,0x24,0x07,0x00,0x05,0x27,0x84,0x89,0x08,
-0x0c,0x00,0x24,0x8d,0x00,0x00,0x00,0x00,0x24,0x07,0x00,0x05,0xaf,0x87,0x84,0x10,
-0x08,0x00,0x15,0xc7,0x00,0x00,0x00,0x00,0x8f,0x82,0x89,0x3c,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00,0x8f,0x84,0xb4,0x30,0xaf,0x80,0x89,0x3c,
-0x94,0x85,0x00,0x14,0x0c,0x00,0x1b,0x84,0x00,0x00,0x00,0x00,0x93,0x82,0x8b,0x61,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x02,0x10,0x40,0x00,0x03,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x01,0x59,0x00,0x00,0x20,0x21,0x8f,0x84,0xb4,0x30,0x0c,0x00,0x20,0xd0,
-0x00,0x00,0x00,0x00,0x08,0x00,0x17,0x5d,0x00,0x00,0x00,0x00,0x3c,0x02,0xff,0x90,
-0x27,0xbd,0xff,0xe8,0x00,0x80,0x18,0x21,0x34,0x42,0x00,0x01,0x27,0x84,0x89,0x08,
-0x10,0x62,0x00,0x05,0xaf,0xbf,0x00,0x10,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x06,0xe1,0x00,0x00,0x00,0x00,
-0x27,0x84,0x86,0x48,0x0c,0x00,0x18,0x4e,0x00,0x00,0x00,0x00,0x27,0x84,0x84,0x10,
-0x0c,0x00,0x13,0xd5,0x00,0x00,0x00,0x00,0x08,0x00,0x17,0xba,0x00,0x00,0x00,0x00,
-0x8f,0x82,0x89,0x48,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x05,0x00,0x00,0x18,0x21,
-0x8f,0x82,0x84,0x18,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x02,0x00,0x00,0x00,0x00,
-0x24,0x03,0x00,0x01,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,0x27,0xbd,0xff,0xe0,
-0x3c,0x06,0xb0,0x03,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0x34,0xc6,0x00,0x5f,
-0xaf,0xbf,0x00,0x18,0x90,0xc3,0x00,0x00,0x3c,0x07,0xb0,0x03,0x34,0xe7,0x00,0x5d,
-0x34,0x63,0x00,0x01,0x3c,0x09,0xb0,0x03,0x24,0x02,0x00,0x01,0xa0,0xc3,0x00,0x00,
-0x00,0x80,0x80,0x21,0xa0,0xe2,0x00,0x00,0x00,0xa0,0x88,0x21,0x35,0x29,0x00,0x5e,
-0x00,0xe0,0x40,0x21,0x24,0x04,0x00,0x01,0x91,0x22,0x00,0x00,0x91,0x03,0x00,0x00,
-0x30,0x42,0x00,0x01,0x14,0x83,0x00,0x03,0x30,0x42,0x00,0x01,0x14,0x40,0xff,0xfa,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x04,0x12,0x02,0x00,0x2c,0x24,0x05,0x0f,0x00,
-0x24,0x02,0x00,0x06,0x12,0x02,0x00,0x08,0x24,0x05,0x00,0x0f,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x02,0x00,0xa0,0x50,0x00,0x00,0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,0x24,0x04,0x0c,0x04,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x0f,0x24,0x04,0x0d,0x04,0x24,0x05,0x00,0x0f,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x80,0x24,0x05,0x1e,0x00,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x8c,0x24,0x05,0x0f,0x00,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x0f,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x2c,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x02,0x24,0x04,0x08,0x3c,0x3c,0x05,0x00,0x30,0x0c,0x00,0x13,0x5b,
-0x24,0x06,0x00,0x02,0x08,0x00,0x17,0xf4,0x3c,0x02,0xb0,0x03,0x24,0x04,0x08,0x8c,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x08,0x80,0x24,0x05,0x1e,0x00,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x0c,0x04,0x24,0x05,0x00,0x0f,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x0d,0x04,0x24,0x05,0x00,0x0f,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x04,0x24,0x04,0x08,0x24,0x3c,0x05,0x00,0x30,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x2c,0x3c,0x05,0x00,0x30,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x03,0x24,0x04,0x08,0x34,0x3c,0x05,0x00,0x30,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x02,0x3c,0x05,0x00,0x30,0x24,0x06,0x00,0x03,
-0x0c,0x00,0x13,0x5b,0x24,0x04,0x08,0x3c,0x02,0x20,0x20,0x21,0x24,0x05,0x00,0x14,
-0x0c,0x00,0x13,0xa0,0x24,0x06,0x01,0x07,0x08,0x00,0x17,0xf4,0x3c,0x02,0xb0,0x03,
-0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x73,0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0x02,0x14,0x40,0x00,0x04,0x00,0x00,0x00,0x00,0xa3,0x80,0x81,0x59,
-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0xa3,0x82,0x81,0x59,
-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x00,0x80,0x70,0x21,0x34,0x63,0x00,0x20,0x24,0x42,0x61,0x38,0x3c,0x04,0xb0,0x03,
-0xac,0x62,0x00,0x00,0x34,0x84,0x00,0x30,0xad,0xc0,0x02,0xbc,0xad,0xc0,0x02,0xb8,
-0x8c,0x83,0x00,0x00,0x24,0x02,0x00,0xff,0xa5,0xc0,0x00,0x0a,0x00,0x00,0x30,0x21,
-0xa7,0x82,0x8f,0xe0,0x27,0x88,0x8f,0xf0,0xa5,0xc3,0x00,0x08,0x3c,0x07,0xb0,0x08,
-0x30,0xc2,0xff,0xff,0x00,0x02,0x20,0xc0,0x24,0xc3,0x00,0x01,0x00,0x82,0x10,0x21,
-0x00,0x60,0x30,0x21,0x00,0x02,0x10,0x80,0x30,0x63,0xff,0xff,0x00,0x48,0x10,0x21,
-0x00,0x87,0x20,0x21,0x28,0xc5,0x00,0xff,0xac,0x83,0x00,0x00,0x14,0xa0,0xff,0xf4,
-0xa4,0x43,0x00,0x00,0x3c,0x02,0xb0,0x08,0x34,0x03,0xff,0xff,0x25,0xc4,0x00,0x0c,
-0x24,0x0a,0x00,0x02,0x34,0x42,0x07,0xf8,0x3c,0x06,0xb0,0x03,0xa7,0x83,0xb3,0xcc,
-0xac,0x43,0x00,0x00,0xaf,0x84,0xb3,0xf0,0x34,0xc6,0x00,0x64,0xa0,0x8a,0x00,0x18,
-0x94,0xc5,0x00,0x00,0x8f,0x82,0xb3,0xf0,0x25,0xc4,0x00,0x30,0x24,0x08,0x00,0x03,
-0x3c,0x03,0xb0,0x03,0xa0,0x45,0x00,0x21,0x34,0x63,0x00,0x66,0xaf,0x84,0xb3,0xf4,
-0xa0,0x88,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb3,0xf4,0x25,0xc4,0x00,0x54,
-0x25,0xc7,0x00,0x78,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb3,0xf8,0xa0,0x88,0x00,0x18,
-0x94,0x65,0x00,0x00,0x8f,0x82,0xb3,0xf8,0x25,0xc8,0x00,0x9c,0x24,0x09,0x00,0x01,
-0xa0,0x45,0x00,0x21,0xaf,0x87,0xb3,0xfc,0xa0,0xea,0x00,0x18,0x94,0xc4,0x00,0x00,
-0x8f,0x82,0xb3,0xfc,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x62,0xa0,0x44,0x00,0x21,
-0xaf,0x88,0xb4,0x00,0xa1,0x09,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x00,
-0x25,0xc4,0x00,0xc0,0x3c,0x06,0xb0,0x03,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x04,
-0xa0,0x89,0x00,0x18,0x94,0x65,0x00,0x00,0x8f,0x82,0xb4,0x04,0x25,0xc4,0x00,0xe4,
-0x34,0xc6,0x00,0x60,0xa0,0x45,0x00,0x21,0xaf,0x84,0xb4,0x08,0xa0,0x80,0x00,0x18,
-0x94,0xc5,0x00,0x00,0x8f,0x82,0xb4,0x08,0x25,0xc3,0x01,0x08,0x25,0xc7,0x01,0x2c,
-0xa0,0x45,0x00,0x21,0xaf,0x83,0xb4,0x0c,0xa0,0x60,0x00,0x18,0x94,0xc8,0x00,0x00,
-0x8f,0x82,0xb4,0x0c,0x25,0xc4,0x01,0x50,0x25,0xc5,0x01,0x74,0xa0,0x48,0x00,0x21,
-0x25,0xc6,0x01,0x98,0x25,0xc9,0x01,0xbc,0x25,0xca,0x01,0xe0,0x25,0xcb,0x02,0x04,
-0x25,0xcc,0x02,0x28,0x25,0xcd,0x02,0x4c,0x24,0x02,0x00,0x10,0x3c,0x03,0xb0,0x03,
-0xaf,0x87,0xb4,0x10,0x34,0x63,0x00,0x38,0xa0,0xe0,0x00,0x18,0xaf,0x84,0xb4,0x14,
-0xa0,0x80,0x00,0x18,0xaf,0x85,0xb4,0x18,0xa0,0xa0,0x00,0x18,0xaf,0x86,0xb4,0x1c,
-0xa0,0xc0,0x00,0x18,0xaf,0x89,0xb4,0x20,0xa1,0x20,0x00,0x18,0xaf,0x8a,0xb4,0x24,
-0xa1,0x40,0x00,0x18,0xaf,0x8b,0xb4,0x28,0xa1,0x60,0x00,0x18,0xaf,0x8c,0xb4,0x2c,
-0xa1,0x80,0x00,0x18,0xaf,0x8d,0xb4,0x30,0xa1,0xa2,0x00,0x18,0x94,0x64,0x00,0x00,
-0x8f,0x82,0xb4,0x30,0x25,0xc5,0x02,0x70,0x3c,0x03,0xb0,0x03,0xa0,0x44,0x00,0x21,
-0x24,0x02,0x00,0x11,0xaf,0x85,0xb4,0x34,0x34,0x63,0x00,0x6e,0xa0,0xa2,0x00,0x18,
-0x94,0x64,0x00,0x00,0x8f,0x82,0xb4,0x34,0x25,0xc5,0x02,0x94,0x3c,0x03,0xb0,0x03,
-0xa0,0x44,0x00,0x21,0x24,0x02,0x00,0x12,0xaf,0x85,0xb4,0x38,0x34,0x63,0x00,0x6c,
-0xa0,0xa2,0x00,0x18,0x94,0x64,0x00,0x00,0x8f,0x82,0xb4,0x38,0x24,0x05,0xff,0xff,
-0x24,0x07,0x00,0x01,0xa0,0x44,0x00,0x21,0x24,0x06,0x00,0x12,0x27,0x84,0xb3,0xf0,
-0x8c,0x82,0x00,0x00,0x24,0xc6,0xff,0xff,0xa0,0x40,0x00,0x04,0x8c,0x83,0x00,0x00,
-0xa4,0x45,0x00,0x00,0xa4,0x45,0x00,0x02,0xa0,0x60,0x00,0x0a,0x8c,0x82,0x00,0x00,
-0xa4,0x65,0x00,0x06,0xa4,0x65,0x00,0x08,0xa0,0x40,0x00,0x10,0x8c,0x83,0x00,0x00,
-0xa4,0x45,0x00,0x0c,0xa4,0x45,0x00,0x0e,0xa0,0x60,0x00,0x12,0x8c,0x82,0x00,0x00,
-0x00,0x00,0x00,0x00,0xa0,0x40,0x00,0x16,0x8c,0x83,0x00,0x00,0xa4,0x45,0x00,0x14,
-0xa0,0x67,0x00,0x17,0x8c,0x82,0x00,0x00,0x24,0x84,0x00,0x04,0xa0,0x40,0x00,0x20,
-0x04,0xc1,0xff,0xe7,0xac,0x40,0x00,0x1c,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x64,0x00,
-0x00,0x05,0x28,0x40,0xac,0x62,0x00,0x00,0x00,0xa6,0x28,0x21,0x2c,0xe2,0x00,0x10,
-0x14,0x80,0x00,0x06,0x00,0x00,0x18,0x21,0x10,0x40,0x00,0x02,0x00,0x00,0x00,0x00,
-0x00,0xe0,0x18,0x21,0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,0x24,0x02,0x00,0x20,
-0x10,0xe2,0x00,0x06,0x2c,0xe4,0x00,0x10,0x24,0xa2,0x00,0x01,0x10,0x80,0xff,0xf9,
-0x00,0x02,0x11,0x00,0x08,0x00,0x19,0x0d,0x00,0x47,0x18,0x21,0x08,0x00,0x19,0x0d,
-0x24,0xa3,0x00,0x50,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x27,0xbd,0xff,0xc8,
-0x34,0x63,0x00,0x20,0x24,0x42,0x64,0x64,0xaf,0xb2,0x00,0x18,0xaf,0xbf,0x00,0x34,
-0xaf,0xbe,0x00,0x30,0xaf,0xb7,0x00,0x2c,0xaf,0xb6,0x00,0x28,0xaf,0xb5,0x00,0x24,
-0xaf,0xb4,0x00,0x20,0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,
-0xac,0x62,0x00,0x00,0x8c,0x86,0x02,0xbc,0x00,0x80,0x90,0x21,0x14,0xc0,0x01,0x66,
-0x00,0xc0,0x38,0x21,0x84,0x82,0x00,0x08,0x3c,0x03,0xb0,0x06,0x94,0x84,0x00,0x08,
-0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x8c,0x45,0x00,0x00,0x8c,0x43,0x00,0x00,
-0x24,0x84,0x00,0x02,0x30,0x84,0x01,0xff,0x30,0xb1,0xff,0xff,0x00,0x03,0x44,0x02,
-0xa6,0x44,0x00,0x08,0x14,0xe0,0x00,0x08,0x3c,0x03,0xb0,0x06,0x34,0x63,0x80,0x24,
-0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x34,0x42,0x01,0x00,0xac,0x62,0x00,0x00,
-0x8e,0x46,0x02,0xbc,0x00,0x00,0x00,0x00,0x14,0xc0,0x01,0x4c,0x00,0x11,0x98,0xc0,
-0x00,0x11,0x3a,0x00,0x3c,0x04,0xb0,0x00,0x00,0xe4,0x20,0x21,0x8c,0x83,0x00,0x0c,
-0x00,0x11,0x98,0xc0,0x02,0x71,0x10,0x21,0x00,0x03,0x1b,0x82,0x30,0x63,0x00,0x1f,
-0x00,0x02,0x10,0x80,0x27,0x9e,0x8f,0xf4,0x00,0x5e,0x10,0x21,0x00,0x60,0x30,0x21,
-0xac,0x44,0x00,0x18,0xae,0x43,0x02,0xbc,0x14,0xc0,0x00,0x10,0x3c,0x02,0xb0,0x00,
-0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21,0x27,0x84,0x8f,0xf0,0x00,0x02,0x10,0x80,
-0x00,0x44,0x10,0x21,0x94,0x45,0x00,0x00,0x02,0x71,0x18,0x21,0x00,0x03,0x18,0x80,
-0x00,0x64,0x18,0x21,0x24,0x02,0xff,0xff,0xa4,0x62,0x00,0x02,0xa4,0x68,0x00,0x04,
-0xae,0x51,0x02,0xb8,0xa6,0x45,0x00,0x0a,0x3c,0x02,0xb0,0x00,0x00,0xe2,0x40,0x21,
-0x8d,0x16,0x00,0x00,0x8d,0x14,0x00,0x04,0x02,0x71,0x10,0x21,0x00,0x02,0x38,0x80,
-0x00,0x14,0x1a,0x02,0x27,0x84,0x90,0x00,0x30,0x63,0x00,0x1f,0x24,0x02,0x00,0x10,
-0x00,0xe4,0x20,0x21,0xa6,0x43,0x00,0x06,0x8d,0x10,0x00,0x08,0xa0,0x82,0x00,0x06,
-0x86,0x45,0x00,0x06,0x00,0xfe,0x10,0x21,0x24,0x03,0x00,0x13,0x10,0xa3,0x01,0x15,
-0xac,0x48,0x00,0x18,0x3c,0x03,0xb0,0x03,0x34,0x63,0x01,0x00,0xa6,0x40,0x00,0x02,
-0x3c,0x02,0xb0,0x03,0x90,0x64,0x00,0x00,0x34,0x42,0x01,0x08,0x8c,0x45,0x00,0x00,
-0x00,0x10,0x1b,0xc2,0x27,0x82,0x8f,0xf0,0x00,0x04,0x20,0x82,0x00,0xe2,0x10,0x21,
-0x30,0x63,0x00,0x01,0xac,0x45,0x00,0x08,0x10,0x60,0x00,0xec,0x30,0x97,0x00,0x01,
-0x00,0x10,0x16,0x82,0x30,0x46,0x00,0x01,0x00,0x10,0x12,0x02,0x00,0x10,0x19,0xc2,
-0x00,0x10,0x26,0x02,0x00,0x10,0x2e,0x42,0x30,0x47,0x00,0x7f,0x24,0x02,0x00,0x01,
-0x30,0x75,0x00,0x01,0x30,0x84,0x00,0x01,0x10,0xc2,0x00,0xd9,0x30,0xa3,0x00,0x01,
-0x0c,0x00,0x19,0x00,0x00,0x60,0x28,0x21,0x02,0x71,0x18,0x21,0x00,0x03,0x18,0x80,
-0x2c,0x46,0x00,0x54,0x27,0x85,0x90,0x00,0x27,0x84,0x8f,0xf8,0x00,0x06,0x10,0x0a,
-0x00,0x65,0x28,0x21,0x26,0xa6,0x00,0x02,0x00,0x64,0x18,0x21,0xa0,0xa2,0x00,0x02,
-0xa0,0x66,0x00,0x06,0xa0,0x62,0x00,0x07,0xa0,0xa2,0x00,0x01,0x02,0x71,0x20,0x21,
-0x00,0x04,0x20,0x80,0x00,0x9e,0x60,0x21,0x8d,0x85,0x00,0x18,0x00,0x10,0x15,0xc2,
-0x30,0x42,0x00,0x01,0x8c,0xa3,0x00,0x0c,0xa6,0x42,0x00,0x00,0x27,0x82,0x90,0x10,
-0x00,0x82,0x50,0x21,0xa6,0x56,0x00,0x04,0x8d,0x45,0x00,0x00,0x00,0x03,0x19,0x42,
-0x3c,0x02,0xff,0xef,0x34,0x42,0xff,0xff,0x30,0x63,0x00,0x01,0x00,0xa2,0x48,0x24,
-0x00,0x03,0x1d,0x00,0x01,0x23,0x48,0x25,0x00,0x09,0x15,0x02,0x26,0xc5,0x00,0x10,
-0x00,0x14,0x19,0x82,0x00,0x14,0x25,0x82,0x00,0x10,0x34,0x02,0x00,0x10,0x3c,0x42,
-0x00,0x10,0x44,0x82,0x30,0x42,0x00,0x01,0x30,0xb5,0xff,0xff,0x30,0xce,0x00,0x01,
-0x30,0xe5,0x00,0x01,0x30,0x6d,0x00,0x01,0x30,0x8b,0x00,0x03,0x32,0x94,0x00,0x07,
-0x31,0x06,0x00,0x01,0xad,0x49,0x00,0x00,0x10,0x40,0x00,0x0b,0x32,0x07,0x00,0x7f,
-0x8d,0x84,0x00,0x18,0x3c,0x03,0xff,0xf0,0x34,0x63,0xff,0xff,0x8c,0x82,0x00,0x0c,
-0x01,0x23,0x18,0x24,0x00,0x02,0x13,0x82,0x30,0x42,0x00,0x0f,0x00,0x02,0x14,0x00,
-0x00,0x62,0x18,0x25,0xad,0x43,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xc2,0x00,0x90,
-0x00,0x00,0x00,0x00,0x15,0xa0,0x00,0x03,0x00,0x00,0x00,0x00,0x15,0x60,0x00,0x81,
-0x24,0x02,0x00,0x01,0x96,0x42,0x00,0x04,0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x04,
-0xa6,0x42,0x00,0x04,0x0c,0x00,0x19,0x00,0x01,0xc0,0x20,0x21,0x02,0x71,0x18,0x21,
-0x00,0x03,0x38,0x80,0x2c,0x45,0x00,0x54,0x27,0x84,0x90,0x00,0x00,0xe4,0x20,0x21,
-0x00,0x05,0x10,0x0a,0xa0,0x82,0x00,0x00,0xa0,0x80,0x00,0x04,0xa0,0x80,0x00,0x05,
-0x96,0x45,0x00,0x04,0x27,0x82,0x8f,0xf0,0x00,0xe2,0x10,0x21,0xa4,0x45,0x00,0x06,
-0x00,0xfe,0x18,0x21,0x92,0x45,0x00,0x01,0x8c,0x66,0x00,0x18,0x27,0x82,0x90,0x10,
-0x00,0xe2,0x10,0x21,0xa0,0x40,0x00,0x00,0xa0,0x85,0x00,0x07,0x94,0xc3,0x00,0x10,
-0x24,0x02,0x00,0x04,0x30,0x63,0x00,0x0f,0x10,0x62,0x00,0x5e,0x24,0xc6,0x00,0x10,
-0x94,0xc3,0x00,0x16,0x27,0x85,0x90,0x08,0x00,0xe5,0x10,0x21,0xa4,0x43,0x00,0x02,
-0x94,0xc2,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x4c,
-0x02,0x71,0x20,0x21,0x94,0xc2,0x00,0x00,0x24,0x03,0x00,0xa4,0x30,0x42,0x00,0xff,
-0x10,0x43,0x00,0x47,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x00,0x24,0x03,0x00,0x88,
-0x30,0x42,0x00,0x88,0x10,0x43,0x00,0x3c,0x02,0x71,0x18,0x21,0x27,0x84,0x90,0x10,
-0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0x00,0x3c,0x04,0x00,0x80,
-0x00,0x44,0x10,0x25,0xac,0x62,0x00,0x00,0x02,0x71,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x45,0x10,0x21,0xa0,0x54,0x00,0x00,0x92,0x43,0x02,0xbf,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x00,0xc3,0xa0,0x43,0x00,0x00,0x8e,0x4b,0x02,0xbc,0x00,0x00,0x00,0x00,
-0x11,0x60,0x00,0x1c,0x32,0xa2,0x00,0xff,0x00,0x15,0x1a,0x02,0x30,0x64,0xff,0xff,
-0x38,0x42,0x00,0x00,0x24,0x65,0x00,0x01,0x00,0x82,0x28,0x0a,0x02,0x20,0x30,0x21,
-0x10,0xa0,0x00,0x12,0x00,0x00,0x38,0x21,0x02,0x71,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x8f,0xf0,0x00,0x43,0x20,0x21,0x24,0xa9,0xff,0xff,0x3c,0x0a,0xb0,0x08,
-0x24,0x0c,0xff,0xff,0x00,0x06,0x10,0xc0,0x00,0x4a,0x10,0x21,0x8c,0x43,0x00,0x00,
-0x24,0xe8,0x00,0x01,0x10,0xe9,0x00,0x0f,0x30,0x63,0x00,0xff,0x31,0x07,0xff,0xff,
-0x00,0xe5,0x10,0x2b,0x14,0x40,0xff,0xf7,0x00,0x60,0x30,0x21,0x25,0x62,0xff,0xff,
-0xae,0x42,0x02,0xbc,0x7b,0xbe,0x01,0xbc,0x7b,0xb6,0x01,0x7c,0x7b,0xb4,0x01,0x3c,
-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x38,0xa4,0x86,0x00,0x04,0xa4,0x8c,0x00,0x02,0xae,0x51,0x02,0xb8,
-0x08,0x00,0x1a,0x2f,0xa6,0x43,0x00,0x0a,0x94,0xc2,0x00,0x18,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0x60,0x10,0x40,0xff,0xc1,0x02,0x71,0x18,0x21,0x02,0x71,0x20,0x21,
-0x27,0x82,0x90,0x10,0x00,0x04,0x20,0x80,0x00,0x82,0x20,0x21,0x8c,0x83,0x00,0x00,
-0x3c,0x02,0xff,0x7f,0x34,0x42,0xff,0xff,0x00,0x62,0x18,0x24,0x08,0x00,0x1a,0x0e,
-0xac,0x83,0x00,0x00,0x27,0x85,0x90,0x08,0x00,0xe5,0x10,0x21,0x08,0x00,0x19,0xf8,
-0xa4,0x40,0x00,0x02,0x11,0x62,0x00,0x07,0x00,0x00,0x00,0x00,0x2d,0x62,0x00,0x02,
-0x14,0x40,0xff,0x80,0x00,0x00,0x00,0x00,0x96,0x42,0x00,0x04,0x08,0x00,0x19,0xd8,
-0x24,0x42,0x00,0x0c,0x96,0x42,0x00,0x04,0x08,0x00,0x19,0xd8,0x24,0x42,0x00,0x08,
-0x16,0xe6,0xff,0x70,0x3c,0x02,0xff,0xfb,0x8d,0x83,0x00,0x18,0x34,0x42,0xff,0xff,
-0x02,0x02,0x10,0x24,0xac,0x62,0x00,0x08,0x08,0x00,0x19,0xd1,0x00,0x00,0x30,0x21,
-0x16,0xe6,0xff,0x27,0x3c,0x02,0xfb,0xff,0x34,0x42,0xff,0xff,0x02,0x02,0x10,0x24,
-0xad,0x02,0x00,0x08,0x08,0x00,0x19,0x90,0x00,0x00,0x30,0x21,0x93,0x88,0xbb,0x04,
-0x00,0x10,0x1e,0x42,0x00,0x10,0x26,0x82,0x27,0x82,0x8f,0xf8,0x2d,0x05,0x00,0x0c,
-0x00,0xe2,0x48,0x21,0x30,0x63,0x00,0x01,0x30,0x86,0x00,0x01,0x14,0xa0,0x00,0x06,
-0x01,0x00,0x38,0x21,0x00,0x03,0x10,0x40,0x00,0x46,0x10,0x21,0x00,0x02,0x11,0x00,
-0x01,0x02,0x10,0x21,0x24,0x47,0x00,0x04,0x02,0x71,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x84,0x90,0x00,0x27,0x83,0x8f,0xf8,0x00,0x44,0x20,0x21,0x00,0x43,0x10,0x21,
-0xa1,0x27,0x00,0x07,0xa0,0x40,0x00,0x06,0xa0,0x80,0x00,0x02,0x08,0x00,0x19,0x9f,
-0xa0,0x80,0x00,0x01,0x24,0x02,0x00,0x01,0xa6,0x42,0x00,0x02,0x0c,0x00,0x01,0xc4,
-0x01,0x00,0x20,0x21,0x08,0x00,0x1a,0x35,0x00,0x00,0x00,0x00,0x27,0x9e,0x8f,0xf4,
-0x08,0x00,0x19,0x52,0x00,0x11,0x3a,0x00,0x94,0x91,0x00,0x0a,0x08,0x00,0x19,0x39,
-0x00,0x00,0x00,0x00,0x30,0xa9,0xff,0xff,0x00,0x09,0x18,0xc0,0x00,0x69,0x18,0x21,
-0x3c,0x06,0xb0,0x03,0x3c,0x02,0x80,0x00,0x24,0x42,0x6a,0x54,0x00,0x03,0x18,0x80,
-0x34,0xc6,0x00,0x20,0x27,0x85,0x90,0x00,0xac,0xc2,0x00,0x00,0x00,0x65,0x18,0x21,
-0x80,0x62,0x00,0x07,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x32,0x24,0x88,0x00,0x06,
-0x90,0x82,0x00,0x16,0x00,0x80,0x40,0x21,0x34,0x42,0x00,0x02,0x30,0x43,0x00,0x01,
-0x14,0x60,0x00,0x02,0xa0,0x82,0x00,0x16,0xa0,0x80,0x00,0x17,0x95,0x03,0x00,0x02,
-0x00,0x00,0x00,0x00,0x10,0x69,0x00,0x22,0x3c,0x02,0x34,0x34,0x91,0x02,0x00,0x04,
-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x06,0x00,0x03,0x20,0xc0,0x24,0x02,0x00,0x01,
-0xa1,0x02,0x00,0x04,0xa5,0x09,0x00,0x02,0x03,0xe0,0x00,0x08,0xa5,0x09,0x00,0x00,
-0x00,0x83,0x20,0x21,0x27,0x87,0x8f,0xf0,0x00,0x04,0x20,0x80,0x00,0x87,0x20,0x21,
-0x94,0x83,0x00,0x04,0x3c,0x02,0xb0,0x08,0x3c,0x06,0xb0,0x03,0x00,0x03,0x28,0xc0,
-0x00,0xa3,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x21,0x3c,0x02,0x80,0x01,
-0x24,0x42,0x82,0xe4,0x00,0x67,0x18,0x21,0x34,0xc6,0x00,0x20,0xac,0xc2,0x00,0x00,
-0xa4,0x69,0x00,0x00,0xa4,0x89,0x00,0x02,0xac,0xa9,0x00,0x00,0x91,0x02,0x00,0x04,
-0xa5,0x09,0x00,0x02,0x24,0x42,0x00,0x01,0x03,0xe0,0x00,0x08,0xa1,0x02,0x00,0x04,
-0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xb0,0x34,0x42,0x34,0x34,0x03,0xe0,0x00,0x08,
-0xac,0x62,0x00,0x00,0x90,0x82,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x01,
-0x30,0x43,0x00,0x02,0x14,0x60,0xff,0xd1,0xa0,0x82,0x00,0x16,0x24,0x02,0x00,0x01,
-0x08,0x00,0x1a,0xab,0xa0,0x82,0x00,0x17,0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,
-0x00,0x80,0x38,0x21,0x84,0x84,0x00,0x02,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x3c,0x0a,0xb0,0x06,0x34,0x63,0x00,0x20,0x24,0x42,0x6b,0x78,0x3c,0x0b,0xb0,0x08,
-0x27,0x89,0x8f,0xf0,0x34,0x0c,0xff,0xff,0x35,0x4a,0x80,0x20,0x10,0x80,0x00,0x30,
-0xac,0x62,0x00,0x00,0x97,0x82,0x8f,0xe0,0x94,0xe6,0x02,0xba,0x00,0x02,0x18,0xc0,
-0x00,0x6b,0x28,0x21,0xac,0xa6,0x00,0x00,0x8c,0xe4,0x02,0xb8,0x00,0x62,0x18,0x21,
-0x00,0x03,0x18,0x80,0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x49,0x10,0x21,0x94,0x48,0x00,0x04,0x00,0x69,0x18,0x21,0xa4,0x66,0x00,0x00,
-0x00,0x08,0x28,0xc0,0x00,0xab,0x10,0x21,0xac,0x4c,0x00,0x00,0x8c,0xe4,0x02,0xb8,
-0x27,0x82,0x8f,0xf4,0x00,0xa8,0x28,0x21,0x00,0x04,0x18,0xc0,0x00,0x64,0x18,0x21,
-0x00,0x03,0x18,0x80,0x00,0x62,0x10,0x21,0x8c,0x46,0x00,0x18,0x27,0x84,0x90,0x00,
-0x00,0x64,0x18,0x21,0x8c,0xc2,0x00,0x00,0x80,0x67,0x00,0x06,0x00,0x05,0x28,0x80,
-0x30,0x42,0xff,0xff,0x00,0x47,0x10,0x21,0x30,0x43,0x00,0xff,0x00,0x03,0x18,0x2b,
-0x00,0x02,0x12,0x02,0x00,0x43,0x10,0x21,0x3c,0x04,0x00,0x04,0x00,0xa9,0x28,0x21,
-0x00,0x44,0x10,0x25,0xa4,0xac,0x00,0x00,0xad,0x42,0x00,0x00,0xa7,0x88,0x8f,0xe0,
-0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,
-0x84,0xe3,0x00,0x06,0x27,0x82,0xb3,0xf0,0x94,0xe5,0x02,0xba,0x00,0x03,0x18,0x80,
-0x00,0x62,0x18,0x21,0x8c,0x64,0x00,0x00,0x0c,0x00,0x1a,0x95,0x00,0x00,0x00,0x00,
-0x08,0x00,0x1b,0x18,0x00,0x00,0x00,0x00,0x94,0x88,0x00,0x00,0x00,0x80,0x58,0x21,
-0x27,0x8a,0x8f,0xf0,0x00,0x08,0x18,0xc0,0x00,0x68,0x18,0x21,0x3c,0x04,0xb0,0x03,
-0x00,0x03,0x18,0x80,0x3c,0x02,0x80,0x00,0x00,0x6a,0x18,0x21,0x34,0x84,0x00,0x20,
-0x24,0x42,0x6c,0x98,0x30,0xa5,0xff,0xff,0xac,0x82,0x00,0x00,0x94,0x67,0x00,0x02,
-0x11,0x05,0x00,0x35,0x24,0x04,0x00,0x01,0x91,0x66,0x00,0x04,0x00,0x00,0x00,0x00,
-0x00,0x86,0x10,0x2a,0x10,0x40,0x00,0x10,0x00,0xc0,0x48,0x21,0x3c,0x0d,0xb0,0x03,
-0x01,0x40,0x60,0x21,0x35,0xad,0x00,0x20,0x10,0xe5,0x00,0x0d,0x24,0x84,0x00,0x01,
-0x00,0x07,0x10,0xc0,0x00,0x47,0x10,0x21,0x00,0x02,0x10,0x80,0x01,0x20,0x30,0x21,
-0x00,0x4a,0x10,0x21,0x00,0x86,0x18,0x2a,0x00,0xe0,0x40,0x21,0x94,0x47,0x00,0x02,
-0x14,0x60,0xff,0xf5,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x10,0x21,
-0x00,0x08,0x20,0xc0,0x00,0x88,0x20,0x21,0x24,0xc2,0xff,0xff,0x00,0x04,0x20,0x80,
-0xa1,0x62,0x00,0x04,0x00,0x8c,0x20,0x21,0x94,0x83,0x00,0x04,0x00,0x07,0x10,0xc0,
-0x00,0x47,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4c,0x10,0x21,0x00,0x03,0x28,0xc0,
-0x94,0x46,0x00,0x02,0x00,0xa3,0x18,0x21,0x00,0x03,0x18,0x80,0x00,0x6c,0x18,0x21,
-0xa4,0x66,0x00,0x00,0xa4,0x86,0x00,0x02,0x95,0x64,0x00,0x02,0x3c,0x03,0xb0,0x08,
-0x3c,0x02,0x80,0x01,0x00,0xa3,0x28,0x21,0x24,0x42,0x82,0xe4,0xad,0xa2,0x00,0x00,
-0x10,0x87,0x00,0x03,0xac,0xa6,0x00,0x00,0x03,0xe0,0x00,0x08,0x24,0x02,0x00,0x01,
-0x08,0x00,0x1b,0x66,0xa5,0x68,0x00,0x02,0x91,0x62,0x00,0x04,0xa5,0x67,0x00,0x00,
-0x24,0x42,0xff,0xff,0x30,0x43,0x00,0xff,0x14,0x60,0x00,0x03,0xa1,0x62,0x00,0x04,
-0x24,0x02,0xff,0xff,0xa5,0x62,0x00,0x02,0x91,0x65,0x00,0x04,0x00,0x00,0x00,0x00,
-0x10,0xa0,0xff,0xf1,0x00,0x00,0x00,0x00,0x95,0x66,0x00,0x00,0x34,0x02,0xff,0xff,
-0x14,0xc2,0xff,0xed,0x3c,0x03,0xb0,0x03,0x95,0x64,0x00,0x02,0x3c,0x02,0xee,0xee,
-0x00,0xa2,0x10,0x25,0x34,0x63,0x00,0xbc,0xac,0x62,0x00,0x00,0x10,0x86,0xff,0xe6,
-0xa1,0x60,0x00,0x04,0x24,0x02,0xff,0xff,0x08,0x00,0x1b,0x66,0xa5,0x62,0x00,0x02,
-0x00,0x05,0x40,0xc0,0x01,0x05,0x30,0x21,0x27,0xbd,0xff,0xd8,0x00,0x06,0x30,0x80,
-0x27,0x82,0x8f,0xf4,0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,
-0xaf,0xb3,0x00,0x1c,0xaf,0xb0,0x00,0x10,0x00,0xc2,0x10,0x21,0x8c,0x47,0x00,0x18,
-0x00,0xa0,0x90,0x21,0x3c,0x02,0x80,0x00,0x3c,0x05,0xb0,0x03,0x34,0xa5,0x00,0x20,
-0x24,0x42,0x6e,0x10,0xac,0xa2,0x00,0x00,0x27,0x83,0x90,0x00,0x00,0xc3,0x30,0x21,
-0x8c,0xe2,0x00,0x00,0x80,0xc5,0x00,0x06,0x00,0x80,0x88,0x21,0x30,0x42,0xff,0xff,
-0x00,0x45,0x10,0x21,0x30,0x43,0x00,0xff,0x10,0x60,0x00,0x02,0x00,0x02,0x12,0x02,
-0x24,0x42,0x00,0x01,0x30,0x53,0x00,0xff,0x01,0x12,0x10,0x21,0x00,0x02,0x10,0x80,
-0x27,0x83,0x90,0x00,0x00,0x43,0x10,0x21,0x80,0x44,0x00,0x07,0x00,0x00,0x00,0x00,
-0x10,0x80,0x00,0x4b,0x26,0x24,0x00,0x06,0x32,0x50,0xff,0xff,0x02,0x20,0x20,0x21,
-0x0c,0x00,0x1b,0x26,0x02,0x00,0x28,0x21,0x92,0x22,0x00,0x10,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x2e,0x3c,0x03,0xb0,0x08,0x3c,0x09,0x80,0x01,0x27,0x88,0x8f,0xf0,
-0xa6,0x32,0x00,0x0c,0x00,0x10,0x20,0xc0,0x00,0x90,0x20,0x21,0x00,0x04,0x20,0x80,
-0x00,0x88,0x20,0x21,0x94,0x82,0x00,0x04,0x3c,0x03,0xb0,0x08,0x3c,0x07,0xb0,0x03,
-0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x48,0x10,0x21,
-0x00,0xa3,0x28,0x21,0x25,0x26,0x82,0xe4,0x34,0x03,0xff,0xff,0x34,0xe7,0x00,0x20,
-0xac,0xe6,0x00,0x00,0xa4,0x83,0x00,0x02,0xa4,0x43,0x00,0x00,0xac,0xa3,0x00,0x00,
-0x92,0x22,0x00,0x10,0x92,0x23,0x00,0x0a,0xa6,0x32,0x00,0x0e,0x02,0x62,0x10,0x21,
-0x14,0x60,0x00,0x05,0xa2,0x22,0x00,0x10,0x92,0x22,0x00,0x16,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xfe,0xa2,0x22,0x00,0x16,0x92,0x22,0x00,0x04,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x92,0x22,0x00,0x16,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0xfd,0xa2,0x22,0x00,0x16,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc,
-0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,0x96,0x22,0x00,0x0e,
-0x27,0x88,0x8f,0xf0,0x00,0x02,0x20,0xc0,0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80,
-0x00,0x88,0x20,0x21,0x94,0x82,0x00,0x04,0x3c,0x06,0xb0,0x03,0x3c,0x09,0x80,0x01,
-0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0xa3,0x28,0x21,
-0x00,0x48,0x10,0x21,0x34,0xc6,0x00,0x20,0x25,0x23,0x82,0xe4,0xac,0xc3,0x00,0x00,
-0xa4,0x50,0x00,0x00,0xac,0xb0,0x00,0x00,0x08,0x00,0x1b,0xb5,0xa4,0x90,0x00,0x02,
-0x08,0x00,0x1b,0xac,0x32,0x50,0xff,0xff,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x24,0x42,0x6f,0xd8,0x34,0x63,0x00,0x20,0xac,0x62,0x00,0x00,0x90,0x82,0x00,0x04,
-0x97,0xaa,0x00,0x12,0x00,0x80,0x60,0x21,0x30,0xa8,0xff,0xff,0x00,0x4a,0x20,0x23,
-0x34,0x09,0xff,0xff,0x30,0xcf,0xff,0xff,0x30,0xee,0xff,0xff,0x11,0x09,0x00,0x73,
-0xa1,0x84,0x00,0x04,0x00,0x0e,0xc0,0xc0,0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21,
-0x03,0x0e,0x20,0x21,0x27,0x8d,0x8f,0xf0,0x00,0x04,0x20,0x80,0x00,0x02,0x10,0x80,
-0x00,0x4d,0x10,0x21,0x00,0x8d,0x20,0x21,0x94,0x86,0x00,0x02,0x94,0x43,0x00,0x04,
-0x3c,0x19,0x80,0x01,0xa4,0x46,0x00,0x02,0x00,0x03,0x28,0xc0,0x00,0xa3,0x18,0x21,
-0x94,0x87,0x00,0x02,0x3c,0x02,0xb0,0x08,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x21,
-0x00,0x6d,0x18,0x21,0x27,0x22,0x82,0xe4,0x3c,0x01,0xb0,0x03,0xac,0x22,0x00,0x20,
-0xa4,0x66,0x00,0x00,0x10,0xe9,0x00,0x57,0xac,0xa6,0x00,0x00,0x01,0xe0,0x30,0x21,
-0x11,0x40,0x00,0x1d,0x00,0x00,0x48,0x21,0x01,0x40,0x38,0x21,0x27,0x8b,0x8f,0xf4,
-0x27,0x8a,0x90,0x00,0x00,0x06,0x40,0xc0,0x01,0x06,0x18,0x21,0x00,0x03,0x18,0x80,
-0x00,0x6b,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x6a,0x18,0x21,0x80,0x65,0x00,0x06,
-0x8c,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0xff,0xff,0x00,0x45,0x10,0x21,
-0x30,0x44,0x00,0xff,0x00,0x02,0x12,0x02,0x01,0x22,0x18,0x21,0x24,0x62,0x00,0x01,
-0x14,0x80,0x00,0x02,0x30,0x49,0x00,0xff,0x30,0x69,0x00,0xff,0x01,0x06,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x4d,0x10,0x21,0x24,0xe7,0xff,0xff,0x94,0x46,0x00,0x02,
-0x14,0xe0,0xff,0xe9,0x00,0x06,0x40,0xc0,0x91,0x82,0x00,0x10,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x20,0x3c,0x06,0xb0,0x03,0xa5,0x8f,0x00,0x0c,0x03,0x0e,0x20,0x21,
-0x00,0x04,0x20,0x80,0x00,0x8d,0x20,0x21,0x94,0x82,0x00,0x04,0x3c,0x03,0xb0,0x08,
-0x3c,0x07,0xb0,0x03,0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x4d,0x10,0x21,0x00,0xa3,0x28,0x21,0x27,0x26,0x82,0xe4,0x34,0x03,0xff,0xff,
-0x34,0xe7,0x00,0x20,0xac,0xe6,0x00,0x00,0xa4,0x83,0x00,0x02,0xa4,0x43,0x00,0x00,
-0xac,0xa3,0x00,0x00,0x91,0x82,0x00,0x10,0x91,0x83,0x00,0x04,0xa5,0x8e,0x00,0x0e,
-0x01,0x22,0x10,0x21,0x14,0x60,0x00,0x05,0xa1,0x82,0x00,0x10,0x91,0x82,0x00,0x16,
-0x00,0x00,0x00,0x00,0x30,0x42,0x00,0xfd,0xa1,0x82,0x00,0x16,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x95,0x82,0x00,0x0e,0x3c,0x03,0xb0,0x08,0x00,0x02,0x20,0xc0,
-0x00,0x82,0x20,0x21,0x00,0x04,0x20,0x80,0x00,0x8d,0x20,0x21,0x94,0x82,0x00,0x04,
-0x34,0xc6,0x00,0x20,0x27,0x27,0x82,0xe4,0x00,0x02,0x28,0xc0,0x00,0xa2,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0xa3,0x28,0x21,0x00,0x4d,0x10,0x21,0xac,0xc7,0x00,0x00,
-0xa4,0x8f,0x00,0x02,0xa4,0x4f,0x00,0x00,0xac,0xaf,0x00,0x00,0x08,0x00,0x1c,0x44,
-0x03,0x0e,0x20,0x21,0x08,0x00,0x1c,0x1f,0xa5,0x88,0x00,0x02,0x00,0x0e,0xc0,0xc0,
-0x03,0x0e,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x8d,0x8f,0xf0,0x00,0x4d,0x10,0x21,
-0x94,0x43,0x00,0x02,0x30,0x84,0x00,0xff,0x14,0x80,0x00,0x05,0xa5,0x83,0x00,0x00,
-0x24,0x02,0xff,0xff,0x3c,0x19,0x80,0x01,0x08,0x00,0x1c,0x1f,0xa5,0x82,0x00,0x02,
-0x08,0x00,0x1c,0x1f,0x3c,0x19,0x80,0x01,0x3c,0x08,0xb0,0x03,0x3c,0x02,0x80,0x00,
-0x27,0xbd,0xff,0x78,0x35,0x08,0x00,0x20,0x24,0x42,0x72,0x18,0xaf,0xb2,0x00,0x68,
-0xaf,0xb1,0x00,0x64,0xaf,0xb0,0x00,0x60,0xad,0x02,0x00,0x00,0xaf,0xbf,0x00,0x84,
-0xaf,0xbe,0x00,0x80,0xaf,0xb7,0x00,0x7c,0xaf,0xb6,0x00,0x78,0xaf,0xb5,0x00,0x74,
-0xaf,0xb4,0x00,0x70,0xaf,0xb3,0x00,0x6c,0xaf,0xa4,0x00,0x88,0x90,0x83,0x00,0x0a,
-0x27,0x82,0xb3,0xf0,0xaf,0xa6,0x00,0x90,0x00,0x03,0x18,0x80,0x00,0x62,0x18,0x21,
-0x8c,0x63,0x00,0x00,0xaf,0xa7,0x00,0x94,0x27,0x86,0x8f,0xf4,0xaf,0xa3,0x00,0x1c,
-0x94,0x63,0x00,0x14,0x30,0xb1,0xff,0xff,0x24,0x08,0x00,0x01,0x00,0x03,0x20,0xc0,
-0xaf,0xa3,0x00,0x18,0x00,0x83,0x18,0x21,0xaf,0xa4,0x00,0x54,0x00,0x03,0x18,0x80,
-0x27,0x84,0x90,0x00,0x00,0x64,0x20,0x21,0x80,0x82,0x00,0x06,0x00,0x66,0x18,0x21,
-0x8c,0x66,0x00,0x18,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x8c,0xc4,0x00,0x08,
-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0x04,0x2f,0xc2,
-0x00,0x04,0x1c,0x82,0x00,0xc2,0x38,0x21,0x00,0x04,0x24,0x42,0x8f,0xa2,0x00,0x1c,
-0x30,0x63,0x00,0x01,0x30,0x84,0x00,0x01,0xaf,0xa5,0x00,0x3c,0xaf,0xa3,0x00,0x34,
-0xaf,0xa4,0x00,0x38,0xaf,0xa0,0x00,0x40,0xaf,0xa0,0x00,0x44,0xaf,0xa0,0x00,0x50,
-0xaf,0xa8,0x00,0x20,0x80,0x42,0x00,0x12,0x8f,0xb2,0x00,0x18,0xaf,0xa2,0x00,0x28,
-0x8c,0xd0,0x00,0x0c,0x14,0xa0,0x01,0xe4,0x00,0x60,0x30,0x21,0x00,0x10,0x10,0x82,
-0x30,0x45,0x00,0x07,0x10,0xa0,0x00,0x11,0xaf,0xa0,0x00,0x30,0x8f,0xa4,0x00,0x98,
-0x27,0x82,0x80,0x1c,0x00,0x04,0x18,0x40,0x00,0x62,0x18,0x21,0x24,0xa2,0x00,0x06,
-0x8f,0xa5,0x00,0x20,0x94,0x64,0x00,0x00,0x00,0x45,0x10,0x04,0x00,0x44,0x00,0x1a,
-0x14,0x80,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d,0x00,0x00,0x10,0x12,
-0x24,0x42,0x00,0x20,0x30,0x42,0xff,0xfc,0xaf,0xa2,0x00,0x30,0x8f,0xa3,0x00,0x18,
-0x8f,0xa4,0x00,0x28,0x34,0x02,0xff,0xff,0xaf,0xa0,0x00,0x2c,0xaf,0xa2,0x00,0x48,
-0xaf,0xa3,0x00,0x4c,0x00,0x60,0xf0,0x21,0x00,0x00,0xb8,0x21,0x18,0x80,0x00,0x48,
-0xaf,0xa0,0x00,0x24,0x00,0x11,0x89,0x02,0xaf,0xb1,0x00,0x58,0x00,0x80,0xa8,0x21,
-0x00,0x12,0x10,0xc0,0x00,0x52,0x18,0x21,0x00,0x03,0x80,0x80,0x27,0x85,0x8f,0xf0,
-0x02,0x40,0x20,0x21,0x00,0x40,0xa0,0x21,0x02,0x05,0x10,0x21,0x94,0x56,0x00,0x02,
-0x0c,0x00,0x12,0x87,0x00,0x00,0x28,0x21,0x90,0x42,0x00,0x00,0x24,0x03,0x00,0x08,
-0x30,0x42,0x00,0x0c,0x10,0x43,0x01,0x9e,0x24,0x04,0x00,0x01,0x24,0x02,0x00,0x01,
-0x10,0x82,0x01,0x7c,0x3c,0x02,0xb0,0x03,0x8f,0xa6,0x00,0x88,0x34,0x42,0x01,0x04,
-0x84,0xc5,0x00,0x0c,0x02,0x92,0x18,0x21,0x94,0x46,0x00,0x00,0x00,0x05,0x20,0xc0,
-0x00,0x85,0x20,0x21,0x00,0x03,0x18,0x80,0x27,0x82,0x90,0x00,0x27,0x85,0x8f,0xf8,
-0x00,0x65,0x28,0x21,0x00,0x62,0x18,0x21,0x80,0x71,0x00,0x05,0x80,0x73,0x00,0x04,
-0x8f,0xa3,0x00,0x88,0x30,0xd0,0xff,0xff,0x00,0x10,0x3a,0x03,0x32,0x08,0x00,0xff,
-0x27,0x82,0x90,0x10,0x00,0x04,0x20,0x80,0x80,0xa6,0x00,0x06,0x00,0x82,0x20,0x21,
-0xa4,0x67,0x00,0x44,0xa4,0x68,0x00,0x46,0x8c,0x84,0x00,0x00,0x38,0xc6,0x00,0x00,
-0x01,0x00,0x80,0x21,0x00,0x04,0x15,0x02,0x30,0x42,0x00,0x01,0x10,0x40,0x00,0x03,
-0x00,0xe6,0x80,0x0a,0x00,0x04,0x14,0x02,0x30,0x50,0x00,0x0f,0x12,0x20,0x01,0x50,
-0x02,0x40,0x20,0x21,0x02,0x71,0x10,0x21,0x00,0x50,0x10,0x2a,0x14,0x40,0x00,0xed,
-0x02,0x92,0x10,0x21,0x93,0x82,0x8b,0x61,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,
-0x14,0x40,0x00,0xe0,0x02,0x92,0x28,0x21,0x26,0xe2,0x00,0x01,0x30,0x57,0xff,0xff,
-0x02,0x40,0xf0,0x21,0x26,0xb5,0xff,0xff,0x16,0xa0,0xff,0xbd,0x02,0xc0,0x90,0x21,
-0x16,0xe0,0x00,0xd0,0x00,0x00,0x00,0x00,0x8f,0xa3,0x00,0x98,0x00,0x00,0x00,0x00,
-0x2c,0x62,0x00,0x10,0x10,0x40,0x00,0x2e,0x00,0x00,0x00,0x00,0x8f,0xa4,0x00,0x24,
-0x00,0x00,0x00,0x00,0x18,0x80,0x00,0x2a,0x24,0x03,0x00,0x01,0x8f,0xa5,0x00,0x1c,
-0x27,0x84,0x8f,0xf4,0x94,0xb2,0x00,0x14,0xa0,0xa3,0x00,0x12,0x8f,0xa6,0x00,0x3c,
-0x00,0x12,0x10,0xc0,0x00,0x52,0x10,0x21,0x00,0x02,0x80,0x80,0x27,0x82,0x90,0x00,
-0x02,0x02,0x10,0x21,0x80,0x43,0x00,0x06,0x02,0x04,0x20,0x21,0x8c,0x85,0x00,0x18,
-0x24,0x63,0x00,0x02,0x00,0x03,0x17,0xc2,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x43,
-0x00,0x03,0x18,0x40,0x14,0xc0,0x00,0x0e,0x00,0xa3,0x38,0x21,0x27,0x82,0x8f,0xf0,
-0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x06,0x8f,0xa8,0x00,0x1c,0x24,0x02,0x00,0x01,
-0xa5,0x03,0x00,0x1a,0x7b,0xbe,0x04,0x3c,0x7b,0xb6,0x03,0xfc,0x7b,0xb4,0x03,0xbc,
-0x7b,0xb2,0x03,0x7c,0x7b,0xb0,0x03,0x3c,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x88,
-0x8f,0xa4,0x00,0x98,0x8f,0xa5,0x00,0x38,0x8f,0xa6,0x00,0x34,0xaf,0xa0,0x00,0x10,
-0x0c,0x00,0x09,0x06,0xaf,0xa0,0x00,0x14,0x08,0x00,0x1d,0x4b,0x00,0x00,0x00,0x00,
-0x8f,0xa3,0x00,0x44,0x93,0x82,0x81,0x59,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x61,
-0x30,0x69,0x00,0x03,0x8f,0xa4,0x00,0x24,0x8f,0xa5,0x00,0x28,0x00,0x00,0x00,0x00,
-0x00,0x85,0x10,0x2a,0x10,0x40,0x00,0x8f,0x00,0x00,0x00,0x00,0x8f,0xa6,0x00,0x1c,
-0x00,0x00,0x00,0x00,0x90,0xc4,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff,
-0x00,0xa3,0x10,0x2a,0x10,0x40,0x00,0x87,0x00,0x00,0x00,0x00,0x8f,0xa8,0x00,0x24,
-0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x83,0x00,0x65,0x10,0x23,0x00,0xa8,0x18,0x23,
-0x00,0x62,0x10,0x2a,0x14,0x40,0x00,0x7d,0x30,0x63,0x00,0xff,0x00,0x85,0x10,0x23,
-0x30,0x42,0x00,0xff,0xaf,0xa2,0x00,0x50,0x8f,0xa2,0x00,0x50,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x73,0x00,0x00,0xa8,0x21,0x27,0x8c,0x8f,0xf0,0x3c,0x0b,0x80,0xff,
-0x24,0x10,0x00,0x04,0x27,0x91,0x8f,0xf4,0x35,0x6b,0xff,0xff,0x3c,0x0d,0x7f,0x00,
-0x27,0x8e,0x90,0x00,0x01,0x80,0x78,0x21,0x00,0x12,0x30,0xc0,0x00,0xd2,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x4c,0x10,0x21,0x94,0x42,0x00,0x06,0x8f,0xa3,0x00,0x2c,
-0x8f,0xa4,0x00,0x30,0xaf,0xa2,0x00,0x44,0x8f,0xa5,0x00,0x44,0x30,0x49,0x00,0x03,
-0x02,0x09,0x10,0x23,0x30,0x42,0x00,0x03,0x00,0xa2,0x10,0x21,0x8f,0xa8,0x00,0x30,
-0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff,0x00,0x64,0x38,0x21,0x01,0x02,0x28,0x23,
-0x00,0x62,0x18,0x21,0x00,0x48,0x10,0x2b,0x10,0x40,0x00,0x52,0x00,0x00,0x20,0x21,
-0x30,0xe7,0xff,0xff,0x30,0xa4,0xff,0xff,0xaf,0xa7,0x00,0x2c,0x00,0xd2,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x51,0x18,0x21,0x8c,0x65,0x00,0x18,0x00,0x04,0x25,0x40,
-0x00,0x8d,0x20,0x24,0x8c,0xa8,0x00,0x04,0x00,0x4e,0x18,0x21,0x00,0x4f,0x50,0x21,
-0x01,0x0b,0x40,0x24,0x01,0x04,0x40,0x25,0xac,0xa8,0x00,0x04,0x8f,0xa4,0x00,0x98,
-0x8f,0xa2,0x00,0x50,0x26,0xb5,0x00,0x01,0xa0,0x64,0x00,0x00,0x8c,0xa4,0x00,0x08,
-0x00,0x00,0x00,0x00,0x04,0x81,0x00,0x0c,0x02,0xa2,0x30,0x2a,0x80,0x62,0x00,0x06,
-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0xa2,0x38,0x21,0x8f,0xa5,0x00,0x40,
-0x00,0x00,0x00,0x00,0xa4,0xe5,0x00,0x00,0x95,0x52,0x00,0x02,0x14,0xc0,0xff,0xc7,
-0x00,0x12,0x30,0xc0,0x8f,0xa4,0x00,0x24,0x8f,0xa5,0x00,0x50,0x8f,0xa6,0x00,0x1c,
-0x8f,0xa3,0x00,0x2c,0x00,0x85,0x80,0x21,0xa0,0xd0,0x00,0x12,0x00,0x09,0x10,0x23,
-0x30,0x42,0x00,0x03,0x8f,0xa8,0x00,0x88,0x00,0x62,0x10,0x23,0xa4,0xc2,0x00,0x1a,
-0x85,0x03,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0xc0,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x80,0x27,0x83,0x8f,0xf4,0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x18,
-0x00,0x00,0x00,0x00,0x8c,0x83,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,
-0x14,0x60,0xff,0x74,0x02,0x00,0x10,0x21,0x8f,0xa3,0x00,0x54,0x8f,0xa4,0x00,0x18,
-0x8f,0xa5,0x00,0x24,0x00,0x64,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x83,0x90,0x08,
-0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x00,0x10,0xa0,0x00,0x03,0x00,0x00,0x30,0x21,
-0x08,0x00,0x1d,0x51,0x02,0x00,0x10,0x21,0x93,0x82,0x80,0x10,0x00,0x00,0x28,0x21,
-0x00,0x00,0x38,0x21,0x0c,0x00,0x21,0xf5,0xaf,0xa2,0x00,0x10,0x08,0x00,0x1d,0x51,
-0x02,0x00,0x10,0x21,0x30,0x63,0xff,0xff,0x08,0x00,0x1d,0xa3,0xaf,0xa3,0x00,0x2c,
-0x8f,0xa8,0x00,0x44,0x08,0x00,0x1d,0xc5,0x31,0x09,0x00,0x03,0x08,0x00,0x1d,0x7e,
-0xaf,0xa3,0x00,0x50,0x8f,0xa6,0x00,0x44,0xaf,0xa0,0x00,0x50,0x08,0x00,0x1d,0xc5,
-0x30,0xc9,0x00,0x03,0x8f,0xa5,0x00,0x48,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x1c,
-0x03,0xc0,0x38,0x21,0x0c,0x00,0x1b,0xf6,0xaf,0xb7,0x00,0x10,0x08,0x00,0x1d,0x2e,
-0x00,0x00,0x00,0x00,0x00,0x05,0x28,0x80,0x27,0x82,0x8f,0xf0,0x00,0xa2,0x28,0x21,
-0x00,0x00,0x20,0x21,0x0c,0x00,0x01,0x4b,0x00,0x00,0x00,0x00,0x08,0x00,0x1d,0x27,
-0x26,0xe2,0x00,0x01,0x00,0x02,0x80,0x80,0x27,0x83,0x90,0x00,0x8f,0xa4,0x00,0x1c,
-0x02,0x03,0x18,0x21,0x26,0x31,0x00,0x01,0x02,0x40,0x28,0x21,0x0c,0x00,0x1f,0x08,
-0xa0,0x71,0x00,0x05,0x14,0x40,0xff,0x13,0x00,0x00,0x00,0x00,0x16,0xe0,0x00,0x4d,
-0x03,0xc0,0x38,0x21,0x8f,0xa4,0x00,0x24,0x8f,0xa5,0x00,0x20,0x24,0x02,0x00,0x01,
-0x24,0x84,0x00,0x01,0xaf,0xb2,0x00,0x48,0xaf,0xb6,0x00,0x4c,0x02,0xc0,0xf0,0x21,
-0x10,0xa2,0x00,0x41,0xaf,0xa4,0x00,0x24,0x27,0x82,0x8f,0xf0,0x02,0x02,0x10,0x21,
-0x94,0x42,0x00,0x06,0x8f,0xa4,0x00,0x30,0xaf,0xa0,0x00,0x20,0xaf,0xa2,0x00,0x44,
-0x30,0x49,0x00,0x03,0x8f,0xa8,0x00,0x44,0x00,0x09,0x10,0x23,0x30,0x42,0x00,0x03,
-0x01,0x02,0x10,0x21,0x24,0x42,0x00,0x04,0x30,0x42,0xff,0xff,0x00,0x44,0x18,0x2b,
-0x10,0x60,0x00,0x2b,0x00,0x00,0x00,0x00,0x8f,0xa5,0x00,0x2c,0x00,0x82,0x10,0x23,
-0x00,0xa4,0x18,0x21,0x30,0x63,0xff,0xff,0x30,0x44,0xff,0xff,0xaf,0xa3,0x00,0x2c,
-0x02,0x92,0x28,0x21,0x00,0x05,0x28,0x80,0x27,0x82,0x8f,0xf4,0x00,0xa2,0x10,0x21,
-0x8c,0x46,0x00,0x18,0x3c,0x03,0x80,0xff,0x3c,0x02,0x7f,0x00,0x8c,0xc8,0x00,0x04,
-0x00,0x04,0x25,0x40,0x34,0x63,0xff,0xff,0x00,0x82,0x20,0x24,0x01,0x03,0x40,0x24,
-0x01,0x04,0x40,0x25,0xac,0xc8,0x00,0x04,0x8f,0xa8,0x00,0x98,0x27,0x82,0x90,0x00,
-0x00,0xa2,0x10,0x21,0xa0,0x48,0x00,0x00,0x8c,0xc4,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x04,0x27,0xc2,0x10,0x80,0xfe,0xdb,0xaf,0xa4,0x00,0x3c,0x80,0x42,0x00,0x06,
-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0xc2,0x38,0x21,0x8f,0xa2,0x00,0x40,
-0x00,0x00,0x00,0x00,0xa4,0xe2,0x00,0x00,0x08,0x00,0x1d,0x2a,0x26,0xb5,0xff,0xff,
-0x8f,0xa6,0x00,0x2c,0x00,0x00,0x20,0x21,0x00,0xc2,0x10,0x21,0x30,0x42,0xff,0xff,
-0x08,0x00,0x1e,0x38,0xaf,0xa2,0x00,0x2c,0x8f,0xa6,0x00,0x1c,0x08,0x00,0x1e,0x22,
-0xa4,0xd2,0x00,0x14,0x8f,0xa5,0x00,0x48,0x8f,0xa6,0x00,0x4c,0x8f,0xa4,0x00,0x1c,
-0x0c,0x00,0x1b,0xf6,0xaf,0xb7,0x00,0x10,0x08,0x00,0x1e,0x19,0x00,0x00,0xb8,0x21,
-0x0c,0x00,0x12,0x87,0x00,0x00,0x28,0x21,0x00,0x40,0x18,0x21,0x94,0x42,0x00,0x00,
-0x00,0x00,0x00,0x00,0x34,0x42,0x08,0x00,0xa4,0x62,0x00,0x00,0x08,0x00,0x1d,0x1e,
-0x02,0x71,0x10,0x21,0x02,0x92,0x18,0x21,0x00,0x03,0x80,0x80,0x27,0x82,0x8f,0xf4,
-0x02,0x02,0x10,0x21,0x8c,0x44,0x00,0x18,0x00,0x00,0x00,0x00,0x8c,0x83,0x00,0x04,
-0x00,0x00,0x00,0x00,0x30,0x63,0x00,0x10,0x10,0x60,0x00,0x09,0x24,0x06,0x00,0x01,
-0x93,0x82,0x8b,0x61,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x10,0x40,0xfe,0xa2,
-0x3c,0x04,0x00,0x80,0x27,0x85,0x8f,0xf0,0x08,0x00,0x1e,0x09,0x02,0x05,0x28,0x21,
-0x27,0x83,0x90,0x08,0x27,0x82,0x90,0x00,0x02,0x03,0x18,0x21,0x02,0x02,0x10,0x21,
-0x90,0x64,0x00,0x00,0x90,0x45,0x00,0x05,0x93,0x83,0x80,0x10,0x00,0x00,0x38,0x21,
-0x0c,0x00,0x21,0xf5,0xaf,0xa3,0x00,0x10,0x08,0x00,0x1e,0x80,0x00,0x00,0x00,0x00,
-0x27,0x82,0x90,0x08,0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x02,0x8f,0xa6,0x00,0x58,
-0x00,0x03,0x19,0x02,0x00,0x66,0x18,0x23,0x30,0x63,0x0f,0xff,0x28,0x62,0x00,0x20,
-0x10,0x40,0x00,0x06,0x28,0x62,0x00,0x40,0x8f,0xa8,0x00,0x90,0x00,0x00,0x00,0x00,
-0x00,0x68,0x10,0x06,0x08,0x00,0x1c,0xf7,0x30,0x44,0x00,0x01,0x10,0x40,0x00,0x04,
-0x00,0x00,0x00,0x00,0x8f,0xa4,0x00,0x94,0x08,0x00,0x1e,0xa1,0x00,0x64,0x10,0x06,
-0x08,0x00,0x1c,0xf7,0x00,0x00,0x20,0x21,0x8f,0xa4,0x00,0x98,0x8f,0xa5,0x00,0x38,
-0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x06,0xaf,0xa8,0x00,0x14,0x30,0x42,0xff,0xff,
-0x08,0x00,0x1c,0xc7,0xaf,0xa2,0x00,0x40,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x00,
-0x27,0xbd,0xff,0xe0,0x34,0x42,0x00,0x20,0x24,0x63,0x7a,0xc8,0xaf,0xb1,0x00,0x14,
-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x18,0xac,0x43,0x00,0x00,0x90,0x82,0x00,0x0a,
-0x00,0x80,0x80,0x21,0x14,0x40,0x00,0x45,0x00,0x00,0x88,0x21,0x92,0x02,0x00,0x04,
-0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x3c,0x00,0x00,0x00,0x00,0x12,0x20,0x00,0x18,
-0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x92,0x05,0x00,0x0a,0x30,0x42,0x00,0xfc,
-0x10,0xa0,0x00,0x03,0xa2,0x02,0x00,0x16,0x34,0x42,0x00,0x01,0xa2,0x02,0x00,0x16,
-0x92,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff,0x10,0x60,0x00,0x05,
-0x00,0x00,0x00,0x00,0x92,0x02,0x00,0x16,0x00,0x00,0x00,0x00,0x34,0x42,0x00,0x02,
-0xa2,0x02,0x00,0x16,0x10,0x60,0x00,0x0a,0x00,0x00,0x00,0x00,0x14,0xa0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x96,0x02,0x00,0x00,0xa2,0x00,0x00,0x17,0xa6,0x02,0x00,0x14,
-0x8f,0xbf,0x00,0x18,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,
-0x14,0x80,0x00,0x05,0x24,0x02,0x00,0x01,0x96,0x03,0x00,0x06,0xa2,0x02,0x00,0x17,
-0x08,0x00,0x1e,0xdc,0xa6,0x03,0x00,0x14,0x96,0x04,0x00,0x00,0x96,0x05,0x00,0x06,
-0x27,0x86,0x8f,0xf0,0x00,0x04,0x10,0xc0,0x00,0x05,0x18,0xc0,0x00,0x44,0x10,0x21,
-0x00,0x65,0x18,0x21,0x00,0x02,0x10,0x80,0x00,0x03,0x18,0x80,0x00,0x66,0x18,0x21,
-0x00,0x46,0x10,0x21,0x8c,0x65,0x00,0x08,0x8c,0x44,0x00,0x08,0x0c,0x00,0x12,0x78,
-0x00,0x00,0x00,0x00,0x30,0x43,0x00,0xff,0x10,0x60,0x00,0x04,0xa2,0x02,0x00,0x17,
-0x96,0x02,0x00,0x06,0x08,0x00,0x1e,0xdc,0xa6,0x02,0x00,0x14,0x96,0x02,0x00,0x00,
-0x08,0x00,0x1e,0xdc,0xa6,0x02,0x00,0x14,0x96,0x05,0x00,0x00,0x0c,0x00,0x1f,0x08,
-0x02,0x00,0x20,0x21,0x08,0x00,0x1e,0xc3,0x02,0x22,0x88,0x21,0x94,0x85,0x00,0x06,
-0x0c,0x00,0x1f,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x1e,0xbf,0x00,0x40,0x88,0x21,
-0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,0x24,0x42,0x7c,0x20,
-0x27,0xbd,0xff,0xf0,0xac,0x62,0x00,0x00,0x00,0x00,0x10,0x21,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x10,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x00,0x34,0x63,0x00,0x20,
-0x24,0x42,0x7c,0x44,0xac,0x62,0x00,0x00,0x90,0x89,0x00,0x0a,0x00,0x80,0x30,0x21,
-0x11,0x20,0x00,0x05,0x00,0xa0,0x50,0x21,0x90,0x82,0x00,0x17,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x1b,0x00,0x00,0x00,0x00,0x90,0xc7,0x00,0x04,0x00,0x00,0x00,0x00,
-0x10,0xe0,0x00,0x1b,0x00,0x00,0x00,0x00,0x94,0xc8,0x00,0x00,0x27,0x83,0x8f,0xf0,
-0x93,0x85,0x8b,0x60,0x00,0x08,0x10,0xc0,0x00,0x48,0x10,0x21,0x00,0x02,0x10,0x80,
-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x08,0x00,0xe5,0x28,0x2b,0x10,0xa0,0x00,0x06,
-0x01,0x44,0x18,0x23,0x8f,0x82,0x8b,0x78,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x2b,
-0x10,0x40,0x00,0x05,0x00,0x00,0x00,0x00,0x24,0x03,0x00,0x10,0xa4,0xc8,0x00,0x14,
-0x03,0xe0,0x00,0x08,0x00,0x60,0x10,0x21,0x11,0x20,0x00,0x05,0x00,0x00,0x00,0x00,
-0x94,0xc2,0x00,0x06,0x24,0x03,0x00,0x08,0x08,0x00,0x1f,0x34,0xa4,0xc2,0x00,0x14,
-0x08,0x00,0x1f,0x34,0x00,0x00,0x18,0x21,0x27,0xbd,0xff,0xc8,0xaf,0xb5,0x00,0x2c,
-0xaf,0xb4,0x00,0x28,0xaf,0xb3,0x00,0x24,0xaf,0xb0,0x00,0x18,0xaf,0xbf,0x00,0x30,
-0xaf,0xb2,0x00,0x20,0xaf,0xb1,0x00,0x1c,0x94,0x91,0x00,0x06,0x00,0x80,0xa0,0x21,
-0x3c,0x02,0x80,0x00,0x3c,0x04,0xb0,0x03,0x00,0x11,0xa8,0xc0,0x34,0x84,0x00,0x20,
-0x24,0x42,0x7c,0xf8,0x02,0xb1,0x48,0x21,0xac,0x82,0x00,0x00,0x00,0x09,0x48,0x80,
-0x24,0x03,0x00,0x01,0x27,0x82,0x90,0x00,0xa2,0x83,0x00,0x12,0x01,0x22,0x10,0x21,
-0x27,0x84,0x8f,0xf4,0x01,0x24,0x20,0x21,0x80,0x48,0x00,0x06,0x8c,0x8a,0x00,0x18,
-0x27,0x83,0x90,0x10,0x01,0x23,0x48,0x21,0x8d,0x24,0x00,0x00,0x25,0x08,0x00,0x02,
-0x8d,0x42,0x00,0x00,0x8d,0x49,0x00,0x04,0x00,0x08,0x17,0xc2,0x8d,0x43,0x00,0x08,
-0x01,0x02,0x40,0x21,0x00,0x04,0x25,0xc2,0x00,0x08,0x40,0x43,0x30,0x84,0x00,0x01,
-0x00,0x03,0x1f,0xc2,0x00,0x08,0x40,0x40,0x00,0xe0,0x80,0x21,0x00,0x64,0x18,0x24,
-0x00,0x09,0x49,0x42,0x01,0x48,0x10,0x21,0x00,0xa0,0x98,0x21,0x00,0xa0,0x20,0x21,
-0x00,0x40,0x38,0x21,0x02,0x00,0x28,0x21,0x14,0x60,0x00,0x19,0x31,0x29,0x00,0x01,
-0x94,0x42,0x00,0x00,0x02,0xb1,0x88,0x21,0x02,0x00,0x28,0x21,0x00,0x11,0x88,0x80,
-0x27,0x90,0x8f,0xf0,0x02,0x30,0x80,0x21,0x96,0x03,0x00,0x06,0x30,0x52,0xff,0xff,
-0x02,0x60,0x20,0x21,0x00,0x60,0x30,0x21,0xa6,0x83,0x00,0x1a,0x27,0x82,0x8f,0xf8,
-0x0c,0x00,0x08,0xdf,0x02,0x22,0x88,0x21,0x00,0x52,0x10,0x21,0x96,0x03,0x00,0x06,
-0xa6,0x22,0x00,0x04,0x8f,0xbf,0x00,0x30,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c,
-0x7b,0xb0,0x00,0xfc,0x00,0x60,0x10,0x21,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x38,
-0xaf,0xa9,0x00,0x10,0x0c,0x00,0x09,0x06,0xaf,0xa0,0x00,0x14,0x08,0x00,0x1f,0x72,
-0x02,0xb1,0x88,0x21,0x27,0xbd,0xff,0xc0,0xaf,0xbe,0x00,0x38,0xaf,0xb7,0x00,0x34,
-0xaf,0xb6,0x00,0x30,0xaf,0xb5,0x00,0x2c,0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,
-0xaf,0xbf,0x00,0x3c,0xaf,0xb4,0x00,0x28,0xaf,0xb2,0x00,0x20,0xaf,0xb0,0x00,0x18,
-0x94,0x90,0x00,0x00,0x3c,0x08,0xb0,0x03,0x35,0x08,0x00,0x20,0x00,0x10,0x10,0xc0,
-0x00,0x50,0x18,0x21,0x00,0x40,0x88,0x21,0x3c,0x02,0x80,0x00,0x00,0x03,0x48,0x80,
-0x24,0x42,0x7e,0x34,0x00,0x80,0x98,0x21,0x27,0x84,0x90,0x00,0x01,0x24,0x20,0x21,
-0x93,0xb7,0x00,0x53,0xad,0x02,0x00,0x00,0x80,0x83,0x00,0x06,0x27,0x82,0x8f,0xf4,
-0x01,0x22,0x10,0x21,0x8c,0x44,0x00,0x18,0x24,0x63,0x00,0x02,0x00,0x03,0x17,0xc2,
-0x8c,0x88,0x00,0x08,0x00,0x62,0x18,0x21,0x00,0x03,0x18,0x43,0x00,0x03,0x18,0x40,
-0xaf,0xa7,0x00,0x4c,0x2c,0xa2,0x00,0x10,0x00,0xa0,0xa8,0x21,0x00,0x83,0x50,0x21,
-0x00,0x08,0x47,0xc2,0x00,0xc0,0x58,0x21,0x00,0x00,0xb0,0x21,0x8c,0x92,0x00,0x0c,
-0x14,0x40,0x00,0x13,0x00,0x00,0xf0,0x21,0x92,0x67,0x00,0x04,0x24,0x14,0x00,0x01,
-0x12,0x87,0x00,0x10,0x02,0x30,0x10,0x21,0x27,0x83,0x90,0x08,0x01,0x23,0x18,0x21,
-0x80,0x64,0x00,0x00,0x27,0x83,0xb5,0x60,0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,
-0x90,0x44,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x80,0x00,0x23,0x00,0x00,0x00,0x00,
-0x02,0x30,0x10,0x21,0x00,0x02,0x80,0x80,0x24,0x04,0x00,0x01,0x27,0x83,0x90,0x10,
-0xa2,0x64,0x00,0x12,0x02,0x03,0x18,0x21,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x02,0x15,0xc2,0x30,0x42,0x00,0x01,0x01,0x02,0x10,0x24,0x14,0x40,0x00,0x0e,
-0x02,0xa0,0x20,0x21,0x27,0x82,0x8f,0xf0,0x02,0x02,0x10,0x21,0x94,0x43,0x00,0x06,
-0x00,0x00,0x00,0x00,0xa6,0x63,0x00,0x1a,0x94,0x42,0x00,0x06,0x7b,0xbe,0x01,0xfc,
-0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,0x8f,0xa5,0x00,0x4c,0x01,0x60,0x30,0x21,
-0x01,0x40,0x38,0x21,0xaf,0xa0,0x00,0x10,0x0c,0x00,0x09,0x06,0xaf,0xa0,0x00,0x14,
-0x08,0x00,0x1f,0xd9,0x00,0x00,0x00,0x00,0x27,0x83,0x90,0x10,0x01,0x23,0x18,0x21,
-0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x15,0xc2,0x30,0x42,0x00,0x01,
-0x01,0x02,0x10,0x24,0x14,0x40,0x00,0xaf,0x00,0xa0,0x20,0x21,0x32,0x4f,0x00,0x03,
-0x00,0x12,0x10,0x82,0x25,0xe3,0x00,0x0d,0x30,0x45,0x00,0x07,0x00,0x74,0x78,0x04,
-0x10,0xa0,0x00,0x0e,0x00,0x00,0x90,0x21,0x27,0x82,0x80,0x1c,0x00,0x15,0x18,0x40,
-0x00,0x62,0x18,0x21,0x94,0x64,0x00,0x00,0x24,0xa2,0x00,0x06,0x00,0x54,0x10,0x04,
-0x00,0x44,0x00,0x1a,0x14,0x80,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d,
-0x00,0x00,0x10,0x12,0x24,0x42,0x00,0x20,0x30,0x52,0xff,0xfc,0x02,0x30,0x10,0x21,
-0x27,0x83,0x90,0x00,0x00,0x02,0x10,0x80,0x00,0x43,0x10,0x21,0x90,0x44,0x00,0x03,
-0x00,0x00,0x00,0x00,0x30,0x83,0x00,0xff,0x2c,0x62,0x00,0x0c,0x14,0x40,0x00,0x04,
-0x2c,0x62,0x00,0x19,0x30,0x82,0x00,0x0f,0x24,0x43,0x00,0x0c,0x2c,0x62,0x00,0x19,
-0x10,0x40,0x00,0x19,0x24,0x0e,0x00,0x20,0x24,0x62,0xff,0xe9,0x2c,0x42,0x00,0x02,
-0x14,0x40,0x00,0x15,0x24,0x0e,0x00,0x10,0x24,0x62,0xff,0xeb,0x2c,0x42,0x00,0x02,
-0x14,0x40,0x00,0x11,0x24,0x0e,0x00,0x08,0x24,0x02,0x00,0x14,0x10,0x62,0x00,0x0e,
-0x24,0x0e,0x00,0x02,0x24,0x62,0xff,0xef,0x2c,0x42,0x00,0x03,0x14,0x40,0x00,0x0a,
-0x24,0x0e,0x00,0x10,0x24,0x62,0xff,0xf1,0x2c,0x42,0x00,0x02,0x14,0x40,0x00,0x06,
-0x24,0x0e,0x00,0x08,0x24,0x62,0xff,0xf3,0x2c,0x42,0x00,0x02,0x24,0x0e,0x00,0x04,
-0x24,0x03,0x00,0x02,0x00,0x62,0x70,0x0a,0x30,0xe2,0x00,0xff,0x00,0x00,0x48,0x21,
-0x00,0x00,0x68,0x21,0x10,0x40,0x00,0x6d,0x00,0x00,0x58,0x21,0x3c,0x14,0x80,0xff,
-0x27,0x99,0x8f,0xf0,0x01,0xf2,0xc0,0x23,0x36,0x94,0xff,0xff,0x01,0xc9,0x10,0x2a,
-0x14,0x40,0x00,0x64,0x24,0x03,0x00,0x04,0x00,0x10,0x28,0xc0,0x00,0xb0,0x10,0x21,
-0x00,0x02,0x10,0x80,0x00,0x59,0x10,0x21,0x94,0x56,0x00,0x06,0x00,0x00,0x00,0x00,
-0x32,0xcc,0x00,0x03,0x00,0x6c,0x10,0x23,0x30,0x42,0x00,0x03,0x02,0xc2,0x10,0x21,
-0x24,0x42,0x00,0x04,0x30,0x51,0xff,0xff,0x02,0x32,0x18,0x2b,0x10,0x60,0x00,0x4d,
-0x01,0xf1,0x10,0x23,0x02,0x51,0x10,0x23,0x01,0x78,0x18,0x2b,0x10,0x60,0x00,0x34,
-0x30,0x44,0xff,0xff,0x29,0x22,0x00,0x40,0x10,0x40,0x00,0x31,0x01,0x72,0x18,0x21,
-0x25,0x22,0x00,0x01,0x00,0x02,0x16,0x00,0x00,0x02,0x4e,0x03,0x00,0xb0,0x10,0x21,
-0x00,0x02,0x30,0x80,0x27,0x82,0x8f,0xf4,0x30,0x6b,0xff,0xff,0x00,0xc2,0x18,0x21,
-0x8c,0x67,0x00,0x18,0x00,0x04,0x25,0x40,0x3c,0x03,0x7f,0x00,0x8c,0xe2,0x00,0x04,
-0x00,0x83,0x20,0x24,0x27,0x83,0x90,0x00,0x00,0x54,0x10,0x24,0x00,0xc3,0x28,0x21,
-0x00,0x44,0x10,0x25,0xac,0xe2,0x00,0x04,0x16,0xe0,0x00,0x02,0xa0,0xb5,0x00,0x00,
-0xa0,0xb5,0x00,0x03,0x27,0x84,0x90,0x10,0x00,0xc4,0x18,0x21,0x8c,0x62,0x00,0x00,
-0x8c,0xe8,0x00,0x08,0x00,0x02,0x15,0xc2,0x00,0x08,0x47,0xc2,0x30,0x42,0x00,0x01,
-0x01,0x02,0x10,0x24,0x10,0x40,0x00,0x0a,0x00,0x00,0x00,0x00,0x80,0xa2,0x00,0x06,
-0x00,0x00,0x00,0x00,0x24,0x42,0x00,0x02,0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,
-0x00,0x02,0x10,0x43,0x00,0x02,0x10,0x40,0x00,0xe2,0x50,0x21,0xa5,0x5e,0x00,0x00,
-0x92,0x62,0x00,0x04,0x25,0xad,0x00,0x01,0x27,0x84,0x8f,0xf0,0x00,0xc4,0x18,0x21,
-0x01,0xa2,0x10,0x2a,0x94,0x70,0x00,0x02,0x14,0x40,0xff,0xb8,0x00,0x00,0x00,0x00,
-0x96,0x63,0x00,0x14,0x00,0x0c,0x10,0x23,0xa2,0x69,0x00,0x12,0x30,0x42,0x00,0x03,
-0x01,0x62,0x10,0x23,0x00,0x03,0x80,0xc0,0x8f,0xa5,0x00,0x4c,0x30,0x4b,0xff,0xff,
-0x02,0x03,0x80,0x21,0x27,0x82,0x8f,0xf8,0x00,0x10,0x80,0x80,0xa6,0x6b,0x00,0x1a,
-0x02,0xa0,0x20,0x21,0x01,0x60,0x30,0x21,0x01,0x60,0x88,0x21,0x0c,0x00,0x08,0xdf,
-0x02,0x02,0x80,0x21,0x00,0x5e,0x10,0x21,0xa6,0x02,0x00,0x04,0x08,0x00,0x1f,0xdf,
-0x02,0x20,0x10,0x21,0x01,0x62,0x10,0x2b,0x10,0x40,0xff,0xe9,0x00,0x00,0x20,0x21,
-0x29,0x22,0x00,0x40,0x10,0x40,0xff,0xe6,0x01,0x71,0x18,0x21,0x08,0x00,0x20,0x55,
-0x25,0x22,0x00,0x01,0x08,0x00,0x20,0x84,0x32,0xcc,0x00,0x03,0x08,0x00,0x20,0x84,
-0x00,0x00,0x60,0x21,0x8f,0xa5,0x00,0x4c,0x01,0x40,0x38,0x21,0xaf,0xa0,0x00,0x10,
-0x0c,0x00,0x09,0x06,0xaf,0xb4,0x00,0x14,0x92,0x67,0x00,0x04,0x08,0x00,0x1f,0xf7,
-0x30,0x5e,0xff,0xff,0x30,0x84,0xff,0xff,0x00,0x04,0x30,0xc0,0x00,0xc4,0x20,0x21,
-0x00,0x04,0x20,0x80,0x27,0x82,0x8f,0xf0,0x3c,0x03,0xb0,0x08,0x30,0xa5,0xff,0xff,
-0x00,0x82,0x20,0x21,0x00,0xc3,0x30,0x21,0xac,0xc5,0x00,0x00,0x03,0xe0,0x00,0x08,
-0xa4,0x85,0x00,0x00,0x30,0x84,0xff,0xff,0x00,0x04,0x30,0xc0,0x00,0xc4,0x30,0x21,
-0x27,0x88,0x8f,0xf0,0x00,0x06,0x30,0x80,0x00,0xc8,0x30,0x21,0x94,0xc3,0x00,0x04,
-0x3c,0x02,0xb0,0x08,0x3c,0x07,0xb0,0x03,0x00,0x03,0x20,0xc0,0x00,0x83,0x18,0x21,
-0x00,0x03,0x18,0x80,0x00,0x82,0x20,0x21,0x3c,0x02,0x80,0x01,0x30,0xa5,0xff,0xff,
-0x00,0x68,0x18,0x21,0x34,0xe7,0x00,0x20,0x24,0x42,0x82,0xe4,0xac,0xe2,0x00,0x00,
-0xa4,0xc5,0x00,0x02,0xa4,0x65,0x00,0x00,0x03,0xe0,0x00,0x08,0xac,0x85,0x00,0x00,
-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20,0x24,0x63,0x83,0x40,
-0xac,0x43,0x00,0x00,0x90,0x82,0x00,0x10,0x3c,0x08,0xb0,0x03,0x3c,0x09,0xb0,0x06,
-0x27,0x87,0x8f,0xf0,0x3c,0x0d,0xb0,0x08,0x34,0x0e,0xff,0xff,0x35,0x08,0x00,0x62,
-0x00,0x80,0x30,0x21,0x24,0x0c,0xff,0xff,0x10,0x40,0x00,0x2c,0x35,0x29,0x80,0x20,
-0x97,0x82,0x8f,0xe0,0x94,0x85,0x00,0x0c,0x3c,0x0b,0xb0,0x03,0x00,0x02,0x18,0xc0,
-0x00,0x62,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21,0xa4,0x45,0x00,0x00,
-0x94,0x84,0x00,0x0e,0x00,0x6d,0x18,0x21,0xac,0x65,0x00,0x00,0x00,0x04,0x10,0xc0,
-0x00,0x44,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x47,0x10,0x21,0x94,0x45,0x00,0x04,
-0x3c,0x0a,0x77,0x77,0x35,0x6b,0x00,0xb4,0x00,0x05,0x10,0xc0,0x00,0x45,0x18,0x21,
-0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,0x00,0x4d,0x10,0x21,0xac,0x4e,0x00,0x00,
-0xa4,0x6e,0x00,0x00,0x95,0x04,0x00,0x00,0x90,0xc3,0x00,0x10,0x24,0x02,0x00,0xff,
-0x00,0x44,0x10,0x23,0x00,0x43,0x10,0x2a,0xa7,0x85,0x8f,0xe0,0x10,0x40,0x00,0x04,
-0x35,0x4a,0x88,0x88,0xad,0x6a,0x00,0x00,0x90,0xc3,0x00,0x10,0x00,0x00,0x00,0x00,
-0x30,0x63,0x00,0xff,0x3c,0x02,0x00,0x40,0x00,0x62,0x18,0x25,0xad,0x23,0x00,0x00,
-0xa4,0xcc,0x00,0x0e,0xa4,0xcc,0x00,0x0c,0xa0,0xc0,0x00,0x10,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x30,0x84,0xff,0xff,0x00,0x04,0x10,0xc0,0x00,0x44,0x10,0x21,
-0x27,0x89,0x8f,0xf0,0x00,0x02,0x10,0x80,0x00,0x49,0x10,0x21,0x97,0x83,0x8f,0xe0,
-0x94,0x4a,0x00,0x04,0x3c,0x02,0xb0,0x08,0x00,0x03,0x38,0xc0,0x00,0x0a,0x40,0xc0,
-0x00,0xe3,0x18,0x21,0x01,0x0a,0x28,0x21,0x00,0xe2,0x38,0x21,0x01,0x02,0x40,0x21,
-0x00,0x03,0x18,0x80,0x00,0x05,0x28,0x80,0x3c,0x06,0xb0,0x03,0x3c,0x02,0x80,0x01,
-0x00,0xa9,0x28,0x21,0x00,0x69,0x18,0x21,0x34,0xc6,0x00,0x20,0x34,0x09,0xff,0xff,
-0x24,0x42,0x84,0x34,0xac,0xc2,0x00,0x00,0xa4,0x64,0x00,0x00,0xac,0xe4,0x00,0x00,
-0xa4,0xa9,0x00,0x00,0xad,0x09,0x00,0x00,0xa7,0x8a,0x8f,0xe0,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0x63,0x00,0x20,
-0x24,0x42,0x84,0xb4,0x3c,0x04,0xb0,0x03,0xac,0x62,0x00,0x00,0x34,0x84,0x01,0x10,
-0x8c,0x82,0x00,0x00,0x97,0x83,0x81,0x60,0x30,0x42,0xff,0xff,0x10,0x62,0x00,0x16,
-0x24,0x0a,0x00,0x01,0xa7,0x82,0x81,0x60,0xaf,0x80,0xb4,0x40,0x00,0x40,0x28,0x21,
-0x24,0x06,0x00,0x01,0x27,0x84,0xb4,0x44,0x25,0x43,0xff,0xff,0x00,0x66,0x10,0x04,
-0x00,0xa2,0x10,0x24,0x14,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x8c,0x83,0xff,0xfc,
-0x00,0x00,0x00,0x00,0x00,0x66,0x10,0x04,0x00,0xa2,0x10,0x24,0x38,0x42,0x00,0x00,
-0x01,0x42,0x18,0x0a,0x25,0x4a,0x00,0x01,0x2d,0x42,0x00,0x14,0xac,0x83,0x00,0x00,
-0x14,0x40,0xff,0xf1,0x24,0x84,0x00,0x04,0x3c,0x0b,0xb0,0x03,0x00,0x00,0x50,0x21,
-0x3c,0x0c,0x80,0x00,0x27,0x89,0xb4,0x90,0x35,0x6b,0x01,0x20,0x8d,0x68,0x00,0x00,
-0x8d,0x23,0x00,0x04,0x01,0x0c,0x10,0x24,0x00,0x02,0x17,0xc2,0x11,0x03,0x00,0x37,
-0xa1,0x22,0x00,0xdc,0xa1,0x20,0x00,0xd5,0xa1,0x20,0x00,0xd6,0x01,0x20,0x30,0x21,
-0x00,0x00,0x38,0x21,0x00,0x00,0x28,0x21,0x01,0x20,0x20,0x21,0x00,0xa8,0x10,0x06,
-0x30,0x42,0x00,0x01,0x10,0xe0,0x00,0x10,0xa0,0x82,0x00,0x0a,0x90,0x82,0x00,0x07,
-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x31,0x24,0xa2,0xff,0xff,0xa0,0x82,0x00,0x08,
-0x90,0x82,0x00,0x0a,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x09,0x00,0x00,0x00,0x00,
-0x90,0x83,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0x40,0x00,0x43,0x10,0x21,
-0x00,0x46,0x10,0x21,0xa0,0x45,0x00,0x09,0x90,0x82,0x00,0x0a,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x07,0x00,0x00,0x00,0x00,0x14,0xe0,0x00,0x04,0x00,0x00,0x00,0x00,
-0xa0,0xc5,0x00,0xd5,0x24,0x07,0x00,0x01,0xa0,0x85,0x00,0x08,0xa0,0xc5,0x00,0xd6,
-0x24,0xa5,0x00,0x01,0x2c,0xa2,0x00,0x1c,0x14,0x40,0xff,0xe0,0x24,0x84,0x00,0x03,
-0x90,0xc4,0x00,0xd5,0x00,0x00,0x28,0x21,0x00,0xa4,0x10,0x2b,0x10,0x40,0x00,0x0b,
-0x00,0x00,0x00,0x00,0x00,0xc0,0x18,0x21,0xa0,0x64,0x00,0x08,0x90,0xc2,0x00,0xd5,
-0x24,0xa5,0x00,0x01,0xa0,0x62,0x00,0x09,0x90,0xc4,0x00,0xd5,0x00,0x00,0x00,0x00,
-0x00,0xa4,0x10,0x2b,0x14,0x40,0xff,0xf8,0x24,0x63,0x00,0x03,0x25,0x4a,0x00,0x01,
-0x2d,0x42,0x00,0x08,0xad,0x28,0x00,0x04,0x25,0x6b,0x00,0x04,0x14,0x40,0xff,0xbf,
-0x25,0x29,0x00,0xec,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x90,0x82,0x00,0x05,
-0x08,0x00,0x21,0x68,0xa0,0x82,0x00,0x08,0x97,0x85,0x8b,0x6a,0x3c,0x03,0xb0,0x03,
-0x3c,0x02,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x63,0x00,0x20,0x24,0x42,0x86,0x68,
-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x62,0x00,0x00,0x30,0x90,0x00,0xff,
-0x00,0x05,0x28,0x42,0x00,0x00,0x48,0x21,0x27,0x8f,0xb4,0x94,0x00,0x00,0x50,0x21,
-0x00,0x00,0x58,0x21,0x27,0x98,0xb5,0x74,0x27,0x99,0xb5,0x70,0x27,0x8e,0xb5,0x6e,
-0x27,0x8c,0xb4,0x98,0x27,0x8d,0xb4,0xf0,0x27,0x88,0xb5,0x68,0x00,0x0a,0x18,0x80,
-0x01,0x6f,0x10,0x21,0xac,0x40,0x00,0x00,0xac,0x45,0x00,0x58,0x00,0x6e,0x20,0x21,
-0x00,0x78,0x10,0x21,0xa1,0x00,0xff,0xfc,0xad,0x00,0x00,0x00,0xa1,0x00,0x00,0x04,
-0xa1,0x00,0x00,0x05,0xad,0x00,0xff,0xf8,0x00,0x79,0x18,0x21,0x24,0x06,0x00,0x01,
-0x24,0xc6,0xff,0xff,0xa0,0x80,0x00,0x00,0xa4,0x60,0x00,0x00,0xac,0x40,0x00,0x00,
-0x24,0x63,0x00,0x02,0x24,0x42,0x00,0x04,0x04,0xc1,0xff,0xf9,0x24,0x84,0x00,0x01,
-0x00,0x0a,0x10,0x80,0x00,0x4d,0x20,0x21,0x00,0x00,0x30,0x21,0x00,0x4c,0x18,0x21,
-0x27,0x87,0x81,0x64,0x8c,0xe2,0x00,0x00,0x24,0xe7,0x00,0x04,0xac,0x82,0x00,0x00,
-0xa0,0x66,0x00,0x00,0xa0,0x66,0x00,0x01,0x24,0xc6,0x00,0x01,0x28,0xc2,0x00,0x1c,
-0xa0,0x60,0x00,0x02,0x24,0x84,0x00,0x04,0x14,0x40,0xff,0xf6,0x24,0x63,0x00,0x03,
-0x25,0x29,0x00,0x01,0x29,0x22,0x00,0x08,0x25,0x4a,0x00,0x3b,0x25,0x08,0x00,0xec,
-0x14,0x40,0xff,0xd6,0x25,0x6b,0x00,0xec,0xa7,0x80,0x81,0x60,0x00,0x00,0x48,0x21,
-0x27,0x83,0xb4,0x40,0xac,0x69,0x00,0x00,0x25,0x29,0x00,0x01,0x29,0x22,0x00,0x0c,
-0x14,0x40,0xff,0xfc,0x24,0x63,0x00,0x04,0x0c,0x00,0x21,0x2d,0x00,0x00,0x00,0x00,
-0x2e,0x04,0x00,0x14,0x27,0x83,0xb4,0x90,0x24,0x09,0x00,0x07,0x10,0x80,0x00,0x0a,
-0x00,0x00,0x00,0x00,0x90,0x62,0x00,0xd5,0x25,0x29,0xff,0xff,0xa0,0x62,0x00,0x00,
-0x05,0x21,0xff,0xfa,0x24,0x63,0x00,0xec,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x90,0x62,0x00,0xd6,0x08,0x00,0x21,0xeb,
-0x25,0x29,0xff,0xff,0x30,0x84,0x00,0xff,0x00,0x04,0x11,0x00,0x00,0x44,0x10,0x23,
-0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x23,0x00,0x02,0x10,0x80,0x27,0x83,0xb4,0x90,
-0x00,0x43,0x60,0x21,0x3c,0x04,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0x84,0x00,0x20,
-0x24,0x42,0x87,0xd4,0x30,0xc6,0x00,0xff,0x93,0xa9,0x00,0x13,0x30,0xa5,0x00,0xff,
-0x30,0xe7,0x00,0xff,0xac,0x82,0x00,0x00,0x10,0xc0,0x00,0xeb,0x25,0x8f,0x00,0xd0,
-0x91,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xfc,0x2c,0x43,0x00,0x18,
-0x10,0x60,0x00,0xcf,0x3c,0x03,0x80,0x01,0x00,0x02,0x10,0x80,0x24,0x63,0x02,0x5c,
-0x00,0x43,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,
-0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x2d,0x10,0x40,0x00,0x14,0x00,0x00,0x00,0x00,
-0x10,0xa0,0x00,0x0f,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x09,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00,
-0x8d,0x82,0x00,0xd0,0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xd0,0x03,0xe0,0x00,0x08,
-0xad,0x82,0x00,0xd0,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xe0,
-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0x00,0x01,0x10,0xa0,0x00,0x0f,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xf9,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x07,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,
-0x14,0xa2,0xff,0xf0,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,
-0x24,0x42,0xff,0xe8,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,
-0x08,0x00,0x22,0x23,0x24,0x42,0x00,0x02,0x10,0xa0,0xff,0xfc,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xe6,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0xa2,0xff,0xf4,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xef,0x00,0x00,0x00,0x00,
-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xf8,0x2d,0x22,0x00,0x19,
-0x14,0x40,0xff,0xde,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xec,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0xa2,0xff,0xe4,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00,
-0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xf0,0x2d,0x22,0x00,0x1b,
-0x10,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xdc,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc6,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x14,0xa2,0xff,0xce,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,
-0x24,0x42,0xff,0xf4,0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xe3,0x00,0x00,0x00,0x00,
-0x10,0xa0,0xff,0xce,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc9,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x34,
-0x24,0x02,0x00,0x03,0x2d,0x22,0x00,0x23,0x10,0x40,0xff,0xd7,0x00,0x00,0x00,0x00,
-0x10,0xa0,0xff,0xaf,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xbd,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xda,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,
-0x14,0xa2,0xff,0x9f,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x25,0x00,0x00,0x00,0x00,
-0x2d,0x22,0x00,0x25,0x10,0x40,0xff,0xc8,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa0,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x97,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x80,
-0x24,0x02,0x00,0x03,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xfc,
-0x2d,0x22,0x00,0x16,0x14,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa3,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x8d,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x9b,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xa8,
-0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x22,0x23,0x24,0x42,0xff,0xfa,
-0x10,0xa0,0xff,0x96,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x80,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x8e,0x00,0x00,0x00,0x00,
-0x08,0x00,0x22,0x48,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x17,0x14,0x40,0xff,0x9e,
-0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x97,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x19,
-0x10,0x40,0xff,0xe2,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x84,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x6e,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0xa2,0xff,0x7c,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x89,0x00,0x00,0x00,0x00,
-0x08,0x00,0x22,0x25,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0xb4,0x2d,0x22,0x00,0x1b,
-0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xde,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x73,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5d,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x6b,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x88,
-0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x25,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x23,
-0x14,0x40,0xff,0xf2,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x4e,0x00,0x00,0x00,0x00,
-0x08,0x00,0x22,0x4c,0x2d,0x22,0x00,0x25,0x08,0x00,0x22,0x85,0x2d,0x22,0x00,0x27,
-0x10,0xa0,0xff,0x5e,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x48,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x56,0x24,0x02,0x00,0x03,
-0x14,0xa2,0xff,0x63,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x91,0x00,0x00,0x00,0x00,
-0x2d,0x22,0x00,0x27,0x14,0x40,0xff,0x8e,0x00,0x00,0x00,0x00,0x08,0x00,0x22,0x3e,
-0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x29,0x14,0x40,0xff,0x89,0x00,0x00,0x00,0x00,
-0x08,0x00,0x22,0x2b,0x00,0x00,0x00,0x00,0x91,0x86,0x00,0x00,0x91,0x83,0x00,0xd4,
-0x25,0x8d,0x00,0x5c,0x30,0xc4,0x00,0xff,0x00,0x04,0x10,0x40,0x00,0x44,0x10,0x21,
-0x00,0x04,0x50,0x80,0x01,0x82,0x58,0x21,0x01,0x8a,0x40,0x21,0x25,0x78,0x00,0x08,
-0x10,0x60,0x00,0x37,0x25,0x0e,0x00,0x60,0x2c,0xa2,0x00,0x03,0x14,0x40,0x00,0x25,
-0x00,0x00,0x00,0x00,0x91,0x82,0x00,0xdd,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x1e,
-0x00,0x00,0x00,0x00,0x27,0x87,0x81,0x64,0x01,0x47,0x10,0x21,0x8c,0x43,0x00,0x00,
-0x00,0x00,0x00,0x00,0xad,0x03,0x00,0x60,0x91,0x62,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x40,0x30,0x21,0xa1,0x82,0x00,0x00,0x30,0xc2,0x00,0xff,0x00,0x02,0x10,0x80,
-0x00,0x47,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x18,0x42,
-0xad,0xa3,0x00,0x00,0x91,0x84,0x00,0x00,0x8d,0xc5,0x00,0x00,0x00,0x04,0x20,0x80,
-0x00,0x87,0x10,0x21,0x8c,0x43,0x00,0x00,0x00,0x05,0x28,0x40,0x00,0x8c,0x20,0x21,
-0x00,0x03,0x18,0x80,0x00,0xa3,0x10,0x2b,0x00,0x62,0x28,0x0a,0xac,0x85,0x00,0x60,
-0x03,0xe0,0x00,0x08,0xa1,0x80,0x00,0xd4,0x27,0x87,0x81,0x64,0x08,0x00,0x23,0x0e,
-0xa1,0x80,0x00,0xdd,0x27,0x82,0x81,0xd4,0x8d,0x83,0x00,0xd8,0x00,0x82,0x10,0x21,
-0x90,0x44,0x00,0x00,0x24,0x63,0x00,0x01,0x00,0x64,0x20,0x2b,0x14,0x80,0xff,0x0d,
-0xad,0x83,0x00,0xd8,0x8d,0x02,0x00,0x60,0xa1,0x80,0x00,0xd4,0x00,0x02,0x1f,0xc2,
-0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x03,0xe0,0x00,0x08,0xad,0x82,0x00,0x5c,
-0x10,0xe0,0x00,0x1a,0x24,0x83,0xff,0xfc,0x2c,0x62,0x00,0x18,0x10,0x40,0x01,0x18,
-0x00,0x03,0x10,0x80,0x3c,0x03,0x80,0x01,0x24,0x63,0x02,0xbc,0x00,0x43,0x10,0x21,
-0x8c,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2d,0x22,0x00,0x2d,0x10,0x40,0x00,0x5f,0x00,0x00,0x00,0x00,0x10,0xa0,0x00,0x5a,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x54,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x51,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,
-0x00,0x00,0x00,0x00,0x24,0x42,0xff,0xd0,0xad,0x82,0x00,0xd0,0x8d,0xe3,0x00,0x00,
-0x8d,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x10,0x21,0xad,0xa2,0x00,0x00,
-0xad,0xe0,0x00,0x00,0x8d,0xa3,0x00,0x00,0x8d,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x83,0x10,0x2a,0x10,0x40,0x00,0x22,0x00,0x00,0x00,0x00,0x93,0x05,0x00,0x01,
-0x91,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x45,0x00,0x05,0x24,0x02,0x00,0x01,
-0xa1,0x85,0x00,0x00,0xa1,0x82,0x00,0xd4,0x03,0xe0,0x00,0x08,0xad,0x80,0x00,0xd8,
-0x91,0x82,0x00,0xdd,0x24,0x03,0x00,0x01,0x10,0x43,0x00,0x05,0x00,0x00,0x00,0x00,
-0xa1,0x83,0x00,0xd4,0xad,0x80,0x00,0xd8,0x03,0xe0,0x00,0x08,0xa1,0x83,0x00,0xdd,
-0x00,0x04,0x17,0xc2,0x00,0x82,0x10,0x21,0x00,0x02,0x10,0x43,0xad,0xa2,0x00,0x00,
-0x91,0x83,0x00,0x00,0x27,0x82,0x81,0x64,0x8d,0xc5,0x00,0x00,0x00,0x03,0x18,0x80,
-0x00,0x62,0x18,0x21,0x8c,0x64,0x00,0x00,0x00,0x05,0x28,0x40,0x00,0x04,0x18,0x80,
-0x00,0xa3,0x10,0x2b,0x00,0x62,0x28,0x0a,0x08,0x00,0x23,0x20,0xad,0xc5,0x00,0x00,
-0x97,0x82,0x8b,0x6c,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x2a,0x10,0x40,0xfe,0xb9,
-0x00,0x00,0x00,0x00,0x91,0x82,0x00,0xdd,0x00,0x00,0x00,0x00,0x14,0x40,0x00,0x15,
-0x00,0x00,0x00,0x00,0x91,0x83,0x00,0x00,0x27,0x82,0x81,0x64,0x00,0x03,0x18,0x80,
-0x00,0x62,0x10,0x21,0x8c,0x44,0x00,0x00,0x00,0x6c,0x18,0x21,0xac,0x64,0x00,0x60,
-0x93,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x10,0x80,0x01,0x82,0x10,0x21,
-0x24,0x4e,0x00,0x60,0xa1,0x85,0x00,0x00,0x8d,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x02,0x1f,0xc2,0x00,0x43,0x10,0x21,0x00,0x02,0x10,0x43,0x03,0xe0,0x00,0x08,
-0xad,0xa2,0x00,0x00,0x08,0x00,0x23,0x92,0xa1,0x80,0x00,0xdd,0x8d,0x82,0x00,0xd0,
-0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xe0,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,
-0x24,0x42,0x00,0x01,0x10,0xa0,0x00,0x0d,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,
-0x10,0xa2,0xff,0xf9,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xa7,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xf0,0x00,0x00,0x00,0x00,
-0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xe8,0x8d,0x82,0x00,0xd0,
-0x08,0x00,0x23,0x4e,0x24,0x42,0x00,0x02,0x10,0xa0,0xff,0xfc,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xe8,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0xa2,0xff,0x96,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00,
-0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xf8,0x2d,0x22,0x00,0x19,
-0x14,0x40,0xff,0xe0,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xec,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xd8,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0xa2,0xff,0x86,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0xf1,0x00,0x00,0x00,0x00,
-0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xf0,0x2d,0x22,0x00,0x1b,
-0x10,0x40,0xff,0xf1,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xdc,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0xc8,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x14,0xa2,0xff,0xd0,0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,
-0x24,0x42,0xff,0xf4,0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xe3,0x00,0x00,0x00,0x00,
-0x10,0xa0,0xff,0xce,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x6b,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xd6,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xaa,
-0x24,0x02,0x00,0x03,0x2d,0x22,0x00,0x23,0x10,0x40,0xff,0xd7,0x00,0x00,0x00,0x00,
-0x10,0xa0,0xff,0xb1,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5f,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0xda,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x03,
-0x14,0xa2,0xff,0x56,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x9b,0x00,0x00,0x00,0x00,
-0x2d,0x22,0x00,0x25,0x10,0x40,0xff,0xc8,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa2,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x06,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x99,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xf4,
-0x24,0x02,0x00,0x03,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xfc,
-0x2d,0x22,0x00,0x16,0x14,0x40,0x00,0x0e,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0xa3,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x8f,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x3d,0x24,0x02,0x00,0x03,0x14,0xa2,0xff,0xa8,
-0x00,0x00,0x00,0x00,0x8d,0x82,0x00,0xd0,0x08,0x00,0x23,0x4e,0x24,0x42,0xff,0xfa,
-0x10,0xa0,0xff,0x96,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x82,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x30,0x00,0x00,0x00,0x00,
-0x08,0x00,0x23,0xbc,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x17,0x14,0x40,0xff,0x9e,
-0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x0b,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x19,
-0x10,0x40,0xff,0xe2,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x84,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x70,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0xa2,0xff,0x1e,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x89,0x00,0x00,0x00,0x00,
-0x08,0x00,0x23,0x9b,0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x28,0x2d,0x22,0x00,0x1b,
-0x2d,0x22,0x00,0x1e,0x10,0x40,0xff,0xde,0x00,0x00,0x00,0x00,0x10,0xa0,0xff,0x73,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x5f,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x02,0x10,0xa2,0xff,0x0d,0x24,0x02,0x00,0x03,0x10,0xa2,0xff,0x88,
-0x00,0x00,0x00,0x00,0x08,0x00,0x23,0x9b,0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x23,
-0x14,0x40,0xff,0xf2,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xc2,0x00,0x00,0x00,0x00,
-0x08,0x00,0x23,0xc0,0x2d,0x22,0x00,0x25,0x08,0x00,0x23,0xf9,0x2d,0x22,0x00,0x27,
-0x10,0xa0,0xff,0x5e,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x01,0x10,0xa2,0xff,0x4a,
-0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,0x10,0xa2,0xfe,0xf8,0x24,0x02,0x00,0x03,
-0x14,0xa2,0xff,0x63,0x00,0x00,0x00,0x00,0x08,0x00,0x24,0x05,0x00,0x00,0x00,0x00,
-0x2d,0x22,0x00,0x27,0x14,0x40,0xff,0x8e,0x00,0x00,0x00,0x00,0x08,0x00,0x23,0xb2,
-0x00,0x00,0x00,0x00,0x2d,0x22,0x00,0x29,0x14,0x40,0xff,0x89,0x00,0x00,0x00,0x00,
-0x08,0x00,0x23,0xa1,0x00,0x00,0x00,0x00,0x27,0xbd,0xff,0xe8,0x3c,0x02,0xb0,0x03,
-0xaf,0xbf,0x00,0x14,0xaf,0xb0,0x00,0x10,0x34,0x42,0x01,0x18,0x3c,0x03,0xb0,0x03,
-0x8c,0x50,0x00,0x00,0x34,0x63,0x01,0x2c,0x90,0x62,0x00,0x00,0x32,0x05,0x00,0x01,
-0xa3,0x82,0x80,0x10,0x14,0xa0,0x00,0x14,0x30,0x44,0x00,0xff,0x32,0x02,0x01,0x00,
-0x14,0x40,0x00,0x09,0x00,0x00,0x00,0x00,0x32,0x02,0x08,0x00,0x10,0x40,0x00,0x02,
-0x24,0x02,0x00,0x01,0xa3,0x82,0xbc,0x08,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x05,0x39,0x00,0x00,0x00,0x00,
-0x26,0x02,0xff,0x00,0xa3,0x80,0xbc,0x08,0x3c,0x01,0xb0,0x03,0xac,0x22,0x01,0x18,
-0x08,0x00,0x24,0x77,0x32,0x02,0x08,0x00,0x0c,0x00,0x21,0x9a,0x00,0x00,0x00,0x00,
-0x26,0x02,0xff,0xff,0x3c,0x01,0xb0,0x03,0xac,0x22,0x01,0x18,0x08,0x00,0x24,0x74,
-0x32,0x02,0x01,0x00,0x27,0xbd,0xff,0xe0,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xd0,
-0xaf,0xbf,0x00,0x18,0x8c,0x43,0x00,0x00,0x3c,0x02,0x00,0x40,0x24,0x07,0x0f,0xff,
-0x00,0x03,0x33,0x02,0x00,0x03,0x2d,0x02,0x00,0x03,0x43,0x02,0x30,0x69,0x0f,0xff,
-0x00,0x62,0x18,0x24,0x30,0xa5,0x00,0x03,0x30,0xc6,0x00,0xff,0x10,0x60,0x00,0x08,
-0x31,0x08,0x00,0xff,0x01,0x00,0x30,0x21,0x0c,0x00,0x25,0x38,0xaf,0xa9,0x00,0x10,
-0x8f,0xbf,0x00,0x18,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x20,
-0x0c,0x00,0x25,0x8a,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xd4,
-0x08,0x00,0x24,0xa0,0xac,0x62,0x00,0x00,0x27,0xbd,0xff,0xc0,0xaf,0xb6,0x00,0x30,
-0xaf,0xb3,0x00,0x24,0xaf,0xb1,0x00,0x1c,0xaf,0xb0,0x00,0x18,0xaf,0xbf,0x00,0x3c,
-0xaf,0xbe,0x00,0x38,0xaf,0xb7,0x00,0x34,0xaf,0xb5,0x00,0x2c,0xaf,0xb4,0x00,0x28,
-0xaf,0xb2,0x00,0x20,0x0c,0x00,0x17,0xc8,0x00,0x80,0x80,0x21,0x00,0x00,0xb0,0x21,
-0x00,0x00,0x88,0x21,0x10,0x40,0x00,0x12,0x00,0x00,0x98,0x21,0x3c,0x02,0xb0,0x03,
-0x3c,0x03,0xb0,0x03,0x3c,0x04,0xb0,0x03,0x24,0x05,0x00,0x01,0x34,0x42,0x00,0xbc,
-0x34,0x63,0x00,0xbb,0x34,0x84,0x00,0xba,0xa4,0x40,0x00,0x00,0xa0,0x65,0x00,0x00,
-0xa0,0x85,0x00,0x00,0x7b,0xbe,0x01,0xfc,0x7b,0xb6,0x01,0xbc,0x7b,0xb4,0x01,0x7c,
-0x7b,0xb2,0x01,0x3c,0x7b,0xb0,0x00,0xfc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x40,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x01,0x47,0x90,0x44,0x00,0x00,0x00,0x10,0x1a,0x02,
-0x3c,0x15,0xfd,0xff,0x30,0x84,0x00,0xff,0xa0,0x50,0x00,0x00,0x30,0x74,0x00,0x0f,
-0xaf,0xa4,0x00,0x10,0x00,0x00,0x90,0x21,0x3c,0x17,0x02,0x00,0x36,0xb5,0xff,0xff,
-0x3c,0x1e,0xb0,0x03,0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x00,0x00,0x57,0x10,0x25,
-0x00,0x40,0x28,0x21,0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x00,0x00,0x00,0x80,0x21,
-0x0c,0x00,0x26,0x52,0x00,0x00,0x00,0x00,0x26,0x03,0x00,0x01,0x30,0x70,0x00,0xff,
-0x10,0x40,0x00,0x47,0x2e,0x03,0x00,0x02,0x14,0x60,0xff,0xf9,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0x00,0x00,0x55,0x10,0x24,0x00,0x40,0x28,0x21,
-0x0c,0x00,0x06,0xc1,0x24,0x04,0x04,0x00,0x24,0x02,0x00,0x01,0x12,0x82,0x00,0x38,
-0x00,0x00,0x00,0x00,0x12,0x80,0x00,0x36,0x00,0x00,0x00,0x00,0x32,0x22,0x00,0x60,
-0x32,0x23,0x0c,0x00,0x00,0x03,0x1a,0x02,0x3c,0x05,0x00,0x60,0x00,0x02,0x11,0x42,
-0x02,0x25,0x20,0x24,0x00,0x43,0x10,0x25,0x3c,0x03,0x04,0x00,0x02,0x23,0x28,0x24,
-0x00,0x04,0x24,0x42,0x00,0x44,0x10,0x25,0x00,0x05,0x2d,0x02,0x00,0x45,0x88,0x25,
-0x12,0x20,0x00,0x05,0x26,0x42,0x00,0x01,0x26,0xc2,0x00,0x01,0x30,0x56,0x00,0xff,
-0x02,0x71,0x98,0x21,0x26,0x42,0x00,0x01,0x02,0x5e,0x20,0x21,0x30,0x52,0x00,0xff,
-0x2e,0x43,0x00,0x05,0xa0,0x91,0x00,0xd8,0x14,0x60,0xff,0xce,0x3c,0x02,0xb0,0x03,
-0x8f,0xa5,0x00,0x10,0x34,0x42,0x01,0x47,0xa0,0x45,0x00,0x00,0x12,0x60,0x00,0x0e,
-0x3c,0x02,0xb0,0x03,0x12,0xc0,0x00,0x0d,0x34,0x42,0x00,0xbc,0x00,0x13,0x10,0x40,
-0x00,0x53,0x10,0x21,0x00,0x02,0x10,0xc0,0x00,0x53,0x10,0x21,0x00,0x02,0x98,0x80,
-0x02,0x76,0x00,0x1b,0x16,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x0d,
-0x00,0x00,0x98,0x12,0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xbc,0x3c,0x03,0xb0,0x03,
-0x3c,0x04,0xb0,0x03,0xa4,0x53,0x00,0x00,0x34,0x63,0x00,0xbb,0x34,0x84,0x00,0xba,
-0x24,0x02,0x00,0x01,0xa0,0x60,0x00,0x00,0x08,0x00,0x24,0xc5,0xa0,0x82,0x00,0x00,
-0x0c,0x00,0x06,0xce,0x24,0x04,0x04,0xfc,0x08,0x00,0x24,0xf3,0x00,0x40,0x88,0x21,
-0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0xbc,0x3c,0x04,0xb0,0x03,0x3c,0x05,0xb0,0x03,
-0xa4,0x60,0x00,0x00,0x34,0x84,0x00,0xbb,0x34,0xa5,0x00,0xba,0x24,0x02,0x00,0x02,
-0x24,0x03,0x00,0x01,0xa0,0x82,0x00,0x00,0x08,0x00,0x24,0xc5,0xa0,0xa3,0x00,0x00,
-0x27,0xbd,0xff,0xd8,0xaf,0xb0,0x00,0x10,0x30,0xd0,0x00,0xff,0x2e,0x02,0x00,0x2e,
-0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xbf,0x00,0x20,0xaf,0xb3,0x00,0x1c,
-0x30,0xb1,0x00,0xff,0x14,0x40,0x00,0x06,0x00,0x80,0x90,0x21,0x8f,0xbf,0x00,0x20,
-0x7b,0xb2,0x00,0xfc,0x7b,0xb0,0x00,0xbc,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,
-0x2e,0x13,0x00,0x10,0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa0,0x24,0x06,0x01,0x07,
-0x12,0x60,0x00,0x38,0x02,0x00,0x30,0x21,0x8f,0xa2,0x00,0x38,0x30,0xc3,0x00,0x3f,
-0x3c,0x04,0xb0,0x09,0x00,0x02,0x14,0x00,0x00,0x43,0x30,0x25,0x34,0x84,0x01,0x60,
-0x90,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xfd,0x24,0x02,0x00,0x01,
-0x12,0x22,0x00,0x2a,0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x24,0x24,0x02,0x00,0x02,
-0x12,0x22,0x00,0x20,0x24,0x02,0x00,0x03,0x12,0x22,0x00,0x19,0x00,0x00,0x00,0x00,
-0x16,0x60,0xff,0xe2,0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x13,0x2a,0x22,0x00,0x02,
-0x14,0x40,0x00,0x0d,0x24,0x02,0x00,0x02,0x12,0x22,0x00,0x09,0x24,0x02,0x00,0x03,
-0x16,0x22,0xff,0xda,0x00,0x00,0x00,0x00,0x24,0x04,0x08,0x4c,0x24,0x05,0xff,0xff,
-0x0c,0x00,0x13,0x5b,0x3c,0x06,0x0c,0xb8,0x08,0x00,0x25,0x43,0x00,0x00,0x00,0x00,
-0x08,0x00,0x25,0x6b,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xd0,0x00,0x00,0x00,0x00,
-0x08,0x00,0x25,0x6b,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x6b,0x24,0x04,0x08,0x44,
-0x24,0x04,0x08,0x4c,0x0c,0x00,0x13,0x5b,0x24,0x05,0xff,0xff,0x08,0x00,0x25,0x60,
-0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x79,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xe0,
-0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x79,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0x79,
-0x24,0x04,0x08,0x44,0x02,0x40,0x20,0x21,0x0c,0x00,0x25,0xca,0x02,0x20,0x28,0x21,
-0x08,0x00,0x25,0x4e,0x00,0x40,0x30,0x21,0x27,0xbd,0xff,0xd8,0x2c,0xc2,0x00,0x2e,
-0xaf,0xb2,0x00,0x18,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x20,
-0xaf,0xb3,0x00,0x1c,0x00,0xc0,0x80,0x21,0x30,0xb1,0x00,0xff,0x00,0x80,0x90,0x21,
-0x14,0x40,0x00,0x07,0x00,0x00,0x18,0x21,0x8f,0xbf,0x00,0x20,0x7b,0xb2,0x00,0xfc,
-0x7b,0xb0,0x00,0xbc,0x00,0x60,0x10,0x21,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x28,
-0x2e,0x13,0x00,0x10,0x24,0x05,0x00,0x14,0x0c,0x00,0x13,0xa0,0x24,0x06,0x01,0x07,
-0x12,0x60,0x00,0x24,0x02,0x00,0x30,0x21,0x3c,0x03,0xb0,0x09,0x34,0x63,0x01,0x60,
-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x40,0xff,0xfd,0x30,0xc5,0x00,0x3f,
-0x0c,0x00,0x26,0x07,0x02,0x20,0x20,0x21,0x16,0x60,0x00,0x0a,0x00,0x40,0x80,0x21,
-0x24,0x02,0x00,0x01,0x12,0x22,0x00,0x15,0x2a,0x22,0x00,0x02,0x14,0x40,0x00,0x0f,
-0x24,0x02,0x00,0x02,0x12,0x22,0x00,0x0b,0x24,0x02,0x00,0x03,0x12,0x22,0x00,0x03,
-0x00,0x00,0x00,0x00,0x08,0x00,0x25,0x96,0x02,0x00,0x18,0x21,0x24,0x04,0x08,0x4c,
-0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5b,0x3c,0x06,0x0c,0xb8,0x08,0x00,0x25,0x96,
-0x02,0x00,0x18,0x21,0x08,0x00,0x25,0xb8,0x24,0x04,0x08,0x48,0x16,0x20,0xff,0xf5,
-0x00,0x00,0x00,0x00,0x08,0x00,0x25,0xb8,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xb8,
-0x24,0x04,0x08,0x44,0x02,0x40,0x20,0x21,0x0c,0x00,0x25,0xca,0x02,0x20,0x28,0x21,
-0x08,0x00,0x25,0xa2,0x00,0x40,0x30,0x21,0x27,0xbd,0xff,0xe8,0x2c,0xc2,0x00,0x1f,
-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0x00,0xc0,0x80,0x21,0x14,0x40,0x00,0x1d,
-0x30,0xa5,0x00,0xff,0x24,0x02,0x00,0x01,0x10,0xa2,0x00,0x18,0x28,0xa2,0x00,0x02,
-0x14,0x40,0x00,0x12,0x24,0x02,0x00,0x02,0x10,0xa2,0x00,0x0e,0x24,0x02,0x00,0x03,
-0x10,0xa2,0x00,0x07,0x24,0x04,0x08,0x4c,0x26,0x10,0xff,0xe2,0x02,0x00,0x10,0x21,
-0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,
-0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5b,0x3c,0x06,0x0d,0xf8,0x08,0x00,0x25,0xdb,
-0x26,0x10,0xff,0xe2,0x08,0x00,0x25,0xe0,0x24,0x04,0x08,0x48,0x14,0xa0,0xff,0xf2,
-0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xe1,0x24,0x05,0xff,0xff,0x08,0x00,0x25,0xe0,
-0x24,0x04,0x08,0x44,0x2c,0xc2,0x00,0x10,0x14,0x40,0xff,0xec,0x24,0x02,0x00,0x01,
-0x10,0xa2,0x00,0x14,0x28,0xa2,0x00,0x02,0x14,0x40,0x00,0x0e,0x24,0x02,0x00,0x02,
-0x10,0xa2,0x00,0x0a,0x24,0x02,0x00,0x03,0x10,0xa2,0x00,0x03,0x24,0x04,0x08,0x4c,
-0x08,0x00,0x25,0xdb,0x26,0x10,0xff,0xf1,0x24,0x05,0xff,0xff,0x0c,0x00,0x13,0x5b,
-0x3c,0x06,0x0d,0xb8,0x08,0x00,0x25,0xdb,0x26,0x10,0xff,0xf1,0x08,0x00,0x25,0xfa,
-0x24,0x04,0x08,0x48,0x14,0xa0,0xff,0xf6,0x24,0x04,0x08,0x40,0x08,0x00,0x25,0xfb,
-0x24,0x05,0xff,0xff,0x08,0x00,0x25,0xfa,0x24,0x04,0x08,0x44,0x27,0xbd,0xff,0xe8,
-0x30,0x84,0x00,0xff,0x24,0x02,0x00,0x01,0x10,0x82,0x00,0x39,0xaf,0xbf,0x00,0x10,
-0x28,0x82,0x00,0x02,0x14,0x40,0x00,0x27,0x00,0x00,0x00,0x00,0x24,0x02,0x00,0x02,
-0x10,0x82,0x00,0x17,0x00,0xa0,0x30,0x21,0x24,0x02,0x00,0x03,0x10,0x82,0x00,0x05,
-0x24,0x04,0x08,0x3c,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x18,0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x3c,
-0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x3c,
-0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,0x24,0x04,0x08,0xac,
-0x0c,0x00,0x13,0x3d,0x24,0x05,0x0f,0xff,0x08,0x00,0x26,0x15,0x00,0x00,0x00,0x00,
-0x24,0x04,0x08,0x34,0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x34,
-0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x34,
-0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,0x08,0x00,0x26,0x24,
-0x24,0x04,0x08,0xa8,0x14,0x80,0xff,0xdf,0x00,0xa0,0x30,0x21,0x24,0x04,0x08,0x24,
-0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,0x24,0x04,0x08,0x24,0x3c,0x05,0x80,0x00,
-0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,0x24,0x04,0x08,0x24,0x3c,0x05,0x80,0x00,
-0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,0x08,0x00,0x26,0x24,0x24,0x04,0x08,0xa0,
-0x00,0xa0,0x30,0x21,0x24,0x04,0x08,0x2c,0x0c,0x00,0x13,0x5b,0x3c,0x05,0x3f,0x00,
-0x24,0x04,0x08,0x2c,0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x00,0x00,0x30,0x21,
-0x24,0x04,0x08,0x2c,0x3c,0x05,0x80,0x00,0x0c,0x00,0x13,0x5b,0x24,0x06,0x00,0x01,
-0x08,0x00,0x26,0x24,0x24,0x04,0x08,0xa4,0x3c,0x05,0x00,0x14,0x3c,0x02,0xb0,0x05,
-0x34,0x42,0x04,0x20,0x3c,0x06,0xc0,0x00,0x3c,0x03,0xb0,0x05,0x3c,0x04,0xb0,0x05,
-0x34,0xa5,0x17,0x09,0xac,0x45,0x00,0x00,0x34,0xc6,0x05,0x07,0x34,0x63,0x04,0x24,
-0x34,0x84,0x02,0x28,0x3c,0x07,0xb0,0x05,0x24,0x02,0x00,0x20,0xac,0x66,0x00,0x00,
-0x34,0xe7,0x04,0x50,0xa0,0x82,0x00,0x00,0x90,0xe2,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x42,0x00,0x03,0x10,0x40,0xff,0xfc,0x24,0x02,0x00,0x01,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x93,0x85,0x81,0xf1,0x24,0x02,0x00,0x01,0x14,0xa2,0x00,0x51,
-0x00,0x80,0x40,0x21,0x8c,0x89,0x00,0x04,0x3c,0x03,0xb0,0x01,0x01,0x23,0x30,0x21,
-0x8c,0xc2,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x08,0x10,0x45,0x00,0x59,
-0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x38,0x24,0x03,0x00,0xb4,0x30,0x44,0x00,0xff,
-0x10,0x83,0x00,0x61,0x24,0x02,0x00,0xc4,0x10,0x82,0x00,0x54,0x24,0x02,0x00,0x94,
-0x10,0x82,0x00,0x45,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x38,0x00,0x00,0x00,0x00,
-0x30,0x47,0xff,0xff,0x30,0xe3,0x40,0xff,0x24,0x02,0x40,0x88,0x14,0x62,0x00,0x39,
-0x30,0xe3,0x03,0x00,0x24,0x02,0x03,0x00,0x10,0x62,0x00,0x38,0x00,0x00,0x00,0x00,
-0x94,0xc2,0x00,0x56,0x00,0x00,0x00,0x00,0x30,0x47,0xff,0xff,0x30,0xe2,0x00,0x80,
-0x14,0x40,0x00,0x30,0x3c,0x02,0xb0,0x01,0x01,0x22,0x30,0x21,0x94,0xc3,0x00,0x60,
-0x24,0x02,0x00,0x08,0x14,0x43,0x00,0x3b,0x00,0x00,0x00,0x00,0x90,0xc2,0x00,0x62,
-0x24,0x03,0x00,0x04,0x00,0x02,0x39,0x02,0x10,0xe3,0x00,0x15,0x24,0x02,0x00,0x06,
-0x14,0xe2,0x00,0x34,0x00,0x00,0x00,0x00,0x8d,0x05,0x01,0xac,0x94,0xc4,0x00,0x66,
-0x27,0x82,0x89,0x58,0x00,0x05,0x28,0x80,0x30,0x87,0xff,0xff,0x00,0xa2,0x28,0x21,
-0x00,0x07,0x1a,0x00,0x8c,0xa4,0x00,0x00,0x00,0x07,0x12,0x02,0x00,0x43,0x10,0x25,
-0x24,0x42,0x00,0x5e,0x24,0x03,0xc0,0x00,0x30,0x47,0xff,0xff,0x00,0x83,0x20,0x24,
-0x00,0x87,0x20,0x25,0xac,0xa4,0x00,0x00,0x08,0x00,0x26,0xcd,0xad,0x07,0x00,0x10,
-0x8d,0x05,0x01,0xac,0x94,0xc4,0x00,0x64,0x27,0x82,0x89,0x58,0x00,0x05,0x28,0x80,
-0x30,0x87,0xff,0xff,0x00,0xa2,0x28,0x21,0x00,0x07,0x1a,0x00,0x8c,0xa4,0x00,0x00,
-0x00,0x07,0x12,0x02,0x00,0x43,0x10,0x25,0x24,0x42,0x00,0x36,0x3c,0x03,0xff,0xff,
-0x30,0x47,0xff,0xff,0x00,0x83,0x20,0x24,0x00,0x87,0x20,0x25,0xac,0xa4,0x00,0x00,
-0xad,0x07,0x00,0x10,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x94,0xc2,0x00,0x50,
-0x08,0x00,0x26,0x8b,0x30,0x47,0xff,0xff,0x8d,0x04,0x01,0xac,0x27,0x83,0x89,0x58,
-0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00,0x3c,0x03,0xff,0xff,
-0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x2e,0xac,0x82,0x00,0x00,0x24,0x03,0x00,0x2e,
-0xad,0x03,0x00,0x10,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8d,0x04,0x01,0xac,
-0x27,0x83,0x89,0x58,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00,
-0x3c,0x03,0xff,0xff,0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x0e,0x24,0x03,0x00,0x0e,
-0x08,0x00,0x26,0xcc,0xac,0x82,0x00,0x00,0x8d,0x04,0x01,0xac,0x27,0x83,0x89,0x58,
-0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x8c,0x82,0x00,0x00,0x3c,0x03,0xff,0xff,
-0x00,0x43,0x10,0x24,0x34,0x42,0x00,0x14,0x24,0x03,0x00,0x14,0x08,0x00,0x26,0xcc,
-0xac,0x82,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0xc6,0x00,0xff,
-0x00,0x06,0x48,0x40,0x01,0x26,0x10,0x21,0x00,0x02,0x10,0x80,0x27,0x8b,0xbc,0x20,
-0x27,0x83,0xbc,0x26,0x00,0x4b,0x40,0x21,0x00,0x43,0x10,0x21,0x94,0x47,0x00,0x00,
-0x30,0xa2,0x3f,0xff,0x10,0xe2,0x00,0x29,0x30,0x8a,0xff,0xff,0x95,0x02,0x00,0x02,
-0x24,0x03,0x00,0x01,0x00,0x02,0x11,0x82,0x30,0x42,0x00,0x01,0x10,0x43,0x00,0x18,
-0x00,0x00,0x00,0x00,0x01,0x26,0x10,0x21,0x00,0x02,0x10,0x80,0x00,0x4b,0x30,0x21,
-0x94,0xc4,0x00,0x02,0x27,0x83,0xbc,0x26,0x27,0x85,0xbc,0x24,0x00,0x45,0x28,0x21,
-0x30,0x84,0xff,0xdf,0x00,0x43,0x10,0x21,0xa4,0xc4,0x00,0x02,0xa4,0x40,0x00,0x00,
-0xa4,0xa0,0x00,0x00,0x94,0xc3,0x00,0x02,0x3c,0x04,0xb0,0x01,0x01,0x44,0x20,0x21,
-0x30,0x63,0xff,0xbf,0xa4,0xc3,0x00,0x02,0xa0,0xc0,0x00,0x00,0x8c,0x82,0x00,0x04,
-0x24,0x03,0xf0,0xff,0x00,0x43,0x10,0x24,0x03,0xe0,0x00,0x08,0xac,0x82,0x00,0x04,
-0x24,0x02,0xc0,0x00,0x91,0x04,0x00,0x01,0x00,0xa2,0x10,0x24,0x00,0x47,0x28,0x25,
-0x3c,0x03,0xb0,0x01,0x24,0x02,0x00,0x02,0x14,0x82,0xff,0xe2,0x01,0x43,0x18,0x21,
-0xac,0x65,0x00,0x00,0x08,0x00,0x26,0xfa,0x01,0x26,0x10,0x21,0x08,0x00,0x26,0xfa,
-0x01,0x26,0x10,0x21,0x93,0x83,0x81,0xf1,0x24,0x02,0x00,0x01,0x14,0x62,0x00,0x0d,
-0x3c,0x02,0xb0,0x01,0x8c,0x84,0x00,0x04,0x3c,0x06,0xb0,0x09,0x00,0x82,0x20,0x21,
-0x8c,0x85,0x00,0x08,0x8c,0x83,0x00,0x04,0x3c,0x02,0x01,0x00,0x34,0xc6,0x01,0x00,
-0x00,0x62,0x18,0x24,0x14,0x60,0x00,0x05,0x30,0xa5,0x20,0x00,0x24,0x02,0x00,0x06,
-0xa0,0xc2,0x00,0x00,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x09,
-0x10,0xa0,0xff,0xfc,0x34,0x63,0x01,0x00,0x24,0x02,0x00,0x0e,0x08,0x00,0x27,0x2d,
-0xa0,0x62,0x00,0x00,0x3c,0x02,0xb0,0x01,0x30,0xa5,0xff,0xff,0x00,0xa2,0x28,0x21,
-0x8c,0xa3,0x00,0x00,0x3c,0x02,0x10,0x00,0x00,0x80,0x30,0x21,0x00,0x62,0x18,0x24,
-0x8c,0xa2,0x00,0x04,0x10,0x60,0x00,0x04,0x00,0x00,0x00,0x00,0x30,0x42,0x80,0x00,
-0x10,0x40,0x00,0x13,0x00,0x00,0x00,0x00,0x8c,0xc2,0x01,0xa8,0x00,0x00,0x00,0x00,
-0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a,
-0x93,0x83,0x81,0xf0,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,
-0x24,0x63,0xff,0xff,0xac,0xc4,0x01,0xa8,0xa3,0x83,0x81,0xf0,0x8c,0xc4,0x01,0xac,
-0x8c,0xc2,0x01,0xa8,0x00,0x00,0x00,0x00,0x00,0x44,0x10,0x26,0x00,0x02,0x10,0x2b,
-0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x3c,0x03,0xb0,0x03,0x34,0x63,0x00,0x73,
-0x90,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x42,0x00,0x01,0x14,0x40,0x00,0x04,
-0x00,0x00,0x00,0x00,0xa3,0x80,0x81,0xf1,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0xa3,0x82,0x81,0xf1,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xa8,0x8c,0x43,0x00,0x00,0x00,0x00,0x00,0x00,
-0x30,0x62,0x00,0xff,0x00,0x03,0x2e,0x02,0x00,0x02,0x39,0x80,0x2c,0xa2,0x00,0x02,
-0x00,0x03,0x34,0x02,0x10,0x40,0x00,0x05,0x00,0x03,0x1a,0x02,0xa4,0x87,0x01,0xd8,
-0xa0,0x85,0x01,0xd4,0xa0,0x86,0x01,0xd5,0xa0,0x83,0x01,0xd6,0x03,0xe0,0x00,0x08,
-0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x04,0x3c,0x05,0xb0,0x01,0x00,0x80,0x50,0x21,
-0x00,0x45,0x10,0x21,0x8c,0x43,0x00,0x04,0x24,0x02,0x00,0x05,0x00,0x03,0x1a,0x02,
-0x30,0x69,0x00,0x0f,0x11,0x22,0x00,0x0b,0x24,0x02,0x00,0x07,0x11,0x22,0x00,0x09,
-0x24,0x02,0x00,0x0a,0x11,0x22,0x00,0x07,0x24,0x02,0x00,0x0b,0x11,0x22,0x00,0x05,
-0x24,0x02,0x00,0x01,0x93,0x83,0x81,0xf0,0x3c,0x04,0xb0,0x06,0x10,0x62,0x00,0x03,
-0x34,0x84,0x80,0x18,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,0x8c,0x82,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x14,0x40,0xff,0xfa,0x00,0x00,0x00,0x00,
-0x8d,0x43,0x01,0xa8,0x27,0x82,0x89,0x58,0x00,0x03,0x18,0x80,0x00,0x6a,0x20,0x21,
-0x8c,0x87,0x00,0xa8,0x00,0x62,0x18,0x21,0x8c,0x68,0x00,0x00,0x00,0xe5,0x28,0x21,
-0x8c,0xa9,0x00,0x00,0x3c,0x02,0xff,0xff,0x27,0x83,0x8a,0x58,0x01,0x22,0x10,0x24,
-0x00,0x48,0x10,0x25,0xac,0xa2,0x00,0x00,0x8d,0x44,0x01,0xa8,0x00,0x07,0x30,0xc2,
-0x3c,0x02,0x00,0x80,0x00,0x04,0x20,0x80,0x00,0x83,0x20,0x21,0x00,0x06,0x32,0x00,
-0x8c,0xa9,0x00,0x04,0x00,0xc2,0x30,0x25,0x8c,0x82,0x00,0x00,0x3c,0x03,0x80,0x00,
-0x01,0x22,0x10,0x25,0x00,0x43,0x10,0x25,0xac,0xa2,0x00,0x04,0xaf,0x87,0xbc,0x10,
-0x8c,0xa2,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x82,0xbc,0x18,0x8c,0xa3,0x00,0x04,
-0x3c,0x01,0xb0,0x07,0xac,0x26,0x80,0x18,0x8d,0x42,0x01,0xa8,0xaf,0x83,0xbc,0x14,
-0x93,0x85,0x81,0xf0,0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,
-0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x24,0xa5,0xff,0xff,
-0x00,0x82,0x20,0x23,0xad,0x44,0x01,0xa8,0xa3,0x85,0x81,0xf0,0x08,0x00,0x27,0x89,
-0x00,0x00,0x00,0x00,0x3c,0x05,0xb0,0x03,0x3c,0x02,0x80,0x01,0x24,0x42,0x9f,0x04,
-0x34,0xa5,0x00,0x20,0xac,0xa2,0x00,0x00,0x24,0x02,0x00,0x02,0x24,0x03,0x00,0x20,
-0xac,0x82,0x00,0x64,0x3c,0x02,0x80,0x01,0xac,0x83,0x00,0x60,0x00,0x80,0x38,0x21,
-0xac,0x80,0x00,0x00,0xac,0x80,0x00,0x04,0xac,0x80,0x00,0x08,0xac,0x80,0x00,0x4c,
-0xac,0x80,0x00,0x50,0xac,0x80,0x00,0x54,0xac,0x80,0x00,0x0c,0xac,0x80,0x00,0x58,
-0xa0,0x80,0x00,0x5c,0x24,0x83,0x00,0x68,0x24,0x42,0xa0,0x14,0x24,0x04,0x00,0x0f,
-0x24,0x84,0xff,0xff,0xac,0x62,0x00,0x00,0x04,0x81,0xff,0xfd,0x24,0x63,0x00,0x04,
-0x3c,0x02,0xb0,0x03,0x34,0x42,0x00,0xa8,0xac,0xe0,0x01,0xa8,0xac,0xe0,0x01,0xac,
-0xac,0xe0,0x01,0xb0,0xac,0xe0,0x01,0xb4,0xa0,0xe0,0x01,0xb8,0xa0,0xe0,0x01,0xb9,
-0xa0,0xe0,0x01,0xba,0xa0,0xe0,0x01,0xc0,0xa0,0xe0,0x01,0xc1,0xac,0xe0,0x01,0xc4,
-0xac,0xe0,0x01,0xc8,0xac,0xe0,0x01,0xcc,0xac,0xe0,0x01,0xd0,0x8c,0x44,0x00,0x00,
-0x3c,0x02,0x80,0x01,0x24,0x42,0xa0,0xfc,0x30,0x83,0x00,0xff,0x00,0x03,0x19,0x80,
-0xa4,0xe3,0x01,0xd8,0xac,0xe2,0x00,0x78,0x3c,0x03,0x80,0x01,0x3c,0x02,0x80,0x01,
-0x24,0x63,0xa2,0x88,0x24,0x42,0xa1,0xf4,0xac,0xe3,0x00,0x88,0xac,0xe2,0x00,0x98,
-0x3c,0x03,0x80,0x01,0x3c,0x02,0x80,0x01,0x00,0x04,0x2e,0x03,0x00,0x04,0x34,0x03,
-0x24,0x63,0xa3,0x30,0x00,0x04,0x22,0x03,0x24,0x42,0xa4,0x74,0xac,0xe3,0x00,0xa0,
-0xac,0xe2,0x00,0xa4,0xa0,0xe5,0x01,0xd4,0xa0,0xe6,0x01,0xd5,0x03,0xe0,0x00,0x08,
-0xa0,0xe4,0x01,0xd6,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01,0x34,0x63,0x00,0x20,
-0x24,0x42,0xa0,0x14,0x03,0xe0,0x00,0x08,0xac,0x62,0x00,0x00,0x3c,0x02,0xb0,0x03,
-0x3c,0x03,0x80,0x01,0x34,0x42,0x00,0x20,0x24,0x63,0xa0,0x2c,0xac,0x43,0x00,0x00,
-0x8c,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x11,0x00,0x80,0x28,0x21,
-0x8c,0x82,0x00,0x14,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0d,0x00,0x00,0x00,0x00,
-0x8c,0x84,0x00,0x10,0x8c,0xa3,0x00,0x14,0x8c,0xa2,0x00,0x04,0x00,0x83,0x20,0x21,
-0x00,0x44,0x10,0x21,0x30,0x43,0x00,0xff,0x00,0x03,0x18,0x2b,0x00,0x02,0x12,0x02,
-0x00,0x43,0x10,0x21,0x00,0x02,0x12,0x00,0x30,0x42,0x3f,0xff,0xac,0xa2,0x00,0x04,
-0xac,0xa0,0x00,0x00,0xac,0xa0,0x00,0x4c,0xac,0xa0,0x00,0x50,0xac,0xa0,0x00,0x54,
-0x03,0xe0,0x00,0x08,0xac,0xa0,0x00,0x0c,0x3c,0x03,0xb0,0x03,0x3c,0x02,0x80,0x01,
-0x34,0x63,0x00,0x20,0x24,0x42,0xa0,0xa8,0xac,0x62,0x00,0x00,0x8c,0x86,0x00,0x04,
-0x3c,0x02,0xb0,0x01,0x24,0x03,0x00,0x01,0x00,0xc2,0x10,0x21,0x8c,0x45,0x00,0x00,
-0xac,0x83,0x00,0x4c,0x00,0x05,0x14,0x02,0x30,0xa3,0x3f,0xff,0x30,0x42,0x00,0xff,
-0xac,0x83,0x00,0x10,0xac,0x82,0x00,0x14,0x8c,0x83,0x00,0x14,0xac,0x85,0x00,0x40,
-0x00,0xc3,0x30,0x21,0x03,0xe0,0x00,0x08,0xac,0x86,0x00,0x08,0x3c,0x02,0xb0,0x03,
-0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa0,0xfc,
-0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x4c,
-0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x0a,0x00,0x80,0x80,0x21,0xae,0x00,0x00,0x00,
-0xae,0x00,0x00,0x4c,0xae,0x00,0x00,0x50,0xae,0x00,0x00,0x54,0xae,0x00,0x00,0x0c,
-0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,
-0x0c,0x00,0x28,0x2a,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x4c,0xae,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,
-0x24,0x63,0xa1,0x60,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,
-0x8c,0x82,0x00,0x4c,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x16,0x00,0x80,0x80,0x21,
-0x8e,0x03,0x00,0x08,0x3c,0x02,0xb0,0x01,0x8e,0x04,0x00,0x44,0x00,0x62,0x18,0x21,
-0x90,0x65,0x00,0x00,0x24,0x02,0x00,0x01,0xae,0x02,0x00,0x50,0x30,0xa3,0x00,0xff,
-0x00,0x03,0x10,0x82,0x00,0x04,0x23,0x02,0x30,0x84,0x00,0x0f,0x30,0x42,0x00,0x03,
-0x00,0x03,0x19,0x02,0xae,0x04,0x00,0x34,0xae,0x02,0x00,0x2c,0xae,0x03,0x00,0x30,
-0xa2,0x05,0x00,0x48,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0x2a,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0x64,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,
-0x34,0x42,0x00,0x20,0x24,0x63,0xa1,0xf4,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,
-0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x50,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x16,
-0x00,0x80,0x80,0x21,0x92,0x03,0x00,0x44,0x8e,0x02,0x00,0x40,0x83,0x85,0x8b,0xc4,
-0x92,0x04,0x00,0x41,0x30,0x63,0x00,0x01,0x00,0x02,0x16,0x02,0xae,0x04,0x00,0x14,
-0x00,0x00,0x30,0x21,0xae,0x02,0x00,0x18,0x10,0xa0,0x00,0x04,0xae,0x03,0x00,0x3c,
-0x10,0x60,0x00,0x03,0x24,0x02,0x00,0x01,0x24,0x06,0x00,0x01,0x24,0x02,0x00,0x01,
-0xa3,0x86,0x8b,0xc4,0x8f,0xbf,0x00,0x14,0xae,0x02,0x00,0x54,0x8f,0xb0,0x00,0x10,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0x58,0x00,0x00,0x00,0x00,
-0x08,0x00,0x28,0x89,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,
-0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xa2,0x88,0xaf,0xb0,0x00,0x10,
-0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x50,0x00,0x00,0x00,0x00,
-0x10,0x40,0x00,0x1b,0x00,0x80,0x80,0x21,0x3c,0x02,0xb0,0x03,0x8c,0x42,0x00,0x00,
-0x92,0x04,0x00,0x44,0x8e,0x03,0x00,0x40,0x83,0x86,0x8b,0xc4,0x92,0x05,0x00,0x41,
-0x30,0x42,0x08,0x00,0x30,0x84,0x00,0x01,0x00,0x02,0x12,0xc2,0x00,0x03,0x1e,0x02,
-0x00,0x82,0x20,0x25,0xae,0x05,0x00,0x14,0x00,0x00,0x38,0x21,0xae,0x03,0x00,0x18,
-0x10,0xc0,0x00,0x04,0xae,0x04,0x00,0x3c,0x10,0x80,0x00,0x03,0x24,0x02,0x00,0x01,
-0x24,0x07,0x00,0x01,0x24,0x02,0x00,0x01,0xa3,0x87,0x8b,0xc4,0x8f,0xbf,0x00,0x14,
-0xae,0x02,0x00,0x54,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,
-0x0c,0x00,0x28,0x58,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0xae,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,
-0x24,0x63,0xa3,0x30,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,
-0x8c,0x82,0x00,0x54,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x42,0x00,0x80,0x80,0x21,
-0x8e,0x04,0x00,0x04,0x8e,0x03,0x00,0x44,0x3c,0x02,0x80,0x00,0x3c,0x08,0xb0,0x01,
-0x34,0x42,0x00,0x10,0x00,0x88,0x20,0x21,0x00,0x62,0x18,0x25,0xac,0x83,0x00,0x04,
-0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x89,0x89,0x58,0x00,0x48,0x10,0x21,
-0x8c,0x45,0x00,0x00,0x00,0x03,0x18,0x80,0x00,0x69,0x18,0x21,0xac,0x65,0x00,0x00,
-0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x87,0x8a,0x58,0x00,0x48,0x10,0x21,
-0x8c,0x45,0x00,0x04,0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,0xac,0x65,0x00,0x00,
-0x8e,0x02,0x01,0xac,0x8e,0x06,0x00,0x04,0x02,0x00,0x20,0x21,0x00,0x02,0x10,0x80,
-0x00,0x47,0x38,0x21,0x94,0xe3,0x00,0x02,0x00,0x49,0x10,0x21,0x90,0x45,0x00,0x00,
-0x00,0x03,0x1a,0x00,0x00,0xc8,0x30,0x21,0x00,0xa3,0x28,0x25,0x0c,0x00,0x26,0x69,
-0xa4,0xc5,0x00,0x2e,0x8e,0x03,0x01,0xac,0x8e,0x07,0x00,0x04,0x3c,0x06,0xb0,0x03,
-0x24,0x65,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0x62,0x00,0x40,0x00,0xa4,0x10,0x0a,
-0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x03,0x18,0x80,0x00,0xa2,0x28,0x23,
-0x00,0x70,0x18,0x21,0xae,0x05,0x01,0xac,0xac,0x67,0x00,0xa8,0x34,0xc6,0x00,0x30,
-0x8c,0xc3,0x00,0x00,0x93,0x82,0x81,0xf0,0x02,0x00,0x20,0x21,0x24,0x63,0x00,0x01,
-0x24,0x42,0x00,0x01,0xac,0xc3,0x00,0x00,0xa3,0x82,0x81,0xf0,0x0c,0x00,0x28,0x0b,
-0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0xa2,0x00,0x00,0x00,0x00,0x08,0x00,0x28,0xd8,
-0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,0x27,0xbd,0xff,0xe8,
-0x34,0x42,0x00,0x20,0x24,0x63,0xa4,0x74,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x14,
-0xac,0x43,0x00,0x00,0x8c,0x82,0x00,0x54,0x00,0x00,0x00,0x00,0x10,0x40,0x00,0x42,
-0x00,0x80,0x80,0x21,0x8e,0x04,0x00,0x04,0x8e,0x03,0x00,0x44,0x3c,0x02,0x80,0x00,
-0x3c,0x08,0xb0,0x01,0x34,0x42,0x00,0x10,0x00,0x88,0x20,0x21,0x00,0x62,0x18,0x25,
-0xac,0x83,0x00,0x04,0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x89,0x89,0x58,
-0x00,0x48,0x10,0x21,0x8c,0x45,0x00,0x00,0x00,0x03,0x18,0x80,0x00,0x69,0x18,0x21,
-0xac,0x65,0x00,0x00,0x8e,0x02,0x00,0x04,0x8e,0x03,0x01,0xac,0x27,0x87,0x8a,0x58,
-0x00,0x48,0x10,0x21,0x8c,0x45,0x00,0x04,0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,
-0xac,0x65,0x00,0x00,0x8e,0x02,0x01,0xac,0x8e,0x06,0x00,0x04,0x02,0x00,0x20,0x21,
-0x00,0x02,0x10,0x80,0x00,0x47,0x38,0x21,0x94,0xe3,0x00,0x02,0x00,0x49,0x10,0x21,
-0x90,0x45,0x00,0x00,0x00,0x03,0x1a,0x00,0x00,0xc8,0x30,0x21,0x00,0xa3,0x28,0x25,
-0x0c,0x00,0x26,0x69,0xa4,0xc5,0x00,0x2e,0x8e,0x03,0x01,0xac,0x8e,0x07,0x00,0x04,
-0x3c,0x06,0xb0,0x03,0x24,0x65,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0x62,0x00,0x40,
-0x00,0xa4,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x03,0x18,0x80,
-0x00,0xa2,0x28,0x23,0x00,0x70,0x18,0x21,0xae,0x05,0x01,0xac,0xac,0x67,0x00,0xa8,
-0x34,0xc6,0x00,0x30,0x8c,0xc3,0x00,0x00,0x93,0x82,0x81,0xf0,0x02,0x00,0x20,0x21,
-0x24,0x63,0x00,0x01,0x24,0x42,0x00,0x01,0xac,0xc3,0x00,0x00,0xa3,0x82,0x81,0xf0,
-0x0c,0x00,0x28,0x0b,0x00,0x00,0x00,0x00,0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x0c,0x00,0x28,0xa2,0x00,0x00,0x00,0x00,
-0x08,0x00,0x29,0x29,0x00,0x00,0x00,0x00,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,
-0x27,0xbd,0xff,0xd8,0x34,0x42,0x00,0x20,0x24,0x63,0xa5,0xb8,0xaf,0xb2,0x00,0x18,
-0xac,0x43,0x00,0x00,0x3c,0x12,0xb0,0x03,0x3c,0x02,0x80,0x01,0xaf,0xb4,0x00,0x20,
-0xaf,0xb3,0x00,0x1c,0xaf,0xb1,0x00,0x14,0xaf,0xb0,0x00,0x10,0xaf,0xbf,0x00,0x24,
-0x00,0x80,0x80,0x21,0x24,0x54,0xa0,0x14,0x00,0x00,0x88,0x21,0x3c,0x13,0xb0,0x01,
-0x36,0x52,0x00,0xef,0x3c,0x02,0xb0,0x09,0x34,0x42,0x00,0x06,0x90,0x43,0x00,0x00,
-0x8e,0x04,0x00,0x04,0x92,0x02,0x01,0xbb,0x30,0x69,0x00,0xff,0x00,0x04,0x42,0x02,
-0x10,0x40,0x00,0x1e,0x00,0x00,0x38,0x21,0x8e,0x03,0x01,0xa8,0x3c,0x06,0x28,0x38,
-0x34,0xc6,0x00,0x20,0x24,0x64,0x00,0x3d,0x28,0x82,0x00,0x00,0x24,0x63,0x00,0x7c,
-0x00,0x82,0x18,0x0a,0x00,0x03,0x19,0x83,0x00,0x03,0x19,0x80,0x00,0x83,0x20,0x23,
-0x00,0x04,0x10,0x80,0x00,0x50,0x10,0x21,0x8c,0x45,0x00,0xa8,0xae,0x04,0x01,0xac,
-0xae,0x04,0x01,0xa8,0x00,0xb3,0x18,0x21,0xae,0x05,0x00,0x04,0xac,0x66,0x00,0x00,
-0x8e,0x02,0x00,0x04,0x3c,0x03,0x80,0x00,0x34,0x63,0x4e,0x00,0x00,0x53,0x10,0x21,
-0xac,0x43,0x00,0x04,0xa2,0x00,0x01,0xbb,0x93,0x83,0x81,0xf7,0x00,0x00,0x00,0x00,
-0x24,0x62,0x00,0x01,0xa3,0x82,0x81,0xf7,0xa2,0x43,0x00,0x00,0x01,0x28,0x10,0x23,
-0x24,0x44,0x00,0x40,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x7f,0x00,0x83,0x10,0x0a,
-0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x24,0x84,0xff,0xff,0x10,0x44,0x00,0x6b,
-0x3c,0x02,0xb0,0x01,0x8e,0x03,0x00,0x04,0x3c,0x04,0x7c,0x00,0x00,0x62,0x18,0x21,
-0x8c,0x65,0x00,0x04,0x34,0x84,0x00,0xf0,0x00,0x00,0x30,0x21,0xae,0x05,0x00,0x44,
-0x00,0xa4,0x20,0x24,0x8c,0x63,0x00,0x00,0x10,0x80,0x00,0x6b,0x3c,0x02,0xff,0xff,
-0x3c,0x09,0xb0,0x03,0x3c,0x05,0x7c,0x00,0x35,0x29,0x00,0x99,0x3c,0x0a,0xb0,0x01,
-0x24,0x08,0x00,0x40,0x34,0xa5,0x00,0xf0,0x3c,0x0b,0xff,0xff,0x3c,0x0c,0x28,0x38,
-0x16,0x20,0x00,0x06,0x24,0xe7,0x00,0x01,0x93,0x82,0x81,0xf6,0x24,0x11,0x00,0x01,
-0x24,0x42,0x00,0x01,0xa1,0x22,0x00,0x00,0xa3,0x82,0x81,0xf6,0x8e,0x02,0x00,0x04,
-0x24,0x06,0x00,0x01,0x24,0x42,0x01,0x00,0x30,0x42,0x3f,0xff,0xae,0x02,0x00,0x04,
-0x00,0x4a,0x10,0x21,0x8c,0x43,0x00,0x04,0x00,0x00,0x00,0x00,0xae,0x03,0x00,0x44,
-0x00,0x65,0x20,0x24,0x8c,0x43,0x00,0x00,0x10,0xe8,0x00,0x2d,0x00,0x00,0x00,0x00,
-0x14,0x80,0xff,0xeb,0x00,0x6b,0x10,0x24,0x14,0x4c,0xff,0xe9,0x24,0x02,0x00,0x01,
-0x10,0xc2,0x00,0x30,0x3c,0x03,0xb0,0x09,0x8e,0x02,0x00,0x44,0x8e,0x04,0x00,0x60,
-0x00,0x02,0x1e,0x42,0x00,0x02,0x12,0x02,0x30,0x42,0x00,0x0f,0x30,0x63,0x00,0x01,
-0xae,0x02,0x00,0x00,0x10,0x44,0x00,0x1a,0xae,0x03,0x00,0x58,0x8e,0x02,0x00,0x64,
-0x8e,0x04,0x00,0x58,0x00,0x00,0x00,0x00,0x10,0x82,0x00,0x05,0x00,0x00,0x00,0x00,
-0xae,0x00,0x00,0x4c,0xae,0x00,0x00,0x50,0xae,0x00,0x00,0x54,0xae,0x00,0x00,0x0c,
-0x8e,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x10,0x80,0x00,0x50,0x10,0x21,
-0x8c,0x42,0x00,0x68,0x00,0x00,0x00,0x00,0x10,0x54,0x00,0x06,0x00,0x00,0x00,0x00,
-0x00,0x40,0xf8,0x09,0x02,0x00,0x20,0x21,0x8e,0x04,0x00,0x58,0x8e,0x03,0x00,0x00,
-0x00,0x00,0x00,0x00,0xae,0x03,0x00,0x60,0x08,0x00,0x29,0x81,0xae,0x04,0x00,0x64,
-0x8e,0x02,0x00,0x64,0x00,0x00,0x00,0x00,0x14,0x62,0xff,0xe5,0x00,0x00,0x00,0x00,
-0x7a,0x02,0x0d,0x7c,0x8f,0xbf,0x00,0x24,0x8f,0xb4,0x00,0x20,0x7b,0xb2,0x00,0xfc,
-0x7b,0xb0,0x00,0xbc,0x00,0x43,0x10,0x26,0x00,0x02,0x10,0x2b,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x28,0x8e,0x04,0x00,0x04,0x34,0x63,0x00,0x06,0x90,0x62,0x00,0x00,
-0x00,0x04,0x42,0x02,0x00,0x48,0x10,0x23,0x24,0x44,0x00,0x40,0x28,0x83,0x00,0x00,
-0x24,0x42,0x00,0x7f,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,
-0x00,0x82,0x20,0x23,0x14,0x86,0xff,0xc4,0x00,0x00,0x00,0x00,0x8e,0x03,0x00,0x00,
-0x00,0x00,0x00,0x00,0x2c,0x62,0x00,0x03,0x14,0x40,0x00,0x05,0x24,0x02,0x00,0x0d,
-0x10,0x62,0x00,0x03,0x24,0x02,0x00,0x01,0x08,0x00,0x2a,0x04,0xa2,0x02,0x00,0x5c,
-0x08,0x00,0x2a,0x04,0xa2,0x00,0x00,0x5c,0x00,0x62,0x10,0x24,0x3c,0x03,0x28,0x38,
-0x14,0x43,0xff,0x93,0x24,0x02,0x00,0x01,0x08,0x00,0x29,0xdc,0x00,0x00,0x00,0x00,
-0x3c,0x02,0xb0,0x01,0x00,0xa2,0x40,0x21,0x00,0xa0,0x48,0x21,0x8d,0x05,0x00,0x00,
-0x24,0x02,0xc0,0x00,0x00,0x09,0x38,0xc2,0x00,0xa2,0x28,0x24,0x24,0xc2,0xff,0xff,
-0x00,0x07,0x3a,0x00,0x3c,0x0a,0xb0,0x06,0x3c,0x03,0x00,0x80,0x00,0xa6,0x28,0x25,
-0x2c,0x42,0x1f,0xff,0x00,0xe3,0x38,0x25,0x35,0x4a,0x80,0x18,0x10,0x40,0x00,0x0e,
-0xad,0x05,0x00,0x00,0xaf,0x89,0xbc,0x10,0x8d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,
-0xaf,0x82,0xbc,0x18,0x8d,0x03,0x00,0x04,0xad,0x47,0x00,0x00,0xaf,0x83,0xbc,0x14,
-0xac,0x80,0x01,0xd0,0xac,0x80,0x01,0xc4,0xa0,0x80,0x01,0xc0,0xa0,0x80,0x01,0xc1,
-0xac,0x80,0x01,0xc8,0xac,0x80,0x01,0xcc,0x03,0xe0,0x00,0x08,0x00,0x00,0x00,0x00,
-0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x10,0x8c,0x83,0x01,0xc4,0x00,0x80,0x38,0x21,
-0x90,0x84,0x01,0xc0,0x00,0x03,0x18,0x80,0x00,0x67,0x18,0x21,0x8c,0x65,0x00,0xa8,
-0x3c,0x02,0xb0,0x01,0x24,0x03,0x00,0x01,0x00,0xa2,0x10,0x21,0x8c,0x42,0x00,0x00,
-0x10,0x83,0x00,0x18,0x00,0x02,0x14,0x02,0x8c,0xe9,0x01,0xcc,0x8c,0xea,0x01,0xc8,
-0x30,0x46,0x00,0xff,0x01,0x2a,0x18,0x21,0x30,0x64,0x00,0xff,0x00,0x03,0x1a,0x02,
-0x24,0x62,0x00,0x01,0x14,0x80,0x00,0x02,0x30,0x48,0x00,0xff,0x30,0x68,0x00,0xff,
-0x90,0xe2,0x01,0xc1,0x00,0x00,0x00,0x00,0x00,0x48,0x10,0x23,0x00,0x02,0x12,0x00,
-0x00,0x49,0x10,0x21,0x00,0x4a,0x10,0x21,0x00,0x46,0x30,0x23,0x0c,0x00,0x2a,0x2c,
-0x00,0xe0,0x20,0x21,0x8f,0xbf,0x00,0x10,0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x18,0x8c,0xe6,0x01,0xc8,0x08,0x00,0x2a,0x6b,0x00,0x00,0x00,0x00,
-0x27,0xbd,0xff,0xe8,0xaf,0xbf,0x00,0x14,0xaf,0xb0,0x00,0x10,0x8c,0x82,0x01,0xc4,
-0x90,0x87,0x01,0xc1,0x00,0x80,0x80,0x21,0x00,0x02,0x10,0x80,0x00,0x44,0x10,0x21,
-0x8c,0x48,0x00,0xa8,0x3c,0x02,0xb0,0x01,0x00,0x07,0x3a,0x00,0x01,0x02,0x10,0x21,
-0x8c,0x43,0x00,0x00,0x00,0xe5,0x38,0x21,0x00,0xe6,0x38,0x21,0x00,0x03,0x1c,0x02,
-0x30,0x63,0x00,0xff,0x00,0xe3,0x38,0x23,0x01,0x00,0x28,0x21,0x0c,0x00,0x2a,0x2c,
-0x00,0xe0,0x30,0x21,0x8e,0x02,0x01,0xa8,0x8f,0xbf,0x00,0x14,0x24,0x44,0x00,0x01,
-0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,
-0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,0xae,0x04,0x01,0xa8,0x8f,0xb0,0x00,0x10,
-0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x18,0x3c,0x02,0xb0,0x03,0x3c,0x03,0x80,0x01,
-0x27,0xbd,0xff,0xe8,0x34,0x42,0x00,0x20,0x24,0x63,0xaa,0x58,0xaf,0xb0,0x00,0x10,
-0xaf,0xbf,0x00,0x14,0xac,0x43,0x00,0x00,0x90,0x82,0x01,0xd4,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x6a,0x00,0x80,0x80,0x21,0x90,0x82,0x01,0xc0,0x00,0x00,0x00,0x00,
-0x14,0x40,0x00,0x61,0x00,0x00,0x00,0x00,0x8c,0x83,0x01,0xa8,0x8c,0x82,0x01,0xac,
-0x00,0x00,0x00,0x00,0x10,0x62,0x00,0x22,0x00,0x00,0x28,0x21,0x93,0x82,0x81,0xf1,
-0x00,0x03,0x30,0x80,0x00,0xc4,0x18,0x21,0x24,0x04,0x00,0x01,0x8c,0x67,0x00,0xa8,
-0x10,0x44,0x00,0x20,0x3c,0x04,0xb0,0x01,0xaf,0x87,0xbc,0x10,0x00,0xe4,0x20,0x21,
-0x8c,0x86,0x00,0x00,0x00,0x07,0x18,0xc2,0x3c,0x02,0x00,0x80,0xaf,0x86,0xbc,0x18,
-0x8c,0x86,0x00,0x04,0x00,0x03,0x1a,0x00,0x3c,0x05,0xb0,0x06,0x00,0x62,0x18,0x25,
-0x34,0xa5,0x80,0x18,0xac,0xa3,0x00,0x00,0x8e,0x02,0x01,0xa8,0x8e,0x09,0x01,0xac,
-0xaf,0x86,0xbc,0x14,0x24,0x44,0x00,0x01,0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,
-0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,
-0x00,0x80,0x30,0x21,0xae,0x04,0x01,0xa8,0x00,0xc9,0x10,0x26,0x00,0x02,0x28,0x2b,
-0x8f,0xbf,0x00,0x14,0x8f,0xb0,0x00,0x10,0x00,0xa0,0x10,0x21,0x03,0xe0,0x00,0x08,
-0x27,0xbd,0x00,0x18,0x93,0x82,0x81,0xf0,0x00,0x00,0x00,0x00,0x2c,0x42,0x00,0x02,
-0x14,0x40,0xff,0xf7,0x00,0x00,0x28,0x21,0x3c,0x05,0xb0,0x01,0x00,0xe5,0x28,0x21,
-0x27,0x83,0x89,0x58,0x00,0xc3,0x18,0x21,0x8c,0xa6,0x00,0x00,0x8c,0x64,0x00,0x00,
-0x24,0x02,0xc0,0x00,0x00,0xc2,0x10,0x24,0x00,0x44,0x10,0x25,0xac,0xa2,0x00,0x00,
-0x8e,0x03,0x01,0xa8,0x27,0x84,0x8a,0x58,0x8c,0xa6,0x00,0x04,0x00,0x03,0x18,0x80,
-0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0x00,0x3c,0x03,0x80,0x00,0x00,0x07,0x20,0xc2,
-0x00,0xc2,0x10,0x25,0x00,0x43,0x10,0x25,0xac,0xa2,0x00,0x04,0xaf,0x87,0xbc,0x10,
-0x8c,0xa6,0x00,0x00,0x3c,0x02,0x00,0x80,0x00,0x04,0x22,0x00,0x3c,0x03,0xb0,0x06,
-0xaf,0x86,0xbc,0x18,0x00,0x82,0x20,0x25,0x34,0x63,0x80,0x18,0x8c,0xa6,0x00,0x04,
-0xac,0x64,0x00,0x00,0x8e,0x02,0x01,0xa8,0xaf,0x86,0xbc,0x14,0x24,0x44,0x00,0x01,
-0x28,0x83,0x00,0x00,0x24,0x42,0x00,0x40,0x00,0x83,0x10,0x0a,0x93,0x83,0x81,0xf0,
-0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,0x00,0x82,0x20,0x23,0x24,0x63,0xff,0xff,
-0xae,0x04,0x01,0xa8,0xa3,0x83,0x81,0xf0,0x8e,0x04,0x01,0xac,0x8e,0x02,0x01,0xa8,
-0x08,0x00,0x2a,0xcb,0x00,0x44,0x10,0x26,0x0c,0x00,0x2a,0x4c,0x00,0x00,0x00,0x00,
-0x7a,0x02,0x0d,0x7c,0x08,0x00,0x2a,0xcb,0x00,0x43,0x10,0x26,0x8c,0x86,0x01,0xa8,
-0x8c,0x89,0x01,0xac,0x00,0x00,0x00,0x00,0x10,0xc9,0x00,0xb4,0x00,0xc0,0x68,0x21,
-0x00,0x06,0x10,0x80,0x27,0x83,0x89,0x58,0x00,0x43,0x18,0x21,0x00,0x44,0x10,0x21,
-0x8c,0x47,0x00,0xa8,0x94,0x65,0x00,0x02,0x3c,0x02,0xb0,0x01,0x00,0xe2,0x10,0x21,
-0x30,0xa5,0x3f,0xff,0xa4,0x45,0x00,0x2c,0x90,0x8a,0x01,0xc0,0x00,0x00,0x00,0x00,
-0x11,0x40,0x00,0x0c,0x00,0x07,0x32,0x02,0x8c,0x83,0x01,0xc4,0x90,0x85,0x01,0xc1,
-0x00,0x03,0x18,0x80,0x00,0x64,0x18,0x21,0x8c,0x62,0x00,0xa8,0x00,0x00,0x00,0x00,
-0x00,0x02,0x12,0x02,0x00,0x45,0x10,0x21,0x30,0x42,0x00,0x3f,0x14,0xc2,0xff,0xde,
-0x00,0x00,0x00,0x00,0x3c,0x04,0xb0,0x01,0x00,0xe4,0x40,0x21,0x8d,0x06,0x00,0x00,
-0x00,0x0d,0x28,0x80,0x00,0x06,0x14,0x02,0x30,0x4b,0x00,0xff,0x00,0xeb,0x70,0x21,
-0x01,0xc4,0x20,0x21,0x90,0x83,0x00,0x00,0x27,0x82,0x89,0x58,0x00,0xa2,0x28,0x21,
-0x8c,0xa4,0x00,0x00,0x00,0x03,0x18,0x82,0x30,0x63,0x00,0x03,0x2c,0x62,0x00,0x02,
-0x14,0x40,0x00,0x66,0x30,0x8c,0x3f,0xff,0x24,0x02,0x00,0x02,0x10,0x62,0x00,0x61,
-0x2d,0x82,0x08,0x00,0x15,0x40,0x00,0x36,0x01,0x6c,0x10,0x21,0x01,0x6c,0x18,0x21,
-0x30,0x62,0x00,0xff,0x00,0x02,0x10,0x2b,0x00,0x03,0x1a,0x02,0x3c,0x04,0xb0,0x01,
-0x00,0x62,0x18,0x21,0x00,0xe4,0x20,0x21,0x24,0x02,0x00,0x01,0xa2,0x03,0x01,0xc1,
-0xa0,0x82,0x00,0x08,0x8e,0x06,0x01,0xa8,0x3c,0x03,0xb0,0x00,0x34,0x63,0xff,0xf4,
-0x24,0xc5,0x00,0x01,0x28,0xa4,0x00,0x00,0x24,0xc2,0x00,0x40,0x00,0xa4,0x10,0x0a,
-0x01,0xc3,0x18,0x21,0xa4,0x6c,0x00,0x00,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,
-0x92,0x04,0x01,0xc0,0x00,0xa2,0x38,0x23,0x3c,0x03,0xb0,0x03,0xae,0x0b,0x01,0xcc,
-0xae,0x0c,0x01,0xc8,0xae,0x06,0x01,0xc4,0xae,0x07,0x01,0xa8,0x34,0x63,0x01,0x08,
-0x92,0x05,0x01,0xd6,0x8c,0x66,0x00,0x00,0x24,0x84,0x00,0x01,0x30,0x82,0x00,0xff,
-0x00,0x45,0x10,0x2b,0xae,0x06,0x01,0xd0,0x10,0x40,0x00,0x07,0xa2,0x04,0x01,0xc0,
-0x92,0x02,0x01,0xd5,0x92,0x03,0x01,0xc1,0x24,0x42,0xff,0xfc,0x00,0x62,0x18,0x2a,
-0x14,0x60,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x00,0x20,0x21,0x0c,0x00,0x2a,0x4c,
-0x00,0x00,0x00,0x00,0x8e,0x09,0x01,0xac,0x8e,0x06,0x01,0xa8,0x08,0x00,0x2a,0xcb,
-0x00,0xc9,0x10,0x26,0x8e,0x09,0x01,0xac,0x08,0x00,0x2a,0xca,0x00,0xe0,0x30,0x21,
-0x30,0x43,0x00,0xff,0x92,0x07,0x01,0xc1,0x00,0x02,0x12,0x02,0x30,0x44,0x00,0xff,
-0x38,0x63,0x00,0x00,0x24,0x46,0x00,0x01,0x92,0x05,0x01,0xd5,0x00,0x83,0x30,0x0a,
-0x00,0xc7,0x18,0x21,0x00,0xa3,0x10,0x2a,0x14,0x40,0xff,0xeb,0x00,0x00,0x00,0x00,
-0x24,0xa2,0xff,0xfc,0x00,0x62,0x10,0x2a,0x10,0x40,0x00,0x07,0x01,0x80,0x28,0x21,
-0x92,0x03,0x01,0xd6,0x25,0x42,0x00,0x01,0x00,0x43,0x10,0x2a,0x14,0x40,0x00,0x07,
-0x25,0xa4,0x00,0x01,0x01,0x80,0x28,0x21,0x01,0x60,0x30,0x21,0x0c,0x00,0x2a,0x74,
-0x02,0x00,0x20,0x21,0x08,0x00,0x2b,0x6d,0x00,0x00,0x00,0x00,0x28,0x83,0x00,0x00,
-0x25,0xa2,0x00,0x40,0x00,0x83,0x10,0x0a,0x00,0x02,0x11,0x83,0x00,0x02,0x11,0x80,
-0x00,0x82,0x20,0x23,0x00,0xc7,0x18,0x21,0x25,0x42,0x00,0x01,0x00,0x80,0x30,0x21,
-0xa2,0x03,0x01,0xc1,0xae,0x0b,0x01,0xcc,0xae,0x0c,0x01,0xc8,0x08,0x00,0x2a,0xc9,
-0xa2,0x02,0x01,0xc0,0x14,0x40,0xff,0x9f,0x00,0x00,0x00,0x00,0x15,0x40,0x00,0x14,
-0x24,0x02,0xc0,0x00,0x00,0xc2,0x10,0x24,0x00,0x4c,0x10,0x25,0xad,0x02,0x00,0x00,
-0xaf,0x87,0xbc,0x10,0x8d,0x05,0x00,0x00,0x00,0x07,0x18,0xc2,0x3c,0x02,0x00,0x80,
-0x00,0x03,0x1a,0x00,0x3c,0x04,0xb0,0x06,0xaf,0x85,0xbc,0x18,0x00,0x62,0x18,0x25,
-0x34,0x84,0x80,0x18,0x8d,0x05,0x00,0x04,0xac,0x83,0x00,0x00,0x8e,0x02,0x01,0xa8,
-0x8e,0x09,0x01,0xac,0xaf,0x85,0xbc,0x14,0x08,0x00,0x2a,0xc2,0x24,0x44,0x00,0x01,
-0x01,0x6c,0x10,0x21,0x30,0x45,0x00,0xff,0x92,0x04,0x01,0xc1,0x00,0x02,0x12,0x02,
-0x30,0x46,0x00,0xff,0x38,0xa5,0x00,0x00,0x24,0x42,0x00,0x01,0x92,0x03,0x01,0xd5,
-0x00,0xc5,0x10,0x0a,0x00,0x82,0x20,0x21,0x00,0x64,0x18,0x2a,0x10,0x60,0xff,0xca,
-0x01,0x80,0x28,0x21,0x08,0x00,0x2b,0x6b,0x02,0x00,0x20,0x21,0x90,0x87,0x01,0xc0,
-0x00,0x00,0x00,0x00,0x10,0xe0,0xff,0x06,0x00,0x00,0x28,0x21,0x3c,0x02,0xb0,0x03,
-0x34,0x42,0x01,0x08,0x94,0x83,0x01,0xd8,0x8c,0x88,0x01,0xd0,0x8c,0x45,0x00,0x00,
-0x01,0x03,0x18,0x21,0x00,0xa3,0x10,0x2b,0x10,0x40,0x00,0x0b,0x2c,0xe2,0x00,0x02,
-0x00,0xa8,0x10,0x2b,0x10,0x40,0xfe,0xf9,0x00,0xc9,0x10,0x26,0x3c,0x02,0x80,0x00,
-0x00,0x62,0x18,0x21,0x00,0xa2,0x10,0x21,0x00,0x43,0x10,0x2b,0x14,0x40,0xfe,0xf3,
-0x00,0xc9,0x10,0x26,0x2c,0xe2,0x00,0x02,0x10,0x40,0xff,0x90,0x00,0x00,0x00,0x00,
-0x24,0x02,0x00,0x01,0x14,0xe2,0xfe,0xed,0x00,0xc9,0x10,0x26,0x3c,0x03,0xb0,0x06,
-0x34,0x63,0x80,0x18,0x8c,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x17,0x02,
-0x14,0x40,0xfe,0xe5,0x00,0x00,0x00,0x00,0x08,0x00,0x2b,0x6b,0x00,0x00,0x00,0x00,
-0x3c,0x04,0xb0,0x03,0x3c,0x06,0xb0,0x07,0x3c,0x02,0x80,0x01,0x34,0xc6,0x00,0x18,
-0x34,0x84,0x00,0x20,0x24,0x42,0xaf,0xa0,0x24,0x03,0xff,0x83,0xac,0x82,0x00,0x00,
-0xa0,0xc3,0x00,0x00,0x90,0xc4,0x00,0x00,0x27,0xbd,0xff,0xf8,0x3c,0x03,0xb0,0x07,
-0x24,0x02,0xff,0x82,0xa3,0xa4,0x00,0x00,0xa0,0x62,0x00,0x00,0x90,0x64,0x00,0x00,
-0x3c,0x02,0xb0,0x07,0x34,0x42,0x00,0x08,0xa3,0xa4,0x00,0x01,0xa0,0x40,0x00,0x00,
-0x90,0x43,0x00,0x00,0x24,0x02,0x00,0x03,0x3c,0x05,0xb0,0x07,0xa3,0xa3,0x00,0x00,
-0xa0,0xc2,0x00,0x00,0x90,0xc4,0x00,0x00,0x34,0xa5,0x00,0x10,0x24,0x02,0x00,0x06,
-0x3c,0x03,0xb0,0x07,0xa3,0xa4,0x00,0x00,0x34,0x63,0x00,0x38,0xa0,0xa2,0x00,0x00,
-0x90,0x64,0x00,0x00,0x3c,0x02,0xb0,0x07,0x34,0x42,0x00,0x20,0xa3,0xa4,0x00,0x00,
-0xa0,0xa0,0x00,0x00,0x90,0xa3,0x00,0x00,0xaf,0x82,0xbf,0x20,0xa3,0xa3,0x00,0x00,
-0xa0,0x40,0x00,0x00,0x90,0x43,0x00,0x00,0x03,0xe0,0x00,0x08,0x27,0xbd,0x00,0x08,
-};
-
-u8 rtl8190_fwdata_array[] ={
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,
-0x02,0xe9,0x01,0x74,0x02,0xab,0x01,0xc7,0x01,0x55,0x00,0xe4,0x00,0xab,0x00,0x72,
-0x00,0x55,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x00,0x4c,0x02,0x76,0x01,0x3b,
-0x00,0xd2,0x00,0x9e,0x00,0x69,0x00,0x4f,0x00,0x46,0x00,0x3f,0x01,0x3b,0x00,0x9e,
-0x00,0x69,0x00,0x4f,0x00,0x35,0x00,0x27,0x00,0x23,0x00,0x20,0x01,0x2f,0x00,0x98,
-0x00,0x65,0x00,0x4c,0x00,0x33,0x00,0x26,0x00,0x22,0x00,0x1e,0x00,0x98,0x00,0x4c,
-0x00,0x33,0x00,0x26,0x00,0x19,0x00,0x13,0x00,0x11,0x00,0x0f,0x02,0x39,0x01,0x1c,
-0x00,0xbd,0x00,0x8e,0x00,0x5f,0x00,0x47,0x00,0x3f,0x00,0x39,0x01,0x1c,0x00,0x8e,
-0x00,0x5f,0x00,0x47,0x00,0x2f,0x00,0x23,0x00,0x20,0x00,0x1c,0x01,0x11,0x00,0x89,
-0x00,0x5b,0x00,0x44,0x00,0x2e,0x00,0x22,0x00,0x1e,0x00,0x1b,0x00,0x89,0x00,0x44,
-0x00,0x2e,0x00,0x22,0x00,0x17,0x00,0x11,0x00,0x0f,0x00,0x0e,0x02,0xab,0x02,0xab,
-0x02,0x66,0x02,0x66,0x07,0x06,0x06,0x06,0x05,0x06,0x07,0x08,0x04,0x06,0x07,0x08,
-0x09,0x0a,0x0b,0x0b,0x49,0x6e,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x4c,
-0x42,0x4d,0x4f,0x44,0x00,0x00,0x00,0x00,0x54,0x4c,0x42,0x4c,0x5f,0x64,0x61,0x74,
-0x61,0x00,0x54,0x4c,0x42,0x53,0x00,0x00,0x00,0x00,0x00,0x00,0x41,0x64,0x45,0x4c,
-0x5f,0x64,0x61,0x74,0x61,0x00,0x41,0x64,0x45,0x53,0x00,0x00,0x00,0x00,0x00,0x00,
-0x45,0x78,0x63,0x43,0x6f,0x64,0x65,0x36,0x00,0x00,0x45,0x78,0x63,0x43,0x6f,0x64,
-0x65,0x37,0x00,0x00,0x53,0x79,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x70,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x49,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x43,0x70,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0x76,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x0b,0x53,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x2c,
-0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,
-0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x01,0x20,0x00,0x00,0x01,0x80,
-0x00,0x00,0x01,0xb0,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x9c,
-0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x38,0x00,0x00,0x01,0xa0,0x00,0x00,0x01,0xd4,
-0x00,0x00,0x02,0x08,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0xd0,0x00,0x00,0x01,0x38,
-0x00,0x00,0x01,0xa0,0x00,0x00,0x02,0x6f,0x00,0x00,0x03,0x40,0x00,0x00,0x03,0xa8,
-0x00,0x00,0x04,0x10,0x01,0x01,0x01,0x02,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,
-0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x07,0x74,0x80,0x00,0x07,0x88,
-0x80,0x00,0x07,0x88,0x80,0x00,0x07,0x78,0x80,0x00,0x07,0x78,0x80,0x00,0x07,0x9c,
-0x80,0x00,0x53,0xc4,0x80,0x00,0x54,0x24,0x80,0x00,0x54,0x38,0x80,0x00,0x54,0x5c,
-0x80,0x00,0x54,0x68,0x80,0x00,0x54,0xa8,0x80,0x00,0x56,0xa8,0x80,0x00,0x57,0xec,
-0x80,0x00,0x58,0x14,0x80,0x00,0x59,0x0c,0x80,0x00,0x59,0xc4,0x80,0x00,0x5a,0x6c,
-0x80,0x00,0x5a,0xe0,0x80,0x00,0x5b,0xec,0x80,0x00,0x5c,0x24,0x80,0x00,0x5c,0x38,
-0x80,0x00,0x5c,0x4c,0x80,0x00,0x5d,0x40,0x80,0x00,0x5d,0x80,0x80,0x00,0x5e,0x34,
-0x80,0x00,0x5e,0x5c,0x80,0x00,0x56,0x68,0x80,0x00,0x5e,0x78,0x80,0x00,0x88,0xf8,
-0x80,0x00,0x88,0xf8,0x80,0x00,0x88,0xf8,0x80,0x00,0x89,0x2c,0x80,0x00,0x89,0x6c,
-0x80,0x00,0x89,0xa4,0x80,0x00,0x89,0xd4,0x80,0x00,0x8a,0x10,0x80,0x00,0x8a,0x50,
-0x80,0x00,0x8a,0xb8,0x80,0x00,0x8a,0xcc,0x80,0x00,0x8b,0x08,0x80,0x00,0x8b,0x10,
-0x80,0x00,0x8b,0x4c,0x80,0x00,0x8b,0x60,0x80,0x00,0x8b,0x68,0x80,0x00,0x8b,0x70,
-0x80,0x00,0x8b,0x70,0x80,0x00,0x8b,0x70,0x80,0x00,0x8b,0x70,0x80,0x00,0x8a,0x90,
-0x80,0x00,0x8b,0xa0,0x80,0x00,0x8b,0xb4,0x80,0x00,0x88,0x54,0x80,0x00,0x8e,0xc8,
-0x80,0x00,0x8e,0xc8,0x80,0x00,0x8e,0xc8,0x80,0x00,0x8e,0xfc,0x80,0x00,0x8f,0x3c,
-0x80,0x00,0x8f,0x74,0x80,0x00,0x8f,0xa4,0x80,0x00,0x8f,0xe0,0x80,0x00,0x90,0x20,
-0x80,0x00,0x90,0x88,0x80,0x00,0x90,0x9c,0x80,0x00,0x90,0xd8,0x80,0x00,0x90,0xe0,
-0x80,0x00,0x91,0x1c,0x80,0x00,0x91,0x30,0x80,0x00,0x91,0x38,0x80,0x00,0x91,0x40,
-0x80,0x00,0x91,0x40,0x80,0x00,0x91,0x40,0x80,0x00,0x91,0x40,0x80,0x00,0x90,0x60,
-0x80,0x00,0x91,0x70,0x80,0x00,0x91,0x84,0x80,0x00,0x8d,0x00,};
-
 u32 Rtl8192UsbPHY_REGArray[] = {
 0x0, };
 
diff --git a/drivers/staging/rtl8192u/r819xU_firmware_img.h b/drivers/staging/rtl8192u/r819xU_firmware_img.h
index d9d9515..18d0a6b 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware_img.h
+++ b/drivers/staging/rtl8192u/r819xU_firmware_img.h
@@ -1,9 +1,6 @@
 #ifndef IMG_H
 #define IMG_H
 
-#define BOOT_ARR_LEN 344
-#define MAIN_ARR_LEN 45136
-#define DATA_ARR_LEN 796
 #define MACPHY_Array_PGLength 30
 #define PHY_REG_1T2RArrayLength 296
 #define AGCTAB_ArrayLength 384
@@ -16,10 +13,6 @@
 #define PHY_REGArrayLength 1
 
 
-extern u8 rtl8190_fwboot_array[BOOT_ARR_LEN];
-extern u8 rtl8190_fwmain_array[MAIN_ARR_LEN];
-extern u8 rtl8190_fwdata_array[DATA_ARR_LEN];
-
 extern u32 Rtl8192UsbPHY_REGArray[];
 extern u32 Rtl8192UsbPHY_REG_1T2RArray[];
 extern u32 Rtl8192UsbRadioA_Array[];
diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig
index 1e9a230..041e1e8 100644
--- a/drivers/staging/rtl8712/Kconfig
+++ b/drivers/staging/rtl8712/Kconfig
@@ -3,6 +3,7 @@ config R8712U
 	depends on WLAN && USB
 	select WIRELESS_EXT
 	select WEXT_PRIV
+	select FW_LOADER
 	default N
 	---help---
 	This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130.
diff --git a/drivers/staging/rtl8712/TODO b/drivers/staging/rtl8712/TODO
index 2aa5deb..d8dfe5b 100644
--- a/drivers/staging/rtl8712/TODO
+++ b/drivers/staging/rtl8712/TODO
@@ -3,8 +3,6 @@ TODO:
 - switch to use LIB80211
 - switch to use MAC80211
 - checkpatch.pl fixes - only a few remain
-- switch from large inline firmware file to use the firmware interface
-  and add the file to the linux-firmware package.
 
 Please send any patches to Greg Kroah-Hartman <greg@kroah.com>,
 Larry Finger <Larry.Finger@lwfinger.net> and
diff --git a/drivers/staging/rtl8712/farray.h b/drivers/staging/rtl8712/farray.h
deleted file mode 100644
index 9217772..0000000
--- a/drivers/staging/rtl8712/farray.h
+++ /dev/null
@@ -1,10197 +0,0 @@
-/* Firmware */
-static const unsigned char f_array[122328] = {
-0x12, 0x87, 0xEC, 0x11, 0x30, 0x00, 0x00, 0x00, 0x08, 0xE8, 0x00, 0x00,
-0x50, 0xF5, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x98, 0xF3, 0x00, 0x00,
-0xF2, 0x00, 0x00, 0x00, 0x05, 0x30, 0x16, 0x53, 0x87, 0x12, 0x12, 0x01,
-0x00, 0x00, 0x12, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01,
-0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x1A, 0x3C, 0x80, 0x03, 0x5A, 0x37, 0x00, 0x80, 0x1B, 0x3C,
-0x80, 0x00, 0x7B, 0x37, 0x00, 0x00, 0x5B, 0xAF, 0x25, 0xB0, 0x1A, 0x3C,
-0x18, 0x03, 0x5A, 0x37, 0x00, 0x80, 0x1B, 0x3C, 0x80, 0x00, 0x7B, 0x37,
-0x00, 0x00, 0x5B, 0xAF, 0x01, 0x80, 0x1A, 0x3C, 0x24, 0xE2, 0x5A, 0x27,
-0x08, 0x00, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xA1, 0xAF, 0x08, 0x00, 0xA2, 0xAF,
-0x0C, 0x00, 0xA3, 0xAF, 0x10, 0x00, 0xA4, 0xAF, 0x14, 0x00, 0xA5, 0xAF,
-0x18, 0x00, 0xA6, 0xAF, 0x1C, 0x00, 0xA7, 0xAF, 0x20, 0x00, 0xA8, 0xAF,
-0x24, 0x00, 0xA9, 0xAF, 0x28, 0x00, 0xAA, 0xAF, 0x2C, 0x00, 0xAB, 0xAF,
-0x30, 0x00, 0xAC, 0xAF, 0x34, 0x00, 0xAD, 0xAF, 0x38, 0x00, 0xAE, 0xAF,
-0x3C, 0x00, 0xAF, 0xAF, 0x12, 0x40, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00,
-0x00, 0x70, 0x0A, 0x40, 0x40, 0x00, 0xB0, 0xAF, 0x44, 0x00, 0xB1, 0xAF,
-0x48, 0x00, 0xB2, 0xAF, 0x4C, 0x00, 0xB3, 0xAF, 0x50, 0x00, 0xB4, 0xAF,
-0x54, 0x00, 0xB5, 0xAF, 0x58, 0x00, 0xB6, 0xAF, 0x5C, 0x00, 0xB7, 0xAF,
-0x60, 0x00, 0xB8, 0xAF, 0x64, 0x00, 0xB9, 0xAF, 0x68, 0x00, 0xBC, 0xAF,
-0x6C, 0x00, 0xBD, 0xAF, 0x70, 0x00, 0xBE, 0xAF, 0x74, 0x00, 0xBF, 0xAF,
-0x78, 0x00, 0xA8, 0xAF, 0x7C, 0x00, 0xA9, 0xAF, 0x80, 0x00, 0xAA, 0xAF,
-0x17, 0x38, 0x00, 0x08, 0x21, 0x20, 0xA0, 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, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xBD, 0x27,
-0x14, 0x00, 0xB1, 0xAF, 0x00, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x11, 0x3C,
-0x18, 0x03, 0x23, 0x36, 0x00, 0x03, 0x42, 0x24, 0x00, 0x00, 0x62, 0xAC,
-0x18, 0x00, 0xB2, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x1C, 0x00, 0xBF, 0xAF,
-0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x42, 0xB0, 0x02, 0x3C,
-0x03, 0x00, 0x47, 0x34, 0x00, 0x00, 0xE3, 0x90, 0x02, 0x80, 0x0A, 0x3C,
-0x02, 0x80, 0x0B, 0x3C, 0xFF, 0x00, 0x70, 0x30, 0x00, 0x36, 0x10, 0x00,
-0x10, 0x00, 0x02, 0x32, 0x03, 0x36, 0x06, 0x00, 0x17, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x12, 0x3C, 0xFC, 0x5C, 0x42, 0x8D, 0x60, 0x1B, 0x44, 0x26,
-0x64, 0x37, 0x83, 0x94, 0x01, 0x00, 0x45, 0x24, 0x10, 0x00, 0x02, 0x24,
-0xB0, 0x03, 0x29, 0x36, 0x1C, 0x03, 0x28, 0x36, 0x00, 0x00, 0xE2, 0xA0,
-0x07, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x68, 0x37, 0x82, 0x94,
-0x64, 0x37, 0x80, 0xA4, 0x68, 0x37, 0x80, 0xA4, 0x00, 0x00, 0x03, 0x24,
-0x00, 0x00, 0x02, 0xAD, 0x00, 0x00, 0x20, 0xAD, 0x10, 0x5E, 0x62, 0x8D,
-0x01, 0x00, 0x63, 0x24, 0xFC, 0x5C, 0x45, 0xAD, 0x01, 0x00, 0x42, 0x24,
-0x10, 0x5E, 0x62, 0xAD, 0x64, 0x37, 0x83, 0xA4, 0x29, 0x00, 0xC0, 0x04,
-0x42, 0xB0, 0x02, 0x3C, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x40, 0x00, 0x02, 0x32, 0x0F, 0x00, 0x40, 0x14, 0x60, 0x1B, 0x44, 0x26,
-0xE0, 0x1B, 0x83, 0x94, 0xDC, 0x1B, 0x85, 0x94, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x80, 0x00, 0x63, 0x30, 0x41, 0xB0, 0x02, 0x3C, 0x25, 0x18, 0x65, 0x00,
-0x08, 0x00, 0x42, 0x34, 0x20, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x43, 0xA4,
-0x08, 0x00, 0xE0, 0x03, 0xDC, 0x1B, 0x83, 0xA4, 0x42, 0xB0, 0x02, 0x3C,
-0x40, 0x00, 0x03, 0x24, 0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0,
-0x25, 0x62, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x44, 0x26,
-0xE0, 0x1B, 0x83, 0x94, 0xDC, 0x1B, 0x85, 0x94, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x80, 0x00, 0x63, 0x30, 0x41, 0xB0, 0x02, 0x3C, 0x25, 0x18, 0x65, 0x00,
-0x08, 0x00, 0x42, 0x34, 0x20, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x43, 0xA4,
-0x08, 0x00, 0xE0, 0x03, 0xDC, 0x1B, 0x83, 0xA4, 0x80, 0xFF, 0x03, 0x24,
-0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0, 0x44, 0x22, 0x00, 0x74,
-0x00, 0x00, 0x00, 0x00, 0xEF, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x84, 0x30, 0x0B, 0x00, 0x82, 0x2C, 0xFF, 0xFF, 0xE7, 0x30,
-0x10, 0x00, 0xA8, 0x93, 0x19, 0x00, 0x40, 0x10, 0x21, 0x18, 0x00, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x80, 0x10, 0x04, 0x00, 0x88, 0xE6, 0x63, 0x24,
-0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0xB0, 0x02, 0x3C,
-0x78, 0x00, 0x44, 0x34, 0x07, 0x00, 0xE2, 0x30, 0x00, 0x00, 0x85, 0xAC,
-0x04, 0x00, 0x86, 0xAC, 0x04, 0x00, 0x40, 0x18, 0x00, 0x00, 0x00, 0x00,
-0xF8, 0xFF, 0xE2, 0x30, 0x08, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x47, 0x30,
-0x21, 0x10, 0xE8, 0x00, 0x00, 0x80, 0x03, 0x3C, 0x08, 0x00, 0x82, 0xAC,
-0x25, 0x10, 0x43, 0x00, 0x08, 0x00, 0x82, 0xAC, 0x01, 0x00, 0x03, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x6C, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x60, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x54, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x48, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x3C, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x30, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x24, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x18, 0x00, 0x44, 0x34, 0x43, 0xB0, 0x02, 0x3C,
-0x2E, 0x01, 0x00, 0x08, 0x0C, 0x00, 0x44, 0x34, 0x2E, 0x01, 0x00, 0x08,
-0x43, 0xB0, 0x04, 0x3C, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x18, 0x03, 0x42, 0x34, 0x6C, 0x05, 0x63, 0x24, 0x00, 0x00, 0x43, 0xAC,
-0x01, 0x00, 0x05, 0x24, 0x43, 0xB0, 0x02, 0x3C, 0x04, 0x28, 0x85, 0x00,
-0x88, 0x00, 0x44, 0x34, 0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24,
-0xFF, 0xFF, 0x42, 0x30, 0x05, 0x00, 0x43, 0x2C, 0xFD, 0xFF, 0x60, 0x14,
-0x01, 0x00, 0x42, 0x24, 0x00, 0x00, 0x82, 0x94, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x42, 0x30, 0x24, 0x10, 0x45, 0x00, 0xF5, 0xFF, 0x40, 0x1C,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x08, 0x3C, 0x00, 0x80, 0x02, 0x3C, 0xC8, 0xFF, 0xBD, 0x27,
-0x18, 0x03, 0x03, 0x35, 0xC8, 0x05, 0x42, 0x24, 0x00, 0x00, 0x62, 0xAC,
-0x30, 0x00, 0xB6, 0xAF, 0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x34, 0x00, 0xBF, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x20, 0x00, 0xB2, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x0C, 0x00, 0xF2, 0x84,
-0x08, 0x00, 0xF5, 0x8C, 0xFF, 0x00, 0xC6, 0x30, 0x00, 0x01, 0x02, 0x24,
-0x23, 0x10, 0x46, 0x00, 0xFF, 0xFF, 0x51, 0x30, 0xD0, 0x03, 0x08, 0x35,
-0xFF, 0x00, 0x96, 0x30, 0x00, 0x00, 0x12, 0xAD, 0x21, 0xA0, 0xA0, 0x00,
-0x21, 0x30, 0xC5, 0x00, 0x00, 0x00, 0x15, 0xAD, 0x21, 0x20, 0xC0, 0x02,
-0x21, 0x28, 0xA0, 0x02, 0x21, 0x38, 0x20, 0x02, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x23, 0x18, 0x51, 0x02, 0xFF, 0xFF, 0x82, 0x32,
-0x00, 0x94, 0x03, 0x00, 0x03, 0x94, 0x12, 0x00, 0xB4, 0x01, 0x00, 0x08,
-0x02, 0x9A, 0x02, 0x00, 0x28, 0xB0, 0x03, 0x3C, 0xC0, 0x10, 0x13, 0x00,
-0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x90, 0x25, 0xB0, 0x10, 0x3C,
-0x20, 0x10, 0x02, 0x3C, 0xFF, 0x00, 0x93, 0x30, 0x00, 0x22, 0x13, 0x00,
-0xFF, 0xFF, 0x43, 0x32, 0x01, 0x01, 0x45, 0x2A, 0x21, 0xA0, 0x82, 0x00,
-0x21, 0xA8, 0xB1, 0x02, 0xD0, 0x03, 0x02, 0x36, 0x00, 0x01, 0x11, 0x24,
-0x0B, 0x88, 0x65, 0x00, 0x21, 0x20, 0xC0, 0x02, 0x00, 0x00, 0x53, 0xAC,
-0x5B, 0x01, 0x00, 0x0C, 0xB0, 0x03, 0x10, 0x36, 0x21, 0x30, 0x80, 0x02,
-0x21, 0x20, 0xC0, 0x02, 0x21, 0x28, 0xA0, 0x02, 0x21, 0x38, 0x20, 0x02,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x23, 0x18, 0x51, 0x02,
-0x00, 0x94, 0x03, 0x00, 0x03, 0x94, 0x12, 0x00, 0x00, 0x00, 0x12, 0xAE,
-0xE2, 0xFF, 0x40, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0xBF, 0x8F,
-0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27,
-0x21, 0x50, 0x80, 0x00, 0x04, 0x00, 0x8D, 0x8C, 0x0C, 0x00, 0x4B, 0x8D,
-0x08, 0x00, 0x84, 0x8C, 0xFF, 0xE0, 0x02, 0x3C, 0x10, 0x00, 0x47, 0x8D,
-0xFF, 0xFF, 0x42, 0x34, 0x1F, 0x00, 0xA9, 0x31, 0x24, 0x20, 0x82, 0x00,
-0x00, 0x1E, 0x09, 0x00, 0x02, 0x14, 0x0B, 0x00, 0x25, 0x40, 0x83, 0x00,
-0x21, 0x78, 0xA0, 0x00, 0xB7, 0x00, 0xE0, 0x04, 0x07, 0x00, 0x44, 0x30,
-0x00, 0x00, 0x42, 0x95, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0F, 0x42, 0x28,
-0xB9, 0x00, 0x40, 0x10, 0xFF, 0xDF, 0x02, 0x3C, 0x02, 0x80, 0x0E, 0x3C,
-0x08, 0x00, 0x48, 0xAD, 0x60, 0x1B, 0xC3, 0x25, 0xC6, 0x3D, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x40, 0x14, 0xC0, 0x30, 0x09, 0x00,
-0xC6, 0x40, 0x62, 0x90, 0xFF, 0xDF, 0x03, 0x3C, 0xFF, 0xFF, 0x63, 0x34,
-0x07, 0x10, 0x82, 0x00, 0x01, 0x00, 0x42, 0x30, 0x24, 0x18, 0x03, 0x01,
-0x40, 0x17, 0x02, 0x00, 0x25, 0x40, 0x62, 0x00, 0x08, 0x00, 0x48, 0xAD,
-0xC0, 0x30, 0x09, 0x00, 0x21, 0x10, 0xC9, 0x00, 0x80, 0x10, 0x02, 0x00,
-0x21, 0x10, 0x49, 0x00, 0x80, 0x10, 0x02, 0x00, 0x60, 0x1B, 0xC9, 0x25,
-0x21, 0x28, 0x49, 0x00, 0x08, 0x25, 0xA3, 0x8C, 0x01, 0x00, 0x0C, 0x24,
-0x02, 0x13, 0x03, 0x00, 0x01, 0x00, 0x42, 0x30, 0xB5, 0x00, 0x4C, 0x10,
-0x42, 0x18, 0x03, 0x00, 0x82, 0x11, 0x08, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0xC0, 0xFF, 0x02, 0x24,
-0x24, 0x10, 0x02, 0x01, 0x04, 0x00, 0x48, 0x34, 0x08, 0x00, 0x48, 0xAD,
-0x02, 0x80, 0x02, 0x3C, 0xD1, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x6A, 0x00, 0x60, 0x14, 0x21, 0x20, 0xC9, 0x00, 0xD4, 0x23, 0x83, 0x8C,
-0xBF, 0xFF, 0x02, 0x24, 0x24, 0x10, 0xE2, 0x00, 0x40, 0x00, 0x63, 0x30,
-0x25, 0x38, 0x43, 0x00, 0x10, 0x00, 0x47, 0xAD, 0xD4, 0x23, 0x83, 0x8C,
-0x7F, 0xF8, 0x02, 0x24, 0x24, 0x10, 0xE2, 0x00, 0x80, 0x07, 0x63, 0x30,
-0x25, 0x38, 0x43, 0x00, 0x10, 0x00, 0x47, 0xAD, 0xC6, 0x3D, 0x22, 0x91,
-0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x40, 0x14, 0x42, 0x17, 0x08, 0x00,
-0x01, 0x00, 0x44, 0x30, 0xB1, 0x00, 0x8C, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0xC4, 0x25, 0x21, 0x20, 0xC4, 0x00, 0xD4, 0x23, 0x83, 0x8C,
-0xFF, 0xF7, 0x02, 0x24, 0x24, 0x10, 0xE2, 0x00, 0x00, 0x08, 0x63, 0x30,
-0x25, 0x38, 0x43, 0x00, 0x10, 0x00, 0x47, 0xAD, 0xD4, 0x23, 0x83, 0x8C,
-0xFF, 0xEF, 0x02, 0x24, 0x24, 0x10, 0xE2, 0x00, 0x00, 0x10, 0x63, 0x30,
-0x25, 0x38, 0x43, 0x00, 0x10, 0x00, 0x47, 0xAD, 0x60, 0x1B, 0xC5, 0x25,
-0x21, 0x30, 0xC5, 0x00, 0xD4, 0x23, 0xC4, 0x8C, 0xFD, 0xFF, 0x02, 0x3C,
-0x02, 0x00, 0x03, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x83, 0x00,
-0x24, 0x10, 0xE2, 0x00, 0x25, 0x38, 0x44, 0x00, 0x10, 0x00, 0x47, 0xAD,
-0xB0, 0x1B, 0xA3, 0x94, 0xFB, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0xC2, 0x1B, 0x03, 0x00, 0x24, 0x10, 0xE2, 0x00, 0x80, 0x1C, 0x03, 0x00,
-0x25, 0x38, 0x43, 0x00, 0x10, 0x00, 0x47, 0xAD, 0x3B, 0x41, 0xA3, 0x90,
-0xE7, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x03, 0x00, 0x63, 0x30,
-0x24, 0x10, 0xE2, 0x00, 0xC0, 0x1C, 0x03, 0x00, 0x25, 0x38, 0x43, 0x00,
-0x10, 0x00, 0x47, 0xAD, 0xD4, 0x23, 0xC4, 0x8C, 0xFF, 0xFD, 0x02, 0x3C,
-0x00, 0x02, 0x03, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x83, 0x00,
-0x24, 0x10, 0xE2, 0x00, 0x25, 0x38, 0x44, 0x00, 0x10, 0x00, 0x47, 0xAD,
-0xB0, 0x1B, 0xA3, 0x94, 0xFF, 0xFB, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0xC2, 0x1B, 0x03, 0x00, 0x24, 0x10, 0xE2, 0x00, 0x80, 0x1E, 0x03, 0x00,
-0x25, 0x38, 0x43, 0x00, 0x10, 0x00, 0x47, 0xAD, 0x3B, 0x41, 0xA3, 0x90,
-0xFF, 0xE7, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x03, 0x00, 0x63, 0x30,
-0x24, 0x10, 0xE2, 0x00, 0xC0, 0x1E, 0x03, 0x00, 0x25, 0x38, 0x43, 0x00,
-0x10, 0x00, 0x47, 0xAD, 0xD4, 0x23, 0xC3, 0x8C, 0xC0, 0xFF, 0x02, 0x24,
-0x24, 0x10, 0xE2, 0x00, 0x3F, 0x00, 0x63, 0x30, 0x25, 0x10, 0x43, 0x00,
-0x10, 0x00, 0x42, 0xAD, 0xD8, 0x23, 0xC4, 0x8C, 0x14, 0x00, 0x43, 0x8D,
-0xFF, 0xFF, 0x02, 0x3C, 0xFF, 0x7F, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00,
-0x00, 0x80, 0x84, 0x30, 0x25, 0x18, 0x64, 0x00, 0x14, 0x00, 0x43, 0xAD,
-0xDA, 0x23, 0xC4, 0x94, 0xE0, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x1F, 0x00, 0x84, 0x30, 0x24, 0x18, 0x62, 0x00, 0x00, 0x24, 0x04, 0x00,
-0x25, 0x18, 0x64, 0x00, 0x14, 0x00, 0x43, 0xAD, 0x02, 0x00, 0x43, 0x91,
-0x02, 0x14, 0x0D, 0x00, 0x01, 0x00, 0x42, 0x30, 0x27, 0x00, 0x40, 0x10,
-0x21, 0x30, 0x6F, 0x00, 0x60, 0x1B, 0xC4, 0x25, 0xE4, 0x1D, 0x85, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA2, 0x24, 0xE4, 0x1D, 0x82, 0xA4,
-0x0C, 0x00, 0x43, 0x8D, 0x00, 0xF0, 0x02, 0x3C, 0xFF, 0x0F, 0xA5, 0x30,
-0xFF, 0xFF, 0x42, 0x34, 0x00, 0x24, 0x05, 0x00, 0x24, 0x18, 0x62, 0x00,
-0x25, 0x58, 0x83, 0x00, 0x0C, 0x00, 0x4B, 0xAD, 0x16, 0x00, 0xC2, 0x94,
-0x00, 0x19, 0x05, 0x00, 0x60, 0x1B, 0xC4, 0x25, 0x0F, 0x00, 0x42, 0x30,
-0x25, 0x10, 0x43, 0x00, 0x16, 0x00, 0xC2, 0xA4, 0x00, 0x00, 0x43, 0x95,
-0x40, 0x41, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x43, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x40, 0x41, 0x82, 0xAC, 0x14, 0x00, 0x42, 0x8D,
-0x00, 0x00, 0x00, 0x00, 0x42, 0x12, 0x02, 0x00, 0x3F, 0x00, 0x42, 0x30,
-0x0C, 0x00, 0x42, 0x28, 0x44, 0xFF, 0x40, 0x10, 0xFF, 0xDF, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x40, 0x02, 0x01, 0x00, 0x40, 0x03, 0x3C,
-0x25, 0x40, 0x03, 0x01, 0xE3, 0x01, 0x00, 0x08, 0x02, 0x80, 0x0E, 0x3C,
-0x60, 0x1B, 0xC3, 0x25, 0xC6, 0x3D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x1D, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x13, 0x0B, 0x00,
-0x0E, 0x00, 0x42, 0x30, 0x21, 0x10, 0x43, 0x00, 0xD4, 0x1D, 0x45, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA3, 0x24, 0xD4, 0x1D, 0x43, 0xA4,
-0x0C, 0x00, 0x44, 0x8D, 0x00, 0xF0, 0x02, 0x3C, 0xFF, 0x0F, 0xA5, 0x30,
-0xFF, 0xFF, 0x42, 0x34, 0x00, 0x1C, 0x05, 0x00, 0x77, 0x02, 0x00, 0x08,
-0x24, 0x20, 0x82, 0x00, 0x7F, 0xFF, 0x02, 0x24, 0x24, 0x10, 0x02, 0x01,
-0x80, 0x00, 0x63, 0x30, 0x25, 0x40, 0x43, 0x00, 0x08, 0x00, 0x48, 0xAD,
-0x08, 0x25, 0xA3, 0x8C, 0xFF, 0xFF, 0x02, 0x3C, 0xFF, 0x1F, 0x42, 0x34,
-0x07, 0x00, 0x63, 0x30, 0x24, 0x10, 0xE2, 0x00, 0x40, 0x1B, 0x03, 0x00,
-0x25, 0x38, 0x43, 0x00, 0xF1, 0x01, 0x00, 0x08, 0x10, 0x00, 0x47, 0xAD,
-0x02, 0x14, 0x0B, 0x00, 0xFF, 0x0F, 0x45, 0x30, 0x16, 0x00, 0xC2, 0x94,
-0x00, 0x19, 0x05, 0x00, 0x60, 0x1B, 0xC4, 0x25, 0x0F, 0x00, 0x42, 0x30,
-0x25, 0x10, 0x43, 0x00, 0x16, 0x00, 0xC2, 0xA4, 0x00, 0x00, 0x43, 0x95,
-0x40, 0x41, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x43, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x40, 0x41, 0x82, 0xAC, 0xCE, 0x5C, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x4E, 0xFF, 0x64, 0x14, 0x60, 0x1B, 0xC4, 0x25,
-0x3C, 0x41, 0x22, 0x91, 0xFF, 0xF7, 0x03, 0x24, 0x24, 0x18, 0xE3, 0x00,
-0x01, 0x00, 0x42, 0x30, 0xC0, 0x12, 0x02, 0x00, 0x25, 0x38, 0x62, 0x00,
-0x10, 0x00, 0x47, 0xAD, 0x3D, 0x41, 0x22, 0x91, 0xFF, 0xEF, 0x03, 0x24,
-0x24, 0x18, 0xE3, 0x00, 0x01, 0x00, 0x42, 0x30, 0x00, 0x13, 0x02, 0x00,
-0x25, 0x38, 0x43, 0x00, 0x1F, 0x02, 0x00, 0x08, 0x10, 0x00, 0x47, 0xAD,
-0xD8, 0xFF, 0xBD, 0x27, 0x20, 0x00, 0xB2, 0xAF, 0x18, 0x00, 0xB0, 0xAF,
-0x24, 0x00, 0xBF, 0xAF, 0x1C, 0x00, 0xB1, 0xAF, 0x04, 0x00, 0x8B, 0x8C,
-0x21, 0x80, 0x80, 0x00, 0x08, 0x00, 0x84, 0x8C, 0x0E, 0x00, 0x07, 0x96,
-0xFF, 0xE0, 0x02, 0x3C, 0x10, 0x00, 0x08, 0x8E, 0x1F, 0x00, 0x6A, 0x31,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x82, 0x00, 0x00, 0x1E, 0x0A, 0x00,
-0x25, 0x48, 0x83, 0x00, 0x21, 0x90, 0xA0, 0x00, 0x21, 0x60, 0xC0, 0x00,
-0xCF, 0x00, 0x00, 0x05, 0x07, 0x00, 0xE7, 0x30, 0x00, 0x00, 0x02, 0x96,
-0x00, 0x00, 0x00, 0x00, 0xFD, 0x0F, 0x42, 0x28, 0xD1, 0x00, 0x40, 0x10,
-0xFF, 0xDF, 0x02, 0x3C, 0x02, 0x80, 0x11, 0x3C, 0x08, 0x00, 0x09, 0xAE,
-0x60, 0x1B, 0x23, 0x26, 0xC6, 0x3D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x40, 0x62, 0x90,
-0xFF, 0xDF, 0x03, 0x3C, 0xFF, 0xFF, 0x63, 0x34, 0x07, 0x10, 0xE2, 0x00,
-0x01, 0x00, 0x42, 0x30, 0x24, 0x18, 0x23, 0x01, 0x40, 0x17, 0x02, 0x00,
-0x25, 0x48, 0x62, 0x00, 0x08, 0x00, 0x09, 0xAE, 0x1C, 0x00, 0x02, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x40, 0x04, 0x04, 0x00, 0x03, 0x24,
-0xC0, 0x30, 0x0A, 0x00, 0x21, 0x10, 0xCA, 0x00, 0x80, 0x10, 0x02, 0x00,
-0x21, 0x10, 0x4A, 0x00, 0x80, 0x10, 0x02, 0x00, 0x60, 0x1B, 0x27, 0x26,
-0x21, 0x28, 0x47, 0x00, 0x08, 0x25, 0xA3, 0x8C, 0x01, 0x00, 0x0A, 0x24,
-0x02, 0x13, 0x03, 0x00, 0x01, 0x00, 0x42, 0x30, 0xE7, 0x00, 0x4A, 0x10,
-0x42, 0x18, 0x03, 0x00, 0x82, 0x11, 0x09, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0xC0, 0xFF, 0x02, 0x24,
-0x24, 0x10, 0x22, 0x01, 0x04, 0x00, 0x49, 0x34, 0x08, 0x00, 0x09, 0xAE,
-0x02, 0x80, 0x02, 0x3C, 0xD1, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x6C, 0x00, 0x60, 0x14, 0x21, 0x28, 0xC7, 0x00, 0xD4, 0x23, 0xA4, 0x8C,
-0x10, 0x00, 0x02, 0x8E, 0xBF, 0xFF, 0x03, 0x24, 0x40, 0x00, 0x84, 0x30,
-0x24, 0x10, 0x43, 0x00, 0x25, 0x40, 0x44, 0x00, 0x10, 0x00, 0x08, 0xAE,
-0xD4, 0x23, 0xA3, 0x8C, 0x7F, 0xF8, 0x02, 0x24, 0x24, 0x10, 0x02, 0x01,
-0x80, 0x07, 0x63, 0x30, 0x25, 0x40, 0x43, 0x00, 0x10, 0x00, 0x08, 0xAE,
-0xC6, 0x3D, 0xE2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x40, 0x14,
-0x60, 0x1B, 0x25, 0x26, 0x42, 0x17, 0x09, 0x00, 0x01, 0x00, 0x44, 0x30,
-0x08, 0x01, 0x8A, 0x10, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x24, 0x26,
-0x21, 0x20, 0xC4, 0x00, 0xD4, 0x23, 0x83, 0x8C, 0xFF, 0xF7, 0x02, 0x24,
-0x24, 0x10, 0x02, 0x01, 0x00, 0x08, 0x63, 0x30, 0x25, 0x40, 0x43, 0x00,
-0x10, 0x00, 0x08, 0xAE, 0xD4, 0x23, 0x83, 0x8C, 0xFF, 0xEF, 0x02, 0x24,
-0x24, 0x10, 0x02, 0x01, 0x00, 0x10, 0x63, 0x30, 0x25, 0x40, 0x43, 0x00,
-0x10, 0x00, 0x08, 0xAE, 0x60, 0x1B, 0x25, 0x26, 0x21, 0x30, 0xC5, 0x00,
-0xD4, 0x23, 0xC4, 0x8C, 0xFD, 0xFF, 0x02, 0x3C, 0x02, 0x00, 0x03, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x83, 0x00, 0x24, 0x10, 0x02, 0x01,
-0x25, 0x40, 0x44, 0x00, 0x10, 0x00, 0x08, 0xAE, 0xB0, 0x1B, 0xA3, 0x94,
-0xFB, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0xC2, 0x1B, 0x03, 0x00,
-0x24, 0x10, 0x02, 0x01, 0x80, 0x1C, 0x03, 0x00, 0x25, 0x40, 0x43, 0x00,
-0x10, 0x00, 0x08, 0xAE, 0x3B, 0x41, 0xA3, 0x90, 0xE7, 0xFF, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x03, 0x00, 0x63, 0x30, 0x24, 0x10, 0x02, 0x01,
-0xC0, 0x1C, 0x03, 0x00, 0x25, 0x40, 0x43, 0x00, 0x10, 0x00, 0x08, 0xAE,
-0xD4, 0x23, 0xC4, 0x8C, 0xFF, 0xFD, 0x02, 0x3C, 0x00, 0x02, 0x03, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x83, 0x00, 0x24, 0x10, 0x02, 0x01,
-0x25, 0x40, 0x44, 0x00, 0x10, 0x00, 0x08, 0xAE, 0xB0, 0x1B, 0xA3, 0x94,
-0xFF, 0xFB, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0xC2, 0x1B, 0x03, 0x00,
-0x24, 0x10, 0x02, 0x01, 0x80, 0x1E, 0x03, 0x00, 0x25, 0x40, 0x43, 0x00,
-0x10, 0x00, 0x08, 0xAE, 0x3B, 0x41, 0xA3, 0x90, 0xFF, 0xE7, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x03, 0x00, 0x63, 0x30, 0x24, 0x10, 0x02, 0x01,
-0xC0, 0x1E, 0x03, 0x00, 0x25, 0x40, 0x43, 0x00, 0x10, 0x00, 0x08, 0xAE,
-0xD4, 0x23, 0xC3, 0x8C, 0xC0, 0xFF, 0x02, 0x24, 0x24, 0x10, 0x02, 0x01,
-0x3F, 0x00, 0x63, 0x30, 0x25, 0x10, 0x43, 0x00, 0x10, 0x00, 0x02, 0xAE,
-0xD8, 0x23, 0xC4, 0x8C, 0x14, 0x00, 0x03, 0x8E, 0xFF, 0xFF, 0x02, 0x3C,
-0xFF, 0x7F, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00, 0x00, 0x80, 0x84, 0x30,
-0x25, 0x18, 0x64, 0x00, 0x14, 0x00, 0x03, 0xAE, 0xDA, 0x23, 0xC4, 0x94,
-0xE0, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x1F, 0x00, 0x84, 0x30,
-0x24, 0x18, 0x62, 0x00, 0x00, 0x24, 0x04, 0x00, 0x25, 0x18, 0x64, 0x00,
-0x14, 0x00, 0x03, 0xAE, 0x02, 0x00, 0x02, 0x92, 0x02, 0x24, 0x0B, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x21, 0x10, 0x4C, 0x00, 0xFF, 0xFF, 0x42, 0x30,
-0x01, 0x00, 0x84, 0x30, 0x36, 0x00, 0x80, 0x10, 0x25, 0x30, 0x43, 0x00,
-0x60, 0x1B, 0x24, 0x26, 0xE4, 0x1D, 0x85, 0x94, 0x80, 0x00, 0x07, 0x24,
-0x01, 0x00, 0xA2, 0x24, 0xE4, 0x1D, 0x82, 0xA4, 0x0C, 0x00, 0x03, 0x8E,
-0x00, 0xF0, 0x02, 0x3C, 0xFF, 0x0F, 0xA5, 0x30, 0xFF, 0xFF, 0x42, 0x34,
-0x00, 0x24, 0x05, 0x00, 0x24, 0x18, 0x62, 0x00, 0x25, 0x18, 0x64, 0x00,
-0x0C, 0x00, 0x03, 0xAE, 0x16, 0x00, 0xC2, 0x94, 0x00, 0x19, 0x05, 0x00,
-0x02, 0x00, 0x04, 0x24, 0x0F, 0x00, 0x42, 0x30, 0x25, 0x10, 0x43, 0x00,
-0x16, 0x00, 0xC2, 0xA4, 0x21, 0x28, 0x80, 0x01, 0x21, 0x30, 0x40, 0x02,
-0x01, 0x00, 0x02, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x52, 0xAC,
-0x5B, 0x01, 0x00, 0x0C, 0x02, 0x00, 0x04, 0x24, 0x60, 0x1B, 0x24, 0x26,
-0x00, 0x00, 0x03, 0x96, 0x40, 0x41, 0x82, 0x8C, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x43, 0x00, 0x28, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03,
-0x40, 0x41, 0x82, 0xAC, 0x14, 0x00, 0x02, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x42, 0x12, 0x02, 0x00, 0x3F, 0x00, 0x42, 0x30, 0x0C, 0x00, 0x42, 0x28,
-0x2C, 0xFF, 0x40, 0x10, 0xFF, 0xDF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x24, 0x48, 0x22, 0x01, 0x00, 0x40, 0x03, 0x3C, 0x25, 0x48, 0x23, 0x01,
-0xFC, 0x02, 0x00, 0x08, 0x02, 0x80, 0x11, 0x3C, 0x60, 0x1B, 0x23, 0x26,
-0xC6, 0x3D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x53, 0x00, 0x40, 0x14,
-0x80, 0x00, 0x07, 0x24, 0x0E, 0x00, 0x02, 0x96, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0x42, 0x30, 0x40, 0x10, 0x02, 0x00, 0x21, 0x10, 0x43, 0x00,
-0xD4, 0x1D, 0x45, 0x94, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA3, 0x24,
-0xD4, 0x1D, 0x43, 0xA4, 0x0C, 0x00, 0x04, 0x8E, 0x00, 0xF0, 0x02, 0x3C,
-0xFF, 0x0F, 0xA5, 0x30, 0xFF, 0xFF, 0x42, 0x34, 0x00, 0x1C, 0x05, 0x00,
-0x24, 0x20, 0x82, 0x00, 0x25, 0x20, 0x83, 0x00, 0x0C, 0x00, 0x04, 0xAE,
-0x16, 0x00, 0xC2, 0x94, 0x00, 0x19, 0x05, 0x00, 0x02, 0x00, 0x04, 0x24,
-0x0F, 0x00, 0x42, 0x30, 0x25, 0x10, 0x43, 0x00, 0x16, 0x00, 0xC2, 0xA4,
-0x21, 0x28, 0x80, 0x01, 0x21, 0x30, 0x40, 0x02, 0x01, 0x00, 0x02, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x52, 0xAC, 0x5B, 0x01, 0x00, 0x0C,
-0x02, 0x00, 0x04, 0x24, 0x60, 0x1B, 0x24, 0x26, 0x00, 0x00, 0x03, 0x96,
-0x40, 0x41, 0x82, 0x8C, 0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x43, 0x00,
-0x28, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03, 0x40, 0x41, 0x82, 0xAC,
-0x7F, 0xFF, 0x02, 0x24, 0x24, 0x10, 0x22, 0x01, 0x80, 0x00, 0x63, 0x30,
-0x25, 0x48, 0x43, 0x00, 0x08, 0x00, 0x09, 0xAE, 0x08, 0x25, 0xA3, 0x8C,
-0x10, 0x00, 0x04, 0x8E, 0xFF, 0xFF, 0x02, 0x3C, 0x07, 0x00, 0x63, 0x30,
-0xFF, 0x1F, 0x42, 0x34, 0x24, 0x20, 0x82, 0x00, 0x40, 0x1B, 0x03, 0x00,
-0x25, 0x40, 0x83, 0x00, 0x0E, 0x03, 0x00, 0x08, 0x10, 0x00, 0x08, 0xAE,
-0x1E, 0x00, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x21, 0x30, 0x50, 0x00,
-0x00, 0x00, 0xC4, 0x90, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x82, 0x30,
-0x02, 0x29, 0x02, 0x00, 0x3F, 0x00, 0xA3, 0x10, 0x06, 0x00, 0x02, 0x24,
-0xF4, 0xFE, 0xA2, 0x14, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x02, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0xC2, 0xA0, 0x1E, 0x00, 0x03, 0x92,
-0x1A, 0x00, 0x02, 0x96, 0x21, 0x18, 0x70, 0x00, 0x03, 0x12, 0x02, 0x00,
-0x38, 0x00, 0x62, 0xA0, 0x04, 0x00, 0x0B, 0x8E, 0x08, 0x00, 0x09, 0x8E,
-0x02, 0x03, 0x00, 0x08, 0xC0, 0x30, 0x0A, 0x00, 0x0E, 0x00, 0x02, 0x96,
-0x02, 0x00, 0x04, 0x24, 0xFF, 0x0F, 0x45, 0x30, 0x16, 0x00, 0xC2, 0x94,
-0x00, 0x19, 0x05, 0x00, 0x21, 0x28, 0x80, 0x01, 0x0F, 0x00, 0x42, 0x30,
-0x25, 0x10, 0x43, 0x00, 0x16, 0x00, 0xC2, 0xA4, 0x21, 0x30, 0x40, 0x02,
-0x01, 0x00, 0x02, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x52, 0xAC,
-0x5B, 0x01, 0x00, 0x0C, 0x02, 0x00, 0x04, 0x24, 0x60, 0x1B, 0x24, 0x26,
-0x00, 0x00, 0x03, 0x96, 0x40, 0x41, 0x82, 0x8C, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x43, 0x00, 0x28, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03,
-0x40, 0x41, 0x82, 0xAC, 0xCE, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xF7, 0xFE, 0x64, 0x14, 0x60, 0x1B, 0x24, 0x26, 0x3C, 0x41, 0xE2, 0x90,
-0xFF, 0xF7, 0x03, 0x24, 0x24, 0x18, 0x03, 0x01, 0x01, 0x00, 0x42, 0x30,
-0xC0, 0x12, 0x02, 0x00, 0x25, 0x40, 0x62, 0x00, 0x10, 0x00, 0x08, 0xAE,
-0x3D, 0x41, 0xE2, 0x90, 0xFF, 0xEF, 0x03, 0x24, 0x24, 0x18, 0x03, 0x01,
-0x01, 0x00, 0x42, 0x30, 0x00, 0x13, 0x02, 0x00, 0x25, 0x40, 0x43, 0x00,
-0x3E, 0x03, 0x00, 0x08, 0x10, 0x00, 0x08, 0xAE, 0x1A, 0x00, 0x05, 0x96,
-0x0F, 0x00, 0x84, 0x30, 0x80, 0x20, 0x04, 0x00, 0x21, 0x18, 0xC4, 0x00,
-0x11, 0x00, 0x65, 0xA0, 0x1E, 0x00, 0x02, 0x92, 0x1A, 0x00, 0x03, 0x96,
-0x21, 0x10, 0x50, 0x00, 0x21, 0x10, 0x44, 0x00, 0x03, 0x1A, 0x03, 0x00,
-0x10, 0x00, 0x43, 0xA0, 0x04, 0x00, 0x0B, 0x8E, 0x08, 0x00, 0x09, 0x8E,
-0x02, 0x03, 0x00, 0x08, 0xC0, 0x30, 0x0A, 0x00, 0x00, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x64, 0x11, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xC0, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x2C, 0x00, 0xB5, 0xAF,
-0x25, 0xB0, 0x03, 0x3C, 0x60, 0x1B, 0x55, 0x24, 0x00, 0x80, 0x02, 0x3C,
-0x38, 0x00, 0xBE, 0xAF, 0x80, 0x11, 0x42, 0x24, 0xB0, 0x03, 0x7E, 0x34,
-0x18, 0x03, 0x63, 0x34, 0x00, 0x00, 0x62, 0xAC, 0x3C, 0x00, 0xBF, 0xAF,
-0x34, 0x00, 0xB7, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x28, 0x00, 0xB4, 0xAF,
-0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x96, 0x40, 0x00, 0x0C, 0x18, 0x00, 0xB0, 0xAF, 0x8E, 0x04, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0xAE, 0x08, 0x38, 0x46, 0x8E,
-0x21, 0x28, 0x60, 0x02, 0x80, 0x00, 0x07, 0x24, 0x01, 0x00, 0x04, 0x24,
-0x01, 0x00, 0x14, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xB4, 0xAF,
-0x08, 0x38, 0x43, 0x8E, 0x01, 0x00, 0x04, 0x24, 0x00, 0x00, 0xC3, 0xAE,
-0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x1C, 0x42, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x40, 0x10, 0x2A, 0xB0, 0x02, 0x3C,
-0x09, 0x00, 0x42, 0x34, 0x02, 0x00, 0x03, 0x24, 0x00, 0x00, 0x54, 0xA0,
-0x00, 0x00, 0x43, 0xA0, 0xFF, 0x00, 0x03, 0x24, 0x71, 0x00, 0x23, 0x12,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x38, 0xA2, 0x8E, 0x70, 0x38, 0xB3, 0x8E,
-0x01, 0x00, 0x04, 0x24, 0x00, 0x00, 0xC2, 0xAF, 0x08, 0x38, 0xA2, 0xAE,
-0x00, 0x00, 0xD3, 0xAF, 0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x70, 0x38, 0xA4, 0x8E, 0x74, 0x38, 0xA3, 0x8E, 0x02, 0x80, 0x02, 0x3C,
-0xB4, 0xE6, 0x42, 0x24, 0x00, 0x00, 0x52, 0x8C, 0x80, 0x00, 0x84, 0x24,
-0xFF, 0x00, 0x62, 0x24, 0x2B, 0x10, 0x44, 0x00, 0x0A, 0x18, 0x82, 0x00,
-0x70, 0x38, 0xA3, 0xAE, 0x02, 0x80, 0x03, 0x3C, 0xB8, 0xE6, 0x63, 0x24,
-0x70, 0x38, 0x42, 0x8E, 0x00, 0x00, 0x76, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xC2, 0xAE, 0x02, 0x80, 0x17, 0x3C, 0xFF, 0xFF, 0x62, 0x32,
-0x25, 0x80, 0x57, 0x00, 0x00, 0x00, 0xD0, 0xAE, 0x0C, 0x00, 0x02, 0x92,
-0x21, 0x28, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xAE, 0x02, 0x00, 0x04, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x93, 0x00, 0xFF, 0xFF, 0x84, 0x30,
-0xE0, 0x61, 0x00, 0x0C, 0x25, 0x20, 0x97, 0x00, 0x0C, 0x00, 0x11, 0x92,
-0x20, 0x10, 0x02, 0x3C, 0x01, 0x00, 0x04, 0x24, 0x00, 0x1A, 0x11, 0x00,
-0x21, 0x18, 0x62, 0x00, 0xFF, 0x00, 0x02, 0x24, 0x21, 0x30, 0x60, 0x00,
-0x06, 0x00, 0x22, 0x12, 0x80, 0x00, 0x07, 0x24, 0x70, 0x38, 0x45, 0x8E,
-0x04, 0x38, 0x43, 0xAE, 0xA8, 0x37, 0x51, 0xA2, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x04, 0x00, 0x04, 0x8E, 0x08, 0x00, 0x03, 0x8E,
-0xFF, 0xE0, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x1F, 0x00, 0x84, 0x30,
-0x24, 0x18, 0x62, 0x00, 0x00, 0x26, 0x04, 0x00, 0xFF, 0xDF, 0x02, 0x3C,
-0x25, 0x18, 0x64, 0x00, 0xFF, 0xFF, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00,
-0x00, 0x40, 0x04, 0x3C, 0x25, 0x18, 0x64, 0x00, 0xC0, 0xFF, 0x05, 0x24,
-0x82, 0x11, 0x03, 0x00, 0x24, 0x20, 0x65, 0x00, 0x01, 0x00, 0x42, 0x30,
-0xA3, 0xFF, 0x40, 0x10, 0x04, 0x00, 0x84, 0x34, 0x08, 0x00, 0x03, 0xAE,
-0x08, 0x38, 0x46, 0x8E, 0x21, 0x28, 0x60, 0x02, 0x80, 0x00, 0x07, 0x24,
-0x01, 0x00, 0x04, 0x24, 0x01, 0x00, 0x14, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xB4, 0xAF, 0x08, 0x38, 0x43, 0x8E, 0x01, 0x00, 0x04, 0x24,
-0x00, 0x00, 0xC3, 0xAE, 0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x2A, 0x1C, 0x42, 0x92, 0x00, 0x00, 0x00, 0x00, 0xA3, 0xFF, 0x40, 0x14,
-0x2A, 0xB0, 0x02, 0x3C, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x2A, 0x1C, 0x54, 0xA2, 0x02, 0x00, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0x53, 0x00, 0xFF, 0xFF, 0x42, 0x30, 0x25, 0x10, 0x57, 0x00,
-0x02, 0x00, 0x43, 0x94, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x64, 0x30,
-0x00, 0xC0, 0x84, 0x24, 0x2B, 0x1C, 0x43, 0xA2, 0xA3, 0x31, 0x00, 0x0C,
-0xFF, 0xFF, 0x84, 0x30, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x2A, 0xB0, 0x02, 0x3C, 0x09, 0x00, 0x42, 0x34, 0x02, 0x00, 0x03, 0x24,
-0x00, 0x00, 0x54, 0xA0, 0x00, 0x00, 0x43, 0xA0, 0xFF, 0x00, 0x03, 0x24,
-0x91, 0xFF, 0x23, 0x16, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x62, 0x24,
-0xD0, 0x1B, 0x43, 0x8C, 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F,
-0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x00, 0x38, 0x63, 0x34,
-0x41, 0xB0, 0x04, 0x3C, 0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x83, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0x43, 0xAC, 0x00, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x4C, 0x14, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xC0, 0xFF, 0xBD, 0x27, 0x34, 0x00, 0xB7, 0xAF, 0x3C, 0x00, 0xBF, 0xAF,
-0x38, 0x00, 0xBE, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x06, 0x3C,
-0xC0, 0x5D, 0xC5, 0x90, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x18, 0x03, 0x42, 0x34, 0x68, 0x14, 0x63, 0x24, 0x40, 0x00, 0xA4, 0x30,
-0x00, 0x00, 0x43, 0xAC, 0x21, 0xB8, 0x00, 0x00, 0x03, 0x00, 0x80, 0x10,
-0x7F, 0x00, 0xA2, 0x30, 0xBF, 0x00, 0xA2, 0x30, 0x01, 0x00, 0x17, 0x24,
-0xC0, 0x5D, 0xC2, 0xA0, 0x96, 0x40, 0x00, 0x0C, 0x02, 0x80, 0x1E, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x60, 0x1B, 0xD3, 0x27, 0xB0, 0x03, 0x55, 0x34,
-0x59, 0x05, 0x00, 0x08, 0x02, 0x80, 0x16, 0x3C, 0x84, 0x37, 0x91, 0xA2,
-0x60, 0x1B, 0xC2, 0x27, 0xBC, 0x37, 0x46, 0x8C, 0x28, 0x38, 0x45, 0x8C,
-0x03, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x60, 0x1B, 0xD4, 0x27, 0xC0, 0x37, 0x85, 0x8E,
-0x21, 0x20, 0x00, 0x02, 0xD4, 0x02, 0x00, 0x0C, 0x21, 0x30, 0x40, 0x02,
-0x2A, 0xB0, 0x07, 0x3C, 0x0D, 0x00, 0xE2, 0x34, 0x04, 0x00, 0x43, 0x24,
-0x0B, 0x10, 0x77, 0x00, 0x01, 0x00, 0x04, 0x24, 0x02, 0x00, 0x03, 0x24,
-0x00, 0x00, 0x44, 0xA0, 0x00, 0x00, 0x43, 0xA0, 0x0C, 0x5D, 0xC4, 0x96,
-0x25, 0xB0, 0x06, 0x3C, 0x66, 0x03, 0xC5, 0x34, 0x01, 0x00, 0x84, 0x24,
-0x0C, 0x5D, 0xC4, 0xA6, 0x0C, 0x5D, 0xC2, 0x96, 0xFF, 0x00, 0x03, 0x24,
-0x00, 0x00, 0xA2, 0xA4, 0x2F, 0x00, 0x23, 0x12, 0x00, 0x00, 0x00, 0x00,
-0xBC, 0x37, 0x62, 0x8E, 0x28, 0x38, 0x72, 0x8E, 0x03, 0x00, 0x04, 0x24,
-0x00, 0x00, 0xA2, 0xAE, 0xC0, 0x37, 0x62, 0xAE, 0x00, 0x00, 0xB2, 0xAE,
-0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x38, 0x64, 0x8E,
-0x2C, 0x38, 0x63, 0x8E, 0x02, 0x80, 0x02, 0x3C, 0xBC, 0xE6, 0x42, 0x24,
-0x00, 0x00, 0x54, 0x8C, 0x80, 0x00, 0x84, 0x24, 0xFF, 0x00, 0x62, 0x24,
-0x2B, 0x10, 0x44, 0x00, 0x0A, 0x18, 0x82, 0x00, 0x28, 0x38, 0x63, 0xAE,
-0x28, 0x38, 0x82, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xAE,
-0x02, 0x80, 0x03, 0x3C, 0xFF, 0xFF, 0x42, 0x32, 0x25, 0x80, 0x43, 0x00,
-0x00, 0x00, 0xB0, 0xAE, 0x0C, 0x00, 0x02, 0x92, 0x01, 0x00, 0x05, 0x24,
-0x00, 0x00, 0xA2, 0xAE, 0x02, 0x00, 0x04, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x20, 0x92, 0x00, 0xFF, 0xFF, 0x84, 0x30, 0xE0, 0x61, 0x00, 0x0C,
-0x25, 0x20, 0x83, 0x00, 0x0C, 0x00, 0x11, 0x92, 0x20, 0x10, 0x02, 0x3C,
-0xFF, 0x00, 0x03, 0x24, 0x00, 0x22, 0x11, 0x00, 0xC2, 0xFF, 0x23, 0x12,
-0x21, 0x20, 0x82, 0x00, 0xB8, 0xFF, 0xE0, 0x16, 0xBC, 0x37, 0x84, 0xAE,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24, 0x3B, 0x05, 0x00, 0x08,
-0x80, 0x37, 0x51, 0xA0, 0x1E, 0x00, 0xE0, 0x12, 0x40, 0x00, 0xE4, 0x34,
-0x84, 0x37, 0x83, 0x92, 0x41, 0x00, 0xE4, 0x34, 0xB0, 0x03, 0xC5, 0x34,
-0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xA3, 0xAC, 0x96, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0xC5, 0x27, 0xD0, 0x1B, 0xA4, 0x8C, 0x01, 0x00, 0x02, 0x3C,
-0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F,
-0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x00, 0x80, 0x42, 0x34, 0x25, 0x20, 0x82, 0x00,
-0x41, 0xB0, 0x03, 0x3C, 0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x64, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA4, 0xAC, 0x80, 0x37, 0x83, 0x92,
-0xB0, 0x03, 0xC5, 0x34, 0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xA3, 0xAC,
-0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0xC5, 0x27, 0xD0, 0x1B, 0xA4, 0x8C,
-0x01, 0x00, 0x02, 0x3C, 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F,
-0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x00, 0x80, 0x42, 0x34,
-0x25, 0x20, 0x82, 0x00, 0x41, 0xB0, 0x03, 0x3C, 0x40, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0x64, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA4, 0xAC,
-0xC0, 0xFF, 0xBD, 0x27, 0x34, 0x00, 0xB7, 0xAF, 0x3C, 0x00, 0xBF, 0xAF,
-0x38, 0x00, 0xBE, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x06, 0x3C,
-0xC0, 0x5D, 0xC5, 0x90, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x18, 0x03, 0x42, 0x34, 0x08, 0x17, 0x63, 0x24, 0x10, 0x00, 0xA4, 0x30,
-0x00, 0x00, 0x43, 0xAC, 0x21, 0xB8, 0x00, 0x00, 0x03, 0x00, 0x80, 0x10,
-0xDF, 0x00, 0xA2, 0x30, 0xEF, 0x00, 0xA2, 0x30, 0x01, 0x00, 0x17, 0x24,
-0xC0, 0x5D, 0xC2, 0xA0, 0xC0, 0x5D, 0xC3, 0x90, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x02, 0x80, 0x1E, 0x3C,
-0x00, 0x00, 0x43, 0xAC, 0x21, 0xA8, 0x40, 0x00, 0x96, 0x40, 0x00, 0x0C,
-0x60, 0x1B, 0xD3, 0x27, 0x05, 0x06, 0x00, 0x08, 0x02, 0x80, 0x16, 0x3C,
-0x8C, 0x37, 0x91, 0xA2, 0x60, 0x1B, 0xC2, 0x27, 0xC8, 0x37, 0x46, 0x8C,
-0x34, 0x38, 0x45, 0x8C, 0x04, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x60, 0x1B, 0xD4, 0x27,
-0xCC, 0x37, 0x85, 0x8E, 0x21, 0x20, 0x00, 0x02, 0xD4, 0x02, 0x00, 0x0C,
-0x21, 0x30, 0x40, 0x02, 0x2A, 0xB0, 0x07, 0x3C, 0x15, 0x00, 0xE2, 0x34,
-0x04, 0x00, 0x43, 0x24, 0x0B, 0x10, 0x77, 0x00, 0x01, 0x00, 0x04, 0x24,
-0x02, 0x00, 0x03, 0x24, 0x00, 0x00, 0x44, 0xA0, 0x00, 0x00, 0x43, 0xA0,
-0x0C, 0x5D, 0xC4, 0x96, 0x25, 0xB0, 0x06, 0x3C, 0x66, 0x03, 0xC5, 0x34,
-0x01, 0x00, 0x84, 0x24, 0x0C, 0x5D, 0xC4, 0xA6, 0x0C, 0x5D, 0xC2, 0x96,
-0xFF, 0x00, 0x03, 0x24, 0x00, 0x00, 0xA2, 0xA4, 0x2F, 0x00, 0x23, 0x12,
-0x00, 0x00, 0x00, 0x00, 0xC8, 0x37, 0x62, 0x8E, 0x34, 0x38, 0x72, 0x8E,
-0x04, 0x00, 0x04, 0x24, 0x00, 0x00, 0xA2, 0xAE, 0xCC, 0x37, 0x62, 0xAE,
-0x00, 0x00, 0xB2, 0xAE, 0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x34, 0x38, 0x64, 0x8E, 0x38, 0x38, 0x63, 0x8E, 0x02, 0x80, 0x02, 0x3C,
-0xC0, 0xE6, 0x42, 0x24, 0x00, 0x00, 0x54, 0x8C, 0x80, 0x00, 0x84, 0x24,
-0xFF, 0x00, 0x62, 0x24, 0x2B, 0x10, 0x44, 0x00, 0x0A, 0x18, 0x82, 0x00,
-0x34, 0x38, 0x63, 0xAE, 0x34, 0x38, 0x82, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xA2, 0xAE, 0x02, 0x80, 0x03, 0x3C, 0xFF, 0xFF, 0x42, 0x32,
-0x25, 0x80, 0x43, 0x00, 0x00, 0x00, 0xB0, 0xAE, 0x0C, 0x00, 0x02, 0x92,
-0x02, 0x00, 0x05, 0x24, 0x00, 0x00, 0xA2, 0xAE, 0x02, 0x00, 0x04, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x92, 0x00, 0xFF, 0xFF, 0x84, 0x30,
-0xE0, 0x61, 0x00, 0x0C, 0x25, 0x20, 0x83, 0x00, 0x0C, 0x00, 0x11, 0x92,
-0x20, 0x10, 0x02, 0x3C, 0xFF, 0x00, 0x03, 0x24, 0x00, 0x22, 0x11, 0x00,
-0xC2, 0xFF, 0x23, 0x12, 0x21, 0x20, 0x82, 0x00, 0xB8, 0xFF, 0xE0, 0x16,
-0xC8, 0x37, 0x84, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0xE7, 0x05, 0x00, 0x08, 0x88, 0x37, 0x51, 0xA0, 0x1D, 0x00, 0xE0, 0x12,
-0x42, 0x00, 0xE4, 0x34, 0x8C, 0x37, 0x83, 0x92, 0x43, 0x00, 0xE4, 0x34,
-0xB0, 0x03, 0xC5, 0x34, 0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xA3, 0xAC,
-0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0xC5, 0x27, 0xD0, 0x1B, 0xA2, 0x8C,
-0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F,
-0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x06, 0x00, 0x03, 0x3C, 0x25, 0x10, 0x43, 0x00,
-0x41, 0xB0, 0x04, 0x3C, 0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x82, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA2, 0xAC, 0x88, 0x37, 0x83, 0x92,
-0xB0, 0x03, 0xC5, 0x34, 0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xA3, 0xAC,
-0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0xC5, 0x27, 0xD0, 0x1B, 0xA2, 0x8C,
-0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F,
-0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x06, 0x00, 0x03, 0x3C, 0x25, 0x10, 0x43, 0x00,
-0x41, 0xB0, 0x04, 0x3C, 0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x82, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA2, 0xAC, 0xC0, 0xFF, 0xBD, 0x27,
-0x34, 0x00, 0xB7, 0xAF, 0x3C, 0x00, 0xBF, 0xAF, 0x38, 0x00, 0xBE, 0xAF,
-0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF, 0x28, 0x00, 0xB4, 0xAF,
-0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x06, 0x3C, 0xC0, 0x5D, 0xC5, 0x90,
-0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C, 0x18, 0x03, 0x42, 0x34,
-0xB0, 0x19, 0x63, 0x24, 0x01, 0x00, 0xA4, 0x30, 0x00, 0x00, 0x43, 0xAC,
-0x21, 0xB8, 0x00, 0x00, 0x03, 0x00, 0x80, 0x10, 0xF7, 0x00, 0xA2, 0x30,
-0xFE, 0x00, 0xA2, 0x30, 0x01, 0x00, 0x17, 0x24, 0xC0, 0x5D, 0xC2, 0xA0,
-0xC0, 0x5D, 0xC3, 0x90, 0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34,
-0x02, 0x80, 0x1E, 0x3C, 0x00, 0x00, 0x43, 0xAC, 0x21, 0xA8, 0x40, 0x00,
-0x96, 0x40, 0x00, 0x0C, 0x60, 0x1B, 0xD3, 0x27, 0xAE, 0x06, 0x00, 0x08,
-0x02, 0x80, 0x16, 0x3C, 0x9C, 0x37, 0x91, 0xA2, 0x60, 0x1B, 0xC2, 0x27,
-0xD4, 0x37, 0x46, 0x8C, 0x40, 0x38, 0x45, 0x8C, 0x05, 0x00, 0x04, 0x24,
-0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF,
-0x60, 0x1B, 0xD4, 0x27, 0xD8, 0x37, 0x85, 0x8E, 0x21, 0x20, 0x00, 0x02,
-0xD4, 0x02, 0x00, 0x0C, 0x21, 0x30, 0x40, 0x02, 0x2A, 0xB0, 0x07, 0x3C,
-0x1D, 0x00, 0xE2, 0x34, 0x04, 0x00, 0x43, 0x24, 0x0B, 0x10, 0x77, 0x00,
-0x01, 0x00, 0x04, 0x24, 0x02, 0x00, 0x03, 0x24, 0x00, 0x00, 0x44, 0xA0,
-0x00, 0x00, 0x43, 0xA0, 0x0C, 0x5D, 0xC4, 0x96, 0x25, 0xB0, 0x06, 0x3C,
-0x66, 0x03, 0xC5, 0x34, 0x01, 0x00, 0x84, 0x24, 0x0C, 0x5D, 0xC4, 0xA6,
-0x0C, 0x5D, 0xC2, 0x96, 0xFF, 0x00, 0x03, 0x24, 0x00, 0x00, 0xA2, 0xA4,
-0x2F, 0x00, 0x23, 0x12, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x37, 0x62, 0x8E,
-0x40, 0x38, 0x72, 0x8E, 0x05, 0x00, 0x04, 0x24, 0x00, 0x00, 0xA2, 0xAE,
-0xD8, 0x37, 0x62, 0xAE, 0x00, 0x00, 0xB2, 0xAE, 0x5B, 0x01, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x40, 0x38, 0x64, 0x8E, 0x44, 0x38, 0x63, 0x8E,
-0x02, 0x80, 0x02, 0x3C, 0xC4, 0xE6, 0x42, 0x24, 0x00, 0x00, 0x54, 0x8C,
-0x80, 0x00, 0x84, 0x24, 0xFF, 0x00, 0x62, 0x24, 0x2B, 0x10, 0x44, 0x00,
-0x0A, 0x18, 0x82, 0x00, 0x40, 0x38, 0x63, 0xAE, 0x40, 0x38, 0x82, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xAE, 0x02, 0x80, 0x03, 0x3C,
-0xFF, 0xFF, 0x42, 0x32, 0x25, 0x80, 0x43, 0x00, 0x00, 0x00, 0xB0, 0xAE,
-0x0C, 0x00, 0x02, 0x92, 0x08, 0x00, 0x05, 0x24, 0x00, 0x00, 0xA2, 0xAE,
-0x02, 0x00, 0x04, 0x92, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x92, 0x00,
-0xFF, 0xFF, 0x84, 0x30, 0xE0, 0x61, 0x00, 0x0C, 0x25, 0x20, 0x83, 0x00,
-0x0C, 0x00, 0x11, 0x92, 0x20, 0x10, 0x02, 0x3C, 0xFF, 0x00, 0x03, 0x24,
-0x00, 0x22, 0x11, 0x00, 0xC2, 0xFF, 0x23, 0x12, 0x21, 0x20, 0x82, 0x00,
-0xB8, 0xFF, 0xE0, 0x16, 0xD4, 0x37, 0x84, 0xAE, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x42, 0x24, 0x90, 0x06, 0x00, 0x08, 0x90, 0x37, 0x51, 0xA0,
-0x1D, 0x00, 0xE0, 0x12, 0x44, 0x00, 0xE4, 0x34, 0x9C, 0x37, 0x83, 0x92,
-0x45, 0x00, 0xE4, 0x34, 0xB0, 0x03, 0xC5, 0x34, 0x00, 0x00, 0x83, 0xA0,
-0x00, 0x00, 0xA3, 0xAC, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0xC5, 0x27,
-0xD0, 0x1B, 0xA2, 0x8C, 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F,
-0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x18, 0x00, 0x03, 0x3C,
-0x25, 0x10, 0x43, 0x00, 0x41, 0xB0, 0x04, 0x3C, 0x40, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0x82, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA2, 0xAC,
-0x90, 0x37, 0x83, 0x92, 0xB0, 0x03, 0xC5, 0x34, 0x00, 0x00, 0x83, 0xA0,
-0x00, 0x00, 0xA3, 0xAC, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0xC5, 0x27,
-0xD0, 0x1B, 0xA2, 0x8C, 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F,
-0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x18, 0x00, 0x03, 0x3C,
-0x25, 0x10, 0x43, 0x00, 0x41, 0xB0, 0x04, 0x3C, 0x40, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0x82, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA2, 0xAC,
-0xC0, 0xFF, 0xBD, 0x27, 0x34, 0x00, 0xB7, 0xAF, 0x3C, 0x00, 0xBF, 0xAF,
-0x38, 0x00, 0xBE, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x06, 0x3C,
-0xC0, 0x5D, 0xC5, 0x90, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x18, 0x03, 0x42, 0x34, 0x54, 0x1C, 0x63, 0x24, 0x02, 0x00, 0xA4, 0x30,
-0x00, 0x00, 0x43, 0xAC, 0x21, 0xB8, 0x00, 0x00, 0x03, 0x00, 0x80, 0x10,
-0xFB, 0x00, 0xA2, 0x30, 0xFD, 0x00, 0xA2, 0x30, 0x01, 0x00, 0x17, 0x24,
-0xC0, 0x5D, 0xC2, 0xA0, 0xC0, 0x5D, 0xC3, 0x90, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0x02, 0x80, 0x1E, 0x3C, 0x00, 0x00, 0x43, 0xAC,
-0x21, 0xA8, 0x40, 0x00, 0x96, 0x40, 0x00, 0x0C, 0x60, 0x1B, 0xD3, 0x27,
-0x57, 0x07, 0x00, 0x08, 0x02, 0x80, 0x16, 0x3C, 0x98, 0x37, 0x91, 0xA2,
-0x60, 0x1B, 0xC2, 0x27, 0xE0, 0x37, 0x46, 0x8C, 0x4C, 0x38, 0x45, 0x8C,
-0x06, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x60, 0x1B, 0xD4, 0x27, 0xE4, 0x37, 0x85, 0x8E,
-0x21, 0x20, 0x00, 0x02, 0xD4, 0x02, 0x00, 0x0C, 0x21, 0x30, 0x40, 0x02,
-0x2A, 0xB0, 0x07, 0x3C, 0x25, 0x00, 0xE2, 0x34, 0x04, 0x00, 0x43, 0x24,
-0x0B, 0x10, 0x77, 0x00, 0x01, 0x00, 0x04, 0x24, 0x02, 0x00, 0x03, 0x24,
-0x00, 0x00, 0x44, 0xA0, 0x00, 0x00, 0x43, 0xA0, 0x0C, 0x5D, 0xC4, 0x96,
-0x25, 0xB0, 0x06, 0x3C, 0x66, 0x03, 0xC5, 0x34, 0x01, 0x00, 0x84, 0x24,
-0x0C, 0x5D, 0xC4, 0xA6, 0x0C, 0x5D, 0xC2, 0x96, 0xFF, 0x00, 0x03, 0x24,
-0x00, 0x00, 0xA2, 0xA4, 0x2F, 0x00, 0x23, 0x12, 0x00, 0x00, 0x00, 0x00,
-0xE0, 0x37, 0x62, 0x8E, 0x4C, 0x38, 0x72, 0x8E, 0x06, 0x00, 0x04, 0x24,
-0x00, 0x00, 0xA2, 0xAE, 0xE4, 0x37, 0x62, 0xAE, 0x00, 0x00, 0xB2, 0xAE,
-0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x38, 0x64, 0x8E,
-0x50, 0x38, 0x63, 0x8E, 0x02, 0x80, 0x02, 0x3C, 0xC8, 0xE6, 0x42, 0x24,
-0x00, 0x00, 0x54, 0x8C, 0x80, 0x00, 0x84, 0x24, 0xFF, 0x00, 0x62, 0x24,
-0x2B, 0x10, 0x44, 0x00, 0x0A, 0x18, 0x82, 0x00, 0x4C, 0x38, 0x63, 0xAE,
-0x4C, 0x38, 0x82, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xAE,
-0x02, 0x80, 0x03, 0x3C, 0xFF, 0xFF, 0x42, 0x32, 0x25, 0x80, 0x43, 0x00,
-0x00, 0x00, 0xB0, 0xAE, 0x0C, 0x00, 0x02, 0x92, 0x04, 0x00, 0x05, 0x24,
-0x00, 0x00, 0xA2, 0xAE, 0x02, 0x00, 0x04, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x20, 0x92, 0x00, 0xFF, 0xFF, 0x84, 0x30, 0xE0, 0x61, 0x00, 0x0C,
-0x25, 0x20, 0x83, 0x00, 0x0C, 0x00, 0x11, 0x92, 0x20, 0x10, 0x02, 0x3C,
-0xFF, 0x00, 0x03, 0x24, 0x00, 0x22, 0x11, 0x00, 0xC2, 0xFF, 0x23, 0x12,
-0x21, 0x20, 0x82, 0x00, 0xB8, 0xFF, 0xE0, 0x16, 0xE0, 0x37, 0x84, 0xAE,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24, 0x39, 0x07, 0x00, 0x08,
-0x94, 0x37, 0x51, 0xA0, 0x1D, 0x00, 0xE0, 0x12, 0x46, 0x00, 0xE4, 0x34,
-0x98, 0x37, 0x83, 0x92, 0x47, 0x00, 0xE4, 0x34, 0xB0, 0x03, 0xC5, 0x34,
-0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xA3, 0xAC, 0x96, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0xC5, 0x27, 0xD0, 0x1B, 0xA2, 0x8C, 0x3C, 0x00, 0xBF, 0x8F,
-0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
-0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x60, 0x00, 0x03, 0x3C, 0x25, 0x10, 0x43, 0x00, 0x41, 0xB0, 0x04, 0x3C,
-0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x82, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0xD0, 0x1B, 0xA2, 0xAC, 0x94, 0x37, 0x83, 0x92, 0xB0, 0x03, 0xC5, 0x34,
-0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xA3, 0xAC, 0x96, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0xC5, 0x27, 0xD0, 0x1B, 0xA2, 0x8C, 0x3C, 0x00, 0xBF, 0x8F,
-0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
-0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x60, 0x00, 0x03, 0x3C, 0x25, 0x10, 0x43, 0x00, 0x41, 0xB0, 0x04, 0x3C,
-0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x82, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0xD0, 0x1B, 0xA2, 0xAC, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0xF8, 0x1E, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34, 0xE8, 0xFF, 0xBD, 0x27,
-0x00, 0x00, 0x43, 0xAC, 0x10, 0x00, 0xBF, 0xAF, 0x96, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x05, 0x3C, 0x60, 0x1B, 0xA5, 0x24, 0xD8, 0x1B, 0xA2, 0x8C,
-0xD0, 0x1B, 0xA4, 0x8C, 0x00, 0x08, 0x03, 0x3C, 0x10, 0x00, 0xBF, 0x8F,
-0x24, 0x10, 0x43, 0x00, 0x25, 0x20, 0x82, 0x00, 0x41, 0xB0, 0x03, 0x3C,
-0x18, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x64, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0xD0, 0x1B, 0xA4, 0xAC, 0xC0, 0xFF, 0xBD, 0x27, 0x20, 0x00, 0xB0, 0xAF,
-0x00, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x10, 0x3C, 0x18, 0x03, 0x03, 0x36,
-0x58, 0x1F, 0x42, 0x24, 0x00, 0x00, 0x62, 0xAC, 0x34, 0x00, 0xB5, 0xAF,
-0x02, 0x80, 0x15, 0x3C, 0x38, 0x00, 0xBF, 0xAF, 0x2C, 0x00, 0xB3, 0xAF,
-0x28, 0x00, 0xB2, 0xAF, 0x60, 0x1B, 0xB3, 0x26, 0x24, 0x00, 0xB1, 0xAF,
-0x96, 0x40, 0x00, 0x0C, 0x30, 0x00, 0xB4, 0xAF, 0xFC, 0x00, 0x02, 0x36,
-0x00, 0x00, 0x45, 0x8C, 0xAC, 0x1B, 0x64, 0x96, 0xCC, 0x38, 0x63, 0x96,
-0xC4, 0x38, 0x66, 0x8E, 0x23, 0x28, 0xA4, 0x00, 0x21, 0x10, 0xA3, 0x00,
-0x23, 0x88, 0x46, 0x00, 0x23, 0x20, 0x23, 0x02, 0xB0, 0x03, 0x10, 0x36,
-0x2B, 0x10, 0x71, 0x00, 0x00, 0x00, 0x03, 0xAE, 0x00, 0x00, 0x11, 0xAE,
-0x0B, 0x88, 0x82, 0x00, 0x21, 0x20, 0x20, 0x02, 0x53, 0x21, 0x00, 0x0C,
-0xC8, 0x38, 0x65, 0xAE, 0x21, 0x90, 0x40, 0x00, 0x4D, 0x00, 0x40, 0x10,
-0x18, 0x00, 0xA4, 0x27, 0x0C, 0x00, 0x51, 0xAC, 0xC4, 0x38, 0x68, 0x8E,
-0xC8, 0x38, 0x62, 0x8E, 0x08, 0x00, 0x45, 0x8E, 0x20, 0xBD, 0x03, 0x3C,
-0x88, 0x03, 0x63, 0x34, 0x2B, 0x10, 0x48, 0x00, 0x40, 0x10, 0x14, 0x3C,
-0x21, 0x20, 0x00, 0x00, 0xFF, 0xFF, 0x27, 0x32, 0x00, 0x00, 0x65, 0xAC,
-0x2A, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x1B, 0x66, 0x96,
-0x08, 0x00, 0x42, 0x96, 0x40, 0x10, 0x05, 0x3C, 0x21, 0x20, 0x00, 0x00,
-0x21, 0x30, 0x06, 0x01, 0x25, 0x28, 0x45, 0x00, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0x18, 0x00, 0xA4, 0x27,
-0x02, 0x80, 0x02, 0x3C, 0x88, 0x54, 0x42, 0x24, 0x04, 0x00, 0x43, 0x8C,
-0x00, 0x00, 0x42, 0xAE, 0x04, 0x00, 0x52, 0xAC, 0x21, 0x20, 0x00, 0x00,
-0x00, 0x00, 0x72, 0xAC, 0x5B, 0x01, 0x00, 0x0C, 0x04, 0x00, 0x43, 0xAE,
-0x60, 0x1B, 0xA5, 0x26, 0xC8, 0x38, 0xA6, 0x8C, 0xAC, 0x1B, 0xA3, 0x94,
-0x25, 0xB0, 0x02, 0x3C, 0xF8, 0x00, 0x42, 0x34, 0x21, 0x18, 0xC3, 0x00,
-0x00, 0x00, 0x43, 0xAC, 0x18, 0x00, 0xA4, 0x27, 0xC4, 0x38, 0xA6, 0xAC,
-0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xBF, 0x8F, 0x34, 0x00, 0xB5, 0x8F,
-0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB2, 0x8F,
-0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x40, 0x00, 0xBD, 0x27, 0xCC, 0x38, 0x70, 0x8E, 0x08, 0x00, 0x45, 0x96,
-0xAC, 0x1B, 0x66, 0x96, 0x23, 0x80, 0x08, 0x02, 0xFF, 0xFF, 0x10, 0x32,
-0x21, 0x30, 0x06, 0x01, 0x25, 0x28, 0xB4, 0x00, 0x21, 0x38, 0x00, 0x02,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x5B, 0x01, 0x00, 0x0C,
-0x21, 0x20, 0x00, 0x00, 0x08, 0x00, 0x45, 0x96, 0xAC, 0x1B, 0x62, 0x96,
-0x23, 0x38, 0x30, 0x02, 0x25, 0x28, 0xB4, 0x00, 0x21, 0x10, 0x06, 0x3C,
-0x21, 0x28, 0xB0, 0x00, 0x21, 0x30, 0x46, 0x00, 0xFF, 0xFF, 0xE7, 0x30,
-0x0D, 0x08, 0x00, 0x08, 0x21, 0x20, 0x00, 0x00, 0x8A, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C, 0xC4, 0x5D, 0x62, 0x8C,
-0x18, 0x00, 0xA4, 0x27, 0x08, 0x00, 0x42, 0x34, 0x23, 0x08, 0x00, 0x08,
-0xC4, 0x5D, 0x62, 0xAC, 0x25, 0xB0, 0x05, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0xC0, 0xFF, 0xBD, 0x27, 0x18, 0x03, 0xA4, 0x34, 0x38, 0x21, 0x42, 0x24,
-0x2A, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x82, 0xAC, 0x3C, 0x00, 0xBF, 0xAF,
-0x38, 0x00, 0xBE, 0xAF, 0x34, 0x00, 0xB7, 0xAF, 0x30, 0x00, 0xB6, 0xAF,
-0x2C, 0x00, 0xB5, 0xAF, 0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF,
-0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF,
-0x2C, 0x00, 0x63, 0x34, 0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x02, 0x24,
-0xFF, 0x00, 0x24, 0x31, 0x48, 0x00, 0x82, 0x10, 0x00, 0x80, 0x22, 0x31,
-0x37, 0x00, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24, 0x14, 0x00, 0x82, 0x10,
-0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x70, 0x24, 0xFF, 0x00, 0x23, 0x31,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x7C, 0x38, 0x05, 0x8E, 0x25, 0xB0, 0x02, 0x3C, 0xFF, 0x00, 0x28, 0x31,
-0x7C, 0x03, 0x42, 0x34, 0x00, 0x00, 0x48, 0xA4, 0x21, 0x30, 0x60, 0x00,
-0x10, 0x38, 0x03, 0xAE, 0xAC, 0x37, 0x09, 0xA2, 0x0A, 0x00, 0x04, 0x24,
-0x00, 0x01, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF,
-0x01, 0x00, 0x03, 0x24, 0x84, 0x38, 0x03, 0xA2, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x50, 0x24, 0x84, 0x38, 0x03, 0x92, 0x01, 0x00, 0x02, 0x24,
-0x31, 0x00, 0x62, 0x10, 0x02, 0x80, 0x04, 0x3C, 0x60, 0x1B, 0x90, 0x24,
-0x85, 0x38, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x10,
-0x00, 0x04, 0x03, 0x3C, 0xD8, 0x1B, 0x02, 0x8E, 0xD0, 0x1B, 0x04, 0x8E,
-0x24, 0x10, 0x43, 0x00, 0x25, 0x20, 0x82, 0x00, 0x41, 0xB0, 0x03, 0x3C,
-0x00, 0x00, 0x64, 0xAC, 0xD0, 0x1B, 0x04, 0xAE, 0x3C, 0x00, 0xBF, 0x8F,
-0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
-0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x40, 0x00, 0xBD, 0x27, 0x24, 0x10, 0x22, 0x01,
-0xCB, 0xFF, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x43, 0x24, 0xAC, 0x37, 0x62, 0x90, 0x20, 0xB0, 0x03, 0x3C,
-0xB0, 0x03, 0xA4, 0x34, 0x00, 0x12, 0x02, 0x00, 0x21, 0x10, 0x43, 0x00,
-0x0C, 0x00, 0x49, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0xAC,
-0x69, 0x08, 0x00, 0x08, 0xFF, 0x00, 0x24, 0x31, 0x02, 0x80, 0x04, 0x3C,
-0x60, 0x1B, 0x82, 0x24, 0x84, 0x38, 0x40, 0xA0, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x50, 0x24, 0x84, 0x38, 0x03, 0x92, 0x01, 0x00, 0x02, 0x24,
-0xD1, 0xFF, 0x62, 0x14, 0x00, 0x00, 0x00, 0x00, 0x96, 0x40, 0x00, 0x0C,
-0x21, 0x88, 0x00, 0x02, 0x25, 0xB0, 0x02, 0x3C, 0x2A, 0xB0, 0x03, 0x3C,
-0x2C, 0x00, 0x7E, 0x34, 0x02, 0x80, 0x17, 0x3C, 0xB0, 0x03, 0x56, 0x34,
-0x01, 0x00, 0x13, 0x24, 0x21, 0xA0, 0x00, 0x02, 0x21, 0xA8, 0x00, 0x02,
-0x7C, 0x38, 0x30, 0x8E, 0x0A, 0x00, 0x04, 0x24, 0x00, 0x00, 0xD0, 0xAE,
-0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0xFF, 0xFF, 0x08, 0x32, 0x25, 0x80, 0x02, 0x01, 0xC2, 0x5C, 0xE3, 0x92,
-0x02, 0x00, 0x04, 0x92, 0x02, 0x00, 0x02, 0x24, 0x0F, 0x00, 0x63, 0x30,
-0x52, 0x00, 0x62, 0x10, 0x21, 0x38, 0x04, 0x02, 0x20, 0x00, 0x02, 0x24,
-0x54, 0x00, 0x82, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x54, 0xF5, 0x47, 0xAC,
-0x02, 0x00, 0xE2, 0x90, 0x85, 0x38, 0x84, 0x92, 0x03, 0x00, 0xE3, 0x90,
-0xFF, 0x00, 0x52, 0x30, 0x01, 0x00, 0x02, 0x24, 0x21, 0x28, 0xE0, 0x00,
-0x7F, 0x00, 0x66, 0x30, 0x08, 0x00, 0xE7, 0x24, 0x57, 0x00, 0x82, 0x10,
-0x02, 0x80, 0x09, 0x3C, 0x0E, 0x00, 0x02, 0x24, 0x51, 0x00, 0x42, 0x12,
-0x37, 0x00, 0x02, 0x24, 0x4F, 0x00, 0x42, 0x12, 0x10, 0x00, 0x02, 0x24,
-0x4E, 0x00, 0x42, 0x12, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0x38, 0xD7, 0x42, 0x24, 0xC0, 0x18, 0x12, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x34, 0xD7, 0x26, 0xA1, 0x04, 0x00, 0x62, 0x8C, 0x02, 0x80, 0x03, 0x3C,
-0x21, 0x20, 0xE0, 0x00, 0x09, 0xF8, 0x40, 0x00, 0x4C, 0xF5, 0x62, 0xAC,
-0x03, 0x00, 0x40, 0x10, 0x39, 0x00, 0x02, 0x24, 0x3B, 0x00, 0x42, 0x12,
-0x00, 0x00, 0x00, 0x00, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x85, 0x38, 0x33, 0xA2, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x39, 0x00, 0x02, 0x24, 0x03, 0x00, 0x42, 0x12, 0x02, 0x00, 0x02, 0x24,
-0x01, 0x00, 0xD3, 0xA3, 0x01, 0x00, 0xC2, 0xA3, 0x85, 0x38, 0xA3, 0x92,
-0x01, 0x00, 0x02, 0x24, 0x42, 0x00, 0x62, 0x14, 0xFF, 0x00, 0x02, 0x24,
-0x0C, 0x00, 0x03, 0x92, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x68, 0x30,
-0x3E, 0x00, 0x02, 0x11, 0x02, 0x80, 0x02, 0x3C, 0xAC, 0x37, 0xA3, 0xA2,
-0xAC, 0x37, 0x22, 0x92, 0x7C, 0x38, 0x25, 0x8E, 0x20, 0x10, 0x03, 0x3C,
-0x00, 0x12, 0x02, 0x00, 0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0xC8, 0xAE,
-0x21, 0x30, 0x40, 0x00, 0x10, 0x38, 0x22, 0xAE, 0x0A, 0x00, 0x04, 0x24,
-0x00, 0x01, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF,
-0x7C, 0x38, 0x30, 0x8E, 0x0A, 0x00, 0x04, 0x24, 0x00, 0x00, 0xD0, 0xAE,
-0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0xFF, 0xFF, 0x08, 0x32, 0x25, 0x80, 0x02, 0x01, 0xC2, 0x5C, 0xE3, 0x92,
-0x02, 0x00, 0x04, 0x92, 0x02, 0x00, 0x02, 0x24, 0x0F, 0x00, 0x63, 0x30,
-0xB0, 0xFF, 0x62, 0x14, 0x21, 0x38, 0x04, 0x02, 0x00, 0x00, 0x02, 0x8E,
-0x00, 0x0C, 0x03, 0x3C, 0x24, 0x10, 0x43, 0x00, 0xAE, 0xFF, 0x43, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x95, 0x58, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x7A, 0x37, 0x22, 0x96, 0x85, 0x38, 0x33, 0xA2, 0x01, 0x00, 0x42, 0x24,
-0xF5, 0x08, 0x00, 0x08, 0x7A, 0x37, 0x22, 0xA6, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xF3, 0x08, 0x00, 0x08, 0x85, 0x38, 0x20, 0xA2,
-0x02, 0x80, 0x02, 0x3C, 0xE2, 0x08, 0x00, 0x08, 0x25, 0x38, 0x02, 0x01,
-0x34, 0xD7, 0x22, 0x91, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x42, 0x30,
-0x13, 0x00, 0xC2, 0x10, 0x25, 0xB0, 0x04, 0x3C, 0x6A, 0x37, 0x82, 0x96,
-0x1E, 0x03, 0x84, 0x34, 0x10, 0x00, 0x42, 0x34, 0x3B, 0x00, 0x43, 0x2E,
-0x00, 0x00, 0x82, 0xA4, 0x9F, 0xFF, 0x60, 0x14, 0x6A, 0x37, 0x82, 0xA6,
-0xF6, 0x08, 0x00, 0x08, 0x39, 0x00, 0x02, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0xB0, 0x5D, 0x44, 0x8C, 0x25, 0xB0, 0x03, 0x3C, 0xB0, 0x03, 0x63, 0x34,
-0x00, 0x00, 0x64, 0xAC, 0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x85, 0x08, 0x00, 0x08, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x00, 0xA5, 0x90,
-0x34, 0xD7, 0x27, 0x91, 0x02, 0x80, 0x04, 0x3C, 0xCC, 0xE6, 0x84, 0x24,
-0xFF, 0x00, 0xA5, 0x30, 0x13, 0x58, 0x00, 0x0C, 0xFF, 0x00, 0xE7, 0x30,
-0xF6, 0x08, 0x00, 0x08, 0x39, 0x00, 0x02, 0x24, 0xC0, 0xFF, 0xBD, 0x27,
-0x34, 0x00, 0xB7, 0xAF, 0x02, 0x80, 0x02, 0x3C, 0x21, 0xB8, 0xA0, 0x00,
-0xFF, 0xFF, 0xA5, 0x30, 0x25, 0x40, 0xA2, 0x00, 0x20, 0x00, 0xB2, 0xAF,
-0x38, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x03, 0x8D, 0xFF, 0xFF, 0xD2, 0x30,
-0x08, 0x00, 0x45, 0x26, 0x00, 0xC0, 0x02, 0x24, 0x04, 0x00, 0x06, 0x8D,
-0x24, 0x18, 0x62, 0x00, 0xFF, 0x3F, 0xA5, 0x30, 0xF0, 0xFF, 0x02, 0x3C,
-0x25, 0x18, 0x65, 0x00, 0xFF, 0xFF, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00,
-0x00, 0x80, 0x05, 0x3C, 0x25, 0x18, 0x65, 0x00, 0xFF, 0x01, 0xC6, 0x34,
-0x00, 0x00, 0x03, 0xAD, 0x04, 0x00, 0x06, 0xAD, 0x21, 0x48, 0x80, 0x00,
-0xFF, 0xFF, 0xE7, 0x30, 0x18, 0x00, 0x06, 0x25, 0x18, 0x00, 0x12, 0xA5,
-0x02, 0x00, 0xC7, 0xA0, 0x18, 0x00, 0x03, 0x8D, 0xFF, 0x7F, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00, 0x02, 0x80, 0x16, 0x3C,
-0x18, 0x00, 0x03, 0xAD, 0x60, 0x1B, 0xC5, 0x26, 0x66, 0x37, 0xA4, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x82, 0x24, 0x66, 0x37, 0xA2, 0xA0,
-0x18, 0x00, 0x03, 0x8D, 0xFF, 0x80, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x7F, 0x00, 0x84, 0x30, 0x00, 0x26, 0x04, 0x00, 0x24, 0x18, 0x62, 0x00,
-0x25, 0x18, 0x64, 0x00, 0x18, 0x00, 0x03, 0xAD, 0x02, 0x80, 0x02, 0x3C,
-0xC2, 0x5C, 0x44, 0x90, 0x20, 0x00, 0x43, 0x26, 0xFF, 0xFF, 0x72, 0x30,
-0x02, 0x00, 0x84, 0x30, 0x04, 0x00, 0x80, 0x10, 0x21, 0x18, 0x40, 0x02,
-0x1F, 0x00, 0x42, 0x32, 0x5C, 0x00, 0x40, 0x10, 0x08, 0x00, 0x42, 0x26,
-0xFF, 0xFF, 0x63, 0x30, 0x5D, 0x00, 0x43, 0x12, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0xC2, 0x8C, 0x21, 0x90, 0x60, 0x00, 0x00, 0xC0, 0x04, 0x24,
-0x01, 0x00, 0x42, 0x34, 0x04, 0x00, 0xC2, 0xAC, 0x00, 0x00, 0x03, 0x8D,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0x62, 0x30, 0x08, 0x00, 0x42, 0x24,
-0x24, 0x18, 0x64, 0x00, 0xFF, 0x3F, 0x42, 0x30, 0x25, 0x18, 0x62, 0x00,
-0x00, 0x00, 0x03, 0xAD, 0x25, 0xB0, 0x02, 0x3C, 0xC0, 0x00, 0x42, 0x34,
-0x07, 0x00, 0x43, 0x32, 0x00, 0x00, 0x52, 0xA4, 0x03, 0x00, 0x60, 0x10,
-0xF8, 0xFF, 0x53, 0x32, 0x08, 0x00, 0x42, 0x26, 0xF8, 0xFF, 0x53, 0x30,
-0x60, 0x1B, 0xD5, 0x26, 0xEC, 0x38, 0xA6, 0x8E, 0xF0, 0x38, 0xB0, 0x8E,
-0x21, 0x10, 0xD3, 0x00, 0x2B, 0x10, 0x02, 0x02, 0x32, 0x00, 0x40, 0x10,
-0xFF, 0x00, 0x34, 0x31, 0x23, 0x80, 0x06, 0x02, 0x21, 0x28, 0xE0, 0x02,
-0xFF, 0xFF, 0x07, 0x32, 0x01, 0x00, 0x11, 0x24, 0x21, 0x20, 0x80, 0x02,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xB1, 0xAF, 0x23, 0x18, 0x70, 0x02,
-0xFF, 0xFF, 0x72, 0x30, 0x22, 0x10, 0x02, 0x3C, 0x21, 0x10, 0x42, 0x02,
-0x21, 0x20, 0x80, 0x02, 0x5B, 0x01, 0x00, 0x0C, 0xEC, 0x38, 0xA2, 0xAE,
-0x21, 0x28, 0xF0, 0x02, 0x21, 0x38, 0x40, 0x02, 0x21, 0x20, 0x80, 0x02,
-0x22, 0x10, 0x06, 0x3C, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xB1, 0xAF,
-0x60, 0x1B, 0xD1, 0x26, 0xEC, 0x38, 0x23, 0x8E, 0x25, 0xB0, 0x10, 0x3C,
-0xB0, 0x03, 0x02, 0x36, 0x21, 0x20, 0x80, 0x02, 0x00, 0x00, 0x43, 0xAC,
-0x5B, 0x01, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x38, 0x25, 0x8E,
-0xEC, 0x00, 0x02, 0x36, 0xBD, 0x00, 0x04, 0x36, 0x00, 0x00, 0x45, 0xAC,
-0x00, 0x00, 0x83, 0x90, 0xC2, 0x00, 0x10, 0x36, 0x38, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0x63, 0x34, 0x00, 0x00, 0x83, 0xA0, 0x34, 0x00, 0xB7, 0x8F,
-0x00, 0x00, 0x05, 0xA6, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x02, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x40, 0x00, 0xBD, 0x27, 0x01, 0x00, 0x02, 0x24,
-0x21, 0x28, 0xE0, 0x02, 0x21, 0x20, 0x80, 0x02, 0x21, 0x38, 0x60, 0x02,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF, 0xEC, 0x38, 0xA3, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x73, 0x00, 0xC4, 0x09, 0x00, 0x08,
-0xEC, 0x38, 0xA3, 0xAE, 0xFF, 0xFF, 0x43, 0x30, 0xFF, 0xFF, 0x63, 0x30,
-0xA5, 0xFF, 0x43, 0x16, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xC2, 0x8C,
-0xFE, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00, 0xA1, 0x09, 0x00, 0x08,
-0x04, 0x00, 0xC2, 0xAC, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0x21, 0x80, 0x80, 0x00, 0x1C, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x14, 0x00, 0x03, 0x8E, 0x16, 0x00, 0x02, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x0A, 0x00, 0x62, 0x10, 0x08, 0x00, 0x06, 0x24,
-0x08, 0x00, 0x02, 0x96, 0x02, 0x80, 0x04, 0x3C, 0xEC, 0x54, 0x00, 0x0C,
-0x25, 0x20, 0x44, 0x00, 0x08, 0x00, 0x05, 0x8E, 0x0C, 0x00, 0x06, 0x96,
-0x14, 0x00, 0x07, 0x96, 0x51, 0x09, 0x00, 0x0C, 0x09, 0x00, 0x04, 0x24,
-0x04, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x02, 0x8E, 0x21, 0x20, 0x00, 0x02,
-0x00, 0x00, 0x62, 0xAC, 0x04, 0x00, 0x43, 0xAC, 0x00, 0x00, 0x10, 0xAE,
-0x74, 0x21, 0x00, 0x0C, 0x04, 0x00, 0x10, 0xAE, 0x90, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x1C, 0x00, 0xBF, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x25, 0xB0, 0x02, 0x3C,
-0xBF, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x63, 0x2C, 0x05, 0x00, 0x60, 0x10, 0x02, 0x80, 0x05, 0x3C,
-0x90, 0x54, 0xA3, 0x8C, 0x90, 0x54, 0xA2, 0x24, 0x0D, 0x00, 0x62, 0x10,
-0x21, 0x20, 0x00, 0x02, 0x90, 0x54, 0xA2, 0x24, 0x04, 0x00, 0x43, 0x8C,
-0x00, 0x00, 0x02, 0xAE, 0x04, 0x00, 0x50, 0xAC, 0x00, 0x00, 0x70, 0xAC,
-0x04, 0x00, 0x03, 0xAE, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xF5, 0x09, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xD8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x08, 0xE7, 0x84, 0x24, 0x24, 0x00, 0xBF, 0xAF,
-0x20, 0x00, 0xB2, 0xAF, 0x13, 0x58, 0x00, 0x0C, 0x1C, 0x00, 0xB1, 0xAF,
-0x00, 0x00, 0x04, 0x96, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x83, 0x24,
-0x07, 0x00, 0x62, 0x30, 0x6A, 0x00, 0x40, 0x10, 0xC2, 0x10, 0x03, 0x00,
-0x28, 0x00, 0x82, 0x24, 0xC2, 0x10, 0x02, 0x00, 0x53, 0x21, 0x00, 0x0C,
-0xC0, 0x20, 0x02, 0x00, 0x68, 0x00, 0x40, 0x10, 0x21, 0x88, 0x40, 0x00,
-0x02, 0x80, 0x12, 0x3C, 0x02, 0x00, 0x06, 0x92, 0x60, 0x1B, 0x50, 0x26,
-0x10, 0x38, 0x05, 0x8E, 0x08, 0x00, 0xC6, 0x24, 0x0A, 0x00, 0x04, 0x24,
-0x72, 0x01, 0x00, 0x0C, 0x21, 0x38, 0x40, 0x00, 0xB0, 0x1B, 0x03, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x30, 0x67, 0x00, 0x40, 0x14,
-0x01, 0x00, 0x62, 0x30, 0x02, 0x80, 0x02, 0x3C, 0x4B, 0xF5, 0x43, 0x90,
-0x60, 0x1B, 0x50, 0x26, 0x10, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0xE8, 0x39, 0x00, 0xAE, 0x04, 0x3A, 0x00, 0xAE, 0xFC, 0x40, 0x00, 0xAE,
-0xBC, 0x40, 0x00, 0xAE, 0xC6, 0x40, 0x00, 0xA2, 0x8A, 0x40, 0x00, 0x0C,
-0xC6, 0x5C, 0x43, 0xA0, 0xA3, 0x6A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x87, 0x6B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x90, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x02, 0x3C, 0xD2, 0x5C, 0x48, 0x90,
-0x25, 0xB0, 0x04, 0x3C, 0x2F, 0x00, 0x02, 0x3C, 0xD0, 0x01, 0x85, 0x34,
-0x17, 0x32, 0x42, 0x34, 0x00, 0x00, 0xA2, 0xAC, 0x5E, 0x00, 0x03, 0x3C,
-0x10, 0x00, 0x02, 0x3C, 0xDC, 0x01, 0x87, 0x34, 0xD4, 0x01, 0x86, 0x34,
-0x17, 0x43, 0x63, 0x34, 0x20, 0x53, 0x42, 0x34, 0xD8, 0x01, 0x84, 0x34,
-0x00, 0x00, 0xC3, 0xAC, 0x00, 0x00, 0x82, 0xAC, 0x44, 0xA4, 0x03, 0x34,
-0x01, 0x00, 0x02, 0x24, 0x00, 0x00, 0xE3, 0xAC, 0x52, 0x00, 0x02, 0x11,
-0xFF, 0xF7, 0x03, 0x24, 0xFC, 0x23, 0x02, 0x8E, 0xFF, 0xEF, 0x04, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x24, 0x10, 0x44, 0x00, 0xFC, 0x23, 0x02, 0xAE,
-0x60, 0x1B, 0x42, 0x8E, 0xDF, 0xFF, 0x03, 0x24, 0xFB, 0xFF, 0x04, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x24, 0x10, 0x44, 0x00, 0xFE, 0xFF, 0x03, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x50, 0x0C, 0x04, 0x24, 0x60, 0x1B, 0x50, 0x26,
-0x30, 0x5C, 0x00, 0x0C, 0x60, 0x1B, 0x42, 0xAE, 0x38, 0x3E, 0x02, 0xA2,
-0x30, 0x5C, 0x00, 0x0C, 0x58, 0x0C, 0x04, 0x24, 0x39, 0x3E, 0x02, 0xA2,
-0x50, 0x0C, 0x04, 0x24, 0x1A, 0x5C, 0x00, 0x0C, 0x17, 0x00, 0x05, 0x24,
-0x17, 0x00, 0x05, 0x24, 0x1A, 0x5C, 0x00, 0x0C, 0x58, 0x0C, 0x04, 0x24,
-0x5B, 0x01, 0x00, 0x0C, 0x0A, 0x00, 0x04, 0x24, 0x08, 0x00, 0x22, 0x96,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x04, 0x3C, 0x25, 0x28, 0x45, 0x00,
-0x74, 0x03, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0xB0, 0x55, 0x84, 0x24,
-0x74, 0x21, 0x00, 0x0C, 0x21, 0x20, 0x20, 0x02, 0x98, 0x3A, 0x02, 0x8E,
-0x49, 0x4B, 0x00, 0x0C, 0xC4, 0x3D, 0x02, 0xA2, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x53, 0x21, 0x00, 0x0C, 0xC0, 0x20, 0x02, 0x00, 0x9A, 0xFF, 0x40, 0x14,
-0x21, 0x88, 0x40, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x18, 0xE7, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0xFC, 0xE6, 0xA5, 0x24,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0x20, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x87, 0x54, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x05, 0x3C,
-0x4C, 0x00, 0xA2, 0x34, 0x00, 0x00, 0x40, 0xA0, 0x48, 0x00, 0xA5, 0x34,
-0xB0, 0x1B, 0x03, 0x96, 0x00, 0x00, 0xA4, 0x8C, 0x7B, 0xFF, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x82, 0x00, 0xFF, 0xFE, 0x63, 0x30,
-0xB0, 0x1B, 0x03, 0xA6, 0x00, 0x00, 0xA4, 0xAC, 0x5F, 0x0A, 0x00, 0x08,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0xD3, 0x5C, 0x44, 0x90,
-0x02, 0x00, 0x03, 0x24, 0x06, 0x00, 0x83, 0x10, 0xFF, 0xF7, 0x03, 0x24,
-0xFC, 0x23, 0x02, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x43, 0x00,
-0x89, 0x0A, 0x00, 0x08, 0x00, 0x10, 0x42, 0x34, 0xFC, 0x23, 0x02, 0x8E,
-0xFF, 0xEF, 0x03, 0x24, 0x00, 0x08, 0x42, 0x34, 0x89, 0x0A, 0x00, 0x08,
-0x24, 0x10, 0x43, 0x00, 0x02, 0x80, 0x04, 0x3C, 0xB4, 0x55, 0x84, 0x24,
-0x1C, 0x4F, 0x00, 0x0C, 0x03, 0x00, 0x05, 0x24, 0xC6, 0x0A, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x00, 0x00, 0x84, 0x90, 0x02, 0x80, 0x06, 0x3C, 0x01, 0x00, 0x02, 0x24,
-0xFF, 0x00, 0x83, 0x30, 0x0C, 0x00, 0x62, 0x10, 0x60, 0x1B, 0xC5, 0x24,
-0x04, 0x00, 0x02, 0x24, 0x13, 0x00, 0x62, 0x10, 0x60, 0x1B, 0xC2, 0x24,
-0xC6, 0x3D, 0x45, 0x90, 0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C,
-0x24, 0xE7, 0x84, 0x24, 0x10, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xC6, 0x3D, 0xA4, 0xA0,
-0x60, 0x1B, 0xC2, 0x24, 0xC6, 0x3D, 0x45, 0x90, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0x24, 0xE7, 0x84, 0x24, 0x10, 0x00, 0xBF, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0x60, 0x1B, 0xC3, 0x24, 0xB0, 0x1B, 0x62, 0x94, 0xC6, 0x3D, 0x64, 0xA0,
-0x02, 0x80, 0x04, 0x3C, 0x04, 0x00, 0x42, 0x34, 0xB0, 0x1B, 0x62, 0xA4,
-0x60, 0x1B, 0xC2, 0x24, 0xC6, 0x3D, 0x45, 0x90, 0x13, 0x58, 0x00, 0x0C,
-0x24, 0xE7, 0x84, 0x24, 0x10, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xD0, 0xFF, 0xBD, 0x27,
-0x20, 0x00, 0xB2, 0xAF, 0x02, 0x80, 0x12, 0x3C, 0x24, 0x00, 0xB3, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x2C, 0x00, 0xBF, 0xAF, 0x28, 0x00, 0xB4, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0x51, 0x26, 0xB0, 0x1B, 0x22, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x42, 0x30, 0x0A, 0x00, 0x40, 0x10,
-0x21, 0x98, 0x80, 0x00, 0x2C, 0x00, 0xBF, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x30, 0x00, 0xBD, 0x27, 0x10, 0x00, 0xA4, 0x27, 0x8A, 0x40, 0x00, 0x0C,
-0x02, 0x80, 0x14, 0x3C, 0xEE, 0x5D, 0x82, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x28, 0x89, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x60, 0x1B, 0x42, 0x8E, 0xDF, 0xFF, 0x03, 0x24, 0xFB, 0xFF, 0x04, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x24, 0x10, 0x44, 0x00, 0xFE, 0xFF, 0x03, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x50, 0x0C, 0x04, 0x24, 0x30, 0x5C, 0x00, 0x0C,
-0x60, 0x1B, 0x42, 0xAE, 0x38, 0x3E, 0x22, 0xA2, 0x30, 0x5C, 0x00, 0x0C,
-0x58, 0x0C, 0x04, 0x24, 0x39, 0x3E, 0x22, 0xA2, 0x50, 0x0C, 0x04, 0x24,
-0x1A, 0x5C, 0x00, 0x0C, 0x17, 0x00, 0x05, 0x24, 0x17, 0x00, 0x05, 0x24,
-0x1A, 0x5C, 0x00, 0x0C, 0x58, 0x0C, 0x04, 0x24, 0xB0, 0x1B, 0x22, 0x96,
-0x02, 0x80, 0x04, 0x3C, 0x34, 0xE7, 0x84, 0x24, 0x00, 0x10, 0x42, 0x34,
-0x13, 0x58, 0x00, 0x0C, 0xB0, 0x1B, 0x22, 0xA6, 0x01, 0x00, 0x02, 0x24,
-0x25, 0xB0, 0x03, 0x3C, 0x04, 0x3E, 0x22, 0xAE, 0x4C, 0x00, 0x63, 0x34,
-0xB0, 0x1B, 0x22, 0x96, 0x00, 0x00, 0x66, 0x90, 0x08, 0x00, 0x65, 0x8E,
-0xC4, 0x3D, 0x27, 0x92, 0xC5, 0x3D, 0x28, 0x92, 0x3B, 0x41, 0x29, 0x92,
-0xD0, 0x3D, 0x2A, 0x92, 0xFF, 0x3D, 0x2B, 0x92, 0x00, 0x80, 0x42, 0x30,
-0x37, 0x3E, 0x26, 0xA2, 0x0C, 0x3E, 0x25, 0xAE, 0x10, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x60, 0xA0, 0x31, 0x3E, 0x27, 0xA2, 0x32, 0x3E, 0x28, 0xA2,
-0x34, 0x3E, 0x22, 0xA6, 0x36, 0x3E, 0x29, 0xA2, 0xC4, 0x3D, 0x2A, 0xA2,
-0xC5, 0x3D, 0x2B, 0xA2, 0x3C, 0x3E, 0x20, 0xAE, 0x40, 0x3E, 0x20, 0xAE,
-0x8A, 0x40, 0x00, 0x0C, 0x33, 0x3E, 0x20, 0xA2, 0x10, 0x00, 0xA4, 0x27,
-0x90, 0x40, 0x00, 0x0C, 0x52, 0x41, 0x20, 0xA2, 0x21, 0x20, 0x00, 0x00,
-0x95, 0x0E, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x08, 0x00, 0x66, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xC0, 0x14, 0x0C, 0x00, 0x70, 0x26,
-0x00, 0x00, 0x62, 0x8E, 0x21, 0x20, 0x20, 0x02, 0x44, 0x3E, 0x23, 0x26,
-0x08, 0x3E, 0x22, 0xAE, 0x3F, 0x00, 0x02, 0x24, 0xFF, 0xFF, 0x42, 0x24,
-0x00, 0x00, 0x60, 0xA0, 0xFD, 0xFF, 0x41, 0x04, 0x07, 0x00, 0x63, 0x24,
-0xB0, 0x1B, 0x83, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x30,
-0x09, 0x00, 0x40, 0x10, 0x60, 0x1B, 0x50, 0x26, 0x01, 0x00, 0x62, 0x30,
-0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x5D, 0x82, 0x92,
-0x0C, 0x00, 0x03, 0x24, 0x0F, 0x00, 0x42, 0x30, 0x37, 0x00, 0x43, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xC4, 0x3D, 0x04, 0x92, 0x75, 0x0D, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xC4, 0x3D, 0x04, 0x92, 0x38, 0x0D, 0x00, 0x0C,
-0x01, 0x00, 0x05, 0x24, 0x25, 0xB0, 0x04, 0x3C, 0x48, 0x00, 0x84, 0x34,
-0x00, 0x00, 0x83, 0x8C, 0x08, 0x3E, 0x05, 0x8E, 0x7B, 0xFF, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x83, 0xAC, 0x0C, 0x00, 0xA2, 0x10, 0x60, 0x1B, 0x43, 0x26,
-0x3C, 0x00, 0x02, 0x24, 0x94, 0x39, 0x62, 0xAC, 0x2C, 0x00, 0xBF, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27, 0xC4, 0x3D, 0x02, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x42, 0x2C, 0xF1, 0xFF, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x12, 0x49, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x43, 0x26, 0x3C, 0x00, 0x02, 0x24, 0xA0, 0x0B, 0x00, 0x08,
-0x94, 0x39, 0x62, 0xAC, 0x02, 0x80, 0x04, 0x3C, 0x21, 0x28, 0x00, 0x02,
-0xF4, 0x54, 0x00, 0x0C, 0x70, 0x59, 0x84, 0x24, 0x02, 0x80, 0x04, 0x3C,
-0x44, 0xE7, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x02,
-0x77, 0x0B, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x24,
-0x4B, 0x2E, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24, 0x36, 0x0B, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x0E, 0x51, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x8D, 0x0B, 0x00, 0x08, 0x60, 0x1B, 0x50, 0x26, 0xE8, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x00, 0x00, 0x02, 0x92, 0x02, 0x80, 0x04, 0x3C, 0x21, 0x28, 0x40, 0x00,
-0x04, 0x00, 0x42, 0x2C, 0x06, 0x00, 0x40, 0x14, 0x50, 0xE7, 0x84, 0x24,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x13, 0x58, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x92, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x02, 0x80, 0x02, 0x3C, 0x84, 0x5B, 0x43, 0xAC,
-0x18, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C, 0xD0, 0xFF, 0xBD, 0x27,
-0x18, 0x03, 0x42, 0x34, 0x80, 0x2F, 0x63, 0x24, 0x24, 0x00, 0xB3, 0xAF,
-0x28, 0x00, 0xBF, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x43, 0xAC, 0x02, 0x80, 0x04, 0x3C,
-0xEC, 0x5D, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x13, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x06, 0x5E, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x60, 0x14, 0x01, 0x00, 0x04, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x0F, 0x5E, 0x44, 0xA0, 0x02, 0x80, 0x03, 0x3C,
-0xED, 0x5D, 0x64, 0x90, 0x01, 0x00, 0x05, 0x24, 0x4B, 0x2E, 0x00, 0x0C,
-0xFF, 0x00, 0x84, 0x30, 0x02, 0x80, 0x02, 0x3C, 0x98, 0x54, 0x43, 0x8C,
-0x98, 0x54, 0x42, 0x24, 0xA2, 0x00, 0x62, 0x10, 0x02, 0x80, 0x13, 0x3C,
-0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x02, 0x3C,
-0x36, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0x90, 0x60, 0x1B, 0x66, 0x26,
-0xF4, 0x38, 0xC5, 0x8C, 0xC0, 0x18, 0x03, 0x00, 0x23, 0xB0, 0x04, 0x3C,
-0xF0, 0x07, 0x63, 0x30, 0xFF, 0x1F, 0x02, 0x3C, 0x21, 0x18, 0x64, 0x00,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x62, 0x00, 0x23, 0x88, 0x85, 0x00,
-0x00, 0x04, 0x22, 0x26, 0x2B, 0x28, 0x85, 0x00, 0x98, 0x38, 0xC3, 0x8C,
-0x0B, 0x88, 0x45, 0x00, 0xE1, 0x01, 0x22, 0x2E, 0x94, 0x38, 0xC3, 0xAC,
-0xF8, 0x38, 0xC4, 0xAC, 0x9E, 0x38, 0xC0, 0xA4, 0x14, 0x00, 0x40, 0x14,
-0x9D, 0x38, 0xC0, 0xA0, 0x20, 0xFE, 0x82, 0x24, 0x20, 0x02, 0x83, 0x24,
-0x0A, 0x18, 0x45, 0x00, 0x23, 0x10, 0x02, 0x3C, 0xFF, 0x03, 0x42, 0x34,
-0x2B, 0x10, 0x43, 0x00, 0x21, 0x28, 0x60, 0x00, 0x32, 0x00, 0x40, 0x14,
-0xF4, 0x38, 0xC3, 0xAC, 0xF8, 0x38, 0xC2, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x18, 0x45, 0x00, 0x23, 0x88, 0x45, 0x00, 0x03, 0x00, 0x60, 0x10,
-0xE1, 0x01, 0x22, 0x2E, 0x00, 0x04, 0x31, 0x26, 0xE1, 0x01, 0x22, 0x2E,
-0x0E, 0x00, 0x40, 0x10, 0x60, 0x1B, 0x70, 0x26, 0x60, 0x1B, 0x70, 0x26,
-0xF8, 0x38, 0x03, 0x8E, 0xF4, 0x38, 0x04, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x10, 0x83, 0x00, 0x2C, 0x00, 0x40, 0x14, 0x2B, 0x10, 0x64, 0x00,
-0x56, 0x00, 0x40, 0x14, 0x25, 0xB0, 0x02, 0x3C, 0x80, 0x00, 0x03, 0x24,
-0xD0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x60, 0x1B, 0x70, 0x26,
-0xF4, 0x38, 0x03, 0x96, 0x2A, 0xB0, 0x02, 0x3C, 0x35, 0x00, 0x42, 0x34,
-0xC2, 0x88, 0x03, 0x00, 0x00, 0x00, 0x51, 0xA0, 0x73, 0x23, 0x00, 0x74,
-0x00, 0x00, 0x00, 0x00, 0x9E, 0x38, 0x03, 0x96, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xD0, 0x1B, 0x02, 0x8E, 0x80, 0x00, 0x03, 0x3C,
-0x41, 0xB0, 0x04, 0x3C, 0x25, 0x10, 0x43, 0x00, 0x00, 0x00, 0x82, 0xAC,
-0x28, 0x00, 0xBF, 0x8F, 0xD0, 0x1B, 0x02, 0xAE, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27, 0x00, 0xFC, 0xA5, 0x24,
-0x23, 0x0C, 0x00, 0x08, 0xF4, 0x38, 0xC5, 0xAC, 0x24, 0x2D, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xE2, 0x2C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0B, 0x00, 0x08,
-0x02, 0x80, 0x02, 0x3C, 0x94, 0x38, 0x05, 0x8E, 0x21, 0x30, 0x80, 0x00,
-0xFF, 0xFF, 0x27, 0x32, 0x09, 0x00, 0x04, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x94, 0x38, 0x03, 0x8E, 0x9E, 0x38, 0x05, 0x96,
-0xF4, 0x38, 0x02, 0x8E, 0x21, 0x18, 0x71, 0x00, 0x21, 0x28, 0x25, 0x02,
-0x21, 0x10, 0x51, 0x00, 0x09, 0x00, 0x04, 0x24, 0xF4, 0x38, 0x02, 0xAE,
-0x94, 0x38, 0x03, 0xAE, 0x5B, 0x01, 0x00, 0x0C, 0x9E, 0x38, 0x05, 0xA6,
-0x60, 0x1B, 0x70, 0x26, 0xF4, 0x38, 0x03, 0x96, 0x2A, 0xB0, 0x02, 0x3C,
-0x35, 0x00, 0x42, 0x34, 0xC2, 0x88, 0x03, 0x00, 0x00, 0x00, 0x51, 0xA0,
-0x73, 0x23, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x38, 0x03, 0x96,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x1B, 0x02, 0x8E,
-0x80, 0x00, 0x03, 0x3C, 0x41, 0xB0, 0x04, 0x3C, 0x25, 0x10, 0x43, 0x00,
-0x00, 0x00, 0x82, 0xAC, 0x28, 0x00, 0xBF, 0x8F, 0xD0, 0x1B, 0x02, 0xAE,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0xFC, 0x38, 0x02, 0x8E, 0x94, 0x38, 0x05, 0x8E, 0x21, 0x30, 0x80, 0x00,
-0x23, 0x88, 0x44, 0x00, 0xFF, 0xFF, 0x27, 0x32, 0x09, 0x00, 0x04, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x94, 0x38, 0x03, 0x8E,
-0x9E, 0x38, 0x02, 0x96, 0xF8, 0x38, 0x12, 0x96, 0x21, 0x18, 0x71, 0x00,
-0x21, 0x10, 0x22, 0x02, 0x23, 0x10, 0x11, 0x3C, 0x94, 0x38, 0x03, 0xAE,
-0x9E, 0x38, 0x02, 0xA6, 0x15, 0x00, 0x40, 0x16, 0xF4, 0x38, 0x11, 0xAE,
-0x09, 0x00, 0x04, 0x24, 0x5B, 0x01, 0x00, 0x0C, 0x60, 0x1B, 0x70, 0x26,
-0x71, 0x0C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x24, 0x2D, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x5C, 0xFF, 0x40, 0x10, 0x60, 0x1B, 0x63, 0x26,
-0x2A, 0x1C, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x58, 0xFF, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x4C, 0x3A, 0x64, 0x94, 0x2A, 0x1C, 0x60, 0xA0,
-0x00, 0xC0, 0x84, 0x24, 0xA3, 0x31, 0x00, 0x0C, 0xFF, 0xFF, 0x84, 0x30,
-0x01, 0x0C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x01, 0x00, 0x0C,
-0x09, 0x00, 0x04, 0x24, 0x94, 0x38, 0x05, 0x8E, 0x09, 0x00, 0x04, 0x24,
-0x23, 0x10, 0x06, 0x3C, 0x21, 0x38, 0x40, 0x02, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x94, 0x38, 0x03, 0x8E, 0x9E, 0x38, 0x02, 0x96,
-0x21, 0x20, 0x51, 0x02, 0x21, 0x18, 0x72, 0x00, 0x21, 0x10, 0x42, 0x02,
-0xF4, 0x38, 0x04, 0xAE, 0x09, 0x00, 0x04, 0x24, 0x94, 0x38, 0x03, 0xAE,
-0x9E, 0x0C, 0x00, 0x08, 0x9E, 0x38, 0x02, 0xA6, 0x08, 0x00, 0xE0, 0x03,
-0x09, 0x00, 0x02, 0x24, 0xFF, 0x00, 0x86, 0x30, 0x02, 0x80, 0x02, 0x3C,
-0x40, 0x00, 0xC3, 0x2C, 0x4A, 0xF5, 0x47, 0x90, 0x00, 0x00, 0x63, 0x38,
-0x3F, 0x00, 0x02, 0x24, 0x0A, 0x30, 0x43, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x08, 0x0E, 0x04, 0x24, 0x00, 0x7F, 0x05, 0x24, 0x03, 0x00, 0xE2, 0x10,
-0x31, 0x00, 0xC3, 0x2C, 0xC1, 0x43, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x30, 0x00, 0x02, 0x24, 0xC1, 0x43, 0x00, 0x08, 0x0A, 0x30, 0x43, 0x00,
-0xC0, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x03, 0x3C, 0x38, 0x00, 0xB4, 0xAF,
-0x34, 0x00, 0xB3, 0xAF, 0x30, 0x00, 0xB2, 0xAF, 0x2C, 0x00, 0xB1, 0xAF,
-0x28, 0x00, 0xB0, 0xAF, 0xA4, 0xE7, 0x62, 0x24, 0x3C, 0x00, 0xBF, 0xAF,
-0x0A, 0x00, 0x4A, 0x94, 0x02, 0x00, 0x48, 0x94, 0x06, 0x00, 0x49, 0x94,
-0xFF, 0x00, 0x84, 0x30, 0xFF, 0x00, 0xA5, 0x30, 0xA4, 0xE7, 0x6B, 0x94,
-0x04, 0x00, 0x4C, 0x94, 0x08, 0x00, 0x4D, 0x94, 0x00, 0x1C, 0x05, 0x00,
-0x00, 0x14, 0x04, 0x00, 0x00, 0x3E, 0x05, 0x00, 0x00, 0x36, 0x04, 0x00,
-0x25, 0x38, 0xE3, 0x00, 0x25, 0x30, 0xC2, 0x00, 0x00, 0x44, 0x08, 0x00,
-0x00, 0x12, 0x05, 0x00, 0x00, 0x4C, 0x09, 0x00, 0x00, 0x54, 0x0A, 0x00,
-0x00, 0x1A, 0x04, 0x00, 0x25, 0x38, 0xE2, 0x00, 0x25, 0x40, 0x0B, 0x01,
-0x25, 0x48, 0x2C, 0x01, 0x25, 0x50, 0x4D, 0x01, 0x25, 0x30, 0xC3, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x10, 0x00, 0xA8, 0xAF, 0x14, 0x00, 0xA9, 0xAF,
-0x18, 0x00, 0xAA, 0xAF, 0x25, 0x98, 0xE5, 0x00, 0x25, 0x90, 0xC4, 0x00,
-0x60, 0x1B, 0x54, 0x24, 0x21, 0x80, 0x00, 0x00, 0x10, 0x00, 0xB1, 0x27,
-0x02, 0x00, 0x02, 0x2E, 0x32, 0x00, 0x40, 0x10, 0x80, 0x10, 0x10, 0x00,
-0x21, 0x10, 0x54, 0x00, 0xF0, 0x1C, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x40, 0x73, 0x00, 0x21, 0x38, 0x00, 0x00, 0x7F, 0x00, 0x09, 0x24,
-0xC0, 0x20, 0x07, 0x00, 0x04, 0x10, 0x89, 0x00, 0x24, 0x10, 0x48, 0x00,
-0x06, 0x10, 0x82, 0x00, 0x01, 0x00, 0xE5, 0x24, 0xFF, 0x00, 0x43, 0x30,
-0x21, 0x30, 0x27, 0x02, 0x40, 0x00, 0x63, 0x2C, 0xFF, 0x00, 0xA7, 0x30,
-0x02, 0x00, 0x60, 0x14, 0x04, 0x00, 0xE4, 0x2C, 0x3F, 0x00, 0x02, 0x24,
-0xF3, 0xFF, 0x80, 0x14, 0x10, 0x00, 0xC2, 0xA0, 0x23, 0x00, 0xA6, 0x93,
-0x22, 0x00, 0xA2, 0x93, 0x21, 0x00, 0xA5, 0x93, 0x40, 0x18, 0x10, 0x00,
-0x00, 0x14, 0x02, 0x00, 0x21, 0x18, 0x71, 0x00, 0x20, 0x00, 0xA7, 0x93,
-0x00, 0x36, 0x06, 0x00, 0x25, 0x30, 0xC2, 0x00, 0x00, 0x2A, 0x05, 0x00,
-0x00, 0x00, 0x64, 0x94, 0x25, 0x30, 0xC5, 0x00, 0x7F, 0x7F, 0x05, 0x3C,
-0x25, 0x30, 0xC7, 0x00, 0xC1, 0x43, 0x00, 0x0C, 0x7F, 0x7F, 0xA5, 0x34,
-0x01, 0x00, 0x02, 0x26, 0xFF, 0x00, 0x50, 0x30, 0x06, 0x00, 0x03, 0x2E,
-0xD5, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0xBF, 0x8F,
-0x38, 0x00, 0xB4, 0x8F, 0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F,
-0x2C, 0x00, 0xB1, 0x8F, 0x28, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x40, 0x00, 0xBD, 0x27, 0x21, 0x10, 0x54, 0x00, 0xF0, 0x1C, 0x43, 0x8C,
-0x07, 0x0D, 0x00, 0x08, 0x21, 0x40, 0x72, 0x00, 0xD8, 0xFF, 0xBD, 0x27,
-0x14, 0x00, 0xB1, 0xAF, 0x20, 0x00, 0xBF, 0xAF, 0x1C, 0x00, 0xB3, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x02, 0x3C,
-0xC6, 0x5C, 0x43, 0x90, 0x02, 0x80, 0x07, 0x3C, 0x60, 0x1B, 0xE2, 0x24,
-0xFF, 0x00, 0x91, 0x30, 0x21, 0x20, 0x22, 0x02, 0x20, 0x00, 0x62, 0x30,
-0x10, 0x00, 0x63, 0x30, 0x63, 0x1D, 0x93, 0x90, 0x27, 0x00, 0x60, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x8D, 0x1D, 0x82, 0x90, 0x7F, 0x1D, 0x83, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x23, 0x10, 0x43, 0x00, 0x00, 0x36, 0x02, 0x00,
-0x03, 0x36, 0x06, 0x00, 0xFF, 0x00, 0x70, 0x30, 0x60, 0x1B, 0xE7, 0x24,
-0x21, 0x40, 0x27, 0x02, 0xB7, 0x1D, 0x02, 0x91, 0xB0, 0x1B, 0xE3, 0x84,
-0x0F, 0x00, 0x05, 0x3C, 0x0F, 0x00, 0x42, 0x30, 0x21, 0x10, 0x50, 0x00,
-0x0C, 0x08, 0x04, 0x24, 0x0F, 0x00, 0xC6, 0x30, 0x00, 0xFF, 0xA5, 0x34,
-0x06, 0x00, 0x60, 0x04, 0xFF, 0x00, 0x52, 0x30, 0xC5, 0x1D, 0x02, 0x91,
-0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x21, 0x10, 0x50, 0x00,
-0xFF, 0x00, 0x50, 0x30, 0xC1, 0x43, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xC5, 0x0C, 0x00, 0x0C, 0x21, 0x20, 0x60, 0x02, 0x21, 0x20, 0x00, 0x02,
-0x21, 0x28, 0x40, 0x02, 0x21, 0x30, 0x20, 0x02, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0xD6, 0x0C, 0x00, 0x08, 0x28, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x1D, 0x82, 0x90,
-0x9B, 0x1D, 0x83, 0x90, 0x4D, 0x0D, 0x00, 0x08, 0x23, 0x10, 0x43, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x02, 0x3C,
-0x18, 0x00, 0xBF, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0xD1, 0x5C, 0x43, 0x90,
-0x01, 0x00, 0x02, 0x24, 0x09, 0x00, 0x62, 0x10, 0xFF, 0x00, 0x90, 0x30,
-0x21, 0x30, 0x00, 0x02, 0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x18, 0x00, 0x04, 0x24, 0xFF, 0x03, 0x05, 0x24,
-0x83, 0x45, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27, 0x0F, 0x00, 0x05, 0x3C,
-0xFF, 0xFF, 0xA5, 0x34, 0x15, 0x00, 0x04, 0x24, 0x0A, 0x00, 0x03, 0x12,
-0xF4, 0xA8, 0x06, 0x34, 0x0F, 0x00, 0x05, 0x3C, 0x0B, 0x00, 0x02, 0x24,
-0xFF, 0xFF, 0xA5, 0x34, 0x05, 0x00, 0x02, 0x12, 0xF5, 0xF8, 0x06, 0x34,
-0x0F, 0x00, 0x05, 0x3C, 0xF4, 0xF8, 0x06, 0x34, 0x15, 0x00, 0x04, 0x24,
-0xFF, 0xFF, 0xA5, 0x34, 0x83, 0x45, 0x00, 0x0C, 0x0F, 0x00, 0x11, 0x3C,
-0x02, 0x80, 0x02, 0x3C, 0x48, 0xF5, 0x46, 0x90, 0xFE, 0x00, 0x03, 0x24,
-0x15, 0x00, 0x04, 0x24, 0xE3, 0xFF, 0xC3, 0x14, 0xFF, 0xFF, 0x25, 0x36,
-0xAC, 0x45, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x46, 0x30,
-0x00, 0xFF, 0x23, 0x36, 0x24, 0x10, 0x43, 0x00, 0x01, 0x00, 0xC6, 0x24,
-0x25, 0x30, 0x46, 0x00, 0xFF, 0xFF, 0x25, 0x36, 0x83, 0x45, 0x00, 0x0C,
-0x15, 0x00, 0x04, 0x24, 0x7F, 0x0D, 0x00, 0x08, 0x21, 0x30, 0x00, 0x02,
-0xFC, 0x00, 0x84, 0x30, 0x80, 0x00, 0x02, 0x24, 0x11, 0x00, 0x82, 0x10,
-0x06, 0x00, 0x03, 0x24, 0x81, 0x00, 0x82, 0x28, 0x10, 0x00, 0x40, 0x10,
-0xB0, 0x00, 0x02, 0x24, 0x20, 0x00, 0x02, 0x24, 0x0B, 0x00, 0x82, 0x10,
-0x02, 0x00, 0x03, 0x24, 0x21, 0x00, 0x82, 0x28, 0x15, 0x00, 0x40, 0x10,
-0x40, 0x00, 0x02, 0x24, 0x06, 0x00, 0x80, 0x10, 0x21, 0x18, 0x00, 0x00,
-0x01, 0x00, 0x03, 0x24, 0x10, 0x00, 0x02, 0x24, 0x02, 0x00, 0x82, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x60, 0x00, 0xFD, 0xFF, 0x82, 0x10, 0x09, 0x00, 0x03, 0x24,
-0xB1, 0x00, 0x82, 0x28, 0x0F, 0x00, 0x40, 0x10, 0xC8, 0x00, 0x02, 0x24,
-0x90, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x82, 0x10, 0x07, 0x00, 0x03, 0x24,
-0x08, 0x00, 0x03, 0x24, 0xB9, 0x0D, 0x00, 0x08, 0xA0, 0x00, 0x02, 0x24,
-0xF2, 0xFF, 0x82, 0x10, 0x04, 0x00, 0x03, 0x24, 0x41, 0x00, 0x82, 0x28,
-0x0F, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x24,
-0xB9, 0x0D, 0x00, 0x08, 0x30, 0x00, 0x02, 0x24, 0xEA, 0xFF, 0x82, 0x10,
-0x0C, 0x00, 0x03, 0x24, 0xC9, 0x00, 0x82, 0x28, 0x04, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x03, 0x24, 0xB9, 0x0D, 0x00, 0x08,
-0xC0, 0x00, 0x02, 0x24, 0x0B, 0x00, 0x03, 0x24, 0xB9, 0x0D, 0x00, 0x08,
-0xD0, 0x00, 0x02, 0x24, 0x05, 0x00, 0x03, 0x24, 0xB9, 0x0D, 0x00, 0x08,
-0x50, 0x00, 0x02, 0x24, 0xD0, 0xFF, 0xBD, 0x27, 0x2C, 0x00, 0xBF, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x08, 0x00, 0x83, 0x8C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x08, 0x00, 0x90, 0x94, 0x02, 0x80, 0x02, 0x3C, 0x21, 0x90, 0x80, 0x00,
-0x25, 0x80, 0x02, 0x02, 0xFF, 0x00, 0xB4, 0x30, 0x21, 0x20, 0x00, 0x02,
-0xFF, 0x00, 0xD1, 0x30, 0x21, 0x28, 0x00, 0x00, 0x08, 0x00, 0x06, 0x24,
-0xEC, 0x54, 0x00, 0x0C, 0xFF, 0x00, 0xF3, 0x30, 0x04, 0x00, 0x06, 0x8E,
-0x08, 0x00, 0x05, 0x8E, 0xFF, 0xDF, 0x02, 0x3C, 0xFF, 0xE0, 0x03, 0x24,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x30, 0xC3, 0x00, 0x24, 0x28, 0xA2, 0x00,
-0x3F, 0xFF, 0x02, 0x3C, 0x10, 0x00, 0x08, 0x8E, 0xFF, 0xFF, 0x42, 0x34,
-0x00, 0x12, 0xC6, 0x34, 0x00, 0x40, 0x03, 0x3C, 0x24, 0x30, 0xC2, 0x00,
-0x05, 0x00, 0x07, 0x24, 0x04, 0x00, 0x02, 0x24, 0x0B, 0x38, 0x54, 0x00,
-0x25, 0x28, 0xA3, 0x00, 0x01, 0x00, 0x84, 0x32, 0x7F, 0xFF, 0x03, 0x24,
-0x00, 0x80, 0x02, 0x3C, 0x14, 0x00, 0x09, 0x8E, 0x24, 0x28, 0xA3, 0x00,
-0xC0, 0x21, 0x04, 0x00, 0x25, 0x40, 0x02, 0x01, 0x03, 0x00, 0x31, 0x32,
-0xFF, 0xE0, 0x02, 0x3C, 0x80, 0x8D, 0x11, 0x00, 0x25, 0x28, 0xA4, 0x00,
-0xFF, 0xFF, 0x42, 0x34, 0x0C, 0x00, 0x4A, 0x8E, 0x25, 0x30, 0xD1, 0x00,
-0xFF, 0x81, 0x03, 0x24, 0xE0, 0xFF, 0x04, 0x24, 0x24, 0x28, 0xA2, 0x00,
-0x3F, 0x00, 0x73, 0x32, 0xFB, 0xFF, 0x02, 0x3C, 0x24, 0x48, 0x23, 0x01,
-0x24, 0x30, 0xC4, 0x00, 0x00, 0x1E, 0x07, 0x00, 0x40, 0x9A, 0x13, 0x00,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x40, 0x02, 0x01, 0x25, 0x48, 0x33, 0x01,
-0x25, 0x28, 0xA3, 0x00, 0x25, 0x30, 0xC7, 0x00, 0x20, 0x00, 0x02, 0x24,
-0x08, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x0A, 0xA6, 0x02, 0x00, 0x02, 0xA2,
-0x10, 0x00, 0x08, 0xAE, 0x14, 0x00, 0x09, 0xAE, 0x04, 0x00, 0x06, 0xAE,
-0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x98, 0x54, 0x42, 0x24, 0x04, 0x00, 0x43, 0x8C, 0x00, 0x00, 0x42, 0xAE,
-0x04, 0x00, 0x52, 0xAC, 0x00, 0x00, 0x72, 0xAC, 0x04, 0x00, 0x43, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x2C, 0x00, 0xBF, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x30, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0xFF, 0xFF, 0x90, 0x30, 0x10, 0x00, 0xA4, 0x27, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x24, 0x00, 0xBF, 0xAF, 0xFF, 0x00, 0xB1, 0x30,
-0x8A, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0xD2, 0x30, 0x00, 0x80, 0x02, 0x34,
-0x20, 0x00, 0x02, 0x12, 0x21, 0x20, 0x20, 0x02, 0x75, 0x0D, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x03, 0x3C, 0x03, 0x02, 0x63, 0x34,
-0x00, 0x00, 0x62, 0x90, 0x00, 0x08, 0x04, 0x24, 0x01, 0x00, 0x05, 0x24,
-0x04, 0x00, 0x42, 0x34, 0x00, 0x00, 0x62, 0xA0, 0x35, 0x45, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0x00, 0x09, 0x04, 0x24, 0x01, 0x00, 0x05, 0x24,
-0x35, 0x45, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0x84, 0x08, 0x04, 0x24,
-0xFF, 0xFF, 0x05, 0x24, 0x35, 0x45, 0x00, 0x0C, 0x58, 0x00, 0x06, 0x24,
-0x18, 0x00, 0x04, 0x24, 0x00, 0x0C, 0x05, 0x24, 0x83, 0x45, 0x00, 0x0C,
-0x01, 0x00, 0x06, 0x24, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x01, 0x00, 0x02, 0x24, 0x02, 0x00, 0x42, 0x12, 0x02, 0x00, 0x24, 0x26,
-0xFE, 0xFF, 0x24, 0x26, 0x75, 0x0D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x07, 0x3C, 0x03, 0x02, 0xE7, 0x34, 0x00, 0x00, 0xE3, 0x90,
-0xFB, 0xFF, 0x02, 0x24, 0x00, 0x08, 0x04, 0x24, 0x24, 0x18, 0x62, 0x00,
-0x00, 0x00, 0xE3, 0xA0, 0x01, 0x00, 0x05, 0x24, 0x35, 0x45, 0x00, 0x0C,
-0x01, 0x00, 0x06, 0x24, 0x03, 0x00, 0x50, 0x32, 0x00, 0x09, 0x04, 0x24,
-0x01, 0x00, 0x05, 0x24, 0x35, 0x45, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24,
-0x42, 0x30, 0x10, 0x00, 0x00, 0x0A, 0x04, 0x24, 0x35, 0x45, 0x00, 0x0C,
-0x10, 0x00, 0x05, 0x24, 0x21, 0x30, 0x00, 0x02, 0x00, 0x0D, 0x04, 0x24,
-0x35, 0x45, 0x00, 0x0C, 0x00, 0x0C, 0x05, 0x24, 0x84, 0x08, 0x04, 0x24,
-0xFF, 0xFF, 0x05, 0x24, 0x35, 0x45, 0x00, 0x0C, 0x18, 0x00, 0x06, 0x24,
-0x18, 0x00, 0x04, 0x24, 0x00, 0x0C, 0x05, 0x24, 0x83, 0x45, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0xD0, 0xFF, 0xBD, 0x27, 0x24, 0x00, 0xB3, 0xAF, 0x02, 0x80, 0x13, 0x3C,
-0x20, 0x00, 0xB2, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0x72, 0x26,
-0xFF, 0xFF, 0x90, 0x30, 0x10, 0x00, 0xA4, 0x27, 0x1C, 0x00, 0xB1, 0xAF,
-0x28, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0xB1, 0x30,
-0xB0, 0x1B, 0x42, 0x96, 0x10, 0x00, 0xA4, 0x27, 0x00, 0x80, 0x42, 0x30,
-0x11, 0x00, 0x50, 0x10, 0x21, 0x30, 0x20, 0x02, 0xC4, 0x3D, 0x45, 0x92,
-0x3C, 0x0E, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02, 0x00, 0x80, 0x02, 0x34,
-0x14, 0x00, 0x02, 0x12, 0x00, 0x80, 0x02, 0x24, 0xB0, 0x1B, 0x42, 0x96,
-0x3B, 0x41, 0x51, 0xA2, 0xFF, 0x7F, 0x42, 0x30, 0xB0, 0x1B, 0x42, 0xA6,
-0x60, 0x1B, 0x62, 0x26, 0xB0, 0x1B, 0x45, 0x94, 0xC4, 0x3D, 0x44, 0x90,
-0x38, 0x0D, 0x00, 0x0C, 0x00, 0x10, 0xA5, 0x30, 0x10, 0x00, 0xA4, 0x27,
-0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0xBF, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0xB0, 0x1B, 0x43, 0x96, 0x3B, 0x41, 0x51, 0xA2, 0x25, 0x18, 0x62, 0x00,
-0xB0, 0x0E, 0x00, 0x08, 0xB0, 0x1B, 0x43, 0xA6, 0xE0, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x14, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xBF, 0xAF, 0x53, 0x21, 0x00, 0x0C, 0x28, 0x00, 0x04, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0x21, 0x88, 0x40, 0x00, 0x21, 0x28, 0x00, 0x02,
-0x06, 0x00, 0x06, 0x24, 0x15, 0x00, 0x40, 0x10, 0xAC, 0xE8, 0x84, 0x24,
-0x08, 0x00, 0x44, 0x94, 0x08, 0x00, 0x02, 0x24, 0x0C, 0x00, 0x22, 0xAE,
-0x02, 0x80, 0x02, 0x3C, 0x0C, 0x00, 0x03, 0x24, 0x25, 0x20, 0x82, 0x00,
-0x14, 0x00, 0x23, 0xAE, 0xF4, 0x54, 0x00, 0x0C, 0x20, 0x00, 0x84, 0x24,
-0x17, 0x0A, 0x00, 0x0C, 0x21, 0x20, 0x20, 0x02, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0x04, 0xE9, 0x84, 0x24, 0x21, 0x10, 0x00, 0x00,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x05, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xEC, 0xE8, 0xA5, 0x24, 0xE0, 0x0E, 0x00, 0x08,
-0xFF, 0xFF, 0x02, 0x24, 0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB3, 0xAF,
-0x21, 0x98, 0x80, 0x00, 0x2C, 0x00, 0x04, 0x24, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x21, 0x90, 0xA0, 0x00, 0x20, 0x00, 0xBF, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x04, 0x3C,
-0x02, 0x80, 0x05, 0x3C, 0x21, 0x88, 0x40, 0x00, 0x28, 0xE9, 0x84, 0x24,
-0x21, 0x30, 0x40, 0x02, 0x19, 0x00, 0x40, 0x10, 0x10, 0xE9, 0xA5, 0x24,
-0x05, 0x00, 0x65, 0x92, 0x13, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x30, 0x96, 0x02, 0x80, 0x02, 0x3C, 0x0B, 0x00, 0x03, 0x24,
-0x25, 0x80, 0x02, 0x02, 0x20, 0x00, 0x10, 0x26, 0x0C, 0x00, 0x02, 0x24,
-0x21, 0x20, 0x00, 0x02, 0x0C, 0x00, 0x22, 0xAE, 0x14, 0x00, 0x23, 0xAE,
-0x21, 0x28, 0x60, 0x02, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x08, 0x00, 0x12, 0xAE, 0x21, 0x20, 0x20, 0x02, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x17, 0x0A, 0x00, 0x08, 0x28, 0x00, 0xBD, 0x27,
-0x02, 0x80, 0x04, 0x3C, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0xAC, 0xE8, 0x84, 0x24, 0x13, 0x58, 0x00, 0x08, 0x28, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x02, 0x3C, 0xEE, 0x5D, 0x43, 0x90,
-0x02, 0x80, 0x11, 0x3C, 0x04, 0x00, 0x04, 0x24, 0x0F, 0x00, 0x63, 0x30,
-0x04, 0x00, 0x63, 0x28, 0x3A, 0x00, 0x60, 0x14, 0x01, 0x00, 0x05, 0x24,
-0x40, 0xDF, 0x23, 0x8E, 0x0F, 0x00, 0x05, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0xFF, 0xFF, 0xA5, 0x34, 0x24, 0x00, 0x04, 0x24, 0x60, 0x00, 0x06, 0x24,
-0x12, 0x00, 0x60, 0x14, 0x60, 0x1B, 0x50, 0x24, 0x83, 0x45, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0x05, 0x92, 0xD0, 0x07, 0x02, 0x24,
-0x01, 0x00, 0x03, 0x24, 0x0A, 0x10, 0x05, 0x00, 0x3C, 0x3A, 0x02, 0xAE,
-0x02, 0x80, 0x02, 0x3C, 0xED, 0x5D, 0x44, 0x90, 0x40, 0xDF, 0x23, 0xAE,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x01, 0x00, 0x05, 0x24, 0xFF, 0x00, 0x84, 0x30, 0x4B, 0x2E, 0x00, 0x08,
-0x20, 0x00, 0xBD, 0x27, 0x0F, 0x00, 0x05, 0x3C, 0xFF, 0xFF, 0xA5, 0x34,
-0xAC, 0x45, 0x00, 0x0C, 0x24, 0x00, 0x04, 0x24, 0x49, 0x41, 0x04, 0x92,
-0xFF, 0x00, 0x43, 0x30, 0x00, 0x2C, 0x03, 0x00, 0x0A, 0x00, 0x64, 0x10,
-0x4A, 0x41, 0x02, 0xA2, 0x02, 0x80, 0x02, 0x3C, 0x49, 0xF5, 0x44, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x04, 0x00, 0x12, 0x27, 0x00, 0x74,
-0x25, 0x20, 0xA4, 0x00, 0x4A, 0x41, 0x03, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x49, 0x41, 0x03, 0xA2, 0x48, 0x41, 0x03, 0x92, 0x10, 0x27, 0x02, 0x24,
-0x40, 0xDF, 0x20, 0xAE, 0x0A, 0x10, 0x03, 0x00, 0x3C, 0x3A, 0x02, 0xAE,
-0x02, 0x80, 0x02, 0x3C, 0xED, 0x5D, 0x44, 0x90, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x05, 0x24,
-0xFF, 0x00, 0x84, 0x30, 0x4B, 0x2E, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27,
-0x4B, 0x2E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x28, 0x0F, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xC8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB2, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x34, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xBE, 0xAF,
-0x2C, 0x00, 0xB7, 0xAF, 0x28, 0x00, 0xB6, 0xAF, 0x24, 0x00, 0xB5, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x21, 0x80, 0x80, 0x00, 0x45, 0x00, 0xA0, 0x14, 0x21, 0x90, 0x00, 0x00,
-0x08, 0x00, 0x82, 0x90, 0x02, 0x80, 0x13, 0x3C, 0x60, 0x1B, 0x63, 0x26,
-0x0F, 0x00, 0x42, 0x30, 0xC0, 0x40, 0x62, 0xAC, 0x25, 0xB0, 0x02, 0x3C,
-0x0A, 0x00, 0x10, 0x26, 0xD0, 0x01, 0x57, 0x34, 0x02, 0x80, 0x14, 0x3C,
-0xD8, 0x01, 0x5E, 0x34, 0xDC, 0x01, 0x55, 0x34, 0xD4, 0x01, 0x56, 0x34,
-0x03, 0x00, 0x11, 0x24, 0x00, 0x00, 0x06, 0x92, 0x60, 0x1B, 0x62, 0x26,
-0xB8, 0x40, 0x47, 0x90, 0x0F, 0x00, 0xC3, 0x30, 0x01, 0x00, 0x05, 0x92,
-0x18, 0x00, 0x67, 0x00, 0x03, 0x00, 0x04, 0x92, 0x02, 0x00, 0x02, 0x92,
-0x0F, 0x00, 0xA7, 0x30, 0x00, 0x3A, 0x07, 0x00, 0x02, 0x29, 0x05, 0x00,
-0x00, 0x22, 0x04, 0x00, 0x25, 0x20, 0x82, 0x00, 0x00, 0x2B, 0x05, 0x00,
-0x42, 0x11, 0x06, 0x00, 0x00, 0x24, 0x04, 0x00, 0x03, 0x00, 0x49, 0x30,
-0x02, 0x31, 0x06, 0x00, 0x01, 0x00, 0x02, 0x24, 0x01, 0x00, 0xC6, 0x30,
-0x12, 0x18, 0x00, 0x00, 0x0A, 0x00, 0x63, 0x24, 0xFF, 0x00, 0x63, 0x30,
-0x25, 0x18, 0x67, 0x00, 0x25, 0x18, 0x65, 0x00, 0x30, 0x00, 0x22, 0x11,
-0x25, 0x38, 0x64, 0x00, 0x02, 0x00, 0x22, 0x29, 0x3E, 0x00, 0x40, 0x14,
-0x02, 0x00, 0x02, 0x24, 0x38, 0x00, 0x22, 0x11, 0x03, 0x00, 0x02, 0x24,
-0x40, 0x00, 0x22, 0x11, 0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0x20, 0x01,
-0x64, 0xE9, 0x84, 0x26, 0x13, 0x58, 0x00, 0x0C, 0xFF, 0xFF, 0x31, 0x26,
-0xD9, 0xFF, 0x21, 0x06, 0x04, 0x00, 0x10, 0x26, 0x25, 0xB0, 0x02, 0x3C,
-0xE7, 0x01, 0x42, 0x34, 0x00, 0x00, 0x52, 0xA0, 0x34, 0x00, 0xBF, 0x8F,
-0x30, 0x00, 0xBE, 0x8F, 0x2C, 0x00, 0xB7, 0x8F, 0x28, 0x00, 0xB6, 0x8F,
-0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x13, 0x3C,
-0x08, 0x00, 0x83, 0x90, 0x60, 0x1B, 0x62, 0x26, 0xC0, 0x40, 0x44, 0x8C,
-0x0F, 0x00, 0x63, 0x30, 0xBB, 0xFF, 0x83, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x34, 0x00, 0xBF, 0x8F, 0x30, 0x00, 0xBE, 0x8F, 0x2C, 0x00, 0xB7, 0x8F,
-0x28, 0x00, 0xB6, 0x8F, 0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0xA7, 0xAE, 0x21, 0x20, 0x00, 0x00, 0x25, 0xB0, 0x08, 0x3C,
-0x07, 0x10, 0x92, 0x00, 0x01, 0x00, 0x42, 0x30, 0x01, 0x00, 0x84, 0x24,
-0x02, 0x00, 0x40, 0x10, 0x03, 0x00, 0x85, 0x2C, 0xD0, 0x01, 0x07, 0xAD,
-0xF9, 0xFF, 0xA0, 0x14, 0x04, 0x00, 0x08, 0x25, 0xA3, 0x0F, 0x00, 0x08,
-0x21, 0x28, 0x20, 0x01, 0x0D, 0x00, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xA2, 0x0F, 0x00, 0x08, 0x02, 0x00, 0x52, 0x36, 0xC7, 0xFF, 0x20, 0x15,
-0x21, 0x28, 0x20, 0x01, 0x0D, 0x00, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xA3, 0x0F, 0x00, 0x08, 0x04, 0x00, 0x52, 0x36, 0x06, 0x00, 0xC0, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xA2, 0x0F, 0x00, 0x08, 0x01, 0x00, 0x52, 0x36,
-0x00, 0x00, 0xC7, 0xAE, 0xA3, 0x0F, 0x00, 0x08, 0x21, 0x28, 0x20, 0x01,
-0x00, 0x00, 0xE7, 0xAE, 0xA3, 0x0F, 0x00, 0x08, 0x21, 0x28, 0x20, 0x01,
-0x00, 0x00, 0xC7, 0xAF, 0xA3, 0x0F, 0x00, 0x08, 0x21, 0x28, 0x20, 0x01,
-0xB8, 0xFF, 0xBD, 0x27, 0x24, 0x00, 0xB1, 0xAF, 0x21, 0x88, 0x80, 0x00,
-0x00, 0x01, 0x04, 0x24, 0x2C, 0x00, 0xB3, 0xAF, 0x44, 0x00, 0xBF, 0xAF,
-0x40, 0x00, 0xBE, 0xAF, 0x3C, 0x00, 0xB7, 0xAF, 0x38, 0x00, 0xB6, 0xAF,
-0x34, 0x00, 0xB5, 0xAF, 0x30, 0x00, 0xB4, 0xAF, 0x28, 0x00, 0xB2, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0x20, 0x00, 0xB0, 0xAF, 0xAC, 0x00, 0x40, 0x10,
-0x21, 0x98, 0x40, 0x00, 0x08, 0x00, 0x50, 0x94, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0x28, 0x20, 0x02, 0x25, 0x80, 0x02, 0x02, 0x24, 0x00, 0x04, 0x26,
-0x20, 0x00, 0x00, 0xA6, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x02, 0x80, 0x05, 0x3C, 0x2A, 0x00, 0x04, 0x26, 0x48, 0x37, 0xA5, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C,
-0xB4, 0x55, 0xA5, 0x24, 0x06, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x30, 0x00, 0x04, 0x26, 0x20, 0x00, 0x03, 0x96, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x54, 0x24, 0x03, 0xFF, 0x63, 0x30, 0x50, 0x00, 0x63, 0x34,
-0x20, 0x00, 0x03, 0xA6, 0xE4, 0x1D, 0x82, 0x96, 0x02, 0x80, 0x03, 0x3C,
-0xB0, 0x55, 0x63, 0x24, 0x74, 0x00, 0x72, 0x24, 0xFF, 0x0F, 0x43, 0x30,
-0x00, 0x19, 0x03, 0x00, 0x01, 0x00, 0x42, 0x24, 0x02, 0x22, 0x03, 0x00,
-0xE4, 0x1D, 0x82, 0xA6, 0x20, 0x00, 0x11, 0x26, 0x20, 0x00, 0x02, 0x24,
-0x16, 0x00, 0x23, 0xA2, 0x17, 0x00, 0x24, 0xA2, 0x21, 0x20, 0x40, 0x02,
-0xFB, 0x51, 0x00, 0x0C, 0x0C, 0x00, 0x62, 0xAE, 0x40, 0x00, 0x11, 0x26,
-0x21, 0x20, 0x20, 0x02, 0x21, 0x28, 0x40, 0x00, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x06, 0x24, 0x0C, 0x00, 0x63, 0x8E, 0x21, 0x20, 0x40, 0x02,
-0x42, 0x00, 0x11, 0x26, 0x02, 0x00, 0x63, 0x24, 0x16, 0x52, 0x00, 0x0C,
-0x0C, 0x00, 0x63, 0xAE, 0x21, 0x28, 0x40, 0x00, 0x21, 0x20, 0x20, 0x02,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x24, 0x0C, 0x00, 0x63, 0x8E,
-0x02, 0x80, 0x02, 0x3C, 0xB0, 0x55, 0x42, 0x24, 0x02, 0x00, 0x63, 0x24,
-0x0C, 0x00, 0x63, 0xAE, 0x0C, 0x00, 0x46, 0x8C, 0x44, 0x00, 0x04, 0x26,
-0x0C, 0x00, 0x76, 0x26, 0x60, 0x00, 0x50, 0x24, 0x21, 0x28, 0x00, 0x00,
-0x10, 0x00, 0x47, 0x24, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB6, 0xAF,
-0x21, 0x20, 0x00, 0x02, 0x1B, 0x53, 0x00, 0x0C, 0x21, 0x88, 0x40, 0x00,
-0x09, 0x00, 0x43, 0x2C, 0x08, 0x00, 0x06, 0x24, 0x21, 0x20, 0x20, 0x02,
-0x0B, 0x30, 0x43, 0x00, 0x21, 0x38, 0x00, 0x02, 0x01, 0x00, 0x05, 0x24,
-0x18, 0x00, 0xA3, 0xAF, 0x21, 0xB8, 0x40, 0x00, 0x25, 0x52, 0x00, 0x0C,
-0x10, 0x00, 0xB6, 0xAF, 0x21, 0x20, 0x40, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0xB0, 0x55, 0x42, 0x24, 0x03, 0x00, 0x05, 0x24, 0x01, 0x00, 0x06, 0x24,
-0x48, 0x00, 0x47, 0x24, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB6, 0xAF,
-0x21, 0x88, 0x40, 0x00, 0xC0, 0x3A, 0x82, 0x8E, 0x0C, 0x00, 0x10, 0x24,
-0x2B, 0x10, 0x02, 0x02, 0x3A, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x26, 0x56, 0x5E, 0x24, 0x68, 0x10, 0x00, 0x08, 0x21, 0xA8, 0x80, 0x02,
-0x21, 0x10, 0x12, 0x02, 0x01, 0x00, 0x43, 0x90, 0xC0, 0x3A, 0xA4, 0x8E,
-0x21, 0x18, 0x70, 0x00, 0x02, 0x00, 0x70, 0x24, 0x2B, 0x20, 0x04, 0x02,
-0x2F, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x12, 0x02,
-0x00, 0x00, 0x47, 0x90, 0x02, 0x80, 0x14, 0x3C, 0x2D, 0x00, 0x03, 0x24,
-0x21, 0x28, 0x1E, 0x02, 0x64, 0x5C, 0x84, 0x26, 0xF1, 0xFF, 0xE3, 0x14,
-0x20, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x41, 0xA3, 0x96, 0x02, 0x80, 0x02, 0x3C, 0xC6, 0x5C, 0x47, 0x90,
-0xBD, 0xFF, 0x63, 0x30, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0x0C, 0x00, 0x63, 0x34, 0x01, 0x00, 0xE7, 0x30, 0x44, 0xDF, 0xA5, 0x24,
-0x67, 0x5C, 0x44, 0x24, 0x10, 0x00, 0x06, 0x24, 0x06, 0x00, 0xE0, 0x14,
-0x04, 0x41, 0xA3, 0xA6, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x54, 0xDF, 0xA5, 0x24, 0x67, 0x5C, 0x64, 0x24, 0x10, 0x00, 0x06, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x12, 0x02,
-0x01, 0x00, 0x46, 0x90, 0x21, 0x20, 0x20, 0x02, 0x64, 0x5C, 0x87, 0x26,
-0x2D, 0x00, 0x05, 0x24, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB6, 0xAF,
-0x21, 0x88, 0x40, 0x00, 0x21, 0x10, 0x12, 0x02, 0x01, 0x00, 0x43, 0x90,
-0xC0, 0x3A, 0xA4, 0x8E, 0x21, 0x18, 0x70, 0x00, 0x02, 0x00, 0x70, 0x24,
-0x2B, 0x20, 0x04, 0x02, 0xD4, 0xFF, 0x80, 0x14, 0x21, 0x10, 0x12, 0x02,
-0x18, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x40, 0x10,
-0x21, 0x20, 0x60, 0x02, 0x44, 0x00, 0xBF, 0x8F, 0x40, 0x00, 0xBE, 0x8F,
-0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F, 0x34, 0x00, 0xB5, 0x8F,
-0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB2, 0x8F,
-0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x05, 0x24,
-0x21, 0x30, 0x00, 0x00, 0x21, 0x38, 0x00, 0x00, 0xDF, 0x0D, 0x00, 0x08,
-0x48, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x44, 0x00, 0xBF, 0x8F, 0x40, 0x00, 0xBE, 0x8F, 0x3C, 0x00, 0xB7, 0x8F,
-0x38, 0x00, 0xB6, 0x8F, 0x34, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB4, 0x8F,
-0x2C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB1, 0x8F,
-0x20, 0x00, 0xB0, 0x8F, 0x58, 0xE9, 0x84, 0x24, 0xAC, 0xE9, 0xA5, 0x24,
-0x13, 0x58, 0x00, 0x08, 0x48, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x03, 0x3C,
-0xB0, 0x55, 0x63, 0x24, 0x21, 0x20, 0x20, 0x02, 0xF8, 0xFF, 0xE6, 0x26,
-0x68, 0x00, 0x67, 0x24, 0x32, 0x00, 0x05, 0x24, 0x25, 0x52, 0x00, 0x0C,
-0x10, 0x00, 0xB6, 0xAF, 0x21, 0x20, 0x60, 0x02, 0x44, 0x00, 0xBF, 0x8F,
-0x40, 0x00, 0xBE, 0x8F, 0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F,
-0x34, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F,
-0x28, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F,
-0x01, 0x00, 0x05, 0x24, 0x21, 0x30, 0x00, 0x00, 0x21, 0x38, 0x00, 0x00,
-0xDF, 0x0D, 0x00, 0x08, 0x48, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x20, 0x00, 0xBF, 0xAF,
-0x02, 0x00, 0x82, 0x90, 0x02, 0x80, 0x03, 0x3C, 0x10, 0x37, 0x65, 0x94,
-0x0F, 0x00, 0x42, 0x30, 0x00, 0x00, 0x83, 0x8C, 0xC0, 0x10, 0x02, 0x00,
-0x21, 0x20, 0x44, 0x00, 0x00, 0x10, 0xA8, 0x30, 0x02, 0x80, 0x02, 0x3C,
-0x00, 0x08, 0xA5, 0x30, 0xB0, 0x55, 0x51, 0x24, 0xFF, 0x3F, 0x63, 0x30,
-0x06, 0x00, 0xA0, 0x10, 0x18, 0x00, 0x90, 0x24, 0xE8, 0xFF, 0x67, 0x24,
-0x30, 0x00, 0x84, 0x24, 0x21, 0x28, 0x00, 0x00, 0x07, 0x00, 0x00, 0x11,
-0x10, 0x00, 0xA6, 0x27, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xAB, 0x1A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xF7, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x44, 0x24,
-0x10, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x10,
-0x10, 0x00, 0x25, 0x26, 0x0C, 0x00, 0x26, 0x8E, 0x1D, 0x55, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xED, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x26, 0x53, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02, 0xEE, 0x0F, 0x00, 0x0C,
-0x21, 0x20, 0x40, 0x00, 0xE8, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0xA0, 0xFF, 0xBD, 0x27, 0x58, 0x00, 0xBE, 0xAF, 0x5C, 0x00, 0xBF, 0xAF,
-0x54, 0x00, 0xB7, 0xAF, 0x50, 0x00, 0xB6, 0xAF, 0x4C, 0x00, 0xB5, 0xAF,
-0x48, 0x00, 0xB4, 0xAF, 0x44, 0x00, 0xB3, 0xAF, 0x40, 0x00, 0xB2, 0xAF,
-0x3C, 0x00, 0xB1, 0xAF, 0x38, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x3F, 0x46, 0x30, 0xE8, 0xFF, 0xC5, 0x24,
-0x01, 0x03, 0xA2, 0x2C, 0x16, 0x00, 0x40, 0x14, 0x21, 0xF0, 0x80, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x63, 0x24, 0x40, 0x3E, 0x62, 0x8C,
-0x02, 0x80, 0x04, 0x3C, 0xD0, 0xE9, 0x84, 0x24, 0x01, 0x00, 0x42, 0x24,
-0x40, 0x3E, 0x62, 0xAC, 0x13, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x5C, 0x00, 0xBF, 0x8F, 0x58, 0x00, 0xBE, 0x8F, 0x54, 0x00, 0xB7, 0x8F,
-0x50, 0x00, 0xB6, 0x8F, 0x4C, 0x00, 0xB5, 0x8F, 0x48, 0x00, 0xB4, 0x8F,
-0x44, 0x00, 0xB3, 0x8F, 0x40, 0x00, 0xB2, 0x8F, 0x3C, 0x00, 0xB1, 0x8F,
-0x38, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x60, 0x00, 0xBD, 0x27,
-0x7C, 0x00, 0xC4, 0x24, 0x5C, 0x00, 0xC6, 0x24, 0x53, 0x21, 0x00, 0x0C,
-0x24, 0x00, 0xA6, 0xAF, 0x74, 0x00, 0x40, 0x10, 0x20, 0x00, 0xA2, 0xAF,
-0x20, 0x00, 0xA3, 0x8F, 0x24, 0x00, 0xA6, 0x8F, 0x21, 0x28, 0x00, 0x00,
-0x08, 0x00, 0x62, 0x94, 0x02, 0x80, 0x03, 0x3C, 0x25, 0x10, 0x43, 0x00,
-0x20, 0x00, 0x57, 0x24, 0xE3, 0x54, 0x00, 0x0C, 0x21, 0x20, 0xE0, 0x02,
-0x02, 0x80, 0x03, 0x3C, 0xE8, 0xE9, 0x62, 0x24, 0xE8, 0xE9, 0x67, 0x90,
-0x01, 0x00, 0x44, 0x90, 0x02, 0x00, 0xC3, 0x93, 0x02, 0x00, 0x45, 0x90,
-0x03, 0x00, 0x46, 0x90, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x50, 0x24,
-0x00, 0x00, 0xC2, 0x8F, 0x00, 0x22, 0x04, 0x00, 0x0F, 0x00, 0x63, 0x30,
-0x25, 0x20, 0x87, 0x00, 0x00, 0x2C, 0x05, 0x00, 0xC0, 0x18, 0x03, 0x00,
-0x4B, 0x41, 0x07, 0x92, 0x21, 0x18, 0x7E, 0x00, 0x25, 0x28, 0xA4, 0x00,
-0xFF, 0x3F, 0x42, 0x30, 0x00, 0x36, 0x06, 0x00, 0x25, 0x30, 0xC5, 0x00,
-0x30, 0x00, 0xA2, 0xAF, 0x22, 0x00, 0x64, 0x24, 0x18, 0x00, 0x62, 0x24,
-0x10, 0x00, 0xA6, 0xAF, 0x2C, 0x00, 0xA4, 0xAF, 0x28, 0x00, 0xA2, 0xAF,
-0x53, 0x00, 0xE0, 0x14, 0x28, 0x00, 0x76, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x54, 0x24, 0xA5, 0x59, 0x73, 0x24,
-0x21, 0x90, 0x00, 0x00, 0x01, 0x00, 0x15, 0x24, 0x64, 0x11, 0x00, 0x08,
-0x21, 0x80, 0x00, 0x00, 0x1D, 0x55, 0x00, 0x0C, 0x01, 0x00, 0x52, 0x26,
-0x07, 0x00, 0x10, 0x26, 0x32, 0x00, 0x40, 0x10, 0x40, 0x00, 0x43, 0x2A,
-0x0C, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x88, 0x14, 0x02,
-0x44, 0x3E, 0x22, 0x92, 0x21, 0x20, 0x13, 0x02, 0x21, 0x28, 0xC0, 0x02,
-0xF4, 0xFF, 0x55, 0x10, 0x06, 0x00, 0x06, 0x24, 0x21, 0x20, 0x13, 0x02,
-0x21, 0x28, 0xC0, 0x02, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x44, 0x3E, 0x35, 0xA2, 0x30, 0x00, 0xA4, 0x8F, 0x74, 0x00, 0xF4, 0x26,
-0x80, 0x00, 0xF3, 0x26, 0x5C, 0x00, 0x83, 0x24, 0xE8, 0xFF, 0x82, 0x24,
-0x1C, 0x00, 0xA2, 0xAF, 0x00, 0x00, 0xE3, 0xAE, 0x28, 0x00, 0xA3, 0x8F,
-0x1C, 0x00, 0xA2, 0x8F, 0x21, 0x20, 0x80, 0x02, 0x18, 0x00, 0x65, 0x24,
-0x21, 0x30, 0x40, 0x00, 0xF4, 0x54, 0x00, 0x0C, 0x70, 0x00, 0xE2, 0xAE,
-0x70, 0x00, 0xE7, 0x8E, 0x21, 0x20, 0x60, 0x02, 0x21, 0x28, 0x00, 0x00,
-0xF4, 0xFF, 0xE7, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x1C, 0x00, 0xA6, 0x27,
-0x0F, 0x00, 0x40, 0x10, 0x21, 0x80, 0x40, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x60, 0x1B, 0x91, 0x24, 0x0C, 0x3E, 0x26, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x32, 0x00, 0xC0, 0x18, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xA2, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0xC2, 0x10, 0x02, 0x80, 0x04, 0x3C,
-0xC0, 0x10, 0x12, 0x00, 0x23, 0x10, 0x52, 0x00, 0x21, 0x10, 0x51, 0x00,
-0x44, 0x3E, 0x40, 0xA0, 0x20, 0x00, 0xA4, 0x8F, 0x74, 0x21, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x5C, 0x00, 0xBF, 0x8F, 0x58, 0x00, 0xBE, 0x8F,
-0x54, 0x00, 0xB7, 0x8F, 0x50, 0x00, 0xB6, 0x8F, 0x4C, 0x00, 0xB5, 0x8F,
-0x48, 0x00, 0xB4, 0x8F, 0x44, 0x00, 0xB3, 0x8F, 0x40, 0x00, 0xB2, 0x8F,
-0x3C, 0x00, 0xB1, 0x8F, 0x38, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x60, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0xAC, 0xE8, 0x84, 0x24, 0x1B, 0x11, 0x00, 0x08, 0xBC, 0xE9, 0xA5, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0xAC, 0x5C, 0x84, 0x24, 0x21, 0x28, 0xC0, 0x02,
-0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0xA8, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x8A, 0x40, 0x00, 0x0C, 0x18, 0x00, 0xA4, 0x27,
-0x52, 0x41, 0x02, 0x92, 0x18, 0x00, 0xA4, 0x27, 0x01, 0x00, 0x42, 0x24,
-0x90, 0x40, 0x00, 0x0C, 0x52, 0x41, 0x02, 0xA2, 0x56, 0x11, 0x00, 0x08,
-0x02, 0x80, 0x02, 0x3C, 0x70, 0x59, 0x84, 0x24, 0x1D, 0x55, 0x00, 0x0C,
-0x02, 0x00, 0x05, 0x26, 0xD5, 0xFF, 0x40, 0x14, 0xC0, 0x10, 0x12, 0x00,
-0x01, 0x00, 0x06, 0x92, 0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0xC0, 0x14,
-0x10, 0x00, 0xE4, 0x26, 0x0C, 0x00, 0xE0, 0xAE, 0x02, 0x00, 0xC2, 0x97,
-0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x28,
-0x5E, 0x00, 0x40, 0x10, 0x21, 0x20, 0xC0, 0x03, 0x34, 0x00, 0xE0, 0xAE,
-0x60, 0x00, 0xF1, 0x26, 0x21, 0x20, 0x20, 0x02, 0x21, 0x28, 0x00, 0x00,
-0xE3, 0x54, 0x00, 0x0C, 0x10, 0x00, 0x06, 0x24, 0x70, 0x00, 0xE7, 0x8E,
-0x21, 0x20, 0x60, 0x02, 0x01, 0x00, 0x05, 0x24, 0xF4, 0xFF, 0xE7, 0x24,
-0xAB, 0x1A, 0x00, 0x0C, 0x1C, 0x00, 0xA6, 0x27, 0x06, 0x00, 0x40, 0x10,
-0x21, 0x90, 0x00, 0x00, 0x1C, 0x00, 0xA6, 0x8F, 0x02, 0x00, 0x45, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x21, 0x20, 0x20, 0x02, 0x1C, 0x00, 0xB2, 0x8F,
-0x70, 0x00, 0xE7, 0x8E, 0x21, 0x20, 0x60, 0x02, 0x32, 0x00, 0x05, 0x24,
-0xF4, 0xFF, 0xE7, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x1C, 0x00, 0xA6, 0x27,
-0x05, 0x00, 0x40, 0x10, 0x21, 0x20, 0xF2, 0x02, 0x1C, 0x00, 0xA6, 0x8F,
-0x60, 0x00, 0x84, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x45, 0x24,
-0x1C, 0x00, 0xA5, 0x8F, 0x21, 0x20, 0x20, 0x02, 0x61, 0x53, 0x00, 0x0C,
-0x21, 0x28, 0xB2, 0x00, 0x21, 0x18, 0x40, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x40, 0x00, 0x62, 0x10, 0x03, 0x00, 0x02, 0x24, 0x38, 0x00, 0xE2, 0xAE,
-0x70, 0x00, 0xE7, 0x8E, 0x21, 0x20, 0x60, 0x02, 0x03, 0x00, 0x05, 0x24,
-0xF4, 0xFF, 0xE7, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x1C, 0x00, 0xA6, 0x27,
-0x48, 0x00, 0xE0, 0xAE, 0x04, 0x00, 0x40, 0x10, 0x3C, 0x00, 0xE0, 0xAE,
-0x02, 0x00, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0xE2, 0xAE,
-0xFB, 0x51, 0x00, 0x0C, 0x21, 0x20, 0x80, 0x02, 0x21, 0x28, 0x40, 0x00,
-0x40, 0x00, 0xE4, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x24,
-0x18, 0x52, 0x00, 0x0C, 0x21, 0x20, 0xE0, 0x02, 0xFF, 0xFF, 0x50, 0x30,
-0x01, 0x00, 0x02, 0x32, 0x1A, 0x00, 0x40, 0x10, 0x21, 0x28, 0xC0, 0x02,
-0x01, 0x00, 0x02, 0x24, 0x5C, 0x00, 0xE2, 0xAE, 0x2C, 0x00, 0xA5, 0x8F,
-0x04, 0x00, 0xE4, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x10, 0x00, 0x02, 0x32, 0x13, 0x00, 0x40, 0x10, 0x01, 0x00, 0x02, 0x24,
-0x30, 0x00, 0xE2, 0xAE, 0x02, 0x80, 0x03, 0x3C, 0x44, 0x00, 0xE0, 0xAE,
-0x60, 0x1B, 0x62, 0x24, 0x3C, 0x3E, 0x43, 0x8C, 0x20, 0x00, 0xA4, 0x8F,
-0x01, 0x00, 0x63, 0x24, 0x3C, 0x3E, 0x43, 0xAC, 0x24, 0x00, 0xA3, 0x8F,
-0x08, 0x00, 0x02, 0x24, 0x0C, 0x00, 0x83, 0xAC, 0x20, 0x00, 0xA3, 0x8F,
-0x17, 0x0A, 0x00, 0x0C, 0x14, 0x00, 0x62, 0xAC, 0x1D, 0x11, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x0A, 0x12, 0x00, 0x08, 0x5C, 0x00, 0xE0, 0xAE,
-0x11, 0x12, 0x00, 0x08, 0x30, 0x00, 0xE0, 0xAE, 0xE3, 0x17, 0x00, 0x0C,
-0x18, 0x00, 0xC5, 0x27, 0xC8, 0x11, 0x00, 0x08, 0x34, 0x00, 0xE2, 0xAE,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x05, 0x26, 0x01, 0x00, 0x03, 0x92,
-0xC1, 0x11, 0x00, 0x08, 0x0C, 0x00, 0xE3, 0xAE, 0xEF, 0x11, 0x00, 0x08,
-0x38, 0x00, 0xE3, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x44, 0x24,
-0xFC, 0x40, 0x83, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x60, 0x10,
-0x01, 0x00, 0x05, 0x24, 0xB6, 0x40, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x42, 0x2C, 0x07, 0x00, 0x40, 0x10, 0x21, 0x28, 0x00, 0x00,
-0xC7, 0x3D, 0x83, 0x90, 0x01, 0x00, 0x02, 0x24, 0x03, 0x00, 0x62, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x01, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x60, 0x1B, 0x82, 0x24, 0x44, 0x41, 0x45, 0x8C,
-0x40, 0x41, 0x46, 0x8C, 0x21, 0x20, 0x40, 0x00, 0x40, 0x18, 0x05, 0x00,
-0x40, 0x10, 0x06, 0x00, 0x2B, 0x18, 0x66, 0x00, 0x2B, 0x38, 0x45, 0x00,
-0x04, 0x00, 0x60, 0x14, 0x21, 0x28, 0x00, 0x00, 0x01, 0x00, 0x05, 0x24,
-0x02, 0x00, 0x02, 0x24, 0x0A, 0x28, 0x47, 0x00, 0x21, 0x10, 0xA0, 0x00,
-0x40, 0x41, 0x80, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x44, 0x41, 0x80, 0xAC,
-0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF,
-0x43, 0x12, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x80, 0x40, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xCE, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x12, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x2F, 0x12, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x24, 0x0D, 0x00, 0x43, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x16, 0x5C, 0x44, 0x90, 0x02, 0x80, 0x02, 0x3C,
-0xD4, 0xDD, 0x42, 0x24, 0x40, 0x18, 0x04, 0x00, 0x21, 0x18, 0x64, 0x00,
-0x21, 0x18, 0x70, 0x00, 0x80, 0x18, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x00, 0x00, 0x64, 0x8C, 0x25, 0xB0, 0x02, 0x3C, 0xD8, 0x01, 0x42, 0x34,
-0x00, 0x00, 0x44, 0xAC, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xE8, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x02, 0x00, 0x84, 0x90, 0x02, 0x80, 0x05, 0x3C, 0x48, 0x37, 0xA5, 0x24,
-0x0F, 0x00, 0x84, 0x30, 0xC0, 0x20, 0x04, 0x00, 0x21, 0x20, 0x90, 0x00,
-0x1C, 0x00, 0x84, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x06, 0x00, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x10, 0x37, 0x43, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x63, 0x30, 0x06, 0x00, 0x60, 0x14,
-0x21, 0x20, 0x00, 0x02, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0x02, 0x11, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0xE0, 0xFF, 0xBD, 0x27, 0x54, 0x4A, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0x18, 0x00, 0xB0, 0xAF, 0x1C, 0x00, 0xBF, 0xAF, 0x00, 0x00, 0x43, 0xAC,
-0x02, 0x00, 0x82, 0x90, 0x02, 0x80, 0x05, 0x3C, 0xB4, 0x55, 0xA5, 0x24,
-0x0F, 0x00, 0x42, 0x30, 0xC0, 0x10, 0x02, 0x00, 0x21, 0x10, 0x44, 0x00,
-0x28, 0x00, 0x44, 0x24, 0x06, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C,
-0x18, 0x00, 0x50, 0x24, 0x06, 0x00, 0x40, 0x10, 0x21, 0x20, 0x00, 0x02,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0x39, 0x53, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x48, 0x37, 0x84, 0x24,
-0x21, 0x28, 0x40, 0x00, 0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0xF3, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x42, 0x30, 0xEE, 0xFF, 0x40, 0x10,
-0x10, 0x00, 0xA4, 0x27, 0x8A, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xEC, 0x5D, 0x43, 0x90, 0x05, 0x00, 0x02, 0x24,
-0xFF, 0x00, 0x63, 0x30, 0x05, 0x00, 0x62, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0xA9, 0x12, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x37, 0x43, 0x94, 0x02, 0x80, 0x04, 0x3C,
-0x00, 0x01, 0x63, 0x30, 0xF8, 0xFF, 0x60, 0x10, 0x01, 0x00, 0x05, 0x24,
-0x07, 0x5E, 0x83, 0x90, 0xFB, 0xFF, 0x02, 0x24, 0x24, 0x18, 0x62, 0x00,
-0x07, 0x5E, 0x83, 0xA0, 0x02, 0x80, 0x02, 0x3C, 0xED, 0x5D, 0x44, 0x90,
-0x4B, 0x2E, 0x00, 0x0C, 0xFF, 0x00, 0x84, 0x30, 0x90, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0xA9, 0x12, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0xD8, 0xFF, 0xBD, 0x27, 0x28, 0x00, 0xA4, 0xA3, 0x00, 0x01, 0x04, 0x24,
-0x18, 0x00, 0xB2, 0xAF, 0x24, 0x00, 0xBF, 0xAF, 0x20, 0x00, 0xB4, 0xAF,
-0x1C, 0x00, 0xB3, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x2C, 0x00, 0xA5, 0xA3, 0x53, 0x21, 0x00, 0x0C, 0x30, 0x00, 0xA6, 0xA7,
-0xA4, 0x00, 0x40, 0x10, 0x21, 0x90, 0x40, 0x00, 0x30, 0x00, 0xA7, 0x97,
-0x28, 0x00, 0xA5, 0x93, 0x2C, 0x00, 0xA6, 0x93, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xB0, 0xEA, 0x84, 0x24, 0x08, 0x00, 0x50, 0x96,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x11, 0x3C, 0x25, 0x80, 0x02, 0x02,
-0xB4, 0x55, 0x31, 0x26, 0x21, 0x28, 0x20, 0x02, 0x24, 0x00, 0x04, 0x26,
-0x06, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x20, 0x00, 0x00, 0xA6,
-0x02, 0x80, 0x05, 0x3C, 0x48, 0x37, 0xA5, 0x24, 0x2A, 0x00, 0x04, 0x26,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x21, 0x28, 0x20, 0x02,
-0x30, 0x00, 0x04, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x20, 0x00, 0x03, 0x96, 0x18, 0x00, 0x02, 0x24, 0x02, 0x80, 0x14, 0x3C,
-0x03, 0xFF, 0x63, 0x30, 0xD0, 0x00, 0x63, 0x34, 0x20, 0x00, 0x03, 0xA6,
-0x60, 0x1B, 0x93, 0x26, 0x0C, 0x00, 0x42, 0xAE, 0xE4, 0x1D, 0x62, 0x96,
-0x20, 0x00, 0x05, 0x26, 0x0C, 0x00, 0x51, 0x26, 0xFF, 0x0F, 0x43, 0x30,
-0x00, 0x19, 0x03, 0x00, 0x02, 0x22, 0x03, 0x00, 0x01, 0x00, 0x42, 0x24,
-0xE4, 0x1D, 0x62, 0xA6, 0x28, 0x00, 0xA6, 0x27, 0x16, 0x00, 0xA3, 0xA0,
-0x17, 0x00, 0xA4, 0xA0, 0x21, 0x38, 0x20, 0x02, 0x38, 0x00, 0x04, 0x26,
-0x4C, 0x52, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24, 0x21, 0x20, 0x40, 0x00,
-0x01, 0x00, 0x05, 0x24, 0x2C, 0x00, 0xA6, 0x27, 0x4C, 0x52, 0x00, 0x0C,
-0x21, 0x38, 0x20, 0x02, 0x28, 0x00, 0xA3, 0x93, 0x21, 0x20, 0x40, 0x00,
-0x03, 0x00, 0x02, 0x24, 0x12, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x82, 0x26, 0xB6, 0x40, 0x43, 0x90, 0x04, 0x00, 0x07, 0x24,
-0x21, 0x20, 0x40, 0x02, 0x01, 0x00, 0x63, 0x38, 0x0B, 0x38, 0x03, 0x00,
-0x21, 0x28, 0x00, 0x00, 0xDF, 0x0D, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27, 0x2C, 0x00, 0xA3, 0x93,
-0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x60, 0x14, 0x01, 0x00, 0x02, 0x24,
-0xC5, 0x40, 0x63, 0x92, 0x21, 0x80, 0x60, 0x02, 0x01, 0x00, 0x68, 0x24,
-0xFF, 0x00, 0x02, 0x31, 0xFD, 0xFF, 0x40, 0x10, 0x21, 0x18, 0x00, 0x01,
-0x02, 0x80, 0x06, 0x3C, 0x21, 0x38, 0x20, 0x02, 0xC5, 0x40, 0x08, 0xA2,
-0x25, 0x5C, 0xC6, 0x24, 0x4C, 0x52, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24,
-0xC8, 0x40, 0x08, 0x8E, 0x30, 0x00, 0xA4, 0x97, 0xC3, 0xFF, 0x03, 0x24,
-0x02, 0x00, 0x08, 0x35, 0x0F, 0x00, 0x84, 0x30, 0x24, 0x40, 0x03, 0x01,
-0x80, 0x20, 0x04, 0x00, 0xFF, 0xFF, 0x03, 0x3C, 0x3F, 0x00, 0x63, 0x34,
-0x25, 0x40, 0x04, 0x01, 0x24, 0x40, 0x03, 0x01, 0x00, 0x08, 0x08, 0x35,
-0x02, 0x80, 0x06, 0x3C, 0x21, 0x38, 0x20, 0x02, 0xC8, 0x40, 0x08, 0xAE,
-0x28, 0x5C, 0xC6, 0x24, 0x21, 0x20, 0x40, 0x00, 0x4C, 0x52, 0x00, 0x0C,
-0x02, 0x00, 0x05, 0x24, 0x02, 0x80, 0x06, 0x3C, 0x21, 0x38, 0x20, 0x02,
-0x2A, 0x5C, 0xC6, 0x24, 0x21, 0x20, 0x40, 0x00, 0x02, 0x00, 0x05, 0x24,
-0x4C, 0x52, 0x00, 0x0C, 0xCA, 0x40, 0x00, 0xA6, 0x30, 0x00, 0xA3, 0x97,
-0x21, 0x20, 0x40, 0x00, 0x02, 0x80, 0x06, 0x3C, 0x07, 0x00, 0x63, 0x30,
-0x40, 0x18, 0x03, 0x00, 0x21, 0x18, 0x70, 0x00, 0xD4, 0x1D, 0x62, 0x94,
-0x2C, 0x5C, 0xC6, 0x24, 0x21, 0x38, 0x20, 0x02, 0x00, 0x11, 0x02, 0x00,
-0x02, 0x00, 0x05, 0x24, 0x4C, 0x52, 0x00, 0x0C, 0xCC, 0x40, 0x02, 0xA6,
-0x22, 0x13, 0x00, 0x08, 0x60, 0x1B, 0x82, 0x26, 0xB5, 0xFF, 0x62, 0x14,
-0x02, 0x80, 0x06, 0x3C, 0x21, 0x38, 0x20, 0x02, 0x24, 0x5C, 0xC6, 0x24,
-0x4C, 0x52, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24, 0x21, 0x20, 0x40, 0x00,
-0x30, 0x00, 0xA6, 0x27, 0x21, 0x38, 0x20, 0x02, 0x4C, 0x52, 0x00, 0x0C,
-0x02, 0x00, 0x05, 0x24, 0xC8, 0x40, 0x68, 0x8E, 0xFF, 0xFF, 0x03, 0x3C,
-0x3F, 0x00, 0x63, 0x34, 0x24, 0x40, 0x03, 0x01, 0x00, 0x08, 0x08, 0x35,
-0x02, 0x80, 0x06, 0x3C, 0x21, 0x38, 0x20, 0x02, 0x21, 0x20, 0x40, 0x00,
-0x28, 0x5C, 0xC6, 0x24, 0x02, 0x00, 0x05, 0x24, 0x4C, 0x52, 0x00, 0x0C,
-0xC8, 0x40, 0x68, 0xAE, 0x02, 0x80, 0x06, 0x3C, 0x21, 0x20, 0x40, 0x00,
-0x2A, 0x5C, 0xC6, 0x24, 0x21, 0x38, 0x20, 0x02, 0x4C, 0x52, 0x00, 0x0C,
-0x02, 0x00, 0x05, 0x24, 0x22, 0x13, 0x00, 0x08, 0x60, 0x1B, 0x82, 0x26,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0xAC, 0xE8, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0xA0, 0xEA, 0xA5, 0x24, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xBF, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x82, 0x90,
-0x02, 0x80, 0x11, 0x3C, 0x21, 0x80, 0x80, 0x00, 0x60, 0x1B, 0x31, 0x26,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x00, 0x06, 0x24, 0x01, 0x00, 0x05, 0x26,
-0x28, 0x5C, 0x84, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0xC4, 0x40, 0x22, 0xA2,
-0x04, 0x00, 0x03, 0x92, 0x03, 0x00, 0x02, 0x92, 0x00, 0x1A, 0x03, 0x00,
-0x25, 0x18, 0x62, 0x00, 0xCA, 0x40, 0x23, 0xA6, 0x06, 0x00, 0x02, 0x92,
-0x05, 0x00, 0x03, 0x92, 0x00, 0x12, 0x02, 0x00, 0x25, 0x10, 0x43, 0x00,
-0xCC, 0x40, 0x22, 0xA6, 0x01, 0x00, 0x05, 0x92, 0x06, 0x00, 0x04, 0x92,
-0x05, 0x00, 0x02, 0x92, 0x82, 0x28, 0x05, 0x00, 0x00, 0x22, 0x04, 0x00,
-0x25, 0x20, 0x82, 0x00, 0x6A, 0x48, 0x00, 0x0C, 0x0F, 0x00, 0xA5, 0x30,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x03, 0x00, 0x04, 0x24, 0x01, 0x00, 0x05, 0x24, 0x21, 0x30, 0x00, 0x00,
-0xD9, 0x12, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27, 0x00, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x03, 0x42, 0x34,
-0xFC, 0x4E, 0x63, 0x24, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x1C, 0x00, 0xBF, 0xAF, 0x18, 0x00, 0xB2, 0xAF, 0x00, 0x00, 0x43, 0xAC,
-0x02, 0x00, 0x82, 0x90, 0x02, 0x80, 0x05, 0x3C, 0xB4, 0x55, 0xA5, 0x24,
-0x0F, 0x00, 0x42, 0x30, 0xC0, 0x10, 0x02, 0x00, 0x21, 0x88, 0x44, 0x00,
-0x28, 0x00, 0x24, 0x26, 0x06, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C,
-0x18, 0x00, 0x30, 0x26, 0x08, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x39, 0x53, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02,
-0x02, 0x80, 0x04, 0x3C, 0x48, 0x37, 0x84, 0x24, 0x21, 0x28, 0x40, 0x00,
-0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0xF1, 0xFF, 0x40, 0x14,
-0x03, 0x00, 0x02, 0x24, 0x30, 0x00, 0x23, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xED, 0xFF, 0x62, 0x14, 0x30, 0x00, 0x24, 0x26, 0x02, 0x80, 0x07, 0x3C,
-0x60, 0x1B, 0xE5, 0x24, 0xFC, 0x40, 0xA2, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0xE7, 0xFF, 0x40, 0x10, 0x01, 0x00, 0x06, 0x24, 0x01, 0x00, 0x83, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x66, 0x10, 0x02, 0x00, 0x62, 0x28,
-0x2E, 0x00, 0x40, 0x14, 0x02, 0x00, 0x02, 0x24, 0xDF, 0xFF, 0x62, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x62, 0x30, 0x0A, 0x00, 0x40, 0x14, 0x02, 0x11, 0x03, 0x00,
-0xC6, 0x40, 0xA3, 0x90, 0x04, 0x10, 0x46, 0x00, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x10, 0x43, 0x00, 0xC6, 0x40, 0xA2, 0xA0, 0x05, 0x00, 0x83, 0x90,
-0x04, 0x00, 0x82, 0x90, 0x00, 0x1A, 0x03, 0x00, 0x25, 0x90, 0x62, 0x00,
-0xC6, 0x40, 0xA5, 0x90, 0x02, 0x80, 0x04, 0x3C, 0xCC, 0xEA, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0x21, 0x30, 0x40, 0x02, 0xD5, 0x13, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x82, 0x90, 0x05, 0x00, 0x83, 0x90,
-0x03, 0x00, 0x84, 0x90, 0x00, 0x12, 0x02, 0x00, 0x82, 0x18, 0x03, 0x00,
-0x25, 0x10, 0x44, 0x00, 0x15, 0x00, 0x40, 0x14, 0x07, 0x00, 0x64, 0x30,
-0xC6, 0x40, 0xA3, 0x90, 0x04, 0x10, 0x86, 0x00, 0x25, 0x10, 0x43, 0x00,
-0xC6, 0x40, 0xA2, 0xA0, 0x60, 0x1B, 0xE2, 0x24, 0xF8, 0x40, 0x43, 0x90,
-0xC6, 0x40, 0x45, 0x90, 0x02, 0x80, 0x04, 0x3C, 0x21, 0x18, 0x62, 0x00,
-0xDC, 0xEA, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0xF0, 0x40, 0x60, 0xA0,
-0xD5, 0x13, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0x60, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x97, 0x13, 0x00, 0x0C, 0x32, 0x00, 0x24, 0x26,
-0xD5, 0x13, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x40, 0xA3, 0x90,
-0x04, 0x10, 0x86, 0x00, 0x27, 0x10, 0x02, 0x00, 0x17, 0x14, 0x00, 0x08,
-0x24, 0x10, 0x43, 0x00, 0xB8, 0xFF, 0xBD, 0x27, 0x38, 0x00, 0xB6, 0xAF,
-0xFF, 0xFF, 0x96, 0x30, 0x00, 0x01, 0x04, 0x24, 0x3C, 0x00, 0xB7, 0xAF,
-0x28, 0x00, 0xB2, 0xAF, 0x40, 0x00, 0xBF, 0xAF, 0x34, 0x00, 0xB5, 0xAF,
-0x30, 0x00, 0xB4, 0xAF, 0x2C, 0x00, 0xB3, 0xAF, 0x24, 0x00, 0xB1, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0x20, 0x00, 0xB0, 0xAF, 0x21, 0x90, 0x40, 0x00,
-0x81, 0x00, 0x40, 0x10, 0x21, 0xB8, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xF8, 0xEA, 0x84, 0x24, 0x08, 0x00, 0x50, 0x96,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x11, 0x3C, 0x25, 0x80, 0x02, 0x02,
-0xB4, 0x55, 0x31, 0x26, 0x24, 0x00, 0x04, 0x26, 0x21, 0x28, 0x20, 0x02,
-0x20, 0x00, 0x00, 0xA6, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x02, 0x80, 0x05, 0x3C, 0x2A, 0x00, 0x04, 0x26, 0x48, 0x37, 0xA5, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x30, 0x00, 0x04, 0x26,
-0x21, 0x28, 0x20, 0x02, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x20, 0x00, 0x03, 0x96, 0x18, 0x00, 0x02, 0x24, 0x02, 0x80, 0x15, 0x3C,
-0x03, 0xFF, 0x63, 0x30, 0xB0, 0x00, 0x63, 0x34, 0x20, 0x00, 0x03, 0xA6,
-0x60, 0x1B, 0xA8, 0x26, 0x0C, 0x00, 0x42, 0xAE, 0xE4, 0x1D, 0x02, 0x95,
-0x20, 0x00, 0x14, 0x26, 0x0C, 0x00, 0x51, 0x26, 0xFF, 0x0F, 0x43, 0x30,
-0x00, 0x19, 0x03, 0x00, 0x02, 0x22, 0x03, 0x00, 0x01, 0x00, 0x42, 0x24,
-0xE4, 0x1D, 0x02, 0xA5, 0x17, 0x00, 0x84, 0xA2, 0x16, 0x00, 0x83, 0xA2,
-0x20, 0x40, 0x04, 0x8D, 0x03, 0x00, 0x02, 0x24, 0x31, 0x00, 0x82, 0x10,
-0x38, 0x00, 0x10, 0x26, 0x60, 0x1B, 0xB3, 0x26, 0x24, 0x40, 0x62, 0x8E,
-0x21, 0x20, 0x00, 0x02, 0x02, 0x00, 0x05, 0x24, 0x01, 0x00, 0x42, 0x38,
-0x01, 0x00, 0x42, 0x2C, 0x18, 0x00, 0xA6, 0x27, 0x21, 0x38, 0x20, 0x02,
-0x4C, 0x52, 0x00, 0x0C, 0x18, 0x00, 0xA2, 0xA7, 0x20, 0x40, 0x63, 0x8E,
-0x21, 0x20, 0x40, 0x00, 0x02, 0x00, 0x05, 0x24, 0x18, 0x00, 0xA6, 0x27,
-0x21, 0x38, 0x20, 0x02, 0x4C, 0x52, 0x00, 0x0C, 0x18, 0x00, 0xA3, 0xA7,
-0x21, 0x20, 0x40, 0x00, 0x02, 0x00, 0x05, 0x24, 0x18, 0x00, 0xA6, 0x27,
-0x21, 0x38, 0x20, 0x02, 0x4C, 0x52, 0x00, 0x0C, 0x18, 0x00, 0xB6, 0xA7,
-0x20, 0x40, 0x63, 0x8E, 0x21, 0x80, 0x40, 0x00, 0x03, 0x00, 0x02, 0x24,
-0x28, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0xA2, 0x26,
-0xB6, 0x40, 0x43, 0x90, 0x04, 0x00, 0x07, 0x24, 0x21, 0x20, 0x40, 0x02,
-0x01, 0x00, 0x63, 0x38, 0x21, 0x30, 0xE0, 0x02, 0x0B, 0x38, 0x03, 0x00,
-0xDF, 0x0D, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x40, 0x00, 0xBF, 0x8F,
-0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F, 0x34, 0x00, 0xB5, 0x8F,
-0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB2, 0x8F,
-0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x48, 0x00, 0xBD, 0x27, 0xB0, 0x1B, 0x02, 0x95, 0x00, 0x00, 0x00, 0x00,
-0x40, 0x00, 0x42, 0x30, 0xCD, 0xFF, 0x40, 0x10, 0x60, 0x1B, 0xB3, 0x26,
-0x2C, 0x40, 0x03, 0x8D, 0x30, 0x40, 0x02, 0x8D, 0x21, 0x20, 0x00, 0x02,
-0x80, 0x1F, 0x03, 0x00, 0x25, 0x18, 0x43, 0x00, 0x04, 0x00, 0x05, 0x24,
-0x01, 0x00, 0x42, 0x24, 0x1C, 0x00, 0xA6, 0x27, 0x21, 0x38, 0x20, 0x02,
-0x30, 0x40, 0x02, 0xAD, 0x4C, 0x52, 0x00, 0x0C, 0x1C, 0x00, 0xA3, 0xAF,
-0x69, 0x14, 0x00, 0x08, 0x21, 0x80, 0x40, 0x00, 0xB0, 0x1B, 0x62, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x42, 0x30, 0xD6, 0xFF, 0x40, 0x10,
-0x60, 0x1B, 0xA2, 0x26, 0x02, 0x80, 0x07, 0x3C, 0x21, 0x20, 0x00, 0x02,
-0x94, 0x5B, 0xE7, 0x24, 0x10, 0x00, 0x05, 0x24, 0x80, 0x00, 0x06, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB1, 0xAF, 0x00, 0x00, 0x83, 0x96,
-0x01, 0x00, 0x17, 0x24, 0x00, 0x40, 0x63, 0x34, 0x85, 0x14, 0x00, 0x08,
-0x00, 0x00, 0x83, 0xA6, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0xAC, 0xE8, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0xEC, 0xEA, 0xA5, 0x24,
-0x40, 0x00, 0xBF, 0x8F, 0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F,
-0x34, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F,
-0x28, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27, 0xB0, 0xFF, 0xBD, 0x27,
-0x38, 0x00, 0xB4, 0xAF, 0x34, 0x00, 0xB3, 0xAF, 0x30, 0x00, 0xB2, 0xAF,
-0x2C, 0x00, 0xB1, 0xAF, 0x28, 0x00, 0xB0, 0xAF, 0x48, 0x00, 0xBF, 0xAF,
-0x44, 0x00, 0xB7, 0xAF, 0x40, 0x00, 0xB6, 0xAF, 0x3C, 0x00, 0xB5, 0xAF,
-0x02, 0x00, 0x82, 0x90, 0x02, 0x80, 0x12, 0x3C, 0x21, 0xA0, 0x80, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0xC0, 0x10, 0x02, 0x00, 0x21, 0x80, 0x44, 0x00,
-0x28, 0x00, 0x11, 0x26, 0xB4, 0x55, 0x45, 0x26, 0x21, 0x20, 0x20, 0x02,
-0x06, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x18, 0x00, 0x13, 0x26,
-0x9F, 0x00, 0x40, 0x10, 0x21, 0x20, 0x60, 0x02, 0x02, 0x80, 0x15, 0x3C,
-0x60, 0x1B, 0xA2, 0x26, 0x4B, 0x41, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x82, 0x00, 0x60, 0x10, 0x3C, 0x00, 0x04, 0x26, 0x60, 0x1B, 0xB0, 0x26,
-0xB0, 0x1B, 0x03, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0x30,
-0x6D, 0x00, 0x40, 0x14, 0x10, 0x00, 0x62, 0x30, 0x13, 0x00, 0x40, 0x14,
-0x10, 0x00, 0x76, 0x26, 0x60, 0x1B, 0xB0, 0x26, 0xB0, 0x1B, 0x02, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30, 0x8F, 0x00, 0x40, 0x14,
-0x21, 0x18, 0x00, 0x00, 0x48, 0x00, 0xBF, 0x8F, 0x44, 0x00, 0xB7, 0x8F,
-0x40, 0x00, 0xB6, 0x8F, 0x3C, 0x00, 0xB5, 0x8F, 0x38, 0x00, 0xB4, 0x8F,
-0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F,
-0x28, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x50, 0x00, 0xBD, 0x27, 0x21, 0x20, 0xC0, 0x02, 0xB4, 0x55, 0x45, 0x26,
-0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0xE9, 0xFF, 0x40, 0x14,
-0x07, 0x00, 0x02, 0x24, 0xB6, 0x40, 0x02, 0xA2, 0xE8, 0x39, 0x00, 0xAE,
-0x00, 0x00, 0x84, 0x8E, 0x0C, 0x00, 0x12, 0x24, 0xFF, 0x3F, 0x82, 0x30,
-0xE8, 0xFF, 0x42, 0x24, 0x2A, 0x10, 0x42, 0x02, 0x9C, 0x00, 0x40, 0x10,
-0x21, 0xB8, 0x00, 0x02, 0x1F, 0x15, 0x00, 0x08, 0x21, 0x80, 0x72, 0x02,
-0x19, 0x00, 0x03, 0x92, 0xFF, 0x3F, 0x82, 0x30, 0xE8, 0xFF, 0x42, 0x24,
-0x21, 0x18, 0x72, 0x00, 0x02, 0x00, 0x72, 0x24, 0x2A, 0x10, 0x42, 0x02,
-0x93, 0x00, 0x40, 0x10, 0x60, 0x1B, 0xB0, 0x26, 0x21, 0x80, 0x72, 0x02,
-0x18, 0x00, 0x03, 0x92, 0xDD, 0x00, 0x02, 0x24, 0xF4, 0xFF, 0x62, 0x14,
-0x1A, 0x00, 0x11, 0x26, 0x02, 0x80, 0x05, 0x3C, 0x64, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x55, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x60, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x4F, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x54, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x44, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x50, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x3E, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x4C, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x38, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x44, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x3B, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x40, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x53, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x48, 0xDE, 0xA5, 0x24,
-0x21, 0x20, 0x20, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x47, 0x01, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x21, 0x20, 0x20, 0x02,
-0x34, 0xDE, 0xA5, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x04, 0x00, 0x06, 0x24,
-0x2F, 0x01, 0x40, 0x10, 0x02, 0x00, 0x02, 0x24, 0x00, 0x00, 0x84, 0x8E,
-0x16, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x11, 0x00, 0x0C,
-0x21, 0x20, 0x80, 0x02, 0x21, 0x18, 0x00, 0x00, 0x48, 0x00, 0xBF, 0x8F,
-0x44, 0x00, 0xB7, 0x8F, 0x40, 0x00, 0xB6, 0x8F, 0x3C, 0x00, 0xB5, 0x8F,
-0x38, 0x00, 0xB4, 0x8F, 0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F,
-0x2C, 0x00, 0xB1, 0x8F, 0x28, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x50, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x87, 0x8E,
-0x07, 0x00, 0x05, 0x24, 0xFF, 0x3F, 0xE7, 0x30, 0xDC, 0xFF, 0xE7, 0x24,
-0xAB, 0x1A, 0x00, 0x0C, 0x20, 0x00, 0xA6, 0x27, 0x78, 0xFF, 0x40, 0x10,
-0x21, 0x38, 0x40, 0x00, 0x20, 0x00, 0xA5, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x06, 0x00, 0xA2, 0x28, 0x73, 0xFF, 0x40, 0x14, 0xFD, 0xFF, 0xA5, 0x24,
-0x05, 0x00, 0xE4, 0x24, 0xE5, 0x4B, 0x00, 0x0C, 0xFF, 0x00, 0xA5, 0x30,
-0x02, 0x80, 0x04, 0x3C, 0xAC, 0x5C, 0x84, 0x24, 0x21, 0x28, 0x20, 0x02,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0xEC, 0x14, 0x00, 0x08,
-0x60, 0x1B, 0xB0, 0x26, 0xB9, 0x2B, 0x00, 0x0C, 0x21, 0x28, 0x80, 0x02,
-0xE6, 0x14, 0x00, 0x08, 0x02, 0x80, 0x15, 0x3C, 0xB4, 0x55, 0x45, 0x26,
-0x10, 0x00, 0x64, 0x26, 0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0xD4, 0xFF, 0x40, 0x14, 0x21, 0x18, 0x00, 0x00, 0x21, 0x20, 0x80, 0x02,
-0xE3, 0x17, 0x00, 0x0C, 0x18, 0x00, 0x85, 0x26, 0x21, 0x20, 0x40, 0x00,
-0x8D, 0x17, 0x00, 0x0C, 0x05, 0x00, 0x05, 0x24, 0xB0, 0x1B, 0x03, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x62, 0x30, 0x0C, 0x00, 0x40, 0x14,
-0x04, 0x00, 0x62, 0x30, 0x4B, 0x00, 0x40, 0x14, 0x60, 0x1B, 0xB0, 0x26,
-0xB7, 0x40, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x44, 0x24,
-0xFF, 0x00, 0x83, 0x30, 0x15, 0x00, 0x02, 0x24, 0x5D, 0x00, 0x62, 0x10,
-0x21, 0x18, 0x00, 0x00, 0xF9, 0x14, 0x00, 0x08, 0xB7, 0x40, 0x04, 0xA2,
-0x8A, 0x40, 0x00, 0x0C, 0x24, 0x00, 0xA4, 0x27, 0xE8, 0x1E, 0x03, 0x8E,
-0xEC, 0x1E, 0x02, 0x8E, 0x24, 0x00, 0xA4, 0x27, 0x01, 0x00, 0x63, 0x24,
-0x01, 0x00, 0x42, 0x24, 0xEC, 0x1E, 0x02, 0xAE, 0x90, 0x40, 0x00, 0x0C,
-0xE8, 0x1E, 0x03, 0xAE, 0x9A, 0x15, 0x00, 0x08, 0x60, 0x1B, 0xB0, 0x26,
-0x60, 0x1B, 0xB0, 0x26, 0xB6, 0x40, 0x03, 0x92, 0x07, 0x00, 0x02, 0x24,
-0x21, 0x00, 0x62, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x04, 0x3C,
-0x5C, 0xEB, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xCE, 0x5C, 0x46, 0x90, 0x01, 0x00, 0x03, 0x24,
-0x0F, 0x00, 0xC3, 0x10, 0x60, 0x1B, 0xA4, 0x26, 0xD5, 0x4E, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0xBF, 0x8F, 0x44, 0x00, 0xB7, 0x8F,
-0x40, 0x00, 0xB6, 0x8F, 0x3C, 0x00, 0xB5, 0x8F, 0x38, 0x00, 0xB4, 0x8F,
-0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F,
-0x28, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x50, 0x00, 0xBD, 0x27, 0xB6, 0x40, 0x83, 0x90, 0x03, 0x00, 0x02, 0x24,
-0x2A, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x41, 0x86, 0xA0,
-0xD5, 0x4E, 0x00, 0x0C, 0x3C, 0x41, 0x80, 0xA0, 0xBF, 0x15, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x5C, 0xDE, 0xA5, 0x24, 0x21, 0x20, 0xC0, 0x02,
-0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24, 0x07, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x05, 0x3C, 0x21, 0x20, 0xC0, 0x02, 0x58, 0xDE, 0xA5, 0x24,
-0x1D, 0x55, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24, 0xD5, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x70, 0xEB, 0x84, 0x24,
-0xB6, 0x15, 0x00, 0x08, 0xB6, 0x40, 0x00, 0xA2, 0x0A, 0x00, 0x76, 0x26,
-0x1F, 0x54, 0x00, 0x0C, 0x21, 0x20, 0xC0, 0x02, 0x20, 0x00, 0x10, 0x24,
-0x37, 0x00, 0x50, 0x10, 0x21, 0x88, 0x40, 0x00, 0x8A, 0x40, 0x00, 0x0C,
-0x24, 0x00, 0xA4, 0x27, 0x40, 0x10, 0x11, 0x00, 0x21, 0x10, 0x51, 0x00,
-0x60, 0x1B, 0xA4, 0x26, 0x00, 0x11, 0x02, 0x00, 0x21, 0x10, 0x44, 0x00,
-0xF8, 0x1D, 0x43, 0x8C, 0x24, 0x00, 0xA4, 0x27, 0x01, 0x00, 0x63, 0x24,
-0x90, 0x40, 0x00, 0x0C, 0xF8, 0x1D, 0x43, 0xAC, 0x60, 0x15, 0x00, 0x08,
-0x21, 0x18, 0x00, 0x00, 0x3C, 0x41, 0x86, 0xA0, 0xD5, 0x4E, 0x00, 0x0C,
-0x3D, 0x41, 0x80, 0xA0, 0xBF, 0x15, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x55, 0x12, 0x00, 0x0C, 0xB7, 0x40, 0x00, 0xA2, 0x02, 0x80, 0x02, 0x3C,
-0xD2, 0x5C, 0x44, 0x90, 0x02, 0x00, 0x03, 0x24, 0x5D, 0xFF, 0x83, 0x14,
-0x21, 0x18, 0x00, 0x00, 0x00, 0x00, 0x87, 0x8E, 0x24, 0x00, 0x64, 0x26,
-0x2A, 0x00, 0x05, 0x24, 0xFF, 0x3F, 0xE7, 0x30, 0xDC, 0xFF, 0xE7, 0x24,
-0xAB, 0x1A, 0x00, 0x0C, 0x20, 0x00, 0xA6, 0x27, 0x54, 0xFF, 0x40, 0x10,
-0x21, 0x18, 0x00, 0x00, 0x02, 0x00, 0x44, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x82, 0x30, 0x95, 0x00, 0x40, 0x10, 0x60, 0x1B, 0xA5, 0x26,
-0x01, 0x00, 0x82, 0x30, 0x92, 0x00, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C,
-0xD3, 0x5C, 0x44, 0x90, 0x01, 0x00, 0x03, 0x24, 0x9F, 0x00, 0x83, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xFC, 0x23, 0x02, 0x8E, 0xFF, 0xEF, 0x03, 0x24,
-0x00, 0x08, 0x42, 0x34, 0x24, 0x10, 0x43, 0x00, 0xFC, 0x23, 0x02, 0xAE,
-0x60, 0x15, 0x00, 0x08, 0x21, 0x18, 0x00, 0x00, 0xFF, 0xFF, 0x04, 0x24,
-0xC7, 0x53, 0x00, 0x0C, 0x21, 0x28, 0xC0, 0x02, 0xC6, 0xFF, 0x50, 0x10,
-0x21, 0x88, 0x40, 0x00, 0x00, 0x00, 0x87, 0x8E, 0x24, 0x00, 0x77, 0x26,
-0x21, 0x20, 0xE0, 0x02, 0xFF, 0x3F, 0xE7, 0x30, 0xDC, 0xFF, 0xE7, 0x24,
-0x01, 0x00, 0x05, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x20, 0x00, 0xA6, 0x27,
-0xCB, 0xFE, 0x40, 0x10, 0x21, 0x18, 0x00, 0x00, 0x20, 0x00, 0xA6, 0x8F,
-0x02, 0x00, 0x45, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x87, 0x8E, 0x21, 0x20, 0xE0, 0x02, 0x32, 0x00, 0x05, 0x24,
-0xFF, 0x3F, 0xE7, 0x30, 0xDC, 0xFF, 0xE7, 0x24, 0x20, 0x00, 0xB0, 0x8F,
-0xAB, 0x1A, 0x00, 0x0C, 0x20, 0x00, 0xA6, 0x27, 0x08, 0x00, 0x40, 0x10,
-0x10, 0x00, 0xA4, 0x27, 0x20, 0x00, 0xA6, 0x8F, 0x21, 0x20, 0x90, 0x00,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x45, 0x24, 0x20, 0x00, 0xA3, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x80, 0x03, 0x02, 0x10, 0x00, 0xA4, 0x27,
-0x61, 0x53, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x02, 0x21, 0x28, 0x00, 0x02,
-0x10, 0x00, 0xA4, 0x27, 0xA6, 0x53, 0x00, 0x0C, 0x0F, 0x00, 0x53, 0x30,
-0x00, 0x00, 0x87, 0x8E, 0x21, 0x20, 0xE0, 0x02, 0x2D, 0x00, 0x05, 0x24,
-0xFF, 0x3F, 0xE7, 0x30, 0xDC, 0xFF, 0xE7, 0x24, 0x20, 0x00, 0xA6, 0x27,
-0xAB, 0x1A, 0x00, 0x0C, 0x21, 0x90, 0x40, 0x00, 0x11, 0x00, 0x40, 0x10,
-0x00, 0x81, 0x11, 0x00, 0x06, 0x00, 0x44, 0x90, 0x05, 0x00, 0x43, 0x90,
-0x02, 0x80, 0x02, 0x3C, 0xC6, 0x5C, 0x45, 0x90, 0x00, 0x1B, 0x03, 0x00,
-0x00, 0x25, 0x04, 0x00, 0x25, 0x18, 0x64, 0x00, 0x10, 0x00, 0xA5, 0x30,
-0x25, 0x90, 0x43, 0x02, 0x02, 0x00, 0xA0, 0x14, 0x0F, 0x00, 0x02, 0x3C,
-0xFF, 0x0F, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34, 0x24, 0x90, 0x42, 0x02,
-0x08, 0x00, 0x73, 0x36, 0x00, 0x81, 0x11, 0x00, 0x25, 0x80, 0x13, 0x02,
-0xFF, 0xFF, 0x10, 0x32, 0x02, 0x80, 0x04, 0x3C, 0x21, 0x28, 0x20, 0x02,
-0x21, 0x30, 0x00, 0x02, 0x21, 0x38, 0x40, 0x02, 0x13, 0x58, 0x00, 0x0C,
-0x8C, 0xEB, 0x84, 0x24, 0x21, 0x20, 0x00, 0x02, 0x63, 0x5E, 0x00, 0x74,
-0x21, 0x28, 0x40, 0x02, 0x60, 0x1B, 0xA3, 0x26, 0x3A, 0x41, 0x62, 0x90,
-0x21, 0x20, 0xC0, 0x02, 0x21, 0x28, 0x20, 0x02, 0x01, 0x00, 0x42, 0x24,
-0xEA, 0x0E, 0x00, 0x0C, 0x3A, 0x41, 0x62, 0xA0, 0xEA, 0x15, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x01, 0x00, 0x02, 0x24,
-0xA0, 0xEB, 0x84, 0x24, 0xB6, 0x15, 0x00, 0x08, 0xB6, 0x40, 0xE2, 0xA2,
-0x02, 0x80, 0x04, 0x3C, 0xB8, 0xEB, 0x84, 0x24, 0xB6, 0x15, 0x00, 0x08,
-0xB6, 0x40, 0xE0, 0xA2, 0x02, 0x80, 0x04, 0x3C, 0x60, 0x1B, 0xA3, 0x26,
-0x03, 0x00, 0x02, 0x24, 0xCC, 0xEB, 0x84, 0x24, 0xB6, 0x15, 0x00, 0x08,
-0xB6, 0x40, 0x62, 0xA0, 0x1E, 0x00, 0x03, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x00, 0x62, 0x14, 0x02, 0x80, 0x04, 0x3C, 0x20, 0x00, 0x02, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x30, 0x05, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0xC8, 0xDF, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x1A, 0x00, 0x60, 0x14, 0x11, 0x00, 0x03, 0x24, 0x13, 0x58, 0x00, 0x0C,
-0xE0, 0xEB, 0x84, 0x24, 0x05, 0x00, 0x02, 0x24, 0xB8, 0x15, 0x00, 0x08,
-0xB6, 0x40, 0xE2, 0xA2, 0x02, 0x80, 0x04, 0x3C, 0x60, 0x1B, 0xA3, 0x26,
-0x02, 0x00, 0x02, 0x24, 0xF8, 0xEB, 0x84, 0x24, 0xB6, 0x15, 0x00, 0x08,
-0xB6, 0x40, 0x62, 0xA0, 0x02, 0x80, 0x04, 0x3C, 0x60, 0x1B, 0xA3, 0x26,
-0x04, 0x00, 0x02, 0x24, 0x0C, 0xEC, 0x84, 0x24, 0xB6, 0x15, 0x00, 0x08,
-0xB6, 0x40, 0x62, 0xA0, 0xFC, 0x23, 0xA2, 0x8C, 0xFF, 0xEF, 0x03, 0x24,
-0xFF, 0xF7, 0x04, 0x24, 0x24, 0x10, 0x43, 0x00, 0x24, 0x10, 0x44, 0x00,
-0x21, 0x18, 0x00, 0x00, 0x60, 0x15, 0x00, 0x08, 0xFC, 0x23, 0xA2, 0xAC,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x20, 0xEC, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0xC6, 0x5C, 0x43, 0xA0, 0x60, 0x1B, 0xA3, 0x26,
-0x06, 0x00, 0x02, 0x24, 0xB8, 0x15, 0x00, 0x08, 0xB6, 0x40, 0x62, 0xA0,
-0xFC, 0x23, 0x02, 0x8E, 0xFF, 0xF7, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0x00, 0x10, 0x42, 0x34, 0x1E, 0x16, 0x00, 0x08, 0xFC, 0x23, 0x02, 0xAE,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x10, 0x3C, 0x60, 0x1B, 0x02, 0x26,
-0x14, 0x00, 0xBF, 0xAF, 0xB0, 0x1B, 0x43, 0x94, 0x21, 0x28, 0x00, 0x00,
-0x00, 0x01, 0x62, 0x30, 0x03, 0x00, 0x40, 0x10, 0x01, 0x00, 0x64, 0x30,
-0x06, 0x00, 0x80, 0x14, 0x00, 0x10, 0x62, 0x30, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0xA0, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x08, 0x00, 0x40, 0x14, 0x60, 0x1B, 0x04, 0x26,
-0x02, 0x80, 0x02, 0x3C, 0xEE, 0x5D, 0x43, 0x90, 0x0C, 0x00, 0x02, 0x24,
-0x0F, 0x00, 0x63, 0x30, 0x09, 0x00, 0x62, 0x10, 0x21, 0x20, 0x00, 0x00,
-0x60, 0x1B, 0x04, 0x26, 0x60, 0xEA, 0x03, 0x34, 0x04, 0x3A, 0x83, 0xAC,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0xA0, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x0E, 0x51, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x04, 0x26, 0x60, 0xEA, 0x03, 0x34,
-0xDB, 0x16, 0x00, 0x08, 0x04, 0x3A, 0x83, 0xAC, 0xD8, 0xFF, 0xBD, 0x27,
-0x1C, 0x00, 0xB1, 0xAF, 0x02, 0x80, 0x11, 0x3C, 0x18, 0x00, 0xB0, 0xAF,
-0x20, 0x00, 0xBF, 0xAF, 0x60, 0x1B, 0x30, 0x26, 0x04, 0x3E, 0x02, 0x8E,
-0x00, 0x10, 0x03, 0x3C, 0x24, 0x10, 0x43, 0x00, 0x12, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x33, 0x3E, 0x03, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x63, 0x24, 0xFF, 0x00, 0x62, 0x30, 0x21, 0x10, 0x50, 0x00,
-0xD0, 0x3D, 0x45, 0x90, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xA4, 0x30,
-0x18, 0x00, 0x80, 0x10, 0x33, 0x3E, 0x03, 0xA2, 0xFF, 0x3D, 0x02, 0x92,
-0xC4, 0x3D, 0x05, 0xA2, 0x75, 0x0D, 0x00, 0x0C, 0xC5, 0x3D, 0x02, 0xA2,
-0xC4, 0x3D, 0x04, 0x92, 0x38, 0x0D, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24,
-0x08, 0x3E, 0x03, 0x8E, 0x01, 0x00, 0x02, 0x24, 0x52, 0x00, 0x62, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x25, 0x26, 0x04, 0x3E, 0xA4, 0x8C,
-0x00, 0x10, 0x02, 0x3C, 0x3C, 0x00, 0x03, 0x24, 0x26, 0x20, 0x82, 0x00,
-0x94, 0x39, 0xA3, 0xAC, 0x04, 0x3E, 0xA4, 0xAC, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xB0, 0x1B, 0x02, 0x96, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0xEF, 0x42, 0x30, 0x00, 0x01, 0x43, 0x30, 0x49, 0x00, 0x60, 0x14,
-0xB0, 0x1B, 0x02, 0xA6, 0x31, 0x3E, 0x06, 0x92, 0x37, 0x3E, 0x03, 0x92,
-0x32, 0x3E, 0x05, 0x92, 0x25, 0xB0, 0x02, 0x3C, 0x4C, 0x00, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xA0, 0xFF, 0x00, 0xC4, 0x30, 0xC5, 0x3D, 0x05, 0xA2,
-0x75, 0x0D, 0x00, 0x0C, 0xC4, 0x3D, 0x06, 0xA2, 0xC4, 0x3D, 0x04, 0x92,
-0x38, 0x0D, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0xB0, 0x1B, 0x03, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x30, 0x09, 0x00, 0x40, 0x10,
-0x01, 0x00, 0x62, 0x30, 0x08, 0x00, 0x40, 0x10, 0x60, 0x1B, 0x30, 0x26,
-0x02, 0x80, 0x02, 0x3C, 0xEE, 0x5D, 0x43, 0x90, 0x0C, 0x00, 0x02, 0x24,
-0x0F, 0x00, 0x63, 0x30, 0x58, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x30, 0x26, 0x34, 0x3E, 0x04, 0x96, 0x36, 0x3E, 0x05, 0x92,
-0x95, 0x0E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x11, 0x48, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xA4, 0x27, 0x8A, 0x40, 0x00, 0x0C,
-0x04, 0x3E, 0x00, 0xAE, 0xB0, 0x1B, 0x02, 0x96, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x01, 0x42, 0x30, 0x2A, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0xEC, 0x5D, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x60, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0xEE, 0x5D, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x28,
-0x3A, 0x00, 0x40, 0x14, 0x04, 0x00, 0x04, 0x24, 0x02, 0x80, 0x03, 0x3C,
-0x0E, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x0E, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x42, 0x24, 0x0E, 0x5E, 0x62, 0xA0, 0x72, 0x17, 0x00, 0x08,
-0x60, 0x1B, 0x30, 0x26, 0xC4, 0x3D, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0x42, 0x2C, 0xAB, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x12, 0x49, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x07, 0x17, 0x00, 0x08,
-0x60, 0x1B, 0x25, 0x26, 0x25, 0xB0, 0x05, 0x3C, 0x48, 0x00, 0xA5, 0x34,
-0x00, 0x00, 0xA3, 0x8C, 0x60, 0x1B, 0x24, 0x8E, 0x84, 0x00, 0x02, 0x3C,
-0x25, 0x18, 0x62, 0x00, 0x25, 0x00, 0x84, 0x34, 0x00, 0x00, 0xA3, 0xAC,
-0x18, 0x17, 0x00, 0x08, 0x60, 0x1B, 0x24, 0xAE, 0x02, 0x80, 0x02, 0x3C,
-0x0E, 0x5E, 0x40, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x64, 0x90,
-0x01, 0x00, 0x05, 0x24, 0x4B, 0x2E, 0x00, 0x0C, 0xFF, 0x00, 0x84, 0x30,
-0x60, 0x1B, 0x30, 0x26, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x52, 0x41, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x96, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0x2C, 0x59, 0x84, 0x24,
-0xA0, 0xDD, 0xA5, 0x24, 0x34, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x4B, 0x41, 0x00, 0xA2, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x0D, 0x17, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x2E, 0x00, 0x0C,
-0x01, 0x00, 0x05, 0x24, 0x4D, 0x17, 0x00, 0x08, 0x02, 0x80, 0x03, 0x3C,
-0x0E, 0x51, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00, 0x33, 0x17, 0x00, 0x08,
-0x60, 0x1B, 0x30, 0x26, 0x02, 0x80, 0x09, 0x3C, 0x60, 0x1B, 0x28, 0x25,
-0x6C, 0x37, 0x06, 0x8D, 0xFF, 0xFF, 0x02, 0x34, 0x44, 0x00, 0xC2, 0x10,
-0x21, 0x38, 0x80, 0x00, 0x2B, 0x10, 0xC7, 0x00, 0x34, 0x00, 0x40, 0x10,
-0x02, 0x19, 0x06, 0x00, 0x21, 0x10, 0xC7, 0x00, 0x23, 0x10, 0x43, 0x00,
-0x10, 0x00, 0x46, 0x24, 0x6C, 0x37, 0x06, 0xAD, 0x70, 0x37, 0x02, 0xAD,
-0x60, 0x1B, 0x26, 0x25, 0x05, 0x00, 0xC4, 0x90, 0xFF, 0xFF, 0x02, 0x34,
-0xFF, 0x00, 0x83, 0x30, 0x33, 0x00, 0x62, 0x10, 0x00, 0x11, 0x07, 0x00,
-0xFF, 0x00, 0x84, 0x30, 0x2B, 0x10, 0x87, 0x00, 0x20, 0x00, 0x40, 0x10,
-0x03, 0x19, 0x04, 0x00, 0x03, 0x11, 0x04, 0x00, 0x21, 0x18, 0x87, 0x00,
-0x23, 0x18, 0x62, 0x00, 0x10, 0x00, 0x64, 0x24, 0x05, 0x00, 0xC4, 0xA0,
-0x70, 0x37, 0xC3, 0xAC, 0xC0, 0x10, 0x05, 0x00, 0x21, 0x10, 0x45, 0x00,
-0x80, 0x10, 0x02, 0x00, 0x21, 0x10, 0x45, 0x00, 0x60, 0x1B, 0x23, 0x25,
-0x80, 0x10, 0x02, 0x00, 0x21, 0x28, 0x43, 0x00, 0xF8, 0x24, 0xA6, 0x8C,
-0x00, 0x21, 0x07, 0x00, 0xFF, 0xFF, 0xC2, 0x38, 0x0A, 0x30, 0x82, 0x00,
-0x2B, 0x18, 0xC7, 0x00, 0x07, 0x00, 0x60, 0x10, 0x21, 0x10, 0xC7, 0x00,
-0x02, 0x19, 0x06, 0x00, 0x23, 0x10, 0x43, 0x00, 0x10, 0x00, 0x46, 0x24,
-0xF8, 0x24, 0xA6, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0xFC, 0x24, 0xA2, 0xAC,
-0x02, 0x19, 0x06, 0x00, 0x23, 0x10, 0x43, 0x00, 0xF8, 0x24, 0xA2, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0xFC, 0x24, 0xA2, 0xAC, 0x21, 0x10, 0x87, 0x00,
-0x23, 0x10, 0x43, 0x00, 0x05, 0x00, 0xC2, 0xA0, 0xAB, 0x17, 0x00, 0x08,
-0x70, 0x37, 0xC2, 0xAC, 0x21, 0x10, 0xC7, 0x00, 0x23, 0x10, 0x43, 0x00,
-0x6C, 0x37, 0x02, 0xAD, 0x70, 0x37, 0x02, 0xAD, 0x60, 0x1B, 0x26, 0x25,
-0x05, 0x00, 0xC4, 0x90, 0xFF, 0xFF, 0x02, 0x34, 0xFF, 0x00, 0x83, 0x30,
-0xCF, 0xFF, 0x62, 0x14, 0x00, 0x11, 0x07, 0x00, 0x21, 0x20, 0x40, 0x00,
-0xA1, 0x17, 0x00, 0x08, 0x05, 0x00, 0xC2, 0xA0, 0x00, 0x31, 0x04, 0x00,
-0x93, 0x17, 0x00, 0x08, 0x6C, 0x37, 0x06, 0xAD, 0x63, 0x00, 0x82, 0x24,
-0x77, 0x00, 0x42, 0x2C, 0x00, 0x00, 0x85, 0x28, 0x04, 0x00, 0x40, 0x10,
-0x21, 0x18, 0x00, 0x00, 0x64, 0x00, 0x82, 0x24, 0x64, 0x00, 0x03, 0x24,
-0x0B, 0x18, 0x45, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF, 0x0C, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x28,
-0x08, 0x00, 0x40, 0x14, 0x25, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0xA4, 0x8C,
-0x10, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xBD, 0x27, 0x3F, 0x00, 0x84, 0x30,
-0x40, 0x20, 0x04, 0x00, 0xD9, 0x17, 0x00, 0x08, 0x96, 0xFF, 0x84, 0x24,
-0x24, 0x08, 0x42, 0x34, 0x00, 0x00, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x02, 0x63, 0x30, 0x1B, 0x00, 0x60, 0x14, 0x01, 0x00, 0x02, 0x24,
-0x05, 0x00, 0xA3, 0x90, 0x00, 0x00, 0x00, 0x00, 0x82, 0x31, 0x03, 0x00,
-0x3C, 0x00, 0xC2, 0x10, 0x02, 0x00, 0xC2, 0x28, 0x57, 0x00, 0x40, 0x14,
-0x02, 0x00, 0x02, 0x24, 0x46, 0x00, 0xC2, 0x10, 0x03, 0x00, 0x02, 0x24,
-0x2E, 0x00, 0xC2, 0x10, 0x3E, 0x00, 0x63, 0x30, 0xD9, 0x17, 0x00, 0x0C,
-0x21, 0x20, 0xE0, 0x00, 0x06, 0x00, 0x45, 0x24, 0x65, 0x00, 0xA4, 0x2C,
-0x64, 0x00, 0x03, 0x24, 0x0A, 0x28, 0x64, 0x00, 0xDD, 0xFF, 0xA2, 0x24,
-0x08, 0x00, 0x42, 0x2C, 0x1F, 0x00, 0x40, 0x10, 0xE5, 0xFF, 0xA2, 0x24,
-0xFE, 0xFF, 0xA5, 0x24, 0x10, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0xA0, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x05, 0x00, 0xA3, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x66, 0x30, 0x42, 0x31, 0x06, 0x00,
-0x25, 0x00, 0xC2, 0x10, 0x02, 0x00, 0xC2, 0x28, 0x36, 0x00, 0x40, 0x14,
-0x02, 0x00, 0x02, 0x24, 0x2F, 0x00, 0xC2, 0x10, 0x03, 0x00, 0x02, 0x24,
-0xE6, 0xFF, 0xC2, 0x14, 0x1F, 0x00, 0x62, 0x30, 0x40, 0x10, 0x02, 0x00,
-0xD8, 0xFF, 0x03, 0x24, 0x23, 0x38, 0x62, 0x00, 0xD9, 0x17, 0x00, 0x0C,
-0x21, 0x20, 0xE0, 0x00, 0x06, 0x00, 0x45, 0x24, 0x65, 0x00, 0xA4, 0x2C,
-0x64, 0x00, 0x03, 0x24, 0x0A, 0x28, 0x64, 0x00, 0xDD, 0xFF, 0xA2, 0x24,
-0x08, 0x00, 0x42, 0x2C, 0xE3, 0xFF, 0x40, 0x14, 0xE5, 0xFF, 0xA2, 0x24,
-0x08, 0x00, 0x42, 0x2C, 0x06, 0x00, 0x40, 0x10, 0xF1, 0xFF, 0xA2, 0x24,
-0x0E, 0x18, 0x00, 0x08, 0xFA, 0xFF, 0xA5, 0x24, 0xD8, 0xFF, 0x02, 0x24,
-0x03, 0x18, 0x00, 0x08, 0x23, 0x38, 0x43, 0x00, 0x0C, 0x00, 0x42, 0x2C,
-0x0C, 0x00, 0x40, 0x10, 0xFB, 0xFF, 0xA2, 0x24, 0x0E, 0x18, 0x00, 0x08,
-0xF8, 0xFF, 0xA5, 0x24, 0x3E, 0x00, 0x63, 0x30, 0xFE, 0xFF, 0x02, 0x24,
-0x03, 0x18, 0x00, 0x08, 0x23, 0x38, 0x43, 0x00, 0x1F, 0x00, 0x62, 0x30,
-0x40, 0x10, 0x02, 0x00, 0xFE, 0xFF, 0x03, 0x24, 0x21, 0x18, 0x00, 0x08,
-0x23, 0x38, 0x62, 0x00, 0x0A, 0x00, 0x42, 0x2C, 0xCB, 0xFF, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x0E, 0x18, 0x00, 0x08, 0xFC, 0xFF, 0xA5, 0x24,
-0x3E, 0x00, 0x63, 0x30, 0xEC, 0xFF, 0x02, 0x24, 0x03, 0x18, 0x00, 0x08,
-0x23, 0x38, 0x43, 0x00, 0x1F, 0x00, 0x62, 0x30, 0x40, 0x10, 0x02, 0x00,
-0xEC, 0xFF, 0x03, 0x24, 0x21, 0x18, 0x00, 0x08, 0x23, 0x38, 0x62, 0x00,
-0xB3, 0xFF, 0xC0, 0x14, 0x1F, 0x00, 0x62, 0x30, 0x40, 0x10, 0x02, 0x00,
-0x0E, 0x00, 0x03, 0x24, 0x21, 0x18, 0x00, 0x08, 0x23, 0x38, 0x62, 0x00,
-0xAD, 0xFF, 0xC0, 0x14, 0x3E, 0x00, 0x63, 0x30, 0x0E, 0x00, 0x02, 0x24,
-0x03, 0x18, 0x00, 0x08, 0x23, 0x38, 0x43, 0x00, 0x98, 0xFF, 0xBD, 0x27,
-0x64, 0x00, 0xBF, 0xAF, 0x60, 0x00, 0xBE, 0xAF, 0x5C, 0x00, 0xB7, 0xAF,
-0x58, 0x00, 0xB6, 0xAF, 0x54, 0x00, 0xB5, 0xAF, 0x50, 0x00, 0xB4, 0xAF,
-0x4C, 0x00, 0xB3, 0xAF, 0x48, 0x00, 0xB2, 0xAF, 0x44, 0x00, 0xB1, 0xAF,
-0x40, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x02, 0x3C, 0x88, 0x54, 0x45, 0x8C,
-0x00, 0x80, 0x04, 0x3C, 0x68, 0x61, 0x83, 0x24, 0x88, 0x54, 0x44, 0x24,
-0x25, 0xB0, 0x02, 0x3C, 0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x81, 0x00, 0xA4, 0x10, 0x02, 0x80, 0x02, 0x3C, 0xE8, 0xEC, 0x42, 0x24,
-0x00, 0x00, 0x5E, 0x8C, 0x02, 0x80, 0x03, 0x3C, 0xEC, 0xEC, 0x63, 0x24,
-0x00, 0x00, 0x75, 0x8C, 0x28, 0x39, 0xD6, 0x8F, 0x21, 0xB8, 0x00, 0x00,
-0x08, 0x00, 0xC2, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xAE,
-0x08, 0x00, 0xC3, 0x96, 0x02, 0x80, 0x02, 0x3C, 0x9E, 0x18, 0x00, 0x08,
-0x25, 0xA0, 0x62, 0x00, 0x17, 0x00, 0x25, 0x92, 0x16, 0x00, 0x26, 0x92,
-0xC8, 0x3D, 0xC2, 0x97, 0xFF, 0x00, 0xA3, 0x30, 0x00, 0x1A, 0x03, 0x00,
-0xFF, 0x00, 0xC4, 0x30, 0x25, 0x18, 0x64, 0x00, 0x14, 0x00, 0x43, 0x10,
-0xFF, 0x00, 0xA2, 0x30, 0xFF, 0x00, 0xC3, 0x30, 0x00, 0x12, 0x02, 0x00,
-0x25, 0x10, 0x43, 0x00, 0xC8, 0x3D, 0xC2, 0xA7, 0x01, 0x00, 0x24, 0x92,
-0x18, 0x00, 0x42, 0x92, 0x00, 0x22, 0x04, 0x00, 0xA8, 0x0D, 0x00, 0x0C,
-0x25, 0x20, 0x82, 0x00, 0x40, 0x18, 0x02, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x98, 0xDE, 0x82, 0x24, 0x80, 0x18, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x08, 0x00, 0x62, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x09, 0xF8, 0x40, 0x00, 0x21, 0x20, 0x60, 0x02, 0x0C, 0x00, 0xC2, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x2B, 0x10, 0xE2, 0x02, 0x41, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x8E, 0x02, 0x80, 0x03, 0x3C,
-0x48, 0x37, 0x64, 0x24, 0x42, 0x1B, 0x02, 0x00, 0x78, 0x00, 0x63, 0x30,
-0x02, 0x2E, 0x02, 0x00, 0xFF, 0x3F, 0x42, 0x30, 0x21, 0x10, 0x43, 0x00,
-0x03, 0x00, 0xA5, 0x30, 0x21, 0x10, 0x45, 0x00, 0x18, 0x00, 0x42, 0x24,
-0xFF, 0xFF, 0x50, 0x30, 0x7F, 0x00, 0x02, 0x32, 0x21, 0x98, 0x80, 0x02,
-0x06, 0x00, 0x06, 0x24, 0x80, 0x00, 0x03, 0x26, 0x00, 0x00, 0xB0, 0xAE,
-0x02, 0x00, 0x40, 0x10, 0x80, 0xFF, 0x05, 0x32, 0x80, 0xFF, 0x65, 0x30,
-0x00, 0x00, 0xA5, 0xAE, 0x02, 0x00, 0x62, 0x96, 0x21, 0x18, 0xE5, 0x02,
-0xFF, 0xFF, 0x77, 0x30, 0x0F, 0x00, 0x42, 0x30, 0x00, 0x00, 0xA2, 0xAE,
-0x00, 0x00, 0x63, 0x8E, 0x21, 0xA0, 0x85, 0x02, 0x42, 0x13, 0x03, 0x00,
-0x78, 0x00, 0x42, 0x30, 0x02, 0x1E, 0x03, 0x00, 0x03, 0x00, 0x63, 0x30,
-0x21, 0x10, 0x53, 0x00, 0x21, 0x90, 0x43, 0x00, 0x1C, 0x00, 0x50, 0x26,
-0x18, 0x00, 0x51, 0x26, 0x21, 0x28, 0x00, 0x02, 0x00, 0x00, 0xB1, 0xAE,
-0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x21, 0x28, 0x00, 0x02, 0x06, 0x00, 0x06, 0x24, 0x0B, 0x00, 0x40, 0x14,
-0x90, 0xDE, 0x64, 0x24, 0x01, 0x00, 0x22, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x12, 0x02, 0x00, 0x00, 0x08, 0x42, 0x30, 0xAD, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x26, 0x92, 0x17, 0x00, 0x25, 0x92,
-0x86, 0x18, 0x00, 0x08, 0xFF, 0x00, 0xA2, 0x30, 0x1D, 0x55, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xF3, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0xC2, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x10, 0xE2, 0x02,
-0xC1, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x40, 0x00, 0x0C,
-0x38, 0x00, 0xA4, 0x27, 0x04, 0x00, 0xC3, 0x8E, 0x00, 0x00, 0xC2, 0x8E,
-0x21, 0x20, 0xC0, 0x02, 0x00, 0x00, 0x62, 0xAC, 0x04, 0x00, 0x43, 0xAC,
-0x00, 0x00, 0xD6, 0xAE, 0x74, 0x21, 0x00, 0x0C, 0x04, 0x00, 0xD6, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0x38, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x88, 0x54, 0x43, 0x8C, 0x88, 0x54, 0x42, 0x24, 0x86, 0xFF, 0x62, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C, 0xE8, 0xEC, 0x63, 0x24,
-0x00, 0x00, 0x71, 0x8C, 0x25, 0xB0, 0x10, 0x3C, 0x04, 0x01, 0x02, 0x36,
-0x00, 0x00, 0x43, 0x8C, 0xDC, 0x38, 0x27, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x77, 0x00, 0xE3, 0x10, 0xE0, 0x38, 0x23, 0xAE, 0x2B, 0x10, 0x67, 0x00,
-0x81, 0x00, 0x40, 0x14, 0x2B, 0x10, 0xE3, 0x00, 0xA9, 0x00, 0x40, 0x14,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x44, 0x24, 0xB0, 0x38, 0x83, 0x94,
-0x02, 0x80, 0x02, 0x3C, 0x21, 0x80, 0x00, 0x00, 0x34, 0x00, 0xE0, 0x1A,
-0x25, 0x90, 0x62, 0x00, 0x21, 0x88, 0x80, 0x00, 0x21, 0x18, 0x00, 0x00,
-0x01, 0x00, 0x14, 0x24, 0x00, 0xC0, 0x15, 0x3C, 0x0E, 0x19, 0x00, 0x08,
-0x03, 0x00, 0x1E, 0x24, 0x80, 0x18, 0x10, 0x00, 0x2A, 0x10, 0x77, 0x00,
-0x2A, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x98, 0x72, 0x00,
-0x00, 0x00, 0x62, 0x8E, 0x44, 0x41, 0x23, 0x8E, 0x38, 0x00, 0xA4, 0x27,
-0xFF, 0x3F, 0x42, 0x30, 0x21, 0x18, 0x62, 0x00, 0x8A, 0x40, 0x00, 0x0C,
-0x44, 0x41, 0x23, 0xAE, 0xE8, 0x1E, 0x22, 0x8E, 0xF0, 0x1E, 0x23, 0x8E,
-0x38, 0x00, 0xA4, 0x27, 0x01, 0x00, 0x42, 0x24, 0x01, 0x00, 0x63, 0x24,
-0xE8, 0x1E, 0x22, 0xAE, 0x90, 0x40, 0x00, 0x0C, 0xF0, 0x1E, 0x23, 0xAE,
-0xEC, 0x2C, 0x00, 0x0C, 0x21, 0x20, 0x60, 0x02, 0x00, 0x00, 0x63, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x60, 0x14, 0x06, 0x00, 0x02, 0x26,
-0x01, 0x00, 0x02, 0x26, 0xFF, 0xFF, 0x50, 0x30, 0x82, 0x16, 0x03, 0x00,
-0x01, 0x00, 0x42, 0x30, 0xE1, 0xFF, 0x54, 0x14, 0x02, 0x80, 0x04, 0x3C,
-0x60, 0x1B, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x42, 0x11, 0x02, 0x00,
-0x01, 0x00, 0x42, 0x30, 0x0C, 0x00, 0x54, 0x10, 0xC2, 0x13, 0x03, 0x00,
-0x1E, 0x00, 0x42, 0x30, 0x21, 0x10, 0x50, 0x00, 0xFF, 0xFF, 0x50, 0x30,
-0x80, 0x18, 0x10, 0x00, 0x2A, 0x10, 0x77, 0x00, 0xD8, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x74, 0x21, 0x00, 0x0C, 0x21, 0x20, 0xC0, 0x02,
-0x75, 0x19, 0x00, 0x08, 0x02, 0x80, 0x03, 0x3C, 0x01, 0x00, 0x22, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x63, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x03, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0x11, 0x00, 0x40, 0x14, 0x02, 0x17, 0x03, 0x00,
-0x03, 0x00, 0x44, 0x30, 0x07, 0x00, 0x80, 0x10, 0x24, 0x10, 0x75, 0x00,
-0x0C, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x9E, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x80, 0x28, 0x10, 0x00, 0x21, 0x28, 0xB2, 0x00, 0xE3, 0x17, 0x00, 0x0C,
-0x21, 0x20, 0x60, 0x02, 0x21, 0x20, 0x40, 0x00, 0x8D, 0x17, 0x00, 0x0C,
-0x21, 0x28, 0x00, 0x00, 0x01, 0x00, 0x22, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x7B, 0x00, 0x54, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x23, 0x92,
-0x02, 0x00, 0x02, 0x24, 0x63, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x4C, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x63, 0x30, 0x08, 0x00, 0x74, 0x10,
-0xD0, 0x02, 0x02, 0x24, 0x00, 0x00, 0x63, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0xC2, 0x13, 0x03, 0x00, 0x1E, 0x00, 0x42, 0x30, 0x21, 0x10, 0x50, 0x00,
-0x33, 0x19, 0x00, 0x08, 0xFF, 0xFF, 0x50, 0x30, 0x6C, 0x37, 0x22, 0xAE,
-0x00, 0x00, 0x63, 0x8E, 0x67, 0x19, 0x00, 0x08, 0xC2, 0x13, 0x03, 0x00,
-0x00, 0x01, 0x02, 0x36, 0x00, 0x00, 0x47, 0xAC, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x42, 0x24, 0xDC, 0x38, 0x47, 0xAC, 0x02, 0x80, 0x03, 0x3C,
-0x08, 0x04, 0x64, 0x24, 0x21, 0x28, 0x00, 0x00, 0x21, 0x30, 0x00, 0x00,
-0x76, 0x39, 0x00, 0x0C, 0x21, 0x38, 0x00, 0x00, 0x66, 0x18, 0x00, 0x08,
-0x02, 0x80, 0x02, 0x3C, 0xE4, 0x38, 0x22, 0x8E, 0xFF, 0xFF, 0x73, 0x30,
-0x23, 0x10, 0x47, 0x00, 0xFF, 0xFF, 0x52, 0x30, 0x21, 0x18, 0x53, 0x02,
-0xFF, 0xFF, 0x77, 0x30, 0x53, 0x21, 0x00, 0x0C, 0x21, 0x20, 0xE0, 0x02,
-0xEF, 0xFF, 0x40, 0x10, 0x21, 0xB0, 0x40, 0x00, 0x08, 0x00, 0x42, 0x8C,
-0xDC, 0x38, 0x26, 0x8E, 0x21, 0x38, 0x40, 0x02, 0x21, 0x18, 0x57, 0x00,
-0xAC, 0x38, 0x23, 0xAE, 0x21, 0x28, 0x40, 0x00, 0x08, 0x00, 0x04, 0x24,
-0xB0, 0x38, 0x22, 0xAE, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF,
-0x5B, 0x01, 0x00, 0x0C, 0x08, 0x00, 0x04, 0x24, 0xB0, 0x38, 0x25, 0x8E,
-0x24, 0x10, 0x02, 0x3C, 0x00, 0x01, 0x10, 0x36, 0x00, 0x00, 0x02, 0xAE,
-0x21, 0x38, 0x60, 0x02, 0x21, 0x28, 0xB2, 0x00, 0x08, 0x00, 0x04, 0x24,
-0x24, 0x10, 0x06, 0x3C, 0xDC, 0x38, 0x22, 0xAE, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0xE0, 0x38, 0x23, 0x8E, 0x08, 0x00, 0x04, 0x24,
-0x5B, 0x01, 0x00, 0x0C, 0xDC, 0x38, 0x23, 0xAE, 0xDC, 0x38, 0x22, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xAE, 0xFE, 0x18, 0x00, 0x08,
-0x02, 0x80, 0x02, 0x3C, 0x23, 0x10, 0x67, 0x00, 0xFF, 0xFF, 0x57, 0x30,
-0x53, 0x21, 0x00, 0x0C, 0x21, 0x20, 0xE0, 0x02, 0x44, 0x00, 0x40, 0x10,
-0x21, 0xB0, 0x40, 0x00, 0x08, 0x00, 0x42, 0x8C, 0xDC, 0x38, 0x26, 0x8E,
-0x08, 0x00, 0x04, 0x24, 0x21, 0x18, 0x57, 0x00, 0xAC, 0x38, 0x23, 0xAE,
-0x21, 0x28, 0x40, 0x00, 0x21, 0x38, 0xE0, 0x02, 0xB0, 0x38, 0x22, 0xAE,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0xE0, 0x38, 0x23, 0x8E,
-0x08, 0x00, 0x04, 0x24, 0x5B, 0x01, 0x00, 0x0C, 0xDC, 0x38, 0x23, 0xAE,
-0xDC, 0x38, 0x23, 0x8E, 0x00, 0x01, 0x02, 0x36, 0x00, 0x00, 0x43, 0xAC,
-0xFE, 0x18, 0x00, 0x08, 0x02, 0x80, 0x02, 0x3C, 0x04, 0x00, 0x63, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x03, 0x00, 0x0F, 0x00, 0x42, 0x30,
-0x08, 0x00, 0x42, 0x28, 0x99, 0xFF, 0x40, 0x10, 0x25, 0xB0, 0x02, 0x3C,
-0x02, 0x17, 0x03, 0x00, 0x03, 0x00, 0x42, 0x30, 0x94, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x28, 0x10, 0x00, 0x21, 0x28, 0xB2, 0x00,
-0xE3, 0x17, 0x00, 0x0C, 0x21, 0x20, 0x60, 0x02, 0x21, 0x20, 0x40, 0x00,
-0x8D, 0x17, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x5E, 0x19, 0x00, 0x08,
-0x25, 0xB0, 0x02, 0x3C, 0x04, 0x00, 0x63, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x14, 0x03, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x08, 0x00, 0x42, 0x28,
-0x06, 0x00, 0x40, 0x10, 0x24, 0x10, 0x75, 0x00, 0x02, 0x17, 0x03, 0x00,
-0x03, 0x00, 0x42, 0x30, 0x0A, 0x00, 0x40, 0x10, 0x80, 0x28, 0x10, 0x00,
-0x24, 0x10, 0x75, 0x00, 0x79, 0xFF, 0x40, 0x14, 0x02, 0x17, 0x03, 0x00,
-0x03, 0x00, 0x42, 0x30, 0x76, 0xFF, 0x5E, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x74, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x80, 0x28, 0x10, 0x00,
-0x21, 0x28, 0xB2, 0x00, 0xE3, 0x17, 0x00, 0x0C, 0x21, 0x20, 0x60, 0x02,
-0x21, 0x20, 0x40, 0x00, 0x8D, 0x17, 0x00, 0x0C, 0x05, 0x00, 0x05, 0x24,
-0x59, 0x19, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x38, 0x23, 0x8E,
-0x00, 0x01, 0x02, 0x36, 0x00, 0x00, 0x43, 0xAC, 0x74, 0x19, 0x00, 0x08,
-0xDC, 0x38, 0x23, 0xAE, 0xB8, 0xFF, 0xBD, 0x27, 0x25, 0xB0, 0x03, 0x3C,
-0x44, 0x00, 0xBF, 0xAF, 0x40, 0x00, 0xBE, 0xAF, 0x3C, 0x00, 0xB7, 0xAF,
-0x38, 0x00, 0xB6, 0xAF, 0x34, 0x00, 0xB5, 0xAF, 0x30, 0x00, 0xB4, 0xAF,
-0x2C, 0x00, 0xB3, 0xAF, 0x28, 0x00, 0xB2, 0xAF, 0x24, 0x00, 0xB1, 0xAF,
-0x20, 0x00, 0xB0, 0xAF, 0x44, 0x00, 0x63, 0x34, 0x00, 0x00, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x0E, 0x00, 0x40, 0x04, 0x1C, 0x00, 0xA0, 0xAF, 0x21, 0x20, 0x60, 0x00,
-0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x42, 0x30,
-0x64, 0x00, 0x43, 0x2C, 0xFD, 0xFF, 0x60, 0x14, 0x01, 0x00, 0x42, 0x24,
-0x00, 0x00, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00,
-0x03, 0x16, 0x02, 0x00, 0xF6, 0xFF, 0x41, 0x04, 0x21, 0x10, 0x00, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x98, 0x54, 0x43, 0x8C, 0x00, 0x80, 0x06, 0x3C,
-0xD0, 0x67, 0xC2, 0x24, 0x25, 0xB0, 0x05, 0x3C, 0x02, 0x80, 0x06, 0x3C,
-0x18, 0x03, 0xA4, 0x34, 0x98, 0x54, 0xD1, 0x24, 0x00, 0x00, 0x82, 0xAC,
-0x4B, 0x00, 0x71, 0x10, 0x01, 0x00, 0x15, 0x24, 0x11, 0x11, 0x02, 0x3C,
-0x2A, 0xB0, 0x03, 0x3C, 0x22, 0x22, 0x57, 0x34, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0xB0, 0x80, 0x00, 0x06, 0x00, 0x7E, 0x34, 0x05, 0x00, 0x73, 0x34,
-0x60, 0x1B, 0x54, 0x24, 0x01, 0x00, 0x12, 0x24, 0x00, 0x00, 0xD7, 0xAE,
-0x05, 0x00, 0xA0, 0x12, 0x02, 0x80, 0x03, 0x3C, 0xEC, 0x5D, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x40, 0x14, 0x21, 0xA8, 0x00, 0x00,
-0x00, 0x00, 0xC2, 0x97, 0x38, 0x39, 0x90, 0x8E, 0x25, 0xB0, 0x03, 0x3C,
-0xB0, 0x03, 0x63, 0x34, 0x00, 0xFF, 0x42, 0x30, 0x00, 0x00, 0x70, 0xAC,
-0x0F, 0x00, 0x40, 0x18, 0x02, 0x80, 0x06, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0xF0, 0xEC, 0xC6, 0x24, 0xF4, 0xEC, 0x42, 0x24, 0x00, 0x00, 0xC5, 0x8C,
-0x00, 0x00, 0x44, 0x8C, 0x02, 0x80, 0x06, 0x3C, 0xF8, 0xEC, 0xC6, 0x24,
-0x00, 0x00, 0xC3, 0x8C, 0x00, 0x00, 0xA4, 0xAC, 0x00, 0x00, 0x62, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x42, 0x30, 0xFB, 0xFF, 0x40, 0x1C,
-0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0x62, 0x30, 0x60, 0x00, 0x40, 0x14, 0x08, 0x00, 0x62, 0x24,
-0xC2, 0x10, 0x03, 0x00, 0x08, 0x00, 0x05, 0x8E, 0xF8, 0x37, 0x86, 0x8E,
-0xC0, 0x10, 0x02, 0x00, 0x20, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x47, 0x30,
-0x01, 0x00, 0x04, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xB2, 0xAF,
-0x5B, 0x01, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24, 0x02, 0x00, 0x02, 0x24,
-0x18, 0x00, 0xA4, 0x27, 0x00, 0x00, 0x72, 0xA2, 0x00, 0x00, 0x62, 0xA2,
-0x8A, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8E,
-0x04, 0x00, 0x03, 0x8E, 0x21, 0x20, 0x00, 0x02, 0x00, 0x00, 0x62, 0xAC,
-0x04, 0x00, 0x43, 0xAC, 0x00, 0x00, 0x10, 0xAE, 0x74, 0x21, 0x00, 0x0C,
-0x04, 0x00, 0x10, 0xAE, 0x90, 0x40, 0x00, 0x0C, 0x18, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x22, 0x8E, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x51, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0xEC, 0x5D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x40, 0x14,
-0x1C, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x02, 0x3C, 0x08, 0x08, 0x44, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x21, 0x30, 0x00, 0x00, 0x76, 0x39, 0x00, 0x0C,
-0x21, 0x38, 0x00, 0x00, 0x15, 0x1A, 0x00, 0x08, 0x02, 0x80, 0x02, 0x3C,
-0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x06, 0x3C,
-0xEE, 0x5D, 0xC2, 0x90, 0x01, 0x00, 0x03, 0x24, 0x0F, 0x00, 0x42, 0x30,
-0x04, 0x00, 0x42, 0x28, 0x0F, 0x00, 0x40, 0x14, 0x1C, 0x00, 0xA3, 0xAF,
-0x02, 0x80, 0x06, 0x3C, 0xC6, 0x5C, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x42, 0x30, 0x12, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x08, 0x04, 0x24, 0x00, 0x02, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C,
-0x01, 0x00, 0x06, 0x24, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x2F, 0x1A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x24,
-0x4B, 0x2E, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24, 0x02, 0x80, 0x06, 0x3C,
-0xC6, 0x5C, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x42, 0x30,
-0xF0, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x2D, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0x8A, 0x1A, 0x00, 0x08, 0x00, 0x08, 0x04, 0x24,
-0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x06, 0x3C,
-0xED, 0x5D, 0xC4, 0x90, 0x01, 0x00, 0x05, 0x24, 0x4B, 0x2E, 0x00, 0x0C,
-0xFF, 0x00, 0x84, 0x30, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x73, 0x1A, 0x00, 0x08, 0x02, 0x80, 0x02, 0x3C, 0x4B, 0x1A, 0x00, 0x08,
-0xC2, 0x10, 0x02, 0x00, 0x10, 0x00, 0xE0, 0x18, 0x21, 0x18, 0x00, 0x00,
-0x00, 0x00, 0xC0, 0xAC, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x82, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x45, 0x10, 0x21, 0x18, 0x80, 0x00,
-0x01, 0x00, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x48, 0x00,
-0x02, 0x00, 0x68, 0x24, 0x21, 0x10, 0x82, 0x00, 0x2B, 0x18, 0x07, 0x01,
-0xF5, 0xFF, 0x60, 0x14, 0x02, 0x00, 0x44, 0x24, 0x21, 0x18, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00, 0x01, 0x00, 0x82, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x60, 0x00, 0x02, 0x80, 0x07, 0x3C, 0x60, 0x1B, 0xE5, 0x24,
-0xCE, 0x40, 0xA3, 0x90, 0xFF, 0x00, 0x84, 0x30, 0x80, 0x10, 0x04, 0x00,
-0x0C, 0x00, 0x60, 0x14, 0x21, 0x30, 0x45, 0x00, 0xC8, 0x00, 0x02, 0x24,
-0x20, 0x3A, 0xA2, 0xAC, 0x01, 0x00, 0x03, 0x24, 0x60, 0x1B, 0xE2, 0x24,
-0x04, 0x18, 0x83, 0x00, 0xF8, 0x40, 0xA4, 0xA0, 0xCE, 0x40, 0x44, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x18, 0x64, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0xCE, 0x40, 0x43, 0xA0, 0x20, 0x3A, 0xA3, 0x8C, 0xC8, 0x00, 0x02, 0x24,
-0x23, 0x10, 0x43, 0x00, 0xD0, 0x40, 0xC2, 0xAC, 0x01, 0x00, 0x03, 0x24,
-0x60, 0x1B, 0xE2, 0x24, 0x04, 0x18, 0x83, 0x00, 0xCE, 0x40, 0x44, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x18, 0x64, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0xCE, 0x40, 0x43, 0xA0, 0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF,
-0x02, 0x80, 0x11, 0x3C, 0x10, 0x00, 0xB0, 0xAF, 0x18, 0x00, 0xBF, 0xAF,
-0x60, 0x1B, 0x25, 0x26, 0xF8, 0x40, 0xA6, 0x90, 0x01, 0x00, 0x02, 0x24,
-0x04, 0x10, 0xC2, 0x00, 0x06, 0x00, 0x40, 0x14, 0xC9, 0x00, 0x10, 0x24,
-0xC6, 0x40, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x23, 0x00, 0x40, 0x14, 0x21, 0x20, 0xC5, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x46, 0x24, 0x21, 0x20, 0x00, 0x00, 0xD0, 0x40, 0xC5, 0x24,
-0x00, 0x00, 0xA2, 0x8C, 0x04, 0x00, 0xA5, 0x24, 0x05, 0x00, 0x40, 0x10,
-0x2B, 0x18, 0x50, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x80, 0x40, 0x00, 0xF8, 0x40, 0xC4, 0xA0, 0x01, 0x00, 0x84, 0x24,
-0x08, 0x00, 0x82, 0x2C, 0xF5, 0xFF, 0x40, 0x14, 0xC9, 0x00, 0x02, 0x24,
-0x21, 0x00, 0x02, 0x12, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x45, 0x24,
-0x07, 0x00, 0x04, 0x24, 0xD0, 0x40, 0xA2, 0x8C, 0xFF, 0xFF, 0x84, 0x24,
-0x02, 0x00, 0x40, 0x10, 0x23, 0x18, 0x50, 0x00, 0xD0, 0x40, 0xA3, 0xAC,
-0xFA, 0xFF, 0x81, 0x04, 0x04, 0x00, 0xA5, 0x24, 0x60, 0x1B, 0x22, 0x26,
-0x20, 0x3A, 0x50, 0xAC, 0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xF0, 0x40, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x63, 0x24,
-0xFF, 0x00, 0x62, 0x30, 0x03, 0x00, 0x42, 0x2C, 0xD8, 0xFF, 0x40, 0x10,
-0xF0, 0x40, 0x83, 0xA0, 0x80, 0x18, 0x06, 0x00, 0x21, 0x18, 0x65, 0x00,
-0xC8, 0x00, 0x02, 0x24, 0x03, 0x00, 0x04, 0x24, 0x21, 0x28, 0x00, 0x00,
-0xD9, 0x12, 0x00, 0x0C, 0xD0, 0x40, 0x62, 0xAC, 0xF2, 0x1A, 0x00, 0x08,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x22, 0x26, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x20, 0x00, 0xBD, 0x27,
-0xCE, 0x40, 0x40, 0xA0, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x3A, 0x40, 0xAC,
-0xB8, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x08, 0x3C, 0x02, 0x80, 0x0B, 0x3C,
-0x02, 0x80, 0x0C, 0x3C, 0x40, 0x00, 0xBF, 0xAF, 0x3C, 0x00, 0xB5, 0xAF,
-0x38, 0x00, 0xB4, 0xAF, 0x34, 0x00, 0xB3, 0xAF, 0x30, 0x00, 0xB2, 0xAF,
-0x2C, 0x00, 0xB1, 0xAF, 0x28, 0x00, 0xB0, 0xAF, 0xE4, 0xEE, 0x63, 0x25,
-0xE0, 0xEE, 0x02, 0x25, 0xE8, 0xEE, 0x84, 0x25, 0x01, 0x00, 0x45, 0x90,
-0x01, 0x00, 0x66, 0x90, 0x01, 0x00, 0x87, 0x90, 0xE0, 0xEE, 0x0F, 0x91,
-0x02, 0x00, 0x4A, 0x90, 0xE4, 0xEE, 0x6E, 0x91, 0x02, 0x00, 0x69, 0x90,
-0xE8, 0xEE, 0x8D, 0x91, 0x02, 0x00, 0x88, 0x90, 0x03, 0x00, 0x4B, 0x90,
-0x03, 0x00, 0x6C, 0x90, 0x03, 0x00, 0x82, 0x90, 0x00, 0x2A, 0x05, 0x00,
-0x00, 0x32, 0x06, 0x00, 0x00, 0x3A, 0x07, 0x00, 0x25, 0x28, 0xAF, 0x00,
-0x25, 0x30, 0xCE, 0x00, 0x25, 0x38, 0xED, 0x00, 0x00, 0x54, 0x0A, 0x00,
-0x00, 0x4C, 0x09, 0x00, 0x00, 0x44, 0x08, 0x00, 0x25, 0x50, 0x45, 0x01,
-0x25, 0x48, 0x26, 0x01, 0x25, 0x40, 0x07, 0x01, 0x00, 0x5E, 0x0B, 0x00,
-0x00, 0x66, 0x0C, 0x00, 0x00, 0x16, 0x02, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x25, 0x58, 0x6A, 0x01, 0x25, 0x60, 0x89, 0x01, 0x25, 0x10, 0x48, 0x00,
-0xB0, 0x55, 0x84, 0x24, 0x10, 0x00, 0xAB, 0xAF, 0x18, 0x00, 0xAC, 0xAF,
-0x18, 0x52, 0x00, 0x0C, 0x20, 0x00, 0xA2, 0xAF, 0x10, 0x00, 0x42, 0x30,
-0x29, 0x00, 0x40, 0x10, 0x21, 0x18, 0x00, 0x00, 0x02, 0x80, 0x13, 0x3C,
-0x60, 0x1B, 0x63, 0x26, 0xC0, 0x3A, 0x62, 0x8C, 0x0C, 0x00, 0x10, 0x24,
-0x2B, 0x10, 0x02, 0x02, 0x2C, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x24, 0x56, 0x51, 0x24, 0x2E, 0x56, 0x72, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x26, 0x56, 0x54, 0x24,
-0x7C, 0x1B, 0x00, 0x08, 0x32, 0x56, 0x75, 0x24, 0xDD, 0x00, 0x02, 0x24,
-0x21, 0x20, 0x14, 0x02, 0x2B, 0x00, 0x62, 0x10, 0x10, 0x00, 0xA5, 0x27,
-0x21, 0x10, 0x11, 0x02, 0x01, 0x00, 0x43, 0x90, 0x60, 0x1B, 0x64, 0x26,
-0xC0, 0x3A, 0x82, 0x8C, 0x21, 0x18, 0x70, 0x00, 0x02, 0x00, 0x70, 0x24,
-0x2B, 0x10, 0x02, 0x02, 0x17, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0x11, 0x02, 0x00, 0x00, 0x43, 0x90, 0x30, 0x00, 0x02, 0x24,
-0x21, 0x20, 0x12, 0x02, 0x20, 0x00, 0xA5, 0x27, 0xED, 0xFF, 0x62, 0x14,
-0x04, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xEE, 0xFF, 0x40, 0x14, 0x21, 0x10, 0x11, 0x02, 0x01, 0x00, 0x03, 0x24,
-0x40, 0x00, 0xBF, 0x8F, 0x3C, 0x00, 0xB5, 0x8F, 0x38, 0x00, 0xB4, 0x8F,
-0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F,
-0x28, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x48, 0x00, 0xBD, 0x27, 0x40, 0x00, 0xBF, 0x8F, 0x3C, 0x00, 0xB5, 0x8F,
-0x38, 0x00, 0xB4, 0x8F, 0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F,
-0x2C, 0x00, 0xB1, 0x8F, 0x28, 0x00, 0xB0, 0x8F, 0x21, 0x18, 0x00, 0x00,
-0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27,
-0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x15, 0x02,
-0x18, 0x00, 0xA5, 0x27, 0xD1, 0xFF, 0x40, 0x14, 0x04, 0x00, 0x06, 0x24,
-0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xCE, 0xFF, 0x40, 0x14,
-0x21, 0x10, 0x11, 0x02, 0x88, 0x1B, 0x00, 0x08, 0x01, 0x00, 0x03, 0x24,
-0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x65, 0x24, 0xB0, 0x1B, 0xA2, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x34, 0x08, 0x00, 0x40, 0x10,
-0x70, 0x17, 0x04, 0x24, 0xB6, 0x40, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFB, 0xFF, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30, 0x02, 0x00, 0x42, 0x2C,
-0x0A, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x40, 0xA3, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x03, 0x00, 0x70, 0x17, 0x62, 0x28,
-0x04, 0x00, 0x40, 0x14, 0x70, 0x17, 0x04, 0x24, 0x21, 0x4E, 0x62, 0x28,
-0x20, 0x4E, 0x04, 0x24, 0x0B, 0x20, 0x62, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x80, 0x00, 0x21, 0x38, 0x80, 0x00, 0x08, 0x00, 0xC0, 0x10,
-0xFF, 0xFF, 0xC3, 0x24, 0xFF, 0xFF, 0x06, 0x24, 0x00, 0x00, 0xA2, 0x8C,
-0xFF, 0xFF, 0x63, 0x24, 0x04, 0x00, 0xA5, 0x24, 0x00, 0x00, 0xE2, 0xAC,
-0xFB, 0xFF, 0x66, 0x14, 0x04, 0x00, 0xE7, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x80, 0x00, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32,
-0x40, 0x32, 0x10, 0xF0, 0x00, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x00, 0xF3,
-0x18, 0x4A, 0x2D, 0xF7, 0x19, 0x4B, 0xF9, 0x63, 0x60, 0xDA, 0x00, 0x6A,
-0x0C, 0x62, 0x0B, 0xD1, 0x0A, 0xD0, 0x07, 0xD2, 0xC9, 0xF7, 0x1B, 0x6A,
-0x4B, 0xEA, 0x40, 0x31, 0x20, 0x31, 0x10, 0xF0, 0x00, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x10, 0xF3, 0x68, 0x41, 0x2D, 0xF7, 0x19, 0x4A, 0x40, 0xDB,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0x66, 0xF7, 0x48, 0xAB, 0x01, 0x4A, 0x66, 0xF7, 0x48, 0xCB, 0x00, 0x1C,
-0x9B, 0x40, 0x00, 0x65, 0xC0, 0xF0, 0x46, 0x41, 0x40, 0xAA, 0x11, 0x5A,
-0x12, 0x61, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x10, 0xF0,
-0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0xAB, 0xF5, 0x50, 0x9C, 0xCB, 0xF5,
-0x68, 0x9D, 0x6D, 0xEA, 0xAB, 0xF5, 0x50, 0xDC, 0x00, 0x6A, 0xCB, 0xF5,
-0x48, 0xDD, 0x00, 0x1C, 0x96, 0x40, 0x00, 0x65, 0x70, 0xF3, 0x60, 0x41,
-0xE0, 0x9B, 0x06, 0x27, 0x07, 0x92, 0xFF, 0xF7, 0x1F, 0x6C, 0x01, 0x4A,
-0x8C, 0xEA, 0x07, 0xD2, 0xFF, 0x6D, 0x01, 0x4D, 0xA0, 0x36, 0xC0, 0x30,
-0x4F, 0x40, 0xE3, 0xEA, 0x0D, 0x65, 0x80, 0xF0, 0x1E, 0x60, 0xFF, 0x6A,
-0x01, 0x4A, 0x4B, 0xEA, 0x40, 0x35, 0xA0, 0x35, 0xF0, 0xF0, 0x4F, 0x45,
-0x62, 0x67, 0x2A, 0x65, 0x00, 0xF3, 0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x34,
-0x80, 0x34, 0x47, 0x44, 0xEC, 0xEB, 0x11, 0x4A, 0x4A, 0xEB, 0x80, 0xF0,
-0x17, 0x60, 0x63, 0xEA, 0xA0, 0xF0, 0x04, 0x61, 0x01, 0xF6, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x35, 0xA0, 0x35, 0x41, 0x45, 0x4A, 0xEB, 0xC0, 0xF0,
-0x04, 0x60, 0x63, 0xEA, 0x00, 0xF1, 0x09, 0x61, 0x02, 0xF0, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x34, 0x80, 0x34, 0x43, 0x44, 0x4A, 0xEB, 0x40, 0xF1,
-0x17, 0x60, 0x63, 0xEA, 0xC0, 0xF1, 0x18, 0x61, 0x8A, 0xEB, 0x00, 0xF3,
-0x12, 0x60, 0x63, 0xEC, 0x80, 0xF3, 0x08, 0x61, 0x04, 0xF0, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x6E, 0xEA, 0xE0, 0xF3, 0x12, 0x22,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x00, 0x6B,
-0x60, 0xF3, 0x10, 0x4A, 0x60, 0xDA, 0x07, 0xD3, 0xC9, 0xF7, 0x1B, 0x68,
-0x0B, 0xE8, 0x00, 0x30, 0x00, 0x30, 0x10, 0xF0, 0x00, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x10, 0xF3, 0x68, 0x40, 0x2E, 0xF0, 0x19, 0x4A, 0x40, 0xDB,
-0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4, 0x00, 0x30, 0x00, 0x1C, 0x9B, 0x40,
-0xFF, 0x69, 0x63, 0xF3, 0x00, 0x48, 0x10, 0x10, 0xC9, 0xF7, 0x1B, 0x6D,
-0xAB, 0xED, 0xA0, 0x35, 0xA0, 0x35, 0x7F, 0x4D, 0x40, 0x4D, 0x40, 0xA5,
-0x2C, 0xEA, 0x04, 0x5A, 0x0F, 0x60, 0x27, 0xF1, 0x90, 0x98, 0x00, 0x1C,
-0xF5, 0x09, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34,
-0x8A, 0xF4, 0x10, 0x4C, 0x00, 0x1C, 0x6A, 0x58, 0x00, 0x65, 0xE6, 0x22,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xEB, 0xF5, 0x4E, 0xA3,
-0x0F, 0x6B, 0xFF, 0x6C, 0x6C, 0xEA, 0x02, 0x72, 0x0B, 0x61, 0x10, 0xF0,
-0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0xEB, 0xF5, 0x4D, 0xA5, 0x8C, 0xEA,
-0x6C, 0xEA, 0x01, 0x72, 0x40, 0xF4, 0x00, 0x60, 0x00, 0x1C, 0x96, 0x40,
-0x00, 0x65, 0x00, 0x6D, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34,
-0x02, 0xF0, 0x08, 0x4C, 0xC5, 0x67, 0x00, 0x1C, 0x76, 0x39, 0xE5, 0x67,
-0x19, 0x17, 0x07, 0x94, 0x0A, 0xF0, 0x00, 0x5C, 0xA5, 0x61, 0x00, 0x6A,
-0x40, 0xDB, 0x07, 0xD2, 0x01, 0x6A, 0x70, 0xF3, 0x64, 0x41, 0x4B, 0xEA,
-0x40, 0xDB, 0x9C, 0x17, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x0C, 0xF0, 0x00, 0x6A, 0x63, 0xF3, 0x00, 0x4D, 0x4B, 0xEA, 0x62, 0x9D,
-0x40, 0x32, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB, 0x62, 0xDD, 0x82, 0x17,
-0xA0, 0xF0, 0x4C, 0x44, 0x4A, 0xEB, 0x00, 0xF4, 0x17, 0x60, 0x63, 0xEA,
-0x39, 0x61, 0xA0, 0xF0, 0x42, 0x44, 0x4A, 0xEB, 0x20, 0xF4, 0x0D, 0x60,
-0x63, 0xEA, 0xE0, 0xF0, 0x02, 0x61, 0x47, 0x44, 0x21, 0x4A, 0x4A, 0xEB,
-0x40, 0xF4, 0x11, 0x60, 0x63, 0xEA, 0xC0, 0xF1, 0x1D, 0x61, 0x47, 0x44,
-0x12, 0x4A, 0x6E, 0xEA, 0x7F, 0xF7, 0x06, 0x2A, 0xC9, 0xF7, 0x1B, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x00, 0x6B, 0x60, 0xF3, 0x10, 0x4A,
-0x60, 0xDA, 0x00, 0x18, 0x12, 0x27, 0x87, 0x67, 0x59, 0x17, 0x70, 0xF3,
-0x44, 0x41, 0xE0, 0x9A, 0x02, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0x40, 0x32,
-0xFF, 0x4A, 0x4C, 0xEF, 0xE3, 0xEE, 0x5F, 0xF7, 0x0D, 0x60, 0x0A, 0xF0,
-0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x4D, 0xEF, 0x70, 0xF3,
-0x48, 0x41, 0xC0, 0x9A, 0xC0, 0xDF, 0x42, 0x17, 0x00, 0xF2, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x36, 0xC0, 0x36, 0x47, 0x46, 0x0B, 0x4A, 0x4A, 0xEB,
-0xC0, 0xF3, 0x17, 0x60, 0x63, 0xEA, 0xC0, 0xF0, 0x01, 0x61, 0xA0, 0xF0,
-0x4F, 0x44, 0x4A, 0xEB, 0x20, 0xF4, 0x15, 0x60, 0x63, 0xEA, 0x60, 0xF1,
-0x18, 0x61, 0xA0, 0xF0, 0x4D, 0x44, 0x6E, 0xEA, 0x60, 0xF4, 0x09, 0x22,
-0xA0, 0xF0, 0x4E, 0x44, 0x6E, 0xEA, 0x3F, 0xF7, 0x03, 0x2A, 0x1F, 0xF7,
-0x00, 0x6A, 0xE2, 0x34, 0x4C, 0xEC, 0x4C, 0xEF, 0x82, 0x34, 0x00, 0x18,
-0x3B, 0x5D, 0xE2, 0x35, 0xC9, 0xF7, 0x1B, 0x6B, 0x6B, 0xEB, 0x60, 0x33,
-0x60, 0x33, 0x60, 0xF3, 0x14, 0x4B, 0x40, 0xC3, 0x11, 0x17, 0x01, 0xF0,
-0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x35, 0xA0, 0x35, 0x47, 0x45, 0x0F, 0x4A,
-0x4A, 0xEB, 0xC0, 0xF3, 0x1A, 0x60, 0x63, 0xEA, 0xA0, 0xF0, 0x19, 0x61,
-0x01, 0xF4, 0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x4A, 0xEB,
-0x00, 0xF4, 0x06, 0x60, 0x63, 0xEA, 0xE0, 0xF1, 0x13, 0x61, 0x01, 0xF5,
-0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x6E, 0xEA, 0xFF, 0xF6,
-0x11, 0x2A, 0x1F, 0xF7, 0x00, 0x6A, 0xEC, 0xEA, 0x42, 0x30, 0x01, 0xF7,
-0x00, 0x6B, 0xE2, 0x32, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x6C, 0xEA, 0x63, 0xF3, 0x00, 0x4D, 0x42, 0x36, 0x28, 0xF1, 0xDB, 0xC5,
-0x20, 0xF3, 0x06, 0x26, 0xA3, 0xF3, 0x50, 0xAD, 0x10, 0xF0, 0x00, 0x6B,
-0x6B, 0xEB, 0x10, 0xF0, 0x00, 0x6C, 0x6D, 0xEA, 0xA3, 0xF3, 0x50, 0xCD,
-0x1E, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0x4C, 0xEF, 0xFF, 0x6A, 0x4C, 0xE8,
-0x00, 0xF5, 0xE2, 0x31, 0x4C, 0xEE, 0x00, 0x1C, 0x3C, 0x0E, 0xB0, 0x67,
-0x90, 0x67, 0x00, 0x1C, 0x38, 0x0D, 0xB1, 0x67, 0xC9, 0xF7, 0x1B, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF3, 0x10, 0x4A, 0x00, 0x6B,
-0x60, 0xDA, 0xBA, 0x16, 0x1F, 0xF7, 0x00, 0x6B, 0xE2, 0x32, 0x6C, 0xEA,
-0x42, 0x32, 0xEC, 0xEB, 0x06, 0xD2, 0x62, 0x37, 0x80, 0xF3, 0x08, 0x22,
-0x01, 0x72, 0x01, 0x6C, 0x01, 0x60, 0x00, 0x6C, 0x00, 0x1C, 0xF0, 0x42,
-0x09, 0xD7, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0x09, 0x97, 0x70, 0xF3, 0x24, 0x42, 0xC0, 0x99, 0x02, 0xF0, 0x00, 0x68,
-0x00, 0x30, 0x87, 0x67, 0xAF, 0x40, 0x00, 0x1C, 0x83, 0x45, 0x09, 0xD7,
-0x09, 0x97, 0xAF, 0x40, 0x00, 0x1C, 0xAC, 0x45, 0x87, 0x67, 0x40, 0xD9,
-0x91, 0x16, 0xA0, 0xF0, 0x45, 0x44, 0x4A, 0xEB, 0x60, 0xF3, 0x06, 0x60,
-0x63, 0xEA, 0x00, 0xF1, 0x0D, 0x61, 0xA0, 0xF0, 0x43, 0x44, 0x6E, 0xEA,
-0x40, 0xF1, 0x02, 0x22, 0xA0, 0xF0, 0x44, 0x44, 0x6E, 0xEA, 0x7F, 0xF6,
-0x1F, 0x2A, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x00, 0x4B, 0xFF, 0xF7, 0x1F, 0x6A, 0x27, 0xF1, 0x44, 0xDB, 0x74, 0x16,
-0x47, 0x46, 0x13, 0x4A, 0x4A, 0xEB, 0x80, 0xF0, 0x16, 0x60, 0x63, 0xEA,
-0x00, 0xF1, 0x1B, 0x61, 0x47, 0x46, 0x11, 0x4A, 0x6E, 0xEA, 0xE0, 0xF3,
-0x05, 0x22, 0x47, 0x46, 0x12, 0x4A, 0x6E, 0xEA, 0x7F, 0xF6, 0x02, 0x2A,
-0x00, 0x1C, 0x9B, 0x40, 0x00, 0x65, 0xC9, 0xF7, 0x1B, 0x6A, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x4B, 0xEA, 0x63, 0xF3, 0x00, 0x4B,
-0x40, 0x32, 0x23, 0xF4, 0x6A, 0xA3, 0x40, 0x32, 0x60, 0xF3, 0x14, 0x4A,
-0x60, 0xDA, 0x00, 0x1C, 0x96, 0x40, 0x00, 0x65, 0x4B, 0x16, 0x47, 0x44,
-0x4A, 0xEB, 0x80, 0xF3, 0x03, 0x60, 0x63, 0xEA, 0x00, 0xF1, 0x0C, 0x61,
-0x47, 0x45, 0x10, 0x4A, 0x6E, 0xEA, 0xC0, 0xF3, 0x11, 0x22, 0x47, 0x45,
-0x11, 0x4A, 0x6E, 0xEA, 0x3F, 0xF6, 0x1A, 0x2A, 0x00, 0x1C, 0x2B, 0x20,
-0x00, 0x65, 0x36, 0x16, 0x01, 0xF7, 0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x36,
-0xC0, 0x36, 0x42, 0x46, 0x4A, 0xEB, 0x3F, 0xF6, 0x0D, 0x60, 0x63, 0xEA,
-0x80, 0xF1, 0x04, 0x61, 0x47, 0x44, 0x01, 0x4A, 0x6E, 0xEA, 0xE0, 0xF1,
-0x01, 0x22, 0x43, 0x67, 0xCE, 0xEA, 0x3F, 0xF6, 0x01, 0x2A, 0xFF, 0x6A,
-0x01, 0x4A, 0x40, 0x32, 0x40, 0x32, 0x80, 0x4A, 0x80, 0x4A, 0x4C, 0xEF,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0xE2, 0x33, 0x63, 0xF3,
-0x00, 0x4C, 0xA3, 0xF3, 0x7A, 0xCC, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC,
-0x80, 0x34, 0x80, 0x34, 0x90, 0xF0, 0x44, 0x44, 0x60, 0xCA, 0x90, 0xF0,
-0xAA, 0x44, 0x00, 0xF4, 0x00, 0x6A, 0x40, 0xCD, 0x90, 0xF0, 0xA8, 0x44,
-0xA0, 0x6A, 0x40, 0xCD, 0xC9, 0xF7, 0x1A, 0x6D, 0xAB, 0xED, 0xA0, 0x35,
-0x04, 0x6E, 0x90, 0xF0, 0x46, 0x44, 0xA0, 0x35, 0xC0, 0xCA, 0x47, 0x45,
-0x73, 0x4A, 0xC0, 0xC2, 0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xEB, 0x74, 0x33,
-0xC8, 0x43, 0xC8, 0x4E, 0xB0, 0xF3, 0x40, 0x44, 0xC0, 0xDA, 0x60, 0xF0,
-0xDC, 0xCD, 0x40, 0xF0, 0x64, 0xAC, 0x00, 0xF2, 0x01, 0x6A, 0x4B, 0xEA,
-0x6C, 0xEA, 0x40, 0xF0, 0x44, 0xCC, 0x40, 0xF0, 0x64, 0xAC, 0x00, 0xF2,
-0x00, 0x6A, 0x6D, 0xEA, 0x40, 0xF0, 0x44, 0xCC, 0xD9, 0x15, 0x0F, 0xF7,
-0x40, 0x40, 0x4C, 0xEF, 0xE2, 0x37, 0x87, 0x67, 0xFF, 0xF7, 0x1F, 0x6D,
-0xAC, 0xEC, 0x01, 0x74, 0x06, 0xD4, 0xA0, 0xF0, 0x18, 0x60, 0x02, 0x54,
-0x20, 0xF3, 0x13, 0x61, 0x06, 0x92, 0x03, 0x72, 0xE0, 0xF1, 0x19, 0x60,
-0xC9, 0xF7, 0x1B, 0x6A, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33,
-0x4B, 0xEA, 0x63, 0xF3, 0x00, 0x4B, 0x40, 0x32, 0x23, 0xF4, 0x64, 0xAB,
-0x40, 0x32, 0x60, 0xF3, 0x14, 0x4A, 0x60, 0xDA, 0xB5, 0x15, 0x47, 0x46,
-0x09, 0x4A, 0x6E, 0xEA, 0xE0, 0xF2, 0x16, 0x22, 0x47, 0x46, 0x0A, 0x4A,
-0x6E, 0xEA, 0xBF, 0xF5, 0x0B, 0x2A, 0x00, 0x1C, 0x9B, 0x40, 0x09, 0xD7,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x00, 0x6A, 0x63, 0xF3,
-0x00, 0x4B, 0x23, 0xF4, 0x4A, 0xC3, 0xFF, 0x6A, 0x01, 0x4A, 0x40, 0x32,
-0x40, 0x32, 0x09, 0x97, 0x80, 0x4A, 0x80, 0x4A, 0x4C, 0xEF, 0xE0, 0x34,
-0x82, 0x34, 0x00, 0x1C, 0xA3, 0x31, 0x82, 0x34, 0x00, 0x1C, 0x96, 0x40,
-0x00, 0x65, 0x8E, 0x15, 0xA0, 0xF0, 0x40, 0x44, 0x6E, 0xEA, 0x80, 0xF0,
-0x1B, 0x22, 0xA0, 0xF0, 0x41, 0x44, 0x6E, 0xEA, 0x9F, 0xF5, 0x04, 0x2A,
-0xE2, 0x34, 0x1F, 0xF7, 0x00, 0x6A, 0x4C, 0xEC, 0x00, 0x18, 0x11, 0x22,
-0x82, 0x34, 0x7C, 0x15, 0xA0, 0xF0, 0x46, 0x44, 0x6E, 0xEA, 0xC0, 0xF2,
-0x1B, 0x22, 0xA0, 0xF0, 0x47, 0x44, 0x6E, 0xEA, 0x7F, 0xF5, 0x12, 0x2A,
-0x1F, 0xF7, 0x00, 0x6A, 0xE2, 0x33, 0x4C, 0xEF, 0xE2, 0x36, 0x4C, 0xEB,
-0x01, 0x76, 0x62, 0x35, 0xA0, 0xF1, 0x17, 0x61, 0xAC, 0x32, 0xA9, 0xE2,
-0x48, 0x32, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0xA9, 0xE2,
-0xC9, 0xF7, 0x1B, 0x6B, 0x63, 0xF3, 0x00, 0x4C, 0x48, 0x32, 0x6B, 0xEB,
-0x89, 0xE2, 0x60, 0x33, 0x04, 0xF5, 0x40, 0x9A, 0x60, 0x33, 0x60, 0xF3,
-0x14, 0x4B, 0x40, 0xDB, 0x51, 0x15, 0x47, 0x45, 0x08, 0x4A, 0x6E, 0xEA,
-0x71, 0x22, 0x47, 0x45, 0x09, 0x4A, 0x6E, 0xEA, 0x5F, 0xF5, 0x08, 0x2A,
-0x1F, 0xF7, 0x00, 0x6A, 0x4C, 0xEF, 0x4A, 0xEF, 0xDF, 0xF6, 0x03, 0x60,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0x00, 0x6A, 0x27, 0xF1, 0x44, 0xDB, 0x38, 0x15, 0x47, 0x44, 0x0D, 0x4A,
-0x6E, 0xEA, 0x69, 0x22, 0x47, 0x44, 0x10, 0x4A, 0x6E, 0xEA, 0x3F, 0xF5,
-0x0F, 0x2A, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34,
-0x60, 0xF3, 0xA8, 0x44, 0x60, 0x9D, 0xFF, 0xF7, 0x1F, 0x6A, 0x60, 0xF3,
-0x04, 0x4C, 0x4C, 0xEB, 0x1F, 0xF7, 0x00, 0x6A, 0x4C, 0xEF, 0xE0, 0x32,
-0x6D, 0xEA, 0x40, 0xDD, 0x60, 0xA4, 0xFF, 0x6A, 0x6C, 0xEA, 0x40, 0x6B,
-0x6D, 0xEA, 0x40, 0xC4, 0x15, 0x15, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0x23, 0xF4, 0x42, 0xAA, 0xFF, 0xF7,
-0x1F, 0x6D, 0x70, 0xF3, 0x64, 0x41, 0xAC, 0xEA, 0x40, 0xDB, 0x06, 0x15,
-0x01, 0x4A, 0x6E, 0xEA, 0xA0, 0xF0, 0x0D, 0x22, 0x47, 0x45, 0x0E, 0x4A,
-0x6E, 0xEA, 0xFF, 0xF4, 0x1D, 0x2A, 0x00, 0x1C, 0xAE, 0x1F, 0x00, 0x65,
-0xF9, 0x14, 0x0F, 0xF7, 0x40, 0x40, 0xEC, 0xEA, 0x42, 0x37, 0x2D, 0xE7,
-0xC0, 0x9B, 0x70, 0xF3, 0x44, 0x41, 0xC0, 0xDA, 0xC0, 0x9B, 0xEE, 0x14,
-0x01, 0xF7, 0x00, 0x6A, 0x4C, 0xEF, 0xE2, 0x32, 0x01, 0x72, 0x01, 0x6C,
-0x07, 0x60, 0x02, 0x72, 0x02, 0x6C, 0x04, 0x60, 0x03, 0x72, 0x03, 0x6C,
-0x01, 0x60, 0x00, 0x6C, 0x00, 0x18, 0x92, 0x5D, 0x00, 0x65, 0xDC, 0x14,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF1,
-0x16, 0x4A, 0xFF, 0x6B, 0x60, 0xCA, 0x01, 0x6A, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0xEB, 0xF4, 0x50, 0xC3, 0xCB, 0x14, 0x0F, 0xF7,
-0x40, 0x40, 0xEC, 0xEA, 0xDF, 0xF4, 0x06, 0x22, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3, 0x44, 0x9B,
-0xA9, 0x67, 0x88, 0x67, 0xAC, 0xEA, 0x8D, 0xEA, 0x00, 0xF3, 0x44, 0xDB,
-0x1F, 0xF7, 0x00, 0x6C, 0xE2, 0x32, 0x8C, 0xEA, 0x42, 0x32, 0x00, 0xF3,
-0x5C, 0xC3, 0x8C, 0xEF, 0xFB, 0x4A, 0x00, 0xF3, 0x5D, 0xC3, 0xE2, 0x32,
-0x00, 0xF3, 0x5E, 0xC3, 0xFB, 0x4A, 0x00, 0xF3, 0x5F, 0xC3, 0xA6, 0x14,
-0x44, 0x46, 0x6E, 0xEA, 0x6D, 0x22, 0x43, 0x67, 0xAE, 0xEA, 0x9F, 0xF4,
-0x1F, 0x2A, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x33, 0x60, 0x33,
-0x70, 0xF3, 0x44, 0x43, 0xE0, 0x9A, 0x02, 0xF0, 0x00, 0x6A, 0x40, 0x32,
-0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEF, 0xFF, 0x6A, 0x01, 0x4A, 0x40, 0x32,
-0xE3, 0xEA, 0x9F, 0xF4, 0x0B, 0x60, 0x0A, 0xF0, 0x00, 0x6A, 0x4B, 0xEA,
-0x40, 0x32, 0x40, 0x32, 0x4D, 0xEF, 0xC0, 0x9F, 0x70, 0xF3, 0x48, 0x43,
-0xC0, 0xDA, 0x80, 0x14, 0x41, 0x44, 0x6E, 0xEA, 0x5E, 0x22, 0x42, 0x44,
-0x6E, 0xEA, 0x7F, 0xF4, 0x19, 0x2A, 0x1F, 0xF7, 0x00, 0x6B, 0xE2, 0x32,
-0x6C, 0xEA, 0x42, 0x32, 0xEC, 0xEB, 0x06, 0xD2, 0x62, 0x37, 0x20, 0xF2,
-0x0C, 0x22, 0x01, 0x72, 0x01, 0x6C, 0x01, 0x60, 0x00, 0x6C, 0x00, 0x1C,
-0xF0, 0x42, 0x09, 0xD7, 0x09, 0x97, 0x02, 0xF0, 0x00, 0x68, 0x00, 0x30,
-0xAF, 0x40, 0x00, 0x1C, 0xAC, 0x45, 0x87, 0x67, 0xFF, 0x48, 0x4C, 0xE8,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x60, 0xF3,
-0x14, 0x4A, 0x00, 0xDA, 0x55, 0x14, 0xC9, 0xF7, 0x1B, 0x6A, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x4B, 0xEA, 0x63, 0xF3, 0x00, 0x4B,
-0x40, 0x32, 0xC4, 0xF7, 0x7C, 0xAB, 0x40, 0x32, 0x60, 0xF3, 0x14, 0x4A,
-0x60, 0xDA, 0x44, 0x14, 0x1F, 0xF7, 0x00, 0x6A, 0xEC, 0xEA, 0x42, 0x37,
-0x87, 0x67, 0x04, 0x27, 0x01, 0x77, 0x01, 0x6C, 0x01, 0x60, 0x00, 0x6C,
-0x00, 0x1C, 0xF0, 0x42, 0x00, 0x65, 0x36, 0x14, 0x1F, 0xF7, 0x00, 0x6B,
-0x47, 0x67, 0x6C, 0xEA, 0x42, 0x32, 0x06, 0xD2, 0xE2, 0x32, 0x6C, 0xEA,
-0x42, 0x36, 0x07, 0x5E, 0x3F, 0xF4, 0x0A, 0x60, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0xC8, 0x32, 0x1D, 0xF7, 0x14, 0x4B, 0x69, 0xE2,
-0x40, 0x9A, 0x00, 0xEA, 0x00, 0x65, 0x0F, 0xF7, 0x40, 0x40, 0xEC, 0xEA,
-0x42, 0x37, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0x70, 0xF3, 0x64, 0x42, 0xC0, 0x9B, 0x49, 0xE7, 0xC0, 0xDA, 0xC0, 0x9A,
-0xC0, 0xDB, 0x0E, 0x14, 0x1F, 0xF7, 0x00, 0x6A, 0xEC, 0xEA, 0x42, 0x32,
-0xFF, 0x72, 0x71, 0x61, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32,
-0x40, 0x32, 0x60, 0xF3, 0x04, 0x4A, 0x60, 0xAA, 0x88, 0x67, 0x6D, 0xEC,
-0x80, 0xCA, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x06, 0xF0,
-0x00, 0x6A, 0x63, 0xF3, 0x00, 0x4C, 0x4B, 0xEA, 0xE0, 0xF2, 0x64, 0x9C,
-0x40, 0x32, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB, 0xE0, 0xF2, 0x64, 0xDC,
-0x1F, 0xF7, 0x00, 0x6A, 0x4C, 0xEF, 0x19, 0xF4, 0x00, 0x77, 0xFF, 0xF3,
-0x05, 0x61, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x06, 0xF0,
-0x00, 0x6A, 0x63, 0xF3, 0x00, 0x4C, 0x4B, 0xEA, 0xE0, 0xF2, 0x64, 0x9C,
-0x40, 0x32, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB, 0x02, 0xF0, 0x00, 0x6A,
-0x40, 0x32, 0x40, 0x32, 0x4D, 0xEB, 0xE0, 0xF2, 0x64, 0xDC, 0xDF, 0xF3,
-0x0D, 0x10, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xC9, 0xF7,
-0x1B, 0x6A, 0x63, 0xF3, 0x00, 0x4B, 0x4B, 0xEA, 0x23, 0xF4, 0x66, 0xAB,
-0x40, 0x32, 0x40, 0x32, 0xFF, 0xF7, 0x1F, 0x6C, 0x60, 0xF3, 0x14, 0x4A,
-0x8C, 0xEB, 0x60, 0xDA, 0xBF, 0xF3, 0x18, 0x10, 0xA3, 0xF3, 0x50, 0xAD,
-0xEF, 0xF7, 0x1F, 0x6B, 0x86, 0x67, 0x6C, 0xEA, 0xDB, 0x14, 0x02, 0x76,
-0x27, 0x61, 0xAC, 0x32, 0xA9, 0xE2, 0x48, 0x32, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0xA9, 0xE2, 0xC9, 0xF7, 0x1B, 0x6B, 0x63, 0xF3,
-0x00, 0x4C, 0x48, 0x32, 0x6B, 0xEB, 0x89, 0xE2, 0x60, 0x33, 0x04, 0xF5,
-0x44, 0x9A, 0x60, 0x33, 0x60, 0xF3, 0x14, 0x4B, 0x40, 0xDB, 0x9F, 0xF3,
-0x17, 0x10, 0xAA, 0x2A, 0xC9, 0xF7, 0x1B, 0x6B, 0x6B, 0xEB, 0x60, 0x33,
-0x60, 0x33, 0x60, 0xF3, 0x04, 0x4B, 0x80, 0xAB, 0xFF, 0x6A, 0x02, 0x4A,
-0x4B, 0xEA, 0x8C, 0xEA, 0x40, 0xCB, 0x8B, 0x17, 0x03, 0x76, 0x9F, 0xF3,
-0x05, 0x61, 0xAC, 0x32, 0xA9, 0xE2, 0x48, 0x32, 0xA9, 0xE2, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xC9, 0xF7, 0x1B, 0x6C, 0x48, 0x32,
-0x68, 0xF0, 0x08, 0x4B, 0x8B, 0xEC, 0x69, 0xE2, 0x80, 0x34, 0x40, 0x9A,
-0x80, 0x34, 0x60, 0xF3, 0x14, 0x4C, 0x40, 0xDC, 0x7F, 0xF3, 0x0E, 0x10,
-0xEB, 0xF5, 0x4D, 0xA5, 0x01, 0x6D, 0x00, 0x1C, 0x4B, 0x2E, 0x4C, 0xEC,
-0xBF, 0xF3, 0x18, 0x10, 0x00, 0x18, 0x84, 0x5C, 0x87, 0x67, 0x7F, 0xF3,
-0x01, 0x10, 0x00, 0x1C, 0x9B, 0x40, 0x09, 0xD7, 0x09, 0x97, 0x0F, 0xF7,
-0x40, 0x40, 0xFF, 0xF7, 0x1F, 0x6D, 0x4C, 0xEF, 0xE2, 0x32, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xAC, 0xEA, 0x63, 0xF3, 0x00, 0x4B,
-0x23, 0xF4, 0x4B, 0xC3, 0x00, 0x1C, 0x96, 0x40, 0x00, 0x65, 0x5F, 0xF3,
-0x09, 0x10, 0x0F, 0xF7, 0x40, 0x40, 0x4C, 0xEF, 0xE2, 0x37, 0x87, 0x67,
-0xFF, 0xF7, 0x1F, 0x6D, 0xAC, 0xEC, 0x06, 0xD4, 0x70, 0xF3, 0x04, 0x41,
-0xA0, 0x98, 0x00, 0x18, 0x63, 0x5E, 0x00, 0x65, 0xC0, 0x98, 0x06, 0x95,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x3D, 0xF7, 0x10, 0x4C,
-0x00, 0x1C, 0x13, 0x58, 0x00, 0x65, 0x3F, 0xF3, 0x0D, 0x10, 0x00, 0x1C,
-0xFA, 0x1F, 0x00, 0x65, 0x3F, 0xF3, 0x08, 0x10, 0x06, 0x94, 0x7A, 0x14,
-0xE2, 0x34, 0x1F, 0xF7, 0x00, 0x6A, 0x4C, 0xEC, 0x00, 0x18, 0x8F, 0x5E,
-0x82, 0x34, 0x1F, 0xF3, 0x1D, 0x10, 0x02, 0xF0, 0x00, 0x68, 0x00, 0x30,
-0x60, 0x6E, 0xAF, 0x40, 0x00, 0x1C, 0x83, 0x45, 0x24, 0x6C, 0xE0, 0xF3,
-0x08, 0x6C, 0x00, 0x1C, 0x2C, 0x1F, 0x00, 0x65, 0x00, 0x1C, 0x9B, 0x40,
-0x00, 0x65, 0x24, 0x6C, 0x00, 0x1C, 0xAC, 0x45, 0xAF, 0x40, 0x1F, 0x6E,
-0x4C, 0xEE, 0x00, 0x1C, 0x96, 0x40, 0x08, 0xD6, 0x00, 0x1C, 0x5B, 0x1F,
-0x64, 0x6C, 0x08, 0x96, 0x70, 0xF3, 0x44, 0x41, 0xC0, 0xC2, 0xFF, 0xF2,
-0x1B, 0x10, 0x00, 0x18, 0x75, 0x5D, 0x00, 0x65, 0xFF, 0xF2, 0x16, 0x10,
-0x0F, 0xF7, 0x40, 0x40, 0x4C, 0xEF, 0xE2, 0x32, 0x01, 0x6B, 0xA2, 0x67,
-0x6C, 0xED, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x46, 0x36,
-0x6C, 0xEE, 0xDB, 0xF7, 0xA8, 0xDC, 0x4A, 0x37, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x4E, 0x32, 0x6C, 0xEA, 0x6C, 0xEF, 0xCB, 0xF4,
-0xD9, 0xC4, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x10, 0xF0,
-0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0xDB, 0xF7, 0xE4, 0xDC, 0x63, 0xF3,
-0x00, 0x4B, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0xC7, 0xF5,
-0x47, 0xC3, 0x5D, 0xF7, 0x0C, 0x4C, 0x00, 0x1C, 0x13, 0x58, 0x04, 0xD2,
-0xDF, 0xF2, 0x04, 0x10, 0x00, 0x18, 0xED, 0x60, 0x87, 0x67, 0xBF, 0xF2,
-0x1F, 0x10, 0x00, 0x18, 0x92, 0x5C, 0x87, 0x67, 0xBF, 0xF2, 0x1A, 0x10,
-0x00, 0x1C, 0x9B, 0x40, 0x09, 0xD7, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x23, 0xF4, 0x4A, 0xA3, 0x09, 0x97,
-0x5F, 0xF4, 0x1D, 0x2A, 0x01, 0x6A, 0x23, 0xF4, 0x4A, 0xC3, 0x0F, 0xF7,
-0x40, 0x40, 0x4C, 0xEF, 0xE0, 0x32, 0x42, 0x32, 0x42, 0x32, 0x23, 0xF4,
-0x4B, 0xC3, 0x82, 0x67, 0x00, 0x1C, 0xA3, 0x31, 0x06, 0xD2, 0x0A, 0x15,
-0x00, 0x18, 0x94, 0x5E, 0x00, 0x65, 0x9F, 0xF2, 0x17, 0x10, 0xDF, 0xF4,
-0x0F, 0x2C, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xC9, 0xF7,
-0x1B, 0x6A, 0x63, 0xF3, 0x00, 0x4B, 0x4B, 0xEA, 0x23, 0xF4, 0x60, 0xAB,
-0x40, 0x32, 0x40, 0x32, 0xFF, 0xF7, 0x1F, 0x6C, 0x60, 0xF3, 0x14, 0x4A,
-0x8C, 0xEB, 0xC7, 0x16, 0x00, 0x1C, 0x9B, 0x40, 0x00, 0x65, 0xC9, 0xF7,
-0x1B, 0x6A, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x4B, 0xEA,
-0x63, 0xF3, 0x00, 0x4B, 0x40, 0x32, 0x23, 0xF4, 0x6B, 0xA3, 0x40, 0x32,
-0x60, 0xF3, 0x14, 0x4A, 0x60, 0xDA, 0x1F, 0x14, 0x00, 0x1C, 0x5C, 0x20,
-0x00, 0x65, 0x7F, 0xF2, 0x09, 0x10, 0x06, 0x95, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0xC9, 0xF7, 0x1B, 0x6C, 0xB0, 0x32, 0x63, 0xF3,
-0x00, 0x4B, 0x8B, 0xEC, 0x69, 0xE2, 0x80, 0x34, 0x20, 0xF3, 0x55, 0xA2,
-0x80, 0x34, 0x60, 0xF3, 0x14, 0x4C, 0xE5, 0x16, 0x06, 0x93, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x70, 0x32, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x69, 0xE2, 0x80, 0x34, 0x20, 0xF3,
-0x54, 0xA2, 0x80, 0x34, 0x60, 0xF3, 0x14, 0x4C, 0xD2, 0x16, 0x06, 0x94,
-0xD6, 0x15, 0x06, 0x93, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x70, 0x32,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0x69, 0xE2, 0x80, 0x34, 0x20, 0xF3, 0x56, 0xAA, 0x80, 0x34, 0x60, 0xF3,
-0x14, 0x4C, 0xBD, 0x16, 0x06, 0x95, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0xC9, 0xF7, 0x1B, 0x6C, 0xB0, 0x32, 0x63, 0xF3, 0x00, 0x4B,
-0x8B, 0xEC, 0x69, 0xE2, 0x80, 0x34, 0x20, 0xF3, 0x52, 0xAA, 0x80, 0x34,
-0x60, 0xF3, 0x14, 0x4C, 0xAA, 0x16, 0x06, 0x93, 0xC9, 0xF7, 0x1B, 0x6C,
-0x8B, 0xEC, 0x70, 0x32, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33,
-0x63, 0xF3, 0x00, 0x4B, 0x69, 0xE2, 0x80, 0x34, 0x20, 0xF3, 0x50, 0xAA,
-0x80, 0x34, 0x60, 0xF3, 0x14, 0x4C, 0x97, 0x16, 0x06, 0x95, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0xB0, 0x32,
-0xC9, 0xF7, 0x1B, 0x6C, 0x69, 0xE2, 0x8B, 0xEC, 0x20, 0xF3, 0x4C, 0x9A,
-0x80, 0x34, 0x80, 0x34, 0x60, 0xF3, 0x14, 0x4C, 0x40, 0xF6, 0x42, 0x32,
-0x82, 0x16, 0x06, 0x93, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x70, 0x32,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0x69, 0xE2, 0x20, 0xF3, 0x4F, 0xA2, 0x80, 0x34, 0x80, 0x34, 0x01, 0x6B,
-0x60, 0xF3, 0x14, 0x4C, 0x6C, 0xEA, 0x6D, 0x16, 0x00, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x18, 0x03, 0x42, 0x34, 0xB0, 0x7C, 0x63, 0x24,
-0x00, 0x00, 0x43, 0xAC, 0x02, 0x80, 0x05, 0x3C, 0xCC, 0x5D, 0xA5, 0x8C,
-0x04, 0x00, 0x02, 0x24, 0x1E, 0x00, 0xA2, 0x10, 0x05, 0x00, 0xA2, 0x2C,
-0x10, 0x00, 0x40, 0x10, 0x05, 0x00, 0x02, 0x24, 0x03, 0x00, 0x02, 0x24,
-0x08, 0x00, 0xA2, 0x10, 0x00, 0x19, 0x04, 0x00, 0x80, 0x10, 0x04, 0x00,
-0x21, 0x10, 0x44, 0x00, 0xC0, 0x10, 0x02, 0x00, 0x23, 0x10, 0x44, 0x00,
-0x00, 0x11, 0x02, 0x00, 0x21, 0x10, 0x44, 0x00, 0x40, 0x19, 0x02, 0x00,
-0xFF, 0xFF, 0x63, 0x24, 0xFE, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xFF, 0xA2, 0x10,
-0x06, 0x00, 0x02, 0x24, 0xF2, 0xFF, 0xA2, 0x14, 0x80, 0x10, 0x04, 0x00,
-0x40, 0x11, 0x04, 0x00, 0x23, 0x10, 0x44, 0x00, 0x80, 0x10, 0x02, 0x00,
-0x21, 0x10, 0x44, 0x00, 0x00, 0x19, 0x02, 0x00, 0x23, 0x18, 0x62, 0x00,
-0x42, 0x1F, 0x00, 0x08, 0x00, 0x19, 0x03, 0x00, 0x80, 0x10, 0x04, 0x00,
-0x21, 0x10, 0x44, 0x00, 0xC0, 0x10, 0x02, 0x00, 0x23, 0x10, 0x44, 0x00,
-0x00, 0x11, 0x02, 0x00, 0x21, 0x10, 0x44, 0x00, 0x42, 0x1F, 0x00, 0x08,
-0x00, 0x19, 0x02, 0x00, 0x00, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x6C, 0x7D, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x02, 0x80, 0x05, 0x3C, 0xCC, 0x5D, 0xA3, 0x8C, 0x05, 0x00, 0x02, 0x24,
-0x06, 0x00, 0x62, 0x10, 0x06, 0x00, 0x62, 0x2C, 0x0C, 0x00, 0x40, 0x10,
-0x06, 0x00, 0x02, 0x24, 0x04, 0x00, 0x02, 0x24, 0x0E, 0x00, 0x62, 0x10,
-0x80, 0x10, 0x04, 0x00, 0x80, 0x10, 0x04, 0x00, 0x21, 0x10, 0x44, 0x00,
-0x80, 0x10, 0x02, 0x00, 0xFF, 0xFF, 0x42, 0x24, 0xFE, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xF7, 0xFF, 0x62, 0x14, 0x00, 0x11, 0x04, 0x00, 0x23, 0x10, 0x44, 0x00,
-0x6D, 0x1F, 0x00, 0x08, 0x40, 0x10, 0x02, 0x00, 0x21, 0x10, 0x44, 0x00,
-0x6D, 0x1F, 0x00, 0x08, 0x40, 0x10, 0x02, 0x00, 0xFF, 0xFF, 0x85, 0x30,
-0x21, 0x30, 0x00, 0x00, 0x25, 0xB0, 0x03, 0x3C, 0x2A, 0xB0, 0x04, 0x3C,
-0xB4, 0x00, 0x63, 0x34, 0x01, 0x00, 0xA2, 0x24, 0x31, 0x00, 0x84, 0x34,
-0x00, 0x00, 0x65, 0xA0, 0x00, 0x00, 0x85, 0xA0, 0xFF, 0xFF, 0x45, 0x30,
-0x12, 0x00, 0xA0, 0x10, 0x01, 0x00, 0x03, 0x24, 0x28, 0xB0, 0x07, 0x3C,
-0x8F, 0x1F, 0x00, 0x08, 0xFF, 0xFF, 0x08, 0x24, 0x00, 0x00, 0x83, 0xA0,
-0x01, 0x00, 0x63, 0x24, 0xFF, 0xFF, 0x63, 0x30, 0x2B, 0x10, 0xA3, 0x00,
-0x09, 0x00, 0x40, 0x14, 0x08, 0x00, 0xC6, 0x24, 0xF9, 0xFF, 0x65, 0x14,
-0x21, 0x20, 0xC7, 0x00, 0x01, 0x00, 0x63, 0x24, 0xFF, 0xFF, 0x63, 0x30,
-0x2B, 0x10, 0xA3, 0x00, 0x00, 0x00, 0x88, 0xA0, 0xF9, 0xFF, 0x40, 0x10,
-0x08, 0x00, 0xC6, 0x24, 0x00, 0x01, 0xA2, 0x2C, 0x13, 0x00, 0x40, 0x10,
-0x21, 0x18, 0xA0, 0x00, 0xFF, 0x00, 0x08, 0x24, 0x28, 0xB0, 0x07, 0x3C,
-0xA3, 0x1F, 0x00, 0x08, 0xFF, 0xFF, 0x09, 0x24, 0xFF, 0xFF, 0x43, 0x30,
-0x00, 0x00, 0xA2, 0xA0, 0x00, 0x01, 0x62, 0x2C, 0x0A, 0x00, 0x40, 0x10,
-0x08, 0x00, 0xC6, 0x24, 0x01, 0x00, 0x62, 0x24, 0xF9, 0xFF, 0x68, 0x14,
-0x21, 0x28, 0xC7, 0x00, 0x00, 0x01, 0x02, 0x24, 0xFF, 0xFF, 0x43, 0x30,
-0x00, 0x01, 0x62, 0x2C, 0x00, 0x00, 0xA9, 0xA0, 0xF8, 0xFF, 0x40, 0x14,
-0x08, 0x00, 0xC6, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xD0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB2, 0xAF, 0x25, 0xB0, 0x12, 0x3C,
-0xFF, 0xFF, 0x02, 0x24, 0x28, 0x00, 0xB6, 0xAF, 0x1C, 0x00, 0xB3, 0xAF,
-0x42, 0x00, 0x56, 0x36, 0x14, 0x00, 0xB1, 0xAF, 0xFC, 0x77, 0x13, 0x24,
-0x40, 0x00, 0x51, 0x36, 0x00, 0x00, 0xC2, 0xA2, 0x10, 0x00, 0xB0, 0xAF,
-0x00, 0x00, 0x33, 0xA6, 0xFC, 0x57, 0x10, 0x24, 0x32, 0x00, 0x04, 0x24,
-0x2C, 0x00, 0xBF, 0xAF, 0x24, 0x00, 0xB5, 0xAF, 0x5B, 0x1F, 0x00, 0x0C,
-0x20, 0x00, 0xB4, 0xAF, 0x00, 0x00, 0x30, 0xA6, 0x5B, 0x1F, 0x00, 0x0C,
-0x32, 0x00, 0x04, 0x24, 0xFC, 0x37, 0x02, 0x24, 0x00, 0x00, 0x22, 0xA6,
-0x5B, 0x1F, 0x00, 0x0C, 0x32, 0x00, 0x04, 0x24, 0x00, 0x00, 0x33, 0xA6,
-0x5B, 0x1F, 0x00, 0x0C, 0x32, 0x00, 0x04, 0x24, 0x00, 0x00, 0x30, 0xA6,
-0x5B, 0x1F, 0x00, 0x0C, 0x32, 0x00, 0x04, 0x24, 0x00, 0x10, 0x02, 0x24,
-0x00, 0x00, 0x22, 0xA6, 0xD8, 0x00, 0x45, 0x36, 0x00, 0x00, 0xA2, 0x90,
-0xA0, 0x00, 0x54, 0x36, 0xA4, 0x00, 0x55, 0x36, 0x7F, 0x00, 0x42, 0x30,
-0x00, 0x00, 0xA2, 0xA0, 0xA8, 0x00, 0x53, 0x36, 0x00, 0x80, 0x02, 0x3C,
-0xFC, 0x17, 0x03, 0x24, 0x00, 0x00, 0x80, 0xAE, 0x00, 0x00, 0xA0, 0xAE,
-0x00, 0x00, 0x62, 0xAE, 0x00, 0x00, 0x23, 0xA6, 0x00, 0x00, 0xA3, 0x90,
-0x02, 0x80, 0x10, 0x3C, 0x60, 0x1B, 0x10, 0x26, 0xAA, 0x1B, 0x04, 0x92,
-0x80, 0xFF, 0x02, 0x24, 0x25, 0x18, 0x62, 0x00, 0x56, 0x01, 0x52, 0x36,
-0xFF, 0x0F, 0x02, 0x24, 0x00, 0x00, 0xA3, 0xA0, 0x00, 0x00, 0x42, 0xA6,
-0x7A, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x04, 0x8E,
-0x14, 0x1C, 0x02, 0x8E, 0x18, 0x1C, 0x03, 0x8E, 0x2C, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x82, 0xAE, 0x18, 0x00, 0xB2, 0x8F, 0x00, 0x00, 0xA3, 0xAE,
-0x20, 0x00, 0xB4, 0x8F, 0x00, 0x00, 0x64, 0xAE, 0x24, 0x00, 0xB5, 0x8F,
-0x00, 0x00, 0xC0, 0xA2, 0x1C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB6, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x30, 0x00, 0xBD, 0x27, 0xC8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0x10, 0x00, 0xA4, 0x27, 0x25, 0xB0, 0x10, 0x3C, 0x34, 0x00, 0xBF, 0xAF,
-0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF, 0x28, 0x00, 0xB4, 0xAF,
-0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x1C, 0x00, 0xB1, 0xAF, 0x40, 0x00, 0x05, 0x36, 0x00, 0x00, 0xA2, 0x94,
-0x24, 0xFA, 0x03, 0x24, 0xA8, 0x00, 0x13, 0x36, 0x24, 0x10, 0x43, 0x00,
-0x00, 0x00, 0xA2, 0xA4, 0xA0, 0x00, 0x12, 0x36, 0xA4, 0x00, 0x10, 0x36,
-0x00, 0x00, 0x55, 0x8E, 0x00, 0x00, 0x16, 0x8E, 0x00, 0x00, 0x71, 0x8E,
-0x00, 0x80, 0x14, 0x3C, 0xFC, 0x37, 0x02, 0x24, 0x00, 0x00, 0x40, 0xAE,
-0x21, 0x88, 0x34, 0x02, 0x00, 0x00, 0x00, 0xAE, 0xFD, 0x00, 0x04, 0x24,
-0x00, 0x00, 0x74, 0xAE, 0x00, 0x00, 0xA2, 0xA4, 0x7A, 0x1F, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAE, 0x10, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x16, 0xAE, 0x00, 0x00, 0x71, 0xAE, 0x90, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0xBF, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
-0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27, 0xC8, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB0, 0xAF, 0x10, 0x00, 0xA4, 0x27, 0x25, 0xB0, 0x10, 0x3C,
-0x34, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0x1C, 0x00, 0xB1, 0xAF, 0x40, 0x00, 0x05, 0x36,
-0x00, 0x00, 0xA2, 0x94, 0xAF, 0xFF, 0x03, 0x24, 0xA8, 0x00, 0x13, 0x36,
-0x24, 0x10, 0x43, 0x00, 0x00, 0x00, 0xA2, 0xA4, 0xA0, 0x00, 0x12, 0x36,
-0xA4, 0x00, 0x10, 0x36, 0x00, 0x00, 0x55, 0x8E, 0x00, 0x00, 0x16, 0x8E,
-0x00, 0x00, 0x71, 0x8E, 0x00, 0x80, 0x14, 0x3C, 0xFC, 0x37, 0x02, 0x24,
-0x00, 0x00, 0x40, 0xAE, 0x21, 0x88, 0x34, 0x02, 0x00, 0x00, 0x00, 0xAE,
-0xFD, 0x00, 0x04, 0x24, 0x00, 0x00, 0x74, 0xAE, 0x00, 0x00, 0xA2, 0xA4,
-0x7A, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAE,
-0x10, 0x00, 0xA4, 0x27, 0x00, 0x00, 0x16, 0xAE, 0x00, 0x00, 0x71, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0xBF, 0x8F,
-0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x25, 0xB0, 0x05, 0x3C, 0x40, 0x00, 0xA5, 0x34,
-0x00, 0x00, 0xA2, 0x94, 0xD8, 0xFD, 0x03, 0x24, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x10, 0x43, 0x00, 0xFC, 0x37, 0x03, 0x24, 0x00, 0x00, 0xA2, 0xA4,
-0x00, 0x00, 0xA3, 0xA4, 0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x00, 0xBF, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xD0, 0xFF, 0xBD, 0x27, 0xFF, 0x00, 0x82, 0x30,
-0x10, 0x00, 0xA4, 0x27, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x21, 0x88, 0xC0, 0x00,
-0x21, 0x80, 0xE0, 0x00, 0xC0, 0x90, 0x02, 0x00, 0x28, 0x00, 0xBF, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0xFF, 0xFF, 0xB3, 0x30, 0x25, 0xB0, 0x02, 0x3C,
-0x40, 0x02, 0x49, 0x34, 0xF8, 0xFF, 0x10, 0x26, 0x21, 0x30, 0x00, 0x00,
-0x01, 0x00, 0x0A, 0x24, 0x44, 0x02, 0x48, 0x34, 0x99, 0x20, 0x00, 0x08,
-0x01, 0x80, 0x07, 0x3C, 0x2E, 0x00, 0xCA, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x02, 0x92, 0x00, 0x00, 0x04, 0x92, 0x02, 0x00, 0x03, 0x92,
-0x03, 0x00, 0x05, 0x92, 0x00, 0x12, 0x02, 0x00, 0x25, 0x20, 0x82, 0x00,
-0x00, 0x1C, 0x03, 0x00, 0x25, 0x20, 0x83, 0x00, 0x21, 0x10, 0x46, 0x02,
-0x00, 0x2E, 0x05, 0x00, 0x01, 0x00, 0xC6, 0x24, 0x25, 0x20, 0x85, 0x00,
-0x25, 0x10, 0x47, 0x00, 0x06, 0x00, 0xC3, 0x2C, 0x00, 0x00, 0x04, 0xAD,
-0x04, 0x00, 0x10, 0x26, 0x00, 0x00, 0x22, 0xAD, 0x12, 0x00, 0x60, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xEA, 0xFF, 0xC0, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x22, 0x92, 0x01, 0x00, 0x23, 0x92, 0x04, 0x00, 0x10, 0x26,
-0x00, 0x14, 0x02, 0x00, 0x25, 0x10, 0x62, 0x02, 0x00, 0x1E, 0x03, 0x00,
-0x25, 0x20, 0x43, 0x00, 0x21, 0x10, 0x46, 0x02, 0x01, 0x00, 0xC6, 0x24,
-0x25, 0x10, 0x47, 0x00, 0x06, 0x00, 0xC3, 0x2C, 0x00, 0x00, 0x04, 0xAD,
-0x00, 0x00, 0x22, 0xAD, 0xF0, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x28, 0x00, 0xBF, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0x03, 0x00, 0x22, 0x92, 0x02, 0x00, 0x24, 0x92, 0x04, 0x00, 0x23, 0x92,
-0x05, 0x00, 0x25, 0x92, 0x8B, 0x20, 0x00, 0x08, 0x00, 0x12, 0x02, 0x00,
-0xFF, 0xFF, 0x84, 0x30, 0x42, 0xB0, 0x08, 0x3C, 0x80, 0x10, 0x04, 0x00,
-0x21, 0x10, 0x48, 0x00, 0x04, 0x00, 0x46, 0xAC, 0x00, 0x00, 0x07, 0x91,
-0x40, 0x18, 0x04, 0x00, 0x03, 0x00, 0x06, 0x24, 0xFF, 0x00, 0xE7, 0x30,
-0x04, 0x30, 0x66, 0x00, 0x01, 0x00, 0x02, 0x24, 0x04, 0x10, 0x62, 0x00,
-0x25, 0x30, 0xC7, 0x00, 0xFF, 0xFF, 0xA5, 0x30, 0x25, 0x10, 0x47, 0x00,
-0x02, 0x00, 0xA0, 0x14, 0xFF, 0x00, 0xC7, 0x30, 0xFF, 0x00, 0x47, 0x30,
-0x42, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x47, 0xA0, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x83, 0x90, 0x01, 0x00, 0x02, 0x24,
-0x08, 0x00, 0x86, 0xAC, 0x18, 0x00, 0x85, 0xAC, 0x00, 0x00, 0x84, 0xAC,
-0x03, 0x00, 0x62, 0x10, 0x04, 0x00, 0x84, 0xAC, 0x5F, 0x5C, 0x00, 0x08,
-0x0C, 0x00, 0x80, 0xAC, 0x0C, 0x00, 0x82, 0x8C, 0x5F, 0x5C, 0x00, 0x08,
-0x10, 0x00, 0x82, 0xAC, 0xC8, 0xFF, 0xBD, 0x27, 0x28, 0x00, 0xB6, 0xAF,
-0x25, 0xB0, 0x02, 0x3C, 0x02, 0x80, 0x16, 0x3C, 0x2C, 0x00, 0xB7, 0xAF,
-0x24, 0x00, 0xB5, 0xAF, 0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x30, 0x00, 0xBF, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x18, 0x03, 0x55, 0x34, 0x01, 0x80, 0x17, 0x3C,
-0x02, 0x80, 0x13, 0x3C, 0x02, 0x80, 0x14, 0x3C, 0xD0, 0xDF, 0xD2, 0x26,
-0x6C, 0x83, 0xE2, 0x26, 0x00, 0x00, 0xA2, 0xAE, 0xD0, 0xDF, 0xD0, 0x8E,
-0x9B, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x5C, 0x71, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00,
-0x96, 0x40, 0x00, 0x0C, 0xFC, 0x5C, 0x60, 0xAE, 0x22, 0x00, 0x12, 0x12,
-0x08, 0x0C, 0x84, 0x26, 0x14, 0x00, 0x03, 0x92, 0x01, 0x00, 0x02, 0x24,
-0x2A, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x60, 0x14,
-0x02, 0x00, 0x02, 0x24, 0x0C, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x10, 0x23, 0x02, 0x1D, 0x00, 0x40, 0x10, 0x23, 0x10, 0x71, 0x00,
-0x0C, 0x00, 0x02, 0xAE, 0x00, 0x00, 0x10, 0x8E, 0xF7, 0x20, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x62, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x60, 0x10,
-0x2B, 0x10, 0x23, 0x02, 0xF5, 0xFF, 0x40, 0x14, 0x23, 0x10, 0x71, 0x00,
-0x08, 0x00, 0x02, 0x8E, 0x18, 0x00, 0x04, 0x8E, 0x09, 0xF8, 0x40, 0x00,
-0x0C, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x10, 0x8E, 0xF7, 0x20, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x96, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x0C, 0x84, 0x26, 0x21, 0x28, 0x00, 0x00, 0x21, 0x30, 0x00, 0x00,
-0x76, 0x39, 0x00, 0x0C, 0x21, 0x38, 0x00, 0x00, 0xED, 0x20, 0x00, 0x08,
-0x6C, 0x83, 0xE2, 0x26, 0x08, 0x00, 0x02, 0x8E, 0x18, 0x00, 0x04, 0x8E,
-0x09, 0xF8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x21, 0x00, 0x08,
-0x0C, 0x00, 0x02, 0xAE, 0x0C, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x10, 0x23, 0x02, 0xDA, 0xFF, 0x40, 0x14, 0x23, 0x10, 0x71, 0x00,
-0x08, 0x00, 0x02, 0x8E, 0x18, 0x00, 0x04, 0x8E, 0x09, 0xF8, 0x40, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0x03, 0xAE, 0x00, 0x00, 0x10, 0x8E, 0xF7, 0x20, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0xC0, 0x54, 0x42, 0x24, 0x18, 0x00, 0xB0, 0xAF, 0xC0, 0x80, 0x04, 0x00,
-0x21, 0x80, 0x02, 0x02, 0x1C, 0x00, 0xB1, 0xAF, 0x20, 0x00, 0xBF, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x00, 0x00, 0x02, 0x8E,
-0x10, 0x00, 0xA4, 0x27, 0x09, 0x00, 0x50, 0x10, 0x21, 0x88, 0x00, 0x00,
-0x04, 0x00, 0x43, 0x8C, 0x21, 0x88, 0x40, 0x00, 0x00, 0x00, 0x42, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xAC, 0x04, 0x00, 0x43, 0xAC,
-0x00, 0x00, 0x31, 0xAE, 0x04, 0x00, 0x31, 0xAE, 0x90, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x20, 0x02, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xE8, 0xFF, 0xBD, 0x27, 0x01, 0x01, 0x82, 0x2C,
-0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x21, 0x18, 0x00, 0x00, 0x10, 0x00, 0x40, 0x14, 0x01, 0x00, 0x04, 0x24,
-0x01, 0x02, 0x02, 0x2E, 0x0D, 0x00, 0x40, 0x14, 0x02, 0x00, 0x04, 0x24,
-0x01, 0x08, 0x02, 0x2E, 0x0A, 0x00, 0x40, 0x14, 0x03, 0x00, 0x04, 0x24,
-0x01, 0x10, 0x02, 0x2E, 0x06, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x04, 0x00, 0x04, 0x24,
-0x35, 0x21, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xF7, 0xFF, 0x40, 0x10,
-0x21, 0x18, 0x40, 0x00, 0x0C, 0x00, 0x50, 0xAC, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0x21, 0x80, 0x80, 0x00, 0x1C, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x10, 0x00, 0x03, 0x8E, 0x02, 0x80, 0x02, 0x3C,
-0xC0, 0x54, 0x42, 0x24, 0xC0, 0x18, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x00, 0x00, 0x64, 0x8C, 0x02, 0x80, 0x06, 0x3C, 0x02, 0x80, 0x07, 0x3C,
-0x00, 0x00, 0x04, 0xAE, 0x04, 0x00, 0x90, 0xAC, 0x04, 0x00, 0x03, 0xAE,
-0xC4, 0x5D, 0xC5, 0x8C, 0x10, 0x00, 0xA4, 0x27, 0x05, 0x00, 0xA0, 0x10,
-0x00, 0x00, 0x70, 0xAC, 0xB0, 0x5D, 0xE2, 0x8C, 0xC4, 0x5D, 0xC0, 0xAC,
-0x25, 0x10, 0x45, 0x00, 0xB0, 0x5D, 0xE2, 0xAC, 0x90, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xC9, 0xF7, 0x1B, 0x6B,
-0x6B, 0xEB, 0x60, 0x33, 0xFF, 0x6A, 0x60, 0x33, 0x4C, 0xEC, 0x60, 0xF1,
-0x00, 0x4B, 0xAC, 0xEA, 0x69, 0xE2, 0x80, 0xC2, 0x20, 0xE8, 0x00, 0x65,
-0xFF, 0x6A, 0x8C, 0xEA, 0x15, 0x5A, 0x0E, 0x60, 0x01, 0x6B, 0x83, 0x67,
-0x84, 0xEA, 0x02, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0xEE, 0xF0, 0x10, 0x4A,
-0x8C, 0xEA, 0x05, 0x2A, 0x0F, 0x6A, 0x8C, 0xEA, 0x02, 0x6B, 0x01, 0x2A,
-0x00, 0x6B, 0x20, 0xE8, 0x43, 0x67, 0x00, 0x00, 0xFF, 0x63, 0x00, 0xD0,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x8C, 0x30, 0x0A, 0x65,
-0x89, 0xE0, 0x48, 0x32, 0x89, 0xE2, 0x68, 0x67, 0x63, 0xF3, 0x00, 0x4B,
-0x48, 0x32, 0x69, 0xE2, 0x01, 0xD1, 0x00, 0x6B, 0x04, 0xF5, 0x6A, 0xC2,
-0x04, 0xF5, 0x6B, 0xC2, 0x04, 0xF5, 0x64, 0x9A, 0x1C, 0x6D, 0x22, 0x67,
-0x01, 0x6F, 0xFF, 0x6E, 0x02, 0x10, 0xFF, 0x4D, 0xCC, 0xED, 0x47, 0x67,
-0x44, 0xED, 0x6C, 0xEA, 0xFA, 0x22, 0x04, 0xF5, 0xAA, 0xC1, 0x00, 0x6D,
-0x1D, 0x5D, 0x13, 0x60, 0x89, 0xE0, 0x48, 0x32, 0x68, 0x67, 0x89, 0xE2,
-0x63, 0xF3, 0x00, 0x4B, 0x48, 0x32, 0x79, 0xE2, 0x04, 0xF5, 0x44, 0x9E,
-0x01, 0x6B, 0x64, 0xED, 0x6C, 0xEA, 0x09, 0x2A, 0x01, 0x4D, 0xFF, 0x6A,
-0x4C, 0xED, 0x1D, 0x5D, 0xED, 0x61, 0x01, 0x91, 0x00, 0x90, 0x20, 0xE8,
-0x01, 0x63, 0x01, 0x91, 0x00, 0x90, 0x04, 0xF5, 0xAB, 0xC6, 0x20, 0xE8,
-0x01, 0x63, 0x00, 0x00, 0xFB, 0x63, 0x07, 0xD1, 0x10, 0xF0, 0x02, 0x69,
-0x00, 0xF4, 0x20, 0x31, 0x00, 0x6A, 0x63, 0xF3, 0x00, 0x49, 0x08, 0x62,
-0x06, 0xD0, 0x04, 0xD2, 0x34, 0x10, 0x03, 0x54, 0x62, 0x60, 0x01, 0x74,
-0x6E, 0x60, 0x04, 0xF5, 0x88, 0x99, 0x07, 0x6A, 0xFF, 0x6B, 0x82, 0x34,
-0x86, 0x34, 0x4C, 0xEC, 0x04, 0x58, 0x6C, 0xEC, 0x12, 0x60, 0x00, 0x18,
-0xA1, 0x5C, 0xB0, 0x67, 0xC9, 0xF7, 0x1B, 0x6C, 0x04, 0xF5, 0x60, 0x99,
-0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x4C, 0xEB, 0x80, 0xF1, 0x04, 0x4C,
-0x08, 0x32, 0x89, 0xE2, 0x04, 0xF5, 0x64, 0xD9, 0x60, 0xDA, 0x00, 0x18,
-0xA5, 0x21, 0x04, 0x94, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x04, 0x93,
-0x80, 0x34, 0x80, 0x34, 0x60, 0xF1, 0x00, 0x4C, 0x89, 0xE3, 0x40, 0xA2,
-0x04, 0x92, 0x7F, 0x49, 0x15, 0x49, 0x01, 0x4A, 0x20, 0x5A, 0x04, 0xD2,
-0x48, 0x60, 0x04, 0xF5, 0xA8, 0x99, 0x01, 0x6B, 0xA2, 0x34, 0x92, 0x32,
-0x6C, 0xEA, 0xFF, 0x6B, 0x6C, 0xEA, 0xF0, 0x22, 0xE4, 0xF4, 0x78, 0x99,
-0xFF, 0x6A, 0x86, 0x34, 0x72, 0x33, 0x4C, 0xEB, 0x7F, 0x6A, 0x4C, 0xEB,
-0x07, 0x6A, 0x4C, 0xEC, 0xFF, 0x6A, 0x4C, 0xEC, 0x07, 0x68, 0xAC, 0xE8,
-0x02, 0x74, 0x4C, 0xE8, 0xB2, 0x61, 0x38, 0x5B, 0x0A, 0x61, 0x01, 0xF6,
-0x01, 0x6A, 0x4B, 0xEA, 0xAC, 0xEA, 0x00, 0xF2, 0x00, 0x6B, 0x6D, 0xEA,
-0x04, 0xF5, 0x48, 0xD9, 0xAA, 0x17, 0x14, 0x5B, 0xA8, 0x60, 0x01, 0xF6,
-0x01, 0x6A, 0x4B, 0xEA, 0xAC, 0xEA, 0x00, 0xF6, 0x00, 0x6B, 0x6D, 0xEA,
-0xF3, 0x17, 0x03, 0x74, 0x9E, 0x61, 0x1A, 0x5B, 0x9C, 0x61, 0x01, 0xF6,
-0x01, 0x6A, 0x4B, 0xEA, 0xAC, 0xEA, 0x00, 0xF4, 0x00, 0x6C, 0x8D, 0xEA,
-0x04, 0xF5, 0x48, 0xD9, 0x92, 0x17, 0x32, 0x5B, 0x90, 0x60, 0x01, 0xF6,
-0x01, 0x6A, 0x4B, 0xEA, 0xAC, 0xEA, 0x00, 0xF4, 0x00, 0x6B, 0x6D, 0xEA,
-0xDB, 0x17, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90, 0x00, 0x6A, 0x00, 0xEF,
-0x05, 0x63, 0x00, 0x00, 0x20, 0xE8, 0x00, 0x65, 0xA4, 0x67, 0xC9, 0xF7,
-0x1B, 0x6C, 0xFC, 0x63, 0x8B, 0xEC, 0x06, 0xD0, 0x80, 0x34, 0xAC, 0x30,
-0xA1, 0xE0, 0x80, 0x34, 0x07, 0x62, 0x80, 0xF1, 0x40, 0x44, 0x08, 0x30,
-0x40, 0xA2, 0xA1, 0xE0, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x63, 0xF3, 0x00, 0x4A, 0x08, 0x30, 0x41, 0xE0, 0x04, 0xF5, 0x48, 0x98,
-0x07, 0x6B, 0x80, 0xF1, 0x04, 0x4C, 0x6C, 0xEA, 0x48, 0x32, 0x89, 0xE2,
-0x04, 0xF5, 0x60, 0x98, 0x40, 0x9A, 0x85, 0x67, 0x6C, 0xEA, 0x04, 0xF5,
-0x44, 0xD8, 0x00, 0x18, 0xA5, 0x21, 0x04, 0xD5, 0x04, 0x95, 0x04, 0xF5,
-0x8A, 0xA0, 0xFF, 0x6A, 0x00, 0x18, 0x93, 0x21, 0x4C, 0xED, 0x07, 0x97,
-0x06, 0x90, 0x00, 0xEF, 0x04, 0x63, 0x00, 0x00, 0xFF, 0xF7, 0x1F, 0x6B,
-0x8C, 0xEB, 0x00, 0xF2, 0x00, 0x6A, 0x0B, 0x6C, 0x6C, 0xEA, 0x6C, 0xEC,
-0x07, 0x6B, 0x0E, 0x2A, 0x0C, 0x5C, 0x0B, 0x60, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x88, 0x32, 0x7D, 0xF7, 0x08, 0x4B, 0x69, 0xE2,
-0x40, 0x9A, 0x00, 0xEA, 0x00, 0x65, 0x07, 0x6B, 0x20, 0xE8, 0x43, 0x67,
-0x06, 0x6B, 0x20, 0xE8, 0x43, 0x67, 0x05, 0x6B, 0x20, 0xE8, 0x43, 0x67,
-0x04, 0x6B, 0x20, 0xE8, 0x43, 0x67, 0x03, 0x6B, 0x20, 0xE8, 0x43, 0x67,
-0x02, 0x6B, 0x20, 0xE8, 0x43, 0x67, 0x01, 0x6B, 0x20, 0xE8, 0x43, 0x67,
-0x00, 0x6B, 0x20, 0xE8, 0x43, 0x67, 0x00, 0x00, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0xF7, 0x63, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0x6A,
-0x0F, 0xD1, 0x23, 0x67, 0x10, 0x62, 0x0E, 0xD0, 0x04, 0xD2, 0x05, 0xD3,
-0x06, 0xD3, 0x07, 0xD3, 0x08, 0xD2, 0x09, 0xD2, 0x0A, 0xD2, 0x0B, 0xD2,
-0x0C, 0xD2, 0xE4, 0xF4, 0x08, 0x49, 0x48, 0x99, 0x01, 0x6B, 0xFF, 0x6C,
-0x42, 0x32, 0x52, 0x32, 0x6C, 0xEA, 0x8C, 0xEA, 0x80, 0xF0, 0x11, 0x22,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x04, 0x96, 0x40, 0x32,
-0x60, 0xF1, 0x00, 0x4A, 0x49, 0xE6, 0x40, 0xA2, 0xFF, 0x6B, 0x4C, 0xEC,
-0x05, 0x92, 0x0C, 0x65, 0x51, 0xE4, 0xC0, 0xF4, 0x4A, 0xA4, 0x6C, 0xEA,
-0x61, 0x99, 0x58, 0xEB, 0xE0, 0xF4, 0x47, 0xA4, 0xFF, 0x6B, 0x6C, 0xEA,
-0x62, 0x99, 0x12, 0xED, 0x00, 0x65, 0x00, 0x65, 0x58, 0xEB, 0x12, 0xEA,
-0x55, 0xE5, 0xFF, 0xF7, 0x4C, 0x99, 0xA3, 0xEA, 0x40, 0xF1, 0x0F, 0x61,
-0xAB, 0xE2, 0xFF, 0xF7, 0x4C, 0xD9, 0x61, 0x99, 0x42, 0x99, 0xC8, 0x67,
-0xFF, 0xF7, 0xEC, 0x99, 0x55, 0xE3, 0xFF, 0xF7, 0x70, 0x99, 0xFF, 0xF7,
-0x54, 0x99, 0x51, 0xE3, 0xFF, 0xF7, 0x7C, 0x99, 0x40, 0x99, 0x41, 0xE3,
-0x05, 0x93, 0x69, 0xE6, 0x20, 0xF5, 0x5E, 0xA2, 0xFF, 0x6E, 0xCC, 0xEA,
-0xC5, 0x67, 0x0F, 0x25, 0xA3, 0xEA, 0xD8, 0x67, 0x0D, 0x2E, 0x48, 0x67,
-0x07, 0x5A, 0x04, 0x61, 0x0C, 0x72, 0x02, 0x60, 0x0D, 0x72, 0x05, 0x61,
-0xAC, 0x32, 0xAB, 0xE2, 0x4E, 0x32, 0x83, 0xEA, 0x10, 0x61, 0x79, 0x26,
-0x05, 0x92, 0x68, 0x67, 0x68, 0x34, 0x51, 0xE4, 0x06, 0x92, 0x69, 0xE2,
-0x44, 0xF5, 0x66, 0xA2, 0xFF, 0x6A, 0x4C, 0xEB, 0x60, 0xF5, 0x40, 0x9C,
-0x44, 0xEB, 0xE3, 0xEA, 0x6A, 0x60, 0x01, 0x68, 0x5F, 0x99, 0x70, 0x67,
-0x88, 0x67, 0x64, 0xEC, 0x6C, 0xEA, 0x00, 0xF1, 0x1C, 0x22, 0x06, 0x96,
-0x95, 0xE6, 0x44, 0xF5, 0x66, 0xA5, 0x04, 0xF5, 0xEC, 0xA5, 0xFF, 0x6E,
-0x46, 0x67, 0xCC, 0xEB, 0x0A, 0x6C, 0xEC, 0xEA, 0x84, 0xEB, 0x82, 0xEA,
-0x00, 0xF1, 0x0D, 0x60, 0x41, 0x47, 0x04, 0xF5, 0x4C, 0xC5, 0xCC, 0xEA,
-0x8E, 0xEA, 0x02, 0x2A, 0x24, 0xF5, 0x09, 0xC5, 0x05, 0x94, 0x68, 0x67,
-0x68, 0x32, 0x89, 0xE2, 0xC0, 0xF5, 0x94, 0x9A, 0x60, 0xF5, 0x40, 0x9A,
-0x84, 0x33, 0x8D, 0xE3, 0x69, 0xE2, 0x4A, 0x37, 0xFF, 0xF7, 0xEC, 0xD9,
-0x05, 0x96, 0x27, 0xF1, 0x44, 0x9E, 0xFF, 0xF7, 0x1F, 0x72, 0xC0, 0xF0,
-0x1B, 0x61, 0x00, 0x6B, 0x61, 0xD9, 0x62, 0xD9, 0xFF, 0xF7, 0x70, 0xD9,
-0xFF, 0xF7, 0x74, 0xD9, 0xFF, 0xF7, 0x78, 0xD9, 0xFF, 0xF7, 0x7C, 0xD9,
-0x60, 0xD9, 0x04, 0x94, 0x0C, 0x96, 0x0B, 0x92, 0x01, 0x4C, 0x0A, 0x93,
-0x04, 0xD4, 0x09, 0x94, 0x7F, 0x4E, 0x7F, 0x4A, 0x7F, 0x4B, 0x15, 0x4E,
-0x15, 0x4A, 0x15, 0x4B, 0x7F, 0x4C, 0x15, 0x4C, 0x0C, 0xD6, 0x0B, 0xD2,
-0x08, 0x96, 0x07, 0x92, 0x0A, 0xD3, 0x06, 0x93, 0x09, 0xD4, 0x04, 0x94,
-0x7F, 0x4E, 0x7F, 0x4A, 0x7F, 0x4B, 0x15, 0x4E, 0x15, 0x4A, 0x15, 0x4B,
-0x7F, 0x49, 0x20, 0x54, 0x08, 0xD6, 0x07, 0xD2, 0x06, 0xD3, 0x15, 0x49,
-0x3F, 0xF7, 0x15, 0x61, 0x10, 0x97, 0x0F, 0x91, 0x0E, 0x90, 0x00, 0xEF,
-0x09, 0x63, 0xA0, 0xF0, 0x0E, 0x25, 0xA0, 0xF0, 0x0E, 0x2E, 0xA4, 0x32,
-0xA9, 0xE2, 0x4A, 0x32, 0x03, 0xEA, 0xC1, 0x60, 0x06, 0x96, 0x48, 0x67,
-0x00, 0x6B, 0x51, 0xE6, 0x04, 0xF5, 0x6C, 0xC4, 0x01, 0x6B, 0x64, 0xEA,
-0x5F, 0x99, 0x6F, 0xEB, 0x6C, 0xEA, 0x5F, 0xD9, 0x24, 0xF5, 0x49, 0xA4,
-0xFF, 0x6C, 0x8C, 0xEA, 0x01, 0x72, 0x10, 0x60, 0x09, 0x96, 0x10, 0xF0,
-0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x00, 0x6D, 0x63, 0xF3, 0x00, 0x4A,
-0x4D, 0xE6, 0x85, 0x67, 0xA9, 0xE3, 0x01, 0x4D, 0x1D, 0x55, 0x44, 0xF5,
-0x86, 0xC2, 0xFA, 0x61, 0x06, 0x93, 0x88, 0x67, 0x00, 0x6E, 0x89, 0xE3,
-0x24, 0xF5, 0xC9, 0xC2, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x9D, 0xF7, 0x18, 0x4A, 0x00, 0x9A, 0x10, 0xF0, 0x02, 0x6F, 0x00, 0xF4,
-0xE0, 0x37, 0x10, 0xF0, 0x02, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0x00, 0x6D,
-0x5C, 0xF4, 0x00, 0x4F, 0xDC, 0xF3, 0x0C, 0x4E, 0xA8, 0x32, 0xED, 0xE2,
-0x60, 0x9B, 0x11, 0xE2, 0xC9, 0xE2, 0xC0, 0xF5, 0x74, 0xDC, 0x40, 0x9A,
-0x01, 0x4D, 0x1D, 0x55, 0x60, 0xF5, 0x40, 0xDC, 0xF3, 0x61, 0x68, 0x67,
-0x20, 0x23, 0x07, 0x94, 0xA8, 0x67, 0xFF, 0x4D, 0x04, 0xF5, 0x4B, 0xA4,
-0xFF, 0x68, 0x42, 0xED, 0x18, 0x61, 0x08, 0x96, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x69, 0xE6, 0x04, 0xF5,
-0x8B, 0xA2, 0x04, 0xF5, 0xC4, 0x9A, 0x01, 0x6F, 0x0C, 0xEC, 0x67, 0x67,
-0x64, 0xED, 0x46, 0x67, 0x6C, 0xEA, 0x6E, 0xEA, 0x00, 0xF1, 0x03, 0x22,
-0xFF, 0x4D, 0x82, 0xED, 0xF6, 0x60, 0x88, 0x67, 0x10, 0xF0, 0x02, 0x6E,
-0x00, 0xF4, 0xC0, 0x36, 0x88, 0x32, 0x63, 0xF3, 0x00, 0x4E, 0xC9, 0xE2,
-0xC0, 0xF5, 0x94, 0x9A, 0x60, 0xF5, 0x40, 0x9A, 0x84, 0x33, 0x8D, 0xE3,
-0x69, 0xE2, 0x4A, 0x37, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0xCB, 0xF4, 0x46, 0xA2, 0xFF, 0x6B, 0x6C, 0xEA, 0x22, 0x72, 0xC0, 0xF0,
-0x17, 0x61, 0x88, 0x67, 0x13, 0x74, 0x3F, 0xF7, 0x0D, 0x60, 0x07, 0x96,
-0x01, 0x6B, 0x64, 0xEC, 0x64, 0xF5, 0x44, 0x9E, 0xFF, 0xF7, 0xEC, 0xD9,
-0x6D, 0xEA, 0x64, 0xF5, 0x44, 0xDE, 0x05, 0x96, 0x27, 0xF1, 0x44, 0x9E,
-0xFF, 0xF7, 0x1F, 0x72, 0x3F, 0xF7, 0x05, 0x60, 0x04, 0x95, 0xFF, 0x6A,
-0x88, 0x67, 0x00, 0x18, 0x93, 0x21, 0x4C, 0xED, 0x1E, 0x17, 0x00, 0x6B,
-0xFF, 0xF7, 0x6C, 0xD9, 0xB0, 0x16, 0x1F, 0xF7, 0x18, 0x26, 0x05, 0x94,
-0x68, 0x67, 0x68, 0x32, 0x89, 0xE2, 0xC0, 0xF5, 0x54, 0x9A, 0x43, 0xEF,
-0x4E, 0x17, 0x48, 0x67, 0x1C, 0x5A, 0xFF, 0xF6, 0x17, 0x60, 0x06, 0x94,
-0x4D, 0xE4, 0x24, 0xF5, 0x49, 0xA3, 0xFF, 0x6C, 0x01, 0x72, 0x53, 0x60,
-0x0C, 0x96, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x00, 0x6D,
-0x63, 0xF3, 0x00, 0x4A, 0x4D, 0xE6, 0x85, 0x67, 0xA9, 0xE3, 0x01, 0x4D,
-0x1D, 0x55, 0x44, 0xF5, 0x86, 0xC2, 0xFA, 0x61, 0x06, 0x93, 0x88, 0x67,
-0x00, 0x6E, 0x89, 0xE3, 0x01, 0x6C, 0x04, 0xF5, 0xCC, 0xC2, 0x24, 0xF5,
-0xC9, 0xC2, 0x64, 0x67, 0x48, 0x67, 0x64, 0xEA, 0x5F, 0x99, 0x6F, 0xEB,
-0x6C, 0xEA, 0x68, 0x67, 0x5F, 0xD9, 0x4E, 0x23, 0x20, 0xF0, 0x42, 0xA1,
-0xA8, 0x67, 0x01, 0x4D, 0xA2, 0xEA, 0xFF, 0x68, 0x17, 0x61, 0x0A, 0x93,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x63, 0xF3, 0x00, 0x4C,
-0x89, 0xE3, 0x04, 0xF5, 0x8A, 0xA2, 0x04, 0xF5, 0xC4, 0x9A, 0x01, 0x6F,
-0x0C, 0xEC, 0x67, 0x67, 0x64, 0xED, 0x46, 0x67, 0x6C, 0xEA, 0x6E, 0xEA,
-0x6F, 0x22, 0x01, 0x4D, 0xA2, 0xEC, 0xF7, 0x60, 0x10, 0xF0, 0x02, 0x6A,
-0x00, 0xF4, 0x40, 0x32, 0xCB, 0xF4, 0x46, 0xA2, 0x22, 0x72, 0xBF, 0xF6,
-0x07, 0x61, 0x48, 0x67, 0xEE, 0x4A, 0xFF, 0x6B, 0x6C, 0xEA, 0x02, 0x5A,
-0xBF, 0xF6, 0x00, 0x60, 0x18, 0x6E, 0x0E, 0x65, 0x9D, 0x16, 0xC8, 0x67,
-0x18, 0x5E, 0x3F, 0x61, 0x44, 0xF5, 0x46, 0xA3, 0x4C, 0xEC, 0x05, 0x5C,
-0x03, 0x60, 0x01, 0x4A, 0x44, 0xF5, 0x46, 0xC3, 0x06, 0x93, 0x88, 0x67,
-0x00, 0x6E, 0x89, 0xE3, 0x01, 0x6C, 0x04, 0xF5, 0xCC, 0xC2, 0x24, 0xF5,
-0xC9, 0xC2, 0x64, 0x67, 0x48, 0x67, 0x64, 0xEA, 0x5F, 0x99, 0x6F, 0xEB,
-0x6C, 0xEA, 0x68, 0x67, 0x5F, 0xD9, 0xB2, 0x2B, 0x20, 0xF0, 0x42, 0xA1,
-0xA4, 0x67, 0xFF, 0x68, 0xAD, 0x22, 0x0B, 0x94, 0x10, 0xF0, 0x02, 0x6E,
-0x00, 0xF4, 0xC0, 0x36, 0x63, 0xF3, 0x00, 0x4E, 0xC9, 0xE4, 0x04, 0xF5,
-0x8A, 0xA2, 0xE5, 0x67, 0x04, 0xF5, 0xC4, 0x9A, 0x0C, 0xEC, 0x67, 0x67,
-0x64, 0xED, 0x46, 0x67, 0x6C, 0xEA, 0x6E, 0xEA, 0x09, 0x22, 0x01, 0x4D,
-0xA2, 0xEC, 0x96, 0x61, 0x67, 0x67, 0x64, 0xED, 0x46, 0x67, 0x6C, 0xEA,
-0x6E, 0xEA, 0xF7, 0x2A, 0x0C, 0xED, 0x0D, 0x65, 0x8D, 0x17, 0x48, 0x67,
-0x05, 0x5A, 0x05, 0x60, 0x44, 0xF5, 0x46, 0xA3, 0x4C, 0xEC, 0x03, 0x5C,
-0xBD, 0x17, 0x44, 0xF5, 0x46, 0xA3, 0x4C, 0xEC, 0x04, 0x5C, 0xB8, 0x17,
-0x07, 0x94, 0x48, 0x67, 0x01, 0x6B, 0x64, 0xEA, 0x64, 0xF5, 0x44, 0x9C,
-0x6D, 0xEA, 0x64, 0xF5, 0x44, 0xDC, 0x50, 0x16, 0x0C, 0xED, 0x0D, 0x65,
-0x91, 0x17, 0x0C, 0xED, 0x0D, 0x65, 0xFD, 0x16, 0xFC, 0x63, 0x10, 0xF0,
-0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x05, 0xD1, 0x06, 0x62, 0x04, 0xD0,
-0x63, 0xF3, 0x00, 0x4C, 0x87, 0xF0, 0x58, 0x9C, 0x87, 0xF0, 0x7D, 0xA4,
-0x65, 0xE2, 0x87, 0xF0, 0x54, 0x9C, 0x43, 0xE9, 0xE0, 0xF0, 0x04, 0x60,
-0x04, 0x67, 0x0C, 0x10, 0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4, 0x00, 0x30,
-0x63, 0xF3, 0x00, 0x48, 0x87, 0xF0, 0x54, 0x98, 0x10, 0x49, 0x43, 0xE9,
-0xC0, 0xF0, 0x16, 0x60, 0x87, 0xF0, 0x5D, 0xA0, 0xFF, 0xF7, 0x1F, 0x6D,
-0x2C, 0xED, 0x10, 0x4A, 0x87, 0xF0, 0x5D, 0xC0, 0xEF, 0xF7, 0x1E, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4,
-0x80, 0x34, 0xAA, 0xF2, 0x14, 0x4C, 0x4D, 0xED, 0x00, 0x1C, 0xF4, 0x54,
-0x10, 0x6E, 0x46, 0xF7, 0xB8, 0x98, 0x1F, 0x6B, 0x40, 0xF4, 0xA2, 0x34,
-0x6C, 0xEC, 0x8C, 0x32, 0x89, 0xE2, 0x48, 0x32, 0x89, 0xE2, 0x48, 0x32,
-0x19, 0xE2, 0x04, 0xF5, 0x48, 0x9E, 0x01, 0x6B, 0x42, 0x32, 0x52, 0x32,
-0x6C, 0xEA, 0xFF, 0x6B, 0x6C, 0xEA, 0xC8, 0x22, 0xC9, 0xF7, 0x1B, 0x6B,
-0x6B, 0xEB, 0x60, 0x33, 0x60, 0x33, 0x60, 0xF1, 0x00, 0x4B, 0x69, 0xE4,
-0x40, 0xA2, 0xFF, 0x6B, 0xFF, 0x6F, 0x4C, 0xEB, 0x0B, 0x65, 0x46, 0xF7,
-0x74, 0x98, 0x3F, 0x68, 0x80, 0xF5, 0x62, 0x32, 0x0C, 0xEA, 0x05, 0x52,
-0x4C, 0xEF, 0x01, 0x61, 0x04, 0x6F, 0xC0, 0xF7, 0x62, 0x32, 0x0E, 0x2A,
-0xE4, 0xF4, 0x54, 0x9E, 0x04, 0x6F, 0x01, 0x4A, 0xE4, 0xF4, 0x54, 0xDE,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A,
-0x46, 0xF7, 0xB8, 0x9A, 0xA2, 0x32, 0x52, 0x32, 0x1F, 0x6B, 0x6C, 0xEA,
-0x08, 0x52, 0x52, 0x60, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x63, 0xF3, 0x00, 0x4D, 0x46, 0xF7, 0x54, 0x9D, 0x0C, 0xEA, 0x08, 0x67,
-0x0E, 0xEA, 0x46, 0x2A, 0x74, 0x27, 0x01, 0x77, 0x05, 0x61, 0xC4, 0xF4,
-0x5C, 0x9E, 0x01, 0x4A, 0xC4, 0xF4, 0x5C, 0xDE, 0x02, 0x77, 0x05, 0x61,
-0xE4, 0xF4, 0x40, 0x9E, 0x01, 0x4A, 0xE4, 0xF4, 0x40, 0xDE, 0x03, 0x77,
-0x05, 0x61, 0xE4, 0xF4, 0x44, 0x9E, 0x01, 0x4A, 0xE4, 0xF4, 0x44, 0xDE,
-0x04, 0x77, 0x05, 0x61, 0xE4, 0xF4, 0x48, 0x9E, 0x01, 0x4A, 0xE4, 0xF4,
-0x48, 0xDE, 0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4, 0x00, 0x30, 0xA8, 0x67,
-0x63, 0xF3, 0x00, 0x48, 0x09, 0xE5, 0xE4, 0xF4, 0x78, 0x9E, 0x00, 0xF5,
-0x44, 0xA2, 0xFF, 0x6D, 0x72, 0x33, 0xAC, 0xEA, 0x43, 0xEB, 0x4D, 0x61,
-0xE4, 0xF4, 0x4C, 0x9E, 0x08, 0x67, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x01, 0x4A, 0xE4, 0xF4, 0x4C, 0xDE, 0x08, 0x32, 0x63, 0xF3,
-0x00, 0x4B, 0x09, 0xE2, 0x69, 0xE2, 0xE9, 0xE2, 0xA0, 0xF3, 0x68, 0xA2,
-0xAC, 0xEB, 0xC4, 0xF4, 0x54, 0x9E, 0x69, 0xE2, 0xC4, 0xF4, 0x54, 0xDE,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0x08, 0xF0, 0x54, 0x9B, 0x3F, 0xF7, 0x1E, 0x22, 0x05, 0x74, 0x3F, 0xF7,
-0x1B, 0x61, 0x46, 0xF7, 0x54, 0x9B, 0xC0, 0xF7, 0x42, 0x32, 0x3F, 0xF7,
-0x15, 0x22, 0x00, 0x6A, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34,
-0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4, 0x00, 0x30, 0x08, 0xF0, 0x54, 0xDB,
-0x9D, 0xF7, 0x1C, 0x4C, 0x63, 0xF3, 0x00, 0x48, 0x00, 0x1C, 0x13, 0x58,
-0x10, 0x49, 0x87, 0xF0, 0x54, 0x98, 0x43, 0xE9, 0x3F, 0xF7, 0x0A, 0x61,
-0x06, 0x97, 0x05, 0x91, 0x04, 0x90, 0x00, 0xEF, 0x04, 0x63, 0xC4, 0xF4,
-0x58, 0x9E, 0x01, 0x4A, 0xC4, 0xF4, 0x58, 0xDE, 0x86, 0x17, 0xE4, 0xF4,
-0x50, 0x9E, 0xA8, 0x67, 0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4, 0x00, 0x30,
-0x01, 0x4A, 0xE4, 0xF4, 0x50, 0xDE, 0xA8, 0x32, 0xA9, 0xE2, 0x63, 0xF3,
-0x00, 0x48, 0x09, 0xE2, 0xE9, 0xE2, 0x20, 0xF4, 0x79, 0xA2, 0xFF, 0x6A,
-0x4C, 0xEB, 0xB1, 0x17, 0xE0, 0x63, 0x00, 0x6A, 0x3E, 0x62, 0x3D, 0xD1,
-0x3C, 0xD0, 0xFC, 0x63, 0x1D, 0xD2, 0x62, 0x67, 0x1D, 0x94, 0x04, 0x05,
-0x07, 0x68, 0x94, 0x32, 0xA9, 0xE2, 0x1E, 0xD0, 0x60, 0xDA, 0x1E, 0x94,
-0x04, 0x4A, 0xFF, 0x4C, 0x00, 0x54, 0x1E, 0xD4, 0xF9, 0x60, 0x1D, 0x95,
-0x01, 0x4D, 0x03, 0x5D, 0x1D, 0xD5, 0xEE, 0x61, 0xC9, 0xF7, 0x1B, 0x6A,
-0x4B, 0xEA, 0x40, 0x31, 0x20, 0x31, 0xC0, 0xF2, 0x44, 0x41, 0x1D, 0xD3,
-0x60, 0xDA, 0x41, 0x99, 0x01, 0xF7, 0x00, 0x6B, 0x01, 0xF4, 0x84, 0x41,
-0x42, 0x32, 0x6C, 0xEA, 0x42, 0x32, 0x00, 0x1C, 0xFA, 0x5B, 0x33, 0xD2,
-0x01, 0xF4, 0x88, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x31, 0xD2, 0x9D, 0x67,
-0x70, 0x4C, 0x00, 0x1C, 0x8A, 0x40, 0x32, 0xD2, 0x1D, 0x94, 0x10, 0x6D,
-0xA4, 0xED, 0x00, 0x1C, 0xAC, 0x45, 0xFF, 0x4D, 0x9D, 0x67, 0x70, 0x4C,
-0x00, 0x1C, 0x90, 0x40, 0x1F, 0xD2, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C,
-0x00, 0x1C, 0xF0, 0x42, 0x01, 0x6C, 0x9D, 0x67, 0x00, 0x1C, 0x8A, 0x40,
-0x70, 0x4C, 0x1D, 0x94, 0x10, 0x6D, 0xA4, 0xED, 0x00, 0x1C, 0xAC, 0x45,
-0xFF, 0x4D, 0x9D, 0x67, 0x70, 0x4C, 0x00, 0x1C, 0x90, 0x40, 0x20, 0xD2,
-0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C, 0xF0, 0x42, 0x1D, 0x94,
-0xE1, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xD1, 0xF6,
-0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x21, 0xD2, 0x71, 0xF6, 0x80, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x22, 0xD2, 0x71, 0xF6, 0x84, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x23, 0xD2, 0x71, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x24, 0xD2, 0x71, 0xF6, 0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x25, 0xD2,
-0x81, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x26, 0xD2, 0x81, 0xF6,
-0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x27, 0xD2, 0x81, 0xF6, 0x88, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x28, 0xD2, 0x81, 0xF6, 0x8C, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x29, 0xD2, 0xD1, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x2A, 0xD2, 0xD1, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x2B, 0xD2,
-0xD1, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x2C, 0xD2, 0x2D, 0xD2,
-0xE7, 0xF7, 0x0E, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xA2, 0x67, 0xE1, 0xF6,
-0x80, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x36, 0xD2,
-0x36, 0x95, 0xD1, 0xF6, 0x8C, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0x71, 0xF6, 0x80, 0x41, 0xF2, 0xF2,
-0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0x71, 0xF6,
-0x84, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x36, 0x95, 0x71, 0xF6, 0x88, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0x71, 0xF6, 0x8C, 0x41, 0xF2, 0xF2,
-0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0x81, 0xF6,
-0x80, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x36, 0x95, 0x81, 0xF6, 0x84, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0x81, 0xF6, 0x88, 0x41, 0xF2, 0xF2,
-0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0x81, 0xF6,
-0x8C, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x36, 0x95, 0xD1, 0xF6, 0x80, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0xD1, 0xF6, 0x84, 0x41, 0xF2, 0xF2,
-0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x36, 0x95, 0xD1, 0xF6,
-0x88, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x33, 0x93, 0x01, 0x6A, 0x1D, 0x90, 0x4E, 0xEB, 0x43, 0xEB, 0x58, 0x67,
-0x39, 0xD2, 0x0F, 0xF7, 0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x10, 0xF0,
-0x00, 0x4A, 0x43, 0xD2, 0x00, 0xF5, 0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32,
-0x40, 0x32, 0x1E, 0xD0, 0x37, 0xD2, 0x11, 0x67, 0x01, 0xF0, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x00, 0x6B, 0x40, 0x32, 0x1D, 0xD3, 0x38, 0xD2,
-0x33, 0x94, 0x60, 0xF1, 0x13, 0x24, 0x39, 0x95, 0xE0, 0xF1, 0x0C, 0x2D,
-0xA1, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x05, 0xF0,
-0x00, 0x6B, 0x6B, 0xEB, 0x60, 0x33, 0x60, 0x33, 0x4C, 0xEB, 0x01, 0x5B,
-0x58, 0x67, 0x91, 0xF6, 0x84, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x35, 0xD2,
-0xE0, 0xF3, 0x1F, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x6C, 0xEA, 0x42, 0x32,
-0x42, 0x32, 0xB1, 0xF6, 0x84, 0x40, 0x3D, 0xD3, 0x00, 0x1C, 0xFA, 0x5B,
-0x2E, 0xD2, 0x3D, 0x94, 0x8C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x91, 0xF6,
-0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x2F, 0xD2, 0x3D, 0x95, 0xB1, 0xF6,
-0x8C, 0x40, 0xAC, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x00, 0x1C, 0xFA, 0x5B,
-0x30, 0xD2, 0x3D, 0x93, 0x2E, 0x94, 0x4C, 0xEB, 0x62, 0x32, 0x20, 0xF1,
-0x00, 0x74, 0x42, 0x32, 0xA0, 0xF2, 0x15, 0x60, 0x2F, 0x95, 0x20, 0xF1,
-0x00, 0x75, 0xA0, 0xF2, 0x10, 0x60, 0x30, 0x93, 0x20, 0x73, 0xA0, 0xF2,
-0x0C, 0x60, 0x20, 0x72, 0x01, 0x6B, 0xA0, 0xF2, 0x08, 0x60, 0x2E, 0x94,
-0x80, 0x74, 0xA0, 0xF2, 0x02, 0x60, 0x2F, 0x95, 0x80, 0x75, 0x80, 0xF2,
-0x1E, 0x60, 0x30, 0x94, 0xE0, 0xF3, 0x00, 0x74, 0x80, 0xF2, 0x19, 0x60,
-0xE0, 0xF3, 0x00, 0x72, 0x01, 0x6A, 0x80, 0xF2, 0x14, 0x60, 0x35, 0x95,
-0x03, 0x25, 0x02, 0x23, 0x20, 0xF4, 0x19, 0x2A, 0x1D, 0x95, 0x01, 0x4D,
-0x0A, 0x5D, 0x1D, 0xD5, 0x97, 0x61, 0x1E, 0x92, 0x01, 0x4A, 0x03, 0x5A,
-0x1E, 0xD2, 0x8A, 0x61, 0x04, 0x90, 0x20, 0xF4, 0x09, 0x28, 0x0C, 0x91,
-0x03, 0x29, 0x14, 0x92, 0xFF, 0x6C, 0x2B, 0x22, 0x90, 0x67, 0x00, 0x18,
-0xA1, 0x5E, 0xB1, 0x67, 0x03, 0x5A, 0x07, 0x60, 0x05, 0x94, 0x00, 0x18,
-0xA1, 0x5E, 0x0D, 0x95, 0x03, 0x5A, 0x00, 0x6C, 0x1E, 0x61, 0x14, 0x93,
-0x90, 0x67, 0xA3, 0x67, 0x00, 0x18, 0xA1, 0x5E, 0x40, 0xD3, 0x03, 0x5A,
-0x07, 0x60, 0x05, 0x94, 0x00, 0x18, 0xA1, 0x5E, 0x15, 0x95, 0x03, 0x5A,
-0x00, 0x6C, 0x0F, 0x61, 0x40, 0x95, 0x00, 0x18, 0xA1, 0x5E, 0x91, 0x67,
-0x03, 0x5A, 0x40, 0xF2, 0x1E, 0x60, 0x0D, 0x94, 0x00, 0x18, 0xA1, 0x5E,
-0x15, 0x95, 0x03, 0x5A, 0x01, 0x6C, 0x40, 0xF2, 0x16, 0x60, 0xFF, 0x74,
-0x40, 0xF2, 0x17, 0x60, 0x04, 0x05, 0x94, 0x34, 0x10, 0xF0, 0x02, 0x69,
-0x00, 0xF4, 0x20, 0x31, 0xB1, 0xE4, 0x63, 0xF3, 0x00, 0x49, 0x60, 0x9C,
-0x43, 0x99, 0x00, 0xF4, 0x00, 0x68, 0xE0, 0xF3, 0x1F, 0x6F, 0x0B, 0xE8,
-0xEC, 0xEB, 0x0C, 0xEA, 0x6D, 0xEA, 0x61, 0x9C, 0x02, 0xF0, 0x00, 0x6E,
-0xCB, 0xEE, 0xEC, 0xEB, 0xC0, 0x36, 0xE0, 0xF3, 0x1F, 0x4E, 0x60, 0x33,
-0x68, 0x33, 0xCC, 0xEA, 0xE7, 0xF7, 0x10, 0x6D, 0x6D, 0xEA, 0xAB, 0xED,
-0x62, 0x9C, 0xA0, 0x35, 0xA0, 0x35, 0xFF, 0x4D, 0xEC, 0xEB, 0x00, 0xF5,
-0x60, 0x33, 0xAC, 0xEA, 0x6D, 0xEA, 0x43, 0xD9, 0x63, 0x9C, 0x44, 0x99,
-0xEC, 0xEB, 0x0C, 0xEA, 0x6D, 0xEA, 0x64, 0x9C, 0xCC, 0xEA, 0xEC, 0xEB,
-0x60, 0x33, 0x68, 0x33, 0x6D, 0xEA, 0x65, 0x9C, 0xAC, 0xEA, 0xEC, 0xEB,
-0x00, 0xF5, 0x60, 0x33, 0x6D, 0xEA, 0x44, 0xD9, 0x46, 0x9C, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x4A, 0xC9,
-0x47, 0x9C, 0x4B, 0xC9, 0x44, 0x9B, 0x80, 0xF7, 0x42, 0x32, 0x01, 0x72,
-0xC0, 0xF2, 0x1E, 0x61, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x31,
-0x20, 0x31, 0xE1, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x21, 0x95,
-0xD1, 0xF6, 0x8C, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x22, 0x95, 0x71, 0xF6,
-0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x23, 0x95, 0x71, 0xF6, 0x84, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x24, 0x95, 0x71, 0xF6, 0x88, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x25, 0x95, 0x71, 0xF6, 0x8C, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x26, 0x95, 0x81, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x27, 0x95,
-0x81, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x28, 0x95, 0x81, 0xF6,
-0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x29, 0x95, 0x81, 0xF6, 0x8C, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x2A, 0x95, 0xD1, 0xF6, 0x80, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x2B, 0x95, 0xD1, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x2C, 0x95, 0x81, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x2D, 0x95,
-0x1F, 0x96, 0x10, 0x6D, 0xA4, 0xED, 0xFF, 0x4D, 0x00, 0x1C, 0x83, 0x45,
-0x00, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C, 0xF0, 0x42,
-0x01, 0x6C, 0x20, 0x96, 0x10, 0x6D, 0xA4, 0xED, 0xFF, 0x4D, 0x00, 0x1C,
-0x83, 0x45, 0x00, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C,
-0xF0, 0x42, 0x00, 0x6C, 0x10, 0x6D, 0xA4, 0xED, 0x1E, 0x6C, 0x00, 0x1C,
-0xAC, 0x45, 0xFF, 0x4D, 0x01, 0x6E, 0x22, 0x67, 0x4D, 0xEE, 0x10, 0x6D,
-0x03, 0x6A, 0x4B, 0xEA, 0xA4, 0xED, 0x4C, 0xEE, 0xFF, 0x4D, 0x00, 0x1C,
-0x83, 0x45, 0x1E, 0x6C, 0x00, 0x1C, 0x2C, 0x1F, 0x03, 0x6C, 0x10, 0x6D,
-0x03, 0x6A, 0xD1, 0x67, 0xA4, 0xED, 0x1E, 0x6C, 0xFF, 0x4D, 0x00, 0x1C,
-0x83, 0x45, 0x4D, 0xEE, 0x04, 0x63, 0x3E, 0x97, 0x3D, 0x91, 0x3C, 0x90,
-0x00, 0xEF, 0x20, 0x63, 0xA0, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x01, 0xF4,
-0x84, 0x40, 0x2A, 0xF4, 0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x08, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x7F, 0x4D, 0x01, 0xF4, 0x88, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x65, 0x4D, 0x8F, 0xF7, 0x00, 0x6D, 0xAB, 0xED,
-0xA0, 0x35, 0x21, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0xA0, 0x35,
-0x00, 0xF2, 0x14, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x41, 0xF6, 0x80, 0x40,
-0x40, 0xF1, 0x08, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x0D, 0xF0,
-0x16, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x41, 0xF6, 0x84, 0x40, 0xA0, 0xF4,
-0x02, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x41, 0xF6, 0x8C, 0x40,
-0xC5, 0xF0, 0x11, 0x6D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0xF2,
-0x14, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x61, 0xF6, 0x80, 0x40, 0x40, 0xF1,
-0x0D, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x05, 0xF0, 0x16, 0x6D,
-0xA0, 0x35, 0xA0, 0x35, 0x61, 0xF6, 0x84, 0x40, 0xA1, 0xF0, 0x1A, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x61, 0xF6, 0x8C, 0x40, 0xC5, 0xF0,
-0x11, 0x6D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x37, 0x95, 0x41, 0xF6,
-0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x01, 0x4D, 0x38, 0x95, 0x41, 0xF6,
-0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x01, 0x4D, 0x00, 0x1C, 0x2C, 0x1F,
-0x03, 0x6C, 0xA0, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x01, 0xF4, 0x84, 0x40,
-0x2A, 0xF4, 0x13, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x01, 0xF4,
-0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0xE4, 0x6D, 0x21, 0xF6, 0x88, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x33, 0x95, 0x39, 0x95, 0x1F, 0xF6, 0x14, 0x25,
-0x21, 0xF0, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xFF, 0x6D,
-0x01, 0x4D, 0xAC, 0xEA, 0x42, 0x32, 0x34, 0xD2, 0x02, 0x22, 0x01, 0x6A,
-0x34, 0xD2, 0xA0, 0x35, 0xA0, 0x35, 0x21, 0xF0, 0x80, 0x41, 0x3A, 0xD5,
-0x00, 0xF1, 0x00, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x3A, 0x95,
-0x21, 0xF0, 0x88, 0x41, 0x00, 0xF1, 0x00, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xA0, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x01, 0xF4, 0x84, 0x41,
-0x2A, 0xF4, 0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x08, 0x6D,
-0xA0, 0x35, 0xA0, 0x35, 0x7F, 0x4D, 0x01, 0xF4, 0x88, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x65, 0x4D, 0x43, 0x93, 0x21, 0xF6, 0x88, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x60, 0x35, 0x3A, 0x95, 0x31, 0xF6, 0x80, 0x41, 0x0F, 0xF4,
-0x00, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x3A, 0x95, 0x31, 0xF6,
-0x84, 0x41, 0x09, 0xF0, 0x00, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x02, 0xF0, 0x01, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x31, 0xF6, 0x88, 0x41,
-0x3B, 0xD5, 0x1B, 0xF4, 0x1F, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x3B, 0x95, 0x31, 0xF6, 0x8C, 0x41, 0x11, 0xF4, 0x1F, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x00, 0xF2, 0x14, 0x6D, 0xA0, 0x35, 0xA0, 0x35,
-0x41, 0xF6, 0x80, 0x41, 0x00, 0xF1, 0x02, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x0D, 0xF0, 0x16, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x41, 0xF6,
-0x84, 0x41, 0xC0, 0xF4, 0x07, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x41, 0xF6, 0x8C, 0x41, 0xC5, 0xF0, 0x11, 0x6D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x61, 0xF6, 0x8C, 0x41, 0xC5, 0xF0, 0x11, 0x6D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x3A, 0x95, 0x51, 0xF6, 0x80, 0x41, 0x0F, 0xF4,
-0x00, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x3A, 0x95, 0x51, 0xF6,
-0x84, 0x41, 0x09, 0xF0, 0x00, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x3B, 0x95, 0x51, 0xF6, 0x88, 0x41, 0x3B, 0xF4, 0x03, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x3B, 0x95, 0x51, 0xF6, 0x8C, 0x41, 0x31, 0xF4,
-0x03, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0xF2, 0x14, 0x6D,
-0xA0, 0x35, 0xA0, 0x35, 0x61, 0xF6, 0x80, 0x41, 0x00, 0xF1, 0x02, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x05, 0xF0, 0x16, 0x6D, 0xA0, 0x35,
-0xA0, 0x35, 0x61, 0xF6, 0x84, 0x41, 0x01, 0xF5, 0x07, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x41, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x37, 0x95, 0x41, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x38, 0x95,
-0x00, 0x1C, 0x2C, 0x1F, 0x03, 0x6C, 0x00, 0xF2, 0x00, 0x6A, 0x40, 0x32,
-0x40, 0x32, 0xA2, 0x67, 0x41, 0xF6, 0x8C, 0x41, 0xC5, 0xF0, 0x11, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x3C, 0xD2, 0x3C, 0x95, 0x61, 0xF6, 0x8C, 0x41,
-0xC5, 0xF0, 0x11, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x41, 0xF6,
-0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x37, 0x95, 0x41, 0xF6, 0x88, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x38, 0x95, 0x00, 0x1C, 0x2C, 0x1F, 0x03, 0x6C,
-0x01, 0xF4, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x31, 0x95, 0x01, 0xF4,
-0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x32, 0x95, 0x21, 0xF6, 0x88, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x6D, 0x34, 0x93, 0x1F, 0xF5, 0x1E, 0x2B,
-0x21, 0xF0, 0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x3A, 0x95, 0x21, 0xF0,
-0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x3A, 0x95, 0x13, 0x15, 0x00, 0x6A,
-0x6A, 0x15, 0x00, 0x6B, 0x56, 0x15, 0xFF, 0x6C, 0xFF, 0x74, 0xBF, 0xF5,
-0x09, 0x61, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34,
-0x41, 0xD4, 0x81, 0xF6, 0x14, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0xE0, 0xF3, 0x1F, 0x6B, 0x60, 0x31, 0x20, 0x31, 0x2C, 0xEA, 0x42, 0x32,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x63, 0xF3, 0x00, 0x4C,
-0x42, 0x32, 0x6C, 0xEA, 0x63, 0x9C, 0x00, 0xF4, 0x00, 0x6D, 0xAB, 0xED,
-0xAC, 0xEB, 0x4D, 0xEB, 0x63, 0xDC, 0x41, 0x94, 0xE0, 0xF3, 0x1F, 0x68,
-0x81, 0xF6, 0x1C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x2C, 0xEA,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x10, 0x6D, 0x63, 0xF3,
-0x00, 0x4C, 0x42, 0x32, 0xAB, 0xED, 0x63, 0x9C, 0x42, 0x32, 0xA0, 0x35,
-0x0C, 0xEA, 0xA0, 0x35, 0xE0, 0xF3, 0x1F, 0x4D, 0x40, 0x32, 0xAC, 0xEB,
-0x48, 0x32, 0x4D, 0xEB, 0x63, 0xDC, 0x41, 0x94, 0xA1, 0xF6, 0x04, 0x4C,
-0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x2C, 0xEA, 0x42, 0x32, 0x42, 0x32,
-0x0C, 0xEA, 0xE7, 0xF7, 0x10, 0x6C, 0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4,
-0x00, 0x30, 0x63, 0xF3, 0x00, 0x48, 0x8B, 0xEC, 0x63, 0x98, 0x80, 0x34,
-0x80, 0x34, 0xFF, 0x4C, 0x00, 0xF5, 0x40, 0x32, 0x8C, 0xEB, 0x4D, 0xEB,
-0x63, 0xD8, 0x41, 0x94, 0xA1, 0xF6, 0x0C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x2C, 0xEA, 0x64, 0x98, 0x42, 0x32, 0x00, 0xF4, 0x00, 0x68,
-0xE0, 0xF3, 0x1F, 0x6D, 0x0B, 0xE8, 0x42, 0x32, 0xAC, 0xEA, 0x0C, 0xEB,
-0x4D, 0xEB, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3,
-0x00, 0x4A, 0x64, 0xDA, 0x41, 0x94, 0xE0, 0xF3, 0x1F, 0x68, 0xA1, 0xF6,
-0x14, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x2C, 0xEA, 0x42, 0x32,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x10, 0x6D, 0x63, 0xF3,
-0x00, 0x4C, 0xE0, 0xF3, 0x1F, 0x6B, 0x42, 0x32, 0xAB, 0xED, 0x6C, 0xEA,
-0xA0, 0x35, 0x64, 0x9C, 0xA0, 0x35, 0xE0, 0xF3, 0x1F, 0x4D, 0x40, 0x32,
-0xAC, 0xEB, 0x48, 0x32, 0x4D, 0xEB, 0x64, 0xDC, 0x41, 0x94, 0xA1, 0xF6,
-0x1C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0xE7, 0xF7, 0x10, 0x6D, 0x63, 0xF3, 0x00, 0x4C,
-0x2C, 0xEA, 0xAB, 0xED, 0x64, 0x9C, 0x42, 0x32, 0xA0, 0x35, 0x42, 0x32,
-0xA0, 0x35, 0xFF, 0x4D, 0x0C, 0xEA, 0xAC, 0xEB, 0x00, 0xF5, 0x40, 0x32,
-0x4D, 0xEB, 0x64, 0xDC, 0x41, 0x94, 0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4,
-0x00, 0x30, 0x63, 0xF3, 0x00, 0x48, 0xC1, 0xF6, 0x04, 0x4C, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x2C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x4A, 0xC8,
-0x41, 0x94, 0xC1, 0xF6, 0x0C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0x4C, 0xE9, 0x22, 0x32, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33,
-0x42, 0x32, 0x63, 0xF3, 0x00, 0x4B, 0x4B, 0xC8, 0x44, 0x9B, 0x80, 0xF7,
-0x42, 0x32, 0x01, 0x72, 0x3F, 0xF5, 0x02, 0x60, 0xC9, 0xF7, 0x1B, 0x6A,
-0x4B, 0xEA, 0x40, 0x31, 0x20, 0x31, 0x81, 0xF4, 0x80, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x82, 0x67, 0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4,
-0x00, 0x30, 0x40, 0x6A, 0x4B, 0xEA, 0x63, 0xF3, 0x00, 0x48, 0x40, 0x32,
-0xC3, 0x98, 0x40, 0x32, 0x8C, 0xEA, 0xE0, 0xF3, 0x1F, 0x6B, 0x80, 0xF5,
-0x42, 0x35, 0xCC, 0xEB, 0x00, 0xF2, 0x00, 0x6A, 0x6C, 0xEA, 0x04, 0x22,
-0x00, 0xF4, 0x00, 0x6A, 0x4B, 0xEA, 0x4D, 0xEB, 0xB8, 0xEB, 0xE0, 0xF3,
-0x1F, 0x68, 0x12, 0xEA, 0x42, 0x33, 0x0C, 0xEB, 0xC2, 0x30, 0xE0, 0xF3,
-0x1F, 0x6A, 0x0A, 0x30, 0x4C, 0xE8, 0x00, 0xF2, 0x00, 0x6A, 0x0C, 0xEA,
-0x04, 0x22, 0x00, 0xF4, 0x00, 0x6A, 0x4B, 0xEA, 0x4D, 0xE8, 0xB8, 0xE8,
-0xE0, 0xF3, 0x1F, 0x6D, 0x12, 0xEA, 0x42, 0x30, 0x3F, 0x6A, 0x4B, 0xEA,
-0xAC, 0xE8, 0x40, 0x32, 0x3F, 0x6D, 0x42, 0xD5, 0x40, 0x32, 0x0C, 0xED,
-0x1F, 0xF4, 0x00, 0x4A, 0xA0, 0x35, 0x4C, 0xEC, 0xA0, 0x35, 0x8D, 0xED,
-0x81, 0xF4, 0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x6D, 0xED, 0x91, 0xF4,
-0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x02, 0xF0, 0x00, 0x6B,
-0x60, 0x33, 0x60, 0x33, 0xFF, 0x4B, 0xC0, 0xF3, 0x00, 0x6C, 0x6C, 0xEA,
-0x8C, 0xE8, 0x80, 0xF5, 0x00, 0x33, 0xA2, 0x67, 0x91, 0xF4, 0x84, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x6D, 0xED, 0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0xBD, 0xF7, 0x10, 0x4D, 0x82, 0x67, 0x40, 0x9D, 0x8C, 0xEA, 0x80, 0xF5,
-0x42, 0x35, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3,
-0x00, 0x4A, 0x04, 0x9A, 0xE0, 0xF3, 0x1F, 0x6A, 0x02, 0x33, 0x6A, 0x33,
-0x4C, 0xEB, 0x00, 0xF2, 0x00, 0x6A, 0x6C, 0xEA, 0x04, 0x22, 0x00, 0xF4,
-0x00, 0x6A, 0x4B, 0xEA, 0x4D, 0xEB, 0xB8, 0xEB, 0x00, 0xF5, 0x02, 0x30,
-0x12, 0xEA, 0x42, 0x33, 0xE0, 0xF3, 0x1F, 0x6A, 0x4C, 0xE8, 0x4C, 0xEB,
-0x00, 0xF2, 0x00, 0x6A, 0x0C, 0xEA, 0x04, 0x22, 0x00, 0xF4, 0x00, 0x6A,
-0x4B, 0xEA, 0x4D, 0xE8, 0xB8, 0xE8, 0xE0, 0xF3, 0x1F, 0x6D, 0x12, 0xEA,
-0x42, 0x30, 0xAC, 0xE8, 0x3F, 0x6A, 0x42, 0x95, 0x4B, 0xEA, 0x40, 0x32,
-0x0C, 0xED, 0x40, 0x32, 0x1F, 0xF4, 0x00, 0x4A, 0x42, 0xD5, 0xA0, 0x35,
-0x4C, 0xEC, 0xA0, 0x35, 0x8D, 0xED, 0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x6D, 0xED, 0x91, 0xF4, 0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xBD, 0xF7,
-0x14, 0x4B, 0xA0, 0x9B, 0xC0, 0xF3, 0x00, 0x6C, 0x8C, 0xE8, 0x4C, 0xED,
-0x80, 0xF5, 0x00, 0x32, 0x91, 0xF4, 0x8C, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x4D, 0xED, 0x58, 0x14, 0x0C, 0x91, 0xDF, 0xF3, 0x19, 0x10, 0x1E, 0x93,
-0x04, 0x04, 0x74, 0x32, 0x91, 0xE2, 0x3E, 0xD4, 0x91, 0xF6, 0x84, 0x40,
-0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF3, 0x1F, 0x6B, 0x60, 0x33,
-0x60, 0x33, 0x3E, 0x95, 0x6C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x3F, 0xD3,
-0x91, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x40, 0xDD, 0x3F, 0x93,
-0x3E, 0x94, 0x6C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x41, 0xDC, 0xA1, 0xF6,
-0x84, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x3F, 0x95, 0x3E, 0x93,
-0xA1, 0xF6, 0x8C, 0x40, 0xAC, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x00, 0x1C,
-0xFA, 0x5B, 0x42, 0xDB, 0x3F, 0x94, 0x3E, 0x95, 0x8C, 0xEA, 0x42, 0x32,
-0x42, 0x32, 0xB1, 0xF6, 0x84, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x43, 0xDD,
-0x3F, 0x93, 0x3E, 0x94, 0x6C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x44, 0xDC,
-0xB1, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x3F, 0x95,
-0x3E, 0x93, 0xC1, 0xF6, 0x84, 0x40, 0xAC, 0xEA, 0x42, 0x32, 0x42, 0x32,
-0x00, 0x1C, 0xFA, 0x5B, 0x45, 0xDB, 0x3F, 0x94, 0x3E, 0x95, 0x8C, 0xEA,
-0x42, 0x32, 0x42, 0x32, 0xC1, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B,
-0x46, 0xDD, 0x3F, 0x93, 0x3E, 0x94, 0x4C, 0xEB, 0x62, 0x32, 0x42, 0x32,
-0x47, 0xDC, 0x7F, 0xF3, 0x0E, 0x10, 0x00, 0x00, 0xFB, 0x63, 0x07, 0xD1,
-0x0C, 0xF0, 0x00, 0x6A, 0x10, 0xF0, 0x02, 0x69, 0x00, 0xF4, 0x20, 0x31,
-0x63, 0xF3, 0x00, 0x49, 0x08, 0x62, 0x0A, 0xD4, 0x06, 0xD0, 0x4B, 0xEA,
-0x62, 0x99, 0x40, 0x32, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB, 0xC9, 0xF7,
-0x1B, 0x6C, 0x04, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0x8B, 0xEC, 0x40, 0x32,
-0x80, 0x34, 0x4D, 0xEB, 0x80, 0x34, 0x62, 0xD9, 0x04, 0xD4, 0x81, 0xF6,
-0x14, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF3, 0x1F, 0x6B,
-0x60, 0x30, 0x00, 0x30, 0x0C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x6C, 0xEA,
-0x63, 0x99, 0x00, 0xF4, 0x00, 0x6C, 0x8B, 0xEC, 0x8C, 0xEB, 0x4D, 0xEB,
-0x63, 0xD9, 0x04, 0x94, 0x81, 0xF6, 0x1C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x0C, 0xEA, 0x42, 0x32, 0x10, 0x6C, 0xE0, 0xF3, 0x1F, 0x6B,
-0x42, 0x32, 0x8B, 0xEC, 0x6C, 0xEA, 0x80, 0x34, 0x63, 0x99, 0x80, 0x34,
-0xE0, 0xF3, 0x1F, 0x4C, 0x40, 0x32, 0x48, 0x32, 0x8C, 0xEB, 0x4D, 0xEB,
-0x63, 0xD9, 0x04, 0x94, 0xA1, 0xF6, 0x04, 0x4C, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x0C, 0xEA, 0x42, 0x32, 0xE7, 0xF7, 0x10, 0x6C, 0xE0, 0xF3,
-0x1F, 0x6B, 0x42, 0x32, 0x8B, 0xEC, 0x6C, 0xEA, 0x80, 0x34, 0x63, 0x99,
-0x80, 0x34, 0xFF, 0x4C, 0x00, 0xF5, 0x40, 0x32, 0x8C, 0xEB, 0x4D, 0xEB,
-0x63, 0xD9, 0x04, 0x94, 0xA1, 0xF6, 0x0C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x0C, 0xEA, 0x42, 0x32, 0xE0, 0xF3, 0x1F, 0x6B, 0x42, 0x32,
-0x6C, 0xEA, 0x64, 0x99, 0x00, 0xF4, 0x00, 0x6C, 0x8B, 0xEC, 0x8C, 0xEB,
-0x4D, 0xEB, 0x64, 0xD9, 0x04, 0x94, 0xA1, 0xF6, 0x14, 0x4C, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x0C, 0xEA, 0x42, 0x32, 0x10, 0x6C, 0xE0, 0xF3,
-0x1F, 0x6B, 0x42, 0x32, 0x8B, 0xEC, 0x6C, 0xEA, 0x80, 0x34, 0x64, 0x99,
-0x80, 0x34, 0xE0, 0xF3, 0x1F, 0x4C, 0x40, 0x32, 0x48, 0x32, 0x8C, 0xEB,
-0x4D, 0xEB, 0x64, 0xD9, 0x04, 0x94, 0xA1, 0xF6, 0x1C, 0x4C, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x0C, 0xEA, 0x42, 0x32, 0xE7, 0xF7, 0x10, 0x6C,
-0xE0, 0xF3, 0x1F, 0x6B, 0x42, 0x32, 0x8B, 0xEC, 0x6C, 0xEA, 0x80, 0x34,
-0x64, 0x99, 0x80, 0x34, 0xFF, 0x4C, 0x00, 0xF5, 0x40, 0x32, 0x8C, 0xEB,
-0x4D, 0xEB, 0x64, 0xD9, 0x04, 0x94, 0xC1, 0xF6, 0x04, 0x4C, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x0C, 0xEA, 0x42, 0x32, 0x42, 0x32, 0x4A, 0xC9,
-0x04, 0x94, 0xC1, 0xF6, 0x0C, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0x4C, 0xE8, 0xFF, 0x6A, 0x01, 0x4A, 0x40, 0x32, 0x40, 0x32, 0x0A, 0x93,
-0x80, 0x4A, 0x02, 0x30, 0x80, 0x4A, 0x02, 0x30, 0x6C, 0xEA, 0x0B, 0xC9,
-0x14, 0x22, 0x1F, 0xF7, 0x00, 0x6A, 0x0A, 0x94, 0x4C, 0xEB, 0x62, 0x33,
-0xC0, 0xF2, 0x63, 0xC1, 0x82, 0x33, 0x4C, 0xEB, 0x62, 0x33, 0xC0, 0xF2,
-0x67, 0xC1, 0x00, 0x18, 0x0A, 0x5F, 0x00, 0x65, 0x08, 0x97, 0x07, 0x91,
-0x06, 0x90, 0x00, 0xEF, 0x05, 0x63, 0x12, 0x6A, 0xC0, 0xF2, 0x43, 0xC1,
-0xC0, 0xF2, 0x47, 0xC1, 0x00, 0x18, 0x0A, 0x5F, 0x00, 0x65, 0x08, 0x97,
-0x07, 0x91, 0x06, 0x90, 0x00, 0xEF, 0x05, 0x63, 0xC9, 0xF7, 0x1B, 0x6A,
-0xFB, 0x63, 0x4B, 0xEA, 0x06, 0xD0, 0x40, 0x30, 0x07, 0xD1, 0x08, 0x62,
-0x00, 0x30, 0x40, 0xF0, 0x4C, 0xA0, 0x03, 0x69, 0x4C, 0xE9, 0x10, 0xF0,
-0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x62, 0x67, 0x04, 0xD2, 0x63, 0xF3,
-0x00, 0x4B, 0xC3, 0xF3, 0x41, 0xA3, 0x2E, 0xEA, 0x1A, 0x22, 0x05, 0x29,
-0xE0, 0xF2, 0x66, 0xA3, 0xFF, 0x6A, 0x4C, 0xEB, 0x1A, 0x23, 0x04, 0x92,
-0xC9, 0xF7, 0x17, 0x6C, 0x8B, 0xEC, 0x63, 0xF3, 0x00, 0x4A, 0x04, 0xD2,
-0xC3, 0xF3, 0x21, 0xC2, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32,
-0x40, 0x32, 0x76, 0x9A, 0x80, 0x34, 0x80, 0x34, 0x60, 0xDC, 0x57, 0x9A,
-0x41, 0xDC, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90, 0x00, 0x6A, 0x00, 0xEF,
-0x05, 0x63, 0x51, 0xF4, 0x80, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x1C, 0x6D,
-0x51, 0xF4, 0x88, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x1C, 0x6D, 0xDB, 0x17,
-0xF9, 0x63, 0x0A, 0xD0, 0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8, 0x00, 0x30,
-0x00, 0x30, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x0B, 0xD1,
-0xA1, 0xF5, 0x82, 0x40, 0x22, 0x67, 0x63, 0xF3, 0x00, 0x49, 0x0C, 0x62,
-0x00, 0x1C, 0xFD, 0x5B, 0x06, 0xD2, 0xC0, 0xF2, 0x58, 0xC9, 0xA1, 0xF5,
-0x84, 0x40, 0x00, 0x1C, 0xFD, 0x5B, 0x00, 0x65, 0xC0, 0xF2, 0x5A, 0xC9,
-0xA1, 0xF5, 0x86, 0x40, 0x00, 0x1C, 0xFD, 0x5B, 0x00, 0x65, 0xC0, 0xF2,
-0x5C, 0xC9, 0xA1, 0xF5, 0x88, 0x40, 0x00, 0x1C, 0xFD, 0x5B, 0x00, 0x65,
-0x82, 0x67, 0xC0, 0xF2, 0x7A, 0xA9, 0xC0, 0xF2, 0x5E, 0xC9, 0xC0, 0xF2,
-0x58, 0xA9, 0x69, 0xE2, 0xC0, 0xF2, 0x7C, 0xA9, 0x69, 0xE2, 0x51, 0xE4,
-0x04, 0xD4, 0x21, 0xF2, 0x8D, 0x40, 0x00, 0x1C, 0x00, 0x5C, 0x00, 0x65,
-0x00, 0xF6, 0x40, 0x35, 0x00, 0xF6, 0xA3, 0x35, 0x40, 0x6A, 0xFF, 0x6B,
-0x4D, 0xED, 0x6C, 0xED, 0x21, 0xF2, 0x8D, 0x40, 0x00, 0x1C, 0xF0, 0x5B,
-0x05, 0xD3, 0x51, 0xF2, 0x8B, 0x40, 0x00, 0x1C, 0x00, 0x5C, 0x00, 0x65,
-0x40, 0x32, 0x51, 0xF2, 0x8C, 0x40, 0xE0, 0xF2, 0x44, 0xC9, 0x00, 0x1C,
-0x00, 0x5C, 0x00, 0x65, 0xE0, 0xF2, 0x64, 0xA9, 0x61, 0xF4, 0x84, 0x40,
-0x75, 0xE2, 0x04, 0x93, 0xFF, 0xF7, 0x1F, 0x6A, 0xE0, 0xF2, 0xA4, 0xC9,
-0x4C, 0xED, 0x69, 0xE5, 0xE0, 0xF2, 0x40, 0xD9, 0xFF, 0xF7, 0x1F, 0x6A,
-0x00, 0x1C, 0xE6, 0x5B, 0x4C, 0xED, 0x43, 0xA9, 0xFF, 0xF7, 0x1F, 0x6B,
-0x6C, 0xEA, 0x10, 0x52, 0x05, 0x60, 0xE0, 0xF2, 0x40, 0x99, 0x1F, 0x5A,
-0xA0, 0xF0, 0x1E, 0x61, 0x00, 0x6A, 0xC0, 0xF2, 0x54, 0xC1, 0xC0, 0xF2,
-0x55, 0xA1, 0x05, 0x93, 0x01, 0x4A, 0x4C, 0xEB, 0x03, 0x53, 0xA0, 0xF0,
-0x0B, 0x60, 0xC0, 0xF2, 0x55, 0xC1, 0x06, 0x94, 0x00, 0x6A, 0x11, 0x6B,
-0x63, 0xF3, 0x00, 0x4C, 0x43, 0xCC, 0xE0, 0xF2, 0x44, 0xCC, 0x40, 0x9C,
-0x6C, 0xEA, 0x01, 0x72, 0x80, 0xF0, 0x13, 0x61, 0xE0, 0xF2, 0x44, 0x9C,
-0x03, 0x6B, 0x00, 0xF7, 0x42, 0x32, 0x6C, 0xEA, 0x80, 0xF0, 0x0B, 0x2A,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF0,
-0x4C, 0xA2, 0x4C, 0xEB, 0x01, 0x73, 0xA0, 0xF0, 0x04, 0x60, 0x06, 0x94,
-0x63, 0xF3, 0x00, 0x4C, 0xE0, 0xF2, 0x46, 0xA4, 0xA0, 0xF0, 0x0B, 0x2A,
-0x40, 0x9C, 0x01, 0x6B, 0x56, 0x32, 0x6C, 0xEA, 0xA0, 0xF0, 0x05, 0x22,
-0x3E, 0x6A, 0xC0, 0xF2, 0x50, 0xC4, 0x1C, 0x6A, 0xC0, 0xF2, 0x51, 0xC4,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x40, 0xF0,
-0x6C, 0xA2, 0xFF, 0x6A, 0x6C, 0xEA, 0x03, 0x6B, 0x6C, 0xEA, 0x61, 0x22,
-0x66, 0xF7, 0x4C, 0x9C, 0xFF, 0xF7, 0x1F, 0x72, 0x5C, 0x60, 0xE0, 0xF2,
-0x40, 0x9C, 0xE0, 0xF3, 0x09, 0x5A, 0x00, 0xF1, 0x03, 0x61, 0xC0, 0xF2,
-0x72, 0xA4, 0x00, 0xF6, 0x60, 0x32, 0x00, 0xF6, 0x43, 0x32, 0xFE, 0x4A,
-0xFF, 0xF7, 0x1C, 0x52, 0x04, 0x6A, 0x4B, 0xEA, 0x01, 0x61, 0x4E, 0x43,
-0xC0, 0xF2, 0x52, 0xC4, 0x06, 0x96, 0x7F, 0x6B, 0x63, 0xF3, 0x00, 0x4E,
-0x66, 0xF7, 0x4C, 0x9E, 0xC0, 0xF2, 0x8E, 0xA6, 0x52, 0x32, 0x6C, 0xEA,
-0xA7, 0x42, 0xC0, 0xF2, 0x52, 0xA6, 0x03, 0x4D, 0xFF, 0x6B, 0x4B, 0xE5,
-0x00, 0xF6, 0x40, 0x35, 0x43, 0x67, 0x00, 0xF6, 0xA3, 0x35, 0x8C, 0xEA,
-0xA2, 0xEA, 0xE0, 0xF0, 0x0C, 0x60, 0x00, 0xF6, 0x80, 0x35, 0x00, 0xF6,
-0xA3, 0x35, 0x06, 0x92, 0x63, 0xF3, 0x00, 0x4A, 0x06, 0xD2, 0xE0, 0xF2,
-0x40, 0x9A, 0x04, 0xF7, 0x11, 0x5A, 0xC0, 0xF0, 0x01, 0x61, 0x32, 0x55,
-0xA0, 0xF0, 0x1E, 0x60, 0x32, 0x6D, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA,
-0x40, 0x32, 0x40, 0x32, 0x21, 0xF4, 0x10, 0x4A, 0x44, 0x6B, 0xC9, 0xF7,
-0x1B, 0x68, 0x0B, 0xE8, 0x60, 0xC2, 0x00, 0x30, 0xFF, 0x6A, 0xAC, 0xEA,
-0x00, 0x30, 0xA2, 0x67, 0x51, 0xF4, 0x80, 0x40, 0x00, 0x1C, 0xF0, 0x5B,
-0x08, 0xD2, 0x08, 0x92, 0x51, 0xF4, 0x88, 0x40, 0x00, 0x1C, 0xF0, 0x5B,
-0xA2, 0x67, 0x00, 0x18, 0x08, 0x61, 0x00, 0x65, 0x0C, 0x97, 0x0B, 0x91,
-0x0A, 0x90, 0x00, 0x6A, 0x00, 0xEF, 0x07, 0x63, 0x03, 0x6A, 0xC0, 0xF2,
-0x55, 0xC1, 0x40, 0x99, 0x08, 0x6B, 0x6D, 0xEA, 0x40, 0xD9, 0x4F, 0x17,
-0x00, 0x6A, 0xC0, 0xF2, 0x55, 0xC1, 0xC0, 0xF2, 0x54, 0xA1, 0x05, 0x93,
-0x01, 0x4A, 0x4C, 0xEB, 0x03, 0x53, 0x14, 0x61, 0x03, 0x6A, 0xC0, 0xF2,
-0x54, 0xC1, 0x40, 0x99, 0x09, 0x6B, 0x6B, 0xEB, 0x6C, 0xEA, 0x40, 0xD9,
-0x3C, 0x17, 0xE0, 0xF2, 0x66, 0xA4, 0xFF, 0x6A, 0x4C, 0xEB, 0x5F, 0xF7,
-0x16, 0x2B, 0x01, 0x6A, 0x4B, 0xEA, 0xE0, 0xF2, 0x46, 0xC4, 0x51, 0x17,
-0xC0, 0xF2, 0x54, 0xC1, 0x2E, 0x17, 0x06, 0x90, 0xFF, 0x6D, 0x63, 0xF3,
-0x00, 0x48, 0xE0, 0xF2, 0x46, 0xA0, 0xAA, 0xEA, 0xC6, 0x61, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x41, 0xF4, 0x10, 0x4C,
-0x00, 0x1C, 0x00, 0x5C, 0x09, 0xD5, 0x09, 0x95, 0x00, 0xF6, 0x40, 0x31,
-0x00, 0xF6, 0x23, 0x31, 0x7F, 0x6A, 0xAC, 0xE9, 0x4C, 0xE9, 0xE0, 0xF2,
-0x60, 0x98, 0xC0, 0xF2, 0x48, 0xA8, 0xFF, 0xF7, 0x1F, 0x6C, 0x43, 0xEB,
-0x38, 0x61, 0xC0, 0xF2, 0x4A, 0xA8, 0x8C, 0xEA, 0x43, 0xEB, 0x07, 0x61,
-0xC0, 0xF2, 0x4C, 0xA8, 0x8C, 0xEA, 0x43, 0xEB, 0x69, 0x60, 0x01, 0x49,
-0xAC, 0xE9, 0x06, 0x93, 0x63, 0xF3, 0x00, 0x4B, 0xC0, 0xF2, 0x50, 0xA3,
-0x23, 0xEA, 0x32, 0x60, 0x22, 0x67, 0x06, 0x93, 0x63, 0xF3, 0x00, 0x4B,
-0x06, 0xD3, 0xE0, 0xF2, 0x40, 0x9B, 0x04, 0xF7, 0x11, 0x5A, 0x1D, 0x61,
-0x32, 0x69, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0x21, 0xF4, 0x10, 0x4A, 0x44, 0x6B, 0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8,
-0x00, 0x30, 0x00, 0x30, 0x51, 0xF4, 0x80, 0x40, 0xB1, 0x67, 0x60, 0xC2,
-0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0x51, 0xF4, 0x88, 0x40, 0x00, 0x1C,
-0xF0, 0x5B, 0xB1, 0x67, 0x74, 0x17, 0xFF, 0x49, 0xD1, 0x17, 0x3A, 0x59,
-0xE2, 0x61, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0x21, 0xF4, 0x10, 0x4A, 0x48, 0x6B, 0xE1, 0x17, 0xC0, 0xF2, 0x71, 0xA3,
-0xFF, 0x6A, 0x4C, 0xEB, 0x63, 0xE9, 0xC9, 0x60, 0x23, 0x67, 0xC7, 0x17,
-0x3A, 0x55, 0x5F, 0xF7, 0x00, 0x61, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA,
-0x40, 0x32, 0x40, 0x32, 0x21, 0xF4, 0x10, 0x4A, 0x48, 0x6B, 0x3F, 0x17,
-0x80, 0xF1, 0x10, 0x5A, 0x1F, 0xF7, 0x08, 0x60, 0xC0, 0xF2, 0x72, 0xA4,
-0x00, 0xF6, 0x60, 0x32, 0x00, 0xF6, 0x43, 0x32, 0x02, 0x4A, 0x0D, 0x52,
-0x0C, 0x6A, 0xFF, 0xF6, 0x1B, 0x60, 0x42, 0x43, 0xF9, 0x16, 0xC0, 0xF2,
-0x4F, 0xA6, 0x4C, 0xEB, 0x62, 0xED, 0x1F, 0xF7, 0x12, 0x60, 0x00, 0xF6,
-0x40, 0x35, 0x0D, 0x17, 0x02, 0x49, 0x96, 0x17, 0xFB, 0x63, 0x06, 0xD0,
-0x02, 0xF0, 0x00, 0x68, 0x00, 0x30, 0xAF, 0x40, 0xFF, 0xF0, 0x10, 0x6E,
-0x15, 0x6C, 0x08, 0x62, 0x00, 0x1C, 0x83, 0x45, 0x07, 0xD1, 0x00, 0x1C,
-0x5B, 0x1F, 0x64, 0x6C, 0x1A, 0x6C, 0x46, 0xF0, 0x16, 0x6E, 0x00, 0x1C,
-0x83, 0x45, 0xAF, 0x40, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x10, 0xF0,
-0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x04, 0xD2, 0x63, 0xF3, 0x40, 0x9A,
-0x01, 0x6B, 0x4E, 0x32, 0x6C, 0xEA, 0x0A, 0x22, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3, 0x47, 0xA3,
-0x01, 0x72, 0x1C, 0x61, 0x04, 0x92, 0x63, 0xF3, 0x20, 0x9A, 0x01, 0x6A,
-0x2E, 0x31, 0x4C, 0xE9, 0x09, 0x29, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3, 0x47, 0xA3, 0x5A, 0x2A,
-0x04, 0x93, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90, 0x63, 0xF3, 0x00, 0x4B,
-0x04, 0xD3, 0x04, 0x6A, 0x00, 0xF3, 0x44, 0xC3, 0x00, 0xEF, 0x05, 0x63,
-0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x31, 0x24, 0xF2, 0x02, 0x68,
-0x20, 0x31, 0x00, 0x30, 0x01, 0xF6, 0x88, 0x41, 0x24, 0xF2, 0x02, 0x6D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x30, 0x01, 0xF6, 0x80, 0x41, 0x24, 0xF2,
-0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x01, 0xF6, 0x84, 0x41,
-0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x11, 0xF6,
-0x80, 0x41, 0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x11, 0xF6, 0x84, 0x41, 0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x11, 0xF6, 0x88, 0x41, 0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x11, 0xF6, 0x8C, 0x41, 0x24, 0xF2, 0xA2, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x01, 0x6B, 0x63, 0xF3, 0x00, 0x4A, 0x00, 0xF3, 0x67, 0xC2,
-0x04, 0x93, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90, 0x63, 0xF3, 0x00, 0x4B,
-0x04, 0xD3, 0x04, 0x6A, 0x00, 0xF3, 0x44, 0xC3, 0x00, 0xEF, 0x05, 0x63,
-0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8, 0x00, 0xF3, 0xB4, 0x9B, 0x00, 0x30,
-0x00, 0x30, 0x01, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A,
-0x00, 0xF3, 0xB4, 0x9A, 0x01, 0xF6, 0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x00, 0x4B, 0x00, 0xF3, 0xB8, 0x9B, 0x01, 0xF6, 0x88, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x63, 0xF3, 0x00, 0x4A, 0x00, 0xF3, 0xB4, 0x9A, 0x11, 0xF6, 0x80, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3, 0xB4, 0x9B, 0x11, 0xF6,
-0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A,
-0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0x00, 0xF3, 0xB4, 0x9A,
-0x11, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3,
-0xB4, 0x9B, 0x11, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A,
-0x00, 0xF3, 0x27, 0xC2, 0x04, 0x93, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90,
-0x63, 0xF3, 0x00, 0x4B, 0x04, 0xD3, 0x04, 0x6A, 0x00, 0xF3, 0x44, 0xC3,
-0x00, 0xEF, 0x05, 0x63, 0xFB, 0x63, 0x06, 0xD0, 0x02, 0xF0, 0x00, 0x68,
-0x00, 0x30, 0xAF, 0x40, 0xFF, 0xF0, 0x10, 0x6E, 0x15, 0x6C, 0x08, 0x62,
-0x00, 0x1C, 0x83, 0x45, 0x07, 0xD1, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C,
-0x1A, 0x6C, 0x46, 0xF0, 0x16, 0x6E, 0x00, 0x1C, 0x83, 0x45, 0xAF, 0x40,
-0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x05, 0xD2, 0x63, 0xF3, 0x40, 0x9A, 0x01, 0x6B, 0x4E, 0x32,
-0x6C, 0xEA, 0x0A, 0x22, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33,
-0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3, 0x47, 0xA3, 0x01, 0x72, 0x1D, 0x61,
-0x05, 0x92, 0x63, 0xF3, 0x20, 0x9A, 0x01, 0x6A, 0x2E, 0x31, 0x4C, 0xE9,
-0x09, 0x29, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x00, 0x4B, 0x00, 0xF3, 0x47, 0xA3, 0x5C, 0x2A, 0x05, 0x92, 0x08, 0x97,
-0x07, 0x91, 0x63, 0xF3, 0x00, 0x4A, 0x05, 0xD2, 0x05, 0x93, 0x06, 0x90,
-0x01, 0x6A, 0x00, 0xF3, 0x44, 0xC3, 0x00, 0xEF, 0x05, 0x63, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x31, 0x24, 0xF2, 0x02, 0x68, 0x20, 0x31,
-0x00, 0x30, 0x01, 0xF6, 0x88, 0x41, 0x24, 0xF2, 0x02, 0x6D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x30, 0x01, 0xF6, 0x80, 0x41, 0x24, 0xF2, 0xA2, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x01, 0xF6, 0x84, 0x41, 0x24, 0xF2,
-0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x11, 0xF6, 0x80, 0x41,
-0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x11, 0xF6,
-0x84, 0x41, 0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x11, 0xF6, 0x88, 0x41, 0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x11, 0xF6, 0x8C, 0x41, 0x24, 0xF2, 0xA2, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x01, 0x6B, 0x63, 0xF3, 0x00, 0x4A, 0x00, 0xF3, 0x67, 0xC2, 0x05, 0x92,
-0x08, 0x97, 0x07, 0x91, 0x63, 0xF3, 0x00, 0x4A, 0x05, 0xD2, 0x05, 0x93,
-0x06, 0x90, 0x01, 0x6A, 0x00, 0xF3, 0x44, 0xC3, 0x00, 0xEF, 0x05, 0x63,
-0xC9, 0xF7, 0x1B, 0x68, 0x02, 0xF0, 0x10, 0x6A, 0x0B, 0xE8, 0x40, 0x32,
-0x40, 0x32, 0x00, 0x30, 0xA2, 0x67, 0x00, 0x30, 0x01, 0xF6, 0x80, 0x40,
-0x02, 0xF0, 0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x04, 0xD2, 0x04, 0x95,
-0x01, 0xF6, 0x84, 0x40, 0x02, 0xF0, 0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x01, 0xF6, 0x88, 0x40, 0x02, 0xF0, 0x10, 0x6D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x04, 0x95, 0x11, 0xF6, 0x80, 0x40, 0x02, 0xF0,
-0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x04, 0x95, 0x11, 0xF6,
-0x84, 0x40, 0x02, 0xF0, 0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x04, 0x95, 0x11, 0xF6, 0x88, 0x40, 0x02, 0xF0, 0x10, 0x4D, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x04, 0x95, 0x11, 0xF6, 0x8C, 0x40, 0x02, 0xF0,
-0x10, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x00, 0xF3, 0x27, 0xC3,
-0x05, 0x92, 0x08, 0x97, 0x07, 0x91, 0x63, 0xF3, 0x00, 0x4A, 0x05, 0xD2,
-0x05, 0x93, 0x06, 0x90, 0x01, 0x6A, 0x00, 0xF3, 0x44, 0xC3, 0x00, 0xEF,
-0x05, 0x63, 0x00, 0x00, 0xFC, 0x63, 0x05, 0xD1, 0x10, 0xF0, 0x02, 0x69,
-0x00, 0xF4, 0x20, 0x31, 0x06, 0x62, 0x04, 0xD0, 0x63, 0xF3, 0x00, 0x49,
-0x00, 0xF3, 0xCC, 0x99, 0x02, 0xF0, 0x00, 0x68, 0x00, 0x30, 0xAF, 0x40,
-0x00, 0x1C, 0x83, 0x45, 0x15, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C,
-0x00, 0xF3, 0xD0, 0x99, 0x1A, 0x6C, 0x00, 0x1C, 0x83, 0x45, 0xAF, 0x40,
-0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0xF3, 0x44, 0xA1, 0x0E, 0x2A,
-0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x01, 0xF6,
-0x00, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0x6C, 0x99,
-0x6E, 0xEA, 0x36, 0x22, 0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8, 0xE0, 0xF2,
-0xA8, 0x99, 0x00, 0x30, 0x00, 0x30, 0x01, 0xF6, 0x88, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0xAC, 0x99, 0x01, 0xF6, 0x80, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0xB0, 0x99, 0x01, 0xF6,
-0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0xB4, 0x99,
-0x11, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2,
-0xB8, 0x99, 0x11, 0xF6, 0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0xE0, 0xF2, 0xBC, 0x99, 0x11, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x00, 0xF3, 0xA0, 0x99, 0x11, 0xF6, 0x8C, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x06, 0x97, 0x05, 0x91, 0x04, 0x90, 0x63, 0xF3, 0x00, 0x4A, 0x00, 0x6B,
-0x00, 0xF3, 0x64, 0xC2, 0x02, 0x6B, 0x00, 0xF3, 0x67, 0xC2, 0x00, 0xEF,
-0x04, 0x63, 0x00, 0x00, 0xFC, 0x63, 0x05, 0xD1, 0x10, 0xF0, 0x02, 0x69,
-0x00, 0xF4, 0x20, 0x31, 0x06, 0x62, 0x04, 0xD0, 0x63, 0xF3, 0x00, 0x49,
-0x00, 0xF3, 0xCC, 0x99, 0x02, 0xF0, 0x00, 0x68, 0x00, 0x30, 0xAF, 0x40,
-0x00, 0x1C, 0x83, 0x45, 0x15, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C,
-0x00, 0xF3, 0xD0, 0x99, 0x1A, 0x6C, 0x00, 0x1C, 0x83, 0x45, 0xAF, 0x40,
-0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0xF3, 0x44, 0xA1, 0x03, 0x72,
-0x5B, 0x60, 0xE0, 0xF2, 0xAC, 0x99, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA,
-0x40, 0x30, 0x00, 0x30, 0x01, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xE0, 0xF2, 0xB0, 0x99, 0x01, 0xF6, 0x84, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0xB4, 0x99, 0x11, 0xF6, 0x80, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0xB8, 0x99, 0x11, 0xF6,
-0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0xBC, 0x99,
-0x11, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0xF3,
-0xA0, 0x99, 0x11, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x00, 0xF3, 0x48, 0x99, 0xE0, 0xF2, 0x68, 0x99, 0x55, 0xE3, 0x1F, 0xF7,
-0x00, 0x6A, 0xAC, 0xEA, 0x07, 0xF7, 0x01, 0x5A, 0x16, 0x60, 0x01, 0xF6,
-0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A,
-0x00, 0xF4, 0x40, 0x32, 0x06, 0x97, 0x05, 0x91, 0x04, 0x90, 0x63, 0xF3,
-0x00, 0x4A, 0x03, 0x6B, 0x00, 0xF3, 0x64, 0xC2, 0x02, 0x6B, 0x00, 0xF3,
-0x67, 0xC2, 0x00, 0xEF, 0x04, 0x63, 0xFF, 0x6A, 0x01, 0x4A, 0x4B, 0xEA,
-0x40, 0x32, 0xE0, 0xF0, 0x1F, 0x4A, 0x4C, 0xED, 0x07, 0xF7, 0x00, 0x6A,
-0x4D, 0xED, 0xDF, 0x17, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34,
-0x80, 0x34, 0x01, 0xF6, 0x00, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0xE0, 0xF2, 0xAC, 0x99, 0xAA, 0xEA, 0x99, 0x61, 0x10, 0xF0, 0x02, 0x6A,
-0x00, 0xF4, 0x40, 0x32, 0x06, 0x97, 0x05, 0x91, 0x04, 0x90, 0x63, 0xF3,
-0x00, 0x4A, 0x03, 0x6B, 0x00, 0xF3, 0x64, 0xC2, 0x02, 0x6B, 0x00, 0xF3,
-0x67, 0xC2, 0x00, 0xEF, 0x04, 0x63, 0x00, 0x00, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x40, 0x9B, 0x10, 0x6B, 0xFB, 0x63,
-0x6D, 0xEA, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x40, 0xDB, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x07, 0xD1, 0x40, 0x31,
-0x20, 0x31, 0x51, 0xF4, 0x80, 0x41, 0x08, 0x62, 0x00, 0x1C, 0x00, 0x5C,
-0x06, 0xD0, 0x00, 0xF6, 0x40, 0x32, 0x00, 0xF6, 0x43, 0x32, 0x51, 0xF4,
-0x80, 0x41, 0x1A, 0x6D, 0x00, 0x1C, 0xF0, 0x5B, 0x04, 0xD2, 0xF1, 0xF0,
-0x88, 0x41, 0x00, 0x1C, 0x00, 0x5C, 0x00, 0x65, 0x04, 0x93, 0x00, 0xF6,
-0x40, 0x32, 0x00, 0xF6, 0x43, 0x32, 0x49, 0xE3, 0x08, 0x42, 0x9A, 0x48,
-0xBF, 0xF7, 0x1B, 0x50, 0x09, 0x61, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x43, 0xAB, 0x01, 0x4A, 0x43, 0xCB,
-0x04, 0x95, 0xFF, 0x6A, 0x51, 0xF4, 0x80, 0x41, 0x00, 0x1C, 0xF0, 0x5B,
-0x4C, 0xED, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x40, 0x9B, 0x11, 0x6B, 0x6B, 0xEB, 0x6C, 0xEA, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x40, 0xDB, 0x0B, 0xED, 0xFF, 0x6A,
-0x91, 0xF4, 0x82, 0x41, 0x00, 0x1C, 0xF0, 0x5B, 0x4C, 0xED, 0x08, 0x97,
-0x07, 0x91, 0x06, 0x90, 0x00, 0x6A, 0x00, 0xEF, 0x05, 0x63, 0x00, 0x00,
-0xF9, 0x63, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x00, 0x4B, 0x0C, 0x62, 0x0B, 0xD1, 0x0A, 0xD0, 0x66, 0xF7, 0x4C, 0x9B,
-0x52, 0x32, 0x05, 0xD2, 0x05, 0x94, 0x7F, 0x6A, 0x4C, 0xEC, 0x05, 0xD4,
-0x00, 0xF3, 0x44, 0xA3, 0x06, 0xD2, 0x40, 0x9B, 0x84, 0x6B, 0x6C, 0xEA,
-0x80, 0x72, 0x2A, 0x61, 0x06, 0x93, 0x01, 0x73, 0x02, 0x60, 0x04, 0x73,
-0x1B, 0x61, 0x02, 0xF0, 0x00, 0x68, 0x00, 0xF2, 0x00, 0x6E, 0x00, 0x30,
-0xC0, 0x36, 0xAF, 0x40, 0xF3, 0xF0, 0x14, 0x4E, 0x00, 0x1C, 0x83, 0x45,
-0x15, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0xFF, 0x6E, 0x01, 0x4E,
-0xC0, 0x36, 0x1A, 0x6C, 0x46, 0xF0, 0x16, 0x4E, 0x00, 0x1C, 0x83, 0x45,
-0xAF, 0x40, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x01, 0x6A, 0x4B, 0xEA,
-0x00, 0xF3, 0x44, 0xC3, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x30,
-0x00, 0x30, 0x40, 0xF0, 0x6C, 0xA0, 0x03, 0x6A, 0x6C, 0xEA, 0x0A, 0x22,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x63, 0xF3, 0x40, 0x9C,
-0x01, 0x6B, 0x5E, 0x32, 0x6C, 0xEA, 0x7C, 0x22, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x63, 0xF3, 0x00, 0x4C, 0x00, 0xF3, 0x44, 0x9C,
-0xFF, 0xF7, 0x1F, 0x6B, 0x42, 0x32, 0x6C, 0xEA, 0x16, 0x2A, 0xC9, 0xF7,
-0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x80, 0xF1, 0x04, 0x4A,
-0x40, 0x9A, 0x0D, 0x72, 0x58, 0x61, 0x46, 0x6A, 0x00, 0xF3, 0x5C, 0xC4,
-0x41, 0x6A, 0x00, 0xF3, 0x5D, 0xC4, 0x40, 0x6A, 0x00, 0xF3, 0x5E, 0xC4,
-0x3B, 0x6A, 0x00, 0xF3, 0x5F, 0xC4, 0x10, 0xF0, 0x02, 0x69, 0x00, 0xF4,
-0x20, 0x31, 0x63, 0xF3, 0x00, 0x49, 0xE4, 0xF4, 0xB8, 0x99, 0xC9, 0xF7,
-0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x30, 0xFF, 0x6E, 0xB2, 0x35, 0x00, 0x30,
-0xCC, 0xED, 0x61, 0xF4, 0x80, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x08, 0xD6,
-0x60, 0x99, 0x84, 0x6A, 0x08, 0x96, 0x6C, 0xEA, 0x84, 0x72, 0x2B, 0x61,
-0xE4, 0xF4, 0x58, 0x99, 0xFF, 0xF7, 0x1F, 0x72, 0x26, 0x60, 0x76, 0x32,
-0x01, 0x6B, 0x6C, 0xEA, 0x22, 0x22, 0x40, 0xF0, 0x4C, 0xA0, 0x03, 0x6B,
-0xCC, 0xEA, 0x6C, 0xEA, 0x1C, 0x22, 0x06, 0x92, 0x6A, 0xEA, 0xA0, 0xF0,
-0x13, 0x60, 0x04, 0x52, 0xA0, 0xF0, 0x1B, 0x60, 0xC0, 0xF0, 0x18, 0x22,
-0x01, 0x72, 0x11, 0x61, 0x00, 0xF3, 0x5C, 0xA1, 0x05, 0x93, 0xCC, 0xEA,
-0x43, 0xEB, 0xC0, 0xF0, 0x0B, 0x60, 0x00, 0xF3, 0x5F, 0xA1, 0x05, 0x94,
-0xCC, 0xEA, 0x83, 0xEA, 0xA0, 0xF0, 0x1A, 0x61, 0x00, 0x18, 0x96, 0x29,
-0x00, 0x65, 0x0C, 0x97, 0x0B, 0x91, 0x0A, 0x90, 0x00, 0x6A, 0x00, 0xEF,
-0x07, 0x63, 0x4A, 0x6A, 0x00, 0xF3, 0x5C, 0xC4, 0x45, 0x6A, 0x00, 0xF3,
-0x5D, 0xC4, 0x46, 0x6A, 0x00, 0xF3, 0x5E, 0xC4, 0x40, 0x6A, 0x00, 0xF3,
-0x5F, 0xC4, 0xA7, 0x17, 0x01, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x0E, 0x2A, 0x11, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x27, 0xF7, 0x1F, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x27, 0xF7,
-0x1F, 0x4B, 0x6E, 0xEA, 0x7F, 0xF7, 0x10, 0x22, 0x9D, 0x67, 0x00, 0x1C,
-0x8A, 0x40, 0x10, 0x4C, 0x10, 0xF0, 0x02, 0x69, 0x00, 0xF4, 0x20, 0x31,
-0x01, 0xF6, 0x88, 0x40, 0x63, 0xF3, 0x00, 0x49, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0xE0, 0xF2, 0x48, 0xD9, 0x01, 0xF6, 0x80, 0x40, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0x4C, 0xD9, 0x01, 0xF6, 0x84, 0x40,
-0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0x50, 0xD9, 0x11, 0xF6,
-0x80, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF2, 0x54, 0xD9,
-0x11, 0xF6, 0x84, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF2,
-0x58, 0xD9, 0x11, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0xE0, 0xF2, 0x5C, 0xD9, 0x11, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x65, 0x00, 0xF3, 0x40, 0xD9, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0xCB, 0xF4, 0x46, 0xA2, 0xFF, 0x6B, 0x6C, 0xEA, 0x22, 0x72,
-0x02, 0x60, 0x92, 0x72, 0x1A, 0x61, 0x01, 0xF0, 0x8D, 0x40, 0x00, 0x1C,
-0x00, 0x5C, 0x00, 0x65, 0x0F, 0x6B, 0x4C, 0xEB, 0x0F, 0x6A, 0x6E, 0xEA,
-0xFF, 0x6C, 0x8C, 0xEA, 0x08, 0x5B, 0xA1, 0x42, 0x0C, 0x61, 0xA0, 0x34,
-0x80, 0x33, 0x00, 0xF6, 0xA0, 0x32, 0x6D, 0xEA, 0x8D, 0xEA, 0xAD, 0xEA,
-0xAD, 0xEC, 0x00, 0xF3, 0x54, 0xD9, 0x00, 0xF3, 0x98, 0xD9, 0x9D, 0x67,
-0x00, 0x1C, 0x90, 0x40, 0x10, 0x4C, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x40, 0x9B, 0x80, 0x6B, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x6D, 0xEA, 0x63, 0xF3, 0x40, 0xDC, 0xFC, 0x16,
-0x20, 0xF3, 0x40, 0xA1, 0x05, 0x93, 0xCC, 0xEA, 0x43, 0xEB, 0x5F, 0xF7,
-0x1B, 0x60, 0x00, 0x18, 0xD2, 0x29, 0x00, 0x65, 0x5A, 0x17, 0x06, 0x93,
-0x04, 0x73, 0x12, 0x60, 0xFF, 0x73, 0x5F, 0xF7, 0x14, 0x61, 0x00, 0xF3,
-0x5E, 0xA1, 0x05, 0x94, 0xCC, 0xEA, 0x43, 0xEC, 0x24, 0x61, 0x00, 0xF3,
-0x5C, 0xA1, 0xCC, 0xEA, 0x43, 0xEC, 0x0A, 0x60, 0x00, 0x18, 0x1E, 0x29,
-0x00, 0x65, 0x45, 0x17, 0x00, 0xF3, 0x5D, 0xA1, 0x05, 0x94, 0xCC, 0xEA,
-0x83, 0xEA, 0xF6, 0x60, 0x00, 0x18, 0x9B, 0x28, 0x00, 0x65, 0x3B, 0x17,
-0x00, 0xF3, 0x5E, 0xA1, 0x05, 0x93, 0xCC, 0xEA, 0x43, 0xEB, 0xEC, 0x60,
-0x20, 0xF3, 0x41, 0xA1, 0x05, 0x94, 0xCC, 0xEA, 0x83, 0xEA, 0x3F, 0xF7,
-0x0B, 0x61, 0x00, 0x18, 0xD2, 0x29, 0x00, 0x65, 0x2A, 0x17, 0x20, 0xF3,
-0x41, 0xA1, 0x05, 0x93, 0xCC, 0xEA, 0x63, 0xEA, 0xF6, 0x60, 0x20, 0x17,
-0xFB, 0x63, 0x10, 0xF0, 0x02, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0x07, 0xD1,
-0x26, 0x67, 0x06, 0xD0, 0x08, 0x62, 0x63, 0xF3, 0x00, 0x49, 0x66, 0xF7,
-0x8C, 0x99, 0x7F, 0x6A, 0x92, 0x30, 0x4C, 0xE8, 0xE0, 0xF2, 0x46, 0xA1,
-0x0F, 0x2A, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x35, 0xA0, 0x35,
-0x40, 0xF0, 0x4C, 0xA5, 0xFF, 0x6B, 0x6C, 0xEA, 0x03, 0x6B, 0x6C, 0xEA,
-0x03, 0x22, 0xFF, 0xF7, 0x1F, 0x74, 0x06, 0x61, 0x08, 0x97, 0x07, 0x91,
-0x06, 0x90, 0x00, 0x6A, 0x00, 0xEF, 0x05, 0x63, 0x01, 0xF0, 0x80, 0x45,
-0x04, 0xD5, 0x00, 0x1C, 0x00, 0x5C, 0x05, 0xD6, 0x01, 0x6B, 0x6C, 0xEA,
-0x04, 0x95, 0x05, 0x96, 0x2C, 0x22, 0x4B, 0x58, 0x06, 0x61, 0xC0, 0xF2,
-0x53, 0xA1, 0xFF, 0x6C, 0x8C, 0xEA, 0x6A, 0xEA, 0x74, 0x61, 0x48, 0x40,
-0xE0, 0x4A, 0xFF, 0x6B, 0x6C, 0xEA, 0x1E, 0x5A, 0x07, 0x60, 0x86, 0x67,
-0x63, 0xF3, 0x00, 0x4C, 0xC0, 0xF2, 0x53, 0xA4, 0x6C, 0xEA, 0x43, 0x2A,
-0x23, 0x58, 0xD8, 0x60, 0x66, 0x67, 0x63, 0xF3, 0x00, 0x4B, 0xC0, 0xF2,
-0x53, 0xA3, 0x02, 0x72, 0xD1, 0x60, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC,
-0x80, 0x34, 0x02, 0x6A, 0x80, 0x34, 0xC0, 0xF2, 0x53, 0xC3, 0x81, 0xF4,
-0x07, 0x4C, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x6D, 0xC3, 0x17, 0x4B, 0x58,
-0x06, 0x61, 0xC0, 0xF2, 0x53, 0xA1, 0xFF, 0x6C, 0x8C, 0xEA, 0x01, 0x72,
-0x40, 0x61, 0x48, 0x40, 0xE0, 0x4A, 0xFF, 0x6B, 0x6C, 0xEA, 0x1E, 0x5A,
-0x07, 0x60, 0x86, 0x67, 0x63, 0xF3, 0x00, 0x4C, 0xC0, 0xF2, 0x53, 0xA4,
-0x6C, 0xEA, 0x25, 0x2A, 0x23, 0x58, 0xAC, 0x60, 0x66, 0x67, 0x63, 0xF3,
-0x00, 0x4B, 0xC0, 0xF2, 0x53, 0xA3, 0x02, 0x72, 0xA5, 0x60, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x02, 0x6A, 0x80, 0x34, 0xC0, 0xF2,
-0x53, 0xC3, 0x21, 0xF4, 0x10, 0x4C, 0x00, 0x1C, 0xF0, 0x5B, 0x42, 0x6D,
-0x97, 0x17, 0x00, 0x6A, 0xC0, 0xF2, 0x53, 0xC4, 0xC9, 0xF7, 0x1B, 0x6C,
-0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x81, 0xF4, 0x07, 0x4C, 0x00, 0x1C,
-0xF0, 0x5B, 0x20, 0x6D, 0x89, 0x17, 0x00, 0x6A, 0xC0, 0xF2, 0x53, 0xC4,
-0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x21, 0xF4,
-0x10, 0x4C, 0x00, 0x1C, 0xF0, 0x5B, 0x44, 0x6D, 0x7B, 0x17, 0x31, 0xF4,
-0x80, 0x45, 0xC0, 0xF2, 0x73, 0xC1, 0x00, 0x1C, 0xF0, 0x5B, 0x43, 0x6D,
-0x73, 0x17, 0x81, 0xF4, 0x87, 0x45, 0xC0, 0xF2, 0x73, 0xC1, 0x00, 0x1C,
-0xF0, 0x5B, 0x10, 0x6D, 0x6B, 0x17, 0x00, 0x65, 0xE8, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xBF, 0xAF, 0x24, 0x63, 0x00, 0x0C, 0x21, 0x38, 0x00, 0x00,
-0x10, 0x00, 0xBF, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0x01, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x10, 0x3C, 0x14, 0xAE, 0x42, 0x24,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x03, 0x11, 0x36, 0x10, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x22, 0xAE, 0x20, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x30, 0x03, 0x10, 0x36, 0x20, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x05, 0x3C,
-0x00, 0x00, 0x02, 0xAE, 0x01, 0x80, 0x02, 0x3C, 0x15, 0xAE, 0x44, 0x24,
-0x33, 0x03, 0xA3, 0x34, 0x00, 0x00, 0x24, 0xAE, 0x00, 0x00, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x42, 0x30, 0xFB, 0xFF, 0x40, 0x10,
-0x30, 0x03, 0xA2, 0x34, 0x00, 0x00, 0x46, 0x8C, 0x0F, 0x00, 0x03, 0x3C,
-0xFF, 0xFF, 0x63, 0x34, 0x24, 0x30, 0xC3, 0x00, 0x40, 0x11, 0x06, 0x00,
-0x23, 0x10, 0x46, 0x00, 0x80, 0x10, 0x02, 0x00, 0x21, 0x10, 0x46, 0x00,
-0xAF, 0x0F, 0x05, 0x3C, 0xC0, 0x10, 0x02, 0x00, 0x00, 0xA0, 0xA5, 0x34,
-0x1B, 0x00, 0xA2, 0x00, 0x02, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x63, 0x24,
-0xC2, 0x30, 0x06, 0x00, 0x10, 0x00, 0xA4, 0x27, 0x54, 0x41, 0x66, 0xAC,
-0x12, 0x28, 0x00, 0x00, 0x90, 0x40, 0x00, 0x0C, 0x58, 0x41, 0x65, 0xAC,
-0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27, 0xC0, 0xFF, 0xBD, 0x27,
-0x2C, 0x00, 0xB5, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x21, 0xA8, 0x80, 0x00,
-0x02, 0x80, 0x12, 0x3C, 0x10, 0x00, 0xA4, 0x27, 0x38, 0x00, 0xBE, 0xAF,
-0x30, 0x00, 0xB6, 0xAF, 0x3C, 0x00, 0xBF, 0xAF, 0x34, 0x00, 0xB7, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0x44, 0x00, 0xA5, 0xAF,
-0xEC, 0x5D, 0x42, 0x92, 0x21, 0xF0, 0x00, 0x00, 0xC5, 0x00, 0x40, 0x10,
-0x21, 0xB0, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x43, 0x24,
-0xB0, 0x1B, 0x62, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30,
-0xBE, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3E, 0x62, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0xBA, 0x00, 0x40, 0x14, 0x02, 0x80, 0x17, 0x3C,
-0x0E, 0x5E, 0xE2, 0x92, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x0E, 0x5E, 0xE2, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x42, 0x24, 0x0E, 0x5E, 0xE2, 0xA2, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0xF2, 0x5D, 0x40, 0xA0, 0x14, 0x5E, 0x60, 0xAC,
-0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0x62, 0x90, 0xFD, 0xFF, 0x03, 0x24,
-0x42, 0xB0, 0x13, 0x3C, 0x24, 0x10, 0x43, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x07, 0x5E, 0x62, 0xA0, 0x00, 0x00, 0x63, 0x92, 0xEF, 0xFF, 0x02, 0x24,
-0x03, 0x00, 0x64, 0x36, 0x24, 0x18, 0x62, 0x00, 0x40, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x63, 0xA2, 0x00, 0x00, 0x82, 0xA0, 0x02, 0x80, 0x04, 0x3C,
-0xF4, 0x5D, 0x82, 0x94, 0x20, 0x00, 0xA3, 0x96, 0xFF, 0xFF, 0x42, 0x30,
-0x0A, 0x00, 0x43, 0x10, 0x02, 0x80, 0x14, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x94, 0x00, 0x42, 0x34, 0xF4, 0x5D, 0x83, 0xA4, 0x00, 0x00, 0x43, 0xA4,
-0xF4, 0x5D, 0x83, 0x94, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x63, 0x30,
-0x80, 0x1A, 0x03, 0x00, 0xF8, 0x5D, 0x83, 0xAE, 0x25, 0xB0, 0x04, 0x3C,
-0x84, 0x00, 0x82, 0x34, 0x00, 0x00, 0x50, 0x8C, 0x80, 0x00, 0x84, 0x34,
-0x00, 0x00, 0x82, 0x8C, 0x21, 0x18, 0x00, 0x00, 0xF8, 0x5D, 0x86, 0x8E,
-0x00, 0x88, 0x10, 0x00, 0x21, 0x80, 0x00, 0x00, 0x25, 0x80, 0x02, 0x02,
-0x25, 0x88, 0x23, 0x02, 0x21, 0x20, 0x00, 0x02, 0x7D, 0x2B, 0x00, 0x0C,
-0x21, 0x28, 0x20, 0x02, 0xF8, 0x5D, 0x88, 0x8E, 0x02, 0x80, 0x0A, 0x3C,
-0xFC, 0x5D, 0x43, 0x95, 0x23, 0x48, 0x02, 0x01, 0x21, 0x20, 0x30, 0x01,
-0x21, 0x28, 0x00, 0x00, 0x2B, 0x10, 0x90, 0x00, 0xFF, 0xFF, 0x63, 0x30,
-0x21, 0x28, 0xB1, 0x00, 0x80, 0x1A, 0x03, 0x00, 0x21, 0x28, 0xA2, 0x00,
-0x21, 0x38, 0x00, 0x00, 0x2B, 0x40, 0x83, 0x00, 0x23, 0x28, 0xA7, 0x00,
-0x23, 0x20, 0x83, 0x00, 0x23, 0x28, 0xA8, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x18, 0x5E, 0x64, 0xAC, 0x1C, 0x5E, 0x65, 0xAC, 0xFC, 0x5D, 0x42, 0x95,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x42, 0x30, 0x80, 0x12, 0x02, 0x00,
-0x2B, 0x10, 0x49, 0x00, 0x97, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xFC, 0x5D, 0x42, 0x95, 0x00, 0x00, 0x64, 0x92, 0xFB, 0xFF, 0x03, 0x24,
-0xFF, 0xFF, 0x42, 0x30, 0x80, 0x12, 0x02, 0x00, 0x24, 0x20, 0x83, 0x00,
-0x23, 0x48, 0x22, 0x01, 0x00, 0x00, 0x64, 0xA2, 0x01, 0x00, 0x06, 0x24,
-0x04, 0x00, 0x20, 0x11, 0x01, 0x00, 0x04, 0x24, 0x80, 0x10, 0x09, 0x00,
-0x21, 0x10, 0x49, 0x00, 0x80, 0x30, 0x02, 0x00, 0xB9, 0x20, 0x00, 0x0C,
-0x21, 0x28, 0x00, 0x00, 0x42, 0xB0, 0x02, 0x3C, 0x22, 0x00, 0x03, 0x24,
-0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0, 0x44, 0x00, 0xA2, 0x8F,
-0x05, 0x00, 0x05, 0x24, 0x24, 0x00, 0xA4, 0x26, 0x00, 0x00, 0x47, 0x8C,
-0x14, 0x00, 0xA6, 0x27, 0xFF, 0x3F, 0xE7, 0x30, 0xAB, 0x1A, 0x00, 0x0C,
-0xDC, 0xFF, 0xE7, 0x24, 0x2C, 0x00, 0x40, 0x10, 0x21, 0x28, 0x40, 0x00,
-0xEC, 0x5D, 0x42, 0x92, 0x02, 0x00, 0x03, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x83, 0x00, 0x43, 0x10, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x00, 0xA2, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0xA3, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x62, 0x30,
-0x04, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C, 0x01, 0x00, 0x16, 0x24,
-0x0B, 0x5E, 0x56, 0xA0, 0x04, 0x00, 0xA3, 0x90, 0x14, 0x00, 0xA7, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0xE2, 0x28, 0x16, 0x00, 0x40, 0x14,
-0xFE, 0x00, 0x66, 0x30, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x43, 0x24,
-0x4C, 0x3A, 0x64, 0x94, 0xC0, 0x10, 0x06, 0x00, 0x2A, 0x10, 0x82, 0x00,
-0x10, 0x00, 0x40, 0x14, 0x02, 0x80, 0x03, 0x3C, 0x21, 0x10, 0xC7, 0x00,
-0xFD, 0xFF, 0x42, 0x24, 0xC0, 0x10, 0x02, 0x00, 0x2A, 0x10, 0x44, 0x00,
-0x0A, 0x00, 0x40, 0x14, 0xC2, 0x10, 0x04, 0x00, 0x23, 0x30, 0x46, 0x00,
-0x21, 0x18, 0xA6, 0x00, 0x05, 0x00, 0x62, 0x90, 0x07, 0x00, 0x84, 0x30,
-0x01, 0x00, 0x03, 0x24, 0x07, 0x10, 0x82, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x0B, 0xF0, 0x62, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0x62, 0x90,
-0xEF, 0xFF, 0x03, 0x24, 0x21, 0x20, 0xC0, 0x02, 0x24, 0x10, 0x43, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0x62, 0xA0, 0xEC, 0x5D, 0x43, 0x92,
-0x02, 0x80, 0x02, 0x3C, 0xE0, 0xE4, 0x42, 0x24, 0xFF, 0x00, 0x63, 0x30,
-0x80, 0x18, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x00, 0x00, 0x66, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x09, 0xF8, 0xC0, 0x00, 0x21, 0x28, 0xC0, 0x03,
-0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x3C, 0x00, 0xBF, 0x8F,
-0x38, 0x00, 0xBE, 0x8F, 0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
-0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x40, 0x00, 0xBD, 0x27, 0xEC, 0x5D, 0x42, 0x92,
-0x00, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x40, 0x14, 0x02, 0x80, 0x03, 0x3C,
-0x60, 0x1B, 0x70, 0x24, 0xB0, 0x1B, 0x02, 0x96, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x01, 0x42, 0x30, 0xE9, 0xFF, 0x40, 0x10, 0x05, 0x00, 0x05, 0x24,
-0x44, 0x00, 0xA2, 0x8F, 0x24, 0x00, 0xA4, 0x26, 0x00, 0x00, 0x47, 0x8C,
-0x14, 0x00, 0xA6, 0x27, 0xFF, 0x3F, 0xE7, 0x30, 0xAB, 0x1A, 0x00, 0x0C,
-0xDC, 0xFF, 0xE7, 0x24, 0xE0, 0xFF, 0x40, 0x10, 0x21, 0x28, 0x40, 0x00,
-0x14, 0x00, 0xA7, 0x8F, 0x04, 0x00, 0x42, 0x90, 0x04, 0x00, 0xE3, 0x28,
-0xDB, 0xFF, 0x60, 0x14, 0xFE, 0x00, 0x46, 0x30, 0x4C, 0x3A, 0x04, 0x96,
-0xC0, 0x10, 0x06, 0x00, 0x2A, 0x10, 0x82, 0x00, 0xD6, 0xFF, 0x40, 0x14,
-0x21, 0x10, 0xC7, 0x00, 0xFD, 0xFF, 0x42, 0x24, 0xC0, 0x10, 0x02, 0x00,
-0x2A, 0x10, 0x44, 0x00, 0xD1, 0xFF, 0x40, 0x14, 0xC2, 0x10, 0x04, 0x00,
-0x23, 0x30, 0x46, 0x00, 0x21, 0x18, 0xA6, 0x00, 0x05, 0x00, 0x62, 0x90,
-0x07, 0x00, 0x84, 0x30, 0x07, 0x10, 0x82, 0x00, 0x01, 0x00, 0x42, 0x30,
-0xC9, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x51, 0x00, 0x0C,
-0x21, 0x20, 0x00, 0x00, 0x83, 0x2C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x0E, 0x5E, 0xE2, 0x92, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x0E, 0x5E, 0xE2, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x42, 0x24, 0x0E, 0x5E, 0xE2, 0xA2, 0x00, 0x00, 0x62, 0x92,
-0xFB, 0xFF, 0x03, 0x24, 0x01, 0x00, 0x06, 0x24, 0x24, 0x10, 0x43, 0x00,
-0x00, 0x00, 0x62, 0xA2, 0x32, 0x2C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x03, 0x00, 0xA2, 0x90, 0x02, 0x80, 0x07, 0x3C, 0x09, 0x5E, 0xE2, 0xA0,
-0x02, 0x00, 0xA3, 0x90, 0x21, 0x30, 0x80, 0x00, 0x0A, 0x5E, 0x83, 0xA0,
-0x0A, 0x5E, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x09, 0x5E, 0xE2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x5E, 0xC2, 0xA0, 0x4C, 0x2C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x5E, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x5E, 0xC2, 0xA0,
-0x4C, 0x2C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x0D, 0x5E, 0x43, 0xA0, 0xD0, 0x07, 0x04, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0xDC, 0x5D, 0x44, 0xAC,
-0x0C, 0x5E, 0x60, 0xA0, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF,
-0x20, 0x00, 0xBF, 0xAF, 0x04, 0x00, 0x82, 0x8C, 0x02, 0x00, 0x03, 0x24,
-0x21, 0x80, 0x80, 0x00, 0x02, 0x17, 0x02, 0x00, 0x03, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x43, 0x10, 0x02, 0x80, 0x11, 0x3C, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xEC, 0x5D, 0x22, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xF8, 0xFF, 0x40, 0x10, 0x10, 0x00, 0xA4, 0x27, 0x8A, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xEC, 0x5D, 0x23, 0x92, 0x02, 0x80, 0x02, 0x3C,
-0xB4, 0xE4, 0x42, 0x24, 0xFF, 0x00, 0x63, 0x30, 0x80, 0x18, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x00, 0x00, 0x66, 0x8C, 0x00, 0x00, 0x04, 0x8E,
-0x04, 0x00, 0x05, 0x8E, 0x09, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xEE, 0x5D, 0x43, 0x90, 0x0C, 0x00, 0x02, 0x24,
-0xFF, 0x00, 0x63, 0x30, 0x05, 0x00, 0x62, 0x10, 0x10, 0x00, 0xA4, 0x27,
-0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xF7, 0x2C, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x06, 0x5E, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x60, 0x10, 0x02, 0x80, 0x05, 0x3C,
-0x0C, 0x5E, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24,
-0x0C, 0x5E, 0xA2, 0xA0, 0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xF7, 0x2C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x04, 0x3C,
-0x28, 0x00, 0x85, 0x34, 0x02, 0x00, 0x82, 0x94, 0x04, 0x00, 0x84, 0x24,
-0x05, 0x00, 0x40, 0x14, 0x2B, 0x18, 0xA4, 0x00, 0xFB, 0xFF, 0x60, 0x10,
-0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x25, 0xB0, 0x03, 0x3C,
-0xBE, 0x00, 0x63, 0x34, 0x00, 0x00, 0x62, 0x94, 0x08, 0x00, 0xE0, 0x03,
-0x01, 0x00, 0x42, 0x2C, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x24, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x19, 0x00, 0x40, 0x10, 0x98, 0x54, 0x64, 0x24, 0x98, 0x54, 0x62, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x44, 0x14, 0x02, 0x80, 0x02, 0x3C,
-0x0D, 0x5E, 0x43, 0x90, 0x01, 0x00, 0x02, 0x24, 0xFF, 0x00, 0x63, 0x30,
-0x10, 0x00, 0x62, 0x10, 0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x05, 0x00, 0x42, 0x28,
-0x0A, 0x00, 0x40, 0x10, 0x01, 0x00, 0x04, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x64, 0x59, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x60, 0x14,
-0x21, 0x10, 0x80, 0x00, 0x10, 0x00, 0xBF, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0x8F,
-0x21, 0x20, 0x00, 0x00, 0x21, 0x10, 0x80, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x24, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x98, 0x54, 0x43, 0x8C, 0x98, 0x54, 0x42, 0x24,
-0x28, 0x00, 0x62, 0x14, 0x02, 0x80, 0x03, 0x3C, 0x05, 0x5E, 0x62, 0x90,
-0x01, 0x00, 0x04, 0x24, 0xFF, 0x00, 0x42, 0x30, 0x23, 0x00, 0x44, 0x10,
-0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0x03, 0x00, 0x42, 0x28, 0x1D, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x42, 0x30, 0x18, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x42, 0x30,
-0x13, 0x00, 0x40, 0x14, 0x02, 0x80, 0x03, 0x3C, 0x0D, 0x5E, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x42, 0x30, 0x0E, 0x00, 0x44, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x0E, 0x5E, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x00, 0x60, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0x04, 0x3E, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x14,
-0x21, 0x18, 0x00, 0x00, 0x3C, 0x3A, 0x42, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x40, 0x14, 0x01, 0x00, 0x03, 0x24, 0x21, 0x18, 0x00, 0x00,
-0x10, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x30, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x0E, 0x00, 0x40, 0x10, 0x90, 0x54, 0x65, 0x24, 0x90, 0x54, 0x62, 0x8C,
-0x02, 0x80, 0x04, 0x3C, 0x88, 0x54, 0x86, 0x24, 0x09, 0x00, 0x45, 0x14,
-0x01, 0x00, 0x03, 0x24, 0x88, 0x54, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x05, 0x00, 0x46, 0x14, 0x21, 0x10, 0x60, 0x00, 0x10, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0x10, 0x00, 0xBF, 0x8F, 0x21, 0x18, 0x00, 0x00, 0x21, 0x10, 0x60, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB0, 0xAF, 0xFF, 0x00, 0x90, 0x30, 0x10, 0x00, 0xA4, 0x27,
-0x20, 0x00, 0xB2, 0xAF, 0x24, 0x00, 0xBF, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0x02, 0x80, 0x12, 0x3C, 0x0F, 0x00, 0x00, 0x12,
-0x00, 0x00, 0x00, 0x00, 0x3C, 0x5E, 0x43, 0x92, 0x01, 0x00, 0x02, 0x24,
-0x04, 0x0C, 0x04, 0x24, 0xFF, 0x00, 0x63, 0x30, 0x2A, 0x00, 0x62, 0x10,
-0x80, 0x01, 0x10, 0x3C, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x3C, 0x5E, 0x43, 0x92, 0x02, 0x00, 0x02, 0x24, 0x21, 0x28, 0x00, 0x00,
-0xFF, 0x00, 0x63, 0x30, 0xF3, 0xFF, 0x62, 0x14, 0x44, 0x08, 0x04, 0x24,
-0x03, 0x5C, 0x00, 0x0C, 0x7F, 0xFE, 0x10, 0x3C, 0x30, 0x5C, 0x00, 0x0C,
-0x04, 0x0C, 0x04, 0x24, 0xFD, 0x00, 0x45, 0x30, 0x1A, 0x5C, 0x00, 0x0C,
-0x04, 0x0C, 0x04, 0x24, 0x30, 0x5C, 0x00, 0x0C, 0x04, 0x0D, 0x04, 0x24,
-0xFD, 0x00, 0x45, 0x30, 0x1A, 0x5C, 0x00, 0x0C, 0x04, 0x0D, 0x04, 0x24,
-0x26, 0x5C, 0x00, 0x0C, 0x70, 0x0E, 0x04, 0x24, 0xFF, 0xFF, 0x10, 0x36,
-0x24, 0x28, 0x50, 0x00, 0x03, 0x5C, 0x00, 0x0C, 0x70, 0x0E, 0x04, 0x24,
-0x26, 0x5C, 0x00, 0x0C, 0x8C, 0x0E, 0x04, 0x24, 0x24, 0x28, 0x50, 0x00,
-0x03, 0x5C, 0x00, 0x0C, 0x8C, 0x0E, 0x04, 0x24, 0x01, 0x00, 0x02, 0x24,
-0x3C, 0x5E, 0x42, 0xA2, 0xB9, 0x2D, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x30, 0x5C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x42, 0x34,
-0xFF, 0x00, 0x45, 0x30, 0x1A, 0x5C, 0x00, 0x0C, 0x04, 0x0C, 0x04, 0x24,
-0x30, 0x5C, 0x00, 0x0C, 0x04, 0x0D, 0x04, 0x24, 0x02, 0x00, 0x42, 0x34,
-0xFF, 0x00, 0x45, 0x30, 0x1A, 0x5C, 0x00, 0x0C, 0x04, 0x0D, 0x04, 0x24,
-0x26, 0x5C, 0x00, 0x0C, 0x70, 0x0E, 0x04, 0x24, 0x25, 0x28, 0x50, 0x00,
-0x03, 0x5C, 0x00, 0x0C, 0x70, 0x0E, 0x04, 0x24, 0x26, 0x5C, 0x00, 0x0C,
-0x8C, 0x0E, 0x04, 0x24, 0x25, 0x28, 0x50, 0x00, 0x03, 0x5C, 0x00, 0x0C,
-0x8C, 0x0E, 0x04, 0x24, 0x03, 0x00, 0x05, 0x3C, 0x59, 0x01, 0xA5, 0x34,
-0x03, 0x5C, 0x00, 0x0C, 0x44, 0x08, 0x04, 0x24, 0x02, 0x00, 0x02, 0x24,
-0x3C, 0x5E, 0x42, 0xA2, 0xB9, 0x2D, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x42, 0x00, 0x46, 0x34, 0xFC, 0x37, 0x03, 0x24,
-0x40, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA4, 0x03, 0x08, 0x04, 0x24,
-0x03, 0x00, 0x05, 0x24, 0x00, 0x00, 0xC0, 0xA0, 0x1A, 0x5C, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x1C, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x02, 0x3C, 0xEC, 0x5D, 0x43, 0x90, 0xFC, 0x57, 0x12, 0x24,
-0x0B, 0x00, 0x60, 0x10, 0xFC, 0x77, 0x11, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0xC6, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x63, 0x30,
-0x2A, 0x00, 0x60, 0x14, 0x21, 0x20, 0x00, 0x00, 0x21, 0x30, 0x00, 0x00,
-0x00, 0x02, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C, 0x00, 0x08, 0x04, 0x24,
-0x25, 0xB0, 0x03, 0x3C, 0x21, 0x00, 0x65, 0x34, 0x00, 0x00, 0xA2, 0x90,
-0x18, 0x00, 0x66, 0x34, 0x40, 0x00, 0x70, 0x34, 0x01, 0x00, 0x42, 0x34,
-0x42, 0x00, 0x63, 0x34, 0x00, 0x00, 0xA2, 0xA0, 0xFF, 0xFF, 0x02, 0x24,
-0x00, 0x00, 0xC0, 0xA0, 0x64, 0x00, 0x04, 0x24, 0x00, 0x00, 0x62, 0xA0,
-0x00, 0x00, 0x12, 0xA6, 0x5B, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x11, 0xA6, 0x5B, 0x1F, 0x00, 0x0C, 0x0A, 0x00, 0x04, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x1A, 0x5C, 0x00, 0x0C, 0x03, 0x08, 0x04, 0x24,
-0x5B, 0x1F, 0x00, 0x0C, 0x0A, 0x00, 0x04, 0x24, 0xFC, 0x37, 0x02, 0x24,
-0x00, 0x00, 0x02, 0xA6, 0x5B, 0x1F, 0x00, 0x0C, 0x0A, 0x00, 0x04, 0x24,
-0x00, 0x00, 0x11, 0xA6, 0x5B, 0x1F, 0x00, 0x0C, 0x0A, 0x00, 0x04, 0x24,
-0x00, 0x00, 0x12, 0xA6, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xA8, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x30, 0x00, 0x00, 0x00, 0x02, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C,
-0x00, 0x08, 0x04, 0x24, 0x1F, 0x2E, 0x00, 0x08, 0x25, 0xB0, 0x03, 0x3C,
-0xB8, 0xFF, 0xBD, 0x27, 0x2C, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x13, 0x3C, 0xFF, 0x00, 0x90, 0x30, 0x18, 0x00, 0xA4, 0x27,
-0x30, 0x00, 0xB4, 0xAF, 0x28, 0x00, 0xB2, 0xAF, 0x24, 0x00, 0xB1, 0xAF,
-0x40, 0x00, 0xBF, 0xAF, 0x3C, 0x00, 0xB7, 0xAF, 0x38, 0x00, 0xB6, 0xAF,
-0x34, 0x00, 0xB5, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0xB2, 0x30,
-0xEE, 0x5D, 0x62, 0x92, 0x0F, 0x00, 0x11, 0x32, 0x0F, 0x00, 0x42, 0x30,
-0x13, 0x00, 0x51, 0x10, 0x21, 0xA0, 0x00, 0x00, 0x04, 0x00, 0x02, 0x32,
-0x40, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x5D, 0x62, 0x92,
-0x0C, 0x00, 0x03, 0x24, 0x0F, 0x00, 0x42, 0x30, 0x8F, 0x00, 0x43, 0x10,
-0x08, 0x00, 0x02, 0x32, 0xEE, 0x5D, 0x62, 0x92, 0x04, 0x00, 0x03, 0x24,
-0x0F, 0x00, 0x42, 0x30, 0xD2, 0x01, 0x43, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xEE, 0x5D, 0x62, 0x92, 0x02, 0x00, 0x03, 0x24, 0x0F, 0x00, 0x42, 0x30,
-0x9B, 0x00, 0x43, 0x10, 0x06, 0x00, 0x02, 0x32, 0x02, 0x80, 0x10, 0x3C,
-0xED, 0x5D, 0x03, 0x92, 0xEE, 0x5D, 0x62, 0x92, 0x0F, 0x00, 0x63, 0x30,
-0x0F, 0x00, 0x42, 0x30, 0x2A, 0x10, 0x43, 0x00, 0x1C, 0x00, 0x40, 0x14,
-0x02, 0x80, 0x12, 0x3C, 0xED, 0x5D, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x40, 0x00, 0x42, 0x30, 0x17, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0xC2, 0x5C, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x43, 0x30,
-0x52, 0x00, 0x60, 0x14, 0x04, 0x00, 0x42, 0x30, 0x10, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xEE, 0x5D, 0x43, 0x92, 0x02, 0x80, 0x06, 0x3C,
-0x14, 0xE5, 0xC5, 0x90, 0x0F, 0x00, 0x63, 0x30, 0x25, 0xB0, 0x02, 0x3C,
-0x25, 0x18, 0x65, 0x00, 0xDD, 0x02, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0,
-0xED, 0x5D, 0x04, 0x92, 0x80, 0xFF, 0x02, 0x24, 0xBF, 0xFF, 0x03, 0x24,
-0x26, 0x28, 0xA2, 0x00, 0x24, 0x20, 0x83, 0x00, 0x14, 0xE5, 0xC5, 0xA0,
-0xED, 0x5D, 0x04, 0xA2, 0x90, 0x40, 0x00, 0x0C, 0x18, 0x00, 0xA4, 0x27,
-0x40, 0x00, 0xBF, 0x8F, 0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F,
-0x34, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F,
-0x28, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27, 0xEE, 0x5D, 0x62, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x42, 0x30, 0x4C, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xEE, 0x5D, 0x62, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x42, 0x30, 0x03, 0x00, 0x40, 0x10, 0x08, 0x00, 0x02, 0x32,
-0x1B, 0x00, 0x40, 0x10, 0x02, 0x80, 0x03, 0x3C, 0xEE, 0x5D, 0x62, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x42, 0x30, 0x0C, 0x00, 0x40, 0x14,
-0x08, 0x00, 0x02, 0x32, 0x0A, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x40, 0x12, 0x02, 0x80, 0x03, 0x3C, 0x10, 0x37, 0x62, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30, 0x03, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x0E, 0x51, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00,
-0xEE, 0x5D, 0x62, 0x92, 0xF0, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0xEE, 0x5D, 0x62, 0xA2, 0xEE, 0x5D, 0x63, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x25, 0x18, 0x23, 0x02, 0xEE, 0x5D, 0x63, 0xA2, 0x72, 0x2E, 0x00, 0x08,
-0x02, 0x80, 0x10, 0x3C, 0x10, 0x37, 0x62, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x01, 0x42, 0x30, 0xF2, 0xFF, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x0D, 0x5E, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xFF, 0x60, 0x14,
-0x01, 0x00, 0x04, 0x24, 0x0E, 0x51, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xBD, 0x2E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x53, 0x21, 0x00, 0x0C,
-0x24, 0x00, 0x04, 0x24, 0x76, 0x01, 0x40, 0x10, 0x21, 0x88, 0x40, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xEC, 0x5D, 0x45, 0x90, 0xEE, 0x5D, 0x44, 0x92,
-0xED, 0x5D, 0x02, 0x92, 0xBF, 0xFF, 0x03, 0x24, 0x0F, 0x00, 0x84, 0x30,
-0x24, 0x10, 0x43, 0x00, 0xED, 0x5D, 0x02, 0xA2, 0x10, 0x00, 0xA5, 0xA3,
-0x11, 0x00, 0xA4, 0xA3, 0x08, 0x00, 0x24, 0x96, 0x02, 0x80, 0x02, 0x3C,
-0x10, 0x00, 0xA5, 0x27, 0x25, 0x20, 0x82, 0x00, 0x20, 0x00, 0x84, 0x24,
-0xC2, 0x1B, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24, 0x04, 0x00, 0x03, 0x24,
-0x17, 0x00, 0x02, 0x24, 0x0C, 0x00, 0x23, 0xAE, 0x14, 0x00, 0x22, 0xAE,
-0x17, 0x0A, 0x00, 0x0C, 0x21, 0x20, 0x20, 0x02, 0x94, 0x2E, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xA6, 0x2E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x71, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x35, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x77, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x5D, 0x62, 0x92,
-0xF0, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00, 0xEE, 0x5D, 0x62, 0xA2,
-0x02, 0x80, 0x03, 0x3C, 0xEE, 0x5D, 0x62, 0x92, 0x10, 0x37, 0x64, 0x94,
-0x04, 0x00, 0x42, 0x34, 0x00, 0x01, 0x84, 0x30, 0xEE, 0x5D, 0x62, 0xA2,
-0x61, 0xFF, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x51, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0x67, 0x2E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x65, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x2D, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x61, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xEE, 0x5D, 0x62, 0x92, 0xF0, 0xFF, 0x03, 0x24, 0x41, 0xB0, 0x04, 0x3C,
-0x24, 0x10, 0x43, 0x00, 0xEE, 0x5D, 0x62, 0xA2, 0xEE, 0x5D, 0x63, 0x92,
-0x08, 0x00, 0x85, 0x34, 0x82, 0x00, 0x02, 0x24, 0x01, 0x00, 0x63, 0x34,
-0x02, 0x80, 0x17, 0x3C, 0xEE, 0x5D, 0x63, 0xA2, 0x00, 0x00, 0x80, 0xAC,
-0x00, 0x00, 0xA2, 0xA4, 0x42, 0xB0, 0x04, 0x3C, 0x60, 0x1B, 0xE2, 0x26,
-0xB0, 0x1B, 0x45, 0x94, 0x00, 0x00, 0x83, 0x90, 0xBE, 0xFF, 0x02, 0x24,
-0x03, 0x00, 0x86, 0x34, 0x24, 0x18, 0x62, 0x00, 0x00, 0x01, 0xA5, 0x30,
-0x90, 0xFF, 0x02, 0x24, 0x00, 0x00, 0x83, 0xA0, 0x00, 0x00, 0xC2, 0xA0,
-0x38, 0x00, 0xA0, 0x10, 0x25, 0xB0, 0x06, 0x3C, 0x25, 0xB0, 0x04, 0x3C,
-0x84, 0x00, 0x82, 0x34, 0x00, 0x00, 0x46, 0x8C, 0x80, 0x00, 0x84, 0x34,
-0x00, 0x00, 0x82, 0x8C, 0x02, 0x80, 0x0B, 0x3C, 0x14, 0x5E, 0x64, 0x8D,
-0x00, 0x38, 0x06, 0x00, 0x21, 0x30, 0x00, 0x00, 0x25, 0xA0, 0xC2, 0x00,
-0x21, 0x18, 0x00, 0x00, 0x02, 0x80, 0x0A, 0x3C, 0x25, 0xA8, 0xE3, 0x00,
-0x21, 0x28, 0x00, 0x00, 0x1C, 0x5E, 0x42, 0x8D, 0x21, 0x20, 0x94, 0x00,
-0x2B, 0x18, 0x94, 0x00, 0x21, 0x28, 0xB5, 0x00, 0x21, 0x28, 0xA3, 0x00,
-0x2B, 0x10, 0xA2, 0x00, 0x24, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x1C, 0x5E, 0x42, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x45, 0x10,
-0x01, 0x00, 0x05, 0x24, 0x60, 0x1B, 0xE2, 0x26, 0x58, 0x41, 0x43, 0x8C,
-0x42, 0xB0, 0x07, 0x3C, 0x00, 0x00, 0xE6, 0x90, 0x18, 0x00, 0x65, 0x00,
-0xFB, 0xFF, 0x02, 0x24, 0x24, 0x30, 0xC2, 0x00, 0x00, 0x00, 0xE6, 0xA0,
-0x67, 0x46, 0x06, 0x3C, 0xCF, 0xAC, 0xC6, 0x34, 0x01, 0x00, 0x04, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00, 0x82, 0x1A, 0x03, 0x00,
-0x40, 0x10, 0x03, 0x00, 0x21, 0x10, 0x43, 0x00, 0xC0, 0x10, 0x02, 0x00,
-0x21, 0x10, 0x43, 0x00, 0x80, 0x10, 0x02, 0x00, 0x19, 0x00, 0x46, 0x00,
-0x10, 0x30, 0x00, 0x00, 0x23, 0x10, 0x46, 0x00, 0x42, 0x10, 0x02, 0x00,
-0x21, 0x30, 0xC2, 0x00, 0x02, 0x33, 0x06, 0x00, 0x01, 0x00, 0x02, 0x24,
-0xB9, 0x20, 0x00, 0x0C, 0x0A, 0x30, 0x46, 0x00, 0x25, 0xB0, 0x06, 0x3C,
-0xF2, 0x02, 0xC3, 0x34, 0x88, 0xFF, 0x02, 0x24, 0x00, 0x00, 0x62, 0xA0,
-0x11, 0x00, 0xC7, 0x34, 0x00, 0x00, 0xE2, 0x90, 0x08, 0x00, 0xC5, 0x34,
-0x60, 0x1B, 0xE4, 0x26, 0x01, 0x00, 0x42, 0x34, 0x00, 0x00, 0xE2, 0xA0,
-0x00, 0x00, 0xA3, 0x94, 0xB0, 0x1B, 0x82, 0x94, 0xFF, 0xFF, 0x64, 0x30,
-0x10, 0x00, 0x84, 0x34, 0x00, 0x00, 0xA4, 0xA4, 0xFB, 0xFF, 0x84, 0x30,
-0x00, 0x00, 0xA4, 0xA4, 0x00, 0x01, 0x42, 0x30, 0x02, 0x00, 0x84, 0x34,
-0x00, 0x00, 0xA4, 0xA4, 0x04, 0x00, 0x40, 0x10, 0x42, 0xB0, 0x02, 0x3C,
-0x22, 0x00, 0x03, 0x24, 0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0,
-0xFF, 0xF7, 0x84, 0x30, 0x00, 0x00, 0xA4, 0xA4, 0x28, 0x00, 0xC4, 0x34,
-0x00, 0x00, 0x83, 0x94, 0xEF, 0xFE, 0x02, 0x24, 0xFE, 0xFF, 0x08, 0x24,
-0x24, 0x18, 0x62, 0x00, 0x00, 0x00, 0x83, 0xA4, 0x00, 0x00, 0x82, 0x94,
-0x26, 0x00, 0xC5, 0x34, 0x02, 0x80, 0x03, 0x3C, 0x24, 0x10, 0x48, 0x00,
-0x00, 0x00, 0x82, 0xA4, 0xC2, 0x5C, 0x64, 0x90, 0x00, 0x00, 0xA2, 0x94,
-0x04, 0x00, 0x84, 0x30, 0x00, 0x24, 0x42, 0x34, 0x00, 0x00, 0xA2, 0xA4,
-0x09, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x48, 0x00, 0x00, 0x00, 0xA2, 0xA4,
-0x00, 0x00, 0xE3, 0x90, 0xFD, 0xFF, 0x02, 0x24, 0x24, 0x18, 0x62, 0x00,
-0x00, 0x00, 0xE3, 0xA0, 0x00, 0x68, 0x02, 0x40, 0x00, 0x08, 0x42, 0x30,
-0xFD, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x12, 0x3C,
-0x11, 0x00, 0x43, 0x36, 0x00, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x42, 0x34, 0x00, 0x00, 0x62, 0xA0, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x44, 0x36, 0x00, 0x00, 0x82, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x34, 0x00, 0x00, 0x82, 0xA4,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x94,
-0xFF, 0xDB, 0x02, 0x24, 0x28, 0x00, 0x45, 0x36, 0x24, 0x18, 0x62, 0x00,
-0x00, 0x00, 0x83, 0xA4, 0x00, 0x00, 0xA2, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x42, 0x34, 0x00, 0x00, 0xA2, 0xA4, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x01, 0x42, 0x34, 0x00, 0x00, 0xA2, 0xA4, 0x08, 0x00, 0x51, 0x36,
-0x00, 0x00, 0x23, 0x96, 0x60, 0x1B, 0xF6, 0x26, 0xB0, 0x1B, 0xC2, 0x96,
-0xFF, 0xFF, 0x70, 0x30, 0x00, 0x18, 0x10, 0x36, 0x00, 0x00, 0x30, 0xA6,
-0x00, 0x01, 0x42, 0x30, 0xFD, 0xFF, 0x10, 0x32, 0x00, 0x00, 0x30, 0xA6,
-0x05, 0x00, 0x40, 0x10, 0x42, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x43, 0x90,
-0xFB, 0xFF, 0x04, 0x24, 0x24, 0x18, 0x64, 0x00, 0x00, 0x00, 0x43, 0xA0,
-0x04, 0x00, 0x10, 0x36, 0x5B, 0x1F, 0x00, 0x0C, 0x32, 0x00, 0x04, 0x24,
-0x00, 0x00, 0x30, 0xA6, 0x22, 0x00, 0x02, 0x24, 0xF2, 0x02, 0x43, 0x36,
-0xEF, 0xFF, 0x10, 0x32, 0x00, 0x00, 0x30, 0xA6, 0xC8, 0x00, 0x04, 0x24,
-0x00, 0x00, 0x62, 0xA0, 0x5B, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xB0, 0x1B, 0xC2, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30,
-0x41, 0x00, 0x40, 0x10, 0x42, 0xB0, 0x06, 0x3C, 0x84, 0x00, 0x42, 0x36,
-0x00, 0x00, 0x44, 0x8C, 0x80, 0x00, 0x46, 0x36, 0x00, 0x00, 0xC2, 0x8C,
-0x00, 0x28, 0x04, 0x00, 0x21, 0x18, 0x00, 0x00, 0x21, 0x20, 0x00, 0x00,
-0x25, 0x30, 0x82, 0x00, 0x25, 0x38, 0xA3, 0x00, 0x58, 0x41, 0xC3, 0x8E,
-0x23, 0x28, 0xD4, 0x00, 0x80, 0x12, 0x05, 0x00, 0x1B, 0x00, 0x43, 0x00,
-0x02, 0x00, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00,
-0x02, 0x80, 0x0B, 0x3C, 0x14, 0x5E, 0x63, 0x8D, 0x12, 0x10, 0x00, 0x00,
-0x23, 0x10, 0x45, 0x00, 0x21, 0x10, 0x43, 0x00, 0x14, 0x5E, 0x62, 0xAD,
-0x14, 0x5E, 0x63, 0x8D, 0x42, 0xB0, 0x02, 0x3C, 0x03, 0x00, 0x42, 0x34,
-0x58, 0x1B, 0x63, 0x24, 0x14, 0x5E, 0x63, 0xAD, 0x00, 0x00, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x63, 0x30, 0x20, 0x00, 0x60, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x5E, 0x62, 0x8D, 0x02, 0x80, 0x0A, 0x3C,
-0x1C, 0x5E, 0x44, 0x8D, 0x21, 0x40, 0x46, 0x00, 0x2B, 0x28, 0x06, 0x01,
-0x21, 0x48, 0x67, 0x00, 0x21, 0x48, 0x25, 0x01, 0x2B, 0x20, 0x24, 0x01,
-0x59, 0x00, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x5E, 0x42, 0x8D,
-0x00, 0x00, 0x00, 0x00, 0x47, 0x00, 0x49, 0x10, 0x01, 0x00, 0x05, 0x24,
-0x42, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x43, 0x90, 0xFB, 0xFF, 0x04, 0x24,
-0x01, 0x00, 0x06, 0x24, 0x24, 0x18, 0x64, 0x00, 0x00, 0x00, 0x43, 0xA0,
-0x04, 0x00, 0xA0, 0x10, 0x01, 0x00, 0x04, 0x24, 0x80, 0x10, 0x05, 0x00,
-0x21, 0x10, 0x45, 0x00, 0x80, 0x30, 0x02, 0x00, 0xB9, 0x20, 0x00, 0x0C,
-0x21, 0x28, 0x00, 0x00, 0x42, 0xB0, 0x02, 0x3C, 0x22, 0x00, 0x03, 0x24,
-0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0, 0x42, 0xB0, 0x06, 0x3C,
-0x00, 0x00, 0xC2, 0x90, 0x60, 0x1B, 0xE5, 0x26, 0xD0, 0x1B, 0xA8, 0x8C,
-0xDC, 0x1B, 0xA7, 0x94, 0x41, 0xB0, 0x03, 0x3C, 0x41, 0x00, 0x42, 0x34,
-0x08, 0x00, 0x64, 0x34, 0x00, 0x00, 0xC2, 0xA0, 0x00, 0x00, 0x68, 0xAC,
-0x00, 0x00, 0x87, 0xA4, 0xEE, 0x5D, 0x63, 0x92, 0xF0, 0xFF, 0x02, 0x24,
-0xDC, 0x1B, 0xA7, 0xA4, 0x24, 0x18, 0x62, 0x00, 0xEE, 0x5D, 0x63, 0xA2,
-0xEE, 0x5D, 0x62, 0x92, 0xD0, 0x1B, 0xA8, 0xAC, 0x02, 0x00, 0x42, 0x34,
-0xEE, 0x5D, 0x62, 0xA2, 0x72, 0x2E, 0x00, 0x08, 0x02, 0x80, 0x10, 0x3C,
-0x59, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x31, 0xFE, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x0A, 0x2E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xEE, 0x5D, 0x62, 0x92, 0xF0, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0xEE, 0x5D, 0x62, 0xA2, 0xEE, 0x5D, 0x63, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x63, 0x34, 0xEE, 0x5D, 0x63, 0xA2, 0x6C, 0x2E, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x99, 0x99, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x97, 0x99, 0x63, 0x34, 0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x94, 0x2E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x5E, 0x42, 0x8D,
-0x00, 0x00, 0x00, 0x00, 0x2B, 0x10, 0x82, 0x00, 0x0C, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x5E, 0x42, 0x8D, 0x45, 0x2F, 0x00, 0x08,
-0x01, 0x00, 0x05, 0x24, 0x18, 0x5E, 0x42, 0x8D, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x10, 0x02, 0x01, 0x0A, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x5E, 0x42, 0x8D, 0x16, 0x30, 0x00, 0x08, 0x01, 0x00, 0x05, 0x24,
-0x18, 0x5E, 0x42, 0x8D, 0x1C, 0x5E, 0x43, 0x8D, 0x14, 0x5E, 0x64, 0x8D,
-0x23, 0x10, 0x54, 0x00, 0x45, 0x2F, 0x00, 0x08, 0x23, 0x28, 0x44, 0x00,
-0x18, 0x5E, 0x42, 0x8D, 0x1C, 0x5E, 0x43, 0x8D, 0x14, 0x5E, 0x64, 0x8D,
-0x23, 0x10, 0x46, 0x00, 0x16, 0x30, 0x00, 0x08, 0x23, 0x28, 0x44, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xEC, 0x5D, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0x60, 0x10, 0x02, 0x80, 0x02, 0x3C, 0xEE, 0x5D, 0x43, 0x90,
-0x04, 0x00, 0x04, 0x24, 0x0F, 0x00, 0x63, 0x30, 0x04, 0x00, 0x63, 0x28,
-0x03, 0x00, 0x60, 0x14, 0x01, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x4B, 0x2E, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x03, 0x3C, 0xE0, 0xFF, 0xBD, 0x27,
-0xFC, 0xC1, 0x42, 0x24, 0x18, 0x03, 0x63, 0x34, 0x10, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x62, 0xAC, 0x18, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x0C, 0x5E, 0x82, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x40, 0x10, 0x01, 0x00, 0x05, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0xD0, 0x07, 0x03, 0x24, 0x0C, 0x5E, 0x80, 0xA0,
-0x10, 0x00, 0xA4, 0x27, 0x90, 0x40, 0x00, 0x0C, 0xDC, 0x5D, 0x43, 0xAC,
-0x18, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x03, 0x3C, 0x01, 0x00, 0x04, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x0F, 0x5E, 0x44, 0xA0, 0x02, 0x80, 0x02, 0x3C,
-0x0D, 0x5E, 0x60, 0xA0, 0xED, 0x5D, 0x44, 0x90, 0x4B, 0x2E, 0x00, 0x0C,
-0xFF, 0x00, 0x84, 0x30, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x18, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x42, 0x11, 0x05, 0x00, 0x0F, 0x00, 0x46, 0x30,
-0xE8, 0xFF, 0xBD, 0x27, 0x09, 0x00, 0xC3, 0x28, 0x14, 0x00, 0xBF, 0xAF,
-0x14, 0x00, 0x60, 0x10, 0x10, 0x00, 0xB0, 0xAF, 0x82, 0x16, 0x05, 0x00,
-0x01, 0x00, 0x42, 0x30, 0x14, 0x00, 0x40, 0x10, 0x00, 0xC0, 0x02, 0x3C,
-0x24, 0x10, 0xA2, 0x00, 0x43, 0x00, 0x40, 0x14, 0xC2, 0x15, 0x04, 0x00,
-0x01, 0x00, 0x42, 0x30, 0x50, 0x00, 0x40, 0x10, 0x02, 0x80, 0x03, 0x3C,
-0x0C, 0xE5, 0x63, 0x24, 0x21, 0x18, 0xC3, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x08, 0x5E, 0x85, 0x90, 0x00, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x10, 0x45, 0x00, 0x47, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x24, 0x10, 0xA2, 0x00, 0x1E, 0x00, 0x40, 0x10,
-0xC2, 0x15, 0x04, 0x00, 0x02, 0x80, 0x06, 0x3C, 0x07, 0x5E, 0xC2, 0x90,
-0xFD, 0xFF, 0x03, 0x24, 0x42, 0xB0, 0x04, 0x3C, 0x24, 0x10, 0x43, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0xC2, 0xA0, 0x0B, 0x5E, 0x60, 0xA0,
-0x00, 0x00, 0x82, 0x90, 0xEF, 0xFF, 0x03, 0x24, 0x03, 0x00, 0x85, 0x34,
-0x24, 0x10, 0x43, 0x00, 0x40, 0x00, 0x03, 0x24, 0x00, 0x00, 0x82, 0xA0,
-0x00, 0x00, 0xA3, 0xA0, 0x07, 0x5E, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0x42, 0x30, 0xE6, 0xFF, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C,
-0x05, 0x5E, 0x40, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x64, 0x90,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x05, 0x24,
-0xFF, 0x00, 0x84, 0x30, 0x4B, 0x2E, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0x01, 0x00, 0x42, 0x30, 0x25, 0x00, 0x40, 0x10, 0x02, 0x80, 0x03, 0x3C,
-0x0C, 0xE5, 0x63, 0x24, 0x21, 0x18, 0xC3, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x08, 0x5E, 0x85, 0x90, 0x00, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x10, 0x45, 0x00, 0xE7, 0xFF, 0x40, 0x14, 0x02, 0x80, 0x06, 0x3C,
-0x07, 0x5E, 0xC2, 0x90, 0xFE, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0x07, 0x5E, 0xC2, 0xA0, 0xD7, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x42, 0xB0, 0x07, 0x3C, 0x00, 0x00, 0xE3, 0x90, 0xEF, 0xFF, 0x02, 0x24,
-0x03, 0x00, 0xF0, 0x34, 0x24, 0x18, 0x62, 0x00, 0x40, 0x00, 0x02, 0x24,
-0x00, 0x00, 0xE3, 0xA0, 0x02, 0x00, 0x04, 0x24, 0x00, 0x00, 0x02, 0xA2,
-0x21, 0x28, 0x00, 0x00, 0xB9, 0x20, 0x00, 0x0C, 0x00, 0xF0, 0x06, 0x34,
-0x44, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0xA2, 0xC1, 0x30, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x01, 0x00, 0x04, 0x24, 0xE1, 0x51, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0x02, 0x80, 0x06, 0x3C, 0x07, 0x5E, 0xC2, 0x90, 0xFE, 0xFF, 0x03, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x07, 0x5E, 0xC2, 0xA0, 0xD7, 0x30, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x82, 0x16, 0x05, 0x00, 0xE8, 0xFF, 0xBD, 0x27,
-0x01, 0x00, 0x42, 0x30, 0x14, 0x00, 0xBF, 0xAF, 0x0E, 0x00, 0x40, 0x10,
-0x10, 0x00, 0xB0, 0xAF, 0x00, 0xC0, 0x02, 0x3C, 0x24, 0x10, 0xA2, 0x00,
-0x37, 0x00, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x06, 0x5E, 0x43, 0x90,
-0x02, 0x00, 0x02, 0x24, 0xFF, 0x00, 0x63, 0x30, 0x44, 0x00, 0x62, 0x10,
-0x01, 0x00, 0x04, 0x24, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0xE1, 0x51, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27, 0x00, 0xC0, 0x02, 0x3C,
-0x24, 0x10, 0xA2, 0x00, 0x0E, 0x00, 0x40, 0x14, 0x02, 0x80, 0x06, 0x3C,
-0x07, 0x5E, 0xC2, 0x90, 0xFE, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0x07, 0x5E, 0xC2, 0xA0, 0x07, 0x5E, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x00, 0x42, 0x30, 0x18, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x07, 0x5E, 0xC2, 0x90, 0xFD, 0xFF, 0x03, 0x24,
-0x42, 0xB0, 0x04, 0x3C, 0x24, 0x10, 0x43, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x07, 0x5E, 0xC2, 0xA0, 0x0B, 0x5E, 0x60, 0xA0, 0x00, 0x00, 0x82, 0x90,
-0xEF, 0xFF, 0x03, 0x24, 0x03, 0x00, 0x85, 0x34, 0x24, 0x10, 0x43, 0x00,
-0x40, 0x00, 0x03, 0x24, 0x00, 0x00, 0x82, 0xA0, 0x00, 0x00, 0xA3, 0xA0,
-0x07, 0x5E, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x42, 0x30,
-0xEA, 0xFF, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x05, 0x5E, 0x40, 0xA0,
-0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x64, 0x90, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x05, 0x24, 0xFF, 0x00, 0x84, 0x30,
-0x4B, 0x2E, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27, 0x42, 0xB0, 0x07, 0x3C,
-0x00, 0x00, 0xE3, 0x90, 0xEF, 0xFF, 0x02, 0x24, 0x03, 0x00, 0xF0, 0x34,
-0x24, 0x18, 0x62, 0x00, 0x40, 0x00, 0x02, 0x24, 0x00, 0x00, 0xE3, 0xA0,
-0x02, 0x00, 0x04, 0x24, 0x00, 0x00, 0x02, 0xA2, 0x21, 0x28, 0x00, 0x00,
-0xB9, 0x20, 0x00, 0x0C, 0x00, 0xF0, 0x06, 0x34, 0x44, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x02, 0xA2, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xE2, 0x2C, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x0C, 0x00, 0x04, 0x24, 0x01, 0x00, 0x05, 0x24, 0x4B, 0x2E, 0x00, 0x08,
-0x18, 0x00, 0xBD, 0x27, 0x01, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x03, 0x3C,
-0xE8, 0xFF, 0xBD, 0x27, 0xB4, 0xC5, 0x42, 0x24, 0x18, 0x03, 0x63, 0x34,
-0x10, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x62, 0xAC, 0x02, 0x80, 0x10, 0x3C,
-0xED, 0x5D, 0x02, 0x92, 0x14, 0x00, 0xBF, 0xAF, 0x0F, 0x00, 0x42, 0x30,
-0x03, 0x00, 0x42, 0x28, 0x05, 0x00, 0x40, 0x10, 0x01, 0x00, 0x05, 0x24,
-0x59, 0x2D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x40, 0x10,
-0x01, 0x00, 0x05, 0x24, 0xED, 0x5D, 0x04, 0x92, 0x4B, 0x2E, 0x00, 0x0C,
-0xFF, 0x00, 0x84, 0x30, 0x02, 0x80, 0x04, 0x3C, 0x60, 0x1B, 0x84, 0x24,
-0xE0, 0x1B, 0x83, 0x94, 0xDC, 0x1B, 0x85, 0x94, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x02, 0x00, 0x63, 0x30, 0x41, 0xB0, 0x02, 0x3C,
-0x25, 0x18, 0x65, 0x00, 0x08, 0x00, 0x42, 0x34, 0x18, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0x43, 0xA4, 0x08, 0x00, 0xE0, 0x03, 0xDC, 0x1B, 0x83, 0xA4,
-0xE0, 0xFF, 0xBD, 0x27, 0x25, 0xB0, 0x02, 0x3C, 0x01, 0x80, 0x03, 0x3C,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x1C, 0x00, 0xBF, 0xAF, 0x18, 0x03, 0x52, 0x34, 0x40, 0xC6, 0x71, 0x24,
-0x02, 0x80, 0x10, 0x3C, 0x08, 0x14, 0x04, 0x26, 0x21, 0x28, 0x00, 0x00,
-0x21, 0x30, 0x00, 0x00, 0x21, 0x38, 0x00, 0x00, 0x00, 0x00, 0x51, 0xAE,
-0x76, 0x39, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x9B, 0x31, 0x00, 0x08,
-0x08, 0x14, 0x04, 0x26, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0xFF, 0xFF, 0x90, 0x30, 0x1C, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x06, 0x3C, 0x60, 0x1B, 0xCD, 0x24,
-0x2A, 0x1C, 0xA2, 0x91, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x40, 0x10,
-0x2A, 0xB0, 0x02, 0x3C, 0x25, 0xB0, 0x03, 0x3C, 0x38, 0x02, 0x64, 0x34,
-0x80, 0xFF, 0x02, 0x24, 0x00, 0x00, 0x82, 0xA0, 0x34, 0x02, 0x6A, 0x34,
-0xD2, 0x01, 0x65, 0x34, 0xD6, 0x01, 0x66, 0x34, 0xDA, 0x01, 0x67, 0x34,
-0xDE, 0x01, 0x63, 0x34, 0x00, 0x00, 0xA8, 0x94, 0x00, 0x00, 0xC9, 0x94,
-0x00, 0x00, 0xEB, 0x94, 0x00, 0x00, 0x6C, 0x94, 0x00, 0x00, 0x44, 0x95,
-0xB0, 0xFE, 0x02, 0x26, 0xFF, 0xFF, 0x50, 0x30, 0x28, 0x1C, 0xA4, 0xA5,
-0x00, 0x00, 0xA0, 0xA4, 0x10, 0x00, 0xA4, 0x27, 0x20, 0x1C, 0xA8, 0xA5,
-0x00, 0x00, 0xC0, 0xA4, 0x22, 0x1C, 0xA9, 0xA5, 0x00, 0x00, 0xE0, 0xA4,
-0x24, 0x1C, 0xAB, 0xA5, 0x00, 0x00, 0x60, 0xA4, 0x00, 0x00, 0x50, 0xA5,
-0x90, 0x40, 0x00, 0x0C, 0x26, 0x1C, 0xAC, 0xA5, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x0A, 0x00, 0x45, 0x34, 0x63, 0x00, 0x03, 0x24, 0xFF, 0xFF, 0x04, 0x34,
-0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x40, 0x10,
-0x64, 0x00, 0x02, 0x24, 0xFF, 0xFF, 0x42, 0x24, 0xFF, 0xFF, 0x42, 0x30,
-0xFE, 0xFF, 0x40, 0x14, 0xFF, 0xFF, 0x42, 0x24, 0xFF, 0xFF, 0x62, 0x24,
-0xFF, 0xFF, 0x43, 0x30, 0xF5, 0xFF, 0x64, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0xC2, 0x24, 0x28, 0x1C, 0x48, 0x94, 0x26, 0x1C, 0x47, 0x94,
-0x20, 0x1C, 0x49, 0x94, 0x22, 0x1C, 0x4A, 0x94, 0x24, 0x1C, 0x4B, 0x94,
-0x25, 0xB0, 0x03, 0x3C, 0x38, 0x02, 0x6C, 0x34, 0x34, 0x02, 0x62, 0x34,
-0xD2, 0x01, 0x64, 0x34, 0xD6, 0x01, 0x65, 0x34, 0xDA, 0x01, 0x66, 0x34,
-0xDE, 0x01, 0x63, 0x34, 0x00, 0x00, 0x48, 0xA4, 0x00, 0x00, 0x89, 0xA4,
-0x00, 0x00, 0xAA, 0xA4, 0x10, 0x00, 0xA4, 0x27, 0x00, 0x00, 0xCB, 0xA4,
-0x00, 0x00, 0x67, 0xA4, 0x00, 0x00, 0x80, 0xA1, 0x90, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xD0, 0xFF, 0xBD, 0x27,
-0x28, 0x00, 0xB4, 0xAF, 0x2C, 0x00, 0xBF, 0xAF, 0x24, 0x00, 0xB3, 0xAF,
-0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF,
-0xFF, 0xFF, 0x14, 0x24, 0x02, 0x80, 0x13, 0x3C, 0x41, 0xB0, 0x02, 0x3C,
-0x60, 0x1B, 0x63, 0x26, 0x04, 0x00, 0x42, 0x34, 0x00, 0x00, 0x45, 0x8C,
-0xD4, 0x1B, 0x64, 0x8C, 0xD0, 0x1B, 0x66, 0x8C, 0x02, 0x80, 0x02, 0x3C,
-0xF0, 0x5C, 0x47, 0x90, 0x25, 0xB0, 0x08, 0x3C, 0xB0, 0x03, 0x02, 0x35,
-0x25, 0x90, 0x85, 0x00, 0x00, 0x00, 0x52, 0xAC, 0x00, 0x00, 0x46, 0xAC,
-0x01, 0x00, 0x02, 0x24, 0x89, 0x03, 0xE2, 0x10, 0xD4, 0x1B, 0x72, 0xAC,
-0x60, 0x1B, 0x64, 0x26, 0xD0, 0x1B, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x10, 0x52, 0x00, 0x01, 0x00, 0x42, 0x30, 0x0E, 0x00, 0x40, 0x10,
-0x60, 0x1B, 0x67, 0x26, 0x25, 0xB0, 0x10, 0x3C, 0xB0, 0x03, 0x02, 0x36,
-0x01, 0x00, 0x05, 0x24, 0x00, 0x00, 0x45, 0xAC, 0x04, 0x00, 0x0B, 0x36,
-0xD4, 0x1B, 0x83, 0x8C, 0x00, 0x00, 0x69, 0x8D, 0x40, 0x00, 0x02, 0x3C,
-0x01, 0x00, 0x63, 0x38, 0x24, 0x10, 0x22, 0x01, 0x26, 0x01, 0x40, 0x10,
-0xD4, 0x1B, 0x83, 0xAC, 0x60, 0x1B, 0x67, 0x26, 0xD0, 0x1B, 0xE2, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x52, 0x00, 0x04, 0x00, 0x42, 0x30,
-0x14, 0x00, 0x40, 0x10, 0x60, 0x1B, 0x71, 0x26, 0x25, 0xB0, 0x03, 0x3C,
-0xB0, 0x03, 0x64, 0x34, 0x04, 0x00, 0x02, 0x24, 0x00, 0x00, 0x82, 0xAC,
-0xD4, 0x1B, 0xE2, 0x8C, 0xC4, 0x38, 0xE6, 0x8C, 0xFC, 0x00, 0x63, 0x34,
-0xAC, 0x1B, 0xE4, 0x94, 0x00, 0x00, 0x65, 0x8C, 0x04, 0x00, 0x42, 0x38,
-0x21, 0x48, 0xC4, 0x00, 0x06, 0x00, 0xA9, 0x10, 0xD4, 0x1B, 0xE2, 0xAC,
-0x02, 0x80, 0x03, 0x3C, 0xB0, 0x5D, 0x62, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x42, 0x34, 0xB0, 0x5D, 0x62, 0xAC, 0x60, 0x1B, 0x71, 0x26,
-0xD0, 0x1B, 0x22, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x52, 0x00,
-0x08, 0x00, 0x42, 0x30, 0x0A, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xB0, 0x1B, 0x22, 0x96, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x42, 0x30,
-0x5D, 0x03, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0xD4, 0x1B, 0x22, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x42, 0x38, 0xD4, 0x1B, 0x22, 0xAE,
-0x60, 0x1B, 0x70, 0x26, 0xD0, 0x1B, 0x02, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x20, 0x52, 0x00, 0x00, 0x08, 0x83, 0x30, 0x06, 0x00, 0x60, 0x10,
-0x00, 0x10, 0x82, 0x30, 0xD4, 0x1B, 0x02, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x08, 0x42, 0x38, 0xD4, 0x1B, 0x02, 0xAE, 0x00, 0x10, 0x82, 0x30,
-0x05, 0x03, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x70, 0x26,
-0xD0, 0x1B, 0x03, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x72, 0x00,
-0x00, 0x20, 0x42, 0x30, 0xF7, 0x02, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x10, 0x72, 0x00, 0x00, 0x80, 0x42, 0x30, 0xB9, 0x01, 0x40, 0x14,
-0x01, 0x00, 0x03, 0x3C, 0x60, 0x1B, 0x70, 0x26, 0xD0, 0x1B, 0x02, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x52, 0x00, 0x24, 0x10, 0x54, 0x00,
-0x24, 0x10, 0x43, 0x00, 0xF1, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0xD0, 0x1B, 0x02, 0x8E, 0x02, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x43, 0x00, 0x28, 0x02, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x70, 0x26, 0xD0, 0x1B, 0x02, 0x8E, 0x04, 0x00, 0x03, 0x3C,
-0x24, 0x10, 0x52, 0x00, 0x24, 0x10, 0x54, 0x00, 0x24, 0x10, 0x43, 0x00,
-0x62, 0x02, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x70, 0x26,
-0xD0, 0x1B, 0x02, 0x8E, 0x08, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x43, 0x00, 0x9B, 0x02, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x70, 0x26, 0xD0, 0x1B, 0x02, 0x8E, 0x10, 0x00, 0x03, 0x3C,
-0x24, 0x10, 0x52, 0x00, 0x24, 0x10, 0x54, 0x00, 0x24, 0x10, 0x43, 0x00,
-0x5A, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x70, 0x26,
-0xD0, 0x1B, 0x02, 0x8E, 0x20, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x43, 0x00, 0x18, 0x01, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x70, 0x26, 0xD0, 0x1B, 0x02, 0x8E, 0x40, 0x00, 0x03, 0x3C,
-0x24, 0x10, 0x52, 0x00, 0x24, 0x10, 0x54, 0x00, 0x24, 0x10, 0x43, 0x00,
-0xD6, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x65, 0x26,
-0xD0, 0x1B, 0xA2, 0x8C, 0x00, 0x04, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x43, 0x00, 0x3D, 0x00, 0x40, 0x10, 0x60, 0x1B, 0x66, 0x26,
-0x2A, 0xB0, 0x02, 0x3C, 0x2C, 0x00, 0x43, 0x34, 0x00, 0x00, 0x69, 0x8C,
-0xFF, 0x00, 0x02, 0x24, 0xFF, 0x00, 0x24, 0x31, 0x29, 0x03, 0x82, 0x10,
-0x00, 0x80, 0x22, 0x31, 0xF9, 0x02, 0x40, 0x14, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0xFF, 0x02, 0x3C, 0x24, 0x10, 0x22, 0x01, 0x0B, 0x00, 0x40, 0x10,
-0xFF, 0x00, 0x02, 0x24, 0xAC, 0x37, 0xA2, 0x90, 0x20, 0xB0, 0x03, 0x3C,
-0x00, 0x12, 0x02, 0x00, 0x21, 0x10, 0x43, 0x00, 0x0C, 0x00, 0x49, 0x8C,
-0x25, 0xB0, 0x03, 0x3C, 0xB0, 0x03, 0x63, 0x34, 0x00, 0x00, 0x69, 0xAC,
-0xFF, 0x00, 0x24, 0x31, 0xFF, 0x00, 0x02, 0x24, 0x1B, 0x00, 0x82, 0x10,
-0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31, 0x7C, 0x38, 0x05, 0x8E,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x21, 0x30, 0x60, 0x00, 0x10, 0x38, 0x03, 0xAE, 0x0A, 0x00, 0x04, 0x24,
-0xAC, 0x37, 0x09, 0xA2, 0x00, 0x01, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0xD0, 0x1B, 0x05, 0x8E, 0x02, 0x80, 0x06, 0x3C,
-0xB0, 0x5D, 0xC4, 0x8C, 0x00, 0x04, 0x02, 0x3C, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x28, 0xA2, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0x00, 0x80, 0x84, 0x34,
-0xB0, 0x03, 0x42, 0x34, 0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x44, 0xAC,
-0x00, 0x00, 0x65, 0xAC, 0xB0, 0x5D, 0xC4, 0xAC, 0xD0, 0x1B, 0x05, 0xAE,
-0x60, 0x1B, 0x65, 0x26, 0xD4, 0x1B, 0xA4, 0x8C, 0x00, 0x04, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x26, 0x20, 0x83, 0x00, 0xB0, 0x03, 0x42, 0x34,
-0x00, 0x00, 0x44, 0xAC, 0xD4, 0x1B, 0xA4, 0xAC, 0x60, 0x1B, 0x66, 0x26,
-0xD0, 0x1B, 0xC7, 0x8C, 0x00, 0x08, 0x04, 0x3C, 0x24, 0x28, 0xF2, 0x00,
-0x24, 0x10, 0xA4, 0x00, 0x08, 0x00, 0x40, 0x10, 0x80, 0x00, 0x08, 0x3C,
-0xD4, 0x1B, 0xC3, 0x8C, 0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34,
-0x26, 0x18, 0x64, 0x00, 0x00, 0x00, 0x44, 0xAC, 0xD4, 0x1B, 0xC3, 0xAC,
-0x80, 0x00, 0x08, 0x3C, 0x24, 0x10, 0xA8, 0x00, 0x21, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xD4, 0x1B, 0xC3, 0x8C, 0x25, 0xB0, 0x09, 0x3C,
-0xB0, 0x03, 0x2A, 0x35, 0x2A, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x43, 0xAD,
-0x36, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0x90, 0x23, 0xB0, 0x04, 0x3C,
-0xFF, 0x1F, 0x02, 0x3C, 0xC0, 0x18, 0x03, 0x00, 0xF0, 0x07, 0x63, 0x30,
-0xF4, 0x38, 0xC5, 0x8C, 0x21, 0x18, 0x64, 0x00, 0xFF, 0xFF, 0x42, 0x34,
-0x24, 0x18, 0x62, 0x00, 0xCE, 0x02, 0x65, 0x10, 0xF8, 0x38, 0xC3, 0xAC,
-0x02, 0x80, 0x05, 0x3C, 0xB0, 0x5D, 0xA3, 0x8C, 0x27, 0x20, 0x08, 0x00,
-0x24, 0x20, 0xE4, 0x00, 0x00, 0x10, 0x63, 0x34, 0x41, 0xB0, 0x02, 0x3C,
-0x00, 0x00, 0x43, 0xAD, 0x00, 0x00, 0x44, 0xAC, 0xB0, 0x5D, 0xA3, 0xAC,
-0xD0, 0x1B, 0xC4, 0xAC, 0x60, 0x1B, 0x62, 0x26, 0xD4, 0x1B, 0x43, 0x8C,
-0x80, 0x00, 0x04, 0x3C, 0x26, 0x18, 0x64, 0x00, 0xD4, 0x1B, 0x43, 0xAC,
-0x60, 0x1B, 0x66, 0x26, 0xD0, 0x1B, 0xC3, 0x8C, 0x00, 0x01, 0x05, 0x3C,
-0x24, 0x20, 0x72, 0x00, 0x24, 0x10, 0x85, 0x00, 0x06, 0x00, 0x40, 0x10,
-0x25, 0xB0, 0x02, 0x3C, 0xD4, 0x1B, 0xC3, 0x8C, 0xB0, 0x03, 0x42, 0x34,
-0x26, 0x18, 0x65, 0x00, 0x00, 0x00, 0x45, 0xAC, 0xD4, 0x1B, 0xC3, 0xAC,
-0x00, 0x02, 0x05, 0x3C, 0x24, 0x10, 0x85, 0x00, 0x06, 0x00, 0x40, 0x10,
-0x25, 0xB0, 0x02, 0x3C, 0xD4, 0x1B, 0xC3, 0x8C, 0xB0, 0x03, 0x42, 0x34,
-0x26, 0x18, 0x65, 0x00, 0x00, 0x00, 0x45, 0xAC, 0xD4, 0x1B, 0xC3, 0xAC,
-0x00, 0x10, 0x05, 0x3C, 0x24, 0x10, 0x85, 0x00, 0x0C, 0x00, 0x40, 0x10,
-0x60, 0x1B, 0x63, 0x26, 0xB0, 0x1B, 0xC3, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x62, 0x30, 0x02, 0x00, 0x40, 0x10, 0x00, 0x08, 0x62, 0x34,
-0xB0, 0x1B, 0xC2, 0xA4, 0xD4, 0x1B, 0xC2, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x26, 0x10, 0x45, 0x00, 0xD4, 0x1B, 0xC2, 0xAC, 0x60, 0x1B, 0x63, 0x26,
-0xD0, 0x1B, 0x62, 0x8C, 0x00, 0x20, 0x05, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x45, 0x00, 0x0B, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xB0, 0x1B, 0x64, 0x94, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x82, 0x30,
-0x02, 0x00, 0x40, 0x10, 0xFF, 0xF7, 0x82, 0x30, 0xB0, 0x1B, 0x62, 0xA4,
-0xD4, 0x1B, 0x62, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x26, 0x10, 0x45, 0x00,
-0xD4, 0x1B, 0x62, 0xAC, 0x2C, 0x00, 0xBF, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0x20, 0xBD, 0x02, 0x3C, 0xEC, 0x02, 0x03, 0x36, 0x4D, 0x00, 0x07, 0x36,
-0xF1, 0x02, 0x08, 0x36, 0x08, 0x00, 0x06, 0x24, 0x78, 0x02, 0x42, 0x34,
-0x00, 0x00, 0x45, 0xA4, 0x00, 0x00, 0xE0, 0xA0, 0x00, 0x00, 0x06, 0xA1,
-0x00, 0x00, 0x60, 0xAC, 0x00, 0x00, 0x62, 0x8C, 0xFF, 0x00, 0x04, 0x3C,
-0x00, 0x00, 0xE0, 0xA0, 0xFF, 0x00, 0x49, 0x30, 0x25, 0x48, 0x24, 0x01,
-0x00, 0x00, 0x06, 0xA1, 0xF2, 0x02, 0x05, 0x36, 0x00, 0x00, 0x64, 0xAC,
-0x0A, 0x00, 0x0A, 0x36, 0x00, 0x00, 0x69, 0xAC, 0x80, 0xFF, 0x03, 0x24,
-0x00, 0x00, 0xA0, 0xA0, 0x00, 0x00, 0x43, 0xA1, 0x00, 0x00, 0x62, 0x8D,
-0x80, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x43, 0x00, 0x02, 0x00, 0x40, 0x10,
-0x84, 0xFF, 0x02, 0x24, 0x00, 0x00, 0x42, 0xA1, 0x2C, 0x1F, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0x02, 0x00, 0x02, 0x36, 0x00, 0x00, 0x43, 0x94,
-0xFF, 0xBF, 0x04, 0x24, 0x24, 0x18, 0x64, 0x00, 0x00, 0x00, 0x43, 0xA4,
-0x25, 0x32, 0x00, 0x08, 0x60, 0x1B, 0x67, 0x26, 0x70, 0x30, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0x2A, 0xB0, 0x06, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0x00, 0x00, 0x54, 0xAC, 0x28, 0x00, 0xC3, 0x34,
-0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x05, 0x24, 0xFF, 0x00, 0x24, 0x31,
-0x6D, 0x03, 0x85, 0x10, 0x25, 0xBD, 0x02, 0x3C, 0x00, 0x80, 0x22, 0x31,
-0x59, 0x02, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24, 0x21, 0x00, 0x82, 0x10,
-0xFF, 0x00, 0x23, 0x31, 0x60, 0x1B, 0x70, 0x26, 0x4C, 0x38, 0x05, 0x8E,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x21, 0x30, 0x60, 0x00, 0x98, 0x37, 0x09, 0xA2, 0xE0, 0x37, 0x03, 0xAE,
-0x06, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x09, 0x3C, 0xC0, 0x5D, 0x27, 0x91,
-0x02, 0x80, 0x08, 0x3C, 0xB0, 0x5D, 0x05, 0x8D, 0xD0, 0x1B, 0x06, 0x8E,
-0x60, 0x00, 0x02, 0x3C, 0x02, 0x00, 0xE7, 0x34, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x30, 0xC2, 0x00, 0x00, 0x08, 0xA5, 0x34, 0x00, 0x26, 0x07, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x25, 0x20, 0x85, 0x00, 0x80, 0x03, 0x42, 0x34,
-0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x66, 0xAC,
-0xB0, 0x5D, 0x05, 0xAD, 0xC0, 0x5D, 0x27, 0xA1, 0xD0, 0x1B, 0x06, 0xAE,
-0x60, 0x1B, 0x62, 0x26, 0xD4, 0x1B, 0x43, 0x8C, 0x40, 0x00, 0x04, 0x3C,
-0x26, 0x18, 0x64, 0x00, 0x9A, 0x32, 0x00, 0x08, 0xD4, 0x1B, 0x43, 0xAC,
-0x70, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x05, 0x3C,
-0x24, 0x00, 0xA3, 0x34, 0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x06, 0x24,
-0xFF, 0x00, 0x24, 0x31, 0x48, 0x03, 0x86, 0x10, 0x25, 0xB0, 0x02, 0x3C,
-0x00, 0x80, 0x22, 0x31, 0x64, 0x02, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24,
-0x25, 0x00, 0x82, 0x10, 0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31,
-0x4C, 0x38, 0x05, 0x8E, 0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x21, 0x30, 0x60, 0x00, 0x94, 0x37, 0x09, 0xA2,
-0xE0, 0x37, 0x03, 0xAE, 0x06, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x0A, 0x3C,
-0xC0, 0x5D, 0x47, 0x91, 0x02, 0x80, 0x09, 0x3C, 0xB0, 0x5D, 0x25, 0x8D,
-0xD0, 0x1B, 0x06, 0x8E, 0x60, 0x00, 0x02, 0x3C, 0x04, 0x00, 0xE7, 0x34,
-0x27, 0x10, 0x02, 0x00, 0x24, 0x30, 0xC2, 0x00, 0x00, 0x08, 0xA5, 0x34,
-0x25, 0xB0, 0x03, 0x3C, 0x40, 0x00, 0x02, 0x3C, 0x00, 0x26, 0x07, 0x00,
-0x26, 0xA0, 0x82, 0x02, 0xB0, 0x03, 0x68, 0x34, 0x25, 0x20, 0x85, 0x00,
-0x80, 0x03, 0x63, 0x34, 0x41, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x64, 0xAC,
-0x00, 0x00, 0x46, 0xAC, 0xB0, 0x5D, 0x25, 0xAD, 0xC0, 0x5D, 0x47, 0xA1,
-0xD0, 0x1B, 0x06, 0xAE, 0x00, 0x00, 0x14, 0xAD, 0x60, 0x1B, 0x62, 0x26,
-0xD4, 0x1B, 0x43, 0x8C, 0x20, 0x00, 0x04, 0x3C, 0x26, 0x18, 0x64, 0x00,
-0x92, 0x32, 0x00, 0x08, 0xD4, 0x1B, 0x43, 0xAC, 0x70, 0x30, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x05, 0x3C, 0xB0, 0x03, 0xA2, 0x34,
-0x2A, 0xB0, 0x07, 0x3C, 0x00, 0x00, 0x54, 0xAC, 0x20, 0x00, 0xE3, 0x34,
-0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x06, 0x24, 0xFF, 0x00, 0x24, 0x31,
-0x07, 0x03, 0x86, 0x10, 0x90, 0x03, 0xA2, 0x34, 0x00, 0x80, 0x22, 0x31,
-0x05, 0x02, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24, 0x21, 0x00, 0x82, 0x10,
-0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31, 0x40, 0x38, 0x05, 0x8E,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x21, 0x30, 0x60, 0x00, 0x9C, 0x37, 0x09, 0xA2, 0xD4, 0x37, 0x03, 0xAE,
-0x05, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x09, 0x3C, 0xC0, 0x5D, 0x27, 0x91,
-0x02, 0x80, 0x08, 0x3C, 0xB0, 0x5D, 0x05, 0x8D, 0xD0, 0x1B, 0x06, 0x8E,
-0x18, 0x00, 0x02, 0x3C, 0x01, 0x00, 0xE7, 0x34, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x30, 0xC2, 0x00, 0x00, 0x04, 0xA5, 0x34, 0x00, 0x26, 0x07, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x25, 0x20, 0x85, 0x00, 0x80, 0x03, 0x42, 0x34,
-0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x66, 0xAC,
-0xB0, 0x5D, 0x05, 0xAD, 0xC0, 0x5D, 0x27, 0xA1, 0xD0, 0x1B, 0x06, 0xAE,
-0x60, 0x1B, 0x62, 0x26, 0xD4, 0x1B, 0x43, 0x8C, 0x10, 0x00, 0x04, 0x3C,
-0x26, 0x18, 0x64, 0x00, 0x8B, 0x32, 0x00, 0x08, 0xD4, 0x1B, 0x43, 0xAC,
-0x70, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x05, 0x3C,
-0x0C, 0x00, 0xA3, 0x34, 0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x06, 0x24,
-0xFF, 0x00, 0x24, 0x31, 0xC6, 0x02, 0x86, 0x10, 0x00, 0x80, 0x22, 0x31,
-0x54, 0x02, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24, 0x24, 0x00, 0x82, 0x10,
-0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31, 0x28, 0x38, 0x05, 0x8E,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x21, 0x30, 0x60, 0x00, 0x80, 0x37, 0x09, 0xA2, 0xBC, 0x37, 0x03, 0xAE,
-0x03, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x0A, 0x3C, 0xC0, 0x5D, 0x47, 0x91,
-0x02, 0x80, 0x09, 0x3C, 0xB0, 0x5D, 0x25, 0x8D, 0xD0, 0x1B, 0x06, 0x8E,
-0x01, 0x00, 0x08, 0x3C, 0x80, 0xFF, 0x02, 0x24, 0x25, 0x38, 0xE2, 0x00,
-0x00, 0x80, 0x03, 0x35, 0x00, 0x01, 0xA5, 0x34, 0x27, 0x18, 0x03, 0x00,
-0x00, 0x26, 0x07, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0x24, 0x30, 0xC3, 0x00,
-0x25, 0x20, 0x85, 0x00, 0x80, 0x03, 0x42, 0x34, 0x41, 0xB0, 0x03, 0x3C,
-0x00, 0x00, 0x44, 0xAC, 0x27, 0xA0, 0x08, 0x00, 0x00, 0x00, 0x66, 0xAC,
-0xB0, 0x5D, 0x25, 0xAD, 0xC0, 0x5D, 0x47, 0xA1, 0xD0, 0x1B, 0x06, 0xAE,
-0x60, 0x1B, 0x63, 0x26, 0xD4, 0x1B, 0x62, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x80, 0x42, 0x38, 0xD4, 0x1B, 0x62, 0xAC, 0x60, 0x1B, 0x70, 0x26,
-0xD0, 0x1B, 0x02, 0x8E, 0x01, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x54, 0x00, 0x24, 0x10, 0x43, 0x00, 0x11, 0xFE, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x70, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x2A, 0xB0, 0x05, 0x3C, 0x10, 0x00, 0xA3, 0x34, 0x00, 0x00, 0x69, 0x8C,
-0xFF, 0x00, 0x06, 0x24, 0xFF, 0x00, 0x24, 0x31, 0x7C, 0x02, 0x86, 0x10,
-0x25, 0xB0, 0x02, 0x3C, 0x00, 0x80, 0x22, 0x31, 0xD0, 0x01, 0x40, 0x10,
-0x00, 0x80, 0x02, 0x3C, 0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24,
-0x22, 0x00, 0x82, 0x10, 0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31,
-0x28, 0x38, 0x05, 0x8E, 0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x21, 0x30, 0x60, 0x00, 0x84, 0x37, 0x09, 0xA2,
-0xBC, 0x37, 0x03, 0xAE, 0x03, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x09, 0x3C,
-0xC0, 0x5D, 0x27, 0x91, 0x02, 0x80, 0x08, 0x3C, 0xB0, 0x5D, 0x05, 0x8D,
-0xD0, 0x1B, 0x06, 0x8E, 0x01, 0x00, 0x02, 0x3C, 0x00, 0x80, 0x42, 0x34,
-0x40, 0x00, 0xE7, 0x34, 0x27, 0x10, 0x02, 0x00, 0x24, 0x30, 0xC2, 0x00,
-0x00, 0x01, 0xA5, 0x34, 0x00, 0x26, 0x07, 0x00, 0x25, 0xB0, 0x02, 0x3C,
-0x25, 0x20, 0x85, 0x00, 0x80, 0x03, 0x42, 0x34, 0x41, 0xB0, 0x03, 0x3C,
-0x00, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x66, 0xAC, 0xB0, 0x5D, 0x05, 0xAD,
-0xC0, 0x5D, 0x27, 0xA1, 0xD0, 0x1B, 0x06, 0xAE, 0x60, 0x1B, 0x62, 0x26,
-0xD4, 0x1B, 0x43, 0x8C, 0x01, 0x00, 0x04, 0x3C, 0x60, 0x1B, 0x70, 0x26,
-0x26, 0x18, 0x64, 0x00, 0xD4, 0x1B, 0x43, 0xAC, 0xD0, 0x1B, 0x02, 0x8E,
-0x02, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00, 0x24, 0x10, 0x43, 0x00,
-0xDB, 0xFD, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x70, 0x30, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x05, 0x3C, 0x14, 0x00, 0xA3, 0x34,
-0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x06, 0x24, 0xFF, 0x00, 0x24, 0x31,
-0x64, 0x02, 0x86, 0x10, 0x25, 0xB0, 0x02, 0x3C, 0x00, 0x80, 0x22, 0x31,
-0xFA, 0x01, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24, 0x25, 0x00, 0x82, 0x10,
-0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31, 0x34, 0x38, 0x05, 0x8E,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x21, 0x30, 0x60, 0x00, 0x88, 0x37, 0x09, 0xA2, 0xC8, 0x37, 0x03, 0xAE,
-0x04, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x0A, 0x3C, 0xC0, 0x5D, 0x47, 0x91,
-0x02, 0x80, 0x09, 0x3C, 0xB0, 0x5D, 0x25, 0x8D, 0xD0, 0x1B, 0x06, 0x8E,
-0x06, 0x00, 0x02, 0x3C, 0x20, 0x00, 0xE7, 0x34, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x30, 0xC2, 0x00, 0x00, 0x02, 0xA5, 0x34, 0x25, 0xB0, 0x03, 0x3C,
-0x04, 0x00, 0x02, 0x3C, 0x00, 0x26, 0x07, 0x00, 0x26, 0xA0, 0x82, 0x02,
-0xB0, 0x03, 0x68, 0x34, 0x25, 0x20, 0x85, 0x00, 0x80, 0x03, 0x63, 0x34,
-0x41, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x64, 0xAC, 0x00, 0x00, 0x46, 0xAC,
-0xB0, 0x5D, 0x25, 0xAD, 0xC0, 0x5D, 0x47, 0xA1, 0xD0, 0x1B, 0x06, 0xAE,
-0x00, 0x00, 0x14, 0xAD, 0x60, 0x1B, 0x62, 0x26, 0xD4, 0x1B, 0x43, 0x8C,
-0x02, 0x00, 0x04, 0x3C, 0x60, 0x1B, 0x70, 0x26, 0x26, 0x18, 0x64, 0x00,
-0xD4, 0x1B, 0x43, 0xAC, 0xD0, 0x1B, 0x02, 0x8E, 0x04, 0x00, 0x03, 0x3C,
-0x24, 0x10, 0x52, 0x00, 0x24, 0x10, 0x54, 0x00, 0x24, 0x10, 0x43, 0x00,
-0xA1, 0xFD, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x70, 0x30, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x03, 0x3C, 0xB0, 0x03, 0x62, 0x34,
-0x2A, 0xB0, 0x07, 0x3C, 0x00, 0x00, 0x54, 0xAC, 0x18, 0x00, 0xE5, 0x34,
-0x00, 0x00, 0xA9, 0x8C, 0xFF, 0x00, 0x06, 0x24, 0xFF, 0x00, 0x24, 0x31,
-0x16, 0x02, 0x86, 0x10, 0x04, 0x00, 0x02, 0x24, 0x00, 0x80, 0x22, 0x31,
-0xD6, 0x01, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0xA2, 0xAC, 0xFF, 0x00, 0x02, 0x24, 0x21, 0x00, 0x82, 0x10,
-0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31, 0x34, 0x38, 0x05, 0x8E,
-0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00,
-0x21, 0x30, 0x60, 0x00, 0x8C, 0x37, 0x09, 0xA2, 0xC8, 0x37, 0x03, 0xAE,
-0x04, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C,
-0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x09, 0x3C, 0xC0, 0x5D, 0x27, 0x91,
-0x02, 0x80, 0x08, 0x3C, 0xB0, 0x5D, 0x05, 0x8D, 0xD0, 0x1B, 0x06, 0x8E,
-0x06, 0x00, 0x02, 0x3C, 0x10, 0x00, 0xE7, 0x34, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x30, 0xC2, 0x00, 0x00, 0x02, 0xA5, 0x34, 0x00, 0x26, 0x07, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x25, 0x20, 0x85, 0x00, 0x80, 0x03, 0x42, 0x34,
-0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x66, 0xAC,
-0xB0, 0x5D, 0x05, 0xAD, 0xC0, 0x5D, 0x27, 0xA1, 0xD0, 0x1B, 0x06, 0xAE,
-0x60, 0x1B, 0x62, 0x26, 0xD4, 0x1B, 0x43, 0x8C, 0x04, 0x00, 0x04, 0x3C,
-0x60, 0x1B, 0x70, 0x26, 0x26, 0x18, 0x64, 0x00, 0xD4, 0x1B, 0x43, 0xAC,
-0xD0, 0x1B, 0x02, 0x8E, 0x08, 0x00, 0x03, 0x3C, 0x24, 0x10, 0x52, 0x00,
-0x24, 0x10, 0x43, 0x00, 0x68, 0xFD, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x70, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x05, 0x3C,
-0x1C, 0x00, 0xA3, 0x34, 0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x06, 0x24,
-0xFF, 0x00, 0x24, 0x31, 0xDD, 0x01, 0x86, 0x10, 0x25, 0xB0, 0x02, 0x3C,
-0x00, 0x80, 0x22, 0x31, 0x33, 0x01, 0x40, 0x10, 0x00, 0xFF, 0x02, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0x00, 0x00, 0x62, 0xAC, 0xFF, 0x00, 0x02, 0x24,
-0x25, 0x00, 0x82, 0x10, 0x60, 0x1B, 0x70, 0x26, 0xFF, 0x00, 0x23, 0x31,
-0x40, 0x38, 0x05, 0x8E, 0x20, 0x10, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x21, 0x30, 0x60, 0x00, 0x90, 0x37, 0x09, 0xA2,
-0xD4, 0x37, 0x03, 0xAE, 0x05, 0x00, 0x04, 0x24, 0x80, 0x00, 0x07, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF, 0x02, 0x80, 0x0A, 0x3C,
-0xC0, 0x5D, 0x47, 0x91, 0x02, 0x80, 0x09, 0x3C, 0xB0, 0x5D, 0x25, 0x8D,
-0xD0, 0x1B, 0x06, 0x8E, 0x18, 0x00, 0x02, 0x3C, 0x08, 0x00, 0xE7, 0x34,
-0x27, 0x10, 0x02, 0x00, 0x24, 0x30, 0xC2, 0x00, 0x00, 0x04, 0xA5, 0x34,
-0x25, 0xB0, 0x03, 0x3C, 0x10, 0x00, 0x02, 0x3C, 0x00, 0x26, 0x07, 0x00,
-0x26, 0xA0, 0x82, 0x02, 0xB0, 0x03, 0x68, 0x34, 0x25, 0x20, 0x85, 0x00,
-0x80, 0x03, 0x63, 0x34, 0x41, 0xB0, 0x02, 0x3C, 0x00, 0x00, 0x64, 0xAC,
-0x00, 0x00, 0x46, 0xAC, 0xB0, 0x5D, 0x25, 0xAD, 0xC0, 0x5D, 0x47, 0xA1,
-0xD0, 0x1B, 0x06, 0xAE, 0x00, 0x00, 0x14, 0xAD, 0x60, 0x1B, 0x62, 0x26,
-0xD4, 0x1B, 0x43, 0x8C, 0x08, 0x00, 0x04, 0x3C, 0x26, 0x18, 0x64, 0x00,
-0x83, 0x32, 0x00, 0x08, 0xD4, 0x1B, 0x43, 0xAC, 0x70, 0x30, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xD4, 0x1B, 0x02, 0x8E, 0xD0, 0x1B, 0x03, 0x8E,
-0x00, 0x20, 0x42, 0x38, 0x62, 0x32, 0x00, 0x08, 0xD4, 0x1B, 0x02, 0xAE,
-0x70, 0x30, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xB0, 0x02, 0x3C,
-0x08, 0x00, 0x43, 0x34, 0x00, 0x00, 0x69, 0x8C, 0xFF, 0x00, 0x02, 0x24,
-0xFF, 0x00, 0x24, 0x31, 0x2C, 0x00, 0x82, 0x10, 0x00, 0x80, 0x22, 0x31,
-0x34, 0x01, 0x40, 0x14, 0x00, 0x80, 0x02, 0x3C, 0x00, 0xFF, 0x02, 0x3C,
-0x24, 0x10, 0x22, 0x01, 0x0B, 0x00, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24,
-0xA8, 0x37, 0x02, 0x92, 0x20, 0xB0, 0x03, 0x3C, 0x00, 0x12, 0x02, 0x00,
-0x21, 0x10, 0x43, 0x00, 0x0C, 0x00, 0x49, 0x8C, 0x25, 0xB0, 0x03, 0x3C,
-0xB0, 0x03, 0x63, 0x34, 0x00, 0x00, 0x69, 0xAC, 0xFF, 0x00, 0x24, 0x31,
-0xFF, 0x00, 0x02, 0x24, 0x1A, 0x00, 0x82, 0x10, 0x60, 0x1B, 0x70, 0x26,
-0xFF, 0x00, 0x23, 0x31, 0x70, 0x38, 0x05, 0x8E, 0x20, 0x10, 0x02, 0x3C,
-0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x21, 0x30, 0x60, 0x00,
-0x04, 0x38, 0x03, 0xAE, 0x01, 0x00, 0x04, 0x24, 0xA8, 0x37, 0x09, 0xA2,
-0x80, 0x00, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA0, 0xAF,
-0xD0, 0x1B, 0x05, 0x8E, 0x02, 0x80, 0x06, 0x3C, 0xB0, 0x5D, 0xC4, 0x8C,
-0xFF, 0xC7, 0x02, 0x24, 0x24, 0x28, 0xA2, 0x00, 0x25, 0xB0, 0x02, 0x3C,
-0x10, 0x00, 0x84, 0x34, 0x80, 0x03, 0x42, 0x34, 0x41, 0xB0, 0x03, 0x3C,
-0x00, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x65, 0xAC, 0xB0, 0x5D, 0xC4, 0xAC,
-0xD0, 0x1B, 0x05, 0xAE, 0x60, 0x1B, 0x63, 0x26, 0xD4, 0x1B, 0x62, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x42, 0x38, 0x5B, 0x32, 0x00, 0x08,
-0xD4, 0x1B, 0x62, 0xAC, 0x56, 0x01, 0x02, 0x35, 0x00, 0x00, 0x43, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x74, 0xFC, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x7E, 0x58, 0x00, 0x0C, 0x07, 0x00, 0x04, 0x24, 0x12, 0x32, 0x00, 0x08,
-0x60, 0x1B, 0x64, 0x26, 0x00, 0x00, 0x62, 0xAC, 0xB8, 0x32, 0x00, 0x08,
-0xFF, 0x00, 0x02, 0x24, 0xE4, 0x1D, 0x24, 0x96, 0x58, 0x38, 0x26, 0x96,
-0x01, 0x00, 0x84, 0x24, 0x00, 0x19, 0x04, 0x00, 0x25, 0x30, 0xC2, 0x00,
-0xF0, 0xFF, 0x63, 0x30, 0x20, 0x00, 0xC5, 0x24, 0x02, 0x12, 0x03, 0x00,
-0xE4, 0x1D, 0x24, 0xA6, 0x17, 0x00, 0xA2, 0xA0, 0x16, 0x00, 0xA3, 0xA0,
-0x0C, 0x00, 0xC4, 0x8C, 0x00, 0xF0, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0xFF, 0x0F, 0x63, 0x30, 0x00, 0x1C, 0x03, 0x00, 0x24, 0x20, 0x82, 0x00,
-0x25, 0x20, 0x83, 0x00, 0x0C, 0x00, 0xC4, 0xAC, 0x58, 0x38, 0x25, 0x8E,
-0x01, 0x00, 0x10, 0x24, 0x01, 0x00, 0x04, 0x24, 0x31, 0x10, 0x06, 0x3C,
-0x00, 0x01, 0x07, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF,
-0x5B, 0x01, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24, 0x2A, 0xB0, 0x02, 0x3C,
-0x01, 0x00, 0x42, 0x34, 0x02, 0x00, 0x03, 0x24, 0x00, 0x00, 0x50, 0xA0,
-0x00, 0x00, 0x43, 0xA0, 0xD4, 0x1B, 0x22, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x42, 0x38, 0x4D, 0x32, 0x00, 0x08, 0xD4, 0x1B, 0x22, 0xAE,
-0xD0, 0x03, 0x23, 0x35, 0x80, 0x00, 0x02, 0x24, 0x00, 0x00, 0x62, 0xAC,
-0x09, 0x33, 0x00, 0x08, 0x60, 0x1B, 0x62, 0x26, 0x25, 0xB0, 0x02, 0x3C,
-0x01, 0x00, 0x03, 0x24, 0x90, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0xD5, 0x32, 0x00, 0x08, 0x60, 0x1B, 0x65, 0x26, 0x24, 0x10, 0x22, 0x01,
-0xA9, 0xFD, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24, 0x47, 0x00, 0xC6, 0x34,
-0x00, 0x00, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x44, 0x30,
-0x0E, 0x00, 0x85, 0x10, 0x60, 0x1B, 0x62, 0x26, 0x98, 0x37, 0x04, 0xA2,
-0x00, 0x00, 0xC2, 0x90, 0xFF, 0x00, 0x83, 0x30, 0xFF, 0x00, 0x44, 0x30,
-0x07, 0x00, 0x83, 0x10, 0x21, 0x38, 0x00, 0x02, 0x21, 0x28, 0xC0, 0x00,
-0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00, 0xFD, 0xFF, 0x62, 0x14,
-0xFF, 0x00, 0x44, 0x30, 0x98, 0x37, 0xE3, 0xA0, 0x60, 0x1B, 0x62, 0x26,
-0x98, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31, 0x00, 0x00, 0x49, 0xAC,
-0x81, 0x33, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24, 0x24, 0x10, 0x22, 0x01,
-0xFD, 0xFD, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24, 0x45, 0x00, 0xE5, 0x34,
-0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x44, 0x30,
-0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26, 0x9C, 0x37, 0x04, 0xA2,
-0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30, 0xFF, 0x00, 0x44, 0x30,
-0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26, 0x21, 0x30, 0x00, 0x02,
-0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00, 0xFD, 0xFF, 0x62, 0x14,
-0xFF, 0x00, 0x44, 0x30, 0x9C, 0x37, 0xC3, 0xA0, 0x60, 0x1B, 0x62, 0x26,
-0x9C, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31, 0x00, 0x00, 0x49, 0xAC,
-0xF6, 0x33, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24, 0x24, 0x10, 0x22, 0x01,
-0x9E, 0xFD, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24, 0x46, 0x00, 0xA5, 0x34,
-0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x44, 0x30,
-0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26, 0x94, 0x37, 0x04, 0xA2,
-0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30, 0xFF, 0x00, 0x44, 0x30,
-0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26, 0x21, 0x30, 0x00, 0x02,
-0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00, 0xFD, 0xFF, 0x62, 0x14,
-0xFF, 0x00, 0x44, 0x30, 0x94, 0x37, 0xC3, 0xA0, 0x60, 0x1B, 0x62, 0x26,
-0x94, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C, 0x00, 0x1A, 0x03, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C, 0x25, 0xB0, 0x02, 0x3C,
-0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31, 0x00, 0x00, 0x49, 0xAC,
-0xB8, 0x33, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24, 0x00, 0xFF, 0x02, 0x3C,
-0x24, 0x10, 0x22, 0x01, 0x30, 0xFE, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24,
-0x41, 0x00, 0xA5, 0x34, 0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x44, 0x30, 0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x84, 0x37, 0x04, 0xA2, 0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30,
-0xFF, 0x00, 0x44, 0x30, 0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x21, 0x30, 0x00, 0x02, 0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00,
-0xFD, 0xFF, 0x62, 0x14, 0xFF, 0x00, 0x44, 0x30, 0x84, 0x37, 0xC3, 0xA0,
-0x60, 0x1B, 0x62, 0x26, 0x84, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C,
-0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31,
-0x00, 0x00, 0x49, 0xAC, 0x6C, 0x34, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24,
-0x24, 0x10, 0x22, 0x01, 0xCF, 0xFE, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24,
-0x44, 0x00, 0xA5, 0x34, 0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x44, 0x30, 0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x90, 0x37, 0x04, 0xA2, 0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30,
-0xFF, 0x00, 0x44, 0x30, 0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x21, 0x30, 0x00, 0x02, 0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00,
-0xFD, 0xFF, 0x62, 0x14, 0xFF, 0x00, 0x44, 0x30, 0x90, 0x37, 0xC3, 0xA0,
-0x60, 0x1B, 0x62, 0x26, 0x90, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C,
-0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31,
-0x00, 0x00, 0x49, 0xAC, 0x2C, 0x35, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24,
-0x24, 0x10, 0x22, 0x01, 0xAE, 0xFD, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24,
-0x40, 0x00, 0xA5, 0x34, 0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x44, 0x30, 0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x80, 0x37, 0x04, 0xA2, 0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30,
-0xFF, 0x00, 0x44, 0x30, 0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x21, 0x30, 0x00, 0x02, 0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00,
-0xFD, 0xFF, 0x62, 0x14, 0xFF, 0x00, 0x44, 0x30, 0x80, 0x37, 0xC3, 0xA0,
-0x60, 0x1B, 0x62, 0x26, 0x80, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C,
-0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31,
-0x00, 0x00, 0x49, 0xAC, 0x2C, 0x34, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x62, 0xAC, 0x78, 0x35, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24,
-0x24, 0x10, 0x22, 0x01, 0x08, 0xFE, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24,
-0x42, 0x00, 0xA5, 0x34, 0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x44, 0x30, 0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x88, 0x37, 0x04, 0xA2, 0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30,
-0xFF, 0x00, 0x44, 0x30, 0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x21, 0x30, 0x00, 0x02, 0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00,
-0xFD, 0xFF, 0x62, 0x14, 0xFF, 0x00, 0x44, 0x30, 0x88, 0x37, 0xC3, 0xA0,
-0x60, 0x1B, 0x62, 0x26, 0x88, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C,
-0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31,
-0x00, 0x00, 0x49, 0xAC, 0xAA, 0x34, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24,
-0x24, 0x10, 0x22, 0x01, 0x2C, 0xFE, 0x40, 0x10, 0xFF, 0x00, 0x02, 0x24,
-0x43, 0x00, 0xE5, 0x34, 0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x44, 0x30, 0x0E, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x8C, 0x37, 0x04, 0xA2, 0x00, 0x00, 0xA2, 0x90, 0xFF, 0x00, 0x83, 0x30,
-0xFF, 0x00, 0x44, 0x30, 0x08, 0x00, 0x83, 0x10, 0x60, 0x1B, 0x62, 0x26,
-0x21, 0x30, 0x00, 0x02, 0x00, 0x00, 0xA2, 0x90, 0x21, 0x18, 0x80, 0x00,
-0xFD, 0xFF, 0x62, 0x14, 0xFF, 0x00, 0x44, 0x30, 0x8C, 0x37, 0xC3, 0xA0,
-0x60, 0x1B, 0x62, 0x26, 0x8C, 0x37, 0x43, 0x90, 0x20, 0xB0, 0x02, 0x3C,
-0x00, 0x1A, 0x03, 0x00, 0x21, 0x18, 0x62, 0x00, 0x0C, 0x00, 0x69, 0x8C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x03, 0x42, 0x34, 0xFF, 0x00, 0x24, 0x31,
-0x00, 0x00, 0x49, 0xAC, 0xEF, 0x34, 0x00, 0x08, 0xFF, 0x00, 0x02, 0x24,
-0x06, 0x00, 0x03, 0x24, 0x90, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x90, 0x34, 0x00, 0x08, 0x60, 0x1B, 0x62, 0x26, 0x01, 0x00, 0x03, 0x24,
-0x90, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0xA4, 0x33, 0x00, 0x08,
-0x60, 0x1B, 0x62, 0x26, 0x25, 0xB0, 0x02, 0x3C, 0x07, 0x00, 0x03, 0x24,
-0x90, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x60, 0x1B, 0x63, 0x26,
-0xD4, 0x1B, 0x62, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x42, 0x38,
-0x56, 0x34, 0x00, 0x08, 0xD4, 0x1B, 0x62, 0xAC, 0x00, 0x00, 0x40, 0xAC,
-0x19, 0x34, 0x00, 0x08, 0x60, 0x1B, 0x62, 0x26, 0x02, 0x00, 0x03, 0x24,
-0x90, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0xDF, 0x33, 0x00, 0x08,
-0x60, 0x1B, 0x62, 0x26, 0x90, 0x03, 0x63, 0x34, 0x00, 0x00, 0x62, 0xAC,
-0x12, 0x35, 0x00, 0x08, 0x60, 0x1B, 0x62, 0x26, 0x03, 0x00, 0x03, 0x24,
-0x90, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x53, 0x35, 0x00, 0x08,
-0x60, 0x1B, 0x62, 0x26, 0x05, 0x00, 0x03, 0x24, 0x90, 0x03, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xAC, 0xD1, 0x34, 0x00, 0x08, 0x60, 0x1B, 0x62, 0x26,
-0xE0, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xBF, 0xAF, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x25, 0xB0, 0x0C, 0x3C,
-0x01, 0x80, 0x02, 0x3C, 0x18, 0x03, 0x83, 0x35, 0x30, 0xDC, 0x42, 0x24,
-0x02, 0x80, 0x12, 0x3C, 0x41, 0xB0, 0x0B, 0x3C, 0x00, 0x00, 0x62, 0xAC,
-0x60, 0x1B, 0x4A, 0x26, 0x0A, 0x00, 0x62, 0x35, 0x00, 0x00, 0x44, 0x94,
-0xDE, 0x1B, 0x43, 0x95, 0xDC, 0x1B, 0x49, 0x95, 0x25, 0x30, 0x64, 0x00,
-0xFF, 0xFF, 0xD0, 0x30, 0x24, 0x10, 0x09, 0x02, 0x02, 0x00, 0x42, 0x30,
-0xC2, 0x00, 0x40, 0x10, 0xC0, 0x03, 0x83, 0x35, 0x02, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x62, 0xAC, 0x02, 0x80, 0x08, 0x3C, 0xB0, 0x5D, 0x04, 0x8D,
-0xDC, 0x02, 0x82, 0x35, 0x00, 0x00, 0x47, 0x90, 0xFD, 0xFF, 0x03, 0x24,
-0x00, 0x80, 0x02, 0x3C, 0x24, 0x18, 0x23, 0x01, 0x25, 0x20, 0x82, 0x00,
-0x02, 0x00, 0xC6, 0x38, 0x08, 0x00, 0x65, 0x35, 0x02, 0x80, 0x02, 0x3C,
-0xED, 0x5D, 0x47, 0xA0, 0xB0, 0x5D, 0x04, 0xAD, 0xDE, 0x1B, 0x46, 0xA5,
-0x21, 0x48, 0x60, 0x00, 0x00, 0x00, 0xA3, 0xA4, 0xDC, 0x1B, 0x43, 0xA5,
-0x24, 0x38, 0x09, 0x02, 0x04, 0x00, 0xE2, 0x30, 0x0A, 0x00, 0x40, 0x10,
-0x08, 0x00, 0xE2, 0x30, 0xDE, 0x1B, 0x43, 0x95, 0x0C, 0x00, 0x64, 0x35,
-0xC0, 0x03, 0x85, 0x35, 0x04, 0x00, 0x63, 0x38, 0x04, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x86, 0x90, 0x00, 0x00, 0xA2, 0xAC, 0xDE, 0x1B, 0x43, 0xA5,
-0x08, 0x00, 0xE2, 0x30, 0x08, 0x00, 0x40, 0x10, 0x10, 0x00, 0xE2, 0x30,
-0xDE, 0x1B, 0x42, 0x95, 0xC0, 0x03, 0x84, 0x35, 0x08, 0x00, 0x03, 0x24,
-0x08, 0x00, 0x42, 0x38, 0x00, 0x00, 0x83, 0xAC, 0xDE, 0x1B, 0x42, 0xA5,
-0x10, 0x00, 0xE2, 0x30, 0x08, 0x00, 0x40, 0x10, 0x20, 0x00, 0xE2, 0x30,
-0xDE, 0x1B, 0x42, 0x95, 0xC0, 0x03, 0x84, 0x35, 0x10, 0x00, 0x03, 0x24,
-0x10, 0x00, 0x42, 0x38, 0x00, 0x00, 0x83, 0xAC, 0xDE, 0x1B, 0x42, 0xA5,
-0x20, 0x00, 0xE2, 0x30, 0x08, 0x00, 0x40, 0x10, 0x80, 0x00, 0xE2, 0x30,
-0xDE, 0x1B, 0x42, 0x95, 0xC0, 0x03, 0x84, 0x35, 0x20, 0x00, 0x03, 0x24,
-0x20, 0x00, 0x42, 0x38, 0x00, 0x00, 0x83, 0xAC, 0xDE, 0x1B, 0x42, 0xA5,
-0x80, 0x00, 0xE2, 0x30, 0x74, 0x00, 0x40, 0x10, 0x60, 0x1B, 0x47, 0x26,
-0xC0, 0x03, 0x83, 0x35, 0x80, 0x00, 0x02, 0x24, 0x42, 0xB0, 0x0B, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0x03, 0x00, 0x71, 0x35, 0xDE, 0x1B, 0x42, 0x95,
-0x00, 0x00, 0x23, 0x92, 0x80, 0x00, 0x42, 0x38, 0x20, 0x00, 0x63, 0x30,
-0x59, 0x00, 0x60, 0x10, 0xDE, 0x1B, 0x42, 0xA5, 0x20, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x22, 0xA2, 0x02, 0x80, 0x03, 0x3C, 0x0F, 0x5E, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x75, 0x00, 0x40, 0x14, 0x21, 0x40, 0x00, 0x00,
-0xB0, 0x1B, 0x42, 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30,
-0x4E, 0x00, 0x40, 0x10, 0x02, 0x80, 0x06, 0x3C, 0x02, 0x80, 0x07, 0x3C,
-0xEC, 0x5D, 0xE2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x09, 0x3C, 0x02, 0x80, 0x04, 0x3C, 0xF8, 0x5D, 0x82, 0x8C,
-0x18, 0x5E, 0x24, 0x8D, 0x1C, 0x5E, 0x25, 0x8D, 0x21, 0x18, 0x00, 0x00,
-0x21, 0x10, 0x44, 0x00, 0x2B, 0x30, 0x44, 0x00, 0x21, 0x18, 0x65, 0x00,
-0x21, 0x18, 0x66, 0x00, 0x18, 0x5E, 0x22, 0xAD, 0x1C, 0x5E, 0x23, 0xAD,
-0xEC, 0x5D, 0xE4, 0x90, 0x02, 0x00, 0x02, 0x24, 0xFF, 0x00, 0x84, 0x30,
-0x07, 0x00, 0x82, 0x10, 0x02, 0x80, 0x04, 0x3C, 0xEC, 0x5D, 0xE2, 0x90,
-0x03, 0x00, 0x03, 0x24, 0xFF, 0x00, 0x42, 0x30, 0x5A, 0x00, 0x43, 0x14,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x04, 0x3C, 0x0A, 0x5E, 0x82, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x42, 0x24, 0x0A, 0x5E, 0x82, 0xA0,
-0x0A, 0x5E, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x60, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0xF2, 0x5D, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x03, 0x00, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x11,
-0x80, 0x00, 0x86, 0x35, 0x0A, 0x5E, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x06, 0x00, 0x40, 0x14, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0x09, 0x5E, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x5E, 0x83, 0xA0,
-0x02, 0x80, 0x05, 0x3C, 0x07, 0x5E, 0xA2, 0x90, 0x02, 0x80, 0x03, 0x3C,
-0x02, 0x00, 0x04, 0x24, 0x10, 0x00, 0x42, 0x34, 0x07, 0x5E, 0xA2, 0xA0,
-0xF1, 0x5D, 0x62, 0x90, 0x21, 0x28, 0x00, 0x00, 0xFF, 0x00, 0x42, 0x30,
-0x80, 0x30, 0x02, 0x00, 0x21, 0x30, 0xC2, 0x00, 0xB9, 0x20, 0x00, 0x0C,
-0x00, 0x33, 0x06, 0x00, 0x42, 0xB0, 0x02, 0x3C, 0x44, 0x00, 0x04, 0x24,
-0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x44, 0xA0, 0x02, 0x80, 0x03, 0x3C,
-0xEE, 0x5D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x42, 0x30,
-0x04, 0x00, 0x42, 0x28, 0x05, 0x00, 0x40, 0x10, 0x02, 0x80, 0x06, 0x3C,
-0x04, 0x00, 0x04, 0x24, 0x4B, 0x2E, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24,
-0x02, 0x80, 0x06, 0x3C, 0xB0, 0x5D, 0xC4, 0x8C, 0x60, 0x1B, 0x47, 0x26,
-0xDC, 0x1B, 0xE5, 0x94, 0x10, 0x00, 0x02, 0x3C, 0x25, 0x20, 0x82, 0x00,
-0x41, 0xB0, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C, 0x7F, 0xFF, 0xA5, 0x30,
-0xB0, 0x03, 0x42, 0x34, 0x08, 0x00, 0x63, 0x34, 0x00, 0x00, 0x44, 0xAC,
-0x00, 0x00, 0x65, 0xA4, 0xB0, 0x5D, 0xC4, 0xAC, 0xDC, 0x1B, 0xE5, 0xA4,
-0x60, 0x1B, 0x47, 0x26, 0xDC, 0x1B, 0xE2, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x10, 0x50, 0x00, 0x00, 0x30, 0x42, 0x30, 0x06, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xDE, 0x1B, 0xE2, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x10, 0x42, 0x38, 0x00, 0x20, 0x42, 0x34, 0xDE, 0x1B, 0xE2, 0xA4,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x36, 0x37, 0x00, 0x08, 0xDE, 0x1B, 0x46, 0xA5, 0x01, 0x00, 0x08, 0x24,
-0x0F, 0x5E, 0x60, 0xA0, 0x72, 0x37, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x07, 0x5E, 0xA2, 0x90, 0x02, 0x80, 0x03, 0x3C, 0x02, 0x00, 0x04, 0x24,
-0x10, 0x00, 0x42, 0x34, 0x07, 0x5E, 0xA2, 0xA0, 0xF1, 0x5D, 0x62, 0x90,
-0x21, 0x28, 0x00, 0x00, 0xFF, 0x00, 0x42, 0x30, 0x80, 0x30, 0x02, 0x00,
-0x21, 0x30, 0xC2, 0x00, 0xB9, 0x20, 0x00, 0x0C, 0x00, 0x33, 0x06, 0x00,
-0x44, 0x00, 0x02, 0x24, 0x00, 0x00, 0x22, 0xA2, 0xBA, 0x37, 0x00, 0x08,
-0x02, 0x80, 0x03, 0x3C, 0x84, 0x00, 0x84, 0x35, 0x00, 0x00, 0x82, 0x8C,
-0x02, 0x80, 0x08, 0x3C, 0x00, 0x00, 0xC4, 0x8C, 0x14, 0x5E, 0x06, 0x8D,
-0x21, 0x10, 0x00, 0x00, 0x18, 0x5E, 0x28, 0x8D, 0x1C, 0x5E, 0x29, 0x8D,
-0x00, 0x00, 0x65, 0x91, 0x25, 0x10, 0x44, 0x00, 0x21, 0x10, 0x46, 0x00,
-0xFB, 0xFF, 0x04, 0x24, 0x24, 0x28, 0xA4, 0x00, 0x23, 0x40, 0x02, 0x01,
-0x00, 0x00, 0x65, 0xA1, 0x04, 0x00, 0x00, 0x11, 0x01, 0x00, 0x06, 0x24,
-0x80, 0x10, 0x08, 0x00, 0x21, 0x10, 0x48, 0x00, 0x80, 0x30, 0x02, 0x00,
-0x01, 0x00, 0x04, 0x24, 0xB9, 0x20, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00,
-0x42, 0xB0, 0x02, 0x3C, 0x22, 0x00, 0x03, 0x24, 0x03, 0x00, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xA0, 0xC4, 0x37, 0x00, 0x08, 0x02, 0x80, 0x06, 0x3C,
-0xF0, 0xFF, 0xBD, 0x27, 0x08, 0x00, 0xB2, 0xAF, 0x04, 0x00, 0xB1, 0xAF,
-0x00, 0x00, 0xB0, 0xAF, 0x00, 0x40, 0x09, 0x40, 0x00, 0x68, 0x0A, 0x40,
-0x00, 0x70, 0x02, 0x40, 0x00, 0x60, 0x0B, 0x40, 0x25, 0xB0, 0x05, 0x3C,
-0x18, 0x03, 0xA7, 0x34, 0x00, 0x00, 0xE6, 0x8C, 0x01, 0x80, 0x02, 0x3C,
-0x1C, 0x03, 0xA3, 0x34, 0x5C, 0xE0, 0x42, 0x24, 0x00, 0x00, 0x66, 0xAC,
-0x00, 0x00, 0xE2, 0xAC, 0x80, 0x00, 0x83, 0x8C, 0x7C, 0x02, 0xA2, 0x34,
-0x80, 0x02, 0xA6, 0x34, 0x84, 0x02, 0xA7, 0x34, 0x88, 0x02, 0xA8, 0x34,
-0x00, 0x00, 0x43, 0xAC, 0x00, 0x00, 0xC9, 0xAC, 0x00, 0x00, 0xEA, 0xAC,
-0x00, 0x00, 0x0B, 0xAD, 0x74, 0x00, 0x83, 0x8C, 0x8C, 0x02, 0xA2, 0x34,
-0x90, 0x02, 0xA7, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x08, 0x00, 0x86, 0x8C,
-0x94, 0x02, 0xA8, 0x34, 0x98, 0x02, 0xA9, 0x34, 0x00, 0x00, 0xE6, 0xAC,
-0x0C, 0x00, 0x82, 0x8C, 0x9C, 0x02, 0xA6, 0x34, 0xA0, 0x02, 0xA7, 0x34,
-0x00, 0x00, 0x02, 0xAD, 0x10, 0x00, 0x83, 0x8C, 0xA4, 0x02, 0xA8, 0x34,
-0xA8, 0x02, 0xAA, 0x34, 0x00, 0x00, 0x23, 0xAD, 0x14, 0x00, 0x82, 0x8C,
-0xAC, 0x02, 0xA9, 0x34, 0xB0, 0x02, 0xAB, 0x34, 0x00, 0x00, 0xC2, 0xAC,
-0x18, 0x00, 0x83, 0x8C, 0xB4, 0x02, 0xAC, 0x34, 0xB8, 0x02, 0xAD, 0x34,
-0x00, 0x00, 0xE3, 0xAC, 0x1C, 0x00, 0x82, 0x8C, 0xBC, 0x02, 0xA7, 0x34,
-0xC0, 0x02, 0xAE, 0x34, 0x00, 0x00, 0x02, 0xAD, 0x20, 0x00, 0x83, 0x8C,
-0xC4, 0x02, 0xA8, 0x34, 0xC8, 0x02, 0xAF, 0x34, 0x00, 0x00, 0x43, 0xAD,
-0x24, 0x00, 0x82, 0x8C, 0xCC, 0x02, 0xAA, 0x34, 0xD0, 0x02, 0xB0, 0x34,
-0x00, 0x00, 0x22, 0xAD, 0x28, 0x00, 0x83, 0x8C, 0xD4, 0x02, 0xA9, 0x34,
-0xD8, 0x02, 0xB1, 0x34, 0x00, 0x00, 0x63, 0xAD, 0x2C, 0x00, 0x86, 0x8C,
-0x70, 0x02, 0xAB, 0x34, 0x74, 0x02, 0xB2, 0x34, 0x00, 0x00, 0x86, 0xAD,
-0x30, 0x00, 0x82, 0x8C, 0x78, 0x02, 0xA6, 0x34, 0x6C, 0x03, 0xAC, 0x34,
-0x00, 0x00, 0xA2, 0xAD, 0x34, 0x00, 0x83, 0x8C, 0x02, 0x80, 0x02, 0x3C,
-0x00, 0x00, 0xE3, 0xAC, 0x38, 0x00, 0x85, 0x8C, 0xE0, 0xC8, 0x47, 0x8C,
-0x00, 0x00, 0xC5, 0xAD, 0x3C, 0x00, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x02, 0xAD, 0x40, 0x00, 0x83, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xE3, 0xAD, 0x44, 0x00, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x42, 0xAD, 0x48, 0x00, 0x83, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x03, 0xAE, 0x4C, 0x00, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x22, 0xAD, 0x50, 0x00, 0x83, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x23, 0xAE, 0x54, 0x00, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x62, 0xAD, 0x58, 0x00, 0x83, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x43, 0xAE, 0x5C, 0x00, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xC2, 0xAC, 0x21, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x82, 0xAD,
-0x01, 0x00, 0xE7, 0x24, 0x21, 0x10, 0xE0, 0x00, 0x01, 0x00, 0xE7, 0x24,
-0x00, 0x00, 0x82, 0xAD, 0x82, 0x38, 0x00, 0x08, 0x21, 0x10, 0xE0, 0x00,
-0x01, 0x80, 0x1B, 0x3C, 0x24, 0xE2, 0x7B, 0x27, 0x25, 0xB0, 0x1A, 0x3C,
-0x18, 0x03, 0x5A, 0x27, 0x00, 0x00, 0x5B, 0xAF, 0x21, 0xD8, 0xA0, 0x03,
-0x82, 0xDA, 0x1B, 0x00, 0x80, 0xDA, 0x1B, 0x00, 0x08, 0x00, 0x7B, 0x27,
-0x04, 0x00, 0x61, 0xAF, 0x08, 0x00, 0x62, 0xAF, 0x0C, 0x00, 0x63, 0xAF,
-0x10, 0x00, 0x64, 0xAF, 0x14, 0x00, 0x65, 0xAF, 0x18, 0x00, 0x66, 0xAF,
-0x1C, 0x00, 0x67, 0xAF, 0x20, 0x00, 0x68, 0xAF, 0x24, 0x00, 0x69, 0xAF,
-0x28, 0x00, 0x6A, 0xAF, 0x2C, 0x00, 0x6B, 0xAF, 0x30, 0x00, 0x6C, 0xAF,
-0x34, 0x00, 0x6D, 0xAF, 0x38, 0x00, 0x6E, 0xAF, 0x3C, 0x00, 0x6F, 0xAF,
-0x12, 0x40, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x00, 0x70, 0x0A, 0x40,
-0x40, 0x00, 0x70, 0xAF, 0x44, 0x00, 0x71, 0xAF, 0x48, 0x00, 0x72, 0xAF,
-0x4C, 0x00, 0x73, 0xAF, 0x50, 0x00, 0x74, 0xAF, 0x54, 0x00, 0x75, 0xAF,
-0x58, 0x00, 0x76, 0xAF, 0x5C, 0x00, 0x77, 0xAF, 0x60, 0x00, 0x78, 0xAF,
-0x64, 0x00, 0x79, 0xAF, 0x68, 0x00, 0x7C, 0xAF, 0x6C, 0x00, 0x7D, 0xAF,
-0x70, 0x00, 0x7E, 0xAF, 0x74, 0x00, 0x7F, 0xAF, 0x78, 0x00, 0x68, 0xAF,
-0x7C, 0x00, 0x69, 0xAF, 0x80, 0x00, 0x6A, 0xAF, 0x00, 0x68, 0x1A, 0x40,
-0x25, 0xB0, 0x1B, 0x3C, 0x1C, 0x03, 0x7B, 0x37, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x7A, 0xAF, 0x7F, 0x00, 0x5B, 0x33, 0x30, 0x00, 0x60, 0x13,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x1B, 0x3C, 0x30, 0x03, 0x7B, 0x37,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xAF, 0x00, 0x00, 0x00, 0x00,
-0x21, 0xD8, 0xA0, 0x03, 0x82, 0xDA, 0x1B, 0x00, 0x80, 0xDA, 0x1B, 0x00,
-0x08, 0x00, 0x7B, 0x27, 0x04, 0x00, 0x61, 0xAF, 0x08, 0x00, 0x62, 0xAF,
-0x0C, 0x00, 0x63, 0xAF, 0x10, 0x00, 0x64, 0xAF, 0x14, 0x00, 0x65, 0xAF,
-0x18, 0x00, 0x66, 0xAF, 0x1C, 0x00, 0x67, 0xAF, 0x20, 0x00, 0x68, 0xAF,
-0x24, 0x00, 0x69, 0xAF, 0x28, 0x00, 0x6A, 0xAF, 0x2C, 0x00, 0x6B, 0xAF,
-0x30, 0x00, 0x6C, 0xAF, 0x34, 0x00, 0x6D, 0xAF, 0x38, 0x00, 0x6E, 0xAF,
-0x3C, 0x00, 0x6F, 0xAF, 0x12, 0x40, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00,
-0x00, 0x70, 0x0A, 0x40, 0x40, 0x00, 0x70, 0xAF, 0x44, 0x00, 0x71, 0xAF,
-0x48, 0x00, 0x72, 0xAF, 0x4C, 0x00, 0x73, 0xAF, 0x50, 0x00, 0x74, 0xAF,
-0x54, 0x00, 0x75, 0xAF, 0x58, 0x00, 0x76, 0xAF, 0x5C, 0x00, 0x77, 0xAF,
-0x60, 0x00, 0x78, 0xAF, 0x64, 0x00, 0x79, 0xAF, 0x68, 0x00, 0x7C, 0xAF,
-0x6C, 0x00, 0x7D, 0xAF, 0x70, 0x00, 0x7E, 0xAF, 0x74, 0x00, 0x7F, 0xAF,
-0x78, 0x00, 0x68, 0xAF, 0x7C, 0x00, 0x69, 0xAF, 0x80, 0x00, 0x6A, 0xAF,
-0x17, 0x38, 0x00, 0x08, 0x21, 0x20, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x08, 0x3C, 0x20, 0x03, 0x08, 0x35, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x1A, 0xAD, 0x00, 0x04, 0x5B, 0x33, 0x0A, 0x00, 0x60, 0x13,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x08, 0x3C, 0xE0, 0xC7, 0x08, 0x25,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x1B, 0x3C, 0x24, 0x03, 0x7B, 0x37,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xAF, 0x09, 0xF8, 0x00, 0x01,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x5B, 0x33, 0x25, 0xB0, 0x08, 0x3C,
-0x28, 0x03, 0x08, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xAD,
-0x06, 0x00, 0x60, 0x13, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x08, 0x3C,
-0x30, 0xDC, 0x08, 0x25, 0x00, 0x00, 0x00, 0x00, 0x09, 0xF8, 0x00, 0x01,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x1A, 0x3C, 0xB0, 0x5D, 0x5A, 0x27,
-0x04, 0x00, 0x5B, 0x97, 0x25, 0xB0, 0x08, 0x3C, 0x30, 0x03, 0x08, 0x35,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xAD, 0x18, 0x00, 0x60, 0x13,
-0x00, 0x00, 0x00, 0x00, 0x08, 0xE8, 0x9B, 0x27, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x61, 0x8F, 0xFC, 0x03, 0x70, 0x7B, 0x7C, 0x00, 0x62, 0x7B,
-0xBC, 0x00, 0x64, 0x7B, 0xFC, 0x00, 0x66, 0x7B, 0x3C, 0x01, 0x68, 0x7B,
-0x13, 0x00, 0x00, 0x02, 0x11, 0x00, 0x20, 0x02, 0x7C, 0x01, 0x6A, 0x7B,
-0xBC, 0x01, 0x6C, 0x7B, 0xFC, 0x01, 0x6E, 0x7B, 0x3C, 0x02, 0x70, 0x7B,
-0x7C, 0x02, 0x72, 0x7B, 0xBC, 0x02, 0x74, 0x7B, 0xFC, 0x02, 0x76, 0x7B,
-0x3C, 0x03, 0x78, 0x7B, 0x7C, 0x03, 0x7C, 0x7B, 0xBC, 0x03, 0x7E, 0x7B,
-0x80, 0x00, 0x7B, 0x8F, 0x74, 0x39, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x21, 0xD8, 0xA0, 0x03, 0x82, 0xDA, 0x1B, 0x00, 0x80, 0xDA, 0x1B, 0x00,
-0x08, 0x00, 0x7B, 0x27, 0x08, 0x00, 0x5B, 0xAF, 0xFC, 0xEB, 0x9D, 0x27,
-0x00, 0x00, 0x4A, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x40, 0x11,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x08, 0x3C, 0x10, 0x5D, 0x08, 0x25,
-0x21, 0x48, 0x00, 0x00, 0x21, 0x58, 0x00, 0x00, 0x01, 0x00, 0x6B, 0x25,
-0x1A, 0x00, 0x40, 0x11, 0x24, 0x70, 0x4B, 0x01, 0x14, 0x00, 0xC0, 0x11,
-0x01, 0x00, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x44, 0xA3,
-0x26, 0x50, 0x4B, 0x01, 0x00, 0x00, 0x4A, 0xAF, 0x80, 0x80, 0x09, 0x00,
-0x21, 0x80, 0x08, 0x02, 0x00, 0x00, 0x10, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x09, 0xF8, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x1B, 0x3C,
-0xFC, 0xE4, 0x7B, 0x27, 0x25, 0xB0, 0x1A, 0x3C, 0x18, 0x03, 0x5A, 0x27,
-0x00, 0x00, 0x5B, 0xAF, 0x02, 0x80, 0x1A, 0x3C, 0xB0, 0x5D, 0x5A, 0x27,
-0xE1, 0xFF, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x29, 0x25,
-0x40, 0x58, 0x0B, 0x00, 0x37, 0x39, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x1B, 0x3C, 0xB0, 0x5D, 0x7B, 0x27, 0x21, 0x60, 0x00, 0x00,
-0x04, 0x00, 0x6C, 0xA7, 0x08, 0x00, 0x7A, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0xF8, 0xFF, 0x5A, 0x27, 0x00, 0x00, 0x5A, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x5A, 0x27, 0x84, 0x00, 0x44, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0xF9, 0xFF, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x41, 0x8F,
-0xFC, 0x03, 0x50, 0x7B, 0x7C, 0x00, 0x42, 0x7B, 0xBC, 0x00, 0x44, 0x7B,
-0xFC, 0x00, 0x46, 0x7B, 0x3C, 0x01, 0x48, 0x7B, 0x13, 0x00, 0x00, 0x02,
-0x11, 0x00, 0x20, 0x02, 0x7C, 0x01, 0x4A, 0x7B, 0xBC, 0x01, 0x4C, 0x7B,
-0xFC, 0x01, 0x4E, 0x7B, 0x3C, 0x02, 0x50, 0x7B, 0x7C, 0x02, 0x52, 0x7B,
-0xBC, 0x02, 0x54, 0x7B, 0xFC, 0x02, 0x56, 0x7B, 0x3C, 0x03, 0x58, 0x7B,
-0x7C, 0x03, 0x5C, 0x7B, 0xBC, 0x03, 0x5E, 0x7B, 0x80, 0x00, 0x5B, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x03, 0x10, 0x00, 0x00, 0x42,
-0x00, 0x60, 0x05, 0x40, 0x42, 0x28, 0x05, 0x00, 0x40, 0x28, 0x05, 0x00,
-0x00, 0x60, 0x85, 0x40, 0x04, 0x00, 0x81, 0xAC, 0x08, 0x00, 0x82, 0xAC,
-0x0C, 0x00, 0x83, 0xAC, 0x20, 0x00, 0x88, 0xAC, 0x24, 0x00, 0x89, 0xAC,
-0x28, 0x00, 0x8A, 0xAC, 0x2C, 0x00, 0x8B, 0xAC, 0x30, 0x00, 0x8C, 0xAC,
-0x34, 0x00, 0x8D, 0xAC, 0x38, 0x00, 0x8E, 0xAC, 0x3C, 0x00, 0x8F, 0xAC,
-0x12, 0x40, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x40, 0x00, 0x90, 0xAC,
-0x44, 0x00, 0x91, 0xAC, 0x48, 0x00, 0x92, 0xAC, 0x4C, 0x00, 0x93, 0xAC,
-0x50, 0x00, 0x94, 0xAC, 0x54, 0x00, 0x95, 0xAC, 0x58, 0x00, 0x96, 0xAC,
-0x5C, 0x00, 0x97, 0xAC, 0x60, 0x00, 0x98, 0xAC, 0x64, 0x00, 0x99, 0xAC,
-0x68, 0x00, 0x9C, 0xAC, 0x6C, 0x00, 0x9D, 0xAC, 0x70, 0x00, 0x9E, 0xAC,
-0x74, 0x00, 0x9F, 0xAC, 0x78, 0x00, 0x88, 0xAC, 0x7C, 0x00, 0x89, 0xAC,
-0x80, 0x00, 0x9F, 0xAC, 0xF8, 0xFF, 0x84, 0x24, 0x00, 0x00, 0x84, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x84, 0x24, 0x84, 0x00, 0x86, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0xF9, 0xFF, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x21, 0xD8, 0x80, 0x00, 0x01, 0x00, 0xBA, 0x34, 0x04, 0x00, 0x61, 0x8F,
-0xFC, 0x03, 0x70, 0x7B, 0x7C, 0x00, 0x62, 0x7B, 0xBC, 0x00, 0x64, 0x7B,
-0xFC, 0x00, 0x66, 0x7B, 0x3C, 0x01, 0x68, 0x7B, 0x13, 0x00, 0x00, 0x02,
-0x11, 0x00, 0x20, 0x02, 0x7C, 0x01, 0x6A, 0x7B, 0xBC, 0x01, 0x6C, 0x7B,
-0xFC, 0x01, 0x6E, 0x7B, 0x3C, 0x02, 0x70, 0x7B, 0x7C, 0x02, 0x72, 0x7B,
-0xBC, 0x02, 0x74, 0x7B, 0xFC, 0x02, 0x76, 0x7B, 0x3C, 0x03, 0x78, 0x7B,
-0x7C, 0x03, 0x7C, 0x7B, 0xBC, 0x03, 0x7E, 0x7B, 0x80, 0x00, 0x7B, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x60, 0x03, 0x00, 0x60, 0x9A, 0x40,
-0x00, 0x60, 0x05, 0x40, 0x42, 0x28, 0x05, 0x00, 0x40, 0x28, 0x05, 0x00,
-0x00, 0x60, 0x85, 0x40, 0x04, 0x00, 0x81, 0xAC, 0x08, 0x00, 0x82, 0xAC,
-0x0C, 0x00, 0x83, 0xAC, 0x20, 0x00, 0x88, 0xAC, 0x24, 0x00, 0x89, 0xAC,
-0x28, 0x00, 0x8A, 0xAC, 0x2C, 0x00, 0x8B, 0xAC, 0x30, 0x00, 0x8C, 0xAC,
-0x34, 0x00, 0x8D, 0xAC, 0x38, 0x00, 0x8E, 0xAC, 0x3C, 0x00, 0x8F, 0xAC,
-0x12, 0x40, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x40, 0x00, 0x90, 0xAC,
-0x44, 0x00, 0x91, 0xAC, 0x48, 0x00, 0x92, 0xAC, 0x4C, 0x00, 0x93, 0xAC,
-0x50, 0x00, 0x94, 0xAC, 0x54, 0x00, 0x94, 0xAC, 0x58, 0x00, 0x96, 0xAC,
-0x5C, 0x00, 0x96, 0xAC, 0x60, 0x00, 0x98, 0xAC, 0x64, 0x00, 0x99, 0xAC,
-0x68, 0x00, 0x9C, 0xAC, 0x6C, 0x00, 0x9D, 0xAC, 0x70, 0x00, 0x9E, 0xAC,
-0x78, 0x00, 0x88, 0xAC, 0x7C, 0x00, 0x89, 0xAC, 0x80, 0x00, 0x9F, 0xAC,
-0x84, 0x00, 0x80, 0xAC, 0xF8, 0xFF, 0x84, 0x24, 0x00, 0x00, 0x84, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x84, 0x24, 0x84, 0x00, 0x86, 0x8C,
-0xFA, 0xFF, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0xD8, 0x80, 0x00,
-0x01, 0x00, 0xBA, 0x24, 0x04, 0x00, 0x61, 0x8F, 0xFC, 0x03, 0x70, 0x7B,
-0x7C, 0x00, 0x62, 0x7B, 0xBC, 0x00, 0x64, 0x7B, 0xFC, 0x00, 0x66, 0x7B,
-0x3C, 0x01, 0x68, 0x7B, 0x13, 0x00, 0x00, 0x02, 0x11, 0x00, 0x20, 0x02,
-0x7C, 0x01, 0x6A, 0x7B, 0xBC, 0x01, 0x6C, 0x7B, 0xFC, 0x01, 0x6E, 0x7B,
-0x3C, 0x02, 0x70, 0x7B, 0x7C, 0x02, 0x72, 0x7B, 0xBC, 0x02, 0x74, 0x7B,
-0xFC, 0x02, 0x76, 0x7B, 0x3C, 0x03, 0x78, 0x7B, 0x7C, 0x03, 0x7C, 0x7B,
-0xBC, 0x03, 0x7E, 0x7B, 0x80, 0x00, 0x7B, 0x8F, 0x08, 0x00, 0x60, 0x03,
-0x00, 0x60, 0x9A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x23, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x1B, 0x3C,
-0x00, 0x00, 0x7B, 0x27, 0x25, 0xB0, 0x1A, 0x3C, 0x18, 0x03, 0x5A, 0x27,
-0x00, 0x00, 0x5B, 0xAF, 0x00, 0x00, 0x05, 0x24, 0x03, 0x00, 0xA4, 0x24,
-0x00, 0xA0, 0x80, 0x40, 0x00, 0xA0, 0x84, 0x40, 0x01, 0x80, 0x04, 0x3C,
-0x40, 0x00, 0x84, 0x24, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x80, 0x1B, 0x3C, 0x40, 0x00, 0x7B, 0x27, 0x25, 0xB0, 0x1A, 0x3C,
-0x18, 0x03, 0x5A, 0x27, 0x00, 0x00, 0x5B, 0xAF, 0x02, 0x80, 0x1A, 0x3C,
-0x00, 0x00, 0x5A, 0x27, 0xFC, 0x03, 0x5D, 0x27, 0x02, 0x80, 0x1C, 0x3C,
-0x00, 0x18, 0x9C, 0x27, 0x00, 0xF0, 0x08, 0x3C, 0x00, 0x0C, 0x08, 0x35,
-0x00, 0x60, 0x88, 0x40, 0x02, 0x80, 0x04, 0x3C, 0x00, 0x00, 0x84, 0x24,
-0xFF, 0x7F, 0x05, 0x3C, 0xFF, 0xFF, 0xA5, 0x34, 0x24, 0x20, 0x85, 0x00,
-0x00, 0x20, 0x84, 0x4C, 0xFF, 0xFF, 0x05, 0x34, 0x21, 0x28, 0xA4, 0x00,
-0x00, 0x28, 0x85, 0x4C, 0x02, 0x80, 0x08, 0x3C, 0x00, 0x00, 0x08, 0x25,
-0x00, 0x00, 0x00, 0xAD, 0x03, 0x80, 0x09, 0x3C, 0x04, 0xDD, 0x29, 0x25,
-0x04, 0x00, 0x08, 0x25, 0xFE, 0xFF, 0x09, 0x15, 0x00, 0x00, 0x00, 0xAD,
-0x00, 0x80, 0x04, 0x3C, 0x00, 0x00, 0x84, 0x24, 0xFF, 0x7F, 0x05, 0x3C,
-0xFF, 0xFF, 0xA5, 0x34, 0x24, 0x20, 0x85, 0x00, 0x00, 0x00, 0x84, 0x4C,
-0xFF, 0xFF, 0x06, 0x34, 0x21, 0x30, 0xC4, 0x00, 0x24, 0x30, 0xC5, 0x00,
-0x00, 0x08, 0x86, 0x4C, 0x00, 0xA0, 0x04, 0x40, 0x10, 0x00, 0x84, 0x34,
-0x00, 0xA0, 0x84, 0x40, 0x01, 0x80, 0x1B, 0x3C, 0xEC, 0x00, 0x7B, 0x27,
-0x25, 0xB0, 0x1A, 0x3C, 0x18, 0x03, 0x5A, 0x27, 0x00, 0x00, 0x5B, 0xAF,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x04, 0x3C, 0x44, 0x00, 0x84, 0x34,
-0x00, 0x00, 0x85, 0x84, 0x20, 0x00, 0x06, 0x24, 0x25, 0x28, 0xA6, 0x00,
-0x00, 0x00, 0x85, 0xA4, 0x01, 0x80, 0x1B, 0x3C, 0x1C, 0x01, 0x7B, 0x27,
-0x25, 0xB0, 0x1A, 0x3C, 0x18, 0x03, 0x5A, 0x27, 0x00, 0x00, 0x5B, 0xAF,
-0x25, 0xB0, 0x04, 0x3C, 0x44, 0x00, 0x84, 0x34, 0x00, 0x00, 0x85, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xA5, 0x30, 0xFC, 0xFF, 0xA0, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x1F, 0x07, 0x3C, 0xFF, 0xFF, 0xE7, 0x34,
-0x02, 0x80, 0x05, 0x3C, 0xC0, 0x5C, 0xA5, 0x24, 0xFF, 0xFF, 0xA5, 0x30,
-0x40, 0xB0, 0x04, 0x3C, 0x25, 0x28, 0xA4, 0x00, 0x24, 0x28, 0xA7, 0x00,
-0x21, 0x30, 0x00, 0x00, 0x43, 0xB0, 0x02, 0x3C, 0x00, 0x80, 0x04, 0x3C,
-0x40, 0x00, 0x84, 0x34, 0x00, 0x00, 0x45, 0xAC, 0x04, 0x00, 0x46, 0xAC,
-0x08, 0x00, 0x44, 0xAC, 0x5F, 0x67, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x04, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x64, 0x30, 0x02, 0x1C, 0x03, 0x00,
-0x08, 0x00, 0x80, 0x10, 0x0F, 0x00, 0x63, 0x30, 0x01, 0x00, 0x02, 0x24,
-0x0C, 0x00, 0x62, 0x10, 0x03, 0x00, 0x02, 0x24, 0x0E, 0x00, 0x62, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x03, 0x00, 0x60, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x08, 0x00, 0xE0, 0x03,
-0xC3, 0x5C, 0x40, 0xA0, 0x01, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0xC3, 0x5C, 0x43, 0xA0, 0x02, 0x00, 0x03, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x08, 0x00, 0xE0, 0x03, 0xC3, 0x5C, 0x43, 0xA0, 0x04, 0x00, 0x03, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x08, 0x00, 0xE0, 0x03, 0xC3, 0x5C, 0x43, 0xA0,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x02, 0x24,
-0xFF, 0xFF, 0x42, 0x24, 0xFF, 0xFF, 0x41, 0x04, 0xFF, 0xFF, 0x42, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x42, 0x24, 0x00, 0x60, 0x02, 0x40,
-0x01, 0x00, 0x41, 0x34, 0x01, 0x00, 0x21, 0x38, 0x00, 0x60, 0x81, 0x40,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x82, 0xAC, 0x00, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x40, 0x00, 0x00, 0x60, 0x83, 0x40,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x82, 0xAC, 0x00, 0x60, 0x01, 0x40,
-0x01, 0x00, 0x21, 0x34, 0x00, 0x60, 0x81, 0x40, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x40, 0x01, 0x00, 0x21, 0x34,
-0x01, 0x00, 0x21, 0x38, 0x00, 0x60, 0x81, 0x40, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x84, 0x02, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x04, 0x00, 0x85, 0x8C, 0x00, 0xA0, 0x03, 0x3C, 0x01, 0x00, 0x02, 0x24,
-0x25, 0x28, 0xA3, 0x00, 0x00, 0x00, 0xA4, 0x8C, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0xB4, 0x02, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x04, 0x00, 0x82, 0x8C, 0x02, 0x00, 0x83, 0x94, 0x00, 0xA0, 0x07, 0x3C,
-0x25, 0x28, 0x47, 0x00, 0x00, 0x00, 0xA2, 0x8C, 0x10, 0x00, 0x02, 0x24,
-0x13, 0x00, 0x62, 0x10, 0x11, 0x00, 0x66, 0x28, 0x06, 0x00, 0xC0, 0x10,
-0x20, 0x00, 0x02, 0x24, 0x08, 0x00, 0x02, 0x24, 0x17, 0x00, 0x62, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24,
-0xFD, 0xFF, 0x62, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x83, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0xAC, 0x04, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x10, 0x47, 0x00, 0x00, 0x00, 0x42, 0x8C,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xA4, 0x04, 0x00, 0x83, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x18, 0x67, 0x00, 0x00, 0x00, 0x62, 0x94,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0xA0, 0x04, 0x00, 0x83, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x18, 0x67, 0x00, 0x00, 0x00, 0x62, 0x90,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x47, 0x24, 0x24, 0x38, 0xE3, 0x90, 0xFF, 0xFF, 0xA5, 0x30,
-0x09, 0x00, 0xA3, 0x10, 0x21, 0x20, 0xC0, 0x00, 0x94, 0x38, 0xE2, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xC2, 0xAC, 0x9E, 0x38, 0xE3, 0x94,
-0x0E, 0x00, 0x02, 0x24, 0x14, 0x00, 0xC2, 0xAC, 0x17, 0x0A, 0x00, 0x08,
-0x0C, 0x00, 0xC3, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0x02, 0x80, 0x11, 0x3C,
-0x1C, 0x00, 0xBF, 0xAF, 0x18, 0x00, 0xB2, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x60, 0x1B, 0x31, 0x26, 0x7C, 0x38, 0x30, 0x96, 0x02, 0x80, 0x02, 0x3C,
-0x01, 0x80, 0x03, 0x3C, 0x25, 0x80, 0x02, 0x02, 0x25, 0xB0, 0x02, 0x3C,
-0xB8, 0x03, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34, 0x60, 0x00, 0x04, 0x26,
-0x80, 0x00, 0x05, 0x26, 0x00, 0x00, 0x43, 0xAC, 0xC2, 0x1B, 0x00, 0x0C,
-0x03, 0x00, 0x06, 0x24, 0x21, 0x20, 0x00, 0x02, 0x21, 0x28, 0x00, 0x00,
-0xEC, 0x54, 0x00, 0x0C, 0x08, 0x00, 0x06, 0x24, 0x7C, 0x38, 0x22, 0x8E,
-0x0C, 0x00, 0x03, 0x24, 0x0C, 0x00, 0x43, 0xAE, 0x08, 0x00, 0x42, 0xAE,
-0x12, 0x00, 0x02, 0x24, 0x14, 0x00, 0x42, 0xAE, 0x21, 0x20, 0x40, 0x02,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x17, 0x0A, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0xD8, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x1C, 0x00, 0xB1, 0xAF,
-0x20, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x0D, 0x00, 0x03, 0x92, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x60, 0x14,
-0x21, 0x88, 0x00, 0x00, 0x01, 0x00, 0x03, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0xF0, 0x5D, 0x43, 0xA0, 0x0C, 0x00, 0x02, 0x92, 0x02, 0x80, 0x05, 0x3C,
-0x06, 0x5E, 0xA2, 0xA0, 0x00, 0x00, 0x04, 0x92, 0x05, 0x00, 0x02, 0x24,
-0xFF, 0x00, 0x83, 0x30, 0x41, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x03, 0x00, 0x02, 0x24, 0x31, 0x00, 0x62, 0x10, 0xFF, 0x00, 0x84, 0x30,
-0x09, 0x00, 0x82, 0x2C, 0x25, 0x00, 0x40, 0x10, 0x02, 0x80, 0x10, 0x3C,
-0xEC, 0x5D, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x42, 0x30,
-0x21, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x99, 0x61, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xEC, 0x5D, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x37, 0x00, 0x40, 0x10, 0x02, 0x80, 0x03, 0x3C, 0x10, 0x37, 0x62, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30, 0x54, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x0E, 0x5E, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x0E, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24,
-0x0E, 0x5E, 0x62, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0xEE, 0x5D, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x04, 0x00, 0x42, 0x28,
-0x06, 0x00, 0x40, 0x10, 0x04, 0x00, 0x04, 0x24, 0x4B, 0x2E, 0x00, 0x0C,
-0x01, 0x00, 0x05, 0x24, 0x5B, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x00, 0x11, 0x24, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x21, 0x10, 0x20, 0x02, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x0B, 0x00, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x14,
-0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x01, 0x00, 0x02, 0x24,
-0x09, 0x5E, 0x62, 0xA0, 0x09, 0x5E, 0x63, 0x90, 0x02, 0x80, 0x02, 0x3C,
-0x0A, 0x5E, 0x43, 0xA0, 0x00, 0x00, 0x04, 0x92, 0x33, 0x41, 0x00, 0x08,
-0xFF, 0x00, 0x84, 0x30, 0x06, 0x5E, 0xA0, 0xA0, 0x0C, 0x00, 0x03, 0x92,
-0x02, 0x80, 0x02, 0x3C, 0x04, 0x5E, 0x43, 0xA0, 0x00, 0x00, 0x04, 0x92,
-0x30, 0x41, 0x00, 0x08, 0xFF, 0x00, 0x83, 0x30, 0x42, 0xB0, 0x06, 0x3C,
-0x00, 0x00, 0xC3, 0x90, 0xEF, 0xFF, 0x02, 0x24, 0x03, 0x00, 0xC7, 0x34,
-0x24, 0x18, 0x62, 0x00, 0x40, 0x00, 0x02, 0x24, 0x00, 0x00, 0xC3, 0xA0,
-0x0C, 0x00, 0x04, 0x24, 0x00, 0x00, 0xE2, 0xA0, 0x4B, 0x2E, 0x00, 0x0C,
-0x01, 0x00, 0x05, 0x24, 0x02, 0x80, 0x03, 0x3C, 0xC6, 0x5C, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x42, 0x30, 0x15, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x24, 0x00, 0x02, 0x05, 0x3C,
-0xC1, 0x43, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x42, 0x24, 0x2A, 0x1C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xCA, 0xFF, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x3A, 0x44, 0x94,
-0x2A, 0x1C, 0x40, 0xA0, 0x00, 0xC0, 0x84, 0x24, 0xA3, 0x31, 0x00, 0x0C,
-0xFF, 0xFF, 0x84, 0x30, 0x5B, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x0E, 0x5E, 0x40, 0xA0, 0x5B, 0x41, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0xA8, 0x2D, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24, 0x89, 0x41, 0x00, 0x08,
-0x00, 0x08, 0x04, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0x02, 0x80, 0x11, 0x3C,
-0x10, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0x30, 0x26, 0xB0, 0x1B, 0x07, 0x96,
-0x18, 0x00, 0xBF, 0xAF, 0xFF, 0xFF, 0xE3, 0x30, 0x00, 0x01, 0x62, 0x30,
-0x0E, 0x00, 0x40, 0x10, 0x01, 0x00, 0x66, 0x30, 0x02, 0x80, 0x04, 0x3C,
-0xB4, 0x55, 0x84, 0x24, 0x03, 0x00, 0x05, 0x24, 0x1E, 0x00, 0xC0, 0x14,
-0x04, 0x00, 0x62, 0x30, 0x02, 0x00, 0x40, 0x10, 0xFB, 0xF6, 0xE3, 0x30,
-0xB0, 0x1B, 0x03, 0xA6, 0x87, 0x54, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x4C, 0x00, 0x42, 0x34, 0x00, 0x00, 0x40, 0xA0,
-0x21, 0x20, 0x00, 0x00, 0x95, 0x0E, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00,
-0x25, 0xB0, 0x06, 0x3C, 0x48, 0x00, 0xC6, 0x34, 0x00, 0x00, 0xC5, 0x8C,
-0x60, 0x1B, 0x24, 0x26, 0x7B, 0xFF, 0x03, 0x3C, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xFF, 0xFF, 0x63, 0x34,
-0x21, 0x10, 0x00, 0x00, 0x24, 0x28, 0xA3, 0x00, 0x20, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0xC5, 0xAC, 0xBC, 0x40, 0x80, 0xAC, 0xE8, 0x39, 0x80, 0xAC,
-0x04, 0x3A, 0x80, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0xFC, 0x40, 0x80, 0xAC,
-0x1C, 0x4F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x1B, 0x02, 0x96,
-0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x42, 0x30, 0x87, 0x54, 0x00, 0x0C,
-0xB0, 0x1B, 0x02, 0xA6, 0x25, 0xB0, 0x02, 0x3C, 0x4C, 0x00, 0x42, 0x34,
-0x00, 0x00, 0x40, 0xA0, 0xBB, 0x41, 0x00, 0x08, 0x21, 0x20, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x01, 0x00, 0x83, 0x90, 0x02, 0x80, 0x02, 0x3C, 0x21, 0x38, 0x80, 0x00,
-0x8C, 0x5B, 0x43, 0xAC, 0x01, 0x00, 0x84, 0x90, 0x00, 0x00, 0xE2, 0x90,
-0x02, 0x80, 0x06, 0x3C, 0xFF, 0x00, 0x85, 0x30, 0x80, 0x10, 0x02, 0x00,
-0x25, 0x28, 0xA2, 0x00, 0x88, 0xDE, 0xC6, 0x24, 0xFF, 0x00, 0x84, 0x30,
-0x00, 0x80, 0xA5, 0x34, 0x6F, 0x20, 0x00, 0x0C, 0x03, 0x00, 0xE7, 0x24,
-0x10, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x03, 0x3C, 0x1C, 0x00, 0xBF, 0xAF, 0x10, 0x37, 0x62, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x30, 0x00, 0x01, 0x42, 0x30,
-0x04, 0x00, 0x40, 0x10, 0x21, 0x80, 0x80, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x06, 0x00, 0x60, 0x14, 0x60, 0xE7, 0x84, 0x24, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x13, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x06, 0x00, 0x07, 0x92, 0x07, 0x00, 0x02, 0x26, 0x21, 0x20, 0x00, 0x02,
-0x80, 0x38, 0x07, 0x00, 0x00, 0x80, 0xE7, 0x34, 0x05, 0x00, 0x05, 0x24,
-0x21, 0x30, 0x00, 0x00, 0x02, 0x54, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27,
-0x02, 0x80, 0x02, 0x3C, 0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF,
-0x60, 0x1B, 0x45, 0x24, 0xFC, 0x40, 0xA3, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x06, 0x00, 0x60, 0x14, 0x21, 0x80, 0x80, 0x00, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xF8, 0x40, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0x45, 0x00, 0xF0, 0x40, 0x40, 0xA0, 0x00, 0x00, 0x84, 0x8C,
-0xC3, 0x1A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8E,
-0x03, 0x00, 0x04, 0x24, 0xD9, 0x12, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x84, 0x90,
-0x75, 0x0D, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xD8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x10, 0x3C,
-0x20, 0x00, 0xB2, 0xAF, 0x60, 0x1B, 0x02, 0x26, 0x24, 0x00, 0xBF, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0xB0, 0x1B, 0x45, 0x94, 0x21, 0x90, 0x80, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C, 0x80, 0xE7, 0x84, 0x24,
-0x00, 0x00, 0x42, 0x96, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x43, 0x24,
-0x20, 0x00, 0x42, 0x24, 0xC2, 0x18, 0x03, 0x00, 0xC2, 0x28, 0x02, 0x00,
-0x07, 0x00, 0x42, 0x30, 0x02, 0x00, 0x40, 0x14, 0xC0, 0x20, 0x03, 0x00,
-0xC0, 0x20, 0x05, 0x00, 0x53, 0x21, 0x00, 0x0C, 0x60, 0x1B, 0x11, 0x26,
-0x02, 0x80, 0x05, 0x3C, 0x21, 0x38, 0x40, 0x00, 0x21, 0x80, 0x40, 0x00,
-0x0A, 0x00, 0x04, 0x24, 0x22, 0x00, 0x40, 0x10, 0x70, 0xE7, 0xA5, 0x24,
-0x02, 0x00, 0x46, 0x92, 0x10, 0x38, 0x25, 0x8E, 0x72, 0x01, 0x00, 0x0C,
-0x08, 0x00, 0xC6, 0x24, 0x5B, 0x01, 0x00, 0x0C, 0x0A, 0x00, 0x04, 0x24,
-0x08, 0x00, 0x02, 0x96, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x04, 0x3C,
-0x25, 0x28, 0x45, 0x00, 0x74, 0x03, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0xB0, 0x55, 0x84, 0x24, 0x74, 0x21, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02,
-0x31, 0x46, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x37, 0x26, 0x8E,
-0x58, 0x38, 0x25, 0x8E, 0x01, 0x00, 0x04, 0x24, 0x00, 0x01, 0x07, 0x24,
-0x01, 0x00, 0x02, 0x24, 0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF,
-0x5B, 0x01, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C, 0x18, 0xE7, 0x84, 0x24,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x82, 0x90, 0x02, 0x80, 0x03, 0x3C,
-0x60, 0x1B, 0x63, 0x24, 0x07, 0x00, 0x40, 0x10, 0x21, 0x20, 0x60, 0x00,
-0xD0, 0x07, 0x02, 0x24, 0x3C, 0x3A, 0x62, 0xAC, 0x01, 0x00, 0x03, 0x24,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x48, 0x41, 0x83, 0xA0,
-0x21, 0x10, 0x00, 0x00, 0x3C, 0x3A, 0x60, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0x48, 0x41, 0x60, 0xA0, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF,
-0x25, 0xB0, 0x10, 0x3C, 0x21, 0x28, 0x80, 0x00, 0x06, 0x00, 0x06, 0x24,
-0x14, 0x00, 0xBF, 0xAF, 0xF4, 0x54, 0x00, 0x0C, 0x50, 0x00, 0x04, 0x36,
-0x02, 0x80, 0x04, 0x3C, 0x50, 0x00, 0x05, 0x36, 0x48, 0x37, 0x84, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0x94, 0xE7, 0x84, 0x24, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x25, 0xB0, 0x05, 0x3C, 0x01, 0x80, 0x03, 0x3C,
-0xE8, 0xFF, 0xBD, 0x27, 0x21, 0x30, 0x80, 0x00, 0x18, 0x03, 0xA2, 0x34,
-0xC0, 0x0B, 0x63, 0x24, 0x01, 0x00, 0x04, 0x24, 0x14, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x43, 0xAC, 0x66, 0x00, 0xC4, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x09, 0x00, 0xC0, 0x10, 0x02, 0x00, 0x02, 0x24,
-0x36, 0x00, 0xC2, 0x10, 0x03, 0x00, 0x02, 0x24, 0x8B, 0x00, 0xC2, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x50, 0x24, 0x70, 0x08, 0x02, 0x24, 0x34, 0x1C, 0x02, 0xAE,
-0xE0, 0x08, 0x03, 0x24, 0x40, 0x08, 0x02, 0x24, 0x38, 0x1C, 0x03, 0xAE,
-0x44, 0x1C, 0x02, 0xAE, 0x78, 0x08, 0x03, 0x24, 0x0C, 0x08, 0x02, 0x24,
-0x48, 0x1C, 0x03, 0xAE, 0x4C, 0x1C, 0x02, 0xAE, 0x10, 0x08, 0x03, 0x24,
-0x20, 0x08, 0x02, 0x24, 0x50, 0x1C, 0x03, 0xAE, 0x54, 0x1C, 0x02, 0xAE,
-0x24, 0x08, 0x03, 0x24, 0x58, 0x08, 0x02, 0x24, 0x58, 0x1C, 0x03, 0xAE,
-0x5C, 0x1C, 0x02, 0xAE, 0x50, 0x0C, 0x03, 0x24, 0x54, 0x0C, 0x02, 0x24,
-0x60, 0x1C, 0x03, 0xAE, 0x64, 0x1C, 0x02, 0xAE, 0x14, 0x0C, 0x03, 0x24,
-0x10, 0x0C, 0x02, 0x24, 0x20, 0x08, 0xA4, 0x34, 0x68, 0x1C, 0x03, 0xAE,
-0x60, 0x08, 0x05, 0x24, 0x6C, 0x1C, 0x02, 0xAE, 0x80, 0x0C, 0x03, 0x24,
-0x84, 0x0C, 0x02, 0x24, 0x40, 0x1C, 0x05, 0xAE, 0x70, 0x1C, 0x03, 0xAE,
-0x74, 0x1C, 0x02, 0xAE, 0x31, 0x1C, 0x00, 0xA2, 0xFA, 0x5B, 0x00, 0x0C,
-0x3C, 0x1C, 0x05, 0xAE, 0x00, 0x01, 0x42, 0x30, 0x31, 0x00, 0x40, 0x14,
-0xB8, 0x08, 0x02, 0x24, 0xA0, 0x08, 0x02, 0x24, 0x78, 0x1C, 0x02, 0xAE,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0xA8, 0x08, 0x03, 0x24, 0x78, 0x1C, 0x43, 0xAC, 0x74, 0x08, 0x03, 0x24,
-0xE4, 0x08, 0x04, 0x24, 0x34, 0x1C, 0x43, 0xAC, 0x48, 0x08, 0x03, 0x24,
-0x38, 0x1C, 0x44, 0xAC, 0x44, 0x1C, 0x43, 0xAC, 0x7C, 0x08, 0x04, 0x24,
-0x0C, 0x08, 0x03, 0x24, 0x48, 0x1C, 0x44, 0xAC, 0x4C, 0x1C, 0x43, 0xAC,
-0x18, 0x08, 0x04, 0x24, 0x30, 0x08, 0x03, 0x24, 0x50, 0x1C, 0x44, 0xAC,
-0x54, 0x1C, 0x43, 0xAC, 0x34, 0x08, 0x04, 0x24, 0x5C, 0x08, 0x03, 0x24,
-0x58, 0x1C, 0x44, 0xAC, 0x5C, 0x1C, 0x43, 0xAC, 0x60, 0x0C, 0x04, 0x24,
-0x64, 0x0C, 0x03, 0x24, 0x60, 0x1C, 0x44, 0xAC, 0x64, 0x1C, 0x43, 0xAC,
-0x24, 0x0C, 0x04, 0x24, 0x20, 0x0C, 0x03, 0x24, 0x68, 0x08, 0x05, 0x24,
-0x68, 0x1C, 0x44, 0xAC, 0x6C, 0x1C, 0x43, 0xAC, 0x90, 0x0C, 0x04, 0x24,
-0x94, 0x0C, 0x03, 0x24, 0x31, 0x1C, 0x46, 0xA0, 0x40, 0x1C, 0x45, 0xAC,
-0x70, 0x1C, 0x44, 0xAC, 0x74, 0x1C, 0x43, 0xAC, 0x3C, 0x1C, 0x45, 0xAC,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x31, 0x43, 0x00, 0x08, 0x78, 0x1C, 0x02, 0xAE,
-0x60, 0x1B, 0x50, 0x24, 0x70, 0x08, 0x02, 0x24, 0x34, 0x1C, 0x02, 0xAE,
-0xE0, 0x08, 0x03, 0x24, 0x44, 0x08, 0x02, 0x24, 0x38, 0x1C, 0x03, 0xAE,
-0x44, 0x1C, 0x02, 0xAE, 0x78, 0x08, 0x03, 0x24, 0x0C, 0x08, 0x02, 0x24,
-0x48, 0x1C, 0x03, 0xAE, 0x4C, 0x1C, 0x02, 0xAE, 0x14, 0x08, 0x03, 0x24,
-0x28, 0x08, 0x02, 0x24, 0x50, 0x1C, 0x03, 0xAE, 0x54, 0x1C, 0x02, 0xAE,
-0x2C, 0x08, 0x03, 0x24, 0x58, 0x08, 0x02, 0x24, 0x58, 0x1C, 0x03, 0xAE,
-0x5C, 0x1C, 0x02, 0xAE, 0x58, 0x0C, 0x03, 0x24, 0x5C, 0x0C, 0x02, 0x24,
-0x60, 0x1C, 0x03, 0xAE, 0x64, 0x1C, 0x02, 0xAE, 0x1C, 0x0C, 0x03, 0x24,
-0x18, 0x0C, 0x02, 0x24, 0x28, 0x08, 0xA4, 0x34, 0x68, 0x1C, 0x03, 0xAE,
-0x64, 0x08, 0x05, 0x24, 0x6C, 0x1C, 0x02, 0xAE, 0x88, 0x0C, 0x03, 0x24,
-0x8C, 0x0C, 0x02, 0x24, 0x31, 0x1C, 0x06, 0xA2, 0x40, 0x1C, 0x05, 0xAE,
-0x70, 0x1C, 0x03, 0xAE, 0x74, 0x1C, 0x02, 0xAE, 0xFA, 0x5B, 0x00, 0x0C,
-0x3C, 0x1C, 0x05, 0xAE, 0x00, 0x01, 0x42, 0x30, 0x2B, 0x00, 0x40, 0x14,
-0xBC, 0x08, 0x02, 0x24, 0xA4, 0x08, 0x02, 0x24, 0x31, 0x43, 0x00, 0x08,
-0x78, 0x1C, 0x02, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0xAC, 0x08, 0x03, 0x24, 0x78, 0x1C, 0x43, 0xAC, 0x74, 0x08, 0x03, 0x24,
-0xE4, 0x08, 0x04, 0x24, 0x34, 0x1C, 0x43, 0xAC, 0x4C, 0x08, 0x03, 0x24,
-0x38, 0x1C, 0x44, 0xAC, 0x44, 0x1C, 0x43, 0xAC, 0x7C, 0x08, 0x04, 0x24,
-0x0C, 0x08, 0x03, 0x24, 0x48, 0x1C, 0x44, 0xAC, 0x4C, 0x1C, 0x43, 0xAC,
-0x1C, 0x08, 0x04, 0x24, 0x38, 0x08, 0x03, 0x24, 0x50, 0x1C, 0x44, 0xAC,
-0x54, 0x1C, 0x43, 0xAC, 0x3C, 0x08, 0x04, 0x24, 0x5C, 0x08, 0x03, 0x24,
-0x58, 0x1C, 0x44, 0xAC, 0x5C, 0x1C, 0x43, 0xAC, 0x68, 0x0C, 0x04, 0x24,
-0x6C, 0x0C, 0x03, 0x24, 0x60, 0x1C, 0x44, 0xAC, 0x64, 0x1C, 0x43, 0xAC,
-0x2C, 0x0C, 0x04, 0x24, 0x28, 0x0C, 0x03, 0x24, 0x6C, 0x08, 0x05, 0x24,
-0x68, 0x1C, 0x44, 0xAC, 0x6C, 0x1C, 0x43, 0xAC, 0x98, 0x0C, 0x04, 0x24,
-0x9C, 0x0C, 0x03, 0x24, 0x31, 0x1C, 0x46, 0xA0, 0x40, 0x1C, 0x45, 0xAC,
-0x70, 0x1C, 0x44, 0xAC, 0x74, 0x1C, 0x43, 0xAC, 0x5B, 0x43, 0x00, 0x08,
-0x3C, 0x1C, 0x45, 0xAC, 0x31, 0x43, 0x00, 0x08, 0x78, 0x1C, 0x02, 0xAE,
-0xBA, 0x43, 0x00, 0x08, 0x21, 0x18, 0x00, 0x00, 0x20, 0x00, 0x62, 0x2C,
-0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x64, 0x00,
-0x01, 0x00, 0x42, 0x30, 0xFA, 0xFF, 0x40, 0x10, 0x01, 0x00, 0x63, 0x24,
-0xFF, 0xFF, 0x63, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0xD8, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0xFF, 0xFF, 0x02, 0x24,
-0x21, 0x88, 0xA0, 0x00, 0x1C, 0x00, 0xB3, 0xAF, 0x18, 0x00, 0xB2, 0xAF,
-0x20, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0x90, 0xC0, 0x00,
-0x21, 0x28, 0xC0, 0x00, 0x0B, 0x00, 0x22, 0x12, 0x21, 0x98, 0x80, 0x00,
-0x26, 0x5C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x20, 0x02,
-0xB5, 0x43, 0x00, 0x0C, 0x21, 0x80, 0x40, 0x00, 0x27, 0x28, 0x11, 0x00,
-0x24, 0x28, 0xB0, 0x00, 0x04, 0x10, 0x52, 0x00, 0x25, 0x28, 0xA2, 0x00,
-0x21, 0x20, 0x60, 0x02, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x03, 0x5C, 0x00, 0x08, 0x28, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0x30, 0x80, 0x00, 0xA4, 0x37, 0x44, 0x8C, 0xC1, 0x43, 0x00, 0x08,
-0xFF, 0xFF, 0x05, 0x24, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xBF, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x26, 0x5C, 0x00, 0x0C,
-0x21, 0x88, 0xA0, 0x00, 0x21, 0x80, 0x40, 0x00, 0xB5, 0x43, 0x00, 0x0C,
-0x21, 0x20, 0x20, 0x02, 0x24, 0x80, 0x11, 0x02, 0x06, 0x10, 0x50, 0x00,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB2, 0xAF, 0x02, 0x80, 0x12, 0x3C, 0x60, 0x1B, 0x52, 0x26,
-0x14, 0x00, 0xB1, 0xAF, 0x21, 0x88, 0x80, 0x00, 0x24, 0x08, 0x04, 0x24,
-0x24, 0x00, 0xBF, 0xAF, 0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF,
-0x26, 0x5C, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF, 0x58, 0x1C, 0x44, 0x8E,
-0x21, 0xA0, 0x40, 0x00, 0x26, 0x5C, 0x00, 0x0C, 0xC0, 0x8D, 0x11, 0x00,
-0xFF, 0x7F, 0x05, 0x3C, 0x7F, 0x80, 0x03, 0x3C, 0xFF, 0xFF, 0xA5, 0x34,
-0xFF, 0xFF, 0x63, 0x34, 0x24, 0x28, 0x85, 0x02, 0x24, 0x08, 0x04, 0x24,
-0x03, 0x5C, 0x00, 0x0C, 0x24, 0x80, 0x43, 0x00, 0x2C, 0x1F, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0x00, 0x80, 0x13, 0x3C, 0x58, 0x1C, 0x44, 0x8E,
-0x25, 0x80, 0x11, 0x02, 0x25, 0x80, 0x13, 0x02, 0x03, 0x5C, 0x00, 0x0C,
-0x21, 0x28, 0x00, 0x02, 0x2C, 0x1F, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x25, 0x28, 0x93, 0x02, 0x03, 0x5C, 0x00, 0x0C, 0x24, 0x08, 0x04, 0x24,
-0x2C, 0x1F, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24, 0x78, 0x1C, 0x44, 0x8E,
-0x0F, 0x00, 0x05, 0x3C, 0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB4, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0xFF, 0xFF, 0xA5, 0x34, 0xE3, 0x43, 0x00, 0x08,
-0x28, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF,
-0x02, 0x80, 0x11, 0x3C, 0x10, 0x00, 0xB0, 0xAF, 0x18, 0x00, 0xBF, 0xAF,
-0x60, 0x1B, 0x27, 0x26, 0x33, 0x1C, 0xE5, 0x90, 0x01, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x94, 0x10, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0x02, 0x00, 0x06, 0x24, 0x00, 0x00, 0x43, 0xAC, 0x34, 0x00, 0xA6, 0x10,
-0x21, 0x80, 0x80, 0x00, 0x03, 0x00, 0x03, 0x24, 0x3A, 0x00, 0xA3, 0x10,
-0x2E, 0x00, 0x02, 0x2E, 0x10, 0x00, 0x02, 0x2E, 0x07, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x04, 0x32, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xF3, 0x43, 0x00, 0x08,
-0x20, 0x00, 0xBD, 0x27, 0xFA, 0xFF, 0xA6, 0x14, 0xFF, 0x00, 0x04, 0x32,
-0x31, 0x1C, 0xE4, 0x90, 0x01, 0x00, 0x02, 0x24, 0x33, 0x00, 0x82, 0x10,
-0x02, 0x00, 0x82, 0x28, 0x38, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x38, 0x00, 0x85, 0x10, 0x60, 0x1B, 0x22, 0x26, 0x2E, 0x00, 0x83, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x24, 0xE3, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0xFF, 0xFC, 0x06, 0x3C, 0xFF, 0xFF, 0xC6, 0x34,
-0x24, 0x30, 0x46, 0x00, 0x00, 0x08, 0x04, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0x60, 0x1B, 0x22, 0x26, 0x31, 0x1C, 0x44, 0x90,
-0x01, 0x00, 0x03, 0x24, 0x07, 0x00, 0x83, 0x10, 0x02, 0x00, 0x82, 0x28,
-0x2C, 0x00, 0x40, 0x14, 0x02, 0x00, 0x02, 0x24, 0x2C, 0x00, 0x82, 0x10,
-0x03, 0x00, 0x02, 0x24, 0xDB, 0xFF, 0x82, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x22, 0x26, 0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x3C,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0x3B, 0x44, 0x00, 0x08,
-0xFF, 0x00, 0x04, 0x32, 0x25, 0x00, 0x82, 0x2C, 0xCC, 0xFF, 0x40, 0x14,
-0x03, 0x00, 0x03, 0x24, 0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xC7, 0xFF, 0x40, 0x14, 0x10, 0x00, 0x02, 0x2E,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x60, 0x1B, 0x22, 0x26, 0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x3C,
-0xC1, 0x43, 0x00, 0x0C, 0x0F, 0x00, 0x06, 0x24, 0x4D, 0x44, 0x00, 0x08,
-0x00, 0x08, 0x04, 0x24, 0xCC, 0xFF, 0x80, 0x14, 0x60, 0x1B, 0x22, 0x26,
-0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0x0F, 0x00, 0x06, 0x24, 0x4D, 0x44, 0x00, 0x08, 0x00, 0x08, 0x04, 0x24,
-0xB2, 0xFF, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x22, 0x26,
-0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0x3B, 0x44, 0x00, 0x08, 0xFF, 0x00, 0x04, 0x32,
-0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0x02, 0x80, 0x11, 0x3C,
-0x60, 0x1B, 0x28, 0x26, 0x33, 0x1C, 0x06, 0x91, 0x01, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x40, 0x12, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0x02, 0x00, 0x07, 0x24, 0x18, 0x00, 0xB2, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x1C, 0x00, 0xBF, 0xAF, 0x00, 0x00, 0x43, 0xAC, 0x21, 0x90, 0xA0, 0x00,
-0x39, 0x00, 0xC7, 0x10, 0xFF, 0x00, 0x90, 0x30, 0x03, 0x00, 0x03, 0x24,
-0x3F, 0x00, 0xC3, 0x10, 0x2E, 0x00, 0x02, 0x2E, 0x10, 0x00, 0x02, 0x2E,
-0x0C, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x04, 0x3C,
-0xFF, 0xFF, 0x84, 0x34, 0x24, 0x20, 0x44, 0x02, 0x00, 0x15, 0x10, 0x00,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x25, 0x20, 0x44, 0x00, 0xDE, 0x43, 0x00, 0x08,
-0x20, 0x00, 0xBD, 0x27, 0xF5, 0xFF, 0xC7, 0x14, 0x0F, 0x00, 0x04, 0x3C,
-0x31, 0x1C, 0x04, 0x91, 0x01, 0x00, 0x02, 0x24, 0x33, 0x00, 0x82, 0x10,
-0x02, 0x00, 0x82, 0x28, 0x38, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x38, 0x00, 0x86, 0x10, 0x60, 0x1B, 0x22, 0x26, 0x2E, 0x00, 0x83, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x24, 0xE3, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0xFF, 0xFC, 0x06, 0x3C, 0xFF, 0xFF, 0xC6, 0x34,
-0x24, 0x30, 0x46, 0x00, 0x00, 0x08, 0x04, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0x60, 0x1B, 0x22, 0x26, 0x31, 0x1C, 0x44, 0x90,
-0x01, 0x00, 0x03, 0x24, 0x07, 0x00, 0x83, 0x10, 0x02, 0x00, 0x82, 0x28,
-0x2C, 0x00, 0x40, 0x14, 0x02, 0x00, 0x02, 0x24, 0x2C, 0x00, 0x82, 0x10,
-0x03, 0x00, 0x02, 0x24, 0xD6, 0xFF, 0x82, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x60, 0x1B, 0x22, 0x26, 0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x3C,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0xA8, 0x44, 0x00, 0x08,
-0x0F, 0x00, 0x04, 0x3C, 0x25, 0x00, 0x02, 0x2E, 0xC7, 0xFF, 0x40, 0x14,
-0x03, 0x00, 0x03, 0x24, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xC1, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x60, 0x1B, 0x22, 0x26, 0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x3C,
-0xC1, 0x43, 0x00, 0x0C, 0x0F, 0x00, 0x06, 0x24, 0xBF, 0x44, 0x00, 0x08,
-0x00, 0x08, 0x04, 0x24, 0xCC, 0xFF, 0x80, 0x14, 0x60, 0x1B, 0x22, 0x26,
-0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0x0F, 0x00, 0x06, 0x24, 0xBF, 0x44, 0x00, 0x08, 0x00, 0x08, 0x04, 0x24,
-0xAD, 0xFF, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x22, 0x26,
-0x34, 0x1C, 0x44, 0x8C, 0x0F, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0xA8, 0x44, 0x00, 0x08, 0x0F, 0x00, 0x04, 0x3C,
-0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x14, 0x00, 0xBF, 0xAF, 0xF3, 0x43, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00,
-0x40, 0x01, 0x44, 0x34, 0x21, 0x18, 0x40, 0x00, 0x1F, 0x00, 0x02, 0x2E,
-0x00, 0x23, 0x04, 0x00, 0x10, 0x00, 0x40, 0x10, 0x10, 0x00, 0x05, 0x2E,
-0x00, 0x01, 0x64, 0x34, 0x06, 0x00, 0xA0, 0x10, 0x00, 0x23, 0x04, 0x00,
-0x21, 0x10, 0x00, 0x02, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xDE, 0x43, 0x00, 0x0C,
-0xF1, 0xFF, 0x10, 0x26, 0x21, 0x10, 0x00, 0x02, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0xDE, 0x43, 0x00, 0x0C, 0xE2, 0xFF, 0x10, 0x26, 0x21, 0x10, 0x00, 0x02,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x25, 0xB0, 0x02, 0x3C,
-0x18, 0x00, 0xBF, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x21, 0x20, 0x82, 0x00, 0x00, 0x00, 0x90, 0x8C, 0x21, 0x88, 0xA0, 0x00,
-0xB5, 0x43, 0x00, 0x0C, 0x21, 0x20, 0xA0, 0x00, 0x24, 0x80, 0x11, 0x02,
-0x06, 0x10, 0x50, 0x00, 0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xD8, 0xFF, 0xBD, 0x27, 0x25, 0xB0, 0x02, 0x3C, 0x18, 0x00, 0xB2, 0xAF,
-0x21, 0x90, 0x82, 0x00, 0xFF, 0xFF, 0x02, 0x24, 0x1C, 0x00, 0xB3, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x20, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x21, 0x88, 0xA0, 0x00, 0x21, 0x20, 0xA0, 0x00, 0x21, 0x18, 0x40, 0x02,
-0x10, 0x00, 0xA2, 0x10, 0x21, 0x98, 0xC0, 0x00, 0x00, 0x00, 0x50, 0x8E,
-0xB5, 0x43, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x27, 0x18, 0x11, 0x00,
-0x24, 0x18, 0x70, 0x00, 0x04, 0x10, 0x53, 0x00, 0x25, 0x18, 0x62, 0x00,
-0x00, 0x00, 0x43, 0xAE, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x28, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x66, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C,
-0x21, 0x38, 0x82, 0x00, 0xFF, 0xFF, 0x02, 0x24, 0x27, 0x40, 0x05, 0x00,
-0x08, 0x00, 0xA2, 0x10, 0x24, 0x18, 0xC5, 0x00, 0x00, 0x00, 0xE2, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x02, 0x01, 0x25, 0x10, 0x43, 0x00,
-0x00, 0x00, 0xE2, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xE6, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0xFF, 0xFF, 0x02, 0x24,
-0x21, 0x80, 0xA0, 0x00, 0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x1C, 0x00, 0xBF, 0xAF, 0x21, 0x88, 0xC0, 0x00, 0x21, 0x28, 0xC0, 0x00,
-0x08, 0x00, 0x02, 0x12, 0x21, 0x90, 0x80, 0x00, 0x26, 0x5C, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x27, 0x28, 0x10, 0x00, 0x24, 0x28, 0xA2, 0x00,
-0x24, 0x10, 0x30, 0x02, 0x25, 0x28, 0xA2, 0x00, 0x21, 0x20, 0x40, 0x02,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x03, 0x5C, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27,
-0x01, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x03, 0x3C, 0xD0, 0xFF, 0xBD, 0x27,
-0x0C, 0x16, 0x42, 0x24, 0x18, 0x03, 0x63, 0x34, 0x20, 0x00, 0xB2, 0xAF,
-0x00, 0x00, 0x62, 0xAC, 0x21, 0x90, 0x80, 0x00, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x00, 0xB3, 0xAF, 0x1C, 0x00, 0xB1, 0xAF, 0x21, 0x98, 0xC0, 0x00,
-0x21, 0x88, 0xA0, 0x00, 0x28, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x18, 0x00, 0xB0, 0xAF, 0x0F, 0x00, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x21, 0x20, 0x40, 0x02, 0x0A, 0x00, 0x22, 0x12, 0x21, 0x28, 0x60, 0x02,
-0x25, 0x44, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x20, 0x02,
-0xB5, 0x43, 0x00, 0x0C, 0x21, 0x80, 0x40, 0x00, 0x27, 0x28, 0x11, 0x00,
-0x24, 0x28, 0xB0, 0x00, 0x04, 0x10, 0x53, 0x00, 0x25, 0x28, 0xA2, 0x00,
-0x90, 0x44, 0x00, 0x0C, 0xFF, 0x00, 0x44, 0x32, 0x90, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x28, 0x00, 0xBF, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27, 0x01, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0xB0, 0x16, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0xE0, 0xFF, 0xBD, 0x27, 0x00, 0x00, 0x43, 0xAC, 0x18, 0x00, 0xBF, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x25, 0x44, 0x00, 0x0C,
-0x21, 0x88, 0xA0, 0x00, 0x21, 0x80, 0x40, 0x00, 0xB5, 0x43, 0x00, 0x0C,
-0x21, 0x20, 0x20, 0x02, 0x24, 0x80, 0x11, 0x02, 0x06, 0x10, 0x50, 0x00,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xD0, 0xFF, 0xBD, 0x27,
-0x24, 0x00, 0xB5, 0xAF, 0xFF, 0x00, 0x84, 0x30, 0x21, 0xA8, 0xC0, 0x00,
-0x28, 0x00, 0xB6, 0xAF, 0x1C, 0x00, 0xB3, 0xAF, 0x2C, 0x00, 0xBF, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x21, 0xB0, 0xA0, 0x00, 0xF0, 0x42, 0x00, 0x0C,
-0x21, 0x98, 0x00, 0x00, 0x21, 0x00, 0xA0, 0x16, 0x80, 0x10, 0x13, 0x00,
-0xFF, 0x45, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x02, 0x24,
-0x23, 0x00, 0x02, 0x12, 0x05, 0x00, 0x04, 0x24, 0xFC, 0x00, 0x02, 0x24,
-0x37, 0x00, 0x02, 0x12, 0x00, 0x00, 0x00, 0x00, 0xFB, 0x00, 0x02, 0x24,
-0x30, 0x00, 0x02, 0x12, 0x32, 0x00, 0x04, 0x24, 0xFA, 0x00, 0x02, 0x24,
-0x2D, 0x00, 0x02, 0x12, 0x05, 0x00, 0x04, 0x24, 0xF9, 0x00, 0x02, 0x24,
-0x29, 0x00, 0x02, 0x12, 0x0F, 0x00, 0x05, 0x3C, 0x04, 0x00, 0xD1, 0x8C,
-0xFF, 0xFF, 0xA5, 0x34, 0x21, 0x20, 0x00, 0x02, 0x83, 0x45, 0x00, 0x0C,
-0x21, 0x30, 0x20, 0x02, 0x2C, 0x1F, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x19, 0x00, 0x02, 0x24, 0x28, 0x00, 0x02, 0x12, 0x21, 0x90, 0x00, 0x00,
-0x02, 0x00, 0x62, 0x26, 0xFF, 0x00, 0x53, 0x30, 0x2B, 0x18, 0x75, 0x02,
-0x0F, 0x00, 0x60, 0x10, 0x80, 0x10, 0x13, 0x00, 0x21, 0x30, 0x56, 0x00,
-0x00, 0x00, 0xD0, 0x8C, 0xFF, 0x00, 0x02, 0x24, 0x0A, 0x00, 0x02, 0x12,
-0xFE, 0x00, 0x02, 0x24, 0xDC, 0xFF, 0x02, 0x16, 0x32, 0x00, 0x04, 0x24,
-0x2C, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x62, 0x26,
-0xFF, 0x00, 0x53, 0x30, 0x2B, 0x18, 0x75, 0x02, 0xF3, 0xFF, 0x60, 0x14,
-0x80, 0x10, 0x13, 0x00, 0x2C, 0x00, 0xBF, 0x8F, 0x28, 0x00, 0xB6, 0x8F,
-0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0x01, 0x00, 0x04, 0x24, 0x5B, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xED, 0x45, 0x00, 0x08, 0x02, 0x00, 0x62, 0x26, 0x2C, 0x1F, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0xFB, 0x45, 0x00, 0x08, 0x02, 0x00, 0x62, 0x26,
-0x0F, 0x00, 0x14, 0x3C, 0x21, 0x20, 0x00, 0x02, 0xAC, 0x45, 0x00, 0x0C,
-0xFF, 0xFF, 0x85, 0x36, 0x21, 0x20, 0x00, 0x02, 0xFF, 0xFF, 0x85, 0x36,
-0xD2, 0xFF, 0x51, 0x10, 0x21, 0x30, 0x20, 0x02, 0x83, 0x45, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x2C, 0x1F, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x01, 0x00, 0x42, 0x26, 0xFF, 0x00, 0x52, 0x30, 0x0A, 0x00, 0x43, 0x2E,
-0xF2, 0xFF, 0x60, 0x14, 0x21, 0x20, 0x00, 0x02, 0xF0, 0x42, 0x00, 0x0C,
-0x21, 0x20, 0x00, 0x00, 0x2C, 0x00, 0xBF, 0x8F, 0x28, 0x00, 0xB6, 0x8F,
-0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0xB0, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x4C, 0x00, 0xBF, 0xAF,
-0x48, 0x00, 0xBE, 0xAF, 0x40, 0x00, 0xB6, 0xAF, 0x3C, 0x00, 0xB5, 0xAF,
-0x38, 0x00, 0xB4, 0xAF, 0x34, 0x00, 0xB3, 0xAF, 0x30, 0x00, 0xB2, 0xAF,
-0x2C, 0x00, 0xB1, 0xAF, 0x28, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0x55, 0x24,
-0x44, 0x00, 0xB7, 0xAF, 0x58, 0x38, 0xA3, 0x96, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x05, 0x3C, 0x25, 0x98, 0x62, 0x00, 0x90, 0xDE, 0xA5, 0x24,
-0x24, 0x00, 0x64, 0x26, 0x06, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x20, 0x00, 0x60, 0xA6, 0x02, 0x80, 0x05, 0x3C, 0x48, 0x37, 0xA5, 0x24,
-0x2A, 0x00, 0x64, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x02, 0x80, 0x05, 0x3C, 0xB4, 0x55, 0xA5, 0x24, 0x06, 0x00, 0x06, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x30, 0x00, 0x64, 0x26, 0x20, 0x00, 0x63, 0x96,
-0x02, 0x80, 0x02, 0x3C, 0xB0, 0x55, 0x42, 0x24, 0x03, 0xFF, 0x63, 0x30,
-0x80, 0x00, 0x63, 0x34, 0x74, 0x00, 0x54, 0x24, 0x20, 0x00, 0x63, 0xA6,
-0x21, 0x20, 0x80, 0x02, 0x20, 0x00, 0x02, 0x24, 0x40, 0x00, 0x72, 0x26,
-0xFB, 0x51, 0x00, 0x0C, 0x1C, 0x00, 0xA2, 0xAF, 0x21, 0x28, 0x40, 0x00,
-0x21, 0x20, 0x40, 0x02, 0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x24,
-0x1C, 0x00, 0xA2, 0x8F, 0x21, 0x20, 0x80, 0x02, 0x42, 0x00, 0x72, 0x26,
-0x02, 0x00, 0x42, 0x24, 0x16, 0x52, 0x00, 0x0C, 0x1C, 0x00, 0xA2, 0xAF,
-0x21, 0x28, 0x40, 0x00, 0x21, 0x20, 0x40, 0x02, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x06, 0x24, 0x02, 0x80, 0x03, 0x3C, 0xB0, 0x55, 0x63, 0x24,
-0x1C, 0x00, 0xA2, 0x8F, 0x0C, 0x00, 0x66, 0x8C, 0x60, 0x00, 0x71, 0x24,
-0x1C, 0x00, 0xB0, 0x27, 0x10, 0x00, 0x67, 0x24, 0x21, 0x28, 0x00, 0x00,
-0x02, 0x00, 0x42, 0x24, 0x44, 0x00, 0x64, 0x26, 0x1C, 0x00, 0xA2, 0xAF,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0x20, 0x20, 0x02,
-0x1B, 0x53, 0x00, 0x0C, 0x21, 0x90, 0x40, 0x00, 0x21, 0xB0, 0x40, 0x00,
-0x08, 0x00, 0x06, 0x24, 0x09, 0x00, 0x42, 0x2C, 0x21, 0x20, 0x40, 0x02,
-0x21, 0x38, 0x20, 0x02, 0x0B, 0x30, 0xC2, 0x02, 0x01, 0x00, 0x05, 0x24,
-0x20, 0x00, 0xA2, 0xAF, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x03, 0x3C, 0xB0, 0x55, 0x63, 0x24, 0x48, 0x00, 0x67, 0x24,
-0x21, 0x20, 0x40, 0x00, 0x03, 0x00, 0x05, 0x24, 0x01, 0x00, 0x06, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0x20, 0x40, 0x00,
-0x06, 0x00, 0x05, 0x24, 0x02, 0x00, 0x06, 0x24, 0x18, 0x00, 0xA7, 0x27,
-0x18, 0x00, 0xA0, 0xA7, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB0, 0xAF,
-0x18, 0x00, 0xA5, 0x97, 0x02, 0x80, 0x04, 0x3C, 0x58, 0xE8, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0x21, 0x90, 0x40, 0x00, 0xC0, 0x3A, 0xA2, 0x8E,
-0x0C, 0x00, 0x11, 0x24, 0x2B, 0x10, 0x22, 0x02, 0x3B, 0x00, 0x40, 0x10,
-0x21, 0xF0, 0x00, 0x02, 0x02, 0x80, 0x02, 0x3C, 0x21, 0x80, 0x80, 0x02,
-0xAA, 0x46, 0x00, 0x08, 0x26, 0x56, 0x57, 0x24, 0x21, 0x10, 0x30, 0x02,
-0x01, 0x00, 0x43, 0x90, 0xC0, 0x3A, 0xA4, 0x8E, 0x21, 0x18, 0x71, 0x00,
-0x02, 0x00, 0x71, 0x24, 0x2B, 0x20, 0x24, 0x02, 0x2F, 0x00, 0x80, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x30, 0x02, 0x00, 0x00, 0x47, 0x90,
-0x02, 0x80, 0x14, 0x3C, 0x2D, 0x00, 0x03, 0x24, 0x21, 0x28, 0x37, 0x02,
-0x64, 0x5C, 0x84, 0x26, 0xF1, 0xFF, 0xE3, 0x14, 0x20, 0x00, 0x06, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x04, 0x41, 0xA3, 0x96,
-0x02, 0x80, 0x02, 0x3C, 0xC6, 0x5C, 0x47, 0x90, 0xBD, 0xFF, 0x63, 0x30,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x0C, 0x00, 0x63, 0x34,
-0x01, 0x00, 0xE7, 0x30, 0x44, 0xDF, 0xA5, 0x24, 0x67, 0x5C, 0x44, 0x24,
-0x10, 0x00, 0x06, 0x24, 0x06, 0x00, 0xE0, 0x14, 0x04, 0x41, 0xA3, 0xA6,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x54, 0xDF, 0xA5, 0x24,
-0x67, 0x5C, 0x64, 0x24, 0x10, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x30, 0x02, 0x01, 0x00, 0x46, 0x90,
-0x21, 0x20, 0x40, 0x02, 0x64, 0x5C, 0x87, 0x26, 0x2D, 0x00, 0x05, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xBE, 0xAF, 0x21, 0x90, 0x40, 0x00,
-0x21, 0x10, 0x30, 0x02, 0x01, 0x00, 0x43, 0x90, 0xC0, 0x3A, 0xA4, 0x8E,
-0x21, 0x18, 0x71, 0x00, 0x02, 0x00, 0x71, 0x24, 0x2B, 0x20, 0x24, 0x02,
-0xD4, 0xFF, 0x80, 0x14, 0x21, 0x10, 0x30, 0x02, 0x20, 0x00, 0xA2, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x40, 0x10, 0x02, 0x80, 0x03, 0x3C,
-0x1C, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x42, 0x24,
-0x01, 0x01, 0x42, 0x2C, 0x1A, 0x00, 0x40, 0x14, 0x21, 0x20, 0x60, 0x02,
-0x4C, 0x00, 0xBF, 0x8F, 0x48, 0x00, 0xBE, 0x8F, 0x44, 0x00, 0xB7, 0x8F,
-0x40, 0x00, 0xB6, 0x8F, 0x3C, 0x00, 0xB5, 0x8F, 0x38, 0x00, 0xB4, 0x8F,
-0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F,
-0x28, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x50, 0x00, 0xBD, 0x27,
-0xB0, 0x55, 0x63, 0x24, 0x21, 0x20, 0x40, 0x02, 0xF8, 0xFF, 0xC6, 0x26,
-0x68, 0x00, 0x67, 0x24, 0x32, 0x00, 0x05, 0x24, 0x25, 0x52, 0x00, 0x0C,
-0x10, 0x00, 0xBE, 0xAF, 0x1C, 0x00, 0xA2, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x00, 0x42, 0x24, 0x01, 0x01, 0x42, 0x2C, 0xE8, 0xFF, 0x40, 0x10,
-0x21, 0x20, 0x60, 0x02, 0x21, 0x28, 0x00, 0x00, 0xEC, 0x54, 0x00, 0x0C,
-0x08, 0x00, 0x06, 0x24, 0x08, 0x00, 0x64, 0x8E, 0x04, 0x00, 0x65, 0x8E,
-0xFF, 0xDF, 0x02, 0x3C, 0x10, 0x00, 0x66, 0x8E, 0x14, 0x00, 0x67, 0x8E,
-0xFF, 0xFF, 0x42, 0x34, 0x1C, 0x00, 0xA8, 0x8F, 0x24, 0x20, 0x82, 0x00,
-0x00, 0x40, 0x03, 0x3C, 0xFF, 0xE0, 0x02, 0x24, 0x24, 0x28, 0xA2, 0x00,
-0x25, 0x20, 0x83, 0x00, 0x00, 0x80, 0x02, 0x3C, 0xFF, 0x81, 0x03, 0x24,
-0x25, 0x30, 0xC2, 0x00, 0x24, 0x38, 0xE3, 0x00, 0x00, 0x10, 0xA5, 0x34,
-0x02, 0x80, 0x03, 0x3C, 0x80, 0x00, 0x84, 0x34, 0x20, 0x00, 0x02, 0x24,
-0x08, 0x00, 0x64, 0xAE, 0x00, 0x00, 0x68, 0xA6, 0x02, 0x00, 0x62, 0xA2,
-0x14, 0x00, 0x67, 0xAE, 0x04, 0x00, 0x65, 0xAE, 0x10, 0x00, 0x66, 0xAE,
-0x60, 0x1B, 0x62, 0x24, 0xEC, 0x37, 0x46, 0x8C, 0x58, 0x38, 0x45, 0x8C,
-0x01, 0x00, 0x04, 0x24, 0x00, 0x01, 0x07, 0x24, 0x01, 0x00, 0x02, 0x24,
-0x1E, 0x01, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF, 0x5B, 0x01, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0x4C, 0x00, 0xBF, 0x8F, 0x48, 0x00, 0xBE, 0x8F,
-0x44, 0x00, 0xB7, 0x8F, 0x40, 0x00, 0xB6, 0x8F, 0x3C, 0x00, 0xB5, 0x8F,
-0x38, 0x00, 0xB4, 0x8F, 0x34, 0x00, 0xB3, 0x8F, 0x30, 0x00, 0xB2, 0x8F,
-0x2C, 0x00, 0xB1, 0x8F, 0x28, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x50, 0x00, 0xBD, 0x27, 0xA0, 0xFF, 0xBD, 0x27, 0x5C, 0x00, 0xBF, 0xAF,
-0x58, 0x00, 0xBE, 0xAF, 0x54, 0x00, 0xB7, 0xAF, 0x50, 0x00, 0xB6, 0xAF,
-0x4C, 0x00, 0xB5, 0xAF, 0x48, 0x00, 0xB4, 0xAF, 0x44, 0x00, 0xB3, 0xAF,
-0x40, 0x00, 0xB2, 0xAF, 0x3C, 0x00, 0xB1, 0xAF, 0x38, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x0B, 0x3C, 0x64, 0xE8, 0x82, 0x24,
-0x78, 0xE8, 0x63, 0x25, 0x78, 0xE8, 0x6B, 0x91, 0x01, 0x00, 0x45, 0x90,
-0x0D, 0x00, 0x48, 0x90, 0x0C, 0x00, 0x58, 0x90, 0x64, 0xE8, 0x97, 0x90,
-0x02, 0x00, 0x54, 0x90, 0x0E, 0x00, 0x50, 0x90, 0x01, 0x00, 0x69, 0x90,
-0x30, 0x00, 0xAB, 0xAF, 0x03, 0x00, 0x4B, 0x90, 0x04, 0x00, 0x76, 0x90,
-0x05, 0x00, 0x6A, 0x90, 0x02, 0x00, 0x6F, 0x90, 0x06, 0x00, 0x64, 0x90,
-0x07, 0x00, 0x75, 0x90, 0x03, 0x00, 0x71, 0x90, 0x00, 0x2A, 0x05, 0x00,
-0x30, 0x00, 0xA3, 0x8F, 0x00, 0x42, 0x08, 0x00, 0x25, 0x40, 0x18, 0x01,
-0x25, 0x28, 0xB7, 0x00, 0x00, 0xA4, 0x14, 0x00, 0x00, 0x84, 0x10, 0x00,
-0x25, 0xA0, 0x85, 0x02, 0x25, 0x80, 0x08, 0x02, 0x00, 0x4A, 0x09, 0x00,
-0x00, 0x5E, 0x0B, 0x00, 0x02, 0x80, 0x08, 0x3C, 0x05, 0x00, 0x46, 0x90,
-0x09, 0x00, 0x47, 0x90, 0x25, 0x48, 0x23, 0x01, 0x00, 0x52, 0x0A, 0x00,
-0x60, 0x1B, 0x03, 0x25, 0x25, 0x58, 0x74, 0x01, 0x04, 0x00, 0x5E, 0x90,
-0x06, 0x00, 0x53, 0x90, 0x08, 0x00, 0x59, 0x90, 0x0A, 0x00, 0x52, 0x90,
-0x07, 0x00, 0x4C, 0x90, 0x0B, 0x00, 0x4D, 0x90, 0x0F, 0x00, 0x4E, 0x90,
-0x11, 0x00, 0x58, 0x90, 0x25, 0x50, 0x56, 0x01, 0x10, 0x00, 0x56, 0x90,
-0x10, 0x00, 0xAB, 0xAF, 0x06, 0x41, 0x62, 0x90, 0x00, 0x32, 0x06, 0x00,
-0x00, 0x3A, 0x07, 0x00, 0x00, 0x7C, 0x0F, 0x00, 0x00, 0x24, 0x04, 0x00,
-0x25, 0x30, 0xDE, 0x00, 0x25, 0x38, 0xF9, 0x00, 0x25, 0x20, 0x8A, 0x00,
-0x1C, 0x00, 0x43, 0x30, 0x00, 0x9C, 0x13, 0x00, 0x00, 0x94, 0x12, 0x00,
-0x25, 0x78, 0xE9, 0x01, 0x00, 0x8E, 0x11, 0x00, 0x00, 0xAE, 0x15, 0x00,
-0x25, 0x98, 0x66, 0x02, 0x25, 0x90, 0x47, 0x02, 0x03, 0x00, 0x46, 0x30,
-0x25, 0xA8, 0xA4, 0x02, 0x25, 0x88, 0x2F, 0x02, 0x10, 0x00, 0xA7, 0x27,
-0x83, 0x18, 0x03, 0x00, 0x02, 0x00, 0xC4, 0x24, 0x28, 0x00, 0xB1, 0xAF,
-0x2C, 0x00, 0xB5, 0xAF, 0x21, 0x18, 0xE3, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x04, 0x10, 0x82, 0x00, 0x18, 0x00, 0x65, 0x90, 0xFF, 0x00, 0x46, 0x30,
-0x00, 0x66, 0x0C, 0x00, 0x00, 0x6E, 0x0D, 0x00, 0x00, 0x76, 0x0E, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0x25, 0x60, 0x93, 0x01, 0x25, 0x68, 0xB2, 0x01,
-0x25, 0x70, 0xD0, 0x01, 0x10, 0x00, 0xC4, 0x2C, 0x37, 0x02, 0x42, 0x34,
-0x0F, 0x00, 0x03, 0x24, 0x14, 0x00, 0xAC, 0xAF, 0x18, 0x00, 0xAD, 0xAF,
-0x1C, 0x00, 0xAE, 0xAF, 0x20, 0x00, 0xB6, 0xA3, 0x21, 0x00, 0xB8, 0xA3,
-0x0A, 0x30, 0x64, 0x00, 0x00, 0x00, 0x45, 0xA0, 0x21, 0x28, 0x00, 0x00,
-0x21, 0x20, 0xE5, 0x00, 0x00, 0x00, 0x82, 0x90, 0x01, 0x00, 0xA5, 0x24,
-0x2B, 0x10, 0xC2, 0x00, 0x02, 0x00, 0x40, 0x10, 0x11, 0x00, 0xA3, 0x2C,
-0x00, 0x00, 0x86, 0xA0, 0xF9, 0xFF, 0x60, 0x14, 0x21, 0x20, 0xE5, 0x00,
-0x21, 0x30, 0xE0, 0x00, 0x21, 0x28, 0x00, 0x00, 0x25, 0xB0, 0x07, 0x3C,
-0x01, 0x00, 0xC2, 0x90, 0x00, 0x00, 0xC3, 0x90, 0x21, 0x20, 0xA7, 0x00,
-0x00, 0x11, 0x02, 0x00, 0x25, 0x10, 0x43, 0x00, 0x01, 0x00, 0xA5, 0x24,
-0xFF, 0x00, 0x42, 0x30, 0x08, 0x00, 0xA3, 0x2C, 0xA8, 0x01, 0x82, 0xA0,
-0xF6, 0xFF, 0x60, 0x14, 0x02, 0x00, 0xC6, 0x24, 0x21, 0x00, 0xA2, 0x93,
-0x20, 0x00, 0xA4, 0x93, 0x02, 0x80, 0x03, 0x3C, 0x00, 0x11, 0x02, 0x00,
-0xD9, 0x5C, 0x66, 0x90, 0x25, 0x10, 0x44, 0x00, 0xFF, 0x00, 0x42, 0x30,
-0xA7, 0x01, 0xE3, 0x34, 0x00, 0x00, 0x62, 0xA0, 0x01, 0x00, 0x02, 0x24,
-0x0F, 0x00, 0xC2, 0x10, 0x60, 0x1B, 0x07, 0x25, 0x60, 0x1B, 0x02, 0x25,
-0x00, 0x41, 0x40, 0xAC, 0x5C, 0x00, 0xBF, 0x8F, 0x58, 0x00, 0xBE, 0x8F,
-0x54, 0x00, 0xB7, 0x8F, 0x50, 0x00, 0xB6, 0x8F, 0x4C, 0x00, 0xB5, 0x8F,
-0x48, 0x00, 0xB4, 0x8F, 0x44, 0x00, 0xB3, 0x8F, 0x40, 0x00, 0xB2, 0x8F,
-0x3C, 0x00, 0xB1, 0x8F, 0x38, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x60, 0x00, 0xBD, 0x27, 0x04, 0x41, 0xE2, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x42, 0x30, 0xEF, 0xFF, 0x40, 0x10, 0x60, 0x1B, 0x02, 0x25,
-0x25, 0x41, 0xE3, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x62, 0x30,
-0xEA, 0xFF, 0x40, 0x10, 0x60, 0x1B, 0x02, 0x25, 0x03, 0x00, 0x63, 0x30,
-0x10, 0x00, 0x66, 0x10, 0x03, 0x00, 0x02, 0x24, 0x07, 0x00, 0x62, 0x10,
-0x60, 0x1B, 0x02, 0x25, 0x00, 0x41, 0x40, 0xAC, 0x21, 0x20, 0x00, 0x00,
-0x95, 0x0E, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0xBE, 0x47, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x34, 0x02, 0x00, 0x05, 0x24,
-0x00, 0x41, 0xE6, 0xAC, 0x95, 0x0E, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xBE, 0x47, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x34,
-0x01, 0x00, 0x05, 0x24, 0xE2, 0x47, 0x00, 0x08, 0x00, 0x41, 0xE6, 0xAC,
-0xE8, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x06, 0x3C, 0x14, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0xB4, 0x55, 0xC2, 0x24, 0x01, 0x00, 0x44, 0x90,
-0xB4, 0x55, 0xC3, 0x90, 0x02, 0x00, 0x45, 0x90, 0x03, 0x00, 0x46, 0x90,
-0x05, 0x00, 0x47, 0x90, 0x04, 0x00, 0x48, 0x90, 0x00, 0x22, 0x04, 0x00,
-0x25, 0x18, 0x64, 0x00, 0x00, 0x2C, 0x05, 0x00, 0x25, 0xB0, 0x10, 0x3C,
-0x25, 0x18, 0x65, 0x00, 0x00, 0x36, 0x06, 0x00, 0x00, 0x3A, 0x07, 0x00,
-0x25, 0x18, 0x66, 0x00, 0x58, 0x00, 0x02, 0x36, 0x5C, 0x00, 0x05, 0x36,
-0x25, 0x40, 0x07, 0x01, 0x02, 0x80, 0x04, 0x3C, 0x00, 0x00, 0x43, 0xAC,
-0xB0, 0x55, 0x84, 0x24, 0x00, 0x00, 0xA8, 0xAC, 0xFD, 0x51, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x03, 0x36, 0x00, 0x00, 0x62, 0xA4,
-0x48, 0x00, 0x10, 0x36, 0x00, 0x00, 0x02, 0x8E, 0x84, 0x00, 0x03, 0x3C,
-0x14, 0x00, 0xBF, 0x8F, 0x25, 0x10, 0x43, 0x00, 0x00, 0x00, 0x02, 0xAE,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0x24, 0x00, 0x04, 0x24, 0x21, 0x30, 0x40, 0x00,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x50, 0x24,
-0x21, 0x20, 0xC0, 0x00, 0x13, 0x00, 0xC0, 0x10, 0x80, 0xE8, 0xA5, 0x24,
-0x04, 0x00, 0x02, 0x24, 0x09, 0x00, 0x03, 0x24, 0x0C, 0x00, 0xC2, 0xAC,
-0x14, 0x00, 0xC3, 0xAC, 0x08, 0x00, 0xC5, 0x94, 0x3C, 0x3E, 0x03, 0x8E,
-0x02, 0x80, 0x02, 0x3C, 0x25, 0x28, 0xA2, 0x00, 0x17, 0x0A, 0x00, 0x0C,
-0x20, 0x00, 0xA3, 0xAC, 0x40, 0x3E, 0x06, 0x8E, 0x3C, 0x3E, 0x05, 0x8E,
-0x02, 0x80, 0x04, 0x3C, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x94, 0xE8, 0x84, 0x24, 0x13, 0x58, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0x02, 0x80, 0x04, 0x3C, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0xAC, 0xE8, 0x84, 0x24, 0x13, 0x58, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB3, 0xAF, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x20, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x02, 0x3C, 0xB0, 0x55, 0x43, 0x8C, 0x21, 0x90, 0x80, 0x00,
-0x3C, 0x00, 0x64, 0x24, 0x53, 0x21, 0x00, 0x0C, 0x1C, 0x00, 0x73, 0x24,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x04, 0x3C, 0x21, 0x88, 0x40, 0x00,
-0xB0, 0x55, 0xA5, 0x24, 0x74, 0x03, 0x06, 0x24, 0x19, 0x00, 0x40, 0x10,
-0xC8, 0xE8, 0x84, 0x24, 0x08, 0x00, 0x50, 0x94, 0x0A, 0x00, 0x02, 0x24,
-0x14, 0x00, 0x22, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0x25, 0x80, 0x02, 0x02,
-0x0C, 0x00, 0x33, 0xAE, 0x3C, 0x00, 0x04, 0x26, 0xF4, 0x54, 0x00, 0x0C,
-0x20, 0x00, 0x10, 0x26, 0x18, 0x00, 0x12, 0xAE, 0x21, 0x20, 0x20, 0x02,
-0x17, 0x0A, 0x00, 0x0C, 0x14, 0x00, 0x12, 0xAE, 0x02, 0x80, 0x04, 0x3C,
-0x21, 0x28, 0x40, 0x02, 0x21, 0x30, 0x60, 0x02, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0xD8, 0xE8, 0x84, 0x24, 0x13, 0x58, 0x00, 0x08,
-0x28, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x06, 0x3C, 0x21, 0x28, 0x60, 0x02,
-0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xB8, 0xE8, 0xC6, 0x24,
-0x13, 0x58, 0x00, 0x08, 0x28, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB2, 0xAF, 0xFF, 0xFF, 0x92, 0x30, 0x2A, 0x00, 0x04, 0x24,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x1C, 0x00, 0xBF, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0xFF, 0x00, 0xB1, 0x30, 0x02, 0x80, 0x05, 0x3C,
-0x21, 0x80, 0x40, 0x00, 0xB4, 0x55, 0xA5, 0x24, 0x13, 0x00, 0x40, 0x10,
-0x06, 0x00, 0x06, 0x24, 0x08, 0x00, 0x44, 0x94, 0x0A, 0x00, 0x02, 0x24,
-0x0C, 0x00, 0x02, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0x25, 0x20, 0x82, 0x00,
-0x20, 0x00, 0x84, 0x24, 0x19, 0x00, 0x03, 0x24, 0x14, 0x00, 0x03, 0xAE,
-0x06, 0x00, 0x92, 0xA4, 0xF4, 0x54, 0x00, 0x0C, 0x08, 0x00, 0x91, 0xA0,
-0x21, 0x20, 0x00, 0x02, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x17, 0x0A, 0x00, 0x08,
-0x20, 0x00, 0xBD, 0x27, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x24, 0x00, 0xBF, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF, 0x02, 0x00, 0x82, 0x90,
-0x02, 0x80, 0x12, 0x3C, 0x60, 0x1B, 0x51, 0x26, 0xB0, 0x1B, 0x25, 0x96,
-0x0F, 0x00, 0x42, 0x30, 0xC0, 0x10, 0x02, 0x00, 0x21, 0x80, 0x44, 0x00,
-0x00, 0x01, 0xA3, 0x30, 0x04, 0x00, 0x60, 0x10, 0x18, 0x00, 0x04, 0x26,
-0x00, 0x10, 0xA2, 0x30, 0x0B, 0x00, 0x40, 0x10, 0x04, 0x00, 0xA2, 0x30,
-0x21, 0x18, 0x00, 0x00, 0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB4, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xF5, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x39, 0x53, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x48, 0x37, 0x84, 0x24, 0x21, 0x28, 0x40, 0x00, 0x1D, 0x55, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0xED, 0xFF, 0x40, 0x14, 0x21, 0x18, 0x00, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xB4, 0x55, 0x53, 0x24, 0x22, 0x00, 0x14, 0x26,
-0x21, 0x20, 0x80, 0x02, 0x21, 0x28, 0x60, 0x02, 0x1D, 0x55, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0xE4, 0xFF, 0x40, 0x14, 0x21, 0x18, 0x00, 0x00,
-0x28, 0x00, 0x04, 0x26, 0x21, 0x28, 0x60, 0x02, 0x1D, 0x55, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0xDE, 0xFF, 0x40, 0x14, 0x21, 0x18, 0x00, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C, 0x38, 0xE9, 0x84, 0x24,
-0xB0, 0x1B, 0x24, 0x96, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x83, 0x30,
-0x01, 0x00, 0x62, 0x30, 0x08, 0x00, 0x40, 0x10, 0x00, 0x20, 0x62, 0x30,
-0x1B, 0x00, 0x40, 0x10, 0xFF, 0xDE, 0x82, 0x30, 0xB0, 0x1B, 0x22, 0xA6,
-0xFE, 0xFF, 0x04, 0x24, 0xCC, 0x39, 0x20, 0xAE, 0x35, 0x48, 0x00, 0x0C,
-0xB0, 0x39, 0x20, 0xAE, 0x25, 0xB0, 0x10, 0x3C, 0x60, 0x1B, 0x51, 0x26,
-0x4C, 0x00, 0x02, 0x36, 0x00, 0x00, 0x40, 0xA0, 0x48, 0x00, 0x10, 0x36,
-0x21, 0x20, 0x00, 0x00, 0x21, 0x28, 0x00, 0x00, 0x95, 0x0E, 0x00, 0x0C,
-0x37, 0x3E, 0x20, 0xA2, 0x00, 0x00, 0x03, 0x8E, 0x7B, 0xFF, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00, 0x00, 0x00, 0x03, 0xAE,
-0xBC, 0x40, 0x20, 0xAE, 0xE8, 0x39, 0x20, 0xAE, 0x04, 0x3A, 0x20, 0xAE,
-0x87, 0x54, 0x00, 0x0C, 0xFC, 0x40, 0x20, 0xAE, 0xA5, 0x48, 0x00, 0x08,
-0x21, 0x18, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x0C, 0x21, 0x20, 0x80, 0x02,
-0xB5, 0xFF, 0x40, 0x14, 0xFF, 0xFF, 0x03, 0x24, 0xB0, 0x1B, 0x22, 0x96,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x42, 0x30, 0xD8, 0x48, 0x00, 0x08,
-0xB0, 0x1B, 0x22, 0xA6, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x10, 0x3C, 0x60, 0x1B, 0x10, 0x26, 0x02, 0x00, 0x02, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0x00, 0x80, 0x06, 0x3C, 0x44, 0x3A, 0x02, 0xA2,
-0x90, 0x55, 0x84, 0x24, 0x21, 0x28, 0x00, 0x00, 0x3C, 0x3A, 0x00, 0xAE,
-0x14, 0x00, 0xBF, 0xAF, 0xCF, 0x20, 0x00, 0x0C, 0x70, 0x3C, 0xC6, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0xD1, 0x5C, 0x44, 0x90, 0x02, 0x80, 0x03, 0x3C,
-0x49, 0xF5, 0x65, 0x90, 0x10, 0x27, 0x02, 0x24, 0x0B, 0x10, 0x04, 0x00,
-0x01, 0x00, 0x84, 0x2C, 0x3C, 0x3A, 0x02, 0xAE, 0x49, 0x41, 0x05, 0xA2,
-0x48, 0x41, 0x04, 0xA2, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xB8, 0xFF, 0xBD, 0x27,
-0x00, 0x01, 0x04, 0x24, 0x3C, 0x00, 0xB3, 0xAF, 0x38, 0x00, 0xB2, 0xAF,
-0x34, 0x00, 0xB1, 0xAF, 0x40, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xB0, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0x02, 0x80, 0x13, 0x3C, 0x02, 0x80, 0x04, 0x3C,
-0x21, 0x88, 0x40, 0x00, 0x90, 0xDE, 0x65, 0x26, 0x06, 0x00, 0x06, 0x24,
-0x0C, 0x00, 0x52, 0x24, 0x4D, 0x00, 0x40, 0x10, 0x58, 0xE9, 0x84, 0x24,
-0x08, 0x00, 0x50, 0x94, 0x02, 0x80, 0x02, 0x3C, 0x25, 0x80, 0x02, 0x02,
-0x24, 0x00, 0x04, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x20, 0x00, 0x00, 0xA6,
-0x02, 0x80, 0x05, 0x3C, 0x2A, 0x00, 0x04, 0x26, 0x48, 0x37, 0xA5, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x30, 0x00, 0x04, 0x26,
-0x90, 0xDE, 0x65, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x20, 0x00, 0x03, 0x96, 0x18, 0x00, 0x02, 0x24, 0x02, 0x80, 0x04, 0x3C,
-0x03, 0xFF, 0x63, 0x30, 0x40, 0x00, 0x63, 0x34, 0x20, 0x00, 0x03, 0xA6,
-0x60, 0x1B, 0x84, 0x24, 0x0C, 0x00, 0x22, 0xAE, 0xE4, 0x1D, 0x82, 0x94,
-0x20, 0x00, 0x06, 0x26, 0x02, 0x80, 0x07, 0x3C, 0xFF, 0x0F, 0x43, 0x30,
-0x00, 0x19, 0x03, 0x00, 0x02, 0x2A, 0x03, 0x00, 0x01, 0x00, 0x42, 0x24,
-0xE4, 0x1D, 0x82, 0xA4, 0x16, 0x00, 0xC3, 0xA0, 0x17, 0x00, 0xC5, 0xA0,
-0x0C, 0x3E, 0x86, 0x8C, 0x70, 0x59, 0xE7, 0x24, 0x38, 0x00, 0x04, 0x26,
-0x21, 0x28, 0x00, 0x00, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB2, 0xAF,
-0x18, 0x00, 0xA4, 0x27, 0x28, 0x00, 0xA5, 0x27, 0x05, 0x53, 0x00, 0x0C,
-0x21, 0x80, 0x40, 0x00, 0x28, 0x00, 0xA3, 0x8F, 0x21, 0x20, 0x00, 0x02,
-0x18, 0x00, 0xA7, 0x27, 0x09, 0x00, 0x62, 0x28, 0x01, 0x00, 0x05, 0x24,
-0x13, 0x00, 0x40, 0x10, 0x08, 0x00, 0x06, 0x24, 0x21, 0x20, 0x00, 0x02,
-0x21, 0x30, 0x60, 0x00, 0x01, 0x00, 0x05, 0x24, 0x18, 0x00, 0xA7, 0x27,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB2, 0xAF, 0x21, 0x20, 0x20, 0x02,
-0x01, 0x00, 0x05, 0x24, 0x21, 0x30, 0x00, 0x00, 0xDF, 0x0D, 0x00, 0x0C,
-0x21, 0x38, 0x00, 0x00, 0x40, 0x00, 0xBF, 0x8F, 0x3C, 0x00, 0xB3, 0x8F,
-0x38, 0x00, 0xB2, 0x8F, 0x34, 0x00, 0xB1, 0x8F, 0x30, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27, 0x25, 0x52, 0x00, 0x0C,
-0x10, 0x00, 0xB2, 0xAF, 0x28, 0x00, 0xA6, 0x8F, 0x21, 0x20, 0x40, 0x00,
-0x32, 0x00, 0x05, 0x24, 0xF8, 0xFF, 0xC6, 0x24, 0x58, 0x49, 0x00, 0x08,
-0x20, 0x00, 0xA7, 0x27, 0x02, 0x80, 0x05, 0x3C, 0x13, 0x58, 0x00, 0x0C,
-0x48, 0xE9, 0xA5, 0x24, 0x40, 0x00, 0xBF, 0x8F, 0x3C, 0x00, 0xB3, 0x8F,
-0x38, 0x00, 0xB2, 0x8F, 0x34, 0x00, 0xB1, 0x8F, 0x30, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0xA8, 0xFF, 0xBD, 0x27, 0x48, 0x00, 0xB6, 0xAF,
-0x3C, 0x00, 0xB3, 0xAF, 0x38, 0x00, 0xB2, 0xAF, 0x30, 0x00, 0xB0, 0xAF,
-0x54, 0x00, 0xBF, 0xAF, 0x50, 0x00, 0xBE, 0xAF, 0x4C, 0x00, 0xB7, 0xAF,
-0x44, 0x00, 0xB5, 0xAF, 0x40, 0x00, 0xB4, 0xAF, 0x34, 0x00, 0xB1, 0xAF,
-0x02, 0x00, 0x82, 0x90, 0x00, 0x00, 0x83, 0x8C, 0x21, 0xB0, 0x00, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0xC0, 0x10, 0x02, 0x00, 0x21, 0x80, 0x44, 0x00,
-0x18, 0x00, 0x12, 0x26, 0x21, 0x20, 0x40, 0x02, 0x39, 0x53, 0x00, 0x0C,
-0xFF, 0x3F, 0x73, 0x30, 0x02, 0x80, 0x04, 0x3C, 0x48, 0x37, 0x84, 0x24,
-0x21, 0x28, 0x40, 0x00, 0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x0B, 0x00, 0x40, 0x14, 0x02, 0x80, 0x15, 0x3C, 0x60, 0x1B, 0xB1, 0x26,
-0xB0, 0x1B, 0x23, 0x96, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x62, 0x30,
-0x05, 0x00, 0x40, 0x10, 0x00, 0x10, 0x62, 0x30, 0x03, 0x00, 0x40, 0x14,
-0x00, 0x01, 0x62, 0x30, 0x0E, 0x00, 0x40, 0x10, 0x20, 0x00, 0xB4, 0x27,
-0x54, 0x00, 0xBF, 0x8F, 0x50, 0x00, 0xBE, 0x8F, 0x4C, 0x00, 0xB7, 0x8F,
-0x48, 0x00, 0xB6, 0x8F, 0x44, 0x00, 0xB5, 0x8F, 0x40, 0x00, 0xB4, 0x8F,
-0x3C, 0x00, 0xB3, 0x8F, 0x38, 0x00, 0xB2, 0x8F, 0x34, 0x00, 0xB1, 0x8F,
-0x30, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x58, 0x00, 0xBD, 0x27, 0x32, 0x00, 0x05, 0x26, 0x21, 0x20, 0x80, 0x02,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x24, 0x20, 0x00, 0xA5, 0x97,
-0x00, 0x00, 0x00, 0x00, 0xB8, 0x00, 0xA0, 0x14, 0x02, 0x80, 0x04, 0x3C,
-0x21, 0x20, 0x80, 0x02, 0x34, 0x00, 0x05, 0x26, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x06, 0x24, 0x20, 0x00, 0xA2, 0x97, 0x21, 0x20, 0x80, 0x02,
-0x30, 0x00, 0x05, 0x26, 0xFF, 0x3F, 0x42, 0x30, 0x02, 0x00, 0x06, 0x24,
-0x4C, 0x3A, 0x22, 0xA6, 0xF4, 0x54, 0x00, 0x0C, 0x28, 0x00, 0xA2, 0xAF,
-0x20, 0x00, 0xA3, 0x97, 0x21, 0x40, 0x20, 0x02, 0x00, 0x04, 0x63, 0x30,
-0x02, 0x00, 0x60, 0x14, 0x09, 0x00, 0x02, 0x24, 0x14, 0x00, 0x02, 0x24,
-0x1E, 0x00, 0x5E, 0x26, 0xE2, 0xFF, 0x77, 0x26, 0x21, 0x20, 0xC0, 0x03,
-0x01, 0x00, 0x05, 0x24, 0x24, 0x00, 0xA6, 0x27, 0x21, 0x38, 0xE0, 0x02,
-0xAB, 0x1A, 0x00, 0x0C, 0xB8, 0x40, 0x02, 0xA1, 0x9E, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xA6, 0x8F, 0x02, 0x00, 0x45, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x21, 0x20, 0xC0, 0x03,
-0x32, 0x00, 0x05, 0x24, 0x24, 0x00, 0xA6, 0x27, 0x24, 0x00, 0xB4, 0x8F,
-0xAB, 0x1A, 0x00, 0x0C, 0x21, 0x38, 0xE0, 0x02, 0x08, 0x00, 0x40, 0x10,
-0x10, 0x00, 0xA4, 0x27, 0x24, 0x00, 0xA6, 0x8F, 0x21, 0x20, 0x94, 0x00,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x45, 0x24, 0x24, 0x00, 0xA3, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x21, 0xA0, 0x83, 0x02, 0x02, 0x80, 0x02, 0x3C,
-0xD2, 0x5C, 0x44, 0x90, 0x02, 0x00, 0x03, 0x24, 0xDA, 0x00, 0x83, 0x10,
-0x21, 0x20, 0xC0, 0x03, 0x60, 0x1B, 0xA4, 0x26, 0xBC, 0x40, 0x82, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x40, 0x10, 0x60, 0x1B, 0xB1, 0x26,
-0x02, 0x80, 0x02, 0x3C, 0xCE, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x1D, 0x00, 0x60, 0x14, 0x23, 0x10, 0xD2, 0x03, 0x2B, 0x10, 0x53, 0x00,
-0x1A, 0x00, 0x40, 0x10, 0x21, 0x80, 0xC0, 0x03, 0x02, 0x80, 0x11, 0x3C,
-0x21, 0x20, 0x00, 0x02, 0xDD, 0x00, 0x05, 0x24, 0x24, 0x00, 0xA6, 0x27,
-0xAB, 0x1A, 0x00, 0x0C, 0x21, 0x38, 0xE0, 0x02, 0x21, 0x80, 0x40, 0x00,
-0x02, 0x00, 0x44, 0x24, 0x68, 0xDE, 0x25, 0x26, 0x03, 0x01, 0x40, 0x10,
-0x06, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x05, 0x01, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xA2, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x02, 0x02, 0x02, 0x00, 0x70, 0x24,
-0x23, 0x20, 0x12, 0x02, 0xF8, 0x00, 0x40, 0x10, 0x2B, 0x20, 0x93, 0x00,
-0xEB, 0xFF, 0x80, 0x14, 0x21, 0x20, 0x00, 0x02, 0x60, 0x1B, 0xB1, 0x26,
-0xFC, 0x40, 0x22, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x40, 0x14,
-0x24, 0x00, 0xA6, 0x27, 0xA9, 0x1B, 0x00, 0x0C, 0x60, 0x1B, 0xB2, 0x26,
-0xB0, 0x1B, 0x45, 0x96, 0x25, 0xB0, 0x17, 0x3C, 0x02, 0x00, 0x03, 0x24,
-0x4C, 0x00, 0xE4, 0x36, 0x00, 0x00, 0x83, 0xA0, 0x00, 0x01, 0xA5, 0x34,
-0xE8, 0x39, 0x42, 0xAE, 0x60, 0xEA, 0x02, 0x34, 0x04, 0x3A, 0x42, 0xAE,
-0xEA, 0x47, 0x00, 0x0C, 0xB0, 0x1B, 0x45, 0xA6, 0x10, 0x00, 0xA4, 0x27,
-0x61, 0x53, 0x00, 0x0C, 0x21, 0x28, 0x80, 0x02, 0x0F, 0x00, 0x50, 0x30,
-0x10, 0x00, 0xA4, 0x27, 0x7A, 0x53, 0x00, 0x0C, 0x21, 0x28, 0x80, 0x02,
-0x40, 0x02, 0x13, 0x36, 0x21, 0x20, 0x60, 0x02, 0x63, 0x5E, 0x00, 0x74,
-0x21, 0x28, 0x40, 0x00, 0x21, 0x28, 0x80, 0x02, 0xA6, 0x53, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x21, 0x88, 0x40, 0x00, 0xFC, 0x40, 0x42, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x40, 0x10, 0x50, 0x00, 0x13, 0x36,
-0x07, 0x41, 0x42, 0x92, 0x08, 0x41, 0x43, 0x92, 0xB6, 0x40, 0x44, 0x92,
-0x00, 0x13, 0x02, 0x00, 0x00, 0x1D, 0x03, 0x00, 0x25, 0x10, 0x43, 0x00,
-0x04, 0x00, 0x03, 0x24, 0x9C, 0x00, 0x83, 0x10, 0x25, 0x88, 0x22, 0x02,
-0x00, 0x41, 0x43, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x60, 0x14,
-0x01, 0x00, 0x02, 0x24, 0x04, 0x41, 0x42, 0x96, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x00, 0x42, 0x30, 0x9D, 0x00, 0x40, 0x14, 0x00, 0x10, 0x02, 0x3C,
-0x01, 0x00, 0x02, 0x24, 0x94, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x94, 0xE9, 0x84, 0x24, 0x21, 0x28, 0x60, 0x02,
-0x21, 0x38, 0xC0, 0x02, 0x13, 0x58, 0x00, 0x0C, 0x21, 0x30, 0x20, 0x02,
-0x21, 0x20, 0x60, 0x02, 0x63, 0x5E, 0x00, 0x74, 0x21, 0x28, 0x20, 0x02,
-0x60, 0x1B, 0xA2, 0x26, 0xB6, 0x40, 0x43, 0x90, 0xB0, 0x1B, 0x44, 0x94,
-0x60, 0x1B, 0xA5, 0x8E, 0xFC, 0xFF, 0x63, 0x24, 0xFF, 0x00, 0x63, 0x30,
-0xFF, 0xDF, 0x84, 0x30, 0x03, 0x00, 0x63, 0x2C, 0xB0, 0x1B, 0x44, 0xA4,
-0xB0, 0x39, 0x40, 0xAC, 0xCC, 0x39, 0x40, 0xAC, 0x40, 0x41, 0x40, 0xAC,
-0x44, 0x41, 0x40, 0xAC, 0x08, 0x00, 0x60, 0x10, 0x25, 0x00, 0xA5, 0x34,
-0x28, 0x00, 0xA4, 0x8F, 0xFB, 0xFF, 0x02, 0x24, 0x24, 0x10, 0xA2, 0x00,
-0x35, 0x48, 0x00, 0x0C, 0x60, 0x1B, 0xA2, 0xAE, 0xA0, 0x49, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0xA4, 0x8F, 0x35, 0x48, 0x00, 0x0C,
-0x60, 0x1B, 0xA5, 0xAE, 0xA0, 0x49, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x13, 0x58, 0x00, 0x0C, 0x78, 0xE9, 0x84, 0x24, 0xFF, 0xFF, 0x02, 0x24,
-0x51, 0x4A, 0x00, 0x08, 0x28, 0x00, 0xA2, 0xAF, 0x21, 0x20, 0xC0, 0x03,
-0x2D, 0x00, 0x05, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x21, 0x38, 0xE0, 0x02,
-0x91, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xAB, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x60, 0x19, 0x21, 0x40, 0x00, 0x00,
-0x02, 0x00, 0x49, 0x24, 0x21, 0x50, 0x20, 0x02, 0x02, 0x00, 0x0C, 0x24,
-0x89, 0x4A, 0x00, 0x08, 0x21, 0x68, 0x20, 0x01, 0x04, 0x41, 0x82, 0x90,
-0x00, 0x00, 0x23, 0x91, 0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x43, 0x00,
-0x04, 0x41, 0x82, 0xA0, 0x01, 0x00, 0x08, 0x25, 0x2A, 0x10, 0x0B, 0x01,
-0x11, 0x00, 0x40, 0x10, 0x01, 0x00, 0x29, 0x25, 0xF6, 0xFF, 0x0C, 0x15,
-0x21, 0x20, 0x0A, 0x01, 0x06, 0x41, 0x43, 0x91, 0x00, 0x00, 0x25, 0x91,
-0x02, 0x00, 0xA2, 0x91, 0x1C, 0x00, 0x64, 0x30, 0x1C, 0x00, 0xA5, 0x30,
-0x03, 0x00, 0x42, 0x30, 0x03, 0x00, 0x63, 0x30, 0x2A, 0x30, 0x43, 0x00,
-0x2A, 0x38, 0xA4, 0x00, 0x0A, 0x10, 0x66, 0x00, 0x0A, 0x20, 0xA7, 0x00,
-0x25, 0x10, 0x44, 0x00, 0x85, 0x4A, 0x00, 0x08, 0x06, 0x41, 0x42, 0xA1,
-0x02, 0x80, 0x02, 0x3C, 0xC6, 0x5C, 0x43, 0x90, 0x02, 0x80, 0x02, 0x3C,
-0x44, 0xDF, 0x47, 0x24, 0x10, 0x00, 0x65, 0x30, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x54, 0xDF, 0x66, 0x24, 0x60, 0x1B, 0x44, 0x24,
-0xAC, 0x4A, 0x00, 0x08, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x43, 0x90,
-0x07, 0x41, 0x82, 0x90, 0x01, 0x00, 0x08, 0x25, 0x24, 0x10, 0x43, 0x00,
-0x07, 0x41, 0x82, 0xA0, 0x10, 0x00, 0x02, 0x29, 0x07, 0x00, 0x40, 0x10,
-0x01, 0x00, 0x84, 0x24, 0x21, 0x10, 0x07, 0x01, 0xF6, 0xFF, 0xA0, 0x14,
-0x21, 0x18, 0x06, 0x01, 0x00, 0x00, 0x63, 0x90, 0xA5, 0x4A, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0xC0, 0x03, 0x21, 0x38, 0xE0, 0x02,
-0x3D, 0x00, 0x05, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x24, 0x00, 0xA6, 0x27,
-0x48, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0xA6, 0x8F,
-0x02, 0x80, 0x04, 0x3C, 0x84, 0x5C, 0x84, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x45, 0x24, 0x2E, 0x47, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x13, 0x4A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x05, 0x24,
-0x24, 0x00, 0xA6, 0x27, 0xAB, 0x1A, 0x00, 0x0C, 0x21, 0x38, 0xE0, 0x02,
-0x30, 0x00, 0x40, 0x10, 0x60, 0x1B, 0xA5, 0x26, 0x02, 0x00, 0x42, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x42, 0x30, 0x2B, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0xD3, 0x5C, 0x44, 0x90, 0x01, 0x00, 0x03, 0x24,
-0x3E, 0x00, 0x83, 0x10, 0x60, 0x1B, 0xA2, 0x26, 0xFC, 0x23, 0x43, 0x8C,
-0xFF, 0xEF, 0x04, 0x24, 0x00, 0x08, 0x63, 0x34, 0x24, 0x18, 0x64, 0x00,
-0xE9, 0x49, 0x00, 0x08, 0xFC, 0x23, 0x43, 0xAC, 0xF6, 0x01, 0xE2, 0x36,
-0x00, 0x00, 0x40, 0xA4, 0x49, 0x4A, 0x00, 0x08, 0x02, 0x80, 0x04, 0x3C,
-0x04, 0x41, 0x42, 0x96, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x42, 0x30,
-0x6A, 0xFF, 0x40, 0x10, 0x02, 0x80, 0x04, 0x3C, 0x00, 0x10, 0x02, 0x3C,
-0x25, 0x88, 0x22, 0x02, 0x0F, 0x00, 0x08, 0x24, 0x01, 0x00, 0x03, 0x24,
-0x0C, 0x00, 0x02, 0x25, 0x04, 0x10, 0x43, 0x00, 0x24, 0x10, 0x51, 0x00,
-0x16, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x08, 0x25,
-0xFA, 0xFF, 0x01, 0x05, 0x0C, 0x00, 0x02, 0x25, 0x00, 0x12, 0x16, 0x00,
-0x00, 0x1B, 0x16, 0x00, 0x25, 0x18, 0x62, 0x00, 0x00, 0x21, 0x16, 0x00,
-0x25, 0x18, 0x64, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0x25, 0x18, 0x76, 0x00,
-0xF6, 0x01, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA4, 0x49, 0x4A, 0x00, 0x08,
-0x02, 0x80, 0x04, 0x3C, 0xFC, 0x23, 0xA2, 0x8C, 0xFF, 0xF7, 0x03, 0x24,
-0xFF, 0xEF, 0x04, 0x24, 0x24, 0x10, 0x43, 0x00, 0x24, 0x10, 0x44, 0x00,
-0xE9, 0x49, 0x00, 0x08, 0xFC, 0x23, 0xA2, 0xAC, 0xEC, 0x4A, 0x00, 0x08,
-0xFF, 0x00, 0x16, 0x31, 0x60, 0x1B, 0xA2, 0x26, 0x13, 0x4A, 0x00, 0x08,
-0xFC, 0x40, 0x40, 0xAC, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0x0E, 0x4A, 0x00, 0x08, 0xBC, 0x40, 0x40, 0xAC, 0x13, 0x4A, 0x00, 0x08,
-0xFC, 0x40, 0x20, 0xAE, 0x21, 0x20, 0x00, 0x02, 0x65, 0x0F, 0x00, 0x0C,
-0x21, 0x28, 0x00, 0x00, 0x0F, 0x4A, 0x00, 0x08, 0x60, 0x1B, 0xB1, 0x26,
-0xFC, 0x23, 0x43, 0x8C, 0xFF, 0xF7, 0x04, 0x24, 0x24, 0x18, 0x64, 0x00,
-0x00, 0x10, 0x63, 0x34, 0xE9, 0x49, 0x00, 0x08, 0xFC, 0x23, 0x43, 0xAC,
-0x02, 0x80, 0x04, 0x3C, 0xB0, 0x55, 0x84, 0x24, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xBF, 0xAF, 0xFB, 0x51, 0x00, 0x0C, 0x74, 0x00, 0x84, 0x24,
-0x21, 0x28, 0x40, 0x00, 0x10, 0x00, 0xA4, 0x27, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x06, 0x24, 0x10, 0x00, 0xA2, 0x97, 0x25, 0xB0, 0x04, 0x3C,
-0x94, 0x00, 0x85, 0x34, 0x9A, 0x00, 0x87, 0x34, 0x26, 0xB0, 0x06, 0x3C,
-0x00, 0x08, 0x03, 0x24, 0x00, 0x00, 0xA2, 0xA4, 0x0A, 0x00, 0x0B, 0x24,
-0x00, 0x00, 0xE3, 0xA4, 0x98, 0x00, 0x88, 0x34, 0x96, 0x00, 0x89, 0x34,
-0x7A, 0x00, 0xCA, 0x34, 0x50, 0x00, 0x02, 0x24, 0x04, 0x00, 0x03, 0x24,
-0x00, 0x00, 0x02, 0xA5, 0x00, 0x00, 0x2B, 0xA5, 0x00, 0x00, 0x43, 0xA1,
-0x10, 0x00, 0xA2, 0x97, 0x89, 0x00, 0x83, 0x34, 0x14, 0x00, 0x07, 0x24,
-0x40, 0x11, 0x02, 0x00, 0xA0, 0xFF, 0x42, 0x24, 0xFF, 0xFF, 0x42, 0x30,
-0x9C, 0x00, 0x85, 0x34, 0x7C, 0x00, 0xC6, 0x34, 0x00, 0x00, 0xC2, 0xA4,
-0x44, 0x00, 0x84, 0x34, 0x00, 0x00, 0x67, 0xA0, 0x00, 0x00, 0xAB, 0xA0,
-0x00, 0x00, 0x82, 0x94, 0xFF, 0xFD, 0x03, 0x24, 0x18, 0x00, 0xBF, 0x8F,
-0x24, 0x10, 0x43, 0x00, 0x00, 0x00, 0x82, 0xA4, 0x00, 0x00, 0x83, 0x94,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24, 0x00, 0x02, 0x63, 0x34,
-0x20, 0x00, 0xBD, 0x27, 0x3A, 0x41, 0x40, 0xA0, 0x00, 0x00, 0x83, 0xA4,
-0x08, 0x00, 0xE0, 0x03, 0xB8, 0x40, 0x47, 0xA0, 0xD0, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x10, 0x3C, 0xB0, 0x55, 0x04, 0x26,
-0x28, 0x00, 0xBF, 0xAF, 0x24, 0x00, 0xB5, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF, 0x18, 0x52, 0x00, 0x0C,
-0x18, 0x00, 0xB2, 0xAF, 0xFF, 0xFF, 0x51, 0x30, 0xB0, 0x55, 0x04, 0x26,
-0xFD, 0x51, 0x00, 0x0C, 0x02, 0x80, 0x15, 0x3C, 0x60, 0x1B, 0xA3, 0x26,
-0x01, 0x00, 0x24, 0x32, 0xB4, 0x40, 0x62, 0xA4, 0x03, 0x00, 0x80, 0x14,
-0x02, 0x00, 0x05, 0x24, 0x40, 0x10, 0x11, 0x00, 0x04, 0x00, 0x45, 0x30,
-0x02, 0x00, 0x02, 0x24, 0x5F, 0x00, 0xA2, 0x10, 0x60, 0x1B, 0xA2, 0x26,
-0x10, 0x00, 0x80, 0x10, 0x02, 0x00, 0x03, 0x24, 0x04, 0x00, 0x02, 0x24,
-0x12, 0x00, 0x62, 0x10, 0x60, 0x1B, 0xB3, 0x26, 0x02, 0x80, 0x04, 0x3C,
-0x21, 0x28, 0x20, 0x02, 0x28, 0x00, 0xBF, 0x8F, 0x24, 0x00, 0xB5, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xEC, 0xE9, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x08, 0x30, 0x00, 0xBD, 0x27, 0x40, 0x10, 0x11, 0x00,
-0x04, 0x00, 0x43, 0x30, 0x04, 0x00, 0x02, 0x24, 0xF0, 0xFF, 0x62, 0x14,
-0x60, 0x1B, 0xB3, 0x26, 0xB4, 0x40, 0x66, 0x96, 0xC4, 0x3D, 0x65, 0x92,
-0x02, 0x80, 0x04, 0x3C, 0xB0, 0x1B, 0x63, 0xA6, 0xFC, 0xE9, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0x25, 0xB0, 0x10, 0x3C, 0x50, 0x02, 0x03, 0x36,
-0x0F, 0x00, 0x02, 0x24, 0x00, 0x00, 0x62, 0xA0, 0x21, 0x28, 0x00, 0x00,
-0x95, 0x0E, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00, 0xC4, 0x3D, 0x64, 0x92,
-0x01, 0x00, 0x14, 0x24, 0x75, 0x0D, 0x00, 0x0C, 0x4C, 0x00, 0x10, 0x36,
-0x02, 0x80, 0x11, 0x3C, 0x00, 0x00, 0x14, 0xA2, 0xEA, 0x47, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x1B, 0x53, 0x00, 0x0C, 0x10, 0x56, 0x24, 0x26,
-0x21, 0x28, 0x40, 0x00, 0x10, 0x56, 0x24, 0x26, 0x61, 0x53, 0x00, 0x0C,
-0x21, 0x90, 0x40, 0x00, 0x0F, 0x00, 0x50, 0x30, 0x10, 0x56, 0x24, 0x26,
-0x7A, 0x53, 0x00, 0x0C, 0x21, 0x28, 0x40, 0x02, 0x40, 0x02, 0x10, 0x36,
-0x02, 0x80, 0x04, 0x3C, 0x21, 0x88, 0x40, 0x00, 0x21, 0x30, 0x40, 0x00,
-0x21, 0x28, 0x00, 0x02, 0x13, 0x58, 0x00, 0x0C, 0x2C, 0xEA, 0x84, 0x24,
-0x21, 0x20, 0x00, 0x02, 0x63, 0x5E, 0x00, 0x74, 0x21, 0x28, 0x20, 0x02,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0x37, 0x3A, 0x84, 0x24,
-0xB4, 0x55, 0xA5, 0x24, 0x06, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0xD6, 0x1E, 0x74, 0xA2, 0x31, 0x46, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x4B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x1B, 0x62, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x34, 0xA9, 0x1B, 0x00, 0x0C,
-0xB0, 0x1B, 0x62, 0xA6, 0xE8, 0x39, 0x62, 0xAE, 0x35, 0x48, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0x60, 0x1B, 0xA2, 0x8E, 0x28, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x21, 0x00, 0x42, 0x34, 0x60, 0x1B, 0xA2, 0xAE,
-0x1C, 0x00, 0xB3, 0x8F, 0x24, 0x00, 0xB5, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x30, 0x00, 0xBD, 0x27, 0x24, 0x40, 0x44, 0x8C, 0x01, 0x20, 0x03, 0x24,
-0xB0, 0x1B, 0x43, 0xA4, 0x02, 0x00, 0x85, 0x10, 0x0C, 0x00, 0x03, 0x24,
-0x0F, 0x00, 0x03, 0x24, 0x25, 0xB0, 0x02, 0x3C, 0x50, 0x02, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xA0, 0x60, 0x1B, 0xB0, 0x26, 0xB0, 0x1B, 0x02, 0x96,
-0xB4, 0x40, 0x06, 0x96, 0xC4, 0x3D, 0x05, 0x92, 0x10, 0x00, 0x42, 0x34,
-0x02, 0x80, 0x04, 0x3C, 0xB0, 0x1B, 0x02, 0xA6, 0x40, 0xEA, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0x14, 0x40, 0x00, 0xAE, 0x21, 0x28, 0x00, 0x00,
-0x95, 0x0E, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00, 0xC4, 0x3D, 0x04, 0x92,
-0x75, 0x0D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x1B, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0x39, 0x02, 0xAE, 0x28, 0x00, 0xBF, 0x8F,
-0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27,
-0x20, 0x00, 0xB2, 0xAF, 0x21, 0x90, 0x80, 0x00, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x00, 0xBF, 0xAF, 0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0xFF, 0x00, 0xB0, 0x30, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x51, 0x24, 0x10, 0x00, 0xA4, 0x27, 0x01, 0x00, 0x02, 0x24,
-0x90, 0x40, 0x00, 0x0C, 0x4B, 0x41, 0x22, 0xA2, 0x02, 0x80, 0x04, 0x3C,
-0x30, 0x59, 0x84, 0x24, 0x21, 0x28, 0x00, 0x00, 0xE3, 0x54, 0x00, 0x0C,
-0x0F, 0x00, 0x06, 0x24, 0x21, 0x40, 0x00, 0x00, 0x18, 0x00, 0x00, 0x12,
-0x21, 0x60, 0x00, 0x00, 0x21, 0x68, 0x20, 0x02, 0x21, 0x10, 0x92, 0x01,
-0x01, 0x00, 0x49, 0x90, 0x00, 0x00, 0x4A, 0x90, 0x0D, 0x00, 0x20, 0x11,
-0x21, 0x30, 0x00, 0x00, 0x21, 0x58, 0xA0, 0x01, 0x01, 0x00, 0xC2, 0x24,
-0x21, 0x38, 0x46, 0x01, 0x01, 0x00, 0x03, 0x25, 0xFF, 0x00, 0x46, 0x30,
-0x0E, 0x00, 0x02, 0x2D, 0x21, 0x28, 0x0B, 0x01, 0x2B, 0x20, 0xC9, 0x00,
-0x08, 0x00, 0x40, 0x10, 0xFF, 0x00, 0x68, 0x30, 0xF6, 0xFF, 0x80, 0x14,
-0xD0, 0x3D, 0xA7, 0xA0, 0x03, 0x00, 0x82, 0x25, 0xFF, 0x00, 0x4C, 0x30,
-0x2B, 0x18, 0x90, 0x01, 0xEC, 0xFF, 0x60, 0x14, 0x21, 0x10, 0x92, 0x01,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27,
-0x10, 0x00, 0xBF, 0xAF, 0x90, 0x48, 0x00, 0x0C, 0xFE, 0xFF, 0x05, 0x24,
-0x10, 0x00, 0xBF, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x90, 0x48, 0x00, 0x0C, 0xFF, 0xFF, 0x05, 0x24, 0x10, 0x00, 0xBF, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0x25, 0xB0, 0x03, 0x3C, 0x01, 0x80, 0x02, 0x3C, 0xB0, 0x03, 0x65, 0x34,
-0xAC, 0x30, 0x42, 0x24, 0x18, 0x03, 0x63, 0x34, 0x00, 0x00, 0x62, 0xAC,
-0x00, 0x00, 0xA4, 0xAC, 0x00, 0x00, 0x83, 0x8C, 0x21, 0x10, 0x00, 0x00,
-0xFF, 0x3F, 0x63, 0x30, 0x00, 0x00, 0xA3, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x06, 0x3C,
-0x02, 0x80, 0x08, 0x3C, 0x78, 0x00, 0xBE, 0xAF, 0x7C, 0x00, 0xBF, 0xAF,
-0x74, 0x00, 0xB7, 0xAF, 0x70, 0x00, 0xB6, 0xAF, 0x6C, 0x00, 0xB5, 0xAF,
-0x68, 0x00, 0xB4, 0xAF, 0x64, 0x00, 0xB3, 0xAF, 0x60, 0x00, 0xB2, 0xAF,
-0x5C, 0x00, 0xB1, 0xAF, 0x58, 0x00, 0xB0, 0xAF, 0xE8, 0xE9, 0xC2, 0x24,
-0x74, 0xEA, 0x03, 0x25, 0x01, 0x00, 0x44, 0x90, 0x01, 0x00, 0x65, 0x90,
-0xE8, 0xE9, 0xCB, 0x90, 0x74, 0xEA, 0x0A, 0x91, 0x02, 0x00, 0x47, 0x90,
-0x02, 0x00, 0x66, 0x90, 0x03, 0x00, 0x48, 0x90, 0x03, 0x00, 0x69, 0x90,
-0x00, 0x22, 0x04, 0x00, 0x00, 0x2A, 0x05, 0x00, 0x25, 0x20, 0x8B, 0x00,
-0x25, 0x28, 0xAA, 0x00, 0x00, 0x3C, 0x07, 0x00, 0x00, 0x34, 0x06, 0x00,
-0x25, 0x38, 0xE4, 0x00, 0x25, 0x30, 0xC5, 0x00, 0x00, 0x46, 0x08, 0x00,
-0x00, 0x4E, 0x09, 0x00, 0x25, 0x40, 0x07, 0x01, 0x25, 0x48, 0x26, 0x01,
-0x00, 0x02, 0x04, 0x24, 0x40, 0x00, 0xA8, 0xAF, 0x53, 0x21, 0x00, 0x0C,
-0x48, 0x00, 0xA9, 0xAF, 0xCF, 0x01, 0x40, 0x10, 0x21, 0xF0, 0x40, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x52, 0x24, 0xC0, 0x3A, 0x45, 0x8E,
-0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C, 0x78, 0xEA, 0x84, 0x24,
-0x08, 0x00, 0xD1, 0x97, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x10, 0x3C,
-0x25, 0x88, 0x22, 0x02, 0xB4, 0x55, 0x10, 0x26, 0x24, 0x00, 0x24, 0x26,
-0x21, 0x28, 0x00, 0x02, 0x20, 0x00, 0x20, 0xA6, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C, 0x2A, 0x00, 0x24, 0x26,
-0x48, 0x37, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x21, 0x28, 0x00, 0x02, 0x06, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x30, 0x00, 0x24, 0x26, 0x18, 0x00, 0x03, 0x24, 0x0C, 0x00, 0xC3, 0xAF,
-0xE4, 0x1D, 0x42, 0x96, 0x20, 0x00, 0x25, 0x26, 0x38, 0x00, 0x37, 0x26,
-0xFF, 0x0F, 0x43, 0x30, 0x00, 0x19, 0x03, 0x00, 0x02, 0x22, 0x03, 0x00,
-0x01, 0x00, 0x42, 0x24, 0xE4, 0x1D, 0x42, 0xA6, 0x17, 0x00, 0xA4, 0xA0,
-0x02, 0x80, 0x04, 0x3C, 0x16, 0x00, 0xA3, 0xA0, 0x16, 0x52, 0x00, 0x0C,
-0x24, 0x56, 0x84, 0x24, 0x21, 0x28, 0x40, 0x00, 0x21, 0x20, 0xE0, 0x02,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x24, 0x3A, 0x00, 0x24, 0x26,
-0x18, 0x00, 0xA5, 0x27, 0x02, 0x00, 0x06, 0x24, 0x03, 0x00, 0x02, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0x18, 0x00, 0xA2, 0xA7, 0x0C, 0x00, 0xC3, 0x8F,
-0x02, 0x80, 0x07, 0x3C, 0x3C, 0x00, 0x24, 0x26, 0x04, 0x00, 0x63, 0x24,
-0x0C, 0x00, 0xC3, 0xAF, 0x5C, 0x3A, 0x46, 0x8E, 0x0C, 0x00, 0xC3, 0x27,
-0xC0, 0x55, 0xE7, 0x24, 0x21, 0x28, 0x00, 0x00, 0x54, 0x00, 0xA3, 0xAF,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA3, 0xAF, 0x20, 0x00, 0xA4, 0x27,
-0x50, 0x00, 0xA5, 0x27, 0x05, 0x53, 0x00, 0x0C, 0x21, 0xB8, 0x40, 0x00,
-0x50, 0x00, 0xA8, 0x8F, 0x21, 0x88, 0x00, 0x00, 0x52, 0x00, 0x00, 0x11,
-0x21, 0x80, 0x00, 0x00, 0x21, 0x38, 0x40, 0x02, 0x18, 0x00, 0xA9, 0x27,
-0x21, 0x10, 0x31, 0x01, 0x08, 0x00, 0x46, 0x90, 0x21, 0x20, 0x00, 0x00,
-0x7F, 0x00, 0xC5, 0x30, 0x21, 0x10, 0x87, 0x00, 0xB0, 0x3A, 0x43, 0x90,
-0x01, 0x00, 0x84, 0x24, 0x7F, 0x00, 0x63, 0x30, 0x3D, 0x00, 0xA3, 0x10,
-0x0D, 0x00, 0x82, 0x2C, 0xFA, 0xFF, 0x40, 0x14, 0x21, 0x10, 0x87, 0x00,
-0x01, 0x00, 0x31, 0x26, 0x2B, 0x10, 0x28, 0x02, 0xF2, 0xFF, 0x40, 0x14,
-0x21, 0x10, 0x31, 0x01, 0x09, 0x00, 0x02, 0x2E, 0x3D, 0x00, 0x40, 0x14,
-0x21, 0x20, 0xE0, 0x02, 0x54, 0x00, 0xA2, 0x8F, 0x01, 0x00, 0x05, 0x24,
-0x08, 0x00, 0x06, 0x24, 0x30, 0x00, 0xA7, 0x27, 0x25, 0x52, 0x00, 0x0C,
-0x10, 0x00, 0xA2, 0xAF, 0x54, 0x00, 0xA3, 0x8F, 0x21, 0x20, 0x40, 0x00,
-0xF8, 0xFF, 0x06, 0x26, 0x32, 0x00, 0x05, 0x24, 0x38, 0x00, 0xA7, 0x27,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA3, 0xAF, 0x21, 0xB8, 0x40, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x44, 0x24, 0x24, 0x40, 0x83, 0x8C,
-0x02, 0x00, 0x02, 0x24, 0x37, 0x00, 0x62, 0x14, 0x00, 0x00, 0x00, 0x00,
-0xC0, 0x3A, 0x83, 0x8C, 0x0C, 0x00, 0x11, 0x24, 0x2B, 0x10, 0x23, 0x02,
-0x32, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C, 0x24, 0x56, 0x46, 0x24,
-0x21, 0x20, 0x60, 0x00, 0xE0, 0x4C, 0x00, 0x08, 0x30, 0x00, 0x05, 0x24,
-0x01, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x51, 0x00,
-0x02, 0x00, 0x51, 0x24, 0x2B, 0x18, 0x24, 0x02, 0x27, 0x00, 0x60, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x26, 0x02, 0x00, 0x00, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xF5, 0xFF, 0x45, 0x14, 0x02, 0x80, 0x07, 0x3C,
-0x01, 0x00, 0x66, 0x90, 0x54, 0x00, 0xA2, 0x8F, 0x26, 0x56, 0xE7, 0x24,
-0x21, 0x20, 0xE0, 0x02, 0x21, 0x38, 0x27, 0x02, 0x30, 0x00, 0x05, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF, 0x06, 0x4D, 0x00, 0x08,
-0x21, 0xB8, 0x40, 0x00, 0x21, 0x10, 0x30, 0x01, 0x18, 0x00, 0x46, 0xA0,
-0x50, 0x00, 0xA8, 0x8F, 0x01, 0x00, 0x31, 0x26, 0x2B, 0x10, 0x28, 0x02,
-0xB4, 0xFF, 0x40, 0x14, 0x01, 0x00, 0x10, 0x26, 0xBA, 0x4C, 0x00, 0x08,
-0x09, 0x00, 0x02, 0x2E, 0x54, 0x00, 0xA3, 0x8F, 0x21, 0x20, 0xE0, 0x02,
-0x21, 0x30, 0x00, 0x02, 0x01, 0x00, 0x05, 0x24, 0x30, 0x00, 0xA7, 0x27,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA3, 0xAF, 0x21, 0xB8, 0x40, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x44, 0x24, 0x24, 0x40, 0x83, 0x8C,
-0x02, 0x00, 0x02, 0x24, 0xCB, 0xFF, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x1B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x40, 0x14,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x43, 0x24, 0xC0, 0x3A, 0x62, 0x8C,
-0x0C, 0x00, 0x11, 0x24, 0x2B, 0x10, 0x22, 0x02, 0x11, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x21, 0x80, 0x60, 0x00, 0x24, 0x56, 0x52, 0x24,
-0x21, 0xA8, 0x60, 0x00, 0x02, 0x80, 0x13, 0x3C, 0x21, 0x20, 0x32, 0x02,
-0x00, 0x00, 0x83, 0x90, 0x2D, 0x00, 0x02, 0x24, 0xD6, 0x00, 0x62, 0x10,
-0x02, 0x80, 0x05, 0x3C, 0x01, 0x00, 0x82, 0x90, 0xC0, 0x3A, 0x03, 0x8E,
-0x21, 0x10, 0x51, 0x00, 0x02, 0x00, 0x51, 0x24, 0x2B, 0x18, 0x23, 0x02,
-0xF6, 0xFF, 0x60, 0x14, 0x21, 0x20, 0x32, 0x02, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x44, 0x24, 0x24, 0x40, 0x83, 0x8C, 0x02, 0x00, 0x02, 0x24,
-0x86, 0x00, 0x62, 0x10, 0x0C, 0x00, 0x11, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x43, 0x24, 0xC0, 0x3A, 0x62, 0x8C, 0x0C, 0x00, 0x11, 0x24,
-0x2B, 0x10, 0x22, 0x02, 0x26, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x24, 0x56, 0x56, 0x24, 0x21, 0xA8, 0x60, 0x00, 0xDD, 0x00, 0x14, 0x24,
-0x39, 0x4D, 0x00, 0x08, 0x02, 0x80, 0x13, 0x3C, 0x01, 0x00, 0x02, 0x92,
-0xC0, 0x3A, 0xA3, 0x8E, 0x21, 0x10, 0x51, 0x00, 0x02, 0x00, 0x51, 0x24,
-0x2B, 0x18, 0x23, 0x02, 0x1B, 0x00, 0x60, 0x10, 0x02, 0x80, 0x03, 0x3C,
-0x21, 0x80, 0x36, 0x02, 0x00, 0x00, 0x02, 0x92, 0x02, 0x00, 0x12, 0x26,
-0x21, 0x20, 0x40, 0x02, 0x70, 0xDE, 0x65, 0x26, 0xF3, 0xFF, 0x54, 0x14,
-0x06, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xEF, 0xFF, 0x40, 0x14, 0x21, 0x20, 0xE0, 0x02, 0x54, 0x00, 0xA2, 0x8F,
-0xDD, 0x00, 0x05, 0x24, 0x21, 0x38, 0x40, 0x02, 0x07, 0x00, 0x06, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF, 0x08, 0x00, 0x04, 0x92,
-0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x65, 0x24, 0x21, 0xB8, 0x40, 0x00,
-0x01, 0x00, 0x03, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x08, 0x5E, 0x44, 0xA0,
-0xBC, 0x40, 0xA3, 0xAC, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x64, 0x24,
-0xC0, 0x3A, 0x82, 0x8C, 0x0C, 0x00, 0x11, 0x24, 0x2B, 0x10, 0x22, 0x02,
-0x20, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x24, 0x56, 0x56, 0x24, 0x26, 0x56, 0x75, 0x24, 0x21, 0xA0, 0x80, 0x00,
-0x66, 0x4D, 0x00, 0x08, 0xDD, 0x00, 0x13, 0x24, 0x01, 0x00, 0x02, 0x92,
-0xC0, 0x3A, 0x83, 0x8E, 0x21, 0x10, 0x51, 0x00, 0x02, 0x00, 0x51, 0x24,
-0x2B, 0x18, 0x23, 0x02, 0x14, 0x00, 0x60, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0x80, 0x36, 0x02, 0x00, 0x00, 0x02, 0x92, 0x21, 0x90, 0x35, 0x02,
-0x21, 0x20, 0x40, 0x02, 0x48, 0x00, 0xA5, 0x27, 0xF3, 0xFF, 0x53, 0x14,
-0x04, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xEF, 0xFF, 0x40, 0x14, 0x21, 0x20, 0xE0, 0x02, 0x01, 0x00, 0x06, 0x92,
-0x54, 0x00, 0xA2, 0x8F, 0x21, 0x38, 0x40, 0x02, 0xDD, 0x00, 0x05, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF, 0x21, 0xB8, 0x40, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x44, 0x24, 0xFC, 0x40, 0x83, 0x8C,
-0x01, 0x00, 0x02, 0x24, 0x61, 0x00, 0x62, 0x10, 0x06, 0x00, 0x02, 0x24,
-0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x62, 0x24, 0xC0, 0x3A, 0x43, 0x8C,
-0x0C, 0x00, 0x11, 0x24, 0x2B, 0x10, 0x23, 0x02, 0x10, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x24, 0x56, 0x46, 0x24, 0x21, 0x20, 0x60, 0x00,
-0x44, 0x00, 0x05, 0x24, 0x21, 0x80, 0x26, 0x02, 0x00, 0x00, 0x02, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x45, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0x51, 0x00,
-0x02, 0x00, 0x51, 0x24, 0x2B, 0x18, 0x24, 0x02, 0xF6, 0xFF, 0x60, 0x14,
-0x21, 0x80, 0x26, 0x02, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x62, 0x24,
-0xB6, 0x40, 0x43, 0x90, 0x04, 0x00, 0x07, 0x24, 0x21, 0x20, 0xC0, 0x03,
-0x01, 0x00, 0x63, 0x38, 0x0B, 0x38, 0x03, 0x00, 0x21, 0x28, 0x00, 0x00,
-0xDF, 0x0D, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0x21, 0x10, 0x00, 0x00,
-0x7C, 0x00, 0xBF, 0x8F, 0x78, 0x00, 0xBE, 0x8F, 0x74, 0x00, 0xB7, 0x8F,
-0x70, 0x00, 0xB6, 0x8F, 0x6C, 0x00, 0xB5, 0x8F, 0x68, 0x00, 0xB4, 0x8F,
-0x64, 0x00, 0xB3, 0x8F, 0x60, 0x00, 0xB2, 0x8F, 0x5C, 0x00, 0xB1, 0x8F,
-0x58, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x80, 0x00, 0xBD, 0x27,
-0xC0, 0x3A, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x10, 0x22, 0x02,
-0x77, 0xFF, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x24, 0x56, 0x56, 0x24, 0x26, 0x56, 0x75, 0x24, 0x21, 0xA0, 0x80, 0x00,
-0xBD, 0x4D, 0x00, 0x08, 0xDD, 0x00, 0x13, 0x24, 0x01, 0x00, 0x02, 0x92,
-0xC0, 0x3A, 0x83, 0x8E, 0x21, 0x10, 0x51, 0x00, 0x02, 0x00, 0x51, 0x24,
-0x2B, 0x18, 0x23, 0x02, 0x6B, 0xFF, 0x60, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0x80, 0x36, 0x02, 0x00, 0x00, 0x02, 0x92, 0x21, 0x90, 0x35, 0x02,
-0x21, 0x20, 0x40, 0x02, 0x40, 0x00, 0xA5, 0x27, 0xF3, 0xFF, 0x53, 0x14,
-0x04, 0x00, 0x06, 0x24, 0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xEF, 0xFF, 0x40, 0x14, 0x21, 0x20, 0xE0, 0x02, 0x01, 0x00, 0x06, 0x92,
-0x54, 0x00, 0xA3, 0x8F, 0x21, 0x38, 0x40, 0x02, 0xDD, 0x00, 0x05, 0x24,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA3, 0xAF, 0x26, 0x4D, 0x00, 0x08,
-0x21, 0xB8, 0x40, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C,
-0x8C, 0xEA, 0x84, 0x24, 0x01, 0x00, 0x06, 0x92, 0x54, 0x00, 0xA2, 0x8F,
-0x02, 0x80, 0x07, 0x3C, 0x26, 0x56, 0xE7, 0x24, 0x21, 0x38, 0x27, 0x02,
-0x21, 0x20, 0xE0, 0x02, 0x44, 0x00, 0x05, 0x24, 0x25, 0x52, 0x00, 0x0C,
-0x10, 0x00, 0xA2, 0xAF, 0x95, 0x4D, 0x00, 0x08, 0x02, 0x80, 0x03, 0x3C,
-0xB6, 0x40, 0x83, 0x90, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x62, 0x10,
-0x05, 0x00, 0x02, 0x24, 0x9C, 0xFF, 0x62, 0x14, 0x02, 0x80, 0x03, 0x3C,
-0x02, 0x80, 0x07, 0x3C, 0x21, 0x20, 0xE0, 0x02, 0x34, 0xDE, 0xE7, 0x24,
-0xDD, 0x00, 0x05, 0x24, 0x06, 0x00, 0x06, 0x24, 0x54, 0x00, 0xA3, 0x8F,
-0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA3, 0xAF, 0x7E, 0x4D, 0x00, 0x08,
-0x21, 0xB8, 0x40, 0x00, 0x02, 0x80, 0x14, 0x3C, 0x26, 0x56, 0xA5, 0x24,
-0x21, 0x28, 0x25, 0x02, 0x64, 0x5C, 0x84, 0x26, 0xF4, 0x54, 0x00, 0x0C,
-0x20, 0x00, 0x06, 0x24, 0x02, 0x80, 0x03, 0x3C, 0xD9, 0x5C, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x41, 0x02, 0x96, 0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0x42, 0x30,
-0x04, 0x41, 0x02, 0xA6, 0x02, 0x80, 0x02, 0x3C, 0xC4, 0xDF, 0x44, 0x8C,
-0x04, 0x41, 0xA3, 0x96, 0x20, 0x00, 0x80, 0x10, 0x0C, 0x00, 0x62, 0x34,
-0x00, 0x01, 0x42, 0x34, 0x04, 0x41, 0xA2, 0xA6, 0x02, 0x80, 0x03, 0x3C,
-0xC6, 0x5C, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x15, 0x00, 0x40, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x67, 0x5C, 0x64, 0x26, 0x44, 0xDF, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x10, 0x00, 0x06, 0x24, 0x21, 0x10, 0x32, 0x02, 0x01, 0x00, 0x46, 0x90,
-0x54, 0x00, 0xA3, 0x8F, 0x21, 0x20, 0xE0, 0x02, 0x64, 0x5C, 0x87, 0x26,
-0x2D, 0x00, 0x05, 0x24, 0x25, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA3, 0xAF,
-0x21, 0xB8, 0x40, 0x00, 0x01, 0x00, 0x02, 0x24, 0x20, 0x4D, 0x00, 0x08,
-0xFC, 0x40, 0x02, 0xAE, 0x04, 0x41, 0x02, 0x96, 0xFC, 0x4D, 0x00, 0x08,
-0x02, 0x00, 0x42, 0x34, 0x67, 0x5C, 0x64, 0x26, 0x0D, 0x4E, 0x00, 0x08,
-0x54, 0xDF, 0xA5, 0x24, 0x04, 0x4E, 0x00, 0x08, 0x04, 0x41, 0xA2, 0xA6,
-0x02, 0x80, 0x02, 0x3C, 0x34, 0xDE, 0x42, 0x24, 0x06, 0x00, 0x48, 0x90,
-0x02, 0x00, 0x03, 0x24, 0x21, 0x20, 0xE0, 0x02, 0x01, 0x00, 0x08, 0x35,
-0x21, 0x38, 0x40, 0x00, 0xDD, 0x00, 0x05, 0x24, 0x07, 0x00, 0x06, 0x24,
-0x04, 0x00, 0x43, 0xA0, 0xE9, 0x4D, 0x00, 0x08, 0x06, 0x00, 0x48, 0xA0,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0xAC, 0xE8, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0x64, 0xEA, 0xA5, 0x24, 0x9F, 0x4D, 0x00, 0x08,
-0xFF, 0xFF, 0x02, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0xB0, 0x1B, 0x43, 0x94, 0x32, 0x00, 0x04, 0x24, 0xCC, 0x39, 0x44, 0xAC,
-0x9F, 0xFE, 0x63, 0x30, 0x80, 0x00, 0x63, 0x34, 0xB0, 0x1B, 0x43, 0xA4,
-0x18, 0x40, 0x40, 0xAC, 0x1C, 0x40, 0x40, 0xAC, 0x38, 0x4C, 0x00, 0x08,
-0xB0, 0x39, 0x40, 0xAC, 0xE8, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF, 0x60, 0x1B, 0x50, 0x24,
-0x1C, 0x40, 0x03, 0x8E, 0xFE, 0xFF, 0x04, 0x24, 0x01, 0x00, 0x63, 0x24,
-0x03, 0x00, 0x62, 0x2C, 0x12, 0x00, 0x40, 0x10, 0x1C, 0x40, 0x03, 0xAE,
-0xB0, 0x1B, 0x02, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0x30,
-0x05, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0x38, 0x4C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x03, 0x24,
-0xCC, 0x39, 0x03, 0xAE, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xB0, 0x1B, 0x02, 0x96,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xDF, 0x42, 0x30, 0x35, 0x48, 0x00, 0x0C,
-0xB0, 0x1B, 0x02, 0xA6, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xD0, 0xFF, 0xBD, 0x27,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x2C, 0x00, 0xBF, 0xAF,
-0x02, 0x00, 0x82, 0x90, 0x02, 0x80, 0x14, 0x3C, 0x60, 0x1B, 0x92, 0x26,
-0xB0, 0x1B, 0x43, 0x96, 0x00, 0x00, 0x85, 0x8C, 0x0F, 0x00, 0x42, 0x30,
-0xC0, 0x10, 0x02, 0x00, 0x21, 0x80, 0x44, 0x00, 0x01, 0x00, 0x63, 0x30,
-0xFF, 0x3F, 0xB3, 0x30, 0x18, 0x00, 0x11, 0x26, 0x0A, 0x00, 0x60, 0x14,
-0x21, 0x20, 0x00, 0x00, 0x2C, 0x00, 0xBF, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x80, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x30, 0x00, 0xBD, 0x27, 0x39, 0x53, 0x00, 0x0C, 0x21, 0x20, 0x20, 0x02,
-0x02, 0x80, 0x04, 0x3C, 0x48, 0x37, 0x84, 0x24, 0x21, 0x28, 0x40, 0x00,
-0x1D, 0x55, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0xEF, 0xFF, 0x40, 0x14,
-0x21, 0x20, 0x00, 0x00, 0xB0, 0x1B, 0x42, 0x96, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x10, 0x42, 0x30, 0xEA, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x00, 0x03, 0x96, 0x04, 0x00, 0x04, 0x24, 0x21, 0x10, 0x80, 0x00,
-0x00, 0x40, 0x63, 0x30, 0x0A, 0x10, 0x03, 0x00, 0x21, 0x10, 0x22, 0x02,
-0x1C, 0x00, 0x43, 0x94, 0x1A, 0x00, 0x45, 0x94, 0x2F, 0x00, 0x60, 0x14,
-0x02, 0x00, 0x02, 0x24, 0x14, 0x00, 0xA2, 0x10, 0x01, 0x00, 0x02, 0x24,
-0x0E, 0x00, 0xA4, 0x14, 0x02, 0x80, 0x04, 0x3C, 0x24, 0x40, 0x43, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x62, 0x10, 0x60, 0x1B, 0x83, 0x26,
-0xB0, 0x1B, 0x62, 0x94, 0xFF, 0xFF, 0x04, 0x24, 0xFF, 0xDF, 0x42, 0x30,
-0x7B, 0x4E, 0x00, 0x08, 0xB0, 0x1B, 0x62, 0xA4, 0x36, 0x4E, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x7B, 0x4E, 0x00, 0x08, 0x21, 0x20, 0x00, 0x00,
-0x13, 0x58, 0x00, 0x0C, 0x04, 0xEB, 0x84, 0x24, 0xA4, 0x4E, 0x00, 0x08,
-0x60, 0x1B, 0x83, 0x26, 0x24, 0x40, 0x43, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0xF5, 0xFF, 0x62, 0x14, 0xE2, 0xFF, 0x67, 0x26, 0x36, 0x00, 0x04, 0x26,
-0x10, 0x00, 0x05, 0x24, 0xAB, 0x1A, 0x00, 0x0C, 0x10, 0x00, 0xA6, 0x27,
-0x16, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xA6, 0x8F,
-0x02, 0x80, 0x04, 0x3C, 0x94, 0x5B, 0x84, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x45, 0x24, 0xB0, 0x1B, 0x43, 0x96, 0x21, 0x20, 0x00, 0x00,
-0x03, 0x00, 0x02, 0x24, 0xDF, 0xFF, 0x63, 0x30, 0x40, 0x00, 0x63, 0x34,
-0xB0, 0x1B, 0x43, 0xA6, 0x2D, 0x14, 0x00, 0x0C, 0x20, 0x40, 0x42, 0xAE,
-0x7B, 0x4E, 0x00, 0x08, 0x21, 0x20, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x2C, 0xEB, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0x21, 0x28, 0x60, 0x00,
-0xA4, 0x4E, 0x00, 0x08, 0x60, 0x1B, 0x83, 0x26, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0x48, 0xEB, 0x84, 0x24, 0xA4, 0x4E, 0x00, 0x08,
-0x60, 0x1B, 0x83, 0x26, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x63, 0x24,
-0xB0, 0x1B, 0x62, 0x94, 0x01, 0x00, 0x05, 0x24, 0x21, 0x20, 0x00, 0x00,
-0xEF, 0xFF, 0x42, 0x30, 0x20, 0x00, 0x42, 0x34, 0xB0, 0x1B, 0x62, 0xA4,
-0x32, 0x00, 0x02, 0x24, 0x20, 0x40, 0x65, 0xAC, 0xB0, 0x39, 0x62, 0xAC,
-0xCC, 0x39, 0x60, 0xAC, 0x18, 0x40, 0x60, 0xAC, 0x2D, 0x14, 0x00, 0x08,
-0x1C, 0x40, 0x60, 0xAC, 0xE8, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x07, 0x3C,
-0x14, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0xE6, 0x24,
-0x18, 0x40, 0xC2, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x45, 0x24,
-0x03, 0x00, 0xA3, 0x2C, 0x0E, 0x00, 0x60, 0x14, 0x60, 0x1B, 0xF0, 0x24,
-0x24, 0x40, 0xC3, 0x8C, 0x03, 0x00, 0x02, 0x24, 0x16, 0x00, 0x62, 0x10,
-0xFF, 0xFF, 0x04, 0x24, 0xB0, 0x1B, 0xC2, 0x94, 0x18, 0x40, 0xC5, 0xAC,
-0xFF, 0xDF, 0x42, 0x30, 0x35, 0x48, 0x00, 0x0C, 0xB0, 0x1B, 0xC2, 0xA4,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xB0, 0x1B, 0x03, 0x96, 0xBF, 0xFF, 0x02, 0x24,
-0x18, 0x40, 0xC5, 0xAC, 0x24, 0x10, 0x62, 0x00, 0x80, 0x00, 0x63, 0x30,
-0x21, 0x20, 0x00, 0x00, 0x0F, 0x00, 0x60, 0x10, 0x20, 0x00, 0x45, 0x34,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xB0, 0x1B, 0x03, 0x96, 0x01, 0x00, 0x02, 0x24,
-0x24, 0x40, 0xC2, 0xAC, 0xBF, 0xFF, 0x02, 0x24, 0x24, 0x10, 0x62, 0x00,
-0x80, 0x00, 0x63, 0x30, 0x18, 0x40, 0xC0, 0xAC, 0x21, 0x20, 0x00, 0x00,
-0xF3, 0xFF, 0x60, 0x14, 0x20, 0x00, 0x45, 0x34, 0x01, 0x00, 0x02, 0x24,
-0x20, 0x40, 0x02, 0xAE, 0x2D, 0x14, 0x00, 0x0C, 0xB0, 0x1B, 0x05, 0xA6,
-0x32, 0x00, 0x03, 0x24, 0xB0, 0x39, 0x03, 0xAE, 0x14, 0x00, 0xBF, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0xD0, 0xFF, 0xBD, 0x27, 0x20, 0x00, 0xB2, 0xAF, 0x21, 0x90, 0x80, 0x00,
-0x00, 0x01, 0x04, 0x24, 0x24, 0x00, 0xB3, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x21, 0x98, 0xA0, 0x00, 0x28, 0x00, 0xBF, 0xAF, 0x53, 0x21, 0x00, 0x0C,
-0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x21, 0x88, 0x40, 0x00, 0x58, 0xEC, 0x84, 0x24, 0x38, 0x00, 0x40, 0x10,
-0x48, 0xEC, 0xA5, 0x24, 0x13, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x30, 0x96, 0x02, 0x80, 0x02, 0x3C, 0x21, 0x28, 0x40, 0x02,
-0x25, 0x80, 0x02, 0x02, 0x24, 0x00, 0x04, 0x26, 0x20, 0x00, 0x00, 0xA6,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C,
-0x2A, 0x00, 0x04, 0x26, 0x48, 0x37, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C, 0x30, 0x00, 0x04, 0x26,
-0xB4, 0x55, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x20, 0x00, 0x03, 0x96, 0x18, 0x00, 0x02, 0x24, 0x02, 0x80, 0x05, 0x3C,
-0x03, 0xFF, 0x63, 0x30, 0xC0, 0x00, 0x63, 0x34, 0x20, 0x00, 0x03, 0xA6,
-0x60, 0x1B, 0xA5, 0x24, 0x0C, 0x00, 0x22, 0xAE, 0xE4, 0x1D, 0xA3, 0x94,
-0x20, 0x00, 0x07, 0x26, 0x38, 0x00, 0x04, 0x26, 0xFF, 0x0F, 0x62, 0x30,
-0x00, 0x11, 0x02, 0x00, 0x02, 0x32, 0x02, 0x00, 0x01, 0x00, 0x63, 0x24,
-0xE4, 0x1D, 0xA3, 0xA4, 0x17, 0x00, 0xE6, 0xA0, 0x16, 0x00, 0xE2, 0xA0,
-0x10, 0x00, 0xA6, 0x27, 0x0C, 0x00, 0x27, 0x26, 0x02, 0x00, 0x05, 0x24,
-0x4C, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB3, 0xA7, 0x21, 0x20, 0x20, 0x02,
-0x21, 0x28, 0x00, 0x00, 0x21, 0x30, 0x00, 0x00, 0xDF, 0x0D, 0x00, 0x0C,
-0x21, 0x38, 0x00, 0x00, 0x28, 0x00, 0xBF, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xAC, 0xE8, 0x84, 0x24, 0x28, 0x00, 0xBF, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0xD0, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB1, 0xAF, 0x21, 0x88, 0x80, 0x00,
-0x00, 0x01, 0x04, 0x24, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x21, 0x98, 0xA0, 0x00, 0x28, 0x00, 0xBF, 0xAF, 0x53, 0x21, 0x00, 0x0C,
-0x18, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x21, 0x90, 0x40, 0x00, 0x78, 0xEC, 0x84, 0x24, 0x3B, 0x00, 0x40, 0x10,
-0x68, 0xEC, 0xA5, 0x24, 0x13, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x50, 0x96, 0x02, 0x80, 0x02, 0x3C, 0x21, 0x28, 0x20, 0x02,
-0x25, 0x80, 0x02, 0x02, 0x24, 0x00, 0x04, 0x26, 0x20, 0x00, 0x00, 0xA6,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C,
-0x2A, 0x00, 0x04, 0x26, 0x48, 0x37, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C, 0x30, 0x00, 0x04, 0x26,
-0xB4, 0x55, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x20, 0x00, 0x03, 0x96, 0x18, 0x00, 0x02, 0x24, 0x02, 0x80, 0x11, 0x3C,
-0x03, 0xFF, 0x63, 0x30, 0xA0, 0x00, 0x63, 0x34, 0x20, 0x00, 0x03, 0xA6,
-0x60, 0x1B, 0x31, 0x26, 0x0C, 0x00, 0x42, 0xAE, 0xE4, 0x1D, 0x23, 0x96,
-0x20, 0x00, 0x06, 0x26, 0x38, 0x00, 0x04, 0x26, 0xFF, 0x0F, 0x62, 0x30,
-0x00, 0x11, 0x02, 0x00, 0x02, 0x2A, 0x02, 0x00, 0x01, 0x00, 0x63, 0x24,
-0xE4, 0x1D, 0x23, 0xA6, 0x0C, 0x00, 0x47, 0x26, 0x17, 0x00, 0xC5, 0xA0,
-0x16, 0x00, 0xC2, 0xA0, 0x02, 0x00, 0x05, 0x24, 0x10, 0x00, 0xA6, 0x27,
-0x4C, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xB3, 0xA7, 0xB6, 0x40, 0x23, 0x92,
-0x04, 0x00, 0x07, 0x24, 0x21, 0x20, 0x40, 0x02, 0x01, 0x00, 0x63, 0x38,
-0x0B, 0x38, 0x03, 0x00, 0x21, 0x28, 0x00, 0x00, 0xDF, 0x0D, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0x28, 0x00, 0xBF, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xAC, 0xE8, 0x84, 0x24, 0x28, 0x00, 0xBF, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0xC8, 0xFF, 0xBD, 0x27, 0x2C, 0x00, 0xB1, 0xAF, 0xFF, 0xFF, 0x05, 0x24,
-0x21, 0x88, 0x80, 0x00, 0x02, 0x00, 0x06, 0x24, 0x10, 0x00, 0xA4, 0x27,
-0x34, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xB2, 0xAF, 0xEC, 0x54, 0x00, 0x0C,
-0x28, 0x00, 0xB0, 0xAF, 0x08, 0x00, 0x30, 0x96, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0x28, 0x00, 0x00, 0x25, 0x80, 0x02, 0x02, 0x21, 0x20, 0x00, 0x02,
-0xEC, 0x54, 0x00, 0x0C, 0x10, 0x00, 0x06, 0x24, 0x20, 0x00, 0x02, 0x96,
-0x24, 0x00, 0x04, 0x26, 0x10, 0x00, 0xA5, 0x27, 0x03, 0xFF, 0x42, 0x30,
-0xC8, 0x00, 0x42, 0x34, 0x20, 0x00, 0x02, 0xA6, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x25, 0xB0, 0x03, 0x3C, 0x50, 0x00, 0x62, 0x34,
-0x00, 0x00, 0x44, 0x8C, 0x54, 0x00, 0x65, 0x34, 0x58, 0x00, 0x66, 0x34,
-0x18, 0x00, 0xA4, 0xAF, 0x00, 0x00, 0xA2, 0x8C, 0x5C, 0x00, 0x63, 0x34,
-0x2A, 0x00, 0x04, 0x26, 0x1C, 0x00, 0xA2, 0xAF, 0x00, 0x00, 0xC7, 0x8C,
-0x18, 0x00, 0xA5, 0x27, 0x06, 0x00, 0x06, 0x24, 0x20, 0x00, 0xA7, 0xAF,
-0x00, 0x00, 0x62, 0x8C, 0x1A, 0x00, 0x12, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x24, 0x00, 0xA2, 0xAF, 0x30, 0x00, 0x04, 0x26, 0x20, 0x00, 0xA5, 0x27,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x13, 0x00, 0x03, 0x24,
-0x14, 0x00, 0x23, 0xAE, 0x0C, 0x00, 0x32, 0xAE, 0x08, 0x00, 0x05, 0x8E,
-0x04, 0x00, 0x04, 0x8E, 0xFF, 0xDF, 0x02, 0x3C, 0x14, 0x00, 0x06, 0x8E,
-0xFF, 0xFF, 0x42, 0x34, 0x10, 0x00, 0x07, 0x8E, 0xFF, 0xE0, 0x03, 0x24,
-0x24, 0x28, 0xA2, 0x00, 0x00, 0x40, 0x02, 0x3C, 0x24, 0x20, 0x83, 0x00,
-0x25, 0x28, 0xA2, 0x00, 0xFF, 0x81, 0x03, 0x24, 0xFE, 0xFF, 0x02, 0x3C,
-0x24, 0x30, 0xC3, 0x00, 0xFF, 0xFF, 0x42, 0x34, 0x00, 0x12, 0x84, 0x34,
-0x00, 0x80, 0x03, 0x3C, 0x24, 0x20, 0x82, 0x00, 0x25, 0x38, 0xE3, 0x00,
-0x00, 0x26, 0xC6, 0x34, 0x80, 0x00, 0xA5, 0x34, 0x20, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x12, 0xA6, 0x10, 0x00, 0x07, 0xAE, 0x02, 0x00, 0x02, 0xA2,
-0x14, 0x00, 0x06, 0xAE, 0x04, 0x00, 0x04, 0xAE, 0x08, 0x00, 0x05, 0xAE,
-0x34, 0x00, 0xBF, 0x8F, 0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F,
-0x28, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27,
-0xB0, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xB5, 0xAF, 0x34, 0x00, 0xB3, 0xAF,
-0xFF, 0xFF, 0xF5, 0x30, 0x25, 0xB0, 0x13, 0x3C, 0x01, 0x80, 0x02, 0x3C,
-0x2C, 0x00, 0xB1, 0xAF, 0x18, 0x03, 0x63, 0x36, 0x54, 0x40, 0x42, 0x24,
-0x20, 0x00, 0xB1, 0x26, 0x48, 0x00, 0xBE, 0xAF, 0x44, 0x00, 0xB7, 0xAF,
-0x38, 0x00, 0xB4, 0xAF, 0x64, 0x00, 0xB7, 0x93, 0x60, 0x00, 0xB4, 0x93,
-0x21, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x62, 0xAC, 0x21, 0x20, 0x20, 0x02,
-0x40, 0x00, 0xB6, 0xAF, 0x30, 0x00, 0xB2, 0xAF, 0x4C, 0x00, 0xBF, 0xAF,
-0x28, 0x00, 0xB0, 0xAF, 0xFF, 0x00, 0xB6, 0x30, 0x53, 0x21, 0x00, 0x0C,
-0xFF, 0x00, 0xD2, 0x30, 0x12, 0x00, 0x40, 0x14, 0x24, 0x00, 0xA2, 0xAF,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0xAC, 0xE8, 0x84, 0x24,
-0x13, 0x58, 0x00, 0x0C, 0x88, 0xEC, 0xA5, 0x24, 0x4C, 0x00, 0xBF, 0x8F,
-0x48, 0x00, 0xBE, 0x8F, 0x44, 0x00, 0xB7, 0x8F, 0x40, 0x00, 0xB6, 0x8F,
-0x3C, 0x00, 0xB5, 0x8F, 0x38, 0x00, 0xB4, 0x8F, 0x34, 0x00, 0xB3, 0x8F,
-0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F, 0x28, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x50, 0x00, 0xBD, 0x27, 0x08, 0x00, 0x43, 0x8C,
-0xB0, 0x03, 0x62, 0x36, 0x02, 0x80, 0x10, 0x3C, 0x00, 0x00, 0x43, 0xAC,
-0x24, 0x00, 0xA2, 0x8F, 0x21, 0x30, 0x20, 0x02, 0x21, 0x28, 0x00, 0x00,
-0x08, 0x00, 0x44, 0x94, 0xE3, 0x54, 0x00, 0x0C, 0x25, 0x20, 0x90, 0x00,
-0x24, 0x00, 0xA3, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x62, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x88, 0x50, 0x00, 0x5C, 0x00, 0x80, 0x16,
-0x20, 0x00, 0x30, 0x26, 0x20, 0x00, 0x32, 0xA6, 0x48, 0x00, 0x02, 0x24,
-0x7A, 0x00, 0x42, 0x12, 0xC8, 0x00, 0x02, 0x24, 0x79, 0x00, 0x42, 0x12,
-0x50, 0x00, 0x62, 0x36, 0x04, 0x00, 0x02, 0x24, 0x56, 0x00, 0xC2, 0x16,
-0x21, 0x28, 0xC0, 0x03, 0xA4, 0x00, 0x02, 0x24, 0x9F, 0x00, 0x42, 0x12,
-0x02, 0x80, 0x02, 0x3C, 0x24, 0x00, 0xA2, 0x8F, 0x25, 0xB0, 0x10, 0x3C,
-0xB0, 0x03, 0x10, 0x36, 0x0C, 0x00, 0x55, 0xAC, 0x24, 0x00, 0xA2, 0x8F,
-0x12, 0x00, 0x03, 0x24, 0x21, 0x28, 0x00, 0x00, 0x14, 0x00, 0x43, 0xAC,
-0x00, 0x00, 0x15, 0xAE, 0x24, 0x00, 0xA2, 0x8F, 0x08, 0x00, 0x06, 0x24,
-0x08, 0x00, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xAE,
-0x24, 0x00, 0xA2, 0x8F, 0x02, 0x80, 0x03, 0x3C, 0x08, 0x00, 0x44, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x88, 0x83, 0x00, 0xEC, 0x54, 0x00, 0x0C,
-0x21, 0x20, 0x20, 0x02, 0x04, 0x00, 0x25, 0x8E, 0x08, 0x00, 0x24, 0x8E,
-0xFF, 0xDF, 0x02, 0x3C, 0xFF, 0xE0, 0x03, 0x24, 0xFF, 0xFF, 0x42, 0x34,
-0x14, 0x00, 0x26, 0x8E, 0x24, 0x28, 0xA3, 0x00, 0x24, 0x20, 0x82, 0x00,
-0x00, 0x40, 0x02, 0x3C, 0x10, 0x00, 0x27, 0x8E, 0x25, 0x20, 0x82, 0x00,
-0xE0, 0xFF, 0x03, 0x24, 0x00, 0x12, 0xA5, 0x34, 0xFF, 0xE0, 0x02, 0x3C,
-0x24, 0x28, 0xA3, 0x00, 0xFF, 0xFF, 0x42, 0x34, 0xFF, 0x81, 0x03, 0x24,
-0x24, 0x30, 0xC3, 0x00, 0x24, 0x20, 0x82, 0x00, 0x00, 0x05, 0x03, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0x25, 0x38, 0xE2, 0x00, 0x25, 0x20, 0x83, 0x00,
-0x05, 0x00, 0xA5, 0x34, 0x20, 0x00, 0x02, 0x24, 0x08, 0x00, 0x24, 0xAE,
-0x00, 0x00, 0x35, 0xA6, 0x02, 0x00, 0x22, 0xA2, 0x14, 0x00, 0x26, 0xAE,
-0x10, 0x00, 0x27, 0xAE, 0x04, 0x00, 0x25, 0xAE, 0x8A, 0x40, 0x00, 0x0C,
-0x20, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x24, 0x00, 0xA3, 0x8F,
-0x98, 0x54, 0x42, 0x24, 0x04, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x62, 0xAC,
-0x04, 0x00, 0x43, 0xAC, 0x24, 0x00, 0xA2, 0x27, 0x00, 0x00, 0x83, 0xAC,
-0x04, 0x00, 0x64, 0xAC, 0x20, 0x00, 0xA4, 0x27, 0x00, 0x00, 0x02, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0xBF, 0x8F,
-0x48, 0x00, 0xBE, 0x8F, 0x44, 0x00, 0xB7, 0x8F, 0x40, 0x00, 0xB6, 0x8F,
-0x3C, 0x00, 0xB5, 0x8F, 0x38, 0x00, 0xB4, 0x8F, 0x34, 0x00, 0xB3, 0x8F,
-0x30, 0x00, 0xB2, 0x8F, 0x2C, 0x00, 0xB1, 0x8F, 0x28, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x50, 0x00, 0xBD, 0x27, 0x00, 0x10, 0x42, 0x36,
-0x53, 0x50, 0x00, 0x08, 0x20, 0x00, 0x22, 0xA6, 0x04, 0x00, 0x04, 0x26,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C,
-0x48, 0x37, 0xA5, 0x24, 0x0A, 0x00, 0x04, 0x26, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C, 0xB4, 0x55, 0xA5, 0x24,
-0x10, 0x00, 0x04, 0x26, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x00, 0x1E, 0x12, 0x00, 0x03, 0x1E, 0x03, 0x00, 0x28, 0x00, 0x60, 0x04,
-0x02, 0x80, 0x05, 0x3C, 0x60, 0x1B, 0xA5, 0x24, 0xE4, 0x1D, 0xA6, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xC2, 0x24, 0x00, 0x21, 0x06, 0x00,
-0xFF, 0xFF, 0x46, 0x30, 0xFF, 0xFF, 0x84, 0x30, 0x00, 0x10, 0xC2, 0x2C,
-0x0A, 0x30, 0x02, 0x00, 0x02, 0x1A, 0x04, 0x00, 0x17, 0x00, 0x03, 0xA2,
-0x16, 0x00, 0x04, 0xA2, 0x5E, 0x50, 0x00, 0x08, 0xE4, 0x1D, 0xA6, 0xA4,
-0x50, 0x00, 0x62, 0x36, 0x00, 0x00, 0x43, 0x8C, 0x54, 0x00, 0x64, 0x36,
-0x58, 0x00, 0x65, 0x36, 0x10, 0x00, 0xA3, 0xAF, 0x00, 0x00, 0x82, 0x8C,
-0x5C, 0x00, 0x67, 0x36, 0x2A, 0x00, 0x24, 0x26, 0x14, 0x00, 0xA2, 0xAF,
-0x00, 0x00, 0xA3, 0x8C, 0x06, 0x00, 0x06, 0x24, 0x10, 0x00, 0xA5, 0x27,
-0x18, 0x00, 0xA3, 0xAF, 0x00, 0x00, 0xE2, 0x8C, 0xF4, 0x54, 0x00, 0x0C,
-0x1C, 0x00, 0xA2, 0xAF, 0x30, 0x00, 0x24, 0x26, 0x18, 0x00, 0xA5, 0x27,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x20, 0x00, 0x23, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x63, 0x34, 0x58, 0x50, 0x00, 0x08,
-0x20, 0x00, 0x23, 0xA6, 0x02, 0x80, 0x02, 0x3C, 0xFF, 0xFF, 0xE3, 0x32,
-0x60, 0x1B, 0x42, 0x24, 0x40, 0x28, 0x17, 0x00, 0x18, 0x00, 0x03, 0xA2,
-0x21, 0x28, 0xA2, 0x00, 0x19, 0x00, 0x00, 0xA2, 0xD4, 0x1D, 0xA6, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xC2, 0x24, 0x00, 0x21, 0x06, 0x00,
-0xFF, 0xFF, 0x46, 0x30, 0xFF, 0xFF, 0x84, 0x30, 0x00, 0x10, 0xC2, 0x2C,
-0x0A, 0x30, 0x02, 0x00, 0x02, 0x1A, 0x04, 0x00, 0x17, 0x00, 0x03, 0xA2,
-0x16, 0x00, 0x04, 0xA2, 0x5E, 0x50, 0x00, 0x08, 0xD4, 0x1D, 0xA6, 0xA4,
-0xAC, 0x55, 0x43, 0x94, 0x02, 0x80, 0x05, 0x3C, 0x04, 0x00, 0x04, 0x26,
-0x00, 0xC0, 0x63, 0x24, 0xFF, 0xFF, 0x63, 0x30, 0x02, 0x12, 0x03, 0x00,
-0xB4, 0x55, 0xA5, 0x24, 0x03, 0x00, 0x02, 0xA2, 0x02, 0x00, 0x03, 0xA2,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x02, 0x80, 0x05, 0x3C,
-0x0A, 0x00, 0x04, 0x26, 0x48, 0x37, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x5E, 0x50, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x82, 0x30, 0x02, 0x80, 0x04, 0x3C, 0xE0, 0xFF, 0xBD, 0x27,
-0xB4, 0x55, 0x84, 0x24, 0x08, 0x00, 0x05, 0x24, 0x48, 0x00, 0x06, 0x24,
-0x18, 0x00, 0x07, 0x24, 0x18, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xA2, 0xAF,
-0x15, 0x50, 0x00, 0x0C, 0x14, 0x00, 0xA0, 0xAF, 0x18, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xC8, 0xFF, 0xBD, 0x27, 0x2C, 0x00, 0xB5, 0xAF, 0x02, 0x80, 0x15, 0x3C,
-0x1C, 0x00, 0xB1, 0xAF, 0x34, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xB6, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0xB1, 0x26, 0xB0, 0x1B, 0x23, 0x96,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x62, 0x30, 0x37, 0x00, 0x40, 0x14,
-0x00, 0x01, 0x62, 0x30, 0x2A, 0x00, 0x40, 0x10, 0x00, 0x10, 0x62, 0x30,
-0x25, 0x00, 0x40, 0x14, 0x01, 0x00, 0x62, 0x30, 0x45, 0x00, 0x40, 0x14,
-0x04, 0x00, 0x62, 0x30, 0x21, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x21, 0x98, 0x20, 0x02, 0x47, 0x39, 0x56, 0x24, 0x01, 0x00, 0x14, 0x24,
-0x20, 0x01, 0x11, 0x24, 0x3E, 0x51, 0x00, 0x08, 0x19, 0x00, 0x12, 0x24,
-0xFF, 0xFF, 0x52, 0x26, 0x18, 0x00, 0x40, 0x06, 0x30, 0x00, 0x31, 0x26,
-0x21, 0x80, 0x33, 0x02, 0xE6, 0x1D, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xF9, 0xFF, 0x54, 0x14, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1D, 0x02, 0x8E,
-0x00, 0x00, 0x00, 0x00, 0x45, 0x00, 0x40, 0x14, 0x10, 0x00, 0xA4, 0x27,
-0x3A, 0x41, 0x62, 0x92, 0x21, 0x20, 0x36, 0x02, 0xFF, 0xFF, 0x42, 0x24,
-0x3A, 0x41, 0x62, 0xA2, 0xC4, 0x0E, 0x00, 0x0C, 0xE6, 0x1D, 0x00, 0xA2,
-0x3C, 0x51, 0x00, 0x08, 0xFF, 0xFF, 0x52, 0x26, 0x8A, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x10, 0x00, 0xA4, 0x27, 0x14, 0x40, 0x20, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0xE8, 0x1E, 0x20, 0xAE, 0xA9, 0x1B, 0x00, 0x0C,
-0x60, 0x1B, 0xB0, 0x26, 0xE8, 0x39, 0x02, 0xAE, 0x34, 0x00, 0xBF, 0x8F,
-0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F,
-0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x38, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C,
-0x98, 0xEC, 0x84, 0x24, 0xB0, 0x1B, 0x22, 0x96, 0xE8, 0x39, 0x20, 0xAE,
-0xFD, 0xFF, 0x04, 0x24, 0xEF, 0xDF, 0x42, 0x30, 0x35, 0x48, 0x00, 0x0C,
-0xB0, 0x1B, 0x22, 0xA6, 0x34, 0x00, 0xBF, 0x8F, 0x30, 0x00, 0xB6, 0x8F,
-0x2C, 0x00, 0xB5, 0x8F, 0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F,
-0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27,
-0xE8, 0x1E, 0x22, 0x8E, 0x00, 0x00, 0x00, 0x00, 0xD5, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x22, 0x8E, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x00, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0xEE, 0x5D, 0x43, 0x90,
-0x01, 0x00, 0x04, 0x24, 0x0F, 0x00, 0x63, 0x30, 0x05, 0x00, 0x63, 0x28,
-0x0E, 0x00, 0x60, 0x10, 0x14, 0x40, 0x24, 0xAE, 0x0E, 0x51, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xA9, 0x1B, 0x00, 0x0C, 0x60, 0x1B, 0xB0, 0x26,
-0x58, 0x51, 0x00, 0x08, 0xE8, 0x39, 0x02, 0xAE, 0x8A, 0x40, 0x00, 0x0C,
-0xFF, 0xFF, 0x52, 0x26, 0x10, 0x00, 0xA4, 0x27, 0x90, 0x40, 0x00, 0x0C,
-0xF8, 0x1D, 0x00, 0xAE, 0x3C, 0x51, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x0E, 0x51, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00, 0x87, 0x51, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C,
-0xB8, 0xEC, 0x84, 0x24, 0x25, 0xB0, 0x06, 0x3C, 0x4C, 0x00, 0xC2, 0x34,
-0x00, 0x00, 0x40, 0xA0, 0x48, 0x00, 0xC6, 0x34, 0x00, 0x00, 0xC3, 0x8C,
-0xB0, 0x1B, 0x27, 0x96, 0x7B, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x24, 0x18, 0x62, 0x00, 0xFE, 0xFE, 0xE7, 0x30, 0x00, 0x00, 0xC3, 0xAC,
-0x21, 0x28, 0x00, 0x00, 0xB0, 0x1B, 0x27, 0xA6, 0x21, 0x20, 0x00, 0x00,
-0x37, 0x3E, 0x20, 0xA2, 0x95, 0x0E, 0x00, 0x0C, 0xD6, 0x1E, 0x20, 0xA2,
-0x02, 0x80, 0x04, 0x3C, 0xC4, 0x0E, 0x00, 0x0C, 0xB4, 0x55, 0x84, 0x24,
-0xA9, 0x1B, 0x00, 0x0C, 0x60, 0x1B, 0xB0, 0x26, 0x58, 0x51, 0x00, 0x08,
-0xE8, 0x39, 0x02, 0xAE, 0xFF, 0x00, 0x84, 0x30, 0x02, 0x00, 0x02, 0x24,
-0x03, 0x00, 0x83, 0x28, 0x0D, 0x00, 0x82, 0x10, 0x21, 0x28, 0x00, 0x00,
-0x06, 0x00, 0x60, 0x10, 0x04, 0x00, 0x02, 0x24, 0x01, 0x00, 0x02, 0x24,
-0x0B, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0xA0, 0x00, 0xFD, 0xFF, 0x82, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x04, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x06, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB1, 0xAF, 0xFF, 0x00, 0x91, 0x30,
-0x02, 0x80, 0x04, 0x3C, 0x18, 0x00, 0xB0, 0xAF, 0xD4, 0xEC, 0x84, 0x24,
-0xFF, 0x00, 0xB0, 0x30, 0x20, 0x00, 0xBF, 0xAF, 0x13, 0x58, 0x00, 0x0C,
-0x21, 0x28, 0x20, 0x02, 0xB1, 0x51, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02,
-0x02, 0x80, 0x04, 0x3C, 0xB4, 0x55, 0x84, 0x24, 0x08, 0x00, 0x05, 0x24,
-0xC8, 0x00, 0x06, 0x24, 0x1A, 0x00, 0x07, 0x24, 0x10, 0x00, 0xB1, 0xAF,
-0x15, 0x50, 0x00, 0x0C, 0x14, 0x00, 0xA2, 0xAF, 0x20, 0x00, 0xBF, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x05, 0x3C,
-0x1C, 0x00, 0xBF, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x60, 0x1B, 0xA5, 0x24,
-0x4C, 0x3A, 0xA2, 0x94, 0x01, 0x00, 0x03, 0x24, 0xFF, 0x00, 0x90, 0x30,
-0x00, 0xC0, 0x42, 0x24, 0xFF, 0xFF, 0x44, 0x30, 0xA3, 0x31, 0x00, 0x0C,
-0x2A, 0x1C, 0xA3, 0xA0, 0x02, 0x80, 0x04, 0x3C, 0xB4, 0x55, 0x84, 0x24,
-0x04, 0x00, 0x05, 0x24, 0xA4, 0x00, 0x06, 0x24, 0x10, 0x00, 0x07, 0x24,
-0x10, 0x00, 0xB0, 0xAF, 0x15, 0x50, 0x00, 0x0C, 0x14, 0x00, 0xA0, 0xAF,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x80, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x08, 0x00, 0x82, 0x24, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xBF, 0xAF, 0xFB, 0x51, 0x00, 0x0C, 0x74, 0x00, 0x84, 0x24,
-0x21, 0x28, 0x40, 0x00, 0x10, 0x00, 0xA4, 0x27, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x06, 0x24, 0x10, 0x00, 0xA2, 0x97, 0x18, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xBF, 0xAF, 0xFB, 0x51, 0x00, 0x0C,
-0x10, 0x00, 0xA5, 0xA7, 0x21, 0x20, 0x40, 0x00, 0x10, 0x00, 0xA5, 0x27,
-0xF4, 0x54, 0x00, 0x0C, 0x02, 0x00, 0x06, 0x24, 0x18, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x08, 0x00, 0xE0, 0x03, 0x0A, 0x00, 0x82, 0x24, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xBF, 0xAF, 0x16, 0x52, 0x00, 0x0C, 0x74, 0x00, 0x84, 0x24,
-0x21, 0x28, 0x40, 0x00, 0x10, 0x00, 0xA4, 0x27, 0xF4, 0x54, 0x00, 0x0C,
-0x02, 0x00, 0x06, 0x24, 0x10, 0x00, 0xA2, 0x97, 0x18, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x00, 0x00, 0x05, 0xA2, 0x01, 0x00, 0x06, 0xA2, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x1C, 0x00, 0xBF, 0xAF, 0x21, 0x88, 0xC0, 0x00,
-0x02, 0x00, 0x84, 0x24, 0x30, 0x00, 0xB2, 0x8F, 0x0D, 0x00, 0xC0, 0x14,
-0x21, 0x28, 0xE0, 0x00, 0x00, 0x00, 0x43, 0x8E, 0x21, 0x10, 0x11, 0x02,
-0x1C, 0x00, 0xBF, 0x8F, 0x21, 0x18, 0x71, 0x00, 0x02, 0x00, 0x63, 0x24,
-0x00, 0x00, 0x43, 0xAE, 0x14, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x02, 0x00, 0x42, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xF4, 0x54, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x43, 0x8E, 0x21, 0x10, 0x11, 0x02, 0x1C, 0x00, 0xBF, 0x8F,
-0x21, 0x18, 0x71, 0x00, 0x02, 0x00, 0x63, 0x24, 0x00, 0x00, 0x43, 0xAE,
-0x14, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x02, 0x00, 0x42, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0xA0, 0x00,
-0x18, 0x00, 0xB2, 0xAF, 0x21, 0x28, 0xC0, 0x00, 0x21, 0x90, 0xE0, 0x00,
-0x21, 0x30, 0x00, 0x02, 0x1C, 0x00, 0xBF, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0xF4, 0x54, 0x00, 0x0C, 0x21, 0x88, 0x80, 0x00, 0x00, 0x00, 0x43, 0x8E,
-0x21, 0x10, 0x30, 0x02, 0x1C, 0x00, 0xBF, 0x8F, 0x21, 0x18, 0x70, 0x00,
-0x00, 0x00, 0x43, 0xAE, 0x14, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x7F, 0x00, 0x84, 0x30, 0x6D, 0x00, 0x82, 0x2C, 0x0A, 0x00, 0x40, 0x10,
-0x21, 0x28, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x80, 0x10, 0x04, 0x00,
-0xFC, 0xEC, 0x63, 0x24, 0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x28, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x0B, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x0A, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x09, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x08, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x07, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x06, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x03, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x05, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x04, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x02, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x01, 0x00, 0x05, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x7F, 0x00, 0x84, 0x30, 0x0C, 0x00, 0x82, 0x2C, 0x0A, 0x00, 0x40, 0x10,
-0x21, 0x18, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x80, 0x10, 0x04, 0x00,
-0xB0, 0xEE, 0x63, 0x24, 0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x6C, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x60, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x48, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x30, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x24, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x18, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x12, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x0C, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x16, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x0B, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x04, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x02, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0xC8, 0xFF, 0xBD, 0x27, 0x24, 0x00, 0xB5, 0xAF, 0x02, 0x80, 0x15, 0x3C,
-0x2C, 0x00, 0xB7, 0xAF, 0x28, 0x00, 0xB6, 0xAF, 0x20, 0x00, 0xB4, 0xAF,
-0x1C, 0x00, 0xB3, 0xAF, 0x30, 0x00, 0xBF, 0xAF, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0xB8, 0x80, 0x00,
-0x21, 0xA0, 0x00, 0x00, 0x21, 0x98, 0x00, 0x00, 0x60, 0x1B, 0xB6, 0x26,
-0x60, 0x1B, 0xA2, 0x26, 0x21, 0x10, 0x62, 0x02, 0xFB, 0x1B, 0x51, 0x90,
-0xFE, 0x00, 0x03, 0x24, 0x1E, 0x00, 0x23, 0x12, 0xFF, 0x00, 0x02, 0x24,
-0x21, 0x00, 0x22, 0x12, 0x21, 0x10, 0x80, 0x02, 0x91, 0x52, 0x00, 0x0C,
-0x21, 0x20, 0x20, 0x02, 0x21, 0x88, 0x40, 0x00, 0x21, 0x80, 0x00, 0x00,
-0x21, 0x90, 0xC0, 0x02, 0x21, 0x10, 0x12, 0x02, 0xEE, 0x1B, 0x44, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x82, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x02, 0x00, 0x42, 0x2C, 0x05, 0x00, 0x40, 0x14, 0x01, 0x00, 0x10, 0x26,
-0x91, 0x52, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x51, 0x10,
-0x01, 0x00, 0x03, 0x24, 0x0D, 0x00, 0x02, 0x2A, 0xF3, 0xFF, 0x40, 0x14,
-0x21, 0x10, 0x12, 0x02, 0x21, 0x18, 0x00, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x14, 0x00, 0x62, 0x10, 0xFF, 0x00, 0x22, 0x32, 0x21, 0x10, 0xF4, 0x02,
-0x00, 0x00, 0x51, 0xA0, 0x01, 0x00, 0x94, 0x26, 0x01, 0x00, 0x73, 0x26,
-0x0D, 0x00, 0x62, 0x2A, 0xDB, 0xFF, 0x40, 0x14, 0x60, 0x1B, 0xA2, 0x26,
-0x21, 0x10, 0x80, 0x02, 0x30, 0x00, 0xBF, 0x8F, 0x2C, 0x00, 0xB7, 0x8F,
-0x28, 0x00, 0xB6, 0x8F, 0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27,
-0xF0, 0x52, 0x00, 0x08, 0x80, 0x00, 0x51, 0x34, 0xD0, 0xFF, 0xBD, 0x27,
-0x24, 0x00, 0xB1, 0xAF, 0x20, 0x00, 0xB0, 0xAF, 0x21, 0x88, 0x80, 0x00,
-0x21, 0x80, 0xA0, 0x00, 0x0D, 0x00, 0x06, 0x24, 0x21, 0x28, 0x00, 0x00,
-0x28, 0x00, 0xBF, 0xAF, 0xE3, 0x54, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0xC1, 0x52, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x00, 0x00, 0x02, 0xAE,
-0x21, 0x20, 0x20, 0x02, 0x10, 0x00, 0xA5, 0x27, 0xF4, 0x54, 0x00, 0x0C,
-0x21, 0x30, 0x40, 0x00, 0x28, 0x00, 0xBF, 0x8F, 0x24, 0x00, 0xB1, 0x8F,
-0x20, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0x21, 0x28, 0x00, 0x00, 0x21, 0x10, 0x85, 0x00, 0x00, 0x00, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x60, 0x10, 0x0D, 0x00, 0xA2, 0x2C,
-0xFA, 0xFF, 0x40, 0x14, 0x01, 0x00, 0xA5, 0x24, 0xFF, 0xFF, 0xA5, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00, 0x00, 0x00, 0x82, 0x94,
-0x21, 0x30, 0x80, 0x00, 0x10, 0x00, 0x85, 0x24, 0x42, 0x1A, 0x02, 0x00,
-0xC2, 0x11, 0x02, 0x00, 0x02, 0x00, 0x42, 0x30, 0x01, 0x00, 0x63, 0x30,
-0x25, 0x18, 0x43, 0x00, 0x01, 0x00, 0x04, 0x24, 0x07, 0x00, 0x64, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x60, 0x10, 0x0A, 0x00, 0xC5, 0x24,
-0x02, 0x00, 0x02, 0x24, 0x02, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x00, 0xC5, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xA0, 0x00,
-0x00, 0x00, 0x82, 0x94, 0x21, 0x30, 0x80, 0x00, 0x04, 0x00, 0x85, 0x24,
-0x42, 0x1A, 0x02, 0x00, 0xC2, 0x11, 0x02, 0x00, 0x02, 0x00, 0x42, 0x30,
-0x01, 0x00, 0x63, 0x30, 0x25, 0x18, 0x43, 0x00, 0x01, 0x00, 0x04, 0x24,
-0x04, 0x00, 0x64, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x60, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xC5, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0xA0, 0x00, 0x13, 0x00, 0xA0, 0x18, 0x21, 0x30, 0x00, 0x00,
-0x02, 0x00, 0x07, 0x24, 0x04, 0x00, 0x08, 0x24, 0x0B, 0x00, 0x09, 0x24,
-0x16, 0x00, 0x0A, 0x24, 0x21, 0x10, 0x86, 0x00, 0x00, 0x00, 0x43, 0x90,
-0x01, 0x00, 0xC6, 0x24, 0x7F, 0x00, 0x63, 0x30, 0x07, 0x00, 0x67, 0x10,
-0x2A, 0x10, 0xC5, 0x00, 0x05, 0x00, 0x68, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x03, 0x00, 0x69, 0x10, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x6A, 0x14,
-0x00, 0x00, 0x00, 0x00, 0xF3, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF,
-0x14, 0x00, 0xBF, 0xAF, 0x02, 0x80, 0x02, 0x3C, 0x5C, 0x5C, 0x43, 0x8C,
-0x08, 0x00, 0x10, 0x24, 0x06, 0x00, 0xA0, 0x14, 0x0A, 0x80, 0x03, 0x00,
-0x21, 0x10, 0x00, 0x02, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x49, 0x53, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x36, 0x01, 0x00, 0x42, 0x38,
-0x03, 0x00, 0x04, 0x36, 0x21, 0x80, 0x60, 0x00, 0x0B, 0x80, 0x82, 0x00,
-0x21, 0x10, 0x00, 0x02, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27,
-0x14, 0x00, 0xB1, 0xAF, 0x0E, 0x00, 0xA3, 0x2C, 0x21, 0x88, 0xA0, 0x00,
-0x0D, 0x00, 0x02, 0x24, 0x0A, 0x88, 0x43, 0x00, 0x1C, 0x00, 0xB3, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x24, 0x00, 0xBF, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x21, 0x98, 0x80, 0x00, 0x21, 0x90, 0x00, 0x00,
-0x15, 0x00, 0x20, 0x12, 0x21, 0x80, 0x00, 0x00, 0x8E, 0x53, 0x00, 0x08,
-0x01, 0x00, 0x14, 0x24, 0x2B, 0x10, 0x11, 0x02, 0x11, 0x00, 0x40, 0x10,
-0x21, 0x10, 0x40, 0x02, 0x21, 0x18, 0x70, 0x02, 0x00, 0x00, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x44, 0x30, 0x00, 0x16, 0x02, 0x00,
-0x03, 0x16, 0x02, 0x00, 0xF6, 0xFF, 0x41, 0x04, 0x01, 0x00, 0x10, 0x26,
-0x61, 0x52, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x54, 0x00,
-0x25, 0x90, 0x42, 0x02, 0x2B, 0x10, 0x11, 0x02, 0xF3, 0xFF, 0x40, 0x14,
-0x21, 0x18, 0x70, 0x02, 0x21, 0x10, 0x40, 0x02, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF,
-0x0E, 0x00, 0xA3, 0x2C, 0x21, 0x88, 0xA0, 0x00, 0x0D, 0x00, 0x02, 0x24,
-0x0A, 0x88, 0x43, 0x00, 0x20, 0x00, 0xB4, 0xAF, 0x18, 0x00, 0xB2, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x24, 0x00, 0xBF, 0xAF, 0x1C, 0x00, 0xB3, 0xAF,
-0x21, 0xA0, 0x80, 0x00, 0x21, 0x90, 0x00, 0x00, 0x0A, 0x00, 0x20, 0x12,
-0x21, 0x80, 0x00, 0x00, 0x01, 0x00, 0x13, 0x24, 0x21, 0x10, 0x90, 0x02,
-0x00, 0x00, 0x44, 0x90, 0x61, 0x52, 0x00, 0x0C, 0x01, 0x00, 0x10, 0x26,
-0x04, 0x10, 0x53, 0x00, 0x2B, 0x18, 0x11, 0x02, 0xF9, 0xFF, 0x60, 0x14,
-0x25, 0x90, 0x42, 0x02, 0x21, 0x10, 0x40, 0x02, 0x24, 0x00, 0xBF, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xE8, 0xFF, 0xBD, 0x27, 0xFF, 0xFF, 0x02, 0x24,
-0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF, 0x21, 0x30, 0xA0, 0x00,
-0x1B, 0x00, 0x82, 0x10, 0x20, 0x00, 0x10, 0x24, 0x20, 0x00, 0x82, 0x28,
-0x06, 0x00, 0x40, 0x14, 0x40, 0x18, 0x04, 0x00, 0x21, 0x10, 0x00, 0x02,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x21, 0x18, 0x64, 0x00, 0x21, 0x80, 0x80, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x04, 0x3C, 0x00, 0x19, 0x03, 0x00,
-0x60, 0x1B, 0x42, 0x24, 0x47, 0x39, 0x84, 0x24, 0x21, 0x20, 0x64, 0x00,
-0x21, 0x18, 0x62, 0x00, 0x01, 0x00, 0x02, 0x24, 0x06, 0x00, 0x06, 0x24,
-0xF4, 0x54, 0x00, 0x0C, 0xE6, 0x1D, 0x62, 0xA0, 0x21, 0x10, 0x00, 0x02,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0xF0, 0x00, 0x47, 0x24, 0x05, 0x00, 0x10, 0x24, 0xD6, 0x1E, 0x43, 0x24,
-0xF4, 0x53, 0x00, 0x08, 0xF0, 0x00, 0x05, 0x24, 0x01, 0x00, 0x10, 0x26,
-0x20, 0x00, 0x02, 0x2E, 0x30, 0x00, 0xA5, 0x24, 0xDE, 0xFF, 0x40, 0x10,
-0x30, 0x00, 0xE7, 0x24, 0x00, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xF8, 0xFF, 0x40, 0x14, 0x30, 0x00, 0x63, 0x24, 0x02, 0x80, 0x04, 0x3C,
-0x47, 0x39, 0x84, 0x24, 0x01, 0x00, 0x02, 0x24, 0x21, 0x20, 0xA4, 0x00,
-0xE6, 0x1D, 0xE2, 0xA0, 0x21, 0x28, 0xC0, 0x00, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0xE4, 0x53, 0x00, 0x08, 0x21, 0x10, 0x00, 0x02,
-0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x30, 0x00, 0xB2, 0x8F, 0x21, 0x88, 0x80, 0x00, 0x21, 0x20, 0xA0, 0x00,
-0x21, 0x28, 0x20, 0x02, 0x10, 0x00, 0xB0, 0xAF, 0x1C, 0x00, 0xBF, 0xAF,
-0xC7, 0x53, 0x00, 0x0C, 0xFF, 0xFF, 0xF0, 0x30, 0x20, 0x00, 0x03, 0x24,
-0xFF, 0x00, 0x44, 0x30, 0x21, 0x28, 0x00, 0x02, 0x21, 0x30, 0x20, 0x02,
-0x07, 0x00, 0x43, 0x10, 0x21, 0x38, 0x40, 0x02, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x6F, 0x20, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xD0, 0xFF, 0xBD, 0x27,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x24, 0x00, 0xB5, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0x21, 0xA8, 0x80, 0x00,
-0x60, 0x1B, 0x54, 0x24, 0x47, 0x39, 0x73, 0x24, 0x05, 0x00, 0x11, 0x24,
-0x01, 0x00, 0x12, 0x24, 0xF0, 0x00, 0x10, 0x24, 0x34, 0x54, 0x00, 0x08,
-0x28, 0x00, 0xBF, 0xAF, 0x01, 0x00, 0x31, 0x26, 0x20, 0x00, 0x22, 0x2A,
-0x0E, 0x00, 0x40, 0x10, 0x21, 0x10, 0x20, 0x02, 0x21, 0x10, 0x14, 0x02,
-0xE6, 0x1D, 0x43, 0x90, 0x21, 0x20, 0x13, 0x02, 0x21, 0x28, 0xA0, 0x02,
-0x06, 0x00, 0x06, 0x24, 0xF6, 0xFF, 0x72, 0x14, 0x30, 0x00, 0x10, 0x26,
-0x1D, 0x55, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xFF, 0x40, 0x14,
-0x01, 0x00, 0x31, 0x26, 0xFF, 0xFF, 0x31, 0x26, 0x21, 0x10, 0x20, 0x02,
-0x28, 0x00, 0xBF, 0x8F, 0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x30, 0x00, 0xBD, 0x27,
-0xD0, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x28, 0x00, 0xB6, 0xAF, 0x24, 0x00, 0xB5, 0xAF, 0x20, 0x00, 0xB4, 0xAF,
-0x1C, 0x00, 0xB3, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x21, 0x98, 0x80, 0x00, 0x60, 0x1B, 0x56, 0x24, 0x47, 0x39, 0x75, 0x24,
-0x21, 0x88, 0x00, 0x00, 0x01, 0x00, 0x14, 0x24, 0x21, 0x80, 0x00, 0x00,
-0x2C, 0x00, 0xBF, 0xAF, 0x60, 0x54, 0x00, 0x08, 0x18, 0x00, 0xB2, 0xAF,
-0x01, 0x00, 0x31, 0x26, 0x20, 0x00, 0x22, 0x2A, 0x1E, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x90, 0x16, 0x02, 0xE6, 0x1D, 0x42, 0x92,
-0x21, 0x20, 0x15, 0x02, 0x21, 0x28, 0x60, 0x02, 0x06, 0x00, 0x06, 0x24,
-0xF6, 0xFF, 0x54, 0x14, 0x30, 0x00, 0x10, 0x26, 0x1D, 0x55, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xF3, 0xFF, 0x40, 0x14, 0x01, 0x00, 0x31, 0x26,
-0xFF, 0xFF, 0x31, 0x26, 0x02, 0x80, 0x06, 0x3C, 0x02, 0x80, 0x07, 0x3C,
-0xFF, 0x00, 0x24, 0x32, 0xE6, 0x1D, 0x40, 0xA2, 0x2C, 0x00, 0xBF, 0x8F,
-0x28, 0x00, 0xB6, 0x8F, 0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F,
-0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x88, 0xDE, 0xC6, 0x24, 0x78, 0xDE, 0xE7, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x6F, 0x20, 0x00, 0x08, 0x30, 0x00, 0xBD, 0x27,
-0x2C, 0x00, 0xBF, 0x8F, 0x28, 0x00, 0xB6, 0x8F, 0x24, 0x00, 0xB5, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x30, 0x00, 0xBD, 0x27, 0xC8, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x18, 0x00, 0xB2, 0xAF, 0x60, 0x1B, 0x52, 0x24, 0x30, 0x00, 0xBE, 0xAF,
-0x2C, 0x00, 0xB7, 0xAF, 0x28, 0x00, 0xB6, 0xAF, 0x24, 0x00, 0xB5, 0xAF,
-0x20, 0x00, 0xB4, 0xAF, 0x1C, 0x00, 0xB3, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x34, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x00, 0x00,
-0x02, 0x80, 0x1E, 0x3C, 0x02, 0x80, 0x17, 0x3C, 0x02, 0x80, 0x16, 0x3C,
-0x01, 0x00, 0x13, 0x24, 0xFF, 0xF7, 0x15, 0x24, 0xFF, 0xEF, 0x14, 0x24,
-0x21, 0x88, 0x40, 0x02, 0xE6, 0x1D, 0x22, 0x92, 0xC0, 0x48, 0x10, 0x00,
-0xD2, 0x5C, 0xC7, 0x93, 0x41, 0x00, 0x53, 0x10, 0x21, 0x30, 0x32, 0x01,
-0xD4, 0x23, 0xC2, 0x8C, 0xBF, 0xFF, 0x03, 0x24, 0x24, 0x28, 0x43, 0x00,
-0x80, 0x07, 0xA3, 0x34, 0x24, 0x10, 0x75, 0x00, 0x31, 0x00, 0xF3, 0x10,
-0x24, 0x10, 0x54, 0x00, 0xD4, 0x23, 0xC2, 0xAC, 0x21, 0x48, 0x32, 0x01,
-0xD4, 0x23, 0x23, 0x8D, 0xFD, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x24, 0x18, 0x62, 0x00, 0xFB, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x24, 0x18, 0x62, 0x00, 0xE7, 0xFF, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0x24, 0x18, 0x62, 0x00, 0xFF, 0xFD, 0x02, 0x3C, 0xFF, 0xFF, 0x42, 0x34,
-0xD8, 0x23, 0x28, 0x8D, 0x24, 0x18, 0x62, 0x00, 0xFF, 0xFB, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x18, 0x62, 0x00, 0xFF, 0xE7, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x1F, 0x00, 0x06, 0x3C, 0x00, 0x80, 0x08, 0x35,
-0x24, 0x18, 0x62, 0x00, 0x25, 0x40, 0x06, 0x01, 0xFF, 0x00, 0x04, 0x32,
-0x21, 0x28, 0x00, 0x00, 0x01, 0x00, 0x10, 0x26, 0x88, 0xDE, 0xE6, 0x26,
-0x78, 0xDE, 0xC7, 0x26, 0xD8, 0x23, 0x28, 0xAD, 0x6F, 0x20, 0x00, 0x0C,
-0xD4, 0x23, 0x23, 0xAD, 0x20, 0x00, 0x02, 0x2A, 0xD1, 0xFF, 0x40, 0x14,
-0x30, 0x00, 0x31, 0x26, 0x34, 0x00, 0xBF, 0x8F, 0x30, 0x00, 0xBE, 0x8F,
-0x2C, 0x00, 0xB7, 0x8F, 0x28, 0x00, 0xB6, 0x8F, 0x24, 0x00, 0xB5, 0x8F,
-0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x38, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0xD3, 0x5C, 0x44, 0x90,
-0x24, 0x18, 0x75, 0x00, 0x80, 0x0F, 0xA2, 0x34, 0x00, 0x10, 0x63, 0x34,
-0xCA, 0xFF, 0x87, 0x14, 0x24, 0x10, 0x54, 0x00, 0xA9, 0x54, 0x00, 0x08,
-0xD4, 0x23, 0xC3, 0xAC, 0xA1, 0x54, 0x00, 0x08, 0xE6, 0x1D, 0x20, 0xA2,
-0xE8, 0x54, 0x00, 0x08, 0xFF, 0x00, 0xA5, 0x30, 0x00, 0x00, 0x85, 0xA0,
-0xFF, 0xFF, 0xC6, 0x24, 0x01, 0x00, 0x84, 0x24, 0xFC, 0xFF, 0xC0, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x05, 0x00, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0xAC,
-0xFF, 0xFF, 0xC6, 0x24, 0xFD, 0xFF, 0xC0, 0x14, 0x04, 0x00, 0x84, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x21, 0x38, 0x80, 0x00,
-0x08, 0x00, 0xC0, 0x10, 0xFF, 0xFF, 0xC3, 0x24, 0xFF, 0xFF, 0x06, 0x24,
-0x00, 0x00, 0xA2, 0x90, 0xFF, 0xFF, 0x63, 0x24, 0x01, 0x00, 0xA5, 0x24,
-0x00, 0x00, 0xE2, 0xA0, 0xFB, 0xFF, 0x66, 0x14, 0x01, 0x00, 0xE7, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x80, 0x00, 0x2B, 0x10, 0xA4, 0x00,
-0x0D, 0x00, 0x40, 0x14, 0xFF, 0xFF, 0x02, 0x24, 0xFF, 0xFF, 0xC6, 0x24,
-0x08, 0x00, 0xC2, 0x10, 0x21, 0x18, 0x80, 0x00, 0xFF, 0xFF, 0x07, 0x24,
-0x00, 0x00, 0xA2, 0x90, 0xFF, 0xFF, 0xC6, 0x24, 0x01, 0x00, 0xA5, 0x24,
-0x00, 0x00, 0x62, 0xA0, 0xFB, 0xFF, 0xC7, 0x14, 0x01, 0x00, 0x63, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x80, 0x00, 0x21, 0x28, 0xA6, 0x00,
-0x21, 0x18, 0x86, 0x00, 0xFF, 0xFF, 0xC6, 0x24, 0xFA, 0xFF, 0xC2, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x07, 0x24, 0xFF, 0xFF, 0xA5, 0x24,
-0x00, 0x00, 0xA2, 0x90, 0xFF, 0xFF, 0x63, 0x24, 0xFF, 0xFF, 0xC6, 0x24,
-0xFB, 0xFF, 0xC7, 0x14, 0x00, 0x00, 0x62, 0xA0, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x80, 0x00, 0x0C, 0x00, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x82, 0x90, 0x00, 0x00, 0xA3, 0x90, 0x01, 0x00, 0x84, 0x24,
-0x23, 0x10, 0x43, 0x00, 0x00, 0x16, 0x02, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x04, 0x00, 0x40, 0x14, 0x01, 0x00, 0xA5, 0x24, 0xFF, 0xFF, 0xC6, 0x24,
-0xF6, 0xFF, 0xC0, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0xC0, 0x00, 0x33, 0x55, 0x00, 0x08, 0x21, 0x18, 0x86, 0x00,
-0x00, 0x00, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x45, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x84, 0x24, 0xFA, 0xFF, 0x83, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x80, 0x00,
-0x09, 0x00, 0xC0, 0x10, 0xFF, 0xFF, 0xC3, 0x24, 0xFF, 0x00, 0xA5, 0x30,
-0xFF, 0xFF, 0x06, 0x24, 0x00, 0x00, 0x82, 0x90, 0xFF, 0xFF, 0x63, 0x24,
-0x05, 0x00, 0x45, 0x10, 0x01, 0x00, 0x84, 0x24, 0xFB, 0xFF, 0x66, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0xFF, 0xFF, 0x82, 0x24, 0x21, 0x38, 0x00, 0x00,
-0x1F, 0x00, 0xC0, 0x10, 0x21, 0x18, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x40, 0xF4, 0x4B, 0x24, 0x00, 0x00, 0x87, 0x90, 0x00, 0x00, 0xA3, 0x90,
-0xFF, 0xFF, 0xC6, 0x24, 0x01, 0x00, 0x84, 0x24, 0x21, 0x10, 0xEB, 0x00,
-0x16, 0x00, 0xE0, 0x10, 0x01, 0x00, 0xA5, 0x24, 0x14, 0x00, 0x60, 0x10,
-0x21, 0x48, 0x6B, 0x00, 0x10, 0x00, 0xE3, 0x10, 0x20, 0x00, 0xE8, 0x24,
-0x00, 0x00, 0x42, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x02, 0x00, 0x40, 0x10, 0x20, 0x00, 0x6A, 0x24, 0xFF, 0x00, 0x07, 0x31,
-0x00, 0x00, 0x22, 0x91, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x02, 0x00, 0x40, 0x10, 0xFF, 0x00, 0xE7, 0x30, 0xFF, 0x00, 0x43, 0x31,
-0xFF, 0x00, 0x63, 0x30, 0x03, 0x00, 0xE3, 0x14, 0x00, 0x00, 0x00, 0x00,
-0xE5, 0xFF, 0xC0, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x23, 0x10, 0xE3, 0x00, 0x21, 0x18, 0x80, 0x00, 0x00, 0x00, 0xA2, 0x90,
-0x01, 0x00, 0xA5, 0x24, 0x00, 0x00, 0x82, 0xA0, 0xFC, 0xFF, 0x40, 0x14,
-0x01, 0x00, 0x84, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x21, 0x38, 0x80, 0x00, 0xFF, 0xFF, 0x03, 0x24, 0xFF, 0xFF, 0xC6, 0x24,
-0x06, 0x00, 0xC3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x90,
-0x01, 0x00, 0xA5, 0x24, 0x00, 0x00, 0x82, 0xA0, 0xF9, 0xFF, 0x40, 0x14,
-0x01, 0x00, 0x84, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xE0, 0x00,
-0x00, 0x00, 0x82, 0x80, 0x82, 0x55, 0x00, 0x08, 0x21, 0x18, 0x80, 0x00,
-0x01, 0x00, 0x84, 0x24, 0x00, 0x00, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00,
-0xFC, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x90,
-0x01, 0x00, 0xA5, 0x24, 0x00, 0x00, 0x82, 0xA0, 0xFC, 0xFF, 0x40, 0x14,
-0x01, 0x00, 0x84, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x12, 0x00, 0xC0, 0x10, 0x21, 0x18, 0x80, 0x00, 0x00, 0x00, 0x82, 0x80,
-0x93, 0x55, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x84, 0x24,
-0x00, 0x00, 0x82, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2, 0x90, 0x01, 0x00, 0xA5, 0x24,
-0x00, 0x00, 0x82, 0xA0, 0x05, 0x00, 0x40, 0x10, 0x01, 0x00, 0x84, 0x24,
-0xFF, 0xFF, 0xC6, 0x24, 0xF9, 0xFF, 0xC0, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x80, 0xA0, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x00, 0x00, 0x83, 0x90, 0x00, 0x00, 0xA2, 0x90, 0x01, 0x00, 0x84, 0x24,
-0x23, 0x10, 0x62, 0x00, 0x00, 0x16, 0x02, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x03, 0x00, 0x40, 0x14, 0x01, 0x00, 0xA5, 0x24, 0xF7, 0xFF, 0x60, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0x00, 0x00, 0x0B, 0x00, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xA2, 0x90, 0x00, 0x00, 0x83, 0x90, 0xFF, 0xFF, 0xC6, 0x24,
-0x23, 0x10, 0x62, 0x00, 0x00, 0x16, 0x02, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x03, 0x00, 0x40, 0x14, 0x01, 0x00, 0xA5, 0x24, 0xF5, 0xFF, 0x60, 0x14,
-0x01, 0x00, 0x84, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x83, 0x80, 0x00, 0x2E, 0x05, 0x00, 0x21, 0x10, 0x80, 0x00,
-0xC4, 0x55, 0x00, 0x08, 0x03, 0x2E, 0x05, 0x00, 0x07, 0x00, 0x60, 0x10,
-0x01, 0x00, 0x42, 0x24, 0x00, 0x00, 0x43, 0x80, 0x00, 0x00, 0x00, 0x00,
-0xFB, 0xFF, 0x65, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0x00, 0x00, 0x82, 0x80, 0xD0, 0x55, 0x00, 0x08, 0x21, 0x18, 0x80, 0x00,
-0x01, 0x00, 0x63, 0x24, 0x00, 0x00, 0x62, 0x80, 0x00, 0x00, 0x00, 0x00,
-0xFC, 0xFF, 0x40, 0x14, 0x23, 0x10, 0x64, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF,
-0x21, 0x80, 0xA0, 0x00, 0x14, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xBF, 0xAF,
-0x21, 0x88, 0x80, 0x00, 0xCA, 0x55, 0x00, 0x0C, 0x00, 0x86, 0x10, 0x00,
-0x21, 0x18, 0x51, 0x00, 0x03, 0x86, 0x10, 0x00, 0x00, 0x00, 0x62, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x50, 0x10, 0x21, 0x10, 0x60, 0x00,
-0xFF, 0xFF, 0x63, 0x24, 0x2B, 0x10, 0x71, 0x00, 0xF9, 0xFF, 0x40, 0x10,
-0x21, 0x10, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0x21, 0x30, 0x80, 0x00,
-0x0D, 0x00, 0xA0, 0x10, 0xFF, 0xFF, 0xA3, 0x24, 0x00, 0x00, 0x82, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x05, 0x24, 0xFF, 0xFF, 0x63, 0x24, 0x05, 0x00, 0x65, 0x10,
-0x01, 0x00, 0xC6, 0x24, 0x00, 0x00, 0xC2, 0x80, 0x00, 0x00, 0x00, 0x00,
-0xFA, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x23, 0x10, 0xC4, 0x00, 0x00, 0x00, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x19, 0x00, 0x40, 0x10, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x80,
-0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x20, 0x11, 0x21, 0x30, 0xA0, 0x00,
-0x00, 0x3E, 0x02, 0x00, 0x03, 0x3E, 0x07, 0x00, 0x21, 0x18, 0x20, 0x01,
-0x15, 0x00, 0xE3, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xC6, 0x24,
-0x00, 0x00, 0xC2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x02, 0x00,
-0x03, 0x1E, 0x03, 0x00, 0xF8, 0xFF, 0x60, 0x14, 0x00, 0x16, 0x02, 0x00,
-0x03, 0x16, 0x02, 0x00, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x84, 0x24, 0x00, 0x00, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xEB, 0xFF, 0x40, 0x14, 0x01, 0x00, 0x08, 0x25, 0x08, 0x00, 0xE0, 0x03,
-0x21, 0x10, 0x00, 0x01, 0x00, 0x00, 0xA2, 0x90, 0x15, 0x56, 0x00, 0x08,
-0x00, 0x16, 0x02, 0x00, 0x00, 0x00, 0xC2, 0x90, 0x15, 0x56, 0x00, 0x08,
-0x00, 0x16, 0x02, 0x00, 0x00, 0x00, 0x87, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x00, 0xE0, 0x10, 0x21, 0x10, 0x80, 0x00, 0x00, 0x00, 0xA4, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x04, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x09, 0x00, 0x60, 0x10, 0x21, 0x30, 0xA0, 0x00, 0x00, 0x3E, 0x07, 0x00,
-0x03, 0x3E, 0x07, 0x00, 0x0B, 0x00, 0xE3, 0x10, 0x01, 0x00, 0xC6, 0x24,
-0x00, 0x00, 0xC3, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFB, 0xFF, 0x60, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24, 0x00, 0x00, 0x47, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xE0, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x18, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x1D, 0x00, 0x80, 0x10,
-0x21, 0x88, 0xA0, 0x00, 0x01, 0x56, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02,
-0x21, 0x80, 0x02, 0x02, 0x00, 0x00, 0x02, 0x82, 0x21, 0x28, 0x20, 0x02,
-0x21, 0x20, 0x00, 0x02, 0x22, 0x00, 0x40, 0x10, 0x21, 0x18, 0x00, 0x00,
-0x25, 0x56, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x10,
-0x21, 0x18, 0x40, 0x00, 0x00, 0x00, 0x42, 0x80, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x58, 0xF5, 0x43, 0xAC, 0x21, 0x18, 0x00, 0x02, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x60, 0xA0,
-0x56, 0x56, 0x00, 0x08, 0x01, 0x00, 0x63, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x58, 0xF5, 0x50, 0x8C, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xFF, 0x00, 0x12,
-0x21, 0x18, 0x00, 0x00, 0x01, 0x56, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x02,
-0x21, 0x80, 0x02, 0x02, 0x00, 0x00, 0x02, 0x82, 0x21, 0x28, 0x20, 0x02,
-0x21, 0x20, 0x00, 0x02, 0xE0, 0xFF, 0x40, 0x14, 0x21, 0x18, 0x00, 0x00,
-0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x02, 0x80, 0x02, 0x3C, 0x58, 0xF5, 0x40, 0xAC, 0x20, 0x00, 0xBD, 0x27,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x1C, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x00, 0x00, 0x90, 0x8C, 0x21, 0x90, 0x80, 0x00,
-0x21, 0x88, 0xA0, 0x00, 0x21, 0x18, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x12,
-0x21, 0x20, 0x00, 0x02, 0x01, 0x56, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x80, 0x02, 0x02, 0x00, 0x00, 0x02, 0x82, 0x21, 0x28, 0x20, 0x02,
-0x21, 0x20, 0x00, 0x02, 0x07, 0x00, 0x40, 0x10, 0x21, 0x18, 0x00, 0x00,
-0x25, 0x56, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x18, 0x40, 0x00,
-0x09, 0x00, 0x40, 0x14, 0x00, 0x00, 0x42, 0xAE, 0x21, 0x18, 0x00, 0x02,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x42, 0x80, 0x00, 0x00, 0x00, 0x00,
-0xF5, 0xFF, 0x40, 0x10, 0x01, 0x00, 0x64, 0x24, 0x00, 0x00, 0x60, 0xA0,
-0x8F, 0x56, 0x00, 0x08, 0x00, 0x00, 0x44, 0xAE, 0xD8, 0xFF, 0xBD, 0x27,
-0x14, 0x00, 0xB1, 0xAF, 0x21, 0x88, 0x80, 0x00, 0x21, 0x20, 0xA0, 0x00,
-0x1C, 0x00, 0xB3, 0xAF, 0x18, 0x00, 0xB2, 0xAF, 0x20, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0xCA, 0x55, 0x00, 0x0C, 0x21, 0x98, 0xA0, 0x00,
-0x21, 0x90, 0x40, 0x00, 0x08, 0x00, 0x40, 0x16, 0x21, 0x10, 0x20, 0x02,
-0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xCA, 0x55, 0x00, 0x0C, 0x21, 0x20, 0x20, 0x02,
-0x21, 0x80, 0x40, 0x00, 0x2A, 0x10, 0x52, 0x00, 0x0A, 0x00, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x20, 0x02, 0x21, 0x28, 0x60, 0x02,
-0x21, 0x30, 0x40, 0x02, 0x1D, 0x55, 0x00, 0x0C, 0xFF, 0xFF, 0x10, 0x26,
-0x0B, 0x00, 0x40, 0x10, 0x2A, 0x18, 0x12, 0x02, 0xF8, 0xFF, 0x60, 0x10,
-0x01, 0x00, 0x31, 0x26, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0xAB, 0x56, 0x00, 0x08, 0x21, 0x10, 0x20, 0x02, 0x00, 0x00, 0x87, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0xE0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xA6, 0x90, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0xC0, 0x10,
-0xDF, 0xFF, 0x02, 0x24, 0x24, 0x18, 0xC2, 0x00, 0x24, 0x10, 0xE2, 0x00,
-0x00, 0x16, 0x02, 0x00, 0x00, 0x1E, 0x03, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x03, 0x1E, 0x03, 0x00, 0x0A, 0x00, 0x43, 0x10, 0x00, 0x00, 0x00, 0x00,
-0xDF, 0xFF, 0x02, 0x24, 0x24, 0x18, 0xC2, 0x00, 0x24, 0x10, 0xE2, 0x00,
-0x00, 0x16, 0x02, 0x00, 0x00, 0x1E, 0x03, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x03, 0x16, 0x02, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x23, 0x10, 0x43, 0x00,
-0xEE, 0x56, 0x00, 0x08, 0xDF, 0xFF, 0x08, 0x24, 0x00, 0x00, 0xA6, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x06, 0x01, 0x00, 0x16, 0x02, 0x00,
-0xF0, 0xFF, 0xC0, 0x10, 0x03, 0x16, 0x02, 0x00, 0xEF, 0xFF, 0x62, 0x14,
-0xDF, 0xFF, 0x02, 0x24, 0x01, 0x00, 0x84, 0x24, 0x00, 0x00, 0x87, 0x90,
-0x01, 0x00, 0xA5, 0x24, 0x24, 0x10, 0x07, 0x01, 0x00, 0x1E, 0x02, 0x00,
-0xF2, 0xFF, 0xE0, 0x14, 0x03, 0x1E, 0x03, 0x00, 0x00, 0x00, 0xA6, 0x90,
-0xDF, 0xFF, 0x02, 0x24, 0x24, 0x18, 0xC2, 0x00, 0x24, 0x10, 0xE2, 0x00,
-0x00, 0x16, 0x02, 0x00, 0x00, 0x1E, 0x03, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x03, 0x16, 0x02, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x23, 0x10, 0x43, 0x00,
-0xA8, 0xFF, 0xBD, 0x27, 0x44, 0x00, 0xB5, 0xAF, 0x40, 0x00, 0xB4, 0xAF,
-0x38, 0x00, 0xB2, 0xAF, 0x34, 0x00, 0xB1, 0xAF, 0x54, 0x00, 0xBF, 0xAF,
-0x50, 0x00, 0xBE, 0xAF, 0x4C, 0x00, 0xB7, 0xAF, 0x48, 0x00, 0xB6, 0xAF,
-0x3C, 0x00, 0xB3, 0xAF, 0x30, 0x00, 0xB0, 0xAF, 0x21, 0x90, 0xA0, 0x00,
-0x00, 0x00, 0xA5, 0x90, 0x21, 0xA0, 0x80, 0x00, 0x21, 0xA8, 0xC0, 0x00,
-0x00, 0x26, 0x05, 0x00, 0x03, 0x26, 0x04, 0x00, 0x11, 0x00, 0x80, 0x10,
-0x21, 0x88, 0x80, 0x02, 0x25, 0x00, 0x02, 0x24, 0x29, 0x00, 0x82, 0x10,
-0x0A, 0x00, 0x02, 0x24, 0x1B, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x1E, 0x00, 0x80, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xA2,
-0x01, 0x00, 0x31, 0x26, 0x01, 0x00, 0x52, 0x26, 0x00, 0x00, 0x45, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x05, 0x00, 0x03, 0x26, 0x04, 0x00,
-0xF2, 0xFF, 0x80, 0x14, 0x25, 0x00, 0x02, 0x24, 0x02, 0x00, 0x80, 0x12,
-0x23, 0x10, 0x34, 0x02, 0x00, 0x00, 0x20, 0xA2, 0x54, 0x00, 0xBF, 0x8F,
-0x50, 0x00, 0xBE, 0x8F, 0x4C, 0x00, 0xB7, 0x8F, 0x48, 0x00, 0xB6, 0x8F,
-0x44, 0x00, 0xB5, 0x8F, 0x40, 0x00, 0xB4, 0x8F, 0x3C, 0x00, 0xB3, 0x8F,
-0x38, 0x00, 0xB2, 0x8F, 0x34, 0x00, 0xB1, 0x8F, 0x30, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x58, 0x00, 0xBD, 0x27, 0xE7, 0xFF, 0x80, 0x16,
-0x00, 0x00, 0x00, 0x00, 0x57, 0x58, 0x00, 0x0C, 0x0D, 0x00, 0x04, 0x24,
-0x0A, 0x00, 0x04, 0x24, 0x57, 0x58, 0x00, 0x0C, 0x01, 0x00, 0x52, 0x26,
-0x00, 0x00, 0x45, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x05, 0x00,
-0x20, 0x57, 0x00, 0x08, 0x03, 0x26, 0x04, 0x00, 0x01, 0x00, 0x52, 0x26,
-0x00, 0x00, 0x45, 0x92, 0x73, 0x00, 0x02, 0x24, 0x00, 0x1E, 0x05, 0x00,
-0x03, 0x1E, 0x03, 0x00, 0x2C, 0x00, 0x62, 0x10, 0x10, 0x00, 0xB3, 0x27,
-0x23, 0x00, 0x02, 0x24, 0x21, 0xF0, 0x60, 0x02, 0x21, 0x38, 0x00, 0x00,
-0x34, 0x00, 0x62, 0x10, 0x1C, 0x00, 0x04, 0x24, 0x00, 0x16, 0x05, 0x00,
-0x03, 0x16, 0x02, 0x00, 0x68, 0x00, 0x03, 0x24, 0x36, 0x00, 0x43, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x05, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x39, 0x00, 0x43, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0xA2, 0x34,
-0x00, 0x16, 0x02, 0x00, 0x03, 0x16, 0x02, 0x00, 0x78, 0x00, 0x03, 0x24,
-0x3C, 0x00, 0x43, 0x10, 0x20, 0x00, 0xA6, 0x30, 0x00, 0x1E, 0x05, 0x00,
-0x03, 0x1E, 0x03, 0x00, 0x64, 0x00, 0x02, 0x24, 0x49, 0x00, 0x62, 0x10,
-0x40, 0x00, 0x02, 0x24, 0x81, 0x00, 0x62, 0x10, 0x21, 0x00, 0x02, 0x24,
-0x92, 0x00, 0x62, 0x10, 0x63, 0x00, 0x02, 0x24, 0xA2, 0x00, 0x62, 0x10,
-0x11, 0x00, 0xB3, 0x27, 0x10, 0x00, 0xA5, 0xA3, 0x21, 0x80, 0xC0, 0x03,
-0x2B, 0x10, 0x13, 0x02, 0xB4, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x6C, 0x00, 0x80, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x92,
-0x01, 0x00, 0x10, 0x26, 0x00, 0x00, 0x22, 0xA2, 0x65, 0x57, 0x00, 0x08,
-0x01, 0x00, 0x31, 0x26, 0x00, 0x00, 0xA2, 0x8E, 0x04, 0x00, 0xB5, 0x26,
-0x21, 0x80, 0x40, 0x00, 0x00, 0x00, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xA6, 0xFF, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x80, 0x12,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xA2, 0x01, 0x00, 0x10, 0x26,
-0x72, 0x57, 0x00, 0x08, 0x01, 0x00, 0x31, 0x26, 0x01, 0x00, 0x52, 0x26,
-0x00, 0x00, 0x45, 0x92, 0x68, 0x00, 0x03, 0x24, 0x00, 0x16, 0x05, 0x00,
-0x03, 0x16, 0x02, 0x00, 0xCC, 0xFF, 0x43, 0x14, 0x01, 0x00, 0x07, 0x24,
-0x01, 0x00, 0x52, 0x26, 0x00, 0x00, 0x45, 0x92, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x16, 0x05, 0x00, 0x03, 0x16, 0x02, 0x00, 0xC9, 0xFF, 0x43, 0x14,
-0x0C, 0x00, 0x04, 0x24, 0x01, 0x00, 0x52, 0x26, 0x00, 0x00, 0x45, 0x92,
-0x78, 0x00, 0x03, 0x24, 0x20, 0x00, 0xA2, 0x34, 0x00, 0x16, 0x02, 0x00,
-0x03, 0x16, 0x02, 0x00, 0xC7, 0xFF, 0x43, 0x14, 0x04, 0x00, 0x04, 0x24,
-0x20, 0x00, 0xA6, 0x30, 0x00, 0x00, 0xA5, 0x8E, 0x35, 0x00, 0xE0, 0x14,
-0x04, 0x00, 0xB5, 0x26, 0xCD, 0xFF, 0x80, 0x04, 0x02, 0x80, 0x02, 0x3C,
-0x0C, 0xEF, 0x42, 0x24, 0x00, 0x00, 0x47, 0x8C, 0x07, 0x10, 0x85, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0x21, 0x10, 0x47, 0x00, 0x00, 0x00, 0x43, 0x90,
-0xFC, 0xFF, 0x84, 0x24, 0x25, 0x18, 0xC3, 0x00, 0x00, 0x00, 0x63, 0xA2,
-0xF8, 0xFF, 0x81, 0x04, 0x01, 0x00, 0x73, 0x26, 0x65, 0x57, 0x00, 0x08,
-0x21, 0x80, 0xC0, 0x03, 0x00, 0x00, 0xA2, 0x8E, 0x04, 0x00, 0xB5, 0x26,
-0x28, 0x00, 0x40, 0x04, 0x21, 0x28, 0x40, 0x00, 0x21, 0x80, 0x60, 0x02,
-0x02, 0x80, 0x02, 0x3C, 0x10, 0xEF, 0x42, 0x24, 0x00, 0x00, 0x46, 0x8C,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xA6, 0x00, 0xC3, 0x27, 0x05, 0x00,
-0x10, 0x10, 0x00, 0x00, 0x83, 0x10, 0x02, 0x00, 0x23, 0x10, 0x44, 0x00,
-0x80, 0x18, 0x02, 0x00, 0x21, 0x18, 0x62, 0x00, 0x40, 0x18, 0x03, 0x00,
-0x23, 0x18, 0xA3, 0x00, 0x30, 0x00, 0x63, 0x24, 0x00, 0x00, 0x63, 0xA2,
-0x21, 0x28, 0x40, 0x00, 0xF3, 0xFF, 0x40, 0x14, 0x01, 0x00, 0x73, 0x26,
-0xC5, 0x57, 0x00, 0x08, 0xFF, 0xFF, 0x63, 0x26, 0x00, 0x00, 0x65, 0x80,
-0x00, 0x00, 0x02, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0xA0,
-0x00, 0x00, 0x05, 0xA2, 0xFF, 0xFF, 0x63, 0x24, 0x01, 0x00, 0x10, 0x26,
-0x2B, 0x10, 0x03, 0x02, 0xF7, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x65, 0x57, 0x00, 0x08, 0x21, 0x80, 0xC0, 0x03, 0x58, 0x00, 0xC3, 0x34,
-0x30, 0x00, 0x02, 0x24, 0x12, 0x00, 0xB3, 0x27, 0x10, 0x00, 0xA2, 0xA3,
-0x96, 0x57, 0x00, 0x08, 0x11, 0x00, 0xA3, 0xA3, 0x2D, 0x00, 0x02, 0x24,
-0x23, 0x28, 0x05, 0x00, 0x11, 0x00, 0xB3, 0x27, 0xA9, 0x57, 0x00, 0x08,
-0x10, 0x00, 0xA2, 0xA3, 0x00, 0x00, 0x04, 0x82, 0x57, 0x58, 0x00, 0x0C,
-0x01, 0x00, 0x10, 0x26, 0x66, 0x57, 0x00, 0x08, 0x2B, 0x10, 0x13, 0x02,
-0x00, 0x00, 0x04, 0x82, 0x57, 0x58, 0x00, 0x0C, 0x01, 0x00, 0x10, 0x26,
-0x72, 0x57, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x8E,
-0x28, 0x00, 0xB0, 0x27, 0x2C, 0x00, 0xA4, 0x27, 0x2B, 0x10, 0x04, 0x02,
-0x28, 0x00, 0xA3, 0xAF, 0x0B, 0x00, 0x40, 0x10, 0x04, 0x00, 0xB5, 0x26,
-0x21, 0xB8, 0x80, 0x00, 0x02, 0x80, 0x16, 0x3C, 0x00, 0x00, 0x06, 0x92,
-0x21, 0x20, 0x60, 0x02, 0x01, 0x00, 0x10, 0x26, 0x08, 0x58, 0x00, 0x0C,
-0x00, 0xEF, 0xC5, 0x26, 0x2B, 0x18, 0x17, 0x02, 0xF9, 0xFF, 0x60, 0x14,
-0x21, 0x98, 0x62, 0x02, 0x64, 0x57, 0x00, 0x08, 0xFF, 0xFF, 0x73, 0x26,
-0x00, 0x00, 0xA2, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x56, 0x24,
-0x21, 0x80, 0x40, 0x00, 0x2B, 0x10, 0x56, 0x00, 0xF8, 0xFF, 0x40, 0x10,
-0x04, 0x00, 0xB5, 0x26, 0x02, 0x80, 0x17, 0x3C, 0x00, 0x00, 0x06, 0x82,
-0x21, 0x20, 0x60, 0x02, 0x01, 0x00, 0x10, 0x26, 0x08, 0x58, 0x00, 0x0C,
-0x04, 0xEF, 0xE5, 0x26, 0x2B, 0x18, 0x16, 0x02, 0xF9, 0xFF, 0x60, 0x14,
-0x21, 0x98, 0x62, 0x02, 0x64, 0x57, 0x00, 0x08, 0xFF, 0xFF, 0x73, 0x26,
-0x00, 0x00, 0xA2, 0x8E, 0x04, 0x00, 0xB5, 0x26, 0x64, 0x57, 0x00, 0x08,
-0x10, 0x00, 0xA2, 0xA3, 0xE8, 0xFF, 0xBD, 0x27, 0x20, 0x00, 0xA6, 0xAF,
-0x20, 0x00, 0xA6, 0x27, 0x10, 0x00, 0xBF, 0xAF, 0x24, 0x00, 0xA7, 0xAF,
-0xFF, 0x56, 0x00, 0x0C, 0x1C, 0x00, 0xA5, 0xAF, 0x10, 0x00, 0xBF, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x20, 0x00, 0xA4, 0xAF, 0x10, 0x00, 0xA4, 0x27,
-0x1C, 0x00, 0xBF, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x24, 0x00, 0xA5, 0xAF,
-0x28, 0x00, 0xA6, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0x2C, 0x00, 0xA7, 0xAF,
-0x53, 0x21, 0x00, 0x0C, 0xA0, 0x00, 0x04, 0x24, 0x1F, 0x00, 0x40, 0x10,
-0x21, 0x80, 0x40, 0x00, 0x08, 0x00, 0x44, 0x94, 0x20, 0x00, 0xA5, 0x8F,
-0x02, 0x80, 0x02, 0x3C, 0x25, 0x20, 0x82, 0x00, 0x20, 0x00, 0x84, 0x24,
-0xFF, 0x56, 0x00, 0x0C, 0x24, 0x00, 0xA6, 0x27, 0x01, 0x00, 0x42, 0x24,
-0x13, 0x00, 0x03, 0x24, 0x81, 0x00, 0x44, 0x2C, 0x14, 0x00, 0x03, 0xAE,
-0x0A, 0x00, 0x80, 0x14, 0x0C, 0x00, 0x02, 0xAE, 0x9B, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x88, 0x88, 0x63, 0x34, 0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x34, 0x58, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x17, 0x0A, 0x00, 0x0C,
-0x21, 0x20, 0x00, 0x02, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x99, 0x99, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C, 0x99, 0x99, 0x63, 0x34,
-0x18, 0x03, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC, 0x3A, 0x58, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x02, 0x80, 0x06, 0x3C, 0x5C, 0xF5, 0xC5, 0x8C, 0x02, 0x80, 0x02, 0x3C,
-0x40, 0xF5, 0x42, 0x24, 0x03, 0x00, 0xA3, 0x30, 0x21, 0x18, 0x62, 0x00,
-0x00, 0x00, 0x64, 0x80, 0x01, 0x00, 0xA5, 0x24, 0x57, 0x58, 0x00, 0x0C,
-0x5C, 0xF5, 0xC5, 0xAC, 0x10, 0x00, 0xBF, 0x8F, 0x08, 0x00, 0x04, 0x24,
-0x57, 0x58, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27, 0x00, 0x26, 0x04, 0x00,
-0x03, 0x26, 0x04, 0x00, 0x00, 0x00, 0x84, 0x48, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x04, 0x00, 0x03, 0x26, 0x04, 0x00,
-0xF7, 0xFF, 0x82, 0x24, 0x05, 0x00, 0x42, 0x2C, 0x06, 0x00, 0x40, 0x14,
-0x21, 0x18, 0x00, 0x00, 0x20, 0x00, 0x02, 0x24, 0x03, 0x00, 0x82, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x01, 0x00, 0x03, 0x24, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x60, 0x00,
-0x00, 0x00, 0x82, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x26, 0x10, 0x44, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x42, 0x2C, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x1C, 0x00, 0xBF, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x10, 0x00, 0xA4, 0x27,
-0x02, 0x80, 0x02, 0x3C, 0xCC, 0x5D, 0x50, 0xAC, 0x90, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0x25, 0xB0, 0x05, 0x3C,
-0x01, 0x00, 0x06, 0x24, 0x01, 0x80, 0x02, 0x3C, 0x04, 0x30, 0x86, 0x00,
-0xF1, 0x02, 0xA7, 0x34, 0xED, 0x02, 0xA4, 0x34, 0xF8, 0x61, 0x42, 0x24,
-0x18, 0x03, 0xA5, 0x34, 0x08, 0x00, 0x03, 0x24, 0x00, 0x00, 0xA2, 0xAC,
-0x00, 0x00, 0xE3, 0xA0, 0x00, 0x00, 0x80, 0xA0, 0x00, 0x00, 0x86, 0xA0,
-0x00, 0x00, 0x80, 0xA0, 0x00, 0x00, 0x86, 0xA0, 0x00, 0x00, 0x80, 0xA0,
-0x00, 0x00, 0x86, 0xA0, 0x00, 0x00, 0x80, 0xA0, 0x00, 0x00, 0x86, 0xA0,
-0x00, 0x00, 0x80, 0xA0, 0x00, 0x00, 0xE0, 0xA0, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF,
-0xFF, 0xFF, 0x90, 0x30, 0x1C, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C,
-0x10, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x63, 0x24,
-0x6A, 0x37, 0x62, 0x94, 0x10, 0x00, 0xA4, 0x27, 0x25, 0x80, 0x02, 0x02,
-0x25, 0xB0, 0x02, 0x3C, 0x1E, 0x03, 0x42, 0x34, 0x00, 0x00, 0x50, 0xA4,
-0x90, 0x40, 0x00, 0x0C, 0x6A, 0x37, 0x70, 0xA4, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF, 0xFF, 0xFF, 0x90, 0x30,
-0x1C, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x02, 0x80, 0x05, 0x3C, 0x60, 0x1B, 0xA5, 0x24, 0x6A, 0x37, 0xA2, 0x94,
-0x78, 0x37, 0xA3, 0x94, 0x27, 0x80, 0x10, 0x00, 0x10, 0x00, 0xA4, 0x27,
-0x24, 0x18, 0x03, 0x02, 0x24, 0x80, 0x02, 0x02, 0x25, 0xB0, 0x02, 0x3C,
-0x1E, 0x03, 0x42, 0x34, 0x78, 0x37, 0xA3, 0xA4, 0x00, 0x00, 0x50, 0xA4,
-0x90, 0x40, 0x00, 0x0C, 0x6A, 0x37, 0xB0, 0xA4, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xC8, 0xFF, 0xBD, 0x27, 0x25, 0xB0, 0x03, 0x3C, 0x1C, 0x00, 0xB3, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x34, 0x00, 0xBF, 0xAF, 0x30, 0x00, 0xBE, 0xAF, 0x2C, 0x00, 0xB7, 0xAF,
-0x28, 0x00, 0xB6, 0xAF, 0x24, 0x00, 0xB5, 0xAF, 0x20, 0x00, 0xB4, 0xAF,
-0x0A, 0x00, 0x67, 0x34, 0x00, 0x00, 0xE2, 0x90, 0xFF, 0xFF, 0xB2, 0x30,
-0x21, 0x98, 0xC0, 0x00, 0xFF, 0x00, 0x91, 0x30, 0x20, 0x00, 0x40, 0x12,
-0xFF, 0x00, 0x50, 0x30, 0x21, 0xA0, 0xE0, 0x00, 0x0C, 0x00, 0x77, 0x34,
-0x0B, 0x00, 0x76, 0x34, 0x21, 0xF0, 0xE0, 0x00, 0xC0, 0xFF, 0x15, 0x24,
-0x25, 0x10, 0x15, 0x02, 0xFF, 0x00, 0x50, 0x30, 0x00, 0x00, 0xD1, 0xA2,
-0x00, 0x00, 0x90, 0xA2, 0x00, 0x00, 0x82, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x50, 0x30, 0xC0, 0x00, 0x03, 0x32, 0x07, 0x00, 0x60, 0x10,
-0x21, 0x20, 0xC0, 0x03, 0x00, 0x00, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0x50, 0x30, 0xC0, 0x00, 0x03, 0x32, 0xFB, 0xFF, 0x60, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x8E, 0x04, 0x00, 0x23, 0x26,
-0x64, 0x00, 0x04, 0x24, 0x00, 0x00, 0x62, 0xAE, 0x2C, 0x1F, 0x00, 0x0C,
-0xFF, 0x00, 0x71, 0x30, 0xFC, 0xFF, 0x42, 0x26, 0xFF, 0xFF, 0x52, 0x30,
-0xE7, 0xFF, 0x40, 0x16, 0x04, 0x00, 0x73, 0x26, 0x34, 0x00, 0xBF, 0x8F,
-0x30, 0x00, 0xBE, 0x8F, 0x2C, 0x00, 0xB7, 0x8F, 0x28, 0x00, 0xB6, 0x8F,
-0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x38, 0x00, 0xBD, 0x27, 0x25, 0xB0, 0x06, 0x3C,
-0x31, 0x00, 0xC2, 0x34, 0xFF, 0xFF, 0x84, 0x30, 0x00, 0x00, 0x44, 0xA0,
-0x32, 0x00, 0xC7, 0x34, 0x00, 0x00, 0xE3, 0x90, 0xFC, 0xFF, 0x02, 0x24,
-0x02, 0x22, 0x04, 0x00, 0x24, 0x18, 0x62, 0x00, 0x03, 0x00, 0x84, 0x30,
-0x25, 0x20, 0x83, 0x00, 0x33, 0x00, 0xC6, 0x34, 0x72, 0x00, 0x02, 0x24,
-0x00, 0x00, 0xE4, 0xA0, 0x00, 0x00, 0xC2, 0xA0, 0x00, 0x00, 0xC3, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x03, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x05, 0x00, 0x61, 0x04, 0x21, 0x10, 0x00, 0x00, 0x23, 0x59, 0x00, 0x08,
-0x25, 0xB0, 0x02, 0x3C, 0x11, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xC3, 0x90, 0x01, 0x00, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x00, 0x1E, 0x03, 0x00, 0x03, 0x1E, 0x03, 0x00, 0xF8, 0xFF, 0x61, 0x04,
-0x64, 0x00, 0x44, 0x2C, 0x64, 0x00, 0x44, 0x2C, 0x07, 0x00, 0x80, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0x30, 0x00, 0x42, 0x34,
-0x00, 0x00, 0x43, 0x90, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0xA3, 0xA0, 0xFF, 0xFF, 0x02, 0x24, 0x00, 0x00, 0xA2, 0xA0,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x25, 0xB0, 0x06, 0x3C,
-0x31, 0x00, 0xC2, 0x34, 0xFF, 0xFF, 0x84, 0x30, 0x00, 0x00, 0x44, 0xA0,
-0x32, 0x00, 0xC3, 0x34, 0x00, 0x00, 0x62, 0x90, 0x02, 0x22, 0x04, 0x00,
-0x03, 0x00, 0x84, 0x30, 0x25, 0x20, 0x82, 0x00, 0x00, 0x00, 0x64, 0xA0,
-0x33, 0x00, 0xC7, 0x34, 0xFF, 0x00, 0xA5, 0x30, 0x30, 0x00, 0xC6, 0x34,
-0xF2, 0xFF, 0x03, 0x24, 0x00, 0x00, 0xC5, 0xA0, 0x00, 0x00, 0xE3, 0xA0,
-0x00, 0x00, 0xE2, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x02, 0x00,
-0x03, 0x16, 0x02, 0x00, 0x03, 0x00, 0x40, 0x04, 0x21, 0x20, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x01, 0x00, 0x02, 0x24, 0x48, 0x59, 0x00, 0x08,
-0x21, 0x30, 0xE0, 0x00, 0x0B, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xC3, 0x90, 0x01, 0x00, 0x82, 0x24, 0xFF, 0x00, 0x44, 0x30,
-0x00, 0x1E, 0x03, 0x00, 0x03, 0x1E, 0x03, 0x00, 0xF8, 0xFF, 0x60, 0x04,
-0x64, 0x00, 0x82, 0x2C, 0x64, 0x00, 0x82, 0x2C, 0xF1, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x25, 0xB0, 0x02, 0x3C, 0x18, 0x00, 0xB0, 0xAF,
-0xF8, 0x02, 0x45, 0x34, 0x25, 0xB0, 0x10, 0x3C, 0xFF, 0x00, 0x83, 0x30,
-0x01, 0x00, 0x02, 0x24, 0x1C, 0x00, 0xBF, 0xAF, 0x03, 0x00, 0x06, 0x36,
-0x0A, 0x00, 0x62, 0x10, 0x0A, 0x00, 0x04, 0x24, 0x00, 0x00, 0xA2, 0x90,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0xFE, 0xFF, 0x03, 0x24,
-0x24, 0x10, 0x43, 0x00, 0x20, 0x00, 0xBD, 0x27, 0x00, 0x00, 0xA2, 0xA0,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x42, 0x30, 0x20, 0x00, 0x43, 0x34,
-0x20, 0x00, 0x42, 0x30, 0x02, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xC3, 0xA0, 0x2C, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x04, 0x36, 0x00, 0x00, 0x82, 0x90, 0xFE, 0xFF, 0x03, 0x24,
-0xF8, 0x02, 0x06, 0x36, 0x24, 0x10, 0x43, 0x00, 0x00, 0x00, 0x82, 0xA0,
-0x00, 0x00, 0xC3, 0x90, 0x10, 0x00, 0xA5, 0x27, 0x21, 0x20, 0x00, 0x00,
-0x03, 0x00, 0x63, 0x34, 0x00, 0x00, 0xC3, 0xA0, 0xFF, 0x58, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xFF, 0x00, 0x84, 0x30,
-0x21, 0x38, 0x00, 0x00, 0x21, 0x28, 0x00, 0x00, 0x01, 0x00, 0xA3, 0x24,
-0x07, 0x10, 0xA4, 0x00, 0x01, 0x00, 0x42, 0x30, 0xFF, 0x00, 0x65, 0x30,
-0x01, 0x00, 0xE6, 0x24, 0x02, 0x00, 0x40, 0x14, 0x04, 0x00, 0xA3, 0x2C,
-0xFF, 0x00, 0xC7, 0x30, 0xF7, 0xFF, 0x60, 0x14, 0x21, 0x10, 0xE0, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x8C, 0x30,
-0x21, 0x48, 0x00, 0x00, 0x21, 0x38, 0x00, 0x00, 0x40, 0x10, 0x07, 0x00,
-0xFF, 0x00, 0x42, 0x30, 0x21, 0x50, 0x46, 0x00, 0x01, 0x00, 0xE3, 0x24,
-0x07, 0x10, 0xEC, 0x00, 0x01, 0x00, 0x42, 0x30, 0xFF, 0x00, 0x67, 0x30,
-0x21, 0x58, 0x25, 0x01, 0x01, 0x00, 0x24, 0x25, 0x09, 0x00, 0x40, 0x14,
-0x04, 0x00, 0xE8, 0x2C, 0x00, 0x00, 0x63, 0x91, 0xFF, 0x00, 0x89, 0x30,
-0x21, 0x20, 0x25, 0x01, 0x00, 0x00, 0x43, 0xA1, 0x00, 0x00, 0x83, 0x90,
-0x01, 0x00, 0x22, 0x25, 0xFF, 0x00, 0x49, 0x30, 0x01, 0x00, 0x43, 0xA1,
-0xED, 0xFF, 0x00, 0x15, 0x40, 0x10, 0x07, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xBD, 0x27, 0x20, 0x00, 0xB2, 0xAF,
-0x1C, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xB0, 0xAF, 0x24, 0x00, 0xBF, 0xAF,
-0x01, 0x00, 0x12, 0x24, 0x21, 0x80, 0x00, 0x00, 0xC5, 0x59, 0x00, 0x08,
-0xFF, 0x00, 0x11, 0x24, 0xFF, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x00, 0x40, 0x10, 0x00, 0x02, 0x03, 0x2E, 0x0F, 0x00, 0x60, 0x10,
-0x21, 0x10, 0x00, 0x02, 0x10, 0x00, 0xA2, 0x93, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x00, 0x51, 0x10, 0x0F, 0x00, 0x44, 0x30, 0x83, 0x59, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x02, 0x00, 0x21, 0x10, 0x50, 0x00,
-0x01, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x50, 0x30, 0x21, 0x20, 0x00, 0x02,
-0xEE, 0xFF, 0x40, 0x16, 0x10, 0x00, 0xA5, 0x27, 0x21, 0x10, 0x00, 0x02,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0xB8, 0xFF, 0xBD, 0x27, 0x3C, 0x00, 0xB7, 0xAF, 0x38, 0x00, 0xB6, 0xAF,
-0x34, 0x00, 0xB5, 0xAF, 0x30, 0x00, 0xB4, 0xAF, 0x2C, 0x00, 0xB3, 0xAF,
-0x24, 0x00, 0xB1, 0xAF, 0x20, 0x00, 0xB0, 0xAF, 0x44, 0x00, 0xBF, 0xAF,
-0x40, 0x00, 0xBE, 0xAF, 0x28, 0x00, 0xB2, 0xAF, 0x21, 0x98, 0xA0, 0x00,
-0xFF, 0x00, 0x96, 0x30, 0x01, 0x00, 0x10, 0x24, 0x01, 0x00, 0x17, 0x24,
-0x21, 0xA0, 0x00, 0x00, 0x21, 0x88, 0x00, 0x00, 0x21, 0xA8, 0x00, 0x00,
-0x04, 0x00, 0xA0, 0x10, 0x21, 0x18, 0x00, 0x00, 0x10, 0x00, 0xC2, 0x2E,
-0x0E, 0x00, 0x40, 0x14, 0x21, 0x20, 0xA0, 0x00, 0x44, 0x00, 0xBF, 0x8F,
-0x40, 0x00, 0xBE, 0x8F, 0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F,
-0x34, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F,
-0x28, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F,
-0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27,
-0x08, 0x00, 0x06, 0x24, 0xE3, 0x54, 0x00, 0x0C, 0xFF, 0x00, 0x05, 0x24,
-0x18, 0x00, 0xA4, 0x27, 0xFF, 0x00, 0x05, 0x24, 0xE3, 0x54, 0x00, 0x0C,
-0x08, 0x00, 0x06, 0x24, 0x54, 0x59, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x04, 0x5A, 0x00, 0x08, 0x10, 0x00, 0xBE, 0x27, 0x1C, 0x00, 0x40, 0x14,
-0x21, 0x20, 0xA0, 0x02, 0x37, 0x00, 0xE0, 0x12, 0x00, 0x02, 0x22, 0x2E,
-0x35, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x32,
-0xF8, 0xFF, 0x40, 0x10, 0x20, 0x00, 0x02, 0x32, 0x21, 0x20, 0x20, 0x02,
-0xFF, 0x58, 0x00, 0x0C, 0x10, 0x00, 0xA5, 0x27, 0x2D, 0x00, 0x40, 0x10,
-0xFF, 0x00, 0x02, 0x24, 0x10, 0x00, 0xB0, 0x93, 0x00, 0x00, 0x00, 0x00,
-0x29, 0x00, 0x02, 0x12, 0x0F, 0x00, 0x15, 0x32, 0x83, 0x59, 0x00, 0x0C,
-0x21, 0x20, 0xA0, 0x02, 0x02, 0x81, 0x10, 0x00, 0x10, 0x00, 0x16, 0x12,
-0x21, 0xA0, 0x40, 0x00, 0x40, 0x10, 0x14, 0x00, 0x21, 0x10, 0x51, 0x00,
-0x01, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x51, 0x30, 0x00, 0x5A, 0x00, 0x08,
-0x01, 0x00, 0x10, 0x24, 0x18, 0x00, 0xA5, 0x27, 0x92, 0x59, 0x00, 0x0C,
-0x21, 0x30, 0x60, 0x02, 0x40, 0x10, 0x14, 0x00, 0x21, 0x10, 0x51, 0x00,
-0x01, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x51, 0x30, 0x00, 0x5A, 0x00, 0x08,
-0x01, 0x00, 0x10, 0x24, 0x40, 0x90, 0x02, 0x00, 0x10, 0x00, 0x40, 0x1A,
-0x21, 0x80, 0x00, 0x00, 0x21, 0x20, 0x30, 0x02, 0x01, 0x00, 0x84, 0x24,
-0xFF, 0xFF, 0x84, 0x30, 0xFF, 0x58, 0x00, 0x0C, 0x10, 0x00, 0xA5, 0x27,
-0x01, 0x00, 0x03, 0x26, 0x21, 0x20, 0xD0, 0x03, 0xFF, 0x00, 0x70, 0x30,
-0x04, 0x00, 0x40, 0x10, 0x2A, 0x18, 0x12, 0x02, 0x10, 0x00, 0xA2, 0x93,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x82, 0xA0, 0xF3, 0xFF, 0x60, 0x14,
-0x21, 0x20, 0x30, 0x02, 0x00, 0x5A, 0x00, 0x08, 0x20, 0x00, 0x10, 0x24,
-0x54, 0x59, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x63, 0x92,
-0xFF, 0x00, 0x02, 0x24, 0x0F, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x03, 0x24, 0x44, 0x00, 0xBF, 0x8F, 0x40, 0x00, 0xBE, 0x8F,
-0x3C, 0x00, 0xB7, 0x8F, 0x38, 0x00, 0xB6, 0x8F, 0x34, 0x00, 0xB5, 0x8F,
-0x30, 0x00, 0xB4, 0x8F, 0x2C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB2, 0x8F,
-0x24, 0x00, 0xB1, 0x8F, 0x20, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x48, 0x00, 0xBD, 0x27, 0x01, 0x00, 0x62, 0x92,
-0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x43, 0x14, 0x01, 0x00, 0x03, 0x24,
-0x02, 0x00, 0x63, 0x92, 0x00, 0x00, 0x00, 0x00, 0xEB, 0xFF, 0x62, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x62, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xE8, 0xFF, 0x43, 0x14, 0x01, 0x00, 0x03, 0x24, 0x04, 0x00, 0x63, 0x92,
-0x00, 0x00, 0x00, 0x00, 0xE3, 0xFF, 0x62, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x05, 0x00, 0x62, 0x92, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xFF, 0x43, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x67, 0x92, 0x00, 0x00, 0x00, 0x00,
-0xDC, 0xFF, 0xE2, 0x14, 0x01, 0x00, 0x03, 0x24, 0x07, 0x00, 0x62, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x47, 0x10, 0x21, 0x18, 0x00, 0x00,
-0x3F, 0x5A, 0x00, 0x08, 0x01, 0x00, 0x03, 0x24, 0xC0, 0xFF, 0xBD, 0x27,
-0x38, 0x00, 0xBE, 0xAF, 0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF,
-0x21, 0xF0, 0xC0, 0x00, 0xFF, 0x00, 0xB6, 0x30, 0xFF, 0xFF, 0x95, 0x30,
-0xFF, 0x00, 0x05, 0x24, 0x10, 0x00, 0xA4, 0x27, 0x08, 0x00, 0x06, 0x24,
-0x34, 0x00, 0xB7, 0xAF, 0x24, 0x00, 0xB3, 0xAF, 0x3C, 0x00, 0xBF, 0xAF,
-0x28, 0x00, 0xB4, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0xE3, 0x54, 0x00, 0x0C, 0x0F, 0x00, 0x17, 0x24,
-0x21, 0x98, 0x00, 0x00, 0x40, 0x10, 0x13, 0x00, 0xFF, 0x00, 0x52, 0x30,
-0x07, 0x10, 0x76, 0x02, 0x01, 0x00, 0x42, 0x30, 0x21, 0xA0, 0x5E, 0x02,
-0x21, 0x88, 0xA0, 0x02, 0x21, 0x20, 0xA0, 0x02, 0x13, 0x00, 0x40, 0x10,
-0x01, 0x00, 0xA3, 0x26, 0x01, 0x00, 0x62, 0x26, 0xFF, 0x00, 0x53, 0x30,
-0x04, 0x00, 0x63, 0x2E, 0xF4, 0xFF, 0x60, 0x14, 0x40, 0x10, 0x13, 0x00,
-0x21, 0x10, 0xE0, 0x02, 0x3C, 0x00, 0xBF, 0x8F, 0x38, 0x00, 0xBE, 0x8F,
-0x34, 0x00, 0xB7, 0x8F, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x40, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x85, 0x92, 0xFF, 0xFF, 0x75, 0x30,
-0x2C, 0x59, 0x00, 0x0C, 0x21, 0x80, 0xA0, 0x02, 0x01, 0x00, 0x85, 0x92,
-0x21, 0x20, 0xA0, 0x02, 0x01, 0x00, 0xA2, 0x26, 0x2C, 0x59, 0x00, 0x0C,
-0xFF, 0xFF, 0x55, 0x30, 0x10, 0x00, 0xA3, 0x27, 0x21, 0x90, 0x72, 0x00,
-0x21, 0x20, 0x20, 0x02, 0xFF, 0x58, 0x00, 0x0C, 0x21, 0x28, 0x40, 0x02,
-0x21, 0x20, 0x00, 0x02, 0xFF, 0x58, 0x00, 0x0C, 0x01, 0x00, 0x45, 0x26,
-0x00, 0x00, 0x84, 0x92, 0x00, 0x00, 0x42, 0x92, 0x01, 0x00, 0x03, 0x24,
-0x04, 0x18, 0x63, 0x02, 0x03, 0x00, 0x82, 0x10, 0x27, 0x30, 0x03, 0x00,
-0x87, 0x5A, 0x00, 0x08, 0x24, 0xB8, 0xD7, 0x00, 0x01, 0x00, 0x83, 0x92,
-0x01, 0x00, 0x42, 0x92, 0x00, 0x00, 0x00, 0x00, 0xD2, 0xFF, 0x62, 0x10,
-0x01, 0x00, 0x62, 0x26, 0x88, 0x5A, 0x00, 0x08, 0x24, 0xB8, 0xD7, 0x00,
-0x98, 0xFF, 0xBD, 0x27, 0x50, 0x00, 0xB4, 0xAF, 0xFF, 0x00, 0x94, 0x30,
-0x01, 0x00, 0x04, 0x24, 0x64, 0x00, 0xBF, 0xAF, 0x60, 0x00, 0xBE, 0xAF,
-0x5C, 0x00, 0xB7, 0xAF, 0x58, 0x00, 0xB6, 0xAF, 0x4C, 0x00, 0xB3, 0xAF,
-0x48, 0x00, 0xB2, 0xAF, 0x44, 0x00, 0xB1, 0xAF, 0x21, 0x98, 0xC0, 0x00,
-0xFF, 0x00, 0xB1, 0x30, 0x54, 0x00, 0xB5, 0xAF, 0x54, 0x59, 0x00, 0x0C,
-0x40, 0x00, 0xB0, 0xAF, 0xAC, 0x59, 0x00, 0x0C, 0x01, 0x00, 0x16, 0x24,
-0x21, 0x18, 0x40, 0x00, 0xFF, 0x01, 0x42, 0x2C, 0x01, 0x00, 0x17, 0x24,
-0x01, 0x00, 0x1E, 0x24, 0x21, 0x90, 0x00, 0x00, 0x0E, 0x00, 0x40, 0x14,
-0x21, 0x20, 0x00, 0x00, 0x64, 0x00, 0xBF, 0x8F, 0x60, 0x00, 0xBE, 0x8F,
-0x5C, 0x00, 0xB7, 0x8F, 0x58, 0x00, 0xB6, 0x8F, 0x54, 0x00, 0xB5, 0x8F,
-0x50, 0x00, 0xB4, 0x8F, 0x4C, 0x00, 0xB3, 0x8F, 0x48, 0x00, 0xB2, 0x8F,
-0x44, 0x00, 0xB1, 0x8F, 0x40, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x80, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x68, 0x00, 0xBD, 0x27, 0xFF, 0x01, 0x02, 0x24,
-0x23, 0x10, 0x43, 0x00, 0x1A, 0x00, 0xA4, 0x27, 0xFF, 0x00, 0x05, 0x24,
-0x08, 0x00, 0x06, 0x24, 0xFF, 0xFF, 0x50, 0x30, 0x18, 0x00, 0xB4, 0xA3,
-0xE3, 0x54, 0x00, 0x0C, 0x19, 0x00, 0xB1, 0xA3, 0x21, 0x20, 0x20, 0x02,
-0x21, 0x28, 0x60, 0x02, 0x92, 0x59, 0x00, 0x0C, 0x1A, 0x00, 0xA6, 0x27,
-0x19, 0x00, 0xA4, 0x93, 0x83, 0x59, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x21, 0xA8, 0x40, 0x00, 0xFF, 0xFF, 0x42, 0x30, 0x2B, 0x10, 0x02, 0x02,
-0xDF, 0xFF, 0x40, 0x14, 0x21, 0x20, 0x00, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x09, 0x00, 0xC2, 0x12, 0x20, 0x00, 0x02, 0x24, 0x22, 0x00, 0xC2, 0x12,
-0x00, 0x00, 0x00, 0x00, 0x3B, 0x00, 0xE0, 0x12, 0x00, 0x02, 0x42, 0x2E,
-0x39, 0x00, 0x40, 0x10, 0x01, 0x00, 0x02, 0x24, 0xF9, 0xFF, 0xC2, 0x16,
-0x20, 0x00, 0x02, 0x24, 0x21, 0x20, 0x40, 0x02, 0x10, 0x00, 0xA5, 0x27,
-0xFF, 0x58, 0x00, 0x0C, 0x01, 0x00, 0x13, 0x24, 0x41, 0x00, 0x40, 0x10,
-0xFF, 0x00, 0x02, 0x24, 0x10, 0x00, 0xA5, 0x93, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0xA4, 0x30, 0x3C, 0x00, 0x82, 0x10, 0x0F, 0x00, 0xA3, 0x30,
-0x02, 0x11, 0x04, 0x00, 0x21, 0x20, 0x60, 0x00, 0x29, 0x00, 0xA3, 0xA3,
-0x28, 0x00, 0xA2, 0xA3, 0x83, 0x59, 0x00, 0x0C, 0x11, 0x00, 0xA5, 0xA3,
-0x21, 0x80, 0x40, 0x00, 0x28, 0x00, 0xA3, 0x93, 0x18, 0x00, 0xA2, 0x93,
-0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x62, 0x10, 0x40, 0x10, 0x10, 0x00,
-0x21, 0x10, 0x52, 0x00, 0x01, 0x00, 0x42, 0x24, 0xF9, 0x5A, 0x00, 0x08,
-0xFF, 0xFF, 0x52, 0x30, 0x19, 0x00, 0xA5, 0x93, 0x01, 0x00, 0x44, 0x26,
-0xFF, 0xFF, 0x84, 0x30, 0x6A, 0x5A, 0x00, 0x0C, 0x1A, 0x00, 0xA6, 0x27,
-0x21, 0x28, 0x40, 0x00, 0x0F, 0x00, 0x43, 0x30, 0x0F, 0x00, 0x02, 0x24,
-0x12, 0x00, 0x62, 0x10, 0x40, 0x10, 0x15, 0x00, 0x21, 0x10, 0x52, 0x00,
-0x01, 0x00, 0x42, 0x24, 0x21, 0x20, 0xA0, 0x00, 0xFF, 0xFF, 0x52, 0x30,
-0x18, 0x00, 0xB4, 0xA3, 0x83, 0x59, 0x00, 0x0C, 0x19, 0x00, 0xA5, 0xA3,
-0x21, 0xA8, 0x40, 0x00, 0x02, 0x80, 0x03, 0x3C, 0xCC, 0xDF, 0x62, 0x8C,
-0x02, 0x80, 0x04, 0x3C, 0x01, 0x00, 0x16, 0x24, 0x01, 0x00, 0x42, 0x24,
-0x04, 0x00, 0x43, 0x28, 0xC6, 0xFF, 0x60, 0x14, 0xCC, 0xDF, 0x82, 0xAC,
-0x21, 0xF0, 0x00, 0x00, 0x54, 0x59, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00,
-0x21, 0x20, 0xC0, 0x03, 0x64, 0x00, 0xBF, 0x8F, 0x60, 0x00, 0xBE, 0x8F,
-0x5C, 0x00, 0xB7, 0x8F, 0x58, 0x00, 0xB6, 0x8F, 0x54, 0x00, 0xB5, 0x8F,
-0x50, 0x00, 0xB4, 0x8F, 0x4C, 0x00, 0xB3, 0x8F, 0x48, 0x00, 0xB2, 0x8F,
-0x44, 0x00, 0xB1, 0x8F, 0x40, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x80, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x68, 0x00, 0xBD, 0x27, 0xAC, 0x59, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x03, 0x24, 0x23, 0x18, 0x62, 0x00,
-0xFF, 0xFF, 0x70, 0x30, 0xFF, 0xFF, 0xA2, 0x32, 0x2B, 0x10, 0x02, 0x02,
-0xE7, 0xFF, 0x40, 0x14, 0x21, 0x20, 0x40, 0x02, 0x18, 0x00, 0xB0, 0x93,
-0x19, 0x00, 0xA2, 0x93, 0x00, 0x81, 0x10, 0x00, 0x25, 0x80, 0x02, 0x02,
-0xFF, 0x00, 0x10, 0x32, 0x2C, 0x59, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x02,
-0x21, 0x20, 0x40, 0x02, 0xFF, 0x58, 0x00, 0x0C, 0x11, 0x00, 0xA5, 0x27,
-0x11, 0x00, 0xA3, 0x93, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x64, 0x30,
-0x9D, 0xFF, 0x90, 0x10, 0x20, 0x00, 0x16, 0x24, 0xFF, 0x00, 0x02, 0x24,
-0xCD, 0xFF, 0x82, 0x10, 0x0F, 0x00, 0x63, 0x30, 0x02, 0x11, 0x04, 0x00,
-0x21, 0x20, 0x60, 0x00, 0x29, 0x00, 0xA3, 0xA3, 0x83, 0x59, 0x00, 0x0C,
-0x28, 0x00, 0xA2, 0xA3, 0x38, 0x00, 0xA4, 0x27, 0xFF, 0x00, 0x05, 0x24,
-0x08, 0x00, 0x06, 0x24, 0xE3, 0x54, 0x00, 0x0C, 0x21, 0x80, 0x40, 0x00,
-0x28, 0x00, 0xA4, 0x93, 0xCF, 0x59, 0x00, 0x0C, 0x38, 0x00, 0xA5, 0x27,
-0x1F, 0x00, 0x40, 0x14, 0x01, 0x00, 0x44, 0x26, 0x40, 0x10, 0x10, 0x00,
-0x21, 0x10, 0x52, 0x00, 0x01, 0x00, 0x42, 0x24, 0x2C, 0x5B, 0x00, 0x08,
-0xFF, 0xFF, 0x52, 0x30, 0x40, 0x88, 0x10, 0x00, 0x27, 0x00, 0x20, 0x1A,
-0x21, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x16, 0x24, 0x21, 0x20, 0x50, 0x02,
-0x01, 0x00, 0x84, 0x24, 0xFF, 0xFF, 0x84, 0x30, 0xFF, 0x58, 0x00, 0x0C,
-0x10, 0x00, 0xA5, 0x27, 0x01, 0x00, 0x03, 0x26, 0xFF, 0x00, 0x70, 0x30,
-0x05, 0x00, 0x40, 0x10, 0x2A, 0x18, 0x11, 0x02, 0x10, 0x00, 0xA2, 0x93,
-0x00, 0x00, 0x00, 0x00, 0x26, 0x10, 0x56, 0x00, 0x0B, 0x98, 0x02, 0x00,
-0xF3, 0xFF, 0x60, 0x14, 0x21, 0x20, 0x50, 0x02, 0x15, 0x00, 0x60, 0x16,
-0x21, 0x10, 0x32, 0x02, 0x01, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x52, 0x30,
-0xF9, 0x5A, 0x00, 0x08, 0x01, 0x00, 0x16, 0x24, 0x29, 0x00, 0xA5, 0x93,
-0xFF, 0xFF, 0x84, 0x30, 0x6A, 0x5A, 0x00, 0x0C, 0x38, 0x00, 0xA6, 0x27,
-0x21, 0x28, 0x40, 0x00, 0x0F, 0x00, 0x43, 0x30, 0x0F, 0x00, 0x02, 0x24,
-0xDB, 0xFF, 0x62, 0x10, 0x40, 0x10, 0x10, 0x00, 0x28, 0x00, 0xA4, 0x93,
-0xB9, 0x5A, 0x00, 0x0C, 0x38, 0x00, 0xA6, 0x27, 0xAC, 0x59, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x2C, 0x5B, 0x00, 0x08, 0x21, 0x90, 0x40, 0x00,
-0x19, 0x00, 0xA3, 0x93, 0x29, 0x00, 0xA6, 0x93, 0x0F, 0x00, 0x13, 0x24,
-0x0E, 0x00, 0x10, 0x24, 0x25, 0x18, 0x66, 0x00, 0x01, 0x00, 0x62, 0x30,
-0x0A, 0x98, 0x02, 0x02, 0x02, 0x00, 0x64, 0x30, 0xFD, 0x00, 0x62, 0x32,
-0x0A, 0x98, 0x44, 0x00, 0x04, 0x00, 0x65, 0x30, 0xFB, 0x00, 0x62, 0x32,
-0x0A, 0x98, 0x45, 0x00, 0x08, 0x00, 0x63, 0x30, 0xF7, 0x00, 0x62, 0x32,
-0x0A, 0x98, 0x43, 0x00, 0x0F, 0x00, 0x64, 0x32, 0x0F, 0x00, 0x16, 0x24,
-0x25, 0x00, 0x96, 0x10, 0x21, 0x28, 0xC0, 0x00, 0x01, 0x00, 0x44, 0x26,
-0xFF, 0xFF, 0x84, 0x30, 0x6A, 0x5A, 0x00, 0x0C, 0x1A, 0x00, 0xA6, 0x27,
-0x21, 0x28, 0x40, 0x00, 0x0F, 0x00, 0x42, 0x30, 0x03, 0x00, 0x56, 0x10,
-0x21, 0x20, 0x80, 0x02, 0xB9, 0x5A, 0x00, 0x0C, 0x38, 0x00, 0xA6, 0x27,
-0x19, 0x00, 0xA5, 0x93, 0x00, 0x00, 0x00, 0x00, 0x26, 0x10, 0x65, 0x02,
-0x01, 0x00, 0x42, 0x30, 0x0A, 0x80, 0xC2, 0x02, 0x26, 0x18, 0x65, 0x02,
-0x02, 0x00, 0x63, 0x30, 0xFD, 0x00, 0x04, 0x32, 0x0B, 0x80, 0x83, 0x00,
-0x26, 0x10, 0x65, 0x02, 0x04, 0x00, 0x42, 0x30, 0xFB, 0x00, 0x03, 0x32,
-0x0B, 0x80, 0x62, 0x00, 0x26, 0x28, 0x65, 0x02, 0x08, 0x00, 0xA5, 0x30,
-0xF7, 0x00, 0x02, 0x32, 0x0B, 0x80, 0x45, 0x00, 0x0F, 0x00, 0x03, 0x32,
-0x0D, 0x00, 0x76, 0x10, 0x00, 0x00, 0x00, 0x00, 0xAC, 0x59, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x90, 0x40, 0x00, 0x19, 0x00, 0xB0, 0xA3,
-0x2C, 0x5B, 0x00, 0x08, 0x18, 0x00, 0xB4, 0xA3, 0x21, 0x10, 0x32, 0x02,
-0x01, 0x00, 0x42, 0x24, 0xFF, 0xFF, 0x52, 0x30, 0x01, 0x00, 0x16, 0x24,
-0xF9, 0x5A, 0x00, 0x08, 0x18, 0x00, 0xB4, 0xA3, 0x2C, 0x5B, 0x00, 0x08,
-0x21, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x85, 0xAC, 0x21, 0x10, 0x00, 0x00,
-0x01, 0x00, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30, 0x06, 0x00, 0x43, 0x2C,
-0xFC, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xA5, 0x30, 0x00, 0x00, 0x85, 0xA4,
-0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x43, 0x2C, 0xFC, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xA5, 0x30,
-0x00, 0x00, 0x85, 0xA0, 0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24,
-0xFF, 0x00, 0x42, 0x30, 0x06, 0x00, 0x43, 0x2C, 0xFC, 0xFF, 0x60, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x82, 0x8C, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x82, 0x94, 0x08, 0x00, 0xE0, 0x03, 0xFF, 0xFF, 0x42, 0x30,
-0x00, 0x00, 0x82, 0x90, 0x08, 0x00, 0xE0, 0x03, 0xFF, 0x00, 0x42, 0x30,
-0x25, 0xB0, 0x02, 0x3C, 0x21, 0x20, 0x82, 0x00, 0x00, 0x00, 0x85, 0xAC,
-0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x43, 0x2C, 0xFC, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C,
-0x21, 0x20, 0x82, 0x00, 0xFF, 0xFF, 0xA5, 0x30, 0x00, 0x00, 0x85, 0xA4,
-0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x43, 0x2C, 0xFC, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C,
-0x21, 0x20, 0x82, 0x00, 0xFF, 0x00, 0xA5, 0x30, 0x00, 0x00, 0x85, 0xA0,
-0x21, 0x10, 0x00, 0x00, 0x01, 0x00, 0x42, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x06, 0x00, 0x43, 0x2C, 0xFC, 0xFF, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C,
-0x21, 0x20, 0x82, 0x00, 0x00, 0x00, 0x82, 0x8C, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0x21, 0x20, 0x82, 0x00,
-0x00, 0x00, 0x82, 0x94, 0x08, 0x00, 0xE0, 0x03, 0xFF, 0xFF, 0x42, 0x30,
-0x25, 0xB0, 0x02, 0x3C, 0x21, 0x20, 0x82, 0x00, 0x00, 0x00, 0x82, 0x90,
-0x08, 0x00, 0xE0, 0x03, 0xFF, 0x00, 0x42, 0x30, 0x01, 0x80, 0x02, 0x3C,
-0x25, 0xB0, 0x03, 0x3C, 0xD4, 0x70, 0x42, 0x24, 0x18, 0x03, 0x63, 0x34,
-0x00, 0x00, 0x62, 0xAC, 0x00, 0x00, 0x83, 0x90, 0x30, 0x00, 0x02, 0x24,
-0x05, 0x00, 0x62, 0x10, 0x21, 0x20, 0x00, 0x00, 0x31, 0x00, 0x02, 0x24,
-0x02, 0x00, 0x62, 0x10, 0x01, 0x00, 0x04, 0x24, 0x07, 0x00, 0x04, 0x24,
-0x7E, 0x58, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x02, 0x3C,
-0x25, 0xB0, 0x03, 0x3C, 0x10, 0x71, 0x42, 0x24, 0x18, 0x03, 0x63, 0x34,
-0x02, 0x80, 0x04, 0x3C, 0x00, 0x00, 0x62, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0xFC, 0x5C, 0x80, 0xAC, 0x42, 0xB0, 0x02, 0x3C, 0x03, 0x00, 0x47, 0x34,
-0x00, 0x00, 0xE3, 0x90, 0xFF, 0x00, 0x84, 0x30, 0x04, 0x00, 0x84, 0x24,
-0xFF, 0x00, 0x65, 0x30, 0x01, 0x00, 0x02, 0x24, 0x04, 0x30, 0x82, 0x00,
-0x07, 0x18, 0x85, 0x00, 0x25, 0xB0, 0x02, 0x3C, 0xE8, 0x03, 0x42, 0x34,
-0x01, 0x00, 0x63, 0x30, 0x21, 0x20, 0xC0, 0x00, 0x00, 0x00, 0x45, 0xA0,
-0x02, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE6, 0xA0,
-0x08, 0x00, 0xE0, 0x03, 0x24, 0x10, 0x85, 0x00, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x1C, 0x00, 0xBF, 0xAF,
-0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0xD0, 0xDF, 0x42, 0x24, 0x04, 0x00, 0x43, 0x8C, 0x00, 0x00, 0x02, 0xAE,
-0x04, 0x00, 0x50, 0xAC, 0x00, 0x00, 0x70, 0xAC, 0x04, 0x00, 0x03, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB0, 0xAF, 0x21, 0x80, 0x80, 0x00,
-0x1C, 0x00, 0xBF, 0xAF, 0x8A, 0x40, 0x00, 0x0C, 0x10, 0x00, 0xA4, 0x27,
-0x04, 0x00, 0x03, 0x8E, 0x00, 0x00, 0x02, 0x8E, 0x10, 0x00, 0xA4, 0x27,
-0x00, 0x00, 0x62, 0xAC, 0x04, 0x00, 0x43, 0xAC, 0x00, 0x00, 0x10, 0xAE,
-0x90, 0x40, 0x00, 0x0C, 0x04, 0x00, 0x10, 0xAE, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x1F, 0xF7, 0x00, 0x6A, 0x82, 0x34, 0x4C, 0xEC, 0x82, 0x34, 0x8C, 0x32,
-0x89, 0xE2, 0x48, 0x32, 0x89, 0xE2, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0x48, 0x32, 0x69, 0xE2, 0x04, 0xF5,
-0x68, 0x9A, 0x01, 0xF6, 0x01, 0x6C, 0x8B, 0xEC, 0x8C, 0xEB, 0x04, 0xF5,
-0x68, 0xDA, 0x20, 0xE8, 0x00, 0x65, 0x00, 0x00, 0x1F, 0xF7, 0x00, 0x6A,
-0x82, 0x34, 0x4C, 0xEC, 0x82, 0x34, 0x8C, 0x32, 0x89, 0xE2, 0x48, 0x32,
-0x89, 0xE2, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x00, 0x4B, 0x48, 0x32, 0x69, 0xE2, 0x04, 0xF5, 0x68, 0x9A, 0x01, 0xF6,
-0x01, 0x6C, 0x8B, 0xEC, 0x8C, 0xEB, 0x00, 0xF2, 0x00, 0x6C, 0x8D, 0xEB,
-0x04, 0xF5, 0x68, 0xDA, 0x20, 0xE8, 0x00, 0x65, 0xFF, 0x6B, 0x6C, 0xED,
-0x04, 0x5D, 0x6C, 0xEC, 0x69, 0x60, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0xCB, 0xF4, 0x46, 0xA2, 0xEF, 0x4A, 0x6C, 0xEA, 0x02, 0x5A,
-0x0C, 0x60, 0x02, 0x74, 0x38, 0x60, 0x03, 0x54, 0x1D, 0x61, 0x03, 0x74,
-0x2C, 0x60, 0x04, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x20, 0xE8,
-0xFF, 0x4A, 0x02, 0x74, 0x3D, 0x60, 0x03, 0x54, 0x18, 0x61, 0x03, 0x74,
-0xF4, 0x61, 0x01, 0x75, 0x43, 0x60, 0x02, 0x55, 0x31, 0x61, 0x02, 0x75,
-0x42, 0x60, 0x03, 0x75, 0xEC, 0x61, 0x02, 0xF0, 0x00, 0x6A, 0x40, 0x32,
-0x1E, 0xF0, 0x00, 0x4A, 0x20, 0xE8, 0x00, 0x65, 0x01, 0x74, 0xE3, 0x61,
-0x02, 0xF0, 0x0F, 0x6A, 0x40, 0x32, 0x20, 0xE8, 0x40, 0x32, 0x01, 0x74,
-0xDC, 0x61, 0x03, 0xF7, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32, 0x10, 0xF0,
-0x00, 0x4A, 0x20, 0xE8, 0x00, 0x65, 0x01, 0x75, 0x1B, 0x60, 0x02, 0x55,
-0x08, 0x61, 0x02, 0x75, 0x29, 0x60, 0x03, 0x75, 0xCC, 0x61, 0x02, 0xF0,
-0x10, 0x6A, 0x40, 0x32, 0xDE, 0x17, 0xC7, 0x2D, 0x02, 0xF0, 0x10, 0x6A,
-0x40, 0x32, 0x40, 0x32, 0x1E, 0xF0, 0x15, 0x4A, 0x20, 0xE8, 0x00, 0x65,
-0xBE, 0x2D, 0x02, 0xF0, 0x00, 0x6A, 0xF7, 0x17, 0x03, 0xF7, 0x10, 0x6A,
-0x40, 0x32, 0xCD, 0x17, 0x02, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0x40, 0x32,
-0x1E, 0xF0, 0x10, 0x4A, 0x20, 0xE8, 0x00, 0x65, 0x02, 0xF0, 0x00, 0x6A,
-0xF8, 0x17, 0x02, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0x1E, 0xF0, 0x05, 0x4A,
-0x20, 0xE8, 0x00, 0x65, 0x02, 0xF0, 0x10, 0x6A, 0x40, 0x32, 0xF7, 0x17,
-0xFC, 0x63, 0x06, 0xD0, 0x8C, 0x30, 0x81, 0xE0, 0x08, 0x30, 0x81, 0xE0,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A,
-0x08, 0x30, 0x41, 0xE0, 0xC9, 0xF7, 0x1B, 0x6D, 0x04, 0xF0, 0x00, 0x6A,
-0x40, 0x32, 0xAB, 0xED, 0x40, 0x32, 0xA0, 0x35, 0xA0, 0x35, 0xFF, 0x4A,
-0x04, 0xF5, 0x40, 0xD8, 0x07, 0x62, 0x80, 0xF1, 0x44, 0x45, 0x40, 0x9A,
-0x08, 0x6B, 0x6B, 0xEB, 0x04, 0xF5, 0x44, 0xD8, 0x04, 0xF5, 0x48, 0x98,
-0xC4, 0x67, 0x6C, 0xEA, 0xFF, 0x6B, 0x02, 0x4B, 0x6B, 0xEB, 0x6C, 0xEA,
-0x02, 0xF0, 0x01, 0x6B, 0x6B, 0xEB, 0x6C, 0xEA, 0x04, 0xF5, 0x48, 0xD8,
-0x04, 0xD5, 0x00, 0x18, 0xA5, 0x21, 0x05, 0xD6, 0x04, 0x95, 0x05, 0x96,
-0x04, 0xF5, 0x4A, 0xA0, 0x60, 0xF1, 0x00, 0x4D, 0xB9, 0xE6, 0x40, 0xC6,
-0x00, 0x6A, 0xC4, 0xF4, 0x58, 0xD8, 0xC4, 0xF4, 0x5C, 0xD8, 0xE4, 0xF4,
-0x40, 0xD8, 0xE4, 0xF4, 0x44, 0xD8, 0xE4, 0xF4, 0x48, 0xD8, 0xE4, 0xF4,
-0x4C, 0xD8, 0xE4, 0xF4, 0x50, 0xD8, 0xE4, 0xF4, 0x54, 0xD8, 0x07, 0x97,
-0x06, 0x90, 0x00, 0xEF, 0x04, 0x63, 0x00, 0x00, 0xFF, 0x63, 0x00, 0xD0,
-0x04, 0x67, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0xFF, 0x6F,
-0x80, 0x34, 0xA0, 0xF1, 0x4F, 0x44, 0xEC, 0xEE, 0x01, 0xD1, 0x59, 0xE6,
-0x40, 0xA6, 0xEC, 0xED, 0xC7, 0x67, 0x4C, 0xEE, 0xAC, 0x32, 0xA9, 0xE2,
-0x48, 0x32, 0xA9, 0xE2, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33,
-0x63, 0xF3, 0x00, 0x4B, 0x48, 0x32, 0x69, 0xE2, 0x04, 0xF5, 0x48, 0x9A,
-0x07, 0x6B, 0x80, 0xF1, 0x04, 0x4C, 0x6C, 0xEA, 0xEC, 0xEA, 0x48, 0x32,
-0xEC, 0xE8, 0x89, 0xE2, 0x00, 0x6D, 0x80, 0x9A, 0x0D, 0x65, 0x70, 0x67,
-0x2E, 0x26, 0x32, 0x24, 0x65, 0x67, 0x01, 0x69, 0x51, 0x67, 0x44, 0xEB,
-0x8C, 0xEA, 0x36, 0x2A, 0x01, 0x4B, 0xEC, 0xEB, 0x1D, 0x5B, 0xF8, 0x61,
-0x6F, 0x40, 0xFF, 0x6A, 0x4C, 0xEB, 0xE8, 0x67, 0xE3, 0xEB, 0x10, 0x61,
-0x01, 0x69, 0xE2, 0x67, 0x51, 0x67, 0x44, 0xEB, 0x8C, 0xEA, 0x05, 0x22,
-0xCA, 0xED, 0x26, 0x60, 0x01, 0x4D, 0xEC, 0xED, 0x03, 0x67, 0xFF, 0x4B,
-0xEC, 0xEB, 0x48, 0x67, 0x43, 0xEB, 0xF2, 0x60, 0xC3, 0xED, 0x70, 0x67,
-0x0A, 0x60, 0x68, 0x67, 0xAB, 0xE6, 0x42, 0xEB, 0x00, 0x6B, 0x05, 0x61,
-0xE8, 0x67, 0xCB, 0xE7, 0xAD, 0xE2, 0xFF, 0x6A, 0x4C, 0xEB, 0x01, 0x91,
-0x00, 0x90, 0x43, 0x67, 0x20, 0xE8, 0x01, 0x63, 0xC3, 0xE8, 0x65, 0x67,
-0xF8, 0x61, 0xCF, 0xE0, 0x01, 0x91, 0x00, 0x90, 0xEC, 0xEB, 0x43, 0x67,
-0x20, 0xE8, 0x01, 0x63, 0x0B, 0x65, 0xCC, 0x17, 0x70, 0x67, 0xED, 0x17,
-0xC9, 0xF7, 0x1B, 0x6E, 0xCB, 0xEE, 0xC0, 0x36, 0xFF, 0x6F, 0xC0, 0x36,
-0xEC, 0xEC, 0xFF, 0x63, 0x60, 0xF1, 0x40, 0x46, 0x01, 0xD1, 0x00, 0xD0,
-0x49, 0xE4, 0x40, 0xA2, 0x07, 0x67, 0xEC, 0xED, 0x4C, 0xE8, 0xA0, 0xF1,
-0x4F, 0x46, 0x55, 0xE5, 0x40, 0xA5, 0x27, 0x67, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x4C, 0xE9, 0x8C, 0x32, 0x89, 0xE2, 0x48, 0x32,
-0x89, 0xE2, 0x63, 0xF3, 0x00, 0x4B, 0x48, 0x32, 0x69, 0xE2, 0x04, 0xF5,
-0x48, 0x9A, 0x07, 0x6B, 0x80, 0xF1, 0x04, 0x4E, 0x6C, 0xEA, 0xEC, 0xEA,
-0x48, 0x32, 0xC9, 0xE2, 0x00, 0x6D, 0x80, 0x9A, 0x2D, 0x65, 0x70, 0x67,
-0x30, 0x21, 0x34, 0x24, 0x01, 0x6A, 0x65, 0x67, 0x0A, 0x65, 0xC7, 0x67,
-0x48, 0x67, 0x44, 0xEB, 0x8C, 0xEA, 0x36, 0x2A, 0x01, 0x4B, 0xCC, 0xEB,
-0x1D, 0x5B, 0xF8, 0x61, 0x6F, 0x40, 0xFF, 0x6A, 0x4C, 0xEB, 0xC9, 0x67,
-0xC3, 0xEB, 0x10, 0x61, 0x01, 0x6F, 0xC2, 0x67, 0x47, 0x67, 0x44, 0xEB,
-0x8C, 0xEA, 0x05, 0x22, 0x2A, 0xED, 0x26, 0x60, 0x01, 0x4D, 0xCC, 0xED,
-0x03, 0x67, 0xFF, 0x4B, 0xCC, 0xEB, 0x49, 0x67, 0x43, 0xEB, 0xF2, 0x60,
-0x23, 0xED, 0x70, 0x67, 0x0A, 0x60, 0x69, 0x67, 0xAB, 0xE1, 0x42, 0xEB,
-0x00, 0x6B, 0x05, 0x61, 0xC9, 0x67, 0x2B, 0xE6, 0xAD, 0xE2, 0xFF, 0x6A,
-0x4C, 0xEB, 0x01, 0x91, 0x00, 0x90, 0x43, 0x67, 0x20, 0xE8, 0x01, 0x63,
-0x23, 0xE8, 0x65, 0x67, 0xF8, 0x61, 0x2F, 0xE0, 0x01, 0x91, 0x00, 0x90,
-0xEC, 0xEB, 0x43, 0x67, 0x20, 0xE8, 0x01, 0x63, 0x2B, 0x65, 0xCC, 0x17,
-0x70, 0x67, 0xED, 0x17, 0x10, 0xF0, 0x02, 0x6E, 0x00, 0xF4, 0xC0, 0x36,
-0xFB, 0x63, 0x00, 0x6D, 0x63, 0xF3, 0x00, 0x4E, 0x07, 0xD1, 0x06, 0xD0,
-0x08, 0x62, 0x05, 0x67, 0x26, 0x67, 0x85, 0x67, 0x04, 0xD5, 0x00, 0x18,
-0xDB, 0x5C, 0x05, 0xD6, 0x04, 0xF5, 0x4A, 0xA1, 0xFF, 0x6B, 0x05, 0x96,
-0x6C, 0xEA, 0x48, 0x32, 0xC9, 0xE2, 0xC0, 0xF5, 0x74, 0x9A, 0x60, 0xF5,
-0x40, 0x9A, 0x4D, 0xE3, 0x66, 0x33, 0xC4, 0xF4, 0x74, 0xD9, 0x04, 0x95,
-0x00, 0x6B, 0x69, 0xE1, 0x01, 0x4B, 0x1D, 0x53, 0x04, 0xF5, 0x0C, 0xC2,
-0x24, 0xF5, 0x09, 0xC2, 0x44, 0xF5, 0x06, 0xC2, 0xF6, 0x61, 0x00, 0x6A,
-0x01, 0x4D, 0x64, 0xF5, 0x44, 0xD9, 0x20, 0x55, 0x7F, 0x49, 0x15, 0x49,
-0xD8, 0x61, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90, 0x00, 0xEF, 0x05, 0x63,
-0xF8, 0x63, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x07, 0xD2,
-0x0E, 0x62, 0x0D, 0xD1, 0x0C, 0xD0, 0x63, 0xF3, 0x00, 0x4A, 0x27, 0xF1,
-0x44, 0x9A, 0xFF, 0x6B, 0x6C, 0xEC, 0x6C, 0x65, 0xFF, 0xF7, 0x1F, 0x72,
-0x00, 0x6C, 0x05, 0xD4, 0x01, 0x61, 0x05, 0xD3, 0x07, 0x93, 0xFF, 0xF7,
-0x1F, 0x6A, 0x8B, 0x67, 0x63, 0xF3, 0x00, 0x4B, 0x27, 0xF1, 0x44, 0xDB,
-0x00, 0x6A, 0x04, 0xD2, 0x00, 0xF1, 0x18, 0x24, 0x10, 0xF0, 0x02, 0x6D,
-0x00, 0xF4, 0xA0, 0x35, 0x22, 0x67, 0xBC, 0xF3, 0x0C, 0x4D, 0xFF, 0x6E,
-0x00, 0xF5, 0x84, 0x43, 0x05, 0x10, 0x01, 0x49, 0x1D, 0x51, 0x60, 0xC4,
-0x01, 0x4C, 0x0B, 0x60, 0xA9, 0xE1, 0x60, 0xA2, 0x46, 0x67, 0x6C, 0xEA,
-0xF6, 0x22, 0x01, 0x49, 0x4D, 0x43, 0x1D, 0x51, 0x40, 0xC4, 0x01, 0x4C,
-0xF5, 0x61, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4,
-0x80, 0x34, 0x00, 0x69, 0x63, 0xF3, 0x00, 0x4A, 0x5C, 0xF1, 0x04, 0x4B,
-0xDC, 0xF0, 0x0C, 0x4C, 0x0A, 0x65, 0x4B, 0x65, 0x2C, 0x65, 0x11, 0x67,
-0x48, 0x67, 0x6A, 0x67, 0x00, 0x6D, 0x5D, 0xE0, 0x79, 0xE0, 0xAD, 0xE6,
-0x40, 0xA3, 0xB1, 0xE7, 0x01, 0x4D, 0xA0, 0xF3, 0x48, 0xC4, 0x80, 0xF0,
-0x51, 0xA3, 0x05, 0x55, 0x20, 0xF4, 0x59, 0xC4, 0xF4, 0x61, 0x48, 0x67,
-0x51, 0xE1, 0x49, 0x67, 0x4D, 0xE1, 0x40, 0xA3, 0x01, 0x49, 0x1D, 0x51,
-0xC0, 0xF4, 0x4A, 0xC4, 0x5D, 0xA3, 0x05, 0x48, 0xE0, 0xF4, 0x47, 0xC4,
-0xE1, 0x61, 0x6B, 0x67, 0x00, 0xF1, 0x0A, 0x23, 0x10, 0xF0, 0x02, 0x6E,
-0x00, 0xF4, 0xC0, 0x36, 0x10, 0xF0, 0x02, 0x6F, 0x00, 0xF4, 0xE0, 0x37,
-0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0x00, 0x69, 0x63, 0xF3,
-0x00, 0x4E, 0x5C, 0xF4, 0x00, 0x4F, 0xDC, 0xF3, 0x0C, 0x4D, 0x28, 0x32,
-0xED, 0xE2, 0x60, 0x9B, 0xD1, 0xE2, 0xA9, 0xE2, 0xC0, 0xF5, 0x74, 0xDC,
-0x40, 0x9A, 0x01, 0x49, 0x04, 0x51, 0x60, 0xF5, 0x40, 0xDC, 0xF3, 0x61,
-0x10, 0xF0, 0x02, 0x6F, 0x00, 0xF4, 0xE0, 0x37, 0x10, 0xF0, 0x02, 0x6E,
-0x00, 0xF4, 0xC0, 0x36, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x04, 0x69, 0x63, 0xF3, 0x00, 0x4F, 0x5C, 0xF4, 0x00, 0x4E, 0xDC, 0xF3,
-0x0C, 0x4D, 0x28, 0x33, 0xC9, 0xE3, 0x40, 0x9A, 0xF1, 0xE3, 0xAD, 0xE3,
-0x4A, 0x32, 0xC0, 0xF5, 0x54, 0xDC, 0x40, 0x9B, 0x01, 0x49, 0x1D, 0x51,
-0x4A, 0x32, 0x60, 0xF5, 0x40, 0xDC, 0xF1, 0x61, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x63, 0xF3, 0x00, 0x4C, 0x00, 0x69, 0x04, 0x67,
-0xD1, 0x67, 0xC4, 0xF4, 0x14, 0x48, 0x06, 0xD4, 0x08, 0xD1, 0x09, 0x10,
-0x08, 0x94, 0x01, 0x49, 0x7F, 0x48, 0x7F, 0x4C, 0x15, 0x4C, 0x20, 0x51,
-0x15, 0x48, 0x08, 0xD4, 0x5E, 0x60, 0x8D, 0x98, 0x01, 0x6B, 0x82, 0x32,
-0x52, 0x32, 0x6C, 0xEA, 0xFF, 0x6B, 0x6C, 0xEA, 0xEF, 0x22, 0x07, 0x6A,
-0x4C, 0xEC, 0x6C, 0xEC, 0x88, 0x32, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC,
-0x80, 0x34, 0x80, 0x34, 0x80, 0xF1, 0x04, 0x4C, 0x89, 0xE2, 0x6B, 0x98,
-0x40, 0x9A, 0x91, 0x67, 0x6C, 0xEA, 0x4C, 0xD8, 0x00, 0x18, 0xA5, 0x21,
-0x0A, 0xD6, 0x20, 0xF0, 0x96, 0xA0, 0xFF, 0x6A, 0xA2, 0x67, 0x4C, 0xEC,
-0x00, 0x18, 0x93, 0x21, 0x2C, 0xED, 0x20, 0xF0, 0x56, 0xA0, 0x04, 0x94,
-0xFF, 0x6B, 0x6C, 0xEA, 0x43, 0xEC, 0x0A, 0x96, 0x01, 0x60, 0x04, 0xD2,
-0xC1, 0xD8, 0xC2, 0xD8, 0xC3, 0xD8, 0xC4, 0xD8, 0xC5, 0xD8, 0xC6, 0xD8,
-0xC7, 0xD8, 0xC8, 0xD8, 0x06, 0x93, 0x48, 0x32, 0xA6, 0x67, 0x69, 0xE2,
-0xC0, 0xF5, 0x74, 0x9A, 0x60, 0xF5, 0x40, 0x9A, 0x4D, 0xE3, 0x66, 0x33,
-0x60, 0xD8, 0x08, 0x92, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33,
-0x63, 0xF3, 0x00, 0x4B, 0x71, 0xE2, 0x66, 0x67, 0xA9, 0xE4, 0x01, 0x4D,
-0x1D, 0x55, 0x04, 0xF5, 0x6C, 0xC2, 0x24, 0xF5, 0x69, 0xC2, 0x44, 0xF5,
-0x66, 0xC2, 0xF6, 0x61, 0x64, 0xF5, 0xC4, 0xDC, 0x08, 0x94, 0x01, 0x49,
-0x7F, 0x48, 0x7F, 0x4C, 0x15, 0x4C, 0x20, 0x51, 0x15, 0x48, 0x08, 0xD4,
-0xA2, 0x61, 0x05, 0x92, 0x06, 0x2A, 0x07, 0x93, 0x63, 0xF3, 0x00, 0x4B,
-0x07, 0xD3, 0x27, 0xF1, 0x44, 0xDB, 0x0E, 0x97, 0x0D, 0x91, 0x0C, 0x90,
-0x00, 0xEF, 0x08, 0x63, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34,
-0x22, 0x67, 0xBC, 0xF3, 0x0C, 0x4C, 0x00, 0xF5, 0x04, 0x4B, 0x89, 0xE1,
-0x40, 0xA2, 0x01, 0x49, 0x1D, 0x51, 0x40, 0xC3, 0x01, 0x4B, 0xF9, 0x61,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x00, 0x69, 0x63, 0xF3, 0x00, 0x4B, 0x7C, 0xF2, 0x08, 0x4C, 0x1C, 0xF1,
-0x08, 0x4A, 0x0B, 0x65, 0x4C, 0x65, 0x2A, 0x65, 0x11, 0x67, 0x68, 0x67,
-0x8A, 0x67, 0x00, 0x6D, 0x7D, 0xE0, 0x99, 0xE0, 0xAD, 0xE6, 0x40, 0xA3,
-0xB1, 0xE7, 0x01, 0x4D, 0xA0, 0xF3, 0x48, 0xC4, 0x80, 0xF0, 0x51, 0xA3,
-0x05, 0x55, 0x20, 0xF4, 0x59, 0xC4, 0xF4, 0x61, 0x48, 0x67, 0x51, 0xE1,
-0x49, 0x67, 0x4D, 0xE1, 0x40, 0xA3, 0x01, 0x49, 0x1D, 0x51, 0xC0, 0xF4,
-0x4A, 0xC4, 0x5D, 0xA3, 0x05, 0x48, 0xE0, 0xF4, 0x47, 0xC4, 0xE1, 0x61,
-0x10, 0xF0, 0x02, 0x6F, 0x00, 0xF4, 0xE0, 0x37, 0x10, 0xF0, 0x02, 0x6E,
-0x00, 0xF4, 0xC0, 0x36, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x2B, 0x67, 0x63, 0xF3, 0x00, 0x4F, 0x5C, 0xF4, 0x00, 0x4E, 0xDC, 0xF3,
-0x0C, 0x4D, 0x28, 0x32, 0xCD, 0xE2, 0x60, 0x9B, 0xF1, 0xE2, 0xA9, 0xE2,
-0xC0, 0xF5, 0x74, 0xDC, 0x40, 0x9A, 0x01, 0x49, 0x1D, 0x51, 0x60, 0xF5,
-0x40, 0xDC, 0xF3, 0x61, 0x17, 0x17, 0x00, 0x00, 0xFF, 0xF7, 0x1F, 0x6F,
-0x8C, 0xEF, 0xE0, 0xF1, 0x10, 0x6E, 0xEC, 0xEE, 0xFB, 0x63, 0xD2, 0x36,
-0x06, 0xD0, 0xCC, 0x30, 0xC1, 0xE0, 0x08, 0x30, 0xC1, 0xE0, 0x10, 0xF0,
-0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0x08, 0x30,
-0x41, 0xE0, 0x08, 0x62, 0x07, 0xD1, 0x25, 0x67, 0x04, 0xF5, 0xA8, 0x98,
-0x02, 0xF0, 0x00, 0x6A, 0xFF, 0x6B, 0x4D, 0xED, 0x00, 0xF2, 0x00, 0x6A,
-0xEC, 0xEA, 0x43, 0x32, 0x02, 0x4B, 0x6B, 0xEB, 0x47, 0x32, 0x6C, 0xED,
-0x40, 0x32, 0x4D, 0xED, 0x04, 0xF5, 0x20, 0xD8, 0x04, 0xF5, 0xA8, 0xD8,
-0x87, 0x67, 0x04, 0xD5, 0x00, 0x18, 0x2C, 0x22, 0x05, 0xD6, 0x04, 0x95,
-0x08, 0x6B, 0x07, 0x6C, 0x6B, 0xEB, 0x8C, 0xEA, 0xAC, 0xEB, 0x4D, 0xEB,
-0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x04, 0xF5, 0x68, 0xD8,
-0x40, 0x32, 0x8C, 0xEB, 0x80, 0xF1, 0x04, 0x4A, 0x68, 0x33, 0x4D, 0xE3,
-0x40, 0x9B, 0x2C, 0xEA, 0x04, 0xF5, 0x44, 0xD8, 0x05, 0x96, 0x00, 0x18,
-0xA5, 0x21, 0x86, 0x67, 0x05, 0x96, 0x04, 0xF5, 0x8A, 0xA0, 0x00, 0x18,
-0x93, 0x21, 0xA6, 0x67, 0x08, 0x97, 0x07, 0x91, 0x06, 0x90, 0x00, 0xEF,
-0x05, 0x63, 0x00, 0x00, 0xFF, 0x6A, 0xFD, 0x63, 0x04, 0x62, 0x00, 0x18,
-0xDB, 0x5C, 0x4C, 0xEC, 0x04, 0x97, 0x00, 0xEF, 0x03, 0x63, 0x00, 0x00,
-0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x02, 0xF0, 0x00, 0x6D,
-0x63, 0xF3, 0x00, 0x4C, 0x1F, 0x6B, 0x04, 0xF5, 0x48, 0x9C, 0xFF, 0x4B,
-0x00, 0x53, 0xAD, 0xEA, 0x04, 0xF5, 0x48, 0xDC, 0x7F, 0x4C, 0x15, 0x4C,
-0xF6, 0x60, 0x20, 0xE8, 0x00, 0x65, 0x00, 0x65, 0x00, 0x1C, 0xA1, 0x5E,
-0x00, 0x65, 0x00, 0x65, 0x83, 0xED, 0xAB, 0xE4, 0x01, 0x61, 0x8B, 0xE5,
-0x20, 0xE8, 0x00, 0x65, 0xC9, 0xF7, 0x1B, 0x6A, 0xF9, 0x63, 0x4B, 0xEA,
-0x0A, 0xD0, 0x40, 0x30, 0x00, 0x30, 0x01, 0xF5, 0x83, 0x40, 0x0C, 0x62,
-0x00, 0x1C, 0x00, 0x5C, 0x0B, 0xD1, 0x05, 0xD2, 0x05, 0x93, 0x70, 0x6A,
-0x6C, 0xEA, 0x3A, 0x2A, 0x67, 0x40, 0x3B, 0x4B, 0x01, 0x6A, 0x4B, 0xEA,
-0x40, 0xC3, 0x05, 0x93, 0x70, 0x6A, 0x4C, 0xEB, 0x08, 0xD3, 0x3C, 0x2B,
-0x9D, 0x67, 0x00, 0x1C, 0x8A, 0x40, 0x10, 0x4C, 0x02, 0xF0, 0x00, 0x6A,
-0x40, 0x31, 0xAF, 0x41, 0x00, 0x1C, 0xAC, 0x45, 0x18, 0x6C, 0x9D, 0x67,
-0x10, 0x4C, 0x00, 0x1C, 0x90, 0x40, 0x02, 0x67, 0x00, 0x1C, 0x5B, 0x1F,
-0x64, 0x6C, 0x10, 0xF0, 0x00, 0x6A, 0xD0, 0x67, 0x4D, 0xEE, 0x18, 0x6C,
-0x00, 0x1C, 0x83, 0x45, 0xAF, 0x41, 0x00, 0x1C, 0x2C, 0x1F, 0x03, 0x6C,
-0x08, 0x92, 0x6A, 0x2A, 0xC9, 0xF7, 0x1B, 0x6A, 0x7D, 0x67, 0x4B, 0xEA,
-0x40, 0x32, 0x20, 0xF0, 0x60, 0xA3, 0x0C, 0x97, 0x0B, 0x91, 0x0A, 0x90,
-0x40, 0x32, 0x42, 0x4A, 0x07, 0x63, 0x60, 0xC2, 0x00, 0xEF, 0x00, 0x65,
-0x8F, 0x6A, 0xA3, 0x67, 0x01, 0xF5, 0x83, 0x40, 0x00, 0x1C, 0xF0, 0x5B,
-0x4C, 0xED, 0x05, 0x93, 0x70, 0x6A, 0x4C, 0xEB, 0x08, 0xD3, 0xC4, 0x23,
-0x9D, 0x67, 0x00, 0x1C, 0x8A, 0x40, 0x10, 0x4C, 0x02, 0xF0, 0x00, 0x6D,
-0xA0, 0x31, 0xAF, 0x41, 0x00, 0x1C, 0xAC, 0x45, 0x00, 0x6C, 0x9D, 0x67,
-0x10, 0x4C, 0x00, 0x1C, 0x90, 0x40, 0x06, 0xD2, 0x00, 0x1C, 0x5B, 0x1F,
-0x64, 0x6C, 0x00, 0x1C, 0xF0, 0x42, 0x01, 0x6C, 0x9D, 0x67, 0x00, 0x1C,
-0x8A, 0x40, 0x10, 0x4C, 0xAF, 0x41, 0x00, 0x1C, 0xAC, 0x45, 0x00, 0x6C,
-0x9D, 0x67, 0x10, 0x4C, 0x00, 0x1C, 0x90, 0x40, 0x07, 0xD2, 0x00, 0x1C,
-0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C, 0xF0, 0x42, 0x00, 0x6C, 0x01, 0xF1,
-0x00, 0x68, 0x06, 0x96, 0x00, 0x30, 0x01, 0x6A, 0xFF, 0x48, 0x40, 0x32,
-0x40, 0x32, 0x0C, 0xEE, 0x4D, 0xEE, 0xAF, 0x41, 0x00, 0x1C, 0x83, 0x45,
-0x00, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C, 0xF0, 0x42,
-0x01, 0x6C, 0x07, 0x93, 0x01, 0x6E, 0xC0, 0x36, 0x6C, 0xE8, 0xC0, 0x36,
-0xAF, 0x41, 0x0D, 0xEE, 0x00, 0x1C, 0x83, 0x45, 0x00, 0x6C, 0x00, 0x1C,
-0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C, 0xF0, 0x42, 0x00, 0x6C, 0x76, 0x17,
-0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x01, 0xF5,
-0x03, 0x4C, 0x00, 0x1C, 0xF0, 0x5B, 0x05, 0x95, 0x06, 0x96, 0xAF, 0x41,
-0x00, 0x1C, 0x83, 0x45, 0x00, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C,
-0x00, 0x1C, 0xF0, 0x42, 0x01, 0x6C, 0x07, 0x96, 0xAF, 0x41, 0x00, 0x1C,
-0x83, 0x45, 0x00, 0x6C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C, 0x00, 0x1C,
-0xF0, 0x42, 0x00, 0x6C, 0x0C, 0x97, 0x0B, 0x91, 0x0A, 0x90, 0x00, 0xEF,
-0x07, 0x63, 0x00, 0x00, 0xF8, 0x63, 0x0D, 0xD1, 0x10, 0xF0, 0x02, 0x69,
-0x00, 0xF4, 0x20, 0x31, 0x0E, 0x62, 0x0C, 0xD0, 0x63, 0xF3, 0x00, 0x49,
-0x03, 0x99, 0x01, 0x6A, 0x80, 0xF7, 0x02, 0x30, 0x4C, 0xE8, 0x08, 0x28,
-0x42, 0x99, 0x03, 0x6B, 0x40, 0xF7, 0x42, 0x32, 0x6C, 0xEA, 0x01, 0x72,
-0x00, 0xF2, 0x07, 0x60, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x63, 0xF3, 0x00, 0x4D, 0x43, 0x9D, 0x01, 0x6B, 0x80, 0xF7, 0x42, 0x32,
-0x6C, 0xEA, 0xE0, 0xF1, 0x14, 0x22, 0x42, 0x9D, 0x03, 0x6B, 0x40, 0xF7,
-0x42, 0x32, 0x6C, 0xEA, 0x01, 0x72, 0xE0, 0xF1, 0x0C, 0x61, 0x44, 0x9D,
-0x80, 0xF7, 0x42, 0x32, 0x01, 0x72, 0xA0, 0xF2, 0x00, 0x60, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0xC0, 0xF2, 0xA7, 0xA5, 0x80, 0x34, 0x80, 0x34,
-0x61, 0xF4, 0x02, 0x4C, 0x00, 0x1C, 0xF0, 0x5B, 0x06, 0xD5, 0x10, 0xF0,
-0x02, 0x69, 0x00, 0xF4, 0x20, 0x31, 0x63, 0xF3, 0x00, 0x49, 0xC0, 0xF2,
-0x46, 0xA1, 0x07, 0x2A, 0xBD, 0x67, 0xAC, 0xAD, 0x01, 0x6A, 0xC0, 0xF2,
-0x46, 0xC1, 0xC0, 0xF2, 0xA4, 0xC9, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA,
-0x40, 0x30, 0x00, 0x30, 0x01, 0xF5, 0x83, 0x40, 0x00, 0x1C, 0x00, 0x5C,
-0x00, 0x65, 0x70, 0x6B, 0x4C, 0xEB, 0x80, 0xF2, 0x16, 0x2B, 0xC0, 0xF2,
-0x44, 0xA9, 0x06, 0x93, 0x53, 0xE3, 0x63, 0xEA, 0x07, 0xD4, 0x02, 0x61,
-0x6B, 0xE2, 0x07, 0xD2, 0x07, 0x95, 0x03, 0x5D, 0x80, 0xF2, 0x0D, 0x60,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0xC9, 0xF7, 0x1B, 0x6C,
-0x63, 0xF3, 0x00, 0x4A, 0x8B, 0xEC, 0x80, 0x34, 0xC0, 0xF2, 0xA4, 0xA2,
-0x80, 0x34, 0x61, 0xF4, 0x03, 0x4C, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65,
-0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0x63, 0xF3, 0x00, 0x4D,
-0x9D, 0x67, 0x62, 0x9D, 0x98, 0xA4, 0x3F, 0x6E, 0x24, 0x6A, 0xC0, 0xF2,
-0x82, 0xC5, 0x83, 0x67, 0x62, 0x33, 0xCC, 0xEC, 0x62, 0x33, 0xCC, 0xEB,
-0x93, 0xE2, 0x20, 0x6A, 0x7B, 0xE2, 0xC0, 0xF2, 0x43, 0xA5, 0x06, 0x95,
-0x4F, 0xE5, 0x43, 0xED, 0x07, 0xD3, 0x02, 0x60, 0xAB, 0xE2, 0x07, 0xD2,
-0x07, 0x95, 0x60, 0xF1, 0x1C, 0x25, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B, 0xC0, 0xF2, 0x43, 0xA3, 0x06, 0x95,
-0x43, 0xED, 0x16, 0x60, 0x07, 0x92, 0x24, 0x68, 0x83, 0xEA, 0x40, 0xF2,
-0x18, 0x61, 0x07, 0x94, 0x20, 0x6D, 0x08, 0xD5, 0xC3, 0xEC, 0x24, 0x60,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A,
-0x45, 0xAA, 0x3F, 0x6B, 0x6C, 0xEA, 0x89, 0xE2, 0x08, 0xD2, 0x18, 0x10,
-0x42, 0x9B, 0x3F, 0x6B, 0x6C, 0xEA, 0x07, 0x93, 0x43, 0xEB, 0x63, 0xE2,
-0x01, 0x61, 0x00, 0x68, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x63, 0xF3, 0x00, 0x4A, 0x45, 0xAA, 0x07, 0x94, 0x3F, 0x6B, 0x6C, 0xEA,
-0x43, 0xEC, 0x8B, 0xE2, 0x08, 0xD2, 0x02, 0x61, 0x00, 0x6D, 0x08, 0xD5,
-0x06, 0x6A, 0x03, 0xEA, 0x80, 0xF2, 0x06, 0x60, 0x10, 0xF0, 0x02, 0x6B,
-0x00, 0xF4, 0x60, 0x33, 0x08, 0x32, 0x63, 0xF3, 0x00, 0x4B, 0x69, 0xE2,
-0xA6, 0x9A, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3,
-0x00, 0x4B, 0xC3, 0x9B, 0xE0, 0xF3, 0x1F, 0x6F, 0x80, 0xF5, 0xA2, 0x35,
-0x86, 0x67, 0xEC, 0xEC, 0x40, 0xF2, 0x17, 0x24, 0x00, 0xF2, 0x00, 0x68,
-0x44, 0x67, 0x0C, 0xEA, 0x04, 0x22, 0x00, 0xF4, 0x00, 0x6A, 0x4B, 0xEA,
-0x4D, 0xEC, 0xB8, 0xEC, 0xC2, 0x33, 0x6A, 0x33, 0xEC, 0xEB, 0x12, 0xEA,
-0x42, 0x34, 0x43, 0x67, 0x0C, 0xEA, 0xEC, 0xEC, 0x04, 0x22, 0x00, 0xF4,
-0x00, 0x6A, 0x4B, 0xEA, 0x4D, 0xEB, 0xB8, 0xEB, 0xC9, 0xF7, 0x1B, 0x68,
-0x0B, 0xE8, 0x80, 0xF5, 0xA0, 0x35, 0x00, 0x30, 0x00, 0x30, 0x12, 0xEA,
-0x42, 0x31, 0xEC, 0xE9, 0x3F, 0x6A, 0x2C, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0x4D, 0xED, 0x8D, 0xED, 0x81, 0xF4, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x04, 0xD5, 0x91, 0xF4, 0x84, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0x02, 0xF0, 0x00, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0xFF, 0x4D, 0x4C, 0xED,
-0xC0, 0xF3, 0x00, 0x6A, 0x4C, 0xE9, 0x80, 0xF5, 0x20, 0x32, 0x4D, 0xED,
-0x04, 0xD5, 0x91, 0xF4, 0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0x42, 0x9B, 0xC0, 0xF7, 0x42, 0x32, 0xC0, 0xF1, 0x0A, 0x2A, 0x08, 0x94,
-0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8, 0x8C, 0x32, 0x65, 0xE2, 0xA0, 0xF0,
-0xAC, 0xA1, 0x00, 0x30, 0x00, 0x30, 0x21, 0xF2, 0x82, 0x40, 0x00, 0x1C,
-0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF0, 0xAD, 0xA1, 0x21, 0xF2, 0x83, 0x40,
-0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF0, 0xAE, 0xA1, 0x21, 0xF2,
-0x84, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF0, 0xAF, 0xA1,
-0x21, 0xF2, 0x85, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF0,
-0xB0, 0xA1, 0x21, 0xF2, 0x86, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65,
-0xA0, 0xF0, 0xB1, 0xA1, 0x21, 0xF2, 0x87, 0x40, 0x00, 0x1C, 0xF0, 0x5B,
-0x00, 0x65, 0xA0, 0xF0, 0xB2, 0xA1, 0x21, 0xF2, 0x88, 0x40, 0x00, 0x1C,
-0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF0, 0xB3, 0xA1, 0x21, 0xF2, 0x89, 0x40,
-0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0xCB, 0xF4, 0x46, 0xA2, 0x22, 0x72, 0x03, 0x60, 0x92, 0x72,
-0x80, 0xF0, 0x0D, 0x61, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x63, 0xF3, 0x00, 0x4A, 0x42, 0x9A, 0x3F, 0x6B, 0x42, 0x32, 0x6C, 0xEA,
-0x24, 0x6B, 0x53, 0xE3, 0x07, 0x92, 0x01, 0x6B, 0x6E, 0xEA, 0x6C, 0xEA,
-0x00, 0xF2, 0x0F, 0x22, 0x07, 0x95, 0xA6, 0x33, 0x64, 0x32, 0x69, 0xE2,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x07, 0xD2, 0x63, 0xF3,
-0x00, 0x4B, 0xC0, 0xF2, 0x43, 0xA3, 0x06, 0x95, 0x43, 0xED, 0xA0, 0xF1,
-0x19, 0x60, 0x07, 0x92, 0x24, 0x68, 0x83, 0xEA, 0x06, 0x60, 0x42, 0x9B,
-0x3F, 0x6B, 0x42, 0x32, 0x6C, 0xEA, 0x07, 0x93, 0x61, 0xE2, 0x06, 0x6D,
-0x03, 0xED, 0xA0, 0xF1, 0x16, 0x60, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x08, 0x32, 0x63, 0xF3, 0x00, 0x4B, 0x69, 0xE2, 0xA6, 0x9A,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x63, 0xF3, 0x00, 0x4B,
-0xC4, 0x9B, 0xE0, 0xF3, 0x1F, 0x6F, 0x80, 0xF5, 0xA2, 0x35, 0xC2, 0x34,
-0x8A, 0x34, 0xEC, 0xEC, 0xA0, 0xF1, 0x1E, 0x24, 0x00, 0xF2, 0x00, 0x68,
-0x44, 0x67, 0x0C, 0xEA, 0x04, 0x22, 0x00, 0xF4, 0x00, 0x6A, 0x4B, 0xEA,
-0x4D, 0xEC, 0xB8, 0xEC, 0x00, 0xF5, 0xC2, 0x33, 0xEC, 0xEB, 0x12, 0xEA,
-0x42, 0x34, 0x43, 0x67, 0x0C, 0xEA, 0xEC, 0xEC, 0x04, 0x22, 0x00, 0xF4,
-0x00, 0x6A, 0x4B, 0xEA, 0x4D, 0xEB, 0xB8, 0xEB, 0xC9, 0xF7, 0x1B, 0x68,
-0x0B, 0xE8, 0x80, 0xF5, 0xA0, 0x35, 0x00, 0x30, 0x00, 0x30, 0x12, 0xEA,
-0x42, 0x31, 0xEC, 0xE9, 0x3F, 0x6A, 0x2C, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0x4D, 0xED, 0x8D, 0xED, 0x81, 0xF4, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x04, 0xD5, 0x91, 0xF4, 0x8C, 0x40, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0x02, 0xF0, 0x00, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0xFF, 0x4D, 0x4C, 0xED,
-0xC0, 0xF3, 0x00, 0x6A, 0x4C, 0xE9, 0x80, 0xF5, 0x20, 0x32, 0x4D, 0xED,
-0x91, 0xF4, 0x8C, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x04, 0xD5, 0x0E, 0x97,
-0x0D, 0x91, 0x0C, 0x90, 0x00, 0x6A, 0x00, 0xEF, 0x08, 0x63, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x81, 0xF4, 0x00, 0x4C,
-0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x08, 0xF0, 0x00, 0x6B, 0x6B, 0xEB,
-0x60, 0x33, 0xA2, 0x67, 0x6C, 0xED, 0xD1, 0x67, 0x03, 0x10, 0x01, 0x48,
-0x25, 0x58, 0x0E, 0x60, 0x08, 0x32, 0xC9, 0xE2, 0x46, 0x9A, 0x6C, 0xEA,
-0xAE, 0xEA, 0xF7, 0x2A, 0x62, 0x9E, 0x40, 0x6C, 0x3F, 0x6A, 0x8B, 0xEC,
-0x0C, 0xEA, 0x8C, 0xEB, 0x4D, 0xEB, 0x62, 0xDE, 0x10, 0xF0, 0x02, 0x6A,
-0x00, 0xF4, 0x40, 0x32, 0xCB, 0xF4, 0x46, 0xA2, 0x22, 0x72, 0x02, 0x60,
-0x92, 0x72, 0x2A, 0x61, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34,
-0x80, 0x34, 0x81, 0xF4, 0x08, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x68,
-0x08, 0xF0, 0x00, 0x6B, 0x6B, 0xEB, 0x60, 0x33, 0xA2, 0x67, 0x10, 0xF0,
-0x02, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0x6C, 0xED, 0x63, 0xF3, 0x00, 0x4E,
-0x03, 0x10, 0x01, 0x48, 0x25, 0x58, 0x10, 0x60, 0x08, 0x32, 0xC9, 0xE2,
-0x46, 0x9A, 0x6C, 0xEA, 0xAE, 0xEA, 0xF7, 0x2A, 0x62, 0x9E, 0x3F, 0x6A,
-0x07, 0xF7, 0x01, 0x6C, 0x0C, 0xEA, 0x8B, 0xEC, 0x40, 0x32, 0x8C, 0xEB,
-0x4D, 0xEB, 0x62, 0xDE, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34,
-0x80, 0x34, 0x21, 0xF2, 0x04, 0x4C, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x68,
-0x27, 0xF7, 0x1F, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x27, 0xF7, 0x1F, 0x4B,
-0x4C, 0xEB, 0x04, 0xD3, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x03, 0xF4, 0x0E, 0x4A,
-0x03, 0xF5, 0x16, 0x4B, 0x09, 0xD2, 0x0A, 0xD3, 0x0C, 0x10, 0x0A, 0x93,
-0x9D, 0x67, 0x10, 0x4C, 0x75, 0xE1, 0x00, 0x1C, 0x1D, 0x55, 0x04, 0x6E,
-0xC0, 0xF0, 0x1B, 0x22, 0x01, 0x48, 0x21, 0x58, 0x22, 0x60, 0x09, 0x92,
-0x0C, 0x31, 0x9D, 0x67, 0x10, 0x4C, 0x55, 0xE1, 0x00, 0x1C, 0x1D, 0x55,
-0x04, 0x6E, 0xEB, 0x2A, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35,
-0x63, 0xF3, 0x00, 0x4D, 0x07, 0xF7, 0x00, 0x6A, 0x62, 0x9D, 0x4B, 0xEA,
-0x40, 0x32, 0xFF, 0x4A, 0x3F, 0x6C, 0x4C, 0xEB, 0x0C, 0xEC, 0x10, 0xF0,
-0x00, 0x6A, 0x80, 0x34, 0x40, 0x32, 0x80, 0x34, 0x40, 0x32, 0x8D, 0xEB,
-0xFF, 0x4A, 0x4C, 0xEB, 0x62, 0xDD, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4,
-0x80, 0x34, 0x63, 0xF3, 0x00, 0x4C, 0x63, 0x9C, 0x08, 0xF0, 0x00, 0x6A,
-0x40, 0x32, 0x40, 0x32, 0x4D, 0xEB, 0x63, 0xDC, 0x45, 0x15, 0x02, 0xF0,
-0x00, 0x68, 0x00, 0x30, 0x60, 0x6E, 0xAF, 0x40, 0x00, 0x1C, 0x83, 0x45,
-0x24, 0x6C, 0xE0, 0xF3, 0x08, 0x6C, 0x00, 0x1C, 0x2C, 0x1F, 0x00, 0x65,
-0x9D, 0x67, 0x00, 0x1C, 0x8A, 0x40, 0x14, 0x4C, 0xAF, 0x40, 0x00, 0x1C,
-0xAC, 0x45, 0x24, 0x6C, 0x1F, 0x6C, 0x4C, 0xEC, 0x06, 0xD4, 0x9D, 0x67,
-0x00, 0x1C, 0x90, 0x40, 0x14, 0x4C, 0x00, 0x1C, 0x5B, 0x1F, 0x64, 0x6C,
-0x4C, 0x15, 0x61, 0xF4, 0x83, 0x40, 0xCC, 0x6D, 0x82, 0x15, 0x00, 0x18,
-0xA4, 0x5E, 0x00, 0x65, 0x7D, 0x67, 0x6C, 0xAB, 0x10, 0xF0, 0x02, 0x6A,
-0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0xC0, 0xF2, 0x64, 0xCA,
-0x65, 0x15, 0x42, 0x9B, 0x3F, 0x6B, 0x6C, 0xEA, 0x07, 0x93, 0x61, 0xE2,
-0xA2, 0x15, 0x08, 0x95, 0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8, 0xAC, 0x32,
-0x65, 0xE2, 0xA0, 0xF1, 0xB4, 0xA1, 0x00, 0x30, 0x00, 0x30, 0x21, 0xF2,
-0x82, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF1, 0xB5, 0xA1,
-0x21, 0xF2, 0x83, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF1,
-0xB6, 0xA1, 0x21, 0xF2, 0x84, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65,
-0xA0, 0xF1, 0xB7, 0xA1, 0x21, 0xF2, 0x85, 0x40, 0x00, 0x1C, 0xF0, 0x5B,
-0x00, 0x65, 0xA0, 0xF1, 0xB8, 0xA1, 0x21, 0xF2, 0x86, 0x40, 0x00, 0x1C,
-0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF1, 0xB9, 0xA1, 0x21, 0xF2, 0x87, 0x40,
-0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF1, 0xBA, 0xA1, 0x21, 0xF2,
-0x88, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x00, 0x65, 0xA0, 0xF1, 0xBB, 0xA1,
-0x21, 0xF2, 0x89, 0x40, 0x35, 0x16, 0x6A, 0x60, 0x08, 0x32, 0xC9, 0xF7,
-0x1B, 0x6C, 0x69, 0xE2, 0x8B, 0xEC, 0x80, 0x34, 0xA6, 0x9A, 0x80, 0x34,
-0x81, 0xF4, 0x00, 0x4C, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x81, 0xF4, 0x14, 0x4C,
-0x00, 0x6D, 0xD3, 0x15, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x63, 0xF3, 0x00, 0x4A, 0xAC, 0x9A, 0x7B, 0x15, 0x42, 0x9B, 0x07, 0x94,
-0x3F, 0x6B, 0x42, 0x32, 0x6C, 0xEA, 0x43, 0xEC, 0x83, 0xE2, 0x5F, 0xF6,
-0x08, 0x61, 0x00, 0x68, 0x18, 0x65, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0xAC, 0x9A, 0x4B, 0x16, 0x10, 0xF0,
-0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0x63, 0xF3, 0x00, 0x4D, 0x07, 0xF7,
-0x00, 0x6A, 0x62, 0x9D, 0x4B, 0xEA, 0x3F, 0x6C, 0x40, 0x32, 0xFF, 0x4A,
-0x0C, 0xEC, 0x4C, 0xEB, 0x80, 0x34, 0x10, 0xF0, 0x00, 0x6A, 0x4B, 0xEA,
-0x80, 0x34, 0x40, 0x32, 0x8D, 0xEB, 0x40, 0x32, 0x4D, 0xEB, 0x30, 0x17,
-0x28, 0x60, 0x08, 0x32, 0xC9, 0xF7, 0x1B, 0x6C, 0x69, 0xE2, 0x8B, 0xEC,
-0x80, 0x34, 0xA6, 0x9A, 0x80, 0x34, 0x81, 0xF4, 0x08, 0x4C, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34,
-0x80, 0x34, 0x81, 0xF4, 0x1C, 0x4C, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x6D,
-0x6C, 0x16, 0x07, 0x93, 0xFF, 0x4B, 0x66, 0x33, 0x64, 0x32, 0x69, 0xE2,
-0x01, 0x4A, 0xEE, 0x15, 0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34,
-0xAC, 0x9B, 0x80, 0x34, 0x81, 0xF4, 0x00, 0x4C, 0x97, 0x17, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0xAC, 0x9B, 0x80, 0x34, 0x81, 0xF4,
-0x08, 0x4C, 0xD9, 0x17, 0x82, 0x34, 0x1F, 0xF7, 0x00, 0x6A, 0x4C, 0xEC,
-0x82, 0x35, 0x20, 0x5D, 0x1B, 0x60, 0xAC, 0x32, 0xA9, 0xE2, 0x48, 0x32,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xA9, 0xE2, 0x63, 0xF3,
-0x00, 0x4B, 0x48, 0x32, 0x69, 0xE2, 0xE4, 0xF4, 0x58, 0x9A, 0xC9, 0xF7,
-0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x52, 0x32, 0x7F, 0x6B,
-0x60, 0xF3, 0x14, 0x4C, 0x6C, 0xEA, 0x40, 0xDC, 0x20, 0xE8, 0x00, 0x65,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0xCA, 0xF2, 0x4C, 0x9A,
-0xC9, 0xF7, 0x1B, 0x6C, 0x8B, 0xEC, 0x80, 0x34, 0x80, 0x34, 0x52, 0x32,
-0x7F, 0x6B, 0x60, 0xF3, 0x14, 0x4C, 0x6C, 0xEA, 0x40, 0xDC, 0x20, 0xE8,
-0x00, 0x65, 0x00, 0x00, 0xFC, 0x63, 0x04, 0xD0, 0xC9, 0xF7, 0x1B, 0x68,
-0x0B, 0xE8, 0x00, 0x30, 0x00, 0x30, 0x01, 0xF5, 0x83, 0x40, 0x06, 0x62,
-0x00, 0x1C, 0x00, 0x5C, 0x05, 0xD1, 0x08, 0x6D, 0x4D, 0xED, 0xFF, 0x69,
-0x01, 0xF5, 0x83, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x2C, 0xED, 0x01, 0xF5,
-0x83, 0x40, 0x00, 0x1C, 0x00, 0x5C, 0x00, 0x65, 0xA2, 0x67, 0xF7, 0x6B,
-0x01, 0xF5, 0x83, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x6C, 0xED, 0x21, 0xF2,
-0x8D, 0x40, 0x00, 0x1C, 0x00, 0x5C, 0x00, 0x65, 0xA2, 0x67, 0x3F, 0x6B,
-0x21, 0xF2, 0x8D, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x6C, 0xED, 0x21, 0xF2,
-0x8D, 0x40, 0x00, 0x1C, 0x00, 0x5C, 0x00, 0x65, 0x80, 0x6D, 0xAB, 0xED,
-0x4D, 0xED, 0x21, 0xF2, 0x8D, 0x40, 0x00, 0x1C, 0xF0, 0x5B, 0x2C, 0xED,
-0x06, 0x97, 0x05, 0x91, 0x04, 0x90, 0x00, 0xEF, 0x04, 0x63, 0x00, 0x65,
-0x00, 0x1C, 0x2A, 0x61, 0x00, 0x65, 0x00, 0x65, 0x00, 0x1C, 0x2C, 0x61,
-0x00, 0x65, 0x00, 0x65, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0x40, 0x32,
-0x40, 0x32, 0x30, 0xF2, 0x63, 0x42, 0x90, 0x34, 0x80, 0xC3, 0x20, 0xF2,
-0x10, 0x4A, 0x40, 0x9A, 0x02, 0xF0, 0x00, 0x6B, 0x60, 0x33, 0xFF, 0x4B,
-0x20, 0xE8, 0x6C, 0xEA, 0xC9, 0xF7, 0x1B, 0x6A, 0x4B, 0xEA, 0xFF, 0x6D,
-0x40, 0x32, 0x8C, 0xED, 0x40, 0x32, 0x30, 0xF2, 0x83, 0x42, 0xB0, 0x33,
-0x60, 0xC4, 0x20, 0xF2, 0x10, 0x4A, 0x60, 0x9A, 0x02, 0xF0, 0x00, 0x6A,
-0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB, 0x83, 0x67, 0x05, 0x23, 0x01, 0x6C,
-0x84, 0xED, 0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xEC, 0x20, 0xE8, 0x44, 0x67,
-0xC9, 0xF7, 0x1B, 0x6A, 0xFB, 0x63, 0x4B, 0xEA, 0x07, 0xD1, 0x40, 0x31,
-0x08, 0x62, 0x06, 0xD0, 0x20, 0x31, 0x40, 0xF0, 0x4C, 0xA1, 0xFF, 0x6C,
-0x8C, 0xEA, 0x02, 0x72, 0x14, 0x61, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0x04, 0xD2, 0x66, 0xF7, 0x56, 0xAA,
-0x01, 0x72, 0x09, 0x61, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0xEB, 0xF5, 0x4C, 0xA2, 0x04, 0x67, 0x4C, 0xE8, 0x05, 0x20, 0x08, 0x97,
-0x07, 0x91, 0x06, 0x90, 0x00, 0xEF, 0x05, 0x63, 0x00, 0x18, 0x2C, 0x61,
-0x04, 0x6C, 0x04, 0x94, 0x08, 0xF0, 0x64, 0x9C, 0x4D, 0xE3, 0x08, 0xF0,
-0x64, 0xDC, 0x00, 0x18, 0x2C, 0x61, 0x06, 0x6C, 0x04, 0x94, 0x08, 0xF0,
-0x68, 0x9C, 0x4D, 0xE3, 0x08, 0xF0, 0x68, 0xDC, 0x00, 0x18, 0x2C, 0x61,
-0x07, 0x6C, 0x04, 0x94, 0x08, 0xF0, 0x6C, 0x9C, 0x4D, 0xE3, 0x08, 0xF0,
-0x6C, 0xDC, 0x00, 0x18, 0x2C, 0x61, 0x05, 0x6C, 0x04, 0x94, 0x08, 0xF0,
-0x70, 0x9C, 0x4D, 0xE3, 0x08, 0xF0, 0x70, 0xDC, 0x00, 0x18, 0x35, 0x61,
-0x90, 0x67, 0x04, 0x6C, 0x00, 0x18, 0x35, 0x61, 0x02, 0x67, 0x4D, 0xE8,
-0xFF, 0xF7, 0x1F, 0x6A, 0x4C, 0xE8, 0x30, 0xF2, 0x63, 0x41, 0x08, 0x6A,
-0x40, 0xC3, 0xC7, 0x28, 0x40, 0xF0, 0x40, 0xA9, 0xFF, 0xF7, 0x1F, 0x6B,
-0x6C, 0xEA, 0xFB, 0xF7, 0x1F, 0x6B, 0x6C, 0xEA, 0x04, 0xF0, 0x00, 0x6B,
-0x40, 0xF0, 0x40, 0xC9, 0x6D, 0xEA, 0x40, 0xF0, 0x40, 0xC9, 0x04, 0x94,
-0xFF, 0xF7, 0x1F, 0x6A, 0x66, 0xF7, 0xB4, 0xAC, 0x01, 0x4D, 0x66, 0xF7,
-0xB4, 0xCC, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x7E, 0xF2,
-0x08, 0x4C, 0x00, 0x1C, 0x13, 0x58, 0x4C, 0xED, 0xA6, 0x17, 0x00, 0x65,
-0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF, 0x85, 0x2B, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xBF, 0x8F, 0x02, 0x80, 0x02, 0x3C,
-0xE8, 0x03, 0x03, 0x24, 0x2C, 0x5E, 0x43, 0xAC, 0x18, 0x00, 0xBD, 0x27,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x0B, 0x5E, 0x40, 0xA0, 0xFF, 0x00, 0x85, 0x30,
-0xF2, 0x5D, 0x60, 0xA0, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x05, 0x5E, 0x40, 0xA0, 0x08, 0x00, 0xA4, 0x2C, 0x07, 0x5E, 0x60, 0xA0,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x0F, 0x5E, 0x40, 0xA0,
-0xEC, 0x5D, 0x65, 0xA0, 0x2C, 0x00, 0x80, 0x10, 0x02, 0x80, 0x03, 0x3C,
-0x80, 0x10, 0x05, 0x00, 0x78, 0xF2, 0x63, 0x24, 0x21, 0x10, 0x43, 0x00,
-0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x05, 0x3C, 0x60, 0x1B, 0xA5, 0x24,
-0xD0, 0x1B, 0xA4, 0x8C, 0x00, 0x70, 0x02, 0x3C, 0x02, 0x00, 0x42, 0x34,
-0x25, 0x20, 0x82, 0x00, 0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x64, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0xD0, 0x1B, 0xA4, 0xAC, 0x02, 0x80, 0x05, 0x3C,
-0x60, 0x1B, 0xA5, 0x24, 0xD0, 0x1B, 0xA4, 0x8C, 0x00, 0x70, 0x02, 0x3C,
-0x02, 0x00, 0x42, 0x34, 0x27, 0x10, 0x02, 0x00, 0x24, 0x20, 0x82, 0x00,
-0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x64, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0xD0, 0x1B, 0xA4, 0xAC, 0x02, 0x80, 0x05, 0x3C, 0x60, 0x1B, 0xA5, 0x24,
-0xD0, 0x1B, 0xA4, 0x8C, 0x00, 0x70, 0x02, 0x3C, 0x27, 0x10, 0x02, 0x00,
-0x24, 0x20, 0x82, 0x00, 0x02, 0x80, 0x07, 0x3C, 0x41, 0xB0, 0x02, 0x3C,
-0x01, 0x00, 0x03, 0x24, 0x00, 0x00, 0x44, 0xAC, 0x09, 0x5E, 0xE3, 0xA0,
-0x09, 0x5E, 0xE6, 0x90, 0x02, 0x80, 0x02, 0x3C, 0xD0, 0x1B, 0xA4, 0xAC,
-0x0A, 0x5E, 0x46, 0xA0, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x05, 0x3C, 0x60, 0x1B, 0xA5, 0x24, 0xD0, 0x1B, 0xA4, 0x8C,
-0x00, 0x70, 0x02, 0x3C, 0x27, 0x10, 0x02, 0x00, 0x24, 0x20, 0x82, 0x00,
-0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x64, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0xD0, 0x1B, 0xA4, 0xAC, 0xE0, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x10, 0x3C, 0xEC, 0x5D, 0x02, 0x92, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x1C, 0x00, 0xBF, 0xAF, 0x21, 0x90, 0x80, 0x00,
-0x1C, 0x00, 0x40, 0x10, 0xFF, 0x00, 0xB1, 0x30, 0x02, 0x80, 0x03, 0x3C,
-0xC6, 0x5C, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x42, 0x30,
-0x1C, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x24,
-0x00, 0x02, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24,
-0x02, 0x80, 0x03, 0x3C, 0xEE, 0x5D, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x0F, 0x00, 0x42, 0x30, 0x0C, 0x00, 0x42, 0x28, 0x06, 0x00, 0x40, 0x10,
-0x08, 0x00, 0x02, 0x24, 0x00, 0x00, 0x44, 0x96, 0x00, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0x83, 0x30, 0x1B, 0x00, 0x62, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0xEC, 0x5D, 0x02, 0x92, 0x05, 0x00, 0x03, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x0B, 0x00, 0x43, 0x10, 0x02, 0x80, 0x03, 0x3C, 0x1C, 0x00, 0xBF, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27, 0xA8, 0x2D, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0xF1, 0x61, 0x00, 0x08, 0x00, 0x08, 0x04, 0x24,
-0x08, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x24, 0x10, 0x22, 0x02,
-0xF2, 0xFF, 0x40, 0x10, 0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0x62, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x42, 0x34, 0x07, 0x5E, 0x62, 0xA0,
-0x05, 0x62, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5E, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x60, 0x14, 0x00, 0x10, 0x82, 0x34,
-0x00, 0x62, 0x00, 0x08, 0x00, 0x00, 0x42, 0xA6, 0x0C, 0x00, 0x04, 0x24,
-0x4B, 0x2E, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x00, 0x62, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x02, 0x80, 0x03, 0x3C, 0x0B, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x00, 0x40, 0x10, 0x02, 0x80, 0x04, 0x3C, 0x0B, 0x5E, 0x60, 0xA0,
-0x02, 0x80, 0x04, 0x3C, 0x07, 0x5E, 0x83, 0x90, 0xFD, 0xFF, 0x02, 0x24,
-0x24, 0x18, 0x62, 0x00, 0x07, 0x5E, 0x83, 0xA0, 0x07, 0x5E, 0x82, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x42, 0x30, 0x49, 0x00, 0x40, 0x10,
-0x02, 0x80, 0x02, 0x3C, 0x10, 0x00, 0xBF, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0xF2, 0x5D, 0x82, 0x90,
-0x02, 0x80, 0x05, 0x3C, 0x01, 0x00, 0x42, 0x24, 0xF2, 0x5D, 0x82, 0xA0,
-0x07, 0x5E, 0xA3, 0x90, 0xEF, 0xFF, 0x02, 0x24, 0x24, 0x18, 0x62, 0x00,
-0x07, 0x5E, 0xA3, 0xA0, 0xF2, 0x5D, 0x82, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0x42, 0x2C, 0x13, 0x00, 0x40, 0x14, 0x25, 0xB0, 0x06, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x10, 0x37, 0x62, 0x94, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x01, 0x42, 0x30, 0x3A, 0x00, 0x40, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x0E, 0x5E, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00,
-0xE5, 0xFF, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x5E, 0x62, 0x90,
-0x10, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xBD, 0x27, 0x01, 0x00, 0x42, 0x24,
-0x0E, 0x5E, 0x62, 0xA0, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x84, 0x00, 0xC4, 0x34, 0x80, 0x00, 0xC6, 0x34, 0x00, 0x00, 0x82, 0x8C,
-0x00, 0x00, 0xC4, 0x8C, 0x02, 0x80, 0x08, 0x3C, 0x21, 0x10, 0x00, 0x00,
-0x14, 0x5E, 0x06, 0x8D, 0x42, 0xB0, 0x0A, 0x3C, 0x25, 0x10, 0x44, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x18, 0x5E, 0x88, 0x8C, 0x1C, 0x5E, 0x89, 0x8C,
-0x00, 0x00, 0x45, 0x91, 0x21, 0x10, 0x46, 0x00, 0xFB, 0xFF, 0x04, 0x24,
-0x24, 0x28, 0xA4, 0x00, 0x23, 0x40, 0x02, 0x01, 0x00, 0x00, 0x45, 0xA1,
-0x04, 0x00, 0x00, 0x11, 0x01, 0x00, 0x06, 0x24, 0x80, 0x10, 0x08, 0x00,
-0x21, 0x10, 0x48, 0x00, 0x80, 0x30, 0x02, 0x00, 0x01, 0x00, 0x04, 0x24,
-0xB9, 0x20, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x42, 0xB0, 0x02, 0x3C,
-0x22, 0x00, 0x04, 0x24, 0x03, 0x00, 0x42, 0x34, 0x00, 0x00, 0x44, 0xA0,
-0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x64, 0x90, 0x10, 0x00, 0xBF, 0x8F,
-0x01, 0x00, 0x05, 0x24, 0xFF, 0x00, 0x84, 0x30, 0x4B, 0x2E, 0x00, 0x08,
-0x18, 0x00, 0xBD, 0x27, 0x05, 0x5E, 0x40, 0xA0, 0x02, 0x80, 0x03, 0x3C,
-0xED, 0x5D, 0x64, 0x90, 0x10, 0x00, 0xBF, 0x8F, 0x01, 0x00, 0x05, 0x24,
-0xFF, 0x00, 0x84, 0x30, 0x4B, 0x2E, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0x10, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xBD, 0x27, 0x0E, 0x5E, 0x40, 0xA0,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27,
-0xFF, 0x00, 0xA5, 0x30, 0x10, 0x00, 0xB0, 0xAF, 0x14, 0x00, 0xBF, 0xAF,
-0x18, 0x00, 0xA0, 0x14, 0xFF, 0x00, 0x90, 0x30, 0x35, 0x00, 0x00, 0x12,
-0x01, 0x00, 0x05, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x01, 0x00, 0x05, 0x24,
-0x05, 0x5E, 0x45, 0xA0, 0x02, 0x80, 0x07, 0x3C, 0x07, 0x5E, 0xE3, 0x90,
-0x02, 0x00, 0x04, 0x24, 0x21, 0x28, 0x00, 0x00, 0x02, 0x00, 0x63, 0x34,
-0x00, 0xF0, 0x06, 0x34, 0x07, 0x5E, 0xE3, 0xA0, 0xB9, 0x20, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x42, 0xB0, 0x02, 0x3C, 0x44, 0x00, 0x03, 0x24, 0x03, 0x00, 0x42, 0x34,
-0x18, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x43, 0xA0, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x05, 0x5E, 0x44, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0x08, 0x5E, 0x65, 0x90,
-0x0F, 0x00, 0x02, 0x24, 0x02, 0x80, 0x06, 0x3C, 0x0F, 0x00, 0xA5, 0x30,
-0x0D, 0x00, 0xA2, 0x10, 0x01, 0x00, 0x04, 0x24, 0x07, 0x5E, 0xC2, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x34, 0x07, 0x5E, 0xC2, 0xA0,
-0xE1, 0x51, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xDB, 0xFF, 0x00, 0x16,
-0x02, 0x80, 0x02, 0x3C, 0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x18, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C,
-0x04, 0x5E, 0x43, 0x90, 0x01, 0x00, 0x04, 0x24, 0xF6, 0xFF, 0x60, 0x10,
-0x01, 0x00, 0x05, 0x24, 0xC8, 0x51, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xB9, 0x62, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x05, 0x5E, 0x40, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x64, 0x90,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xFF, 0x00, 0x84, 0x30,
-0x4B, 0x2E, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27,
-0xFF, 0x00, 0xA5, 0x30, 0x14, 0x00, 0xB1, 0xAF, 0x18, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x03, 0x00, 0xA0, 0x14, 0xFF, 0x00, 0x91, 0x30,
-0x3A, 0x00, 0x20, 0x12, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x10, 0x3C,
-0x07, 0x5E, 0x02, 0x92, 0xFB, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0x07, 0x5E, 0x02, 0xA2, 0x10, 0x00, 0xA0, 0x14, 0x02, 0x80, 0x03, 0x3C,
-0x07, 0x5E, 0x02, 0x92, 0xFE, 0xFF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00,
-0x07, 0x5E, 0x02, 0xA2, 0x19, 0x00, 0x20, 0x16, 0x02, 0x80, 0x02, 0x3C,
-0x07, 0x5E, 0x02, 0x92, 0xFD, 0xFF, 0x03, 0x24, 0x18, 0x00, 0xBF, 0x8F,
-0x24, 0x10, 0x43, 0x00, 0x07, 0x5E, 0x02, 0xA2, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x01, 0x00, 0x04, 0x24, 0x05, 0x5E, 0x64, 0xA0, 0x07, 0x5E, 0x02, 0x92,
-0x02, 0x80, 0x03, 0x3C, 0x01, 0x00, 0x42, 0x34, 0x07, 0x5E, 0x02, 0xA2,
-0x06, 0x5E, 0x62, 0x90, 0x02, 0x00, 0x03, 0x24, 0xFF, 0x00, 0x42, 0x30,
-0x23, 0x00, 0x43, 0x10, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x51, 0x00, 0x0C,
-0x01, 0x00, 0x04, 0x24, 0xE9, 0xFF, 0x20, 0x12, 0x02, 0x80, 0x02, 0x3C,
-0x01, 0x00, 0x04, 0x24, 0x05, 0x5E, 0x44, 0xA0, 0x07, 0x5E, 0x03, 0x92,
-0x02, 0x00, 0x04, 0x24, 0x21, 0x28, 0x00, 0x00, 0x02, 0x00, 0x63, 0x34,
-0x00, 0xF0, 0x06, 0x34, 0x07, 0x5E, 0x03, 0xA2, 0xB9, 0x20, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x42, 0xB0, 0x02, 0x3C, 0x44, 0x00, 0x03, 0x24,
-0x03, 0x00, 0x42, 0x34, 0x20, 0x00, 0xBD, 0x27, 0x00, 0x00, 0x43, 0xA0,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05, 0x5E, 0x40, 0xA0,
-0x02, 0x80, 0x03, 0x3C, 0xED, 0x5D, 0x64, 0x90, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x05, 0x24,
-0xFF, 0x00, 0x84, 0x30, 0x4B, 0x2E, 0x00, 0x08, 0x20, 0x00, 0xBD, 0x27,
-0xE2, 0x2C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x04, 0x24,
-0x4B, 0x2E, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24, 0xE5, 0x62, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB2, 0xAF,
-0x0C, 0x00, 0xB1, 0xAF, 0x08, 0x00, 0xB0, 0xAF, 0x21, 0x40, 0xE0, 0x00,
-0x21, 0x90, 0xA0, 0x03, 0x21, 0x60, 0xC0, 0x00, 0x21, 0x78, 0x80, 0x00,
-0x45, 0x00, 0xE0, 0x14, 0x21, 0x50, 0xA0, 0x00, 0x2B, 0x10, 0xA6, 0x00,
-0x78, 0x00, 0x40, 0x10, 0xFF, 0xFF, 0x02, 0x34, 0x2B, 0x10, 0x46, 0x00,
-0x8F, 0x01, 0x40, 0x10, 0x21, 0x28, 0xC0, 0x00, 0xFF, 0x00, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x10, 0x00, 0x03, 0x24, 0x2B, 0x10, 0x46, 0x00,
-0x18, 0x00, 0x04, 0x24, 0x21, 0x30, 0x60, 0x00, 0x0B, 0x30, 0x82, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x06, 0x10, 0xC5, 0x00, 0x98, 0xF2, 0x63, 0x24,
-0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x90, 0x20, 0x00, 0x02, 0x24,
-0x21, 0x20, 0x86, 0x00, 0x23, 0x30, 0x44, 0x00, 0x08, 0x00, 0xC0, 0x10,
-0x02, 0x4C, 0x0C, 0x00, 0x23, 0x10, 0x46, 0x00, 0x06, 0x10, 0x4F, 0x00,
-0x04, 0x18, 0xCA, 0x00, 0x25, 0x50, 0x62, 0x00, 0x04, 0x60, 0xCC, 0x00,
-0x04, 0x78, 0xCF, 0x00, 0x02, 0x4C, 0x0C, 0x00, 0x1B, 0x00, 0x49, 0x01,
-0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00,
-0xFF, 0xFF, 0x87, 0x31, 0x02, 0x24, 0x0F, 0x00, 0x12, 0x18, 0x00, 0x00,
-0x10, 0x28, 0x00, 0x00, 0x00, 0x14, 0x05, 0x00, 0x25, 0x28, 0x44, 0x00,
-0x18, 0x00, 0x67, 0x00, 0x12, 0x58, 0x00, 0x00, 0x2B, 0x18, 0xAB, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x49, 0x01, 0x02, 0x00, 0x20, 0x15,
-0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00, 0x08, 0x00, 0x60, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0xAC, 0x00, 0x2B, 0x10, 0xAC, 0x00,
-0x04, 0x00, 0x40, 0x14, 0x2B, 0x10, 0xAB, 0x00, 0x00, 0x00, 0x42, 0x38,
-0x21, 0x18, 0xAC, 0x00, 0x0B, 0x28, 0x62, 0x00, 0x23, 0x28, 0xAB, 0x00,
-0x1B, 0x00, 0xA9, 0x00, 0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xE4, 0x31, 0x12, 0x18, 0x00, 0x00,
-0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x63, 0x00, 0x08,
-0x18, 0x00, 0x67, 0x00, 0x2B, 0x10, 0xA7, 0x00, 0x0A, 0x00, 0x40, 0x10,
-0xFF, 0xFF, 0x02, 0x34, 0x10, 0x00, 0xB2, 0x8F, 0x0C, 0x00, 0xB1, 0x8F,
-0x08, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x80, 0x00, 0x21, 0x18, 0xA0, 0x00,
-0x00, 0x00, 0xA4, 0xAF, 0x04, 0x00, 0xA5, 0xAF, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x2B, 0x10, 0x47, 0x00, 0xD2, 0x00, 0x40, 0x10,
-0x00, 0x01, 0xE3, 0x2C, 0xFF, 0x00, 0x02, 0x3C, 0x10, 0x00, 0x03, 0x24,
-0xFF, 0xFF, 0x42, 0x34, 0x2B, 0x10, 0x47, 0x00, 0x18, 0x00, 0x04, 0x24,
-0x21, 0x28, 0x60, 0x00, 0x0B, 0x28, 0x82, 0x00, 0x06, 0x10, 0xA8, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x98, 0xF2, 0x63, 0x24, 0x21, 0x10, 0x43, 0x00,
-0x00, 0x00, 0x44, 0x90, 0x20, 0x00, 0x02, 0x24, 0x21, 0x20, 0x85, 0x00,
-0x23, 0x30, 0x44, 0x00, 0xCE, 0x00, 0xC0, 0x14, 0x23, 0x38, 0x46, 0x00,
-0x2B, 0x10, 0x0A, 0x01, 0x04, 0x00, 0x40, 0x14, 0x23, 0x20, 0xEC, 0x01,
-0x2B, 0x10, 0xEC, 0x01, 0x05, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x10, 0xE4, 0x01, 0x23, 0x18, 0x48, 0x01, 0x23, 0x50, 0x62, 0x00,
-0x21, 0x78, 0x80, 0x00, 0x04, 0x00, 0x40, 0x12, 0x21, 0xC0, 0xE0, 0x01,
-0x21, 0xC8, 0x40, 0x01, 0x00, 0x00, 0x58, 0xAE, 0x04, 0x00, 0x59, 0xAE,
-0x00, 0x00, 0xA2, 0x8F, 0x04, 0x00, 0xA3, 0x8F, 0x10, 0x00, 0xB2, 0x8F,
-0x0C, 0x00, 0xB1, 0x8F, 0x08, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x53, 0x00, 0xC0, 0x10, 0x01, 0x00, 0x02, 0x24,
-0xFF, 0xFF, 0x02, 0x34, 0x2B, 0x10, 0x4C, 0x00, 0x59, 0x00, 0x40, 0x14,
-0xFF, 0x00, 0x02, 0x3C, 0x00, 0x01, 0x83, 0x2D, 0x08, 0x00, 0x02, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x0A, 0x28, 0x43, 0x00, 0x06, 0x10, 0xAC, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x98, 0xF2, 0x63, 0x24, 0x21, 0x10, 0x43, 0x00,
-0x00, 0x00, 0x44, 0x90, 0x20, 0x00, 0x02, 0x24, 0x21, 0x20, 0x85, 0x00,
-0x23, 0x30, 0x44, 0x00, 0x5B, 0x00, 0xC0, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x23, 0x50, 0x4C, 0x01, 0x02, 0x4C, 0x0C, 0x00, 0xFF, 0xFF, 0x8D, 0x31,
-0x1B, 0x00, 0x49, 0x01, 0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0x02, 0x24, 0x0F, 0x00, 0x12, 0x18, 0x00, 0x00,
-0x10, 0x28, 0x00, 0x00, 0x00, 0x14, 0x05, 0x00, 0x25, 0x28, 0x44, 0x00,
-0x18, 0x00, 0x6D, 0x00, 0x12, 0x58, 0x00, 0x00, 0x2B, 0x18, 0xAB, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x49, 0x01, 0x02, 0x00, 0x20, 0x15,
-0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00, 0x08, 0x00, 0x60, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x28, 0xAC, 0x00, 0x2B, 0x10, 0xAC, 0x00,
-0x04, 0x00, 0x40, 0x14, 0x2B, 0x10, 0xAB, 0x00, 0x00, 0x00, 0x42, 0x38,
-0x21, 0x18, 0xAC, 0x00, 0x0B, 0x28, 0x62, 0x00, 0x23, 0x28, 0xAB, 0x00,
-0x1B, 0x00, 0xA9, 0x00, 0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xE4, 0x31, 0x12, 0x18, 0x00, 0x00,
-0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x00, 0x6D, 0x00, 0x00, 0x14, 0x08, 0x00, 0x12, 0x58, 0x00, 0x00,
-0x25, 0x40, 0x44, 0x00, 0x2B, 0x18, 0x0B, 0x01, 0x1B, 0x00, 0xA9, 0x00,
-0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00,
-0x08, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x21, 0x40, 0x0C, 0x01,
-0x2B, 0x10, 0x0C, 0x01, 0x04, 0x00, 0x40, 0x14, 0x2B, 0x10, 0x0B, 0x01,
-0x21, 0x18, 0x0C, 0x01, 0x00, 0x00, 0x42, 0x38, 0x0B, 0x40, 0x62, 0x00,
-0xAB, 0xFF, 0x40, 0x12, 0x23, 0x78, 0x0B, 0x01, 0x06, 0xC0, 0xCF, 0x00,
-0x21, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x58, 0xAE, 0xA1, 0x63, 0x00, 0x08,
-0x04, 0x00, 0x59, 0xAE, 0x1B, 0x00, 0x47, 0x00, 0x02, 0x00, 0xE0, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0x02, 0x34,
-0x12, 0x60, 0x00, 0x00, 0x2B, 0x10, 0x4C, 0x00, 0xAB, 0xFF, 0x40, 0x10,
-0x00, 0x01, 0x83, 0x2D, 0xFF, 0x00, 0x02, 0x3C, 0x10, 0x00, 0x03, 0x24,
-0xFF, 0xFF, 0x42, 0x34, 0x2B, 0x10, 0x4C, 0x00, 0x18, 0x00, 0x04, 0x24,
-0x21, 0x28, 0x60, 0x00, 0x0B, 0x28, 0x82, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x06, 0x10, 0xAC, 0x00, 0x98, 0xF2, 0x63, 0x24, 0x21, 0x10, 0x43, 0x00,
-0x00, 0x00, 0x44, 0x90, 0x20, 0x00, 0x02, 0x24, 0x21, 0x20, 0x85, 0x00,
-0x23, 0x30, 0x44, 0x00, 0xA7, 0xFF, 0xC0, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x23, 0x38, 0x46, 0x00, 0x04, 0x60, 0xCC, 0x00, 0x06, 0x58, 0xEA, 0x00,
-0x02, 0x4C, 0x0C, 0x00, 0x1B, 0x00, 0x69, 0x01, 0x02, 0x00, 0x20, 0x15,
-0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0x8D, 0x31,
-0x06, 0x18, 0xEF, 0x00, 0x04, 0x10, 0xCA, 0x00, 0x25, 0x50, 0x43, 0x00,
-0x02, 0x24, 0x0A, 0x00, 0x12, 0x28, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00,
-0x00, 0x14, 0x08, 0x00, 0x25, 0x40, 0x44, 0x00, 0x18, 0x00, 0xAD, 0x00,
-0x12, 0x28, 0x00, 0x00, 0x2B, 0x18, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
-0x1B, 0x00, 0x69, 0x01, 0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0x05, 0x00, 0x60, 0x10, 0x04, 0x78, 0xCF, 0x00,
-0x21, 0x40, 0x0C, 0x01, 0x2B, 0x10, 0x0C, 0x01, 0x93, 0x00, 0x40, 0x10,
-0x2B, 0x10, 0x05, 0x01, 0x23, 0x40, 0x05, 0x01, 0x1B, 0x00, 0x09, 0x01,
-0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00,
-0xFF, 0xFF, 0x44, 0x31, 0x12, 0x18, 0x00, 0x00, 0x10, 0x58, 0x00, 0x00,
-0x00, 0x14, 0x0B, 0x00, 0x25, 0x58, 0x44, 0x00, 0x18, 0x00, 0x6D, 0x00,
-0x12, 0x28, 0x00, 0x00, 0x2B, 0x18, 0x65, 0x01, 0x00, 0x00, 0x00, 0x00,
-0x1B, 0x00, 0x09, 0x01, 0x02, 0x00, 0x20, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0x77, 0xFF, 0x60, 0x10, 0x23, 0x50, 0x65, 0x01,
-0x21, 0x58, 0x6C, 0x01, 0x2B, 0x10, 0x6C, 0x01, 0x04, 0x00, 0x40, 0x14,
-0x2B, 0x10, 0x65, 0x01, 0x00, 0x00, 0x42, 0x38, 0x21, 0x18, 0x6C, 0x01,
-0x0B, 0x58, 0x62, 0x00, 0xBF, 0x63, 0x00, 0x08, 0x23, 0x50, 0x65, 0x01,
-0x08, 0x00, 0x02, 0x24, 0x21, 0x28, 0x00, 0x00, 0x0A, 0x28, 0x43, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x06, 0x10, 0xA8, 0x00, 0x98, 0xF2, 0x63, 0x24,
-0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x90, 0x20, 0x00, 0x02, 0x24,
-0x21, 0x20, 0x85, 0x00, 0x23, 0x30, 0x44, 0x00, 0x34, 0xFF, 0xC0, 0x10,
-0x23, 0x38, 0x46, 0x00, 0x06, 0x10, 0xEC, 0x00, 0x04, 0x18, 0xC8, 0x00,
-0x25, 0x40, 0x62, 0x00, 0x06, 0x58, 0xEA, 0x00, 0x02, 0x6C, 0x08, 0x00,
-0x1B, 0x00, 0x6D, 0x01, 0x02, 0x00, 0xA0, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0x11, 0x31, 0x06, 0x10, 0xEF, 0x00,
-0x04, 0x18, 0xCA, 0x00, 0x25, 0x50, 0x62, 0x00, 0x02, 0x24, 0x0A, 0x00,
-0x04, 0x60, 0xCC, 0x00, 0x12, 0x80, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00,
-0x00, 0x14, 0x09, 0x00, 0x25, 0x48, 0x44, 0x00, 0x12, 0x28, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x11, 0x02,
-0x12, 0x70, 0x00, 0x00, 0x2B, 0x18, 0x2E, 0x01, 0x00, 0x00, 0x00, 0x00,
-0x1B, 0x00, 0x6D, 0x01, 0x02, 0x00, 0xA0, 0x15, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x07, 0x00, 0x0A, 0x00, 0x60, 0x10, 0x04, 0x78, 0xCF, 0x00,
-0x21, 0x48, 0x28, 0x01, 0x2B, 0x10, 0x28, 0x01, 0x06, 0x00, 0x40, 0x14,
-0xFF, 0xFF, 0xB0, 0x24, 0x2B, 0x10, 0x2E, 0x01, 0x03, 0x00, 0x40, 0x10,
-0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x26, 0x21, 0x48, 0x28, 0x01,
-0x23, 0x48, 0x2E, 0x01, 0x1B, 0x00, 0x2D, 0x01, 0x02, 0x00, 0xA0, 0x15,
-0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0x44, 0x31,
-0x12, 0x28, 0x00, 0x00, 0x10, 0x58, 0x00, 0x00, 0x00, 0x14, 0x0B, 0x00,
-0x25, 0x58, 0x44, 0x00, 0x18, 0x00, 0xB1, 0x00, 0x12, 0x70, 0x00, 0x00,
-0x2B, 0x18, 0x6E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x2D, 0x01,
-0x02, 0x00, 0xA0, 0x15, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x07, 0x00,
-0x0B, 0x00, 0x60, 0x10, 0x00, 0x14, 0x10, 0x00, 0x21, 0x58, 0x68, 0x01,
-0x2B, 0x10, 0x68, 0x01, 0x06, 0x00, 0x40, 0x14, 0xFF, 0xFF, 0xA5, 0x24,
-0x2B, 0x10, 0x6E, 0x01, 0x04, 0x00, 0x40, 0x10, 0x00, 0x14, 0x10, 0x00,
-0xFF, 0xFF, 0xA5, 0x24, 0x21, 0x58, 0x68, 0x01, 0x00, 0x14, 0x10, 0x00,
-0x25, 0x10, 0x45, 0x00, 0x23, 0x58, 0x6E, 0x01, 0x19, 0x00, 0x4C, 0x00,
-0x10, 0x28, 0x00, 0x00, 0x2B, 0x18, 0x65, 0x01, 0x12, 0x48, 0x00, 0x00,
-0x05, 0x00, 0x60, 0x14, 0x23, 0x20, 0x2C, 0x01, 0x07, 0x00, 0xAB, 0x14,
-0x2B, 0x10, 0xE9, 0x01, 0x05, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00,
-0x2B, 0x10, 0x24, 0x01, 0x23, 0x18, 0xA8, 0x00, 0x23, 0x28, 0x62, 0x00,
-0x21, 0x48, 0x80, 0x00, 0xEA, 0xFE, 0x40, 0x12, 0x23, 0x18, 0xE9, 0x01,
-0x23, 0x20, 0x65, 0x01, 0x2B, 0x10, 0xE3, 0x01, 0x23, 0x50, 0x82, 0x00,
-0x04, 0x28, 0xEA, 0x00, 0x06, 0x18, 0xC3, 0x00, 0x25, 0xC0, 0xA3, 0x00,
-0x06, 0xC8, 0xCA, 0x00, 0x00, 0x00, 0x58, 0xAE, 0xA1, 0x63, 0x00, 0x08,
-0x04, 0x00, 0x59, 0xAE, 0x00, 0x01, 0xC3, 0x2C, 0x08, 0x00, 0x02, 0x24,
-0x21, 0x30, 0x00, 0x00, 0x3B, 0x63, 0x00, 0x08, 0x0A, 0x30, 0x43, 0x00,
-0x00, 0x00, 0x42, 0x38, 0x21, 0x18, 0x0C, 0x01, 0x35, 0x64, 0x00, 0x08,
-0x0B, 0x40, 0x62, 0x00, 0x25, 0xB0, 0x03, 0x3C, 0x4D, 0x00, 0x64, 0x34,
-0xF1, 0x02, 0x65, 0x34, 0x08, 0x00, 0x02, 0x24, 0x00, 0x00, 0x80, 0xA0,
-0xEC, 0x02, 0x66, 0x34, 0x00, 0x00, 0xA2, 0xA0, 0xF0, 0x02, 0x63, 0x34,
-0xFF, 0x00, 0x02, 0x3C, 0x00, 0x00, 0x60, 0xA0, 0x00, 0x00, 0xC2, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x60, 0x93, 0x63, 0x24, 0x18, 0x03, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x7F, 0x00, 0x02, 0x3C, 0x0D, 0xB8, 0x44, 0x34, 0x80, 0x04, 0x03, 0x3C,
-0x25, 0x20, 0x83, 0x00, 0x00, 0x08, 0x02, 0x3C, 0x25, 0x20, 0x82, 0x00,
-0x00, 0x30, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0x25, 0x20, 0x83, 0x00, 0x41, 0xB0, 0x03, 0x3C, 0x00, 0x00, 0x64, 0xAC,
-0xD8, 0x1B, 0x44, 0xAC, 0xD0, 0x1B, 0x44, 0xAC, 0x08, 0x00, 0x63, 0x34,
-0x86, 0x00, 0x04, 0x24, 0x00, 0x00, 0x64, 0xA4, 0xDC, 0x1B, 0x44, 0xA4,
-0xD4, 0x1B, 0x40, 0xAC, 0xDE, 0x1B, 0x40, 0xA4, 0x08, 0x00, 0xE0, 0x03,
-0xE0, 0x1B, 0x44, 0xA4, 0xF5, 0x64, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x42, 0xB0, 0x03, 0x3C, 0x01, 0x00, 0x63, 0x34, 0x02, 0x00, 0x02, 0x24,
-0xE8, 0xFF, 0xBD, 0x27, 0x00, 0x00, 0x62, 0xA0, 0x10, 0x00, 0xBF, 0xAF,
-0x85, 0x2B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x00, 0x00,
-0x01, 0x00, 0x05, 0x24, 0xB9, 0x20, 0x00, 0x0C, 0x00, 0x50, 0x06, 0x24,
-0x1F, 0x00, 0x06, 0x3C, 0x10, 0x00, 0xBF, 0x8F, 0x00, 0x40, 0xC6, 0x34,
-0x03, 0x00, 0x04, 0x24, 0x01, 0x00, 0x05, 0x24, 0xB9, 0x20, 0x00, 0x08,
-0x18, 0x00, 0xBD, 0x27, 0x25, 0xB0, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0xC8, 0xFF, 0xBD, 0x27, 0x18, 0x03, 0x64, 0x34, 0x28, 0x94, 0x42, 0x24,
-0x00, 0x00, 0x82, 0xAC, 0x30, 0x00, 0xBE, 0xAF, 0x2C, 0x00, 0xB7, 0xAF,
-0x28, 0x00, 0xB6, 0xAF, 0x24, 0x00, 0xB5, 0xAF, 0x20, 0x00, 0xB4, 0xAF,
-0x1C, 0x00, 0xB3, 0xAF, 0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF,
-0x34, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF, 0xB6, 0x00, 0x63, 0x34,
-0x00, 0x00, 0x64, 0x90, 0x02, 0x80, 0x03, 0x3C, 0x60, 0x1B, 0x62, 0x24,
-0x48, 0x01, 0x03, 0x24, 0x70, 0x37, 0x43, 0xAC, 0x6C, 0x37, 0x43, 0xAC,
-0xAB, 0x1B, 0x44, 0xA0, 0xC6, 0x3D, 0x40, 0xA0, 0x66, 0x37, 0x40, 0xA0,
-0x84, 0x6C, 0x00, 0x0C, 0x21, 0x98, 0x40, 0x00, 0xFD, 0xFF, 0x02, 0x3C,
-0xFB, 0xFF, 0x03, 0x3C, 0x21, 0xA0, 0x60, 0x02, 0xFF, 0xFF, 0x55, 0x34,
-0xFF, 0xFF, 0x76, 0x34, 0x21, 0x88, 0x00, 0x00, 0x02, 0x80, 0x1E, 0x3C,
-0x02, 0x80, 0x17, 0x3C, 0x21, 0x90, 0x60, 0x02, 0x40, 0x10, 0x11, 0x00,
-0x21, 0x10, 0x51, 0x00, 0x00, 0x11, 0x02, 0x00, 0x21, 0x10, 0x53, 0x00,
-0xD4, 0x1D, 0x42, 0x24, 0x07, 0x00, 0x03, 0x24, 0xFF, 0xFF, 0x63, 0x24,
-0x00, 0x00, 0x40, 0xA4, 0xFD, 0xFF, 0x61, 0x04, 0x02, 0x00, 0x42, 0x24,
-0xC0, 0x80, 0x11, 0x00, 0x34, 0x3F, 0xC4, 0x27, 0x21, 0x20, 0x04, 0x02,
-0x21, 0x28, 0x00, 0x00, 0x02, 0x00, 0x06, 0x24, 0xE4, 0x1D, 0x40, 0xA6,
-0xEC, 0x54, 0x00, 0x0C, 0xE6, 0x1D, 0x40, 0xA2, 0x21, 0x20, 0x13, 0x02,
-0xD4, 0x23, 0x83, 0x8C, 0xD2, 0x5C, 0xE7, 0x92, 0xBF, 0xFF, 0x02, 0x24,
-0x24, 0x28, 0x62, 0x00, 0x01, 0x00, 0x02, 0x24, 0x63, 0x00, 0xE2, 0x10,
-0x80, 0x07, 0xA6, 0x34, 0xFF, 0xF7, 0x03, 0x24, 0x24, 0x10, 0xC3, 0x00,
-0xFF, 0xEF, 0x03, 0x24, 0x24, 0x10, 0x43, 0x00, 0xD4, 0x23, 0x82, 0xAC,
-0x21, 0x30, 0x14, 0x02, 0xD4, 0x23, 0xC4, 0x8C, 0xE7, 0xFF, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x24, 0x20, 0x95, 0x00, 0x24, 0x20, 0x96, 0x00,
-0xFF, 0xFD, 0x03, 0x3C, 0x24, 0x20, 0x82, 0x00, 0xFF, 0xFF, 0x63, 0x34,
-0xFF, 0xFB, 0x02, 0x3C, 0x24, 0x20, 0x83, 0x00, 0xD8, 0x23, 0xC5, 0x8C,
-0xFF, 0xFF, 0x42, 0x34, 0xFF, 0xE7, 0x03, 0x3C, 0x24, 0x20, 0x82, 0x00,
-0xFF, 0xFF, 0x63, 0x34, 0xFF, 0xFF, 0x02, 0x3C, 0x24, 0x20, 0x83, 0x00,
-0xFF, 0x7F, 0x42, 0x34, 0xC0, 0xFF, 0x03, 0x24, 0x24, 0x28, 0xA2, 0x00,
-0x24, 0x20, 0x83, 0x00, 0x1F, 0x00, 0x02, 0x3C, 0x01, 0x00, 0x31, 0x26,
-0x25, 0x28, 0xA2, 0x00, 0x08, 0x00, 0x84, 0x34, 0x20, 0x00, 0x22, 0x2A,
-0xD4, 0x23, 0xC4, 0xAC, 0xD8, 0x23, 0xC5, 0xAC, 0xC3, 0xFF, 0x40, 0x14,
-0x30, 0x00, 0x52, 0x26, 0x25, 0xB0, 0x02, 0x3C, 0x10, 0x00, 0x03, 0x24,
-0xB0, 0x03, 0x42, 0x34, 0x02, 0x80, 0x04, 0x3C, 0x00, 0x00, 0x43, 0xAC,
-0x88, 0x1E, 0x84, 0x24, 0x21, 0x28, 0x00, 0x00, 0xEC, 0x54, 0x00, 0x0C,
-0x20, 0x00, 0x06, 0x24, 0x02, 0x80, 0x02, 0x3C, 0xD1, 0x5C, 0x43, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x3A, 0x00, 0x60, 0x10, 0x02, 0x80, 0x03, 0x3C,
-0x60, 0x1B, 0x62, 0x24, 0x25, 0x03, 0x40, 0xA0, 0xC2, 0x6F, 0x00, 0x74,
-0x24, 0x03, 0x40, 0xA0, 0xD8, 0x70, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x47, 0x6C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0xBF, 0x8F,
-0x30, 0x00, 0xBE, 0x8F, 0x2C, 0x00, 0xB7, 0x8F, 0x28, 0x00, 0xB6, 0x8F,
-0x24, 0x00, 0xB5, 0x8F, 0x20, 0x00, 0xB4, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x02, 0x80, 0x09, 0x3C, 0x02, 0x80, 0x0A, 0x3C, 0x02, 0x80, 0x0B, 0x3C,
-0x02, 0x80, 0x0C, 0x3C, 0x02, 0x80, 0x0D, 0x3C, 0x02, 0x80, 0x0E, 0x3C,
-0x02, 0x80, 0x0F, 0x3C, 0x88, 0x54, 0x22, 0x25, 0x90, 0x54, 0x43, 0x25,
-0x98, 0x54, 0x64, 0x25, 0xA0, 0x54, 0x85, 0x25, 0xA8, 0x54, 0xA6, 0x25,
-0xB0, 0x54, 0xC7, 0x25, 0xB8, 0x54, 0xE8, 0x25, 0x38, 0x00, 0xBD, 0x27,
-0x04, 0x00, 0x42, 0xAC, 0x88, 0x54, 0x22, 0xAD, 0x04, 0x00, 0x63, 0xAC,
-0x90, 0x54, 0x43, 0xAD, 0x04, 0x00, 0x84, 0xAC, 0x98, 0x54, 0x64, 0xAD,
-0x04, 0x00, 0xA5, 0xAC, 0xA0, 0x54, 0x85, 0xAD, 0x04, 0x00, 0xC6, 0xAC,
-0xA8, 0x54, 0xA6, 0xAD, 0x04, 0x00, 0xE7, 0xAC, 0xB0, 0x54, 0xC7, 0xAD,
-0xB8, 0x54, 0xE8, 0xAD, 0x08, 0x00, 0xE0, 0x03, 0x04, 0x00, 0x08, 0xAD,
-0x02, 0x80, 0x02, 0x3C, 0xD3, 0x5C, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x9C, 0xFF, 0x67, 0x14, 0x80, 0x0F, 0xA2, 0x34, 0xFF, 0xF7, 0x03, 0x24,
-0x24, 0x10, 0xC3, 0x00, 0x4D, 0x65, 0x00, 0x08, 0x00, 0x10, 0x42, 0x34,
-0x7A, 0x6D, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0xAD, 0x6F, 0x00, 0x74,
-0x24, 0x39, 0x80, 0xAE, 0x26, 0x70, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0xC6, 0x5C, 0x64, 0x90, 0x92, 0x00, 0x02, 0x24,
-0x03, 0x00, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x60, 0x70, 0x00, 0x74,
-0x00, 0x00, 0x00, 0x00, 0xC1, 0x70, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00,
-0x7B, 0x65, 0x00, 0x08, 0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0xC8, 0xFF, 0xBD, 0x27, 0x14, 0x97, 0x63, 0x24,
-0x18, 0x03, 0x42, 0x34, 0x18, 0x00, 0xB0, 0xAF, 0x34, 0x00, 0xBF, 0xAF,
-0x30, 0x00, 0xB6, 0xAF, 0x2C, 0x00, 0xB5, 0xAF, 0x28, 0x00, 0xB4, 0xAF,
-0x24, 0x00, 0xB3, 0xAF, 0x20, 0x00, 0xB2, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x00, 0x00, 0x43, 0xAC, 0x21, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x26,
-0xFF, 0xFF, 0x50, 0x30, 0x64, 0x00, 0x03, 0x2E, 0xFD, 0xFF, 0x60, 0x14,
-0x01, 0x00, 0x02, 0x26, 0x64, 0x40, 0x00, 0x0C, 0x02, 0x80, 0x14, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0xC3, 0x5C, 0x68, 0x90, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0xC0, 0x5C, 0x4B, 0x94, 0xDB, 0x5C, 0x6A, 0x90,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0xE2, 0x5C, 0x67, 0x90,
-0xD0, 0x5C, 0x49, 0x90, 0xC2, 0x5C, 0x83, 0x92, 0x02, 0x80, 0x0C, 0x3C,
-0x02, 0x80, 0x02, 0x3C, 0xDD, 0x5C, 0x46, 0x90, 0xE0, 0x5C, 0x85, 0x91,
-0x25, 0xB0, 0x04, 0x3C, 0xB0, 0x03, 0x82, 0x34, 0x00, 0x00, 0x4B, 0xAC,
-0x00, 0x00, 0x48, 0xAC, 0x00, 0x00, 0x49, 0xAC, 0x00, 0x00, 0x43, 0xAC,
-0x02, 0x80, 0x03, 0x3C, 0x00, 0x00, 0x4A, 0xAC, 0x0A, 0x00, 0x88, 0x34,
-0x00, 0x00, 0x46, 0xAC, 0x00, 0x00, 0x45, 0xAC, 0x00, 0x00, 0x47, 0xAC,
-0x0C, 0x5D, 0x60, 0xA4, 0x00, 0x00, 0x06, 0x91, 0x02, 0x80, 0x02, 0x3C,
-0x0B, 0x00, 0x04, 0x24, 0x02, 0x80, 0x13, 0x3C, 0xCD, 0x5C, 0x44, 0xA0,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x65, 0x26, 0x00, 0x70, 0x03, 0x24,
-0xF0, 0x5C, 0x40, 0xA0, 0xF0, 0xFF, 0x02, 0x24, 0x01, 0x00, 0x07, 0x24,
-0x02, 0x80, 0x16, 0x3C, 0xAC, 0x1B, 0xA3, 0xA4, 0xAA, 0x1B, 0xA2, 0xA0,
-0xFF, 0x07, 0x03, 0x24, 0xFF, 0xFF, 0x02, 0x24, 0x20, 0x00, 0xC6, 0x30,
-0xE0, 0x5C, 0x87, 0xA1, 0xA8, 0x1B, 0xA7, 0xA0, 0xAE, 0x1B, 0xA3, 0xA4,
-0x48, 0xF5, 0xC2, 0xA2, 0x9A, 0x00, 0xC0, 0x10, 0xB0, 0x1B, 0xA0, 0xA4,
-0x00, 0x00, 0x02, 0x91, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x42, 0x30,
-0x0B, 0x01, 0x40, 0x14, 0x02, 0x80, 0x15, 0x3C, 0x21, 0x80, 0x00, 0x00,
-0x21, 0x88, 0x00, 0x00, 0x98, 0xF3, 0xB2, 0x26, 0xFF, 0x00, 0x24, 0x32,
-0xCF, 0x59, 0x00, 0x0C, 0x21, 0x28, 0x12, 0x02, 0x08, 0x00, 0x03, 0x26,
-0xFF, 0xFF, 0x70, 0x30, 0x01, 0x00, 0x22, 0x26, 0x80, 0x00, 0x03, 0x2E,
-0xF8, 0xFF, 0x60, 0x14, 0xFF, 0xFF, 0x51, 0x30, 0xC2, 0x5C, 0x83, 0x92,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x62, 0x30, 0xCA, 0x00, 0x40, 0x14,
-0x04, 0x00, 0x62, 0x30, 0x83, 0x00, 0x40, 0x10, 0x25, 0xB0, 0x03, 0x3C,
-0x25, 0xB0, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0x50, 0x00, 0x84, 0x34,
-0xE7, 0xF3, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24,
-0x98, 0xF3, 0xA3, 0x26, 0x7B, 0x00, 0x67, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x02, 0x00, 0xE2, 0x2C, 0x04, 0x00, 0x40, 0x14, 0x02, 0x00, 0x0B, 0x24,
-0x79, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x4B, 0x30,
-0x04, 0x00, 0xE2, 0x2C, 0xEC, 0x00, 0x40, 0x10, 0x98, 0xF3, 0xA2, 0x26,
-0x60, 0x1B, 0x62, 0x8E, 0xBF, 0xFF, 0x03, 0x24, 0x02, 0x80, 0x12, 0x3C,
-0x24, 0x10, 0x43, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x4A, 0xF5, 0x60, 0xA0,
-0x60, 0x1B, 0x62, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0xCF, 0x5C, 0x43, 0x90,
-0x01, 0x00, 0x02, 0x24, 0x02, 0x00, 0x62, 0x10, 0xFC, 0xFF, 0x08, 0x24,
-0x21, 0x40, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x98, 0xF3, 0x4A, 0x24, 0x60, 0x1B, 0x69, 0x24, 0x21, 0x60, 0x00, 0x00,
-0x21, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x26, 0x21, 0x30, 0x30, 0x01,
-0x03, 0x00, 0x03, 0x2E, 0x08, 0x00, 0x04, 0x2E, 0xFF, 0xFF, 0x50, 0x30,
-0x0E, 0x00, 0x07, 0x2E, 0x04, 0x00, 0x60, 0x14, 0x21, 0x88, 0x00, 0x00,
-0x01, 0x00, 0x11, 0x24, 0x02, 0x00, 0x02, 0x24, 0x0A, 0x88, 0x44, 0x00,
-0x21, 0x10, 0x51, 0x01, 0x61, 0x00, 0x43, 0x90, 0x55, 0x00, 0x44, 0x90,
-0x5B, 0x00, 0x45, 0x90, 0x21, 0x18, 0x03, 0x01, 0x21, 0x20, 0x04, 0x01,
-0x21, 0x28, 0x05, 0x01, 0x9C, 0x1D, 0xC3, 0xA0, 0x64, 0x1D, 0xC4, 0xA0,
-0xEB, 0xFF, 0xE0, 0x14, 0x80, 0x1D, 0xC5, 0xA0, 0x01, 0x00, 0x8C, 0x25,
-0x02, 0x00, 0x82, 0x2D, 0x0E, 0x00, 0x29, 0x25, 0xE5, 0xFF, 0x40, 0x14,
-0x03, 0x00, 0x4A, 0x25, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x60, 0x1B, 0x47, 0x24, 0x98, 0xF3, 0x66, 0x24, 0x21, 0x80, 0x00, 0x00,
-0x03, 0x00, 0x02, 0x2E, 0x21, 0x20, 0x07, 0x02, 0xD1, 0x00, 0x40, 0x10,
-0x08, 0x00, 0x03, 0x2E, 0x71, 0x00, 0xC3, 0x90, 0x6E, 0x00, 0xC2, 0x90,
-0x00, 0x00, 0x00, 0x00, 0xC6, 0x1D, 0x82, 0xA0, 0xB8, 0x1D, 0x83, 0xA0,
-0x01, 0x00, 0x02, 0x26, 0xFF, 0xFF, 0x50, 0x30, 0x0E, 0x00, 0x03, 0x2E,
-0xF4, 0xFF, 0x60, 0x14, 0x03, 0x00, 0x02, 0x2E, 0x03, 0x00, 0x02, 0x24,
-0x51, 0x00, 0x62, 0x15, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x98, 0xF3, 0x4E, 0x24, 0xC0, 0xD9, 0x6F, 0x24, 0x21, 0x60, 0x00, 0x00,
-0x21, 0x68, 0x00, 0x00, 0x21, 0x10, 0xAE, 0x01, 0x74, 0x00, 0x43, 0x90,
-0x21, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x6A, 0x30, 0x02, 0x49, 0x03, 0x00,
-0x21, 0x10, 0xB0, 0x01, 0x00, 0x11, 0x02, 0x00, 0x21, 0x58, 0x4F, 0x00,
-0x21, 0x38, 0x00, 0x00, 0x21, 0x40, 0x67, 0x01, 0x00, 0x00, 0x03, 0x91,
-0x00, 0x31, 0x09, 0x00, 0x01, 0x00, 0xE7, 0x24, 0x02, 0x11, 0x03, 0x00,
-0x00, 0x21, 0x02, 0x00, 0x0F, 0x00, 0x63, 0x30, 0x2B, 0x10, 0x49, 0x00,
-0x0A, 0x20, 0xC2, 0x00, 0x2B, 0x28, 0x6A, 0x00, 0x00, 0x00, 0xA5, 0x38,
-0x25, 0x18, 0x83, 0x00, 0xFF, 0xFF, 0xE7, 0x30, 0x25, 0x20, 0x8A, 0x00,
-0x0A, 0x18, 0x85, 0x00, 0x10, 0x00, 0xE2, 0x2C, 0xEF, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x03, 0xA1, 0x01, 0x00, 0x02, 0x26, 0xFF, 0xFF, 0x50, 0x30,
-0x03, 0x00, 0x03, 0x2E, 0xE7, 0xFF, 0x60, 0x14, 0x21, 0x10, 0xB0, 0x01,
-0x01, 0x00, 0x8C, 0x25, 0x02, 0x00, 0x82, 0x2D, 0xDD, 0xFF, 0x40, 0x14,
-0x03, 0x00, 0xAD, 0x25, 0xCC, 0x66, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x03, 0x3C, 0x4C, 0x87, 0x02, 0x3C, 0x54, 0x00, 0x65, 0x34,
-0x00, 0xE0, 0x42, 0x34, 0x50, 0x00, 0x63, 0x34, 0x00, 0x00, 0x62, 0xAC,
-0x12, 0x01, 0x04, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x00, 0x00, 0xA4, 0xAC,
-0x60, 0x1B, 0x46, 0x24, 0x21, 0x60, 0x00, 0x00, 0x10, 0x00, 0x05, 0x24,
-0x21, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x26, 0x21, 0x18, 0xD0, 0x00,
-0xFF, 0xFF, 0x50, 0x30, 0x0E, 0x00, 0x04, 0x2E, 0x80, 0x1D, 0x65, 0xA0,
-0x64, 0x1D, 0x65, 0xA0, 0xF9, 0xFF, 0x80, 0x14, 0x9C, 0x1D, 0x65, 0xA0,
-0x01, 0x00, 0x8C, 0x25, 0x02, 0x00, 0x82, 0x2D, 0xF4, 0xFF, 0x40, 0x14,
-0x0E, 0x00, 0xC6, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x46, 0x24,
-0x21, 0x80, 0x00, 0x00, 0x04, 0x00, 0x05, 0x24, 0x01, 0x00, 0x02, 0x26,
-0x21, 0x18, 0x06, 0x02, 0xFF, 0xFF, 0x50, 0x30, 0x0E, 0x00, 0x04, 0x2E,
-0xC6, 0x1D, 0x60, 0xA0, 0xFA, 0xFF, 0x80, 0x14, 0xB8, 0x1D, 0x65, 0xA0,
-0x02, 0x80, 0x12, 0x3C, 0xC6, 0x5C, 0x43, 0x92, 0x01, 0x00, 0x04, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x54, 0x59, 0x00, 0x0C, 0x4B, 0xF5, 0x43, 0xA0,
-0x48, 0xF5, 0xC5, 0x26, 0xFF, 0x58, 0x00, 0x0C, 0xFA, 0x01, 0x04, 0x24,
-0x54, 0x59, 0x00, 0x0C, 0x21, 0x20, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x25, 0xB0, 0x05, 0x3C, 0x48, 0x37, 0x84, 0x24, 0x50, 0x00, 0xA5, 0x34,
-0xF4, 0x54, 0x00, 0x0C, 0x06, 0x00, 0x06, 0x24, 0x60, 0x1B, 0x65, 0x26,
-0x01, 0x00, 0x02, 0x24, 0x06, 0x00, 0x03, 0x24, 0x05, 0x00, 0x04, 0x24,
-0x33, 0x1C, 0xA2, 0xA0, 0x6F, 0x58, 0x00, 0x0C, 0xC4, 0x3D, 0xA3, 0xA0,
-0x34, 0x00, 0xBF, 0x8F, 0x30, 0x00, 0xB6, 0x8F, 0x2C, 0x00, 0xB5, 0x8F,
-0x28, 0x00, 0xB4, 0x8F, 0x24, 0x00, 0xB3, 0x8F, 0x20, 0x00, 0xB2, 0x8F,
-0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x38, 0x00, 0xBD, 0x27, 0x25, 0xB0, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x50, 0x00, 0x84, 0x34, 0xAA, 0xF3, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C,
-0x06, 0x00, 0x06, 0x24, 0x98, 0xF3, 0xA2, 0x92, 0x98, 0xF3, 0xA5, 0x26,
-0x01, 0x00, 0xA4, 0x90, 0x21, 0x18, 0x40, 0x00, 0x10, 0x00, 0xA2, 0xA3,
-0x29, 0x00, 0x02, 0x24, 0x11, 0x00, 0xA4, 0xA3, 0x50, 0x00, 0xA7, 0x90,
-0x4F, 0x00, 0x62, 0x10, 0x02, 0x80, 0x12, 0x3C, 0x98, 0xF3, 0xA6, 0x26,
-0x68, 0x00, 0xC2, 0x90, 0x02, 0x80, 0x03, 0x3C, 0x04, 0x00, 0xE4, 0x2C,
-0x1F, 0x00, 0x42, 0x30, 0x34, 0x00, 0x80, 0x14, 0x49, 0xF5, 0x62, 0xA0,
-0x7A, 0x00, 0xC4, 0x90, 0x60, 0x1B, 0x65, 0x8E, 0x79, 0x00, 0xC6, 0x90,
-0x01, 0x00, 0x83, 0x30, 0xBF, 0xFF, 0x02, 0x24, 0x24, 0x28, 0xA2, 0x00,
-0x80, 0x19, 0x03, 0x00, 0x04, 0x00, 0x84, 0x30, 0x25, 0x28, 0xA3, 0x00,
-0x83, 0x20, 0x04, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x03, 0x00, 0xCB, 0x30,
-0x4A, 0xF5, 0x44, 0xA0, 0x60, 0x1B, 0x65, 0xAE, 0x06, 0x00, 0xE2, 0x2C,
-0x2C, 0xFF, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x98, 0xF3, 0xA3, 0x26,
-0x69, 0x00, 0x62, 0x90, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x42, 0x30,
-0x26, 0xFF, 0x40, 0x14, 0x02, 0x80, 0x02, 0x3C, 0x45, 0x66, 0x00, 0x08,
-0x21, 0x40, 0x00, 0x00, 0x21, 0x20, 0x00, 0x00, 0x80, 0x00, 0x05, 0x24,
-0xC1, 0x58, 0x00, 0x0C, 0x98, 0xF3, 0xA6, 0x26, 0x1F, 0x66, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x7A, 0x00, 0x43, 0x90, 0x69, 0x00, 0x46, 0x90,
-0x7D, 0x00, 0x44, 0x90, 0x60, 0x1B, 0x65, 0x8E, 0xBF, 0xFF, 0x02, 0x24,
-0x01, 0x00, 0x63, 0x30, 0x24, 0x28, 0xA2, 0x00, 0x01, 0x00, 0xC6, 0x30,
-0x04, 0x00, 0x84, 0x30, 0x80, 0x19, 0x03, 0x00, 0x25, 0x28, 0xA3, 0x00,
-0x83, 0x20, 0x04, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x01, 0x00, 0xC6, 0x2C,
-0x4A, 0xF5, 0x44, 0xA0, 0x60, 0x1B, 0x65, 0xAE, 0x0B, 0xFF, 0xC0, 0x10,
-0x02, 0x80, 0x12, 0x3C, 0x45, 0x66, 0x00, 0x08, 0x21, 0x40, 0x00, 0x00,
-0x60, 0x1B, 0x62, 0x8E, 0xBF, 0xFF, 0x03, 0x24, 0x02, 0x80, 0x04, 0x3C,
-0x24, 0x10, 0x43, 0x00, 0x02, 0x00, 0x0B, 0x24, 0x4A, 0xF5, 0x80, 0xA0,
-0x12, 0x67, 0x00, 0x08, 0x60, 0x1B, 0x62, 0xAE, 0x21, 0x28, 0x07, 0x02,
-0x06, 0x00, 0x60, 0x10, 0x21, 0x20, 0xA0, 0x00, 0x67, 0x00, 0xC3, 0x90,
-0x6F, 0x00, 0xC2, 0x90, 0xB8, 0x1D, 0xA3, 0xA0, 0x74, 0x66, 0x00, 0x08,
-0xC6, 0x1D, 0xA2, 0xA0, 0x72, 0x00, 0xC3, 0x90, 0x70, 0x00, 0xC2, 0x90,
-0x73, 0x66, 0x00, 0x08, 0xC6, 0x1D, 0x82, 0xA0, 0xFF, 0x00, 0x83, 0x30,
-0x81, 0x00, 0x02, 0x24, 0xB0, 0xFF, 0x62, 0x14, 0x98, 0xF3, 0xA6, 0x26,
-0x54, 0x00, 0xA3, 0x90, 0x01, 0x00, 0x02, 0x24, 0x09, 0x00, 0x62, 0x10,
-0x02, 0x00, 0x02, 0x24, 0x04, 0x00, 0x62, 0x10, 0x11, 0x00, 0x02, 0x24,
-0x02, 0x80, 0x12, 0x3C, 0xFE, 0x66, 0x00, 0x08, 0xC6, 0x5C, 0x42, 0xA2,
-0x22, 0x00, 0x02, 0x24, 0xFD, 0x66, 0x00, 0x08, 0xC6, 0x5C, 0x42, 0xA2,
-0x02, 0x80, 0x12, 0x3C, 0x12, 0x00, 0x02, 0x24, 0xFD, 0x66, 0x00, 0x08,
-0xC6, 0x5C, 0x42, 0xA2, 0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB1, 0xAF,
-0x02, 0x80, 0x02, 0x3C, 0x25, 0xB0, 0x11, 0x3C, 0x18, 0x03, 0x23, 0x36,
-0x7C, 0x9D, 0x42, 0x24, 0x20, 0x00, 0xB2, 0xAF, 0x02, 0x80, 0x12, 0x3C,
-0x00, 0x00, 0x62, 0xAC, 0x18, 0x00, 0xB0, 0xAF, 0x24, 0x00, 0xBF, 0xAF,
-0xC5, 0x65, 0x00, 0x0C, 0x60, 0x1B, 0x50, 0x26, 0x08, 0x68, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xA3, 0x6A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x87, 0x6B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xEA, 0x6D, 0x00, 0x74,
-0x00, 0x00, 0x00, 0x00, 0xEF, 0x6A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xC4, 0x3D, 0x04, 0x92, 0x38, 0x0D, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00,
-0xC4, 0x3D, 0x04, 0x92, 0x75, 0x0D, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0xCB, 0x64, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x82, 0x40, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x23, 0x36, 0x00, 0x00, 0x62, 0x94,
-0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x42, 0x34, 0x00, 0x00, 0x62, 0xA4,
-0x0A, 0x65, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x64, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0xF7, 0x64, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x53, 0x6B, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x10, 0x6B, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x3C, 0x68, 0x61, 0x84, 0x24,
-0x70, 0x6B, 0x00, 0x0C, 0x01, 0x00, 0x05, 0x24, 0x00, 0x80, 0x04, 0x3C,
-0xD0, 0x67, 0x84, 0x24, 0x70, 0x6B, 0x00, 0x0C, 0x02, 0x00, 0x05, 0x24,
-0x00, 0x80, 0x04, 0x3C, 0x39, 0x6F, 0x84, 0x24, 0x70, 0x6B, 0x00, 0x0C,
-0x04, 0x00, 0x05, 0x24, 0x44, 0x5C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x01, 0x80, 0x04, 0x3C, 0x6C, 0x83, 0x84, 0x24, 0x70, 0x6B, 0x00, 0x0C,
-0x03, 0x00, 0x05, 0x24, 0x02, 0x80, 0x03, 0x3C, 0xD0, 0x5C, 0x63, 0x90,
-0x00, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x60, 0x10, 0x43, 0x00, 0x22, 0x36,
-0x07, 0x00, 0x02, 0x24, 0x0C, 0x00, 0x62, 0x10, 0x03, 0x00, 0x02, 0x24,
-0x25, 0xB0, 0x04, 0x3C, 0x43, 0x00, 0x85, 0x34, 0x10, 0x02, 0x86, 0x34,
-0x10, 0x00, 0x03, 0x24, 0x00, 0x00, 0xA2, 0xA0, 0xD8, 0x00, 0x84, 0x34,
-0x00, 0x00, 0xC3, 0xA0, 0x00, 0x00, 0x82, 0x90, 0x80, 0xFF, 0x03, 0x24,
-0x25, 0x10, 0x43, 0x00, 0x00, 0x00, 0x82, 0xA0, 0xDF, 0x64, 0x00, 0x0C,
-0x25, 0xB0, 0x10, 0x3C, 0x44, 0x00, 0x03, 0x36, 0x00, 0x00, 0x62, 0x94,
-0x02, 0x80, 0x04, 0x3C, 0x18, 0xE5, 0x84, 0x24, 0xC0, 0x00, 0x42, 0x34,
-0x00, 0x00, 0x62, 0xA4, 0x13, 0x58, 0x00, 0x0C, 0xF2, 0x00, 0x05, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0xC3, 0x5C, 0x45, 0x90, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0x5C, 0xE5, 0x84, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0xC2, 0x5C, 0x45, 0x90, 0xC7, 0x5C, 0x66, 0x90,
-0x02, 0x80, 0x04, 0x3C, 0x13, 0x58, 0x00, 0x0C, 0x6C, 0xE5, 0x84, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0xC6, 0x5C, 0x45, 0x90,
-0x48, 0xF5, 0x66, 0x90, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0xCF, 0x5C, 0x47, 0x90, 0x4A, 0xF5, 0x62, 0x90, 0x02, 0x80, 0x04, 0x3C,
-0x80, 0xE5, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C, 0x10, 0x00, 0xA2, 0xAF,
-0xFA, 0x5B, 0x00, 0x0C, 0x80, 0x0C, 0x04, 0x36, 0x02, 0x80, 0x03, 0x3C,
-0x02, 0x80, 0x04, 0x3C, 0xD1, 0x5C, 0x65, 0x90, 0xCE, 0x5C, 0x86, 0x90,
-0x02, 0x80, 0x04, 0x3C, 0x21, 0x38, 0x40, 0x00, 0x13, 0x58, 0x00, 0x0C,
-0x9C, 0xE5, 0x84, 0x24, 0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0xD3, 0x5C, 0x66, 0x90, 0xD2, 0x5C, 0x45, 0x90, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xB8, 0xE5, 0x84, 0x24, 0x60, 0x1B, 0x42, 0x26,
-0x54, 0x41, 0x46, 0x8C, 0x58, 0x41, 0x45, 0x8C, 0x02, 0x80, 0x04, 0x3C,
-0x13, 0x58, 0x00, 0x0C, 0xCC, 0xE5, 0x84, 0x24, 0x60, 0x1B, 0x46, 0x8E,
-0x02, 0x80, 0x02, 0x3C, 0x49, 0xF5, 0x45, 0x90, 0x82, 0x31, 0x06, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0xEC, 0xE5, 0x84, 0x24, 0x13, 0x58, 0x00, 0x0C,
-0x01, 0x00, 0xC6, 0x30, 0x02, 0x80, 0x04, 0x3C, 0x08, 0x00, 0x84, 0x24,
-0x21, 0x28, 0x00, 0x00, 0x21, 0x30, 0x00, 0x00, 0x76, 0x39, 0x00, 0x0C,
-0x21, 0x38, 0x00, 0x00, 0xF5, 0x64, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x24, 0x00, 0xBF, 0x8F, 0x20, 0x00, 0xB2, 0x8F, 0x1C, 0x00, 0xB1, 0x8F,
-0x18, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0xD8, 0x00, 0x24, 0x36, 0x00, 0x00, 0x40, 0xA0,
-0xB0, 0x67, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0xBD, 0x27,
-0x24, 0x00, 0xB1, 0xAF, 0x44, 0x00, 0xBF, 0xAF, 0x40, 0x00, 0xBE, 0xAF,
-0x3C, 0x00, 0xB7, 0xAF, 0x38, 0x00, 0xB6, 0xAF, 0x34, 0x00, 0xB5, 0xAF,
-0x30, 0x00, 0xB4, 0xAF, 0x2C, 0x00, 0xB3, 0xAF, 0x28, 0x00, 0xB2, 0xAF,
-0x20, 0x00, 0xB0, 0xAF, 0x02, 0x80, 0x02, 0x3C, 0xC2, 0x5C, 0x42, 0x90,
-0x25, 0xB0, 0x11, 0x3C, 0x58, 0x00, 0x25, 0x36, 0x10, 0x00, 0xA2, 0xAF,
-0x4C, 0x81, 0x02, 0x3C, 0x00, 0xE0, 0x42, 0x34, 0x00, 0x00, 0xA2, 0xAC,
-0xFF, 0xFF, 0x04, 0x24, 0x96, 0x01, 0x03, 0x24, 0x28, 0x28, 0x02, 0x24,
-0x5C, 0x00, 0x26, 0x36, 0x60, 0x00, 0x27, 0x36, 0x64, 0x00, 0x28, 0x36,
-0x8A, 0x00, 0x29, 0x36, 0x00, 0x00, 0xC3, 0xAC, 0x00, 0x00, 0xE4, 0xAC,
-0x00, 0x00, 0x04, 0xAD, 0x00, 0x00, 0x22, 0xA5, 0x0E, 0x0E, 0x02, 0x3C,
-0x09, 0x00, 0x03, 0x24, 0x0A, 0x0A, 0x42, 0x34, 0x89, 0x00, 0x2A, 0x36,
-0x8C, 0x00, 0x2B, 0x36, 0x00, 0x00, 0x43, 0xA1, 0x90, 0x00, 0x2C, 0x36,
-0x00, 0x00, 0x62, 0xAD, 0x13, 0x00, 0x03, 0x24, 0x40, 0x00, 0x02, 0x24,
-0x91, 0x00, 0x2D, 0x36, 0x00, 0x00, 0x83, 0xA1, 0x92, 0x00, 0x2E, 0x36,
-0x00, 0x00, 0xA2, 0xA1, 0x3A, 0x01, 0x03, 0x24, 0x21, 0x00, 0x02, 0x24,
-0xB5, 0x00, 0x2F, 0x36, 0x00, 0x00, 0xC3, 0xA5, 0x00, 0x00, 0xE2, 0xA1,
-0x10, 0x00, 0xA2, 0x8F, 0x12, 0x00, 0x03, 0x24, 0x87, 0x01, 0x43, 0x10,
-0x07, 0x07, 0x02, 0x3C, 0x07, 0x07, 0x42, 0x34, 0xA0, 0x00, 0x24, 0x36,
-0x00, 0x00, 0x82, 0xAC, 0xA4, 0x00, 0x25, 0x36, 0x00, 0x07, 0x03, 0x24,
-0x00, 0xC0, 0x02, 0x3C, 0xA8, 0x00, 0x26, 0x36, 0x00, 0x00, 0xA3, 0xAC,
-0x00, 0xC4, 0x42, 0x34, 0x02, 0x80, 0x03, 0x3C, 0x00, 0x00, 0xC2, 0xAC,
-0x60, 0x1B, 0x62, 0x24, 0xAC, 0x1B, 0x45, 0x94, 0xAE, 0x1B, 0x46, 0x94,
-0xAA, 0x1B, 0x42, 0x90, 0x02, 0x80, 0x03, 0x3C, 0x21, 0xB0, 0x07, 0x3C,
-0x14, 0x00, 0xA2, 0xA3, 0xD1, 0x5C, 0x63, 0x90, 0x20, 0xB0, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x18, 0x00, 0xA3, 0xAF, 0x23, 0xB0, 0x03, 0x3C,
-0xFF, 0xFF, 0x63, 0x34, 0x24, 0xB0, 0x08, 0x3C, 0xFF, 0x1F, 0x04, 0x3C,
-0x25, 0xB0, 0x1E, 0x3C, 0xFF, 0xFF, 0x84, 0x34, 0x21, 0x38, 0xA7, 0x00,
-0x21, 0x40, 0xC8, 0x00, 0x21, 0x28, 0xA2, 0x00, 0x21, 0x30, 0xC3, 0x00,
-0x24, 0x40, 0x04, 0x01, 0x24, 0x28, 0xA4, 0x00, 0x24, 0x38, 0xE4, 0x00,
-0x24, 0x30, 0xC4, 0x00, 0x35, 0x00, 0x02, 0x24, 0x20, 0x00, 0xC4, 0x37,
-0x00, 0x00, 0x82, 0xA0, 0x22, 0x00, 0x03, 0x24, 0x09, 0x00, 0x02, 0x24,
-0x03, 0x05, 0xC9, 0x37, 0x60, 0x05, 0xCA, 0x37, 0xAC, 0x00, 0xCB, 0x37,
-0xF8, 0x00, 0xCC, 0x37, 0xB0, 0x00, 0xCD, 0x37, 0x08, 0x01, 0xCE, 0x37,
-0xD8, 0x00, 0xCF, 0x37, 0x00, 0x00, 0x23, 0xA1, 0x00, 0x00, 0x42, 0xA1,
-0x00, 0x00, 0x65, 0xAD, 0x00, 0x00, 0x87, 0xAD, 0x00, 0x00, 0xA6, 0xAD,
-0x00, 0x00, 0xC8, 0xAD, 0x00, 0x00, 0xE0, 0xA1, 0x14, 0x00, 0xA3, 0x93,
-0x25, 0xB0, 0x02, 0x3C, 0xB4, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0xA0,
-0xB6, 0x00, 0xD1, 0x37, 0x04, 0x00, 0x02, 0x24, 0x25, 0xB0, 0x03, 0x3C,
-0x00, 0x00, 0x22, 0xA2, 0xB9, 0x00, 0x63, 0x34, 0xFF, 0xFF, 0x02, 0x24,
-0x00, 0x00, 0x62, 0xA0, 0x25, 0xB0, 0x03, 0x3C, 0x0F, 0x00, 0x02, 0x24,
-0xBA, 0x00, 0x63, 0x34, 0x00, 0x00, 0x62, 0xA4, 0xDC, 0x00, 0xD4, 0x37,
-0xFF, 0xCF, 0x03, 0x24, 0x3F, 0x3F, 0x02, 0x24, 0x16, 0x01, 0xD5, 0x37,
-0x00, 0x00, 0x83, 0xAE, 0x00, 0x00, 0xA2, 0xA6, 0x2F, 0x00, 0x02, 0x3C,
-0x00, 0x10, 0x03, 0x24, 0x17, 0x32, 0x42, 0x34, 0x18, 0x01, 0xD6, 0x37,
-0x1A, 0x01, 0xD7, 0x37, 0xD0, 0x01, 0xD8, 0x37, 0x00, 0x00, 0xC0, 0xA6,
-0x00, 0x00, 0xE3, 0xA6, 0x00, 0x00, 0x02, 0xAF, 0x5E, 0x00, 0x03, 0x3C,
-0x25, 0xB0, 0x02, 0x3C, 0x17, 0x43, 0x63, 0x34, 0xD4, 0x01, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xAC, 0x10, 0x00, 0x02, 0x3C, 0x20, 0x53, 0x42, 0x34,
-0xD8, 0x01, 0xDF, 0x37, 0x00, 0x00, 0xE2, 0xAF, 0x25, 0xB0, 0x02, 0x3C,
-0x44, 0xA4, 0x03, 0x34, 0xDC, 0x01, 0x42, 0x34, 0x00, 0x00, 0x43, 0xAC,
-0x25, 0xB0, 0x03, 0x3C, 0x1A, 0x06, 0x02, 0x24, 0xE0, 0x01, 0x63, 0x34,
-0x00, 0x00, 0x62, 0xA4, 0xC2, 0x00, 0x02, 0x3C, 0x30, 0x30, 0x03, 0x24,
-0x51, 0x10, 0x42, 0x34, 0xF4, 0x01, 0xD0, 0x37, 0xF8, 0x01, 0xD3, 0x37,
-0x00, 0x00, 0x03, 0xA6, 0x00, 0x02, 0xD2, 0x37, 0x00, 0x00, 0x62, 0xAE,
-0x26, 0x00, 0x03, 0x24, 0x03, 0x02, 0xD9, 0x37, 0x04, 0x00, 0x02, 0x24,
-0x00, 0x00, 0x43, 0xA6, 0x00, 0x00, 0x22, 0xA3, 0x18, 0x00, 0xA3, 0x8F,
-0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x60, 0x14, 0x36, 0x02, 0xC2, 0x37,
-0x04, 0x00, 0x03, 0x24, 0x00, 0x00, 0x43, 0xA0, 0x02, 0x80, 0x0B, 0x3C,
-0xC6, 0x5C, 0x66, 0x91, 0x25, 0xB0, 0x09, 0x3C, 0x34, 0x02, 0x23, 0x35,
-0x80, 0x00, 0x02, 0x24, 0x00, 0x00, 0x62, 0xA4, 0x38, 0x02, 0x24, 0x35,
-0x37, 0x02, 0x25, 0x35, 0x07, 0x00, 0x02, 0x24, 0x22, 0x00, 0x03, 0x24,
-0x00, 0x00, 0x80, 0xA0, 0x00, 0x00, 0xA2, 0xA0, 0xE1, 0x00, 0xC3, 0x10,
-0x1B, 0x1B, 0x02, 0x3C, 0x13, 0x13, 0x02, 0x3C, 0x13, 0x13, 0x42, 0x34,
-0x60, 0x01, 0x23, 0x35, 0x64, 0x01, 0x24, 0x35, 0x68, 0x01, 0x25, 0x35,
-0x7C, 0x01, 0x2A, 0x35, 0x6C, 0x01, 0x26, 0x35, 0x70, 0x01, 0x27, 0x35,
-0x74, 0x01, 0x28, 0x35, 0x78, 0x01, 0x29, 0x35, 0x00, 0x00, 0x62, 0xAC,
-0x00, 0x00, 0x82, 0xAC, 0x00, 0x00, 0xA2, 0xAC, 0x00, 0x00, 0xC2, 0xAC,
-0x00, 0x00, 0xE2, 0xAC, 0x00, 0x00, 0x02, 0xAD, 0x00, 0x00, 0x22, 0xAD,
-0x00, 0x00, 0x42, 0xAD, 0xC6, 0x5C, 0x65, 0x91, 0x25, 0xB0, 0x0C, 0x3C,
-0x01, 0x00, 0x03, 0x3C, 0x80, 0x01, 0x82, 0x35, 0x08, 0x5F, 0x63, 0x34,
-0x22, 0x00, 0x04, 0x24, 0x00, 0x00, 0x43, 0xAC, 0xE0, 0x00, 0xA4, 0x10,
-0x0F, 0x1F, 0x02, 0x3C, 0x92, 0x00, 0x02, 0x24, 0xDD, 0x00, 0xA2, 0x10,
-0x0F, 0x1F, 0x02, 0x3C, 0x0F, 0x10, 0x02, 0x3C, 0x00, 0xF0, 0x4F, 0x34,
-0xF7, 0x01, 0x91, 0x35, 0x15, 0xF0, 0x4D, 0x34, 0x77, 0x00, 0x0E, 0x24,
-0x84, 0x01, 0x87, 0x35, 0x88, 0x01, 0x88, 0x35, 0x10, 0xF0, 0x44, 0x34,
-0x8C, 0x01, 0x85, 0x35, 0x05, 0xF0, 0x42, 0x34, 0x00, 0x00, 0xED, 0xAC,
-0x90, 0x01, 0x83, 0x35, 0x00, 0x00, 0x04, 0xAD, 0x94, 0x01, 0x86, 0x35,
-0x00, 0x00, 0xA2, 0xAC, 0xF5, 0x0F, 0x02, 0x24, 0x00, 0x00, 0x6F, 0xAC,
-0x98, 0x01, 0x89, 0x35, 0x00, 0x00, 0xC2, 0xAC, 0x9C, 0x01, 0x8A, 0x35,
-0xA0, 0x01, 0x8B, 0x35, 0xF0, 0x0F, 0x03, 0x24, 0xF6, 0x01, 0x8C, 0x35,
-0x0D, 0x00, 0x02, 0x24, 0x00, 0x00, 0x23, 0xAD, 0x00, 0x00, 0x42, 0xAD,
-0x00, 0x00, 0x6D, 0xAD, 0x02, 0x80, 0x02, 0x3C, 0x00, 0x00, 0x8E, 0xA1,
-0x00, 0x00, 0x2E, 0xA2, 0xE3, 0x5C, 0x42, 0x90, 0x25, 0xB0, 0x1F, 0x3C,
-0xA7, 0x01, 0xE7, 0x37, 0x1C, 0x00, 0xA2, 0xAF, 0xFF, 0xFF, 0x02, 0x24,
-0x00, 0x00, 0xE2, 0xA0, 0x05, 0x06, 0x03, 0x3C, 0x25, 0xB0, 0x02, 0x3C,
-0x03, 0x04, 0x63, 0x34, 0x0C, 0x00, 0x04, 0x24, 0xFF, 0xFF, 0x05, 0x24,
-0x01, 0x02, 0x06, 0x3C, 0xC2, 0x01, 0x42, 0x34, 0xA8, 0x01, 0xE8, 0x37,
-0xAC, 0x01, 0xE9, 0x37, 0xB0, 0x01, 0xEA, 0x37, 0xB4, 0x01, 0xEB, 0x37,
-0xB8, 0x01, 0xEC, 0x37, 0xBC, 0x01, 0xED, 0x37, 0xC0, 0x01, 0xEE, 0x37,
-0xC1, 0x01, 0xEF, 0x37, 0x00, 0x00, 0x05, 0xAD, 0x00, 0x00, 0x25, 0xAD,
-0x00, 0x00, 0x46, 0xAD, 0x00, 0x00, 0x63, 0xAD, 0x00, 0x00, 0x86, 0xAD,
-0x00, 0x00, 0xA3, 0xAD, 0x00, 0x00, 0xC4, 0xA1, 0x25, 0xB0, 0x03, 0x3C,
-0x00, 0x00, 0xE4, 0xA1, 0x00, 0x00, 0x44, 0xA0, 0x25, 0xB0, 0x02, 0x3C,
-0x0D, 0x00, 0x17, 0x24, 0x0E, 0x00, 0x18, 0x24, 0xC4, 0x01, 0x63, 0x34,
-0xC5, 0x01, 0x42, 0x34, 0xC3, 0x01, 0xF1, 0x37, 0x00, 0x00, 0x37, 0xA2,
-0xC6, 0x01, 0xF4, 0x37, 0x00, 0x00, 0x77, 0xA0, 0xC7, 0x01, 0xF5, 0x37,
-0x00, 0x00, 0x58, 0xA0, 0x0F, 0x00, 0x02, 0x24, 0x00, 0x00, 0x98, 0xA2,
-0x00, 0x00, 0xA2, 0xA2, 0x53, 0x01, 0x02, 0x3C, 0x46, 0x00, 0xF6, 0x37,
-0x48, 0x00, 0xFE, 0x37, 0x0E, 0xF0, 0x42, 0x34, 0x00, 0x00, 0xC0, 0xA6,
-0x00, 0x00, 0xC2, 0xAF, 0x1C, 0x00, 0xA3, 0x8F, 0x00, 0x00, 0x00, 0x00,
-0x09, 0x00, 0x60, 0x10, 0x44, 0x00, 0xF7, 0x37, 0x00, 0x00, 0xE2, 0x8E,
-0x00, 0x02, 0x03, 0x3C, 0x25, 0x10, 0x43, 0x00, 0x00, 0x00, 0xE2, 0xAE,
-0x00, 0x00, 0xC3, 0x8F, 0x00, 0x04, 0x02, 0x3C, 0x25, 0x18, 0x62, 0x00,
-0x00, 0x00, 0xC3, 0xAF, 0x4C, 0x00, 0xE2, 0x37, 0x00, 0x00, 0x40, 0xA0,
-0x40, 0x00, 0xE4, 0x37, 0xBC, 0x00, 0x03, 0x24, 0xFC, 0x37, 0x02, 0x24,
-0x00, 0x00, 0x83, 0xA4, 0x00, 0x00, 0x82, 0xA4, 0x02, 0x80, 0x02, 0x3C,
-0xD8, 0x00, 0xE9, 0x37, 0x60, 0x1B, 0x43, 0x24, 0x00, 0x00, 0x26, 0x91,
-0xAA, 0x1B, 0x64, 0x90, 0x2A, 0xB0, 0x05, 0x3C, 0xA0, 0xFF, 0x02, 0x24,
-0x26, 0xB0, 0x07, 0x3C, 0x25, 0x30, 0xC2, 0x00, 0x30, 0x00, 0xAD, 0x34,
-0x34, 0x00, 0xA8, 0x34, 0x01, 0x00, 0x83, 0x24, 0x38, 0x00, 0xA5, 0x34,
-0x20, 0x20, 0x02, 0x24, 0x00, 0x00, 0x26, 0xA1, 0x79, 0x00, 0xEA, 0x34,
-0x00, 0x00, 0x03, 0xA1, 0x00, 0x00, 0xA2, 0xA4, 0x40, 0x00, 0x03, 0x24,
-0x16, 0x00, 0x02, 0x24, 0x00, 0x00, 0xA3, 0xA1, 0x94, 0x00, 0xEB, 0x37,
-0x00, 0x00, 0x42, 0xA1, 0x98, 0x00, 0xEC, 0x37, 0x64, 0x00, 0x03, 0x24,
-0x22, 0x00, 0x02, 0x24, 0x00, 0x00, 0x63, 0xA5, 0x7C, 0x00, 0xF4, 0x34,
-0x00, 0x00, 0x82, 0xA5, 0x7A, 0x00, 0xE7, 0x34, 0x04, 0x00, 0x03, 0x24,
-0x20, 0x0C, 0x02, 0x24, 0x00, 0x00, 0xE3, 0xA0, 0x9C, 0x00, 0xEE, 0x37,
-0x00, 0x00, 0x82, 0xA6, 0x9A, 0x00, 0xEF, 0x37, 0x0A, 0x00, 0x03, 0x24,
-0xFF, 0x03, 0x02, 0x24, 0x00, 0x00, 0xC3, 0xA1, 0x00, 0x00, 0xE2, 0xA5,
-0x25, 0xB0, 0x02, 0x3C, 0x02, 0x00, 0x03, 0x24, 0x96, 0x00, 0x42, 0x34,
-0x00, 0x00, 0x43, 0xA4, 0x89, 0x00, 0xF5, 0x37, 0xB7, 0x00, 0xF1, 0x37,
-0x20, 0x00, 0x02, 0x24, 0x09, 0x00, 0x03, 0x24, 0x00, 0x00, 0x22, 0xA2,
-0x00, 0x00, 0xA3, 0xA2, 0x00, 0x00, 0xE2, 0x96, 0xFF, 0xFD, 0x03, 0x24,
-0x04, 0x02, 0x05, 0x24, 0x24, 0x10, 0x43, 0x00, 0x00, 0x00, 0xE2, 0xA6,
-0x00, 0x00, 0xE3, 0x96, 0x29, 0xB0, 0x02, 0x3C, 0x40, 0x00, 0x42, 0x34,
-0x00, 0x02, 0x63, 0x34, 0x00, 0x00, 0xE3, 0xA6, 0xFF, 0x00, 0x84, 0x30,
-0x00, 0x00, 0x45, 0xA4, 0x7A, 0x1F, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x44, 0x00, 0xBF, 0x8F, 0x40, 0x00, 0xBE, 0x8F, 0x3C, 0x00, 0xB7, 0x8F,
-0x38, 0x00, 0xB6, 0x8F, 0x34, 0x00, 0xB5, 0x8F, 0x30, 0x00, 0xB4, 0x8F,
-0x2C, 0x00, 0xB3, 0x8F, 0x28, 0x00, 0xB2, 0x8F, 0x24, 0x00, 0xB1, 0x8F,
-0x20, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x02, 0x24, 0x08, 0x00, 0xE0, 0x03,
-0x48, 0x00, 0xBD, 0x27, 0xFF, 0xFF, 0x03, 0x24, 0x00, 0x00, 0x43, 0xA0,
-0x02, 0x80, 0x0B, 0x3C, 0xC6, 0x5C, 0x66, 0x91, 0x25, 0xB0, 0x09, 0x3C,
-0x34, 0x02, 0x23, 0x35, 0x80, 0x00, 0x02, 0x24, 0x00, 0x00, 0x62, 0xA4,
-0x38, 0x02, 0x24, 0x35, 0x37, 0x02, 0x25, 0x35, 0x07, 0x00, 0x02, 0x24,
-0x22, 0x00, 0x03, 0x24, 0x00, 0x00, 0x80, 0xA0, 0x00, 0x00, 0xA2, 0xA0,
-0x23, 0xFF, 0xC3, 0x14, 0x13, 0x13, 0x02, 0x3C, 0x1B, 0x1B, 0x02, 0x3C,
-0x1B, 0x1B, 0x42, 0x34, 0x60, 0x01, 0x23, 0x35, 0x64, 0x01, 0x24, 0x35,
-0x68, 0x01, 0x25, 0x35, 0x7C, 0x01, 0x2A, 0x35, 0x6C, 0x01, 0x26, 0x35,
-0x70, 0x01, 0x27, 0x35, 0x74, 0x01, 0x28, 0x35, 0x78, 0x01, 0x29, 0x35,
-0x00, 0x00, 0x62, 0xAC, 0x00, 0x00, 0x82, 0xAC, 0x00, 0x00, 0xA2, 0xAC,
-0x00, 0x00, 0xC2, 0xAC, 0x00, 0x00, 0xE2, 0xAC, 0x00, 0x00, 0x02, 0xAD,
-0x00, 0x00, 0x22, 0xAD, 0x00, 0x00, 0x42, 0xAD, 0xC6, 0x5C, 0x65, 0x91,
-0x25, 0xB0, 0x0C, 0x3C, 0x01, 0x00, 0x03, 0x3C, 0x80, 0x01, 0x82, 0x35,
-0x08, 0x5F, 0x63, 0x34, 0x22, 0x00, 0x04, 0x24, 0x00, 0x00, 0x43, 0xAC,
-0x22, 0xFF, 0xA4, 0x14, 0x0F, 0x1F, 0x02, 0x3C, 0x00, 0xF0, 0x4F, 0x34,
-0xF7, 0x01, 0x91, 0x35, 0x15, 0xF0, 0x4D, 0x34, 0xE7, 0x68, 0x00, 0x08,
-0xFF, 0xFF, 0x0E, 0x24, 0x02, 0x80, 0x02, 0x3C, 0xC7, 0x5C, 0x44, 0x90,
-0x06, 0x00, 0x03, 0x24, 0x0C, 0x00, 0x83, 0x10, 0xA0, 0x00, 0x24, 0x36,
-0x00, 0x15, 0x02, 0x3C, 0x00, 0x07, 0x42, 0x34, 0x00, 0x00, 0x82, 0xAC,
-0x04, 0xE0, 0x02, 0x3C, 0xA4, 0x00, 0x25, 0x36, 0x00, 0x22, 0x03, 0x24,
-0xA8, 0x00, 0x26, 0x36, 0x00, 0xAE, 0x42, 0x34, 0x00, 0x00, 0xA3, 0xAC,
-0x47, 0x68, 0x00, 0x08, 0x02, 0x80, 0x03, 0x3C, 0x00, 0x15, 0x02, 0x3C,
-0x00, 0x07, 0x42, 0x34, 0x00, 0x00, 0x82, 0xAC, 0x04, 0xC0, 0x02, 0x3C,
-0xA4, 0x00, 0x25, 0x36, 0x00, 0x22, 0x03, 0x24, 0xA8, 0x00, 0x26, 0x36,
-0x00, 0xB0, 0x42, 0x34, 0x00, 0x00, 0xA3, 0xAC, 0x47, 0x68, 0x00, 0x08,
-0x02, 0x80, 0x03, 0x3C, 0xE8, 0xFF, 0xBD, 0x27, 0x01, 0x00, 0x06, 0x24,
-0xE8, 0x0E, 0x04, 0x24, 0x10, 0x00, 0xBF, 0xAF, 0xC1, 0x43, 0x00, 0x0C,
-0x00, 0x10, 0x05, 0x3C, 0x60, 0x08, 0x04, 0x24, 0xE3, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0x20, 0x04, 0x06, 0x3C, 0x20, 0x04, 0xC6, 0x34,
-0x25, 0x30, 0x46, 0x00, 0x60, 0x08, 0x04, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0x70, 0x08, 0x04, 0x24, 0x00, 0x04, 0x05, 0x24,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0x00, 0x20, 0x06, 0x3C,
-0x80, 0x00, 0xC6, 0x34, 0x80, 0x0C, 0x04, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0xFF, 0xFF, 0x05, 0x24, 0x00, 0x40, 0x06, 0x3C, 0x10, 0x00, 0xBF, 0x8F,
-0x00, 0x01, 0xC6, 0x34, 0x88, 0x0C, 0x04, 0x24, 0xFF, 0xFF, 0x05, 0x24,
-0xC1, 0x43, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x1C, 0x00, 0xBF, 0xAF,
-0x10, 0x00, 0xB0, 0xAF, 0x21, 0x90, 0xA0, 0x00, 0x0A, 0x00, 0xA0, 0x10,
-0x21, 0x88, 0x00, 0x00, 0x21, 0x80, 0x80, 0x00, 0x00, 0x00, 0x04, 0x8E,
-0x04, 0x00, 0x05, 0x8E, 0x02, 0x00, 0x31, 0x26, 0x03, 0x5C, 0x00, 0x0C,
-0x08, 0x00, 0x10, 0x26, 0x2B, 0x10, 0x32, 0x02, 0xF9, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0xE0, 0xFF, 0xBD, 0x27, 0x18, 0x00, 0xB2, 0xAF,
-0x14, 0x00, 0xB1, 0xAF, 0x1C, 0x00, 0xBF, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x21, 0x90, 0xA0, 0x00, 0x0B, 0x00, 0xA0, 0x10, 0x21, 0x88, 0x00, 0x00,
-0x21, 0x80, 0x80, 0x00, 0x00, 0x00, 0x04, 0x8E, 0x04, 0x00, 0x05, 0x8E,
-0x08, 0x00, 0x06, 0x8E, 0x03, 0x00, 0x31, 0x26, 0xC1, 0x43, 0x00, 0x0C,
-0x0C, 0x00, 0x10, 0x26, 0x2B, 0x10, 0x32, 0x02, 0xF8, 0xFF, 0x40, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x21, 0x40, 0x80, 0x00, 0x21, 0x48, 0x00, 0x00,
-0x1E, 0x00, 0xA0, 0x10, 0x21, 0x38, 0x00, 0x00, 0x80, 0x30, 0x07, 0x00,
-0x21, 0x10, 0xC8, 0x00, 0x00, 0x00, 0x43, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xF2, 0x63, 0x24, 0x1D, 0x00, 0x62, 0x2C, 0x12, 0x00, 0x40, 0x10,
-0x80, 0x10, 0x03, 0x00, 0x02, 0x80, 0x03, 0x3C, 0x14, 0xE6, 0x63, 0x24,
-0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0xC8, 0x00,
-0xC0, 0x18, 0x09, 0x00, 0x23, 0x18, 0x69, 0x00, 0x08, 0x00, 0x44, 0x8C,
-0x02, 0x80, 0x02, 0x3C, 0x80, 0x18, 0x03, 0x00, 0x60, 0x1B, 0x42, 0x24,
-0x21, 0x18, 0x62, 0x00, 0x04, 0x1D, 0x64, 0xAC, 0x01, 0x00, 0x29, 0x25,
-0x03, 0x00, 0xE7, 0x24, 0x2B, 0x10, 0xE5, 0x00, 0xE5, 0xFF, 0x40, 0x14,
-0x80, 0x30, 0x07, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0xC8, 0x00, 0xC0, 0x18, 0x09, 0x00, 0x08, 0x00, 0x44, 0x8C,
-0x23, 0x18, 0x69, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0x80, 0x18, 0x03, 0x00, 0x03, 0x00, 0xE7, 0x24, 0x21, 0x18, 0x62, 0x00,
-0x2B, 0x10, 0xE5, 0x00, 0xD6, 0xFF, 0x40, 0x14, 0x00, 0x1D, 0x64, 0xAC,
-0x4D, 0x6A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0xC8, 0x00,
-0xC0, 0x18, 0x09, 0x00, 0x08, 0x00, 0x44, 0x8C, 0x23, 0x18, 0x69, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24, 0x80, 0x18, 0x03, 0x00,
-0x03, 0x00, 0xE7, 0x24, 0x21, 0x18, 0x62, 0x00, 0x2B, 0x10, 0xE5, 0x00,
-0xC8, 0xFF, 0x40, 0x14, 0xFC, 0x1C, 0x64, 0xAC, 0x4D, 0x6A, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0xC8, 0x00, 0xC0, 0x18, 0x09, 0x00,
-0x08, 0x00, 0x44, 0x8C, 0x23, 0x18, 0x69, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x42, 0x24, 0x80, 0x18, 0x03, 0x00, 0x03, 0x00, 0xE7, 0x24,
-0x21, 0x18, 0x62, 0x00, 0x2B, 0x10, 0xE5, 0x00, 0xBA, 0xFF, 0x40, 0x14,
-0xF8, 0x1C, 0x64, 0xAC, 0x4D, 0x6A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x21, 0x10, 0xC8, 0x00, 0xC0, 0x18, 0x09, 0x00, 0x08, 0x00, 0x44, 0x8C,
-0x23, 0x18, 0x69, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24,
-0x80, 0x18, 0x03, 0x00, 0x03, 0x00, 0xE7, 0x24, 0x21, 0x18, 0x62, 0x00,
-0x2B, 0x10, 0xE5, 0x00, 0xAC, 0xFF, 0x40, 0x14, 0x08, 0x1D, 0x64, 0xAC,
-0x4D, 0x6A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0xC8, 0x00,
-0xC0, 0x18, 0x09, 0x00, 0x08, 0x00, 0x44, 0x8C, 0x23, 0x18, 0x69, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24, 0x80, 0x18, 0x03, 0x00,
-0x03, 0x00, 0xE7, 0x24, 0x21, 0x18, 0x62, 0x00, 0x2B, 0x10, 0xE5, 0x00,
-0x9E, 0xFF, 0x40, 0x14, 0xF4, 0x1C, 0x64, 0xAC, 0x4D, 0x6A, 0x00, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x21, 0x10, 0xC8, 0x00, 0xC0, 0x18, 0x09, 0x00,
-0x08, 0x00, 0x44, 0x8C, 0x23, 0x18, 0x69, 0x00, 0x02, 0x80, 0x02, 0x3C,
-0x60, 0x1B, 0x42, 0x24, 0x80, 0x18, 0x03, 0x00, 0x03, 0x00, 0xE7, 0x24,
-0x21, 0x18, 0x62, 0x00, 0x2B, 0x10, 0xE5, 0x00, 0x90, 0xFF, 0x40, 0x14,
-0xF0, 0x1C, 0x64, 0xAC, 0x4D, 0x6A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x25, 0xB0, 0x02, 0x3C, 0xFC, 0x37, 0x03, 0x24, 0x40, 0x00, 0x42, 0x34,
-0x02, 0x80, 0x04, 0x3C, 0x00, 0x00, 0x43, 0xA4, 0xE8, 0xFF, 0xBD, 0x27,
-0x5C, 0xD1, 0x84, 0x24, 0x10, 0x00, 0xBF, 0xAF, 0xFD, 0x69, 0x00, 0x0C,
-0x74, 0x01, 0x05, 0x24, 0x02, 0x80, 0x02, 0x3C, 0xC6, 0x5C, 0x44, 0x90,
-0x12, 0x00, 0x03, 0x24, 0x34, 0x00, 0x83, 0x10, 0x13, 0x00, 0x82, 0x28,
-0x17, 0x00, 0x40, 0x14, 0x11, 0x00, 0x02, 0x24, 0x22, 0x00, 0x02, 0x24,
-0x36, 0x00, 0x82, 0x10, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x04, 0x3C,
-0xE4, 0xCD, 0x84, 0x24, 0x2C, 0x6A, 0x00, 0x0C, 0x54, 0x00, 0x05, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0x4A, 0xF5, 0x44, 0x90, 0x01, 0x00, 0x03, 0x24,
-0x1A, 0x00, 0x83, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0xE4, 0xC8, 0x84, 0x24, 0xFD, 0x69, 0x00, 0x0C, 0x40, 0x01, 0x05, 0x24,
-0x10, 0x00, 0xBF, 0x8F, 0x84, 0x08, 0x04, 0x24, 0xFF, 0x00, 0x05, 0x24,
-0x58, 0x00, 0x06, 0x24, 0x35, 0x45, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0xED, 0xFF, 0x82, 0x14, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x04, 0x3C,
-0x9C, 0xD0, 0x84, 0x24, 0x14, 0x6A, 0x00, 0x0C, 0x30, 0x00, 0x05, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0xE4, 0xCD, 0x84, 0x24, 0x2C, 0x6A, 0x00, 0x0C,
-0x54, 0x00, 0x05, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x4A, 0xF5, 0x44, 0x90,
-0x01, 0x00, 0x03, 0x24, 0xE8, 0xFF, 0x83, 0x14, 0x00, 0x00, 0x00, 0x00,
-0xDE, 0x69, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0xE4, 0xC8, 0x84, 0x24, 0xFD, 0x69, 0x00, 0x0C, 0x40, 0x01, 0x05, 0x24,
-0x10, 0x00, 0xBF, 0x8F, 0x84, 0x08, 0x04, 0x24, 0xFF, 0x00, 0x05, 0x24,
-0x58, 0x00, 0x06, 0x24, 0x35, 0x45, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0x02, 0x80, 0x04, 0x3C, 0xE8, 0xCF, 0x84, 0x24, 0x2D, 0x00, 0x05, 0x24,
-0x14, 0x6A, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xD1, 0x6A, 0x00, 0x08,
-0x02, 0x80, 0x04, 0x3C, 0x34, 0xCF, 0x84, 0x24, 0xE8, 0x6A, 0x00, 0x08,
-0x2D, 0x00, 0x05, 0x24, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xB0, 0xAF,
-0x50, 0x0C, 0x04, 0x24, 0xFF, 0x00, 0x05, 0x24, 0x02, 0x80, 0x10, 0x3C,
-0x14, 0x00, 0xBF, 0xAF, 0x24, 0x45, 0x00, 0x0C, 0x60, 0x1B, 0x10, 0x26,
-0x60, 0x1D, 0x02, 0xA2, 0x58, 0x0C, 0x04, 0x24, 0x24, 0x45, 0x00, 0x0C,
-0xFF, 0x00, 0x05, 0x24, 0x61, 0x1D, 0x02, 0xA2, 0x60, 0x0C, 0x04, 0x24,
-0x24, 0x45, 0x00, 0x0C, 0xFF, 0x00, 0x05, 0x24, 0x62, 0x1D, 0x02, 0xA2,
-0x68, 0x0C, 0x04, 0x24, 0x24, 0x45, 0x00, 0x0C, 0xFF, 0x00, 0x05, 0x24,
-0x63, 0x1D, 0x02, 0xA2, 0x38, 0x0C, 0x04, 0x24, 0x24, 0x45, 0x00, 0x0C,
-0xFF, 0x00, 0x05, 0x24, 0xE8, 0x1C, 0x02, 0xA2, 0x34, 0x0C, 0x04, 0x24,
-0x24, 0x45, 0x00, 0x0C, 0xFF, 0xFF, 0x05, 0x24, 0xEC, 0x1C, 0x02, 0xAE,
-0x14, 0x00, 0xBF, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x38, 0xAD, 0x42, 0x24, 0xB0, 0x5D, 0x60, 0xAC,
-0x10, 0x5D, 0xA2, 0xAC, 0x02, 0x80, 0x03, 0x3C, 0x00, 0x80, 0x02, 0x3C,
-0xB4, 0x5D, 0x60, 0xA4, 0x10, 0x5D, 0xA4, 0x24, 0x64, 0x11, 0x42, 0x24,
-0x02, 0x80, 0x03, 0x3C, 0xB6, 0x5D, 0x60, 0xA4, 0x08, 0x00, 0x82, 0xAC,
-0x00, 0x80, 0x03, 0x3C, 0x00, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x06, 0x3C,
-0x4C, 0x14, 0x42, 0x24, 0x80, 0x11, 0x63, 0x24, 0xB8, 0x5D, 0xC7, 0x24,
-0x14, 0x00, 0x82, 0xAC, 0x10, 0x00, 0x83, 0xAC, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0xB8, 0x5D, 0xC0, 0xAC, 0x04, 0x00, 0xE0, 0xAC,
-0xC0, 0x5D, 0x40, 0xA0, 0xC4, 0x5D, 0x60, 0xAC, 0x01, 0x80, 0x02, 0x3C,
-0xB4, 0xC5, 0x42, 0x24, 0x7C, 0x00, 0x82, 0xAC, 0x00, 0x80, 0x03, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0x68, 0x14, 0x63, 0x24, 0x08, 0x17, 0x42, 0x24,
-0x20, 0x00, 0x83, 0xAC, 0x24, 0x00, 0x82, 0xAC, 0x00, 0x80, 0x03, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0xB0, 0x19, 0x63, 0x24, 0x54, 0x1C, 0x42, 0x24,
-0x28, 0x00, 0x83, 0xAC, 0x2C, 0x00, 0x82, 0xAC, 0x00, 0x80, 0x03, 0x3C,
-0x01, 0x80, 0x02, 0x3C, 0x80, 0x2F, 0x63, 0x24, 0x10, 0x02, 0x42, 0x24,
-0x30, 0x00, 0x83, 0xAC, 0x54, 0x00, 0x82, 0xAC, 0x00, 0x80, 0x03, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0x58, 0x1F, 0x63, 0x24, 0x38, 0x21, 0x42, 0x24,
-0x0C, 0x00, 0x83, 0xAC, 0x3C, 0x00, 0x82, 0xAC, 0x00, 0x80, 0x03, 0x3C,
-0x00, 0x80, 0x02, 0x3C, 0x00, 0x03, 0x63, 0x24, 0xF8, 0x1E, 0x42, 0x24,
-0x50, 0x00, 0x83, 0xAC, 0x08, 0x00, 0xE0, 0x03, 0x40, 0x00, 0x82, 0xAC,
-0x25, 0xB0, 0x02, 0x3C, 0x08, 0x00, 0x42, 0x34, 0x00, 0x00, 0x43, 0x8C,
-0x08, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x0E, 0x3C,
-0x02, 0x80, 0x08, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0xF8, 0x03, 0x4D, 0x24, 0x00, 0x18, 0x6C, 0x24, 0x01, 0x00, 0x07, 0x24,
-0x00, 0x00, 0xCB, 0x25, 0xFF, 0xFF, 0x0A, 0x24, 0x00, 0x04, 0x09, 0x25,
-0x80, 0x1A, 0x07, 0x00, 0x21, 0x10, 0x6B, 0x00, 0x00, 0x00, 0x42, 0xAC,
-0x90, 0x00, 0x4A, 0xAC, 0x00, 0x04, 0x04, 0x8D, 0x01, 0x00, 0xE7, 0x24,
-0x08, 0x00, 0x45, 0x24, 0x21, 0x18, 0x6D, 0x00, 0x06, 0x00, 0xE6, 0x28,
-0x04, 0x00, 0x82, 0xAC, 0x00, 0x00, 0x44, 0xAC, 0x04, 0x00, 0x49, 0xAC,
-0x00, 0x04, 0x02, 0xAD, 0x8C, 0x00, 0x40, 0xAC, 0x6C, 0x00, 0xA3, 0xAC,
-0xF0, 0xFF, 0xC0, 0x14, 0x68, 0x00, 0xAC, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0xC9, 0xAD, 0x06, 0x00, 0xA2, 0x2C, 0x13, 0x00, 0x40, 0x10,
-0xFF, 0xFF, 0x07, 0x24, 0x02, 0x80, 0x02, 0x3C, 0x80, 0x1A, 0x05, 0x00,
-0x00, 0x00, 0x42, 0x24, 0x0E, 0x00, 0xA0, 0x10, 0x21, 0x30, 0x62, 0x00,
-0x90, 0x00, 0xC3, 0x8C, 0xFF, 0xFF, 0x02, 0x24, 0x0A, 0x00, 0x62, 0x14,
-0x00, 0x00, 0x00, 0x00, 0x8C, 0x00, 0xC2, 0x8C, 0x00, 0x00, 0x00, 0x00,
-0x06, 0x00, 0x40, 0x14, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x24,
-0x88, 0x00, 0xC4, 0xAC, 0x8C, 0x00, 0xC2, 0xAC, 0x90, 0x00, 0xC5, 0xAC,
-0x21, 0x38, 0xA0, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0xE0, 0x00,
-0xE0, 0xFF, 0xBD, 0x27, 0x02, 0x80, 0x02, 0x3C, 0x1C, 0x00, 0xBF, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0xC3, 0x5C, 0x46, 0x90, 0x25, 0xB0, 0x07, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0xDB, 0xFF, 0x03, 0x24, 0x18, 0x03, 0xE4, 0x34, 0x27, 0x00, 0xE5, 0x34,
-0x1C, 0xAE, 0x42, 0x24, 0x00, 0x00, 0x82, 0xAC, 0x00, 0x00, 0xA3, 0xA0,
-0x02, 0x00, 0xC0, 0x10, 0x1B, 0x00, 0xE3, 0x34, 0x1F, 0x00, 0xE3, 0x34,
-0x07, 0x00, 0x02, 0x24, 0x00, 0x00, 0x62, 0xA0, 0xF0, 0x42, 0x00, 0x0C,
-0x21, 0x20, 0x00, 0x00, 0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x50, 0x24,
-0x34, 0x1C, 0x04, 0x8E, 0xE3, 0x43, 0x00, 0x0C, 0x10, 0x00, 0x05, 0x24,
-0x40, 0x1C, 0x04, 0x8E, 0x10, 0x00, 0x05, 0x3C, 0x01, 0x00, 0x06, 0x24,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x90, 0x40, 0x00, 0x3C, 0x1C, 0x04, 0x8E,
-0x10, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24,
-0x58, 0x1C, 0x04, 0x8E, 0x00, 0x04, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0x58, 0x1C, 0x04, 0x8E, 0x00, 0x08, 0x05, 0x24,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0x02, 0x80, 0x05, 0x3C,
-0x78, 0xDA, 0xA5, 0x24, 0x21, 0x20, 0x00, 0x00, 0xC1, 0x45, 0x00, 0x0C,
-0xCA, 0x00, 0x06, 0x24, 0x31, 0x00, 0x40, 0x10, 0x21, 0x18, 0x00, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xCF, 0x5C, 0x43, 0x90, 0x01, 0x00, 0x11, 0x24,
-0x53, 0x00, 0x71, 0x10, 0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0x4A, 0xF5, 0x43, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x71, 0x10,
-0x02, 0x80, 0x05, 0x3C, 0x34, 0x1C, 0x04, 0x8E, 0x21, 0x30, 0x40, 0x02,
-0x10, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C, 0x02, 0x80, 0x11, 0x3C,
-0xC6, 0x5C, 0x23, 0x92, 0x11, 0x00, 0x02, 0x24, 0x2A, 0x00, 0x62, 0x10,
-0x00, 0x08, 0x04, 0x24, 0xF0, 0x42, 0x00, 0x0C, 0x01, 0x00, 0x04, 0x24,
-0x34, 0x1C, 0x04, 0x8E, 0xE3, 0x43, 0x00, 0x0C, 0x10, 0x00, 0x05, 0x3C,
-0x40, 0x1C, 0x04, 0x8E, 0x10, 0x00, 0x05, 0x3C, 0x01, 0x00, 0x06, 0x24,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x90, 0x40, 0x00, 0x3C, 0x1C, 0x04, 0x8E,
-0x10, 0x00, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24,
-0x58, 0x1C, 0x04, 0x8E, 0x00, 0x04, 0x05, 0x24, 0xC1, 0x43, 0x00, 0x0C,
-0x21, 0x30, 0x00, 0x00, 0x58, 0x1C, 0x04, 0x8E, 0x00, 0x08, 0x05, 0x24,
-0xC1, 0x43, 0x00, 0x0C, 0x21, 0x30, 0x00, 0x00, 0x02, 0x80, 0x05, 0x3C,
-0x20, 0xDA, 0xA5, 0x24, 0x01, 0x00, 0x04, 0x24, 0xC1, 0x45, 0x00, 0x0C,
-0x16, 0x00, 0x06, 0x24, 0x08, 0x00, 0x40, 0x14, 0x21, 0x18, 0x00, 0x00,
-0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F,
-0x10, 0x00, 0xB0, 0x8F, 0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x34, 0x1C, 0x04, 0x8E, 0x21, 0x30, 0x40, 0x02,
-0xC1, 0x43, 0x00, 0x0C, 0x10, 0x00, 0x05, 0x3C, 0x00, 0x08, 0x04, 0x24,
-0x00, 0x01, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C, 0x01, 0x00, 0x06, 0x24,
-0x00, 0x08, 0x04, 0x24, 0x00, 0x02, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C,
-0x01, 0x00, 0x06, 0x24, 0xC6, 0x5C, 0x23, 0x92, 0x11, 0x00, 0x02, 0x24,
-0x1D, 0x00, 0x62, 0x10, 0x00, 0x08, 0x04, 0x24, 0xF0, 0x42, 0x00, 0x0C,
-0x21, 0x20, 0x00, 0x00, 0x0F, 0x00, 0x05, 0x3C, 0x0C, 0x00, 0x06, 0x3C,
-0xFF, 0xFF, 0xA5, 0x34, 0x00, 0xB4, 0xC6, 0x34, 0x83, 0x45, 0x00, 0x0C,
-0x08, 0x00, 0x04, 0x24, 0x1C, 0x00, 0xBF, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x01, 0x00, 0x03, 0x24,
-0x21, 0x10, 0x60, 0x00, 0x08, 0x00, 0xE0, 0x03, 0x20, 0x00, 0xBD, 0x27,
-0x10, 0xD9, 0xA5, 0x24, 0x21, 0x20, 0x00, 0x00, 0xC1, 0x45, 0x00, 0x0C,
-0x16, 0x00, 0x06, 0x24, 0xC0, 0x6B, 0x00, 0x08, 0x02, 0x80, 0x02, 0x3C,
-0x68, 0xD9, 0xA5, 0x24, 0x21, 0x20, 0x00, 0x00, 0xC1, 0x45, 0x00, 0x0C,
-0x16, 0x00, 0x06, 0x24, 0xC4, 0x6B, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-0x00, 0xFF, 0x05, 0x3C, 0xC1, 0x43, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x24,
-0x01, 0x6C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x02, 0x80, 0x02, 0x3C, 0x25, 0x59, 0x47, 0x90, 0x02, 0x80, 0x04, 0x3C,
-0x02, 0x80, 0x05, 0x3C, 0x03, 0x00, 0x03, 0x24, 0x4E, 0x37, 0x84, 0x24,
-0xB4, 0xDF, 0xA5, 0x24, 0x0F, 0x00, 0xE3, 0x10, 0x0D, 0x00, 0x06, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0x4E, 0x37, 0x84, 0x24,
-0x64, 0xDF, 0xA5, 0x24, 0xF4, 0x54, 0x00, 0x0C, 0x0D, 0x00, 0x06, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C, 0x10, 0x00, 0xBF, 0x8F,
-0x5B, 0x37, 0x84, 0x24, 0x74, 0xDF, 0xA5, 0x24, 0x0D, 0x00, 0x06, 0x24,
-0xF4, 0x54, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27, 0xF4, 0x54, 0x00, 0x0C,
-0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x02, 0x80, 0x05, 0x3C,
-0x10, 0x00, 0xBF, 0x8F, 0x5B, 0x37, 0x84, 0x24, 0xA4, 0xDF, 0xA5, 0x24,
-0x0D, 0x00, 0x06, 0x24, 0xF4, 0x54, 0x00, 0x08, 0x18, 0x00, 0xBD, 0x27,
-0xE0, 0xFF, 0xBD, 0x27, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x02, 0x80, 0x05, 0x3C, 0x02, 0x80, 0x10, 0x3C, 0x02, 0x80, 0x11, 0x3C,
-0x60, 0x1B, 0x31, 0x26, 0x2C, 0x59, 0x04, 0x26, 0xA0, 0xDD, 0xA5, 0x24,
-0x34, 0x00, 0x06, 0x24, 0x18, 0x00, 0xBF, 0xAF, 0xF4, 0x54, 0x00, 0x0C,
-0x2C, 0x59, 0x10, 0x26, 0x24, 0x6C, 0x00, 0x0C, 0x00, 0x3E, 0x30, 0xAE,
-0x02, 0x00, 0x10, 0x24, 0x02, 0x80, 0x04, 0x3C, 0x00, 0x80, 0x06, 0x3C,
-0x9C, 0x39, 0x30, 0xA2, 0xE8, 0x54, 0x84, 0x24, 0x98, 0x5B, 0xC6, 0x24,
-0xCF, 0x20, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x01, 0x80, 0x06, 0x3C, 0xB8, 0x39, 0x30, 0xA2, 0x04, 0x55, 0x84, 0x24,
-0x90, 0x3B, 0xC6, 0x24, 0xCF, 0x20, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00,
-0x02, 0x80, 0x04, 0x3C, 0x01, 0x80, 0x06, 0x3C, 0xD4, 0x39, 0x30, 0xA2,
-0x20, 0x55, 0x84, 0x24, 0x08, 0x39, 0xC6, 0x24, 0xCF, 0x20, 0x00, 0x0C,
-0x21, 0x28, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C, 0x01, 0x80, 0x06, 0x3C,
-0xF0, 0x39, 0x30, 0xA2, 0x3C, 0x55, 0x84, 0x24, 0x74, 0x44, 0xC6, 0x24,
-0xCF, 0x20, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00, 0x02, 0x80, 0x04, 0x3C,
-0x00, 0x80, 0x06, 0x3C, 0x0C, 0x3A, 0x30, 0xA2, 0x58, 0x55, 0x84, 0x24,
-0xFC, 0x5A, 0xC6, 0x24, 0xCF, 0x20, 0x00, 0x0C, 0x21, 0x28, 0x00, 0x00,
-0x09, 0x00, 0x02, 0x24, 0xB8, 0x40, 0x22, 0xA2, 0xC7, 0x3D, 0x20, 0xA2,
-0x3A, 0x41, 0x20, 0xA2, 0xC8, 0x3D, 0x20, 0xA6, 0x18, 0x00, 0xBF, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x20, 0x00, 0xBD, 0x27, 0x03, 0x80, 0x05, 0x3C, 0x00, 0x80, 0xA5, 0x24,
-0xD8, 0xFF, 0xBD, 0x27, 0x40, 0x10, 0x0D, 0x3C, 0xFF, 0xFF, 0xA5, 0x30,
-0x02, 0x80, 0x02, 0x3C, 0x60, 0x1B, 0x42, 0x24, 0x20, 0x00, 0xBE, 0xAF,
-0x25, 0xF0, 0xAD, 0x00, 0x2C, 0x38, 0x5E, 0xAC, 0x00, 0x01, 0xDE, 0x27,
-0x38, 0x38, 0x5E, 0xAC, 0x00, 0x01, 0xDE, 0x27, 0x1C, 0x00, 0xB7, 0xAF,
-0x18, 0x00, 0xB6, 0xAF, 0x14, 0x00, 0xB5, 0xAF, 0x10, 0x00, 0xB4, 0xAF,
-0x0C, 0x00, 0xB3, 0xAF, 0x08, 0x00, 0xB2, 0xAF, 0x04, 0x00, 0xB1, 0xAF,
-0x00, 0x00, 0xB0, 0xAF, 0x44, 0x38, 0x5E, 0xAC, 0x00, 0x01, 0xDE, 0x27,
-0x50, 0x38, 0x5E, 0xAC, 0xAA, 0x1B, 0x44, 0x90, 0x00, 0x01, 0xDE, 0x27,
-0x5C, 0x38, 0x5E, 0xAC, 0x00, 0x01, 0xDE, 0x27, 0x68, 0x38, 0x5E, 0xAC,
-0x20, 0xB0, 0x06, 0x3C, 0x38, 0x38, 0x48, 0x8C, 0x44, 0x38, 0x49, 0x8C,
-0x50, 0x38, 0x4A, 0x8C, 0x5C, 0x38, 0x4B, 0x8C, 0x68, 0x38, 0x4C, 0x8C,
-0x00, 0x22, 0x04, 0x00, 0x00, 0x01, 0xC7, 0x34, 0xFF, 0x1F, 0x03, 0x3C,
-0x00, 0x01, 0xDE, 0x27, 0xFF, 0xFF, 0x63, 0x34, 0x21, 0x38, 0x87, 0x00,
-0x21, 0x20, 0x86, 0x00, 0x24, 0x38, 0xE3, 0x00, 0x20, 0x10, 0x06, 0x3C,
-0x24, 0x20, 0x83, 0x00, 0x74, 0x38, 0x5E, 0xAC, 0x21, 0x70, 0xC0, 0x03,
-0x25, 0x28, 0xAD, 0x00, 0x25, 0xB0, 0x0F, 0x3C, 0x00, 0x01, 0xDE, 0x27,
-0x28, 0x38, 0x45, 0xAC, 0x34, 0x38, 0x48, 0xAC, 0x40, 0x38, 0x49, 0xAC,
-0x4C, 0x38, 0x4A, 0xAC, 0xEC, 0x37, 0x44, 0xAC, 0x58, 0x38, 0x4B, 0xAC,
-0xF8, 0x37, 0x47, 0xAC, 0x64, 0x38, 0x4C, 0xAC, 0xAC, 0x00, 0xE3, 0x35,
-0xC0, 0x37, 0x46, 0xAC, 0xBC, 0x37, 0x46, 0xAC, 0xCC, 0x37, 0x46, 0xAC,
-0xC8, 0x37, 0x46, 0xAC, 0x80, 0x38, 0x5E, 0xAC, 0xF0, 0x37, 0x44, 0xAC,
-0xFC, 0x37, 0x47, 0xAC, 0x70, 0x38, 0x4E, 0xAC, 0xD8, 0x37, 0x46, 0xAC,
-0xD4, 0x37, 0x46, 0xAC, 0xE4, 0x37, 0x46, 0xAC, 0xE0, 0x37, 0x46, 0xAC,
-0x08, 0x38, 0x46, 0xAC, 0x04, 0x38, 0x46, 0xAC, 0xAC, 0x1B, 0x47, 0x94,
-0x00, 0x02, 0xDE, 0x27, 0x00, 0x00, 0x69, 0x8C, 0x21, 0x10, 0x05, 0x3C,
-0x98, 0x38, 0x5E, 0xAC, 0xB0, 0x00, 0xE3, 0x35, 0x00, 0x00, 0x79, 0x8C,
-0x80, 0x38, 0x54, 0x8C, 0x00, 0x80, 0xA4, 0x34, 0x23, 0x10, 0x0D, 0x3C,
-0x22, 0x10, 0x10, 0x3C, 0x02, 0x80, 0x16, 0x3C, 0x02, 0x80, 0x17, 0x3C,
-0x02, 0x80, 0x18, 0x3C, 0x02, 0x80, 0x13, 0x3C, 0x23, 0x20, 0x87, 0x00,
-0x02, 0x80, 0x03, 0x3C, 0x24, 0x10, 0x07, 0x3C, 0xC0, 0x54, 0x68, 0x24,
-0xCC, 0x38, 0x44, 0xAC, 0x21, 0xA8, 0xC0, 0x03, 0xC8, 0x54, 0xCE, 0x26,
-0x00, 0x04, 0xDE, 0x27, 0xD0, 0x54, 0xEA, 0x26, 0xD8, 0x54, 0x0B, 0x27,
-0xE0, 0x54, 0x6C, 0x26, 0x00, 0x04, 0xB1, 0x35, 0x01, 0x00, 0x29, 0x25,
-0x00, 0x40, 0x12, 0x36, 0x00, 0x01, 0xEF, 0x35, 0x01, 0x00, 0x03, 0x24,
-0x02, 0x80, 0x04, 0x3C, 0x7C, 0x38, 0x54, 0xAC, 0x85, 0x38, 0x43, 0xA0,
-0x94, 0x38, 0x55, 0xAC, 0xFC, 0x38, 0x51, 0xAC, 0xC0, 0x38, 0x49, 0xAC,
-0xF0, 0x38, 0x52, 0xAC, 0xE4, 0x38, 0x59, 0xAC, 0x00, 0x00, 0xE7, 0xAD,
-0xE0, 0x38, 0x47, 0xAC, 0x00, 0x39, 0x46, 0xAC, 0x14, 0x38, 0x46, 0xAC,
-0x10, 0x38, 0x46, 0xAC, 0x9E, 0x38, 0x40, 0xA4, 0x9D, 0x38, 0x40, 0xA0,
-0x9C, 0x38, 0x40, 0xA0, 0xF4, 0x38, 0x4D, 0xAC, 0xF8, 0x38, 0x4D, 0xAC,
-0xB8, 0x38, 0x45, 0xAC, 0xBC, 0x38, 0x45, 0xAC, 0xC4, 0x38, 0x45, 0xAC,
-0xC8, 0x38, 0x45, 0xAC, 0xE8, 0x38, 0x50, 0xAC, 0xEC, 0x38, 0x50, 0xAC,
-0xDC, 0x38, 0x47, 0xAC, 0x04, 0x39, 0x46, 0xAC, 0x10, 0x39, 0x5E, 0xAC,
-0x0C, 0x39, 0x5E, 0xAC, 0x04, 0x00, 0x4A, 0xAD, 0xC8, 0x54, 0xCE, 0xAE,
-0x04, 0x00, 0x6B, 0xAD, 0xD0, 0x54, 0xEA, 0xAE, 0x04, 0x00, 0x8C, 0xAD,
-0xD8, 0x54, 0x0B, 0xAF, 0x04, 0x00, 0x08, 0xAD, 0xE0, 0x54, 0x6C, 0xAE,
-0xC0, 0x54, 0x88, 0xAC, 0x04, 0x00, 0xCE, 0xAD, 0x02, 0x80, 0x04, 0x3C,
-0x18, 0x18, 0x83, 0x24, 0x02, 0x80, 0x05, 0x3C, 0x00, 0x18, 0xA2, 0x24,
-0x18, 0x18, 0x83, 0xAC, 0x02, 0x80, 0x04, 0x3C, 0x04, 0x00, 0x02, 0xAD,
-0x00, 0x18, 0xA8, 0xAC, 0xC0, 0x54, 0x82, 0xAC, 0x21, 0x48, 0x60, 0x00,
-0x08, 0x00, 0x5E, 0xAC, 0x01, 0x00, 0x07, 0x24, 0x04, 0x00, 0x63, 0xAC,
-0x00, 0x01, 0xDE, 0x27, 0x04, 0x00, 0x48, 0xAC, 0x10, 0x00, 0x40, 0xAC,
-0x21, 0x40, 0x40, 0x00, 0x21, 0x18, 0xC0, 0x01, 0x21, 0x28, 0x00, 0x00,
-0x0F, 0x00, 0x06, 0x24, 0x21, 0x20, 0xA9, 0x00, 0x21, 0x10, 0xA8, 0x00,
-0xFF, 0xFF, 0xC6, 0x24, 0x20, 0x00, 0x5E, 0xAC, 0x28, 0x00, 0x47, 0xAC,
-0x18, 0x00, 0xA5, 0x24, 0x00, 0x00, 0x8E, 0xAC, 0x04, 0x00, 0x83, 0xAC,
-0x00, 0x00, 0x64, 0xAC, 0x00, 0x01, 0xDE, 0x27, 0xF5, 0xFF, 0xC1, 0x04,
-0x21, 0x18, 0x80, 0x00, 0x02, 0x80, 0x02, 0x3C, 0xD0, 0x54, 0x48, 0x24,
-0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0x04, 0x00, 0x07, 0x8D,
-0x98, 0x19, 0x4B, 0x24, 0x04, 0x00, 0xC4, 0xAD, 0x00, 0x18, 0x6A, 0x24,
-0x02, 0x00, 0x09, 0x24, 0x21, 0x28, 0x00, 0x00, 0x0F, 0x00, 0x06, 0x24,
-0x21, 0x20, 0xAB, 0x00, 0x21, 0x10, 0xAA, 0x00, 0xFF, 0xFF, 0xC6, 0x24,
-0xA0, 0x01, 0x5E, 0xAC, 0xA8, 0x01, 0x49, 0xAC, 0x18, 0x00, 0xA5, 0x24,
-0x00, 0x00, 0x88, 0xAC, 0x04, 0x00, 0x87, 0xAC, 0x00, 0x00, 0xE4, 0xAC,
-0x00, 0x02, 0xDE, 0x27, 0xF5, 0xFF, 0xC1, 0x04, 0x21, 0x38, 0x80, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xD8, 0x54, 0x49, 0x24, 0x02, 0x80, 0x03, 0x3C,
-0x02, 0x80, 0x02, 0x3C, 0x04, 0x00, 0x25, 0x8D, 0x18, 0x1B, 0x4B, 0x24,
-0x04, 0x00, 0x04, 0xAD, 0x00, 0x18, 0x6A, 0x24, 0x03, 0x00, 0x07, 0x24,
-0x21, 0x20, 0x00, 0x00, 0x01, 0x00, 0x06, 0x24, 0x21, 0x40, 0x8B, 0x00,
-0x21, 0x10, 0x8A, 0x00, 0xFF, 0xFF, 0xC6, 0x24, 0x20, 0x03, 0x5E, 0xAC,
-0x28, 0x03, 0x47, 0xAC, 0x18, 0x00, 0x84, 0x24, 0x00, 0x00, 0x09, 0xAD,
-0x04, 0x00, 0x05, 0xAD, 0x00, 0x00, 0xA8, 0xAC, 0x00, 0x08, 0xDE, 0x27,
-0xF5, 0xFF, 0xC1, 0x04, 0x21, 0x28, 0x00, 0x01, 0x02, 0x80, 0x05, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0xE0, 0x54, 0xA5, 0x24, 0x00, 0x18, 0x63, 0x24,
-0x04, 0x00, 0xA6, 0x8C, 0x1C, 0x00, 0xB7, 0x8F, 0x50, 0x03, 0x7E, 0xAC,
-0x18, 0x00, 0xB6, 0x8F, 0x20, 0x00, 0xBE, 0x8F, 0x14, 0x00, 0xB5, 0x8F,
-0x10, 0x00, 0xB4, 0x8F, 0x0C, 0x00, 0xB3, 0x8F, 0x08, 0x00, 0xB2, 0x8F,
-0x04, 0x00, 0xB1, 0x8F, 0x00, 0x00, 0xB0, 0x8F, 0x02, 0x80, 0x07, 0x3C,
-0x48, 0x1B, 0xE4, 0x24, 0x04, 0x00, 0x02, 0x24, 0x28, 0x00, 0xBD, 0x27,
-0x04, 0x00, 0x28, 0xAD, 0x04, 0x00, 0xA4, 0xAC, 0x58, 0x03, 0x62, 0xAC,
-0x48, 0x1B, 0xE5, 0xAC, 0x04, 0x00, 0x86, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0xC4, 0xAC, 0xFA, 0x63, 0x00, 0x6A, 0x09, 0xD1, 0x0A, 0x62,
-0x08, 0xD0, 0x06, 0xD2, 0x7D, 0x67, 0x18, 0xA3, 0x10, 0xF0, 0x02, 0x69,
-0x00, 0xF4, 0x20, 0x31, 0x63, 0xF3, 0x00, 0x49, 0x00, 0x18, 0xDB, 0x5C,
-0x06, 0x94, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0x5C, 0xF4, 0x00, 0x4A, 0xDC, 0xF3,
-0x0C, 0x4B, 0x7B, 0x9B, 0x5B, 0x9A, 0x00, 0x6D, 0x69, 0xE2, 0x46, 0x32,
-0xC4, 0xF4, 0x54, 0xD9, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0xBC, 0xF3, 0x0C, 0x4A, 0x5B, 0xA2, 0x01, 0xF6, 0x01, 0x6B, 0x6B, 0xEB,
-0x50, 0x32, 0xE4, 0xF4, 0x5C, 0xD9, 0xE4, 0xF4, 0x58, 0xD9, 0x04, 0xF5,
-0x48, 0x99, 0x6C, 0xEA, 0x00, 0xF2, 0x00, 0x6B, 0x6D, 0xEA, 0x04, 0xF5,
-0x48, 0xD9, 0xA9, 0xE1, 0x01, 0x4D, 0x1D, 0x55, 0x04, 0xF5, 0x0C, 0xC2,
-0x44, 0xF5, 0x06, 0xC2, 0x24, 0xF5, 0x09, 0xC2, 0xF6, 0x61, 0x00, 0x6A,
-0x64, 0xF5, 0x44, 0xD9, 0x06, 0x94, 0x7F, 0x49, 0x15, 0x49, 0x01, 0x4C,
-0x20, 0x54, 0x06, 0xD4, 0xBF, 0x61, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4,
-0xA0, 0x35, 0x10, 0xF0, 0x02, 0x69, 0x00, 0xF4, 0x20, 0x31, 0x10, 0xF0,
-0x02, 0x68, 0x00, 0xF4, 0x00, 0x30, 0x10, 0xF0, 0x02, 0x6F, 0x00, 0xF4,
-0xE0, 0x37, 0x10, 0xF0, 0x02, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0x06, 0xD2,
-0x63, 0xF3, 0x00, 0x4D, 0x5C, 0xF4, 0x00, 0x49, 0xDC, 0xF3, 0x0C, 0x48,
-0xBC, 0xF3, 0x0C, 0x4F, 0x9C, 0xF3, 0x0C, 0x4E, 0x06, 0x93, 0x68, 0x32,
-0x2D, 0xE2, 0x60, 0x9B, 0xB1, 0xE2, 0x09, 0xE2, 0xC0, 0xF5, 0x74, 0xDC,
-0x40, 0x9A, 0x60, 0xF5, 0x40, 0xDC, 0x06, 0x94, 0xE9, 0xE4, 0x40, 0xA2,
-0xAD, 0xE4, 0x00, 0xF5, 0x44, 0xC3, 0xC9, 0xE4, 0x40, 0xA2, 0x01, 0x4C,
-0x1D, 0x54, 0x20, 0xF5, 0x5E, 0xC3, 0x06, 0xD4, 0xE7, 0x61, 0x10, 0xF0,
-0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4,
-0x60, 0x33, 0x00, 0x6D, 0x10, 0xF0, 0x02, 0x69, 0x00, 0xF4, 0x20, 0x31,
-0x7C, 0xF2, 0x08, 0x4A, 0x1C, 0xF1, 0x08, 0x4B, 0x06, 0xD5, 0x63, 0xF3,
-0x00, 0x49, 0x2A, 0x65, 0x0B, 0x65, 0x05, 0x67, 0x89, 0x67, 0x00, 0x6D,
-0x3D, 0xE0, 0x99, 0xE0, 0xAD, 0xE6, 0x40, 0xA3, 0xB1, 0xE7, 0x01, 0x4D,
-0xA0, 0xF3, 0x48, 0xC4, 0x80, 0xF0, 0x51, 0xA3, 0x05, 0x55, 0x20, 0xF4,
-0x59, 0xC4, 0xF4, 0x61, 0x06, 0x95, 0x48, 0x67, 0x05, 0x48, 0x4D, 0xE5,
-0x40, 0xA3, 0x31, 0xE5, 0x01, 0x4D, 0xC0, 0xF4, 0x4A, 0xC4, 0x5D, 0xA3,
-0x1D, 0x55, 0xE0, 0xF4, 0x47, 0xC4, 0x06, 0xD5, 0xE1, 0x61, 0x9D, 0x67,
-0x52, 0x6A, 0x50, 0xC4, 0x41, 0x6A, 0x51, 0xC4, 0x00, 0x6B, 0x4D, 0x6A,
-0x52, 0xC4, 0x73, 0xC4, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34,
-0x7E, 0xF5, 0x00, 0x4C, 0xE0, 0xF3, 0x08, 0x6A, 0x43, 0xDC, 0xBD, 0x67,
-0x01, 0x6A, 0x10, 0xF0, 0x01, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0x54, 0xC4,
-0x30, 0xF7, 0x01, 0x4E, 0x00, 0x1C, 0xCF, 0x20, 0x10, 0x4D, 0x0A, 0x97,
-0x09, 0x91, 0x08, 0x90, 0x00, 0xEF, 0x06, 0x63, 0xC9, 0xF7, 0x1B, 0x6C,
-0xF1, 0x63, 0x8B, 0xEC, 0x1B, 0xD1, 0x80, 0x31, 0x20, 0x31, 0xE1, 0xF6,
-0x80, 0x41, 0x1C, 0x62, 0x00, 0x1C, 0xFA, 0x5B, 0x1A, 0xD0, 0xD1, 0xF6,
-0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x07, 0xD2, 0x71, 0xF6, 0x80, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x08, 0xD2, 0x71, 0xF6, 0x84, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x09, 0xD2, 0x71, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x0A, 0xD2, 0x71, 0xF6, 0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x0B, 0xD2,
-0x81, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x0C, 0xD2, 0x81, 0xF6,
-0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x0D, 0xD2, 0x81, 0xF6, 0x88, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x0E, 0xD2, 0x81, 0xF6, 0x8C, 0x41, 0xE7, 0xF7,
-0x0E, 0x68, 0x00, 0x1C, 0xFA, 0x5B, 0x0F, 0xD2, 0xD1, 0xF6, 0x80, 0x41,
-0x10, 0xD2, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x30, 0xD1, 0xF6, 0x84, 0x41,
-0x00, 0x30, 0x00, 0x1C, 0xFA, 0x5B, 0x11, 0xD2, 0xD1, 0xF6, 0x88, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x12, 0xD2, 0xB0, 0x67, 0xE1, 0xF6, 0x80, 0x41,
-0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x13, 0xD2, 0xB0, 0x67,
-0xD1, 0xF6, 0x8C, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xB0, 0x67, 0x71, 0xF6, 0x80, 0x41, 0xF2, 0xF2, 0x1B, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67, 0x71, 0xF6, 0x84, 0x41,
-0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67,
-0x71, 0xF6, 0x88, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xB0, 0x67, 0x71, 0xF6, 0x8C, 0x41, 0xF2, 0xF2, 0x1B, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67, 0x81, 0xF6, 0x80, 0x41,
-0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67,
-0x81, 0xF6, 0x84, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xB0, 0x67, 0x81, 0xF6, 0x88, 0x41, 0xF2, 0xF2, 0x1B, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67, 0x81, 0xF6, 0x8C, 0x41,
-0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67,
-0xD1, 0xF6, 0x80, 0x41, 0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xB0, 0x67, 0xD1, 0xF6, 0x84, 0x41, 0xF2, 0xF2, 0x1B, 0x4D,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0xB0, 0x67, 0xD1, 0xF6, 0x88, 0x41,
-0xF2, 0xF2, 0x1B, 0x4D, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0x6A,
-0x04, 0xD2, 0xFF, 0x6A, 0x01, 0x4A, 0x40, 0x30, 0x00, 0xF5, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x15, 0xD2, 0x01, 0xF0, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0x00, 0x30, 0x16, 0xD2, 0x21, 0xF0,
-0x80, 0x41, 0x00, 0xF1, 0xA0, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65,
-0x21, 0xF0, 0x88, 0x41, 0x00, 0xF1, 0xA0, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0xA0, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x2A, 0xF4, 0x10, 0x4D,
-0x01, 0xF4, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0x1C,
-0x5B, 0x1F, 0x05, 0x6C, 0x01, 0xF0, 0x00, 0x6D, 0xA0, 0x35, 0x7F, 0x4D,
-0x01, 0xF4, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x65, 0x4D, 0x00, 0x1C,
-0x5B, 0x1F, 0x05, 0x6C, 0x8F, 0xF7, 0x00, 0x6D, 0xAB, 0xED, 0xA0, 0x35,
-0x21, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0xA0, 0x35, 0x00, 0x1C,
-0x5B, 0x1F, 0x05, 0x6C, 0x00, 0xF2, 0x14, 0x6D, 0xA0, 0x35, 0xA0, 0x35,
-0x00, 0xF1, 0x02, 0x4D, 0x41, 0xF6, 0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x0D, 0xF0, 0x16, 0x6D,
-0xA0, 0x35, 0xA0, 0x35, 0xC0, 0xF4, 0x02, 0x4D, 0x41, 0xF6, 0x84, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C,
-0xC5, 0xF0, 0x11, 0x6D, 0x41, 0xF6, 0x8C, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x00, 0xF2, 0x14, 0x6D,
-0xA0, 0x35, 0xA0, 0x35, 0x00, 0xF1, 0x02, 0x4D, 0x61, 0xF6, 0x80, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C,
-0x05, 0xF0, 0x16, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0x01, 0xF5, 0x05, 0x4D,
-0x61, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x65, 0x00, 0x1C,
-0x5B, 0x1F, 0x05, 0x6C, 0x41, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x15, 0x95, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x41, 0xF6, 0x88, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0x16, 0x95, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C,
-0x00, 0x1C, 0x2C, 0x1F, 0x02, 0x6C, 0x00, 0xF2, 0x00, 0x6D, 0xA0, 0x35,
-0xA0, 0x35, 0xC5, 0xF0, 0x11, 0x4D, 0x61, 0xF6, 0x8C, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x00, 0x65, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x41, 0xF6,
-0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x15, 0x95, 0x00, 0x1C, 0x5B, 0x1F,
-0x05, 0x6C, 0x41, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x16, 0x95,
-0x00, 0x1C, 0x2C, 0x1F, 0x02, 0x6C, 0xA0, 0x6D, 0xA0, 0x35, 0xA0, 0x35,
-0x2A, 0xF4, 0x13, 0x4D, 0x01, 0xF4, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x00, 0x65, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x01, 0xF4, 0x88, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0xE4, 0x6D, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C,
-0x21, 0xF6, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x00, 0x6D, 0x21, 0xF0,
-0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0xB0, 0x67, 0x21, 0xF0, 0x88, 0x41,
-0x00, 0x1C, 0xDD, 0x5B, 0xB0, 0x67, 0xA1, 0xF6, 0x8C, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x05, 0xF0, 0x00, 0x6B, 0x6B, 0xEB, 0x60, 0x33,
-0x60, 0x33, 0x4C, 0xEB, 0x51, 0x23, 0x04, 0x95, 0x01, 0x4D, 0x0A, 0x5D,
-0x04, 0xD5, 0x3F, 0xF7, 0x04, 0x61, 0xC9, 0xF7, 0x1B, 0x68, 0x0B, 0xE8,
-0x00, 0x30, 0x00, 0x30, 0xE1, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x07, 0x95, 0xD1, 0xF6, 0x8C, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x08, 0x95,
-0x71, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x09, 0x95, 0x71, 0xF6,
-0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x0A, 0x95, 0x71, 0xF6, 0x88, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x0B, 0x95, 0x71, 0xF6, 0x8C, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x0C, 0x95, 0x81, 0xF6, 0x80, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x0D, 0x95, 0x81, 0xF6, 0x84, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x0E, 0x95,
-0x81, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x0F, 0x95, 0x81, 0xF6,
-0x8C, 0x40, 0x00, 0x1C, 0xDD, 0x5B, 0x10, 0x95, 0xD1, 0xF6, 0x80, 0x40,
-0x00, 0x1C, 0xDD, 0x5B, 0x11, 0x95, 0xD1, 0xF6, 0x84, 0x40, 0x00, 0x1C,
-0xDD, 0x5B, 0x12, 0x95, 0x81, 0xF6, 0x88, 0x40, 0x00, 0x1C, 0xDD, 0x5B,
-0x13, 0x95, 0x1C, 0x97, 0x1B, 0x91, 0x1A, 0x90, 0x00, 0xEF, 0x0F, 0x63,
-0x81, 0xF4, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF3,
-0x1F, 0x6B, 0x4C, 0xEB, 0x91, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x14, 0xD3, 0xE0, 0xF3, 0x1F, 0x6C, 0x80, 0x34, 0x80, 0x34, 0x8C, 0xEA,
-0x42, 0x33, 0x14, 0x92, 0x62, 0x33, 0x10, 0xF0, 0x02, 0x6D, 0x00, 0xF4,
-0xA0, 0x35, 0x58, 0xEB, 0x63, 0xF3, 0x00, 0x4D, 0x17, 0xD5, 0xE0, 0xF3,
-0x1F, 0x6D, 0x07, 0xF7, 0x00, 0x68, 0x12, 0xEC, 0x82, 0x33, 0x17, 0x94,
-0xAC, 0xEB, 0x00, 0xF4, 0x00, 0x6D, 0x43, 0x9C, 0xAB, 0xED, 0xAC, 0xEA,
-0x6D, 0xEA, 0x43, 0xDC, 0x81, 0xF4, 0x80, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x00, 0x30, 0x17, 0x94, 0x00, 0xF4, 0x00, 0x6B, 0x6B, 0xEB, 0x6C, 0xEA,
-0x63, 0x9C, 0xE0, 0xF3, 0x1F, 0x6D, 0x81, 0xF4, 0x80, 0x41, 0xAC, 0xEB,
-0xA2, 0x67, 0x00, 0x1C, 0xDD, 0x5B, 0x6D, 0xED, 0x00, 0x1C, 0x5B, 0x1F,
-0x05, 0x6C, 0x91, 0xF6, 0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0xE0, 0xF3, 0x1F, 0x6B, 0x60, 0x33, 0x60, 0x33, 0x6C, 0xEA, 0x14, 0x93,
-0x42, 0x32, 0x42, 0x32, 0x78, 0xEA, 0xE0, 0xF3, 0x1F, 0x6C, 0x80, 0x33,
-0x17, 0x94, 0x06, 0xD2, 0x43, 0x9C, 0x12, 0xED, 0xAC, 0xEB, 0x10, 0x6D,
-0xAB, 0xED, 0xA0, 0x35, 0xA0, 0x35, 0xE0, 0xF3, 0x1F, 0x4D, 0x68, 0x33,
-0xAC, 0xEA, 0x6D, 0xEA, 0x43, 0xDC, 0x81, 0xF4, 0x80, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x3F, 0x6B, 0x6B, 0xEB, 0x17, 0x94, 0x60, 0x33,
-0x60, 0x33, 0xFF, 0x4B, 0x6C, 0xEA, 0x63, 0x9C, 0xE0, 0xF3, 0x1F, 0x6D,
-0x3F, 0x6C, 0x62, 0x33, 0x6A, 0x33, 0xAC, 0xEB, 0x8C, 0xEB, 0x60, 0x33,
-0x60, 0x33, 0xA2, 0x67, 0x81, 0xF4, 0x80, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x6D, 0xED, 0x91, 0xF4, 0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0x02, 0xF0, 0x00, 0x6D, 0x06, 0x93, 0xA0, 0x35, 0xA0, 0x35, 0xFF, 0x4D,
-0xC0, 0xF3, 0x00, 0x6C, 0xAC, 0xEA, 0x8C, 0xEB, 0xA2, 0x67, 0x06, 0xD3,
-0x80, 0xF5, 0x60, 0x33, 0x91, 0xF4, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x6D, 0xED, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x11, 0xF4, 0x84, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xA1, 0xF6, 0x84, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x05, 0xD2, 0xE0, 0xF3, 0x1F, 0x6D, 0xA0, 0x35, 0xA0, 0x35,
-0xAC, 0xEA, 0x42, 0x33, 0x05, 0x92, 0x00, 0xF4, 0x00, 0x6C, 0x8B, 0xEC,
-0x62, 0x33, 0x8C, 0xEA, 0x6D, 0xEA, 0x11, 0xF4, 0x84, 0x41, 0xA2, 0x67,
-0x00, 0x1C, 0xDD, 0x5B, 0x05, 0xD2, 0xA1, 0xF6, 0x8C, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0x01, 0x6B, 0x6B, 0xEB, 0x05, 0x95, 0x60, 0x33,
-0x60, 0x33, 0xE0, 0xF3, 0x1F, 0x4B, 0x0C, 0xEA, 0x6C, 0xED, 0x5A, 0x32,
-0x05, 0xD5, 0x11, 0xF4, 0x84, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x4D, 0xED,
-0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF3, 0x1F, 0x6C, 0x4C, 0xEC, 0x14, 0xD4,
-0xB1, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF3,
-0x1F, 0x6D, 0xA0, 0x35, 0xA0, 0x35, 0xAC, 0xEA, 0x42, 0x33, 0x62, 0x33,
-0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x18, 0xD3, 0x18, 0x93,
-0x14, 0x94, 0x98, 0xEB, 0xE0, 0xF3, 0x1F, 0x6B, 0x12, 0xED, 0xA2, 0x34,
-0x17, 0x95, 0x6C, 0xEC, 0x63, 0x9D, 0x00, 0xF4, 0x00, 0x6D, 0xAB, 0xED,
-0xAC, 0xEB, 0x8D, 0xEB, 0x17, 0x94, 0xAC, 0xEA, 0xE0, 0xF3, 0x1F, 0x6D,
-0x63, 0xDC, 0xAC, 0xEB, 0xA2, 0x67, 0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C,
-0xDD, 0x5B, 0x6D, 0xED, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0xB1, 0xF6,
-0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0xE0, 0xF3, 0x1F, 0x6B,
-0x60, 0x33, 0x60, 0x33, 0x6C, 0xEA, 0x14, 0x93, 0x42, 0x32, 0x42, 0x32,
-0x78, 0xEA, 0xE0, 0xF3, 0x1F, 0x6C, 0x80, 0x33, 0x17, 0x94, 0x06, 0xD2,
-0x43, 0x9C, 0x12, 0xED, 0xAC, 0xEB, 0x10, 0x6D, 0xAB, 0xED, 0xA0, 0x35,
-0xA0, 0x35, 0xE0, 0xF3, 0x1F, 0x4D, 0x68, 0x33, 0xAC, 0xEA, 0x6D, 0xEA,
-0x43, 0xDC, 0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65,
-0x10, 0xF0, 0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xBD, 0xF7, 0x18, 0x4B,
-0x17, 0x94, 0xA0, 0x9B, 0xE0, 0xF3, 0x1F, 0x6B, 0x4C, 0xED, 0x43, 0x9C,
-0x3F, 0x6C, 0x42, 0x32, 0x4A, 0x32, 0x6C, 0xEA, 0x8C, 0xEA, 0x40, 0x32,
-0x40, 0x32, 0x81, 0xF4, 0x88, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x4D, 0xED,
-0x91, 0xF4, 0x8C, 0x41, 0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x10, 0xF0,
-0x02, 0x6B, 0x00, 0xF4, 0x60, 0x33, 0xBD, 0xF7, 0x1C, 0x4B, 0xA0, 0x9B,
-0x06, 0x94, 0x4C, 0xED, 0xC0, 0xF3, 0x00, 0x6A, 0x4C, 0xEC, 0x80, 0xF5,
-0x80, 0x32, 0x91, 0xF4, 0x8C, 0x41, 0x00, 0x1C, 0xDD, 0x5B, 0x4D, 0xED,
-0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x11, 0xF4, 0x8C, 0x41, 0x00, 0x1C,
-0xFA, 0x5B, 0x00, 0x65, 0xC1, 0xF6, 0x84, 0x41, 0x00, 0x1C, 0xFA, 0x5B,
-0x05, 0xD2, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0xDD, 0xF7,
-0x00, 0x4C, 0x60, 0x9C, 0x05, 0x95, 0x11, 0xF4, 0x8C, 0x41, 0x4C, 0xEB,
-0x00, 0xF4, 0x00, 0x6A, 0x4B, 0xEA, 0x62, 0x33, 0x62, 0x33, 0x4C, 0xED,
-0x6D, 0xED, 0x00, 0x1C, 0xDD, 0x5B, 0x05, 0xD5, 0xC1, 0xF6, 0x8C, 0x41,
-0x00, 0x1C, 0xFA, 0x5B, 0x00, 0x65, 0x01, 0x6C, 0x8B, 0xEC, 0x05, 0x93,
-0x80, 0x34, 0x80, 0x34, 0xE0, 0xF3, 0x1F, 0x4C, 0x8C, 0xEB, 0x4C, 0xE8,
-0xA3, 0x67, 0x1A, 0x30, 0x11, 0xF4, 0x8C, 0x41, 0x00, 0x1C, 0xDD, 0x5B,
-0x0D, 0xED, 0x00, 0x1C, 0x5B, 0x1F, 0x05, 0x6C, 0x1E, 0x16, 0x00, 0x00,
-0xFC, 0x63, 0x00, 0x6B, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x9D, 0x67, 0x26, 0xF7, 0x61, 0xC2, 0x42, 0x6A, 0x50, 0xC4, 0x43, 0x6A,
-0x51, 0xC4, 0x4E, 0x6A, 0x52, 0xC4, 0x73, 0xC4, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x9E, 0xF5, 0x18, 0x4C, 0xC0, 0xF7, 0x10, 0x6A,
-0x43, 0xDC, 0xBD, 0x67, 0x01, 0x6A, 0x10, 0xF0, 0x01, 0x6E, 0x00, 0xF4,
-0xC0, 0x36, 0x54, 0xC4, 0x13, 0xF6, 0x11, 0x4E, 0x06, 0x62, 0x00, 0x1C,
-0xCF, 0x20, 0x10, 0x4D, 0x06, 0x97, 0x00, 0xEF, 0x04, 0x63, 0x00, 0x00,
-0xE0, 0x63, 0x3E, 0x62, 0x3C, 0xD0, 0x3D, 0xD1, 0x10, 0xF0, 0x02, 0x6D,
-0x00, 0xF4, 0xA0, 0x35, 0xC7, 0x63, 0x04, 0x04, 0xDD, 0xF7, 0x04, 0x4D,
-0x00, 0x1C, 0xF4, 0x54, 0x94, 0x6E, 0x9D, 0x67, 0x7F, 0x4C, 0x10, 0xF0,
-0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0xFF, 0x6E, 0x29, 0x4C, 0x5E, 0xF0,
-0x18, 0x4D, 0x00, 0x1C, 0xF4, 0x54, 0x09, 0x4E, 0x9D, 0x67, 0x10, 0xF0,
-0x02, 0x6D, 0x00, 0xF4, 0xA0, 0x35, 0xFF, 0x6E, 0xA0, 0xF1, 0x10, 0x4C,
-0x7E, 0xF1, 0x00, 0x4D, 0x00, 0x1C, 0xF4, 0x54, 0x09, 0x4E, 0x10, 0xF0,
-0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0x00, 0x6B,
-0x63, 0xC2, 0x00, 0x68, 0xA2, 0x67, 0xFF, 0x6C, 0x08, 0x32, 0x04, 0x06,
-0xAD, 0xE2, 0xC9, 0xE2, 0x40, 0x9A, 0x01, 0x48, 0x8C, 0xE8, 0x25, 0x58,
-0x46, 0xDB, 0xF6, 0x61, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32,
-0x63, 0xF3, 0x00, 0x4A, 0x00, 0x68, 0x0A, 0x65, 0xFF, 0x69, 0x0C, 0x32,
-0x68, 0x67, 0x04, 0x04, 0x00, 0x6D, 0x7D, 0xE2, 0x99, 0xE2, 0xAD, 0xE6,
-0x80, 0xF0, 0x58, 0xA3, 0xB1, 0xE7, 0x01, 0x4D, 0xA0, 0xF0, 0x4C, 0xC4,
-0xA0, 0xF1, 0x40, 0xA3, 0x2C, 0xED, 0x08, 0x5D, 0xA0, 0xF1, 0x54, 0xC4,
-0xF2, 0x61, 0x01, 0x48, 0x2C, 0xE8, 0x21, 0x58, 0xE8, 0x61, 0xC8, 0x67,
-0x1F, 0x6A, 0xA0, 0xF2, 0x5E, 0xC6, 0x00, 0x6F, 0x01, 0x6A, 0x62, 0x9E,
-0xA0, 0xF2, 0xFF, 0xC6, 0xC0, 0xF2, 0x40, 0xC6, 0x10, 0xF0, 0x00, 0x6E,
-0xC0, 0x36, 0xC0, 0x36, 0xFF, 0x4E, 0x40, 0x6A, 0xCC, 0xEB, 0x4B, 0xEA,
-0x4C, 0xEB, 0x0C, 0x6A, 0x4D, 0xEB, 0x07, 0xF7, 0x01, 0x6A, 0x4B, 0xEA,
-0x4C, 0xEB, 0x03, 0xF0, 0x00, 0x6A, 0x4D, 0xEB, 0x07, 0xF7, 0x00, 0x6A,
-0x4B, 0xEA, 0x08, 0xF0, 0x00, 0x6C, 0x40, 0x32, 0x8B, 0xEC, 0xFF, 0x4A,
-0x80, 0x34, 0x4C, 0xEB, 0x4F, 0x44, 0x4C, 0xEB, 0x10, 0xF0, 0x00, 0x6A,
-0x4B, 0xEA, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB, 0x40, 0x6A, 0x4D, 0xEB,
-0x08, 0xF0, 0x00, 0x6D, 0x81, 0x6A, 0xAD, 0xEB, 0x4B, 0xEA, 0x4C, 0xEB,
-0xFF, 0x6A, 0x01, 0x4A, 0x4B, 0xEA, 0x40, 0x32, 0xEF, 0xF7, 0x1F, 0x4A,
-0x4C, 0xEB, 0x0C, 0xF0, 0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32,
-0xFF, 0x4A, 0x4C, 0xEB, 0x48, 0x67, 0x62, 0xDA, 0xA0, 0x35, 0x63, 0x9A,
-0x44, 0x9A, 0x80, 0x34, 0xA0, 0x35, 0xFF, 0x4C, 0xFF, 0x4D, 0xAC, 0xEA,
-0x8C, 0xEB, 0x88, 0x67, 0x44, 0xDC, 0x01, 0x6A, 0x4B, 0xEA, 0xC0, 0xF2,
-0x42, 0xC4, 0xFF, 0x6A, 0xCC, 0xEB, 0xC0, 0xF2, 0x44, 0xCC, 0x12, 0x6A,
-0xC0, 0xF2, 0xE6, 0xC4, 0x63, 0xDC, 0xC0, 0xF2, 0x47, 0xC4, 0x00, 0x1C,
-0xF6, 0x48, 0x00, 0x65, 0x39, 0x63, 0x3E, 0x97, 0x3D, 0x91, 0x3C, 0x90,
-0x00, 0xEF, 0x20, 0x63, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34,
-0x63, 0xF3, 0x00, 0x4C, 0xFF, 0xF7, 0x1F, 0x6A, 0x66, 0xF7, 0x4C, 0xDC,
-0x01, 0x6A, 0x4B, 0xEA, 0xFC, 0x63, 0x45, 0xC4, 0x1C, 0x6A, 0x06, 0x62,
-0xC0, 0xF2, 0x4F, 0xC4, 0xC0, 0xF2, 0x51, 0xC4, 0x0A, 0x6A, 0x3E, 0x6B,
-0xC0, 0xF2, 0x52, 0xC4, 0x40, 0x9C, 0xC0, 0xF2, 0x6E, 0xC4, 0xC0, 0xF2,
-0x70, 0xC4, 0x02, 0x6B, 0x6B, 0xEB, 0x6C, 0xEA, 0x21, 0x6B, 0x6B, 0xEB,
-0x6C, 0xEA, 0x00, 0x6D, 0x40, 0xDC, 0x06, 0xF0, 0x00, 0x6A, 0xE0, 0xF2,
-0xA6, 0xC4, 0x4B, 0xEA, 0xE0, 0xF2, 0x64, 0x9C, 0x40, 0x32, 0x40, 0x32,
-0xFF, 0x4A, 0x4C, 0xEB, 0x20, 0x6A, 0xC0, 0xF2, 0x57, 0xC4, 0x08, 0xF0,
-0x00, 0x6A, 0x4B, 0xEA, 0x40, 0x32, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB,
-0x10, 0xF0, 0x00, 0x6A, 0x40, 0x32, 0x40, 0x32, 0xFF, 0x4A, 0x4C, 0xEB,
-0x20, 0x6A, 0xC0, 0xF2, 0x48, 0xCC, 0xFF, 0x6A, 0x01, 0x4A, 0xE0, 0xF2,
-0x64, 0xDC, 0xC0, 0xF2, 0x4A, 0xCC, 0x01, 0x6B, 0x00, 0xF2, 0x00, 0x6A,
-0xC0, 0xF2, 0xB6, 0xC4, 0xC0, 0xF2, 0xB4, 0xC4, 0xC0, 0xF2, 0xB5, 0xC4,
-0xC0, 0xF2, 0x4C, 0xCC, 0x61, 0xC4, 0x44, 0x6A, 0x9D, 0x67, 0x50, 0xC4,
-0x49, 0x6A, 0x51, 0xC4, 0x47, 0x6A, 0x52, 0xC4, 0xB3, 0xC4, 0x10, 0xF0,
-0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x7E, 0xF5, 0x1C, 0x4C, 0xC0, 0xF7,
-0x10, 0x6A, 0xBD, 0x67, 0x10, 0xF0, 0x01, 0x6E, 0x00, 0xF4, 0xC0, 0x36,
-0x43, 0xDC, 0x74, 0xC4, 0x93, 0xF6, 0x19, 0x4E, 0x00, 0x1C, 0xCF, 0x20,
-0x10, 0x4D, 0x06, 0x97, 0x00, 0xEF, 0x04, 0x63, 0xFA, 0x63, 0x08, 0xD0,
-0x10, 0xF0, 0x02, 0x68, 0x00, 0xF4, 0x00, 0x30, 0x63, 0xF3, 0x00, 0x48,
-0x40, 0x98, 0x11, 0x6B, 0x6B, 0xEB, 0x6C, 0xEA, 0x09, 0x6B, 0x6B, 0xEB,
-0x6C, 0xEA, 0x40, 0xD8, 0x7D, 0x67, 0x44, 0x6A, 0x50, 0xC3, 0x49, 0x6A,
-0x09, 0xD1, 0x51, 0xC3, 0x00, 0x69, 0x47, 0x6A, 0x10, 0xF0, 0x02, 0x6C,
-0x00, 0xF4, 0x80, 0x34, 0x1E, 0xF6, 0x08, 0x4C, 0x52, 0xC3, 0x33, 0xC3,
-0x14, 0x6A, 0x01, 0x6B, 0xBD, 0x67, 0x10, 0xF0, 0x01, 0x6E, 0x00, 0xF4,
-0xC0, 0x36, 0x43, 0xDC, 0x74, 0xC4, 0x10, 0x4D, 0x95, 0xF0, 0x05, 0x4E,
-0x0A, 0x62, 0x00, 0x1C, 0xCF, 0x20, 0x23, 0xC8, 0x5D, 0x67, 0x47, 0x6B,
-0x78, 0xC2, 0x7D, 0x67, 0x3B, 0x6A, 0x59, 0xC3, 0x43, 0x6A, 0x5A, 0xC3,
-0x01, 0x6A, 0x4B, 0xEA, 0x00, 0xF3, 0x44, 0xC0, 0xFF, 0x6A, 0x01, 0x4A,
-0x3B, 0xC3, 0x4B, 0xEA, 0x00, 0xF3, 0x64, 0x98, 0x40, 0x32, 0x40, 0x32,
-0xE0, 0xF0, 0x1F, 0x4A, 0x4C, 0xEB, 0x00, 0xF2, 0x00, 0x6A, 0x40, 0x32,
-0xF3, 0xF0, 0x14, 0x4A, 0x00, 0xF3, 0x4C, 0xD8, 0xFF, 0x6A, 0x01, 0x4A,
-0x40, 0x32, 0x46, 0xF0, 0x16, 0x4A, 0x00, 0xF3, 0x64, 0xD8, 0x00, 0xF3,
-0x50, 0xD8, 0x60, 0x98, 0x02, 0x6A, 0x00, 0xF3, 0x47, 0xC0, 0x05, 0x6A,
-0x4B, 0xEA, 0x00, 0x6C, 0x4C, 0xEB, 0x81, 0x6A, 0x00, 0xF3, 0x88, 0xD8,
-0x00, 0xF3, 0x94, 0xD8, 0x00, 0xF3, 0x98, 0xD8, 0x4B, 0xEA, 0x10, 0xF0,
-0x02, 0x6C, 0x00, 0xF4, 0x80, 0x34, 0x4C, 0xEB, 0xBE, 0xF5, 0x14, 0x4C,
-0xC0, 0xF7, 0x10, 0x6A, 0x60, 0xD8, 0xBD, 0x67, 0x43, 0xDC, 0x10, 0xF0,
-0x01, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0x01, 0x6A, 0x54, 0xC4, 0x55, 0xF1,
-0x09, 0x4E, 0x00, 0x1C, 0xCF, 0x20, 0x18, 0x4D, 0x4A, 0x6A, 0x00, 0xF3,
-0x5C, 0xC0, 0x45, 0x6A, 0x00, 0xF3, 0x5D, 0xC0, 0x46, 0x6A, 0x00, 0xF3,
-0x5E, 0xC0, 0x40, 0x6A, 0x00, 0xF3, 0x5F, 0xC0, 0x23, 0x6A, 0x20, 0xF3,
-0x40, 0xC0, 0x1E, 0x6A, 0x20, 0xF3, 0x41, 0xC0, 0x0A, 0x97, 0x09, 0x91,
-0x08, 0x90, 0x00, 0xEF, 0x06, 0x63, 0x00, 0x00, 0xFC, 0x63, 0x7D, 0x67,
-0x3B, 0x6A, 0x50, 0xC3, 0x43, 0x6A, 0x51, 0xC3, 0x36, 0x6A, 0x52, 0xC3,
-0x00, 0x6B, 0x5D, 0x67, 0x73, 0xC2, 0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4,
-0x40, 0x32, 0x63, 0xF3, 0x00, 0x4A, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4,
-0x80, 0x34, 0xDE, 0xF5, 0x10, 0x4C, 0xC0, 0xF2, 0x73, 0xC2, 0xC0, 0xF7,
-0x10, 0x6A, 0x43, 0xDC, 0xBD, 0x67, 0x01, 0x6A, 0x10, 0xF0, 0x01, 0x6E,
-0x00, 0xF4, 0xC0, 0x36, 0x54, 0xC4, 0x95, 0xF4, 0x05, 0x4E, 0x06, 0x62,
-0x00, 0x1C, 0xCF, 0x20, 0x10, 0x4D, 0x06, 0x97, 0x00, 0xEF, 0x04, 0x63,
-0x10, 0xF0, 0x02, 0x6A, 0x00, 0xF4, 0x40, 0x32, 0xFC, 0x63, 0x63, 0xF3,
-0x00, 0x4A, 0x01, 0x6D, 0x00, 0x6B, 0x9D, 0x67, 0x66, 0xF7, 0xB6, 0xCA,
-0x66, 0xF7, 0x74, 0xCA, 0x52, 0x6A, 0x50, 0xC4, 0x53, 0x6A, 0x51, 0xC4,
-0x54, 0x6A, 0x52, 0xC4, 0x73, 0xC4, 0x10, 0xF0, 0x02, 0x6C, 0x00, 0xF4,
-0x80, 0x34, 0x3E, 0xF6, 0x04, 0x4C, 0xE0, 0xF1, 0x14, 0x6A, 0xB4, 0xC4,
-0x10, 0xF0, 0x02, 0x6E, 0x00, 0xF4, 0xC0, 0x36, 0xBD, 0x67, 0x43, 0xDC,
-0x10, 0xF5, 0x0D, 0x4E, 0x06, 0x62, 0x00, 0x1C, 0xCF, 0x20, 0x10, 0x4D,
-0x06, 0x97, 0x00, 0xEF, 0x04, 0x63, 0x00, 0x65, 0xD8, 0xFF, 0xBD, 0x27,
-0x02, 0x80, 0x03, 0x3C, 0x20, 0x00, 0xBF, 0xAF, 0x1C, 0x00, 0xB1, 0xAF,
-0x18, 0x00, 0xB0, 0xAF, 0x74, 0xF2, 0x62, 0x24, 0x02, 0x00, 0x48, 0x90,
-0x74, 0xF2, 0x67, 0x94, 0x02, 0x80, 0x02, 0x3C, 0xD0, 0x5D, 0x42, 0x24,
-0x02, 0x00, 0x10, 0x24, 0x01, 0x80, 0x06, 0x3C, 0x21, 0x20, 0x40, 0x00,
-0x14, 0x00, 0x50, 0xA0, 0x10, 0x00, 0xA5, 0x27, 0xFC, 0xC1, 0xC6, 0x24,
-0x02, 0x80, 0x11, 0x3C, 0x20, 0x5E, 0x31, 0x26, 0x10, 0x00, 0xA7, 0xA7,
-0x12, 0x00, 0xA8, 0xA3, 0xCF, 0x20, 0x00, 0x0C, 0x13, 0x00, 0xA0, 0xA3,
-0x02, 0x80, 0x06, 0x3C, 0x21, 0x20, 0x20, 0x02, 0x10, 0x00, 0xA5, 0x27,
-0x14, 0x00, 0x30, 0xA2, 0xCF, 0x20, 0x00, 0x0C, 0x08, 0x86, 0xC6, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0xEC, 0x5D, 0x40, 0xA0, 0x0C, 0x00, 0x04, 0x24,
-0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0xED, 0x5D, 0x64, 0xA0,
-0xEE, 0x5D, 0x44, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0x04, 0x5E, 0x60, 0xA0, 0x06, 0x5E, 0x40, 0xA0, 0x02, 0x80, 0x03, 0x3C,
-0x02, 0x80, 0x02, 0x3C, 0x0C, 0x5E, 0x60, 0xA0, 0x01, 0x00, 0x06, 0x24,
-0x0D, 0x5E, 0x40, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C,
-0xF0, 0x5D, 0x66, 0xA0, 0x12, 0x00, 0x04, 0x24, 0x0E, 0x5E, 0x40, 0xA0,
-0x02, 0x80, 0x03, 0x3C, 0x02, 0x80, 0x02, 0x3C, 0xEF, 0x5D, 0x66, 0xA0,
-0xF1, 0x5D, 0x44, 0xA0, 0x02, 0x80, 0x03, 0x3C, 0x0C, 0x00, 0x04, 0x24,
-0x02, 0x80, 0x02, 0x3C, 0xF2, 0x5D, 0x60, 0xA0, 0x02, 0x80, 0x05, 0x3C,
-0xFC, 0x5D, 0x44, 0xA4, 0x64, 0x00, 0x03, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0xF4, 0x5D, 0xA3, 0xA4, 0xC6, 0x5C, 0x43, 0x90, 0xF4, 0x5D, 0xA4, 0x94,
-0x02, 0x00, 0x05, 0x24, 0x02, 0x00, 0x63, 0x30, 0x01, 0x00, 0x63, 0x2C,
-0xFF, 0xFF, 0x84, 0x30, 0x23, 0x28, 0xA3, 0x00, 0x80, 0x22, 0x04, 0x00,
-0x02, 0x80, 0x02, 0x3C, 0xE8, 0x03, 0x03, 0x24, 0xF8, 0x5D, 0x44, 0xAC,
-0x0C, 0x00, 0x23, 0xAE, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x00, 0x5E, 0x40, 0xAC, 0x05, 0x5E, 0x60, 0xA0, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x07, 0x5E, 0x40, 0xA0, 0x0F, 0x5E, 0x60, 0xA0,
-0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C, 0x3C, 0x5E, 0x45, 0xA0,
-0x20, 0x00, 0xBF, 0x8F, 0x08, 0x5E, 0x60, 0xA0, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x1C, 0x00, 0xB1, 0x8F, 0x18, 0x00, 0xB0, 0x8F,
-0x09, 0x5E, 0x46, 0xA0, 0x0A, 0x5E, 0x66, 0xA0, 0x02, 0x80, 0x02, 0x3C,
-0x02, 0x80, 0x03, 0x3C, 0x0B, 0x5E, 0x40, 0xA0, 0x21, 0x20, 0x00, 0x00,
-0x10, 0x5E, 0x60, 0xAC, 0x02, 0x80, 0x02, 0x3C, 0x02, 0x80, 0x03, 0x3C,
-0x21, 0x28, 0x00, 0x00, 0x28, 0x00, 0xBD, 0x27, 0x14, 0x5E, 0x40, 0xAC,
-0x18, 0x5E, 0x64, 0xAC, 0x1C, 0x5E, 0x65, 0xAC, 0x08, 0x00, 0xE0, 0x03,
-0x00, 0x00, 0x00, 0x00, 0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB3, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x20, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x21, 0x98, 0xA0, 0x00,
-0x21, 0x88, 0xC0, 0x00, 0x21, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0x82,
-0x5C, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x40, 0x14,
-0x01, 0x00, 0x10, 0x26, 0xFF, 0xFF, 0x10, 0x26, 0x00, 0x00, 0x04, 0x92,
-0x2B, 0x00, 0x02, 0x24, 0x00, 0x1E, 0x04, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x41, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x24,
-0x30, 0x00, 0x22, 0x12, 0x00, 0x1E, 0x04, 0x00, 0x07, 0x00, 0x20, 0x16,
-0x21, 0x18, 0x80, 0x00, 0x00, 0x1E, 0x04, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x30, 0x00, 0x02, 0x24, 0x3B, 0x00, 0x62, 0x10, 0x0A, 0x00, 0x11, 0x24,
-0x21, 0x18, 0x80, 0x00, 0x00, 0x16, 0x03, 0x00, 0x03, 0x16, 0x02, 0x00,
-0x1A, 0x00, 0x40, 0x10, 0xFF, 0x00, 0x64, 0x30, 0xA9, 0xFF, 0x82, 0x24,
-0x61, 0x00, 0x83, 0x2C, 0xFF, 0x00, 0x45, 0x30, 0x09, 0x00, 0x60, 0x10,
-0x41, 0x00, 0x86, 0x2C, 0xC9, 0xFF, 0x82, 0x24, 0xFF, 0x00, 0x45, 0x30,
-0x05, 0x00, 0xC0, 0x10, 0x3A, 0x00, 0x87, 0x2C, 0xD0, 0xFF, 0x82, 0x24,
-0x02, 0x00, 0xE0, 0x10, 0xFF, 0x00, 0x05, 0x24, 0xFF, 0x00, 0x45, 0x30,
-0x2A, 0x10, 0xB1, 0x00, 0x0A, 0x00, 0x40, 0x10, 0x18, 0x00, 0x51, 0x02,
-0x01, 0x00, 0x10, 0x26, 0x12, 0x10, 0x00, 0x00, 0x2B, 0x18, 0x52, 0x00,
-0x23, 0x00, 0x60, 0x14, 0x21, 0x90, 0xA2, 0x00, 0x00, 0x00, 0x03, 0x92,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0xFF, 0x60, 0x14, 0xFF, 0x00, 0x64, 0x30,
-0x02, 0x00, 0x60, 0x12, 0x21, 0x10, 0x40, 0x02, 0x00, 0x00, 0x70, 0xAE,
-0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0x08, 0x00, 0xE0, 0x03,
-0x28, 0x00, 0xBD, 0x27, 0x03, 0x1E, 0x03, 0x00, 0x30, 0x00, 0x02, 0x24,
-0xCE, 0xFF, 0x62, 0x14, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x82,
-0x78, 0x00, 0x02, 0x24, 0x03, 0x00, 0x62, 0x10, 0x58, 0x00, 0x02, 0x24,
-0xD0, 0xFF, 0x62, 0x14, 0x21, 0x18, 0x80, 0x00, 0x02, 0x00, 0x10, 0x26,
-0x00, 0x00, 0x04, 0x92, 0x63, 0x71, 0x00, 0x08, 0x10, 0x00, 0x11, 0x24,
-0x01, 0x00, 0x10, 0x26, 0x00, 0x00, 0x04, 0x92, 0x5A, 0x71, 0x00, 0x08,
-0x10, 0x00, 0x02, 0x24, 0x8F, 0x71, 0x00, 0x08, 0x08, 0x00, 0x11, 0x24,
-0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xFF, 0xFF, 0x02, 0x24,
-0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27, 0x21, 0x48, 0x80, 0x00,
-0x31, 0x00, 0xC0, 0x14, 0x21, 0x50, 0x00, 0x00, 0x00, 0x00, 0x87, 0x90,
-0x30, 0x00, 0x02, 0x24, 0x00, 0x1E, 0x07, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x2E, 0x00, 0x62, 0x10, 0x0A, 0x00, 0x06, 0x24, 0x02, 0x80, 0x02, 0x3C,
-0x40, 0xF4, 0x4B, 0x24, 0xFF, 0x00, 0xE8, 0x30, 0x21, 0x10, 0x0B, 0x01,
-0x00, 0x00, 0x44, 0x90, 0x00, 0x1E, 0x07, 0x00, 0x03, 0x1E, 0x03, 0x00,
-0x44, 0x00, 0x82, 0x30, 0x02, 0x00, 0x87, 0x30, 0xD0, 0xFF, 0x63, 0x24,
-0x1A, 0x00, 0x40, 0x10, 0x04, 0x00, 0x84, 0x30, 0x07, 0x00, 0x80, 0x14,
-0x2B, 0x10, 0x66, 0x00, 0x21, 0x10, 0x00, 0x01, 0x02, 0x00, 0xE0, 0x10,
-0xE0, 0xFF, 0x03, 0x25, 0xFF, 0x00, 0x62, 0x30, 0xC9, 0xFF, 0x43, 0x24,
-0x2B, 0x10, 0x66, 0x00, 0x10, 0x00, 0x40, 0x10, 0x18, 0x00, 0x46, 0x01,
-0x01, 0x00, 0x29, 0x25, 0x00, 0x00, 0x27, 0x91, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0x00, 0xE8, 0x30, 0x12, 0x10, 0x00, 0x00, 0x21, 0x50, 0x43, 0x00,
-0x21, 0x10, 0x0B, 0x01, 0x00, 0x00, 0x44, 0x90, 0x00, 0x1E, 0x07, 0x00,
-0x03, 0x1E, 0x03, 0x00, 0x44, 0x00, 0x82, 0x30, 0x02, 0x00, 0x87, 0x30,
-0xD0, 0xFF, 0x63, 0x24, 0xE8, 0xFF, 0x40, 0x14, 0x04, 0x00, 0x84, 0x30,
-0x02, 0x00, 0xA0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0xAC,
-0x08, 0x00, 0xE0, 0x03, 0x21, 0x10, 0x40, 0x01, 0x00, 0x00, 0x87, 0x90,
-0xB1, 0x71, 0x00, 0x08, 0x02, 0x80, 0x02, 0x3C, 0x01, 0x00, 0x89, 0x24,
-0x00, 0x00, 0x27, 0x91, 0x78, 0x00, 0x02, 0x24, 0x00, 0x1E, 0x07, 0x00,
-0x03, 0x1E, 0x03, 0x00, 0xCD, 0xFF, 0x62, 0x14, 0x08, 0x00, 0x06, 0x24,
-0x01, 0x00, 0x22, 0x91, 0x02, 0x80, 0x03, 0x3C, 0x40, 0xF4, 0x63, 0x24,
-0x21, 0x10, 0x43, 0x00, 0x00, 0x00, 0x44, 0x90, 0x00, 0x00, 0x00, 0x00,
-0x44, 0x00, 0x84, 0x30, 0xC5, 0xFF, 0x80, 0x10, 0x02, 0x80, 0x02, 0x3C,
-0x01, 0x00, 0x29, 0x25, 0x00, 0x00, 0x27, 0x91, 0xB1, 0x71, 0x00, 0x08,
-0x10, 0x00, 0x06, 0x24, 0xE8, 0xFF, 0xBD, 0x27, 0x10, 0x00, 0xBF, 0xAF,
-0x00, 0x00, 0x83, 0x80, 0x2D, 0x00, 0x02, 0x24, 0x04, 0x00, 0x62, 0x10,
-0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xBF, 0x8F, 0xA7, 0x71, 0x00, 0x08,
-0x18, 0x00, 0xBD, 0x27, 0xA7, 0x71, 0x00, 0x0C, 0x01, 0x00, 0x84, 0x24,
-0x10, 0x00, 0xBF, 0x8F, 0x23, 0x10, 0x02, 0x00, 0x08, 0x00, 0xE0, 0x03,
-0x18, 0x00, 0xBD, 0x27, 0xD8, 0xFF, 0xBD, 0x27, 0x1C, 0x00, 0xB3, 0xAF,
-0x18, 0x00, 0xB2, 0xAF, 0x14, 0x00, 0xB1, 0xAF, 0x10, 0x00, 0xB0, 0xAF,
-0x20, 0x00, 0xBF, 0xAF, 0x21, 0x80, 0x80, 0x00, 0x21, 0x90, 0xA0, 0x00,
-0x21, 0x98, 0xC0, 0x00, 0x21, 0x88, 0x00, 0x00, 0x00, 0x00, 0x04, 0x82,
-0x5C, 0x58, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x40, 0x14,
-0x01, 0x00, 0x10, 0x26, 0xFF, 0xFF, 0x10, 0x26, 0x00, 0x00, 0x03, 0x82,
-0x2D, 0x00, 0x02, 0x24, 0x0F, 0x00, 0x62, 0x10, 0x21, 0x20, 0x00, 0x02,
-0x21, 0x28, 0x40, 0x02, 0x43, 0x71, 0x00, 0x0C, 0x21, 0x30, 0x60, 0x02,
-0x12, 0x00, 0x40, 0x04, 0x21, 0x18, 0x40, 0x00, 0x23, 0x10, 0x02, 0x00,
-0x0A, 0x10, 0x71, 0x00, 0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F,
-0x18, 0x00, 0xB2, 0x8F, 0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F,
-0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27, 0x01, 0x00, 0x10, 0x26,
-0x21, 0x20, 0x00, 0x02, 0x21, 0x28, 0x40, 0x02, 0x43, 0x71, 0x00, 0x0C,
-0x21, 0x30, 0x60, 0x02, 0xFF, 0xFF, 0x11, 0x24, 0xF0, 0xFF, 0x41, 0x04,
-0x21, 0x18, 0x40, 0x00, 0xF0, 0xFF, 0x20, 0x16, 0x00, 0x80, 0x02, 0x3C,
-0x20, 0x00, 0xBF, 0x8F, 0x1C, 0x00, 0xB3, 0x8F, 0x18, 0x00, 0xB2, 0x8F,
-0x14, 0x00, 0xB1, 0x8F, 0x10, 0x00, 0xB0, 0x8F, 0xFF, 0x7F, 0x02, 0x3C,
-0xFF, 0xFF, 0x42, 0x34, 0x08, 0x00, 0xE0, 0x03, 0x28, 0x00, 0xBD, 0x27,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7F,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x02, 0x7E, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x03, 0x7D,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x04, 0x7C, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x05, 0x7B, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x06, 0x7A,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x07, 0x79, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x08, 0x78, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x09, 0x77,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x0A, 0x76, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x0B, 0x75, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x74,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x0D, 0x73, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x0E, 0x72, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x0F, 0x71,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x10, 0x70, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x11, 0x6F, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x12, 0x6F,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x13, 0x6E, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x14, 0x6D, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x15, 0x6D,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x16, 0x6C, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x17, 0x6B, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x18, 0x6A,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x19, 0x6A, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x1A, 0x69, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x1B, 0x68,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x1C, 0x67, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x1D, 0x66, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x1E, 0x65,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x1F, 0x64, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x20, 0x63, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x21, 0x4C,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x22, 0x4B, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x23, 0x4A, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x24, 0x49,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x25, 0x48, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x26, 0x47, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x27, 0x46,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x28, 0x45, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x29, 0x44, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x2A, 0x2C,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x2B, 0x2B, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x2C, 0x2A, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x2D, 0x29,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x2E, 0x28, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x2F, 0x27, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x30, 0x26,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x31, 0x25, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x32, 0x24, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x33, 0x23,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x34, 0x22, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x35, 0x09, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x36, 0x08,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x37, 0x07, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x38, 0x06, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x39, 0x05,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x3A, 0x04, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x3B, 0x03, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x3C, 0x02,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x3D, 0x01, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x3E, 0x00, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x3F, 0x00,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x40, 0x7F, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x41, 0x7F, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x42, 0x7E,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x43, 0x7D, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x44, 0x7C, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x45, 0x7B,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x46, 0x7A, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x47, 0x79, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x48, 0x78,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x49, 0x77, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x4A, 0x76, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x4B, 0x75,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x4C, 0x74, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x4D, 0x73, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x4E, 0x72,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x4F, 0x71, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x50, 0x70, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x51, 0x6F,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x52, 0x6F, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x53, 0x6E, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x54, 0x6D,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x55, 0x6D, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x56, 0x6C, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x57, 0x6B,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x58, 0x6A, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x59, 0x6A, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x5A, 0x69,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x5B, 0x68, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x5C, 0x67, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x5D, 0x66,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x5E, 0x65, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x5F, 0x64, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x60, 0x63,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x61, 0x4C, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x62, 0x4B, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x63, 0x4A,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x64, 0x49, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x65, 0x48, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x66, 0x47,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x67, 0x46, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x68, 0x45, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x69, 0x44,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x6A, 0x2C, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x6B, 0x2B, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x6C, 0x2A,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x6D, 0x29, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x6E, 0x28, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x6F, 0x27,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x70, 0x26, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x71, 0x25, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x72, 0x24,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x73, 0x23, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x74, 0x22, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x75, 0x09,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x76, 0x08, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x77, 0x07, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x78, 0x06,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x79, 0x05, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x7A, 0x04, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x7B, 0x03,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x7C, 0x02, 0x78, 0x0C, 0x00, 0x00,
-0x01, 0x00, 0x7D, 0x01, 0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x7E, 0x00,
-0x78, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x7F, 0x00, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x00, 0x30, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x01, 0x30,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x02, 0x30, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x03, 0x30, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x04, 0x30,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x05, 0x34, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x06, 0x38, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x07, 0x3E,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x08, 0x3E, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x09, 0x44, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x0A, 0x46,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x0B, 0x48, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x0C, 0x48, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x0D, 0x4E,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x0E, 0x56, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x0F, 0x5A, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x10, 0x5E,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x11, 0x62, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x12, 0x6C, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x13, 0x72,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x14, 0x72, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x15, 0x72, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x16, 0x72,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x17, 0x72, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x18, 0x72, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x19, 0x72,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x1A, 0x72, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x1B, 0x72, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x1C, 0x72,
-0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x1D, 0x72, 0x78, 0x0C, 0x00, 0x00,
-0x1E, 0x00, 0x1E, 0x72, 0x78, 0x0C, 0x00, 0x00, 0x1E, 0x00, 0x1F, 0x72,
-0x00, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x06, 0x06, 0x04,
-0x04, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x02, 0x02, 0x00,
-0x08, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x08, 0x08, 0x04,
-0x14, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x02, 0x02, 0x00,
-0x18, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x08, 0x08, 0x04,
-0x1C, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x02, 0x02, 0x00,
-0x00, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x1C, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x1C, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x0E, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x14, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x18, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x1C, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
-0x04, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-0x24, 0x08, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x30, 0x00,
-0x2C, 0x08, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x30, 0x00,
-0x70, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00,
-0x64, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-0x78, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x02, 0x00,
-0x74, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
-0x78, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
-0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
-0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x06, 0x00, 0x00, 0x00,
-0x0C, 0x09, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
-0x04, 0x0C, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
-0x04, 0x0D, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
-0x34, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x13, 0x00, 0x00, 0x00,
-0x04, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-0x24, 0x08, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x30, 0x00,
-0x2C, 0x08, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x02, 0x00, 0x30, 0x00,
-0x70, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00,
-0x64, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x78, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00,
-0x74, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x78, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x0C, 0x09, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
-0x04, 0x0C, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00,
-0x04, 0x0D, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x77, 0x77, 0x00, 0x00,
-0x34, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0A, 0x00, 0x00, 0x00,
-0x44, 0x08, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00,
-0x04, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-0x24, 0x08, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x30, 0x00,
-0x2C, 0x08, 0x00, 0x00, 0x0F, 0x00, 0xF0, 0x00, 0x02, 0x00, 0x10, 0x00,
-0x70, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00,
-0x64, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x78, 0x08, 0x00, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00,
-0x74, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x78, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x7C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x80, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x02, 0x00, 0x00, 0x00,
-0x0C, 0x09, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
-0x04, 0x0C, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
-0x04, 0x0D, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-0xF4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x77, 0x77, 0x00, 0x00,
-0x34, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0A, 0x00, 0x00, 0x00,
-0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00,
-0x00, 0x00, 0x04, 0x00, 0x04, 0x08, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00,
-0x08, 0x08, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x0C, 0x08, 0x00, 0x00,
-0x0A, 0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x88, 0x50, 0x00, 0x10,
-0x14, 0x08, 0x00, 0x00, 0x10, 0x3D, 0x0C, 0x02, 0x18, 0x08, 0x00, 0x00,
-0x85, 0x01, 0x20, 0x00, 0x1C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x24, 0x08, 0x00, 0x00,
-0x04, 0x00, 0x39, 0x00, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-0x2C, 0x08, 0x00, 0x00, 0x04, 0x00, 0x39, 0x00, 0x30, 0x08, 0x00, 0x00,
-0x04, 0x00, 0x00, 0x00, 0x34, 0x08, 0x00, 0x00, 0x00, 0x02, 0x69, 0x00,
-0x38, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3C, 0x08, 0x00, 0x00,
-0x00, 0x02, 0x69, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-0x44, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x48, 0x08, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x4C, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x50, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x08, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x58, 0x08, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48,
-0x5C, 0x08, 0x00, 0x00, 0xA9, 0x65, 0xA9, 0x65, 0x60, 0x08, 0x00, 0x00,
-0x30, 0x01, 0x7F, 0x0F, 0x64, 0x08, 0x00, 0x00, 0x30, 0x01, 0x7F, 0x0F,
-0x68, 0x08, 0x00, 0x00, 0x30, 0x01, 0x7F, 0x0F, 0x6C, 0x08, 0x00, 0x00,
-0x30, 0x01, 0x7F, 0x0F, 0x70, 0x08, 0x00, 0x00, 0x00, 0x07, 0x00, 0x03,
-0x74, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x78, 0x08, 0x00, 0x00,
-0x02, 0x00, 0x02, 0x00, 0x7C, 0x08, 0x00, 0x00, 0x01, 0x02, 0x4F, 0x00,
-0x80, 0x08, 0x00, 0x00, 0xC1, 0x0A, 0x30, 0xA8, 0x84, 0x08, 0x00, 0x00,
-0x58, 0x00, 0x00, 0x00, 0x88, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-0x8C, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x90, 0x08, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x94, 0x08, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,
-0x98, 0x08, 0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x9C, 0x08, 0x00, 0x00,
-0x50, 0x60, 0x70, 0x00, 0xB0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xE0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE4, 0x08, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x33, 0x33, 0x33, 0x30,
-0x04, 0x0E, 0x00, 0x00, 0x2F, 0x2E, 0x2D, 0x2A, 0x08, 0x0E, 0x00, 0x00,
-0x32, 0x32, 0x00, 0x00, 0x10, 0x0E, 0x00, 0x00, 0x33, 0x33, 0x33, 0x30,
-0x14, 0x0E, 0x00, 0x00, 0x2F, 0x2E, 0x2D, 0x2A, 0x18, 0x0E, 0x00, 0x00,
-0x33, 0x33, 0x33, 0x30, 0x1C, 0x0E, 0x00, 0x00, 0x2F, 0x2E, 0x2D, 0x2A,
-0x30, 0x0E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01, 0x34, 0x0E, 0x00, 0x00,
-0x00, 0x48, 0x00, 0x01, 0x38, 0x0E, 0x00, 0x00, 0x1F, 0xDC, 0x00, 0x10,
-0x3C, 0x0E, 0x00, 0x00, 0x1F, 0x8C, 0x00, 0x10, 0x40, 0x0E, 0x00, 0x00,
-0xA0, 0x00, 0x14, 0x02, 0x44, 0x0E, 0x00, 0x00, 0xA0, 0x00, 0x16, 0x28,
-0x48, 0x0E, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF8, 0x4C, 0x0E, 0x00, 0x00,
-0x10, 0x29, 0x00, 0x00, 0x50, 0x0E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x01,
-0x54, 0x0E, 0x00, 0x00, 0x00, 0x48, 0x00, 0x01, 0x58, 0x0E, 0x00, 0x00,
-0x1F, 0xDC, 0x00, 0x10, 0x5C, 0x0E, 0x00, 0x00, 0x1F, 0x8C, 0x00, 0x10,
-0x60, 0x0E, 0x00, 0x00, 0xA0, 0x00, 0x14, 0x02, 0x64, 0x0E, 0x00, 0x00,
-0xA0, 0x00, 0x16, 0x28, 0x6C, 0x0E, 0x00, 0x00, 0x10, 0x29, 0x00, 0x00,
-0x70, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0xED, 0x31, 0x74, 0x0E, 0x00, 0x00,
-0xFB, 0x36, 0x15, 0x36, 0x78, 0x0E, 0x00, 0x00, 0xFB, 0x36, 0x15, 0x36,
-0x7C, 0x0E, 0x00, 0x00, 0xFB, 0x36, 0x15, 0x36, 0x80, 0x0E, 0x00, 0x00,
-0xFB, 0x36, 0x15, 0x36, 0x84, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0x0D, 0x00,
-0x88, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0x0D, 0x00, 0x8C, 0x0E, 0x00, 0x00,
-0xFB, 0x92, 0xED, 0x31, 0xD0, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0xED, 0x31,
-0xD4, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0xED, 0x31, 0xD8, 0x0E, 0x00, 0x00,
-0xFB, 0x92, 0x0D, 0x00, 0xDC, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0x0D, 0x00,
-0xE0, 0x0E, 0x00, 0x00, 0xFB, 0x92, 0x0D, 0x00, 0xE4, 0x0E, 0x00, 0x00,
-0x48, 0x54, 0x5E, 0x01, 0xE8, 0x0E, 0x00, 0x00, 0x48, 0x54, 0x55, 0x21,
-0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x09, 0x00, 0x00,
-0x23, 0x00, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x0C, 0x09, 0x00, 0x00, 0x13, 0x13, 0x12, 0x01, 0x00, 0x0A, 0x00, 0x00,
-0xC8, 0x47, 0xD0, 0x00, 0x04, 0x0A, 0x00, 0x00, 0x08, 0x00, 0xFF, 0x80,
-0x08, 0x0A, 0x00, 0x00, 0x00, 0x83, 0xCD, 0x88, 0x0C, 0x0A, 0x00, 0x00,
-0x0F, 0x12, 0x62, 0x2E, 0x10, 0x0A, 0x00, 0x00, 0x78, 0xBB, 0x00, 0x95,
-0x14, 0x0A, 0x00, 0x00, 0x28, 0x40, 0x14, 0x11, 0x18, 0x0A, 0x00, 0x00,
-0x17, 0x11, 0x88, 0x00, 0x1C, 0x0A, 0x00, 0x00, 0x00, 0x0F, 0x14, 0x89,
-0x20, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x1A, 0x24, 0x0A, 0x00, 0x00,
-0x17, 0x13, 0x0E, 0x09, 0x28, 0x0A, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00,
-0x2C, 0x0A, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x10, 0x00, 0x0C, 0x00, 0x00,
-0x40, 0x1D, 0x07, 0x40, 0x04, 0x0C, 0x00, 0x00, 0x33, 0x56, 0xA0, 0x00,
-0x08, 0x0C, 0x00, 0x00, 0xE4, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, 0x00,
-0x6C, 0x6C, 0x6C, 0x6C, 0x10, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x80, 0x08,
-0x14, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x18, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x08, 0x1C, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40,
-0x20, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x24, 0x0C, 0x00, 0x00,
-0x00, 0x01, 0x00, 0x40, 0x28, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-0x2C, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x30, 0x0C, 0x00, 0x00,
-0x44, 0xAC, 0xE9, 0x6D, 0x34, 0x0C, 0x00, 0x00, 0xCF, 0x52, 0x96, 0x46,
-0x38, 0x0C, 0x00, 0x00, 0x94, 0x59, 0x79, 0x49, 0x3C, 0x0C, 0x00, 0x00,
-0x64, 0x97, 0x97, 0x0A, 0x40, 0x0C, 0x00, 0x00, 0x3F, 0x40, 0x7C, 0x1F,
-0x44, 0x0C, 0x00, 0x00, 0xB7, 0x00, 0x01, 0x00, 0x48, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x02, 0xEC, 0x4C, 0x0C, 0x00, 0x00, 0x7F, 0x03, 0x7F, 0x00,
-0x50, 0x0C, 0x00, 0x00, 0x20, 0x34, 0x54, 0x69, 0x54, 0x0C, 0x00, 0x00,
-0x94, 0x00, 0x3C, 0x43, 0x58, 0x0C, 0x00, 0x00, 0x20, 0x34, 0x54, 0x69,
-0x5C, 0x0C, 0x00, 0x00, 0x94, 0x00, 0x3C, 0x43, 0x60, 0x0C, 0x00, 0x00,
-0x20, 0x34, 0x54, 0x69, 0x64, 0x0C, 0x00, 0x00, 0x94, 0x00, 0x3C, 0x43,
-0x68, 0x0C, 0x00, 0x00, 0x20, 0x34, 0x54, 0x69, 0x6C, 0x0C, 0x00, 0x00,
-0x94, 0x00, 0x3C, 0x43, 0x70, 0x0C, 0x00, 0x00, 0x0D, 0x00, 0x7F, 0x2C,
-0x74, 0x0C, 0x00, 0x00, 0x5B, 0x17, 0x86, 0x01, 0x78, 0x0C, 0x00, 0x00,
-0x1F, 0x00, 0x00, 0x00, 0x7C, 0x0C, 0x00, 0x00, 0x12, 0x16, 0xB9, 0x00,
-0x80, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x84, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0xF6, 0x20, 0x88, 0x0C, 0x00, 0x00, 0x80, 0x00, 0x00, 0x20,
-0x8C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x90, 0x0C, 0x00, 0x00,
-0x00, 0x01, 0x00, 0x40, 0x94, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x98, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x9C, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0x92, 0x24, 0x49, 0x00,
-0xA4, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xAC, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xB0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xB8, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xBC, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0xC0, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xC4, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xC8, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xD0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xD4, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x0C, 0x00, 0x00,
-0x27, 0x24, 0xB2, 0x64, 0xDC, 0x0C, 0x00, 0x00, 0x32, 0x69, 0x76, 0x00,
-0xE0, 0x0C, 0x00, 0x00, 0x22, 0x22, 0x22, 0x00, 0xE4, 0x0C, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xE8, 0x0C, 0x00, 0x00, 0x02, 0x43, 0x64, 0x37,
-0xEC, 0x0C, 0x00, 0x00, 0x0C, 0xD4, 0x97, 0x2F, 0x00, 0x0D, 0x00, 0x00,
-0x50, 0x07, 0x00, 0x00, 0x04, 0x0D, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00,
-0x08, 0x0D, 0x00, 0x00, 0x7F, 0x90, 0x00, 0x00, 0x0C, 0x0D, 0x00, 0x00,
-0x01, 0x00, 0x00, 0x00, 0x10, 0x0D, 0x00, 0x00, 0x33, 0x33, 0x63, 0xA0,
-0x14, 0x0D, 0x00, 0x00, 0x63, 0x3C, 0x33, 0x33, 0x18, 0x0D, 0x00, 0x00,
-0x6B, 0x5B, 0x8F, 0x6A, 0x1C, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x0D, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x28, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x2C, 0x0D, 0x00, 0x00, 0x75, 0x99, 0x97, 0xCC, 0x30, 0x0D, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x34, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x38, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0D, 0x00, 0x00,
-0x93, 0x72, 0x02, 0x00, 0x40, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x44, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0D, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x50, 0x0D, 0x00, 0x00, 0x0A, 0x14, 0x37, 0x64,
-0x54, 0x0D, 0x00, 0x00, 0x02, 0xBD, 0x4D, 0x02, 0x58, 0x0D, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x5C, 0x0D, 0x00, 0x00, 0x64, 0x20, 0x03, 0x30,
-0x60, 0x0D, 0x00, 0x00, 0x68, 0xDE, 0x53, 0x46, 0x64, 0x0D, 0x00, 0x00,
-0x3C, 0x8A, 0x51, 0x00, 0x68, 0x0D, 0x00, 0x00, 0x01, 0x21, 0x00, 0x00,
-0x14, 0x0F, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x4C, 0x0F, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
-0x40, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
-0x10, 0x00, 0x00, 0x00, 0x84, 0x02, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00,
-0xB4, 0x02, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00, 0xC0, 0x08, 0x01, 0x80,
-0x10, 0x00, 0x00, 0x00, 0xC8, 0x08, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00,
-0xD0, 0x08, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00, 0xD8, 0x08, 0x01, 0x80,
-0x10, 0x00, 0x00, 0x00, 0xB0, 0x08, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00,
-0xB8, 0x08, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00, 0x10, 0x09, 0x01, 0x80,
-0x10, 0x00, 0x00, 0x00, 0x18, 0x09, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00,
-0x58, 0x04, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00, 0x50, 0x04, 0x01, 0x80,
-0x10, 0x00, 0x00, 0x00, 0x20, 0x09, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00,
-0x28, 0x09, 0x01, 0x80, 0x74, 0x03, 0x00, 0x00, 0xF0, 0x28, 0x00, 0x80,
-0x04, 0x00, 0x00, 0x00, 0x88, 0x06, 0x01, 0x80, 0x74, 0x03, 0x00, 0x00,
-0xF0, 0x28, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0xAC, 0x2B, 0x00, 0x80,
-0x30, 0x00, 0x00, 0x00, 0x58, 0x2C, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00,
-0x1C, 0x2F, 0x00, 0x80, 0x13, 0x00, 0x00, 0x00, 0x7C, 0x07, 0x01, 0x80,
-0x17, 0x00, 0x00, 0x00, 0xD0, 0x07, 0x01, 0x80, 0x06, 0x00, 0x00, 0x00,
-0x58, 0x08, 0x01, 0x80, 0x06, 0x00, 0x00, 0x00, 0x60, 0x08, 0x01, 0x80,
-0x08, 0x00, 0x00, 0x00, 0x68, 0x08, 0x01, 0x80, 0x0C, 0x00, 0x00, 0x00,
-0x70, 0x08, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00, 0x78, 0x08, 0x01, 0x80,
-0x0E, 0x00, 0x00, 0x00, 0x80, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00,
-0x88, 0x08, 0x01, 0x80, 0x38, 0x00, 0x00, 0x00, 0x90, 0x08, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0x98, 0x08, 0x01, 0x80, 0x02, 0x00, 0x00, 0x00,
-0xA0, 0x08, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00, 0xA8, 0x08, 0x01, 0x80,
-0x01, 0x00, 0x00, 0x00, 0xE8, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00,
-0xF0, 0x08, 0x01, 0x80, 0x0C, 0x00, 0x00, 0x00, 0x60, 0x04, 0x01, 0x80,
-0x0E, 0x00, 0x00, 0x00, 0x68, 0x04, 0x01, 0x80, 0x0C, 0x00, 0x00, 0x00,
-0x80, 0x06, 0x01, 0x80, 0x34, 0x00, 0x00, 0x00, 0xF8, 0x08, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00,
-0x30, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00, 0x38, 0x09, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0x40, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00,
-0x08, 0x09, 0x01, 0x80, 0x08, 0x00, 0x00, 0x00, 0xB8, 0x03, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0x48, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00,
-0xC0, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00, 0xCC, 0x09, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0xD4, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00,
-0xDC, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00, 0xE4, 0x09, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0xEC, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00,
-0xF4, 0x09, 0x01, 0x80, 0x04, 0x00, 0x00, 0x00, 0xFC, 0x09, 0x01, 0x80,
-0x04, 0x00, 0x00, 0x00, 0x04, 0x0A, 0x01, 0x80, 0x74, 0x03, 0x00, 0x00,
-0x0C, 0x0A, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x30, 0x0B, 0x01, 0x80,
-0x10, 0x00, 0x00, 0x00, 0x0C, 0x33, 0x00, 0x80, 0x06, 0x00, 0x00, 0x00,
-0x6C, 0x0B, 0x01, 0x80, 0x13, 0x00, 0x00, 0x00, 0xF8, 0x9E, 0x02, 0x00,
-0x13, 0x00, 0x00, 0x00, 0xC8, 0x5E, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00,
-0xF8, 0x0E, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0xC8, 0xCE, 0x01, 0x00,
-0x13, 0x00, 0x00, 0x00, 0xD4, 0x8E, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00,
-0xA4, 0x4E, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, 0xD0, 0x0E, 0x01, 0x00,
-0x13, 0x00, 0x00, 0x00, 0xA0, 0xCE, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
-0xD0, 0x86, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xA0, 0x46, 0x00, 0x00,
-0x13, 0x00, 0x00, 0x00, 0x70, 0x06, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
-0xA4, 0x9E, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00, 0x74, 0x5E, 0x02, 0x00,
-0x13, 0x00, 0x00, 0x00, 0xA4, 0x0E, 0x02, 0x00, 0x13, 0x00, 0x00, 0x00,
-0xD0, 0xCE, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, 0x40, 0x9F, 0x01, 0x00,
-0x13, 0x00, 0x00, 0x00, 0x70, 0x4E, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00,
-0xA0, 0x06, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, 0x70, 0xC6, 0x00, 0x00,
-0x13, 0x00, 0x00, 0x00, 0xA0, 0x82, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
-0x70, 0x42, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00,
-0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44,
-0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00,
-0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44,
-0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00,
-0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44,
-0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00,
-0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44,
-0x44, 0x22, 0x22, 0x00, 0xAA, 0x88, 0x88, 0x44, 0x44, 0x22, 0x22, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x59, 0x01, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00,
-0x41, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00,
-0x05, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00,
-0x03, 0xC8, 0x0F, 0x00, 0x13, 0x00, 0x00, 0x00, 0xB0, 0x7C, 0x01, 0x00,
-0x13, 0x00, 0x00, 0x00, 0xC0, 0x1C, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00,
-0x60, 0xDC, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x60, 0x8C, 0x00, 0x00,
-0x13, 0x00, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
-0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x01, 0x03, 0x00,
-0x01, 0x00, 0x00, 0x00, 0x50, 0x02, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x08, 0x00,
-0x11, 0x00, 0x00, 0x00, 0xFC, 0x31, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00,
-0x0F, 0x00, 0x0C, 0x00, 0x11, 0x00, 0x00, 0x00, 0xF8, 0xF9, 0x03, 0x00,
-0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x02, 0x00, 0x11, 0x00, 0x00, 0x00,
-0x01, 0x01, 0x02, 0x00, 0x14, 0x00, 0x00, 0x00, 0x3E, 0x09, 0x01, 0x00,
-0x14, 0x00, 0x00, 0x00, 0x3E, 0x09, 0x09, 0x00, 0x15, 0x00, 0x00, 0x00,
-0xF4, 0x98, 0x01, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x65, 0x0F, 0x00,
-0x1A, 0x00, 0x00, 0x00, 0x56, 0x30, 0x01, 0x00, 0x1B, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x06, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
-0x1E, 0x00, 0x00, 0x00, 0x59, 0x10, 0x03, 0x00, 0x21, 0x00, 0x00, 0x00,
-0x00, 0x40, 0x05, 0x00, 0x22, 0x00, 0x00, 0x00, 0x3C, 0x08, 0x00, 0x00,
-0x23, 0x00, 0x00, 0x00, 0x58, 0x15, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
-0x60, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x83, 0x25, 0x02, 0x00,
-0x26, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
-0xF1, 0xAC, 0x0E, 0x00, 0x28, 0x00, 0x00, 0x00, 0x54, 0xBD, 0x09, 0x00,
-0x29, 0x00, 0x00, 0x00, 0x82, 0x45, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x34, 0x13, 0x02, 0x00,
-0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x0A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x33, 0x33, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x08, 0x08, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x33, 0xB3, 0x05, 0x00,
-0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
-0x03, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x33, 0x33, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x33, 0xB3, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x09, 0x07, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x33, 0x33, 0x05, 0x00,
-0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
-0x06, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x33, 0xB3, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x09, 0x07, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x33, 0x33, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x09, 0x07, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x33, 0xB3, 0x06, 0x00,
-0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
-0x09, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x33, 0x33, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x33, 0xB3, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x0A, 0x06, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x33, 0x33, 0x06, 0x00,
-0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
-0x0C, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x06, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x33, 0xB3, 0x06, 0x00, 0x2C, 0x00, 0x00, 0x00,
-0x0D, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
-0x2B, 0x00, 0x00, 0x00, 0x0B, 0x05, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x33, 0x33, 0x05, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
-0x2A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00,
-0x0B, 0x05, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x23, 0x66, 0x06, 0x00,
-0x2C, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00,
-0x00, 0x40, 0x0E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
-0x31, 0x00, 0x00, 0x00, 0x31, 0x96, 0x0B, 0x00, 0x32, 0x00, 0x00, 0x00,
-0x0D, 0x13, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x87, 0x01, 0x00, 0x00,
-0x13, 0x00, 0x00, 0x00, 0x6C, 0x9E, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00,
-0x94, 0x5E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x01, 0x01, 0x00,
-0x18, 0x00, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x5B, 0x10, 0x03, 0x00,
-0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x59, 0x01, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x04, 0x00,
-0x11, 0x00, 0x00, 0x00, 0xF9, 0x03, 0x02, 0x00, 0x6C, 0x09, 0x00, 0x00,
-0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
-0x0D, 0x00, 0x00, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
-0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
-0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x17, 0x05, 0x03,
-0x22, 0x43, 0x5E, 0x00, 0x4F, 0xA4, 0x00, 0x00, 0x4F, 0xA4, 0x00, 0x00,
-0x22, 0x43, 0x5E, 0x00, 0x4F, 0xA4, 0x00, 0x00, 0x22, 0x43, 0x5E, 0x00,
-0x4F, 0xA4, 0x3E, 0x00, 0x30, 0xA6, 0x00, 0x00, 0x4F, 0xA4, 0x3E, 0x00,
-0x2B, 0xA4, 0x5E, 0x00, 0x2B, 0xA4, 0x00, 0x00, 0x2B, 0xA4, 0x5E, 0x00,
-0x22, 0xA4, 0x5E, 0x00, 0x4F, 0xA4, 0x00, 0x00, 0x4F, 0xA4, 0x00, 0x00,
-0x4F, 0xA4, 0x5E, 0x00, 0x4F, 0xA4, 0x5E, 0x00, 0x4F, 0xA4, 0x5E, 0x00,
-0x1C, 0x42, 0x2F, 0x00, 0x4F, 0x64, 0x5E, 0x00, 0x4F, 0xA4, 0x5E, 0x00,
-0x4F, 0xA4, 0x5E, 0x00, 0x4F, 0xA4, 0x00, 0x00, 0x4F, 0xA4, 0x5E, 0x00,
-0x00, 0xE0, 0x4C, 0x02, 0x01, 0x20, 0x00, 0x00, 0x00, 0xE0, 0x4C, 0x00,
-0x00, 0x0C, 0x43, 0x00, 0x00, 0x50, 0x43, 0x00, 0x00, 0x40, 0x96, 0x00,
-0x00, 0x05, 0xB5, 0x00, 0x00, 0x0A, 0xF7, 0x00, 0x00, 0x10, 0x18, 0x00,
-0x00, 0x21, 0x91, 0x00, 0x00, 0x1C, 0xF0, 0x00, 0x00, 0x13, 0x74, 0x00,
-0x00, 0x03, 0x7F, 0x00, 0x00, 0x50, 0xF2, 0x02, 0x01, 0x01, 0x00, 0x00,
-0x00, 0x50, 0xF2, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
-0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xE7, 0x01, 0x80,
-0xE0, 0x25, 0x01, 0x80, 0x10, 0x00, 0x00, 0x00, 0xBC, 0xE7, 0x01, 0x80,
-0xE8, 0x25, 0x01, 0x80, 0x20, 0x00, 0x00, 0x00, 0xC8, 0xE7, 0x01, 0x80,
-0xE0, 0x25, 0x01, 0x80, 0x30, 0x00, 0x00, 0x00, 0xD8, 0xE7, 0x01, 0x80,
-0xE8, 0x25, 0x01, 0x80, 0x40, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0x01, 0x80,
-0x44, 0x43, 0x00, 0x80, 0x50, 0x00, 0x00, 0x00, 0xF4, 0xE7, 0x01, 0x80,
-0xD4, 0x49, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x01, 0x80,
-0x34, 0x53, 0x00, 0x80, 0x90, 0x00, 0x00, 0x00, 0x0C, 0xE8, 0x01, 0x80,
-0x64, 0x30, 0x01, 0x80, 0xA0, 0x00, 0x00, 0x00, 0x14, 0xE8, 0x01, 0x80,
-0x6C, 0x30, 0x01, 0x80, 0xB0, 0x00, 0x00, 0x00, 0x20, 0xE8, 0x01, 0x80,
-0x9C, 0x39, 0x01, 0x80, 0xC0, 0x00, 0x00, 0x00, 0x28, 0xE8, 0x01, 0x80,
-0x8C, 0x30, 0x01, 0x80, 0xD0, 0x00, 0x00, 0x00, 0x34, 0xE8, 0x01, 0x80,
-0xFC, 0x4E, 0x00, 0x80, 0xC8, 0x00, 0x00, 0x00, 0x40, 0xE8, 0x01, 0x80,
-0x54, 0x4A, 0x00, 0x80, 0x0D, 0x00, 0x00, 0x00, 0x4C, 0xE8, 0x01, 0x80,
-0xAC, 0x30, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
-0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0xFF, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
-0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0x00, 0x00, 0x00,
-0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0xFF, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x08, 0xFF, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
-0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x01, 0x01, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xD0, 0xDF, 0x01, 0x80, 0xD0, 0xDF, 0x01, 0x80,
-0x31, 0x10, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x31, 0x20, 0x10, 0x00,
-0x00, 0x30, 0x00, 0x00, 0x31, 0x28, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00,
-0x31, 0x2C, 0x10, 0x10, 0x00, 0x30, 0x00, 0x00, 0x31, 0x2F, 0x10, 0x10,
-0x00, 0x30, 0x00, 0x00, 0x31, 0x30, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00,
-0x31, 0x30, 0x20, 0x10, 0x00, 0x30, 0x00, 0x00, 0x22, 0x20, 0x18, 0x08,
-0x00, 0x20, 0x00, 0x00, 0x22, 0x21, 0x14, 0x08, 0x00, 0x20, 0x00, 0x00,
-0x22, 0x21, 0x1C, 0x08, 0x00, 0x20, 0x00, 0x00, 0x22, 0x21, 0x20, 0x08,
-0x00, 0x20, 0x00, 0x00, 0x22, 0x21, 0x20, 0x10, 0x00, 0x20, 0x00, 0x00,
-0x22, 0x21, 0x20, 0x18, 0x00, 0x20, 0x00, 0x00, 0x1A, 0x19, 0x18, 0x10,
-0x00, 0x18, 0x00, 0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x10, 0x00, 0x00,
-0x0A, 0x09, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x02,
-0x00, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x08, 0x00, 0x00,
-0x0A, 0x09, 0x08, 0x06, 0x00, 0x08, 0x00, 0x00, 0x08, 0x07, 0x06, 0x04,
-0x00, 0x06, 0x00, 0x00, 0x06, 0x05, 0x04, 0x02, 0x00, 0x04, 0x00, 0x00,
-0x06, 0x05, 0x04, 0x03, 0x00, 0x04, 0x00, 0x00, 0x05, 0x04, 0x03, 0x02,
-0x00, 0x03, 0x00, 0x00, 0x09, 0x08, 0x07, 0x06, 0x07, 0x06, 0x06, 0x05,
-0x05, 0x04, 0x04, 0x03, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x03,
-0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x00, 0x09, 0x08, 0x07,
-0x06, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04,
-0x03, 0x03, 0x02, 0x02, 0x02, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01,
-0x01, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x10, 0x10, 0x20, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20, 0x20, 0x20,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20, 0x20, 0x30, 0x08, 0x08, 0x08,
-0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x30, 0x30, 0x10, 0x20, 0x20,
-0x20, 0x20, 0x20, 0x30, 0x30, 0x08, 0x10, 0x20, 0x30, 0x30, 0x30, 0x30,
-0x30, 0x30, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x10, 0x10, 0x20, 0x08, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20, 0x20,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x20, 0x20, 0x20, 0x20, 0x08, 0x08, 0x08,
-0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x30, 0x30, 0x10, 0x20, 0x20,
-0x20, 0x20, 0x20, 0x30, 0x30, 0x08, 0x10, 0x20, 0x30, 0x30, 0x30, 0x30,
-0x30, 0x30, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08,
-0x04, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00,
-0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09,
-0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x00,
-0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x22,
-0x21, 0x20, 0x18, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08,
-0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00,
-0x22, 0x21, 0x20, 0x18, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00, 0x22, 0x21,
-0x1C, 0x08, 0x00, 0x22, 0x20, 0x18, 0x08, 0x00, 0x0A, 0x09, 0x08, 0x02,
-0x00, 0x0A, 0x09, 0x08, 0x02, 0x00, 0x0A, 0x09, 0x08, 0x02, 0x00, 0x0A,
-0x09, 0x08, 0x02, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x22, 0x21, 0x20,
-0x10, 0x00, 0x22, 0x21, 0x20, 0x08, 0x00, 0x22, 0x21, 0x1C, 0x08, 0x00,
-0x31, 0x30, 0x18, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09,
-0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x04,
-0x00, 0x1A, 0x19, 0x18, 0x10, 0x00, 0x1A, 0x19, 0x18, 0x10, 0x00, 0x1A,
-0x19, 0x18, 0x10, 0x00, 0x1A, 0x19, 0x18, 0x10, 0x00, 0x1A, 0x19, 0x18,
-0x10, 0x00, 0x22, 0x21, 0x20, 0x08, 0x00, 0x31, 0x2C, 0x10, 0x10, 0x00,
-0x31, 0x28, 0x10, 0x00, 0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x22, 0x21,
-0x20, 0x18, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00, 0x22, 0x21, 0x20, 0x08,
-0x00, 0x22, 0x21, 0x14, 0x08, 0x00, 0x22, 0x20, 0x18, 0x08, 0x00, 0x31,
-0x30, 0x20, 0x10, 0x00, 0x31, 0x2C, 0x10, 0x10, 0x00, 0x0A, 0x09, 0x08,
-0x00, 0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00,
-0x22, 0x21, 0x20, 0x18, 0x00, 0x31, 0x30, 0x20, 0x10, 0x00, 0x31, 0x2F,
-0x10, 0x10, 0x00, 0x31, 0x2F, 0x10, 0x10, 0x00, 0x31, 0x10, 0x10, 0x00,
-0x00, 0x31, 0x2C, 0x10, 0x10, 0x00, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x04,
-0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A,
-0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08,
-0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00,
-0x0A, 0x09, 0x08, 0x00, 0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x12, 0x11,
-0x10, 0x08, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00, 0x0A, 0x09, 0x08, 0x04,
-0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x02, 0x00, 0x0A,
-0x09, 0x08, 0x00, 0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x22, 0x21, 0x20,
-0x18, 0x00, 0x22, 0x21, 0x1C, 0x08, 0x00, 0x22, 0x21, 0x14, 0x08, 0x00,
-0x0A, 0x09, 0x08, 0x02, 0x00, 0x0A, 0x09, 0x08, 0x02, 0x00, 0x0A, 0x09,
-0x08, 0x02, 0x00, 0x0A, 0x09, 0x08, 0x02, 0x00, 0x0A, 0x09, 0x08, 0x00,
-0x00, 0x22, 0x21, 0x20, 0x10, 0x00, 0x22, 0x21, 0x20, 0x08, 0x00, 0x22,
-0x21, 0x14, 0x08, 0x00, 0x22, 0x21, 0x14, 0x08, 0x00, 0x0A, 0x09, 0x08,
-0x04, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00, 0x0A, 0x09, 0x08, 0x04, 0x00,
-0x0A, 0x09, 0x08, 0x04, 0x00, 0x1A, 0x19, 0x18, 0x10, 0x00, 0x1A, 0x19,
-0x18, 0x10, 0x00, 0x1A, 0x19, 0x18, 0x10, 0x00, 0x1A, 0x19, 0x18, 0x10,
-0x00, 0x1A, 0x19, 0x18, 0x10, 0x00, 0x22, 0x21, 0x20, 0x08, 0x00, 0x31,
-0x2C, 0x10, 0x10, 0x00, 0x31, 0x28, 0x10, 0x00, 0x00, 0x12, 0x11, 0x10,
-0x08, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00,
-0x22, 0x21, 0x20, 0x08, 0x00, 0x22, 0x21, 0x14, 0x08, 0x00, 0x22, 0x20,
-0x18, 0x08, 0x00, 0x31, 0x30, 0x20, 0x10, 0x00, 0x31, 0x2C, 0x10, 0x10,
-0x00, 0x0A, 0x09, 0x08, 0x00, 0x00, 0x12, 0x11, 0x10, 0x08, 0x00, 0x22,
-0x21, 0x20, 0x18, 0x00, 0x22, 0x21, 0x20, 0x18, 0x00, 0x31, 0x30, 0x20,
-0x10, 0x00, 0x31, 0x2F, 0x10, 0x10, 0x00, 0x31, 0x2F, 0x10, 0x10, 0x00,
-0x31, 0x10, 0x10, 0x00, 0x00, 0x31, 0x2C, 0x10, 0x10, 0x00, 0x00, 0x00,
-0x01, 0x02, 0x04, 0x08, 0x02, 0x04, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30,
-0x02, 0x04, 0x08, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x06, 0x0C, 0x10, 0x18,
-0x24, 0x30, 0x3C, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x27, 0x2C, 0x19, 0x1B, 0x1E, 0x20,
-0x23, 0x29, 0x2A, 0x2B, 0x00, 0x00, 0x00, 0x00, 0x25, 0x29, 0x2B, 0x2E,
-0x2E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-0x24, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
-0x60, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
-0xD8, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
-0xA0, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00,
-0x90, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00,
-0x2C, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00,
-0xD0, 0x02, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00, 0x80, 0x0C, 0x00, 0x00,
-0x80, 0x0C, 0x00, 0x00, 0xA0, 0x0F, 0x00, 0x00, 0xA0, 0x0F, 0x00, 0x00,
-0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-0x08, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
-0x18, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-0x48, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00,
-0x28, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
-0x64, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0xC8, 0x00, 0x00, 0x00,
-0xF0, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
-0xA0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x00,
-0x40, 0x06, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00,
-0xD0, 0x07, 0x00, 0x00, 0xD0, 0x07, 0x00, 0x00, 0x54, 0x86, 0x01, 0x80,
-0x4C, 0xC4, 0x00, 0x80, 0x4C, 0xC4, 0x00, 0x80, 0x4C, 0xC4, 0x00, 0x80,
-0x4C, 0xC4, 0x00, 0x80, 0x9C, 0xC2, 0x00, 0x80, 0x5C, 0x86, 0x01, 0x80,
-0x54, 0x86, 0x01, 0x80, 0x54, 0x86, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x44, 0x8B, 0x01, 0x80, 0x44, 0x8B, 0x01, 0x80,
-0x44, 0x8B, 0x01, 0x80, 0x44, 0x8B, 0x01, 0x80, 0x34, 0x86, 0x01, 0x80,
-0x30, 0x8A, 0x01, 0x80, 0x3C, 0x86, 0x01, 0x80, 0x44, 0x86, 0x01, 0x80,
-0x4C, 0x86, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x08, 0x04, 0x04, 0x08, 0x02, 0x02, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00,
-0x52, 0x54, 0x4C, 0x38, 0x37, 0x31, 0x32, 0x20, 0x46, 0x57, 0x20, 0x76,
-0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x30, 0x2E, 0x30, 0x2E, 0x31,
-0x23, 0x20, 0xE4, 0xB8, 0x80, 0x20, 0x35, 0xE6, 0x9C, 0x88, 0x20, 0x33,
-0x31, 0x20, 0x31, 0x35, 0x3A, 0x32, 0x35, 0x3A, 0x33, 0x39, 0x20, 0x43,
-0x53, 0x54, 0x20, 0x32, 0x30, 0x31, 0x30, 0x20, 0x20, 0x53, 0x56, 0x4E,
-0x3A, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x43, 0x68, 0x69, 0x70,
-0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x3A, 0x25, 0x78, 0x00,
-0x48, 0x43, 0x49, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3A, 0x20, 0x25, 0x78,
-0x28, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x66, 0x5F, 0x63,
-0x6F, 0x66, 0x69, 0x67, 0x3A, 0x20, 0x25, 0x78, 0x28, 0x25, 0x78, 0x2C,
-0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00, 0x00,
-0x6D, 0x70, 0x5F, 0x6D, 0x6F, 0x64, 0x65, 0x3A, 0x20, 0x25, 0x78, 0x28,
-0x25, 0x78, 0x29, 0x2C, 0x20, 0x49, 0x51, 0x4B, 0x3A, 0x20, 0x25, 0x78,
-0x0A, 0x00, 0x00, 0x00, 0x76, 0x63, 0x73, 0x20, 0x74, 0x79, 0x70, 0x65,
-0x3A, 0x20, 0x25, 0x78, 0x28, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00, 0x00,
-0x33, 0x32, 0x6B, 0x20, 0x63, 0x61, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x3A,
-0x20, 0x25, 0x64, 0x2C, 0x20, 0x33, 0x32, 0x4B, 0x20, 0x54, 0x53, 0x46,
-0x3A, 0x20, 0x25, 0x78, 0x00, 0x00, 0x00, 0x00, 0x74, 0x61, 0x72, 0x67,
-0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x72, 0x6D, 0x61, 0x6C, 0x3A, 0x20,
-0x25, 0x78, 0x2C, 0x20, 0x20, 0x62, 0x74, 0x5F, 0x63, 0x6F, 0x65, 0x78,
-0x69, 0x73, 0x74, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00,
-0x54, 0xAA, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0x1C, 0xAA, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0xE4, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0xAC, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0x74, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x3C, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80, 0x24, 0xA9, 0x01, 0x80,
-0x24, 0xA9, 0x01, 0x80, 0xFC, 0xA8, 0x01, 0x80, 0x64, 0x05, 0x00, 0x80,
-0x58, 0x05, 0x00, 0x80, 0x4C, 0x05, 0x00, 0x80, 0x40, 0x05, 0x00, 0x80,
-0x34, 0x05, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 0x1C, 0x05, 0x00, 0x80,
-0x10, 0x05, 0x00, 0x80, 0x04, 0x05, 0x00, 0x80, 0xF8, 0x04, 0x00, 0x80,
-0xB0, 0x04, 0x00, 0x80, 0x60, 0x1B, 0x02, 0x80, 0xB0, 0x03, 0x25, 0xB0,
-0x60, 0x1B, 0x02, 0x80, 0x60, 0x1B, 0x02, 0x80, 0x60, 0x1B, 0x02, 0x80,
-0x60, 0x1B, 0x02, 0x80, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x65, 0x64,
-0x20, 0x65, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x49, 0x44, 0x3A,
-0x20, 0x25, 0x78, 0x2C, 0x20, 0x63, 0x6D, 0x64, 0x20, 0x73, 0x65, 0x71,
-0x3D, 0x25, 0x78, 0x2C, 0x20, 0x68, 0x32, 0x64, 0x73, 0x65, 0x71, 0x3D,
-0x25, 0x78, 0x0A, 0x00, 0x6A, 0x6F, 0x69, 0x6E, 0x62, 0x73, 0x73, 0x5F,
-0x68, 0x64, 0x6C, 0x00, 0x67, 0x65, 0x74, 0x20, 0x6A, 0x6F, 0x69, 0x6E,
-0x20, 0x63, 0x6D, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x69,
-0x72, 0x70, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00, 0x73, 0x65, 0x74, 0x20,
-0x6F, 0x70, 0x6D, 0x6F, 0x64, 0x65, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00,
-0x67, 0x65, 0x74, 0x20, 0x73, 0x75, 0x72, 0x76, 0x65, 0x79, 0x20, 0x63,
-0x6D, 0x64, 0x0A, 0x00, 0x53, 0x53, 0x49, 0x44, 0x3A, 0x20, 0x25, 0x73,
-0x0A, 0x00, 0x00, 0x00, 0x73, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x3A,
-0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x63, 0x76, 0x20,
-0x73, 0x65, 0x74, 0x5F, 0x73, 0x74, 0x61, 0x6B, 0x65, 0x79, 0x0A, 0x00,
-0x54, 0x78, 0x5F, 0x42, 0x65, 0x61, 0x63, 0x6F, 0x6E, 0x5F, 0x68, 0x64,
-0x6C, 0x00, 0x00, 0x00, 0x74, 0x78, 0x20, 0x62, 0x65, 0x61, 0x63, 0x6F,
-0x6E, 0x20, 0x63, 0x6D, 0x64, 0x28, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00,
-0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x4D, 0x61, 0x63, 0x41, 0x64,
-0x64, 0x72, 0x0A, 0x00, 0x00, 0x0E, 0x04, 0x0E, 0x10, 0x0E, 0x14, 0x0E,
-0x18, 0x0E, 0x1C, 0x0E, 0x4F, 0x6E, 0x41, 0x73, 0x73, 0x6F, 0x63, 0x52,
-0x65, 0x71, 0x00, 0x00, 0x4F, 0x6E, 0x41, 0x73, 0x73, 0x6F, 0x63, 0x52,
-0x73, 0x70, 0x00, 0x00, 0x4F, 0x6E, 0x52, 0x65, 0x41, 0x73, 0x73, 0x6F,
-0x63, 0x52, 0x65, 0x71, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6E, 0x52, 0x65,
-0x41, 0x73, 0x73, 0x6F, 0x63, 0x52, 0x73, 0x70, 0x00, 0x00, 0x00, 0x00,
-0x4F, 0x6E, 0x50, 0x72, 0x6F, 0x62, 0x65, 0x52, 0x65, 0x71, 0x00, 0x00,
-0x4F, 0x6E, 0x50, 0x72, 0x6F, 0x62, 0x65, 0x52, 0x73, 0x70, 0x00, 0x00,
-0x4F, 0x6E, 0x42, 0x65, 0x61, 0x63, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00,
-0x4F, 0x6E, 0x41, 0x54, 0x49, 0x4D, 0x00, 0x00, 0x4F, 0x6E, 0x44, 0x69,
-0x73, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x00, 0x00, 0x4F, 0x6E, 0x41, 0x75,
-0x74, 0x68, 0x00, 0x00, 0x4F, 0x6E, 0x44, 0x65, 0x41, 0x75, 0x74, 0x68,
-0x00, 0x00, 0x00, 0x00, 0x4F, 0x6E, 0x41, 0x63, 0x74, 0x69, 0x6F, 0x6E,
-0x00, 0x00, 0x00, 0x00, 0x4F, 0x6E, 0x51, 0x6F, 0x73, 0x4E, 0x75, 0x6C,
-0x6C, 0x00, 0x00, 0x00, 0x4F, 0x6E, 0x45, 0x78, 0x63, 0x65, 0x70, 0x74,
-0x69, 0x6F, 0x6E, 0x00, 0x41, 0x54, 0x49, 0x4D, 0x3A, 0x20, 0x25, 0x78,
-0x0A, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x07, 0x07, 0x0D, 0x0D, 0x0D,
-0x02, 0x07, 0x07, 0x0D, 0x0D, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00,
-0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x08, 0x10, 0x72, 0x65, 0x70, 0x6F,
-0x72, 0x74, 0x5F, 0x73, 0x75, 0x72, 0x76, 0x65, 0x79, 0x5F, 0x64, 0x6F,
-0x6E, 0x65, 0x00, 0x00, 0x73, 0x75, 0x72, 0x76, 0x65, 0x79, 0x20, 0x64,
-0x6F, 0x6E, 0x65, 0x28, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x29, 0x0A,
-0x00, 0x00, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x69, 0x72, 0x70, 0x20, 0x25,
-0x73, 0x0A, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x6A,
-0x6F, 0x69, 0x6E, 0x5F, 0x72, 0x65, 0x73, 0x00, 0x4E, 0x6F, 0x20, 0x69,
-0x72, 0x70, 0x28, 0x25, 0x78, 0x29, 0x20, 0x25, 0x73, 0x0A, 0x00, 0x00,
-0x6A, 0x6F, 0x69, 0x6E, 0x20, 0x72, 0x65, 0x73, 0x28, 0x25, 0x78, 0x2C,
-0x20, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F,
-0x72, 0x74, 0x5F, 0x64, 0x65, 0x6C, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x65,
-0x76, 0x65, 0x6E, 0x74, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x6C, 0x20,
-0x73, 0x74, 0x61, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x72, 0x65, 0x70, 0x6F,
-0x72, 0x74, 0x5F, 0x61, 0x64, 0x64, 0x5F, 0x73, 0x74, 0x61, 0x5F, 0x65,
-0x76, 0x65, 0x6E, 0x74, 0x00, 0x00, 0x00, 0x00, 0x61, 0x64, 0x64, 0x20,
-0x73, 0x74, 0x61, 0x3A, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00,
-0x72, 0x63, 0x76, 0x20, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x65,
-0x63, 0x74, 0x0A, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x70, 0x72,
-0x6F, 0x62, 0x65, 0x72, 0x65, 0x71, 0x00, 0x00, 0x4E, 0x6F, 0x20, 0x69,
-0x72, 0x70, 0x20, 0x40, 0x25, 0x73, 0x0A, 0x00, 0x57, 0x4D, 0x4D, 0x28,
-0x25, 0x78, 0x29, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A,
-0x00, 0x00, 0x00, 0x00, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x20, 0x72, 0x65,
-0x6A, 0x65, 0x63, 0x74, 0x2C, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
-0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x63, 0x20,
-0x69, 0x64, 0x20, 0x23, 0x35, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25,
-0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75,
-0x65, 0x5F, 0x70, 0x72, 0x6F, 0x62, 0x65, 0x72, 0x73, 0x70, 0x00, 0x00,
-0x72, 0x65, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x42, 0x53, 0x53, 0x49, 0x44,
-0x5F, 0x69, 0x6E, 0x66, 0x6F, 0x00, 0x00, 0x00, 0x70, 0x61, 0x63, 0x6B,
-0x65, 0x74, 0x20, 0x74, 0x6F, 0x6F, 0x20, 0x6C, 0x61, 0x72, 0x67, 0x65,
-0x28, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x50, 0xF2, 0x01,
-0x69, 0x6E, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x63, 0x61, 0x70, 0x3A,
-0x25, 0x78, 0x0A, 0x00, 0x49, 0x42, 0x53, 0x53, 0x20, 0x6D, 0x6F, 0x64,
-0x65, 0x2C, 0x20, 0x63, 0x75, 0x72, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x6E,
-0x65, 0x6C, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x63, 0x6E, 0x20,
-0x69, 0x6E, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6C, 0x3A, 0x20, 0x25, 0x78,
-0x0A, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x63, 0x20, 0x69, 0x64, 0x20, 0x23,
-0x34, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00,
-0x63, 0x75, 0x72, 0x20, 0x63, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x3A,
-0x20, 0x25, 0x78, 0x2C, 0x20, 0x62, 0x63, 0x6E, 0x20, 0x69, 0x6E, 0x74,
-0x65, 0x72, 0x76, 0x61, 0x6C, 0x3A, 0x20, 0x25, 0x78, 0x0A, 0x00, 0x00,
-0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x72,
-0x65, 0x71, 0x00, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x69, 0x73, 0x73, 0x75,
-0x65, 0x20, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x72, 0x65, 0x71, 0x28, 0x25,
-0x78, 0x29, 0x0A, 0x00, 0x5B, 0x57, 0x41, 0x50, 0x49, 0x5D, 0x20, 0x67,
-0x65, 0x74, 0x20, 0x77, 0x61, 0x70, 0x69, 0x20, 0x49, 0x45, 0x0A, 0x00,
-0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x61, 0x63, 0x74, 0x69, 0x6F, 0x6E,
-0x00, 0x00, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x20, 0x61, 0x63,
-0x74, 0x69, 0x6F, 0x6E, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78,
-0x2C, 0x20, 0x25, 0x78, 0x20, 0x0A, 0x00, 0x00, 0x44, 0x45, 0x4C, 0x42,
-0x41, 0x3A, 0x20, 0x25, 0x78, 0x28, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00,
-0x41, 0x44, 0x44, 0x42, 0x41, 0x20, 0x52, 0x53, 0x50, 0x3A, 0x20, 0x25,
-0x78, 0x0A, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x61, 0x75,
-0x74, 0x68, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x20, 0x61, 0x75,
-0x74, 0x68, 0x0A, 0x00, 0x63, 0x6C, 0x6E, 0x74, 0x20, 0x61, 0x75, 0x74,
-0x68, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x65, 0x64, 0x20, 0x64, 0x75, 0x65,
-0x20, 0x74, 0x6F, 0x20, 0x69, 0x6C, 0x6C, 0x65, 0x67, 0x61, 0x6C, 0x20,
-0x73, 0x65, 0x71, 0x3D, 0x25, 0x78, 0x0A, 0x00, 0x63, 0x6C, 0x6E, 0x74,
-0x20, 0x61, 0x75, 0x74, 0x68, 0x20, 0x66, 0x61, 0x69, 0x6C, 0x2C, 0x20,
-0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3A, 0x20, 0x25, 0x64, 0x0A, 0x00,
-0x6E, 0x6F, 0x20, 0x63, 0x68, 0x61, 0x6C, 0x6C, 0x65, 0x6E, 0x67, 0x65,
-0x20, 0x74, 0x65, 0x78, 0x74, 0x3F, 0x0A, 0x00, 0x6C, 0x69, 0x6E, 0x6B,
-0x20, 0x74, 0x6F, 0x20, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x20,
-0x41, 0x50, 0x0A, 0x00, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x74, 0x6F, 0x20,
-0x41, 0x74, 0x68, 0x65, 0x72, 0x6F, 0x73, 0x20, 0x41, 0x50, 0x28, 0x4D,
-0x41, 0x43, 0x29, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x61, 0x63, 0x20,
-0x69, 0x64, 0x20, 0x23, 0x25, 0x78, 0x3A, 0x20, 0x25, 0x78, 0x2C, 0x20,
-0x25, 0x78, 0x0A, 0x00, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x74, 0x6F, 0x20,
-0x42, 0x72, 0x6F, 0x61, 0x64, 0x63, 0x6F, 0x6D, 0x20, 0x41, 0x50, 0x0A,
-0x00, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x74, 0x6F, 0x20,
-0x41, 0x74, 0x68, 0x65, 0x72, 0x6F, 0x73, 0x20, 0x41, 0x50, 0x0A, 0x00,
-0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x74, 0x6F, 0x20, 0x4D, 0x61, 0x72, 0x76,
-0x65, 0x6C, 0x6C, 0x20, 0x41, 0x50, 0x0A, 0x00, 0x6C, 0x69, 0x6E, 0x6B,
-0x20, 0x74, 0x6F, 0x20, 0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x6B, 0x20,
-0x39, 0x36, 0x42, 0x20, 0x41, 0x50, 0x0A, 0x00, 0x6C, 0x69, 0x6E, 0x6B,
-0x20, 0x74, 0x6F, 0x20, 0x43, 0x69, 0x73, 0x63, 0x6F, 0x20, 0x41, 0x50,
-0x0A, 0x00, 0x00, 0x00, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x74, 0x6F, 0x20,
-0x52, 0x61, 0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x41, 0x50, 0x0A, 0x00, 0x00,
-0x6C, 0x69, 0x6E, 0x6B, 0x20, 0x74, 0x6F, 0x20, 0x52, 0x65, 0x61, 0x6C,
-0x74, 0x65, 0x6B, 0x20, 0x39, 0x36, 0x42, 0x20, 0x41, 0x50, 0x20, 0x77,
-0x69, 0x74, 0x68, 0x20, 0x76, 0x69, 0x64, 0x65, 0x6F, 0x20, 0x6D, 0x6F,
-0x64, 0x65, 0x0A, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x64, 0x65,
-0x61, 0x75, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75,
-0x65, 0x5F, 0x64, 0x65, 0x61, 0x75, 0x74, 0x68, 0x0A, 0x00, 0x00, 0x00,
-0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x64, 0x69, 0x73, 0x61, 0x73, 0x73,
-0x6F, 0x63, 0x00, 0x00, 0x69, 0x73, 0x73, 0x75, 0x65, 0x5F, 0x64, 0x69,
-0x73, 0x61, 0x73, 0x73, 0x6F, 0x63, 0x0A, 0x00, 0x69, 0x73, 0x73, 0x75,
-0x65, 0x5F, 0x66, 0x72, 0x61, 0x6D, 0x65, 0x5F, 0x6C, 0x65, 0x6E, 0x00,
-0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x20, 0x74,
-0x69, 0x6D, 0x65, 0x72, 0x3A, 0x20, 0x6E, 0x6F, 0x20, 0x62, 0x65, 0x61,
-0x63, 0x6F, 0x6E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x64, 0x69, 0x73, 0x63,
-0x6F, 0x6E, 0x6E, 0x65, 0x63, 0x74, 0x28, 0x6E, 0x6F, 0x20, 0x64, 0x61,
-0x74, 0x61, 0x20, 0x72, 0x63, 0x76, 0x64, 0x29, 0x0A, 0x00, 0x00, 0x00,
-0x69, 0x73, 0x73, 0x75, 0x65, 0x20, 0x51, 0x6F, 0x73, 0x4E, 0x75, 0x6C,
-0x6C, 0x28, 0x25, 0x64, 0x29, 0x00, 0x00, 0x00, 0x60, 0x1B, 0x02, 0x80,
-0xB0, 0x03, 0x25, 0xB0, 0x18, 0x03, 0x25, 0xB0, 0x44, 0x44, 0x33, 0x33,
-0x06, 0x00, 0x2A, 0xB0, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB4, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0x38, 0x4A, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0x2C, 0x4A, 0x01, 0x80, 0x20, 0x4A, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0x14, 0x4A, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0x08, 0x4A, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xFC, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xF0, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xE4, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xD8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xCC, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80, 0xB8, 0x49, 0x01, 0x80,
-0xB8, 0x49, 0x01, 0x80, 0xC0, 0x49, 0x01, 0x80, 0xF8, 0x4A, 0x01, 0x80,
-0xEC, 0x4A, 0x01, 0x80, 0xE0, 0x4A, 0x01, 0x80, 0xD4, 0x4A, 0x01, 0x80,
-0xC8, 0x4A, 0x01, 0x80, 0xBC, 0x4A, 0x01, 0x80, 0xB0, 0x4A, 0x01, 0x80,
-0xA4, 0x4A, 0x01, 0x80, 0x98, 0x4A, 0x01, 0x80, 0x8C, 0x4A, 0x01, 0x80,
-0x80, 0x4A, 0x01, 0x80, 0x74, 0x4A, 0x01, 0x80, 0x00, 0x50, 0xF2, 0x01,
-0x00, 0x50, 0xF2, 0x02, 0x00, 0x0F, 0xAC, 0x02, 0x30, 0x31, 0x32, 0x33,
-0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46,
-0x00, 0x00, 0x00, 0x00, 0x25, 0x64, 0x2E, 0x00, 0x25, 0x68, 0x68, 0x58,
-0x3A, 0x00, 0x00, 0x00, 0xEC, 0xEE, 0x01, 0x80, 0x67, 0x66, 0x66, 0x66,
-0x87, 0x7C, 0x00, 0x80, 0x5D, 0x7C, 0x00, 0x80, 0x37, 0x7C, 0x00, 0x80,
-0x11, 0x7C, 0x00, 0x80, 0xC1, 0x7B, 0x00, 0x80, 0x9B, 0x7B, 0x00, 0x80,
-0xEB, 0x7B, 0x00, 0x80, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x63,
-0x61, 0x6D, 0x20, 0x65, 0x6E, 0x74, 0x72, 0x79, 0x20, 0x28, 0x25, 0x78,
-0x2C, 0x20, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00, 0x2D, 0x3E, 0x28, 0x25,
-0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25, 0x78, 0x2C, 0x20, 0x25,
-0x78, 0x29, 0x0A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x09, 0x00, 0x00,
-0xDF, 0x88, 0x00, 0x80, 0xE5, 0x88, 0x00, 0x80, 0xEB, 0x88, 0x00, 0x80,
-0xF1, 0x88, 0x00, 0x80, 0xDF, 0x88, 0x00, 0x80, 0xDF, 0x88, 0x00, 0x80,
-0xDF, 0x88, 0x00, 0x80, 0xDF, 0x88, 0x00, 0x80, 0xF7, 0x88, 0x00, 0x80,
-0xFD, 0x88, 0x00, 0x80, 0x03, 0x89, 0x00, 0x80, 0x09, 0x89, 0x00, 0x80,
-0x60, 0x1B, 0x02, 0x80, 0x55, 0x6E, 0x69, 0x20, 0x4F, 0x6B, 0x3A, 0x20,
-0x41, 0x50, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0xFF,
-0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xFF, 0x03, 0xFE, 0x01, 0x80, 0x7F,
-0xE2, 0x01, 0x80, 0x78, 0xC7, 0x01, 0xC0, 0x71, 0xAE, 0x01, 0x80, 0x6B,
-0x95, 0x01, 0x40, 0x65, 0x7F, 0x01, 0xC0, 0x5F, 0x69, 0x01, 0x40, 0x5A,
-0x55, 0x01, 0x40, 0x55, 0x42, 0x01, 0x80, 0x50, 0x30, 0x01, 0x00, 0x4C,
-0x1F, 0x01, 0xC0, 0x47, 0x0F, 0x01, 0xC0, 0x43, 0x00, 0x01, 0x00, 0x40,
-0xF2, 0x00, 0x80, 0x3C, 0xE4, 0x00, 0x00, 0x39, 0xD7, 0x00, 0xC0, 0x35,
-0xCB, 0x00, 0xC0, 0x32, 0xC0, 0x00, 0x00, 0x30, 0xB5, 0x00, 0x40, 0x2D,
-0xAB, 0x00, 0xC0, 0x2A, 0xA2, 0x00, 0x80, 0x28, 0x98, 0x00, 0x00, 0x26,
-0x90, 0x00, 0x00, 0x24, 0x88, 0x00, 0x00, 0x22, 0x80, 0x00, 0x00, 0x20,
-0x79, 0x00, 0x40, 0x1E, 0x72, 0x00, 0x80, 0x1C, 0x6C, 0x00, 0x00, 0x1B,
-0x66, 0x00, 0x80, 0x19, 0x60, 0x00, 0x00, 0x18, 0x5B, 0x00, 0xC0, 0x16,
-0x56, 0x00, 0x80, 0x15, 0x51, 0x00, 0x40, 0x14, 0x4C, 0x00, 0x00, 0x13,
-0x48, 0x00, 0x00, 0x12, 0x44, 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x10,
-0x36, 0x35, 0x2E, 0x25, 0x1C, 0x12, 0x09, 0x04, 0x33, 0x32, 0x2B, 0x23,
-0x1A, 0x11, 0x08, 0x04, 0x30, 0x2F, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
-0x2D, 0x2D, 0x27, 0x1F, 0x18, 0x0F, 0x08, 0x03, 0x2B, 0x2A, 0x25, 0x1E,
-0x16, 0x0E, 0x07, 0x03, 0x28, 0x28, 0x22, 0x1C, 0x15, 0x0D, 0x07, 0x03,
-0x26, 0x25, 0x21, 0x1B, 0x14, 0x0D, 0x06, 0x03, 0x24, 0x23, 0x1F, 0x19,
-0x13, 0x0C, 0x06, 0x03, 0x22, 0x21, 0x1D, 0x18, 0x11, 0x0B, 0x06, 0x02,
-0x20, 0x20, 0x1B, 0x16, 0x11, 0x08, 0x05, 0x02, 0x1F, 0x1E, 0x1A, 0x15,
-0x10, 0x0A, 0x05, 0x02, 0x1D, 0x1C, 0x18, 0x14, 0x0F, 0x0A, 0x05, 0x02,
-0x1B, 0x1A, 0x17, 0x13, 0x0E, 0x09, 0x04, 0x02, 0x1A, 0x19, 0x16, 0x12,
-0x0D, 0x09, 0x04, 0x02, 0x18, 0x17, 0x15, 0x11, 0x0C, 0x08, 0x04, 0x02,
-0x17, 0x16, 0x13, 0x10, 0x0C, 0x08, 0x04, 0x02, 0x16, 0x15, 0x12, 0x0F,
-0x0B, 0x07, 0x04, 0x01, 0x14, 0x14, 0x11, 0x0E, 0x0B, 0x07, 0x03, 0x02,
-0x13, 0x13, 0x10, 0x0D, 0x0A, 0x06, 0x03, 0x01, 0x12, 0x12, 0x0F, 0x0C,
-0x09, 0x06, 0x03, 0x01, 0x11, 0x11, 0x0F, 0x0C, 0x09, 0x06, 0x03, 0x01,
-0x10, 0x10, 0x0E, 0x0B, 0x08, 0x05, 0x03, 0x01, 0x0F, 0x0F, 0x0D, 0x0B,
-0x08, 0x05, 0x03, 0x01, 0x0E, 0x0E, 0x0C, 0x0A, 0x08, 0x05, 0x02, 0x01,
-0x0D, 0x0D, 0x0C, 0x0A, 0x07, 0x05, 0x02, 0x01, 0x0D, 0x0C, 0x0B, 0x09,
-0x07, 0x04, 0x02, 0x01, 0x0C, 0x0C, 0x0A, 0x09, 0x06, 0x04, 0x02, 0x01,
-0x0B, 0x0B, 0x0A, 0x08, 0x06, 0x04, 0x02, 0x01, 0x0B, 0x0A, 0x09, 0x08,
-0x06, 0x04, 0x02, 0x01, 0x0A, 0x0A, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01,
-0x0A, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01, 0x09, 0x09, 0x08, 0x06,
-0x05, 0x03, 0x01, 0x01, 0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01,
-0x36, 0x35, 0x2E, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x33, 0x32, 0x2B, 0x19,
-0x00, 0x00, 0x00, 0x00, 0x30, 0x2F, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00,
-0x2D, 0x2D, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x2A, 0x25, 0x15,
-0x00, 0x00, 0x00, 0x00, 0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00,
-0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, 0x24, 0x23, 0x1F, 0x12,
-0x00, 0x00, 0x00, 0x00, 0x22, 0x21, 0x1D, 0x11, 0x00, 0x00, 0x00, 0x00,
-0x20, 0x20, 0x1B, 0x10, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1E, 0x1A, 0x0F,
-0x00, 0x00, 0x00, 0x00, 0x1D, 0x1C, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00,
-0x1B, 0x1A, 0x17, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x19, 0x16, 0x0D,
-0x00, 0x00, 0x00, 0x00, 0x18, 0x17, 0x15, 0x0C, 0x00, 0x00, 0x00, 0x00,
-0x17, 0x16, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x16, 0x15, 0x12, 0x0B,
-0x00, 0x00, 0x00, 0x00, 0x14, 0x14, 0x11, 0x0A, 0x00, 0x00, 0x00, 0x00,
-0x13, 0x13, 0x10, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0F, 0x09,
-0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x0F, 0x09, 0x00, 0x00, 0x00, 0x00,
-0x10, 0x10, 0x0E, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0D, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x0C, 0x07, 0x00, 0x00, 0x00, 0x00,
-0x0D, 0x0D, 0x0C, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0C, 0x0B, 0x06,
-0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00,
-0x0B, 0x0B, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x0A, 0x09, 0x05,
-0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00,
-0x0A, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x08, 0x05,
-0x00, 0x00, 0x00, 0x00, 0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00,
-0x72, 0x65, 0x73, 0x65, 0x74, 0x28, 0x25, 0x78, 0x29, 0x0A, 0x00, 0x00,
-0x50, 0x53, 0x00, 0x00, 0xE8, 0x86, 0x01, 0x80, 0x58, 0x87, 0x01, 0x80,
-0x14, 0x87, 0x01, 0x80, 0x58, 0x87, 0x01, 0x80, 0x58, 0x87, 0x01, 0x80,
-0x58, 0x87, 0x01, 0x80, 0x58, 0x87, 0x01, 0x80, 0xC0, 0x86, 0x01, 0x80,
-0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
-0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
-0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
-0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
-0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x28, 0x28, 0x28, 0x28, 0x28, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
-0xA0, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-0x10, 0x10, 0x10, 0x10, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
-0x04, 0x04, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x41, 0x41, 0x41,
-0x41, 0x41, 0x41, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x10,
-0x10, 0x10, 0x10, 0x10, 0x10, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x02,
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x10, 0x10, 0x10, 0x08,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x10, 0x10, 0x10,
-0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
-0x10, 0x10, 0x10, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-0x01, 0x01, 0x01, 0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x10,
-0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x2D, 0x5C, 0x7C, 0x2F,
-0x00, 0x00, 0x00, 0x00, 0x0A, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0xF0, 0xF4, 0x5E, 0x00, 0xF0, 0xF4, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE5, 0x5E, 0x00,
-0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0xB8, 0xA0, 0xFC, 0x08, 0xFF, 0xFF, 0xFF, 0xFF,
-};
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
index 84be383..1411c7bf 100644
--- a/drivers/staging/rtl8712/hal_init.c
+++ b/drivers/staging/rtl8712/hal_init.c
@@ -31,7 +31,6 @@
 #include "osdep_service.h"
 #include "drv_types.h"
 #include "rtl871x_byteorder.h"
-#include "farray.h"
 #include "usb_osintf.h"
 
 #define FWBUFF_ALIGN_SZ 512
@@ -40,12 +39,26 @@
 static u32 rtl871x_open_fw(struct _adapter *padapter, void **pphfwfile_hdl,
 		    const u8 **ppmappedfw)
 {
-	u32 len;
+	int rc;
+	const char firmware_file[] = "rtlwifi/rtl8712u.bin";
+	const struct firmware **praw = (const struct firmware **)
+				       (pphfwfile_hdl);
+	struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
+					(&padapter->dvobjpriv);
+	struct usb_device *pusbdev = pdvobjpriv->pusbdev;
 
-	*ppmappedfw = f_array;
-	len = sizeof(f_array);
-	return len;
+	printk(KERN_INFO "r8712u: Loading firmware from \"%s\"\n",
+	       firmware_file);
+	rc = request_firmware(praw, firmware_file, &pusbdev->dev);
+	if (rc < 0) {
+		printk(KERN_ERR "r8712u: Unable to load firmware\n");
+		printk(KERN_ERR "r8712u: Install latest linux-firmware\n");
+		return 0;
+	}
+	*ppmappedfw = (u8 *)((*praw)->data);
+	return (*praw)->size;
 }
+MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
 
 static void fill_fwpriv(struct _adapter *padapter, struct fw_priv *pfwpriv)
 {
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index 685a7b1..bd315c7 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -27,6 +27,7 @@
  ******************************************************************************/
 
 #define _RTL871X_IOCTL_LINUX_C_
+#define _RTL871X_MP_IOCTL_C_
 
 #include "osdep_service.h"
 #include "drv_types.h"
@@ -280,18 +281,20 @@ static inline char *translate_scan(struct _adapter *padapter,
 	/* parsing WPA/WPA2 IE */
 	{
 		u16 wpa_len = 0, rsn_len = 0;
-		u8 *p;
+		int n;
 		sint out_len = 0;
 		out_len = r8712_get_sec_ie(pnetwork->network.IEs,
 					   pnetwork->network.
 					   IELength, rsn_ie, &rsn_len,
 					   wpa_ie, &wpa_len);
 		if (wpa_len > 0) {
-			p = buf;
 			memset(buf, 0, MAX_WPA_IE_LEN);
-			p += snprintf(p, 7, "wpa_ie=");
-			for (i = 0; i < wpa_len; i++)
-				p += snprintf(p, 2, "%02x", wpa_ie[i]);
+			n = sprintf(buf, "wpa_ie=");
+			for (i = 0; i < wpa_len; i++) {
+				n += snprintf(buf + n, MAX_WPA_IE_LEN - n, "%02x", wpa_ie[i]);
+				if (n >= MAX_WPA_IE_LEN)
+					break;
+			}
 			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVCUSTOM;
 			iwe.u.data.length = (u16)strlen(buf);
@@ -304,11 +307,13 @@ static inline char *translate_scan(struct _adapter *padapter,
 				&iwe, wpa_ie);
 		}
 		if (rsn_len > 0) {
-			p = buf;
 			memset(buf, 0, MAX_WPA_IE_LEN);
-			p += snprintf(p, 7, "rsn_ie=");
-			for (i = 0; i < rsn_len; i++)
-				p += snprintf(p, 2, "%02x", rsn_ie[i]);
+			n = sprintf(buf, "rsn_ie=");
+			for (i = 0; i < rsn_len; i++) {
+				n += snprintf(buf + n, MAX_WPA_IE_LEN - n, "%02x", rsn_ie[i]);
+				if (n >= MAX_WPA_IE_LEN)
+					break;
+			}
 			memset(&iwe, 0, sizeof(iwe));
 			iwe.cmd = IWEVCUSTOM;
 			iwe.u.data.length = strlen(buf);
@@ -953,7 +958,7 @@ static int r871x_wx_set_priv(struct net_device *dev,
 
 	len = dwrq->length;
 	ext = _malloc(len);
-	if (!_malloc(len))
+	if (!ext)
 		return -ENOMEM;
 	if (copy_from_user(ext, dwrq->pointer, len)) {
 		kfree(ext);
@@ -1868,8 +1873,7 @@ static int r871x_mp_ioctl_hdl(struct net_device *dev,
 		goto _r871x_mp_ioctl_hdl_exit;
 	}
 _r871x_mp_ioctl_hdl_exit:
-	if (pparmbuf != NULL)
-		kfree(pparmbuf);
+	kfree(pparmbuf);
 	return ret;
 }
 
@@ -1965,9 +1969,9 @@ static int r871x_wps_start(struct net_device *dev,
 	struct _adapter *padapter = (struct _adapter *)_netdev_priv(dev);
 	struct iw_point *pdata = &wrqu->data;
 	u32   u32wps_start = 0;
-	unsigned int uintRet = 0;
 
-	uintRet = copy_from_user((void *)&u32wps_start, pdata->pointer, 4);
+	if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
+		return -EFAULT;
 	if ((padapter->bDriverStopped) || (pdata == NULL))
 		return -EINVAL;
 	if (u32wps_start == 0)
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
index d60aaa9..5eb461b 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
+++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
@@ -26,8 +26,6 @@
  *
  ******************************************************************************/
 
-#define _RTL871X_MP_IOCTL_C_
-
 #include "osdep_service.h"
 #include "drv_types.h"
 #include "mlme_osdep.h"
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
index 2225bd1..fdd2278 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
+++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
@@ -373,7 +373,7 @@ unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv);
 #ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */
 /* This ifdef _MUST_ be left in!! */
 
-struct mp_ioctl_handler mp_ioctl_hdl[] = {
+static struct mp_ioctl_handler mp_ioctl_hdl[] = {
 	{sizeof(u32), oid_rt_pro_start_test_hdl,
 			     OID_RT_PRO_START_TEST},/*0*/
 	{sizeof(u32), oid_rt_pro_stop_test_hdl,
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
index 9244c8a..23e72a0 100644
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c
+++ b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
@@ -92,7 +92,7 @@ void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode, uint smart_ps)
  *
  * This will be called when CPWM interrupt is up.
  *
- * using to update cpwn of drv; and drv willl make a decision to up or
+ * using to update cpwn of drv; and drv will make a decision to up or
  * down pwr level
  */
 void r8712_cpwm_int_hdl(struct _adapter *padapter,
diff --git a/drivers/staging/rts_pstor/Kconfig b/drivers/staging/rts_pstor/Kconfig
new file mode 100644
index 0000000..4d66a99
--- /dev/null
+++ b/drivers/staging/rts_pstor/Kconfig
@@ -0,0 +1,16 @@
+config RTS_PSTOR
+	tristate "RealTek PCI-E Card Reader support"
+	depends on PCI && SCSI
+	help
+	  Say Y here to include driver code to support the Realtek
+	  PCI-E card readers.
+
+	  If this driver is compiled as a module, it will be named rts_pstor.
+
+config RTS_PSTOR_DEBUG
+	bool "Realtek PCI-E Card Reader verbose debug"
+	depends on RTS_PSTOR
+	help
+	  Say Y here in order to have the rts_pstor code generate
+	  verbose debugging messages.
+
diff --git a/drivers/staging/rts_pstor/Makefile b/drivers/staging/rts_pstor/Makefile
new file mode 100644
index 0000000..61609ae
--- /dev/null
+++ b/drivers/staging/rts_pstor/Makefile
@@ -0,0 +1,16 @@
+EXTRA_CFLAGS	:= -Idrivers/scsi
+
+obj-$(CONFIG_RTS_PSTOR)	:= rts_pstor.o
+
+rts_pstor-y :=				\
+		rtsx.o			\
+		rtsx_chip.o		\
+		rtsx_transport.o	\
+		rtsx_scsi.o		\
+		rtsx_card.o		\
+		general.o		\
+		sd.o			\
+		xd.o			\
+		ms.o			\
+		spi.o
+
diff --git a/drivers/staging/rts_pstor/TODO b/drivers/staging/rts_pstor/TODO
new file mode 100644
index 0000000..2f93a7c
--- /dev/null
+++ b/drivers/staging/rts_pstor/TODO
@@ -0,0 +1,5 @@
+TODO:
+- support more pcie card reader of Realtek family
+- use kernel coding style
+- checkpatch.pl fixes
+
diff --git a/drivers/staging/rts_pstor/debug.h b/drivers/staging/rts_pstor/debug.h
new file mode 100644
index 0000000..e1408b0
--- /dev/null
+++ b/drivers/staging/rts_pstor/debug.h
@@ -0,0 +1,43 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_DEBUG_H
+#define __REALTEK_RTSX_DEBUG_H
+
+#include <linux/kernel.h>
+
+#define RTSX_STOR "rts_pstor: "
+
+#if CONFIG_RTS_PSTOR_DEBUG
+#define RTSX_DEBUGP(x...) printk(KERN_DEBUG RTSX_STOR x)
+#define RTSX_DEBUGPN(x...) printk(KERN_DEBUG x)
+#define RTSX_DEBUGPX(x...) printk(x)
+#define RTSX_DEBUG(x) x
+#else
+#define RTSX_DEBUGP(x...)
+#define RTSX_DEBUGPN(x...)
+#define RTSX_DEBUGPX(x...)
+#define RTSX_DEBUG(x)
+#endif
+
+#endif   /* __REALTEK_RTSX_DEBUG_H */
diff --git a/drivers/staging/rts_pstor/general.c b/drivers/staging/rts_pstor/general.c
new file mode 100644
index 0000000..056e98d
--- /dev/null
+++ b/drivers/staging/rts_pstor/general.c
@@ -0,0 +1,35 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include "general.h"
+
+int bit1cnt_long(u32 data)
+{
+	int i, cnt = 0;
+	for (i = 0; i < 32; i++) {
+		if (data & 0x01)
+			cnt++;
+		data >>= 1;
+	}
+	return cnt;
+}
+
diff --git a/drivers/staging/rts_pstor/general.h b/drivers/staging/rts_pstor/general.h
new file mode 100644
index 0000000..f17930d
--- /dev/null
+++ b/drivers/staging/rts_pstor/general.h
@@ -0,0 +1,31 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_GENERAL_H
+#define __RTSX_GENERAL_H
+
+#include "rtsx.h"
+
+int bit1cnt_long(u32 data);
+
+#endif /* __RTSX_GENERAL_H */
diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c
new file mode 100644
index 0000000..810e170
--- /dev/null
+++ b/drivers/staging/rts_pstor/ms.c
@@ -0,0 +1,4248 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "ms.h"
+
+static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+
+	ms_card->err_code = err_code;
+}
+
+static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+
+	return (ms_card->err_code == err_code);
+}
+
+static int ms_parse_err_code(struct rtsx_chip *chip)
+{
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode, u8 tpc, u8 cnt, u8 cfg)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	u8 *ptr;
+
+	RTSX_DEBUGP("ms_transfer_tpc: tpc = 0x%x\n", tpc);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+	rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
+	if (retval < 0) {
+		rtsx_clear_ms_error(chip);
+		ms_set_err_code(chip, MS_TO_ERROR);
+		TRACE_RET(chip, ms_parse_err_code(chip));
+	}
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+
+	if (!(tpc & 0x08)) {		/* Read Packet */
+		if (*ptr & MS_CRC16_ERR) {
+			ms_set_err_code(chip, MS_CRC16_ERROR);
+			TRACE_RET(chip, ms_parse_err_code(chip));
+		}
+	} else {			/* Write Packet */
+		if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) {
+			if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) {
+				ms_set_err_code(chip, MS_CMD_NK);
+				TRACE_RET(chip, ms_parse_err_code(chip));
+			}
+		}
+	}
+
+	if (*ptr & MS_RDY_TIMEOUT) {
+		rtsx_clear_ms_error(chip);
+		ms_set_err_code(chip, MS_TO_ERROR);
+		TRACE_RET(chip, ms_parse_err_code(chip));
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode, u8 tpc, u16 sec_cnt,
+		u8 cfg, int mode_2k, int use_sg, void *buf, int buf_len)
+{
+	int retval;
+	u8 val, err_code = 0;
+	enum dma_data_direction dir;
+
+	if (!buf || !buf_len) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (trans_mode == MS_TM_AUTO_READ) {
+		dir = DMA_FROM_DEVICE;
+		err_code = MS_FLASH_READ_ERROR;
+	} else if (trans_mode == MS_TM_AUTO_WRITE) {
+		dir = DMA_TO_DEVICE;
+		err_code = MS_FLASH_WRITE_ERROR;
+	} else {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_add_cmd(chip, WRITE_REG_CMD,
+		     MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+
+	if (mode_2k) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD,
+			     MS_CFG, MS_2K_SECTOR_MODE, MS_2K_SECTOR_MODE);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, 0);
+	}
+
+	trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD,
+		     MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode);
+	rtsx_add_cmd(chip, CHECK_REG_CMD,
+		     MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+	rtsx_send_cmd_no_wait(chip);
+
+	retval = rtsx_transfer_data(chip, MS_CARD, buf, buf_len,
+				    use_sg, dir, chip->mspro_timeout);
+	if (retval < 0) {
+		ms_set_err_code(chip, err_code);
+		if (retval == -ETIMEDOUT) {
+			retval = STATUS_TIMEDOUT;
+		} else {
+			retval = STATUS_FAIL;
+		}
+		TRACE_RET(chip, retval);
+	}
+
+	RTSX_READ_REG(chip, MS_TRANS_CFG, &val);
+	if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_write_bytes(struct rtsx_chip *chip,
+			  u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+
+	if (!data || (data_len < cnt)) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	rtsx_init_cmd(chip);
+
+	for (i = 0; i < cnt; i++) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD,
+			     PPBUF_BASE2 + i, 0xFF, data[i]);
+	}
+	if (cnt % 2) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF);
+	}
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD,
+		     MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
+	rtsx_add_cmd(chip, CHECK_REG_CMD,
+		     MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
+	if (retval < 0) {
+		u8 val = 0;
+
+		rtsx_read_register(chip, MS_TRANS_CFG, &val);
+		RTSX_DEBUGP("MS_TRANS_CFG: 0x%02x\n", val);
+
+		rtsx_clear_ms_error(chip);
+
+		if (!(tpc & 0x08)) {
+			if (val & MS_CRC16_ERR) {
+				ms_set_err_code(chip, MS_CRC16_ERROR);
+				TRACE_RET(chip, ms_parse_err_code(chip));
+			}
+		} else {
+			if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
+				if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
+					ms_set_err_code(chip, MS_CMD_NK);
+					TRACE_RET(chip, ms_parse_err_code(chip));
+				}
+			}
+		}
+
+		if (val & MS_RDY_TIMEOUT) {
+			ms_set_err_code(chip, MS_TO_ERROR);
+			TRACE_RET(chip, ms_parse_err_code(chip));
+		}
+
+		ms_set_err_code(chip, MS_TO_ERROR);
+		TRACE_RET(chip, ms_parse_err_code(chip));
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_read_bytes(struct rtsx_chip *chip, u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 *ptr;
+
+	if (!data) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_READ_BYTES);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+	for (i = 0; i < data_len - 1; i++) {
+	       rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
+	}
+	if (data_len % 2) {
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
+	} else {
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1, 0, 0);
+	}
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
+	if (retval < 0) {
+		u8 val = 0;
+
+		rtsx_read_register(chip, MS_TRANS_CFG, &val);
+		rtsx_clear_ms_error(chip);
+
+		if (!(tpc & 0x08)) {
+			if (val & MS_CRC16_ERR) {
+				ms_set_err_code(chip, MS_CRC16_ERROR);
+				TRACE_RET(chip, ms_parse_err_code(chip));
+			}
+		} else {
+			if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
+				if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
+					ms_set_err_code(chip, MS_CMD_NK);
+					TRACE_RET(chip, ms_parse_err_code(chip));
+				}
+			}
+		}
+
+		if (val & MS_RDY_TIMEOUT) {
+			ms_set_err_code(chip, MS_TO_ERROR);
+			TRACE_RET(chip, ms_parse_err_code(chip));
+		}
+
+		ms_set_err_code(chip, MS_TO_ERROR);
+		TRACE_RET(chip, ms_parse_err_code(chip));
+	}
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+
+	for (i = 0; i < data_len; i++) {
+		data[i] = ptr[i];
+	}
+
+	if ((tpc == PRO_READ_SHORT_DATA) && (data_len == 8)) {
+		RTSX_DEBUGP("Read format progress:\n");
+		RTSX_DUMP(ptr, cnt);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_set_rw_reg_addr(struct rtsx_chip *chip,
+		u8 read_start, u8 read_cnt, u8 write_start, u8 write_cnt)
+{
+	int retval, i;
+	u8 data[4];
+
+	data[0] = read_start;
+	data[1] = read_cnt;
+	data[2] = write_start;
+	data[3] = write_cnt;
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, SET_RW_REG_ADRS, 4,
+					NO_WAIT_INT, data, 4);
+		if (retval == STATUS_SUCCESS)
+			return STATUS_SUCCESS;
+		rtsx_clear_ms_error(chip);
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg)
+{
+	u8 data[2];
+
+	data[0] = cmd;
+	data[1] = 0;
+
+	return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1);
+}
+
+static int ms_set_init_para(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	if (CHK_HG8BIT(ms_card)) {
+		if (chip->asic_code) {
+			ms_card->ms_clock = chip->asic_ms_hg_clk;
+		} else {
+			ms_card->ms_clock = chip->fpga_ms_hg_clk;
+		}
+	} else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) {
+		if (chip->asic_code) {
+			ms_card->ms_clock = chip->asic_ms_4bit_clk;
+		} else {
+			ms_card->ms_clock = chip->fpga_ms_4bit_clk;
+		}
+	} else {
+		if (chip->asic_code) {
+			ms_card->ms_clock = chip->asic_ms_1bit_clk;
+		} else {
+			ms_card->ms_clock = chip->fpga_ms_1bit_clk;
+		}
+	}
+
+	retval = switch_clock(chip, ms_card->ms_clock);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = select_card(chip, MS_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_switch_clock(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	retval = select_card(chip, MS_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = switch_clock(chip, ms_card->ms_clock);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_pull_ctl_disable(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, 0x15);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
+			MS_D1_PD | MS_D2_PD | MS_CLK_PD | MS_D6_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
+			MS_D3_PD | MS_D0_PD | MS_BS_PD | XD_D4_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
+			MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF,
+			MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_pull_ctl_enable(struct rtsx_chip *chip)
+{
+	int retval;
+
+	rtsx_init_cmd(chip);
+
+	if (CHECK_PID(chip, 0x5209)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x15);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
+			MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
+			MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
+			MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
+			MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD,
+				     CARD_PULL_CTL1, 0xFF, 0x55);
+			rtsx_add_cmd(chip, WRITE_REG_CMD,
+				     CARD_PULL_CTL2, 0xFF, 0x45);
+			rtsx_add_cmd(chip, WRITE_REG_CMD,
+				     CARD_PULL_CTL3, 0xFF, 0x4B);
+			rtsx_add_cmd(chip, WRITE_REG_CMD,
+				     CARD_PULL_CTL4, 0xFF, 0x29);
+		}
+	}
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 100);
+	if (retval < 0) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_prepare_reset(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	u8 oc_mask = 0;
+
+	ms_card->ms_type = 0;
+	ms_card->check_ms_flow = 0;
+	ms_card->switch_8bit_fail = 0;
+	ms_card->delay_write.delay_write_flag = 0;
+
+	ms_card->pro_under_formatting = 0;
+
+	retval = ms_power_off_card3v3(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!chip->ft2_fast_mode)
+		wait_timeout(250);
+
+	retval = enable_card_clock(chip, MS_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (chip->asic_code) {
+		retval = ms_pull_ctl_enable(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_MS_PULL_CTL_BIT | 0x20, 0);
+	}
+
+	if (!chip->ft2_fast_mode) {
+		retval = card_power_on(chip, MS_CARD);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		wait_timeout(150);
+
+#ifdef SUPPORT_OCP
+		if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+			oc_mask = MS_OC_NOW | MS_OC_EVER;
+		} else {
+			oc_mask = SD_OC_NOW | SD_OC_EVER;
+		}
+		if (chip->ocp_stat & oc_mask) {
+			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n",
+				     chip->ocp_stat);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+#endif
+	}
+
+	RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, MS_OUTPUT_EN);
+
+	if (chip->asic_code) {
+		RTSX_WRITE_REG(chip, MS_CFG, 0xFF,
+			SAMPLE_TIME_RISING | PUSH_TIME_DEFAULT |
+			NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
+	} else {
+		RTSX_WRITE_REG(chip, MS_CFG, 0xFF,
+			SAMPLE_TIME_FALLING | PUSH_TIME_DEFAULT |
+			NO_EXTEND_TOGGLE | MS_BUS_WIDTH_1);
+	}
+	RTSX_WRITE_REG(chip, MS_TRANS_CFG, 0xFF, NO_WAIT_INT | NO_AUTO_READ_INT_REG);
+	RTSX_WRITE_REG(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
+
+	retval = ms_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 val;
+
+	retval = ms_set_rw_reg_addr(chip, Pro_StatusReg, 6, SystemParm, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG, 6, NO_WAIT_INT);
+		if (retval == STATUS_SUCCESS) {
+			break;
+		}
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, PPBUF_BASE2 + 2, &val);
+	RTSX_DEBUGP("Type register: 0x%x\n", val);
+	if (val != 0x01) {
+		if (val != 0x02) {
+			ms_card->check_ms_flow = 1;
+		}
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, PPBUF_BASE2 + 4, &val);
+	RTSX_DEBUGP("Category register: 0x%x\n", val);
+	if (val != 0) {
+		ms_card->check_ms_flow = 1;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, PPBUF_BASE2 + 5, &val);
+	RTSX_DEBUGP("Class register: 0x%x\n", val);
+	if (val == 0) {
+		RTSX_READ_REG(chip, PPBUF_BASE2, &val);
+		if (val & WRT_PRTCT) {
+			chip->card_wp |= MS_CARD;
+		} else {
+			chip->card_wp &= ~MS_CARD;
+		}
+	} else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) {
+		chip->card_wp |= MS_CARD;
+	} else {
+		ms_card->check_ms_flow = 1;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_card->ms_type |= TYPE_MSPRO;
+
+	RTSX_READ_REG(chip, PPBUF_BASE2 + 3, &val);
+	RTSX_DEBUGP("IF Mode register: 0x%x\n", val);
+	if (val == 0) {
+		ms_card->ms_type &= 0x0F;
+	} else if (val == 7) {
+		if (switch_8bit_bus) {
+			ms_card->ms_type |= MS_HG;
+		} else {
+			ms_card->ms_type &= 0x0F;
+		}
+	} else {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
+{
+	int retval, i, k;
+	u8 val;
+
+	/* Confirm CPU StartUp */
+	k = 0;
+	do {
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			ms_set_err_code(chip, MS_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+			retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+			if (retval == STATUS_SUCCESS) {
+				break;
+			}
+		}
+		if (i == MS_MAX_RETRY_COUNT) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (k > 100) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		k++;
+		wait_timeout(100);
+	} while (!(val & INT_REG_CED));
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val & INT_REG_ERR) {
+		if (val & INT_REG_CMDNK) {
+			chip->card_wp |= (MS_CARD);
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+	/* --  end confirm CPU startup */
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_switch_parallel_bus(struct rtsx_chip *chip)
+{
+	int retval, i;
+	u8 data[2];
+
+	data[0] = PARALLEL_4BIT_IF;
+	data[1] = 0;
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_switch_8bit_bus(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 data[2];
+
+	data[0] = PARALLEL_8BIT_IF;
+	data[1] = 0;
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT, data, 2);
+		if (retval == STATUS_SUCCESS) {
+			break;
+		}
+	}
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, MS_CFG, 0x98, MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING);
+	ms_card->ms_type |= MS_8BIT;
+	retval = ms_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, NO_WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+
+	for (i = 0; i < 3; i++) {
+		retval = ms_prepare_reset(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_identify_media_type(chip, switch_8bit_bus);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_confirm_cpu_startup(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_switch_parallel_bus(chip);
+		if (retval != STATUS_SUCCESS) {
+			if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+				ms_set_err_code(chip, MS_NO_CARD);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	/* Switch MS-PRO into Parallel mode */
+	RTSX_WRITE_REG(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4);
+	RTSX_WRITE_REG(chip, MS_CFG, PUSH_TIME_ODD, PUSH_TIME_ODD);
+
+	retval = ms_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	/* If MSPro HG Card, We shall try to switch to 8-bit bus */
+	if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) {
+		retval = ms_switch_8bit_bus(chip);
+		if (retval != STATUS_SUCCESS) {
+			ms_card->switch_8bit_fail = 1;
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+#ifdef XC_POWERCLASS
+static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
+{
+	int retval;
+	u8 buf[6];
+
+	ms_cleanup_work(chip);
+
+	retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf[0] = 0;
+	buf[1] = mode;
+	buf[2] = 0;
+	buf[3] = 0;
+	buf[4] = 0;
+	buf[5] = 0;
+
+	retval = ms_write_bytes(chip, PRO_WRITE_REG , 6, NO_WAIT_INT, buf, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, MS_TRANS_CFG, buf);
+	if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif
+
+static int ms_read_attribute_info(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 val, *buf, class_code, device_type, sub_class, data[16];
+	u16 total_blk = 0, blk_size = 0;
+#ifdef SUPPORT_MSXC
+	u32 xc_total_blk = 0, xc_blk_size = 0;
+#endif
+	u32 sys_info_addr = 0, sys_info_size;
+#ifdef SUPPORT_PCGL_1P18
+	u32 model_name_addr = 0, model_name_size;
+	int found_sys_info = 0, found_model_name = 0;
+#endif
+
+	retval = ms_set_rw_reg_addr(chip, Pro_IntReg, 2, Pro_SystemParm, 7);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MS8BIT(ms_card)) {
+		data[0] = PARALLEL_8BIT_IF;
+	} else {
+		data[0] = PARALLEL_4BIT_IF;
+	}
+	data[1] = 0;
+
+	data[2] = 0x40;
+	data[3] = 0;
+	data[4] = 0;
+	data[5] = 0;
+	data[6] = 0;
+	data[7] = 0;
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT, data, 8);
+		if (retval == STATUS_SUCCESS) {
+			break;
+		}
+	}
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf = (u8 *)rtsx_alloc_dma_buf(chip, 64 * 512, GFP_KERNEL);
+	if (buf == NULL) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			continue;
+		}
+		retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
+		if (retval != STATUS_SUCCESS) {
+			rtsx_free_dma_buf(chip, buf);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (!(val & MS_INT_BREQ)) {
+			rtsx_free_dma_buf(chip, buf);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
+				0x40, WAIT_INT, 0, 0, buf, 64 * 512);
+		if (retval == STATUS_SUCCESS) {
+			break;
+		} else {
+			rtsx_clear_ms_error(chip);
+		}
+	}
+	if (retval != STATUS_SUCCESS) {
+		rtsx_free_dma_buf(chip, buf);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	i = 0;
+	do {
+		retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
+		if (retval != STATUS_SUCCESS) {
+			rtsx_free_dma_buf(chip, buf);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if ((val & MS_INT_CED) || !(val & MS_INT_BREQ))
+			break;
+
+		retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, PRO_READ_LONG_DATA, 0, WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			rtsx_free_dma_buf(chip, buf);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		i++;
+	} while (i < 1024);
+
+	if (retval != STATUS_SUCCESS) {
+		rtsx_free_dma_buf(chip, buf);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if ((buf[0] != 0xa5) && (buf[1] != 0xc3)) {
+		/* Signature code is wrong */
+		rtsx_free_dma_buf(chip, buf);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if ((buf[4] < 1) || (buf[4] > 12)) {
+		rtsx_free_dma_buf(chip, buf);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (i = 0; i < buf[4]; i++) {
+		int cur_addr_off = 16 + i * 12;
+
+#ifdef SUPPORT_MSXC
+		if ((buf[cur_addr_off + 8] == 0x10) || (buf[cur_addr_off + 8] == 0x13))
+#else
+		if (buf[cur_addr_off + 8] == 0x10)
+#endif
+		{
+			sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) |
+				((u32)buf[cur_addr_off + 1] << 16) |
+				((u32)buf[cur_addr_off + 2] << 8) | buf[cur_addr_off + 3];
+			sys_info_size = ((u32)buf[cur_addr_off + 4] << 24) |
+				((u32)buf[cur_addr_off + 5] << 16) |
+				((u32)buf[cur_addr_off + 6] << 8) | buf[cur_addr_off + 7];
+			RTSX_DEBUGP("sys_info_addr = 0x%x, sys_info_size = 0x%x\n",
+					sys_info_addr, sys_info_size);
+			if (sys_info_size != 96)  {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (sys_info_addr < 0x1A0) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if ((sys_info_size + sys_info_addr) > 0x8000) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+#ifdef SUPPORT_MSXC
+			if (buf[cur_addr_off + 8] == 0x13) {
+				ms_card->ms_type |= MS_XC;
+			}
+#endif
+#ifdef SUPPORT_PCGL_1P18
+			found_sys_info = 1;
+#else
+			break;
+#endif
+		}
+#ifdef SUPPORT_PCGL_1P18
+		if (buf[cur_addr_off + 8] == 0x15) {
+			model_name_addr = ((u32)buf[cur_addr_off + 0] << 24) |
+				((u32)buf[cur_addr_off + 1] << 16) |
+				((u32)buf[cur_addr_off + 2] << 8) | buf[cur_addr_off + 3];
+			model_name_size = ((u32)buf[cur_addr_off + 4] << 24) |
+				((u32)buf[cur_addr_off + 5] << 16) |
+				((u32)buf[cur_addr_off + 6] << 8) | buf[cur_addr_off + 7];
+			RTSX_DEBUGP("model_name_addr = 0x%x, model_name_size = 0x%x\n",
+					model_name_addr, model_name_size);
+			if (model_name_size != 48)  {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (model_name_addr < 0x1A0) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if ((model_name_size + model_name_addr) > 0x8000) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			found_model_name = 1;
+		}
+
+		if (found_sys_info && found_model_name)
+			break;
+#endif
+	}
+
+	if (i == buf[4]) {
+		rtsx_free_dma_buf(chip, buf);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	class_code =  buf[sys_info_addr + 0];
+	device_type = buf[sys_info_addr + 56];
+	sub_class = buf[sys_info_addr + 46];
+#ifdef SUPPORT_MSXC
+	if (CHK_MSXC(ms_card)) {
+		xc_total_blk = ((u32)buf[sys_info_addr + 6] << 24) |
+				((u32)buf[sys_info_addr + 7] << 16) |
+				((u32)buf[sys_info_addr + 8] << 8) |
+				buf[sys_info_addr + 9];
+		xc_blk_size = ((u32)buf[sys_info_addr + 32] << 24) |
+				((u32)buf[sys_info_addr + 33] << 16) |
+				((u32)buf[sys_info_addr + 34] << 8) |
+				buf[sys_info_addr + 35];
+		RTSX_DEBUGP("xc_total_blk = 0x%x, xc_blk_size = 0x%x\n", xc_total_blk, xc_blk_size);
+	} else {
+		total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7];
+		blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3];
+		RTSX_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, blk_size);
+	}
+#else
+	total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7];
+	blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3];
+	RTSX_DEBUGP("total_blk = 0x%x, blk_size = 0x%x\n", total_blk, blk_size);
+#endif
+
+	RTSX_DEBUGP("class_code = 0x%x, device_type = 0x%x, sub_class = 0x%x\n",
+			class_code, device_type, sub_class);
+
+	memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96);
+#ifdef SUPPORT_PCGL_1P18
+	memcpy(ms_card->raw_model_name, buf + model_name_addr, 48);
+#endif
+
+	rtsx_free_dma_buf(chip, buf);
+
+#ifdef SUPPORT_MSXC
+	if (CHK_MSXC(ms_card)) {
+		if (class_code != 0x03) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		if (class_code != 0x02) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+#else
+	if (class_code != 0x02) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+#endif
+
+	if (device_type != 0x00) {
+		if ((device_type == 0x01) || (device_type == 0x02) ||
+				(device_type == 0x03)) {
+			chip->card_wp |= MS_CARD;
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (sub_class & 0xC0) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n",
+		class_code, device_type, sub_class);
+
+#ifdef SUPPORT_MSXC
+	if (CHK_MSXC(ms_card)) {
+		chip->capacity[chip->card2lun[MS_CARD]] =
+			ms_card->capacity = xc_total_blk * xc_blk_size;
+	} else {
+		chip->capacity[chip->card2lun[MS_CARD]] =
+			ms_card->capacity = total_blk * blk_size;
+	}
+#else
+	chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity = total_blk * blk_size;
+#endif
+
+	return STATUS_SUCCESS;
+}
+
+#ifdef SUPPORT_MAGIC_GATE
+static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, u8 mg_entry_num);
+#endif
+
+static int reset_ms_pro(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+#ifdef XC_POWERCLASS
+	u8 change_power_class;
+
+	if (chip->ms_power_class_en & 0x02)
+		change_power_class = 2;
+	else if (chip->ms_power_class_en & 0x01)
+		change_power_class = 1;
+	else
+		change_power_class = 0;
+#endif
+
+#ifdef XC_POWERCLASS
+Retry:
+#endif
+	retval = ms_pro_reset_flow(chip, 1);
+	if (retval != STATUS_SUCCESS) {
+		if (ms_card->switch_8bit_fail) {
+			retval = ms_pro_reset_flow(chip, 0);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = ms_read_attribute_info(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+#ifdef XC_POWERCLASS
+	if (CHK_HG8BIT(ms_card)) {
+		change_power_class = 0;
+	}
+
+	if (change_power_class && CHK_MSXC(ms_card)) {
+		u8 power_class_en = chip->ms_power_class_en;
+
+		RTSX_DEBUGP("power_class_en = 0x%x\n", power_class_en);
+		RTSX_DEBUGP("change_power_class = %d\n", change_power_class);
+
+		if (change_power_class) {
+			power_class_en &= (1 << (change_power_class - 1));
+		} else {
+			power_class_en = 0;
+		}
+
+		if (power_class_en) {
+			u8 power_class_mode = (ms_card->raw_sys_info[46] & 0x18) >> 3;
+			RTSX_DEBUGP("power_class_mode = 0x%x", power_class_mode);
+			if (change_power_class > power_class_mode)
+				change_power_class = power_class_mode;
+			if (change_power_class) {
+				retval = msxc_change_power(chip, change_power_class);
+				if (retval != STATUS_SUCCESS) {
+					change_power_class--;
+					goto Retry;
+				}
+			}
+		}
+	}
+#endif
+
+#ifdef SUPPORT_MAGIC_GATE
+	retval = mg_set_tpc_para_sub(chip, 0, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+#endif
+
+	if (CHK_HG8BIT(ms_card)) {
+		chip->card_bus_width[chip->card2lun[MS_CARD]] = 8;
+	} else {
+		chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_read_status_reg(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 val[2];
+
+	retval = ms_set_rw_reg_addr(chip, StatusReg0, 2, 0, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) {
+		ms_set_err_code(chip, MS_FLASH_READ_ERROR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int ms_read_extra_data(struct rtsx_chip *chip,
+		u16 block_addr, u8 page_num, u8 *buf, int buf_len)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 val, data[10];
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MS4BIT(ms_card)) {
+		/* Parallel interface */
+		data[0] = 0x88;
+	} else {
+		/* Serial interface */
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(block_addr >> 8);
+	data[3] = (u8)block_addr;
+	data[4] = 0x40;
+	data[5] = page_num;
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (val & INT_REG_CMDNK) {
+		ms_set_err_code(chip, MS_CMD_NK);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (val & INT_REG_CED) {
+		if (val & INT_REG_ERR) {
+			retval = ms_read_status_reg(chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+	}
+
+	retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT, data, MS_EXTRA_SIZE);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (buf && buf_len) {
+		if (buf_len > MS_EXTRA_SIZE)
+			buf_len = MS_EXTRA_SIZE;
+		memcpy(buf, data, buf_len);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_write_extra_data(struct rtsx_chip *chip,
+		u16 block_addr, u8 page_num, u8 *buf, int buf_len)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 val, data[16];
+
+	if (!buf || (buf_len < MS_EXTRA_SIZE)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6 + MS_EXTRA_SIZE);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MS4BIT(ms_card)) {
+		data[0] = 0x88;
+	} else {
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(block_addr >> 8);
+	data[3] = (u8)block_addr;
+	data[4] = 0x40;
+	data[5] = page_num;
+
+	for (i = 6; i < MS_EXTRA_SIZE + 6; i++) {
+		data[i] = buf[i - 6];
+	}
+
+	retval = ms_write_bytes(chip, WRITE_REG , (6+MS_EXTRA_SIZE), NO_WAIT_INT, data, 16);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (val & INT_REG_CMDNK) {
+		ms_set_err_code(chip, MS_CMD_NK);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (val & INT_REG_CED) {
+		if (val & INT_REG_ERR) {
+			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	u8 val, data[6];
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MS4BIT(ms_card)) {
+		data[0] = 0x88;
+	} else {
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(block_addr >> 8);
+	data[3] = (u8)block_addr;
+	data[4] = 0x20;
+	data[5] = page_num;
+
+	retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (val & INT_REG_CMDNK) {
+		ms_set_err_code(chip, MS_CMD_NK);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val & INT_REG_CED) {
+		if (val & INT_REG_ERR) {
+			if (!(val & INT_REG_BREQ)) {
+				ms_set_err_code(chip,  MS_FLASH_READ_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			retval = ms_read_status_reg(chip);
+			if (retval != STATUS_SUCCESS) {
+				ms_set_err_code(chip,  MS_FLASH_WRITE_ERROR);
+			}
+		} else {
+			if (!(val & INT_REG_BREQ)) {
+				ms_set_err_code(chip, MS_BREQ_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+	}
+
+	retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, NO_WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	u8 val, data[8], extra[MS_EXTRA_SIZE];
+
+	retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	if (CHK_MS4BIT(ms_card)) {
+		data[0] = 0x88;
+	} else {
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(phy_blk >> 8);
+	data[3] = (u8)phy_blk;
+	data[4] = 0x80;
+	data[5] = 0;
+	data[6] = extra[0] & 0x7F;
+	data[7] = 0xFF;
+
+	retval = ms_write_bytes(chip, WRITE_REG , 7, NO_WAIT_INT, data, 7);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val & INT_REG_CMDNK) {
+		ms_set_err_code(chip, MS_CMD_NK);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val & INT_REG_CED) {
+		if (val & INT_REG_ERR) {
+			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i = 0;
+	u8 val, data[6];
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	if (CHK_MS4BIT(ms_card)) {
+		data[0] = 0x88;
+	} else {
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(phy_blk >> 8);
+	data[3] = (u8)phy_blk;
+	data[4] = 0;
+	data[5] = 0;
+
+	retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+ERASE_RTY:
+	retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val & INT_REG_CMDNK) {
+		if (i < 3) {
+			i++;
+			goto ERASE_RTY;
+		}
+
+		ms_set_err_code(chip, MS_CMD_NK);
+		ms_set_bad_block(chip, phy_blk);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (val & INT_REG_CED) {
+		if (val & INT_REG_ERR) {
+			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len)
+{
+	if (!extra || (extra_len < MS_EXTRA_SIZE)) {
+		return;
+	}
+
+	memset(extra, 0xFF, MS_EXTRA_SIZE);
+
+	if (type == setPS_NG) {
+		/* set page status as 1:NG,and block status keep 1:OK */
+		extra[0] = 0xB8;
+	} else {
+		/* set page status as 0:Data Error,and block status keep 1:OK */
+		extra[0] = 0x98;
+	}
+
+	extra[2] = (u8)(log_blk >> 8);
+	extra[3] = (u8)log_blk;
+}
+
+static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk, u8 start_page, u8 end_page)
+{
+	int retval;
+	u8 extra[MS_EXTRA_SIZE], i;
+
+	memset(extra, 0xff, MS_EXTRA_SIZE);
+
+	extra[0] = 0xf8;	/* Block, page OK, data erased */
+	extra[1] = 0xff;
+	extra[2] = (u8)(log_blk >> 8);
+	extra[3] = (u8)log_blk;
+
+	for (i = start_page; i < end_page; i++) {
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			ms_set_err_code(chip, MS_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_write_extra_data(chip, phy_blk, i, extra, MS_EXTRA_SIZE);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
+		u16 log_blk, u8 start_page, u8 end_page)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, rty_cnt, uncorrect_flag = 0;
+	u8 extra[MS_EXTRA_SIZE], val, i, j, data[16];
+
+	RTSX_DEBUGP("Copy page from 0x%x to 0x%x, logical block is 0x%x\n",
+		old_blk, new_blk, log_blk);
+	RTSX_DEBUGP("start_page = %d, end_page = %d\n", start_page, end_page);
+
+	retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_status_reg(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, PPBUF_BASE2, &val);
+
+	if (val & BUF_FULL) {
+		retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (!(val & INT_REG_CED)) {
+			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	for (i = start_page; i < end_page; i++) {
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			ms_set_err_code(chip, MS_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		ms_read_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
+
+		retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		ms_set_err_code(chip, MS_NO_ERROR);
+
+		if (CHK_MS4BIT(ms_card)) {
+			data[0] = 0x88;
+		} else {
+			data[0] = 0x80;
+		}
+		data[1] = 0;
+		data[2] = (u8)(old_blk >> 8);
+		data[3] = (u8)old_blk;
+		data[4] = 0x20;
+		data[5] = i;
+
+		retval = ms_write_bytes(chip, WRITE_REG , 6, NO_WAIT_INT, data, 6);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		ms_set_err_code(chip, MS_NO_ERROR);
+		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (val & INT_REG_CMDNK) {
+			ms_set_err_code(chip, MS_CMD_NK);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (val & INT_REG_CED) {
+			if (val & INT_REG_ERR) {
+				retval = ms_read_status_reg(chip);
+				if (retval != STATUS_SUCCESS) {
+					uncorrect_flag = 1;
+					RTSX_DEBUGP("Uncorrectable error\n");
+				} else {
+					uncorrect_flag = 0;
+				}
+
+				retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA, 0, NO_WAIT_INT);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+
+				if (uncorrect_flag) {
+					ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE);
+					if (i == 0) {
+						extra[0] &= 0xEF;
+					}
+					ms_write_extra_data(chip, old_blk, i, extra, MS_EXTRA_SIZE);
+					RTSX_DEBUGP("page %d : extra[0] = 0x%x\n", i, extra[0]);
+					MS_SET_BAD_BLOCK_FLG(ms_card);
+
+					ms_set_page_status(log_blk, setPS_Error, extra, MS_EXTRA_SIZE);
+					ms_write_extra_data(chip, new_blk, i, extra, MS_EXTRA_SIZE);
+					continue;
+				}
+
+				for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT; rty_cnt++) {
+					retval = ms_transfer_tpc(chip, MS_TM_NORMAL_WRITE,
+							WRITE_PAGE_DATA, 0, NO_WAIT_INT);
+					if (retval == STATUS_SUCCESS) {
+						break;
+					}
+				}
+				if (rty_cnt == MS_MAX_RETRY_COUNT) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+
+			if (!(val & INT_REG_BREQ)) {
+				ms_set_err_code(chip, MS_BREQ_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		retval = ms_set_rw_reg_addr(chip, OverwriteFlag,
+				MS_EXTRA_SIZE, SystemParm, (6+MS_EXTRA_SIZE));
+
+		ms_set_err_code(chip, MS_NO_ERROR);
+
+		if (CHK_MS4BIT(ms_card)) {
+			data[0] = 0x88;
+		} else {
+			data[0] = 0x80;
+		}
+		data[1] = 0;
+		data[2] = (u8)(new_blk >> 8);
+		data[3] = (u8)new_blk;
+		data[4] = 0x20;
+		data[5] = i;
+
+		if ((extra[0] & 0x60) != 0x60) {
+			data[6] = extra[0];
+		} else {
+			data[6] = 0xF8;
+		}
+		data[6 + 1] = 0xFF;
+		data[6 + 2] = (u8)(log_blk >> 8);
+		data[6 + 3] = (u8)log_blk;
+
+		for (j = 4; j <= MS_EXTRA_SIZE; j++) {
+			data[6 + j] = 0xFF;
+		}
+
+		retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE), NO_WAIT_INT, data, 16);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		ms_set_err_code(chip, MS_NO_ERROR);
+		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (val & INT_REG_CMDNK) {
+			ms_set_err_code(chip, MS_CMD_NK);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (val & INT_REG_CED) {
+			if (val & INT_REG_ERR) {
+				ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		if (i == 0) {
+			retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			ms_set_err_code(chip, MS_NO_ERROR);
+
+			if (CHK_MS4BIT(ms_card)) {
+				data[0] = 0x88;
+			} else {
+				data[0] = 0x80;
+			}
+			data[1] = 0;
+			data[2] = (u8)(old_blk >> 8);
+			data[3] = (u8)old_blk;
+			data[4] = 0x80;
+			data[5] = 0;
+			data[6] = 0xEF;
+			data[7] = 0xFF;
+
+			retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			ms_set_err_code(chip, MS_NO_ERROR);
+			retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			if (val & INT_REG_CMDNK) {
+				ms_set_err_code(chip, MS_CMD_NK);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			if (val & INT_REG_CED) {
+				if (val & INT_REG_ERR) {
+					ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int reset_ms(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	u16 i, reg_addr, block_size;
+	u8 val, extra[MS_EXTRA_SIZE], j, *ptr;
+#ifndef SUPPORT_MAGIC_GATE
+	u16 eblock_cnt;
+#endif
+
+	retval = ms_prepare_reset(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_card->ms_type |= TYPE_MS;
+
+	retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_status_reg(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, PPBUF_BASE2, &val);
+	if (val & WRT_PRTCT) {
+		chip->card_wp |= MS_CARD;
+	} else {
+		chip->card_wp &= ~MS_CARD;
+	}
+
+	i = 0;
+
+RE_SEARCH:
+	/* Search Boot Block */
+	while (i < (MAX_DEFECTIVE_BLOCK + 2)) {
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			ms_set_err_code(chip, MS_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE);
+		if (retval != STATUS_SUCCESS) {
+			i++;
+			continue;
+		}
+
+		if (extra[0] & BLOCK_OK) {
+			if (!(extra[1] & NOT_BOOT_BLOCK)) {
+				ms_card->boot_block = i;
+				break;
+			}
+		}
+		i++;
+	}
+
+	if (i == (MAX_DEFECTIVE_BLOCK + 2)) {
+		RTSX_DEBUGP("No boot block found!");
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (j = 0; j < 3; j++) {
+		retval = ms_read_page(chip, ms_card->boot_block, j);
+		if (retval != STATUS_SUCCESS) {
+			if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) {
+				i = ms_card->boot_block + 1;
+				ms_set_err_code(chip, MS_NO_ERROR);
+				goto RE_SEARCH;
+			}
+		}
+	}
+
+	retval = ms_read_page(chip, ms_card->boot_block, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	/* Read MS system information as sys_info */
+	rtsx_init_cmd(chip);
+
+	for (i = 0; i < 96; i++) {
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0);
+	}
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 100);
+	if (retval < 0) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ptr = rtsx_get_cmd_data(chip);
+	memcpy(ms_card->raw_sys_info, ptr, 96);
+
+	/* Read useful block contents */
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0);
+
+	for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3; reg_addr++) {
+		rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
+	}
+
+	for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++) {
+		rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
+	}
+
+	rtsx_add_cmd(chip, READ_REG_CMD, MS_Device_Type, 0, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_Support, 0, 0);
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 100);
+	if (retval < 0) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ptr = rtsx_get_cmd_data(chip);
+
+	RTSX_DEBUGP("Boot block data:\n");
+	RTSX_DUMP(ptr, 16);
+
+	/* Block ID error
+	 * HEADER_ID0, HEADER_ID1
+	 */
+	if (ptr[0] != 0x00 || ptr[1] != 0x01) {
+		i = ms_card->boot_block + 1;
+		goto RE_SEARCH;
+	}
+
+	/* Page size error
+	 * PAGE_SIZE_0, PAGE_SIZE_1
+	 */
+	if (ptr[12] != 0x02 || ptr[13] != 0x00) {
+		i = ms_card->boot_block + 1;
+		goto RE_SEARCH;
+	}
+
+	if ((ptr[14] == 1) || (ptr[14] == 3)) {
+		chip->card_wp |= MS_CARD;
+	}
+
+	/* BLOCK_SIZE_0, BLOCK_SIZE_1 */
+	block_size = ((u16)ptr[6] << 8) | ptr[7];
+	if (block_size == 0x0010) {
+		/* Block size 16KB */
+		ms_card->block_shift = 5;
+		ms_card->page_off = 0x1F;
+	} else if (block_size == 0x0008) {
+		/* Block size 8KB */
+		ms_card->block_shift = 4;
+		ms_card->page_off = 0x0F;
+	}
+
+	/* BLOCK_COUNT_0, BLOCK_COUNT_1 */
+	ms_card->total_block = ((u16)ptr[8] << 8) | ptr[9];
+
+#ifdef SUPPORT_MAGIC_GATE
+	j = ptr[10];
+
+	if (ms_card->block_shift == 4)  { /* 4MB or 8MB */
+		if (j < 2)  { /* Effective block for 4MB: 0x1F0 */
+			ms_card->capacity = 0x1EE0;
+		} else { /* Effective block for 8MB: 0x3E0 */
+			ms_card->capacity = 0x3DE0;
+		}
+	} else  { /* 16MB, 32MB, 64MB or 128MB */
+		if (j < 5)  { /* Effective block for 16MB: 0x3E0 */
+			ms_card->capacity = 0x7BC0;
+		} else if (j < 0xA) { /* Effective block for 32MB: 0x7C0 */
+			ms_card->capacity = 0xF7C0;
+		} else if (j < 0x11) { /* Effective block for 64MB: 0xF80 */
+			ms_card->capacity = 0x1EF80;
+		} else { /* Effective block for 128MB: 0x1F00 */
+			ms_card->capacity = 0x3DF00;
+		}
+	}
+#else
+	/* EBLOCK_COUNT_0, EBLOCK_COUNT_1 */
+	eblock_cnt = ((u16)ptr[10] << 8) | ptr[11];
+
+	ms_card->capacity = ((u32)eblock_cnt - 2) << ms_card->block_shift;
+#endif
+
+	chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity;
+
+	/* Switch I/F Mode */
+	if (ptr[15]) {
+		retval = ms_set_rw_reg_addr(chip, 0, 0, SystemParm, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		RTSX_WRITE_REG(chip, PPBUF_BASE2, 0xFF, 0x88);
+		RTSX_WRITE_REG(chip, PPBUF_BASE2 + 1, 0xFF, 0);
+
+		retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG , 1, NO_WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		RTSX_WRITE_REG(chip, MS_CFG, 0x58 | MS_NO_CHECK_INT,
+				MS_BUS_WIDTH_4 | PUSH_TIME_ODD | MS_NO_CHECK_INT);
+
+		ms_card->ms_type |= MS_4BIT;
+	}
+
+	if (CHK_MS4BIT(ms_card)) {
+		chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
+	} else {
+		chip->card_bus_width[chip->card2lun[MS_CARD]] = 1;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_init_l2p_tbl(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int size, i, seg_no, retval;
+	u16 defect_block, reg_addr;
+	u8 val1, val2;
+
+	ms_card->segment_cnt = ms_card->total_block >> 9;
+	RTSX_DEBUGP("ms_card->segment_cnt = %d\n", ms_card->segment_cnt);
+
+	size = ms_card->segment_cnt * sizeof(struct zone_entry);
+	ms_card->segment = (struct zone_entry *)vmalloc(size);
+	if (ms_card->segment == NULL) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	memset(ms_card->segment, 0, size);
+
+	retval = ms_read_page(chip, ms_card->boot_block, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, INIT_FAIL);
+	}
+
+	reg_addr = PPBUF_BASE2;
+	for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) {
+		retval = rtsx_read_register(chip, reg_addr++, &val1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, INIT_FAIL);
+		}
+		retval = rtsx_read_register(chip, reg_addr++, &val2);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, INIT_FAIL);
+		}
+
+		defect_block = ((u16)val1 << 8) | val2;
+		if (defect_block == 0xFFFF) {
+			break;
+		}
+		seg_no = defect_block / 512;
+		ms_card->segment[seg_no].defect_list[ms_card->segment[seg_no].disable_count++] = defect_block;
+	}
+
+	for (i = 0; i < ms_card->segment_cnt; i++) {
+		ms_card->segment[i].build_flag = 0;
+		ms_card->segment[i].l2p_table = NULL;
+		ms_card->segment[i].free_table = NULL;
+		ms_card->segment[i].get_index = 0;
+		ms_card->segment[i].set_index = 0;
+		ms_card->segment[i].unused_blk_cnt = 0;
+
+		RTSX_DEBUGP("defective block count of segment %d is %d\n",
+					i, ms_card->segment[i].disable_count);
+	}
+
+	return STATUS_SUCCESS;
+
+INIT_FAIL:
+	if (ms_card->segment) {
+		vfree(ms_card->segment);
+		ms_card->segment = NULL;
+	}
+
+	return STATUS_FAIL;
+}
+
+static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct zone_entry *segment;
+
+	if (ms_card->segment == NULL)
+		return 0xFFFF;
+
+	segment = &(ms_card->segment[seg_no]);
+
+	if (segment->l2p_table)
+		return segment->l2p_table[log_off];
+
+	return 0xFFFF;
+}
+
+static void ms_set_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off, u16 phy_blk)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct zone_entry *segment;
+
+	if (ms_card->segment == NULL)
+		return;
+
+	segment = &(ms_card->segment[seg_no]);
+	if (segment->l2p_table) {
+		segment->l2p_table[log_off] = phy_blk;
+	}
+}
+
+static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct zone_entry *segment;
+	int seg_no;
+
+	seg_no = (int)phy_blk >> 9;
+	segment = &(ms_card->segment[seg_no]);
+
+	segment->free_table[segment->set_index++] = phy_blk;
+	if (segment->set_index >= MS_FREE_TABLE_CNT) {
+		segment->set_index = 0;
+	}
+	segment->unused_blk_cnt++;
+}
+
+static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct zone_entry *segment;
+	u16 phy_blk;
+
+	segment = &(ms_card->segment[seg_no]);
+
+	if (segment->unused_blk_cnt <= 0)
+		return 0xFFFF;
+
+	phy_blk = segment->free_table[segment->get_index];
+	segment->free_table[segment->get_index++] = 0xFFFF;
+	if (segment->get_index >= MS_FREE_TABLE_CNT) {
+		segment->get_index = 0;
+	}
+	segment->unused_blk_cnt--;
+
+	return phy_blk;
+}
+
+static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478, 2974, 3470,
+	3966, 4462, 4958, 5454, 5950, 6446, 6942, 7438, 7934};
+
+static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk, u16 log_off, u8 us1, u8 us2)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct zone_entry *segment;
+	int seg_no;
+	u16 tmp_blk;
+
+	seg_no = (int)phy_blk >> 9;
+	segment = &(ms_card->segment[seg_no]);
+	tmp_blk = segment->l2p_table[log_off];
+
+	if (us1 != us2) {
+		if (us1 == 0) {
+			if (!(chip->card_wp & MS_CARD)) {
+				ms_erase_block(chip, tmp_blk);
+			}
+			ms_set_unused_block(chip, tmp_blk);
+			segment->l2p_table[log_off] = phy_blk;
+		} else {
+			if (!(chip->card_wp & MS_CARD)) {
+				ms_erase_block(chip, phy_blk);
+			}
+			ms_set_unused_block(chip, phy_blk);
+		}
+	} else {
+		if (phy_blk < tmp_blk) {
+			if (!(chip->card_wp & MS_CARD)) {
+				ms_erase_block(chip, phy_blk);
+			}
+			ms_set_unused_block(chip, phy_blk);
+		} else {
+			if (!(chip->card_wp & MS_CARD)) {
+				ms_erase_block(chip, tmp_blk);
+			}
+			ms_set_unused_block(chip, tmp_blk);
+			segment->l2p_table[log_off] = phy_blk;
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct zone_entry *segment;
+	int retval, table_size, disable_cnt, defect_flag, i;
+	u16 start, end, phy_blk, log_blk, tmp_blk;
+	u8 extra[MS_EXTRA_SIZE], us1, us2;
+
+	RTSX_DEBUGP("ms_build_l2p_tbl: %d\n", seg_no);
+
+	if (ms_card->segment == NULL) {
+		retval = ms_init_l2p_tbl(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, retval);
+		}
+	}
+
+	if (ms_card->segment[seg_no].build_flag) {
+		RTSX_DEBUGP("l2p table of segment %d has been built\n", seg_no);
+		return STATUS_SUCCESS;
+	}
+
+	if (seg_no == 0) {
+		table_size = 494;
+	} else {
+		table_size = 496;
+	}
+
+	segment = &(ms_card->segment[seg_no]);
+
+	if (segment->l2p_table == NULL) {
+		segment->l2p_table = (u16 *)vmalloc(table_size * 2);
+		if (segment->l2p_table == NULL) {
+			TRACE_GOTO(chip, BUILD_FAIL);
+		}
+	}
+	memset((u8 *)(segment->l2p_table), 0xff, table_size * 2);
+
+	if (segment->free_table == NULL) {
+		segment->free_table = (u16 *)vmalloc(MS_FREE_TABLE_CNT * 2);
+		if (segment->free_table == NULL) {
+			TRACE_GOTO(chip, BUILD_FAIL);
+		}
+	}
+	memset((u8 *)(segment->free_table), 0xff, MS_FREE_TABLE_CNT * 2);
+
+	start = (u16)seg_no << 9;
+	end = (u16)(seg_no + 1) << 9;
+
+	disable_cnt = segment->disable_count;
+
+	segment->get_index = segment->set_index = 0;
+	segment->unused_blk_cnt = 0;
+
+	for (phy_blk = start; phy_blk < end; phy_blk++) {
+		if (disable_cnt) {
+			defect_flag = 0;
+			for (i = 0; i < segment->disable_count; i++) {
+				if (phy_blk == segment->defect_list[i]) {
+					defect_flag = 1;
+					break;
+				}
+			}
+			if (defect_flag) {
+				disable_cnt--;
+				continue;
+			}
+		}
+
+		retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
+		if (retval != STATUS_SUCCESS) {
+			RTSX_DEBUGP("read extra data fail\n");
+			ms_set_bad_block(chip, phy_blk);
+			continue;
+		}
+
+		if (seg_no == ms_card->segment_cnt - 1) {
+			if (!(extra[1] & NOT_TRANSLATION_TABLE)) {
+				if (!(chip->card_wp & MS_CARD)) {
+					retval = ms_erase_block(chip, phy_blk);
+					if (retval != STATUS_SUCCESS)
+						continue;
+					extra[2] = 0xff;
+					extra[3] = 0xff;
+				}
+			}
+		}
+
+		if (!(extra[0] & BLOCK_OK))
+			continue;
+		if (!(extra[1] & NOT_BOOT_BLOCK))
+			continue;
+		if ((extra[0] & PAGE_OK) != PAGE_OK)
+			continue;
+
+		log_blk = ((u16)extra[2] << 8) | extra[3];
+
+		if (log_blk == 0xFFFF) {
+			if (!(chip->card_wp & MS_CARD)) {
+				retval = ms_erase_block(chip, phy_blk);
+				if (retval != STATUS_SUCCESS)
+					continue;
+			}
+			ms_set_unused_block(chip, phy_blk);
+			continue;
+		}
+
+		if ((log_blk < ms_start_idx[seg_no]) ||
+				(log_blk >= ms_start_idx[seg_no+1])) {
+			if (!(chip->card_wp & MS_CARD)) {
+				retval = ms_erase_block(chip, phy_blk);
+				if (retval != STATUS_SUCCESS)
+					continue;
+			}
+			ms_set_unused_block(chip, phy_blk);
+			continue;
+		}
+
+		if (segment->l2p_table[log_blk - ms_start_idx[seg_no]] == 0xFFFF) {
+			segment->l2p_table[log_blk - ms_start_idx[seg_no]] = phy_blk;
+			continue;
+		}
+
+		us1 = extra[0] & 0x10;
+		tmp_blk = segment->l2p_table[log_blk - ms_start_idx[seg_no]];
+		retval = ms_read_extra_data(chip, tmp_blk, 0, extra, MS_EXTRA_SIZE);
+		if (retval != STATUS_SUCCESS)
+			continue;
+		us2 = extra[0] & 0x10;
+
+		(void)ms_arbitrate_l2p(chip, phy_blk, log_blk-ms_start_idx[seg_no], us1, us2);
+		continue;
+	}
+
+	segment->build_flag = 1;
+
+	RTSX_DEBUGP("unused block count: %d\n", segment->unused_blk_cnt);
+
+	/* Logical Address Confirmation Process */
+	if (seg_no == ms_card->segment_cnt - 1) {
+		if (segment->unused_blk_cnt < 2) {
+			chip->card_wp |= MS_CARD;
+		}
+	} else {
+		if (segment->unused_blk_cnt < 1) {
+			chip->card_wp |= MS_CARD;
+		}
+	}
+
+	if (chip->card_wp & MS_CARD)
+		return STATUS_SUCCESS;
+
+	for (log_blk = ms_start_idx[seg_no]; log_blk < ms_start_idx[seg_no + 1]; log_blk++) {
+		if (segment->l2p_table[log_blk-ms_start_idx[seg_no]] == 0xFFFF) {
+			phy_blk = ms_get_unused_block(chip, seg_no);
+			if (phy_blk == 0xFFFF) {
+				chip->card_wp |= MS_CARD;
+				return STATUS_SUCCESS;
+			}
+			retval = ms_init_page(chip, phy_blk, log_blk, 0, 1);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_GOTO(chip, BUILD_FAIL);
+			}
+			segment->l2p_table[log_blk-ms_start_idx[seg_no]] = phy_blk;
+			if (seg_no == ms_card->segment_cnt - 1) {
+				if (segment->unused_blk_cnt < 2) {
+					chip->card_wp |= MS_CARD;
+					return STATUS_SUCCESS;
+				}
+			} else {
+				if (segment->unused_blk_cnt < 1) {
+					chip->card_wp |= MS_CARD;
+					return STATUS_SUCCESS;
+				}
+			}
+		}
+	}
+
+	/* Make boot block be the first normal block */
+	if (seg_no == 0) {
+		for (log_blk = 0; log_blk < 494; log_blk++) {
+			tmp_blk = segment->l2p_table[log_blk];
+			if (tmp_blk < ms_card->boot_block) {
+				RTSX_DEBUGP("Boot block is not the first normal block.\n");
+
+				if (chip->card_wp & MS_CARD)
+					break;
+
+				phy_blk = ms_get_unused_block(chip, 0);
+				retval = ms_copy_page(chip, tmp_blk, phy_blk,
+						log_blk, 0, ms_card->page_off + 1);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+
+				segment->l2p_table[log_blk] = phy_blk;
+
+				retval = ms_set_bad_block(chip, tmp_blk);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+		}
+	}
+
+	return STATUS_SUCCESS;
+
+BUILD_FAIL:
+	segment->build_flag = 0;
+	if (segment->l2p_table) {
+		vfree(segment->l2p_table);
+		segment->l2p_table = NULL;
+	}
+	if (segment->free_table) {
+		vfree(segment->free_table);
+		segment->free_table = NULL;
+	}
+
+	return STATUS_FAIL;
+}
+
+
+int reset_ms_card(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	memset(ms_card, 0, sizeof(struct ms_info));
+
+	retval = enable_card_clock(chip, MS_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = select_card(chip, MS_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_card->ms_type = 0;
+
+	retval = reset_ms_pro(chip);
+	if (retval != STATUS_SUCCESS) {
+		if (ms_card->check_ms_flow) {
+			retval = reset_ms(chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = ms_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!CHK_MSPRO(ms_card)) {
+		/* Build table for the last segment,
+		 * to check if L2P talbe block exist,erasing it
+		 */
+		retval = ms_build_l2p_tbl(chip, ms_card->total_block / 512 - 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	RTSX_DEBUGP("ms_card->ms_type = 0x%x\n", ms_card->ms_type);
+
+	return STATUS_SUCCESS;
+}
+
+static int mspro_set_rw_cmd(struct rtsx_chip *chip, u32 start_sec, u16 sec_cnt, u8 cmd)
+{
+	int retval, i;
+	u8 data[8];
+
+	data[0] = cmd;
+	data[1] = (u8)(sec_cnt >> 8);
+	data[2] = (u8)sec_cnt;
+	data[3] = (u8)(start_sec >> 24);
+	data[4] = (u8)(start_sec >> 16);
+	data[5] = (u8)(start_sec >> 8);
+	data[6] = (u8)start_sec;
+	data[7] = 0;
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+void mspro_stop_seq_mode(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	if (ms_card->seq_mode) {
+		retval = ms_switch_clock(chip);
+		if (retval != STATUS_SUCCESS)
+			return;
+
+		ms_card->seq_mode = 0;
+		ms_card->total_sec_cnt = 0;
+		ms_send_cmd(chip, PRO_STOP, WAIT_INT);
+
+		rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
+	}
+}
+
+static inline int ms_auto_tune_clock(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	if (chip->asic_code) {
+		if (ms_card->ms_clock > 30) {
+			ms_card->ms_clock -= 20;
+		}
+	} else {
+		if (ms_card->ms_clock == CLK_80) {
+			ms_card->ms_clock = CLK_60;
+		} else if (ms_card->ms_clock == CLK_60) {
+			ms_card->ms_clock = CLK_40;
+		}
+	}
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int mspro_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, mode_2k = 0;
+	u16 count;
+	u8 val, trans_mode, rw_tpc, rw_cmd;
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	ms_card->cleanup_counter = 0;
+
+	if (CHK_MSHG(ms_card)) {
+		if ((start_sector % 4) || (sector_cnt % 4)) {
+			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+				rw_tpc = PRO_READ_LONG_DATA;
+				rw_cmd = PRO_READ_DATA;
+			} else {
+				rw_tpc = PRO_WRITE_LONG_DATA;
+				rw_cmd = PRO_WRITE_DATA;
+			}
+		} else {
+			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+				rw_tpc = PRO_READ_QUAD_DATA;
+				rw_cmd = PRO_READ_2K_DATA;
+			} else {
+				rw_tpc = PRO_WRITE_QUAD_DATA;
+				rw_cmd = PRO_WRITE_2K_DATA;
+			}
+			mode_2k = 1;
+		}
+	} else {
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			rw_tpc = PRO_READ_LONG_DATA;
+			rw_cmd = PRO_READ_DATA;
+		} else {
+			rw_tpc = PRO_WRITE_LONG_DATA;
+			rw_cmd = PRO_WRITE_DATA;
+		}
+	}
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+		trans_mode = MS_TM_AUTO_READ;
+	} else {
+		trans_mode = MS_TM_AUTO_WRITE;
+	}
+
+	RTSX_READ_REG(chip, MS_TRANS_CFG, &val);
+
+	if (ms_card->seq_mode) {
+		if ((ms_card->pre_dir != srb->sc_data_direction)
+				|| ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) != start_sector)
+				|| (mode_2k && (ms_card->seq_mode & MODE_512_SEQ))
+				|| (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ))
+				|| !(val & MS_INT_BREQ)
+				|| ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) {
+			ms_card->seq_mode = 0;
+			ms_card->total_sec_cnt = 0;
+			if (val & MS_INT_BREQ) {
+				retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+
+				rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
+			}
+		}
+	}
+
+	if (!ms_card->seq_mode) {
+		ms_card->total_sec_cnt = 0;
+		if (sector_cnt >= SEQ_START_CRITERIA) {
+			if ((ms_card->capacity - start_sector) > 0xFE00) {
+				count = 0xFE00;
+			} else {
+				count = (u16)(ms_card->capacity - start_sector);
+			}
+			if (count > sector_cnt) {
+				if (mode_2k) {
+					ms_card->seq_mode |= MODE_2K_SEQ;
+				} else {
+					ms_card->seq_mode |= MODE_512_SEQ;
+				}
+			}
+		} else {
+			count = sector_cnt;
+		}
+		retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd);
+		if (retval != STATUS_SUCCESS) {
+			ms_card->seq_mode = 0;
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt, WAIT_INT, mode_2k,
+			scsi_sg_count(srb), scsi_sglist(srb), scsi_bufflen(srb));
+	if (retval != STATUS_SUCCESS) {
+		ms_card->seq_mode = 0;
+		rtsx_read_register(chip, MS_TRANS_CFG, &val);
+		rtsx_clear_ms_error(chip);
+
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			chip->rw_need_retry = 0;
+			RTSX_DEBUGP("No card exist, exit mspro_rw_multi_sector\n");
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (val & MS_INT_BREQ) {
+			ms_send_cmd(chip, PRO_STOP, WAIT_INT);
+		}
+		if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
+			RTSX_DEBUGP("MSPro CRC error, tune clock!\n");
+			chip->rw_need_retry = 1;
+			ms_auto_tune_clock(chip);
+		}
+
+		TRACE_RET(chip, retval);
+	}
+
+	if (ms_card->seq_mode) {
+		ms_card->pre_sec_addr = start_sector;
+		ms_card->pre_sec_cnt = sector_cnt;
+		ms_card->pre_dir = srb->sc_data_direction;
+		ms_card->total_sec_cnt += sector_cnt;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int mspro_read_format_progress(struct rtsx_chip *chip, const int short_data_len)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u32 total_progress, cur_progress;
+	u8 cnt, tmp;
+	u8 data[8];
+
+	RTSX_DEBUGP("mspro_read_format_progress, short_data_len = %d\n", short_data_len);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
+	if (retval != STATUS_SUCCESS) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!(tmp & MS_INT_BREQ)) {
+		if ((tmp &  (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK | MS_INT_ERR)) == MS_INT_CED) {
+			ms_card->format_status = FORMAT_SUCCESS;
+			return STATUS_SUCCESS;
+		}
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (short_data_len >= 256) {
+		cnt = 0;
+	} else {
+		cnt = (u8)short_data_len;
+	}
+
+	retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, MS_NO_CHECK_INT);
+	if (retval != STATUS_SUCCESS) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT, data, 8);
+	if (retval != STATUS_SUCCESS) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	total_progress = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
+	cur_progress = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7];
+
+	RTSX_DEBUGP("total_progress = %d, cur_progress = %d\n",
+				total_progress, cur_progress);
+
+	if (total_progress == 0) {
+		ms_card->progress = 0;
+	} else {
+		u64 ulltmp = (u64)cur_progress * (u64)65535;
+		do_div(ulltmp, total_progress);
+		ms_card->progress = (u16)ulltmp;
+	}
+	RTSX_DEBUGP("progress = %d\n", ms_card->progress);
+
+	for (i = 0; i < 5000; i++) {
+		retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
+		if (retval != STATUS_SUCCESS) {
+			ms_card->format_status = FORMAT_FAIL;
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (tmp & (MS_INT_CED | MS_INT_CMDNK | MS_INT_BREQ | MS_INT_ERR)) {
+			break;
+		}
+
+		wait_timeout(1);
+	}
+
+	retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0);
+	if (retval != STATUS_SUCCESS) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (i == 5000) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
+		ms_card->format_status = FORMAT_FAIL;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (tmp & MS_INT_CED) {
+		ms_card->format_status = FORMAT_SUCCESS;
+		ms_card->pro_under_formatting = 0;
+	} else if (tmp & MS_INT_BREQ) {
+		ms_card->format_status = FORMAT_IN_PROGRESS;
+	} else {
+		ms_card->format_status = FORMAT_FAIL;
+		ms_card->pro_under_formatting = 0;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+void mspro_polling_format_status(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int i;
+
+	if (ms_card->pro_under_formatting && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
+		rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+		for (i = 0; i < 65535; i++) {
+			mspro_read_format_progress(chip, MS_SHORT_DATA_LEN);
+			if (ms_card->format_status != FORMAT_IN_PROGRESS)
+				break;
+		}
+	}
+
+	return;
+}
+
+int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_len, int quick_format)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 buf[8], tmp;
+	u16 para;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, Pro_TPCParm, 0x01);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	memset(buf, 0, 2);
+	switch (short_data_len) {
+	case 32:
+		buf[0] = 0;
+		break;
+	case 64:
+		buf[0] = 1;
+		break;
+	case 128:
+		buf[0] = 2;
+		break;
+	case 256:
+	default:
+		buf[0] = 3;
+		break;
+	}
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, PRO_WRITE_REG, 1, NO_WAIT_INT, buf, 2);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (quick_format) {
+		para = 0x0000;
+	} else {
+		para = 0x0001;
+	}
+	retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, MS_TRANS_CFG, &tmp);
+
+	if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) {
+		ms_card->pro_under_formatting = 1;
+		ms_card->progress = 0;
+		ms_card->format_status = FORMAT_IN_PROGRESS;
+		return STATUS_SUCCESS;
+	}
+
+	if (tmp & MS_INT_CED) {
+		ms_card->pro_under_formatting = 0;
+		ms_card->progress = 0;
+		ms_card->format_status = FORMAT_SUCCESS;
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
+		return STATUS_SUCCESS;
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+
+static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk,
+		u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6];
+	u8 *ptr;
+
+	retval = ms_read_extra_data(chip, phy_blk, start_page, extra, MS_EXTRA_SIZE);
+	if (retval == STATUS_SUCCESS) {
+		if ((extra[1] & 0x30) != 0x30) {
+			ms_set_err_code(chip, MS_FLASH_READ_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MS4BIT(ms_card)) {
+		data[0] = 0x88;
+	} else {
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(phy_blk >> 8);
+	data[3] = (u8)phy_blk;
+	data[4] = 0;
+	data[5] = start_page;
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ptr = buf;
+
+	for (page_addr = start_page; page_addr < end_page; page_addr++) {
+		ms_set_err_code(chip, MS_NO_ERROR);
+
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			ms_set_err_code(chip, MS_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (val & INT_REG_CMDNK) {
+			ms_set_err_code(chip, MS_CMD_NK);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (val & INT_REG_ERR) {
+			if (val & INT_REG_BREQ) {
+				retval = ms_read_status_reg(chip);
+				if (retval != STATUS_SUCCESS) {
+					if (!(chip->card_wp & MS_CARD)) {
+						reset_ms(chip);
+						ms_set_page_status(log_blk, setPS_NG, extra, MS_EXTRA_SIZE);
+						ms_write_extra_data(chip, phy_blk,
+								page_addr, extra, MS_EXTRA_SIZE);
+					}
+					ms_set_err_code(chip, MS_FLASH_READ_ERROR);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			} else {
+				ms_set_err_code(chip, MS_FLASH_READ_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			if (!(val & INT_REG_BREQ)) {
+				ms_set_err_code(chip, MS_BREQ_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		if (page_addr == (end_page - 1)) {
+			if (!(val & INT_REG_CED)) {
+				retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+
+			retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (!(val & INT_REG_CED)) {
+				ms_set_err_code(chip, MS_FLASH_READ_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			trans_cfg = NO_WAIT_INT;
+		} else {
+			trans_cfg = WAIT_INT;
+		}
+
+		rtsx_init_cmd(chip);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, trans_cfg);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+		trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
+				MS_TRANSFER_START |  MS_TM_NORMAL_READ);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, scsi_sg_count(chip->srb),
+				index, offset, DMA_FROM_DEVICE, chip->ms_timeout);
+		if (retval < 0) {
+			if (retval == -ETIMEDOUT) {
+				ms_set_err_code(chip, MS_TO_ERROR);
+				rtsx_clear_ms_error(chip);
+				TRACE_RET(chip, STATUS_TIMEDOUT);
+			}
+
+			retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
+			if (retval != STATUS_SUCCESS) {
+				ms_set_err_code(chip, MS_TO_ERROR);
+				rtsx_clear_ms_error(chip);
+				TRACE_RET(chip, STATUS_TIMEDOUT);
+			}
+			if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
+				ms_set_err_code(chip, MS_CRC16_ERROR);
+				rtsx_clear_ms_error(chip);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		if (scsi_sg_count(chip->srb) == 0)
+			ptr += 512;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
+		u16 log_blk, u8 start_page, u8 end_page, u8 *buf,
+		unsigned int *index, unsigned int *offset)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, i;
+	u8 page_addr, val, data[16];
+	u8 *ptr;
+
+	if (!start_page) {
+		retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, 7);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (CHK_MS4BIT(ms_card)) {
+			data[0] = 0x88;
+		} else {
+			data[0] = 0x80;
+		}
+		data[1] = 0;
+		data[2] = (u8)(old_blk >> 8);
+		data[3] = (u8)old_blk;
+		data[4] = 0x80;
+		data[5] = 0;
+		data[6] = 0xEF;
+		data[7] = 0xFF;
+
+		retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 8);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		ms_set_err_code(chip, MS_NO_ERROR);
+		retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1, NO_WAIT_INT);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = ms_set_rw_reg_addr(chip, OverwriteFlag, MS_EXTRA_SIZE, SystemParm, (6 + MS_EXTRA_SIZE));
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	if (CHK_MS4BIT(ms_card)) {
+		data[0] = 0x88;
+	} else {
+		data[0] = 0x80;
+	}
+	data[1] = 0;
+	data[2] = (u8)(new_blk >> 8);
+	data[3] = (u8)new_blk;
+	if ((end_page - start_page) == 1) {
+		data[4] = 0x20;
+	} else {
+		data[4] = 0;
+	}
+	data[5] = start_page;
+	data[6] = 0xF8;
+	data[7] = 0xFF;
+	data[8] = (u8)(log_blk >> 8);
+	data[9] = (u8)log_blk;
+
+	for (i = 0x0A; i < 0x10; i++) {
+		data[i] = 0xFF;
+	}
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE, NO_WAIT_INT, data, 16);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ptr = buf;
+	for (page_addr = start_page; page_addr < end_page; page_addr++) {
+		ms_set_err_code(chip, MS_NO_ERROR);
+
+		if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+			ms_set_err_code(chip, MS_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (val & INT_REG_CMDNK) {
+			ms_set_err_code(chip, MS_CMD_NK);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (val & INT_REG_ERR) {
+			ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (!(val & INT_REG_BREQ)) {
+			ms_set_err_code(chip, MS_BREQ_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		udelay(30);
+
+		rtsx_init_cmd(chip);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, WRITE_PAGE_DATA);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
+				MS_TRANSFER_START |  MS_TM_NORMAL_WRITE);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512, scsi_sg_count(chip->srb),
+				index, offset, DMA_TO_DEVICE, chip->ms_timeout);
+		if (retval < 0) {
+			ms_set_err_code(chip, MS_TO_ERROR);
+			rtsx_clear_ms_error(chip);
+
+			if (retval == -ETIMEDOUT) {
+				TRACE_RET(chip, STATUS_TIMEDOUT);
+			} else {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if ((end_page - start_page) == 1) {
+			if (!(val & INT_REG_CED)) {
+				ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			if (page_addr == (end_page - 1)) {
+				if (!(val & INT_REG_CED)) {
+					retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
+					if (retval != STATUS_SUCCESS) {
+						TRACE_RET(chip, STATUS_FAIL);
+					}
+				}
+
+				retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+
+			if ((page_addr == (end_page - 1)) || (page_addr == ms_card->page_off)) {
+				if (!(val & INT_REG_CED)) {
+					ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+		}
+
+		if (scsi_sg_count(chip->srb) == 0)
+			ptr += 512;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
+		u16 log_blk, u8 page_off)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval, seg_no;
+
+	retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
+			page_off, ms_card->page_off + 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	seg_no = old_blk >> 9;
+
+	if (MS_TST_BAD_BLOCK_FLG(ms_card)) {
+		MS_CLR_BAD_BLOCK_FLG(ms_card);
+		ms_set_bad_block(chip, old_blk);
+	} else {
+		retval = ms_erase_block(chip, old_blk);
+		if (retval == STATUS_SUCCESS) {
+			ms_set_unused_block(chip, old_blk);
+		}
+	}
+
+	ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk);
+
+	return STATUS_SUCCESS;
+}
+
+static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
+		u16 log_blk, u8 start_page)
+{
+	int retval;
+
+	if (start_page) {
+		retval = ms_copy_page(chip, old_blk, new_blk, log_blk, 0, start_page);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+#ifdef MS_DELAY_WRITE
+int ms_delay_write(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
+	int retval;
+
+	if (delay_write->delay_write_flag) {
+		retval = ms_set_init_para(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		delay_write->delay_write_flag = 0;
+		retval = ms_finish_write(chip,
+				delay_write->old_phyblock, delay_write->new_phyblock,
+				delay_write->logblock, delay_write->pageoff);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif
+
+static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+	} else {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+	}
+}
+
+static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval, seg_no;
+	unsigned int index = 0, offset = 0;
+	u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt;
+	u8 start_page, end_page = 0, page_cnt;
+	u8 *ptr;
+#ifdef MS_DELAY_WRITE
+	struct ms_delay_write_tag *delay_write = &(ms_card->delay_write);
+#endif
+
+	ms_set_err_code(chip, MS_NO_ERROR);
+
+	ms_card->cleanup_counter = 0;
+
+	ptr = (u8 *)scsi_sglist(srb);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		ms_rw_fail(srb, chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	log_blk = (u16)(start_sector >> ms_card->block_shift);
+	start_page = (u8)(start_sector & ms_card->page_off);
+
+	for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) {
+		if (log_blk < ms_start_idx[seg_no+1])
+			break;
+	}
+
+	if (ms_card->segment[seg_no].build_flag == 0) {
+		retval = ms_build_l2p_tbl(chip, seg_no);
+		if (retval != STATUS_SUCCESS) {
+			chip->card_fail |= MS_CARD;
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
+#ifdef MS_DELAY_WRITE
+		if (delay_write->delay_write_flag &&
+				(delay_write->logblock == log_blk) &&
+				(start_page > delay_write->pageoff)) {
+			delay_write->delay_write_flag = 0;
+			retval = ms_copy_page(chip,
+				delay_write->old_phyblock,
+				delay_write->new_phyblock, log_blk,
+				delay_write->pageoff, start_page);
+			if (retval != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			old_blk = delay_write->old_phyblock;
+			new_blk = delay_write->new_phyblock;
+		} else if (delay_write->delay_write_flag &&
+				(delay_write->logblock == log_blk) &&
+				(start_page == delay_write->pageoff)) {
+			delay_write->delay_write_flag = 0;
+			old_blk = delay_write->old_phyblock;
+			new_blk = delay_write->new_phyblock;
+		} else {
+			retval = ms_delay_write(chip);
+			if (retval != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+#endif
+			old_blk = ms_get_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no]);
+			new_blk  = ms_get_unused_block(chip, seg_no);
+			if ((old_blk == 0xFFFF) || (new_blk == 0xFFFF)) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = ms_prepare_write(chip, old_blk, new_blk, log_blk, start_page);
+			if (retval != STATUS_SUCCESS) {
+				if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+#ifdef MS_DELAY_WRITE
+		}
+#endif
+	} else {
+#ifdef MS_DELAY_WRITE
+		retval = ms_delay_write(chip);
+		if (retval != STATUS_SUCCESS) {
+			if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+#endif
+		old_blk = ms_get_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no]);
+		if (old_blk == 0xFFFF) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", seg_no, old_blk, new_blk);
+
+	while (total_sec_cnt) {
+		if ((start_page + total_sec_cnt) > (ms_card->page_off + 1)) {
+			end_page = ms_card->page_off + 1;
+		} else {
+			end_page = start_page + (u8)total_sec_cnt;
+		}
+		page_cnt = end_page - start_page;
+
+		RTSX_DEBUGP("start_page = %d, end_page = %d, page_cnt = %d\n",
+				start_page, end_page, page_cnt);
+
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			retval = ms_read_multiple_pages(chip,
+				old_blk, log_blk, start_page, end_page,
+				ptr, &index, &offset);
+		} else {
+			retval = ms_write_multiple_pages(chip, old_blk,
+				new_blk, log_blk, start_page, end_page,
+				ptr, &index, &offset);
+		}
+
+		if (retval != STATUS_SUCCESS) {
+			toggle_gpio(chip, 1);
+			if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			ms_rw_fail(srb, chip);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (srb->sc_data_direction == DMA_TO_DEVICE) {
+			if (end_page == (ms_card->page_off + 1)) {
+				retval = ms_erase_block(chip, old_blk);
+				if (retval == STATUS_SUCCESS) {
+					ms_set_unused_block(chip, old_blk);
+				}
+				ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk);
+			}
+		}
+
+		total_sec_cnt -= page_cnt;
+		if (scsi_sg_count(srb) == 0)
+			ptr += page_cnt * 512;
+
+		if (total_sec_cnt == 0)
+			break;
+
+		log_blk++;
+
+		for (seg_no = 0; seg_no < sizeof(ms_start_idx)/2; seg_no++) {
+			if (log_blk < ms_start_idx[seg_no+1])
+				break;
+		}
+
+		if (ms_card->segment[seg_no].build_flag == 0) {
+			retval = ms_build_l2p_tbl(chip, seg_no);
+			if (retval != STATUS_SUCCESS) {
+				chip->card_fail |= MS_CARD;
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		old_blk = ms_get_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no]);
+		if (old_blk == 0xFFFF) {
+			ms_rw_fail(srb, chip);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (srb->sc_data_direction == DMA_TO_DEVICE) {
+			new_blk = ms_get_unused_block(chip, seg_no);
+			if (new_blk == 0xFFFF) {
+				ms_rw_fail(srb, chip);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		RTSX_DEBUGP("seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n", seg_no, old_blk, new_blk);
+
+		start_page = 0;
+	}
+
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
+		if (end_page < (ms_card->page_off + 1)) {
+#ifdef MS_DELAY_WRITE
+			delay_write->delay_write_flag = 1;
+			delay_write->old_phyblock = old_blk;
+			delay_write->new_phyblock = new_blk;
+			delay_write->logblock = log_blk;
+			delay_write->pageoff = end_page;
+#else
+			retval = ms_finish_write(chip, old_blk, new_blk, log_blk, end_page);
+			if (retval != STATUS_SUCCESS) {
+				if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
+					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+
+				ms_rw_fail(srb, chip);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+#endif
+		}
+	}
+
+	scsi_set_resid(srb, 0);
+
+	return STATUS_SUCCESS;
+}
+
+int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	if (CHK_MSPRO(ms_card)) {
+		retval = mspro_rw_multi_sector(srb, chip, start_sector, sector_cnt);
+	} else {
+		retval = ms_rw_multi_sector(srb, chip, start_sector, sector_cnt);
+	}
+
+	return retval;
+}
+
+
+void ms_free_l2p_tbl(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int i = 0;
+
+	if (ms_card->segment != NULL) {
+		for (i = 0; i < ms_card->segment_cnt; i++) {
+			if (ms_card->segment[i].l2p_table != NULL) {
+				vfree(ms_card->segment[i].l2p_table);
+				ms_card->segment[i].l2p_table = NULL;
+			}
+			if (ms_card->segment[i].free_table != NULL) {
+				vfree(ms_card->segment[i].free_table);
+				ms_card->segment[i].free_table = NULL;
+			}
+		}
+		vfree(ms_card->segment);
+		ms_card->segment = NULL;
+	}
+}
+
+#ifdef SUPPORT_MAGIC_GATE
+
+#ifdef READ_BYTES_WAIT_INT
+static int ms_poll_int(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 val;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED);
+
+	retval = rtsx_send_cmd(chip, MS_CARD, 5000);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	val = *rtsx_get_cmd_data(chip);
+	if (val & MS_INT_ERR) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif
+
+#ifdef MS_SAMPLE_INT_ERR
+static int check_ms_err(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 val;
+
+	retval = rtsx_read_register(chip, MS_TRANSFER, &val);
+	if (retval != STATUS_SUCCESS)
+		return 1;
+	if (val & MS_TRANSFER_ERR)
+		return 1;
+
+	retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
+	if (retval != STATUS_SUCCESS)
+		return 1;
+
+	if (val & (MS_INT_ERR | MS_INT_CMDNK))
+		return 1;
+
+	return 0;
+}
+#else
+static int check_ms_err(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 val;
+
+	retval = rtsx_read_register(chip, MS_TRANSFER, &val);
+	if (retval != STATUS_SUCCESS)
+		return 1;
+	if (val & MS_TRANSFER_ERR)
+		return 1;
+
+	return 0;
+}
+#endif
+
+static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num)
+{
+	int retval, i;
+	u8 data[8];
+
+	data[0] = cmd;
+	data[1] = 0;
+	data[2] = 0;
+	data[3] = 0;
+	data[4] = 0;
+	data[5] = 0;
+	data[6] = entry_num;
+	data[7] = 0;
+
+	for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
+		retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT, data, 8);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+	if (i == MS_MAX_RETRY_COUNT) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (check_ms_err(chip)) {
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type, u8 mg_entry_num)
+{
+	int retval;
+	u8 buf[6];
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	if (type == 0) {
+		retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_TPCParm, 1);
+	} else {
+		retval = ms_set_rw_reg_addr(chip, 0, 0, Pro_DataCount1, 6);
+	}
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf[0] = 0;
+	buf[1] = 0;
+	if (type == 1) {
+		buf[2] = 0;
+		buf[3] = 0;
+		buf[4] = 0;
+		buf[5] = mg_entry_num;
+	}
+	retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6, NO_WAIT_INT, buf, 6);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	int i;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 buf1[32], buf2[12];
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	if (scsi_bufflen(srb) < 12) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	memset(buf1, 0, 32);
+	rtsx_stor_get_xfer_buf(buf2, min(12, (int)scsi_bufflen(srb)), srb);
+	for (i = 0; i < 8; i++) {
+		buf1[8+i] = buf2[4+i];
+	}
+	retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf1, 32);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval = STATUS_FAIL;
+	int bufflen;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 *buf = NULL;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf = (u8 *)rtsx_alloc_dma_buf(chip, 1540, GFP_KERNEL);
+	if (!buf) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	buf[0] = 0x04;
+	buf[1] = 0x1A;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+
+	retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		TRACE_GOTO(chip, GetEKBFinish);
+	}
+
+	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
+				3, WAIT_INT, 0, 0, buf + 4, 1536);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rtsx_clear_ms_error(chip);
+		TRACE_GOTO(chip, GetEKBFinish);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	bufflen = min(1052, (int)scsi_bufflen(srb));
+	rtsx_stor_set_xfer_buf(buf, bufflen, srb);
+
+GetEKBFinish:
+	if (buf) {
+		rtsx_free_dma_buf(chip, buf);
+	}
+	return retval;
+}
+
+int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	int bufflen;
+	int i;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 buf[32];
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf, 32);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	memcpy(ms_card->magic_gate_id, buf, 16);
+
+#ifdef READ_BYTES_WAIT_INT
+	retval = ms_poll_int(chip);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+#endif
+
+	retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	bufflen = min(12, (int)scsi_bufflen(srb));
+	rtsx_stor_get_xfer_buf(buf, bufflen, srb);
+
+	for (i = 0; i < 8; i++) {
+		buf[i] = buf[4+i];
+	}
+	for (i = 0; i < 24; i++) {
+		buf[8+i] = 0;
+	}
+	retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA,
+				32, WAIT_INT, buf, 32);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_card->mg_auth = 0;
+
+	return STATUS_SUCCESS;
+}
+
+int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	int bufflen;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 buf1[32], buf2[36];
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT, buf1, 32);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf2[0] = 0x00;
+	buf2[1] = 0x22;
+	buf2[2] = 0x00;
+	buf2[3] = 0x00;
+
+	memcpy(buf2 + 4, ms_card->magic_gate_id, 16);
+	memcpy(buf2 + 20, buf1, 16);
+
+	bufflen = min(36, (int)scsi_bufflen(srb));
+	rtsx_stor_set_xfer_buf(buf2, bufflen, srb);
+
+#ifdef READ_BYTES_WAIT_INT
+	retval = ms_poll_int(chip);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+#endif
+
+	return STATUS_SUCCESS;
+}
+
+int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	int i;
+	int bufflen;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 buf[32];
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	bufflen = min(12, (int)scsi_bufflen(srb));
+	rtsx_stor_get_xfer_buf(buf, bufflen, srb);
+
+	for (i = 0; i < 8; i++) {
+		buf[i] = buf[4+i];
+	}
+	for (i = 0; i < 24; i++) {
+		buf[8+i] = 0;
+	}
+	retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT, buf, 32);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ms_card->mg_auth = 1;
+
+	return STATUS_SUCCESS;
+}
+
+int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	int bufflen;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 *buf = NULL;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf = (u8 *)rtsx_alloc_dma_buf(chip, 1028, GFP_KERNEL);
+	if (!buf) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	buf[0] = 0x04;
+	buf[1] = 0x02;
+	buf[2] = 0x00;
+	buf[3] = 0x00;
+
+	retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_GOTO(chip, GetICVFinish);
+	}
+
+	retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
+				2, WAIT_INT, 0, 0, buf + 4, 1024);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		rtsx_clear_ms_error(chip);
+		TRACE_GOTO(chip, GetICVFinish);
+	}
+	if (check_ms_err(chip)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		rtsx_clear_ms_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	bufflen = min(1028, (int)scsi_bufflen(srb));
+	rtsx_stor_set_xfer_buf(buf, bufflen, srb);
+
+GetICVFinish:
+	if (buf) {
+		rtsx_free_dma_buf(chip, buf);
+	}
+	return retval;
+}
+
+int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	int bufflen;
+#ifdef MG_SET_ICV_SLOW
+	int i;
+#endif
+	unsigned int lun = SCSI_LUN(srb);
+	u8 *buf = NULL;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	ms_cleanup_work(chip);
+
+	retval = ms_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf = (u8 *)rtsx_alloc_dma_buf(chip, 1028, GFP_KERNEL);
+	if (!buf) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	bufflen = min(1028, (int)scsi_bufflen(srb));
+	rtsx_stor_get_xfer_buf(buf, bufflen, srb);
+
+	retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num);
+	if (retval != STATUS_SUCCESS) {
+		if (ms_card->mg_auth == 0) {
+			if ((buf[5] & 0xC0) != 0) {
+				set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+			} else {
+				set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+		}
+		TRACE_GOTO(chip, SetICVFinish);
+	}
+
+#ifdef MG_SET_ICV_SLOW
+	for (i = 0; i < 2; i++) {
+		udelay(50);
+
+		rtsx_init_cmd(chip);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, PRO_WRITE_LONG_DATA);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
+				MS_TRANSFER_START |  MS_TM_NORMAL_WRITE);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i*512, 512, 0, DMA_TO_DEVICE, 3000);
+		if ((retval < 0) || check_ms_err(chip)) {
+			rtsx_clear_ms_error(chip);
+			if (ms_card->mg_auth == 0) {
+				if ((buf[5] & 0xC0) != 0) {
+					set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+				} else {
+					set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+				}
+			} else {
+				set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+			}
+			retval = STATUS_FAIL;
+			TRACE_GOTO(chip, SetICVFinish);
+		}
+	}
+#else
+	retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA,
+				2, WAIT_INT, 0, 0, buf + 4, 1024);
+	if ((retval != STATUS_SUCCESS) || check_ms_err(chip) {
+		rtsx_clear_ms_error(chip);
+		if (ms_card->mg_auth == 0) {
+			if ((buf[5] & 0xC0) != 0) {
+				set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
+			} else {
+				set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
+		}
+		TRACE_GOTO(chip, SetICVFinish);
+	}
+#endif
+
+SetICVFinish:
+	if (buf) {
+		rtsx_free_dma_buf(chip, buf);
+	}
+	return retval;
+}
+
+#endif /* SUPPORT_MAGIC_GATE */
+
+void ms_cleanup_work(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+
+	if (CHK_MSPRO(ms_card)) {
+		if (ms_card->seq_mode) {
+			RTSX_DEBUGP("MS Pro: stop transmission\n");
+			mspro_stop_seq_mode(chip);
+			ms_card->cleanup_counter = 0;
+		}
+		if (CHK_MSHG(ms_card)) {
+			rtsx_write_register(chip, MS_CFG,
+				MS_2K_SECTOR_MODE, 0x00);
+		}
+	}
+#ifdef MS_DELAY_WRITE
+	else if ((!CHK_MSPRO(ms_card)) && ms_card->delay_write.delay_write_flag) {
+		RTSX_DEBUGP("MS: delay write\n");
+		ms_delay_write(chip);
+		ms_card->cleanup_counter = 0;
+	}
+#endif
+}
+
+int ms_power_off_card3v3(struct rtsx_chip *chip)
+{
+	int retval;
+
+	retval = disable_card_clock(chip, MS_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (chip->asic_code) {
+		retval = ms_pull_ctl_disable(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
+			FPGA_MS_PULL_CTL_BIT | 0x20, FPGA_MS_PULL_CTL_BIT);
+	}
+	RTSX_WRITE_REG(chip, CARD_OE, MS_OUTPUT_EN, 0);
+	if (!chip->ft2_fast_mode) {
+		retval = card_power_off(chip, MS_CARD);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int release_ms_card(struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+
+	RTSX_DEBUGP("release_ms_card\n");
+
+#ifdef MS_DELAY_WRITE
+	ms_card->delay_write.delay_write_flag = 0;
+#endif
+	ms_card->pro_under_formatting = 0;
+
+	chip->card_ready &= ~MS_CARD;
+	chip->card_fail &= ~MS_CARD;
+	chip->card_wp &= ~MS_CARD;
+
+	ms_free_l2p_tbl(chip);
+
+	memset(ms_card->raw_sys_info, 0, 96);
+#ifdef SUPPORT_PCGL_1P18
+	memset(ms_card->raw_model_name, 0, 48);
+#endif
+
+	retval = ms_power_off_card3v3(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
diff --git a/drivers/staging/rts_pstor/ms.h b/drivers/staging/rts_pstor/ms.h
new file mode 100644
index 0000000..5370198
--- /dev/null
+++ b/drivers/staging/rts_pstor/ms.h
@@ -0,0 +1,225 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_MS_H
+#define __REALTEK_RTSX_MS_H
+
+#define MS_DELAY_WRITE
+
+#define	MS_MAX_RETRY_COUNT	3
+
+#define	MS_EXTRA_SIZE		0x9
+
+#define	WRT_PRTCT		0x01
+
+/* Error Code */
+#define	MS_NO_ERROR				0x00
+#define	MS_CRC16_ERROR				0x80
+#define	MS_TO_ERROR				0x40
+#define	MS_NO_CARD				0x20
+#define	MS_NO_MEMORY				0x10
+#define	MS_CMD_NK				0x08
+#define	MS_FLASH_READ_ERROR			0x04
+#define	MS_FLASH_WRITE_ERROR			0x02
+#define	MS_BREQ_ERROR				0x01
+#define	MS_NOT_FOUND				0x03
+
+/* Transfer Protocol Command */
+#define READ_PAGE_DATA				0x02
+#define READ_REG				0x04
+#define	GET_INT					0x07
+#define WRITE_PAGE_DATA				0x0D
+#define WRITE_REG				0x0B
+#define SET_RW_REG_ADRS				0x08
+#define SET_CMD					0x0E
+
+#define	PRO_READ_LONG_DATA			0x02
+#define	PRO_READ_SHORT_DATA			0x03
+#define PRO_READ_REG				0x04
+#define	PRO_READ_QUAD_DATA			0x05
+#define PRO_GET_INT				0x07
+#define	PRO_WRITE_LONG_DATA			0x0D
+#define	PRO_WRITE_SHORT_DATA			0x0C
+#define	PRO_WRITE_QUAD_DATA			0x0A
+#define PRO_WRITE_REG				0x0B
+#define PRO_SET_RW_REG_ADRS			0x08
+#define PRO_SET_CMD				0x0E
+#define PRO_EX_SET_CMD				0x09
+
+#ifdef SUPPORT_MAGIC_GATE
+
+#define MG_GET_ID		0x40
+#define MG_SET_LID		0x41
+#define MG_GET_LEKB		0x42
+#define MG_SET_RD		0x43
+#define MG_MAKE_RMS		0x44
+#define MG_MAKE_KSE		0x45
+#define MG_SET_IBD		0x46
+#define MG_GET_IBD		0x47
+
+#endif
+
+#ifdef XC_POWERCLASS
+#define XC_CHG_POWER		0x16
+#endif
+
+#define BLOCK_READ	0xAA
+#define	BLOCK_WRITE	0x55
+#define BLOCK_END	0x33
+#define BLOCK_ERASE	0x99
+#define FLASH_STOP	0xCC
+
+#define SLEEP		0x5A
+#define CLEAR_BUF	0xC3
+#define MS_RESET	0x3C
+
+#define PRO_READ_DATA		0x20
+#define	PRO_WRITE_DATA		0x21
+#define PRO_READ_ATRB		0x24
+#define PRO_STOP		0x25
+#define PRO_ERASE		0x26
+#define	PRO_READ_2K_DATA	0x27
+#define	PRO_WRITE_2K_DATA	0x28
+
+#define PRO_FORMAT		0x10
+#define PRO_SLEEP		0x11
+
+#define	IntReg			0x01
+#define StatusReg0		0x02
+#define StatusReg1		0x03
+
+#define SystemParm		0x10
+#define BlockAdrs		0x11
+#define CMDParm			0x14
+#define PageAdrs		0x15
+
+#define OverwriteFlag		0x16
+#define ManagemenFlag		0x17
+#define LogicalAdrs		0x18
+#define ReserveArea		0x1A
+
+#define	Pro_IntReg		0x01
+#define Pro_StatusReg		0x02
+#define Pro_TypeReg		0x04
+#define	Pro_IFModeReg		0x05
+#define Pro_CatagoryReg		0x06
+#define Pro_ClassReg		0x07
+
+
+#define Pro_SystemParm		0x10
+#define Pro_DataCount1		0x11
+#define Pro_DataCount0		0x12
+#define Pro_DataAddr3		0x13
+#define Pro_DataAddr2		0x14
+#define Pro_DataAddr1		0x15
+#define Pro_DataAddr0		0x16
+
+#define Pro_TPCParm		0x17
+#define Pro_CMDParm		0x18
+
+#define	INT_REG_CED		0x80
+#define	INT_REG_ERR		0x40
+#define	INT_REG_BREQ		0x20
+#define	INT_REG_CMDNK		0x01
+
+#define	BLOCK_BOOT		0xC0
+#define	BLOCK_OK		0x80
+#define	PAGE_OK			0x60
+#define	DATA_COMPL		0x10
+
+#define	NOT_BOOT_BLOCK		0x4
+#define	NOT_TRANSLATION_TABLE	0x8
+
+#define	HEADER_ID0		PPBUF_BASE2
+#define	HEADER_ID1		(PPBUF_BASE2 + 1)
+#define	DISABLED_BLOCK0		(PPBUF_BASE2 + 0x170 + 4)
+#define	DISABLED_BLOCK1		(PPBUF_BASE2 + 0x170 + 5)
+#define	DISABLED_BLOCK2		(PPBUF_BASE2 + 0x170 + 6)
+#define	DISABLED_BLOCK3		(PPBUF_BASE2 + 0x170 + 7)
+#define	BLOCK_SIZE_0		(PPBUF_BASE2 + 0x1a0 + 2)
+#define	BLOCK_SIZE_1		(PPBUF_BASE2 + 0x1a0 + 3)
+#define	BLOCK_COUNT_0		(PPBUF_BASE2 + 0x1a0 + 4)
+#define	BLOCK_COUNT_1		(PPBUF_BASE2 + 0x1a0 + 5)
+#define	EBLOCK_COUNT_0		(PPBUF_BASE2 + 0x1a0 + 6)
+#define	EBLOCK_COUNT_1		(PPBUF_BASE2 + 0x1a0 + 7)
+#define	PAGE_SIZE_0		(PPBUF_BASE2 + 0x1a0 + 8)
+#define	PAGE_SIZE_1		(PPBUF_BASE2 + 0x1a0 + 9)
+
+#define MS_Device_Type		(PPBUF_BASE2 + 0x1D8)
+
+#define	MS_4bit_Support		(PPBUF_BASE2 + 0x1D3)
+
+#define setPS_NG	1
+#define setPS_Error	0
+
+#define	PARALLEL_8BIT_IF	0x40
+#define	PARALLEL_4BIT_IF	0x00
+#define	SERIAL_IF		0x80
+
+#define BUF_FULL	0x10
+#define BUF_EMPTY	0x20
+
+#define	MEDIA_BUSY	0x80
+#define	FLASH_BUSY	0x40
+#define	DATA_ERROR	0x20
+#define	STS_UCDT	0x10
+#define	EXTRA_ERROR	0x08
+#define	STS_UCEX	0x04
+#define	FLAG_ERROR	0x02
+#define	STS_UCFG	0x01
+
+#define MS_SHORT_DATA_LEN	32
+
+#define FORMAT_SUCCESS		0
+#define FORMAT_FAIL		1
+#define FORMAT_IN_PROGRESS	2
+
+#define	MS_SET_BAD_BLOCK_FLG(ms_card)	((ms_card)->multi_flag |= 0x80)
+#define MS_CLR_BAD_BLOCK_FLG(ms_card)	((ms_card)->multi_flag &= 0x7F)
+#define MS_TST_BAD_BLOCK_FLG(ms_card)	((ms_card)->multi_flag & 0x80)
+
+void mspro_polling_format_status(struct rtsx_chip *chip);
+
+void mspro_stop_seq_mode(struct rtsx_chip *chip);
+int reset_ms_card(struct rtsx_chip *chip);
+int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
+int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip, int short_data_len, int quick_format);
+void ms_free_l2p_tbl(struct rtsx_chip *chip);
+void ms_cleanup_work(struct rtsx_chip *chip);
+int ms_power_off_card3v3(struct rtsx_chip *chip);
+int release_ms_card(struct rtsx_chip *chip);
+#ifdef MS_DELAY_WRITE
+int ms_delay_write(struct rtsx_chip *chip);
+#endif
+
+#ifdef SUPPORT_MAGIC_GATE
+int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+#endif
+
+#endif  /* __REALTEK_RTSX_MS_H */
diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c
new file mode 100644
index 0000000..4514419
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx.c
@@ -0,0 +1,1124 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include "rtsx.h"
+#include "rtsx_chip.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "general.h"
+
+#include "ms.h"
+#include "sd.h"
+#include "xd.h"
+
+#define DRIVER_VERSION 		"v1.10"
+
+MODULE_DESCRIPTION("Realtek PCI-Express card reader driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRIVER_VERSION);
+
+static unsigned int delay_use = 1;
+module_param(delay_use, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
+
+static int ss_en;
+module_param(ss_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ss_en, "enable selective suspend");
+
+static int ss_interval = 50;
+module_param(ss_interval, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds");
+
+static int auto_delink_en;
+module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
+
+static unsigned char aspm_l0s_l1_en;
+module_param(aspm_l0s_l1_en, byte, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm");
+
+static int msi_en;
+module_param(msi_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msi_en, "enable msi");
+
+/* These are used to make sure the module doesn't unload before all the
+ * threads have exited.
+ */
+static atomic_t total_threads = ATOMIC_INIT(0);
+static DECLARE_COMPLETION(threads_gone);
+
+static irqreturn_t rtsx_interrupt(int irq, void *dev_id);
+
+/***********************************************************************
+ * Host functions
+ ***********************************************************************/
+
+static const char *host_info(struct Scsi_Host *host)
+{
+	return "SCSI emulation for PCI-Express Mass Storage devices";
+}
+
+static int slave_alloc (struct scsi_device *sdev)
+{
+	/*
+	 * Set the INQUIRY transfer length to 36.  We don't use any of
+	 * the extra data and many devices choke if asked for more or
+	 * less than 36 bytes.
+	 */
+	sdev->inquiry_len = 36;
+	return 0;
+}
+
+static int slave_configure(struct scsi_device *sdev)
+{
+	/* Scatter-gather buffers (all but the last) must have a length
+	 * divisible by the bulk maxpacket size.  Otherwise a data packet
+	 * would end up being short, causing a premature end to the data
+	 * transfer.  Since high-speed bulk pipes have a maxpacket size
+	 * of 512, we'll use that as the scsi device queue's DMA alignment
+	 * mask.  Guaranteeing proper alignment of the first buffer will
+	 * have the desired effect because, except at the beginning and
+	 * the end, scatter-gather buffers follow page boundaries. */
+	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
+
+	/* Set the SCSI level to at least 2.  We'll leave it at 3 if that's
+	 * what is originally reported.  We need this to avoid confusing
+	 * the SCSI layer with devices that report 0 or 1, but need 10-byte
+	 * commands (ala ATAPI devices behind certain bridges, or devices
+	 * which simply have broken INQUIRY data).
+	 *
+	 * NOTE: This means /dev/sg programs (ala cdrecord) will get the
+	 * actual information.  This seems to be the preference for
+	 * programs like that.
+	 *
+	 * NOTE: This also means that /proc/scsi/scsi and sysfs may report
+	 * the actual value or the modified one, depending on where the
+	 * data comes from.
+	 */
+	if (sdev->scsi_level < SCSI_2)
+		sdev->scsi_level = sdev->sdev_target->scsi_level = SCSI_2;
+
+	return 0;
+}
+
+
+/***********************************************************************
+ * /proc/scsi/ functions
+ ***********************************************************************/
+
+/* 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)
+
+static int proc_info (struct Scsi_Host *host, char *buffer,
+		char **start, off_t offset, int length, int inout)
+{
+	char *pos = buffer;
+
+	/* if someone is sending us data, just throw it away */
+	if (inout)
+		return length;
+
+	/* print the controller name */
+	SPRINTF("   Host scsi%d: %s\n", host->host_no, CR_DRIVER_NAME);
+
+	/* print product, vendor, and driver version strings */
+	SPRINTF("       Vendor: Realtek Corp.\n");
+	SPRINTF("      Product: PCIE Card Reader\n");
+	SPRINTF("      Version: %s\n", DRIVER_VERSION);
+
+	/*
+	 * 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;
+}
+
+/* queue a command */
+/* This is always called with scsi_lock(host) held */
+static int queuecommand_lck(struct scsi_cmnd *srb,
+			void (*done)(struct scsi_cmnd *))
+{
+	struct rtsx_dev *dev = host_to_rtsx(srb->device->host);
+	struct rtsx_chip *chip = dev->chip;
+
+	/* check for state-transition errors */
+	if (chip->srb != NULL) {
+		printk(KERN_ERR "Error in %s: chip->srb = %p\n",
+			__func__, chip->srb);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	/* fail the command if we are disconnecting */
+	if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
+		printk(KERN_INFO "Fail command during disconnect\n");
+		srb->result = DID_NO_CONNECT << 16;
+		done(srb);
+		return 0;
+	}
+
+	/* enqueue the command and wake up the control thread */
+	srb->scsi_done = done;
+	chip->srb = srb;
+	up(&(dev->sema));
+
+	return 0;
+}
+
+static DEF_SCSI_QCMD(queuecommand)
+
+/***********************************************************************
+ * Error handling functions
+ ***********************************************************************/
+
+/* Command timeout and abort */
+static int command_abort(struct scsi_cmnd *srb)
+{
+	struct Scsi_Host *host = srb->device->host;
+	struct rtsx_dev *dev = host_to_rtsx(host);
+	struct rtsx_chip *chip = dev->chip;
+
+	printk(KERN_INFO "%s called\n", __func__);
+
+	scsi_lock(host);
+
+	/* Is this command still active? */
+	if (chip->srb != srb) {
+		scsi_unlock(host);
+		printk(KERN_INFO "-- nothing to abort\n");
+		return FAILED;
+	}
+
+	rtsx_set_stat(chip, RTSX_STAT_ABORT);
+
+	scsi_unlock(host);
+
+	/* Wait for the aborted command to finish */
+	wait_for_completion(&dev->notify);
+
+	return SUCCESS;
+}
+
+/* This invokes the transport reset mechanism to reset the state of the
+ * device */
+static int device_reset(struct scsi_cmnd *srb)
+{
+	int result = 0;
+
+	printk(KERN_INFO "%s called\n", __func__);
+
+	return result < 0 ? FAILED : SUCCESS;
+}
+
+/* Simulate a SCSI bus reset by resetting the device's USB port. */
+static int bus_reset(struct scsi_cmnd *srb)
+{
+	int result = 0;
+
+	printk(KERN_INFO "%s called\n", __func__);
+
+	return result < 0 ? FAILED : SUCCESS;
+}
+
+
+/*
+ * this defines our host template, with which we'll allocate hosts
+ */
+
+static struct scsi_host_template rtsx_host_template = {
+	/* basic userland interface stuff */
+	.name =				CR_DRIVER_NAME,
+	.proc_name =			CR_DRIVER_NAME,
+	.proc_info =			proc_info,
+	.info =				host_info,
+
+	/* command interface -- queued only */
+	.queuecommand =			queuecommand,
+
+	/* error and abort handlers */
+	.eh_abort_handler =		command_abort,
+	.eh_device_reset_handler =	device_reset,
+	.eh_bus_reset_handler =		bus_reset,
+
+	/* queue commands only, only one command per LUN */
+	.can_queue =			1,
+	.cmd_per_lun =			1,
+
+	/* unknown initiator id */
+	.this_id =			-1,
+
+	.slave_alloc =			slave_alloc,
+	.slave_configure =		slave_configure,
+
+	/* lots of sg segments can be handled */
+	.sg_tablesize =			SG_ALL,
+
+	/* limit the total size of a transfer to 120 KB */
+	.max_sectors =                  240,
+
+	/* merge commands... this seems to help performance, but
+	 * periodically someone should test to see which setting is more
+	 * optimal.
+	 */
+	.use_clustering =		1,
+
+	/* emulated HBA */
+	.emulated =			1,
+
+	/* we do our own delay after a device or bus reset */
+	.skip_settle_delay =		1,
+
+	/* module management */
+	.module =			THIS_MODULE
+};
+
+
+static int rtsx_acquire_irq(struct rtsx_dev *dev)
+{
+	struct rtsx_chip *chip = dev->chip;
+
+	printk(KERN_INFO "%s: chip->msi_en = %d, pci->irq = %d\n",
+			__func__, chip->msi_en, dev->pci->irq);
+
+	if (request_irq(dev->pci->irq, rtsx_interrupt,
+			chip->msi_en ? 0 : IRQF_SHARED,
+			CR_DRIVER_NAME, dev)) {
+		printk(KERN_ERR "rtsx: unable to grab IRQ %d, "
+		       "disabling device\n", dev->pci->irq);
+		return -1;
+	}
+
+	dev->irq = dev->pci->irq;
+	pci_intx(dev->pci, !chip->msi_en);
+
+	return 0;
+}
+
+
+int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val)
+{
+	struct pci_dev *pdev;
+	u8 data;
+	u8 devfn = (dev << 3) | func;
+
+	pdev = pci_get_bus_and_slot(bus, devfn);
+	if (!pdev)
+		return -1;
+
+	pci_read_config_byte(pdev, offset, &data);
+	if (val)
+		*val = data;
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static int rtsx_suspend(struct pci_dev *pci, pm_message_t state)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
+	struct rtsx_chip *chip;
+
+	printk(KERN_INFO "Ready to suspend\n");
+
+	if (!dev) {
+		printk(KERN_ERR "Invalid memory\n");
+		return 0;
+	}
+
+	/* lock the device pointers */
+	mutex_lock(&(dev->dev_mutex));
+
+	chip = dev->chip;
+
+	rtsx_do_before_power_down(chip, PM_S3);
+
+	if (dev->irq >= 0) {
+		synchronize_irq(dev->irq);
+		free_irq(dev->irq, (void *)dev);
+		dev->irq = -1;
+	}
+
+	if (chip->msi_en)
+		pci_disable_msi(pci);
+
+	pci_save_state(pci);
+	pci_enable_wake(pci, pci_choose_state(pci, state), 1);
+	pci_disable_device(pci);
+	pci_set_power_state(pci, pci_choose_state(pci, state));
+
+	/* unlock the device pointers */
+	mutex_unlock(&dev->dev_mutex);
+
+	return 0;
+}
+
+static int rtsx_resume(struct pci_dev *pci)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
+	struct rtsx_chip *chip;
+
+	printk(KERN_INFO "Ready to resume\n");
+
+	if (!dev) {
+		printk(KERN_ERR "Invalid memory\n");
+		return 0;
+	}
+
+	chip = dev->chip;
+
+	/* lock the device pointers */
+	mutex_lock(&(dev->dev_mutex));
+
+	pci_set_power_state(pci, PCI_D0);
+	pci_restore_state(pci);
+	if (pci_enable_device(pci) < 0) {
+		printk(KERN_ERR "%s: pci_enable_device failed, "
+		       "disabling device\n", CR_DRIVER_NAME);
+		/* unlock the device pointers */
+		mutex_unlock(&dev->dev_mutex);
+		return -EIO;
+	}
+	pci_set_master(pci);
+
+	if (chip->msi_en) {
+		if (pci_enable_msi(pci) < 0)
+			chip->msi_en = 0;
+	}
+
+	if (rtsx_acquire_irq(dev) < 0) {
+		/* unlock the device pointers */
+		mutex_unlock(&dev->dev_mutex);
+		return -EIO;
+	}
+
+	rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
+	rtsx_init_chip(chip);
+
+	/* unlock the device pointers */
+	mutex_unlock(&dev->dev_mutex);
+
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static void rtsx_shutdown(struct pci_dev *pci)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
+	struct rtsx_chip *chip;
+
+	printk(KERN_INFO "Ready to shutdown\n");
+
+	if (!dev) {
+		printk(KERN_ERR "Invalid memory\n");
+		return;
+	}
+
+	chip = dev->chip;
+
+	rtsx_do_before_power_down(chip, PM_S1);
+
+	if (dev->irq >= 0) {
+		synchronize_irq(dev->irq);
+		free_irq(dev->irq, (void *)dev);
+		dev->irq = -1;
+	}
+
+	if (chip->msi_en)
+		pci_disable_msi(pci);
+
+	pci_disable_device(pci);
+
+	return;
+}
+
+static int rtsx_control_thread(void *__dev)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
+	struct rtsx_chip *chip = dev->chip;
+	struct Scsi_Host *host = rtsx_to_host(dev);
+
+	current->flags |= PF_NOFREEZE;
+
+	for (;;) {
+		if (down_interruptible(&dev->sema))
+			break;
+
+		/* lock the device pointers */
+		mutex_lock(&(dev->dev_mutex));
+
+		/* if the device has disconnected, we are free to exit */
+		if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
+			printk(KERN_INFO "-- rtsx-control exiting\n");
+			mutex_unlock(&dev->dev_mutex);
+			break;
+		}
+
+		/* lock access to the state */
+		scsi_lock(host);
+
+		/* has the command aborted ? */
+		if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
+			chip->srb->result = DID_ABORT << 16;
+			goto SkipForAbort;
+		}
+
+		scsi_unlock(host);
+
+		/* reject the command if the direction indicator
+		 * is UNKNOWN
+		 */
+		if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
+			printk(KERN_ERR "UNKNOWN data direction\n");
+			chip->srb->result = DID_ERROR << 16;
+		}
+
+		/* reject if target != 0 or if LUN is higher than
+		 * the maximum known LUN
+		 */
+		else if (chip->srb->device->id) {
+			printk(KERN_ERR "Bad target number (%d:%d)\n",
+				  chip->srb->device->id, chip->srb->device->lun);
+			chip->srb->result = DID_BAD_TARGET << 16;
+		}
+
+		else if (chip->srb->device->lun > chip->max_lun) {
+			printk(KERN_ERR "Bad LUN (%d:%d)\n",
+				  chip->srb->device->id, chip->srb->device->lun);
+			chip->srb->result = DID_BAD_TARGET << 16;
+		}
+
+		/* we've got a command, let's do it! */
+		else {
+			RTSX_DEBUG(scsi_show_command(chip->srb));
+			rtsx_invoke_transport(chip->srb, chip);
+		}
+
+		/* lock access to the state */
+		scsi_lock(host);
+
+		/* did the command already complete because of a disconnect? */
+		if (!chip->srb)
+			;		/* nothing to do */
+
+		/* indicate that the command is done */
+		else if (chip->srb->result != DID_ABORT << 16) {
+			chip->srb->scsi_done(chip->srb);
+		} else {
+SkipForAbort:
+			printk(KERN_ERR "scsi command aborted\n");
+		}
+
+		if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
+			complete(&(dev->notify));
+
+			rtsx_set_stat(chip, RTSX_STAT_IDLE);
+		}
+
+		/* finished working on this command */
+		chip->srb = NULL;
+		scsi_unlock(host);
+
+		/* unlock the device pointers */
+		mutex_unlock(&dev->dev_mutex);
+	} /* for (;;) */
+
+	scsi_host_put(host);
+
+	/* notify the exit routine that we're actually exiting now
+	 *
+	 * complete()/wait_for_completion() is similar to up()/down(),
+	 * except that complete() is safe in the case where the structure
+	 * is getting deleted in a parallel mode of execution (i.e. just
+	 * after the down() -- that's necessary for the thread-shutdown
+	 * case.
+	 *
+	 * complete_and_exit() goes even further than this -- it is safe in
+	 * the case that the thread of the caller is going away (not just
+	 * the structure) -- this is necessary for the module-remove case.
+	 * This is important in preemption kernels, which transfer the flow
+	 * of execution immediately upon a complete().
+	 */
+	complete_and_exit(&threads_gone, 0);
+}
+
+
+static int rtsx_polling_thread(void *__dev)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
+	struct rtsx_chip *chip = dev->chip;
+	struct Scsi_Host *host = rtsx_to_host(dev);
+	struct sd_info *sd_card = &(chip->sd_card);
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct ms_info *ms_card = &(chip->ms_card);
+
+	sd_card->cleanup_counter = 0;
+	xd_card->cleanup_counter = 0;
+	ms_card->cleanup_counter = 0;
+
+	/* Wait until SCSI scan finished */
+	wait_timeout((delay_use + 5) * 1000);
+
+	for (;;) {
+		wait_timeout(POLLING_INTERVAL);
+
+		/* lock the device pointers */
+		mutex_lock(&(dev->dev_mutex));
+
+		/* if the device has disconnected, we are free to exit */
+		if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
+			printk(KERN_INFO "-- rtsx-polling exiting\n");
+			mutex_unlock(&dev->dev_mutex);
+			break;
+		}
+
+		mutex_unlock(&dev->dev_mutex);
+
+		mspro_polling_format_status(chip);
+
+		/* lock the device pointers */
+		mutex_lock(&(dev->dev_mutex));
+
+		rtsx_polling_func(chip);
+
+		/* unlock the device pointers */
+		mutex_unlock(&dev->dev_mutex);
+	}
+
+	scsi_host_put(host);
+	complete_and_exit(&threads_gone, 0);
+}
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t rtsx_interrupt(int irq, void *dev_id)
+{
+	struct rtsx_dev *dev = dev_id;
+	struct rtsx_chip *chip;
+	int retval;
+	u32 status;
+
+	if (dev) {
+		chip = dev->chip;
+	} else {
+		return IRQ_NONE;
+	}
+
+	if (!chip) {
+		return IRQ_NONE;
+	}
+
+	spin_lock(&dev->reg_lock);
+
+	retval = rtsx_pre_handle_interrupt(chip);
+	if (retval == STATUS_FAIL) {
+		spin_unlock(&dev->reg_lock);
+		if (chip->int_reg == 0xFFFFFFFF) {
+			return IRQ_HANDLED;
+		} else {
+			return IRQ_NONE;
+		}
+	}
+
+	status = chip->int_reg;
+
+	if (dev->check_card_cd) {
+		if (!(dev->check_card_cd & status)) {
+			/* card not exist, return TRANS_RESULT_FAIL */
+			dev->trans_result = TRANS_RESULT_FAIL;
+			if (dev->done)
+				complete(dev->done);
+			goto Exit;
+		}
+	}
+
+	if (status & (NEED_COMPLETE_INT | DELINK_INT)) {
+		if (status & (TRANS_FAIL_INT | DELINK_INT)) {
+			if (status & DELINK_INT) {
+				RTSX_SET_DELINK(chip);
+			}
+			dev->trans_result = TRANS_RESULT_FAIL;
+			if (dev->done)
+				complete(dev->done);
+		} else if (status & TRANS_OK_INT) {
+			dev->trans_result = TRANS_RESULT_OK;
+			if (dev->done)
+				complete(dev->done);
+		} else if (status & DATA_DONE_INT) {
+			dev->trans_result = TRANS_NOT_READY;
+			if (dev->done && (dev->trans_state == STATE_TRANS_SG))
+				complete(dev->done);
+		}
+	}
+
+Exit:
+	spin_unlock(&dev->reg_lock);
+	return IRQ_HANDLED;
+}
+
+
+/* Release all our dynamic resources */
+static void rtsx_release_resources(struct rtsx_dev *dev)
+{
+	printk(KERN_INFO "-- %s\n", __func__);
+
+	if (dev->rtsx_resv_buf) {
+		dma_free_coherent(&(dev->pci->dev), HOST_CMDS_BUF_LEN,
+				dev->rtsx_resv_buf, dev->rtsx_resv_buf_addr);
+		dev->chip->host_cmds_ptr = NULL;
+		dev->chip->host_sg_tbl_ptr = NULL;
+	}
+
+	pci_disable_device(dev->pci);
+	pci_release_regions(dev->pci);
+
+	if (dev->irq > 0) {
+		free_irq(dev->irq, (void *)dev);
+	}
+	if (dev->chip->msi_en) {
+		pci_disable_msi(dev->pci);
+	}
+
+	/* Tell the control thread to exit.  The SCSI host must
+	 * already have been removed so it won't try to queue
+	 * any more commands.
+	 */
+	printk(KERN_INFO "-- sending exit command to thread\n");
+	up(&dev->sema);
+}
+
+/* First stage of disconnect processing: stop all commands and remove
+ * the host */
+static void quiesce_and_remove_host(struct rtsx_dev *dev)
+{
+	struct Scsi_Host *host = rtsx_to_host(dev);
+	struct rtsx_chip *chip = dev->chip;
+
+	/* Prevent new transfers, stop the current command, and
+	 * interrupt a SCSI-scan or device-reset delay */
+	mutex_lock(&dev->dev_mutex);
+	scsi_lock(host);
+	rtsx_set_stat(chip, RTSX_STAT_DISCONNECT);
+	scsi_unlock(host);
+	mutex_unlock(&dev->dev_mutex);
+	wake_up(&dev->delay_wait);
+
+	/* Wait some time to let other threads exist */
+	wait_timeout(100);
+
+	/* queuecommand won't accept any new commands and the control
+	 * thread won't execute a previously-queued command.  If there
+	 * is such a command pending, complete it with an error. */
+	mutex_lock(&dev->dev_mutex);
+	if (chip->srb) {
+		chip->srb->result = DID_NO_CONNECT << 16;
+		scsi_lock(host);
+		chip->srb->scsi_done(dev->chip->srb);
+		chip->srb = NULL;
+		scsi_unlock(host);
+	}
+	mutex_unlock(&dev->dev_mutex);
+
+	/* Now we own no commands so it's safe to remove the SCSI host */
+	scsi_remove_host(host);
+}
+
+/* Second stage of disconnect processing: deallocate all resources */
+static void release_everything(struct rtsx_dev *dev)
+{
+	rtsx_release_resources(dev);
+
+	/* Drop our reference to the host; the SCSI core will free it
+	 * when the refcount becomes 0. */
+	scsi_host_put(rtsx_to_host(dev));
+}
+
+/* Thread to carry out delayed SCSI-device scanning */
+static int rtsx_scan_thread(void *__dev)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)__dev;
+	struct rtsx_chip *chip = dev->chip;
+
+	/* Wait for the timeout to expire or for a disconnect */
+	if (delay_use > 0) {
+		printk(KERN_INFO "%s: waiting for device "
+				"to settle before scanning\n", CR_DRIVER_NAME);
+		wait_event_interruptible_timeout(dev->delay_wait,
+				rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT),
+				delay_use * HZ);
+	}
+
+	/* If the device is still connected, perform the scanning */
+	if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
+		scsi_scan_host(rtsx_to_host(dev));
+		printk(KERN_INFO "%s: device scan complete\n", CR_DRIVER_NAME);
+
+		/* Should we unbind if no devices were detected? */
+	}
+
+	scsi_host_put(rtsx_to_host(dev));
+	complete_and_exit(&threads_gone, 0);
+}
+
+static void rtsx_init_options(struct rtsx_chip *chip)
+{
+	chip->vendor_id = chip->rtsx->pci->vendor;
+	chip->product_id = chip->rtsx->pci->device;
+	chip->adma_mode = 1;
+	chip->lun_mc = 0;
+	chip->driver_first_load = 1;
+#ifdef HW_AUTO_SWITCH_SD_BUS
+	chip->sdio_in_charge = 0;
+#endif
+
+	chip->mspro_formatter_enable = 1;
+	chip->ignore_sd = 0;
+	chip->use_hw_setting = 0;
+	chip->lun_mode = DEFAULT_SINGLE;
+	chip->auto_delink_en = auto_delink_en;
+	chip->ss_en = ss_en;
+	chip->ss_idle_period = ss_interval * 1000;
+	chip->remote_wakeup_en = 0;
+	chip->aspm_l0s_l1_en = aspm_l0s_l1_en;
+	chip->dynamic_aspm = 1;
+	chip->fpga_sd_sdr104_clk = CLK_200;
+	chip->fpga_sd_ddr50_clk = CLK_100;
+	chip->fpga_sd_sdr50_clk = CLK_100;
+	chip->fpga_sd_hs_clk = CLK_100;
+	chip->fpga_mmc_52m_clk = CLK_80;
+	chip->fpga_ms_hg_clk = CLK_80;
+	chip->fpga_ms_4bit_clk = CLK_80;
+	chip->fpga_ms_1bit_clk = CLK_40;
+	chip->asic_sd_sdr104_clk = 207;
+	chip->asic_sd_sdr50_clk = 99;
+	chip->asic_sd_ddr50_clk = 99;
+	chip->asic_sd_hs_clk = 99;
+	chip->asic_mmc_52m_clk = 99;
+	chip->asic_ms_hg_clk = 119;
+	chip->asic_ms_4bit_clk = 79;
+	chip->asic_ms_1bit_clk = 39;
+	chip->ssc_depth_sd_sdr104 = SSC_DEPTH_2M;
+	chip->ssc_depth_sd_sdr50 = SSC_DEPTH_2M;
+	chip->ssc_depth_sd_ddr50 = SSC_DEPTH_1M;
+	chip->ssc_depth_sd_hs = SSC_DEPTH_1M;
+	chip->ssc_depth_mmc_52m = SSC_DEPTH_1M;
+	chip->ssc_depth_ms_hg = SSC_DEPTH_1M;
+	chip->ssc_depth_ms_4bit = SSC_DEPTH_512K;
+	chip->ssc_depth_low_speed = SSC_DEPTH_512K;
+	chip->ssc_en = 1;
+	chip->sd_speed_prior = 0x01040203;
+	chip->sd_current_prior = 0x00010203;
+	chip->sd_ctl = SD_PUSH_POINT_AUTO | SD_SAMPLE_POINT_AUTO | SUPPORT_MMC_DDR_MODE;
+	chip->sd_ddr_tx_phase = 0;
+	chip->mmc_ddr_tx_phase = 1;
+	chip->sd_default_tx_phase = 15;
+	chip->sd_default_rx_phase = 15;
+	chip->pmos_pwr_on_interval = 200;
+	chip->sd_voltage_switch_delay = 1000;
+	chip->ms_power_class_en = 3;
+
+	chip->sd_400mA_ocp_thd = 1;
+	chip->sd_800mA_ocp_thd = 5;
+	chip->ms_ocp_thd = 2;
+
+	chip->card_drive_sel = 0x55;
+	chip->sd30_drive_sel_1v8 = 0x03;
+	chip->sd30_drive_sel_3v3 = 0x01;
+
+	chip->do_delink_before_power_down = 1;
+	chip->auto_power_down = 1;
+	chip->polling_config = 0;
+
+	chip->force_clkreq_0 = 1;
+	chip->ft2_fast_mode = 0;
+
+	chip->sdio_retry_cnt = 1;
+
+	chip->xd_timeout = 2000;
+	chip->sd_timeout = 10000;
+	chip->ms_timeout = 2000;
+	chip->mspro_timeout = 15000;
+
+	chip->power_down_in_ss = 1;
+
+	chip->sdr104_en = 1;
+	chip->sdr50_en = 1;
+	chip->ddr50_en = 1;
+
+	chip->delink_stage1_step = 100;
+	chip->delink_stage2_step = 40;
+	chip->delink_stage3_step = 20;
+
+	chip->auto_delink_in_L1 = 1;
+	chip->blink_led = 1;
+	chip->msi_en = msi_en;
+	chip->hp_watch_bios_hotplug = 0;
+	chip->max_payload = 0;
+	chip->phy_voltage = 0;
+
+	chip->support_ms_8bit = 1;
+	chip->s3_pwr_off_delay = 1000;
+}
+
+static int __devinit rtsx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+	struct Scsi_Host *host;
+	struct rtsx_dev *dev;
+	int err = 0;
+	struct task_struct *th;
+
+	RTSX_DEBUGP("Realtek PCI-E card reader detected\n");
+
+	err = pci_enable_device(pci);
+	if (err < 0) {
+		printk(KERN_ERR "PCI enable device failed!\n");
+		return err;
+	}
+
+	err = pci_request_regions(pci, CR_DRIVER_NAME);
+	if (err < 0) {
+		printk(KERN_ERR "PCI request regions for %s failed!\n", CR_DRIVER_NAME);
+		pci_disable_device(pci);
+		return err;
+	}
+
+	/*
+	 * Ask the SCSI layer to allocate a host structure, with extra
+	 * space at the end for our private rtsx_dev structure.
+	 */
+	host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev));
+	if (!host) {
+		printk(KERN_ERR "Unable to allocate the scsi host\n");
+		pci_release_regions(pci);
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+
+	dev = host_to_rtsx(host);
+	memset(dev, 0, sizeof(struct rtsx_dev));
+
+	dev->chip = kzalloc(sizeof(struct rtsx_chip), GFP_KERNEL);
+	if (dev->chip == NULL) {
+		goto errout;
+	}
+
+	spin_lock_init(&dev->reg_lock);
+	mutex_init(&(dev->dev_mutex));
+	sema_init(&(dev->sema), 0);
+	init_completion(&(dev->notify));
+	init_waitqueue_head(&dev->delay_wait);
+
+	dev->pci = pci;
+	dev->irq = -1;
+
+	printk(KERN_INFO "Resource length: 0x%x\n", (unsigned int)pci_resource_len(pci, 0));
+	dev->addr = pci_resource_start(pci, 0);
+	dev->remap_addr = ioremap_nocache(dev->addr, pci_resource_len(pci, 0));
+	if (dev->remap_addr == NULL) {
+		printk(KERN_ERR "ioremap error\n");
+		err = -ENXIO;
+		goto errout;
+	}
+
+	/* Using "unsigned long" cast here to eliminate gcc warning in 64-bit system */
+	printk(KERN_INFO "Original address: 0x%lx, remapped address: 0x%lx\n",
+			(unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
+
+	dev->rtsx_resv_buf = dma_alloc_coherent(&(pci->dev), RTSX_RESV_BUF_LEN,
+			&(dev->rtsx_resv_buf_addr), GFP_KERNEL);
+	if (dev->rtsx_resv_buf == NULL) {
+		printk(KERN_ERR "alloc dma buffer fail\n");
+		err = -ENXIO;
+		goto errout;
+	}
+	dev->chip->host_cmds_ptr = dev->rtsx_resv_buf;
+	dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr;
+	dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
+	dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
+
+	dev->chip->rtsx = dev;
+
+	rtsx_init_options(dev->chip);
+
+	printk(KERN_INFO "pci->irq = %d\n", pci->irq);
+
+	if (dev->chip->msi_en) {
+		if (pci_enable_msi(pci) < 0)
+			dev->chip->msi_en = 0;
+	}
+
+	if (rtsx_acquire_irq(dev) < 0) {
+		err = -EBUSY;
+		goto errout;
+	}
+
+	pci_set_master(pci);
+	synchronize_irq(dev->irq);
+
+	err = scsi_add_host(host, &pci->dev);
+	if (err) {
+		printk(KERN_ERR "Unable to add the scsi host\n");
+		goto errout;
+	}
+
+	rtsx_init_chip(dev->chip);
+
+	/* Start up our control thread */
+	th = kthread_create(rtsx_control_thread, dev, CR_DRIVER_NAME);
+	if (IS_ERR(th)) {
+		printk(KERN_ERR "Unable to start control thread\n");
+		err = PTR_ERR(th);
+		goto errout;
+	}
+
+	/* Take a reference to the host for the control thread and
+	 * count it among all the threads we have launched.  Then
+	 * start it up. */
+	scsi_host_get(rtsx_to_host(dev));
+	atomic_inc(&total_threads);
+	wake_up_process(th);
+
+	/* Start up the thread for delayed SCSI-device scanning */
+	th = kthread_create(rtsx_scan_thread, dev, "rtsx-scan");
+	if (IS_ERR(th)) {
+		printk(KERN_ERR "Unable to start the device-scanning thread\n");
+		quiesce_and_remove_host(dev);
+		err = PTR_ERR(th);
+		goto errout;
+	}
+
+	/* Take a reference to the host for the scanning thread and
+	 * count it among all the threads we have launched.  Then
+	 * start it up. */
+	scsi_host_get(rtsx_to_host(dev));
+	atomic_inc(&total_threads);
+	wake_up_process(th);
+
+	/* Start up the thread for polling thread */
+	th = kthread_create(rtsx_polling_thread, dev, "rtsx-polling");
+	if (IS_ERR(th)) {
+		printk(KERN_ERR "Unable to start the device-polling thread\n");
+		quiesce_and_remove_host(dev);
+		err = PTR_ERR(th);
+		goto errout;
+	}
+
+	/* Take a reference to the host for the polling thread and
+	 * count it among all the threads we have launched.  Then
+	 * start it up. */
+	scsi_host_get(rtsx_to_host(dev));
+	atomic_inc(&total_threads);
+	wake_up_process(th);
+
+	pci_set_drvdata(pci, dev);
+
+	return 0;
+
+	/* We come here if there are any problems */
+errout:
+	printk(KERN_ERR "rtsx_probe() failed\n");
+	release_everything(dev);
+
+	return err;
+}
+
+
+static void __devexit rtsx_remove(struct pci_dev *pci)
+{
+	struct rtsx_dev *dev = (struct rtsx_dev *)pci_get_drvdata(pci);
+
+	printk(KERN_INFO "rtsx_remove() called\n");
+
+	quiesce_and_remove_host(dev);
+	release_everything(dev);
+
+	pci_set_drvdata(pci, NULL);
+}
+
+/* PCI IDs */
+static struct pci_device_id rtsx_ids[] = {
+	{ 0x10EC, 0x5208, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_OTHERS << 16, 0xFF0000 },
+	{ 0x10EC, 0x5209, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_OTHERS << 16, 0xFF0000 },
+	{ 0x10EC, 0x5288, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_OTHERS << 16, 0xFF0000 },
+	{ 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, rtsx_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+	.name = CR_DRIVER_NAME,
+	.id_table = rtsx_ids,
+	.probe = rtsx_probe,
+	.remove = __devexit_p(rtsx_remove),
+#ifdef CONFIG_PM
+	.suspend = rtsx_suspend,
+	.resume = rtsx_resume,
+#endif
+	.shutdown = rtsx_shutdown,
+};
+
+static int __init rtsx_init(void)
+{
+	printk(KERN_INFO "Initializing Realtek PCIE storage driver...\n");
+
+	return pci_register_driver(&driver);
+}
+
+static void __exit rtsx_exit(void)
+{
+	printk(KERN_INFO "rtsx_exit() called\n");
+
+	pci_unregister_driver(&driver);
+
+	/* Don't return until all of our control and scanning threads
+	 * have exited.  Since each thread signals threads_gone as its
+	 * last act, we have to call wait_for_completion the right number
+	 * of times.
+	 */
+	while (atomic_read(&total_threads) > 0) {
+		wait_for_completion(&threads_gone);
+		atomic_dec(&total_threads);
+	}
+
+	printk(KERN_INFO "%s module exit\n", CR_DRIVER_NAME);
+}
+
+module_init(rtsx_init)
+module_exit(rtsx_exit)
+
diff --git a/drivers/staging/rts_pstor/rtsx.h b/drivers/staging/rts_pstor/rtsx.h
new file mode 100644
index 0000000..4d5ddf6
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx.h
@@ -0,0 +1,183 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_H
+#define __REALTEK_RTSX_H
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/mutex.h>
+#include <linux/cdrom.h>
+#include <linux/workqueue.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+#include "debug.h"
+#include "trace.h"
+#include "general.h"
+
+#define CR_DRIVER_NAME		"rts_pstor"
+
+#define pci_get_bus_and_slot(bus, devfn)	\
+	pci_get_domain_bus_and_slot(0, (bus), (devfn))
+
+/*
+ * macros for easy use
+ */
+#define rtsx_writel(chip, reg, value) \
+	iowrite32(value, (chip)->rtsx->remap_addr + reg)
+#define rtsx_readl(chip, reg) \
+	ioread32((chip)->rtsx->remap_addr + reg)
+#define rtsx_writew(chip, reg, value) \
+	iowrite16(value, (chip)->rtsx->remap_addr + reg)
+#define rtsx_readw(chip, reg) \
+	ioread16((chip)->rtsx->remap_addr + reg)
+#define rtsx_writeb(chip, reg, value) \
+	iowrite8(value, (chip)->rtsx->remap_addr + reg)
+#define rtsx_readb(chip, reg) \
+	ioread8((chip)->rtsx->remap_addr + reg)
+
+#define rtsx_read_config_byte(chip, where, val) \
+	pci_read_config_byte((chip)->rtsx->pci, where, val)
+
+#define rtsx_write_config_byte(chip, where, val) \
+	pci_write_config_byte((chip)->rtsx->pci, where, val)
+
+#define wait_timeout_x(task_state, msecs)		\
+do {							\
+		set_current_state((task_state)); 	\
+		schedule_timeout((msecs) * HZ / 1000);	\
+} while (0)
+#define wait_timeout(msecs)	wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
+
+
+#define STATE_TRANS_NONE	0
+#define STATE_TRANS_CMD		1
+#define STATE_TRANS_BUF		2
+#define STATE_TRANS_SG		3
+
+#define TRANS_NOT_READY		0
+#define TRANS_RESULT_OK		1
+#define TRANS_RESULT_FAIL	2
+
+#define SCSI_LUN(srb)		((srb)->device->lun)
+
+#define rtsx_alloc_dma_buf(chip, size, flag)	kmalloc((size), (flag))
+#define rtsx_free_dma_buf(chip, ptr)		kfree((ptr))
+
+typedef unsigned long DELAY_PARA_T;
+
+struct rtsx_chip;
+
+struct rtsx_dev {
+	struct pci_dev 		*pci;
+
+	/* pci resources */
+	unsigned long 		addr;
+	void __iomem 		*remap_addr;
+	int 			irq;
+
+	/* locks */
+	spinlock_t 		reg_lock;
+
+	/* mutual exclusion and synchronization structures */
+	struct semaphore	sema;		 /* to sleep thread on	    */
+	struct completion	notify;		 /* thread begin/end	    */
+	wait_queue_head_t	delay_wait;	 /* wait during scan, reset */
+	struct mutex		dev_mutex;
+
+	/* host reserved buffer */
+	void 			*rtsx_resv_buf;
+	dma_addr_t 		rtsx_resv_buf_addr;
+
+	char			trans_result;
+	char			trans_state;
+
+	struct completion 	*done;
+	/* Whether interrupt handler should care card cd info */
+	u32 			check_card_cd;
+
+	struct rtsx_chip 	*chip;
+};
+
+typedef struct rtsx_dev rtsx_dev_t;
+
+/* Convert between rtsx_dev and the corresponding Scsi_Host */
+static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev)
+{
+	return container_of((void *) dev, struct Scsi_Host, hostdata);
+}
+static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host)
+{
+	return (struct rtsx_dev *) host->hostdata;
+}
+
+static inline void get_current_time(u8 *timeval_buf, int buf_len)
+{
+	struct timeval tv;
+
+	if (!timeval_buf || (buf_len < 8))
+		return;
+
+	do_gettimeofday(&tv);
+
+	timeval_buf[0] = (u8)(tv.tv_sec >> 24);
+	timeval_buf[1] = (u8)(tv.tv_sec >> 16);
+	timeval_buf[2] = (u8)(tv.tv_sec >> 8);
+	timeval_buf[3] = (u8)(tv.tv_sec);
+	timeval_buf[4] = (u8)(tv.tv_usec >> 24);
+	timeval_buf[5] = (u8)(tv.tv_usec >> 16);
+	timeval_buf[6] = (u8)(tv.tv_usec >> 8);
+	timeval_buf[7] = (u8)(tv.tv_usec);
+}
+
+/* The scsi_lock() and scsi_unlock() macros protect the sm_state and the
+ * single queue element srb for write access */
+#define scsi_unlock(host)	spin_unlock_irq(host->host_lock)
+#define scsi_lock(host)		spin_lock_irq(host->host_lock)
+
+#define lock_state(chip)	spin_lock_irq(&((chip)->rtsx->reg_lock))
+#define unlock_state(chip)	spin_unlock_irq(&((chip)->rtsx->reg_lock))
+
+/* struct scsi_cmnd transfer buffer access utilities */
+enum xfer_buf_dir	{TO_XFER_BUF, FROM_XFER_BUF};
+
+int rtsx_read_pci_cfg_byte(u8 bus, u8 dev, u8 func, u8 offset, u8 *val);
+
+#endif  /* __REALTEK_RTSX_H */
diff --git a/drivers/staging/rts_pstor/rtsx_card.c b/drivers/staging/rts_pstor/rtsx_card.c
new file mode 100644
index 0000000..4f971f2
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_card.c
@@ -0,0 +1,1257 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+
+#include "rtsx_sys.h"
+#include "general.h"
+
+#include "sd.h"
+#include "xd.h"
+#include "ms.h"
+
+void do_remaining_work(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+#ifdef XD_DELAY_WRITE
+	struct xd_info *xd_card = &(chip->xd_card);
+#endif
+	struct ms_info *ms_card = &(chip->ms_card);
+
+	if (chip->card_ready & SD_CARD) {
+		if (sd_card->seq_mode) {
+			rtsx_set_stat(chip, RTSX_STAT_RUN);
+			sd_card->cleanup_counter++;
+		} else {
+			sd_card->cleanup_counter = 0;
+		}
+	}
+
+#ifdef XD_DELAY_WRITE
+	if (chip->card_ready & XD_CARD) {
+		if (xd_card->delay_write.delay_write_flag) {
+			rtsx_set_stat(chip, RTSX_STAT_RUN);
+			xd_card->cleanup_counter++;
+		} else {
+			xd_card->cleanup_counter = 0;
+		}
+	}
+#endif
+
+	if (chip->card_ready & MS_CARD) {
+		if (CHK_MSPRO(ms_card)) {
+			if (ms_card->seq_mode) {
+				rtsx_set_stat(chip, RTSX_STAT_RUN);
+				ms_card->cleanup_counter++;
+			} else {
+				ms_card->cleanup_counter = 0;
+			}
+		} else {
+#ifdef MS_DELAY_WRITE
+			if (ms_card->delay_write.delay_write_flag) {
+				rtsx_set_stat(chip, RTSX_STAT_RUN);
+				ms_card->cleanup_counter++;
+			} else {
+				ms_card->cleanup_counter = 0;
+			}
+#endif
+		}
+	}
+
+	if (sd_card->cleanup_counter > POLLING_WAIT_CNT)
+		sd_cleanup_work(chip);
+
+	if (xd_card->cleanup_counter > POLLING_WAIT_CNT)
+		xd_cleanup_work(chip);
+
+	if (ms_card->cleanup_counter > POLLING_WAIT_CNT)
+		ms_cleanup_work(chip);
+}
+
+void try_to_switch_sdio_ctrl(struct rtsx_chip *chip)
+{
+	u8 reg1 = 0, reg2 = 0;
+
+	rtsx_read_register(chip, 0xFF34, &reg1);
+	rtsx_read_register(chip, 0xFF38, &reg2);
+	RTSX_DEBUGP("reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n", reg1, reg2);
+	if ((reg1 & 0xC0) && (reg2 & 0xC0)) {
+		chip->sd_int = 1;
+		rtsx_write_register(chip, SDIO_CTRL, 0xFF, SDIO_BUS_CTRL | SDIO_CD_CTRL);
+		rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
+	}
+}
+
+#ifdef SUPPORT_SDIO_ASPM
+void dynamic_configure_sdio_aspm(struct rtsx_chip *chip)
+{
+	u8 buf[12], reg;
+	int i;
+
+	for (i = 0; i < 12; i++)
+		rtsx_read_register(chip, 0xFF08 + i, &buf[i]);
+	rtsx_read_register(chip, 0xFF25, &reg);
+	if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) {
+		chip->sdio_counter = 0;
+		chip->sdio_idle = 0;
+	} else {
+		if (!chip->sdio_idle) {
+			chip->sdio_counter++;
+			if (chip->sdio_counter >= SDIO_IDLE_COUNT) {
+				chip->sdio_counter = 0;
+				chip->sdio_idle = 1;
+			}
+		}
+	}
+	memcpy(chip->sdio_raw_data, buf, 12);
+
+	if (chip->sdio_idle) {
+		if (!chip->sdio_aspm) {
+			RTSX_DEBUGP("SDIO enter ASPM!\n");
+			rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC,
+					0x30 | (chip->aspm_level[1] << 2));
+			chip->sdio_aspm = 1;
+		}
+	} else {
+		if (chip->sdio_aspm) {
+			RTSX_DEBUGP("SDIO exit ASPM!\n");
+			rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30);
+			chip->sdio_aspm = 0;
+		}
+	}
+}
+#endif
+
+void do_reset_sd_card(struct rtsx_chip *chip)
+{
+	int retval;
+
+	RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__,
+		     chip->sd_reset_counter, chip->card2lun[SD_CARD]);
+
+	if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) {
+		clear_bit(SD_NR, &(chip->need_reset));
+		chip->sd_reset_counter = 0;
+		chip->sd_show_cnt = 0;
+		return;
+	}
+
+	chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
+
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+	rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
+
+	retval = reset_sd_card(chip);
+	if (chip->need_release & SD_CARD)
+		return;
+	if (retval == STATUS_SUCCESS) {
+		clear_bit(SD_NR, &(chip->need_reset));
+		chip->sd_reset_counter = 0;
+		chip->sd_show_cnt = 0;
+		chip->card_ready |= SD_CARD;
+		chip->card_fail &= ~SD_CARD;
+		chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
+	} else {
+		if (chip->sd_io || (chip->sd_reset_counter >= MAX_RESET_CNT)) {
+			clear_bit(SD_NR, &(chip->need_reset));
+			chip->sd_reset_counter = 0;
+			chip->sd_show_cnt = 0;
+		} else {
+			chip->sd_reset_counter++;
+		}
+		chip->card_ready &= ~SD_CARD;
+		chip->card_fail |= SD_CARD;
+		chip->capacity[chip->card2lun[SD_CARD]] = 0;
+		chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
+
+		rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
+		if (!chip->ft2_fast_mode)
+			card_power_off(chip, SD_CARD);
+		if (chip->sd_io) {
+			chip->sd_int = 0;
+			try_to_switch_sdio_ctrl(chip);
+		} else {
+			disable_card_clock(chip, SD_CARD);
+		}
+	}
+}
+
+void do_reset_xd_card(struct rtsx_chip *chip)
+{
+	int retval;
+
+	RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__,
+		     chip->xd_reset_counter, chip->card2lun[XD_CARD]);
+
+	if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) {
+		clear_bit(XD_NR, &(chip->need_reset));
+		chip->xd_reset_counter = 0;
+		chip->xd_show_cnt = 0;
+		return;
+	}
+
+	chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
+
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+	rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
+
+	retval = reset_xd_card(chip);
+	if (chip->need_release & XD_CARD)
+		return;
+	if (retval == STATUS_SUCCESS) {
+		clear_bit(XD_NR, &(chip->need_reset));
+		chip->xd_reset_counter = 0;
+		chip->card_ready |= XD_CARD;
+		chip->card_fail &= ~XD_CARD;
+		chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
+	} else {
+		if (chip->xd_reset_counter >= MAX_RESET_CNT) {
+			clear_bit(XD_NR, &(chip->need_reset));
+			chip->xd_reset_counter = 0;
+			chip->xd_show_cnt = 0;
+		} else {
+			chip->xd_reset_counter++;
+		}
+		chip->card_ready &= ~XD_CARD;
+		chip->card_fail |= XD_CARD;
+		chip->capacity[chip->card2lun[XD_CARD]] = 0;
+		chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
+
+		rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
+		if (!chip->ft2_fast_mode)
+			card_power_off(chip, XD_CARD);
+		disable_card_clock(chip, XD_CARD);
+	}
+}
+
+void do_reset_ms_card(struct rtsx_chip *chip)
+{
+	int retval;
+
+	RTSX_DEBUGP("%s: %d, card2lun = 0x%x\n", __func__,
+		     chip->ms_reset_counter, chip->card2lun[MS_CARD]);
+
+	if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) {
+		clear_bit(MS_NR, &(chip->need_reset));
+		chip->ms_reset_counter = 0;
+		chip->ms_show_cnt = 0;
+		return;
+	}
+
+	chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
+
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+	rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
+
+	retval = reset_ms_card(chip);
+	if (chip->need_release & MS_CARD)
+		return;
+	if (retval == STATUS_SUCCESS) {
+		clear_bit(MS_NR, &(chip->need_reset));
+		chip->ms_reset_counter = 0;
+		chip->card_ready |= MS_CARD;
+		chip->card_fail &= ~MS_CARD;
+		chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
+	} else {
+		if (chip->ms_reset_counter >= MAX_RESET_CNT) {
+			clear_bit(MS_NR, &(chip->need_reset));
+			chip->ms_reset_counter = 0;
+			chip->ms_show_cnt = 0;
+		} else {
+			chip->ms_reset_counter++;
+		}
+		chip->card_ready &= ~MS_CARD;
+		chip->card_fail |= MS_CARD;
+		chip->capacity[chip->card2lun[MS_CARD]] = 0;
+		chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
+
+		rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
+		if (!chip->ft2_fast_mode)
+			card_power_off(chip, MS_CARD);
+		disable_card_clock(chip, MS_CARD);
+	}
+}
+
+static void release_sdio(struct rtsx_chip *chip)
+{
+	if (chip->sd_io) {
+		rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
+				SD_STOP | SD_CLR_ERR);
+
+		if (chip->chip_insert_with_sdio) {
+			chip->chip_insert_with_sdio = 0;
+
+			if (CHECK_PID(chip, 0x5288)) {
+				rtsx_write_register(chip, 0xFE5A, 0x08, 0x00);
+			} else {
+				rtsx_write_register(chip, 0xFE70, 0x80, 0x00);
+			}
+		}
+
+		rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0);
+		chip->sd_io = 0;
+	}
+}
+
+void rtsx_power_off_card(struct rtsx_chip *chip)
+{
+	if ((chip->card_ready & SD_CARD) || chip->sd_io) {
+		sd_cleanup_work(chip);
+		sd_power_off_card3v3(chip);
+	}
+
+	if (chip->card_ready & XD_CARD) {
+		xd_cleanup_work(chip);
+		xd_power_off_card3v3(chip);
+	}
+
+	if (chip->card_ready & MS_CARD) {
+		ms_cleanup_work(chip);
+		ms_power_off_card3v3(chip);
+	}
+}
+
+void rtsx_release_cards(struct rtsx_chip *chip)
+{
+	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
+
+	if ((chip->card_ready & SD_CARD) || chip->sd_io) {
+		if (chip->int_reg & SD_EXIST)
+			sd_cleanup_work(chip);
+		release_sd_card(chip);
+	}
+
+	if (chip->card_ready & XD_CARD) {
+		if (chip->int_reg & XD_EXIST)
+			xd_cleanup_work(chip);
+		release_xd_card(chip);
+	}
+
+	if (chip->card_ready & MS_CARD) {
+		if (chip->int_reg & MS_EXIST)
+			ms_cleanup_work(chip);
+		release_ms_card(chip);
+	}
+}
+
+void rtsx_reset_cards(struct rtsx_chip *chip)
+{
+	if (!chip->need_reset)
+		return;
+
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
+
+	rtsx_disable_aspm(chip);
+
+	if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio)
+		clear_bit(SD_NR, &(chip->need_reset));
+
+	if (chip->need_reset & XD_CARD) {
+		chip->card_exist |= XD_CARD;
+
+		if (chip->xd_show_cnt >= MAX_SHOW_CNT) {
+			do_reset_xd_card(chip);
+		} else {
+			chip->xd_show_cnt++;
+		}
+	}
+	if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
+		if (chip->card_exist & XD_CARD) {
+			clear_bit(SD_NR, &(chip->need_reset));
+			clear_bit(MS_NR, &(chip->need_reset));
+		}
+	}
+	if (chip->need_reset & SD_CARD) {
+		chip->card_exist |= SD_CARD;
+
+		if (chip->sd_show_cnt >= MAX_SHOW_CNT) {
+			rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
+			do_reset_sd_card(chip);
+		} else {
+			chip->sd_show_cnt++;
+		}
+	}
+	if (chip->need_reset & MS_CARD) {
+		chip->card_exist |= MS_CARD;
+
+		if (chip->ms_show_cnt >= MAX_SHOW_CNT) {
+			do_reset_ms_card(chip);
+		} else {
+			chip->ms_show_cnt++;
+		}
+	}
+}
+
+void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip)
+{
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
+
+	if (reset_chip)
+		rtsx_reset_chip(chip);
+
+	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
+
+	if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) {
+		release_sdio(chip);
+		release_sd_card(chip);
+
+		wait_timeout(100);
+
+		chip->card_exist |= SD_CARD;
+		do_reset_sd_card(chip);
+	}
+
+	if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) {
+		release_xd_card(chip);
+
+		wait_timeout(100);
+
+		chip->card_exist |= XD_CARD;
+		do_reset_xd_card(chip);
+	}
+
+	if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) {
+		release_ms_card(chip);
+
+		wait_timeout(100);
+
+		chip->card_exist |= MS_CARD;
+		do_reset_ms_card(chip);
+	}
+
+	chip->need_reinit = 0;
+}
+
+#ifdef DISABLE_CARD_INT
+void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset, unsigned long *need_release)
+{
+	u8 release_map = 0, reset_map = 0;
+
+	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
+
+	if (chip->card_exist) {
+		if (chip->card_exist & XD_CARD) {
+			if (!(chip->int_reg & XD_EXIST))
+				release_map |= XD_CARD;
+		} else if (chip->card_exist & SD_CARD) {
+			if (!(chip->int_reg & SD_EXIST))
+				release_map |= SD_CARD;
+		} else if (chip->card_exist & MS_CARD) {
+			if (!(chip->int_reg & MS_EXIST))
+				release_map |= MS_CARD;
+		}
+	} else {
+		if (chip->int_reg & XD_EXIST) {
+			reset_map |= XD_CARD;
+		} else if (chip->int_reg & SD_EXIST) {
+			reset_map |= SD_CARD;
+		} else if (chip->int_reg & MS_EXIST) {
+			reset_map |= MS_CARD;
+		}
+	}
+
+	if (reset_map) {
+		int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0;
+		int i;
+
+		for (i = 0; i < (DEBOUNCE_CNT); i++) {
+			chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
+
+			if (chip->int_reg & XD_EXIST) {
+				xd_cnt++;
+			} else {
+				xd_cnt = 0;
+			}
+			if (chip->int_reg & SD_EXIST) {
+				sd_cnt++;
+			} else {
+				sd_cnt = 0;
+			}
+			if (chip->int_reg & MS_EXIST) {
+				ms_cnt++;
+			} else {
+				ms_cnt = 0;
+			}
+			wait_timeout(30);
+		}
+
+		reset_map = 0;
+		if (!(chip->card_exist & XD_CARD) && (xd_cnt > (DEBOUNCE_CNT-1)))
+			reset_map |= XD_CARD;
+		if (!(chip->card_exist & SD_CARD) && (sd_cnt > (DEBOUNCE_CNT-1)))
+			reset_map |= SD_CARD;
+		if (!(chip->card_exist & MS_CARD) && (ms_cnt > (DEBOUNCE_CNT-1)))
+			reset_map |= MS_CARD;
+	}
+
+	if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
+		rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00);
+
+	if (need_reset)
+		*need_reset = reset_map;
+	if (need_release)
+		*need_release = release_map;
+}
+#endif
+
+void rtsx_init_cards(struct rtsx_chip *chip)
+{
+	if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
+		RTSX_DEBUGP("Reset chip in polling thread!\n");
+		rtsx_reset_chip(chip);
+		RTSX_CLR_DELINK(chip);
+	}
+
+#ifdef DISABLE_CARD_INT
+	card_cd_debounce(chip, &(chip->need_reset), &(chip->need_release));
+#endif
+
+	if (chip->need_release) {
+		if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
+			if (chip->int_reg & XD_EXIST) {
+				clear_bit(SD_NR, &(chip->need_release));
+				clear_bit(MS_NR, &(chip->need_release));
+			}
+		}
+
+		if (!(chip->card_exist & SD_CARD) && !chip->sd_io)
+			clear_bit(SD_NR, &(chip->need_release));
+		if (!(chip->card_exist & XD_CARD))
+			clear_bit(XD_NR, &(chip->need_release));
+		if (!(chip->card_exist & MS_CARD))
+			clear_bit(MS_NR, &(chip->need_release));
+
+		RTSX_DEBUGP("chip->need_release = 0x%x\n", (unsigned int)(chip->need_release));
+
+#ifdef SUPPORT_OCP
+		if (chip->need_release) {
+			if (CHECK_PID(chip, 0x5209)) {
+				u8 mask = 0, val = 0;
+				if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+					if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) {
+						mask |= MS_OCP_INT_CLR | MS_OC_CLR;
+						val |= MS_OCP_INT_CLR | MS_OC_CLR;
+					}
+				}
+				if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+					mask |= SD_OCP_INT_CLR | SD_OC_CLR;
+					val |= SD_OCP_INT_CLR | SD_OC_CLR;
+				}
+				if (mask)
+					rtsx_write_register(chip, OCPCTL, mask, val);
+			} else {
+				if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER))
+					rtsx_write_register(chip, OCPCLR,
+							    CARD_OC_INT_CLR | CARD_OC_CLR,
+							    CARD_OC_INT_CLR | CARD_OC_CLR);
+			}
+			chip->ocp_stat = 0;
+		}
+#endif
+		if (chip->need_release) {
+			rtsx_set_stat(chip, RTSX_STAT_RUN);
+			rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
+		}
+
+		if (chip->need_release & SD_CARD) {
+			clear_bit(SD_NR, &(chip->need_release));
+			chip->card_exist &= ~SD_CARD;
+			chip->card_ejected &= ~SD_CARD;
+			chip->card_fail &= ~SD_CARD;
+			CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]);
+			chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
+			rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
+
+			release_sdio(chip);
+			release_sd_card(chip);
+		}
+
+		if (chip->need_release & XD_CARD) {
+			clear_bit(XD_NR, &(chip->need_release));
+			chip->card_exist &= ~XD_CARD;
+			chip->card_ejected &= ~XD_CARD;
+			chip->card_fail &= ~XD_CARD;
+			CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]);
+			chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
+
+			release_xd_card(chip);
+
+			if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
+				rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0xC0);
+		}
+
+		if (chip->need_release & MS_CARD) {
+			clear_bit(MS_NR, &(chip->need_release));
+			chip->card_exist &= ~MS_CARD;
+			chip->card_ejected &= ~MS_CARD;
+			chip->card_fail &= ~MS_CARD;
+			CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]);
+			chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
+
+			release_ms_card(chip);
+		}
+
+		RTSX_DEBUGP("chip->card_exist = 0x%x\n", chip->card_exist);
+
+		if (!chip->card_exist)
+			turn_off_led(chip, LED_GPIO);
+	}
+
+	if (chip->need_reset) {
+		RTSX_DEBUGP("chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset));
+
+		rtsx_reset_cards(chip);
+	}
+
+	if (chip->need_reinit) {
+		RTSX_DEBUGP("chip->need_reinit = 0x%x\n", (unsigned int)(chip->need_reinit));
+
+		rtsx_reinit_cards(chip, 0);
+	}
+}
+
+static inline u8 double_depth(u8 depth)
+{
+	return ((depth > 1) ? (depth - 1) : depth);
+}
+
+int switch_ssc_clock(struct rtsx_chip *chip, int clk)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	u8 N = (u8)(clk - 2), min_N, max_N;
+	u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask;
+	int sd_vpclk_phase_reset = 0;
+
+	if (chip->cur_clk == clk)
+		return STATUS_SUCCESS;
+
+	if (CHECK_PID(chip, 0x5209)) {
+		min_N = 80;
+		max_N = 208;
+		max_div = CLK_DIV_8;
+	} else {
+		min_N = 60;
+		max_N = 120;
+		max_div = CLK_DIV_4;
+	}
+
+	if (CHECK_PID(chip, 0x5209) && (chip->cur_card == SD_CARD)) {
+		struct sd_info *sd_card = &(chip->sd_card);
+		if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))
+			sd_vpclk_phase_reset = 1;
+	}
+
+	RTSX_DEBUGP("Switch SSC clock to %dMHz (cur_clk = %d)\n", clk, chip->cur_clk);
+
+	if ((clk <= 2) || (N > max_N)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	mcu_cnt = (u8)(125/clk + 3);
+	if (CHECK_PID(chip, 0x5209)) {
+		if (mcu_cnt > 15)
+			mcu_cnt = 15;
+	} else {
+		if (mcu_cnt > 7)
+			mcu_cnt = 7;
+	}
+
+	div = CLK_DIV_1;
+	while ((N < min_N) && (div < max_div)) {
+		N = (N + 2) * 2 - 2;
+		div++;
+	}
+	RTSX_DEBUGP("N = %d, div = %d\n", N, div);
+
+	if (chip->ssc_en) {
+		if (CHECK_PID(chip, 0x5209)) {
+			if (chip->cur_card == SD_CARD) {
+				if (CHK_SD_SDR104(sd_card)) {
+					ssc_depth = chip->ssc_depth_sd_sdr104;
+				} else if (CHK_SD_SDR50(sd_card)) {
+					ssc_depth = chip->ssc_depth_sd_sdr50;
+				} else if (CHK_SD_DDR50(sd_card)) {
+					ssc_depth = double_depth(chip->ssc_depth_sd_ddr50);
+				} else if (CHK_SD_HS(sd_card)) {
+					ssc_depth = double_depth(chip->ssc_depth_sd_hs);
+				} else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
+					ssc_depth = double_depth(chip->ssc_depth_mmc_52m);
+				} else {
+					ssc_depth = double_depth(chip->ssc_depth_low_speed);
+				}
+			} else if (chip->cur_card == MS_CARD) {
+				if (CHK_MSPRO(ms_card)) {
+					if (CHK_HG8BIT(ms_card)) {
+						ssc_depth = double_depth(chip->ssc_depth_ms_hg);
+					} else {
+						ssc_depth = double_depth(chip->ssc_depth_ms_4bit);
+					}
+				} else {
+					if (CHK_MS4BIT(ms_card)) {
+						ssc_depth = double_depth(chip->ssc_depth_ms_4bit);
+					} else {
+						ssc_depth = double_depth(chip->ssc_depth_low_speed);
+					}
+				}
+			} else {
+				ssc_depth = double_depth(chip->ssc_depth_low_speed);
+			}
+
+			if (ssc_depth) {
+				if (div == CLK_DIV_2) {
+					if (ssc_depth > 1) {
+						ssc_depth -= 1;
+					} else {
+						ssc_depth = SSC_DEPTH_4M;
+					}
+				} else if (div == CLK_DIV_4) {
+					if (ssc_depth > 2) {
+						ssc_depth -= 2;
+					} else {
+						ssc_depth = SSC_DEPTH_4M;
+					}
+				} else if (div == CLK_DIV_8) {
+					if (ssc_depth > 3) {
+						ssc_depth -= 3;
+					} else {
+						ssc_depth = SSC_DEPTH_4M;
+					}
+				}
+			}
+		} else {
+			ssc_depth = 0x01;
+			N -= 2;
+		}
+	} else {
+		ssc_depth = 0;
+	}
+
+	if (CHECK_PID(chip, 0x5209)) {
+		ssc_depth_mask = SSC_DEPTH_MASK;
+	} else {
+		ssc_depth_mask = 0x03;
+	}
+
+	RTSX_DEBUGP("ssc_depth = %d\n", ssc_depth);
+
+	rtsx_init_cmd(chip);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, N);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+	if (sd_vpclk_phase_reset) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
+	}
+
+	retval = rtsx_send_cmd(chip, 0, WAIT_TIME);
+	if (retval < 0) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	udelay(10);
+	RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
+
+	chip->cur_clk = clk;
+
+	return STATUS_SUCCESS;
+}
+
+int switch_normal_clock(struct rtsx_chip *chip, int clk)
+{
+	u8 sel, div, mcu_cnt;
+	int sd_vpclk_phase_reset = 0;
+
+	if (chip->cur_clk == clk)
+		return STATUS_SUCCESS;
+
+	if (CHECK_PID(chip, 0x5209) && (chip->cur_card == SD_CARD)) {
+		struct sd_info *sd_card = &(chip->sd_card);
+		if (CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))
+			sd_vpclk_phase_reset = 1;
+	}
+
+	switch (clk) {
+	case CLK_20:
+		RTSX_DEBUGP("Switch clock to 20MHz\n");
+		sel = SSC_80;
+		div = CLK_DIV_4;
+		mcu_cnt = 7;
+		break;
+
+	case CLK_30:
+		RTSX_DEBUGP("Switch clock to 30MHz\n");
+		sel = SSC_120;
+		div = CLK_DIV_4;
+		mcu_cnt = 7;
+		break;
+
+	case CLK_40:
+		RTSX_DEBUGP("Switch clock to 40MHz\n");
+		sel = SSC_80;
+		div = CLK_DIV_2;
+		mcu_cnt = 7;
+		break;
+
+	case CLK_50:
+		RTSX_DEBUGP("Switch clock to 50MHz\n");
+		sel = SSC_100;
+		div = CLK_DIV_2;
+		mcu_cnt = 6;
+		break;
+
+	case CLK_60:
+		RTSX_DEBUGP("Switch clock to 60MHz\n");
+		sel = SSC_120;
+		div = CLK_DIV_2;
+		mcu_cnt = 6;
+		break;
+
+	case CLK_80:
+		RTSX_DEBUGP("Switch clock to 80MHz\n");
+		sel = SSC_80;
+		div = CLK_DIV_1;
+		mcu_cnt = 5;
+		break;
+
+	case CLK_100:
+		RTSX_DEBUGP("Switch clock to 100MHz\n");
+		sel = SSC_100;
+		div = CLK_DIV_1;
+		mcu_cnt = 5;
+		break;
+
+	case CLK_120:
+		RTSX_DEBUGP("Switch clock to 120MHz\n");
+		sel = SSC_120;
+		div = CLK_DIV_1;
+		mcu_cnt = 5;
+		break;
+
+	case CLK_150:
+		RTSX_DEBUGP("Switch clock to 150MHz\n");
+		sel = SSC_150;
+		div = CLK_DIV_1;
+		mcu_cnt = 4;
+		break;
+
+	case CLK_200:
+		RTSX_DEBUGP("Switch clock to 200MHz\n");
+		sel = SSC_200;
+		div = CLK_DIV_1;
+		mcu_cnt = 4;
+		break;
+
+	default:
+		RTSX_DEBUGP("Try to switch to an illegal clock (%d)\n", clk);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
+	if (sd_vpclk_phase_reset) {
+		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+		RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, 0);
+	}
+	RTSX_WRITE_REG(chip, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
+	RTSX_WRITE_REG(chip, CLK_SEL, 0xFF, sel);
+
+	if (sd_vpclk_phase_reset) {
+		udelay(200);
+		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
+		RTSX_WRITE_REG(chip, SD_VPCLK1_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
+		udelay(200);
+	}
+	RTSX_WRITE_REG(chip, CLK_CTL, 0xFF, 0);
+
+	chip->cur_clk = clk;
+
+	return STATUS_SUCCESS;
+}
+
+void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size)
+{
+	if (pack_size > DMA_1024)
+		pack_size = DMA_512;
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt);
+
+	if (dir == DMA_FROM_DEVICE) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK,
+			     DMA_DIR_FROM_CARD | DMA_EN | pack_size);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK,
+			     DMA_DIR_TO_CARD | DMA_EN | pack_size);
+	}
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+}
+
+int enable_card_clock(struct rtsx_chip *chip, u8 card)
+{
+	u8 clk_en = 0;
+
+	if (card & XD_CARD)
+		clk_en |= XD_CLK_EN;
+	if (card & SD_CARD)
+		clk_en |= SD_CLK_EN;
+	if (card & MS_CARD)
+		clk_en |= MS_CLK_EN;
+
+	RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, clk_en);
+
+	return STATUS_SUCCESS;
+}
+
+int disable_card_clock(struct rtsx_chip *chip, u8 card)
+{
+	u8 clk_en = 0;
+
+	if (card & XD_CARD)
+		clk_en |= XD_CLK_EN;
+	if (card & SD_CARD)
+		clk_en |= SD_CLK_EN;
+	if (card & MS_CARD)
+		clk_en |= MS_CLK_EN;
+
+	RTSX_WRITE_REG(chip, CARD_CLK_EN, clk_en, 0);
+
+	return STATUS_SUCCESS;
+}
+
+int card_power_on(struct rtsx_chip *chip, u8 card)
+{
+	int retval;
+	u8 mask, val1, val2;
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) {
+		mask = MS_POWER_MASK;
+		val1 = MS_PARTIAL_POWER_ON;
+		val2 = MS_POWER_ON;
+	} else {
+		mask = SD_POWER_MASK;
+		val1 = SD_PARTIAL_POWER_ON;
+		val2 = SD_POWER_ON;
+	}
+
+	rtsx_init_cmd(chip);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1);
+	if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_SUSPEND);
+	}
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	udelay(chip->pmos_pwr_on_interval);
+
+	rtsx_init_cmd(chip);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2);
+	if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
+	}
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int card_power_off(struct rtsx_chip *chip, u8 card)
+{
+	u8 mask, val;
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (card == MS_CARD)) {
+		mask = MS_POWER_MASK;
+		val = MS_POWER_OFF;
+	} else {
+		mask = SD_POWER_MASK;
+		val = SD_POWER_OFF;
+	}
+	if (CHECK_PID(chip, 0x5209)) {
+		mask |= PMOS_STRG_MASK;
+		val |= PMOS_STRG_400mA;
+	}
+
+	RTSX_WRITE_REG(chip, CARD_PWR_CTL, mask, val);
+	if (CHECK_PID(chip, 0x5209) && (card == SD_CARD)) {
+		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt)
+{
+	int retval;
+	unsigned int lun = SCSI_LUN(srb);
+	int i;
+
+	if (chip->rw_card[lun] == NULL) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (i = 0; i < 3; i++) {
+		chip->rw_need_retry = 0;
+
+		retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt);
+		if (retval != STATUS_SUCCESS) {
+			if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) {
+				rtsx_release_chip(chip);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (detect_card_cd(chip, chip->cur_card) != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (!chip->rw_need_retry) {
+				RTSX_DEBUGP("RW fail, but no need to retry\n");
+				break;
+			}
+		} else {
+			chip->rw_need_retry = 0;
+			break;
+		}
+
+		RTSX_DEBUGP("Retry RW, (i = %d)\n", i);
+	}
+
+	return retval;
+}
+
+int card_share_mode(struct rtsx_chip *chip, int card)
+{
+	u8 mask, value;
+
+	if (CHECK_PID(chip, 0x5209) || CHECK_PID(chip, 0x5208)) {
+		mask = CARD_SHARE_MASK;
+		if (card == SD_CARD) {
+			value = CARD_SHARE_48_SD;
+		} else if (card == MS_CARD) {
+			value = CARD_SHARE_48_MS;
+		} else if (card == XD_CARD) {
+			value = CARD_SHARE_48_XD;
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else if (CHECK_PID(chip, 0x5288)) {
+		mask = 0x03;
+		if (card == SD_CARD) {
+			value = CARD_SHARE_BAROSSA_SD;
+		} else if (card == MS_CARD) {
+			value = CARD_SHARE_BAROSSA_MS;
+		} else if (card == XD_CARD) {
+			value = CARD_SHARE_BAROSSA_XD;
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, CARD_SHARE_MODE, mask, value);
+
+	return STATUS_SUCCESS;
+}
+
+
+int select_card(struct rtsx_chip *chip, int card)
+{
+	int retval;
+
+	if (chip->cur_card != card) {
+		u8 mod;
+
+		if (card == SD_CARD) {
+			mod = SD_MOD_SEL;
+		} else if (card == MS_CARD) {
+			mod = MS_MOD_SEL;
+		} else if (card == XD_CARD) {
+			mod = XD_MOD_SEL;
+		} else if (card == SPI_CARD) {
+			mod = SPI_MOD_SEL;
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		RTSX_WRITE_REG(chip, CARD_SELECT, 0x07, mod);
+		chip->cur_card = card;
+
+		retval =  card_share_mode(chip, card);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+void toggle_gpio(struct rtsx_chip *chip, u8 gpio)
+{
+	u8 temp_reg;
+
+	rtsx_read_register(chip, CARD_GPIO, &temp_reg);
+	temp_reg ^= (0x01 << gpio);
+	rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg);
+}
+
+void turn_on_led(struct rtsx_chip *chip, u8 gpio)
+{
+	if (CHECK_PID(chip, 0x5288)) {
+		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio));
+	} else {
+		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
+	}
+}
+
+void turn_off_led(struct rtsx_chip *chip, u8 gpio)
+{
+	if (CHECK_PID(chip, 0x5288)) {
+		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
+	} else {
+		rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), (u8)(1 << gpio));
+	}
+}
+
+int detect_card_cd(struct rtsx_chip *chip, int card)
+{
+	u32 card_cd, status;
+
+	if (card == SD_CARD) {
+		card_cd = SD_EXIST;
+	} else if (card == MS_CARD) {
+		card_cd = MS_EXIST;
+	} else if (card == XD_CARD) {
+		card_cd = XD_EXIST;
+	} else {
+		RTSX_DEBUGP("Wrong card type: 0x%x\n", card);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	status = rtsx_readl(chip, RTSX_BIPR);
+	if (!(status & card_cd)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int check_card_exist(struct rtsx_chip *chip, unsigned int lun)
+{
+	if (chip->card_exist & chip->lun2card[lun]) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int check_card_ready(struct rtsx_chip *chip, unsigned int lun)
+{
+	if (chip->card_ready & chip->lun2card[lun]) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int check_card_wp(struct rtsx_chip *chip, unsigned int lun)
+{
+	if (chip->card_wp & chip->lun2card[lun]) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int check_card_fail(struct rtsx_chip *chip, unsigned int lun)
+{
+	if (chip->card_fail & chip->lun2card[lun]) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int check_card_ejected(struct rtsx_chip *chip, unsigned int lun)
+{
+	if (chip->card_ejected & chip->lun2card[lun]) {
+		return 1;
+	}
+
+	return 0;
+}
+
+u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun)
+{
+	if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
+		return (u8)XD_CARD;
+	} else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
+		return (u8)SD_CARD;
+	} else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
+		return (u8)MS_CARD;
+	}
+
+	return 0;
+}
+
+void eject_card(struct rtsx_chip *chip, unsigned int lun)
+{
+	do_remaining_work(chip);
+
+	if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
+		release_sd_card(chip);
+		chip->card_ejected |= SD_CARD;
+		chip->card_ready &= ~SD_CARD;
+		chip->capacity[lun] = 0;
+	} else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
+		release_xd_card(chip);
+		chip->card_ejected |= XD_CARD;
+		chip->card_ready &= ~XD_CARD;
+		chip->capacity[lun] = 0;
+	} else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
+		release_ms_card(chip);
+		chip->card_ejected |= MS_CARD;
+		chip->card_ready &= ~MS_CARD;
+		chip->capacity[lun] = 0;
+	}
+}
diff --git a/drivers/staging/rts_pstor/rtsx_card.h b/drivers/staging/rts_pstor/rtsx_card.h
new file mode 100644
index 0000000..3f72776
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_card.h
@@ -0,0 +1,1093 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_CARD_H
+#define __REALTEK_RTSX_CARD_H
+
+#include "debug.h"
+#include "rtsx.h"
+#include "rtsx_chip.h"
+#include "rtsx_transport.h"
+#include "sd.h"
+
+#define SSC_POWER_DOWN		0x01
+#define SD_OC_POWER_DOWN	0x02
+#define MS_OC_POWER_DOWN	0x04
+#define ALL_POWER_DOWN		0x07
+#define OC_POWER_DOWN		0x06
+
+#define PMOS_STRG_MASK		0x10
+#define PMOS_STRG_800mA		0x10
+#define PMOS_STRG_400mA		0x00
+
+#define POWER_OFF		0x03
+#define PARTIAL_POWER_ON	0x01
+#define POWER_ON		0x00
+
+#define MS_POWER_OFF		0x0C
+#define MS_PARTIAL_POWER_ON	0x04
+#define MS_POWER_ON		0x00
+#define MS_POWER_MASK		0x0C
+
+#define SD_POWER_OFF		0x03
+#define SD_PARTIAL_POWER_ON	0x01
+#define SD_POWER_ON		0x00
+#define SD_POWER_MASK		0x03
+
+#define XD_OUTPUT_EN		0x02
+#define SD_OUTPUT_EN		0x04
+#define MS_OUTPUT_EN		0x08
+#define SPI_OUTPUT_EN		0x10
+
+#define CLK_LOW_FREQ		0x01
+
+#define CLK_DIV_1		0x01
+#define CLK_DIV_2		0x02
+#define CLK_DIV_4		0x03
+#define CLK_DIV_8		0x04
+
+#define SSC_80			0
+#define SSC_100			1
+#define SSC_120			2
+#define SSC_150			3
+#define SSC_200			4
+
+#define XD_CLK_EN		0x02
+#define SD_CLK_EN		0x04
+#define MS_CLK_EN		0x08
+#define SPI_CLK_EN		0x10
+
+#define XD_MOD_SEL		1
+#define SD_MOD_SEL		2
+#define MS_MOD_SEL		3
+#define SPI_MOD_SEL		4
+
+#define CHANGE_CLK		0x01
+
+#define	SD_CRC7_ERR			0x80
+#define	SD_CRC16_ERR			0x40
+#define	SD_CRC_WRITE_ERR		0x20
+#define	SD_CRC_WRITE_ERR_MASK	    	0x1C
+#define	GET_CRC_TIME_OUT		0x02
+#define	SD_TUNING_COMPARE_ERR		0x01
+
+#define	SD_RSP_80CLK_TIMEOUT		0x01
+
+#define	SD_CLK_TOGGLE_EN		0x80
+#define	SD_CLK_FORCE_STOP	        0x40
+#define	SD_DAT3_STATUS		        0x10
+#define	SD_DAT2_STATUS		        0x08
+#define	SD_DAT1_STATUS		        0x04
+#define	SD_DAT0_STATUS		        0x02
+#define	SD_CMD_STATUS			0x01
+
+#define	SD_IO_USING_1V8		        0x80
+#define	SD_IO_USING_3V3		        0x7F
+#define	TYPE_A_DRIVING		        0x00
+#define	TYPE_B_DRIVING			0x01
+#define	TYPE_C_DRIVING			0x02
+#define	TYPE_D_DRIVING		        0x03
+
+#define	DDR_FIX_RX_DAT			0x00
+#define	DDR_VAR_RX_DAT			0x80
+#define	DDR_FIX_RX_DAT_EDGE		0x00
+#define	DDR_FIX_RX_DAT_14_DELAY		0x40
+#define	DDR_FIX_RX_CMD			0x00
+#define	DDR_VAR_RX_CMD			0x20
+#define	DDR_FIX_RX_CMD_POS_EDGE		0x00
+#define	DDR_FIX_RX_CMD_14_DELAY		0x10
+#define	SD20_RX_POS_EDGE		0x00
+#define	SD20_RX_14_DELAY		0x08
+#define SD20_RX_SEL_MASK		0x08
+
+#define	DDR_FIX_TX_CMD_DAT		0x00
+#define	DDR_VAR_TX_CMD_DAT		0x80
+#define	DDR_FIX_TX_DAT_14_TSU		0x00
+#define	DDR_FIX_TX_DAT_12_TSU		0x40
+#define	DDR_FIX_TX_CMD_NEG_EDGE		0x00
+#define	DDR_FIX_TX_CMD_14_AHEAD		0x20
+#define	SD20_TX_NEG_EDGE		0x00
+#define	SD20_TX_14_AHEAD		0x10
+#define SD20_TX_SEL_MASK		0x10
+#define	DDR_VAR_SDCLK_POL_SWAP		0x01
+
+#define	SD_TRANSFER_START		0x80
+#define	SD_TRANSFER_END			0x40
+#define SD_STAT_IDLE			0x20
+#define	SD_TRANSFER_ERR			0x10
+#define	SD_TM_NORMAL_WRITE		0x00
+#define	SD_TM_AUTO_WRITE_3		0x01
+#define	SD_TM_AUTO_WRITE_4		0x02
+#define	SD_TM_AUTO_READ_3		0x05
+#define	SD_TM_AUTO_READ_4		0x06
+#define	SD_TM_CMD_RSP			0x08
+#define	SD_TM_AUTO_WRITE_1		0x09
+#define	SD_TM_AUTO_WRITE_2		0x0A
+#define	SD_TM_NORMAL_READ		0x0C
+#define	SD_TM_AUTO_READ_1		0x0D
+#define	SD_TM_AUTO_READ_2		0x0E
+#define	SD_TM_AUTO_TUNING		0x0F
+
+#define PHASE_CHANGE			0x80
+#define PHASE_NOT_RESET			0x40
+
+#define DCMPS_CHANGE			0x80
+#define DCMPS_CHANGE_DONE	   	0x40
+#define DCMPS_ERROR			0x20
+#define DCMPS_CURRENT_PHASE     	0x1F
+
+#define SD_CLK_DIVIDE_0			0x00
+#define	SD_CLK_DIVIDE_256		0xC0
+#define	SD_CLK_DIVIDE_128		0x80
+#define	SD_BUS_WIDTH_1			0x00
+#define	SD_BUS_WIDTH_4			0x01
+#define	SD_BUS_WIDTH_8			0x02
+#define	SD_ASYNC_FIFO_NOT_RST		0x10
+#define	SD_20_MODE			0x00
+#define	SD_DDR_MODE			0x04
+#define	SD_30_MODE			0x08
+
+#define SD_CLK_DIVIDE_MASK		0xC0
+
+#define SD_CMD_IDLE			0x80
+
+#define SD_DATA_IDLE			0x80
+
+#define DCM_RESET			0x08
+#define DCM_LOCKED			0x04
+#define DCM_208M			0x00
+#define DCM_TX			        0x01
+#define DCM_RX			        0x02
+
+#define DRP_START			0x80
+#define DRP_DONE			0x40
+
+#define DRP_WRITE			0x80
+#define DRP_READ			0x00
+#define DCM_WRITE_ADDRESS_50		0x50
+#define DCM_WRITE_ADDRESS_51		0x51
+#define DCM_READ_ADDRESS_00		0x00
+#define DCM_READ_ADDRESS_51		0x51
+
+#define	SD_CALCULATE_CRC7		0x00
+#define	SD_NO_CALCULATE_CRC7		0x80
+#define	SD_CHECK_CRC16			0x00
+#define	SD_NO_CHECK_CRC16		0x40
+#define SD_NO_CHECK_WAIT_CRC_TO		0x20
+#define	SD_WAIT_BUSY_END		0x08
+#define	SD_NO_WAIT_BUSY_END		0x00
+#define	SD_CHECK_CRC7			0x00
+#define	SD_NO_CHECK_CRC7		0x04
+#define	SD_RSP_LEN_0			0x00
+#define	SD_RSP_LEN_6			0x01
+#define	SD_RSP_LEN_17			0x02
+#define	SD_RSP_TYPE_R0			0x04
+#define	SD_RSP_TYPE_R1			0x01
+#define	SD_RSP_TYPE_R1b			0x09
+#define	SD_RSP_TYPE_R2			0x02
+#define	SD_RSP_TYPE_R3			0x05
+#define	SD_RSP_TYPE_R4			0x05
+#define	SD_RSP_TYPE_R5			0x01
+#define	SD_RSP_TYPE_R6			0x01
+#define	SD_RSP_TYPE_R7			0x01
+
+#define	SD_RSP_80CLK_TIMEOUT_EN	   	0x01
+
+#define	SAMPLE_TIME_RISING		0x00
+#define	SAMPLE_TIME_FALLING		0x80
+#define	PUSH_TIME_DEFAULT		0x00
+#define	PUSH_TIME_ODD			0x40
+#define	NO_EXTEND_TOGGLE		0x00
+#define	EXTEND_TOGGLE_CHK		0x20
+#define	MS_BUS_WIDTH_1			0x00
+#define	MS_BUS_WIDTH_4			0x10
+#define	MS_BUS_WIDTH_8			0x18
+#define	MS_2K_SECTOR_MODE		0x04
+#define	MS_512_SECTOR_MODE		0x00
+#define	MS_TOGGLE_TIMEOUT_EN		0x00
+#define	MS_TOGGLE_TIMEOUT_DISEN		0x01
+#define MS_NO_CHECK_INT			0x02
+
+#define	WAIT_INT			0x80
+#define	NO_WAIT_INT			0x00
+#define	NO_AUTO_READ_INT_REG		0x00
+#define	AUTO_READ_INT_REG		0x40
+#define	MS_CRC16_ERR			0x20
+#define	MS_RDY_TIMEOUT			0x10
+#define	MS_INT_CMDNK			0x08
+#define	MS_INT_BREQ			0x04
+#define	MS_INT_ERR			0x02
+#define	MS_INT_CED			0x01
+
+#define	MS_TRANSFER_START		0x80
+#define	MS_TRANSFER_END			0x40
+#define	MS_TRANSFER_ERR			0x20
+#define	MS_BS_STATE			0x10
+#define	MS_TM_READ_BYTES		0x00
+#define	MS_TM_NORMAL_READ		0x01
+#define	MS_TM_WRITE_BYTES		0x04
+#define	MS_TM_NORMAL_WRITE		0x05
+#define	MS_TM_AUTO_READ			0x08
+#define	MS_TM_AUTO_WRITE		0x0C
+
+#define CARD_SHARE_MASK			0x0F
+#define CARD_SHARE_MULTI_LUN		0x00
+#define	CARD_SHARE_NORMAL		0x00
+#define	CARD_SHARE_48_XD		0x02
+#define	CARD_SHARE_48_SD		0x04
+#define	CARD_SHARE_48_MS		0x08
+#define CARD_SHARE_BAROSSA_XD		0x00
+#define CARD_SHARE_BAROSSA_SD		0x01
+#define CARD_SHARE_BAROSSA_MS		0x02
+
+#define	MS_DRIVE_8			0x00
+#define	MS_DRIVE_4			0x40
+#define	MS_DRIVE_12			0x80
+#define	SD_DRIVE_8			0x00
+#define	SD_DRIVE_4			0x10
+#define	SD_DRIVE_12			0x20
+#define	XD_DRIVE_8			0x00
+#define	XD_DRIVE_4			0x04
+#define	XD_DRIVE_12			0x08
+
+#define SPI_STOP		0x01
+#define XD_STOP			0x02
+#define SD_STOP			0x04
+#define MS_STOP			0x08
+#define SPI_CLR_ERR		0x10
+#define XD_CLR_ERR		0x20
+#define SD_CLR_ERR		0x40
+#define MS_CLR_ERR		0x80
+
+#define CRC_FIX_CLK		(0x00 << 0)
+#define CRC_VAR_CLK0		(0x01 << 0)
+#define CRC_VAR_CLK1		(0x02 << 0)
+#define SD30_FIX_CLK		(0x00 << 2)
+#define SD30_VAR_CLK0		(0x01 << 2)
+#define SD30_VAR_CLK1		(0x02 << 2)
+#define SAMPLE_FIX_CLK		(0x00 << 4)
+#define SAMPLE_VAR_CLK0		(0x01 << 4)
+#define SAMPLE_VAR_CLK1		(0x02 << 4)
+
+#define SDIO_VER_20		0x80
+#define SDIO_VER_10		0x00
+#define SDIO_VER_CHG		0x40
+#define SDIO_BUS_AUTO_SWITCH	0x10
+
+#define PINGPONG_BUFFER		0x01
+#define RING_BUFFER		0x00
+
+#define RB_FLUSH		0x80
+
+#define DMA_DONE_INT_EN			0x80
+#define SUSPEND_INT_EN			0x40
+#define LINK_RDY_INT_EN			0x20
+#define LINK_DOWN_INT_EN		0x10
+
+#define DMA_DONE_INT			0x80
+#define SUSPEND_INT			0x40
+#define LINK_RDY_INT			0x20
+#define LINK_DOWN_INT			0x10
+
+#define MRD_ERR_INT_EN			0x40
+#define MWR_ERR_INT_EN			0x20
+#define SCSI_CMD_INT_EN			0x10
+#define TLP_RCV_INT_EN			0x08
+#define TLP_TRSMT_INT_EN		0x04
+#define MRD_COMPLETE_INT_EN		0x02
+#define MWR_COMPLETE_INT_EN		0x01
+
+#define MRD_ERR_INT			0x40
+#define MWR_ERR_INT			0x20
+#define SCSI_CMD_INT			0x10
+#define TLP_RX_INT			0x08
+#define TLP_TX_INT			0x04
+#define MRD_COMPLETE_INT		0x02
+#define MWR_COMPLETE_INT		0x01
+
+#define MSG_RX_INT_EN			0x08
+#define MRD_RX_INT_EN			0x04
+#define MWR_RX_INT_EN			0x02
+#define CPLD_RX_INT_EN			0x01
+
+#define MSG_RX_INT			0x08
+#define MRD_RX_INT			0x04
+#define MWR_RX_INT			0x02
+#define CPLD_RX_INT			0x01
+
+#define MSG_TX_INT_EN			0x08
+#define MRD_TX_INT_EN			0x04
+#define MWR_TX_INT_EN			0x02
+#define CPLD_TX_INT_EN			0x01
+
+#define MSG_TX_INT			0x08
+#define MRD_TX_INT			0x04
+#define MWR_TX_INT			0x02
+#define CPLD_TX_INT			0x01
+
+#define DMA_RST				0x80
+#define DMA_BUSY			0x04
+#define DMA_DIR_TO_CARD			0x00
+#define DMA_DIR_FROM_CARD		0x02
+#define DMA_EN				0x01
+#define DMA_128				(0 << 4)
+#define DMA_256				(1 << 4)
+#define DMA_512				(2 << 4)
+#define DMA_1024			(3 << 4)
+#define DMA_PACK_SIZE_MASK		0x30
+
+#define	XD_PWR_OFF_DELAY0		0x00
+#define	XD_PWR_OFF_DELAY1		0x02
+#define	XD_PWR_OFF_DELAY2		0x04
+#define	XD_PWR_OFF_DELAY3		0x06
+#define	XD_AUTO_PWR_OFF_EN		0xF7
+#define	XD_NO_AUTO_PWR_OFF		0x08
+
+#define	XD_TIME_RWN_1			0x00
+#define	XD_TIME_RWN_STEP		0x20
+#define	XD_TIME_RW_1			0x00
+#define	XD_TIME_RW_STEP			0x04
+#define	XD_TIME_SETUP_1			0x00
+#define	XD_TIME_SETUP_STEP		0x01
+
+#define	XD_ECC2_UNCORRECTABLE		0x80
+#define	XD_ECC2_ERROR			0x40
+#define	XD_ECC1_UNCORRECTABLE		0x20
+#define	XD_ECC1_ERROR			0x10
+#define	XD_RDY				0x04
+#define	XD_CE_EN			0xFD
+#define	XD_CE_DISEN			0x02
+#define	XD_WP_EN			0xFE
+#define	XD_WP_DISEN			0x01
+
+#define	XD_TRANSFER_START		0x80
+#define	XD_TRANSFER_END			0x40
+#define	XD_PPB_EMPTY			0x20
+#define	XD_RESET			0x00
+#define	XD_ERASE			0x01
+#define	XD_READ_STATUS			0x02
+#define	XD_READ_ID			0x03
+#define	XD_READ_REDUNDANT		0x04
+#define	XD_READ_PAGES			0x05
+#define	XD_SET_CMD			0x06
+#define	XD_NORMAL_READ			0x07
+#define	XD_WRITE_PAGES			0x08
+#define	XD_NORMAL_WRITE			0x09
+#define	XD_WRITE_REDUNDANT		0x0A
+#define	XD_SET_ADDR			0x0B
+
+#define	XD_PPB_TO_SIE			0x80
+#define	XD_TO_PPB_ONLY			0x00
+#define	XD_BA_TRANSFORM			0x40
+#define	XD_BA_NO_TRANSFORM		0x00
+#define	XD_NO_CALC_ECC			0x20
+#define	XD_CALC_ECC			0x00
+#define	XD_IGNORE_ECC			0x10
+#define	XD_CHECK_ECC			0x00
+#define	XD_DIRECT_TO_RB			0x08
+#define	XD_ADDR_LENGTH_0		0x00
+#define	XD_ADDR_LENGTH_1		0x01
+#define	XD_ADDR_LENGTH_2		0x02
+#define	XD_ADDR_LENGTH_3		0x03
+#define	XD_ADDR_LENGTH_4		0x04
+
+#define	XD_GPG				0xFF
+#define	XD_BPG				0x00
+
+#define	XD_GBLK				0xFF
+#define	XD_LATER_BBLK			0xF0
+
+#define	XD_ECC2_ALL1			0x80
+#define	XD_ECC1_ALL1			0x40
+#define	XD_BA2_ALL0			0x20
+#define	XD_BA1_ALL0			0x10
+#define	XD_BA1_BA2_EQL			0x04
+#define	XD_BA2_VALID			0x02
+#define	XD_BA1_VALID			0x01
+
+#define	XD_PGSTS_ZEROBIT_OVER4		0x00
+#define	XD_PGSTS_NOT_FF			0x02
+#define	XD_AUTO_CHK_DATA_STATUS		0x01
+
+#define	RSTB_MODE_DETECT		0x80
+#define	MODE_OUT_VLD			0x40
+#define	MODE_OUT_0_NONE			0x00
+#define	MODE_OUT_10_NONE		0x04
+#define	MODE_OUT_10_47			0x05
+#define	MODE_OUT_10_180			0x06
+#define	MODE_OUT_10_680			0x07
+#define	MODE_OUT_16_NONE		0x08
+#define	MODE_OUT_16_47			0x09
+#define	MODE_OUT_16_180			0x0A
+#define	MODE_OUT_16_680			0x0B
+#define	MODE_OUT_NONE_NONE		0x0C
+#define	MODE_OUT_NONE_47		0x0D
+#define	MODE_OUT_NONE_180		0x0E
+#define	MODE_OUT_NONE_680		0x0F
+
+#define	CARD_OC_INT_EN			0x20
+#define	CARD_DETECT_EN			0x08
+
+#define MS_DETECT_EN			0x80
+#define MS_OCP_INT_EN			0x40
+#define MS_OCP_INT_CLR			0x20
+#define MS_OC_CLR			0x10
+#define SD_DETECT_EN			0x08
+#define SD_OCP_INT_EN			0x04
+#define SD_OCP_INT_CLR			0x02
+#define SD_OC_CLR			0x01
+
+#define	CARD_OCP_DETECT			0x80
+#define	CARD_OC_NOW			0x08
+#define	CARD_OC_EVER			0x04
+
+#define MS_OCP_DETECT			0x80
+#define MS_OC_NOW			0x40
+#define MS_OC_EVER			0x20
+#define SD_OCP_DETECT			0x08
+#define SD_OC_NOW			0x04
+#define SD_OC_EVER			0x02
+
+#define	CARD_OC_INT_CLR			0x08
+#define	CARD_OC_CLR			0x02
+
+#define SD_OCP_GLITCH_MASK		0x07
+#define SD_OCP_GLITCH_6_4		0x00
+#define SD_OCP_GLITCH_64		0x01
+#define SD_OCP_GLITCH_640		0x02
+#define SD_OCP_GLITCH_1000		0x03
+#define SD_OCP_GLITCH_2000		0x04
+#define SD_OCP_GLITCH_4000		0x05
+#define SD_OCP_GLITCH_8000		0x06
+#define SD_OCP_GLITCH_10000		0x07
+
+#define MS_OCP_GLITCH_MASK		0x70
+#define MS_OCP_GLITCH_6_4		(0x00 << 4)
+#define MS_OCP_GLITCH_64		(0x01 << 4)
+#define MS_OCP_GLITCH_640		(0x02 << 4)
+#define MS_OCP_GLITCH_1000		(0x03 << 4)
+#define MS_OCP_GLITCH_2000		(0x04 << 4)
+#define MS_OCP_GLITCH_4000		(0x05 << 4)
+#define MS_OCP_GLITCH_8000		(0x06 << 4)
+#define MS_OCP_GLITCH_10000		(0x07 << 4)
+
+#define OCP_TIME_60			0x00
+#define OCP_TIME_100			(0x01 << 3)
+#define OCP_TIME_200			(0x02 << 3)
+#define OCP_TIME_400			(0x03 << 3)
+#define OCP_TIME_600			(0x04 << 3)
+#define OCP_TIME_800			(0x05 << 3)
+#define OCP_TIME_1100			(0x06 << 3)
+#define OCP_TIME_MASK			0x38
+
+#define MS_OCP_TIME_60			0x00
+#define MS_OCP_TIME_100			(0x01 << 4)
+#define MS_OCP_TIME_200			(0x02 << 4)
+#define MS_OCP_TIME_400			(0x03 << 4)
+#define MS_OCP_TIME_600			(0x04 << 4)
+#define MS_OCP_TIME_800			(0x05 << 4)
+#define MS_OCP_TIME_1100		(0x06 << 4)
+#define MS_OCP_TIME_MASK		0x70
+
+#define SD_OCP_TIME_60			0x00
+#define SD_OCP_TIME_100			0x01
+#define SD_OCP_TIME_200			0x02
+#define SD_OCP_TIME_400			0x03
+#define SD_OCP_TIME_600			0x04
+#define SD_OCP_TIME_800			0x05
+#define SD_OCP_TIME_1100		0x06
+#define SD_OCP_TIME_MASK		0x07
+
+#define OCP_THD_315_417			0x00
+#define OCP_THD_283_783			(0x01 << 6)
+#define OCP_THD_244_946			(0x02 << 6)
+#define OCP_THD_191_1080		(0x03 << 6)
+#define OCP_THD_MASK			0xC0
+
+#define MS_OCP_THD_450			0x00
+#define MS_OCP_THD_550			(0x01 << 4)
+#define MS_OCP_THD_650			(0x02 << 4)
+#define MS_OCP_THD_750			(0x03 << 4)
+#define MS_OCP_THD_850			(0x04 << 4)
+#define MS_OCP_THD_950			(0x05 << 4)
+#define MS_OCP_THD_1050			(0x06 << 4)
+#define MS_OCP_THD_1150			(0x07 << 4)
+#define MS_OCP_THD_MASK			0x70
+
+#define SD_OCP_THD_450			0x00
+#define SD_OCP_THD_550			0x01
+#define SD_OCP_THD_650			0x02
+#define SD_OCP_THD_750			0x03
+#define SD_OCP_THD_850			0x04
+#define SD_OCP_THD_950			0x05
+#define SD_OCP_THD_1050			0x06
+#define SD_OCP_THD_1150			0x07
+#define SD_OCP_THD_MASK			0x07
+
+#define FPGA_MS_PULL_CTL_EN		0xEF
+#define FPGA_SD_PULL_CTL_EN		0xF7
+#define FPGA_XD_PULL_CTL_EN1		0xFE
+#define FPGA_XD_PULL_CTL_EN2		0xFD
+#define FPGA_XD_PULL_CTL_EN3		0xFB
+
+#define FPGA_MS_PULL_CTL_BIT		0x10
+#define FPGA_SD_PULL_CTL_BIT		0x08
+
+#define BLINK_EN			0x08
+#define LED_GPIO0			(0 << 4)
+#define LED_GPIO1			(1 << 4)
+#define LED_GPIO2			(2 << 4)
+
+#define SDIO_BUS_CTRL		0x01
+#define SDIO_CD_CTRL		0x02
+
+#define SSC_RSTB		0x80
+#define SSC_8X_EN		0x40
+#define SSC_FIX_FRAC		0x20
+#define SSC_SEL_1M		0x00
+#define SSC_SEL_2M		0x08
+#define SSC_SEL_4M		0x10
+#define SSC_SEL_8M		0x18
+
+#define SSC_DEPTH_MASK		0x07
+#define SSC_DEPTH_DISALBE	0x00
+#define SSC_DEPTH_4M		0x01
+#define SSC_DEPTH_2M		0x02
+#define SSC_DEPTH_1M		0x03
+#define SSC_DEPTH_512K		0x04
+#define SSC_DEPTH_256K		0x05
+#define SSC_DEPTH_128K		0x06
+#define SSC_DEPTH_64K		0x07
+
+#define XD_D3_NP		0x00
+#define XD_D3_PD		(0x01 << 6)
+#define XD_D3_PU		(0x02 << 6)
+#define XD_D2_NP		0x00
+#define XD_D2_PD		(0x01 << 4)
+#define XD_D2_PU		(0x02 << 4)
+#define XD_D1_NP		0x00
+#define XD_D1_PD		(0x01 << 2)
+#define XD_D1_PU		(0x02 << 2)
+#define XD_D0_NP		0x00
+#define XD_D0_PD		0x01
+#define XD_D0_PU		0x02
+
+#define SD_D7_NP		0x00
+#define SD_D7_PD		(0x01 << 4)
+#define SD_DAT7_PU		(0x02 << 4)
+#define SD_CLK_NP		0x00
+#define SD_CLK_PD		(0x01 << 2)
+#define SD_CLK_PU		(0x02 << 2)
+#define SD_D5_NP		0x00
+#define SD_D5_PD		0x01
+#define SD_D5_PU		0x02
+
+#define MS_D1_NP		0x00
+#define MS_D1_PD		(0x01 << 6)
+#define MS_D1_PU		(0x02 << 6)
+#define MS_D2_NP		0x00
+#define MS_D2_PD		(0x01 << 4)
+#define MS_D2_PU		(0x02 << 4)
+#define MS_CLK_NP		0x00
+#define MS_CLK_PD		(0x01 << 2)
+#define MS_CLK_PU		(0x02 << 2)
+#define MS_D6_NP		0x00
+#define MS_D6_PD		0x01
+#define MS_D6_PU		0x02
+
+#define XD_D7_NP		0x00
+#define XD_D7_PD		(0x01 << 6)
+#define XD_D7_PU		(0x02 << 6)
+#define XD_D6_NP		0x00
+#define XD_D6_PD		(0x01 << 4)
+#define XD_D6_PU		(0x02 << 4)
+#define XD_D5_NP		0x00
+#define XD_D5_PD		(0x01 << 2)
+#define XD_D5_PU		(0x02 << 2)
+#define XD_D4_NP		0x00
+#define XD_D4_PD		0x01
+#define XD_D4_PU		0x02
+
+#define SD_D6_NP		0x00
+#define SD_D6_PD		(0x01 << 6)
+#define SD_D6_PU		(0x02 << 6)
+#define SD_D0_NP		0x00
+#define SD_D0_PD		(0x01 << 4)
+#define SD_D0_PU		(0x02 << 4)
+#define SD_D1_NP		0x00
+#define SD_D1_PD		0x01
+#define SD_D1_PU		0x02
+
+#define MS_D3_NP		0x00
+#define MS_D3_PD		(0x01 << 6)
+#define MS_D3_PU		(0x02 << 6)
+#define MS_D0_NP		0x00
+#define MS_D0_PD		(0x01 << 4)
+#define MS_D0_PU		(0x02 << 4)
+#define MS_BS_NP		0x00
+#define MS_BS_PD		(0x01 << 2)
+#define MS_BS_PU		(0x02 << 2)
+
+#define XD_WP_NP		0x00
+#define XD_WP_PD		(0x01 << 6)
+#define XD_WP_PU		(0x02 << 6)
+#define XD_CE_NP		0x00
+#define XD_CE_PD		(0x01 << 3)
+#define XD_CE_PU		(0x02 << 3)
+#define XD_CLE_NP		0x00
+#define XD_CLE_PD		(0x01 << 1)
+#define XD_CLE_PU		(0x02 << 1)
+#define XD_CD_PD		0x00
+#define XD_CD_PU		0x01
+
+#define SD_D4_NP		0x00
+#define SD_D4_PD		(0x01 << 6)
+#define SD_D4_PU		(0x02 << 6)
+
+#define MS_D7_NP		0x00
+#define MS_D7_PD		(0x01 << 6)
+#define MS_D7_PU		(0x02 << 6)
+
+#define XD_RDY_NP		0x00
+#define XD_RDY_PD		(0x01 << 6)
+#define XD_RDY_PU		(0x02 << 6)
+#define XD_WE_NP		0x00
+#define XD_WE_PD		(0x01 << 4)
+#define XD_WE_PU		(0x02 << 4)
+#define XD_RE_NP		0x00
+#define XD_RE_PD		(0x01 << 2)
+#define XD_RE_PU		(0x02 << 2)
+#define XD_ALE_NP		0x00
+#define XD_ALE_PD		0x01
+#define XD_ALE_PU		0x02
+
+#define SD_D3_NP		0x00
+#define SD_D3_PD		(0x01 << 4)
+#define SD_D3_PU		(0x02 << 4)
+#define SD_D2_NP		0x00
+#define SD_D2_PD		(0x01 << 2)
+#define SD_D2_PU		(0x02 << 2)
+
+#define MS_INS_PD		0x00
+#define MS_INS_PU		(0x01 << 7)
+#define SD_WP_NP		0x00
+#define SD_WP_PD		(0x01 << 5)
+#define SD_WP_PU		(0x02 << 5)
+#define SD_CD_PD		0x00
+#define SD_CD_PU		(0x01 << 4)
+#define SD_CMD_NP		0x00
+#define SD_CMD_PD		(0x01 << 2)
+#define SD_CMD_PU		(0x02 << 2)
+
+#define MS_D5_NP		0x00
+#define MS_D5_PD		(0x01 << 2)
+#define MS_D5_PU		(0x02 << 2)
+#define MS_D4_NP		0x00
+#define MS_D4_PD		0x01
+#define MS_D4_PU		0x02
+
+#define FORCE_PM_CLOCK		0x10
+#define EN_CLOCK_PM		0x01
+
+#define HOST_ENTER_S3		0x02
+#define HOST_ENTER_S1		0x01
+
+#define AUX_PWR_DETECTED	0x01
+
+#define PHY_DEBUG_MODE		0x01
+
+#define SPI_COMMAND_BIT_8	0xE0
+#define SPI_ADDRESS_BIT_24	0x17
+#define SPI_ADDRESS_BIT_32	0x1F
+
+#define SPI_TRANSFER0_START	0x80
+#define SPI_TRANSFER0_END	0x40
+#define SPI_C_MODE0		0x00
+#define SPI_CA_MODE0		0x01
+#define SPI_CDO_MODE0		0x02
+#define SPI_CDI_MODE0		0x03
+#define SPI_CADO_MODE0		0x04
+#define SPI_CADI_MODE0		0x05
+#define SPI_POLLING_MODE0	0x06
+
+#define SPI_TRANSFER1_START	0x80
+#define SPI_TRANSFER1_END	0x40
+#define SPI_DO_MODE1		0x00
+#define SPI_DI_MODE1		0x01
+
+#define CS_POLARITY_HIGH	0x40
+#define CS_POLARITY_LOW		0x00
+#define DTO_MSB_FIRST		0x00
+#define DTO_LSB_FIRST		0x20
+#define SPI_MASTER		0x00
+#define SPI_SLAVE		0x10
+#define SPI_MODE0		0x00
+#define SPI_MODE1		0x04
+#define SPI_MODE2		0x08
+#define SPI_MODE3		0x0C
+#define SPI_MANUAL		0x00
+#define SPI_HALF_AUTO		0x01
+#define SPI_AUTO		0x02
+#define SPI_EEPROM_AUTO		0x03
+
+#define EDO_TIMING_MASK		0x03
+#define SAMPLE_RISING		0x00
+#define SAMPLE_DELAY_HALF	0x01
+#define SAMPLE_DELAY_ONE	0x02
+#define SAPMLE_DELAY_ONE_HALF	0x03
+#define TCS_MASK		0x0C
+
+#define NOT_BYPASS_SD		0x02
+#define DISABLE_SDIO_FUNC	0x04
+#define SELECT_1LUN		0x08
+
+#define PWR_GATE_EN		0x01
+#define LDO3318_PWR_MASK	0x06
+#define LDO_ON			0x00
+#define LDO_SUSPEND		0x04
+#define LDO_OFF			0x06
+
+#define SD_CFG1			0xFDA0
+#define SD_CFG2			0xFDA1
+#define SD_CFG3			0xFDA2
+#define SD_STAT1		0xFDA3
+#define SD_STAT2		0xFDA4
+#define SD_BUS_STAT		0xFDA5
+#define SD_PAD_CTL		0xFDA6
+#define SD_SAMPLE_POINT_CTL	0xFDA7
+#define SD_PUSH_POINT_CTL	0xFDA8
+#define SD_CMD0			0xFDA9
+#define SD_CMD1			0xFDAA
+#define SD_CMD2			0xFDAB
+#define SD_CMD3			0xFDAC
+#define SD_CMD4			0xFDAD
+#define SD_CMD5			0xFDAE
+#define SD_BYTE_CNT_L		0xFDAF
+#define SD_BYTE_CNT_H		0xFDB0
+#define SD_BLOCK_CNT_L		0xFDB1
+#define SD_BLOCK_CNT_H		0xFDB2
+#define SD_TRANSFER		0xFDB3
+#define SD_CMD_STATE		0xFDB5
+#define SD_DATA_STATE		0xFDB6
+
+#define	DCM_DRP_CTL         	0xFC23
+#define	DCM_DRP_TRIG		0xFC24
+#define	DCM_DRP_CFG         	0xFC25
+#define	DCM_DRP_WR_DATA_L   	0xFC26
+#define	DCM_DRP_WR_DATA_H   	0xFC27
+#define	DCM_DRP_RD_DATA_L   	0xFC28
+#define	DCM_DRP_RD_DATA_H   	0xFC29
+#define SD_VPCLK0_CTL		0xFC2A
+#define SD_VPCLK1_CTL		0xFC2B
+#define SD_DCMPS0_CTL		0xFC2C
+#define SD_DCMPS1_CTL		0xFC2D
+#define SD_VPTX_CTL		SD_VPCLK0_CTL
+#define SD_VPRX_CTL		SD_VPCLK1_CTL
+#define SD_DCMPS_TX_CTL		SD_DCMPS0_CTL
+#define SD_DCMPS_RX_CTL		SD_DCMPS1_CTL
+
+#define CARD_CLK_SOURCE		0xFC2E
+
+#define CARD_PWR_CTL		0xFD50
+#define CARD_CLK_SWITCH		0xFD51
+#define CARD_SHARE_MODE		0xFD52
+#define CARD_DRIVE_SEL		0xFD53
+#define CARD_STOP		0xFD54
+#define CARD_OE			0xFD55
+#define CARD_AUTO_BLINK		0xFD56
+#define CARD_GPIO_DIR		0xFD57
+#define CARD_GPIO		0xFD58
+
+#define CARD_DATA_SOURCE	0xFD5B
+#define CARD_SELECT		0xFD5C
+#define SD30_DRIVE_SEL		0xFD5E
+
+#define CARD_CLK_EN		0xFD69
+
+#define SDIO_CTRL		0xFD6B
+
+#define FPDCTL			0xFC00
+#define PDINFO			0xFC01
+
+#define CLK_CTL			0xFC02
+#define CLK_DIV			0xFC03
+#define CLK_SEL			0xFC04
+
+#define SSC_DIV_N_0		0xFC0F
+#define SSC_DIV_N_1		0xFC10
+
+#define RCCTL			0xFC14
+
+#define FPGA_PULL_CTL		0xFC1D
+
+#define CARD_PULL_CTL1		0xFD60
+#define CARD_PULL_CTL2		0xFD61
+#define CARD_PULL_CTL3		0xFD62
+#define CARD_PULL_CTL4		0xFD63
+#define CARD_PULL_CTL5		0xFD64
+#define CARD_PULL_CTL6		0xFD65
+
+#define IRQEN0				0xFE20
+#define IRQSTAT0			0xFE21
+#define IRQEN1				0xFE22
+#define IRQSTAT1			0xFE23
+#define TLPRIEN				0xFE24
+#define TLPRISTAT			0xFE25
+#define TLPTIEN				0xFE26
+#define TLPTISTAT			0xFE27
+#define DMATC0				0xFE28
+#define DMATC1				0xFE29
+#define DMATC2				0xFE2A
+#define DMATC3				0xFE2B
+#define DMACTL				0xFE2C
+#define BCTL				0xFE2D
+#define RBBC0				0xFE2E
+#define RBBC1				0xFE2F
+#define RBDAT				0xFE30
+#define RBCTL				0xFE34
+#define CFGADDR0			0xFE35
+#define CFGADDR1			0xFE36
+#define CFGDATA0			0xFE37
+#define CFGDATA1			0xFE38
+#define CFGDATA2			0xFE39
+#define CFGDATA3			0xFE3A
+#define CFGRWCTL			0xFE3B
+#define PHYRWCTL			0xFE3C
+#define PHYDATA0			0xFE3D
+#define PHYDATA1			0xFE3E
+#define PHYADDR				0xFE3F
+#define MSGRXDATA0			0xFE40
+#define MSGRXDATA1			0xFE41
+#define MSGRXDATA2			0xFE42
+#define MSGRXDATA3			0xFE43
+#define MSGTXDATA0			0xFE44
+#define MSGTXDATA1			0xFE45
+#define MSGTXDATA2			0xFE46
+#define MSGTXDATA3			0xFE47
+#define MSGTXCTL			0xFE48
+#define PETXCFG				0xFE49
+
+#define CDRESUMECTL			0xFE52
+#define WAKE_SEL_CTL			0xFE54
+#define PME_FORCE_CTL			0xFE56
+#define ASPM_FORCE_CTL			0xFE57
+#define PM_CLK_FORCE_CTL		0xFE58
+#define PERST_GLITCH_WIDTH		0xFE5C
+#define CHANGE_LINK_STATE		0xFE5B
+#define RESET_LOAD_REG			0xFE5E
+#define HOST_SLEEP_STATE		0xFE60
+#define MAIN_PWR_OFF_CTL		0xFE70	/* RTS5208 */
+#define SDIO_CFG			0xFE70	/* RTS5209 */
+
+#define NFTS_TX_CTRL			0xFE72
+
+#define PWR_GATE_CTRL			0xFE75
+#define PWD_SUSPEND_EN			0xFE76
+
+#define EFUSE_CONTENT			0xFE5F
+
+#define XD_INIT				0xFD10
+#define XD_DTCTL			0xFD11
+#define XD_CTL				0xFD12
+#define XD_TRANSFER			0xFD13
+#define XD_CFG				0xFD14
+#define XD_ADDRESS0			0xFD15
+#define XD_ADDRESS1			0xFD16
+#define XD_ADDRESS2			0xFD17
+#define XD_ADDRESS3			0xFD18
+#define XD_ADDRESS4			0xFD19
+#define XD_DAT				0xFD1A
+#define XD_PAGE_CNT			0xFD1B
+#define XD_PAGE_STATUS			0xFD1C
+#define XD_BLOCK_STATUS			0xFD1D
+#define XD_BLOCK_ADDR1_L		0xFD1E
+#define XD_BLOCK_ADDR1_H		0xFD1F
+#define XD_BLOCK_ADDR2_L		0xFD20
+#define XD_BLOCK_ADDR2_H		0xFD21
+#define XD_BYTE_CNT_L			0xFD22
+#define XD_BYTE_CNT_H			0xFD23
+#define	XD_PARITY			0xFD24
+#define XD_ECC_BIT1			0xFD25
+#define XD_ECC_BYTE1			0xFD26
+#define XD_ECC_BIT2			0xFD27
+#define XD_ECC_BYTE2			0xFD28
+#define XD_RESERVED0			0xFD29
+#define XD_RESERVED1			0xFD2A
+#define XD_RESERVED2			0xFD2B
+#define XD_RESERVED3			0xFD2C
+#define XD_CHK_DATA_STATUS		0xFD2D
+#define XD_CATCTL			0xFD2E
+
+#define MS_CFG				0xFD40
+#define MS_TPC				0xFD41
+#define MS_TRANS_CFG			0xFD42
+#define MS_TRANSFER			0xFD43
+#define MS_INT_REG			0xFD44
+#define MS_BYTE_CNT			0xFD45
+#define MS_SECTOR_CNT_L			0xFD46
+#define MS_SECTOR_CNT_H			0xFD47
+#define MS_DBUS_H			0xFD48
+
+#define SSC_CTL1			0xFC11
+#define SSC_CTL2			0xFC12
+
+#define OCPCTL				0xFC15
+#define OCPSTAT				0xFC16
+#define OCPCLR				0xFC17	/* 5208 */
+#define OCPGLITCH			0xFC17	/* 5209 */
+#define OCPPARA1			0xFC18
+#define OCPPARA2			0xFC19
+
+#define EFUSE_OP			0xFC20
+#define EFUSE_CTRL			0xFC21
+#define EFUSE_DATA			0xFC22
+
+#define	SPI_COMMAND			0xFD80
+#define	SPI_ADDR0			0xFD81
+#define	SPI_ADDR1			0xFD82
+#define	SPI_ADDR2			0xFD83
+#define	SPI_ADDR3			0xFD84
+#define	SPI_CA_NUMBER			0xFD85
+#define	SPI_LENGTH0			0xFD86
+#define	SPI_LENGTH1			0xFD87
+#define	SPI_DATA			0xFD88
+#define SPI_DATA_NUMBER			0xFD89
+#define	SPI_TRANSFER0			0xFD90
+#define	SPI_TRANSFER1			0xFD91
+#define	SPI_CONTROL			0xFD92
+#define	SPI_SIG				0xFD93
+#define	SPI_TCTL			0xFD94
+#define	SPI_SLAVE_NUM			0xFD95
+#define	SPI_CLK_DIVIDER0		0xFD96
+#define	SPI_CLK_DIVIDER1		0xFD97
+
+#define SRAM_BASE			0xE600
+#define RBUF_BASE			0xF400
+#define PPBUF_BASE1			0xF800
+#define PPBUF_BASE2			0xFA00
+#define IMAGE_FLAG_ADDR0		0xCE80
+#define IMAGE_FLAG_ADDR1		0xCE81
+
+#define READ_OP			1
+#define WRITE_OP		2
+
+#define LCTLR		0x80
+
+#define POLLING_WAIT_CNT	1
+#define IDLE_MAX_COUNT		10
+#define SDIO_IDLE_COUNT		10
+
+#define DEBOUNCE_CNT			5
+
+void do_remaining_work(struct rtsx_chip *chip);
+void try_to_switch_sdio_ctrl(struct rtsx_chip *chip);
+void do_reset_sd_card(struct rtsx_chip *chip);
+void do_reset_xd_card(struct rtsx_chip *chip);
+void do_reset_ms_card(struct rtsx_chip *chip);
+void rtsx_power_off_card(struct rtsx_chip *chip);
+void rtsx_release_cards(struct rtsx_chip *chip);
+void rtsx_reset_cards(struct rtsx_chip *chip);
+void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip);
+void rtsx_init_cards(struct rtsx_chip *chip);
+int switch_ssc_clock(struct rtsx_chip *chip, int clk);
+int switch_normal_clock(struct rtsx_chip *chip, int clk);
+int enable_card_clock(struct rtsx_chip *chip, u8 card);
+int disable_card_clock(struct rtsx_chip *chip, u8 card);
+int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt);
+void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size);
+void toggle_gpio(struct rtsx_chip *chip, u8 gpio);
+void turn_on_led(struct rtsx_chip *chip, u8 gpio);
+void turn_off_led(struct rtsx_chip *chip, u8 gpio);
+
+int card_share_mode(struct rtsx_chip *chip, int card);
+int select_card(struct rtsx_chip *chip, int card);
+int detect_card_cd(struct rtsx_chip *chip, int card);
+int check_card_exist(struct rtsx_chip *chip, unsigned int lun);
+int check_card_ready(struct rtsx_chip *chip, unsigned int lun);
+int check_card_wp(struct rtsx_chip *chip, unsigned int lun);
+int check_card_fail(struct rtsx_chip *chip, unsigned int lun);
+int check_card_ejected(struct rtsx_chip *chip, unsigned int lun);
+void eject_card(struct rtsx_chip *chip, unsigned int lun);
+u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun);
+
+static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun)
+{
+#ifdef SUPPORT_SD_LOCK
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	if ((get_lun_card(chip, lun) == SD_CARD) && (sd_card->sd_lock_status & SD_LOCKED))
+		return 0;
+	else
+		return chip->capacity[lun];
+#else
+	return chip->capacity[lun];
+#endif
+}
+
+static inline int switch_clock(struct rtsx_chip *chip, int clk)
+{
+	int retval = 0;
+
+	if (chip->asic_code)
+		retval = switch_ssc_clock(chip, clk);
+	else
+		retval = switch_normal_clock(chip, clk);
+
+	return retval;
+}
+
+int card_power_on(struct rtsx_chip *chip, u8 card);
+int card_power_off(struct rtsx_chip *chip, u8 card);
+
+static inline int card_power_off_all(struct rtsx_chip *chip)
+{
+	RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0x0F, 0x0F);
+
+	return STATUS_SUCCESS;
+}
+
+static inline void rtsx_clear_xd_error(struct rtsx_chip *chip)
+{
+	rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR, XD_STOP | XD_CLR_ERR);
+}
+
+static inline void rtsx_clear_sd_error(struct rtsx_chip *chip)
+{
+	rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
+}
+
+static inline void rtsx_clear_ms_error(struct rtsx_chip *chip)
+{
+	rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR, MS_STOP | MS_CLR_ERR);
+}
+
+static inline void rtsx_clear_spi_error(struct rtsx_chip *chip)
+{
+	rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR, SPI_STOP | SPI_CLR_ERR);
+}
+
+#ifdef SUPPORT_SDIO_ASPM
+void dynamic_configure_sdio_aspm(struct rtsx_chip *chip);
+#endif
+
+#endif  /* __REALTEK_RTSX_CARD_H */
diff --git a/drivers/staging/rts_pstor/rtsx_chip.c b/drivers/staging/rts_pstor/rtsx_chip.c
new file mode 100644
index 0000000..f443d97
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_chip.c
@@ -0,0 +1,2337 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "rtsx_chip.h"
+#include "rtsx_sys.h"
+#include "general.h"
+
+#include "sd.h"
+#include "xd.h"
+#include "ms.h"
+
+static void rtsx_calibration(struct rtsx_chip *chip)
+{
+	rtsx_write_phy_register(chip, 0x1B, 0x135E);
+	wait_timeout(10);
+	rtsx_write_phy_register(chip, 0x00, 0x0280);
+	rtsx_write_phy_register(chip, 0x01, 0x7112);
+	rtsx_write_phy_register(chip, 0x01, 0x7110);
+	rtsx_write_phy_register(chip, 0x01, 0x7112);
+	rtsx_write_phy_register(chip, 0x01, 0x7113);
+	rtsx_write_phy_register(chip, 0x00, 0x0288);
+}
+
+void rtsx_disable_card_int(struct rtsx_chip *chip)
+{
+	u32 reg = rtsx_readl(chip, RTSX_BIER);
+
+	reg &= ~(XD_INT_EN | SD_INT_EN | MS_INT_EN);
+	rtsx_writel(chip, RTSX_BIER, reg);
+}
+
+void rtsx_enable_card_int(struct rtsx_chip *chip)
+{
+	u32 reg = rtsx_readl(chip, RTSX_BIER);
+	int i;
+
+	for (i = 0; i <= chip->max_lun; i++) {
+		if (chip->lun2card[i] & XD_CARD)
+			reg |= XD_INT_EN;
+		if (chip->lun2card[i] & SD_CARD)
+			reg |= SD_INT_EN;
+		if (chip->lun2card[i] & MS_CARD)
+			reg |= MS_INT_EN;
+	}
+	if (chip->hw_bypass_sd)
+		reg &= ~((u32)SD_INT_EN);
+
+	rtsx_writel(chip, RTSX_BIER, reg);
+}
+
+void rtsx_enable_bus_int(struct rtsx_chip *chip)
+{
+	u32 reg = 0;
+#ifndef DISABLE_CARD_INT
+	int i;
+#endif
+
+	reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN;
+
+#ifndef DISABLE_CARD_INT
+	for (i = 0; i <= chip->max_lun; i++) {
+		RTSX_DEBUGP("lun2card[%d] = 0x%02x\n", i, chip->lun2card[i]);
+
+		if (chip->lun2card[i] & XD_CARD)
+			reg |= XD_INT_EN;
+		if (chip->lun2card[i] & SD_CARD)
+			reg |= SD_INT_EN;
+		if (chip->lun2card[i] & MS_CARD)
+			reg |= MS_INT_EN;
+	}
+	if (chip->hw_bypass_sd)
+		reg &= ~((u32)SD_INT_EN);
+#endif
+
+	if (chip->ic_version >= IC_VER_C)
+		reg |= DELINK_INT_EN;
+#ifdef SUPPORT_OCP
+	if (CHECK_PID(chip, 0x5209)) {
+		if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+			reg |= MS_OC_INT_EN | SD_OC_INT_EN;
+		} else {
+			reg |= SD_OC_INT_EN;
+		}
+	} else {
+		reg |= OC_INT_EN;
+	}
+#endif
+	if (!chip->adma_mode)
+		reg |= DATA_DONE_INT_EN;
+
+	/* Enable Bus Interrupt */
+	rtsx_writel(chip, RTSX_BIER, reg);
+
+	RTSX_DEBUGP("RTSX_BIER: 0x%08x\n", reg);
+}
+
+void rtsx_disable_bus_int(struct rtsx_chip *chip)
+{
+	rtsx_writel(chip, RTSX_BIER, 0);
+}
+
+static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
+{
+	if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) {
+		if (chip->asic_code) {
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
+				MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
+		} else {
+			RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, FPGA_SD_PULL_CTL_EN);
+		}
+		RTSX_WRITE_REG(chip, CARD_SHARE_MODE, 0xFF, CARD_SHARE_48_SD);
+
+		/* Enable SDIO internal clock */
+		RTSX_WRITE_REG(chip, 0xFF2C, 0x01, 0x01);
+
+		RTSX_WRITE_REG(chip, SDIO_CTRL, 0xFF, SDIO_BUS_CTRL | SDIO_CD_CTRL);
+
+		chip->sd_int = 1;
+		chip->sd_io = 1;
+	} else {
+		chip->need_reset |= SD_CARD;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+#ifdef HW_AUTO_SWITCH_SD_BUS
+static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
+{
+	u8 tmp;
+	int sw_bypass_sd = 0;
+	int retval;
+
+	if (chip->driver_first_load) {
+		if (CHECK_PID(chip, 0x5288)) {
+			RTSX_READ_REG(chip, 0xFE5A, &tmp);
+			if (tmp & 0x08)
+				sw_bypass_sd = 1;
+		} else if (CHECK_PID(chip, 0x5208)) {
+			RTSX_READ_REG(chip, 0xFE70, &tmp);
+			if (tmp & 0x80)
+				sw_bypass_sd = 1;
+		} else if (CHECK_PID(chip, 0x5209)) {
+			RTSX_READ_REG(chip, SDIO_CFG, &tmp);
+			if (tmp & SDIO_BUS_AUTO_SWITCH)
+				sw_bypass_sd = 1;
+		}
+	} else {
+		if (chip->sdio_in_charge)
+			sw_bypass_sd = 1;
+	}
+	RTSX_DEBUGP("chip->sdio_in_charge = %d\n", chip->sdio_in_charge);
+	RTSX_DEBUGP("chip->driver_first_load = %d\n", chip->driver_first_load);
+	RTSX_DEBUGP("sw_bypass_sd = %d\n", sw_bypass_sd);
+
+	if (sw_bypass_sd) {
+		u8 cd_toggle_mask = 0;
+
+		RTSX_READ_REG(chip, TLPTISTAT, &tmp);
+		if (CHECK_PID(chip, 0x5209)) {
+			cd_toggle_mask = 0x10;
+		} else {
+			cd_toggle_mask = 0x08;
+		}
+		if (tmp & cd_toggle_mask) {
+			/* Disable sdio_bus_auto_switch */
+			if (CHECK_PID(chip, 0x5288)) {
+				RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x00);
+			} else if (CHECK_PID(chip, 0x5208)) {
+				RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x00);
+			} else {
+				RTSX_WRITE_REG(chip, SDIO_CFG, SDIO_BUS_AUTO_SWITCH, 0);
+			}
+			RTSX_WRITE_REG(chip, TLPTISTAT, 0xFF, tmp);
+
+			chip->need_reset |= SD_CARD;
+		} else {
+			RTSX_DEBUGP("Chip inserted with SDIO!\n");
+
+			if (chip->asic_code) {
+				retval = sd_pull_ctl_enable(chip);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			} else {
+				RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0);
+			}
+			retval = card_share_mode(chip, SD_CARD);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			/* Enable sdio_bus_auto_switch */
+			if (CHECK_PID(chip, 0x5288)) {
+				RTSX_WRITE_REG(chip, 0xFE5A, 0x08, 0x08);
+			} else if (CHECK_PID(chip, 0x5208)) {
+				RTSX_WRITE_REG(chip, 0xFE70, 0x80, 0x80);
+			} else {
+				RTSX_WRITE_REG(chip, SDIO_CFG,
+					SDIO_BUS_AUTO_SWITCH, SDIO_BUS_AUTO_SWITCH);
+			}
+			chip->chip_insert_with_sdio = 1;
+			chip->sd_io = 1;
+		}
+	} else {
+		if (CHECK_PID(chip, 0x5209)) {
+			RTSX_WRITE_REG(chip, TLPTISTAT, 0x10, 0x10);
+		} else {
+			RTSX_WRITE_REG(chip, TLPTISTAT, 0x08, 0x08);
+		}
+		chip->need_reset |= SD_CARD;
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif
+
+int rtsx_reset_chip(struct rtsx_chip *chip)
+{
+	int retval;
+
+	rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
+
+	rtsx_disable_aspm(chip);
+
+	if (CHECK_PID(chip, 0x5209) && chip->asic_code) {
+		u16 val;
+
+		/* optimize PHY */
+		retval = rtsx_write_phy_register(chip, 0x00, 0xB966);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = rtsx_write_phy_register(chip, 0x01, 0x713F);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = rtsx_write_phy_register(chip, 0x03, 0xA549);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = rtsx_write_phy_register(chip, 0x06, 0xB235);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = rtsx_write_phy_register(chip, 0x07, 0xEF40);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = rtsx_write_phy_register(chip, 0x1E, 0xF8EB);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = rtsx_write_phy_register(chip, 0x19, 0xFE6C);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		wait_timeout(1);
+		retval = rtsx_write_phy_register(chip, 0x0A, 0x05C0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = rtsx_write_cfg_dw(chip, 1, 0x110, 0xFFFF, 0xFFFF);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = rtsx_read_phy_register(chip, 0x08, &val);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		RTSX_DEBUGP("Read from phy 0x08: 0x%04x\n", val);
+
+		if (chip->phy_voltage) {
+			chip->phy_voltage &= 0x3F;
+			RTSX_DEBUGP("chip->phy_voltage = 0x%x\n", chip->phy_voltage);
+			val &= ~0x3F;
+			val |= chip->phy_voltage;
+			RTSX_DEBUGP("Write to phy 0x08: 0x%04x\n", val);
+			retval = rtsx_write_phy_register(chip, 0x08, val);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			chip->phy_voltage = (u8)(val & 0x3F);
+			RTSX_DEBUGP("Default, chip->phy_voltage = 0x%x\n", chip->phy_voltage);
+		}
+	}
+
+	RTSX_WRITE_REG(chip, HOST_SLEEP_STATE, 0x03, 0x00);
+
+	/* Disable card clock */
+	RTSX_WRITE_REG(chip, CARD_CLK_EN, 0x1E, 0);
+
+#ifdef SUPPORT_OCP
+	/* SSC power on, OCD power on */
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, 0);
+	} else {
+		RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, MS_OC_POWER_DOWN);
+	}
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, OCPPARA1, SD_OCP_TIME_MASK | MS_OCP_TIME_MASK,
+				    SD_OCP_TIME_800 | MS_OCP_TIME_800);
+		RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK | MS_OCP_THD_MASK,
+				    chip->sd_400mA_ocp_thd | (chip->ms_ocp_thd << 4));
+		if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+			RTSX_WRITE_REG(chip, OCPGLITCH, SD_OCP_GLITCH_MASK | MS_OCP_GLITCH_MASK,
+				       SD_OCP_GLITCH_10000 | MS_OCP_GLITCH_10000);
+		} else {
+			RTSX_WRITE_REG(chip, OCPGLITCH, SD_OCP_GLITCH_MASK, SD_OCP_GLITCH_10000);
+		}
+		RTSX_WRITE_REG(chip, OCPCTL, 0xFF,
+				    SD_OCP_INT_EN | SD_DETECT_EN | MS_OCP_INT_EN | MS_DETECT_EN);
+	} else {
+		RTSX_WRITE_REG(chip, OCPPARA1, OCP_TIME_MASK, OCP_TIME_800);
+		RTSX_WRITE_REG(chip, OCPPARA2, OCP_THD_MASK, OCP_THD_244_946);
+		RTSX_WRITE_REG(chip, OCPCTL, 0xFF, CARD_OC_INT_EN | CARD_DETECT_EN);
+	}
+#else
+	/* OC power down */
+	RTSX_WRITE_REG(chip, FPDCTL, OC_POWER_DOWN, OC_POWER_DOWN);
+#endif
+
+	if (!CHECK_PID(chip, 0x5288)) {
+		RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0xFF, 0x03);
+	}
+
+	/* Turn off LED */
+	RTSX_WRITE_REG(chip, CARD_GPIO, 0xFF, 0x03);
+
+	/* Reset delink mode */
+	RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x0A, 0);
+
+	/* Card driving select */
+	RTSX_WRITE_REG(chip, CARD_DRIVE_SEL, 0xFF, chip->card_drive_sel);
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3);
+	}
+
+#ifdef LED_AUTO_BLINK
+	RTSX_WRITE_REG(chip, CARD_AUTO_BLINK, 0xFF,
+			LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
+#endif
+
+	if (chip->asic_code) {
+		/* Enable SSC Clock */
+		RTSX_WRITE_REG(chip, SSC_CTL1, 0xFF, SSC_8X_EN | SSC_SEL_4M);
+		RTSX_WRITE_REG(chip, SSC_CTL2, 0xFF, 0x12);
+	}
+
+	/* Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
+	      0xFE5B
+	      bit[1]    u_cd_rst_core_en    	rst_value = 0
+	      bit[2]    u_force_rst_core_en 	rst_value = 0
+	      bit[5]    u_mac_phy_rst_n_dbg 	rst_value = 1
+	      bit[4]	u_non_sticky_rst_n_dbg	rst_value = 0
+	*/
+	RTSX_WRITE_REG(chip, CHANGE_LINK_STATE, 0x16, 0x10);
+
+	/* Enable ASPM */
+	if (chip->aspm_l0s_l1_en) {
+		if (chip->dynamic_aspm) {
+			if (CHK_SDIO_EXIST(chip)) {
+				if (CHECK_PID(chip, 0x5209)) {
+					retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
+					if (retval != STATUS_SUCCESS) {
+						TRACE_RET(chip, STATUS_FAIL);
+					}
+				} else if (CHECK_PID(chip, 0x5288)) {
+					retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
+					if (retval != STATUS_SUCCESS) {
+						TRACE_RET(chip, STATUS_FAIL);
+					}
+				}
+			}
+		} else {
+			if (CHECK_PID(chip, 0x5208)) {
+				RTSX_WRITE_REG(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
+			}
+
+			retval = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			chip->aspm_level[0] = chip->aspm_l0s_l1_en;
+			if (CHK_SDIO_EXIST(chip)) {
+				chip->aspm_level[1] = chip->aspm_l0s_l1_en;
+				if (CHECK_PID(chip, 0x5288)) {
+					retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
+				} else {
+					retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF, chip->aspm_l0s_l1_en);
+				}
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+
+			chip->aspm_enabled = 1;
+		}
+	} else {
+		if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
+			retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+		retval = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = rtsx_write_config_byte(chip, 0x81, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_SDIO_EXIST(chip)) {
+		if (CHECK_PID(chip, 0x5288)) {
+			retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100);
+		} else {
+			retval = rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100);
+		}
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (CHECK_PID(chip, 0x5209)) {
+		retval = rtsx_write_cfg_dw(chip, 0, 0x70C, 0xFF000000, 0x5B);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (CHECK_PID(chip, 0x5288)) {
+		if (!CHK_SDIO_EXIST(chip)) {
+			retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+	}
+
+	RTSX_WRITE_REG(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
+
+	RTSX_WRITE_REG(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
+
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, PWD_SUSPEND_EN, 0xFF, 0xFF);
+		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, PWR_GATE_EN, PWR_GATE_EN);
+	}
+
+	/* Enable PCIE interrupt */
+	if (chip->asic_code) {
+		if (CHECK_PID(chip, 0x5208)) {
+			if (chip->phy_debug_mode) {
+				RTSX_WRITE_REG(chip, CDRESUMECTL, 0x77, 0);
+				rtsx_disable_bus_int(chip);
+			} else {
+				rtsx_enable_bus_int(chip);
+			}
+
+			if (chip->ic_version >= IC_VER_D) {
+				u16 reg;
+				retval = rtsx_read_phy_register(chip, 0x00, &reg);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				reg &= 0xFE7F;
+				reg |= 0x80;
+				retval = rtsx_write_phy_register(chip, 0x00, reg);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				retval = rtsx_read_phy_register(chip, 0x1C, &reg);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				reg &= 0xFFF7;
+				retval = rtsx_write_phy_register(chip, 0x1C, reg);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+
+			if (chip->driver_first_load && (chip->ic_version < IC_VER_C)) {
+				rtsx_calibration(chip);
+			}
+		} else {
+			rtsx_enable_bus_int(chip);
+		}
+	} else {
+		rtsx_enable_bus_int(chip);
+	}
+
+#ifdef HW_INT_WRITE_CLR
+	if (CHECK_PID(chip, 0x5209)) {
+		/* Set interrupt write clear */
+		RTSX_WRITE_REG(chip, NFTS_TX_CTRL, 0x02, 0);
+	}
+#endif
+
+	chip->need_reset = 0;
+
+	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
+#ifdef HW_INT_WRITE_CLR
+	if (CHECK_PID(chip, 0x5209)) {
+		/* Clear interrupt flag */
+		rtsx_writel(chip, RTSX_BIPR, chip->int_reg);
+	}
+#endif
+	if (chip->hw_bypass_sd)
+		goto NextCard;
+	RTSX_DEBUGP("In rtsx_reset_chip, chip->int_reg = 0x%x\n", chip->int_reg);
+	if (chip->int_reg & SD_EXIST) {
+#ifdef HW_AUTO_SWITCH_SD_BUS
+		if (CHECK_PID(chip, 0x5208) && (chip->ic_version < IC_VER_C)) {
+			retval = rtsx_pre_handle_sdio_old(chip);
+		} else {
+			retval = rtsx_pre_handle_sdio_new(chip);
+		}
+		RTSX_DEBUGP("chip->need_reset = 0x%x (rtsx_reset_chip)\n", (unsigned int)(chip->need_reset));
+#else  /* HW_AUTO_SWITCH_SD_BUS */
+		retval = rtsx_pre_handle_sdio_old(chip);
+#endif  /* HW_AUTO_SWITCH_SD_BUS */
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		chip->sd_io = 0;
+		RTSX_WRITE_REG(chip, SDIO_CTRL, SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
+	}
+
+NextCard:
+	if (chip->int_reg & XD_EXIST)
+		chip->need_reset |= XD_CARD;
+	if (chip->int_reg & MS_EXIST)
+		chip->need_reset |= MS_CARD;
+	if (chip->int_reg & CARD_EXIST) {
+		RTSX_WRITE_REG(chip, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+	}
+
+	RTSX_DEBUGP("In rtsx_init_chip, chip->need_reset = 0x%x\n", (unsigned int)(chip->need_reset));
+
+	RTSX_WRITE_REG(chip, RCCTL, 0x01, 0x00);
+
+	if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
+		/* Turn off main power when entering S3/S4 state */
+		RTSX_WRITE_REG(chip, MAIN_PWR_OFF_CTL, 0x03, 0x03);
+	}
+
+	if (chip->remote_wakeup_en && !chip->auto_delink_en) {
+		RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x07);
+		if (chip->aux_pwr_exist) {
+			RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x33);
+		}
+	} else {
+		RTSX_WRITE_REG(chip, WAKE_SEL_CTL, 0x07, 0x04);
+		RTSX_WRITE_REG(chip, PME_FORCE_CTL, 0xFF, 0x30);
+	}
+
+	if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
+		RTSX_WRITE_REG(chip, PETXCFG, 0x1C, 0x14);
+	} else if (CHECK_PID(chip, 0x5209)) {
+		if (chip->force_clkreq_0) {
+			RTSX_WRITE_REG(chip, PETXCFG, 0x08, 0x08);
+		} else {
+			RTSX_WRITE_REG(chip, PETXCFG, 0x08, 0x00);
+		}
+	}
+
+	if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
+		retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (chip->ft2_fast_mode) {
+		RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF, MS_PARTIAL_POWER_ON | SD_PARTIAL_POWER_ON);
+		udelay(chip->pmos_pwr_on_interval);
+		RTSX_WRITE_REG(chip, CARD_PWR_CTL, 0xFF, MS_POWER_ON | SD_POWER_ON);
+
+		wait_timeout(200);
+	}
+
+	/* Reset card */
+	rtsx_reset_detected_cards(chip, 0);
+
+	chip->driver_first_load = 0;
+
+	return STATUS_SUCCESS;
+}
+
+static inline int check_sd_speed_prior(u32 sd_speed_prior)
+{
+	int i, fake_para = 0;
+
+	for (i = 0; i < 4; i++) {
+		u8 tmp = (u8)(sd_speed_prior >> (i*8));
+		if ((tmp < 0x01) || (tmp > 0x04)) {
+			fake_para = 1;
+			break;
+		}
+	}
+
+	return !fake_para;
+}
+
+static inline int check_sd_current_prior(u32 sd_current_prior)
+{
+	int i, fake_para = 0;
+
+	for (i = 0; i < 4; i++) {
+		u8 tmp = (u8)(sd_current_prior >> (i*8));
+		if (tmp > 0x03) {
+			fake_para = 1;
+			break;
+		}
+	}
+
+	return !fake_para;
+}
+
+static int rts5209_init(struct rtsx_chip *chip)
+{
+	int retval;
+	u32 lval = 0;
+	u8 val = 0;
+
+	val = rtsx_readb(chip, 0x1C);
+	if ((val & 0x10) == 0) {
+		chip->asic_code = 1;
+	} else {
+		chip->asic_code = 0;
+	}
+
+	chip->ic_version = val & 0x0F;
+	chip->phy_debug_mode = 0;
+
+	chip->aux_pwr_exist = 0;
+
+	chip->ms_power_class_en = 0x03;
+
+	retval = rtsx_read_cfg_dw(chip, 0, 0x724, &lval);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	RTSX_DEBUGP("dw in 0x724: 0x%x\n", lval);
+	val = (u8)lval;
+	if (!(val & 0x80)) {
+		if (val & 0x04) {
+			SET_SDIO_EXIST(chip);
+		} else {
+			CLR_SDIO_EXIST(chip);
+		}
+
+		if (val & 0x02) {
+			chip->hw_bypass_sd = 0;
+		} else {
+			chip->hw_bypass_sd = 1;
+		}
+	} else {
+		SET_SDIO_EXIST(chip);
+		chip->hw_bypass_sd = 0;
+	}
+
+	if (chip->use_hw_setting) {
+		u8 clk;
+
+		chip->aspm_l0s_l1_en = (val >> 5) & 0x03;
+
+		if (val & 0x08) {
+			chip->lun_mode = DEFAULT_SINGLE;
+		} else {
+			chip->lun_mode = SD_MS_2LUN;
+		}
+
+		val = (u8)(lval >> 8);
+
+		clk = (val >> 5) & 0x07;
+		if (clk != 0x07) {
+			chip->asic_sd_sdr50_clk = 98 - clk * 2;
+		}
+
+		if (val & 0x10) {
+			chip->auto_delink_en = 1;
+		} else {
+			chip->auto_delink_en = 0;
+		}
+
+		if (chip->ss_en == 2) {
+			chip->ss_en = 0;
+		} else {
+			if (val & 0x08) {
+				chip->ss_en = 1;
+			} else {
+				chip->ss_en = 0;
+			}
+		}
+
+		clk = val & 0x07;
+		if (clk != 0x07)
+			chip->asic_ms_hg_clk = (59 - clk) * 2;
+
+		val = (u8)(lval >> 16);
+
+		clk = (val >> 6) & 0x03;
+		if (clk != 0x03) {
+			chip->asic_sd_hs_clk = (49 - clk * 2) * 2;
+			chip->asic_mmc_52m_clk = (49 - clk * 2) * 2;
+		}
+
+		clk = (val >> 4) & 0x03;
+		if (clk != 0x03)
+			chip->asic_sd_ddr50_clk = (48 - clk * 2) * 2;
+
+		if (val & 0x01) {
+			chip->sdr104_en = 1;
+		} else {
+			chip->sdr104_en = 0;
+		}
+		if (val & 0x02) {
+			chip->ddr50_en = 1;
+		} else {
+			chip->ddr50_en = 0;
+		}
+		if (val & 0x04) {
+			chip->sdr50_en = 1;
+		} else {
+			chip->sdr50_en = 0;
+		}
+
+		val = (u8)(lval >> 24);
+
+		clk = (val >> 5) & 0x07;
+		if (clk != 0x07)
+			chip->asic_sd_sdr104_clk = 206 - clk * 3;
+
+		if (val & 0x10) {
+			chip->power_down_in_ss = 1;
+		} else {
+			chip->power_down_in_ss = 0;
+		}
+
+		chip->ms_power_class_en = val & 0x03;
+	}
+
+	if (chip->hp_watch_bios_hotplug && chip->auto_delink_en) {
+		u8 reg58, reg5b;
+
+		retval = rtsx_read_pci_cfg_byte(0x00,
+						0x1C, 0x02, 0x58, &reg58);
+		if (retval < 0) {
+			return STATUS_SUCCESS;
+		}
+		retval = rtsx_read_pci_cfg_byte(0x00,
+						0x1C, 0x02, 0x5B, &reg5b);
+		if (retval < 0) {
+			return STATUS_SUCCESS;
+		}
+
+		RTSX_DEBUGP("reg58 = 0x%x, reg5b = 0x%x\n", reg58, reg5b);
+
+		if ((reg58 == 0x00) && (reg5b == 0x01)) {
+			chip->auto_delink_en = 0;
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int rts5208_init(struct rtsx_chip *chip)
+{
+	int retval;
+	u16 reg = 0;
+	u8 val = 0;
+
+	RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03);
+	RTSX_READ_REG(chip, CLK_SEL, &val);
+	if (val == 0) {
+		chip->asic_code = 1;
+	} else {
+		chip->asic_code = 0;
+	}
+
+	if (chip->asic_code) {
+		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		RTSX_DEBUGP("Value of phy register 0x1C is 0x%x\n", reg);
+		chip->ic_version = (reg >> 4) & 0x07;
+		if (reg & PHY_DEBUG_MODE) {
+			chip->phy_debug_mode = 1;
+		} else {
+			chip->phy_debug_mode = 0;
+		}
+	} else {
+		RTSX_READ_REG(chip, 0xFE80, &val);
+		chip->ic_version = val;
+		chip->phy_debug_mode = 0;
+	}
+
+	RTSX_READ_REG(chip, PDINFO, &val);
+	RTSX_DEBUGP("PDINFO: 0x%x\n", val);
+	if (val & AUX_PWR_DETECTED) {
+		chip->aux_pwr_exist = 1;
+	} else {
+		chip->aux_pwr_exist = 0;
+	}
+
+	RTSX_READ_REG(chip, 0xFE50, &val);
+	if (val & 0x01) {
+		chip->hw_bypass_sd = 1;
+	} else {
+		chip->hw_bypass_sd = 0;
+	}
+
+	rtsx_read_config_byte(chip, 0x0E, &val);
+	if (val & 0x80) {
+		SET_SDIO_EXIST(chip);
+	} else {
+		CLR_SDIO_EXIST(chip);
+	}
+
+	if (chip->use_hw_setting) {
+		RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val);
+		if (val & 0x80) {
+			chip->auto_delink_en = 1;
+		} else {
+			chip->auto_delink_en = 0;
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int rts5288_init(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 val = 0, max_func;
+	u32 lval = 0;
+
+	RTSX_WRITE_REG(chip, CLK_SEL, 0x03, 0x03);
+	RTSX_READ_REG(chip, CLK_SEL, &val);
+	if (val == 0) {
+		chip->asic_code = 1;
+	} else {
+		chip->asic_code = 0;
+	}
+
+	chip->ic_version = 0;
+	chip->phy_debug_mode = 0;
+
+	RTSX_READ_REG(chip, PDINFO, &val);
+	RTSX_DEBUGP("PDINFO: 0x%x\n", val);
+	if (val & AUX_PWR_DETECTED) {
+		chip->aux_pwr_exist = 1;
+	} else {
+		chip->aux_pwr_exist = 0;
+	}
+
+	RTSX_READ_REG(chip, CARD_SHARE_MODE, &val);
+	RTSX_DEBUGP("CARD_SHARE_MODE: 0x%x\n", val);
+	if (val & 0x04) {
+		chip->baro_pkg = QFN;
+	} else {
+		chip->baro_pkg = LQFP;
+	}
+
+	RTSX_READ_REG(chip, 0xFE5A, &val);
+	if (val & 0x10) {
+		chip->hw_bypass_sd = 1;
+	} else {
+		chip->hw_bypass_sd = 0;
+	}
+
+	retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	max_func = (u8)((lval >> 29) & 0x07);
+	RTSX_DEBUGP("Max function number: %d\n", max_func);
+	if (max_func == 0x02) {
+		SET_SDIO_EXIST(chip);
+	} else {
+		CLR_SDIO_EXIST(chip);
+	}
+
+	if (chip->use_hw_setting) {
+		RTSX_READ_REG(chip, CHANGE_LINK_STATE, &val);
+		if (val & 0x80) {
+			chip->auto_delink_en = 1;
+		} else {
+			chip->auto_delink_en = 0;
+		}
+
+		if (CHECK_BARO_PKG(chip, LQFP)) {
+			chip->lun_mode = SD_MS_1LUN;
+		} else {
+			chip->lun_mode = DEFAULT_SINGLE;
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_init_chip(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct ms_info *ms_card = &(chip->ms_card);
+	int retval;
+	unsigned int i;
+
+	RTSX_DEBUGP("Vendor ID: 0x%04x, Product ID: 0x%04x\n",
+		     chip->vendor_id, chip->product_id);
+
+	chip->ic_version = 0;
+
+#ifdef _MSG_TRACE
+	chip->msg_idx = 0;
+#endif
+
+	memset(xd_card, 0, sizeof(struct xd_info));
+	memset(sd_card, 0, sizeof(struct sd_info));
+	memset(ms_card, 0, sizeof(struct ms_info));
+
+	chip->xd_reset_counter = 0;
+	chip->sd_reset_counter = 0;
+	chip->ms_reset_counter = 0;
+
+	chip->xd_show_cnt = MAX_SHOW_CNT;
+	chip->sd_show_cnt = MAX_SHOW_CNT;
+	chip->ms_show_cnt = MAX_SHOW_CNT;
+
+	chip->sd_io = 0;
+	chip->auto_delink_cnt = 0;
+	chip->auto_delink_allowed = 1;
+	rtsx_set_stat(chip, RTSX_STAT_INIT);
+
+	chip->aspm_enabled = 0;
+	chip->chip_insert_with_sdio = 0;
+	chip->sdio_aspm = 0;
+	chip->sdio_idle = 0;
+	chip->sdio_counter = 0;
+	chip->cur_card = 0;
+	chip->phy_debug_mode = 0;
+	chip->sdio_func_exist = 0;
+	memset(chip->sdio_raw_data, 0, 12);
+
+	for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) {
+		set_sense_type(chip, i, SENSE_TYPE_NO_SENSE);
+		chip->rw_fail_cnt[i] = 0;
+	}
+
+	if (!check_sd_speed_prior(chip->sd_speed_prior)) {
+		chip->sd_speed_prior = 0x01040203;
+	}
+	RTSX_DEBUGP("sd_speed_prior = 0x%08x\n", chip->sd_speed_prior);
+
+	if (!check_sd_current_prior(chip->sd_current_prior)) {
+		chip->sd_current_prior = 0x00010203;
+	}
+	RTSX_DEBUGP("sd_current_prior = 0x%08x\n", chip->sd_current_prior);
+
+	if ((chip->sd_ddr_tx_phase > 31) || (chip->sd_ddr_tx_phase < 0)) {
+		chip->sd_ddr_tx_phase = 0;
+	}
+	if ((chip->mmc_ddr_tx_phase > 31) || (chip->mmc_ddr_tx_phase < 0)) {
+		chip->mmc_ddr_tx_phase = 0;
+	}
+
+	RTSX_WRITE_REG(chip, FPDCTL, SSC_POWER_DOWN, 0);
+	wait_timeout(200);
+	RTSX_WRITE_REG(chip, CLK_DIV, 0x07, 0x07);
+	RTSX_DEBUGP("chip->use_hw_setting = %d\n", chip->use_hw_setting);
+
+	if (CHECK_PID(chip, 0x5209)) {
+		retval = rts5209_init(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else if (CHECK_PID(chip, 0x5208)) {
+		retval = rts5208_init(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else if (CHECK_PID(chip, 0x5288)) {
+		retval = rts5288_init(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (chip->ss_en == 2) {
+		chip->ss_en = 0;
+	}
+
+	RTSX_DEBUGP("chip->asic_code = %d\n", chip->asic_code);
+	RTSX_DEBUGP("chip->ic_version = 0x%x\n", chip->ic_version);
+	RTSX_DEBUGP("chip->phy_debug_mode = %d\n", chip->phy_debug_mode);
+	RTSX_DEBUGP("chip->aux_pwr_exist = %d\n", chip->aux_pwr_exist);
+	RTSX_DEBUGP("chip->sdio_func_exist = %d\n", chip->sdio_func_exist);
+	RTSX_DEBUGP("chip->hw_bypass_sd = %d\n", chip->hw_bypass_sd);
+	RTSX_DEBUGP("chip->aspm_l0s_l1_en = %d\n", chip->aspm_l0s_l1_en);
+	RTSX_DEBUGP("chip->lun_mode = %d\n", chip->lun_mode);
+	RTSX_DEBUGP("chip->auto_delink_en = %d\n", chip->auto_delink_en);
+	RTSX_DEBUGP("chip->ss_en = %d\n", chip->ss_en);
+	RTSX_DEBUGP("chip->baro_pkg = %d\n", chip->baro_pkg);
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		chip->card2lun[SD_CARD] = 0;
+		chip->card2lun[MS_CARD] = 1;
+		chip->card2lun[XD_CARD] = 0xFF;
+		chip->lun2card[0] = SD_CARD;
+		chip->lun2card[1] = MS_CARD;
+		chip->max_lun = 1;
+		SET_SDIO_IGNORED(chip);
+	} else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
+		chip->card2lun[SD_CARD] = 0;
+		chip->card2lun[MS_CARD] = 0;
+		chip->card2lun[XD_CARD] = 0xFF;
+		chip->lun2card[0] = SD_CARD | MS_CARD;
+		chip->max_lun = 0;
+	} else {
+		chip->card2lun[XD_CARD] = 0;
+		chip->card2lun[SD_CARD] = 0;
+		chip->card2lun[MS_CARD] = 0;
+		chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
+		chip->max_lun = 0;
+	}
+
+	retval = rtsx_reset_chip(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+void rtsx_release_chip(struct rtsx_chip *chip)
+{
+	xd_free_l2p_tbl(chip);
+	ms_free_l2p_tbl(chip);
+	chip->card_exist = 0;
+	chip->card_ready = 0;
+}
+
+#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
+static inline void rtsx_blink_led(struct rtsx_chip *chip)
+{
+	if (chip->card_exist && chip->blink_led) {
+		if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) {
+			chip->led_toggle_counter++;
+		} else {
+			chip->led_toggle_counter = 0;
+			toggle_gpio(chip, LED_GPIO);
+		}
+	}
+}
+#endif
+
+static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
+{
+	int maybe_support_aspm, reg_changed;
+	u32 tmp = 0;
+	u8 reg0 = 0, reg1 = 0;
+
+	maybe_support_aspm = 0;
+	reg_changed = 0;
+	rtsx_read_config_byte(chip, LCTLR, &reg0);
+	if (chip->aspm_level[0] != reg0) {
+		reg_changed = 1;
+		chip->aspm_level[0] = reg0;
+	}
+	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
+		rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
+		reg1 = (u8)tmp;
+		if (chip->aspm_level[1] != reg1) {
+			reg_changed = 1;
+			chip->aspm_level[1] = reg1;
+		}
+
+		if ((reg0 & 0x03) && (reg1 & 0x03)) {
+			maybe_support_aspm = 1;
+		}
+	} else {
+		if (reg0 & 0x03) {
+			maybe_support_aspm = 1;
+		}
+	}
+
+	if (reg_changed) {
+		if (maybe_support_aspm) {
+			chip->aspm_l0s_l1_en = 0x03;
+		}
+		RTSX_DEBUGP("aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n",
+			      chip->aspm_level[0], chip->aspm_level[1]);
+
+		if (chip->aspm_l0s_l1_en) {
+			chip->aspm_enabled = 1;
+		} else {
+			chip->aspm_enabled = 0;
+			chip->sdio_aspm = 0;
+		}
+		rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF,
+			0x30 | chip->aspm_level[0] | (chip->aspm_level[1] << 2));
+	}
+}
+
+void rtsx_polling_func(struct rtsx_chip *chip)
+{
+#ifdef SUPPORT_SD_LOCK
+	struct sd_info *sd_card = &(chip->sd_card);
+#endif
+	int ss_allowed;
+
+	if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
+		return;
+
+	if (rtsx_chk_stat(chip, RTSX_STAT_DELINK))
+		goto Delink_Stage;
+
+	if (chip->polling_config) {
+		u8 val;
+		rtsx_read_config_byte(chip, 0, &val);
+	}
+
+	if (rtsx_chk_stat(chip, RTSX_STAT_SS))
+		return;
+
+#ifdef SUPPORT_OCP
+	if (chip->ocp_int) {
+		rtsx_read_register(chip, OCPSTAT, &(chip->ocp_stat));
+
+		if (CHECK_PID(chip, 0x5209) &&
+				CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+			if (chip->ocp_int & SD_OC_INT)
+				sd_power_off_card3v3(chip);
+			if (chip->ocp_int & MS_OC_INT)
+				ms_power_off_card3v3(chip);
+		} else {
+			if (chip->card_exist & SD_CARD) {
+				sd_power_off_card3v3(chip);
+			} else if (chip->card_exist & MS_CARD) {
+				ms_power_off_card3v3(chip);
+			} else if (chip->card_exist & XD_CARD) {
+				xd_power_off_card3v3(chip);
+			}
+		}
+
+		chip->ocp_int = 0;
+	}
+#endif
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_erase_status) {
+		if (chip->card_exist & SD_CARD) {
+			u8 val;
+			if (CHECK_PID(chip, 0x5209)) {
+				rtsx_read_register(chip, SD_BUS_STAT, &val);
+				if (val & SD_DAT0_STATUS) {
+					sd_card->sd_erase_status = SD_NOT_ERASE;
+					sd_card->sd_lock_notify = 1;
+					chip->need_reinit |= SD_CARD;
+				}
+			} else {
+				rtsx_read_register(chip, 0xFD30, &val);
+				if (val & 0x02) {
+					sd_card->sd_erase_status = SD_NOT_ERASE;
+					sd_card->sd_lock_notify = 1;
+					chip->need_reinit |= SD_CARD;
+				}
+			}
+		} else {
+			sd_card->sd_erase_status = SD_NOT_ERASE;
+		}
+	}
+#endif
+
+	rtsx_init_cards(chip);
+
+	if (chip->ss_en) {
+		ss_allowed = 1;
+
+		if (CHECK_PID(chip, 0x5288)) {
+			ss_allowed = 0;
+		} else {
+			if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
+				u32 val;
+				rtsx_read_cfg_dw(chip, 1, 0x04, &val);
+				if (val & 0x07) {
+					ss_allowed = 0;
+				}
+			}
+		}
+	} else {
+		ss_allowed = 0;
+	}
+
+	if (ss_allowed && !chip->sd_io) {
+		if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
+			chip->ss_counter = 0;
+		} else {
+			if (chip->ss_counter <
+				(chip->ss_idle_period / POLLING_INTERVAL)) {
+				chip->ss_counter++;
+			} else {
+				rtsx_exclusive_enter_ss(chip);
+				return;
+			}
+		}
+	}
+
+	if (CHECK_PID(chip, 0x5208)) {
+		rtsx_monitor_aspm_config(chip);
+
+#ifdef SUPPORT_SDIO_ASPM
+		if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) &&
+				chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
+			if (chip->sd_io) {
+				dynamic_configure_sdio_aspm(chip);
+			} else {
+				if (!chip->sdio_aspm) {
+					RTSX_DEBUGP("SDIO enter ASPM!\n");
+					rtsx_write_register(chip,
+						ASPM_FORCE_CTL, 0xFC,
+						0x30 | (chip->aspm_level[1] << 2));
+					chip->sdio_aspm = 1;
+				}
+			}
+		}
+#endif
+	}
+
+	if (chip->idle_counter < IDLE_MAX_COUNT) {
+		chip->idle_counter++;
+	} else {
+		if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
+			RTSX_DEBUGP("Idle state!\n");
+			rtsx_set_stat(chip, RTSX_STAT_IDLE);
+
+#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
+			chip->led_toggle_counter = 0;
+#endif
+			rtsx_force_power_on(chip, SSC_PDCTL);
+
+			turn_off_led(chip, LED_GPIO);
+
+			if (chip->auto_power_down && !chip->card_ready && !chip->sd_io) {
+				rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
+			}
+		}
+	}
+
+	switch (rtsx_get_stat(chip)) {
+	case RTSX_STAT_RUN:
+#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
+		rtsx_blink_led(chip);
+#endif
+		do_remaining_work(chip);
+		break;
+
+	case RTSX_STAT_IDLE:
+		if (chip->sd_io && !chip->sd_int) {
+			try_to_switch_sdio_ctrl(chip);
+		}
+		rtsx_enable_aspm(chip);
+		break;
+
+	default:
+		break;
+	}
+
+
+#ifdef SUPPORT_OCP
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		#if CONFIG_RTS_PSTOR_DEBUG
+		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER)) {
+			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
+		}
+		#endif
+
+		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+			if (chip->card_exist & SD_CARD) {
+				rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
+				card_power_off(chip, SD_CARD);
+				chip->card_fail |= SD_CARD;
+			}
+		}
+		if (chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER)) {
+			if (chip->card_exist & MS_CARD) {
+				rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
+				card_power_off(chip, MS_CARD);
+				chip->card_fail |= MS_CARD;
+			}
+		}
+	} else {
+		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
+			if (chip->card_exist & SD_CARD) {
+				rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
+				chip->card_fail |= SD_CARD;
+			} else if (chip->card_exist & MS_CARD) {
+				rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
+				chip->card_fail |= MS_CARD;
+			} else if (chip->card_exist & XD_CARD) {
+				rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
+				chip->card_fail |= XD_CARD;
+			}
+			card_power_off(chip, SD_CARD);
+		}
+	}
+#endif
+
+Delink_Stage:
+	if (chip->auto_delink_en && chip->auto_delink_allowed &&
+			!chip->card_ready && !chip->card_ejected && !chip->sd_io) {
+		int enter_L1 = chip->auto_delink_in_L1 && (chip->aspm_l0s_l1_en || chip->ss_en);
+		int delink_stage1_cnt = chip->delink_stage1_step;
+		int delink_stage2_cnt = delink_stage1_cnt + chip->delink_stage2_step;
+		int delink_stage3_cnt = delink_stage2_cnt + chip->delink_stage3_step;
+
+		if (chip->auto_delink_cnt <= delink_stage3_cnt) {
+			if (chip->auto_delink_cnt == delink_stage1_cnt) {
+				rtsx_set_stat(chip, RTSX_STAT_DELINK);
+
+				if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
+					rtsx_set_phy_reg_bit(chip, 0x1C, 2);
+				}
+				if (chip->card_exist) {
+					RTSX_DEBUGP("False card inserted, do force delink\n");
+
+					if (enter_L1) {
+						rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
+					}
+					rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
+
+					if (enter_L1) {
+						rtsx_enter_L1(chip);
+					}
+
+					chip->auto_delink_cnt = delink_stage3_cnt + 1;
+				} else {
+					RTSX_DEBUGP("No card inserted, do delink\n");
+
+					if (enter_L1) {
+						rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
+					}
+#ifdef HW_INT_WRITE_CLR
+					if (CHECK_PID(chip, 0x5209)) {
+						rtsx_writel(chip, RTSX_BIPR, 0xFFFFFFFF);
+						RTSX_DEBUGP("RTSX_BIPR: 0x%x\n", rtsx_readl(chip, RTSX_BIPR));
+					}
+#endif
+					rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0x02);
+
+					if (enter_L1) {
+						rtsx_enter_L1(chip);
+					}
+				}
+			}
+
+			if (chip->auto_delink_cnt == delink_stage2_cnt) {
+				RTSX_DEBUGP("Try to do force delink\n");
+
+				if (enter_L1) {
+					rtsx_exit_L1(chip);
+				}
+
+				if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
+					rtsx_set_phy_reg_bit(chip, 0x1C, 2);
+				}
+				rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
+			}
+
+			chip->auto_delink_cnt++;
+		}
+	} else {
+		chip->auto_delink_cnt = 0;
+	}
+}
+
+void rtsx_undo_delink(struct rtsx_chip *chip)
+{
+	chip->auto_delink_allowed = 0;
+	rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x00);
+}
+
+/**
+ * rtsx_stop_cmd - stop command transfer and DMA transfer
+ * @chip: Realtek's card reader chip
+ * @card: flash card type
+ *
+ * Stop command transfer and DMA transfer.
+ * This function is called in error handler.
+ */
+void rtsx_stop_cmd(struct rtsx_chip *chip, int card)
+{
+	int i;
+
+	for (i = 0; i <= 8; i++) {
+		int addr = RTSX_HCBAR + i * 4;
+		u32 reg;
+		reg = rtsx_readl(chip, addr);
+		RTSX_DEBUGP("BAR (0x%02x): 0x%08x\n", addr, reg);
+	}
+	rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD);
+	rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA);
+
+	for (i = 0; i < 16; i++) {
+		u16 addr = 0xFE20 + (u16)i;
+		u8 val;
+		rtsx_read_register(chip, addr, &val);
+		RTSX_DEBUGP("0x%04X: 0x%02x\n", addr, val);
+	}
+
+	rtsx_write_register(chip, DMACTL, 0x80, 0x80);
+	rtsx_write_register(chip, RBCTL, 0x80, 0x80);
+}
+
+#define MAX_RW_REG_CNT		1024
+
+int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
+{
+	int i;
+	u32 val = 3 << 30;
+
+	val |= (u32)(addr & 0x3FFF) << 16;
+	val |= (u32)mask << 8;
+	val |= (u32)data;
+
+	rtsx_writel(chip, RTSX_HAIMR, val);
+
+	for (i = 0; i < MAX_RW_REG_CNT; i++) {
+		val = rtsx_readl(chip, RTSX_HAIMR);
+		if ((val & (1 << 31)) == 0) {
+			if (data != (u8)val) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			return STATUS_SUCCESS;
+		}
+	}
+
+	TRACE_RET(chip, STATUS_TIMEDOUT);
+}
+
+int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
+{
+	u32 val = 2 << 30;
+	int i;
+
+	if (data) {
+		*data = 0;
+	}
+
+	val |= (u32)(addr & 0x3FFF) << 16;
+
+	rtsx_writel(chip, RTSX_HAIMR, val);
+
+	for (i = 0; i < MAX_RW_REG_CNT; i++) {
+		val = rtsx_readl(chip, RTSX_HAIMR);
+		if ((val & (1 << 31)) == 0) {
+			break;
+		}
+	}
+
+	if (i >= MAX_RW_REG_CNT) {
+		TRACE_RET(chip, STATUS_TIMEDOUT);
+	}
+
+	if (data) {
+		*data = (u8)(val & 0xFF);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, u32 val)
+{
+	u8 mode = 0, tmp;
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		if (mask & 0xFF) {
+			RTSX_WRITE_REG(chip, CFGDATA0 + i,
+				       0xFF, (u8)(val & mask & 0xFF));
+			mode |= (1 << i);
+		}
+		mask >>= 8;
+		val >>= 8;
+	}
+
+	if (mode) {
+		RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr);
+		RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
+
+		RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF,
+			       0x80 | mode | ((func_no & 0x03) << 4));
+
+		for (i = 0; i < MAX_RW_REG_CNT; i++) {
+			RTSX_READ_REG(chip, CFGRWCTL, &tmp);
+			if ((tmp & 0x80) == 0) {
+				break;
+			}
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
+{
+	int i;
+	u8 tmp;
+	u32 data = 0;
+
+	RTSX_WRITE_REG(chip, CFGADDR0, 0xFF, (u8)addr);
+	RTSX_WRITE_REG(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
+	RTSX_WRITE_REG(chip, CFGRWCTL, 0xFF, 0x80 | ((func_no & 0x03) << 4));
+
+	for (i = 0; i < MAX_RW_REG_CNT; i++) {
+		RTSX_READ_REG(chip, CFGRWCTL, &tmp);
+		if ((tmp & 0x80) == 0) {
+			break;
+		}
+	}
+
+	for (i = 0; i < 4; i++) {
+		RTSX_READ_REG(chip, CFGDATA0 + i, &tmp);
+		data |= (u32)tmp << (i * 8);
+	}
+
+	if (val) {
+		*val = data;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len)
+{
+	u32 *data, *mask;
+	u16 offset = addr % 4;
+	u16 aligned_addr = addr - offset;
+	int dw_len, i, j;
+	int retval;
+
+	RTSX_DEBUGP("%s\n", __func__);
+
+	if (!buf) {
+		TRACE_RET(chip, STATUS_NOMEM);
+	}
+
+	if ((len + offset) % 4) {
+		dw_len = (len + offset) / 4 + 1;
+	} else {
+		dw_len = (len + offset) / 4;
+	}
+	RTSX_DEBUGP("dw_len = %d\n", dw_len);
+
+	data = (u32 *)vmalloc(dw_len * 4);
+	if (!data) {
+		TRACE_RET(chip, STATUS_NOMEM);
+	}
+	memset(data, 0, dw_len * 4);
+
+	mask = (u32 *)vmalloc(dw_len * 4);
+	if (!mask) {
+		vfree(data);
+		TRACE_RET(chip, STATUS_NOMEM);
+	}
+	memset(mask, 0, dw_len * 4);
+
+	j = 0;
+	for (i = 0; i < len; i++) {
+		mask[j] |= 0xFF << (offset * 8);
+		data[j] |= buf[i] << (offset * 8);
+		if (++offset == 4) {
+			j++;
+			offset = 0;
+		}
+	}
+
+	RTSX_DUMP(mask, dw_len * 4);
+	RTSX_DUMP(data, dw_len * 4);
+
+	for (i = 0; i < dw_len; i++) {
+		retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4, mask[i], data[i]);
+		if (retval != STATUS_SUCCESS) {
+			vfree(data);
+			vfree(mask);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	vfree(data);
+	vfree(mask);
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len)
+{
+	u32 *data;
+	u16 offset = addr % 4;
+	u16 aligned_addr = addr - offset;
+	int dw_len, i, j;
+	int retval;
+
+	RTSX_DEBUGP("%s\n", __func__);
+
+	if ((len + offset) % 4) {
+		dw_len = (len + offset) / 4 + 1;
+	} else {
+		dw_len = (len + offset) / 4;
+	}
+	RTSX_DEBUGP("dw_len = %d\n", dw_len);
+
+	data = (u32 *)vmalloc(dw_len * 4);
+	if (!data) {
+		TRACE_RET(chip, STATUS_NOMEM);
+	}
+
+	for (i = 0; i < dw_len; i++) {
+		retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4, data + i);
+		if (retval != STATUS_SUCCESS) {
+			vfree(data);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (buf) {
+		j = 0;
+
+		for (i = 0; i < len; i++) {
+			buf[i] = (u8)(data[j] >> (offset * 8));
+			if (++offset == 4) {
+				j++;
+				offset = 0;
+			}
+		}
+	}
+
+	vfree(data);
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
+{
+	int i, finished = 0;
+	u8 tmp;
+
+	RTSX_WRITE_REG(chip, PHYDATA0, 0xFF, (u8)val);
+	RTSX_WRITE_REG(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
+	RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr);
+	RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x81);
+
+	for (i = 0; i < 100000; i++) {
+		RTSX_READ_REG(chip, PHYRWCTL, &tmp);
+		if (!(tmp & 0x80)) {
+			finished = 1;
+			break;
+		}
+	}
+
+	if (!finished) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
+{
+	int i, finished = 0;
+	u16 data = 0;
+	u8 tmp;
+
+	RTSX_WRITE_REG(chip, PHYADDR, 0xFF, addr);
+	RTSX_WRITE_REG(chip, PHYRWCTL, 0xFF, 0x80);
+
+	for (i = 0; i < 100000; i++) {
+		RTSX_READ_REG(chip, PHYRWCTL, &tmp);
+		if (!(tmp & 0x80)) {
+			finished = 1;
+			break;
+		}
+	}
+
+	if (!finished) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, PHYDATA0, &tmp);
+	data = tmp;
+	RTSX_READ_REG(chip, PHYDATA1, &tmp);
+	data |= (u16)tmp << 8;
+
+	if (val)
+		*val = data;
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
+{
+	int i;
+	u8 data = 0;
+
+	RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0x80|addr);
+
+	for (i = 0; i < 100; i++) {
+		RTSX_READ_REG(chip, EFUSE_CTRL, &data);
+		if (!(data & 0x80))
+			break;
+		udelay(1);
+	}
+
+	if (data & 0x80) {
+		TRACE_RET(chip, STATUS_TIMEDOUT);
+	}
+
+	RTSX_READ_REG(chip, EFUSE_DATA, &data);
+	if (val)
+		*val = data;
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
+{
+	int i, j;
+	u8 data = 0, tmp = 0xFF;
+
+	for (i = 0; i < 8; i++) {
+		if (val & (u8)(1 << i))
+			continue;
+
+		tmp &= (~(u8)(1 << i));
+		RTSX_DEBUGP("Write 0x%x to 0x%x\n", tmp, addr);
+
+		RTSX_WRITE_REG(chip, EFUSE_DATA, 0xFF, tmp);
+		RTSX_WRITE_REG(chip, EFUSE_CTRL, 0xFF, 0xA0|addr);
+
+		for (j = 0; j < 100; j++) {
+			RTSX_READ_REG(chip, EFUSE_CTRL, &data);
+			if (!(data & 0x80))
+				break;
+			wait_timeout(3);
+		}
+
+		if (data & 0x80) {
+			TRACE_RET(chip, STATUS_TIMEDOUT);
+		}
+
+		wait_timeout(5);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
+{
+	int retval;
+	u16 value;
+
+	retval = rtsx_read_phy_register(chip, reg, &value);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (value & (1 << bit)) {
+		value &= ~(1 << bit);
+		retval = rtsx_write_phy_register(chip, reg, value);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
+{
+	int retval;
+	u16 value;
+
+	retval = rtsx_read_phy_register(chip, reg, &value);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	if (0 == (value & (1 << bit))) {
+		value |= (1 << bit);
+		retval = rtsx_write_phy_register(chip, reg, value);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_check_link_ready(struct rtsx_chip *chip)
+{
+	u8 val;
+
+	RTSX_READ_REG(chip, IRQSTAT0, &val);
+
+	RTSX_DEBUGP("IRQSTAT0: 0x%x\n", val);
+	if (val & LINK_RDY_INT) {
+		RTSX_DEBUGP("Delinked!\n");
+		rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
+		return STATUS_FAIL;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate)
+{
+	u32 ultmp;
+
+	RTSX_DEBUGP("%04x set pm_dstate to %d\n", chip->product_id, dstate);
+
+	if (CHK_SDIO_EXIST(chip)) {
+		u8 func_no;
+
+		if (CHECK_PID(chip, 0x5288)) {
+			func_no = 2;
+		} else {
+			func_no = 1;
+		}
+		rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp);
+		RTSX_DEBUGP("pm_dstate of function %d: 0x%x\n", (int)func_no, ultmp);
+		rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate);
+	}
+
+	rtsx_write_config_byte(chip, 0x44, dstate);
+	rtsx_write_config_byte(chip, 0x45, 0);
+}
+
+void rtsx_enter_L1(struct rtsx_chip *chip)
+{
+	rtsx_handle_pm_dstate(chip, 2);
+}
+
+void rtsx_exit_L1(struct rtsx_chip *chip)
+{
+	rtsx_write_config_byte(chip, 0x44, 0);
+	rtsx_write_config_byte(chip, 0x45, 0);
+}
+
+void rtsx_enter_ss(struct rtsx_chip *chip)
+{
+	RTSX_DEBUGP("Enter Selective Suspend State!\n");
+
+	rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
+
+	if (chip->power_down_in_ss) {
+		rtsx_power_off_card(chip);
+		rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
+	}
+
+	if (CHK_SDIO_EXIST(chip)) {
+		if (CHECK_PID(chip, 0x5288)) {
+			rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF00, 0x0100);
+		} else {
+			rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFF00, 0x0100);
+		}
+	}
+
+	if (chip->auto_delink_en) {
+		rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01);
+	} else {
+		if (!chip->phy_debug_mode) {
+			u32 tmp;
+			tmp = rtsx_readl(chip, RTSX_BIER);
+			tmp |= CARD_INT;
+			rtsx_writel(chip, RTSX_BIER, tmp);
+		}
+
+		rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0);
+	}
+
+	rtsx_enter_L1(chip);
+
+	RTSX_CLR_DELINK(chip);
+	rtsx_set_stat(chip, RTSX_STAT_SS);
+}
+
+void rtsx_exit_ss(struct rtsx_chip *chip)
+{
+	RTSX_DEBUGP("Exit Selective Suspend State!\n");
+
+	rtsx_exit_L1(chip);
+
+	if (chip->power_down_in_ss) {
+		rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
+		udelay(1000);
+	}
+
+	if (RTSX_TST_DELINK(chip)) {
+		chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
+		rtsx_reinit_cards(chip, 1);
+		RTSX_CLR_DELINK(chip);
+	} else if (chip->power_down_in_ss) {
+		chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
+		rtsx_reinit_cards(chip, 0);
+	}
+}
+
+int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
+{
+	u32 status, int_enable;
+	int exit_ss = 0;
+#ifdef SUPPORT_OCP
+	u32 ocp_int = 0;
+
+	if (CHECK_PID(chip, 0x5209)) {
+		if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+			ocp_int = MS_OC_INT | SD_OC_INT;
+		} else {
+			ocp_int = SD_OC_INT;
+		}
+	} else {
+		ocp_int = OC_INT;
+	}
+#endif
+
+	if (chip->ss_en) {
+		chip->ss_counter = 0;
+		if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
+			exit_ss = 1;
+			rtsx_exit_L1(chip);
+			rtsx_set_stat(chip, RTSX_STAT_RUN);
+		}
+	}
+
+	int_enable = rtsx_readl(chip, RTSX_BIER);
+	chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
+
+#ifdef HW_INT_WRITE_CLR
+	if (CHECK_PID(chip, 0x5209)) {
+		rtsx_writel(chip, RTSX_BIPR, chip->int_reg);
+	}
+#endif
+
+	if (((chip->int_reg & int_enable) == 0) || (chip->int_reg == 0xFFFFFFFF))
+		return STATUS_FAIL;
+
+	if (!chip->msi_en) {
+		if (CHECK_PID(chip, 0x5209)) {
+			u8 val;
+			rtsx_read_config_byte(chip, 0x05, &val);
+			if (val & 0x04) {
+				return STATUS_FAIL;
+			}
+		}
+	}
+
+	status = chip->int_reg &= (int_enable | 0x7FFFFF);
+
+	if (status & CARD_INT) {
+		chip->auto_delink_cnt = 0;
+
+		if (status & SD_INT) {
+			if (status & SD_EXIST) {
+				set_bit(SD_NR, &(chip->need_reset));
+			} else {
+				set_bit(SD_NR, &(chip->need_release));
+				chip->sd_reset_counter = 0;
+				chip->sd_show_cnt = 0;
+				clear_bit(SD_NR, &(chip->need_reset));
+			}
+		} else {
+			/* If multi-luns, it's possible that
+			   when plugging/unplugging one card
+			   there is another card which still
+			   exists in the slot. In this case,
+			   all existed cards should be reset.
+			*/
+			if (exit_ss && (status & SD_EXIST))
+				set_bit(SD_NR, &(chip->need_reinit));
+		}
+		if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) {
+			if (status & XD_INT) {
+				if (status & XD_EXIST) {
+					set_bit(XD_NR, &(chip->need_reset));
+				} else {
+					set_bit(XD_NR, &(chip->need_release));
+					chip->xd_reset_counter = 0;
+					chip->xd_show_cnt = 0;
+					clear_bit(XD_NR, &(chip->need_reset));
+				}
+			} else {
+				if (exit_ss && (status & XD_EXIST))
+					set_bit(XD_NR, &(chip->need_reinit));
+			}
+		}
+		if (status & MS_INT) {
+			if (status & MS_EXIST) {
+				set_bit(MS_NR, &(chip->need_reset));
+			} else {
+				set_bit(MS_NR, &(chip->need_release));
+				chip->ms_reset_counter = 0;
+				chip->ms_show_cnt = 0;
+				clear_bit(MS_NR, &(chip->need_reset));
+			}
+		} else {
+			if (exit_ss && (status & MS_EXIST))
+				set_bit(MS_NR, &(chip->need_reinit));
+		}
+	}
+
+#ifdef SUPPORT_OCP
+	chip->ocp_int = ocp_int & status;
+#endif
+
+	if (chip->sd_io) {
+		if (chip->int_reg & DATA_DONE_INT)
+			chip->int_reg &= ~(u32)DATA_DONE_INT;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat)
+{
+	int retval;
+
+	RTSX_DEBUGP("rtsx_do_before_power_down, pm_stat = %d\n", pm_stat);
+
+	rtsx_set_stat(chip, RTSX_STAT_SUSPEND);
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS)
+		return;
+
+	rtsx_release_cards(chip);
+	rtsx_disable_bus_int(chip);
+	turn_off_led(chip, LED_GPIO);
+
+#ifdef HW_AUTO_SWITCH_SD_BUS
+	if (chip->sd_io) {
+		chip->sdio_in_charge = 1;
+		if (CHECK_PID(chip, 0x5208)) {
+			rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
+			/* Enable sdio_bus_auto_switch */
+			rtsx_write_register(chip, 0xFE70, 0x80, 0x80);
+		} else if (CHECK_PID(chip, 0x5288)) {
+			rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
+			/* Enable sdio_bus_auto_switch */
+			rtsx_write_register(chip, 0xFE5A, 0x08, 0x08);
+		} else if (CHECK_PID(chip, 0x5209)) {
+			rtsx_write_register(chip, TLPTISTAT, 0x10, 0x10);
+			/* Enable sdio_bus_auto_switch */
+			rtsx_write_register(chip, SDIO_CFG, SDIO_BUS_AUTO_SWITCH, SDIO_BUS_AUTO_SWITCH);
+		}
+	}
+#endif
+
+	if (CHECK_PID(chip, 0x5208) && (chip->ic_version >= IC_VER_D)) {
+		/* u_force_clkreq_0 */
+		rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
+	} else if (CHECK_PID(chip, 0x5209)) {
+		/* u_force_clkreq_0 */
+		rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
+	}
+
+	if (pm_stat == PM_S1) {
+		RTSX_DEBUGP("Host enter S1\n");
+		rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, HOST_ENTER_S1);
+	} else if (pm_stat == PM_S3) {
+		if (chip->s3_pwr_off_delay > 0) {
+			wait_timeout(chip->s3_pwr_off_delay);
+		}
+		RTSX_DEBUGP("Host enter S3\n");
+		rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, HOST_ENTER_S3);
+	}
+
+	if (chip->do_delink_before_power_down && chip->auto_delink_en) {
+		rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2);
+	}
+
+	rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
+
+	chip->cur_clk = 0;
+	chip->cur_card = 0;
+	chip->card_exist = 0;
+}
+
+void rtsx_enable_aspm(struct rtsx_chip *chip)
+{
+	if (chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
+		if (!chip->aspm_enabled) {
+			RTSX_DEBUGP("Try to enable ASPM\n");
+			chip->aspm_enabled = 1;
+
+			if (chip->asic_code && CHECK_PID(chip, 0x5208))
+				rtsx_write_phy_register(chip, 0x07, 0);
+			if (CHECK_PID(chip, 0x5208)) {
+				rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3,
+					0x30 | chip->aspm_level[0]);
+			} else {
+				rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
+			}
+
+			if (CHK_SDIO_EXIST(chip)) {
+				u16 val = chip->aspm_l0s_l1_en | 0x0100;
+				if (CHECK_PID(chip, 0x5288)) {
+					rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, val);
+				} else {
+					rtsx_write_cfg_dw(chip, 1, 0xC0, 0xFFFF, val);
+				}
+			}
+		}
+	}
+
+	return;
+}
+
+void rtsx_disable_aspm(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5208))
+		rtsx_monitor_aspm_config(chip);
+
+	if (chip->aspm_l0s_l1_en && chip->dynamic_aspm) {
+		if (chip->aspm_enabled) {
+			RTSX_DEBUGP("Try to disable ASPM\n");
+			chip->aspm_enabled = 0;
+
+			if (chip->asic_code && CHECK_PID(chip, 0x5208))
+				rtsx_write_phy_register(chip, 0x07, 0x0129);
+			if (CHECK_PID(chip, 0x5208)) {
+				rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3, 0x30);
+			} else {
+				rtsx_write_config_byte(chip, LCTLR, 0x00);
+			}
+			wait_timeout(1);
+		}
+	}
+
+	return;
+}
+
+int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
+{
+	int retval;
+	int i, j;
+	u16 reg_addr;
+	u8 *ptr;
+
+	if (!buf) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	ptr = buf;
+	reg_addr = PPBUF_BASE2;
+	for (i = 0; i < buf_len/256; i++) {
+		rtsx_init_cmd(chip);
+
+		for (j = 0; j < 256; j++)
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
+
+		retval = rtsx_send_cmd(chip, 0, 250);
+		if (retval < 0) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		memcpy(ptr, rtsx_get_cmd_data(chip), 256);
+		ptr += 256;
+	}
+
+	if (buf_len%256) {
+		rtsx_init_cmd(chip);
+
+		for (j = 0; j < buf_len%256; j++)
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
+
+		retval = rtsx_send_cmd(chip, 0, 250);
+		if (retval < 0) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	memcpy(ptr, rtsx_get_cmd_data(chip), buf_len%256);
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
+{
+	int retval;
+	int i, j;
+	u16 reg_addr;
+	u8 *ptr;
+
+	if (!buf) {
+		TRACE_RET(chip, STATUS_ERROR);
+	}
+
+	ptr = buf;
+	reg_addr = PPBUF_BASE2;
+	for (i = 0; i < buf_len/256; i++) {
+		rtsx_init_cmd(chip);
+
+		for (j = 0; j < 256; j++) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, *ptr);
+			ptr++;
+		}
+
+		retval = rtsx_send_cmd(chip, 0, 250);
+		if (retval < 0) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (buf_len%256) {
+		rtsx_init_cmd(chip);
+
+		for (j = 0; j < buf_len%256; j++) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF, *ptr);
+			ptr++;
+		}
+
+		retval = rtsx_send_cmd(chip, 0, 250);
+		if (retval < 0) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_check_chip_exist(struct rtsx_chip *chip)
+{
+	if (rtsx_readl(chip, 0) == 0xFFFFFFFF) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
+{
+	int retval;
+	u8 mask = 0;
+
+	if (ctl & SSC_PDCTL)
+		mask |= SSC_POWER_DOWN;
+
+#ifdef SUPPORT_OCP
+	if (ctl & OC_PDCTL) {
+		mask |= SD_OC_POWER_DOWN;
+		if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+			mask |= MS_OC_POWER_DOWN;
+		}
+	}
+#endif
+
+	if (mask) {
+		retval = rtsx_write_register(chip, FPDCTL, mask, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (CHECK_PID(chip, 0x5288))
+			wait_timeout(200);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
+{
+	int retval;
+	u8 mask = 0, val = 0;
+
+	if (ctl & SSC_PDCTL)
+		mask |= SSC_POWER_DOWN;
+
+#ifdef SUPPORT_OCP
+	if (ctl & OC_PDCTL) {
+		mask |= SD_OC_POWER_DOWN;
+		if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
+			mask |= MS_OC_POWER_DOWN;
+	}
+#endif
+
+	if (mask) {
+		val = mask;
+		retval = rtsx_write_register(chip, FPDCTL, mask, val);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
diff --git a/drivers/staging/rts_pstor/rtsx_chip.h b/drivers/staging/rts_pstor/rtsx_chip.h
new file mode 100644
index 0000000..713c5ea
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_chip.h
@@ -0,0 +1,989 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_CHIP_H
+#define __REALTEK_RTSX_CHIP_H
+
+#include "rtsx.h"
+
+#define SUPPORT_CPRM
+#define SUPPORT_OCP
+#define SUPPORT_SDIO_ASPM
+#define SUPPORT_MAGIC_GATE
+#define SUPPORT_MSXC
+#define SUPPORT_SD_LOCK
+/* Hardware switch bus_ctl and cd_ctl automatically */
+#define HW_AUTO_SWITCH_SD_BUS
+/* Enable hardware interrupt write clear */
+#define HW_INT_WRITE_CLR
+/* #define LED_AUTO_BLINK */
+/* #define DISABLE_CARD_INT */
+
+#ifdef SUPPORT_MAGIC_GATE
+	/* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */
+	#define MG_SET_ICV_SLOW
+	/* HW may miss ERR/CMDNK signal when sampling INT status. */
+	#define MS_SAMPLE_INT_ERR
+	/* HW DO NOT support Wait_INT function during READ_BYTES transfer mode */
+	#define READ_BYTES_WAIT_INT
+#endif
+
+#ifdef SUPPORT_MSXC
+#define XC_POWERCLASS
+#define SUPPORT_PCGL_1P18
+#endif
+
+#ifndef LED_AUTO_BLINK
+#define REGULAR_BLINK
+#endif
+
+#define LED_BLINK_SPEED		5
+#define LED_TOGGLE_INTERVAL	6
+#define	GPIO_TOGGLE_THRESHOLD   1024
+#define LED_GPIO		0
+
+#define POLLING_INTERVAL	30
+
+#define TRACE_ITEM_CNT		64
+
+#ifndef STATUS_SUCCESS
+#define STATUS_SUCCESS		0
+#endif
+#ifndef STATUS_FAIL
+#define STATUS_FAIL		1
+#endif
+#ifndef STATUS_TIMEDOUT
+#define STATUS_TIMEDOUT		2
+#endif
+#ifndef STATUS_NOMEM
+#define STATUS_NOMEM		3
+#endif
+#ifndef STATUS_READ_FAIL
+#define STATUS_READ_FAIL	4
+#endif
+#ifndef STATUS_WRITE_FAIL
+#define STATUS_WRITE_FAIL	5
+#endif
+#ifndef STATUS_ERROR
+#define STATUS_ERROR		10
+#endif
+
+#define PM_S1			1
+#define PM_S3			3
+
+/*
+ * Transport return codes
+ */
+
+#define TRANSPORT_GOOD	   	0   /* Transport good, command good	   */
+#define TRANSPORT_FAILED  	1   /* Transport good, command failed   */
+#define TRANSPORT_NO_SENSE 	2  /* Command failed, no auto-sense    */
+#define TRANSPORT_ERROR   	3   /* Transport bad (i.e. device dead) */
+
+
+/*-----------------------------------
+    Start-Stop-Unit
+-----------------------------------*/
+#define STOP_MEDIUM			0x00    /* access disable         */
+#define MAKE_MEDIUM_READY		0x01    /* access enable          */
+#define UNLOAD_MEDIUM			0x02    /* unload                 */
+#define LOAD_MEDIUM			0x03    /* load                   */
+
+/*-----------------------------------
+    STANDARD_INQUIRY
+-----------------------------------*/
+#define QULIFIRE                0x00
+#define AENC_FNC                0x00
+#define TRML_IOP                0x00
+#define REL_ADR                 0x00
+#define WBUS_32                 0x00
+#define WBUS_16                 0x00
+#define SYNC                    0x00
+#define LINKED                  0x00
+#define CMD_QUE                 0x00
+#define SFT_RE                  0x00
+
+#define VEN_ID_LEN              8               /* Vendor ID Length         */
+#define PRDCT_ID_LEN            16              /* Product ID Length        */
+#define PRDCT_REV_LEN           4               /* Product LOT Length       */
+
+/* Dynamic flag definitions: used in set_bit() etc. */
+#define RTSX_FLIDX_TRANS_ACTIVE		18  /* 0x00040000  transfer is active */
+#define RTSX_FLIDX_ABORTING		20  /* 0x00100000  abort is in progress */
+#define RTSX_FLIDX_DISCONNECTING	21  /* 0x00200000  disconnect in progress */
+#define ABORTING_OR_DISCONNECTING	((1UL << US_FLIDX_ABORTING) | \
+					 (1UL << US_FLIDX_DISCONNECTING))
+#define RTSX_FLIDX_RESETTING		22  /* 0x00400000  device reset in progress */
+#define RTSX_FLIDX_TIMED_OUT		23  /* 0x00800000  SCSI midlayer timed out  */
+
+#define DRCT_ACCESS_DEV         0x00    /* Direct Access Device      */
+#define RMB_DISC                0x80    /* The Device is Removable   */
+#define ANSI_SCSI2              0x02    /* Based on ANSI-SCSI2       */
+
+#define SCSI                    0x00    /* Interface ID              */
+
+#define	WRITE_PROTECTED_MEDIA 0x07
+
+/*---- sense key ----*/
+#define ILI                     0x20    /* ILI bit is on                    */
+
+#define NO_SENSE                0x00    /* not exist sense key              */
+#define RECOVER_ERR             0x01    /* Target/Logical unit is recoverd  */
+#define NOT_READY               0x02    /* Logical unit is not ready        */
+#define MEDIA_ERR               0x03    /* medium/data error                */
+#define HARDWARE_ERR            0x04    /* hardware error                   */
+#define ILGAL_REQ               0x05    /* CDB/parameter/identify msg error */
+#define UNIT_ATTENTION          0x06    /* unit attention condition occur   */
+#define DAT_PRTCT               0x07    /* read/write is desable            */
+#define BLNC_CHK                0x08    /* find blank/DOF in read           */
+					/* write to unblank area            */
+#define CPY_ABRT                0x0a    /* Copy/Compare/Copy&Verify illgal  */
+#define ABRT_CMD                0x0b    /* Target make the command in error */
+#define EQUAL                   0x0c    /* Search Data end with Equal       */
+#define VLM_OVRFLW              0x0d    /* Some data are left in buffer     */
+#define MISCMP                  0x0e    /* find inequality                  */
+
+#define READ_ERR                -1
+#define WRITE_ERR               -2
+
+#define	FIRST_RESET		0x01
+#define	USED_EXIST		0x02
+
+/*-----------------------------------
+    SENSE_DATA
+-----------------------------------*/
+/*---- valid ----*/
+#define SENSE_VALID             0x80    /* Sense data is valid as SCSI2     */
+#define SENSE_INVALID           0x00    /* Sense data is invalid as SCSI2   */
+
+/*---- error code ----*/
+#define CUR_ERR                 0x70    /* current error                    */
+#define DEF_ERR                 0x71    /* specific command error           */
+
+/*---- sense key Infomation ----*/
+#define SNSKEYINFO_LEN          3       /* length of sense key infomation   */
+
+#define SKSV                    0x80
+#define CDB_ILLEGAL             0x40
+#define DAT_ILLEGAL             0x00
+#define BPV                     0x08
+#define BIT_ILLEGAL0            0       /* bit0 is illegal                  */
+#define BIT_ILLEGAL1            1       /* bit1 is illegal                  */
+#define BIT_ILLEGAL2            2       /* bit2 is illegal                  */
+#define BIT_ILLEGAL3            3       /* bit3 is illegal                  */
+#define BIT_ILLEGAL4            4       /* bit4 is illegal                  */
+#define BIT_ILLEGAL5            5       /* bit5 is illegal                  */
+#define BIT_ILLEGAL6            6       /* bit6 is illegal                  */
+#define BIT_ILLEGAL7            7       /* bit7 is illegal                  */
+
+/*---- ASC ----*/
+#define ASC_NO_INFO             0x00
+#define ASC_MISCMP              0x1d
+#define ASC_INVLD_CDB           0x24
+#define ASC_INVLD_PARA          0x26
+#define ASC_LU_NOT_READY	0x04
+#define ASC_WRITE_ERR           0x0c
+#define ASC_READ_ERR            0x11
+#define ASC_LOAD_EJCT_ERR       0x53
+#define	ASC_MEDIA_NOT_PRESENT	0x3A
+#define	ASC_MEDIA_CHANGED	0x28
+#define	ASC_MEDIA_IN_PROCESS	0x04
+#define	ASC_WRITE_PROTECT	0x27
+#define ASC_LUN_NOT_SUPPORTED	0x25
+
+/*---- ASQC ----*/
+#define ASCQ_NO_INFO            0x00
+#define	ASCQ_MEDIA_IN_PROCESS	0x01
+#define ASCQ_MISCMP             0x00
+#define ASCQ_INVLD_CDB          0x00
+#define ASCQ_INVLD_PARA         0x02
+#define ASCQ_LU_NOT_READY	0x02
+#define ASCQ_WRITE_ERR          0x02
+#define ASCQ_READ_ERR           0x00
+#define ASCQ_LOAD_EJCT_ERR      0x00
+#define	ASCQ_WRITE_PROTECT	0x00
+
+
+struct sense_data_t {
+    unsigned char   err_code;		/* error code */
+						/* bit7 : valid                    */
+						/*   (1 : SCSI2)                    */
+						/*   (0 : Vendor specific)          */
+						/* bit6-0 : error code             */
+						/*  (0x70 : current error)          */
+						/*  (0x71 : specific command error) */
+    unsigned char   seg_no;		/* segment No.                      */
+    unsigned char   sense_key;		/* byte5 : ILI                      */
+						/* bit3-0 : sense key              */
+    unsigned char   info[4];		/* infomation                       */
+    unsigned char   ad_sense_len;	/* additional sense data length     */
+    unsigned char   cmd_info[4];	/* command specific infomation      */
+    unsigned char   asc;		/* ASC                              */
+    unsigned char   ascq;		/* ASCQ                             */
+    unsigned char   rfu;		/* FRU                              */
+    unsigned char   sns_key_info[3];	/* sense key specific infomation    */
+};
+
+/* PCI Operation Register Address */
+#define RTSX_HCBAR		0x00
+#define RTSX_HCBCTLR		0x04
+#define RTSX_HDBAR		0x08
+#define RTSX_HDBCTLR		0x0C
+#define RTSX_HAIMR		0x10
+#define RTSX_BIPR		0x14
+#define RTSX_BIER		0x18
+
+/* Host command buffer control register */
+#define STOP_CMD		(0x01 << 28)
+
+/* Host data buffer control register */
+#define SDMA_MODE		0x00
+#define ADMA_MODE		(0x02 << 26)
+#define STOP_DMA		(0x01 << 28)
+#define TRIG_DMA		(0x01 << 31)
+
+/* Bus interrupt pending register */
+#define CMD_DONE_INT		(1 << 31)
+#define DATA_DONE_INT		(1 << 30)
+#define TRANS_OK_INT		(1 << 29)
+#define TRANS_FAIL_INT		(1 << 28)
+#define XD_INT			(1 << 27)
+#define MS_INT			(1 << 26)
+#define SD_INT			(1 << 25)
+#define GPIO0_INT		(1 << 24)
+#define OC_INT			(1 << 23)
+#define SD_WRITE_PROTECT	(1 << 19)
+#define XD_EXIST		(1 << 18)
+#define MS_EXIST		(1 << 17)
+#define SD_EXIST		(1 << 16)
+#define DELINK_INT		GPIO0_INT
+#define MS_OC_INT		(1 << 23)
+#define SD_OC_INT		(1 << 22)
+
+#define CARD_INT		(XD_INT | MS_INT | SD_INT)
+#define NEED_COMPLETE_INT	(DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
+#define RTSX_INT		(CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | GPIO0_INT | OC_INT)
+
+#define CARD_EXIST		(XD_EXIST | MS_EXIST | SD_EXIST)
+
+/* Bus interrupt enable register */
+#define CMD_DONE_INT_EN		(1 << 31)
+#define DATA_DONE_INT_EN	(1 << 30)
+#define TRANS_OK_INT_EN		(1 << 29)
+#define TRANS_FAIL_INT_EN	(1 << 28)
+#define XD_INT_EN		(1 << 27)
+#define MS_INT_EN		(1 << 26)
+#define SD_INT_EN		(1 << 25)
+#define GPIO0_INT_EN		(1 << 24)
+#define OC_INT_EN		(1 << 23)
+#define DELINK_INT_EN		GPIO0_INT_EN
+#define MS_OC_INT_EN		(1 << 23)
+#define SD_OC_INT_EN		(1 << 22)
+
+
+#define READ_REG_CMD		0
+#define WRITE_REG_CMD		1
+#define CHECK_REG_CMD		2
+
+#define HOST_TO_DEVICE		0
+#define DEVICE_TO_HOST		1
+
+
+#define RTSX_RESV_BUF_LEN	4096
+#define HOST_CMDS_BUF_LEN	1024
+#define HOST_SG_TBL_BUF_LEN	(RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
+
+#define SD_NR		2
+#define MS_NR		3
+#define XD_NR		4
+#define SPI_NR		7
+#define SD_CARD		(1 << SD_NR)
+#define MS_CARD		(1 << MS_NR)
+#define XD_CARD		(1 << XD_NR)
+#define SPI_CARD	(1 << SPI_NR)
+
+#define MAX_ALLOWED_LUN_CNT	8
+
+#define XD_FREE_TABLE_CNT	1200
+#define MS_FREE_TABLE_CNT	512
+
+
+/* Bit Operation */
+#define SET_BIT(data, idx)	((data) |= 1 << (idx))
+#define CLR_BIT(data, idx)	((data) &= ~(1 << (idx)))
+#define CHK_BIT(data, idx)	((data) & (1 << (idx)))
+
+/* SG descriptor */
+#define SG_INT			0x04
+#define SG_END			0x02
+#define SG_VALID		0x01
+
+#define SG_NO_OP		0x00
+#define SG_TRANS_DATA		(0x02 << 4)
+#define SG_LINK_DESC		(0x03 << 4)
+
+struct rtsx_chip;
+
+typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 sec_addr, u16 sec_cnt);
+
+/* Supported Clock */
+enum card_clock	{CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60, CLK_80, CLK_100, CLK_120, CLK_150, CLK_200};
+
+enum RTSX_STAT	{RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS,
+		RTSX_STAT_DELINK, RTSX_STAT_SUSPEND, RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT};
+enum IC_VER	{IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3};
+
+#define MAX_RESET_CNT		3
+
+/* For MS Card */
+#define MAX_DEFECTIVE_BLOCK     10
+
+struct zone_entry {
+	u16 *l2p_table;
+	u16 *free_table;
+	u16 defect_list[MAX_DEFECTIVE_BLOCK];  /* For MS card only */
+	int set_index;
+	int get_index;
+	int unused_blk_cnt;
+	int disable_count;
+	/* To indicate whether the L2P table of this zone has been built. */
+	int build_flag;
+};
+
+#define TYPE_SD			0x0000
+#define TYPE_MMC		0x0001
+
+/* TYPE_SD */
+#define SD_HS			0x0100
+#define SD_SDR50		0x0200
+#define SD_DDR50		0x0400
+#define SD_SDR104		0x0800
+#define SD_HCXC			0x1000
+
+/* TYPE_MMC */
+#define MMC_26M			0x0100
+#define MMC_52M			0x0200
+#define MMC_4BIT		0x0400
+#define MMC_8BIT		0x0800
+#define MMC_SECTOR_MODE		0x1000
+#define MMC_DDR52		0x2000
+
+/* SD card */
+#define CHK_SD(sd_card)			(((sd_card)->sd_type & 0xFF) == TYPE_SD)
+#define CHK_SD_HS(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HS))
+#define CHK_SD_SDR50(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR50))
+#define CHK_SD_DDR50(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_DDR50))
+#define CHK_SD_SDR104(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_SDR104))
+#define CHK_SD_HCXC(sd_card)		(CHK_SD(sd_card) && ((sd_card)->sd_type & SD_HCXC))
+#define CHK_SD_HC(sd_card)		(CHK_SD_HCXC(sd_card) && ((sd_card)->capacity <= 0x4000000))
+#define CHK_SD_XC(sd_card)		(CHK_SD_HCXC(sd_card) && ((sd_card)->capacity > 0x4000000))
+#define CHK_SD30_SPEED(sd_card)		(CHK_SD_SDR50(sd_card) || CHK_SD_DDR50(sd_card) || CHK_SD_SDR104(sd_card))
+
+#define SET_SD(sd_card)			((sd_card)->sd_type = TYPE_SD)
+#define SET_SD_HS(sd_card)		((sd_card)->sd_type |= SD_HS)
+#define SET_SD_SDR50(sd_card)		((sd_card)->sd_type |= SD_SDR50)
+#define SET_SD_DDR50(sd_card)		((sd_card)->sd_type |= SD_DDR50)
+#define SET_SD_SDR104(sd_card)		((sd_card)->sd_type |= SD_SDR104)
+#define SET_SD_HCXC(sd_card)		((sd_card)->sd_type |= SD_HCXC)
+
+#define CLR_SD_HS(sd_card)		((sd_card)->sd_type &= ~SD_HS)
+#define CLR_SD_SDR50(sd_card)		((sd_card)->sd_type &= ~SD_SDR50)
+#define CLR_SD_DDR50(sd_card)		((sd_card)->sd_type &= ~SD_DDR50)
+#define CLR_SD_SDR104(sd_card)		((sd_card)->sd_type &= ~SD_SDR104)
+#define CLR_SD_HCXC(sd_card)		((sd_card)->sd_type &= ~SD_HCXC)
+
+/* MMC card */
+#define CHK_MMC(sd_card)		(((sd_card)->sd_type & 0xFF) == TYPE_MMC)
+#define CHK_MMC_26M(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_26M))
+#define CHK_MMC_52M(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_52M))
+#define CHK_MMC_4BIT(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_4BIT))
+#define CHK_MMC_8BIT(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_8BIT))
+#define CHK_MMC_SECTOR_MODE(sd_card)	(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_SECTOR_MODE))
+#define CHK_MMC_DDR52(sd_card)		(CHK_MMC(sd_card) && ((sd_card)->sd_type & MMC_DDR52))
+
+#define SET_MMC(sd_card)		((sd_card)->sd_type = TYPE_MMC)
+#define SET_MMC_26M(sd_card)		((sd_card)->sd_type |= MMC_26M)
+#define SET_MMC_52M(sd_card)		((sd_card)->sd_type |= MMC_52M)
+#define SET_MMC_4BIT(sd_card)		((sd_card)->sd_type |= MMC_4BIT)
+#define SET_MMC_8BIT(sd_card)		((sd_card)->sd_type |= MMC_8BIT)
+#define SET_MMC_SECTOR_MODE(sd_card)	((sd_card)->sd_type |= MMC_SECTOR_MODE)
+#define SET_MMC_DDR52(sd_card)		((sd_card)->sd_type |= MMC_DDR52)
+
+#define CLR_MMC_26M(sd_card)		((sd_card)->sd_type &= ~MMC_26M)
+#define CLR_MMC_52M(sd_card)		((sd_card)->sd_type &= ~MMC_52M)
+#define CLR_MMC_4BIT(sd_card)		((sd_card)->sd_type &= ~MMC_4BIT)
+#define CLR_MMC_8BIT(sd_card)		((sd_card)->sd_type &= ~MMC_8BIT)
+#define CLR_MMC_SECTOR_MODE(sd_card)	((sd_card)->sd_type &= ~MMC_SECTOR_MODE)
+#define CLR_MMC_DDR52(sd_card)		((sd_card)->sd_type &= ~MMC_DDR52)
+
+#define CHK_MMC_HS(sd_card)		(CHK_MMC_52M(sd_card) && CHK_MMC_26M(sd_card))
+#define CLR_MMC_HS(sd_card)			\
+do {						\
+	CLR_MMC_DDR52(sd_card);			\
+	CLR_MMC_52M(sd_card);			\
+	CLR_MMC_26M(sd_card);			\
+} while (0)
+
+#define SD_SUPPORT_CLASS_TEN		0x01
+#define SD_SUPPORT_1V8			0x02
+
+#define SD_SET_CLASS_TEN(sd_card)	((sd_card)->sd_setting |= SD_SUPPORT_CLASS_TEN)
+#define SD_CHK_CLASS_TEN(sd_card)	((sd_card)->sd_setting & SD_SUPPORT_CLASS_TEN)
+#define SD_CLR_CLASS_TEN(sd_card)	((sd_card)->sd_setting &= ~SD_SUPPORT_CLASS_TEN)
+#define SD_SET_1V8(sd_card)		((sd_card)->sd_setting |= SD_SUPPORT_1V8)
+#define SD_CHK_1V8(sd_card)		((sd_card)->sd_setting & SD_SUPPORT_1V8)
+#define SD_CLR_1V8(sd_card)		((sd_card)->sd_setting &= ~SD_SUPPORT_1V8)
+
+struct sd_info {
+	u16 sd_type;
+	u8 err_code;
+	u8 sd_data_buf_ready;
+	u32 sd_addr;
+	u32 capacity;
+
+	u8 raw_csd[16];
+	u8 raw_scr[8];
+
+	/* Sequential RW */
+	int seq_mode;
+	enum dma_data_direction pre_dir;
+	u32 pre_sec_addr;
+	u16 pre_sec_cnt;
+
+	int cleanup_counter;
+
+	int sd_clock;
+
+	int mmc_dont_switch_bus;
+
+#ifdef SUPPORT_CPRM
+	int sd_pass_thru_en;
+	int pre_cmd_err;
+	u8 last_rsp_type;
+	u8 rsp[17];
+#endif
+
+	u8 func_group1_mask;
+	u8 func_group2_mask;
+	u8 func_group3_mask;
+	u8 func_group4_mask;
+
+	u8 sd_switch_fail;
+	u8 sd_read_phase;
+
+#ifdef SUPPORT_SD_LOCK
+	u8 sd_lock_status;
+	u8 sd_erase_status;
+	u8 sd_lock_notify;
+#endif
+	int need_retune;
+};
+
+struct xd_delay_write_tag {
+	u32 old_phyblock;
+	u32 new_phyblock;
+	u32 logblock;
+	u8 pageoff;
+	u8 delay_write_flag;
+};
+
+struct xd_info {
+	u8 maker_code;
+	u8 device_code;
+	u8 block_shift;
+	u8 page_off;
+	u8 addr_cycle;
+	u16 cis_block;
+	u8 multi_flag;
+	u8 err_code;
+	u32 capacity;
+
+	struct zone_entry *zone;
+	int zone_cnt;
+
+	struct xd_delay_write_tag delay_write;
+	int cleanup_counter;
+
+	int xd_clock;
+};
+
+#define MODE_512_SEQ		0x01
+#define MODE_2K_SEQ		0x02
+
+#define TYPE_MS			0x0000
+#define TYPE_MSPRO		0x0001
+
+#define MS_4BIT			0x0100
+#define MS_8BIT			0x0200
+#define MS_HG			0x0400
+#define MS_XC			0x0800
+
+#define HG8BIT			(MS_HG | MS_8BIT)
+
+#define CHK_MSPRO(ms_card)	(((ms_card)->ms_type & 0xFF) == TYPE_MSPRO)
+#define CHK_HG8BIT(ms_card)	(CHK_MSPRO(ms_card) && (((ms_card)->ms_type & HG8BIT) == HG8BIT))
+#define CHK_MSXC(ms_card)	(CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_XC))
+#define CHK_MSHG(ms_card)	(CHK_MSPRO(ms_card) && ((ms_card)->ms_type & MS_HG))
+
+#define CHK_MS8BIT(ms_card)	(((ms_card)->ms_type & MS_8BIT))
+#define CHK_MS4BIT(ms_card)	(((ms_card)->ms_type & MS_4BIT))
+
+struct ms_delay_write_tag {
+	u16 old_phyblock;
+	u16 new_phyblock;
+	u16 logblock;
+	u8 pageoff;
+	u8 delay_write_flag;
+};
+
+struct ms_info {
+	u16 ms_type;
+	u8 block_shift;
+	u8 page_off;
+	u16 total_block;
+	u16 boot_block;
+	u32 capacity;
+
+	u8 check_ms_flow;
+	u8 switch_8bit_fail;
+	u8 err_code;
+
+	struct zone_entry *segment;
+	int segment_cnt;
+
+	int pro_under_formatting;
+	int format_status;
+	u16 progress;
+	u8 raw_sys_info[96];
+#ifdef SUPPORT_PCGL_1P18
+	u8 raw_model_name[48];
+#endif
+
+	u8 multi_flag;
+
+	/* Sequential RW */
+	u8 seq_mode;
+	enum dma_data_direction pre_dir;
+	u32 pre_sec_addr;
+	u16 pre_sec_cnt;
+	u32 total_sec_cnt;
+
+	struct ms_delay_write_tag delay_write;
+
+	int cleanup_counter;
+
+	int ms_clock;
+
+#ifdef SUPPORT_MAGIC_GATE
+	u8 magic_gate_id[16];
+	u8 mg_entry_num;
+	int mg_auth;    /* flag to indicate authentication process */
+#endif
+};
+
+struct spi_info {
+	u8 use_clk;
+	u8 write_en;
+	u16 clk_div;
+	u8 err_code;
+
+	int spi_clock;
+};
+
+
+#ifdef _MSG_TRACE
+struct trace_msg_t {
+	u16 line;
+#define MSG_FUNC_LEN 64
+	char func[MSG_FUNC_LEN];
+#define MSG_FILE_LEN 32
+	char file[MSG_FILE_LEN];
+#define TIME_VAL_LEN 16
+	u8 timeval_buf[TIME_VAL_LEN];
+	u8 valid;
+};
+#endif
+
+/************/
+/* LUN mode */
+/************/
+/* Single LUN, support xD/SD/MS */
+#define DEFAULT_SINGLE		0
+/* 2 LUN mode, support SD/MS */
+#define SD_MS_2LUN		1
+/* Single LUN, but only support SD/MS, for Barossa LQFP */
+#define SD_MS_1LUN		2
+
+#define LAST_LUN_MODE		2
+
+/* Barossa package */
+#define QFN		0
+#define LQFP		1
+
+/******************/
+/* sd_ctl bit map */
+/******************/
+/* SD push point control, bit 0, 1 */
+#define SD_PUSH_POINT_CTL_MASK		0x03
+#define SD_PUSH_POINT_DELAY		0x01
+#define SD_PUSH_POINT_AUTO		0x02
+/* SD sample point control, bit 2, 3 */
+#define SD_SAMPLE_POINT_CTL_MASK	0x0C
+#define SD_SAMPLE_POINT_DELAY		0x04
+#define SD_SAMPLE_POINT_AUTO		0x08
+/* SD DDR Tx phase set by user, bit 4 */
+#define SD_DDR_TX_PHASE_SET_BY_USER	0x10
+/* MMC DDR Tx phase set by user, bit 5 */
+#define MMC_DDR_TX_PHASE_SET_BY_USER	0x20
+/* Support MMC DDR mode, bit 6 */
+#define SUPPORT_MMC_DDR_MODE		0x40
+/* Reset MMC at first */
+#define RESET_MMC_FIRST			0x80
+
+#define SEQ_START_CRITERIA		0x20
+
+/* MS Power Class En */
+#define POWER_CLASS_2_EN		0x02
+#define POWER_CLASS_1_EN		0x01
+
+#define MAX_SHOW_CNT			10
+#define MAX_RESET_CNT			3
+
+#define SDIO_EXIST			0x01
+#define SDIO_IGNORED			0x02
+
+#define CHK_SDIO_EXIST(chip)		((chip)->sdio_func_exist & SDIO_EXIST)
+#define SET_SDIO_EXIST(chip)		((chip)->sdio_func_exist |= SDIO_EXIST)
+#define CLR_SDIO_EXIST(chip)		((chip)->sdio_func_exist &= ~SDIO_EXIST)
+
+#define CHK_SDIO_IGNORED(chip)		((chip)->sdio_func_exist & SDIO_IGNORED)
+#define SET_SDIO_IGNORED(chip)		((chip)->sdio_func_exist |= SDIO_IGNORED)
+#define CLR_SDIO_IGNORED(chip)		((chip)->sdio_func_exist &= ~SDIO_IGNORED)
+
+struct rtsx_chip {
+	rtsx_dev_t 		*rtsx;
+
+	u32 			int_reg;		/* Bus interrupt pending register */
+	char 			max_lun;
+	void 			*context;
+
+	void 			*host_cmds_ptr;		/* host commands buffer pointer */
+	dma_addr_t		host_cmds_addr;
+	int 			ci;			/* Command Index */
+
+	void			*host_sg_tbl_ptr;	/* SG descriptor table */
+	dma_addr_t		host_sg_tbl_addr;
+	int			sgi;			/* SG entry index */
+
+	struct scsi_cmnd	*srb;		 	/* current srb */
+	struct sense_data_t 	sense_buffer[MAX_ALLOWED_LUN_CNT];
+
+	int			cur_clk;		/* current card clock */
+
+	/* Current accessed card */
+	int 			cur_card;
+
+	unsigned long 		need_release;		/* need release bit map */
+	unsigned long 		need_reset;		/* need reset bit map */
+	/* Flag to indicate that this card is just resumed from SS state,
+	 * and need released before being resetted
+	 */
+	unsigned long 		need_reinit;
+
+	int 			rw_need_retry;
+
+#ifdef SUPPORT_OCP
+	u32 			ocp_int;
+	u8 			ocp_stat;
+#endif
+
+	u8 			card_exist;		/* card exist bit map (physical exist) */
+	u8 			card_ready;		/* card ready bit map (reset successfully) */
+	u8 			card_fail;		/* card reset fail bit map */
+	u8 			card_ejected;		/* card ejected bit map */
+	u8 			card_wp;		/* card write protected bit map */
+
+	u8 			lun_mc;			/* flag to indicate whether to answer MediaChange */
+
+#ifndef LED_AUTO_BLINK
+	int 			led_toggle_counter;
+#endif
+
+	int 			sd_reset_counter;
+	int 			xd_reset_counter;
+	int 			ms_reset_counter;
+
+	/* card bus width */
+	u8			card_bus_width[MAX_ALLOWED_LUN_CNT];
+	/* card capacity */
+	u32 			capacity[MAX_ALLOWED_LUN_CNT];
+	/* read/write card function pointer */
+	card_rw_func 		rw_card[MAX_ALLOWED_LUN_CNT];
+	/* read/write capacity, used for GPIO Toggle */
+	u32			rw_cap[MAX_ALLOWED_LUN_CNT];
+	/* card to lun mapping table */
+	u8			card2lun[32];
+	/* lun to card mapping table */
+	u8			lun2card[MAX_ALLOWED_LUN_CNT];
+
+	int 			rw_fail_cnt[MAX_ALLOWED_LUN_CNT];
+
+	int 			sd_show_cnt;
+	int 			xd_show_cnt;
+	int 			ms_show_cnt;
+
+	/* card information */
+	struct sd_info		sd_card;
+	struct xd_info		xd_card;
+	struct ms_info		ms_card;
+
+	struct spi_info		spi;
+
+#ifdef _MSG_TRACE
+	struct trace_msg_t	trace_msg[TRACE_ITEM_CNT];
+	int 			msg_idx;
+#endif
+
+	int 			auto_delink_cnt;
+	int 			auto_delink_allowed;
+
+	int 			aspm_enabled;
+
+	int 			sdio_aspm;
+	int 			sdio_idle;
+	int 			sdio_counter;
+	u8 			sdio_raw_data[12];
+
+	u8 			sd_io;
+	u8 			sd_int;
+
+	u8 			rtsx_flag;
+
+	int 			ss_counter;
+	int 			idle_counter;
+	enum RTSX_STAT 		rtsx_stat;
+
+	u16 			vendor_id;
+	u16			product_id;
+	u8 			ic_version;
+
+	int			driver_first_load;
+
+#ifdef HW_AUTO_SWITCH_SD_BUS
+	int 			sdio_in_charge;
+#endif
+
+	u8 			aspm_level[2];
+
+	int 			chip_insert_with_sdio;
+
+	/* Options */
+
+	int adma_mode;
+
+	int auto_delink_en;
+	int ss_en;
+	u8 lun_mode;
+	u8 aspm_l0s_l1_en;
+
+	int power_down_in_ss;
+
+	int sdr104_en;
+	int ddr50_en;
+	int sdr50_en;
+
+	int baro_pkg;
+
+	int asic_code;
+	int phy_debug_mode;
+	int hw_bypass_sd;
+	int sdio_func_exist;
+	int aux_pwr_exist;
+	u8 ms_power_class_en;
+
+	int mspro_formatter_enable;
+
+	int remote_wakeup_en;
+
+	int ignore_sd;
+	int use_hw_setting;
+
+	int ss_idle_period;
+
+	int dynamic_aspm;
+
+	int fpga_sd_sdr104_clk;
+	int fpga_sd_ddr50_clk;
+	int fpga_sd_sdr50_clk;
+	int fpga_sd_hs_clk;
+	int fpga_mmc_52m_clk;
+	int fpga_ms_hg_clk;
+	int fpga_ms_4bit_clk;
+	int fpga_ms_1bit_clk;
+
+	int asic_sd_sdr104_clk;
+	int asic_sd_ddr50_clk;
+	int asic_sd_sdr50_clk;
+	int asic_sd_hs_clk;
+	int asic_mmc_52m_clk;
+	int asic_ms_hg_clk;
+	int asic_ms_4bit_clk;
+	int asic_ms_1bit_clk;
+
+	u8 ssc_depth_sd_sdr104;
+	u8 ssc_depth_sd_ddr50;
+	u8 ssc_depth_sd_sdr50;
+	u8 ssc_depth_sd_hs;
+	u8 ssc_depth_mmc_52m;
+	u8 ssc_depth_ms_hg;
+	u8 ssc_depth_ms_4bit;
+	u8 ssc_depth_low_speed;
+
+	u8 card_drive_sel;
+	u8 sd30_drive_sel_1v8;
+	u8 sd30_drive_sel_3v3;
+
+	u8 sd_400mA_ocp_thd;
+	u8 sd_800mA_ocp_thd;
+	u8 ms_ocp_thd;
+
+	int ssc_en;
+	int msi_en;
+
+	int xd_timeout;
+	int sd_timeout;
+	int ms_timeout;
+	int mspro_timeout;
+
+	int auto_power_down;
+
+	int sd_ddr_tx_phase;
+	int mmc_ddr_tx_phase;
+	int sd_default_tx_phase;
+	int sd_default_rx_phase;
+
+	int pmos_pwr_on_interval;
+	int sd_voltage_switch_delay;
+	int s3_pwr_off_delay;
+
+	int force_clkreq_0;
+	int ft2_fast_mode;
+
+	int do_delink_before_power_down;
+	int polling_config;
+	int sdio_retry_cnt;
+
+	int delink_stage1_step;
+	int delink_stage2_step;
+	int delink_stage3_step;
+
+	int auto_delink_in_L1;
+	int hp_watch_bios_hotplug;
+	int support_ms_8bit;
+
+	u8 blink_led;
+	u8 phy_voltage;
+	u8 max_payload;
+
+	u32 sd_speed_prior;
+	u32 sd_current_prior;
+	u32 sd_ctl;
+};
+
+#define rtsx_set_stat(chip, stat)				\
+do {								\
+	if ((stat) != RTSX_STAT_IDLE) {				\
+		(chip)->idle_counter = 0;			\
+	}							\
+	(chip)->rtsx_stat = (enum RTSX_STAT)(stat);		\
+} while (0)
+#define rtsx_get_stat(chip)		((chip)->rtsx_stat)
+#define rtsx_chk_stat(chip, stat)	((chip)->rtsx_stat == (stat))
+
+#define RTSX_SET_DELINK(chip)	((chip)->rtsx_flag |= 0x01)
+#define RTSX_CLR_DELINK(chip)	((chip)->rtsx_flag &= 0xFE)
+#define RTSX_TST_DELINK(chip)	((chip)->rtsx_flag & 0x01)
+
+#define CHECK_PID(chip, pid)		((chip)->product_id == (pid))
+#define CHECK_BARO_PKG(chip, pkg)	((chip)->baro_pkg == (pkg))
+#define CHECK_LUN_MODE(chip, mode)	((chip)->lun_mode == (mode))
+
+/* Power down control */
+#define SSC_PDCTL		0x01
+#define OC_PDCTL		0x02
+
+int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl);
+int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl);
+
+void rtsx_disable_card_int(struct rtsx_chip *chip);
+void rtsx_enable_card_int(struct rtsx_chip *chip);
+void rtsx_enable_bus_int(struct rtsx_chip *chip);
+void rtsx_disable_bus_int(struct rtsx_chip *chip);
+int rtsx_reset_chip(struct rtsx_chip *chip);
+int rtsx_init_chip(struct rtsx_chip *chip);
+void rtsx_release_chip(struct rtsx_chip *chip);
+void rtsx_polling_func(struct rtsx_chip *chip);
+void rtsx_undo_delink(struct rtsx_chip *chip);
+void rtsx_stop_cmd(struct rtsx_chip *chip, int card);
+int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data);
+int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data);
+int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask, u32 val);
+int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val);
+int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len);
+int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf, int len);
+int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val);
+int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val);
+int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val);
+int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val);
+int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
+int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
+int rtsx_check_link_ready(struct rtsx_chip *chip);
+void rtsx_enter_ss(struct rtsx_chip *chip);
+void rtsx_exit_ss(struct rtsx_chip *chip);
+int rtsx_pre_handle_interrupt(struct rtsx_chip *chip);
+void rtsx_enter_L1(struct rtsx_chip *chip);
+void rtsx_exit_L1(struct rtsx_chip *chip);
+void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat);
+void rtsx_enable_aspm(struct rtsx_chip *chip);
+void rtsx_disable_aspm(struct rtsx_chip *chip);
+int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
+int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
+int rtsx_check_chip_exist(struct rtsx_chip *chip);
+
+#define RTSX_WRITE_REG(chip, addr, mask, data)					\
+do {										\
+	int retval = rtsx_write_register((chip), (addr), (mask), (data));	\
+	if (retval != STATUS_SUCCESS) {						\
+		TRACE_RET((chip), retval);					\
+	}									\
+} while (0)
+
+#define RTSX_READ_REG(chip, addr, data)						\
+do {										\
+	int retval = rtsx_read_register((chip), (addr), (data));		\
+	if (retval != STATUS_SUCCESS) {						\
+		TRACE_RET((chip), retval);					\
+	}									\
+} while (0)
+
+#endif  /* __REALTEK_RTSX_CHIP_H */
diff --git a/drivers/staging/rts_pstor/rtsx_scsi.c b/drivers/staging/rts_pstor/rtsx_scsi.c
new file mode 100644
index 0000000..20c2464
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_scsi.c
@@ -0,0 +1,3203 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_sys.h"
+#include "rtsx_card.h"
+#include "rtsx_chip.h"
+#include "rtsx_scsi.h"
+#include "sd.h"
+#include "ms.h"
+#include "spi.h"
+
+void scsi_show_command(struct scsi_cmnd *srb)
+{
+	char *what = NULL;
+	int i, unknown_cmd = 0;
+
+	switch (srb->cmnd[0]) {
+	case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
+	case REZERO_UNIT: what = "REZERO_UNIT"; break;
+	case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
+	case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
+	case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
+	case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
+	case READ_6: what = "READ_6"; break;
+	case WRITE_6: what = "WRITE_6"; break;
+	case SEEK_6: what = "SEEK_6"; break;
+	case READ_REVERSE: what = "READ_REVERSE"; break;
+	case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
+	case SPACE: what = "SPACE"; break;
+	case INQUIRY: what = "INQUIRY"; break;
+	case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
+	case MODE_SELECT: what = "MODE_SELECT"; break;
+	case RESERVE: what = "RESERVE"; break;
+	case RELEASE: what = "RELEASE"; break;
+	case COPY: what = "COPY"; break;
+	case ERASE: what = "ERASE"; break;
+	case MODE_SENSE: what = "MODE_SENSE"; break;
+	case START_STOP: what = "START_STOP"; break;
+	case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
+	case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
+	case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
+	case SET_WINDOW: what = "SET_WINDOW"; break;
+	case READ_CAPACITY: what = "READ_CAPACITY"; break;
+	case READ_10: what = "READ_10"; break;
+	case WRITE_10: what = "WRITE_10"; break;
+	case SEEK_10: what = "SEEK_10"; break;
+	case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
+	case VERIFY: what = "VERIFY"; break;
+	case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
+	case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
+	case SEARCH_LOW: what = "SEARCH_LOW"; break;
+	case SET_LIMITS: what = "SET_LIMITS"; break;
+	case READ_POSITION: what = "READ_POSITION"; break;
+	case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
+	case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
+	case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
+	case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
+	case COMPARE: what = "COMPARE"; break;
+	case COPY_VERIFY: what = "COPY_VERIFY"; break;
+	case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
+	case READ_BUFFER: what = "READ_BUFFER"; break;
+	case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
+	case READ_LONG: what = "READ_LONG"; break;
+	case WRITE_LONG: what = "WRITE_LONG"; break;
+	case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
+	case WRITE_SAME: what = "WRITE_SAME"; break;
+	case GPCMD_READ_SUBCHANNEL: what = "READ SUBCHANNEL"; break;
+	case READ_TOC: what = "READ_TOC"; break;
+	case GPCMD_READ_HEADER: what = "READ HEADER"; break;
+	case GPCMD_PLAY_AUDIO_10: what = "PLAY AUDIO (10)"; break;
+	case GPCMD_PLAY_AUDIO_MSF: what = "PLAY AUDIO MSF"; break;
+	case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
+		what = "GET EVENT/STATUS NOTIFICATION"; break;
+	case GPCMD_PAUSE_RESUME: what = "PAUSE/RESUME"; break;
+	case LOG_SELECT: what = "LOG_SELECT"; break;
+	case LOG_SENSE: what = "LOG_SENSE"; break;
+	case GPCMD_STOP_PLAY_SCAN: what = "STOP PLAY/SCAN"; break;
+	case GPCMD_READ_DISC_INFO: what = "READ DISC INFORMATION"; break;
+	case GPCMD_READ_TRACK_RZONE_INFO:
+		what = "READ TRACK INFORMATION"; break;
+	case GPCMD_RESERVE_RZONE_TRACK: what = "RESERVE TRACK"; break;
+	case GPCMD_SEND_OPC: what = "SEND OPC"; break;
+	case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
+	case GPCMD_REPAIR_RZONE_TRACK: what = "REPAIR TRACK"; break;
+	case 0x59: what = "READ MASTER CUE"; break;
+	case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
+	case GPCMD_CLOSE_TRACK: what = "CLOSE TRACK/SESSION"; break;
+	case 0x5C: what = "READ BUFFER CAPACITY"; break;
+	case 0x5D: what = "SEND CUE SHEET"; break;
+	case GPCMD_BLANK: what = "BLANK"; break;
+	case REPORT_LUNS: what = "REPORT LUNS"; break;
+	case MOVE_MEDIUM: what = "MOVE_MEDIUM or PLAY AUDIO (12)"; break;
+	case READ_12: what = "READ_12"; break;
+	case WRITE_12: what = "WRITE_12"; break;
+	case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
+	case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
+	case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
+	case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
+	case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
+	case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
+	case GPCMD_READ_CD_MSF: what = "READ CD MSF"; break;
+	case GPCMD_SCAN: what = "SCAN"; break;
+	case GPCMD_SET_SPEED: what = "SET CD SPEED"; break;
+	case GPCMD_MECHANISM_STATUS: what = "MECHANISM STATUS"; break;
+	case GPCMD_READ_CD: what = "READ CD"; break;
+	case 0xE1: what = "WRITE CONTINUE"; break;
+	case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
+	case VENDOR_CMND: what = "Realtek's vendor command"; break;
+	default: what = "(unknown command)"; unknown_cmd = 1; break;
+	}
+
+	if (srb->cmnd[0] != TEST_UNIT_READY) {
+		RTSX_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
+	}
+	if (unknown_cmd) {
+		RTSX_DEBUGP("");
+		for (i = 0; i < srb->cmd_len && i < 16; i++)
+			RTSX_DEBUGPN(" %02x", srb->cmnd[i]);
+		RTSX_DEBUGPN("\n");
+	}
+}
+
+void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type)
+{
+	switch (sense_type) {
+	case SENSE_TYPE_MEDIA_CHANGE:
+		set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_NOT_PRESENT:
+		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
+		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
+		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_WRITE_PROTECT:
+		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
+		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_WRITE_ERR:
+		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
+		break;
+
+	case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
+		set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
+				ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
+		break;
+
+	case SENSE_TYPE_FORMAT_IN_PROGRESS:
+		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
+		break;
+
+	case SENSE_TYPE_FORMAT_CMD_FAILED:
+		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
+		break;
+
+#ifdef SUPPORT_MAGIC_GATE
+	case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
+		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
+		break;
+
+	case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
+		set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
+		break;
+
+	case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
+		set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
+		break;
+
+	case SENSE_TYPE_MG_WRITE_ERR:
+		set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
+		break;
+#endif
+
+#ifdef SUPPORT_SD_LOCK
+	case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
+		set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
+		break;
+#endif
+
+	case SENSE_TYPE_NO_SENSE:
+	default:
+		set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
+		break;
+	}
+}
+
+void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key,
+		u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1)
+{
+	struct sense_data_t *sense = &(chip->sense_buffer[lun]);
+
+	sense->err_code = err_code;
+	sense->sense_key = sense_key;
+	sense->info[0] = (u8)(info >> 24);
+	sense->info[1] = (u8)(info >> 16);
+	sense->info[2] = (u8)(info >> 8);
+	sense->info[3] = (u8)info;
+
+	sense->ad_sense_len = sizeof(struct sense_data_t) - 8;
+	sense->asc = asc;
+	sense->ascq = ascq;
+	if (sns_key_info0 != 0) {
+		sense->sns_key_info[0] = SKSV | sns_key_info0;
+		sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8;
+		sense->sns_key_info[2] = sns_key_info1 & 0x0f;
+	}
+}
+
+static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		return TRANSPORT_FAILED;
+	}
+
+	if (!(CHK_BIT(chip->lun_mc, lun))) {
+		SET_BIT(chip->lun_mc, lun);
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		return TRANSPORT_FAILED;
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
+		struct sd_info *sd_card = &(chip->sd_card);
+		if (sd_card->sd_lock_notify) {
+			sd_card->sd_lock_notify = 0;
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+			return TRANSPORT_FAILED;
+		} else if (sd_card->sd_lock_status & SD_LOCKED) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
+			return TRANSPORT_FAILED;
+		}
+	}
+#endif
+
+	return TRANSPORT_GOOD;
+}
+
+static unsigned char formatter_inquiry_str[20] = {
+	'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K',
+#ifdef SUPPORT_MAGIC_GATE
+	'-', 'M', 'G', /* Byte[47:49] */
+#else
+	0x20, 0x20, 0x20,  /* Byte[47:49] */
+#endif
+
+#ifdef SUPPORT_MAGIC_GATE
+	0x0B,  /* Byte[50]: MG, MS, MSPro, MSXC */
+#else
+	0x09,  /* Byte[50]: MS, MSPro, MSXC */
+#endif
+	0x00,  /* Byte[51]: Category Specific Commands */
+	0x00,  /* Byte[52]: Access Control and feature */
+	0x20, 0x20, 0x20, /* Byte[53:55] */
+};
+
+static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+	char *inquiry_default = (char *)"Generic-xD/SD/M.S.      1.00 ";
+	char *inquiry_sdms =    (char *)"Generic-SD/MemoryStick  1.00 ";
+	char *inquiry_sd =      (char *)"Generic-SD/MMC          1.00 ";
+	char *inquiry_ms =      (char *)"Generic-MemoryStick     1.00 ";
+	char *inquiry_string;
+	unsigned char sendbytes;
+	unsigned char *buf;
+	u8 card = get_lun_card(chip, lun);
+	int pro_formatter_flag = 0;
+	unsigned char inquiry_buf[] = {
+		QULIFIRE|DRCT_ACCESS_DEV,
+		RMB_DISC|0x0D,
+		0x00,
+		0x01,
+		0x1f,
+		0x02,
+		0,
+		REL_ADR|WBUS_32|WBUS_16|SYNC|LINKED|CMD_QUE|SFT_RE,
+	};
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		if (chip->lun2card[lun] == SD_CARD) {
+			inquiry_string = inquiry_sd;
+		} else {
+			inquiry_string = inquiry_ms;
+		}
+	} else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
+		inquiry_string = inquiry_sdms;
+	} else {
+		inquiry_string = inquiry_default;
+	}
+
+	buf = vmalloc(scsi_bufflen(srb));
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+#ifdef SUPPORT_MAGIC_GATE
+	if ((chip->mspro_formatter_enable) &&
+			(chip->lun2card[lun] & MS_CARD))
+#else
+	if (chip->mspro_formatter_enable)
+#endif
+	{
+		if (!card || (card == MS_CARD)) {
+			pro_formatter_flag = 1;
+		}
+	}
+
+	if (pro_formatter_flag) {
+		if (scsi_bufflen(srb) < 56) {
+			sendbytes = (unsigned char)(scsi_bufflen(srb));
+		} else {
+			sendbytes = 56;
+		}
+	} else {
+		if (scsi_bufflen(srb) < 36) {
+			sendbytes = (unsigned char)(scsi_bufflen(srb));
+		} else {
+			sendbytes = 36;
+		}
+	}
+
+	if (sendbytes > 8) {
+		memcpy(buf, inquiry_buf, 8);
+		memcpy(buf + 8, inquiry_string,	sendbytes - 8);
+		if (pro_formatter_flag) {
+			/* Additional Length */
+			buf[4] = 0x33;
+		}
+	} else {
+		memcpy(buf, inquiry_buf, sendbytes);
+	}
+
+	if (pro_formatter_flag) {
+		if (sendbytes > 36) {
+			memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36);
+		}
+	}
+
+	scsi_set_resid(srb, 0);
+
+	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+
+static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+
+	scsi_set_resid(srb, scsi_bufflen(srb));
+
+	if (srb->cmnd[1] == 1)
+		return TRANSPORT_GOOD;
+
+	switch (srb->cmnd[0x4]) {
+	case STOP_MEDIUM:
+		/* Media disabled */
+		return TRANSPORT_GOOD;
+
+	case UNLOAD_MEDIUM:
+		/* Media shall be unload */
+		if (check_card_ready(chip, lun))
+			eject_card(chip, lun);
+		return TRANSPORT_GOOD;
+
+	case MAKE_MEDIUM_READY:
+	case LOAD_MEDIUM:
+		if (check_card_ready(chip, lun)) {
+			return TRANSPORT_GOOD;
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+
+		break;
+	}
+
+	TRACE_RET(chip, TRANSPORT_ERROR);
+}
+
+
+static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int prevent;
+
+	prevent = srb->cmnd[4] & 0x1;
+
+	scsi_set_resid(srb, 0);
+
+	if (prevent) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+
+static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sense_data_t *sense;
+	unsigned int lun = SCSI_LUN(srb);
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned char *tmp, *buf;
+
+	sense = &(chip->sense_buffer[lun]);
+
+	if ((get_lun_card(chip, lun) == MS_CARD) && ms_card->pro_under_formatting) {
+		if (ms_card->format_status == FORMAT_SUCCESS) {
+			set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+			ms_card->pro_under_formatting = 0;
+			ms_card->progress = 0;
+		} else if (ms_card->format_status == FORMAT_IN_PROGRESS) {
+			/* Logical Unit Not Ready Format in Progress */
+			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
+					0, (u16)(ms_card->progress));
+		} else {
+			/* Format Command Failed */
+			set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
+			ms_card->pro_under_formatting = 0;
+			ms_card->progress = 0;
+		}
+
+		rtsx_set_stat(chip, RTSX_STAT_RUN);
+	}
+
+	buf = vmalloc(scsi_bufflen(srb));
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	tmp = (unsigned char *)sense;
+	memcpy(buf, tmp, scsi_bufflen(srb));
+
+	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
+	vfree(buf);
+
+	scsi_set_resid(srb, 0);
+	/* Reset Sense Data */
+	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	return TRANSPORT_GOOD;
+}
+
+static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
+		int lun, u8 *buf, int buf_len)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	int sys_info_offset;
+	int data_size = buf_len;
+	int support_format = 0;
+	int i = 0;
+
+	if (cmd == MODE_SENSE) {
+		sys_info_offset = 8;
+		if (data_size > 0x68) {
+			data_size = 0x68;
+		}
+		buf[i++] = 0x67;  /* Mode Data Length */
+	} else {
+		sys_info_offset = 12;
+		if (data_size > 0x6C) {
+			data_size = 0x6C;
+		}
+		buf[i++] = 0x00;  /* Mode Data Length (MSB) */
+		buf[i++] = 0x6A;  /* Mode Data Length (LSB) */
+	}
+
+	/* Medium Type Code */
+	if (check_card_ready(chip, lun)) {
+		if (CHK_MSXC(ms_card)) {
+			support_format = 1;
+			buf[i++] = 0x40;
+		} else if (CHK_MSPRO(ms_card)) {
+			support_format = 1;
+			buf[i++] = 0x20;
+		} else {
+			buf[i++] = 0x10;
+		}
+
+		/* WP */
+		if (check_card_wp(chip, lun)) {
+			buf[i++] = 0x80;
+		} else {
+			buf[i++] = 0x00;
+		}
+	} else {
+		buf[i++] = 0x00;	/* MediaType */
+		buf[i++] = 0x00;	/* WP */
+	}
+
+	buf[i++] = 0x00;		/* Reserved */
+
+	if (cmd == MODE_SENSE_10) {
+		buf[i++] = 0x00;  /* Reserved */
+		buf[i++] = 0x00;  /* Block descriptor length(MSB) */
+		buf[i++] = 0x00;  /* Block descriptor length(LSB) */
+
+		/* The Following Data is the content of "Page 0x20" */
+		if (data_size >= 9)
+			buf[i++] = 0x20;		/* Page Code */
+		if (data_size >= 10)
+			buf[i++] = 0x62;		/* Page Length */
+		if (data_size >= 11)
+			buf[i++] = 0x00;		/* No Access Control */
+		if (data_size >= 12) {
+			if (support_format) {
+				buf[i++] = 0xC0;	/* SF, SGM */
+			} else {
+				buf[i++] = 0x00;
+			}
+		}
+	} else {
+		/* The Following Data is the content of "Page 0x20" */
+		if (data_size >= 5)
+			buf[i++] = 0x20;		/* Page Code */
+		if (data_size >= 6)
+			buf[i++] = 0x62;		/* Page Length */
+		if (data_size >= 7)
+			buf[i++] = 0x00;		/* No Access Control */
+		if (data_size >= 8) {
+			if (support_format) {
+				buf[i++] = 0xC0;	/* SF, SGM */
+			} else {
+				buf[i++] = 0x00;
+			}
+		}
+	}
+
+	if (data_size > sys_info_offset) {
+		/* 96 Bytes Attribute Data */
+		int len = data_size - sys_info_offset;
+		len = (len < 96) ? len : 96;
+
+		memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len);
+	}
+}
+
+static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+	unsigned int dataSize;
+	int status;
+	int pro_formatter_flag;
+	unsigned char pageCode, *buf;
+	u8 card = get_lun_card(chip, lun);
+
+#ifndef SUPPORT_MAGIC_GATE
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		scsi_set_resid(srb, scsi_bufflen(srb));
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+#endif
+
+	pro_formatter_flag = 0;
+	dataSize = 8;
+#ifdef SUPPORT_MAGIC_GATE
+	if ((chip->lun2card[lun] & MS_CARD)) {
+		if (!card || (card == MS_CARD)) {
+			dataSize = 108;
+			if (chip->mspro_formatter_enable) {
+				pro_formatter_flag = 1;
+			}
+		}
+	}
+#else
+	if (card == MS_CARD) {
+		if (chip->mspro_formatter_enable) {
+			pro_formatter_flag = 1;
+			dataSize = 108;
+		}
+	}
+#endif
+
+	buf = kmalloc(dataSize, GFP_KERNEL);
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	pageCode = srb->cmnd[2] & 0x3f;
+
+	if ((pageCode == 0x3F) || (pageCode == 0x1C) ||
+		(pageCode == 0x00) ||
+		(pro_formatter_flag && (pageCode == 0x20))) {
+		if (srb->cmnd[0] == MODE_SENSE) {
+			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
+				ms_mode_sense(chip, srb->cmnd[0],
+					      lun, buf, dataSize);
+			} else {
+				dataSize = 4;
+				buf[0] = 0x03;
+				buf[1] = 0x00;
+				if (check_card_wp(chip, lun)) {
+					buf[2] = 0x80;
+				} else {
+					buf[2] = 0x00;
+				}
+				buf[3] = 0x00;
+			}
+		} else {
+			if ((pageCode == 0x3F) || (pageCode == 0x20)) {
+				ms_mode_sense(chip, srb->cmnd[0],
+					      lun, buf, dataSize);
+			} else {
+				dataSize = 8;
+				buf[0] = 0x00;
+				buf[1] = 0x06;
+				buf[2] = 0x00;
+				if (check_card_wp(chip, lun)) {
+					buf[3] = 0x80;
+				} else {
+					buf[3] = 0x00;
+				}
+				buf[4] = 0x00;
+				buf[5] = 0x00;
+				buf[6] = 0x00;
+				buf[7] = 0x00;
+			}
+		}
+		status = TRANSPORT_GOOD;
+	} else {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		scsi_set_resid(srb, scsi_bufflen(srb));
+		status = TRANSPORT_FAILED;
+	}
+
+	if (status == TRANSPORT_GOOD) {
+		unsigned int len = min(scsi_bufflen(srb), dataSize);
+		rtsx_stor_set_xfer_buf(buf, len, srb);
+		scsi_set_resid(srb, scsi_bufflen(srb) - len);
+	}
+	kfree(buf);
+
+	return status;
+}
+
+static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+#ifdef SUPPORT_SD_LOCK
+	struct sd_info *sd_card = &(chip->sd_card);
+#endif
+	unsigned int lun = SCSI_LUN(srb);
+	int retval;
+	u32 start_sec;
+	u16 sec_cnt;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (!(CHK_BIT(chip->lun_mc, lun))) {
+		SET_BIT(chip->lun_mc, lun);
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		return TRANSPORT_FAILED;
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_erase_status) {
+		/* Accessing to any card is forbidden
+		 * until the erase procedure of SD is completed
+		 */
+		RTSX_DEBUGP("SD card being erased!\n");
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (get_lun_card(chip, lun) == SD_CARD) {
+		if (sd_card->sd_lock_status & SD_LOCKED) {
+			RTSX_DEBUGP("SD card locked!\n");
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+#endif
+
+	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
+		start_sec = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) |
+			((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]);
+		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
+	} else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
+		start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) |
+			((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]);
+		sec_cnt = srb->cmnd[4];
+	} else if ((srb->cmnd[0] == VENDOR_CMND) && (srb->cmnd[1] == SCSI_APP_CMD) &&
+			((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) {
+		start_sec = ((u32)srb->cmnd[4] << 24) | ((u32)srb->cmnd[5] << 16) |
+			((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]);
+		sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
+	} else {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	/* In some test, we will receive a start_sec like 0xFFFFFFFF.
+	 * In this situation, start_sec + sec_cnt will overflow, so we
+	 * need to judge start_sec at first
+	 */
+	if ((start_sec > get_card_size(chip, lun)) ||
+			((start_sec + sec_cnt) > get_card_size(chip, lun))) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (sec_cnt == 0) {
+		scsi_set_resid(srb, 0);
+		return TRANSPORT_GOOD;
+	}
+
+	if (chip->rw_fail_cnt[lun] == 3) {
+		RTSX_DEBUGP("read/write fail three times in succession\n");
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+		}
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
+		if (check_card_wp(chip, lun)) {
+			RTSX_DEBUGP("Write protected card!\n");
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		if (CHECK_PID(chip, 0x5209) && chip->max_payload) {
+			u8 val = 0x10 | (chip->max_payload << 5);
+			retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, val);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_ERROR);
+			}
+		}
+	}
+
+	retval = card_rw(srb, chip, start_sec, sec_cnt);
+	if (retval != STATUS_SUCCESS) {
+		if (chip->need_release & chip->lun2card[lun]) {
+			chip->rw_fail_cnt[lun] = 0;
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		} else {
+			chip->rw_fail_cnt[lun]++;
+			if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			} else {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+			}
+		}
+		retval = TRANSPORT_FAILED;
+		TRACE_GOTO(chip, Exit);
+	} else {
+		chip->rw_fail_cnt[lun] = 0;
+		retval = TRANSPORT_GOOD;
+	}
+
+	scsi_set_resid(srb, 0);
+
+Exit:
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
+		if (CHECK_PID(chip, 0x5209) && chip->max_payload) {
+			retval = rtsx_write_cfg_dw(chip, 0, 0x78, 0xFF, 0x10);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_ERROR);
+			}
+		}
+	}
+
+	return retval;
+}
+
+static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned char *buf;
+	unsigned int lun = SCSI_LUN(srb);
+	unsigned int buf_len;
+	u8 card = get_lun_card(chip, lun);
+	u32 card_size;
+	int desc_cnt;
+	int i = 0;
+
+	if (!check_card_ready(chip, lun)) {
+		if (!chip->mspro_formatter_enable) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
+
+	buf = kmalloc(buf_len, GFP_KERNEL);
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	buf[i++] = 0;
+	buf[i++] = 0;
+	buf[i++] = 0;
+
+	/* Capacity List Length */
+	if ((buf_len > 12) && chip->mspro_formatter_enable &&
+			(chip->lun2card[lun] & MS_CARD) &&
+			(!card || (card == MS_CARD))) {
+		buf[i++] = 0x10;
+		desc_cnt = 2;
+	} else {
+		buf[i++] = 0x08;
+		desc_cnt = 1;
+	}
+
+	while (desc_cnt) {
+		if (check_card_ready(chip, lun)) {
+			card_size = get_card_size(chip, lun);
+			buf[i++] = (unsigned char)(card_size >> 24);
+			buf[i++] = (unsigned char)(card_size >> 16);
+			buf[i++] = (unsigned char)(card_size >> 8);
+			buf[i++] = (unsigned char)card_size;
+
+			if (desc_cnt == 2) {
+				buf[i++] = 2;
+			} else {
+				buf[i++] = 0;
+			}
+		} else {
+			buf[i++] = 0xFF;
+			buf[i++] = 0xFF;
+			buf[i++] = 0xFF;
+			buf[i++] = 0xFF;
+
+			if (desc_cnt == 2) {
+				buf[i++] = 3;
+			} else {
+				buf[i++] = 0;
+			}
+		}
+
+		buf[i++] = 0x00;
+		buf[i++] = 0x02;
+		buf[i++] = 0x00;
+
+		desc_cnt--;
+	}
+
+	buf_len = min(scsi_bufflen(srb), buf_len);
+	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
+	kfree(buf);
+
+	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
+
+	return TRANSPORT_GOOD;
+}
+
+static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned char *buf;
+	unsigned int lun = SCSI_LUN(srb);
+	u32 card_size;
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (!(CHK_BIT(chip->lun_mc, lun))) {
+		SET_BIT(chip->lun_mc, lun);
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		return TRANSPORT_FAILED;
+	}
+
+	buf = kmalloc(8, GFP_KERNEL);
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	card_size = get_card_size(chip, lun);
+	buf[0] = (unsigned char)((card_size - 1) >> 24);
+	buf[1] = (unsigned char)((card_size - 1) >> 16);
+	buf[2] = (unsigned char)((card_size - 1) >> 8);
+	buf[3] = (unsigned char)(card_size - 1);
+
+	buf[4] = 0x00;
+	buf[5] = 0x00;
+	buf[6] = 0x02;
+	buf[7] = 0x00;
+
+	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
+	kfree(buf);
+
+	scsi_set_resid(srb, 0);
+
+	return TRANSPORT_GOOD;
+}
+
+static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short len, i;
+	int retval;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+
+	buf = (u8 *)vmalloc(len);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	for (i = 0; i < len; i++) {
+		retval = spi_read_eeprom(chip, i, buf + i);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short len, i;
+	int retval;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (len == 511) {
+		retval = spi_erase_eeprom_chip(chip);
+		if (retval != STATUS_SUCCESS) {
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	} else {
+		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+		buf = (u8 *)vmalloc(len);
+		if (buf == NULL) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		rtsx_stor_get_xfer_buf(buf, len, srb);
+		scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+		for (i = 0; i < len; i++) {
+			retval = spi_write_eeprom(chip, i, buf[i]);
+			if (retval != STATUS_SUCCESS) {
+				vfree(buf);
+				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		}
+
+		vfree(buf);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr, len, i;
+	int retval;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
+	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+
+	if (addr < 0xFC00) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	buf = (u8 *)vmalloc(len);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	for (i = 0; i < len; i++) {
+		retval = rtsx_read_register(chip, addr + i, buf + i);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr, len, i;
+	int retval;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
+	len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+
+	if (addr < 0xFC00) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+	buf = (u8 *)vmalloc(len);
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	rtsx_stor_get_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	for (i = 0; i < len; i++) {
+		retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (get_lun_card(chip, lun) != SD_CARD) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	scsi_set_resid(srb, 0);
+	rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb);
+
+	return TRANSPORT_GOOD;
+}
+
+static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	u8 gpio = srb->cmnd[2];
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	if (gpio > 3)
+		gpio = 1;
+	toggle_gpio(chip, gpio);
+
+	return TRANSPORT_GOOD;
+}
+
+#ifdef _MSG_TRACE
+static int trace_msg_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned char *ptr, *buf = NULL;
+	int i, msg_cnt;
+	u8 clear;
+	unsigned int buf_len;
+
+	buf_len = 4 + ((2 + MSG_FUNC_LEN + MSG_FILE_LEN + TIME_VAL_LEN) * TRACE_ITEM_CNT);
+
+	if ((scsi_bufflen(srb) < buf_len) || (scsi_sglist(srb) == NULL)) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	clear = srb->cmnd[2];
+
+	buf = (unsigned char *)vmalloc(scsi_bufflen(srb));
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+	ptr = buf;
+
+	if (chip->trace_msg[chip->msg_idx].valid) {
+		msg_cnt = TRACE_ITEM_CNT;
+	} else {
+		msg_cnt = chip->msg_idx;
+	}
+	*(ptr++) = (u8)(msg_cnt >> 24);
+	*(ptr++) = (u8)(msg_cnt >> 16);
+	*(ptr++) = (u8)(msg_cnt >> 8);
+	*(ptr++) = (u8)msg_cnt;
+	RTSX_DEBUGP("Trace message count is %d\n", msg_cnt);
+
+	for (i = 1; i <= msg_cnt; i++) {
+		int j, idx;
+
+		idx = chip->msg_idx - i;
+		if (idx < 0)
+			idx += TRACE_ITEM_CNT;
+
+		*(ptr++) = (u8)(chip->trace_msg[idx].line >> 8);
+		*(ptr++) = (u8)(chip->trace_msg[idx].line);
+		for (j = 0; j < MSG_FUNC_LEN; j++) {
+			*(ptr++) = chip->trace_msg[idx].func[j];
+		}
+		for (j = 0; j < MSG_FILE_LEN; j++) {
+			*(ptr++) = chip->trace_msg[idx].file[j];
+		}
+		for (j = 0; j < TIME_VAL_LEN; j++) {
+			*(ptr++) = chip->trace_msg[idx].timeval_buf[j];
+		}
+	}
+
+	rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
+	vfree(buf);
+
+	if (clear) {
+		chip->msg_idx = 0;
+		for (i = 0; i < TRACE_ITEM_CNT; i++)
+			chip->trace_msg[i].valid = 0;
+	}
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+}
+#endif
+
+static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	u8 addr, buf[4];
+	u32 val;
+	unsigned int len;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = srb->cmnd[4];
+
+	val = rtsx_readl(chip, addr);
+	RTSX_DEBUGP("Host register (0x%x): 0x%x\n", addr, val);
+
+	buf[0] = (u8)(val >> 24);
+	buf[1] = (u8)(val >> 16);
+	buf[2] = (u8)(val >> 8);
+	buf[3] = (u8)val;
+
+	len = min(scsi_bufflen(srb), (unsigned int)4);
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	u8 addr, buf[4];
+	u32 val;
+	unsigned int len;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = srb->cmnd[4];
+
+	len = min(scsi_bufflen(srb), (unsigned int)4);
+	rtsx_stor_get_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2] << 8) | buf[3];
+
+	rtsx_writel(chip, addr, val);
+
+	return TRANSPORT_GOOD;
+}
+
+static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned lun = SCSI_LUN(srb);
+
+	if (srb->cmnd[3] == 1) {
+		/* Variable Clock */
+		struct xd_info *xd_card = &(chip->xd_card);
+		struct sd_info *sd_card = &(chip->sd_card);
+		struct ms_info *ms_card = &(chip->ms_card);
+
+		switch (srb->cmnd[4]) {
+		case XD_CARD:
+			xd_card->xd_clock = srb->cmnd[5];
+			break;
+
+		case SD_CARD:
+			sd_card->sd_clock = srb->cmnd[5];
+			break;
+
+		case MS_CARD:
+			ms_card->ms_clock = srb->cmnd[5];
+			break;
+
+		default:
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	} else if (srb->cmnd[3] == 2) {
+		if (srb->cmnd[4]) {
+			chip->blink_led = 1;
+		} else {
+			int retval;
+
+			chip->blink_led = 0;
+
+			rtsx_disable_aspm(chip);
+
+			if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+				rtsx_exit_ss(chip);
+				wait_timeout(100);
+			}
+			rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+			retval = rtsx_force_power_on(chip, SSC_PDCTL);
+			if (retval != STATUS_SUCCESS) {
+				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+
+			turn_off_led(chip, LED_GPIO);
+		}
+	} else {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+
+	if (srb->cmnd[3] == 1) {
+		struct xd_info *xd_card = &(chip->xd_card);
+		struct sd_info *sd_card = &(chip->sd_card);
+		struct ms_info *ms_card = &(chip->ms_card);
+		u8 tmp;
+
+		switch (srb->cmnd[4]) {
+		case XD_CARD:
+			tmp = (u8)(xd_card->xd_clock);
+			break;
+
+		case SD_CARD:
+			tmp = (u8)(sd_card->sd_clock);
+			break;
+
+		case MS_CARD:
+			tmp = (u8)(ms_card->ms_clock);
+			break;
+
+		default:
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+
+		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
+	} else if (srb->cmnd[3] == 2) {
+		u8 tmp = chip->blink_led;
+		rtsx_stor_set_xfer_buf(&tmp, 1, srb);
+	} else {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	unsigned int lun = SCSI_LUN(srb);
+	u16 len;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
+	len = min(len, (u16)scsi_bufflen(srb));
+
+	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+		RTSX_DEBUGP("Read from device\n");
+	} else {
+		RTSX_DEBUGP("Write to device\n");
+	}
+
+	retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len,
+			scsi_sg_count(srb), srb->sc_data_direction, 1000);
+	if (retval < 0) {
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+		}
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	scsi_set_resid(srb, 0);
+
+	return TRANSPORT_GOOD;
+}
+
+static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	struct ms_info *ms_card = &(chip->ms_card);
+	int buf_len;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 card = get_lun_card(chip, lun);
+	u8 status[32];
+#ifdef SUPPORT_OCP
+	u8 oc_now_mask = 0, oc_ever_mask = 0;
+#endif
+
+	memset(status, 0, 32);
+
+	status[0] = (u8)(chip->product_id);
+	status[1] = chip->ic_version;
+
+	if (chip->auto_delink_en) {
+		status[2] = 0x10;
+	} else {
+		status[2] = 0x00;
+	}
+
+	status[3] = 20;
+	status[4] = 10;
+	status[5] = 05;
+	status[6] = 21;
+
+	if (chip->card_wp) {
+		status[7] = 0x20;
+	} else {
+		status[7] = 0x00;
+	}
+
+#ifdef SUPPORT_OCP
+	status[8] = 0;
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && (chip->lun2card[lun] == MS_CARD)) {
+		oc_now_mask = MS_OC_NOW;
+		oc_ever_mask = MS_OC_EVER;
+	} else {
+		oc_now_mask = SD_OC_NOW;
+		oc_ever_mask = SD_OC_EVER;
+	}
+
+	if (chip->ocp_stat & oc_now_mask) {
+		status[8] |= 0x02;
+	}
+	if (chip->ocp_stat & oc_ever_mask) {
+		status[8] |= 0x01;
+	}
+#endif
+
+	if (card == SD_CARD) {
+		if (CHK_SD(sd_card)) {
+			if (CHK_SD_HCXC(sd_card)) {
+				if (sd_card->capacity > 0x4000000) {
+					status[0x0E] = 0x02;
+				} else {
+					status[0x0E] = 0x01;
+				}
+			} else {
+				status[0x0E] = 0x00;
+			}
+
+			if (CHK_SD_SDR104(sd_card)) {
+				status[0x0F] = 0x03;
+			} else if (CHK_SD_DDR50(sd_card)) {
+				status[0x0F] = 0x04;
+			} else if (CHK_SD_SDR50(sd_card)) {
+				status[0x0F] = 0x02;
+			} else if (CHK_SD_HS(sd_card)) {
+				status[0x0F] = 0x01;
+			} else {
+				status[0x0F] = 0x00;
+			}
+		} else {
+			if (CHK_MMC_SECTOR_MODE(sd_card)) {
+				status[0x0E] = 0x01;
+			} else {
+				status[0x0E] = 0x00;
+			}
+
+			if (CHK_MMC_DDR52(sd_card)) {
+				status[0x0F] = 0x03;
+			} else if (CHK_MMC_52M(sd_card)) {
+				status[0x0F] = 0x02;
+			} else if (CHK_MMC_26M(sd_card)) {
+				status[0x0F] = 0x01;
+			} else {
+				status[0x0F] = 0x00;
+			}
+		}
+	} else if (card == MS_CARD) {
+		if (CHK_MSPRO(ms_card)) {
+			if (CHK_MSXC(ms_card)) {
+				status[0x0E] = 0x01;
+			} else {
+				status[0x0E] = 0x00;
+			}
+
+			if (CHK_HG8BIT(ms_card)) {
+				status[0x0F] = 0x01;
+			} else {
+				status[0x0F] = 0x00;
+			}
+		}
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if (card == SD_CARD) {
+		status[0x17] = 0x80;
+		if (sd_card->sd_erase_status)
+			status[0x17] |= 0x01;
+		if (sd_card->sd_lock_status & SD_LOCKED) {
+			status[0x17] |= 0x02;
+			status[0x07] |= 0x40;
+		}
+		if (sd_card->sd_lock_status & SD_PWD_EXIST)
+			status[0x17] |= 0x04;
+	} else {
+		status[0x17] = 0x00;
+	}
+
+	RTSX_DEBUGP("status[0x17] = 0x%x\n", status[0x17]);
+#endif
+
+	status[0x18] = 0x8A;
+	status[0x1A] = 0x28;
+#ifdef SUPPORT_SD_LOCK
+	status[0x1F] = 0x01;
+#endif
+
+	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(status));
+	rtsx_stor_set_xfer_buf(status, buf_len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
+
+	return TRANSPORT_GOOD;
+}
+
+static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int phy_debug_mode;
+	int retval;
+	u16 reg;
+
+	if (!CHECK_PID(chip, 0x5208)) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	phy_debug_mode = (int)(srb->cmnd[3]);
+
+	if (phy_debug_mode) {
+		chip->phy_debug_mode = 1;
+		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		rtsx_disable_bus_int(chip);
+
+		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		reg |= 0x0001;
+		retval = rtsx_write_phy_register(chip, 0x1C, reg);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	} else {
+		chip->phy_debug_mode = 0;
+		retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		rtsx_enable_bus_int(chip);
+
+		retval = rtsx_read_phy_register(chip, 0x1C, &reg);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		reg &= 0xFFFE;
+		retval = rtsx_write_phy_register(chip, 0x1C, reg);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval =  STATUS_SUCCESS;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 cmd_type, mask, value, idx;
+	u16 addr;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	switch (srb->cmnd[3]) {
+	case INIT_BATCHCMD:
+		rtsx_init_cmd(chip);
+		break;
+
+	case ADD_BATCHCMD:
+		cmd_type = srb->cmnd[4];
+		if (cmd_type > 2) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
+		mask = srb->cmnd[7];
+		value = srb->cmnd[8];
+		rtsx_add_cmd(chip, cmd_type, addr, mask, value);
+		break;
+
+	case SEND_BATCHCMD:
+		retval = rtsx_send_cmd(chip, 0, 1000);
+		break;
+
+	case GET_BATCHRSP:
+		idx = srb->cmnd[4];
+		value = *(rtsx_get_cmd_data(chip) + idx);
+		if (scsi_bufflen(srb) < 1) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		rtsx_stor_set_xfer_buf(&value, 1, srb);
+		scsi_set_resid(srb, 0);
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int result;
+
+	switch (srb->cmnd[3]) {
+	case INIT_BATCHCMD:
+	case ADD_BATCHCMD:
+	case SEND_BATCHCMD:
+	case GET_BATCHRSP:
+		result = rw_mem_cmd_buf(srb, chip);
+		break;
+	default:
+		result = TRANSPORT_ERROR;
+	}
+
+	return result;
+}
+
+static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr, len, i;
+	int retval;
+	u8 *buf;
+	u16 val;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
+
+	if (len % 2)
+		len -= len % 2;
+
+	if (len) {
+		buf = (u8 *)vmalloc(len);
+		if (!buf) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		retval = rtsx_force_power_on(chip, SSC_PDCTL);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+
+		for (i = 0; i < len / 2; i++) {
+			retval = rtsx_read_phy_register(chip, addr + i, &val);
+			if (retval != STATUS_SUCCESS) {
+				vfree(buf);
+				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+
+			buf[2*i] = (u8)(val >> 8);
+			buf[2*i+1] = (u8)val;
+		}
+
+		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+		rtsx_stor_set_xfer_buf(buf, len, srb);
+		scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+		vfree(buf);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr, len, i;
+	int retval;
+	u8 *buf;
+	u16 val;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
+
+	if (len % 2)
+		len -= len % 2;
+
+	if (len) {
+		len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+
+		buf = (u8 *)vmalloc(len);
+		if (buf == NULL) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		rtsx_stor_get_xfer_buf(buf, len, srb);
+		scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+		retval = rtsx_force_power_on(chip, SSC_PDCTL);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+
+		for (i = 0; i < len / 2; i++) {
+			val = ((u16)buf[2*i] << 8) | buf[2*i+1];
+			retval = rtsx_write_phy_register(chip, addr + i, val);
+			if (retval != STATUS_SUCCESS) {
+				vfree(buf);
+				set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		}
+
+		vfree(buf);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr;
+	int retval;
+	u8 mode;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	mode = srb->cmnd[3];
+	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+
+	if (mode == 0) {
+		retval = spi_erase_eeprom_chip(chip);
+		if (retval != STATUS_SUCCESS) {
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	} else if (mode == 1) {
+		retval = spi_erase_eeprom_byte(chip, addr);
+		if (retval != STATUS_SUCCESS) {
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	} else {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr, len, i;
+	int retval;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
+
+	buf = (u8 *)vmalloc(len);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	for (i = 0; i < len; i++) {
+		retval = spi_read_eeprom(chip, addr + i, buf + i);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned short addr, len, i;
+	int retval;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
+	len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
+
+	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+	buf = (u8 *)vmalloc(len);
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	rtsx_stor_get_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	for (i = 0; i < len; i++) {
+		retval = spi_write_eeprom(chip, addr + i, buf[i]);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u8 addr, len, i;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = srb->cmnd[4];
+	len = srb->cmnd[5];
+
+	buf = (u8 *)vmalloc(len);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	for (i = 0; i < len; i++) {
+		retval = rtsx_read_efuse(chip, addr + i, buf + i);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	len = (u8)min(scsi_bufflen(srb), (unsigned int)len);
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval, result = TRANSPORT_GOOD;
+	u16 val;
+	u8 addr, len, i;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	addr = srb->cmnd[4];
+	len = srb->cmnd[5];
+
+	len = (u8)min(scsi_bufflen(srb), (unsigned int)len);
+	buf = (u8 *)vmalloc(len);
+	if (buf == NULL) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	rtsx_stor_get_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	retval = rtsx_force_power_on(chip, SSC_PDCTL);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	if (chip->asic_code) {
+		retval = rtsx_read_phy_register(chip, 0x08, &val);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		wait_timeout(600);
+
+		retval = rtsx_write_phy_register(chip, 0x08, 0x4C00 | chip->phy_voltage);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
+		if (retval != STATUS_SUCCESS) {
+			vfree(buf);
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		wait_timeout(600);
+	}
+
+	retval = card_power_on(chip, SPI_CARD);
+	if (retval != STATUS_SUCCESS) {
+		vfree(buf);
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	wait_timeout(50);
+
+	for (i = 0; i < len; i++) {
+		retval = rtsx_write_efuse(chip, addr + i, buf[i]);
+		if (retval != STATUS_SUCCESS) {
+			set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+			result = TRANSPORT_FAILED;
+			TRACE_GOTO(chip, Exit);
+		}
+	}
+
+Exit:
+	vfree(buf);
+
+	retval = card_power_off(chip, SPI_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	if (chip->asic_code) {
+		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		wait_timeout(600);
+
+		retval = rtsx_write_phy_register(chip, 0x08, val);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		retval = rtsx_write_register(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+	}
+
+	return result;
+}
+
+static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u8 func, func_max;
+	u16 addr, len;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	func = srb->cmnd[3];
+	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
+	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
+
+	RTSX_DEBUGP("%s: func = %d, addr = 0x%x, len = %d\n", __func__, func, addr, len);
+
+	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
+		func_max = 1;
+	} else {
+		func_max = 0;
+	}
+
+	if (func > func_max) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	buf = (u8 *)vmalloc(len);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		vfree(buf);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	len = (u16)min(scsi_bufflen(srb), (unsigned int)len);
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u8 func, func_max;
+	u16 addr, len;
+	u8 *buf;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	func = srb->cmnd[3];
+	addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
+	len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
+
+	RTSX_DEBUGP("%s: func = %d, addr = 0x%x\n", __func__, func, addr);
+
+	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
+		func_max = 1;
+	} else {
+		func_max = 0;
+	}
+
+	if (func > func_max) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	len = (unsigned short)min(scsi_bufflen(srb), (unsigned int)len);
+	buf = (u8 *)vmalloc(len);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	rtsx_stor_get_xfer_buf(buf, len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - len);
+
+	retval = rtsx_write_cfg_seq(chip, func, addr, buf, len);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
+		vfree(buf);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	vfree(buf);
+
+	return TRANSPORT_GOOD;
+}
+
+static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int result;
+
+	switch (srb->cmnd[2]) {
+	case PP_READ10:
+	case PP_WRITE10:
+		result = read_write(srb, chip);
+		break;
+
+	case READ_HOST_REG:
+		result = read_host_reg(srb, chip);
+		break;
+
+	case WRITE_HOST_REG:
+		result = write_host_reg(srb, chip);
+		break;
+
+	case GET_VAR:
+		result = get_variable(srb, chip);
+		break;
+
+	case SET_VAR:
+		result = set_variable(srb, chip);
+		break;
+
+	case DMA_READ:
+	case DMA_WRITE:
+		result = dma_access_ring_buffer(srb, chip);
+		break;
+
+	case READ_PHY:
+		result = read_phy_register(srb, chip);
+		break;
+
+	case WRITE_PHY:
+		result = write_phy_register(srb, chip);
+		break;
+
+	case ERASE_EEPROM2:
+		result = erase_eeprom2(srb, chip);
+		break;
+
+	case READ_EEPROM2:
+		result = read_eeprom2(srb, chip);
+		break;
+
+	case WRITE_EEPROM2:
+		result = write_eeprom2(srb, chip);
+		break;
+
+	case READ_EFUSE:
+		result = read_efuse(srb, chip);
+		break;
+
+	case WRITE_EFUSE:
+		result = write_efuse(srb, chip);
+		break;
+
+	case READ_CFG:
+		result = read_cfg_byte(srb, chip);
+		break;
+
+	case WRITE_CFG:
+		result = write_cfg_byte(srb, chip);
+		break;
+
+	case SET_CHIP_MODE:
+		result = set_chip_mode(srb, chip);
+		break;
+
+	case SUIT_CMD:
+		result = suit_cmd(srb, chip);
+		break;
+
+	case GET_DEV_STATUS:
+		result = get_dev_status(srb, chip);
+		break;
+
+	default:
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return result;
+}
+
+
+static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	u8 rtsx_status[16];
+	int buf_len;
+	unsigned int lun = SCSI_LUN(srb);
+
+	rtsx_status[0] = (u8)(chip->vendor_id >> 8);
+	rtsx_status[1] = (u8)(chip->vendor_id);
+
+	rtsx_status[2] = (u8)(chip->product_id >> 8);
+	rtsx_status[3] = (u8)(chip->product_id);
+
+	rtsx_status[4] = (u8)lun;
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		if (chip->lun2card[lun] == SD_CARD) {
+			rtsx_status[5] = 2;
+		} else {
+			rtsx_status[5] = 3;
+		}
+	} else {
+		if (chip->card_exist) {
+			if (chip->card_exist & XD_CARD) {
+				rtsx_status[5] = 4;
+			} else if (chip->card_exist & SD_CARD) {
+				rtsx_status[5] = 2;
+			} else if (chip->card_exist & MS_CARD) {
+				rtsx_status[5] = 3;
+			} else {
+				rtsx_status[5] = 7;
+			}
+		} else {
+			rtsx_status[5] = 7;
+		}
+	}
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		rtsx_status[6] = 2;
+	} else {
+		rtsx_status[6] = 1;
+	}
+
+	rtsx_status[7] = (u8)(chip->product_id);
+	rtsx_status[8] = chip->ic_version;
+
+	if (check_card_exist(chip, lun)) {
+		rtsx_status[9] = 1;
+	} else {
+		rtsx_status[9] = 0;
+	}
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		rtsx_status[10] = 0;
+	} else {
+		rtsx_status[10] = 1;
+	}
+
+	if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
+		if (chip->lun2card[lun] == SD_CARD) {
+			rtsx_status[11] = SD_CARD;
+		} else {
+			rtsx_status[11] = MS_CARD;
+		}
+	} else {
+		rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD;
+	}
+
+	if (check_card_ready(chip, lun)) {
+		rtsx_status[12] = 1;
+	} else {
+		rtsx_status[12] = 0;
+	}
+
+	if (get_lun_card(chip, lun) == XD_CARD) {
+		rtsx_status[13] = 0x40;
+	} else if (get_lun_card(chip, lun) == SD_CARD) {
+		struct sd_info *sd_card = &(chip->sd_card);
+
+		rtsx_status[13] = 0x20;
+		if (CHK_SD(sd_card)) {
+			if (CHK_SD_HCXC(sd_card))
+				rtsx_status[13] |= 0x04;
+			if (CHK_SD_HS(sd_card))
+				rtsx_status[13] |= 0x02;
+		} else {
+			rtsx_status[13] |= 0x08;
+			if (CHK_MMC_52M(sd_card))
+				rtsx_status[13] |= 0x02;
+			if (CHK_MMC_SECTOR_MODE(sd_card))
+				rtsx_status[13] |= 0x04;
+		}
+	} else if (get_lun_card(chip, lun) == MS_CARD) {
+		struct ms_info *ms_card = &(chip->ms_card);
+
+		if (CHK_MSPRO(ms_card)) {
+			rtsx_status[13] = 0x38;
+			if (CHK_HG8BIT(ms_card))
+				rtsx_status[13] |= 0x04;
+#ifdef SUPPORT_MSXC
+			if (CHK_MSXC(ms_card))
+				rtsx_status[13] |= 0x01;
+#endif
+		} else {
+			rtsx_status[13] = 0x30;
+		}
+	} else {
+		if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) {
+#ifdef SUPPORT_SDIO
+			if (chip->sd_io && chip->sd_int) {
+				rtsx_status[13] = 0x60;
+			} else {
+				rtsx_status[13] = 0x70;
+			}
+#else
+			rtsx_status[13] = 0x70;
+#endif
+		} else {
+			if (chip->lun2card[lun] == SD_CARD) {
+				rtsx_status[13] = 0x20;
+			} else {
+				rtsx_status[13] = 0x30;
+			}
+		}
+	}
+
+	rtsx_status[14] = 0x78;
+	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
+		rtsx_status[15] = 0x83;
+	} else {
+		rtsx_status[15] = 0x82;
+	}
+
+	buf_len = min(scsi_bufflen(srb), (unsigned int)sizeof(rtsx_status));
+	rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
+
+	return TRANSPORT_GOOD;
+}
+
+static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+	u8 card, bus_width;
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	card = get_lun_card(chip, lun);
+	if ((card == SD_CARD) || (card == MS_CARD)) {
+		bus_width = chip->card_bus_width[lun];
+	} else {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	scsi_set_resid(srb, 0);
+	rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb);
+
+	return TRANSPORT_GOOD;
+}
+
+static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int result;
+	unsigned int lun = SCSI_LUN(srb);
+	u8 gpio_dir;
+
+	if (CHECK_PID(chip, 0x5208) && CHECK_PID(chip, 0x5288)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	rtsx_force_power_on(chip, SSC_PDCTL);
+
+	rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir);
+	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06);
+
+	switch (srb->cmnd[2]) {
+	case SCSI_SPI_GETSTATUS:
+		result = spi_get_status(srb, chip);
+		break;
+
+	case SCSI_SPI_SETPARAMETER:
+		result = spi_set_parameter(srb, chip);
+		break;
+
+	case SCSI_SPI_READFALSHID:
+		result = spi_read_flash_id(srb, chip);
+		break;
+
+	case SCSI_SPI_READFLASH:
+		result = spi_read_flash(srb, chip);
+		break;
+
+	case SCSI_SPI_WRITEFLASH:
+		result = spi_write_flash(srb, chip);
+		break;
+
+	case SCSI_SPI_WRITEFLASHSTATUS:
+		result = spi_write_flash_status(srb, chip);
+		break;
+
+	case SCSI_SPI_ERASEFLASH:
+		result = spi_erase_flash(srb, chip);
+		break;
+
+	default:
+		rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
+
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
+
+	if (result != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return TRANSPORT_GOOD;
+}
+
+static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int result;
+
+	switch (srb->cmnd[1]) {
+	case READ_STATUS:
+		result = read_status(srb, chip);
+		break;
+
+	case READ_MEM:
+		result = read_mem(srb, chip);
+		break;
+
+	case WRITE_MEM:
+		result = write_mem(srb, chip);
+		break;
+
+	case READ_EEPROM:
+		result = read_eeprom(srb, chip);
+		break;
+
+	case WRITE_EEPROM:
+		result = write_eeprom(srb, chip);
+		break;
+
+	case TOGGLE_GPIO:
+		result = toggle_gpio_cmd(srb, chip);
+		break;
+
+	case GET_SD_CSD:
+		result = get_sd_csd(srb, chip);
+		break;
+
+	case GET_BUS_WIDTH:
+		result = get_card_bus_width(srb, chip);
+		break;
+
+#ifdef _MSG_TRACE
+	case TRACE_MSG:
+		result = trace_msg_cmd(srb, chip);
+		break;
+#endif
+
+	case SCSI_APP_CMD:
+		result = app_cmd(srb, chip);
+		break;
+
+	case SPI_VENDOR_COMMAND:
+		result = spi_vendor_cmd(srb, chip);
+		break;
+
+	default:
+		set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return result;
+}
+
+#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
+void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+	u16 sec_cnt;
+
+	if ((srb->cmnd[0] == READ_10) || (srb->cmnd[0] == WRITE_10)) {
+		sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
+	} else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
+		sec_cnt = srb->cmnd[4];
+	} else {
+		return;
+	}
+
+	if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) {
+		toggle_gpio(chip, LED_GPIO);
+		chip->rw_cap[lun] = 0;
+	} else {
+		chip->rw_cap[lun] += sec_cnt;
+	}
+}
+#endif
+
+static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval, quick_format;
+
+	if (get_lun_card(chip, lun) != MS_CARD) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if ((srb->cmnd[3] != 0x4D) || (srb->cmnd[4] != 0x47) ||
+		(srb->cmnd[5] != 0x66) || (srb->cmnd[6] != 0x6D) ||
+		(srb->cmnd[7] != 0x74)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+
+		if (!check_card_ready(chip, lun) ||
+				(get_card_size(chip, lun) == 0)) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	if (srb->cmnd[8] & 0x01) {
+		quick_format = 0;
+	} else {
+		quick_format = 1;
+	}
+
+	if (!(chip->card_ready & MS_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (chip->card_wp & MS_CARD) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (!CHK_MSPRO(ms_card)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+}
+
+#ifdef SUPPORT_PCGL_1P18
+static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned int lun = SCSI_LUN(srb);
+	u8 dev_info_id, data_len;
+	u8 *buf;
+	unsigned int buf_len;
+	int i;
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	if ((get_lun_card(chip, lun) != MS_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if ((srb->cmnd[2] != 0xB0) || (srb->cmnd[4] != 0x4D) ||
+		(srb->cmnd[5] != 0x53) || (srb->cmnd[6] != 0x49) ||
+		(srb->cmnd[7] != 0x44)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	dev_info_id = srb->cmnd[3];
+	if ((CHK_MSXC(ms_card) && (dev_info_id == 0x10)) ||
+			(!CHK_MSXC(ms_card) && (dev_info_id == 0x13)) ||
+			!CHK_MSPRO(ms_card)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (dev_info_id == 0x15) {
+		buf_len = data_len = 0x3A;
+	} else {
+		buf_len = data_len = 0x6A;
+	}
+
+	buf = (u8 *)kmalloc(buf_len, GFP_KERNEL);
+	if (!buf) {
+		TRACE_RET(chip, TRANSPORT_ERROR);
+	}
+
+	i = 0;
+	/*  GET Memory Stick Media Information Response Header */
+	buf[i++] = 0x00;		/* Data length MSB */
+	buf[i++] = data_len; 		/* Data length LSB */
+	/* Device Information Type Code */
+	if (CHK_MSXC(ms_card)) {
+		buf[i++] = 0x03;
+	} else {
+		buf[i++] = 0x02;
+	}
+	/* SGM bit */
+	buf[i++] = 0x01;
+	/* Reserved */
+	buf[i++] = 0x00;
+	buf[i++] = 0x00;
+	buf[i++] = 0x00;
+	/* Number of Device Information */
+	buf[i++] = 0x01;
+
+	/*  Device Information Body */
+
+	/* Device Information ID Number */
+	buf[i++] = dev_info_id;
+	/* Device Information Length */
+	if (dev_info_id == 0x15) {
+		data_len = 0x31;
+	} else {
+		data_len = 0x61;
+	}
+	buf[i++] = 0x00;		/* Data length MSB */
+	buf[i++] = data_len; 		/* Data length LSB */
+	/* Valid Bit */
+	buf[i++] = 0x80;
+	if ((dev_info_id == 0x10) || (dev_info_id == 0x13)) {
+		/* System Information */
+		memcpy(buf+i, ms_card->raw_sys_info, 96);
+	} else {
+		/* Model Name */
+		memcpy(buf+i, ms_card->raw_model_name, 48);
+	}
+
+	rtsx_stor_set_xfer_buf(buf, buf_len, srb);
+
+	if (dev_info_id == 0x15) {
+		scsi_set_resid(srb, scsi_bufflen(srb)-0x3C);
+	} else {
+		scsi_set_resid(srb, scsi_bufflen(srb)-0x6C);
+	}
+
+	kfree(buf);
+	return STATUS_SUCCESS;
+}
+#endif
+
+static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval = TRANSPORT_ERROR;
+
+	if (srb->cmnd[2] == MS_FORMAT) {
+		retval = ms_format_cmnd(srb, chip);
+	}
+#ifdef SUPPORT_PCGL_1P18
+	else if (srb->cmnd[2] == GET_MS_INFORMATION) {
+		retval = get_ms_information(srb, chip);
+	}
+#endif
+
+	return retval;
+}
+
+#ifdef SUPPORT_CPRM
+static int sd_extention_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	unsigned int lun = SCSI_LUN(srb);
+	int result;
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	sd_cleanup_work(chip);
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	if ((get_lun_card(chip, lun) != SD_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	switch (srb->cmnd[0]) {
+	case SD_PASS_THRU_MODE:
+		result = sd_pass_thru_mode(srb, chip);
+		break;
+
+	case SD_EXECUTE_NO_DATA:
+		result = sd_execute_no_data(srb, chip);
+		break;
+
+	case SD_EXECUTE_READ:
+		result = sd_execute_read_data(srb, chip);
+		break;
+
+	case SD_EXECUTE_WRITE:
+		result = sd_execute_write_data(srb, chip);
+		break;
+
+	case SD_GET_RSP:
+		result = sd_get_cmd_rsp(srb, chip);
+		break;
+
+	case SD_HW_RST:
+		result = sd_hw_rst(srb, chip);
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	return result;
+}
+#endif
+
+#ifdef SUPPORT_MAGIC_GATE
+static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval;
+	u8 key_format;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	ms_cleanup_work(chip);
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	if ((get_lun_card(chip, lun) != MS_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (srb->cmnd[7] != KC_MG_R_PRO) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (!CHK_MSPRO(ms_card)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	key_format = srb->cmnd[10] & 0x3F;
+	RTSX_DEBUGP("key_format = 0x%x\n", key_format);
+
+	switch (key_format) {
+	case KF_GET_LOC_EKB:
+		if ((scsi_bufflen(srb) == 0x41C) &&
+			(srb->cmnd[8] == 0x04) &&
+			(srb->cmnd[9] == 0x1C)) {
+			retval = mg_get_local_EKB(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	case KF_RSP_CHG:
+		if ((scsi_bufflen(srb) == 0x24) &&
+			(srb->cmnd[8] == 0x00) &&
+			(srb->cmnd[9] == 0x24)) {
+			retval = mg_get_rsp_chg(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	case KF_GET_ICV:
+		ms_card->mg_entry_num = srb->cmnd[5];
+		if ((scsi_bufflen(srb) == 0x404) &&
+			(srb->cmnd[8] == 0x04) &&
+			(srb->cmnd[9] == 0x04) &&
+			(srb->cmnd[2] == 0x00) &&
+			(srb->cmnd[3] == 0x00) &&
+			(srb->cmnd[4] == 0x00) &&
+			(srb->cmnd[5] < 32)) {
+			retval = mg_get_ICV(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+}
+
+static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval;
+	u8 key_format;
+
+	RTSX_DEBUGP("--%s--\n", __func__);
+
+	rtsx_disable_aspm(chip);
+
+	if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
+		rtsx_exit_ss(chip);
+		wait_timeout(100);
+	}
+	rtsx_set_stat(chip, RTSX_STAT_RUN);
+
+	ms_cleanup_work(chip);
+
+	if (!check_card_ready(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	if (check_card_wp(chip, lun)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	if ((get_lun_card(chip, lun) != MS_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (srb->cmnd[7] != KC_MG_R_PRO) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (!CHK_MSPRO(ms_card)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	key_format = srb->cmnd[10] & 0x3F;
+	RTSX_DEBUGP("key_format = 0x%x\n", key_format);
+
+	switch (key_format) {
+	case KF_SET_LEAF_ID:
+		if ((scsi_bufflen(srb) == 0x0C) &&
+			(srb->cmnd[8] == 0x00) &&
+			(srb->cmnd[9] == 0x0C)) {
+			retval = mg_set_leaf_id(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	case KF_CHG_HOST:
+		if ((scsi_bufflen(srb) == 0x0C) &&
+			(srb->cmnd[8] == 0x00) &&
+			(srb->cmnd[9] == 0x0C)) {
+			retval = mg_chg(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	case KF_RSP_HOST:
+		if ((scsi_bufflen(srb) == 0x0C) &&
+			(srb->cmnd[8] == 0x00) &&
+			(srb->cmnd[9] == 0x0C)) {
+			retval = mg_rsp(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	case KF_SET_ICV:
+		ms_card->mg_entry_num = srb->cmnd[5];
+		if ((scsi_bufflen(srb) == 0x404) &&
+			(srb->cmnd[8] == 0x04) &&
+			(srb->cmnd[9] == 0x04) &&
+			(srb->cmnd[2] == 0x00) &&
+			(srb->cmnd[3] == 0x00) &&
+			(srb->cmnd[4] == 0x00) &&
+			(srb->cmnd[5] < 32)) {
+			retval = mg_set_ICV(srb, chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+}
+#endif
+
+int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+#ifdef SUPPORT_SD_LOCK
+	struct sd_info *sd_card = &(chip->sd_card);
+#endif
+	struct ms_info *ms_card = &(chip->ms_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int result;
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_erase_status) {
+		/* Block all SCSI command except for
+		 * REQUEST_SENSE and rs_ppstatus
+		 */
+		if (!((srb->cmnd[0] == VENDOR_CMND) &&
+				(srb->cmnd[1] == SCSI_APP_CMD) &&
+				(srb->cmnd[2] == GET_DEV_STATUS)) &&
+				(srb->cmnd[0] != REQUEST_SENSE)) {
+			/* Logical Unit Not Ready Format in Progress */
+			set_sense_data(chip, lun, CUR_ERR,
+				       0x02, 0, 0x04, 0x04, 0, 0);
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+#endif
+
+	if ((get_lun_card(chip, lun) == MS_CARD) &&
+			(ms_card->format_status == FORMAT_IN_PROGRESS)) {
+		if ((srb->cmnd[0] != REQUEST_SENSE) && (srb->cmnd[0] != INQUIRY)) {
+			/* Logical Unit Not Ready Format in Progress */
+			set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
+					0, (u16)(ms_card->progress));
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+	}
+
+	switch (srb->cmnd[0]) {
+	case READ_10:
+	case WRITE_10:
+	case READ_6:
+	case WRITE_6:
+		result = read_write(srb, chip);
+#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
+		led_shine(srb, chip);
+#endif
+		break;
+
+	case TEST_UNIT_READY:
+		result = test_unit_ready(srb, chip);
+		break;
+
+	case INQUIRY:
+		result = inquiry(srb, chip);
+		break;
+
+	case READ_CAPACITY:
+		result = read_capacity(srb, chip);
+		break;
+
+	case START_STOP:
+		result = start_stop_unit(srb, chip);
+		break;
+
+	case ALLOW_MEDIUM_REMOVAL:
+		result = allow_medium_removal(srb, chip);
+		break;
+
+	case REQUEST_SENSE:
+		result = request_sense(srb, chip);
+		break;
+
+	case MODE_SENSE:
+	case MODE_SENSE_10:
+		result = mode_sense(srb, chip);
+		break;
+
+	case 0x23:
+		result = read_format_capacity(srb, chip);
+		break;
+
+	case VENDOR_CMND:
+		result = vendor_cmnd(srb, chip);
+		break;
+
+	case MS_SP_CMND:
+		result = ms_sp_cmnd(srb, chip);
+		break;
+
+#ifdef SUPPORT_CPRM
+	case SD_PASS_THRU_MODE:
+	case SD_EXECUTE_NO_DATA:
+	case SD_EXECUTE_READ:
+	case SD_EXECUTE_WRITE:
+	case SD_GET_RSP:
+	case SD_HW_RST:
+		result = sd_extention_cmnd(srb, chip);
+		break;
+#endif
+
+#ifdef SUPPORT_MAGIC_GATE
+	case CMD_MSPRO_MG_RKEY:
+		result = mg_report_key(srb, chip);
+		break;
+
+	case CMD_MSPRO_MG_SKEY:
+		result = mg_send_key(srb, chip);
+		break;
+#endif
+
+	case FORMAT_UNIT:
+	case MODE_SELECT:
+	case VERIFY:
+		result = TRANSPORT_GOOD;
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		result = TRANSPORT_FAILED;
+	}
+
+	return result;
+}
diff --git a/drivers/staging/rts_pstor/rtsx_scsi.h b/drivers/staging/rts_pstor/rtsx_scsi.h
new file mode 100644
index 0000000..fac122c
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_scsi.h
@@ -0,0 +1,142 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_SCSI_H
+#define __REALTEK_RTSX_SCSI_H
+
+#include "rtsx.h"
+#include "rtsx_chip.h"
+
+#define MS_SP_CMND		0xFA
+#define MS_FORMAT		0xA0
+#define GET_MS_INFORMATION	0xB0
+
+#define VENDOR_CMND		0xF0
+
+#define READ_STATUS		0x09
+
+#define READ_EEPROM		0x04
+#define WRITE_EEPROM		0x05
+#define READ_MEM		0x0D
+#define WRITE_MEM		0x0E
+#define GET_BUS_WIDTH		0x13
+#define GET_SD_CSD		0x14
+#define TOGGLE_GPIO		0x15
+#define TRACE_MSG		0x18
+
+#define SCSI_APP_CMD		0x10
+
+#define PP_READ10		0x1A
+#define PP_WRITE10		0x0A
+#define READ_HOST_REG		0x1D
+#define WRITE_HOST_REG		0x0D
+#define SET_VAR			0x05
+#define GET_VAR			0x15
+#define DMA_READ		0x16
+#define DMA_WRITE		0x06
+#define GET_DEV_STATUS		0x10
+#define SET_CHIP_MODE		0x27
+#define SUIT_CMD		0xE0
+#define WRITE_PHY		0x07
+#define READ_PHY		0x17
+#define WRITE_EEPROM2		0x03
+#define READ_EEPROM2		0x13
+#define ERASE_EEPROM2		0x23
+#define WRITE_EFUSE		0x04
+#define READ_EFUSE		0x14
+#define WRITE_CFG		0x0E
+#define READ_CFG		0x1E
+
+#define SPI_VENDOR_COMMAND		0x1C
+
+#define	SCSI_SPI_GETSTATUS		0x00
+#define	SCSI_SPI_SETPARAMETER		0x01
+#define	SCSI_SPI_READFALSHID		0x02
+#define	SCSI_SPI_READFLASH		0x03
+#define	SCSI_SPI_WRITEFLASH		0x04
+#define	SCSI_SPI_WRITEFLASHSTATUS	0x05
+#define	SCSI_SPI_ERASEFLASH		0x06
+
+#define INIT_BATCHCMD		0x41
+#define ADD_BATCHCMD		0x42
+#define SEND_BATCHCMD		0x43
+#define GET_BATCHRSP		0x44
+
+#define CHIP_NORMALMODE		0x00
+#define CHIP_DEBUGMODE		0x01
+
+/* SD Pass Through Command Extention */
+#define SD_PASS_THRU_MODE	0xD0
+#define SD_EXECUTE_NO_DATA	0xD1
+#define SD_EXECUTE_READ		0xD2
+#define SD_EXECUTE_WRITE	0xD3
+#define SD_GET_RSP		0xD4
+#define SD_HW_RST		0xD6
+
+#ifdef SUPPORT_MAGIC_GATE
+#define CMD_MSPRO_MG_RKEY	0xA4   /* Report Key Command */
+#define CMD_MSPRO_MG_SKEY	0xA3   /* Send Key Command */
+
+/* CBWCB field: key class */
+#define KC_MG_R_PRO		0xBE   /* MG-R PRO*/
+
+/* CBWCB field: key format */
+#define KF_SET_LEAF_ID		0x31   /* Set Leaf ID */
+#define KF_GET_LOC_EKB		0x32   /* Get Local EKB */
+#define KF_CHG_HOST		0x33   /* Challenge (host) */
+#define KF_RSP_CHG		0x34   /* Response and Challenge (device)  */
+#define KF_RSP_HOST		0x35   /* Response (host) */
+#define KF_GET_ICV		0x36   /* Get ICV */
+#define KF_SET_ICV		0x37   /* SSet ICV */
+#endif
+
+/* Sense type */
+#define	SENSE_TYPE_NO_SENSE				0
+#define	SENSE_TYPE_MEDIA_CHANGE				1
+#define	SENSE_TYPE_MEDIA_NOT_PRESENT			2
+#define	SENSE_TYPE_MEDIA_LBA_OVER_RANGE			3
+#define	SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT		4
+#define	SENSE_TYPE_MEDIA_WRITE_PROTECT			5
+#define	SENSE_TYPE_MEDIA_INVALID_CMD_FIELD		6
+#define	SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR		7
+#define	SENSE_TYPE_MEDIA_WRITE_ERR			8
+#define SENSE_TYPE_FORMAT_IN_PROGRESS			9
+#define SENSE_TYPE_FORMAT_CMD_FAILED			10
+#ifdef SUPPORT_MAGIC_GATE
+#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB		0x0b
+#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN		0x0c
+#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM		0x0d
+#define SENSE_TYPE_MG_WRITE_ERR				0x0e
+#endif
+#ifdef SUPPORT_SD_LOCK
+#define SENSE_TYPE_MEDIA_READ_FORBIDDEN			0x10  /* FOR Locked SD card*/
+#endif
+
+void scsi_show_command(struct scsi_cmnd *srb);
+void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type);
+void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code, u8 sense_key,
+		u32 info, u8 asc, u8 ascq, u8 sns_key_info0, u16 sns_key_info1);
+int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+
+#endif   /* __REALTEK_RTSX_SCSI_H */
+
diff --git a/drivers/staging/rts_pstor/rtsx_sys.h b/drivers/staging/rts_pstor/rtsx_sys.h
new file mode 100644
index 0000000..8e55a3a
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_sys.h
@@ -0,0 +1,50 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __RTSX_SYS_H
+#define __RTSX_SYS_H
+
+#include "rtsx.h"
+#include "rtsx_chip.h"
+#include "rtsx_card.h"
+
+typedef dma_addr_t ULONG_PTR;
+
+static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip)
+{
+	struct rtsx_dev *dev = chip->rtsx;
+
+	spin_lock(&(dev->reg_lock));
+	rtsx_enter_ss(chip);
+	spin_unlock(&(dev->reg_lock));
+}
+
+static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag)
+{
+	rtsx_reset_cards(chip);
+}
+
+#define RTSX_MSG_IN_INT(x)
+
+#endif  /* __RTSX_SYS_H */
+
diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c
new file mode 100644
index 0000000..4e3d2c1
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_transport.c
@@ -0,0 +1,778 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "rtsx.h"
+#include "rtsx_scsi.h"
+#include "rtsx_transport.h"
+#include "rtsx_chip.h"
+#include "rtsx_card.h"
+#include "debug.h"
+
+/***********************************************************************
+ * Scatter-gather transfer buffer access routines
+ ***********************************************************************/
+
+/* Copy a buffer of length buflen to/from the srb's transfer buffer.
+ * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
+ * points to a list of s-g entries and we ignore srb->request_bufflen.
+ * For non-scatter-gather transfers, srb->request_buffer points to the
+ * transfer buffer itself and srb->request_bufflen is the buffer's length.)
+ * Update the *index and *offset variables so that the next copy will
+ * pick up from where this one left off. */
+
+unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
+	unsigned int *offset, enum xfer_buf_dir dir)
+{
+	unsigned int cnt;
+
+	/* If not using scatter-gather, just transfer the data directly.
+	 * Make certain it will fit in the available buffer space. */
+	if (scsi_sg_count(srb) == 0) {
+		if (*offset >= scsi_bufflen(srb))
+			return 0;
+		cnt = min(buflen, scsi_bufflen(srb) - *offset);
+		if (dir == TO_XFER_BUF)
+			memcpy((unsigned char *) scsi_sglist(srb) + *offset,
+					buffer, cnt);
+		else
+			memcpy(buffer, (unsigned char *) scsi_sglist(srb) +
+					*offset, cnt);
+		*offset += cnt;
+
+	/* Using scatter-gather.  We have to go through the list one entry
+	 * at a time.  Each s-g entry contains some number of pages, and
+	 * each page has to be kmap()'ed separately.  If the page is already
+	 * in kernel-addressable memory then kmap() will return its address.
+	 * If the page is not directly accessible -- such as a user buffer
+	 * located in high memory -- then kmap() will map it to a temporary
+	 * position in the kernel's virtual address space. */
+	} else {
+		struct scatterlist *sg =
+				(struct scatterlist *) scsi_sglist(srb)
+				+ *index;
+
+		/* This loop handles a single s-g list entry, which may
+		 * include multiple pages.  Find the initial page structure
+		 * and the starting offset within the page, and update
+		 * the *offset and *index values for the next loop. */
+		cnt = 0;
+		while (cnt < buflen && *index < scsi_sg_count(srb)) {
+			struct page *page = sg_page(sg) +
+					((sg->offset + *offset) >> PAGE_SHIFT);
+			unsigned int poff =
+					(sg->offset + *offset) & (PAGE_SIZE-1);
+			unsigned int sglen = sg->length - *offset;
+
+			if (sglen > buflen - cnt) {
+
+				/* Transfer ends within this s-g entry */
+				sglen = buflen - cnt;
+				*offset += sglen;
+			} else {
+
+				/* Transfer continues to next s-g entry */
+				*offset = 0;
+				++*index;
+				++sg;
+			}
+
+			/* Transfer the data for all the pages in this
+			 * s-g entry.  For each page: call kmap(), do the
+			 * transfer, and call kunmap() immediately after. */
+			while (sglen > 0) {
+				unsigned int plen = min(sglen, (unsigned int)
+						PAGE_SIZE - poff);
+				unsigned char *ptr = kmap(page);
+
+				if (dir == TO_XFER_BUF)
+					memcpy(ptr + poff, buffer + cnt, plen);
+				else
+					memcpy(buffer + cnt, ptr + poff, plen);
+				kunmap(page);
+
+				/* Start at the beginning of the next page */
+				poff = 0;
+				++page;
+				cnt += plen;
+				sglen -= plen;
+			}
+		}
+	}
+
+	/* Return the amount actually transferred */
+	return cnt;
+}
+
+/* Store the contents of buffer into srb's transfer buffer and set the
+* SCSI residue. */
+void rtsx_stor_set_xfer_buf(unsigned char *buffer,
+       unsigned int buflen, struct scsi_cmnd *srb)
+{
+	unsigned int index = 0, offset = 0;
+
+	rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
+				  TO_XFER_BUF);
+	if (buflen < scsi_bufflen(srb))
+		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
+}
+
+void rtsx_stor_get_xfer_buf(unsigned char *buffer,
+       unsigned int buflen, struct scsi_cmnd *srb)
+{
+	unsigned int index = 0, offset = 0;
+
+	rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
+				  FROM_XFER_BUF);
+	if (buflen < scsi_bufflen(srb))
+		scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
+}
+
+
+/***********************************************************************
+ * Transport routines
+ ***********************************************************************/
+
+/* Invoke the transport and basic error-handling/recovery methods
+ *
+ * This is used to send the message to the device and receive the response.
+ */
+void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int result;
+
+	result = rtsx_scsi_handler(srb, chip);
+
+	/* if the command gets aborted by the higher layers, we need to
+	 * short-circuit all other processing
+	 */
+	if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
+		RTSX_DEBUGP("-- command was aborted\n");
+		srb->result = DID_ABORT << 16;
+		goto Handle_Errors;
+	}
+
+	/* if there is a transport error, reset and don't auto-sense */
+	if (result == TRANSPORT_ERROR) {
+		RTSX_DEBUGP("-- transport indicates error, resetting\n");
+		srb->result = DID_ERROR << 16;
+		goto Handle_Errors;
+	}
+
+	srb->result = SAM_STAT_GOOD;
+
+	/*
+	 * If we have a failure, we're going to do a REQUEST_SENSE
+	 * automatically.  Note that we differentiate between a command
+	 * "failure" and an "error" in the transport mechanism.
+	 */
+	if (result == TRANSPORT_FAILED) {
+		/* set the result so the higher layers expect this data */
+		srb->result = SAM_STAT_CHECK_CONDITION;
+		memcpy(srb->sense_buffer,
+			(unsigned char *)&(chip->sense_buffer[SCSI_LUN(srb)]),
+			sizeof(struct sense_data_t));
+	}
+
+	return;
+
+	/* Error and abort processing: try to resynchronize with the device
+	 * by issuing a port reset.  If that fails, try a class-specific
+	 * device reset. */
+Handle_Errors:
+	return;
+}
+
+void rtsx_add_cmd(struct rtsx_chip *chip,
+		u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
+{
+	u32 *cb = (u32 *)(chip->host_cmds_ptr);
+	u32 val = 0;
+
+	val |= (u32)(cmd_type & 0x03) << 30;
+	val |= (u32)(reg_addr & 0x3FFF) << 16;
+	val |= (u32)mask << 8;
+	val |= (u32)data;
+
+	spin_lock_irq(&chip->rtsx->reg_lock);
+	if (chip->ci < (HOST_CMDS_BUF_LEN / 4)) {
+		cb[(chip->ci)++] = cpu_to_le32(val);
+	}
+	spin_unlock_irq(&chip->rtsx->reg_lock);
+}
+
+void rtsx_send_cmd_no_wait(struct rtsx_chip *chip)
+{
+	u32 val = 1 << 31;
+
+	rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
+
+	val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
+	/* Hardware Auto Response */
+	val |= 0x40000000;
+	rtsx_writel(chip, RTSX_HCBCTLR, val);
+}
+
+int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout)
+{
+	struct rtsx_dev *rtsx = chip->rtsx;
+	struct completion trans_done;
+	u32 val = 1 << 31;
+	long timeleft;
+	int err = 0;
+
+	if (card == SD_CARD) {
+		rtsx->check_card_cd = SD_EXIST;
+	} else if (card == MS_CARD) {
+		rtsx->check_card_cd = MS_EXIST;
+	} else if (card == XD_CARD) {
+		rtsx->check_card_cd = XD_EXIST;
+	} else {
+		rtsx->check_card_cd = 0;
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+
+	/* set up data structures for the wakeup system */
+	rtsx->done = &trans_done;
+	rtsx->trans_result = TRANS_NOT_READY;
+	init_completion(&trans_done);
+	rtsx->trans_state = STATE_TRANS_CMD;
+
+	rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
+
+	val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
+	/* Hardware Auto Response */
+	val |= 0x40000000;
+	rtsx_writel(chip, RTSX_HCBCTLR, val);
+
+	spin_unlock_irq(&rtsx->reg_lock);
+
+	/* Wait for TRANS_OK_INT */
+	timeleft = wait_for_completion_interruptible_timeout(
+		&trans_done, timeout * HZ / 1000);
+	if (timeleft <= 0) {
+		RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
+		err = -ETIMEDOUT;
+		TRACE_GOTO(chip, finish_send_cmd);
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_RESULT_FAIL) {
+		err = -EIO;
+	} else if (rtsx->trans_result == TRANS_RESULT_OK) {
+		err = 0;
+	}
+	spin_unlock_irq(&rtsx->reg_lock);
+
+finish_send_cmd:
+	rtsx->done = NULL;
+	rtsx->trans_state = STATE_TRANS_NONE;
+
+	if (err < 0)
+		rtsx_stop_cmd(chip, card);
+
+	return err;
+}
+
+static inline void rtsx_add_sg_tbl(
+	struct rtsx_chip *chip, u32 addr, u32 len, u8 option)
+{
+	u64 *sgb = (u64 *)(chip->host_sg_tbl_ptr);
+	u64 val = 0;
+	u32 temp_len = 0;
+	u8  temp_opt = 0;
+
+	do {
+		if (len > 0x80000) {
+			temp_len = 0x80000;
+			temp_opt = option & (~SG_END);
+		} else {
+			temp_len = len;
+			temp_opt = option;
+		}
+		val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt;
+
+		if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8))
+			sgb[(chip->sgi)++] = cpu_to_le64(val);
+
+		len -= temp_len;
+		addr += temp_len;
+	} while (len);
+}
+
+static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
+		struct scatterlist *sg, int num_sg, unsigned int *index,
+		unsigned int *offset, int size,
+		enum dma_data_direction dma_dir, int timeout)
+{
+	struct rtsx_dev *rtsx = chip->rtsx;
+	struct completion trans_done;
+	u8 dir;
+	int sg_cnt, i, resid;
+	int err = 0;
+	long timeleft;
+	u32 val = TRIG_DMA;
+
+	if ((sg == NULL) || (num_sg <= 0) || !offset || !index)
+		return -EIO;
+
+	if (dma_dir == DMA_TO_DEVICE) {
+		dir = HOST_TO_DEVICE;
+	} else if (dma_dir == DMA_FROM_DEVICE) {
+		dir = DEVICE_TO_HOST;
+	} else {
+		return -ENXIO;
+	}
+
+	if (card == SD_CARD) {
+		rtsx->check_card_cd = SD_EXIST;
+	} else if (card == MS_CARD) {
+		rtsx->check_card_cd = MS_EXIST;
+	} else if (card == XD_CARD) {
+		rtsx->check_card_cd = XD_EXIST;
+	} else {
+		rtsx->check_card_cd = 0;
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+
+	/* set up data structures for the wakeup system */
+	rtsx->done = &trans_done;
+
+	rtsx->trans_state = STATE_TRANS_SG;
+	rtsx->trans_result = TRANS_NOT_READY;
+
+	spin_unlock_irq(&rtsx->reg_lock);
+
+	sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
+
+	resid = size;
+
+	chip->sgi = 0;
+	/* Usually the next entry will be @sg@ + 1, but if this sg element
+	 * is part of a chained scatterlist, it could jump to the start of
+	 * a new scatterlist array. So here we use sg_next to move to
+	 * the proper sg
+	 */
+	for (i = 0; i < *index; i++)
+		sg = sg_next(sg);
+	for (i = *index; i < sg_cnt; i++) {
+		dma_addr_t addr;
+		unsigned int len;
+		u8 option;
+
+		addr = sg_dma_address(sg);
+		len = sg_dma_len(sg);
+
+		RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
+			     (unsigned int)addr, len);
+		RTSX_DEBUGP("*index = %d, *offset = %d\n", *index, *offset);
+
+		addr += *offset;
+
+		if ((len - *offset) > resid) {
+			*offset += resid;
+			len = resid;
+			resid = 0;
+		} else {
+			resid -= (len - *offset);
+			len -= *offset;
+			*offset = 0;
+			*index = *index + 1;
+		}
+		if ((i == (sg_cnt - 1)) || !resid) {
+			option = SG_VALID | SG_END | SG_TRANS_DATA;
+		} else {
+			option = SG_VALID | SG_TRANS_DATA;
+		}
+
+		rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
+
+		if (!resid)
+			break;
+
+		sg = sg_next(sg);
+	}
+
+	RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
+
+	val |= (u32)(dir & 0x01) << 29;
+	val |= ADMA_MODE;
+
+	spin_lock_irq(&rtsx->reg_lock);
+
+	init_completion(&trans_done);
+
+	rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
+	rtsx_writel(chip, RTSX_HDBCTLR, val);
+
+	spin_unlock_irq(&rtsx->reg_lock);
+
+	timeleft = wait_for_completion_interruptible_timeout(
+		&trans_done, timeout * HZ / 1000);
+	if (timeleft <= 0) {
+		RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
+		RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
+		err = -ETIMEDOUT;
+		goto out;
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_RESULT_FAIL) {
+		err = -EIO;
+		spin_unlock_irq(&rtsx->reg_lock);
+		goto out;
+	}
+	spin_unlock_irq(&rtsx->reg_lock);
+
+	/* Wait for TRANS_OK_INT */
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_NOT_READY) {
+		init_completion(&trans_done);
+		spin_unlock_irq(&rtsx->reg_lock);
+		timeleft = wait_for_completion_interruptible_timeout(
+			&trans_done, timeout * HZ / 1000);
+		if (timeleft <= 0) {
+			RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
+			RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
+			err = -ETIMEDOUT;
+			goto out;
+		}
+	} else {
+		spin_unlock_irq(&rtsx->reg_lock);
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_RESULT_FAIL) {
+		err = -EIO;
+	} else if (rtsx->trans_result == TRANS_RESULT_OK) {
+		err = 0;
+	}
+	spin_unlock_irq(&rtsx->reg_lock);
+
+out:
+	rtsx->done = NULL;
+	rtsx->trans_state = STATE_TRANS_NONE;
+	dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
+
+	if (err < 0)
+		rtsx_stop_cmd(chip, card);
+
+	return err;
+}
+
+static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card,
+		struct scatterlist *sg, int num_sg,
+		enum dma_data_direction dma_dir, int timeout)
+{
+	struct rtsx_dev *rtsx = chip->rtsx;
+	struct completion trans_done;
+	u8 dir;
+	int buf_cnt, i;
+	int err = 0;
+	long timeleft;
+	struct scatterlist *sg_ptr;
+
+	if ((sg == NULL) || (num_sg <= 0))
+		return -EIO;
+
+	if (dma_dir == DMA_TO_DEVICE) {
+		dir = HOST_TO_DEVICE;
+	} else if (dma_dir == DMA_FROM_DEVICE) {
+		dir = DEVICE_TO_HOST;
+	} else {
+		return -ENXIO;
+	}
+
+	if (card == SD_CARD) {
+		rtsx->check_card_cd = SD_EXIST;
+	} else if (card == MS_CARD) {
+		rtsx->check_card_cd = MS_EXIST;
+	} else if (card == XD_CARD) {
+		rtsx->check_card_cd = XD_EXIST;
+	} else {
+		rtsx->check_card_cd = 0;
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+
+	/* set up data structures for the wakeup system */
+	rtsx->done = &trans_done;
+
+	rtsx->trans_state = STATE_TRANS_SG;
+	rtsx->trans_result = TRANS_NOT_READY;
+
+	spin_unlock_irq(&rtsx->reg_lock);
+
+	buf_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
+
+	sg_ptr = sg;
+
+	for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) {
+		u32 val = TRIG_DMA;
+		int sg_cnt, j;
+
+		if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8)) {
+			sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8);
+		} else {
+			sg_cnt = (HOST_SG_TBL_BUF_LEN / 8);
+		}
+
+		chip->sgi = 0;
+		for (j = 0; j < sg_cnt; j++) {
+			dma_addr_t addr = sg_dma_address(sg_ptr);
+			unsigned int len = sg_dma_len(sg_ptr);
+			u8 option;
+
+			RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
+				     (unsigned int)addr, len);
+
+			if (j == (sg_cnt - 1)) {
+				option = SG_VALID | SG_END | SG_TRANS_DATA;
+			} else {
+				option = SG_VALID | SG_TRANS_DATA;
+			}
+
+			rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
+
+			sg_ptr = sg_next(sg_ptr);
+		}
+
+		RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
+
+		val |= (u32)(dir & 0x01) << 29;
+		val |= ADMA_MODE;
+
+		spin_lock_irq(&rtsx->reg_lock);
+
+		init_completion(&trans_done);
+
+		rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
+		rtsx_writel(chip, RTSX_HDBCTLR, val);
+
+		spin_unlock_irq(&rtsx->reg_lock);
+
+		timeleft = wait_for_completion_interruptible_timeout(
+			&trans_done, timeout * HZ / 1000);
+		if (timeleft <= 0) {
+			RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
+			RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
+			err = -ETIMEDOUT;
+			goto out;
+		}
+
+		spin_lock_irq(&rtsx->reg_lock);
+		if (rtsx->trans_result == TRANS_RESULT_FAIL) {
+			err = -EIO;
+			spin_unlock_irq(&rtsx->reg_lock);
+			goto out;
+		}
+		spin_unlock_irq(&rtsx->reg_lock);
+
+		sg_ptr += sg_cnt;
+	}
+
+	/* Wait for TRANS_OK_INT */
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_NOT_READY) {
+		init_completion(&trans_done);
+		spin_unlock_irq(&rtsx->reg_lock);
+		timeleft = wait_for_completion_interruptible_timeout(
+			&trans_done, timeout * HZ / 1000);
+		if (timeleft <= 0) {
+			RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
+			RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
+			err = -ETIMEDOUT;
+			goto out;
+		}
+	} else {
+		spin_unlock_irq(&rtsx->reg_lock);
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_RESULT_FAIL) {
+		err = -EIO;
+	} else if (rtsx->trans_result == TRANS_RESULT_OK) {
+		err = 0;
+	}
+	spin_unlock_irq(&rtsx->reg_lock);
+
+out:
+	rtsx->done = NULL;
+	rtsx->trans_state = STATE_TRANS_NONE;
+	dma_unmap_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
+
+	if (err < 0)
+		rtsx_stop_cmd(chip, card);
+
+	return err;
+}
+
+static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
+		enum dma_data_direction dma_dir, int timeout)
+{
+	struct rtsx_dev *rtsx = chip->rtsx;
+	struct completion trans_done;
+	dma_addr_t addr;
+	u8 dir;
+	int err = 0;
+	u32 val = (1 << 31);
+	long timeleft;
+
+	if ((buf == NULL) || (len <= 0))
+		return -EIO;
+
+	if (dma_dir == DMA_TO_DEVICE) {
+		dir = HOST_TO_DEVICE;
+	} else if (dma_dir == DMA_FROM_DEVICE) {
+		dir = DEVICE_TO_HOST;
+	} else {
+		return -ENXIO;
+	}
+
+	addr = dma_map_single(&(rtsx->pci->dev), buf, len, dma_dir);
+	if (!addr)
+		return -ENOMEM;
+
+	if (card == SD_CARD) {
+		rtsx->check_card_cd = SD_EXIST;
+	} else if (card == MS_CARD) {
+		rtsx->check_card_cd = MS_EXIST;
+	} else if (card == XD_CARD) {
+		rtsx->check_card_cd = XD_EXIST;
+	} else {
+		rtsx->check_card_cd = 0;
+	}
+
+	val |= (u32)(dir & 0x01) << 29;
+	val |= (u32)(len & 0x00FFFFFF);
+
+	spin_lock_irq(&rtsx->reg_lock);
+
+	/* set up data structures for the wakeup system */
+	rtsx->done = &trans_done;
+
+	init_completion(&trans_done);
+
+	rtsx->trans_state = STATE_TRANS_BUF;
+	rtsx->trans_result = TRANS_NOT_READY;
+
+	rtsx_writel(chip, RTSX_HDBAR, addr);
+	rtsx_writel(chip, RTSX_HDBCTLR, val);
+
+	spin_unlock_irq(&rtsx->reg_lock);
+
+	/* Wait for TRANS_OK_INT */
+	timeleft = wait_for_completion_interruptible_timeout(
+		&trans_done, timeout * HZ / 1000);
+	if (timeleft <= 0) {
+		RTSX_DEBUGP("Timeout (%s %d)\n", __func__, __LINE__);
+		RTSX_DEBUGP("chip->int_reg = 0x%x\n", chip->int_reg);
+		err = -ETIMEDOUT;
+		goto out;
+	}
+
+	spin_lock_irq(&rtsx->reg_lock);
+	if (rtsx->trans_result == TRANS_RESULT_FAIL) {
+		err = -EIO;
+	} else if (rtsx->trans_result == TRANS_RESULT_OK) {
+		err = 0;
+	}
+	spin_unlock_irq(&rtsx->reg_lock);
+
+out:
+	rtsx->done = NULL;
+	rtsx->trans_state = STATE_TRANS_NONE;
+	dma_unmap_single(&(rtsx->pci->dev), addr, len, dma_dir);
+
+	if (err < 0)
+		rtsx_stop_cmd(chip, card);
+
+	return err;
+}
+
+int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card,
+		void *buf, size_t len, int use_sg, unsigned int *index,
+		unsigned int *offset, enum dma_data_direction dma_dir,
+		int timeout)
+{
+	int err = 0;
+
+	/* don't transfer data during abort processing */
+	if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
+		return -EIO;
+
+	if (use_sg) {
+		err = rtsx_transfer_sglist_adma_partial(chip, card,
+				(struct scatterlist *)buf, use_sg,
+				index, offset, (int)len, dma_dir, timeout);
+	} else {
+		err = rtsx_transfer_buf(chip, card,
+					buf, len, dma_dir, timeout);
+	}
+
+	if (err < 0) {
+		if (RTSX_TST_DELINK(chip)) {
+			RTSX_CLR_DELINK(chip);
+			chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
+			rtsx_reinit_cards(chip, 1);
+		}
+	}
+
+	return err;
+}
+
+int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
+		int use_sg, enum dma_data_direction dma_dir, int timeout)
+{
+	int err = 0;
+
+	RTSX_DEBUGP("use_sg = %d\n", use_sg);
+
+	/* don't transfer data during abort processing */
+	if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
+		return -EIO;
+
+	if (use_sg) {
+		err = rtsx_transfer_sglist_adma(chip, card,
+				(struct scatterlist *)buf,
+				use_sg, dma_dir, timeout);
+	} else {
+		err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout);
+	}
+
+	if (err < 0) {
+		if (RTSX_TST_DELINK(chip)) {
+			RTSX_CLR_DELINK(chip);
+			chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
+			rtsx_reinit_cards(chip, 1);
+		}
+	}
+
+	return err;
+}
+
diff --git a/drivers/staging/rts_pstor/rtsx_transport.h b/drivers/staging/rts_pstor/rtsx_transport.h
new file mode 100644
index 0000000..41f1ea0
--- /dev/null
+++ b/drivers/staging/rts_pstor/rtsx_transport.h
@@ -0,0 +1,66 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_TRANSPORT_H
+#define __REALTEK_RTSX_TRANSPORT_H
+
+#include "rtsx.h"
+#include "rtsx_chip.h"
+
+#define WAIT_TIME	2000
+
+unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index,
+	unsigned int *offset, enum xfer_buf_dir dir);
+void rtsx_stor_set_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, struct scsi_cmnd *srb);
+void rtsx_stor_get_xfer_buf(unsigned char *buffer,
+	unsigned int buflen, struct scsi_cmnd *srb);
+void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+
+
+#define rtsx_init_cmd(chip)			((chip)->ci = 0)
+
+void rtsx_add_cmd(struct rtsx_chip *chip,
+		u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
+void rtsx_send_cmd_no_wait(struct rtsx_chip *chip);
+int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout);
+
+extern inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip)
+{
+#ifdef CMD_USING_SG
+	return (u8 *)(chip->host_sg_tbl_ptr);
+#else
+	return (u8 *)(chip->host_cmds_ptr);
+#endif
+}
+
+int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
+		int use_sg, enum dma_data_direction dma_dir, int timeout);
+
+int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
+		int use_sg, unsigned int *index, unsigned int *offset,
+		enum dma_data_direction dma_dir, int timeout);
+
+#endif   /* __REALTEK_RTSX_TRANSPORT_H */
+
diff --git a/drivers/staging/rts_pstor/sd.c b/drivers/staging/rts_pstor/sd.c
new file mode 100644
index 0000000..21bfa57
--- /dev/null
+++ b/drivers/staging/rts_pstor/sd.c
@@ -0,0 +1,4776 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "sd.h"
+
+#define SD_MAX_RETRY_COUNT	3
+
+static u16 REG_SD_CFG1;
+static u16 REG_SD_CFG2;
+static u16 REG_SD_CFG3;
+static u16 REG_SD_STAT1;
+static u16 REG_SD_STAT2;
+static u16 REG_SD_BUS_STAT;
+static u16 REG_SD_PAD_CTL;
+static u16 REG_SD_SAMPLE_POINT_CTL;
+static u16 REG_SD_PUSH_POINT_CTL;
+static u16 REG_SD_CMD0;
+static u16 REG_SD_CMD1;
+static u16 REG_SD_CMD2;
+static u16 REG_SD_CMD3;
+static u16 REG_SD_CMD4;
+static u16 REG_SD_CMD5;
+static u16 REG_SD_BYTE_CNT_L;
+static u16 REG_SD_BYTE_CNT_H;
+static u16 REG_SD_BLOCK_CNT_L;
+static u16 REG_SD_BLOCK_CNT_H;
+static u16 REG_SD_TRANSFER;
+static u16 REG_SD_VPCLK0_CTL;
+static u16 REG_SD_VPCLK1_CTL;
+static u16 REG_SD_DCMPS0_CTL;
+static u16 REG_SD_DCMPS1_CTL;
+
+static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	sd_card->err_code |= err_code;
+}
+
+static inline void sd_clr_err_code(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	sd_card->err_code = 0;
+}
+
+static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	return sd_card->err_code & err_code;
+}
+
+static void sd_init_reg_addr(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		REG_SD_CFG1 = SD_CFG1;
+		REG_SD_CFG2 = SD_CFG2;
+		REG_SD_CFG3 = SD_CFG3;
+		REG_SD_STAT1 = SD_STAT1;
+		REG_SD_STAT2 = SD_STAT2;
+		REG_SD_BUS_STAT = SD_BUS_STAT;
+		REG_SD_PAD_CTL = SD_PAD_CTL;
+		REG_SD_SAMPLE_POINT_CTL = SD_SAMPLE_POINT_CTL;
+		REG_SD_PUSH_POINT_CTL = SD_PUSH_POINT_CTL;
+		REG_SD_CMD0 = SD_CMD0;
+		REG_SD_CMD1 = SD_CMD1;
+		REG_SD_CMD2 = SD_CMD2;
+		REG_SD_CMD3 = SD_CMD3;
+		REG_SD_CMD4 = SD_CMD4;
+		REG_SD_CMD5 = SD_CMD5;
+		REG_SD_BYTE_CNT_L = SD_BYTE_CNT_L;
+		REG_SD_BYTE_CNT_H = SD_BYTE_CNT_H;
+		REG_SD_BLOCK_CNT_L = SD_BLOCK_CNT_L;
+		REG_SD_BLOCK_CNT_H = SD_BLOCK_CNT_H;
+		REG_SD_TRANSFER = SD_TRANSFER;
+		REG_SD_VPCLK0_CTL = SD_VPCLK0_CTL;
+		REG_SD_VPCLK1_CTL = SD_VPCLK1_CTL;
+		REG_SD_DCMPS0_CTL = SD_DCMPS0_CTL;
+		REG_SD_DCMPS1_CTL = SD_DCMPS1_CTL;
+	} else {
+		REG_SD_CFG1 = 0xFD31;
+		REG_SD_CFG2 = 0xFD33;
+		REG_SD_CFG3 = 0xFD3E;
+		REG_SD_STAT1 = 0xFD30;
+		REG_SD_STAT2 = 0;
+		REG_SD_BUS_STAT = 0;
+		REG_SD_PAD_CTL = 0;
+		REG_SD_SAMPLE_POINT_CTL = 0;
+		REG_SD_PUSH_POINT_CTL = 0;
+		REG_SD_CMD0 = 0xFD34;
+		REG_SD_CMD1 = 0xFD35;
+		REG_SD_CMD2 = 0xFD36;
+		REG_SD_CMD3 = 0xFD37;
+		REG_SD_CMD4 = 0xFD38;
+		REG_SD_CMD5 = 0xFD5A;
+		REG_SD_BYTE_CNT_L = 0xFD39;
+		REG_SD_BYTE_CNT_H = 0xFD3A;
+		REG_SD_BLOCK_CNT_L = 0xFD3B;
+		REG_SD_BLOCK_CNT_H = 0xFD3C;
+		REG_SD_TRANSFER = 0xFD32;
+		REG_SD_VPCLK0_CTL = 0;
+		REG_SD_VPCLK1_CTL = 0;
+		REG_SD_DCMPS0_CTL = 0;
+		REG_SD_DCMPS1_CTL = 0;
+	}
+}
+
+static int sd_check_data0_status(struct rtsx_chip *chip)
+{
+	u8 stat;
+
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_READ_REG(chip, REG_SD_BUS_STAT, &stat);
+	} else {
+		RTSX_READ_REG(chip, REG_SD_STAT1, &stat);
+	}
+
+	if (!(stat & SD_DAT0_STATUS)) {
+		sd_set_err_code(chip, SD_BUSY);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
+		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int timeout = 100;
+	u16 reg_addr;
+	u8 *ptr;
+	int stat_idx = 0;
+	int rty_cnt = 0;
+
+	sd_clr_err_code(chip);
+
+	RTSX_DEBUGP("SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg);
+
+	if (rsp_type == SD_RSP_TYPE_R1b)
+		timeout = 3000;
+
+RTY_SEND_CMD:
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, PINGPONG_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
+			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
+		     SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END | SD_STAT_IDLE);
+
+	if (rsp_type == SD_RSP_TYPE_R2) {
+		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
+		}
+		stat_idx = 16;
+	} else if (rsp_type != SD_RSP_TYPE_R0) {
+		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) {
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
+		}
+		stat_idx = 5;
+	}
+
+	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
+
+	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
+	if (retval < 0) {
+		u8 val;
+
+		rtsx_read_register(chip, REG_SD_STAT1, &val);
+		RTSX_DEBUGP("SD_STAT1: 0x%x\n", val);
+
+		if (CHECK_PID(chip, 0x5209)) {
+			rtsx_read_register(chip, REG_SD_STAT2, &val);
+			RTSX_DEBUGP("SD_STAT2: 0x%x\n", val);
+
+			if (val & SD_RSP_80CLK_TIMEOUT) {
+				rtsx_clear_sd_error(chip);
+				sd_set_err_code(chip, SD_RSP_TIMEOUT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			rtsx_read_register(chip, REG_SD_BUS_STAT, &val);
+			RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", val);
+		} else {
+			rtsx_read_register(chip, REG_SD_CFG3, &val);
+			RTSX_DEBUGP("SD_CFG3: 0x%x\n", val);
+		}
+
+		if (retval == -ETIMEDOUT) {
+			if (rsp_type & SD_WAIT_BUSY_END) {
+				retval = sd_check_data0_status(chip);
+				if (retval != STATUS_SUCCESS) {
+					rtsx_clear_sd_error(chip);
+					TRACE_RET(chip, retval);
+				}
+			} else {
+				sd_set_err_code(chip, SD_TO_ERR);
+			}
+			retval = STATUS_TIMEDOUT;
+		} else {
+			retval = STATUS_FAIL;
+		}
+		rtsx_clear_sd_error(chip);
+
+		TRACE_RET(chip, retval);
+	}
+
+	if (rsp_type == SD_RSP_TYPE_R0)
+		return STATUS_SUCCESS;
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+
+	if ((ptr[0] & 0xC0) != 0) {
+		sd_set_err_code(chip, SD_STS_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
+		if (ptr[stat_idx] & SD_CRC7_ERR) {
+			if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
+				sd_set_err_code(chip, SD_CRC_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (rty_cnt < SD_MAX_RETRY_COUNT) {
+				wait_timeout(20);
+				rty_cnt++;
+				goto RTY_SEND_CMD;
+			} else {
+				sd_set_err_code(chip, SD_CRC_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+	}
+
+	if ((rsp_type == SD_RSP_TYPE_R1) || (rsp_type == SD_RSP_TYPE_R1b)) {
+		if ((cmd_idx != SEND_RELATIVE_ADDR) && (cmd_idx != SEND_IF_COND)) {
+			if (cmd_idx != STOP_TRANSMISSION) {
+				if (ptr[1] & 0x80) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+#ifdef SUPPORT_SD_LOCK
+			if (ptr[1] & 0x7D)
+#else
+			if (ptr[1] & 0x7F)
+#endif
+			{
+				RTSX_DEBUGP("ptr[1]: 0x%02x\n", ptr[1]);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (ptr[2] & 0xFF) {
+				RTSX_DEBUGP("ptr[2]: 0x%02x\n", ptr[2]);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (ptr[3] & 0x80) {
+				RTSX_DEBUGP("ptr[3]: 0x%02x\n", ptr[3]);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (ptr[3] & 0x01) {
+				sd_card->sd_data_buf_ready = 1;
+			} else {
+				sd_card->sd_data_buf_ready = 0;
+			}
+		}
+	}
+
+	if (rsp && rsp_len)
+		memcpy(rsp, ptr, rsp_len);
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_read_data(struct rtsx_chip *chip,
+			u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt,
+			u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len,
+			int timeout)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i;
+
+	sd_clr_err_code(chip);
+
+	if (!buf)
+		buf_len = 0;
+
+	if (buf_len > 512) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	rtsx_init_cmd(chip);
+
+	if (cmd_len) {
+		RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40);
+		for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i, 0xFF, cmd[i]);
+		}
+	}
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8));
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
+			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+			SD_CHECK_CRC7 | SD_RSP_LEN_6);
+	if (trans_mode != SD_TM_AUTO_TUNING) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+	}
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
+	if (retval < 0) {
+		if (retval == -ETIMEDOUT) {
+			sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
+					    SD_RSP_TYPE_R1, NULL, 0);
+		}
+
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (buf && buf_len) {
+		retval = rtsx_read_ppbuf(chip, buf, buf_len);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
+		u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt, u8 bus_width,
+		u8 *buf, int buf_len, int timeout)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i;
+
+	sd_clr_err_code(chip);
+
+	if (!buf)
+		buf_len = 0;
+
+	if (buf_len > 512) {
+		/* This function can't write data more than one page */
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (buf && buf_len) {
+		retval = rtsx_write_ppbuf(chip, buf, buf_len);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	rtsx_init_cmd(chip);
+
+	if (cmd_len) {
+		RTSX_DEBUGP("SD/MMC CMD %d\n", cmd[0] - 0x40);
+		for (i = 0; i < (cmd_len < 6 ? cmd_len : 6); i++) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD,
+				     REG_SD_CMD0 + i, 0xFF, cmd[i]);
+		}
+	}
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, (u8)byte_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, (u8)(byte_cnt >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)blk_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(blk_cnt >> 8));
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
+		SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+		SD_CHECK_CRC7 | SD_RSP_LEN_6);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
+	if (retval < 0) {
+		if (retval == -ETIMEDOUT) {
+			sd_send_cmd_get_rsp(chip, SEND_STATUS,
+				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		}
+
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i;
+	u8 csd_ver, trans_speed;
+	u8 rsp[16];
+
+	for (i = 0; i < 6; i++) {
+		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr, SD_RSP_TYPE_R2, rsp, 16);
+		if (retval == STATUS_SUCCESS)
+			break;
+	}
+
+	if (i == 6) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	memcpy(sd_card->raw_csd, rsp + 1, 15);
+
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_READ_REG(chip, REG_SD_CMD5, sd_card->raw_csd + 15);
+	}
+
+	RTSX_DEBUGP("CSD Response:\n");
+	RTSX_DUMP(sd_card->raw_csd, 16);
+
+	csd_ver = (rsp[1] & 0xc0) >> 6;
+	RTSX_DEBUGP("csd_ver = %d\n", csd_ver);
+
+	trans_speed = rsp[4];
+	if ((trans_speed & 0x07) == 0x02) {
+		if ((trans_speed & 0xf8) >= 0x30) {
+			if (chip->asic_code) {
+				sd_card->sd_clock = 47;
+			} else {
+				sd_card->sd_clock = CLK_50;
+			}
+		} else if ((trans_speed & 0xf8) == 0x28) {
+			if (chip->asic_code) {
+				sd_card->sd_clock = 39;
+			} else {
+				sd_card->sd_clock = CLK_40;
+			}
+		} else if ((trans_speed & 0xf8) == 0x20) {
+			if (chip->asic_code) {
+				sd_card->sd_clock = 29;
+			} else {
+				sd_card->sd_clock = CLK_30;
+			}
+		} else if ((trans_speed & 0xf8) >= 0x10) {
+			if (chip->asic_code) {
+				sd_card->sd_clock = 23;
+			} else {
+				sd_card->sd_clock = CLK_20;
+			}
+		} else if ((trans_speed & 0x08) >= 0x08) {
+			if (chip->asic_code) {
+				sd_card->sd_clock = 19;
+			} else {
+				sd_card->sd_clock = CLK_20;
+			}
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MMC_SECTOR_MODE(sd_card)) {
+		sd_card->capacity = 0;
+	} else {
+		if ((!CHK_SD_HCXC(sd_card)) || (csd_ver == 0)) {
+			u8 blk_size, c_size_mult;
+			u16 c_size;
+			blk_size = rsp[6] & 0x0F;
+			c_size =  ((u16)(rsp[7] & 0x03) << 10)
+					+ ((u16)rsp[8] << 2)
+					+ ((u16)(rsp[9] & 0xC0) >> 6);
+			c_size_mult = (u8)((rsp[10] & 0x03) << 1);
+			c_size_mult += (rsp[11] & 0x80) >> 7;
+			sd_card->capacity = (((u32)(c_size + 1)) * (1 << (c_size_mult + 2))) << (blk_size - 9);
+		} else {
+			u32 total_sector = 0;
+			total_sector = (((u32)rsp[8] & 0x3f) << 16) |
+				((u32)rsp[9] << 8) | (u32)rsp[10];
+			sd_card->capacity = (total_sector + 1) << 10;
+		}
+	}
+
+	if (check_wp) {
+		if (rsp[15] & 0x30) {
+			chip->card_wp |= SD_CARD;
+		}
+		RTSX_DEBUGP("CSD WP Status: 0x%x\n", rsp[15]);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_set_sample_push_timing(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	if (CHECK_PID(chip, 0x5209)) {
+		if (CHK_SD_SDR104(sd_card) || CHK_SD_SDR50(sd_card)) {
+			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST,
+					SD_30_MODE | SD_ASYNC_FIFO_NOT_RST);
+			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
+			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
+					CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
+		} else if (CHK_SD_DDR50(sd_card) || CHK_MMC_DDR52(sd_card)) {
+			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C | SD_ASYNC_FIFO_NOT_RST,
+					SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST);
+			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
+			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
+					CRC_VAR_CLK0 | SD30_FIX_CLK | SAMPLE_VAR_CLK1);
+			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
+			RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, DDR_VAR_TX_CMD_DAT,
+					DDR_VAR_TX_CMD_DAT);
+			RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, DDR_VAR_RX_DAT | DDR_VAR_RX_CMD,
+					DDR_VAR_RX_DAT | DDR_VAR_RX_CMD);
+		} else {
+			u8 val = 0;
+
+			RTSX_WRITE_REG(chip, SD_CFG1, 0x0C, SD_20_MODE);
+			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
+			RTSX_WRITE_REG(chip, CARD_CLK_SOURCE, 0xFF,
+					CRC_FIX_CLK | SD30_VAR_CLK0 | SAMPLE_VAR_CLK1);
+			RTSX_WRITE_REG(chip, CLK_CTL, CLK_LOW_FREQ, 0);
+
+			if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_AUTO) {
+				val = SD20_TX_NEG_EDGE;
+			} else if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) {
+				val = SD20_TX_14_AHEAD;
+			} else {
+				val = SD20_TX_NEG_EDGE;
+			}
+			RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, SD20_TX_SEL_MASK, val);
+
+			if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
+				if (chip->asic_code) {
+					if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
+						val = SD20_RX_14_DELAY;
+					} else {
+						val = SD20_RX_POS_EDGE;
+					}
+				} else {
+					val = SD20_RX_14_DELAY;
+				}
+			} else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) {
+				val = SD20_RX_14_DELAY;
+			} else {
+				val = SD20_RX_POS_EDGE;
+			}
+			RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, SD20_RX_SEL_MASK, val);
+		}
+	} else {
+		u8 val = 0;
+
+		if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY) {
+			val |= 0x10;
+		}
+
+		if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
+			if (chip->asic_code) {
+				if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
+					if (val & 0x10) {
+						val |= 0x04;
+					} else {
+						val |= 0x08;
+					}
+				}
+			} else {
+				if (val & 0x10) {
+					val |= 0x04;
+				} else {
+					val |= 0x08;
+				}
+			}
+		} else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_DELAY) {
+			if (val & 0x10) {
+				val |= 0x04;
+			} else {
+				val |= 0x08;
+			}
+		}
+
+		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0x1C, val);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void sd_choose_proper_clock(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	if (CHK_SD_SDR104(sd_card)) {
+		if (chip->asic_code) {
+			sd_card->sd_clock = chip->asic_sd_sdr104_clk;
+		} else {
+			sd_card->sd_clock = chip->fpga_sd_sdr104_clk;
+		}
+	} else if (CHK_SD_DDR50(sd_card)) {
+		if (chip->asic_code) {
+			sd_card->sd_clock = chip->asic_sd_ddr50_clk;
+		} else {
+			sd_card->sd_clock = chip->fpga_sd_ddr50_clk;
+		}
+	} else if (CHK_SD_SDR50(sd_card)) {
+		if (chip->asic_code) {
+			sd_card->sd_clock = chip->asic_sd_sdr50_clk;
+		} else {
+			sd_card->sd_clock = chip->fpga_sd_sdr50_clk;
+		}
+	} else if (CHK_SD_HS(sd_card)) {
+		if (chip->asic_code) {
+			sd_card->sd_clock = chip->asic_sd_hs_clk;
+		} else {
+			sd_card->sd_clock = chip->fpga_sd_hs_clk;
+		}
+	} else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
+		if (chip->asic_code) {
+			sd_card->sd_clock = chip->asic_mmc_52m_clk;
+		} else {
+			sd_card->sd_clock = chip->fpga_mmc_52m_clk;
+		}
+	} else if (CHK_MMC_26M(sd_card)) {
+		if (chip->asic_code) {
+			sd_card->sd_clock = 48;
+		} else {
+			sd_card->sd_clock = CLK_50;
+		}
+	}
+}
+
+static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
+{
+	u8 mask = 0, val = 0;
+
+	if (CHECK_PID(chip, 0x5209)) {
+		mask = SD_CLK_DIVIDE_MASK;
+		val = clk_div;
+	} else {
+		mask = 0x60;
+		if (clk_div == SD_CLK_DIVIDE_0) {
+			val = 0x00;
+		} else if (clk_div == SD_CLK_DIVIDE_128) {
+			val = 0x40;
+		} else if (clk_div == SD_CLK_DIVIDE_256) {
+			val = 0x20;
+		}
+	}
+
+	RTSX_WRITE_REG(chip, REG_SD_CFG1, mask, val);
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_set_init_para(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	retval = sd_set_sample_push_timing(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	sd_choose_proper_clock(chip);
+
+	retval = switch_clock(chip, sd_card->sd_clock);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int sd_select_card(struct rtsx_chip *chip, int select)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd_idx, cmd_type;
+	u32 addr;
+
+	if (select) {
+		cmd_idx = SELECT_CARD;
+		cmd_type = SD_RSP_TYPE_R1;
+		addr = sd_card->sd_addr;
+	} else {
+		cmd_idx = DESELECT_CARD;
+		cmd_type = SD_RSP_TYPE_R0;
+		addr = 0;
+	}
+
+	retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+#ifdef SUPPORT_SD_LOCK
+static int sd_update_lock_status(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 rsp[5];
+
+	retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (rsp[1] & 0x02) {
+		sd_card->sd_lock_status |= SD_LOCKED;
+	} else {
+		sd_card->sd_lock_status &= ~SD_LOCKED;
+	}
+
+	RTSX_DEBUGP("sd_card->sd_lock_status = 0x%x\n", sd_card->sd_lock_status);
+
+	if (rsp[1] & 0x01) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif
+
+static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state, u8 data_ready, int polling_cnt)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval, i;
+	u8 rsp[5];
+
+	for (i = 0; i < polling_cnt; i++) {
+		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
+					     sd_card->sd_addr, SD_RSP_TYPE_R1, rsp, 5);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (((rsp[3] & 0x1E) == state) && ((rsp[3] & 0x01) == data_ready)) {
+			return STATUS_SUCCESS;
+		}
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
+{
+	int retval;
+
+	if (voltage == SD_IO_3V3) {
+		if (chip->asic_code) {
+			retval = rtsx_write_phy_register(chip, 0x08, 0x4FC0 | chip->phy_voltage);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, 0);
+		}
+	} else if (voltage == SD_IO_1V8) {
+		if (chip->asic_code) {
+			retval = rtsx_write_phy_register(chip, 0x08, 0x4C40 | chip->phy_voltage);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			RTSX_WRITE_REG(chip, SD_PAD_CTL, SD_IO_USING_1V8, SD_IO_USING_1V8);
+		}
+	} else {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_voltage_switch(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 stat;
+
+	RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, SD_CLK_TOGGLE_EN);
+
+	retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	udelay(chip->sd_voltage_switch_delay);
+
+	RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
+	if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+				SD_DAT1_STATUS | SD_DAT0_STATUS)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_FORCE_STOP);
+	retval = sd_change_bank_voltage(chip, SD_IO_1V8);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	wait_timeout(50);
+
+	RTSX_WRITE_REG(chip, SD_BUS_STAT, 0xFF, SD_CLK_TOGGLE_EN);
+	wait_timeout(10);
+
+	RTSX_READ_REG(chip, SD_BUS_STAT, &stat);
+	if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+				SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
+			(SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
+				SD_DAT1_STATUS | SD_DAT0_STATUS)) {
+		RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", stat);
+		rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+		rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
+{
+	if (tune_dir == TUNE_RX) {
+		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_RX);
+		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
+	} else {
+		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_RESET | DCM_TX);
+		RTSX_WRITE_REG(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	u16 SD_VP_CTL, SD_DCMPS_CTL;
+	u8 val;
+	int retval;
+	int ddr_rx = 0;
+
+	RTSX_DEBUGP("sd_change_phase (sample_point = %d, tune_dir = %d)\n",
+				sample_point, tune_dir);
+
+	if (tune_dir == TUNE_RX) {
+		SD_VP_CTL = SD_VPRX_CTL;
+		SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
+		if (CHK_SD_DDR50(sd_card)) {
+			ddr_rx = 1;
+		}
+	} else {
+		SD_VP_CTL = SD_VPTX_CTL;
+		SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
+	}
+
+	if (chip->asic_code) {
+		RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
+		RTSX_WRITE_REG(chip, SD_VP_CTL, 0x1F, sample_point);
+		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0);
+		RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
+		RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
+	} else {
+#if CONFIG_RTS_PSTOR_DEBUG
+		rtsx_read_register(chip, SD_VP_CTL, &val);
+		RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
+		rtsx_read_register(chip, SD_DCMPS_CTL, &val);
+		RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val);
+#endif
+
+		if (ddr_rx) {
+			RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, PHASE_CHANGE);
+			udelay(50);
+			RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
+					PHASE_CHANGE | PHASE_NOT_RESET | sample_point);
+		} else {
+			RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, CHANGE_CLK);
+			udelay(50);
+			RTSX_WRITE_REG(chip, SD_VP_CTL, 0xFF,
+					PHASE_NOT_RESET | sample_point);
+		}
+		udelay(100);
+
+		rtsx_init_cmd(chip);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE, DCMPS_CHANGE);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
+		retval = rtsx_send_cmd(chip, SD_CARD, 100);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, Fail);
+		}
+
+		val = *rtsx_get_cmd_data(chip);
+		if (val & DCMPS_ERROR) {
+			TRACE_GOTO(chip, Fail);
+		}
+		if ((val & DCMPS_CURRENT_PHASE) != sample_point) {
+			TRACE_GOTO(chip, Fail);
+		}
+		RTSX_WRITE_REG(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
+		if (ddr_rx) {
+			RTSX_WRITE_REG(chip, SD_VP_CTL, PHASE_CHANGE, 0);
+		} else {
+			RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
+		}
+		udelay(50);
+	}
+
+	RTSX_WRITE_REG(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
+
+	return STATUS_SUCCESS;
+
+Fail:
+#if CONFIG_RTS_PSTOR_DEBUG
+	rtsx_read_register(chip, SD_VP_CTL, &val);
+	RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
+	rtsx_read_register(chip, SD_DCMPS_CTL, &val);
+	RTSX_DEBUGP("SD_DCMPS_CTL: 0x%x\n", val);
+#endif
+
+	rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
+	rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
+	wait_timeout(10);
+	sd_reset_dcm(chip, tune_dir);
+	return STATUS_FAIL;
+}
+
+static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd[5], buf[8];
+
+	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	cmd[0] = 0x40 | SEND_SCR;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width, buf, 8, 250);
+	if (retval != STATUS_SUCCESS) {
+		rtsx_clear_sd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	memcpy(sd_card->raw_scr, buf, 8);
+
+	if ((buf[0] & 0x0F) == 0) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group, u8 func_to_switch,
+		u8 *buf, int buf_len)
+{
+	u8 support_mask = 0, query_switch = 0, switch_busy = 0;
+	int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0;
+
+	if (func_group == SD_FUNC_GROUP_1) {
+		support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET;
+		query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET;
+		check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET;
+
+		switch (func_to_switch) {
+		case HS_SUPPORT:
+			support_mask = HS_SUPPORT_MASK;
+			query_switch = HS_QUERY_SWITCH_OK;
+			switch_busy = HS_SWITCH_BUSY;
+			break;
+
+		case SDR50_SUPPORT:
+			support_mask = SDR50_SUPPORT_MASK;
+			query_switch = SDR50_QUERY_SWITCH_OK;
+			switch_busy = SDR50_SWITCH_BUSY;
+			break;
+
+		case SDR104_SUPPORT:
+			support_mask = SDR104_SUPPORT_MASK;
+			query_switch = SDR104_QUERY_SWITCH_OK;
+			switch_busy = SDR104_SWITCH_BUSY;
+			break;
+
+		case DDR50_SUPPORT:
+			support_mask = DDR50_SUPPORT_MASK;
+			query_switch = DDR50_QUERY_SWITCH_OK;
+			switch_busy = DDR50_SWITCH_BUSY;
+			break;
+
+		default:
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else if (func_group == SD_FUNC_GROUP_3) {
+		support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
+		query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET;
+		check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET;
+
+		switch (func_to_switch) {
+		case DRIVING_TYPE_A:
+			support_mask = DRIVING_TYPE_A_MASK;
+			query_switch = TYPE_A_QUERY_SWITCH_OK;
+			switch_busy = TYPE_A_SWITCH_BUSY;
+			break;
+
+		case DRIVING_TYPE_C:
+			support_mask = DRIVING_TYPE_C_MASK;
+			query_switch = TYPE_C_QUERY_SWITCH_OK;
+			switch_busy = TYPE_C_SWITCH_BUSY;
+			break;
+
+		case DRIVING_TYPE_D:
+			support_mask = DRIVING_TYPE_D_MASK;
+			query_switch = TYPE_D_QUERY_SWITCH_OK;
+			switch_busy = TYPE_D_SWITCH_BUSY;
+			break;
+
+		default:
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else if (func_group == SD_FUNC_GROUP_4) {
+		support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
+		query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET;
+		check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET;
+
+		switch (func_to_switch) {
+		case CURRENT_LIMIT_400:
+			support_mask = CURRENT_LIMIT_400_MASK;
+			query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK;
+			switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY;
+			break;
+
+		case CURRENT_LIMIT_600:
+			support_mask = CURRENT_LIMIT_600_MASK;
+			query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK;
+			switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY;
+			break;
+
+		case CURRENT_LIMIT_800:
+			support_mask = CURRENT_LIMIT_800_MASK;
+			query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK;
+			switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY;
+			break;
+
+		default:
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (func_group == SD_FUNC_GROUP_1) {
+		if (!(buf[support_offset] & support_mask) ||
+				((buf[query_switch_offset] & 0x0F) != query_switch)) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	/* Check 'Busy Status' */
+	if ((buf[DATA_STRUCTURE_VER_OFFSET] == 0x01) &&
+		    ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode,
+		u8 func_group, u8 func_to_switch, u8 bus_width)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd[5], buf[64];
+
+	RTSX_DEBUGP("sd_check_switch_mode (mode = %d, func_group = %d, func_to_switch = %d)\n",
+			mode, func_group, func_to_switch);
+
+	cmd[0] = 0x40 | SWITCH;
+	cmd[1] = mode;
+
+	if (func_group == SD_FUNC_GROUP_1) {
+		cmd[2] = 0xFF;
+		cmd[3] = 0xFF;
+		cmd[4] = 0xF0 + func_to_switch;
+	} else if (func_group == SD_FUNC_GROUP_3) {
+		cmd[2] = 0xFF;
+		cmd[3] = 0xF0 + func_to_switch;
+		cmd[4] = 0xFF;
+	} else if (func_group == SD_FUNC_GROUP_4) {
+		cmd[2] = 0xFF;
+		cmd[3] = 0x0F + (func_to_switch << 4);
+		cmd[4] = 0xFF;
+	} else {
+		cmd[1] = SD_CHECK_MODE;
+		cmd[2] = 0xFF;
+		cmd[3] = 0xFF;
+		cmd[4] = 0xFF;
+	}
+
+	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width, buf, 64, 250);
+	if (retval != STATUS_SUCCESS) {
+		rtsx_clear_sd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DUMP(buf, 64);
+
+	if (func_group == NO_ARGUMENT) {
+		sd_card->func_group1_mask = buf[0x0D];
+		sd_card->func_group2_mask = buf[0x0B];
+		sd_card->func_group3_mask = buf[0x09];
+		sd_card->func_group4_mask = buf[0x07];
+
+		RTSX_DEBUGP("func_group1_mask = 0x%02x\n", buf[0x0D]);
+		RTSX_DEBUGP("func_group2_mask = 0x%02x\n", buf[0x0B]);
+		RTSX_DEBUGP("func_group3_mask = 0x%02x\n", buf[0x09]);
+		RTSX_DEBUGP("func_group4_mask = 0x%02x\n", buf[0x07]);
+	} else {
+		/* Maximum current consumption, check whether current is acceptable;
+		 * bit[511:496] = 0x0000 means some error happaned.
+		 */
+		u16 cc = ((u16)buf[0] << 8) | buf[1];
+		RTSX_DEBUGP("Maximum current consumption: %dmA\n", cc);
+		if ((cc == 0) || (cc > 800)) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = sd_query_switch_result(chip, func_group, func_to_switch, buf, 64);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if ((cc > 400) || (func_to_switch > CURRENT_LIMIT_400)) {
+			RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_800mA_ocp_thd);
+			RTSX_WRITE_REG(chip, CARD_PWR_CTL, PMOS_STRG_MASK, PMOS_STRG_800mA);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch)
+{
+	if (func_group == SD_FUNC_GROUP_1) {
+		if (func_to_switch > HS_SUPPORT) {
+			func_to_switch--;
+		}
+	} else if (func_group == SD_FUNC_GROUP_4) {
+		if (func_to_switch > CURRENT_LIMIT_200) {
+			func_to_switch--;
+		}
+	}
+
+	return func_to_switch;
+}
+
+static int sd_check_switch(struct rtsx_chip *chip,
+		u8 func_group, u8 func_to_switch, u8 bus_width)
+{
+	int retval;
+	int i;
+	int switch_good = 0;
+
+	for (i = 0; i < 3; i++) {
+		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
+				func_to_switch, bus_width);
+		if (retval == STATUS_SUCCESS) {
+			u8 stat;
+
+			retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
+					func_group, func_to_switch, bus_width);
+			if (retval == STATUS_SUCCESS) {
+				switch_good = 1;
+				break;
+			}
+
+			RTSX_READ_REG(chip, SD_STAT1, &stat);
+			if (stat & SD_CRC16_ERR) {
+				RTSX_DEBUGP("SD CRC16 error when switching mode\n");
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		func_to_switch = downgrade_switch_mode(func_group, func_to_switch);
+
+		wait_timeout(20);
+	}
+
+	if (!switch_good) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i;
+	u8 func_to_switch = 0;
+
+	/* Get supported functions */
+	retval = sd_check_switch_mode(chip, SD_CHECK_MODE,
+			NO_ARGUMENT, NO_ARGUMENT, bus_width);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
+
+	/* Function Group 1: Access Mode */
+	for (i = 0; i < 4; i++) {
+		switch ((u8)(chip->sd_speed_prior >> (i*8))) {
+		case SDR104_SUPPORT:
+			if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK)
+					&& chip->sdr104_en) {
+				func_to_switch = SDR104_SUPPORT;
+			}
+			break;
+
+		case DDR50_SUPPORT:
+			if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK)
+					&& chip->ddr50_en) {
+				func_to_switch = DDR50_SUPPORT;
+			}
+			break;
+
+		case SDR50_SUPPORT:
+			if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK)
+					&& chip->sdr50_en) {
+				func_to_switch = SDR50_SUPPORT;
+			}
+			break;
+
+		case HS_SUPPORT:
+			if (sd_card->func_group1_mask & HS_SUPPORT_MASK) {
+				func_to_switch = HS_SUPPORT;
+			}
+			break;
+
+		default:
+			continue;
+		}
+
+
+		if (func_to_switch) {
+			break;
+		}
+	}
+	RTSX_DEBUGP("SD_FUNC_GROUP_1: func_to_switch = 0x%02x", func_to_switch);
+
+#ifdef SUPPORT_SD_LOCK
+	if ((sd_card->sd_lock_status & SD_SDR_RST)
+			&& (DDR50_SUPPORT == func_to_switch)
+			&& (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
+		func_to_switch = SDR50_SUPPORT;
+		RTSX_DEBUGP("Using SDR50 instead of DDR50 for SD Lock\n");
+	}
+#endif
+
+	if (func_to_switch) {
+		retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch, bus_width);
+		if (retval != STATUS_SUCCESS) {
+			if (func_to_switch == SDR104_SUPPORT) {
+				sd_card->sd_switch_fail = SDR104_SUPPORT_MASK;
+			} else if (func_to_switch == DDR50_SUPPORT) {
+				sd_card->sd_switch_fail =
+					SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK;
+			} else if (func_to_switch == SDR50_SUPPORT) {
+				sd_card->sd_switch_fail =
+					SDR104_SUPPORT_MASK | DDR50_SUPPORT_MASK |
+					SDR50_SUPPORT_MASK;
+			}
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (func_to_switch == SDR104_SUPPORT) {
+			SET_SD_SDR104(sd_card);
+		} else if (func_to_switch == DDR50_SUPPORT) {
+			SET_SD_DDR50(sd_card);
+		} else if (func_to_switch == SDR50_SUPPORT) {
+			SET_SD_SDR50(sd_card);
+		} else {
+			SET_SD_HS(sd_card);
+		}
+	}
+
+	if (CHK_SD_DDR50(sd_card)) {
+		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0x04);
+		retval = sd_set_sample_push_timing(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (!func_to_switch || (func_to_switch == HS_SUPPORT)) {
+		/* Do not try to switch current limit if the card doesn't
+		 * support UHS mode or we don't want it to support UHS mode
+		 */
+		return STATUS_SUCCESS;
+	}
+
+	/* Function Group 4: Current Limit */
+	func_to_switch = 0xFF;
+
+	for (i = 0; i < 4; i++) {
+		switch ((u8)(chip->sd_current_prior >> (i*8))) {
+		case CURRENT_LIMIT_800:
+			if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK) {
+				func_to_switch = CURRENT_LIMIT_800;
+			}
+			break;
+
+		case CURRENT_LIMIT_600:
+			if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK) {
+				func_to_switch = CURRENT_LIMIT_600;
+			}
+			break;
+
+		case CURRENT_LIMIT_400:
+			if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK) {
+				func_to_switch = CURRENT_LIMIT_400;
+			}
+			break;
+
+		case CURRENT_LIMIT_200:
+			if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK) {
+				func_to_switch = CURRENT_LIMIT_200;
+			}
+			break;
+
+		default:
+			continue;
+		}
+
+		if (func_to_switch != 0xFF) {
+			break;
+		}
+	}
+
+	RTSX_DEBUGP("SD_FUNC_GROUP_4: func_to_switch = 0x%02x", func_to_switch);
+
+	if (func_to_switch <= CURRENT_LIMIT_800) {
+		retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch, bus_width);
+		if (retval != STATUS_SUCCESS) {
+			if (sd_check_err_code(chip, SD_NO_CARD)) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+		RTSX_DEBUGP("Switch current limit finished! (%d)\n", retval);
+	}
+
+	if (CHK_SD_DDR50(sd_card)) {
+		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0x06, 0);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_wait_data_idle(struct rtsx_chip *chip)
+{
+	int retval = STATUS_TIMEDOUT;
+	int i;
+	u8 val = 0;
+
+	for (i = 0; i < 100; i++) {
+		RTSX_READ_REG(chip, SD_DATA_STATE, &val);
+		if (val & SD_DATA_IDLE) {
+			retval = STATUS_SUCCESS;
+			break;
+		}
+		udelay(100);
+	}
+	RTSX_DEBUGP("SD_DATA_STATE: 0x%02x\n", val);
+
+	return retval;
+}
+
+static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
+{
+	int retval;
+	u8 cmd[5];
+
+	retval = sd_change_phase(chip, sample_point, TUNE_RX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	cmd[0] = 0x40 | SEND_TUNING_PATTERN;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	retval = sd_read_data(chip, SD_TM_AUTO_TUNING,
+			cmd, 5, 0x40, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		(void)sd_wait_data_idle(chip);
+
+		rtsx_clear_sd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd[5];
+
+	retval = sd_change_phase(chip, sample_point, TUNE_RX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("sd ddr tuning rx\n");
+
+	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	cmd[0] = 0x40 | SD_STATUS;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	retval = sd_read_data(chip, SD_TM_NORMAL_READ,
+			cmd, 5, 64, 1, SD_BUS_WIDTH_4, NULL, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		(void)sd_wait_data_idle(chip);
+
+		rtsx_clear_sd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int mmc_ddr_tunning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd[5], bus_width;
+
+	if (CHK_MMC_8BIT(sd_card)) {
+		bus_width = SD_BUS_WIDTH_8;
+	} else if (CHK_MMC_4BIT(sd_card)) {
+		bus_width = SD_BUS_WIDTH_4;
+	} else {
+		bus_width = SD_BUS_WIDTH_1;
+	}
+
+	retval = sd_change_phase(chip, sample_point, TUNE_RX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("mmc ddr tuning rx\n");
+
+	cmd[0] = 0x40 | SEND_EXT_CSD;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	retval = sd_read_data(chip, SD_TM_NORMAL_READ,
+			cmd, 5, 0x200, 1, bus_width, NULL, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		(void)sd_wait_data_idle(chip);
+
+		rtsx_clear_sd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	retval = sd_change_phase(chip, sample_point, TUNE_TX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
+
+	retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
+		SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
+			rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd[5], bus_width;
+
+	retval = sd_change_phase(chip, sample_point, TUNE_TX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_SD(sd_card)) {
+		bus_width = SD_BUS_WIDTH_4;
+	} else {
+		if (CHK_MMC_8BIT(sd_card)) {
+			bus_width = SD_BUS_WIDTH_8;
+		} else if (CHK_MMC_4BIT(sd_card)) {
+			bus_width = SD_BUS_WIDTH_4;
+		} else {
+			bus_width = SD_BUS_WIDTH_1;
+		}
+	}
+
+	retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
+
+	cmd[0] = 0x40 | PROGRAM_CSD;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2,
+			cmd, 5, 16, 1, bus_width, sd_card->raw_csd, 16, 100);
+	if (retval != STATUS_SUCCESS) {
+		rtsx_clear_sd_error(chip);
+		rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+
+	sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+
+	return STATUS_SUCCESS;
+}
+
+static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map, u8 tune_dir)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	struct timing_phase_path path[MAX_PHASE + 1];
+	int i, j, cont_path_cnt;
+	int new_block, max_len, final_path_idx;
+	u8 final_phase = 0xFF;
+
+	if (phase_map == 0xFFFFFFFF) {
+		if (tune_dir == TUNE_RX) {
+			final_phase = (u8)chip->sd_default_rx_phase;
+		} else {
+			final_phase = (u8)chip->sd_default_tx_phase;
+		}
+
+		goto Search_Finish;
+	}
+
+	cont_path_cnt = 0;
+	new_block = 1;
+	j = 0;
+	for (i = 0; i < MAX_PHASE + 1; i++) {
+		if (phase_map & (1 << i)) {
+			if (new_block) {
+				new_block = 0;
+				j = cont_path_cnt++;
+				path[j].start = i;
+				path[j].end = i;
+			} else {
+				path[j].end = i;
+			}
+		} else {
+			new_block = 1;
+			if (cont_path_cnt) {
+				int idx = cont_path_cnt - 1;
+				path[idx].len = path[idx].end - path[idx].start + 1;
+				path[idx].mid = path[idx].start + path[idx].len / 2;
+			}
+		}
+	}
+
+	if (cont_path_cnt == 0) {
+		RTSX_DEBUGP("No continuous phase path\n");
+		goto Search_Finish;
+	} else {
+		int idx = cont_path_cnt - 1;
+		path[idx].len = path[idx].end - path[idx].start + 1;
+		path[idx].mid = path[idx].start + path[idx].len / 2;
+	}
+
+	if ((path[0].start == 0) && (path[cont_path_cnt - 1].end == MAX_PHASE)) {
+		path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
+		path[0].len += path[cont_path_cnt - 1].len;
+		path[0].mid = path[0].start + path[0].len / 2;
+		if (path[0].mid < 0) {
+			path[0].mid += MAX_PHASE + 1;
+		}
+		cont_path_cnt--;
+	}
+
+	max_len = 0;
+	final_phase = 0;
+	final_path_idx = 0;
+	for (i = 0; i < cont_path_cnt; i++) {
+		if (path[i].len > max_len) {
+			max_len = path[i].len;
+			final_phase = (u8)path[i].mid;
+			final_path_idx = i;
+		}
+
+		RTSX_DEBUGP("path[%d].start = %d\n", i, path[i].start);
+		RTSX_DEBUGP("path[%d].end = %d\n", i, path[i].end);
+		RTSX_DEBUGP("path[%d].len = %d\n", i, path[i].len);
+		RTSX_DEBUGP("path[%d].mid = %d\n", i, path[i].mid);
+		RTSX_DEBUGP("\n");
+	}
+
+	if (tune_dir == TUNE_TX) {
+		if (CHK_SD_SDR104(sd_card)) {
+			if (max_len > 15) {
+				int temp_mid = (max_len - 16) / 2;
+				int temp_final_phase =
+					path[final_path_idx].end - (max_len - (6 + temp_mid));
+
+				if (temp_final_phase < 0) {
+					final_phase = (u8)(temp_final_phase + MAX_PHASE + 1);
+				} else {
+					final_phase = (u8)temp_final_phase;
+				}
+			}
+		} else if (CHK_SD_SDR50(sd_card)) {
+			if (max_len > 12) {
+				int temp_mid = (max_len - 13) / 2;
+				int temp_final_phase =
+					path[final_path_idx].end - (max_len - (3 + temp_mid));
+
+				if (temp_final_phase < 0) {
+					final_phase = (u8)(temp_final_phase + MAX_PHASE + 1);
+				} else {
+					final_phase = (u8)temp_final_phase;
+				}
+			}
+		}
+	}
+
+Search_Finish:
+	RTSX_DEBUGP("Final choosen phase: %d\n", final_phase);
+	return final_phase;
+}
+
+static int sd_tuning_rx(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i, j;
+	u32 raw_phase_map[3], phase_map;
+	u8 final_phase;
+	int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
+
+	if (CHK_SD(sd_card)) {
+		if (CHK_SD_DDR50(sd_card)) {
+			tuning_cmd = sd_ddr_tuning_rx_cmd;
+		} else {
+			tuning_cmd = sd_sdr_tuning_rx_cmd;
+		}
+	} else {
+		if (CHK_MMC_DDR52(sd_card)) {
+			tuning_cmd = mmc_ddr_tunning_rx_cmd;
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	for (i = 0; i < 3; i++) {
+		raw_phase_map[i] = 0;
+		for (j = MAX_PHASE; j >= 0; j--) {
+			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+				sd_set_err_code(chip, SD_NO_CARD);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = tuning_cmd(chip, (u8)j);
+			if (retval == STATUS_SUCCESS) {
+				raw_phase_map[i] |= 1 << j;
+			}
+		}
+	}
+
+	phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
+	for (i = 0; i < 3; i++) {
+		RTSX_DEBUGP("RX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]);
+	}
+	RTSX_DEBUGP("RX phase_map = 0x%08x\n", phase_map);
+
+	final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
+	if (final_phase == 0xFF) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_change_phase(chip, final_phase, TUNE_RX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i;
+	u32 phase_map;
+	u8 final_phase;
+
+	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, SD_RSP_80CLK_TIMEOUT_EN);
+
+	phase_map = 0;
+	for (i = MAX_PHASE; i >= 0; i--) {
+		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_NO_CARD);
+			rtsx_write_register(chip, SD_CFG3,
+						SD_RSP_80CLK_TIMEOUT_EN, 0);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = sd_change_phase(chip, (u8)i, TUNE_TX);
+		if (retval != STATUS_SUCCESS) {
+			continue;
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
+				SD_RSP_TYPE_R1, NULL, 0);
+		if ((retval == STATUS_SUCCESS) || !sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
+			phase_map |= 1 << i;
+		}
+	}
+
+	RTSX_WRITE_REG(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
+
+	RTSX_DEBUGP("DDR TX pre tune phase_map = 0x%08x\n", phase_map);
+
+	final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
+	if (final_phase == 0xFF) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_change_phase(chip, final_phase, TUNE_TX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("DDR TX pre tune phase: %d\n", (int)final_phase);
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_tuning_tx(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int i, j;
+	u32 raw_phase_map[3], phase_map;
+	u8 final_phase;
+	int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
+
+	if (CHK_SD(sd_card)) {
+		if (CHK_SD_DDR50(sd_card)) {
+			tuning_cmd = sd_ddr_tuning_tx_cmd;
+		} else {
+			tuning_cmd = sd_sdr_tuning_tx_cmd;
+		}
+	} else {
+		if (CHK_MMC_DDR52(sd_card)) {
+			tuning_cmd = sd_ddr_tuning_tx_cmd;
+		} else {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	for (i = 0; i < 3; i++) {
+		raw_phase_map[i] = 0;
+		for (j = MAX_PHASE; j >= 0; j--) {
+			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+				sd_set_err_code(chip, SD_NO_CARD);
+				rtsx_write_register(chip, SD_CFG3,
+						    SD_RSP_80CLK_TIMEOUT_EN, 0);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = tuning_cmd(chip, (u8)j);
+			if (retval == STATUS_SUCCESS) {
+				raw_phase_map[i] |= 1 << j;
+			}
+		}
+	}
+
+	phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
+	for (i = 0; i < 3; i++) {
+		RTSX_DEBUGP("TX raw_phase_map[%d] = 0x%08x\n", i, raw_phase_map[i]);
+	}
+	RTSX_DEBUGP("TX phase_map = 0x%08x\n", phase_map);
+
+	final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
+	if (final_phase == 0xFF) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_change_phase(chip, final_phase, TUNE_TX);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_sdr_tuning(struct rtsx_chip *chip)
+{
+	int retval;
+
+	retval = sd_tuning_tx(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_tuning_rx(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_ddr_tuning(struct rtsx_chip *chip)
+{
+	int retval;
+
+	if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
+		retval = sd_ddr_pre_tuning_tx(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase, TUNE_TX);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = sd_tuning_rx(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
+		retval = sd_tuning_tx(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int mmc_ddr_tuning(struct rtsx_chip *chip)
+{
+	int retval;
+
+	if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
+		retval = sd_ddr_pre_tuning_tx(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase, TUNE_TX);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = sd_tuning_rx(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
+		retval = sd_tuning_tx(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int sd_switch_clock(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	int re_tuning = 0;
+
+	retval = select_card(chip, SD_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHECK_PID(chip, 0x5209) &&
+			(CHK_SD30_SPEED(sd_card) || CHK_MMC_DDR52(sd_card))) {
+		if (sd_card->need_retune && (sd_card->sd_clock != chip->cur_clk)) {
+			re_tuning = 1;
+			sd_card->need_retune = 0;
+		}
+	}
+
+	retval = switch_clock(chip, sd_card->sd_clock);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (re_tuning) {
+		if (CHK_SD(sd_card)) {
+			if (CHK_SD_DDR50(sd_card)) {
+				retval = sd_ddr_tuning(chip);
+			} else {
+				retval = sd_sdr_tuning(chip);
+			}
+		} else {
+			if (CHK_MMC_DDR52(sd_card)) {
+				retval = mmc_ddr_tuning(chip);
+			}
+		}
+
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_prepare_reset(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	if (chip->asic_code) {
+		sd_card->sd_clock = 29;
+	} else {
+		sd_card->sd_clock = CLK_30;
+	}
+
+	sd_card->sd_type = 0;
+	sd_card->seq_mode = 0;
+	sd_card->sd_data_buf_ready = 0;
+	sd_card->capacity = 0;
+
+#ifdef SUPPORT_SD_LOCK
+	sd_card->sd_lock_status = 0;
+	sd_card->sd_erase_status = 0;
+#endif
+
+	chip->capacity[chip->card2lun[SD_CARD]] = 0;
+	chip->sd_io = 0;
+
+	retval = sd_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, retval);
+	}
+
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF,
+			SD_CLK_DIVIDE_128 | SD_20_MODE | SD_BUS_WIDTH_1);
+		RTSX_WRITE_REG(chip, SD_SAMPLE_POINT_CTL, 0xFF, SD20_RX_POS_EDGE);
+		RTSX_WRITE_REG(chip, SD_PUSH_POINT_CTL, 0xFF, 0);
+	} else {
+		RTSX_WRITE_REG(chip, REG_SD_CFG1, 0xFF, 0x40);
+	}
+
+	RTSX_WRITE_REG(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
+
+	retval = select_card(chip, SD_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_pull_ctl_disable(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0xD5);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
+			XD_D3_PD | SD_D7_PD | SD_CLK_PD | SD_D5_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
+			SD_D6_PD | SD_D0_PD | SD_D1_PD | XD_D5_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
+			SD_D4_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int sd_pull_ctl_enable(struct rtsx_chip *chip)
+{
+	int retval;
+
+	rtsx_init_cmd(chip);
+
+	if (CHECK_PID(chip, 0x5209)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xE9);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
+			XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
+			SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
+			SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xA8);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x5A);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x95);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0xAA);
+		}
+	}
+
+	retval = rtsx_send_cmd(chip, SD_CARD, 100);
+	if (retval < 0) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_init_power(struct rtsx_chip *chip)
+{
+	int retval;
+
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_OFF);
+	}
+
+	retval = sd_power_off_card3v3(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!chip->ft2_fast_mode) {
+		wait_timeout(250);
+	}
+
+	retval = enable_card_clock(chip, SD_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (chip->asic_code) {
+		retval = sd_pull_ctl_enable(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, FPGA_SD_PULL_CTL_BIT | 0x20, 0);
+	}
+
+	if (chip->ft2_fast_mode) {
+		if (CHECK_PID(chip, 0x5209)) {
+			RTSX_WRITE_REG(chip, PWR_GATE_CTRL, LDO3318_PWR_MASK, LDO_ON);
+		}
+	} else {
+		retval = card_power_on(chip, SD_CARD);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		wait_timeout(260);
+
+#ifdef SUPPORT_OCP
+		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+#endif
+	}
+
+	RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_dummy_clock(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
+		wait_timeout(5);
+		RTSX_WRITE_REG(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0x00);
+	} else {
+		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0x01);
+		wait_timeout(5);
+		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x01, 0);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_read_lba0(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 cmd[5], bus_width;
+
+	cmd[0] = 0x40 | READ_SINGLE_BLOCK;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	if (CHK_SD(sd_card)) {
+		bus_width = SD_BUS_WIDTH_4;
+	} else {
+		if (CHK_MMC_8BIT(sd_card)) {
+			bus_width = SD_BUS_WIDTH_8;
+		} else if (CHK_MMC_4BIT(sd_card)) {
+			bus_width = SD_BUS_WIDTH_4;
+		} else {
+			bus_width = SD_BUS_WIDTH_1;
+		}
+	}
+
+	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd,
+		5, 512, 1, bus_width, NULL, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sd_check_wp_state(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u32 val;
+	u16 sd_card_type;
+	u8 cmd[5], buf[64];
+
+	retval = sd_send_cmd_get_rsp(chip, APP_CMD,
+			sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	cmd[0] = 0x40 | SD_STATUS;
+	cmd[1] = 0;
+	cmd[2] = 0;
+	cmd[3] = 0;
+	cmd[4] = 0;
+
+	retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, SD_BUS_WIDTH_4, buf, 64, 250);
+	if (retval != STATUS_SUCCESS) {
+		rtsx_clear_sd_error(chip);
+
+		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("ACMD13:\n");
+	RTSX_DUMP(buf, 64);
+
+	sd_card_type = ((u16)buf[2] << 8) | buf[3];
+	RTSX_DEBUGP("sd_card_type = 0x%04x\n", sd_card_type);
+	if ((sd_card_type == 0x0001) || (sd_card_type == 0x0002)) {
+		/* ROM card or OTP */
+		chip->card_wp |= SD_CARD;
+	}
+
+	/* Check SD Machanical Write-Protect Switch */
+	val = rtsx_readl(chip, RTSX_BIPR);
+	if (val & SD_WRITE_PROTECT) {
+		chip->card_wp |= SD_CARD;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int reset_sd(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval, i = 0, j = 0, k = 0, hi_cap_flow = 0;
+	int sd_dont_switch = 0;
+	int support_1v8 = 0;
+	int try_sdio = 1;
+	u8 rsp[16];
+	u8 switch_bus_width;
+	u32 voltage = 0;
+	int sd20_mode = 0;
+
+	SET_SD(sd_card);
+
+Switch_Fail:
+
+	i = 0;
+	j = 0;
+	k = 0;
+	hi_cap_flow = 0;
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
+		goto SD_UNLOCK_ENTRY;
+#endif
+
+	retval = sd_prepare_reset(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_dummy_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
+		int rty_cnt = 0;
+
+		for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
+			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+				sd_set_err_code(chip, SD_NO_CARD);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0, SD_RSP_TYPE_R4, rsp, 5);
+			if (retval == STATUS_SUCCESS) {
+				int func_num = (rsp[1] >> 4) && 0x07;
+				if (func_num) {
+					RTSX_DEBUGP("SD_IO card (Function number: %d)!\n", func_num);
+					chip->sd_io = 1;
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+
+				break;
+			}
+
+			sd_init_power(chip);
+
+			sd_dummy_clock(chip);
+		}
+
+		RTSX_DEBUGP("Normal card!\n");
+	}
+
+	/* Start Initialization Process of SD Card */
+RTY_SD_RST:
+	retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+	       TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	wait_timeout(20);
+
+	retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA, SD_RSP_TYPE_R7, rsp, 5);
+	if (retval == STATUS_SUCCESS) {
+		if ((rsp[4] == 0xAA) && ((rsp[3] & 0x0f) == 0x01)) {
+			hi_cap_flow = 1;
+			if (CHECK_PID(chip, 0x5209)) {
+				if (sd20_mode) {
+					voltage = SUPPORT_VOLTAGE |
+						SUPPORT_HIGH_AND_EXTENDED_CAPACITY;
+				} else {
+					voltage = SUPPORT_VOLTAGE |
+						SUPPORT_HIGH_AND_EXTENDED_CAPACITY |
+						SUPPORT_MAX_POWER_PERMANCE | SUPPORT_1V8;
+				}
+			} else {
+				voltage = SUPPORT_VOLTAGE | 0x40000000;
+			}
+		}
+	}
+
+	if (!hi_cap_flow) {
+		voltage = SUPPORT_VOLTAGE;
+
+		retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+		       TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		wait_timeout(20);
+	}
+
+	do {
+		retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+				sd_set_err_code(chip, SD_NO_CARD);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			j++;
+			if (j < 3) {
+				goto RTY_SD_RST;
+			} else {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage, SD_RSP_TYPE_R3, rsp, 5);
+		if (retval != STATUS_SUCCESS) {
+			k++;
+			if (k < 3) {
+				goto RTY_SD_RST;
+			} else {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		i++;
+		wait_timeout(20);
+	} while (!(rsp[1] & 0x80) && (i < 255));
+
+	if (i == 255) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (hi_cap_flow) {
+		if (rsp[1] & 0x40) {
+			SET_SD_HCXC(sd_card);
+		} else {
+			CLR_SD_HCXC(sd_card);
+		}
+		if (CHECK_PID(chip, 0x5209) && CHK_SD_HCXC(sd_card) && !sd20_mode) {
+			support_1v8 = (rsp[1] & 0x01) ? 1 : 0;
+		} else {
+			support_1v8 = 0;
+		}
+	} else {
+		CLR_SD_HCXC(sd_card);
+		support_1v8 = 0;
+	}
+	RTSX_DEBUGP("support_1v8 = %d\n", support_1v8);
+
+	if (support_1v8) {
+		retval = sd_voltage_switch(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	for (i = 0; i < 3; i++) {
+		retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0, SD_RSP_TYPE_R6, rsp, 5);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		sd_card->sd_addr = (u32)rsp[1] << 24;
+		sd_card->sd_addr += (u32)rsp[2] << 16;
+
+		if (sd_card->sd_addr) {
+			break;
+		}
+	}
+
+	retval = sd_check_csd(chip, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_select_card(chip, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+SD_UNLOCK_ENTRY:
+	retval = sd_update_lock_status(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (sd_card->sd_lock_status & SD_LOCKED) {
+		sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
+		return STATUS_SUCCESS;
+	} else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
+		sd_card->sd_lock_status &= ~SD_PWD_EXIST;
+	}
+#endif
+
+	retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (support_1v8) {
+		retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		switch_bus_width = SD_BUS_WIDTH_4;
+	} else {
+		switch_bus_width = SD_BUS_WIDTH_1;
+	}
+
+	retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!(sd_card->raw_csd[4] & 0x40))
+		sd_dont_switch = 1;
+
+	if (!sd_dont_switch) {
+		if (sd20_mode) {
+			/* Set sd_switch_fail here, because we needn't
+			 * switch to UHS mode
+			 */
+			sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
+				DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
+		}
+
+		/* Check the card whether follow SD1.1 spec or higher */
+		retval = sd_check_spec(chip, switch_bus_width);
+		if (retval == STATUS_SUCCESS) {
+			retval = sd_switch_function(chip, switch_bus_width);
+			if (retval != STATUS_SUCCESS) {
+				if (CHECK_PID(chip, 0x5209)) {
+					sd_change_bank_voltage(chip, SD_IO_3V3);
+				}
+				sd_init_power(chip);
+				sd_dont_switch = 1;
+				try_sdio = 0;
+
+				goto Switch_Fail;
+			}
+		} else {
+			if (support_1v8) {
+				if (CHECK_PID(chip, 0x5209)) {
+					sd_change_bank_voltage(chip, SD_IO_3V3);
+				}
+				sd_init_power(chip);
+				sd_dont_switch = 1;
+				try_sdio = 0;
+
+				goto Switch_Fail;
+			}
+		}
+	}
+
+	if (!support_1v8) {
+		retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2, SD_RSP_TYPE_R1, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
+#endif
+
+	if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
+		int read_lba0 = 1;
+
+		RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_1v8);
+
+		retval = sd_set_init_para(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (CHK_SD_DDR50(sd_card)) {
+			retval = sd_ddr_tuning(chip);
+		} else {
+			retval = sd_sdr_tuning(chip);
+		}
+
+		if (retval != STATUS_SUCCESS) {
+			if (sd20_mode) {
+				TRACE_RET(chip, STATUS_FAIL);
+			} else {
+				retval = sd_init_power(chip);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				try_sdio = 0;
+				sd20_mode = 1;
+				goto Switch_Fail;
+			}
+		}
+
+		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+
+		if (CHK_SD_DDR50(sd_card)) {
+			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
+			if (retval != STATUS_SUCCESS) {
+				read_lba0 = 0;
+			}
+		}
+
+		if (read_lba0) {
+			retval = sd_read_lba0(chip);
+			if (retval != STATUS_SUCCESS) {
+				if (sd20_mode) {
+					TRACE_RET(chip, STATUS_FAIL);
+				} else {
+					retval = sd_init_power(chip);
+					if (retval != STATUS_SUCCESS) {
+						TRACE_RET(chip, STATUS_FAIL);
+					}
+					try_sdio = 0;
+					sd20_mode = 1;
+					goto Switch_Fail;
+				}
+			}
+		}
+	}
+
+	retval = sd_check_wp_state(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
+		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
+		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
+	}
+#endif
+
+	return STATUS_SUCCESS;
+}
+
+
+static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 buf[8] = {0}, bus_width, *ptr;
+	u16 byte_cnt;
+	int len;
+
+	retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (width == MMC_8BIT_BUS) {
+		buf[0] = 0x55;
+		buf[1] = 0xAA;
+		len = 8;
+		byte_cnt = 8;
+		bus_width = SD_BUS_WIDTH_8;
+	} else {
+		buf[0] = 0x5A;
+		len = 4;
+		byte_cnt = 4;
+		bus_width = SD_BUS_WIDTH_4;
+	}
+
+	if (!CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x02, 0x02);
+	}
+
+	retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3,
+			NULL, 0, byte_cnt, 1, bus_width, buf, len, 100);
+	if (retval != STATUS_SUCCESS) {
+		if (CHECK_PID(chip, 0x5209)) {
+			u8 val1 = 0, val2 = 0;
+			rtsx_read_register(chip, REG_SD_STAT1, &val1);
+			rtsx_read_register(chip, REG_SD_STAT2, &val2);
+			rtsx_clear_sd_error(chip);
+			if ((val1 & 0xE0) || val2) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			rtsx_clear_sd_error(chip);
+			rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (!CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, REG_SD_CFG3, 0x02, 0);
+	}
+
+	RTSX_DEBUGP("SD/MMC CMD %d\n", BUSTEST_R);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R);
+
+	if (width == MMC_8BIT_BUS) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x08);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x04);
+	}
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
+			SD_CALCULATE_CRC7 | SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+			SD_CHECK_CRC7 | SD_RSP_LEN_6);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0);
+	if (width == MMC_8BIT_BUS) {
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0);
+	}
+
+	retval = rtsx_send_cmd(chip, SD_CARD, 100);
+	if (retval < 0) {
+		rtsx_clear_sd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+
+	if (width == MMC_8BIT_BUS) {
+		RTSX_DEBUGP("BUSTEST_R [8bits]: 0x%02x 0x%02x\n", ptr[0], ptr[1]);
+		if ((ptr[0] == 0xAA) && (ptr[1] == 0x55)) {
+			u8 rsp[5];
+			u32 arg;
+
+			if (CHK_MMC_DDR52(sd_card)) {
+				arg = 0x03B70600;
+			} else {
+				arg = 0x03B70200;
+			}
+			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
+			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
+				return STATUS_SUCCESS;
+			}
+		}
+	} else {
+		RTSX_DEBUGP("BUSTEST_R [4bits]: 0x%02x\n", ptr[0]);
+		if (ptr[0] == 0xA5) {
+			u8 rsp[5];
+			u32 arg;
+
+			if (CHK_MMC_DDR52(sd_card)) {
+				arg = 0x03B70500;
+			} else {
+				arg = 0x03B70100;
+			}
+			retval = sd_send_cmd_get_rsp(chip, SWITCH, arg, SD_RSP_TYPE_R1b, rsp, 5);
+			if ((retval == STATUS_SUCCESS) && !(rsp[4] & MMC_SWITCH_ERR)) {
+				return STATUS_SUCCESS;
+			}
+		}
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+
+static int mmc_switch_timing_bus(struct rtsx_chip *chip, int switch_ddr)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+	u8 *ptr, card_type, card_type_mask = 0;
+
+	CLR_MMC_HS(sd_card);
+
+	RTSX_DEBUGP("SD/MMC CMD %d\n", SEND_EXT_CSD);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | SEND_EXT_CSD);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
+			SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+			SD_CHECK_CRC7 | SD_RSP_LEN_6);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_NORMAL_READ | SD_TRANSFER_START);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0);
+
+	retval = rtsx_send_cmd(chip, SD_CARD, 1000);
+	if (retval < 0) {
+		if (retval == -ETIMEDOUT) {
+			rtsx_clear_sd_error(chip);
+			sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
+					SD_RSP_TYPE_R1, NULL, 0);
+		}
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	ptr = rtsx_get_cmd_data(chip);
+	if (ptr[0] & SD_TRANSFER_ERR) {
+		sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHK_MMC_SECTOR_MODE(sd_card)) {
+		sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) |
+			((u32)ptr[3] << 8) | ((u32)ptr[2]);
+	}
+
+	if (CHECK_PID(chip, 0x5209)) {
+#ifdef SUPPORT_SD_LOCK
+		if (!(sd_card->sd_lock_status & SD_SDR_RST) &&
+				(chip->sd_ctl & SUPPORT_MMC_DDR_MODE)) {
+			card_type_mask = 0x07;
+		} else {
+			card_type_mask = 0x03;
+		}
+#else
+		if (chip->sd_ctl & SUPPORT_MMC_DDR_MODE) {
+			card_type_mask = 0x07;
+		} else {
+			card_type_mask = 0x03;
+		}
+#endif
+	} else {
+		card_type_mask = 0x03;
+	}
+	card_type = ptr[1] & card_type_mask;
+	if (card_type) {
+		u8 rsp[5];
+
+		if (card_type & 0x04) {
+			if (switch_ddr) {
+				SET_MMC_DDR52(sd_card);
+			} else {
+				SET_MMC_52M(sd_card);
+			}
+		} else if (card_type & 0x02) {
+			SET_MMC_52M(sd_card);
+		} else {
+			SET_MMC_26M(sd_card);
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, SWITCH,
+				0x03B90100, SD_RSP_TYPE_R1b, rsp, 5);
+		if ((retval != STATUS_SUCCESS) || (rsp[4] & MMC_SWITCH_ERR)) {
+			CLR_MMC_HS(sd_card);
+		}
+	}
+
+	sd_choose_proper_clock(chip);
+	retval = switch_clock(chip, sd_card->sd_clock);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (mmc_test_switch_bus(chip, MMC_8BIT_BUS) == STATUS_SUCCESS) {
+		SET_MMC_8BIT(sd_card);
+		chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
+#ifdef SUPPORT_SD_LOCK
+		sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
+#endif
+	} else if (mmc_test_switch_bus(chip, MMC_4BIT_BUS) == STATUS_SUCCESS) {
+		SET_MMC_4BIT(sd_card);
+		chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
+#ifdef SUPPORT_SD_LOCK
+		sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
+#endif
+	} else {
+		CLR_MMC_8BIT(sd_card);
+		CLR_MMC_4BIT(sd_card);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int reset_mmc(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval, i = 0, j = 0, k = 0;
+	int switch_ddr = 1;
+	u8 rsp[16];
+	u8 spec_ver = 0;
+	u32 temp;
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
+		goto MMC_UNLOCK_ENTRY;
+#endif
+
+DDR_TUNING_FAIL:
+
+	retval = sd_prepare_reset(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, retval);
+	}
+
+	SET_MMC(sd_card);
+
+RTY_MMC_RST:
+	retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+	       TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	do {
+		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
+				(SUPPORT_VOLTAGE|0x40000000), SD_RSP_TYPE_R3, rsp, 5);
+		if (retval != STATUS_SUCCESS) {
+			if (sd_check_err_code(chip, SD_BUSY) || sd_check_err_code(chip, SD_TO_ERR)) {
+				k++;
+				if (k < 20) {
+					sd_clr_err_code(chip);
+					goto RTY_MMC_RST;
+				} else {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			} else {
+				j++;
+				if (j < 100) {
+					sd_clr_err_code(chip);
+					goto RTY_MMC_RST;
+				} else {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+		}
+
+		wait_timeout(20);
+		i++;
+	} while (!(rsp[1] & 0x80) && (i < 255));
+
+	if (i == 255) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if ((rsp[1] & 0x60) == 0x40) {
+		SET_MMC_SECTOR_MODE(sd_card);
+	} else {
+		CLR_MMC_SECTOR_MODE(sd_card);
+	}
+
+	retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	sd_card->sd_addr = 0x00100000;
+	retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr, SD_RSP_TYPE_R6, rsp, 5);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_check_csd(chip, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
+
+	retval = sd_select_card(chip, 1);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1, NULL, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+MMC_UNLOCK_ENTRY:
+	retval = sd_update_lock_status(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+#endif
+
+	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
+
+	if (!sd_card->mmc_dont_switch_bus) {
+		if (spec_ver == 4) {
+			(void)mmc_switch_timing_bus(chip, switch_ddr);
+		}
+
+		if (CHK_MMC_SECTOR_MODE(sd_card) && (sd_card->capacity == 0)) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
+			retval = sd_set_init_para(chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = mmc_ddr_tuning(chip);
+			if (retval != STATUS_SUCCESS) {
+				retval = sd_init_power(chip);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				switch_ddr = 0;
+				goto DDR_TUNING_FAIL;
+			}
+
+			retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
+			if (retval == STATUS_SUCCESS) {
+				retval = sd_read_lba0(chip);
+				if (retval != STATUS_SUCCESS) {
+					retval = sd_init_power(chip);
+					if (retval != STATUS_SUCCESS) {
+						TRACE_RET(chip, STATUS_FAIL);
+					}
+					switch_ddr = 0;
+					goto DDR_TUNING_FAIL;
+				}
+			}
+		}
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
+		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_H, 0xFF, 0x02);
+		RTSX_WRITE_REG(chip, REG_SD_BLOCK_CNT_L, 0xFF, 0x00);
+	}
+#endif
+
+	temp = rtsx_readl(chip, RTSX_BIPR);
+	if (temp & SD_WRITE_PROTECT) {
+		chip->card_wp |= SD_CARD;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int reset_sd_card(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	sd_init_reg_addr(chip);
+
+	memset(sd_card, 0, sizeof(struct sd_info));
+	chip->capacity[chip->card2lun[SD_CARD]] = 0;
+
+	retval = enable_card_clock(chip, SD_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (chip->ignore_sd && CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
+		if (chip->asic_code) {
+			retval = sd_pull_ctl_enable(chip);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			retval = rtsx_write_register(chip, FPGA_PULL_CTL,
+						     FPGA_SD_PULL_CTL_BIT | 0x20, 0);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+		retval = card_share_mode(chip, SD_CARD);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		chip->sd_io = 1;
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_init_power(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (chip->sd_ctl & RESET_MMC_FIRST) {
+		retval = reset_mmc(chip);
+		if ((retval != STATUS_SUCCESS) && !sd_check_err_code(chip, SD_NO_CARD)) {
+			retval = reset_sd(chip);
+			if (retval != STATUS_SUCCESS) {
+				if (CHECK_PID(chip, 0x5209)) {
+					retval = sd_change_bank_voltage(chip, SD_IO_3V3);
+					if (retval != STATUS_SUCCESS) {
+						TRACE_RET(chip, STATUS_FAIL);
+					}
+				}
+			}
+		}
+	} else {
+		retval = reset_sd(chip);
+		if (retval != STATUS_SUCCESS) {
+			if (sd_check_err_code(chip, SD_NO_CARD)) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			if (CHECK_PID(chip, 0x5209)) {
+				retval = sd_change_bank_voltage(chip, SD_IO_3V3);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+
+			if (!chip->sd_io) {
+				retval = reset_mmc(chip);
+			}
+		}
+	}
+
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
+	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
+
+	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
+
+	retval = sd_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("sd_card->sd_type = 0x%x\n", sd_card->sd_type);
+
+	return STATUS_SUCCESS;
+}
+
+static int reset_mmc_only(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	sd_card->sd_type = 0;
+	sd_card->seq_mode = 0;
+	sd_card->sd_data_buf_ready = 0;
+	sd_card->capacity = 0;
+	sd_card->sd_switch_fail = 0;
+
+#ifdef SUPPORT_SD_LOCK
+	sd_card->sd_lock_status = 0;
+	sd_card->sd_erase_status = 0;
+#endif
+
+	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
+
+	retval = enable_card_clock(chip, SD_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_init_power(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = reset_mmc(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
+	RTSX_WRITE_REG(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
+
+	chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
+
+	retval = sd_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_DEBUGP("In reset_mmc_only, sd_card->sd_type = 0x%x\n", sd_card->sd_type);
+
+	return STATUS_SUCCESS;
+}
+
+#define WAIT_DATA_READY_RTY_CNT		255
+
+static int wait_data_buf_ready(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int i, retval;
+
+	for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
+		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		sd_card->sd_data_buf_ready = 0;
+
+		retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
+				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (sd_card->sd_data_buf_ready) {
+			return sd_send_cmd_get_rsp(chip, SEND_STATUS,
+				sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		}
+	}
+
+	sd_set_err_code(chip, SD_TO_ERR);
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+void sd_stop_seq_mode(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	if (sd_card->seq_mode) {
+		retval = sd_switch_clock(chip);
+		if (retval != STATUS_SUCCESS) {
+			return;
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
+				SD_RSP_TYPE_R1b, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_STS_ERR);
+		}
+		retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
+		if (retval != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_STS_ERR);
+		}
+		sd_card->seq_mode = 0;
+
+		rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
+	}
+}
+
+static inline int sd_auto_tune_clock(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	if (chip->asic_code) {
+		if (sd_card->sd_clock > 30) {
+			sd_card->sd_clock -= 20;
+		}
+	} else {
+		switch (sd_card->sd_clock) {
+		case CLK_200:
+			sd_card->sd_clock = CLK_150;
+			break;
+
+		case CLK_150:
+			sd_card->sd_clock = CLK_120;
+			break;
+
+		case CLK_120:
+			sd_card->sd_clock = CLK_100;
+			break;
+
+		case CLK_100:
+			sd_card->sd_clock = CLK_80;
+			break;
+
+		case CLK_80:
+			sd_card->sd_clock = CLK_60;
+			break;
+
+		case CLK_60:
+			sd_card->sd_clock = CLK_50;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	u32 data_addr;
+	u8 cfg2;
+	int retval;
+
+	if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+		RTSX_DEBUGP("sd_rw: Read %d %s from 0x%x\n", sector_cnt,
+			     (sector_cnt > 1) ? "sectors" : "sector", start_sector);
+	} else {
+		RTSX_DEBUGP("sd_rw: Write %d %s to 0x%x\n", sector_cnt,
+			     (sector_cnt > 1) ? "sectors" : "sector", start_sector);
+	}
+
+	sd_card->cleanup_counter = 0;
+
+	if (!(chip->card_ready & SD_CARD)) {
+		sd_card->seq_mode = 0;
+
+		retval = reset_sd_card(chip);
+		if (retval == STATUS_SUCCESS) {
+			chip->card_ready |= SD_CARD;
+			chip->card_fail &= ~SD_CARD;
+		} else {
+			chip->card_ready &= ~SD_CARD;
+			chip->card_fail |= SD_CARD;
+			chip->capacity[chip->card2lun[SD_CARD]] = 0;
+			chip->rw_need_retry = 1;
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card)) {
+		data_addr = start_sector << 9;
+	} else {
+		data_addr = start_sector;
+	}
+
+	sd_clr_err_code(chip);
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		sd_set_err_code(chip, SD_IO_ERR);
+		TRACE_GOTO(chip, RW_FAIL);
+	}
+
+	if (sd_card->seq_mode && ((sd_card->pre_dir != srb->sc_data_direction)
+			|| ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) != start_sector))) {
+		if ((sd_card->pre_sec_cnt < 0x80)
+				&& (sd_card->pre_dir == DMA_FROM_DEVICE)
+				&& !CHK_SD30_SPEED(sd_card)
+				&& !CHK_SD_HS(sd_card)
+				&& !CHK_MMC_HS(sd_card)) {
+			sd_send_cmd_get_rsp(chip, SEND_STATUS,
+					sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		}
+
+		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
+				0, SD_RSP_TYPE_R1b, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			chip->rw_need_retry = 1;
+			sd_set_err_code(chip, SD_STS_ERR);
+			TRACE_GOTO(chip, RW_FAIL);
+		}
+
+		sd_card->seq_mode = 0;
+
+		retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
+		if (retval != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_IO_ERR);
+			TRACE_GOTO(chip, RW_FAIL);
+		}
+
+		if ((sd_card->pre_sec_cnt < 0x80)
+				&& !CHK_SD30_SPEED(sd_card)
+				&& !CHK_SD_HS(sd_card)
+				&& !CHK_MMC_HS(sd_card)) {
+			sd_send_cmd_get_rsp(chip, SEND_STATUS,
+					sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
+		}
+	}
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, (u8)sector_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, (u8)(sector_cnt >> 8));
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+	if (CHK_MMC_8BIT(sd_card)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
+	} else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_1);
+	}
+
+	if (sd_card->seq_mode) {
+		cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+				SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
+		if (CHECK_PID(chip, 0x5209)) {
+			if (!CHK_SD30_SPEED(sd_card)) {
+				cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
+			}
+		}
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
+
+		trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
+
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
+				     SD_TM_AUTO_READ_3 | SD_TRANSFER_START);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
+				     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
+		}
+
+		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+	} else {
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			RTSX_DEBUGP("SD/MMC CMD %d\n", READ_MULTIPLE_BLOCK);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
+				     0x40 | READ_MULTIPLE_BLOCK);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(data_addr >> 24));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(data_addr >> 16));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(data_addr >> 8));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)data_addr);
+
+			cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+					SD_CHECK_CRC7 | SD_RSP_LEN_6;
+			if (CHECK_PID(chip, 0x5209)) {
+				if (!CHK_SD30_SPEED(sd_card)) {
+					cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
+				}
+			}
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
+
+			trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
+
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
+				     SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
+			rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
+				     SD_TRANSFER_END, SD_TRANSFER_END);
+
+			rtsx_send_cmd_no_wait(chip);
+		} else {
+			retval = rtsx_send_cmd(chip, SD_CARD, 50);
+			if (retval < 0) {
+				rtsx_clear_sd_error(chip);
+
+				chip->rw_need_retry = 1;
+				sd_set_err_code(chip, SD_TO_ERR);
+				TRACE_GOTO(chip, RW_FAIL);
+			}
+
+			retval = wait_data_buf_ready(chip);
+			if (retval != STATUS_SUCCESS) {
+				chip->rw_need_retry = 1;
+				sd_set_err_code(chip, SD_TO_ERR);
+				TRACE_GOTO(chip, RW_FAIL);
+			}
+
+			retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
+					data_addr, SD_RSP_TYPE_R1, NULL, 0);
+			if (retval != STATUS_SUCCESS) {
+				chip->rw_need_retry = 1;
+				TRACE_GOTO(chip, RW_FAIL);
+			}
+
+			rtsx_init_cmd(chip);
+
+			cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
+					SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
+			if (CHECK_PID(chip, 0x5209)) {
+				if (!CHK_SD30_SPEED(sd_card)) {
+					cfg2 |= SD_NO_CHECK_WAIT_CRC_TO;
+				}
+			}
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
+
+			trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512, DMA_512);
+
+			rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
+				     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
+			rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
+				     SD_TRANSFER_END, SD_TRANSFER_END);
+
+			rtsx_send_cmd_no_wait(chip);
+		}
+
+		sd_card->seq_mode = 1;
+	}
+
+	retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
+			scsi_sg_count(srb), srb->sc_data_direction, chip->sd_timeout);
+	if (retval < 0) {
+		u8 stat = 0;
+		int err;
+
+		sd_card->seq_mode = 0;
+
+		if (retval == -ETIMEDOUT) {
+			err = STATUS_TIMEDOUT;
+		} else {
+			err = STATUS_FAIL;
+		}
+
+		rtsx_read_register(chip, REG_SD_STAT1, &stat);
+		rtsx_clear_sd_error(chip);
+		if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+			chip->rw_need_retry = 0;
+			RTSX_DEBUGP("No card exist, exit sd_rw\n");
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		chip->rw_need_retry = 1;
+
+		retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0, SD_RSP_TYPE_R1b, NULL, 0);
+		if (retval != STATUS_SUCCESS) {
+			sd_set_err_code(chip, SD_STS_ERR);
+			TRACE_GOTO(chip, RW_FAIL);
+		}
+
+		if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
+			RTSX_DEBUGP("SD CRC error, tune clock!\n");
+			sd_set_err_code(chip, SD_CRC_ERR);
+			TRACE_GOTO(chip, RW_FAIL);
+		}
+
+		if (err == STATUS_TIMEDOUT) {
+			sd_set_err_code(chip, SD_TO_ERR);
+			TRACE_GOTO(chip, RW_FAIL);
+		}
+
+		TRACE_RET(chip, err);
+	}
+
+	sd_card->pre_sec_addr = start_sector;
+	sd_card->pre_sec_cnt = sector_cnt;
+	sd_card->pre_dir = srb->sc_data_direction;
+
+	return STATUS_SUCCESS;
+
+RW_FAIL:
+	sd_card->seq_mode = 0;
+
+	if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
+		chip->rw_need_retry = 0;
+		RTSX_DEBUGP("No card exist, exit sd_rw\n");
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (sd_check_err_code(chip, SD_CRC_ERR)) {
+		if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) {
+			sd_card->mmc_dont_switch_bus = 1;
+			reset_mmc_only(chip);
+			sd_card->mmc_dont_switch_bus = 0;
+		} else {
+			sd_card->need_retune = 1;
+			sd_auto_tune_clock(chip);
+		}
+	} else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) {
+		retval = reset_sd_card(chip);
+		if (retval != STATUS_SUCCESS) {
+			chip->card_ready &= ~SD_CARD;
+			chip->card_fail |= SD_CARD;
+			chip->capacity[chip->card2lun[SD_CARD]] = 0;
+		}
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+#ifdef SUPPORT_CPRM
+int soft_reset_sd_card(struct rtsx_chip *chip)
+{
+	return reset_sd(chip);
+}
+
+int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
+		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check)
+{
+	int retval;
+	int timeout = 100;
+	u16 reg_addr;
+	u8 *ptr;
+	int stat_idx = 0;
+	int rty_cnt = 0;
+
+	RTSX_DEBUGP("EXT SD/MMC CMD %d\n", cmd_idx);
+
+	if (rsp_type == SD_RSP_TYPE_R1b) {
+		timeout = 3000;
+	}
+
+RTY_SEND_CMD:
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
+			0x01, PINGPONG_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
+			0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+	if (rsp_type == SD_RSP_TYPE_R2) {
+		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
+		}
+		stat_idx = 17;
+	} else if (rsp_type != SD_RSP_TYPE_R0) {
+		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) {
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
+		}
+		stat_idx = 6;
+	}
+	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0);
+
+	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
+
+	retval = rtsx_send_cmd(chip, SD_CARD, timeout);
+	if (retval < 0) {
+		if (retval == -ETIMEDOUT) {
+			rtsx_clear_sd_error(chip);
+
+			if (rsp_type & SD_WAIT_BUSY_END) {
+				retval = sd_check_data0_status(chip);
+				if (retval != STATUS_SUCCESS) {
+					TRACE_RET(chip, retval);
+				}
+			} else {
+				sd_set_err_code(chip, SD_TO_ERR);
+			}
+		}
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (rsp_type == SD_RSP_TYPE_R0) {
+		return STATUS_SUCCESS;
+	}
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+
+	if ((ptr[0] & 0xC0) != 0) {
+		sd_set_err_code(chip, SD_STS_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (!(rsp_type & SD_NO_CHECK_CRC7)) {
+		if (ptr[stat_idx] & SD_CRC7_ERR) {
+			if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
+				sd_set_err_code(chip, SD_CRC_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			if (rty_cnt < SD_MAX_RETRY_COUNT) {
+				wait_timeout(20);
+				rty_cnt++;
+				goto RTY_SEND_CMD;
+			} else {
+				sd_set_err_code(chip, SD_CRC_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+	}
+
+	if ((cmd_idx == SELECT_CARD) || (cmd_idx == APP_CMD) ||
+			(cmd_idx == SEND_STATUS) || (cmd_idx == STOP_TRANSMISSION)) {
+		if ((cmd_idx != STOP_TRANSMISSION) && (special_check == 0)) {
+			if (ptr[1] & 0x80) {
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+#ifdef SUPPORT_SD_LOCK
+		if (ptr[1] & 0x7D)
+#else
+		if (ptr[1] & 0x7F)
+#endif
+		{
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		if (ptr[2] & 0xF8) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (cmd_idx == SELECT_CARD) {
+			if (rsp_type == SD_RSP_TYPE_R2) {
+				if ((ptr[3] & 0x1E) != 0x04) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			} else if (rsp_type == SD_RSP_TYPE_R2) {
+				if ((ptr[3] & 0x1E) != 0x03) {
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+		}
+	}
+
+	if (rsp && rsp_len) {
+		memcpy(rsp, ptr, rsp_len);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
+{
+	int retval, rsp_len;
+	u16 reg_addr;
+
+	if (rsp_type == SD_RSP_TYPE_R0) {
+		return STATUS_SUCCESS;
+	}
+
+	rtsx_init_cmd(chip);
+
+	if (rsp_type == SD_RSP_TYPE_R2) {
+		for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16; reg_addr++) {
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
+		}
+		rsp_len = 17;
+	} else if (rsp_type != SD_RSP_TYPE_R0) {
+		for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4; reg_addr++) {
+			rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
+		}
+		rsp_len = 6;
+	}
+	rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
+
+	retval = rtsx_send_cmd(chip, SD_CARD, 100);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (rsp) {
+		int min_len = (rsp_len < len) ? rsp_len : len;
+
+		memcpy(rsp, rtsx_get_cmd_data(chip), min_len);
+
+		RTSX_DEBUGP("min_len = %d\n", min_len);
+		RTSX_DEBUGP("Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
+			rsp[0], rsp[1], rsp[2], rsp[3]);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int len;
+	u8 buf[18] = {
+		0x00,
+		0x00,
+		0x00,
+		0x0E,
+		0x00,
+		0x00,
+		0x00,
+		0x00,
+		0x53,
+		0x44,
+		0x20,
+		0x43,
+		0x61,
+		0x72,
+		0x64,
+		0x00,
+		0x00,
+		0x00,
+	};
+
+	sd_card->pre_cmd_err = 0;
+
+	if (!(CHK_BIT(chip->lun_mc, lun))) {
+		SET_BIT(chip->lun_mc, lun);
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) ||
+			(0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) ||
+			(0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	switch (srb->cmnd[1] & 0x0F) {
+	case 0:
+		sd_card->sd_pass_thru_en = 0;
+		break;
+
+	case 1:
+		sd_card->sd_pass_thru_en = 1;
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	buf[5] = (1 == CHK_SD(sd_card)) ?  0x01 : 0x02;
+	if (chip->card_wp & SD_CARD) {
+		buf[5] |= 0x80;
+	}
+
+	buf[6] = (u8)(sd_card->sd_addr >> 16);
+	buf[7] = (u8)(sd_card->sd_addr >> 24);
+
+	buf[15] = chip->max_lun;
+
+	len = min(18, (int)scsi_bufflen(srb));
+	rtsx_stor_set_xfer_buf(buf, len, srb);
+
+	return TRANSPORT_GOOD;
+}
+
+static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type, int *rsp_len)
+{
+	if (!rsp_type || !rsp_len) {
+		return STATUS_FAIL;
+	}
+
+	switch (srb->cmnd[10]) {
+	case 0x03:
+		*rsp_type = SD_RSP_TYPE_R0;
+		*rsp_len = 0;
+		break;
+
+	case 0x04:
+		*rsp_type = SD_RSP_TYPE_R1;
+		*rsp_len = 6;
+		break;
+
+	case 0x05:
+		*rsp_type = SD_RSP_TYPE_R1b;
+		*rsp_len = 6;
+		break;
+
+	case 0x06:
+		*rsp_type = SD_RSP_TYPE_R2;
+		*rsp_len = 17;
+		break;
+
+	case 0x07:
+		*rsp_type = SD_RSP_TYPE_R3;
+		*rsp_len = 6;
+		break;
+
+	default:
+		return STATUS_FAIL;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval, rsp_len;
+	u8 cmd_idx, rsp_type;
+	u8 standby = 0, acmd = 0;
+	u32 arg;
+
+	if (!sd_card->sd_pass_thru_en) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (sd_card->pre_cmd_err) {
+		sd_card->pre_cmd_err = 0;
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	cmd_idx = srb->cmnd[2] & 0x3F;
+	if (srb->cmnd[1] & 0x02) {
+		standby = 1;
+	}
+	if (srb->cmnd[1] & 0x01) {
+		acmd = 1;
+	}
+
+	arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
+		((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
+
+	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	sd_card->last_rsp_type = rsp_type;
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
+		if (CHK_MMC_8BIT(sd_card)) {
+			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
+			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		}
+	}
+#else
+	retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+#endif
+
+	if (standby) {
+		retval = sd_select_card(chip, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+		}
+	}
+
+	if (acmd) {
+		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+		}
+	}
+
+	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
+			sd_card->rsp, rsp_len, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+	}
+
+	if (standby) {
+		retval = sd_select_card(chip, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+		}
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	retval = sd_update_lock_status(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, SD_Execute_Cmd_Failed);
+	}
+#endif
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+
+SD_Execute_Cmd_Failed:
+	sd_card->pre_cmd_err = 1;
+	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	release_sd_card(chip);
+	do_reset_sd_card(chip);
+	if (!(chip->card_ready & SD_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+	}
+
+	TRACE_RET(chip, TRANSPORT_FAILED);
+}
+
+int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval, rsp_len, i;
+	int cmd13_checkbit = 0, read_err = 0;
+	u8 cmd_idx, rsp_type, bus_width;
+	u8 send_cmd12 = 0, standby = 0, acmd = 0;
+	u32 data_len;
+
+	if (!sd_card->sd_pass_thru_en) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (sd_card->pre_cmd_err) {
+		sd_card->pre_cmd_err = 0;
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	cmd_idx = srb->cmnd[2] & 0x3F;
+	if (srb->cmnd[1] & 0x04) {
+		send_cmd12 = 1;
+	}
+	if (srb->cmnd[1] & 0x02) {
+		standby = 1;
+	}
+	if (srb->cmnd[1] & 0x01) {
+		acmd = 1;
+	}
+
+	data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9];
+
+	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	sd_card->last_rsp_type = rsp_type;
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
+		if (CHK_MMC_8BIT(sd_card)) {
+			bus_width = SD_BUS_WIDTH_8;
+		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
+			bus_width = SD_BUS_WIDTH_4;
+		} else {
+			bus_width = SD_BUS_WIDTH_1;
+		}
+	} else {
+		bus_width = SD_BUS_WIDTH_4;
+	}
+	RTSX_DEBUGP("bus_width = %d\n", bus_width);
+#else
+	bus_width = SD_BUS_WIDTH_4;
+#endif
+
+	if (data_len < 512) {
+		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+	}
+
+	if (standby) {
+		retval = sd_select_card(chip, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+	}
+
+	if (acmd) {
+		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+	}
+
+	if (data_len <= 512) {
+		int min_len;
+		u8 *buf;
+		u16 byte_cnt, blk_cnt;
+		u8 cmd[5];
+
+		byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9];
+		blk_cnt = 1;
+
+		cmd[0] = 0x40 | cmd_idx;
+		cmd[1] = srb->cmnd[3];
+		cmd[2] = srb->cmnd[4];
+		cmd[3] = srb->cmnd[5];
+		cmd[4] = srb->cmnd[6];
+
+		buf = (u8 *)kmalloc(data_len, GFP_KERNEL);
+		if (buf == NULL) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
+				       blk_cnt, bus_width, buf, data_len, 2000);
+		if (retval != STATUS_SUCCESS) {
+			read_err = 1;
+			kfree(buf);
+			rtsx_clear_sd_error(chip);
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+
+		min_len = min(data_len, scsi_bufflen(srb));
+		rtsx_stor_set_xfer_buf(buf, min_len, srb);
+
+		kfree(buf);
+	} else if (!(data_len & 0x1FF)) {
+		rtsx_init_cmd(chip);
+
+		trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
+				0xFF, (srb->cmnd[7] & 0xFE) >> 1);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
+				0xFF, (u8)((data_len & 0x0001FE00) >> 9));
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, srb->cmnd[3]);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, srb->cmnd[4]);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, srb->cmnd[5]);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, srb->cmnd[6]);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
+			     0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
+			scsi_sg_count(srb), DMA_FROM_DEVICE, 10000);
+		if (retval < 0) {
+			read_err = 1;
+			rtsx_clear_sd_error(chip);
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+
+	} else {
+		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+	}
+
+	retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+	}
+
+	if (standby) {
+		retval = sd_select_card(chip, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+	}
+
+	if (send_cmd12) {
+		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
+				0, SD_RSP_TYPE_R1b, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+	}
+
+	if (data_len < 512) {
+		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+
+		retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+		retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+		}
+	}
+
+	if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) {
+		cmd13_checkbit = 1;
+	}
+
+	for (i = 0; i < 3; i++) {
+		retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
+			SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit);
+		if (retval == STATUS_SUCCESS) {
+			break;
+		}
+	}
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, SD_Execute_Read_Cmd_Failed);
+	}
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+
+SD_Execute_Read_Cmd_Failed:
+	sd_card->pre_cmd_err = 1;
+	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	if (read_err) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+	}
+	release_sd_card(chip);
+	do_reset_sd_card(chip);
+	if (!(chip->card_ready & SD_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+	}
+
+	TRACE_RET(chip, TRANSPORT_FAILED);
+}
+
+int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval, rsp_len, i;
+	int cmd13_checkbit = 0, write_err = 0;
+	u8 cmd_idx, rsp_type;
+	u8 send_cmd12 = 0, standby = 0, acmd = 0;
+	u32 data_len, arg;
+#ifdef SUPPORT_SD_LOCK
+	int lock_cmd_fail = 0;
+	u8 sd_lock_state = 0;
+	u8 lock_cmd_type = 0;
+#endif
+
+	if (!sd_card->sd_pass_thru_en) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (sd_card->pre_cmd_err) {
+		sd_card->pre_cmd_err = 0;
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	cmd_idx = srb->cmnd[2] & 0x3F;
+	if (srb->cmnd[1] & 0x04) {
+		send_cmd12 = 1;
+	}
+	if (srb->cmnd[1] & 0x02) {
+		standby = 1;
+	}
+	if (srb->cmnd[1] & 0x01) {
+		acmd = 1;
+	}
+
+	data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8] << 8) | srb->cmnd[9];
+	arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
+		((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
+
+#ifdef SUPPORT_SD_LOCK
+	if (cmd_idx == LOCK_UNLOCK) {
+		sd_lock_state = sd_card->sd_lock_status;
+		sd_lock_state &= SD_LOCKED;
+	}
+#endif
+
+	retval = get_rsp_type(srb, &rsp_type, &rsp_len);
+	if (retval != STATUS_SUCCESS) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+	sd_card->last_rsp_type = rsp_type;
+
+	retval = sd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
+		if (CHK_MMC_8BIT(sd_card)) {
+			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_8);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		} else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
+			retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
+			if (retval != STATUS_SUCCESS) {
+				TRACE_RET(chip, TRANSPORT_FAILED);
+			}
+		}
+	}
+#else
+	retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+#endif
+
+	if (data_len < 512) {
+		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+	}
+
+	if (standby) {
+		retval = sd_select_card(chip, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+	}
+
+	if (acmd) {
+		retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+	}
+
+	retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
+			sd_card->rsp, rsp_len, 0);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+	}
+
+	if (data_len <= 512) {
+		u16 i;
+		u8 *buf;
+
+		buf = (u8 *)kmalloc(data_len, GFP_KERNEL);
+		if (buf == NULL) {
+			TRACE_RET(chip, TRANSPORT_ERROR);
+		}
+
+		rtsx_stor_get_xfer_buf(buf, data_len, srb);
+
+#ifdef SUPPORT_SD_LOCK
+		if (cmd_idx == LOCK_UNLOCK) {
+			lock_cmd_type = buf[0] & 0x0F;
+		}
+#endif
+
+		if (data_len > 256) {
+			rtsx_init_cmd(chip);
+			for (i = 0; i < 256; i++) {
+				rtsx_add_cmd(chip, WRITE_REG_CMD,
+						PPBUF_BASE2 + i, 0xFF, buf[i]);
+			}
+			retval = rtsx_send_cmd(chip, 0, 250);
+			if (retval != STATUS_SUCCESS) {
+				kfree(buf);
+				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+			}
+
+			rtsx_init_cmd(chip);
+			for (i = 256; i < data_len; i++) {
+				rtsx_add_cmd(chip, WRITE_REG_CMD,
+						PPBUF_BASE2 + i, 0xFF, buf[i]);
+			}
+			retval = rtsx_send_cmd(chip, 0, 250);
+			if (retval != STATUS_SUCCESS) {
+				kfree(buf);
+				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+			}
+		} else {
+			rtsx_init_cmd(chip);
+			for (i = 0; i < data_len; i++) {
+				rtsx_add_cmd(chip, WRITE_REG_CMD,
+						PPBUF_BASE2 + i, 0xFF, buf[i]);
+			}
+			retval = rtsx_send_cmd(chip, 0, 250);
+			if (retval != STATUS_SUCCESS) {
+				kfree(buf);
+				TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+			}
+		}
+
+		kfree(buf);
+
+		rtsx_init_cmd(chip);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, srb->cmnd[8] & 0x03);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, srb->cmnd[9]);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0x00);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 0x01);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
+			     SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+		retval = rtsx_send_cmd(chip, SD_CARD, 250);
+	} else if (!(data_len & 0x1FF)) {
+		rtsx_init_cmd(chip);
+
+		trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
+				0xFF, (srb->cmnd[7] & 0xFE) >> 1);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
+				0xFF, (u8)((data_len & 0x0001FE00) >> 9));
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF, SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb), scsi_bufflen(srb),
+			scsi_sg_count(srb), DMA_TO_DEVICE, 10000);
+
+	} else {
+		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+	}
+
+	if (retval < 0) {
+		write_err = 1;
+		rtsx_clear_sd_error(chip);
+		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if (cmd_idx == LOCK_UNLOCK) {
+		if (lock_cmd_type == SD_ERASE) {
+			sd_card->sd_erase_status = SD_UNDER_ERASING;
+			scsi_set_resid(srb, 0);
+			return TRANSPORT_GOOD;
+		}
+
+		rtsx_init_cmd(chip);
+		if (CHECK_PID(chip, 0x5209)) {
+			rtsx_add_cmd(chip, CHECK_REG_CMD, SD_BUS_STAT, SD_DAT0_STATUS, SD_DAT0_STATUS);
+		} else {
+			rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
+		}
+		rtsx_send_cmd(chip, SD_CARD, 250);
+
+		retval = sd_update_lock_status(chip);
+		if (retval != STATUS_SUCCESS) {
+			RTSX_DEBUGP("Lock command fail!\n");
+			lock_cmd_fail = 1;
+		}
+	}
+#endif /* SUPPORT_SD_LOCK */
+
+	if (standby) {
+		retval = sd_select_card(chip, 1);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+	}
+
+	if (send_cmd12) {
+		retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION,
+				0, SD_RSP_TYPE_R1b, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+	}
+
+	if (data_len < 512) {
+		retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
+				SD_RSP_TYPE_R1, NULL, 0, 0);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+
+		retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+		rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+		}
+	}
+
+	if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04)) {
+		cmd13_checkbit = 1;
+	}
+
+	for (i = 0; i < 3; i++) {
+		retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
+			SD_RSP_TYPE_R1, NULL, 0, cmd13_checkbit);
+		if (retval == STATUS_SUCCESS) {
+			break;
+		}
+	}
+	if (retval != STATUS_SUCCESS) {
+		TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+	}
+
+#ifdef SUPPORT_SD_LOCK
+	if (cmd_idx == LOCK_UNLOCK) {
+		if (!lock_cmd_fail) {
+			RTSX_DEBUGP("lock_cmd_type = 0x%x\n", lock_cmd_type);
+			if (lock_cmd_type & SD_CLR_PWD) {
+				sd_card->sd_lock_status &= ~SD_PWD_EXIST;
+			}
+			if (lock_cmd_type & SD_SET_PWD) {
+				sd_card->sd_lock_status |= SD_PWD_EXIST;
+			}
+		}
+
+		RTSX_DEBUGP("sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n",
+			     sd_lock_state, sd_card->sd_lock_status);
+		if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
+			sd_card->sd_lock_notify = 1;
+			if (sd_lock_state) {
+				if (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) {
+					sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST);
+					if (CHK_SD(sd_card)) {
+						retval = reset_sd(chip);
+						if (retval != STATUS_SUCCESS) {
+							sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
+							TRACE_GOTO(chip, SD_Execute_Write_Cmd_Failed);
+						}
+					}
+
+					sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
+				}
+			}
+		}
+	}
+
+	if (lock_cmd_fail) {
+		scsi_set_resid(srb, 0);
+		set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+#endif  /* SUPPORT_SD_LOCK */
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+
+SD_Execute_Write_Cmd_Failed:
+	sd_card->pre_cmd_err = 1;
+	set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
+	if (write_err) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+	}
+	release_sd_card(chip);
+	do_reset_sd_card(chip);
+	if (!(chip->card_ready & SD_CARD)) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+	}
+
+	TRACE_RET(chip, TRANSPORT_FAILED);
+}
+
+int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int count;
+	u16 data_len;
+
+	if (!sd_card->sd_pass_thru_en) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (sd_card->pre_cmd_err) {
+		sd_card->pre_cmd_err = 0;
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
+
+	if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	} else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
+		count = (data_len < 17) ? data_len : 17;
+	} else {
+		count = (data_len < 6) ? data_len : 6;
+	}
+	rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb);
+
+	RTSX_DEBUGP("Response length: %d\n", data_len);
+	RTSX_DEBUGP("Response: 0x%x 0x%x 0x%x 0x%x\n",
+		sd_card->rsp[0], sd_card->rsp[1], sd_card->rsp[2], sd_card->rsp[3]);
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+}
+
+int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	unsigned int lun = SCSI_LUN(srb);
+	int retval;
+
+	if (!sd_card->sd_pass_thru_en) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if (sd_card->pre_cmd_err) {
+		sd_card->pre_cmd_err = 0;
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	if ((0x53 != srb->cmnd[2]) || (0x44 != srb->cmnd[3]) || (0x20 != srb->cmnd[4]) ||
+			(0x43 != srb->cmnd[5]) || (0x61 != srb->cmnd[6]) ||
+			(0x72 != srb->cmnd[7]) || (0x64 != srb->cmnd[8])) {
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	switch (srb->cmnd[1] & 0x0F) {
+	case 0:
+#ifdef SUPPORT_SD_LOCK
+		if (0x64 == srb->cmnd[9]) {
+			sd_card->sd_lock_status |= SD_SDR_RST;
+		}
+#endif
+		retval = reset_sd_card(chip);
+		if (retval != STATUS_SUCCESS) {
+#ifdef SUPPORT_SD_LOCK
+			sd_card->sd_lock_status &= ~SD_SDR_RST;
+#endif
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			sd_card->pre_cmd_err = 1;
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+#ifdef SUPPORT_SD_LOCK
+		sd_card->sd_lock_status &= ~SD_SDR_RST;
+#endif
+		break;
+
+	case 1:
+		retval = soft_reset_sd_card(chip);
+		if (retval != STATUS_SUCCESS) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			sd_card->pre_cmd_err = 1;
+			TRACE_RET(chip, TRANSPORT_FAILED);
+		}
+		break;
+
+	default:
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
+		TRACE_RET(chip, TRANSPORT_FAILED);
+	}
+
+	scsi_set_resid(srb, 0);
+	return TRANSPORT_GOOD;
+}
+#endif
+
+void sd_cleanup_work(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+
+	if (sd_card->seq_mode) {
+		RTSX_DEBUGP("SD: stop transmission\n");
+		sd_stop_seq_mode(chip);
+		sd_card->cleanup_counter = 0;
+	}
+}
+
+int sd_power_off_card3v3(struct rtsx_chip *chip)
+{
+	int retval;
+
+	retval = disable_card_clock(chip, SD_CARD);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_WRITE_REG(chip, CARD_OE, SD_OUTPUT_EN, 0);
+
+	if (!chip->ft2_fast_mode) {
+		retval = card_power_off(chip, SD_CARD);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		wait_timeout(50);
+	}
+
+	if (chip->asic_code) {
+		retval = sd_pull_ctl_disable(chip);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		RTSX_WRITE_REG(chip, FPGA_PULL_CTL,
+			FPGA_SD_PULL_CTL_BIT | 0x20, FPGA_SD_PULL_CTL_BIT);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int release_sd_card(struct rtsx_chip *chip)
+{
+	struct sd_info *sd_card = &(chip->sd_card);
+	int retval;
+
+	RTSX_DEBUGP("release_sd_card\n");
+
+	chip->card_ready &= ~SD_CARD;
+	chip->card_fail &= ~SD_CARD;
+	chip->card_wp &= ~SD_CARD;
+
+	chip->sd_io = 0;
+	chip->sd_int = 0;
+
+#ifdef SUPPORT_SD_LOCK
+	sd_card->sd_lock_status = 0;
+	sd_card->sd_erase_status = 0;
+#endif
+
+	memset(sd_card->raw_csd, 0, 16);
+	memset(sd_card->raw_scr, 0, 8);
+
+	retval = sd_power_off_card3v3(chip);
+	if (retval != STATUS_SUCCESS) {
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (CHECK_PID(chip, 0x5209)) {
+		retval = sd_change_bank_voltage(chip, SD_IO_3V3);
+		if (retval != STATUS_SUCCESS) {
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (CHK_SD30_SPEED(sd_card)) {
+			RTSX_WRITE_REG(chip, SD30_DRIVE_SEL, 0x07, chip->sd30_drive_sel_3v3);
+		}
+
+		RTSX_WRITE_REG(chip, OCPPARA2, SD_OCP_THD_MASK, chip->sd_400mA_ocp_thd);
+	}
+
+	return STATUS_SUCCESS;
+}
diff --git a/drivers/staging/rts_pstor/sd.h b/drivers/staging/rts_pstor/sd.h
new file mode 100644
index 0000000..d62e690
--- /dev/null
+++ b/drivers/staging/rts_pstor/sd.h
@@ -0,0 +1,295 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_SD_H
+#define __REALTEK_RTSX_SD_H
+
+#include "rtsx_chip.h"
+
+#define SUPPORT_VOLTAGE	0x003C0000
+
+/* Error Code */
+#define	SD_NO_ERROR		0x0
+#define	SD_CRC_ERR		0x80
+#define	SD_TO_ERR		0x40
+#define	SD_NO_CARD		0x20
+#define SD_BUSY			0x10
+#define	SD_STS_ERR		0x08
+#define SD_RSP_TIMEOUT		0x04
+#define SD_IO_ERR		0x02
+
+/* MMC/SD Command Index */
+/* Basic command (class 0) */
+#define GO_IDLE_STATE		0
+#define	SEND_OP_COND		1
+#define	ALL_SEND_CID		2
+#define	SET_RELATIVE_ADDR	3
+#define	SEND_RELATIVE_ADDR	3
+#define	SET_DSR			4
+#define IO_SEND_OP_COND		5
+#define	SWITCH			6
+#define	SELECT_CARD		7
+#define	DESELECT_CARD		7
+/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec
+ * while is "SEND_IF_COND" for SD 2.0
+ */
+#define	SEND_EXT_CSD		8
+#define	SEND_IF_COND		8
+
+#define	SEND_CSD		9
+#define	SEND_CID		10
+#define	VOLTAGE_SWITCH	    	11
+#define	READ_DAT_UTIL_STOP	11
+#define	STOP_TRANSMISSION	12
+#define	SEND_STATUS		13
+#define	GO_INACTIVE_STATE	15
+
+#define	SET_BLOCKLEN		16
+#define	READ_SINGLE_BLOCK	17
+#define	READ_MULTIPLE_BLOCK	18
+#define	SEND_TUNING_PATTERN	19
+
+#define	BUSTEST_R		14
+#define	BUSTEST_W		19
+
+#define	WRITE_BLOCK		24
+#define	WRITE_MULTIPLE_BLOCK	25
+#define	PROGRAM_CSD		27
+
+#define	ERASE_WR_BLK_START	32
+#define	ERASE_WR_BLK_END	33
+#define	ERASE_CMD		38
+
+#define LOCK_UNLOCK 		42
+#define	IO_RW_DIRECT		52
+
+#define	APP_CMD			55
+#define	GEN_CMD			56
+
+#define	SET_BUS_WIDTH		6
+#define	SD_STATUS		13
+#define	SEND_NUM_WR_BLOCKS	22
+#define	SET_WR_BLK_ERASE_COUNT	23
+#define	SD_APP_OP_COND		41
+#define	SET_CLR_CARD_DETECT	42
+#define	SEND_SCR		51
+
+#define	SD_READ_COMPLETE	0x00
+#define	SD_READ_TO		0x01
+#define	SD_READ_ADVENCE		0x02
+
+#define	SD_CHECK_MODE		0x00
+#define	SD_SWITCH_MODE		0x80
+#define	SD_FUNC_GROUP_1	    	0x01
+#define	SD_FUNC_GROUP_2	    	0x02
+#define	SD_FUNC_GROUP_3	    	0x03
+#define	SD_FUNC_GROUP_4	    	0x04
+#define	SD_CHECK_SPEC_V1_1	0xFF
+
+#define	NO_ARGUMENT	                        0x00
+#define	CHECK_PATTERN	                    	0x000000AA
+#define	VOLTAGE_SUPPLY_RANGE	            	0x00000100
+#define	SUPPORT_HIGH_AND_EXTENDED_CAPACITY	0x40000000
+#define	SUPPORT_MAX_POWER_PERMANCE	        0x10000000
+#define	SUPPORT_1V8	                        0x01000000
+
+#define	SWTICH_NO_ERR	  	0x00
+#define	CARD_NOT_EXIST	  	0x01
+#define	SPEC_NOT_SUPPORT  	0x02
+#define	CHECK_MODE_ERR	  	0x03
+#define	CHECK_NOT_READY	  	0x04
+#define	SWITCH_CRC_ERR	  	0x05
+#define	SWITCH_MODE_ERR	  	0x06
+#define	SWITCH_PASS		0x07
+
+#ifdef SUPPORT_SD_LOCK
+#define SD_ERASE		0x08
+#define SD_LOCK			0x04
+#define SD_UNLOCK		0x00
+#define SD_CLR_PWD		0x02
+#define SD_SET_PWD		0x01
+
+#define SD_PWD_LEN		0x10
+
+#define SD_LOCKED		0x80
+#define SD_LOCK_1BIT_MODE	0x40
+#define SD_PWD_EXIST		0x20
+#define SD_UNLOCK_POW_ON	0x01
+#define SD_SDR_RST		0x02
+
+#define SD_NOT_ERASE		0x00
+#define SD_UNDER_ERASING	0x01
+#define SD_COMPLETE_ERASE	0x02
+
+#define SD_RW_FORBIDDEN		0x0F
+
+#endif
+
+#define	HS_SUPPORT			0x01
+#define	SDR50_SUPPORT			0x02
+#define	SDR104_SUPPORT	        	0x03
+#define	DDR50_SUPPORT		    	0x04
+
+#define	HS_SUPPORT_MASK	        	0x02
+#define	SDR50_SUPPORT_MASK	    	0x04
+#define	SDR104_SUPPORT_MASK	    	0x08
+#define	DDR50_SUPPORT_MASK	    	0x10
+
+#define	HS_QUERY_SWITCH_OK	    	0x01
+#define	SDR50_QUERY_SWITCH_OK		0x02
+#define	SDR104_QUERY_SWITCH_OK  	0x03
+#define	DDR50_QUERY_SWITCH_OK   	0x04
+
+#define	HS_SWITCH_BUSY	        	0x02
+#define	SDR50_SWITCH_BUSY	    	0x04
+#define	SDR104_SWITCH_BUSY      	0x08
+#define	DDR50_SWITCH_BUSY       	0x10
+
+#define	FUNCTION_GROUP1_SUPPORT_OFFSET       0x0D
+#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET  0x10
+#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET    0x1D
+
+#define	DRIVING_TYPE_A	        0x01
+#define	DRIVING_TYPE_B		    0x00
+#define	DRIVING_TYPE_C		    0x02
+#define	DRIVING_TYPE_D	        0x03
+
+#define	DRIVING_TYPE_A_MASK	    0x02
+#define	DRIVING_TYPE_B_MASK	    0x01
+#define	DRIVING_TYPE_C_MASK	    0x04
+#define	DRIVING_TYPE_D_MASK	    0x08
+
+#define	TYPE_A_QUERY_SWITCH_OK	0x01
+#define	TYPE_B_QUERY_SWITCH_OK	0x00
+#define	TYPE_C_QUERY_SWITCH_OK  0x02
+#define	TYPE_D_QUERY_SWITCH_OK  0x03
+
+#define	TYPE_A_SWITCH_BUSY	    0x02
+#define	TYPE_B_SWITCH_BUSY	    0x01
+#define	TYPE_C_SWITCH_BUSY      0x04
+#define	TYPE_D_SWITCH_BUSY      0x08
+
+#define	FUNCTION_GROUP3_SUPPORT_OFFSET       0x09
+#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET  0x0F
+#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET    0x19
+
+#define	CURRENT_LIMIT_200	    0x00
+#define	CURRENT_LIMIT_400	    0x01
+#define	CURRENT_LIMIT_600	    0x02
+#define	CURRENT_LIMIT_800	    0x03
+
+#define	CURRENT_LIMIT_200_MASK	0x01
+#define	CURRENT_LIMIT_400_MASK	0x02
+#define	CURRENT_LIMIT_600_MASK	0x04
+#define	CURRENT_LIMIT_800_MASK	0x08
+
+#define	CURRENT_LIMIT_200_QUERY_SWITCH_OK    0x00
+#define	CURRENT_LIMIT_400_QUERY_SWITCH_OK    0x01
+#define	CURRENT_LIMIT_600_QUERY_SWITCH_OK    0x02
+#define	CURRENT_LIMIT_800_QUERY_SWITCH_OK    0x03
+
+#define	CURRENT_LIMIT_200_SWITCH_BUSY        0x01
+#define	CURRENT_LIMIT_400_SWITCH_BUSY	     0x02
+#define	CURRENT_LIMIT_600_SWITCH_BUSY        0x04
+#define	CURRENT_LIMIT_800_SWITCH_BUSY        0x08
+
+#define	FUNCTION_GROUP4_SUPPORT_OFFSET       0x07
+#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET  0x0F
+#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET    0x17
+
+#define	DATA_STRUCTURE_VER_OFFSET	0x11
+
+#define MAX_PHASE			31
+
+#define MMC_8BIT_BUS			0x0010
+#define MMC_4BIT_BUS			0x0020
+
+#define MMC_SWITCH_ERR			0x80
+
+#define SD_IO_3V3		0
+#define SD_IO_1V8		1
+
+#define TUNE_TX    0x00
+#define TUNE_RX	   0x01
+
+#define CHANGE_TX  0x00
+#define CHANGE_RX  0x01
+
+#define DCM_HIGH_FREQUENCY_MODE  0x00
+#define DCM_LOW_FREQUENCY_MODE   0x01
+
+#define DCM_HIGH_FREQUENCY_MODE_SET  0x0C
+#define DCM_Low_FREQUENCY_MODE_SET   0x00
+
+#define MULTIPLY_BY_1    0x00
+#define MULTIPLY_BY_2    0x01
+#define MULTIPLY_BY_3    0x02
+#define MULTIPLY_BY_4    0x03
+#define MULTIPLY_BY_5    0x04
+#define MULTIPLY_BY_6    0x05
+#define MULTIPLY_BY_7    0x06
+#define MULTIPLY_BY_8    0x07
+#define MULTIPLY_BY_9    0x08
+#define MULTIPLY_BY_10   0x09
+
+#define DIVIDE_BY_2      0x01
+#define DIVIDE_BY_3      0x02
+#define DIVIDE_BY_4      0x03
+#define DIVIDE_BY_5      0x04
+#define DIVIDE_BY_6      0x05
+#define DIVIDE_BY_7      0x06
+#define DIVIDE_BY_8      0x07
+#define DIVIDE_BY_9      0x08
+#define DIVIDE_BY_10     0x09
+
+struct timing_phase_path {
+	int start;
+	int end;
+	int mid;
+	int len;
+};
+
+int sd_select_card(struct rtsx_chip *chip, int select);
+int sd_pull_ctl_enable(struct rtsx_chip *chip);
+int reset_sd_card(struct rtsx_chip *chip);
+int sd_switch_clock(struct rtsx_chip *chip);
+void sd_stop_seq_mode(struct rtsx_chip *chip);
+int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
+void sd_cleanup_work(struct rtsx_chip *chip);
+int sd_power_off_card3v3(struct rtsx_chip *chip);
+int release_sd_card(struct rtsx_chip *chip);
+#ifdef SUPPORT_CPRM
+int soft_reset_sd_card(struct rtsx_chip *chip);
+int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
+		u32 arg, u8 rsp_type, u8 *rsp, int rsp_len, int special_check);
+int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type);
+
+int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+#endif
+
+#endif  /* __REALTEK_RTSX_SD_H */
diff --git a/drivers/staging/rts_pstor/spi.c b/drivers/staging/rts_pstor/spi.c
new file mode 100644
index 0000000..8a8689b
--- /dev/null
+++ b/drivers/staging/rts_pstor/spi.c
@@ -0,0 +1,812 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "spi.h"
+
+static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct spi_info *spi = &(chip->spi);
+
+	spi->err_code = err_code;
+}
+
+static int spi_init(struct rtsx_chip *chip)
+{
+	RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF,
+		CS_POLARITY_LOW | DTO_MSB_FIRST | SPI_MASTER | SPI_MODE0 | SPI_AUTO);
+	RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
+
+	return STATUS_SUCCESS;
+}
+
+static int spi_set_init_para(struct rtsx_chip *chip)
+{
+	struct spi_info *spi = &(chip->spi);
+	int retval;
+
+	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, (u8)(spi->clk_div >> 8));
+	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, (u8)(spi->clk_div));
+
+	retval = switch_clock(chip, spi->spi_clock);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = select_card(chip, SPI_CARD);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
+	RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
+
+	wait_timeout(10);
+
+	retval = spi_init(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
+
+static int sf_polling_status(struct rtsx_chip *chip, int msec)
+{
+	int retval;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_POLLING_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, msec);
+	if (retval < 0) {
+		rtsx_clear_spi_error(chip);
+		spi_set_err_code(chip, SPI_BUSY_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sf_enable_write(struct rtsx_chip *chip, u8 ins)
+{
+	struct spi_info *spi = &(chip->spi);
+	int retval;
+
+	if (!spi->write_en)
+		return STATUS_SUCCESS;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0) {
+		rtsx_clear_spi_error(chip);
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int sf_disable_write(struct rtsx_chip *chip, u8 ins)
+{
+	struct spi_info *spi = &(chip->spi);
+	int retval;
+
+	if (!spi->write_en)
+		return STATUS_SUCCESS;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0) {
+		rtsx_clear_spi_error(chip);
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr, u16 len)
+{
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8));
+	if (addr_mode) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADO_MODE0);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CDO_MODE0);
+	}
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+}
+
+static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)
+{
+	int retval;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+	if (addr_mode) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
+	}
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0) {
+		rtsx_clear_spi_error(chip);
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int spi_init_eeprom(struct rtsx_chip *chip)
+{
+	int retval;
+	int clk;
+
+	if (chip->asic_code)
+		clk = 30;
+	else
+		clk = CLK_30;
+
+	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
+	RTSX_WRITE_REG(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
+
+	retval = switch_clock(chip, clk);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = select_card(chip, SPI_CARD);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	RTSX_WRITE_REG(chip, CARD_CLK_EN, SPI_CLK_EN, SPI_CLK_EN);
+	RTSX_WRITE_REG(chip, CARD_OE, SPI_OUTPUT_EN, SPI_OUTPUT_EN);
+
+	wait_timeout(10);
+
+	RTSX_WRITE_REG(chip, SPI_CONTROL, 0xFF, CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
+	RTSX_WRITE_REG(chip, SPI_TCTL, EDO_TIMING_MASK, SAMPLE_DELAY_HALF);
+
+	return STATUS_SUCCESS;
+}
+
+static int spi_eeprom_program_enable(struct rtsx_chip *chip)
+{
+	int retval;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
+
+int spi_erase_eeprom_chip(struct rtsx_chip *chip)
+{
+	int retval;
+
+	retval = spi_init_eeprom(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = spi_eeprom_program_enable(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+
+	return STATUS_SUCCESS;
+}
+
+int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
+{
+	int retval;
+
+	retval = spi_init_eeprom(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = spi_eeprom_program_enable(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+
+	return STATUS_SUCCESS;
+}
+
+
+int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
+{
+	int retval;
+	u8 data;
+
+	retval = spi_init_eeprom(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	wait_timeout(5);
+	RTSX_READ_REG(chip, SPI_DATA, &data);
+
+	if (val)
+		*val = data;
+
+	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+
+	return STATUS_SUCCESS;
+}
+
+int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
+{
+	int retval;
+
+	retval = spi_init_eeprom(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = spi_eeprom_program_enable(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	RTSX_WRITE_REG(chip, CARD_GPIO_DIR, 0x01, 0x01);
+
+	return STATUS_SUCCESS;
+}
+
+
+int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct spi_info *spi = &(chip->spi);
+
+	RTSX_DEBUGP("spi_get_status: err_code = 0x%x\n", spi->err_code);
+	rtsx_stor_set_xfer_buf(&(spi->err_code), min((int)scsi_bufflen(srb), 1), srb);
+	scsi_set_resid(srb, scsi_bufflen(srb) - 1);
+
+	return STATUS_SUCCESS;
+}
+
+int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	struct spi_info *spi = &(chip->spi);
+
+	spi_set_err_code(chip, SPI_NO_ERR);
+
+	if (chip->asic_code)
+		spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9];
+	else
+		spi->spi_clock = srb->cmnd[3];
+
+	spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
+	spi->write_en = srb->cmnd[6];
+
+	RTSX_DEBUGP("spi_set_parameter: spi_clock = %d, clk_div = %d, write_en = %d\n",
+		     spi->spi_clock, spi->clk_div, spi->write_en);
+
+	return STATUS_SUCCESS;
+}
+
+int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u16 len;
+	u8 *buf;
+
+	spi_set_err_code(chip, SPI_NO_ERR);
+
+	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
+	if (len > 512) {
+		spi_set_err_code(chip, SPI_INVALID_COMMAND);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = spi_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]);
+
+	if (len == 0) {
+		if (srb->cmnd[9]) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
+				      0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
+				      0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
+		}
+	} else {
+		if (srb->cmnd[9]) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
+				      0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
+				      0xFF, SPI_TRANSFER0_START | SPI_CDI_MODE0);
+		}
+	}
+
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval < 0) {
+		rtsx_clear_spi_error(chip);
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (len) {
+		buf = (u8 *)kmalloc(len, GFP_KERNEL);
+		if (!buf)
+			TRACE_RET(chip, STATUS_ERROR);
+
+		retval = rtsx_read_ppbuf(chip, buf, len);
+		if (retval != STATUS_SUCCESS) {
+			spi_set_err_code(chip, SPI_READ_ERR);
+			kfree(buf);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
+		scsi_set_resid(srb, 0);
+
+		kfree(buf);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	unsigned int index = 0, offset = 0;
+	u8 ins, slow_read;
+	u32 addr;
+	u16 len;
+	u8 *buf;
+
+	spi_set_err_code(chip, SPI_NO_ERR);
+
+	ins = srb->cmnd[3];
+	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
+	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
+	slow_read = srb->cmnd[9];
+
+	retval = spi_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	buf = (u8 *)rtsx_alloc_dma_buf(chip, SF_PAGE_LEN, GFP_KERNEL);
+	if (buf == NULL)
+		TRACE_RET(chip, STATUS_ERROR);
+
+	while (len) {
+		u16 pagelen = SF_PAGE_LEN - (u8)addr;
+
+		if (pagelen > len)
+			pagelen = len;
+
+		rtsx_init_cmd(chip);
+
+		trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
+
+		if (slow_read) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 16));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF, (u8)(addr >> 16));
+			rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32);
+		}
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(pagelen >> 8));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)pagelen);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CADI_MODE0);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, DMA_FROM_DEVICE, 10000);
+		if (retval < 0) {
+			rtsx_free_dma_buf(chip, buf);
+			rtsx_clear_spi_error(chip);
+			spi_set_err_code(chip, SPI_HW_ERR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, TO_XFER_BUF);
+
+		addr += pagelen;
+		len -= pagelen;
+	}
+
+	scsi_set_resid(srb, 0);
+	rtsx_free_dma_buf(chip, buf);
+
+	return STATUS_SUCCESS;
+}
+
+int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u8 ins, program_mode;
+	u32 addr;
+	u16 len;
+	u8 *buf;
+	unsigned int index = 0, offset = 0;
+
+	spi_set_err_code(chip, SPI_NO_ERR);
+
+	ins = srb->cmnd[3];
+	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
+	len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
+	program_mode = srb->cmnd[9];
+
+	retval = spi_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (program_mode == BYTE_PROGRAM) {
+		buf = rtsx_alloc_dma_buf(chip, 4, GFP_KERNEL);
+		if (!buf)
+			TRACE_RET(chip, STATUS_ERROR);
+
+		while (len) {
+			retval = sf_enable_write(chip, SPI_WREN);
+			if (retval != STATUS_SUCCESS) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, FROM_XFER_BUF);
+
+			rtsx_init_cmd(chip);
+
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, buf[0]);
+			sf_program(chip, ins, 1, addr, 1);
+
+			retval = rtsx_send_cmd(chip, 0, 100);
+			if (retval < 0) {
+				rtsx_free_dma_buf(chip, buf);
+				rtsx_clear_spi_error(chip);
+				spi_set_err_code(chip, SPI_HW_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = sf_polling_status(chip, 100);
+			if (retval != STATUS_SUCCESS) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			addr++;
+			len--;
+		}
+
+		rtsx_free_dma_buf(chip, buf);
+
+	} else if (program_mode == AAI_PROGRAM) {
+		int first_byte = 1;
+
+		retval = sf_enable_write(chip, SPI_WREN);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		buf = rtsx_alloc_dma_buf(chip, 4, GFP_KERNEL);
+		if (!buf)
+			TRACE_RET(chip, STATUS_ERROR);
+
+		while (len) {
+			rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset, FROM_XFER_BUF);
+
+			rtsx_init_cmd(chip);
+
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, buf[0]);
+			if (first_byte) {
+				sf_program(chip, ins, 1, addr, 1);
+				first_byte = 0;
+			} else {
+				sf_program(chip, ins, 0, 0, 1);
+			}
+
+			retval = rtsx_send_cmd(chip, 0, 100);
+			if (retval < 0) {
+				rtsx_free_dma_buf(chip, buf);
+				rtsx_clear_spi_error(chip);
+				spi_set_err_code(chip, SPI_HW_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = sf_polling_status(chip, 100);
+			if (retval != STATUS_SUCCESS) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			len--;
+		}
+
+		rtsx_free_dma_buf(chip, buf);
+
+		retval = sf_disable_write(chip, SPI_WRDI);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		retval = sf_polling_status(chip, 100);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+	} else if (program_mode == PAGE_PROGRAM) {
+		buf = rtsx_alloc_dma_buf(chip, SF_PAGE_LEN, GFP_KERNEL);
+		if (!buf)
+			TRACE_RET(chip, STATUS_NOMEM);
+
+		while (len) {
+			u16 pagelen = SF_PAGE_LEN - (u8)addr;
+
+			if (pagelen > len)
+				pagelen = len;
+
+			retval = sf_enable_write(chip, SPI_WREN);
+			if (retval != STATUS_SUCCESS) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			rtsx_init_cmd(chip);
+
+			trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256);
+			sf_program(chip, ins, 1, addr, pagelen);
+
+			rtsx_send_cmd_no_wait(chip);
+
+			rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset, FROM_XFER_BUF);
+
+			retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0, DMA_TO_DEVICE, 100);
+			if (retval < 0) {
+				rtsx_free_dma_buf(chip, buf);
+				rtsx_clear_spi_error(chip);
+				spi_set_err_code(chip, SPI_HW_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = sf_polling_status(chip, 100);
+			if (retval != STATUS_SUCCESS) {
+				rtsx_free_dma_buf(chip, buf);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			addr += pagelen;
+			len -= pagelen;
+		}
+
+		rtsx_free_dma_buf(chip, buf);
+	} else {
+		spi_set_err_code(chip, SPI_INVALID_COMMAND);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u8 ins, erase_mode;
+	u32 addr;
+
+	spi_set_err_code(chip, SPI_NO_ERR);
+
+	ins = srb->cmnd[3];
+	addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5]) << 8) | srb->cmnd[6];
+	erase_mode = srb->cmnd[9];
+
+	retval = spi_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	if (erase_mode == PAGE_ERASE) {
+		retval = sf_enable_write(chip, SPI_WREN);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		retval = sf_erase(chip, ins, 1, addr);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+	} else if (erase_mode == CHIP_ERASE) {
+		retval = sf_enable_write(chip, SPI_WREN);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		retval = sf_erase(chip, ins, 0, 0);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+	} else {
+		spi_set_err_code(chip, SPI_INVALID_COMMAND);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
+{
+	int retval;
+	u8 ins, status, ewsr;
+
+	ins = srb->cmnd[3];
+	status = srb->cmnd[4];
+	ewsr = srb->cmnd[5];
+
+	retval = spi_set_init_para(chip);
+	if (retval != STATUS_SUCCESS) {
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = sf_enable_write(chip, ewsr);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF, SPI_TRANSFER0_START | SPI_CDO_MODE0);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END, SPI_TRANSFER0_END);
+
+	retval = rtsx_send_cmd(chip, 0, 100);
+	if (retval != STATUS_SUCCESS) {
+		rtsx_clear_spi_error(chip);
+		spi_set_err_code(chip, SPI_HW_ERR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
diff --git a/drivers/staging/rts_pstor/spi.h b/drivers/staging/rts_pstor/spi.h
new file mode 100644
index 0000000..b59291f
--- /dev/null
+++ b/drivers/staging/rts_pstor/spi.h
@@ -0,0 +1,65 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_SPI_H
+#define __REALTEK_RTSX_SPI_H
+
+/* SPI operation error */
+#define SPI_NO_ERR		0x00
+#define SPI_HW_ERR		0x01
+#define SPI_INVALID_COMMAND	0x02
+#define SPI_READ_ERR		0x03
+#define SPI_WRITE_ERR		0x04
+#define SPI_ERASE_ERR		0x05
+#define SPI_BUSY_ERR		0x06
+
+/* Serial flash instruction */
+#define SPI_READ 		0x03
+#define SPI_FAST_READ		0x0B
+#define SPI_WREN		0x06
+#define SPI_WRDI		0x04
+#define SPI_RDSR		0x05
+
+#define SF_PAGE_LEN		256
+
+#define BYTE_PROGRAM		0
+#define AAI_PROGRAM		1
+#define PAGE_PROGRAM		2
+
+#define PAGE_ERASE		0
+#define CHIP_ERASE		1
+
+int spi_erase_eeprom_chip(struct rtsx_chip *chip);
+int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr);
+int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val);
+int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val);
+int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
+
+
+#endif  /* __REALTEK_RTSX_SPI_H */
diff --git a/drivers/staging/rts_pstor/trace.h b/drivers/staging/rts_pstor/trace.h
new file mode 100644
index 0000000..2c668ba
--- /dev/null
+++ b/drivers/staging/rts_pstor/trace.h
@@ -0,0 +1,117 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_TRACE_H
+#define __REALTEK_RTSX_TRACE_H
+
+#define _MSG_TRACE
+
+#ifdef _MSG_TRACE
+static inline char *filename(char *path)
+{
+	char *ptr;
+
+	if (path == NULL)
+		return NULL;
+
+	ptr = path;
+
+	while (*ptr != '\0') {
+		if ((*ptr == '\\') || (*ptr == '/'))
+			path = ptr + 1;
+		
+		ptr++;
+	}
+
+	return path;
+}
+
+#define TRACE_RET(chip, ret)   										\
+do {													\
+	char *_file = filename(__FILE__);								\
+	RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__);					\
+	(chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__);					\
+	strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1);			\
+	strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); 			\
+	get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN);			\
+	(chip)->trace_msg[(chip)->msg_idx].valid = 1;							\
+	(chip)->msg_idx++; 										\
+	if ((chip)->msg_idx >= TRACE_ITEM_CNT) { 							\
+		(chip)->msg_idx = 0;									\
+	}												\
+	return ret; 											\
+} while (0)
+
+#define TRACE_GOTO(chip, label)   									\
+do {													\
+	char *_file = filename(__FILE__);								\
+	RTSX_DEBUGP("[%s][%s]:[%d]\n", _file, __func__, __LINE__);					\
+	(chip)->trace_msg[(chip)->msg_idx].line = (u16)(__LINE__);					\
+	strncpy((chip)->trace_msg[(chip)->msg_idx].func, __func__, MSG_FUNC_LEN-1);			\
+	strncpy((chip)->trace_msg[(chip)->msg_idx].file, _file, MSG_FILE_LEN-1); 			\
+	get_current_time((chip)->trace_msg[(chip)->msg_idx].timeval_buf, TIME_VAL_LEN);			\
+	(chip)->trace_msg[(chip)->msg_idx].valid = 1;							\
+	(chip)->msg_idx++; 										\
+	if ((chip)->msg_idx >= TRACE_ITEM_CNT) { 							\
+		(chip)->msg_idx = 0;									\
+	}												\
+	goto label; 											\
+} while (0)
+#else
+#define TRACE_RET(chip, ret)	return ret
+#define TRACE_GOTO(chip, label)	goto label
+#endif
+
+#if CONFIG_RTS_PSTOR_DEBUG
+static inline void rtsx_dump(u8 *buf, int buf_len)
+{
+	int i;
+	u8 tmp[16] = {0};
+	u8 *_ptr = buf;
+
+	for (i = 0; i < ((buf_len)/16); i++) {
+		RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
+			"%02x %02x %02x %02x %02x %02x %02x %02x\n",
+			_ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5],
+			_ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11],
+			_ptr[12], _ptr[13], _ptr[14], _ptr[15]);
+		_ptr += 16;
+	}
+	if ((buf_len) % 16) {
+		memcpy(tmp, _ptr, (buf_len) % 16);
+		_ptr = tmp;
+		RTSX_DEBUGP("%02x %02x %02x %02x %02x %02x %02x %02x "
+			"%02x %02x %02x %02x %02x %02x %02x %02x\n",
+			_ptr[0], _ptr[1], _ptr[2], _ptr[3], _ptr[4], _ptr[5],
+			_ptr[6], _ptr[7], _ptr[8], _ptr[9], _ptr[10], _ptr[11],
+			_ptr[12], _ptr[13], _ptr[14], _ptr[15]);
+	}
+}
+
+#define RTSX_DUMP(buf, buf_len)		rtsx_dump((u8 *)(buf), (buf_len))
+
+#else
+#define RTSX_DUMP(buf, buf_len)
+#endif
+
+#endif  /* __REALTEK_RTSX_TRACE_H */
diff --git a/drivers/staging/rts_pstor/xd.c b/drivers/staging/rts_pstor/xd.c
new file mode 100644
index 0000000..7bcd468
--- /dev/null
+++ b/drivers/staging/rts_pstor/xd.c
@@ -0,0 +1,2051 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include "rtsx.h"
+#include "rtsx_transport.h"
+#include "rtsx_scsi.h"
+#include "rtsx_card.h"
+#include "xd.h"
+
+static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no);
+static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, u8 start_page, u8 end_page);
+
+static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+
+	xd_card->err_code = err_code;
+}
+
+static inline int xd_check_err_code(struct rtsx_chip *chip, u8 err_code)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+
+	return (xd_card->err_code == err_code);
+}
+
+static int xd_set_init_para(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval;
+
+	if (chip->asic_code)
+		xd_card->xd_clock = 47;
+	else
+		xd_card->xd_clock = CLK_50;
+
+	retval = switch_clock(chip, xd_card->xd_clock);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_switch_clock(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval;
+
+	retval = select_card(chip, XD_CARD);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = switch_clock(chip, xd_card->xd_clock);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len)
+{
+	int retval, i;
+	u8 *ptr;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_ID);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	for (i = 0; i < 4; i++)
+		rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 20);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+	if (id_buf && buf_len) {
+		if (buf_len > 4)
+			buf_len = 4;
+		memcpy(id_buf, ptr, buf_len);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+
+	switch (mode) {
+	case XD_RW_ADDR:
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, (u8)(addr >> 8));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3, 0xFF, (u8)(addr >> 16));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
+				xd_card->addr_cycle | XD_CALC_ECC | XD_BA_NO_TRANSFORM);
+		break;
+
+	case XD_ERASE_ADDR:
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)(addr >> 8));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2, 0xFF, (u8)(addr >> 16));
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
+				(xd_card->addr_cycle - 1) | XD_CALC_ECC | XD_BA_NO_TRANSFORM);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr, u8 *buf, int buf_len)
+{
+	int retval, i;
+
+	rtsx_init_cmd(chip);
+
+	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	for (i = 0; i < 6; i++)
+		rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i), 0, 0);
+	for (i = 0; i < 4; i++)
+		rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i), 0, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 500);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	if (buf && buf_len) {
+		u8 *ptr = rtsx_get_cmd_data(chip) + 1;
+
+		if (buf_len > 11)
+			buf_len = 11;
+		memcpy(buf, ptr, buf_len);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset, u8 *buf, int buf_len)
+{
+	int retval, i;
+
+	if (!buf || (buf_len < 0))
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	for (i = 0; i < buf_len; i++)
+		rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i, 0, 0);
+
+	retval = rtsx_send_cmd(chip, 0, 250);
+	if (retval < 0) {
+		rtsx_clear_xd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	memcpy(buf, rtsx_get_cmd_data(chip), buf_len);
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf, int buf_len)
+{
+	int retval;
+	u8 reg;
+
+	if (!buf || (buf_len < 10))
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_PAGES);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 250);
+	if (retval == -ETIMEDOUT) {
+		rtsx_clear_xd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, XD_PAGE_STATUS, &reg);
+	if (reg != XD_GPG) {
+		rtsx_clear_xd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	RTSX_READ_REG(chip, XD_CTL, &reg);
+	if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) {
+		retval = xd_read_data_from_ppb(chip, 0, buf, buf_len);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+		if (reg & XD_ECC1_ERROR) {
+			u8 ecc_bit, ecc_byte;
+
+			RTSX_READ_REG(chip, XD_ECC_BIT1, &ecc_bit);
+			RTSX_READ_REG(chip, XD_ECC_BYTE1, &ecc_byte);
+
+			RTSX_DEBUGP("ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n", ecc_bit, ecc_byte);
+			if (ecc_byte < buf_len) {
+				RTSX_DEBUGP("Before correct: 0x%x\n", buf[ecc_byte]);
+				buf[ecc_byte] ^= (1 << ecc_bit);
+				RTSX_DEBUGP("After correct: 0x%x\n", buf[ecc_byte]);
+			}
+		}
+	} else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) {
+		rtsx_clear_xd_error(chip);
+
+		retval = xd_read_data_from_ppb(chip, 256, buf, buf_len);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+		if (reg & XD_ECC2_ERROR) {
+			u8 ecc_bit, ecc_byte;
+
+			RTSX_READ_REG(chip, XD_ECC_BIT2, &ecc_bit);
+			RTSX_READ_REG(chip, XD_ECC_BYTE2, &ecc_byte);
+
+			RTSX_DEBUGP("ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n", ecc_bit, ecc_byte);
+			if (ecc_byte < buf_len) {
+				RTSX_DEBUGP("Before correct: 0x%x\n", buf[ecc_byte]);
+				buf[ecc_byte] ^= (1 << ecc_bit);
+				RTSX_DEBUGP("After correct: 0x%x\n", buf[ecc_byte]);
+			}
+		}
+	} else {
+		rtsx_clear_xd_error(chip);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xD5);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x15);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
+			XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
+			XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
+			XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x69);
+		}
+	}
+}
+
+static void xd_fill_pull_ctl_stage1_barossa(struct rtsx_chip *chip)
+{
+	if (CHECK_BARO_PKG(chip, QFN)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+	}
+}
+
+static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0xAA);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0xD5);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF, 0x55);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, 0x15);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
+			XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
+			XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
+			XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x53);
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0xA9);
+		}
+	}
+}
+
+static int xd_pull_ctl_disable(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0xD5);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF, 0x55);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, 0x15);
+	} else if (CHECK_PID(chip, 0x5208)) {
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF,
+			XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF,
+			XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF,
+			XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF,
+			XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL5, 0xFF,
+			MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
+		RTSX_WRITE_REG(chip, CARD_PULL_CTL6, 0xFF, MS_D5_PD | MS_D4_PD);
+	} else if (CHECK_PID(chip, 0x5288)) {
+		if (CHECK_BARO_PKG(chip, QFN)) {
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0x55);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL2, 0xFF, 0x55);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL3, 0xFF, 0x4B);
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL4, 0xFF, 0x69);
+		}
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static void xd_clear_dma_buffer(struct rtsx_chip *chip)
+{
+	if (CHECK_PID(chip, 0x5209)) {
+		int retval;
+		u8 *buf;
+
+		RTSX_DEBUGP("xD ECC error, dummy write!\n");
+
+		buf = (u8 *)rtsx_alloc_dma_buf(chip, 512, GFP_KERNEL);
+		if (!buf)
+			return;
+
+		rtsx_init_cmd(chip);
+
+		trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_CLK_EN, SD_CLK_EN, SD_CLK_EN);
+		if (chip->asic_code) {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0xAA);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL,
+					FPGA_SD_PULL_CTL_BIT, 0);
+		}
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, 1);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, 0);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_CFG1, 0x03, SD_BUS_WIDTH_4);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, SD_TRANSFER, 0xFF,
+			SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END);
+
+		rtsx_send_cmd_no_wait(chip);
+
+		retval = rtsx_transfer_data(chip, SD_CARD, buf, 512, 0, DMA_TO_DEVICE, 100);
+		if (retval < 0) {
+			u8 val;
+
+			rtsx_read_register(chip, SD_STAT1, &val);
+			RTSX_DEBUGP("SD_STAT1: 0x%x\n", val);
+
+			rtsx_read_register(chip, SD_STAT2, &val);
+			RTSX_DEBUGP("SD_STAT2: 0x%x\n", val);
+
+			rtsx_read_register(chip, SD_BUS_STAT, &val);
+			RTSX_DEBUGP("SD_BUS_STAT: 0x%x\n", val);
+
+			rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR, SD_STOP | SD_CLR_ERR);
+		}
+
+		rtsx_free_dma_buf(chip, buf);
+
+		if (chip->asic_code) {
+			rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF, 0x55);
+		} else {
+			rtsx_write_register(chip, FPGA_PULL_CTL,
+						FPGA_SD_PULL_CTL_BIT, FPGA_SD_PULL_CTL_BIT);
+		}
+		rtsx_write_register(chip, CARD_SELECT, 0x07, XD_MOD_SEL);
+		rtsx_write_register(chip, CARD_CLK_EN, SD_CLK_EN, 0);
+	}
+}
+
+static int reset_xd(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval, i, j;
+	u8 *ptr, id_buf[4], redunt[11];
+
+	retval = select_card(chip, XD_CARD);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF, XD_PGSTS_NOT_FF);
+	if (chip->asic_code) {
+		if (!CHECK_PID(chip, 0x5288))
+			xd_fill_pull_ctl_disable(chip);
+		else
+			xd_fill_pull_ctl_stage1_barossa(chip);
+	} else {
+		rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
+			(FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) | 0x20);
+	}
+
+	if (!chip->ft2_fast_mode)
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT, XD_NO_AUTO_PWR_OFF, 0);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	if (!chip->ft2_fast_mode) {
+		retval = card_power_off(chip, XD_CARD);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		wait_timeout(250);
+
+		if (CHECK_PID(chip, 0x5209))
+			RTSX_WRITE_REG(chip, CARD_PULL_CTL1, 0xFF, 0xAA);
+
+		rtsx_init_cmd(chip);
+
+		if (chip->asic_code) {
+			xd_fill_pull_ctl_enable(chip);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
+				(FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | 0x20);
+		}
+
+		retval = rtsx_send_cmd(chip, XD_CARD, 100);
+		if (retval < 0)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		retval = card_power_on(chip, XD_CARD);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+#ifdef SUPPORT_OCP
+		wait_timeout(50);
+		if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+			RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+#endif
+	}
+
+	rtsx_init_cmd(chip);
+
+	if (chip->ft2_fast_mode) {
+		if (chip->asic_code) {
+			xd_fill_pull_ctl_enable(chip);
+		} else {
+			rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
+				(FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN2) | 0x20);
+		}
+	}
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, XD_OUTPUT_EN);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	if (!chip->ft2_fast_mode)
+		wait_timeout(200);
+
+	retval = xd_set_init_para(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	/* Read ID to check if the timing setting is right */
+	for (i = 0; i < 4; i++) {
+		rtsx_init_cmd(chip);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
+				XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
+				XD_TIME_SETUP_STEP * 3 + XD_TIME_RW_STEP * (4 + i) + XD_TIME_RWN_STEP * (3 + i));
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_RESET);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+		rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
+		rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
+
+		retval = rtsx_send_cmd(chip, XD_CARD, 100);
+		if (retval < 0)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		ptr = rtsx_get_cmd_data(chip) + 1;
+
+		RTSX_DEBUGP("XD_DAT: 0x%x, XD_CTL: 0x%x\n", ptr[0], ptr[1]);
+
+		if (((ptr[0] & READY_FLAG) != READY_STATE) || !(ptr[1] & XD_RDY))
+			continue;
+
+		retval = xd_read_id(chip, READ_ID, id_buf, 4);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		RTSX_DEBUGP("READ_ID: 0x%x 0x%x 0x%x 0x%x\n",
+					id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
+
+		xd_card->device_code = id_buf[1];
+
+		/* Check if the xD card is supported */
+		switch (xd_card->device_code) {
+		case XD_4M_X8_512_1:
+		case XD_4M_X8_512_2:
+			xd_card->block_shift = 4;
+			xd_card->page_off = 0x0F;
+			xd_card->addr_cycle = 3;
+			xd_card->zone_cnt = 1;
+			xd_card->capacity = 8000;
+			XD_SET_4MB(xd_card);
+			break;
+		case XD_8M_X8_512:
+			xd_card->block_shift = 4;
+			xd_card->page_off = 0x0F;
+			xd_card->addr_cycle = 3;
+			xd_card->zone_cnt = 1;
+			xd_card->capacity = 16000;
+			break;
+		case XD_16M_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 3;
+			xd_card->zone_cnt = 1;
+			xd_card->capacity = 32000;
+			break;
+		case XD_32M_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 3;
+			xd_card->zone_cnt = 2;
+			xd_card->capacity = 64000;
+			break;
+		case XD_64M_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 4;
+			xd_card->zone_cnt = 4;
+			xd_card->capacity = 128000;
+			break;
+		case XD_128M_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 4;
+			xd_card->zone_cnt = 8;
+			xd_card->capacity = 256000;
+			break;
+		case XD_256M_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 4;
+			xd_card->zone_cnt = 16;
+			xd_card->capacity = 512000;
+			break;
+		case XD_512M_X8:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 4;
+			xd_card->zone_cnt = 32;
+			xd_card->capacity = 1024000;
+			break;
+		case xD_1G_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 4;
+			xd_card->zone_cnt = 64;
+			xd_card->capacity = 2048000;
+			break;
+		case xD_2G_X8_512:
+			XD_PAGE_512(xd_card);
+			xd_card->addr_cycle = 4;
+			xd_card->zone_cnt = 128;
+			xd_card->capacity = 4096000;
+			break;
+		default:
+			continue;
+		}
+
+		/* Confirm timing setting */
+		for (j = 0; j < 10; j++) {
+			retval = xd_read_id(chip, READ_ID, id_buf, 4);
+			if (retval != STATUS_SUCCESS)
+				TRACE_RET(chip, STATUS_FAIL);
+
+			if (id_buf[1] != xd_card->device_code)
+				break;
+		}
+
+		if (j == 10)
+			break;
+	}
+
+	if (i == 4) {
+		xd_card->block_shift = 0;
+		xd_card->page_off = 0;
+		xd_card->addr_cycle = 0;
+		xd_card->capacity = 0;
+
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	retval = xd_read_id(chip, READ_xD_ID, id_buf, 4);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+	RTSX_DEBUGP("READ_xD_ID: 0x%x 0x%x 0x%x 0x%x\n",
+			id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
+	if (id_buf[2] != XD_ID_CODE)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	/* Search CIS block */
+	for (i = 0; i < 24; i++) {
+		u32 page_addr;
+
+		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		page_addr = (u32)i << xd_card->block_shift;
+
+		for (j = 0; j < 3; j++) {
+			retval = xd_read_redundant(chip, page_addr, redunt, 11);
+			if (retval == STATUS_SUCCESS)
+				break;
+		}
+		if (j == 3)
+			continue;
+
+		if (redunt[BLOCK_STATUS] != XD_GBLK)
+			continue;
+
+		j = 0;
+		if (redunt[PAGE_STATUS] != XD_GPG) {
+			for (j = 1; j <= 8; j++) {
+				retval = xd_read_redundant(chip, page_addr + j, redunt, 11);
+				if (retval == STATUS_SUCCESS) {
+					if (redunt[PAGE_STATUS] == XD_GPG)
+						break;
+				}
+			}
+
+			if (j == 9)
+				break;
+		}
+
+		/* Check CIS data */
+		if ((redunt[BLOCK_STATUS] == XD_GBLK) && (redunt[PARITY] & XD_BA1_ALL0)) {
+			u8 buf[10];
+
+			page_addr += j;
+
+			retval = xd_read_cis(chip, page_addr, buf, 10);
+			if (retval != STATUS_SUCCESS)
+				TRACE_RET(chip, STATUS_FAIL);
+
+			if ((buf[0] == 0x01) && (buf[1] == 0x03) && (buf[2] == 0xD9)
+					&& (buf[3] == 0x01) && (buf[4] == 0xFF)
+					&& (buf[5] == 0x18) && (buf[6] == 0x02)
+					&& (buf[7] == 0xDF) && (buf[8] == 0x01)
+					&& (buf[9] == 0x20)) {
+				xd_card->cis_block = (u16)i;
+			}
+		}
+
+		break;
+	}
+
+	RTSX_DEBUGP("CIS block: 0x%x\n", xd_card->cis_block);
+	if (xd_card->cis_block == 0xFFFF)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity;
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_check_data_blank(u8 *redunt)
+{
+	int i;
+
+	for (i = 0; i < 6; i++) {
+		if (redunt[PAGE_STATUS + i] != 0xFF)
+			return 0;
+	}
+
+	if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1)) != (XD_ECC1_ALL1 | XD_ECC2_ALL1))
+		return 0;
+
+
+	for (i = 0; i < 4; i++) {
+		if (redunt[RESERVED0 + i] != 0xFF)
+			return 0;
+	}
+
+	return 1;
+}
+
+static u16 xd_load_log_block_addr(u8 *redunt)
+{
+	u16 addr = 0xFFFF;
+
+	if (redunt[PARITY] & XD_BA1_BA2_EQL)
+		addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L];
+	else if (redunt[PARITY] & XD_BA1_VALID)
+		addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) | redunt[BLOCK_ADDR1_L];
+	else if (redunt[PARITY] & XD_BA2_VALID)
+		addr = ((u16)redunt[BLOCK_ADDR2_H] << 8) | redunt[BLOCK_ADDR2_L];
+
+	return addr;
+}
+
+static int xd_init_l2p_tbl(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int size, i;
+
+	RTSX_DEBUGP("xd_init_l2p_tbl: zone_cnt = %d\n", xd_card->zone_cnt);
+
+	if (xd_card->zone_cnt < 1)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	size = xd_card->zone_cnt * sizeof(struct zone_entry);
+	RTSX_DEBUGP("Buffer size for l2p table is %d\n", size);
+
+	xd_card->zone = (struct zone_entry *)vmalloc(size);
+	if (!xd_card->zone)
+		TRACE_RET(chip, STATUS_ERROR);
+
+	for (i = 0; i < xd_card->zone_cnt; i++) {
+		xd_card->zone[i].build_flag = 0;
+		xd_card->zone[i].l2p_table = NULL;
+		xd_card->zone[i].free_table = NULL;
+		xd_card->zone[i].get_index = 0;
+		xd_card->zone[i].set_index = 0;
+		xd_card->zone[i].unused_blk_cnt = 0;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static inline void free_zone(struct zone_entry *zone)
+{
+	RTSX_DEBUGP("free_zone\n");
+
+	if (!zone)
+		return;
+
+	zone->build_flag = 0;
+	zone->set_index = 0;
+	zone->get_index = 0;
+	zone->unused_blk_cnt = 0;
+	if (zone->l2p_table) {
+		vfree(zone->l2p_table);
+		zone->l2p_table = NULL;
+	}
+	if (zone->free_table) {
+		vfree(zone->free_table);
+		zone->free_table = NULL;
+	}
+}
+
+static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct zone_entry *zone;
+	int zone_no;
+
+	zone_no = (int)phy_blk >> 10;
+	if (zone_no >= xd_card->zone_cnt) {
+		RTSX_DEBUGP("Set unused block to invalid zone (zone_no = %d, zone_cnt = %d)\n",
+			zone_no, xd_card->zone_cnt);
+		return;
+	}
+	zone = &(xd_card->zone[zone_no]);
+
+	if (zone->free_table == NULL) {
+		if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS)
+			return;
+	}
+
+	if ((zone->set_index >= XD_FREE_TABLE_CNT)
+			|| (zone->set_index < 0)) {
+		free_zone(zone);
+		RTSX_DEBUGP("Set unused block fail, invalid set_index\n");
+		return;
+	}
+
+	RTSX_DEBUGP("Set unused block to index %d\n", zone->set_index);
+
+	zone->free_table[zone->set_index++] = (u16) (phy_blk & 0x3ff);
+	if (zone->set_index >= XD_FREE_TABLE_CNT)
+		zone->set_index = 0;
+	zone->unused_blk_cnt++;
+}
+
+static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct zone_entry *zone;
+	u32 phy_blk;
+
+	if (zone_no >= xd_card->zone_cnt) {
+		RTSX_DEBUGP("Get unused block from invalid zone (zone_no = %d, zone_cnt = %d)\n",
+			zone_no, xd_card->zone_cnt);
+		return BLK_NOT_FOUND;
+	}
+	zone = &(xd_card->zone[zone_no]);
+
+	if ((zone->unused_blk_cnt == 0) || (zone->set_index == zone->get_index)) {
+		free_zone(zone);
+		RTSX_DEBUGP("Get unused block fail, no unused block available\n");
+		return BLK_NOT_FOUND;
+	}
+	if ((zone->get_index >= XD_FREE_TABLE_CNT) || (zone->get_index < 0)) {
+		free_zone(zone);
+		RTSX_DEBUGP("Get unused block fail, invalid get_index\n");
+		return BLK_NOT_FOUND;
+	}
+
+	RTSX_DEBUGP("Get unused block from index %d\n", zone->get_index);
+
+	phy_blk = zone->free_table[zone->get_index];
+	zone->free_table[zone->get_index++] = 0xFFFF;
+	if (zone->get_index >= XD_FREE_TABLE_CNT)
+		zone->get_index = 0;
+	zone->unused_blk_cnt--;
+
+	phy_blk += ((u32)(zone_no) << 10);
+	return phy_blk;
+}
+
+static void xd_set_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off, u16 phy_off)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct zone_entry *zone;
+
+	zone = &(xd_card->zone[zone_no]);
+	zone->l2p_table[log_off] = phy_off;
+}
+
+static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct zone_entry *zone;
+	int retval;
+
+	zone = &(xd_card->zone[zone_no]);
+	if (zone->l2p_table[log_off] == 0xFFFF) {
+		u32 phy_blk = 0;
+		int i;
+
+#ifdef XD_DELAY_WRITE
+		retval = xd_delay_write(chip);
+		if (retval != STATUS_SUCCESS) {
+			RTSX_DEBUGP("In xd_get_l2p_tbl, delay write fail!\n");
+			return BLK_NOT_FOUND;
+		}
+#endif
+
+		if (zone->unused_blk_cnt <= 0) {
+			RTSX_DEBUGP("No unused block!\n");
+			return BLK_NOT_FOUND;
+		}
+
+		for (i = 0; i < zone->unused_blk_cnt; i++) {
+			phy_blk = xd_get_unused_block(chip, zone_no);
+			if (phy_blk == BLK_NOT_FOUND) {
+				RTSX_DEBUGP("No unused block available!\n");
+				return BLK_NOT_FOUND;
+			}
+
+			retval = xd_init_page(chip, phy_blk, log_off, 0, xd_card->page_off + 1);
+			if (retval == STATUS_SUCCESS)
+				break;
+		}
+		if (i >= zone->unused_blk_cnt) {
+			RTSX_DEBUGP("No good unused block available!\n");
+			return BLK_NOT_FOUND;
+		}
+
+		xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(phy_blk & 0x3FF));
+		return phy_blk;
+	}
+
+	return (u32)zone->l2p_table[log_off] + ((u32)(zone_no) << 10);
+}
+
+int reset_xd_card(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval;
+
+	memset(xd_card, 0, sizeof(struct xd_info));
+
+	xd_card->block_shift = 0;
+	xd_card->page_off = 0;
+	xd_card->addr_cycle = 0;
+	xd_card->capacity = 0;
+	xd_card->zone_cnt = 0;
+	xd_card->cis_block = 0xFFFF;
+	xd_card->delay_write.delay_write_flag = 0;
+
+	retval = enable_card_clock(chip, XD_CARD);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = reset_xd(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	retval = xd_init_l2p_tbl(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval;
+	u32 page_addr;
+	u8 reg = 0;
+
+	RTSX_DEBUGP("mark block 0x%x as bad block\n", phy_blk);
+
+	if (phy_blk == BLK_NOT_FOUND)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_LATER_BBLK);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF);
+
+	page_addr = phy_blk << xd_card->block_shift;
+
+	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, xd_card->page_off + 1);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 500);
+	if (retval < 0) {
+		rtsx_clear_xd_error(chip);
+		rtsx_read_register(chip, XD_DAT, &reg);
+		if (reg & PROGRAM_ERROR)
+			xd_set_err_code(chip, XD_PRG_ERROR);
+		else
+			xd_set_err_code(chip, XD_TO_ERROR);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff, u8 start_page, u8 end_page)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval;
+	u32 page_addr;
+	u8 reg = 0;
+
+	RTSX_DEBUGP("Init block 0x%x\n", phy_blk);
+
+	if (start_page > end_page)
+		TRACE_RET(chip, STATUS_FAIL);
+	if (phy_blk == BLK_NOT_FOUND)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, (u8)(logoff >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff);
+
+	page_addr = (phy_blk << xd_card->block_shift) + start_page;
+
+	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, XD_BA_TRANSFORM);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, (end_page - start_page));
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 500);
+	if (retval < 0) {
+		rtsx_clear_xd_error(chip);
+		rtsx_read_register(chip, XD_DAT, &reg);
+		if (reg & PROGRAM_ERROR) {
+			xd_mark_bad_block(chip, phy_blk);
+			xd_set_err_code(chip, XD_PRG_ERROR);
+		} else {
+			xd_set_err_code(chip, XD_TO_ERROR);
+		}
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u8 start_page, u8 end_page)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	u32 old_page, new_page;
+	u8 i, reg = 0;
+	int retval;
+
+	RTSX_DEBUGP("Copy page from block 0x%x to block 0x%x\n", old_blk, new_blk);
+
+	if (start_page > end_page)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND))
+		TRACE_RET(chip, STATUS_FAIL);
+
+	old_page = (old_blk << xd_card->block_shift) + start_page;
+	new_page = (new_blk << xd_card->block_shift) + start_page;
+
+	XD_CLR_BAD_NEWBLK(xd_card);
+
+	RTSX_WRITE_REG(chip, CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
+
+	for (i = start_page; i < end_page; i++) {
+		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+			rtsx_clear_xd_error(chip);
+			xd_set_err_code(chip, XD_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		rtsx_init_cmd(chip);
+
+		xd_assign_phy_addr(chip, old_page, XD_RW_ADDR);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS, 0);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_PAGES);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+		retval = rtsx_send_cmd(chip, XD_CARD, 500);
+		if (retval < 0) {
+			rtsx_clear_xd_error(chip);
+			reg = 0;
+			rtsx_read_register(chip, XD_CTL, &reg);
+			if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
+				wait_timeout(100);
+
+				if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+					xd_set_err_code(chip, XD_NO_CARD);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+
+				if (((reg & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ==
+						(XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
+					|| ((reg & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) ==
+						(XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
+					rtsx_write_register(chip, XD_PAGE_STATUS, 0xFF, XD_BPG);
+					rtsx_write_register(chip, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
+					XD_SET_BAD_OLDBLK(xd_card);
+					RTSX_DEBUGP("old block 0x%x ecc error\n", old_blk);
+				}
+			} else {
+				xd_set_err_code(chip, XD_TO_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		if (XD_CHK_BAD_OLDBLK(xd_card))
+			rtsx_clear_xd_error(chip);
+
+		rtsx_init_cmd(chip);
+
+		xd_assign_phy_addr(chip, new_page, XD_RW_ADDR);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
+			     XD_TRANSFER_START | XD_WRITE_PAGES);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+		retval = rtsx_send_cmd(chip, XD_CARD, 300);
+		if (retval < 0) {
+			rtsx_clear_xd_error(chip);
+			reg = 0;
+			rtsx_read_register(chip, XD_DAT, &reg);
+			if (reg & PROGRAM_ERROR) {
+				xd_mark_bad_block(chip, new_blk);
+				xd_set_err_code(chip, XD_PRG_ERROR);
+				XD_SET_BAD_NEWBLK(xd_card);
+			} else {
+				xd_set_err_code(chip, XD_TO_ERROR);
+			}
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		old_page++;
+		new_page++;
+	}
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_reset_cmd(struct rtsx_chip *chip)
+{
+	int retval;
+	u8 *ptr;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_RESET);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+	rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
+	rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 100);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	ptr = rtsx_get_cmd_data(chip) + 1;
+	if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY))
+		return STATUS_SUCCESS;
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	u32 page_addr;
+	u8 reg = 0, *ptr;
+	int i, retval;
+
+	if (phy_blk == BLK_NOT_FOUND)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	page_addr = phy_blk << xd_card->block_shift;
+
+	for (i = 0; i < 3; i++) {
+		rtsx_init_cmd(chip);
+
+		xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR);
+
+		rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_ERASE);
+		rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+		rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
+
+		retval = rtsx_send_cmd(chip, XD_CARD, 250);
+		if (retval < 0) {
+			rtsx_clear_xd_error(chip);
+			rtsx_read_register(chip, XD_DAT, &reg);
+			if (reg & PROGRAM_ERROR) {
+				xd_mark_bad_block(chip, phy_blk);
+				xd_set_err_code(chip, XD_PRG_ERROR);
+				TRACE_RET(chip, STATUS_FAIL);
+			} else {
+				xd_set_err_code(chip, XD_ERASE_FAIL);
+			}
+			retval = xd_reset_cmd(chip);
+			if (retval != STATUS_SUCCESS)
+				TRACE_RET(chip, STATUS_FAIL);
+			continue;
+		}
+
+		ptr = rtsx_get_cmd_data(chip) + 1;
+		if (*ptr & PROGRAM_ERROR) {
+			xd_mark_bad_block(chip, phy_blk);
+			xd_set_err_code(chip, XD_PRG_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		return STATUS_SUCCESS;
+	}
+
+	xd_mark_bad_block(chip, phy_blk);
+	xd_set_err_code(chip, XD_ERASE_FAIL);
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+
+static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct zone_entry *zone;
+	int retval;
+	u32 start, end, i;
+	u16 max_logoff, cur_fst_page_logoff, cur_lst_page_logoff, ent_lst_page_logoff;
+	u8 redunt[11];
+
+	RTSX_DEBUGP("xd_build_l2p_tbl: %d\n", zone_no);
+
+	if (xd_card->zone == NULL) {
+		retval = xd_init_l2p_tbl(chip);
+		if (retval != STATUS_SUCCESS)
+			return retval;
+	}
+
+	if (xd_card->zone[zone_no].build_flag) {
+		RTSX_DEBUGP("l2p table of zone %d has been built\n", zone_no);
+		return STATUS_SUCCESS;
+	}
+
+	zone = &(xd_card->zone[zone_no]);
+
+	if (zone->l2p_table == NULL) {
+		zone->l2p_table = (u16 *)vmalloc(2000);
+		if (zone->l2p_table == NULL)
+			TRACE_GOTO(chip, Build_Fail);
+	}
+	memset((u8 *)(zone->l2p_table), 0xff, 2000);
+
+	if (zone->free_table == NULL) {
+		zone->free_table = (u16 *)vmalloc(XD_FREE_TABLE_CNT * 2);
+		if (zone->free_table == NULL)
+			TRACE_GOTO(chip, Build_Fail);
+	}
+	memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2);
+
+	if (zone_no == 0) {
+		if (xd_card->cis_block == 0xFFFF)
+			start = 0;
+		else
+			start = xd_card->cis_block + 1;
+		if (XD_CHK_4MB(xd_card)) {
+			end = 0x200;
+			max_logoff = 499;
+		} else {
+			end = 0x400;
+			max_logoff = 999;
+		}
+	} else {
+		start = (u32)(zone_no) << 10;
+		end = (u32)(zone_no + 1) << 10;
+		max_logoff = 999;
+	}
+
+	RTSX_DEBUGP("start block 0x%x, end block 0x%x\n", start, end);
+
+	zone->set_index = zone->get_index = 0;
+	zone->unused_blk_cnt = 0;
+
+	for (i = start; i < end; i++) {
+		u32 page_addr = i << xd_card->block_shift;
+		u32 phy_block;
+
+		retval = xd_read_redundant(chip, page_addr, redunt, 11);
+		if (retval != STATUS_SUCCESS)
+			continue;
+
+		if (redunt[BLOCK_STATUS] != 0xFF) {
+			RTSX_DEBUGP("bad block\n");
+			continue;
+		}
+
+		if (xd_check_data_blank(redunt)) {
+			RTSX_DEBUGP("blank block\n");
+			xd_set_unused_block(chip, i);
+			continue;
+		}
+
+		cur_fst_page_logoff = xd_load_log_block_addr(redunt);
+		if ((cur_fst_page_logoff == 0xFFFF) || (cur_fst_page_logoff > max_logoff)) {
+			retval = xd_erase_block(chip, i);
+			if (retval == STATUS_SUCCESS)
+				xd_set_unused_block(chip, i);
+			continue;
+		}
+
+		if ((zone_no == 0) && (cur_fst_page_logoff == 0) && (redunt[PAGE_STATUS] != XD_GPG))
+			XD_SET_MBR_FAIL(xd_card);
+
+		if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) {
+			zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
+			continue;
+		}
+
+		phy_block = zone->l2p_table[cur_fst_page_logoff] + ((u32)((zone_no) << 10));
+
+		page_addr = ((i + 1) << xd_card->block_shift) - 1;
+
+		retval = xd_read_redundant(chip, page_addr, redunt, 11);
+		if (retval != STATUS_SUCCESS)
+			continue;
+
+		cur_lst_page_logoff = xd_load_log_block_addr(redunt);
+		if (cur_lst_page_logoff == cur_fst_page_logoff) {
+			int m;
+
+			page_addr = ((phy_block + 1) << xd_card->block_shift) - 1;
+
+			for (m = 0; m < 3; m++) {
+				retval = xd_read_redundant(chip, page_addr, redunt, 11);
+				if (retval == STATUS_SUCCESS)
+					break;
+			}
+
+			if (m == 3) {
+				zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
+				retval = xd_erase_block(chip, phy_block);
+				if (retval == STATUS_SUCCESS)
+					xd_set_unused_block(chip, phy_block);
+				continue;
+			}
+
+			ent_lst_page_logoff = xd_load_log_block_addr(redunt);
+			if (ent_lst_page_logoff != cur_fst_page_logoff) {
+				zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
+				retval = xd_erase_block(chip, phy_block);
+				if (retval == STATUS_SUCCESS)
+					xd_set_unused_block(chip, phy_block);
+				continue;
+			} else {
+				retval = xd_erase_block(chip, i);
+				if (retval == STATUS_SUCCESS)
+					xd_set_unused_block(chip, i);
+			}
+		} else {
+			retval = xd_erase_block(chip, i);
+			if (retval == STATUS_SUCCESS)
+				xd_set_unused_block(chip, i);
+		}
+	}
+
+	if (XD_CHK_4MB(xd_card))
+		end = 500;
+	else
+		end = 1000;
+
+	i = 0;
+	for (start = 0; start < end; start++) {
+		if (zone->l2p_table[start] == 0xFFFF)
+			i++;
+	}
+
+	RTSX_DEBUGP("Block count %d, invalid L2P entry %d\n", end, i);
+	RTSX_DEBUGP("Total unused block: %d\n", zone->unused_blk_cnt);
+
+	if ((zone->unused_blk_cnt - i) < 1)
+		chip->card_wp |= XD_CARD;
+
+	zone->build_flag = 1;
+
+	return STATUS_SUCCESS;
+
+Build_Fail:
+	if (zone->l2p_table) {
+		vfree(zone->l2p_table);
+		zone->l2p_table = NULL;
+	}
+	if (zone->free_table) {
+		vfree(zone->free_table);
+		zone->free_table = NULL;
+	}
+
+	return STATUS_FAIL;
+}
+
+static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd)
+{
+	int retval;
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_SET_CMD);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	retval = rtsx_send_cmd(chip, XD_CARD, 200);
+	if (retval < 0)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk, u32 log_blk,
+		u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	u32 page_addr, new_blk;
+	u16 log_off;
+	u8 reg_val, page_cnt;
+	int zone_no, retval, i;
+
+	if (start_page > end_page)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	page_cnt = end_page - start_page;
+	zone_no = (int)(log_blk / 1000);
+	log_off = (u16)(log_blk % 1000);
+
+	if ((phy_blk & 0x3FF) == 0x3FF) {
+		for (i = 0; i < 256; i++) {
+			page_addr = ((u32)i) << xd_card->block_shift;
+
+			retval = xd_read_redundant(chip, page_addr, NULL, 0);
+			if (retval == STATUS_SUCCESS)
+				break;
+
+			if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+				xd_set_err_code(chip, XD_NO_CARD);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+	}
+
+	page_addr = (phy_blk << xd_card->block_shift) + start_page;
+
+	rtsx_init_cmd(chip);
+
+	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, XD_PPB_TO_SIE);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
+			XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
+
+	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, DMA_512);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_READ_PAGES);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
+		     XD_TRANSFER_END | XD_PPB_EMPTY, XD_TRANSFER_END | XD_PPB_EMPTY);
+
+	rtsx_send_cmd_no_wait(chip);
+
+	retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, scsi_sg_count(chip->srb),
+			index, offset, DMA_FROM_DEVICE, chip->xd_timeout);
+	if (retval < 0) {
+		rtsx_clear_xd_error(chip);
+		xd_clear_dma_buffer(chip);
+
+		if (retval == -ETIMEDOUT) {
+			xd_set_err_code(chip, XD_TO_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		} else {
+			TRACE_GOTO(chip, Fail);
+		}
+	}
+
+	return STATUS_SUCCESS;
+
+Fail:
+	RTSX_READ_REG(chip, XD_PAGE_STATUS, &reg_val);
+
+	if (reg_val !=  XD_GPG)
+		xd_set_err_code(chip, XD_PRG_ERROR);
+
+	RTSX_READ_REG(chip, XD_CTL, &reg_val);
+
+	if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
+				== (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE))
+		|| ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))
+			== (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
+		wait_timeout(100);
+
+		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+			xd_set_err_code(chip, XD_NO_CARD);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		xd_set_err_code(chip, XD_ECC_ERROR);
+
+		new_blk = xd_get_unused_block(chip, zone_no);
+		if (new_blk == NO_NEW_BLK) {
+			XD_CLR_BAD_OLDBLK(xd_card);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = xd_copy_page(chip, phy_blk, new_blk, 0, xd_card->page_off + 1);
+		if (retval != STATUS_SUCCESS) {
+			if (!XD_CHK_BAD_NEWBLK(xd_card)) {
+				retval = xd_erase_block(chip, new_blk);
+				if (retval == STATUS_SUCCESS)
+					xd_set_unused_block(chip, new_blk);
+			} else {
+				XD_CLR_BAD_NEWBLK(xd_card);
+			}
+			XD_CLR_BAD_OLDBLK(xd_card);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+		xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
+		xd_erase_block(chip, phy_blk);
+		xd_mark_bad_block(chip, phy_blk);
+		XD_CLR_BAD_OLDBLK(xd_card);
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+static int xd_finish_write(struct rtsx_chip *chip,
+		u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval, zone_no;
+	u16 log_off;
+
+	RTSX_DEBUGP("xd_finish_write, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
+				old_blk, new_blk, log_blk);
+
+	if (page_off > xd_card->page_off)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	zone_no = (int)(log_blk / 1000);
+	log_off = (u16)(log_blk % 1000);
+
+	if (old_blk == BLK_NOT_FOUND) {
+		retval = xd_init_page(chip, new_blk, log_off,
+				page_off, xd_card->page_off + 1);
+		if (retval != STATUS_SUCCESS) {
+			retval = xd_erase_block(chip, new_blk);
+			if (retval == STATUS_SUCCESS)
+				xd_set_unused_block(chip, new_blk);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	} else {
+		retval = xd_copy_page(chip, old_blk, new_blk,
+				page_off, xd_card->page_off + 1);
+		if (retval != STATUS_SUCCESS) {
+			if (!XD_CHK_BAD_NEWBLK(xd_card)) {
+				retval = xd_erase_block(chip, new_blk);
+				if (retval == STATUS_SUCCESS)
+					xd_set_unused_block(chip, new_blk);
+			}
+			XD_CLR_BAD_NEWBLK(xd_card);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = xd_erase_block(chip, old_blk);
+		if (retval == STATUS_SUCCESS) {
+			if (XD_CHK_BAD_OLDBLK(xd_card)) {
+				xd_mark_bad_block(chip, old_blk);
+				XD_CLR_BAD_OLDBLK(xd_card);
+			} else {
+				xd_set_unused_block(chip, old_blk);
+			}
+		} else {
+			xd_set_err_code(chip, XD_NO_ERROR);
+			XD_CLR_BAD_OLDBLK(xd_card);
+		}
+	}
+
+	xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
+
+	return STATUS_SUCCESS;
+}
+
+static int xd_prepare_write(struct rtsx_chip *chip,
+		u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
+{
+	int retval;
+
+	RTSX_DEBUGP("%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x, page_off = %d\n",
+				__func__, old_blk, new_blk, log_blk, (int)page_off);
+
+	if (page_off) {
+		retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+
+static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk, u32 new_blk, u32 log_blk,
+		u8 start_page, u8 end_page, u8 *buf, unsigned int *index, unsigned int *offset)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	u32 page_addr;
+	int zone_no, retval;
+	u16 log_off;
+	u8 page_cnt, reg_val;
+
+	RTSX_DEBUGP("%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
+				__func__, old_blk, new_blk, log_blk);
+
+	if (start_page > end_page)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	page_cnt = end_page - start_page;
+	zone_no = (int)(log_blk / 1000);
+	log_off = (u16)(log_blk % 1000);
+
+	page_addr = (new_blk << xd_card->block_shift) + start_page;
+
+	retval = xd_send_cmd(chip, READ1_1);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	rtsx_init_cmd(chip);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, (u8)(log_off >> 8));
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
+
+	xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM, XD_BA_TRANSFORM);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
+	rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
+
+	trans_dma_enable(chip->srb->sc_data_direction, chip, page_cnt * 512, DMA_512);
+
+	rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES);
+	rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END, XD_TRANSFER_END);
+
+	rtsx_send_cmd_no_wait(chip);
+
+	retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512, scsi_sg_count(chip->srb),
+			index, offset, DMA_TO_DEVICE, chip->xd_timeout);
+	if (retval < 0) {
+		rtsx_clear_xd_error(chip);
+
+		if (retval == -ETIMEDOUT) {
+			xd_set_err_code(chip, XD_TO_ERROR);
+			TRACE_RET(chip, STATUS_FAIL);
+		} else {
+			TRACE_GOTO(chip, Fail);
+		}
+	}
+
+	if (end_page == (xd_card->page_off + 1)) {
+		xd_card->delay_write.delay_write_flag = 0;
+
+		if (old_blk != BLK_NOT_FOUND) {
+			retval = xd_erase_block(chip, old_blk);
+			if (retval == STATUS_SUCCESS) {
+				if (XD_CHK_BAD_OLDBLK(xd_card)) {
+					xd_mark_bad_block(chip, old_blk);
+					XD_CLR_BAD_OLDBLK(xd_card);
+				} else {
+					xd_set_unused_block(chip, old_blk);
+				}
+			} else {
+				xd_set_err_code(chip, XD_NO_ERROR);
+				XD_CLR_BAD_OLDBLK(xd_card);
+			}
+		}
+		xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
+	}
+
+	return STATUS_SUCCESS;
+
+Fail:
+	RTSX_READ_REG(chip, XD_DAT, &reg_val);
+	if (reg_val & PROGRAM_ERROR) {
+		xd_set_err_code(chip, XD_PRG_ERROR);
+		xd_mark_bad_block(chip, new_blk);
+	}
+
+	TRACE_RET(chip, STATUS_FAIL);
+}
+
+#ifdef XD_DELAY_WRITE
+int xd_delay_write(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
+	int retval;
+
+	if (delay_write->delay_write_flag) {
+		RTSX_DEBUGP("xd_delay_write\n");
+		retval = xd_switch_clock(chip);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		delay_write->delay_write_flag = 0;
+		retval = xd_finish_write(chip,
+				delay_write->old_phyblock, delay_write->new_phyblock,
+				delay_write->logblock, delay_write->pageoff);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	return STATUS_SUCCESS;
+}
+#endif
+
+int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	unsigned int lun = SCSI_LUN(srb);
+#ifdef XD_DELAY_WRITE
+	struct xd_delay_write_tag *delay_write = &(xd_card->delay_write);
+#endif
+	int retval, zone_no;
+	unsigned int index = 0, offset = 0;
+	u32 log_blk, old_blk = 0, new_blk = 0;
+	u16 log_off, total_sec_cnt = sector_cnt;
+	u8 start_page, end_page = 0, page_cnt;
+	u8 *ptr;
+
+	xd_set_err_code(chip, XD_NO_ERROR);
+
+	xd_card->cleanup_counter = 0;
+
+	RTSX_DEBUGP("xd_rw: scsi_sg_count = %d\n", scsi_sg_count(srb));
+
+	ptr = (u8 *)scsi_sglist(srb);
+
+	retval = xd_switch_clock(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+
+	if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+		chip->card_fail |= XD_CARD;
+		set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+		TRACE_RET(chip, STATUS_FAIL);
+	}
+
+	log_blk = start_sector >> xd_card->block_shift;
+	start_page = (u8)start_sector & xd_card->page_off;
+	zone_no = (int)(log_blk / 1000);
+	log_off = (u16)(log_blk % 1000);
+
+	if (xd_card->zone[zone_no].build_flag == 0) {
+		retval = xd_build_l2p_tbl(chip, zone_no);
+		if (retval != STATUS_SUCCESS) {
+			chip->card_fail |= XD_CARD;
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	if (srb->sc_data_direction == DMA_TO_DEVICE) {
+#ifdef XD_DELAY_WRITE
+		if (delay_write->delay_write_flag &&
+				(delay_write->logblock == log_blk) &&
+				(start_page > delay_write->pageoff)) {
+			delay_write->delay_write_flag = 0;
+			if (delay_write->old_phyblock != BLK_NOT_FOUND) {
+				retval = xd_copy_page(chip,
+					delay_write->old_phyblock,
+					delay_write->new_phyblock,
+					delay_write->pageoff, start_page);
+				if (retval != STATUS_SUCCESS) {
+					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+			}
+			old_blk = delay_write->old_phyblock;
+			new_blk = delay_write->new_phyblock;
+		} else if (delay_write->delay_write_flag &&
+				(delay_write->logblock == log_blk) &&
+				(start_page == delay_write->pageoff)) {
+			delay_write->delay_write_flag = 0;
+			old_blk = delay_write->old_phyblock;
+			new_blk = delay_write->new_phyblock;
+		} else {
+			retval = xd_delay_write(chip);
+			if (retval != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+#endif
+			old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
+			new_blk  = xd_get_unused_block(chip, zone_no);
+			if ((old_blk == BLK_NOT_FOUND) || (new_blk == BLK_NOT_FOUND)) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+
+			retval = xd_prepare_write(chip, old_blk, new_blk, log_blk, start_page);
+			if (retval != STATUS_SUCCESS) {
+				if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+					set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+					TRACE_RET(chip, STATUS_FAIL);
+				}
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+#ifdef XD_DELAY_WRITE
+		}
+#endif
+	} else {
+#ifdef XD_DELAY_WRITE
+		retval = xd_delay_write(chip);
+		if (retval != STATUS_SUCCESS) {
+			if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+#endif
+
+		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
+		if (old_blk == BLK_NOT_FOUND) {
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+	}
+
+	RTSX_DEBUGP("old_blk = 0x%x\n", old_blk);
+
+	while (total_sec_cnt) {
+		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+			chip->card_fail |= XD_CARD;
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if ((start_page + total_sec_cnt) > (xd_card->page_off + 1))
+			end_page = xd_card->page_off + 1;
+		else
+			end_page = start_page + (u8)total_sec_cnt;
+
+		page_cnt = end_page - start_page;
+		if (srb->sc_data_direction == DMA_FROM_DEVICE) {
+			retval = xd_read_multiple_pages(chip, old_blk, log_blk,
+					start_page, end_page, ptr, &index, &offset);
+			if (retval != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		} else {
+			retval = xd_write_multiple_pages(chip, old_blk, new_blk, log_blk,
+					start_page, end_page, ptr, &index, &offset);
+			if (retval != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		total_sec_cnt -= page_cnt;
+		if (scsi_sg_count(srb) == 0)
+			ptr += page_cnt * 512;
+
+		if (total_sec_cnt == 0)
+			break;
+
+		log_blk++;
+		zone_no = (int)(log_blk / 1000);
+		log_off = (u16)(log_blk % 1000);
+
+		if (xd_card->zone[zone_no].build_flag == 0) {
+			retval = xd_build_l2p_tbl(chip, zone_no);
+			if (retval != STATUS_SUCCESS) {
+				chip->card_fail |= XD_CARD;
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
+		if (old_blk == BLK_NOT_FOUND) {
+			if (srb->sc_data_direction == DMA_FROM_DEVICE)
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
+			else
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+			
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		if (srb->sc_data_direction == DMA_TO_DEVICE) {
+			new_blk = xd_get_unused_block(chip, zone_no);
+			if (new_blk == BLK_NOT_FOUND) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+		}
+
+		start_page = 0;
+	}
+
+	if ((srb->sc_data_direction == DMA_TO_DEVICE) &&
+			(end_page != (xd_card->page_off + 1))) {
+#ifdef XD_DELAY_WRITE
+		delay_write->delay_write_flag = 1;
+		delay_write->old_phyblock = old_blk;
+		delay_write->new_phyblock = new_blk;
+		delay_write->logblock = log_blk;
+		delay_write->pageoff = end_page;
+#else
+		if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+			chip->card_fail |= XD_CARD;
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+
+		retval = xd_finish_write(chip, old_blk, new_blk, log_blk, end_page);
+		if (retval != STATUS_SUCCESS) {
+			if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
+				set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
+				TRACE_RET(chip, STATUS_FAIL);
+			}
+			set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
+			TRACE_RET(chip, STATUS_FAIL);
+		}
+#endif
+	}
+
+	scsi_set_resid(srb, 0);
+
+	return STATUS_SUCCESS;
+}
+
+void xd_free_l2p_tbl(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int i = 0;
+
+	if (xd_card->zone != NULL) {
+		for (i = 0; i < xd_card->zone_cnt; i++) {
+			if (xd_card->zone[i].l2p_table != NULL) {
+				vfree(xd_card->zone[i].l2p_table);
+				xd_card->zone[i].l2p_table = NULL;
+			}
+			if (xd_card->zone[i].free_table != NULL) {
+				vfree(xd_card->zone[i].free_table);
+				xd_card->zone[i].free_table = NULL;
+			}
+		}
+		vfree(xd_card->zone);
+		xd_card->zone = NULL;
+	}
+}
+
+void xd_cleanup_work(struct rtsx_chip *chip)
+{
+#ifdef XD_DELAY_WRITE
+	struct xd_info *xd_card = &(chip->xd_card);
+
+	if (xd_card->delay_write.delay_write_flag) {
+		RTSX_DEBUGP("xD: delay write\n");
+		xd_delay_write(chip);
+		xd_card->cleanup_counter = 0;
+	}
+#endif
+}
+
+int xd_power_off_card3v3(struct rtsx_chip *chip)
+{
+	int retval;
+
+	retval = disable_card_clock(chip, XD_CARD);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	RTSX_WRITE_REG(chip, CARD_OE, XD_OUTPUT_EN, 0);
+
+	if (!chip->ft2_fast_mode) {
+		retval = card_power_off(chip, XD_CARD);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+
+		wait_timeout(50);
+	}
+
+	if (chip->asic_code) {
+		retval = xd_pull_ctl_disable(chip);
+		if (retval != STATUS_SUCCESS)
+			TRACE_RET(chip, STATUS_FAIL);
+	} else {
+		RTSX_WRITE_REG(chip, FPGA_PULL_CTL, 0xFF, 0xDF);
+	}
+
+	return STATUS_SUCCESS;
+}
+
+int release_xd_card(struct rtsx_chip *chip)
+{
+	struct xd_info *xd_card = &(chip->xd_card);
+	int retval;
+
+	RTSX_DEBUGP("release_xd_card\n");
+
+	chip->card_ready &= ~XD_CARD;
+	chip->card_fail &= ~XD_CARD;
+	chip->card_wp &= ~XD_CARD;
+
+	xd_card->delay_write.delay_write_flag = 0;
+
+	xd_free_l2p_tbl(chip);
+
+	retval = xd_power_off_card3v3(chip);
+	if (retval != STATUS_SUCCESS)
+		TRACE_RET(chip, STATUS_FAIL);
+
+	return STATUS_SUCCESS;
+}
diff --git a/drivers/staging/rts_pstor/xd.h b/drivers/staging/rts_pstor/xd.h
new file mode 100644
index 0000000..cd9fbc1
--- /dev/null
+++ b/drivers/staging/rts_pstor/xd.h
@@ -0,0 +1,188 @@
+/* Driver for Realtek PCI-Express card reader
+ * Header file
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#ifndef __REALTEK_RTSX_XD_H
+#define __REALTEK_RTSX_XD_H
+
+#define	XD_DELAY_WRITE
+
+/* Error Codes */
+#define	XD_NO_ERROR			0x00
+#define	XD_NO_MEMORY			0x80
+#define	XD_PRG_ERROR			0x40
+#define	XD_NO_CARD			0x20
+#define	XD_READ_FAIL			0x10
+#define	XD_ERASE_FAIL			0x08
+#define	XD_WRITE_FAIL			0x04
+#define	XD_ECC_ERROR			0x02
+#define	XD_TO_ERROR			0x01
+
+/* XD Commands */
+#define	READ1_1				0x00
+#define	READ1_2				0x01
+#define	READ2				0x50
+#define READ_ID				0x90
+#define RESET				0xff
+#define PAGE_PRG_1			0x80
+#define PAGE_PRG_2			0x10
+#define	BLK_ERASE_1			0x60
+#define	BLK_ERASE_2			0xD0
+#define READ_STS			0x70
+#define READ_xD_ID			0x9A
+#define	COPY_BACK_512			0x8A
+#define	COPY_BACK_2K			0x85
+#define	READ1_1_2			0x30
+#define	READ1_1_3			0x35
+#define	CHG_DAT_OUT_1			0x05
+#define RDM_DAT_OUT_1			0x05
+#define	CHG_DAT_OUT_2			0xE0
+#define RDM_DAT_OUT_2			0xE0
+#define	CHG_DAT_OUT_2			0xE0
+#define	CHG_DAT_IN_1			0x85
+#define	CACHE_PRG			0x15
+
+/* Redundant Area Related */
+#define XD_EXTRA_SIZE			0x10
+#define XD_2K_EXTRA_SIZE		0x40
+
+#define	NOT_WRITE_PROTECTED		0x80
+#define	READY_STATE			0x40
+#define	PROGRAM_ERROR			0x01
+#define	PROGRAM_ERROR_N_1		0x02
+#define	INTERNAL_READY			0x20
+#define	READY_FLAG			0x5F
+
+#define	XD_8M_X8_512			0xE6
+#define	XD_16M_X8_512			0x73
+#define	XD_32M_X8_512			0x75
+#define	XD_64M_X8_512			0x76
+#define	XD_128M_X8_512			0x79
+#define	XD_256M_X8_512			0x71
+#define	XD_128M_X8_2048			0xF1
+#define	XD_256M_X8_2048			0xDA
+#define	XD_512M_X8			0xDC
+#define	XD_128M_X16_2048		0xC1
+#define	XD_4M_X8_512_1			0xE3
+#define	XD_4M_X8_512_2			0xE5
+#define	xD_1G_X8_512			0xD3
+#define	xD_2G_X8_512			0xD5
+
+#define	XD_ID_CODE			0xB5
+
+#define	VENDOR_BLOCK			0xEFFF
+#define	CIS_BLOCK			0xDFFF
+
+#define	BLK_NOT_FOUND			0xFFFFFFFF
+
+#define	NO_NEW_BLK			0xFFFFFFFF
+
+#define	PAGE_CORRECTABLE		0x0
+#define	PAGE_NOTCORRECTABLE		0x1
+
+#define	NO_OFFSET			0x0
+#define	WITH_OFFSET			0x1
+
+#define	Sect_Per_Page			4
+#define	XD_ADDR_MODE_2C			XD_ADDR_MODE_2A
+
+#define ZONE0_BAD_BLOCK 		23
+#define NOT_ZONE0_BAD_BLOCK 		24
+
+#define	XD_RW_ADDR			0x01
+#define	XD_ERASE_ADDR			0x02
+
+#define	XD_PAGE_512(xd_card)		\
+do {					\
+	(xd_card)->block_shift = 5; 	\
+	(xd_card)->page_off = 0x1F;	\
+} while (0)
+
+#define	XD_SET_BAD_NEWBLK(xd_card)	((xd_card)->multi_flag |= 0x01)
+#define	XD_CLR_BAD_NEWBLK(xd_card)	((xd_card)->multi_flag &= ~0x01)
+#define	XD_CHK_BAD_NEWBLK(xd_card)	((xd_card)->multi_flag & 0x01)
+
+#define	XD_SET_BAD_OLDBLK(xd_card)	((xd_card)->multi_flag |= 0x02)
+#define	XD_CLR_BAD_OLDBLK(xd_card)	((xd_card)->multi_flag &= ~0x02)
+#define	XD_CHK_BAD_OLDBLK(xd_card)	((xd_card)->multi_flag & 0x02)
+
+#define	XD_SET_MBR_FAIL(xd_card)	((xd_card)->multi_flag |= 0x04)
+#define	XD_CLR_MBR_FAIL(xd_card)	((xd_card)->multi_flag &= ~0x04)
+#define	XD_CHK_MBR_FAIL(xd_card)	((xd_card)->multi_flag & 0x04)
+
+#define	XD_SET_ECC_FLD_ERR(xd_card)	((xd_card)->multi_flag |= 0x08)
+#define	XD_CLR_ECC_FLD_ERR(xd_card)	((xd_card)->multi_flag &= ~0x08)
+#define	XD_CHK_ECC_FLD_ERR(xd_card)	((xd_card)->multi_flag & 0x08)
+
+#define	XD_SET_4MB(xd_card)		((xd_card)->multi_flag |= 0x10)
+#define	XD_CLR_4MB(xd_card)		((xd_card)->multi_flag &= ~0x10)
+#define	XD_CHK_4MB(xd_card)		((xd_card)->multi_flag & 0x10)
+
+#define	XD_SET_ECC_ERR(xd_card)		((xd_card)->multi_flag |= 0x40)
+#define	XD_CLR_ECC_ERR(xd_card)		((xd_card)->multi_flag &= ~0x40)
+#define	XD_CHK_ECC_ERR(xd_card)		((xd_card)->multi_flag & 0x40)
+
+#define PAGE_STATUS		0
+#define BLOCK_STATUS		1
+#define BLOCK_ADDR1_L		2
+#define BLOCK_ADDR1_H		3
+#define BLOCK_ADDR2_L		4
+#define BLOCK_ADDR2_H		5
+#define RESERVED0		6
+#define RESERVED1		7
+#define RESERVED2		8
+#define RESERVED3		9
+#define PARITY			10
+
+#define	CIS0_0			0
+#define	CIS0_1			1
+#define	CIS0_2			2
+#define	CIS0_3			3
+#define	CIS0_4			4
+#define	CIS0_5			5
+#define	CIS0_6			6
+#define	CIS0_7			7
+#define	CIS0_8			8
+#define	CIS0_9			9
+#define	CIS1_0			256
+#define	CIS1_1			(256 + 1)
+#define	CIS1_2			(256 + 2)
+#define	CIS1_3			(256 + 3)
+#define	CIS1_4			(256 + 4)
+#define	CIS1_5			(256 + 5)
+#define	CIS1_6			(256 + 6)
+#define	CIS1_7			(256 + 7)
+#define	CIS1_8			(256 + 8)
+#define	CIS1_9			(256 + 9)
+
+int reset_xd_card(struct rtsx_chip *chip);
+#ifdef XD_DELAY_WRITE
+int xd_delay_write(struct rtsx_chip *chip);
+#endif
+int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector, u16 sector_cnt);
+void xd_free_l2p_tbl(struct rtsx_chip *chip);
+void xd_cleanup_work(struct rtsx_chip *chip);
+int xd_power_off_card3v3(struct rtsx_chip *chip);
+int release_xd_card(struct rtsx_chip *chip);
+
+#endif  /* __REALTEK_RTSX_XD_H */
+
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
index 701e8d5..2529446 100644
--- a/drivers/staging/samsung-laptop/samsung-laptop.c
+++ b/drivers/staging/samsung-laptop/samsung-laptop.c
@@ -1,14 +1,16 @@
 /*
- * Samsung N130 Laptop driver
+ * Samsung Laptop driver
  *
- * Copyright (C) 2009 Greg Kroah-Hartman (gregkh@suse.de)
- * Copyright (C) 2009 Novell Inc.
+ * Copyright (C) 2009,2011 Greg Kroah-Hartman (gregkh@suse.de)
+ * Copyright (C) 2009,2011 Novell 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.
  *
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -33,51 +35,6 @@
  */
 #define MAX_BRIGHT	0x07
 
-/* Brightness is 0 - 8, as described above.  Value 0 is for the BIOS to use */
-#define GET_BRIGHTNESS			0x00
-#define SET_BRIGHTNESS			0x01
-
-/* first byte:
- * 0x00 - wireless is off
- * 0x01 - wireless is on
- * second byte:
- * 0x02 - 3G is off
- * 0x03 - 3G is on
- * TODO, verify 3G is correct, that doesn't seem right...
- */
-#define GET_WIRELESS_BUTTON		0x02
-#define SET_WIRELESS_BUTTON		0x03
-
-/* 0 is off, 1 is on */
-#define GET_BACKLIGHT			0x04
-#define SET_BACKLIGHT			0x05
-
-/*
- * 0x80 or 0x00 - no action
- * 0x81 - recovery key pressed
- */
-#define GET_RECOVERY_METHOD		0x06
-#define SET_RECOVERY_METHOD		0x07
-
-/* 0 is low, 1 is high */
-#define GET_PERFORMANCE_LEVEL		0x08
-#define SET_PERFORMANCE_LEVEL		0x09
-
-/*
- * Tell the BIOS that Linux is running on this machine.
- * 81 is on, 80 is off
- */
-#define SET_LINUX			0x0a
-
-
-#define MAIN_FUNCTION			0x4c49
-
-#define SABI_HEADER_PORT		0x00
-#define SABI_HEADER_RE_MEM		0x02
-#define SABI_HEADER_IFACEFUNC		0x03
-#define SABI_HEADER_EN_MEM		0x04
-#define SABI_HEADER_DATA_OFFSET		0x05
-#define SABI_HEADER_DATA_SEGMENT	0x07
 
 #define SABI_IFACE_MAIN			0x00
 #define SABI_IFACE_SUB			0x02
@@ -89,6 +46,179 @@ struct sabi_retval {
 	u8 retval[20];
 };
 
+struct sabi_header_offsets {
+	u8 port;
+	u8 re_mem;
+	u8 iface_func;
+	u8 en_mem;
+	u8 data_offset;
+	u8 data_segment;
+};
+
+struct sabi_commands {
+	/*
+	 * Brightness is 0 - 8, as described above.
+	 * Value 0 is for the BIOS to use
+	 */
+	u8 get_brightness;
+	u8 set_brightness;
+
+	/*
+	 * first byte:
+	 * 0x00 - wireless is off
+	 * 0x01 - wireless is on
+	 * second byte:
+	 * 0x02 - 3G is off
+	 * 0x03 - 3G is on
+	 * TODO, verify 3G is correct, that doesn't seem right...
+	 */
+	u8 get_wireless_button;
+	u8 set_wireless_button;
+
+	/* 0 is off, 1 is on */
+	u8 get_backlight;
+	u8 set_backlight;
+
+	/*
+	 * 0x80 or 0x00 - no action
+	 * 0x81 - recovery key pressed
+	 */
+	u8 get_recovery_mode;
+	u8 set_recovery_mode;
+
+	/*
+	 * on seclinux: 0 is low, 1 is high,
+	 * on swsmi: 0 is normal, 1 is silent, 2 is turbo
+	 */
+	u8 get_performance_level;
+	u8 set_performance_level;
+
+	/*
+	 * Tell the BIOS that Linux is running on this machine.
+	 * 81 is on, 80 is off
+	 */
+	u8 set_linux;
+};
+
+struct sabi_performance_level {
+	const char *name;
+	u8 value;
+};
+
+struct sabi_config {
+	const char *test_string;
+	u16 main_function;
+	const struct sabi_header_offsets header_offsets;
+	const struct sabi_commands commands;
+	const struct sabi_performance_level performance_levels[4];
+	u8 min_brightness;
+	u8 max_brightness;
+};
+
+static const struct sabi_config sabi_configs[] = {
+	{
+		.test_string = "SECLINUX",
+
+		.main_function = 0x4c49,
+
+		.header_offsets = {
+			.port = 0x00,
+			.re_mem = 0x02,
+			.iface_func = 0x03,
+			.en_mem = 0x04,
+			.data_offset = 0x05,
+			.data_segment = 0x07,
+		},
+
+		.commands = {
+			.get_brightness = 0x00,
+			.set_brightness = 0x01,
+
+			.get_wireless_button = 0x02,
+			.set_wireless_button = 0x03,
+
+			.get_backlight = 0x04,
+			.set_backlight = 0x05,
+
+			.get_recovery_mode = 0x06,
+			.set_recovery_mode = 0x07,
+
+			.get_performance_level = 0x08,
+			.set_performance_level = 0x09,
+
+			.set_linux = 0x0a,
+		},
+
+		.performance_levels = {
+			{
+				.name = "silent",
+				.value = 0,
+			},
+			{
+				.name = "normal",
+				.value = 1,
+			},
+			{ },
+		},
+		.min_brightness = 1,
+		.max_brightness = 8,
+	},
+	{
+		.test_string = "SwSmi@",
+
+		.main_function = 0x5843,
+
+		.header_offsets = {
+			.port = 0x00,
+			.re_mem = 0x04,
+			.iface_func = 0x02,
+			.en_mem = 0x03,
+			.data_offset = 0x05,
+			.data_segment = 0x07,
+		},
+
+		.commands = {
+			.get_brightness = 0x10,
+			.set_brightness = 0x11,
+
+			.get_wireless_button = 0x12,
+			.set_wireless_button = 0x13,
+
+			.get_backlight = 0x2d,
+			.set_backlight = 0x2e,
+
+			.get_recovery_mode = 0xff,
+			.set_recovery_mode = 0xff,
+
+			.get_performance_level = 0x31,
+			.set_performance_level = 0x32,
+
+			.set_linux = 0xff,
+		},
+
+		.performance_levels = {
+			{
+				.name = "normal",
+				.value = 0,
+			},
+			{
+				.name = "silent",
+				.value = 1,
+			},
+			{
+				.name = "overclock",
+				.value = 2,
+			},
+			{ },
+		},
+		.min_brightness = 0,
+		.max_brightness = 8,
+	},
+	{ },
+};
+
+static const struct sabi_config *sabi_config;
+
 static void __iomem *sabi;
 static void __iomem *sabi_iface;
 static void __iomem *f0000_segment;
@@ -109,44 +239,43 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
 static int sabi_get_command(u8 command, struct sabi_retval *sretval)
 {
 	int retval = 0;
-	u16 port = readw(sabi + SABI_HEADER_PORT);
+	u16 port = readw(sabi + sabi_config->header_offsets.port);
+	u8 complete, iface_data;
 
 	mutex_lock(&sabi_mutex);
 
 	/* enable memory to be able to write to it */
-	outb(readb(sabi + SABI_HEADER_EN_MEM), port);
+	outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
 
 	/* write out the command */
-	writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
+	writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
 	writew(command, sabi_iface + SABI_IFACE_SUB);
 	writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-	outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
+	outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
 
 	/* write protect memory to make it safe */
-	outb(readb(sabi + SABI_HEADER_RE_MEM), port);
+	outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
 
 	/* see if the command actually succeeded */
-	if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
-	    readb(sabi_iface + SABI_IFACE_DATA) != 0xff) {
-		/*
-		 * It did!
-		 * Save off the data into a structure so the caller use it.
-		 * Right now we only care about the first 4 bytes,
-		 * I suppose there are commands that need more, but I don't
-		 * know about them.
-		 */
-		sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
-		sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
-		sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
-		sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
+	complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
+	iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+	if (complete != 0xaa || iface_data == 0xff) {
+		pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
+		        command, complete, iface_data);
+		retval = -EINVAL;
 		goto exit;
 	}
+	/*
+	 * Save off the data into a structure so the caller use it.
+	 * Right now we only want the first 4 bytes,
+	 * There are commands that need more, but not for the ones we
+	 * currently care about.
+	 */
+	sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
+	sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
+	sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
+	sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
 
-	/* Something bad happened, so report it and error out */
-	printk(KERN_WARNING "SABI command 0x%02x failed with completion flag 0x%02x and output 0x%02x\n",
-		command, readb(sabi_iface + SABI_IFACE_COMPLETE),
-		readb(sabi_iface + SABI_IFACE_DATA));
-	retval = -EINVAL;
 exit:
 	mutex_unlock(&sabi_mutex);
 	return retval;
@@ -156,36 +285,33 @@ exit:
 static int sabi_set_command(u8 command, u8 data)
 {
 	int retval = 0;
-	u16 port = readw(sabi + SABI_HEADER_PORT);
+	u16 port = readw(sabi + sabi_config->header_offsets.port);
+	u8 complete, iface_data;
 
 	mutex_lock(&sabi_mutex);
 
 	/* enable memory to be able to write to it */
-	outb(readb(sabi + SABI_HEADER_EN_MEM), port);
+	outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
 
 	/* write out the command */
-	writew(MAIN_FUNCTION, sabi_iface + SABI_IFACE_MAIN);
+	writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
 	writew(command, sabi_iface + SABI_IFACE_SUB);
 	writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
 	writeb(data, sabi_iface + SABI_IFACE_DATA);
-	outb(readb(sabi + SABI_HEADER_IFACEFUNC), port);
+	outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
 
 	/* write protect memory to make it safe */
-	outb(readb(sabi + SABI_HEADER_RE_MEM), port);
+	outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
 
 	/* see if the command actually succeeded */
-	if (readb(sabi_iface + SABI_IFACE_COMPLETE) == 0xaa &&
-	    readb(sabi_iface + SABI_IFACE_DATA) != 0xff) {
-		/* it did! */
-		goto exit;
+	complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
+	iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+	if (complete != 0xaa || iface_data == 0xff) {
+		pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
+		       command, complete, iface_data);
+		retval = -EINVAL;
 	}
 
-	/* Something bad happened, so report it and error out */
-	printk(KERN_WARNING "SABI command 0x%02x failed with completion flag 0x%02x and output 0x%02x\n",
-		command, readb(sabi_iface + SABI_IFACE_COMPLETE),
-		readb(sabi_iface + SABI_IFACE_DATA));
-	retval = -EINVAL;
-exit:
 	mutex_unlock(&sabi_mutex);
 	return retval;
 }
@@ -194,21 +320,21 @@ static void test_backlight(void)
 {
 	struct sabi_retval sretval;
 
-	sabi_get_command(GET_BACKLIGHT, &sretval);
+	sabi_get_command(sabi_config->commands.get_backlight, &sretval);
 	printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
 
-	sabi_set_command(SET_BACKLIGHT, 0);
+	sabi_set_command(sabi_config->commands.set_backlight, 0);
 	printk(KERN_DEBUG "backlight should be off\n");
 
-	sabi_get_command(GET_BACKLIGHT, &sretval);
+	sabi_get_command(sabi_config->commands.get_backlight, &sretval);
 	printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
 
 	msleep(1000);
 
-	sabi_set_command(SET_BACKLIGHT, 1);
+	sabi_set_command(sabi_config->commands.set_backlight, 1);
 	printk(KERN_DEBUG "backlight should be on\n");
 
-	sabi_get_command(GET_BACKLIGHT, &sretval);
+	sabi_get_command(sabi_config->commands.get_backlight, &sretval);
 	printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
 }
 
@@ -216,21 +342,21 @@ static void test_wireless(void)
 {
 	struct sabi_retval sretval;
 
-	sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
+	sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
 	printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
 
-	sabi_set_command(SET_WIRELESS_BUTTON, 0);
+	sabi_set_command(sabi_config->commands.set_wireless_button, 0);
 	printk(KERN_DEBUG "wireless led should be off\n");
 
-	sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
+	sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
 	printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
 
 	msleep(1000);
 
-	sabi_set_command(SET_WIRELESS_BUTTON, 1);
+	sabi_set_command(sabi_config->commands.set_wireless_button, 1);
 	printk(KERN_DEBUG "wireless led should be on\n");
 
-	sabi_get_command(GET_WIRELESS_BUTTON, &sretval);
+	sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
 	printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
 }
 
@@ -240,17 +366,21 @@ static u8 read_brightness(void)
 	int user_brightness = 0;
 	int retval;
 
-	retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
-	if (!retval)
+	retval = sabi_get_command(sabi_config->commands.get_brightness,
+				  &sretval);
+	if (!retval) {
 		user_brightness = sretval.retval[0];
 		if (user_brightness != 0)
-			--user_brightness;
+			user_brightness -= sabi_config->min_brightness;
+	}
 	return user_brightness;
 }
 
 static void set_brightness(u8 user_brightness)
 {
-	sabi_set_command(SET_BRIGHTNESS, user_brightness + 1);
+	u8 user_level = user_brightness - sabi_config->min_brightness;
+
+	sabi_set_command(sabi_config->commands.set_brightness, user_level);
 }
 
 static int get_brightness(struct backlight_device *bd)
@@ -263,9 +393,9 @@ static int update_status(struct backlight_device *bd)
 	set_brightness(bd->props.brightness);
 
 	if (bd->props.power == FB_BLANK_UNBLANK)
-		sabi_set_command(SET_BACKLIGHT, 1);
+		sabi_set_command(sabi_config->commands.set_backlight, 1);
 	else
-		sabi_set_command(SET_BACKLIGHT, 0);
+		sabi_set_command(sabi_config->commands.set_backlight, 0);
 	return 0;
 }
 
@@ -282,9 +412,9 @@ static int rfkill_set(void *data, bool blocked)
 	 * blocked == true is off
 	 */
 	if (blocked)
-		sabi_set_command(SET_WIRELESS_BUTTON, 0);
+		sabi_set_command(sabi_config->commands.set_wireless_button, 0);
 	else
-		sabi_set_command(SET_WIRELESS_BUTTON, 1);
+		sabi_set_command(sabi_config->commands.set_wireless_button, 1);
 
 	return 0;
 }
@@ -317,52 +447,54 @@ static void destroy_wireless(void)
 	rfkill_destroy(rfk);
 }
 
-static ssize_t get_silent_state(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t get_performance_level(struct device *dev,
+				     struct device_attribute *attr, char *buf)
 {
 	struct sabi_retval sretval;
 	int retval;
+	int i;
 
 	/* Read the state */
-	retval = sabi_get_command(GET_PERFORMANCE_LEVEL, &sretval);
+	retval = sabi_get_command(sabi_config->commands.get_performance_level,
+				  &sretval);
 	if (retval)
 		return retval;
 
 	/* The logic is backwards, yeah, lots of fun... */
-	if (sretval.retval[0] == 0)
-		retval = 1;
-	else
-		retval = 0;
-	return sprintf(buf, "%d\n", retval);
+	for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+		if (sretval.retval[0] == sabi_config->performance_levels[i].value)
+			return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
+	}
+	return sprintf(buf, "%s\n", "unknown");
 }
 
-static ssize_t set_silent_state(struct device *dev,
+static ssize_t set_performance_level(struct device *dev,
 				struct device_attribute *attr, const char *buf,
 				size_t count)
 {
-	char value;
-
 	if (count >= 1) {
-		value = buf[0];
-		if ((value == '0') || (value == 'n') || (value == 'N')) {
-			/* Turn speed up */
-			sabi_set_command(SET_PERFORMANCE_LEVEL, 0x01);
-		} else if ((value == '1') || (value == 'y') || (value == 'Y')) {
-			/* Turn speed down */
-			sabi_set_command(SET_PERFORMANCE_LEVEL, 0x00);
-		} else {
-			return -EINVAL;
+		int i;
+		for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+			const struct sabi_performance_level *level =
+				&sabi_config->performance_levels[i];
+			if (!strncasecmp(level->name, buf, strlen(level->name))) {
+				sabi_set_command(sabi_config->commands.set_performance_level,
+						 level->value);
+				break;
+			}
 		}
+		if (!sabi_config->performance_levels[i].name)
+			return -EINVAL;
 	}
 	return count;
 }
-static DEVICE_ATTR(silent, S_IWUSR | S_IRUGO,
-		   get_silent_state, set_silent_state);
+static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
+		   get_performance_level, set_performance_level);
 
 
 static int __init dmi_check_cb(const struct dmi_system_id *id)
 {
-	printk(KERN_INFO KBUILD_MODNAME ": found laptop model '%s'\n",
+	pr_info("found laptop model '%s'\n",
 		id->ident);
 	return 0;
 }
@@ -388,18 +520,181 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
 		},
 		.callback = dmi_check_cb,
 	},
+	{
+		.ident = "X125",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
+			DMI_MATCH(DMI_BOARD_NAME, "X125"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "X120/X170",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
+			DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "NC10",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
+			DMI_MATCH(DMI_BOARD_NAME, "NC10"),
+		},
+		.callback = dmi_check_cb,
+	},
+		{
+		.ident = "NP-Q45",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
+			DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
+		},
+		.callback = dmi_check_cb,
+		},
+	{
+		.ident = "X360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
+			DMI_MATCH(DMI_BOARD_NAME, "X360"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R410 Plus",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
+			DMI_MATCH(DMI_BOARD_NAME, "R460"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R518",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
+			DMI_MATCH(DMI_BOARD_NAME, "R518"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R519/R719",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
+			DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N150/N210/N220/N230",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
+			DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N150P/N210P/N220P",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
+			DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R530/R730",
+		.matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
+		      DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "NF110/NF210/NF310",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
+			DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N145P/N250P/N260P",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
+			DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R70/R71",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
+			DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "P460",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
+			DMI_MATCH(DMI_BOARD_NAME, "P460"),
+		},
+		.callback = dmi_check_cb,
+	},
 	{ },
 };
 MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
 
+static int find_signature(void __iomem *memcheck, const char *testStr)
+{
+	int i = 0;
+	int loca;
+
+	for (loca = 0; loca < 0xffff; loca++) {
+		char temp = readb(memcheck + loca);
+
+		if (temp == testStr[i]) {
+			if (i == strlen(testStr)-1)
+				break;
+			++i;
+		} else {
+			i = 0;
+		}
+	}
+	return loca;
+}
+
 static int __init samsung_init(void)
 {
 	struct backlight_properties props;
 	struct sabi_retval sretval;
-	const char *testStr = "SECLINUX";
-	void __iomem *memcheck;
 	unsigned int ifaceP;
-	int pStr;
+	int i;
 	int loca;
 	int retval;
 
@@ -408,59 +703,53 @@ static int __init samsung_init(void)
 	if (!force && !dmi_check_system(samsung_dmi_table))
 		return -ENODEV;
 
-	f0000_segment = ioremap(0xf0000, 0xffff);
+	f0000_segment = ioremap_nocache(0xf0000, 0xffff);
 	if (!f0000_segment) {
-		printk(KERN_ERR "Can't map the segment at 0xf0000\n");
+		pr_err("Can't map the segment at 0xf0000\n");
 		return -EINVAL;
 	}
 
-	/* Try to find the signature "SECLINUX" in memory to find the header */
-	pStr = 0;
-	memcheck = f0000_segment;
-	for (loca = 0; loca < 0xffff; loca++) {
-		char temp = readb(memcheck + loca);
-
-		if (temp == testStr[pStr]) {
-			if (pStr == strlen(testStr)-1)
-				break;
-			++pStr;
-		} else {
-			pStr = 0;
-		}
+	/* Try to find one of the signatures in memory to find the header */
+	for (i = 0; sabi_configs[i].test_string != 0; ++i) {
+		sabi_config = &sabi_configs[i];
+		loca = find_signature(f0000_segment, sabi_config->test_string);
+		if (loca != 0xffff)
+			break;
 	}
+
 	if (loca == 0xffff) {
-		printk(KERN_ERR "This computer does not support SABI\n");
+		pr_err("This computer does not support SABI\n");
 		goto error_no_signature;
-		}
+	}
 
 	/* point to the SMI port Number */
 	loca += 1;
-	sabi = (memcheck + loca);
+	sabi = (f0000_segment + loca);
 
 	if (debug) {
 		printk(KERN_DEBUG "This computer supports SABI==%x\n",
 			loca + 0xf0000 - 6);
 		printk(KERN_DEBUG "SABI header:\n");
 		printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
-			readw(sabi + SABI_HEADER_PORT));
+			readw(sabi + sabi_config->header_offsets.port));
 		printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
-			readb(sabi + SABI_HEADER_IFACEFUNC));
+			readb(sabi + sabi_config->header_offsets.iface_func));
 		printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
-			readb(sabi + SABI_HEADER_EN_MEM));
+			readb(sabi + sabi_config->header_offsets.en_mem));
 		printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
-			readb(sabi + SABI_HEADER_RE_MEM));
+			readb(sabi + sabi_config->header_offsets.re_mem));
 		printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
-			readw(sabi + SABI_HEADER_DATA_OFFSET));
+			readw(sabi + sabi_config->header_offsets.data_offset));
 		printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
-			readw(sabi + SABI_HEADER_DATA_SEGMENT));
+			readw(sabi + sabi_config->header_offsets.data_segment));
 	}
 
 	/* Get a pointer to the SABI Interface */
-	ifaceP = (readw(sabi + SABI_HEADER_DATA_SEGMENT) & 0x0ffff) << 4;
-	ifaceP += readw(sabi + SABI_HEADER_DATA_OFFSET) & 0x0ffff;
-	sabi_iface = ioremap(ifaceP, 16);
+	ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
+	ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
+	sabi_iface = ioremap_nocache(ifaceP, 16);
 	if (!sabi_iface) {
-		printk(KERN_ERR "Can't remap %x\n", ifaceP);
+		pr_err("Can't remap %x\n", ifaceP);
 		goto exit;
 	}
 	if (debug) {
@@ -470,15 +759,19 @@ static int __init samsung_init(void)
 		test_backlight();
 		test_wireless();
 
-		retval = sabi_get_command(GET_BRIGHTNESS, &sretval);
+		retval = sabi_get_command(sabi_config->commands.get_brightness,
+					  &sretval);
 		printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
 	}
 
 	/* Turn on "Linux" mode in the BIOS */
-	retval = sabi_set_command(SET_LINUX, 0x81);
-	if (retval) {
-		printk(KERN_ERR KBUILD_MODNAME ": Linux mode was not set!\n");
-		goto error_no_platform;
+	if (sabi_config->commands.set_linux != 0xff) {
+		retval = sabi_set_command(sabi_config->commands.set_linux,
+					  0x81);
+		if (retval) {
+			pr_warn("Linux mode was not set!\n");
+			goto error_no_platform;
+		}
 	}
 
 	/* knock up a platform device to hang stuff off of */
@@ -488,7 +781,8 @@ static int __init samsung_init(void)
 
 	/* create a backlight device to talk to this one */
 	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = MAX_BRIGHT;
+	props.type = BACKLIGHT_PLATFORM;
+	props.max_brightness = sabi_config->max_brightness;
 	backlight_device = backlight_device_register("samsung", &sdev->dev,
 						     NULL, &backlight_ops,
 						     &props);
@@ -503,7 +797,7 @@ static int __init samsung_init(void)
 	if (retval)
 		goto error_no_rfk;
 
-	retval = device_create_file(&sdev->dev, &dev_attr_silent);
+	retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
 	if (retval)
 		goto error_file_create;
 
@@ -530,9 +824,10 @@ error_no_signature:
 static void __exit samsung_exit(void)
 {
 	/* Turn off "Linux" mode in the BIOS */
-	sabi_set_command(SET_LINUX, 0x80);
+	if (sabi_config->commands.set_linux != 0xff)
+		sabi_set_command(sabi_config->commands.set_linux, 0x80);
 
-	device_remove_file(&sdev->dev, &dev_attr_silent);
+	device_remove_file(&sdev->dev, &dev_attr_performance_level);
 	backlight_device_unregister(backlight_device);
 	destroy_wireless();
 	iounmap(sabi_iface);
diff --git a/drivers/staging/sep/TODO b/drivers/staging/sep/TODO
index 089c240..8f3b878 100644
--- a/drivers/staging/sep/TODO
+++ b/drivers/staging/sep/TODO
@@ -1,5 +1,4 @@
 Todo's so far (from Alan Cox)
 - Check whether it can be plugged into any of the kernel crypto API
   interfaces - Crypto API 'glue' is still not ready to submit
-- Clean up unused ioctls - Needs vendor help
-- Clean up unused fields in ioctl structures - Needs vendor help
+- Clean up un-needed debug prints - Started to work on this
diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h
index 0ffe68c..696ab0d 100644
--- a/drivers/staging/sep/sep_dev.h
+++ b/drivers/staging/sep/sep_dev.h
@@ -69,31 +69,6 @@ struct sep_device {
 	size_t shared_size;
 	void *shared_addr;
 
-	/* restricted access region (coherent alloc) */
-	dma_addr_t rar_bus;
-	size_t rar_size;
-	void *rar_addr;
-
-	/* Firmware regions; cache is at rar for Moorestown and
-	   resident is at rar for Medfield */
-	dma_addr_t cache_bus;
-	size_t cache_size;
-	void *cache_addr;
-
-	dma_addr_t resident_bus;
-	size_t resident_size;
-	void *resident_addr;
-
-	/* sep's scratchpad */
-	dma_addr_t dcache_bus;
-	size_t dcache_size;
-	void *dcache_addr;
-
-	/* Only used on Medfield */
-	dma_addr_t extapp_bus;
-	size_t extapp_size;
-	void *extapp_addr;
-
 	/* start address of the access to the SEP registers from driver */
 	dma_addr_t reg_physical_addr;
 	dma_addr_t reg_physical_end;
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index ac5d569..71a5fbc 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -29,7 +29,6 @@
  *  2010.09.14  Upgrade to Medfield
  *
  */
-#define DEBUG
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/miscdevice.h>
@@ -78,105 +77,6 @@
 static struct sep_device *sep_dev;
 
 /**
- *	sep_load_firmware - copy firmware cache/resident
- *	@sep: pointer to struct sep_device we are loading
- *
- *	This functions copies the cache and resident from their source
- *	location into destination shared memory.
- */
-static int sep_load_firmware(struct sep_device *sep)
-{
-	const struct firmware *fw;
-	char *cache_name = "cache.image.bin";
-	char *res_name = "resident.image.bin";
-	char *extapp_name = "extapp.image.bin";
-	int error ;
-	unsigned long work1, work2, work3;
-
-	/* Set addresses and load resident */
-	sep->resident_bus = sep->rar_bus;
-	sep->resident_addr = sep->rar_addr;
-
-	error = request_firmware(&fw, res_name, &sep->pdev->dev);
-	if (error) {
-		dev_warn(&sep->pdev->dev, "can't request resident fw\n");
-		return error;
-	}
-
-	memcpy(sep->resident_addr, (void *)fw->data, fw->size);
-	sep->resident_size = fw->size;
-	release_firmware(fw);
-
-	dev_dbg(&sep->pdev->dev, "resident virtual is %p\n",
-		sep->resident_addr);
-	dev_dbg(&sep->pdev->dev, "resident bus is %lx\n",
-		(unsigned long)sep->resident_bus);
-	dev_dbg(&sep->pdev->dev, "resident size is %08zx\n",
-		sep->resident_size);
-
-	/* Set addresses for dcache (no loading needed) */
-	work1 = (unsigned long)sep->resident_bus;
-	work2 = (unsigned long)sep->resident_size;
-	work3 = (work1 + work2 + (1024 * 4)) & 0xfffff000;
-	sep->dcache_bus = (dma_addr_t)work3;
-
-	work1 = (unsigned long)sep->resident_addr;
-	work2 = (unsigned long)sep->resident_size;
-	work3 = (work1 + work2 + (1024 * 4)) & 0xfffff000;
-	sep->dcache_addr = (void *)work3;
-
-	sep->dcache_size = 1024 * 128;
-
-	/* Set addresses and load cache */
-	sep->cache_bus = sep->dcache_bus + sep->dcache_size;
-	sep->cache_addr = sep->dcache_addr + sep->dcache_size;
-
-	error = request_firmware(&fw, cache_name, &sep->pdev->dev);
-	if (error) {
-		dev_warn(&sep->pdev->dev, "Unable to request cache firmware\n");
-		return error;
-	}
-
-	memcpy(sep->cache_addr, (void *)fw->data, fw->size);
-	sep->cache_size = fw->size;
-	release_firmware(fw);
-
-	dev_dbg(&sep->pdev->dev, "cache virtual is %p\n",
-		sep->cache_addr);
-	dev_dbg(&sep->pdev->dev, "cache bus is %08lx\n",
-		(unsigned long)sep->cache_bus);
-	dev_dbg(&sep->pdev->dev, "cache size is %08zx\n",
-		sep->cache_size);
-
-	/* Set addresses and load extapp */
-	sep->extapp_bus = sep->cache_bus + (1024 * 370);
-	sep->extapp_addr = sep->cache_addr + (1024 * 370);
-
-	error = request_firmware(&fw, extapp_name, &sep->pdev->dev);
-	if (error) {
-		dev_warn(&sep->pdev->dev, "Unable to request extapp firmware\n");
-		return error;
-	}
-
-	memcpy(sep->extapp_addr, (void *)fw->data, fw->size);
-	sep->extapp_size = fw->size;
-	release_firmware(fw);
-
-	dev_dbg(&sep->pdev->dev, "extapp virtual is %p\n",
-		sep->extapp_addr);
-	dev_dbg(&sep->pdev->dev, "extapp bus is %08llx\n",
-		(unsigned long long)sep->extapp_bus);
-	dev_dbg(&sep->pdev->dev, "extapp size is %08zx\n",
-		sep->extapp_size);
-
-	return error;
-}
-
-MODULE_FIRMWARE("sep/cache.image.bin");
-MODULE_FIRMWARE("sep/resident.image.bin");
-MODULE_FIRMWARE("sep/extapp.image.bin");
-
-/**
  *	sep_dump_message - dump the message that is pending
  *	@sep: SEP device
  */
@@ -218,7 +118,6 @@ static int sep_map_and_alloc_shared_area(struct sep_device *sep)
  */
 static void sep_unmap_and_free_shared_area(struct sep_device *sep)
 {
-	dev_dbg(&sep->pdev->dev, "shared area unmap and free\n");
 	dma_free_coherent(&sep->pdev->dev, sep->shared_size,
 				sep->shared_addr, sep->shared_bus);
 }
@@ -246,7 +145,6 @@ static void *sep_shared_bus_to_virt(struct sep_device *sep,
  */
 static int sep_singleton_open(struct inode *inode_ptr, struct file *file_ptr)
 {
-	int error = 0;
 	struct sep_device *sep;
 
 	/*
@@ -257,17 +155,9 @@ static int sep_singleton_open(struct inode *inode_ptr, struct file *file_ptr)
 
 	file_ptr->private_data = sep;
 
-	dev_dbg(&sep->pdev->dev, "Singleton open for pid %d\n", current->pid);
-
-	dev_dbg(&sep->pdev->dev, "calling test and set for singleton 0\n");
-	if (test_and_set_bit(0, &sep->singleton_access_flag)) {
-		error = -EBUSY;
-		goto end_function;
-	}
-
-	dev_dbg(&sep->pdev->dev, "sep_singleton_open end\n");
-end_function:
-	return error;
+	if (test_and_set_bit(0, &sep->singleton_access_flag))
+		return -EBUSY;
+	return 0;
 }
 
 /**
@@ -291,8 +181,6 @@ static int sep_open(struct inode *inode, struct file *filp)
 	sep = sep_dev;
 	filp->private_data = sep;
 
-	dev_dbg(&sep->pdev->dev, "Open for pid %d\n", current->pid);
-
 	/* Anyone can open; locking takes place at transaction level */
 	return 0;
 }
@@ -310,8 +198,6 @@ static int sep_singleton_release(struct inode *inode, struct file *filp)
 {
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "Singleton release for pid %d\n",
-							current->pid);
 	clear_bit(0, &sep->singleton_access_flag);
 	return 0;
 }
@@ -333,11 +219,7 @@ static int sep_request_daemon_open(struct inode *inode, struct file *filp)
 
 	filp->private_data = sep;
 
-	dev_dbg(&sep->pdev->dev, "Request daemon open for pid %d\n",
-		current->pid);
-
 	/* There is supposed to be only one request daemon */
-	dev_dbg(&sep->pdev->dev, "calling test and set for req_dmon open 0\n");
 	if (test_and_set_bit(0, &sep->request_daemon_open))
 		error = -EBUSY;
 	return error;
@@ -354,7 +236,7 @@ static int sep_request_daemon_release(struct inode *inode, struct file *filp)
 {
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "Reques daemon release for pid %d\n",
+	dev_dbg(&sep->pdev->dev, "Request daemon release for pid %d\n",
 		current->pid);
 
 	/* Clear the request_daemon_open flag */
@@ -373,9 +255,6 @@ static int sep_req_daemon_send_reply_command_handler(struct sep_device *sep)
 {
 	unsigned long lck_flags;
 
-	dev_dbg(&sep->pdev->dev,
-		"sep_req_daemon_send_reply_command_handler start\n");
-
 	sep_dump_message(sep);
 
 	/* Counters are lockable region */
@@ -393,9 +272,6 @@ static int sep_req_daemon_send_reply_command_handler(struct sep_device *sep)
 		"sep_req_daemon_send_reply send_ct %lx reply_ct %lx\n",
 		sep->send_ct, sep->reply_ct);
 
-	dev_dbg(&sep->pdev->dev,
-		"sep_req_daemon_send_reply_command_handler end\n");
-
 	return 0;
 }
 
@@ -413,8 +289,6 @@ static int sep_free_dma_table_data_handler(struct sep_device *sep)
 	/* Pointer to the current dma_resource struct */
 	struct sep_dma_resource *dma;
 
-	dev_dbg(&sep->pdev->dev, "sep_free_dma_table_data_handler start\n");
-
 	for (dcb_counter = 0; dcb_counter < sep->nr_dcb_creat; dcb_counter++) {
 		dma = &sep->dma_res_arr[dcb_counter];
 
@@ -473,7 +347,6 @@ static int sep_free_dma_table_data_handler(struct sep_device *sep)
 	sep->nr_dcb_creat = 0;
 	sep->num_lli_tables_created = 0;
 
-	dev_dbg(&sep->pdev->dev, "sep_free_dma_table_data_handler end\n");
 	return 0;
 }
 
@@ -492,8 +365,6 @@ static int sep_request_daemon_mmap(struct file  *filp,
 	dma_addr_t bus_address;
 	int error = 0;
 
-	dev_dbg(&sep->pdev->dev, "daemon mmap start\n");
-
 	if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
 		error = -EINVAL;
 		goto end_function;
@@ -502,9 +373,6 @@ static int sep_request_daemon_mmap(struct file  *filp,
 	/* Get physical address */
 	bus_address = sep->shared_bus;
 
-	dev_dbg(&sep->pdev->dev, "bus_address is %08lx\n",
-					(unsigned long)bus_address);
-
 	if (remap_pfn_range(vma, vma->vm_start, bus_address >> PAGE_SHIFT,
 		vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
 
@@ -514,7 +382,6 @@ static int sep_request_daemon_mmap(struct file  *filp,
 	}
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "daemon mmap end\n");
 	return error;
 }
 
@@ -535,8 +402,6 @@ static unsigned int sep_request_daemon_poll(struct file *filp,
 	unsigned long lck_flags;
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "daemon poll: start\n");
-
 	poll_wait(filp, &sep->event_request_daemon, wait);
 
 	dev_dbg(&sep->pdev->dev, "daemon poll: send_ct is %lx reply ct is %lx\n",
@@ -569,7 +434,6 @@ static unsigned int sep_request_daemon_poll(struct file *filp,
 		mask = 0;
 	}
 end_function:
-	dev_dbg(&sep->pdev->dev, "daemon poll: exit\n");
 	return mask;
 }
 
@@ -592,7 +456,6 @@ static int sep_release(struct inode *inode, struct file *filp)
 	 * clear the in use flags, and then wake up sep_event
 	 * so that other processes can do transactions
 	 */
-	dev_dbg(&sep->pdev->dev, "waking up event and mmap_event\n");
 	if (sep->pid_doing_transaction == current->pid) {
 		clear_bit(SEP_MMAP_LOCK_BIT, &sep->in_use_flags);
 		clear_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags);
@@ -618,8 +481,6 @@ static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
 	struct sep_device *sep = filp->private_data;
 	unsigned long error = 0;
 
-	dev_dbg(&sep->pdev->dev, "mmap start\n");
-
 	/* Set the transaction busy (own the device) */
 	wait_event_interruptible(sep->event,
 		test_and_set_bit(SEP_MMAP_LOCK_BIT,
@@ -661,16 +522,12 @@ static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
 	/* Get bus address */
 	bus_addr = sep->shared_bus;
 
-	dev_dbg(&sep->pdev->dev,
-		"bus_address is %lx\n", (unsigned long)bus_addr);
-
 	if (remap_pfn_range(vma, vma->vm_start, bus_addr >> PAGE_SHIFT,
 		vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
 		dev_warn(&sep->pdev->dev, "remap_page_range failed\n");
 		error = -EAGAIN;
 		goto end_function_with_error;
 	}
-	dev_dbg(&sep->pdev->dev, "mmap end\n");
 	goto end_function;
 
 end_function_with_error:
@@ -682,7 +539,6 @@ end_function_with_error:
 
 	/* Raise event for stuck contextes */
 
-	dev_warn(&sep->pdev->dev, "mmap error - waking up event\n");
 	wake_up(&sep->event);
 
 end_function:
@@ -706,12 +562,10 @@ static unsigned int sep_poll(struct file *filp, poll_table *wait)
 
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "poll: start\n");
-
 	/* Am I the process that owns the transaction? */
 	mutex_lock(&sep->sep_mutex);
 	if (current->pid != sep->pid_doing_transaction) {
-		dev_warn(&sep->pdev->dev, "poll; wrong pid\n");
+		dev_dbg(&sep->pdev->dev, "poll; wrong pid\n");
 		mask = POLLERR;
 		mutex_unlock(&sep->sep_mutex);
 		goto end_function;
@@ -720,7 +574,6 @@ static unsigned int sep_poll(struct file *filp, poll_table *wait)
 
 	/* Check if send command or send_reply were activated previously */
 	if (!test_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags)) {
-		dev_warn(&sep->pdev->dev, "poll; lock bit set\n");
 		mask = POLLERR;
 		goto end_function;
 	}
@@ -777,7 +630,6 @@ static unsigned int sep_poll(struct file *filp, poll_table *wait)
 	}
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "poll: end\n");
 	return mask;
 }
 
@@ -806,8 +658,6 @@ static unsigned long sep_set_time(struct sep_device *sep)
 	u32 *time_addr;	/* Address of time as seen by the kernel */
 
 
-	dev_dbg(&sep->pdev->dev, "sep_set_time start\n");
-
 	do_gettimeofday(&time);
 
 	/* Set value in the SYSTEM MEMORY offset */
@@ -838,16 +688,14 @@ static int sep_set_caller_id_handler(struct sep_device *sep, unsigned long arg)
 	int   i;
 	struct caller_id_struct command_args;
 
-	dev_dbg(&sep->pdev->dev, "sep_set_caller_id_handler start\n");
-
 	for (i = 0; i < SEP_CALLER_ID_TABLE_NUM_ENTRIES; i++) {
 		if (sep->caller_id_table[i].pid == 0)
 			break;
 	}
 
 	if (i == SEP_CALLER_ID_TABLE_NUM_ENTRIES) {
-		dev_warn(&sep->pdev->dev, "no more caller id entries left\n");
-		dev_warn(&sep->pdev->dev, "maximum number is %d\n",
+		dev_dbg(&sep->pdev->dev, "no more caller id entries left\n");
+		dev_dbg(&sep->pdev->dev, "maximum number is %d\n",
 					SEP_CALLER_ID_TABLE_NUM_ENTRIES);
 		error = -EUSERS;
 		goto end_function;
@@ -883,7 +731,6 @@ static int sep_set_caller_id_handler(struct sep_device *sep, unsigned long arg)
 		hash, command_args.callerIdSizeInBytes))
 		error = -EFAULT;
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_set_caller_id_handler end\n");
 	return error;
 }
 
@@ -899,9 +746,6 @@ static int sep_set_current_caller_id(struct sep_device *sep)
 	int i;
 	u32 *hash_buf_ptr;
 
-	dev_dbg(&sep->pdev->dev, "sep_set_current_caller_id start\n");
-	dev_dbg(&sep->pdev->dev, "current process is %d\n", current->pid);
-
 	/* Zero the previous value */
 	memset(sep->shared_addr + SEP_CALLER_ID_OFFSET_BYTES,
 					0, SEP_CALLER_ID_HASH_SIZE_IN_BYTES);
@@ -923,7 +767,6 @@ static int sep_set_current_caller_id(struct sep_device *sep)
 	for (i = 0; i < SEP_CALLER_ID_HASH_SIZE_IN_WORDS; i++)
 		hash_buf_ptr[i] = cpu_to_le32(hash_buf_ptr[i]);
 
-	dev_dbg(&sep->pdev->dev, "sep_set_current_caller_id end\n");
 	return 0;
 }
 
@@ -941,8 +784,6 @@ static int sep_send_command_handler(struct sep_device *sep)
 	unsigned long lck_flags;
 	int error = 0;
 
-	dev_dbg(&sep->pdev->dev, "sep_send_command_handler start\n");
-
 	if (test_and_set_bit(SEP_SEND_MSG_LOCK_BIT, &sep->in_use_flags)) {
 		error = -EPROTO;
 		goto end_function;
@@ -966,7 +807,6 @@ static int sep_send_command_handler(struct sep_device *sep)
 	sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x2);
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_send_command_handler end\n");
 	return error;
 }
 
@@ -990,9 +830,6 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
 	/* Holds the allocated buffer address in the system memory pool */
 	u32 *token_addr;
 
-	dev_dbg(&sep->pdev->dev,
-		"sep_allocate_data_pool_memory_handler start\n");
-
 	if (copy_from_user(&command_args, (void __user *)arg,
 					sizeof(struct alloc_struct))) {
 		error = -EFAULT;
@@ -1007,33 +844,23 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
 	}
 
 	dev_dbg(&sep->pdev->dev,
-		"bytes_allocated: %x\n", (int)sep->data_pool_bytes_allocated);
+		"data pool bytes_allocated: %x\n", (int)sep->data_pool_bytes_allocated);
 	dev_dbg(&sep->pdev->dev,
 		"offset: %x\n", SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES);
 	/* Set the virtual and bus address */
 	command_args.offset = SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
 		sep->data_pool_bytes_allocated;
 
-	dev_dbg(&sep->pdev->dev,
-		"command_args.offset: %x\n", command_args.offset);
-
 	/* Place in the shared area that is known by the SEP */
 	token_addr = (u32 *)(sep->shared_addr +
 		SEP_DRIVER_DATA_POOL_ALLOCATION_OFFSET_IN_BYTES +
 		(sep->num_of_data_allocations)*2*sizeof(u32));
 
-	dev_dbg(&sep->pdev->dev, "allocation offset: %x\n",
-		SEP_DRIVER_DATA_POOL_ALLOCATION_OFFSET_IN_BYTES);
-	dev_dbg(&sep->pdev->dev, "data pool token addr is %p\n", token_addr);
-
 	token_addr[0] = SEP_DATA_POOL_POINTERS_VAL_TOKEN;
 	token_addr[1] = (u32)sep->shared_bus +
 		SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES +
 		sep->data_pool_bytes_allocated;
 
-	dev_dbg(&sep->pdev->dev, "data pool token [0] %x\n", token_addr[0]);
-	dev_dbg(&sep->pdev->dev, "data pool token [1] %x\n", token_addr[1]);
-
 	/* Write the memory back to the user space */
 	error = copy_to_user((void *)arg, (void *)&command_args,
 		sizeof(struct alloc_struct));
@@ -1046,13 +873,7 @@ static int sep_allocate_data_pool_memory_handler(struct sep_device *sep,
 	sep->data_pool_bytes_allocated += command_args.num_bytes;
 	sep->num_of_data_allocations += 1;
 
-	dev_dbg(&sep->pdev->dev, "data_allocations %d\n",
-		sep->num_of_data_allocations);
-	dev_dbg(&sep->pdev->dev, "bytes allocated  %d\n",
-		(int)sep->data_pool_bytes_allocated);
-
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_allocate_data_pool_memory_handler end\n");
 	return error;
 }
 
@@ -1083,8 +904,7 @@ static int sep_lock_kernel_pages(struct sep_device *sep,
 	/* Map array */
 	struct sep_dma_map *map_array;
 
-	dev_dbg(&sep->pdev->dev, "sep_lock_kernel_pages start\n");
-	dev_dbg(&sep->pdev->dev, "kernel_virt_addr is %08lx\n",
+	dev_dbg(&sep->pdev->dev, "lock kernel pages kernel_virt_addr is %08lx\n",
 				(unsigned long)kernel_virt_addr);
 	dev_dbg(&sep->pdev->dev, "data_size is %x\n", data_size);
 
@@ -1137,7 +957,6 @@ end_function_with_error:
 	kfree(lli_array);
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_lock_kernel_pages end\n");
 	return error;
 }
 
@@ -1179,21 +998,17 @@ static int sep_lock_user_pages(struct sep_device *sep,
 	/* Direction of the DMA mapping for locked pages */
 	enum dma_data_direction	dir;
 
-	dev_dbg(&sep->pdev->dev, "sep_lock_user_pages start\n");
-
 	/* Set start and end pages  and num pages */
 	end_page = (app_virt_addr + data_size - 1) >> PAGE_SHIFT;
 	start_page = app_virt_addr >> PAGE_SHIFT;
 	num_pages = end_page - start_page + 1;
 
-	dev_dbg(&sep->pdev->dev, "app_virt_addr is %x\n", app_virt_addr);
+	dev_dbg(&sep->pdev->dev, "lock user pages app_virt_addr is %x\n", app_virt_addr);
 	dev_dbg(&sep->pdev->dev, "data_size is %x\n", data_size);
 	dev_dbg(&sep->pdev->dev, "start_page is %x\n", start_page);
 	dev_dbg(&sep->pdev->dev, "end_page is %x\n", end_page);
 	dev_dbg(&sep->pdev->dev, "num_pages is %x\n", num_pages);
 
-	dev_dbg(&sep->pdev->dev, "starting page_array malloc\n");
-
 	/* Allocate array of pages structure pointers */
 	page_array = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC);
 	if (!page_array) {
@@ -1216,8 +1031,6 @@ static int sep_lock_user_pages(struct sep_device *sep,
 		goto end_function_with_error2;
 	}
 
-	dev_dbg(&sep->pdev->dev, "starting get_user_pages\n");
-
 	/* Convert the application virtual address into a set of physical */
 	down_read(&current->mm->mmap_sem);
 	result = get_user_pages(current, current->mm, app_virt_addr,
@@ -1324,7 +1137,6 @@ end_function_with_error1:
 	kfree(page_array);
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_lock_user_pages end\n");
 	return error;
 }
 
@@ -1395,8 +1207,6 @@ static u32 sep_calculate_lli_table_max_size(struct sep_device *sep,
 		table_data_size -= (SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE -
 			next_table_data_size);
 
-	dev_dbg(&sep->pdev->dev, "table data size is %x\n",
-							table_data_size);
 end_function:
 	return table_data_size;
 }
@@ -1425,14 +1235,12 @@ static void sep_build_lli_table(struct sep_device *sep,
 	/* Counter of lli array entry */
 	u32 array_counter;
 
-	dev_dbg(&sep->pdev->dev, "sep_build_lli_table start\n");
-
 	/* Init currrent table data size and lli array entry counter */
 	curr_table_data_size = 0;
 	array_counter = 0;
 	*num_table_entries_ptr = 1;
 
-	dev_dbg(&sep->pdev->dev, "table_data_size is %x\n", table_data_size);
+	dev_dbg(&sep->pdev->dev, "build lli table table_data_size is %x\n", table_data_size);
 
 	/* Fill the table till table size reaches the needed amount */
 	while (curr_table_data_size < table_data_size) {
@@ -1489,19 +1297,9 @@ static void sep_build_lli_table(struct sep_device *sep,
 	lli_table_ptr->bus_address = 0xffffffff;
 	lli_table_ptr->block_size = 0;
 
-	dev_dbg(&sep->pdev->dev, "lli_table_ptr is %p\n", lli_table_ptr);
-	dev_dbg(&sep->pdev->dev, "lli_table_ptr->bus_address is %08lx\n",
-				(unsigned long)lli_table_ptr->bus_address);
-	dev_dbg(&sep->pdev->dev, "lli_table_ptr->block_size is %x\n",
-						lli_table_ptr->block_size);
-
 	/* Set the output parameter */
 	*num_processed_entries_ptr += array_counter;
 
-	dev_dbg(&sep->pdev->dev, "num_processed_entries_ptr is %x\n",
-		*num_processed_entries_ptr);
-
-	dev_dbg(&sep->pdev->dev, "sep_build_lli_table end\n");
 }
 
 /**
@@ -1631,8 +1429,6 @@ static void sep_prepare_empty_lli_table(struct sep_device *sep,
 {
 	struct sep_lli_entry *lli_table_ptr;
 
-	dev_dbg(&sep->pdev->dev, "sep_prepare_empty_lli_table start\n");
-
 	/* Find the area for new table */
 	lli_table_ptr =
 		(struct sep_lli_entry *)(sep->shared_addr +
@@ -1660,9 +1456,6 @@ static void sep_prepare_empty_lli_table(struct sep_device *sep,
 
 	/* Update the number of created tables */
 	sep->num_lli_tables_created++;
-
-	dev_dbg(&sep->pdev->dev, "sep_prepare_empty_lli_table start\n");
-
 }
 
 /**
@@ -1709,8 +1502,7 @@ static int sep_prepare_input_dma_table(struct sep_device *sep,
 	/* Next table address */
 	void *lli_table_alloc_addr = 0;
 
-	dev_dbg(&sep->pdev->dev, "sep_prepare_input_dma_table start\n");
-	dev_dbg(&sep->pdev->dev, "data_size is %x\n", data_size);
+	dev_dbg(&sep->pdev->dev, "prepare intput dma table data_size is %x\n", data_size);
 	dev_dbg(&sep->pdev->dev, "block_size is %x\n", block_size);
 
 	/* Initialize the pages pointers */
@@ -1842,7 +1634,6 @@ end_function_error:
 	kfree(sep->dma_res_arr[sep->nr_dcb_creat].in_page_array);
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_prepare_input_dma_table end\n");
 	return error;
 
 }
@@ -1906,8 +1697,6 @@ static int sep_construct_dma_tables_from_lli(
 	/* Number of etnries in the output table */
 	u32 num_entries_out_table = 0;
 
-	dev_dbg(&sep->pdev->dev, "sep_construct_dma_tables_from_lli start\n");
-
 	/* Initiate to point after the message area */
 	lli_table_alloc_addr = (void *)(sep->shared_addr +
 		SYNCHRONIC_DMA_TABLES_AREA_OFFSET_BYTES +
@@ -1960,11 +1749,11 @@ static int sep_construct_dma_tables_from_lli(
 			&last_table_flag);
 
 		dev_dbg(&sep->pdev->dev,
-			"in_table_data_size is %x\n",
+			"construct tables from lli in_table_data_size is %x\n",
 			in_table_data_size);
 
 		dev_dbg(&sep->pdev->dev,
-			"out_table_data_size is %x\n",
+			"construct tables from lli out_table_data_size is %x\n",
 			out_table_data_size);
 
 		table_data_size = in_table_data_size;
@@ -1986,9 +1775,6 @@ static int sep_construct_dma_tables_from_lli(
 				block_size;
 		}
 
-		dev_dbg(&sep->pdev->dev, "table_data_size is %x\n",
-							table_data_size);
-
 		/* Construct input lli table */
 		sep_build_lli_table(sep, &lli_in_array[current_in_entry],
 			in_lli_table_ptr,
@@ -2085,7 +1871,6 @@ static int sep_construct_dma_tables_from_lli(
 	*out_num_entries_ptr,
 	*table_data_size_ptr);
 
-	dev_dbg(&sep->pdev->dev, "sep_construct_dma_tables_from_lli end\n");
 	return 0;
 }
 
@@ -2127,8 +1912,6 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 	/* Array of pointers of page */
 	struct sep_lli_entry *lli_out_array;
 
-	dev_dbg(&sep->pdev->dev, "sep_prepare_input_output_dma_table start\n");
-
 	if (data_size == 0) {
 		/* Prepare empty table for input and output */
 		sep_prepare_empty_lli_table(sep, lli_table_in_ptr,
@@ -2184,7 +1967,7 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 		}
 	}
 
-	dev_dbg(&sep->pdev->dev, "sep_in_num_pages is %x\n",
+	dev_dbg(&sep->pdev->dev, "prep input output dma table sep_in_num_pages is %x\n",
 		sep->dma_res_arr[sep->nr_dcb_creat].in_num_pages);
 	dev_dbg(&sep->pdev->dev, "sep_out_num_pages is %x\n",
 		sep->dma_res_arr[sep->nr_dcb_creat].out_num_pages);
@@ -2211,13 +1994,6 @@ static int sep_prepare_input_output_dma_table(struct sep_device *sep,
 update_dcb_counter:
 	/* Update DCB counter */
 	sep->nr_dcb_creat++;
-	/* Fall through - free the lli entry arrays */
-	dev_dbg(&sep->pdev->dev, "in_num_entries_ptr is %08x\n",
-						*in_num_entries_ptr);
-	dev_dbg(&sep->pdev->dev, "out_num_entries_ptr is %08x\n",
-						*out_num_entries_ptr);
-	dev_dbg(&sep->pdev->dev, "table_data_size_ptr is %08x\n",
-						*table_data_size_ptr);
 
 	goto end_function;
 
@@ -2233,8 +2009,6 @@ end_function_free_lli_in:
 	kfree(lli_in_array);
 
 end_function:
-	dev_dbg(&sep->pdev->dev,
-		"sep_prepare_input_output_dma_table end result = %d\n", error);
 
 	return error;
 
@@ -2281,8 +2055,6 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 	/* Data in the first input/output table */
 	u32  first_data_size = 0;
 
-	dev_dbg(&sep->pdev->dev, "prepare_input_output_dma_table_in_dcb start\n");
-
 	if (sep->nr_dcb_creat == SEP_MAX_NUM_SYNC_DMA_OPS) {
 		/* No more DCBs to allocate */
 		dev_warn(&sep->pdev->dev, "no more DCBs available\n");
@@ -2306,22 +2078,6 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 	dcb_table_ptr->out_vr_tail_pt = 0;
 
 	if (isapplet == true) {
-		tail_size = data_in_size % block_size;
-		if (tail_size) {
-			if (data_in_size < tail_block_size) {
-				dev_warn(&sep->pdev->dev, "data in size smaller than tail block size\n");
-				error = -ENOSPC;
-				goto end_function;
-			}
-			if (tail_block_size)
-				/*
-				 * Case the tail size should be
-				 * bigger than the real block size
-				 */
-				tail_size = tail_block_size +
-					((data_in_size -
-						tail_block_size) % block_size);
-		}
 
 		/* Check if there is enough data for DMA operation */
 		if (data_in_size < SEP_DRIVER_MIN_DATA_SIZE_PER_TABLE) {
@@ -2342,7 +2098,7 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 			/* Set the output user-space address for mem2mem op */
 			if (app_out_address)
 				dcb_table_ptr->out_vr_tail_pt =
-							(u32)app_out_address;
+							(aligned_u64)app_out_address;
 
 			/*
 			 * Update both data length parameters in order to avoid
@@ -2351,6 +2107,17 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 			 */
 			tail_size = 0x0;
 			data_in_size = 0x0;
+
+		} else {
+			if (!app_out_address) {
+				tail_size = data_in_size % block_size;
+				if (!tail_size) {
+					if (tail_block_size == block_size)
+						tail_size = block_size;
+				}
+			} else {
+				tail_size = 0;
+			}
 		}
 		if (tail_size) {
 			if (is_kva == true) {
@@ -2372,7 +2139,7 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 				 * according to tail data size
 				 */
 				dcb_table_ptr->out_vr_tail_pt =
-					(u32)app_out_address + data_in_size
+					(aligned_u64)app_out_address + data_in_size
 					- tail_size;
 
 			/* Save the real tail data size */
@@ -2424,68 +2191,10 @@ static int sep_prepare_input_output_dma_table_in_dcb(struct sep_device *sep,
 	dcb_table_ptr->output_mlli_data_size = first_data_size;
 
 end_function:
-	dev_dbg(&sep->pdev->dev,
-		"sep_prepare_input_output_dma_table_in_dcb end\n");
 	return error;
 
 }
 
-
-/**
- *	sep_create_sync_dma_tables_handler - create sync DMA tables
- *	@sep: pointer to struct sep_device
- *	@arg: pointer to struct bld_syn_tab_struct
- *
- *	Handle the request for creation of the DMA tables for the synchronic
- *	symmetric operations (AES,DES). Note that all bus addresses that are
- *	passed to the SEP are in 32 bit format; the SEP is a 32 bit device
- */
-static int sep_create_sync_dma_tables_handler(struct sep_device *sep,
-						unsigned long arg)
-{
-	int error = 0;
-
-	/* Command arguments */
-	struct bld_syn_tab_struct command_args;
-
-	dev_dbg(&sep->pdev->dev,
-		"sep_create_sync_dma_tables_handler start\n");
-
-	if (copy_from_user(&command_args, (void __user *)arg,
-					sizeof(struct bld_syn_tab_struct))) {
-		error = -EFAULT;
-		goto end_function;
-	}
-
-	dev_dbg(&sep->pdev->dev, "app_in_address is %08llx\n",
-						command_args.app_in_address);
-	dev_dbg(&sep->pdev->dev, "app_out_address is %08llx\n",
-						command_args.app_out_address);
-	dev_dbg(&sep->pdev->dev, "data_size is %u\n",
-						command_args.data_in_size);
-	dev_dbg(&sep->pdev->dev, "block_size is %u\n",
-						command_args.block_size);
-
-	/* Validate user parameters */
-	if (!command_args.app_in_address) {
-		error = -EINVAL;
-		goto end_function;
-	}
-
-	error = sep_prepare_input_output_dma_table_in_dcb(sep,
-		(unsigned long)command_args.app_in_address,
-		(unsigned long)command_args.app_out_address,
-		command_args.data_in_size,
-		command_args.block_size,
-		0x0,
-		false,
-		false);
-
-end_function:
-	dev_dbg(&sep->pdev->dev, "sep_create_sync_dma_tables_handler end\n");
-	return error;
-}
-
 /**
  *	sep_free_dma_tables_and_dcb - free DMA tables and DCBs
  *	@sep: pointer to struct sep_device
@@ -2504,8 +2213,6 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet,
 	unsigned long pt_hold;
 	void *tail_pt;
 
-	dev_dbg(&sep->pdev->dev, "sep_free_dma_tables_and_dcb start\n");
-
 	if (isapplet == true) {
 		/* Set pointer to first DCB table */
 		dcb_table_ptr = (struct sep_dcblock *)
@@ -2538,7 +2245,6 @@ static int sep_free_dma_tables_and_dcb(struct sep_device *sep, bool isapplet,
 	/* Free the output pages, if any */
 	sep_free_dma_table_data_handler(sep);
 
-	dev_dbg(&sep->pdev->dev, "sep_free_dma_tables_and_dcb end\n");
 	return error;
 }
 
@@ -2552,8 +2258,6 @@ static int sep_get_static_pool_addr_handler(struct sep_device *sep)
 {
 	u32 *static_pool_addr = NULL;
 
-	dev_dbg(&sep->pdev->dev, "sep_get_static_pool_addr_handler start\n");
-
 	static_pool_addr = (u32 *)(sep->shared_addr +
 		SEP_DRIVER_SYSTEM_RAR_MEMORY_OFFSET_IN_BYTES);
 
@@ -2561,223 +2265,13 @@ static int sep_get_static_pool_addr_handler(struct sep_device *sep)
 	static_pool_addr[1] = (u32)sep->shared_bus +
 		SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES;
 
-	dev_dbg(&sep->pdev->dev, "static pool: physical %x\n",
+	dev_dbg(&sep->pdev->dev, "static pool segment: physical %x\n",
 		(u32)static_pool_addr[1]);
 
-	dev_dbg(&sep->pdev->dev, "sep_get_static_pool_addr_handler end\n");
-
 	return 0;
 }
 
 /**
- *	sep_start_handler - start device
- *	@sep: pointer to struct sep_device
- */
-static int sep_start_handler(struct sep_device *sep)
-{
-	unsigned long reg_val;
-	unsigned long error = 0;
-
-	dev_dbg(&sep->pdev->dev, "sep_start_handler start\n");
-
-	/* Wait in polling for message from SEP */
-	do {
-		reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-	} while (!reg_val);
-
-	/* Check the value */
-	if (reg_val == 0x1)
-		/* Fatal error - read error status from GPRO */
-		error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
-	dev_dbg(&sep->pdev->dev, "sep_start_handler end\n");
-	return error;
-}
-
-/**
- *	ep_check_sum_calc - checksum messages
- *	@data: buffer to checksum
- *	@length: buffer size
- *
- *	This function performs a checksum for messages that are sent
- *	to the SEP.
- */
-static u32 sep_check_sum_calc(u8 *data, u32 length)
-{
-	u32 sum = 0;
-	u16 *Tdata = (u16 *)data;
-
-	while (length > 1) {
-		/*  This is the inner loop */
-		sum += *Tdata++;
-		length -= 2;
-	}
-
-	/*  Add left-over byte, if any */
-	if (length > 0)
-		sum += *(u8 *)Tdata;
-
-	/*  Fold 32-bit sum to 16 bits */
-	while (sum>>16)
-		sum = (sum & 0xffff) + (sum >> 16);
-
-	return ~sum & 0xFFFF;
-}
-
-/**
- *	sep_init_handler -
- *	@sep: pointer to struct sep_device
- *	@arg: parameters from user space application
- *
- *	Handles the request for SEP initialization
- *	Note that this will go away for Medfield once the SCU
- *	SEP initialization is complete
- *	Also note that the message to the SEP has components
- *	from user space as well as components written by the driver
- *	This is becuase the portions of the message that pertain to
- *	physical addresses must be set by the driver after the message
- *	leaves custody of the user space application for security
- *	reasons.
- */
-static int sep_init_handler(struct sep_device *sep, unsigned long arg)
-{
-	u32 message_buff[14];
-	u32 counter;
-	int error = 0;
-	u32 reg_val;
-	dma_addr_t new_base_addr;
-	unsigned long addr_hold;
-	struct init_struct command_args;
-
-	dev_dbg(&sep->pdev->dev, "sep_init_handler start\n");
-
-	/* Make sure that we have not initialized already */
-	reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-
-	if (reg_val != 0x2) {
-		error = SEP_ALREADY_INITIALIZED_ERR;
-		dev_warn(&sep->pdev->dev, "init; device already initialized\n");
-		goto end_function;
-	}
-
-	/* Only root can initialize */
-	if (!capable(CAP_SYS_ADMIN)) {
-		error = -EACCES;
-		goto end_function;
-	}
-
-	/* Copy in the parameters */
-	error = copy_from_user(&command_args, (void __user *)arg,
-		sizeof(struct init_struct));
-
-	if (error) {
-		error = -EFAULT;
-		goto end_function;
-	}
-
-	/* Validate parameters */
-	if (!command_args.message_addr || !command_args.sep_sram_addr ||
-		command_args.message_size_in_words > 14) {
-		error = -EINVAL;
-		goto end_function;
-	}
-
-	/* Copy in the SEP init message */
-	addr_hold = (unsigned long)command_args.message_addr;
-	error = copy_from_user(message_buff,
-		(void __user *)addr_hold,
-		command_args.message_size_in_words*sizeof(u32));
-
-	if (error) {
-		error = -EFAULT;
-		goto end_function;
-	}
-
-	/* Load resident, cache, and extapp firmware */
-	error = sep_load_firmware(sep);
-
-	if (error) {
-		dev_warn(&sep->pdev->dev,
-			"init; copy SEP init message failed %x\n", error);
-		goto end_function;
-	}
-
-	/* Compute the base address */
-	new_base_addr = sep->shared_bus;
-
-	if (sep->resident_bus < new_base_addr)
-		new_base_addr = sep->resident_bus;
-
-	if (sep->cache_bus < new_base_addr)
-		new_base_addr = sep->cache_bus;
-
-	if (sep->dcache_bus < new_base_addr)
-		new_base_addr = sep->dcache_bus;
-
-	/* Put physical addresses in SEP message */
-	message_buff[3] = (u32)new_base_addr;
-	message_buff[4] = (u32)sep->shared_bus;
-	message_buff[6] = (u32)sep->resident_bus;
-	message_buff[7] = (u32)sep->cache_bus;
-	message_buff[8] = (u32)sep->dcache_bus;
-
-	message_buff[command_args.message_size_in_words - 1] = 0x0;
-	message_buff[command_args.message_size_in_words - 1] =
-		sep_check_sum_calc((u8 *)message_buff,
-		command_args.message_size_in_words*sizeof(u32));
-
-	/* Debug print of message */
-	for (counter = 0; counter < command_args.message_size_in_words;
-								counter++)
-		dev_dbg(&sep->pdev->dev, "init; SEP message word %d is %x\n",
-			counter, message_buff[counter]);
-
-	/* Tell the SEP the sram address */
-	sep_write_reg(sep, HW_SRAM_ADDR_REG_ADDR, command_args.sep_sram_addr);
-
-	/* Push the message to the SEP */
-	for (counter = 0; counter < command_args.message_size_in_words;
-								counter++) {
-		sep_write_reg(sep, HW_SRAM_DATA_REG_ADDR,
-						message_buff[counter]);
-		sep_wait_sram_write(sep);
-	}
-
-	/* Signal SEP that message is ready and to init */
-	sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x1);
-
-	/* Wait for acknowledge */
-	dev_dbg(&sep->pdev->dev, "init; waiting for msg response\n");
-
-	do {
-		reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-	} while (!(reg_val & 0xFFFFFFFD));
-
-	if (reg_val == 0x1) {
-		dev_warn(&sep->pdev->dev, "init; device int failed\n");
-		error = sep_read_reg(sep, 0x8060);
-		dev_warn(&sep->pdev->dev, "init; sw monitor is %x\n", error);
-		error = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR0_REG_ADDR);
-		dev_warn(&sep->pdev->dev, "init; error is %x\n", error);
-		goto end_function;
-	}
-	dev_dbg(&sep->pdev->dev, "init; end CC INIT, reg_val is %x\n", reg_val);
-
-	/* Signal SEP to zero the GPR3 */
-	sep_write_reg(sep, HW_HOST_HOST_SEP_GPR0_REG_ADDR, 0x10);
-
-	/* Wait for response */
-	dev_dbg(&sep->pdev->dev, "init; waiting for zero set response\n");
-
-	do {
-		reg_val = sep_read_reg(sep, HW_HOST_SEP_HOST_GPR3_REG_ADDR);
-	} while (reg_val != 0);
-
-end_function:
-	dev_dbg(&sep->pdev->dev, "init is done\n");
-	return error;
-}
-
-/**
  *	sep_end_transaction_handler - end transaction
  *	@sep: pointer to struct sep_device
  *
@@ -2785,8 +2279,6 @@ end_function:
  */
 static int sep_end_transaction_handler(struct sep_device *sep)
 {
-	dev_dbg(&sep->pdev->dev, "sep_end_transaction_handler start\n");
-
 	/* Clear the data pool pointers Token */
 	memset((void *)(sep->shared_addr +
 		SEP_DRIVER_DATA_POOL_ALLOCATION_OFFSET_IN_BYTES),
@@ -2808,9 +2300,6 @@ static int sep_end_transaction_handler(struct sep_device *sep)
 	/* Raise event for stuck contextes */
 	wake_up(&sep->event);
 
-	dev_dbg(&sep->pdev->dev, "waking up event\n");
-	dev_dbg(&sep->pdev->dev, "sep_end_transaction_handler end\n");
-
 	return 0;
 }
 
@@ -2828,8 +2317,6 @@ static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg)
 	/* Command arguments */
 	struct build_dcb_struct command_args;
 
-	dev_dbg(&sep->pdev->dev, "sep_prepare_dcb_handler start\n");
-
 	/* Get the command arguments */
 	if (copy_from_user(&command_args, (void __user *)arg,
 					sizeof(struct build_dcb_struct))) {
@@ -2837,7 +2324,7 @@ static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg)
 		goto end_function;
 	}
 
-	dev_dbg(&sep->pdev->dev, "app_in_address is %08llx\n",
+	dev_dbg(&sep->pdev->dev, "prep dcb handler app_in_address is %08llx\n",
 						command_args.app_in_address);
 	dev_dbg(&sep->pdev->dev, "app_out_address is %08llx\n",
 						command_args.app_out_address);
@@ -2855,7 +2342,6 @@ static int sep_prepare_dcb_handler(struct sep_device *sep, unsigned long arg)
 		command_args.tail_block_size, true, false);
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_prepare_dcb_handler end\n");
 	return error;
 
 }
@@ -2869,15 +2355,7 @@ end_function:
  */
 static int sep_free_dcb_handler(struct sep_device *sep)
 {
-	int error ;
-
-	dev_dbg(&sep->pdev->dev, "sep_prepare_dcb_handler start\n");
-	dev_dbg(&sep->pdev->dev, "num of DCBs %x\n", sep->nr_dcb_creat);
-
-	error = sep_free_dma_tables_and_dcb(sep, false, false);
-
-	dev_dbg(&sep->pdev->dev, "sep_free_dcb_handler end\n");
-	return error;
+	return sep_free_dma_tables_and_dcb(sep, false, false);
 }
 
 /**
@@ -2900,8 +2378,6 @@ static int sep_rar_prepare_output_msg_handler(struct sep_device *sep,
 	/* Holds the RAR address in the system memory offset */
 	u32 *rar_addr;
 
-	dev_dbg(&sep->pdev->dev, "sep_rar_prepare_output_msg_handler start\n");
-
 	/* Copy the data */
 	if (copy_from_user(&command_args, (void __user *)arg,
 						sizeof(command_args))) {
@@ -2915,7 +2391,6 @@ static int sep_rar_prepare_output_msg_handler(struct sep_device *sep,
 		rar_buf.info.handle = (u32)command_args.rar_handle;
 
 		if (rar_handle_to_bus(&rar_buf, 1) != 1) {
-			dev_dbg(&sep->pdev->dev, "rar_handle_to_bus failure\n");
 			error = -EFAULT;
 			goto end_function;
 		}
@@ -2932,39 +2407,10 @@ static int sep_rar_prepare_output_msg_handler(struct sep_device *sep,
 	rar_addr[1] = rar_bus;
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "sep_rar_prepare_output_msg_handler start\n");
 	return error;
 }
 
 /**
- *	sep_realloc_ext_cache_handler - report location of extcache
- *	@sep: pointer to struct sep_device
- *	@arg: pointer to user parameters
- *
- *	This function tells the SEP where the extapp is located
- */
-static int sep_realloc_ext_cache_handler(struct sep_device *sep,
-	unsigned long arg)
-{
-	/* Holds the new ext cache address in the system memory offset */
-	u32 *system_addr;
-
-	/* Set value in the SYSTEM MEMORY offset */
-	system_addr = (u32 *)(sep->shared_addr +
-		SEP_DRIVER_SYSTEM_EXT_CACHE_ADDR_OFFSET_IN_BYTES);
-
-	/* Copy the physical address to the System Area for the SEP */
-	system_addr[0] = SEP_EXT_CACHE_ADDR_VAL_TOKEN;
-	dev_dbg(&sep->pdev->dev, "ext cache init; system addr 0 is %x\n",
-							system_addr[0]);
-	system_addr[1] = sep->extapp_bus;
-	dev_dbg(&sep->pdev->dev, "ext cache init; system addr 1 is %x\n",
-							system_addr[1]);
-
-	return 0;
-}
-
-/**
  *	sep_ioctl - ioctl api
  *	@filp: pointer to struct file
  *	@cmd: command
@@ -2977,27 +2423,19 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	int error = 0;
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "ioctl start\n");
-
-	dev_dbg(&sep->pdev->dev, "cmd is %x\n", cmd);
-
 	/* Make sure we own this device */
 	mutex_lock(&sep->sep_mutex);
 	if ((current->pid != sep->pid_doing_transaction) &&
 				(sep->pid_doing_transaction != 0)) {
 		dev_dbg(&sep->pdev->dev, "ioctl pid is not owner\n");
-		mutex_unlock(&sep->sep_mutex);
 		error = -EACCES;
 		goto end_function;
 	}
 
 	mutex_unlock(&sep->sep_mutex);
 
-	/* Check that the command is for SEP device */
-	if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) {
-		error = -ENOTTY;
-		goto end_function;
-	}
+	if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
+		return -ENOTTY;
 
 	/* Lock to prevent the daemon to interfere with operation */
 	mutex_lock(&sep->ioctl_mutex);
@@ -3011,28 +2449,6 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		/* Allocate data pool */
 		error = sep_allocate_data_pool_memory_handler(sep, arg);
 		break;
-	case SEP_IOCCREATESYMDMATABLE:
-		/* Create DMA table for synhronic operation */
-		error = sep_create_sync_dma_tables_handler(sep, arg);
-		break;
-	case SEP_IOCFREEDMATABLEDATA:
-		/* Free the pages */
-		error = sep_free_dma_table_data_handler(sep);
-		break;
-	case SEP_IOCSEPSTART:
-		/* Start command to SEP */
-		if (sep->pdev->revision == 0) /* Only for old chip */
-			error = sep_start_handler(sep);
-		else
-			error = -EPERM; /* Not permitted on new chip */
-		break;
-	case SEP_IOCSEPINIT:
-		/* Init command to SEP */
-		if (sep->pdev->revision == 0) /* Only for old chip */
-			error = sep_init_handler(sep, arg);
-		else
-			error = -EPERM; /* Not permitted on new chip */
-		break;
 	case SEP_IOCGETSTATICPOOLADDR:
 		/* Inform the SEP the bus address of the static pool */
 		error = sep_get_static_pool_addr_handler(sep);
@@ -3040,12 +2456,6 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	case SEP_IOCENDTRANSACTION:
 		error = sep_end_transaction_handler(sep);
 		break;
-	case SEP_IOCREALLOCEXTCACHE:
-		if (sep->pdev->revision == 0) /* Only for old chip */
-			error = sep_realloc_ext_cache_handler(sep, arg);
-		else
-			error = -EPERM; /* Not permitted on new chip */
-		break;
 	case SEP_IOCRARPREPAREMESSAGE:
 		error = sep_rar_prepare_output_msg_handler(sep, arg);
 		break;
@@ -3056,14 +2466,12 @@ static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		error = sep_free_dcb_handler(sep);
 		break;
 	default:
-		dev_dbg(&sep->pdev->dev, "invalid ioctl %x\n", cmd);
 		error = -ENOTTY;
 		break;
 	}
-	mutex_unlock(&sep->ioctl_mutex);
 
 end_function:
-	dev_dbg(&sep->pdev->dev, "ioctl end\n");
+	mutex_unlock(&sep->ioctl_mutex);
 	return error;
 }
 
@@ -3080,14 +2488,9 @@ static long sep_singleton_ioctl(struct file  *filp, u32 cmd, unsigned long arg)
 	long error = 0;
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "singleton_ioctl start\n");
-	dev_dbg(&sep->pdev->dev, "cmd is %x\n", cmd);
-
 	/* Check that the command is for the SEP device */
-	if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) {
-		error =  -ENOTTY;
-		goto end_function;
-	}
+	if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
+		return -ENOTTY;
 
 	/* Make sure we own this device */
 	mutex_lock(&sep->sep_mutex);
@@ -3095,8 +2498,7 @@ static long sep_singleton_ioctl(struct file  *filp, u32 cmd, unsigned long arg)
 				(sep->pid_doing_transaction != 0)) {
 		dev_dbg(&sep->pdev->dev, "singleton ioctl pid is not owner\n");
 		mutex_unlock(&sep->sep_mutex);
-		error = -EACCES;
-		goto end_function;
+		return -EACCES;
 	}
 
 	mutex_unlock(&sep->sep_mutex);
@@ -3111,9 +2513,6 @@ static long sep_singleton_ioctl(struct file  *filp, u32 cmd, unsigned long arg)
 		error = sep_ioctl(filp, cmd, arg);
 		break;
 	}
-
-end_function:
-	dev_dbg(&sep->pdev->dev, "singleton ioctl end\n");
 	return error;
 }
 
@@ -3132,14 +2531,9 @@ static long sep_request_daemon_ioctl(struct file *filp, u32 cmd,
 	long error;
 	struct sep_device *sep = filp->private_data;
 
-	dev_dbg(&sep->pdev->dev, "daemon ioctl: start\n");
-	dev_dbg(&sep->pdev->dev, "daemon ioctl: cmd is %x\n", cmd);
-
 	/* Check that the command is for SEP device */
-	if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER) {
-		error = -ENOTTY;
-		goto end_function;
-	}
+	if (_IOC_TYPE(cmd) != SEP_IOC_MAGIC_NUMBER)
+		return -ENOTTY;
 
 	/* Only one process can access ioctl at any given time */
 	mutex_lock(&sep->ioctl_mutex);
@@ -3158,15 +2552,10 @@ static long sep_request_daemon_ioctl(struct file *filp, u32 cmd,
 		error = 0;
 		break;
 	default:
-		dev_dbg(&sep->pdev->dev, "daemon ioctl: no such IOCTL\n");
 		error = -ENOTTY;
 	}
 	mutex_unlock(&sep->ioctl_mutex);
-
-end_function:
-	dev_dbg(&sep->pdev->dev, "daemon ioctl: end\n");
 	return error;
-
 }
 
 /**
@@ -3183,7 +2572,6 @@ static irqreturn_t sep_inthandler(int irq, void *dev_id)
 
 	/* Read the IRR register to check if this is SEP interrupt */
 	reg_val = sep_read_reg(sep, HW_HOST_IRR_REG_ADDR);
-	dev_dbg(&sep->pdev->dev, "SEP Interrupt - reg is %08x\n", reg_val);
 
 	if (reg_val & (0x1 << 13)) {
 		/* Lock and update the counter of reply messages */
@@ -3233,10 +2621,8 @@ static int sep_reconfig_shared_area(struct sep_device *sep)
 	/* use to limit waiting for SEP */
 	unsigned long end_time;
 
-	dev_dbg(&sep->pdev->dev, "reconfig shared area start\n");
-
 	/* Send the new SHARED MESSAGE AREA to the SEP */
-	dev_dbg(&sep->pdev->dev, "sending %08llx to sep\n",
+	dev_dbg(&sep->pdev->dev, "reconfig shared; sending %08llx to sep\n",
 				(unsigned long long)sep->shared_bus);
 
 	sep_write_reg(sep, HW_HOST_HOST_SEP_GPR1_REG_ADDR, sep->shared_bus);
@@ -3356,7 +2742,6 @@ static int __devinit sep_probe(struct pci_dev *pdev,
 	int error = 0;
 	struct sep_device *sep;
 
-	pr_debug("SEP pci probe starting\n");
 	if (sep_dev != NULL) {
 		dev_warn(&pdev->dev, "only one SEP supported.\n");
 		return -EBUSY;
@@ -3394,7 +2779,7 @@ static int __devinit sep_probe(struct pci_dev *pdev,
 	mutex_init(&sep->sep_mutex);
 	mutex_init(&sep->ioctl_mutex);
 
-	dev_dbg(&sep->pdev->dev, "PCI obtained, device being prepared\n");
+	dev_dbg(&sep->pdev->dev, "sep probe: PCI obtained, device being prepared\n");
 	dev_dbg(&sep->pdev->dev, "revision is %d\n", sep->pdev->revision);
 
 	/* Set up our register area */
@@ -3439,22 +2824,6 @@ static int __devinit sep_probe(struct pci_dev *pdev,
 		goto end_function_error;
 	}
 
-	sep->rar_size = FAKE_RAR_SIZE;
-	sep->rar_addr = dma_alloc_coherent(&sep->pdev->dev,
-		sep->rar_size, &sep->rar_bus, GFP_KERNEL);
-	if (sep->rar_addr == NULL) {
-		dev_warn(&sep->pdev->dev, "can't allocate mfld rar\n");
-		error = -ENOMEM;
-		goto end_function_deallocate_sep_shared_area;
-	}
-
-	dev_dbg(&sep->pdev->dev, "rar start is %p, phy is %llx,"
-		" size is %zx\n", sep->rar_addr,
-		(unsigned long long)sep->rar_bus,
-		sep->rar_size);
-
-	dev_dbg(&sep->pdev->dev, "about to write IMR and ICR REG_ADDR\n");
-
 	/* Clear ICR register */
 	sep_write_reg(sep, HW_HOST_ICR_REG_ADDR, 0xFFFFFFFF);
 
@@ -3466,15 +2835,14 @@ static int __devinit sep_probe(struct pci_dev *pdev,
 	sep->reply_ct &= 0x3FFFFFFF;
 	sep->send_ct = sep->reply_ct;
 
-	dev_dbg(&sep->pdev->dev, "about to call request_irq\n");
 	/* Get the interrupt line */
 	error = request_irq(pdev->irq, sep_inthandler, IRQF_SHARED,
 		"sep_driver", sep);
 
 	if (error)
-		goto end_function_dealloc_rar;
+		goto end_function_deallocate_sep_shared_area;
 
-	/* The new chip requires ashared area reconfigure */
+	/* The new chip requires a shared area reconfigure */
 	if (sep->pdev->revision == 4) { /* Only for new chip */
 		error = sep_reconfig_shared_area(sep);
 		if (error)
@@ -3490,12 +2858,6 @@ static int __devinit sep_probe(struct pci_dev *pdev,
 end_function_free_irq:
 	free_irq(pdev->irq, sep);
 
-end_function_dealloc_rar:
-	if (sep->rar_addr)
-		dma_free_coherent(&sep->pdev->dev, sep->rar_size,
-			sep->rar_addr, sep->rar_bus);
-	goto end_function;
-
 end_function_deallocate_sep_shared_area:
 	/* De-allocate shared area */
 	sep_unmap_and_free_shared_area(sep);
diff --git a/drivers/staging/sep/sep_driver_api.h b/drivers/staging/sep/sep_driver_api.h
index fbbfa23..c3aacfc 100644
--- a/drivers/staging/sep/sep_driver_api.h
+++ b/drivers/staging/sep/sep_driver_api.h
@@ -42,48 +42,6 @@
     TYPEDEFS
 ----------------------------------------------*/
 
-/*
- * Note that several members of these structres are only here
- * for campatability with the middleware; they are not used
- * by this driver.
- * All user space buffer addresses are set to aligned u64
- * in order to ensure compatibility with 64 bit systems
- */
-
-/*
-  init command struct; this will go away when SCU does init
-*/
-struct init_struct {
-	/* address that SEP can access for message */
-	aligned_u64   message_addr;
-
-	/* message size */
-	u32   message_size_in_words;
-
-	/* offset of the init message in the sep sram */
-	u32   sep_sram_addr;
-
-	/* -not used- resident size in bytes*/
-	u32   unused_resident_size_in_bytes;
-
-	/* -not used- cache size in bytes*/
-	u32   unused_cache_size_in_bytes;
-
-	/* -not used- ext cache current address */
-	aligned_u64   unused_extcache_addr;
-
-	/* -not used- ext cache size in bytes*/
-	u32   unused_extcache_size_in_bytes;
-};
-
-struct realloc_ext_struct {
-	/* -not used- current external cache address */
-	aligned_u64   unused_ext_cache_addr;
-
-	/* -not used- external cache size in bytes*/
-	u32   unused_ext_cache_size_in_bytes;
-};
-
 struct alloc_struct {
 	/* offset from start of shared pool area */
 	u32  offset;
@@ -91,29 +49,6 @@ struct alloc_struct {
 	u32  num_bytes;
 };
 
-/*
-	Note that all app addresses are cast as u32; the sep
-	middleware sends them as fixed 32 bit words
-*/
-struct bld_syn_tab_struct {
-	/* address value of the data in (user space addr) */
-	aligned_u64 app_in_address;
-
-	/* size of data in */
-	u32 data_in_size;
-
-	/* address of the data out (user space addr) */
-	aligned_u64 app_out_address;
-
-	/* the size of the block of the operation - if needed,
-	   every table will be modulo this parameter */
-	u32 block_size;
-
-	/* -not used- distinct user/kernel layout */
-	bool isKernelVirtualAddress;
-
-};
-
 /* command struct for getting caller id value and address */
 struct caller_id_struct {
 	/* pid of the process */
@@ -141,11 +76,11 @@ struct sep_dcblock {
 	/* size of data in the first output mlli */
 	u32	output_mlli_data_size;
 	/* pointer to the output virtual tail */
-	u32	out_vr_tail_pt;
+	aligned_u64 out_vr_tail_pt;
 	/* size of tail data */
 	u32	tail_data_size;
 	/* input tail data array */
-	u8	tail_data[64];
+	u8	tail_data[68];
 };
 
 struct sep_caller_id_entry {
@@ -253,10 +188,6 @@ struct sep_lli_entry {
 #define SEP_IOCALLOCDATAPOLL	\
 	_IOW(SEP_IOC_MAGIC_NUMBER, 2, struct alloc_struct)
 
-/* create sym dma lli tables */
-#define SEP_IOCCREATESYMDMATABLE	\
-	_IOW(SEP_IOC_MAGIC_NUMBER, 5, struct bld_syn_tab_struct)
-
 /* free dynamic data aalocated during table creation */
 #define SEP_IOCFREEDMATABLEDATA	 \
 	_IO(SEP_IOC_MAGIC_NUMBER, 7)
@@ -265,23 +196,10 @@ struct sep_lli_entry {
 #define SEP_IOCGETSTATICPOOLADDR	\
 	_IO(SEP_IOC_MAGIC_NUMBER, 8)
 
-/* start sep command */
-#define SEP_IOCSEPSTART	 \
-	_IO(SEP_IOC_MAGIC_NUMBER, 12)
-
-/* init sep command */
-#define SEP_IOCSEPINIT	\
-	_IOW(SEP_IOC_MAGIC_NUMBER, 13, struct init_struct)
-
 /* end transaction command */
 #define SEP_IOCENDTRANSACTION	 \
 	_IO(SEP_IOC_MAGIC_NUMBER, 15)
 
-/* reallocate external app; unused structure still needed for
- * compatability with middleware */
-#define SEP_IOCREALLOCEXTCACHE	\
-	_IOW(SEP_IOC_MAGIC_NUMBER, 18, struct realloc_ext_struct)
-
 #define SEP_IOCRARPREPAREMESSAGE	\
 	_IOW(SEP_IOC_MAGIC_NUMBER, 20, struct rar_hndl_to_bus_struct)
 
diff --git a/drivers/staging/sep/sep_driver_config.h b/drivers/staging/sep/sep_driver_config.h
index b18625d..d3b9220 100644
--- a/drivers/staging/sep/sep_driver_config.h
+++ b/drivers/staging/sep/sep_driver_config.h
@@ -76,6 +76,10 @@ held by the proccess (struct file) */
 #define SEP_REQUEST_DAEMON_MAPPED 1
 #define SEP_REQUEST_DAEMON_UNMAPPED 0
 
+#define SEP_DEV_NAME "sep_sec_driver"
+#define SEP_DEV_SINGLETON "sep_sec_singleton_driver"
+#define SEP_DEV_DAEMON "sep_req_daemon_driver"
+
 /*--------------------------------------------------------
 	SHARED AREA  memory total size is 36K
 	it is divided is following:
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 27841ef..12f5eba 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -1098,8 +1098,7 @@ static void qt_close(struct usb_serial_port *port)
 
 	if (qt_port->write_urb) {
 		/* if this urb had a transfer buffer already (old tx) free it */
-		if (qt_port->write_urb->transfer_buffer != NULL)
-			kfree(qt_port->write_urb->transfer_buffer);
+		kfree(qt_port->write_urb->transfer_buffer);
 		usb_free_urb(qt_port->write_urb);
 	}
 
@@ -1191,7 +1190,7 @@ static int qt_write_room(struct tty_struct *tty)
 
 }
 
-static int qt_ioctl(struct tty_struct *tty, struct file *file,
+static int qt_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -1383,7 +1382,7 @@ static void qt_break(struct tty_struct *tty, int break_state)
 
 static inline int qt_real_tiocmget(struct tty_struct *tty,
 				   struct usb_serial_port *port,
-				   struct file *file, struct usb_serial *serial)
+				   struct usb_serial *serial)
 {
 
 	u8 mcr;
@@ -1425,7 +1424,6 @@ static inline int qt_real_tiocmget(struct tty_struct *tty,
 
 static inline int qt_real_tiocmset(struct tty_struct *tty,
 				   struct usb_serial_port *port,
-				   struct file *file,
 				   struct usb_serial *serial,
 				   unsigned int value)
 {
@@ -1462,7 +1460,7 @@ static inline int qt_real_tiocmset(struct tty_struct *tty,
 		return 0;
 }
 
-static int qt_tiocmget(struct tty_struct *tty, struct file *file)
+static int qt_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = get_usb_serial(port, __func__);
@@ -1480,13 +1478,13 @@ static int qt_tiocmget(struct tty_struct *tty, struct file *file)
 	dbg("%s - port %d\n", __func__, port->number);
 	dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding);
 
-	retval = qt_real_tiocmget(tty, port, file, serial);
+	retval = qt_real_tiocmget(tty, port, serial);
 
 	spin_unlock_irqrestore(&qt_port->lock, flags);
 	return retval;
 }
 
-static int qt_tiocmset(struct tty_struct *tty, struct file *file,
+static int qt_tiocmset(struct tty_struct *tty,
 		       unsigned int set, unsigned int clear)
 {
 
@@ -1506,7 +1504,7 @@ static int qt_tiocmset(struct tty_struct *tty, struct file *file,
 	dbg("%s - port %d\n", __func__, port->number);
 	dbg("%s - qt_port->RxHolding = %d\n", __func__, qt_port->RxHolding);
 
-	retval = qt_real_tiocmset(tty, port, file, serial, set);
+	retval = qt_real_tiocmset(tty, port, serial, set);
 
 	spin_unlock_irqrestore(&qt_port->lock, flags);
 	return retval;
diff --git a/drivers/staging/smbfs/Kconfig b/drivers/staging/smbfs/Kconfig
deleted file mode 100644
index 2bc24a8..0000000
--- a/drivers/staging/smbfs/Kconfig
+++ /dev/null
@@ -1,56 +0,0 @@
-config SMB_FS
-	tristate "SMB file system support (OBSOLETE, please use CIFS)"
-	depends on BKL # probably unfixable
-	depends on INET
-	select NLS
-	help
-	  SMB (Server Message Block) is the protocol Windows for Workgroups
-	  (WfW), Windows 95/98, Windows NT and OS/2 Lan Manager use to share
-	  files and printers over local networks.  Saying Y here allows you to
-	  mount their file systems (often called "shares" in this context) and
-	  access them just like any other Unix directory.  Currently, this
-	  works only if the Windows machines use TCP/IP as the underlying
-	  transport protocol, and not NetBEUI.  For details, read
-	  <file:Documentation/filesystems/smbfs.txt> and the SMB-HOWTO,
-	  available from <http://www.tldp.org/docs.html#howto>.
-
-	  Note: if you just want your box to act as an SMB *server* and make
-	  files and printing services available to Windows clients (which need
-	  to have a TCP/IP stack), you don't need to say Y here; you can use
-	  the program SAMBA (available from <ftp://ftp.samba.org/pub/samba/>)
-	  for that.
-
-	  General information about how to connect Linux, Windows machines and
-	  Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
-
-	  To compile the SMB support as a module, choose M here:
-	  the module will be called smbfs.  Most people say N, however.
-
-config SMB_NLS_DEFAULT
-	bool "Use a default NLS"
-	depends on SMB_FS
-	help
-	  Enabling this will make smbfs use nls translations by default. You
-	  need to specify the local charset (CONFIG_NLS_DEFAULT) in the nls
-	  settings and you need to give the default nls for the SMB server as
-	  CONFIG_SMB_NLS_REMOTE.
-
-	  The nls settings can be changed at mount time, if your smbmount
-	  supports that, using the codepage and iocharset parameters.
-
-	  smbmount from samba 2.2.0 or later supports this.
-
-config SMB_NLS_REMOTE
-	string "Default Remote NLS Option"
-	depends on SMB_NLS_DEFAULT
-	default "cp437"
-	help
-	  This setting allows you to specify a default value for which
-	  codepage the server uses. If this field is left blank no
-	  translations will be done by default. The local codepage/charset
-	  default to CONFIG_NLS_DEFAULT.
-
-	  The nls settings can be changed at mount time, if your smbmount
-	  supports that, using the codepage and iocharset parameters.
-
-	  smbmount from samba 2.2.0 or later supports this.
diff --git a/drivers/staging/smbfs/Makefile b/drivers/staging/smbfs/Makefile
deleted file mode 100644
index d2a92c5..0000000
--- a/drivers/staging/smbfs/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux smb-filesystem routines.
-#
-
-obj-$(CONFIG_SMB_FS) += smbfs.o
-
-smbfs-y := proc.o dir.o cache.o sock.o inode.o file.o ioctl.o getopt.o \
-		symlink.o smbiod.o request.o
-
-# If you want debugging output, you may add these flags to the EXTRA_CFLAGS
-# SMBFS_PARANOIA should normally be enabled.
-
-ccflags-y := -DSMBFS_PARANOIA
-#ccflags-y += -DSMBFS_DEBUG
-#ccflags-y += -DSMBFS_DEBUG_VERBOSE
-#ccflags-y += -DDEBUG_SMB_TIMESTAMP
-#ccflags-y += -Werror
-
diff --git a/drivers/staging/smbfs/TODO b/drivers/staging/smbfs/TODO
deleted file mode 100644
index 24f4d29..0000000
--- a/drivers/staging/smbfs/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-smbfs is on its way out of the kernel, it has been replaced
-by cifs several years ago.
-
-The smbfs code uses the big kernel lock which
-is getting deprecated.
-
-Users that find smbfs to work but not cifs should contact
-the CIFS developers on linux-cifs@vger.kernel.org.
diff --git a/drivers/staging/smbfs/cache.c b/drivers/staging/smbfs/cache.c
deleted file mode 100644
index f2a1323..0000000
--- a/drivers/staging/smbfs/cache.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- *  cache.c
- *
- * Copyright (C) 1997 by Bill Hawes
- *
- * Routines to support directory cacheing using the page cache.
- * This cache code is almost directly taken from ncpfs.
- *
- * Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/net.h>
-
-#include <asm/page.h>
-
-#include "smb_fs.h"
-#include "smb_debug.h"
-#include "proto.h"
-
-/*
- * Force the next attempt to use the cache to be a timeout.
- * If we can't find the page that's fine, it will cause a refresh.
- */
-void
-smb_invalid_dir_cache(struct inode * dir)
-{
-	struct smb_sb_info *server = server_from_inode(dir);
-	union  smb_dir_cache *cache = NULL;
-	struct page *page = NULL;
-
-	page = grab_cache_page(&dir->i_data, 0);
-	if (!page)
-		goto out;
-
-	if (!PageUptodate(page))
-		goto out_unlock;
-
-	cache = kmap(page);
-	cache->head.time = jiffies - SMB_MAX_AGE(server);
-
-	kunmap(page);
-	SetPageUptodate(page);
-out_unlock:
-	unlock_page(page);
-	page_cache_release(page);
-out:
-	return;
-}
-
-/*
- * Mark all dentries for 'parent' as invalid, forcing them to be re-read
- */
-void
-smb_invalidate_dircache_entries(struct dentry *parent)
-{
-	struct smb_sb_info *server = server_from_dentry(parent);
-	struct list_head *next;
-	struct dentry *dentry;
-
-	spin_lock(&parent->d_lock);
-	next = parent->d_subdirs.next;
-	while (next != &parent->d_subdirs) {
-		dentry = list_entry(next, struct dentry, d_u.d_child);
-		dentry->d_fsdata = NULL;
-		smb_age_dentry(server, dentry);
-		next = next->next;
-	}
-	spin_unlock(&parent->d_lock);
-}
-
-/*
- * dget, but require that fpos and parent matches what the dentry contains.
- * dentry is not known to be a valid pointer at entry.
- */
-struct dentry *
-smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
-{
-	struct dentry *dent = dentry;
-	struct list_head *next;
-
-	if (d_validate(dent, parent)) {
-		if (dent->d_name.len <= SMB_MAXNAMELEN &&
-		    (unsigned long)dent->d_fsdata == fpos) {
-			if (!dent->d_inode) {
-				dput(dent);
-				dent = NULL;
-			}
-			return dent;
-		}
-		dput(dent);
-	}
-
-	/* If a pointer is invalid, we search the dentry. */
-	spin_lock(&parent->d_lock);
-	next = parent->d_subdirs.next;
-	while (next != &parent->d_subdirs) {
-		dent = list_entry(next, struct dentry, d_u.d_child);
-		if ((unsigned long)dent->d_fsdata == fpos) {
-			if (dent->d_inode)
-				dget(dent);
-			else
-				dent = NULL;
-			goto out_unlock;
-		}
-		next = next->next;
-	}
-	dent = NULL;
-out_unlock:
-	spin_unlock(&parent->d_lock);
-	return dent;
-}
-
-
-/*
- * Create dentry/inode for this file and add it to the dircache.
- */
-int
-smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
-	       struct smb_cache_control *ctrl, struct qstr *qname,
-	       struct smb_fattr *entry)
-{
-	struct dentry *newdent, *dentry = filp->f_path.dentry;
-	struct inode *newino, *inode = dentry->d_inode;
-	struct smb_cache_control ctl = *ctrl;
-	int valid = 0;
-	int hashed = 0;
-	ino_t ino = 0;
-
-	qname->hash = full_name_hash(qname->name, qname->len);
-
-	if (dentry->d_op && dentry->d_op->d_hash)
-		if (dentry->d_op->d_hash(dentry, inode, qname) != 0)
-			goto end_advance;
-
-	newdent = d_lookup(dentry, qname);
-
-	if (!newdent) {
-		newdent = d_alloc(dentry, qname);
-		if (!newdent)
-			goto end_advance;
-	} else {
-		hashed = 1;
-		/* dir i_mutex is locked because we're in readdir */
-		dentry_update_name_case(newdent, qname);
-	}
-
-	if (!newdent->d_inode) {
-		smb_renew_times(newdent);
-		entry->f_ino = iunique(inode->i_sb, 2);
-		newino = smb_iget(inode->i_sb, entry);
-		if (newino) {
-			smb_new_dentry(newdent);
-			d_instantiate(newdent, newino);
-			if (!hashed)
-				d_rehash(newdent);
-		}
-	} else
-		smb_set_inode_attr(newdent->d_inode, entry);
-
-        if (newdent->d_inode) {
-		ino = newdent->d_inode->i_ino;
-		newdent->d_fsdata = (void *) ctl.fpos;
-		smb_new_dentry(newdent);
-	}
-
-	if (ctl.idx >= SMB_DIRCACHE_SIZE) {
-		if (ctl.page) {
-			kunmap(ctl.page);
-			SetPageUptodate(ctl.page);
-			unlock_page(ctl.page);
-			page_cache_release(ctl.page);
-		}
-		ctl.cache = NULL;
-		ctl.idx  -= SMB_DIRCACHE_SIZE;
-		ctl.ofs  += 1;
-		ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
-		if (ctl.page)
-			ctl.cache = kmap(ctl.page);
-	}
-	if (ctl.cache) {
-		ctl.cache->dentry[ctl.idx] = newdent;
-		valid = 1;
-	}
-	dput(newdent);
-
-end_advance:
-	if (!valid)
-		ctl.valid = 0;
-	if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
-		if (!ino)
-			ino = find_inode_number(dentry, qname);
-		if (!ino)
-			ino = iunique(inode->i_sb, 2);
-		ctl.filled = filldir(dirent, qname->name, qname->len,
-				     filp->f_pos, ino, DT_UNKNOWN);
-		if (!ctl.filled)
-			filp->f_pos += 1;
-	}
-	ctl.fpos += 1;
-	ctl.idx  += 1;
-	*ctrl = ctl;
-	return (ctl.valid || !ctl.filled);
-}
diff --git a/drivers/staging/smbfs/dir.c b/drivers/staging/smbfs/dir.c
deleted file mode 100644
index f204d33..0000000
--- a/drivers/staging/smbfs/dir.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- *  dir.c
- *
- *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/smp_lock.h>
-#include <linux/ctype.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/namei.h>
-
-#include "smb_fs.h"
-#include "smb_mount.h"
-#include "smbno.h"
-
-#include "smb_debug.h"
-#include "proto.h"
-
-static int smb_readdir(struct file *, void *, filldir_t);
-static int smb_dir_open(struct inode *, struct file *);
-
-static struct dentry *smb_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int smb_create(struct inode *, struct dentry *, int, struct nameidata *);
-static int smb_mkdir(struct inode *, struct dentry *, int);
-static int smb_rmdir(struct inode *, struct dentry *);
-static int smb_unlink(struct inode *, struct dentry *);
-static int smb_rename(struct inode *, struct dentry *,
-		      struct inode *, struct dentry *);
-static int smb_make_node(struct inode *,struct dentry *,int,dev_t);
-static int smb_link(struct dentry *, struct inode *, struct dentry *);
-
-const struct file_operations smb_dir_operations =
-{
-	.llseek		= generic_file_llseek,
-	.read		= generic_read_dir,
-	.readdir	= smb_readdir,
-	.unlocked_ioctl	= smb_ioctl,
-	.open		= smb_dir_open,
-};
-
-const struct inode_operations smb_dir_inode_operations =
-{
-	.create		= smb_create,
-	.lookup		= smb_lookup,
-	.unlink		= smb_unlink,
-	.mkdir		= smb_mkdir,
-	.rmdir		= smb_rmdir,
-	.rename		= smb_rename,
-	.getattr	= smb_getattr,
-	.setattr	= smb_notify_change,
-};
-
-const struct inode_operations smb_dir_inode_operations_unix =
-{
-	.create		= smb_create,
-	.lookup		= smb_lookup,
-	.unlink		= smb_unlink,
-	.mkdir		= smb_mkdir,
-	.rmdir		= smb_rmdir,
-	.rename		= smb_rename,
-	.getattr	= smb_getattr,
-	.setattr	= smb_notify_change,
-	.symlink	= smb_symlink,
-	.mknod		= smb_make_node,
-	.link		= smb_link,
-};
-
-/*
- * Read a directory, using filldir to fill the dirent memory.
- * smb_proc_readdir does the actual reading from the smb server.
- *
- * The cache code is almost directly taken from ncpfs
- */
-static int 
-smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
-	struct dentry *dentry = filp->f_path.dentry;
-	struct inode *dir = dentry->d_inode;
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	union  smb_dir_cache *cache = NULL;
-	struct smb_cache_control ctl;
-	struct page *page = NULL;
-	int result;
-
-	ctl.page  = NULL;
-	ctl.cache = NULL;
-
-	VERBOSE("reading %s/%s, f_pos=%d\n",
-		DENTRY_PATH(dentry),  (int) filp->f_pos);
-
-	result = 0;
-
-	lock_kernel();
-
-	switch ((unsigned int) filp->f_pos) {
-	case 0:
-		if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
-			goto out;
-		filp->f_pos = 1;
-		/* fallthrough */
-	case 1:
-		if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR) < 0)
-			goto out;
-		filp->f_pos = 2;
-	}
-
-	/*
-	 * Make sure our inode is up-to-date.
-	 */
-	result = smb_revalidate_inode(dentry);
-	if (result)
-		goto out;
-
-
-	page = grab_cache_page(&dir->i_data, 0);
-	if (!page)
-		goto read_really;
-
-	ctl.cache = cache = kmap(page);
-	ctl.head  = cache->head;
-
-	if (!PageUptodate(page) || !ctl.head.eof) {
-		VERBOSE("%s/%s, page uptodate=%d, eof=%d\n",
-			 DENTRY_PATH(dentry), PageUptodate(page),ctl.head.eof);
-		goto init_cache;
-	}
-
-	if (filp->f_pos == 2) {
-		if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
-			goto init_cache;
-
-		/*
-		 * N.B. ncpfs checks mtime of dentry too here, we don't.
-		 *   1. common smb servers do not update mtime on dir changes
-		 *   2. it requires an extra smb request
-		 *      (revalidate has the same timeout as ctl.head.time)
-		 *
-		 * Instead smbfs invalidates its own cache on local changes
-		 * and remote changes are not seen until timeout.
-		 */
-	}
-
-	if (filp->f_pos > ctl.head.end)
-		goto finished;
-
-	ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
-	ctl.ofs  = ctl.fpos / SMB_DIRCACHE_SIZE;
-	ctl.idx  = ctl.fpos % SMB_DIRCACHE_SIZE;
-
-	for (;;) {
-		if (ctl.ofs != 0) {
-			ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
-			if (!ctl.page)
-				goto invalid_cache;
-			ctl.cache = kmap(ctl.page);
-			if (!PageUptodate(ctl.page))
-				goto invalid_cache;
-		}
-		while (ctl.idx < SMB_DIRCACHE_SIZE) {
-			struct dentry *dent;
-			int res;
-
-			dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
-					     dentry, filp->f_pos);
-			if (!dent)
-				goto invalid_cache;
-
-			res = filldir(dirent, dent->d_name.name,
-				      dent->d_name.len, filp->f_pos,
-				      dent->d_inode->i_ino, DT_UNKNOWN);
-			dput(dent);
-			if (res)
-				goto finished;
-			filp->f_pos += 1;
-			ctl.idx += 1;
-			if (filp->f_pos > ctl.head.end)
-				goto finished;
-		}
-		if (ctl.page) {
-			kunmap(ctl.page);
-			SetPageUptodate(ctl.page);
-			unlock_page(ctl.page);
-			page_cache_release(ctl.page);
-			ctl.page = NULL;
-		}
-		ctl.idx  = 0;
-		ctl.ofs += 1;
-	}
-invalid_cache:
-	if (ctl.page) {
-		kunmap(ctl.page);
-		unlock_page(ctl.page);
-		page_cache_release(ctl.page);
-		ctl.page = NULL;
-	}
-	ctl.cache = cache;
-init_cache:
-	smb_invalidate_dircache_entries(dentry);
-	ctl.head.time = jiffies;
-	ctl.head.eof = 0;
-	ctl.fpos = 2;
-	ctl.ofs = 0;
-	ctl.idx = SMB_DIRCACHE_START;
-	ctl.filled = 0;
-	ctl.valid  = 1;
-read_really:
-	result = server->ops->readdir(filp, dirent, filldir, &ctl);
-	if (result == -ERESTARTSYS && page)
-		ClearPageUptodate(page);
-	if (ctl.idx == -1)
-		goto invalid_cache;	/* retry */
-	ctl.head.end = ctl.fpos - 1;
-	ctl.head.eof = ctl.valid;
-finished:
-	if (page) {
-		cache->head = ctl.head;
-		kunmap(page);
-		if (result != -ERESTARTSYS)
-			SetPageUptodate(page);
-		unlock_page(page);
-		page_cache_release(page);
-	}
-	if (ctl.page) {
-		kunmap(ctl.page);
-		SetPageUptodate(ctl.page);
-		unlock_page(ctl.page);
-		page_cache_release(ctl.page);
-	}
-out:
-	unlock_kernel();
-	return result;
-}
-
-static int
-smb_dir_open(struct inode *dir, struct file *file)
-{
-	struct dentry *dentry = file->f_path.dentry;
-	struct smb_sb_info *server;
-	int error = 0;
-
-	VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
-		file->f_path.dentry->d_name.name);
-
-	/*
-	 * Directory timestamps in the core protocol aren't updated
-	 * when a file is added, so we give them a very short TTL.
-	 */
-	lock_kernel();
-	server = server_from_dentry(dentry);
-	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
-		unsigned long age = jiffies - SMB_I(dir)->oldmtime;
-		if (age > 2*HZ)
-			smb_invalid_dir_cache(dir);
-	}
-
-	/*
-	 * Note: in order to allow the smbmount process to open the
-	 * mount point, we only revalidate if the connection is valid or
-	 * if the process is trying to access something other than the root.
-	 */
-	if (server->state == CONN_VALID || !IS_ROOT(dentry))
-		error = smb_revalidate_inode(dentry);
-	unlock_kernel();
-	return error;
-}
-
-/*
- * Dentry operations routines
- */
-static int smb_lookup_validate(struct dentry *, struct nameidata *);
-static int smb_hash_dentry(const struct dentry *, const struct inode *,
-		struct qstr *);
-static int smb_compare_dentry(const struct dentry *,
-		const struct inode *,
-		const struct dentry *, const struct inode *,
-		unsigned int, const char *, const struct qstr *);
-static int smb_delete_dentry(const struct dentry *);
-
-const struct dentry_operations smbfs_dentry_operations =
-{
-	.d_revalidate	= smb_lookup_validate,
-	.d_hash		= smb_hash_dentry,
-	.d_compare	= smb_compare_dentry,
-	.d_delete	= smb_delete_dentry,
-};
-
-const struct dentry_operations smbfs_dentry_operations_case =
-{
-	.d_revalidate	= smb_lookup_validate,
-	.d_delete	= smb_delete_dentry,
-};
-
-
-/*
- * This is the callback when the dcache has a lookup hit.
- */
-static int
-smb_lookup_validate(struct dentry *dentry, struct nameidata *nd)
-{
-	struct smb_sb_info *server;
-	struct inode *inode;
-	unsigned long age;
-	int valid;
-
-	if (nd->flags & LOOKUP_RCU)
-		return -ECHILD;
-
-	server = server_from_dentry(dentry);
-	inode = dentry->d_inode;
-	age = jiffies - dentry->d_time;
-
-	/*
-	 * The default validation is based on dentry age:
-	 * we believe in dentries for a few seconds.  (But each
-	 * successful server lookup renews the timestamp.)
-	 */
-	valid = (age <= SMB_MAX_AGE(server));
-#ifdef SMBFS_DEBUG_VERBOSE
-	if (!valid)
-		VERBOSE("%s/%s not valid, age=%lu\n", 
-			DENTRY_PATH(dentry), age);
-#endif
-
-	if (inode) {
-		lock_kernel();
-		if (is_bad_inode(inode)) {
-			PARANOIA("%s/%s has dud inode\n", DENTRY_PATH(dentry));
-			valid = 0;
-		} else if (!valid)
-			valid = (smb_revalidate_inode(dentry) == 0);
-		unlock_kernel();
-	} else {
-		/*
-		 * What should we do for negative dentries?
-		 */
-	}
-	return valid;
-}
-
-static int 
-smb_hash_dentry(const struct dentry *dir, const struct inode *inode,
-		struct qstr *this)
-{
-	unsigned long hash;
-	int i;
-
-	hash = init_name_hash();
-	for (i=0; i < this->len ; i++)
-		hash = partial_name_hash(tolower(this->name[i]), hash);
-	this->hash = end_name_hash(hash);
-  
-	return 0;
-}
-
-static int
-smb_compare_dentry(const struct dentry *parent,
-		const struct inode *pinode,
-		const struct dentry *dentry, const struct inode *inode,
-		unsigned int len, const char *str, const struct qstr *name)
-{
-	int i, result = 1;
-
-	if (len != name->len)
-		goto out;
-	for (i=0; i < len; i++) {
-		if (tolower(str[i]) != tolower(name->name[i]))
-			goto out;
-	}
-	result = 0;
-out:
-	return result;
-}
-
-/*
- * This is the callback from dput() when d_count is going to 0.
- * We use this to unhash dentries with bad inodes.
- */
-static int
-smb_delete_dentry(const struct dentry *dentry)
-{
-	if (dentry->d_inode) {
-		if (is_bad_inode(dentry->d_inode)) {
-			PARANOIA("bad inode, unhashing %s/%s\n",
-				 DENTRY_PATH(dentry));
-			return 1;
-		}
-	} else {
-		/* N.B. Unhash negative dentries? */
-	}
-	return 0;
-}
-
-/*
- * Initialize a new dentry
- */
-void
-smb_new_dentry(struct dentry *dentry)
-{
-	dentry->d_time = jiffies;
-}
-
-
-/*
- * Whenever a lookup succeeds, we know the parent directories
- * are all valid, so we want to update the dentry timestamps.
- * N.B. Move this to dcache?
- */
-void
-smb_renew_times(struct dentry * dentry)
-{
-	dget(dentry);
-	dentry->d_time = jiffies;
-
-	while (!IS_ROOT(dentry)) {
-		struct dentry *parent = dget_parent(dentry);
-		dput(dentry);
-		dentry = parent;
-
-		dentry->d_time = jiffies;
-	}
-	dput(dentry);
-}
-
-static struct dentry *
-smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-	struct smb_fattr finfo;
-	struct inode *inode;
-	int error;
-
-	error = -ENAMETOOLONG;
-	if (dentry->d_name.len > SMB_MAXNAMELEN)
-		goto out;
-
-	/* Do not allow lookup of names with backslashes in */
-	error = -EINVAL;
-	if (memchr(dentry->d_name.name, '\\', dentry->d_name.len))
-		goto out;
-
-	lock_kernel();
-	error = smb_proc_getattr(dentry, &finfo);
-#ifdef SMBFS_PARANOIA
-	if (error && error != -ENOENT)
-		PARANOIA("find %s/%s failed, error=%d\n",
-			 DENTRY_PATH(dentry), error);
-#endif
-
-	inode = NULL;
-	if (error == -ENOENT)
-		goto add_entry;
-	if (!error) {
-		error = -EACCES;
-		finfo.f_ino = iunique(dentry->d_sb, 2);
-		inode = smb_iget(dir->i_sb, &finfo);
-		if (inode) {
-	add_entry:
-			d_add(dentry, inode);
-			smb_renew_times(dentry);
-			error = 0;
-		}
-	}
-	unlock_kernel();
-out:
-	return ERR_PTR(error);
-}
-
-/*
- * This code is common to all routines creating a new inode.
- */
-static int
-smb_instantiate(struct dentry *dentry, __u16 fileid, int have_id)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	struct inode *inode;
-	int error;
-	struct smb_fattr fattr;
-
-	VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid);
-
-	error = smb_proc_getattr(dentry, &fattr);
-	if (error)
-		goto out_close;
-
-	smb_renew_times(dentry);
-	fattr.f_ino = iunique(dentry->d_sb, 2);
-	inode = smb_iget(dentry->d_sb, &fattr);
-	if (!inode)
-		goto out_no_inode;
-
-	if (have_id) {
-		struct smb_inode_info *ei = SMB_I(inode);
-		ei->fileid = fileid;
-		ei->access = SMB_O_RDWR;
-		ei->open = server->generation;
-	}
-	d_instantiate(dentry, inode);
-out:
-	return error;
-
-out_no_inode:
-	error = -EACCES;
-out_close:
-	if (have_id) {
-		PARANOIA("%s/%s failed, error=%d, closing %u\n",
-			 DENTRY_PATH(dentry), error, fileid);
-		smb_close_fileid(dentry, fileid);
-	}
-	goto out;
-}
-
-/* N.B. How should the mode argument be used? */
-static int
-smb_create(struct inode *dir, struct dentry *dentry, int mode,
-		struct nameidata *nd)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	__u16 fileid;
-	int error;
-	struct iattr attr;
-
-	VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode);
-
-	lock_kernel();
-	smb_invalid_dir_cache(dir);
-	error = smb_proc_create(dentry, 0, get_seconds(), &fileid);
-	if (!error) {
-		if (server->opt.capabilities & SMB_CAP_UNIX) {
-			/* Set attributes for new file */
-			attr.ia_valid = ATTR_MODE;
-			attr.ia_mode = mode;
-			error = smb_proc_setattr_unix(dentry, &attr, 0, 0);
-		}
-		error = smb_instantiate(dentry, fileid, 1);
-	} else {
-		PARANOIA("%s/%s failed, error=%d\n",
-			 DENTRY_PATH(dentry), error);
-	}
-	unlock_kernel();
-	return error;
-}
-
-/* N.B. How should the mode argument be used? */
-static int
-smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	int error;
-	struct iattr attr;
-
-	lock_kernel();
-	smb_invalid_dir_cache(dir);
-	error = smb_proc_mkdir(dentry);
-	if (!error) {
-		if (server->opt.capabilities & SMB_CAP_UNIX) {
-			/* Set attributes for new directory */
-			attr.ia_valid = ATTR_MODE;
-			attr.ia_mode = mode;
-			error = smb_proc_setattr_unix(dentry, &attr, 0, 0);
-		}
-		error = smb_instantiate(dentry, 0, 0);
-	}
-	unlock_kernel();
-	return error;
-}
-
-static int
-smb_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	struct inode *inode = dentry->d_inode;
-	int error;
-
-	/*
-	 * Close the directory if it's open.
-	 */
-	lock_kernel();
-	smb_close(inode);
-
-	/*
-	 * Check that nobody else is using the directory..
-	 */
-	error = -EBUSY;
-	if (!d_unhashed(dentry))
-		goto out;
-
-	smb_invalid_dir_cache(dir);
-	error = smb_proc_rmdir(dentry);
-
-out:
-	unlock_kernel();
-	return error;
-}
-
-static int
-smb_unlink(struct inode *dir, struct dentry *dentry)
-{
-	int error;
-
-	/*
-	 * Close the file if it's open.
-	 */
-	lock_kernel();
-	smb_close(dentry->d_inode);
-
-	smb_invalid_dir_cache(dir);
-	error = smb_proc_unlink(dentry);
-	if (!error)
-		smb_renew_times(dentry);
-	unlock_kernel();
-	return error;
-}
-
-static int
-smb_rename(struct inode *old_dir, struct dentry *old_dentry,
-	   struct inode *new_dir, struct dentry *new_dentry)
-{
-	int error;
-
-	/*
-	 * Close any open files, and check whether to delete the
-	 * target before attempting the rename.
-	 */
-	lock_kernel();
-	if (old_dentry->d_inode)
-		smb_close(old_dentry->d_inode);
-	if (new_dentry->d_inode) {
-		smb_close(new_dentry->d_inode);
-		error = smb_proc_unlink(new_dentry);
-		if (error) {
-			VERBOSE("unlink %s/%s, error=%d\n",
-				DENTRY_PATH(new_dentry), error);
-			goto out;
-		}
-		/* FIXME */
-		d_delete(new_dentry);
-	}
-
-	smb_invalid_dir_cache(old_dir);
-	smb_invalid_dir_cache(new_dir);
-	error = smb_proc_mv(old_dentry, new_dentry);
-	if (!error) {
-		smb_renew_times(old_dentry);
-		smb_renew_times(new_dentry);
-	}
-out:
-	unlock_kernel();
-	return error;
-}
-
-/*
- * FIXME: samba servers won't let you create device nodes unless uid/gid
- * matches the connection credentials (and we don't know which those are ...)
- */
-static int
-smb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-{
-	int error;
-	struct iattr attr;
-
-	attr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID;
-	attr.ia_mode = mode;
-	current_euid_egid(&attr.ia_uid, &attr.ia_gid);
-
-	if (!new_valid_dev(dev))
-		return -EINVAL;
-
-	smb_invalid_dir_cache(dir);
-	error = smb_proc_setattr_unix(dentry, &attr, MAJOR(dev), MINOR(dev));
-	if (!error) {
-		error = smb_instantiate(dentry, 0, 0);
-	}
-	return error;
-}
-
-/*
- * dentry = existing file
- * new_dentry = new file
- */
-static int
-smb_link(struct dentry *dentry, struct inode *dir, struct dentry *new_dentry)
-{
-	int error;
-
-	DEBUG1("smb_link old=%s/%s new=%s/%s\n",
-	       DENTRY_PATH(dentry), DENTRY_PATH(new_dentry));
-	smb_invalid_dir_cache(dir);
-	error = smb_proc_link(server_from_dentry(dentry), dentry, new_dentry);
-	if (!error) {
-		smb_renew_times(dentry);
-		error = smb_instantiate(new_dentry, 0, 0);
-	}
-	return error;
-}
diff --git a/drivers/staging/smbfs/file.c b/drivers/staging/smbfs/file.c
deleted file mode 100644
index 31372e7..0000000
--- a/drivers/staging/smbfs/file.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- *  file.c
- *
- *  Copyright (C) 1995, 1996, 1997 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-#include <linux/net.h>
-#include <linux/aio.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "smbno.h"
-#include "smb_fs.h"
-#include "smb_debug.h"
-#include "proto.h"
-
-static int
-smb_fsync(struct file *file, int datasync)
-{
-	struct dentry *dentry = file->f_path.dentry;
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	int result;
-
-	VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
-
-	/*
-	 * The VFS will writepage() all dirty pages for us, but we
-	 * should send a SMBflush to the server, letting it know that
-	 * we want things synchronized with actual storage.
-	 *
-	 * Note: this function requires all pages to have been written already
-	 *       (should be ok with writepage_sync)
-	 */
-	result = smb_proc_flush(server, SMB_I(dentry->d_inode)->fileid);
-	return result;
-}
-
-/*
- * Read a page synchronously.
- */
-static int
-smb_readpage_sync(struct dentry *dentry, struct page *page)
-{
-	char *buffer = kmap(page);
-	loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT;
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	unsigned int rsize = smb_get_rsize(server);
-	int count = PAGE_SIZE;
-	int result;
-
-	VERBOSE("file %s/%s, count=%d@%Ld, rsize=%d\n",
-		DENTRY_PATH(dentry), count, offset, rsize);
-
-	result = smb_open(dentry, SMB_O_RDONLY);
-	if (result < 0)
-		goto io_error;
-
-	do {
-		if (count < rsize)
-			rsize = count;
-
-		result = server->ops->read(dentry->d_inode,offset,rsize,buffer);
-		if (result < 0)
-			goto io_error;
-
-		count -= result;
-		offset += result;
-		buffer += result;
-		dentry->d_inode->i_atime =
-			current_fs_time(dentry->d_inode->i_sb);
-		if (result < rsize)
-			break;
-	} while (count);
-
-	memset(buffer, 0, count);
-	flush_dcache_page(page);
-	SetPageUptodate(page);
-	result = 0;
-
-io_error:
-	kunmap(page);
-	unlock_page(page);
-	return result;
-}
-
-/*
- * We are called with the page locked and we unlock it when done.
- */
-static int
-smb_readpage(struct file *file, struct page *page)
-{
-	int		error;
-	struct dentry  *dentry = file->f_path.dentry;
-
-	page_cache_get(page);
-	error = smb_readpage_sync(dentry, page);
-	page_cache_release(page);
-	return error;
-}
-
-/*
- * Write a page synchronously.
- * Offset is the data offset within the page.
- */
-static int
-smb_writepage_sync(struct inode *inode, struct page *page,
-		   unsigned long pageoffset, unsigned int count)
-{
-	loff_t offset;
-	char *buffer = kmap(page) + pageoffset;
-	struct smb_sb_info *server = server_from_inode(inode);
-	unsigned int wsize = smb_get_wsize(server);
-	int ret = 0;
-
-	offset = ((loff_t)page->index << PAGE_CACHE_SHIFT) + pageoffset;
-	VERBOSE("file ino=%ld, fileid=%d, count=%d@%Ld, wsize=%d\n",
-		inode->i_ino, SMB_I(inode)->fileid, count, offset, wsize);
-
-	do {
-		int write_ret;
-
-		if (count < wsize)
-			wsize = count;
-
-		write_ret = server->ops->write(inode, offset, wsize, buffer);
-		if (write_ret < 0) {
-			PARANOIA("failed write, wsize=%d, write_ret=%d\n",
-				 wsize, write_ret);
-			ret = write_ret;
-			break;
-		}
-		/* N.B. what if result < wsize?? */
-#ifdef SMBFS_PARANOIA
-		if (write_ret < wsize)
-			PARANOIA("short write, wsize=%d, write_ret=%d\n",
-				 wsize, write_ret);
-#endif
-		buffer += wsize;
-		offset += wsize;
-		count -= wsize;
-		/*
-		 * Update the inode now rather than waiting for a refresh.
-		 */
-		inode->i_mtime = inode->i_atime = current_fs_time(inode->i_sb);
-		SMB_I(inode)->flags |= SMB_F_LOCALWRITE;
-		if (offset > inode->i_size)
-			inode->i_size = offset;
-	} while (count);
-
-	kunmap(page);
-	return ret;
-}
-
-/*
- * Write a page to the server. This will be used for NFS swapping only
- * (for now), and we currently do this synchronously only.
- *
- * We are called with the page locked and we unlock it when done.
- */
-static int
-smb_writepage(struct page *page, struct writeback_control *wbc)
-{
-	struct address_space *mapping = page->mapping;
-	struct inode *inode;
-	unsigned long end_index;
-	unsigned offset = PAGE_CACHE_SIZE;
-	int err;
-
-	BUG_ON(!mapping);
-	inode = mapping->host;
-	BUG_ON(!inode);
-
-	end_index = inode->i_size >> PAGE_CACHE_SHIFT;
-
-	/* easy case */
-	if (page->index < end_index)
-		goto do_it;
-	/* things got complicated... */
-	offset = inode->i_size & (PAGE_CACHE_SIZE-1);
-	/* OK, are we completely out? */
-	if (page->index >= end_index+1 || !offset)
-		return 0; /* truncated - don't care */
-do_it:
-	page_cache_get(page);
-	err = smb_writepage_sync(inode, page, 0, offset);
-	SetPageUptodate(page);
-	unlock_page(page);
-	page_cache_release(page);
-	return err;
-}
-
-static int
-smb_updatepage(struct file *file, struct page *page, unsigned long offset,
-	       unsigned int count)
-{
-	struct dentry *dentry = file->f_path.dentry;
-
-	DEBUG1("(%s/%s %d@%lld)\n", DENTRY_PATH(dentry), count,
-		((unsigned long long)page->index << PAGE_CACHE_SHIFT) + offset);
-
-	return smb_writepage_sync(dentry->d_inode, page, offset, count);
-}
-
-static ssize_t
-smb_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
-			unsigned long nr_segs, loff_t pos)
-{
-	struct file * file = iocb->ki_filp;
-	struct dentry * dentry = file->f_path.dentry;
-	ssize_t	status;
-
-	VERBOSE("file %s/%s, count=%lu@%lu\n", DENTRY_PATH(dentry),
-		(unsigned long) iocb->ki_left, (unsigned long) pos);
-
-	status = smb_revalidate_inode(dentry);
-	if (status) {
-		PARANOIA("%s/%s validation failed, error=%Zd\n",
-			 DENTRY_PATH(dentry), status);
-		goto out;
-	}
-
-	VERBOSE("before read, size=%ld, flags=%x, atime=%ld\n",
-		(long)dentry->d_inode->i_size,
-		dentry->d_inode->i_flags, dentry->d_inode->i_atime.tv_sec);
-
-	status = generic_file_aio_read(iocb, iov, nr_segs, pos);
-out:
-	return status;
-}
-
-static int
-smb_file_mmap(struct file * file, struct vm_area_struct * vma)
-{
-	struct dentry * dentry = file->f_path.dentry;
-	int	status;
-
-	VERBOSE("file %s/%s, address %lu - %lu\n",
-		DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
-
-	status = smb_revalidate_inode(dentry);
-	if (status) {
-		PARANOIA("%s/%s validation failed, error=%d\n",
-			 DENTRY_PATH(dentry), status);
-		goto out;
-	}
-	status = generic_file_mmap(file, vma);
-out:
-	return status;
-}
-
-static ssize_t
-smb_file_splice_read(struct file *file, loff_t *ppos,
-		     struct pipe_inode_info *pipe, size_t count,
-		     unsigned int flags)
-{
-	struct dentry *dentry = file->f_path.dentry;
-	ssize_t status;
-
-	VERBOSE("file %s/%s, pos=%Ld, count=%lu\n",
-		DENTRY_PATH(dentry), *ppos, count);
-
-	status = smb_revalidate_inode(dentry);
-	if (status) {
-		PARANOIA("%s/%s validation failed, error=%Zd\n",
-			 DENTRY_PATH(dentry), status);
-		goto out;
-	}
-	status = generic_file_splice_read(file, ppos, pipe, count, flags);
-out:
-	return status;
-}
-
-/*
- * This does the "real" work of the write. The generic routine has
- * allocated the page, locked it, done all the page alignment stuff
- * calculations etc. Now we should just copy the data from user
- * space and write it back to the real medium..
- *
- * If the writer ends up delaying the write, the writer needs to
- * increment the page use counts until he is done with the page.
- */
-static int smb_write_begin(struct file *file, struct address_space *mapping,
-			loff_t pos, unsigned len, unsigned flags,
-			struct page **pagep, void **fsdata)
-{
-	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
-	*pagep = grab_cache_page_write_begin(mapping, index, flags);
-	if (!*pagep)
-		return -ENOMEM;
-	return 0;
-}
-
-static int smb_write_end(struct file *file, struct address_space *mapping,
-			loff_t pos, unsigned len, unsigned copied,
-			struct page *page, void *fsdata)
-{
-	int status;
-	unsigned offset = pos & (PAGE_CACHE_SIZE - 1);
-
-	lock_kernel();
-	status = smb_updatepage(file, page, offset, copied);
-	unlock_kernel();
-
-	if (!status) {
-		if (!PageUptodate(page) && copied == PAGE_CACHE_SIZE)
-			SetPageUptodate(page);
-		status = copied;
-	}
-
-	unlock_page(page);
-	page_cache_release(page);
-
-	return status;
-}
-
-const struct address_space_operations smb_file_aops = {
-	.readpage = smb_readpage,
-	.writepage = smb_writepage,
-	.write_begin = smb_write_begin,
-	.write_end = smb_write_end,
-};
-
-/* 
- * Write to a file (through the page cache).
- */
-static ssize_t
-smb_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
-			       unsigned long nr_segs, loff_t pos)
-{
-	struct file * file = iocb->ki_filp;
-	struct dentry * dentry = file->f_path.dentry;
-	ssize_t	result;
-
-	VERBOSE("file %s/%s, count=%lu@%lu\n",
-		DENTRY_PATH(dentry),
-		(unsigned long) iocb->ki_left, (unsigned long) pos);
-
-	result = smb_revalidate_inode(dentry);
-	if (result) {
-		PARANOIA("%s/%s validation failed, error=%Zd\n",
-			 DENTRY_PATH(dentry), result);
-		goto out;
-	}
-
-	result = smb_open(dentry, SMB_O_WRONLY);
-	if (result)
-		goto out;
-
-	if (iocb->ki_left > 0) {
-		result = generic_file_aio_write(iocb, iov, nr_segs, pos);
-		VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
-			(long) file->f_pos, (long) dentry->d_inode->i_size,
-			dentry->d_inode->i_mtime.tv_sec,
-			dentry->d_inode->i_atime.tv_sec);
-	}
-out:
-	return result;
-}
-
-static int
-smb_file_open(struct inode *inode, struct file * file)
-{
-	int result;
-	struct dentry *dentry = file->f_path.dentry;
-	int smb_mode = (file->f_mode & O_ACCMODE) - 1;
-
-	lock_kernel();
-	result = smb_open(dentry, smb_mode);
-	if (result)
-		goto out;
-	SMB_I(inode)->openers++;
-out:
-	unlock_kernel();
-	return result;
-}
-
-static int
-smb_file_release(struct inode *inode, struct file * file)
-{
-	lock_kernel();
-	if (!--SMB_I(inode)->openers) {
-		/* We must flush any dirty pages now as we won't be able to
-		   write anything after close. mmap can trigger this.
-		   "openers" should perhaps include mmap'ers ... */
-		filemap_write_and_wait(inode->i_mapping);
-		smb_close(inode);
-	}
-	unlock_kernel();
-	return 0;
-}
-
-/*
- * Check whether the required access is compatible with
- * an inode's permission. SMB doesn't recognize superuser
- * privileges, so we need our own check for this.
- */
-static int
-smb_file_permission(struct inode *inode, int mask, unsigned int flags)
-{
-	int mode = inode->i_mode;
-	int error = 0;
-
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
-	VERBOSE("mode=%x, mask=%x\n", mode, mask);
-
-	/* Look at user permissions */
-	mode >>= 6;
-	if (mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC))
-		error = -EACCES;
-	return error;
-}
-
-static loff_t smb_remote_llseek(struct file *file, loff_t offset, int origin)
-{
-	loff_t ret;
-	lock_kernel();
-	ret = generic_file_llseek_unlocked(file, offset, origin);
-	unlock_kernel();
-	return ret;
-}
-
-const struct file_operations smb_file_operations =
-{
-	.llseek 	= smb_remote_llseek,
-	.read		= do_sync_read,
-	.aio_read	= smb_file_aio_read,
-	.write		= do_sync_write,
-	.aio_write	= smb_file_aio_write,
-	.unlocked_ioctl	= smb_ioctl,
-	.mmap		= smb_file_mmap,
-	.open		= smb_file_open,
-	.release	= smb_file_release,
-	.fsync		= smb_fsync,
-	.splice_read	= smb_file_splice_read,
-};
-
-const struct inode_operations smb_file_inode_operations =
-{
-	.permission	= smb_file_permission,
-	.getattr	= smb_getattr,
-	.setattr	= smb_notify_change,
-};
diff --git a/drivers/staging/smbfs/getopt.c b/drivers/staging/smbfs/getopt.c
deleted file mode 100644
index 7ae0f52..0000000
--- a/drivers/staging/smbfs/getopt.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * getopt.c
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/net.h>
-
-#include "getopt.h"
-
-/**
- *	smb_getopt - option parser
- *	@caller: name of the caller, for error messages
- *	@options: the options string
- *	@opts: an array of &struct option entries controlling parser operations
- *	@optopt: output; will contain the current option
- *	@optarg: output; will contain the value (if one exists)
- *	@flag: output; may be NULL; should point to a long for or'ing flags
- *	@value: output; may be NULL; will be overwritten with the integer value
- *		of the current argument.
- *
- *	Helper to parse options on the format used by mount ("a=b,c=d,e,f").
- *	Returns opts->val if a matching entry in the 'opts' array is found,
- *	0 when no more tokens are found, -1 if an error is encountered.
- */
-int smb_getopt(char *caller, char **options, struct option *opts,
-	       char **optopt, char **optarg, unsigned long *flag,
-	       unsigned long *value)
-{
-	char *token;
-	char *val;
-	int i;
-
-	do {
-		if ((token = strsep(options, ",")) == NULL)
-			return 0;
-	} while (*token == '\0');
-	*optopt = token;
-
-	*optarg = NULL;
-	if ((val = strchr (token, '=')) != NULL) {
-		*val++ = 0;
-		if (value)
-			*value = simple_strtoul(val, NULL, 0);
-		*optarg = val;
-	}
-
-	for (i = 0; opts[i].name != NULL; i++) {
-		if (!strcmp(opts[i].name, token)) {
-			if (!opts[i].flag && (!val || !*val)) {
-				printk("%s: the %s option requires an argument\n",
-				       caller, token);
-				return -1;
-			}
-
-			if (flag && opts[i].flag)
-				*flag |= opts[i].flag;
-
-			return opts[i].val;
-		}
-	}
-	printk("%s: Unrecognized mount option %s\n", caller, token);
-	return -1;
-}
diff --git a/drivers/staging/smbfs/getopt.h b/drivers/staging/smbfs/getopt.h
deleted file mode 100644
index 146219a..0000000
--- a/drivers/staging/smbfs/getopt.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _LINUX_GETOPT_H
-#define _LINUX_GETOPT_H
-
-struct option {
-	const char *name;
-	unsigned long flag;
-	int val;
-};
-
-extern int smb_getopt(char *caller, char **options, struct option *opts,
-		      char **optopt, char **optarg, unsigned long *flag,
-		      unsigned long *value);
-
-#endif /* _LINUX_GETOPT_H */
diff --git a/drivers/staging/smbfs/inode.c b/drivers/staging/smbfs/inode.c
deleted file mode 100644
index 0778589..0000000
--- a/drivers/staging/smbfs/inode.c
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
- *  inode.c
- *
- *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/module.h>
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/dcache.h>
-#include <linux/smp_lock.h>
-#include <linux/nls.h>
-#include <linux/seq_file.h>
-#include <linux/mount.h>
-#include <linux/net.h>
-#include <linux/vfs.h>
-#include <linux/highuid.h>
-#include <linux/sched.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "smb_fs.h"
-#include "smbno.h"
-#include "smb_mount.h"
-#include "smb_debug.h"
-#include "getopt.h"
-#include "proto.h"
-
-/* Always pick a default string */
-#ifdef CONFIG_SMB_NLS_REMOTE
-#define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE
-#else
-#define SMB_NLS_REMOTE ""
-#endif
-
-#define SMB_TTL_DEFAULT 1000
-
-static void smb_evict_inode(struct inode *);
-static void smb_put_super(struct super_block *);
-static int  smb_statfs(struct dentry *, struct kstatfs *);
-static int  smb_show_options(struct seq_file *, struct vfsmount *);
-
-static struct kmem_cache *smb_inode_cachep;
-
-static struct inode *smb_alloc_inode(struct super_block *sb)
-{
-	struct smb_inode_info *ei;
-	ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, GFP_KERNEL);
-	if (!ei)
-		return NULL;
-	return &ei->vfs_inode;
-}
-
-static void smb_i_callback(struct rcu_head *head)
-{
-	struct inode *inode = container_of(head, struct inode, i_rcu);
-	INIT_LIST_HEAD(&inode->i_dentry);
-	kmem_cache_free(smb_inode_cachep, SMB_I(inode));
-}
-
-static void smb_destroy_inode(struct inode *inode)
-{
-	call_rcu(&inode->i_rcu, smb_i_callback);
-}
-
-static void init_once(void *foo)
-{
-	struct smb_inode_info *ei = (struct smb_inode_info *) foo;
-
-	inode_init_once(&ei->vfs_inode);
-}
-
-static int init_inodecache(void)
-{
-	smb_inode_cachep = kmem_cache_create("smb_inode_cache",
-					     sizeof(struct smb_inode_info),
-					     0, (SLAB_RECLAIM_ACCOUNT|
-						SLAB_MEM_SPREAD),
-					     init_once);
-	if (smb_inode_cachep == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-static void destroy_inodecache(void)
-{
-	kmem_cache_destroy(smb_inode_cachep);
-}
-
-static int smb_remount(struct super_block *sb, int *flags, char *data)
-{
-	*flags |= MS_NODIRATIME;
-	return 0;
-}
-
-static const struct super_operations smb_sops =
-{
-	.alloc_inode	= smb_alloc_inode,
-	.destroy_inode	= smb_destroy_inode,
-	.drop_inode	= generic_delete_inode,
-	.evict_inode	= smb_evict_inode,
-	.put_super	= smb_put_super,
-	.statfs		= smb_statfs,
-	.show_options	= smb_show_options,
-	.remount_fs	= smb_remount,
-};
-
-
-/* We are always generating a new inode here */
-struct inode *
-smb_iget(struct super_block *sb, struct smb_fattr *fattr)
-{
-	struct smb_sb_info *server = SMB_SB(sb);
-	struct inode *result;
-
-	DEBUG1("smb_iget: %p\n", fattr);
-
-	result = new_inode(sb);
-	if (!result)
-		return result;
-	result->i_ino = fattr->f_ino;
-	SMB_I(result)->open = 0;
-	SMB_I(result)->fileid = 0;
-	SMB_I(result)->access = 0;
-	SMB_I(result)->flags = 0;
-	SMB_I(result)->closed = 0;
-	SMB_I(result)->openers = 0;
-	smb_set_inode_attr(result, fattr);
-	if (S_ISREG(result->i_mode)) {
-		result->i_op = &smb_file_inode_operations;
-		result->i_fop = &smb_file_operations;
-		result->i_data.a_ops = &smb_file_aops;
-	} else if (S_ISDIR(result->i_mode)) {
-		if (server->opt.capabilities & SMB_CAP_UNIX)
-			result->i_op = &smb_dir_inode_operations_unix;
-		else
-			result->i_op = &smb_dir_inode_operations;
-		result->i_fop = &smb_dir_operations;
-	} else if (S_ISLNK(result->i_mode)) {
-		result->i_op = &smb_link_inode_operations;
-	} else {
-		init_special_inode(result, result->i_mode, fattr->f_rdev);
-	}
-	insert_inode_hash(result);
-	return result;
-}
-
-/*
- * Copy the inode data to a smb_fattr structure.
- */
-void
-smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
-{
-	memset(fattr, 0, sizeof(struct smb_fattr));
-	fattr->f_mode	= inode->i_mode;
-	fattr->f_nlink	= inode->i_nlink;
-	fattr->f_ino	= inode->i_ino;
-	fattr->f_uid	= inode->i_uid;
-	fattr->f_gid	= inode->i_gid;
-	fattr->f_size	= inode->i_size;
-	fattr->f_mtime	= inode->i_mtime;
-	fattr->f_ctime	= inode->i_ctime;
-	fattr->f_atime	= inode->i_atime;
-	fattr->f_blocks	= inode->i_blocks;
-
-	fattr->attr	= SMB_I(inode)->attr;
-	/*
-	 * Keep the attributes in sync with the inode permissions.
-	 */
-	if (fattr->f_mode & S_IWUSR)
-		fattr->attr &= ~aRONLY;
-	else
-		fattr->attr |= aRONLY;
-}
-
-/*
- * Update the inode, possibly causing it to invalidate its pages if mtime/size
- * is different from last time.
- */
-void
-smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
-{
-	struct smb_inode_info *ei = SMB_I(inode);
-
-	/*
-	 * A size change should have a different mtime, or same mtime
-	 * but different size.
-	 */
-	time_t last_time = inode->i_mtime.tv_sec;
-	loff_t last_sz = inode->i_size;
-
-	inode->i_mode	= fattr->f_mode;
-	inode->i_nlink	= fattr->f_nlink;
-	inode->i_uid	= fattr->f_uid;
-	inode->i_gid	= fattr->f_gid;
-	inode->i_ctime	= fattr->f_ctime;
-	inode->i_blocks = fattr->f_blocks;
-	inode->i_size	= fattr->f_size;
-	inode->i_mtime	= fattr->f_mtime;
-	inode->i_atime	= fattr->f_atime;
-	ei->attr = fattr->attr;
-
-	/*
-	 * Update the "last time refreshed" field for revalidation.
-	 */
-	ei->oldmtime = jiffies;
-
-	if (inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz) {
-		VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
-			inode->i_ino,
-			(long) last_time, (long) inode->i_mtime.tv_sec,
-			(long) last_sz, (long) inode->i_size);
-
-		if (!S_ISDIR(inode->i_mode))
-			invalidate_remote_inode(inode);
-	}
-}
-
-/*
- * This is called if the connection has gone bad ...
- * try to kill off all the current inodes.
- */
-void
-smb_invalidate_inodes(struct smb_sb_info *server)
-{
-	VERBOSE("\n");
-	shrink_dcache_sb(SB_of(server));
-}
-
-/*
- * This is called to update the inode attributes after
- * we've made changes to a file or directory.
- */
-static int
-smb_refresh_inode(struct dentry *dentry)
-{
-	struct inode *inode = dentry->d_inode;
-	int error;
-	struct smb_fattr fattr;
-
-	error = smb_proc_getattr(dentry, &fattr);
-	if (!error) {
-		smb_renew_times(dentry);
-		/*
-		 * Check whether the type part of the mode changed,
-		 * and don't update the attributes if it did.
-		 *
-		 * And don't dick with the root inode
-		 */
-		if (inode->i_ino == 2)
-			return error;
-		if (S_ISLNK(inode->i_mode))
-			return error;	/* VFS will deal with it */
-
-		if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) {
-			smb_set_inode_attr(inode, &fattr);
-		} else {
-			/*
-			 * Big trouble! The inode has become a new object,
-			 * so any operations attempted on it are invalid.
-			 *
-			 * To limit damage, mark the inode as bad so that
-			 * subsequent lookup validations will fail.
-			 */
-			PARANOIA("%s/%s changed mode, %07o to %07o\n",
-				 DENTRY_PATH(dentry),
-				 inode->i_mode, fattr.f_mode);
-
-			fattr.f_mode = inode->i_mode; /* save mode */
-			make_bad_inode(inode);
-			inode->i_mode = fattr.f_mode; /* restore mode */
-			/*
-			 * No need to worry about unhashing the dentry: the
-			 * lookup validation will see that the inode is bad.
-			 * But we do want to invalidate the caches ...
-			 */
-			if (!S_ISDIR(inode->i_mode))
-				invalidate_remote_inode(inode);
-			else
-				smb_invalid_dir_cache(inode);
-			error = -EIO;
-		}
-	}
-	return error;
-}
-
-/*
- * This is called when we want to check whether the inode
- * has changed on the server.  If it has changed, we must
- * invalidate our local caches.
- */
-int
-smb_revalidate_inode(struct dentry *dentry)
-{
-	struct smb_sb_info *s = server_from_dentry(dentry);
-	struct inode *inode = dentry->d_inode;
-	int error = 0;
-
-	DEBUG1("smb_revalidate_inode\n");
-	lock_kernel();
-
-	/*
-	 * Check whether we've recently refreshed the inode.
-	 */
-	if (time_before(jiffies, SMB_I(inode)->oldmtime + SMB_MAX_AGE(s))) {
-		VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",
-			inode->i_ino, jiffies, SMB_I(inode)->oldmtime);
-		goto out;
-	}
-
-	error = smb_refresh_inode(dentry);
-out:
-	unlock_kernel();
-	return error;
-}
-
-/*
- * This routine is called when i_nlink == 0 and i_count goes to 0.
- * All blocking cleanup operations need to go here to avoid races.
- */
-static void
-smb_evict_inode(struct inode *ino)
-{
-	DEBUG1("ino=%ld\n", ino->i_ino);
-	truncate_inode_pages(&ino->i_data, 0);
-	end_writeback(ino);
-	lock_kernel();
-	if (smb_close(ino))
-		PARANOIA("could not close inode %ld\n", ino->i_ino);
-	unlock_kernel();
-}
-
-static struct option opts[] = {
-	{ "version",	0, 'v' },
-	{ "win95",	SMB_MOUNT_WIN95, 1 },
-	{ "oldattr",	SMB_MOUNT_OLDATTR, 1 },
-	{ "dirattr",	SMB_MOUNT_DIRATTR, 1 },
-	{ "case",	SMB_MOUNT_CASE, 1 },
-	{ "uid",	0, 'u' },
-	{ "gid",	0, 'g' },
-	{ "file_mode",	0, 'f' },
-	{ "dir_mode",	0, 'd' },
-	{ "iocharset",	0, 'i' },
-	{ "codepage",	0, 'c' },
-	{ "ttl",	0, 't' },
-	{ NULL,		0, 0}
-};
-
-static int
-parse_options(struct smb_mount_data_kernel *mnt, char *options)
-{
-	int c;
-	unsigned long flags;
-	unsigned long value;
-	char *optarg;
-	char *optopt;
-
-	flags = 0;
-	while ( (c = smb_getopt("smbfs", &options, opts,
-				&optopt, &optarg, &flags, &value)) > 0) {
-
-		VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");
-		switch (c) {
-		case 1:
-			/* got a "flag" option */
-			break;
-		case 'v':
-			if (value != SMB_MOUNT_VERSION) {
-			printk ("smbfs: Bad mount version %ld, expected %d\n",
-				value, SMB_MOUNT_VERSION);
-				return 0;
-			}
-			mnt->version = value;
-			break;
-		case 'u':
-			mnt->uid = value;
-			flags |= SMB_MOUNT_UID;
-			break;
-		case 'g':
-			mnt->gid = value;
-			flags |= SMB_MOUNT_GID;
-			break;
-		case 'f':
-			mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
-			flags |= SMB_MOUNT_FMODE;
-			break;
-		case 'd':
-			mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
-			flags |= SMB_MOUNT_DMODE;
-			break;
-		case 'i':
-			strlcpy(mnt->codepage.local_name, optarg, 
-				SMB_NLS_MAXNAMELEN);
-			break;
-		case 'c':
-			strlcpy(mnt->codepage.remote_name, optarg,
-				SMB_NLS_MAXNAMELEN);
-			break;
-		case 't':
-			mnt->ttl = value;
-			break;
-		default:
-			printk ("smbfs: Unrecognized mount option %s\n",
-				optopt);
-			return -1;
-		}
-	}
-	mnt->flags = flags;
-	return c;
-}
-
-/*
- * smb_show_options() is for displaying mount options in /proc/mounts.
- * It tries to avoid showing settings that were not changed from their
- * defaults.
- */
-static int
-smb_show_options(struct seq_file *s, struct vfsmount *m)
-{
-	struct smb_mount_data_kernel *mnt = SMB_SB(m->mnt_sb)->mnt;
-	int i;
-
-	for (i = 0; opts[i].name != NULL; i++)
-		if (mnt->flags & opts[i].flag)
-			seq_printf(s, ",%s", opts[i].name);
-
-	if (mnt->flags & SMB_MOUNT_UID)
-		seq_printf(s, ",uid=%d", mnt->uid);
-	if (mnt->flags & SMB_MOUNT_GID)
-		seq_printf(s, ",gid=%d", mnt->gid);
-	if (mnt->mounted_uid != 0)
-		seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
-
-	/* 
-	 * Defaults for file_mode and dir_mode are unknown to us; they
-	 * depend on the current umask of the user doing the mount.
-	 */
-	if (mnt->flags & SMB_MOUNT_FMODE)
-		seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
-	if (mnt->flags & SMB_MOUNT_DMODE)
-		seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
-
-	if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
-		seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
-	if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
-		seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
-
-	if (mnt->ttl != SMB_TTL_DEFAULT)
-		seq_printf(s, ",ttl=%d", mnt->ttl);
-
-	return 0;
-}
-
-static void
-smb_unload_nls(struct smb_sb_info *server)
-{
-	unload_nls(server->remote_nls);
-	unload_nls(server->local_nls);
-}
-
-static void
-smb_put_super(struct super_block *sb)
-{
-	struct smb_sb_info *server = SMB_SB(sb);
-
-	lock_kernel();
-
-	smb_lock_server(server);
-	server->state = CONN_INVALID;
-	smbiod_unregister_server(server);
-
-	smb_close_socket(server);
-
-	if (server->conn_pid)
-		kill_pid(server->conn_pid, SIGTERM, 1);
-
-	bdi_destroy(&server->bdi);
-	kfree(server->ops);
-	smb_unload_nls(server);
-	sb->s_fs_info = NULL;
-	smb_unlock_server(server);
-	put_pid(server->conn_pid);
-	kfree(server);
-
-	unlock_kernel();
-}
-
-static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
-{
-	struct smb_sb_info *server;
-	struct smb_mount_data_kernel *mnt;
-	struct smb_mount_data *oldmnt;
-	struct inode *root_inode;
-	struct smb_fattr root;
-	int ver;
-	void *mem;
-	static int warn_count;
-
-	lock_kernel();
-
-	if (warn_count < 5) {
-		warn_count++;
-		printk(KERN_EMERG "smbfs is deprecated and will be removed"
-			" from the 2.6.37 kernel. Please migrate to cifs\n");
-	}
-
-	if (!raw_data)
-		goto out_no_data;
-
-	oldmnt = (struct smb_mount_data *) raw_data;
-	ver = oldmnt->version;
-	if (ver != SMB_MOUNT_OLDVERSION && cpu_to_be32(ver) != SMB_MOUNT_ASCII)
-		goto out_wrong_data;
-
-	sb->s_flags |= MS_NODIRATIME;
-	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
-	sb->s_blocksize_bits = 10;
-	sb->s_magic = SMB_SUPER_MAGIC;
-	sb->s_op = &smb_sops;
-	sb->s_time_gran = 100;
-
-	server = kzalloc(sizeof(struct smb_sb_info), GFP_KERNEL);
-	if (!server)
-		goto out_no_server;
-	sb->s_fs_info = server;
-	
-	if (bdi_setup_and_register(&server->bdi, "smbfs", BDI_CAP_MAP_COPY))
-		goto out_bdi;
-
-	sb->s_bdi = &server->bdi;
-
-	server->super_block = sb;
-	server->mnt = NULL;
-	server->sock_file = NULL;
-	init_waitqueue_head(&server->conn_wq);
-	sema_init(&server->sem, 1);
-	INIT_LIST_HEAD(&server->entry);
-	INIT_LIST_HEAD(&server->xmitq);
-	INIT_LIST_HEAD(&server->recvq);
-	server->conn_error = 0;
-	server->conn_pid = NULL;
-	server->state = CONN_INVALID; /* no connection yet */
-	server->generation = 0;
-
-	/* Allocate the global temp buffer and some superblock helper structs */
-	/* FIXME: move these to the smb_sb_info struct */
-	VERBOSE("alloc chunk = %lu\n", sizeof(struct smb_ops) +
-		sizeof(struct smb_mount_data_kernel));
-	mem = kmalloc(sizeof(struct smb_ops) +
-		      sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
-	if (!mem)
-		goto out_no_mem;
-
-	server->ops = mem;
-	smb_install_null_ops(server->ops);
-	server->mnt = mem + sizeof(struct smb_ops);
-
-	/* Setup NLS stuff */
-	server->remote_nls = NULL;
-	server->local_nls = NULL;
-
-	mnt = server->mnt;
-
-	memset(mnt, 0, sizeof(struct smb_mount_data_kernel));
-	strlcpy(mnt->codepage.local_name, CONFIG_NLS_DEFAULT,
-		SMB_NLS_MAXNAMELEN);
-	strlcpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
-		SMB_NLS_MAXNAMELEN);
-
-	mnt->ttl = SMB_TTL_DEFAULT;
-	if (ver == SMB_MOUNT_OLDVERSION) {
-		mnt->version = oldmnt->version;
-
-		SET_UID(mnt->uid, oldmnt->uid);
-		SET_GID(mnt->gid, oldmnt->gid);
-
-		mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
-		mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
-
-		mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID |
-			SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE;
-	} else {
-		mnt->file_mode = S_IRWXU | S_IRGRP | S_IXGRP |
-				S_IROTH | S_IXOTH | S_IFREG;
-		mnt->dir_mode = S_IRWXU | S_IRGRP | S_IXGRP |
-				S_IROTH | S_IXOTH | S_IFDIR;
-		if (parse_options(mnt, raw_data))
-			goto out_bad_option;
-	}
-	mnt->mounted_uid = current_uid();
-	smb_setcodepage(server, &mnt->codepage);
-
-	/*
-	 * Display the enabled options
-	 * Note: smb_proc_getattr uses these in 2.4 (but was changed in 2.2)
-	 */
-	if (mnt->flags & SMB_MOUNT_OLDATTR)
-		printk("SMBFS: Using core getattr (Win 95 speedup)\n");
-	else if (mnt->flags & SMB_MOUNT_DIRATTR)
-		printk("SMBFS: Using dir ff getattr\n");
-
-	if (smbiod_register_server(server) < 0) {
-		printk(KERN_ERR "smbfs: failed to start smbiod\n");
-		goto out_no_smbiod;
-	}
-	if (server->mnt->flags & SMB_MOUNT_CASE)
-		sb->s_d_op = &smbfs_dentry_operations_case;
-	else
-		sb->s_d_op = &smbfs_dentry_operations;
-
-	/*
-	 * Keep the super block locked while we get the root inode.
-	 */
-	smb_init_root_dirent(server, &root, sb);
-	root_inode = smb_iget(sb, &root);
-	if (!root_inode)
-		goto out_no_root;
-
-	sb->s_root = d_alloc_root(root_inode);
-	if (!sb->s_root)
-		goto out_no_root;
-
-	smb_new_dentry(sb->s_root);
-
-	unlock_kernel();
-	return 0;
-
-out_no_root:
-	iput(root_inode);
-out_no_smbiod:
-	smb_unload_nls(server);
-out_bad_option:
-	kfree(mem);
-out_no_mem:
-	bdi_destroy(&server->bdi);
-out_bdi:
-	if (!server->mnt)
-		printk(KERN_ERR "smb_fill_super: allocation failure\n");
-	sb->s_fs_info = NULL;
-	kfree(server);
-	goto out_fail;
-out_wrong_data:
-	printk(KERN_ERR "smbfs: mount_data version %d is not supported\n", ver);
-	goto out_fail;
-out_no_data:
-	printk(KERN_ERR "smb_fill_super: missing data argument\n");
-out_fail:
-	unlock_kernel();
-	return -EINVAL;
-out_no_server:
-	printk(KERN_ERR "smb_fill_super: cannot allocate struct smb_sb_info\n");
-	unlock_kernel();
-	return -ENOMEM;
-}
-
-static int
-smb_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-	int result;
-	
-	lock_kernel();
-
-	result = smb_proc_dskattr(dentry, buf);
-
-	unlock_kernel();
-
-	buf->f_type = SMB_SUPER_MAGIC;
-	buf->f_namelen = SMB_MAXPATHLEN;
-	return result;
-}
-
-int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
-{
-	int err = smb_revalidate_inode(dentry);
-	if (!err)
-		generic_fillattr(dentry->d_inode, stat);
-	return err;
-}
-
-int
-smb_notify_change(struct dentry *dentry, struct iattr *attr)
-{
-	struct inode *inode = dentry->d_inode;
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
-	int error, changed, refresh = 0;
-	struct smb_fattr fattr;
-
-	lock_kernel();
-
-	error = smb_revalidate_inode(dentry);
-	if (error)
-		goto out;
-
-	if ((error = inode_change_ok(inode, attr)) < 0)
-		goto out;
-
-	error = -EPERM;
-	if ((attr->ia_valid & ATTR_UID) && (attr->ia_uid != server->mnt->uid))
-		goto out;
-
-	if ((attr->ia_valid & ATTR_GID) && (attr->ia_uid != server->mnt->gid))
-		goto out;
-
-	if ((attr->ia_valid & ATTR_MODE) && (attr->ia_mode & ~mask))
-		goto out;
-
-	if ((attr->ia_valid & ATTR_SIZE) != 0) {
-		VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
-			DENTRY_PATH(dentry),
-			(long) inode->i_size, (long) attr->ia_size);
-
-		filemap_write_and_wait(inode->i_mapping);
-
-		error = smb_open(dentry, O_WRONLY);
-		if (error)
-			goto out;
-		error = server->ops->truncate(inode, attr->ia_size);
-		if (error)
-			goto out;
-		truncate_setsize(inode, attr->ia_size);
-		refresh = 1;
-	}
-
-	if (server->opt.capabilities & SMB_CAP_UNIX) {
-		/* For now we don't want to set the size with setattr_unix */
-		attr->ia_valid &= ~ATTR_SIZE;
-		/* FIXME: only call if we actually want to set something? */
-		error = smb_proc_setattr_unix(dentry, attr, 0, 0);
-		if (!error)
-			refresh = 1;
-
-		goto out;
-	}
-
-	/*
-	 * Initialize the fattr and check for changed fields.
-	 * Note: CTIME under SMB is creation time rather than
-	 * change time, so we don't attempt to change it.
-	 */
-	smb_get_inode_attr(inode, &fattr);
-
-	changed = 0;
-	if ((attr->ia_valid & ATTR_MTIME) != 0) {
-		fattr.f_mtime = attr->ia_mtime;
-		changed = 1;
-	}
-	if ((attr->ia_valid & ATTR_ATIME) != 0) {
-		fattr.f_atime = attr->ia_atime;
-		/* Earlier protocols don't have an access time */
-		if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
-			changed = 1;
-	}
-	if (changed) {
-		error = smb_proc_settime(dentry, &fattr);
-		if (error)
-			goto out;
-		refresh = 1;
-	}
-
-	/*
-	 * Check for mode changes ... we're extremely limited in
-	 * what can be set for SMB servers: just the read-only bit.
-	 */
-	if ((attr->ia_valid & ATTR_MODE) != 0) {
-		VERBOSE("%s/%s mode change, old=%x, new=%x\n",
-			DENTRY_PATH(dentry), fattr.f_mode, attr->ia_mode);
-		changed = 0;
-		if (attr->ia_mode & S_IWUSR) {
-			if (fattr.attr & aRONLY) {
-				fattr.attr &= ~aRONLY;
-				changed = 1;
-			}
-		} else {
-			if (!(fattr.attr & aRONLY)) {
-				fattr.attr |= aRONLY;
-				changed = 1;
-			}
-		}
-		if (changed) {
-			error = smb_proc_setattr(dentry, &fattr);
-			if (error)
-				goto out;
-			refresh = 1;
-		}
-	}
-	error = 0;
-
-out:
-	if (refresh)
-		smb_refresh_inode(dentry);
-	unlock_kernel();
-	return error;
-}
-
-static struct dentry *smb_mount(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
-{
-	return mount_nodev(fs_type, flags, data, smb_fill_super);
-}
-
-static struct file_system_type smb_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "smbfs",
-	.mount		= smb_mount,
-	.kill_sb	= kill_anon_super,
-	.fs_flags	= FS_BINARY_MOUNTDATA,
-};
-
-static int __init init_smb_fs(void)
-{
-	int err;
-	DEBUG1("registering ...\n");
-
-	err = init_inodecache();
-	if (err)
-		goto out_inode;
-	err = smb_init_request_cache();
-	if (err)
-		goto out_request;
-	err = register_filesystem(&smb_fs_type);
-	if (err)
-		goto out;
-	return 0;
-out:
-	smb_destroy_request_cache();
-out_request:
-	destroy_inodecache();
-out_inode:
-	return err;
-}
-
-static void __exit exit_smb_fs(void)
-{
-	DEBUG1("unregistering ...\n");
-	unregister_filesystem(&smb_fs_type);
-	smb_destroy_request_cache();
-	destroy_inodecache();
-}
-
-module_init(init_smb_fs)
-module_exit(exit_smb_fs)
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/smbfs/ioctl.c b/drivers/staging/smbfs/ioctl.c
deleted file mode 100644
index 2da1692..0000000
--- a/drivers/staging/smbfs/ioctl.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  ioctl.c
- *
- *  Copyright (C) 1995, 1996 by Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/time.h>
-#include <linux/mm.h>
-#include <linux/highuid.h>
-#include <linux/smp_lock.h>
-#include <linux/net.h>
-
-#include <asm/uaccess.h>
-
-#include "smb_fs.h"
-#include "smb_mount.h"
-#include "proto.h"
-
-long
-smb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	struct smb_sb_info *server = server_from_inode(filp->f_path.dentry->d_inode);
-	struct smb_conn_opt opt;
-	int result = -EINVAL;
-
-	lock_kernel();
-	switch (cmd) {
-		uid16_t uid16;
-		uid_t uid32;
-	case SMB_IOC_GETMOUNTUID:
-		SET_UID(uid16, server->mnt->mounted_uid);
-		result = put_user(uid16, (uid16_t __user *) arg);
-		break;
-	case SMB_IOC_GETMOUNTUID32:
-		SET_UID(uid32, server->mnt->mounted_uid);
-		result = put_user(uid32, (uid_t __user *) arg);
-		break;
-
-	case SMB_IOC_NEWCONN:
-		/* arg is smb_conn_opt, or NULL if no connection was made */
-		if (!arg) {
-			result = 0;
-			smb_lock_server(server);
-			server->state = CONN_RETRIED;
-			printk(KERN_ERR "Connection attempt failed!  [%d]\n",
-			       server->conn_error);
-			smbiod_flush(server);
-			smb_unlock_server(server);
-			break;
-		}
-
-		result = -EFAULT;
-		if (!copy_from_user(&opt, (void __user *)arg, sizeof(opt)))
-			result = smb_newconn(server, &opt);
-		break;
-	default:
-		break;
-	}
-	unlock_kernel();
-
-	return result;
-}
diff --git a/drivers/staging/smbfs/proc.c b/drivers/staging/smbfs/proc.c
deleted file mode 100644
index ba37b1f..0000000
--- a/drivers/staging/smbfs/proc.c
+++ /dev/null
@@ -1,3502 +0,0 @@
-/*
- *  proc.c
- *
- *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/types.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/stat.h>
-#include <linux/fcntl.h>
-#include <linux/dcache.h>
-#include <linux/nls.h>
-#include <linux/smp_lock.h>
-#include <linux/net.h>
-#include <linux/vfs.h>
-#include <net/sock.h>
-
-#include <asm/string.h>
-#include <asm/div64.h>
-
-#include "smb_fs.h"
-#include "smbno.h"
-#include "smb_mount.h"
-#include "smb_debug.h"
-#include "proto.h"
-#include "request.h"
-
-
-/* Features. Undefine if they cause problems, this should perhaps be a
-   config option. */
-#define SMBFS_POSIX_UNLINK 1
-
-/* Allow smb_retry to be interrupted. */
-#define SMB_RETRY_INTR
-
-#define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)
-#define SMB_CMD(packet)  (*(packet+8))
-#define SMB_WCT(packet)  (*(packet+SMB_HEADER_LEN - 1))
-
-#define SMB_DIRINFO_SIZE 43
-#define SMB_STATUS_SIZE  21
-
-#define SMB_ST_BLKSIZE	(PAGE_SIZE)
-#define SMB_ST_BLKSHIFT	(PAGE_SHIFT)
-
-static struct smb_ops smb_ops_core;
-static struct smb_ops smb_ops_os2;
-static struct smb_ops smb_ops_win95;
-static struct smb_ops smb_ops_winNT;
-static struct smb_ops smb_ops_unix;
-static struct smb_ops smb_ops_null;
-
-static void
-smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
-static void
-smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr);
-static int
-smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
-		      struct smb_fattr *fattr);
-static int
-smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
-		    struct smb_fattr *fattr);
-static int
-smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
-		      u16 attr);
-static int
-smb_proc_setattr_ext(struct smb_sb_info *server,
-		     struct inode *inode, struct smb_fattr *fattr);
-static int
-smb_proc_query_cifsunix(struct smb_sb_info *server);
-static void
-install_ops(struct smb_ops *dst, struct smb_ops *src);
-
-
-static void
-str_upper(char *name, int len)
-{
-	while (len--)
-	{
-		if (*name >= 'a' && *name <= 'z')
-			*name -= ('a' - 'A');
-		name++;
-	}
-}
-
-#if 0
-static void
-str_lower(char *name, int len)
-{
-	while (len--)
-	{
-		if (*name >= 'A' && *name <= 'Z')
-			*name += ('a' - 'A');
-		name++;
-	}
-}
-#endif
-
-/* reverse a string inline. This is used by the dircache walking routines */
-static void reverse_string(char *buf, int len)
-{
-	char c;
-	char *end = buf+len-1;
-
-	while(buf < end) {
-		c = *buf;
-		*(buf++) = *end;
-		*(end--) = c;
-	}
-}
-
-/* no conversion, just a wrapper for memcpy. */
-static int convert_memcpy(unsigned char *output, int olen,
-			  const unsigned char *input, int ilen,
-			  struct nls_table *nls_from,
-			  struct nls_table *nls_to)
-{
-	if (olen < ilen)
-		return -ENAMETOOLONG;
-	memcpy(output, input, ilen);
-	return ilen;
-}
-
-static inline int write_char(unsigned char ch, char *output, int olen)
-{
-	if (olen < 4)
-		return -ENAMETOOLONG;
-	sprintf(output, ":x%02x", ch);
-	return 4;
-}
-
-static inline int write_unichar(wchar_t ch, char *output, int olen)
-{
-	if (olen < 5)
-		return -ENAMETOOLONG;
-	sprintf(output, ":%04x", ch);
-	return 5;
-}
-
-/* convert from one "codepage" to another (possibly being utf8). */
-static int convert_cp(unsigned char *output, int olen,
-		      const unsigned char *input, int ilen,
-		      struct nls_table *nls_from,
-		      struct nls_table *nls_to)
-{
-	int len = 0;
-	int n;
-	wchar_t ch;
-
-	while (ilen > 0) {
-		/* convert by changing to unicode and back to the new cp */
-		n = nls_from->char2uni(input, ilen, &ch);
-		if (n == -EINVAL) {
-			ilen--;
-			n = write_char(*input++, output, olen);
-			if (n < 0)
-				goto fail;
-			output += n;
-			olen -= n;
-			len += n;
-			continue;
-		} else if (n < 0)
-			goto fail;
-		input += n;
-		ilen -= n;
-
-		n = nls_to->uni2char(ch, output, olen);
-		if (n == -EINVAL)
-			n = write_unichar(ch, output, olen);
-		if (n < 0)
-			goto fail;
-		output += n;
-		olen -= n;
-
-		len += n;
-	}
-	return len;
-fail:
-	return n;
-}
-
-/* ----------------------------------------------------------- */
-
-/*
- * nls_unicode
- *
- * This encodes/decodes little endian unicode format
- */
-
-static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
-{
-	if (boundlen < 2)
-		return -EINVAL;
-	*out++ = uni & 0xff;
-	*out++ = uni >> 8;
-	return 2;
-}
-
-static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
-{
-	if (boundlen < 2)
-		return -EINVAL;
-	*uni = (rawstring[1] << 8) | rawstring[0];
-	return 2;
-}
-
-static struct nls_table unicode_table = {
-	.charset	= "unicode",
-	.uni2char	= uni2char,
-	.char2uni	= char2uni,
-};
-
-/* ----------------------------------------------------------- */
-
-static int setcodepage(struct nls_table **p, char *name)
-{
-	struct nls_table *nls;
-
-	if (!name || !*name) {
-		nls = NULL;
-	} else if ( (nls = load_nls(name)) == NULL) {
-		printk (KERN_ERR "smbfs: failed to load nls '%s'\n", name);
-		return -EINVAL;
-	}
-
-	/* if already set, unload the previous one. */
-	if (*p && *p != &unicode_table)
-		unload_nls(*p);
-	*p = nls;
-
-	return 0;
-}
-
-/* Handles all changes to codepage settings. */
-int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp)
-{
-	int n = 0;
-
-	smb_lock_server(server);
-
-	/* Don't load any nls_* at all, if no remote is requested */
-	if (!*cp->remote_name)
-		goto out;
-
-	/* local */
-	n = setcodepage(&server->local_nls, cp->local_name);
-	if (n != 0)
-		goto out;
-
-	/* remote */
-	if (!strcmp(cp->remote_name, "unicode")) {
-		server->remote_nls = &unicode_table;
-	} else {
-		n = setcodepage(&server->remote_nls, cp->remote_name);
-		if (n != 0)
-			setcodepage(&server->local_nls, NULL);
-	}
-
-out:
-	if (server->local_nls != NULL && server->remote_nls != NULL)
-		server->ops->convert = convert_cp;
-	else
-		server->ops->convert = convert_memcpy;
-
-	smb_unlock_server(server);
-	return n;
-}
-
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Encoding/Decoding section                                                */
-/*                                                                           */
-/*****************************************************************************/
-
-static __u8 *
-smb_encode_smb_length(__u8 * p, __u32 len)
-{
-	*p = 0;
-	*(p+1) = 0;
-	*(p+2) = (len & 0xFF00) >> 8;
-	*(p+3) = (len & 0xFF);
-	if (len > 0xFFFF)
-	{
-		*(p+1) = 1;
-	}
-	return p + 4;
-}
-
-/*
- * smb_build_path: build the path to entry and name storing it in buf.
- * The path returned will have the trailing '\0'.
- */
-static int smb_build_path(struct smb_sb_info *server, unsigned char *buf,
-			  int maxlen,
-			  struct dentry *entry, struct qstr *name)
-{
-	unsigned char *path = buf;
-	int len;
-	int unicode = (server->mnt->flags & SMB_MOUNT_UNICODE) != 0;
-
-	if (maxlen < (2<<unicode))
-		return -ENAMETOOLONG;
-
-	if (maxlen > SMB_MAXPATHLEN + 1)
-		maxlen = SMB_MAXPATHLEN + 1;
-
-	if (entry == NULL)
-		goto test_name_and_out;
-
-	/*
-	 * If IS_ROOT, we have to do no walking at all.
-	 */
-	if (IS_ROOT(entry) && !name) {
-		*path++ = '\\';
-		if (unicode) *path++ = '\0';
-		*path++ = '\0';
-		if (unicode) *path++ = '\0';
-		return path-buf;
-	}
-
-	/*
-	 * Build the path string walking the tree backward from end to ROOT
-	 * and store it in reversed order [see reverse_string()]
-	 */
-	dget(entry);
-	while (!IS_ROOT(entry)) {
-		struct dentry *parent;
-
-		if (maxlen < (3<<unicode)) {
-			dput(entry);
-			return -ENAMETOOLONG;
-		}
-
-		spin_lock(&entry->d_lock);
-		len = server->ops->convert(path, maxlen-2, 
-				      entry->d_name.name, entry->d_name.len,
-				      server->local_nls, server->remote_nls);
-		if (len < 0) {
-			spin_unlock(&entry->d_lock);
-			dput(entry);
-			return len;
-		}
-		reverse_string(path, len);
-		path += len;
-		if (unicode) {
-			/* Note: reverse order */
-			*path++ = '\0';
-			maxlen--;
-		}
-		*path++ = '\\';
-		maxlen -= len+1;
-		spin_unlock(&entry->d_lock);
-
-		parent = dget_parent(entry);
-		dput(entry);
-		entry = parent;
-	}
-	dput(entry);
-	reverse_string(buf, path-buf);
-
-	/* maxlen has space for at least one char */
-test_name_and_out:
-	if (name) {
-		if (maxlen < (3<<unicode))
-			return -ENAMETOOLONG;
-		*path++ = '\\';
-		if (unicode) {
-			*path++ = '\0';
-			maxlen--;
-		}
-		len = server->ops->convert(path, maxlen-2, 
-				      name->name, name->len,
-				      server->local_nls, server->remote_nls);
-		if (len < 0)
-			return len;
-		path += len;
-		maxlen -= len+1;
-	}
-	/* maxlen has space for at least one char */
-	*path++ = '\0';
-	if (unicode) *path++ = '\0';
-	return path-buf;
-}
-
-static int smb_encode_path(struct smb_sb_info *server, char *buf, int maxlen,
-			   struct dentry *dir, struct qstr *name)
-{
-	int result;
-
-	result = smb_build_path(server, buf, maxlen, dir, name);
-	if (result < 0)
-		goto out;
-	if (server->opt.protocol <= SMB_PROTOCOL_COREPLUS)
-		str_upper(buf, result);
-out:
-	return result;
-}
-
-/* encode_path for non-trans2 request SMBs */
-static int smb_simple_encode_path(struct smb_request *req, char **p,
-				  struct dentry * entry, struct qstr * name)
-{
-	struct smb_sb_info *server = req->rq_server;
-	char *s = *p;
-	int res;
-	int maxlen = ((char *)req->rq_buffer + req->rq_bufsize) - s;
-	int unicode = (server->mnt->flags & SMB_MOUNT_UNICODE);
-
-	if (!maxlen)
-		return -ENAMETOOLONG;
-	*s++ = 4;	/* ASCII data format */
-
-	/*
-	 * SMB Unicode strings must be 16bit aligned relative the start of the
-	 * packet. If they are not they must be padded with 0.
-	 */
-	if (unicode) {
-		int align = s - (char *)req->rq_buffer;
-		if (!(align & 1)) {
-			*s++ = '\0';
-			maxlen--;
-		}
-	}
-
-	res = smb_encode_path(server, s, maxlen-1, entry, name);
-	if (res < 0)
-		return res;
-	*p = s + res;
-	return 0;
-}
-
-/* The following are taken directly from msdos-fs */
-
-/* Linear day numbers of the respective 1sts in non-leap years. */
-
-static int day_n[] =
-{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
-		  /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
-
-
-static time_t
-utc2local(struct smb_sb_info *server, time_t time)
-{
-	return time - server->opt.serverzone*60;
-}
-
-static time_t
-local2utc(struct smb_sb_info *server, time_t time)
-{
-	return time + server->opt.serverzone*60;
-}
-
-/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
-
-static time_t
-date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time)
-{
-	int month, year;
-	time_t secs;
-
-	/* first subtract and mask after that... Otherwise, if
-	   date == 0, bad things happen */
-	month = ((date >> 5) - 1) & 15;
-	year = date >> 9;
-	secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *
-	    ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&
-						   month < 2 ? 1 : 0) + 3653);
-	/* days since 1.1.70 plus 80's leap day */
-	return local2utc(server, secs);
-}
-
-
-/* Convert linear UNIX date to a MS-DOS time/date pair. */
-
-static void
-date_unix2dos(struct smb_sb_info *server,
-	      int unix_date, __u16 *date, __u16 *time)
-{
-	int day, year, nl_day, month;
-
-	unix_date = utc2local(server, unix_date);
-	if (unix_date < 315532800)
-		unix_date = 315532800;
-
-	*time = (unix_date % 60) / 2 +
-		(((unix_date / 60) % 60) << 5) +
-		(((unix_date / 3600) % 24) << 11);
-
-	day = unix_date / 86400 - 3652;
-	year = day / 365;
-	if ((year + 3) / 4 + 365 * year > day)
-		year--;
-	day -= (year + 3) / 4 + 365 * year;
-	if (day == 59 && !(year & 3)) {
-		nl_day = day;
-		month = 2;
-	} else {
-		nl_day = (year & 3) || day <= 59 ? day : day - 1;
-		for (month = 1; month < 12; month++)
-			if (day_n[month] > nl_day)
-				break;
-	}
-	*date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9);
-}
-
-/* The following are taken from fs/ntfs/util.c */
-
-#define NTFS_TIME_OFFSET ((u64)(369*365 + 89) * 24 * 3600 * 10000000)
-
-/*
- * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
- * into Unix UTC (based 1970-01-01, in seconds).
- */
-static struct timespec
-smb_ntutc2unixutc(u64 ntutc)
-{
-	struct timespec ts;
-	/* FIXME: what about the timezone difference? */
-	/* Subtract the NTFS time offset, then convert to 1s intervals. */
-	u64 t = ntutc - NTFS_TIME_OFFSET;
-	ts.tv_nsec = do_div(t, 10000000) * 100;
-	ts.tv_sec = t; 
-	return ts;
-}
-
-/* Convert the Unix UTC into NT time */
-static u64
-smb_unixutc2ntutc(struct timespec ts)
-{
-	/* Note: timezone conversion is probably wrong. */
-	/* return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET; */
-	return ((u64)ts.tv_sec) * 10000000 + ts.tv_nsec/100 + NTFS_TIME_OFFSET;
-}
-
-#define MAX_FILE_MODE	6
-static mode_t file_mode[] = {
-	S_IFREG, S_IFDIR, S_IFLNK, S_IFCHR, S_IFBLK, S_IFIFO, S_IFSOCK
-};
-
-static int smb_filetype_to_mode(u32 filetype)
-{
-	if (filetype > MAX_FILE_MODE) {
-		PARANOIA("Filetype out of range: %d\n", filetype);
-		return S_IFREG;
-	}
-	return file_mode[filetype];
-}
-
-static u32 smb_filetype_from_mode(int mode)
-{
-	if (S_ISREG(mode))
-		return UNIX_TYPE_FILE;
-	if (S_ISDIR(mode))
-		return UNIX_TYPE_DIR;
-	if (S_ISLNK(mode))
-		return UNIX_TYPE_SYMLINK;
-	if (S_ISCHR(mode))
-		return UNIX_TYPE_CHARDEV;
-	if (S_ISBLK(mode))
-		return UNIX_TYPE_BLKDEV;
-	if (S_ISFIFO(mode))
-		return UNIX_TYPE_FIFO;
-	if (S_ISSOCK(mode))
-		return UNIX_TYPE_SOCKET;
-	return UNIX_TYPE_UNKNOWN;
-}
-
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Support section.                                                         */
-/*                                                                           */
-/*****************************************************************************/
-
-__u32
-smb_len(__u8 * p)
-{
-	return ((*(p+1) & 0x1) << 16L) | (*(p+2) << 8L) | *(p+3);
-}
-
-static __u16
-smb_bcc(__u8 * packet)
-{
-	int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(__u16);
-	return WVAL(packet, pos);
-}
-
-/* smb_valid_packet: We check if packet fulfills the basic
-   requirements of a smb packet */
-
-static int
-smb_valid_packet(__u8 * packet)
-{
-	return (packet[4] == 0xff
-		&& packet[5] == 'S'
-		&& packet[6] == 'M'
-		&& packet[7] == 'B'
-		&& (smb_len(packet) + 4 == SMB_HEADER_LEN
-		    + SMB_WCT(packet) * 2 + smb_bcc(packet)));
-}
-
-/* smb_verify: We check if we got the answer we expected, and if we
-   got enough data. If bcc == -1, we don't care. */
-
-static int
-smb_verify(__u8 * packet, int command, int wct, int bcc)
-{
-	if (SMB_CMD(packet) != command)
-		goto bad_command;
-	if (SMB_WCT(packet) < wct)
-		goto bad_wct;
-	if (bcc != -1 && smb_bcc(packet) < bcc)
-		goto bad_bcc;
-	return 0;
-
-bad_command:
-	printk(KERN_ERR "smb_verify: command=%x, SMB_CMD=%x??\n",
-	       command, SMB_CMD(packet));
-	goto fail;
-bad_wct:
-	printk(KERN_ERR "smb_verify: command=%x, wct=%d, SMB_WCT=%d??\n",
-	       command, wct, SMB_WCT(packet));
-	goto fail;
-bad_bcc:
-	printk(KERN_ERR "smb_verify: command=%x, bcc=%d, SMB_BCC=%d??\n",
-	       command, bcc, smb_bcc(packet));
-fail:
-	return -EIO;
-}
-
-/*
- * Returns the maximum read or write size for the "payload". Making all of the
- * packet fit within the negotiated max_xmit size.
- *
- * N.B. Since this value is usually computed before locking the server,
- * the server's packet size must never be decreased!
- */
-static inline int
-smb_get_xmitsize(struct smb_sb_info *server, int overhead)
-{
-	return server->opt.max_xmit - overhead;
-}
-
-/*
- * Calculate the maximum read size
- */
-int
-smb_get_rsize(struct smb_sb_info *server)
-{
-	/* readX has 12 parameters, read has 5 */
-	int overhead = SMB_HEADER_LEN + 12 * sizeof(__u16) + 2 + 1 + 2;
-	int size = smb_get_xmitsize(server, overhead);
-
-	VERBOSE("xmit=%d, size=%d\n", server->opt.max_xmit, size);
-
-	return size;
-}
-
-/*
- * Calculate the maximum write size
- */
-int
-smb_get_wsize(struct smb_sb_info *server)
-{
-	/* writeX has 14 parameters, write has 5 */
-	int overhead = SMB_HEADER_LEN + 14 * sizeof(__u16) + 2 + 1 + 2;
-	int size = smb_get_xmitsize(server, overhead);
-
-	VERBOSE("xmit=%d, size=%d\n", server->opt.max_xmit, size);
-
-	return size;
-}
-
-/*
- * Convert SMB error codes to -E... errno values.
- */
-int
-smb_errno(struct smb_request *req)
-{
-	int errcls = req->rq_rcls;
-	int error  = req->rq_err;
-	char *class = "Unknown";
-
-	VERBOSE("errcls %d  code %d  from command 0x%x\n",
-		errcls, error, SMB_CMD(req->rq_header));
-
-	if (errcls == ERRDOS) {
-		switch (error) {
-		case ERRbadfunc:
-			return -EINVAL;
-		case ERRbadfile:
-		case ERRbadpath:
-			return -ENOENT;
-		case ERRnofids:
-			return -EMFILE;
-		case ERRnoaccess:
-			return -EACCES;
-		case ERRbadfid:
-			return -EBADF;
-		case ERRbadmcb:
-			return -EREMOTEIO;
-		case ERRnomem:
-			return -ENOMEM;
-		case ERRbadmem:
-			return -EFAULT;
-		case ERRbadenv:
-		case ERRbadformat:
-			return -EREMOTEIO;
-		case ERRbadaccess:
-			return -EACCES;
-		case ERRbaddata:
-			return -E2BIG;
-		case ERRbaddrive:
-			return -ENXIO;
-		case ERRremcd:
-			return -EREMOTEIO;
-		case ERRdiffdevice:
-			return -EXDEV;
-		case ERRnofiles:
-			return -ENOENT;
-		case ERRbadshare:
-			return -ETXTBSY;
-		case ERRlock:
-			return -EDEADLK;
-		case ERRfilexists:
-			return -EEXIST;
-		case ERROR_INVALID_PARAMETER:
-			return -EINVAL;
-		case ERROR_DISK_FULL:
-			return -ENOSPC;
-		case ERROR_INVALID_NAME:
-			return -ENOENT;
-		case ERROR_DIR_NOT_EMPTY:
-			return -ENOTEMPTY;
-		case ERROR_NOT_LOCKED:
-                       return -ENOLCK;
-		case ERROR_ALREADY_EXISTS:
-			return -EEXIST;
-		default:
-			class = "ERRDOS";
-			goto err_unknown;
-		}
-	} else if (errcls == ERRSRV) {
-		switch (error) {
-		/* N.B. This is wrong ... EIO ? */
-		case ERRerror:
-			return -ENFILE;
-		case ERRbadpw:
-			return -EINVAL;
-		case ERRbadtype:
-		case ERRtimeout:
-			return -EIO;
-		case ERRaccess:
-			return -EACCES;
-		/*
-		 * This is a fatal error, as it means the "tree ID"
-		 * for this connection is no longer valid. We map
-		 * to a special error code and get a new connection.
-		 */
-		case ERRinvnid:
-			return -EBADSLT;
-		default:
-			class = "ERRSRV";
-			goto err_unknown;
-		}
-	} else if (errcls == ERRHRD) {
-		switch (error) {
-		case ERRnowrite:
-			return -EROFS;
-		case ERRbadunit:
-			return -ENODEV;
-		case ERRnotready:
-			return -EUCLEAN;
-		case ERRbadcmd:
-		case ERRdata:
-			return -EIO;
-		case ERRbadreq:
-			return -ERANGE;
-		case ERRbadshare:
-			return -ETXTBSY;
-		case ERRlock:
-			return -EDEADLK;
-		case ERRdiskfull:
-			return -ENOSPC;
-		default:
-			class = "ERRHRD";
-			goto err_unknown;
-		}
-	} else if (errcls == ERRCMD) {
-		class = "ERRCMD";
-	} else if (errcls == SUCCESS) {
-		return 0;	/* This is the only valid 0 return */
-	}
-
-err_unknown:
-	printk(KERN_ERR "smb_errno: class %s, code %d from command 0x%x\n",
-	       class, error, SMB_CMD(req->rq_header));
-	return -EIO;
-}
-
-/* smb_request_ok: We expect the server to be locked. Then we do the
-   request and check the answer completely. When smb_request_ok
-   returns 0, you can be quite sure that everything went well. When
-   the answer is <=0, the returned number is a valid unix errno. */
-
-static int
-smb_request_ok(struct smb_request *req, int command, int wct, int bcc)
-{
-	int result;
-
-	req->rq_resp_wct = wct;
-	req->rq_resp_bcc = bcc;
-
-	result = smb_add_request(req);
-	if (result != 0) {
-		DEBUG1("smb_request failed\n");
-		goto out;
-	}
-
-	if (smb_valid_packet(req->rq_header) != 0) {
-		PARANOIA("invalid packet!\n");
-		goto out;
-	}
-
-	result = smb_verify(req->rq_header, command, wct, bcc);
-
-out:
-	return result;
-}
-
-/*
- * This implements the NEWCONN ioctl. It installs the server pid,
- * sets server->state to CONN_VALID, and wakes up the waiting process.
- */
-int
-smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
-{
-	struct file *filp;
-	struct sock *sk;
-	int error;
-
-	VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
-
-	smb_lock_server(server);
-
-	/*
-	 * Make sure we don't already have a valid connection ...
-	 */
-	error = -EINVAL;
-	if (server->state == CONN_VALID)
-		goto out;
-
-	error = -EACCES;
-	if (current_uid() != server->mnt->mounted_uid &&
-	    !capable(CAP_SYS_ADMIN))
-		goto out;
-
-	error = -EBADF;
-	filp = fget(opt->fd);
-	if (!filp)
-		goto out;
-	if (!smb_valid_socket(filp->f_path.dentry->d_inode))
-		goto out_putf;
-
-	server->sock_file = filp;
-	server->conn_pid = get_pid(task_pid(current));
-	server->opt = *opt;
-	server->generation += 1;
-	server->state = CONN_VALID;
-	error = 0;
-
-	if (server->conn_error) {
-		/*
-		 * conn_error is the returncode we originally decided to
-		 * drop the old connection on. This message should be positive
-		 * and not make people ask questions on why smbfs is printing
-		 * error messages ...
-		 */
-		printk(KERN_INFO "SMB connection re-established (%d)\n",
-		       server->conn_error);
-		server->conn_error = 0;
-	}
-
-	/*
-	 * Store the server in sock user_data (Only used by sunrpc)
-	 */
-	sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk;
-	sk->sk_user_data = server;
-
-	/* chain into the data_ready callback */
-	server->data_ready = xchg(&sk->sk_data_ready, smb_data_ready);
-
-	/* check if we have an old smbmount that uses seconds for the 
-	   serverzone */
-	if (server->opt.serverzone > 12*60 || server->opt.serverzone < -12*60)
-		server->opt.serverzone /= 60;
-
-	/* now that we have an established connection we can detect the server
-	   type and enable bug workarounds */
-	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
-		install_ops(server->ops, &smb_ops_core);
-	else if (server->opt.protocol == SMB_PROTOCOL_LANMAN2)
-		install_ops(server->ops, &smb_ops_os2);
-	else if (server->opt.protocol == SMB_PROTOCOL_NT1 &&
-		 (server->opt.max_xmit < 0x1000) &&
-		 !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
-		/* FIXME: can we kill the WIN95 flag now? */
-		server->mnt->flags |= SMB_MOUNT_WIN95;
-		VERBOSE("detected WIN95 server\n");
-		install_ops(server->ops, &smb_ops_win95);
-	} else {
-		/*
-		 * Samba has max_xmit 65535
-		 * NT4spX has max_xmit 4536 (or something like that)
-		 * win2k has ...
-		 */
-		VERBOSE("detected NT1 (Samba, NT4/5) server\n");
-		install_ops(server->ops, &smb_ops_winNT);
-	}
-
-	/* FIXME: the win9x code wants to modify these ... (seek/trunc bug) */
-	if (server->mnt->flags & SMB_MOUNT_OLDATTR) {
-		server->ops->getattr = smb_proc_getattr_core;
-	} else if (server->mnt->flags & SMB_MOUNT_DIRATTR) {
-		server->ops->getattr = smb_proc_getattr_ff;
-	}
-
-	/* Decode server capabilities */
-	if (server->opt.capabilities & SMB_CAP_LARGE_FILES) {
-		/* Should be ok to set this now, as no one can access the
-		   mount until the connection has been established. */
-		SB_of(server)->s_maxbytes = ~0ULL >> 1;
-		VERBOSE("LFS enabled\n");
-	}
-	if (server->opt.capabilities & SMB_CAP_UNICODE) {
-		server->mnt->flags |= SMB_MOUNT_UNICODE;
-		VERBOSE("Unicode enabled\n");
-	} else {
-		server->mnt->flags &= ~SMB_MOUNT_UNICODE;
-	}
-#if 0
-	/* flags we may test for other patches ... */
-	if (server->opt.capabilities & SMB_CAP_LARGE_READX) {
-		VERBOSE("Large reads enabled\n");
-	}
-	if (server->opt.capabilities & SMB_CAP_LARGE_WRITEX) {
-		VERBOSE("Large writes enabled\n");
-	}
-#endif
-	if (server->opt.capabilities & SMB_CAP_UNIX) {
-		struct inode *inode;
-		VERBOSE("Using UNIX CIFS extensions\n");
-		install_ops(server->ops, &smb_ops_unix);
-		inode = SB_of(server)->s_root->d_inode;
-		if (inode)
-			inode->i_op = &smb_dir_inode_operations_unix;
-	}
-
-	VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
-		server->opt.protocol, server->opt.max_xmit,
-		pid_nr(server->conn_pid), server->opt.capabilities);
-
-	/* FIXME: this really should be done by smbmount. */
-	if (server->opt.max_xmit > SMB_MAX_PACKET_SIZE) {
-		server->opt.max_xmit = SMB_MAX_PACKET_SIZE;
-	}
-
-	smb_unlock_server(server);
-	smbiod_wake_up();
-	if (server->opt.capabilities & SMB_CAP_UNIX)
-		smb_proc_query_cifsunix(server);
-
-	server->conn_complete++;
-	wake_up_interruptible_all(&server->conn_wq);
-	return error;
-
-out:
-	smb_unlock_server(server);
-	smbiod_wake_up();
-	return error;
-
-out_putf:
-	fput(filp);
-	goto out;
-}
-
-/* smb_setup_header: We completely set up the packet. You only have to
-   insert the command-specific fields */
-
-__u8 *
-smb_setup_header(struct smb_request *req, __u8 command, __u16 wct, __u16 bcc)
-{
-	__u32 xmit_len = SMB_HEADER_LEN + wct * sizeof(__u16) + bcc + 2;
-	__u8 *p = req->rq_header;
-	struct smb_sb_info *server = req->rq_server;
-
-	p = smb_encode_smb_length(p, xmit_len - 4);
-
-	*p++ = 0xff;
-	*p++ = 'S';
-	*p++ = 'M';
-	*p++ = 'B';
-	*p++ = command;
-
-	memset(p, '\0', 19);
-	p += 19;
-	p += 8;
-
-	if (server->opt.protocol > SMB_PROTOCOL_CORE) {
-		int flags = SMB_FLAGS_CASELESS_PATHNAMES;
-		int flags2 = SMB_FLAGS2_LONG_PATH_COMPONENTS |
-			SMB_FLAGS2_EXTENDED_ATTRIBUTES;	/* EA? not really ... */
-
-		*(req->rq_header + smb_flg) = flags;
-		if (server->mnt->flags & SMB_MOUNT_UNICODE)
-			flags2 |= SMB_FLAGS2_UNICODE_STRINGS;
-		WSET(req->rq_header, smb_flg2, flags2);
-	}
-	*p++ = wct;		/* wct */
-	p += 2 * wct;
-	WSET(p, 0, bcc);
-
-	/* Include the header in the data to send */
-	req->rq_iovlen = 1;
-	req->rq_iov[0].iov_base = req->rq_header;
-	req->rq_iov[0].iov_len  = xmit_len - bcc;
-
-	return req->rq_buffer;
-}
-
-static void
-smb_setup_bcc(struct smb_request *req, __u8 *p)
-{
-	u16 bcc = p - req->rq_buffer;
-	u8 *pbcc = req->rq_header + SMB_HEADER_LEN + 2*SMB_WCT(req->rq_header);
-
-	WSET(pbcc, 0, bcc);
-
-	smb_encode_smb_length(req->rq_header, SMB_HEADER_LEN + 
-			      2*SMB_WCT(req->rq_header) - 2 + bcc);
-
-	/* Include the "bytes" in the data to send */
-	req->rq_iovlen = 2;
-	req->rq_iov[1].iov_base = req->rq_buffer;
-	req->rq_iov[1].iov_len  = bcc;
-}
-
-static int
-smb_proc_seek(struct smb_sb_info *server, __u16 fileid,
-	      __u16 mode, off_t offset)
-{
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBlseek, 4, 0);
-	WSET(req->rq_header, smb_vwv0, fileid);
-	WSET(req->rq_header, smb_vwv1, mode);
-	DSET(req->rq_header, smb_vwv2, offset);
-	req->rq_flags |= SMB_REQ_NORETRY;
-
-	result = smb_request_ok(req, SMBlseek, 2, 0);
-	if (result < 0) {
-		result = 0;
-		goto out_free;
-	}
-
-	result = DVAL(req->rq_header, smb_vwv0);
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_open(struct smb_sb_info *server, struct dentry *dentry, int wish)
-{
-	struct inode *ino = dentry->d_inode;
-	struct smb_inode_info *ei = SMB_I(ino);
-	int mode, read_write = 0x42, read_only = 0x40;
-	int res;
-	char *p;
-	struct smb_request *req;
-
-	/*
-	 * Attempt to open r/w, unless there are no write privileges.
-	 */
-	mode = read_write;
-	if (!(ino->i_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
-		mode = read_only;
-#if 0
-	/* FIXME: why is this code not in? below we fix it so that a caller
-	   wanting RO doesn't get RW. smb_revalidate_inode does some 
-	   optimization based on access mode. tail -f needs it to be correct.
-
-	   We must open rw since we don't do the open if called a second time
-	   with different 'wish'. Is that not supported by smb servers? */
-	if (!(wish & (O_WRONLY | O_RDWR)))
-		mode = read_only;
-#endif
-
-	res = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-      retry:
-	p = smb_setup_header(req, SMBopen, 2, 0);
-	WSET(req->rq_header, smb_vwv0, mode);
-	WSET(req->rq_header, smb_vwv1, aSYSTEM | aHIDDEN | aDIR);
-	res = smb_simple_encode_path(req, &p, dentry, NULL);
-	if (res < 0)
-		goto out_free;
-	smb_setup_bcc(req, p);
-
-	res = smb_request_ok(req, SMBopen, 7, 0);
-	if (res != 0) {
-		if (mode == read_write &&
-		    (res == -EACCES || res == -ETXTBSY || res == -EROFS))
-		{
-			VERBOSE("%s/%s R/W failed, error=%d, retrying R/O\n",
-				DENTRY_PATH(dentry), res);
-			mode = read_only;
-			req->rq_flags = 0;
-			goto retry;
-		}
-		goto out_free;
-	}
-	/* We should now have data in vwv[0..6]. */
-
-	ei->fileid = WVAL(req->rq_header, smb_vwv0);
-	ei->attr   = WVAL(req->rq_header, smb_vwv1);
-	/* smb_vwv2 has mtime */
-	/* smb_vwv4 has size  */
-	ei->access = (WVAL(req->rq_header, smb_vwv6) & SMB_ACCMASK);
-	ei->open = server->generation;
-
-out_free:
-	smb_rput(req);
-out:
-	return res;
-}
-
-/*
- * Make sure the file is open, and check that the access
- * is compatible with the desired access.
- */
-int
-smb_open(struct dentry *dentry, int wish)
-{
-	struct inode *inode = dentry->d_inode;
-	int result;
-	__u16 access;
-
-	result = -ENOENT;
-	if (!inode) {
-		printk(KERN_ERR "smb_open: no inode for dentry %s/%s\n",
-		       DENTRY_PATH(dentry));
-		goto out;
-	}
-
-	if (!smb_is_open(inode)) {
-		struct smb_sb_info *server = server_from_inode(inode);
-		result = 0;
-		if (!smb_is_open(inode))
-			result = smb_proc_open(server, dentry, wish);
-		if (result)
-			goto out;
-		/*
-		 * A successful open means the path is still valid ...
-		 */
-		smb_renew_times(dentry);
-	}
-
-	/*
-	 * Check whether the access is compatible with the desired mode.
-	 */
-	result = 0;
-	access = SMB_I(inode)->access;
-	if (access != wish && access != SMB_O_RDWR) {
-		PARANOIA("%s/%s access denied, access=%x, wish=%x\n",
-			 DENTRY_PATH(dentry), access, wish);
-		result = -EACCES;
-	}
-out:
-	return result;
-}
-
-static int 
-smb_proc_close(struct smb_sb_info *server, __u16 fileid, __u32 mtime)
-{
-	struct smb_request *req;
-	int result = -ENOMEM;
-
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBclose, 3, 0);
-	WSET(req->rq_header, smb_vwv0, fileid);
-	DSET(req->rq_header, smb_vwv1, utc2local(server, mtime));
-	req->rq_flags |= SMB_REQ_NORETRY;
-	result = smb_request_ok(req, SMBclose, 0, 0);
-
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * Win NT 4.0 has an apparent bug in that it fails to update the
- * modify time when writing to a file. As a workaround, we update
- * both modify and access time locally, and post the times to the
- * server when closing the file.
- */
-static int 
-smb_proc_close_inode(struct smb_sb_info *server, struct inode * ino)
-{
-	struct smb_inode_info *ei = SMB_I(ino);
-	int result = 0;
-	if (smb_is_open(ino))
-	{
-		/*
-		 * We clear the open flag in advance, in case another
- 		 * process observes the value while we block below.
-		 */
-		ei->open = 0;
-
-		/*
-		 * Kludge alert: SMB timestamps are accurate only to
-		 * two seconds ... round the times to avoid needless
-		 * cache invalidations!
-		 */
-		if (ino->i_mtime.tv_sec & 1) { 
-			ino->i_mtime.tv_sec--;
-			ino->i_mtime.tv_nsec = 0; 
-		}
-		if (ino->i_atime.tv_sec & 1) {
-			ino->i_atime.tv_sec--;
-			ino->i_atime.tv_nsec = 0;
-		}
-		/*
-		 * If the file is open with write permissions,
-		 * update the time stamps to sync mtime and atime.
-		 */
-		if ((server->opt.capabilities & SMB_CAP_UNIX) == 0 &&
-		    (server->opt.protocol >= SMB_PROTOCOL_LANMAN2) &&
-		    !(ei->access == SMB_O_RDONLY))
-		{
-			struct smb_fattr fattr;
-			smb_get_inode_attr(ino, &fattr);
-			smb_proc_setattr_ext(server, ino, &fattr);
-		}
-
-		result = smb_proc_close(server, ei->fileid, ino->i_mtime.tv_sec);
-		/*
-		 * Force a revalidation after closing ... some servers
-		 * don't post the size until the file has been closed.
-		 */
-		if (server->opt.protocol < SMB_PROTOCOL_NT1)
-			ei->oldmtime = 0;
-		ei->closed = jiffies;
-	}
-	return result;
-}
-
-int
-smb_close(struct inode *ino)
-{
-	int result = 0;
-
-	if (smb_is_open(ino)) {
-		struct smb_sb_info *server = server_from_inode(ino);
-		result = smb_proc_close_inode(server, ino);
-	}
-	return result;
-}
-
-/*
- * This is used to close a file following a failed instantiate.
- * Since we don't have an inode, we can't use any of the above.
- */
-int
-smb_close_fileid(struct dentry *dentry, __u16 fileid)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	int result;
-
-	result = smb_proc_close(server, fileid, get_seconds());
-	return result;
-}
-
-/* In smb_proc_read and smb_proc_write we do not retry, because the
-   file-id would not be valid after a reconnection. */
-
-static void
-smb_proc_read_data(struct smb_request *req)
-{
-	req->rq_iov[0].iov_base = req->rq_buffer;
-	req->rq_iov[0].iov_len  = 3;
-
-	req->rq_iov[1].iov_base = req->rq_page;
-	req->rq_iov[1].iov_len  = req->rq_rsize;
-	req->rq_iovlen = 2;
-
-	req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;
-}
-
-static int
-smb_proc_read(struct inode *inode, loff_t offset, int count, char *data)
-{
-	struct smb_sb_info *server = server_from_inode(inode);
-	__u16 returned_count, data_len;
-	unsigned char *buf;
-	int result;
-	struct smb_request *req;
-	u8 rbuf[4];
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBread, 5, 0);
-	buf = req->rq_header;
-	WSET(buf, smb_vwv0, SMB_I(inode)->fileid);
-	WSET(buf, smb_vwv1, count);
-	DSET(buf, smb_vwv2, offset);
-	WSET(buf, smb_vwv4, 0);
-
-	req->rq_page = data;
-	req->rq_rsize = count;
-	req->rq_callback = smb_proc_read_data;
-	req->rq_buffer = rbuf;
-	req->rq_flags |= SMB_REQ_NORETRY | SMB_REQ_STATIC;
-
-	result = smb_request_ok(req, SMBread, 5, -1);
-	if (result < 0)
-		goto out_free;
-	returned_count = WVAL(req->rq_header, smb_vwv0);
-
-	data_len = WVAL(rbuf, 1);
-
-	if (returned_count != data_len) {
-		printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");
-		printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",
-		       returned_count, data_len);
-	}
-	result = data_len;
-
-out_free:
-	smb_rput(req);
-out:
-	VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
-		inode->i_ino, SMB_I(inode)->fileid, count, result);
-	return result;
-}
-
-static int
-smb_proc_write(struct inode *inode, loff_t offset, int count, const char *data)
-{
-	struct smb_sb_info *server = server_from_inode(inode);
-	int result;
-	u16 fileid = SMB_I(inode)->fileid;
-	u8 buf[4];
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	VERBOSE("ino=%ld, fileid=%d, count=%d@%Ld\n",
-		inode->i_ino, fileid, count, offset);
-
-	smb_setup_header(req, SMBwrite, 5, count + 3);
-	WSET(req->rq_header, smb_vwv0, fileid);
-	WSET(req->rq_header, smb_vwv1, count);
-	DSET(req->rq_header, smb_vwv2, offset);
-	WSET(req->rq_header, smb_vwv4, 0);
-
-	buf[0] = 1;
-	WSET(buf, 1, count);	/* yes, again ... */
-	req->rq_iov[1].iov_base = buf;
-	req->rq_iov[1].iov_len = 3;
-	req->rq_iov[2].iov_base = (char *) data;
-	req->rq_iov[2].iov_len = count;
-	req->rq_iovlen = 3;
-	req->rq_flags |= SMB_REQ_NORETRY;
-
-	result = smb_request_ok(req, SMBwrite, 1, 0);
-	if (result >= 0)
-		result = WVAL(req->rq_header, smb_vwv0);
-
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * In smb_proc_readX and smb_proc_writeX we do not retry, because the
- * file-id would not be valid after a reconnection.
- */
-
-#define SMB_READX_MAX_PAD      64
-static void
-smb_proc_readX_data(struct smb_request *req)
-{
-	/* header length, excluding the netbios length (-4) */
-	int hdrlen = SMB_HEADER_LEN + req->rq_resp_wct*2 - 2;
-	int data_off = WVAL(req->rq_header, smb_vwv6);
-
-	/*
-	 * Some genius made the padding to the data bytes arbitrary.
-	 * So we must first calculate the amount of padding used by the server.
-	 */
-	data_off -= hdrlen;
-	if (data_off > SMB_READX_MAX_PAD || data_off < 0) {
-		PARANOIA("offset is larger than SMB_READX_MAX_PAD or negative!\n");
-		PARANOIA("%d > %d || %d < 0\n", data_off, SMB_READX_MAX_PAD, data_off);
-		req->rq_rlen = req->rq_bufsize + 1;
-		return;
-	}
-	req->rq_iov[0].iov_base = req->rq_buffer;
-	req->rq_iov[0].iov_len  = data_off;
-
-	req->rq_iov[1].iov_base = req->rq_page;
-	req->rq_iov[1].iov_len  = req->rq_rsize;
-	req->rq_iovlen = 2;
-
-	req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;
-}
-
-static int
-smb_proc_readX(struct inode *inode, loff_t offset, int count, char *data)
-{
-	struct smb_sb_info *server = server_from_inode(inode);
-	unsigned char *buf;
-	int result;
-	struct smb_request *req;
-	static char pad[SMB_READX_MAX_PAD];
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBreadX, 12, 0);
-	buf = req->rq_header;
-	WSET(buf, smb_vwv0, 0x00ff);
-	WSET(buf, smb_vwv1, 0);
-	WSET(buf, smb_vwv2, SMB_I(inode)->fileid);
-	DSET(buf, smb_vwv3, (u32)offset);               /* low 32 bits */
-	WSET(buf, smb_vwv5, count);
-	WSET(buf, smb_vwv6, 0);
-	DSET(buf, smb_vwv7, 0);
-	WSET(buf, smb_vwv9, 0);
-	DSET(buf, smb_vwv10, (u32)(offset >> 32));      /* high 32 bits */
-	WSET(buf, smb_vwv11, 0);
-
-	req->rq_page = data;
-	req->rq_rsize = count;
-	req->rq_callback = smb_proc_readX_data;
-	req->rq_buffer = pad;
-	req->rq_bufsize = SMB_READX_MAX_PAD;
-	req->rq_flags |= SMB_REQ_STATIC | SMB_REQ_NORETRY;
-
-	result = smb_request_ok(req, SMBreadX, 12, -1);
-	if (result < 0)
-		goto out_free;
-	result = WVAL(req->rq_header, smb_vwv5);
-
-out_free:
-	smb_rput(req);
-out:
-	VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
-		inode->i_ino, SMB_I(inode)->fileid, count, result);
-	return result;
-}
-
-static int
-smb_proc_writeX(struct inode *inode, loff_t offset, int count, const char *data)
-{
-	struct smb_sb_info *server = server_from_inode(inode);
-	int result;
-	u8 *p;
-	static u8 pad[4];
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	VERBOSE("ino=%ld, fileid=%d, count=%d@%Ld\n",
-		inode->i_ino, SMB_I(inode)->fileid, count, offset);
-
-	p = smb_setup_header(req, SMBwriteX, 14, count + 1);
-	WSET(req->rq_header, smb_vwv0, 0x00ff);
-	WSET(req->rq_header, smb_vwv1, 0);
-	WSET(req->rq_header, smb_vwv2, SMB_I(inode)->fileid);
-	DSET(req->rq_header, smb_vwv3, (u32)offset);	/* low 32 bits */
-	DSET(req->rq_header, smb_vwv5, 0);
-	WSET(req->rq_header, smb_vwv7, 0);		/* write mode */
-	WSET(req->rq_header, smb_vwv8, 0);
-	WSET(req->rq_header, smb_vwv9, 0);
-	WSET(req->rq_header, smb_vwv10, count);		/* data length */
-	WSET(req->rq_header, smb_vwv11, smb_vwv12 + 2 + 1);
-	DSET(req->rq_header, smb_vwv12, (u32)(offset >> 32));
-
-	req->rq_iov[1].iov_base = pad;
-	req->rq_iov[1].iov_len = 1;
-	req->rq_iov[2].iov_base = (char *) data;
-	req->rq_iov[2].iov_len = count;
-	req->rq_iovlen = 3;
-	req->rq_flags |= SMB_REQ_NORETRY;
-
-	result = smb_request_ok(req, SMBwriteX, 6, 0);
- 	if (result >= 0)
-		result = WVAL(req->rq_header, smb_vwv2);
-
-	smb_rput(req);
-out:
-	return result;
-}
-
-int
-smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	char *p;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	p = smb_setup_header(req, SMBcreate, 3, 0);
-	WSET(req->rq_header, smb_vwv0, attr);
-	DSET(req->rq_header, smb_vwv1, utc2local(server, ctime));
-	result = smb_simple_encode_path(req, &p, dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	smb_setup_bcc(req, p);
-
-	result = smb_request_ok(req, SMBcreate, 1, 0);
-	if (result < 0)
-		goto out_free;
-
-	*fileid = WVAL(req->rq_header, smb_vwv0);
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-int
-smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry)
-{
-	struct smb_sb_info *server = server_from_dentry(old_dentry);
-	char *p;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	p = smb_setup_header(req, SMBmv, 1, 0);
-	WSET(req->rq_header, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);
-	result = smb_simple_encode_path(req, &p, old_dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	result = smb_simple_encode_path(req, &p, new_dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	smb_setup_bcc(req, p);
-
-	if ((result = smb_request_ok(req, SMBmv, 0, 0)) < 0)
-		goto out_free;
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * Code common to mkdir and rmdir.
- */
-static int
-smb_proc_generic_command(struct dentry *dentry, __u8 command)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	char *p;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	p = smb_setup_header(req, command, 0, 0);
-	result = smb_simple_encode_path(req, &p, dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	smb_setup_bcc(req, p);
-
-	result = smb_request_ok(req, command, 0, 0);
-	if (result < 0)
-		goto out_free;
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-int
-smb_proc_mkdir(struct dentry *dentry)
-{
-	return smb_proc_generic_command(dentry, SMBmkdir);
-}
-
-int
-smb_proc_rmdir(struct dentry *dentry)
-{
-	return smb_proc_generic_command(dentry, SMBrmdir);
-}
-
-#if SMBFS_POSIX_UNLINK
-/*
- * Removes readonly attribute from a file. Used by unlink to give posix
- * semantics.
- */
-static int
-smb_set_rw(struct dentry *dentry,struct smb_sb_info *server)
-{
-	int result;
-	struct smb_fattr fattr;
-
-	/* FIXME: cifsUE should allow removing a readonly file. */
-
-	/* first get current attribute */
-	smb_init_dirent(server, &fattr);
-	result = server->ops->getattr(server, dentry, &fattr);
-	smb_finish_dirent(server, &fattr);
-	if (result < 0)
-		return result;
-
-	/* if RONLY attribute is set, remove it */
-	if (fattr.attr & aRONLY) {  /* read only attribute is set */
-		fattr.attr &= ~aRONLY;
-		result = smb_proc_setattr_core(server, dentry, fattr.attr);
-	}
-	return result;
-}
-#endif
-
-int
-smb_proc_unlink(struct dentry *dentry)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	int flag = 0;
-	char *p;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-      retry:
-	p = smb_setup_header(req, SMBunlink, 1, 0);
-	WSET(req->rq_header, smb_vwv0, aSYSTEM | aHIDDEN);
-	result = smb_simple_encode_path(req, &p, dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	smb_setup_bcc(req, p);
-
-	if ((result = smb_request_ok(req, SMBunlink, 0, 0)) < 0) {
-#if SMBFS_POSIX_UNLINK
-		if (result == -EACCES && !flag) {
-			/* Posix semantics is for the read-only state
-			   of a file to be ignored in unlink(). In the
-			   SMB world a unlink() is refused on a
-			   read-only file. To make things easier for
-			   unix users we try to override the files
-			   permission if the unlink fails with the
-			   right error.
-			   This introduces a race condition that could
-			   lead to a file being written by someone who
-			   shouldn't have access, but as far as I can
-			   tell that is unavoidable */
-
-			/* remove RONLY attribute and try again */
-			result = smb_set_rw(dentry,server);
-			if (result == 0) {
-				flag = 1;
-				req->rq_flags = 0;
-				goto retry;
-			}
-		}
-#endif
-		goto out_free;
-	}
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-int
-smb_proc_flush(struct smb_sb_info *server, __u16 fileid)
-{
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBflush, 1, 0);
-	WSET(req->rq_header, smb_vwv0, fileid);
-	req->rq_flags |= SMB_REQ_NORETRY;
-	result = smb_request_ok(req, SMBflush, 0, 0);
-
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_trunc32(struct inode *inode, loff_t length)
-{
-	/*
-	 * Writing 0bytes is old-SMB magic for truncating files.
-	 * MAX_NON_LFS should prevent this from being called with a too
-	 * large offset.
-	 */
-	return smb_proc_write(inode, length, 0, NULL);
-}
-
-static int
-smb_proc_trunc64(struct inode *inode, loff_t length)
-{
-	struct smb_sb_info *server = server_from_inode(inode);
-	int result;
-	char *param;
-	char *data;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 14)))
-		goto out;
-
-	param = req->rq_buffer;
-	data = req->rq_buffer + 6;
-
-	/* FIXME: must we also set allocation size? winNT seems to do that */
-	WSET(param, 0, SMB_I(inode)->fileid);
-	WSET(param, 2, SMB_SET_FILE_END_OF_FILE_INFO);
-	WSET(param, 4, 0);
-	LSET(data, 0, length);
-
-	req->rq_trans2_command = TRANSACT2_SETFILEINFO;
-	req->rq_ldata = 8;
-	req->rq_data  = data;
-	req->rq_lparm = 6;
-	req->rq_parm  = param;
-	req->rq_flags |= SMB_REQ_NORETRY;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-
-	result = 0;
-	if (req->rq_rcls != 0)
-		result = smb_errno(req);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_trunc95(struct inode *inode, loff_t length)
-{
-	struct smb_sb_info *server = server_from_inode(inode);
-	int result = smb_proc_trunc32(inode, length);
- 
-	/*
-	 * win9x doesn't appear to update the size immediately.
-	 * It will return the old file size after the truncate,
-	 * confusing smbfs. So we force an update.
-	 *
-	 * FIXME: is this still necessary?
-	 */
-	smb_proc_flush(server, SMB_I(inode)->fileid);
-	return result;
-}
-
-static void
-smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
-{
-	memset(fattr, 0, sizeof(*fattr));
-
-	fattr->f_nlink = 1;
-	fattr->f_uid = server->mnt->uid;
-	fattr->f_gid = server->mnt->gid;
-	fattr->f_unix = 0;
-}
-
-static void
-smb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
-{
-	if (fattr->f_unix)
-		return;
-
-	fattr->f_mode = server->mnt->file_mode;
-	if (fattr->attr & aDIR) {
-		fattr->f_mode = server->mnt->dir_mode;
-		fattr->f_size = SMB_ST_BLKSIZE;
-	}
-	/* Check the read-only flag */
-	if (fattr->attr & aRONLY)
-		fattr->f_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
-
-	/* How many 512 byte blocks do we need for this file? */
-	fattr->f_blocks = 0;
-	if (fattr->f_size != 0)
-		fattr->f_blocks = 1 + ((fattr->f_size-1) >> 9);
-	return;
-}
-
-void
-smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr,
-		     struct super_block *sb)
-{
-	smb_init_dirent(server, fattr);
-	fattr->attr = aDIR;
-	fattr->f_ino = 2; /* traditional root inode number */
-	fattr->f_mtime = current_fs_time(sb);
-	smb_finish_dirent(server, fattr);
-}
-
-/*
- * Decode a dirent for old protocols
- *
- * qname is filled with the decoded, and possibly translated, name.
- * fattr receives decoded attributes
- *
- * Bugs Noted:
- * (1) Pathworks servers may pad the name with extra spaces.
- */
-static char *
-smb_decode_short_dirent(struct smb_sb_info *server, char *p,
-			struct qstr *qname, struct smb_fattr *fattr,
-			unsigned char *name_buf)
-{
-	int len;
-
-	/*
-	 * SMB doesn't have a concept of inode numbers ...
-	 */
-	smb_init_dirent(server, fattr);
-	fattr->f_ino = 0;	/* FIXME: do we need this? */
-
-	p += SMB_STATUS_SIZE;	/* reserved (search_status) */
-	fattr->attr = *p;
-	fattr->f_mtime.tv_sec = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));
-	fattr->f_mtime.tv_nsec = 0;
-	fattr->f_size = DVAL(p, 5);
-	fattr->f_ctime = fattr->f_mtime;
-	fattr->f_atime = fattr->f_mtime;
-	qname->name = p + 9;
-	len = strnlen(qname->name, 12);
-
-	/*
-	 * Trim trailing blanks for Pathworks servers
-	 */
-	while (len > 2 && qname->name[len-1] == ' ')
-		len--;
-
-	smb_finish_dirent(server, fattr);
-
-#if 0
-	/* FIXME: These only work for ascii chars, and recent smbmount doesn't
-	   allow the flag to be set anyway. It kills const. Remove? */
-	switch (server->opt.case_handling) {
-	case SMB_CASE_UPPER:
-		str_upper(entry->name, len);
-		break;
-	case SMB_CASE_LOWER:
-		str_lower(entry->name, len);
-		break;
-	default:
-		break;
-	}
-#endif
-
-	qname->len = 0;
-	len = server->ops->convert(name_buf, SMB_MAXNAMELEN,
-				   qname->name, len,
-				   server->remote_nls, server->local_nls);
-	if (len > 0) {
-		qname->len = len;
-		qname->name = name_buf;
-		DEBUG1("len=%d, name=%.*s\n",qname->len,qname->len,qname->name);
-	}
-
-	return p + 22;
-}
-
-/*
- * This routine is used to read in directory entries from the network.
- * Note that it is for short directory name seeks, i.e.: protocol <
- * SMB_PROTOCOL_LANMAN2
- */
-static int
-smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
-		       struct smb_cache_control *ctl)
-{
-	struct dentry *dir = filp->f_path.dentry;
-	struct smb_sb_info *server = server_from_dentry(dir);
-	struct qstr qname;
-	struct smb_fattr fattr;
-	char *p;
-	int result;
-	int i, first, entries_seen, entries;
-	int entries_asked = (server->opt.max_xmit - 100) / SMB_DIRINFO_SIZE;
-	__u16 bcc;
-	__u16 count;
-	char status[SMB_STATUS_SIZE];
-	static struct qstr mask = {
-		.name	= "*.*",
-		.len	= 3,
-	};
-	unsigned char *last_status;
-	struct smb_request *req;
-	unsigned char *name_buf;
-
-	VERBOSE("%s/%s\n", DENTRY_PATH(dir));
-
-	lock_kernel();
-
-	result = -ENOMEM;
-	if (! (name_buf = kmalloc(SMB_MAXNAMELEN, GFP_KERNEL)))
-		goto out;
-
-	first = 1;
-	entries = 0;
-	entries_seen = 2; /* implicit . and .. */
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, server->opt.max_xmit)))
-		goto out_name;
-
-	while (1) {
-		p = smb_setup_header(req, SMBsearch, 2, 0);
-		WSET(req->rq_header, smb_vwv0, entries_asked);
-		WSET(req->rq_header, smb_vwv1, aDIR);
-		if (first == 1) {
-			result = smb_simple_encode_path(req, &p, dir, &mask);
-			if (result < 0)
-				goto out_free;
-			if (p + 3 > (char *)req->rq_buffer + req->rq_bufsize) {
-				result = -ENAMETOOLONG;
-				goto out_free;
-			}
-			*p++ = 5;
-			WSET(p, 0, 0);
-			p += 2;
-			first = 0;
-		} else {
-			if (p + 5 + SMB_STATUS_SIZE >
-			    (char *)req->rq_buffer + req->rq_bufsize) {
-				result = -ENAMETOOLONG;
-				goto out_free;
-			}
-				
-			*p++ = 4;
-			*p++ = 0;
-			*p++ = 5;
-			WSET(p, 0, SMB_STATUS_SIZE);
-			p += 2;
-			memcpy(p, status, SMB_STATUS_SIZE);
-			p += SMB_STATUS_SIZE;
-		}
-
-		smb_setup_bcc(req, p);
-
-		result = smb_request_ok(req, SMBsearch, 1, -1);
-		if (result < 0) {
-			if ((req->rq_rcls == ERRDOS) && 
-			    (req->rq_err  == ERRnofiles))
-				break;
-			goto out_free;
-		}
-		count = WVAL(req->rq_header, smb_vwv0);
-		if (count <= 0)
-			break;
-
-		result = -EIO;
-		bcc = smb_bcc(req->rq_header);
-		if (bcc != count * SMB_DIRINFO_SIZE + 3)
-			goto out_free;
-		p = req->rq_buffer + 3;
-
-
-		/* Make sure the response fits in the buffer. Fixed sized 
-		   entries means we don't have to check in the decode loop. */
-
-		last_status = req->rq_buffer + 3 + (count-1) * SMB_DIRINFO_SIZE;
-
-		if (last_status + SMB_DIRINFO_SIZE >=
-		    req->rq_buffer + req->rq_bufsize) {
-			printk(KERN_ERR "smb_proc_readdir_short: "
-			       "last dir entry outside buffer! "
-			       "%d@%p  %d@%p\n", SMB_DIRINFO_SIZE, last_status,
-			       req->rq_bufsize, req->rq_buffer);
-			goto out_free;
-		}
-
-		/* Read the last entry into the status field. */
-		memcpy(status, last_status, SMB_STATUS_SIZE);
-
-
-		/* Now we are ready to parse smb directory entries. */
-
-		for (i = 0; i < count; i++) {
-			p = smb_decode_short_dirent(server, p, 
-						    &qname, &fattr, name_buf);
-			if (qname.len == 0)
-				continue;
-
-			if (entries_seen == 2 && qname.name[0] == '.') {
-				if (qname.len == 1)
-					continue;
-				if (qname.name[1] == '.' && qname.len == 2)
-					continue;
-			}
-			if (!smb_fill_cache(filp, dirent, filldir, ctl, 
-					    &qname, &fattr))
-				;	/* stop reading? */
-			entries_seen++;
-		}
-	}
-	result = entries;
-
-out_free:
-	smb_rput(req);
-out_name:
-	kfree(name_buf);
-out:
-	unlock_kernel();
-	return result;
-}
-
-static void smb_decode_unix_basic(struct smb_fattr *fattr, struct smb_sb_info *server, char *p)
-{
-	u64 size, disk_bytes;
-
-	/* FIXME: verify nls support. all is sent as utf8? */
-
-	fattr->f_unix = 1;
-	fattr->f_mode = 0;
-
-	/* FIXME: use the uniqueID from the remote instead? */
-	/* 0 L file size in bytes */
-	/* 8 L file size on disk in bytes (block count) */
-	/* 40 L uid */
-	/* 48 L gid */
-	/* 56 W file type */
-	/* 60 L devmajor */
-	/* 68 L devminor */
-	/* 76 L unique ID (inode) */
-	/* 84 L permissions */
-	/* 92 L link count */
-
-	size = LVAL(p, 0);
-	disk_bytes = LVAL(p, 8);
-
-	/*
-	 * Some samba versions round up on-disk byte usage
-	 * to 1MB boundaries, making it useless. When seeing
-	 * that, use the size instead.
-	 */
-	if (!(disk_bytes & 0xfffff))
-		disk_bytes = size+511;
-
-	fattr->f_size = size;
-	fattr->f_blocks = disk_bytes >> 9;
-	fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 16));
-	fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 24));
-	fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 32));
-
-	if (server->mnt->flags & SMB_MOUNT_UID)
-		fattr->f_uid = server->mnt->uid;
-	else
-		fattr->f_uid = LVAL(p, 40);
-
-	if (server->mnt->flags & SMB_MOUNT_GID)
-		fattr->f_gid = server->mnt->gid;
-	else
-		fattr->f_gid = LVAL(p, 48);
-
-	fattr->f_mode |= smb_filetype_to_mode(WVAL(p, 56));
-
-	if (S_ISBLK(fattr->f_mode) || S_ISCHR(fattr->f_mode)) {
-		__u64 major = LVAL(p, 60);
-		__u64 minor = LVAL(p, 68);
-
-		fattr->f_rdev = MKDEV(major & 0xffffffff, minor & 0xffffffff);
-		if (MAJOR(fattr->f_rdev) != (major & 0xffffffff) ||
-	    	MINOR(fattr->f_rdev) != (minor & 0xffffffff))
-			fattr->f_rdev = 0;
-	}
-
-	fattr->f_mode |= LVAL(p, 84);
-
-	if ( (server->mnt->flags & SMB_MOUNT_DMODE) &&
-	     (S_ISDIR(fattr->f_mode)) )
-		fattr->f_mode = (server->mnt->dir_mode & S_IRWXUGO) | S_IFDIR;
-	else if ( (server->mnt->flags & SMB_MOUNT_FMODE) &&
-	          !(S_ISDIR(fattr->f_mode)) )
-		fattr->f_mode = (server->mnt->file_mode & S_IRWXUGO) |
-				(fattr->f_mode & S_IFMT);
-
-}
-
-/*
- * Interpret a long filename structure using the specified info level:
- *   level 1 for anything below NT1 protocol
- *   level 260 for NT1 protocol
- *
- * qname is filled with the decoded, and possibly translated, name
- * fattr receives decoded attributes.
- *
- * Bugs Noted:
- * (1) Win NT 4.0 appends a null byte to names and counts it in the length!
- */
-static char *
-smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
-		       struct qstr *qname, struct smb_fattr *fattr,
-		       unsigned char *name_buf)
-{
-	char *result;
-	unsigned int len = 0;
-	int n;
-	__u16 date, time;
-	int unicode = (server->mnt->flags & SMB_MOUNT_UNICODE);
-
-	/*
-	 * SMB doesn't have a concept of inode numbers ...
-	 */
-	smb_init_dirent(server, fattr);
-	fattr->f_ino = 0;	/* FIXME: do we need this? */
-
-	switch (level) {
-	case 1:
-		len = *((unsigned char *) p + 22);
-		qname->name = p + 23;
-		result = p + 24 + len;
-
-		date = WVAL(p, 0);
-		time = WVAL(p, 2);
-		fattr->f_ctime.tv_sec = date_dos2unix(server, date, time);
-		fattr->f_ctime.tv_nsec = 0;
-
-		date = WVAL(p, 4);
-		time = WVAL(p, 6);
-		fattr->f_atime.tv_sec = date_dos2unix(server, date, time);
-		fattr->f_atime.tv_nsec = 0;
-
-		date = WVAL(p, 8);
-		time = WVAL(p, 10);
-		fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
-		fattr->f_mtime.tv_nsec = 0;
-		fattr->f_size = DVAL(p, 12);
-		/* ULONG allocation size */
-		fattr->attr = WVAL(p, 20);
-
-		VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
-			p, len, len, qname->name);
-		break;
-	case 260:
-		result = p + WVAL(p, 0);
-		len = DVAL(p, 60);
-		if (len > 255) len = 255;
-		/* NT4 null terminates, unless we are using unicode ... */
-		qname->name = p + 94;
-		if (!unicode && len && qname->name[len-1] == '\0')
-			len--;
-
-		fattr->f_ctime = smb_ntutc2unixutc(LVAL(p, 8));
-		fattr->f_atime = smb_ntutc2unixutc(LVAL(p, 16));
-		fattr->f_mtime = smb_ntutc2unixutc(LVAL(p, 24));
-		/* change time (32) */
-		fattr->f_size = LVAL(p, 40);
-		/* alloc size (48) */
-		fattr->attr = DVAL(p, 56);
-
-		VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
-			p, len, len, qname->name);
-		break;
-	case SMB_FIND_FILE_UNIX:
-		result = p + WVAL(p, 0);
-		qname->name = p + 108;
-
-		len = strlen(qname->name);
-		/* FIXME: should we check the length?? */
-
-		p += 8;
-		smb_decode_unix_basic(fattr, server, p);
-		VERBOSE("info SMB_FIND_FILE_UNIX at %p, len=%d, name=%.*s\n",
-			p, len, len, qname->name);
-		break;
-	default:
-		PARANOIA("Unknown info level %d\n", level);
-		result = p + WVAL(p, 0);
-		goto out;
-	}
-
-	smb_finish_dirent(server, fattr);
-
-#if 0
-	/* FIXME: These only work for ascii chars, and recent smbmount doesn't
-	   allow the flag to be set anyway. Remove? */
-	switch (server->opt.case_handling) {
-	case SMB_CASE_UPPER:
-		str_upper(qname->name, len);
-		break;
-	case SMB_CASE_LOWER:
-		str_lower(qname->name, len);
-		break;
-	default:
-		break;
-	}
-#endif
-
-	qname->len = 0;
-	n = server->ops->convert(name_buf, SMB_MAXNAMELEN,
-				 qname->name, len,
-				 server->remote_nls, server->local_nls);
-	if (n > 0) {
-		qname->len = n;
-		qname->name = name_buf;
-	}
-
-out:
-	return result;
-}
-
-/* findfirst/findnext flags */
-#define SMB_CLOSE_AFTER_FIRST (1<<0)
-#define SMB_CLOSE_IF_END (1<<1)
-#define SMB_REQUIRE_RESUME_KEY (1<<2)
-#define SMB_CONTINUE_BIT (1<<3)
-
-/*
- * Note: samba-2.0.7 (at least) has a very similar routine, cli_list, in
- * source/libsmb/clilist.c. When looking for smb bugs in the readdir code,
- * go there for advise.
- *
- * Bugs Noted:
- * (1) When using Info Level 1 Win NT 4.0 truncates directory listings 
- * for certain patterns of names and/or lengths. The breakage pattern
- * is completely reproducible and can be toggled by the creation of a
- * single file. (E.g. echo hi >foo breaks, rm -f foo works.)
- */
-static int
-smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
-		      struct smb_cache_control *ctl)
-{
-	struct dentry *dir = filp->f_path.dentry;
-	struct smb_sb_info *server = server_from_dentry(dir);
-	struct qstr qname;
-	struct smb_fattr fattr;
-
-	unsigned char *p, *lastname;
-	char *mask, *param;
-	__u16 command;
-	int first, entries_seen;
-
-	/* Both NT and OS/2 accept info level 1 (but see note below). */
-	int info_level = 260;
-	const int max_matches = 512;
-
-	unsigned int ff_searchcount = 0;
-	unsigned int ff_eos = 0;
-	unsigned int ff_lastname = 0;
-	unsigned int ff_dir_handle = 0;
-	unsigned int loop_count = 0;
-	unsigned int mask_len, i;
-	int result;
-	struct smb_request *req;
-	unsigned char *name_buf;
-	static struct qstr star = {
-		.name	= "*",
-		.len	= 1,
-	};
-
-	lock_kernel();
-
-	/*
-	 * We always prefer unix style. Use info level 1 for older
-	 * servers that don't do 260.
-	 */
-	if (server->opt.capabilities & SMB_CAP_UNIX)
-		info_level = SMB_FIND_FILE_UNIX;
-	else if (server->opt.protocol < SMB_PROTOCOL_NT1)
-		info_level = 1;
-
-	result = -ENOMEM;
-	if (! (name_buf = kmalloc(SMB_MAXNAMELEN+2, GFP_KERNEL)))
-		goto out;
-	if (! (req = smb_alloc_request(server, server->opt.max_xmit)))
-		goto out_name;
-	param = req->rq_buffer;
-
-	/*
-	 * Encode the initial path
-	 */
-	mask = param + 12;
-
-	result = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dir, &star);
-	if (result <= 0)
-		goto out_free;
-	mask_len = result - 1;	/* mask_len is strlen, not #bytes */
-	result = 0;
-	first = 1;
-	VERBOSE("starting mask_len=%d, mask=%s\n", mask_len, mask);
-
-	entries_seen = 2;
-	ff_eos = 0;
-
-	while (ff_eos == 0) {
-		loop_count += 1;
-		if (loop_count > 10) {
-			printk(KERN_WARNING "smb_proc_readdir_long: "
-			       "Looping in FIND_NEXT??\n");
-			result = -EIO;
-			break;
-		}
-
-		if (first != 0) {
-			command = TRANSACT2_FINDFIRST;
-			WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
-			WSET(param, 2, max_matches);	/* max count */
-			WSET(param, 4, SMB_CLOSE_IF_END);
-			WSET(param, 6, info_level);
-			DSET(param, 8, 0);
-		} else {
-			command = TRANSACT2_FINDNEXT;
-
-			VERBOSE("handle=0x%X, lastname=%d, mask=%.*s\n",
-				ff_dir_handle, ff_lastname, mask_len, mask);
-
-			WSET(param, 0, ff_dir_handle);	/* search handle */
-			WSET(param, 2, max_matches);	/* max count */
-			WSET(param, 4, info_level);
-			DSET(param, 6, 0);
-			WSET(param, 10, SMB_CONTINUE_BIT|SMB_CLOSE_IF_END);
-		}
-
-		req->rq_trans2_command = command;
-		req->rq_ldata = 0;
-		req->rq_data  = NULL;
-		req->rq_lparm = 12 + mask_len + 1;
-		req->rq_parm  = param;
-		req->rq_flags = 0;
-		result = smb_add_request(req);
-		if (result < 0) {
-			PARANOIA("error=%d, breaking\n", result);
-			break;
-		}
-
-		if (req->rq_rcls == ERRSRV && req->rq_err == ERRerror) {
-			/* a damn Win95 bug - sometimes it clags if you 
-			   ask it too fast */
-			schedule_timeout_interruptible(msecs_to_jiffies(200));
-			continue;
-                }
-
-		if (req->rq_rcls != 0) {
-			result = smb_errno(req);
-			PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
-				 mask, result, req->rq_rcls, req->rq_err);
-			break;
-		}
-
-		/* parse out some important return info */
-		if (first != 0) {
-			ff_dir_handle = WVAL(req->rq_parm, 0);
-			ff_searchcount = WVAL(req->rq_parm, 2);
-			ff_eos = WVAL(req->rq_parm, 4);
-			ff_lastname = WVAL(req->rq_parm, 8);
-		} else {
-			ff_searchcount = WVAL(req->rq_parm, 0);
-			ff_eos = WVAL(req->rq_parm, 2);
-			ff_lastname = WVAL(req->rq_parm, 6);
-		}
-
-		if (ff_searchcount == 0)
-			break;
-
-		/* Now we are ready to parse smb directory entries. */
-
-		/* point to the data bytes */
-		p = req->rq_data;
-		for (i = 0; i < ff_searchcount; i++) {
-			/* make sure we stay within the buffer */
-			if (p >= req->rq_data + req->rq_ldata) {
-				printk(KERN_ERR "smb_proc_readdir_long: "
-				       "dirent pointer outside buffer! "
-				       "%p  %d@%p\n",
-				       p, req->rq_ldata, req->rq_data);
-				result = -EIO; /* always a comm. error? */
-				goto out_free;
-			}
-
-			p = smb_decode_long_dirent(server, p, info_level,
-						   &qname, &fattr, name_buf);
-
-			/* ignore . and .. from the server */
-			if (entries_seen == 2 && qname.name[0] == '.') {
-				if (qname.len == 1)
-					continue;
-				if (qname.name[1] == '.' && qname.len == 2)
-					continue;
-			}
-
-			if (!smb_fill_cache(filp, dirent, filldir, ctl, 
-					    &qname, &fattr))
-				;	/* stop reading? */
-			entries_seen++;
-		}
-
-		VERBOSE("received %d entries, eos=%d\n", ff_searchcount,ff_eos);
-
-		/*
-		 * We might need the lastname for continuations.
-		 *
-		 * Note that some servers (win95?) point to the filename and
-		 * others (NT4, Samba using NT1) to the dir entry. We assume
-		 * here that those who do not point to a filename do not need
-		 * this info to continue the listing.
-		 *
-		 * OS/2 needs this and talks infolevel 1.
-		 * NetApps want lastname with infolevel 260.
-		 * win2k want lastname with infolevel 260, and points to
-		 *       the record not to the name.
-		 * Samba+CifsUnixExt doesn't need lastname.
-		 *
-		 * Both are happy if we return the data they point to. So we do.
-		 * (FIXME: above is not true with win2k)
-		 */
-		mask_len = 0;
-		if (info_level != SMB_FIND_FILE_UNIX &&
-		    ff_lastname > 0 && ff_lastname < req->rq_ldata) {
-			lastname = req->rq_data + ff_lastname;
-
-			switch (info_level) {
-			case 260:
-				mask_len = req->rq_ldata - ff_lastname;
-				break;
-			case 1:
-				/* lastname points to a length byte */
-				mask_len = *lastname++;
-				if (ff_lastname + 1 + mask_len > req->rq_ldata)
-					mask_len = req->rq_ldata - ff_lastname - 1;
-				break;
-			}
-
-			/*
-			 * Update the mask string for the next message.
-			 */
-			if (mask_len > 255)
-				mask_len = 255;
-			if (mask_len)
-				strncpy(mask, lastname, mask_len);
-		}
-		mask_len = strnlen(mask, mask_len);
-		VERBOSE("new mask, len=%d@%d of %d, mask=%.*s\n",
-			mask_len, ff_lastname, req->rq_ldata, mask_len, mask);
-
-		first = 0;
-		loop_count = 0;
-	}
-
-out_free:
-	smb_rput(req);
-out_name:
-	kfree(name_buf);
-out:
-	unlock_kernel();
-	return result;
-}
-
-/*
- * This version uses the trans2 TRANSACT2_FINDFIRST message 
- * to get the attribute data.
- *
- * Bugs Noted:
- */
-static int
-smb_proc_getattr_ff(struct smb_sb_info *server, struct dentry *dentry,
-			struct smb_fattr *fattr)
-{
-	char *param, *mask;
-	__u16 date, time;
-	int mask_len, result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-	param = req->rq_buffer;
-	mask = param + 12;
-
-	mask_len = smb_encode_path(server, mask, SMB_MAXPATHLEN+1, dentry,NULL);
-	if (mask_len < 0) {
-		result = mask_len;
-		goto out_free;
-	}
-	VERBOSE("name=%s, len=%d\n", mask, mask_len);
-	WSET(param, 0, aSYSTEM | aHIDDEN | aDIR);
-	WSET(param, 2, 1);	/* max count */
-	WSET(param, 4, 1);	/* close after this call */
-	WSET(param, 6, 1);	/* info_level */
-	DSET(param, 8, 0);
-
-	req->rq_trans2_command = TRANSACT2_FINDFIRST;
-	req->rq_ldata = 0;
-	req->rq_data  = NULL;
-	req->rq_lparm = 12 + mask_len;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-	if (req->rq_rcls != 0) {
-		result = smb_errno(req);
-#ifdef SMBFS_PARANOIA
-		if (result != -ENOENT)
-			PARANOIA("error for %s, rcls=%d, err=%d\n",
-				 mask, req->rq_rcls, req->rq_err);
-#endif
-		goto out_free;
-	}
-	/* Make sure we got enough data ... */
-	result = -EINVAL;
-	if (req->rq_ldata < 22 || WVAL(req->rq_parm, 2) != 1) {
-		PARANOIA("bad result for %s, len=%d, count=%d\n",
-			 mask, req->rq_ldata, WVAL(req->rq_parm, 2));
-		goto out_free;
-	}
-
-	/*
-	 * Decode the response into the fattr ...
-	 */
-	date = WVAL(req->rq_data, 0);
-	time = WVAL(req->rq_data, 2);
-	fattr->f_ctime.tv_sec = date_dos2unix(server, date, time);
-	fattr->f_ctime.tv_nsec = 0;
-
-	date = WVAL(req->rq_data, 4);
-	time = WVAL(req->rq_data, 6);
-	fattr->f_atime.tv_sec = date_dos2unix(server, date, time);
-	fattr->f_atime.tv_nsec = 0;
-
-	date = WVAL(req->rq_data, 8);
-	time = WVAL(req->rq_data, 10);
-	fattr->f_mtime.tv_sec = date_dos2unix(server, date, time);
-	fattr->f_mtime.tv_nsec = 0;
-	VERBOSE("name=%s, date=%x, time=%x, mtime=%ld\n",
-		mask, date, time, fattr->f_mtime.tv_sec);
-	fattr->f_size = DVAL(req->rq_data, 12);
-	/* ULONG allocation size */
-	fattr->attr = WVAL(req->rq_data, 20);
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_getattr_core(struct smb_sb_info *server, struct dentry *dir,
-		      struct smb_fattr *fattr)
-{
-	int result;
-	char *p;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	p = smb_setup_header(req, SMBgetatr, 0, 0);
-	result = smb_simple_encode_path(req, &p, dir, NULL);
-	if (result < 0)
- 		goto out_free;
-	smb_setup_bcc(req, p);
-
-	if ((result = smb_request_ok(req, SMBgetatr, 10, 0)) < 0)
-		goto out_free;
-	fattr->attr    = WVAL(req->rq_header, smb_vwv0);
-	fattr->f_mtime.tv_sec = local2utc(server, DVAL(req->rq_header, smb_vwv1));
-	fattr->f_mtime.tv_nsec = 0;
-	fattr->f_size  = DVAL(req->rq_header, smb_vwv3);
-	fattr->f_ctime = fattr->f_mtime; 
-	fattr->f_atime = fattr->f_mtime; 
-#ifdef SMBFS_DEBUG_TIMESTAMP
-	printk("getattr_core: %s/%s, mtime=%ld\n",
-	       DENTRY_PATH(dir), fattr->f_mtime);
-#endif
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * Bugs Noted:
- * (1) Win 95 swaps the date and time fields in the standard info level.
- */
-static int
-smb_proc_getattr_trans2(struct smb_sb_info *server, struct dentry *dir,
-			struct smb_request *req, int infolevel)
-{
-	char *p, *param;
-	int result;
-
-	param = req->rq_buffer;
-	WSET(param, 0, infolevel);
-	DSET(param, 2, 0);
-	result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, dir, NULL);
-	if (result < 0)
-		goto out;
-	p = param + 6 + result;
-
-	req->rq_trans2_command = TRANSACT2_QPATHINFO;
-	req->rq_ldata = 0;
-	req->rq_data  = NULL;
-	req->rq_lparm = p - param;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out;
-	if (req->rq_rcls != 0) {
-		VERBOSE("for %s: result=%d, rcls=%d, err=%d\n",
-			&param[6], result, req->rq_rcls, req->rq_err);
-		result = smb_errno(req);
-		goto out;
-	}
-	result = -ENOENT;
-	if (req->rq_ldata < 22) {
-		PARANOIA("not enough data for %s, len=%d\n",
-			 &param[6], req->rq_ldata);
-		goto out;
-	}
-
-	result = 0;
-out:
-	return result;
-}
-
-static int
-smb_proc_getattr_trans2_std(struct smb_sb_info *server, struct dentry *dir,
-			    struct smb_fattr *attr)
-{
-	u16 date, time;
-	int off_date = 0, off_time = 2;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	result = smb_proc_getattr_trans2(server, dir, req, SMB_INFO_STANDARD);
-	if (result < 0)
-		goto out_free;
-
-	/*
-	 * Kludge alert: Win 95 swaps the date and time field,
-	 * contrary to the CIFS docs and Win NT practice.
-	 */
-	if (server->mnt->flags & SMB_MOUNT_WIN95) {
-		off_date = 2;
-		off_time = 0;
-	}
-	date = WVAL(req->rq_data, off_date);
-	time = WVAL(req->rq_data, off_time);
-	attr->f_ctime.tv_sec = date_dos2unix(server, date, time);
-	attr->f_ctime.tv_nsec = 0;
-
-	date = WVAL(req->rq_data, 4 + off_date);
-	time = WVAL(req->rq_data, 4 + off_time);
-	attr->f_atime.tv_sec = date_dos2unix(server, date, time);
-	attr->f_atime.tv_nsec = 0;
-
-	date = WVAL(req->rq_data, 8 + off_date);
-	time = WVAL(req->rq_data, 8 + off_time);
-	attr->f_mtime.tv_sec = date_dos2unix(server, date, time);
-	attr->f_mtime.tv_nsec = 0;
-#ifdef SMBFS_DEBUG_TIMESTAMP
-	printk(KERN_DEBUG "getattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n",
-	       DENTRY_PATH(dir), date, time, attr->f_mtime);
-#endif
-	attr->f_size = DVAL(req->rq_data, 12);
-	attr->attr = WVAL(req->rq_data, 20);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_getattr_trans2_all(struct smb_sb_info *server, struct dentry *dir,
-			    struct smb_fattr *attr)
-{
-	struct smb_request *req;
-	int result;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	result = smb_proc_getattr_trans2(server, dir, req,
-					 SMB_QUERY_FILE_ALL_INFO);
-	if (result < 0)
-		goto out_free;
-
-	attr->f_ctime = smb_ntutc2unixutc(LVAL(req->rq_data, 0));
-	attr->f_atime = smb_ntutc2unixutc(LVAL(req->rq_data, 8));
-	attr->f_mtime = smb_ntutc2unixutc(LVAL(req->rq_data, 16));
-	/* change (24) */
-	attr->attr = WVAL(req->rq_data, 32);
-	/* pad? (34) */
-	/* allocated size (40) */
-	attr->f_size = LVAL(req->rq_data, 48);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_getattr_unix(struct smb_sb_info *server, struct dentry *dir,
-		      struct smb_fattr *attr)
-{
-	struct smb_request *req;
-	int result;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	result = smb_proc_getattr_trans2(server, dir, req,
-					 SMB_QUERY_FILE_UNIX_BASIC);
-	if (result < 0)
-		goto out_free;
-
-	smb_decode_unix_basic(attr, server, req->rq_data);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_getattr_95(struct smb_sb_info *server, struct dentry *dir,
-		    struct smb_fattr *attr)
-{
-	struct inode *inode = dir->d_inode;
-	int result;
-
-	/* FIXME: why not use the "all" version? */
-	result = smb_proc_getattr_trans2_std(server, dir, attr);
-	if (result < 0)
-		goto out;
-
-	/*
-	 * None of the getattr versions here can make win9x return the right
-	 * filesize if there are changes made to an open file.
-	 * A seek-to-end does return the right size, but we only need to do
-	 * that on files we have written.
-	 */
-	if (inode && SMB_I(inode)->flags & SMB_F_LOCALWRITE &&
-	    smb_is_open(inode))
-	{
-		__u16 fileid = SMB_I(inode)->fileid;
-		attr->f_size = smb_proc_seek(server, fileid, 2, 0);
-	}
-
-out:
-	return result;
-}
-
-static int
-smb_proc_ops_wait(struct smb_sb_info *server)
-{
-	int result;
-
-	result = wait_event_interruptible_timeout(server->conn_wq,
-				server->conn_complete, 30*HZ);
-
-	if (!result || signal_pending(current))
-		return -EIO;
-
-	return 0;
-}
-
-static int
-smb_proc_getattr_null(struct smb_sb_info *server, struct dentry *dir,
-			  struct smb_fattr *fattr)
-{
-	int result;
-
-	if (smb_proc_ops_wait(server) < 0)
-		return -EIO;
-
-	smb_init_dirent(server, fattr);
-	result = server->ops->getattr(server, dir, fattr);
-	smb_finish_dirent(server, fattr);
-
-	return result;
-}
-
-static int
-smb_proc_readdir_null(struct file *filp, void *dirent, filldir_t filldir,
-		      struct smb_cache_control *ctl)
-{
-	struct smb_sb_info *server = server_from_dentry(filp->f_path.dentry);
-
-	if (smb_proc_ops_wait(server) < 0)
-		return -EIO;
-
-	return server->ops->readdir(filp, dirent, filldir, ctl);
-}
-
-int
-smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr)
-{
-	struct smb_sb_info *server = server_from_dentry(dir);
-	int result;
-
-	smb_init_dirent(server, fattr);
-	result = server->ops->getattr(server, dir, fattr);
-	smb_finish_dirent(server, fattr);
-
-	return result;
-}
-
-
-/*
- * Because of bugs in the core protocol, we use this only to set
- * attributes. See smb_proc_settime() below for timestamp handling.
- *
- * Bugs Noted:
- * (1) If mtime is non-zero, both Win 3.1 and Win 95 fail
- * with an undocumented error (ERRDOS code 50). Setting
- * mtime to 0 allows the attributes to be set.
- * (2) The extra parameters following the name string aren't
- * in the CIFS docs, but seem to be necessary for operation.
- */
-static int
-smb_proc_setattr_core(struct smb_sb_info *server, struct dentry *dentry,
-		      __u16 attr)
-{
-	char *p;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-
-	p = smb_setup_header(req, SMBsetatr, 8, 0);
-	WSET(req->rq_header, smb_vwv0, attr);
-	DSET(req->rq_header, smb_vwv1, 0); /* mtime */
-	WSET(req->rq_header, smb_vwv3, 0); /* reserved values */
-	WSET(req->rq_header, smb_vwv4, 0);
-	WSET(req->rq_header, smb_vwv5, 0);
-	WSET(req->rq_header, smb_vwv6, 0);
-	WSET(req->rq_header, smb_vwv7, 0);
-	result = smb_simple_encode_path(req, &p, dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	if (p + 2 > (char *)req->rq_buffer + req->rq_bufsize) {
-		result = -ENAMETOOLONG;
-		goto out_free;
-	}
-	*p++ = 4;
-	*p++ = 0;
-	smb_setup_bcc(req, p);
-
-	result = smb_request_ok(req, SMBsetatr, 0, 0);
-	if (result < 0)
-		goto out_free;
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * Because of bugs in the trans2 setattr messages, we must set
- * attributes and timestamps separately. The core SMBsetatr
- * message seems to be the only reliable way to set attributes.
- */
-int
-smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr)
-{
-	struct smb_sb_info *server = server_from_dentry(dir);
-	int result;
-
-	VERBOSE("setting %s/%s, open=%d\n", 
-		DENTRY_PATH(dir), smb_is_open(dir->d_inode));
-	result = smb_proc_setattr_core(server, dir, fattr->attr);
-	return result;
-}
-
-/*
- * Sets the timestamps for an file open with write permissions.
- */
-static int
-smb_proc_setattr_ext(struct smb_sb_info *server,
-		      struct inode *inode, struct smb_fattr *fattr)
-{
-	__u16 date, time;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBsetattrE, 7, 0);
-	WSET(req->rq_header, smb_vwv0, SMB_I(inode)->fileid);
-	/* We don't change the creation time */
-	WSET(req->rq_header, smb_vwv1, 0);
-	WSET(req->rq_header, smb_vwv2, 0);
-	date_unix2dos(server, fattr->f_atime.tv_sec, &date, &time);
-	WSET(req->rq_header, smb_vwv3, date);
-	WSET(req->rq_header, smb_vwv4, time);
-	date_unix2dos(server, fattr->f_mtime.tv_sec, &date, &time);
-	WSET(req->rq_header, smb_vwv5, date);
-	WSET(req->rq_header, smb_vwv6, time);
-#ifdef SMBFS_DEBUG_TIMESTAMP
-	printk(KERN_DEBUG "smb_proc_setattr_ext: date=%d, time=%d, mtime=%ld\n",
-	       date, time, fattr->f_mtime);
-#endif
-
-	req->rq_flags |= SMB_REQ_NORETRY;
-	result = smb_request_ok(req, SMBsetattrE, 0, 0);
-	if (result < 0)
-		goto out_free;
-	result = 0;
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * Bugs Noted:
- * (1) The TRANSACT2_SETPATHINFO message under Win NT 4.0 doesn't
- * set the file's attribute flags.
- */
-static int
-smb_proc_setattr_trans2(struct smb_sb_info *server,
-			struct dentry *dir, struct smb_fattr *fattr)
-{
-	__u16 date, time;
-	char *p, *param;
-	int result;
-	char data[26];
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-	param = req->rq_buffer;
-
-	WSET(param, 0, 1);	/* Info level SMB_INFO_STANDARD */
-	DSET(param, 2, 0);
-	result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, dir, NULL);
-	if (result < 0)
-		goto out_free;
-	p = param + 6 + result;
-
-	WSET(data, 0, 0); /* creation time */
-	WSET(data, 2, 0);
-	date_unix2dos(server, fattr->f_atime.tv_sec, &date, &time);
-	WSET(data, 4, date);
-	WSET(data, 6, time);
-	date_unix2dos(server, fattr->f_mtime.tv_sec, &date, &time);
-	WSET(data, 8, date);
-	WSET(data, 10, time);
-#ifdef SMBFS_DEBUG_TIMESTAMP
-	printk(KERN_DEBUG "setattr_trans2: %s/%s, date=%x, time=%x, mtime=%ld\n", 
-	       DENTRY_PATH(dir), date, time, fattr->f_mtime);
-#endif
-	DSET(data, 12, 0); /* size */
-	DSET(data, 16, 0); /* blksize */
-	WSET(data, 20, 0); /* attr */
-	DSET(data, 22, 0); /* ULONG EA size */
-
-	req->rq_trans2_command = TRANSACT2_SETPATHINFO;
-	req->rq_ldata = 26;
-	req->rq_data  = data;
-	req->rq_lparm = p - param;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-	result = 0;
-	if (req->rq_rcls != 0)
-		result = smb_errno(req);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * ATTR_MODE      0x001
- * ATTR_UID       0x002
- * ATTR_GID       0x004
- * ATTR_SIZE      0x008
- * ATTR_ATIME     0x010
- * ATTR_MTIME     0x020
- * ATTR_CTIME     0x040
- * ATTR_ATIME_SET 0x080
- * ATTR_MTIME_SET 0x100
- * ATTR_FORCE     0x200	
- * ATTR_ATTR_FLAG 0x400
- *
- * major/minor should only be set by mknod.
- */
-int
-smb_proc_setattr_unix(struct dentry *d, struct iattr *attr,
-		      unsigned int major, unsigned int minor)
-{
-	struct smb_sb_info *server = server_from_dentry(d);
-	u64 nttime;
-	char *p, *param;
-	int result;
-	char data[100];
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-	param = req->rq_buffer;
-
-	DEBUG1("valid flags = 0x%04x\n", attr->ia_valid);
-
-	WSET(param, 0, SMB_SET_FILE_UNIX_BASIC);
-	DSET(param, 2, 0);
-	result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, d, NULL);
-	if (result < 0)
-		goto out_free;
-	p = param + 6 + result;
-
-	/* 0 L file size in bytes */
-	/* 8 L file size on disk in bytes (block count) */
-	/* 40 L uid */
-	/* 48 L gid */
-	/* 56 W file type enum */
-	/* 60 L devmajor */
-	/* 68 L devminor */
-	/* 76 L unique ID (inode) */
-	/* 84 L permissions */
-	/* 92 L link count */
-	LSET(data, 0, SMB_SIZE_NO_CHANGE);
-	LSET(data, 8, SMB_SIZE_NO_CHANGE);
-	LSET(data, 16, SMB_TIME_NO_CHANGE);
-	LSET(data, 24, SMB_TIME_NO_CHANGE);
-	LSET(data, 32, SMB_TIME_NO_CHANGE);
-	LSET(data, 40, SMB_UID_NO_CHANGE);
-	LSET(data, 48, SMB_GID_NO_CHANGE);
-	DSET(data, 56, smb_filetype_from_mode(attr->ia_mode));
-	LSET(data, 60, major);
-	LSET(data, 68, minor);
-	LSET(data, 76, 0);
-	LSET(data, 84, SMB_MODE_NO_CHANGE);
-	LSET(data, 92, 0);
-
-	if (attr->ia_valid & ATTR_SIZE) {
-		LSET(data, 0, attr->ia_size);
-		LSET(data, 8, 0); /* can't set anyway */
-	}
-
-	/*
-	 * FIXME: check the conversion function it the correct one
-	 *
-	 * we can't set ctime but we might as well pass this to the server
-	 * and let it ignore it.
-	 */
-	if (attr->ia_valid & ATTR_CTIME) {
-		nttime = smb_unixutc2ntutc(attr->ia_ctime);
-		LSET(data, 16, nttime);
-	}
-	if (attr->ia_valid & ATTR_ATIME) {
-		nttime = smb_unixutc2ntutc(attr->ia_atime);
-		LSET(data, 24, nttime);
-	}
-	if (attr->ia_valid & ATTR_MTIME) {
-		nttime = smb_unixutc2ntutc(attr->ia_mtime);
-		LSET(data, 32, nttime);
-	}
-	
-	if (attr->ia_valid & ATTR_UID) {
-		LSET(data, 40, attr->ia_uid);
-	}
-	if (attr->ia_valid & ATTR_GID) {
-		LSET(data, 48, attr->ia_gid); 
-	}
-	
-	if (attr->ia_valid & ATTR_MODE) {
-		LSET(data, 84, attr->ia_mode);
-	}
-
-	req->rq_trans2_command = TRANSACT2_SETPATHINFO;
-	req->rq_ldata = 100;
-	req->rq_data  = data;
-	req->rq_lparm = p - param;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-
-/*
- * Set the modify and access timestamps for a file.
- *
- * Incredibly enough, in all of SMB there is no message to allow
- * setting both attributes and timestamps at once. 
- *
- * Bugs Noted:
- * (1) Win 95 doesn't support the TRANSACT2_SETFILEINFO message 
- * with info level 1 (INFO_STANDARD).
- * (2) Win 95 seems not to support setting directory timestamps.
- * (3) Under the core protocol apparently the only way to set the
- * timestamp is to open and close the file.
- */
-int
-smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr)
-{
-	struct smb_sb_info *server = server_from_dentry(dentry);
-	struct inode *inode = dentry->d_inode;
-	int result;
-
-	VERBOSE("setting %s/%s, open=%d\n",
-		DENTRY_PATH(dentry), smb_is_open(inode));
-
-	/* setting the time on a Win95 server fails (tridge) */
-	if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2 && 
-	    !(server->mnt->flags & SMB_MOUNT_WIN95)) {
-		if (smb_is_open(inode) && SMB_I(inode)->access != SMB_O_RDONLY)
-			result = smb_proc_setattr_ext(server, inode, fattr);
-		else
-			result = smb_proc_setattr_trans2(server, dentry, fattr);
-	} else {
-		/*
-		 * Fail silently on directories ... timestamp can't be set?
-		 */
-		result = 0;
-		if (S_ISREG(inode->i_mode)) {
-			/*
-			 * Set the mtime by opening and closing the file.
-			 * Note that the file is opened read-only, but this
-			 * still allows us to set the date (tridge)
-			 */
-			result = -EACCES;
-			if (!smb_is_open(inode))
-				smb_proc_open(server, dentry, SMB_O_RDONLY);
-			if (smb_is_open(inode)) {
-				inode->i_mtime = fattr->f_mtime;
-				result = smb_proc_close_inode(server, inode);
-			}
-		}
-	}
-
-	return result;
-}
-
-int
-smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr)
-{
-	struct smb_sb_info *server = SMB_SB(dentry->d_sb);
-	int result;
-	char *p;
-	long unit;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 0)))
-		goto out;
-
-	smb_setup_header(req, SMBdskattr, 0, 0);
-	if ((result = smb_request_ok(req, SMBdskattr, 5, 0)) < 0)
-		goto out_free;
-	p = SMB_VWV(req->rq_header);
-	unit = (WVAL(p, 2) * WVAL(p, 4)) >> SMB_ST_BLKSHIFT;
-	attr->f_blocks = WVAL(p, 0) * unit;
-	attr->f_bsize  = SMB_ST_BLKSIZE;
-	attr->f_bavail = attr->f_bfree = WVAL(p, 6) * unit;
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-int
-smb_proc_read_link(struct smb_sb_info *server, struct dentry *d,
-		   char *buffer, int len)
-{
-	char *p, *param;
-	int result;
-	struct smb_request *req;
-
-	DEBUG1("readlink of %s/%s\n", DENTRY_PATH(d));
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-	param = req->rq_buffer;
-
-	WSET(param, 0, SMB_QUERY_FILE_UNIX_LINK);
-	DSET(param, 2, 0);
-	result = smb_encode_path(server, param+6, SMB_MAXPATHLEN+1, d, NULL);
-	if (result < 0)
-		goto out_free;
-	p = param + 6 + result;
-
-	req->rq_trans2_command = TRANSACT2_QPATHINFO;
-	req->rq_ldata = 0;
-	req->rq_data  = NULL;
-	req->rq_lparm = p - param;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-	DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
-		&param[6], result, req->rq_rcls, req->rq_err);
-
-	/* copy data up to the \0 or buffer length */
-	result = len;
-	if (req->rq_ldata < len)
-		result = req->rq_ldata;
-	strncpy(buffer, req->rq_data, result);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-
-/*
- * Create a symlink object called dentry which points to oldpath.
- * Samba does not permit dangling links but returns a suitable error message.
- */
-int
-smb_proc_symlink(struct smb_sb_info *server, struct dentry *d,
-		 const char *oldpath)
-{
-	char *p, *param;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-	param = req->rq_buffer;
-
-	WSET(param, 0, SMB_SET_FILE_UNIX_LINK);
-	DSET(param, 2, 0);
-	result = smb_encode_path(server, param + 6, SMB_MAXPATHLEN+1, d, NULL);
-	if (result < 0)
-		goto out_free;
-	p = param + 6 + result;
-
-	req->rq_trans2_command = TRANSACT2_SETPATHINFO;
-	req->rq_ldata = strlen(oldpath) + 1;
-	req->rq_data  = (char *) oldpath;
-	req->rq_lparm = p - param;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-
-	DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
-		&param[6], result, req->rq_rcls, req->rq_err);
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-/*
- * Create a hard link object called new_dentry which points to dentry.
- */
-int
-smb_proc_link(struct smb_sb_info *server, struct dentry *dentry,
-	      struct dentry *new_dentry)
-{
-	char *p, *param;
-	int result;
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, PAGE_SIZE)))
-		goto out;
-	param = req->rq_buffer;
-
-	WSET(param, 0, SMB_SET_FILE_UNIX_HLINK);
-	DSET(param, 2, 0);
-	result = smb_encode_path(server, param + 6, SMB_MAXPATHLEN+1,
-				 new_dentry, NULL);
-	if (result < 0)
-		goto out_free;
-	p = param + 6 + result;
-
-	/* Grr, pointless separation of parameters and data ... */
-	req->rq_data = p;
-	req->rq_ldata = smb_encode_path(server, p, SMB_MAXPATHLEN+1,
-					dentry, NULL);
-
-	req->rq_trans2_command = TRANSACT2_SETPATHINFO;
-	req->rq_lparm = p - param;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-
-	DEBUG1("for %s: result=%d, rcls=%d, err=%d\n",
-	       &param[6], result, req->rq_rcls, req->rq_err);
-	result = 0;
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-static int
-smb_proc_query_cifsunix(struct smb_sb_info *server)
-{
-	int result;
-	int major, minor;
-	u64 caps;
-	char param[2];
-	struct smb_request *req;
-
-	result = -ENOMEM;
-	if (! (req = smb_alloc_request(server, 100)))
-		goto out;
-
-	WSET(param, 0, SMB_QUERY_CIFS_UNIX_INFO);
-
-	req->rq_trans2_command = TRANSACT2_QFSINFO;
-	req->rq_ldata = 0;
-	req->rq_data  = NULL;
-	req->rq_lparm = 2;
-	req->rq_parm  = param;
-	req->rq_flags = 0;
-	result = smb_add_request(req);
-	if (result < 0)
-		goto out_free;
-
-	if (req->rq_ldata < 12) {
-		PARANOIA("Not enough data\n");
-		goto out_free;
-	}
-	major = WVAL(req->rq_data, 0);
-	minor = WVAL(req->rq_data, 2);
-
-	DEBUG1("Server implements CIFS Extensions for UNIX systems v%d.%d\n",
-	       major, minor);
-	/* FIXME: verify that we are ok with this major/minor? */
-
-	caps = LVAL(req->rq_data, 4);
-	DEBUG1("Server capabilities 0x%016llx\n", caps);
-
-out_free:
-	smb_rput(req);
-out:
-	return result;
-}
-
-
-static void
-install_ops(struct smb_ops *dst, struct smb_ops *src)
-{
-	memcpy(dst, src, sizeof(void *) * SMB_OPS_NUM_STATIC);
-}
-
-/* < LANMAN2 */
-static struct smb_ops smb_ops_core =
-{
-	.read		= smb_proc_read,
-	.write		= smb_proc_write,
-	.readdir	= smb_proc_readdir_short,
-	.getattr	= smb_proc_getattr_core,
-	.truncate	= smb_proc_trunc32,
-};
-
-/* LANMAN2, OS/2, others? */
-static struct smb_ops smb_ops_os2 =
-{
-	.read		= smb_proc_read,
-	.write		= smb_proc_write,
-	.readdir	= smb_proc_readdir_long,
-	.getattr	= smb_proc_getattr_trans2_std,
-	.truncate	= smb_proc_trunc32,
-};
-
-/* Win95, and possibly some NetApp versions too */
-static struct smb_ops smb_ops_win95 =
-{
-	.read		= smb_proc_read,    /* does not support 12word readX */
-	.write		= smb_proc_write,
-	.readdir	= smb_proc_readdir_long,
-	.getattr	= smb_proc_getattr_95,
-	.truncate	= smb_proc_trunc95,
-};
-
-/* Samba, NT4 and NT5 */
-static struct smb_ops smb_ops_winNT =
-{
-	.read		= smb_proc_readX,
-	.write		= smb_proc_writeX,
-	.readdir	= smb_proc_readdir_long,
-	.getattr	= smb_proc_getattr_trans2_all,
-	.truncate	= smb_proc_trunc64,
-};
-
-/* Samba w/ unix extensions. Others? */
-static struct smb_ops smb_ops_unix =
-{
-	.read		= smb_proc_readX,
-	.write		= smb_proc_writeX,
-	.readdir	= smb_proc_readdir_long,
-	.getattr	= smb_proc_getattr_unix,
-	/* FIXME: core/ext/time setattr needs to be cleaned up! */
-	/* .setattr	= smb_proc_setattr_unix, */
-	.truncate	= smb_proc_trunc64,
-};
-
-/* Place holder until real ops are in place */
-static struct smb_ops smb_ops_null =
-{
-	.readdir	= smb_proc_readdir_null,
-	.getattr	= smb_proc_getattr_null,
-};
-
-void smb_install_null_ops(struct smb_ops *ops)
-{
-	install_ops(ops, &smb_ops_null);
-}
diff --git a/drivers/staging/smbfs/proto.h b/drivers/staging/smbfs/proto.h
deleted file mode 100644
index 3883cb1..0000000
--- a/drivers/staging/smbfs/proto.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  Autogenerated with cproto on:  Sat Sep 13 17:18:51 CEST 2003
- */
-
-struct smb_request;
-struct sock;
-struct statfs;
-
-/* proc.c */
-extern int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
-extern __u32 smb_len(__u8 *p);
-extern int smb_get_rsize(struct smb_sb_info *server);
-extern int smb_get_wsize(struct smb_sb_info *server);
-extern int smb_errno(struct smb_request *req);
-extern int smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt);
-extern __u8 *smb_setup_header(struct smb_request *req, __u8 command, __u16 wct, __u16 bcc);
-extern int smb_open(struct dentry *dentry, int wish);
-extern int smb_close(struct inode *ino);
-extern int smb_close_fileid(struct dentry *dentry, __u16 fileid);
-extern int smb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid);
-extern int smb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry);
-extern int smb_proc_mkdir(struct dentry *dentry);
-extern int smb_proc_rmdir(struct dentry *dentry);
-extern int smb_proc_unlink(struct dentry *dentry);
-extern int smb_proc_flush(struct smb_sb_info *server, __u16 fileid);
-extern void smb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr,
-				 struct super_block *sb);
-extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr);
-extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
-extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor);
-extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr);
-extern int smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr);
-extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len);
-extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath);
-extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
-extern void smb_install_null_ops(struct smb_ops *ops);
-/* dir.c */
-extern const struct file_operations smb_dir_operations;
-extern const struct inode_operations smb_dir_inode_operations;
-extern const struct inode_operations smb_dir_inode_operations_unix;
-extern const struct dentry_operations smbfs_dentry_operations_case;
-extern const struct dentry_operations smbfs_dentry_operations;
-extern void smb_new_dentry(struct dentry *dentry);
-extern void smb_renew_times(struct dentry *dentry);
-/* cache.c */
-extern void smb_invalid_dir_cache(struct inode *dir);
-extern void smb_invalidate_dircache_entries(struct dentry *parent);
-extern struct dentry *smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos);
-extern int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir, struct smb_cache_control *ctrl, struct qstr *qname, struct smb_fattr *entry);
-/* sock.c */
-extern void smb_data_ready(struct sock *sk, int len);
-extern int smb_valid_socket(struct inode *inode);
-extern void smb_close_socket(struct smb_sb_info *server);
-extern int smb_recv_available(struct smb_sb_info *server);
-extern int smb_receive_header(struct smb_sb_info *server);
-extern int smb_receive_drop(struct smb_sb_info *server);
-extern int smb_receive(struct smb_sb_info *server, struct smb_request *req);
-extern int smb_send_request(struct smb_request *req);
-/* inode.c */
-extern struct inode *smb_iget(struct super_block *sb, struct smb_fattr *fattr);
-extern void smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr);
-extern void smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr);
-extern void smb_invalidate_inodes(struct smb_sb_info *server);
-extern int smb_revalidate_inode(struct dentry *dentry);
-extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
-extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
-/* file.c */
-extern const struct address_space_operations smb_file_aops;
-extern const struct file_operations smb_file_operations;
-extern const struct inode_operations smb_file_inode_operations;
-/* ioctl.c */
-extern long smb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-/* smbiod.c */
-extern void smbiod_wake_up(void);
-extern int smbiod_register_server(struct smb_sb_info *server);
-extern void smbiod_unregister_server(struct smb_sb_info *server);
-extern void smbiod_flush(struct smb_sb_info *server);
-extern int smbiod_retry(struct smb_sb_info *server);
-/* request.c */
-extern int smb_init_request_cache(void);
-extern void smb_destroy_request_cache(void);
-extern struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize);
-extern void smb_rput(struct smb_request *req);
-extern int smb_add_request(struct smb_request *req);
-extern int smb_request_send_server(struct smb_sb_info *server);
-extern int smb_request_recv(struct smb_sb_info *server);
-/* symlink.c */
-extern int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname);
-extern const struct inode_operations smb_link_inode_operations;
diff --git a/drivers/staging/smbfs/request.c b/drivers/staging/smbfs/request.c
deleted file mode 100644
index 3e77168..0000000
--- a/drivers/staging/smbfs/request.c
+++ /dev/null
@@ -1,817 +0,0 @@
-/*
- *  request.c
- *
- *  Copyright (C) 2001 by Urban Widmark
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-
-#include "smb_fs.h"
-#include "smbno.h"
-#include "smb_mount.h"
-#include "smb_debug.h"
-#include "request.h"
-#include "proto.h"
-
-/* #define SMB_SLAB_DEBUG	(SLAB_RED_ZONE | SLAB_POISON) */
-#define SMB_SLAB_DEBUG	0
-
-/* cache for request structures */
-static struct kmem_cache *req_cachep;
-
-static int smb_request_send_req(struct smb_request *req);
-
-/*
-  /proc/slabinfo:
-  name, active, num, objsize, active_slabs, num_slaps, #pages
-*/
-
-
-int smb_init_request_cache(void)
-{
-	req_cachep = kmem_cache_create("smb_request",
-				       sizeof(struct smb_request), 0,
-				       SMB_SLAB_DEBUG | SLAB_HWCACHE_ALIGN,
-				       NULL);
-	if (req_cachep == NULL)
-		return -ENOMEM;
-
-	return 0;
-}
-
-void smb_destroy_request_cache(void)
-{
-	kmem_cache_destroy(req_cachep);
-}
-
-/*
- * Allocate and initialise a request structure
- */
-static struct smb_request *smb_do_alloc_request(struct smb_sb_info *server,
-						int bufsize)
-{
-	struct smb_request *req;
-	unsigned char *buf = NULL;
-
-	req = kmem_cache_zalloc(req_cachep, GFP_KERNEL);
-	VERBOSE("allocating request: %p\n", req);
-	if (!req)
-		goto out;
-
-	if (bufsize > 0) {
-		buf = kmalloc(bufsize, GFP_NOFS);
-		if (!buf) {
-			kmem_cache_free(req_cachep, req);
-			return NULL;
-		}
-	}
-
-	req->rq_buffer = buf;
-	req->rq_bufsize = bufsize;
-	req->rq_server = server;
-	init_waitqueue_head(&req->rq_wait);
-	INIT_LIST_HEAD(&req->rq_queue);
-	atomic_set(&req->rq_count, 1);
-
-out:
-	return req;
-}
-
-struct smb_request *smb_alloc_request(struct smb_sb_info *server, int bufsize)
-{
-	struct smb_request *req = NULL;
-
-	for (;;) {
-		atomic_inc(&server->nr_requests);
-		if (atomic_read(&server->nr_requests) <= MAX_REQUEST_HARD) {
-			req = smb_do_alloc_request(server, bufsize);
-			if (req != NULL)
-				break;
-		}
-
-#if 0
-		/*
-		 * Try to free up at least one request in order to stay
-		 * below the hard limit
-		 */
-                if (nfs_try_to_free_pages(server))
-			continue;
-
-		if (fatal_signal_pending(current))
-			return ERR_PTR(-ERESTARTSYS);
-		current->policy = SCHED_YIELD;
-		schedule();
-#else
-		/* FIXME: we want something like nfs does above, but that
-		   requires changes to all callers and can wait. */
-		break;
-#endif
-	}
-	return req;
-}
-
-static void smb_free_request(struct smb_request *req)
-{
-	atomic_dec(&req->rq_server->nr_requests);
-	if (req->rq_buffer && !(req->rq_flags & SMB_REQ_STATIC))
-		kfree(req->rq_buffer);
-	kfree(req->rq_trans2buffer);
-	kmem_cache_free(req_cachep, req);
-}
-
-/*
- * What prevents a rget to race with a rput? The count must never drop to zero
- * while it is in use. Only rput if it is ok that it is free'd.
- */
-static void smb_rget(struct smb_request *req)
-{
-	atomic_inc(&req->rq_count);
-}
-void smb_rput(struct smb_request *req)
-{
-	if (atomic_dec_and_test(&req->rq_count)) {
-		list_del_init(&req->rq_queue);
-		smb_free_request(req);
-	}
-}
-
-/* setup to receive the data part of the SMB */
-static int smb_setup_bcc(struct smb_request *req)
-{
-	int result = 0;
-	req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;
-
-	if (req->rq_rlen > req->rq_bufsize) {
-		PARANOIA("Packet too large %d > %d\n",
-			 req->rq_rlen, req->rq_bufsize);
-		return -ENOBUFS;
-	}
-
-	req->rq_iov[0].iov_base = req->rq_buffer;
-	req->rq_iov[0].iov_len  = req->rq_rlen;
-	req->rq_iovlen = 1;
-
-	return result;
-}
-
-/*
- * Prepare a "normal" request structure.
- */
-static int smb_setup_request(struct smb_request *req)
-{
-	int len = smb_len(req->rq_header) + 4;
-	req->rq_slen = len;
-
-	/* if we expect a data part in the reply we set the iov's to read it */
-	if (req->rq_resp_bcc)
-		req->rq_setup_read = smb_setup_bcc;
-
-	/* This tries to support re-using the same request */
-	req->rq_bytes_sent = 0;
-	req->rq_rcls = 0;
-	req->rq_err = 0;
-	req->rq_errno = 0;
-	req->rq_fragment = 0;
-	kfree(req->rq_trans2buffer);
-	req->rq_trans2buffer = NULL;
-
-	return 0;
-}
-
-/*
- * Prepare a transaction2 request structure
- */
-static int smb_setup_trans2request(struct smb_request *req)
-{
-	struct smb_sb_info *server = req->rq_server;
-	int mparam, mdata;
-	static unsigned char padding[4];
-
-	/* I know the following is very ugly, but I want to build the
-	   smb packet as efficiently as possible. */
-
-	const int smb_parameters = 15;
-	const int header = SMB_HEADER_LEN + 2 * smb_parameters + 2;
-	const int oparam = ALIGN(header + 3, sizeof(u32));
-	const int odata  = ALIGN(oparam + req->rq_lparm, sizeof(u32));
-	const int bcc = (req->rq_data ? odata + req->rq_ldata :
-					oparam + req->rq_lparm) - header;
-
-	if ((bcc + oparam) > server->opt.max_xmit)
-		return -ENOMEM;
-	smb_setup_header(req, SMBtrans2, smb_parameters, bcc);
-
-	/*
-	 * max parameters + max data + max setup == bufsize to make NT4 happy
-	 * and not abort the transfer or split into multiple responses. It also
-	 * makes smbfs happy as handling packets larger than the buffer size
-	 * is extra work.
-	 *
-	 * OS/2 is probably going to hate me for this ...
-	 */
-	mparam = SMB_TRANS2_MAX_PARAM;
-	mdata = req->rq_bufsize - mparam;
-
-	mdata = server->opt.max_xmit - mparam - 100;
-	if (mdata < 1024) {
-		mdata = 1024;
-		mparam = 20;
-	}
-
-#if 0
-	/* NT/win2k has ~4k max_xmit, so with this we request more than it wants
-	   to return as one SMB. Useful for testing the fragmented trans2
-	   handling. */
-	mdata = 8192;
-#endif
-
-	WSET(req->rq_header, smb_tpscnt, req->rq_lparm);
-	WSET(req->rq_header, smb_tdscnt, req->rq_ldata);
-	WSET(req->rq_header, smb_mprcnt, mparam);
-	WSET(req->rq_header, smb_mdrcnt, mdata);
-	WSET(req->rq_header, smb_msrcnt, 0);    /* max setup always 0 ? */
-	WSET(req->rq_header, smb_flags, 0);
-	DSET(req->rq_header, smb_timeout, 0);
-	WSET(req->rq_header, smb_pscnt, req->rq_lparm);
-	WSET(req->rq_header, smb_psoff, oparam - 4);
-	WSET(req->rq_header, smb_dscnt, req->rq_ldata);
-	WSET(req->rq_header, smb_dsoff, req->rq_data ? odata - 4 : 0);
-	*(req->rq_header + smb_suwcnt) = 0x01;          /* setup count */
-	*(req->rq_header + smb_suwcnt + 1) = 0x00;      /* reserved */
-	WSET(req->rq_header, smb_setup0, req->rq_trans2_command);
-
-	req->rq_iovlen = 2;
-	req->rq_iov[0].iov_base = (void *) req->rq_header;
-	req->rq_iov[0].iov_len = oparam;
-	req->rq_iov[1].iov_base = (req->rq_parm==NULL) ? padding : req->rq_parm;
-	req->rq_iov[1].iov_len = req->rq_lparm;
-	req->rq_slen = oparam + req->rq_lparm;
-
-	if (req->rq_data) {
-		req->rq_iovlen += 2;
-		req->rq_iov[2].iov_base = padding;
-		req->rq_iov[2].iov_len = odata - oparam - req->rq_lparm;
-		req->rq_iov[3].iov_base = req->rq_data;
-		req->rq_iov[3].iov_len = req->rq_ldata;
-		req->rq_slen = odata + req->rq_ldata;
-	}
-
-	/* always a data part for trans2 replies */
-	req->rq_setup_read = smb_setup_bcc;
-
-	return 0;
-}
-
-/*
- * Add a request and tell smbiod to process it
- */
-int smb_add_request(struct smb_request *req)
-{
-	long timeleft;
-	struct smb_sb_info *server = req->rq_server;
-	int result = 0;
-
-	smb_setup_request(req);
-	if (req->rq_trans2_command) {
-		if (req->rq_buffer == NULL) {
-			PARANOIA("trans2 attempted without response buffer!\n");
-			return -EIO;
-		}
-		result = smb_setup_trans2request(req);
-	}
-	if (result < 0)
-		return result;
-
-#ifdef SMB_DEBUG_PACKET_SIZE
-	add_xmit_stats(req);
-#endif
-
-	/* add 'req' to the queue of requests */
-	if (smb_lock_server_interruptible(server))
-		return -EINTR;
-
-	/*
-	 * Try to send the request as the process. If that fails we queue the
-	 * request and let smbiod send it later.
-	 */
-
-	/* FIXME: each server has a number on the maximum number of parallel
-	   requests. 10, 50 or so. We should not allow more requests to be
-	   active. */
-	if (server->mid > 0xf000)
-		server->mid = 0;
-	req->rq_mid = server->mid++;
-	WSET(req->rq_header, smb_mid, req->rq_mid);
-
-	result = 0;
-	if (server->state == CONN_VALID) {
-		if (list_empty(&server->xmitq))
-			result = smb_request_send_req(req);
-		if (result < 0) {
-			/* Connection lost? */
-			server->conn_error = result;
-			server->state = CONN_INVALID;
-		}
-	}
-	if (result != 1)
-		list_add_tail(&req->rq_queue, &server->xmitq);
-	smb_rget(req);
-
-	if (server->state != CONN_VALID)
-		smbiod_retry(server);
-
-	smb_unlock_server(server);
-
-	smbiod_wake_up();
-
-	timeleft = wait_event_interruptible_timeout(req->rq_wait,
-				    req->rq_flags & SMB_REQ_RECEIVED, 30*HZ);
-	if (!timeleft || signal_pending(current)) {
-		/*
-		 * On timeout or on interrupt we want to try and remove the
-		 * request from the recvq/xmitq.
-		 * First check if the request is still part of a queue. (May
-		 * have been removed by some error condition)
-		 */
-		smb_lock_server(server);
-		if (!list_empty(&req->rq_queue)) {
-			list_del_init(&req->rq_queue);
-			smb_rput(req);
-		}
-		smb_unlock_server(server);
-	}
-
-	if (!timeleft) {
-		PARANOIA("request [%p, mid=%d] timed out!\n",
-			 req, req->rq_mid);
-		VERBOSE("smb_com:  %02x\n", *(req->rq_header + smb_com));
-		VERBOSE("smb_rcls: %02x\n", *(req->rq_header + smb_rcls));
-		VERBOSE("smb_flg:  %02x\n", *(req->rq_header + smb_flg));
-		VERBOSE("smb_tid:  %04x\n", WVAL(req->rq_header, smb_tid));
-		VERBOSE("smb_pid:  %04x\n", WVAL(req->rq_header, smb_pid));
-		VERBOSE("smb_uid:  %04x\n", WVAL(req->rq_header, smb_uid));
-		VERBOSE("smb_mid:  %04x\n", WVAL(req->rq_header, smb_mid));
-		VERBOSE("smb_wct:  %02x\n", *(req->rq_header + smb_wct));
-
-		req->rq_rcls = ERRSRV;
-		req->rq_err  = ERRtimeout;
-
-		/* Just in case it was "stuck" */
-		smbiod_wake_up();
-	}
-	VERBOSE("woke up, rcls=%d\n", req->rq_rcls);
-
-	if (req->rq_rcls != 0)
-		req->rq_errno = smb_errno(req);
-	if (signal_pending(current))
-		req->rq_errno = -ERESTARTSYS;
-	return req->rq_errno;
-}
-
-/*
- * Send a request and place it on the recvq if successfully sent.
- * Must be called with the server lock held.
- */
-static int smb_request_send_req(struct smb_request *req)
-{
-	struct smb_sb_info *server = req->rq_server;
-	int result;
-
-	if (req->rq_bytes_sent == 0) {
-		WSET(req->rq_header, smb_tid, server->opt.tid);
-		WSET(req->rq_header, smb_pid, 1);
-		WSET(req->rq_header, smb_uid, server->opt.server_uid);
-	}
-
-	result = smb_send_request(req);
-	if (result < 0 && result != -EAGAIN)
-		goto out;
-
-	result = 0;
-	if (!(req->rq_flags & SMB_REQ_TRANSMITTED))
-		goto out;
-
-	list_move_tail(&req->rq_queue, &server->recvq);
-	result = 1;
-out:
-	return result;
-}
-
-/*
- * Sends one request for this server. (smbiod)
- * Must be called with the server lock held.
- * Returns: <0 on error
- *           0 if no request could be completely sent
- *           1 if all data for one request was sent
- */
-int smb_request_send_server(struct smb_sb_info *server)
-{
-	struct list_head *head;
-	struct smb_request *req;
-	int result;
-
-	if (server->state != CONN_VALID)
-		return 0;
-
-	/* dequeue first request, if any */
-	req = NULL;
-	head = server->xmitq.next;
-	if (head != &server->xmitq) {
-		req = list_entry(head, struct smb_request, rq_queue);
-	}
-	if (!req)
-		return 0;
-
-	result = smb_request_send_req(req);
-	if (result < 0) {
-		server->conn_error = result;
-		list_move(&req->rq_queue, &server->xmitq);
-		result = -EIO;
-		goto out;
-	}
-
-out:
-	return result;
-}
-
-/*
- * Try to find a request matching this "mid". Typically the first entry will
- * be the matching one.
- */
-static struct smb_request *find_request(struct smb_sb_info *server, int mid)
-{
-	struct list_head *tmp;
-	struct smb_request *req = NULL;
-
-	list_for_each(tmp, &server->recvq) {
-		req = list_entry(tmp, struct smb_request, rq_queue);
-		if (req->rq_mid == mid) {
-			break;
-		}
-		req = NULL;
-	}
-
-	if (!req) {
-		VERBOSE("received reply with mid %d but no request!\n",
-			WVAL(server->header, smb_mid));
-		server->rstate = SMB_RECV_DROP;
-	}
-
-	return req;
-}
-
-/*
- * Called when we have read the smb header and believe this is a response.
- */
-static int smb_init_request(struct smb_sb_info *server, struct smb_request *req)
-{
-	int hdrlen, wct;
-
-	memcpy(req->rq_header, server->header, SMB_HEADER_LEN);
-
-	wct = *(req->rq_header + smb_wct);
-	if (wct > 20) {	
-		PARANOIA("wct too large, %d > 20\n", wct);
-		server->rstate = SMB_RECV_DROP;
-		return 0;
-	}
-
-	req->rq_resp_wct = wct;
-	hdrlen = SMB_HEADER_LEN + wct*2 + 2;
-	VERBOSE("header length: %d   smb_wct: %2d\n", hdrlen, wct);
-
-	req->rq_bytes_recvd = SMB_HEADER_LEN;
-	req->rq_rlen = hdrlen;
-	req->rq_iov[0].iov_base = req->rq_header;
-	req->rq_iov[0].iov_len  = hdrlen;
-	req->rq_iovlen = 1;
-	server->rstate = SMB_RECV_PARAM;
-
-#ifdef SMB_DEBUG_PACKET_SIZE
-	add_recv_stats(smb_len(server->header));
-#endif
-	return 0;
-}
-
-/*
- * Reads the SMB parameters
- */
-static int smb_recv_param(struct smb_sb_info *server, struct smb_request *req)
-{
-	int result;
-
-	result = smb_receive(server, req);
-	if (result < 0)
-		return result;
-	if (req->rq_bytes_recvd < req->rq_rlen)
-		return 0;
-
-	VERBOSE("result: %d   smb_bcc:  %04x\n", result,
-		WVAL(req->rq_header, SMB_HEADER_LEN +
-		     (*(req->rq_header + smb_wct) * 2)));
-
-	result = 0;
-	req->rq_iov[0].iov_base = NULL;
-	req->rq_rlen = 0;
-	if (req->rq_callback)
-		req->rq_callback(req);
-	else if (req->rq_setup_read)
-		result = req->rq_setup_read(req);
-	if (result < 0) {
-		server->rstate = SMB_RECV_DROP;
-		return result;
-	}
-
-	server->rstate = req->rq_rlen > 0 ? SMB_RECV_DATA : SMB_RECV_END;
-
-	req->rq_bytes_recvd = 0;	// recvd out of the iov
-
-	VERBOSE("rlen: %d\n", req->rq_rlen);
-	if (req->rq_rlen < 0) {
-		PARANOIA("Parameters read beyond end of packet!\n");
-		server->rstate = SMB_RECV_END;
-		return -EIO;
-	}
-	return 0;
-}
-
-/*
- * Reads the SMB data
- */
-static int smb_recv_data(struct smb_sb_info *server, struct smb_request *req)
-{
-	int result;
-
-	result = smb_receive(server, req);
-	if (result < 0)
-		goto out;
-	if (req->rq_bytes_recvd < req->rq_rlen)
-		goto out;
-	server->rstate = SMB_RECV_END;
-out:
-	VERBOSE("result: %d\n", result);
-	return result;
-}
-
-/*
- * Receive a transaction2 response
- * Return: 0 if the response has been fully read
- *         1 if there are further "fragments" to read
- *        <0 if there is an error
- */
-static int smb_recv_trans2(struct smb_sb_info *server, struct smb_request *req)
-{
-	unsigned char *inbuf;
-	unsigned int parm_disp, parm_offset, parm_count, parm_tot;
-	unsigned int data_disp, data_offset, data_count, data_tot;
-	int hdrlen = SMB_HEADER_LEN + req->rq_resp_wct*2 - 2;
-
-	VERBOSE("handling trans2\n");
-
-	inbuf = req->rq_header;
-	data_tot    = WVAL(inbuf, smb_tdrcnt);
-	parm_tot    = WVAL(inbuf, smb_tprcnt);
-	parm_disp   = WVAL(inbuf, smb_prdisp);
-	parm_offset = WVAL(inbuf, smb_proff);
-	parm_count  = WVAL(inbuf, smb_prcnt);
-	data_disp   = WVAL(inbuf, smb_drdisp);
-	data_offset = WVAL(inbuf, smb_droff);
-	data_count  = WVAL(inbuf, smb_drcnt);
-
-	/* Modify offset for the split header/buffer we use */
-	if (data_count || data_offset) {
-		if (unlikely(data_offset < hdrlen))
-			goto out_bad_data;
-		else
-			data_offset -= hdrlen;
-	}
-	if (parm_count || parm_offset) {
-		if (unlikely(parm_offset < hdrlen))
-			goto out_bad_parm;
-		else
-			parm_offset -= hdrlen;
-	}
-
-	if (parm_count == parm_tot && data_count == data_tot) {
-		/*
-		 * This packet has all the trans2 data.
-		 *
-		 * We setup the request so that this will be the common
-		 * case. It may be a server error to not return a
-		 * response that fits.
-		 */
-		VERBOSE("single trans2 response  "
-			"dcnt=%u, pcnt=%u, doff=%u, poff=%u\n",
-			data_count, parm_count,
-			data_offset, parm_offset);
-		req->rq_ldata = data_count;
-		req->rq_lparm = parm_count;
-		req->rq_data = req->rq_buffer + data_offset;
-		req->rq_parm = req->rq_buffer + parm_offset;
-		if (unlikely(parm_offset + parm_count > req->rq_rlen))
-			goto out_bad_parm;
-		if (unlikely(data_offset + data_count > req->rq_rlen))
-			goto out_bad_data;
-		return 0;
-	}
-
-	VERBOSE("multi trans2 response  "
-		"frag=%d, dcnt=%u, pcnt=%u, doff=%u, poff=%u\n",
-		req->rq_fragment,
-		data_count, parm_count,
-		data_offset, parm_offset);
-
-	if (!req->rq_fragment) {
-		int buf_len;
-
-		/* We got the first trans2 fragment */
-		req->rq_fragment = 1;
-		req->rq_total_data = data_tot;
-		req->rq_total_parm = parm_tot;
-		req->rq_ldata = 0;
-		req->rq_lparm = 0;
-
-		buf_len = data_tot + parm_tot;
-		if (buf_len > SMB_MAX_PACKET_SIZE)
-			goto out_too_long;
-
-		req->rq_trans2bufsize = buf_len;
-		req->rq_trans2buffer = kzalloc(buf_len, GFP_NOFS);
-		if (!req->rq_trans2buffer)
-			goto out_no_mem;
-
-		req->rq_parm = req->rq_trans2buffer;
-		req->rq_data = req->rq_trans2buffer + parm_tot;
-	} else if (unlikely(req->rq_total_data < data_tot ||
-			    req->rq_total_parm < parm_tot))
-		goto out_data_grew;
-
-	if (unlikely(parm_disp + parm_count > req->rq_total_parm ||
-		     parm_offset + parm_count > req->rq_rlen))
-		goto out_bad_parm;
-	if (unlikely(data_disp + data_count > req->rq_total_data ||
-		     data_offset + data_count > req->rq_rlen))
-		goto out_bad_data;
-
-	inbuf = req->rq_buffer;
-	memcpy(req->rq_parm + parm_disp, inbuf + parm_offset, parm_count);
-	memcpy(req->rq_data + data_disp, inbuf + data_offset, data_count);
-
-	req->rq_ldata += data_count;
-	req->rq_lparm += parm_count;
-
-	/*
-	 * Check whether we've received all of the data. Note that
-	 * we use the packet totals -- total lengths might shrink!
-	 */
-	if (req->rq_ldata >= data_tot && req->rq_lparm >= parm_tot) {
-		req->rq_ldata = data_tot;
-		req->rq_lparm = parm_tot;
-		return 0;
-	}
-	return 1;
-
-out_too_long:
-	printk(KERN_ERR "smb_trans2: data/param too long, data=%u, parm=%u\n",
-		data_tot, parm_tot);
-	goto out_EIO;
-out_no_mem:
-	printk(KERN_ERR "smb_trans2: couldn't allocate data area of %d bytes\n",
-	       req->rq_trans2bufsize);
-	req->rq_errno = -ENOMEM;
-	goto out;
-out_data_grew:
-	printk(KERN_ERR "smb_trans2: data/params grew!\n");
-	goto out_EIO;
-out_bad_parm:
-	printk(KERN_ERR "smb_trans2: invalid parms, disp=%u, cnt=%u, tot=%u, ofs=%u\n",
-	       parm_disp, parm_count, parm_tot, parm_offset);
-	goto out_EIO;
-out_bad_data:
-	printk(KERN_ERR "smb_trans2: invalid data, disp=%u, cnt=%u, tot=%u, ofs=%u\n",
-	       data_disp, data_count, data_tot, data_offset);
-out_EIO:
-	req->rq_errno = -EIO;
-out:
-	return req->rq_errno;
-}
-
-/*
- * State machine for receiving responses. We handle the fact that we can't
- * read the full response in one try by having states telling us how much we
- * have read.
- *
- * Must be called with the server lock held (only called from smbiod).
- *
- * Return: <0 on error
- */
-int smb_request_recv(struct smb_sb_info *server)
-{
-	struct smb_request *req = NULL;
-	int result = 0;
-
-	if (smb_recv_available(server) <= 0)
-		return 0;
-
-	VERBOSE("state: %d\n", server->rstate);
-	switch (server->rstate) {
-	case SMB_RECV_DROP:
-		result = smb_receive_drop(server);
-		if (result < 0)
-			break;
-		if (server->rstate == SMB_RECV_DROP)
-			break;
-		server->rstate = SMB_RECV_START;
-		/* fallthrough */
-	case SMB_RECV_START:
-		server->smb_read = 0;
-		server->rstate = SMB_RECV_HEADER;
-		/* fallthrough */
-	case SMB_RECV_HEADER:
-		result = smb_receive_header(server);
-		if (result < 0)
-			break;
-		if (server->rstate == SMB_RECV_HEADER)
-			break;
-		if (! (*(server->header + smb_flg) & SMB_FLAGS_REPLY) ) {
-			server->rstate = SMB_RECV_REQUEST;
-			break;
-		}
-		if (server->rstate != SMB_RECV_HCOMPLETE)
-			break;
-		/* fallthrough */
-	case SMB_RECV_HCOMPLETE:
-		req = find_request(server, WVAL(server->header, smb_mid));
-		if (!req)
-			break;
-		smb_init_request(server, req);
-		req->rq_rcls = *(req->rq_header + smb_rcls);
-		req->rq_err  = WVAL(req->rq_header, smb_err);
-		if (server->rstate != SMB_RECV_PARAM)
-			break;
-		/* fallthrough */
-	case SMB_RECV_PARAM:
-		if (!req)
-			req = find_request(server,WVAL(server->header,smb_mid));
-		if (!req)
-			break;
-		result = smb_recv_param(server, req);
-		if (result < 0)
-			break;
-		if (server->rstate != SMB_RECV_DATA)
-			break;
-		/* fallthrough */
-	case SMB_RECV_DATA:
-		if (!req)
-			req = find_request(server,WVAL(server->header,smb_mid));
-		if (!req)
-			break;
-		result = smb_recv_data(server, req);
-		if (result < 0)
-			break;
-		break;
-
-		/* We should never be called with any of these states */
-	case SMB_RECV_END:
-	case SMB_RECV_REQUEST:
-		BUG();
-	}
-
-	if (result < 0) {
-		/* We saw an error */
-		return result;
-	}
-
-	if (server->rstate != SMB_RECV_END)
-		return 0;
-
-	result = 0;
-	if (req->rq_trans2_command && req->rq_rcls == SUCCESS)
-		result = smb_recv_trans2(server, req);
-
-	/*
-	 * Response completely read. Drop any extra bytes sent by the server.
-	 * (Yes, servers sometimes add extra bytes to responses)
-	 */
-	VERBOSE("smb_len: %d   smb_read: %d\n",
-		server->smb_len, server->smb_read);
-	if (server->smb_read < server->smb_len)
-		smb_receive_drop(server);
-
-	server->rstate = SMB_RECV_START;
-
-	if (!result) {
-		list_del_init(&req->rq_queue);
-		req->rq_flags |= SMB_REQ_RECEIVED;
-		smb_rput(req);
-		wake_up_interruptible(&req->rq_wait);
-	}
-	return 0;
-}
diff --git a/drivers/staging/smbfs/request.h b/drivers/staging/smbfs/request.h
deleted file mode 100644
index efb2145..0000000
--- a/drivers/staging/smbfs/request.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#include <linux/list.h>
-#include <linux/types.h>
-#include <linux/uio.h>
-#include <linux/wait.h>
-
-struct smb_request {
-	struct list_head rq_queue;	/* recvq or xmitq for the server */
-
-	atomic_t rq_count;
-
-	wait_queue_head_t rq_wait;
-	int rq_flags;
-	int rq_mid;	/* multiplex ID, set by request.c */
-
-	struct smb_sb_info *rq_server;
-
-	/* header + word count + parameter words + byte count */
-	unsigned char rq_header[SMB_HEADER_LEN + 20*2 + 2];
-
-	int rq_bufsize;
-	unsigned char *rq_buffer;
-
-	/* FIXME: this is not good enough for merging IO requests. */
-	unsigned char *rq_page;
-	int rq_rsize;
-
-	int rq_resp_wct;
-	int rq_resp_bcc;
-
-	int rq_rlen;
-	int rq_bytes_recvd;
-
-	int rq_slen;
-	int rq_bytes_sent;
-
-	int rq_iovlen;
-	struct kvec rq_iov[4];
-
-	int (*rq_setup_read) (struct smb_request *);
-	void (*rq_callback) (struct smb_request *);
-
-	/* ------ trans2 stuff ------ */
-
-	u16 rq_trans2_command;	/* 0 if not a trans2 request */
-	unsigned int rq_ldata;
-	unsigned char *rq_data;
-	unsigned int rq_lparm;
-	unsigned char *rq_parm;
-
-	int rq_fragment;
-	u32 rq_total_data;
-	u32 rq_total_parm;
-	int rq_trans2bufsize;
-	unsigned char *rq_trans2buffer;
-
-	/* ------ response ------ */
-
-	unsigned short rq_rcls;
-	unsigned short rq_err;
-	int rq_errno;
-};
-
-#define SMB_REQ_STATIC		0x0001	/* rq_buffer is static */
-#define SMB_REQ_NORETRY		0x0002	/* request is invalid after retry */
-
-#define SMB_REQ_TRANSMITTED	0x4000	/* all data has been sent */
-#define SMB_REQ_RECEIVED	0x8000	/* reply received, smbiod is done */
-
-#define xSMB_REQ_NOREPLY	0x0004	/* we don't want the reply (if any) */
-#define xSMB_REQ_NORECEIVER	0x0008	/* caller doesn't wait for response */
diff --git a/drivers/staging/smbfs/smb.h b/drivers/staging/smbfs/smb.h
deleted file mode 100644
index 82fefdd..0000000
--- a/drivers/staging/smbfs/smb.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *  smb.h
- *
- *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- */
-
-#ifndef _LINUX_SMB_H
-#define _LINUX_SMB_H
-
-#include <linux/types.h>
-#include <linux/magic.h>
-#ifdef __KERNEL__
-#include <linux/time.h>
-#endif
-
-enum smb_protocol { 
-	SMB_PROTOCOL_NONE, 
-	SMB_PROTOCOL_CORE, 
-	SMB_PROTOCOL_COREPLUS, 
-	SMB_PROTOCOL_LANMAN1, 
-	SMB_PROTOCOL_LANMAN2, 
-	SMB_PROTOCOL_NT1 
-};
-
-enum smb_case_hndl {
-	SMB_CASE_DEFAULT,
-	SMB_CASE_LOWER,
-	SMB_CASE_UPPER
-};
-
-struct smb_dskattr {
-        __u16 total;
-        __u16 allocblocks;
-        __u16 blocksize;
-        __u16 free;
-};
-
-struct smb_conn_opt {
-
-        /* The socket */
-	unsigned int fd;
-
-	enum smb_protocol protocol;
-	enum smb_case_hndl case_handling;
-
-	/* Connection-Options */
-
-	__u32              max_xmit;
-	__u16              server_uid;
-	__u16              tid;
-
-        /* The following are LANMAN 1.0 options */
-        __u16              secmode;
-        __u16              maxmux;
-        __u16              maxvcs;
-        __u16              rawmode;
-        __u32              sesskey;
-
-	/* The following are NT LM 0.12 options */
-	__u32              maxraw;
-	__u32              capabilities;
-	__s16              serverzone;
-};
-
-#ifdef __KERNEL__
-
-#define SMB_NLS_MAXNAMELEN 20
-struct smb_nls_codepage {
-	char local_name[SMB_NLS_MAXNAMELEN];
-	char remote_name[SMB_NLS_MAXNAMELEN];
-};
-
-
-#define SMB_MAXNAMELEN 255
-#define SMB_MAXPATHLEN 1024
-
-/*
- * Contains all relevant data on a SMB networked file.
- */
-struct smb_fattr {
-	__u16 attr;
-
-	unsigned long	f_ino;
-	umode_t		f_mode;
-	nlink_t		f_nlink;
-	uid_t		f_uid;
-	gid_t		f_gid;
-	dev_t		f_rdev;
-	loff_t		f_size;
-	struct timespec	f_atime;
-	struct timespec f_mtime;
-	struct timespec f_ctime;
-	unsigned long	f_blocks;
-	int		f_unix;
-};
-
-enum smb_conn_state {
-	CONN_VALID,		/* everything's fine */
-	CONN_INVALID,		/* Something went wrong, but did not
-				   try to reconnect yet. */
-	CONN_RETRIED,		/* Tried a reconnection, but was refused */
-	CONN_RETRYING		/* Currently trying to reconnect */
-};
-
-#define SMB_HEADER_LEN   37     /* includes everything up to, but not
-                                 * including smb_bcc */
-
-#define SMB_INITIAL_PACKET_SIZE		4000
-#define SMB_MAX_PACKET_SIZE		32768
-
-/* reserve this much space for trans2 parameters. Shouldn't have to be more
-   than 10 or so, but OS/2 seems happier like this. */
-#define SMB_TRANS2_MAX_PARAM 64
-
-#endif
-#endif
diff --git a/drivers/staging/smbfs/smb_debug.h b/drivers/staging/smbfs/smb_debug.h
deleted file mode 100644
index fc4b1a5..0000000
--- a/drivers/staging/smbfs/smb_debug.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Defines some debug macros for smbfs.
- */
-
-/* This makes a dentry parent/child name pair. Useful for debugging printk's */
-#define DENTRY_PATH(dentry) \
-	(dentry)->d_parent->d_name.name,(dentry)->d_name.name
-
-/*
- * safety checks that should never happen ???
- * these are normally enabled.
- */
-#ifdef SMBFS_PARANOIA
-# define PARANOIA(f, a...) printk(KERN_NOTICE "%s: " f, __func__ , ## a)
-#else
-# define PARANOIA(f, a...) do { ; } while(0)
-#endif
-
-/* lots of debug messages */
-#ifdef SMBFS_DEBUG_VERBOSE
-# define VERBOSE(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
-#else
-# define VERBOSE(f, a...) do { ; } while(0)
-#endif
-
-/*
- * "normal" debug messages, but not with a normal DEBUG define ... way
- * too common name.
- */
-#ifdef SMBFS_DEBUG
-#define DEBUG1(f, a...) printk(KERN_DEBUG "%s: " f, __func__ , ## a)
-#else
-#define DEBUG1(f, a...) do { ; } while(0)
-#endif
diff --git a/drivers/staging/smbfs/smb_fs.h b/drivers/staging/smbfs/smb_fs.h
deleted file mode 100644
index 20a05c1..0000000
--- a/drivers/staging/smbfs/smb_fs.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- *  smb_fs.h
- *
- *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- */
-
-#ifndef _LINUX_SMB_FS_H
-#define _LINUX_SMB_FS_H
-
-#include "smb.h"
-
-/*
- * ioctl commands
- */
-#define	SMB_IOC_GETMOUNTUID		_IOR('u', 1, __kernel_old_uid_t)
-#define SMB_IOC_NEWCONN                 _IOW('u', 2, struct smb_conn_opt)
-
-/* __kernel_uid_t can never change, so we have to use __kernel_uid32_t */
-#define	SMB_IOC_GETMOUNTUID32		_IOR('u', 3, __kernel_uid32_t)
-
-
-#ifdef __KERNEL__
-#include "smb_fs_i.h"
-#include "smb_fs_sb.h"
-#include "smb_mount.h"
-
-#include <linux/fs.h>
-#include <linux/pagemap.h>
-#include <linux/vmalloc.h>
-#include <linux/jiffies.h>
-#include <asm/unaligned.h>
-
-static inline struct smb_sb_info *SMB_SB(struct super_block *sb)
-{
-	return sb->s_fs_info;
-}
-
-static inline struct smb_inode_info *SMB_I(struct inode *inode)
-{
-	return container_of(inode, struct smb_inode_info, vfs_inode);
-}
-
-/* macro names are short for word, double-word, long value (?) */
-#define WVAL(buf, pos) (get_unaligned_le16((u8 *)(buf) + (pos)))
-#define DVAL(buf, pos) (get_unaligned_le32((u8 *)(buf) + (pos)))
-#define LVAL(buf, pos) (get_unaligned_le64((u8 *)(buf) + (pos)))
-
-#define WSET(buf, pos, val) put_unaligned_le16((val), (u8 *)(buf) + (pos))
-#define DSET(buf, pos, val) put_unaligned_le32((val), (u8 *)(buf) + (pos))
-#define LSET(buf, pos, val) put_unaligned_le64((val), (u8 *)(buf) + (pos))
-
-/* where to find the base of the SMB packet proper */
-#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
-
-/*
- * Flags for the in-memory inode
- */
-#define SMB_F_LOCALWRITE	0x02	/* file modified locally */
-
-
-/* NT1 protocol capability bits */
-#define SMB_CAP_RAW_MODE         0x00000001
-#define SMB_CAP_MPX_MODE         0x00000002
-#define SMB_CAP_UNICODE          0x00000004
-#define SMB_CAP_LARGE_FILES      0x00000008
-#define SMB_CAP_NT_SMBS          0x00000010
-#define SMB_CAP_RPC_REMOTE_APIS  0x00000020
-#define SMB_CAP_STATUS32         0x00000040
-#define SMB_CAP_LEVEL_II_OPLOCKS 0x00000080
-#define SMB_CAP_LOCK_AND_READ    0x00000100
-#define SMB_CAP_NT_FIND          0x00000200
-#define SMB_CAP_DFS              0x00001000
-#define SMB_CAP_LARGE_READX      0x00004000
-#define SMB_CAP_LARGE_WRITEX     0x00008000
-#define SMB_CAP_UNIX             0x00800000	/* unofficial ... */
-
-
-/*
- * This is the time we allow an inode, dentry or dir cache to live. It is bad
- * for performance to have shorter ttl on an inode than on the cache. It can
- * cause refresh on each inode for a dir listing ... one-by-one
- */
-#define SMB_MAX_AGE(server) (((server)->mnt->ttl * HZ) / 1000)
-
-static inline void
-smb_age_dentry(struct smb_sb_info *server, struct dentry *dentry)
-{
-	dentry->d_time = jiffies - SMB_MAX_AGE(server);
-}
-
-struct smb_cache_head {
-	time_t		mtime;	/* unused */
-	unsigned long	time;	/* cache age */
-	unsigned long	end;	/* last valid fpos in cache */
-	int		eof;
-};
-
-#define SMB_DIRCACHE_SIZE	((int)(PAGE_CACHE_SIZE/sizeof(struct dentry *)))
-union smb_dir_cache {
-	struct smb_cache_head   head;
-	struct dentry           *dentry[SMB_DIRCACHE_SIZE];
-};
-
-#define SMB_FIRSTCACHE_SIZE	((int)((SMB_DIRCACHE_SIZE * \
-	sizeof(struct dentry *) - sizeof(struct smb_cache_head)) / \
-	sizeof(struct dentry *)))
-
-#define SMB_DIRCACHE_START      (SMB_DIRCACHE_SIZE - SMB_FIRSTCACHE_SIZE)
-
-struct smb_cache_control {
-	struct  smb_cache_head		head;
-	struct  page			*page;
-	union   smb_dir_cache		*cache;
-	unsigned long			fpos, ofs;
-	int				filled, valid, idx;
-};
-
-#define SMB_OPS_NUM_STATIC	5
-struct smb_ops {
-	int (*read)(struct inode *inode, loff_t offset, int count,
-		    char *data);
-	int (*write)(struct inode *inode, loff_t offset, int count, const
-		     char *data);
-	int (*readdir)(struct file *filp, void *dirent, filldir_t filldir,
-		       struct smb_cache_control *ctl);
-
-	int (*getattr)(struct smb_sb_info *server, struct dentry *dir,
-		       struct smb_fattr *fattr);
-	/* int (*setattr)(...); */      /* setattr is really icky! */
-
-	int (*truncate)(struct inode *inode, loff_t length);
-
-
-	/* --- --- --- end of "static" entries --- --- --- */
-
-	int (*convert)(unsigned char *output, int olen,
-		       const unsigned char *input, int ilen,
-		       struct nls_table *nls_from,
-		       struct nls_table *nls_to);
-};
-
-static inline int
-smb_is_open(struct inode *i)
-{
-	return (SMB_I(i)->open == server_from_inode(i)->generation);
-}
-
-extern void smb_install_null_ops(struct smb_ops *);
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_SMB_FS_H */
diff --git a/drivers/staging/smbfs/smb_fs_i.h b/drivers/staging/smbfs/smb_fs_i.h
deleted file mode 100644
index 8ccf4ec..0000000
--- a/drivers/staging/smbfs/smb_fs_i.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  smb_fs_i.h
- *
- *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- */
-
-#ifndef _LINUX_SMB_FS_I
-#define _LINUX_SMB_FS_I
-
-#include <linux/types.h>
-#include <linux/fs.h>
-
-/*
- * smb fs inode data (in memory only)
- */
-struct smb_inode_info {
-
-	/*
-	 * file handles are local to a connection. A file is open if
-	 * (open == generation).
-	 */
-        unsigned int open;	/* open generation */
-	__u16 fileid;		/* What id to handle a file with? */
-	__u16 attr;		/* Attribute fields, DOS value */
-
-	__u16 access;		/* Access mode */
-	__u16 flags;
-	unsigned long oldmtime;	/* last time refreshed */
-	unsigned long closed;	/* timestamp when closed */
-	unsigned openers;	/* number of fileid users */
-
-	struct inode vfs_inode;	/* must be at the end */
-};
-
-#endif
diff --git a/drivers/staging/smbfs/smb_fs_sb.h b/drivers/staging/smbfs/smb_fs_sb.h
deleted file mode 100644
index ca058af..0000000
--- a/drivers/staging/smbfs/smb_fs_sb.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  smb_fs_sb.h
- *
- *  Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- */
-
-#ifndef _SMB_FS_SB
-#define _SMB_FS_SB
-
-#include <linux/types.h>
-#include <linux/backing-dev.h>
-#include "smb.h"
-
-/*
- * Upper limit on the total number of active smb_request structs.
- */
-#define MAX_REQUEST_HARD       256
-
-enum smb_receive_state {
-	SMB_RECV_START,		/* No data read, looking for length + sig */
-	SMB_RECV_HEADER,	/* Reading the header data */
-	SMB_RECV_HCOMPLETE,	/* Done with the header */
-	SMB_RECV_PARAM,		/* Reading parameter words */
-	SMB_RECV_DATA,		/* Reading data bytes */
-	SMB_RECV_END,		/* End of request */
-	SMB_RECV_DROP,		/* Dropping this SMB */
-	SMB_RECV_REQUEST,	/* Received a request and not a reply */
-};
-
-/* structure access macros */
-#define server_from_inode(inode) SMB_SB((inode)->i_sb)
-#define server_from_dentry(dentry) SMB_SB((dentry)->d_sb)
-#define SB_of(server) ((server)->super_block)
-
-struct smb_sb_info {
-	/* List of all smbfs superblocks */
-	struct list_head entry;
-
-        enum smb_conn_state state;
-	struct file * sock_file;
-	int conn_error;
-	enum smb_receive_state rstate;
-
-	atomic_t nr_requests;
-	struct list_head xmitq;
-	struct list_head recvq;
-	u16 mid;
-
-        struct smb_mount_data_kernel *mnt;
-
-	/* Connections are counted. Each time a new socket arrives,
-	 * generation is incremented.
-	 */
-	unsigned int generation;
-	struct pid *conn_pid;
-	struct smb_conn_opt opt;
-	wait_queue_head_t conn_wq;
-	int conn_complete;
-	struct semaphore sem;
-
-	unsigned char      header[SMB_HEADER_LEN + 20*2 + 2];
-	u32                header_len;
-	u32                smb_len;
-	u32                smb_read;
-
-        /* We use our own data_ready callback, but need the original one */
-        void *data_ready;
-
-	/* nls pointers for codepage conversions */
-	struct nls_table *remote_nls;
-	struct nls_table *local_nls;
-
-	struct smb_ops *ops;
-
-	struct super_block *super_block;
-
-	struct backing_dev_info bdi;
-};
-
-static inline int
-smb_lock_server_interruptible(struct smb_sb_info *server)
-{
-	return down_interruptible(&(server->sem));
-}
-
-static inline void
-smb_lock_server(struct smb_sb_info *server)
-{
-	down(&(server->sem));
-}
-
-static inline void
-smb_unlock_server(struct smb_sb_info *server)
-{
-	up(&(server->sem));
-}
-
-#endif
diff --git a/drivers/staging/smbfs/smb_mount.h b/drivers/staging/smbfs/smb_mount.h
deleted file mode 100644
index d10f00c..0000000
--- a/drivers/staging/smbfs/smb_mount.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  smb_mount.h
- *
- *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- */
-
-#ifndef _LINUX_SMB_MOUNT_H
-#define _LINUX_SMB_MOUNT_H
-
-#include <linux/types.h>
-
-#define SMB_MOUNT_VERSION	6
-
-struct smb_mount_data {
-	int version;
-	__kernel_uid_t mounted_uid; /* Who may umount() this filesystem? */
-	__kernel_uid_t uid;
-	__kernel_gid_t gid;
-	__kernel_mode_t file_mode;
-	__kernel_mode_t dir_mode;
-};
-
-
-#ifdef __KERNEL__
-
-/* "vers" in big-endian */
-#define SMB_MOUNT_ASCII 0x76657273
-
-#define SMB_MOUNT_OLDVERSION	6
-#undef SMB_MOUNT_VERSION
-#define SMB_MOUNT_VERSION	7
-
-/* flags */
-#define SMB_MOUNT_WIN95		0x0001	/* Win 95 server */
-#define SMB_MOUNT_OLDATTR	0x0002	/* Use core getattr (Win 95 speedup) */
-#define SMB_MOUNT_DIRATTR	0x0004	/* Use find_first for getattr */
-#define SMB_MOUNT_CASE		0x0008	/* Be case sensitive */
-#define SMB_MOUNT_UNICODE	0x0010	/* Server talks unicode */
-#define SMB_MOUNT_UID		0x0020  /* Use user specified uid */
-#define SMB_MOUNT_GID		0x0040  /* Use user specified gid */
-#define SMB_MOUNT_FMODE		0x0080  /* Use user specified file mode */
-#define SMB_MOUNT_DMODE		0x0100  /* Use user specified dir mode */
-
-struct smb_mount_data_kernel {
-	int version;
-
-	uid_t mounted_uid;	/* Who may umount() this filesystem? */
-	uid_t uid;
-	gid_t gid;
-	mode_t file_mode;
-	mode_t dir_mode;
-
-	u32 flags;
-
-        /* maximum age in jiffies (inode, dentry and dircache) */
-	int ttl;
-
-	struct smb_nls_codepage codepage;
-};
-
-#endif
-
-#endif
diff --git a/drivers/staging/smbfs/smbfs.txt b/drivers/staging/smbfs/smbfs.txt
deleted file mode 100644
index 194fb0d..0000000
--- a/drivers/staging/smbfs/smbfs.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Smbfs is a filesystem that implements the SMB protocol, which is the
-protocol used by Windows for Workgroups, Windows 95 and Windows NT.
-Smbfs was inspired by Samba, the program written by Andrew Tridgell
-that turns any Unix host into a file server for DOS or Windows clients.
-
-Smbfs is a SMB client, but uses parts of samba for its operation. For
-more info on samba, including documentation, please go to
-http://www.samba.org/ and then on to your nearest mirror.
diff --git a/drivers/staging/smbfs/smbiod.c b/drivers/staging/smbfs/smbiod.c
deleted file mode 100644
index ec99892..0000000
--- a/drivers/staging/smbfs/smbiod.c
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- *  smbiod.c
- *
- *  Copyright (C) 2000, Charles Loep / Corel Corp.
- *  Copyright (C) 2001, Urban Widmark
- */
-
-
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/dcache.h>
-#include <linux/module.h>
-#include <linux/net.h>
-#include <linux/kthread.h>
-#include <net/ip.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include "smb_fs.h"
-#include "smbno.h"
-#include "smb_mount.h"
-#include "smb_debug.h"
-#include "request.h"
-#include "proto.h"
-
-enum smbiod_state {
-	SMBIOD_DEAD,
-	SMBIOD_STARTING,
-	SMBIOD_RUNNING,
-};
-
-static enum smbiod_state smbiod_state = SMBIOD_DEAD;
-static struct task_struct *smbiod_thread;
-static DECLARE_WAIT_QUEUE_HEAD(smbiod_wait);
-static LIST_HEAD(smb_servers);
-static DEFINE_SPINLOCK(servers_lock);
-
-#define SMBIOD_DATA_READY	(1<<0)
-static unsigned long smbiod_flags;
-
-static int smbiod(void *);
-static int smbiod_start(void);
-
-/*
- * called when there's work for us to do
- */
-void smbiod_wake_up(void)
-{
-	if (smbiod_state == SMBIOD_DEAD)
-		return;
-	set_bit(SMBIOD_DATA_READY, &smbiod_flags);
-	wake_up_interruptible(&smbiod_wait);
-}
-
-/*
- * start smbiod if none is running
- */
-static int smbiod_start(void)
-{
-	struct task_struct *tsk;
-	int err = 0;
-
-	if (smbiod_state != SMBIOD_DEAD)
-		return 0;
-	smbiod_state = SMBIOD_STARTING;
-	__module_get(THIS_MODULE);
-	spin_unlock(&servers_lock);
-	tsk = kthread_run(smbiod, NULL, "smbiod");
-	if (IS_ERR(tsk)) {
-		err = PTR_ERR(tsk);
-		module_put(THIS_MODULE);
-	}
-
-	spin_lock(&servers_lock);
-	if (err < 0) {
-		smbiod_state = SMBIOD_DEAD;
-		smbiod_thread = NULL;
-	} else {
-		smbiod_state = SMBIOD_RUNNING;
-		smbiod_thread = tsk;
-	}
-	return err;
-}
-
-/*
- * register a server & start smbiod if necessary
- */
-int smbiod_register_server(struct smb_sb_info *server)
-{
-	int ret;
-	spin_lock(&servers_lock);
-	list_add(&server->entry, &smb_servers);
-	VERBOSE("%p\n", server);
-	ret = smbiod_start();
-	spin_unlock(&servers_lock);
-	return ret;
-}
-
-/*
- * Unregister a server
- * Must be called with the server lock held.
- */
-void smbiod_unregister_server(struct smb_sb_info *server)
-{
-	spin_lock(&servers_lock);
-	list_del_init(&server->entry);
-	VERBOSE("%p\n", server);
-	spin_unlock(&servers_lock);
-
-	smbiod_wake_up();
-	smbiod_flush(server);
-}
-
-void smbiod_flush(struct smb_sb_info *server)
-{
-	struct list_head *tmp, *n;
-	struct smb_request *req;
-
-	list_for_each_safe(tmp, n, &server->xmitq) {
-		req = list_entry(tmp, struct smb_request, rq_queue);
-		req->rq_errno = -EIO;
-		list_del_init(&req->rq_queue);
-		smb_rput(req);
-		wake_up_interruptible(&req->rq_wait);
-	}
-	list_for_each_safe(tmp, n, &server->recvq) {
-		req = list_entry(tmp, struct smb_request, rq_queue);
-		req->rq_errno = -EIO;
-		list_del_init(&req->rq_queue);
-		smb_rput(req);
-		wake_up_interruptible(&req->rq_wait);
-	}
-}
-
-/*
- * Wake up smbmount and make it reconnect to the server.
- * This must be called with the server locked.
- *
- * FIXME: add smbconnect version to this
- */
-int smbiod_retry(struct smb_sb_info *server)
-{
-	struct list_head *head;
-	struct smb_request *req;
-	struct pid *pid = get_pid(server->conn_pid);
-	int result = 0;
-
-	VERBOSE("state: %d\n", server->state);
-	if (server->state == CONN_VALID || server->state == CONN_RETRYING)
-		goto out;
-
-	smb_invalidate_inodes(server);
-
-	/*
-	 * Some requests are meaningless after a retry, so we abort them.
-	 * One example are all requests using 'fileid' since the files are
-	 * closed on retry.
-	 */
-	head = server->xmitq.next;
-	while (head != &server->xmitq) {
-		req = list_entry(head, struct smb_request, rq_queue);
-		head = head->next;
-
-		req->rq_bytes_sent = 0;
-		if (req->rq_flags & SMB_REQ_NORETRY) {
-			VERBOSE("aborting request %p on xmitq\n", req);
-			req->rq_errno = -EIO;
-			list_del_init(&req->rq_queue);
-			smb_rput(req);
-			wake_up_interruptible(&req->rq_wait);
-		}
-	}
-
-	/*
-	 * FIXME: test the code for retrying request we already sent
-	 */
-	head = server->recvq.next;
-	while (head != &server->recvq) {
-		req = list_entry(head, struct smb_request, rq_queue);
-		head = head->next;
-#if 0
-		if (req->rq_flags & SMB_REQ_RETRY) {
-			/* must move the request to the xmitq */
-			VERBOSE("retrying request %p on recvq\n", req);
-			list_move(&req->rq_queue, &server->xmitq);
-			continue;
-		}
-#endif
-
-		VERBOSE("aborting request %p on recvq\n", req);
-		/* req->rq_rcls = ???; */ /* FIXME: set smb error code too? */
-		req->rq_errno = -EIO;
-		list_del_init(&req->rq_queue);
-		smb_rput(req);
-		wake_up_interruptible(&req->rq_wait);
-	}
-
-	smb_close_socket(server);
-
-	if (!pid) {
-		/* FIXME: this is fatal, umount? */
-		printk(KERN_ERR "smb_retry: no connection process\n");
-		server->state = CONN_RETRIED;
-		goto out;
-	}
-
-	/*
-	 * Change state so that only one retry per server will be started.
-	 */
-	server->state = CONN_RETRYING;
-
-	/*
-	 * Note: use the "priv" flag, as a user process may need to reconnect.
-	 */
-	result = kill_pid(pid, SIGUSR1, 1);
-	if (result) {
-		/* FIXME: this is most likely fatal, umount? */
-		printk(KERN_ERR "smb_retry: signal failed [%d]\n", result);
-		goto out;
-	}
-	VERBOSE("signalled pid %d\n", pid_nr(pid));
-
-	/* FIXME: The retried requests should perhaps get a "time boost". */
-
-out:
-	put_pid(pid);
-	return result;
-}
-
-/*
- * Currently handles lockingX packets.
- */
-static void smbiod_handle_request(struct smb_sb_info *server)
-{
-	PARANOIA("smbiod got a request ... and we don't implement oplocks!\n");
-	server->rstate = SMB_RECV_DROP;
-}
-
-/*
- * Do some IO for one server.
- */
-static void smbiod_doio(struct smb_sb_info *server)
-{
-	int result;
-	int maxwork = 7;
-
-	if (server->state != CONN_VALID)
-		goto out;
-
-	do {
-		result = smb_request_recv(server);
-		if (result < 0) {
-			server->state = CONN_INVALID;
-			smbiod_retry(server);
-			goto out;	/* reconnecting is slow */
-		} else if (server->rstate == SMB_RECV_REQUEST)
-			smbiod_handle_request(server);
-	} while (result > 0 && maxwork-- > 0);
-
-	/*
-	 * If there is more to read then we want to be sure to wake up again.
-	 */
-	if (server->state != CONN_VALID)
-		goto out;
-	if (smb_recv_available(server) > 0)
-		set_bit(SMBIOD_DATA_READY, &smbiod_flags);
-
-	do {
-		result = smb_request_send_server(server);
-		if (result < 0) {
-			server->state = CONN_INVALID;
-			smbiod_retry(server);
-			goto out;	/* reconnecting is slow */
-		}
-	} while (result > 0);
-
-	/*
-	 * If the last request was not sent out we want to wake up again.
-	 */
-	if (!list_empty(&server->xmitq))
-		set_bit(SMBIOD_DATA_READY, &smbiod_flags);
-
-out:
-	return;
-}
-
-/*
- * smbiod kernel thread
- */
-static int smbiod(void *unused)
-{
-	VERBOSE("SMB Kernel thread starting (%d) ...\n", current->pid);
-
-	for (;;) {
-		struct smb_sb_info *server;
-		struct list_head *pos, *n;
-
-		/* FIXME: Use poll? */
-		wait_event_interruptible(smbiod_wait,
-			 test_bit(SMBIOD_DATA_READY, &smbiod_flags));
-		if (signal_pending(current)) {
-			spin_lock(&servers_lock);
-			smbiod_state = SMBIOD_DEAD;
-			spin_unlock(&servers_lock);
-			break;
-		}
-
-		clear_bit(SMBIOD_DATA_READY, &smbiod_flags);
-
-		spin_lock(&servers_lock);
-		if (list_empty(&smb_servers)) {
-			smbiod_state = SMBIOD_DEAD;
-			spin_unlock(&servers_lock);
-			break;
-		}
-
-		list_for_each_safe(pos, n, &smb_servers) {
-			server = list_entry(pos, struct smb_sb_info, entry);
-			VERBOSE("checking server %p\n", server);
-
-			if (server->state == CONN_VALID) {
-				spin_unlock(&servers_lock);
-
-				smb_lock_server(server);
-				smbiod_doio(server);
-				smb_unlock_server(server);
-
-				spin_lock(&servers_lock);
-			}
-		}
-		spin_unlock(&servers_lock);
-	}
-
-	VERBOSE("SMB Kernel thread exiting (%d) ...\n", current->pid);
-	module_put_and_exit(0);
-}
diff --git a/drivers/staging/smbfs/smbno.h b/drivers/staging/smbfs/smbno.h
deleted file mode 100644
index f99e02d..0000000
--- a/drivers/staging/smbfs/smbno.h
+++ /dev/null
@@ -1,363 +0,0 @@
-#ifndef _SMBNO_H_
-#define _SMBNO_H_
-
-/* these define the attribute byte as seen by DOS */
-#define aRONLY	(1L<<0)
-#define aHIDDEN	(1L<<1)
-#define aSYSTEM	(1L<<2)
-#define aVOLID	(1L<<3)
-#define aDIR	(1L<<4)
-#define aARCH	(1L<<5)
-
-/* error classes */
-#define SUCCESS 0  /* The request was successful. */
-#define ERRDOS 0x01 /*  Error is from the core DOS operating system set. */
-#define ERRSRV 0x02 /* Error is generated by the server network file manager.*/
-#define ERRHRD 0x03  /* Error is an hardware error. */
-#define ERRCMD 0xFF  /* Command was not in the "SMB" format. */
-
-/* SMB X/Open error codes for the ERRdos error class */
-
-#define ERRbadfunc 1            /* Invalid function (or system call) */
-#define ERRbadfile 2            /* File not found (pathname error) */
-#define ERRbadpath 3            /* Directory not found */
-#define ERRnofids 4             /* Too many open files */
-#define ERRnoaccess 5           /* Access denied */
-#define ERRbadfid 6             /* Invalid fid */
-#define ERRbadmcb 7             /* Memory control blocks destroyed */
-#define ERRnomem 8              /* Out of memory */
-#define ERRbadmem 9             /* Invalid memory block address */
-#define ERRbadenv 10            /* Invalid environment */
-#define ERRbadformat 11         /* Invalid format */
-#define ERRbadaccess 12         /* Invalid open mode */
-#define ERRbaddata 13           /* Invalid data (only from ioctl call) */
-#define ERRres 14               /* reserved */
-#define ERRbaddrive 15          /* Invalid drive */
-#define ERRremcd 16             /* Attempt to delete current directory */
-#define ERRdiffdevice 17        /* rename/move across different filesystems */
-#define ERRnofiles 18           /* no more files found in file search */
-#define ERRbadshare 32          /* Share mode on file conflict with open mode */
-#define ERRlock 33              /* Lock request conflicts with existing lock */
-#define ERRfilexists 80         /* File in operation already exists */
-#define ERRbadpipe 230          /* Named pipe invalid */
-#define ERRpipebusy 231         /* All instances of pipe are busy */
-#define ERRpipeclosing 232      /* named pipe close in progress */
-#define ERRnotconnected 233     /* No process on other end of named pipe */
-#define ERRmoredata 234         /* More data to be returned */
-
-#define ERROR_INVALID_PARAMETER	 87
-#define ERROR_DISK_FULL		112
-#define ERROR_INVALID_NAME	123
-#define ERROR_DIR_NOT_EMPTY	145
-#define ERROR_NOT_LOCKED	158
-#define ERROR_ALREADY_EXISTS	183  /* see also 80 ? */
-#define ERROR_EAS_DIDNT_FIT	275 /* Extended attributes didn't fit */
-#define ERROR_EAS_NOT_SUPPORTED	282 /* Extended attributes not supported */
-
-/* Error codes for the ERRSRV class */
-
-#define ERRerror 1              /* Non specific error code */
-#define ERRbadpw 2              /* Bad password */
-#define ERRbadtype 3            /* reserved */
-#define ERRaccess 4          /* No permissions to do the requested operation */
-#define ERRinvnid 5             /* tid invalid */
-#define ERRinvnetname 6         /* Invalid servername */
-#define ERRinvdevice 7          /* Invalid device */
-#define ERRqfull 49             /* Print queue full */
-#define ERRqtoobig 50           /* Queued item too big */
-#define ERRinvpfid 52           /* Invalid print file in smb_fid */
-#define ERRsmbcmd 64            /* Unrecognised command */
-#define ERRsrverror 65          /* smb server internal error */
-#define ERRfilespecs 67         /* fid and pathname invalid combination */
-#define ERRbadlink 68           /* reserved */
-#define ERRbadpermits 69        /* Access specified for a file is not valid */
-#define ERRbadpid 70            /* reserved */
-#define ERRsetattrmode 71       /* attribute mode invalid */
-#define ERRpaused 81            /* Message server paused */
-#define ERRmsgoff 82            /* Not receiving messages */
-#define ERRnoroom 83            /* No room for message */
-#define ERRrmuns 87             /* too many remote usernames */
-#define ERRtimeout 88           /* operation timed out */
-#define ERRnoresource  89   /* No resources currently available for request. */
-#define ERRtoomanyuids 90       /* too many userids */
-#define ERRbaduid 91            /* bad userid */
-#define ERRuseMPX 250    /* temporarily unable to use raw mode, use MPX mode */
-#define ERRuseSTD 251    /* temporarily unable to use raw mode, use std.mode */
-#define ERRcontMPX 252          /* resume MPX mode */
-#define ERRbadPW                /* reserved */
-#define ERRnosupport 0xFFFF
-
-/* Error codes for the ERRHRD class */
-
-#define ERRnowrite 19           /* read only media */
-#define ERRbadunit 20           /* Unknown device */
-#define ERRnotready 21          /* Drive not ready */
-#define ERRbadcmd 22            /* Unknown command */
-#define ERRdata 23              /* Data (CRC) error */
-#define ERRbadreq 24            /* Bad request structure length */
-#define ERRseek 25
-#define ERRbadmedia 26
-#define ERRbadsector 27
-#define ERRnopaper 28
-#define ERRwrite 29             /* write fault */
-#define ERRread 30              /* read fault */
-#define ERRgeneral 31           /* General hardware failure */
-#define ERRwrongdisk 34
-#define ERRFCBunavail 35
-#define ERRsharebufexc 36       /* share buffer exceeded */
-#define ERRdiskfull 39
-
-/*
- * Access modes when opening a file
- */
-#define SMB_ACCMASK	0x0003
-#define SMB_O_RDONLY	0x0000
-#define SMB_O_WRONLY	0x0001
-#define SMB_O_RDWR	0x0002
-
-/* offsets into message for common items */
-#define smb_com 8
-#define smb_rcls 9
-#define smb_reh 10
-#define smb_err 11
-#define smb_flg 13
-#define smb_flg2 14
-#define smb_reb 13
-#define smb_tid 28
-#define smb_pid 30
-#define smb_uid 32
-#define smb_mid 34
-#define smb_wct 36
-#define smb_vwv 37
-#define smb_vwv0 37
-#define smb_vwv1 39
-#define smb_vwv2 41
-#define smb_vwv3 43
-#define smb_vwv4 45
-#define smb_vwv5 47
-#define smb_vwv6 49
-#define smb_vwv7 51
-#define smb_vwv8 53
-#define smb_vwv9 55
-#define smb_vwv10 57
-#define smb_vwv11 59
-#define smb_vwv12 61
-#define smb_vwv13 63
-#define smb_vwv14 65
-
-/* these are the trans2 sub fields for primary requests */
-#define smb_tpscnt smb_vwv0
-#define smb_tdscnt smb_vwv1
-#define smb_mprcnt smb_vwv2
-#define smb_mdrcnt smb_vwv3
-#define smb_msrcnt smb_vwv4
-#define smb_flags smb_vwv5
-#define smb_timeout smb_vwv6
-#define smb_pscnt smb_vwv9
-#define smb_psoff smb_vwv10
-#define smb_dscnt smb_vwv11
-#define smb_dsoff smb_vwv12
-#define smb_suwcnt smb_vwv13
-#define smb_setup smb_vwv14
-#define smb_setup0 smb_setup
-#define smb_setup1 (smb_setup+2)
-#define smb_setup2 (smb_setup+4)
-
-/* these are for the secondary requests */
-#define smb_spscnt smb_vwv2
-#define smb_spsoff smb_vwv3
-#define smb_spsdisp smb_vwv4
-#define smb_sdscnt smb_vwv5
-#define smb_sdsoff smb_vwv6
-#define smb_sdsdisp smb_vwv7
-#define smb_sfid smb_vwv8
-
-/* and these for responses */
-#define smb_tprcnt smb_vwv0
-#define smb_tdrcnt smb_vwv1
-#define smb_prcnt smb_vwv3
-#define smb_proff smb_vwv4
-#define smb_prdisp smb_vwv5
-#define smb_drcnt smb_vwv6
-#define smb_droff smb_vwv7
-#define smb_drdisp smb_vwv8
-
-/* the complete */
-#define SMBmkdir      0x00   /* create directory */
-#define SMBrmdir      0x01   /* delete directory */
-#define SMBopen       0x02   /* open file */
-#define SMBcreate     0x03   /* create file */
-#define SMBclose      0x04   /* close file */
-#define SMBflush      0x05   /* flush file */
-#define SMBunlink     0x06   /* delete file */
-#define SMBmv         0x07   /* rename file */
-#define SMBgetatr     0x08   /* get file attributes */
-#define SMBsetatr     0x09   /* set file attributes */
-#define SMBread       0x0A   /* read from file */
-#define SMBwrite      0x0B   /* write to file */
-#define SMBlock       0x0C   /* lock byte range */
-#define SMBunlock     0x0D   /* unlock byte range */
-#define SMBctemp      0x0E   /* create temporary file */
-#define SMBmknew      0x0F   /* make new file */
-#define SMBchkpth     0x10   /* check directory path */
-#define SMBexit       0x11   /* process exit */
-#define SMBlseek      0x12   /* seek */
-#define SMBtcon       0x70   /* tree connect */
-#define SMBtconX      0x75   /* tree connect and X*/
-#define SMBtdis       0x71   /* tree disconnect */
-#define SMBnegprot    0x72   /* negotiate protocol */
-#define SMBdskattr    0x80   /* get disk attributes */
-#define SMBsearch     0x81   /* search directory */
-#define SMBsplopen    0xC0   /* open print spool file */
-#define SMBsplwr      0xC1   /* write to print spool file */
-#define SMBsplclose   0xC2   /* close print spool file */
-#define SMBsplretq    0xC3   /* return print queue */
-#define SMBsends      0xD0   /* send single block message */
-#define SMBsendb      0xD1   /* send broadcast message */
-#define SMBfwdname    0xD2   /* forward user name */
-#define SMBcancelf    0xD3   /* cancel forward */
-#define SMBgetmac     0xD4   /* get machine name */
-#define SMBsendstrt   0xD5   /* send start of multi-block message */
-#define SMBsendend    0xD6   /* send end of multi-block message */
-#define SMBsendtxt    0xD7   /* send text of multi-block message */
-
-/* Core+ protocol */
-#define SMBlockread	  0x13   /* Lock a range and read */
-#define SMBwriteunlock 0x14 /* Unlock a range then write */
-#define SMBreadbraw   0x1a  /* read a block of data with no smb header */
-#define SMBwritebraw  0x1d  /* write a block of data with no smb header */
-#define SMBwritec     0x20  /* secondary write request */
-#define SMBwriteclose 0x2c  /* write a file then close it */
-
-/* dos extended protocol */
-#define SMBreadBraw      0x1A   /* read block raw */
-#define SMBreadBmpx      0x1B   /* read block multiplexed */
-#define SMBreadBs        0x1C   /* read block (secondary response) */
-#define SMBwriteBraw     0x1D   /* write block raw */
-#define SMBwriteBmpx     0x1E   /* write block multiplexed */
-#define SMBwriteBs       0x1F   /* write block (secondary request) */
-#define SMBwriteC        0x20   /* write complete response */
-#define SMBsetattrE      0x22   /* set file attributes expanded */
-#define SMBgetattrE      0x23   /* get file attributes expanded */
-#define SMBlockingX      0x24   /* lock/unlock byte ranges and X */
-#define SMBtrans         0x25   /* transaction - name, bytes in/out */
-#define SMBtranss        0x26   /* transaction (secondary request/response) */
-#define SMBioctl         0x27   /* IOCTL */
-#define SMBioctls        0x28   /* IOCTL  (secondary request/response) */
-#define SMBcopy          0x29   /* copy */
-#define SMBmove          0x2A   /* move */
-#define SMBecho          0x2B   /* echo */
-#define SMBopenX         0x2D   /* open and X */
-#define SMBreadX         0x2E   /* read and X */
-#define SMBwriteX        0x2F   /* write and X */
-#define SMBsesssetupX    0x73   /* Session Set Up & X (including User Logon) */
-#define SMBtconX         0x75   /* tree connect and X */
-#define SMBffirst        0x82   /* find first */
-#define SMBfunique       0x83   /* find unique */
-#define SMBfclose        0x84   /* find close */
-#define SMBinvalid       0xFE   /* invalid command */
-
-
-/* Extended 2.0 protocol */
-#define SMBtrans2        0x32   /* TRANS2 protocol set */
-#define SMBtranss2       0x33   /* TRANS2 protocol set, secondary command */
-#define SMBfindclose     0x34   /* Terminate a TRANSACT2_FINDFIRST */
-#define SMBfindnclose    0x35   /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
-#define SMBulogoffX      0x74   /* user logoff */
-
-/* these are the TRANS2 sub commands */
-#define TRANSACT2_OPEN          0
-#define TRANSACT2_FINDFIRST     1
-#define TRANSACT2_FINDNEXT      2
-#define TRANSACT2_QFSINFO       3
-#define TRANSACT2_SETFSINFO     4
-#define TRANSACT2_QPATHINFO     5
-#define TRANSACT2_SETPATHINFO   6
-#define TRANSACT2_QFILEINFO     7
-#define TRANSACT2_SETFILEINFO   8
-#define TRANSACT2_FSCTL         9
-#define TRANSACT2_IOCTL           10
-#define TRANSACT2_FINDNOTIFYFIRST 11
-#define TRANSACT2_FINDNOTIFYNEXT  12
-#define TRANSACT2_MKDIR           13
-
-/* Information Levels -  Shared? */
-#define SMB_INFO_STANDARD		1
-#define SMB_INFO_QUERY_EA_SIZE		2
-#define SMB_INFO_QUERY_EAS_FROM_LIST	3
-#define SMB_INFO_QUERY_ALL_EAS		4
-#define SMB_INFO_IS_NAME_VALID		6
-
-/* Information Levels -  TRANSACT2_FINDFIRST */
-#define SMB_FIND_FILE_DIRECTORY_INFO		0x101
-#define SMB_FIND_FILE_FULL_DIRECTORY_INFO	0x102
-#define SMB_FIND_FILE_NAMES_INFO		0x103
-#define SMB_FIND_FILE_BOTH_DIRECTORY_INFO	0x104
-
-/* Information Levels -  TRANSACT2_QPATHINFO */
-#define SMB_QUERY_FILE_BASIC_INFO	0x101
-#define SMB_QUERY_FILE_STANDARD_INFO	0x102
-#define SMB_QUERY_FILE_EA_INFO		0x103
-#define SMB_QUERY_FILE_NAME_INFO	0x104
-#define SMB_QUERY_FILE_ALL_INFO		0x107
-#define SMB_QUERY_FILE_ALT_NAME_INFO	0x108
-#define SMB_QUERY_FILE_STREAM_INFO	0x109
-#define SMB_QUERY_FILE_COMPRESSION_INFO	0x10b
-
-/* Information Levels - TRANSACT2_SETFILEINFO */
-#define SMB_SET_FILE_BASIC_INFO		0x101
-#define SMB_SET_FILE_DISPOSITION_INFO	0x102
-#define SMB_SET_FILE_ALLOCATION_INFO	0x103
-#define SMB_SET_FILE_END_OF_FILE_INFO	0x104
-
-/* smb_flg field flags */
-#define SMB_FLAGS_SUPPORT_LOCKREAD	0x01
-#define SMB_FLAGS_CLIENT_BUF_AVAIL	0x02
-#define SMB_FLAGS_RESERVED		0x04
-#define SMB_FLAGS_CASELESS_PATHNAMES	0x08
-#define SMB_FLAGS_CANONICAL_PATHNAMES	0x10
-#define SMB_FLAGS_REQUEST_OPLOCK	0x20
-#define SMB_FLAGS_REQUEST_BATCH_OPLOCK	0x40
-#define SMB_FLAGS_REPLY			0x80
-
-/* smb_flg2 field flags (samba-2.2.0/source/include/smb.h) */
-#define SMB_FLAGS2_LONG_PATH_COMPONENTS		0x0001
-#define SMB_FLAGS2_EXTENDED_ATTRIBUTES		0x0002
-#define SMB_FLAGS2_DFS_PATHNAMES		0x1000
-#define SMB_FLAGS2_READ_PERMIT_NO_EXECUTE	0x2000
-#define SMB_FLAGS2_32_BIT_ERROR_CODES		0x4000 
-#define SMB_FLAGS2_UNICODE_STRINGS		0x8000
-
-
-/*
- * UNIX stuff  (from samba trans2.h)
- */
-#define MIN_UNIX_INFO_LEVEL		0x200
-#define MAX_UNIX_INFO_LEVEL		0x2FF
-#define SMB_FIND_FILE_UNIX		0x202
-#define SMB_QUERY_FILE_UNIX_BASIC	0x200
-#define SMB_QUERY_FILE_UNIX_LINK	0x201
-#define SMB_QUERY_FILE_UNIX_HLINK	0x202
-#define SMB_SET_FILE_UNIX_BASIC		0x200
-#define SMB_SET_FILE_UNIX_LINK		0x201
-#define SMB_SET_FILE_UNIX_HLINK		0x203
-#define SMB_QUERY_CIFS_UNIX_INFO	0x200
-
-/* values which means "don't change it" */
-#define SMB_MODE_NO_CHANGE		0xFFFFFFFF
-#define SMB_UID_NO_CHANGE		0xFFFFFFFF
-#define SMB_GID_NO_CHANGE		0xFFFFFFFF
-#define SMB_TIME_NO_CHANGE		0xFFFFFFFFFFFFFFFFULL
-#define SMB_SIZE_NO_CHANGE		0xFFFFFFFFFFFFFFFFULL
-
-/* UNIX filetype mappings. */
-#define UNIX_TYPE_FILE		0
-#define UNIX_TYPE_DIR		1
-#define UNIX_TYPE_SYMLINK	2
-#define UNIX_TYPE_CHARDEV	3
-#define UNIX_TYPE_BLKDEV	4
-#define UNIX_TYPE_FIFO		5
-#define UNIX_TYPE_SOCKET	6
-#define UNIX_TYPE_UNKNOWN	0xFFFFFFFF
-
-#endif /* _SMBNO_H_ */
diff --git a/drivers/staging/smbfs/sock.c b/drivers/staging/smbfs/sock.c
deleted file mode 100644
index 9e26409..0000000
--- a/drivers/staging/smbfs/sock.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/*
- *  sock.c
- *
- *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
- *  Copyright (C) 1997 by Volker Lendecke
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/fs.h>
-#include <linux/time.h>
-#include <linux/errno.h>
-#include <linux/socket.h>
-#include <linux/fcntl.h>
-#include <linux/file.h>
-#include <linux/in.h>
-#include <linux/net.h>
-#include <linux/mm.h>
-#include <linux/netdevice.h>
-#include <linux/workqueue.h>
-#include <net/scm.h>
-#include <net/tcp_states.h>
-#include <net/ip.h>
-
-#include <asm/uaccess.h>
-#include <asm/ioctls.h>
-
-#include "smb_fs.h"
-#include "smb.h"
-#include "smbno.h"
-#include "smb_debug.h"
-#include "proto.h"
-#include "request.h"
-
-
-static int
-_recvfrom(struct socket *socket, unsigned char *ubuf, int size, unsigned flags)
-{
-	struct kvec iov = {ubuf, size};
-	struct msghdr msg = {.msg_flags = flags};
-	msg.msg_flags |= MSG_DONTWAIT | MSG_NOSIGNAL;
-	return kernel_recvmsg(socket, &msg, &iov, 1, size, msg.msg_flags);
-}
-
-/*
- * Return the server this socket belongs to
- */
-static struct smb_sb_info *
-server_from_socket(struct socket *socket)
-{
-	return socket->sk->sk_user_data;
-}
-
-/*
- * Called when there is data on the socket.
- */
-void
-smb_data_ready(struct sock *sk, int len)
-{
-	struct smb_sb_info *server = server_from_socket(sk->sk_socket);
-	void (*data_ready)(struct sock *, int) = server->data_ready;
-
-	data_ready(sk, len);
-	VERBOSE("(%p, %d)\n", sk, len);
-	smbiod_wake_up();
-}
-
-int
-smb_valid_socket(struct inode * inode)
-{
-	return (inode && S_ISSOCK(inode->i_mode) && 
-		SOCKET_I(inode)->type == SOCK_STREAM);
-}
-
-static struct socket *
-server_sock(struct smb_sb_info *server)
-{
-	struct file *file;
-
-	if (server && (file = server->sock_file))
-	{
-#ifdef SMBFS_PARANOIA
-		if (!smb_valid_socket(file->f_path.dentry->d_inode))
-			PARANOIA("bad socket!\n");
-#endif
-		return SOCKET_I(file->f_path.dentry->d_inode);
-	}
-	return NULL;
-}
-
-void
-smb_close_socket(struct smb_sb_info *server)
-{
-	struct file * file = server->sock_file;
-
-	if (file) {
-		struct socket *sock = server_sock(server);
-
-		VERBOSE("closing socket %p\n", sock);
-		sock->sk->sk_data_ready = server->data_ready;
-		server->sock_file = NULL;
-		fput(file);
-	}
-}
-
-static int
-smb_get_length(struct socket *socket, unsigned char *header)
-{
-	int result;
-
-	result = _recvfrom(socket, header, 4, MSG_PEEK);
-	if (result == -EAGAIN)
-		return -ENODATA;
-	if (result < 0) {
-		PARANOIA("recv error = %d\n", -result);
-		return result;
-	}
-	if (result < 4)
-		return -ENODATA;
-
-	switch (header[0]) {
-	case 0x00:
-	case 0x82:
-		break;
-
-	case 0x85:
-		DEBUG1("Got SESSION KEEP ALIVE\n");
-		_recvfrom(socket, header, 4, 0);	/* read away */
-		return -ENODATA;
-
-	default:
-		PARANOIA("Invalid NBT packet, code=%x\n", header[0]);
-		return -EIO;
-	}
-
-	/* The length in the RFC NB header is the raw data length */
-	return smb_len(header);
-}
-
-int
-smb_recv_available(struct smb_sb_info *server)
-{
-	mm_segment_t oldfs;
-	int avail, err;
-	struct socket *sock = server_sock(server);
-
-	oldfs = get_fs();
-	set_fs(get_ds());
-	err = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail);
-	set_fs(oldfs);
-	return (err >= 0) ? avail : err;
-}
-
-/*
- * Adjust the kvec to move on 'n' bytes (from nfs/sunrpc)
- */
-static int
-smb_move_iov(struct kvec **data, size_t *num, struct kvec *vec, unsigned amount)
-{
-	struct kvec *iv = *data;
-	int i;
-	int len;
-
-	/*
-	 *	Eat any sent kvecs
-	 */
-	while (iv->iov_len <= amount) {
-		amount -= iv->iov_len;
-		iv++;
-		(*num)--;
-	}
-
-	/*
-	 *	And chew down the partial one
-	 */
-	vec[0].iov_len = iv->iov_len-amount;
-	vec[0].iov_base =((unsigned char *)iv->iov_base)+amount;
-	iv++;
-
-	len = vec[0].iov_len;
-
-	/*
-	 *	And copy any others
-	 */
-	for (i = 1; i < *num; i++) {
-		vec[i] = *iv++;
-		len += vec[i].iov_len;
-	}
-
-	*data = vec;
-	return len;
-}
-
-/*
- * smb_receive_header
- * Only called by the smbiod thread.
- */
-int
-smb_receive_header(struct smb_sb_info *server)
-{
-	struct socket *sock;
-	int result = 0;
-	unsigned char peek_buf[4];
-
-	result = -EIO; 
-	sock = server_sock(server);
-	if (!sock)
-		goto out;
-	if (sock->sk->sk_state != TCP_ESTABLISHED)
-		goto out;
-
-	if (!server->smb_read) {
-		result = smb_get_length(sock, peek_buf);
-		if (result < 0) {
-			if (result == -ENODATA)
-				result = 0;
-			goto out;
-		}
-		server->smb_len = result + 4;
-
-		if (server->smb_len < SMB_HEADER_LEN) {
-			PARANOIA("short packet: %d\n", result);
-			server->rstate = SMB_RECV_DROP;
-			result = -EIO;
-			goto out;
-		}
-		if (server->smb_len > SMB_MAX_PACKET_SIZE) {
-			PARANOIA("long packet: %d\n", result);
-			server->rstate = SMB_RECV_DROP;
-			result = -EIO;
-			goto out;
-		}
-	}
-
-	result = _recvfrom(sock, server->header + server->smb_read,
-			   SMB_HEADER_LEN - server->smb_read, 0);
-	VERBOSE("_recvfrom: %d\n", result);
-	if (result < 0) {
-		VERBOSE("receive error: %d\n", result);
-		goto out;
-	}
-	server->smb_read += result;
-
-	if (server->smb_read == SMB_HEADER_LEN)
-		server->rstate = SMB_RECV_HCOMPLETE;
-out:
-	return result;
-}
-
-static char drop_buffer[PAGE_SIZE];
-
-/*
- * smb_receive_drop - read and throw away the data
- * Only called by the smbiod thread.
- *
- * FIXME: we are in the kernel, could we just tell the socket that we want
- * to drop stuff from the buffer?
- */
-int
-smb_receive_drop(struct smb_sb_info *server)
-{
-	struct socket *sock;
-	unsigned int flags;
-	struct kvec iov;
-	struct msghdr msg;
-	int rlen = smb_len(server->header) - server->smb_read + 4;
-	int result = -EIO;
-
-	if (rlen > PAGE_SIZE)
-		rlen = PAGE_SIZE;
-
-	sock = server_sock(server);
-	if (!sock)
-		goto out;
-	if (sock->sk->sk_state != TCP_ESTABLISHED)
-		goto out;
-
-	flags = MSG_DONTWAIT | MSG_NOSIGNAL;
-	iov.iov_base = drop_buffer;
-	iov.iov_len = PAGE_SIZE;
-	msg.msg_flags = flags;
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_control = NULL;
-
-	result = kernel_recvmsg(sock, &msg, &iov, 1, rlen, flags);
-
-	VERBOSE("read: %d\n", result);
-	if (result < 0) {
-		VERBOSE("receive error: %d\n", result);
-		goto out;
-	}
-	server->smb_read += result;
-
-	if (server->smb_read >= server->smb_len)
-		server->rstate = SMB_RECV_END;
-
-out:
-	return result;
-}
-
-/*
- * smb_receive
- * Only called by the smbiod thread.
- */
-int
-smb_receive(struct smb_sb_info *server, struct smb_request *req)
-{
-	struct socket *sock;
-	unsigned int flags;
-	struct kvec iov[4];
-	struct kvec *p = req->rq_iov;
-	size_t num = req->rq_iovlen;
-	struct msghdr msg;
-	int rlen;
-	int result = -EIO;
-
-	sock = server_sock(server);
-	if (!sock)
-		goto out;
-	if (sock->sk->sk_state != TCP_ESTABLISHED)
-		goto out;
-
-	flags = MSG_DONTWAIT | MSG_NOSIGNAL;
-	msg.msg_flags = flags;
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_control = NULL;
-
-	/* Dont repeat bytes and count available bufferspace */
-	rlen = min_t(int, smb_move_iov(&p, &num, iov, req->rq_bytes_recvd),
-			(req->rq_rlen - req->rq_bytes_recvd));
-
-	result = kernel_recvmsg(sock, &msg, p, num, rlen, flags);
-
-	VERBOSE("read: %d\n", result);
-	if (result < 0) {
-		VERBOSE("receive error: %d\n", result);
-		goto out;
-	}
-	req->rq_bytes_recvd += result;
-	server->smb_read += result;
-
-out:
-	return result;
-}
-
-/*
- * Try to send a SMB request. This may return after sending only parts of the
- * request. SMB_REQ_TRANSMITTED will be set if a request was fully sent.
- *
- * Parts of this was taken from xprt_sendmsg from net/sunrpc/xprt.c
- */
-int
-smb_send_request(struct smb_request *req)
-{
-	struct smb_sb_info *server = req->rq_server;
-	struct socket *sock;
-	struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT};
-        int slen = req->rq_slen - req->rq_bytes_sent;
-	int result = -EIO;
-	struct kvec iov[4];
-	struct kvec *p = req->rq_iov;
-	size_t num = req->rq_iovlen;
-
-	sock = server_sock(server);
-	if (!sock)
-		goto out;
-	if (sock->sk->sk_state != TCP_ESTABLISHED)
-		goto out;
-
-	/* Dont repeat bytes */
-	if (req->rq_bytes_sent)
-		smb_move_iov(&p, &num, iov, req->rq_bytes_sent);
-
-	result = kernel_sendmsg(sock, &msg, p, num, slen);
-
-	if (result >= 0) {
-		req->rq_bytes_sent += result;
-		if (req->rq_bytes_sent >= req->rq_slen)
-			req->rq_flags |= SMB_REQ_TRANSMITTED;
-	}
-out:
-	return result;
-}
diff --git a/drivers/staging/smbfs/symlink.c b/drivers/staging/smbfs/symlink.c
deleted file mode 100644
index 632c4ac..0000000
--- a/drivers/staging/smbfs/symlink.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  symlink.c
- *
- *  Copyright (C) 2002 by John Newbigin
- *
- *  Please add a note about your changes to smbfs in the ChangeLog file.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/pagemap.h>
-#include <linux/net.h>
-#include <linux/namei.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include "smbno.h"
-#include "smb_fs.h"
-#include "smb_debug.h"
-#include "proto.h"
-
-int smb_symlink(struct inode *inode, struct dentry *dentry, const char *oldname)
-{
-	DEBUG1("create symlink %s -> %s/%s\n", oldname, DENTRY_PATH(dentry));
-
-	return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname);
-}
-
-static void *smb_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	char *link = __getname();
-	DEBUG1("followlink of %s/%s\n", DENTRY_PATH(dentry));
-
-	if (!link) {
-		link = ERR_PTR(-ENOMEM);
-	} else {
-		int len = smb_proc_read_link(server_from_dentry(dentry),
-						dentry, link, PATH_MAX - 1);
-		if (len < 0) {
-			__putname(link);
-			link = ERR_PTR(len);
-		} else {
-			link[len] = 0;
-		}
-	}
-	nd_set_link(nd, link);
-	return NULL;
-}
-
-static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
-{
-	char *s = nd_get_link(nd);
-	if (!IS_ERR(s))
-		__putname(s);
-}
-
-const struct inode_operations smb_link_inode_operations =
-{
-	.readlink	= generic_readlink,
-	.follow_link	= smb_follow_link,
-	.put_link	= smb_put_link,
-};
diff --git a/drivers/staging/solo6x10/Makefile b/drivers/staging/solo6x10/Makefile
index 1616b55..72816cf 100644
--- a/drivers/staging/solo6x10/Makefile
+++ b/drivers/staging/solo6x10/Makefile
@@ -1,6 +1,3 @@
-solo6x10-y	:= solo6010-core.o solo6010-i2c.o solo6010-p2m.o \
-		   solo6010-v4l2.o solo6010-tw28.o solo6010-gpio.o \
-		   solo6010-disp.o solo6010-enc.o solo6010-v4l2-enc.o \
-		   solo6010-g723.o
+solo6x10-y := core.o i2c.o p2m.o v4l2.o tw28.o gpio.o disp.o enc.o v4l2-enc.o g723.o
 
 obj-$(CONFIG_SOLO6X10) := solo6x10.o
diff --git a/drivers/staging/solo6x10/core.c b/drivers/staging/solo6x10/core.c
new file mode 100644
index 0000000..7677994
--- /dev/null
+++ b/drivers/staging/solo6x10/core.c
@@ -0,0 +1,331 @@
+/*
+ * 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/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 __devinit 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 __devexit 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,
+};
+
+static int __init solo_module_init(void)
+{
+	return pci_register_driver(&solo_pci_driver);
+}
+
+static void __exit solo_module_exit(void)
+{
+	pci_unregister_driver(&solo_pci_driver);
+}
+
+module_init(solo_module_init);
+module_exit(solo_module_exit);
diff --git a/drivers/staging/solo6x10/disp.c b/drivers/staging/solo6x10/disp.c
new file mode 100644
index 0000000..884c0eb
--- /dev/null
+++ b/drivers/staging/solo6x10/disp.c
@@ -0,0 +1,270 @@
+/*
+ * 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/solo6x10/enc.c b/drivers/staging/solo6x10/enc.c
new file mode 100644
index 0000000..285f7f3
--- /dev/null
+++ b/drivers/staging/solo6x10/enc.c
@@ -0,0 +1,237 @@
+/*
+ * 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 "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/solo6x10/g723.c b/drivers/staging/solo6x10/g723.c
new file mode 100644
index 0000000..bd8eb92
--- /dev/null
+++ b/drivers/staging/solo6x10/g723.c
@@ -0,0 +1,398 @@
+/*
+ * 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/freezer.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/solo6x10/gpio.c b/drivers/staging/solo6x10/gpio.c
new file mode 100644
index 0000000..0925e6f
--- /dev/null
+++ b/drivers/staging/solo6x10/gpio.c
@@ -0,0 +1,102 @@
+/*
+ * 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/solo6x10/i2c.c b/drivers/staging/solo6x10/i2c.c
new file mode 100644
index 0000000..ef95a50
--- /dev/null
+++ b/drivers/staging/solo6x10/i2c.c
@@ -0,0 +1,330 @@
+/*
+ * 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/solo6x10/jpeg.h b/drivers/staging/solo6x10/jpeg.h
new file mode 100644
index 0000000..50defec
--- /dev/null
+++ b/drivers/staging/solo6x10/jpeg.h
@@ -0,0 +1,105 @@
+/*
+ * 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_JPEG_H
+#define __SOLO6X10_JPEG_H
+
+static 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,
+	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, 0xc4, 0x01, 0xa2, 0x00,
+	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01,
+	0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
+	0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03,
+	0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
+	0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14,
+	0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
+	0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
+	0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
+	0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34,
+	0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
+	0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
+	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
+	0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
+	0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84,
+	0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
+	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
+	0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
+	0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
+	0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+	0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
+	0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
+	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01,
+	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01,
+	0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
+	0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
+	0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
+	0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32,
+	0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
+	0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72,
+	0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1,
+	0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29,
+	0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43,
+	0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53,
+	0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
+	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
+	0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
+	0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
+	0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+	0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
+	0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
+	0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
+	0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4,
+	0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3,
+	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff,
+	0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0,
+	0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03,
+	0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
+	0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
+};
+
+/* This is the byte marker for the start of SOF0: 0xffc0 marker */
+#define SOF0_START	575
+
+#endif /* __SOLO6X10_JPEG_H */
diff --git a/drivers/staging/solo6x10/offsets.h b/drivers/staging/solo6x10/offsets.h
new file mode 100644
index 0000000..3d7e569
--- /dev/null
+++ b/drivers/staging/solo6x10/offsets.h
@@ -0,0 +1,74 @@
+/*
+ * 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/solo6x10/osd-font.h b/drivers/staging/solo6x10/osd-font.h
new file mode 100644
index 0000000..591e0e8
--- /dev/null
+++ b/drivers/staging/solo6x10/osd-font.h
@@ -0,0 +1,154 @@
+/*
+ * 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/solo6x10/p2m.c b/drivers/staging/solo6x10/p2m.c
new file mode 100644
index 0000000..5717eab
--- /dev/null
+++ b/drivers/staging/solo6x10/p2m.c
@@ -0,0 +1,305 @@
+/*
+ * 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/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;
+
+	printk(KERN_WARNING "%s: Testing %u bytes of external ram\n",
+	       SOLO6X10_NAME, 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);
+
+	printk(KERN_WARNING "%s: Found %llu errors during p2m test\n",
+	       SOLO6X10_NAME, 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/solo6x10/registers.h b/drivers/staging/solo6x10/registers.h
new file mode 100644
index 0000000..aca5444
--- /dev/null
+++ b/drivers/staging/solo6x10/registers.h
@@ -0,0 +1,637 @@
+/*
+ * 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/solo6x10/solo6010-core.c b/drivers/staging/solo6x10/solo6010-core.c
deleted file mode 100644
index c433136..0000000
--- a/drivers/staging/solo6x10/solo6010-core.c
+++ /dev/null
@@ -1,300 +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/videodev2.h>
-
-#include "solo6010.h"
-#include "solo6010-tw28.h"
-
-MODULE_DESCRIPTION("Softlogic 6010 MP4 Encoder/Decoder V4L2/ALSA Driver");
-MODULE_AUTHOR("Ben Collins <bcollins@bluecherry.net>");
-MODULE_VERSION(SOLO6010_VERSION);
-MODULE_LICENSE("GPL");
-
-void solo6010_irq_on(struct solo6010_dev *solo_dev, u32 mask)
-{
-	solo_dev->irq_mask |= mask;
-	solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask);
-}
-
-void solo6010_irq_off(struct solo6010_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 solo6010_isr(int irq, void *data)
-{
-	struct solo6010_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 solo6010_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) {
-		solo6010_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 __devinit solo6010_pci_probe(struct pci_dev *pdev,
-					const struct pci_device_id *id)
-{
-	struct solo6010_dev *solo_dev;
-	int ret;
-	int sdram;
-	u8 chip_id;
-
-	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, SOLO6010_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;
-	}
-
-	/* Disable all interrupts to start */
-	solo6010_irq_off(solo_dev, ~0);
-
-	/* Initial global settings */
-	solo_reg_write(solo_dev, SOLO_SYS_CFG, SOLO_SYS_CFG_SDRAM64BIT |
-		       SOLO_SYS_CFG_INPUTDIV(25) |
-		       SOLO_SYS_CFG_FEEDBACKDIV((SOLO_CLOCK_MHZ * 2) - 2) |
-		       SOLO_SYS_CFG_OUTDIV(3));
-	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, solo6010_isr, IRQF_SHARED, SOLO6010_NAME,
-			  solo_dev);
-	if (ret)
-		goto fail_probe;
-
-	/* Handle this from the start */
-	solo6010_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 __devexit solo6010_pci_remove(struct pci_dev *pdev)
-{
-	struct solo6010_dev *solo_dev = pci_get_drvdata(pdev);
-
-	free_solo_dev(solo_dev);
-}
-
-static struct pci_device_id solo6010_id_table[] = {
-	/* 6010 based cards */
-	{PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010)},
-	{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, solo6010_id_table);
-
-static struct pci_driver solo6010_pci_driver = {
-	.name = SOLO6010_NAME,
-	.id_table = solo6010_id_table,
-	.probe = solo6010_pci_probe,
-	.remove = solo6010_pci_remove,
-};
-
-static int __init solo6010_module_init(void)
-{
-	return pci_register_driver(&solo6010_pci_driver);
-}
-
-static void __exit solo6010_module_exit(void)
-{
-	pci_unregister_driver(&solo6010_pci_driver);
-}
-
-module_init(solo6010_module_init);
-module_exit(solo6010_module_exit);
diff --git a/drivers/staging/solo6x10/solo6010-disp.c b/drivers/staging/solo6x10/solo6010-disp.c
deleted file mode 100644
index f866f84..0000000
--- a/drivers/staging/solo6x10/solo6010-disp.c
+++ /dev/null
@@ -1,271 +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 "solo6010.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 solo6010_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 solo6010_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_dev)));
-
-	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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_dev *solo_dev)
-{
-	int i;
-
-	solo6010_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/solo6x10/solo6010-enc.c b/drivers/staging/solo6x10/solo6010-enc.c
deleted file mode 100644
index 481a492..0000000
--- a/drivers/staging/solo6x10/solo6010-enc.c
+++ /dev/null
@@ -1,229 +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 "solo6010.h"
-#include "solo6010-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 solo6010_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(solo_dev) >> 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(solo_dev) +
-				     (i * SOLO_EOSD_EXT_SIZE) + j,
-				     OSG_BUFFER_SIZE);
-		}
-	}
-	kfree(buf);
-}
-
-int solo_osd_print(struct solo_enc_dev *solo_enc)
-{
-	struct solo6010_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_dev) +
-		     (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 solo6010_dev *solo_dev)
-{
-	solo_reg_write(solo_dev, SOLO_VE_JPEG_QP_TBL,
-		       (2 << 24) | (2 << 16) | (2 << 8) | (2 << 0));
-	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);
-}
-
-static void solo_mp4e_config(struct solo6010_dev *solo_dev)
-{
-	int i;
-
-	/* 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_BYTE_ALIGN(2) |
-		       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);
-
-	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(36 / 4));
-
-	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);
-}
-
-int solo_enc_init(struct solo6010_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);
-	}
-
-	solo6010_irq_on(solo_dev, SOLO_IRQ_ENCODER);
-
-	return 0;
-}
-
-void solo_enc_exit(struct solo6010_dev *solo_dev)
-{
-	int i;
-
-	solo6010_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/solo6x10/solo6010-g723.c b/drivers/staging/solo6x10/solo6010-g723.c
deleted file mode 100644
index 254b46a..0000000
--- a/drivers/staging/solo6x10/solo6010-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/freezer.h>
-
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/control.h>
-
-#include "solo6010.h"
-#include "solo6010-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 solo6010_dev		*solo_dev;
-	unsigned char			g723_buf[G723_PERIOD_BYTES];
-};
-
-static void solo_g723_config(struct solo6010_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 solo6010_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 solo6010_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 solo6010_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)
-				solo6010_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)
-				solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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, SOLO6010_NAME);
-	strcpy(card->shortname, "SOLO-6010 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-6010");
-	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 solo6010_dev *solo_dev)
-{
-	solo_reg_write(solo_dev, SOLO_AUDIO_CONTROL, 0);
-	solo6010_irq_off(solo_dev, SOLO_IRQ_G723);
-
-	snd_card_free(solo_dev->snd_card);
-}
diff --git a/drivers/staging/solo6x10/solo6010-gpio.c b/drivers/staging/solo6x10/solo6010-gpio.c
deleted file mode 100644
index 8869b88..0000000
--- a/drivers/staging/solo6x10/solo6010-gpio.c
+++ /dev/null
@@ -1,103 +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 "solo6010.h"
-
-static void solo_gpio_mode(struct solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_dev *solo_dev)
-{
-	solo_gpio_config(solo_dev);
-	return 0;
-}
-
-void solo_gpio_exit(struct solo6010_dev *solo_dev)
-{
-	solo_gpio_clear(solo_dev, 0x30);
-	solo_gpio_config(solo_dev);
-}
diff --git a/drivers/staging/solo6x10/solo6010-i2c.c b/drivers/staging/solo6x10/solo6010-i2c.c
deleted file mode 100644
index 60b69cd..0000000
--- a/drivers/staging/solo6x10/solo6010-i2c.c
+++ /dev/null
@@ -1,332 +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 SOLO6010 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 "solo6010.h"
-
-u8 solo_i2c_readbyte(struct solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_dev *solo_dev)
-{
-	solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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);
-	solo6010_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 solo6010_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",
-			 SOLO6010_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 solo6010_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/solo6x10/solo6010-jpeg.h b/drivers/staging/solo6x10/solo6010-jpeg.h
deleted file mode 100644
index fb0507e..0000000
--- a/drivers/staging/solo6x10/solo6010-jpeg.h
+++ /dev/null
@@ -1,105 +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 __SOLO6010_JPEG_H
-#define __SOLO6010_JPEG_H
-
-static 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,
-	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, 0xc4, 0x01, 0xa2, 0x00,
-	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00, 0x02, 0x01,
-	0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
-	0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03,
-	0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41,
-	0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14,
-	0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1,
-	0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
-	0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19,
-	0x1a, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34,
-	0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44,
-	0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53, 0x54,
-	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
-	0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74,
-	0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84,
-	0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x92, 0x93,
-	0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2,
-	0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
-	0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
-	0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
-	0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-	0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
-	0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
-	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x01,
-	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x11, 0x00, 0x02, 0x01,
-	0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
-	0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02,
-	0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12,
-	0x41, 0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32,
-	0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1,
-	0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72,
-	0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1,
-	0x17, 0x18, 0x19, 0x1a, 0x26, 0x27, 0x28, 0x29,
-	0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43,
-	0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x53,
-	0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63,
-	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73,
-	0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82,
-	0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a,
-	0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
-	0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8,
-	0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-	0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6,
-	0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5,
-	0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3, 0xe4,
-	0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3,
-	0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff,
-	0xc0, 0x00, 0x11, 0x08, 0x00, 0xf0, 0x02, 0xc0,
-	0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03,
-	0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
-	0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
-};
-
-/* This is the byte marker for the start of SOF0: 0xffc0 marker */
-#define SOF0_START	575
-
-#endif /* __SOLO6010_JPEG_H */
diff --git a/drivers/staging/solo6x10/solo6010-offsets.h b/drivers/staging/solo6x10/solo6010-offsets.h
deleted file mode 100644
index 2431de9..0000000
--- a/drivers/staging/solo6x10/solo6010-offsets.h
+++ /dev/null
@@ -1,78 +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 __SOLO6010_OFFSETS_H
-#define __SOLO6010_OFFSETS_H
-
-/* Offsets and sizes of the external address */
-#define SOLO_DISP_EXT_ADDR(__solo)		0x00000000
-#define SOLO_DISP_EXT_SIZE			0x00480000
-
-#define SOLO_DEC2LIVE_EXT_ADDR(__solo) \
-		(SOLO_DISP_EXT_ADDR(__solo) + SOLO_DISP_EXT_SIZE)
-#define SOLO_DEC2LIVE_EXT_SIZE			0x00240000
-
-#define SOLO_OSG_EXT_ADDR(__solo) \
-		(SOLO_DEC2LIVE_EXT_ADDR(__solo) + SOLO_DEC2LIVE_EXT_SIZE)
-#define SOLO_OSG_EXT_SIZE			0x00120000
-
-#define SOLO_EOSD_EXT_ADDR(__solo) \
-		(SOLO_OSG_EXT_ADDR(__solo) + SOLO_OSG_EXT_SIZE)
-#define SOLO_EOSD_EXT_SIZE			0x00010000
-
-#define SOLO_MOTION_EXT_ADDR(__solo) \
-		(SOLO_EOSD_EXT_ADDR(__solo) + \
-		 (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 /* __SOLO6010_OFFSETS_H */
diff --git a/drivers/staging/solo6x10/solo6010-osd-font.h b/drivers/staging/solo6x10/solo6010-osd-font.h
deleted file mode 100644
index d72efbb..0000000
--- a/drivers/staging/solo6x10/solo6010-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 __SOLO6010_OSD_FONT_H
-#define __SOLO6010_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 /* __SOLO6010_OSD_FONT_H */
diff --git a/drivers/staging/solo6x10/solo6010-p2m.c b/drivers/staging/solo6x10/solo6010-p2m.c
deleted file mode 100644
index 956dea0..0000000
--- a/drivers/staging/solo6x10/solo6010-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/scatterlist.h>
-
-#include "solo6010.h"
-
-/* #define SOLO_TEST_P2M */
-
-int solo_p2m_dma(struct solo6010_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 solo6010_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 = dma_addr;
-	desc->fa = ext_addr;
-
-	desc->ext = 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;
-
-	/* Ext size only matters when we're repeating */
-	if (repeat) {
-		desc->ext |= SOLO_P2M_EXT_INC(ext_size >> 2);
-		desc->ctrl |=  SOLO_P2M_PCI_INC(size >> 2) |
-			SOLO_P2M_REPEAT(repeat);
-	}
-}
-
-int solo_p2m_dma_desc(struct solo6010_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 solo6010_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 solo6010_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(SOLO6010_NAME ": Failed to malloc for p2m_test\n");
-		return size;
-	}
-
-	rd_buf = kmalloc(size, GFP_KERNEL);
-	if (!rd_buf) {
-		printk(SOLO6010_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 solo6010_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;
-
-	printk(KERN_WARNING "%s: Testing %u bytes of external ram\n",
-	       SOLO6010_NAME, 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);
-
-	printk(KERN_WARNING "%s: Found %llu errors during p2m test\n",
-	       SOLO6010_NAME, errs);
-
-	return;
-}
-#else
-#define run_p2m_test(__solo)	do {} while (0)
-#endif
-
-void solo_p2m_isr(struct solo6010_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 solo6010_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 solo6010_dev *solo_dev)
-{
-	int i;
-
-	for (i = 0; i < SOLO_NR_P2M; i++)
-		solo6010_irq_off(solo_dev, SOLO_IRQ_P2M(i));
-}
-
-int solo_p2m_init(struct solo6010_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);
-		solo6010_irq_on(solo_dev, SOLO_IRQ_P2M(i));
-	}
-
-	run_p2m_test(solo_dev);
-
-	return 0;
-}
diff --git a/drivers/staging/solo6x10/solo6010-registers.h b/drivers/staging/solo6x10/solo6010-registers.h
deleted file mode 100644
index d39d3c6..0000000
--- a/drivers/staging/solo6x10/solo6010-registers.h
+++ /dev/null
@@ -1,657 +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 __SOLO6010_REGISTERS_H
-#define __SOLO6010_REGISTERS_H
-
-#include "solo6010-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)
-
-#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 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	  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_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))
-struct videnc_status {
-	union {
-		u32 status0;
-		struct {
-			u32 mp4_enc_code_size:20, sad_motion:1, vid_motion:1,
-			    vop_type:2, video_channel:5, source_field_idx:1,
-			    interlace:1, progressive:1;
-		} status0_st;
-	};
-	union {
-		u32 status1;
-		struct {
-			u32 vsize:8, hsize:8, last_queue:4, foo1:8, scale:4;
-		} status1_st;
-	};
-	union {
-		u32 status4;
-		struct {
-			u32 jpeg_code_size:20, interval:10, foo1:2;
-		} status4_st;
-	};
-	union {
-		u32 status9;
-		struct {
-			u32 channel:5, foo1:27;
-		} status9_st;
-	};
-	union {
-		u32 status10;
-		struct {
-			u32 mp4_code_size:20, foo:12;
-		} status10_st;
-	};
-	union {
-		u32 status11;
-		struct {
-			u32 last_queue:8, foo1:24;
-		} status11_st;
-	};
-};
-
-#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 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_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 /* __SOLO6010_REGISTERS_H */
diff --git a/drivers/staging/solo6x10/solo6010-tw28.c b/drivers/staging/solo6x10/solo6010-tw28.c
deleted file mode 100644
index 905a6ad..0000000
--- a/drivers/staging/solo6x10/solo6010-tw28.c
+++ /dev/null
@@ -1,823 +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 "solo6010.h"
-#include "solo6010-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 solo6010_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 solo6010_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 solo6010_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("solo6010/tw28: Error writing register: %02x->%02x [%02x]\n",
-		addr, off, val); */
-}
-
-static int tw2865_setup(struct solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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/solo6x10/solo6010-tw28.h b/drivers/staging/solo6x10/solo6010-tw28.h
deleted file mode 100644
index a7eecfa..0000000
--- a/drivers/staging/solo6x10/solo6010-tw28.h
+++ /dev/null
@@ -1,65 +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 __SOLO6010_TW28_H
-#define __SOLO6010_TW28_H
-
-#include "solo6010.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 solo6010_dev *solo_dev);
-
-int tw28_set_ctrl_val(struct solo6010_dev *solo_dev, u32 ctrl, u8 ch,
-		      s32 val);
-int tw28_get_ctrl_val(struct solo6010_dev *solo_dev, u32 ctrl, u8 ch,
-		      s32 *val);
-
-u8 tw28_get_audio_gain(struct solo6010_dev *solo_dev, u8 ch);
-void tw28_set_audio_gain(struct solo6010_dev *solo_dev, u8 ch, u8 val);
-int tw28_get_video_status(struct solo6010_dev *solo_dev, u8 ch);
-
-#if 0
-unsigned int tw2815_get_audio_status(struct SOLO6010 *solo6010);
-void tw2815_Set_AudioOutVol(struct SOLO6010 *solo6010, unsigned int u_val);
-#endif
-
-#endif /* __SOLO6010_TW28_H */
diff --git a/drivers/staging/solo6x10/solo6010-v4l2-enc.c b/drivers/staging/solo6x10/solo6010-v4l2-enc.c
deleted file mode 100644
index 7bbb940..0000000
--- a/drivers/staging/solo6x10/solo6010-v4l2-enc.c
+++ /dev/null
@@ -1,1706 +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 "solo6010.h"
-#include "solo6010-tw28.h"
-#include "solo6010-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 unsigned char vid_vop_header[] = {
-	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x20,
-	0x02, 0x48, 0x05, 0xc0, 0x00, 0x40, 0x00, 0x40,
-	0x00, 0x40, 0x00, 0x80, 0x00, 0x97, 0x53, 0x04,
-	0x1f, 0x4c, 0x58, 0x10, 0x78, 0x51, 0x18, 0x3f,
-};
-
-/*
- * Things we can change around:
- *
- * byte  10,        4-bits 01111000                   aspect
- * bytes 21,22,23  16-bits 000x1111 11111111 1111x000 fps/res
- * bytes 23,24,25  15-bits 00000n11 11111111 11111x00 interval
- * bytes 25,26,27  13-bits 00000x11 11111111 111x0000 width
- * bytes 27,28,29  13-bits 000x1111 11111111 1x000000 height
- * byte  29         1-bit  0x100000                   interlace
- */
-
-/* For aspect */
-#define XVID_PAR_43_PAL		2
-#define XVID_PAR_43_NTSC	3
-
-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
-};
-
-struct vop_header {
-	/* VD_IDX0 */
-	u32 size:20, sync_start:1, page_stop:1, vop_type:2, channel:4,
-		nop0:1, source_fl:1, interlace:1, progressive:1;
-
-	/* VD_IDX1 */
-	u32 vsize:8, hsize:8, frame_interop:1, nop1:7, win_id:4, scale:4;
-
-	/* VD_IDX2 */
-	u32 base_addr:16, nop2:15, hoff:1;
-
-	/* VD_IDX3 - User set macros */
-	u32 sy:12, sx:12, nop3:1, hzoom:1, read_interop:1, write_interlace:1,
-		scale_mode:4;
-
-	/* VD_IDX4 - User set macros continued */
-	u32 write_page:8, nop4:24;
-
-	/* VD_IDX5 */
-	u32 next_code_addr;
-
-	u32 end_nops[10];
-} __attribute__((packed));
-
-static int solo_is_motion_on(struct solo_enc_dev *solo_enc)
-{
-	struct solo6010_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 solo6010_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)
-		solo6010_irq_on(solo_dev, SOLO_IRQ_MOTION);
-	else
-		solo6010_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 solo6010_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 solo6010_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 solo6010_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, SOLO6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 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 solo6010_dev *solo_dev = solo_enc->solo_dev;
-	struct vop_header vh;
-	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(vh.size > enc_buf->size))
-		return -EINVAL;
-
-	vb->width = vh.hsize << 4;
-	vb->height = vh.vsize << 4;
-	vb->size = vh.size;
-
-	/* If this is a key frame, add extra m4v header */
-	if (!enc_buf->vop) {
-		u16 fps = solo_dev->fps * 1000;
-		u16 interval = solo_enc->interval * 1000;
-		u8 p[sizeof(vid_vop_header)];
-
-		memcpy(p, vid_vop_header, sizeof(p));
-
-		if (solo_dev->video_type == SOLO_VO_FMT_TYPE_NTSC)
-			p[10] |= ((XVID_PAR_43_NTSC << 3) & 0x78);
-		else
-			p[10] |= ((XVID_PAR_43_PAL << 3) & 0x78);
-
-		/* Frame rate and interval */
-		p[22] = fps >> 4;
-		p[23] = ((fps << 4) & 0xf0) | 0x0c | ((interval >> 13) & 0x3);
-		p[24] = (interval >> 5) & 0xff;
-		p[25] = ((interval << 3) & 0xf8) | 0x04;
-
-		/* Width and height */
-		p[26] = (vb->width >> 3) & 0xff;
-		p[27] = ((vb->height >> 9) & 0x0f) | 0x10;
-		p[28] = (vb->height >> 1) & 0xff;
-
-		/* Interlace */
-		if (vh.interlace)
-			p[29] |= 0x20;
-
-		enc_write_sg(vbuf->sglist, p, sizeof(p));
-
-		/* Adjust the dma buffer past this header */
-		vb->size += sizeof(vid_vop_header);
-		skip = sizeof(vid_vop_header);
-	}
-
-	/* 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 solo6010_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 solo6010_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 solo6010_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 solo6010_dev *solo_dev)
-{
-	struct solo_enc_buf *enc_buf;
-	struct videnc_status vstatus;
-	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);
-
-	vstatus.status11 = solo_reg_read(solo_dev, SOLO_VE_STATE(11));
-	cur_q = (vstatus.status11_st.last_queue + 1) % MP4_QS;
-
-	vstatus.status0 = solo_reg_read(solo_dev, SOLO_VE_STATE(0));
-	reg_mpeg_size = (vstatus.status0_st.mp4_enc_code_size + 64 + 32) &
-			(~31);
-
-	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 solo6010_dev *solo_dev = solo_enc->solo_dev;
-
-	strcpy(cap->driver, SOLO6010_NAME);
-	snprintf(cap->card, sizeof(cap->card), "Softlogic 6010 Enc %d",
-		 solo_enc->ch);
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
-		 pci_name(solo_dev->pdev));
-	cap->version = SOLO6010_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 solo6010_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 solo6010_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;
-	} else if (!(pix->width == solo_dev->video_hsize &&
-	      pix->height == solo_dev->video_vsize << 1) &&
-	    !(pix->width == solo_dev->video_hsize >> 1 &&
-	      pix->height == solo_dev->video_vsize)) {
-		/* Default to CIF 1/2 size */
-		pix->width = solo_dev->video_hsize >> 1;
-		pix->height = solo_dev->video_vsize;
-	}
-
-	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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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);
-			}
-			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);
-			}
-			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			= SOLO6010_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 solo6010_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)", SOLO6010_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 solo6010_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 solo6010_dev *solo_dev)
-{
-	int i;
-
-	solo6010_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/solo6x10/solo6010-v4l2.c b/drivers/staging/solo6x10/solo6010-v4l2.c
deleted file mode 100644
index a8491dc..0000000
--- a/drivers/staging/solo6x10/solo6010-v4l2.c
+++ /dev/null
@@ -1,966 +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 "solo6010.h"
-#include "solo6010-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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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(solo_dev) + (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 solo6010_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, SOLO6010_NAME "_disp");
-
-	if (IS_ERR(fh->kthread))
-		return PTR_ERR(fh->kthread);
-
-	return 0;
-}
-
-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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_dev *solo_dev = fh->solo_dev;
-
-	strcpy(cap->driver, SOLO6010_NAME);
-	strcpy(cap->card, "Softlogic 6010");
-	snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI %s",
-		 pci_name(solo_dev->pdev));
-	cap->version = SOLO6010_VER_NUM;
-	cap->capabilities =     V4L2_CAP_VIDEO_CAPTURE |
-				V4L2_CAP_READWRITE |
-				V4L2_CAP_STREAMING;
-	return 0;
-}
-
-static int solo_enum_ext_input(struct solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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 solo6010_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			= SOLO6010_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 solo6010_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)",
-		 SOLO6010_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 */
-
-	solo6010_irq_on(solo_dev, SOLO_IRQ_VIDEO_IN);
-
-	return 0;
-}
-
-void solo_v4l2_exit(struct solo6010_dev *solo_dev)
-{
-	solo6010_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/solo6x10/solo6010.h b/drivers/staging/solo6x10/solo6010.h
deleted file mode 100644
index 9c930f3..0000000
--- a/drivers/staging/solo6x10/solo6010.h
+++ /dev/null
@@ -1,334 +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 __SOLO6010_H
-#define __SOLO6010_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 <asm/io.h>
-#include <asm/atomic.h>
-
-#include <linux/videodev2.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf-core.h>
-
-#include "solo6010-registers.h"
-
-#ifndef PCI_VENDOR_ID_SOFTLOGIC
-#define PCI_VENDOR_ID_SOFTLOGIC		0x9413
-#define PCI_DEVICE_ID_SOLO6010		0x6010
-#endif
-
-#ifndef PCI_VENDOR_ID_BLUECHERRY
-#define PCI_VENDOR_ID_BLUECHERRY	0x1BB3
-/* Neugent Softlogic 6010 based cards */
-#define PCI_DEVICE_ID_NEUSOLO_4		0x4304
-#define PCI_DEVICE_ID_NEUSOLO_9		0x4309
-#define PCI_DEVICE_ID_NEUSOLO_16	0x4310
-/* Bluecherry Softlogic 6010 based cards */
-#define PCI_DEVICE_ID_BC_SOLO_4		0x4E04
-#define PCI_DEVICE_ID_BC_SOLO_9		0x4E09
-#define PCI_DEVICE_ID_BC_SOLO_16	0x4E10
-/* Bluecherry Softlogic 6110 based cards */
-#define PCI_DEVICE_ID_BC_6110_4		0x5304
-#define PCI_DEVICE_ID_BC_6110_8		0x5308
-#define PCI_DEVICE_ID_BC_6110_16	0x5310
-#endif /* Bluecherry */
-
-#define SOLO6010_NAME			"solo6010"
-
-#define SOLO_MAX_CHANNELS		16
-
-/* Make sure these two match */
-#define SOLO6010_VERSION		"2.0.0"
-#define SOLO6010_VER_MAJOR		2
-#define SOLO6010_VER_MINOR		0
-#define SOLO6010_VER_SUB		0
-#define SOLO6010_VER_NUM \
-	KERNEL_VERSION(SOLO6010_VER_MAJOR, SOLO6010_VER_MINOR, SOLO6010_VER_SUB)
-
-/*
- * The SOLO6010 actually has 8 i2c channels, but we only use 2.
- * 0 - Techwell chip(s)
- * 1 - SAA7128
- */
-#define SOLO_I2C_ADAPTERS		2
-#define SOLO_I2C_TW			0
-#define SOLO_I2C_SAA			1
-
-/* 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
-
-/* Encoder standard modes */
-#define SOLO_ENC_MODE_CIF		2
-#define SOLO_ENC_MODE_HD1		1
-#define SOLO_ENC_MODE_D1		9
-
-#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)
-#endif
-
-enum SOLO_I2C_STATE {
-	IIC_STATE_IDLE,
-	IIC_STATE_START,
-	IIC_STATE_READ,
-	IIC_STATE_WRITE,
-	IIC_STATE_STOP
-};
-
-struct p2m_desc {
-	u32 ctrl;
-	u32 ext;
-	u32 ta;
-	u32 fa;
-};
-
-struct solo_p2m_dev {
-	struct mutex		mutex;
-	struct completion	completion;
-	int			error;
-};
-
-#define OSD_TEXT_MAX		30
-
-enum solo_enc_types {
-	SOLO_ENC_TYPE_STD,
-	SOLO_ENC_TYPE_EXT,
-};
-
-struct solo_enc_dev {
-	struct solo6010_dev	*solo_dev;
-	/* V4L2 Items */
-	struct video_device	*vfd;
-	/* General accounting */
-	wait_queue_head_t	thread_wait;
-	spinlock_t		lock;
-	atomic_t		readers;
-	u8			ch;
-	u8			mode, gop, qp, interlaced, interval;
-	u8			reset_gop;
-	u8			bw_weight;
-	u8			motion_detected;
-	u16			motion_thresh;
-	u16			width;
-	u16			height;
-	char			osd_text[OSD_TEXT_MAX + 1];
-};
-
-struct solo_enc_buf {
-	u8			vop;
-	u8			ch;
-	enum solo_enc_types	type;
-	u32			off;
-	u32			size;
-	u32			jpeg_off;
-	u32			jpeg_size;
-	struct timeval		ts;
-};
-
-/* The SOLO6010 PCI Device */
-struct solo6010_dev {
-	/* General stuff */
-	struct pci_dev		*pdev;
-	u8 __iomem		*reg_base;
-	int			nr_chans;
-	int			nr_ext;
-	u32			irq_mask;
-	u32			motion_mask;
-	spinlock_t		reg_io_lock;
-
-	/* tw28xx accounting */
-	u8			tw2865, tw2864, tw2815;
-	u8			tw28_cnt;
-
-	/* i2c related items */
-	struct i2c_adapter	i2c_adap[SOLO_I2C_ADAPTERS];
-	enum SOLO_I2C_STATE	i2c_state;
-	struct mutex		i2c_mutex;
-	int			i2c_id;
-	wait_queue_head_t	i2c_wait;
-	struct i2c_msg		*i2c_msg;
-	unsigned int		i2c_msg_num;
-	unsigned int		i2c_msg_ptr;
-
-	/* P2M DMA Engine */
-	struct solo_p2m_dev	p2m_dev[SOLO_NR_P2M];
-
-	/* V4L2 Display items */
-	struct video_device	*vfd;
-	unsigned int		erasing;
-	unsigned int		frame_blank;
-	u8			cur_disp_ch;
-	wait_queue_head_t	disp_thread_wait;
-
-	/* 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;
-	u16			video_hsize, video_vsize;
-	u16			vout_hstart, vout_vstart;
-	u16			vin_hstart, vin_vstart;
-	u8			fps;
-
-	/* Audio components */
-	struct snd_card		*snd_card;
-	struct snd_pcm		*snd_pcm;
-	atomic_t		snd_users;
-	int			g723_hw_idx;
-};
-
-static inline u32 solo_reg_read(struct solo6010_dev *solo_dev, int reg)
-{
-	unsigned long flags;
-	u32 ret;
-	u16 val;
-
-	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
-
-	ret = readl(solo_dev->reg_base + reg);
-	rmb();
-	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
-	rmb();
-
-	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
-
-	return ret;
-}
-
-static inline void solo_reg_write(struct solo6010_dev *solo_dev, int reg,
-				      u32 data)
-{
-	unsigned long flags;
-	u16 val;
-
-	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
-
-	writel(data, solo_dev->reg_base + reg);
-	wmb();
-	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
-	rmb();
-
-	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
-}
-
-void solo6010_irq_on(struct solo6010_dev *solo_dev, u32 mask);
-void solo6010_irq_off(struct solo6010_dev *solo_dev, u32 mask);
-
-/* Init/exit routeines for subsystems */
-int solo_disp_init(struct solo6010_dev *solo_dev);
-void solo_disp_exit(struct solo6010_dev *solo_dev);
-
-int solo_gpio_init(struct solo6010_dev *solo_dev);
-void solo_gpio_exit(struct solo6010_dev *solo_dev);
-
-int solo_i2c_init(struct solo6010_dev *solo_dev);
-void solo_i2c_exit(struct solo6010_dev *solo_dev);
-
-int solo_p2m_init(struct solo6010_dev *solo_dev);
-void solo_p2m_exit(struct solo6010_dev *solo_dev);
-
-int solo_v4l2_init(struct solo6010_dev *solo_dev);
-void solo_v4l2_exit(struct solo6010_dev *solo_dev);
-
-int solo_enc_init(struct solo6010_dev *solo_dev);
-void solo_enc_exit(struct solo6010_dev *solo_dev);
-
-int solo_enc_v4l2_init(struct solo6010_dev *solo_dev);
-void solo_enc_v4l2_exit(struct solo6010_dev *solo_dev);
-
-int solo_g723_init(struct solo6010_dev *solo_dev);
-void solo_g723_exit(struct solo6010_dev *solo_dev);
-
-/* ISR's */
-int solo_i2c_isr(struct solo6010_dev *solo_dev);
-void solo_p2m_isr(struct solo6010_dev *solo_dev, int id);
-void solo_p2m_error_isr(struct solo6010_dev *solo_dev, u32 status);
-void solo_enc_v4l2_isr(struct solo6010_dev *solo_dev);
-void solo_g723_isr(struct solo6010_dev *solo_dev);
-void solo_motion_isr(struct solo6010_dev *solo_dev);
-void solo_video_in_isr(struct solo6010_dev *solo_dev);
-
-/* i2c read/write */
-u8 solo_i2c_readbyte(struct solo6010_dev *solo_dev, int id, u8 addr, u8 off);
-void solo_i2c_writebyte(struct solo6010_dev *solo_dev, int id, u8 addr, u8 off,
-			u8 data);
-
-/* P2M DMA */
-int solo_p2m_dma_t(struct solo6010_dev *solo_dev, u8 id, int wr,
-		   dma_addr_t dma_addr, u32 ext_addr, u32 size);
-int solo_p2m_dma(struct solo6010_dev *solo_dev, u8 id, int wr,
-		 void *sys_addr, u32 ext_addr, u32 size);
-int solo_p2m_dma_sg(struct solo6010_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 solo6010_dev *solo_dev, u8 id,
-		      struct p2m_desc *desc, int desc_count);
-
-/* Set the threshold for motion detection */
-void solo_set_motion_threshold(struct solo6010_dev *solo_dev, u8 ch, u16 val);
-#define SOLO_DEF_MOT_THRESH		0x0300
-
-/* Write text on OSD */
-int solo_osd_print(struct solo_enc_dev *solo_enc);
-
-#endif /* __SOLO6010_H */
diff --git a/drivers/staging/solo6x10/solo6x10.h b/drivers/staging/solo6x10/solo6x10.h
new file mode 100644
index 0000000..fd59b09
--- /dev/null
+++ b/drivers/staging/solo6x10/solo6x10.h
@@ -0,0 +1,335 @@
+/*
+ * 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_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 <asm/io.h>
+#include <asm/atomic.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-dev.h>
+#include <media/videobuf-core.h>
+#include "registers.h"
+
+#ifndef PCI_VENDOR_ID_SOFTLOGIC
+#define PCI_VENDOR_ID_SOFTLOGIC		0x9413
+#define PCI_DEVICE_ID_SOLO6010		0x6010
+#define PCI_DEVICE_ID_SOLO6110		0x6110
+#endif
+
+#ifndef PCI_VENDOR_ID_BLUECHERRY
+#define PCI_VENDOR_ID_BLUECHERRY	0x1BB3
+/* Neugent Softlogic 6010 based cards */
+#define PCI_DEVICE_ID_NEUSOLO_4		0x4304
+#define PCI_DEVICE_ID_NEUSOLO_9		0x4309
+#define PCI_DEVICE_ID_NEUSOLO_16	0x4310
+/* Bluecherry Softlogic 6010 based cards */
+#define PCI_DEVICE_ID_BC_SOLO_4		0x4E04
+#define PCI_DEVICE_ID_BC_SOLO_9		0x4E09
+#define PCI_DEVICE_ID_BC_SOLO_16	0x4E10
+/* Bluecherry Softlogic 6110 based cards */
+#define PCI_DEVICE_ID_BC_6110_4		0x5304
+#define PCI_DEVICE_ID_BC_6110_8		0x5308
+#define PCI_DEVICE_ID_BC_6110_16	0x5310
+#endif /* Bluecherry */
+
+#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
+
+/*
+ * The SOLO6x10 actually has 8 i2c channels, but we only use 2.
+ * 0 - Techwell chip(s)
+ * 1 - SAA7128
+ */
+#define SOLO_I2C_ADAPTERS		2
+#define SOLO_I2C_TW			0
+#define SOLO_I2C_SAA			1
+
+/* 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
+
+/* Encoder standard modes */
+#define SOLO_ENC_MODE_CIF		2
+#define SOLO_ENC_MODE_HD1		1
+#define SOLO_ENC_MODE_D1		9
+
+#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)
+#endif
+
+enum SOLO_I2C_STATE {
+	IIC_STATE_IDLE,
+	IIC_STATE_START,
+	IIC_STATE_READ,
+	IIC_STATE_WRITE,
+	IIC_STATE_STOP
+};
+
+struct p2m_desc {
+	u32 ctrl;
+	u32 ext;
+	u32 ta;
+	u32 fa;
+};
+
+struct solo_p2m_dev {
+	struct mutex		mutex;
+	struct completion	completion;
+	int			error;
+};
+
+#define OSD_TEXT_MAX		30
+
+enum solo_enc_types {
+	SOLO_ENC_TYPE_STD,
+	SOLO_ENC_TYPE_EXT,
+};
+
+struct solo_enc_dev {
+	struct solo_dev		*solo_dev;
+	/* V4L2 Items */
+	struct video_device	*vfd;
+	/* General accounting */
+	wait_queue_head_t	thread_wait;
+	spinlock_t		lock;
+	atomic_t		readers;
+	u8			ch;
+	u8			mode, gop, qp, interlaced, interval;
+	u8			reset_gop;
+	u8			bw_weight;
+	u8			motion_detected;
+	u16			motion_thresh;
+	u16			width;
+	u16			height;
+	char			osd_text[OSD_TEXT_MAX + 1];
+};
+
+struct solo_enc_buf {
+	u8			vop;
+	u8			ch;
+	enum solo_enc_types	type;
+	u32			off;
+	u32			size;
+	u32			jpeg_off;
+	u32			jpeg_size;
+	struct timeval		ts;
+};
+
+/* The SOLO6x10 PCI Device */
+struct solo_dev {
+	/* General stuff */
+	struct pci_dev		*pdev;
+	u8 __iomem		*reg_base;
+	int			nr_chans;
+	int			nr_ext;
+	u32			flags;
+	u32			irq_mask;
+	u32			motion_mask;
+	spinlock_t		reg_io_lock;
+
+	/* tw28xx accounting */
+	u8			tw2865, tw2864, tw2815;
+	u8			tw28_cnt;
+
+	/* i2c related items */
+	struct i2c_adapter	i2c_adap[SOLO_I2C_ADAPTERS];
+	enum SOLO_I2C_STATE	i2c_state;
+	struct mutex		i2c_mutex;
+	int			i2c_id;
+	wait_queue_head_t	i2c_wait;
+	struct i2c_msg		*i2c_msg;
+	unsigned int		i2c_msg_num;
+	unsigned int		i2c_msg_ptr;
+
+	/* P2M DMA Engine */
+	struct solo_p2m_dev	p2m_dev[SOLO_NR_P2M];
+
+	/* V4L2 Display items */
+	struct video_device	*vfd;
+	unsigned int		erasing;
+	unsigned int		frame_blank;
+	u8			cur_disp_ch;
+	wait_queue_head_t	disp_thread_wait;
+
+	/* 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;
+	u16			video_hsize, video_vsize;
+	u16			vout_hstart, vout_vstart;
+	u16			vin_hstart, vin_vstart;
+	u8			fps;
+
+	/* Audio components */
+	struct snd_card		*snd_card;
+	struct snd_pcm		*snd_pcm;
+	atomic_t		snd_users;
+	int			g723_hw_idx;
+};
+
+static inline u32 solo_reg_read(struct solo_dev *solo_dev, int reg)
+{
+	unsigned long flags;
+	u32 ret;
+	u16 val;
+
+	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
+
+	ret = readl(solo_dev->reg_base + reg);
+	rmb();
+	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
+	rmb();
+
+	spin_unlock_irqrestore(&solo_dev->reg_io_lock, flags);
+
+	return ret;
+}
+
+static inline void solo_reg_write(struct solo_dev *solo_dev, int reg, u32 data)
+{
+	unsigned long flags;
+	u16 val;
+
+	spin_lock_irqsave(&solo_dev->reg_io_lock, flags);
+
+	writel(data, solo_dev->reg_base + reg);
+	wmb();
+	pci_read_config_word(solo_dev->pdev, PCI_STATUS, &val);
+	rmb();
+
+	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);
+
+/* Init/exit routeines for subsystems */
+int solo_disp_init(struct solo_dev *solo_dev);
+void solo_disp_exit(struct solo_dev *solo_dev);
+
+int solo_gpio_init(struct solo_dev *solo_dev);
+void solo_gpio_exit(struct solo_dev *solo_dev);
+
+int solo_i2c_init(struct solo_dev *solo_dev);
+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);
+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);
+void solo_enc_v4l2_exit(struct solo_dev *solo_dev);
+
+int solo_g723_init(struct solo_dev *solo_dev);
+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_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);
+void solo_video_in_isr(struct solo_dev *solo_dev);
+
+/* i2c read/write */
+u8 solo_i2c_readbyte(struct solo_dev *solo_dev, int id, u8 addr, u8 off);
+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);
+
+/* Set the threshold for motion detection */
+void solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
+#define SOLO_DEF_MOT_THRESH		0x0300
+
+/* Write text on OSD */
+int solo_osd_print(struct solo_enc_dev *solo_enc);
+
+#endif /* __SOLO6X10_H */
diff --git a/drivers/staging/solo6x10/tw28.c b/drivers/staging/solo6x10/tw28.c
new file mode 100644
index 0000000..db56b42
--- /dev/null
+++ b/drivers/staging/solo6x10/tw28.c
@@ -0,0 +1,821 @@
+/*
+ * 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/solo6x10/tw28.h b/drivers/staging/solo6x10/tw28.h
new file mode 100644
index 0000000..a44a03a
--- /dev/null
+++ b/drivers/staging/solo6x10/tw28.h
@@ -0,0 +1,63 @@
+/*
+ * 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/solo6x10/v4l2-enc.c b/drivers/staging/solo6x10/v4l2-enc.c
new file mode 100644
index 0000000..bee7280
--- /dev/null
+++ b/drivers/staging/solo6x10/v4l2-enc.c
@@ -0,0 +1,1825 @@
+/*
+ * 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 "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);
+			}
+			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);
+			}
+			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/solo6x10/v4l2.c b/drivers/staging/solo6x10/v4l2.c
new file mode 100644
index 0000000..571c3a3
--- /dev/null
+++ b/drivers/staging/solo6x10/v4l2.c
@@ -0,0 +1,964 @@
+/*
+ * 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");
+
+	if (IS_ERR(fh->kthread))
+		return PTR_ERR(fh->kthread);
+
+	return 0;
+}
+
+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/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c
index 236f06d..23cf7f4 100644
--- a/drivers/staging/speakup/keyhelp.c
+++ b/drivers/staging/speakup/keyhelp.c
@@ -161,7 +161,9 @@ int handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key)
 		}
 	cur_item = letter_offsets[ch-'a'];
 	} else if (type == KT_CUR) {
-		if (ch == 0 && (cur_item + 1) <= MSG_FUNCNAMES_END)
+		if (ch == 0
+		    && (MSG_FUNCNAMES_START + cur_item + 1) <=
+		    MSG_FUNCNAMES_END)
 			cur_item++;
 		else if (ch == 3 && cur_item > 0)
 			cur_item--;
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 3cd0039..42fcf7e 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -1283,7 +1283,7 @@ static int edit_bits(struct vc_data *vc, u_char type, u_char ch, u_short key)
 }
 
 /* Allocation concurrency is protected by the console semaphore */
-void speakup_allocate(struct vc_data *vc)
+int speakup_allocate(struct vc_data *vc)
 {
 	int vc_num;
 
@@ -1292,10 +1292,12 @@ void speakup_allocate(struct vc_data *vc)
 		speakup_console[vc_num] = kzalloc(sizeof(*speakup_console[0]),
 						  GFP_ATOMIC);
 		if (speakup_console[vc_num] == NULL)
-			return;
+			return -ENOMEM;
 		speakup_date(vc);
 	} else if (!spk_parked)
 		speakup_date(vc);
+
+	return 0;
 }
 
 void speakup_deallocate(struct vc_data *vc)
@@ -1303,10 +1305,8 @@ void speakup_deallocate(struct vc_data *vc)
 	int vc_num;
 
 	vc_num = vc->vc_num;
-	if (speakup_console[vc_num] != NULL) {
-		kfree(speakup_console[vc_num]);
-		speakup_console[vc_num] = NULL;
-	}
+	kfree(speakup_console[vc_num]);
+	speakup_console[vc_num] = NULL;
 }
 
 static u_char is_cursor;
@@ -2217,18 +2217,23 @@ static void __exit speakup_exit(void)
 {
 	int i;
 
-	free_user_msgs();
 	unregister_keyboard_notifier(&keyboard_notifier_block);
 	unregister_vt_notifier(&vt_notifier_block);
 	speakup_unregister_devsynth();
 	del_timer(&cursor_timer);
-
 	kthread_stop(speakup_task);
 	speakup_task = NULL;
 	mutex_lock(&spk_mutex);
 	synth_release();
 	mutex_unlock(&spk_mutex);
 
+	speakup_kobj_exit();
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		kfree(speakup_console[i]);
+
+	speakup_remove_virtual_keyboard();
+
 	for (i = 0; i < MAXVARS; i++)
 		speakup_unregister_var(i);
 
@@ -2236,42 +2241,23 @@ static void __exit speakup_exit(void)
 		if (characters[i] != default_chars[i])
 			kfree(characters[i]);
 	}
-	for (i = 0; speakup_console[i]; i++)
-		kfree(speakup_console[i]);
-	speakup_kobj_exit();
-	speakup_remove_virtual_keyboard();
+
+	free_user_msgs();
 }
 
 /* call by: module_init() */
 static int __init speakup_init(void)
 {
 	int i;
-	int err;
+	long err = 0;
 	struct st_spk_t *first_console;
 	struct vc_data *vc = vc_cons[fg_console].d;
 	struct var_t *var;
 
-	err = speakup_add_virtual_keyboard();
-	if (err)
-		goto out;
-
+	/* These first few initializations cannot fail. */
 	initialize_msgs();	/* Initialize arrays for i18n. */
-	first_console = kzalloc(sizeof(*first_console), GFP_KERNEL);
-	if (!first_console) {
-		err = -ENOMEM;
-		goto err_cons;
-	}
-	err = speakup_kobj_init();
-	if (err)
-		goto err_kobject;
-
 	reset_default_chars();
 	reset_default_chartab();
-
-	speakup_console[vc->vc_num] = first_console;
-	speakup_date(vc);
-	pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
-
 	strlwr(synth_name);
 	spk_vars[0].u.n.high = vc->vc_cols;
 	for (var = spk_vars; var->var_id != MAXVARS; var++)
@@ -2286,31 +2272,92 @@ static int __init speakup_init(void)
 	if (quiet_boot)
 		spk_shut_up |= 0x01;
 
+	/* From here on out, initializations can fail. */
+	err = speakup_add_virtual_keyboard();
+	if (err)
+		goto error_virtkeyboard;
+
+	first_console = kzalloc(sizeof(*first_console), GFP_KERNEL);
+	if (!first_console) {
+		err = -ENOMEM;
+		goto error_alloc;
+	}
+
+	speakup_console[vc->vc_num] = first_console;
+	speakup_date(vc);
+
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
-		if (vc_cons[i].d)
-			speakup_allocate(vc_cons[i].d);
+		if (vc_cons[i].d) {
+			err = speakup_allocate(vc_cons[i].d);
+			if (err)
+				goto error_kobjects;
+		}
+
+	err = speakup_kobj_init();
+	if (err)
+		goto error_kobjects;
 
-	pr_warn("synth name on entry is: %s\n", synth_name);
 	synth_init(synth_name);
 	speakup_register_devsynth();
+	/*
+	 * register_devsynth might fail, but this error is not fatal.
+	 * /dev/synth is an extra feature; the rest of Speakup
+	 * will work fine without it.
+	 */
 
-	register_keyboard_notifier(&keyboard_notifier_block);
-	register_vt_notifier(&vt_notifier_block);
+	err = register_keyboard_notifier(&keyboard_notifier_block);
+	if (err)
+		goto error_kbdnotifier;
+	err = register_vt_notifier(&vt_notifier_block);
+	if (err)
+		goto error_vtnotifier;
 
 	speakup_task = kthread_create(speakup_thread, NULL, "speakup");
-	set_user_nice(speakup_task, 10);
+
 	if (IS_ERR(speakup_task)) {
-		err = -ENOMEM;
-		goto err_kobject;
+		err = PTR_ERR(speakup_task);
+		goto error_task;
 	}
+
+	set_user_nice(speakup_task, 10);
 	wake_up_process(speakup_task);
+
+	pr_info("speakup %s: initialized\n", SPEAKUP_VERSION);
+	pr_info("synth name on entry is: %s\n", synth_name);
 	goto out;
 
-err_kobject:
-speakup_kobj_exit();
-	kfree(first_console);
-err_cons:
+error_task:
+	unregister_vt_notifier(&vt_notifier_block);
+
+error_vtnotifier:
+	unregister_keyboard_notifier(&keyboard_notifier_block);
+	del_timer(&cursor_timer);
+
+error_kbdnotifier:
+	speakup_unregister_devsynth();
+	mutex_lock(&spk_mutex);
+	synth_release();
+	mutex_unlock(&spk_mutex);
+	speakup_kobj_exit();
+
+error_kobjects:
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		kfree(speakup_console[i]);
+
+error_alloc:
 	speakup_remove_virtual_keyboard();
+
+error_virtkeyboard:
+	for (i = 0; i < MAXVARS; i++)
+		speakup_unregister_var(i);
+
+	for (i = 0; i < 256; i++) {
+		if (characters[i] != default_chars[i])
+			kfree(characters[i]);
+	}
+
+	free_user_msgs();
+
 out:
 	return err;
 }
diff --git a/drivers/staging/speakup/spk_priv_keyinfo.h b/drivers/staging/speakup/spk_priv_keyinfo.h
index 3fd4b82..95c473a 100644
--- a/drivers/staging/speakup/spk_priv_keyinfo.h
+++ b/drivers/staging/speakup/spk_priv_keyinfo.h
@@ -84,27 +84,27 @@
 
 /* keys for setting variables, must be ordered same as the enum for var_ids */
 /* with dec being even and inc being 1 greater */
-#define SPELL_DELAY_DEC VAR_START+0
-#define SPELL_DELAY_INC SPELL_DELAY_DEC+1
-#define PUNC_LEVEL_DEC SPELL_DELAY_DEC+2
-#define PUNC_LEVEL_INC PUNC_LEVEL_DEC+1
-#define READING_PUNC_DEC PUNC_LEVEL_DEC+2
-#define READING_PUNC_INC READING_PUNC_DEC+1
-#define ATTRIB_BLEEP_DEC READING_PUNC_DEC+2
-#define ATTRIB_BLEEP_INC ATTRIB_BLEEP_DEC+1
-#define BLEEPS_DEC ATTRIB_BLEEP_DEC+2
-#define BLEEPS_INC BLEEPS_DEC+1
-#define RATE_DEC BLEEPS_DEC+2
-#define RATE_INC RATE_DEC+1
-#define PITCH_DEC RATE_DEC+2
-#define PITCH_INC PITCH_DEC+1
-#define VOL_DEC PITCH_DEC+2
-#define VOL_INC VOL_DEC+1
-#define TONE_DEC VOL_DEC+2
-#define TONE_INC TONE_DEC+1
-#define PUNCT_DEC TONE_DEC+2
-#define PUNCT_INC PUNCT_DEC+1
-#define VOICE_DEC PUNCT_DEC+2
-#define VOICE_INC VOICE_DEC+1
+#define SPELL_DELAY_DEC (VAR_START+0)
+#define SPELL_DELAY_INC (SPELL_DELAY_DEC+1)
+#define PUNC_LEVEL_DEC (SPELL_DELAY_DEC+2)
+#define PUNC_LEVEL_INC (PUNC_LEVEL_DEC+1)
+#define READING_PUNC_DEC (PUNC_LEVEL_DEC+2)
+#define READING_PUNC_INC (READING_PUNC_DEC+1)
+#define ATTRIB_BLEEP_DEC (READING_PUNC_DEC+2)
+#define ATTRIB_BLEEP_INC (ATTRIB_BLEEP_DEC+1)
+#define BLEEPS_DEC (ATTRIB_BLEEP_DEC+2)
+#define BLEEPS_INC (BLEEPS_DEC+1)
+#define RATE_DEC (BLEEPS_DEC+2)
+#define RATE_INC (RATE_DEC+1)
+#define PITCH_DEC (RATE_DEC+2)
+#define PITCH_INC (PITCH_DEC+1)
+#define VOL_DEC (PITCH_DEC+2)
+#define VOL_INC (VOL_DEC+1)
+#define TONE_DEC (VOL_DEC+2)
+#define TONE_INC (TONE_DEC+1)
+#define PUNCT_DEC (TONE_DEC+2)
+#define PUNCT_INC (PUNCT_DEC+1)
+#define VOICE_DEC (PUNCT_DEC+2)
+#define VOICE_INC (VOICE_DEC+1)
 
 #endif
diff --git a/drivers/staging/speakup/spk_types.h b/drivers/staging/speakup/spk_types.h
index d36c90e..3ac552c 100644
--- a/drivers/staging/speakup/spk_types.h
+++ b/drivers/staging/speakup/spk_types.h
@@ -79,14 +79,14 @@ struct st_spk_t {
 };
 
 /* now some defines to make these easier to use. */
-#define spk_shut_up speakup_console[vc->vc_num]->shut_up
+#define spk_shut_up (speakup_console[vc->vc_num]->shut_up)
 #define spk_killed (speakup_console[vc->vc_num]->shut_up & 0x40)
-#define spk_x speakup_console[vc->vc_num]->reading_x
-#define spk_cx speakup_console[vc->vc_num]->cursor_x
-#define spk_y speakup_console[vc->vc_num]->reading_y
-#define spk_cy speakup_console[vc->vc_num]->cursor_y
+#define spk_x (speakup_console[vc->vc_num]->reading_x)
+#define spk_cx (speakup_console[vc->vc_num]->cursor_x)
+#define spk_y (speakup_console[vc->vc_num]->reading_y)
+#define spk_cy (speakup_console[vc->vc_num]->cursor_y)
 #define spk_pos (speakup_console[vc->vc_num]->reading_pos)
-#define spk_cp speakup_console[vc->vc_num]->cursor_pos
+#define spk_cp (speakup_console[vc->vc_num]->cursor_pos)
 #define goto_pos (speakup_console[vc->vc_num]->go_pos)
 #define goto_x (speakup_console[vc->vc_num]->go_x)
 #define win_top (speakup_console[vc->vc_num]->w_top)
@@ -95,9 +95,9 @@ struct st_spk_t {
 #define win_right (speakup_console[vc->vc_num]->w_right)
 #define win_start (speakup_console[vc->vc_num]->w_start)
 #define win_enabled (speakup_console[vc->vc_num]->w_enabled)
-#define spk_attr speakup_console[vc->vc_num]->reading_attr
-#define spk_old_attr speakup_console[vc->vc_num]->old_attr
-#define spk_parked speakup_console[vc->vc_num]->parked
+#define spk_attr (speakup_console[vc->vc_num]->reading_attr)
+#define spk_old_attr (speakup_console[vc->vc_num]->old_attr)
+#define spk_parked (speakup_console[vc->vc_num]->parked)
 
 struct st_var_header {
 	char *name;
diff --git a/drivers/staging/spectra/flash.c b/drivers/staging/spectra/flash.c
index fb39c8e..a2f8200 100644
--- a/drivers/staging/spectra/flash.c
+++ b/drivers/staging/spectra/flash.c
@@ -428,10 +428,9 @@ static int allocate_memory(void)
 		DeviceInfo.wPageDataSize;
 
 	/* Malloc memory for block tables */
-	g_pBlockTable = kmalloc(block_table_size, GFP_ATOMIC);
+	g_pBlockTable = kzalloc(block_table_size, GFP_ATOMIC);
 	if (!g_pBlockTable)
 		goto block_table_fail;
-	memset(g_pBlockTable, 0, block_table_size);
 	total_bytes += block_table_size;
 
 	g_pWearCounter = (u8 *)(g_pBlockTable +
@@ -447,19 +446,17 @@ static int allocate_memory(void)
 		Cache.array[i].address = NAND_CACHE_INIT_ADDR;
 		Cache.array[i].use_cnt = 0;
 		Cache.array[i].changed = CLEAR;
-		Cache.array[i].buf = kmalloc(Cache.cache_item_size,
-			GFP_ATOMIC);
+		Cache.array[i].buf = kzalloc(Cache.cache_item_size,
+					     GFP_ATOMIC);
 		if (!Cache.array[i].buf)
 			goto cache_item_fail;
-		memset(Cache.array[i].buf, 0, Cache.cache_item_size);
 		total_bytes += Cache.cache_item_size;
 	}
 
 	/* Malloc memory for IPF */
-	g_pIPF = kmalloc(page_size, GFP_ATOMIC);
+	g_pIPF = kzalloc(page_size, GFP_ATOMIC);
 	if (!g_pIPF)
 		goto ipf_fail;
-	memset(g_pIPF, 0, page_size);
 	total_bytes += page_size;
 
 	/* Malloc memory for data merging during Level2 Cache flush */
@@ -476,10 +473,9 @@ static int allocate_memory(void)
 	total_bytes += block_size;
 
 	/* Malloc memory for temp buffer */
-	g_pTempBuf = kmalloc(Cache.cache_item_size, GFP_ATOMIC);
+	g_pTempBuf = kzalloc(Cache.cache_item_size, GFP_ATOMIC);
 	if (!g_pTempBuf)
 		goto Temp_buf_fail;
-	memset(g_pTempBuf, 0, Cache.cache_item_size);
 	total_bytes += Cache.cache_item_size;
 
 	/* Malloc memory for block table blocks */
@@ -589,10 +585,9 @@ static int allocate_memory(void)
 	total_bytes += block_size;
 
 	/* Malloc memory for copy of block table used in CDMA mode */
-	g_pBTStartingCopy = kmalloc(block_table_size, GFP_ATOMIC);
+	g_pBTStartingCopy = kzalloc(block_table_size, GFP_ATOMIC);
 	if (!g_pBTStartingCopy)
 		goto bt_starting_copy;
-	memset(g_pBTStartingCopy, 0, block_table_size);
 	total_bytes += block_table_size;
 
 	g_pWearCounterCopy = (u8 *)(g_pBTStartingCopy +
@@ -608,28 +603,25 @@ static int allocate_memory(void)
 			5 * DeviceInfo.wDataBlockNum * sizeof(u8);
 	if (DeviceInfo.MLCDevice)
 		mem_size += 5 * DeviceInfo.wDataBlockNum * sizeof(u16);
-	g_pBlockTableCopies = kmalloc(mem_size, GFP_ATOMIC);
+	g_pBlockTableCopies = kzalloc(mem_size, GFP_ATOMIC);
 	if (!g_pBlockTableCopies)
 		goto blk_table_copies_fail;
-	memset(g_pBlockTableCopies, 0, mem_size);
 	total_bytes += mem_size;
 	g_pNextBlockTable = g_pBlockTableCopies;
 
 	/* Malloc memory for Block Table Delta */
 	mem_size = MAX_DESCS * sizeof(struct BTableChangesDelta);
-	g_pBTDelta = kmalloc(mem_size, GFP_ATOMIC);
+	g_pBTDelta = kzalloc(mem_size, GFP_ATOMIC);
 	if (!g_pBTDelta)
 		goto bt_delta_fail;
-	memset(g_pBTDelta, 0, mem_size);
 	total_bytes += mem_size;
 	g_pBTDelta_Free = g_pBTDelta;
 
 	/* Malloc memory for Copy Back Buffers */
 	for (j = 0; j < COPY_BACK_BUF_NUM; j++) {
-		cp_back_buf_copies[j] = kmalloc(block_size, GFP_ATOMIC);
+		cp_back_buf_copies[j] = kzalloc(block_size, GFP_ATOMIC);
 		if (!cp_back_buf_copies[j])
 			goto cp_back_buf_copies_fail;
-		memset(cp_back_buf_copies[j], 0, block_size);
 		total_bytes += block_size;
 	}
 	cp_back_buf_idx = 0;
@@ -3911,7 +3903,7 @@ int GLOB_FTL_Page_Write(u8 *pData, u64 dwPageAddr)
 * Description:  erases the specified block
 *               increments the erase count
 *               If erase count reaches its upper limit,call function to
-*               do the ajustment as per the relative erase count values
+*               do the adjustment as per the relative erase count values
 *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
 int GLOB_FTL_Block_Erase(u64 blk_addr)
 {
diff --git a/drivers/staging/spectra/lld_nand.c b/drivers/staging/spectra/lld_nand.c
index 2263d3e..0be7adc 100644
--- a/drivers/staging/spectra/lld_nand.c
+++ b/drivers/staging/spectra/lld_nand.c
@@ -1400,7 +1400,7 @@ void Conv_Spare_Data_Log2Phy_Format(u8 *data)
 	const u32 PageSpareSize  = DeviceInfo.wPageSpareSize;
 
 	if (enable_ecc) {
-		for (i = spareFlagBytes - 1; i >= 0; i++)
+		for (i = spareFlagBytes - 1; i >= 0; i--)
 			data[PageSpareSize - spareFlagBytes + i] = data[i];
 	}
 }
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 80183a7..d55a8e4 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -764,8 +764,10 @@ static int synaptics_rmi4_i2c_query_device(struct synaptics_rmi4_data *pdata)
 								(pdata,	rfi,
 								&rmi_fd,
 								intr_count);
-					if (retval < 0)
+					if (retval < 0) {
+						kfree(rfi);
 						return retval;
+					}
 				}
 				break;
 			}
@@ -924,10 +926,8 @@ static int __devinit synaptics_rmi4_probe
 		goto err_input;
 	}
 
-	dev_set_name(&client->dev, platformdata->name);
-
 	if (platformdata->regulator_en) {
-		rmi4_data->regulator = regulator_get(&client->dev, "v-touch");
+		rmi4_data->regulator = regulator_get(&client->dev, "vdd");
 		if (IS_ERR(rmi4_data->regulator)) {
 			dev_err(&client->dev, "%s:get regulator failed\n",
 								__func__);
@@ -993,11 +993,11 @@ static int __devinit synaptics_rmi4_probe
 	retval = request_threaded_irq(platformdata->irq_number, NULL,
 					synaptics_rmi4_irq,
 					platformdata->irq_type,
-					platformdata->name, rmi4_data);
+					DRIVER_NAME, rmi4_data);
 	if (retval) {
 		dev_err(&client->dev, "%s:Unable to get attn irq %d\n",
 				__func__, platformdata->irq_number);
-		goto err_unset_clientdata;
+		goto err_query_dev;
 	}
 
 	retval = input_register_device(rmi4_data->input_dev);
@@ -1010,8 +1010,6 @@ static int __devinit synaptics_rmi4_probe
 
 err_free_irq:
 	free_irq(platformdata->irq_number, rmi4_data);
-err_unset_clientdata:
-	i2c_set_clientdata(client, NULL);
 err_query_dev:
 	if (platformdata->regulator_en) {
 		regulator_disable(rmi4_data->regulator);
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
index 820ae27..3686a2f 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h
@@ -39,7 +39,6 @@
  * This structure gives platform data for rmi4.
  */
 struct synaptics_rmi4_platform_data {
-	const char *name;
 	int irq_number;
 	int irq_type;
 	bool x_flip;
diff --git a/drivers/staging/ti-st/Kconfig b/drivers/staging/ti-st/Kconfig
deleted file mode 100644
index 074b8e8..0000000
--- a/drivers/staging/ti-st/Kconfig
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# TI's shared transport line discipline and the protocol
-# drivers (BT, FM and GPS)
-#
-menu "Texas Instruments shared transport line discipline"
-config ST_BT
-	tristate "BlueZ bluetooth driver for ST"
-	depends on BT && RFKILL
-	select TI_ST
-	help
-	  This enables the Bluetooth driver for TI BT/FM/GPS combo devices.
-	  This makes use of shared transport line discipline core driver to
-	  communicate with the BT core of the combo chip.
-endmenu
diff --git a/drivers/staging/ti-st/Makefile b/drivers/staging/ti-st/Makefile
deleted file mode 100644
index 5f11b82..0000000
--- a/drivers/staging/ti-st/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for TI's shared transport line discipline
-# and its protocol drivers (BT, FM, GPS)
-#
-obj-$(CONFIG_ST_BT) 		+= bt_drv.o
diff --git a/drivers/staging/ti-st/TODO b/drivers/staging/ti-st/TODO
deleted file mode 100644
index ebfd6bb..0000000
--- a/drivers/staging/ti-st/TODO
+++ /dev/null
@@ -1,8 +0,0 @@
-TODO:
-
-1. Step up and maintain this driver to ensure that it continues
-to work.  Having the hardware for this is pretty much a
-requirement.  If this does not happen, the will be removed in
-the 2.6.35 kernel release.
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com>.
diff --git a/drivers/staging/ti-st/bt_drv.c b/drivers/staging/ti-st/bt_drv.c
deleted file mode 100644
index 75065bf..0000000
--- a/drivers/staging/ti-st/bt_drv.c
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- *  Texas Instrument's Bluetooth Driver For Shared Transport.
- *
- *  Bluetooth Driver acts as interface between HCI CORE and
- *  TI Shared Transport Layer.
- *
- *  Copyright (C) 2009 Texas Instruments
- *
- *  This program is free software; you can 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 <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-
-#include <linux/ti_wilink_st.h>
-#include "bt_drv.h"
-
-/* Define this macro to get debug msg */
-#undef DEBUG
-
-#ifdef DEBUG
-#define BT_DRV_DBG(fmt, arg...)  printk(KERN_INFO "(btdrv):"fmt"\n" , ## arg)
-#define BTDRV_API_START()        printk(KERN_INFO "(btdrv): %s Start\n", \
-	__func__)
-#define BTDRV_API_EXIT(errno)    printk(KERN_INFO "(btdrv): %s Exit(%d)\n", \
-	__func__, errno)
-#else
-#define BT_DRV_DBG(fmt, arg...)
-#define BTDRV_API_START()
-#define BTDRV_API_EXIT(errno)
-#endif
-
-#define BT_DRV_ERR(fmt, arg...)  printk(KERN_ERR "(btdrv):"fmt"\n" , ## arg)
-
-static int reset;
-static struct hci_st *hst;
-
-/* Increments HCI counters based on pocket ID (cmd,acl,sco) */
-static inline void hci_st_tx_complete(struct hci_st *hst, int pkt_type)
-{
-	struct hci_dev *hdev;
-
-	BTDRV_API_START();
-
-	hdev = hst->hdev;
-
-	/* Update HCI stat counters */
-	switch (pkt_type) {
-	case HCI_COMMAND_PKT:
-		hdev->stat.cmd_tx++;
-		break;
-
-	case HCI_ACLDATA_PKT:
-		hdev->stat.acl_tx++;
-		break;
-
-	case HCI_SCODATA_PKT:
-		hdev->stat.cmd_tx++;
-		break;
-	}
-
-	BTDRV_API_EXIT(0);
-}
-
-/* ------- Interfaces to Shared Transport ------ */
-
-/* Called by ST layer to indicate protocol registration completion
- * status.hci_st_open() function will wait for signal from this
- * API when st_register() function returns ST_PENDING.
- */
-static void hci_st_registration_completion_cb(void *priv_data, char data)
-{
-	struct hci_st *lhst = (struct hci_st *)priv_data;
-	BTDRV_API_START();
-
-	/* hci_st_open() function needs value of 'data' to know
-	 * the registration status(success/fail),So have a back
-	 * up of it.
-	 */
-	lhst->streg_cbdata = data;
-
-	/* Got a feedback from ST for BT driver registration
-	 * request.Wackup hci_st_open() function to continue
-	 * it's open operation.
-	 */
-	complete(&lhst->wait_for_btdrv_reg_completion);
-
-	BTDRV_API_EXIT(0);
-}
-
-/* Called by Shared Transport layer when receive data is
- * available */
-static long hci_st_receive(void *priv_data, struct sk_buff *skb)
-{
-	int err;
-	int len;
-	struct hci_st *lhst = (struct hci_st *)priv_data;
-
-	BTDRV_API_START();
-
-	err = 0;
-	len = 0;
-
-	if (skb == NULL) {
-		BT_DRV_ERR("Invalid SKB received from ST");
-		BTDRV_API_EXIT(-EFAULT);
-		return -EFAULT;
-	}
-	if (!lhst) {
-		kfree_skb(skb);
-		BT_DRV_ERR("Invalid hci_st memory,freeing SKB");
-		BTDRV_API_EXIT(-EFAULT);
-		return -EFAULT;
-	}
-	if (!test_bit(BT_DRV_RUNNING, &lhst->flags)) {
-		kfree_skb(skb);
-		BT_DRV_ERR("Device is not running,freeing SKB");
-		BTDRV_API_EXIT(-EINVAL);
-		return -EINVAL;
-	}
-
-	len = skb->len;
-	skb->dev = (struct net_device *)lhst->hdev;
-
-	/* Forward skb to HCI CORE layer */
-	err = hci_recv_frame(skb);
-	if (err) {
-		kfree_skb(skb);
-		BT_DRV_ERR("Unable to push skb to HCI CORE(%d),freeing SKB",
-			   err);
-		BTDRV_API_EXIT(err);
-		return err;
-	}
-	lhst->hdev->stat.byte_rx += len;
-
-	BTDRV_API_EXIT(0);
-	return 0;
-}
-
-/* ------- Interfaces to HCI layer ------ */
-
-/* Called from HCI core to initialize the device */
-static int hci_st_open(struct hci_dev *hdev)
-{
-	static struct st_proto_s hci_st_proto;
-	unsigned long timeleft;
-	int err;
-
-	BTDRV_API_START();
-
-	err = 0;
-
-	BT_DRV_DBG("%s %p", hdev->name, hdev);
-
-	/* Already registered with ST ? */
-	if (test_bit(BT_ST_REGISTERED, &hst->flags)) {
-		BT_DRV_ERR("Registered with ST already,open called again?");
-		BTDRV_API_EXIT(0);
-		return 0;
-	}
-
-	/* Populate BT driver info required by ST */
-	memset(&hci_st_proto, 0, sizeof(hci_st_proto));
-
-	/* BT driver ID */
-	hci_st_proto.type = ST_BT;
-
-	/* Receive function which called from ST */
-	hci_st_proto.recv = hci_st_receive;
-
-	/* Packet match function may used in future */
-	hci_st_proto.match_packet = NULL;
-
-	/* Callback to be called when registration is pending */
-	hci_st_proto.reg_complete_cb = hci_st_registration_completion_cb;
-
-	/* This is write function pointer of ST. BT driver will make use of this
-	 * for sending any packets to chip. ST will assign and give to us, so
-	 * make it as NULL */
-	hci_st_proto.write = NULL;
-
-	/* send in the hst to be received at registration complete callback
-	 * and during st's receive
-	 */
-	hci_st_proto.priv_data = hst;
-
-	/* Register with ST layer */
-	err = st_register(&hci_st_proto);
-	if (err == -EINPROGRESS) {
-		/* Prepare wait-for-completion handler data structures.
-		 * Needed to syncronize this and st_registration_completion_cb()
-		 * functions.
-		 */
-		init_completion(&hst->wait_for_btdrv_reg_completion);
-
-		/* Reset ST registration callback status flag , this value
-		 * will be updated in hci_st_registration_completion_cb()
-		 * function whenever it called from ST driver.
-		 */
-		hst->streg_cbdata = -EINPROGRESS;
-
-		/* ST is busy with other protocol registration(may be busy with
-		 * firmware download).So,Wait till the registration callback
-		 * (passed as a argument to st_register() function) getting
-		 * called from ST.
-		 */
-		BT_DRV_DBG(" %s waiting for reg completion signal from ST",
-			   __func__);
-
-		timeleft =
-		    wait_for_completion_timeout
-		    (&hst->wait_for_btdrv_reg_completion,
-		     msecs_to_jiffies(BT_REGISTER_TIMEOUT));
-		if (!timeleft) {
-			BT_DRV_ERR("Timeout(%ld sec),didn't get reg"
-				   "completion signal from ST",
-				   BT_REGISTER_TIMEOUT / 1000);
-			BTDRV_API_EXIT(-ETIMEDOUT);
-			return -ETIMEDOUT;
-		}
-
-		/* Is ST registration callback called with ERROR value? */
-		if (hst->streg_cbdata != 0) {
-			BT_DRV_ERR("ST reg completion CB called with invalid"
-				   "status %d", hst->streg_cbdata);
-			BTDRV_API_EXIT(-EAGAIN);
-			return -EAGAIN;
-		}
-		err = 0;
-	} else if (err == -1) {
-		BT_DRV_ERR("st_register failed %d", err);
-		BTDRV_API_EXIT(-EAGAIN);
-		return -EAGAIN;
-	}
-
-	/* Do we have proper ST write function? */
-	if (hci_st_proto.write != NULL) {
-		/* We need this pointer for sending any Bluetooth pkts */
-		hst->st_write = hci_st_proto.write;
-	} else {
-		BT_DRV_ERR("failed to get ST write func pointer");
-
-		/* Undo registration with ST */
-		err = st_unregister(ST_BT);
-		if (err < 0)
-			BT_DRV_ERR("st_unregister failed %d", err);
-
-		hst->st_write = NULL;
-		BTDRV_API_EXIT(-EAGAIN);
-		return -EAGAIN;
-	}
-
-	/* Registration with ST layer is completed successfully,
-	 * now chip is ready to accept commands from HCI CORE.
-	 * Mark HCI Device flag as RUNNING
-	 */
-	set_bit(HCI_RUNNING, &hdev->flags);
-
-	/* Registration with ST successful */
-	set_bit(BT_ST_REGISTERED, &hst->flags);
-
-	BTDRV_API_EXIT(err);
-	return err;
-}
-
-/* Close device */
-static int hci_st_close(struct hci_dev *hdev)
-{
-	int err;
-
-	BTDRV_API_START();
-
-	err = 0;
-
-	/* Unregister from ST layer */
-	if (test_and_clear_bit(BT_ST_REGISTERED, &hst->flags)) {
-		err = st_unregister(ST_BT);
-		if (err != 0) {
-			BT_DRV_ERR("st_unregister failed %d", err);
-			BTDRV_API_EXIT(-EBUSY);
-			return -EBUSY;
-		}
-	}
-
-	hst->st_write = NULL;
-
-	/* ST layer would have moved chip to inactive state.
-	 * So,clear HCI device RUNNING flag.
-	 */
-	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) {
-		BTDRV_API_EXIT(0);
-		return 0;
-	}
-
-	BTDRV_API_EXIT(err);
-	return err;
-}
-
-/* Called from HCI CORE , Sends frames to Shared Transport */
-static int hci_st_send_frame(struct sk_buff *skb)
-{
-	struct hci_dev *hdev;
-	struct hci_st *hst;
-	long len;
-
-	BTDRV_API_START();
-
-	if (skb == NULL) {
-		BT_DRV_ERR("Invalid skb received from HCI CORE");
-		BTDRV_API_EXIT(-ENOMEM);
-		return -ENOMEM;
-	}
-	hdev = (struct hci_dev *)skb->dev;
-	if (!hdev) {
-		BT_DRV_ERR("SKB received for invalid HCI Device (hdev=NULL)");
-		BTDRV_API_EXIT(-ENODEV);
-		return -ENODEV;
-	}
-	if (!test_bit(HCI_RUNNING, &hdev->flags)) {
-		BT_DRV_ERR("Device is not running");
-		BTDRV_API_EXIT(-EBUSY);
-		return -EBUSY;
-	}
-
-	hst = (struct hci_st *)hdev->driver_data;
-
-	/* Prepend skb with frame type */
-	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
-
-	BT_DRV_DBG(" %s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
-		   skb->len);
-
-	/* Insert skb to shared transport layer's transmit queue.
-	 * Freeing skb memory is taken care in shared transport layer,
-	 * so don't free skb memory here.
-	 */
-	if (!hst->st_write) {
-		kfree_skb(skb);
-		BT_DRV_ERR(" Can't write to ST, st_write null?");
-		BTDRV_API_EXIT(-EAGAIN);
-		return -EAGAIN;
-	}
-	len = hst->st_write(skb);
-	if (len < 0) {
-		/* Something went wrong in st write , free skb memory */
-		kfree_skb(skb);
-		BT_DRV_ERR(" ST write failed (%ld)", len);
-		BTDRV_API_EXIT(-EAGAIN);
-		return -EAGAIN;
-	}
-
-	/* ST accepted our skb. So, Go ahead and do rest */
-	hdev->stat.byte_tx += len;
-	hci_st_tx_complete(hst, bt_cb(skb)->pkt_type);
-
-	BTDRV_API_EXIT(0);
-	return 0;
-}
-
-static void hci_st_destruct(struct hci_dev *hdev)
-{
-	BTDRV_API_START();
-
-	if (!hdev) {
-		BT_DRV_ERR("Destruct called with invalid HCI Device"
-			   "(hdev=NULL)");
-		BTDRV_API_EXIT(0);
-		return;
-	}
-
-	BT_DRV_DBG("%s", hdev->name);
-
-	/* free hci_st memory */
-	if (hdev->driver_data != NULL)
-		kfree(hdev->driver_data);
-
-	BTDRV_API_EXIT(0);
-	return;
-}
-
-/* Creates new HCI device */
-static int hci_st_register_dev(struct hci_st *hst)
-{
-	struct hci_dev *hdev;
-
-	BTDRV_API_START();
-
-	/* Initialize and register HCI device */
-	hdev = hci_alloc_dev();
-	if (!hdev) {
-		BT_DRV_ERR("Can't allocate HCI device");
-		BTDRV_API_EXIT(-ENOMEM);
-		return -ENOMEM;
-	}
-	BT_DRV_DBG(" HCI device allocated. hdev= %p", hdev);
-
-	hst->hdev = hdev;
-	hdev->bus = HCI_UART;
-	hdev->driver_data = hst;
-	hdev->open = hci_st_open;
-	hdev->close = hci_st_close;
-	hdev->flush = NULL;
-	hdev->send = hci_st_send_frame;
-	hdev->destruct = hci_st_destruct;
-	hdev->owner = THIS_MODULE;
-
-	if (reset)
-		set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks);
-
-	if (hci_register_dev(hdev) < 0) {
-		BT_DRV_ERR("Can't register HCI device");
-		hci_free_dev(hdev);
-		BTDRV_API_EXIT(-ENODEV);
-		return -ENODEV;
-	}
-
-	BT_DRV_DBG(" HCI device registered. hdev= %p", hdev);
-	BTDRV_API_EXIT(0);
-	return 0;
-}
-
-/* ------- Module Init interface ------ */
-
-static int __init bt_drv_init(void)
-{
-	int err;
-
-	BTDRV_API_START();
-
-	err = 0;
-
-	BT_DRV_DBG(" Bluetooth Driver Version %s", VERSION);
-
-	/* Allocate local resource memory */
-	hst = kzalloc(sizeof(struct hci_st), GFP_KERNEL);
-	if (!hst) {
-		BT_DRV_ERR("Can't allocate control structure");
-		BTDRV_API_EXIT(-ENFILE);
-		return -ENFILE;
-	}
-
-	/* Expose "hciX" device to user space */
-	err = hci_st_register_dev(hst);
-	if (err) {
-		/* Release local resource memory */
-		kfree(hst);
-
-		BT_DRV_ERR("Unable to expose hci0 device(%d)", err);
-		BTDRV_API_EXIT(err);
-		return err;
-	}
-	set_bit(BT_DRV_RUNNING, &hst->flags);
-
-	BTDRV_API_EXIT(err);
-	return err;
-}
-
-/* ------- Module Exit interface ------ */
-
-static void __exit bt_drv_exit(void)
-{
-	BTDRV_API_START();
-
-	/* Deallocate local resource's memory  */
-	if (hst) {
-		struct hci_dev *hdev = hst->hdev;
-
-		if (hdev == NULL) {
-			BT_DRV_ERR("Invalid hdev memory");
-			kfree(hst);
-		} else {
-			hci_st_close(hdev);
-			if (test_and_clear_bit(BT_DRV_RUNNING, &hst->flags)) {
-				/* Remove HCI device (hciX) created
-				 * in module init.
-				 */
-				hci_unregister_dev(hdev);
-
-				/* Free HCI device memory */
-				hci_free_dev(hdev);
-			}
-		}
-	}
-	BTDRV_API_EXIT(0);
-}
-
-module_init(bt_drv_init);
-module_exit(bt_drv_exit);
-
-/* ------ Module Info ------ */
-
-module_param(reset, bool, 0644);
-MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
-MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");
-MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/ti-st/bt_drv.h b/drivers/staging/ti-st/bt_drv.h
deleted file mode 100644
index a0beebe..0000000
--- a/drivers/staging/ti-st/bt_drv.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Texas Instrument's Bluetooth Driver For Shared Transport.
- *
- *  Bluetooth Driver acts as interface between HCI CORE and
- *  TI Shared Transport Layer.
- *
- *  Copyright (C) 2009 Texas Instruments
- *
- *  This program is free software; you can 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 _BT_DRV_H
-#define _BT_DRV_H
-
-/* Bluetooth Driver Version */
-#define VERSION               "1.0"
-
-/* Defines number of seconds to wait for reg completion
- * callback getting called from ST (in case,registration
- * with ST returns PENDING status)
- */
-#define BT_REGISTER_TIMEOUT   msecs_to_jiffies(6000)	/* 6 sec */
-
-/* BT driver's local status */
-#define BT_DRV_RUNNING        0
-#define BT_ST_REGISTERED      1
-
-/* BT driver operation structure */
-struct hci_st {
-
-	/* hci device pointer which binds to bt driver */
-	struct hci_dev *hdev;
-
-	/* used locally,to maintain various BT driver status */
-	unsigned long flags;
-
-	/* to hold ST registration callback  status */
-	char streg_cbdata;
-
-	/* write function pointer of ST driver */
-	long (*st_write) (struct sk_buff *);
-
-	/* Wait on comepletion handler needed to synchronize
-	 * hci_st_open() and hci_st_registration_completion_cb()
-	 * functions.*/
-	struct completion wait_for_btdrv_reg_completion;
-};
-
-#endif
diff --git a/drivers/staging/ti-st/sysfs-uim b/drivers/staging/ti-st/sysfs-uim
deleted file mode 100644
index 626bda5..0000000
--- a/drivers/staging/ti-st/sysfs-uim
+++ /dev/null
@@ -1,28 +0,0 @@
-What:           /sys/class/rfkill/rfkill%d/
-Date:           March 22
-Contact:        Pavan Savoy <pavan_savoy@ti.com>
-Description:
-		Creates the rfkill entries for Radio apps like
-		BT app, FM app or GPS app to toggle corresponding
-		cores of the chip
-
-What:           /dev/rfkill
-Date:           March 22
-Contact:        Pavan Savoy <pavan_savoy@ti.com>
-Description:
-		A daemon which maintains the ldisc installation and
-		uninstallation would be ppolling on this device and listening
-		on events which would suggest either to install or un-install
-		line discipline
-
-What:           /sys/kernel/debug/ti-st/version
-Contact:        Pavan Savoy <pavan_savoy@ti.com>
-Description:
-		WiLink chip's ROM version exposed to user-space for some
-		proprietary protocol stacks to make use of.
-
-What:           /sys/kernel/debug/ti-st/protocols
-Contact:        Pavan Savoy <pavan_savoy@ti.com>
-Description:
-		The reason for chip being ON, the list of protocols registered.
-
diff --git a/drivers/staging/tidspbridge/Makefile b/drivers/staging/tidspbridge/Makefile
index 41c644c..fd6a276 100644
--- a/drivers/staging/tidspbridge/Makefile
+++ b/drivers/staging/tidspbridge/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_TIDSPBRIDGE)	+= bridgedriver.o
 
-libgen = gen/gb.o gen/gs.o gen/gh.o gen/uuidutil.o
+libgen = gen/gh.o gen/uuidutil.o
 libcore = core/chnl_sm.o core/msg_sm.o core/io_sm.o core/tiomap3430.o \
 		core/tiomap3430_pwr.o core/tiomap_io.o \
 		core/ue_deh.o core/wdt.o core/dsp-clock.o core/sync.o
diff --git a/drivers/staging/tidspbridge/TODO b/drivers/staging/tidspbridge/TODO
index 187363f..1c51e2d 100644
--- a/drivers/staging/tidspbridge/TODO
+++ b/drivers/staging/tidspbridge/TODO
@@ -6,7 +6,6 @@
 * Eliminate general services and libraries - use or extend existing kernel
   libraries instead (e.g. gcf/lcm in nldr.c, global helpers in gen/)
 * Eliminate direct manipulation of OMAP_SYSC_BASE
-* Eliminate list.h : seem like a redundant wrapper to existing kernel lists
 * Eliminate DSP_SUCCEEDED macros and their imposed redundant indentations
   (adopt the kernel way of checking for return values)
 * Audit interfaces exposed to user space
diff --git a/drivers/staging/tidspbridge/core/_deh.h b/drivers/staging/tidspbridge/core/_deh.h
index 16723cd..025d343 100644
--- a/drivers/staging/tidspbridge/core/_deh.h
+++ b/drivers/staging/tidspbridge/core/_deh.h
@@ -25,7 +25,7 @@
 
 /* DEH Manager: only one created per board: */
 struct deh_mgr {
-	struct bridge_dev_context *hbridge_context;	/* Bridge context. */
+	struct bridge_dev_context *bridge_context;	/* Bridge context. */
 	struct ntfy_object *ntfy_obj;	/* NTFY object */
 
 	/* MMU Fault DPC */
diff --git a/drivers/staging/tidspbridge/core/_msg_sm.h b/drivers/staging/tidspbridge/core/_msg_sm.h
index 556de5c..f6e58e3 100644
--- a/drivers/staging/tidspbridge/core/_msg_sm.h
+++ b/drivers/staging/tidspbridge/core/_msg_sm.h
@@ -20,7 +20,7 @@
 #ifndef _MSG_SM_
 #define _MSG_SM_
 
-#include <dspbridge/list.h>
+#include <linux/list.h>
 #include <dspbridge/msgdefs.h>
 
 /*
@@ -85,13 +85,13 @@ struct msg_mgr {
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
 
-	struct io_mgr *hio_mgr;	/* IO manager */
-	struct lst_list *queue_list;	/* List of MSG_QUEUEs */
+	struct io_mgr *iomgr;		/* IO manager */
+	struct list_head queue_list;	/* List of MSG_QUEUEs */
 	spinlock_t msg_mgr_lock;	/* For critical sections */
 	/* Signalled when MsgFrame is available */
 	struct sync_object *sync_event;
-	struct lst_list *msg_free_list;	/* Free MsgFrames ready to be filled */
-	struct lst_list *msg_used_list;	/* MsgFrames ready to go to DSP */
+	struct list_head msg_free_list;	/* Free MsgFrames ready to be filled */
+	struct list_head msg_used_list;	/* MsgFrames ready to go to DSP */
 	u32 msgs_pending;	/* # of queued messages to go to DSP */
 	u32 max_msgs;		/* Max # of msgs that fit in buffer */
 	msg_onexit on_exit;	/* called when RMS_EXIT is received */
@@ -108,12 +108,12 @@ struct msg_mgr {
  */
 struct msg_queue {
 	struct list_head list_elem;
-	struct msg_mgr *hmsg_mgr;
+	struct msg_mgr *msg_mgr;
 	u32 max_msgs;		/* Node message depth */
 	u32 msgq_id;		/* Node environment pointer */
-	struct lst_list *msg_free_list;	/* Free MsgFrames ready to be filled */
+	struct list_head msg_free_list;	/* Free MsgFrames ready to be filled */
 	/* Filled MsgFramess waiting to be read */
-	struct lst_list *msg_used_list;
+	struct list_head msg_used_list;
 	void *arg;		/* Handle passed to mgr on_exit callback */
 	struct sync_object *sync_event;	/* Signalled when message is ready */
 	struct sync_object *sync_done;	/* For synchronizing cleanup */
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h
index 1159a50..1e0273e 100644
--- a/drivers/staging/tidspbridge/core/_tiomap.h
+++ b/drivers/staging/tidspbridge/core/_tiomap.h
@@ -319,24 +319,24 @@ static const struct bpwr_clk_t bpwr_clks[] = {
 
 /* This Bridge driver's device context: */
 struct bridge_dev_context {
-	struct dev_object *hdev_obj;	/* Handle to Bridge device object. */
-	u32 dw_dsp_base_addr;	/* Arm's API to DSP virt base addr */
+	struct dev_object *dev_obj;	/* Handle to Bridge device object. */
+	u32 dsp_base_addr;	/* Arm's API to DSP virt base addr */
 	/*
 	 * DSP External memory prog address as seen virtually by the OS on
 	 * the host side.
 	 */
-	u32 dw_dsp_ext_base_addr;	/* See the comment above */
-	u32 dw_api_reg_base;	/* API mem map'd registers */
-	void __iomem *dw_dsp_mmu_base;	/* DSP MMU Mapped registers */
-	u32 dw_api_clk_base;	/* CLK Registers */
-	u32 dw_dsp_clk_m2_base;	/* DSP Clock Module m2 */
-	u32 dw_public_rhea;	/* Pub Rhea */
-	u32 dw_int_addr;	/* MB INTR reg */
-	u32 dw_tc_endianism;	/* TC Endianism register */
-	u32 dw_test_base;	/* DSP MMU Mapped registers */
-	u32 dw_self_loop;	/* Pointer to the selfloop */
-	u32 dw_dsp_start_add;	/* API Boot vector */
-	u32 dw_internal_size;	/* Internal memory size */
+	u32 dsp_ext_base_addr;	/* See the comment above */
+	u32 api_reg_base;	/* API mem map'd registers */
+	void __iomem *dsp_mmu_base;	/* DSP MMU Mapped registers */
+	u32 api_clk_base;	/* CLK Registers */
+	u32 dsp_clk_m2_base;	/* DSP Clock Module m2 */
+	u32 public_rhea;	/* Pub Rhea */
+	u32 int_addr;		/* MB INTR reg */
+	u32 tc_endianism;	/* TC Endianism register */
+	u32 test_base;		/* DSP MMU Mapped registers */
+	u32 self_loop;		/* Pointer to the selfloop */
+	u32 dsp_start_add;	/* API Boot vector */
+	u32 internal_size;	/* Internal memory size */
 
 	struct omap_mbox *mbox;		/* Mail box handle */
 
@@ -348,7 +348,7 @@ struct bridge_dev_context {
 	 */
 	/* DMMU TLB entries */
 	struct bridge_ioctl_extproc atlb_entry[BRDIOCTL_NUMOFMMUTLB];
-	u32 dw_brd_state;       /* Last known board state. */
+	u32 brd_state;       /* Last known board state. */
 
 	/* TC Settings */
 	bool tc_word_swap_on;	/* Traffic Controller Word Swap */
diff --git a/drivers/staging/tidspbridge/core/chnl_sm.c b/drivers/staging/tidspbridge/core/chnl_sm.c
index 662a5b5..8381130 100644
--- a/drivers/staging/tidspbridge/core/chnl_sm.c
+++ b/drivers/staging/tidspbridge/core/chnl_sm.c
@@ -37,9 +37,9 @@
  *      which may cause timeouts and/or failure offunction sync_wait_on_event.
  *      This invariant condition is:
  *
- *          LST_Empty(pchnl->pio_completions) ==> pchnl->sync_event is reset
+ *          list_empty(&pchnl->io_completions) ==> pchnl->sync_event is reset
  *      and
- *          !LST_Empty(pchnl->pio_completions) ==> pchnl->sync_event is set.
+ *          !list_empty(&pchnl->io_completions) ==> pchnl->sync_event is set.
  */
 
 #include <linux/types.h>
@@ -73,11 +73,9 @@
 #define MAILBOX_IRQ INT_MAIL_MPU_IRQ
 
 /*  ----------------------------------- Function Prototypes */
-static struct lst_list *create_chirp_list(u32 chirps);
+static int create_chirp_list(struct list_head *list, u32 chirps);
 
-static void free_chirp_list(struct lst_list *chirp_list);
-
-static struct chnl_irp *make_new_chirp(void);
+static void free_chirp_list(struct list_head *list);
 
 static int search_free_channel(struct chnl_mgr *chnl_mgr_obj,
 				      u32 *chnl);
@@ -107,35 +105,31 @@ int bridge_chnl_add_io_req(struct chnl_object *chnl_obj, void *host_buf,
 	is_eos = (byte_size == 0);
 
 	/* Validate args */
-	if (!host_buf || !pchnl) {
-		status = -EFAULT;
-	} else if (is_eos && CHNL_IS_INPUT(pchnl->chnl_mode)) {
-		status = -EPERM;
-	} else {
-		/*
-		 * Check the channel state: only queue chirp if channel state
-		 * allows it.
-		 */
-		dw_state = pchnl->dw_state;
-		if (dw_state != CHNL_STATEREADY) {
-			if (dw_state & CHNL_STATECANCEL)
-				status = -ECANCELED;
-			else if ((dw_state & CHNL_STATEEOS) &&
-				 CHNL_IS_OUTPUT(pchnl->chnl_mode))
-				status = -EPIPE;
-			else
-				/* No other possible states left */
-				DBC_ASSERT(0);
-		}
+	if (!host_buf || !pchnl)
+		return -EFAULT;
+
+	if (is_eos && CHNL_IS_INPUT(pchnl->chnl_mode))
+		return -EPERM;
+
+	/*
+	 * Check the channel state: only queue chirp if channel state
+	 * allows it.
+	 */
+	dw_state = pchnl->state;
+	if (dw_state != CHNL_STATEREADY) {
+		if (dw_state & CHNL_STATECANCEL)
+			return -ECANCELED;
+		if ((dw_state & CHNL_STATEEOS) &&
+				CHNL_IS_OUTPUT(pchnl->chnl_mode))
+			return -EPIPE;
+		/* No other possible states left */
+		DBC_ASSERT(0);
 	}
 
 	dev_obj = dev_get_first();
 	dev_get_bridge_context(dev_obj, &dev_ctxt);
 	if (!dev_ctxt)
-		status = -EFAULT;
-
-	if (status)
-		goto func_end;
+		return -EFAULT;
 
 	if (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1 && host_buf) {
 		if (!(host_buf < (void *)USERMODE_ADDR)) {
@@ -144,18 +138,16 @@ int bridge_chnl_add_io_req(struct chnl_object *chnl_obj, void *host_buf,
 		}
 		/* if addr in user mode, then copy to kernel space */
 		host_sys_buf = kmalloc(buf_size, GFP_KERNEL);
-		if (host_sys_buf == NULL) {
-			status = -ENOMEM;
-			goto func_end;
-		}
+		if (host_sys_buf == NULL)
+			return -ENOMEM;
+
 		if (CHNL_IS_OUTPUT(pchnl->chnl_mode)) {
 			status = copy_from_user(host_sys_buf, host_buf,
-						buf_size);
+					buf_size);
 			if (status) {
 				kfree(host_sys_buf);
 				host_sys_buf = NULL;
-				status = -EFAULT;
-				goto func_end;
+				return -EFAULT;
 			}
 		}
 	}
@@ -169,63 +161,62 @@ func_cont:
 	omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
 	if (pchnl->chnl_type == CHNL_PCPY) {
 		/* This is a processor-copy channel. */
-		if (!status && CHNL_IS_OUTPUT(pchnl->chnl_mode)) {
+		if (CHNL_IS_OUTPUT(pchnl->chnl_mode)) {
 			/* Check buffer size on output channels for fit. */
-			if (byte_size >
-			    io_buf_size(pchnl->chnl_mgr_obj->hio_mgr))
+			if (byte_size > io_buf_size(
+						pchnl->chnl_mgr_obj->iomgr)) {
 				status = -EINVAL;
-
+				goto out;
+			}
 		}
 	}
-	if (!status) {
-		/* Get a free chirp: */
-		chnl_packet_obj =
-		    (struct chnl_irp *)lst_get_head(pchnl->free_packets_list);
-		if (chnl_packet_obj == NULL)
-			status = -EIO;
 
-	}
-	if (!status) {
-		/* Enqueue the chirp on the chnl's IORequest queue: */
-		chnl_packet_obj->host_user_buf = chnl_packet_obj->host_sys_buf =
-		    host_buf;
-		if (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1)
-			chnl_packet_obj->host_sys_buf = host_sys_buf;
-
-		/*
-		 * Note: for dma chans dw_dsp_addr contains dsp address
-		 * of SM buffer.
-		 */
-		DBC_ASSERT(chnl_mgr_obj->word_size != 0);
-		/* DSP address */
-		chnl_packet_obj->dsp_tx_addr =
-		    dw_dsp_addr / chnl_mgr_obj->word_size;
-		chnl_packet_obj->byte_size = byte_size;
-		chnl_packet_obj->buf_size = buf_size;
-		/* Only valid for output channel */
-		chnl_packet_obj->dw_arg = dw_arg;
-		chnl_packet_obj->status = (is_eos ? CHNL_IOCSTATEOS :
-					   CHNL_IOCSTATCOMPLETE);
-		lst_put_tail(pchnl->pio_requests,
-			     (struct list_head *)chnl_packet_obj);
-		pchnl->cio_reqs++;
-		DBC_ASSERT(pchnl->cio_reqs <= pchnl->chnl_packets);
-		/*
-		 * If end of stream, update the channel state to prevent
-		 * more IOR's.
-		 */
-		if (is_eos)
-			pchnl->dw_state |= CHNL_STATEEOS;
-
-		/* Legacy DSM Processor-Copy */
-		DBC_ASSERT(pchnl->chnl_type == CHNL_PCPY);
-		/* Request IO from the DSP */
-		io_request_chnl(chnl_mgr_obj->hio_mgr, pchnl,
-				(CHNL_IS_INPUT(pchnl->chnl_mode) ? IO_INPUT :
-				 IO_OUTPUT), &mb_val);
-		sched_dpc = true;
-
-	}
+	/* Get a free chirp: */
+	if (list_empty(&pchnl->free_packets_list)) {
+		status = -EIO;
+		goto out;
+	}
+	chnl_packet_obj = list_first_entry(&pchnl->free_packets_list,
+			struct chnl_irp, link);
+	list_del(&chnl_packet_obj->link);
+
+	/* Enqueue the chirp on the chnl's IORequest queue: */
+	chnl_packet_obj->host_user_buf = chnl_packet_obj->host_sys_buf =
+		host_buf;
+	if (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1)
+		chnl_packet_obj->host_sys_buf = host_sys_buf;
+
+	/*
+	 * Note: for dma chans dw_dsp_addr contains dsp address
+	 * of SM buffer.
+	 */
+	DBC_ASSERT(chnl_mgr_obj->word_size != 0);
+	/* DSP address */
+	chnl_packet_obj->dsp_tx_addr = dw_dsp_addr / chnl_mgr_obj->word_size;
+	chnl_packet_obj->byte_size = byte_size;
+	chnl_packet_obj->buf_size = buf_size;
+	/* Only valid for output channel */
+	chnl_packet_obj->arg = dw_arg;
+	chnl_packet_obj->status = (is_eos ? CHNL_IOCSTATEOS :
+			CHNL_IOCSTATCOMPLETE);
+	list_add_tail(&chnl_packet_obj->link, &pchnl->io_requests);
+	pchnl->cio_reqs++;
+	DBC_ASSERT(pchnl->cio_reqs <= pchnl->chnl_packets);
+	/*
+	 * If end of stream, update the channel state to prevent
+	 * more IOR's.
+	 */
+	if (is_eos)
+		pchnl->state |= CHNL_STATEEOS;
+
+	/* Legacy DSM Processor-Copy */
+	DBC_ASSERT(pchnl->chnl_type == CHNL_PCPY);
+	/* Request IO from the DSP */
+	io_request_chnl(chnl_mgr_obj->iomgr, pchnl,
+			(CHNL_IS_INPUT(pchnl->chnl_mode) ? IO_INPUT :
+			 IO_OUTPUT), &mb_val);
+	sched_dpc = true;
+out:
 	omap_mbox_enable_irq(dev_ctxt->mbox, IRQ_RX);
 	spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
 	if (mb_val != 0)
@@ -233,9 +224,8 @@ func_cont:
 
 	/* Schedule a DPC, to do the actual data transfer */
 	if (sched_dpc)
-		iosm_schedule(chnl_mgr_obj->hio_mgr);
+		iosm_schedule(chnl_mgr_obj->iomgr);
 
-func_end:
 	return status;
 }
 
@@ -250,59 +240,55 @@ func_end:
  */
 int bridge_chnl_cancel_io(struct chnl_object *chnl_obj)
 {
-	int status = 0;
 	struct chnl_object *pchnl = (struct chnl_object *)chnl_obj;
 	u32 chnl_id = -1;
 	s8 chnl_mode;
-	struct chnl_irp *chnl_packet_obj;
+	struct chnl_irp *chirp, *tmp;
 	struct chnl_mgr *chnl_mgr_obj = NULL;
 
 	/* Check args: */
-	if (pchnl && pchnl->chnl_mgr_obj) {
-		chnl_id = pchnl->chnl_id;
-		chnl_mode = pchnl->chnl_mode;
-		chnl_mgr_obj = pchnl->chnl_mgr_obj;
-	} else {
-		status = -EFAULT;
-	}
-	if (status)
-		goto func_end;
+	if (!pchnl || !pchnl->chnl_mgr_obj)
+		return -EFAULT;
+
+	chnl_id = pchnl->chnl_id;
+	chnl_mode = pchnl->chnl_mode;
+	chnl_mgr_obj = pchnl->chnl_mgr_obj;
 
 	/*  Mark this channel as cancelled, to prevent further IORequests or
 	 *  IORequests or dispatching. */
 	spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock);
-	pchnl->dw_state |= CHNL_STATECANCEL;
-	if (LST_IS_EMPTY(pchnl->pio_requests))
-		goto func_cont;
+
+	pchnl->state |= CHNL_STATECANCEL;
+
+	if (list_empty(&pchnl->io_requests)) {
+		spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
+		return 0;
+	}
 
 	if (pchnl->chnl_type == CHNL_PCPY) {
 		/* Indicate we have no more buffers available for transfer: */
 		if (CHNL_IS_INPUT(pchnl->chnl_mode)) {
-			io_cancel_chnl(chnl_mgr_obj->hio_mgr, chnl_id);
+			io_cancel_chnl(chnl_mgr_obj->iomgr, chnl_id);
 		} else {
 			/* Record that we no longer have output buffers
 			 * available: */
-			chnl_mgr_obj->dw_output_mask &= ~(1 << chnl_id);
+			chnl_mgr_obj->output_mask &= ~(1 << chnl_id);
 		}
 	}
 	/* Move all IOR's to IOC queue: */
-	while (!LST_IS_EMPTY(pchnl->pio_requests)) {
-		chnl_packet_obj =
-		    (struct chnl_irp *)lst_get_head(pchnl->pio_requests);
-		if (chnl_packet_obj) {
-			chnl_packet_obj->byte_size = 0;
-			chnl_packet_obj->status |= CHNL_IOCSTATCANCEL;
-			lst_put_tail(pchnl->pio_completions,
-				     (struct list_head *)chnl_packet_obj);
-			pchnl->cio_cs++;
-			pchnl->cio_reqs--;
-			DBC_ASSERT(pchnl->cio_reqs >= 0);
-		}
+	list_for_each_entry_safe(chirp, tmp, &pchnl->io_requests, link) {
+		list_del(&chirp->link);
+		chirp->byte_size = 0;
+		chirp->status |= CHNL_IOCSTATCANCEL;
+		list_add_tail(&chirp->link, &pchnl->io_completions);
+		pchnl->cio_cs++;
+		pchnl->cio_reqs--;
+		DBC_ASSERT(pchnl->cio_reqs >= 0);
 	}
-func_cont:
+
 	spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
-func_end:
-	return status;
+
+	return 0;
 }
 
 /*
@@ -319,59 +305,43 @@ int bridge_chnl_close(struct chnl_object *chnl_obj)
 	struct chnl_object *pchnl = (struct chnl_object *)chnl_obj;
 
 	/* Check args: */
-	if (!pchnl) {
-		status = -EFAULT;
-		goto func_cont;
-	}
-	{
-		/* Cancel IO: this ensures no further IO requests or
-		 * notifications. */
-		status = bridge_chnl_cancel_io(chnl_obj);
+	if (!pchnl)
+		return -EFAULT;
+	/* Cancel IO: this ensures no further IO requests or notifications */
+	status = bridge_chnl_cancel_io(chnl_obj);
+	if (status)
+		return status;
+	/* Assert I/O on this channel is now cancelled: Protects from io_dpc */
+	DBC_ASSERT((pchnl->state & CHNL_STATECANCEL));
+	/* Invalidate channel object: Protects from CHNL_GetIOCompletion() */
+	/* Free the slot in the channel manager: */
+	pchnl->chnl_mgr_obj->channels[pchnl->chnl_id] = NULL;
+	spin_lock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
+	pchnl->chnl_mgr_obj->open_channels -= 1;
+	spin_unlock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
+	if (pchnl->ntfy_obj) {
+		ntfy_delete(pchnl->ntfy_obj);
+		kfree(pchnl->ntfy_obj);
+		pchnl->ntfy_obj = NULL;
 	}
-func_cont:
-	if (!status) {
-		/* Assert I/O on this channel is now cancelled: Protects
-		 * from io_dpc. */
-		DBC_ASSERT((pchnl->dw_state & CHNL_STATECANCEL));
-		/* Invalidate channel object: Protects from
-		 * CHNL_GetIOCompletion(). */
-		/* Free the slot in the channel manager: */
-		pchnl->chnl_mgr_obj->ap_channel[pchnl->chnl_id] = NULL;
-		spin_lock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
-		pchnl->chnl_mgr_obj->open_channels -= 1;
-		spin_unlock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
-		if (pchnl->ntfy_obj) {
-			ntfy_delete(pchnl->ntfy_obj);
-			kfree(pchnl->ntfy_obj);
-			pchnl->ntfy_obj = NULL;
-		}
-		/* Reset channel event: (NOTE: user_event freed in user
-		 * context.). */
-		if (pchnl->sync_event) {
-			sync_reset_event(pchnl->sync_event);
-			kfree(pchnl->sync_event);
-			pchnl->sync_event = NULL;
-		}
-		/* Free I/O request and I/O completion queues: */
-		if (pchnl->pio_completions) {
-			free_chirp_list(pchnl->pio_completions);
-			pchnl->pio_completions = NULL;
-			pchnl->cio_cs = 0;
-		}
-		if (pchnl->pio_requests) {
-			free_chirp_list(pchnl->pio_requests);
-			pchnl->pio_requests = NULL;
-			pchnl->cio_reqs = 0;
-		}
-		if (pchnl->free_packets_list) {
-			free_chirp_list(pchnl->free_packets_list);
-			pchnl->free_packets_list = NULL;
-		}
-		/* Release channel object. */
-		kfree(pchnl);
-		pchnl = NULL;
+	/* Reset channel event: (NOTE: user_event freed in user context) */
+	if (pchnl->sync_event) {
+		sync_reset_event(pchnl->sync_event);
+		kfree(pchnl->sync_event);
+		pchnl->sync_event = NULL;
 	}
-	DBC_ENSURE(status || !pchnl);
+	/* Free I/O request and I/O completion queues: */
+	free_chirp_list(&pchnl->io_completions);
+	pchnl->cio_cs = 0;
+
+	free_chirp_list(&pchnl->io_requests);
+	pchnl->cio_reqs = 0;
+
+	free_chirp_list(&pchnl->free_packets_list);
+
+	/* Release channel object. */
+	kfree(pchnl);
+
 	return status;
 }
 
@@ -407,18 +377,18 @@ int bridge_chnl_create(struct chnl_mgr **channel_mgr,
 		DBC_ASSERT(mgr_attrts->max_channels == CHNL_MAXCHANNELS);
 		max_channels = CHNL_MAXCHANNELS + CHNL_MAXCHANNELS * CHNL_PCPY;
 		/* Create array of channels */
-		chnl_mgr_obj->ap_channel = kzalloc(sizeof(struct chnl_object *)
+		chnl_mgr_obj->channels = kzalloc(sizeof(struct chnl_object *)
 						* max_channels, GFP_KERNEL);
-		if (chnl_mgr_obj->ap_channel) {
+		if (chnl_mgr_obj->channels) {
 			/* Initialize chnl_mgr object */
-			chnl_mgr_obj->dw_type = CHNL_TYPESM;
+			chnl_mgr_obj->type = CHNL_TYPESM;
 			chnl_mgr_obj->word_size = mgr_attrts->word_size;
 			/* Total # chnls supported */
 			chnl_mgr_obj->max_channels = max_channels;
 			chnl_mgr_obj->open_channels = 0;
-			chnl_mgr_obj->dw_output_mask = 0;
-			chnl_mgr_obj->dw_last_output = 0;
-			chnl_mgr_obj->hdev_obj = hdev_obj;
+			chnl_mgr_obj->output_mask = 0;
+			chnl_mgr_obj->last_output = 0;
+			chnl_mgr_obj->dev_obj = hdev_obj;
 			spin_lock_init(&chnl_mgr_obj->chnl_mgr_lock);
 		} else {
 			status = -ENOMEM;
@@ -453,7 +423,7 @@ int bridge_chnl_destroy(struct chnl_mgr *hchnl_mgr)
 		for (chnl_id = 0; chnl_id < chnl_mgr_obj->max_channels;
 		     chnl_id++) {
 			status =
-			    bridge_chnl_close(chnl_mgr_obj->ap_channel
+			    bridge_chnl_close(chnl_mgr_obj->channels
 					      [chnl_id]);
 			if (status)
 				dev_dbg(bridge, "%s: Error status 0x%x\n",
@@ -461,10 +431,10 @@ int bridge_chnl_destroy(struct chnl_mgr *hchnl_mgr)
 		}
 
 		/* Free channel manager object: */
-		kfree(chnl_mgr_obj->ap_channel);
+		kfree(chnl_mgr_obj->channels);
 
 		/* Set hchnl_mgr to NULL in device object. */
-		dev_set_chnl_mgr(chnl_mgr_obj->hdev_obj, NULL);
+		dev_set_chnl_mgr(chnl_mgr_obj->dev_obj, NULL);
 		/* Free this Chnl Mgr object: */
 		kfree(hchnl_mgr);
 	} else {
@@ -505,7 +475,7 @@ int bridge_chnl_flush_io(struct chnl_object *chnl_obj, u32 timeout)
 		    && (pchnl->chnl_type == CHNL_PCPY)) {
 			/* Wait for IO completions, up to the specified
 			 * timeout: */
-			while (!LST_IS_EMPTY(pchnl->pio_requests) && !status) {
+			while (!list_empty(&pchnl->io_requests) && !status) {
 				status = bridge_chnl_get_ioc(chnl_obj,
 						timeout, &chnl_ioc_obj);
 				if (status)
@@ -518,10 +488,10 @@ int bridge_chnl_flush_io(struct chnl_object *chnl_obj, u32 timeout)
 		} else {
 			status = bridge_chnl_cancel_io(chnl_obj);
 			/* Now, leave the channel in the ready state: */
-			pchnl->dw_state &= ~CHNL_STATECANCEL;
+			pchnl->state &= ~CHNL_STATECANCEL;
 		}
 	}
-	DBC_ENSURE(status || LST_IS_EMPTY(pchnl->pio_requests));
+	DBC_ENSURE(status || list_empty(&pchnl->io_requests));
 	return status;
 }
 
@@ -538,16 +508,16 @@ int bridge_chnl_get_info(struct chnl_object *chnl_obj,
 	if (channel_info != NULL) {
 		if (pchnl) {
 			/* Return the requested information: */
-			channel_info->hchnl_mgr = pchnl->chnl_mgr_obj;
+			channel_info->chnl_mgr = pchnl->chnl_mgr_obj;
 			channel_info->event_obj = pchnl->user_event;
 			channel_info->cnhl_id = pchnl->chnl_id;
-			channel_info->dw_mode = pchnl->chnl_mode;
+			channel_info->mode = pchnl->chnl_mode;
 			channel_info->bytes_tx = pchnl->bytes_moved;
 			channel_info->process = pchnl->process;
 			channel_info->sync_event = pchnl->sync_event;
 			channel_info->cio_cs = pchnl->cio_cs;
 			channel_info->cio_reqs = pchnl->cio_reqs;
-			channel_info->dw_state = pchnl->dw_state;
+			channel_info->state = pchnl->state;
 		} else {
 			status = -EFAULT;
 		}
@@ -581,7 +551,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 	if (!chan_ioc || !pchnl) {
 		status = -EFAULT;
 	} else if (timeout == CHNL_IOCNOWAIT) {
-		if (LST_IS_EMPTY(pchnl->pio_completions))
+		if (list_empty(&pchnl->io_completions))
 			status = -EREMOTEIO;
 
 	}
@@ -596,7 +566,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 
 	ioc.status = CHNL_IOCSTATCOMPLETE;
 	if (timeout !=
-	    CHNL_IOCNOWAIT && LST_IS_EMPTY(pchnl->pio_completions)) {
+	    CHNL_IOCNOWAIT && list_empty(&pchnl->io_completions)) {
 		if (timeout == CHNL_IOCINFINITE)
 			timeout = SYNC_INFINITE;
 
@@ -611,7 +581,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 			 * fails due to unkown causes. */
 			/* Even though Wait failed, there may be something in
 			 * the Q: */
-			if (LST_IS_EMPTY(pchnl->pio_completions)) {
+			if (list_empty(&pchnl->io_completions)) {
 				ioc.status |= CHNL_IOCSTATCANCEL;
 				dequeue_ioc = false;
 			}
@@ -622,38 +592,34 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 	omap_mbox_disable_irq(dev_ctxt->mbox, IRQ_RX);
 	if (dequeue_ioc) {
 		/* Dequeue IOC and set chan_ioc; */
-		DBC_ASSERT(!LST_IS_EMPTY(pchnl->pio_completions));
-		chnl_packet_obj =
-		    (struct chnl_irp *)lst_get_head(pchnl->pio_completions);
+		DBC_ASSERT(!list_empty(&pchnl->io_completions));
+		chnl_packet_obj = list_first_entry(&pchnl->io_completions,
+				struct chnl_irp, link);
+		list_del(&chnl_packet_obj->link);
 		/* Update chan_ioc from channel state and chirp: */
-		if (chnl_packet_obj) {
-			pchnl->cio_cs--;
-			/*  If this is a zero-copy channel, then set IOC's pbuf
-			 *  to the DSP's address. This DSP address will get
-			 *  translated to user's virtual addr later. */
-			{
-				host_sys_buf = chnl_packet_obj->host_sys_buf;
-				ioc.pbuf = chnl_packet_obj->host_user_buf;
-			}
-			ioc.byte_size = chnl_packet_obj->byte_size;
-			ioc.buf_size = chnl_packet_obj->buf_size;
-			ioc.dw_arg = chnl_packet_obj->dw_arg;
-			ioc.status |= chnl_packet_obj->status;
-			/* Place the used chirp on the free list: */
-			lst_put_tail(pchnl->free_packets_list,
-				     (struct list_head *)chnl_packet_obj);
-		} else {
-			ioc.pbuf = NULL;
-			ioc.byte_size = 0;
-		}
+		pchnl->cio_cs--;
+		/*
+		 * If this is a zero-copy channel, then set IOC's pbuf
+		 * to the DSP's address. This DSP address will get
+		 * translated to user's virtual addr later.
+		 */
+		host_sys_buf = chnl_packet_obj->host_sys_buf;
+		ioc.buf = chnl_packet_obj->host_user_buf;
+		ioc.byte_size = chnl_packet_obj->byte_size;
+		ioc.buf_size = chnl_packet_obj->buf_size;
+		ioc.arg = chnl_packet_obj->arg;
+		ioc.status |= chnl_packet_obj->status;
+		/* Place the used chirp on the free list: */
+		list_add_tail(&chnl_packet_obj->link,
+				&pchnl->free_packets_list);
 	} else {
-		ioc.pbuf = NULL;
+		ioc.buf = NULL;
 		ioc.byte_size = 0;
-		ioc.dw_arg = 0;
+		ioc.arg = 0;
 		ioc.buf_size = 0;
 	}
 	/* Ensure invariant: If any IOC's are queued for this channel... */
-	if (!LST_IS_EMPTY(pchnl->pio_completions)) {
+	if (!list_empty(&pchnl->io_completions)) {
 		/*  Since DSPStream_Reclaim() does not take a timeout
 		 *  parameter, we pass the stream's timeout value to
 		 *  bridge_chnl_get_ioc. We cannot determine whether or not
@@ -674,11 +640,11 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 	spin_unlock_bh(&pchnl->chnl_mgr_obj->chnl_mgr_lock);
 	if (dequeue_ioc
 	    && (pchnl->chnl_type == CHNL_PCPY && pchnl->chnl_id > 1)) {
-		if (!(ioc.pbuf < (void *)USERMODE_ADDR))
+		if (!(ioc.buf < (void *)USERMODE_ADDR))
 			goto func_cont;
 
 		/* If the addr is in user mode, then copy it */
-		if (!host_sys_buf || !ioc.pbuf) {
+		if (!host_sys_buf || !ioc.buf) {
 			status = -EFAULT;
 			goto func_cont;
 		}
@@ -686,7 +652,7 @@ int bridge_chnl_get_ioc(struct chnl_object *chnl_obj, u32 timeout,
 			goto func_cont1;
 
 		/*host_user_buf */
-		status = copy_to_user(ioc.pbuf, host_sys_buf, ioc.byte_size);
+		status = copy_to_user(ioc.buf, host_sys_buf, ioc.byte_size);
 		if (status) {
 			if (current->flags & PF_EXITING)
 				status = 0;
@@ -710,32 +676,22 @@ func_end:
 int bridge_chnl_get_mgr_info(struct chnl_mgr *hchnl_mgr, u32 ch_id,
 				 struct chnl_mgrinfo *mgr_info)
 {
-	int status = 0;
 	struct chnl_mgr *chnl_mgr_obj = (struct chnl_mgr *)hchnl_mgr;
 
-	if (mgr_info != NULL) {
-		if (ch_id <= CHNL_MAXCHANNELS) {
-			if (hchnl_mgr) {
-				/* Return the requested information: */
-				mgr_info->chnl_obj =
-				    chnl_mgr_obj->ap_channel[ch_id];
-				mgr_info->open_channels =
-				    chnl_mgr_obj->open_channels;
-				mgr_info->dw_type = chnl_mgr_obj->dw_type;
-				/* total # of chnls */
-				mgr_info->max_channels =
-				    chnl_mgr_obj->max_channels;
-			} else {
-				status = -EFAULT;
-			}
-		} else {
-			status = -ECHRNG;
-		}
-	} else {
-		status = -EFAULT;
-	}
+	if (!mgr_info || !hchnl_mgr)
+		return -EFAULT;
 
-	return status;
+	if (ch_id > CHNL_MAXCHANNELS)
+		return -ECHRNG;
+
+	/* Return the requested information: */
+	mgr_info->chnl_obj = chnl_mgr_obj->channels[ch_id];
+	mgr_info->open_channels = chnl_mgr_obj->open_channels;
+	mgr_info->type = chnl_mgr_obj->type;
+	/* total # of chnls */
+	mgr_info->max_channels = chnl_mgr_obj->max_channels;
+
+	return 0;
 }
 
 /*
@@ -762,7 +718,7 @@ int bridge_chnl_idle(struct chnl_object *chnl_obj, u32 timeout,
 
 		/* Reset the byte count and put channel back in ready state. */
 		chnl_obj->bytes_moved = 0;
-		chnl_obj->dw_state &= ~CHNL_STATECANCEL;
+		chnl_obj->state &= ~CHNL_STATECANCEL;
 	}
 
 	return status;
@@ -785,116 +741,102 @@ int bridge_chnl_open(struct chnl_object **chnl,
 	DBC_REQUIRE(pattrs != NULL);
 	DBC_REQUIRE(hchnl_mgr != NULL);
 	*chnl = NULL;
+
 	/* Validate Args: */
-	if (pattrs->uio_reqs == 0) {
-		status = -EINVAL;
+	if (!pattrs->uio_reqs)
+		return -EINVAL;
+
+	if (!hchnl_mgr)
+		return -EFAULT;
+
+	if (ch_id != CHNL_PICKFREE) {
+		if (ch_id >= chnl_mgr_obj->max_channels)
+			return -ECHRNG;
+		if (chnl_mgr_obj->channels[ch_id] != NULL)
+			return -EALREADY;
 	} else {
-		if (!hchnl_mgr) {
-			status = -EFAULT;
-		} else {
-			if (ch_id != CHNL_PICKFREE) {
-				if (ch_id >= chnl_mgr_obj->max_channels)
-					status = -ECHRNG;
-				else if (chnl_mgr_obj->ap_channel[ch_id] !=
-					 NULL)
-					status = -EALREADY;
-			} else {
-				/* Check for free channel */
-				status =
-				    search_free_channel(chnl_mgr_obj, &ch_id);
-			}
-		}
+		/* Check for free channel */
+		status = search_free_channel(chnl_mgr_obj, &ch_id);
+		if (status)
+			return status;
 	}
-	if (status)
-		goto func_end;
 
 	DBC_ASSERT(ch_id < chnl_mgr_obj->max_channels);
+
 	/* Create channel object: */
 	pchnl = kzalloc(sizeof(struct chnl_object), GFP_KERNEL);
-	if (!pchnl) {
-		status = -ENOMEM;
-		goto func_end;
-	}
+	if (!pchnl)
+		return -ENOMEM;
+
 	/* Protect queues from io_dpc: */
-	pchnl->dw_state = CHNL_STATECANCEL;
+	pchnl->state = CHNL_STATECANCEL;
+
 	/* Allocate initial IOR and IOC queues: */
-	pchnl->free_packets_list = create_chirp_list(pattrs->uio_reqs);
-	pchnl->pio_requests = create_chirp_list(0);
-	pchnl->pio_completions = create_chirp_list(0);
+	status = create_chirp_list(&pchnl->free_packets_list,
+			pattrs->uio_reqs);
+	if (status)
+		goto out_err;
+
+	INIT_LIST_HEAD(&pchnl->io_requests);
+	INIT_LIST_HEAD(&pchnl->io_completions);
+
 	pchnl->chnl_packets = pattrs->uio_reqs;
 	pchnl->cio_cs = 0;
 	pchnl->cio_reqs = 0;
+
 	sync_event = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
-	if (sync_event)
-		sync_init_event(sync_event);
-	else
+	if (!sync_event) {
 		status = -ENOMEM;
-
-	if (!status) {
-		pchnl->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
-							GFP_KERNEL);
-		if (pchnl->ntfy_obj)
-			ntfy_init(pchnl->ntfy_obj);
-		else
-			status = -ENOMEM;
+		goto out_err;
 	}
+	sync_init_event(sync_event);
 
-	if (!status) {
-		if (pchnl->pio_completions && pchnl->pio_requests &&
-		    pchnl->free_packets_list) {
-			/* Initialize CHNL object fields: */
-			pchnl->chnl_mgr_obj = chnl_mgr_obj;
-			pchnl->chnl_id = ch_id;
-			pchnl->chnl_mode = chnl_mode;
-			pchnl->user_event = sync_event;
-			pchnl->sync_event = sync_event;
-			/* Get the process handle */
-			pchnl->process = current->tgid;
-			pchnl->pcb_arg = 0;
-			pchnl->bytes_moved = 0;
-			/* Default to proc-copy */
-			pchnl->chnl_type = CHNL_PCPY;
-		} else {
-			status = -ENOMEM;
-		}
-	}
+	pchnl->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
+	if (!pchnl->ntfy_obj) {
+		status = -ENOMEM;
+		goto out_err;
+	}
+	ntfy_init(pchnl->ntfy_obj);
+
+	/* Initialize CHNL object fields: */
+	pchnl->chnl_mgr_obj = chnl_mgr_obj;
+	pchnl->chnl_id = ch_id;
+	pchnl->chnl_mode = chnl_mode;
+	pchnl->user_event = sync_event;
+	pchnl->sync_event = sync_event;
+	/* Get the process handle */
+	pchnl->process = current->tgid;
+	pchnl->cb_arg = 0;
+	pchnl->bytes_moved = 0;
+	/* Default to proc-copy */
+	pchnl->chnl_type = CHNL_PCPY;
+
+	/* Insert channel object in channel manager: */
+	chnl_mgr_obj->channels[pchnl->chnl_id] = pchnl;
+	spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock);
+	chnl_mgr_obj->open_channels++;
+	spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
+	/* Return result... */
+	pchnl->state = CHNL_STATEREADY;
+	*chnl = pchnl;
 
-	if (status) {
-		/* Free memory */
-		if (pchnl->pio_completions) {
-			free_chirp_list(pchnl->pio_completions);
-			pchnl->pio_completions = NULL;
-			pchnl->cio_cs = 0;
-		}
-		if (pchnl->pio_requests) {
-			free_chirp_list(pchnl->pio_requests);
-			pchnl->pio_requests = NULL;
-		}
-		if (pchnl->free_packets_list) {
-			free_chirp_list(pchnl->free_packets_list);
-			pchnl->free_packets_list = NULL;
-		}
-		kfree(sync_event);
-		sync_event = NULL;
+	return status;
 
-		if (pchnl->ntfy_obj) {
-			ntfy_delete(pchnl->ntfy_obj);
-			kfree(pchnl->ntfy_obj);
-			pchnl->ntfy_obj = NULL;
-		}
-		kfree(pchnl);
-	} else {
-		/* Insert channel object in channel manager: */
-		chnl_mgr_obj->ap_channel[pchnl->chnl_id] = pchnl;
-		spin_lock_bh(&chnl_mgr_obj->chnl_mgr_lock);
-		chnl_mgr_obj->open_channels++;
-		spin_unlock_bh(&chnl_mgr_obj->chnl_mgr_lock);
-		/* Return result... */
-		pchnl->dw_state = CHNL_STATEREADY;
-		*chnl = pchnl;
+out_err:
+	/* Free memory */
+	free_chirp_list(&pchnl->io_completions);
+	free_chirp_list(&pchnl->io_requests);
+	free_chirp_list(&pchnl->free_packets_list);
+
+	kfree(sync_event);
+
+	if (pchnl->ntfy_obj) {
+		ntfy_delete(pchnl->ntfy_obj);
+		kfree(pchnl->ntfy_obj);
+		pchnl->ntfy_obj = NULL;
 	}
-func_end:
-	DBC_ENSURE((!status && pchnl) || (*chnl == NULL));
+	kfree(pchnl);
+
 	return status;
 }
 
@@ -924,37 +866,35 @@ int bridge_chnl_register_notify(struct chnl_object *chnl_obj,
  *  Purpose:
  *      Initialize a queue of channel I/O Request/Completion packets.
  *  Parameters:
+ *      list:       Pointer to a list_head
  *      chirps:     Number of Chirps to allocate.
  *  Returns:
- *      Pointer to queue of IRPs, or NULL.
+ *      0 if successful, error code otherwise.
  *  Requires:
  *  Ensures:
  */
-static struct lst_list *create_chirp_list(u32 chirps)
+static int create_chirp_list(struct list_head *list, u32 chirps)
 {
-	struct lst_list *chirp_list;
-	struct chnl_irp *chnl_packet_obj;
+	struct chnl_irp *chirp;
 	u32 i;
 
-	chirp_list = kzalloc(sizeof(struct lst_list), GFP_KERNEL);
+	INIT_LIST_HEAD(list);
 
-	if (chirp_list) {
-		INIT_LIST_HEAD(&chirp_list->head);
-		/* Make N chirps and place on queue. */
-		for (i = 0; (i < chirps)
-		     && ((chnl_packet_obj = make_new_chirp()) != NULL); i++) {
-			lst_put_tail(chirp_list,
-				     (struct list_head *)chnl_packet_obj);
-		}
+	/* Make N chirps and place on queue. */
+	for (i = 0; i < chirps; i++) {
+		chirp = kzalloc(sizeof(struct chnl_irp), GFP_KERNEL);
+		if (!chirp)
+			break;
+		list_add_tail(&chirp->link, list);
+	}
 
-		/* If we couldn't allocate all chirps, free those allocated: */
-		if (i != chirps) {
-			free_chirp_list(chirp_list);
-			chirp_list = NULL;
-		}
+	/* If we couldn't allocate all chirps, free those allocated: */
+	if (i != chirps) {
+		free_chirp_list(list);
+		return -ENOMEM;
 	}
 
-	return chirp_list;
+	return 0;
 }
 
 /*
@@ -962,31 +902,16 @@ static struct lst_list *create_chirp_list(u32 chirps)
  *  Purpose:
  *      Free the queue of Chirps.
  */
-static void free_chirp_list(struct lst_list *chirp_list)
+static void free_chirp_list(struct list_head *chirp_list)
 {
-	DBC_REQUIRE(chirp_list != NULL);
-
-	while (!LST_IS_EMPTY(chirp_list))
-		kfree(lst_get_head(chirp_list));
+	struct chnl_irp *chirp, *tmp;
 
-	kfree(chirp_list);
-}
-
-/*
- *  ======== make_new_chirp ========
- *      Allocate the memory for a new channel IRP.
- */
-static struct chnl_irp *make_new_chirp(void)
-{
-	struct chnl_irp *chnl_packet_obj;
+	DBC_REQUIRE(chirp_list != NULL);
 
-	chnl_packet_obj = kzalloc(sizeof(struct chnl_irp), GFP_KERNEL);
-	if (chnl_packet_obj != NULL) {
-		/* lst_init_elem only resets the list's member values. */
-		lst_init_elem(&chnl_packet_obj->link);
+	list_for_each_entry_safe(chirp, tmp, chirp_list, link) {
+		list_del(&chirp->link);
+		kfree(chirp);
 	}
-
-	return chnl_packet_obj;
 }
 
 /*
@@ -1002,7 +927,7 @@ static int search_free_channel(struct chnl_mgr *chnl_mgr_obj,
 	DBC_REQUIRE(chnl_mgr_obj);
 
 	for (i = 0; i < chnl_mgr_obj->max_channels; i++) {
-		if (chnl_mgr_obj->ap_channel[i] == NULL) {
+		if (chnl_mgr_obj->channels[i] == NULL) {
 			status = 0;
 			*chnl = i;
 			break;
diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c
index 46d17c7..589a055 100644
--- a/drivers/staging/tidspbridge/core/dsp-clock.c
+++ b/drivers/staging/tidspbridge/core/dsp-clock.c
@@ -146,54 +146,6 @@ void dsp_clk_init(void)
 					ssi.sst_fck, ssi.ssr_fck, ssi.ick);
 }
 
-#ifdef CONFIG_OMAP_MCBSP
-static void mcbsp_clk_prepare(bool flag, u8 id)
-{
-	struct cfg_hostres *resources;
-	struct dev_object *hdev_object = NULL;
-	struct bridge_dev_context *bridge_context = NULL;
-	u32 val;
-
-	hdev_object = (struct dev_object *)drv_get_first_dev_object();
-	if (!hdev_object)
-		return;
-
-	dev_get_bridge_context(hdev_object, &bridge_context);
-	if (!bridge_context)
-		return;
-
-	resources = bridge_context->resources;
-	if (!resources)
-		return;
-
-	if (flag) {
-		if (id == DSP_CLK_MCBSP1) {
-			/* set MCBSP1_CLKS, on McBSP1 ON */
-			val = __raw_readl(resources->dw_sys_ctrl_base + 0x274);
-			val |= 1 << 2;
-			__raw_writel(val, resources->dw_sys_ctrl_base + 0x274);
-		} else if (id == DSP_CLK_MCBSP2) {
-			/* set MCBSP2_CLKS, on McBSP2 ON */
-			val = __raw_readl(resources->dw_sys_ctrl_base + 0x274);
-			val |= 1 << 6;
-			__raw_writel(val, resources->dw_sys_ctrl_base + 0x274);
-		}
-	} else {
-		if (id == DSP_CLK_MCBSP1) {
-			/* clear MCBSP1_CLKS, on McBSP1 OFF */
-			val = __raw_readl(resources->dw_sys_ctrl_base + 0x274);
-			val &= ~(1 << 2);
-			__raw_writel(val, resources->dw_sys_ctrl_base + 0x274);
-		} else if (id == DSP_CLK_MCBSP2) {
-			/* clear MCBSP2_CLKS, on McBSP2 OFF */
-			val = __raw_readl(resources->dw_sys_ctrl_base + 0x274);
-			val &= ~(1 << 6);
-			__raw_writel(val, resources->dw_sys_ctrl_base + 0x274);
-		}
-	}
-}
-#endif
-
 /**
  * dsp_gpt_wait_overflow - set gpt overflow and wait for fixed timeout
  * @clk_id:      GP Timer clock id.
@@ -257,9 +209,9 @@ int dsp_clk_enable(enum dsp_clk_id clk_id)
 		break;
 #ifdef CONFIG_OMAP_MCBSP
 	case MCBSP_CLK:
-		mcbsp_clk_prepare(true, clk_id);
 		omap_mcbsp_set_io_type(MCBSP_ID(clk_id), OMAP_MCBSP_POLL_IO);
 		omap_mcbsp_request(MCBSP_ID(clk_id));
+		omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PAD_SRC);
 		break;
 #endif
 	case WDT_CLK:
@@ -334,7 +286,7 @@ int dsp_clk_disable(enum dsp_clk_id clk_id)
 		break;
 #ifdef CONFIG_OMAP_MCBSP
 	case MCBSP_CLK:
-		mcbsp_clk_prepare(false, clk_id);
+		omap2_mcbsp_set_clks_src(MCBSP_ID(clk_id), MCBSP_CLKS_PRCM_SRC);
 		omap_mcbsp_free(MCBSP_ID(clk_id));
 		break;
 #endif
diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c
index 27e0aa8..694c0e5 100644
--- a/drivers/staging/tidspbridge/core/io_sm.c
+++ b/drivers/staging/tidspbridge/core/io_sm.c
@@ -24,6 +24,7 @@
  * function.
  */
 #include <linux/types.h>
+#include <linux/list.h>
 
 /* Host OS */
 #include <dspbridge/host_os.h>
@@ -88,39 +89,39 @@
 struct io_mgr {
 	/* These four fields must be the first fields in a io_mgr_ struct */
 	/* Bridge device context */
-	struct bridge_dev_context *hbridge_context;
+	struct bridge_dev_context *bridge_context;
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
-	struct dev_object *hdev_obj;	/* Device this board represents */
+	struct dev_object *dev_obj;	/* Device this board represents */
 
 	/* These fields initialized in bridge_io_create() */
-	struct chnl_mgr *hchnl_mgr;
+	struct chnl_mgr *chnl_mgr;
 	struct shm *shared_mem;	/* Shared Memory control */
 	u8 *input;		/* Address of input channel */
 	u8 *output;		/* Address of output channel */
-	struct msg_mgr *hmsg_mgr;	/* Message manager */
+	struct msg_mgr *msg_mgr;	/* Message manager */
 	/* Msg control for from DSP messages */
 	struct msg_ctrl *msg_input_ctrl;
 	/* Msg control for to DSP messages */
 	struct msg_ctrl *msg_output_ctrl;
 	u8 *msg_input;		/* Address of input messages */
 	u8 *msg_output;		/* Address of output messages */
-	u32 usm_buf_size;	/* Size of a shared memory I/O channel */
+	u32 sm_buf_size;	/* Size of a shared memory I/O channel */
 	bool shared_irq;	/* Is this IRQ shared? */
 	u32 word_size;		/* Size in bytes of DSP word */
 	u16 intr_val;		/* Interrupt value */
 	/* Private extnd proc info; mmu setup */
 	struct mgr_processorextinfo ext_proc_info;
-	struct cmm_object *hcmm_mgr;	/* Shared Mem Mngr */
+	struct cmm_object *cmm_mgr;	/* Shared Mem Mngr */
 	struct work_struct io_workq;	/* workqueue */
 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG)
-	u32 ul_trace_buffer_begin;	/* Trace message start address */
-	u32 ul_trace_buffer_end;	/* Trace message end address */
-	u32 ul_trace_buffer_current;	/* Trace message current address */
-	u32 ul_gpp_read_pointer;	/* GPP Read pointer to Trace buffer */
-	u8 *pmsg;
-	u32 ul_gpp_va;
-	u32 ul_dsp_va;
+	u32 trace_buffer_begin;	/* Trace message start address */
+	u32 trace_buffer_end;	/* Trace message end address */
+	u32 trace_buffer_current;	/* Trace message current address */
+	u32 gpp_read_pointer;		/* GPP Read pointer to Trace buffer */
+	u8 *msg;
+	u32 gpp_va;
+	u32 dsp_va;
 #endif
 	/* IO Dpc */
 	u32 dpc_req;		/* Number of requested DPC's. */
@@ -167,57 +168,41 @@ int bridge_io_create(struct io_mgr **io_man,
 			    struct dev_object *hdev_obj,
 			    const struct io_attrs *mgr_attrts)
 {
-	int status = 0;
 	struct io_mgr *pio_mgr = NULL;
-	struct shm *shared_mem = NULL;
 	struct bridge_dev_context *hbridge_context = NULL;
 	struct cfg_devnode *dev_node_obj;
 	struct chnl_mgr *hchnl_mgr;
 	u8 dev_type;
 
 	/* Check requirements */
-	if (!io_man || !mgr_attrts || mgr_attrts->word_size == 0) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!io_man || !mgr_attrts || mgr_attrts->word_size == 0)
+		return -EFAULT;
+
+	*io_man = NULL;
+
 	dev_get_chnl_mgr(hdev_obj, &hchnl_mgr);
-	if (!hchnl_mgr || hchnl_mgr->hio_mgr) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!hchnl_mgr || hchnl_mgr->iomgr)
+		return -EFAULT;
+
 	/*
 	 * Message manager will be created when a file is loaded, since
 	 * size of message buffer in shared memory is configurable in
 	 * the base image.
 	 */
 	dev_get_bridge_context(hdev_obj, &hbridge_context);
-	if (!hbridge_context) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!hbridge_context)
+		return -EFAULT;
+
 	dev_get_dev_type(hdev_obj, &dev_type);
-	/*
-	 * DSP shared memory area will get set properly when
-	 * a program is loaded. They are unknown until a COFF file is
-	 * loaded. I chose the value -1 because it was less likely to be
-	 * a valid address than 0.
-	 */
-	shared_mem = (struct shm *)-1;
 
 	/* Allocate IO manager object */
 	pio_mgr = kzalloc(sizeof(struct io_mgr), GFP_KERNEL);
-	if (pio_mgr == NULL) {
-		status = -ENOMEM;
-		goto func_end;
-	}
+	if (!pio_mgr)
+		return -ENOMEM;
 
 	/* Initialize chnl_mgr object */
-#if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG)
-	pio_mgr->pmsg = NULL;
-#endif
-	pio_mgr->hchnl_mgr = hchnl_mgr;
+	pio_mgr->chnl_mgr = hchnl_mgr;
 	pio_mgr->word_size = mgr_attrts->word_size;
-	pio_mgr->shared_mem = shared_mem;
 
 	if (dev_type == DSP_UNIT) {
 		/* Create an IO DPC */
@@ -229,29 +214,24 @@ int bridge_io_create(struct io_mgr **io_man,
 
 		spin_lock_init(&pio_mgr->dpc_lock);
 
-		status = dev_get_dev_node(hdev_obj, &dev_node_obj);
+		if (dev_get_dev_node(hdev_obj, &dev_node_obj)) {
+			bridge_io_destroy(pio_mgr);
+			return -EIO;
+		}
 	}
 
-	if (!status) {
-		pio_mgr->hbridge_context = hbridge_context;
-		pio_mgr->shared_irq = mgr_attrts->irq_shared;
-		if (dsp_wdt_init())
-			status = -EPERM;
-	} else {
-		status = -EIO;
-	}
-func_end:
-	if (status) {
-		/* Cleanup */
+	pio_mgr->bridge_context = hbridge_context;
+	pio_mgr->shared_irq = mgr_attrts->irq_shared;
+	if (dsp_wdt_init()) {
 		bridge_io_destroy(pio_mgr);
-		if (io_man)
-			*io_man = NULL;
-	} else {
-		/* Return IO manager object to caller... */
-		hchnl_mgr->hio_mgr = pio_mgr;
-		*io_man = pio_mgr;
+		return -EPERM;
 	}
-	return status;
+
+	/* Return IO manager object to caller... */
+	hchnl_mgr->iomgr = pio_mgr;
+	*io_man = pio_mgr;
+
+	return 0;
 }
 
 /*
@@ -267,7 +247,7 @@ int bridge_io_destroy(struct io_mgr *hio_mgr)
 		tasklet_kill(&hio_mgr->dpc_tasklet);
 
 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG)
-		kfree(hio_mgr->pmsg);
+		kfree(hio_mgr->msg);
 #endif
 		dsp_wdt_exit();
 		/* Free this IO manager object */
@@ -326,7 +306,7 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 		HW_PAGE_SIZE64KB, HW_PAGE_SIZE4KB
 	};
 
-	status = dev_get_bridge_context(hio_mgr->hdev_obj, &pbridge_context);
+	status = dev_get_bridge_context(hio_mgr->dev_obj, &pbridge_context);
 	if (!pbridge_context) {
 		status = -EFAULT;
 		goto func_end;
@@ -337,15 +317,15 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 		status = -EFAULT;
 		goto func_end;
 	}
-	status = dev_get_cod_mgr(hio_mgr->hdev_obj, &cod_man);
+	status = dev_get_cod_mgr(hio_mgr->dev_obj, &cod_man);
 	if (!cod_man) {
 		status = -EFAULT;
 		goto func_end;
 	}
-	hchnl_mgr = hio_mgr->hchnl_mgr;
+	hchnl_mgr = hio_mgr->chnl_mgr;
 	/* The message manager is destroyed when the board is stopped. */
-	dev_get_msg_mgr(hio_mgr->hdev_obj, &hio_mgr->hmsg_mgr);
-	hmsg_mgr = hio_mgr->hmsg_mgr;
+	dev_get_msg_mgr(hio_mgr->dev_obj, &hio_mgr->msg_mgr);
+	hmsg_mgr = hio_mgr->msg_mgr;
 	if (!hchnl_mgr || !hmsg_mgr) {
 		status = -EFAULT;
 		goto func_end;
@@ -437,11 +417,11 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 
 		/* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
 		ndx = 0;
-		ul_gpp_pa = host_res->dw_mem_phys[1];
-		ul_gpp_va = host_res->dw_mem_base[1];
+		ul_gpp_pa = host_res->mem_phys[1];
+		ul_gpp_va = host_res->mem_base[1];
 		/* This is the virtual uncached ioremapped address!!! */
 		/* Why can't we directly take the DSPVA from the symbols? */
-		ul_dsp_va = hio_mgr->ext_proc_info.ty_tlb[0].ul_dsp_virt;
+		ul_dsp_va = hio_mgr->ext_proc_info.ty_tlb[0].dsp_virt;
 		ul_seg_size = (shm0_end - ul_dsp_va) * hio_mgr->word_size;
 		ul_seg1_size =
 		    (ul_ext_end - ul_dyn_ext_base) * hio_mgr->word_size;
@@ -461,9 +441,9 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 			ul_dyn_ext_base, ul_ext_end, ul_seg_size, ul_seg1_size);
 
 		if ((ul_seg_size + ul_seg1_size + ul_pad_size) >
-		    host_res->dw_mem_length[1]) {
+		    host_res->mem_length[1]) {
 			pr_err("%s: shm Error, reserved 0x%x required 0x%x\n",
-			       __func__, host_res->dw_mem_length[1],
+			       __func__, host_res->mem_length[1],
 			       ul_seg_size + ul_seg1_size + ul_pad_size);
 			status = -ENOMEM;
 		}
@@ -503,7 +483,7 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 							      1)) == 0)) {
 				status =
 				    hio_mgr->intf_fxns->
-				    pfn_brd_mem_map(hio_mgr->hbridge_context,
+				    brd_mem_map(hio_mgr->bridge_context,
 						    pa_curr, va_curr,
 						    page_size[i], map_attrs,
 						    NULL);
@@ -547,38 +527,38 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 				 * This is the physical address written to
 				 * DSP MMU.
 				 */
-				ae_proc[ndx].ul_gpp_pa = pa_curr;
+				ae_proc[ndx].gpp_pa = pa_curr;
 				/*
 				 * This is the virtual uncached ioremapped
 				 * address!!!
 				 */
-				ae_proc[ndx].ul_gpp_va = gpp_va_curr;
-				ae_proc[ndx].ul_dsp_va =
+				ae_proc[ndx].gpp_va = gpp_va_curr;
+				ae_proc[ndx].dsp_va =
 				    va_curr / hio_mgr->word_size;
-				ae_proc[ndx].ul_size = page_size[i];
+				ae_proc[ndx].size = page_size[i];
 				ae_proc[ndx].endianism = HW_LITTLE_ENDIAN;
 				ae_proc[ndx].elem_size = HW_ELEM_SIZE16BIT;
 				ae_proc[ndx].mixed_mode = HW_MMU_CPUES;
 				dev_dbg(bridge, "shm MMU TLB entry PA %x"
 					" VA %x DSP_VA %x Size %x\n",
-					ae_proc[ndx].ul_gpp_pa,
-					ae_proc[ndx].ul_gpp_va,
-					ae_proc[ndx].ul_dsp_va *
+					ae_proc[ndx].gpp_pa,
+					ae_proc[ndx].gpp_va,
+					ae_proc[ndx].dsp_va *
 					hio_mgr->word_size, page_size[i]);
 				ndx++;
 			} else {
 				status =
 				    hio_mgr->intf_fxns->
-				    pfn_brd_mem_map(hio_mgr->hbridge_context,
+				    brd_mem_map(hio_mgr->bridge_context,
 						    pa_curr, va_curr,
 						    page_size[i], map_attrs,
 						    NULL);
 				dev_dbg(bridge,
 					"shm MMU PTE entry PA %x"
 					" VA %x DSP_VA %x Size %x\n",
-					ae_proc[ndx].ul_gpp_pa,
-					ae_proc[ndx].ul_gpp_va,
-					ae_proc[ndx].ul_dsp_va *
+					ae_proc[ndx].gpp_pa,
+					ae_proc[ndx].gpp_va,
+					ae_proc[ndx].dsp_va *
 					hio_mgr->word_size, page_size[i]);
 				if (status)
 					goto func_end;
@@ -600,47 +580,47 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 	 * should not conflict with shm entries on MPU or DSP side.
 	 */
 	for (i = 3; i < 7 && ndx < BRDIOCTL_NUMOFMMUTLB; i++) {
-		if (hio_mgr->ext_proc_info.ty_tlb[i].ul_gpp_phys == 0)
+		if (hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys == 0)
 			continue;
 
-		if ((hio_mgr->ext_proc_info.ty_tlb[i].ul_gpp_phys >
+		if ((hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys >
 		     ul_gpp_pa - 0x100000
-		     && hio_mgr->ext_proc_info.ty_tlb[i].ul_gpp_phys <=
+		     && hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys <=
 		     ul_gpp_pa + ul_seg_size)
-		    || (hio_mgr->ext_proc_info.ty_tlb[i].ul_dsp_virt >
+		    || (hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt >
 			ul_dsp_va - 0x100000 / hio_mgr->word_size
-			&& hio_mgr->ext_proc_info.ty_tlb[i].ul_dsp_virt <=
+			&& hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt <=
 			ul_dsp_va + ul_seg_size / hio_mgr->word_size)) {
 			dev_dbg(bridge,
 				"CDB MMU entry %d conflicts with "
 				"shm.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
 				"GppPa %x, DspVa %x, Bytes %x.\n", i,
-				hio_mgr->ext_proc_info.ty_tlb[i].ul_gpp_phys,
-				hio_mgr->ext_proc_info.ty_tlb[i].ul_dsp_virt,
+				hio_mgr->ext_proc_info.ty_tlb[i].gpp_phys,
+				hio_mgr->ext_proc_info.ty_tlb[i].dsp_virt,
 				ul_gpp_pa, ul_dsp_va, ul_seg_size);
 			status = -EPERM;
 		} else {
 			if (ndx < MAX_LOCK_TLB_ENTRIES) {
-				ae_proc[ndx].ul_dsp_va =
+				ae_proc[ndx].dsp_va =
 				    hio_mgr->ext_proc_info.ty_tlb[i].
-				    ul_dsp_virt;
-				ae_proc[ndx].ul_gpp_pa =
+				    dsp_virt;
+				ae_proc[ndx].gpp_pa =
 				    hio_mgr->ext_proc_info.ty_tlb[i].
-				    ul_gpp_phys;
-				ae_proc[ndx].ul_gpp_va = 0;
+				    gpp_phys;
+				ae_proc[ndx].gpp_va = 0;
 				/* 1 MB */
-				ae_proc[ndx].ul_size = 0x100000;
+				ae_proc[ndx].size = 0x100000;
 				dev_dbg(bridge, "shm MMU entry PA %x "
-					"DSP_VA 0x%x\n", ae_proc[ndx].ul_gpp_pa,
-					ae_proc[ndx].ul_dsp_va);
+					"DSP_VA 0x%x\n", ae_proc[ndx].gpp_pa,
+					ae_proc[ndx].dsp_va);
 				ndx++;
 			} else {
-				status = hio_mgr->intf_fxns->pfn_brd_mem_map
-				    (hio_mgr->hbridge_context,
+				status = hio_mgr->intf_fxns->brd_mem_map
+				    (hio_mgr->bridge_context,
 				     hio_mgr->ext_proc_info.ty_tlb[i].
-				     ul_gpp_phys,
+				     gpp_phys,
 				     hio_mgr->ext_proc_info.ty_tlb[i].
-				     ul_dsp_virt, 0x100000, map_attrs,
+				     dsp_virt, 0x100000, map_attrs,
 				     NULL);
 			}
 		}
@@ -657,8 +637,8 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 	/* Map the L4 peripherals */
 	i = 0;
 	while (l4_peripheral_table[i].phys_addr) {
-		status = hio_mgr->intf_fxns->pfn_brd_mem_map
-		    (hio_mgr->hbridge_context, l4_peripheral_table[i].phys_addr,
+		status = hio_mgr->intf_fxns->brd_mem_map
+		    (hio_mgr->bridge_context, l4_peripheral_table[i].phys_addr,
 		     l4_peripheral_table[i].dsp_virt_addr, HW_PAGE_SIZE4KB,
 		     map_attrs, NULL);
 		if (status)
@@ -667,33 +647,33 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 	}
 
 	for (i = ndx; i < BRDIOCTL_NUMOFMMUTLB; i++) {
-		ae_proc[i].ul_dsp_va = 0;
-		ae_proc[i].ul_gpp_pa = 0;
-		ae_proc[i].ul_gpp_va = 0;
-		ae_proc[i].ul_size = 0;
+		ae_proc[i].dsp_va = 0;
+		ae_proc[i].gpp_pa = 0;
+		ae_proc[i].gpp_va = 0;
+		ae_proc[i].size = 0;
 	}
 	/*
 	 * Set the shm physical address entry (grayed out in CDB file)
 	 * to the virtual uncached ioremapped address of shm reserved
 	 * on MPU.
 	 */
-	hio_mgr->ext_proc_info.ty_tlb[0].ul_gpp_phys =
+	hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys =
 	    (ul_gpp_va + ul_seg1_size + ul_pad_size);
 
 	/*
 	 * Need shm Phys addr. IO supports only one DSP for now:
 	 * num_procs = 1.
 	 */
-	if (!hio_mgr->ext_proc_info.ty_tlb[0].ul_gpp_phys || num_procs != 1) {
+	if (!hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys || num_procs != 1) {
 		status = -EFAULT;
 		goto func_end;
 	} else {
-		if (ae_proc[0].ul_dsp_va > ul_shm_base) {
+		if (ae_proc[0].dsp_va > ul_shm_base) {
 			status = -EPERM;
 			goto func_end;
 		}
 		/* ul_shm_base may not be at ul_dsp_va address */
-		ul_shm_base_offset = (ul_shm_base - ae_proc[0].ul_dsp_va) *
+		ul_shm_base_offset = (ul_shm_base - ae_proc[0].dsp_va) *
 		    hio_mgr->word_size;
 		/*
 		 * bridge_dev_ctrl() will set dev context dsp-mmu info. In
@@ -703,12 +683,12 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 		 */
 
 		status =
-		    hio_mgr->intf_fxns->pfn_dev_cntrl(hio_mgr->hbridge_context,
+		    hio_mgr->intf_fxns->dev_cntrl(hio_mgr->bridge_context,
 						      BRDIOCTL_SETMMUCONFIG,
 						      ae_proc);
 		if (status)
 			goto func_end;
-		ul_shm_base = hio_mgr->ext_proc_info.ty_tlb[0].ul_gpp_phys;
+		ul_shm_base = hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys;
 		ul_shm_base += ul_shm_base_offset;
 		ul_shm_base = (u32) MEM_LINEAR_ADDRESS((void *)ul_shm_base,
 						       ul_mem_length);
@@ -718,14 +698,14 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 		}
 		/* Register SM */
 		status =
-		    register_shm_segs(hio_mgr, cod_man, ae_proc[0].ul_gpp_pa);
+		    register_shm_segs(hio_mgr, cod_man, ae_proc[0].gpp_pa);
 	}
 
 	hio_mgr->shared_mem = (struct shm *)ul_shm_base;
 	hio_mgr->input = (u8 *) hio_mgr->shared_mem + sizeof(struct shm);
 	hio_mgr->output = hio_mgr->input + (ul_shm_length -
 					    sizeof(struct shm)) / 2;
-	hio_mgr->usm_buf_size = hio_mgr->output - hio_mgr->input;
+	hio_mgr->sm_buf_size = hio_mgr->output - hio_mgr->input;
 
 	/*  Set up Shared memory addresses for messaging. */
 	hio_mgr->msg_input_ctrl = (struct msg_ctrl *)((u8 *) hio_mgr->shared_mem
@@ -754,45 +734,45 @@ int bridge_io_on_loaded(struct io_mgr *hio_mgr)
 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG)
 	/* Get the start address of trace buffer */
 	status = cod_get_sym_value(cod_man, SYS_PUTCBEG,
-				   &hio_mgr->ul_trace_buffer_begin);
+				   &hio_mgr->trace_buffer_begin);
 	if (status) {
 		status = -EFAULT;
 		goto func_end;
 	}
 
-	hio_mgr->ul_gpp_read_pointer = hio_mgr->ul_trace_buffer_begin =
+	hio_mgr->gpp_read_pointer = hio_mgr->trace_buffer_begin =
 	    (ul_gpp_va + ul_seg1_size + ul_pad_size) +
-	    (hio_mgr->ul_trace_buffer_begin - ul_dsp_va);
+	    (hio_mgr->trace_buffer_begin - ul_dsp_va);
 	/* Get the end address of trace buffer */
 	status = cod_get_sym_value(cod_man, SYS_PUTCEND,
-				   &hio_mgr->ul_trace_buffer_end);
+				   &hio_mgr->trace_buffer_end);
 	if (status) {
 		status = -EFAULT;
 		goto func_end;
 	}
-	hio_mgr->ul_trace_buffer_end =
+	hio_mgr->trace_buffer_end =
 	    (ul_gpp_va + ul_seg1_size + ul_pad_size) +
-	    (hio_mgr->ul_trace_buffer_end - ul_dsp_va);
+	    (hio_mgr->trace_buffer_end - ul_dsp_va);
 	/* Get the current address of DSP write pointer */
 	status = cod_get_sym_value(cod_man, BRIDGE_SYS_PUTC_CURRENT,
-				   &hio_mgr->ul_trace_buffer_current);
+				   &hio_mgr->trace_buffer_current);
 	if (status) {
 		status = -EFAULT;
 		goto func_end;
 	}
-	hio_mgr->ul_trace_buffer_current =
+	hio_mgr->trace_buffer_current =
 	    (ul_gpp_va + ul_seg1_size + ul_pad_size) +
-	    (hio_mgr->ul_trace_buffer_current - ul_dsp_va);
+	    (hio_mgr->trace_buffer_current - ul_dsp_va);
 	/* Calculate the size of trace buffer */
-	kfree(hio_mgr->pmsg);
-	hio_mgr->pmsg = kmalloc(((hio_mgr->ul_trace_buffer_end -
-				hio_mgr->ul_trace_buffer_begin) *
+	kfree(hio_mgr->msg);
+	hio_mgr->msg = kmalloc(((hio_mgr->trace_buffer_end -
+				hio_mgr->trace_buffer_begin) *
 				hio_mgr->word_size) + 2, GFP_KERNEL);
-	if (!hio_mgr->pmsg)
+	if (!hio_mgr->msg)
 		status = -ENOMEM;
 
-	hio_mgr->ul_dsp_va = ul_dsp_va;
-	hio_mgr->ul_gpp_va = (ul_gpp_va + ul_seg1_size + ul_pad_size);
+	hio_mgr->dsp_va = ul_dsp_va;
+	hio_mgr->gpp_va = (ul_gpp_va + ul_seg1_size + ul_pad_size);
 
 #endif
 func_end:
@@ -806,7 +786,7 @@ func_end:
 u32 io_buf_size(struct io_mgr *hio_mgr)
 {
 	if (hio_mgr)
-		return hio_mgr->usm_buf_size;
+		return hio_mgr->sm_buf_size;
 	else
 		return 0;
 }
@@ -827,7 +807,7 @@ void io_cancel_chnl(struct io_mgr *hio_mgr, u32 chnl)
 	/* Inform DSP that we have no more buffers on this channel */
 	set_chnl_free(sm, chnl);
 
-	sm_interrupt_dsp(pio_mgr->hbridge_context, MBX_PCPY_CLASS);
+	sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
 func_end:
 	return;
 }
@@ -849,7 +829,7 @@ static void io_dispatch_pm(struct io_mgr *pio_mgr)
 	if (parg[0] == MBX_PM_HIBERNATE_EN) {
 		dev_dbg(bridge, "PM: Hibernate command\n");
 		status = pio_mgr->intf_fxns->
-				pfn_dev_cntrl(pio_mgr->hbridge_context,
+				dev_cntrl(pio_mgr->bridge_context,
 					      BRDIOCTL_PWR_HIBERNATE, parg);
 		if (status)
 			pr_err("%s: hibernate cmd failed 0x%x\n",
@@ -858,7 +838,7 @@ static void io_dispatch_pm(struct io_mgr *pio_mgr)
 		parg[1] = pio_mgr->shared_mem->opp_request.rqst_opp_pt;
 		dev_dbg(bridge, "PM: Requested OPP = 0x%x\n", parg[1]);
 		status = pio_mgr->intf_fxns->
-				pfn_dev_cntrl(pio_mgr->hbridge_context,
+				dev_cntrl(pio_mgr->bridge_context,
 					BRDIOCTL_CONSTRAINT_REQUEST, parg);
 		if (status)
 			dev_dbg(bridge, "PM: Failed to set constraint "
@@ -867,7 +847,7 @@ static void io_dispatch_pm(struct io_mgr *pio_mgr)
 		dev_dbg(bridge, "PM: clk control value of msg = 0x%x\n",
 			parg[0]);
 		status = pio_mgr->intf_fxns->
-				pfn_dev_cntrl(pio_mgr->hbridge_context,
+				dev_cntrl(pio_mgr->bridge_context,
 					      BRDIOCTL_CLK_CTRL, parg);
 		if (status)
 			dev_dbg(bridge, "PM: Failed to ctrl the DSP clk"
@@ -892,9 +872,9 @@ void io_dpc(unsigned long ref_data)
 
 	if (!pio_mgr)
 		goto func_end;
-	chnl_mgr_obj = pio_mgr->hchnl_mgr;
-	dev_get_msg_mgr(pio_mgr->hdev_obj, &msg_mgr_obj);
-	dev_get_deh_mgr(pio_mgr->hdev_obj, &hdeh_mgr);
+	chnl_mgr_obj = pio_mgr->chnl_mgr;
+	dev_get_msg_mgr(pio_mgr->dev_obj, &msg_mgr_obj);
+	dev_get_deh_mgr(pio_mgr->dev_obj, &hdeh_mgr);
 	if (!chnl_mgr_obj)
 		goto func_end;
 
@@ -990,15 +970,15 @@ void io_request_chnl(struct io_mgr *io_manager, struct chnl_object *pchnl,
 
 	if (!pchnl || !mbx_val)
 		goto func_end;
-	chnl_mgr_obj = io_manager->hchnl_mgr;
+	chnl_mgr_obj = io_manager->chnl_mgr;
 	sm = io_manager->shared_mem;
 	if (io_mode == IO_INPUT) {
 		/*
 		 * Assertion fires if CHNL_AddIOReq() called on a stream
 		 * which was cancelled, or attached to a dead board.
 		 */
-		DBC_ASSERT((pchnl->dw_state == CHNL_STATEREADY) ||
-			   (pchnl->dw_state == CHNL_STATEEOS));
+		DBC_ASSERT((pchnl->state == CHNL_STATEREADY) ||
+			   (pchnl->state == CHNL_STATEEOS));
 		/* Indicate to the DSP we have a buffer available for input */
 		set_chnl_busy(sm, pchnl->chnl_id);
 		*mbx_val = MBX_PCPY_CLASS;
@@ -1007,13 +987,13 @@ void io_request_chnl(struct io_mgr *io_manager, struct chnl_object *pchnl,
 		 * This assertion fails if CHNL_AddIOReq() was called on a
 		 * stream which was cancelled, or attached to a dead board.
 		 */
-		DBC_ASSERT((pchnl->dw_state & ~CHNL_STATEEOS) ==
+		DBC_ASSERT((pchnl->state & ~CHNL_STATEEOS) ==
 			   CHNL_STATEREADY);
 		/*
 		 * Record the fact that we have a buffer available for
 		 * output.
 		 */
-		chnl_mgr_obj->dw_output_mask |= (1 << pchnl->chnl_id);
+		chnl_mgr_obj->output_mask |= (1 << pchnl->chnl_id);
 	} else {
 		DBC_ASSERT(io_mode);	/* Shouldn't get here. */
 	}
@@ -1056,7 +1036,7 @@ static u32 find_ready_output(struct chnl_mgr *chnl_mgr_obj,
 	u32 shift;
 
 	id = (pchnl !=
-	      NULL ? pchnl->chnl_id : (chnl_mgr_obj->dw_last_output + 1));
+	      NULL ? pchnl->chnl_id : (chnl_mgr_obj->last_output + 1));
 	id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
 	if (id >= CHNL_MAXCHANNELS)
 		goto func_end;
@@ -1067,7 +1047,7 @@ static u32 find_ready_output(struct chnl_mgr *chnl_mgr_obj,
 			if (mask & shift) {
 				ret = id;
 				if (pchnl == NULL)
-					chnl_mgr_obj->dw_last_output = id;
+					chnl_mgr_obj->last_output = id;
 				break;
 			}
 			id = id + 1;
@@ -1096,7 +1076,7 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 	bool notify_client = false;
 
 	sm = pio_mgr->shared_mem;
-	chnl_mgr_obj = pio_mgr->hchnl_mgr;
+	chnl_mgr_obj = pio_mgr->chnl_mgr;
 
 	/* Attempt to perform input */
 	if (!sm->input_full)
@@ -1110,18 +1090,20 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 		DBC_ASSERT(chnl_id);
 		goto func_end;
 	}
-	pchnl = chnl_mgr_obj->ap_channel[chnl_id];
+	pchnl = chnl_mgr_obj->channels[chnl_id];
 	if ((pchnl != NULL) && CHNL_IS_INPUT(pchnl->chnl_mode)) {
-		if ((pchnl->dw_state & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
-			if (!pchnl->pio_requests)
-				goto func_end;
+		if ((pchnl->state & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
 			/* Get the I/O request, and attempt a transfer */
-			chnl_packet_obj = (struct chnl_irp *)
-			    lst_get_head(pchnl->pio_requests);
-			if (chnl_packet_obj) {
-				pchnl->cio_reqs--;
-				if (pchnl->cio_reqs < 0)
+			if (!list_empty(&pchnl->io_requests)) {
+				if (!pchnl->cio_reqs)
 					goto func_end;
+
+				chnl_packet_obj = list_first_entry(
+						&pchnl->io_requests,
+						struct chnl_irp, link);
+				list_del(&chnl_packet_obj->link);
+				pchnl->cio_reqs--;
+
 				/*
 				 * Ensure we don't overflow the client's
 				 * buffer.
@@ -1131,7 +1113,7 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 						pio_mgr->input, bytes);
 				pchnl->bytes_moved += bytes;
 				chnl_packet_obj->byte_size = bytes;
-				chnl_packet_obj->dw_arg = dw_arg;
+				chnl_packet_obj->arg = dw_arg;
 				chnl_packet_obj->status = CHNL_IOCSTATCOMPLETE;
 
 				if (bytes == 0) {
@@ -1140,7 +1122,7 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 					 * sends EOS more than once on this
 					 * channel.
 					 */
-					if (pchnl->dw_state & CHNL_STATEEOS)
+					if (pchnl->state & CHNL_STATEEOS)
 						goto func_end;
 					/*
 					 * Zero bytes indicates EOS. Update
@@ -1148,21 +1130,18 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 					 * the channel state.
 					 */
 					chnl_packet_obj->status |=
-					    CHNL_IOCSTATEOS;
-					pchnl->dw_state |= CHNL_STATEEOS;
+						CHNL_IOCSTATEOS;
+					pchnl->state |= CHNL_STATEEOS;
 					/*
 					 * Notify that end of stream has
 					 * occurred.
 					 */
 					ntfy_notify(pchnl->ntfy_obj,
-						    DSP_STREAMDONE);
+							DSP_STREAMDONE);
 				}
 				/* Tell DSP if no more I/O buffers available */
-				if (!pchnl->pio_requests)
-					goto func_end;
-				if (LST_IS_EMPTY(pchnl->pio_requests)) {
+				if (list_empty(&pchnl->io_requests))
 					set_chnl_free(sm, pchnl->chnl_id);
-				}
 				clear_chnl = true;
 				notify_client = true;
 			} else {
@@ -1185,7 +1164,7 @@ static void input_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 	if (clear_chnl) {
 		/* Indicate to the DSP we have read the input */
 		sm->input_full = 0;
-		sm_interrupt_dsp(pio_mgr->hbridge_context, MBX_PCPY_CLASS);
+		sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
 	}
 	if (notify_client) {
 		/* Notify client with IO completion record */
@@ -1216,89 +1195,73 @@ static void input_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr)
 	input_empty = msg_ctr_obj->buf_empty;
 	num_msgs = msg_ctr_obj->size;
 	if (input_empty)
-		goto func_end;
+		return;
 
 	msg_input = pio_mgr->msg_input;
 	for (i = 0; i < num_msgs; i++) {
 		/* Read the next message */
-		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.dw_cmd);
-		msg.msg.dw_cmd =
-		    read_ext32_bit_dsp_data(pio_mgr->hbridge_context, addr);
-		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.dw_arg1);
-		msg.msg.dw_arg1 =
-		    read_ext32_bit_dsp_data(pio_mgr->hbridge_context, addr);
-		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.dw_arg2);
-		msg.msg.dw_arg2 =
-		    read_ext32_bit_dsp_data(pio_mgr->hbridge_context, addr);
+		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.cmd);
+		msg.msg.cmd =
+			read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
+		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.arg1);
+		msg.msg.arg1 =
+			read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
+		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msg.arg2);
+		msg.msg.arg2 =
+			read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
 		addr = (u32) &(((struct msg_dspmsg *)msg_input)->msgq_id);
 		msg.msgq_id =
-		    read_ext32_bit_dsp_data(pio_mgr->hbridge_context, addr);
+			read_ext32_bit_dsp_data(pio_mgr->bridge_context, addr);
 		msg_input += sizeof(struct msg_dspmsg);
-		if (!hmsg_mgr->queue_list)
-			goto func_end;
 
 		/* Determine which queue to put the message in */
-		msg_queue_obj =
-		    (struct msg_queue *)lst_first(hmsg_mgr->queue_list);
-		dev_dbg(bridge,	"input msg: dw_cmd=0x%x dw_arg1=0x%x "
-			"dw_arg2=0x%x msgq_id=0x%x \n", msg.msg.dw_cmd,
-			msg.msg.dw_arg1, msg.msg.dw_arg2, msg.msgq_id);
+		dev_dbg(bridge,	"input msg: cmd=0x%x arg1=0x%x "
+				"arg2=0x%x msgq_id=0x%x\n", msg.msg.cmd,
+				msg.msg.arg1, msg.msg.arg2, msg.msgq_id);
 		/*
 		 * Interrupt may occur before shared memory and message
 		 * input locations have been set up. If all nodes were
 		 * cleaned up, hmsg_mgr->max_msgs should be 0.
 		 */
-		while (msg_queue_obj != NULL) {
-			if (msg.msgq_id == msg_queue_obj->msgq_id) {
-				/* Found it */
-				if (msg.msg.dw_cmd == RMS_EXITACK) {
-					/*
-					 * Call the node exit notification.
-					 * The exit message does not get
-					 * queued.
-					 */
-					(*hmsg_mgr->on_exit) ((void *)
-							   msg_queue_obj->arg,
-							   msg.msg.dw_arg1);
-				} else {
-					/*
-					 * Not an exit acknowledgement, queue
-					 * the message.
-					 */
-					if (!msg_queue_obj->msg_free_list)
-						goto func_end;
-					pmsg = (struct msg_frame *)lst_get_head
-					    (msg_queue_obj->msg_free_list);
-					if (msg_queue_obj->msg_used_list
-					    && pmsg) {
-						pmsg->msg_data = msg;
-						lst_put_tail
-						 (msg_queue_obj->msg_used_list,
-						     (struct list_head *)pmsg);
-						ntfy_notify
-						    (msg_queue_obj->ntfy_obj,
-						     DSP_NODEMESSAGEREADY);
-						sync_set_event
-						    (msg_queue_obj->sync_event);
-					} else {
-						/*
-						 * No free frame to copy the
-						 * message into.
-						 */
-						pr_err("%s: no free msg frames,"
-						       " discarding msg\n",
-						       __func__);
-					}
-				}
+		list_for_each_entry(msg_queue_obj, &hmsg_mgr->queue_list,
+				list_elem) {
+			if (msg.msgq_id != msg_queue_obj->msgq_id)
+				continue;
+			/* Found it */
+			if (msg.msg.cmd == RMS_EXITACK) {
+				/*
+				 * Call the node exit notification.
+				 * The exit message does not get
+				 * queued.
+				 */
+				(*hmsg_mgr->on_exit)(msg_queue_obj->arg,
+						msg.msg.arg1);
+				break;
+			}
+			/*
+			 * Not an exit acknowledgement, queue
+			 * the message.
+			 */
+			if (list_empty(&msg_queue_obj->msg_free_list)) {
+				/*
+				 * No free frame to copy the
+				 * message into.
+				 */
+				pr_err("%s: no free msg frames,"
+						" discarding msg\n",
+						__func__);
 				break;
 			}
 
-			if (!hmsg_mgr->queue_list || !msg_queue_obj)
-				goto func_end;
-			msg_queue_obj =
-			    (struct msg_queue *)lst_next(hmsg_mgr->queue_list,
-							 (struct list_head *)
-							 msg_queue_obj);
+			pmsg = list_first_entry(&msg_queue_obj->msg_free_list,
+					struct msg_frame, list_elem);
+			list_del(&pmsg->list_elem);
+			pmsg->msg_data = msg;
+			list_add_tail(&pmsg->list_elem,
+					&msg_queue_obj->msg_used_list);
+			ntfy_notify(msg_queue_obj->ntfy_obj,
+					DSP_NODEMESSAGEREADY);
+			sync_set_event(msg_queue_obj->sync_event);
 		}
 	}
 	/* Set the post SWI flag */
@@ -1306,10 +1269,8 @@ static void input_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr)
 		/* Tell the DSP we've read the messages */
 		msg_ctr_obj->buf_empty = true;
 		msg_ctr_obj->post_swi = true;
-		sm_interrupt_dsp(pio_mgr->hbridge_context, MBX_PCPY_CLASS);
+		sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
 	}
-func_end:
-	return;
 }
 
 /*
@@ -1322,8 +1283,7 @@ static void notify_chnl_complete(struct chnl_object *pchnl,
 {
 	bool signal_event;
 
-	if (!pchnl || !pchnl->sync_event ||
-	    !pchnl->pio_completions || !chnl_packet_obj)
+	if (!pchnl || !pchnl->sync_event || !chnl_packet_obj)
 		goto func_end;
 
 	/*
@@ -1332,10 +1292,9 @@ static void notify_chnl_complete(struct chnl_object *pchnl,
 	 * signalled by the only IO completion list consumer:
 	 * bridge_chnl_get_ioc().
 	 */
-	signal_event = LST_IS_EMPTY(pchnl->pio_completions);
+	signal_event = list_empty(&pchnl->io_completions);
 	/* Enqueue the IO completion info for the client */
-	lst_put_tail(pchnl->pio_completions,
-		     (struct list_head *)chnl_packet_obj);
+	list_add_tail(&chnl_packet_obj->link, &pchnl->io_completions);
 	pchnl->cio_cs++;
 
 	if (pchnl->cio_cs > pchnl->chnl_packets)
@@ -1364,49 +1323,51 @@ static void output_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 	struct chnl_irp *chnl_packet_obj;
 	u32 dw_dsp_f_mask;
 
-	chnl_mgr_obj = pio_mgr->hchnl_mgr;
+	chnl_mgr_obj = pio_mgr->chnl_mgr;
 	sm = pio_mgr->shared_mem;
 	/* Attempt to perform output */
 	if (sm->output_full)
 		goto func_end;
 
-	if (pchnl && !((pchnl->dw_state & ~CHNL_STATEEOS) == CHNL_STATEREADY))
+	if (pchnl && !((pchnl->state & ~CHNL_STATEEOS) == CHNL_STATEREADY))
 		goto func_end;
 
 	/* Look to see if both a PC and DSP output channel are ready */
 	dw_dsp_f_mask = sm->dsp_free_mask;
 	chnl_id =
 	    find_ready_output(chnl_mgr_obj, pchnl,
-			      (chnl_mgr_obj->dw_output_mask & dw_dsp_f_mask));
+			      (chnl_mgr_obj->output_mask & dw_dsp_f_mask));
 	if (chnl_id == OUTPUTNOTREADY)
 		goto func_end;
 
-	pchnl = chnl_mgr_obj->ap_channel[chnl_id];
-	if (!pchnl || !pchnl->pio_requests) {
+	pchnl = chnl_mgr_obj->channels[chnl_id];
+	if (!pchnl || list_empty(&pchnl->io_requests)) {
 		/* Shouldn't get here */
 		goto func_end;
 	}
-	/* Get the I/O request, and attempt a transfer */
-	chnl_packet_obj = (struct chnl_irp *)lst_get_head(pchnl->pio_requests);
-	if (!chnl_packet_obj)
+
+	if (!pchnl->cio_reqs)
 		goto func_end;
 
+	/* Get the I/O request, and attempt a transfer */
+	chnl_packet_obj = list_first_entry(&pchnl->io_requests,
+			struct chnl_irp, link);
+	list_del(&chnl_packet_obj->link);
+
 	pchnl->cio_reqs--;
-	if (pchnl->cio_reqs < 0 || !pchnl->pio_requests)
-		goto func_end;
 
 	/* Record fact that no more I/O buffers available */
-	if (LST_IS_EMPTY(pchnl->pio_requests))
-		chnl_mgr_obj->dw_output_mask &= ~(1 << chnl_id);
+	if (list_empty(&pchnl->io_requests))
+		chnl_mgr_obj->output_mask &= ~(1 << chnl_id);
 
 	/* Transfer buffer to DSP side */
-	chnl_packet_obj->byte_size = min(pio_mgr->usm_buf_size,
+	chnl_packet_obj->byte_size = min(pio_mgr->sm_buf_size,
 					chnl_packet_obj->byte_size);
 	memcpy(pio_mgr->output,	chnl_packet_obj->host_sys_buf,
 					chnl_packet_obj->byte_size);
 	pchnl->bytes_moved += chnl_packet_obj->byte_size;
 	/* Write all 32 bits of arg */
-	sm->arg = chnl_packet_obj->dw_arg;
+	sm->arg = chnl_packet_obj->arg;
 #if _CHNL_WORDSIZE == 2
 	/* Access can be different SM access word size (e.g. 16/32 bit words) */
 	sm->output_id = (u16) chnl_id;
@@ -1420,7 +1381,7 @@ static void output_chnl(struct io_mgr *pio_mgr, struct chnl_object *pchnl,
 #endif
 	sm->output_full =  1;
 	/* Indicate to the DSP we have written the output */
-	sm_interrupt_dsp(pio_mgr->hbridge_context, MBX_PCPY_CLASS);
+	sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
 	/* Notify client with IO completion record (keep EOS) */
 	chnl_packet_obj->status &= CHNL_IOCSTATEOS;
 	notify_chnl_complete(pchnl, chnl_packet_obj);
@@ -1440,81 +1401,69 @@ static void output_msg(struct io_mgr *pio_mgr, struct msg_mgr *hmsg_mgr)
 {
 	u32 num_msgs = 0;
 	u32 i;
-	u8 *msg_output;
+	struct msg_dspmsg *msg_output;
 	struct msg_frame *pmsg;
 	struct msg_ctrl *msg_ctr_obj;
-	u32 output_empty;
 	u32 val;
 	u32 addr;
 
 	msg_ctr_obj = pio_mgr->msg_output_ctrl;
 
 	/* Check if output has been cleared */
-	output_empty = msg_ctr_obj->buf_empty;
-	if (output_empty) {
-		num_msgs = (hmsg_mgr->msgs_pending > hmsg_mgr->max_msgs) ?
-		    hmsg_mgr->max_msgs : hmsg_mgr->msgs_pending;
-		msg_output = pio_mgr->msg_output;
-		/* Copy num_msgs messages into shared memory */
-		for (i = 0; i < num_msgs; i++) {
-			if (!hmsg_mgr->msg_used_list) {
-				pmsg = NULL;
-				goto func_end;
-			} else {
-				pmsg = (struct msg_frame *)
-				    lst_get_head(hmsg_mgr->msg_used_list);
-			}
-			if (pmsg != NULL) {
-				val = (pmsg->msg_data).msgq_id;
-				addr = (u32) &(((struct msg_dspmsg *)
-						 msg_output)->msgq_id);
-				write_ext32_bit_dsp_data(
-					pio_mgr->hbridge_context, addr, val);
-				val = (pmsg->msg_data).msg.dw_cmd;
-				addr = (u32) &((((struct msg_dspmsg *)
-						  msg_output)->msg).dw_cmd);
-				write_ext32_bit_dsp_data(
-					pio_mgr->hbridge_context, addr, val);
-				val = (pmsg->msg_data).msg.dw_arg1;
-				addr = (u32) &((((struct msg_dspmsg *)
-						  msg_output)->msg).dw_arg1);
-				write_ext32_bit_dsp_data(
-					pio_mgr->hbridge_context, addr, val);
-				val = (pmsg->msg_data).msg.dw_arg2;
-				addr = (u32) &((((struct msg_dspmsg *)
-						  msg_output)->msg).dw_arg2);
-				write_ext32_bit_dsp_data(
-					pio_mgr->hbridge_context, addr, val);
-				msg_output += sizeof(struct msg_dspmsg);
-				if (!hmsg_mgr->msg_free_list)
-					goto func_end;
-				lst_put_tail(hmsg_mgr->msg_free_list,
-					     (struct list_head *)pmsg);
-				sync_set_event(hmsg_mgr->sync_event);
-			}
-		}
+	if (!msg_ctr_obj->buf_empty)
+		return;
+
+	num_msgs = (hmsg_mgr->msgs_pending > hmsg_mgr->max_msgs) ?
+		hmsg_mgr->max_msgs : hmsg_mgr->msgs_pending;
+	msg_output = (struct msg_dspmsg *) pio_mgr->msg_output;
+
+	/* Copy num_msgs messages into shared memory */
+	for (i = 0; i < num_msgs; i++) {
+		if (list_empty(&hmsg_mgr->msg_used_list))
+			continue;
+
+		pmsg = list_first_entry(&hmsg_mgr->msg_used_list,
+				struct msg_frame, list_elem);
+		list_del(&pmsg->list_elem);
+
+		val = (pmsg->msg_data).msgq_id;
+		addr = (u32) &msg_output->msgq_id;
+		write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
+
+		val = (pmsg->msg_data).msg.cmd;
+		addr = (u32) &msg_output->msg.cmd;
+		write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
+
+		val = (pmsg->msg_data).msg.arg1;
+		addr = (u32) &msg_output->msg.arg1;
+		write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
+
+		val = (pmsg->msg_data).msg.arg2;
+		addr = (u32) &msg_output->msg.arg2;
+		write_ext32_bit_dsp_data(pio_mgr->bridge_context, addr, val);
+
+		msg_output++;
+		list_add_tail(&pmsg->list_elem, &hmsg_mgr->msg_free_list);
+		sync_set_event(hmsg_mgr->sync_event);
+	}
 
-		if (num_msgs > 0) {
-			hmsg_mgr->msgs_pending -= num_msgs;
+	if (num_msgs > 0) {
+		hmsg_mgr->msgs_pending -= num_msgs;
 #if _CHNL_WORDSIZE == 2
-			/*
-			 * Access can be different SM access word size
-			 * (e.g. 16/32 bit words)
-			 */
-			msg_ctr_obj->size = (u16) num_msgs;
+		/*
+		 * Access can be different SM access word size
+		 * (e.g. 16/32 bit words)
+		 */
+		msg_ctr_obj->size = (u16) num_msgs;
 #else
-			msg_ctr_obj->size = num_msgs;
+		msg_ctr_obj->size = num_msgs;
 #endif
-			msg_ctr_obj->buf_empty = false;
-			/* Set the post SWI flag */
-			msg_ctr_obj->post_swi = true;
-			/* Tell the DSP we have written the output. */
-			sm_interrupt_dsp(pio_mgr->hbridge_context,
-						MBX_PCPY_CLASS);
-		}
+		msg_ctr_obj->buf_empty = false;
+		/* Set the post SWI flag */
+		msg_ctr_obj->post_swi = true;
+		/* Tell the DSP we have written the output. */
+		sm_interrupt_dsp(pio_mgr->bridge_context, MBX_PCPY_CLASS);
 	}
-func_end:
-	return;
 }
 
 /*
@@ -1569,9 +1518,9 @@ static int register_shm_segs(struct io_mgr *hio_mgr,
 	}
 	/* Register with CMM */
 	if (!status) {
-		status = dev_get_cmm_mgr(hio_mgr->hdev_obj, &hio_mgr->hcmm_mgr);
+		status = dev_get_cmm_mgr(hio_mgr->dev_obj, &hio_mgr->cmm_mgr);
 		if (!status) {
-			status = cmm_un_register_gppsm_seg(hio_mgr->hcmm_mgr,
+			status = cmm_un_register_gppsm_seg(hio_mgr->cmm_mgr,
 							   CMM_ALLSEGMENTS);
 		}
 	}
@@ -1592,10 +1541,10 @@ static int register_shm_segs(struct io_mgr *hio_mgr,
 			goto func_end;
 		}
 		/* First TLB entry reserved for Bridge SM use. */
-		ul_gpp_phys = hio_mgr->ext_proc_info.ty_tlb[0].ul_gpp_phys;
+		ul_gpp_phys = hio_mgr->ext_proc_info.ty_tlb[0].gpp_phys;
 		/* Get size in bytes */
 		ul_dsp_virt =
-		    hio_mgr->ext_proc_info.ty_tlb[0].ul_dsp_virt *
+		    hio_mgr->ext_proc_info.ty_tlb[0].dsp_virt *
 		    hio_mgr->word_size;
 		/*
 		 * Calc byte offset used to convert GPP phys <-> DSP byte
@@ -1626,7 +1575,7 @@ static int register_shm_segs(struct io_mgr *hio_mgr,
 		    ul_dsp_virt;
 		/* Register SM Segment 0. */
 		status =
-		    cmm_register_gppsm_seg(hio_mgr->hcmm_mgr, dw_gpp_base_pa,
+		    cmm_register_gppsm_seg(hio_mgr->cmm_mgr, dw_gpp_base_pa,
 					   ul_rsrvd_size, dw_offset,
 					   (dw_gpp_base_pa >
 					    ul_dsp_virt) ? CMM_ADDTODSPPA :
@@ -1714,6 +1663,9 @@ int io_sh_msetting(struct io_mgr *hio_mgr, u8 desc, void *pargs)
 int bridge_io_get_proc_load(struct io_mgr *hio_mgr,
 				struct dsp_procloadstat *proc_lstat)
 {
+	if (!hio_mgr->shared_mem)
+		return -EFAULT;
+
 	proc_lstat->curr_load =
 			hio_mgr->shared_mem->load_mon_info.curr_dsp_load;
 	proc_lstat->predicted_load =
@@ -1730,10 +1682,6 @@ int bridge_io_get_proc_load(struct io_mgr *hio_mgr,
 	return 0;
 }
 
-void io_sm_init(void)
-{
-	/* Do nothing */
-}
 
 #if defined(CONFIG_TIDSPBRIDGE_BACKTRACE) || defined(CONFIG_TIDSPBRIDGE_DEBUG)
 void print_dsp_debug_trace(struct io_mgr *hio_mgr)
@@ -1743,54 +1691,54 @@ void print_dsp_debug_trace(struct io_mgr *hio_mgr)
 	while (true) {
 		/* Get the DSP current pointer */
 		ul_gpp_cur_pointer =
-		    *(u32 *) (hio_mgr->ul_trace_buffer_current);
+		    *(u32 *) (hio_mgr->trace_buffer_current);
 		ul_gpp_cur_pointer =
-		    hio_mgr->ul_gpp_va + (ul_gpp_cur_pointer -
-					  hio_mgr->ul_dsp_va);
+		    hio_mgr->gpp_va + (ul_gpp_cur_pointer -
+					  hio_mgr->dsp_va);
 
 		/* No new debug messages available yet */
-		if (ul_gpp_cur_pointer == hio_mgr->ul_gpp_read_pointer) {
+		if (ul_gpp_cur_pointer == hio_mgr->gpp_read_pointer) {
 			break;
-		} else if (ul_gpp_cur_pointer > hio_mgr->ul_gpp_read_pointer) {
+		} else if (ul_gpp_cur_pointer > hio_mgr->gpp_read_pointer) {
 			/* Continuous data */
 			ul_new_message_length =
-			    ul_gpp_cur_pointer - hio_mgr->ul_gpp_read_pointer;
+			    ul_gpp_cur_pointer - hio_mgr->gpp_read_pointer;
 
-			memcpy(hio_mgr->pmsg,
-			       (char *)hio_mgr->ul_gpp_read_pointer,
+			memcpy(hio_mgr->msg,
+			       (char *)hio_mgr->gpp_read_pointer,
 			       ul_new_message_length);
-			hio_mgr->pmsg[ul_new_message_length] = '\0';
+			hio_mgr->msg[ul_new_message_length] = '\0';
 			/*
 			 * Advance the GPP trace pointer to DSP current
 			 * pointer.
 			 */
-			hio_mgr->ul_gpp_read_pointer += ul_new_message_length;
+			hio_mgr->gpp_read_pointer += ul_new_message_length;
 			/* Print the trace messages */
-			pr_info("DSPTrace: %s\n", hio_mgr->pmsg);
-		} else if (ul_gpp_cur_pointer < hio_mgr->ul_gpp_read_pointer) {
+			pr_info("DSPTrace: %s\n", hio_mgr->msg);
+		} else if (ul_gpp_cur_pointer < hio_mgr->gpp_read_pointer) {
 			/* Handle trace buffer wraparound */
-			memcpy(hio_mgr->pmsg,
-			       (char *)hio_mgr->ul_gpp_read_pointer,
-			       hio_mgr->ul_trace_buffer_end -
-			       hio_mgr->ul_gpp_read_pointer);
+			memcpy(hio_mgr->msg,
+			       (char *)hio_mgr->gpp_read_pointer,
+			       hio_mgr->trace_buffer_end -
+			       hio_mgr->gpp_read_pointer);
 			ul_new_message_length =
-			    ul_gpp_cur_pointer - hio_mgr->ul_trace_buffer_begin;
-			memcpy(&hio_mgr->pmsg[hio_mgr->ul_trace_buffer_end -
-					      hio_mgr->ul_gpp_read_pointer],
-			       (char *)hio_mgr->ul_trace_buffer_begin,
+			    ul_gpp_cur_pointer - hio_mgr->trace_buffer_begin;
+			memcpy(&hio_mgr->msg[hio_mgr->trace_buffer_end -
+					      hio_mgr->gpp_read_pointer],
+			       (char *)hio_mgr->trace_buffer_begin,
 			       ul_new_message_length);
-			hio_mgr->pmsg[hio_mgr->ul_trace_buffer_end -
-				      hio_mgr->ul_gpp_read_pointer +
+			hio_mgr->msg[hio_mgr->trace_buffer_end -
+				      hio_mgr->gpp_read_pointer +
 				      ul_new_message_length] = '\0';
 			/*
 			 * Advance the GPP trace pointer to DSP current
 			 * pointer.
 			 */
-			hio_mgr->ul_gpp_read_pointer =
-			    hio_mgr->ul_trace_buffer_begin +
+			hio_mgr->gpp_read_pointer =
+			    hio_mgr->trace_buffer_begin +
 			    ul_new_message_length;
 			/* Print the trace messages */
-			pr_info("DSPTrace: %s\n", hio_mgr->pmsg);
+			pr_info("DSPTrace: %s\n", hio_mgr->msg);
 		}
 	}
 }
@@ -1828,7 +1776,7 @@ int print_dsp_trace_buffer(struct bridge_dev_context *hbridge_context)
 	struct bridge_dev_context *pbridge_context = hbridge_context;
 	struct bridge_drv_interface *intf_fxns;
 	struct dev_object *dev_obj = (struct dev_object *)
-	    pbridge_context->hdev_obj;
+	    pbridge_context->dev_obj;
 
 	status = dev_get_cod_mgr(dev_obj, &cod_mgr);
 
@@ -1862,7 +1810,7 @@ int print_dsp_trace_buffer(struct bridge_dev_context *hbridge_context)
 	psz_buf = kzalloc(ul_num_bytes + 2, GFP_ATOMIC);
 	if (psz_buf != NULL) {
 		/* Read trace buffer data */
-		status = (*intf_fxns->pfn_brd_read)(pbridge_context,
+		status = (*intf_fxns->brd_read)(pbridge_context,
 			(u8 *)psz_buf, (u32)ul_trace_begin,
 			ul_num_bytes, 0);
 
@@ -1877,7 +1825,7 @@ int print_dsp_trace_buffer(struct bridge_dev_context *hbridge_context)
 			__func__, psz_buf);
 
 		/* Read the value at the DSP address in trace_cur_pos. */
-		status = (*intf_fxns->pfn_brd_read)(pbridge_context,
+		status = (*intf_fxns->brd_read)(pbridge_context,
 				(u8 *)&trace_cur_pos, (u32)trace_cur_pos,
 				4, 0);
 		if (status)
@@ -2001,7 +1949,7 @@ int dump_dsp_stack(struct bridge_dev_context *bridge_context)
 				"ILC", "RILC", "IER", "CSR"};
 	const char *exec_ctxt[] = {"Task", "SWI", "HWI", "Unknown"};
 	struct bridge_drv_interface *intf_fxns;
-	struct dev_object *dev_object = bridge_context->hdev_obj;
+	struct dev_object *dev_object = bridge_context->dev_obj;
 
 	status = dev_get_cod_mgr(dev_object, &code_mgr);
 	if (!code_mgr) {
@@ -2044,7 +1992,7 @@ int dump_dsp_stack(struct bridge_dev_context *bridge_context)
 			poll_cnt < POLL_MAX) {
 
 			/* Read DSP dump size from the DSP trace buffer... */
-			status = (*intf_fxns->pfn_brd_read)(bridge_context,
+			status = (*intf_fxns->brd_read)(bridge_context,
 				(u8 *)&mmu_fault_dbg_info, (u32)trace_begin,
 				sizeof(mmu_fault_dbg_info), 0);
 
@@ -2080,7 +2028,7 @@ int dump_dsp_stack(struct bridge_dev_context *bridge_context)
 		buffer_end =  buffer + total_size / 4;
 
 		/* Read bytes from the DSP trace buffer... */
-		status = (*intf_fxns->pfn_brd_read)(bridge_context,
+		status = (*intf_fxns->brd_read)(bridge_context,
 				(u8 *)buffer, (u32)trace_begin,
 				total_size, 0);
 		if (status) {
@@ -2207,7 +2155,7 @@ void dump_dl_modules(struct bridge_dev_context *bridge_context)
 	struct cod_manager *code_mgr;
 	struct bridge_drv_interface *intf_fxns;
 	struct bridge_dev_context *bridge_ctxt = bridge_context;
-	struct dev_object *dev_object = bridge_ctxt->hdev_obj;
+	struct dev_object *dev_object = bridge_ctxt->dev_obj;
 	struct modules_header modules_hdr;
 	struct dll_module *module_struct = NULL;
 	u32 module_dsp_addr;
@@ -2241,7 +2189,7 @@ void dump_dl_modules(struct bridge_dev_context *bridge_context)
 	pr_debug("%s: _DLModules at 0x%x\n", __func__, module_dsp_addr);
 
 	/* Copy the modules_header structure from DSP memory. */
-	status = (*intf_fxns->pfn_brd_read)(bridge_context, (u8 *) &modules_hdr,
+	status = (*intf_fxns->brd_read)(bridge_context, (u8 *) &modules_hdr,
 				(u32) module_dsp_addr, sizeof(modules_hdr), 0);
 
 	if (status) {
@@ -2276,7 +2224,7 @@ void dump_dl_modules(struct bridge_dev_context *bridge_context)
 				goto func_end;
 		}
 		/* Copy the dll_module structure from DSP memory */
-		status = (*intf_fxns->pfn_brd_read)(bridge_context,
+		status = (*intf_fxns->brd_read)(bridge_context,
 			(u8 *)module_struct, module_dsp_addr, module_size, 0);
 
 		if (status) {
diff --git a/drivers/staging/tidspbridge/core/msg_sm.c b/drivers/staging/tidspbridge/core/msg_sm.c
index 87712e2..94d9e04 100644
--- a/drivers/staging/tidspbridge/core/msg_sm.c
+++ b/drivers/staging/tidspbridge/core/msg_sm.c
@@ -24,7 +24,6 @@
 #include <dspbridge/dbc.h>
 
 /*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
 #include <dspbridge/sync.h>
 
 /*  ----------------------------------- Platform Manager */
@@ -38,10 +37,10 @@
 #include <dspbridge/dspmsg.h>
 
 /*  ----------------------------------- Function Prototypes */
-static int add_new_msg(struct lst_list *msg_list);
+static int add_new_msg(struct list_head *msg_list);
 static void delete_msg_mgr(struct msg_mgr *hmsg_mgr);
 static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp);
-static void free_msg_list(struct lst_list *msg_list);
+static void free_msg_list(struct list_head *msg_list);
 
 /*
  *  ======== bridge_msg_create ========
@@ -56,61 +55,46 @@ int bridge_msg_create(struct msg_mgr **msg_man,
 	struct io_mgr *hio_mgr;
 	int status = 0;
 
-	if (!msg_man || !msg_callback || !hdev_obj) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!msg_man || !msg_callback || !hdev_obj)
+		return -EFAULT;
+
 	dev_get_io_mgr(hdev_obj, &hio_mgr);
-	if (!hio_mgr) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!hio_mgr)
+		return -EFAULT;
+
 	*msg_man = NULL;
 	/* Allocate msg_ctrl manager object */
 	msg_mgr_obj = kzalloc(sizeof(struct msg_mgr), GFP_KERNEL);
+	if (!msg_mgr_obj)
+		return -ENOMEM;
 
-	if (msg_mgr_obj) {
-		msg_mgr_obj->on_exit = msg_callback;
-		msg_mgr_obj->hio_mgr = hio_mgr;
-		/* List of MSG_QUEUEs */
-		msg_mgr_obj->queue_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		/*  Queues of message frames for messages to the DSP. Message
-		 * frames will only be added to the free queue when a
-		 * msg_queue object is created. */
-		msg_mgr_obj->msg_free_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		msg_mgr_obj->msg_used_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		if (msg_mgr_obj->queue_list == NULL ||
-		    msg_mgr_obj->msg_free_list == NULL ||
-		    msg_mgr_obj->msg_used_list == NULL) {
-			status = -ENOMEM;
-		} else {
-			INIT_LIST_HEAD(&msg_mgr_obj->queue_list->head);
-			INIT_LIST_HEAD(&msg_mgr_obj->msg_free_list->head);
-			INIT_LIST_HEAD(&msg_mgr_obj->msg_used_list->head);
-			spin_lock_init(&msg_mgr_obj->msg_mgr_lock);
-		}
+	msg_mgr_obj->on_exit = msg_callback;
+	msg_mgr_obj->iomgr = hio_mgr;
+	/* List of MSG_QUEUEs */
+	INIT_LIST_HEAD(&msg_mgr_obj->queue_list);
+	/*
+	 * Queues of message frames for messages to the DSP. Message
+	 * frames will only be added to the free queue when a
+	 * msg_queue object is created.
+	 */
+	INIT_LIST_HEAD(&msg_mgr_obj->msg_free_list);
+	INIT_LIST_HEAD(&msg_mgr_obj->msg_used_list);
+	spin_lock_init(&msg_mgr_obj->msg_mgr_lock);
 
-		/*  Create an event to be used by bridge_msg_put() in waiting
-		 *  for an available free frame from the message manager. */
-		msg_mgr_obj->sync_event =
-				kzalloc(sizeof(struct sync_object), GFP_KERNEL);
-		if (!msg_mgr_obj->sync_event)
-			status = -ENOMEM;
-		else
-			sync_init_event(msg_mgr_obj->sync_event);
-
-		if (!status)
-			*msg_man = msg_mgr_obj;
-		else
-			delete_msg_mgr(msg_mgr_obj);
-
-	} else {
-		status = -ENOMEM;
+	/*
+	 * Create an event to be used by bridge_msg_put() in waiting
+	 * for an available free frame from the message manager.
+	 */
+	msg_mgr_obj->sync_event =
+		kzalloc(sizeof(struct sync_object), GFP_KERNEL);
+	if (!msg_mgr_obj->sync_event) {
+		kfree(msg_mgr_obj);
+		return -ENOMEM;
 	}
-func_end:
+	sync_init_event(msg_mgr_obj->sync_event);
+
+	*msg_man = msg_mgr_obj;
+
 	return status;
 }
 
@@ -119,8 +103,7 @@ func_end:
  *      Create a msg_queue for sending/receiving messages to/from a node
  *      on the DSP.
  */
-int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr,
-				struct msg_queue **msgq,
+int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr, struct msg_queue **msgq,
 				u32 msgq_id, u32 max_msgs, void *arg)
 {
 	u32 i;
@@ -128,107 +111,87 @@ int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr,
 	struct msg_queue *msg_q;
 	int status = 0;
 
-	if (!hmsg_mgr || msgq == NULL || !hmsg_mgr->msg_free_list) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!hmsg_mgr || msgq == NULL)
+		return -EFAULT;
 
 	*msgq = NULL;
 	/* Allocate msg_queue object */
 	msg_q = kzalloc(sizeof(struct msg_queue), GFP_KERNEL);
-	if (!msg_q) {
-		status = -ENOMEM;
-		goto func_end;
-	}
-	lst_init_elem((struct list_head *)msg_q);
+	if (!msg_q)
+		return -ENOMEM;
+
 	msg_q->max_msgs = max_msgs;
-	msg_q->hmsg_mgr = hmsg_mgr;
+	msg_q->msg_mgr = hmsg_mgr;
 	msg_q->arg = arg;	/* Node handle */
 	msg_q->msgq_id = msgq_id;	/* Node env (not valid yet) */
 	/* Queues of Message frames for messages from the DSP */
-	msg_q->msg_free_list = kzalloc(sizeof(struct lst_list), GFP_KERNEL);
-	msg_q->msg_used_list = kzalloc(sizeof(struct lst_list), GFP_KERNEL);
-	if (msg_q->msg_free_list == NULL || msg_q->msg_used_list == NULL)
-		status = -ENOMEM;
-	else {
-		INIT_LIST_HEAD(&msg_q->msg_free_list->head);
-		INIT_LIST_HEAD(&msg_q->msg_used_list->head);
-	}
+	INIT_LIST_HEAD(&msg_q->msg_free_list);
+	INIT_LIST_HEAD(&msg_q->msg_used_list);
 
 	/*  Create event that will be signalled when a message from
 	 *  the DSP is available. */
-	if (!status) {
-		msg_q->sync_event = kzalloc(sizeof(struct sync_object),
-							GFP_KERNEL);
-		if (msg_q->sync_event)
-			sync_init_event(msg_q->sync_event);
-		else
-			status = -ENOMEM;
+	msg_q->sync_event = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
+	if (!msg_q->sync_event) {
+		status = -ENOMEM;
+		goto out_err;
+
 	}
+	sync_init_event(msg_q->sync_event);
 
 	/* Create a notification list for message ready notification. */
-	if (!status) {
-		msg_q->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
-							GFP_KERNEL);
-		if (msg_q->ntfy_obj)
-			ntfy_init(msg_q->ntfy_obj);
-		else
-			status = -ENOMEM;
+	msg_q->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
+	if (!msg_q->ntfy_obj) {
+		status = -ENOMEM;
+		goto out_err;
 	}
+	ntfy_init(msg_q->ntfy_obj);
 
 	/*  Create events that will be used to synchronize cleanup
 	 *  when the object is deleted. sync_done will be set to
 	 *  unblock threads in MSG_Put() or MSG_Get(). sync_done_ack
 	 *  will be set by the unblocked thread to signal that it
 	 *  is unblocked and will no longer reference the object. */
-	if (!status) {
-		msg_q->sync_done = kzalloc(sizeof(struct sync_object),
-							GFP_KERNEL);
-		if (msg_q->sync_done)
-			sync_init_event(msg_q->sync_done);
-		else
-			status = -ENOMEM;
+	msg_q->sync_done = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
+	if (!msg_q->sync_done) {
+		status = -ENOMEM;
+		goto out_err;
 	}
+	sync_init_event(msg_q->sync_done);
 
-	if (!status) {
-		msg_q->sync_done_ack = kzalloc(sizeof(struct sync_object),
-							GFP_KERNEL);
-		if (msg_q->sync_done_ack)
-			sync_init_event(msg_q->sync_done_ack);
-		else
-			status = -ENOMEM;
+	msg_q->sync_done_ack = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
+	if (!msg_q->sync_done_ack) {
+		status = -ENOMEM;
+		goto out_err;
 	}
+	sync_init_event(msg_q->sync_done_ack);
 
-	if (!status) {
-		/* Enter critical section */
-		spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
-		/* Initialize message frames and put in appropriate queues */
-		for (i = 0; i < max_msgs && !status; i++) {
-			status = add_new_msg(hmsg_mgr->msg_free_list);
-			if (!status) {
-				num_allocated++;
-				status = add_new_msg(msg_q->msg_free_list);
-			}
-		}
-		if (status) {
-			/*  Stay inside CS to prevent others from taking any
-			 *  of the newly allocated message frames. */
-			delete_msg_queue(msg_q, num_allocated);
-		} else {
-			lst_put_tail(hmsg_mgr->queue_list,
-				     (struct list_head *)msg_q);
-			*msgq = msg_q;
-			/* Signal that free frames are now available */
-			if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list))
-				sync_set_event(hmsg_mgr->sync_event);
-
+	/* Enter critical section */
+	spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
+	/* Initialize message frames and put in appropriate queues */
+	for (i = 0; i < max_msgs && !status; i++) {
+		status = add_new_msg(&hmsg_mgr->msg_free_list);
+		if (!status) {
+			num_allocated++;
+			status = add_new_msg(&msg_q->msg_free_list);
 		}
-		/* Exit critical section */
+	}
+	if (status) {
 		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-	} else {
-		delete_msg_queue(msg_q, 0);
+		goto out_err;
 	}
-func_end:
+
+	list_add_tail(&msg_q->list_elem, &hmsg_mgr->queue_list);
+	*msgq = msg_q;
+	/* Signal that free frames are now available */
+	if (!list_empty(&hmsg_mgr->msg_free_list))
+		sync_set_event(hmsg_mgr->sync_event);
+
+	/* Exit critical section */
+	spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+
+	return 0;
+out_err:
+	delete_msg_queue(msg_q, num_allocated);
 	return status;
 }
 
@@ -251,10 +214,10 @@ void bridge_msg_delete_queue(struct msg_queue *msg_queue_obj)
 	struct msg_mgr *hmsg_mgr;
 	u32 io_msg_pend;
 
-	if (!msg_queue_obj || !msg_queue_obj->hmsg_mgr)
-		goto func_end;
+	if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
+		return;
 
-	hmsg_mgr = msg_queue_obj->hmsg_mgr;
+	hmsg_mgr = msg_queue_obj->msg_mgr;
 	msg_queue_obj->done = true;
 	/*  Unblock all threads blocked in MSG_Get() or MSG_Put(). */
 	io_msg_pend = msg_queue_obj->io_msg_pend;
@@ -267,18 +230,12 @@ void bridge_msg_delete_queue(struct msg_queue *msg_queue_obj)
 	}
 	/* Remove message queue from hmsg_mgr->queue_list */
 	spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
-	lst_remove_elem(hmsg_mgr->queue_list,
-			(struct list_head *)msg_queue_obj);
+	list_del(&msg_queue_obj->list_elem);
 	/* Free the message queue object */
 	delete_msg_queue(msg_queue_obj, msg_queue_obj->max_msgs);
-	if (!hmsg_mgr->msg_free_list)
-		goto func_cont;
-	if (LST_IS_EMPTY(hmsg_mgr->msg_free_list))
+	if (list_empty(&hmsg_mgr->msg_free_list))
 		sync_reset_event(hmsg_mgr->sync_event);
-func_cont:
 	spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-func_end:
-	return;
 }
 
 /*
@@ -290,91 +247,74 @@ int bridge_msg_get(struct msg_queue *msg_queue_obj,
 {
 	struct msg_frame *msg_frame_obj;
 	struct msg_mgr *hmsg_mgr;
-	bool got_msg = false;
 	struct sync_object *syncs[2];
 	u32 index;
 	int status = 0;
 
-	if (!msg_queue_obj || pmsg == NULL) {
-		status = -ENOMEM;
-		goto func_end;
-	}
+	if (!msg_queue_obj || pmsg == NULL)
+		return -ENOMEM;
 
-	hmsg_mgr = msg_queue_obj->hmsg_mgr;
-	if (!msg_queue_obj->msg_used_list) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	hmsg_mgr = msg_queue_obj->msg_mgr;
 
-	/* Enter critical section */
 	spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
 	/* If a message is already there, get it */
-	if (!LST_IS_EMPTY(msg_queue_obj->msg_used_list)) {
-		msg_frame_obj = (struct msg_frame *)
-		    lst_get_head(msg_queue_obj->msg_used_list);
-		if (msg_frame_obj != NULL) {
-			*pmsg = msg_frame_obj->msg_data.msg;
-			lst_put_tail(msg_queue_obj->msg_free_list,
-				     (struct list_head *)msg_frame_obj);
-			if (LST_IS_EMPTY(msg_queue_obj->msg_used_list))
-				sync_reset_event(msg_queue_obj->sync_event);
-
-			got_msg = true;
-		}
-	} else {
-		if (msg_queue_obj->done)
-			status = -EPERM;
-		else
-			msg_queue_obj->io_msg_pend++;
+	if (!list_empty(&msg_queue_obj->msg_used_list)) {
+		msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
+				struct msg_frame, list_elem);
+		list_del(&msg_frame_obj->list_elem);
+		*pmsg = msg_frame_obj->msg_data.msg;
+		list_add_tail(&msg_frame_obj->list_elem,
+				&msg_queue_obj->msg_free_list);
+		if (list_empty(&msg_queue_obj->msg_used_list))
+			sync_reset_event(msg_queue_obj->sync_event);
+		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+		return 0;
+	}
 
+	if (msg_queue_obj->done) {
+		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+		return -EPERM;
 	}
-	/* Exit critical section */
+	msg_queue_obj->io_msg_pend++;
 	spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-	if (!status && !got_msg) {
-		/*  Wait til message is available, timeout, or done. We don't
-		 *  have to schedule the DPC, since the DSP will send messages
-		 *  when they are available. */
-		syncs[0] = msg_queue_obj->sync_event;
-		syncs[1] = msg_queue_obj->sync_done;
-		status = sync_wait_on_multiple_events(syncs, 2, utimeout,
-						      &index);
-		/* Enter critical section */
-		spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
-		if (msg_queue_obj->done) {
-			msg_queue_obj->io_msg_pend--;
-			/* Exit critical section */
-			spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-			/*  Signal that we're not going to access msg_queue_obj
-			 *  anymore, so it can be deleted. */
-			(void)sync_set_event(msg_queue_obj->sync_done_ack);
-			status = -EPERM;
-		} else {
-			if (!status) {
-				DBC_ASSERT(!LST_IS_EMPTY
-					   (msg_queue_obj->msg_used_list));
-				/* Get msg from used list */
-				msg_frame_obj = (struct msg_frame *)
-				    lst_get_head(msg_queue_obj->msg_used_list);
-				/* Copy message into pmsg and put frame on the
-				 * free list */
-				if (msg_frame_obj != NULL) {
-					*pmsg = msg_frame_obj->msg_data.msg;
-					lst_put_tail
-					    (msg_queue_obj->msg_free_list,
-					     (struct list_head *)
-					     msg_frame_obj);
-				}
-			}
-			msg_queue_obj->io_msg_pend--;
-			/* Reset the event if there are still queued messages */
-			if (!LST_IS_EMPTY(msg_queue_obj->msg_used_list))
-				sync_set_event(msg_queue_obj->sync_event);
-
-			/* Exit critical section */
-			spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-		}
-	}
-func_end:
+
+	/*
+	 * Wait til message is available, timeout, or done. We don't
+	 * have to schedule the DPC, since the DSP will send messages
+	 * when they are available.
+	 */
+	syncs[0] = msg_queue_obj->sync_event;
+	syncs[1] = msg_queue_obj->sync_done;
+	status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
+
+	spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
+	if (msg_queue_obj->done) {
+		msg_queue_obj->io_msg_pend--;
+		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+		/*
+		 * Signal that we're not going to access msg_queue_obj
+		 * anymore, so it can be deleted.
+		 */
+		sync_set_event(msg_queue_obj->sync_done_ack);
+		return -EPERM;
+	}
+	if (!status && !list_empty(&msg_queue_obj->msg_used_list)) {
+		/* Get msg from used list */
+		msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
+				struct msg_frame, list_elem);
+		list_del(&msg_frame_obj->list_elem);
+		/* Copy message into pmsg and put frame on the free list */
+		*pmsg = msg_frame_obj->msg_data.msg;
+		list_add_tail(&msg_frame_obj->list_elem,
+				&msg_queue_obj->msg_free_list);
+	}
+	msg_queue_obj->io_msg_pend--;
+	/* Reset the event if there are still queued messages */
+	if (!list_empty(&msg_queue_obj->msg_used_list))
+		sync_set_event(msg_queue_obj->sync_event);
+
+	spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+
 	return status;
 }
 
@@ -387,107 +327,100 @@ int bridge_msg_put(struct msg_queue *msg_queue_obj,
 {
 	struct msg_frame *msg_frame_obj;
 	struct msg_mgr *hmsg_mgr;
-	bool put_msg = false;
 	struct sync_object *syncs[2];
 	u32 index;
-	int status = 0;
+	int status;
 
-	if (!msg_queue_obj || !pmsg || !msg_queue_obj->hmsg_mgr) {
-		status = -ENOMEM;
-		goto func_end;
-	}
-	hmsg_mgr = msg_queue_obj->hmsg_mgr;
-	if (!hmsg_mgr->msg_free_list) {
-		status = -EFAULT;
-		goto func_end;
-	}
+	if (!msg_queue_obj || !pmsg || !msg_queue_obj->msg_mgr)
+		return -EFAULT;
+
+	hmsg_mgr = msg_queue_obj->msg_mgr;
 
 	spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
 
 	/* If a message frame is available, use it */
-	if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list)) {
-		msg_frame_obj =
-		    (struct msg_frame *)lst_get_head(hmsg_mgr->msg_free_list);
-		if (msg_frame_obj != NULL) {
-			msg_frame_obj->msg_data.msg = *pmsg;
-			msg_frame_obj->msg_data.msgq_id =
-			    msg_queue_obj->msgq_id;
-			lst_put_tail(hmsg_mgr->msg_used_list,
-				     (struct list_head *)msg_frame_obj);
-			hmsg_mgr->msgs_pending++;
-			put_msg = true;
-		}
-		if (LST_IS_EMPTY(hmsg_mgr->msg_free_list))
+	if (!list_empty(&hmsg_mgr->msg_free_list)) {
+		msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
+				struct msg_frame, list_elem);
+		list_del(&msg_frame_obj->list_elem);
+		msg_frame_obj->msg_data.msg = *pmsg;
+		msg_frame_obj->msg_data.msgq_id =
+			msg_queue_obj->msgq_id;
+		list_add_tail(&msg_frame_obj->list_elem,
+				&hmsg_mgr->msg_used_list);
+		hmsg_mgr->msgs_pending++;
+
+		if (list_empty(&hmsg_mgr->msg_free_list))
 			sync_reset_event(hmsg_mgr->sync_event);
 
 		/* Release critical section before scheduling DPC */
 		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
 		/* Schedule a DPC, to do the actual data transfer: */
-		iosm_schedule(hmsg_mgr->hio_mgr);
-	} else {
-		if (msg_queue_obj->done)
-			status = -EPERM;
-		else
-			msg_queue_obj->io_msg_pend++;
+		iosm_schedule(hmsg_mgr->iomgr);
+		return 0;
+	}
 
+	if (msg_queue_obj->done) {
 		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+		return -EPERM;
 	}
-	if (!status && !put_msg) {
-		/* Wait til a free message frame is available, timeout,
-		 * or done */
-		syncs[0] = hmsg_mgr->sync_event;
-		syncs[1] = msg_queue_obj->sync_done;
-		status = sync_wait_on_multiple_events(syncs, 2, utimeout,
-						      &index);
-		if (status)
-			goto func_end;
-		/* Enter critical section */
-		spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
-		if (msg_queue_obj->done) {
-			msg_queue_obj->io_msg_pend--;
-			/* Exit critical section */
-			spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-			/*  Signal that we're not going to access msg_queue_obj
-			 *  anymore, so it can be deleted. */
-			(void)sync_set_event(msg_queue_obj->sync_done_ack);
-			status = -EPERM;
-		} else {
-			if (LST_IS_EMPTY(hmsg_mgr->msg_free_list)) {
-				status = -EFAULT;
-				goto func_cont;
-			}
-			/* Get msg from free list */
-			msg_frame_obj = (struct msg_frame *)
-			    lst_get_head(hmsg_mgr->msg_free_list);
-			/*
-			 * Copy message into pmsg and put frame on the
-			 * used list.
-			 */
-			if (msg_frame_obj) {
-				msg_frame_obj->msg_data.msg = *pmsg;
-				msg_frame_obj->msg_data.msgq_id =
-				    msg_queue_obj->msgq_id;
-				lst_put_tail(hmsg_mgr->msg_used_list,
-					     (struct list_head *)msg_frame_obj);
-				hmsg_mgr->msgs_pending++;
-				/*
-				 * Schedule a DPC, to do the actual
-				 * data transfer.
-				 */
-				iosm_schedule(hmsg_mgr->hio_mgr);
-			}
-
-			msg_queue_obj->io_msg_pend--;
-			/* Reset event if there are still frames available */
-			if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list))
-				sync_set_event(hmsg_mgr->sync_event);
-func_cont:
-			/* Exit critical section */
-			spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
-		}
+	msg_queue_obj->io_msg_pend++;
+
+	spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+
+	/* Wait til a free message frame is available, timeout, or done */
+	syncs[0] = hmsg_mgr->sync_event;
+	syncs[1] = msg_queue_obj->sync_done;
+	status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
+	if (status)
+		return status;
+
+	/* Enter critical section */
+	spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
+	if (msg_queue_obj->done) {
+		msg_queue_obj->io_msg_pend--;
+		/* Exit critical section */
+		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+		/*
+		 * Signal that we're not going to access msg_queue_obj
+		 * anymore, so it can be deleted.
+		 */
+		sync_set_event(msg_queue_obj->sync_done_ack);
+		return -EPERM;
 	}
-func_end:
-	return status;
+
+	if (list_empty(&hmsg_mgr->msg_free_list)) {
+		spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+		return -EFAULT;
+	}
+
+	/* Get msg from free list */
+	msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
+			struct msg_frame, list_elem);
+	/*
+	 * Copy message into pmsg and put frame on the
+	 * used list.
+	 */
+	list_del(&msg_frame_obj->list_elem);
+	msg_frame_obj->msg_data.msg = *pmsg;
+	msg_frame_obj->msg_data.msgq_id = msg_queue_obj->msgq_id;
+	list_add_tail(&msg_frame_obj->list_elem, &hmsg_mgr->msg_used_list);
+	hmsg_mgr->msgs_pending++;
+	/*
+	 * Schedule a DPC, to do the actual
+	 * data transfer.
+	 */
+	iosm_schedule(hmsg_mgr->iomgr);
+
+	msg_queue_obj->io_msg_pend--;
+	/* Reset event if there are still frames available */
+	if (!list_empty(&hmsg_mgr->msg_free_list))
+		sync_set_event(hmsg_mgr->sync_event);
+
+	/* Exit critical section */
+	spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
+
+	return 0;
 }
 
 /*
@@ -551,20 +484,17 @@ void bridge_msg_set_queue_id(struct msg_queue *msg_queue_obj, u32 msgq_id)
  *  ======== add_new_msg ========
  *      Must be called in message manager critical section.
  */
-static int add_new_msg(struct lst_list *msg_list)
+static int add_new_msg(struct list_head *msg_list)
 {
 	struct msg_frame *pmsg;
-	int status = 0;
 
 	pmsg = kzalloc(sizeof(struct msg_frame), GFP_ATOMIC);
-	if (pmsg != NULL) {
-		lst_init_elem((struct list_head *)pmsg);
-		lst_put_tail(msg_list, (struct list_head *)pmsg);
-	} else {
-		status = -ENOMEM;
-	}
+	if (!pmsg)
+		return -ENOMEM;
 
-	return status;
+	list_add_tail(&pmsg->list_elem, msg_list);
+
+	return 0;
 }
 
 /*
@@ -573,30 +503,13 @@ static int add_new_msg(struct lst_list *msg_list)
 static void delete_msg_mgr(struct msg_mgr *hmsg_mgr)
 {
 	if (!hmsg_mgr)
-		goto func_end;
-
-	if (hmsg_mgr->queue_list) {
-		if (LST_IS_EMPTY(hmsg_mgr->queue_list)) {
-			kfree(hmsg_mgr->queue_list);
-			hmsg_mgr->queue_list = NULL;
-		}
-	}
-
-	if (hmsg_mgr->msg_free_list) {
-		free_msg_list(hmsg_mgr->msg_free_list);
-		hmsg_mgr->msg_free_list = NULL;
-	}
-
-	if (hmsg_mgr->msg_used_list) {
-		free_msg_list(hmsg_mgr->msg_used_list);
-		hmsg_mgr->msg_used_list = NULL;
-	}
+		return;
 
+	/* FIXME: free elements from queue_list? */
+	free_msg_list(&hmsg_mgr->msg_free_list);
+	free_msg_list(&hmsg_mgr->msg_used_list);
 	kfree(hmsg_mgr->sync_event);
-
 	kfree(hmsg_mgr);
-func_end:
-	return;
 }
 
 /*
@@ -605,37 +518,26 @@ func_end:
 static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp)
 {
 	struct msg_mgr *hmsg_mgr;
-	struct msg_frame *pmsg;
+	struct msg_frame *pmsg, *tmp;
 	u32 i;
 
-	if (!msg_queue_obj ||
-	    !msg_queue_obj->hmsg_mgr || !msg_queue_obj->hmsg_mgr->msg_free_list)
-		goto func_end;
+	if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
+		return;
 
-	hmsg_mgr = msg_queue_obj->hmsg_mgr;
+	hmsg_mgr = msg_queue_obj->msg_mgr;
 
 	/* Pull off num_to_dsp message frames from Msg manager and free */
-	for (i = 0; i < num_to_dsp; i++) {
-
-		if (!LST_IS_EMPTY(hmsg_mgr->msg_free_list)) {
-			pmsg = (struct msg_frame *)
-			    lst_get_head(hmsg_mgr->msg_free_list);
-			kfree(pmsg);
-		} else {
-			/* Cannot free all of the message frames */
+	i = 0;
+	list_for_each_entry_safe(pmsg, tmp, &hmsg_mgr->msg_free_list,
+			list_elem) {
+		list_del(&pmsg->list_elem);
+		kfree(pmsg);
+		if (i++ >= num_to_dsp)
 			break;
-		}
-	}
-
-	if (msg_queue_obj->msg_free_list) {
-		free_msg_list(msg_queue_obj->msg_free_list);
-		msg_queue_obj->msg_free_list = NULL;
 	}
 
-	if (msg_queue_obj->msg_used_list) {
-		free_msg_list(msg_queue_obj->msg_used_list);
-		msg_queue_obj->msg_used_list = NULL;
-	}
+	free_msg_list(&msg_queue_obj->msg_free_list);
+	free_msg_list(&msg_queue_obj->msg_used_list);
 
 	if (msg_queue_obj->ntfy_obj) {
 		ntfy_delete(msg_queue_obj->ntfy_obj);
@@ -647,27 +549,20 @@ static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp)
 	kfree(msg_queue_obj->sync_done_ack);
 
 	kfree(msg_queue_obj);
-func_end:
-	return;
-
 }
 
 /*
  *  ======== free_msg_list ========
  */
-static void free_msg_list(struct lst_list *msg_list)
+static void free_msg_list(struct list_head *msg_list)
 {
-	struct msg_frame *pmsg;
+	struct msg_frame *pmsg, *tmp;
 
 	if (!msg_list)
-		goto func_end;
+		return;
 
-	while ((pmsg = (struct msg_frame *)lst_get_head(msg_list)) != NULL)
+	list_for_each_entry_safe(pmsg, tmp, msg_list, list_elem) {
+		list_del(&pmsg->list_elem);
 		kfree(pmsg);
-
-	DBC_ASSERT(LST_IS_EMPTY(msg_list));
-
-	kfree(msg_list);
-func_end:
-	return;
+	}
 }
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index a3f69f6..e1c4492 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -229,11 +229,11 @@ static struct notifier_block dsp_mbox_notifier = {
 
 static inline void flush_all(struct bridge_dev_context *dev_context)
 {
-	if (dev_context->dw_brd_state == BRD_DSP_HIBERNATION ||
-	    dev_context->dw_brd_state == BRD_HIBERNATION)
+	if (dev_context->brd_state == BRD_DSP_HIBERNATION ||
+	    dev_context->brd_state == BRD_HIBERNATION)
 		wake_dsp(dev_context, NULL);
 
-	hw_mmu_tlb_flush_all(dev_context->dw_dsp_mmu_base);
+	hw_mmu_tlb_flush_all(dev_context->dsp_mmu_base);
 }
 
 static void bad_page_dump(u32 pa, struct page *pg)
@@ -259,8 +259,6 @@ void bridge_drv_entry(struct bridge_drv_interface **drv_intf,
 
 	DBC_REQUIRE(driver_file_name != NULL);
 
-	io_sm_init();		/* Initialization of io_sm module */
-
 	if (strcmp(driver_file_name, "UMA") == 0)
 		*drv_intf = &drv_interface_fxns;
 	else
@@ -308,7 +306,7 @@ static int bridge_brd_monitor(struct bridge_dev_context *dev_ctxt)
 	dsp_clk_enable(DSP_CLK_IVA2);
 
 	/* set the device state to IDLE */
-	dev_context->dw_brd_state = BRD_IDLE;
+	dev_context->brd_state = BRD_IDLE;
 
 	return 0;
 }
@@ -325,16 +323,16 @@ static int bridge_brd_read(struct bridge_dev_context *dev_ctxt,
 	int status = 0;
 	struct bridge_dev_context *dev_context = dev_ctxt;
 	u32 offset;
-	u32 dsp_base_addr = dev_ctxt->dw_dsp_base_addr;
+	u32 dsp_base_addr = dev_ctxt->dsp_base_addr;
 
-	if (dsp_addr < dev_context->dw_dsp_start_add) {
+	if (dsp_addr < dev_context->dsp_start_add) {
 		status = -EPERM;
 		return status;
 	}
 	/* change here to account for the 3 bands of the DSP internal memory */
-	if ((dsp_addr - dev_context->dw_dsp_start_add) <
-	    dev_context->dw_internal_size) {
-		offset = dsp_addr - dev_context->dw_dsp_start_add;
+	if ((dsp_addr - dev_context->dsp_start_add) <
+	    dev_context->internal_size) {
+		offset = dsp_addr - dev_context->dsp_start_add;
 	} else {
 		status = read_ext_dsp_data(dev_context, host_buff, dsp_addr,
 					   ul_num_bytes, mem_type);
@@ -356,7 +354,7 @@ static int bridge_brd_set_state(struct bridge_dev_context *dev_ctxt,
 	int status = 0;
 	struct bridge_dev_context *dev_context = dev_ctxt;
 
-	dev_context->dw_brd_state = brd_state;
+	dev_context->brd_state = brd_state;
 	return status;
 }
 
@@ -398,17 +396,17 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 	 * last dsp base image was loaded. The first entry is always
 	 * SHMMEM base. */
 	/* Get SHM_BEG - convert to byte address */
-	(void)dev_get_symbol(dev_context->hdev_obj, SHMBASENAME,
+	(void)dev_get_symbol(dev_context->dev_obj, SHMBASENAME,
 			     &ul_shm_base_virt);
 	ul_shm_base_virt *= DSPWORDSIZE;
 	DBC_ASSERT(ul_shm_base_virt != 0);
 	/* DSP Virtual address */
-	ul_tlb_base_virt = dev_context->atlb_entry[0].ul_dsp_va;
+	ul_tlb_base_virt = dev_context->atlb_entry[0].dsp_va;
 	DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt);
 	ul_shm_offset_virt =
 	    ul_shm_base_virt - (ul_tlb_base_virt * DSPWORDSIZE);
 	/* Kernel logical address */
-	ul_shm_base = dev_context->atlb_entry[0].ul_gpp_va + ul_shm_offset_virt;
+	ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt;
 
 	DBC_ASSERT(ul_shm_base != 0);
 	/* 2nd wd is used as sync field */
@@ -454,9 +452,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 		udelay(100);
 
 		/* Disbale the DSP MMU */
-		hw_mmu_disable(resources->dw_dmmu_base);
+		hw_mmu_disable(resources->dmmu_base);
 		/* Disable TWL */
-		hw_mmu_twl_disable(resources->dw_dmmu_base);
+		hw_mmu_twl_disable(resources->dmmu_base);
 
 		/* Only make TLB entry if both addresses are non-zero */
 		for (entry_ndx = 0; entry_ndx < BRDIOCTL_NUMOFMMUTLB;
@@ -468,20 +466,20 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 				.mixed_size = e->mixed_mode,
 			};
 
-			if (!e->ul_gpp_pa || !e->ul_dsp_va)
+			if (!e->gpp_pa || !e->dsp_va)
 				continue;
 
 			dev_dbg(bridge,
 					"MMU %d, pa: 0x%x, va: 0x%x, size: 0x%x",
 					itmp_entry_ndx,
-					e->ul_gpp_pa,
-					e->ul_dsp_va,
-					e->ul_size);
-
-			hw_mmu_tlb_add(dev_context->dw_dsp_mmu_base,
-					e->ul_gpp_pa,
-					e->ul_dsp_va,
-					e->ul_size,
+					e->gpp_pa,
+					e->dsp_va,
+					e->size);
+
+			hw_mmu_tlb_add(dev_context->dsp_mmu_base,
+					e->gpp_pa,
+					e->dsp_va,
+					e->size,
 					itmp_entry_ndx,
 					&map_attrs, 1, 1);
 
@@ -492,24 +490,24 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 	/* Lock the above TLB entries and get the BIOS and load monitor timer
 	 * information */
 	if (!status) {
-		hw_mmu_num_locked_set(resources->dw_dmmu_base, itmp_entry_ndx);
-		hw_mmu_victim_num_set(resources->dw_dmmu_base, itmp_entry_ndx);
-		hw_mmu_ttb_set(resources->dw_dmmu_base,
+		hw_mmu_num_locked_set(resources->dmmu_base, itmp_entry_ndx);
+		hw_mmu_victim_num_set(resources->dmmu_base, itmp_entry_ndx);
+		hw_mmu_ttb_set(resources->dmmu_base,
 			       dev_context->pt_attrs->l1_base_pa);
-		hw_mmu_twl_enable(resources->dw_dmmu_base);
+		hw_mmu_twl_enable(resources->dmmu_base);
 		/* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
 
-		temp = __raw_readl((resources->dw_dmmu_base) + 0x10);
+		temp = __raw_readl((resources->dmmu_base) + 0x10);
 		temp = (temp & 0xFFFFFFEF) | 0x11;
-		__raw_writel(temp, (resources->dw_dmmu_base) + 0x10);
+		__raw_writel(temp, (resources->dmmu_base) + 0x10);
 
 		/* Let the DSP MMU run */
-		hw_mmu_enable(resources->dw_dmmu_base);
+		hw_mmu_enable(resources->dmmu_base);
 
 		/* Enable the BIOS clock */
-		(void)dev_get_symbol(dev_context->hdev_obj,
+		(void)dev_get_symbol(dev_context->dev_obj,
 				     BRIDGEINIT_BIOSGPTIMER, &ul_bios_gp_timer);
-		(void)dev_get_symbol(dev_context->hdev_obj,
+		(void)dev_get_symbol(dev_context->dev_obj,
 				     BRIDGEINIT_LOADMON_GPTIMER,
 				     &ul_load_monitor_timer);
 	}
@@ -538,7 +536,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 
 	if (!status) {
 		/* Set the DSP clock rate */
-		(void)dev_get_symbol(dev_context->hdev_obj,
+		(void)dev_get_symbol(dev_context->dev_obj,
 				     "_BRIDGEINIT_DSP_FREQ", &ul_dsp_clk_addr);
 		/*Set Autoidle Mode for IVA2 PLL */
 		(*pdata->dsp_cm_write)(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
@@ -568,18 +566,18 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 	}
 	if (!status) {
 /*PM_IVA2GRPSEL_PER = 0xC0;*/
-		temp = readl(resources->dw_per_pm_base + 0xA8);
+		temp = readl(resources->per_pm_base + 0xA8);
 		temp = (temp & 0xFFFFFF30) | 0xC0;
-		writel(temp, resources->dw_per_pm_base + 0xA8);
+		writel(temp, resources->per_pm_base + 0xA8);
 
 /*PM_MPUGRPSEL_PER &= 0xFFFFFF3F; */
-		temp = readl(resources->dw_per_pm_base + 0xA4);
+		temp = readl(resources->per_pm_base + 0xA4);
 		temp = (temp & 0xFFFFFF3F);
-		writel(temp, resources->dw_per_pm_base + 0xA4);
+		writel(temp, resources->per_pm_base + 0xA4);
 /*CM_SLEEPDEP_PER |= 0x04; */
-		temp = readl(resources->dw_per_base + 0x44);
+		temp = readl(resources->per_base + 0x44);
 		temp = (temp & 0xFFFFFFFB) | 0x04;
-		writel(temp, resources->dw_per_base + 0x44);
+		writel(temp, resources->per_base + 0x44);
 
 /*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions */
 		(*pdata->dsp_cm_write)(OMAP34XX_CLKSTCTRL_ENABLE_AUTO,
@@ -588,7 +586,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 		/* Let DSP go */
 		dev_dbg(bridge, "%s Unreset\n", __func__);
 		/* Enable DSP MMU Interrupts */
-		hw_mmu_event_enable(resources->dw_dmmu_base,
+		hw_mmu_event_enable(resources->dmmu_base,
 				    HW_MMU_ALL_INTERRUPTS);
 		/* release the RST1, DSP starts executing now .. */
 		(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,
@@ -609,7 +607,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 		dsp_wdt_sm_set((void *)ul_shm_base);
 		dsp_wdt_enable(true);
 
-		status = dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr);
+		status = dev_get_io_mgr(dev_context->dev_obj, &hio_mgr);
 		if (hio_mgr) {
 			io_sh_msetting(hio_mgr, SHM_OPPINFO, NULL);
 			/* Write the synchronization bit to indicate the
@@ -618,10 +616,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 			__raw_writel(0XCAFECAFE, dw_sync_addr);
 
 			/* update board state */
-			dev_context->dw_brd_state = BRD_RUNNING;
+			dev_context->brd_state = BRD_RUNNING;
 			/* (void)chnlsm_enable_interrupt(dev_context); */
 		} else {
-			dev_context->dw_brd_state = BRD_UNKNOWN;
+			dev_context->brd_state = BRD_UNKNOWN;
 		}
 	}
 	return status;
@@ -644,7 +642,7 @@ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt)
 	struct omap_dsp_platform_data *pdata =
 		omap_dspbridge_dev->dev.platform_data;
 
-	if (dev_context->dw_brd_state == BRD_STOPPED)
+	if (dev_context->brd_state == BRD_STOPPED)
 		return status;
 
 	/* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
@@ -669,10 +667,10 @@ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt)
 	udelay(10);
 	/* Release the Ext Base virtual Address as the next DSP Program
 	 * may have a different load address */
-	if (dev_context->dw_dsp_ext_base_addr)
-		dev_context->dw_dsp_ext_base_addr = 0;
+	if (dev_context->dsp_ext_base_addr)
+		dev_context->dsp_ext_base_addr = 0;
 
-	dev_context->dw_brd_state = BRD_STOPPED;	/* update board state */
+	dev_context->brd_state = BRD_STOPPED;	/* update board state */
 
 	dsp_wdt_enable(false);
 
@@ -708,7 +706,7 @@ static int bridge_brd_status(struct bridge_dev_context *dev_ctxt,
 				    int *board_state)
 {
 	struct bridge_dev_context *dev_context = dev_ctxt;
-	*board_state = dev_context->dw_brd_state;
+	*board_state = dev_context->brd_state;
 	return 0;
 }
 
@@ -723,12 +721,12 @@ static int bridge_brd_write(struct bridge_dev_context *dev_ctxt,
 	int status = 0;
 	struct bridge_dev_context *dev_context = dev_ctxt;
 
-	if (dsp_addr < dev_context->dw_dsp_start_add) {
+	if (dsp_addr < dev_context->dsp_start_add) {
 		status = -EPERM;
 		return status;
 	}
-	if ((dsp_addr - dev_context->dw_dsp_start_add) <
-	    dev_context->dw_internal_size) {
+	if ((dsp_addr - dev_context->dsp_start_add) <
+	    dev_context->internal_size) {
 		status = write_dsp_data(dev_ctxt, host_buff, dsp_addr,
 					ul_num_bytes, mem_type);
 	} else {
@@ -766,24 +764,24 @@ static int bridge_dev_create(struct bridge_dev_context
 		goto func_end;
 	}
 
-	dev_context->dw_dsp_start_add = (u32) OMAP_GEM_BASE;
-	dev_context->dw_self_loop = (u32) NULL;
+	dev_context->dsp_start_add = (u32) OMAP_GEM_BASE;
+	dev_context->self_loop = (u32) NULL;
 	dev_context->dsp_per_clks = 0;
-	dev_context->dw_internal_size = OMAP_DSP_SIZE;
+	dev_context->internal_size = OMAP_DSP_SIZE;
 	/*  Clear dev context MMU table entries.
 	 *  These get set on bridge_io_on_loaded() call after program loaded. */
 	for (entry_ndx = 0; entry_ndx < BRDIOCTL_NUMOFMMUTLB; entry_ndx++) {
-		dev_context->atlb_entry[entry_ndx].ul_gpp_pa =
-		    dev_context->atlb_entry[entry_ndx].ul_dsp_va = 0;
+		dev_context->atlb_entry[entry_ndx].gpp_pa =
+		    dev_context->atlb_entry[entry_ndx].dsp_va = 0;
 	}
-	dev_context->dw_dsp_base_addr = (u32) MEM_LINEAR_ADDRESS((void *)
+	dev_context->dsp_base_addr = (u32) MEM_LINEAR_ADDRESS((void *)
 								 (config_param->
-								  dw_mem_base
+								  mem_base
 								  [3]),
 								 config_param->
-								 dw_mem_length
+								 mem_length
 								 [3]);
-	if (!dev_context->dw_dsp_base_addr)
+	if (!dev_context->dsp_base_addr)
 		status = -EPERM;
 
 	pt_attrs = kzalloc(sizeof(struct pg_table_attrs), GFP_KERNEL);
@@ -871,12 +869,12 @@ static int bridge_dev_create(struct bridge_dev_context
 		udelay(5);
 		/* MMU address is obtained from the host
 		 * resources struct */
-		dev_context->dw_dsp_mmu_base = resources->dw_dmmu_base;
+		dev_context->dsp_mmu_base = resources->dmmu_base;
 	}
 	if (!status) {
-		dev_context->hdev_obj = hdev_obj;
+		dev_context->dev_obj = hdev_obj;
 		/* Store current board state. */
-		dev_context->dw_brd_state = BRD_UNKNOWN;
+		dev_context->brd_state = BRD_UNKNOWN;
 		dev_context->resources = resources;
 		dsp_clk_enable(DSP_CLK_IVA2);
 		bridge_brd_stop(dev_context);
@@ -1003,12 +1001,12 @@ static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt)
 		host_res = dev_context->resources;
 		shm_size = drv_datap->shm_size;
 		if (shm_size >= 0x10000) {
-			if ((host_res->dw_mem_base[1]) &&
-			    (host_res->dw_mem_phys[1])) {
+			if ((host_res->mem_base[1]) &&
+			    (host_res->mem_phys[1])) {
 				mem_free_phys_mem((void *)
-						  host_res->dw_mem_base
+						  host_res->mem_base
 						  [1],
-						  host_res->dw_mem_phys
+						  host_res->mem_phys
 						  [1], shm_size);
 			}
 		} else {
@@ -1017,34 +1015,31 @@ static int bridge_dev_destroy(struct bridge_dev_context *dev_ctxt)
 				"mem_free_phys_mem\n", __func__,
 				status);
 		}
-		host_res->dw_mem_base[1] = 0;
-		host_res->dw_mem_phys[1] = 0;
-
-		if (host_res->dw_mem_base[0])
-			iounmap((void *)host_res->dw_mem_base[0]);
-		if (host_res->dw_mem_base[2])
-			iounmap((void *)host_res->dw_mem_base[2]);
-		if (host_res->dw_mem_base[3])
-			iounmap((void *)host_res->dw_mem_base[3]);
-		if (host_res->dw_mem_base[4])
-			iounmap((void *)host_res->dw_mem_base[4]);
-		if (host_res->dw_dmmu_base)
-			iounmap(host_res->dw_dmmu_base);
-		if (host_res->dw_per_base)
-			iounmap(host_res->dw_per_base);
-		if (host_res->dw_per_pm_base)
-			iounmap((void *)host_res->dw_per_pm_base);
-		if (host_res->dw_core_pm_base)
-			iounmap((void *)host_res->dw_core_pm_base);
-		if (host_res->dw_sys_ctrl_base)
-			iounmap(host_res->dw_sys_ctrl_base);
-
-		host_res->dw_mem_base[0] = (u32) NULL;
-		host_res->dw_mem_base[2] = (u32) NULL;
-		host_res->dw_mem_base[3] = (u32) NULL;
-		host_res->dw_mem_base[4] = (u32) NULL;
-		host_res->dw_dmmu_base = NULL;
-		host_res->dw_sys_ctrl_base = NULL;
+		host_res->mem_base[1] = 0;
+		host_res->mem_phys[1] = 0;
+
+		if (host_res->mem_base[0])
+			iounmap((void *)host_res->mem_base[0]);
+		if (host_res->mem_base[2])
+			iounmap((void *)host_res->mem_base[2]);
+		if (host_res->mem_base[3])
+			iounmap((void *)host_res->mem_base[3]);
+		if (host_res->mem_base[4])
+			iounmap((void *)host_res->mem_base[4]);
+		if (host_res->dmmu_base)
+			iounmap(host_res->dmmu_base);
+		if (host_res->per_base)
+			iounmap(host_res->per_base);
+		if (host_res->per_pm_base)
+			iounmap((void *)host_res->per_pm_base);
+		if (host_res->core_pm_base)
+			iounmap((void *)host_res->core_pm_base);
+
+		host_res->mem_base[0] = (u32) NULL;
+		host_res->mem_base[2] = (u32) NULL;
+		host_res->mem_base[3] = (u32) NULL;
+		host_res->mem_base[4] = (u32) NULL;
+		host_res->dmmu_base = NULL;
 
 		kfree(host_res);
 	}
@@ -1075,8 +1070,8 @@ static int bridge_brd_mem_copy(struct bridge_dev_context *dev_ctxt,
 		status = read_ext_dsp_data(dev_ctxt, host_buf, src_addr,
 					   copy_bytes, mem_type);
 		if (!status) {
-			if (dest_addr < (dev_context->dw_dsp_start_add +
-					 dev_context->dw_internal_size)) {
+			if (dest_addr < (dev_context->dsp_start_add +
+					 dev_context->internal_size)) {
 				/* Write to Internal memory */
 				status = write_dsp_data(dev_ctxt, host_buf,
 							dest_addr, copy_bytes,
@@ -1109,8 +1104,8 @@ static int bridge_brd_mem_write(struct bridge_dev_context *dev_ctxt,
 	while (ul_remain_bytes > 0 && !status) {
 		ul_bytes =
 		    ul_remain_bytes > BUFFERSIZE ? BUFFERSIZE : ul_remain_bytes;
-		if (dsp_addr < (dev_context->dw_dsp_start_add +
-				 dev_context->dw_internal_size)) {
+		if (dsp_addr < (dev_context->dsp_start_add +
+				 dev_context->internal_size)) {
 			status =
 			    write_dsp_data(dev_ctxt, host_buff, dsp_addr,
 					   ul_bytes, mem_type);
diff --git a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
index fb9026e..02dd439 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430_pwr.c
@@ -29,13 +29,13 @@
 /*  ----------------------------------- Platform Manager */
 #include <dspbridge/brddefs.h>
 #include <dspbridge/dev.h>
-#include <dspbridge/iodefs.h>
+#include <dspbridge/io.h>
 
 /* ------------------------------------ Hardware Abstraction Layer */
 #include <hw_defs.h>
 #include <hw_mmu.h>
 
-#include <dspbridge/pwr_sh.h>
+#include <dspbridge/pwr.h>
 
 /*  ----------------------------------- Bridge Driver */
 #include <dspbridge/dspdeh.h>
@@ -118,10 +118,10 @@ int handle_hibernation_from_dsp(struct bridge_dev_context *dev_context)
 
 		if (!status) {
 			/* Update the Bridger Driver state */
-			dev_context->dw_brd_state = BRD_DSP_HIBERNATION;
+			dev_context->brd_state = BRD_DSP_HIBERNATION;
 #ifdef CONFIG_TIDSPBRIDGE_DVFS
 			status =
-			    dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr);
+			    dev_get_io_mgr(dev_context->dev_obj, &hio_mgr);
 			if (!hio_mgr) {
 				status = DSP_EHANDLE;
 				return status;
@@ -163,7 +163,7 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
 	if ((dw_cmd != PWR_DEEPSLEEP) && (dw_cmd != PWR_EMERGENCYDEEPSLEEP))
 		return -EINVAL;
 
-	switch (dev_context->dw_brd_state) {
+	switch (dev_context->brd_state) {
 	case BRD_RUNNING:
 		omap_mbox_save_ctx(dev_context->mbox);
 		if (dsp_test_sleepstate == PWRDM_POWER_OFF) {
@@ -216,16 +216,16 @@ int sleep_dsp(struct bridge_dev_context *dev_context, u32 dw_cmd,
 		pr_err("%s: Timed out waiting for DSP off mode, state %x\n",
 		       __func__, pwr_state);
 #ifdef CONFIG_TIDSPBRIDGE_NTFY_PWRERR
-		dev_get_deh_mgr(dev_context->hdev_obj, &hdeh_mgr);
+		dev_get_deh_mgr(dev_context->dev_obj, &hdeh_mgr);
 		bridge_deh_notify(hdeh_mgr, DSP_PWRERROR, 0);
 #endif /* CONFIG_TIDSPBRIDGE_NTFY_PWRERR */
 		return -ETIMEDOUT;
 	} else {
 		/* Update the Bridger Driver state */
 		if (dsp_test_sleepstate == PWRDM_POWER_OFF)
-			dev_context->dw_brd_state = BRD_HIBERNATION;
+			dev_context->brd_state = BRD_HIBERNATION;
 		else
-			dev_context->dw_brd_state = BRD_RETENTION;
+			dev_context->brd_state = BRD_RETENTION;
 
 		/* Disable wdt on hibernation. */
 		dsp_wdt_enable(false);
@@ -258,8 +258,8 @@ int wake_dsp(struct bridge_dev_context *dev_context, void *pargs)
 #ifdef CONFIG_PM
 
 	/* Check the board state, if it is not 'SLEEP' then return */
-	if (dev_context->dw_brd_state == BRD_RUNNING ||
-	    dev_context->dw_brd_state == BRD_STOPPED) {
+	if (dev_context->brd_state == BRD_RUNNING ||
+	    dev_context->brd_state == BRD_STOPPED) {
 		/* The Device is in 'RET' or 'OFF' state and Bridge state is not
 		 * 'SLEEP', this means state inconsistency, so return */
 		return 0;
@@ -269,7 +269,7 @@ int wake_dsp(struct bridge_dev_context *dev_context, void *pargs)
 	sm_interrupt_dsp(dev_context, MBX_PM_DSPWAKEUP);
 
 	/* Set the device state to RUNNIG */
-	dev_context->dw_brd_state = BRD_RUNNING;
+	dev_context->brd_state = BRD_RUNNING;
 #endif /* CONFIG_PM */
 	return status;
 }
@@ -351,12 +351,12 @@ int pre_scale_dsp(struct bridge_dev_context *dev_context, void *pargs)
 
 	dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
 		__func__, voltage_domain, level);
-	if ((dev_context->dw_brd_state == BRD_HIBERNATION) ||
-	    (dev_context->dw_brd_state == BRD_RETENTION) ||
-	    (dev_context->dw_brd_state == BRD_DSP_HIBERNATION)) {
+	if ((dev_context->brd_state == BRD_HIBERNATION) ||
+	    (dev_context->brd_state == BRD_RETENTION) ||
+	    (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
 		dev_dbg(bridge, "OPP: %s IVA in sleep. No message to DSP\n");
 		return 0;
-	} else if ((dev_context->dw_brd_state == BRD_RUNNING)) {
+	} else if ((dev_context->brd_state == BRD_RUNNING)) {
 		/* Send a prenotificatio to DSP */
 		dev_dbg(bridge, "OPP: %s sent notification to DSP\n", __func__);
 		sm_interrupt_dsp(dev_context, MBX_PM_SETPOINT_PRENOTIFY);
@@ -382,7 +382,7 @@ int post_scale_dsp(struct bridge_dev_context *dev_context,
 	u32 voltage_domain;
 	struct io_mgr *hio_mgr;
 
-	status = dev_get_io_mgr(dev_context->hdev_obj, &hio_mgr);
+	status = dev_get_io_mgr(dev_context->dev_obj, &hio_mgr);
 	if (!hio_mgr)
 		return -EFAULT;
 
@@ -390,14 +390,14 @@ int post_scale_dsp(struct bridge_dev_context *dev_context,
 	level = *((u32 *) pargs + 1);
 	dev_dbg(bridge, "OPP: %s voltage_domain = %x, level = 0x%x\n",
 		__func__, voltage_domain, level);
-	if ((dev_context->dw_brd_state == BRD_HIBERNATION) ||
-	    (dev_context->dw_brd_state == BRD_RETENTION) ||
-	    (dev_context->dw_brd_state == BRD_DSP_HIBERNATION)) {
+	if ((dev_context->brd_state == BRD_HIBERNATION) ||
+	    (dev_context->brd_state == BRD_RETENTION) ||
+	    (dev_context->brd_state == BRD_DSP_HIBERNATION)) {
 		/* Update the OPP value in shared memory */
 		io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
 		dev_dbg(bridge, "OPP: %s IVA in sleep. Wrote to shm\n",
 			__func__);
-	} else if ((dev_context->dw_brd_state == BRD_RUNNING)) {
+	} else if ((dev_context->brd_state == BRD_RUNNING)) {
 		/* Update the OPP value in shared memory */
 		io_sh_msetting(hio_mgr, SHM_CURROPP, &level);
 		/* Send a post notification to DSP */
@@ -434,8 +434,8 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 
 	switch (clock_id) {
 	case BPWR_GP_TIMER5:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
@@ -443,12 +443,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_GPT5_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_GP_TIMER6:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
@@ -456,12 +456,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_GPT6_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_GP_TIMER7:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
@@ -469,12 +469,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_GPT7_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_GP_TIMER8:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
@@ -482,12 +482,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_GPT8_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_MCBSP1:
-		iva2_grpsel = readl(resources->dw_core_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_core_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->core_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->core_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
@@ -495,12 +495,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_core_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_core_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->core_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->core_pm_base + 0xA4);
 		break;
 	case BPWR_MCBSP2:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
@@ -508,12 +508,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_MCBSP3:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
@@ -521,12 +521,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_MCBSP4:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
@@ -534,12 +534,12 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	case BPWR_MCBSP5:
-		iva2_grpsel = readl(resources->dw_per_pm_base + 0xA8);
-		mpu_grpsel = readl(resources->dw_per_pm_base + 0xA4);
+		iva2_grpsel = readl(resources->per_pm_base + 0xA8);
+		mpu_grpsel = readl(resources->per_pm_base + 0xA4);
 		if (enable) {
 			iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
 			mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
@@ -547,8 +547,8 @@ void dsp_clk_wakeup_event_ctrl(u32 clock_id, bool enable)
 			mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5_MASK;
 			iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5_MASK;
 		}
-		writel(iva2_grpsel, resources->dw_per_pm_base + 0xA8);
-		writel(mpu_grpsel, resources->dw_per_pm_base + 0xA4);
+		writel(iva2_grpsel, resources->per_pm_base + 0xA8);
+		writel(mpu_grpsel, resources->per_pm_base + 0xA4);
 		break;
 	}
 }
diff --git a/drivers/staging/tidspbridge/core/tiomap_io.c b/drivers/staging/tidspbridge/core/tiomap_io.c
index ba29610..dfb356e 100644
--- a/drivers/staging/tidspbridge/core/tiomap_io.c
+++ b/drivers/staging/tidspbridge/core/tiomap_io.c
@@ -61,24 +61,24 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
 	u32 ul_tlb_base_virt = 0;
 	u32 ul_shm_offset_virt = 0;
 	u32 dw_ext_prog_virt_mem;
-	u32 dw_base_addr = dev_context->dw_dsp_ext_base_addr;
+	u32 dw_base_addr = dev_context->dsp_ext_base_addr;
 	bool trace_read = false;
 
 	if (!ul_shm_base_virt) {
-		status = dev_get_symbol(dev_context->hdev_obj,
+		status = dev_get_symbol(dev_context->dev_obj,
 					SHMBASENAME, &ul_shm_base_virt);
 	}
 	DBC_ASSERT(ul_shm_base_virt != 0);
 
 	/* Check if it is a read of Trace section */
 	if (!status && !ul_trace_sec_beg) {
-		status = dev_get_symbol(dev_context->hdev_obj,
+		status = dev_get_symbol(dev_context->dev_obj,
 					DSP_TRACESEC_BEG, &ul_trace_sec_beg);
 	}
 	DBC_ASSERT(ul_trace_sec_beg != 0);
 
 	if (!status && !ul_trace_sec_end) {
-		status = dev_get_symbol(dev_context->hdev_obj,
+		status = dev_get_symbol(dev_context->dev_obj,
 					DSP_TRACESEC_END, &ul_trace_sec_end);
 	}
 	DBC_ASSERT(ul_trace_sec_end != 0);
@@ -92,7 +92,7 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
 	/* If reading from TRACE, force remap/unmap */
 	if (trace_read && dw_base_addr) {
 		dw_base_addr = 0;
-		dev_context->dw_dsp_ext_base_addr = 0;
+		dev_context->dsp_ext_base_addr = 0;
 	}
 
 	if (!dw_base_addr) {
@@ -102,19 +102,19 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
 
 		/* Get DYNEXT_BEG, EXT_BEG and EXT_END. */
 		if (!status && !ul_dyn_ext_base) {
-			status = dev_get_symbol(dev_context->hdev_obj,
+			status = dev_get_symbol(dev_context->dev_obj,
 						DYNEXTBASE, &ul_dyn_ext_base);
 		}
 		DBC_ASSERT(ul_dyn_ext_base != 0);
 
 		if (!status) {
-			status = dev_get_symbol(dev_context->hdev_obj,
+			status = dev_get_symbol(dev_context->dev_obj,
 						EXTBASE, &ul_ext_base);
 		}
 		DBC_ASSERT(ul_ext_base != 0);
 
 		if (!status) {
-			status = dev_get_symbol(dev_context->hdev_obj,
+			status = dev_get_symbol(dev_context->dev_obj,
 						EXTEND, &ul_ext_end);
 		}
 		DBC_ASSERT(ul_ext_end != 0);
@@ -134,10 +134,10 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
 
 		if (!status) {
 			ul_tlb_base_virt =
-			    dev_context->atlb_entry[0].ul_dsp_va * DSPWORDSIZE;
+			    dev_context->atlb_entry[0].dsp_va * DSPWORDSIZE;
 			DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt);
 			dw_ext_prog_virt_mem =
-			    dev_context->atlb_entry[0].ul_gpp_va;
+			    dev_context->atlb_entry[0].gpp_va;
 
 			if (!trace_read) {
 				ul_shm_offset_virt =
@@ -148,14 +148,14 @@ int read_ext_dsp_data(struct bridge_dev_context *dev_ctxt,
 				dw_ext_prog_virt_mem -= ul_shm_offset_virt;
 				dw_ext_prog_virt_mem +=
 				    (ul_ext_base - ul_dyn_ext_base);
-				dev_context->dw_dsp_ext_base_addr =
+				dev_context->dsp_ext_base_addr =
 				    dw_ext_prog_virt_mem;
 
 				/*
-				 * This dw_dsp_ext_base_addr will get cleared
+				 * This dsp_ext_base_addr will get cleared
 				 * only when the board is stopped.
 				*/
-				if (!dev_context->dw_dsp_ext_base_addr)
+				if (!dev_context->dsp_ext_base_addr)
 					status = -EPERM;
 			}
 
@@ -184,7 +184,7 @@ int write_dsp_data(struct bridge_dev_context *dev_context,
 			  u32 mem_type)
 {
 	u32 offset;
-	u32 dw_base_addr = dev_context->dw_dsp_base_addr;
+	u32 dw_base_addr = dev_context->dsp_base_addr;
 	struct cfg_hostres *resources = dev_context->resources;
 	int status = 0;
 	u32 base1, base2, base3;
@@ -195,18 +195,18 @@ int write_dsp_data(struct bridge_dev_context *dev_context,
 	if (!resources)
 		return -EPERM;
 
-	offset = dsp_addr - dev_context->dw_dsp_start_add;
+	offset = dsp_addr - dev_context->dsp_start_add;
 	if (offset < base1) {
-		dw_base_addr = MEM_LINEAR_ADDRESS(resources->dw_mem_base[2],
-						  resources->dw_mem_length[2]);
+		dw_base_addr = MEM_LINEAR_ADDRESS(resources->mem_base[2],
+						  resources->mem_length[2]);
 	} else if (offset > base1 && offset < base2 + OMAP_DSP_MEM2_SIZE) {
-		dw_base_addr = MEM_LINEAR_ADDRESS(resources->dw_mem_base[3],
-						  resources->dw_mem_length[3]);
+		dw_base_addr = MEM_LINEAR_ADDRESS(resources->mem_base[3],
+						  resources->mem_length[3]);
 		offset = offset - base2;
 	} else if (offset >= base2 + OMAP_DSP_MEM2_SIZE &&
 		   offset < base3 + OMAP_DSP_MEM3_SIZE) {
-		dw_base_addr = MEM_LINEAR_ADDRESS(resources->dw_mem_base[4],
-						  resources->dw_mem_length[4]);
+		dw_base_addr = MEM_LINEAR_ADDRESS(resources->mem_base[4],
+						  resources->mem_length[4]);
 		offset = offset - base3;
 	} else {
 		return -EPERM;
@@ -230,7 +230,7 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 			      u32 ul_num_bytes, u32 mem_type,
 			      bool dynamic_load)
 {
-	u32 dw_base_addr = dev_context->dw_dsp_ext_base_addr;
+	u32 dw_base_addr = dev_context->dsp_ext_base_addr;
 	u32 dw_offset = 0;
 	u8 temp_byte1, temp_byte2;
 	u8 remain_byte[4];
@@ -246,10 +246,10 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 
 	if (symbols_reloaded) {
 		/* Check if it is a load to Trace section */
-		ret = dev_get_symbol(dev_context->hdev_obj,
+		ret = dev_get_symbol(dev_context->dev_obj,
 				     DSP_TRACESEC_BEG, &ul_trace_sec_beg);
 		if (!ret)
-			ret = dev_get_symbol(dev_context->hdev_obj,
+			ret = dev_get_symbol(dev_context->dev_obj,
 					     DSP_TRACESEC_END,
 					     &ul_trace_sec_end);
 	}
@@ -263,13 +263,13 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 	if ((dynamic_load || trace_load) && dw_base_addr) {
 		dw_base_addr = 0;
 		MEM_UNMAP_LINEAR_ADDRESS((void *)
-					 dev_context->dw_dsp_ext_base_addr);
-		dev_context->dw_dsp_ext_base_addr = 0x0;
+					 dev_context->dsp_ext_base_addr);
+		dev_context->dsp_ext_base_addr = 0x0;
 	}
 	if (!dw_base_addr) {
 		if (symbols_reloaded)
 			/* Get SHM_BEG  EXT_BEG and EXT_END. */
-			ret = dev_get_symbol(dev_context->hdev_obj,
+			ret = dev_get_symbol(dev_context->dev_obj,
 					     SHMBASENAME, &ul_shm_base_virt);
 		DBC_ASSERT(ul_shm_base_virt != 0);
 		if (dynamic_load) {
@@ -277,7 +277,7 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 				if (symbols_reloaded)
 					ret =
 					    dev_get_symbol
-					    (dev_context->hdev_obj, DYNEXTBASE,
+					    (dev_context->dev_obj, DYNEXTBASE,
 					     &ul_ext_base);
 			}
 			DBC_ASSERT(ul_ext_base != 0);
@@ -289,7 +289,7 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 				if (symbols_reloaded)
 					ret =
 					    dev_get_symbol
-					    (dev_context->hdev_obj, EXTEND,
+					    (dev_context->dev_obj, EXTEND,
 					     &ul_ext_end);
 			}
 		} else {
@@ -297,13 +297,13 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 				if (!ret)
 					ret =
 					    dev_get_symbol
-					    (dev_context->hdev_obj, EXTBASE,
+					    (dev_context->dev_obj, EXTBASE,
 					     &ul_ext_base);
 				DBC_ASSERT(ul_ext_base != 0);
 				if (!ret)
 					ret =
 					    dev_get_symbol
-					    (dev_context->hdev_obj, EXTEND,
+					    (dev_context->dev_obj, EXTEND,
 					     &ul_ext_end);
 			}
 		}
@@ -319,17 +319,17 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 
 		if (!ret) {
 			ul_tlb_base_virt =
-			    dev_context->atlb_entry[0].ul_dsp_va * DSPWORDSIZE;
+			    dev_context->atlb_entry[0].dsp_va * DSPWORDSIZE;
 			DBC_ASSERT(ul_tlb_base_virt <= ul_shm_base_virt);
 
 			if (symbols_reloaded) {
 				ret = dev_get_symbol
-					    (dev_context->hdev_obj,
+					    (dev_context->dev_obj,
 					     DSP_TRACESEC_END, &shm0_end);
 				if (!ret) {
 					ret =
 					    dev_get_symbol
-					    (dev_context->hdev_obj, DYNEXTBASE,
+					    (dev_context->dev_obj, DYNEXTBASE,
 					     &ul_dyn_ext_base);
 				}
 			}
@@ -337,21 +337,21 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 			    ul_shm_base_virt - ul_tlb_base_virt;
 			if (trace_load) {
 				dw_ext_prog_virt_mem =
-				    dev_context->atlb_entry[0].ul_gpp_va;
+				    dev_context->atlb_entry[0].gpp_va;
 			} else {
-				dw_ext_prog_virt_mem = host_res->dw_mem_base[1];
+				dw_ext_prog_virt_mem = host_res->mem_base[1];
 				dw_ext_prog_virt_mem +=
 				    (ul_ext_base - ul_dyn_ext_base);
 			}
 
-			dev_context->dw_dsp_ext_base_addr =
+			dev_context->dsp_ext_base_addr =
 			    (u32) MEM_LINEAR_ADDRESS((void *)
 						     dw_ext_prog_virt_mem,
 						     ul_ext_end - ul_ext_base);
-			dw_base_addr += dev_context->dw_dsp_ext_base_addr;
-			/* This dw_dsp_ext_base_addr will get cleared only when
+			dw_base_addr += dev_context->dsp_ext_base_addr;
+			/* This dsp_ext_base_addr will get cleared only when
 			 * the board is stopped. */
-			if (!dev_context->dw_dsp_ext_base_addr)
+			if (!dev_context->dsp_ext_base_addr)
 				ret = -EPERM;
 		}
 	}
@@ -375,10 +375,10 @@ int write_ext_dsp_data(struct bridge_dev_context *dev_context,
 			*((u32 *) host_buff) = dw_base_addr + dw_offset;
 	}
 	/* Unmap here to force remap for other Ext loads */
-	if ((dynamic_load || trace_load) && dev_context->dw_dsp_ext_base_addr) {
+	if ((dynamic_load || trace_load) && dev_context->dsp_ext_base_addr) {
 		MEM_UNMAP_LINEAR_ADDRESS((void *)
-					 dev_context->dw_dsp_ext_base_addr);
-		dev_context->dw_dsp_ext_base_addr = 0x0;
+					 dev_context->dsp_ext_base_addr);
+		dev_context->dsp_ext_base_addr = 0x0;
 	}
 	symbols_reloaded = false;
 	return ret;
@@ -401,8 +401,8 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
 	if (!resources)
 		return -EPERM;
 
-	if (dev_context->dw_brd_state == BRD_DSP_HIBERNATION ||
-	    dev_context->dw_brd_state == BRD_HIBERNATION) {
+	if (dev_context->brd_state == BRD_DSP_HIBERNATION ||
+	    dev_context->brd_state == BRD_HIBERNATION) {
 #ifdef CONFIG_TIDSPBRIDGE_DVFS
 		if (pdata->dsp_get_opp)
 			opplevel = (*pdata->dsp_get_opp) ();
@@ -437,10 +437,10 @@ int sm_interrupt_dsp(struct bridge_dev_context *dev_context, u16 mb_val)
 		omap_mbox_restore_ctx(dev_context->mbox);
 
 		/* Access MMU SYS CONFIG register to generate a short wakeup */
-		temp = readl(resources->dw_dmmu_base + 0x10);
+		temp = readl(resources->dmmu_base + 0x10);
 
-		dev_context->dw_brd_state = BRD_RUNNING;
-	} else if (dev_context->dw_brd_state == BRD_RETENTION) {
+		dev_context->brd_state = BRD_RUNNING;
+	} else if (dev_context->brd_state == BRD_RETENTION) {
 		/* Restart the peripheral clocks */
 		dsp_clock_enable_all(dev_context->dsp_per_clks);
 	}
diff --git a/drivers/staging/tidspbridge/core/ue_deh.c b/drivers/staging/tidspbridge/core/ue_deh.c
index 3430418..006ffd7 100644
--- a/drivers/staging/tidspbridge/core/ue_deh.c
+++ b/drivers/staging/tidspbridge/core/ue_deh.c
@@ -52,16 +52,16 @@ static irqreturn_t mmu_fault_isr(int irq, void *data)
 	if (!deh)
 		return IRQ_HANDLED;
 
-	resources = deh->hbridge_context->resources;
+	resources = deh->bridge_context->resources;
 	if (!resources) {
 		dev_dbg(bridge, "%s: Failed to get Host Resources\n",
 				__func__);
 		return IRQ_HANDLED;
 	}
 
-	hw_mmu_event_status(resources->dw_dmmu_base, &event);
+	hw_mmu_event_status(resources->dmmu_base, &event);
 	if (event == HW_MMU_TRANSLATION_FAULT) {
-		hw_mmu_fault_addr_read(resources->dw_dmmu_base, &fault_addr);
+		hw_mmu_fault_addr_read(resources->dmmu_base, &fault_addr);
 		dev_dbg(bridge, "%s: event=0x%x, fault_addr=0x%x\n", __func__,
 				event, fault_addr);
 		/*
@@ -73,10 +73,10 @@ static irqreturn_t mmu_fault_isr(int irq, void *data)
 
 		/* Disable the MMU events, else once we clear it will
 		 * start to raise INTs again */
-		hw_mmu_event_disable(resources->dw_dmmu_base,
+		hw_mmu_event_disable(resources->dmmu_base,
 				HW_MMU_TRANSLATION_FAULT);
 	} else {
-		hw_mmu_event_disable(resources->dw_dmmu_base,
+		hw_mmu_event_disable(resources->dmmu_base,
 				HW_MMU_ALL_INTERRUPTS);
 	}
 	return IRQ_HANDLED;
@@ -113,7 +113,7 @@ int bridge_deh_create(struct deh_mgr **ret_deh,
 	tasklet_init(&deh->dpc_tasklet, mmu_fault_dpc, (u32) deh);
 
 	/* Fill in context structure */
-	deh->hbridge_context = hbridge_context;
+	deh->bridge_context = hbridge_context;
 
 	/* Install ISR function for DSP MMU fault */
 	status = request_irq(INT_DSP_MMU_IRQ, mmu_fault_isr, 0,
@@ -185,10 +185,10 @@ static void mmu_fault_print_stack(struct bridge_dev_context *dev_context)
 	 * access entry #0. Then add a new entry so that the DSP OS
 	 * can continue in order to dump the stack.
 	 */
-	hw_mmu_twl_disable(resources->dw_dmmu_base);
-	hw_mmu_tlb_flush_all(resources->dw_dmmu_base);
+	hw_mmu_twl_disable(resources->dmmu_base);
+	hw_mmu_tlb_flush_all(resources->dmmu_base);
 
-	hw_mmu_tlb_add(resources->dw_dmmu_base,
+	hw_mmu_tlb_add(resources->dmmu_base,
 			virt_to_phys(dummy_va_addr), fault_addr,
 			HW_PAGE_SIZE4KB, 1,
 			&map_attrs, HW_SET, HW_SET);
@@ -198,12 +198,12 @@ static void mmu_fault_print_stack(struct bridge_dev_context *dev_context)
 	dsp_gpt_wait_overflow(DSP_CLK_GPT8, 0xfffffffe);
 
 	/* Clear MMU interrupt */
-	hw_mmu_event_ack(resources->dw_dmmu_base,
+	hw_mmu_event_ack(resources->dmmu_base,
 			HW_MMU_TRANSLATION_FAULT);
 	dump_dsp_stack(dev_context);
 	dsp_clk_disable(DSP_CLK_GPT8);
 
-	hw_mmu_disable(resources->dw_dmmu_base);
+	hw_mmu_disable(resources->dmmu_base);
 	free_page((unsigned long)dummy_va_addr);
 }
 #endif
@@ -228,7 +228,7 @@ void bridge_deh_notify(struct deh_mgr *deh, int event, int info)
 		return;
 
 	dev_dbg(bridge, "%s: device exception", __func__);
-	dev_context = deh->hbridge_context;
+	dev_context = deh->bridge_context;
 
 	switch (event) {
 	case DSP_SYSERROR:
@@ -254,7 +254,7 @@ void bridge_deh_notify(struct deh_mgr *deh, int event, int info)
 	}
 
 	/* Filter subsequent notifications when an error occurs */
-	if (dev_context->dw_brd_state != BRD_ERROR) {
+	if (dev_context->brd_state != BRD_ERROR) {
 		ntfy_notify(deh->ntfy_obj, event);
 #ifdef CONFIG_TIDSPBRIDGE_RECOVERY
 		bridge_recover_schedule();
@@ -262,7 +262,7 @@ void bridge_deh_notify(struct deh_mgr *deh, int event, int info)
 	}
 
 	/* Set the Board state as ERROR */
-	dev_context->dw_brd_state = BRD_ERROR;
+	dev_context->brd_state = BRD_ERROR;
 	/* Disable all the clocks that were enabled by DSP */
 	dsp_clock_disable_all(dev_context->dsp_per_clks);
 	/*
diff --git a/drivers/staging/tidspbridge/dynload/cload.c b/drivers/staging/tidspbridge/dynload/cload.c
index c85a5e8..3900409 100644
--- a/drivers/staging/tidspbridge/dynload/cload.c
+++ b/drivers/staging/tidspbridge/dynload/cload.c
@@ -498,8 +498,8 @@ static void allocate_sections(struct dload_state *dlthis)
 		return;
 	}
 	/* initialize the handle header */
-	hndl->dm.hnext = hndl->dm.hprev = hndl;	/* circular list */
-	hndl->dm.hroot = NULL;
+	hndl->dm.next = hndl->dm.prev = hndl;	/* circular list */
+	hndl->dm.root = NULL;
 	hndl->dm.dbthis = 0;
 	dlthis->myhandle = hndl;	/* save away for return */
 	/* pointer to the section list of allocated sections */
@@ -1131,9 +1131,6 @@ static void dload_data(struct dload_state *dlthis)
 	u16 curr_sect;
 	struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
 	struct ldr_section_info *lptr = dlthis->ldr_sections;
-#ifdef OPT_ZERO_COPY_LOADER
-	bool zero_copy = false;
-#endif
 	u8 *dest;
 
 	struct {
@@ -1192,17 +1189,6 @@ static void dload_data(struct dload_state *dlthis)
 					return;
 				}
 				dest = ibuf.bufr;
-#ifdef OPT_ZERO_COPY_LOADER
-				zero_copy = false;
-				if (!dload_check_type(sptr, DLOAD_CINIT) {
-					dlthis->myio->writemem(dlthis->myio,
-							       &dest,
-							       lptr->load_addr +
-							       image_offset,
-							       lptr, 0);
-					zero_copy = (dest != ibuf.bufr);
-				}
-#endif
 				/* End of determination */
 
 				if (dlthis->strm->read_buffer(dlthis->strm,
@@ -1266,33 +1252,27 @@ static void dload_data(struct dload_state *dlthis)
 							    &ibuf.ipacket);
 						cinit_processed = true;
 					} else {
-#ifdef OPT_ZERO_COPY_LOADER
-						if (!zero_copy) {
-#endif
-							/* FIXME */
-							if (!dlthis->myio->
-							    writemem(dlthis->
-								myio,
-								ibuf.bufr,
-								lptr->
-								load_addr +
-								image_offset,
-								lptr,
-								BYTE_TO_HOST
-								(ibuf.
-								ipacket.
-								packet_size))) {
-								DL_ERROR
-								  ("Write to "
-								  FMT_UI32
-								  " failed",
-								  lptr->
-								  load_addr +
-								  image_offset);
-							}
-#ifdef OPT_ZERO_COPY_LOADER
+						/* FIXME */
+						if (!dlthis->myio->
+						    writemem(dlthis->
+							myio,
+							ibuf.bufr,
+							lptr->
+							load_addr +
+							image_offset,
+							lptr,
+							BYTE_TO_HOST
+							(ibuf.
+							ipacket.
+							packet_size))) {
+							DL_ERROR
+							  ("Write to "
+							  FMT_UI32
+							  " failed",
+							  lptr->
+							  load_addr +
+							  image_offset);
 						}
-#endif
 					}
 				}
 				image_offset +=
@@ -1646,7 +1626,7 @@ static void init_module_handle(struct dload_state *dlthis)
 			DL_ERROR(err_alloc, sizeof(struct dbg_mirror_root));
 			return;
 		}
-		mlst->hnext = NULL;
+		mlst->next = NULL;
 		mlst->changes = 0;
 		mlst->refcount = 0;
 		mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
@@ -1671,7 +1651,7 @@ static void init_module_handle(struct dload_state *dlthis)
 #else
 	mlist = (struct dbg_mirror_root *)&debug_list_header;
 #endif
-	hndl->dm.hroot = mlist;	/* set pointer to root into our handle */
+	hndl->dm.root = mlist;	/* set pointer to root into our handle */
 	if (!dlthis->allocated_secn_count)
 		return;		/* no load addresses to be recorded */
 	/* reuse temporary symbol storage */
@@ -1722,9 +1702,9 @@ static void init_module_handle(struct dload_state *dlthis)
 	dllview_info.context = 0;
 	hndl->dm.context = 0;
 	/* fill in next pointer and size */
-	if (mlist->hnext) {
-		dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
-		dbmod->next_module_size = mlist->hnext->dm.dbsiz;
+	if (mlist->next) {
+		dbmod->next_module = TADDR_TO_TDATA(mlist->next->dm.dbthis);
+		dbmod->next_module_size = mlist->next->dm.dbsiz;
 	} else {
 		dbmod->next_module_size = 0;
 		dbmod->next_module = 0;
@@ -1770,11 +1750,11 @@ static void init_module_handle(struct dload_state *dlthis)
 	}
 	/* Add the module handle to this processor's list
 	   of handles with debug info */
-	hndl->dm.hnext = mlist->hnext;
-	if (hndl->dm.hnext)
-		hndl->dm.hnext->dm.hprev = hndl;
-	hndl->dm.hprev = (struct my_handle *)mlist;
-	mlist->hnext = hndl;	/* insert after root */
+	hndl->dm.next = mlist->next;
+	if (hndl->dm.next)
+		hndl->dm.next->dm.prev = hndl;
+	hndl->dm.prev = (struct my_handle *)mlist;
+	mlist->next = hndl;	/* insert after root */
 }				/* init_module_handle */
 
 /*************************************************************************
@@ -1830,7 +1810,7 @@ int dynamic_unload_module(void *mhandle,
 			asecs->name = NULL;
 			alloc->dload_deallocate(alloc, asecs++);
 		}
-	root = hndl->dm.hroot;
+	root = hndl->dm.root;
 	if (!root) {
 		/* there is a debug list containing this module */
 		goto func_end;
@@ -1840,20 +1820,20 @@ int dynamic_unload_module(void *mhandle,
 	}
 	/* Retrieve memory context in which .dllview was allocated */
 	dllview_info.context = hndl->dm.context;
-	if (hndl->dm.hprev == hndl)
+	if (hndl->dm.prev == hndl)
 		goto exitunltgt;
 
 	/* target-side dllview record is in list */
 	/* dequeue this record from our GPP-side mirror list */
-	hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
-	if (hndl->dm.hnext)
-		hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
+	hndl->dm.prev->dm.next = hndl->dm.next;
+	if (hndl->dm.next)
+		hndl->dm.next->dm.prev = hndl->dm.prev;
 	/* Update next_module of previous entry in target list
 	 * We are using mhdr here as a surrogate for either a
 	 struct modules_header or a dll_module */
-	if (hndl->dm.hnext) {
-		mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
-		mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
+	if (hndl->dm.next) {
+		mhdr.first_module = TADDR_TO_TDATA(hndl->dm.next->dm.dbthis);
+		mhdr.first_module_size = hndl->dm.next->dm.dbsiz;
 	} else {
 		mhdr.first_module = 0;
 		mhdr.first_module_size = 0;
@@ -1871,7 +1851,7 @@ int dynamic_unload_module(void *mhandle,
 		swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
 			   MODULES_HEADER_BITMAP);
 	}
-	if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
+	if (!init->writemem(init, &mhdr, hndl->dm.prev->dm.dbthis,
 			    &dllview_info, sizeof(struct modules_header) -
 			    sizeof(mhdr.update_flag))) {
 		dload_syms_error(syms, dlvwrite);
diff --git a/drivers/staging/tidspbridge/dynload/dload_internal.h b/drivers/staging/tidspbridge/dynload/dload_internal.h
index 302a7c5..7b77573 100644
--- a/drivers/staging/tidspbridge/dynload/dload_internal.h
+++ b/drivers/staging/tidspbridge/dynload/dload_internal.h
@@ -78,15 +78,15 @@ struct my_handle;
 struct dbg_mirror_root {
 	/* must be same as dbg_mirror_list; __DLModules address on target */
 	u32 dbthis;
-	struct my_handle *hnext;	/* must be same as dbg_mirror_list */
+	struct my_handle *next;	/* must be same as dbg_mirror_list */
 	u16 changes;		/* change counter */
 	u16 refcount;		/* number of modules referencing this root */
 };
 
 struct dbg_mirror_list {
 	u32 dbthis;
-	struct my_handle *hnext, *hprev;
-	struct dbg_mirror_root *hroot;
+	struct my_handle *next, *prev;
+	struct dbg_mirror_root *root;
 	u16 dbsiz;
 	u32 context;	/* Save context for .dllview memory allocation */
 };
diff --git a/drivers/staging/tidspbridge/gen/gb.c b/drivers/staging/tidspbridge/gen/gb.c
deleted file mode 100644
index 9f59023..0000000
--- a/drivers/staging/tidspbridge/gen/gb.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * gb.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Generic bitmap operations.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*  ----------------------------------- DSP/BIOS Bridge */
-#include <linux/types.h>
-/*  ----------------------------------- This */
-#include <dspbridge/gs.h>
-#include <dspbridge/gb.h>
-
-struct gb_t_map {
-	u32 len;
-	u32 wcnt;
-	u32 *words;
-};
-
-/*
- *  ======== gb_clear ========
- *  purpose:
- *      Clears a bit in the bit map.
- */
-
-void gb_clear(struct gb_t_map *map, u32 bitn)
-{
-	u32 mask;
-
-	mask = 1L << (bitn % BITS_PER_LONG);
-	map->words[bitn / BITS_PER_LONG] &= ~mask;
-}
-
-/*
- *  ======== gb_create ========
- *  purpose:
- *      Creates a bit map.
- */
-
-struct gb_t_map *gb_create(u32 len)
-{
-	struct gb_t_map *map;
-	u32 i;
-	map = (struct gb_t_map *)gs_alloc(sizeof(struct gb_t_map));
-	if (map != NULL) {
-		map->len = len;
-		map->wcnt = len / BITS_PER_LONG + 1;
-		map->words = (u32 *) gs_alloc(map->wcnt * sizeof(u32));
-		if (map->words != NULL) {
-			for (i = 0; i < map->wcnt; i++)
-				map->words[i] = 0L;
-
-		} else {
-			gs_frees(map, sizeof(struct gb_t_map));
-			map = NULL;
-		}
-	}
-
-	return map;
-}
-
-/*
- *  ======== gb_delete ========
- *  purpose:
- *      Frees a bit map.
- */
-
-void gb_delete(struct gb_t_map *map)
-{
-	gs_frees(map->words, map->wcnt * sizeof(u32));
-	gs_frees(map, sizeof(struct gb_t_map));
-}
-
-/*
- *  ======== gb_findandset ========
- *  purpose:
- *      Finds a free bit and sets it.
- */
-u32 gb_findandset(struct gb_t_map *map)
-{
-	u32 bitn;
-
-	bitn = gb_minclear(map);
-
-	if (bitn != GB_NOBITS)
-		gb_set(map, bitn);
-
-	return bitn;
-}
-
-/*
- *  ======== gb_minclear ========
- *  purpose:
- *      returns the location of the first unset bit in the bit map.
- */
-u32 gb_minclear(struct gb_t_map *map)
-{
-	u32 bit_location = 0;
-	u32 bit_acc = 0;
-	u32 i;
-	u32 bit;
-	u32 *word;
-
-	for (word = map->words, i = 0; i < map->wcnt; word++, i++) {
-		if (~*word) {
-			for (bit = 0; bit < BITS_PER_LONG; bit++, bit_acc++) {
-				if (bit_acc == map->len)
-					return GB_NOBITS;
-
-				if (~*word & (1L << bit)) {
-					bit_location = i * BITS_PER_LONG + bit;
-					return bit_location;
-				}
-
-			}
-		} else {
-			bit_acc += BITS_PER_LONG;
-		}
-	}
-
-	return GB_NOBITS;
-}
-
-/*
- *  ======== gb_set ========
- *  purpose:
- *      Sets a bit in the bit map.
- */
-
-void gb_set(struct gb_t_map *map, u32 bitn)
-{
-	u32 mask;
-
-	mask = 1L << (bitn % BITS_PER_LONG);
-	map->words[bitn / BITS_PER_LONG] |= mask;
-}
-
-/*
- *  ======== gb_test ========
- *  purpose:
- *      Returns true if the bit is set in the specified location.
- */
-
-bool gb_test(struct gb_t_map *map, u32 bitn)
-{
-	bool state;
-	u32 mask;
-	u32 word;
-
-	mask = 1L << (bitn % BITS_PER_LONG);
-	word = map->words[bitn / BITS_PER_LONG];
-	state = word & mask ? true : false;
-
-	return state;
-}
diff --git a/drivers/staging/tidspbridge/gen/gh.c b/drivers/staging/tidspbridge/gen/gh.c
index f72d943..cd72503 100644
--- a/drivers/staging/tidspbridge/gen/gh.c
+++ b/drivers/staging/tidspbridge/gen/gh.c
@@ -17,9 +17,6 @@
 #include <linux/types.h>
 
 #include <dspbridge/host_os.h>
-
-#include <dspbridge/gs.h>
-
 #include <dspbridge/gh.h>
 
 struct element {
@@ -37,8 +34,6 @@ struct gh_t_hash_tab {
 };
 
 static void noop(void *p);
-static s32 cur_init;
-static void myfree(void *ptr, s32 size);
 
 /*
  *  ======== gh_create ========
@@ -51,8 +46,7 @@ struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size,
 {
 	struct gh_t_hash_tab *hash_tab;
 	u16 i;
-	hash_tab =
-	    (struct gh_t_hash_tab *)gs_alloc(sizeof(struct gh_t_hash_tab));
+	hash_tab = kzalloc(sizeof(struct gh_t_hash_tab), GFP_KERNEL);
 	if (hash_tab == NULL)
 		return NULL;
 	hash_tab->max_bucket = max_bucket;
@@ -62,7 +56,7 @@ struct gh_t_hash_tab *gh_create(u16 max_bucket, u16 val_size,
 	hash_tab->delete = delete == NULL ? noop : delete;
 
 	hash_tab->buckets = (struct element **)
-	    gs_alloc(sizeof(struct element *) * max_bucket);
+	    kzalloc(sizeof(struct element *) * max_bucket, GFP_KERNEL);
 	if (hash_tab->buckets == NULL) {
 		gh_delete(hash_tab);
 		return NULL;
@@ -89,17 +83,14 @@ void gh_delete(struct gh_t_hash_tab *hash_tab)
 				     elem = next) {
 					next = elem->next;
 					(*hash_tab->delete) (elem->data);
-					myfree(elem,
-					       sizeof(struct element) - 1 +
-					       hash_tab->val_size);
+					kfree(elem);
 				}
 			}
 
-			myfree(hash_tab->buckets, sizeof(struct element *)
-			       * hash_tab->max_bucket);
+			kfree(hash_tab->buckets);
 		}
 
-		myfree(hash_tab, sizeof(struct gh_t_hash_tab));
+		kfree(hash_tab);
 	}
 }
 
@@ -109,9 +100,7 @@ void gh_delete(struct gh_t_hash_tab *hash_tab)
 
 void gh_exit(void)
 {
-	if (cur_init-- == 1)
-		gs_exit();
-
+	/* Do nothing */
 }
 
 /*
@@ -138,8 +127,7 @@ void *gh_find(struct gh_t_hash_tab *hash_tab, void *key)
 
 void gh_init(void)
 {
-	if (cur_init++ == 0)
-		gs_init();
+	/* Do nothing */
 }
 
 /*
@@ -152,8 +140,8 @@ void *gh_insert(struct gh_t_hash_tab *hash_tab, void *key, void *value)
 	u16 i;
 	char *src, *dst;
 
-	elem = (struct element *)gs_alloc(sizeof(struct element) - 1 +
-					  hash_tab->val_size);
+	elem = kzalloc(sizeof(struct element) - 1 + hash_tab->val_size,
+			GFP_KERNEL);
 	if (elem != NULL) {
 
 		dst = (char *)elem->data;
@@ -180,14 +168,6 @@ static void noop(void *p)
 	p = p;			/* stifle compiler warning */
 }
 
-/*
- *  ======== myfree ========
- */
-static void myfree(void *ptr, s32 size)
-{
-	gs_free(ptr);
-}
-
 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
 /**
  * gh_iterate() - This function goes through all the elements in the hash table
diff --git a/drivers/staging/tidspbridge/gen/gs.c b/drivers/staging/tidspbridge/gen/gs.c
deleted file mode 100644
index 8335bf5..0000000
--- a/drivers/staging/tidspbridge/gen/gs.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * gs.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * General storage memory allocator services.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#include <linux/types.h>
-/*  ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/*  ----------------------------------- This */
-#include <dspbridge/gs.h>
-
-#include <linux/slab.h>
-
-/*  ----------------------------------- Globals */
-static u32 cumsize;
-
-/*
- *  ======== gs_alloc ========
- *  purpose:
- *      Allocates memory of the specified size.
- */
-void *gs_alloc(u32 size)
-{
-	void *p;
-
-	p = kzalloc(size, GFP_KERNEL);
-	if (p == NULL)
-		return NULL;
-	cumsize += size;
-	return p;
-}
-
-/*
- *  ======== gs_exit ========
- *  purpose:
- *      Discontinue the usage of the GS module.
- */
-void gs_exit(void)
-{
-	/* Do nothing */
-}
-
-/*
- *  ======== gs_free ========
- *  purpose:
- *      Frees the memory.
- */
-void gs_free(void *ptr)
-{
-	kfree(ptr);
-	/* ack! no size info */
-	/* cumsize -= size; */
-}
-
-/*
- *  ======== gs_frees ========
- *  purpose:
- *      Frees the memory.
- */
-void gs_frees(void *ptr, u32 size)
-{
-	kfree(ptr);
-	cumsize -= size;
-}
-
-/*
- *  ======== gs_init ========
- *  purpose:
- *      Initializes the GS module.
- */
-void gs_init(void)
-{
-	/* Do nothing */
-}
diff --git a/drivers/staging/tidspbridge/gen/uuidutil.c b/drivers/staging/tidspbridge/gen/uuidutil.c
index da39c4f..ff6ebad 100644
--- a/drivers/staging/tidspbridge/gen/uuidutil.c
+++ b/drivers/staging/tidspbridge/gen/uuidutil.c
@@ -45,11 +45,11 @@ void uuid_uuid_to_string(struct dsp_uuid *uuid_obj, char *sz_uuid,
 
 	i = snprintf(sz_uuid, size,
 		     "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
-		     uuid_obj->ul_data1, uuid_obj->us_data2, uuid_obj->us_data3,
-		     uuid_obj->uc_data4, uuid_obj->uc_data5,
-		     uuid_obj->uc_data6[0], uuid_obj->uc_data6[1],
-		     uuid_obj->uc_data6[2], uuid_obj->uc_data6[3],
-		     uuid_obj->uc_data6[4], uuid_obj->uc_data6[5]);
+		     uuid_obj->data1, uuid_obj->data2, uuid_obj->data3,
+		     uuid_obj->data4, uuid_obj->data5,
+		     uuid_obj->data6[0], uuid_obj->data6[1],
+		     uuid_obj->data6[2], uuid_obj->data6[3],
+		     uuid_obj->data6[4], uuid_obj->data6[5]);
 
 	DBC_ENSURE(i != -1);
 }
@@ -79,35 +79,35 @@ void uuid_uuid_from_string(char *sz_uuid, struct dsp_uuid *uuid_obj)
 {
 	s32 j;
 
-	uuid_obj->ul_data1 = uuid_hex_to_bin(sz_uuid, 8);
+	uuid_obj->data1 = uuid_hex_to_bin(sz_uuid, 8);
 	sz_uuid += 8;
 
 	/* Step over underscore */
 	sz_uuid++;
 
-	uuid_obj->us_data2 = (u16) uuid_hex_to_bin(sz_uuid, 4);
+	uuid_obj->data2 = (u16) uuid_hex_to_bin(sz_uuid, 4);
 	sz_uuid += 4;
 
 	/* Step over underscore */
 	sz_uuid++;
 
-	uuid_obj->us_data3 = (u16) uuid_hex_to_bin(sz_uuid, 4);
+	uuid_obj->data3 = (u16) uuid_hex_to_bin(sz_uuid, 4);
 	sz_uuid += 4;
 
 	/* Step over underscore */
 	sz_uuid++;
 
-	uuid_obj->uc_data4 = (u8) uuid_hex_to_bin(sz_uuid, 2);
+	uuid_obj->data4 = (u8) uuid_hex_to_bin(sz_uuid, 2);
 	sz_uuid += 2;
 
-	uuid_obj->uc_data5 = (u8) uuid_hex_to_bin(sz_uuid, 2);
+	uuid_obj->data5 = (u8) uuid_hex_to_bin(sz_uuid, 2);
 	sz_uuid += 2;
 
 	/* Step over underscore */
 	sz_uuid++;
 
 	for (j = 0; j < 6; j++) {
-		uuid_obj->uc_data6[j] = (u8) uuid_hex_to_bin(sz_uuid, 2);
+		uuid_obj->data6[j] = (u8) uuid_hex_to_bin(sz_uuid, 2);
 		sz_uuid += 2;
 	}
 }
diff --git a/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h b/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h
index 8efd1fb..d60e252 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/_chnl_sm.h
@@ -26,7 +26,7 @@
 #include <dspbridge/dspapi.h>
 #include <dspbridge/dspdefs.h>
 
-#include <dspbridge/list.h>
+#include <linux/list.h>
 #include <dspbridge/ntfy.h>
 
 /*
@@ -114,20 +114,20 @@ struct shm {
 struct chnl_mgr {
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
-	struct io_mgr *hio_mgr;	/* IO manager */
+	struct io_mgr *iomgr;	/* IO manager */
 	/* Device this board represents */
-	struct dev_object *hdev_obj;
+	struct dev_object *dev_obj;
 
 	/* These fields initialized in bridge_chnl_create(): */
-	u32 dw_output_mask;	/* Host output channels w/ full buffers */
-	u32 dw_last_output;	/* Last output channel fired from DPC */
+	u32 output_mask;	/* Host output channels w/ full buffers */
+	u32 last_output;	/* Last output channel fired from DPC */
 	/* Critical section object handle */
 	spinlock_t chnl_mgr_lock;
 	u32 word_size;		/* Size in bytes of DSP word */
 	u8 max_channels;	/* Total number of channels */
 	u8 open_channels;	/* Total number of open channels */
-	struct chnl_object **ap_channel;	/* Array of channels */
-	u8 dw_type;		/* Type of channel class library */
+	struct chnl_object **channels;		/* Array of channels */
+	u8 type;		/* Type of channel class library */
 	/* If no shm syms, return for CHNL_Open */
 	int chnl_open_status;
 };
@@ -140,21 +140,21 @@ struct chnl_object {
 	/* Pointer back to channel manager */
 	struct chnl_mgr *chnl_mgr_obj;
 	u32 chnl_id;		/* Channel id */
-	u8 dw_state;		/* Current channel state */
+	u8 state;		/* Current channel state */
 	s8 chnl_mode;		/* Chnl mode and attributes */
 	/* Chnl I/O completion event (user mode) */
 	void *user_event;
 	/* Abstract syncronization object */
 	struct sync_object *sync_event;
 	u32 process;		/* Process which created this channel */
-	u32 pcb_arg;		/* Argument to use with callback */
-	struct lst_list *pio_requests;	/* List of IOR's to driver */
+	u32 cb_arg;		/* Argument to use with callback */
+	struct list_head io_requests;	/* List of IOR's to driver */
 	s32 cio_cs;		/* Number of IOC's in queue */
 	s32 cio_reqs;		/* Number of IORequests in queue */
 	s32 chnl_packets;	/* Initial number of free Irps */
 	/* List of IOC's from driver */
-	struct lst_list *pio_completions;
-	struct lst_list *free_packets_list;	/* List of free Irps */
+	struct list_head io_completions;
+	struct list_head free_packets_list;	/* List of free Irps */
 	struct ntfy_object *ntfy_obj;
 	u32 bytes_moved;	/* Total number of bytes transfered */
 
@@ -171,7 +171,7 @@ struct chnl_irp {
 	u8 *host_user_buf;
 	/* Buffer to be filled/emptied. (System) */
 	u8 *host_sys_buf;
-	u32 dw_arg;		/* Issue/Reclaim argument. */
+	u32 arg;		/* Issue/Reclaim argument. */
 	u32 dsp_tx_addr;	/* Transfer address on DSP side. */
 	u32 byte_size;		/* Bytes transferred. */
 	u32 buf_size;		/* Actual buffer size when allocated. */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/brddefs.h b/drivers/staging/tidspbridge/include/dspbridge/brddefs.h
index f80d9a5..725d7b37 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/brddefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/brddefs.h
@@ -24,9 +24,7 @@
 #define BRD_IDLE        0x1	/* Monitor Loaded, but suspended. */
 #define BRD_RUNNING     0x2	/* Monitor loaded, and executing. */
 #define BRD_UNKNOWN     0x3	/* Board state is indeterminate. */
-#define BRD_SYNCINIT    0x4
 #define BRD_LOADED      0x5
-#define BRD_LASTSTATE   BRD_LOADED	/* Set to highest legal board state. */
 #define BRD_SLEEP_TRANSITION 0x6	/* Sleep transition in progress */
 #define BRD_HIBERNATION 0x7	/* MPU initiated hibernation */
 #define BRD_RETENTION     0x8	/* Retention mode */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
index 38122db..60a2781 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
@@ -19,25 +19,12 @@
 #ifndef CFGDEFS_
 #define CFGDEFS_
 
-/* Maximum length of module search path. */
-#define CFG_MAXSEARCHPATHLEN    255
-
-/* Maximum length of general paths. */
-#define CFG_MAXPATH             255
-
 /* Host Resources: */
 #define CFG_MAXMEMREGISTERS     9
-#define CFG_MAXIOPORTS          20
-#define CFG_MAXIRQS             7
-#define CFG_MAXDMACHANNELS      7
 
 /* IRQ flag */
 #define CFG_IRQSHARED           0x01	/* IRQ can be shared */
 
-/* DSP Resources: */
-#define CFG_DSPMAXMEMTYPES      10
-#define CFG_DEFAULT_NUM_WINDOWS 1	/* We support only one window. */
-
 /* A platform-related device handle: */
 struct cfg_devnode;
 
@@ -47,35 +34,28 @@ struct cfg_devnode;
 struct cfg_hostres {
 	u32 num_mem_windows;	/* Set to default */
 	/* This is the base.memory */
-	u32 dw_mem_base[CFG_MAXMEMREGISTERS];	/* shm virtual address */
-	u32 dw_mem_length[CFG_MAXMEMREGISTERS];	/* Length of the Base */
-	u32 dw_mem_phys[CFG_MAXMEMREGISTERS];	/* shm Physical address */
+	u32 mem_base[CFG_MAXMEMREGISTERS];	/* shm virtual address */
+	u32 mem_length[CFG_MAXMEMREGISTERS];	/* Length of the Base */
+	u32 mem_phys[CFG_MAXMEMREGISTERS];	/* shm Physical address */
 	u8 birq_registers;	/* IRQ Number */
 	u8 birq_attrib;		/* IRQ Attribute */
-	u32 dw_offset_for_monitor;	/* The Shared memory starts from
-					 * dw_mem_base + this offset */
+	u32 offset_for_monitor;	/* The Shared memory starts from
+					 * mem_base + this offset */
 	/*
 	 *  Info needed by NODE for allocating channels to communicate with RMS:
-	 *      dw_chnl_offset:       Offset of RMS channels. Lower channels are
+	 *      chnl_offset:       Offset of RMS channels. Lower channels are
 	 *                          reserved.
-	 *      dw_chnl_buf_size:      Size of channel buffer to send to RMS
-	 *      dw_num_chnls:		Total number of channels
+	 *      chnl_buf_size:      Size of channel buffer to send to RMS
+	 *      num_chnls:		Total number of channels
 	 *      			(including reserved).
 	 */
-	u32 dw_chnl_offset;
-	u32 dw_chnl_buf_size;
-	u32 dw_num_chnls;
-	void __iomem *dw_per_base;
-	u32 dw_per_pm_base;
-	u32 dw_core_pm_base;
-	void __iomem *dw_dmmu_base;
-	void __iomem *dw_sys_ctrl_base;
-};
-
-struct cfg_dspmemdesc {
-	u32 mem_type;		/* Type of memory. */
-	u32 ul_min;		/* Minimum amount of memory of this type. */
-	u32 ul_max;		/* Maximum amount of memory of this type. */
+	u32 chnl_offset;
+	u32 chnl_buf_size;
+	u32 num_chnls;
+	void __iomem *per_base;
+	u32 per_pm_base;
+	u32 core_pm_base;
+	void __iomem *dmmu_base;
 };
 
 #endif /* CFGDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/chnl.h b/drivers/staging/tidspbridge/include/dspbridge/chnl.h
index 8733b3b..92f6a13 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/chnl.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/chnl.h
@@ -25,27 +25,6 @@
 #include <dspbridge/chnlpriv.h>
 
 /*
- *  ======== chnl_close ========
- *  Purpose:
- *      Ensures all pending I/O on this channel is cancelled, discards all
- *      queued I/O completion notifications, then frees the resources allocated
- *      for this channel, and makes the corresponding logical channel id
- *      available for subsequent use.
- *  Parameters:
- *      chnl_obj:          Channel object handle.
- *  Returns:
- *      0:        Success;
- *      -EFAULT:    Invalid chnl_obj.
- *  Requires:
- *      chnl_init(void) called.
- *      No thread must be blocked on this channel's I/O completion event.
- *  Ensures:
- *      0:        The I/O completion event for this channel is freed.
- *                      chnl_obj is no longer valid.
- */
-extern int chnl_close(struct chnl_object *chnl_obj);
-
-/*
  *  ======== chnl_create ========
  *  Purpose:
  *      Create a channel manager object, responsible for opening new channels
diff --git a/drivers/staging/tidspbridge/include/dspbridge/chnldefs.h b/drivers/staging/tidspbridge/include/dspbridge/chnldefs.h
index 5bf5f6b..cb67c30 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/chnldefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/chnldefs.h
@@ -22,9 +22,6 @@
 /* Channel id option. */
 #define CHNL_PICKFREE       (~0UL)	/* Let manager pick a free channel. */
 
-/* Channel manager limits: */
-#define CHNL_INITIOREQS      4	/* Default # of I/O requests. */
-
 /* Channel modes */
 #define CHNL_MODETODSP		0	/* Data streaming to the DSP. */
 #define CHNL_MODEFROMDSP	1	/* Data streaming from the DSP. */
@@ -48,7 +45,7 @@
 struct chnl_attr {
 	u32 uio_reqs;		/* Max # of preallocated I/O requests. */
 	void *event_obj;	/* User supplied auto-reset event object. */
-	char *pstr_event_name;	/* Ptr to name of user event object. */
+	char *str_event_name;	/* Ptr to name of user event object. */
 	void *reserved1;	/* Reserved for future use. */
 	u32 reserved2;		/* Reserved for future use. */
 
@@ -56,11 +53,11 @@ struct chnl_attr {
 
 /* I/O completion record: */
 struct chnl_ioc {
-	void *pbuf;		/* Buffer to be filled/emptied. */
+	void *buf;		/* Buffer to be filled/emptied. */
 	u32 byte_size;		/* Bytes transferred. */
 	u32 buf_size;		/* Actual buffer size in bytes */
 	u32 status;		/* Status of IO completion. */
-	u32 dw_arg;		/* User argument associated with pbuf. */
+	u32 arg;		/* User argument associated with buf. */
 };
 
 #endif /* CHNLDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/chnlpriv.h b/drivers/staging/tidspbridge/include/dspbridge/chnlpriv.h
index 9292100..4114c79 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/chnlpriv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/chnlpriv.h
@@ -39,12 +39,6 @@
  */
 #define CHNL_PCPY       0	/* Proc-copy transport 0 */
 
-#define CHNL_MAXIRQ     0xff	/* Arbitrarily large number. */
-
-/* The following modes are private: */
-#define CHNL_MODEUSEREVENT  0x1000	/* User provided the channel event. */
-#define CHNL_MODEMASK       0x1001
-
 /* Higher level channel states: */
 #define CHNL_STATEREADY		0	/* Channel ready for I/O. */
 #define CHNL_STATECANCEL	1	/* I/O was cancelled. */
@@ -56,23 +50,16 @@
 
 /* Types of channel class libraries: */
 #define CHNL_TYPESM         1	/* Shared memory driver. */
-#define CHNL_TYPEBM         2	/* Bus Mastering driver. */
-
-/* Max string length of channel I/O completion event name - change if needed */
-#define CHNL_MAXEVTNAMELEN  32
-
-/* Max memory pages lockable in CHNL_PrepareBuffer() - change if needed */
-#define CHNL_MAXLOCKPAGES   64
 
 /* Channel info. */
 struct chnl_info {
-	struct chnl_mgr *hchnl_mgr;	/* Owning channel manager. */
+	struct chnl_mgr *chnl_mgr;	/* Owning channel manager. */
 	u32 cnhl_id;		/* Channel ID. */
 	void *event_obj;	/* Channel I/O completion event. */
 	/*Abstraction of I/O completion event. */
 	struct sync_object *sync_event;
-	s8 dw_mode;		/* Channel mode. */
-	u8 dw_state;		/* Current channel state. */
+	s8 mode;		/* Channel mode. */
+	u8 state;		/* Current channel state. */
 	u32 bytes_tx;		/* Total bytes transferred. */
 	u32 cio_cs;		/* Number of IOCs in queue. */
 	u32 cio_reqs;		/* Number of IO Requests in queue. */
@@ -81,7 +68,7 @@ struct chnl_info {
 
 /* Channel manager info: */
 struct chnl_mgrinfo {
-	u8 dw_type;		/* Type of channel class library. */
+	u8 type;		/* Type of channel class library. */
 	/* Channel handle, given the channel id. */
 	struct chnl_object *chnl_obj;
 	u8 open_channels;	/* Number of open channels. */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/cmm.h b/drivers/staging/tidspbridge/include/dspbridge/cmm.h
index 6ad313f..27a21b5 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/cmm.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/cmm.h
@@ -81,7 +81,7 @@ extern void *cmm_calloc_buf(struct cmm_object *hcmm_mgr,
  *  Requires:
  *      cmm_init(void) called.
  *      ph_cmm_mgr != NULL.
- *      mgr_attrts->ul_min_block_size >= 4 bytes.
+ *      mgr_attrts->min_block_size >= 4 bytes.
  *  Ensures:
  *
  */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/cmmdefs.h b/drivers/staging/tidspbridge/include/dspbridge/cmmdefs.h
index fbff372..a264fa69 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/cmmdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/cmmdefs.h
@@ -19,18 +19,17 @@
 #ifndef CMMDEFS_
 #define CMMDEFS_
 
-#include <dspbridge/list.h>
 
 /* Cmm attributes used in cmm_create() */
 struct cmm_mgrattrs {
 	/* Minimum SM allocation; default 32 bytes. */
-	u32 ul_min_block_size;
+	u32 min_block_size;
 };
 
 /* Attributes for CMM_AllocBuf() & CMM_AllocDesc() */
 struct cmm_attrs {
-	u32 ul_seg_id;		/*  1,2... are SM segments. 0 is not. */
-	u32 ul_alignment;	/*  0,1,2,4....ul_min_block_size */
+	u32 seg_id;		/*  1,2... are SM segments. 0 is not. */
+	u32 alignment;		/*  0,1,2,4....min_block_size */
 };
 
 /*
@@ -52,40 +51,40 @@ struct cmm_attrs {
  */
 
 struct cmm_seginfo {
-	u32 dw_seg_base_pa;	/* Start Phys address of SM segment */
+	u32 seg_base_pa;	/* Start Phys address of SM segment */
 	/* Total size in bytes of segment: DSP+GPP */
-	u32 ul_total_seg_size;
-	u32 dw_gpp_base_pa;	/* Start Phys addr of Gpp SM seg */
-	u32 ul_gpp_size;	/* Size of Gpp SM seg in bytes */
-	u32 dw_dsp_base_va;	/* DSP virt base byte address */
-	u32 ul_dsp_size;	/* DSP seg size in bytes */
+	u32 total_seg_size;
+	u32 gpp_base_pa;	/* Start Phys addr of Gpp SM seg */
+	u32 gpp_size;	/* Size of Gpp SM seg in bytes */
+	u32 dsp_base_va;	/* DSP virt base byte address */
+	u32 dsp_size;		/* DSP seg size in bytes */
 	/* # of current GPP allocations from this segment */
-	u32 ul_in_use_cnt;
-	u32 dw_seg_base_va;	/* Start Virt address of SM seg */
+	u32 in_use_cnt;
+	u32 seg_base_va;	/* Start Virt address of SM seg */
 
 };
 
 /* CMM useful information */
 struct cmm_info {
 	/* # of SM segments registered with this Cmm. */
-	u32 ul_num_gppsm_segs;
+	u32 num_gppsm_segs;
 	/* Total # of allocations outstanding for CMM */
-	u32 ul_total_in_use_cnt;
+	u32 total_in_use_cnt;
 	/* Min SM block size allocation from cmm_create() */
-	u32 ul_min_block_size;
+	u32 min_block_size;
 	/* Info per registered SM segment. */
 	struct cmm_seginfo seg_info[CMM_MAXGPPSEGS];
 };
 
 /* XlatorCreate attributes */
 struct cmm_xlatorattrs {
-	u32 ul_seg_id;		/* segment Id used for SM allocations */
-	u32 dw_dsp_bufs;	/* # of DSP-side bufs */
-	u32 dw_dsp_buf_size;	/* size of DSP-side bufs in GPP bytes */
+	u32 seg_id;		/* segment Id used for SM allocations */
+	u32 dsp_bufs;		/* # of DSP-side bufs */
+	u32 dsp_buf_size;	/* size of DSP-side bufs in GPP bytes */
 	/* Vm base address alloc'd in client process context */
 	void *vm_base;
-	/* dw_vm_size must be >= (dwMaxNumBufs * dwMaxSize) */
-	u32 dw_vm_size;
+	/* vm_size must be >= (dwMaxNumBufs * dwMaxSize) */
+	u32 vm_size;
 };
 
 /*
diff --git a/drivers/staging/tidspbridge/include/dspbridge/cod.h b/drivers/staging/tidspbridge/include/dspbridge/cod.h
index 42bce2e..53bd4bb 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/cod.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/cod.h
@@ -27,9 +27,6 @@
 #define COD_TRACEBEG            "SYS_PUTCBEG"
 #define COD_TRACEEND            "SYS_PUTCEND"
 #define COD_TRACECURPOS	"BRIDGE_SYS_PUTC_current"
-#define COD_TRACESECT           "trace"
-#define COD_TRACEBEGOLD         "PUTCBEG"
-#define COD_TRACEENDOLD         "PUTCEND"
 
 #define COD_NOLOAD              DBLL_NOLOAD
 #define COD_SYMB                DBLL_SYMB
@@ -40,11 +37,6 @@ struct cod_manager;
 /* COD library handle */
 struct cod_libraryobj;
 
-/* COD attributes */
-struct cod_attrs {
-	u32 ul_reserved;
-};
-
 /*
  *  Function prototypes for writing memory to a DSP system, allocating
  *  and freeing DSP memory.
@@ -79,8 +71,6 @@ extern void cod_close(struct cod_libraryobj *lib);
  *  Parameters:
  *      manager:        created manager object
  *      str_zl_file:    ZL DLL filename, of length < COD_MAXPATHLENGTH.
- *      attrs:          attributes to be used by this object. A NULL value
- *                      will cause default attrs to be used.
  *  Returns:
  *      0:                Success.
  *      -ESPIPE:   ZL_Create failed.
@@ -92,8 +82,7 @@ extern void cod_close(struct cod_libraryobj *lib);
  *  Ensures:
  */
 extern int cod_create(struct cod_manager **mgr,
-			     char *str_zl_file,
-			     const struct cod_attrs *attrs);
+			     char *str_zl_file);
 
 /*
  *  ======== cod_delete ========
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbdcddef.h b/drivers/staging/tidspbridge/include/dspbridge/dbdcddef.h
index 1daa4b5..bc201b3 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dbdcddef.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dbdcddef.h
@@ -48,15 +48,15 @@ struct dcd_nodeprops {
 	struct dsp_ndbprops ndb_props;
 	u32 msg_segid;
 	u32 msg_notify_type;
-	char *pstr_create_phase_fxn;
-	char *pstr_delete_phase_fxn;
-	char *pstr_execute_phase_fxn;
-	char *pstr_i_alg_name;
+	char *str_create_phase_fxn;
+	char *str_delete_phase_fxn;
+	char *str_execute_phase_fxn;
+	char *str_i_alg_name;
 
 	/* Dynamic load properties */
-	u16 us_load_type;	/* Static, dynamic, overlay */
-	u32 ul_data_mem_seg_mask;	/* Data memory requirements */
-	u32 ul_code_mem_seg_mask;	/* Code memory requirements */
+	u16 load_type;	/* Static, dynamic, overlay */
+	u32 data_mem_seg_mask;		/* Data memory requirements */
+	u32 code_mem_seg_mask;		/* Code memory requirements */
 };
 
 /* DCD Generic Object Type */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbdefs.h b/drivers/staging/tidspbridge/include/dspbridge/dbdefs.h
index 5af075d..c8f4645 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dbdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dbdefs.h
@@ -31,9 +31,6 @@
 /* API return value and calling convention */
 #define DBAPI                       int
 
-/* Infinite time value for the utimeout parameter to DSPStream_Select() */
-#define DSP_FOREVER                 (-1)
-
 /* Maximum length of node name, used in dsp_ndbprops */
 #define DSP_MAXNAMELEN              32
 
@@ -74,16 +71,9 @@
 #define DSP_NODE_MIN_PRIORITY       1
 #define DSP_NODE_MAX_PRIORITY       15
 
-/* Pre-Defined Message Command Codes available to user: */
-#define DSP_RMSUSERCODESTART RMS_USER	/* Start of RMS user cmd codes */
-/* end of user codes */
-#define DSP_RMSUSERCODEEND (RMS_USER + RMS_MAXUSERCODES);
 /* msg_ctrl contains SM buffer description */
 #define DSP_RMSBUFDESC RMS_BUFDESC
 
-/* Shared memory identifier for MEM segment named "SHMSEG0" */
-#define DSP_SHMSEG0     (u32)(-1)
-
 /* Processor ID numbers */
 #define DSP_UNIT    0
 #define IVA_UNIT    1
@@ -91,15 +81,6 @@
 #define DSPWORD       unsigned char
 #define DSPWORDSIZE     sizeof(DSPWORD)
 
-/* Power control enumerations */
-#define PROC_PWRCONTROL             0x8070
-
-#define PROC_PWRMGT_ENABLE          (PROC_PWRCONTROL + 0x3)
-#define PROC_PWRMGT_DISABLE         (PROC_PWRCONTROL + 0x4)
-
-/* Bridge Code Version */
-#define BRIDGE_VERSION_CODE         333
-
 #define    MAX_PROFILES     16
 
 /* DSP chip type */
@@ -118,12 +99,12 @@ static inline bool is_valid_proc_event(u32 x)
 
 /* The Node UUID structure */
 struct dsp_uuid {
-	u32 ul_data1;
-	u16 us_data2;
-	u16 us_data3;
-	u8 uc_data4;
-	u8 uc_data5;
-	u8 uc_data6[6];
+	u32 data1;
+	u16 data2;
+	u16 data3;
+	u8 data4;
+	u8 data5;
+	u8 data6[6];
 };
 
 /* DCD types */
@@ -227,11 +208,11 @@ enum dsp_flushtype {
 
 /* Memory Segment Status Values */
 struct dsp_memstat {
-	u32 ul_size;
-	u32 ul_total_free_size;
-	u32 ul_len_max_free_block;
-	u32 ul_num_free_blocks;
-	u32 ul_num_alloc_blocks;
+	u32 size;
+	u32 total_free_size;
+	u32 len_max_free_block;
+	u32 num_free_blocks;
+	u32 num_alloc_blocks;
 };
 
 /* Processor Load information Values */
@@ -248,11 +229,11 @@ struct dsp_strmattr {
 	u32 buf_size;		/* Buffer size (DSP words) */
 	u32 num_bufs;		/* Number of buffers */
 	u32 buf_alignment;	/* Buffer alignment */
-	u32 utimeout;		/* Timeout for blocking STRM calls */
+	u32 timeout;		/* Timeout for blocking STRM calls */
 	enum dsp_strmmode strm_mode;	/* mode of stream when opened */
 	/* DMA chnl id if dsp_strmmode is LDMA or RDMA */
-	u32 udma_chnl_id;
-	u32 udma_priority;	/* DMA channel priority 0=lowest, >0=high */
+	u32 dma_chnl_id;
+	u32 dma_priority;	/* DMA channel priority 0=lowest, >0=high */
 };
 
 /* The dsp_cbdata structure */
@@ -263,9 +244,9 @@ struct dsp_cbdata {
 
 /* The dsp_msg structure */
 struct dsp_msg {
-	u32 dw_cmd;
-	u32 dw_arg1;
-	u32 dw_arg2;
+	u32 cmd;
+	u32 arg1;
+	u32 arg2;
 };
 
 /* The dsp_resourcereqmts structure for node's resource requirements */
@@ -274,9 +255,9 @@ struct dsp_resourcereqmts {
 	u32 static_data_size;
 	u32 global_data_size;
 	u32 program_mem_size;
-	u32 uwc_execution_time;
-	u32 uwc_period;
-	u32 uwc_deadline;
+	u32 wc_execution_time;
+	u32 wc_period;
+	u32 wc_deadline;
 	u32 avg_exection_time;
 	u32 minimum_period;
 };
@@ -295,7 +276,7 @@ struct dsp_streamconnect {
 };
 
 struct dsp_nodeprofs {
-	u32 ul_heap_size;
+	u32 heap_size;
 };
 
 /* The dsp_ndbprops structure reports the attributes of a node */
@@ -313,7 +294,7 @@ struct dsp_ndbprops {
 	u32 message_depth;
 	u32 num_input_streams;
 	u32 num_output_streams;
-	u32 utimeout;
+	u32 timeout;
 	u32 count_profiles;	/* Number of supported profiles */
 	/* Array of profiles */
 	struct dsp_nodeprofs node_profiles[MAX_PROFILES];
@@ -325,7 +306,7 @@ struct dsp_ndbprops {
 struct dsp_nodeattrin {
 	u32 cb_struct;
 	s32 prio;
-	u32 utimeout;
+	u32 timeout;
 	u32 profile_id;
 	/* Reserved, for Bridge Internal use only */
 	u32 heap_size;
@@ -359,14 +340,14 @@ struct dsp_nodeattr {
  *  window handle.
  */
 struct dsp_notification {
-	char *ps_name;
+	char *name;
 	void *handle;
 };
 
 /* The dsp_processorattrin structure describes the attributes of a processor */
 struct dsp_processorattrin {
 	u32 cb_struct;
-	u32 utimeout;
+	u32 timeout;
 };
 /*
  * The dsp_processorinfo structure describes basic capabilities of a
@@ -377,8 +358,8 @@ struct dsp_processorinfo {
 	int processor_family;
 	int processor_type;
 	u32 clock_rate;
-	u32 ul_internal_mem_size;
-	u32 ul_external_mem_size;
+	u32 internal_mem_size;
+	u32 external_mem_size;
 	u32 processor_id;
 	int ty_running_rtos;
 	s32 node_min_priority;
@@ -387,10 +368,10 @@ struct dsp_processorinfo {
 
 /* Error information of last DSP exception signalled to the GPP */
 struct dsp_errorinfo {
-	u32 dw_err_mask;
-	u32 dw_val1;
-	u32 dw_val2;
-	u32 dw_val3;
+	u32 err_mask;
+	u32 val1;
+	u32 val2;
+	u32 val3;
 };
 
 /* The dsp_processorstate structure describes the state of a DSP processor */
@@ -407,7 +388,7 @@ struct dsp_resourceinfo {
 	u32 cb_struct;
 	enum dsp_resourceinfotype resource_type;
 	union {
-		u32 ul_resource;
+		u32 resource;
 		struct dsp_memstat mem_stat;
 		struct dsp_procloadstat proc_load_stat;
 	} result;
@@ -420,13 +401,13 @@ struct dsp_resourceinfo {
  */
 struct dsp_streamattrin {
 	u32 cb_struct;
-	u32 utimeout;
+	u32 timeout;
 	u32 segment_id;
 	u32 buf_alignment;
 	u32 num_bufs;
 	enum dsp_strmmode strm_mode;
-	u32 udma_chnl_id;
-	u32 udma_priority;
+	u32 dma_chnl_id;
+	u32 dma_priority;
 };
 
 /* The dsp_bufferattr structure describes the attributes of a data buffer */
@@ -444,7 +425,7 @@ struct dsp_streaminfo {
 	u32 cb_struct;
 	u32 number_bufs_allowed;
 	u32 number_bufs_in_stream;
-	u32 ul_number_bytes;
+	u32 number_bytes;
 	void *sync_object_handle;
 	enum dsp_streamstate ss_stream_state;
 };
@@ -501,13 +482,6 @@ bit 15 - Output (writeable) buffer
 #define DSPPROCTYPE_C64		6410
 #define IVAPROCTYPE_ARM7	470
 
-#define REG_MGR_OBJECT	1
-#define REG_DRV_OBJECT	2
-
-/* registry */
-#define DRVOBJECT	"DrvObject"
-#define MGROBJECT	"MgrObject"
-
 /* Max registry path length. Also the max registry value length. */
 #define MAXREGPATHLENGTH	255
 
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbldefs.h b/drivers/staging/tidspbridge/include/dspbridge/dbldefs.h
deleted file mode 100644
index bf4fb99..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/dbldefs.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * dbldefs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef DBLDEFS_
-#define DBLDEFS_
-
-/*
- *  Bit masks for dbl_flags.
- */
-#define DBL_NOLOAD   0x0	/* Don't load symbols, code, or data */
-#define DBL_SYMB     0x1	/* load symbols */
-#define DBL_CODE     0x2	/* load code */
-#define DBL_DATA     0x4	/* load data */
-#define DBL_DYNAMIC  0x8	/* dynamic load */
-#define DBL_BSS      0x20	/* Unitialized section */
-
-#define DBL_MAXPATHLENGTH       255
-
-/*
- *  ======== dbl_flags ========
- *  Specifies whether to load code, data, or symbols
- */
-typedef s32 dbl_flags;
-
-/*
- *  ======== dbl_sect_info ========
- *  For collecting info on overlay sections
- */
-struct dbl_sect_info {
-	const char *name;	/* name of section */
-	u32 sect_run_addr;	/* run address of section */
-	u32 sect_load_addr;	/* load address of section */
-	u32 size;		/* size of section (target MAUs) */
-	dbl_flags type;		/* Code, data, or BSS */
-};
-
-/*
- *  ======== dbl_symbol ========
- *  (Needed for dynamic load library)
- */
-struct dbl_symbol {
-	u32 value;
-};
-
-/*
- *  ======== dbl_alloc_fxn ========
- *  Allocate memory function.  Allocate or reserve (if reserved == TRUE)
- *  "size" bytes of memory from segment "space" and return the address in
- *  *dsp_address (or starting at *dsp_address if reserve == TRUE). Returns 0 on
- *  success, or an error code on failure.
- */
-typedef s32(*dbl_alloc_fxn) (void *hdl, s32 space, u32 size, u32 align,
-			     u32 *dsp_address, s32 seg_id, s32 req,
-			     bool reserved);
-
-/*
- *  ======== dbl_free_fxn ========
- *  Free memory function.  Free, or unreserve (if reserved == TRUE) "size"
- *  bytes of memory from segment "space"
- */
-typedef bool(*dbl_free_fxn) (void *hdl, u32 addr, s32 space, u32 size,
-			     bool reserved);
-
-/*
- *  ======== dbl_log_write_fxn ========
- *  Function to call when writing data from a section, to log the info.
- *  Can be NULL if no logging is required.
- */
-typedef int(*dbl_log_write_fxn) (void *handle,
-					struct dbl_sect_info *sect, u32 addr,
-					u32 bytes);
-
-/*
- *  ======== dbl_sym_lookup ========
- *  Symbol lookup function - Find the symbol name and return its value.
- *
- *  Parameters:
- *      handle          - Opaque handle
- *      parg            - Opaque argument.
- *      name            - Name of symbol to lookup.
- *      sym             - Location to store address of symbol structure.
- *
- *  Returns:
- *      TRUE:           Success (symbol was found).
- *      FALSE:          Failed to find symbol.
- */
-typedef bool(*dbl_sym_lookup) (void *handle, void *parg, void *rmm_handle,
-			       const char *name, struct dbl_symbol ** sym);
-
-/*
- *  ======== dbl_write_fxn ========
- *  Write memory function.  Write "n" HOST bytes of memory to segment "mtype"
- *  starting at address "dsp_address" from the buffer "buf".  The buffer is
- *  formatted as an array of words appropriate for the DSP.
- */
-typedef s32(*dbl_write_fxn) (void *hdl, u32 dsp_address, void *buf,
-			     u32 n, s32 mtype);
-
-/*
- *  ======== dbl_attrs ========
- */
-struct dbl_attrs {
-	dbl_alloc_fxn alloc;
-	dbl_free_fxn free;
-	void *rmm_handle;	/* Handle to pass to alloc, free functions */
-	dbl_write_fxn write;
-	void *input_params;	/* Handle to pass to write, cinit function */
-
-	dbl_log_write_fxn log_write;
-	void *log_write_handle;
-
-	/* Symbol matching function and handle to pass to it */
-	dbl_sym_lookup sym_lookup;
-	void *sym_handle;
-	void *sym_arg;
-
-	/*
-	 *  These file manipulation functions should be compatible with the
-	 *  "C" run time library functions of the same name.
-	 */
-	 s32(*fread) (void *, size_t, size_t, void *);
-	 s32(*fseek) (void *, long, int);
-	 s32(*ftell) (void *);
-	 s32(*fclose) (void *);
-	void *(*fopen) (const char *, const char *);
-};
-
-#endif /* DBLDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dbll.h b/drivers/staging/tidspbridge/include/dspbridge/dbll.h
index b018676..46a9e00 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dbll.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dbll.h
@@ -42,18 +42,12 @@ extern bool dbll_init(void);
 extern int dbll_load(struct dbll_library_obj *lib,
 			    dbll_flags flags,
 			    struct dbll_attrs *attrs, u32 * entry);
-extern int dbll_load_sect(struct dbll_library_obj *zl_lib,
-				 char *sec_name, struct dbll_attrs *attrs);
 extern int dbll_open(struct dbll_tar_obj *target, char *file,
 			    dbll_flags flags,
 		       struct dbll_library_obj **lib_obj);
 extern int dbll_read_sect(struct dbll_library_obj *lib,
 				 char *name, char *buf, u32 size);
-extern void dbll_set_attrs(struct dbll_tar_obj *target,
-			   struct dbll_attrs *pattrs);
 extern void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs);
-extern int dbll_unload_sect(struct dbll_library_obj *lib,
-				   char *sect_name, struct dbll_attrs *attrs);
 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
 bool dbll_find_dsp_symbol(struct dbll_library_obj *zl_lib, u32 address,
 		u32 offset_range, u32 *sym_addr_output, char *name_output);
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dblldefs.h b/drivers/staging/tidspbridge/include/dspbridge/dblldefs.h
index d2b4fda..30e0aa0 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dblldefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dblldefs.h
@@ -348,29 +348,6 @@ typedef bool(*dbll_init_fxn) (void);
 typedef int(*dbll_load_fxn) (struct dbll_library_obj *lib,
 				    dbll_flags flags,
 				    struct dbll_attrs *attrs, u32 *entry);
-
-/*
- *  ======== dbll_load_sect ========
- *  Load a named section from an library (for overlay support).
- *  Parameters:
- *      lib             - Handle returned from dbll_open().
- *      sec_name        - Name of section to load.
- *      attrs           - Contains write function and handle to pass to it.
- *  Returns:
- *      0:        Success.
- *      -ENXIO:    Section not found.
- *      -ENOSYS:   Function not implemented.
- *  Requires:
- *      Valid lib.
- *      sec_name != NULL.
- *      attrs != NULL.
- *      attrs->write != NULL.
- *  Ensures:
- */
-typedef int(*dbll_load_sect_fxn) (struct dbll_library_obj *lib,
-					 char *sz_sect_name,
-					 struct dbll_attrs *attrs);
-
 /*
  *  ======== dbll_open ========
  *  dbll_open() returns a library handle that can be used to load/unload
@@ -421,23 +398,6 @@ typedef int(*dbll_open_fxn) (struct dbll_tar_obj *target, char *file,
 typedef int(*dbll_read_sect_fxn) (struct dbll_library_obj *lib,
 					 char *name, char *content,
 					 u32 cont_size);
-
-/*
- *  ======== dbll_set_attrs ========
- *  Set the attributes of the target.
- *  Parameters:
- *      target          - Handle returned from dbll_create().
- *      pattrs          - New attributes.
- *  Returns:
- *  Requires:
- *      DBL initialized.
- *      Valid target.
- *      pattrs != NULL.
- *  Ensures:
- */
-typedef void (*dbll_set_attrs_fxn) (struct dbll_tar_obj *target,
-				    struct dbll_attrs *attrs);
-
 /*
  *  ======== dbll_unload ========
  *  Unload library loaded with dbll_load().
@@ -452,28 +412,6 @@ typedef void (*dbll_set_attrs_fxn) (struct dbll_tar_obj *target,
  */
 typedef void (*dbll_unload_fxn) (struct dbll_library_obj *library,
 				 struct dbll_attrs *attrs);
-
-/*
- *  ======== dbll_unload_sect ========
- *  Unload a named section from an library (for overlay support).
- *  Parameters:
- *      lib             - Handle returned from dbll_open().
- *      sec_name        - Name of section to load.
- *      attrs           - Contains free() function and handle to pass to it.
- *  Returns:
- *      0:        Success.
- *      -ENXIO:    Named section not found.
- *      -ENOSYS
- *  Requires:
- *      DBL initialized.
- *      Valid lib.
- *      sec_name != NULL.
- *  Ensures:
- */
-typedef int(*dbll_unload_sect_fxn) (struct dbll_library_obj *lib,
-					   char *sz_sect_name,
-					   struct dbll_attrs *attrs);
-
 struct dbll_fxns {
 	dbll_close_fxn close_fxn;
 	dbll_create_fxn create_fxn;
@@ -485,12 +423,9 @@ struct dbll_fxns {
 	dbll_get_sect_fxn get_sect_fxn;
 	dbll_init_fxn init_fxn;
 	dbll_load_fxn load_fxn;
-	dbll_load_sect_fxn load_sect_fxn;
 	dbll_open_fxn open_fxn;
 	dbll_read_sect_fxn read_sect_fxn;
-	dbll_set_attrs_fxn set_attrs_fxn;
 	dbll_unload_fxn unload_fxn;
-	dbll_unload_sect_fxn unload_sect_fxn;
 };
 
 #endif /* DBLDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dehdefs.h b/drivers/staging/tidspbridge/include/dspbridge/dehdefs.h
deleted file mode 100644
index 09f8bf8..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/dehdefs.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * dehdefs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Definition for Bridge driver module DEH.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef DEHDEFS_
-#define DEHDEFS_
-
-#include <dspbridge/mbx_sh.h>	/* shared mailbox codes */
-
-/* DEH object manager */
-struct deh_mgr;
-
-/* Magic code used to determine if DSP signaled exception. */
-#define DEH_BASE        MBX_DEH_BASE
-#define DEH_USERS_BASE  MBX_DEH_USERS_BASE
-#define DEH_LIMIT       MBX_DEH_LIMIT
-
-#endif /* _DEHDEFS_H */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dev.h b/drivers/staging/tidspbridge/include/dspbridge/dev.h
index 357458f..f41e478 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dev.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dev.h
@@ -23,9 +23,9 @@
 #include <dspbridge/chnldefs.h>
 #include <dspbridge/cmm.h>
 #include <dspbridge/cod.h>
-#include <dspbridge/dehdefs.h>
+#include <dspbridge/dspdeh.h>
 #include <dspbridge/nodedefs.h>
-#include <dspbridge/dispdefs.h>
+#include <dspbridge/disp.h>
 #include <dspbridge/dspdefs.h>
 #include <dspbridge/dmm.h>
 #include <dspbridge/host_os.h>
@@ -95,43 +95,6 @@ extern int dev_create_device(struct dev_object
 				    struct cfg_devnode *dev_node_obj);
 
 /*
- *  ======== dev_create_iva_device ========
- *  Purpose:
- *      Called by the operating system to load the Bridge Driver for IVA.
- *  Parameters:
- *      device_obj:     Ptr to location to receive the device object handle.
- *      driver_file_name: Name of Bridge driver PE DLL file to load.  If the
- *                      absolute path is not provided, the file is loaded
- *                      through 'Bridge's module search path.
- *      host_config:    Host configuration information, to be passed down
- *                      to the Bridge driver when bridge_dev_create() is called.
- *      pDspConfig:     DSP resources, to be passed down to the Bridge driver
- *                      when bridge_dev_create() is called.
- *      dev_node_obj:       Platform specific device node.
- *  Returns:
- *      0:            Module is loaded, device object has been created
- *      -ENOMEM:        Insufficient memory to create needed resources.
- *      -EPERM:              Unable to find Bridge driver entry point function.
- *      -ESPIPE:   Unable to load ZL DLL.
- *  Requires:
- *      DEV Initialized.
- *      device_obj != NULL.
- *      driver_file_name != NULL.
- *      host_config != NULL.
- *      pDspConfig != NULL.
- *  Ensures:
- *      0:  *device_obj will contain handle to the new device object.
- *      Otherwise, does not create the device object, ensures the Bridge driver
- *      module is unloaded, and sets *device_obj to NULL.
- */
-extern int dev_create_iva_device(struct dev_object
-					**device_obj,
-					const char *driver_file_name,
-					const struct cfg_hostres
-					*host_config,
-					struct cfg_devnode *dev_node_obj);
-
-/*
  *  ======== dev_create2 ========
  *  Purpose:
  *      After successful loading of the image from api_init_complete2
@@ -146,8 +109,8 @@ extern int dev_create_iva_device(struct dev_object
  *      DEV Initialized
  *      Valid hdev_obj
  *  Ensures:
- *      0 and hdev_obj->hnode_mgr != NULL
- *      else    hdev_obj->hnode_mgr == NULL
+ *      0 and hdev_obj->node_mgr != NULL
+ *      else    hdev_obj->node_mgr == NULL
  */
 extern int dev_create2(struct dev_object *hdev_obj);
 
@@ -164,7 +127,7 @@ extern int dev_create2(struct dev_object *hdev_obj);
  *      DEV Initialized
  *      Valid hdev_obj
  *  Ensures:
- *      0 and hdev_obj->hnode_mgr == NULL
+ *      0 and hdev_obj->node_mgr == NULL
  *      else    -EPERM.
  */
 extern int dev_destroy2(struct dev_object *hdev_obj);
@@ -542,24 +505,6 @@ extern void dev_exit(void);
 extern bool dev_init(void);
 
 /*
- *  ======== dev_is_locked ========
- *  Purpose:
- *      Predicate function to determine if the device has been
- *      locked by a client for exclusive access.
- *  Parameters:
- *      hdev_obj:     Handle to device object created with
- *                      dev_create_device().
- *  Returns:
- *      0:        TRUE: device has been locked.
- *      0:     FALSE: device not locked.
- *      -EFAULT:    hdev_obj was invalid.
- *  Requires:
- *      DEV Initialized.
- *  Ensures:
- */
-extern int dev_is_locked(struct dev_object *hdev_obj);
-
-/*
  *  ======== dev_insert_proc_object ========
  *  Purpose:
  *      Inserts the Processor Object into the List of PROC Objects
diff --git a/drivers/staging/tidspbridge/include/dspbridge/disp.h b/drivers/staging/tidspbridge/include/dspbridge/disp.h
index 82bf721..5dfdc8c 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/disp.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/disp.h
@@ -22,7 +22,20 @@
 #include <dspbridge/dbdefs.h>
 #include <dspbridge/nodedefs.h>
 #include <dspbridge/nodepriv.h>
-#include <dspbridge/dispdefs.h>
+
+struct disp_object;
+
+/* Node Dispatcher attributes */
+struct disp_attr {
+	u32 chnl_offset;	/* Offset of channel ids reserved for RMS */
+	/* Size of buffer for sending data to RMS */
+	u32 chnl_buf_size;
+	int proc_family;	/* eg, 5000 */
+	int proc_type;		/* eg, 5510 */
+	void *reserved1;	/* Reserved for future use. */
+	u32 reserved2;		/* Reserved for future use. */
+};
+
 
 /*
  *  ======== disp_create ========
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dispdefs.h b/drivers/staging/tidspbridge/include/dspbridge/dispdefs.h
deleted file mode 100644
index 946551a..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/dispdefs.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * dispdefs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Global DISP constants and types, shared by PROCESSOR, NODE, and DISP.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef DISPDEFS_
-#define DISPDEFS_
-
-struct disp_object;
-
-/* Node Dispatcher attributes */
-struct disp_attr {
-	u32 ul_chnl_offset;	/* Offset of channel ids reserved for RMS */
-	/* Size of buffer for sending data to RMS */
-	u32 ul_chnl_buf_size;
-	int proc_family;	/* eg, 5000 */
-	int proc_type;		/* eg, 5510 */
-	void *reserved1;	/* Reserved for future use. */
-	u32 reserved2;		/* Reserved for future use. */
-};
-
-#endif /* DISPDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/drv.h b/drivers/staging/tidspbridge/include/dspbridge/drv.h
index c1f363e..25ef1a2 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/drv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/drv.h
@@ -23,11 +23,10 @@
 
 #include <dspbridge/devdefs.h>
 
-#include <dspbridge/drvdefs.h>
 #include <linux/idr.h>
 
-#define DRV_ASSIGN     1
-#define DRV_RELEASE    0
+/* Bridge Driver Object */
+struct drv_object;
 
 /* Provide the DSP Internal memory windows that can be accessed from L3 address
  * space */
@@ -38,23 +37,14 @@
 /* MEM1 is L2 RAM + L2 Cache space */
 #define OMAP_DSP_MEM1_BASE 0x5C7F8000
 #define OMAP_DSP_MEM1_SIZE 0x18000
-#define OMAP_DSP_GEM1_BASE 0x107F8000
 
 /* MEM2 is L1P RAM/CACHE space */
 #define OMAP_DSP_MEM2_BASE 0x5CE00000
 #define OMAP_DSP_MEM2_SIZE 0x8000
-#define OMAP_DSP_GEM2_BASE 0x10E00000
 
 /* MEM3 is L1D RAM/CACHE space */
 #define OMAP_DSP_MEM3_BASE 0x5CF04000
 #define OMAP_DSP_MEM3_SIZE 0x14000
-#define OMAP_DSP_GEM3_BASE 0x10F04000
-
-#define OMAP_IVA2_PRM_BASE 0x48306000
-#define OMAP_IVA2_PRM_SIZE 0x1000
-
-#define OMAP_IVA2_CM_BASE 0x48004000
-#define OMAP_IVA2_CM_SIZE 0x1000
 
 #define OMAP_PER_CM_BASE 0x48005000
 #define OMAP_PER_CM_SIZE 0x1000
@@ -65,20 +55,14 @@
 #define OMAP_CORE_PRM_BASE 0x48306A00
 #define OMAP_CORE_PRM_SIZE 0x1000
 
-#define OMAP_SYSC_BASE 0x48002000
-#define OMAP_SYSC_SIZE 0x1000
-
 #define OMAP_DMMU_BASE 0x5D000000
 #define OMAP_DMMU_SIZE 0x1000
 
-#define OMAP_PRCM_VDD1_DOMAIN 1
-#define OMAP_PRCM_VDD2_DOMAIN 2
-
 /* GPP PROCESS CLEANUP Data structures */
 
 /* New structure (member of process context) abstracts NODE resource info */
 struct node_res_object {
-	void *hnode;
+	void *node;
 	s32 node_allocated;	/* Node status */
 	s32 heap_allocated;	/* Heap status */
 	s32 streams_allocated;	/* Streams status */
@@ -114,21 +98,10 @@ struct dmm_rsv_object {
 	u32 dsp_reserved_addr;
 };
 
-/* New structure (member of process context) abstracts DMM resource info */
-struct dspheap_res_object {
-	s32 heap_allocated;	/* DMM status */
-	u32 ul_mpu_addr;
-	u32 ul_dsp_addr;
-	u32 ul_dsp_res_addr;
-	u32 heap_size;
-	void *hprocessor;
-	struct dspheap_res_object *next;
-};
-
 /* New structure (member of process context) abstracts stream resource info */
 struct strm_res_object {
 	s32 stream_allocated;	/* Stream status */
-	void *hstream;
+	void *stream;
 	u32 num_bufs;
 	u32 dir;
 	int id;
@@ -156,7 +129,7 @@ struct process_context {
 	enum gpp_proc_res_state res_state;
 
 	/* Handle to Processor */
-	void *hprocessor;
+	void *processor;
 
 	/* DSP Node resources */
 	struct idr *node_id;
@@ -169,9 +142,6 @@ struct process_context {
 	struct list_head dmm_rsv_list;
 	spinlock_t dmm_rsv_lock;
 
-	/* DSP Heap resources */
-	struct dspheap_res_object *pdspheap_list;
-
 	/* Stream resources */
 	struct idr *stream_id;
 };
@@ -425,7 +395,7 @@ void bridge_recover_schedule(void);
 /*
  *  ======== mem_ext_phys_pool_init ========
  *  Purpose:
- *      Uses the physical memory chunk passed for internal consitent memory
+ *      Uses the physical memory chunk passed for internal consistent memory
  *      allocations.
  *      physical address based on the page frame address.
  *  Parameters:
diff --git a/drivers/staging/tidspbridge/include/dspbridge/drvdefs.h b/drivers/staging/tidspbridge/include/dspbridge/drvdefs.h
deleted file mode 100644
index 2920917..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/drvdefs.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * drvdefs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Definition of common struct between dspdefs.h and drv.h.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef DRVDEFS_
-#define DRVDEFS_
-
-/* Bridge Driver Object */
-struct drv_object;
-
-#endif /* DRVDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspapi-ioctl.h b/drivers/staging/tidspbridge/include/dspbridge/dspapi-ioctl.h
index 8da5bd8..6ff8082 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dspapi-ioctl.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dspapi-ioctl.h
@@ -29,22 +29,22 @@ union trapped_args {
 	/* MGR Module */
 	struct {
 		u32 node_id;
-		struct dsp_ndbprops __user *pndb_props;
-		u32 undb_props_size;
-		u32 __user *pu_num_nodes;
+		struct dsp_ndbprops __user *ndb_props;
+		u32 ndb_props_size;
+		u32 __user *num_nodes;
 	} args_mgr_enumnode_info;
 
 	struct {
 		u32 processor_id;
 		struct dsp_processorinfo __user *processor_info;
 		u32 processor_info_size;
-		u32 __user *pu_num_procs;
+		u32 __user *num_procs;
 	} args_mgr_enumproc_info;
 
 	struct {
 		struct dsp_uuid *uuid_obj;
 		enum dsp_dcdobjtype obj_type;
-		char *psz_path_name;
+		char *sz_path_name;
 	} args_mgr_registerobject;
 
 	struct {
@@ -55,8 +55,8 @@ union trapped_args {
 	struct {
 		struct dsp_notification __user *__user *anotifications;
 		u32 count;
-		u32 __user *pu_index;
-		u32 utimeout;
+		u32 __user *index;
+		u32 timeout;
 	} args_mgr_wait;
 
 	/* PROC Module */
@@ -67,196 +67,188 @@ union trapped_args {
 	} args_proc_attach;
 
 	struct {
-		void *hprocessor;
-		u32 dw_cmd;
-		struct dsp_cbdata __user *pargs;
+		void *processor;
+		u32 cmd;
+		struct dsp_cbdata __user *args;
 	} args_proc_ctrl;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 	} args_proc_detach;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 		void *__user *node_tab;
 		u32 node_tab_size;
-		u32 __user *pu_num_nodes;
-		u32 __user *pu_allocated;
+		u32 __user *num_nodes;
+		u32 __user *allocated;
 	} args_proc_enumnode_info;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 		u32 resource_type;
 		struct dsp_resourceinfo *resource_info;
 		u32 resource_info_size;
 	} args_proc_enumresources;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 		struct dsp_processorstate __user *proc_state_obj;
 		u32 state_info_size;
 	} args_proc_getstate;
 
 	struct {
-		void *hprocessor;
-		u8 __user *pbuf;
-		u8 __user *psize;
+		void *processor;
+		u8 __user *buf;
+		u8 __user *size;
 		u32 max_size;
 	} args_proc_gettrace;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 		s32 argc_index;
 		char __user *__user *user_args;
 		char *__user *user_envp;
 	} args_proc_load;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 		u32 event_mask;
 		u32 notify_type;
-		struct dsp_notification __user *hnotification;
+		struct dsp_notification __user *notification;
 	} args_proc_register_notify;
 
 	struct {
-		void *hprocessor;
-	} args_proc_start;
-
-	struct {
-		void *hprocessor;
-		u32 ul_size;
-		void *__user *pp_rsv_addr;
+		void *processor;
+		u32 size;
+		void *__user *rsv_addr;
 	} args_proc_rsvmem;
 
 	struct {
-		void *hprocessor;
-		u32 ul_size;
-		void *prsv_addr;
+		void *processor;
+		u32 size;
+		void *rsv_addr;
 	} args_proc_unrsvmem;
 
 	struct {
-		void *hprocessor;
-		void *pmpu_addr;
-		u32 ul_size;
+		void *processor;
+		void *mpu_addr;
+		u32 size;
 		void *req_addr;
-		void *__user *pp_map_addr;
-		u32 ul_map_attr;
+		void *__user *map_addr;
+		u32 map_attr;
 	} args_proc_mapmem;
 
 	struct {
-		void *hprocessor;
-		u32 ul_size;
+		void *processor;
+		u32 size;
 		void *map_addr;
 	} args_proc_unmapmem;
 
 	struct {
-		void *hprocessor;
-		void *pmpu_addr;
-		u32 ul_size;
+		void *processor;
+		void *mpu_addr;
+		u32 size;
 		u32 dir;
 	} args_proc_dma;
 
 	struct {
-		void *hprocessor;
-		void *pmpu_addr;
-		u32 ul_size;
-		u32 ul_flags;
+		void *processor;
+		void *mpu_addr;
+		u32 size;
+		u32 flags;
 	} args_proc_flushmemory;
 
 	struct {
-		void *hprocessor;
-	} args_proc_stop;
-
-	struct {
-		void *hprocessor;
-		void *pmpu_addr;
-		u32 ul_size;
+		void *processor;
+		void *mpu_addr;
+		u32 size;
 	} args_proc_invalidatememory;
 
 	/* NODE Module */
 	struct {
-		void *hprocessor;
+		void *processor;
 		struct dsp_uuid __user *node_id_ptr;
-		struct dsp_cbdata __user *pargs;
+		struct dsp_cbdata __user *args;
 		struct dsp_nodeattrin __user *attr_in;
-		void *__user *ph_node;
+		void *__user *node;
 	} args_node_allocate;
 
 	struct {
-		void *hnode;
-		u32 usize;
-		struct dsp_bufferattr __user *pattr;
-		u8 *__user *pbuffer;
+		void *node;
+		u32 size;
+		struct dsp_bufferattr __user *attr;
+		u8 *__user *buffer;
 	} args_node_allocmsgbuf;
 
 	struct {
-		void *hnode;
+		void *node;
 		s32 prio;
 	} args_node_changepriority;
 
 	struct {
-		void *hnode;
+		void *node;
 		u32 stream_id;
 		void *other_node;
 		u32 other_stream;
-		struct dsp_strmattr __user *pattrs;
+		struct dsp_strmattr __user *attrs;
 		struct dsp_cbdata __user *conn_param;
 	} args_node_connect;
 
 	struct {
-		void *hnode;
+		void *node;
 	} args_node_create;
 
 	struct {
-		void *hnode;
+		void *node;
 	} args_node_delete;
 
 	struct {
-		void *hnode;
-		struct dsp_bufferattr __user *pattr;
-		u8 *pbuffer;
+		void *node;
+		struct dsp_bufferattr __user *attr;
+		u8 *buffer;
 	} args_node_freemsgbuf;
 
 	struct {
-		void *hnode;
-		struct dsp_nodeattr __user *pattr;
+		void *node;
+		struct dsp_nodeattr __user *attr;
 		u32 attr_size;
 	} args_node_getattr;
 
 	struct {
-		void *hnode;
+		void *node;
 		struct dsp_msg __user *message;
-		u32 utimeout;
+		u32 timeout;
 	} args_node_getmessage;
 
 	struct {
-		void *hnode;
+		void *node;
 	} args_node_pause;
 
 	struct {
-		void *hnode;
+		void *node;
 		struct dsp_msg __user *message;
-		u32 utimeout;
+		u32 timeout;
 	} args_node_putmessage;
 
 	struct {
-		void *hnode;
+		void *node;
 		u32 event_mask;
 		u32 notify_type;
-		struct dsp_notification __user *hnotification;
+		struct dsp_notification __user *notification;
 	} args_node_registernotify;
 
 	struct {
-		void *hnode;
+		void *node;
 	} args_node_run;
 
 	struct {
-		void *hnode;
-		int __user *pstatus;
+		void *node;
+		int __user *status;
 	} args_node_terminate;
 
 	struct {
-		void *hprocessor;
+		void *processor;
 		struct dsp_uuid __user *node_id_ptr;
 		struct dsp_ndbprops __user *node_props;
 	} args_node_getuuidprops;
@@ -264,104 +256,104 @@ union trapped_args {
 	/* STRM module */
 
 	struct {
-		void *hstream;
-		u32 usize;
+		void *stream;
+		u32 size;
 		u8 *__user *ap_buffer;
 		u32 num_bufs;
 	} args_strm_allocatebuffer;
 
 	struct {
-		void *hstream;
+		void *stream;
 	} args_strm_close;
 
 	struct {
-		void *hstream;
+		void *stream;
 		u8 *__user *ap_buffer;
 		u32 num_bufs;
 	} args_strm_freebuffer;
 
 	struct {
-		void *hstream;
-		void **ph_event;
+		void *stream;
+		void **event;
 	} args_strm_geteventhandle;
 
 	struct {
-		void *hstream;
+		void *stream;
 		struct stream_info __user *stream_info;
 		u32 stream_info_size;
 	} args_strm_getinfo;
 
 	struct {
-		void *hstream;
+		void *stream;
 		bool flush_flag;
 	} args_strm_idle;
 
 	struct {
-		void *hstream;
-		u8 *pbuffer;
-		u32 dw_bytes;
-		u32 dw_buf_size;
-		u32 dw_arg;
+		void *stream;
+		u8 *buffer;
+		u32 bytes;
+		u32 buf_size;
+		u32 arg;
 	} args_strm_issue;
 
 	struct {
-		void *hnode;
+		void *node;
 		u32 direction;
 		u32 index;
 		struct strm_attr __user *attr_in;
-		void *__user *ph_stream;
+		void *__user *stream;
 	} args_strm_open;
 
 	struct {
-		void *hstream;
+		void *stream;
 		u8 *__user *buf_ptr;
 		u32 __user *bytes;
 		u32 __user *buf_size_ptr;
-		u32 __user *pdw_arg;
+		u32 __user *arg;
 	} args_strm_reclaim;
 
 	struct {
-		void *hstream;
+		void *stream;
 		u32 event_mask;
 		u32 notify_type;
-		struct dsp_notification __user *hnotification;
+		struct dsp_notification __user *notification;
 	} args_strm_registernotify;
 
 	struct {
 		void *__user *stream_tab;
 		u32 strm_num;
-		u32 __user *pmask;
-		u32 utimeout;
+		u32 __user *mask;
+		u32 timeout;
 	} args_strm_select;
 
 	/* CMM Module */
 	struct {
-		struct cmm_object *hcmm_mgr;
-		u32 usize;
-		struct cmm_attrs *pattrs;
-		void **pp_buf_va;
+		struct cmm_object *cmm_mgr;
+		u32 size;
+		struct cmm_attrs *attrs;
+		void **buf_va;
 	} args_cmm_allocbuf;
 
 	struct {
-		struct cmm_object *hcmm_mgr;
+		struct cmm_object *cmm_mgr;
 		void *buf_pa;
-		u32 ul_seg_id;
+		u32 seg_id;
 	} args_cmm_freebuf;
 
 	struct {
-		void *hprocessor;
-		struct cmm_object *__user *ph_cmm_mgr;
+		void *processor;
+		struct cmm_object *__user *cmm_mgr;
 	} args_cmm_gethandle;
 
 	struct {
-		struct cmm_object *hcmm_mgr;
+		struct cmm_object *cmm_mgr;
 		struct cmm_info __user *cmm_info_obj;
 	} args_cmm_getinfo;
 
 	/* UTIL module */
 	struct {
 		s32 util_argc;
-		char **pp_argv;
+		char **argv;
 	} args_util_testdll;
 };
 
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h b/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
index 0ae7d16..c2ba26c 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dspdefs.h
@@ -32,17 +32,11 @@
 #include <dspbridge/brddefs.h>
 #include <dspbridge/cfgdefs.h>
 #include <dspbridge/chnlpriv.h>
-#include <dspbridge/dehdefs.h>
+#include <dspbridge/dspdeh.h>
 #include <dspbridge/devdefs.h>
-#include <dspbridge/iodefs.h>
+#include <dspbridge/io.h>
 #include <dspbridge/msgdefs.h>
 
-/*
- *  Any IOCTLS at or above this value are reserved for standard Bridge driver
- *  interfaces.
- */
-#define BRD_RESERVEDIOCTLBASE   0x8000
-
 /* Handle to Bridge driver's private device context. */
 struct bridge_dev_context;
 
@@ -306,7 +300,7 @@ typedef int(*fxn_brd_write) (struct bridge_dev_context *dev_ctxt,
  *      mgr_attrts->irq_shared:   TRUE if the IRQ is shareable.
  *      mgr_attrts->word_size: DSP Word size in equivalent PC bytes..
  *      mgr_attrts->shm_base:  Base physical address of shared memory, if any.
- *      mgr_attrts->usm_length: Bytes of shared memory block.
+ *      mgr_attrts->sm_length: Bytes of shared memory block.
  *  Returns:
  *      0:            Success;
  *      -ENOMEM:        Insufficient memory for requested resources.
@@ -981,51 +975,51 @@ typedef void (*fxn_msg_setqueueid) (struct msg_queue *msg_queue_obj,
 struct bridge_drv_interface {
 	u32 brd_api_major_version;	/* Set to BRD_API_MAJOR_VERSION. */
 	u32 brd_api_minor_version;	/* Set to BRD_API_MINOR_VERSION. */
-	fxn_dev_create pfn_dev_create;	/* Create device context */
-	fxn_dev_destroy pfn_dev_destroy;	/* Destroy device context */
-	fxn_dev_ctrl pfn_dev_cntrl;	/* Optional vendor interface */
-	fxn_brd_monitor pfn_brd_monitor;	/* Load and/or start monitor */
-	fxn_brd_start pfn_brd_start;	/* Start DSP program. */
-	fxn_brd_stop pfn_brd_stop;	/* Stop/reset board. */
-	fxn_brd_status pfn_brd_status;	/* Get current board status. */
-	fxn_brd_read pfn_brd_read;	/* Read board memory */
-	fxn_brd_write pfn_brd_write;	/* Write board memory. */
-	fxn_brd_setstate pfn_brd_set_state;	/* Sets the Board State */
-	fxn_brd_memcopy pfn_brd_mem_copy;	/* Copies DSP Memory */
-	fxn_brd_memwrite pfn_brd_mem_write;	/* Write DSP Memory w/o halt */
-	fxn_brd_memmap pfn_brd_mem_map;	/* Maps MPU mem to DSP mem */
-	fxn_brd_memunmap pfn_brd_mem_un_map;	/* Unmaps MPU mem to DSP mem */
-	fxn_chnl_create pfn_chnl_create;	/* Create channel manager. */
-	fxn_chnl_destroy pfn_chnl_destroy;	/* Destroy channel manager. */
-	fxn_chnl_open pfn_chnl_open;	/* Create a new channel. */
-	fxn_chnl_close pfn_chnl_close;	/* Close a channel. */
-	fxn_chnl_addioreq pfn_chnl_add_io_req;	/* Req I/O on a channel. */
-	fxn_chnl_getioc pfn_chnl_get_ioc;	/* Wait for I/O completion. */
-	fxn_chnl_cancelio pfn_chnl_cancel_io;	/* Cancl I/O on a channel. */
-	fxn_chnl_flushio pfn_chnl_flush_io;	/* Flush I/O. */
-	fxn_chnl_getinfo pfn_chnl_get_info;	/* Get channel specific info */
+	fxn_dev_create dev_create;	/* Create device context */
+	fxn_dev_destroy dev_destroy;	/* Destroy device context */
+	fxn_dev_ctrl dev_cntrl;	/* Optional vendor interface */
+	fxn_brd_monitor brd_monitor;	/* Load and/or start monitor */
+	fxn_brd_start brd_start;	/* Start DSP program. */
+	fxn_brd_stop brd_stop;	/* Stop/reset board. */
+	fxn_brd_status brd_status;	/* Get current board status. */
+	fxn_brd_read brd_read;	/* Read board memory */
+	fxn_brd_write brd_write;	/* Write board memory. */
+	fxn_brd_setstate brd_set_state;	/* Sets the Board State */
+	fxn_brd_memcopy brd_mem_copy;	/* Copies DSP Memory */
+	fxn_brd_memwrite brd_mem_write;	/* Write DSP Memory w/o halt */
+	fxn_brd_memmap brd_mem_map;	/* Maps MPU mem to DSP mem */
+	fxn_brd_memunmap brd_mem_un_map;	/* Unmaps MPU mem to DSP mem */
+	fxn_chnl_create chnl_create;	/* Create channel manager. */
+	fxn_chnl_destroy chnl_destroy;	/* Destroy channel manager. */
+	fxn_chnl_open chnl_open;	/* Create a new channel. */
+	fxn_chnl_close chnl_close;	/* Close a channel. */
+	fxn_chnl_addioreq chnl_add_io_req;	/* Req I/O on a channel. */
+	fxn_chnl_getioc chnl_get_ioc;	/* Wait for I/O completion. */
+	fxn_chnl_cancelio chnl_cancel_io;	/* Cancl I/O on a channel. */
+	fxn_chnl_flushio chnl_flush_io;	/* Flush I/O. */
+	fxn_chnl_getinfo chnl_get_info;	/* Get channel specific info */
 	/* Get channel manager info. */
-	fxn_chnl_getmgrinfo pfn_chnl_get_mgr_info;
-	fxn_chnl_idle pfn_chnl_idle;	/* Idle the channel */
+	fxn_chnl_getmgrinfo chnl_get_mgr_info;
+	fxn_chnl_idle chnl_idle;	/* Idle the channel */
 	/* Register for notif. */
-	fxn_chnl_registernotify pfn_chnl_register_notify;
-	fxn_io_create pfn_io_create;	/* Create IO manager */
-	fxn_io_destroy pfn_io_destroy;	/* Destroy IO manager */
-	fxn_io_onloaded pfn_io_on_loaded;	/* Notify of program loaded */
+	fxn_chnl_registernotify chnl_register_notify;
+	fxn_io_create io_create;	/* Create IO manager */
+	fxn_io_destroy io_destroy;	/* Destroy IO manager */
+	fxn_io_onloaded io_on_loaded;	/* Notify of program loaded */
 	/* Get Processor's current and predicted load */
-	fxn_io_getprocload pfn_io_get_proc_load;
-	fxn_msg_create pfn_msg_create;	/* Create message manager */
+	fxn_io_getprocload io_get_proc_load;
+	fxn_msg_create msg_create;	/* Create message manager */
 	/* Create message queue */
-	fxn_msg_createqueue pfn_msg_create_queue;
-	fxn_msg_delete pfn_msg_delete;	/* Delete message manager */
+	fxn_msg_createqueue msg_create_queue;
+	fxn_msg_delete msg_delete;	/* Delete message manager */
 	/* Delete message queue */
-	fxn_msg_deletequeue pfn_msg_delete_queue;
-	fxn_msg_get pfn_msg_get;	/* Get a message */
-	fxn_msg_put pfn_msg_put;	/* Send a message */
+	fxn_msg_deletequeue msg_delete_queue;
+	fxn_msg_get msg_get;	/* Get a message */
+	fxn_msg_put msg_put;	/* Send a message */
 	/* Register for notif. */
-	fxn_msg_registernotify pfn_msg_register_notify;
+	fxn_msg_registernotify msg_register_notify;
 	/* Set message queue id */
-	fxn_msg_setqueueid pfn_msg_set_queue_id;
+	fxn_msg_setqueueid msg_set_queue_id;
 };
 
 /*
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspdrv.h b/drivers/staging/tidspbridge/include/dspbridge/dspdrv.h
index 0bb250f..7adf1e7 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dspdrv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dspdrv.h
@@ -20,8 +20,6 @@
 #if !defined _DSPDRV_H_
 #define _DSPDRV_H_
 
-#define MAX_DEV     10		/* Max support of 10 devices */
-
 /*
  *  ======== dsp_deinit ========
  *  Purpose:
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspio.h b/drivers/staging/tidspbridge/include/dspbridge/dspio.h
index 88f5f90..66b64fa 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dspio.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dspio.h
@@ -24,7 +24,8 @@
 #define DSPIO_
 
 #include <dspbridge/devdefs.h>
-#include <dspbridge/iodefs.h>
+#include <dspbridge/io.h>
+
 
 extern int bridge_io_create(struct io_mgr **io_man,
 				   struct dev_object *hdev_obj,
@@ -34,7 +35,6 @@ extern int bridge_io_destroy(struct io_mgr *hio_mgr);
 
 extern int bridge_io_on_loaded(struct io_mgr *hio_mgr);
 
-extern int iva_io_on_loaded(struct io_mgr *hio_mgr);
 extern int bridge_io_get_proc_load(struct io_mgr *hio_mgr,
 				       struct dsp_procloadstat *proc_lstat);
 
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h b/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h
index 41e0594..0c7ec04 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dspioctl.h
@@ -31,9 +31,6 @@
 
 #define BRDIOCTL_CHNLREAD           (BRDIOCTL_RESERVEDBASE + 0x10)
 #define BRDIOCTL_CHNLWRITE          (BRDIOCTL_RESERVEDBASE + 0x20)
-#define BRDIOCTL_GETINTRCOUNT       (BRDIOCTL_RESERVEDBASE + 0x30)
-#define BRDIOCTL_RESETINTRCOUNT     (BRDIOCTL_RESERVEDBASE + 0x40)
-#define BRDIOCTL_INTERRUPTDSP       (BRDIOCTL_RESERVEDBASE + 0x50)
 /* DMMU */
 #define BRDIOCTL_SETMMUCONFIG       (BRDIOCTL_RESERVEDBASE + 0x60)
 /* PWR */
@@ -47,8 +44,6 @@
 #define BRDIOCTL_DEEPSLEEP          (BRDIOCTL_PWRCONTROL + 0x0)
 #define BRDIOCTL_EMERGENCYSLEEP     (BRDIOCTL_PWRCONTROL + 0x1)
 #define BRDIOCTL_WAKEUP             (BRDIOCTL_PWRCONTROL + 0x2)
-#define BRDIOCTL_PWRENABLE          (BRDIOCTL_PWRCONTROL + 0x3)
-#define BRDIOCTL_PWRDISABLE         (BRDIOCTL_PWRCONTROL + 0x4)
 #define BRDIOCTL_CLK_CTRL		    (BRDIOCTL_PWRCONTROL + 0x7)
 /* DSP Initiated Hibernate */
 #define BRDIOCTL_PWR_HIBERNATE	(BRDIOCTL_PWRCONTROL + 0x8)
@@ -60,11 +55,11 @@
 #define BRDIOCTL_NUMOFMMUTLB        32
 
 struct bridge_ioctl_extproc {
-	u32 ul_dsp_va;		/* DSP virtual address */
-	u32 ul_gpp_pa;		/* GPP physical address */
+	u32 dsp_va;		/* DSP virtual address */
+	u32 gpp_pa;		/* GPP physical address */
 	/* GPP virtual address. __va does not work for ioremapped addresses */
-	u32 ul_gpp_va;
-	u32 ul_size;		/* Size of the mapped memory in bytes */
+	u32 gpp_va;
+	u32 size;		/* Size of the mapped memory in bytes */
 	enum hw_endianism_t endianism;
 	enum hw_mmu_mixed_size_t mixed_mode;
 	enum hw_element_size_t elem_size;
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dynamic_loader.h b/drivers/staging/tidspbridge/include/dspbridge/dynamic_loader.h
index 4b109d1..052d27e 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dynamic_loader.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dynamic_loader.h
@@ -46,8 +46,6 @@ struct dynamic_loader_initialize;
  * Option flags to modify the behavior of module loading
  */
 #define DLOAD_INITBSS 0x1	/* initialize BSS sections to zero */
-#define DLOAD_BIGEND 0x2	/* require big-endian load module */
-#define DLOAD_LITTLE 0x4	/* require little-endian load module */
 
 /*****************************************************************************
  * Procedure dynamic_load_module
diff --git a/drivers/staging/tidspbridge/include/dspbridge/gb.h b/drivers/staging/tidspbridge/include/dspbridge/gb.h
deleted file mode 100644
index fda783a..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/gb.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * gb.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Generic bitmap manager.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef GB_
-#define GB_
-
-#define GB_NOBITS (~0)
-#include <dspbridge/host_os.h>
-
-struct gb_t_map;
-
-/*
- *  ======== gb_clear ========
- *  Clear the bit in position bitn in the bitmap map.  Bit positions are
- *  zero based.
- */
-
-extern void gb_clear(struct gb_t_map *map, u32 bitn);
-
-/*
- *  ======== gb_create ========
- *  Create a bit map with len bits.  Initially all bits are cleared.
- */
-
-extern struct gb_t_map *gb_create(u32 len);
-
-/*
- *  ======== gb_delete ========
- *  Delete previously created bit map
- */
-
-extern void gb_delete(struct gb_t_map *map);
-
-/*
- *  ======== gb_findandset ========
- *  Finds a clear bit, sets it, and returns the position
- */
-
-extern u32 gb_findandset(struct gb_t_map *map);
-
-/*
- *  ======== gb_minclear ========
- *  gb_minclear returns the minimum clear bit position.  If no bit is
- *  clear, gb_minclear returns -1.
- */
-extern u32 gb_minclear(struct gb_t_map *map);
-
-/*
- *  ======== gb_set ========
- *  Set the bit in position bitn in the bitmap map.  Bit positions are
- *  zero based.
- */
-
-extern void gb_set(struct gb_t_map *map, u32 bitn);
-
-/*
- *  ======== gb_test ========
- *  Returns TRUE if the bit in position bitn is set in map; otherwise
- *  gb_test returns FALSE.  Bit positions are zero based.
- */
-
-extern bool gb_test(struct gb_t_map *map, u32 bitn);
-
-#endif /*GB_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/gs.h b/drivers/staging/tidspbridge/include/dspbridge/gs.h
deleted file mode 100644
index f32d8d9..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/gs.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * gs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Memory allocation/release wrappers.  This module allows clients to
- * avoid OS spacific issues related to memory allocation.  It also provides
- * simple diagnostic capabilities to assist in the detection of memory
- * leaks.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef GS_
-#define GS_
-
-/*
- *  ======== gs_alloc ========
- *  Alloc size bytes of space.  Returns pointer to space
- *  allocated, otherwise NULL.
- */
-extern void *gs_alloc(u32 size);
-
-/*
- *  ======== gs_exit ========
- *  Module exit.  Do not change to "#define gs_init()"; in
- *  some environments this operation must actually do some work!
- */
-extern void gs_exit(void);
-
-/*
- *  ======== gs_free ========
- *  Free space allocated by gs_alloc() or GS_calloc().
- */
-extern void gs_free(void *ptr);
-
-/*
- *  ======== gs_frees ========
- *  Free space allocated by gs_alloc() or GS_calloc() and assert that
- *  the size of the allocation is size bytes.
- */
-extern void gs_frees(void *ptr, u32 size);
-
-/*
- *  ======== gs_init ========
- *  Module initialization.  Do not change to "#define gs_init()"; in
- *  some environments this operation must actually do some work!
- */
-extern void gs_init(void);
-
-#endif /*GS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index 6549898..b1b8acb 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -57,13 +57,4 @@
 extern struct platform_device *omap_dspbridge_dev;
 extern struct device *bridge;
 
-#if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE)
-extern void dspbridge_reserve_sdram(void);
-#else
-static inline void dspbridge_reserve_sdram(void)
-{
-}
-#endif
-
-extern unsigned long dspbridge_get_mempool_base(void);
 #endif
diff --git a/drivers/staging/tidspbridge/include/dspbridge/io.h b/drivers/staging/tidspbridge/include/dspbridge/io.h
index bc346f9..500bbd7 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/io.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/io.h
@@ -22,7 +22,18 @@
 #include <dspbridge/cfgdefs.h>
 #include <dspbridge/devdefs.h>
 
-#include <dspbridge/iodefs.h>
+/* IO Objects: */
+struct io_mgr;
+
+/* IO manager attributes: */
+struct io_attrs {
+	u8 birq;		/* Channel's I/O IRQ number. */
+	bool irq_shared;	/* TRUE if the IRQ is shareable. */
+	u32 word_size;		/* DSP Word size. */
+	u32 shm_base;		/* Physical base address of shared memory. */
+	u32 sm_length;		/* Size (in bytes) of shared memory. */
+};
+
 
 /*
  *  ======== io_create ========
@@ -95,20 +106,4 @@ extern void io_exit(void);
  */
 extern bool io_init(void);
 
-/*
- *  ======== io_on_loaded ========
- *  Purpose:
- *      Called when a program is loaded so IO manager can update its
- *      internal state.
- *  Parameters:
- *      hio_mgr:         IOmanager object.
- *  Returns:
- *      0:        Success.
- *      -EFAULT:    hio_mgr was invalid.
- *  Requires:
- *      io_init(void) called.
- *  Ensures:
- */
-extern int io_on_loaded(struct io_mgr *hio_mgr);
-
 #endif /* CHNL_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h
index 8242c70..a054dad 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h
@@ -23,12 +23,16 @@
 #include <dspbridge/_chnl_sm.h>
 #include <dspbridge/host_os.h>
 
-#include <dspbridge/iodefs.h>
+#include <dspbridge/io.h>
+#include <dspbridge/mbx_sh.h>	/* shared mailbox codes */
+
+/* Magic code used to determine if DSP signaled exception. */
+#define DEH_BASE        MBX_DEH_BASE
+#define DEH_LIMIT       MBX_DEH_LIMIT
 
 #define IO_INPUT            0
 #define IO_OUTPUT           1
 #define IO_SERVICE          2
-#define IO_MAXSERVICE       IO_SERVICE
 
 #ifdef CONFIG_TIDSPBRIDGE_DVFS
 /* The maximum number of OPPs that are supported */
@@ -116,122 +120,6 @@ extern void io_request_chnl(struct io_mgr *io_manager,
 extern void iosm_schedule(struct io_mgr *io_manager);
 
 /*
- * DSP-DMA IO functions
- */
-
-/*
- *  ======== io_ddma_init_chnl_desc ========
- *  Purpose:
- *      Initialize DSP DMA channel descriptor.
- *  Parameters:
- *      hio_mgr:         Handle to a I/O manager.
- *      ddma_chnl_id:    DDMA channel identifier.
- *      num_desc:       Number of buffer descriptors(equals # of IOReqs &
- *                      Chirps)
- *      dsp:           Dsp address;
- *  Returns:
- *  Requires:
- *     ddma_chnl_id < DDMA_MAXDDMACHNLS
- *     num_desc > 0
- *     pVa != NULL
- *     pDspPa != NULL
- *
- *  Ensures:
- */
-extern void io_ddma_init_chnl_desc(struct io_mgr *hio_mgr, u32 ddma_chnl_id,
-				   u32 num_desc, void *dsp);
-
-/*
- *  ======== io_ddma_clear_chnl_desc ========
- *  Purpose:
- *      Clear DSP DMA channel descriptor.
- *  Parameters:
- *      hio_mgr:         Handle to a I/O manager.
- *      ddma_chnl_id:    DDMA channel identifier.
- *  Returns:
- *  Requires:
- *     ddma_chnl_id < DDMA_MAXDDMACHNLS
- *  Ensures:
- */
-extern void io_ddma_clear_chnl_desc(struct io_mgr *hio_mgr, u32 ddma_chnl_id);
-
-/*
- *  ======== io_ddma_request_chnl ========
- *  Purpose:
- *      Request channel DSP-DMA from the DSP. Sets up SM descriptors and
- *      control fields in shared memory.
- *  Parameters:
- *      hio_mgr:     Handle to a I/O manager.
- *      pchnl:      Ptr to channel object
- *      chnl_packet_obj:     Ptr to channel i/o request packet.
- *  Returns:
- *  Requires:
- *      pchnl != NULL
- *      pchnl->cio_reqs > 0
- *      chnl_packet_obj != NULL
- *  Ensures:
- */
-extern void io_ddma_request_chnl(struct io_mgr *hio_mgr,
-				 struct chnl_object *pchnl,
-				 struct chnl_irp *chnl_packet_obj,
-				 u16 *mbx_val);
-
-/*
- * Zero-copy IO functions
- */
-
-/*
- *  ======== io_ddzc_init_chnl_desc ========
- *  Purpose:
- *      Initialize ZCPY channel descriptor.
- *  Parameters:
- *      hio_mgr:     Handle to a I/O manager.
- *      zid:        zero-copy channel identifier.
- *  Returns:
- *  Requires:
- *     ddma_chnl_id < DDMA_MAXZCPYCHNLS
- *     hio_mgr != Null
- *  Ensures:
- */
-extern void io_ddzc_init_chnl_desc(struct io_mgr *hio_mgr, u32 zid);
-
-/*
- *  ======== io_ddzc_clear_chnl_desc ========
- *  Purpose:
- *      Clear DSP ZC channel descriptor.
- *  Parameters:
- *      hio_mgr:         Handle to a I/O manager.
- *      ch_id:        ZC channel identifier.
- *  Returns:
- *  Requires:
- *      hio_mgr is valid
- *      ch_id < DDMA_MAXZCPYCHNLS
- *  Ensures:
- */
-extern void io_ddzc_clear_chnl_desc(struct io_mgr *hio_mgr, u32 ch_id);
-
-/*
- *  ======== io_ddzc_request_chnl ========
- *  Purpose:
- *      Request zero-copy channel transfer. Sets up SM descriptors and
- *      control fields in shared memory.
- *  Parameters:
- *      hio_mgr:         Handle to a I/O manager.
- *      pchnl:          Ptr to channel object
- *      chnl_packet_obj:         Ptr to channel i/o request packet.
- *  Returns:
- *  Requires:
- *      pchnl != NULL
- *      pchnl->cio_reqs > 0
- *      chnl_packet_obj != NULL
- *  Ensures:
- */
-extern void io_ddzc_request_chnl(struct io_mgr *hio_mgr,
-				 struct chnl_object *pchnl,
-				 struct chnl_irp *chnl_packet_obj,
-				 u16 *mbx_val);
-
-/*
  *  ======== io_sh_msetting ========
  *  Purpose:
  *      Sets the shared memory setting
@@ -254,25 +142,6 @@ extern int io_sh_msetting(struct io_mgr *hio_mgr, u8 desc, void *pargs);
 /* Maximum channel bufsize that can be used. */
 extern u32 io_buf_size(struct io_mgr *hio_mgr);
 
-extern u32 io_read_value(struct bridge_dev_context *dev_ctxt, u32 dsp_addr);
-
-extern void io_write_value(struct bridge_dev_context *dev_ctxt,
-			   u32 dsp_addr, u32 value);
-
-extern u32 io_read_value_long(struct bridge_dev_context *dev_ctxt,
-			      u32 dsp_addr);
-
-extern void io_write_value_long(struct bridge_dev_context *dev_ctxt,
-				u32 dsp_addr, u32 value);
-
-extern void io_or_set_value(struct bridge_dev_context *dev_ctxt,
-			    u32 dsp_addr, u32 value);
-
-extern void io_and_set_value(struct bridge_dev_context *dev_ctxt,
-			     u32 dsp_addr, u32 value);
-
-extern void io_sm_init(void);
-
 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
 /*
  *  ========print_dsp_trace_buffer ========
diff --git a/drivers/staging/tidspbridge/include/dspbridge/iodefs.h b/drivers/staging/tidspbridge/include/dspbridge/iodefs.h
deleted file mode 100644
index 8bd10a0..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/iodefs.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * iodefs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * System-wide channel objects and constants.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef IODEFS_
-#define IODEFS_
-
-#define IO_MAXIRQ   0xff	/* Arbitrarily large number. */
-
-/* IO Objects: */
-struct io_mgr;
-
-/* IO manager attributes: */
-struct io_attrs {
-	u8 birq;		/* Channel's I/O IRQ number. */
-	bool irq_shared;	/* TRUE if the IRQ is shareable. */
-	u32 word_size;		/* DSP Word size. */
-	u32 shm_base;		/* Physical base address of shared memory. */
-	u32 usm_length;		/* Size (in bytes) of shared memory. */
-};
-
-#endif /* IODEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/ldr.h b/drivers/staging/tidspbridge/include/dspbridge/ldr.h
deleted file mode 100644
index 6a0269c..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/ldr.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * ldr.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Provide module loading services and symbol export services.
- *
- * Notes:
- *   This service is meant to be used by modules of the DSP/BIOS Bridge
- *   driver.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef LDR_
-#define LDR_
-
-/* Loader objects: */
-struct ldr_module;
-
-#endif /* LDR_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/list.h b/drivers/staging/tidspbridge/include/dspbridge/list.h
deleted file mode 100644
index 6837b61..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/list.h
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * list.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Declarations of list management control structures and definitions
- * of inline list management functions.
- *
- * Copyright (C) 2008 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef LIST_
-#define LIST_
-
-#include <dspbridge/host_os.h>
-#include <linux/list.h>
-
-#define LST_IS_EMPTY(l)      list_empty(&(l)->head)
-
-struct lst_list {
-	struct list_head head;
-};
-
-/*
- *  ======== lst_first ========
- *  Purpose:
- *      Returns a pointer to the first element of the list, or NULL if the list
- *      is empty.
- *  Parameters:
- *      lst:  Pointer to list control structure.
- *  Returns:
- *      Pointer to first list element, or NULL.
- *  Requires:
- *      - LST initialized.
- *      - lst != NULL.
- *  Ensures:
- */
-static inline struct list_head *lst_first(struct lst_list *lst)
-{
-	if (lst && !list_empty(&lst->head))
-		return lst->head.next;
-	return NULL;
-}
-
-/*
- *  ======== lst_get_head ========
- *  Purpose:
- *      Pops the head off the list and returns a pointer to it.
- *  Details:
- *      If the list is empty, returns NULL.
- *      Else, removes the element at the head of the list, making the next
- *      element the head of the list.
- *      The head is removed by making the tail element of the list point its
- *      "next" pointer at the next element after the head, and by making the
- *      "prev" pointer of the next element after the head point at the tail
- *      element.  So the next element after the head becomes the new head of
- *      the list.
- *  Parameters:
- *      lst:    Pointer to list control structure of list whose head
- *              element is to be removed
- *  Returns:
- *      Pointer to element that was at the head of the list (success)
- *      NULL          No elements in list
- *  Requires:
- *      - LST initialized.
- *      - lst != NULL.
- *  Ensures:
- *  Notes:
- *      Because the tail of the list points forward (its "next" pointer) to
- *      the head of the list, and the head of the list points backward (its
- *      "prev" pointer) to the tail of the list, this list is circular.
- */
-static inline struct list_head *lst_get_head(struct lst_list *lst)
-{
-	struct list_head *elem_list;
-
-	if (!lst || list_empty(&lst->head))
-		return NULL;
-
-	elem_list = lst->head.next;
-	lst->head.next = elem_list->next;
-	elem_list->next->prev = &lst->head;
-
-	return elem_list;
-}
-
-/*
- *  ======== lst_init_elem ========
- *  Purpose:
- *      Initializes a list element to default (cleared) values
- *  Details:
- *  Parameters:
- *      elem_list:  Pointer to list element to be reset
- *  Returns:
- *  Requires:
- *      LST initialized.
- *  Ensures:
- *  Notes:
- *      This function must not be called to "reset" an element in the middle
- *      of a list chain -- that would break the chain.
- *
- */
-static inline void lst_init_elem(struct list_head *elem_list)
-{
-	if (elem_list) {
-		elem_list->next = NULL;
-		elem_list->prev = NULL;
-	}
-}
-
-/*
- *  ======== lst_insert_before ========
- *  Purpose:
- *     Insert the element before the existing element.
- *  Parameters:
- *      lst:            Pointer to list control structure.
- *      elem_list:          Pointer to element in list to insert.
- *      elem_existing:  Pointer to existing list element.
- *  Returns:
- *  Requires:
- *      - LST initialized.
- *      - lst != NULL.
- *      - elem_list != NULL.
- *      - elem_existing != NULL.
- *  Ensures:
- */
-static inline void lst_insert_before(struct lst_list *lst,
-				     struct list_head *elem_list,
-				     struct list_head *elem_existing)
-{
-	if (lst && elem_list && elem_existing)
-		list_add_tail(elem_list, elem_existing);
-}
-
-/*
- *  ======== lst_next ========
- *  Purpose:
- *      Returns a pointer to the next element of the list, or NULL if the next
- *      element is the head of the list or the list is empty.
- *  Parameters:
- *      lst:        Pointer to list control structure.
- *      cur_elem:   Pointer to element in list to remove.
- *  Returns:
- *      Pointer to list element, or NULL.
- *  Requires:
- *      - LST initialized.
- *      - lst != NULL.
- *      - cur_elem != NULL.
- *  Ensures:
- */
-static inline struct list_head *lst_next(struct lst_list *lst,
-					 struct list_head *cur_elem)
-{
-	if (lst && !list_empty(&lst->head) && cur_elem &&
-	    (cur_elem->next != &lst->head))
-		return cur_elem->next;
-	return NULL;
-}
-
-/*
- *  ======== lst_put_tail ========
- *  Purpose:
- *      Adds the specified element to the tail of the list
- *  Details:
- *      Sets new element's "prev" pointer to the address previously held by
- *      the head element's prev pointer.  This is the previous tail member of
- *      the list.
- *      Sets the new head's prev pointer to the address of the element.
- *      Sets next pointer of the previous tail member of the list to point to
- *      the new element (rather than the head, which it had been pointing at).
- *      Sets new element's next pointer to the address of the head element.
- *      Sets head's prev pointer to the address of the new element.
- *  Parameters:
- *      lst:    Pointer to list control structure to which *elem_list will be
- *              added
- *      elem_list:  Pointer to list element to be added
- *  Returns:
- *      Void
- *  Requires:
- *      *elem_list and *lst must both exist.
- *      LST initialized.
- *  Ensures:
- *  Notes:
- *      Because the tail is always "just before" the head of the list (the
- *      tail's "next" pointer points at the head of the list, and the head's
- *      "prev" pointer points at the tail of the list), the list is circular.
- */
-static inline void lst_put_tail(struct lst_list *lst,
-				struct list_head *elem_list)
-{
-	if (lst && elem_list)
-		list_add_tail(elem_list, &lst->head);
-}
-
-/*
- *  ======== lst_remove_elem ========
- *  Purpose:
- *      Removes (unlinks) the given element from the list, if the list is not
- *      empty.  Does not free the list element.
- *  Parameters:
- *      lst:        Pointer to list control structure.
- *      cur_elem:   Pointer to element in list to remove.
- *  Returns:
- *  Requires:
- *      - LST initialized.
- *      - lst != NULL.
- *      - cur_elem != NULL.
- *  Ensures:
- */
-static inline void lst_remove_elem(struct lst_list *lst,
-				   struct list_head *cur_elem)
-{
-	if (lst && !list_empty(&lst->head) && cur_elem)
-		list_del_init(cur_elem);
-}
-
-#endif /* LIST_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h b/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h
index 5d165cd..7424c88 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/mbx_sh.h
@@ -110,13 +110,7 @@
 #ifndef _MBX_SH_H
 #define _MBX_SH_H
 
-#define MBX_CLASS_MSK      0xFC00	/* Class bits are 10 thru 15 */
-#define MBX_VALUE_MSK      0x03FF	/* Value is 0 thru 9 */
-
-#define MBX_DEH_CLASS      0x0000	/* DEH owns Mbx INTR */
-#define MBX_DDMA_CLASS     0x0400	/* DSP-DMA link drvr chnls owns INTR */
 #define MBX_PCPY_CLASS     0x0800	/* PROC-COPY  " */
-#define MBX_ZCPY_CLASS     0x1000	/* ZERO-COPY  " */
 #define MBX_PM_CLASS       0x2000	/* Power Management */
 #define MBX_DBG_CLASS      0x4000	/* For debugging purpose */
 
@@ -128,55 +122,21 @@
 #define MBX_DEH_USERS_BASE  0x100	/* 256 */
 #define MBX_DEH_LIMIT       0x3FF	/* 1023 */
 #define MBX_DEH_RESET       0x101	/* DSP RESET (DEH) */
-#define MBX_DEH_EMMU        0X103	/*DSP MMU FAULT RECOVERY */
 
 /*
  *  Link driver command/status codes.
  */
-/* DSP-DMA */
-#define MBX_DDMA_NUMCHNLBITS 5	/* # chnl Id: # bits available */
-#define MBX_DDMA_CHNLSHIFT   0	/* # of bits to shift */
-#define MBX_DDMA_CHNLMSK     0x01F	/* bits 0 thru 4 */
-
-#define MBX_DDMA_NUMBUFBITS  5	/* buffer index: # of bits avail */
-#define MBX_DDMA_BUFSHIFT    (MBX_DDMA_NUMCHNLBITS + MBX_DDMA_CHNLSHIFT)
-#define MBX_DDMA_BUFMSK      0x3E0	/* bits 5 thru 9 */
-
-/* Zero-Copy */
-#define MBX_ZCPY_NUMCHNLBITS 5	/* # chnl Id: # bits available */
-#define MBX_ZCPY_CHNLSHIFT   0	/* # of bits to shift */
-#define MBX_ZCPY_CHNLMSK     0x01F	/* bits 0 thru 4 */
 
 /*  Power Management Commands */
 #define MBX_PM_DSPIDLE                  (MBX_PM_CLASS + 0x0)
 #define MBX_PM_DSPWAKEUP                (MBX_PM_CLASS + 0x1)
 #define MBX_PM_EMERGENCYSLEEP           (MBX_PM_CLASS + 0x2)
-#define MBX_PM_SLEEPUNTILRESTART        (MBX_PM_CLASS + 0x3)
-#define MBX_PM_DSPGLOBALIDLE_OFF        (MBX_PM_CLASS + 0x4)
-#define MBX_PM_DSPGLOBALIDLE_ON         (MBX_PM_CLASS + 0x5)
 #define MBX_PM_SETPOINT_PRENOTIFY       (MBX_PM_CLASS + 0x6)
 #define MBX_PM_SETPOINT_POSTNOTIFY      (MBX_PM_CLASS + 0x7)
-#define MBX_PM_DSPRETN                  (MBX_PM_CLASS + 0x8)
 #define MBX_PM_DSPRETENTION        (MBX_PM_CLASS + 0x8)
 #define MBX_PM_DSPHIBERNATE        (MBX_PM_CLASS + 0x9)
 #define MBX_PM_HIBERNATE_EN        (MBX_PM_CLASS + 0xA)
 #define MBX_PM_OPP_REQ                  (MBX_PM_CLASS + 0xB)
-#define MBX_PM_OPP_CHG                  (MBX_PM_CLASS + 0xC)
-
-#define MBX_PM_TYPE_MASK 0x0300
-#define MBX_PM_TYPE_PWR_CHNG 0x0100
-#define MBX_PM_TYPE_OPP_PRECHNG 0x0200
-#define MBX_PM_TYPE_OPP_POSTCHNG 0x0300
-#define MBX_PM_TYPE_OPP_MASK 0x0300
-#define MBX_PM_OPP_PRECHNG (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG)
-/* DSP to MPU */
-#define MBX_PM_OPP_CHNG(OPP) (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG | (OPP))
-#define MBX_PM_RET (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0006)
-#define MBX_PM_HIB (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0002)
-#define MBX_PM_OPP1 0
-#define MBX_PM_OPP2 1
-#define MBX_PM_OPP3 2
-#define MBX_PM_OPP4 3
 
 /* Bridge Debug Commands */
 #define MBX_DBG_SYSPRINTF       (MBX_DBG_CLASS + 0x0)
diff --git a/drivers/staging/tidspbridge/include/dspbridge/mgrpriv.h b/drivers/staging/tidspbridge/include/dspbridge/mgrpriv.h
index bca4e10..3a4e337 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/mgrpriv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/mgrpriv.h
@@ -28,8 +28,8 @@
 struct mgr_object;
 
 struct mgr_tlbentry {
-	u32 ul_dsp_virt;	/* DSP virtual address */
-	u32 ul_gpp_phys;	/* GPP physical address */
+	u32 dsp_virt;	/* DSP virtual address */
+	u32 gpp_phys;	/* GPP physical address */
 };
 
 /*
diff --git a/drivers/staging/tidspbridge/include/dspbridge/nldrdefs.h b/drivers/staging/tidspbridge/include/dspbridge/nldrdefs.h
index c85d3da..ee3a85f 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/nldrdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/nldrdefs.h
@@ -82,10 +82,10 @@ typedef u32(*nldr_writefxn) (void *priv_ref,
  *  Attributes passed to nldr_create function.
  */
 struct nldr_attrs {
-	nldr_ovlyfxn pfn_ovly;
-	nldr_writefxn pfn_write;
-	u16 us_dsp_word_size;
-	u16 us_dsp_mau_size;
+	nldr_ovlyfxn ovly;
+	nldr_writefxn write;
+	u16 dsp_word_size;
+	u16 dsp_mau_size;
 };
 
 /*
@@ -280,14 +280,14 @@ typedef int(*nldr_unloadfxn) (struct nldr_nodeobject *nldr_node_obj,
  *  ======== node_ldr_fxns ========
  */
 struct node_ldr_fxns {
-	nldr_allocatefxn pfn_allocate;
-	nldr_createfxn pfn_create;
-	nldr_deletefxn pfn_delete;
-	nldr_exitfxn pfn_exit;
-	nldr_getfxnaddrfxn pfn_get_fxn_addr;
-	nldr_initfxn pfn_init;
-	nldr_loadfxn pfn_load;
-	nldr_unloadfxn pfn_unload;
+	nldr_allocatefxn allocate;
+	nldr_createfxn create;
+	nldr_deletefxn delete;
+	nldr_exitfxn exit;
+	nldr_getfxnaddrfxn get_fxn_addr;
+	nldr_initfxn init;
+	nldr_loadfxn load;
+	nldr_unloadfxn unload;
 };
 
 #endif /* NLDRDEFS_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/node.h b/drivers/staging/tidspbridge/include/dspbridge/node.h
index 49ed5c1..53da0ef 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/node.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/node.h
@@ -22,7 +22,7 @@
 #include <dspbridge/procpriv.h>
 
 #include <dspbridge/nodedefs.h>
-#include <dspbridge/dispdefs.h>
+#include <dspbridge/disp.h>
 #include <dspbridge/nldrdefs.h>
 #include <dspbridge/drv.h>
 
@@ -113,28 +113,10 @@ extern int node_alloc_msg_buf(struct node_object *hnode,
 extern int node_change_priority(struct node_object *hnode, s32 prio);
 
 /*
- *  ======== node_close_orphans ========
- *  Purpose:
- *      Delete all nodes whose owning processor is being destroyed.
- *  Parameters:
- *      hnode_mgr:       Node manager object.
- *      proc:          Handle to processor object being destroyed.
- *  Returns:
- *      0:        Success.
- *      -EPERM:      Unable to delete all nodes belonging to proc.
- *  Requires:
- *      Valid hnode_mgr.
- *      proc != NULL.
- *  Ensures:
- */
-extern int node_close_orphans(struct node_mgr *hnode_mgr,
-				     struct proc_object *proc);
-
-/*
  *  ======== node_connect ========
  *  Purpose:
  *      Connect two nodes on the DSP, or a node on the DSP to the GPP. In the
- *      case that the connnection is being made between a node on the DSP and
+ *      case that the connection is being made between a node on the DSP and
  *      the GPP, one of the node handles (either node1 or node2) must be
  *      the constant NODE_HGPPNODE.
  *  Parameters:
diff --git a/drivers/staging/tidspbridge/include/dspbridge/nodepriv.h b/drivers/staging/tidspbridge/include/dspbridge/nodepriv.h
index 16b0233..9c1e067 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/nodepriv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/nodepriv.h
@@ -43,7 +43,7 @@ struct node_strmdef {
 	u32 buf_size;		/* Size of buffers for SIO stream */
 	u32 num_bufs;		/* max # of buffers in SIO stream at once */
 	u32 seg_id;		/* Memory segment id to allocate buffers */
-	u32 utimeout;		/* Timeout for blocking SIO calls */
+	u32 timeout;		/* Timeout for blocking SIO calls */
 	u32 buf_alignment;	/* Buffer alignment */
 	char *sz_device;	/* Device name for stream */
 };
@@ -55,14 +55,14 @@ struct node_taskargs {
 	u32 stack_size;
 	u32 sys_stack_size;
 	u32 stack_seg;
-	u32 udsp_heap_res_addr;	/* DSP virtual heap address */
-	u32 udsp_heap_addr;	/* DSP virtual heap address */
+	u32 dsp_heap_res_addr;	/* DSP virtual heap address */
+	u32 dsp_heap_addr;	/* DSP virtual heap address */
 	u32 heap_size;		/* Heap size */
-	u32 ugpp_heap_addr;	/* GPP virtual heap address */
+	u32 gpp_heap_addr;	/* GPP virtual heap address */
 	u32 profile_id;		/* Profile ID */
 	u32 num_inputs;
 	u32 num_outputs;
-	u32 ul_dais_arg;	/* Address of iAlg object */
+	u32 dais_arg;	/* Address of iAlg object */
 	struct node_strmdef *strm_in_def;
 	struct node_strmdef *strm_out_def;
 };
diff --git a/drivers/staging/tidspbridge/include/dspbridge/pwr.h b/drivers/staging/tidspbridge/include/dspbridge/pwr.h
index a6dc783..5e3ab21 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/pwr.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/pwr.h
@@ -18,7 +18,13 @@
 #define PWR_
 
 #include <dspbridge/dbdefs.h>
-#include <dspbridge/pwr_sh.h>
+#include <dspbridge/mbx_sh.h>
+
+/* valid sleep command codes that can be sent by GPP via mailbox: */
+#define PWR_DEEPSLEEP           MBX_PM_DSPIDLE
+#define PWR_EMERGENCYDEEPSLEEP  MBX_PM_EMERGENCYSLEEP
+#define PWR_WAKEUP              MBX_PM_DSPWAKEUP
+
 
 /*
  *  ======== pwr_sleep_dsp ========
diff --git a/drivers/staging/tidspbridge/include/dspbridge/pwr_sh.h b/drivers/staging/tidspbridge/include/dspbridge/pwr_sh.h
deleted file mode 100644
index 1b4a090..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/pwr_sh.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * pwr_sh.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Power Manager shared definitions (used on both GPP and DSP sides).
- *
- * Copyright (C) 2008 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef PWR_SH_
-#define PWR_SH_
-
-#include <dspbridge/mbx_sh.h>
-
-/* valid sleep command codes that can be sent by GPP via mailbox: */
-#define PWR_DEEPSLEEP           MBX_PM_DSPIDLE
-#define PWR_EMERGENCYDEEPSLEEP  MBX_PM_EMERGENCYSLEEP
-#define PWR_SLEEPUNTILRESTART   MBX_PM_SLEEPUNTILRESTART
-#define PWR_WAKEUP              MBX_PM_DSPWAKEUP
-#define PWR_AUTOENABLE          MBX_PM_PWRENABLE
-#define PWR_AUTODISABLE         MBX_PM_PWRDISABLE
-#define PWR_RETENTION             MBX_PM_DSPRETN
-
-#endif /* PWR_SH_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h b/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h
index dfaf0c6..8c9c902 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/resourcecleanup.h
@@ -17,23 +17,12 @@
 #include <dspbridge/nodepriv.h>
 #include <dspbridge/drv.h>
 
-extern int drv_get_proc_ctxt_list(struct process_context **pctxt,
-					 struct drv_object *hdrv_obj);
-
-extern int drv_insert_proc_context(struct drv_object *driver_obj,
-					  void *process_ctxt);
-
 extern int drv_remove_all_dmm_res_elements(void *process_ctxt);
 
 extern int drv_remove_all_node_res_elements(void *process_ctxt);
 
-extern int drv_proc_set_pid(void *ctxt, s32 process);
-
 extern int drv_remove_all_resources(void *process_ctxt);
 
-extern int drv_remove_proc_context(struct drv_object *driver_obj,
-					  void *pr_ctxt);
-
 extern int drv_insert_node_res_element(void *hnode, void *node_resource,
 					      void *process_ctxt);
 
diff --git a/drivers/staging/tidspbridge/include/dspbridge/rms_sh.h b/drivers/staging/tidspbridge/include/dspbridge/rms_sh.h
index 7bc5574..ba7f478 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/rms_sh.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/rms_sh.h
@@ -22,27 +22,18 @@
 
 #include <dspbridge/rmstypes.h>
 
-/* Node Types: */
-#define RMS_TASK                1	/* Task node */
-#define RMS_DAIS                2	/* xDAIS socket node */
-#define RMS_MSG                 3	/* Message node */
-
 /* Memory Types: */
 #define RMS_CODE                0	/* Program space */
 #define RMS_DATA                1	/* Data space */
-#define RMS_IO                	2	/* I/O space */
 
 /* RM Server Command and Response Buffer Sizes: */
 #define RMS_COMMANDBUFSIZE     256	/* Size of command buffer */
-#define RMS_RESPONSEBUFSIZE    16	/* Size of response buffer */
 
 /* Pre-Defined Command/Response Codes: */
 #define RMS_EXIT                0x80000000	/* GPP->Node: shutdown */
 #define RMS_EXITACK             0x40000000	/* Node->GPP: ack shutdown */
 #define RMS_BUFDESC             0x20000000	/* Arg1 SM buf, Arg2 SM size */
 #define RMS_KILLTASK            0x10000000	/* GPP->Node: Kill Task */
-#define RMS_USER                0x0	/* Start of user-defined msg codes */
-#define RMS_MAXUSERCODES        0xfff	/* Maximum user defined C/R Codes */
 
 /* RM Server RPC Command Structure: */
 struct rms_command {
diff --git a/drivers/staging/tidspbridge/include/dspbridge/strm.h b/drivers/staging/tidspbridge/include/dspbridge/strm.h
index 3e4671e..613fe53 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/strm.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/strm.h
@@ -142,25 +142,6 @@ extern int strm_free_buffer(struct strm_res_object *strmres,
 				   struct process_context *pr_ctxt);
 
 /*
- *  ======== strm_get_event_handle ========
- *  Purpose:
- *      Get stream's user event handle. This function is used when closing
- *      a stream, so the event can be closed.
- *  Parameter:
- *      stream_obj:      Stream handle returned from strm_open().
- *      ph_event:        Location to store event handle on output.
- *  Returns:
- *      0:        Success.
- *      -EFAULT:    Invalid stream_obj.
- *  Requires:
- *      strm_init(void) called.
- *      ph_event != NULL.
- *  Ensures:
- */
-extern int strm_get_event_handle(struct strm_object *stream_obj,
-					void **ph_event);
-
-/*
  *  ======== strm_get_info ========
  *  Purpose:
  *      Get information about a stream. User's dsp_streaminfo is contained
@@ -276,27 +257,6 @@ extern int strm_open(struct node_object *hnode, u32 dir,
 			    struct process_context *pr_ctxt);
 
 /*
- *  ======== strm_prepare_buffer ========
- *  Purpose:
- *      Prepare a data buffer not allocated by DSPStream_AllocateBuffers()
- *      for use with a stream.
- *  Parameter:
- *      stream_obj:     Stream handle returned from strm_open().
- *      usize:          Size (GPP bytes) of the buffer.
- *      pbuffer:        Buffer address.
- *  Returns:
- *      0:        Success.
- *      -EFAULT:    Invalid stream_obj.
- *      -EPERM:      Failure occurred, unable to prepare buffer.
- *  Requires:
- *      strm_init(void) called.
- *      pbuffer != NULL.
- *  Ensures:
- */
-extern int strm_prepare_buffer(struct strm_object *stream_obj,
-				      u32 usize, u8 *pbuffer);
-
-/*
  *  ======== strm_reclaim ========
  *  Purpose:
  *      Request a buffer back from a stream.
@@ -379,26 +339,4 @@ extern int strm_register_notify(struct strm_object *stream_obj,
 extern int strm_select(struct strm_object **strm_tab,
 			      u32 strms, u32 *pmask, u32 utimeout);
 
-/*
- *  ======== strm_unprepare_buffer ========
- *  Purpose:
- *      Unprepare a data buffer that was previously prepared for a stream
- *      with DSPStream_PrepareBuffer(), and that will no longer be used with
- *      the stream.
- *  Parameter:
- *      stream_obj:     Stream handle returned from strm_open().
- *      usize:          Size (GPP bytes) of the buffer.
- *      pbuffer:        Buffer address.
- *  Returns:
- *      0:        Success.
- *      -EFAULT:    Invalid stream_obj.
- *      -EPERM:      Failure occurred, unable to unprepare buffer.
- *  Requires:
- *      strm_init(void) called.
- *      pbuffer != NULL.
- *  Ensures:
- */
-extern int strm_unprepare_buffer(struct strm_object *stream_obj,
-					u32 usize, u8 *pbuffer);
-
 #endif /* STRM_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/strmdefs.h b/drivers/staging/tidspbridge/include/dspbridge/strmdefs.h
index b363f79..4f90e6b 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/strmdefs.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/strmdefs.h
@@ -19,18 +19,16 @@
 #ifndef STRMDEFS_
 #define STRMDEFS_
 
-#define STRM_MAXEVTNAMELEN      32
-
 struct strm_mgr;
 
 struct strm_object;
 
 struct strm_attr {
 	void *user_event;
-	char *pstr_event_name;
+	char *str_event_name;
 	void *virt_base;	/* Process virtual base address of
 				 * mapped SM */
-	u32 ul_virt_size;	/* Size of virtual space in bytes */
+	u32 virt_size;		/* Size of virtual space in bytes */
 	struct dsp_streamattrin *stream_attr_in;
 };
 
diff --git a/drivers/staging/tidspbridge/include/dspbridge/sync.h b/drivers/staging/tidspbridge/include/dspbridge/sync.h
index e2651e7..b1e75eb 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/sync.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/sync.h
@@ -20,6 +20,7 @@
 #define _SYNC_H
 
 #include <dspbridge/dbdefs.h>
+#include <dspbridge/host_os.h>
 
 
 /* Special timeout value indicating an infinite wait: */
@@ -80,13 +81,22 @@ void sync_set_event(struct sync_object *event);
  * This functios will wait until @event is set or until timeout. In case of
  * success the function will return 0 and
  * in case of timeout the function will return -ETIME
+ * in case of signal the function will return -ERESTARTSYS
  */
 
 static inline int sync_wait_on_event(struct sync_object *event,
 							unsigned timeout)
 {
-	return wait_for_completion_timeout(&event->comp,
-		msecs_to_jiffies(timeout)) ? 0 : -ETIME;
+	int res;
+
+	res = wait_for_completion_interruptible_timeout(&event->comp,
+						msecs_to_jiffies(timeout));
+	if (!res)
+		res = -ETIME;
+	else if (res > 0)
+		res = 0;
+
+	return res;
 }
 
 /**
diff --git a/drivers/staging/tidspbridge/include/dspbridge/utildefs.h b/drivers/staging/tidspbridge/include/dspbridge/utildefs.h
deleted file mode 100644
index 8fe5414..0000000
--- a/drivers/staging/tidspbridge/include/dspbridge/utildefs.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * utildefs.h
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * Global UTIL constants and types, shared between DSP API and DSPSYS.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * 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
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef UTILDEFS_
-#define UTILDEFS_
-
-/* constants taken from configmg.h */
-#define UTIL_MAXMEMREGS     9
-#define UTIL_MAXIOPORTS     20
-#define UTIL_MAXIRQS        7
-#define UTIL_MAXDMACHNLS    7
-
-/* misc. constants */
-#define UTIL_MAXARGVS       10
-
-/* Platform specific important info */
-struct util_sysinfo {
-	/* Granularity of page protection; usually 1k or 4k */
-	u32 dw_page_size;
-	u32 dw_allocation_granularity;	/* VM granularity, usually 64K */
-	u32 dw_number_of_processors;	/* Used as sanity check */
-};
-
-#endif /* UTILDEFS_ */
diff --git a/drivers/staging/tidspbridge/pmgr/chnl.c b/drivers/staging/tidspbridge/pmgr/chnl.c
index 78b0d0f..245de82 100644
--- a/drivers/staging/tidspbridge/pmgr/chnl.c
+++ b/drivers/staging/tidspbridge/pmgr/chnl.c
@@ -87,7 +87,7 @@ int chnl_create(struct chnl_mgr **channel_mgr,
 		struct bridge_drv_interface *intf_fxns;
 		dev_get_intf_fxns(hdev_obj, &intf_fxns);
 		/* Let Bridge channel module finish the create: */
-		status = (*intf_fxns->pfn_chnl_create) (&hchnl_mgr, hdev_obj,
+		status = (*intf_fxns->chnl_create) (&hchnl_mgr, hdev_obj,
 							mgr_attrts);
 		if (!status) {
 			/* Fill in DSP API channel module's fields of the
@@ -120,7 +120,7 @@ int chnl_destroy(struct chnl_mgr *hchnl_mgr)
 	if (chnl_mgr_obj) {
 		intf_fxns = chnl_mgr_obj->intf_fxns;
 		/* Let Bridge channel module destroy the chnl_mgr: */
-		status = (*intf_fxns->pfn_chnl_destroy) (hchnl_mgr);
+		status = (*intf_fxns->chnl_destroy) (hchnl_mgr);
 	} else {
 		status = -EFAULT;
 	}
diff --git a/drivers/staging/tidspbridge/pmgr/cmm.c b/drivers/staging/tidspbridge/pmgr/cmm.c
index 93a7c4f..e6b2c89 100644
--- a/drivers/staging/tidspbridge/pmgr/cmm.c
+++ b/drivers/staging/tidspbridge/pmgr/cmm.c
@@ -12,7 +12,7 @@
  * describes a block of physically contiguous shared memory used for
  * future allocations by CMM.
  *
- * Memory is coelesced back to the appropriate heap when a buffer is
+ * Memory is coalesced back to the appropriate heap when a buffer is
  * freed.
  *
  * Notes:
@@ -30,6 +30,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 #include <linux/types.h>
+#include <linux/list.h>
 
 /*  ----------------------------------- DSP/BIOS Bridge */
 #include <dspbridge/dbdefs.h>
@@ -38,9 +39,7 @@
 #include <dspbridge/dbc.h>
 
 /*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
 #include <dspbridge/sync.h>
-#include <dspbridge/utildefs.h>
 
 /*  ----------------------------------- Platform Manager */
 #include <dspbridge/dev.h>
@@ -50,7 +49,7 @@
 #include <dspbridge/cmm.h>
 
 /*  ----------------------------------- Defines, Data Structures, Typedefs */
-#define NEXT_PA(pnode)   (pnode->dw_pa + pnode->ul_size)
+#define NEXT_PA(pnode)   (pnode->pa + pnode->size)
 
 /* Other bus/platform translations */
 #define DSPPA2GPPPA(base, x, y)  ((x)+(y))
@@ -64,32 +63,32 @@
  */
 struct cmm_allocator {		/* sma */
 	unsigned int shm_base;	/* Start of physical SM block */
-	u32 ul_sm_size;		/* Size of SM block in bytes */
-	unsigned int dw_vm_base;	/* Start of VM block. (Dev driver
+	u32 sm_size;		/* Size of SM block in bytes */
+	unsigned int vm_base;	/* Start of VM block. (Dev driver
 					 * context for 'sma') */
-	u32 dw_dsp_phys_addr_offset;	/* DSP PA to GPP PA offset for this
+	u32 dsp_phys_addr_offset;	/* DSP PA to GPP PA offset for this
 					 * SM space */
 	s8 c_factor;		/* DSPPa to GPPPa Conversion Factor */
-	unsigned int dw_dsp_base;	/* DSP virt base byte address */
-	u32 ul_dsp_size;	/* DSP seg size in bytes */
-	struct cmm_object *hcmm_mgr;	/* back ref to parent mgr */
+	unsigned int dsp_base;	/* DSP virt base byte address */
+	u32 dsp_size;	/* DSP seg size in bytes */
+	struct cmm_object *cmm_mgr;	/* back ref to parent mgr */
 	/* node list of available memory */
-	struct lst_list *free_list_head;
+	struct list_head free_list;
 	/* node list of memory in use */
-	struct lst_list *in_use_list_head;
+	struct list_head in_use_list;
 };
 
 struct cmm_xlator {		/* Pa<->Va translator object */
 	/* CMM object this translator associated */
-	struct cmm_object *hcmm_mgr;
+	struct cmm_object *cmm_mgr;
 	/*
 	 *  Client process virtual base address that corresponds to phys SM
-	 *  base address for translator's ul_seg_id.
+	 *  base address for translator's seg_id.
 	 *  Only 1 segment ID currently supported.
 	 */
-	unsigned int dw_virt_base;	/* virtual base address */
-	u32 ul_virt_size;	/* size of virt space in bytes */
-	u32 ul_seg_id;		/* Segment Id */
+	unsigned int virt_base;	/* virtual base address */
+	u32 virt_size;		/* size of virt space in bytes */
+	u32 seg_id;		/* Segment Id */
 };
 
 /* CMM Mgr */
@@ -98,40 +97,40 @@ struct cmm_object {
 	 * Cmm Lock is used to serialize access mem manager for multi-threads.
 	 */
 	struct mutex cmm_lock;	/* Lock to access cmm mgr */
-	struct lst_list *node_free_list_head;	/* Free list of memory nodes */
-	u32 ul_min_block_size;	/* Min SM block; default 16 bytes */
-	u32 dw_page_size;	/* Memory Page size (1k/4k) */
+	struct list_head node_free_list;	/* Free list of memory nodes */
+	u32 min_block_size;	/* Min SM block; default 16 bytes */
+	u32 page_size;	/* Memory Page size (1k/4k) */
 	/* GPP SM segment ptrs */
 	struct cmm_allocator *pa_gppsm_seg_tab[CMM_MAXGPPSEGS];
 };
 
 /* Default CMM Mgr attributes */
 static struct cmm_mgrattrs cmm_dfltmgrattrs = {
-	/* ul_min_block_size, min block size(bytes) allocated by cmm mgr */
+	/* min_block_size, min block size(bytes) allocated by cmm mgr */
 	16
 };
 
 /* Default allocation attributes */
 static struct cmm_attrs cmm_dfltalctattrs = {
-	1		/* ul_seg_id, default segment Id for allocator */
+	1		/* seg_id, default segment Id for allocator */
 };
 
 /* Address translator default attrs */
 static struct cmm_xlatorattrs cmm_dfltxlatorattrs = {
-	/* ul_seg_id, does not have to match cmm_dfltalctattrs ul_seg_id */
+	/* seg_id, does not have to match cmm_dfltalctattrs ul_seg_id */
 	1,
-	0,			/* dw_dsp_bufs */
-	0,			/* dw_dsp_buf_size */
+	0,			/* dsp_bufs */
+	0,			/* dsp_buf_size */
 	NULL,			/* vm_base */
-	0,			/* dw_vm_size */
+	0,			/* vm_size */
 };
 
 /* SM node representing a block of memory. */
 struct cmm_mnode {
 	struct list_head link;	/* must be 1st element */
-	u32 dw_pa;		/* Phys addr */
-	u32 dw_va;		/* Virtual address in device process context */
-	u32 ul_size;		/* SM block size in bytes */
+	u32 pa;		/* Phys addr */
+	u32 va;			/* Virtual address in device process context */
+	u32 size;		/* SM block size in bytes */
 	u32 client_proc;	/* Process that allocated this mem block */
 };
 
@@ -181,32 +180,32 @@ void *cmm_calloc_buf(struct cmm_object *hcmm_mgr, u32 usize,
 		*pp_buf_va = NULL;
 
 	if (cmm_mgr_obj && (usize != 0)) {
-		if (pattrs->ul_seg_id > 0) {
+		if (pattrs->seg_id > 0) {
 			/* SegId > 0 is SM */
 			/* get the allocator object for this segment id */
 			allocator =
-			    get_allocator(cmm_mgr_obj, pattrs->ul_seg_id);
-			/* keep block size a multiple of ul_min_block_size */
+			    get_allocator(cmm_mgr_obj, pattrs->seg_id);
+			/* keep block size a multiple of min_block_size */
 			usize =
-			    ((usize - 1) & ~(cmm_mgr_obj->ul_min_block_size -
+			    ((usize - 1) & ~(cmm_mgr_obj->min_block_size -
 					     1))
-			    + cmm_mgr_obj->ul_min_block_size;
+			    + cmm_mgr_obj->min_block_size;
 			mutex_lock(&cmm_mgr_obj->cmm_lock);
 			pnode = get_free_block(allocator, usize);
 		}
 		if (pnode) {
-			delta_size = (pnode->ul_size - usize);
-			if (delta_size >= cmm_mgr_obj->ul_min_block_size) {
+			delta_size = (pnode->size - usize);
+			if (delta_size >= cmm_mgr_obj->min_block_size) {
 				/* create a new block with the leftovers and
 				 * add to freelist */
 				new_node =
-				    get_node(cmm_mgr_obj, pnode->dw_pa + usize,
-					     pnode->dw_va + usize,
+				    get_node(cmm_mgr_obj, pnode->pa + usize,
+					     pnode->va + usize,
 					     (u32) delta_size);
 				/* leftovers go free */
 				add_to_free_list(allocator, new_node);
 				/* adjust our node's size */
-				pnode->ul_size = usize;
+				pnode->size = usize;
 			}
 			/* Tag node with client process requesting allocation
 			 * We'll need to free up a process's alloc'd SM if the
@@ -216,17 +215,16 @@ void *cmm_calloc_buf(struct cmm_object *hcmm_mgr, u32 usize,
 			pnode->client_proc = current->tgid;
 
 			/* put our node on InUse list */
-			lst_put_tail(allocator->in_use_list_head,
-				     (struct list_head *)pnode);
-			buf_pa = (void *)pnode->dw_pa;	/* physical address */
+			list_add_tail(&pnode->link, &allocator->in_use_list);
+			buf_pa = (void *)pnode->pa;	/* physical address */
 			/* clear mem */
-			pbyte = (u8 *) pnode->dw_va;
+			pbyte = (u8 *) pnode->va;
 			for (cnt = 0; cnt < (s32) usize; cnt++, pbyte++)
 				*pbyte = 0;
 
 			if (pp_buf_va != NULL) {
 				/* Virtual address */
-				*pp_buf_va = (void *)pnode->dw_va;
+				*pp_buf_va = (void *)pnode->va;
 			}
 		}
 		mutex_unlock(&cmm_mgr_obj->cmm_lock);
@@ -245,7 +243,6 @@ int cmm_create(struct cmm_object **ph_cmm_mgr,
 {
 	struct cmm_object *cmm_obj = NULL;
 	int status = 0;
-	struct util_sysinfo sys_info;
 
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(ph_cmm_mgr != NULL);
@@ -253,40 +250,23 @@ int cmm_create(struct cmm_object **ph_cmm_mgr,
 	*ph_cmm_mgr = NULL;
 	/* create, zero, and tag a cmm mgr object */
 	cmm_obj = kzalloc(sizeof(struct cmm_object), GFP_KERNEL);
-	if (cmm_obj != NULL) {
-		if (mgr_attrts == NULL)
-			mgr_attrts = &cmm_dfltmgrattrs;	/* set defaults */
-
-		/* 4 bytes minimum */
-		DBC_ASSERT(mgr_attrts->ul_min_block_size >= 4);
-		/* save away smallest block allocation for this cmm mgr */
-		cmm_obj->ul_min_block_size = mgr_attrts->ul_min_block_size;
-		/* save away the systems memory page size */
-		sys_info.dw_page_size = PAGE_SIZE;
-		sys_info.dw_allocation_granularity = PAGE_SIZE;
-		sys_info.dw_number_of_processors = 1;
-
-		cmm_obj->dw_page_size = sys_info.dw_page_size;
-
-		/* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by
-		 * MEM_ALLOC_OBJECT */
-
-		/* create node free list */
-		cmm_obj->node_free_list_head =
-				kzalloc(sizeof(struct lst_list),
-						GFP_KERNEL);
-		if (cmm_obj->node_free_list_head == NULL) {
-			status = -ENOMEM;
-			cmm_destroy(cmm_obj, true);
-		} else {
-			INIT_LIST_HEAD(&cmm_obj->
-				       node_free_list_head->head);
-			mutex_init(&cmm_obj->cmm_lock);
-			*ph_cmm_mgr = cmm_obj;
-		}
-	} else {
-		status = -ENOMEM;
-	}
+	if (!cmm_obj)
+		return -ENOMEM;
+
+	if (mgr_attrts == NULL)
+		mgr_attrts = &cmm_dfltmgrattrs;	/* set defaults */
+
+	/* 4 bytes minimum */
+	DBC_ASSERT(mgr_attrts->min_block_size >= 4);
+	/* save away smallest block allocation for this cmm mgr */
+	cmm_obj->min_block_size = mgr_attrts->min_block_size;
+	cmm_obj->page_size = PAGE_SIZE;
+
+	/* create node free list */
+	INIT_LIST_HEAD(&cmm_obj->node_free_list);
+	mutex_init(&cmm_obj->cmm_lock);
+	*ph_cmm_mgr = cmm_obj;
+
 	return status;
 }
 
@@ -301,7 +281,7 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force)
 	struct cmm_info temp_info;
 	int status = 0;
 	s32 slot_seg;
-	struct cmm_mnode *pnode;
+	struct cmm_mnode *node, *tmp;
 
 	DBC_REQUIRE(refs > 0);
 	if (!hcmm_mgr) {
@@ -314,7 +294,7 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force)
 		/* Check for outstanding memory allocations */
 		status = cmm_get_info(hcmm_mgr, &temp_info);
 		if (!status) {
-			if (temp_info.ul_total_in_use_cnt > 0) {
+			if (temp_info.total_in_use_cnt > 0) {
 				/* outstanding allocations */
 				status = -EPERM;
 			}
@@ -331,15 +311,10 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force)
 			}
 		}
 	}
-	if (cmm_mgr_obj->node_free_list_head != NULL) {
-		/* Free the free nodes */
-		while (!LST_IS_EMPTY(cmm_mgr_obj->node_free_list_head)) {
-			pnode = (struct cmm_mnode *)
-			    lst_get_head(cmm_mgr_obj->node_free_list_head);
-			kfree(pnode);
-		}
-		/* delete NodeFreeList list */
-		kfree(cmm_mgr_obj->node_free_list_head);
+	list_for_each_entry_safe(node, tmp, &cmm_mgr_obj->node_free_list,
+			link) {
+		list_del(&node->link);
+		kfree(node);
 	}
 	mutex_unlock(&cmm_mgr_obj->cmm_lock);
 	if (!status) {
@@ -368,13 +343,12 @@ void cmm_exit(void)
  *  Purpose:
  *      Free the given buffer.
  */
-int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa,
-			u32 ul_seg_id)
+int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa, u32 ul_seg_id)
 {
 	struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
 	int status = -EFAULT;
-	struct cmm_mnode *mnode_obj = NULL;
-	struct cmm_allocator *allocator = NULL;
+	struct cmm_mnode *curr, *tmp;
+	struct cmm_allocator *allocator;
 	struct cmm_attrs *pattrs;
 
 	DBC_REQUIRE(refs > 0);
@@ -382,35 +356,28 @@ int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa,
 
 	if (ul_seg_id == 0) {
 		pattrs = &cmm_dfltalctattrs;
-		ul_seg_id = pattrs->ul_seg_id;
+		ul_seg_id = pattrs->seg_id;
 	}
 	if (!hcmm_mgr || !(ul_seg_id > 0)) {
 		status = -EFAULT;
 		return status;
 	}
-	/* get the allocator for this segment id */
+
 	allocator = get_allocator(cmm_mgr_obj, ul_seg_id);
-	if (allocator != NULL) {
-		mutex_lock(&cmm_mgr_obj->cmm_lock);
-		mnode_obj =
-		    (struct cmm_mnode *)lst_first(allocator->in_use_list_head);
-		while (mnode_obj) {
-			if ((u32) buf_pa == mnode_obj->dw_pa) {
-				/* Found it */
-				lst_remove_elem(allocator->in_use_list_head,
-						(struct list_head *)mnode_obj);
-				/* back to freelist */
-				add_to_free_list(allocator, mnode_obj);
-				status = 0;	/* all right! */
-				break;
-			}
-			/* next node. */
-			mnode_obj = (struct cmm_mnode *)
-			    lst_next(allocator->in_use_list_head,
-				     (struct list_head *)mnode_obj);
+	if (!allocator)
+		return status;
+
+	mutex_lock(&cmm_mgr_obj->cmm_lock);
+	list_for_each_entry_safe(curr, tmp, &allocator->in_use_list, link) {
+		if (curr->pa == (u32) buf_pa) {
+			list_del(&curr->link);
+			add_to_free_list(allocator, curr);
+			status = 0;
+			break;
 		}
-		mutex_unlock(&cmm_mgr_obj->cmm_lock);
 	}
+	mutex_unlock(&cmm_mgr_obj->cmm_lock);
+
 	return status;
 }
 
@@ -450,7 +417,7 @@ int cmm_get_info(struct cmm_object *hcmm_mgr,
 	u32 ul_seg;
 	int status = 0;
 	struct cmm_allocator *altr;
-	struct cmm_mnode *mnode_obj = NULL;
+	struct cmm_mnode *curr;
 
 	DBC_REQUIRE(cmm_info_obj != NULL);
 
@@ -459,46 +426,39 @@ int cmm_get_info(struct cmm_object *hcmm_mgr,
 		return status;
 	}
 	mutex_lock(&cmm_mgr_obj->cmm_lock);
-	cmm_info_obj->ul_num_gppsm_segs = 0;	/* # of SM segments */
+	cmm_info_obj->num_gppsm_segs = 0;	/* # of SM segments */
 	/* Total # of outstanding alloc */
-	cmm_info_obj->ul_total_in_use_cnt = 0;
+	cmm_info_obj->total_in_use_cnt = 0;
 	/* min block size */
-	cmm_info_obj->ul_min_block_size = cmm_mgr_obj->ul_min_block_size;
+	cmm_info_obj->min_block_size = cmm_mgr_obj->min_block_size;
 	/* check SM memory segments */
 	for (ul_seg = 1; ul_seg <= CMM_MAXGPPSEGS; ul_seg++) {
 		/* get the allocator object for this segment id */
 		altr = get_allocator(cmm_mgr_obj, ul_seg);
-		if (altr != NULL) {
-			cmm_info_obj->ul_num_gppsm_segs++;
-			cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_pa =
-			    altr->shm_base - altr->ul_dsp_size;
-			cmm_info_obj->seg_info[ul_seg - 1].ul_total_seg_size =
-			    altr->ul_dsp_size + altr->ul_sm_size;
-			cmm_info_obj->seg_info[ul_seg - 1].dw_gpp_base_pa =
-			    altr->shm_base;
-			cmm_info_obj->seg_info[ul_seg - 1].ul_gpp_size =
-			    altr->ul_sm_size;
-			cmm_info_obj->seg_info[ul_seg - 1].dw_dsp_base_va =
-			    altr->dw_dsp_base;
-			cmm_info_obj->seg_info[ul_seg - 1].ul_dsp_size =
-			    altr->ul_dsp_size;
-			cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_va =
-			    altr->dw_vm_base - altr->ul_dsp_size;
-			cmm_info_obj->seg_info[ul_seg - 1].ul_in_use_cnt = 0;
-			mnode_obj = (struct cmm_mnode *)
-			    lst_first(altr->in_use_list_head);
-			/* Count inUse blocks */
-			while (mnode_obj) {
-				cmm_info_obj->ul_total_in_use_cnt++;
-				cmm_info_obj->seg_info[ul_seg -
-						       1].ul_in_use_cnt++;
-				/* next node. */
-				mnode_obj = (struct cmm_mnode *)
-				    lst_next(altr->in_use_list_head,
-					     (struct list_head *)mnode_obj);
-			}
+		if (!altr)
+			continue;
+		cmm_info_obj->num_gppsm_segs++;
+		cmm_info_obj->seg_info[ul_seg - 1].seg_base_pa =
+			altr->shm_base - altr->dsp_size;
+		cmm_info_obj->seg_info[ul_seg - 1].total_seg_size =
+			altr->dsp_size + altr->sm_size;
+		cmm_info_obj->seg_info[ul_seg - 1].gpp_base_pa =
+			altr->shm_base;
+		cmm_info_obj->seg_info[ul_seg - 1].gpp_size =
+			altr->sm_size;
+		cmm_info_obj->seg_info[ul_seg - 1].dsp_base_va =
+			altr->dsp_base;
+		cmm_info_obj->seg_info[ul_seg - 1].dsp_size =
+			altr->dsp_size;
+		cmm_info_obj->seg_info[ul_seg - 1].seg_base_va =
+			altr->vm_base - altr->dsp_size;
+		cmm_info_obj->seg_info[ul_seg - 1].in_use_cnt = 0;
+
+		list_for_each_entry(curr, &altr->in_use_list, link) {
+			cmm_info_obj->total_in_use_cnt++;
+			cmm_info_obj->seg_info[ul_seg - 1].in_use_cnt++;
 		}
-	}			/* end for */
+	}
 	mutex_unlock(&cmm_mgr_obj->cmm_lock);
 	return status;
 }
@@ -544,75 +504,62 @@ int cmm_register_gppsm_seg(struct cmm_object *hcmm_mgr,
 	DBC_REQUIRE(dw_gpp_base_pa != 0);
 	DBC_REQUIRE(gpp_base_va != 0);
 	DBC_REQUIRE((c_factor <= CMM_ADDTODSPPA) &&
-		    (c_factor >= CMM_SUBFROMDSPPA));
+			(c_factor >= CMM_SUBFROMDSPPA));
+
 	dev_dbg(bridge, "%s: dw_gpp_base_pa %x ul_size %x dsp_addr_offset %x "
-		"dw_dsp_base %x ul_dsp_size %x gpp_base_va %x\n", __func__,
-		dw_gpp_base_pa, ul_size, dsp_addr_offset, dw_dsp_base,
-		ul_dsp_size, gpp_base_va);
-	if (!hcmm_mgr) {
-		status = -EFAULT;
-		return status;
-	}
+			"dw_dsp_base %x ul_dsp_size %x gpp_base_va %x\n",
+			__func__, dw_gpp_base_pa, ul_size, dsp_addr_offset,
+			dw_dsp_base, ul_dsp_size, gpp_base_va);
+
+	if (!hcmm_mgr)
+		return -EFAULT;
+
 	/* make sure we have room for another allocator */
 	mutex_lock(&cmm_mgr_obj->cmm_lock);
+
 	slot_seg = get_slot(cmm_mgr_obj);
 	if (slot_seg < 0) {
-		/* get a slot number */
 		status = -EPERM;
 		goto func_end;
 	}
+
 	/* Check if input ul_size is big enough to alloc at least one block */
-	if (ul_size < cmm_mgr_obj->ul_min_block_size) {
+	if (ul_size < cmm_mgr_obj->min_block_size) {
 		status = -EINVAL;
 		goto func_end;
 	}
 
 	/* create, zero, and tag an SM allocator object */
 	psma = kzalloc(sizeof(struct cmm_allocator), GFP_KERNEL);
-	if (psma != NULL) {
-		psma->hcmm_mgr = hcmm_mgr;	/* ref to parent */
-		psma->shm_base = dw_gpp_base_pa;	/* SM Base phys */
-		psma->ul_sm_size = ul_size;	/* SM segment size in bytes */
-		psma->dw_vm_base = gpp_base_va;
-		psma->dw_dsp_phys_addr_offset = dsp_addr_offset;
-		psma->c_factor = c_factor;
-		psma->dw_dsp_base = dw_dsp_base;
-		psma->ul_dsp_size = ul_dsp_size;
-		if (psma->dw_vm_base == 0) {
-			status = -EPERM;
-			goto func_end;
-		}
-		/* return the actual segment identifier */
-		*sgmt_id = (u32) slot_seg + 1;
-		/* create memory free list */
-		psma->free_list_head = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		if (psma->free_list_head == NULL) {
-			status = -ENOMEM;
-			goto func_end;
-		}
-		INIT_LIST_HEAD(&psma->free_list_head->head);
-
-		/* create memory in-use list */
-		psma->in_use_list_head = kzalloc(sizeof(struct
-						lst_list), GFP_KERNEL);
-		if (psma->in_use_list_head == NULL) {
-			status = -ENOMEM;
-			goto func_end;
-		}
-		INIT_LIST_HEAD(&psma->in_use_list_head->head);
-
-		/* Get a mem node for this hunk-o-memory */
-		new_node = get_node(cmm_mgr_obj, dw_gpp_base_pa,
-				    psma->dw_vm_base, ul_size);
-		/* Place node on the SM allocator's free list */
-		if (new_node) {
-			lst_put_tail(psma->free_list_head,
-				     (struct list_head *)new_node);
-		} else {
-			status = -ENOMEM;
-			goto func_end;
-		}
+	if (!psma) {
+		status = -ENOMEM;
+		goto func_end;
+	}
+
+	psma->cmm_mgr = hcmm_mgr;	/* ref to parent */
+	psma->shm_base = dw_gpp_base_pa;	/* SM Base phys */
+	psma->sm_size = ul_size;	/* SM segment size in bytes */
+	psma->vm_base = gpp_base_va;
+	psma->dsp_phys_addr_offset = dsp_addr_offset;
+	psma->c_factor = c_factor;
+	psma->dsp_base = dw_dsp_base;
+	psma->dsp_size = ul_dsp_size;
+	if (psma->vm_base == 0) {
+		status = -EPERM;
+		goto func_end;
+	}
+	/* return the actual segment identifier */
+	*sgmt_id = (u32) slot_seg + 1;
+
+	INIT_LIST_HEAD(&psma->free_list);
+	INIT_LIST_HEAD(&psma->in_use_list);
+
+	/* Get a mem node for this hunk-o-memory */
+	new_node = get_node(cmm_mgr_obj, dw_gpp_base_pa,
+			psma->vm_base, ul_size);
+	/* Place node on the SM allocator's free list */
+	if (new_node) {
+		list_add_tail(&new_node->link, &psma->free_list);
 	} else {
 		status = -ENOMEM;
 		goto func_end;
@@ -621,12 +568,11 @@ int cmm_register_gppsm_seg(struct cmm_object *hcmm_mgr,
 	cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] = psma;
 
 func_end:
-	if (status && psma) {
-		/* Cleanup allocator */
+	/* Cleanup allocator */
+	if (status && psma)
 		un_register_gppsm_seg(psma);
-	}
-
 	mutex_unlock(&cmm_mgr_obj->cmm_lock);
+
 	return status;
 }
 
@@ -644,36 +590,36 @@ int cmm_un_register_gppsm_seg(struct cmm_object *hcmm_mgr,
 	u32 ul_id = ul_seg_id;
 
 	DBC_REQUIRE(ul_seg_id > 0);
-	if (hcmm_mgr) {
-		if (ul_seg_id == CMM_ALLSEGMENTS)
-			ul_id = 1;
-
-		if ((ul_id > 0) && (ul_id <= CMM_MAXGPPSEGS)) {
-			while (ul_id <= CMM_MAXGPPSEGS) {
-				mutex_lock(&cmm_mgr_obj->cmm_lock);
-				/* slot = seg_id-1 */
-				psma = cmm_mgr_obj->pa_gppsm_seg_tab[ul_id - 1];
-				if (psma != NULL) {
-					un_register_gppsm_seg(psma);
-					/* Set alctr ptr to NULL for future
-					 * reuse */
-					cmm_mgr_obj->pa_gppsm_seg_tab[ul_id -
-								      1] = NULL;
-				} else if (ul_seg_id != CMM_ALLSEGMENTS) {
-					status = -EPERM;
-				}
-				mutex_unlock(&cmm_mgr_obj->cmm_lock);
-				if (ul_seg_id != CMM_ALLSEGMENTS)
-					break;
-
-				ul_id++;
-			}	/* end while */
-		} else {
-			status = -EINVAL;
+	if (!hcmm_mgr)
+		return -EFAULT;
+
+	if (ul_seg_id == CMM_ALLSEGMENTS)
+		ul_id = 1;
+
+	if ((ul_id <= 0) || (ul_id > CMM_MAXGPPSEGS))
+		return -EINVAL;
+
+	/*
+	 * FIXME: CMM_MAXGPPSEGS == 1. why use a while cycle? Seems to me like
+	 * the ul_seg_id is not needed here. It must be always 1.
+	 */
+	while (ul_id <= CMM_MAXGPPSEGS) {
+		mutex_lock(&cmm_mgr_obj->cmm_lock);
+		/* slot = seg_id-1 */
+		psma = cmm_mgr_obj->pa_gppsm_seg_tab[ul_id - 1];
+		if (psma != NULL) {
+			un_register_gppsm_seg(psma);
+			/* Set alctr ptr to NULL for future reuse */
+			cmm_mgr_obj->pa_gppsm_seg_tab[ul_id - 1] = NULL;
+		} else if (ul_seg_id != CMM_ALLSEGMENTS) {
+			status = -EPERM;
 		}
-	} else {
-		status = -EFAULT;
-	}
+		mutex_unlock(&cmm_mgr_obj->cmm_lock);
+		if (ul_seg_id != CMM_ALLSEGMENTS)
+			break;
+
+		ul_id++;
+	}	/* end while */
 	return status;
 }
 
@@ -687,43 +633,24 @@ int cmm_un_register_gppsm_seg(struct cmm_object *hcmm_mgr,
  */
 static void un_register_gppsm_seg(struct cmm_allocator *psma)
 {
-	struct cmm_mnode *mnode_obj = NULL;
-	struct cmm_mnode *next_node = NULL;
+	struct cmm_mnode *curr, *tmp;
 
 	DBC_REQUIRE(psma != NULL);
-	if (psma->free_list_head != NULL) {
-		/* free nodes on free list */
-		mnode_obj = (struct cmm_mnode *)lst_first(psma->free_list_head);
-		while (mnode_obj) {
-			next_node =
-			    (struct cmm_mnode *)lst_next(psma->free_list_head,
-							 (struct list_head *)
-							 mnode_obj);
-			lst_remove_elem(psma->free_list_head,
-					(struct list_head *)mnode_obj);
-			kfree((void *)mnode_obj);
-			/* next node. */
-			mnode_obj = next_node;
-		}
-		kfree(psma->free_list_head);	/* delete freelist */
-		/* free nodes on InUse list */
-		mnode_obj =
-		    (struct cmm_mnode *)lst_first(psma->in_use_list_head);
-		while (mnode_obj) {
-			next_node =
-			    (struct cmm_mnode *)lst_next(psma->in_use_list_head,
-							 (struct list_head *)
-							 mnode_obj);
-			lst_remove_elem(psma->in_use_list_head,
-					(struct list_head *)mnode_obj);
-			kfree((void *)mnode_obj);
-			/* next node. */
-			mnode_obj = next_node;
-		}
-		kfree(psma->in_use_list_head);	/* delete InUse list */
+
+	/* free nodes on free list */
+	list_for_each_entry_safe(curr, tmp, &psma->free_list, link) {
+		list_del(&curr->link);
+		kfree(curr);
 	}
-	if ((void *)psma->dw_vm_base != NULL)
-		MEM_UNMAP_LINEAR_ADDRESS((void *)psma->dw_vm_base);
+
+	/* free nodes on InUse list */
+	list_for_each_entry_safe(curr, tmp, &psma->in_use_list, link) {
+		list_del(&curr->link);
+		kfree(curr);
+	}
+
+	if ((void *)psma->vm_base != NULL)
+		MEM_UNMAP_LINEAR_ADDRESS((void *)psma->vm_base);
 
 	/* Free allocator itself */
 	kfree(psma);
@@ -758,26 +685,29 @@ static s32 get_slot(struct cmm_object *cmm_mgr_obj)
 static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa,
 				  u32 dw_va, u32 ul_size)
 {
-	struct cmm_mnode *pnode = NULL;
+	struct cmm_mnode *pnode;
 
 	DBC_REQUIRE(cmm_mgr_obj != NULL);
 	DBC_REQUIRE(dw_pa != 0);
 	DBC_REQUIRE(dw_va != 0);
 	DBC_REQUIRE(ul_size != 0);
+
 	/* Check cmm mgr's node freelist */
-	if (LST_IS_EMPTY(cmm_mgr_obj->node_free_list_head)) {
+	if (list_empty(&cmm_mgr_obj->node_free_list)) {
 		pnode = kzalloc(sizeof(struct cmm_mnode), GFP_KERNEL);
+		if (!pnode)
+			return NULL;
 	} else {
 		/* surely a valid element */
-		pnode = (struct cmm_mnode *)
-		    lst_get_head(cmm_mgr_obj->node_free_list_head);
-	}
-	if (pnode) {
-		lst_init_elem((struct list_head *)pnode);	/* set self */
-		pnode->dw_pa = dw_pa;	/* Physical addr of start of block */
-		pnode->dw_va = dw_va;	/* Virtual   "            " */
-		pnode->ul_size = ul_size;	/* Size of block */
+		pnode = list_first_entry(&cmm_mgr_obj->node_free_list,
+				struct cmm_mnode, link);
+		list_del_init(&pnode->link);
 	}
+
+	pnode->pa = dw_pa;
+	pnode->va = dw_va;
+	pnode->size = ul_size;
+
 	return pnode;
 }
 
@@ -790,9 +720,7 @@ static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa,
 static void delete_node(struct cmm_object *cmm_mgr_obj, struct cmm_mnode *pnode)
 {
 	DBC_REQUIRE(pnode != NULL);
-	lst_init_elem((struct list_head *)pnode);	/* init .self ptr */
-	lst_put_tail(cmm_mgr_obj->node_free_list_head,
-		     (struct list_head *)pnode);
+	list_add_tail(&pnode->link, &cmm_mgr_obj->node_free_list);
 }
 
 /*
@@ -804,103 +732,57 @@ static void delete_node(struct cmm_object *cmm_mgr_obj, struct cmm_mnode *pnode)
 static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator,
 					u32 usize)
 {
-	if (allocator) {
-		struct cmm_mnode *mnode_obj = (struct cmm_mnode *)
-		    lst_first(allocator->free_list_head);
-		while (mnode_obj) {
-			if (usize <= (u32) mnode_obj->ul_size) {
-				lst_remove_elem(allocator->free_list_head,
-						(struct list_head *)mnode_obj);
-				return mnode_obj;
-			}
-			/* next node. */
-			mnode_obj = (struct cmm_mnode *)
-			    lst_next(allocator->free_list_head,
-				     (struct list_head *)mnode_obj);
+	struct cmm_mnode *node, *tmp;
+
+	if (!allocator)
+		return NULL;
+
+	list_for_each_entry_safe(node, tmp, &allocator->free_list, link) {
+		if (usize <= node->size) {
+			list_del(&node->link);
+			return node;
 		}
 	}
+
 	return NULL;
 }
 
 /*
  *  ======== add_to_free_list ========
  *  Purpose:
- *      Coelesce node into the freelist in ascending size order.
+ *      Coalesce node into the freelist in ascending size order.
  */
 static void add_to_free_list(struct cmm_allocator *allocator,
-			     struct cmm_mnode *pnode)
+			     struct cmm_mnode *node)
 {
-	struct cmm_mnode *node_prev = NULL;
-	struct cmm_mnode *node_next = NULL;
-	struct cmm_mnode *mnode_obj;
-	u32 dw_this_pa;
-	u32 dw_next_pa;
+	struct cmm_mnode *curr;
 
-	DBC_REQUIRE(pnode != NULL);
-	DBC_REQUIRE(allocator != NULL);
-	dw_this_pa = pnode->dw_pa;
-	dw_next_pa = NEXT_PA(pnode);
-	mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
-	while (mnode_obj) {
-		if (dw_this_pa == NEXT_PA(mnode_obj)) {
-			/* found the block ahead of this one */
-			node_prev = mnode_obj;
-		} else if (dw_next_pa == mnode_obj->dw_pa) {
-			node_next = mnode_obj;
-		}
-		if ((node_prev == NULL) || (node_next == NULL)) {
-			/* next node. */
-			mnode_obj = (struct cmm_mnode *)
-			    lst_next(allocator->free_list_head,
-				     (struct list_head *)mnode_obj);
-		} else {
-			/* got 'em */
-			break;
-		}
-	}			/* while */
-	if (node_prev != NULL) {
-		/* combine with previous block */
-		lst_remove_elem(allocator->free_list_head,
-				(struct list_head *)node_prev);
-		/* grow node to hold both */
-		pnode->ul_size += node_prev->ul_size;
-		pnode->dw_pa = node_prev->dw_pa;
-		pnode->dw_va = node_prev->dw_va;
-		/* place node on mgr nodeFreeList */
-		delete_node((struct cmm_object *)allocator->hcmm_mgr,
-			    node_prev);
-	}
-	if (node_next != NULL) {
-		/* combine with next block */
-		lst_remove_elem(allocator->free_list_head,
-				(struct list_head *)node_next);
-		/* grow da node */
-		pnode->ul_size += node_next->ul_size;
-		/* place node on mgr nodeFreeList */
-		delete_node((struct cmm_object *)allocator->hcmm_mgr,
-			    node_next);
+	if (!node) {
+		pr_err("%s: failed - node is NULL\n", __func__);
+		return;
 	}
-	/* Now, let's add to freelist in increasing size order */
-	mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
-	while (mnode_obj) {
-		if (pnode->ul_size <= mnode_obj->ul_size)
-			break;
 
-		/* next node. */
-		mnode_obj =
-		    (struct cmm_mnode *)lst_next(allocator->free_list_head,
-						 (struct list_head *)mnode_obj);
+	list_for_each_entry(curr, &allocator->free_list, link) {
+		if (NEXT_PA(curr) == node->pa) {
+			curr->size += node->size;
+			delete_node(allocator->cmm_mgr, node);
+			return;
+		}
+		if (curr->pa == NEXT_PA(node)) {
+			curr->pa = node->pa;
+			curr->va = node->va;
+			curr->size += node->size;
+			delete_node(allocator->cmm_mgr, node);
+			return;
+		}
 	}
-	/* if mnode_obj is NULL then add our pnode to the end of the freelist */
-	if (mnode_obj == NULL) {
-		lst_put_tail(allocator->free_list_head,
-			     (struct list_head *)pnode);
-	} else {
-		/* insert our node before the current traversed node */
-		lst_insert_before(allocator->free_list_head,
-				  (struct list_head *)pnode,
-				  (struct list_head *)mnode_obj);
+	list_for_each_entry(curr, &allocator->free_list, link) {
+		if (curr->size >= node->size) {
+			list_add_tail(&node->link, &curr->link);
+			return;
+		}
 	}
+	list_add_tail(&node->link, &allocator->free_list);
 }
 
 /*
@@ -912,19 +794,10 @@ static void add_to_free_list(struct cmm_allocator *allocator,
 static struct cmm_allocator *get_allocator(struct cmm_object *cmm_mgr_obj,
 					   u32 ul_seg_id)
 {
-	struct cmm_allocator *allocator = NULL;
-
 	DBC_REQUIRE(cmm_mgr_obj != NULL);
 	DBC_REQUIRE((ul_seg_id > 0) && (ul_seg_id <= CMM_MAXGPPSEGS));
-	allocator = cmm_mgr_obj->pa_gppsm_seg_tab[ul_seg_id - 1];
-	if (allocator != NULL) {
-		/* make sure it's for real */
-		if (!allocator) {
-			allocator = NULL;
-			DBC_ASSERT(false);
-		}
-	}
-	return allocator;
+
+	return cmm_mgr_obj->pa_gppsm_seg_tab[ul_seg_id - 1];
 }
 
 /*
@@ -955,9 +828,9 @@ int cmm_xlator_create(struct cmm_xlatorobject **xlator,
 
 	xlator_object = kzalloc(sizeof(struct cmm_xlator), GFP_KERNEL);
 	if (xlator_object != NULL) {
-		xlator_object->hcmm_mgr = hcmm_mgr;	/* ref back to CMM */
+		xlator_object->cmm_mgr = hcmm_mgr;	/* ref back to CMM */
 		/* SM seg_id */
-		xlator_object->ul_seg_id = xlator_attrs->ul_seg_id;
+		xlator_object->seg_id = xlator_attrs->seg_id;
 	} else {
 		status = -ENOMEM;
 	}
@@ -980,17 +853,17 @@ void *cmm_xlator_alloc_buf(struct cmm_xlatorobject *xlator, void *va_buf,
 
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(xlator != NULL);
-	DBC_REQUIRE(xlator_obj->hcmm_mgr != NULL);
+	DBC_REQUIRE(xlator_obj->cmm_mgr != NULL);
 	DBC_REQUIRE(va_buf != NULL);
 	DBC_REQUIRE(pa_size > 0);
-	DBC_REQUIRE(xlator_obj->ul_seg_id > 0);
+	DBC_REQUIRE(xlator_obj->seg_id > 0);
 
 	if (xlator_obj) {
-		attrs.ul_seg_id = xlator_obj->ul_seg_id;
+		attrs.seg_id = xlator_obj->seg_id;
 		__raw_writel(0, va_buf);
 		/* Alloc SM */
 		pbuf =
-		    cmm_calloc_buf(xlator_obj->hcmm_mgr, pa_size, &attrs, NULL);
+		    cmm_calloc_buf(xlator_obj->cmm_mgr, pa_size, &attrs, NULL);
 		if (pbuf) {
 			/* convert to translator(node/strm) process Virtual
 			 * address */
@@ -1016,14 +889,14 @@ int cmm_xlator_free_buf(struct cmm_xlatorobject *xlator, void *buf_va)
 
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(buf_va != NULL);
-	DBC_REQUIRE(xlator_obj->ul_seg_id > 0);
+	DBC_REQUIRE(xlator_obj->seg_id > 0);
 
 	if (xlator_obj) {
 		/* convert Va to Pa so we can free it. */
 		buf_pa = cmm_xlator_translate(xlator, buf_va, CMM_VA2PA);
 		if (buf_pa) {
-			status = cmm_free_buf(xlator_obj->hcmm_mgr, buf_pa,
-					      xlator_obj->ul_seg_id);
+			status = cmm_free_buf(xlator_obj->cmm_mgr, buf_pa,
+					      xlator_obj->seg_id);
 			if (status) {
 				/* Uh oh, this shouldn't happen. Descriptor
 				 * gone! */
@@ -1052,10 +925,10 @@ int cmm_xlator_info(struct cmm_xlatorobject *xlator, u8 ** paddr,
 	if (xlator_obj) {
 		if (set_info) {
 			/* set translators virtual address range */
-			xlator_obj->dw_virt_base = (u32) *paddr;
-			xlator_obj->ul_virt_size = ul_size;
+			xlator_obj->virt_base = (u32) *paddr;
+			xlator_obj->virt_size = ul_size;
 		} else {	/* return virt base address */
-			*paddr = (u8 *) xlator_obj->dw_virt_base;
+			*paddr = (u8 *) xlator_obj->virt_base;
 		}
 	} else {
 		status = -EFAULT;
@@ -1082,10 +955,10 @@ void *cmm_xlator_translate(struct cmm_xlatorobject *xlator, void *paddr,
 	if (!xlator_obj)
 		goto loop_cont;
 
-	cmm_mgr_obj = (struct cmm_object *)xlator_obj->hcmm_mgr;
+	cmm_mgr_obj = (struct cmm_object *)xlator_obj->cmm_mgr;
 	/* get this translator's default SM allocator */
-	DBC_ASSERT(xlator_obj->ul_seg_id > 0);
-	allocator = cmm_mgr_obj->pa_gppsm_seg_tab[xlator_obj->ul_seg_id - 1];
+	DBC_ASSERT(xlator_obj->seg_id > 0);
+	allocator = cmm_mgr_obj->pa_gppsm_seg_tab[xlator_obj->seg_id - 1];
 	if (!allocator)
 		goto loop_cont;
 
@@ -1095,21 +968,21 @@ void *cmm_xlator_translate(struct cmm_xlatorobject *xlator, void *paddr,
 			/* Gpp Va = Va Base + offset */
 			dw_offset = (u8 *) paddr - (u8 *) (allocator->shm_base -
 							   allocator->
-							   ul_dsp_size);
-			dw_addr_xlate = xlator_obj->dw_virt_base + dw_offset;
+							   dsp_size);
+			dw_addr_xlate = xlator_obj->virt_base + dw_offset;
 			/* Check if translated Va base is in range */
-			if ((dw_addr_xlate < xlator_obj->dw_virt_base) ||
+			if ((dw_addr_xlate < xlator_obj->virt_base) ||
 			    (dw_addr_xlate >=
-			     (xlator_obj->dw_virt_base +
-			      xlator_obj->ul_virt_size))) {
+			     (xlator_obj->virt_base +
+			      xlator_obj->virt_size))) {
 				dw_addr_xlate = 0;	/* bad address */
 			}
 		} else {
 			/* Gpp PA =  Gpp Base + offset */
 			dw_offset =
-			    (u8 *) paddr - (u8 *) xlator_obj->dw_virt_base;
+			    (u8 *) paddr - (u8 *) xlator_obj->virt_base;
 			dw_addr_xlate =
-			    allocator->shm_base - allocator->ul_dsp_size +
+			    allocator->shm_base - allocator->dsp_size +
 			    dw_offset;
 		}
 	} else {
@@ -1119,16 +992,16 @@ void *cmm_xlator_translate(struct cmm_xlatorobject *xlator, void *paddr,
 	if ((xtype == CMM_VA2DSPPA) || (xtype == CMM_PA2DSPPA)) {
 		/* Got Gpp Pa now, convert to DSP Pa */
 		dw_addr_xlate =
-		    GPPPA2DSPPA((allocator->shm_base - allocator->ul_dsp_size),
+		    GPPPA2DSPPA((allocator->shm_base - allocator->dsp_size),
 				dw_addr_xlate,
-				allocator->dw_dsp_phys_addr_offset *
+				allocator->dsp_phys_addr_offset *
 				allocator->c_factor);
 	} else if (xtype == CMM_DSPPA2PA) {
 		/* Got DSP Pa, convert to GPP Pa */
 		dw_addr_xlate =
-		    DSPPA2GPPPA(allocator->shm_base - allocator->ul_dsp_size,
+		    DSPPA2GPPPA(allocator->shm_base - allocator->dsp_size,
 				dw_addr_xlate,
-				allocator->dw_dsp_phys_addr_offset *
+				allocator->dsp_phys_addr_offset *
 				allocator->c_factor);
 	}
 loop_cont:
diff --git a/drivers/staging/tidspbridge/pmgr/cod.c b/drivers/staging/tidspbridge/pmgr/cod.c
index 52989ab..1a29264 100644
--- a/drivers/staging/tidspbridge/pmgr/cod.c
+++ b/drivers/staging/tidspbridge/pmgr/cod.c
@@ -33,9 +33,6 @@
 /*  ----------------------------------- Trace & Debug */
 #include <dspbridge/dbc.h>
 
-/*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/ldr.h>
-
 /*  ----------------------------------- Platform Manager */
 /* Include appropriate loader header file */
 #include <dspbridge/dbll.h>
@@ -50,8 +47,7 @@ struct cod_manager {
 	struct dbll_tar_obj *target;
 	struct dbll_library_obj *base_lib;
 	bool loaded;		/* Base library loaded? */
-	u32 ul_entry;
-	struct ldr_module *dll_obj;
+	u32 entry;
 	struct dbll_fxns fxns;
 	struct dbll_attrs attrs;
 	char sz_zl_file[COD_MAXPATHLENGTH];
@@ -78,12 +74,9 @@ static struct dbll_fxns ldr_fxns = {
 	(dbll_get_sect_fxn) dbll_get_sect,
 	(dbll_init_fxn) dbll_init,
 	(dbll_load_fxn) dbll_load,
-	(dbll_load_sect_fxn) dbll_load_sect,
 	(dbll_open_fxn) dbll_open,
 	(dbll_read_sect_fxn) dbll_read_sect,
-	(dbll_set_attrs_fxn) dbll_set_attrs,
 	(dbll_unload_fxn) dbll_unload,
-	(dbll_unload_sect_fxn) dbll_unload_sect,
 };
 
 static bool no_op(void);
@@ -209,8 +202,7 @@ void cod_close(struct cod_libraryobj *lib)
  *      dynamically loaded object files.
  *
  */
-int cod_create(struct cod_manager **mgr, char *str_zl_file,
-		      const struct cod_attrs *attrs)
+int cod_create(struct cod_manager **mgr, char *str_zl_file)
 {
 	struct cod_manager *mgr_new;
 	struct dbll_attrs zl_attrs;
@@ -222,10 +214,6 @@ int cod_create(struct cod_manager **mgr, char *str_zl_file,
 	/* assume failure */
 	*mgr = NULL;
 
-	/* we don't support non-default attrs yet */
-	if (attrs != NULL)
-		return -ENOSYS;
-
 	mgr_new = kzalloc(sizeof(struct cod_manager), GFP_KERNEL);
 	if (mgr_new == NULL)
 		return -ENOMEM;
@@ -358,7 +346,7 @@ int cod_get_entry(struct cod_manager *cod_mgr_obj, u32 *entry_pt)
 	DBC_REQUIRE(cod_mgr_obj);
 	DBC_REQUIRE(entry_pt != NULL);
 
-	*entry_pt = cod_mgr_obj->ul_entry;
+	*entry_pt = cod_mgr_obj->entry;
 
 	return 0;
 }
@@ -528,7 +516,7 @@ int cod_load_base(struct cod_manager *cod_mgr_obj, u32 num_argc, char *args[],
 	flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
 	status = cod_mgr_obj->fxns.load_fxn(cod_mgr_obj->base_lib, flags,
 					    &new_attrs,
-					    &cod_mgr_obj->ul_entry);
+					    &cod_mgr_obj->entry);
 	if (status)
 		cod_mgr_obj->fxns.close_fxn(cod_mgr_obj->base_lib);
 
diff --git a/drivers/staging/tidspbridge/pmgr/dbll.c b/drivers/staging/tidspbridge/pmgr/dbll.c
index 878aa50..31da62b 100644
--- a/drivers/staging/tidspbridge/pmgr/dbll.c
+++ b/drivers/staging/tidspbridge/pmgr/dbll.c
@@ -123,7 +123,7 @@ struct dbll_library_obj {
 	u32 open_ref;		/* Number of times opened */
 	u32 load_ref;		/* Number of times loaded */
 	struct gh_t_hash_tab *sym_tab;	/* Hash table of symbols */
-	u32 ul_pos;
+	u32 pos;
 };
 
 /*
@@ -272,8 +272,7 @@ void dbll_delete(struct dbll_tar_obj *target)
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(zl_target);
 
-	if (zl_target != NULL)
-		kfree(zl_target);
+	kfree(zl_target);
 
 }
 
@@ -398,7 +397,7 @@ int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr,
 
 		} else {
 			(*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
-							      zl_lib->ul_pos,
+							      zl_lib->pos,
 							      SEEK_SET);
 		}
 	} else {
@@ -522,7 +521,7 @@ int dbll_load(struct dbll_library_obj *lib, dbll_flags flags,
 
 		}
 		if (!status) {
-			zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell))
+			zl_lib->pos = (*(zl_lib->target_obj->attrs.ftell))
 			    (zl_lib->fp);
 			/* Reset file cursor */
 			(*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
@@ -568,18 +567,6 @@ int dbll_load(struct dbll_library_obj *lib, dbll_flags flags,
 }
 
 /*
- *  ======== dbll_load_sect ========
- *  Not supported for COFF.
- */
-int dbll_load_sect(struct dbll_library_obj *zl_lib, char *sec_name,
-			  struct dbll_attrs *attrs)
-{
-	DBC_REQUIRE(zl_lib);
-
-	return -ENOSYS;
-}
-
-/*
  *  ======== dbll_open ========
  */
 int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
@@ -611,7 +598,7 @@ int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
 		if (zl_lib == NULL) {
 			status = -ENOMEM;
 		} else {
-			zl_lib->ul_pos = 0;
+			zl_lib->pos = 0;
 			/* Increment ref count to allow close on failure
 			 * later on */
 			zl_lib->open_ref++;
@@ -661,7 +648,7 @@ int dbll_open(struct dbll_tar_obj *target, char *file, dbll_flags flags,
 	if (!status && zl_lib->fp == NULL)
 		status = dof_open(zl_lib);
 
-	zl_lib->ul_pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp);
+	zl_lib->pos = (*(zl_lib->target_obj->attrs.ftell)) (zl_lib->fp);
 	(*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, (long)0, SEEK_SET);
 	/* Create a hash table for symbols if flag is set */
 	if (zl_lib->sym_tab != NULL || !(flags & DBLL_SYMB))
@@ -750,7 +737,7 @@ int dbll_read_sect(struct dbll_library_obj *lib, char *name,
 
 		} else {
 			(*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp,
-							      zl_lib->ul_pos,
+							      zl_lib->pos,
 							      SEEK_SET);
 		}
 	} else {
@@ -794,22 +781,6 @@ func_cont:
 }
 
 /*
- *  ======== dbll_set_attrs ========
- *  Set the attributes of the target.
- */
-void dbll_set_attrs(struct dbll_tar_obj *target, struct dbll_attrs *pattrs)
-{
-	struct dbll_tar_obj *zl_target = (struct dbll_tar_obj *)target;
-	DBC_REQUIRE(refs > 0);
-	DBC_REQUIRE(zl_target);
-	DBC_REQUIRE(pattrs != NULL);
-
-	if ((pattrs != NULL) && (zl_target != NULL))
-		zl_target->attrs = *pattrs;
-
-}
-
-/*
  *  ======== dbll_unload ========
  */
 void dbll_unload(struct dbll_library_obj *lib, struct dbll_attrs *attrs)
@@ -848,19 +819,6 @@ func_end:
 }
 
 /*
- *  ======== dbll_unload_sect ========
- *  Not supported for COFF.
- */
-int dbll_unload_sect(struct dbll_library_obj *lib, char *sec_name,
-			    struct dbll_attrs *attrs)
-{
-	DBC_REQUIRE(refs > 0);
-	DBC_REQUIRE(sec_name != NULL);
-
-	return -ENOSYS;
-}
-
-/*
  *  ======== dof_close ========
  */
 static void dof_close(struct dbll_library_obj *zl_lib)
diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c
index 132e960..9a38d86 100644
--- a/drivers/staging/tidspbridge/pmgr/dev.c
+++ b/drivers/staging/tidspbridge/pmgr/dev.c
@@ -16,6 +16,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 #include <linux/types.h>
+#include <linux/list.h>
 
 /*  ----------------------------------- Host OS */
 #include <dspbridge/host_os.h>
@@ -26,10 +27,6 @@
 /*  ----------------------------------- Trace & Debug */
 #include <dspbridge/dbc.h>
 
-/*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/ldr.h>
-#include <dspbridge/list.h>
-
 /*  ----------------------------------- Platform Manager */
 #include <dspbridge/cod.h>
 #include <dspbridge/drv.h>
@@ -60,28 +57,26 @@
 
 /* The Bridge device object: */
 struct dev_object {
-	/* LST requires "link" to be first field! */
 	struct list_head link;	/* Link to next dev_object. */
 	u8 dev_type;		/* Device Type */
 	struct cfg_devnode *dev_node_obj;	/* Platform specific dev id */
 	/* Bridge Context Handle */
-	struct bridge_dev_context *hbridge_context;
+	struct bridge_dev_context *bridge_context;
 	/* Function interface to Bridge driver. */
 	struct bridge_drv_interface bridge_interface;
 	struct brd_object *lock_owner;	/* Client with exclusive access. */
 	struct cod_manager *cod_mgr;	/* Code manager handle. */
-	struct chnl_mgr *hchnl_mgr;	/* Channel manager. */
-	struct deh_mgr *hdeh_mgr;	/* DEH manager. */
-	struct msg_mgr *hmsg_mgr;	/* Message manager. */
-	struct io_mgr *hio_mgr;	/* IO manager (CHNL, msg_ctrl) */
-	struct cmm_object *hcmm_mgr;	/* SM memory manager. */
+	struct chnl_mgr *chnl_mgr;	/* Channel manager. */
+	struct deh_mgr *deh_mgr;	/* DEH manager. */
+	struct msg_mgr *msg_mgr;	/* Message manager. */
+	struct io_mgr *iomgr;	/* IO manager (CHNL, msg_ctrl) */
+	struct cmm_object *cmm_mgr;	/* SM memory manager. */
 	struct dmm_object *dmm_mgr;	/* Dynamic memory manager. */
-	struct ldr_module *module_obj;	/* Bridge Module handle. */
 	u32 word_size;		/* DSP word size: quick access. */
-	struct drv_object *hdrv_obj;	/* Driver Object */
-	struct lst_list *proc_list;	/* List of Proceeosr attached to
-					 * this device */
-	struct node_mgr *hnode_mgr;
+	struct drv_object *drv_obj;	/* Driver Object */
+	/* List of Processors attached to this device */
+	struct list_head proc_list;
+	struct node_mgr *node_mgr;
 };
 
 struct drv_ext {
@@ -115,9 +110,9 @@ u32 dev_brd_write_fxn(void *arb, u32 dsp_add, void *host_buf,
 	DBC_REQUIRE(host_buf != NULL);	/* Required of BrdWrite(). */
 	if (dev_obj) {
 		/* Require of BrdWrite() */
-		DBC_ASSERT(dev_obj->hbridge_context != NULL);
-		status = (*dev_obj->bridge_interface.pfn_brd_write) (
-					dev_obj->hbridge_context, host_buf,
+		DBC_ASSERT(dev_obj->bridge_context != NULL);
+		status = (*dev_obj->bridge_interface.brd_write) (
+					dev_obj->bridge_context, host_buf,
 					dsp_add, ul_num_bytes, mem_space);
 		/* Special case of getting the address only */
 		if (ul_num_bytes == 0)
@@ -140,7 +135,6 @@ int dev_create_device(struct dev_object **device_obj,
 			     struct cfg_devnode *dev_node_obj)
 {
 	struct cfg_hostres *host_res;
-	struct ldr_module *module_obj = NULL;
 	struct bridge_drv_interface *drv_fxns = NULL;
 	struct dev_object *dev_obj = NULL;
 	struct chnl_mgrattrs mgr_attrs;
@@ -180,13 +174,12 @@ int dev_create_device(struct dev_object **device_obj,
 		if (dev_obj) {
 			/* Fill out the rest of the Dev Object structure: */
 			dev_obj->dev_node_obj = dev_node_obj;
-			dev_obj->module_obj = module_obj;
 			dev_obj->cod_mgr = NULL;
-			dev_obj->hchnl_mgr = NULL;
-			dev_obj->hdeh_mgr = NULL;
+			dev_obj->chnl_mgr = NULL;
+			dev_obj->deh_mgr = NULL;
 			dev_obj->lock_owner = NULL;
 			dev_obj->word_size = DSPWORDSIZE;
-			dev_obj->hdrv_obj = hdrv_obj;
+			dev_obj->drv_obj = hdrv_obj;
 			dev_obj->dev_type = DSP_UNIT;
 			/* Store this Bridge's interface functions, based on its
 			 * version. */
@@ -195,12 +188,12 @@ int dev_create_device(struct dev_object **device_obj,
 
 			/* Call fxn_dev_create() to get the Bridge's device
 			 * context handle. */
-			status = (dev_obj->bridge_interface.pfn_dev_create)
-			    (&dev_obj->hbridge_context, dev_obj,
+			status = (dev_obj->bridge_interface.dev_create)
+			    (&dev_obj->bridge_context, dev_obj,
 			     host_res);
 			/* Assert bridge_dev_create()'s ensure clause: */
 			DBC_ASSERT(status
-				   || (dev_obj->hbridge_context != NULL));
+				   || (dev_obj->bridge_context != NULL));
 		} else {
 			status = -ENOMEM;
 		}
@@ -220,54 +213,47 @@ int dev_create_device(struct dev_object **device_obj,
 		num_windows = host_res->num_mem_windows;
 		if (num_windows) {
 			/* Assume last memory window is for CHNL */
-			io_mgr_attrs.shm_base = host_res->dw_mem_base[1] +
-			    host_res->dw_offset_for_monitor;
-			io_mgr_attrs.usm_length =
-			    host_res->dw_mem_length[1] -
-			    host_res->dw_offset_for_monitor;
+			io_mgr_attrs.shm_base = host_res->mem_base[1] +
+			    host_res->offset_for_monitor;
+			io_mgr_attrs.sm_length =
+			    host_res->mem_length[1] -
+			    host_res->offset_for_monitor;
 		} else {
 			io_mgr_attrs.shm_base = 0;
-			io_mgr_attrs.usm_length = 0;
+			io_mgr_attrs.sm_length = 0;
 			pr_err("%s: No memory reserved for shared structures\n",
 			       __func__);
 		}
-		status = chnl_create(&dev_obj->hchnl_mgr, dev_obj, &mgr_attrs);
+		status = chnl_create(&dev_obj->chnl_mgr, dev_obj, &mgr_attrs);
 		if (status == -ENOSYS) {
 			/* It's OK for a device not to have a channel
 			 * manager: */
 			status = 0;
 		}
 		/* Create CMM mgr even if Msg Mgr not impl. */
-		status = cmm_create(&dev_obj->hcmm_mgr,
+		status = cmm_create(&dev_obj->cmm_mgr,
 				    (struct dev_object *)dev_obj, NULL);
 		/* Only create IO manager if we have a channel manager */
-		if (!status && dev_obj->hchnl_mgr) {
-			status = io_create(&dev_obj->hio_mgr, dev_obj,
+		if (!status && dev_obj->chnl_mgr) {
+			status = io_create(&dev_obj->iomgr, dev_obj,
 					   &io_mgr_attrs);
 		}
 		/* Only create DEH manager if we have an IO manager */
 		if (!status) {
 			/* Instantiate the DEH module */
-			status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj);
+			status = bridge_deh_create(&dev_obj->deh_mgr, dev_obj);
 		}
 		/* Create DMM mgr . */
 		status = dmm_create(&dev_obj->dmm_mgr,
 				    (struct dev_object *)dev_obj, NULL);
 	}
 	/* Add the new DEV_Object to the global list: */
-	if (!status) {
-		lst_init_elem(&dev_obj->link);
+	if (!status)
 		status = drv_insert_dev_object(hdrv_obj, dev_obj);
-	}
+
 	/* Create the Processor List */
-	if (!status) {
-		dev_obj->proc_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		if (!(dev_obj->proc_list))
-			status = -EPERM;
-		else
-			INIT_LIST_HEAD(&dev_obj->proc_list->head);
-	}
+	if (!status)
+		INIT_LIST_HEAD(&dev_obj->proc_list);
 leave:
 	/*  If all went well, return a handle to the dev object;
 	 *  else, cleanup and return NULL in the OUT parameter. */
@@ -275,7 +261,6 @@ leave:
 		*device_obj = dev_obj;
 	} else {
 		if (dev_obj) {
-			kfree(dev_obj->proc_list);
 			if (dev_obj->cod_mgr)
 				cod_delete(dev_obj->cod_mgr);
 			if (dev_obj->dmm_mgr)
@@ -306,13 +291,13 @@ int dev_create2(struct dev_object *hdev_obj)
 	DBC_REQUIRE(hdev_obj);
 
 	/* There can be only one Node Manager per DEV object */
-	DBC_ASSERT(!dev_obj->hnode_mgr);
-	status = node_create_mgr(&dev_obj->hnode_mgr, hdev_obj);
+	DBC_ASSERT(!dev_obj->node_mgr);
+	status = node_create_mgr(&dev_obj->node_mgr, hdev_obj);
 	if (status)
-		dev_obj->hnode_mgr = NULL;
+		dev_obj->node_mgr = NULL;
 
-	DBC_ENSURE((!status && dev_obj->hnode_mgr != NULL)
-		   || (status && dev_obj->hnode_mgr == NULL));
+	DBC_ENSURE((!status && dev_obj->node_mgr != NULL)
+		   || (status && dev_obj->node_mgr == NULL));
 	return status;
 }
 
@@ -329,15 +314,15 @@ int dev_destroy2(struct dev_object *hdev_obj)
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(hdev_obj);
 
-	if (dev_obj->hnode_mgr) {
-		if (node_delete_mgr(dev_obj->hnode_mgr))
+	if (dev_obj->node_mgr) {
+		if (node_delete_mgr(dev_obj->node_mgr))
 			status = -EPERM;
 		else
-			dev_obj->hnode_mgr = NULL;
+			dev_obj->node_mgr = NULL;
 
 	}
 
-	DBC_ENSURE((!status && dev_obj->hnode_mgr == NULL) || status);
+	DBC_ENSURE((!status && dev_obj->node_mgr == NULL) || status);
 	return status;
 }
 
@@ -360,33 +345,33 @@ int dev_destroy_device(struct dev_object *hdev_obj)
 			dev_obj->cod_mgr = NULL;
 		}
 
-		if (dev_obj->hnode_mgr) {
-			node_delete_mgr(dev_obj->hnode_mgr);
-			dev_obj->hnode_mgr = NULL;
+		if (dev_obj->node_mgr) {
+			node_delete_mgr(dev_obj->node_mgr);
+			dev_obj->node_mgr = NULL;
 		}
 
 		/* Free the io, channel, and message managers for this board: */
-		if (dev_obj->hio_mgr) {
-			io_destroy(dev_obj->hio_mgr);
-			dev_obj->hio_mgr = NULL;
+		if (dev_obj->iomgr) {
+			io_destroy(dev_obj->iomgr);
+			dev_obj->iomgr = NULL;
 		}
-		if (dev_obj->hchnl_mgr) {
-			chnl_destroy(dev_obj->hchnl_mgr);
-			dev_obj->hchnl_mgr = NULL;
+		if (dev_obj->chnl_mgr) {
+			chnl_destroy(dev_obj->chnl_mgr);
+			dev_obj->chnl_mgr = NULL;
 		}
-		if (dev_obj->hmsg_mgr) {
-			msg_delete(dev_obj->hmsg_mgr);
-			dev_obj->hmsg_mgr = NULL;
+		if (dev_obj->msg_mgr) {
+			msg_delete(dev_obj->msg_mgr);
+			dev_obj->msg_mgr = NULL;
 		}
 
-		if (dev_obj->hdeh_mgr) {
+		if (dev_obj->deh_mgr) {
 			/* Uninitialize DEH module. */
-			bridge_deh_destroy(dev_obj->hdeh_mgr);
-			dev_obj->hdeh_mgr = NULL;
+			bridge_deh_destroy(dev_obj->deh_mgr);
+			dev_obj->deh_mgr = NULL;
 		}
-		if (dev_obj->hcmm_mgr) {
-			cmm_destroy(dev_obj->hcmm_mgr, true);
-			dev_obj->hcmm_mgr = NULL;
+		if (dev_obj->cmm_mgr) {
+			cmm_destroy(dev_obj->cmm_mgr, true);
+			dev_obj->cmm_mgr = NULL;
 		}
 
 		if (dev_obj->dmm_mgr) {
@@ -396,18 +381,15 @@ int dev_destroy_device(struct dev_object *hdev_obj)
 
 		/* Call the driver's bridge_dev_destroy() function: */
 		/* Require of DevDestroy */
-		if (dev_obj->hbridge_context) {
-			status = (*dev_obj->bridge_interface.pfn_dev_destroy)
-			    (dev_obj->hbridge_context);
-			dev_obj->hbridge_context = NULL;
+		if (dev_obj->bridge_context) {
+			status = (*dev_obj->bridge_interface.dev_destroy)
+			    (dev_obj->bridge_context);
+			dev_obj->bridge_context = NULL;
 		} else
 			status = -EPERM;
 		if (!status) {
-			kfree(dev_obj->proc_list);
-			dev_obj->proc_list = NULL;
-
 			/* Remove this DEV_Object from the global list: */
-			drv_remove_dev_object(dev_obj->hdrv_obj, dev_obj);
+			drv_remove_dev_object(dev_obj->drv_obj, dev_obj);
 			/* Free The library * LDR_FreeModule
 			 * (dev_obj->module_obj); */
 			/* Free this dev object: */
@@ -437,7 +419,7 @@ int dev_get_chnl_mgr(struct dev_object *hdev_obj,
 	DBC_REQUIRE(mgr != NULL);
 
 	if (hdev_obj) {
-		*mgr = dev_obj->hchnl_mgr;
+		*mgr = dev_obj->chnl_mgr;
 	} else {
 		*mgr = NULL;
 		status = -EFAULT;
@@ -463,7 +445,7 @@ int dev_get_cmm_mgr(struct dev_object *hdev_obj,
 	DBC_REQUIRE(mgr != NULL);
 
 	if (hdev_obj) {
-		*mgr = dev_obj->hcmm_mgr;
+		*mgr = dev_obj->cmm_mgr;
 	} else {
 		*mgr = NULL;
 		status = -EFAULT;
@@ -536,7 +518,7 @@ int dev_get_deh_mgr(struct dev_object *hdev_obj,
 	DBC_REQUIRE(deh_manager != NULL);
 	DBC_REQUIRE(hdev_obj);
 	if (hdev_obj) {
-		*deh_manager = hdev_obj->hdeh_mgr;
+		*deh_manager = hdev_obj->deh_mgr;
 	} else {
 		*deh_manager = NULL;
 		status = -EFAULT;
@@ -623,7 +605,7 @@ int dev_get_io_mgr(struct dev_object *hdev_obj,
 	DBC_REQUIRE(hdev_obj);
 
 	if (hdev_obj) {
-		*io_man = hdev_obj->hio_mgr;
+		*io_man = hdev_obj->iomgr;
 	} else {
 		*io_man = NULL;
 		status = -EFAULT;
@@ -660,7 +642,7 @@ void dev_get_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr **msg_man)
 	DBC_REQUIRE(msg_man != NULL);
 	DBC_REQUIRE(hdev_obj);
 
-	*msg_man = hdev_obj->hmsg_mgr;
+	*msg_man = hdev_obj->msg_mgr;
 }
 
 /*
@@ -678,7 +660,7 @@ int dev_get_node_manager(struct dev_object *hdev_obj,
 	DBC_REQUIRE(node_man != NULL);
 
 	if (hdev_obj) {
-		*node_man = dev_obj->hnode_mgr;
+		*node_man = dev_obj->node_mgr;
 	} else {
 		*node_man = NULL;
 		status = -EFAULT;
@@ -728,7 +710,7 @@ int dev_get_bridge_context(struct dev_object *hdev_obj,
 	DBC_REQUIRE(phbridge_context != NULL);
 
 	if (hdev_obj) {
-		*phbridge_context = dev_obj->hbridge_context;
+		*phbridge_context = dev_obj->bridge_context;
 	} else {
 		*phbridge_context = NULL;
 		status = -EFAULT;
@@ -799,20 +781,18 @@ bool dev_init(void)
  *  Purpose:
  *      Notify all clients of this device of a change in device status.
  */
-int dev_notify_clients(struct dev_object *hdev_obj, u32 ret)
+int dev_notify_clients(struct dev_object *dev_obj, u32 ret)
 {
-	int status = 0;
-
-	struct dev_object *dev_obj = hdev_obj;
-	void *proc_obj;
+	struct list_head *curr;
 
-	for (proc_obj = (void *)lst_first(dev_obj->proc_list);
-	     proc_obj != NULL;
-	     proc_obj = (void *)lst_next(dev_obj->proc_list,
-					 (struct list_head *)proc_obj))
-		proc_notify_clients(proc_obj, (u32) ret);
+	/*
+	 * FIXME: this code needs struct proc_object to have a list_head
+	 * at the begining. If not, this can go horribly wrong.
+	 */
+	list_for_each(curr, &dev_obj->proc_list)
+		proc_notify_clients((void *)curr, ret);
 
-	return status;
+	return 0;
 }
 
 /*
@@ -864,11 +844,11 @@ int dev_set_chnl_mgr(struct dev_object *hdev_obj,
 	DBC_REQUIRE(refs > 0);
 
 	if (hdev_obj)
-		dev_obj->hchnl_mgr = hmgr;
+		dev_obj->chnl_mgr = hmgr;
 	else
 		status = -EFAULT;
 
-	DBC_ENSURE(status || (dev_obj->hchnl_mgr == hmgr));
+	DBC_ENSURE(status || (dev_obj->chnl_mgr == hmgr));
 	return status;
 }
 
@@ -882,7 +862,7 @@ void dev_set_msg_mgr(struct dev_object *hdev_obj, struct msg_mgr *hmgr)
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(hdev_obj);
 
-	hdev_obj->hmsg_mgr = hmgr;
+	hdev_obj->msg_mgr = hmgr;
 }
 
 /*
@@ -894,7 +874,7 @@ int dev_start_device(struct cfg_devnode *dev_node_obj)
 {
 	struct dev_object *hdev_obj = NULL;	/* handle to 'Bridge Device */
 	/* Bridge driver filename */
-	char bridge_file_name[CFG_MAXSEARCHPATHLEN] = "UMA";
+	char *bridge_file_name = "UMA";
 	int status;
 	struct mgr_object *hmgr_obj = NULL;
 	struct drv_data *drv_datap = dev_get_drvdata(bridge);
@@ -967,7 +947,7 @@ static int init_cod_mgr(struct dev_object *dev_obj)
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(!dev_obj || (dev_obj->cod_mgr == NULL));
 
-	status = cod_create(&dev_obj->cod_mgr, sz_dummy_file, NULL);
+	status = cod_create(&dev_obj->cod_mgr, sz_dummy_file);
 
 	return status;
 }
@@ -994,23 +974,23 @@ static int init_cod_mgr(struct dev_object *dev_obj)
 int dev_insert_proc_object(struct dev_object *hdev_obj,
 				  u32 proc_obj, bool *already_attached)
 {
-	int status = 0;
 	struct dev_object *dev_obj = (struct dev_object *)hdev_obj;
 
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(dev_obj);
 	DBC_REQUIRE(proc_obj != 0);
-	DBC_REQUIRE(dev_obj->proc_list != NULL);
 	DBC_REQUIRE(already_attached != NULL);
-	if (!LST_IS_EMPTY(dev_obj->proc_list))
+	if (!list_empty(&dev_obj->proc_list))
 		*already_attached = true;
 
 	/* Add DevObject to tail. */
-	lst_put_tail(dev_obj->proc_list, (struct list_head *)proc_obj);
-
-	DBC_ENSURE(!status && !LST_IS_EMPTY(dev_obj->proc_list));
+	/*
+	 * FIXME: this code needs struct proc_object to have a list_head
+	 * at the begining. If not, this can go horribly wrong.
+	 */
+	list_add_tail((struct list_head *)proc_obj, &dev_obj->proc_list);
 
-	return status;
+	return 0;
 }
 
 /*
@@ -1039,15 +1019,12 @@ int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
 
 	DBC_REQUIRE(dev_obj);
 	DBC_REQUIRE(proc_obj != 0);
-	DBC_REQUIRE(dev_obj->proc_list != NULL);
-	DBC_REQUIRE(!LST_IS_EMPTY(dev_obj->proc_list));
+	DBC_REQUIRE(!list_empty(&dev_obj->proc_list));
 
 	/* Search list for dev_obj: */
-	for (cur_elem = lst_first(dev_obj->proc_list); cur_elem != NULL;
-	     cur_elem = lst_next(dev_obj->proc_list, cur_elem)) {
-		/* If found, remove it. */
+	list_for_each(cur_elem, &dev_obj->proc_list) {
 		if ((u32) cur_elem == proc_obj) {
-			lst_remove_elem(dev_obj->proc_list, cur_elem);
+			list_del(cur_elem);
 			status = 0;
 			break;
 		}
@@ -1056,14 +1033,10 @@ int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
 	return status;
 }
 
-int dev_get_dev_type(struct dev_object *device_obj, u8 *dev_type)
+int dev_get_dev_type(struct dev_object *dev_obj, u8 *dev_type)
 {
-	int status = 0;
-	struct dev_object *dev_obj = (struct dev_object *)device_obj;
-
 	*dev_type = dev_obj->dev_type;
-
-	return status;
+	return 0;
 }
 
 /*
@@ -1106,73 +1079,73 @@ static void store_interface_fxns(struct bridge_drv_interface *drv_fxns,
 	intf_fxns->brd_api_minor_version = drv_fxns->brd_api_minor_version;
 	/* Install functions up to DSP API version .80 (first alpha): */
 	if (bridge_version > 0) {
-		STORE_FXN(fxn_dev_create, pfn_dev_create);
-		STORE_FXN(fxn_dev_destroy, pfn_dev_destroy);
-		STORE_FXN(fxn_dev_ctrl, pfn_dev_cntrl);
-		STORE_FXN(fxn_brd_monitor, pfn_brd_monitor);
-		STORE_FXN(fxn_brd_start, pfn_brd_start);
-		STORE_FXN(fxn_brd_stop, pfn_brd_stop);
-		STORE_FXN(fxn_brd_status, pfn_brd_status);
-		STORE_FXN(fxn_brd_read, pfn_brd_read);
-		STORE_FXN(fxn_brd_write, pfn_brd_write);
-		STORE_FXN(fxn_brd_setstate, pfn_brd_set_state);
-		STORE_FXN(fxn_brd_memcopy, pfn_brd_mem_copy);
-		STORE_FXN(fxn_brd_memwrite, pfn_brd_mem_write);
-		STORE_FXN(fxn_brd_memmap, pfn_brd_mem_map);
-		STORE_FXN(fxn_brd_memunmap, pfn_brd_mem_un_map);
-		STORE_FXN(fxn_chnl_create, pfn_chnl_create);
-		STORE_FXN(fxn_chnl_destroy, pfn_chnl_destroy);
-		STORE_FXN(fxn_chnl_open, pfn_chnl_open);
-		STORE_FXN(fxn_chnl_close, pfn_chnl_close);
-		STORE_FXN(fxn_chnl_addioreq, pfn_chnl_add_io_req);
-		STORE_FXN(fxn_chnl_getioc, pfn_chnl_get_ioc);
-		STORE_FXN(fxn_chnl_cancelio, pfn_chnl_cancel_io);
-		STORE_FXN(fxn_chnl_flushio, pfn_chnl_flush_io);
-		STORE_FXN(fxn_chnl_getinfo, pfn_chnl_get_info);
-		STORE_FXN(fxn_chnl_getmgrinfo, pfn_chnl_get_mgr_info);
-		STORE_FXN(fxn_chnl_idle, pfn_chnl_idle);
-		STORE_FXN(fxn_chnl_registernotify, pfn_chnl_register_notify);
-		STORE_FXN(fxn_io_create, pfn_io_create);
-		STORE_FXN(fxn_io_destroy, pfn_io_destroy);
-		STORE_FXN(fxn_io_onloaded, pfn_io_on_loaded);
-		STORE_FXN(fxn_io_getprocload, pfn_io_get_proc_load);
-		STORE_FXN(fxn_msg_create, pfn_msg_create);
-		STORE_FXN(fxn_msg_createqueue, pfn_msg_create_queue);
-		STORE_FXN(fxn_msg_delete, pfn_msg_delete);
-		STORE_FXN(fxn_msg_deletequeue, pfn_msg_delete_queue);
-		STORE_FXN(fxn_msg_get, pfn_msg_get);
-		STORE_FXN(fxn_msg_put, pfn_msg_put);
-		STORE_FXN(fxn_msg_registernotify, pfn_msg_register_notify);
-		STORE_FXN(fxn_msg_setqueueid, pfn_msg_set_queue_id);
+		STORE_FXN(fxn_dev_create, dev_create);
+		STORE_FXN(fxn_dev_destroy, dev_destroy);
+		STORE_FXN(fxn_dev_ctrl, dev_cntrl);
+		STORE_FXN(fxn_brd_monitor, brd_monitor);
+		STORE_FXN(fxn_brd_start, brd_start);
+		STORE_FXN(fxn_brd_stop, brd_stop);
+		STORE_FXN(fxn_brd_status, brd_status);
+		STORE_FXN(fxn_brd_read, brd_read);
+		STORE_FXN(fxn_brd_write, brd_write);
+		STORE_FXN(fxn_brd_setstate, brd_set_state);
+		STORE_FXN(fxn_brd_memcopy, brd_mem_copy);
+		STORE_FXN(fxn_brd_memwrite, brd_mem_write);
+		STORE_FXN(fxn_brd_memmap, brd_mem_map);
+		STORE_FXN(fxn_brd_memunmap, brd_mem_un_map);
+		STORE_FXN(fxn_chnl_create, chnl_create);
+		STORE_FXN(fxn_chnl_destroy, chnl_destroy);
+		STORE_FXN(fxn_chnl_open, chnl_open);
+		STORE_FXN(fxn_chnl_close, chnl_close);
+		STORE_FXN(fxn_chnl_addioreq, chnl_add_io_req);
+		STORE_FXN(fxn_chnl_getioc, chnl_get_ioc);
+		STORE_FXN(fxn_chnl_cancelio, chnl_cancel_io);
+		STORE_FXN(fxn_chnl_flushio, chnl_flush_io);
+		STORE_FXN(fxn_chnl_getinfo, chnl_get_info);
+		STORE_FXN(fxn_chnl_getmgrinfo, chnl_get_mgr_info);
+		STORE_FXN(fxn_chnl_idle, chnl_idle);
+		STORE_FXN(fxn_chnl_registernotify, chnl_register_notify);
+		STORE_FXN(fxn_io_create, io_create);
+		STORE_FXN(fxn_io_destroy, io_destroy);
+		STORE_FXN(fxn_io_onloaded, io_on_loaded);
+		STORE_FXN(fxn_io_getprocload, io_get_proc_load);
+		STORE_FXN(fxn_msg_create, msg_create);
+		STORE_FXN(fxn_msg_createqueue, msg_create_queue);
+		STORE_FXN(fxn_msg_delete, msg_delete);
+		STORE_FXN(fxn_msg_deletequeue, msg_delete_queue);
+		STORE_FXN(fxn_msg_get, msg_get);
+		STORE_FXN(fxn_msg_put, msg_put);
+		STORE_FXN(fxn_msg_registernotify, msg_register_notify);
+		STORE_FXN(fxn_msg_setqueueid, msg_set_queue_id);
 	}
 	/* Add code for any additional functions in newerBridge versions here */
 	/* Ensure postcondition: */
-	DBC_ENSURE(intf_fxns->pfn_dev_create != NULL);
-	DBC_ENSURE(intf_fxns->pfn_dev_destroy != NULL);
-	DBC_ENSURE(intf_fxns->pfn_dev_cntrl != NULL);
-	DBC_ENSURE(intf_fxns->pfn_brd_monitor != NULL);
-	DBC_ENSURE(intf_fxns->pfn_brd_start != NULL);
-	DBC_ENSURE(intf_fxns->pfn_brd_stop != NULL);
-	DBC_ENSURE(intf_fxns->pfn_brd_status != NULL);
-	DBC_ENSURE(intf_fxns->pfn_brd_read != NULL);
-	DBC_ENSURE(intf_fxns->pfn_brd_write != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_create != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_destroy != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_open != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_close != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_add_io_req != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_get_ioc != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_cancel_io != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_flush_io != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_get_info != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_get_mgr_info != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_idle != NULL);
-	DBC_ENSURE(intf_fxns->pfn_chnl_register_notify != NULL);
-	DBC_ENSURE(intf_fxns->pfn_io_create != NULL);
-	DBC_ENSURE(intf_fxns->pfn_io_destroy != NULL);
-	DBC_ENSURE(intf_fxns->pfn_io_on_loaded != NULL);
-	DBC_ENSURE(intf_fxns->pfn_io_get_proc_load != NULL);
-	DBC_ENSURE(intf_fxns->pfn_msg_set_queue_id != NULL);
+	DBC_ENSURE(intf_fxns->dev_create != NULL);
+	DBC_ENSURE(intf_fxns->dev_destroy != NULL);
+	DBC_ENSURE(intf_fxns->dev_cntrl != NULL);
+	DBC_ENSURE(intf_fxns->brd_monitor != NULL);
+	DBC_ENSURE(intf_fxns->brd_start != NULL);
+	DBC_ENSURE(intf_fxns->brd_stop != NULL);
+	DBC_ENSURE(intf_fxns->brd_status != NULL);
+	DBC_ENSURE(intf_fxns->brd_read != NULL);
+	DBC_ENSURE(intf_fxns->brd_write != NULL);
+	DBC_ENSURE(intf_fxns->chnl_create != NULL);
+	DBC_ENSURE(intf_fxns->chnl_destroy != NULL);
+	DBC_ENSURE(intf_fxns->chnl_open != NULL);
+	DBC_ENSURE(intf_fxns->chnl_close != NULL);
+	DBC_ENSURE(intf_fxns->chnl_add_io_req != NULL);
+	DBC_ENSURE(intf_fxns->chnl_get_ioc != NULL);
+	DBC_ENSURE(intf_fxns->chnl_cancel_io != NULL);
+	DBC_ENSURE(intf_fxns->chnl_flush_io != NULL);
+	DBC_ENSURE(intf_fxns->chnl_get_info != NULL);
+	DBC_ENSURE(intf_fxns->chnl_get_mgr_info != NULL);
+	DBC_ENSURE(intf_fxns->chnl_idle != NULL);
+	DBC_ENSURE(intf_fxns->chnl_register_notify != NULL);
+	DBC_ENSURE(intf_fxns->io_create != NULL);
+	DBC_ENSURE(intf_fxns->io_destroy != NULL);
+	DBC_ENSURE(intf_fxns->io_on_loaded != NULL);
+	DBC_ENSURE(intf_fxns->io_get_proc_load != NULL);
+	DBC_ENSURE(intf_fxns->msg_set_queue_id != NULL);
 
 #undef  STORE_FXN
 }
diff --git a/drivers/staging/tidspbridge/pmgr/dspapi.c b/drivers/staging/tidspbridge/pmgr/dspapi.c
index 86ca785..767ffe2 100644
--- a/drivers/staging/tidspbridge/pmgr/dspapi.c
+++ b/drivers/staging/tidspbridge/pmgr/dspapi.c
@@ -68,7 +68,7 @@
 /* Device IOCtl function pointer */
 struct api_cmd {
 	u32(*fxn) (union trapped_args *args, void *pr_ctxt);
-	u32 dw_index;
+	u32 index;
 };
 
 /*  ----------------------------------- Globals */
@@ -416,7 +416,7 @@ u32 mgrwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
 	u8 *pndb_props;
 	u32 num_nodes;
 	int status = 0;
-	u32 size = args->args_mgr_enumnode_info.undb_props_size;
+	u32 size = args->args_mgr_enumnode_info.ndb_props_size;
 
 	if (size < sizeof(struct dsp_ndbprops))
 		return -EINVAL;
@@ -431,9 +431,9 @@ u32 mgrwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
 				       (struct dsp_ndbprops *)pndb_props, size,
 				       &num_nodes);
 	}
-	CP_TO_USR(args->args_mgr_enumnode_info.pndb_props, pndb_props, status,
+	CP_TO_USR(args->args_mgr_enumnode_info.ndb_props, pndb_props, status,
 		  size);
-	CP_TO_USR(args->args_mgr_enumnode_info.pu_num_nodes, &num_nodes, status,
+	CP_TO_USR(args->args_mgr_enumnode_info.num_nodes, &num_nodes, status,
 		  1);
 	kfree(pndb_props);
 
@@ -466,7 +466,7 @@ u32 mgrwrap_enum_proc_info(union trapped_args *args, void *pr_ctxt)
 	}
 	CP_TO_USR(args->args_mgr_enumproc_info.processor_info, processor_info,
 		  status, size);
-	CP_TO_USR(args->args_mgr_enumproc_info.pu_num_procs, &num_procs,
+	CP_TO_USR(args->args_mgr_enumproc_info.num_procs, &num_procs,
 		  status, 1);
 	kfree(processor_info);
 
@@ -490,7 +490,7 @@ u32 mgrwrap_register_object(union trapped_args *args, void *pr_ctxt)
 		goto func_end;
 	/* path_size is increased by 1 to accommodate NULL */
 	path_size = strlen_user((char *)
-				args->args_mgr_registerobject.psz_path_name) +
+				args->args_mgr_registerobject.sz_path_name) +
 	    1;
 	psz_path_name = kmalloc(path_size, GFP_KERNEL);
 	if (!psz_path_name) {
@@ -499,7 +499,7 @@ u32 mgrwrap_register_object(union trapped_args *args, void *pr_ctxt)
 	}
 	ret = strncpy_from_user(psz_path_name,
 				(char *)args->args_mgr_registerobject.
-				psz_path_name, path_size);
+				sz_path_name, path_size);
 	if (!ret) {
 		status = -EFAULT;
 		goto func_end;
@@ -569,9 +569,9 @@ u32 mgrwrap_wait_for_bridge_events(union trapped_args *args, void *pr_ctxt)
 		status = mgr_wait_for_bridge_events(anotifications, count,
 							 &index,
 							 args->args_mgr_wait.
-							 utimeout);
+							 timeout);
 	}
-	CP_TO_USR(args->args_mgr_wait.pu_index, &index, status, 1);
+	CP_TO_USR(args->args_mgr_wait.index, &index, status, 1);
 	return status;
 }
 
@@ -617,10 +617,10 @@ func_end:
 u32 procwrap_ctrl(union trapped_args *args, void *pr_ctxt)
 {
 	u32 cb_data_size, __user * psize = (u32 __user *)
-	    args->args_proc_ctrl.pargs;
+	    args->args_proc_ctrl.args;
 	u8 *pargs = NULL;
 	int status = 0;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	if (psize) {
 		if (get_user(cb_data_size, psize)) {
@@ -634,16 +634,16 @@ u32 procwrap_ctrl(union trapped_args *args, void *pr_ctxt)
 			goto func_end;
 		}
 
-		CP_FM_USR(pargs, args->args_proc_ctrl.pargs, status,
+		CP_FM_USR(pargs, args->args_proc_ctrl.args, status,
 			  cb_data_size);
 	}
 	if (!status) {
 		status = proc_ctrl(hprocessor,
-				   args->args_proc_ctrl.dw_cmd,
+				   args->args_proc_ctrl.cmd,
 				   (struct dsp_cbdata *)pargs);
 	}
 
-	/* CP_TO_USR(args->args_proc_ctrl.pargs, pargs, status, 1); */
+	/* CP_TO_USR(args->args_proc_ctrl.args, pargs, status, 1); */
 	kfree(pargs);
 func_end:
 	return status;
@@ -668,7 +668,7 @@ u32 procwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
 	void *node_tab[MAX_NODES];
 	u32 num_nodes;
 	u32 alloc_cnt;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	if (!args->args_proc_enumnode_info.node_tab_size)
 		return -EINVAL;
@@ -679,9 +679,9 @@ u32 procwrap_enum_node_info(union trapped_args *args, void *pr_ctxt)
 				 &num_nodes, &alloc_cnt);
 	CP_TO_USR(args->args_proc_enumnode_info.node_tab, node_tab, status,
 		  num_nodes);
-	CP_TO_USR(args->args_proc_enumnode_info.pu_num_nodes, &num_nodes,
+	CP_TO_USR(args->args_proc_enumnode_info.num_nodes, &num_nodes,
 		  status, 1);
-	CP_TO_USR(args->args_proc_enumnode_info.pu_allocated, &alloc_cnt,
+	CP_TO_USR(args->args_proc_enumnode_info.allocated, &alloc_cnt,
 		  status, 1);
 	return status;
 }
@@ -694,8 +694,8 @@ u32 procwrap_end_dma(union trapped_args *args, void *pr_ctxt)
 		return -EINVAL;
 
 	status = proc_end_dma(pr_ctxt,
-				   args->args_proc_dma.pmpu_addr,
-				   args->args_proc_dma.ul_size,
+				   args->args_proc_dma.mpu_addr,
+				   args->args_proc_dma.size,
 				   args->args_proc_dma.dir);
 	return status;
 }
@@ -708,8 +708,8 @@ u32 procwrap_begin_dma(union trapped_args *args, void *pr_ctxt)
 		return -EINVAL;
 
 	status = proc_begin_dma(pr_ctxt,
-				   args->args_proc_dma.pmpu_addr,
-				   args->args_proc_dma.ul_size,
+				   args->args_proc_dma.mpu_addr,
+				   args->args_proc_dma.size,
 				   args->args_proc_dma.dir);
 	return status;
 }
@@ -721,14 +721,14 @@ u32 procwrap_flush_memory(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 
-	if (args->args_proc_flushmemory.ul_flags >
+	if (args->args_proc_flushmemory.flags >
 	    PROC_WRITEBACK_INVALIDATE_MEM)
 		return -EINVAL;
 
 	status = proc_flush_memory(pr_ctxt,
-				   args->args_proc_flushmemory.pmpu_addr,
-				   args->args_proc_flushmemory.ul_size,
-				   args->args_proc_flushmemory.ul_flags);
+				   args->args_proc_flushmemory.mpu_addr,
+				   args->args_proc_flushmemory.size,
+				   args->args_proc_flushmemory.flags);
 	return status;
 }
 
@@ -741,8 +741,8 @@ u32 procwrap_invalidate_memory(union trapped_args *args, void *pr_ctxt)
 
 	status =
 	    proc_invalidate_memory(pr_ctxt,
-				   args->args_proc_invalidatememory.pmpu_addr,
-				   args->args_proc_invalidatememory.ul_size);
+				   args->args_proc_invalidatememory.mpu_addr,
+				   args->args_proc_invalidatememory.size);
 	return status;
 }
 
@@ -753,7 +753,7 @@ u32 procwrap_enum_resources(union trapped_args *args, void *pr_ctxt)
 {
 	int status = 0;
 	struct dsp_resourceinfo resource_info;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	if (args->args_proc_enumresources.resource_info_size <
 	    sizeof(struct dsp_resourceinfo))
@@ -780,7 +780,7 @@ u32 procwrap_get_state(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 	struct dsp_processorstate proc_state;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	if (args->args_proc_getstate.state_info_size <
 	    sizeof(struct dsp_processorstate))
@@ -801,7 +801,7 @@ u32 procwrap_get_trace(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 	u8 *pbuf;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	if (args->args_proc_gettrace.max_size > MAX_TRACEBUFLEN)
 		return -EINVAL;
@@ -813,7 +813,7 @@ u32 procwrap_get_trace(union trapped_args *args, void *pr_ctxt)
 	} else {
 		status = -ENOMEM;
 	}
-	CP_TO_USR(args->args_proc_gettrace.pbuf, pbuf, status,
+	CP_TO_USR(args->args_proc_gettrace.buf, pbuf, status,
 		  args->args_proc_gettrace.max_size);
 	kfree(pbuf);
 
@@ -830,7 +830,7 @@ u32 procwrap_load(union trapped_args *args, void *pr_ctxt)
 	char *temp;
 	s32 count = args->args_proc_load.argc_index;
 	u8 **argv = NULL, **envp = NULL;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	if (count <= 0 || count > MAX_LOADARGS) {
 		status = -EINVAL;
@@ -948,18 +948,18 @@ u32 procwrap_map(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 	void *map_addr;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
-	if (!args->args_proc_mapmem.ul_size)
+	if (!args->args_proc_mapmem.size)
 		return -EINVAL;
 
-	status = proc_map(args->args_proc_mapmem.hprocessor,
-			  args->args_proc_mapmem.pmpu_addr,
-			  args->args_proc_mapmem.ul_size,
+	status = proc_map(args->args_proc_mapmem.processor,
+			  args->args_proc_mapmem.mpu_addr,
+			  args->args_proc_mapmem.size,
 			  args->args_proc_mapmem.req_addr, &map_addr,
-			  args->args_proc_mapmem.ul_map_attr, pr_ctxt);
+			  args->args_proc_mapmem.map_attr, pr_ctxt);
 	if (!status) {
-		if (put_user(map_addr, args->args_proc_mapmem.pp_map_addr)) {
+		if (put_user(map_addr, args->args_proc_mapmem.map_addr)) {
 			status = -EINVAL;
 			proc_un_map(hprocessor, map_addr, pr_ctxt);
 		}
@@ -975,17 +975,17 @@ u32 procwrap_register_notify(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 	struct dsp_notification notification;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	/* Initialize the notification data structure */
-	notification.ps_name = NULL;
+	notification.name = NULL;
 	notification.handle = NULL;
 
 	status = proc_register_notify(hprocessor,
 				 args->args_proc_register_notify.event_mask,
 				 args->args_proc_register_notify.notify_type,
 				 &notification);
-	CP_TO_USR(args->args_proc_register_notify.hnotification, &notification,
+	CP_TO_USR(args->args_proc_register_notify.notification, &notification,
 		  status, 1);
 	return status;
 }
@@ -997,20 +997,20 @@ u32 procwrap_reserve_memory(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 	void *prsv_addr;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
-	if ((args->args_proc_rsvmem.ul_size <= 0) ||
-	    (args->args_proc_rsvmem.ul_size & (PG_SIZE4K - 1)) != 0)
+	if ((args->args_proc_rsvmem.size <= 0) ||
+	    (args->args_proc_rsvmem.size & (PG_SIZE4K - 1)) != 0)
 		return -EINVAL;
 
 	status = proc_reserve_memory(hprocessor,
-				     args->args_proc_rsvmem.ul_size, &prsv_addr,
+				     args->args_proc_rsvmem.size, &prsv_addr,
 				     pr_ctxt);
 	if (!status) {
-		if (put_user(prsv_addr, args->args_proc_rsvmem.pp_rsv_addr)) {
+		if (put_user(prsv_addr, args->args_proc_rsvmem.rsv_addr)) {
 			status = -EINVAL;
 			proc_un_reserve_memory(args->args_proc_rsvmem.
-					       hprocessor, prsv_addr, pr_ctxt);
+					       processor, prsv_addr, pr_ctxt);
 		}
 	}
 	return status;
@@ -1023,7 +1023,7 @@ u32 procwrap_start(union trapped_args *args, void *pr_ctxt)
 {
 	u32 ret;
 
-	ret = proc_start(((struct process_context *)pr_ctxt)->hprocessor);
+	ret = proc_start(((struct process_context *)pr_ctxt)->processor);
 	return ret;
 }
 
@@ -1034,7 +1034,7 @@ u32 procwrap_un_map(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
 
-	status = proc_un_map(((struct process_context *)pr_ctxt)->hprocessor,
+	status = proc_un_map(((struct process_context *)pr_ctxt)->processor,
 			     args->args_proc_unmapmem.map_addr, pr_ctxt);
 	return status;
 }
@@ -1045,10 +1045,10 @@ u32 procwrap_un_map(union trapped_args *args, void *pr_ctxt)
 u32 procwrap_un_reserve_memory(union trapped_args *args, void *pr_ctxt)
 {
 	int status;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	status = proc_un_reserve_memory(hprocessor,
-					args->args_proc_unrsvmem.prsv_addr,
+					args->args_proc_unrsvmem.rsv_addr,
 					pr_ctxt);
 	return status;
 }
@@ -1060,7 +1060,7 @@ u32 procwrap_stop(union trapped_args *args, void *pr_ctxt)
 {
 	u32 ret;
 
-	ret = proc_stop(((struct process_context *)pr_ctxt)->hprocessor);
+	ret = proc_stop(((struct process_context *)pr_ctxt)->processor);
 
 	return ret;
 }
@@ -1087,12 +1087,12 @@ u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt)
 	int status = 0;
 	struct dsp_uuid node_uuid;
 	u32 cb_data_size = 0;
-	u32 __user *psize = (u32 __user *) args->args_node_allocate.pargs;
+	u32 __user *psize = (u32 __user *) args->args_node_allocate.args;
 	u8 *pargs = NULL;
 	struct dsp_nodeattrin proc_attr_in, *attr_in = NULL;
 	struct node_res_object *node_res;
 	int nodeid;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	/* Optional argument */
 	if (psize) {
@@ -1106,7 +1106,7 @@ u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt)
 				status = -ENOMEM;
 
 		}
-		CP_FM_USR(pargs, args->args_node_allocate.pargs, status,
+		CP_FM_USR(pargs, args->args_node_allocate.args, status,
 			  cb_data_size);
 	}
 	CP_FM_USR(&node_uuid, args->args_node_allocate.node_id_ptr, status, 1);
@@ -1129,7 +1129,7 @@ u32 nodewrap_allocate(union trapped_args *args, void *pr_ctxt)
 	}
 	if (!status) {
 		nodeid = node_res->id + 1;
-		CP_TO_USR(args->args_node_allocate.ph_node, &nodeid,
+		CP_TO_USR(args->args_node_allocate.node, &nodeid,
 			status, 1);
 		if (status) {
 			status = -EFAULT;
@@ -1154,28 +1154,28 @@ u32 nodewrap_alloc_msg_buf(union trapped_args *args, void *pr_ctxt)
 	struct node_res_object *node_res;
 
 	find_node_handle(&node_res,  pr_ctxt,
-				args->args_node_allocmsgbuf.hnode);
+				args->args_node_allocmsgbuf.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	if (!args->args_node_allocmsgbuf.usize)
+	if (!args->args_node_allocmsgbuf.size)
 		return -EINVAL;
 
-	if (args->args_node_allocmsgbuf.pattr) {	/* Optional argument */
-		CP_FM_USR(&attr, args->args_node_allocmsgbuf.pattr, status, 1);
+	if (args->args_node_allocmsgbuf.attr) {	/* Optional argument */
+		CP_FM_USR(&attr, args->args_node_allocmsgbuf.attr, status, 1);
 		if (!status)
 			pattr = &attr;
 
 	}
 	/* argument */
-	CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.pbuffer, status, 1);
+	CP_FM_USR(&pbuffer, args->args_node_allocmsgbuf.buffer, status, 1);
 	if (!status) {
-		status = node_alloc_msg_buf(node_res->hnode,
-					    args->args_node_allocmsgbuf.usize,
+		status = node_alloc_msg_buf(node_res->node,
+					    args->args_node_allocmsgbuf.size,
 					    pattr, &pbuffer);
 	}
-	CP_TO_USR(args->args_node_allocmsgbuf.pbuffer, &pbuffer, status, 1);
+	CP_TO_USR(args->args_node_allocmsgbuf.buffer, &pbuffer, status, 1);
 	return status;
 }
 
@@ -1188,12 +1188,12 @@ u32 nodewrap_change_priority(union trapped_args *args, void *pr_ctxt)
 	struct node_res_object *node_res;
 
 	find_node_handle(&node_res, pr_ctxt,
-				args->args_node_changepriority.hnode);
+				args->args_node_changepriority.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	ret = node_change_priority(node_res->hnode,
+	ret = node_change_priority(node_res->node,
 				   args->args_node_changepriority.prio);
 
 	return ret;
@@ -1213,20 +1213,20 @@ u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt)
 	struct node_res_object *node_res1, *node_res2;
 	struct node_object *node1 = NULL, *node2 = NULL;
 
-	if ((int)args->args_node_connect.hnode != DSP_HGPPNODE) {
+	if ((int)args->args_node_connect.node != DSP_HGPPNODE) {
 		find_node_handle(&node_res1, pr_ctxt,
-				args->args_node_connect.hnode);
+				args->args_node_connect.node);
 		if (node_res1)
-			node1 = node_res1->hnode;
+			node1 = node_res1->node;
 	} else {
-		node1 = args->args_node_connect.hnode;
+		node1 = args->args_node_connect.node;
 	}
 
 	if ((int)args->args_node_connect.other_node != DSP_HGPPNODE) {
 		find_node_handle(&node_res2, pr_ctxt,
 				args->args_node_connect.other_node);
 		if (node_res2)
-			node2 = node_res2->hnode;
+			node2 = node_res2->node;
 	} else {
 		node2 = args->args_node_connect.other_node;
 	}
@@ -1253,8 +1253,8 @@ u32 nodewrap_connect(union trapped_args *args, void *pr_ctxt)
 		if (status)
 			goto func_cont;
 	}
-	if (args->args_node_connect.pattrs) {	/* Optional argument */
-		CP_FM_USR(&attrs, args->args_node_connect.pattrs, status, 1);
+	if (args->args_node_connect.attrs) {	/* Optional argument */
+		CP_FM_USR(&attrs, args->args_node_connect.attrs, status, 1);
 		if (!status)
 			pattrs = &attrs;
 
@@ -1280,12 +1280,12 @@ u32 nodewrap_create(union trapped_args *args, void *pr_ctxt)
 	u32 ret;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_create.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_create.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	ret = node_create(node_res->hnode);
+	ret = node_create(node_res->node);
 
 	return ret;
 }
@@ -1298,7 +1298,7 @@ u32 nodewrap_delete(union trapped_args *args, void *pr_ctxt)
 	u32 ret;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_delete.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_delete.node);
 
 	if (!node_res)
 		return -EFAULT;
@@ -1318,24 +1318,24 @@ u32 nodewrap_free_msg_buf(union trapped_args *args, void *pr_ctxt)
 	struct dsp_bufferattr attr;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_freemsgbuf.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	if (args->args_node_freemsgbuf.pattr) {	/* Optional argument */
-		CP_FM_USR(&attr, args->args_node_freemsgbuf.pattr, status, 1);
+	if (args->args_node_freemsgbuf.attr) {	/* Optional argument */
+		CP_FM_USR(&attr, args->args_node_freemsgbuf.attr, status, 1);
 		if (!status)
 			pattr = &attr;
 
 	}
 
-	if (!args->args_node_freemsgbuf.pbuffer)
+	if (!args->args_node_freemsgbuf.buffer)
 		return -EFAULT;
 
 	if (!status) {
-		status = node_free_msg_buf(node_res->hnode,
-					   args->args_node_freemsgbuf.pbuffer,
+		status = node_free_msg_buf(node_res->node,
+					   args->args_node_freemsgbuf.buffer,
 					   pattr);
 	}
 
@@ -1351,14 +1351,14 @@ u32 nodewrap_get_attr(union trapped_args *args, void *pr_ctxt)
 	struct dsp_nodeattr attr;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_getattr.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	status = node_get_attr(node_res->hnode, &attr,
+	status = node_get_attr(node_res->node, &attr,
 			       args->args_node_getattr.attr_size);
-	CP_TO_USR(args->args_node_getattr.pattr, &attr, status, 1);
+	CP_TO_USR(args->args_node_getattr.attr, &attr, status, 1);
 
 	return status;
 }
@@ -1372,13 +1372,13 @@ u32 nodewrap_get_message(union trapped_args *args, void *pr_ctxt)
 	struct dsp_msg msg;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_getmessage.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	status = node_get_message(node_res->hnode, &msg,
-				  args->args_node_getmessage.utimeout);
+	status = node_get_message(node_res->node, &msg,
+				  args->args_node_getmessage.timeout);
 
 	CP_TO_USR(args->args_node_getmessage.message, &msg, status, 1);
 
@@ -1393,12 +1393,12 @@ u32 nodewrap_pause(union trapped_args *args, void *pr_ctxt)
 	u32 ret;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_pause.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_pause.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	ret = node_pause(node_res->hnode);
+	ret = node_pause(node_res->node);
 
 	return ret;
 }
@@ -1412,7 +1412,7 @@ u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt)
 	struct dsp_msg msg;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_putmessage.node);
 
 	if (!node_res)
 		return -EFAULT;
@@ -1421,8 +1421,8 @@ u32 nodewrap_put_message(union trapped_args *args, void *pr_ctxt)
 
 	if (!status) {
 		status =
-		    node_put_message(node_res->hnode, &msg,
-				     args->args_node_putmessage.utimeout);
+		    node_put_message(node_res->node, &msg,
+				     args->args_node_putmessage.timeout);
 	}
 
 	return status;
@@ -1438,25 +1438,25 @@ u32 nodewrap_register_notify(union trapped_args *args, void *pr_ctxt)
 	struct node_res_object *node_res;
 
 	find_node_handle(&node_res, pr_ctxt,
-			args->args_node_registernotify.hnode);
+			args->args_node_registernotify.node);
 
 	if (!node_res)
 		return -EFAULT;
 
 	/* Initialize the notification data structure */
-	notification.ps_name = NULL;
+	notification.name = NULL;
 	notification.handle = NULL;
 
 	if (!args->args_proc_register_notify.event_mask)
 		CP_FM_USR(&notification,
-			  args->args_proc_register_notify.hnotification,
+			  args->args_proc_register_notify.notification,
 			  status, 1);
 
-	status = node_register_notify(node_res->hnode,
+	status = node_register_notify(node_res->node,
 				      args->args_node_registernotify.event_mask,
 				      args->args_node_registernotify.
 				      notify_type, &notification);
-	CP_TO_USR(args->args_node_registernotify.hnotification, &notification,
+	CP_TO_USR(args->args_node_registernotify.notification, &notification,
 		  status, 1);
 	return status;
 }
@@ -1469,12 +1469,12 @@ u32 nodewrap_run(union trapped_args *args, void *pr_ctxt)
 	u32 ret;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_run.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_run.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	ret = node_run(node_res->hnode);
+	ret = node_run(node_res->node);
 
 	return ret;
 }
@@ -1488,14 +1488,14 @@ u32 nodewrap_terminate(union trapped_args *args, void *pr_ctxt)
 	int tempstatus;
 	struct node_res_object *node_res;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_node_terminate.node);
 
 	if (!node_res)
 		return -EFAULT;
 
-	status = node_terminate(node_res->hnode, &tempstatus);
+	status = node_terminate(node_res->node, &tempstatus);
 
-	CP_TO_USR(args->args_node_terminate.pstatus, &tempstatus, status, 1);
+	CP_TO_USR(args->args_node_terminate.status, &tempstatus, status, 1);
 
 	return status;
 }
@@ -1508,7 +1508,7 @@ u32 nodewrap_get_uuid_props(union trapped_args *args, void *pr_ctxt)
 	int status = 0;
 	struct dsp_uuid node_uuid;
 	struct dsp_ndbprops *pnode_props = NULL;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	CP_FM_USR(&node_uuid, args->args_node_getuuidprops.node_id_ptr, status,
 		  1);
@@ -1551,7 +1551,7 @@ u32 strmwrap_allocate_buffer(union trapped_args *args, void *pr_ctxt)
 	struct strm_res_object *strm_res;
 
 	find_strm_handle(&strm_res, pr_ctxt,
-		args->args_strm_allocatebuffer.hstream);
+		args->args_strm_allocatebuffer.stream);
 
 	if (!strm_res)
 		return -EFAULT;
@@ -1564,7 +1564,7 @@ u32 strmwrap_allocate_buffer(union trapped_args *args, void *pr_ctxt)
 		return -ENOMEM;
 
 	status = strm_allocate_buffer(strm_res,
-				      args->args_strm_allocatebuffer.usize,
+				      args->args_strm_allocatebuffer.size,
 				      ap_buffer, num_bufs, pr_ctxt);
 	if (!status) {
 		CP_TO_USR(args->args_strm_allocatebuffer.ap_buffer, ap_buffer,
@@ -1587,7 +1587,7 @@ u32 strmwrap_close(union trapped_args *args, void *pr_ctxt)
 {
 	struct strm_res_object *strm_res;
 
-	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_close.hstream);
+	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_close.stream);
 
 	if (!strm_res)
 		return -EFAULT;
@@ -1606,7 +1606,7 @@ u32 strmwrap_free_buffer(union trapped_args *args, void *pr_ctxt)
 	struct strm_res_object *strm_res;
 
 	find_strm_handle(&strm_res, pr_ctxt,
-			args->args_strm_freebuffer.hstream);
+			args->args_strm_freebuffer.stream);
 
 	if (!strm_res)
 		return -EFAULT;
@@ -1654,7 +1654,7 @@ u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt)
 	struct strm_res_object *strm_res;
 
 	find_strm_handle(&strm_res, pr_ctxt,
-			args->args_strm_getinfo.hstream);
+			args->args_strm_getinfo.stream);
 
 	if (!strm_res)
 		return -EFAULT;
@@ -1665,7 +1665,7 @@ u32 strmwrap_get_info(union trapped_args *args, void *pr_ctxt)
 	strm_info.user_strm = &user;
 
 	if (!status) {
-		status = strm_get_info(strm_res->hstream,
+		status = strm_get_info(strm_res->stream,
 				       &strm_info,
 				       args->args_strm_getinfo.
 				       stream_info_size);
@@ -1684,12 +1684,12 @@ u32 strmwrap_idle(union trapped_args *args, void *pr_ctxt)
 	u32 ret;
 	struct strm_res_object *strm_res;
 
-	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_idle.hstream);
+	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_idle.stream);
 
 	if (!strm_res)
 		return -EFAULT;
 
-	ret = strm_idle(strm_res->hstream, args->args_strm_idle.flush_flag);
+	ret = strm_idle(strm_res->stream, args->args_strm_idle.flush_flag);
 
 	return ret;
 }
@@ -1702,22 +1702,22 @@ u32 strmwrap_issue(union trapped_args *args, void *pr_ctxt)
 	int status = 0;
 	struct strm_res_object *strm_res;
 
-	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_issue.hstream);
+	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_issue.stream);
 
 	if (!strm_res)
 		return -EFAULT;
 
-	if (!args->args_strm_issue.pbuffer)
+	if (!args->args_strm_issue.buffer)
 		return -EFAULT;
 
 	/* No need of doing CP_FM_USR for the user buffer (pbuffer)
 	   as this is done in Bridge internal function bridge_chnl_add_io_req
 	   in chnl_sm.c */
-	status = strm_issue(strm_res->hstream,
-			    args->args_strm_issue.pbuffer,
-			    args->args_strm_issue.dw_bytes,
-			    args->args_strm_issue.dw_buf_size,
-			    args->args_strm_issue.dw_arg);
+	status = strm_issue(strm_res->stream,
+			    args->args_strm_issue.buffer,
+			    args->args_strm_issue.bytes,
+			    args->args_strm_issue.buf_size,
+			    args->args_strm_issue.arg);
 
 	return status;
 }
@@ -1734,7 +1734,7 @@ u32 strmwrap_open(union trapped_args *args, void *pr_ctxt)
 	struct node_res_object *node_res;
 	int strmid;
 
-	find_node_handle(&node_res, pr_ctxt, args->args_strm_open.hnode);
+	find_node_handle(&node_res, pr_ctxt, args->args_strm_open.node);
 
 	if (!node_res)
 		return -EFAULT;
@@ -1750,13 +1750,13 @@ u32 strmwrap_open(union trapped_args *args, void *pr_ctxt)
 		}
 
 	}
-	status = strm_open(node_res->hnode,
+	status = strm_open(node_res->node,
 			   args->args_strm_open.direction,
 			   args->args_strm_open.index, &attr, &strm_res_obj,
 			   pr_ctxt);
 	if (!status) {
 		strmid = strm_res_obj->id + 1;
-		CP_TO_USR(args->args_strm_open.ph_stream, &strmid, status, 1);
+		CP_TO_USR(args->args_strm_open.stream, &strmid, status, 1);
 	}
 	return status;
 }
@@ -1773,16 +1773,16 @@ u32 strmwrap_reclaim(union trapped_args *args, void *pr_ctxt)
 	u32 ul_buf_size;
 	struct strm_res_object *strm_res;
 
-	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_reclaim.hstream);
+	find_strm_handle(&strm_res, pr_ctxt, args->args_strm_reclaim.stream);
 
 	if (!strm_res)
 		return -EFAULT;
 
-	status = strm_reclaim(strm_res->hstream, &buf_ptr,
+	status = strm_reclaim(strm_res->stream, &buf_ptr,
 			      &ul_bytes, &ul_buf_size, &dw_arg);
 	CP_TO_USR(args->args_strm_reclaim.buf_ptr, &buf_ptr, status, 1);
 	CP_TO_USR(args->args_strm_reclaim.bytes, &ul_bytes, status, 1);
-	CP_TO_USR(args->args_strm_reclaim.pdw_arg, &dw_arg, status, 1);
+	CP_TO_USR(args->args_strm_reclaim.arg, &dw_arg, status, 1);
 
 	if (args->args_strm_reclaim.buf_size_ptr != NULL) {
 		CP_TO_USR(args->args_strm_reclaim.buf_size_ptr, &ul_buf_size,
@@ -1802,20 +1802,20 @@ u32 strmwrap_register_notify(union trapped_args *args, void *pr_ctxt)
 	struct strm_res_object *strm_res;
 
 	find_strm_handle(&strm_res, pr_ctxt,
-			args->args_strm_registernotify.hstream);
+			args->args_strm_registernotify.stream);
 
 	if (!strm_res)
 		return -EFAULT;
 
 	/* Initialize the notification data structure */
-	notification.ps_name = NULL;
+	notification.name = NULL;
 	notification.handle = NULL;
 
-	status = strm_register_notify(strm_res->hstream,
+	status = strm_register_notify(strm_res->stream,
 				      args->args_strm_registernotify.event_mask,
 				      args->args_strm_registernotify.
 				      notify_type, &notification);
-	CP_TO_USR(args->args_strm_registernotify.hnotification, &notification,
+	CP_TO_USR(args->args_strm_registernotify.notification, &notification,
 		  status, 1);
 
 	return status;
@@ -1848,14 +1848,14 @@ u32 strmwrap_select(union trapped_args *args, void *pr_ctxt)
 		if (!strm_res)
 			return -EFAULT;
 
-		strm_tab[i] = strm_res->hstream;
+		strm_tab[i] = strm_res->stream;
 	}
 
 	if (!status) {
 		status = strm_select(strm_tab, args->args_strm_select.strm_num,
-				     &mask, args->args_strm_select.utimeout);
+				     &mask, args->args_strm_select.timeout);
 	}
-	CP_TO_USR(args->args_strm_select.pmask, &mask, status, 1);
+	CP_TO_USR(args->args_strm_select.mask, &mask, status, 1);
 	return status;
 }
 
@@ -1888,11 +1888,11 @@ u32 cmmwrap_get_handle(union trapped_args *args, void *pr_ctxt)
 {
 	int status = 0;
 	struct cmm_object *hcmm_mgr;
-	void *hprocessor = ((struct process_context *)pr_ctxt)->hprocessor;
+	void *hprocessor = ((struct process_context *)pr_ctxt)->processor;
 
 	status = cmm_get_handle(hprocessor, &hcmm_mgr);
 
-	CP_TO_USR(args->args_cmm_gethandle.ph_cmm_mgr, &hcmm_mgr, status, 1);
+	CP_TO_USR(args->args_cmm_gethandle.cmm_mgr, &hcmm_mgr, status, 1);
 
 	return status;
 }
@@ -1905,7 +1905,7 @@ u32 cmmwrap_get_info(union trapped_args *args, void *pr_ctxt)
 	int status = 0;
 	struct cmm_info cmm_info_obj;
 
-	status = cmm_get_info(args->args_cmm_getinfo.hcmm_mgr, &cmm_info_obj);
+	status = cmm_get_info(args->args_cmm_getinfo.cmm_mgr, &cmm_info_obj);
 
 	CP_TO_USR(args->args_cmm_getinfo.cmm_info_obj, &cmm_info_obj, status,
 		  1);
diff --git a/drivers/staging/tidspbridge/pmgr/io.c b/drivers/staging/tidspbridge/pmgr/io.c
index 20cbb9f..65245f3 100644
--- a/drivers/staging/tidspbridge/pmgr/io.c
+++ b/drivers/staging/tidspbridge/pmgr/io.c
@@ -31,7 +31,6 @@
 
 /*  ----------------------------------- This */
 #include <ioobj.h>
-#include <dspbridge/iodefs.h>
 #include <dspbridge/io.h>
 
 /*  ----------------------------------- Globals */
@@ -58,7 +57,7 @@ int io_create(struct io_mgr **io_man, struct dev_object *hdev_obj,
 	*io_man = NULL;
 
 	/* A memory base of 0 implies no memory base: */
-	if ((mgr_attrts->shm_base != 0) && (mgr_attrts->usm_length == 0))
+	if ((mgr_attrts->shm_base != 0) && (mgr_attrts->sm_length == 0))
 		status = -EINVAL;
 
 	if (mgr_attrts->word_size == 0)
@@ -68,13 +67,13 @@ int io_create(struct io_mgr **io_man, struct dev_object *hdev_obj,
 		dev_get_intf_fxns(hdev_obj, &intf_fxns);
 
 		/* Let Bridge channel module finish the create: */
-		status = (*intf_fxns->pfn_io_create) (&hio_mgr, hdev_obj,
+		status = (*intf_fxns->io_create) (&hio_mgr, hdev_obj,
 						      mgr_attrts);
 
 		if (!status) {
 			pio_mgr = (struct io_mgr_ *)hio_mgr;
 			pio_mgr->intf_fxns = intf_fxns;
-			pio_mgr->hdev_obj = hdev_obj;
+			pio_mgr->dev_obj = hdev_obj;
 
 			/* Return the new channel manager handle: */
 			*io_man = hio_mgr;
@@ -100,7 +99,7 @@ int io_destroy(struct io_mgr *hio_mgr)
 	intf_fxns = pio_mgr->intf_fxns;
 
 	/* Let Bridge channel module destroy the io_mgr: */
-	status = (*intf_fxns->pfn_io_destroy) (hio_mgr);
+	status = (*intf_fxns->io_destroy) (hio_mgr);
 
 	return status;
 }
diff --git a/drivers/staging/tidspbridge/pmgr/ioobj.h b/drivers/staging/tidspbridge/pmgr/ioobj.h
index f46355f..7defd94 100644
--- a/drivers/staging/tidspbridge/pmgr/ioobj.h
+++ b/drivers/staging/tidspbridge/pmgr/ioobj.h
@@ -29,10 +29,10 @@
  */
 struct io_mgr_ {
 	/* These must be the first fields in a io_mgr struct: */
-	struct bridge_dev_context *hbridge_context;	/* Bridge context. */
+	struct bridge_dev_context *bridge_context;	/* Bridge context. */
 	/* Function interface to Bridge driver. */
 	struct bridge_drv_interface *intf_fxns;
-	struct dev_object *hdev_obj;	/* Device this board represents. */
+	struct dev_object *dev_obj;	/* Device this board represents. */
 };
 
 #endif /* IOOBJ_ */
diff --git a/drivers/staging/tidspbridge/pmgr/msg.c b/drivers/staging/tidspbridge/pmgr/msg.c
index abd4365..a691603 100644
--- a/drivers/staging/tidspbridge/pmgr/msg.c
+++ b/drivers/staging/tidspbridge/pmgr/msg.c
@@ -64,7 +64,7 @@ int msg_create(struct msg_mgr **msg_man,
 
 	/* Let Bridge message module finish the create: */
 	status =
-	    (*intf_fxns->pfn_msg_create) (&hmsg_mgr, hdev_obj, msg_callback);
+	    (*intf_fxns->msg_create) (&hmsg_mgr, hdev_obj, msg_callback);
 
 	if (!status) {
 		/* Fill in DSP API message module's fields of the msg_mgr
@@ -96,7 +96,7 @@ void msg_delete(struct msg_mgr *hmsg_mgr)
 		intf_fxns = msg_mgr_obj->intf_fxns;
 
 		/* Let Bridge message module destroy the msg_mgr: */
-		(*intf_fxns->pfn_msg_delete) (hmsg_mgr);
+		(*intf_fxns->msg_delete) (hmsg_mgr);
 	} else {
 		dev_dbg(bridge, "%s: Error hmsg_mgr handle: %p\n",
 			__func__, hmsg_mgr);
diff --git a/drivers/staging/tidspbridge/rmgr/dbdcd.c b/drivers/staging/tidspbridge/rmgr/dbdcd.c
index 3581a55..a7e407e 100644
--- a/drivers/staging/tidspbridge/rmgr/dbdcd.c
+++ b/drivers/staging/tidspbridge/rmgr/dbdcd.c
@@ -134,7 +134,7 @@ int dcd_create_manager(char *sz_zl_dll_name,
 	DBC_REQUIRE(refs >= 0);
 	DBC_REQUIRE(dcd_mgr);
 
-	status = cod_create(&cod_mgr, sz_zl_dll_name, NULL);
+	status = cod_create(&cod_mgr, sz_zl_dll_name);
 	if (status)
 		goto func_end;
 
@@ -1020,8 +1020,6 @@ static s32 atoi(char *psz_buf)
 {
 	char *pch = psz_buf;
 	s32 base = 0;
-	unsigned long res;
-	int ret_val;
 
 	while (isspace(*pch))
 		pch++;
@@ -1033,9 +1031,7 @@ static s32 atoi(char *psz_buf)
 		base = 16;
 	}
 
-	ret_val = strict_strtoul(pch, base, &res);
-
-	return ret_val ? : res;
+	return simple_strtoul(pch, NULL, base);
 }
 
 /*
@@ -1116,14 +1112,14 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
 		    dsp_resource_reqmts.program_mem_size = atoi(token);
 		token = strsep(&psz_cur, seps);
 		gen_obj->obj_data.node_obj.ndb_props.
-		    dsp_resource_reqmts.uwc_execution_time = atoi(token);
+		    dsp_resource_reqmts.wc_execution_time = atoi(token);
 		token = strsep(&psz_cur, seps);
 		gen_obj->obj_data.node_obj.ndb_props.
-		    dsp_resource_reqmts.uwc_period = atoi(token);
+		    dsp_resource_reqmts.wc_period = atoi(token);
 		token = strsep(&psz_cur, seps);
 
 		gen_obj->obj_data.node_obj.ndb_props.
-		    dsp_resource_reqmts.uwc_deadline = atoi(token);
+		    dsp_resource_reqmts.wc_deadline = atoi(token);
 		token = strsep(&psz_cur, seps);
 
 		gen_obj->obj_data.node_obj.ndb_props.
@@ -1166,40 +1162,40 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
 		    atoi(token);
 		token = strsep(&psz_cur, seps);
 
-		/* u32 utimeout */
-		gen_obj->obj_data.node_obj.ndb_props.utimeout = atoi(token);
+		/* u32 timeout */
+		gen_obj->obj_data.node_obj.ndb_props.timeout = atoi(token);
 		token = strsep(&psz_cur, seps);
 
-		/* char *pstr_create_phase_fxn */
+		/* char *str_create_phase_fxn */
 		DBC_REQUIRE(token);
 		token_len = strlen(token);
-		gen_obj->obj_data.node_obj.pstr_create_phase_fxn =
+		gen_obj->obj_data.node_obj.str_create_phase_fxn =
 					kzalloc(token_len + 1, GFP_KERNEL);
-		strncpy(gen_obj->obj_data.node_obj.pstr_create_phase_fxn,
+		strncpy(gen_obj->obj_data.node_obj.str_create_phase_fxn,
 			token, token_len);
-		gen_obj->obj_data.node_obj.pstr_create_phase_fxn[token_len] =
+		gen_obj->obj_data.node_obj.str_create_phase_fxn[token_len] =
 		    '\0';
 		token = strsep(&psz_cur, seps);
 
-		/* char *pstr_execute_phase_fxn */
+		/* char *str_execute_phase_fxn */
 		DBC_REQUIRE(token);
 		token_len = strlen(token);
-		gen_obj->obj_data.node_obj.pstr_execute_phase_fxn =
+		gen_obj->obj_data.node_obj.str_execute_phase_fxn =
 					kzalloc(token_len + 1, GFP_KERNEL);
-		strncpy(gen_obj->obj_data.node_obj.pstr_execute_phase_fxn,
+		strncpy(gen_obj->obj_data.node_obj.str_execute_phase_fxn,
 			token, token_len);
-		gen_obj->obj_data.node_obj.pstr_execute_phase_fxn[token_len] =
+		gen_obj->obj_data.node_obj.str_execute_phase_fxn[token_len] =
 		    '\0';
 		token = strsep(&psz_cur, seps);
 
-		/* char *pstr_delete_phase_fxn */
+		/* char *str_delete_phase_fxn */
 		DBC_REQUIRE(token);
 		token_len = strlen(token);
-		gen_obj->obj_data.node_obj.pstr_delete_phase_fxn =
+		gen_obj->obj_data.node_obj.str_delete_phase_fxn =
 					kzalloc(token_len + 1, GFP_KERNEL);
-		strncpy(gen_obj->obj_data.node_obj.pstr_delete_phase_fxn,
+		strncpy(gen_obj->obj_data.node_obj.str_delete_phase_fxn,
 			token, token_len);
-		gen_obj->obj_data.node_obj.pstr_delete_phase_fxn[token_len] =
+		gen_obj->obj_data.node_obj.str_delete_phase_fxn[token_len] =
 		    '\0';
 		token = strsep(&psz_cur, seps);
 
@@ -1211,34 +1207,34 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
 		gen_obj->obj_data.node_obj.msg_notify_type = atoi(token);
 		token = strsep(&psz_cur, seps);
 
-		/* char *pstr_i_alg_name */
+		/* char *str_i_alg_name */
 		if (token) {
 			token_len = strlen(token);
-			gen_obj->obj_data.node_obj.pstr_i_alg_name =
+			gen_obj->obj_data.node_obj.str_i_alg_name =
 					kzalloc(token_len + 1, GFP_KERNEL);
-			strncpy(gen_obj->obj_data.node_obj.pstr_i_alg_name,
+			strncpy(gen_obj->obj_data.node_obj.str_i_alg_name,
 				token, token_len);
-			gen_obj->obj_data.node_obj.pstr_i_alg_name[token_len] =
+			gen_obj->obj_data.node_obj.str_i_alg_name[token_len] =
 			    '\0';
 			token = strsep(&psz_cur, seps);
 		}
 
 		/* Load type (static, dynamic, or overlay) */
 		if (token) {
-			gen_obj->obj_data.node_obj.us_load_type = atoi(token);
+			gen_obj->obj_data.node_obj.load_type = atoi(token);
 			token = strsep(&psz_cur, seps);
 		}
 
 		/* Dynamic load data requirements */
 		if (token) {
-			gen_obj->obj_data.node_obj.ul_data_mem_seg_mask =
+			gen_obj->obj_data.node_obj.data_mem_seg_mask =
 			    atoi(token);
 			token = strsep(&psz_cur, seps);
 		}
 
 		/* Dynamic load code requirements */
 		if (token) {
-			gen_obj->obj_data.node_obj.ul_code_mem_seg_mask =
+			gen_obj->obj_data.node_obj.code_mem_seg_mask =
 			    atoi(token);
 			token = strsep(&psz_cur, seps);
 		}
@@ -1257,7 +1253,7 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
 					/* Heap Size for the node */
 					gen_obj->obj_data.node_obj.
 					    ndb_props.node_profiles[i].
-					    ul_heap_size = atoi(token);
+					    heap_size = atoi(token);
 				}
 			}
 		}
@@ -1289,10 +1285,10 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
 		gen_obj->obj_data.proc_info.clock_rate = atoi(token);
 		token = strsep(&psz_cur, seps);
 
-		gen_obj->obj_data.proc_info.ul_internal_mem_size = atoi(token);
+		gen_obj->obj_data.proc_info.internal_mem_size = atoi(token);
 		token = strsep(&psz_cur, seps);
 
-		gen_obj->obj_data.proc_info.ul_external_mem_size = atoi(token);
+		gen_obj->obj_data.proc_info.external_mem_size = atoi(token);
 		token = strsep(&psz_cur, seps);
 
 		gen_obj->obj_data.proc_info.processor_id = atoi(token);
@@ -1312,11 +1308,11 @@ static int get_attrs_from_buf(char *psz_buf, u32 ul_buf_size,
 		for (entry_id = 0; entry_id < 7; entry_id++) {
 			token = strsep(&psz_cur, seps);
 			gen_obj->obj_data.ext_proc_obj.ty_tlb[entry_id].
-			    ul_gpp_phys = atoi(token);
+			    gpp_phys = atoi(token);
 
 			token = strsep(&psz_cur, seps);
 			gen_obj->obj_data.ext_proc_obj.ty_tlb[entry_id].
-			    ul_dsp_virt = atoi(token);
+			    dsp_virt = atoi(token);
 		}
 #endif
 
diff --git a/drivers/staging/tidspbridge/rmgr/disp.c b/drivers/staging/tidspbridge/rmgr/disp.c
index b7ce435..a9aa22f 100644
--- a/drivers/staging/tidspbridge/rmgr/disp.c
+++ b/drivers/staging/tidspbridge/rmgr/disp.c
@@ -58,15 +58,15 @@
  *  ======== disp_object ========
  */
 struct disp_object {
-	struct dev_object *hdev_obj;	/* Device for this processor */
+	struct dev_object *dev_obj;	/* Device for this processor */
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
-	struct chnl_mgr *hchnl_mgr;	/* Channel manager */
+	struct chnl_mgr *chnl_mgr;	/* Channel manager */
 	struct chnl_object *chnl_to_dsp;	/* Chnl for commands to RMS */
 	struct chnl_object *chnl_from_dsp;	/* Chnl for replies from RMS */
-	u8 *pbuf;		/* Buffer for commands, replies */
-	u32 ul_bufsize;		/* pbuf size in bytes */
-	u32 ul_bufsize_rms;	/* pbuf size in RMS words */
+	u8 *buf;		/* Buffer for commands, replies */
+	u32 bufsize;		/* buf size in bytes */
+	u32 bufsize_rms;	/* buf size in RMS words */
 	u32 char_size;		/* Size of DSP character */
 	u32 word_size;		/* Size of DSP word */
 	u32 data_mau_size;	/* Size of DSP Data MAU */
@@ -108,11 +108,11 @@ int disp_create(struct disp_object **dispatch_obj,
 	if (disp_obj == NULL)
 		status = -ENOMEM;
 	else
-		disp_obj->hdev_obj = hdev_obj;
+		disp_obj->dev_obj = hdev_obj;
 
 	/* Get Channel manager and Bridge function interface */
 	if (!status) {
-		status = dev_get_chnl_mgr(hdev_obj, &(disp_obj->hchnl_mgr));
+		status = dev_get_chnl_mgr(hdev_obj, &(disp_obj->chnl_mgr));
 		if (!status) {
 			(void)dev_get_intf_fxns(hdev_obj, &intf_fxns);
 			disp_obj->intf_fxns = intf_fxns;
@@ -140,26 +140,26 @@ int disp_create(struct disp_object **dispatch_obj,
 	/* Open channels for communicating with the RMS */
 	chnl_attr_obj.uio_reqs = CHNLIOREQS;
 	chnl_attr_obj.event_obj = NULL;
-	ul_chnl_id = disp_attrs->ul_chnl_offset + CHNLTORMSOFFSET;
-	status = (*intf_fxns->pfn_chnl_open) (&(disp_obj->chnl_to_dsp),
-					      disp_obj->hchnl_mgr,
+	ul_chnl_id = disp_attrs->chnl_offset + CHNLTORMSOFFSET;
+	status = (*intf_fxns->chnl_open) (&(disp_obj->chnl_to_dsp),
+					      disp_obj->chnl_mgr,
 					      CHNL_MODETODSP, ul_chnl_id,
 					      &chnl_attr_obj);
 
 	if (!status) {
-		ul_chnl_id = disp_attrs->ul_chnl_offset + CHNLFROMRMSOFFSET;
+		ul_chnl_id = disp_attrs->chnl_offset + CHNLFROMRMSOFFSET;
 		status =
-		    (*intf_fxns->pfn_chnl_open) (&(disp_obj->chnl_from_dsp),
-						 disp_obj->hchnl_mgr,
+		    (*intf_fxns->chnl_open) (&(disp_obj->chnl_from_dsp),
+						 disp_obj->chnl_mgr,
 						 CHNL_MODEFROMDSP, ul_chnl_id,
 						 &chnl_attr_obj);
 	}
 	if (!status) {
 		/* Allocate buffer for commands, replies */
-		disp_obj->ul_bufsize = disp_attrs->ul_chnl_buf_size;
-		disp_obj->ul_bufsize_rms = RMS_COMMANDBUFSIZE;
-		disp_obj->pbuf = kzalloc(disp_obj->ul_bufsize, GFP_KERNEL);
-		if (disp_obj->pbuf == NULL)
+		disp_obj->bufsize = disp_attrs->chnl_buf_size;
+		disp_obj->bufsize_rms = RMS_COMMANDBUFSIZE;
+		disp_obj->buf = kzalloc(disp_obj->bufsize, GFP_KERNEL);
+		if (disp_obj->buf == NULL)
 			status = -ENOMEM;
 	}
 func_cont:
@@ -232,7 +232,7 @@ int disp_node_change_priority(struct disp_object *disp_obj,
 	DBC_REQUIRE(hnode != NULL);
 
 	/* Send message to RMS to change priority */
-	rms_cmd = (struct rms_command *)(disp_obj->pbuf);
+	rms_cmd = (struct rms_command *)(disp_obj->buf);
 	rms_cmd->fxn = (rms_word) (rms_fxn);
 	rms_cmd->arg1 = (rms_word) node_env;
 	rms_cmd->arg2 = prio;
@@ -282,7 +282,7 @@ int disp_node_create(struct disp_object *disp_obj,
 	DBC_REQUIRE(node_get_type(hnode) != NODE_DEVICE);
 	DBC_REQUIRE(node_env != NULL);
 
-	status = dev_get_dev_type(disp_obj->hdev_obj, &dev_type);
+	status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);
 
 	if (status)
 		goto func_end;
@@ -295,7 +295,7 @@ int disp_node_create(struct disp_object *disp_obj,
 	DBC_REQUIRE(pargs != NULL);
 	node_type = node_get_type(hnode);
 	node_msg_args = pargs->asa.node_msg_args;
-	max = disp_obj->ul_bufsize_rms;	/*Max # of RMS words that can be sent */
+	max = disp_obj->bufsize_rms;	/*Max # of RMS words that can be sent */
 	DBC_ASSERT(max == RMS_COMMANDBUFSIZE);
 	chars_in_rms_word = sizeof(rms_word) / disp_obj->char_size;
 	/* Number of RMS words needed to hold arg data */
@@ -347,7 +347,7 @@ int disp_node_create(struct disp_object *disp_obj,
 	 */
 	if (!status) {
 		total = 0;	/* Total number of words in buffer so far */
-		pdw_buf = (rms_word *) disp_obj->pbuf;
+		pdw_buf = (rms_word *) disp_obj->buf;
 		rms_cmd = (struct rms_command *)pdw_buf;
 		rms_cmd->fxn = (rms_word) (rms_fxn);
 		rms_cmd->arg1 = (rms_word) (ul_create_fxn);
@@ -402,16 +402,16 @@ int disp_node_create(struct disp_object *disp_obj,
 			more_task_args->sysstack_size =
 			    task_arg_obj.sys_stack_size;
 			more_task_args->stack_seg = task_arg_obj.stack_seg;
-			more_task_args->heap_addr = task_arg_obj.udsp_heap_addr;
+			more_task_args->heap_addr = task_arg_obj.dsp_heap_addr;
 			more_task_args->heap_size = task_arg_obj.heap_size;
-			more_task_args->misc = task_arg_obj.ul_dais_arg;
+			more_task_args->misc = task_arg_obj.dais_arg;
 			more_task_args->num_input_streams =
 			    task_arg_obj.num_inputs;
 			total +=
 			    sizeof(struct rms_more_task_args) /
 			    sizeof(rms_word);
-			dev_dbg(bridge, "%s: udsp_heap_addr %x, heap_size %x\n",
-				__func__, task_arg_obj.udsp_heap_addr,
+			dev_dbg(bridge, "%s: dsp_heap_addr %x, heap_size %x\n",
+				__func__, task_arg_obj.dsp_heap_addr,
 				task_arg_obj.heap_size);
 			/* Keep track of pSIOInDef[] and pSIOOutDef[]
 			 * positions in the buffer, since this needs to be
@@ -460,17 +460,6 @@ int disp_node_create(struct disp_object *disp_obj,
 		DBC_ASSERT(ul_bytes < (RMS_COMMANDBUFSIZE * sizeof(rms_word)));
 		status = send_message(disp_obj, node_get_timeout(hnode),
 				      ul_bytes, node_env);
-		if (status >= 0) {
-			/*
-			 * Message successfully received from RMS.
-			 * Return the status of the Node's create function
-			 * on the DSP-side
-			 */
-			status = (((rms_word *) (disp_obj->pbuf))[0]);
-			if (status < 0)
-				dev_dbg(bridge, "%s: DSP-side failed: 0x%x\n",
-					__func__, status);
-		}
 	}
 func_end:
 	return status;
@@ -495,7 +484,7 @@ int disp_node_delete(struct disp_object *disp_obj,
 	DBC_REQUIRE(disp_obj);
 	DBC_REQUIRE(hnode != NULL);
 
-	status = dev_get_dev_type(disp_obj->hdev_obj, &dev_type);
+	status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);
 
 	if (!status) {
 
@@ -504,7 +493,7 @@ int disp_node_delete(struct disp_object *disp_obj,
 			/*
 			 *  Fill in buffer to send to RMS
 			 */
-			rms_cmd = (struct rms_command *)disp_obj->pbuf;
+			rms_cmd = (struct rms_command *)disp_obj->buf;
 			rms_cmd->fxn = (rms_word) (rms_fxn);
 			rms_cmd->arg1 = (rms_word) node_env;
 			rms_cmd->arg2 = (rms_word) (ul_delete_fxn);
@@ -513,18 +502,6 @@ int disp_node_delete(struct disp_object *disp_obj,
 			status = send_message(disp_obj, node_get_timeout(hnode),
 					      sizeof(struct rms_command),
 					      &dw_arg);
-			if (status >= 0) {
-				/*
-				 * Message successfully received from RMS.
-				 * Return the status of the Node's delete
-				 * function on the DSP-side
-				 */
-				status = (((rms_word *) (disp_obj->pbuf))[0]);
-				if (status < 0)
-					dev_dbg(bridge, "%s: DSP-side failed: "
-						"0x%x\n", __func__, status);
-			}
-
 		}
 	}
 	return status;
@@ -548,7 +525,7 @@ int disp_node_run(struct disp_object *disp_obj,
 	DBC_REQUIRE(disp_obj);
 	DBC_REQUIRE(hnode != NULL);
 
-	status = dev_get_dev_type(disp_obj->hdev_obj, &dev_type);
+	status = dev_get_dev_type(disp_obj->dev_obj, &dev_type);
 
 	if (!status) {
 
@@ -557,7 +534,7 @@ int disp_node_run(struct disp_object *disp_obj,
 			/*
 			 *  Fill in buffer to send to RMS.
 			 */
-			rms_cmd = (struct rms_command *)disp_obj->pbuf;
+			rms_cmd = (struct rms_command *)disp_obj->buf;
 			rms_cmd->fxn = (rms_word) (rms_fxn);
 			rms_cmd->arg1 = (rms_word) node_env;
 			rms_cmd->arg2 = (rms_word) (ul_execute_fxn);
@@ -566,18 +543,6 @@ int disp_node_run(struct disp_object *disp_obj,
 			status = send_message(disp_obj, node_get_timeout(hnode),
 					      sizeof(struct rms_command),
 					      &dw_arg);
-			if (status >= 0) {
-				/*
-				 * Message successfully received from RMS.
-				 * Return the status of the Node's execute
-				 * function on the DSP-side
-				 */
-				status = (((rms_word *) (disp_obj->pbuf))[0]);
-				if (status < 0)
-					dev_dbg(bridge, "%s: DSP-side failed: "
-						"0x%x\n", __func__, status);
-			}
-
 		}
 	}
 
@@ -601,7 +566,7 @@ static void delete_disp(struct disp_object *disp_obj)
 		if (disp_obj->chnl_from_dsp) {
 			/* Channel close can fail only if the channel handle
 			 * is invalid. */
-			status = (*intf_fxns->pfn_chnl_close)
+			status = (*intf_fxns->chnl_close)
 			    (disp_obj->chnl_from_dsp);
 			if (status) {
 				dev_dbg(bridge, "%s: Failed to close channel "
@@ -610,14 +575,14 @@ static void delete_disp(struct disp_object *disp_obj)
 		}
 		if (disp_obj->chnl_to_dsp) {
 			status =
-			    (*intf_fxns->pfn_chnl_close) (disp_obj->
+			    (*intf_fxns->chnl_close) (disp_obj->
 							  chnl_to_dsp);
 			if (status) {
 				dev_dbg(bridge, "%s: Failed to close channel to"
 					" RMS: 0x%x\n", __func__, status);
 			}
 		}
-		kfree(disp_obj->pbuf);
+		kfree(disp_obj->buf);
 
 		kfree(disp_obj);
 	}
@@ -646,7 +611,7 @@ static int fill_stream_def(rms_word *pdw_buf, u32 *ptotal, u32 offset,
 		strm_def_obj->nbufs = strm_def.num_bufs;
 		strm_def_obj->segid = strm_def.seg_id;
 		strm_def_obj->align = strm_def.buf_alignment;
-		strm_def_obj->timeout = strm_def.utimeout;
+		strm_def_obj->timeout = strm_def.timeout;
 	}
 
 	if (!status) {
@@ -699,16 +664,16 @@ static int send_message(struct disp_object *disp_obj, u32 timeout,
 	*pdw_arg = (u32) NULL;
 	intf_fxns = disp_obj->intf_fxns;
 	chnl_obj = disp_obj->chnl_to_dsp;
-	pbuf = disp_obj->pbuf;
+	pbuf = disp_obj->buf;
 
 	/* Send the command */
-	status = (*intf_fxns->pfn_chnl_add_io_req) (chnl_obj, pbuf, ul_bytes, 0,
+	status = (*intf_fxns->chnl_add_io_req) (chnl_obj, pbuf, ul_bytes, 0,
 						    0L, dw_arg);
 	if (status)
 		goto func_end;
 
 	status =
-	    (*intf_fxns->pfn_chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj);
+	    (*intf_fxns->chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj);
 	if (!status) {
 		if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
 			if (CHNL_IS_TIMED_OUT(chnl_ioc_obj))
@@ -723,13 +688,13 @@ static int send_message(struct disp_object *disp_obj, u32 timeout,
 
 	chnl_obj = disp_obj->chnl_from_dsp;
 	ul_bytes = REPLYSIZE;
-	status = (*intf_fxns->pfn_chnl_add_io_req) (chnl_obj, pbuf, ul_bytes,
+	status = (*intf_fxns->chnl_add_io_req) (chnl_obj, pbuf, ul_bytes,
 						    0, 0L, dw_arg);
 	if (status)
 		goto func_end;
 
 	status =
-	    (*intf_fxns->pfn_chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj);
+	    (*intf_fxns->chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj);
 	if (!status) {
 		if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) {
 			status = -ETIME;
@@ -738,10 +703,17 @@ static int send_message(struct disp_object *disp_obj, u32 timeout,
 			status = -EPERM;
 		} else {
 			if (CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
-				DBC_ASSERT(chnl_ioc_obj.pbuf == pbuf);
-				status = (*((rms_word *) chnl_ioc_obj.pbuf));
+				DBC_ASSERT(chnl_ioc_obj.buf == pbuf);
+				if (*((int *)chnl_ioc_obj.buf) < 0) {
+					/* Translate DSP's to kernel error */
+					status = -EREMOTEIO;
+					dev_dbg(bridge, "%s: DSP-side failed:"
+						" DSP errcode = 0x%x, Kernel "
+						"errcode = %d\n", __func__,
+						*(int *)pbuf, status);
+				}
 				*pdw_arg =
-				    (((rms_word *) (chnl_ioc_obj.pbuf))[1]);
+				    (((rms_word *) (chnl_ioc_obj.buf))[1]);
 			} else {
 				status = -EPERM;
 			}
diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c
index 81b1b90..8c88583 100644
--- a/drivers/staging/tidspbridge/rmgr/drv.c
+++ b/drivers/staging/tidspbridge/rmgr/drv.c
@@ -16,6 +16,7 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 #include <linux/types.h>
+#include <linux/list.h>
 
 /*  ----------------------------------- Host OS */
 #include <dspbridge/host_os.h>
@@ -26,9 +27,6 @@
 /*  ----------------------------------- Trace & Debug */
 #include <dspbridge/dbc.h>
 
-/*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
-
 /*  ----------------------------------- This */
 #include <dspbridge/drv.h>
 #include <dspbridge/dev.h>
@@ -42,8 +40,8 @@
 
 /*  ----------------------------------- Defines, Data Structures, Typedefs */
 struct drv_object {
-	struct lst_list *dev_list;
-	struct lst_list *dev_node_string;
+	struct list_head dev_list;
+	struct list_head dev_node_string;
 };
 
 /*
@@ -91,7 +89,7 @@ int drv_insert_node_res_element(void *hnode, void *node_resource,
 		goto func_end;
 	}
 
-	(*node_res_obj)->hnode = hnode;
+	(*node_res_obj)->node = hnode;
 	retval = idr_get_new(ctxt->node_id, *node_res_obj,
 						&(*node_res_obj)->id);
 	if (retval == -EAGAIN) {
@@ -125,13 +123,13 @@ static int drv_proc_free_node_res(int id, void *p, void *data)
 	u32 node_state;
 
 	if (node_res_obj->node_allocated) {
-		node_state = node_get_state(node_res_obj->hnode);
+		node_state = node_get_state(node_res_obj->node);
 		if (node_state <= NODE_DELETING) {
 			if ((node_state == NODE_RUNNING) ||
 			    (node_state == NODE_PAUSED) ||
 			    (node_state == NODE_TERMINATING))
 				node_terminate
-				    (node_res_obj->hnode, &status);
+				    (node_res_obj->node, &status);
 
 			node_delete(node_res_obj, ctxt);
 		}
@@ -150,7 +148,7 @@ int drv_remove_all_dmm_res_elements(void *process_ctxt)
 
 	/* Free DMM mapped memory resources */
 	list_for_each_entry_safe(map_obj, temp_map, &ctxt->dmm_map_list, link) {
-		status = proc_un_map(ctxt->hprocessor,
+		status = proc_un_map(ctxt->processor,
 				     (void *)map_obj->dsp_addr, ctxt);
 		if (status)
 			pr_err("%s: proc_un_map failed!"
@@ -159,7 +157,7 @@ int drv_remove_all_dmm_res_elements(void *process_ctxt)
 
 	/* Free DMM reserved memory resources */
 	list_for_each_entry_safe(rsv_obj, temp_rsv, &ctxt->dmm_rsv_list, link) {
-		status = proc_un_reserve_memory(ctxt->hprocessor, (void *)
+		status = proc_un_reserve_memory(ctxt->processor, (void *)
 						rsv_obj->dsp_reserved_addr,
 						ctxt);
 		if (status)
@@ -218,7 +216,7 @@ int drv_proc_insert_strm_res_element(void *stream_obj,
 		goto func_end;
 	}
 
-	(*pstrm_res)->hstream = stream_obj;
+	(*pstrm_res)->stream = stream_obj;
 	retval = idr_get_new(ctxt->stream_id, *pstrm_res,
 						&(*pstrm_res)->id);
 	if (retval == -EAGAIN) {
@@ -265,9 +263,9 @@ static int drv_proc_free_strm_res(int id, void *p, void *process_ctxt)
 	}
 	strm_info.user_strm = &user;
 	user.number_bufs_in_stream = 0;
-	strm_get_info(strm_res->hstream, &strm_info, sizeof(strm_info));
+	strm_get_info(strm_res->stream, &strm_info, sizeof(strm_info));
 	while (user.number_bufs_in_stream--)
-		strm_reclaim(strm_res->hstream, &buf_ptr, &ul_bytes,
+		strm_reclaim(strm_res->stream, &buf_ptr, &ul_bytes,
 			     (u32 *) &ul_buf_size, &dw_arg);
 	strm_close(strm_res, ctxt);
 	return 0;
@@ -316,22 +314,8 @@ int drv_create(struct drv_object **drv_obj)
 	pdrv_object = kzalloc(sizeof(struct drv_object), GFP_KERNEL);
 	if (pdrv_object) {
 		/* Create and Initialize List of device objects */
-		pdrv_object->dev_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		if (pdrv_object->dev_list) {
-			/* Create and Initialize List of device Extension */
-			pdrv_object->dev_node_string =
-				kzalloc(sizeof(struct lst_list), GFP_KERNEL);
-			if (!(pdrv_object->dev_node_string)) {
-				status = -EPERM;
-			} else {
-				INIT_LIST_HEAD(&pdrv_object->
-					       dev_node_string->head);
-				INIT_LIST_HEAD(&pdrv_object->dev_list->head);
-			}
-		} else {
-			status = -ENOMEM;
-		}
+		INIT_LIST_HEAD(&pdrv_object->dev_list);
+		INIT_LIST_HEAD(&pdrv_object->dev_node_string);
 	} else {
 		status = -ENOMEM;
 	}
@@ -348,8 +332,6 @@ int drv_create(struct drv_object **drv_obj)
 	if (!status) {
 		*drv_obj = pdrv_object;
 	} else {
-		kfree(pdrv_object->dev_list);
-		kfree(pdrv_object->dev_node_string);
 		/* Free the DRV Object */
 		kfree(pdrv_object);
 	}
@@ -386,13 +368,6 @@ int drv_destroy(struct drv_object *driver_obj)
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(pdrv_object);
 
-	/*
-	 *  Delete the List if it exists.Should not come here
-	 *  as the drv_remove_dev_object and the Last drv_request_resources
-	 *  removes the list if the lists are empty.
-	 */
-	kfree(pdrv_object->dev_list);
-	kfree(pdrv_object->dev_node_string);
 	kfree(pdrv_object);
 	/* Update the DRV Object in the driver data */
 	if (drv_datap) {
@@ -424,7 +399,7 @@ int drv_get_dev_object(u32 index, struct drv_object *hdrv_obj,
 	DBC_REQUIRE(device_obj != NULL);
 	DBC_REQUIRE(index >= 0);
 	DBC_REQUIRE(refs > 0);
-	DBC_ASSERT(!(LST_IS_EMPTY(pdrv_obj->dev_list)));
+	DBC_ASSERT(!(list_empty(&pdrv_obj->dev_list)));
 
 	dev_obj = (struct dev_object *)drv_get_first_dev_object();
 	for (i = 0; i < index; i++) {
@@ -455,9 +430,8 @@ u32 drv_get_first_dev_object(void)
 
 	if (drv_datap && drv_datap->drv_object) {
 		pdrv_obj = drv_datap->drv_object;
-		if ((pdrv_obj->dev_list != NULL) &&
-		    !LST_IS_EMPTY(pdrv_obj->dev_list))
-			dw_dev_object = (u32) lst_first(pdrv_obj->dev_list);
+		if (!list_empty(&pdrv_obj->dev_list))
+			dw_dev_object = (u32) pdrv_obj->dev_list.next;
 	} else {
 		pr_err("%s: Failed to retrieve the object handle\n", __func__);
 	}
@@ -479,10 +453,9 @@ u32 drv_get_first_dev_extension(void)
 
 	if (drv_datap && drv_datap->drv_object) {
 		pdrv_obj = drv_datap->drv_object;
-		if ((pdrv_obj->dev_node_string != NULL) &&
-		    !LST_IS_EMPTY(pdrv_obj->dev_node_string)) {
+		if (!list_empty(&pdrv_obj->dev_node_string)) {
 			dw_dev_extension =
-			    (u32) lst_first(pdrv_obj->dev_node_string);
+			    (u32) pdrv_obj->dev_node_string.next;
 		}
 	} else {
 		pr_err("%s: Failed to retrieve the object handle\n", __func__);
@@ -503,16 +476,15 @@ u32 drv_get_next_dev_object(u32 hdev_obj)
 	u32 dw_next_dev_object = 0;
 	struct drv_object *pdrv_obj;
 	struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
-	DBC_REQUIRE(hdev_obj != 0);
+	struct list_head *curr;
 
 	if (drv_datap && drv_datap->drv_object) {
 		pdrv_obj = drv_datap->drv_object;
-		if ((pdrv_obj->dev_list != NULL) &&
-		    !LST_IS_EMPTY(pdrv_obj->dev_list)) {
-			dw_next_dev_object = (u32) lst_next(pdrv_obj->dev_list,
-							    (struct list_head *)
-							    hdev_obj);
+		if (!list_empty(&pdrv_obj->dev_list)) {
+			curr = (struct list_head *)hdev_obj;
+			if (list_is_last(curr, &pdrv_obj->dev_list))
+				return 0;
+			dw_next_dev_object = (u32) curr->next;
 		}
 	} else {
 		pr_err("%s: Failed to retrieve the object handle\n", __func__);
@@ -534,16 +506,15 @@ u32 drv_get_next_dev_extension(u32 dev_extension)
 	u32 dw_dev_extension = 0;
 	struct drv_object *pdrv_obj;
 	struct drv_data *drv_datap = dev_get_drvdata(bridge);
-
-	DBC_REQUIRE(dev_extension != 0);
+	struct list_head *curr;
 
 	if (drv_datap && drv_datap->drv_object) {
 		pdrv_obj = drv_datap->drv_object;
-		if ((pdrv_obj->dev_node_string != NULL) &&
-		    !LST_IS_EMPTY(pdrv_obj->dev_node_string)) {
-			dw_dev_extension =
-			    (u32) lst_next(pdrv_obj->dev_node_string,
-					   (struct list_head *)dev_extension);
+		if (!list_empty(&pdrv_obj->dev_node_string)) {
+			curr = (struct list_head *)dev_extension;
+			if (list_is_last(curr, &pdrv_obj->dev_node_string))
+				return 0;
+			dw_dev_extension = (u32) curr->next;
 		}
 	} else {
 		pr_err("%s: Failed to retrieve the object handle\n", __func__);
@@ -584,11 +555,8 @@ int drv_insert_dev_object(struct drv_object *driver_obj,
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(hdev_obj != NULL);
 	DBC_REQUIRE(pdrv_object);
-	DBC_ASSERT(pdrv_object->dev_list);
-
-	lst_put_tail(pdrv_object->dev_list, (struct list_head *)hdev_obj);
 
-	DBC_ENSURE(!LST_IS_EMPTY(pdrv_object->dev_list));
+	list_add_tail((struct list_head *)hdev_obj, &pdrv_object->dev_list);
 
 	return 0;
 }
@@ -610,26 +578,17 @@ int drv_remove_dev_object(struct drv_object *driver_obj,
 	DBC_REQUIRE(pdrv_object);
 	DBC_REQUIRE(hdev_obj != NULL);
 
-	DBC_REQUIRE(pdrv_object->dev_list != NULL);
-	DBC_REQUIRE(!LST_IS_EMPTY(pdrv_object->dev_list));
+	DBC_REQUIRE(!list_empty(&pdrv_object->dev_list));
 
 	/* Search list for p_proc_object: */
-	for (cur_elem = lst_first(pdrv_object->dev_list); cur_elem != NULL;
-	     cur_elem = lst_next(pdrv_object->dev_list, cur_elem)) {
+	list_for_each(cur_elem, &pdrv_object->dev_list) {
 		/* If found, remove it. */
 		if ((struct dev_object *)cur_elem == hdev_obj) {
-			lst_remove_elem(pdrv_object->dev_list, cur_elem);
+			list_del(cur_elem);
 			status = 0;
 			break;
 		}
 	}
-	/* Remove list if empty. */
-	if (LST_IS_EMPTY(pdrv_object->dev_list)) {
-		kfree(pdrv_object->dev_list);
-		pdrv_object->dev_list = NULL;
-	}
-	DBC_ENSURE((pdrv_object->dev_list == NULL) ||
-		   !LST_IS_EMPTY(pdrv_object->dev_list));
 
 	return status;
 }
@@ -663,14 +622,13 @@ int drv_request_resources(u32 dw_context, u32 *dev_node_strg)
 	if (!status) {
 		pszdev_node = kzalloc(sizeof(struct drv_ext), GFP_KERNEL);
 		if (pszdev_node) {
-			lst_init_elem(&pszdev_node->link);
 			strncpy(pszdev_node->sz_string,
 				(char *)dw_context, MAXREGPATHLENGTH - 1);
 			pszdev_node->sz_string[MAXREGPATHLENGTH - 1] = '\0';
 			/* Update the Driver Object List */
 			*dev_node_strg = (u32) pszdev_node->sz_string;
-			lst_put_tail(pdrv_object->dev_node_string,
-				     (struct list_head *)pszdev_node);
+			list_add_tail(&pszdev_node->link,
+					&pdrv_object->dev_node_string);
 		} else {
 			status = -ENOMEM;
 			*dev_node_strg = 0;
@@ -682,7 +640,7 @@ int drv_request_resources(u32 dw_context, u32 *dev_node_strg)
 	}
 
 	DBC_ENSURE((!status && dev_node_strg != NULL &&
-		    !LST_IS_EMPTY(pdrv_object->dev_node_string)) ||
+		    !list_empty(&pdrv_object->dev_node_string)) ||
 		   (status && *dev_node_strg == 0));
 
 	return status;
@@ -696,7 +654,6 @@ int drv_request_resources(u32 dw_context, u32 *dev_node_strg)
 int drv_release_resources(u32 dw_context, struct drv_object *hdrv_obj)
 {
 	int status = 0;
-	struct drv_object *pdrv_object = (struct drv_object *)hdrv_obj;
 	struct drv_ext *pszdev_node;
 
 	/*
@@ -706,23 +663,13 @@ int drv_release_resources(u32 dw_context, struct drv_object *hdrv_obj)
 	for (pszdev_node = (struct drv_ext *)drv_get_first_dev_extension();
 	     pszdev_node != NULL; pszdev_node = (struct drv_ext *)
 	     drv_get_next_dev_extension((u32) pszdev_node)) {
-		if (!pdrv_object->dev_node_string) {
-			/* When this could happen? */
-			continue;
-		}
 		if ((u32) pszdev_node == dw_context) {
 			/* Found it */
 			/* Delete from the Driver object list */
-			lst_remove_elem(pdrv_object->dev_node_string,
-					(struct list_head *)pszdev_node);
-			kfree((void *)pszdev_node);
+			list_del(&pszdev_node->link);
+			kfree(pszdev_node);
 			break;
 		}
-		/* Delete the List if it is empty */
-		if (LST_IS_EMPTY(pdrv_object->dev_node_string)) {
-			kfree(pdrv_object->dev_node_string);
-			pdrv_object->dev_node_string = NULL;
-		}
 	}
 	return status;
 }
@@ -740,10 +687,9 @@ static int request_bridge_resources(struct cfg_hostres *res)
 	host_res->num_mem_windows = 2;
 
 	/* First window is for DSP internal memory */
-	host_res->dw_sys_ctrl_base = ioremap(OMAP_SYSC_BASE, OMAP_SYSC_SIZE);
-	dev_dbg(bridge, "dw_mem_base[0] 0x%x\n", host_res->dw_mem_base[0]);
-	dev_dbg(bridge, "dw_mem_base[3] 0x%x\n", host_res->dw_mem_base[3]);
-	dev_dbg(bridge, "dw_dmmu_base %p\n", host_res->dw_dmmu_base);
+	dev_dbg(bridge, "mem_base[0] 0x%x\n", host_res->mem_base[0]);
+	dev_dbg(bridge, "mem_base[3] 0x%x\n", host_res->mem_base[3]);
+	dev_dbg(bridge, "dmmu_base %p\n", host_res->dmmu_base);
 
 	/* for 24xx base port is not mapping the mamory for DSP
 	 * internal memory TODO Do a ioremap here */
@@ -752,11 +698,11 @@ static int request_bridge_resources(struct cfg_hostres *res)
 	/* These are hard-coded values */
 	host_res->birq_registers = 0;
 	host_res->birq_attrib = 0;
-	host_res->dw_offset_for_monitor = 0;
-	host_res->dw_chnl_offset = 0;
+	host_res->offset_for_monitor = 0;
+	host_res->chnl_offset = 0;
 	/* CHNL_MAXCHANNELS */
-	host_res->dw_num_chnls = CHNL_MAXCHANNELS;
-	host_res->dw_chnl_buf_size = 0x400;
+	host_res->num_chnls = CHNL_MAXCHANNELS;
+	host_res->chnl_buf_size = 0x400;
 
 	return 0;
 }
@@ -784,51 +730,51 @@ int drv_request_bridge_res_dsp(void **phost_resources)
 		/* num_mem_windows must not be more than CFG_MAXMEMREGISTERS */
 		host_res->num_mem_windows = 4;
 
-		host_res->dw_mem_base[0] = 0;
-		host_res->dw_mem_base[2] = (u32) ioremap(OMAP_DSP_MEM1_BASE,
+		host_res->mem_base[0] = 0;
+		host_res->mem_base[2] = (u32) ioremap(OMAP_DSP_MEM1_BASE,
 							 OMAP_DSP_MEM1_SIZE);
-		host_res->dw_mem_base[3] = (u32) ioremap(OMAP_DSP_MEM2_BASE,
+		host_res->mem_base[3] = (u32) ioremap(OMAP_DSP_MEM2_BASE,
 							 OMAP_DSP_MEM2_SIZE);
-		host_res->dw_mem_base[4] = (u32) ioremap(OMAP_DSP_MEM3_BASE,
+		host_res->mem_base[4] = (u32) ioremap(OMAP_DSP_MEM3_BASE,
 							 OMAP_DSP_MEM3_SIZE);
-		host_res->dw_per_base = ioremap(OMAP_PER_CM_BASE,
+		host_res->per_base = ioremap(OMAP_PER_CM_BASE,
 						OMAP_PER_CM_SIZE);
-		host_res->dw_per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
+		host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
 							 OMAP_PER_PRM_SIZE);
-		host_res->dw_core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
+		host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
 							  OMAP_CORE_PRM_SIZE);
-		host_res->dw_dmmu_base = ioremap(OMAP_DMMU_BASE,
+		host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,
 						 OMAP_DMMU_SIZE);
 
-		dev_dbg(bridge, "dw_mem_base[0] 0x%x\n",
-			host_res->dw_mem_base[0]);
-		dev_dbg(bridge, "dw_mem_base[1] 0x%x\n",
-			host_res->dw_mem_base[1]);
-		dev_dbg(bridge, "dw_mem_base[2] 0x%x\n",
-			host_res->dw_mem_base[2]);
-		dev_dbg(bridge, "dw_mem_base[3] 0x%x\n",
-			host_res->dw_mem_base[3]);
-		dev_dbg(bridge, "dw_mem_base[4] 0x%x\n",
-			host_res->dw_mem_base[4]);
-		dev_dbg(bridge, "dw_dmmu_base %p\n", host_res->dw_dmmu_base);
+		dev_dbg(bridge, "mem_base[0] 0x%x\n",
+			host_res->mem_base[0]);
+		dev_dbg(bridge, "mem_base[1] 0x%x\n",
+			host_res->mem_base[1]);
+		dev_dbg(bridge, "mem_base[2] 0x%x\n",
+			host_res->mem_base[2]);
+		dev_dbg(bridge, "mem_base[3] 0x%x\n",
+			host_res->mem_base[3]);
+		dev_dbg(bridge, "mem_base[4] 0x%x\n",
+			host_res->mem_base[4]);
+		dev_dbg(bridge, "dmmu_base %p\n", host_res->dmmu_base);
 
 		shm_size = drv_datap->shm_size;
 		if (shm_size >= 0x10000) {
 			/* Allocate Physically contiguous,
 			 * non-cacheable  memory */
-			host_res->dw_mem_base[1] =
+			host_res->mem_base[1] =
 			    (u32) mem_alloc_phys_mem(shm_size, 0x100000,
 						     &dma_addr);
-			if (host_res->dw_mem_base[1] == 0) {
+			if (host_res->mem_base[1] == 0) {
 				status = -ENOMEM;
 				pr_err("shm reservation Failed\n");
 			} else {
-				host_res->dw_mem_length[1] = shm_size;
-				host_res->dw_mem_phys[1] = dma_addr;
+				host_res->mem_length[1] = shm_size;
+				host_res->mem_phys[1] = dma_addr;
 
 				dev_dbg(bridge, "%s: Bridge shm address 0x%x "
 					"dma_addr %x size %x\n", __func__,
-					host_res->dw_mem_base[1],
+					host_res->mem_base[1],
 					dma_addr, shm_size);
 			}
 		}
@@ -836,11 +782,11 @@ int drv_request_bridge_res_dsp(void **phost_resources)
 			/* These are hard-coded values */
 			host_res->birq_registers = 0;
 			host_res->birq_attrib = 0;
-			host_res->dw_offset_for_monitor = 0;
-			host_res->dw_chnl_offset = 0;
+			host_res->offset_for_monitor = 0;
+			host_res->chnl_offset = 0;
 			/* CHNL_MAXCHANNELS */
-			host_res->dw_num_chnls = CHNL_MAXCHANNELS;
-			host_res->dw_chnl_buf_size = 0x400;
+			host_res->num_chnls = CHNL_MAXCHANNELS;
+			host_res->chnl_buf_size = 0x400;
 			dw_buff_size = sizeof(struct cfg_hostres);
 		}
 		*phost_resources = host_res;
diff --git a/drivers/staging/tidspbridge/rmgr/drv_interface.c b/drivers/staging/tidspbridge/rmgr/drv_interface.c
index 324fcdf..c43c7e3 100644
--- a/drivers/staging/tidspbridge/rmgr/drv_interface.c
+++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c
@@ -59,7 +59,6 @@
 #include <dspbridge/chnl.h>
 #include <dspbridge/proc.h>
 #include <dspbridge/dev.h>
-#include <dspbridge/drvdefs.h>
 #include <dspbridge/drv.h>
 
 #ifdef CONFIG_TIDSPBRIDGE_DVFS
diff --git a/drivers/staging/tidspbridge/rmgr/mgr.c b/drivers/staging/tidspbridge/rmgr/mgr.c
index 0ea89a1..d635c01 100644
--- a/drivers/staging/tidspbridge/rmgr/mgr.c
+++ b/drivers/staging/tidspbridge/rmgr/mgr.c
@@ -44,7 +44,7 @@
 #define ZLDLLNAME               ""
 
 struct mgr_object {
-	struct dcd_manager *hdcd_mgr;	/* Proc/Node data manager */
+	struct dcd_manager *dcd_mgr;	/* Proc/Node data manager */
 };
 
 /*  ----------------------------------- Globals */
@@ -67,7 +67,7 @@ int mgr_create(struct mgr_object **mgr_obj,
 
 	pmgr_obj = kzalloc(sizeof(struct mgr_object), GFP_KERNEL);
 	if (pmgr_obj) {
-		status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->hdcd_mgr);
+		status = dcd_create_manager(ZLDLLNAME, &pmgr_obj->dcd_mgr);
 		if (!status) {
 			/* If succeeded store the handle in the MGR Object */
 			if (drv_datap) {
@@ -81,7 +81,7 @@ int mgr_create(struct mgr_object **mgr_obj,
 			if (!status) {
 				*mgr_obj = pmgr_obj;
 			} else {
-				dcd_destroy_manager(pmgr_obj->hdcd_mgr);
+				dcd_destroy_manager(pmgr_obj->dcd_mgr);
 				kfree(pmgr_obj);
 			}
 		} else {
@@ -110,8 +110,8 @@ int mgr_destroy(struct mgr_object *hmgr_obj)
 	DBC_REQUIRE(hmgr_obj);
 
 	/* Free resources */
-	if (hmgr_obj->hdcd_mgr)
-		dcd_destroy_manager(hmgr_obj->hdcd_mgr);
+	if (hmgr_obj->dcd_mgr)
+		dcd_destroy_manager(hmgr_obj->dcd_mgr);
 
 	kfree(pmgr_obj);
 	/* Update the driver data with NULL for MGR Object */
@@ -134,8 +134,7 @@ int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
 			      u32 undb_props_size, u32 *pu_num_nodes)
 {
 	int status = 0;
-	struct dsp_uuid node_uuid, temp_uuid;
-	u32 temp_index = 0;
+	struct dsp_uuid node_uuid;
 	u32 node_index = 0;
 	struct dcd_genericobj gen_obj;
 	struct mgr_object *pmgr_obj = NULL;
@@ -149,46 +148,33 @@ int mgr_enum_node_info(u32 node_id, struct dsp_ndbprops *pndb_props,
 	*pu_num_nodes = 0;
 	/* Get the Manager Object from the driver data */
 	if (!drv_datap || !drv_datap->mgr_object) {
-		status = -ENODATA;
 		pr_err("%s: Failed to retrieve the object handle\n", __func__);
-		goto func_cont;
-	} else {
-		pmgr_obj = drv_datap->mgr_object;
+		return -ENODATA;
 	}
+	pmgr_obj = drv_datap->mgr_object;
 
 	DBC_ASSERT(pmgr_obj);
 	/* Forever loop till we hit failed or no more items in the
 	 * Enumeration. We will exit the loop other than 0; */
-	while (status == 0) {
-		status = dcd_enumerate_object(temp_index++, DSP_DCDNODETYPE,
-					      &temp_uuid);
-		if (status == 0) {
-			node_index++;
-			if (node_id == (node_index - 1))
-				node_uuid = temp_uuid;
-
-		}
-	}
-	if (!status) {
-		if (node_id > (node_index - 1)) {
-			status = -EINVAL;
-		} else {
-			status = dcd_get_object_def(pmgr_obj->hdcd_mgr,
-						    (struct dsp_uuid *)
-						    &node_uuid, DSP_DCDNODETYPE,
-						    &gen_obj);
-			if (!status) {
-				/* Get the Obj def */
-				*pndb_props =
-				    gen_obj.obj_data.node_obj.ndb_props;
-				*pu_num_nodes = node_index;
-			}
+	while (!status) {
+		status = dcd_enumerate_object(node_index++, DSP_DCDNODETYPE,
+				&node_uuid);
+		if (status)
+			break;
+		*pu_num_nodes = node_index;
+		if (node_id == (node_index - 1)) {
+			status = dcd_get_object_def(pmgr_obj->dcd_mgr,
+					&node_uuid, DSP_DCDNODETYPE, &gen_obj);
+			if (status)
+				break;
+			/* Get the Obj def */
+			*pndb_props = gen_obj.obj_data.node_obj.ndb_props;
 		}
 	}
 
-func_cont:
-	DBC_ENSURE((!status && *pu_num_nodes > 0) ||
-		   (status && *pu_num_nodes == 0));
+	/* the last status is not 0, but neither an error */
+	if (status > 0)
+		status = 0;
 
 	return status;
 }
@@ -272,7 +258,7 @@ int mgr_enum_processor_info(u32 processor_id,
 		if (proc_detect != false)
 			continue;
 
-		status2 = dcd_get_object_def(pmgr_obj->hdcd_mgr,
+		status2 = dcd_get_object_def(pmgr_obj->dcd_mgr,
 					     (struct dsp_uuid *)&temp_uuid,
 					     DSP_DCDPROCESSORTYPE, &gen_obj);
 		if (!status2) {
@@ -347,7 +333,7 @@ int mgr_get_dcd_handle(struct mgr_object *mgr_handle,
 
 	*dcd_handle = (u32) NULL;
 	if (pmgr_obj) {
-		*dcd_handle = (u32) pmgr_obj->hdcd_mgr;
+		*dcd_handle = (u32) pmgr_obj->dcd_mgr;
 		status = 0;
 	}
 	DBC_ENSURE((!status && *dcd_handle != (u32) NULL) ||
diff --git a/drivers/staging/tidspbridge/rmgr/nldr.c b/drivers/staging/tidspbridge/rmgr/nldr.c
index 28354bb..fb5c2ba 100644
--- a/drivers/staging/tidspbridge/rmgr/nldr.c
+++ b/drivers/staging/tidspbridge/rmgr/nldr.c
@@ -190,8 +190,8 @@ struct ovly_node {
  *  Overlay loader object.
  */
 struct nldr_object {
-	struct dev_object *hdev_obj;	/* Device object */
-	struct dcd_manager *hdcd_mgr;	/* Proc/Node data manager */
+	struct dev_object *dev_obj;	/* Device object */
+	struct dcd_manager *dcd_mgr;	/* Proc/Node data manager */
 	struct dbll_tar_obj *dbll;	/* The DBL loader */
 	struct dbll_library_obj *base_lib;	/* Base image library */
 	struct rmm_target_obj *rmm;	/* Remote memory manager for DSP */
@@ -206,8 +206,8 @@ struct nldr_object {
 	u32 *seg_table;		/* memtypes of dynamic memory segs
 				 * indexed by segid
 				 */
-	u16 us_dsp_mau_size;	/* Size of DSP MAU */
-	u16 us_dsp_word_size;	/* Size of DSP word */
+	u16 dsp_mau_size;	/* Size of DSP MAU */
+	u16 dsp_word_size;	/* Size of DSP word */
 };
 
 /*
@@ -220,7 +220,7 @@ struct nldr_nodeobject {
 	struct dsp_uuid uuid;	/* Node's UUID */
 	bool dynamic;		/* Dynamically loaded node? */
 	bool overlay;		/* Overlay node? */
-	bool *pf_phase_split;	/* Multiple phase libraries? */
+	bool *phase_split;	/* Multiple phase libraries? */
 	struct lib_node root;	/* Library containing node phase */
 	struct lib_node create_lib;	/* Library with create phase lib */
 	struct lib_node execute_lib;	/* Library with execute phase lib */
@@ -260,12 +260,9 @@ static struct dbll_fxns ldr_fxns = {
 	(dbll_get_sect_fxn) dbll_get_sect,
 	(dbll_init_fxn) dbll_init,
 	(dbll_load_fxn) dbll_load,
-	(dbll_load_sect_fxn) dbll_load_sect,
 	(dbll_open_fxn) dbll_open,
 	(dbll_read_sect_fxn) dbll_read_sect,
-	(dbll_set_attrs_fxn) dbll_set_attrs,
 	(dbll_unload_fxn) dbll_unload,
-	(dbll_unload_sect_fxn) dbll_unload_sect,
 };
 
 static u32 refs;		/* module reference count */
@@ -329,7 +326,7 @@ int nldr_allocate(struct nldr_object *nldr_obj, void *priv_ref,
 	if (nldr_node_obj == NULL) {
 		status = -ENOMEM;
 	} else {
-		nldr_node_obj->pf_phase_split = pf_phase_split;
+		nldr_node_obj->phase_split = pf_phase_split;
 		nldr_node_obj->pers_libs = 0;
 		nldr_node_obj->nldr_obj = nldr_obj;
 		nldr_node_obj->priv_ref = priv_ref;
@@ -339,7 +336,7 @@ int nldr_allocate(struct nldr_object *nldr_obj, void *priv_ref,
 		 *  Determine if node is a dynamically loaded node from
 		 *  ndb_props.
 		 */
-		if (node_props->us_load_type == NLDR_DYNAMICLOAD) {
+		if (node_props->load_type == NLDR_DYNAMICLOAD) {
 			/* Dynamic node */
 			nldr_node_obj->dynamic = true;
 			/*
@@ -347,51 +344,51 @@ int nldr_allocate(struct nldr_object *nldr_obj, void *priv_ref,
 			 */
 			/* Create phase */
 			nldr_node_obj->seg_id[CREATEDATAFLAGBIT] = (u16)
-			    (node_props->ul_data_mem_seg_mask >> CREATEBIT) &
+			    (node_props->data_mem_seg_mask >> CREATEBIT) &
 			    SEGMASK;
 			nldr_node_obj->code_data_flag_mask |=
-			    ((node_props->ul_data_mem_seg_mask >>
+			    ((node_props->data_mem_seg_mask >>
 			      (CREATEBIT + FLAGBIT)) & 1) << CREATEDATAFLAGBIT;
 			nldr_node_obj->seg_id[CREATECODEFLAGBIT] = (u16)
-			    (node_props->ul_code_mem_seg_mask >>
+			    (node_props->code_mem_seg_mask >>
 			     CREATEBIT) & SEGMASK;
 			nldr_node_obj->code_data_flag_mask |=
-			    ((node_props->ul_code_mem_seg_mask >>
+			    ((node_props->code_mem_seg_mask >>
 			      (CREATEBIT + FLAGBIT)) & 1) << CREATECODEFLAGBIT;
 			/* Execute phase */
 			nldr_node_obj->seg_id[EXECUTEDATAFLAGBIT] = (u16)
-			    (node_props->ul_data_mem_seg_mask >>
+			    (node_props->data_mem_seg_mask >>
 			     EXECUTEBIT) & SEGMASK;
 			nldr_node_obj->code_data_flag_mask |=
-			    ((node_props->ul_data_mem_seg_mask >>
+			    ((node_props->data_mem_seg_mask >>
 			      (EXECUTEBIT + FLAGBIT)) & 1) <<
 			    EXECUTEDATAFLAGBIT;
 			nldr_node_obj->seg_id[EXECUTECODEFLAGBIT] = (u16)
-			    (node_props->ul_code_mem_seg_mask >>
+			    (node_props->code_mem_seg_mask >>
 			     EXECUTEBIT) & SEGMASK;
 			nldr_node_obj->code_data_flag_mask |=
-			    ((node_props->ul_code_mem_seg_mask >>
+			    ((node_props->code_mem_seg_mask >>
 			      (EXECUTEBIT + FLAGBIT)) & 1) <<
 			    EXECUTECODEFLAGBIT;
 			/* Delete phase */
 			nldr_node_obj->seg_id[DELETEDATAFLAGBIT] = (u16)
-			    (node_props->ul_data_mem_seg_mask >> DELETEBIT) &
+			    (node_props->data_mem_seg_mask >> DELETEBIT) &
 			    SEGMASK;
 			nldr_node_obj->code_data_flag_mask |=
-			    ((node_props->ul_data_mem_seg_mask >>
+			    ((node_props->data_mem_seg_mask >>
 			      (DELETEBIT + FLAGBIT)) & 1) << DELETEDATAFLAGBIT;
 			nldr_node_obj->seg_id[DELETECODEFLAGBIT] = (u16)
-			    (node_props->ul_code_mem_seg_mask >>
+			    (node_props->code_mem_seg_mask >>
 			     DELETEBIT) & SEGMASK;
 			nldr_node_obj->code_data_flag_mask |=
-			    ((node_props->ul_code_mem_seg_mask >>
+			    ((node_props->code_mem_seg_mask >>
 			      (DELETEBIT + FLAGBIT)) & 1) << DELETECODEFLAGBIT;
 		} else {
 			/* Non-dynamically loaded nodes are part of the
 			 * base image */
 			nldr_node_obj->root.lib = nldr_obj->base_lib;
 			/* Check for overlay node */
-			if (node_props->us_load_type == NLDR_OVLYLOAD)
+			if (node_props->load_type == NLDR_OVLYLOAD)
 				nldr_node_obj->overlay = true;
 
 		}
@@ -432,13 +429,13 @@ int nldr_create(struct nldr_object **nldr,
 	DBC_REQUIRE(nldr != NULL);
 	DBC_REQUIRE(hdev_obj != NULL);
 	DBC_REQUIRE(pattrs != NULL);
-	DBC_REQUIRE(pattrs->pfn_ovly != NULL);
-	DBC_REQUIRE(pattrs->pfn_write != NULL);
+	DBC_REQUIRE(pattrs->ovly != NULL);
+	DBC_REQUIRE(pattrs->write != NULL);
 
 	/* Allocate dynamic loader object */
 	nldr_obj = kzalloc(sizeof(struct nldr_object), GFP_KERNEL);
 	if (nldr_obj) {
-		nldr_obj->hdev_obj = hdev_obj;
+		nldr_obj->dev_obj = hdev_obj;
 		/* warning, lazy status checking alert! */
 		dev_get_cod_mgr(hdev_obj, &cod_mgr);
 		if (cod_mgr) {
@@ -453,8 +450,8 @@ int nldr_create(struct nldr_object **nldr,
 		}
 		status = 0;
 		/* end lazy status checking */
-		nldr_obj->us_dsp_mau_size = pattrs->us_dsp_mau_size;
-		nldr_obj->us_dsp_word_size = pattrs->us_dsp_word_size;
+		nldr_obj->dsp_mau_size = pattrs->dsp_mau_size;
+		nldr_obj->dsp_word_size = pattrs->dsp_word_size;
 		nldr_obj->ldr_fxns = ldr_fxns;
 		if (!(nldr_obj->ldr_fxns.init_fxn()))
 			status = -ENOMEM;
@@ -464,7 +461,7 @@ int nldr_create(struct nldr_object **nldr,
 	}
 	/* Create the DCD Manager */
 	if (!status)
-		status = dcd_create_manager(NULL, &nldr_obj->hdcd_mgr);
+		status = dcd_create_manager(NULL, &nldr_obj->dcd_mgr);
 
 	/* Get dynamic loading memory sections from base lib */
 	if (!status) {
@@ -474,7 +471,7 @@ int nldr_create(struct nldr_object **nldr,
 						    &ul_len);
 		if (!status) {
 			psz_coff_buf =
-				kzalloc(ul_len * nldr_obj->us_dsp_mau_size,
+				kzalloc(ul_len * nldr_obj->dsp_mau_size,
 								GFP_KERNEL);
 			if (!psz_coff_buf)
 				status = -ENOMEM;
@@ -536,9 +533,9 @@ int nldr_create(struct nldr_object **nldr,
 		new_attrs.free = (dbll_free_fxn) remote_free;
 		new_attrs.sym_lookup = (dbll_sym_lookup) get_symbol_value;
 		new_attrs.sym_handle = nldr_obj;
-		new_attrs.write = (dbll_write_fxn) pattrs->pfn_write;
-		nldr_obj->ovly_fxn = pattrs->pfn_ovly;
-		nldr_obj->write_fxn = pattrs->pfn_write;
+		new_attrs.write = (dbll_write_fxn) pattrs->write;
+		nldr_obj->ovly_fxn = pattrs->ovly;
+		nldr_obj->write_fxn = pattrs->write;
 		nldr_obj->ldr_attrs = new_attrs;
 	}
 	kfree(rmm_segs);
@@ -553,7 +550,7 @@ int nldr_create(struct nldr_object **nldr,
 		DBC_ASSERT(!status);
 		/* First count number of overlay nodes */
 		status =
-		    dcd_get_objects(nldr_obj->hdcd_mgr, sz_zl_file,
+		    dcd_get_objects(nldr_obj->dcd_mgr, sz_zl_file,
 				    add_ovly_node, (void *)nldr_obj);
 		/* Now build table of overlay nodes */
 		if (!status && nldr_obj->ovly_nodes > 0) {
@@ -563,7 +560,7 @@ int nldr_create(struct nldr_object **nldr,
 					nldr_obj->ovly_nodes, GFP_KERNEL);
 			/* Put overlay nodes in the table */
 			nldr_obj->ovly_nid = 0;
-			status = dcd_get_objects(nldr_obj->hdcd_mgr, sz_zl_file,
+			status = dcd_get_objects(nldr_obj->dcd_mgr, sz_zl_file,
 						 add_ovly_node,
 						 (void *)nldr_obj);
 		}
@@ -607,8 +604,8 @@ void nldr_delete(struct nldr_object *nldr_obj)
 
 	kfree(nldr_obj->seg_table);
 
-	if (nldr_obj->hdcd_mgr)
-		dcd_destroy_manager(nldr_obj->hdcd_mgr);
+	if (nldr_obj->dcd_mgr)
+		dcd_destroy_manager(nldr_obj->dcd_mgr);
 
 	/* Free overlay node information */
 	if (nldr_obj->ovly_table) {
@@ -681,7 +678,7 @@ int nldr_get_fxn_addr(struct nldr_nodeobject *nldr_node_obj,
 
 	nldr_obj = nldr_node_obj->nldr_obj;
 	/* Called from node_create(), node_delete(), or node_run(). */
-	if (nldr_node_obj->dynamic && *nldr_node_obj->pf_phase_split) {
+	if (nldr_node_obj->dynamic && *nldr_node_obj->phase_split) {
 		switch (nldr_node_obj->phase) {
 		case NLDR_CREATE:
 			root = nldr_node_obj->create_lib;
@@ -824,7 +821,7 @@ int nldr_load(struct nldr_nodeobject *nldr_node_obj,
 			     false, nldr_node_obj->lib_path, phase, 0);
 
 		if (!status) {
-			if (*nldr_node_obj->pf_phase_split) {
+			if (*nldr_node_obj->phase_split) {
 				switch (phase) {
 				case NLDR_CREATE:
 					nldr_node_obj->create_lib =
@@ -871,7 +868,7 @@ int nldr_unload(struct nldr_nodeobject *nldr_node_obj,
 
 	if (nldr_node_obj != NULL) {
 		if (nldr_node_obj->dynamic) {
-			if (*nldr_node_obj->pf_phase_split) {
+			if (*nldr_node_obj->phase_split) {
 				switch (phase) {
 				case NLDR_CREATE:
 					root_lib = &nldr_node_obj->create_lib;
@@ -1008,13 +1005,13 @@ static int add_ovly_node(struct dsp_uuid *uuid_obj,
 		goto func_end;
 
 	status =
-	    dcd_get_object_def(nldr_obj->hdcd_mgr, uuid_obj, obj_type,
+	    dcd_get_object_def(nldr_obj->dcd_mgr, uuid_obj, obj_type,
 			       &obj_def);
 	if (status)
 		goto func_end;
 
 	/* If overlay node, add to the list */
-	if (obj_def.obj_data.node_obj.us_load_type == NLDR_OVLYLOAD) {
+	if (obj_def.obj_data.node_obj.load_type == NLDR_OVLYLOAD) {
 		if (nldr_obj->ovly_table == NULL) {
 			nldr_obj->ovly_nodes++;
 		} else {
@@ -1038,13 +1035,13 @@ static int add_ovly_node(struct dsp_uuid *uuid_obj,
 		}
 	}
 	/* These were allocated in dcd_get_object_def */
-	kfree(obj_def.obj_data.node_obj.pstr_create_phase_fxn);
+	kfree(obj_def.obj_data.node_obj.str_create_phase_fxn);
 
-	kfree(obj_def.obj_data.node_obj.pstr_execute_phase_fxn);
+	kfree(obj_def.obj_data.node_obj.str_execute_phase_fxn);
 
-	kfree(obj_def.obj_data.node_obj.pstr_delete_phase_fxn);
+	kfree(obj_def.obj_data.node_obj.str_delete_phase_fxn);
 
-	kfree(obj_def.obj_data.node_obj.pstr_i_alg_name);
+	kfree(obj_def.obj_data.node_obj.str_i_alg_name);
 
 func_end:
 	return status;
@@ -1265,14 +1262,14 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj,
 		if (depth == 0) {
 			status =
 			    dcd_get_library_name(nldr_node_obj->nldr_obj->
-						 hdcd_mgr, &uuid, psz_file_name,
+						 dcd_mgr, &uuid, psz_file_name,
 						 &dw_buf_size, phase,
-						 nldr_node_obj->pf_phase_split);
+						 nldr_node_obj->phase_split);
 		} else {
 			/* Dependent libraries are registered with a phase */
 			status =
 			    dcd_get_library_name(nldr_node_obj->nldr_obj->
-						 hdcd_mgr, &uuid, psz_file_name,
+						 dcd_mgr, &uuid, psz_file_name,
 						 &dw_buf_size, NLDR_NOPHASE,
 						 NULL);
 		}
@@ -1312,12 +1309,12 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj,
 		depth++;
 		/* Get number of dependent libraries */
 		status =
-		    dcd_get_num_dep_libs(nldr_node_obj->nldr_obj->hdcd_mgr,
+		    dcd_get_num_dep_libs(nldr_node_obj->nldr_obj->dcd_mgr,
 					 &uuid, &nd_libs, &np_libs, phase);
 	}
 	DBC_ASSERT(nd_libs >= np_libs);
 	if (!status) {
-		if (!(*nldr_node_obj->pf_phase_split))
+		if (!(*nldr_node_obj->phase_split))
 			np_libs = 0;
 
 		/* nd_libs = #of dependent libraries */
@@ -1345,7 +1342,7 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj,
 				/* Get the dependent library UUIDs */
 				status =
 				    dcd_get_dep_libs(nldr_node_obj->
-						     nldr_obj->hdcd_mgr, &uuid,
+						     nldr_obj->dcd_mgr, &uuid,
 						     nd_libs, dep_lib_uui_ds,
 						     persistent_dep_libs,
 						     phase);
@@ -1362,7 +1359,7 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj,
 			 * is, then record it.  If root library IS persistent,
 			 * the deplib is already included */
 			if (!root_prstnt && persistent_dep_libs[i] &&
-			    *nldr_node_obj->pf_phase_split) {
+			    *nldr_node_obj->phase_split) {
 				if ((nldr_node_obj->pers_libs) >= MAXLIBS) {
 					status = -EILSEQ;
 					break;
@@ -1388,11 +1385,11 @@ static int load_lib(struct nldr_nodeobject *nldr_node_obj,
 			if (!status) {
 				if ((status != 0) &&
 				    !root_prstnt && persistent_dep_libs[i] &&
-				    *nldr_node_obj->pf_phase_split) {
+				    *nldr_node_obj->phase_split) {
 					(nldr_node_obj->pers_libs)++;
 				} else {
 					if (!persistent_dep_libs[i] ||
-					    !(*nldr_node_obj->pf_phase_split)) {
+					    !(*nldr_node_obj->phase_split)) {
 						nd_libs_loaded++;
 					}
 				}
@@ -1633,8 +1630,8 @@ static int remote_alloc(void **ref, u16 mem_sect, u32 size,
 	rmm = nldr_obj->rmm;
 	/* Convert size to DSP words */
 	word_size =
-	    (size + nldr_obj->us_dsp_word_size -
-	     1) / nldr_obj->us_dsp_word_size;
+	    (size + nldr_obj->dsp_word_size -
+	     1) / nldr_obj->dsp_word_size;
 	/* Modify memory 'align' to account for DSP cache line size */
 	align = lcm(GEM_CACHE_LINE_SIZE, align);
 	dev_dbg(bridge, "%s: memory align to 0x%x\n", __func__, align);
@@ -1745,8 +1742,8 @@ static int remote_free(void **ref, u16 space, u32 dsp_address,
 
 	/* Convert size to DSP words */
 	word_size =
-	    (size + nldr_obj->us_dsp_word_size -
-	     1) / nldr_obj->us_dsp_word_size;
+	    (size + nldr_obj->dsp_word_size -
+	     1) / nldr_obj->dsp_word_size;
 
 	if (rmm_free(rmm, space, dsp_address, word_size, reserve))
 		status = 0;
@@ -1906,7 +1903,7 @@ int nldr_find_addr(struct nldr_nodeobject *nldr_node, u32 sym_addr,
 	pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x,  %s)\n", __func__, (u32) nldr_node,
 			sym_addr, offset_range, (u32) offset_output, sym_name);
 
-	if (nldr_node->dynamic && *nldr_node->pf_phase_split) {
+	if (nldr_node->dynamic && *nldr_node->phase_split) {
 		switch (nldr_node->phase) {
 		case NLDR_CREATE:
 			root = nldr_node->create_lib;
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
index 1562f3c..5dadaa4 100644
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ b/drivers/staging/tidspbridge/rmgr/node.c
@@ -17,6 +17,9 @@
  */
 
 #include <linux/types.h>
+#include <linux/bitmap.h>
+#include <linux/list.h>
+
 /*  ----------------------------------- Host OS */
 #include <dspbridge/host_os.h>
 
@@ -27,7 +30,6 @@
 #include <dspbridge/dbc.h>
 
 /*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
 #include <dspbridge/memdefs.h>
 #include <dspbridge/proc.h>
 #include <dspbridge/strm.h>
@@ -50,7 +52,6 @@
 #include <dspbridge/dspioctl.h>
 
 /*  ----------------------------------- Others */
-#include <dspbridge/gb.h>
 #include <dspbridge/uuidutil.h>
 
 /*  ----------------------------------- This */
@@ -63,7 +64,6 @@
 #include <dspbridge/nldr.h>
 
 #include <dspbridge/drv.h>
-#include <dspbridge/drvdefs.h>
 #include <dspbridge/resourcecleanup.h>
 #include <_tiomap.h>
 
@@ -124,33 +124,36 @@
  *  ======== node_mgr ========
  */
 struct node_mgr {
-	struct dev_object *hdev_obj;	/* Device object */
+	struct dev_object *dev_obj;	/* Device object */
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
-	struct dcd_manager *hdcd_mgr;	/* Proc/Node data manager */
+	struct dcd_manager *dcd_mgr;	/* Proc/Node data manager */
 	struct disp_object *disp_obj;	/* Node dispatcher */
-	struct lst_list *node_list;	/* List of all allocated nodes */
+	struct list_head node_list;	/* List of all allocated nodes */
 	u32 num_nodes;		/* Number of nodes in node_list */
 	u32 num_created;	/* Number of nodes *created* on DSP */
-	struct gb_t_map *pipe_map;	/* Pipe connection bit map */
-	struct gb_t_map *pipe_done_map;	/* Pipes that are half free */
-	struct gb_t_map *chnl_map;	/* Channel allocation bit map */
-	struct gb_t_map *dma_chnl_map;	/* DMA Channel allocation bit map */
-	struct gb_t_map *zc_chnl_map;	/* Zero-Copy Channel alloc bit map */
+	DECLARE_BITMAP(pipe_map, MAXPIPES); /* Pipe connection bitmap */
+	DECLARE_BITMAP(pipe_done_map, MAXPIPES); /* Pipes that are half free */
+	/* Channel allocation bitmap */
+	DECLARE_BITMAP(chnl_map, CHNL_MAXCHANNELS);
+	/* DMA Channel allocation bitmap */
+	DECLARE_BITMAP(dma_chnl_map, CHNL_MAXCHANNELS);
+	/* Zero-Copy Channel alloc bitmap */
+	DECLARE_BITMAP(zc_chnl_map, CHNL_MAXCHANNELS);
 	struct ntfy_object *ntfy_obj;	/* Manages registered notifications */
 	struct mutex node_mgr_lock;	/* For critical sections */
-	u32 ul_fxn_addrs[NUMRMSFXNS];	/* RMS function addresses */
+	u32 fxn_addrs[NUMRMSFXNS];	/* RMS function addresses */
 	struct msg_mgr *msg_mgr_obj;
 
 	/* Processor properties needed by Node Dispatcher */
-	u32 ul_num_chnls;	/* Total number of channels */
-	u32 ul_chnl_offset;	/* Offset of chnl ids rsvd for RMS */
-	u32 ul_chnl_buf_size;	/* Buffer size for data to RMS */
+	u32 num_chnls;		/* Total number of channels */
+	u32 chnl_offset;	/* Offset of chnl ids rsvd for RMS */
+	u32 chnl_buf_size;	/* Buffer size for data to RMS */
 	int proc_family;	/* eg, 5000 */
 	int proc_type;		/* eg, 5510 */
-	u32 udsp_word_size;	/* Size of DSP word on host bytes */
-	u32 udsp_data_mau_size;	/* Size of DSP data MAU */
-	u32 udsp_mau_size;	/* Size of MAU */
+	u32 dsp_word_size;	/* Size of DSP word on host bytes */
+	u32 dsp_data_mau_size;	/* Size of DSP data MAU */
+	u32 dsp_mau_size;	/* Size of MAU */
 	s32 min_pri;		/* Minimum runtime priority for node */
 	s32 max_pri;		/* Maximum runtime priority for node */
 
@@ -185,14 +188,14 @@ struct stream_chnl {
  */
 struct node_object {
 	struct list_head list_elem;
-	struct node_mgr *hnode_mgr;	/* The manager of this node */
-	struct proc_object *hprocessor;	/* Back pointer to processor */
+	struct node_mgr *node_mgr;	/* The manager of this node */
+	struct proc_object *processor;	/* Back pointer to processor */
 	struct dsp_uuid node_uuid;	/* Node's ID */
 	s32 prio;		/* Node's current priority */
-	u32 utimeout;		/* Timeout for blocking NODE calls */
+	u32 timeout;		/* Timeout for blocking NODE calls */
 	u32 heap_size;		/* Heap Size */
-	u32 udsp_heap_virt_addr;	/* Heap Size */
-	u32 ugpp_heap_virt_addr;	/* Heap Size */
+	u32 dsp_heap_virt_addr;	/* Heap Size */
+	u32 gpp_heap_virt_addr;	/* Heap Size */
 	enum node_type ntype;	/* Type of node: message, task, etc */
 	enum node_state node_state;	/* NODE_ALLOCATED, NODE_CREATED, ... */
 	u32 num_inputs;		/* Current number of inputs */
@@ -204,9 +207,9 @@ struct node_object {
 	struct node_createargs create_args;	/* Args for node create func */
 	nodeenv node_env;	/* Environment returned by RMS */
 	struct dcd_genericobj dcd_props;	/* Node properties from DCD */
-	struct dsp_cbdata *pargs;	/* Optional args to pass to node */
+	struct dsp_cbdata *args;	/* Optional args to pass to node */
 	struct ntfy_object *ntfy_obj;	/* Manages registered notifications */
-	char *pstr_dev_name;	/* device name, if device node */
+	char *str_dev_name;	/* device name, if device node */
 	struct sync_object *sync_done;	/* Synchronize node_terminate */
 	s32 exit_status;	/* execute function return status */
 
@@ -232,9 +235,9 @@ struct node_object {
 
 /* Default buffer attributes */
 static struct dsp_bufferattr node_dfltbufattrs = {
-	0,			/* cb_struct */
-	1,			/* segment_id */
-	0,			/* buf_alignment */
+	.cb_struct = 0,
+	.segment_id = 1,
+	.buf_alignment = 0,
 };
 
 static void delete_node(struct node_object *hnode,
@@ -280,8 +283,7 @@ enum node_state node_get_state(void *hnode)
 	struct node_object *pnode = (struct node_object *)hnode;
 	if (!pnode)
 		return -1;
-	else
-		return pnode->node_state;
+	return pnode->node_state;
 }
 
 /*
@@ -365,7 +367,7 @@ int node_allocate(struct proc_object *hprocessor,
 	}
 
 	/* Assuming that 0 is not a valid function address */
-	if (hnode_mgr->ul_fxn_addrs[0] == 0) {
+	if (hnode_mgr->fxn_addrs[0] == 0) {
 		/* No RMS on target - we currently can't handle this */
 		pr_err("%s: Failed, no RMS in base image\n", __func__);
 		status = -EPERM;
@@ -387,28 +389,28 @@ int node_allocate(struct proc_object *hprocessor,
 		status = -ENOMEM;
 		goto func_end;
 	}
-	pnode->hnode_mgr = hnode_mgr;
+	pnode->node_mgr = hnode_mgr;
 	/* This critical section protects get_node_props */
 	mutex_lock(&hnode_mgr->node_mgr_lock);
 
 	/* Get dsp_ndbprops from node database */
-	status = get_node_props(hnode_mgr->hdcd_mgr, pnode, node_uuid,
+	status = get_node_props(hnode_mgr->dcd_mgr, pnode, node_uuid,
 				&(pnode->dcd_props));
 	if (status)
 		goto func_cont;
 
 	pnode->node_uuid = *node_uuid;
-	pnode->hprocessor = hprocessor;
+	pnode->processor = hprocessor;
 	pnode->ntype = pnode->dcd_props.obj_data.node_obj.ndb_props.ntype;
-	pnode->utimeout = pnode->dcd_props.obj_data.node_obj.ndb_props.utimeout;
+	pnode->timeout = pnode->dcd_props.obj_data.node_obj.ndb_props.timeout;
 	pnode->prio = pnode->dcd_props.obj_data.node_obj.ndb_props.prio;
 
 	/* Currently only C64 DSP builds support Node Dynamic * heaps */
 	/* Allocate memory for node heap */
 	pnode->create_args.asa.task_arg_obj.heap_size = 0;
-	pnode->create_args.asa.task_arg_obj.udsp_heap_addr = 0;
-	pnode->create_args.asa.task_arg_obj.udsp_heap_res_addr = 0;
-	pnode->create_args.asa.task_arg_obj.ugpp_heap_addr = 0;
+	pnode->create_args.asa.task_arg_obj.dsp_heap_addr = 0;
+	pnode->create_args.asa.task_arg_obj.dsp_heap_res_addr = 0;
+	pnode->create_args.asa.task_arg_obj.gpp_heap_addr = 0;
 	if (!attr_in)
 		goto func_cont;
 
@@ -424,7 +426,7 @@ int node_allocate(struct proc_object *hprocessor,
 	} else {
 		pnode->create_args.asa.task_arg_obj.heap_size =
 		    attr_in->heap_size;
-		pnode->create_args.asa.task_arg_obj.ugpp_heap_addr =
+		pnode->create_args.asa.task_arg_obj.gpp_heap_addr =
 		    (u32) attr_in->pgpp_virt_addr;
 	}
 	if (status)
@@ -434,7 +436,7 @@ int node_allocate(struct proc_object *hprocessor,
 				     pnode->create_args.asa.task_arg_obj.
 				     heap_size + PAGE_SIZE,
 				     (void **)&(pnode->create_args.asa.
-					task_arg_obj.udsp_heap_res_addr),
+					task_arg_obj.dsp_heap_res_addr),
 				     pr_ctxt);
 	if (status) {
 		pr_err("%s: Failed to reserve memory for heap: 0x%x\n",
@@ -457,20 +459,20 @@ int node_allocate(struct proc_object *hprocessor,
 	status = proc_map(hprocessor, (void *)attr_in->pgpp_virt_addr,
 			  pnode->create_args.asa.task_arg_obj.heap_size,
 			  (void *)pnode->create_args.asa.task_arg_obj.
-			  udsp_heap_res_addr, (void **)&mapped_addr, map_attrs,
+			  dsp_heap_res_addr, (void **)&mapped_addr, map_attrs,
 			  pr_ctxt);
 	if (status)
 		pr_err("%s: Failed to map memory for Heap: 0x%x\n",
 		       __func__, status);
 	else
-		pnode->create_args.asa.task_arg_obj.udsp_heap_addr =
+		pnode->create_args.asa.task_arg_obj.dsp_heap_addr =
 		    (u32) mapped_addr;
 
 func_cont:
 	mutex_unlock(&hnode_mgr->node_mgr_lock);
 	if (attr_in != NULL) {
 		/* Overrides of NBD properties */
-		pnode->utimeout = attr_in->utimeout;
+		pnode->timeout = attr_in->timeout;
 		pnode->prio = attr_in->prio;
 	}
 	/* Create object to manage notifications */
@@ -562,7 +564,7 @@ func_cont:
 		/* Create a message queue for this node */
 		intf_fxns = hnode_mgr->intf_fxns;
 		status =
-		    (*intf_fxns->pfn_msg_create_queue) (hnode_mgr->msg_mgr_obj,
+		    (*intf_fxns->msg_create_queue) (hnode_mgr->msg_mgr_obj,
 							&pnode->msg_queue_obj,
 							0,
 							pnode->create_args.asa.
@@ -573,7 +575,7 @@ func_cont:
 	if (!status) {
 		/* Create object for dynamic loading */
 
-		status = hnode_mgr->nldr_fxns.pfn_allocate(hnode_mgr->nldr_obj,
+		status = hnode_mgr->nldr_fxns.allocate(hnode_mgr->nldr_obj,
 							   (void *)pnode,
 							   &pnode->dcd_props.
 							   obj_data.node_obj,
@@ -594,7 +596,7 @@ func_cont:
 			   stack_seg_name, STACKSEGLABEL) == 0) {
 			status =
 			    hnode_mgr->nldr_fxns.
-			    pfn_get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
+			    get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
 					     &dynext_base);
 			if (status)
 				pr_err("%s: Failed to get addr for DYNEXT_BEG"
@@ -602,7 +604,7 @@ func_cont:
 
 			status =
 			    hnode_mgr->nldr_fxns.
-			    pfn_get_fxn_addr(pnode->nldr_node_obj,
+			    get_fxn_addr(pnode->nldr_node_obj,
 					     "L1DSRAM_HEAP", &pul_value);
 
 			if (status)
@@ -619,7 +621,7 @@ func_cont:
 				goto func_end;
 			}
 
-			ul_gpp_mem_base = (u32) host_res->dw_mem_base[1];
+			ul_gpp_mem_base = (u32) host_res->mem_base[1];
 			off_set = pul_value - dynext_base;
 			ul_stack_seg_addr = ul_gpp_mem_base + off_set;
 			ul_stack_seg_val = readl(ul_stack_seg_addr);
@@ -637,13 +639,12 @@ func_cont:
 	if (!status) {
 		/* Add the node to the node manager's list of allocated
 		 * nodes. */
-		lst_init_elem((struct list_head *)pnode);
 		NODE_SET_STATE(pnode, NODE_ALLOCATED);
 
 		mutex_lock(&hnode_mgr->node_mgr_lock);
 
-		lst_put_tail(hnode_mgr->node_list, (struct list_head *) pnode);
-			++(hnode_mgr->num_nodes);
+		list_add_tail(&pnode->list_elem, &hnode_mgr->node_list);
+		++(hnode_mgr->num_nodes);
 
 		/* Exit critical section */
 		mutex_unlock(&hnode_mgr->node_mgr_lock);
@@ -711,7 +712,7 @@ DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
 	if (pattr == NULL)
 		pattr = &node_dfltbufattrs;	/* set defaults */
 
-	status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+	status = proc_get_processor_id(pnode->processor, &proc_id);
 	if (proc_id != DSP_UNIT) {
 		DBC_ASSERT(NULL);
 		goto func_end;
@@ -783,10 +784,10 @@ int node_change_priority(struct node_object *hnode, s32 prio)
 
 	DBC_REQUIRE(refs > 0);
 
-	if (!hnode || !hnode->hnode_mgr) {
+	if (!hnode || !hnode->node_mgr) {
 		status = -EFAULT;
 	} else {
-		hnode_mgr = hnode->hnode_mgr;
+		hnode_mgr = hnode->node_mgr;
 		node_type = node_get_type(hnode);
 		if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
 			status = -EPERM;
@@ -807,12 +808,12 @@ int node_change_priority(struct node_object *hnode, s32 prio)
 			status = -EBADR;
 			goto func_cont;
 		}
-		status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+		status = proc_get_processor_id(pnode->processor, &proc_id);
 		if (proc_id == DSP_UNIT) {
 			status =
 			    disp_node_change_priority(hnode_mgr->disp_obj,
 						      hnode,
-						      hnode_mgr->ul_fxn_addrs
+						      hnode_mgr->fxn_addrs
 						      [RMSCHANGENODEPRIORITY],
 						      hnode->node_env, prio);
 		}
@@ -841,229 +842,209 @@ int node_connect(struct node_object *node1, u32 stream1,
 	char *pstr_dev_name = NULL;
 	enum node_type node1_type = NODE_TASK;
 	enum node_type node2_type = NODE_TASK;
+	enum dsp_strmmode strm_mode;
 	struct node_strmdef *pstrm_def;
 	struct node_strmdef *input = NULL;
 	struct node_strmdef *output = NULL;
 	struct node_object *dev_node_obj;
 	struct node_object *hnode;
 	struct stream_chnl *pstream;
-	u32 pipe_id = GB_NOBITS;
-	u32 chnl_id = GB_NOBITS;
+	u32 pipe_id;
+	u32 chnl_id;
 	s8 chnl_mode;
 	u32 dw_length;
 	int status = 0;
 	DBC_REQUIRE(refs > 0);
 
-	if ((node1 != (struct node_object *)DSP_HGPPNODE && !node1) ||
-	    (node2 != (struct node_object *)DSP_HGPPNODE && !node2))
-		status = -EFAULT;
+	if (!node1 || !node2)
+		return -EFAULT;
 
-	if (!status) {
-		/* The two nodes must be on the same processor */
-		if (node1 != (struct node_object *)DSP_HGPPNODE &&
-		    node2 != (struct node_object *)DSP_HGPPNODE &&
-		    node1->hnode_mgr != node2->hnode_mgr)
-			status = -EPERM;
-		/* Cannot connect a node to itself */
-		if (node1 == node2)
-			status = -EPERM;
+	/* The two nodes must be on the same processor */
+	if (node1 != (struct node_object *)DSP_HGPPNODE &&
+			node2 != (struct node_object *)DSP_HGPPNODE &&
+			node1->node_mgr != node2->node_mgr)
+		return -EPERM;
+
+	/* Cannot connect a node to itself */
+	if (node1 == node2)
+		return -EPERM;
+
+	/* node_get_type() will return NODE_GPP if hnode =  DSP_HGPPNODE. */
+	node1_type = node_get_type(node1);
+	node2_type = node_get_type(node2);
+	/* Check stream indices ranges */
+	if ((node1_type != NODE_GPP && node1_type != NODE_DEVICE &&
+				stream1 >= MAX_OUTPUTS(node1)) ||
+			(node2_type != NODE_GPP && node2_type != NODE_DEVICE &&
+			 stream2 >= MAX_INPUTS(node2)))
+		return -EINVAL;
 
-	}
-	if (!status) {
-		/* node_get_type() will return NODE_GPP if hnode =
-		 * DSP_HGPPNODE. */
-		node1_type = node_get_type(node1);
-		node2_type = node_get_type(node2);
-		/* Check stream indices ranges */
-		if ((node1_type != NODE_GPP && node1_type != NODE_DEVICE &&
-		     stream1 >= MAX_OUTPUTS(node1)) || (node2_type != NODE_GPP
-							  && node2_type !=
-							  NODE_DEVICE
-							  && stream2 >=
-							  MAX_INPUTS(node2)))
-			status = -EINVAL;
-	}
-	if (!status) {
-		/*
-		 *  Only the following types of connections are allowed:
-		 *      task/dais socket < == > task/dais socket
-		 *      task/dais socket < == > device
-		 *      task/dais socket < == > GPP
-		 *
-		 *  ie, no message nodes, and at least one task or dais
-		 *  socket node.
-		 */
-		if (node1_type == NODE_MESSAGE || node2_type == NODE_MESSAGE ||
-		    (node1_type != NODE_TASK && node1_type != NODE_DAISSOCKET &&
-		     node2_type != NODE_TASK && node2_type != NODE_DAISSOCKET))
-			status = -EPERM;
-	}
+	/*
+	 *  Only the following types of connections are allowed:
+	 *      task/dais socket < == > task/dais socket
+	 *      task/dais socket < == > device
+	 *      task/dais socket < == > GPP
+	 *
+	 *  ie, no message nodes, and at least one task or dais
+	 *  socket node.
+	 */
+	if (node1_type == NODE_MESSAGE || node2_type == NODE_MESSAGE ||
+			(node1_type != NODE_TASK &&
+			 node1_type != NODE_DAISSOCKET &&
+			 node2_type != NODE_TASK &&
+			 node2_type != NODE_DAISSOCKET))
+		return -EPERM;
 	/*
 	 * Check stream mode. Default is STRMMODE_PROCCOPY.
 	 */
-	if (!status && pattrs) {
-		if (pattrs->strm_mode != STRMMODE_PROCCOPY)
-			status = -EPERM;	/* illegal stream mode */
-
-	}
-	if (status)
-		goto func_end;
+	if (pattrs && pattrs->strm_mode != STRMMODE_PROCCOPY)
+		return -EPERM;	/* illegal stream mode */
 
 	if (node1_type != NODE_GPP) {
-		hnode_mgr = node1->hnode_mgr;
+		hnode_mgr = node1->node_mgr;
 	} else {
 		DBC_ASSERT(node2 != (struct node_object *)DSP_HGPPNODE);
-		hnode_mgr = node2->hnode_mgr;
+		hnode_mgr = node2->node_mgr;
 	}
+
 	/* Enter critical section */
 	mutex_lock(&hnode_mgr->node_mgr_lock);
 
 	/* Nodes must be in the allocated state */
-	if (node1_type != NODE_GPP && node_get_state(node1) != NODE_ALLOCATED)
+	if (node1_type != NODE_GPP &&
+			node_get_state(node1) != NODE_ALLOCATED) {
 		status = -EBADR;
+		goto out_unlock;
+	}
 
-	if (node2_type != NODE_GPP && node_get_state(node2) != NODE_ALLOCATED)
+	if (node2_type != NODE_GPP &&
+			node_get_state(node2) != NODE_ALLOCATED) {
 		status = -EBADR;
+		goto out_unlock;
+	}
 
-	if (!status) {
-		/*  Check that stream indices for task and dais socket nodes
-		 *  are not already be used. (Device nodes checked later) */
-		if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
-			output =
-			    &(node1->create_args.asa.
-			      task_arg_obj.strm_out_def[stream1]);
-			if (output->sz_device != NULL)
-				status = -EISCONN;
-
+	/*
+	 *  Check that stream indices for task and dais socket nodes
+	 *  are not already be used. (Device nodes checked later)
+	 */
+	if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
+		output = &(node1->create_args.asa.
+				task_arg_obj.strm_out_def[stream1]);
+		if (output->sz_device) {
+			status = -EISCONN;
+			goto out_unlock;
 		}
-		if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
-			input =
-			    &(node2->create_args.asa.
-			      task_arg_obj.strm_in_def[stream2]);
-			if (input->sz_device != NULL)
-				status = -EISCONN;
 
+	}
+	if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
+		input = &(node2->create_args.asa.
+				task_arg_obj.strm_in_def[stream2]);
+		if (input->sz_device) {
+			status = -EISCONN;
+			goto out_unlock;
 		}
+
 	}
 	/* Connecting two task nodes? */
-	if (!status && ((node1_type == NODE_TASK ||
-				       node1_type == NODE_DAISSOCKET)
-				      && (node2_type == NODE_TASK
-					  || node2_type == NODE_DAISSOCKET))) {
+	if ((node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) &&
+				(node2_type == NODE_TASK ||
+				 node2_type == NODE_DAISSOCKET)) {
 		/* Find available pipe */
-		pipe_id = gb_findandset(hnode_mgr->pipe_map);
-		if (pipe_id == GB_NOBITS) {
+		pipe_id = find_first_zero_bit(hnode_mgr->pipe_map, MAXPIPES);
+		if (pipe_id == MAXPIPES) {
 			status = -ECONNREFUSED;
-		} else {
-			node1->outputs[stream1].type = NODECONNECT;
-			node2->inputs[stream2].type = NODECONNECT;
-			node1->outputs[stream1].dev_id = pipe_id;
-			node2->inputs[stream2].dev_id = pipe_id;
-			output->sz_device = kzalloc(PIPENAMELEN + 1,
-							GFP_KERNEL);
-			input->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
-			if (output->sz_device == NULL ||
-			    input->sz_device == NULL) {
-				/* Undo the connection */
-				kfree(output->sz_device);
-
-				kfree(input->sz_device);
-
-				output->sz_device = NULL;
-				input->sz_device = NULL;
-				gb_clear(hnode_mgr->pipe_map, pipe_id);
-				status = -ENOMEM;
-			} else {
-				/* Copy "/dbpipe<pipId>" name to device names */
-				sprintf(output->sz_device, "%s%d",
-					PIPEPREFIX, pipe_id);
-				strcpy(input->sz_device, output->sz_device);
-			}
+			goto out_unlock;
+		}
+		set_bit(pipe_id, hnode_mgr->pipe_map);
+		node1->outputs[stream1].type = NODECONNECT;
+		node2->inputs[stream2].type = NODECONNECT;
+		node1->outputs[stream1].dev_id = pipe_id;
+		node2->inputs[stream2].dev_id = pipe_id;
+		output->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
+		input->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
+		if (!output->sz_device || !input->sz_device) {
+			/* Undo the connection */
+			kfree(output->sz_device);
+			kfree(input->sz_device);
+			clear_bit(pipe_id, hnode_mgr->pipe_map);
+			status = -ENOMEM;
+			goto out_unlock;
 		}
+		/* Copy "/dbpipe<pipId>" name to device names */
+		sprintf(output->sz_device, "%s%d", PIPEPREFIX, pipe_id);
+		strcpy(input->sz_device, output->sz_device);
 	}
 	/* Connecting task node to host? */
-	if (!status && (node1_type == NODE_GPP ||
-				      node2_type == NODE_GPP)) {
-		if (node1_type == NODE_GPP) {
-			chnl_mode = CHNL_MODETODSP;
-		} else {
-			DBC_ASSERT(node2_type == NODE_GPP);
-			chnl_mode = CHNL_MODEFROMDSP;
+	if (node1_type == NODE_GPP || node2_type == NODE_GPP) {
+		pstr_dev_name = kzalloc(HOSTNAMELEN + 1, GFP_KERNEL);
+		if (!pstr_dev_name) {
+			status = -ENOMEM;
+			goto out_unlock;
 		}
-		/*  Reserve a channel id. We need to put the name "/host<id>"
+
+		DBC_ASSERT((node1_type == NODE_GPP) ||
+				(node2_type == NODE_GPP));
+
+		chnl_mode = (node1_type == NODE_GPP) ?
+			CHNL_MODETODSP : CHNL_MODEFROMDSP;
+
+		/*
+		 *  Reserve a channel id. We need to put the name "/host<id>"
 		 *  in the node's create_args, but the host
 		 *  side channel will not be opened until DSPStream_Open is
-		 *  called for this node. */
-		if (pattrs) {
-			if (pattrs->strm_mode == STRMMODE_RDMA) {
-				chnl_id =
-				    gb_findandset(hnode_mgr->dma_chnl_map);
+		 *  called for this node.
+		 */
+		strm_mode = pattrs ? pattrs->strm_mode : STRMMODE_PROCCOPY;
+		switch (strm_mode) {
+		case STRMMODE_RDMA:
+			chnl_id = find_first_zero_bit(hnode_mgr->dma_chnl_map,
+					CHNL_MAXCHANNELS);
+			if (chnl_id < CHNL_MAXCHANNELS) {
+				set_bit(chnl_id, hnode_mgr->dma_chnl_map);
 				/* dma chans are 2nd transport chnl set
 				 * ids(e.g. 16-31) */
-				(chnl_id != GB_NOBITS) ?
-				    (chnl_id =
-				     chnl_id +
-				     hnode_mgr->ul_num_chnls) : chnl_id;
-			} else if (pattrs->strm_mode == STRMMODE_ZEROCOPY) {
-				chnl_id = gb_findandset(hnode_mgr->zc_chnl_map);
+				chnl_id = chnl_id + hnode_mgr->num_chnls;
+			}
+			break;
+		case STRMMODE_ZEROCOPY:
+			chnl_id = find_first_zero_bit(hnode_mgr->zc_chnl_map,
+					CHNL_MAXCHANNELS);
+			if (chnl_id < CHNL_MAXCHANNELS) {
+				set_bit(chnl_id, hnode_mgr->zc_chnl_map);
 				/* zero-copy chans are 3nd transport set
 				 * (e.g. 32-47) */
-				(chnl_id != GB_NOBITS) ? (chnl_id = chnl_id +
-							  (2 *
-							   hnode_mgr->
-							   ul_num_chnls))
-				    : chnl_id;
-			} else {	/* must be PROCCOPY */
-				DBC_ASSERT(pattrs->strm_mode ==
-					   STRMMODE_PROCCOPY);
-				chnl_id = gb_findandset(hnode_mgr->chnl_map);
-				/* e.g. 0-15 */
+				chnl_id = chnl_id +
+					(2 * hnode_mgr->num_chnls);
 			}
-		} else {
-			/* default to PROCCOPY */
-			chnl_id = gb_findandset(hnode_mgr->chnl_map);
+			break;
+		case STRMMODE_PROCCOPY:
+			chnl_id = find_first_zero_bit(hnode_mgr->chnl_map,
+					CHNL_MAXCHANNELS);
+			if (chnl_id < CHNL_MAXCHANNELS)
+				set_bit(chnl_id, hnode_mgr->chnl_map);
+			break;
+		default:
+			status = -EINVAL;
+			goto out_unlock;
 		}
-		if (chnl_id == GB_NOBITS) {
+		if (chnl_id == CHNL_MAXCHANNELS) {
 			status = -ECONNREFUSED;
-			goto func_cont2;
+			goto out_unlock;
 		}
-		pstr_dev_name = kzalloc(HOSTNAMELEN + 1, GFP_KERNEL);
-		if (pstr_dev_name != NULL)
-			goto func_cont2;
-
-		if (pattrs) {
-			if (pattrs->strm_mode == STRMMODE_RDMA) {
-				gb_clear(hnode_mgr->dma_chnl_map, chnl_id -
-					 hnode_mgr->ul_num_chnls);
-			} else if (pattrs->strm_mode == STRMMODE_ZEROCOPY) {
-				gb_clear(hnode_mgr->zc_chnl_map, chnl_id -
-					 (2 * hnode_mgr->ul_num_chnls));
-			} else {
-				DBC_ASSERT(pattrs->strm_mode ==
-					   STRMMODE_PROCCOPY);
-				gb_clear(hnode_mgr->chnl_map, chnl_id);
-			}
+
+		if (node1 == (struct node_object *)DSP_HGPPNODE) {
+			node2->inputs[stream2].type = HOSTCONNECT;
+			node2->inputs[stream2].dev_id = chnl_id;
+			input->sz_device = pstr_dev_name;
 		} else {
-			gb_clear(hnode_mgr->chnl_map, chnl_id);
-		}
-		status = -ENOMEM;
-func_cont2:
-		if (!status) {
-			if (node1 == (struct node_object *)DSP_HGPPNODE) {
-				node2->inputs[stream2].type = HOSTCONNECT;
-				node2->inputs[stream2].dev_id = chnl_id;
-				input->sz_device = pstr_dev_name;
-			} else {
-				node1->outputs[stream1].type = HOSTCONNECT;
-				node1->outputs[stream1].dev_id = chnl_id;
-				output->sz_device = pstr_dev_name;
-			}
-			sprintf(pstr_dev_name, "%s%d", HOSTPREFIX, chnl_id);
+			node1->outputs[stream1].type = HOSTCONNECT;
+			node1->outputs[stream1].dev_id = chnl_id;
+			output->sz_device = pstr_dev_name;
 		}
+		sprintf(pstr_dev_name, "%s%d", HOSTPREFIX, chnl_id);
 	}
 	/* Connecting task node to device node? */
-	if (!status && ((node1_type == NODE_DEVICE) ||
-				      (node2_type == NODE_DEVICE))) {
+	if ((node1_type == NODE_DEVICE) || (node2_type == NODE_DEVICE)) {
 		if (node2_type == NODE_DEVICE) {
 			/* node1 == > device */
 			dev_node_obj = node2;
@@ -1079,61 +1060,59 @@ func_cont2:
 		}
 		/* Set up create args */
 		pstream->type = DEVICECONNECT;
-		dw_length = strlen(dev_node_obj->pstr_dev_name);
-		if (conn_param != NULL) {
+		dw_length = strlen(dev_node_obj->str_dev_name);
+		if (conn_param)
 			pstrm_def->sz_device = kzalloc(dw_length + 1 +
-							conn_param->cb_data,
-							GFP_KERNEL);
-		} else {
+					conn_param->cb_data,
+					GFP_KERNEL);
+		else
 			pstrm_def->sz_device = kzalloc(dw_length + 1,
-							GFP_KERNEL);
-		}
-		if (pstrm_def->sz_device == NULL) {
+					GFP_KERNEL);
+		if (!pstrm_def->sz_device) {
 			status = -ENOMEM;
-		} else {
-			/* Copy device name */
-			strncpy(pstrm_def->sz_device,
-				dev_node_obj->pstr_dev_name, dw_length);
-			if (conn_param != NULL) {
-				strncat(pstrm_def->sz_device,
+			goto out_unlock;
+		}
+		/* Copy device name */
+		strncpy(pstrm_def->sz_device,
+				dev_node_obj->str_dev_name, dw_length);
+		if (conn_param)
+			strncat(pstrm_def->sz_device,
 					(char *)conn_param->node_data,
 					(u32) conn_param->cb_data);
-			}
-			dev_node_obj->device_owner = hnode;
-		}
+		dev_node_obj->device_owner = hnode;
 	}
-	if (!status) {
-		/* Fill in create args */
-		if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
-			node1->create_args.asa.task_arg_obj.num_outputs++;
-			fill_stream_def(node1, output, pattrs);
-		}
-		if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
-			node2->create_args.asa.task_arg_obj.num_inputs++;
-			fill_stream_def(node2, input, pattrs);
-		}
-		/* Update node1 and node2 stream_connect */
-		if (node1_type != NODE_GPP && node1_type != NODE_DEVICE) {
-			node1->num_outputs++;
-			if (stream1 > node1->max_output_index)
-				node1->max_output_index = stream1;
+	/* Fill in create args */
+	if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
+		node1->create_args.asa.task_arg_obj.num_outputs++;
+		fill_stream_def(node1, output, pattrs);
+	}
+	if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
+		node2->create_args.asa.task_arg_obj.num_inputs++;
+		fill_stream_def(node2, input, pattrs);
+	}
+	/* Update node1 and node2 stream_connect */
+	if (node1_type != NODE_GPP && node1_type != NODE_DEVICE) {
+		node1->num_outputs++;
+		if (stream1 > node1->max_output_index)
+			node1->max_output_index = stream1;
 
-		}
-		if (node2_type != NODE_GPP && node2_type != NODE_DEVICE) {
-			node2->num_inputs++;
-			if (stream2 > node2->max_input_index)
-				node2->max_input_index = stream2;
+	}
+	if (node2_type != NODE_GPP && node2_type != NODE_DEVICE) {
+		node2->num_inputs++;
+		if (stream2 > node2->max_input_index)
+			node2->max_input_index = stream2;
 
-		}
-		fill_stream_connect(node1, node2, stream1, stream2);
 	}
+	fill_stream_connect(node1, node2, stream1, stream2);
 	/* end of sync_enter_cs */
 	/* Exit critical section */
+out_unlock:
+	if (status && pstr_dev_name)
+		kfree(pstr_dev_name);
 	mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
 	dev_dbg(bridge, "%s: node1: %p stream1: %d node2: %p stream2: %d"
-		"pattrs: %p status: 0x%x\n", __func__, node1,
-		stream1, node2, stream2, pattrs, status);
+			"pattrs: %p status: 0x%x\n", __func__, node1,
+			stream1, node2, stream2, pattrs, status);
 	return status;
 }
 
@@ -1165,7 +1144,7 @@ int node_create(struct node_object *hnode)
 		status = -EFAULT;
 		goto func_end;
 	}
-	hprocessor = hnode->hprocessor;
+	hprocessor = hnode->processor;
 	status = proc_get_state(hprocessor, &proc_state,
 				sizeof(struct dsp_processorstate));
 	if (status)
@@ -1179,7 +1158,7 @@ int node_create(struct node_object *hnode)
 	/* create struct dsp_cbdata struct for PWR calls */
 	cb_data.cb_data = PWR_TIMEOUT;
 	node_type = node_get_type(hnode);
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 	intf_fxns = hnode_mgr->intf_fxns;
 	/* Get access to node dispatcher */
 	mutex_lock(&hnode_mgr->node_mgr_lock);
@@ -1189,7 +1168,7 @@ int node_create(struct node_object *hnode)
 		status = -EBADR;
 
 	if (!status)
-		status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+		status = proc_get_processor_id(pnode->processor, &proc_id);
 
 	if (status)
 		goto func_cont2;
@@ -1211,7 +1190,7 @@ int node_create(struct node_object *hnode)
 		if (pdata->cpu_set_freq)
 			(*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP3]);
 #endif
-		status = hnode_mgr->nldr_fxns.pfn_load(hnode->nldr_node_obj,
+		status = hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
 						       NLDR_CREATE);
 		/* Get address of node's create function */
 		if (!status) {
@@ -1232,19 +1211,19 @@ int node_create(struct node_object *hnode)
 		/* Get address of iAlg functions, if socket node */
 		if (!status) {
 			if (node_type == NODE_DAISSOCKET) {
-				status = hnode_mgr->nldr_fxns.pfn_get_fxn_addr
+				status = hnode_mgr->nldr_fxns.get_fxn_addr
 				    (hnode->nldr_node_obj,
 				     hnode->dcd_props.obj_data.node_obj.
-				     pstr_i_alg_name,
+				     str_i_alg_name,
 				     &hnode->create_args.asa.
-				     task_arg_obj.ul_dais_arg);
+				     task_arg_obj.dais_arg);
 			}
 		}
 	}
 	if (!status) {
 		if (node_type != NODE_DEVICE) {
 			status = disp_node_create(hnode_mgr->disp_obj, hnode,
-						  hnode_mgr->ul_fxn_addrs
+						  hnode_mgr->fxn_addrs
 						  [RMSCREATENODE],
 						  ul_create_fxn,
 						  &(hnode->create_args),
@@ -1253,7 +1232,7 @@ int node_create(struct node_object *hnode)
 				/* Set the message queue id to the node env
 				 * pointer */
 				intf_fxns = hnode_mgr->intf_fxns;
-				(*intf_fxns->pfn_msg_set_queue_id) (hnode->
+				(*intf_fxns->msg_set_queue_id) (hnode->
 							msg_queue_obj,
 							hnode->node_env);
 			}
@@ -1264,7 +1243,7 @@ int node_create(struct node_object *hnode)
 	if (hnode->loaded && hnode->phase_split) {
 		/* If create code was dynamically loaded, we can now unload
 		 * it. */
-		status1 = hnode_mgr->nldr_fxns.pfn_unload(hnode->nldr_node_obj,
+		status1 = hnode_mgr->nldr_fxns.unload(hnode->nldr_node_obj,
 							  NLDR_CREATE);
 		hnode->loaded = false;
 	}
@@ -1287,7 +1266,7 @@ func_cont:
 	mutex_unlock(&hnode_mgr->node_mgr_lock);
 func_end:
 	if (status >= 0) {
-		proc_notify_clients(hnode->hprocessor, DSP_NODESTATECHANGE);
+		proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
 		ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
 	}
 
@@ -1311,6 +1290,7 @@ int node_create_mgr(struct node_mgr **node_man,
 	struct nldr_attrs nldr_attrs_obj;
 	int status = 0;
 	u8 dev_type;
+
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(node_man != NULL);
 	DBC_REQUIRE(hdev_obj != NULL);
@@ -1318,113 +1298,89 @@ int node_create_mgr(struct node_mgr **node_man,
 	*node_man = NULL;
 	/* Allocate Node manager object */
 	node_mgr_obj = kzalloc(sizeof(struct node_mgr), GFP_KERNEL);
-	if (node_mgr_obj) {
-		node_mgr_obj->hdev_obj = hdev_obj;
-		node_mgr_obj->node_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		node_mgr_obj->pipe_map = gb_create(MAXPIPES);
-		node_mgr_obj->pipe_done_map = gb_create(MAXPIPES);
-		if (node_mgr_obj->node_list == NULL
-		    || node_mgr_obj->pipe_map == NULL
-		    || node_mgr_obj->pipe_done_map == NULL) {
-			status = -ENOMEM;
-		} else {
-			INIT_LIST_HEAD(&node_mgr_obj->node_list->head);
-			node_mgr_obj->ntfy_obj = kmalloc(
-				sizeof(struct ntfy_object), GFP_KERNEL);
-			if (node_mgr_obj->ntfy_obj)
-				ntfy_init(node_mgr_obj->ntfy_obj);
-			else
-				status = -ENOMEM;
-		}
-		node_mgr_obj->num_created = 0;
-	} else {
+	if (!node_mgr_obj)
+		return -ENOMEM;
+
+	node_mgr_obj->dev_obj = hdev_obj;
+
+	node_mgr_obj->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
+			GFP_KERNEL);
+	if (!node_mgr_obj->ntfy_obj) {
 		status = -ENOMEM;
+		goto out_err;
 	}
-	/* get devNodeType */
-	if (!status)
-		status = dev_get_dev_type(hdev_obj, &dev_type);
+	ntfy_init(node_mgr_obj->ntfy_obj);
 
-	/* Create the DCD Manager */
-	if (!status) {
-		status =
-		    dcd_create_manager(sz_zl_file, &node_mgr_obj->hdcd_mgr);
-		if (!status)
-			status = get_proc_props(node_mgr_obj, hdev_obj);
+	INIT_LIST_HEAD(&node_mgr_obj->node_list);
+
+	dev_get_dev_type(hdev_obj, &dev_type);
+
+	status = dcd_create_manager(sz_zl_file, &node_mgr_obj->dcd_mgr);
+	if (status)
+		goto out_err;
+
+	status = get_proc_props(node_mgr_obj, hdev_obj);
+	if (status)
+		goto out_err;
 
-	}
 	/* Create NODE Dispatcher */
-	if (!status) {
-		disp_attr_obj.ul_chnl_offset = node_mgr_obj->ul_chnl_offset;
-		disp_attr_obj.ul_chnl_buf_size = node_mgr_obj->ul_chnl_buf_size;
-		disp_attr_obj.proc_family = node_mgr_obj->proc_family;
-		disp_attr_obj.proc_type = node_mgr_obj->proc_type;
-		status =
-		    disp_create(&node_mgr_obj->disp_obj, hdev_obj,
-				&disp_attr_obj);
-	}
+	disp_attr_obj.chnl_offset = node_mgr_obj->chnl_offset;
+	disp_attr_obj.chnl_buf_size = node_mgr_obj->chnl_buf_size;
+	disp_attr_obj.proc_family = node_mgr_obj->proc_family;
+	disp_attr_obj.proc_type = node_mgr_obj->proc_type;
+
+	status = disp_create(&node_mgr_obj->disp_obj, hdev_obj, &disp_attr_obj);
+	if (status)
+		goto out_err;
+
 	/* Create a STRM Manager */
-	if (!status)
-		status = strm_create(&node_mgr_obj->strm_mgr_obj, hdev_obj);
+	status = strm_create(&node_mgr_obj->strm_mgr_obj, hdev_obj);
+	if (status)
+		goto out_err;
 
-	if (!status) {
-		dev_get_intf_fxns(hdev_obj, &node_mgr_obj->intf_fxns);
-		/* Get msg_ctrl queue manager */
-		dev_get_msg_mgr(hdev_obj, &node_mgr_obj->msg_mgr_obj);
-		mutex_init(&node_mgr_obj->node_mgr_lock);
-		node_mgr_obj->chnl_map = gb_create(node_mgr_obj->ul_num_chnls);
-		/* dma chnl map. ul_num_chnls is # per transport */
-		node_mgr_obj->dma_chnl_map =
-		    gb_create(node_mgr_obj->ul_num_chnls);
-		node_mgr_obj->zc_chnl_map =
-		    gb_create(node_mgr_obj->ul_num_chnls);
-		if ((node_mgr_obj->chnl_map == NULL)
-		    || (node_mgr_obj->dma_chnl_map == NULL)
-		    || (node_mgr_obj->zc_chnl_map == NULL)) {
-			status = -ENOMEM;
-		} else {
-			/* Block out reserved channels */
-			for (i = 0; i < node_mgr_obj->ul_chnl_offset; i++)
-				gb_set(node_mgr_obj->chnl_map, i);
-
-			/* Block out channels reserved for RMS */
-			gb_set(node_mgr_obj->chnl_map,
-			       node_mgr_obj->ul_chnl_offset);
-			gb_set(node_mgr_obj->chnl_map,
-			       node_mgr_obj->ul_chnl_offset + 1);
-		}
-	}
-	if (!status) {
-		/* NO RM Server on the IVA */
-		if (dev_type != IVA_UNIT) {
-			/* Get addresses of any RMS functions loaded */
-			status = get_rms_fxns(node_mgr_obj);
-		}
+	dev_get_intf_fxns(hdev_obj, &node_mgr_obj->intf_fxns);
+	/* Get msg_ctrl queue manager */
+	dev_get_msg_mgr(hdev_obj, &node_mgr_obj->msg_mgr_obj);
+	mutex_init(&node_mgr_obj->node_mgr_lock);
+
+	/* Block out reserved channels */
+	for (i = 0; i < node_mgr_obj->chnl_offset; i++)
+		set_bit(i, node_mgr_obj->chnl_map);
+
+	/* Block out channels reserved for RMS */
+	set_bit(node_mgr_obj->chnl_offset, node_mgr_obj->chnl_map);
+	set_bit(node_mgr_obj->chnl_offset + 1, node_mgr_obj->chnl_map);
+
+	/* NO RM Server on the IVA */
+	if (dev_type != IVA_UNIT) {
+		/* Get addresses of any RMS functions loaded */
+		status = get_rms_fxns(node_mgr_obj);
+		if (status)
+			goto out_err;
 	}
 
 	/* Get loader functions and create loader */
-	if (!status)
-		node_mgr_obj->nldr_fxns = nldr_fxns;	/* Dyn loader funcs */
+	node_mgr_obj->nldr_fxns = nldr_fxns;	/* Dyn loader funcs */
+
+	nldr_attrs_obj.ovly = ovly;
+	nldr_attrs_obj.write = mem_write;
+	nldr_attrs_obj.dsp_word_size = node_mgr_obj->dsp_word_size;
+	nldr_attrs_obj.dsp_mau_size = node_mgr_obj->dsp_mau_size;
+	node_mgr_obj->loader_init = node_mgr_obj->nldr_fxns.init();
+	status = node_mgr_obj->nldr_fxns.create(&node_mgr_obj->nldr_obj,
+			hdev_obj,
+			&nldr_attrs_obj);
+	if (status)
+		goto out_err;
 
-	if (!status) {
-		nldr_attrs_obj.pfn_ovly = ovly;
-		nldr_attrs_obj.pfn_write = mem_write;
-		nldr_attrs_obj.us_dsp_word_size = node_mgr_obj->udsp_word_size;
-		nldr_attrs_obj.us_dsp_mau_size = node_mgr_obj->udsp_mau_size;
-		node_mgr_obj->loader_init = node_mgr_obj->nldr_fxns.pfn_init();
-		status =
-		    node_mgr_obj->nldr_fxns.pfn_create(&node_mgr_obj->nldr_obj,
-						       hdev_obj,
-						       &nldr_attrs_obj);
-	}
-	if (!status)
-		*node_man = node_mgr_obj;
-	else
-		delete_node_mgr(node_mgr_obj);
+	*node_man = node_mgr_obj;
 
 	DBC_ENSURE((status && *node_man == NULL) || (!status && *node_man));
 
 	return status;
+out_err:
+	delete_node_mgr(node_mgr_obj);
+	return status;
 }
 
 /*
@@ -1437,7 +1393,7 @@ int node_create_mgr(struct node_mgr **node_man,
 int node_delete(struct node_res_object *noderes,
 		       struct process_context *pr_ctxt)
 {
-	struct node_object *pnode = noderes->hnode;
+	struct node_object *pnode = noderes->node;
 	struct node_mgr *hnode_mgr;
 	struct proc_object *hprocessor;
 	struct disp_object *disp_obj;
@@ -1461,8 +1417,8 @@ int node_delete(struct node_res_object *noderes,
 	}
 	/* create struct dsp_cbdata struct for PWR call */
 	cb_data.cb_data = PWR_TIMEOUT;
-	hnode_mgr = pnode->hnode_mgr;
-	hprocessor = pnode->hprocessor;
+	hnode_mgr = pnode->node_mgr;
+	hprocessor = pnode->processor;
 	disp_obj = hnode_mgr->disp_obj;
 	node_type = node_get_type(pnode);
 	intf_fxns = hnode_mgr->intf_fxns;
@@ -1477,7 +1433,7 @@ int node_delete(struct node_res_object *noderes,
 	 *  code must be  executed. */
 	if (!(state == NODE_ALLOCATED && pnode->node_env == (u32) NULL) &&
 	    node_type != NODE_DEVICE) {
-		status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+		status = proc_get_processor_id(pnode->processor, &proc_id);
 		if (status)
 			goto func_cont1;
 
@@ -1494,7 +1450,7 @@ int node_delete(struct node_res_object *noderes,
 				 * is not * running */
 				status1 =
 				    hnode_mgr->nldr_fxns.
-				    pfn_unload(pnode->nldr_node_obj,
+				    unload(pnode->nldr_node_obj,
 					       NLDR_EXECUTE);
 				pnode->loaded = false;
 				NODE_SET_STATE(pnode, NODE_DONE);
@@ -1505,7 +1461,7 @@ int node_delete(struct node_res_object *noderes,
 			    pnode->phase_split) {
 				status =
 				    hnode_mgr->nldr_fxns.
-				    pfn_load(pnode->nldr_node_obj, NLDR_DELETE);
+				    load(pnode->nldr_node_obj, NLDR_DELETE);
 				if (!status)
 					pnode->loaded = true;
 				else
@@ -1533,7 +1489,7 @@ func_cont1:
 					status =
 					    disp_node_delete(disp_obj, pnode,
 							     hnode_mgr->
-							     ul_fxn_addrs
+							     fxn_addrs
 							     [RMSDELETENODE],
 							     ul_delete_fxn,
 							     pnode->node_env);
@@ -1546,7 +1502,7 @@ func_cont1:
 				    pnode->phase_split) {
 					status1 =
 					    hnode_mgr->nldr_fxns.
-					    pfn_unload(pnode->nldr_node_obj,
+					    unload(pnode->nldr_node_obj,
 						       NLDR_EXECUTE);
 				}
 				if (status1)
@@ -1554,7 +1510,7 @@ func_cont1:
 					       " 0x%x\n", __func__, status1);
 
 				status1 =
-				    hnode_mgr->nldr_fxns.pfn_unload(pnode->
+				    hnode_mgr->nldr_fxns.unload(pnode->
 							    nldr_node_obj,
 							    NLDR_DELETE);
 				pnode->loaded = false;
@@ -1566,7 +1522,7 @@ func_cont1:
 	}
 	/* Free host side resources even if a failure occurred */
 	/* Remove node from hnode_mgr->node_list */
-	lst_remove_elem(hnode_mgr->node_list, (struct list_head *)pnode);
+	list_del(&pnode->list_elem);
 	hnode_mgr->num_nodes--;
 	/* Decrement count of nodes created on DSP */
 	if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
@@ -1598,16 +1554,14 @@ func_end:
  */
 int node_delete_mgr(struct node_mgr *hnode_mgr)
 {
-	int status = 0;
-
 	DBC_REQUIRE(refs > 0);
 
-	if (hnode_mgr)
-		delete_node_mgr(hnode_mgr);
-	else
-		status = -EFAULT;
+	if (!hnode_mgr)
+		return -EFAULT;
 
-	return status;
+	delete_node_mgr(hnode_mgr);
+
+	return 0;
 }
 
 /*
@@ -1620,7 +1574,7 @@ int node_enum_nodes(struct node_mgr *hnode_mgr, void **node_tab,
 			   u32 *pu_allocated)
 {
 	struct node_object *hnode;
-	u32 i;
+	u32 i = 0;
 	int status = 0;
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(node_tab != NULL || node_tab_size == 0);
@@ -1639,15 +1593,8 @@ int node_enum_nodes(struct node_mgr *hnode_mgr, void **node_tab,
 		*pu_num_nodes = 0;
 		status = -EINVAL;
 	} else {
-		hnode = (struct node_object *)lst_first(hnode_mgr->
-			node_list);
-		for (i = 0; i < hnode_mgr->num_nodes; i++) {
-			DBC_ASSERT(hnode);
-			node_tab[i] = hnode;
-			hnode = (struct node_object *)lst_next
-				(hnode_mgr->node_list,
-				(struct list_head *)hnode);
-		}
+		list_for_each_entry(hnode, &hnode_mgr->node_list, list_elem)
+			node_tab[i++] = hnode;
 		*pu_allocated = *pu_num_nodes = hnode_mgr->num_nodes;
 	}
 	/* end of sync_enter_cs */
@@ -1691,7 +1638,7 @@ int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer,
 		status = -EFAULT;
 		goto func_end;
 	}
-	status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+	status = proc_get_processor_id(pnode->processor, &proc_id);
 	if (proc_id == DSP_UNIT) {
 		if (!status) {
 			if (pattr == NULL) {
@@ -1722,38 +1669,37 @@ int node_get_attr(struct node_object *hnode,
 			 struct dsp_nodeattr *pattr, u32 attr_size)
 {
 	struct node_mgr *hnode_mgr;
-	int status = 0;
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(pattr != NULL);
 	DBC_REQUIRE(attr_size >= sizeof(struct dsp_nodeattr));
 
-	if (!hnode) {
-		status = -EFAULT;
-	} else {
-		hnode_mgr = hnode->hnode_mgr;
-		/* Enter hnode_mgr critical section (since we're accessing
-		 * data that could be changed by node_change_priority() and
-		 * node_connect(). */
-		mutex_lock(&hnode_mgr->node_mgr_lock);
-		pattr->cb_struct = sizeof(struct dsp_nodeattr);
-		/* dsp_nodeattrin */
-		pattr->in_node_attr_in.cb_struct =
-				 sizeof(struct dsp_nodeattrin);
-		pattr->in_node_attr_in.prio = hnode->prio;
-		pattr->in_node_attr_in.utimeout = hnode->utimeout;
-		pattr->in_node_attr_in.heap_size =
-			hnode->create_args.asa.task_arg_obj.heap_size;
-		pattr->in_node_attr_in.pgpp_virt_addr = (void *)
-			hnode->create_args.asa.task_arg_obj.ugpp_heap_addr;
-		pattr->node_attr_inputs = hnode->num_gpp_inputs;
-		pattr->node_attr_outputs = hnode->num_gpp_outputs;
-		/* dsp_nodeinfo */
-		get_node_info(hnode, &(pattr->node_info));
-		/* end of sync_enter_cs */
-		/* Exit critical section */
-		mutex_unlock(&hnode_mgr->node_mgr_lock);
-	}
-	return status;
+	if (!hnode)
+		return -EFAULT;
+
+	hnode_mgr = hnode->node_mgr;
+	/* Enter hnode_mgr critical section (since we're accessing
+	 * data that could be changed by node_change_priority() and
+	 * node_connect(). */
+	mutex_lock(&hnode_mgr->node_mgr_lock);
+	pattr->cb_struct = sizeof(struct dsp_nodeattr);
+	/* dsp_nodeattrin */
+	pattr->in_node_attr_in.cb_struct =
+		sizeof(struct dsp_nodeattrin);
+	pattr->in_node_attr_in.prio = hnode->prio;
+	pattr->in_node_attr_in.timeout = hnode->timeout;
+	pattr->in_node_attr_in.heap_size =
+		hnode->create_args.asa.task_arg_obj.heap_size;
+	pattr->in_node_attr_in.pgpp_virt_addr = (void *)
+		hnode->create_args.asa.task_arg_obj.gpp_heap_addr;
+	pattr->node_attr_inputs = hnode->num_gpp_inputs;
+	pattr->node_attr_outputs = hnode->num_gpp_outputs;
+	/* dsp_nodeinfo */
+	get_node_info(hnode, &(pattr->node_info));
+	/* end of sync_enter_cs */
+	/* Exit critical section */
+	mutex_unlock(&hnode_mgr->node_mgr_lock);
+
+	return 0;
 }
 
 /*
@@ -1822,7 +1768,7 @@ int node_get_message(struct node_object *hnode,
 		status = -EFAULT;
 		goto func_end;
 	}
-	hprocessor = hnode->hprocessor;
+	hprocessor = hnode->processor;
 	status = proc_get_state(hprocessor, &proc_state,
 				sizeof(struct dsp_processorstate));
 	if (status)
@@ -1833,7 +1779,7 @@ int node_get_message(struct node_object *hnode,
 		status = -EPERM;
 		goto func_end;
 	}
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 	node_type = node_get_type(hnode);
 	if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
 	    node_type != NODE_DAISSOCKET) {
@@ -1847,24 +1793,24 @@ int node_get_message(struct node_object *hnode,
 	 *  available. */
 	intf_fxns = hnode_mgr->intf_fxns;
 	status =
-	    (*intf_fxns->pfn_msg_get) (hnode->msg_queue_obj, message, utimeout);
+	    (*intf_fxns->msg_get) (hnode->msg_queue_obj, message, utimeout);
 	/* Check if message contains SM descriptor */
-	if (status || !(message->dw_cmd & DSP_RMSBUFDESC))
+	if (status || !(message->cmd & DSP_RMSBUFDESC))
 		goto func_end;
 
 	/* Translate DSP byte addr to GPP Va. */
 	tmp_buf = cmm_xlator_translate(hnode->xlator,
-				       (void *)(message->dw_arg1 *
-						hnode->hnode_mgr->
-						udsp_word_size), CMM_DSPPA2PA);
+				       (void *)(message->arg1 *
+						hnode->node_mgr->
+						dsp_word_size), CMM_DSPPA2PA);
 	if (tmp_buf != NULL) {
 		/* now convert this GPP Pa to Va */
 		tmp_buf = cmm_xlator_translate(hnode->xlator, tmp_buf,
 					       CMM_PA2VA);
 		if (tmp_buf != NULL) {
 			/* Adjust SM size in msg */
-			message->dw_arg1 = (u32) tmp_buf;
-			message->dw_arg2 *= hnode->hnode_mgr->udsp_word_size;
+			message->arg1 = (u32) tmp_buf;
+			message->arg2 *= hnode->node_mgr->dsp_word_size;
 		} else {
 			status = -ESRCH;
 		}
@@ -1911,7 +1857,7 @@ int node_get_strm_mgr(struct node_object *hnode,
 	if (!hnode)
 		status = -EFAULT;
 	else
-		*strm_man = hnode->hnode_mgr->strm_mgr_obj;
+		*strm_man = hnode->node_mgr->strm_mgr_obj;
 
 	return status;
 }
@@ -1927,7 +1873,7 @@ enum nldr_loadtype node_get_load_type(struct node_object *hnode)
 		dev_dbg(bridge, "%s: Failed. hnode: %p\n", __func__, hnode);
 		return -1;
 	} else {
-		return hnode->dcd_props.obj_data.node_obj.us_load_type;
+		return hnode->dcd_props.obj_data.node_obj.load_type;
 	}
 }
 
@@ -1944,7 +1890,7 @@ u32 node_get_timeout(struct node_object *hnode)
 		dev_dbg(bridge, "%s: failed. hnode: %p\n", __func__, hnode);
 		return 0;
 	} else {
-		return hnode->utimeout;
+		return hnode->timeout;
 	}
 }
 
@@ -1996,7 +1942,7 @@ void node_on_exit(struct node_object *hnode, s32 node_status)
 	NODE_SET_STATE(hnode, NODE_DONE);
 	hnode->exit_status = node_status;
 	if (hnode->loaded && hnode->phase_split) {
-		(void)hnode->hnode_mgr->nldr_fxns.pfn_unload(hnode->
+		(void)hnode->node_mgr->nldr_fxns.unload(hnode->
 							     nldr_node_obj,
 							     NLDR_EXECUTE);
 		hnode->loaded = false;
@@ -2004,7 +1950,7 @@ void node_on_exit(struct node_object *hnode, s32 node_status)
 	/* Unblock call to node_terminate */
 	(void)sync_set_event(hnode->sync_done);
 	/* Notify clients */
-	proc_notify_clients(hnode->hprocessor, DSP_NODESTATECHANGE);
+	proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
 	ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
 }
 
@@ -2036,13 +1982,13 @@ int node_pause(struct node_object *hnode)
 	if (status)
 		goto func_end;
 
-	status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+	status = proc_get_processor_id(pnode->processor, &proc_id);
 
 	if (proc_id == IVA_UNIT)
 		status = -ENOSYS;
 
 	if (!status) {
-		hnode_mgr = hnode->hnode_mgr;
+		hnode_mgr = hnode->node_mgr;
 
 		/* Enter critical section */
 		mutex_lock(&hnode_mgr->node_mgr_lock);
@@ -2053,7 +1999,7 @@ int node_pause(struct node_object *hnode)
 
 		if (status)
 			goto func_cont;
-		hprocessor = hnode->hprocessor;
+		hprocessor = hnode->processor;
 		status = proc_get_state(hprocessor, &proc_state,
 				sizeof(struct dsp_processorstate));
 		if (status)
@@ -2066,7 +2012,7 @@ int node_pause(struct node_object *hnode)
 		}
 
 		status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
-			hnode_mgr->ul_fxn_addrs[RMSCHANGENODEPRIORITY],
+			hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY],
 			hnode->node_env, NODE_SUSPENDEDPRI);
 
 		/* Update state */
@@ -2078,7 +2024,7 @@ func_cont:
 		/* Leave critical section */
 		mutex_unlock(&hnode_mgr->node_mgr_lock);
 		if (status >= 0) {
-			proc_notify_clients(hnode->hprocessor,
+			proc_notify_clients(hnode->processor,
 					    DSP_NODESTATECHANGE);
 			ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
 		}
@@ -2115,7 +2061,7 @@ int node_put_message(struct node_object *hnode,
 		status = -EFAULT;
 		goto func_end;
 	}
-	hprocessor = hnode->hprocessor;
+	hprocessor = hnode->processor;
 	status = proc_get_state(hprocessor, &proc_state,
 				sizeof(struct dsp_processorstate));
 	if (status)
@@ -2126,7 +2072,7 @@ int node_put_message(struct node_object *hnode,
 		status = -EPERM;
 		goto func_end;
 	}
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 	node_type = node_get_type(hnode);
 	if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
 	    node_type != NODE_DAISSOCKET)
@@ -2154,22 +2100,22 @@ int node_put_message(struct node_object *hnode,
 	/* assign pmsg values to new msg */
 	new_msg = *pmsg;
 	/* Now, check if message contains a SM buffer descriptor */
-	if (pmsg->dw_cmd & DSP_RMSBUFDESC) {
+	if (pmsg->cmd & DSP_RMSBUFDESC) {
 		/* Translate GPP Va to DSP physical buf Ptr. */
 		tmp_buf = cmm_xlator_translate(hnode->xlator,
-					       (void *)new_msg.dw_arg1,
+					       (void *)new_msg.arg1,
 					       CMM_VA2DSPPA);
 		if (tmp_buf != NULL) {
 			/* got translation, convert to MAUs in msg */
-			if (hnode->hnode_mgr->udsp_word_size != 0) {
-				new_msg.dw_arg1 =
+			if (hnode->node_mgr->dsp_word_size != 0) {
+				new_msg.arg1 =
 				    (u32) tmp_buf /
-				    hnode->hnode_mgr->udsp_word_size;
+				    hnode->node_mgr->dsp_word_size;
 				/* MAUs */
-				new_msg.dw_arg2 /= hnode->hnode_mgr->
-				    udsp_word_size;
+				new_msg.arg2 /= hnode->node_mgr->
+				    dsp_word_size;
 			} else {
-				pr_err("%s: udsp_word_size is zero!\n",
+				pr_err("%s: dsp_word_size is zero!\n",
 				       __func__);
 				status = -EPERM;	/* bad DSPWordSize */
 			}
@@ -2179,7 +2125,7 @@ int node_put_message(struct node_object *hnode,
 	}
 	if (!status) {
 		intf_fxns = hnode_mgr->intf_fxns;
-		status = (*intf_fxns->pfn_msg_put) (hnode->msg_queue_obj,
+		status = (*intf_fxns->msg_put) (hnode->msg_queue_obj,
 						    &new_msg, utimeout);
 	}
 func_end:
@@ -2226,8 +2172,8 @@ int node_register_notify(struct node_object *hnode, u32 event_mask,
 					       notify_type);
 		} else {
 			/* Send Message part of event mask to msg_ctrl */
-			intf_fxns = hnode->hnode_mgr->intf_fxns;
-			status = (*intf_fxns->pfn_msg_register_notify)
+			intf_fxns = hnode->node_mgr->intf_fxns;
+			status = (*intf_fxns->msg_register_notify)
 			    (hnode->msg_queue_obj,
 			     event_mask & DSP_NODEMESSAGEREADY, notify_type,
 			     hnotification);
@@ -2267,7 +2213,7 @@ int node_run(struct node_object *hnode)
 		status = -EFAULT;
 		goto func_end;
 	}
-	hprocessor = hnode->hprocessor;
+	hprocessor = hnode->processor;
 	status = proc_get_state(hprocessor, &proc_state,
 				sizeof(struct dsp_processorstate));
 	if (status)
@@ -2283,7 +2229,7 @@ int node_run(struct node_object *hnode)
 	if (status)
 		goto func_end;
 
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 	if (!hnode_mgr) {
 		status = -EFAULT;
 		goto func_end;
@@ -2297,7 +2243,7 @@ int node_run(struct node_object *hnode)
 		status = -EBADR;
 
 	if (!status)
-		status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+		status = proc_get_processor_id(pnode->processor, &proc_id);
 
 	if (status)
 		goto func_cont1;
@@ -2309,7 +2255,7 @@ int node_run(struct node_object *hnode)
 		/* If node's execute function is not loaded, load it */
 		if (!(hnode->loaded) && hnode->phase_split) {
 			status =
-			    hnode_mgr->nldr_fxns.pfn_load(hnode->nldr_node_obj,
+			    hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
 							  NLDR_EXECUTE);
 			if (!status) {
 				hnode->loaded = true;
@@ -2328,14 +2274,14 @@ int node_run(struct node_object *hnode)
 			}
 		}
 		if (!status) {
-			ul_fxn_addr = hnode_mgr->ul_fxn_addrs[RMSEXECUTENODE];
+			ul_fxn_addr = hnode_mgr->fxn_addrs[RMSEXECUTENODE];
 			status =
 			    disp_node_run(hnode_mgr->disp_obj, hnode,
 					  ul_fxn_addr, ul_execute_fxn,
 					  hnode->node_env);
 		}
 	} else if (state == NODE_PAUSED) {
-		ul_fxn_addr = hnode_mgr->ul_fxn_addrs[RMSCHANGENODEPRIORITY];
+		ul_fxn_addr = hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY];
 		status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
 						   ul_fxn_addr, hnode->node_env,
 						   NODE_GET_PRIORITY(hnode));
@@ -2353,7 +2299,7 @@ func_cont1:
 	/* Exit critical section */
 	mutex_unlock(&hnode_mgr->node_mgr_lock);
 	if (status >= 0) {
-		proc_notify_clients(hnode->hprocessor, DSP_NODESTATECHANGE);
+		proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
 		ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
 	}
 func_end:
@@ -2383,18 +2329,18 @@ int node_terminate(struct node_object *hnode, int *pstatus)
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(pstatus != NULL);
 
-	if (!hnode || !hnode->hnode_mgr) {
+	if (!hnode || !hnode->node_mgr) {
 		status = -EFAULT;
 		goto func_end;
 	}
-	if (pnode->hprocessor == NULL) {
+	if (pnode->processor == NULL) {
 		status = -EFAULT;
 		goto func_end;
 	}
-	status = proc_get_processor_id(pnode->hprocessor, &proc_id);
+	status = proc_get_processor_id(pnode->processor, &proc_id);
 
 	if (!status) {
-		hnode_mgr = hnode->hnode_mgr;
+		hnode_mgr = hnode->node_mgr;
 		node_type = node_get_type(hnode);
 		if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
 			status = -EPERM;
@@ -2421,7 +2367,7 @@ int node_terminate(struct node_object *hnode, int *pstatus)
 		 *  Send exit message. Do not change state to NODE_DONE
 		 *  here. That will be done in callback.
 		 */
-		status = proc_get_state(pnode->hprocessor, &proc_state,
+		status = proc_get_state(pnode->processor, &proc_state,
 					sizeof(struct dsp_processorstate));
 		if (status)
 			goto func_cont;
@@ -2432,19 +2378,19 @@ int node_terminate(struct node_object *hnode, int *pstatus)
 			goto func_cont;
 		}
 
-		msg.dw_cmd = RMS_EXIT;
-		msg.dw_arg1 = hnode->node_env;
-		killmsg.dw_cmd = RMS_KILLTASK;
-		killmsg.dw_arg1 = hnode->node_env;
+		msg.cmd = RMS_EXIT;
+		msg.arg1 = hnode->node_env;
+		killmsg.cmd = RMS_KILLTASK;
+		killmsg.arg1 = hnode->node_env;
 		intf_fxns = hnode_mgr->intf_fxns;
 
-		if (hnode->utimeout > MAXTIMEOUT)
+		if (hnode->timeout > MAXTIMEOUT)
 			kill_time_out = MAXTIMEOUT;
 		else
-			kill_time_out = (hnode->utimeout) * 2;
+			kill_time_out = (hnode->timeout) * 2;
 
-		status = (*intf_fxns->pfn_msg_put) (hnode->msg_queue_obj, &msg,
-						    hnode->utimeout);
+		status = (*intf_fxns->msg_put) (hnode->msg_queue_obj, &msg,
+						    hnode->timeout);
 		if (status)
 			goto func_cont;
 
@@ -2459,8 +2405,8 @@ int node_terminate(struct node_object *hnode, int *pstatus)
 		if (status != ETIME)
 			goto func_cont;
 
-		status = (*intf_fxns->pfn_msg_put)(hnode->msg_queue_obj,
-						&killmsg, hnode->utimeout);
+		status = (*intf_fxns->msg_put)(hnode->msg_queue_obj,
+						&killmsg, hnode->timeout);
 		if (status)
 			goto func_cont;
 		status = sync_wait_on_event(hnode->sync_done,
@@ -2470,7 +2416,7 @@ int node_terminate(struct node_object *hnode, int *pstatus)
 			 * Here it goes the part of the simulation of
 			 * the DSP exception.
 			 */
-			dev_get_deh_mgr(hnode_mgr->hdev_obj, &hdeh_mgr);
+			dev_get_deh_mgr(hnode_mgr->dev_obj, &hdeh_mgr);
 			if (!hdeh_mgr)
 				goto func_cont;
 
@@ -2514,12 +2460,12 @@ static void delete_node(struct node_object *hnode,
 #ifdef DSP_DMM_DEBUG
 	struct dmm_object *dmm_mgr;
 	struct proc_object *p_proc_object =
-	    (struct proc_object *)hnode->hprocessor;
+	    (struct proc_object *)hnode->processor;
 #endif
 	int status;
 	if (!hnode)
 		goto func_end;
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 	if (!hnode_mgr)
 		goto func_end;
 
@@ -2531,7 +2477,7 @@ static void delete_node(struct node_object *hnode,
 		/* Free msg_ctrl queue */
 		if (hnode->msg_queue_obj) {
 			intf_fxns = hnode_mgr->intf_fxns;
-			(*intf_fxns->pfn_msg_delete_queue) (hnode->
+			(*intf_fxns->msg_delete_queue) (hnode->
 							    msg_queue_obj);
 			hnode->msg_queue_obj = NULL;
 		}
@@ -2572,15 +2518,15 @@ static void delete_node(struct node_object *hnode,
 			kfree(task_arg_obj.strm_out_def);
 			task_arg_obj.strm_out_def = NULL;
 		}
-		if (task_arg_obj.udsp_heap_res_addr) {
-			status = proc_un_map(hnode->hprocessor, (void *)
-					     task_arg_obj.udsp_heap_addr,
+		if (task_arg_obj.dsp_heap_res_addr) {
+			status = proc_un_map(hnode->processor, (void *)
+					     task_arg_obj.dsp_heap_addr,
 					     pr_ctxt);
 
-			status = proc_un_reserve_memory(hnode->hprocessor,
+			status = proc_un_reserve_memory(hnode->processor,
 							(void *)
 							task_arg_obj.
-							udsp_heap_res_addr,
+							dsp_heap_res_addr,
 							pr_ctxt);
 #ifdef DSP_DMM_DEBUG
 			status = dmm_get_handle(p_proc_object, &dmm_mgr);
@@ -2595,8 +2541,8 @@ static void delete_node(struct node_object *hnode,
 		kfree(hnode->stream_connect);
 		hnode->stream_connect = NULL;
 	}
-	kfree(hnode->pstr_dev_name);
-	hnode->pstr_dev_name = NULL;
+	kfree(hnode->str_dev_name);
+	hnode->str_dev_name = NULL;
 
 	if (hnode->ntfy_obj) {
 		ntfy_delete(hnode->ntfy_obj);
@@ -2605,23 +2551,23 @@ static void delete_node(struct node_object *hnode,
 	}
 
 	/* These were allocated in dcd_get_object_def (via node_allocate) */
-	kfree(hnode->dcd_props.obj_data.node_obj.pstr_create_phase_fxn);
-	hnode->dcd_props.obj_data.node_obj.pstr_create_phase_fxn = NULL;
+	kfree(hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn);
+	hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn = NULL;
 
-	kfree(hnode->dcd_props.obj_data.node_obj.pstr_execute_phase_fxn);
-	hnode->dcd_props.obj_data.node_obj.pstr_execute_phase_fxn = NULL;
+	kfree(hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn);
+	hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn = NULL;
 
-	kfree(hnode->dcd_props.obj_data.node_obj.pstr_delete_phase_fxn);
-	hnode->dcd_props.obj_data.node_obj.pstr_delete_phase_fxn = NULL;
+	kfree(hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn);
+	hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn = NULL;
 
-	kfree(hnode->dcd_props.obj_data.node_obj.pstr_i_alg_name);
-	hnode->dcd_props.obj_data.node_obj.pstr_i_alg_name = NULL;
+	kfree(hnode->dcd_props.obj_data.node_obj.str_i_alg_name);
+	hnode->dcd_props.obj_data.node_obj.str_i_alg_name = NULL;
 
 	/* Free all SM address translator resources */
 	kfree(hnode->xlator);
 	kfree(hnode->nldr_node_obj);
 	hnode->nldr_node_obj = NULL;
-	hnode->hnode_mgr = NULL;
+	hnode->node_mgr = NULL;
 	kfree(hnode);
 	hnode = NULL;
 func_end:
@@ -2635,21 +2581,18 @@ func_end:
  */
 static void delete_node_mgr(struct node_mgr *hnode_mgr)
 {
-	struct node_object *hnode;
+	struct node_object *hnode, *tmp;
 
 	if (hnode_mgr) {
 		/* Free resources */
-		if (hnode_mgr->hdcd_mgr)
-			dcd_destroy_manager(hnode_mgr->hdcd_mgr);
+		if (hnode_mgr->dcd_mgr)
+			dcd_destroy_manager(hnode_mgr->dcd_mgr);
 
 		/* Remove any elements remaining in lists */
-		if (hnode_mgr->node_list) {
-			while ((hnode = (struct node_object *)
-				lst_get_head(hnode_mgr->node_list)))
-				delete_node(hnode, NULL);
-
-			DBC_ASSERT(LST_IS_EMPTY(hnode_mgr->node_list));
-			kfree(hnode_mgr->node_list);
+		list_for_each_entry_safe(hnode, tmp, &hnode_mgr->node_list,
+				list_elem) {
+			list_del(&hnode->list_elem);
+			delete_node(hnode, NULL);
 		}
 		mutex_destroy(&hnode_mgr->node_mgr_lock);
 		if (hnode_mgr->ntfy_obj) {
@@ -2657,21 +2600,6 @@ static void delete_node_mgr(struct node_mgr *hnode_mgr)
 			kfree(hnode_mgr->ntfy_obj);
 		}
 
-		if (hnode_mgr->pipe_map)
-			gb_delete(hnode_mgr->pipe_map);
-
-		if (hnode_mgr->pipe_done_map)
-			gb_delete(hnode_mgr->pipe_done_map);
-
-		if (hnode_mgr->chnl_map)
-			gb_delete(hnode_mgr->chnl_map);
-
-		if (hnode_mgr->dma_chnl_map)
-			gb_delete(hnode_mgr->dma_chnl_map);
-
-		if (hnode_mgr->zc_chnl_map)
-			gb_delete(hnode_mgr->zc_chnl_map);
-
 		if (hnode_mgr->disp_obj)
 			disp_delete(hnode_mgr->disp_obj);
 
@@ -2680,10 +2608,10 @@ static void delete_node_mgr(struct node_mgr *hnode_mgr)
 
 		/* Delete the loader */
 		if (hnode_mgr->nldr_obj)
-			hnode_mgr->nldr_fxns.pfn_delete(hnode_mgr->nldr_obj);
+			hnode_mgr->nldr_fxns.delete(hnode_mgr->nldr_obj);
 
 		if (hnode_mgr->loader_init)
-			hnode_mgr->nldr_fxns.pfn_exit();
+			hnode_mgr->nldr_fxns.exit();
 
 		kfree(hnode_mgr);
 	}
@@ -2758,22 +2686,22 @@ static void fill_stream_def(struct node_object *hnode,
 			    struct node_strmdef *pstrm_def,
 			    struct dsp_strmattr *pattrs)
 {
-	struct node_mgr *hnode_mgr = hnode->hnode_mgr;
+	struct node_mgr *hnode_mgr = hnode->node_mgr;
 
 	if (pattrs != NULL) {
 		pstrm_def->num_bufs = pattrs->num_bufs;
 		pstrm_def->buf_size =
-		    pattrs->buf_size / hnode_mgr->udsp_data_mau_size;
+		    pattrs->buf_size / hnode_mgr->dsp_data_mau_size;
 		pstrm_def->seg_id = pattrs->seg_id;
 		pstrm_def->buf_alignment = pattrs->buf_alignment;
-		pstrm_def->utimeout = pattrs->utimeout;
+		pstrm_def->timeout = pattrs->timeout;
 	} else {
 		pstrm_def->num_bufs = DEFAULTNBUFS;
 		pstrm_def->buf_size =
-		    DEFAULTBUFSIZE / hnode_mgr->udsp_data_mau_size;
+		    DEFAULTBUFSIZE / hnode_mgr->dsp_data_mau_size;
 		pstrm_def->seg_id = DEFAULTSEGID;
 		pstrm_def->buf_alignment = DEFAULTALIGNMENT;
-		pstrm_def->utimeout = DEFAULTTIMEOUT;
+		pstrm_def->timeout = DEFAULTTIMEOUT;
 	}
 }
 
@@ -2786,25 +2714,25 @@ static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream)
 {
 	/* Free up the pipe id unless other node has not yet been deleted. */
 	if (stream.type == NODECONNECT) {
-		if (gb_test(hnode_mgr->pipe_done_map, stream.dev_id)) {
+		if (test_bit(stream.dev_id, hnode_mgr->pipe_done_map)) {
 			/* The other node has already been deleted */
-			gb_clear(hnode_mgr->pipe_done_map, stream.dev_id);
-			gb_clear(hnode_mgr->pipe_map, stream.dev_id);
+			clear_bit(stream.dev_id, hnode_mgr->pipe_done_map);
+			clear_bit(stream.dev_id, hnode_mgr->pipe_map);
 		} else {
 			/* The other node has not been deleted yet */
-			gb_set(hnode_mgr->pipe_done_map, stream.dev_id);
+			set_bit(stream.dev_id, hnode_mgr->pipe_done_map);
 		}
 	} else if (stream.type == HOSTCONNECT) {
-		if (stream.dev_id < hnode_mgr->ul_num_chnls) {
-			gb_clear(hnode_mgr->chnl_map, stream.dev_id);
-		} else if (stream.dev_id < (2 * hnode_mgr->ul_num_chnls)) {
+		if (stream.dev_id < hnode_mgr->num_chnls) {
+			clear_bit(stream.dev_id, hnode_mgr->chnl_map);
+		} else if (stream.dev_id < (2 * hnode_mgr->num_chnls)) {
 			/* dsp-dma */
-			gb_clear(hnode_mgr->dma_chnl_map, stream.dev_id -
-				 (1 * hnode_mgr->ul_num_chnls));
-		} else if (stream.dev_id < (3 * hnode_mgr->ul_num_chnls)) {
+			clear_bit(stream.dev_id - (1 * hnode_mgr->num_chnls),
+					hnode_mgr->dma_chnl_map);
+		} else if (stream.dev_id < (3 * hnode_mgr->num_chnls)) {
 			/* zero-copy */
-			gb_clear(hnode_mgr->zc_chnl_map, stream.dev_id -
-				 (2 * hnode_mgr->ul_num_chnls));
+			clear_bit(stream.dev_id - (2 * hnode_mgr->num_chnls),
+					hnode_mgr->zc_chnl_map);
 		}
 	}
 }
@@ -2818,7 +2746,7 @@ static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
 				  u32 phase)
 {
 	char *pstr_fxn_name = NULL;
-	struct node_mgr *hnode_mgr = hnode->hnode_mgr;
+	struct node_mgr *hnode_mgr = hnode->node_mgr;
 	int status = 0;
 	DBC_REQUIRE(node_get_type(hnode) == NODE_TASK ||
 		    node_get_type(hnode) == NODE_DAISSOCKET ||
@@ -2827,15 +2755,15 @@ static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
 	switch (phase) {
 	case CREATEPHASE:
 		pstr_fxn_name =
-		    hnode->dcd_props.obj_data.node_obj.pstr_create_phase_fxn;
+		    hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn;
 		break;
 	case EXECUTEPHASE:
 		pstr_fxn_name =
-		    hnode->dcd_props.obj_data.node_obj.pstr_execute_phase_fxn;
+		    hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn;
 		break;
 	case DELETEPHASE:
 		pstr_fxn_name =
-		    hnode->dcd_props.obj_data.node_obj.pstr_delete_phase_fxn;
+		    hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn;
 		break;
 	default:
 		/* Should never get here */
@@ -2844,7 +2772,7 @@ static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
 	}
 
 	status =
-	    hnode_mgr->nldr_fxns.pfn_get_fxn_addr(hnode->nldr_node_obj,
+	    hnode_mgr->nldr_fxns.get_fxn_addr(hnode->nldr_node_obj,
 						  pstr_fxn_name, fxn_addr);
 
 	return status;
@@ -2923,11 +2851,11 @@ static int get_node_props(struct dcd_manager *hdcd_mgr,
 			DBC_REQUIRE(pndb_props->ac_name);
 			len = strlen(pndb_props->ac_name);
 			DBC_ASSERT(len < MAXDEVNAMELEN);
-			hnode->pstr_dev_name = kzalloc(len + 1, GFP_KERNEL);
-			if (hnode->pstr_dev_name == NULL) {
+			hnode->str_dev_name = kzalloc(len + 1, GFP_KERNEL);
+			if (hnode->str_dev_name == NULL) {
 				status = -ENOMEM;
 			} else {
-				strncpy(hnode->pstr_dev_name,
+				strncpy(hnode->str_dev_name,
 					pndb_props->ac_name, len);
 			}
 		}
@@ -2974,9 +2902,9 @@ static int get_proc_props(struct node_mgr *hnode_mgr,
 		host_res = pbridge_context->resources;
 		if (!host_res)
 			return -EPERM;
-		hnode_mgr->ul_chnl_offset = host_res->dw_chnl_offset;
-		hnode_mgr->ul_chnl_buf_size = host_res->dw_chnl_buf_size;
-		hnode_mgr->ul_num_chnls = host_res->dw_num_chnls;
+		hnode_mgr->chnl_offset = host_res->chnl_offset;
+		hnode_mgr->chnl_buf_size = host_res->chnl_buf_size;
+		hnode_mgr->num_chnls = host_res->num_chnls;
 
 		/*
 		 *  PROC will add an API to get dsp_processorinfo.
@@ -2987,9 +2915,9 @@ static int get_proc_props(struct node_mgr *hnode_mgr,
 		hnode_mgr->proc_type = 6410;
 		hnode_mgr->min_pri = DSP_NODE_MIN_PRIORITY;
 		hnode_mgr->max_pri = DSP_NODE_MAX_PRIORITY;
-		hnode_mgr->udsp_word_size = DSPWORDSIZE;
-		hnode_mgr->udsp_data_mau_size = DSPWORDSIZE;
-		hnode_mgr->udsp_mau_size = 1;
+		hnode_mgr->dsp_word_size = DSPWORDSIZE;
+		hnode_mgr->dsp_data_mau_size = DSPWORDSIZE;
+		hnode_mgr->dsp_mau_size = 1;
 
 	}
 	return status;
@@ -3046,24 +2974,24 @@ int node_get_uuid_props(void *hprocessor,
 	 */
 	mutex_lock(&hnode_mgr->node_mgr_lock);
 
-	dcd_node_props.pstr_create_phase_fxn = NULL;
-	dcd_node_props.pstr_execute_phase_fxn = NULL;
-	dcd_node_props.pstr_delete_phase_fxn = NULL;
-	dcd_node_props.pstr_i_alg_name = NULL;
+	dcd_node_props.str_create_phase_fxn = NULL;
+	dcd_node_props.str_execute_phase_fxn = NULL;
+	dcd_node_props.str_delete_phase_fxn = NULL;
+	dcd_node_props.str_i_alg_name = NULL;
 
-	status = dcd_get_object_def(hnode_mgr->hdcd_mgr,
+	status = dcd_get_object_def(hnode_mgr->dcd_mgr,
 		(struct dsp_uuid *)node_uuid, DSP_DCDNODETYPE,
 		(struct dcd_genericobj *)&dcd_node_props);
 
 	if (!status) {
 		*node_props = dcd_node_props.ndb_props;
-		kfree(dcd_node_props.pstr_create_phase_fxn);
+		kfree(dcd_node_props.str_create_phase_fxn);
 
-		kfree(dcd_node_props.pstr_execute_phase_fxn);
+		kfree(dcd_node_props.str_execute_phase_fxn);
 
-		kfree(dcd_node_props.pstr_delete_phase_fxn);
+		kfree(dcd_node_props.str_delete_phase_fxn);
 
-		kfree(dcd_node_props.pstr_i_alg_name);
+		kfree(dcd_node_props.str_i_alg_name);
 	}
 	/*  Leave the critical section, we're done. */
 	mutex_unlock(&hnode_mgr->node_mgr_lock);
@@ -3079,7 +3007,7 @@ func_end:
 static int get_rms_fxns(struct node_mgr *hnode_mgr)
 {
 	s32 i;
-	struct dev_object *dev_obj = hnode_mgr->hdev_obj;
+	struct dev_object *dev_obj = hnode_mgr->dev_obj;
 	int status = 0;
 
 	static char *psz_fxns[NUMRMSFXNS] = {
@@ -3096,7 +3024,7 @@ static int get_rms_fxns(struct node_mgr *hnode_mgr)
 
 	for (i = 0; i < NUMRMSFXNS; i++) {
 		status = dev_get_symbol(dev_obj, psz_fxns[i],
-					&(hnode_mgr->ul_fxn_addrs[i]));
+					&(hnode_mgr->fxn_addrs[i]));
 		if (status) {
 			if (status == -ESPIPE) {
 				/*
@@ -3137,17 +3065,17 @@ static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
 
 	DBC_REQUIRE(hnode);
 
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 
-	ul_size = ul_num_bytes / hnode_mgr->udsp_word_size;
-	ul_timeout = hnode->utimeout;
+	ul_size = ul_num_bytes / hnode_mgr->dsp_word_size;
+	ul_timeout = hnode->timeout;
 
 	/* Call new MemCopy function */
 	intf_fxns = hnode_mgr->intf_fxns;
-	status = dev_get_bridge_context(hnode_mgr->hdev_obj, &hbridge_context);
+	status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
 	if (!status) {
 		status =
-		    (*intf_fxns->pfn_brd_mem_copy) (hbridge_context,
+		    (*intf_fxns->brd_mem_copy) (hbridge_context,
 						dsp_run_addr, dsp_load_addr,
 						ul_num_bytes, (u32) mem_space);
 		if (!status)
@@ -3181,15 +3109,15 @@ static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
 	DBC_REQUIRE(hnode);
 	DBC_REQUIRE(mem_space & DBLL_CODE || mem_space & DBLL_DATA);
 
-	hnode_mgr = hnode->hnode_mgr;
+	hnode_mgr = hnode->node_mgr;
 
-	ul_timeout = hnode->utimeout;
+	ul_timeout = hnode->timeout;
 	mem_sect_type = (mem_space & DBLL_CODE) ? RMS_CODE : RMS_DATA;
 
 	/* Call new MemWrite function */
 	intf_fxns = hnode_mgr->intf_fxns;
-	status = dev_get_bridge_context(hnode_mgr->hdev_obj, &hbridge_context);
-	status = (*intf_fxns->pfn_brd_mem_write) (hbridge_context, pbuf,
+	status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
+	status = (*intf_fxns->brd_mem_write) (hbridge_context, pbuf,
 					dsp_add, ul_num_bytes, mem_sect_type);
 
 	return ul_num_bytes;
@@ -3204,23 +3132,17 @@ int node_find_addr(struct node_mgr *node_mgr, u32 sym_addr,
 {
 	struct node_object *node_obj;
 	int status = -ENOENT;
-	u32 n;
 
 	pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x,  %s)\n", __func__,
 			(unsigned int) node_mgr,
 			sym_addr, offset_range,
 			(unsigned int) sym_addr_output, sym_name);
 
-	node_obj = (struct node_object *)(node_mgr->node_list->head.next);
-
-	for (n = 0; n < node_mgr->num_nodes; n++) {
+	list_for_each_entry(node_obj, &node_mgr->node_list, list_elem) {
 		status = nldr_find_addr(node_obj->nldr_node_obj, sym_addr,
 			offset_range, sym_addr_output, sym_name);
-
 		if (!status)
 			break;
-
-		node_obj = (struct node_object *) (node_obj->list_elem.next);
 	}
 
 	return status;
diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c
index b47d7aa..c4e5c4e 100644
--- a/drivers/staging/tidspbridge/rmgr/proc.c
+++ b/drivers/staging/tidspbridge/rmgr/proc.c
@@ -29,7 +29,6 @@
 #include <dspbridge/dbc.h>
 
 /*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
 #include <dspbridge/ntfy.h>
 #include <dspbridge/sync.h>
 /*  ----------------------------------- Bridge Driver */
@@ -81,24 +80,24 @@ extern struct device *bridge;
 /* The proc_object structure. */
 struct proc_object {
 	struct list_head link;	/* Link to next proc_object */
-	struct dev_object *hdev_obj;	/* Device this PROC represents */
+	struct dev_object *dev_obj;	/* Device this PROC represents */
 	u32 process;		/* Process owning this Processor */
-	struct mgr_object *hmgr_obj;	/* Manager Object Handle */
+	struct mgr_object *mgr_obj;	/* Manager Object Handle */
 	u32 attach_count;	/* Processor attach count */
 	u32 processor_id;	/* Processor number */
-	u32 utimeout;		/* Time out count */
+	u32 timeout;		/* Time out count */
 	enum dsp_procstate proc_state;	/* Processor state */
-	u32 ul_unit;		/* DDSP unit number */
+	u32 unit;		/* DDSP unit number */
 	bool is_already_attached;	/*
 					 * True if the Device below has
 					 * GPP Client attached
 					 */
 	struct ntfy_object *ntfy_obj;	/* Manages  notifications */
 	/* Bridge Context Handle */
-	struct bridge_dev_context *hbridge_context;
+	struct bridge_dev_context *bridge_context;
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
-	char *psz_last_coff;
+	char *last_coff;
 	struct list_head proc_list;
 };
 
@@ -285,8 +284,8 @@ proc_attach(u32 processor_id,
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(ph_processor != NULL);
 
-	if (pr_ctxt->hprocessor) {
-		*ph_processor = pr_ctxt->hprocessor;
+	if (pr_ctxt->processor) {
+		*ph_processor = pr_ctxt->processor;
 		return status;
 	}
 
@@ -316,8 +315,8 @@ proc_attach(u32 processor_id,
 		status = -ENOMEM;
 		goto func_end;
 	}
-	p_proc_object->hdev_obj = hdev_obj;
-	p_proc_object->hmgr_obj = hmgr_obj;
+	p_proc_object->dev_obj = hdev_obj;
+	p_proc_object->mgr_obj = hmgr_obj;
 	p_proc_object->processor_id = dev_type;
 	/* Store TGID instead of process handle */
 	p_proc_object->process = current->tgid;
@@ -325,14 +324,14 @@ proc_attach(u32 processor_id,
 	INIT_LIST_HEAD(&p_proc_object->proc_list);
 
 	if (attr_in)
-		p_proc_object->utimeout = attr_in->utimeout;
+		p_proc_object->timeout = attr_in->timeout;
 	else
-		p_proc_object->utimeout = PROC_DFLT_TIMEOUT;
+		p_proc_object->timeout = PROC_DFLT_TIMEOUT;
 
 	status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns);
 	if (!status) {
 		status = dev_get_bridge_context(hdev_obj,
-					     &p_proc_object->hbridge_context);
+					     &p_proc_object->bridge_context);
 		if (status)
 			kfree(p_proc_object);
 	} else
@@ -357,8 +356,7 @@ proc_attach(u32 processor_id,
 		 * Return handle to this Processor Object:
 		 * Find out if the Device is already attached to a
 		 * Processor. If so, return AlreadyAttached status */
-		lst_init_elem(&p_proc_object->link);
-		status = dev_insert_proc_object(p_proc_object->hdev_obj,
+		status = dev_insert_proc_object(p_proc_object->dev_obj,
 						(u32) p_proc_object,
 						&p_proc_object->
 						is_already_attached);
@@ -375,7 +373,7 @@ proc_attach(u32 processor_id,
 		}
 		if (!status) {
 			*ph_processor = (void *)p_proc_object;
-			pr_ctxt->hprocessor = *ph_processor;
+			pr_ctxt->processor = *ph_processor;
 			(void)proc_notify_clients(p_proc_object,
 						  DSP_PROCESSORATTACH);
 		}
@@ -465,12 +463,12 @@ int proc_auto_start(struct cfg_devnode *dev_node_obj,
 		status = -ENOMEM;
 		goto func_end;
 	}
-	p_proc_object->hdev_obj = hdev_obj;
-	p_proc_object->hmgr_obj = hmgr_obj;
+	p_proc_object->dev_obj = hdev_obj;
+	p_proc_object->mgr_obj = hmgr_obj;
 	status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns);
 	if (!status)
 		status = dev_get_bridge_context(hdev_obj,
-					     &p_proc_object->hbridge_context);
+					     &p_proc_object->bridge_context);
 	if (status)
 		goto func_cont;
 
@@ -493,8 +491,8 @@ int proc_auto_start(struct cfg_devnode *dev_node_obj,
 		if (!status)
 			status = proc_start(p_proc_object);
 	}
-	kfree(p_proc_object->psz_last_coff);
-	p_proc_object->psz_last_coff = NULL;
+	kfree(p_proc_object->last_coff);
+	p_proc_object->last_coff = NULL;
 func_cont:
 	kfree(p_proc_object);
 func_end:
@@ -542,8 +540,8 @@ int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata * arg)
 			/* timeout = arg->cb_data; */
 			status = pwr_wake_dsp(timeout);
 		} else
-		    if (!((*p_proc_object->intf_fxns->pfn_dev_cntrl)
-				      (p_proc_object->hbridge_context, dw_cmd,
+		    if (!((*p_proc_object->intf_fxns->dev_cntrl)
+				      (p_proc_object->bridge_context, dw_cmd,
 				       arg))) {
 			status = 0;
 		} else {
@@ -569,7 +567,7 @@ int proc_detach(struct process_context *pr_ctxt)
 
 	DBC_REQUIRE(refs > 0);
 
-	p_proc_object = (struct proc_object *)pr_ctxt->hprocessor;
+	p_proc_object = (struct proc_object *)pr_ctxt->processor;
 
 	if (p_proc_object) {
 		/* Notify the Client */
@@ -580,14 +578,14 @@ int proc_detach(struct process_context *pr_ctxt)
 			kfree(p_proc_object->ntfy_obj);
 		}
 
-		kfree(p_proc_object->psz_last_coff);
-		p_proc_object->psz_last_coff = NULL;
+		kfree(p_proc_object->last_coff);
+		p_proc_object->last_coff = NULL;
 		/* Remove the Proc from the DEV List */
-		(void)dev_remove_proc_object(p_proc_object->hdev_obj,
+		(void)dev_remove_proc_object(p_proc_object->dev_obj,
 					     (u32) p_proc_object);
 		/* Free the Processor Object */
 		kfree(p_proc_object);
-		pr_ctxt->hprocessor = NULL;
+		pr_ctxt->processor = NULL;
 	} else {
 		status = -EFAULT;
 	}
@@ -615,7 +613,7 @@ int proc_enum_nodes(void *hprocessor, void **node_tab,
 	DBC_REQUIRE(pu_allocated != NULL);
 
 	if (p_proc_object) {
-		if (!(dev_get_node_manager(p_proc_object->hdev_obj,
+		if (!(dev_get_node_manager(p_proc_object->dev_obj,
 						       &hnode_mgr))) {
 			if (hnode_mgr) {
 				status = node_enum_nodes(hnode_mgr, node_tab,
@@ -781,12 +779,14 @@ int proc_begin_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
 							(u32)pmpu_addr,
 							ul_size, dir);
 
+	mutex_lock(&proc_lock);
+
 	/* find requested memory are in cached mapping information */
 	map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
 	if (!map_obj) {
 		pr_err("%s: find_containing_mapping failed\n", __func__);
 		status = -EFAULT;
-		goto err_out;
+		goto no_map;
 	}
 
 	if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
@@ -795,6 +795,8 @@ int proc_begin_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
 		status = -EFAULT;
 	}
 
+no_map:
+	mutex_unlock(&proc_lock);
 err_out:
 
 	return status;
@@ -819,21 +821,24 @@ int proc_end_dma(void *hprocessor, void *pmpu_addr, u32 ul_size,
 							(u32)pmpu_addr,
 							ul_size, dir);
 
+	mutex_lock(&proc_lock);
+
 	/* find requested memory are in cached mapping information */
 	map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size);
 	if (!map_obj) {
 		pr_err("%s: find_containing_mapping failed\n", __func__);
 		status = -EFAULT;
-		goto err_out;
+		goto no_map;
 	}
 
 	if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) {
 		pr_err("%s: InValid address parameters %p %x\n",
 		       __func__, pmpu_addr, ul_size);
 		status = -EFAULT;
-		goto err_out;
 	}
 
+no_map:
+	mutex_unlock(&proc_lock);
 err_out:
 	return status;
 }
@@ -892,7 +897,7 @@ int proc_get_resource_info(void *hprocessor, u32 resource_type,
 	case DSP_RESOURCE_DYNSARAM:
 	case DSP_RESOURCE_DYNEXTERNAL:
 	case DSP_RESOURCE_DYNSRAM:
-		status = dev_get_node_manager(p_proc_object->hdev_obj,
+		status = dev_get_node_manager(p_proc_object->dev_obj,
 					      &hnode_mgr);
 		if (!hnode_mgr) {
 			status = -EFAULT;
@@ -915,11 +920,11 @@ int proc_get_resource_info(void *hprocessor, u32 resource_type,
 		}
 		break;
 	case DSP_RESOURCE_PROCLOAD:
-		status = dev_get_io_mgr(p_proc_object->hdev_obj, &hio_mgr);
+		status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr);
 		if (hio_mgr)
 			status =
 			    p_proc_object->intf_fxns->
-			    pfn_io_get_proc_load(hio_mgr,
+			    io_get_proc_load(hio_mgr,
 						 (struct dsp_procloadstat *)
 						 &(resource_info->result.
 						   proc_load_stat));
@@ -965,7 +970,7 @@ int proc_get_dev_object(void *hprocessor,
 	DBC_REQUIRE(device_obj != NULL);
 
 	if (p_proc_object) {
-		*device_obj = p_proc_object->hdev_obj;
+		*device_obj = p_proc_object->dev_obj;
 		status = 0;
 	} else {
 		*device_obj = NULL;
@@ -997,8 +1002,8 @@ int proc_get_state(void *hprocessor,
 
 	if (p_proc_object) {
 		/* First, retrieve BRD state information */
-		status = (*p_proc_object->intf_fxns->pfn_brd_status)
-		    (p_proc_object->hbridge_context, &brd_status);
+		status = (*p_proc_object->intf_fxns->brd_status)
+		    (p_proc_object->bridge_context, &brd_status);
 		if (!status) {
 			switch (brd_status) {
 			case BRD_STOPPED:
@@ -1117,7 +1122,7 @@ int proc_load(void *hprocessor, const s32 argc_index,
 		status = -EFAULT;
 		goto func_end;
 	}
-	dev_get_cod_mgr(p_proc_object->hdev_obj, &cod_mgr);
+	dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr);
 	if (!cod_mgr) {
 		status = -EPERM;
 		goto func_end;
@@ -1149,7 +1154,7 @@ int proc_load(void *hprocessor, const s32 argc_index,
 			    prepend_envp(new_envp, (char **)user_envp,
 					 envp_elems, cnew_envp, sz_proc_id);
 			/* Get the DCD Handle */
-			status = mgr_get_dcd_handle(p_proc_object->hmgr_obj,
+			status = mgr_get_dcd_handle(p_proc_object->mgr_obj,
 						    (u32 *) &hdcd_handle);
 			if (!status) {
 				/*  Before proceeding with new load,
@@ -1158,16 +1163,16 @@ int proc_load(void *hprocessor, const s32 argc_index,
 				 *  If yes, unregister nodes in previously
 				 *  registered COFF.  If any error occurred,
 				 *  set previously registered COFF to NULL. */
-				if (p_proc_object->psz_last_coff != NULL) {
+				if (p_proc_object->last_coff != NULL) {
 					status =
 					    dcd_auto_unregister(hdcd_handle,
 								p_proc_object->
-								psz_last_coff);
+								last_coff);
 					/* Regardless of auto unregister status,
 					 *  free previously allocated
 					 *  memory. */
-					kfree(p_proc_object->psz_last_coff);
-					p_proc_object->psz_last_coff = NULL;
+					kfree(p_proc_object->last_coff);
+					p_proc_object->last_coff = NULL;
 				}
 			}
 			/* On success, do cod_open_base() */
@@ -1180,7 +1185,7 @@ int proc_load(void *hprocessor, const s32 argc_index,
 	if (!status) {
 		/* Auto-register data base */
 		/* Get the DCD Handle */
-		status = mgr_get_dcd_handle(p_proc_object->hmgr_obj,
+		status = mgr_get_dcd_handle(p_proc_object->mgr_obj,
 					    (u32 *) &hdcd_handle);
 		if (!status) {
 			/*  Auto register nodes in specified COFF
@@ -1197,15 +1202,15 @@ int proc_load(void *hprocessor, const s32 argc_index,
 			if (status) {
 				status = -EPERM;
 			} else {
-				DBC_ASSERT(p_proc_object->psz_last_coff ==
+				DBC_ASSERT(p_proc_object->last_coff ==
 					   NULL);
 				/* Allocate memory for pszLastCoff */
-				p_proc_object->psz_last_coff =
+				p_proc_object->last_coff =
 						kzalloc((strlen(user_args[0]) +
 						1), GFP_KERNEL);
 				/* If memory allocated, save COFF file name */
-				if (p_proc_object->psz_last_coff) {
-					strncpy(p_proc_object->psz_last_coff,
+				if (p_proc_object->last_coff) {
+					strncpy(p_proc_object->last_coff,
 						(char *)user_args[0],
 						(strlen((char *)user_args[0]) +
 						 1));
@@ -1217,19 +1222,19 @@ int proc_load(void *hprocessor, const s32 argc_index,
 	if (!status) {
 		/*  Create the message manager. This must be done
 		 *  before calling the IOOnLoaded function. */
-		dev_get_msg_mgr(p_proc_object->hdev_obj, &hmsg_mgr);
+		dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr);
 		if (!hmsg_mgr) {
-			status = msg_create(&hmsg_mgr, p_proc_object->hdev_obj,
+			status = msg_create(&hmsg_mgr, p_proc_object->dev_obj,
 					    (msg_onexit) node_on_exit);
 			DBC_ASSERT(!status);
-			dev_set_msg_mgr(p_proc_object->hdev_obj, hmsg_mgr);
+			dev_set_msg_mgr(p_proc_object->dev_obj, hmsg_mgr);
 		}
 	}
 	if (!status) {
 		/* Set the Device object's message manager */
-		status = dev_get_io_mgr(p_proc_object->hdev_obj, &hio_mgr);
+		status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr);
 		if (hio_mgr)
-			status = (*p_proc_object->intf_fxns->pfn_io_on_loaded)
+			status = (*p_proc_object->intf_fxns->io_on_loaded)
 								(hio_mgr);
 		else
 			status = -EFAULT;
@@ -1244,7 +1249,7 @@ int proc_load(void *hprocessor, const s32 argc_index,
 #endif
 		status = cod_load_base(cod_mgr, argc_index, (char **)user_args,
 				       dev_brd_write_fxn,
-				       p_proc_object->hdev_obj, NULL);
+				       p_proc_object->dev_obj, NULL);
 		if (status) {
 			if (status == -EBADF) {
 				dev_dbg(bridge, "%s: Failure to Load the EXE\n",
@@ -1264,8 +1269,8 @@ int proc_load(void *hprocessor, const s32 argc_index,
 	}
 	if (!status) {
 		/* Update the Processor status to loaded */
-		status = (*p_proc_object->intf_fxns->pfn_brd_set_state)
-		    (p_proc_object->hbridge_context, BRD_LOADED);
+		status = (*p_proc_object->intf_fxns->brd_set_state)
+		    (p_proc_object->bridge_context, BRD_LOADED);
 		if (!status) {
 			p_proc_object->proc_state = PROC_LOADED;
 			if (p_proc_object->ntfy_obj)
@@ -1285,7 +1290,7 @@ int proc_load(void *hprocessor, const s32 argc_index,
 			/* Reset DMM structs and add an initial free chunk */
 			if (!status) {
 				status =
-				    dev_get_dmm_mgr(p_proc_object->hdev_obj,
+				    dev_get_dmm_mgr(p_proc_object->dev_obj,
 						    &dmm_mgr);
 				if (dmm_mgr) {
 					/* Set dw_ext_end to DMM START u8
@@ -1306,8 +1311,8 @@ int proc_load(void *hprocessor, const s32 argc_index,
 	kfree(new_envp);
 	user_args[0] = pargv0;
 	if (!status) {
-		if (!((*p_proc_object->intf_fxns->pfn_brd_status)
-				(p_proc_object->hbridge_context, &brd_state))) {
+		if (!((*p_proc_object->intf_fxns->brd_status)
+				(p_proc_object->bridge_context, &brd_state))) {
 			pr_info("%s: Processor Loaded %s\n", __func__, pargv0);
 			kfree(drv_datap->base_img);
 			drv_datap->base_img = kmalloc(strlen(pargv0) + 1,
@@ -1399,8 +1404,8 @@ int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size,
 		if (!map_obj)
 			status = -ENOMEM;
 		else
-			status = (*p_proc_object->intf_fxns->pfn_brd_mem_map)
-			    (p_proc_object->hbridge_context, pa_align, va_align,
+			status = (*p_proc_object->intf_fxns->brd_mem_map)
+			    (p_proc_object->bridge_context, pa_align, va_align,
 			     size_align, ul_map_attr, map_obj->pages);
 	}
 	if (!status) {
@@ -1477,7 +1482,7 @@ int proc_register_notify(void *hprocessor, u32 event_mask,
 			 */
 			if ((event_mask == 0) && status) {
 				status =
-				    dev_get_deh_mgr(p_proc_object->hdev_obj,
+				    dev_get_deh_mgr(p_proc_object->dev_obj,
 						    &hdeh_mgr);
 				status =
 					bridge_deh_register_notify(hdeh_mgr,
@@ -1486,7 +1491,7 @@ int proc_register_notify(void *hprocessor, u32 event_mask,
 							hnotification);
 			}
 		} else {
-			status = dev_get_deh_mgr(p_proc_object->hdev_obj,
+			status = dev_get_deh_mgr(p_proc_object->dev_obj,
 						 &hdeh_mgr);
 			status =
 			    bridge_deh_register_notify(hdeh_mgr,
@@ -1572,7 +1577,7 @@ int proc_start(void *hprocessor)
 		status = -EBADR;
 		goto func_end;
 	}
-	status = dev_get_cod_mgr(p_proc_object->hdev_obj, &cod_mgr);
+	status = dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr);
 	if (!cod_mgr) {
 		status = -EFAULT;
 		goto func_cont;
@@ -1582,13 +1587,13 @@ int proc_start(void *hprocessor)
 	if (status)
 		goto func_cont;
 
-	status = (*p_proc_object->intf_fxns->pfn_brd_start)
-	    (p_proc_object->hbridge_context, dw_dsp_addr);
+	status = (*p_proc_object->intf_fxns->brd_start)
+	    (p_proc_object->bridge_context, dw_dsp_addr);
 	if (status)
 		goto func_cont;
 
 	/* Call dev_create2 */
-	status = dev_create2(p_proc_object->hdev_obj);
+	status = dev_create2(p_proc_object->dev_obj);
 	if (!status) {
 		p_proc_object->proc_state = PROC_RUNNING;
 		/* Deep sleep switces off the peripheral clocks.
@@ -1603,13 +1608,13 @@ int proc_start(void *hprocessor)
 		/* Failed to Create Node Manager and DISP Object
 		 * Stop the Processor from running. Put it in STOPPED State */
 		(void)(*p_proc_object->intf_fxns->
-		       pfn_brd_stop) (p_proc_object->hbridge_context);
+		       brd_stop) (p_proc_object->bridge_context);
 		p_proc_object->proc_state = PROC_STOPPED;
 	}
 func_cont:
 	if (!status) {
-		if (!((*p_proc_object->intf_fxns->pfn_brd_status)
-				(p_proc_object->hbridge_context, &brd_state))) {
+		if (!((*p_proc_object->intf_fxns->brd_status)
+				(p_proc_object->bridge_context, &brd_state))) {
 			pr_info("%s: dsp in running state\n", __func__);
 			DBC_ASSERT(brd_state != BRD_HIBERNATION);
 		}
@@ -1647,7 +1652,7 @@ int proc_stop(void *hprocessor)
 		goto func_end;
 	}
 	/* check if there are any running nodes */
-	status = dev_get_node_manager(p_proc_object->hdev_obj, &hnode_mgr);
+	status = dev_get_node_manager(p_proc_object->dev_obj, &hnode_mgr);
 	if (!status && hnode_mgr) {
 		status = node_enum_nodes(hnode_mgr, &hnode, node_tab_size,
 					 &num_nodes, &nodes_allocated);
@@ -1661,21 +1666,21 @@ int proc_stop(void *hprocessor)
 	/* It is OK to stop a device that does n't have nodes OR not started */
 	status =
 	    (*p_proc_object->intf_fxns->
-	     pfn_brd_stop) (p_proc_object->hbridge_context);
+	     brd_stop) (p_proc_object->bridge_context);
 	if (!status) {
 		dev_dbg(bridge, "%s: processor in standby mode\n", __func__);
 		p_proc_object->proc_state = PROC_STOPPED;
 		/* Destory the Node Manager, msg_ctrl Manager */
-		if (!(dev_destroy2(p_proc_object->hdev_obj))) {
+		if (!(dev_destroy2(p_proc_object->dev_obj))) {
 			/* Destroy the msg_ctrl by calling msg_delete */
-			dev_get_msg_mgr(p_proc_object->hdev_obj, &hmsg_mgr);
+			dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr);
 			if (hmsg_mgr) {
 				msg_delete(hmsg_mgr);
-				dev_set_msg_mgr(p_proc_object->hdev_obj, NULL);
+				dev_set_msg_mgr(p_proc_object->dev_obj, NULL);
 			}
 			if (!((*p_proc_object->
-			      intf_fxns->pfn_brd_status) (p_proc_object->
-							  hbridge_context,
+			      intf_fxns->brd_status) (p_proc_object->
+							  bridge_context,
 							  &brd_state)))
 				DBC_ASSERT(brd_state == BRD_STOPPED);
 		}
@@ -1722,13 +1727,12 @@ int proc_un_map(void *hprocessor, void *map_addr,
 	status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align);
 	/* Remove mapping from the page tables. */
 	if (!status) {
-		status = (*p_proc_object->intf_fxns->pfn_brd_mem_un_map)
-		    (p_proc_object->hbridge_context, va_align, size_align);
+		status = (*p_proc_object->intf_fxns->brd_mem_un_map)
+		    (p_proc_object->bridge_context, va_align, size_align);
 	}
 
-	mutex_unlock(&proc_lock);
 	if (status)
-		goto func_end;
+		goto unmap_failed;
 
 	/*
 	 * A successful unmap should be followed by removal of map_obj
@@ -1737,6 +1741,9 @@ int proc_un_map(void *hprocessor, void *map_addr,
 	 */
 	remove_mapping_information(pr_ctxt, (u32) map_addr, size_align);
 
+unmap_failed:
+	mutex_unlock(&proc_lock);
+
 func_end:
 	dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n",
 		__func__, hprocessor, map_addr, status);
@@ -1821,20 +1828,20 @@ static int proc_monitor(struct proc_object *proc_obj)
 	/* This is needed only when Device is loaded when it is
 	 * already 'ACTIVE' */
 	/* Destory the Node Manager, msg_ctrl Manager */
-	if (!dev_destroy2(proc_obj->hdev_obj)) {
+	if (!dev_destroy2(proc_obj->dev_obj)) {
 		/* Destroy the msg_ctrl by calling msg_delete */
-		dev_get_msg_mgr(proc_obj->hdev_obj, &hmsg_mgr);
+		dev_get_msg_mgr(proc_obj->dev_obj, &hmsg_mgr);
 		if (hmsg_mgr) {
 			msg_delete(hmsg_mgr);
-			dev_set_msg_mgr(proc_obj->hdev_obj, NULL);
+			dev_set_msg_mgr(proc_obj->dev_obj, NULL);
 		}
 	}
 	/* Place the Board in the Monitor State */
-	if (!((*proc_obj->intf_fxns->pfn_brd_monitor)
-			  (proc_obj->hbridge_context))) {
+	if (!((*proc_obj->intf_fxns->brd_monitor)
+			  (proc_obj->bridge_context))) {
 		status = 0;
-		if (!((*proc_obj->intf_fxns->pfn_brd_status)
-				  (proc_obj->hbridge_context, &brd_state)))
+		if (!((*proc_obj->intf_fxns->brd_status)
+				  (proc_obj->bridge_context, &brd_state)))
 			DBC_ASSERT(brd_state == BRD_IDLE);
 	}
 
@@ -1931,7 +1938,7 @@ int proc_notify_all_clients(void *proc, u32 events)
 		goto func_end;
 	}
 
-	dev_notify_clients(p_proc_object->hdev_obj, events);
+	dev_notify_clients(p_proc_object->dev_obj, events);
 
 func_end:
 	return status;
diff --git a/drivers/staging/tidspbridge/rmgr/pwr.c b/drivers/staging/tidspbridge/rmgr/pwr.c
index 85cb1a2..17748df 100644
--- a/drivers/staging/tidspbridge/rmgr/pwr.c
+++ b/drivers/staging/tidspbridge/rmgr/pwr.c
@@ -67,7 +67,7 @@ int pwr_sleep_dsp(const u32 sleep_code, const u32 timeout)
 			status = -EINVAL;
 
 		if (status != -EINVAL) {
-			status = (*intf_fxns->pfn_dev_cntrl) (dw_context,
+			status = (*intf_fxns->dev_cntrl) (dw_context,
 							      ioctlcode,
 							      (void *)&arg);
 		}
@@ -97,7 +97,7 @@ int pwr_wake_dsp(const u32 timeout)
 			if (!(dev_get_intf_fxns(hdev_obj,
 			      (struct bridge_drv_interface **)&intf_fxns))) {
 				status =
-				    (*intf_fxns->pfn_dev_cntrl) (dw_context,
+				    (*intf_fxns->dev_cntrl) (dw_context,
 							BRDIOCTL_WAKEUP,
 							(void *)&arg);
 			}
@@ -131,7 +131,7 @@ int pwr_pm_pre_scale(u16 voltage_domain, u32 level)
 			if (!(dev_get_intf_fxns(hdev_obj,
 			      (struct bridge_drv_interface **)&intf_fxns))) {
 				status =
-				    (*intf_fxns->pfn_dev_cntrl) (dw_context,
+				    (*intf_fxns->dev_cntrl) (dw_context,
 						BRDIOCTL_PRESCALE_NOTIFY,
 						(void *)&arg);
 			}
@@ -165,7 +165,7 @@ int pwr_pm_post_scale(u16 voltage_domain, u32 level)
 			if (!(dev_get_intf_fxns(hdev_obj,
 			      (struct bridge_drv_interface **)&intf_fxns))) {
 				status =
-				    (*intf_fxns->pfn_dev_cntrl) (dw_context,
+				    (*intf_fxns->dev_cntrl) (dw_context,
 						BRDIOCTL_POSTSCALE_NOTIFY,
 						(void *)&arg);
 			}
diff --git a/drivers/staging/tidspbridge/rmgr/rmm.c b/drivers/staging/tidspbridge/rmgr/rmm.c
index 761e8f4..f3dc0dd 100644
--- a/drivers/staging/tidspbridge/rmgr/rmm.c
+++ b/drivers/staging/tidspbridge/rmgr/rmm.c
@@ -38,6 +38,10 @@
  */
 
 #include <linux/types.h>
+#include <linux/list.h>
+
+/*  ----------------------------------- Host OS */
+#include <dspbridge/host_os.h>
 
 /*  ----------------------------------- DSP/BIOS Bridge */
 #include <dspbridge/dbdefs.h>
@@ -45,9 +49,6 @@
 /*  ----------------------------------- Trace & Debug */
 #include <dspbridge/dbc.h>
 
-/*  ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/list.h>
-
 /*  ----------------------------------- This */
 #include <dspbridge/rmm.h>
 
@@ -79,7 +80,7 @@ struct rmm_target_obj {
 	struct rmm_segment *seg_tab;
 	struct rmm_header **free_list;
 	u32 num_segs;
-	struct lst_list *ovly_list;	/* List of overlay memory in use */
+	struct list_head ovly_list;	/* List of overlay memory in use */
 };
 
 static u32 refs;		/* module reference count */
@@ -95,8 +96,7 @@ static bool free_block(struct rmm_target_obj *target, u32 segid, u32 addr,
 int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
 		     u32 align, u32 *dsp_address, bool reserve)
 {
-	struct rmm_ovly_sect *sect;
-	struct rmm_ovly_sect *prev_sect = NULL;
+	struct rmm_ovly_sect *sect, *prev_sect = NULL;
 	struct rmm_ovly_sect *new_sect;
 	u32 addr;
 	int status = 0;
@@ -120,10 +120,9 @@ int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
 	/* An overlay section - See if block is already in use. If not,
 	 * insert into the list in ascending address size. */
 	addr = *dsp_address;
-	sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list);
 	/*  Find place to insert new list element. List is sorted from
 	 *  smallest to largest address. */
-	while (sect != NULL) {
+	list_for_each_entry(sect, &target->ovly_list, list_elem) {
 		if (addr <= sect->addr) {
 			/* Check for overlap with sect */
 			if ((addr + size > sect->addr) || (prev_sect &&
@@ -135,9 +134,6 @@ int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
 			break;
 		}
 		prev_sect = sect;
-		sect = (struct rmm_ovly_sect *)lst_next(target->ovly_list,
-							(struct list_head *)
-							sect);
 	}
 	if (!status) {
 		/* No overlap - allocate list element for new section. */
@@ -145,20 +141,17 @@ int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size,
 		if (new_sect == NULL) {
 			status = -ENOMEM;
 		} else {
-			lst_init_elem((struct list_head *)new_sect);
 			new_sect->addr = addr;
 			new_sect->size = size;
 			new_sect->page = segid;
-			if (sect == NULL) {
+			if (list_is_last(&sect->list_elem, &target->ovly_list))
 				/* Put new section at the end of the list */
-				lst_put_tail(target->ovly_list,
-					     (struct list_head *)new_sect);
-			} else {
+				list_add_tail(&new_sect->list_elem,
+						&target->ovly_list);
+			else
 				/* Put new section just before sect */
-				lst_insert_before(target->ovly_list,
-						  (struct list_head *)new_sect,
-						  (struct list_head *)sect);
-			}
+				list_add_tail(&new_sect->list_elem,
+						&sect->list_elem);
 		}
 	}
 func_end:
@@ -230,14 +223,8 @@ int rmm_create(struct rmm_target_obj **target_obj,
 	}
 func_cont:
 	/* Initialize overlay memory list */
-	if (!status) {
-		target->ovly_list = kzalloc(sizeof(struct lst_list),
-							GFP_KERNEL);
-		if (target->ovly_list == NULL)
-			status = -ENOMEM;
-		else
-			INIT_LIST_HEAD(&target->ovly_list->head);
-	}
+	if (!status)
+		INIT_LIST_HEAD(&target->ovly_list);
 
 	if (!status) {
 		*target_obj = target;
@@ -259,7 +246,7 @@ func_cont:
  */
 void rmm_delete(struct rmm_target_obj *target)
 {
-	struct rmm_ovly_sect *ovly_section;
+	struct rmm_ovly_sect *sect, *tmp;
 	struct rmm_header *hptr;
 	struct rmm_header *next;
 	u32 i;
@@ -268,13 +255,9 @@ void rmm_delete(struct rmm_target_obj *target)
 
 	kfree(target->seg_tab);
 
-	if (target->ovly_list) {
-		while ((ovly_section = (struct rmm_ovly_sect *)lst_get_head
-			(target->ovly_list))) {
-			kfree(ovly_section);
-		}
-		DBC_ASSERT(LST_IS_EMPTY(target->ovly_list));
-		kfree(target->ovly_list);
+	list_for_each_entry_safe(sect, tmp, &target->ovly_list, list_elem) {
+		list_del(&sect->list_elem);
+		kfree(sect);
 	}
 
 	if (target->free_list != NULL) {
@@ -311,8 +294,8 @@ void rmm_exit(void)
 bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size,
 	      bool reserved)
 {
-	struct rmm_ovly_sect *sect;
-	bool ret = true;
+	struct rmm_ovly_sect *sect, *tmp;
+	bool ret = false;
 
 	DBC_REQUIRE(target);
 
@@ -333,24 +316,16 @@ bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size,
 
 	} else {
 		/* Unreserve memory */
-		sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list);
-		while (sect != NULL) {
+		list_for_each_entry_safe(sect, tmp, &target->ovly_list,
+				list_elem) {
 			if (dsp_addr == sect->addr) {
 				DBC_ASSERT(size == sect->size);
 				/* Remove from list */
-				lst_remove_elem(target->ovly_list,
-						(struct list_head *)sect);
+				list_del(&sect->list_elem);
 				kfree(sect);
-				break;
+				return true;
 			}
-			sect =
-			    (struct rmm_ovly_sect *)lst_next(target->ovly_list,
-							     (struct list_head
-							      *)sect);
 		}
-		if (sect == NULL)
-			ret = false;
-
 	}
 	return ret;
 }
@@ -394,19 +369,19 @@ bool rmm_stat(struct rmm_target_obj *target, enum dsp_memtype segid,
 		}
 
 		/* ul_size */
-		mem_stat_buf->ul_size = target->seg_tab[segid].length;
+		mem_stat_buf->size = target->seg_tab[segid].length;
 
-		/* ul_num_free_blocks */
-		mem_stat_buf->ul_num_free_blocks = free_blocks;
+		/* num_free_blocks */
+		mem_stat_buf->num_free_blocks = free_blocks;
 
-		/* ul_total_free_size */
-		mem_stat_buf->ul_total_free_size = total_free_size;
+		/* total_free_size */
+		mem_stat_buf->total_free_size = total_free_size;
 
-		/* ul_len_max_free_block */
-		mem_stat_buf->ul_len_max_free_block = max_free_size;
+		/* len_max_free_block */
+		mem_stat_buf->len_max_free_block = max_free_size;
 
-		/* ul_num_alloc_blocks */
-		mem_stat_buf->ul_num_alloc_blocks =
+		/* num_alloc_blocks */
+		mem_stat_buf->num_alloc_blocks =
 		    target->seg_tab[segid].number;
 
 		ret = true;
diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c
index 2e42714..3fae0e9 100644
--- a/drivers/staging/tidspbridge/rmgr/strm.c
+++ b/drivers/staging/tidspbridge/rmgr/strm.c
@@ -55,7 +55,7 @@
  */
 struct strm_mgr {
 	struct dev_object *dev_obj;	/* Device for this processor */
-	struct chnl_mgr *hchnl_mgr;	/* Channel manager */
+	struct chnl_mgr *chnl_mgr;	/* Channel manager */
 	/* Function interface to Bridge driver */
 	struct bridge_drv_interface *intf_fxns;
 };
@@ -68,16 +68,16 @@ struct strm_object {
 	struct strm_mgr *strm_mgr_obj;
 	struct chnl_object *chnl_obj;
 	u32 dir;		/* DSP_TONODE or DSP_FROMNODE */
-	u32 utimeout;
+	u32 timeout;
 	u32 num_bufs;		/* Max # of bufs allowed in stream */
-	u32 un_bufs_in_strm;	/* Current # of bufs in stream */
-	u32 ul_n_bytes;		/* bytes transferred since idled */
+	u32 bufs_in_strm;	/* Current # of bufs in stream */
+	u32 bytes;		/* bytes transferred since idled */
 	/* STREAM_IDLE, STREAM_READY, ... */
 	enum dsp_streamstate strm_state;
 	void *user_event;	/* Saved for strm_get_info() */
 	enum dsp_strmmode strm_mode;	/* STRMMODE_[PROCCOPY][ZEROCOPY]... */
-	u32 udma_chnl_id;	/* DMA chnl id */
-	u32 udma_priority;	/* DMA priority:DMAPRI_[LOW][HIGH] */
+	u32 dma_chnl_id;	/* DMA chnl id */
+	u32 dma_priority;	/* DMA priority:DMAPRI_[LOW][HIGH] */
 	u32 segment_id;		/* >0 is SM segment.=0 is local heap */
 	u32 buf_alignment;	/* Alignment for stream bufs */
 	/* Stream's SM address translator */
@@ -102,7 +102,7 @@ int strm_allocate_buffer(struct strm_res_object *strmres, u32 usize,
 	int status = 0;
 	u32 alloc_cnt = 0;
 	u32 i;
-	struct strm_object *stream_obj = strmres->hstream;
+	struct strm_object *stream_obj = strmres->stream;
 
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(ap_buffer != NULL);
@@ -154,7 +154,7 @@ int strm_close(struct strm_res_object *strmres,
 	struct bridge_drv_interface *intf_fxns;
 	struct chnl_info chnl_info_obj;
 	int status = 0;
-	struct strm_object *stream_obj = strmres->hstream;
+	struct strm_object *stream_obj = strmres->stream;
 
 	DBC_REQUIRE(refs > 0);
 
@@ -165,7 +165,7 @@ int strm_close(struct strm_res_object *strmres,
 		 * -EPIPE */
 		intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
 		status =
-		    (*intf_fxns->pfn_chnl_get_info) (stream_obj->chnl_obj,
+		    (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj,
 						     &chnl_info_obj);
 		DBC_ASSERT(!status);
 
@@ -213,7 +213,7 @@ int strm_create(struct strm_mgr **strm_man,
 
 	/* Get Channel manager and Bridge function interface */
 	if (!status) {
-		status = dev_get_chnl_mgr(dev_obj, &(strm_mgr_obj->hchnl_mgr));
+		status = dev_get_chnl_mgr(dev_obj, &(strm_mgr_obj->chnl_mgr));
 		if (!status) {
 			(void)dev_get_intf_fxns(dev_obj,
 						&(strm_mgr_obj->intf_fxns));
@@ -268,7 +268,7 @@ int strm_free_buffer(struct strm_res_object *strmres, u8 ** ap_buffer,
 {
 	int status = 0;
 	u32 i = 0;
-	struct strm_object *stream_obj = strmres->hstream;
+	struct strm_object *stream_obj = strmres->stream;
 
 	DBC_REQUIRE(refs > 0);
 	DBC_REQUIRE(ap_buffer != NULL);
@@ -323,7 +323,7 @@ int strm_get_info(struct strm_object *stream_obj,
 
 	intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
 	status =
-	    (*intf_fxns->pfn_chnl_get_info) (stream_obj->chnl_obj,
+	    (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj,
 						  &chnl_info_obj);
 	if (status)
 		goto func_end;
@@ -341,10 +341,10 @@ int strm_get_info(struct strm_object *stream_obj,
 	stream_info->user_strm->number_bufs_in_stream = chnl_info_obj.cio_cs +
 	    chnl_info_obj.cio_reqs;
 	/* # of bytes transferred since last call to DSPStream_Idle() */
-	stream_info->user_strm->ul_number_bytes = chnl_info_obj.bytes_tx;
+	stream_info->user_strm->number_bytes = chnl_info_obj.bytes_tx;
 	stream_info->user_strm->sync_object_handle = chnl_info_obj.event_obj;
 	/* Determine stream state based on channel state and info */
-	if (chnl_info_obj.dw_state & CHNL_STATEEOS) {
+	if (chnl_info_obj.state & CHNL_STATEEOS) {
 		stream_info->user_strm->ss_stream_state = STREAM_DONE;
 	} else {
 		if (chnl_info_obj.cio_cs > 0)
@@ -377,8 +377,8 @@ int strm_idle(struct strm_object *stream_obj, bool flush_data)
 	} else {
 		intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
 
-		status = (*intf_fxns->pfn_chnl_idle) (stream_obj->chnl_obj,
-						      stream_obj->utimeout,
+		status = (*intf_fxns->chnl_idle) (stream_obj->chnl_obj,
+						      stream_obj->timeout,
 						      flush_data);
 	}
 
@@ -435,7 +435,7 @@ int strm_issue(struct strm_object *stream_obj, u8 *pbuf, u32 ul_bytes,
 
 		}
 		if (!status) {
-			status = (*intf_fxns->pfn_chnl_add_io_req)
+			status = (*intf_fxns->chnl_add_io_req)
 			    (stream_obj->chnl_obj, pbuf, ul_bytes, ul_buf_size,
 			     (u32) tmp_buf, dw_arg);
 		}
@@ -494,8 +494,8 @@ int strm_open(struct node_object *hnode, u32 dir, u32 index,
 			strm_obj->strm_state = STREAM_IDLE;
 			strm_obj->user_event = pattr->user_event;
 			if (pattr->stream_attr_in != NULL) {
-				strm_obj->utimeout =
-				    pattr->stream_attr_in->utimeout;
+				strm_obj->timeout =
+				    pattr->stream_attr_in->timeout;
 				strm_obj->num_bufs =
 				    pattr->stream_attr_in->num_bufs;
 				strm_obj->strm_mode =
@@ -504,25 +504,25 @@ int strm_open(struct node_object *hnode, u32 dir, u32 index,
 				    pattr->stream_attr_in->segment_id;
 				strm_obj->buf_alignment =
 				    pattr->stream_attr_in->buf_alignment;
-				strm_obj->udma_chnl_id =
-				    pattr->stream_attr_in->udma_chnl_id;
-				strm_obj->udma_priority =
-				    pattr->stream_attr_in->udma_priority;
+				strm_obj->dma_chnl_id =
+				    pattr->stream_attr_in->dma_chnl_id;
+				strm_obj->dma_priority =
+				    pattr->stream_attr_in->dma_priority;
 				chnl_attr_obj.uio_reqs =
 				    pattr->stream_attr_in->num_bufs;
 			} else {
-				strm_obj->utimeout = DEFAULTTIMEOUT;
+				strm_obj->timeout = DEFAULTTIMEOUT;
 				strm_obj->num_bufs = DEFAULTNUMBUFS;
 				strm_obj->strm_mode = STRMMODE_PROCCOPY;
 				strm_obj->segment_id = 0;	/* local mem */
 				strm_obj->buf_alignment = 0;
-				strm_obj->udma_chnl_id = 0;
-				strm_obj->udma_priority = 0;
+				strm_obj->dma_chnl_id = 0;
+				strm_obj->dma_priority = 0;
 				chnl_attr_obj.uio_reqs = DEFAULTNUMBUFS;
 			}
 			chnl_attr_obj.reserved1 = NULL;
 			/* DMA chnl flush timeout */
-			chnl_attr_obj.reserved2 = strm_obj->utimeout;
+			chnl_attr_obj.reserved2 = strm_obj->timeout;
 			chnl_attr_obj.event_obj = NULL;
 			if (pattr->user_event != NULL)
 				chnl_attr_obj.event_obj = pattr->user_event;
@@ -532,7 +532,7 @@ int strm_open(struct node_object *hnode, u32 dir, u32 index,
 	if (status)
 		goto func_cont;
 
-	if ((pattr->virt_base == NULL) || !(pattr->ul_virt_size > 0))
+	if ((pattr->virt_base == NULL) || !(pattr->virt_size > 0))
 		goto func_cont;
 
 	/* No System DMA */
@@ -547,7 +547,7 @@ int strm_open(struct node_object *hnode, u32 dir, u32 index,
 			/*  Set translators Virt Addr attributes */
 			status = cmm_xlator_info(strm_obj->xlator,
 						 (u8 **) &pattr->virt_base,
-						 pattr->ul_virt_size,
+						 pattr->virt_size,
 						 strm_obj->segment_id, true);
 		}
 	}
@@ -557,8 +557,8 @@ func_cont:
 		chnl_mode = (dir == DSP_TONODE) ?
 		    CHNL_MODETODSP : CHNL_MODEFROMDSP;
 		intf_fxns = strm_mgr_obj->intf_fxns;
-		status = (*intf_fxns->pfn_chnl_open) (&(strm_obj->chnl_obj),
-						      strm_mgr_obj->hchnl_mgr,
+		status = (*intf_fxns->chnl_open) (&(strm_obj->chnl_obj),
+						      strm_mgr_obj->chnl_mgr,
 						      chnl_mode, ul_chnl_id,
 						      &chnl_attr_obj);
 		if (status) {
@@ -572,7 +572,7 @@ func_cont:
 				 * We got a status that's not return-able.
 				 * Assert that we got something we were
 				 * expecting (-EFAULT isn't acceptable,
-				 * strm_mgr_obj->hchnl_mgr better be valid or we
+				 * strm_mgr_obj->chnl_mgr better be valid or we
 				 * assert here), and then return -EPERM.
 				 */
 				DBC_ASSERT(status == -ENOSR ||
@@ -631,15 +631,15 @@ int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr,
 	intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
 
 	status =
-	    (*intf_fxns->pfn_chnl_get_ioc) (stream_obj->chnl_obj,
-					    stream_obj->utimeout,
+	    (*intf_fxns->chnl_get_ioc) (stream_obj->chnl_obj,
+					    stream_obj->timeout,
 					    &chnl_ioc_obj);
 	if (!status) {
 		*nbytes = chnl_ioc_obj.byte_size;
 		if (buff_size)
 			*buff_size = chnl_ioc_obj.buf_size;
 
-		*pdw_arg = chnl_ioc_obj.dw_arg;
+		*pdw_arg = chnl_ioc_obj.arg;
 		if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
 			if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) {
 				status = -ETIME;
@@ -655,14 +655,14 @@ int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr,
 		    && (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
 		    && (stream_obj->strm_mode == STRMMODE_ZEROCOPY)) {
 			/*
-			 *  This is a zero-copy channel so chnl_ioc_obj.pbuf
+			 *  This is a zero-copy channel so chnl_ioc_obj.buf
 			 *  contains the DSP address of SM. We need to
 			 *  translate it to a virtual address for the user
 			 *  thread to access.
 			 *  Note: Could add CMM_DSPPA2VA to CMM in the future.
 			 */
 			tmp_buf = cmm_xlator_translate(stream_obj->xlator,
-						       chnl_ioc_obj.pbuf,
+						       chnl_ioc_obj.buf,
 						       CMM_DSPPA2PA);
 			if (tmp_buf != NULL) {
 				/* now convert this GPP Pa to Va */
@@ -674,9 +674,9 @@ int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr,
 			if (tmp_buf == NULL)
 				status = -ESRCH;
 
-			chnl_ioc_obj.pbuf = tmp_buf;
+			chnl_ioc_obj.buf = tmp_buf;
 		}
-		*buf_ptr = chnl_ioc_obj.pbuf;
+		*buf_ptr = chnl_ioc_obj.buf;
 	}
 func_end:
 	/* ensure we return a documented return code */
@@ -719,7 +719,7 @@ int strm_register_notify(struct strm_object *stream_obj, u32 event_mask,
 		intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
 
 		status =
-		    (*intf_fxns->pfn_chnl_register_notify) (stream_obj->
+		    (*intf_fxns->chnl_register_notify) (stream_obj->
 							    chnl_obj,
 							    event_mask,
 							    notify_type,
@@ -765,7 +765,7 @@ int strm_select(struct strm_object **strm_tab, u32 strms,
 	/* Determine which channels have IO ready */
 	for (i = 0; i < strms; i++) {
 		intf_fxns = strm_tab[i]->strm_mgr_obj->intf_fxns;
-		status = (*intf_fxns->pfn_chnl_get_info) (strm_tab[i]->chnl_obj,
+		status = (*intf_fxns->chnl_get_info) (strm_tab[i]->chnl_obj,
 							  &chnl_info_obj);
 		if (status) {
 			break;
@@ -786,7 +786,7 @@ int strm_select(struct strm_object **strm_tab, u32 strms,
 			for (i = 0; i < strms; i++) {
 				intf_fxns =
 				    strm_tab[i]->strm_mgr_obj->intf_fxns;
-				status = (*intf_fxns->pfn_chnl_get_info)
+				status = (*intf_fxns->chnl_get_info)
 				    (strm_tab[i]->chnl_obj, &chnl_info_obj);
 				if (status)
 					break;
@@ -832,7 +832,7 @@ static int delete_strm(struct strm_object *stream_obj)
 			intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
 			/* Channel close can fail only if the channel handle
 			 * is invalid. */
-			status = (*intf_fxns->pfn_chnl_close)
+			status = (*intf_fxns->chnl_close)
 					(stream_obj->chnl_obj);
 		}
 		/* Free all SM address translator resources */
diff --git a/drivers/staging/tm6000/tm6000-input.c b/drivers/staging/tm6000/tm6000-input.c
index 21e7da4..dae2f1f 100644
--- a/drivers/staging/tm6000/tm6000-input.c
+++ b/drivers/staging/tm6000/tm6000-input.c
@@ -313,6 +313,8 @@ int tm6000_ir_int_start(struct tm6000_core *dev)
 		return -ENODEV;
 
 	ir->int_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ir->int_urb)
+		return -ENOMEM;
 
 	pipe = usb_rcvintpipe(dev->udev,
 		dev->int_in.endp->desc.bEndpointAddress
@@ -374,7 +376,7 @@ int tm6000_ir_init(struct tm6000_core *dev)
 
 	ir = kzalloc(sizeof(*ir), GFP_KERNEL);
 	rc = rc_allocate_device();
-	if (!ir | !rc)
+	if (!ir || !rc)
 		goto out;
 
 	/* record handles to ourself */
diff --git a/drivers/staging/tty/Kconfig b/drivers/staging/tty/Kconfig
new file mode 100644
index 0000000..77103a0
--- /dev/null
+++ b/drivers/staging/tty/Kconfig
@@ -0,0 +1,87 @@
+config STALLION
+	tristate "Stallion EasyIO or EC8/32 support"
+	depends on STALDRV && (ISA || EISA || PCI)
+	help
+	  If you have an EasyIO or EasyConnection 8/32 multiport Stallion
+	  card, then this is for you; say Y.  Make sure to read
+	  <file:Documentation/serial/stallion.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called stallion.
+
+config ISTALLION
+	tristate "Stallion EC8/64, ONboard, Brumby support"
+	depends on STALDRV && (ISA || EISA || PCI)
+	help
+	  If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
+	  serial multiport card, say Y here. Make sure to read
+	  <file:Documentation/serial/stallion.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called istallion.
+
+config DIGIEPCA
+	tristate "Digiboard Intelligent Async Support"
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
+	---help---
+	  This is a driver for Digi International's Xx, Xeve, and Xem series
+	  of cards which provide multiple serial ports. You would need
+	  something like this to connect more than two modems to your Linux
+	  box, for instance in order to become a dial-in server. This driver
+	  supports the original PC (ISA) boards as well as PCI, and EISA. If
+	  you have a card like this, say Y here and read the file
+	  <file:Documentation/serial/digiepca.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called epca.
+
+config RISCOM8
+	tristate "SDL RISCom/8 card support"
+	depends on SERIAL_NONSTANDARD
+	help
+	  This is a driver for the SDL Communications RISCom/8 multiport card,
+	  which gives you many serial ports. You would need something like
+	  this to connect more than two modems to your Linux box, for instance
+	  in order to become a dial-in server. If you have a card like that,
+	  say Y here and read the file <file:Documentation/serial/riscom8.txt>.
+
+	  Also it's possible to say M here and compile this driver as kernel
+	  loadable module; the module will be called riscom8.
+
+config SPECIALIX
+	tristate "Specialix IO8+ card support"
+	depends on SERIAL_NONSTANDARD
+	help
+	  This is a driver for the Specialix IO8+ multiport card (both the
+	  ISA and the PCI version) which gives you many serial ports. You
+	  would need something like this to connect more than two modems to
+	  your Linux box, for instance in order to become a dial-in server.
+
+	  If you have a card like that, say Y here and read the file
+	  <file:Documentation/serial/specialix.txt>. Also it's possible to say
+	  M here and compile this driver as kernel loadable module which will be
+	  called specialix.
+
+config COMPUTONE
+	tristate "Computone IntelliPort Plus serial support"
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
+	---help---
+	  This driver supports the entire family of Intelliport II/Plus
+	  controllers with the exception of the MicroChannel controllers and
+	  products previous to the Intelliport II. These are multiport cards,
+	  which give you many serial ports. You would need something like this
+	  to connect more than two modems to your Linux box, for instance in
+	  order to become a dial-in server. If you have a card like that, say
+	  Y here and read <file:Documentation/serial/computone.txt>.
+
+	  To compile this driver as module, choose M here: the
+	  module will be called ip2.
+
+config SERIAL167
+	bool "CD2401 support for MVME166/7 serial ports"
+	depends on MVME16x
+	help
+	  This is the driver for the serial ports on the Motorola MVME166,
+	  167, and 172 boards.  Everyone using one of these boards should say
+	  Y here.
+
diff --git a/drivers/staging/tty/Makefile b/drivers/staging/tty/Makefile
new file mode 100644
index 0000000..ac57c105
--- /dev/null
+++ b/drivers/staging/tty/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_STALLION)		+= stallion.o
+obj-$(CONFIG_ISTALLION)		+= istallion.o
+obj-$(CONFIG_DIGIEPCA)		+= epca.o
+obj-$(CONFIG_SERIAL167)		+= serial167.o
+obj-$(CONFIG_SPECIALIX)		+= specialix.o
+obj-$(CONFIG_RISCOM8)		+= riscom8.o
+obj-$(CONFIG_COMPUTONE)		+= ip2/
diff --git a/drivers/staging/tty/TODO b/drivers/staging/tty/TODO
new file mode 100644
index 0000000..8875645
--- /dev/null
+++ b/drivers/staging/tty/TODO
@@ -0,0 +1,6 @@
+These are a few tty/serial drivers that either do not build,
+or work if they do build, or if they seem to work, are for obsolete
+hardware, or are full of unfixable races and no one uses them anymore.
+
+If no one steps up to adopt any of these drivers, they will be removed
+in the 2.6.41 release.
diff --git a/drivers/staging/tty/cd1865.h b/drivers/staging/tty/cd1865.h
new file mode 100644
index 0000000..9940966
--- /dev/null
+++ b/drivers/staging/tty/cd1865.h
@@ -0,0 +1,263 @@
+/*
+ *      linux/drivers/char/cd1865.h -- Definitions relating to the CD1865
+ *                          for the Specialix IO8+ multiport serial driver.
+ *
+ *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
+ *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
+ *
+ *      Specialix pays for the development and support of this driver.
+ *      Please DO contact io8-linux@specialix.co.uk if you require
+ *      support.
+ *
+ *      This driver was developped in the BitWizard linux device
+ *      driver service. If you require a linux device driver for your
+ *      product, please contact devices@BitWizard.nl for a quote.
+ *
+ */
+
+/*
+ * Definitions for Driving CD180/CD1864/CD1865 based eightport serial cards.
+ */
+
+
+/* Values of choice for Interrupt ACKs */
+/* These values are "obligatory" if you use the register based
+ * interrupt acknowledgements. See page 99-101 of V2.0 of the CD1865
+ * databook */
+#define SX_ACK_MINT     0x75    /* goes to PILR1                           */
+#define SX_ACK_TINT     0x76    /* goes to PILR2                           */
+#define SX_ACK_RINT     0x77    /* goes to PILR3                           */
+
+/* Chip ID (is used when chips ar daisy chained.) */
+#define SX_ID           0x10
+
+/* Definitions for Cirrus Logic CL-CD186x 8-port async mux chip */
+ 
+#define CD186x_NCH       8       /* Total number of channels                */
+#define CD186x_TPC       16      /* Ticks per character                     */
+#define CD186x_NFIFO	 8	 /* TX FIFO size                            */
+
+
+/* Global registers */
+
+#define CD186x_GIVR      0x40    /* Global Interrupt Vector Register        */
+#define CD186x_GICR      0x41    /* Global Interrupting Channel Register    */
+#define CD186x_PILR1     0x61    /* Priority Interrupt Level Register 1     */
+#define CD186x_PILR2     0x62    /* Priority Interrupt Level Register 2     */
+#define CD186x_PILR3     0x63    /* Priority Interrupt Level Register 3     */
+#define CD186x_CAR       0x64    /* Channel Access Register                 */
+#define CD186x_SRSR      0x65    /* Channel Access Register                 */
+#define CD186x_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
+#define CD186x_PPRH      0x70    /* Prescaler Period Register High          */
+#define CD186x_PPRL      0x71    /* Prescaler Period Register Low           */
+#define CD186x_RDR       0x78    /* Receiver Data Register                  */
+#define CD186x_RCSR      0x7a    /* Receiver Character Status Register      */
+#define CD186x_TDR       0x7b    /* Transmit Data Register                  */
+#define CD186x_EOIR      0x7f    /* End of Interrupt Register               */
+#define CD186x_MRAR      0x75    /* Modem Request Acknowledge register       */
+#define CD186x_TRAR      0x76    /* Transmit Request Acknowledge register    */
+#define CD186x_RRAR      0x77    /* Receive Request Acknowledge register     */
+#define CD186x_SRCR      0x66    /* Service Request Configuration register  */
+
+/* Channel Registers */
+
+#define CD186x_CCR       0x01    /* Channel Command Register                */
+#define CD186x_IER       0x02    /* Interrupt Enable Register               */
+#define CD186x_COR1      0x03    /* Channel Option Register 1               */
+#define CD186x_COR2      0x04    /* Channel Option Register 2               */
+#define CD186x_COR3      0x05    /* Channel Option Register 3               */
+#define CD186x_CCSR      0x06    /* Channel Control Status Register         */
+#define CD186x_RDCR      0x07    /* Receive Data Count Register             */
+#define CD186x_SCHR1     0x09    /* Special Character Register 1            */
+#define CD186x_SCHR2     0x0a    /* Special Character Register 2            */
+#define CD186x_SCHR3     0x0b    /* Special Character Register 3            */
+#define CD186x_SCHR4     0x0c    /* Special Character Register 4            */
+#define CD186x_MCOR1     0x10    /* Modem Change Option 1 Register          */
+#define CD186x_MCOR2     0x11    /* Modem Change Option 2 Register          */
+#define CD186x_MCR       0x12    /* Modem Change Register                   */
+#define CD186x_RTPR      0x18    /* Receive Timeout Period Register         */
+#define CD186x_MSVR      0x28    /* Modem Signal Value Register             */
+#define CD186x_MSVRTS    0x29    /* Modem Signal Value Register             */
+#define CD186x_MSVDTR    0x2a    /* Modem Signal Value Register             */
+#define CD186x_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
+#define CD186x_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
+#define CD186x_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
+#define CD186x_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
+
+
+/* Global Interrupt Vector Register (R/W) */
+
+#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
+#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
+#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
+#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
+#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
+
+
+/* Global Interrupt Channel Register (R/W) */
+ 
+#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
+#define GICR_CHAN_OFF   2       /* Channel Number shift                    */
+
+
+/* Channel Address Register (R/W) */
+
+#define CAR_CHAN        0x07    /* Channel Number Mask                     */
+#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
+
+
+/* Receive Character Status Register (R/O) */
+
+#define RCSR_TOUT       0x80    /* Rx Timeout                              */
+#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
+#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
+#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
+#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
+#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
+#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
+#define RCSR_BREAK      0x08    /* Break has been detected                 */
+#define RCSR_PE         0x04    /* Parity Error                            */
+#define RCSR_FE         0x02    /* Frame Error                             */
+#define RCSR_OE         0x01    /* Overrun Error                           */
+
+
+/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
+
+#define CCR_HARDRESET   0x81    /* Reset the chip                          */
+
+#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
+
+#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
+#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
+#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
+
+#define CCR_SSCH1       0x21    /* Send Special Character 1                */
+
+#define CCR_SSCH2       0x22    /* Send Special Character 2                */
+
+#define CCR_SSCH3       0x23    /* Send Special Character 3                */
+
+#define CCR_SSCH4       0x24    /* Send Special Character 4                */
+
+#define CCR_TXEN        0x18    /* Enable Transmitter                      */
+#define CCR_RXEN        0x12    /* Enable Receiver                         */
+
+#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
+#define CCR_RXDIS       0x11    /* Disable Receiver                        */
+
+
+/* Interrupt Enable Register (R/W) */
+
+#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
+#define IER_CD          0x40    /* Enable interrupt on CD change           */
+#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
+#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
+#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
+#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
+#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
+#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
+
+
+/* Channel Option Register 1 (R/W) */
+
+#define COR1_ODDP       0x80    /* Odd Parity                              */
+#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
+#define  COR1_NOPAR      0x00   /* No Parity                               */
+#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
+#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
+#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
+#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
+#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
+#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
+#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
+#define COR1_CHARLEN    0x03    /* Character Length                        */
+#define  COR1_5BITS      0x00   /* 5 bits                                  */
+#define  COR1_6BITS      0x01   /* 6 bits                                  */
+#define  COR1_7BITS      0x02   /* 7 bits                                  */
+#define  COR1_8BITS      0x03   /* 8 bits                                  */
+
+
+/* Channel Option Register 2 (R/W) */
+
+#define COR2_IXM        0x80    /* Implied XON mode                        */
+#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
+#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
+#define COR2_LLM        0x10    /* Local Loopback Mode                     */
+#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
+#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
+#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
+#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
+
+
+/* Channel Option Register 3 (R/W) */
+
+#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
+#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
+#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
+#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
+#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
+
+
+/* Channel Control Status Register (R/O) */
+
+#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
+#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
+#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
+#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
+#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
+#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
+
+
+/* Modem Change Option Register 1 (R/W) */
+
+#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
+#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
+#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
+#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
+#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
+
+
+/* Modem Change Option Register 2 (R/W) */
+
+#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
+#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
+#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
+
+/* Modem Change Register (R/W) */
+
+#define MCR_DSRCHG      0x80    /* DSR Changed                             */
+#define MCR_CDCHG       0x40    /* CD Changed                              */
+#define MCR_CTSCHG      0x20    /* CTS Changed                             */
+
+
+/* Modem Signal Value Register (R/W) */
+
+#define MSVR_DSR        0x80    /* Current state of DSR input              */
+#define MSVR_CD         0x40    /* Current state of CD input               */
+#define MSVR_CTS        0x20    /* Current state of CTS input              */
+#define MSVR_DTR        0x02    /* Current state of DTR output             */
+#define MSVR_RTS        0x01    /* Current state of RTS output             */
+
+
+/* Escape characters */
+
+#define CD186x_C_ESC     0x00    /* Escape character                        */
+#define CD186x_C_SBRK    0x81    /* Start sending BREAK                     */
+#define CD186x_C_DELAY   0x82    /* Delay output                            */
+#define CD186x_C_EBRK    0x83    /* Stop sending BREAK                      */
+
+#define SRSR_RREQint     0x10    /* This chip wants "rec" serviced          */
+#define SRSR_TREQint     0x04    /* This chip wants "transmit" serviced     */
+#define SRSR_MREQint     0x01    /* This chip wants "mdm change" serviced   */
+
+
+
+#define SRCR_PKGTYPE    0x80
+#define SRCR_REGACKEN   0x40
+#define SRCR_DAISYEN    0x20
+#define SRCR_GLOBPRI    0x10
+#define SRCR_UNFAIR     0x08
+#define SRCR_AUTOPRI    0x02
+#define SRCR_PRISEL     0x01
+
+
diff --git a/drivers/staging/tty/digi1.h b/drivers/staging/tty/digi1.h
new file mode 100644
index 0000000..94d4eab
--- /dev/null
+++ b/drivers/staging/tty/digi1.h
@@ -0,0 +1,100 @@
+/*          Definitions for DigiBoard ditty(1) command.                 */
+
+#if !defined(TIOCMODG)
+#define	TIOCMODG	(('d'<<8) | 250)	/* get modem ctrl state	*/
+#define	TIOCMODS	(('d'<<8) | 251)	/* set modem ctrl state	*/
+#endif
+
+#if !defined(TIOCMSET)
+#define	TIOCMSET	(('d'<<8) | 252)	/* set modem ctrl state	*/
+#define	TIOCMGET	(('d'<<8) | 253)	/* set modem ctrl state	*/
+#endif
+
+#if !defined(TIOCMBIC)
+#define	TIOCMBIC	(('d'<<8) | 254)	/* set modem ctrl state */
+#define	TIOCMBIS	(('d'<<8) | 255)	/* set modem ctrl state */
+#endif
+
+#if !defined(TIOCSDTR)
+#define	TIOCSDTR	(('e'<<8) | 0)		/* set DTR		*/
+#define	TIOCCDTR	(('e'<<8) | 1)		/* clear DTR		*/
+#endif
+
+/************************************************************************
+ * Ioctl command arguments for DIGI parameters.
+ ************************************************************************/
+#define DIGI_GETA	(('e'<<8) | 94)		/* Read params		*/
+
+#define DIGI_SETA	(('e'<<8) | 95)		/* Set params		*/
+#define DIGI_SETAW	(('e'<<8) | 96)		/* Drain & set params	*/
+#define DIGI_SETAF	(('e'<<8) | 97)		/* Drain, flush & set params */
+
+#define	DIGI_GETFLOW	(('e'<<8) | 99)		/* Get startc/stopc flow */
+						/* control characters 	 */
+#define	DIGI_SETFLOW	(('e'<<8) | 100)	/* Set startc/stopc flow */
+						/* control characters	 */
+#define	DIGI_GETAFLOW	(('e'<<8) | 101)	/* Get Aux. startc/stopc */
+						/* flow control chars 	 */
+#define	DIGI_SETAFLOW	(('e'<<8) | 102)	/* Set Aux. startc/stopc */
+						/* flow control chars	 */
+
+#define	DIGI_GETINFO	(('e'<<8) | 103)	/* Fill in digi_info */
+#define	DIGI_POLLER	(('e'<<8) | 104)	/* Turn on/off poller */
+#define	DIGI_INIT	(('e'<<8) | 105)	/* Allow things to run. */
+
+struct	digiflow_struct 
+{
+	unsigned char	startc;				/* flow cntl start char	*/
+	unsigned char	stopc;				/* flow cntl stop char	*/
+};
+
+typedef struct digiflow_struct digiflow_t;
+
+
+/************************************************************************
+ * Values for digi_flags 
+ ************************************************************************/
+#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
+#define DIGI_FAST	0x0002		/* Fast baud rates		*/
+#define RTSPACE		0x0004		/* RTS input flow control	*/
+#define CTSPACE		0x0008		/* CTS output flow control	*/
+#define DSRPACE		0x0010		/* DSR output flow control	*/
+#define DCDPACE		0x0020		/* DCD output flow control	*/
+#define DTRPACE		0x0040		/* DTR input flow control	*/
+#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
+#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
+#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
+
+
+/************************************************************************
+ * Values for digiDload
+ ************************************************************************/
+#define NORMAL  0
+#define PCI_CTL 1
+
+#define SIZE8  0
+#define SIZE16 1
+#define SIZE32 2
+
+/************************************************************************
+ * Structure used with ioctl commands for DIGI parameters.
+ ************************************************************************/
+struct digi_struct 
+{
+	unsigned short	digi_flags;		/* Flags (see above)	*/
+};
+
+typedef struct digi_struct digi_t;
+
+struct digi_info 
+{
+	unsigned long board;        /* Which board is this ? */
+	unsigned char status;       /* Alive or dead */
+	unsigned char type;         /* see epca.h */
+	unsigned char subtype;      /* For future XEM, XR, etc ... */
+	unsigned short numports;    /* Number of ports configured */
+	unsigned char *port;        /* I/O Address */
+	unsigned char *membase;     /* DPR Address */
+	unsigned char *version;     /* For future ... */
+	unsigned short windowData;  /* For future ... */
+} ;
diff --git a/drivers/staging/tty/digiFep1.h b/drivers/staging/tty/digiFep1.h
new file mode 100644
index 0000000..3c1f192
--- /dev/null
+++ b/drivers/staging/tty/digiFep1.h
@@ -0,0 +1,136 @@
+
+#define CSTART       0x400L
+#define CMAX         0x800L
+#define ISTART       0x800L
+#define IMAX         0xC00L
+#define CIN          0xD10L
+#define GLOBAL       0xD10L
+#define EIN          0xD18L
+#define FEPSTAT      0xD20L
+#define CHANSTRUCT   0x1000L
+#define RXTXBUF      0x4000L
+
+
+struct global_data 
+{
+	u16 cin;
+	u16 cout;
+	u16 cstart;
+	u16 cmax;
+	u16 ein;
+	u16 eout;
+	u16 istart;
+	u16 imax;
+};
+
+
+struct board_chan 
+{
+	u32 filler1;
+	u32 filler2;
+	u16 tseg;
+	u16 tin;
+	u16 tout;
+	u16 tmax;
+
+	u16 rseg;
+	u16 rin;
+	u16 rout;
+	u16 rmax;
+
+	u16 tlow;
+	u16 rlow;
+	u16 rhigh;
+	u16 incr;
+
+	u16 etime;
+	u16 edelay;
+	unchar *dev;
+
+	u16 iflag;
+	u16 oflag;
+	u16 cflag;
+	u16 gmask;
+
+	u16 col;
+	u16 delay;
+	u16 imask;
+	u16 tflush;
+
+	u32 filler3;
+	u32 filler4;
+	u32 filler5;
+	u32 filler6;
+
+	u8 num;
+	u8 ract;
+	u8 bstat;
+	u8 tbusy;
+	u8 iempty;
+	u8 ilow;
+	u8 idata;
+	u8 eflag;
+
+	u8 tflag;
+	u8 rflag;
+	u8 xmask;
+	u8 xval;
+	u8 mstat;
+	u8 mchange;
+	u8 mint;
+	u8 lstat;
+
+	u8 mtran;
+	u8 orun;
+	u8 startca;
+	u8 stopca;
+	u8 startc;
+	u8 stopc;
+	u8 vnext;
+	u8 hflow;
+
+	u8 fillc;
+	u8 ochar;
+	u8 omask;
+
+	u8 filler7;
+	u8 filler8[28];
+}; 
+
+
+#define SRXLWATER      0xE0
+#define SRXHWATER      0xE1
+#define STOUT          0xE2
+#define PAUSETX        0xE3
+#define RESUMETX       0xE4
+#define SAUXONOFFC     0xE6
+#define SENDBREAK      0xE8
+#define SETMODEM       0xE9
+#define SETIFLAGS      0xEA
+#define SONOFFC        0xEB
+#define STXLWATER      0xEC
+#define PAUSERX        0xEE
+#define RESUMERX       0xEF
+#define SETBUFFER      0xF2
+#define SETCOOKED      0xF3
+#define SETHFLOW       0xF4
+#define SETCTRLFLAGS   0xF5
+#define SETVNEXT       0xF6
+
+
+
+#define BREAK_IND        0x01
+#define LOWTX_IND        0x02
+#define EMPTYTX_IND      0x04
+#define DATA_IND         0x08
+#define MODEMCHG_IND     0x20
+
+#define FEP_HUPCL  0002000
+#if 0
+#define RTS   0x02
+#define CD    0x08
+#define DSR   0x10
+#define CTS   0x20
+#define RI    0x40
+#define DTR   0x80
+#endif
diff --git a/drivers/staging/tty/digiPCI.h b/drivers/staging/tty/digiPCI.h
new file mode 100644
index 0000000..6ca7819
--- /dev/null
+++ b/drivers/staging/tty/digiPCI.h
@@ -0,0 +1,42 @@
+/*************************************************************************
+ * Defines and structure definitions for PCI BIOS Interface 
+ *************************************************************************/
+#define	PCIMAX  32		/* maximum number of PCI boards */
+
+
+#define	PCI_VENDOR_DIGI		0x114F
+#define	PCI_DEVICE_EPC		0x0002
+#define	PCI_DEVICE_RIGHTSWITCH 0x0003  /* For testing */
+#define	PCI_DEVICE_XEM		0x0004
+#define	PCI_DEVICE_XR		0x0005
+#define	PCI_DEVICE_CX		0x0006
+#define	PCI_DEVICE_XRJ		0x0009   /* Jupiter boards with */
+#define	PCI_DEVICE_EPCJ		0x000a   /* PLX 9060 chip for PCI  */
+
+
+/*
+ * On the PCI boards, there is no IO space allocated 
+ * The I/O registers will be in the first 3 bytes of the   
+ * upper 2MB of the 4MB memory space.  The board memory 
+ * will be mapped into the low 2MB of the 4MB memory space 
+ */
+
+/* Potential location of PCI Bios from E0000 to FFFFF*/
+#define PCI_BIOS_SIZE		0x00020000	
+
+/* Size of Memory and I/O for PCI (4MB) */
+#define PCI_RAM_SIZE		0x00400000	
+
+/* Size of Memory (2MB) */
+#define PCI_MEM_SIZE		0x00200000	
+
+/* Offset of I/0 in Memory (2MB) */
+#define PCI_IO_OFFSET 		0x00200000	
+
+#define MEMOUTB(basemem, pnum, setmemval)  *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval)
+#define MEMINB(basemem, pnum)  *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum ))   /* for PCI I/O */
+
+
+
+
+
diff --git a/drivers/staging/tty/epca.c b/drivers/staging/tty/epca.c
new file mode 100644
index 0000000..7ad3638
--- /dev/null
+++ b/drivers/staging/tty/epca.c
@@ -0,0 +1,2784 @@
+/*
+	Copyright (C) 1996  Digi International.
+
+	For technical support please email digiLinux@dgii.com or
+	call Digi tech support at (612) 912-3456
+
+	** This driver is no longer supported by Digi **
+
+	Much of this design and code came from epca.c which was
+	copyright (C) 1994, 1995 Troy De Jongh, and subsquently
+	modified by David Nugent, Christoph Lameter, Mike McLagan.
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/* See README.epca for change history --DAT*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/pci.h>
+#include "digiPCI.h"
+
+
+#include "digi1.h"
+#include "digiFep1.h"
+#include "epca.h"
+#include "epcaconfig.h"
+
+#define VERSION            "1.3.0.1-LK2.6"
+
+/* This major needs to be submitted to Linux to join the majors list */
+#define DIGIINFOMAJOR       35  /* For Digi specific ioctl */
+
+
+#define MAXCARDS 7
+#define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
+
+#define PFX "epca: "
+
+static int nbdevs, num_cards, liloconfig;
+static int digi_poller_inhibited = 1 ;
+
+static int setup_error_code;
+static int invalid_lilo_config;
+
+/*
+ * The ISA boards do window flipping into the same spaces so its only sane with
+ * a single lock. It's still pretty efficient. This lock guards the hardware
+ * and the tty_port lock guards the kernel side stuff like use counts. Take
+ * this lock inside the port lock if you must take both.
+ */
+static DEFINE_SPINLOCK(epca_lock);
+
+/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
+   to 7 below. */
+static struct board_info boards[MAXBOARDS];
+
+static struct tty_driver *pc_driver;
+static struct tty_driver *pc_info;
+
+/* ------------------ Begin Digi specific structures -------------------- */
+
+/*
+ * digi_channels represents an array of structures that keep track of each
+ * channel of the Digi product. Information such as transmit and receive
+ * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored
+ * here. This structure is NOT used to overlay the cards physical channel
+ * structure.
+ */
+static struct channel digi_channels[MAX_ALLOC];
+
+/*
+ * card_ptr is an array used to hold the address of the first channel structure
+ * of each card. This array will hold the addresses of various channels located
+ * in digi_channels.
+ */
+static struct channel *card_ptr[MAXCARDS];
+
+static struct timer_list epca_timer;
+
+/*
+ * Begin generic memory functions. These functions will be alias (point at)
+ * more specific functions dependent on the board being configured.
+ */
+static void memwinon(struct board_info *b, unsigned int win);
+static void memwinoff(struct board_info *b, unsigned int win);
+static void globalwinon(struct channel *ch);
+static void rxwinon(struct channel *ch);
+static void txwinon(struct channel *ch);
+static void memoff(struct channel *ch);
+static void assertgwinon(struct channel *ch);
+static void assertmemoff(struct channel *ch);
+
+/* ---- Begin more 'specific' memory functions for cx_like products --- */
+
+static void pcxem_memwinon(struct board_info *b, unsigned int win);
+static void pcxem_memwinoff(struct board_info *b, unsigned int win);
+static void pcxem_globalwinon(struct channel *ch);
+static void pcxem_rxwinon(struct channel *ch);
+static void pcxem_txwinon(struct channel *ch);
+static void pcxem_memoff(struct channel *ch);
+
+/* ------ Begin more 'specific' memory functions for the pcxe ------- */
+
+static void pcxe_memwinon(struct board_info *b, unsigned int win);
+static void pcxe_memwinoff(struct board_info *b, unsigned int win);
+static void pcxe_globalwinon(struct channel *ch);
+static void pcxe_rxwinon(struct channel *ch);
+static void pcxe_txwinon(struct channel *ch);
+static void pcxe_memoff(struct channel *ch);
+
+/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
+/* Note : pc64xe and pcxi share the same windowing routines */
+
+static void pcxi_memwinon(struct board_info *b, unsigned int win);
+static void pcxi_memwinoff(struct board_info *b, unsigned int win);
+static void pcxi_globalwinon(struct channel *ch);
+static void pcxi_rxwinon(struct channel *ch);
+static void pcxi_txwinon(struct channel *ch);
+static void pcxi_memoff(struct channel *ch);
+
+/* - Begin 'specific' do nothing memory functions needed for some cards - */
+
+static void dummy_memwinon(struct board_info *b, unsigned int win);
+static void dummy_memwinoff(struct board_info *b, unsigned int win);
+static void dummy_globalwinon(struct channel *ch);
+static void dummy_rxwinon(struct channel *ch);
+static void dummy_txwinon(struct channel *ch);
+static void dummy_memoff(struct channel *ch);
+static void dummy_assertgwinon(struct channel *ch);
+static void dummy_assertmemoff(struct channel *ch);
+
+static struct channel *verifyChannel(struct tty_struct *);
+static void pc_sched_event(struct channel *, int);
+static void epca_error(int, char *);
+static void pc_close(struct tty_struct *, struct file *);
+static void shutdown(struct channel *, struct tty_struct *tty);
+static void pc_hangup(struct tty_struct *);
+static int pc_write_room(struct tty_struct *);
+static int pc_chars_in_buffer(struct tty_struct *);
+static void pc_flush_buffer(struct tty_struct *);
+static void pc_flush_chars(struct tty_struct *);
+static int pc_open(struct tty_struct *, struct file *);
+static void post_fep_init(unsigned int crd);
+static void epcapoll(unsigned long);
+static void doevent(int);
+static void fepcmd(struct channel *, int, int, int, int, int);
+static unsigned termios2digi_h(struct channel *ch, unsigned);
+static unsigned termios2digi_i(struct channel *ch, unsigned);
+static unsigned termios2digi_c(struct channel *ch, unsigned);
+static void epcaparam(struct tty_struct *, struct channel *);
+static void receive_data(struct channel *, struct tty_struct *tty);
+static int pc_ioctl(struct tty_struct *,
+			unsigned int, unsigned long);
+static int info_ioctl(struct tty_struct *,
+			unsigned int, unsigned long);
+static void pc_set_termios(struct tty_struct *, struct ktermios *);
+static void do_softint(struct work_struct *work);
+static void pc_stop(struct tty_struct *);
+static void pc_start(struct tty_struct *);
+static void pc_throttle(struct tty_struct *tty);
+static void pc_unthrottle(struct tty_struct *tty);
+static int pc_send_break(struct tty_struct *tty, int msec);
+static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
+
+static int pc_write(struct tty_struct *, const unsigned char *, int);
+static int pc_init(void);
+static int init_PCI(void);
+
+/*
+ * Table of functions for each board to handle memory. Mantaining parallelism
+ * is a *very* good idea here. The idea is for the runtime code to blindly call
+ * these functions, not knowing/caring about the underlying hardware. This
+ * stuff should contain no conditionals; if more functionality is needed a
+ * different entry should be established. These calls are the interface calls
+ * and are the only functions that should be accessed. Anyone caught making
+ * direct calls deserves what they get.
+ */
+static void memwinon(struct board_info *b, unsigned int win)
+{
+	b->memwinon(b, win);
+}
+
+static void memwinoff(struct board_info *b, unsigned int win)
+{
+	b->memwinoff(b, win);
+}
+
+static void globalwinon(struct channel *ch)
+{
+	ch->board->globalwinon(ch);
+}
+
+static void rxwinon(struct channel *ch)
+{
+	ch->board->rxwinon(ch);
+}
+
+static void txwinon(struct channel *ch)
+{
+	ch->board->txwinon(ch);
+}
+
+static void memoff(struct channel *ch)
+{
+	ch->board->memoff(ch);
+}
+static void assertgwinon(struct channel *ch)
+{
+	ch->board->assertgwinon(ch);
+}
+
+static void assertmemoff(struct channel *ch)
+{
+	ch->board->assertmemoff(ch);
+}
+
+/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
+static void pcxem_memwinon(struct board_info *b, unsigned int win)
+{
+	outb_p(FEPWIN | win, b->port + 1);
+}
+
+static void pcxem_memwinoff(struct board_info *b, unsigned int win)
+{
+	outb_p(0, b->port + 1);
+}
+
+static void pcxem_globalwinon(struct channel *ch)
+{
+	outb_p(FEPWIN, (int)ch->board->port + 1);
+}
+
+static void pcxem_rxwinon(struct channel *ch)
+{
+	outb_p(ch->rxwin, (int)ch->board->port + 1);
+}
+
+static void pcxem_txwinon(struct channel *ch)
+{
+	outb_p(ch->txwin, (int)ch->board->port + 1);
+}
+
+static void pcxem_memoff(struct channel *ch)
+{
+	outb_p(0, (int)ch->board->port + 1);
+}
+
+/* ----------------- Begin pcxe memory window stuff ------------------ */
+static void pcxe_memwinon(struct board_info *b, unsigned int win)
+{
+	outb_p(FEPWIN | win, b->port + 1);
+}
+
+static void pcxe_memwinoff(struct board_info *b, unsigned int win)
+{
+	outb_p(inb(b->port) & ~FEPMEM, b->port + 1);
+	outb_p(0, b->port + 1);
+}
+
+static void pcxe_globalwinon(struct channel *ch)
+{
+	outb_p(FEPWIN, (int)ch->board->port + 1);
+}
+
+static void pcxe_rxwinon(struct channel *ch)
+{
+	outb_p(ch->rxwin, (int)ch->board->port + 1);
+}
+
+static void pcxe_txwinon(struct channel *ch)
+{
+	outb_p(ch->txwin, (int)ch->board->port + 1);
+}
+
+static void pcxe_memoff(struct channel *ch)
+{
+	outb_p(0, (int)ch->board->port);
+	outb_p(0, (int)ch->board->port + 1);
+}
+
+/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
+static void pcxi_memwinon(struct board_info *b, unsigned int win)
+{
+	outb_p(inb(b->port) | FEPMEM, b->port);
+}
+
+static void pcxi_memwinoff(struct board_info *b, unsigned int win)
+{
+	outb_p(inb(b->port) & ~FEPMEM, b->port);
+}
+
+static void pcxi_globalwinon(struct channel *ch)
+{
+	outb_p(FEPMEM, ch->board->port);
+}
+
+static void pcxi_rxwinon(struct channel *ch)
+{
+	outb_p(FEPMEM, ch->board->port);
+}
+
+static void pcxi_txwinon(struct channel *ch)
+{
+	outb_p(FEPMEM, ch->board->port);
+}
+
+static void pcxi_memoff(struct channel *ch)
+{
+	outb_p(0, ch->board->port);
+}
+
+static void pcxi_assertgwinon(struct channel *ch)
+{
+	epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
+}
+
+static void pcxi_assertmemoff(struct channel *ch)
+{
+	epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
+}
+
+/*
+ * Not all of the cards need specific memory windowing routines. Some cards
+ * (Such as PCI) needs no windowing routines at all. We provide these do
+ * nothing routines so that the same code base can be used. The driver will
+ * ALWAYS call a windowing routine if it thinks it needs to; regardless of the
+ * card. However, dependent on the card the routine may or may not do anything.
+ */
+static void dummy_memwinon(struct board_info *b, unsigned int win)
+{
+}
+
+static void dummy_memwinoff(struct board_info *b, unsigned int win)
+{
+}
+
+static void dummy_globalwinon(struct channel *ch)
+{
+}
+
+static void dummy_rxwinon(struct channel *ch)
+{
+}
+
+static void dummy_txwinon(struct channel *ch)
+{
+}
+
+static void dummy_memoff(struct channel *ch)
+{
+}
+
+static void dummy_assertgwinon(struct channel *ch)
+{
+}
+
+static void dummy_assertmemoff(struct channel *ch)
+{
+}
+
+static struct channel *verifyChannel(struct tty_struct *tty)
+{
+	/*
+	 * This routine basically provides a sanity check. It insures that the
+	 * channel returned is within the proper range of addresses as well as
+	 * properly initialized. If some bogus info gets passed in
+	 * through tty->driver_data this should catch it.
+	 */
+	if (tty) {
+		struct channel *ch = tty->driver_data;
+		if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
+			if (ch->magic == EPCA_MAGIC)
+				return ch;
+		}
+	}
+	return NULL;
+}
+
+static void pc_sched_event(struct channel *ch, int event)
+{
+	/*
+	 * We call this to schedule interrupt processing on some event. The
+	 * kernel sees our request and calls the related routine in OUR driver.
+	 */
+	ch->event |= 1 << event;
+	schedule_work(&ch->tqueue);
+}
+
+static void epca_error(int line, char *msg)
+{
+	printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
+}
+
+static void pc_close(struct tty_struct *tty, struct file *filp)
+{
+	struct channel *ch;
+	struct tty_port *port;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch == NULL)
+		return;
+	port = &ch->port;
+
+	if (tty_port_close_start(port, tty, filp) == 0)
+		return;
+
+	pc_flush_buffer(tty);
+	shutdown(ch, tty);
+
+	tty_port_close_end(port, tty);
+	ch->event = 0;	/* FIXME: review ch->event locking */
+	tty_port_tty_set(port, NULL);
+}
+
+static void shutdown(struct channel *ch, struct tty_struct *tty)
+{
+	unsigned long flags;
+	struct board_chan __iomem *bc;
+	struct tty_port *port = &ch->port;
+
+	if (!(port->flags & ASYNC_INITIALIZED))
+		return;
+
+	spin_lock_irqsave(&epca_lock, flags);
+
+	globalwinon(ch);
+	bc = ch->brdchan;
+
+	/*
+	 * In order for an event to be generated on the receipt of data the
+	 * idata flag must be set. Since we are shutting down, this is not
+	 * necessary clear this flag.
+	 */
+	if (bc)
+		writeb(0, &bc->idata);
+
+	/* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
+	if (tty->termios->c_cflag & HUPCL)  {
+		ch->omodem &= ~(ch->m_rts | ch->m_dtr);
+		fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
+	}
+	memoff(ch);
+
+	/*
+	 * The channel has officialy been closed. The next time it is opened it
+	 * will have to reinitialized. Set a flag to indicate this.
+	 */
+	/* Prevent future Digi programmed interrupts from coming active */
+	port->flags &= ~ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&epca_lock, flags);
+}
+
+static void pc_hangup(struct tty_struct *tty)
+{
+	struct channel *ch;
+
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		pc_flush_buffer(tty);
+		tty_ldisc_flush(tty);
+		shutdown(ch, tty);
+
+		ch->event = 0;	/* FIXME: review locking of ch->event */
+		tty_port_hangup(&ch->port);
+	}
+}
+
+static int pc_write(struct tty_struct *tty,
+			const unsigned char *buf, int bytesAvailable)
+{
+	unsigned int head, tail;
+	int dataLen;
+	int size;
+	int amountCopied;
+	struct channel *ch;
+	unsigned long flags;
+	int remain;
+	struct board_chan __iomem *bc;
+
+	/*
+	 * pc_write is primarily called directly by the kernel routine
+	 * tty_write (Though it can also be called by put_char) found in
+	 * tty_io.c. pc_write is passed a line discipline buffer where the data
+	 * to be written out is stored. The line discipline implementation
+	 * itself is done at the kernel level and is not brought into the
+	 * driver.
+	 */
+
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch == NULL)
+		return 0;
+
+	/* Make a pointer to the channel data structure found on the board. */
+	bc   = ch->brdchan;
+	size = ch->txbufsize;
+	amountCopied = 0;
+
+	spin_lock_irqsave(&epca_lock, flags);
+	globalwinon(ch);
+
+	head = readw(&bc->tin) & (size - 1);
+	tail = readw(&bc->tout);
+
+	if (tail != readw(&bc->tout))
+		tail = readw(&bc->tout);
+	tail &= (size - 1);
+
+	if (head >= tail) {
+		/* head has not wrapped */
+		/*
+		 * remain (much like dataLen above) represents the total amount
+		 * of space available on the card for data. Here dataLen
+		 * represents the space existing between the head pointer and
+		 * the end of buffer. This is important because a memcpy cannot
+		 * be told to automatically wrap around when it hits the buffer
+		 * end.
+		 */
+		dataLen = size - head;
+		remain = size - (head - tail) - 1;
+	} else {
+		/* head has wrapped around */
+		remain = tail - head - 1;
+		dataLen = remain;
+	}
+	/*
+	 * Check the space on the card. If we have more data than space; reduce
+	 * the amount of data to fit the space.
+	 */
+	bytesAvailable = min(remain, bytesAvailable);
+	txwinon(ch);
+	while (bytesAvailable > 0) {
+		/* there is data to copy onto card */
+
+		/*
+		 * If head is not wrapped, the below will make sure the first
+		 * data copy fills to the end of card buffer.
+		 */
+		dataLen = min(bytesAvailable, dataLen);
+		memcpy_toio(ch->txptr + head, buf, dataLen);
+		buf += dataLen;
+		head += dataLen;
+		amountCopied += dataLen;
+		bytesAvailable -= dataLen;
+
+		if (head >= size) {
+			head = 0;
+			dataLen = tail;
+		}
+	}
+	ch->statusflags |= TXBUSY;
+	globalwinon(ch);
+	writew(head, &bc->tin);
+
+	if ((ch->statusflags & LOWWAIT) == 0)  {
+		ch->statusflags |= LOWWAIT;
+		writeb(1, &bc->ilow);
+	}
+	memoff(ch);
+	spin_unlock_irqrestore(&epca_lock, flags);
+	return amountCopied;
+}
+
+static int pc_write_room(struct tty_struct *tty)
+{
+	int remain = 0;
+	struct channel *ch;
+	unsigned long flags;
+	unsigned int head, tail;
+	struct board_chan __iomem *bc;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		spin_lock_irqsave(&epca_lock, flags);
+		globalwinon(ch);
+
+		bc   = ch->brdchan;
+		head = readw(&bc->tin) & (ch->txbufsize - 1);
+		tail = readw(&bc->tout);
+
+		if (tail != readw(&bc->tout))
+			tail = readw(&bc->tout);
+		/* Wrap tail if necessary */
+		tail &= (ch->txbufsize - 1);
+		remain = tail - head - 1;
+		if (remain < 0)
+			remain += ch->txbufsize;
+
+		if (remain && (ch->statusflags & LOWWAIT) == 0) {
+			ch->statusflags |= LOWWAIT;
+			writeb(1, &bc->ilow);
+		}
+		memoff(ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+	/* Return how much room is left on card */
+	return remain;
+}
+
+static int pc_chars_in_buffer(struct tty_struct *tty)
+{
+	int chars;
+	unsigned int ctail, head, tail;
+	int remain;
+	unsigned long flags;
+	struct channel *ch;
+	struct board_chan __iomem *bc;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch == NULL)
+		return 0;
+
+	spin_lock_irqsave(&epca_lock, flags);
+	globalwinon(ch);
+
+	bc = ch->brdchan;
+	tail = readw(&bc->tout);
+	head = readw(&bc->tin);
+	ctail = readw(&ch->mailbox->cout);
+
+	if (tail == head && readw(&ch->mailbox->cin) == ctail &&
+						readb(&bc->tbusy) == 0)
+		chars = 0;
+	else  { /* Begin if some space on the card has been used */
+		head = readw(&bc->tin) & (ch->txbufsize - 1);
+		tail &= (ch->txbufsize - 1);
+		/*
+		 * The logic here is basically opposite of the above
+		 * pc_write_room here we are finding the amount of bytes in the
+		 * buffer filled. Not the amount of bytes empty.
+		 */
+		remain = tail - head - 1;
+		if (remain < 0)
+			remain += ch->txbufsize;
+		chars = (int)(ch->txbufsize - remain);
+		/*
+		 * Make it possible to wakeup anything waiting for output in
+		 * tty_ioctl.c, etc.
+		 *
+		 * If not already set. Setup an event to indicate when the
+		 * transmit buffer empties.
+		 */
+		if (!(ch->statusflags & EMPTYWAIT))
+			setup_empty_event(tty, ch);
+	} /* End if some space on the card has been used */
+	memoff(ch);
+	spin_unlock_irqrestore(&epca_lock, flags);
+	/* Return number of characters residing on card. */
+	return chars;
+}
+
+static void pc_flush_buffer(struct tty_struct *tty)
+{
+	unsigned int tail;
+	unsigned long flags;
+	struct channel *ch;
+	struct board_chan __iomem *bc;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch == NULL)
+		return;
+
+	spin_lock_irqsave(&epca_lock, flags);
+	globalwinon(ch);
+	bc   = ch->brdchan;
+	tail = readw(&bc->tout);
+	/* Have FEP move tout pointer; effectively flushing transmit buffer */
+	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
+	memoff(ch);
+	spin_unlock_irqrestore(&epca_lock, flags);
+	tty_wakeup(tty);
+}
+
+static void pc_flush_chars(struct tty_struct *tty)
+{
+	struct channel *ch;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		unsigned long flags;
+		spin_lock_irqsave(&epca_lock, flags);
+		/*
+		 * If not already set and the transmitter is busy setup an
+		 * event to indicate when the transmit empties.
+		 */
+		if ((ch->statusflags & TXBUSY) &&
+				!(ch->statusflags & EMPTYWAIT))
+			setup_empty_event(tty, ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+}
+
+static int epca_carrier_raised(struct tty_port *port)
+{
+	struct channel *ch = container_of(port, struct channel, port);
+	if (ch->imodem & ch->dcd)
+		return 1;
+	return 0;
+}
+
+static void epca_dtr_rts(struct tty_port *port, int onoff)
+{
+}
+
+static int pc_open(struct tty_struct *tty, struct file *filp)
+{
+	struct channel *ch;
+	struct tty_port *port;
+	unsigned long flags;
+	int line, retval, boardnum;
+	struct board_chan __iomem *bc;
+	unsigned int head;
+
+	line = tty->index;
+	if (line < 0 || line >= nbdevs)
+		return -ENODEV;
+
+	ch = &digi_channels[line];
+	port = &ch->port;
+	boardnum = ch->boardnum;
+
+	/* Check status of board configured in system.  */
+
+	/*
+	 * I check to see if the epca_setup routine detected a user error. It
+	 * might be better to put this in pc_init, but for the moment it goes
+	 * here.
+	 */
+	if (invalid_lilo_config) {
+		if (setup_error_code & INVALID_BOARD_TYPE)
+			printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
+		if (setup_error_code & INVALID_NUM_PORTS)
+			printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
+		if (setup_error_code & INVALID_MEM_BASE)
+			printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
+		if (setup_error_code & INVALID_PORT_BASE)
+			printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
+		if (setup_error_code & INVALID_BOARD_STATUS)
+			printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
+		if (setup_error_code & INVALID_ALTPIN)
+			printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
+		tty->driver_data = NULL;   /* Mark this device as 'down' */
+		return -ENODEV;
+	}
+	if (boardnum >= num_cards || boards[boardnum].status == DISABLED)  {
+		tty->driver_data = NULL;   /* Mark this device as 'down' */
+		return(-ENODEV);
+	}
+
+	bc = ch->brdchan;
+	if (bc == NULL) {
+		tty->driver_data = NULL;
+		return -ENODEV;
+	}
+
+	spin_lock_irqsave(&port->lock, flags);
+	/*
+	 * Every time a channel is opened, increment a counter. This is
+	 * necessary because we do not wish to flush and shutdown the channel
+	 * until the last app holding the channel open, closes it.
+	 */
+	port->count++;
+	/*
+	 * Set a kernel structures pointer to our local channel structure. This
+	 * way we can get to it when passed only a tty struct.
+	 */
+	tty->driver_data = ch;
+	port->tty = tty;
+	/*
+	 * If this is the first time the channel has been opened, initialize
+	 * the tty->termios struct otherwise let pc_close handle it.
+	 */
+	spin_lock(&epca_lock);
+	globalwinon(ch);
+	ch->statusflags = 0;
+
+	/* Save boards current modem status */
+	ch->imodem = readb(&bc->mstat);
+
+	/*
+	 * Set receive head and tail ptrs to each other. This indicates no data
+	 * available to read.
+	 */
+	head = readw(&bc->rin);
+	writew(head, &bc->rout);
+
+	/* Set the channels associated tty structure */
+
+	/*
+	 * The below routine generally sets up parity, baud, flow control
+	 * issues, etc.... It effect both control flags and input flags.
+	 */
+	epcaparam(tty, ch);
+	memoff(ch);
+	spin_unlock(&epca_lock);
+	port->flags |= ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	retval = tty_port_block_til_ready(port, tty, filp);
+	if (retval)
+		return retval;
+	/*
+	 * Set this again in case a hangup set it to zero while this open() was
+	 * waiting for the line...
+	 */
+	spin_lock_irqsave(&port->lock, flags);
+	port->tty = tty;
+	spin_lock(&epca_lock);
+	globalwinon(ch);
+	/* Enable Digi Data events */
+	writeb(1, &bc->idata);
+	memoff(ch);
+	spin_unlock(&epca_lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+	return 0;
+}
+
+static int __init epca_module_init(void)
+{
+	return pc_init();
+}
+module_init(epca_module_init);
+
+static struct pci_driver epca_driver;
+
+static void __exit epca_module_exit(void)
+{
+	int               count, crd;
+	struct board_info *bd;
+	struct channel    *ch;
+
+	del_timer_sync(&epca_timer);
+
+	if (tty_unregister_driver(pc_driver) ||
+				tty_unregister_driver(pc_info)) {
+		printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
+		return;
+	}
+	put_tty_driver(pc_driver);
+	put_tty_driver(pc_info);
+
+	for (crd = 0; crd < num_cards; crd++) {
+		bd = &boards[crd];
+		if (!bd) { /* sanity check */
+			printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
+			return;
+		}
+		ch = card_ptr[crd];
+		for (count = 0; count < bd->numports; count++, ch++) {
+			struct tty_struct *tty = tty_port_tty_get(&ch->port);
+			if (tty) {
+				tty_hangup(tty);
+				tty_kref_put(tty);
+			}
+		}
+	}
+	pci_unregister_driver(&epca_driver);
+}
+module_exit(epca_module_exit);
+
+static const struct tty_operations pc_ops = {
+	.open = pc_open,
+	.close = pc_close,
+	.write = pc_write,
+	.write_room = pc_write_room,
+	.flush_buffer = pc_flush_buffer,
+	.chars_in_buffer = pc_chars_in_buffer,
+	.flush_chars = pc_flush_chars,
+	.ioctl = pc_ioctl,
+	.set_termios = pc_set_termios,
+	.stop = pc_stop,
+	.start = pc_start,
+	.throttle = pc_throttle,
+	.unthrottle = pc_unthrottle,
+	.hangup = pc_hangup,
+	.break_ctl = pc_send_break
+};
+
+static const struct tty_port_operations epca_port_ops = {
+	.carrier_raised = epca_carrier_raised,
+	.dtr_rts = epca_dtr_rts,
+};
+
+static int info_open(struct tty_struct *tty, struct file *filp)
+{
+	return 0;
+}
+
+static const struct tty_operations info_ops = {
+	.open = info_open,
+	.ioctl = info_ioctl,
+};
+
+static int __init pc_init(void)
+{
+	int crd;
+	struct board_info *bd;
+	unsigned char board_id = 0;
+	int err = -ENOMEM;
+
+	int pci_boards_found, pci_count;
+
+	pci_count = 0;
+
+	pc_driver = alloc_tty_driver(MAX_ALLOC);
+	if (!pc_driver)
+		goto out1;
+
+	pc_info = alloc_tty_driver(MAX_ALLOC);
+	if (!pc_info)
+		goto out2;
+
+	/*
+	 * If epca_setup has not been ran by LILO set num_cards to defaults;
+	 * copy board structure defined by digiConfig into drivers board
+	 * structure. Note : If LILO has ran epca_setup then epca_setup will
+	 * handle defining num_cards as well as copying the data into the board
+	 * structure.
+	 */
+	if (!liloconfig) {
+		/* driver has been configured via. epcaconfig */
+		nbdevs = NBDEVS;
+		num_cards = NUMCARDS;
+		memcpy(&boards, &static_boards,
+		       sizeof(struct board_info) * NUMCARDS);
+	}
+
+	/*
+	 * Note : If lilo was used to configure the driver and the ignore
+	 * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards
+	 * will equal 0 at this point. This is okay; PCI cards will still be
+	 * picked up if detected.
+	 */
+
+	/*
+	 * Set up interrupt, we will worry about memory allocation in
+	 * post_fep_init.
+	 */
+	printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
+
+	/*
+	 * NOTE : This code assumes that the number of ports found in the
+	 * boards array is correct. This could be wrong if the card in question
+	 * is PCI (And therefore has no ports entry in the boards structure.)
+	 * The rest of the information will be valid for PCI because the
+	 * beginning of pc_init scans for PCI and determines i/o and base
+	 * memory addresses. I am not sure if it is possible to read the number
+	 * of ports supported by the card prior to it being booted (Since that
+	 * is the state it is in when pc_init is run). Because it is not
+	 * possible to query the number of supported ports until after the card
+	 * has booted; we are required to calculate the card_ptrs as the card
+	 * is initialized (Inside post_fep_init). The negative thing about this
+	 * approach is that digiDload's call to GET_INFO will have a bad port
+	 * value. (Since this is called prior to post_fep_init.)
+	 */
+	pci_boards_found = 0;
+	if (num_cards < MAXBOARDS)
+		pci_boards_found += init_PCI();
+	num_cards += pci_boards_found;
+
+	pc_driver->owner = THIS_MODULE;
+	pc_driver->name = "ttyD";
+	pc_driver->major = DIGI_MAJOR;
+	pc_driver->minor_start = 0;
+	pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	pc_driver->subtype = SERIAL_TYPE_NORMAL;
+	pc_driver->init_termios = tty_std_termios;
+	pc_driver->init_termios.c_iflag = 0;
+	pc_driver->init_termios.c_oflag = 0;
+	pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	pc_driver->init_termios.c_lflag = 0;
+	pc_driver->init_termios.c_ispeed = 9600;
+	pc_driver->init_termios.c_ospeed = 9600;
+	pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
+	tty_set_operations(pc_driver, &pc_ops);
+
+	pc_info->owner = THIS_MODULE;
+	pc_info->name = "digi_ctl";
+	pc_info->major = DIGIINFOMAJOR;
+	pc_info->minor_start = 0;
+	pc_info->type = TTY_DRIVER_TYPE_SERIAL;
+	pc_info->subtype = SERIAL_TYPE_INFO;
+	pc_info->init_termios = tty_std_termios;
+	pc_info->init_termios.c_iflag = 0;
+	pc_info->init_termios.c_oflag = 0;
+	pc_info->init_termios.c_lflag = 0;
+	pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
+	pc_info->init_termios.c_ispeed = 9600;
+	pc_info->init_termios.c_ospeed = 9600;
+	pc_info->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(pc_info, &info_ops);
+
+
+	for (crd = 0; crd < num_cards; crd++) {
+		/*
+		 * This is where the appropriate memory handlers for the
+		 * hardware is set. Everything at runtime blindly jumps through
+		 * these vectors.
+		 */
+
+		/* defined in epcaconfig.h */
+		bd = &boards[crd];
+
+		switch (bd->type) {
+		case PCXEM:
+		case EISAXEM:
+			bd->memwinon     = pcxem_memwinon;
+			bd->memwinoff    = pcxem_memwinoff;
+			bd->globalwinon  = pcxem_globalwinon;
+			bd->txwinon      = pcxem_txwinon;
+			bd->rxwinon      = pcxem_rxwinon;
+			bd->memoff       = pcxem_memoff;
+			bd->assertgwinon = dummy_assertgwinon;
+			bd->assertmemoff = dummy_assertmemoff;
+			break;
+
+		case PCIXEM:
+		case PCIXRJ:
+		case PCIXR:
+			bd->memwinon     = dummy_memwinon;
+			bd->memwinoff    = dummy_memwinoff;
+			bd->globalwinon  = dummy_globalwinon;
+			bd->txwinon      = dummy_txwinon;
+			bd->rxwinon      = dummy_rxwinon;
+			bd->memoff       = dummy_memoff;
+			bd->assertgwinon = dummy_assertgwinon;
+			bd->assertmemoff = dummy_assertmemoff;
+			break;
+
+		case PCXE:
+		case PCXEVE:
+			bd->memwinon     = pcxe_memwinon;
+			bd->memwinoff    = pcxe_memwinoff;
+			bd->globalwinon  = pcxe_globalwinon;
+			bd->txwinon      = pcxe_txwinon;
+			bd->rxwinon      = pcxe_rxwinon;
+			bd->memoff       = pcxe_memoff;
+			bd->assertgwinon = dummy_assertgwinon;
+			bd->assertmemoff = dummy_assertmemoff;
+			break;
+
+		case PCXI:
+		case PC64XE:
+			bd->memwinon     = pcxi_memwinon;
+			bd->memwinoff    = pcxi_memwinoff;
+			bd->globalwinon  = pcxi_globalwinon;
+			bd->txwinon      = pcxi_txwinon;
+			bd->rxwinon      = pcxi_rxwinon;
+			bd->memoff       = pcxi_memoff;
+			bd->assertgwinon = pcxi_assertgwinon;
+			bd->assertmemoff = pcxi_assertmemoff;
+			break;
+
+		default:
+			break;
+		}
+
+		/*
+		 * Some cards need a memory segment to be defined for use in
+		 * transmit and receive windowing operations. These boards are
+		 * listed in the below switch. In the case of the XI the amount
+		 * of memory on the board is variable so the memory_seg is also
+		 * variable. This code determines what they segment should be.
+		 */
+		switch (bd->type) {
+		case PCXE:
+		case PCXEVE:
+		case PC64XE:
+			bd->memory_seg = 0xf000;
+			break;
+
+		case PCXI:
+			board_id = inb((int)bd->port);
+			if ((board_id & 0x1) == 0x1) {
+				/* it's an XI card */
+				/* Is it a 64K board */
+				if ((board_id & 0x30) == 0)
+					bd->memory_seg = 0xf000;
+
+				/* Is it a 128K board */
+				if ((board_id & 0x30) == 0x10)
+					bd->memory_seg = 0xe000;
+
+				/* Is is a 256K board */
+				if ((board_id & 0x30) == 0x20)
+					bd->memory_seg = 0xc000;
+
+				/* Is it a 512K board */
+				if ((board_id & 0x30) == 0x30)
+					bd->memory_seg = 0x8000;
+			} else
+				printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
+			break;
+		}
+	}
+
+	err = tty_register_driver(pc_driver);
+	if (err) {
+		printk(KERN_ERR "Couldn't register Digi PC/ driver");
+		goto out3;
+	}
+
+	err = tty_register_driver(pc_info);
+	if (err) {
+		printk(KERN_ERR "Couldn't register Digi PC/ info ");
+		goto out4;
+	}
+
+	/* Start up the poller to check for events on all enabled boards */
+	init_timer(&epca_timer);
+	epca_timer.function = epcapoll;
+	mod_timer(&epca_timer, jiffies + HZ/25);
+	return 0;
+
+out4:
+	tty_unregister_driver(pc_driver);
+out3:
+	put_tty_driver(pc_info);
+out2:
+	put_tty_driver(pc_driver);
+out1:
+	return err;
+}
+
+static void post_fep_init(unsigned int crd)
+{
+	int i;
+	void __iomem *memaddr;
+	struct global_data __iomem *gd;
+	struct board_info *bd;
+	struct board_chan __iomem *bc;
+	struct channel *ch;
+	int shrinkmem = 0, lowwater;
+
+	/*
+	 * This call is made by the user via. the ioctl call DIGI_INIT. It is
+	 * responsible for setting up all the card specific stuff.
+	 */
+	bd = &boards[crd];
+
+	/*
+	 * If this is a PCI board, get the port info. Remember PCI cards do not
+	 * have entries into the epcaconfig.h file, so we can't get the number
+	 * of ports from it. Unfortunetly, this means that anyone doing a
+	 * DIGI_GETINFO before the board has booted will get an invalid number
+	 * of ports returned (It should return 0). Calls to DIGI_GETINFO after
+	 * DIGI_INIT has been called will return the proper values.
+	 */
+	if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
+		/*
+		 * Below we use XEMPORTS as a memory offset regardless of which
+		 * PCI card it is. This is because all of the supported PCI
+		 * cards have the same memory offset for the channel data. This
+		 * will have to be changed if we ever develop a PCI/XE card.
+		 * NOTE : The FEP manual states that the port offset is 0xC22
+		 * as opposed to 0xC02. This is only true for PC/XE, and PC/XI
+		 * cards; not for the XEM, or CX series. On the PCI cards the
+		 * number of ports is determined by reading a ID PROM located
+		 * in the box attached to the card. The card can then determine
+		 * the index the id to determine the number of ports available.
+		 * (FYI - The id should be located at 0x1ac (And may use up to
+		 * 4 bytes if the box in question is a XEM or CX)).
+		 */
+		/* PCI cards are already remapped at this point ISA are not */
+		bd->numports = readw(bd->re_map_membase + XEMPORTS);
+		epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
+		nbdevs += (bd->numports);
+	} else {
+		/* Fix up the mappings for ISA/EISA etc */
+		/* FIXME: 64K - can we be smarter ? */
+		bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
+	}
+
+	if (crd != 0)
+		card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
+	else
+		card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
+
+	ch = card_ptr[crd];
+	epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
+
+	memaddr = bd->re_map_membase;
+
+	/*
+	 * The below assignment will set bc to point at the BEGINING of the
+	 * cards channel structures. For 1 card there will be between 8 and 64
+	 * of these structures.
+	 */
+	bc = memaddr + CHANSTRUCT;
+
+	/*
+	 * The below assignment will set gd to point at the BEGINING of global
+	 * memory address 0xc00. The first data in that global memory actually
+	 * starts at address 0xc1a. The command in pointer begins at 0xd10.
+	 */
+	gd = memaddr + GLOBAL;
+
+	/*
+	 * XEPORTS (address 0xc22) points at the number of channels the card
+	 * supports. (For 64XE, XI, XEM, and XR use 0xc02)
+	 */
+	if ((bd->type == PCXEVE || bd->type == PCXE) &&
+					(readw(memaddr + XEPORTS) < 3))
+		shrinkmem = 1;
+	if (bd->type < PCIXEM)
+		if (!request_region((int)bd->port, 4, board_desc[bd->type]))
+			return;
+	memwinon(bd, 0);
+
+	/*
+	 * Remember ch is the main drivers channels structure, while bc is the
+	 * cards channel structure.
+	 */
+	for (i = 0; i < bd->numports; i++, ch++, bc++) {
+		unsigned long flags;
+		u16 tseg, rseg;
+
+		tty_port_init(&ch->port);
+		ch->port.ops = &epca_port_ops;
+		ch->brdchan = bc;
+		ch->mailbox = gd;
+		INIT_WORK(&ch->tqueue, do_softint);
+		ch->board = &boards[crd];
+
+		spin_lock_irqsave(&epca_lock, flags);
+		switch (bd->type) {
+		/*
+		 * Since some of the boards use different bitmaps for
+		 * their control signals we cannot hard code these
+		 * values and retain portability. We virtualize this
+		 * data here.
+		 */
+		case EISAXEM:
+		case PCXEM:
+		case PCIXEM:
+		case PCIXRJ:
+		case PCIXR:
+			ch->m_rts = 0x02;
+			ch->m_dcd = 0x80;
+			ch->m_dsr = 0x20;
+			ch->m_cts = 0x10;
+			ch->m_ri  = 0x40;
+			ch->m_dtr = 0x01;
+			break;
+
+		case PCXE:
+		case PCXEVE:
+		case PCXI:
+		case PC64XE:
+			ch->m_rts = 0x02;
+			ch->m_dcd = 0x08;
+			ch->m_dsr = 0x10;
+			ch->m_cts = 0x20;
+			ch->m_ri  = 0x40;
+			ch->m_dtr = 0x80;
+			break;
+		}
+
+		if (boards[crd].altpin) {
+			ch->dsr = ch->m_dcd;
+			ch->dcd = ch->m_dsr;
+			ch->digiext.digi_flags |= DIGI_ALTPIN;
+		} else {
+			ch->dcd = ch->m_dcd;
+			ch->dsr = ch->m_dsr;
+		}
+
+		ch->boardnum   = crd;
+		ch->channelnum = i;
+		ch->magic      = EPCA_MAGIC;
+		tty_port_tty_set(&ch->port, NULL);
+
+		if (shrinkmem) {
+			fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
+			shrinkmem = 0;
+		}
+
+		tseg = readw(&bc->tseg);
+		rseg = readw(&bc->rseg);
+
+		switch (bd->type) {
+		case PCIXEM:
+		case PCIXRJ:
+		case PCIXR:
+			/* Cover all the 2MEG cards */
+			ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
+			ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
+			ch->txwin = FEPWIN | (tseg >> 11);
+			ch->rxwin = FEPWIN | (rseg >> 11);
+			break;
+
+		case PCXEM:
+		case EISAXEM:
+			/* Cover all the 32K windowed cards */
+			/* Mask equal to window size - 1 */
+			ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
+			ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
+			ch->txwin = FEPWIN | (tseg >> 11);
+			ch->rxwin = FEPWIN | (rseg >> 11);
+			break;
+
+		case PCXEVE:
+		case PCXE:
+			ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
+								& 0x1fff);
+			ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+			ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
+								& 0x1fff);
+			ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
+			break;
+
+		case PCXI:
+		case PC64XE:
+			ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
+			ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
+			ch->txwin = ch->rxwin = 0;
+			break;
+		}
+
+		ch->txbufhead = 0;
+		ch->txbufsize = readw(&bc->tmax) + 1;
+
+		ch->rxbufhead = 0;
+		ch->rxbufsize = readw(&bc->rmax) + 1;
+
+		lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
+
+		/* Set transmitter low water mark */
+		fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
+
+		/* Set receiver low water mark */
+		fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0);
+
+		/* Set receiver high water mark */
+		fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
+
+		writew(100, &bc->edelay);
+		writeb(1, &bc->idata);
+
+		ch->startc  = readb(&bc->startc);
+		ch->stopc   = readb(&bc->stopc);
+		ch->startca = readb(&bc->startca);
+		ch->stopca  = readb(&bc->stopca);
+
+		ch->fepcflag = 0;
+		ch->fepiflag = 0;
+		ch->fepoflag = 0;
+		ch->fepstartc = 0;
+		ch->fepstopc = 0;
+		ch->fepstartca = 0;
+		ch->fepstopca = 0;
+
+		ch->port.close_delay = 50;
+
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+
+	printk(KERN_INFO
+	"Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
+				VERSION, board_desc[bd->type], (long)bd->port,
+					(long)bd->membase, bd->numports);
+	memwinoff(bd, 0);
+}
+
+static void epcapoll(unsigned long ignored)
+{
+	unsigned long flags;
+	int crd;
+	unsigned int head, tail;
+	struct channel *ch;
+	struct board_info *bd;
+
+	/*
+	 * This routine is called upon every timer interrupt. Even though the
+	 * Digi series cards are capable of generating interrupts this method
+	 * of non-looping polling is more efficient. This routine checks for
+	 * card generated events (Such as receive data, are transmit buffer
+	 * empty) and acts on those events.
+	 */
+	for (crd = 0; crd < num_cards; crd++) {
+		bd = &boards[crd];
+		ch = card_ptr[crd];
+
+		if ((bd->status == DISABLED) || digi_poller_inhibited)
+			continue;
+
+		/*
+		 * assertmemoff is not needed here; indeed it is an empty
+		 * subroutine. It is being kept because future boards may need
+		 * this as well as some legacy boards.
+		 */
+		spin_lock_irqsave(&epca_lock, flags);
+
+		assertmemoff(ch);
+
+		globalwinon(ch);
+
+		/*
+		 * In this case head and tail actually refer to the event queue
+		 * not the transmit or receive queue.
+		 */
+		head = readw(&ch->mailbox->ein);
+		tail = readw(&ch->mailbox->eout);
+
+		/* If head isn't equal to tail we have an event */
+		if (head != tail)
+			doevent(crd);
+		memoff(ch);
+
+		spin_unlock_irqrestore(&epca_lock, flags);
+	} /* End for each card */
+	mod_timer(&epca_timer, jiffies + (HZ / 25));
+}
+
+static void doevent(int crd)
+{
+	void __iomem *eventbuf;
+	struct channel *ch, *chan0;
+	static struct tty_struct *tty;
+	struct board_info *bd;
+	struct board_chan __iomem *bc;
+	unsigned int tail, head;
+	int event, channel;
+	int mstat, lstat;
+
+	/*
+	 * This subroutine is called by epcapoll when an event is detected
+	 * in the event queue. This routine responds to those events.
+	 */
+	bd = &boards[crd];
+
+	chan0 = card_ptr[crd];
+	epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
+	assertgwinon(chan0);
+	while ((tail = readw(&chan0->mailbox->eout)) !=
+			(head = readw(&chan0->mailbox->ein))) {
+		/* Begin while something in event queue */
+		assertgwinon(chan0);
+		eventbuf = bd->re_map_membase + tail + ISTART;
+		/* Get the channel the event occurred on */
+		channel = readb(eventbuf);
+		/* Get the actual event code that occurred */
+		event = readb(eventbuf + 1);
+		/*
+		 * The two assignments below get the current modem status
+		 * (mstat) and the previous modem status (lstat). These are
+		 * useful becuase an event could signal a change in modem
+		 * signals itself.
+		 */
+		mstat = readb(eventbuf + 2);
+		lstat = readb(eventbuf + 3);
+
+		ch = chan0 + channel;
+		if ((unsigned)channel >= bd->numports || !ch)  {
+			if (channel >= bd->numports)
+				ch = chan0;
+			bc = ch->brdchan;
+			goto next;
+		}
+
+		bc = ch->brdchan;
+		if (bc == NULL)
+			goto next;
+
+		tty = tty_port_tty_get(&ch->port);
+		if (event & DATA_IND)  { /* Begin DATA_IND */
+			receive_data(ch, tty);
+			assertgwinon(ch);
+		} /* End DATA_IND */
+		/* else *//* Fix for DCD transition missed bug */
+		if (event & MODEMCHG_IND) {
+			/* A modem signal change has been indicated */
+			ch->imodem = mstat;
+			if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) {
+				/* We are now receiving dcd */
+				if (mstat & ch->dcd)
+					wake_up_interruptible(&ch->port.open_wait);
+				else	/* No dcd; hangup */
+					pc_sched_event(ch, EPCA_EVENT_HANGUP);
+			}
+		}
+		if (tty) {
+			if (event & BREAK_IND) {
+				/* A break has been indicated */
+				tty_insert_flip_char(tty, 0, TTY_BREAK);
+				tty_schedule_flip(tty);
+			} else if (event & LOWTX_IND)  {
+				if (ch->statusflags & LOWWAIT) {
+					ch->statusflags &= ~LOWWAIT;
+					tty_wakeup(tty);
+				}
+			} else if (event & EMPTYTX_IND) {
+				/* This event is generated by
+				   setup_empty_event */
+				ch->statusflags &= ~TXBUSY;
+				if (ch->statusflags & EMPTYWAIT) {
+					ch->statusflags &= ~EMPTYWAIT;
+					tty_wakeup(tty);
+				}
+			}
+			tty_kref_put(tty);
+		}
+next:
+		globalwinon(ch);
+		BUG_ON(!bc);
+		writew(1, &bc->idata);
+		writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
+		globalwinon(chan0);
+	} /* End while something in event queue */
+}
+
+static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
+					int byte2, int ncmds, int bytecmd)
+{
+	unchar __iomem *memaddr;
+	unsigned int head, cmdTail, cmdStart, cmdMax;
+	long count;
+	int n;
+
+	/* This is the routine in which commands may be passed to the card. */
+
+	if (ch->board->status == DISABLED)
+		return;
+	assertgwinon(ch);
+	/* Remember head (As well as max) is just an offset not a base addr */
+	head = readw(&ch->mailbox->cin);
+	/* cmdStart is a base address */
+	cmdStart = readw(&ch->mailbox->cstart);
+	/*
+	 * We do the addition below because we do not want a max pointer
+	 * relative to cmdStart. We want a max pointer that points at the
+	 * physical end of the command queue.
+	 */
+	cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
+	memaddr = ch->board->re_map_membase;
+
+	if (head >= (cmdMax - cmdStart) || (head & 03))  {
+		printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
+						__LINE__,  cmd, head);
+		printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
+						__LINE__,  cmdMax, cmdStart);
+		return;
+	}
+	if (bytecmd)  {
+		writeb(cmd, memaddr + head + cmdStart + 0);
+		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
+		/* Below word_or_byte is bits to set */
+		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
+		/* Below byte2 is bits to reset */
+		writeb(byte2, memaddr + head + cmdStart + 3);
+	}  else {
+		writeb(cmd, memaddr + head + cmdStart + 0);
+		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
+		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
+	}
+	head = (head + 4) & (cmdMax - cmdStart - 4);
+	writew(head, &ch->mailbox->cin);
+	count = FEPTIMEOUT;
+
+	for (;;) {
+		count--;
+		if (count == 0)  {
+			printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
+			return;
+		}
+		head = readw(&ch->mailbox->cin);
+		cmdTail = readw(&ch->mailbox->cout);
+		n = (head - cmdTail) & (cmdMax - cmdStart - 4);
+		/*
+		 * Basically this will break when the FEP acknowledges the
+		 * command by incrementing cmdTail (Making it equal to head).
+		 */
+		if (n <= ncmds * (sizeof(short) * 4))
+			break;
+	}
+}
+
+/*
+ * Digi products use fields in their channels structures that are very similar
+ * to the c_cflag and c_iflag fields typically found in UNIX termios
+ * structures. The below three routines allow mappings between these hardware
+ * "flags" and their respective Linux flags.
+ */
+static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
+{
+	unsigned res = 0;
+
+	if (cflag & CRTSCTS) {
+		ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
+		res |= ((ch->m_cts) | (ch->m_rts));
+	}
+
+	if (ch->digiext.digi_flags & RTSPACE)
+		res |= ch->m_rts;
+
+	if (ch->digiext.digi_flags & DTRPACE)
+		res |= ch->m_dtr;
+
+	if (ch->digiext.digi_flags & CTSPACE)
+		res |= ch->m_cts;
+
+	if (ch->digiext.digi_flags & DSRPACE)
+		res |= ch->dsr;
+
+	if (ch->digiext.digi_flags & DCDPACE)
+		res |= ch->dcd;
+
+	if (res & (ch->m_rts))
+		ch->digiext.digi_flags |= RTSPACE;
+
+	if (res & (ch->m_cts))
+		ch->digiext.digi_flags |= CTSPACE;
+
+	return res;
+}
+
+static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
+{
+	unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
+					INPCK | ISTRIP | IXON | IXANY | IXOFF);
+	if (ch->digiext.digi_flags & DIGI_AIXON)
+		res |= IAIXON;
+	return res;
+}
+
+static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
+{
+	unsigned res = 0;
+	if (cflag & CBAUDEX) {
+		ch->digiext.digi_flags |= DIGI_FAST;
+		/*
+		 * HUPCL bit is used by FEP to indicate fast baud table is to
+		 * be used.
+		 */
+		res |= FEP_HUPCL;
+	} else
+		ch->digiext.digi_flags &= ~DIGI_FAST;
+	/*
+	 * CBAUD has bit position 0x1000 set these days to indicate Linux
+	 * baud rate remap. Digi hardware can't handle the bit assignment.
+	 * (We use a different bit assignment for high speed.). Clear this
+	 * bit out.
+	 */
+	res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
+	/*
+	 * This gets a little confusing. The Digi cards have their own
+	 * representation of c_cflags controlling baud rate. For the most part
+	 * this is identical to the Linux implementation. However; Digi
+	 * supports one rate (76800) that Linux doesn't. This means that the
+	 * c_cflag entry that would normally mean 76800 for Digi actually means
+	 * 115200 under Linux. Without the below mapping, a stty 115200 would
+	 * only drive the board at 76800. Since the rate 230400 is also found
+	 * after 76800, the same problem afflicts us when we choose a rate of
+	 * 230400. Without the below modificiation stty 230400 would actually
+	 * give us 115200.
+	 *
+	 * There are two additional differences. The Linux value for CLOCAL
+	 * (0x800; 0004000) has no meaning to the Digi hardware. Also in later
+	 * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000)
+	 * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be
+	 * checked for a screened out prior to termios2digi_c returning. Since
+	 * CLOCAL isn't used by the board this can be ignored as long as the
+	 * returned value is used only by Digi hardware.
+	 */
+	if (cflag & CBAUDEX) {
+		/*
+		 * The below code is trying to guarantee that only baud rates
+		 * 115200 and 230400 are remapped. We use exclusive or because
+		 * the various baud rates share common bit positions and
+		 * therefore can't be tested for easily.
+		 */
+		if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
+		    (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
+			res += 1;
+	}
+	return res;
+}
+
+/* Caller must hold the locks */
+static void epcaparam(struct tty_struct *tty, struct channel *ch)
+{
+	unsigned int cmdHead;
+	struct ktermios *ts;
+	struct board_chan __iomem *bc;
+	unsigned mval, hflow, cflag, iflag;
+
+	bc = ch->brdchan;
+	epcaassert(bc != NULL, "bc out of range");
+
+	assertgwinon(ch);
+	ts = tty->termios;
+	if ((ts->c_cflag & CBAUD) == 0)  { /* Begin CBAUD detected */
+		cmdHead = readw(&bc->rin);
+		writew(cmdHead, &bc->rout);
+		cmdHead = readw(&bc->tin);
+		/* Changing baud in mid-stream transmission can be wonderful */
+		/*
+		 * Flush current transmit buffer by setting cmdTail pointer
+		 * (tout) to cmdHead pointer (tin). Hopefully the transmit
+		 * buffer is empty.
+		 */
+		fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
+		mval = 0;
+	} else { /* Begin CBAUD not detected */
+		/*
+		 * c_cflags have changed but that change had nothing to do with
+		 * BAUD. Propagate the change to the card.
+		 */
+		cflag = termios2digi_c(ch, ts->c_cflag);
+		if (cflag != ch->fepcflag)  {
+			ch->fepcflag = cflag;
+			/* Set baud rate, char size, stop bits, parity */
+			fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
+		}
+		/*
+		 * If the user has not forced CLOCAL and if the device is not a
+		 * CALLOUT device (Which is always CLOCAL) we set flags such
+		 * that the driver will wait on carrier detect.
+		 */
+		if (ts->c_cflag & CLOCAL)
+			clear_bit(ASYNCB_CHECK_CD, &ch->port.flags);
+		else
+			set_bit(ASYNCB_CHECK_CD, &ch->port.flags);
+		mval = ch->m_dtr | ch->m_rts;
+	} /* End CBAUD not detected */
+	iflag = termios2digi_i(ch, ts->c_iflag);
+	/* Check input mode flags */
+	if (iflag != ch->fepiflag)  {
+		ch->fepiflag = iflag;
+		/*
+		 * Command sets channels iflag structure on the board. Such
+		 * things as input soft flow control, handling of parity
+		 * errors, and break handling are all set here.
+		 *
+		 * break handling, parity handling, input stripping,
+		 * flow control chars
+		 */
+		fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
+	}
+	/*
+	 * Set the board mint value for this channel. This will cause hardware
+	 * events to be generated each time the DCD signal (Described in mint)
+	 * changes.
+	 */
+	writeb(ch->dcd, &bc->mint);
+	if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
+		if (ch->digiext.digi_flags & DIGI_FORCEDCD)
+			writeb(0, &bc->mint);
+	ch->imodem = readb(&bc->mstat);
+	hflow = termios2digi_h(ch, ts->c_cflag);
+	if (hflow != ch->hflow)  {
+		ch->hflow = hflow;
+		/*
+		 * Hard flow control has been selected but the board is not
+		 * using it. Activate hard flow control now.
+		 */
+		fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
+	}
+	mval ^= ch->modemfake & (mval ^ ch->modem);
+
+	if (ch->omodem ^ mval)  {
+		ch->omodem = mval;
+		/*
+		 * The below command sets the DTR and RTS mstat structure. If
+		 * hard flow control is NOT active these changes will drive the
+		 * output of the actual DTR and RTS lines. If hard flow control
+		 * is active, the changes will be saved in the mstat structure
+		 * and only asserted when hard flow control is turned off.
+		 */
+
+		/* First reset DTR & RTS; then set them */
+		fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
+		fepcmd(ch, SETMODEM, mval, 0, 0, 1);
+	}
+	if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)  {
+		ch->fepstartc = ch->startc;
+		ch->fepstopc = ch->stopc;
+		/*
+		 * The XON / XOFF characters have changed; propagate these
+		 * changes to the card.
+		 */
+		fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
+	}
+	if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)  {
+		ch->fepstartca = ch->startca;
+		ch->fepstopca = ch->stopca;
+		/*
+		 * Similar to the above, this time the auxilarly XON / XOFF
+		 * characters have changed; propagate these changes to the card.
+		 */
+		fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
+	}
+}
+
+/* Caller holds lock */
+static void receive_data(struct channel *ch, struct tty_struct *tty)
+{
+	unchar *rptr;
+	struct ktermios *ts = NULL;
+	struct board_chan __iomem *bc;
+	int dataToRead, wrapgap, bytesAvailable;
+	unsigned int tail, head;
+	unsigned int wrapmask;
+
+	/*
+	 * This routine is called by doint when a receive data event has taken
+	 * place.
+	 */
+	globalwinon(ch);
+	if (ch->statusflags & RXSTOPPED)
+		return;
+	if (tty)
+		ts = tty->termios;
+	bc = ch->brdchan;
+	BUG_ON(!bc);
+	wrapmask = ch->rxbufsize - 1;
+
+	/*
+	 * Get the head and tail pointers to the receiver queue. Wrap the head
+	 * pointer if it has reached the end of the buffer.
+	 */
+	head = readw(&bc->rin);
+	head &= wrapmask;
+	tail = readw(&bc->rout) & wrapmask;
+
+	bytesAvailable = (head - tail) & wrapmask;
+	if (bytesAvailable == 0)
+		return;
+
+	/* If CREAD bit is off or device not open, set TX tail to head */
+	if (!tty || !ts || !(ts->c_cflag & CREAD)) {
+		writew(head, &bc->rout);
+		return;
+	}
+
+	if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
+		return;
+
+	if (readb(&bc->orun)) {
+		writeb(0, &bc->orun);
+		printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
+								tty->name);
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+	}
+	rxwinon(ch);
+	while (bytesAvailable > 0) {
+		/* Begin while there is data on the card */
+		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
+		/*
+		 * Even if head has wrapped around only report the amount of
+		 * data to be equal to the size - tail. Remember memcpy can't
+		 * automaticly wrap around the receive buffer.
+		 */
+		dataToRead = (wrapgap < bytesAvailable) ? wrapgap
+							: bytesAvailable;
+		/* Make sure we don't overflow the buffer */
+		dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
+		if (dataToRead == 0)
+			break;
+		/*
+		 * Move data read from our card into the line disciplines
+		 * buffer for translation if necessary.
+		 */
+		memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
+		tail = (tail + dataToRead) & wrapmask;
+		bytesAvailable -= dataToRead;
+	} /* End while there is data on the card */
+	globalwinon(ch);
+	writew(tail, &bc->rout);
+	/* Must be called with global data */
+	tty_schedule_flip(tty);
+}
+
+static int info_ioctl(struct tty_struct *tty,
+		    unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case DIGI_GETINFO:
+		{
+			struct digi_info di;
+			int brd;
+
+			if (get_user(brd, (unsigned int __user *)arg))
+				return -EFAULT;
+			if (brd < 0 || brd >= num_cards || num_cards == 0)
+				return -ENODEV;
+
+			memset(&di, 0, sizeof(di));
+
+			di.board = brd;
+			di.status = boards[brd].status;
+			di.type = boards[brd].type ;
+			di.numports = boards[brd].numports ;
+			/* Legacy fixups - just move along nothing to see */
+			di.port = (unsigned char *)boards[brd].port ;
+			di.membase = (unsigned char *)boards[brd].membase ;
+
+			if (copy_to_user((void __user *)arg, &di, sizeof(di)))
+				return -EFAULT;
+			break;
+
+		}
+
+	case DIGI_POLLER:
+		{
+			int brd = arg & 0xff000000 >> 16;
+			unsigned char state = arg & 0xff;
+
+			if (brd < 0 || brd >= num_cards) {
+				printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
+				return -ENODEV;
+			}
+			digi_poller_inhibited = state;
+			break;
+		}
+
+	case DIGI_INIT:
+		{
+			/*
+			 * This call is made by the apps to complete the
+			 * initialization of the board(s). This routine is
+			 * responsible for setting the card to its initial
+			 * state and setting the drivers control fields to the
+			 * sutianle settings for the card in question.
+			 */
+			int crd;
+			for (crd = 0; crd < num_cards; crd++)
+				post_fep_init(crd);
+			break;
+		}
+	default:
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static int pc_tiocmget(struct tty_struct *tty)
+{
+	struct channel *ch = tty->driver_data;
+	struct board_chan __iomem *bc;
+	unsigned int mstat, mflag = 0;
+	unsigned long flags;
+
+	if (ch)
+		bc = ch->brdchan;
+	else
+		return -EINVAL;
+
+	spin_lock_irqsave(&epca_lock, flags);
+	globalwinon(ch);
+	mstat = readb(&bc->mstat);
+	memoff(ch);
+	spin_unlock_irqrestore(&epca_lock, flags);
+
+	if (mstat & ch->m_dtr)
+		mflag |= TIOCM_DTR;
+	if (mstat & ch->m_rts)
+		mflag |= TIOCM_RTS;
+	if (mstat & ch->m_cts)
+		mflag |= TIOCM_CTS;
+	if (mstat & ch->dsr)
+		mflag |= TIOCM_DSR;
+	if (mstat & ch->m_ri)
+		mflag |= TIOCM_RI;
+	if (mstat & ch->dcd)
+		mflag |= TIOCM_CD;
+	return mflag;
+}
+
+static int pc_tiocmset(struct tty_struct *tty,
+		       unsigned int set, unsigned int clear)
+{
+	struct channel *ch = tty->driver_data;
+	unsigned long flags;
+
+	if (!ch)
+		return -EINVAL;
+
+	spin_lock_irqsave(&epca_lock, flags);
+	/*
+	 * I think this modemfake stuff is broken. It doesn't correctly reflect
+	 * the behaviour desired by the TIOCM* ioctls. Therefore this is
+	 * probably broken.
+	 */
+	if (set & TIOCM_RTS) {
+		ch->modemfake |= ch->m_rts;
+		ch->modem |= ch->m_rts;
+	}
+	if (set & TIOCM_DTR) {
+		ch->modemfake |= ch->m_dtr;
+		ch->modem |= ch->m_dtr;
+	}
+	if (clear & TIOCM_RTS) {
+		ch->modemfake |= ch->m_rts;
+		ch->modem &= ~ch->m_rts;
+	}
+	if (clear & TIOCM_DTR) {
+		ch->modemfake |= ch->m_dtr;
+		ch->modem &= ~ch->m_dtr;
+	}
+	globalwinon(ch);
+	/*
+	 * The below routine generally sets up parity, baud, flow control
+	 * issues, etc.... It effect both control flags and input flags.
+	 */
+	epcaparam(tty, ch);
+	memoff(ch);
+	spin_unlock_irqrestore(&epca_lock, flags);
+	return 0;
+}
+
+static int pc_ioctl(struct tty_struct *tty,
+					unsigned int cmd, unsigned long arg)
+{
+	digiflow_t dflow;
+	unsigned long flags;
+	unsigned int mflag, mstat;
+	unsigned char startc, stopc;
+	struct board_chan __iomem *bc;
+	struct channel *ch = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+
+	if (ch)
+		bc = ch->brdchan;
+	else
+		return -EINVAL;
+	switch (cmd) {
+	case TIOCMODG:
+		mflag = pc_tiocmget(tty);
+		if (put_user(mflag, (unsigned long __user *)argp))
+			return -EFAULT;
+		break;
+	case TIOCMODS:
+		if (get_user(mstat, (unsigned __user *)argp))
+			return -EFAULT;
+		return pc_tiocmset(tty, mstat, ~mstat);
+	case TIOCSDTR:
+		spin_lock_irqsave(&epca_lock, flags);
+		ch->omodem |= ch->m_dtr;
+		globalwinon(ch);
+		fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
+		memoff(ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+		break;
+
+	case TIOCCDTR:
+		spin_lock_irqsave(&epca_lock, flags);
+		ch->omodem &= ~ch->m_dtr;
+		globalwinon(ch);
+		fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
+		memoff(ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+		break;
+	case DIGI_GETA:
+		if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
+			return -EFAULT;
+		break;
+	case DIGI_SETAW:
+	case DIGI_SETAF:
+		if (cmd == DIGI_SETAW) {
+			/* Setup an event to indicate when the transmit
+			   buffer empties */
+			spin_lock_irqsave(&epca_lock, flags);
+			setup_empty_event(tty, ch);
+			spin_unlock_irqrestore(&epca_lock, flags);
+			tty_wait_until_sent(tty, 0);
+		} else {
+			/* ldisc lock already held in ioctl */
+			if (tty->ldisc->ops->flush_buffer)
+				tty->ldisc->ops->flush_buffer(tty);
+		}
+		/* Fall Thru */
+	case DIGI_SETA:
+		if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
+			return -EFAULT;
+
+		if (ch->digiext.digi_flags & DIGI_ALTPIN)  {
+			ch->dcd = ch->m_dsr;
+			ch->dsr = ch->m_dcd;
+		} else {
+			ch->dcd = ch->m_dcd;
+			ch->dsr = ch->m_dsr;
+			}
+
+		spin_lock_irqsave(&epca_lock, flags);
+		globalwinon(ch);
+
+		/*
+		 * The below routine generally sets up parity, baud, flow
+		 * control issues, etc.... It effect both control flags and
+		 * input flags.
+		 */
+		epcaparam(tty, ch);
+		memoff(ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+		break;
+
+	case DIGI_GETFLOW:
+	case DIGI_GETAFLOW:
+		spin_lock_irqsave(&epca_lock, flags);
+		globalwinon(ch);
+		if (cmd == DIGI_GETFLOW) {
+			dflow.startc = readb(&bc->startc);
+			dflow.stopc = readb(&bc->stopc);
+		} else {
+			dflow.startc = readb(&bc->startca);
+			dflow.stopc = readb(&bc->stopca);
+		}
+		memoff(ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+
+		if (copy_to_user(argp, &dflow, sizeof(dflow)))
+			return -EFAULT;
+		break;
+
+	case DIGI_SETAFLOW:
+	case DIGI_SETFLOW:
+		if (cmd == DIGI_SETFLOW) {
+			startc = ch->startc;
+			stopc = ch->stopc;
+		} else {
+			startc = ch->startca;
+			stopc = ch->stopca;
+		}
+
+		if (copy_from_user(&dflow, argp, sizeof(dflow)))
+			return -EFAULT;
+
+		if (dflow.startc != startc || dflow.stopc != stopc) {
+			/* Begin  if setflow toggled */
+			spin_lock_irqsave(&epca_lock, flags);
+			globalwinon(ch);
+
+			if (cmd == DIGI_SETFLOW) {
+				ch->fepstartc = ch->startc = dflow.startc;
+				ch->fepstopc = ch->stopc = dflow.stopc;
+				fepcmd(ch, SONOFFC, ch->fepstartc,
+						ch->fepstopc, 0, 1);
+			} else {
+				ch->fepstartca = ch->startca = dflow.startc;
+				ch->fepstopca  = ch->stopca = dflow.stopc;
+				fepcmd(ch, SAUXONOFFC, ch->fepstartca,
+						ch->fepstopca, 0, 1);
+			}
+
+			if (ch->statusflags & TXSTOPPED)
+				pc_start(tty);
+
+			memoff(ch);
+			spin_unlock_irqrestore(&epca_lock, flags);
+		} /* End if setflow toggled */
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct channel *ch;
+	unsigned long flags;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+
+	if (ch != NULL)  { /* Begin if channel valid */
+		spin_lock_irqsave(&epca_lock, flags);
+		globalwinon(ch);
+		epcaparam(tty, ch);
+		memoff(ch);
+		spin_unlock_irqrestore(&epca_lock, flags);
+
+		if ((old_termios->c_cflag & CRTSCTS) &&
+			 ((tty->termios->c_cflag & CRTSCTS) == 0))
+			tty->hw_stopped = 0;
+
+		if (!(old_termios->c_cflag & CLOCAL) &&
+			 (tty->termios->c_cflag & CLOCAL))
+			wake_up_interruptible(&ch->port.open_wait);
+
+	} /* End if channel valid */
+}
+
+static void do_softint(struct work_struct *work)
+{
+	struct channel *ch = container_of(work, struct channel, tqueue);
+	/* Called in response to a modem change event */
+	if (ch && ch->magic == EPCA_MAGIC) {
+		struct tty_struct *tty = tty_port_tty_get(&ch->port);
+
+		if (tty && tty->driver_data) {
+			if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
+				tty_hangup(tty);
+				wake_up_interruptible(&ch->port.open_wait);
+				clear_bit(ASYNCB_NORMAL_ACTIVE,
+						&ch->port.flags);
+			}
+		}
+		tty_kref_put(tty);
+	}
+}
+
+/*
+ * pc_stop and pc_start provide software flow control to the routine and the
+ * pc_ioctl routine.
+ */
+static void pc_stop(struct tty_struct *tty)
+{
+	struct channel *ch;
+	unsigned long flags;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		spin_lock_irqsave(&epca_lock, flags);
+		if ((ch->statusflags & TXSTOPPED) == 0) {
+			/* Begin if transmit stop requested */
+			globalwinon(ch);
+			/* STOP transmitting now !! */
+			fepcmd(ch, PAUSETX, 0, 0, 0, 0);
+			ch->statusflags |= TXSTOPPED;
+			memoff(ch);
+		} /* End if transmit stop requested */
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+}
+
+static void pc_start(struct tty_struct *tty)
+{
+	struct channel *ch;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		unsigned long flags;
+		spin_lock_irqsave(&epca_lock, flags);
+		/* Just in case output was resumed because of a change
+		   in Digi-flow */
+		if (ch->statusflags & TXSTOPPED)  {
+			/* Begin transmit resume requested */
+			struct board_chan __iomem *bc;
+			globalwinon(ch);
+			bc = ch->brdchan;
+			if (ch->statusflags & LOWWAIT)
+				writeb(1, &bc->ilow);
+			/* Okay, you can start transmitting again... */
+			fepcmd(ch, RESUMETX, 0, 0, 0, 0);
+			ch->statusflags &= ~TXSTOPPED;
+			memoff(ch);
+		} /* End transmit resume requested */
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+}
+
+/*
+ * The below routines pc_throttle and pc_unthrottle are used to slow (And
+ * resume) the receipt of data into the kernels receive buffers. The exact
+ * occurrence of this depends on the size of the kernels receive buffer and
+ * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for
+ * more details.
+ */
+static void pc_throttle(struct tty_struct *tty)
+{
+	struct channel *ch;
+	unsigned long flags;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		spin_lock_irqsave(&epca_lock, flags);
+		if ((ch->statusflags & RXSTOPPED) == 0) {
+			globalwinon(ch);
+			fepcmd(ch, PAUSERX, 0, 0, 0, 0);
+			ch->statusflags |= RXSTOPPED;
+			memoff(ch);
+		}
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+}
+
+static void pc_unthrottle(struct tty_struct *tty)
+{
+	struct channel *ch;
+	unsigned long flags;
+	/*
+	 * verifyChannel returns the channel from the tty struct if it is
+	 * valid. This serves as a sanity check.
+	 */
+	ch = verifyChannel(tty);
+	if (ch != NULL) {
+		/* Just in case output was resumed because of a change
+		   in Digi-flow */
+		spin_lock_irqsave(&epca_lock, flags);
+		if (ch->statusflags & RXSTOPPED) {
+			globalwinon(ch);
+			fepcmd(ch, RESUMERX, 0, 0, 0, 0);
+			ch->statusflags &= ~RXSTOPPED;
+			memoff(ch);
+		}
+		spin_unlock_irqrestore(&epca_lock, flags);
+	}
+}
+
+static int pc_send_break(struct tty_struct *tty, int msec)
+{
+	struct channel *ch = tty->driver_data;
+	unsigned long flags;
+
+	if (msec == -1)
+		msec = 0xFFFF;
+	else if (msec > 0xFFFE)
+		msec = 0xFFFE;
+	else if (msec < 1)
+		msec = 1;
+
+	spin_lock_irqsave(&epca_lock, flags);
+	globalwinon(ch);
+	/*
+	 * Maybe I should send an infinite break here, schedule() for msec
+	 * amount of time, and then stop the break. This way, the user can't
+	 * screw up the FEP by causing digi_send_break() to be called (i.e. via
+	 * an ioctl()) more than once in msec amount of time.
+	 * Try this for now...
+	 */
+	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
+	memoff(ch);
+	spin_unlock_irqrestore(&epca_lock, flags);
+	return 0;
+}
+
+/* Caller MUST hold the lock */
+static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
+{
+	struct board_chan __iomem *bc = ch->brdchan;
+
+	globalwinon(ch);
+	ch->statusflags |= EMPTYWAIT;
+	/*
+	 * When set the iempty flag request a event to be generated when the
+	 * transmit buffer is empty (If there is no BREAK in progress).
+	 */
+	writeb(1, &bc->iempty);
+	memoff(ch);
+}
+
+#ifndef MODULE
+static void __init epca_setup(char *str, int *ints)
+{
+	struct board_info board;
+	int               index, loop, last;
+	char              *temp, *t2;
+	unsigned          len;
+
+	/*
+	 * If this routine looks a little strange it is because it is only
+	 * called if a LILO append command is given to boot the kernel with
+	 * parameters. In this way, we can provide the user a method of
+	 * changing his board configuration without rebuilding the kernel.
+	 */
+	if (!liloconfig)
+		liloconfig = 1;
+
+	memset(&board, 0, sizeof(board));
+
+	/* Assume the data is int first, later we can change it */
+	/* I think that array position 0 of ints holds the number of args */
+	for (last = 0, index = 1; index <= ints[0]; index++)
+		switch (index) { /* Begin parse switch */
+		case 1:
+			board.status = ints[index];
+			/*
+			 * We check for 2 (As opposed to 1; because 2 is a flag
+			 * instructing the driver to ignore epcaconfig.) For
+			 * this reason we check for 2.
+			 */
+			if (board.status == 2) {
+			/* Begin ignore epcaconfig as well as lilo cmd line */
+				nbdevs = 0;
+				num_cards = 0;
+				return;
+			} /* End ignore epcaconfig as well as lilo cmd line */
+
+			if (board.status > 2) {
+				printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
+						board.status);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_BOARD_STATUS;
+				return;
+			}
+			last = index;
+			break;
+		case 2:
+			board.type = ints[index];
+			if (board.type >= PCIXEM)  {
+				printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_BOARD_TYPE;
+				return;
+			}
+			last = index;
+			break;
+		case 3:
+			board.altpin = ints[index];
+			if (board.altpin > 1) {
+				printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_ALTPIN;
+				return;
+			}
+			last = index;
+			break;
+
+		case 4:
+			board.numports = ints[index];
+			if (board.numports < 2 || board.numports > 256) {
+				printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_NUM_PORTS;
+				return;
+			}
+			nbdevs += board.numports;
+			last = index;
+			break;
+
+		case 5:
+			board.port = ints[index];
+			if (ints[index] <= 0) {
+				printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_PORT_BASE;
+				return;
+			}
+			last = index;
+			break;
+
+		case 6:
+			board.membase = ints[index];
+			if (ints[index] <= 0) {
+				printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
+					(unsigned int)board.membase);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_MEM_BASE;
+				return;
+			}
+			last = index;
+			break;
+
+		default:
+			printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n");
+			return;
+
+		} /* End parse switch */
+
+	while (str && *str)  { /* Begin while there is a string arg */
+		/* find the next comma or terminator */
+		temp = str;
+		/* While string is not null, and a comma hasn't been found */
+		while (*temp && (*temp != ','))
+			temp++;
+		if (!*temp)
+			temp = NULL;
+		else
+			*temp++ = 0;
+		/* Set index to the number of args + 1 */
+		index = last + 1;
+
+		switch (index) {
+		case 1:
+			len = strlen(str);
+			if (strncmp("Disable", str, len) == 0)
+				board.status = 0;
+			else if (strncmp("Enable", str, len) == 0)
+				board.status = 1;
+			else {
+				printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_BOARD_STATUS;
+				return;
+			}
+			last = index;
+			break;
+
+		case 2:
+			for (loop = 0; loop < EPCA_NUM_TYPES; loop++)
+				if (strcmp(board_desc[loop], str) == 0)
+					break;
+			/*
+			 * If the index incremented above refers to a
+			 * legitamate board type set it here.
+			 */
+			if (index < EPCA_NUM_TYPES)
+				board.type = loop;
+			else {
+				printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_BOARD_TYPE;
+				return;
+			}
+			last = index;
+			break;
+
+		case 3:
+			len = strlen(str);
+			if (strncmp("Disable", str, len) == 0)
+				board.altpin = 0;
+			else if (strncmp("Enable", str, len) == 0)
+				board.altpin = 1;
+			else {
+				printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_ALTPIN;
+				return;
+			}
+			last = index;
+			break;
+
+		case 4:
+			t2 = str;
+			while (isdigit(*t2))
+				t2++;
+
+			if (*t2) {
+				printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_NUM_PORTS;
+				return;
+			}
+
+			/*
+			 * There is not a man page for simple_strtoul but the
+			 * code can be found in vsprintf.c. The first argument
+			 * is the string to translate (To an unsigned long
+			 * obviously), the second argument can be the address
+			 * of any character variable or a NULL. If a variable
+			 * is given, the end pointer of the string will be
+			 * stored in that variable; if a NULL is given the end
+			 * pointer will not be returned. The last argument is
+			 * the base to use. If a 0 is indicated, the routine
+			 * will attempt to determine the proper base by looking
+			 * at the values prefix (A '0' for octal, a 'x' for
+			 * hex, etc ... If a value is given it will use that
+			 * value as the base.
+			 */
+			board.numports = simple_strtoul(str, NULL, 0);
+			nbdevs += board.numports;
+			last = index;
+			break;
+
+		case 5:
+			t2 = str;
+			while (isxdigit(*t2))
+				t2++;
+
+			if (*t2) {
+				printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_PORT_BASE;
+				return;
+			}
+
+			board.port = simple_strtoul(str, NULL, 16);
+			last = index;
+			break;
+
+		case 6:
+			t2 = str;
+			while (isxdigit(*t2))
+				t2++;
+
+			if (*t2) {
+				printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
+				invalid_lilo_config = 1;
+				setup_error_code |= INVALID_MEM_BASE;
+				return;
+			}
+			board.membase = simple_strtoul(str, NULL, 16);
+			last = index;
+			break;
+		default:
+			printk(KERN_ERR "epca: Too many string parms\n");
+			return;
+		}
+		str = temp;
+	} /* End while there is a string arg */
+
+	if (last < 6) {
+		printk(KERN_ERR "epca: Insufficient parms specified\n");
+		return;
+	}
+
+	/* I should REALLY validate the stuff here */
+	/* Copies our local copy of board into boards */
+	memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
+	/* Does this get called once per lilo arg are what ? */
+	printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
+		num_cards, board_desc[board.type],
+		board.numports, (int)board.port, (unsigned int) board.membase);
+	num_cards++;
+}
+
+static int __init epca_real_setup(char *str)
+{
+	int ints[11];
+
+	epca_setup(get_options(str, 11, ints), ints);
+	return 1;
+}
+
+__setup("digiepca", epca_real_setup);
+#endif
+
+enum epic_board_types {
+	brd_xr = 0,
+	brd_xem,
+	brd_cx,
+	brd_xrj,
+};
+
+/* indexed directly by epic_board_types enum */
+static struct {
+	unsigned char board_type;
+	unsigned bar_idx;		/* PCI base address region */
+} epca_info_tbl[] = {
+	{ PCIXR, 0, },
+	{ PCIXEM, 0, },
+	{ PCICX, 0, },
+	{ PCIXRJ, 2, },
+};
+
+static int __devinit epca_init_one(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	static int board_num = -1;
+	int board_idx, info_idx = ent->driver_data;
+	unsigned long addr;
+
+	if (pci_enable_device(pdev))
+		return -EIO;
+
+	board_num++;
+	board_idx = board_num + num_cards;
+	if (board_idx >= MAXBOARDS)
+		goto err_out;
+
+	addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
+	if (!addr) {
+		printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
+			epca_info_tbl[info_idx].bar_idx);
+		goto err_out;
+	}
+
+	boards[board_idx].status = ENABLED;
+	boards[board_idx].type = epca_info_tbl[info_idx].board_type;
+	boards[board_idx].numports = 0x0;
+	boards[board_idx].port = addr + PCI_IO_OFFSET;
+	boards[board_idx].membase = addr;
+
+	if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
+		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+			0x200000, addr + PCI_IO_OFFSET);
+		goto err_out;
+	}
+
+	boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
+								0x200000);
+	if (!boards[board_idx].re_map_port) {
+		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+			0x200000, addr + PCI_IO_OFFSET);
+		goto err_out_free_pciio;
+	}
+
+	if (!request_mem_region(addr, 0x200000, "epca")) {
+		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
+			0x200000, addr);
+		goto err_out_free_iounmap;
+	}
+
+	boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
+	if (!boards[board_idx].re_map_membase) {
+		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
+			0x200000, addr + PCI_IO_OFFSET);
+		goto err_out_free_memregion;
+	}
+
+	/*
+	 * I don't know what the below does, but the hardware guys say its
+	 * required on everything except PLX (In this case XRJ).
+	 */
+	if (info_idx != brd_xrj) {
+		pci_write_config_byte(pdev, 0x40, 0);
+		pci_write_config_byte(pdev, 0x46, 0);
+	}
+
+	return 0;
+
+err_out_free_memregion:
+	release_mem_region(addr, 0x200000);
+err_out_free_iounmap:
+	iounmap(boards[board_idx].re_map_port);
+err_out_free_pciio:
+	release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
+err_out:
+	return -ENODEV;
+}
+
+
+static struct pci_device_id epca_pci_tbl[] = {
+	{ PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr },
+	{ PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem },
+	{ PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx },
+	{ PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
+
+static int __init init_PCI(void)
+{
+	memset(&epca_driver, 0, sizeof(epca_driver));
+	epca_driver.name = "epca";
+	epca_driver.id_table = epca_pci_tbl;
+	epca_driver.probe = epca_init_one;
+
+	return pci_register_driver(&epca_driver);
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tty/epca.h b/drivers/staging/tty/epca.h
new file mode 100644
index 0000000..d414bf2
--- /dev/null
+++ b/drivers/staging/tty/epca.h
@@ -0,0 +1,158 @@
+#define XEMPORTS    0xC02
+#define XEPORTS     0xC22
+
+#define MAX_ALLOC   0x100
+
+#define MAXBOARDS   12
+#define FEPCODESEG  0x0200L
+#define FEPCODE     0x2000L
+#define BIOSCODE    0xf800L
+
+#define MISCGLOBAL  0x0C00L
+#define NPORT       0x0C22L
+#define MBOX        0x0C40L
+#define PORTBASE    0x0C90L
+
+/* Begin code defines used for epca_setup */
+
+#define INVALID_BOARD_TYPE   0x1
+#define INVALID_NUM_PORTS    0x2
+#define INVALID_MEM_BASE     0x4
+#define INVALID_PORT_BASE    0x8
+#define INVALID_BOARD_STATUS 0x10
+#define INVALID_ALTPIN       0x20
+
+/* End code defines used for epca_setup */
+
+
+#define FEPCLR      0x00
+#define FEPMEM      0x02
+#define FEPRST      0x04
+#define FEPINT      0x08
+#define	FEPMASK     0x0e
+#define	FEPWIN      0x80
+
+#define PCXE    0
+#define PCXEVE  1
+#define PCXEM   2   
+#define EISAXEM 3
+#define PC64XE  4
+#define PCXI    5
+#define PCIXEM  7
+#define PCICX   8
+#define PCIXR   9
+#define PCIXRJ  10
+#define EPCA_NUM_TYPES 6
+
+
+static char *board_desc[] = 
+{
+	"PC/Xe",
+	"PC/Xeve",
+	"PC/Xem",
+	"EISA/Xem",
+	"PC/64Xe",
+	"PC/Xi",
+	"unknown",
+	"PCI/Xem",
+	"PCI/CX",
+	"PCI/Xr",
+	"PCI/Xrj",
+};
+
+#define STARTC      021
+#define STOPC       023
+#define IAIXON      0x2000
+
+
+#define TXSTOPPED  0x1
+#define LOWWAIT    0x2
+#define EMPTYWAIT  0x4
+#define RXSTOPPED  0x8
+#define TXBUSY     0x10
+
+#define DISABLED   0
+#define ENABLED    1
+#define OFF        0
+#define ON         1
+
+#define FEPTIMEOUT 200000  
+#define SERIAL_TYPE_INFO    3
+#define EPCA_EVENT_HANGUP   1
+#define EPCA_MAGIC          0x5c6df104L
+
+struct channel 
+{
+	long   magic;
+	struct tty_port port;
+	unsigned char boardnum;
+	unsigned char channelnum;
+	unsigned char omodem;         /* FEP output modem status     */
+	unsigned char imodem;         /* FEP input modem status      */
+	unsigned char modemfake;      /* Modem values to be forced   */
+	unsigned char modem;          /* Force values                */
+	unsigned char hflow;
+	unsigned char dsr;
+	unsigned char dcd;
+	unsigned char m_rts ; 		/* The bits used in whatever FEP */
+	unsigned char m_dcd ;		/* is indiginous to this board to */
+	unsigned char m_dsr ;		/* represent each of the physical */
+	unsigned char m_cts ;		/* handshake lines */
+	unsigned char m_ri ;
+	unsigned char m_dtr ;
+	unsigned char stopc;
+	unsigned char startc;
+	unsigned char stopca;
+	unsigned char startca;
+	unsigned char fepstopc;
+	unsigned char fepstartc;
+	unsigned char fepstopca;
+	unsigned char fepstartca;
+	unsigned char txwin;
+	unsigned char rxwin;
+	unsigned short fepiflag;
+	unsigned short fepcflag;
+	unsigned short fepoflag;
+	unsigned short txbufhead;
+	unsigned short txbufsize;
+	unsigned short rxbufhead;
+	unsigned short rxbufsize;
+	int    close_delay;
+	unsigned long  event;
+	uint   dev;
+	unsigned long  statusflags;
+	unsigned long  c_iflag;
+	unsigned long  c_cflag;
+	unsigned long  c_lflag;
+	unsigned long  c_oflag;
+	unsigned char __iomem *txptr;
+	unsigned char __iomem *rxptr;
+	struct board_info           *board;
+	struct board_chan	    __iomem *brdchan;
+	struct digi_struct          digiext;
+	struct work_struct          tqueue;
+	struct global_data 	    __iomem *mailbox;
+};
+
+struct board_info	
+{
+	unsigned char status;
+	unsigned char type;
+	unsigned char altpin;
+	unsigned short numports;
+	unsigned long port;
+	unsigned long membase;
+	void __iomem *re_map_port;
+	void __iomem *re_map_membase;
+	unsigned long  memory_seg;
+	void ( * memwinon )	(struct board_info *, unsigned int) ;
+	void ( * memwinoff ) 	(struct board_info *, unsigned int) ;
+	void ( * globalwinon )	(struct channel *) ;
+	void ( * txwinon ) 	(struct channel *) ;
+	void ( * rxwinon )	(struct channel *) ;
+	void ( * memoff )	(struct channel *) ;
+	void ( * assertgwinon )	(struct channel *) ;
+	void ( * assertmemoff )	(struct channel *) ;
+	unsigned char poller_inhibited ;
+};
+
diff --git a/drivers/staging/tty/epcaconfig.h b/drivers/staging/tty/epcaconfig.h
new file mode 100644
index 0000000..55dec06
--- /dev/null
+++ b/drivers/staging/tty/epcaconfig.h
@@ -0,0 +1,7 @@
+#define NUMCARDS 0
+#define NBDEVS 0
+
+struct board_info static_boards[NUMCARDS]={
+};
+
+/* DO NOT HAND EDIT THIS FILE! */
diff --git a/drivers/staging/tty/ip2/Makefile b/drivers/staging/tty/ip2/Makefile
new file mode 100644
index 0000000..7b78e0d
--- /dev/null
+++ b/drivers/staging/tty/ip2/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the Computone IntelliPort Plus Driver
+#
+
+obj-$(CONFIG_COMPUTONE)         += ip2.o
+
+ip2-y			:= ip2main.o
+
diff --git a/drivers/staging/tty/ip2/i2cmd.c b/drivers/staging/tty/ip2/i2cmd.c
new file mode 100644
index 0000000..e7af647
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2cmd.c
@@ -0,0 +1,210 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Definition table for In-line and Bypass commands. Applicable
+*                only when the standard loadware is active. (This is included
+*                source code, not a separate compilation module.)
+*
+*******************************************************************************/
+
+//------------------------------------------------------------------------------
+//
+// Revision History:
+//
+// 10 October 1991   MAG First Draft
+//  7 November 1991  MAG Reflects additional commands.
+// 24 February 1992  MAG Additional commands for 1.4.x loadware
+// 11 March 1992     MAG Additional commands
+// 30 March 1992     MAG Additional command: CMD_DSS_NOW
+// 18 May 1992       MAG Discovered commands 39 & 40 must be at the end of a
+//                       packet: affects implementation.
+//------------------------------------------------------------------------------
+
+//************
+//* Includes *
+//************
+
+#include "i2cmd.h"   /* To get some bit-defines */
+
+//------------------------------------------------------------------------------
+// Here is the table of global arrays which represent each type of command
+// supported in the IntelliPort standard loadware. See also i2cmd.h
+// for a more complete explanation of what is going on.
+//------------------------------------------------------------------------------
+
+// Here are the various globals: note that the names are not used except through
+// the macros defined in i2cmd.h. Also note that although they are character
+// arrays here (for extendability) they are cast to structure pointers in the
+// i2cmd.h macros. See i2cmd.h for flags definitions.
+
+//                     Length Flags Command
+static UCHAR ct02[] = { 1, BTH,     0x02                     }; // DTR UP
+static UCHAR ct03[] = { 1, BTH,     0x03                     }; // DTR DN
+static UCHAR ct04[] = { 1, BTH,     0x04                     }; // RTS UP
+static UCHAR ct05[] = { 1, BTH,     0x05                     }; // RTS DN
+static UCHAR ct06[] = { 1, BYP,     0x06                     }; // START FL
+static UCHAR ct07[] = { 2, BTH,     0x07,0                   }; // BAUD
+static UCHAR ct08[] = { 2, BTH,     0x08,0                   }; // BITS
+static UCHAR ct09[] = { 2, BTH,     0x09,0                   }; // STOP
+static UCHAR ct10[] = { 2, BTH,     0x0A,0                   }; // PARITY
+static UCHAR ct11[] = { 2, BTH,     0x0B,0                   }; // XON
+static UCHAR ct12[] = { 2, BTH,     0x0C,0                   }; // XOFF
+static UCHAR ct13[] = { 1, BTH,     0x0D                     }; // STOP FL
+static UCHAR ct14[] = { 1, BYP|VIP, 0x0E                     }; // ACK HOTK
+//static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0                   }; // IRQ SET
+static UCHAR ct16[] = { 2, INL,     0x10,0                   }; // IXONOPTS
+static UCHAR ct17[] = { 2, INL,     0x11,0                   }; // OXONOPTS
+static UCHAR ct18[] = { 1, INL,     0x12                     }; // CTSENAB
+static UCHAR ct19[] = { 1, BTH,     0x13                     }; // CTSDSAB
+static UCHAR ct20[] = { 1, INL,     0x14                     }; // DCDENAB
+static UCHAR ct21[] = { 1, BTH,     0x15                     }; // DCDDSAB
+static UCHAR ct22[] = { 1, BTH,     0x16                     }; // DSRENAB
+static UCHAR ct23[] = { 1, BTH,     0x17                     }; // DSRDSAB
+static UCHAR ct24[] = { 1, BTH,     0x18                     }; // RIENAB
+static UCHAR ct25[] = { 1, BTH,     0x19                     }; // RIDSAB
+static UCHAR ct26[] = { 2, BTH,     0x1A,0                   }; // BRKENAB
+static UCHAR ct27[] = { 1, BTH,     0x1B                     }; // BRKDSAB
+//static UCHAR ct28[]={ 2, BTH,     0x1C,0                   }; // MAXBLOKSIZE
+//static UCHAR ct29[]={ 2, 0,       0x1D,0                   }; // reserved
+static UCHAR ct30[] = { 1, INL,     0x1E                     }; // CTSFLOWENAB
+static UCHAR ct31[] = { 1, INL,     0x1F                     }; // CTSFLOWDSAB
+static UCHAR ct32[] = { 1, INL,     0x20                     }; // RTSFLOWENAB
+static UCHAR ct33[] = { 1, INL,     0x21                     }; // RTSFLOWDSAB
+static UCHAR ct34[] = { 2, BTH,     0x22,0                   }; // ISTRIPMODE
+static UCHAR ct35[] = { 2, BTH|END, 0x23,0                   }; // SENDBREAK
+static UCHAR ct36[] = { 2, BTH,     0x24,0                   }; // SETERRMODE
+//static UCHAR ct36a[]={ 3, INL,    0x24,0,0                 }; // SET_REPLACE
+
+// The following is listed for completeness, but should never be sent directly
+// by user-level code. It is sent only by library routines in response to data
+// movement.
+//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0             }; // FLOW PACKET
+
+// Back to normal
+//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ
+//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0                 }; // OPOSTON
+//static UCHAR ct40[]={ 1, BTH|END, 0x28                     }; // OPOSTOFF
+static UCHAR ct41[] = { 1, BYP,     0x29                     }; // RESUME
+//static UCHAR ct42[]={ 2, BTH,     0x2A,0                   }; // TXBAUD
+//static UCHAR ct43[]={ 2, BTH,     0x2B,0                   }; // RXBAUD
+//static UCHAR ct44[]={ 2, BTH,     0x2C,0                   }; // MS PING
+//static UCHAR ct45[]={ 1, BTH,     0x2D                     }; // HOTENAB
+//static UCHAR ct46[]={ 1, BTH,     0x2E                     }; // HOTDSAB
+//static UCHAR ct47[]={ 7, BTH,     0x2F,0,0,0,0,0,0         }; // UNIX FLAGS
+//static UCHAR ct48[]={ 1, BTH,     0x30                     }; // DSRFLOWENAB
+//static UCHAR ct49[]={ 1, BTH,     0x31                     }; // DSRFLOWDSAB
+//static UCHAR ct50[]={ 1, BTH,     0x32                     }; // DTRFLOWENAB
+//static UCHAR ct51[]={ 1, BTH,     0x33                     }; // DTRFLOWDSAB
+//static UCHAR ct52[]={ 1, BTH,     0x34                     }; // BAUDTABRESET
+//static UCHAR ct53[] = { 3, BTH,     0x35,0,0                 }; // BAUDREMAP
+static UCHAR ct54[] = { 3, BTH,     0x36,0,0                 }; // CUSTOMBAUD1
+static UCHAR ct55[] = { 3, BTH,     0x37,0,0                 }; // CUSTOMBAUD2
+static UCHAR ct56[] = { 2, BTH|END, 0x38,0                   }; // PAUSE
+static UCHAR ct57[] = { 1, BYP,     0x39                     }; // SUSPEND
+static UCHAR ct58[] = { 1, BYP,     0x3A                     }; // UNSUSPEND
+static UCHAR ct59[] = { 2, BTH,     0x3B,0                   }; // PARITYCHK
+static UCHAR ct60[] = { 1, INL|VIP, 0x3C                     }; // BOOKMARKREQ
+//static UCHAR ct61[]={ 2, BTH,     0x3D,0                   }; // INTERNALLOOP
+//static UCHAR ct62[]={ 2, BTH,     0x3E,0                   }; // HOTKTIMEOUT
+static UCHAR ct63[] = { 2, INL,     0x3F,0                   }; // SETTXON
+static UCHAR ct64[] = { 2, INL,     0x40,0                   }; // SETTXOFF
+//static UCHAR ct65[]={ 2, BTH,     0x41,0                   }; // SETAUTORTS
+//static UCHAR ct66[]={ 2, BTH,     0x42,0                   }; // SETHIGHWAT
+//static UCHAR ct67[]={ 2, BYP,     0x43,0                   }; // STARTSELFL
+//static UCHAR ct68[]={ 2, INL,     0x44,0                   }; // ENDSELFL
+//static UCHAR ct69[]={ 1, BYP,     0x45                     }; // HWFLOW_OFF
+//static UCHAR ct70[]={ 1, BTH,     0x46                     }; // ODSRFL_ENAB
+//static UCHAR ct71[]={ 1, BTH,     0x47                     }; // ODSRFL_DSAB
+//static UCHAR ct72[]={ 1, BTH,     0x48                     }; // ODCDFL_ENAB
+//static UCHAR ct73[]={ 1, BTH,     0x49                     }; // ODCDFL_DSAB
+//static UCHAR ct74[]={ 2, BTH,     0x4A,0                   }; // LOADLEVEL
+//static UCHAR ct75[]={ 2, BTH,     0x4B,0                   }; // STATDATA
+//static UCHAR ct76[]={ 1, BYP,     0x4C                     }; // BREAK_ON
+//static UCHAR ct77[]={ 1, BYP,     0x4D                     }; // BREAK_OFF
+//static UCHAR ct78[]={ 1, BYP,     0x4E                     }; // GETFC
+static UCHAR ct79[] = { 2, BYP,     0x4F,0                   }; // XMIT_NOW
+//static UCHAR ct80[]={ 4, BTH,     0x50,0,0,0               }; // DIVISOR_LATCH
+//static UCHAR ct81[]={ 1, BYP,     0x51                     }; // GET_STATUS
+//static UCHAR ct82[]={ 1, BYP,     0x52                     }; // GET_TXCNT
+//static UCHAR ct83[]={ 1, BYP,     0x53                     }; // GET_RXCNT
+//static UCHAR ct84[]={ 1, BYP,     0x54                     }; // GET_BOXIDS
+//static UCHAR ct85[]={10, BYP,     0x55,0,0,0,0,0,0,0,0,0   }; // ENAB_MULT
+//static UCHAR ct86[]={ 2, BTH,     0x56,0                   }; // RCV_ENABLE
+static UCHAR ct87[] = { 1, BYP,     0x57                     }; // HW_TEST
+//static UCHAR ct88[]={ 3, BTH,     0x58,0,0                 }; // RCV_THRESHOLD
+//static UCHAR ct90[]={ 3, BYP,     0x5A,0,0                 }; // Set SILO
+//static UCHAR ct91[]={ 2, BYP,     0x5B,0                   }; // timed break
+
+// Some composite commands as well
+//static UCHAR cc01[]={ 2, BTH,     0x02,0x04                }; // DTR & RTS UP
+//static UCHAR cc02[]={ 2, BTH,     0x03,0x05                }; // DTR & RTS DN
+
+//********
+//* Code *
+//********
+
+//******************************************************************************
+// Function:   i2cmdUnixFlags(iflag, cflag, lflag)
+// Parameters: Unix tty flags
+//
+// Returns:    Pointer to command structure
+//
+// Description:
+//
+// This routine sets the parameters of command 47 and returns a pointer to the
+// appropriate structure.
+//******************************************************************************
+#if 0
+cmdSyntaxPtr
+i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
+{
+	cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47;
+
+	pCM->cmd[1] = (unsigned char)  iflag;
+	pCM->cmd[2] = (unsigned char) (iflag >> 8);
+	pCM->cmd[3] = (unsigned char)  cflag;
+	pCM->cmd[4] = (unsigned char) (cflag >> 8);
+	pCM->cmd[5] = (unsigned char)  lflag;
+	pCM->cmd[6] = (unsigned char) (lflag >> 8);
+	return pCM;
+}
+#endif  /*  0  */
+
+//******************************************************************************
+// Function:   i2cmdBaudDef(which, rate)
+// Parameters: ?
+//
+// Returns:    Pointer to command structure
+//
+// Description:
+//
+// This routine sets the parameters of commands 54 or 55 (according to the
+// argument which), and returns a pointer to the appropriate structure.
+//******************************************************************************
+static cmdSyntaxPtr
+i2cmdBaudDef(int which, unsigned short rate)
+{
+	cmdSyntaxPtr pCM;
+
+	switch(which)
+	{
+	case 1:
+		pCM = (cmdSyntaxPtr) ct54;
+		break;
+	default:
+	case 2:
+		pCM = (cmdSyntaxPtr) ct55;
+		break;
+	}
+	pCM->cmd[1] = (unsigned char) rate;
+	pCM->cmd[2] = (unsigned char) (rate >> 8);
+	return pCM;
+}
+
diff --git a/drivers/staging/tty/ip2/i2cmd.h b/drivers/staging/tty/ip2/i2cmd.h
new file mode 100644
index 0000000..29277ec
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2cmd.h
@@ -0,0 +1,630 @@
+/*******************************************************************************
+*
+*   (c) 1999 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Definitions and support for In-line and Bypass commands.
+*                Applicable only when the standard loadware is active.
+*
+*******************************************************************************/
+//------------------------------------------------------------------------------
+// Revision History:
+//
+// 10 October 1991   MAG First Draft
+//  7 November 1991  MAG Reflects some new commands
+// 20 February 1992  MAG CMD_HOTACK corrected: no argument.
+// 24 February 1992  MAG Support added for new commands for 1.4.x loadware.
+// 11 March 1992     MAG Additional commands.
+// 16 March 1992     MAG Additional commands.
+// 30 March 1992     MAG Additional command: CMD_DSS_NOW
+// 18 May   1992     MAG Changed CMD_OPOST
+//
+//------------------------------------------------------------------------------
+#ifndef I2CMD_H      // To prevent multiple includes
+#define I2CMD_H   1
+
+#include "ip2types.h"
+
+// This module is designed to provide a uniform method of sending commands to
+// the board through command packets. The difficulty is, some commands take
+// parameters, others do not. Furthermore, it is often useful to send several
+// commands to the same channel as part of the same packet. (See also i2pack.h.)
+//
+// This module is designed so that the caller should not be responsible for
+// remembering the exact syntax of each command, or at least so that the
+// compiler could check things somewhat. I'll explain as we go...
+//
+// First, a structure which can embody the syntax of each type of command.
+//
+typedef struct _cmdSyntax
+{
+	UCHAR length;   // Number of bytes in the command
+	UCHAR flags;    // Information about the command (see below)
+
+	// The command and its parameters, which may be of arbitrary length. Don't
+	// worry yet how the parameters will be initialized; macros later take care
+	// of it. Also, don't worry about the arbitrary length issue; this structure
+	// is never used to allocate space (see i2cmd.c).
+	UCHAR cmd[2];
+} cmdSyntax, *cmdSyntaxPtr;
+
+// Bit assignments for flags
+
+#define INL 1           // Set if suitable for inline commands
+#define BYP 2           // Set if suitable for bypass commands
+#define BTH (INL|BYP)   // suitable for either!
+#define END 4           // Set if this must be the last command in a block
+#define VIP 8           // Set if this command is special in some way and really
+						// should only be sent from the library-level and not
+						// directly from user-level
+#define VAR 0x10        // This command is of variable length!
+
+// Declarations for the global arrays used to bear the commands and their
+// arguments.
+//
+// Note: Since these are globals and the arguments might change, it is important
+// that the library routine COPY these into buffers from whence they would be
+// sent, rather than merely storing the pointers. In multi-threaded
+// environments, important that the copy should obtain before any context switch
+// is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND
+// MORE THAN ONCE WITH THE SAME PARAMETERS in the same call.
+//
+static UCHAR ct02[];
+static UCHAR ct03[];
+static UCHAR ct04[];
+static UCHAR ct05[];
+static UCHAR ct06[];
+static UCHAR ct07[];
+static UCHAR ct08[];
+static UCHAR ct09[];
+static UCHAR ct10[];
+static UCHAR ct11[];
+static UCHAR ct12[];
+static UCHAR ct13[];
+static UCHAR ct14[];
+static UCHAR ct15[];
+static UCHAR ct16[];
+static UCHAR ct17[];
+static UCHAR ct18[];
+static UCHAR ct19[];
+static UCHAR ct20[];
+static UCHAR ct21[];
+static UCHAR ct22[];
+static UCHAR ct23[];
+static UCHAR ct24[];
+static UCHAR ct25[];
+static UCHAR ct26[];
+static UCHAR ct27[];
+static UCHAR ct28[];
+static UCHAR ct29[];
+static UCHAR ct30[];
+static UCHAR ct31[];
+static UCHAR ct32[];
+static UCHAR ct33[];
+static UCHAR ct34[];
+static UCHAR ct35[];
+static UCHAR ct36[];
+static UCHAR ct36a[];
+static UCHAR ct41[];
+static UCHAR ct42[];
+static UCHAR ct43[];
+static UCHAR ct44[];
+static UCHAR ct45[];
+static UCHAR ct46[];
+static UCHAR ct48[];
+static UCHAR ct49[];
+static UCHAR ct50[];
+static UCHAR ct51[];
+static UCHAR ct52[];
+static UCHAR ct56[];
+static UCHAR ct57[];
+static UCHAR ct58[];
+static UCHAR ct59[];
+static UCHAR ct60[];
+static UCHAR ct61[];
+static UCHAR ct62[];
+static UCHAR ct63[];
+static UCHAR ct64[];
+static UCHAR ct65[];
+static UCHAR ct66[];
+static UCHAR ct67[];
+static UCHAR ct68[];
+static UCHAR ct69[];
+static UCHAR ct70[];
+static UCHAR ct71[];
+static UCHAR ct72[];
+static UCHAR ct73[];
+static UCHAR ct74[];
+static UCHAR ct75[];
+static UCHAR ct76[];
+static UCHAR ct77[];
+static UCHAR ct78[];
+static UCHAR ct79[];
+static UCHAR ct80[];
+static UCHAR ct81[];
+static UCHAR ct82[];
+static UCHAR ct83[];
+static UCHAR ct84[];
+static UCHAR ct85[];
+static UCHAR ct86[];
+static UCHAR ct87[];
+static UCHAR ct88[];
+static UCHAR ct89[];
+static UCHAR ct90[];
+static UCHAR ct91[];
+static UCHAR cc01[];
+static UCHAR cc02[];
+
+// Now, refer to i2cmd.c, and see the character arrays defined there. They are
+// cast here to cmdSyntaxPtr.
+//
+// There are library functions for issuing bypass or inline commands. These
+// functions take one or more arguments of the type cmdSyntaxPtr. The routine
+// then can figure out how long each command is supposed to be and easily add it
+// to the list.
+//
+// For ease of use, we define manifests which return pointers to appropriate
+// cmdSyntaxPtr things. But some commands also take arguments. If a single
+// argument is used, we define a macro which performs the single assignment and
+// (through the expedient of a comma expression) references the appropriate
+// pointer. For commands requiring several arguments, we actually define a
+// function to perform the assignments.
+
+#define CMD_DTRUP	(cmdSyntaxPtr)(ct02)	// Raise DTR
+#define CMD_DTRDN	(cmdSyntaxPtr)(ct03)	// Lower DTR
+#define CMD_RTSUP	(cmdSyntaxPtr)(ct04)	// Raise RTS
+#define CMD_RTSDN	(cmdSyntaxPtr)(ct05)	// Lower RTS
+#define CMD_STARTFL	(cmdSyntaxPtr)(ct06)	// Start Flushing Data
+
+#define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01)	// Raise DTR and RTS
+#define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02)	// Lower DTR and RTS
+
+// Set Baud Rate for transmit and receive
+#define CMD_SETBAUD(arg) \
+	(((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07))
+
+#define CBR_50       1
+#define CBR_75       2
+#define CBR_110      3
+#define CBR_134      4
+#define CBR_150      5
+#define CBR_200      6
+#define CBR_300      7
+#define CBR_600      8
+#define CBR_1200     9
+#define CBR_1800     10
+#define CBR_2400     11
+#define CBR_4800     12
+#define CBR_9600     13
+#define CBR_19200    14
+#define CBR_38400    15
+#define CBR_2000     16
+#define CBR_3600     17
+#define CBR_7200     18
+#define CBR_56000    19
+#define CBR_57600    20
+#define CBR_64000    21
+#define CBR_76800    22
+#define CBR_115200   23
+#define CBR_C1       24    // Custom baud rate 1
+#define CBR_C2       25    // Custom baud rate 2
+#define CBR_153600   26
+#define CBR_230400   27
+#define CBR_307200   28
+#define CBR_460800   29
+#define CBR_921600   30
+
+// Set Character size
+//
+#define CMD_SETBITS(arg) \
+	(((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08))
+
+#define CSZ_5  0
+#define CSZ_6  1
+#define CSZ_7  2
+#define CSZ_8  3
+
+// Set number of stop bits
+//
+#define CMD_SETSTOP(arg) \
+	(((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09))
+
+#define CST_1  0
+#define CST_15 1  // 1.5 stop bits
+#define CST_2  2
+
+// Set parity option
+//
+#define CMD_SETPAR(arg) \
+	(((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10))
+
+#define CSP_NP 0  // no parity
+#define CSP_OD 1  // odd parity
+#define CSP_EV 2  // Even parity
+#define CSP_SP 3  // Space parity
+#define CSP_MK 4  // Mark parity
+
+// Define xon char for transmitter flow control
+//
+#define CMD_DEF_IXON(arg) \
+	(((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11))
+
+// Define xoff char for transmitter flow control
+//
+#define CMD_DEF_IXOFF(arg) \
+	(((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12))
+
+#define CMD_STOPFL   (cmdSyntaxPtr)(ct13) // Stop Flushing data
+
+// Acknowledge receipt of hotkey signal
+//
+#define CMD_HOTACK   (cmdSyntaxPtr)(ct14)
+
+// Define irq level to use. Should actually be sent by library-level code, not
+// directly from user...
+//
+#define CMDVALUE_IRQ 15 // For library use at initialization. Until this command
+						// is sent, board processing doesn't really start.
+#define CMD_SET_IRQ(arg) \
+	(((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15))
+
+#define CIR_POLL  0  // No IRQ - Poll
+#define CIR_3     3  // IRQ 3
+#define CIR_4     4  // IRQ 4
+#define CIR_5     5  // IRQ 5
+#define CIR_7     7  // IRQ 7
+#define CIR_10    10 // IRQ 10
+#define CIR_11    11 // IRQ 11
+#define CIR_12    12 // IRQ 12
+#define CIR_15    15 // IRQ 15
+
+// Select transmit flow xon/xoff options
+//
+#define CMD_IXON_OPT(arg) \
+	(((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16))
+
+#define CIX_NONE  0  // Incoming Xon/Xoff characters not special
+#define CIX_XON   1  // Xoff disable, Xon enable
+#define CIX_XANY  2  // Xoff disable, any key enable
+
+// Select receive flow xon/xoff options
+//
+#define CMD_OXON_OPT(arg) \
+	(((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17))
+
+#define COX_NONE  0  // Don't send Xon/Xoff
+#define COX_XON   1  // Send xon/xoff to start/stop incoming data
+
+
+#define CMD_CTS_REP  (cmdSyntaxPtr)(ct18) // Enable  CTS reporting
+#define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting
+
+#define CMD_DCD_REP  (cmdSyntaxPtr)(ct20) // Enable  DCD reporting
+#define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting
+
+#define CMD_DSR_REP  (cmdSyntaxPtr)(ct22) // Enable  DSR reporting
+#define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting
+
+#define CMD_RI_REP   (cmdSyntaxPtr)(ct24) // Enable  RI  reporting
+#define CMD_RI_NREP  (cmdSyntaxPtr)(ct25) // Disable RI  reporting
+
+// Enable break reporting and select style
+//
+#define CMD_BRK_REP(arg) \
+	(((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26))
+
+#define CBK_STAT     0x00  // Report breaks as a status (exception,irq)
+#define CBK_NULL     0x01  // Report breaks as a good null
+#define CBK_STAT_SEQ 0x02  // Report breaks as a status AND as in-band character
+                           //  sequence FFh, 01h, 10h
+#define CBK_SEQ      0x03  // Report breaks as the in-band 
+						   //sequence FFh, 01h, 10h ONLY.
+#define CBK_FLSH     0x04  // if this bit set also flush input data
+#define CBK_POSIX    0x08  // if this bit set report as FF,0,0 sequence
+#define CBK_SINGLE   0x10  // if this bit set with CBK_SEQ or CBK_STAT_SEQ
+						   //then reports single null instead of triple
+
+#define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting
+
+// Specify maximum block size for received data
+//
+#define CMD_MAX_BLOCK(arg) \
+	(((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28))
+
+// -- COMMAND 29 is reserved --
+
+#define CMD_CTSFL_ENAB  (cmdSyntaxPtr)(ct30) // Enable  CTS flow control
+#define CMD_CTSFL_DSAB  (cmdSyntaxPtr)(ct31) // Disable CTS flow control
+#define CMD_RTSFL_ENAB  (cmdSyntaxPtr)(ct32) // Enable  RTS flow control
+#define CMD_RTSFL_DSAB  (cmdSyntaxPtr)(ct33) // Disable RTS flow control
+
+// Specify istrip option
+//
+#define CMD_ISTRIP_OPT(arg) \
+	(((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34))
+
+#define CIS_NOSTRIP  0  // Strip characters to character size
+#define CIS_STRIP    1  // Strip any 8-bit characters to 7 bits
+
+// Send a break of arg milliseconds
+//
+#define CMD_SEND_BRK(arg) \
+	(((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35))
+
+// Set error reporting mode
+//
+#define CMD_SET_ERROR(arg) \
+	(((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36))
+
+#define CSE_ESTAT 0  // Report error in a status packet
+#define CSE_NOREP 1  // Treat character as though it were good
+#define CSE_DROP  2  // Discard the character
+#define CSE_NULL  3  // Replace with a null
+#define CSE_MARK  4  // Replace with a 3-character sequence (as Unix)
+
+#define CSE_REPLACE  0x8	// Replace the errored character with the
+							// replacement character defined here
+
+#define CSE_STAT_REPLACE   0x18	// Replace the errored character with the
+								// replacement character defined here AND
+								// report the error as a status packet (as in
+								// CSE_ESTAT).
+
+
+// COMMAND 37, to send flow control packets, is handled only by low-level
+// library code in response to data movement and shouldn't ever be sent by the
+// user code. See i2pack.h and the body of i2lib.c for details.
+
+// Enable on-board post-processing, using options given in oflag argument.
+// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command
+// because the loadware does not permit sending back-to-back CMD_OPOST_ON
+// commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that
+// CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a
+// solo packet). This means the caller must specify separately CMD_OPOST_OFF,
+// CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure
+// each gets a separate packet. Extra CMD_OPOST_OFF's are always ok.
+//
+#define CMD_OPOST_ON(oflag)   \
+	(*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \
+		(cmdSyntaxPtr)(ct39))
+
+#define CMD_OPOST_OFF   (cmdSyntaxPtr)(ct40) // Disable on-board post-proc
+
+#define CMD_RESUME   (cmdSyntaxPtr)(ct41)	// Resume: behave as though an XON
+											// were received;
+
+// Set Transmit baud rate (see command 7 for arguments)
+//
+#define CMD_SETBAUD_TX(arg) \
+	(((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42))
+
+// Set Receive baud rate (see command 7 for arguments)
+//
+#define CMD_SETBAUD_RX(arg) \
+	(((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43))
+
+// Request interrupt from board each arg milliseconds. Interrupt will specify
+// "received data", even though there may be no data present. If arg == 0,
+// disables any such interrupts.
+//
+#define CMD_PING_REQ(arg) \
+	(((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44))
+
+#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
+#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
+
+#if 0
+// COMMAND 47: Send Protocol info via Unix flags:
+// iflag = Unix tty t_iflag
+// cflag = Unix tty t_cflag
+// lflag = Unix tty t_lflag
+// See System V Unix/Xenix documentation for the meanings of the bit fields
+// within these flags
+//
+#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
+#endif  /*  0  */
+
+#define CMD_DSRFL_ENAB  (cmdSyntaxPtr)(ct48) // Enable  DSR receiver ctrl
+#define CMD_DSRFL_DSAB  (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
+#define CMD_DTRFL_ENAB  (cmdSyntaxPtr)(ct50) // Enable  DTR flow control
+#define CMD_DTRFL_DSAB  (cmdSyntaxPtr)(ct51) // Disable DTR flow control
+#define CMD_BAUD_RESET  (cmdSyntaxPtr)(ct52) // Reset baudrate table
+
+// COMMAND 54: Define custom rate #1
+// rate = (short) 1/10 of the desired baud rate
+//
+#define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate)
+
+// COMMAND 55: Define custom rate #2
+// rate = (short) 1/10 of the desired baud rate
+//
+#define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate)
+
+// Pause arg hundredths of seconds. (Note, this is NOT milliseconds.)
+//
+#define CMD_PAUSE(arg) \
+	(((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56))
+
+#define CMD_SUSPEND     (cmdSyntaxPtr)(ct57) // Suspend output
+#define CMD_UNSUSPEND   (cmdSyntaxPtr)(ct58) // Un-Suspend output
+
+// Set parity-checking options
+//
+#define CMD_PARCHK(arg) \
+	(((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59))
+
+#define CPK_ENAB  0     // Enable parity checking on input
+#define CPK_DSAB  1     // Disable parity checking on input
+
+#define CMD_BMARK_REQ   (cmdSyntaxPtr)(ct60) // Bookmark request
+
+
+// Enable/Disable internal loopback mode
+//
+#define CMD_INLOOP(arg) \
+	(((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61))
+
+#define CIN_DISABLE  0  // Normal operation (default)
+#define CIN_ENABLE   1  // Internal (local) loopback
+#define CIN_REMOTE   2  // Remote loopback
+
+// Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0
+// --> no timeout: wait forever.
+//
+#define CMD_HOT_TIME(arg) \
+	(((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62))
+
+
+// Define (outgoing) xon for receive flow control
+//
+#define CMD_DEF_OXON(arg) \
+	(((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63))
+
+// Define (outgoing) xoff for receiver flow control
+//
+#define CMD_DEF_OXOFF(arg) \
+	(((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64))
+
+// Enable/Disable RTS on transmit (1/2 duplex-style)
+//
+#define CMD_RTS_XMIT(arg) \
+	(((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65))
+
+#define CHD_DISABLE  0
+#define CHD_ENABLE   1
+
+// Set high-water-mark level (debugging use only)
+//
+#define CMD_SETHIGHWAT(arg) \
+	(((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66))
+
+// Start flushing tagged data (tag = 0-14)
+//
+#define CMD_START_SELFL(tag) \
+	(((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67))
+
+// End flushing tagged data (tag = 0-14)
+//
+#define CMD_END_SELFL(tag) \
+	(((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68))
+
+#define CMD_HWFLOW_OFF  (cmdSyntaxPtr)(ct69) // Disable HW TX flow control
+#define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c
+#define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c
+#define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c
+#define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c
+
+// Set transmit interrupt load level. Count should be an even value 2-12
+//
+#define CMD_LOADLEVEL(count) \
+	(((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74))
+
+// If reporting DSS changes, map to character sequence FFh, 2, MSR
+//
+#define CMD_STATDATA(arg) \
+	(((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75))
+
+#define CSTD_DISABLE// Report DSS changes as status packets only (default)
+#define CSTD_ENABLE	// Report DSS changes as in-band data sequence as well as
+					// by status packet.
+
+#define CMD_BREAK_ON    (cmdSyntaxPtr)(ct76)// Set break and stop xmit
+#define CMD_BREAK_OFF   (cmdSyntaxPtr)(ct77)// End break and restart xmit
+#define CMD_GETFC       (cmdSyntaxPtr)(ct78)// Request for flow control packet
+											// from board.
+
+// Transmit this character immediately
+//
+#define CMD_XMIT_NOW(ch) \
+	(((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79))
+
+// Set baud rate via "divisor latch"
+//
+#define CMD_DIVISOR_LATCH(which,value) \
+			(((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \
+			*(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \
+			(cmdSyntaxPtr)(ct80))
+
+#define CDL_RX 1	// Set receiver rate
+#define CDL_TX 2	// Set transmit rate
+					// (CDL_TX | CDL_RX) Set both rates
+
+// Request for special diagnostic status pkt from the board.
+//
+#define CMD_GET_STATUS (cmdSyntaxPtr)(ct81)
+
+// Request time-stamped transmit character count packet.
+//
+#define CMD_GET_TXCNT  (cmdSyntaxPtr)(ct82)
+
+// Request time-stamped receive character count packet.
+//
+#define CMD_GET_RXCNT  (cmdSyntaxPtr)(ct83)
+
+// Request for box/board I.D. packet.
+#define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84)
+
+// Enable or disable multiple channels according to bit-mapped ushorts box 1-4
+//
+#define CMD_ENAB_MULT(enable, box1, box2, box3, box4)    \
+			(((cmdSytaxPtr)(ct85))->cmd[1] = (enable),            \
+			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \
+			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \
+			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \
+			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \
+			(cmdSyntaxPtr)(ct85))
+
+#define CEM_DISABLE  0
+#define CEM_ENABLE   1
+
+// Enable or disable receiver or receiver interrupts (default both enabled)
+//
+#define CMD_RCV_ENABLE(ch) \
+	(((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86))
+
+#define CRE_OFF      0  // Disable the receiver
+#define CRE_ON       1  // Enable the receiver
+#define CRE_INTOFF   2  // Disable receiver interrupts (to loadware)
+#define CRE_INTON    3  // Enable receiver interrupts (to loadware)
+
+// Starts up a hardware test process, which runs transparently, and sends a
+// STAT_HWFAIL packet in case a hardware failure is detected.
+//
+#define CMD_HW_TEST  (cmdSyntaxPtr)(ct87)
+
+// Change receiver threshold and timeout value:
+// Defaults: timeout = 20mS
+// threshold count = 8 when DTRflow not in use,
+// threshold count = 5 when DTRflow in use.
+//
+#define CMD_RCV_THRESHOLD(count,ms) \
+			(((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \
+			((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \
+			(cmdSyntaxPtr)(ct88))
+
+// Makes the loadware report DSS signals for this channel immediately.
+//
+#define CMD_DSS_NOW (cmdSyntaxPtr)(ct89)
+	
+// Set the receive silo parameters 
+// 	timeout is ms idle wait until delivery       (~VTIME)
+// 	threshold is max characters cause interrupt  (~VMIN)
+//
+#define CMD_SET_SILO(timeout,threshold) \
+			(((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \
+			((cmdSyntaxPtr)(ct90))->cmd[2]  = (threshold), \
+			(cmdSyntaxPtr)(ct90))
+
+// Set timed break in decisecond (1/10s)
+//
+#define CMD_LBREAK(ds) \
+	(((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66))
+
+
+
+#endif // I2CMD_H
diff --git a/drivers/staging/tty/ip2/i2ellis.c b/drivers/staging/tty/ip2/i2ellis.c
new file mode 100644
index 0000000..29db44d
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2ellis.c
@@ -0,0 +1,1403 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Low-level interface code for the device driver
+*                (This is included source code, not a separate compilation
+*                module.)
+*
+*******************************************************************************/
+//---------------------------------------------
+// Function declarations private to this module
+//---------------------------------------------
+// Functions called only indirectly through i2eBordStr entries.
+
+static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int);
+static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int);
+static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int);
+static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int);
+
+static unsigned short iiReadWord16(i2eBordStrPtr);
+static unsigned short iiReadWord8(i2eBordStrPtr);
+static void iiWriteWord16(i2eBordStrPtr, unsigned short);
+static void iiWriteWord8(i2eBordStrPtr, unsigned short);
+
+static int iiWaitForTxEmptyII(i2eBordStrPtr, int);
+static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int);
+static int iiTxMailEmptyII(i2eBordStrPtr);
+static int iiTxMailEmptyIIEX(i2eBordStrPtr);
+static int iiTrySendMailII(i2eBordStrPtr, unsigned char);
+static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char);
+
+static unsigned short iiGetMailII(i2eBordStrPtr);
+static unsigned short iiGetMailIIEX(i2eBordStrPtr);
+
+static void iiEnableMailIrqII(i2eBordStrPtr);
+static void iiEnableMailIrqIIEX(i2eBordStrPtr);
+static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
+static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
+
+static void ii2Nop(void);
+
+//***************
+//* Static Data *
+//***************
+
+static int ii2Safe;         // Safe I/O address for delay routine
+
+static int iiDelayed;	// Set when the iiResetDelay function is
+							// called. Cleared when ANY board is reset.
+static DEFINE_RWLOCK(Dl_spinlock);
+
+//********
+//* Code *
+//********
+
+//=======================================================
+// Initialization Routines
+//
+// iiSetAddress
+// iiReset
+// iiResetDelay
+// iiInitialize
+//=======================================================
+
+//******************************************************************************
+// Function:   iiSetAddress(pB, address, delay)
+// Parameters: pB      - pointer to the board structure
+//             address - the purported I/O address of the board
+//             delay   - pointer to the 1-ms delay function to use
+//                       in this and any future operations to this board
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// This routine (roughly) checks for address validity, sets the i2eValid OK and
+// sets the state to II_STATE_COLD which means that we haven't even sent a reset
+// yet.
+//
+//******************************************************************************
+static int
+iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay )
+{
+	// Should any failure occur before init is finished...
+	pB->i2eValid = I2E_INCOMPLETE;
+
+	// Cannot check upper limit except extremely: Might be microchannel
+	// Address must be on an 8-byte boundary
+
+	if ((unsigned int)address <= 0x100
+		|| (unsigned int)address >= 0xfff8
+		|| (address & 0x7)
+		)
+	{
+		I2_COMPLETE(pB, I2EE_BADADDR);
+	}
+
+	// Initialize accelerators
+	pB->i2eBase    = address;
+	pB->i2eData    = address + FIFO_DATA;
+	pB->i2eStatus  = address + FIFO_STATUS;
+	pB->i2ePointer = address + FIFO_PTR;
+	pB->i2eXMail   = address + FIFO_MAIL;
+	pB->i2eXMask   = address + FIFO_MASK;
+
+	// Initialize i/o address for ii2DelayIO
+	ii2Safe = address + FIFO_NOP;
+
+	// Initialize the delay routine
+	pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop);
+
+	pB->i2eValid = I2E_MAGIC;
+	pB->i2eState = II_STATE_COLD;
+
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiReset(pB)
+// Parameters: pB - pointer to the board structure
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Attempts to reset the board (see also i2hw.h). Normally, we would use this to
+// reset a board immediately after iiSetAddress(), but it is valid to reset a
+// board from any state, say, in order to change or re-load loadware. (Under
+// such circumstances, no reason to re-run iiSetAddress(), which is why it is a
+// separate routine and not included in this routine.
+//
+//******************************************************************************
+static int
+iiReset(i2eBordStrPtr pB)
+{
+	// Magic number should be set, else even the address is suspect
+	if (pB->i2eValid != I2E_MAGIC)
+	{
+		I2_COMPLETE(pB, I2EE_BADMAGIC);
+	}
+
+	outb(0, pB->i2eBase + FIFO_RESET);  /* Any data will do */
+	iiDelay(pB, 50);                    // Pause between resets
+	outb(0, pB->i2eBase + FIFO_RESET);  /* Second reset */
+
+	// We must wait before even attempting to read anything from the FIFO: the
+	// board's P.O.S.T may actually attempt to read and write its end of the
+	// FIFO in order to check flags, loop back (where supported), etc. On
+	// completion of this testing it would reset the FIFO, and on completion
+	// of all // P.O.S.T., write the message. We must not mistake data which
+	// might have been sent for testing as part of the reset message. To
+	// better utilize time, say, when resetting several boards, we allow the
+	// delay to be performed externally; in this way the caller can reset 
+	// several boards, delay a single time, then call the initialization
+	// routine for all.
+
+	pB->i2eState = II_STATE_RESET;
+
+	iiDelayed = 0;	// i.e., the delay routine hasn't been called since the most
+					// recent reset.
+
+	// Ensure anything which would have been of use to standard loadware is
+	// blanked out, since board has now forgotten everything!.
+
+	pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */
+	pB->i2eWaitingForEmptyFifo = 0;
+	pB->i2eOutMailWaiting = 0;
+	pB->i2eChannelPtr = NULL;
+	pB->i2eChannelCnt = 0;
+
+	pB->i2eLeadoffWord[0] = 0;
+	pB->i2eFifoInInts = 0;
+	pB->i2eFifoOutInts = 0;
+	pB->i2eFatalTrap = NULL;
+	pB->i2eFatal = 0;
+
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiResetDelay(pB)
+// Parameters: pB - pointer to the board structure
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Using the delay defined in board structure, waits two seconds (for board to
+// reset).
+//
+//******************************************************************************
+static int
+iiResetDelay(i2eBordStrPtr pB)
+{
+	if (pB->i2eValid != I2E_MAGIC) {
+		I2_COMPLETE(pB, I2EE_BADMAGIC);
+	}
+	if (pB->i2eState != II_STATE_RESET) {
+		I2_COMPLETE(pB, I2EE_BADSTATE);
+	}
+	iiDelay(pB,2000);       /* Now we wait for two seconds. */
+	iiDelayed = 1;          /* Delay has been called: ok to initialize */
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiInitialize(pB)
+// Parameters: pB - pointer to the board structure
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Attempts to read the Power-on reset message. Initializes any remaining fields
+// in the pB structure.
+//
+// This should be called as the third step of a process beginning with
+// iiReset(), then iiResetDelay(). This routine checks to see that the structure
+// is "valid" and in the reset state, also confirms that the delay routine has
+// been called since the latest reset (to any board! overly strong!).
+//
+//******************************************************************************
+static int
+iiInitialize(i2eBordStrPtr pB)
+{
+	int itemp;
+	unsigned char c;
+	unsigned short utemp;
+	unsigned int ilimit;
+
+	if (pB->i2eValid != I2E_MAGIC)
+	{
+		I2_COMPLETE(pB, I2EE_BADMAGIC);
+	}
+
+	if (pB->i2eState != II_STATE_RESET || !iiDelayed)
+	{
+		I2_COMPLETE(pB, I2EE_BADSTATE);
+	}
+
+	// In case there is a failure short of our completely reading the power-up
+	// message.
+	pB->i2eValid = I2E_INCOMPLETE;
+
+
+	// Now attempt to read the message.
+
+	for (itemp = 0; itemp < sizeof(porStr); itemp++)
+	{
+		// We expect the entire message is ready.
+		if (!I2_HAS_INPUT(pB)) {
+			pB->i2ePomSize = itemp;
+			I2_COMPLETE(pB, I2EE_PORM_SHORT);
+		}
+
+		pB->i2ePom.c[itemp] = c = inb(pB->i2eData);
+
+		// We check the magic numbers as soon as they are supposed to be read
+		// (rather than after) to minimize effect of reading something we
+		// already suspect can't be "us".
+		if (  (itemp == POR_1_INDEX && c != POR_MAGIC_1) ||
+				(itemp == POR_2_INDEX && c != POR_MAGIC_2))
+		{
+			pB->i2ePomSize = itemp+1;
+			I2_COMPLETE(pB, I2EE_BADMAGIC);
+		}
+	}
+
+	pB->i2ePomSize = itemp;
+
+	// Ensure that this was all the data...
+	if (I2_HAS_INPUT(pB))
+		I2_COMPLETE(pB, I2EE_PORM_LONG);
+
+	// For now, we'll fail to initialize if P.O.S.T reports bad chip mapper:
+	// Implying we will not be able to download any code either:  That's ok: the
+	// condition is pretty explicit.
+	if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER)
+	{
+		I2_COMPLETE(pB, I2EE_POSTERR);
+	}
+
+	// Determine anything which must be done differently depending on the family
+	// of boards!
+	switch (pB->i2ePom.e.porID & POR_ID_FAMILY)
+	{
+	case POR_ID_FII:  // IntelliPort-II
+
+		pB->i2eFifoStyle   = FIFO_II;
+		pB->i2eFifoSize    = 512;     // 512 bytes, always
+		pB->i2eDataWidth16 = false;
+
+		pB->i2eMaxIrq = 15;	// Because board cannot tell us it is in an 8-bit
+							// slot, we do allow it to be done (documentation!)
+
+		pB->i2eGoodMap[1] =
+		pB->i2eGoodMap[2] =
+		pB->i2eGoodMap[3] =
+		pB->i2eChannelMap[1] =
+		pB->i2eChannelMap[2] =
+		pB->i2eChannelMap[3] = 0;
+
+		switch (pB->i2ePom.e.porID & POR_ID_SIZE)
+		{
+		case POR_ID_II_4:
+			pB->i2eGoodMap[0] =
+			pB->i2eChannelMap[0] = 0x0f;  // four-port
+
+			// Since porPorts1 is based on the Hardware ID register, the numbers
+			// should always be consistent for IntelliPort-II.  Ditto below...
+			if (pB->i2ePom.e.porPorts1 != 4)
+			{
+				I2_COMPLETE(pB, I2EE_INCONSIST);
+			}
+			break;
+
+		case POR_ID_II_8:
+		case POR_ID_II_8R:
+			pB->i2eGoodMap[0] =
+			pB->i2eChannelMap[0] = 0xff;  // Eight port
+			if (pB->i2ePom.e.porPorts1 != 8)
+			{
+				I2_COMPLETE(pB, I2EE_INCONSIST);
+			}
+			break;
+
+		case POR_ID_II_6:
+			pB->i2eGoodMap[0] =
+			pB->i2eChannelMap[0] = 0x3f;  // Six Port
+			if (pB->i2ePom.e.porPorts1 != 6)
+			{
+				I2_COMPLETE(pB, I2EE_INCONSIST);
+			}
+			break;
+		}
+
+		// Fix up the "good channel list based on any errors reported.
+		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1)
+		{
+			pB->i2eGoodMap[0] &= ~0x0f;
+		}
+
+		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2)
+		{
+			pB->i2eGoodMap[0] &= ~0xf0;
+		}
+
+		break;   // POR_ID_FII case
+
+	case POR_ID_FIIEX:   // IntelliPort-IIEX
+
+		pB->i2eFifoStyle = FIFO_IIEX;
+
+		itemp = pB->i2ePom.e.porFifoSize;
+
+		// Implicit assumption that fifo would not grow beyond 32k, 
+		// nor would ever be less than 256.
+
+		if (itemp < 8 || itemp > 15)
+		{
+			I2_COMPLETE(pB, I2EE_INCONSIST);
+		}
+		pB->i2eFifoSize = (1 << itemp);
+
+		// These are based on what P.O.S.T thinks should be there, based on
+		// box ID registers
+		ilimit = pB->i2ePom.e.porNumBoxes;
+		if (ilimit > ABS_MAX_BOXES)
+		{
+			ilimit = ABS_MAX_BOXES;
+		}
+
+		// For as many boxes as EXIST, gives the type of box.
+		// Added 8/6/93: check for the ISA-4 (asic) which looks like an
+		// expandable but for whom "8 or 16?" is not the right question.
+
+		utemp = pB->i2ePom.e.porFlags;
+		if (utemp & POR_CEX4)
+		{
+			pB->i2eChannelMap[0] = 0x000f;
+		} else {
+			utemp &= POR_BOXES;
+			for (itemp = 0; itemp < ilimit; itemp++)
+			{
+				pB->i2eChannelMap[itemp] = 
+					((utemp & POR_BOX_16) ? 0xffff : 0x00ff);
+				utemp >>= 1;
+			}
+		}
+
+		// These are based on what P.O.S.T actually found.
+
+		utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1;
+
+		for (itemp = 0; itemp < ilimit; itemp++)
+		{
+			pB->i2eGoodMap[itemp] = 0;
+			if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f;
+			if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0;
+			if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00;
+			if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000;
+			utemp >>= 4;
+		}
+
+		// Now determine whether we should transfer in 8 or 16-bit mode.
+		switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) )
+		{
+		case POR_BUS_SLOT16 | POR_BUS_DIP16:
+			pB->i2eDataWidth16 = true;
+			pB->i2eMaxIrq = 15;
+			break;
+
+		case POR_BUS_SLOT16:
+			pB->i2eDataWidth16 = false;
+			pB->i2eMaxIrq = 15;
+			break;
+
+		case 0:
+		case POR_BUS_DIP16:     // In an 8-bit slot, DIP switch don't care.
+		default:
+			pB->i2eDataWidth16 = false;
+			pB->i2eMaxIrq = 7;
+			break;
+		}
+		break;   // POR_ID_FIIEX case
+
+	default:    // Unknown type of board
+		I2_COMPLETE(pB, I2EE_BAD_FAMILY);
+		break;
+	}  // End the switch based on family
+
+	// Temporarily, claim there is no room in the outbound fifo. 
+	// We will maintain this whenever we check for an empty outbound FIFO.
+	pB->i2eFifoRemains = 0;
+
+	// Now, based on the bus type, should we expect to be able to re-configure
+	// interrupts (say, for testing purposes).
+	switch (pB->i2ePom.e.porBus & POR_BUS_TYPE)
+	{
+	case POR_BUS_T_ISA:
+	case POR_BUS_T_UNK:  // If the type of bus is undeclared, assume ok.
+	case POR_BUS_T_MCA:
+	case POR_BUS_T_EISA:
+		break;
+	default:
+		I2_COMPLETE(pB, I2EE_BADBUS);
+	}
+
+	if (pB->i2eDataWidth16)
+	{
+		pB->i2eWriteBuf  = iiWriteBuf16;
+		pB->i2eReadBuf   = iiReadBuf16;
+		pB->i2eWriteWord = iiWriteWord16;
+		pB->i2eReadWord  = iiReadWord16;
+	} else {
+		pB->i2eWriteBuf  = iiWriteBuf8;
+		pB->i2eReadBuf   = iiReadBuf8;
+		pB->i2eWriteWord = iiWriteWord8;
+		pB->i2eReadWord  = iiReadWord8;
+	}
+
+	switch(pB->i2eFifoStyle)
+	{
+	case FIFO_II:
+		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII;
+		pB->i2eTxMailEmpty    = iiTxMailEmptyII;
+		pB->i2eTrySendMail    = iiTrySendMailII;
+		pB->i2eGetMail        = iiGetMailII;
+		pB->i2eEnableMailIrq  = iiEnableMailIrqII;
+		pB->i2eWriteMask      = iiWriteMaskII;
+
+		break;
+
+	case FIFO_IIEX:
+		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX;
+		pB->i2eTxMailEmpty    = iiTxMailEmptyIIEX;
+		pB->i2eTrySendMail    = iiTrySendMailIIEX;
+		pB->i2eGetMail        = iiGetMailIIEX;
+		pB->i2eEnableMailIrq  = iiEnableMailIrqIIEX;
+		pB->i2eWriteMask      = iiWriteMaskIIEX;
+
+		break;
+
+	default:
+		I2_COMPLETE(pB, I2EE_INCONSIST);
+	}
+
+	// Initialize state information.
+	pB->i2eState = II_STATE_READY;   // Ready to load loadware.
+
+	// Some Final cleanup:
+	// For some boards, the bootstrap firmware may perform some sort of test
+	// resulting in a stray character pending in the incoming mailbox. If one is
+	// there, it should be read and discarded, especially since for the standard
+	// firmware, it's the mailbox that interrupts the host.
+
+	pB->i2eStartMail = iiGetMail(pB);
+
+	// Throw it away and clear the mailbox structure element
+	pB->i2eStartMail = NO_MAIL_HERE;
+
+	// Everything is ok now, return with good status/
+
+	pB->i2eValid = I2E_MAGIC;
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   ii2DelayTimer(mseconds)
+// Parameters: mseconds - number of milliseconds to delay
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// This routine delays for approximately mseconds milliseconds and is intended
+// to be called indirectly through i2Delay field in i2eBordStr. It uses the
+// Linux timer_list mechanism.
+//
+// The Linux timers use a unit called "jiffies" which are 10mS in the Intel
+// architecture. This function rounds the delay period up to the next "jiffy".
+// In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended
+// for Alpha platforms at this time.
+//
+//******************************************************************************
+static void
+ii2DelayTimer(unsigned int mseconds)
+{
+	msleep_interruptible(mseconds);
+}
+
+#if 0
+//static void ii2DelayIO(unsigned int);
+//******************************************************************************
+// !!! Not Used, this is DOS crap, some of you young folks may be interested in
+//     in how things were done in the stone age of caculating machines       !!!
+// Function:   ii2DelayIO(mseconds)
+// Parameters: mseconds - number of milliseconds to delay
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// This routine delays for approximately mseconds milliseconds and is intended
+// to be called indirectly through i2Delay field in i2eBordStr. It is intended
+// for use where a clock-based function is impossible: for example, DOS drivers.
+//
+// This function uses the IN instruction to place bounds on the timing and
+// assumes that ii2Safe has been set. This is because I/O instructions are not
+// subject to caching and will therefore take a certain minimum time. To ensure
+// the delay is at least long enough on fast machines, it is based on some
+// fastest-case calculations.  On slower machines this may cause VERY long
+// delays. (3 x fastest case). In the fastest case, everything is cached except
+// the I/O instruction itself.
+//
+// Timing calculations:
+// The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O
+// operation in question is a byte operation to an odd address. For 8-bit
+// operations, the architecture generally enforces two wait states. At 10 MHz, a
+// single cycle time is 100nS. A read operation at two wait states takes 6
+// cycles for a total time of 600nS. Therefore approximately 1666 iterations
+// would be required to generate a single millisecond delay. The worst
+// (reasonable) case would be an 8MHz system with no cacheing. In this case, the
+// I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code
+// fetch of other instructions in the loop would take time (zero wait states,
+// however) and would be hard to estimate. This is minimized by using in-line
+// assembler for the in inner loop of IN instructions. This consists of just a
+// few bytes. So we'll guess about four code fetches per loop. Each code fetch
+// should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is
+// that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS.
+//
+// So much for theoretical timings: results using 1666 value on some actual
+// machines:
+// IBM      286      6MHz     3.15 mS
+// Zenith   386      33MHz    2.45 mS
+// (brandX) 386      33MHz    1.90 mS  (has cache)
+// (brandY) 486      33MHz    2.35 mS
+// NCR      486      ??       1.65 mS (microchannel)
+//
+// For most machines, it is probably safe to scale this number back (remember,
+// for robust operation use an actual timed delay if possible), so we are using
+// a value of 1190. This yields 1.17 mS for the fastest machine in our sample,
+// 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine.
+//
+// 1/29/93:
+// The above timings are too slow. Actual cycle times might be faster. ISA cycle
+// times could approach 500 nS, and ...
+// The IBM model 77 being microchannel has no wait states for 8-bit reads and
+// seems to be accessing the I/O at 440 nS per access (from start of one to
+// start of next). This would imply we need 1000/.440 = 2272 iterations to
+// guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in
+// fact enough. For diagnostics, we keep the level at 1190, but developers note
+// this needs tuning.
+//
+// Safe assumption:  2270 i/o reads = 1 millisecond
+//
+//******************************************************************************
+
+
+static int ii2DelValue = 1190;  // See timing calculations below
+						// 1666 for fastest theoretical machine
+						// 1190 safe for most fast 386 machines
+						// 1000 for fastest machine tested here
+						//  540 (sic) for AT286/6Mhz
+static void
+ii2DelayIO(unsigned int mseconds)
+{
+	if (!ii2Safe) 
+		return;   /* Do nothing if this variable uninitialized */
+
+	while(mseconds--) {
+		int i = ii2DelValue;
+		while ( i-- ) {
+			inb(ii2Safe);
+		}
+	}
+}
+#endif 
+
+//******************************************************************************
+// Function:   ii2Nop()
+// Parameters: None
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// iiInitialize will set i2eDelay to this if the delay parameter is NULL. This
+// saves checking for a NULL pointer at every call.
+//******************************************************************************
+static void
+ii2Nop(void)
+{
+	return;	// no mystery here
+}
+
+//=======================================================
+// Routines which are available in 8/16-bit versions, or
+// in different fifo styles. These are ALL called
+// indirectly through the board structure.
+//=======================================================
+
+//******************************************************************************
+// Function:   iiWriteBuf16(pB, address, count)
+// Parameters: pB      - pointer to board structure
+//             address - address of data to write
+//             count   - number of data bytes to write
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Writes 'count' bytes from 'address' to the data fifo specified by the board
+// structure pointer pB. Should count happen to be odd, an extra pad byte is
+// sent (identity unknown...). Uses 16-bit (word) operations. Is called
+// indirectly through pB->i2eWriteBuf.
+//
+//******************************************************************************
+static int
+iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
+{
+	// Rudimentary sanity checking here.
+	if (pB->i2eValid != I2E_MAGIC)
+		I2_COMPLETE(pB, I2EE_INVALID);
+
+	I2_OUTSW(pB->i2eData, address, count);
+
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiWriteBuf8(pB, address, count)
+// Parameters: pB      - pointer to board structure
+//             address - address of data to write
+//             count   - number of data bytes to write
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Writes 'count' bytes from 'address' to the data fifo specified by the board
+// structure pointer pB. Should count happen to be odd, an extra pad byte is
+// sent (identity unknown...). This is to be consistent with the 16-bit version.
+// Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf.
+//
+//******************************************************************************
+static int
+iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
+{
+	/* Rudimentary sanity checking here */
+	if (pB->i2eValid != I2E_MAGIC)
+		I2_COMPLETE(pB, I2EE_INVALID);
+
+	I2_OUTSB(pB->i2eData, address, count);
+
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiReadBuf16(pB, address, count)
+// Parameters: pB      - pointer to board structure
+//             address - address to put data read
+//             count   - number of data bytes to read
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Reads 'count' bytes into 'address' from the data fifo specified by the board
+// structure pointer pB. Should count happen to be odd, an extra pad byte is
+// received (identity unknown...). Uses 16-bit (word) operations. Is called
+// indirectly through pB->i2eReadBuf.
+//
+//******************************************************************************
+static int
+iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
+{
+	// Rudimentary sanity checking here.
+	if (pB->i2eValid != I2E_MAGIC)
+		I2_COMPLETE(pB, I2EE_INVALID);
+
+	I2_INSW(pB->i2eData, address, count);
+
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiReadBuf8(pB, address, count)
+// Parameters: pB      - pointer to board structure
+//             address - address to put data read
+//             count   - number of data bytes to read
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Reads 'count' bytes into 'address' from the data fifo specified by the board
+// structure pointer pB. Should count happen to be odd, an extra pad byte is
+// received (identity unknown...). This to match the 16-bit behaviour. Uses
+// 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf.
+//
+//******************************************************************************
+static int
+iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
+{
+	// Rudimentary sanity checking here.
+	if (pB->i2eValid != I2E_MAGIC)
+		I2_COMPLETE(pB, I2EE_INVALID);
+
+	I2_INSB(pB->i2eData, address, count);
+
+	I2_COMPLETE(pB, I2EE_GOOD);
+}
+
+//******************************************************************************
+// Function:   iiReadWord16(pB)
+// Parameters: pB      - pointer to board structure
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Returns the word read from the data fifo specified by the board-structure
+// pointer pB. Uses a 16-bit operation. Is called indirectly through
+// pB->i2eReadWord.
+//
+//******************************************************************************
+static unsigned short
+iiReadWord16(i2eBordStrPtr pB)
+{
+	return inw(pB->i2eData);
+}
+
+//******************************************************************************
+// Function:   iiReadWord8(pB)
+// Parameters: pB      - pointer to board structure
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Returns the word read from the data fifo specified by the board-structure
+// pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is
+// called indirectly through pB->i2eReadWord.
+//
+//******************************************************************************
+static unsigned short
+iiReadWord8(i2eBordStrPtr pB)
+{
+	unsigned short urs;
+
+	urs = inb(pB->i2eData);
+
+	return (inb(pB->i2eData) << 8) | urs;
+}
+
+//******************************************************************************
+// Function:   iiWriteWord16(pB, value)
+// Parameters: pB    - pointer to board structure
+//             value - data to write
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Writes the word 'value' to the data fifo specified by the board-structure
+// pointer pB. Uses 16-bit operation. Is called indirectly through
+// pB->i2eWriteWord.
+//
+//******************************************************************************
+static void
+iiWriteWord16(i2eBordStrPtr pB, unsigned short value)
+{
+	outw((int)value, pB->i2eData);
+}
+
+//******************************************************************************
+// Function:   iiWriteWord8(pB, value)
+// Parameters: pB    - pointer to board structure
+//             value - data to write
+//
+// Returns:    True if everything appears copacetic.
+//             False if there is any error: the pB->i2eError field has the error
+//
+// Description:
+//
+// Writes the word 'value' to the data fifo specified by the board-structure
+// pointer pB. Uses two 8-bit operations (writes LSB first). Is called
+// indirectly through pB->i2eWriteWord.
+//
+//******************************************************************************
+static void
+iiWriteWord8(i2eBordStrPtr pB, unsigned short value)
+{
+	outb((char)value, pB->i2eData);
+	outb((char)(value >> 8), pB->i2eData);
+}
+
+//******************************************************************************
+// Function:   iiWaitForTxEmptyII(pB, mSdelay)
+// Parameters: pB      - pointer to board structure
+//             mSdelay - period to wait before returning
+//
+// Returns:    True if the FIFO is empty.
+//             False if it not empty in the required time: the pB->i2eError
+//             field has the error.
+//
+// Description:
+//
+// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
+// not empty by the required time, returns false and error in pB->i2eError,
+// otherwise returns true.
+//
+// mSdelay == 0 is taken to mean must be empty on the first test.
+//
+// This version operates on IntelliPort-II - style FIFO's
+//
+// Note this routine is organized so that if status is ok there is no delay at
+// all called either before or after the test.  Is called indirectly through
+// pB->i2eWaitForTxEmpty.
+//
+//******************************************************************************
+static int
+iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay)
+{
+	unsigned long	flags;
+	int itemp;
+
+	for (;;)
+	{
+		// This routine hinges on being able to see the "other" status register
+		// (as seen by the local processor).  His incoming fifo is our outgoing
+		// FIFO.
+		//
+		// By the nature of this routine, you would be using this as part of a
+		// larger atomic context: i.e., you would use this routine to ensure the
+		// fifo empty, then act on this information. Between these two halves, 
+		// you will generally not want to service interrupts or in any way 
+		// disrupt the assumptions implicit in the larger context.
+		//
+		// Even worse, however, this routine "shifts" the status register to 
+		// point to the local status register which is not the usual situation.
+		// Therefore for extra safety, we force the critical section to be
+		// completely atomic, and pick up after ourselves before allowing any
+		// interrupts of any kind.
+
+
+		write_lock_irqsave(&Dl_spinlock, flags);
+		outb(SEL_COMMAND, pB->i2ePointer);
+		outb(SEL_CMD_SH, pB->i2ePointer);
+
+		itemp = inb(pB->i2eStatus);
+
+		outb(SEL_COMMAND, pB->i2ePointer);
+		outb(SEL_CMD_UNSH, pB->i2ePointer);
+
+		if (itemp & ST_IN_EMPTY)
+		{
+			I2_UPDATE_FIFO_ROOM(pB);
+			write_unlock_irqrestore(&Dl_spinlock, flags);
+			I2_COMPLETE(pB, I2EE_GOOD);
+		}
+
+		write_unlock_irqrestore(&Dl_spinlock, flags);
+
+		if (mSdelay-- == 0)
+			break;
+
+		iiDelay(pB, 1);      /* 1 mS granularity on checking condition */
+	}
+	I2_COMPLETE(pB, I2EE_TXE_TIME);
+}
+
+//******************************************************************************
+// Function:   iiWaitForTxEmptyIIEX(pB, mSdelay)
+// Parameters: pB      - pointer to board structure
+//             mSdelay - period to wait before returning
+//
+// Returns:    True if the FIFO is empty.
+//             False if it not empty in the required time: the pB->i2eError
+//             field has the error.
+//
+// Description:
+//
+// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
+// not empty by the required time, returns false and error in pB->i2eError,
+// otherwise returns true.
+//
+// mSdelay == 0 is taken to mean must be empty on the first test.
+//
+// This version operates on IntelliPort-IIEX - style FIFO's
+//
+// Note this routine is organized so that if status is ok there is no delay at
+// all called either before or after the test.  Is called indirectly through
+// pB->i2eWaitForTxEmpty.
+//
+//******************************************************************************
+static int
+iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay)
+{
+	unsigned long	flags;
+
+	for (;;)
+	{
+		// By the nature of this routine, you would be using this as part of a
+		// larger atomic context: i.e., you would use this routine to ensure the
+		// fifo empty, then act on this information. Between these two halves,
+		// you will generally not want to service interrupts or in any way
+		// disrupt the assumptions implicit in the larger context.
+
+		write_lock_irqsave(&Dl_spinlock, flags);
+
+		if (inb(pB->i2eStatus) & STE_OUT_MT) {
+			I2_UPDATE_FIFO_ROOM(pB);
+			write_unlock_irqrestore(&Dl_spinlock, flags);
+			I2_COMPLETE(pB, I2EE_GOOD);
+		}
+		write_unlock_irqrestore(&Dl_spinlock, flags);
+
+		if (mSdelay-- == 0)
+			break;
+
+		iiDelay(pB, 1);      // 1 mS granularity on checking condition
+	}
+	I2_COMPLETE(pB, I2EE_TXE_TIME);
+}
+
+//******************************************************************************
+// Function:   iiTxMailEmptyII(pB)
+// Parameters: pB      - pointer to board structure
+//
+// Returns:    True if the transmit mailbox is empty.
+//             False if it not empty.
+//
+// Description:
+//
+// Returns true or false according to whether the transmit mailbox is empty (and
+// therefore able to accept more mail)
+//
+// This version operates on IntelliPort-II - style FIFO's
+//
+//******************************************************************************
+static int
+iiTxMailEmptyII(i2eBordStrPtr pB)
+{
+	int port = pB->i2ePointer;
+	outb(SEL_OUTMAIL, port);
+	return inb(port) == 0;
+}
+
+//******************************************************************************
+// Function:   iiTxMailEmptyIIEX(pB)
+// Parameters: pB      - pointer to board structure
+//
+// Returns:    True if the transmit mailbox is empty.
+//             False if it not empty.
+//
+// Description:
+//
+// Returns true or false according to whether the transmit mailbox is empty (and
+// therefore able to accept more mail)
+//
+// This version operates on IntelliPort-IIEX - style FIFO's
+//
+//******************************************************************************
+static int
+iiTxMailEmptyIIEX(i2eBordStrPtr pB)
+{
+	return !(inb(pB->i2eStatus) & STE_OUT_MAIL);
+}
+
+//******************************************************************************
+// Function:   iiTrySendMailII(pB,mail)
+// Parameters: pB   - pointer to board structure
+//             mail - value to write to mailbox
+//
+// Returns:    True if the transmit mailbox is empty, and mail is sent.
+//             False if it not empty.
+//
+// Description:
+//
+// If outgoing mailbox is empty, sends mail and returns true. If outgoing
+// mailbox is not empty, returns false.
+//
+// This version operates on IntelliPort-II - style FIFO's
+//
+//******************************************************************************
+static int
+iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail)
+{
+	int port = pB->i2ePointer;
+
+	outb(SEL_OUTMAIL, port);
+	if (inb(port) == 0) {
+		outb(SEL_OUTMAIL, port);
+		outb(mail, port);
+		return 1;
+	}
+	return 0;
+}
+
+//******************************************************************************
+// Function:   iiTrySendMailIIEX(pB,mail)
+// Parameters: pB   - pointer to board structure
+//             mail - value to write to mailbox
+//
+// Returns:    True if the transmit mailbox is empty, and mail is sent.
+//             False if it not empty.
+//
+// Description:
+//
+// If outgoing mailbox is empty, sends mail and returns true. If outgoing
+// mailbox is not empty, returns false.
+//
+// This version operates on IntelliPort-IIEX - style FIFO's
+//
+//******************************************************************************
+static int
+iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail)
+{
+	if (inb(pB->i2eStatus) & STE_OUT_MAIL)
+		return 0;
+	outb(mail, pB->i2eXMail);
+	return 1;
+}
+
+//******************************************************************************
+// Function:   iiGetMailII(pB,mail)
+// Parameters: pB   - pointer to board structure
+//
+// Returns:    Mailbox data or NO_MAIL_HERE.
+//
+// Description:
+//
+// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
+// the mailbox, which is guaranteed != NO_MAIL_HERE.
+//
+// This version operates on IntelliPort-II - style FIFO's
+//
+//******************************************************************************
+static unsigned short
+iiGetMailII(i2eBordStrPtr pB)
+{
+	if (I2_HAS_MAIL(pB)) {
+		outb(SEL_INMAIL, pB->i2ePointer);
+		return inb(pB->i2ePointer);
+	} else {
+		return NO_MAIL_HERE;
+	}
+}
+
+//******************************************************************************
+// Function:   iiGetMailIIEX(pB,mail)
+// Parameters: pB   - pointer to board structure
+//
+// Returns:    Mailbox data or NO_MAIL_HERE.
+//
+// Description:
+//
+// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
+// the mailbox, which is guaranteed != NO_MAIL_HERE.
+//
+// This version operates on IntelliPort-IIEX - style FIFO's
+//
+//******************************************************************************
+static unsigned short
+iiGetMailIIEX(i2eBordStrPtr pB)
+{
+	if (I2_HAS_MAIL(pB))
+		return inb(pB->i2eXMail);
+	else
+		return NO_MAIL_HERE;
+}
+
+//******************************************************************************
+// Function:   iiEnableMailIrqII(pB)
+// Parameters: pB - pointer to board structure
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
+//
+// This version operates on IntelliPort-II - style FIFO's
+//
+//******************************************************************************
+static void
+iiEnableMailIrqII(i2eBordStrPtr pB)
+{
+	outb(SEL_MASK, pB->i2ePointer);
+	outb(ST_IN_MAIL, pB->i2ePointer);
+}
+
+//******************************************************************************
+// Function:   iiEnableMailIrqIIEX(pB)
+// Parameters: pB - pointer to board structure
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
+//
+// This version operates on IntelliPort-IIEX - style FIFO's
+//
+//******************************************************************************
+static void
+iiEnableMailIrqIIEX(i2eBordStrPtr pB)
+{
+	outb(MX_IN_MAIL, pB->i2eXMask);
+}
+
+//******************************************************************************
+// Function:   iiWriteMaskII(pB)
+// Parameters: pB - pointer to board structure
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// Writes arbitrary value to the mask register.
+//
+// This version operates on IntelliPort-II - style FIFO's
+//
+//******************************************************************************
+static void
+iiWriteMaskII(i2eBordStrPtr pB, unsigned char value)
+{
+	outb(SEL_MASK, pB->i2ePointer);
+	outb(value, pB->i2ePointer);
+}
+
+//******************************************************************************
+// Function:   iiWriteMaskIIEX(pB)
+// Parameters: pB - pointer to board structure
+//
+// Returns:    Nothing
+//
+// Description:
+//
+// Writes arbitrary value to the mask register.
+//
+// This version operates on IntelliPort-IIEX - style FIFO's
+//
+//******************************************************************************
+static void
+iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value)
+{
+	outb(value, pB->i2eXMask);
+}
+
+//******************************************************************************
+// Function:   iiDownloadBlock(pB, pSource, isStandard)
+// Parameters: pB         - pointer to board structure
+//             pSource    - loadware block to download
+//             isStandard - True if "standard" loadware, else false.
+//
+// Returns:    Success or Failure
+//
+// Description:
+//
+// Downloads a single block (at pSource)to the board referenced by pB. Caller
+// sets isStandard to true/false according to whether the "standard" loadware is
+// what's being loaded. The normal process, then, is to perform an iiInitialize
+// to the board, then perform some number of iiDownloadBlocks using the returned
+// state to determine when download is complete.
+//
+// Possible return values: (see I2ELLIS.H)
+// II_DOWN_BADVALID
+// II_DOWN_BADFILE
+// II_DOWN_CONTINUING
+// II_DOWN_GOOD
+// II_DOWN_BAD
+// II_DOWN_BADSTATE
+// II_DOWN_TIMEOUT
+//
+// Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to
+// determine whether this is the first block, whether to check for magic
+// numbers, how many blocks there are to go...
+//
+//******************************************************************************
+static int
+iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard)
+{
+	int itemp;
+	int loadedFirst;
+
+	if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID;
+
+	switch(pB->i2eState)
+	{
+	case II_STATE_READY:
+
+		// Loading the first block after reset. Must check the magic number of the
+		// loadfile, store the number of blocks we expect to load.
+		if (pSource->e.loadMagic != MAGIC_LOADFILE)
+		{
+			return II_DOWN_BADFILE;
+		}
+
+		// Next we store the total number of blocks to load, including this one.
+		pB->i2eToLoad = 1 + pSource->e.loadBlocksMore;
+
+		// Set the state, store the version numbers. ('Cause this may have come
+		// from a file - we might want to report these versions and revisions in
+		// case of an error!
+		pB->i2eState = II_STATE_LOADING;
+		pB->i2eLVersion = pSource->e.loadVersion;
+		pB->i2eLRevision = pSource->e.loadRevision;
+		pB->i2eLSub = pSource->e.loadSubRevision;
+
+		// The time and date of compilation is also available but don't bother
+		// storing it for normal purposes.
+		loadedFirst = 1;
+		break;
+
+	case II_STATE_LOADING:
+		loadedFirst = 0;
+		break;
+
+	default:
+		return II_DOWN_BADSTATE;
+	}
+
+	// Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad
+	// must be positive still, because otherwise we would have cleaned up last
+	// time and set the state to II_STATE_LOADED.
+	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
+		return II_DOWN_TIMEOUT;
+	}
+
+	if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) {
+		return II_DOWN_BADVALID;
+	}
+
+	// If we just loaded the first block, wait for the fifo to empty an extra
+	// long time to allow for any special startup code in the firmware, like
+	// sending status messages to the LCD's.
+
+	if (loadedFirst) {
+		if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) {
+			return II_DOWN_TIMEOUT;
+		}
+	}
+
+	// Determine whether this was our last block!
+	if (--(pB->i2eToLoad)) {
+		return II_DOWN_CONTINUING;    // more to come...
+	}
+
+	// It WAS our last block: Clean up operations...
+	// ...Wait for last buffer to drain from the board...
+	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
+		return II_DOWN_TIMEOUT;
+	}
+	// If there were only a single block written, this would come back
+	// immediately and be harmless, though not strictly necessary.
+	itemp = MAX_DLOAD_ACK_TIME/10;
+	while (--itemp) {
+		if (I2_HAS_INPUT(pB)) {
+			switch (inb(pB->i2eData)) {
+			case LOADWARE_OK:
+				pB->i2eState =
+					isStandard ? II_STATE_STDLOADED :II_STATE_LOADED;
+
+				// Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2)
+				// will, // if there is a debug port attached, require some
+				// time to send information to the debug port now. It will do
+				// this before // executing any of the code we just downloaded.
+				// It may take up to 700 milliseconds.
+				if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) {
+					iiDelay(pB, 700);
+				}
+
+				return II_DOWN_GOOD;
+
+			case LOADWARE_BAD:
+			default:
+				return II_DOWN_BAD;
+			}
+		}
+
+		iiDelay(pB, 10);      // 10 mS granularity on checking condition
+	}
+
+	// Drop-through --> timed out waiting for firmware confirmation
+
+	pB->i2eState = II_STATE_BADLOAD;
+	return II_DOWN_TIMEOUT;
+}
+
+//******************************************************************************
+// Function:   iiDownloadAll(pB, pSource, isStandard, size)
+// Parameters: pB         - pointer to board structure
+//             pSource    - loadware block to download
+//             isStandard - True if "standard" loadware, else false.
+//             size       - size of data to download (in bytes)
+//
+// Returns:    Success or Failure
+//
+// Description:
+//
+// Given a pointer to a board structure, a pointer to the beginning of some
+// loadware, whether it is considered the "standard loadware", and the size of
+// the array in bytes loads the entire array to the board as loadware.
+//
+// Assumes the board has been freshly reset and the power-up reset message read.
+// (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be
+// too much or too little data to load, or if iiDownloadBlock complains.
+//******************************************************************************
+static int
+iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size)
+{
+	int status;
+
+	// We know (from context) board should be ready for the first block of
+	// download.  Complain if not.
+	if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE;
+
+	while (size > 0) {
+		size -= LOADWARE_BLOCK_SIZE;	// How much data should there be left to
+										// load after the following operation ?
+
+		// Note we just bump pSource by "one", because its size is actually that
+		// of an entire block, same as LOADWARE_BLOCK_SIZE.
+		status = iiDownloadBlock(pB, pSource++, isStandard);
+
+		switch(status)
+		{
+		case II_DOWN_GOOD:
+			return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD);
+
+		case II_DOWN_CONTINUING:
+			break;
+
+		default:
+			return status;
+		}
+	}
+
+	// We shouldn't drop out: it means "while" caught us with nothing left to
+	// download, yet the previous DownloadBlock did not return complete. Ergo,
+	// not enough data to match the size byte in the header.
+	return II_DOWN_UNDER;
+}
diff --git a/drivers/staging/tty/ip2/i2ellis.h b/drivers/staging/tty/ip2/i2ellis.h
new file mode 100644
index 0000000..fb6df24
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2ellis.h
@@ -0,0 +1,566 @@
+/*******************************************************************************
+*
+*   (c) 1999 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Mainline code for the device driver
+*
+*******************************************************************************/
+//------------------------------------------------------------------------------
+// i2ellis.h
+//
+// IntelliPort-II and IntelliPort-IIEX
+//
+// Extremely
+// Low
+// Level
+// Interface
+// Services
+//
+// Structure Definitions and declarations for "ELLIS" service routines found in
+// i2ellis.c
+//
+// These routines are based on properties of the IntelliPort-II and -IIEX
+// hardware and bootstrap firmware, and are not sensitive to particular
+// conventions of any particular loadware.
+//
+// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material
+// here and in i2ellis.c is intended to provice a useful, but not required,
+// layer of insulation from the hardware specifics.
+//------------------------------------------------------------------------------
+#ifndef  I2ELLIS_H   /* To prevent multiple includes */
+#define  I2ELLIS_H   1
+//------------------------------------------------
+// Revision History:
+//
+// 30 September 1991 MAG First Draft Started
+// 12 October   1991 ...continued...
+//
+// 20 December  1996 AKM Linux version
+//-------------------------------------------------
+
+//----------------------
+// Mandatory Includes:
+//----------------------
+#include "ip2types.h"
+#include "i2hw.h"       // The hardware definitions
+
+//------------------------------------------
+// STAT_BOXIDS packets
+//------------------------------------------
+#define MAX_BOX		4
+
+typedef struct _bidStat
+{
+	unsigned char bid_value[MAX_BOX];
+} bidStat, *bidStatPtr;
+
+// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX
+// boards, reports the hardware-specific "asynchronous resource register" on
+// each expansion box. Boxes not present report 0xff. For -II boards, the first
+// element contains 0x80 for 8-port, 0x40 for 4-port boards.
+
+// Box IDs aka ARR or Async Resource Register (more than you want to know)
+//   7   6   5   4   3   2   1   0
+//   F   F   N   N   L   S   S   S
+//   =============================
+//   F   F   -  Product Family Designator
+//   =====+++++++++++++++++++++++++++++++
+//   0   0   -  Intelliport II EX / ISA-8
+//   1   0   -  IntelliServer
+//   0   1   -  SAC - Port Device (Intelliport III ??? )
+//           =====+++++++++++++++++++++++++++++++++++++++
+//           N   N   -  Number of Ports
+//           0   0   -  8  (eight)
+//           0   1   -  4  (four)
+//           1   0   -  12 (twelve)
+//           1   1   -  16 (sixteen)
+//                   =++++++++++++++++++++++++++++++++++
+//                   L  -   LCD Display Module Present
+//                   0  -   No
+//                   1  -   LCD module present
+//                   =========+++++++++++++++++++++++++++++++++++++
+//                      S   S   S - Async Signals Supported Designator
+//                      0   0   0 - 8dss, Mod DCE DB25 Female
+//                      0   0   1 - 6dss, RJ-45
+//                      0   1   0 - RS-232/422 dss, DB25 Female
+//                      0   1   1 - RS-232/422 dss, separate 232/422 DB25 Female
+//                      1   0   0 - 6dss, 921.6 I/F with ST654's
+//                      1   0   1 - RS-423/232 8dss, RJ-45 10Pin
+//                      1   1   0 - 6dss, Mod DCE DB25 Female
+//                      1   1   1 - NO BOX PRESENT
+
+#define FF(c)	((c & 0xC0) >> 6)
+#define NN(c)	((c & 0x30) >> 4)
+#define L(c)	((c & 0x08) >> 3)
+#define SSS(c)	 (c & 0x07)
+
+#define BID_HAS_654(x)	(SSS(x) == 0x04)
+#define BID_NO_BOX	0xff /* no box */
+#define BID_8PORT  	0x80 /* IP2-8 port */
+#define BID_4PORT   	0x81 /* IP2-4 port */
+#define BID_EXP_MASK   	0x30 /* IP2-EX  */
+#define BID_EXP_8PORT	0x00 /*     8, */
+#define BID_EXP_4PORT	0x10 /*     4, */
+#define BID_EXP_UNDEF	0x20 /*     UNDEF, */
+#define BID_EXP_16PORT	0x30 /*    16, */
+#define BID_LCD_CTRL   	0x08 /* LCD Controller */
+#define BID_LCD_NONE	0x00 /* - no controller present */
+#define BID_LCD_PRES   	0x08 /* - controller present */
+#define BID_CON_MASK	0x07 /* - connector pinouts */
+#define BID_CON_DB25	0x00 /* - DB-25 F */
+#define BID_CON_RJ45	0x01 /* - rj45 */
+
+//------------------------------------------------------------------------------
+// i2eBordStr
+//
+// This structure contains all the information the ELLIS routines require in
+// dealing with a particular board.
+//------------------------------------------------------------------------------
+// There are some queues here which are guaranteed to never contain the entry
+// for a single channel twice. So they must be slightly larger to allow
+// unambiguous full/empty management
+//
+#define CH_QUEUE_SIZE ABS_MOST_PORTS+2
+
+typedef struct _i2eBordStr
+{
+	porStr         i2ePom;	// Structure containing the power-on message.
+
+	unsigned short i2ePomSize;
+						// The number of bytes actually read if
+						// different from sizeof i2ePom, indicates
+						// there is an error!
+
+	unsigned short i2eStartMail;
+						// Contains whatever inbound mailbox data
+						// present at startup. NO_MAIL_HERE indicates
+						// nothing was present. No special
+						// significance as of this writing, but may be
+						// useful for diagnostic reasons.
+
+	unsigned short i2eValid;
+						// Indicates validity of the structure; if
+						// i2eValid == I2E_MAGIC, then we can trust
+						// the other fields. Some (especially
+						// initialization) functions are good about
+						// checking for validity.  Many functions do
+						// not, it being assumed that the larger
+						// context assures we are using a valid
+						// i2eBordStrPtr.
+
+	unsigned short i2eError;
+						// Used for returning an error condition from
+						// several functions which use i2eBordStrPtr
+						// as an argument.
+
+	// Accelerators to characterize separate features of a board, derived from a
+	// number of sources.
+
+	unsigned short i2eFifoSize;
+						// Always, the size of the FIFO. For
+						// IntelliPort-II, always the same, for -IIEX
+						// taken from the Power-On reset message.
+
+	volatile 
+	unsigned short i2eFifoRemains;
+						// Used during normal operation to indicate a
+						// lower bound on the amount of data which
+						// might be in the outbound fifo.
+
+	unsigned char  i2eFifoStyle;
+						// Accelerator which tells which style (-II or
+						// -IIEX) FIFO we are using.
+
+	unsigned char  i2eDataWidth16;
+						// Accelerator which tells whether we should
+						// do 8 or 16-bit data transfers.
+
+	unsigned char  i2eMaxIrq;
+						// The highest allowable IRQ, based on the
+						// slot size.
+
+	// Accelerators for various addresses on the board
+	int            i2eBase;        // I/O Address of the Board
+	int            i2eData;        // From here data transfers happen
+	int            i2eStatus;      // From here status reads happen
+	int            i2ePointer;     // (IntelliPort-II: pointer/commands)
+	int            i2eXMail;       // (IntelliPOrt-IIEX: mailboxes
+	int            i2eXMask;       // (IntelliPort-IIEX: mask write
+
+	//-------------------------------------------------------
+	// Information presented in a common format across boards
+	// For each box, bit map of the channels present.  Box closest to 
+	// the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable)
+	// is taken to be box 0. These are derived from product i.d. registers.
+
+	unsigned short i2eChannelMap[ABS_MAX_BOXES];
+
+	// Same as above, except each is derived from firmware attempting to detect
+	// the uart presence (by reading a valid GFRCR register). If bits are set in
+	// i2eChannelMap and not in i2eGoodMap, there is a potential problem.
+
+	unsigned short i2eGoodMap[ABS_MAX_BOXES];
+
+	// ---------------------------
+	// For indirect function calls
+
+	// Routine to cause an N-millisecond delay: Patched by the ii2Initialize
+	// function.
+
+	void  (*i2eDelay)(unsigned int);
+
+	// Routine to write N bytes to the board through the FIFO. Returns true if
+	// all copacetic, otherwise returns false and error is in i2eError field.
+	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
+
+	int   (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int);
+
+	// Routine to read N bytes from the board through the FIFO. Returns true if
+	// copacetic, otherwise returns false and error in i2eError.
+	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
+
+	int   (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int);
+
+	// Returns a word from FIFO. Will use 2 byte operations if needed.
+
+	unsigned short (*i2eReadWord)(struct _i2eBordStr *);
+
+	// Writes a word to FIFO. Will use 2 byte operations if needed.
+
+	void  (*i2eWriteWord)(struct _i2eBordStr *, unsigned short);
+
+	// Waits specified time for the Transmit FIFO to go empty. Returns true if
+	//  ok, otherwise returns false and error in i2eError.
+
+	int   (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int);
+
+	// Returns true or false according to whether the outgoing mailbox is empty.
+
+	int   (*i2eTxMailEmpty)(struct _i2eBordStr *);
+
+	// Checks whether outgoing mailbox is empty.  If so, sends mail and returns
+	// true.  Otherwise returns false.
+
+	int   (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char);
+
+	// If no mail available, returns NO_MAIL_HERE, else returns the value in the
+	// mailbox (guaranteed can't be NO_MAIL_HERE).
+
+	unsigned short (*i2eGetMail)(struct _i2eBordStr *);
+
+	// Enables the board to interrupt the host when it writes to the mailbox.
+	// Irqs will not occur, however, until the loadware separately enables
+	// interrupt generation to the host.  The standard loadware does this in
+	// response to a command packet sent by the host. (Also, disables
+	// any other potential interrupt sources from the board -- other than the
+	// inbound mailbox).
+
+	void  (*i2eEnableMailIrq)(struct _i2eBordStr *);
+
+	// Writes an arbitrary value to the mask register.
+
+	void  (*i2eWriteMask)(struct _i2eBordStr *, unsigned char);
+
+
+	// State information
+
+	// During downloading, indicates the number of blocks remaining to download
+	// to the board.
+
+	short i2eToLoad;
+
+	// State of board (see manifests below) (e.g., whether in reset condition,
+	// whether standard loadware is installed, etc.
+
+	unsigned char  i2eState;
+
+	// These three fields are only valid when there is loadware running on the
+	// board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED )
+
+	unsigned char  i2eLVersion;  // Loadware version
+	unsigned char  i2eLRevision; // Loadware revision
+	unsigned char  i2eLSub;      // Loadware subrevision
+
+	// Flags which only have meaning in the context of the standard loadware.
+	// Somewhat violates the layering concept, but there is so little additional
+	// needed at the board level (while much additional at the channel level),
+	// that this beats maintaining two different per-board structures.
+
+	// Indicates which IRQ the board has been initialized (from software) to use
+	// For MicroChannel boards, any value different from IRQ_UNDEFINED means
+	// that the software command has been sent to enable interrupts (or specify
+	// they are disabled). Special value: IRQ_UNDEFINED indicates that the
+	// software command to select the interrupt has not yet been sent, therefore
+	// (since the standard loadware insists that it be sent before any other
+	// packets are sent) no other packets should be sent yet.
+
+	unsigned short i2eUsingIrq;
+
+	// This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us
+	// putting more in the mailbox until an appropriate mailbox message is
+	// received.
+
+	unsigned char  i2eWaitingForEmptyFifo;
+
+	// Any mailbox bits waiting to be sent to the board are OR'ed in here.
+
+	unsigned char  i2eOutMailWaiting;
+
+	// The head of any incoming packet is read into here, is then examined and 
+	// we dispatch accordingly.
+
+	unsigned short i2eLeadoffWord[1];
+
+	// Running counter of interrupts where the mailbox indicated incoming data.
+
+	unsigned short i2eFifoInInts;
+
+	// Running counter of interrupts where the mailbox indicated outgoing data
+	// had been stripped.
+
+	unsigned short i2eFifoOutInts;
+
+	// If not void, gives the address of a routine to call if fatal board error
+	// is found (only applies to standard l/w).
+
+	void  (*i2eFatalTrap)(struct _i2eBordStr *);
+
+	// Will point to an array of some sort of channel structures (whose format
+	// is unknown at this level, being a function of what loadware is
+	// installed and the code configuration (max sizes of buffers, etc.)).
+
+	void  *i2eChannelPtr;
+
+	// Set indicates that the board has gone fatal.
+
+	unsigned short i2eFatal;
+
+	// The number of elements pointed to by i2eChannelPtr.
+
+	unsigned short i2eChannelCnt;
+
+	// Ring-buffers of channel structures whose channels have particular needs.
+
+	rwlock_t	Fbuf_spinlock;
+	volatile
+	unsigned short i2Fbuf_strip;	// Strip index
+	volatile 
+	unsigned short i2Fbuf_stuff;	// Stuff index
+	void  *i2Fbuf[CH_QUEUE_SIZE];	// An array of channel pointers
+									// of channels who need to send
+									// flow control packets.
+	rwlock_t	Dbuf_spinlock;
+	volatile
+	unsigned short i2Dbuf_strip;	// Strip index
+	volatile
+	unsigned short i2Dbuf_stuff;	// Stuff index
+	void  *i2Dbuf[CH_QUEUE_SIZE];	// An array of channel pointers
+									// of channels who need to send
+									// data or in-line command packets.
+	rwlock_t	Bbuf_spinlock;
+	volatile
+	unsigned short i2Bbuf_strip;	// Strip index
+	volatile
+	unsigned short i2Bbuf_stuff;	// Stuff index
+	void  *i2Bbuf[CH_QUEUE_SIZE];	// An array of channel pointers
+									// of channels who need to send
+									// bypass command packets.
+
+	/*
+	 * A set of flags to indicate that certain events have occurred on at least
+	 * one of the ports on this board. We use this to decide whether to spin
+	 * through the channels looking for breaks, etc.
+	 */
+	int		got_input;
+	int		status_change;
+	bidStat	channelBtypes;
+
+	/*
+	 * Debugging counters, etc.
+	 */
+	unsigned long debugFlowQueued;
+	unsigned long debugInlineQueued;
+	unsigned long debugDataQueued;
+	unsigned long debugBypassQueued;
+	unsigned long debugFlowCount;
+	unsigned long debugInlineCount;
+	unsigned long debugBypassCount;
+	
+	rwlock_t	read_fifo_spinlock;
+	rwlock_t	write_fifo_spinlock;
+
+//	For queuing interrupt bottom half handlers.	/\/\|=mhw=|\/\/
+	struct work_struct	tqueue_interrupt;
+
+	struct timer_list  SendPendingTimer;   // Used by iiSendPending
+	unsigned int	SendPendingRetry;
+} i2eBordStr, *i2eBordStrPtr;
+
+//-------------------------------------------------------------------
+// Macro Definitions for the indirect calls defined in the i2eBordStr
+//-------------------------------------------------------------------
+//
+#define iiDelay(a,b)          (*(a)->i2eDelay)(b)
+#define iiWriteBuf(a,b,c)     (*(a)->i2eWriteBuf)(a,b,c)
+#define iiReadBuf(a,b,c)      (*(a)->i2eReadBuf)(a,b,c)
+
+#define iiWriteWord(a,b)      (*(a)->i2eWriteWord)(a,b)
+#define iiReadWord(a)         (*(a)->i2eReadWord)(a)
+
+#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b)
+
+#define iiTxMailEmpty(a)      (*(a)->i2eTxMailEmpty)(a)
+#define iiTrySendMail(a,b)    (*(a)->i2eTrySendMail)(a,b)
+
+#define iiGetMail(a)          (*(a)->i2eGetMail)(a)
+#define iiEnableMailIrq(a)    (*(a)->i2eEnableMailIrq)(a)
+#define iiDisableMailIrq(a)   (*(a)->i2eWriteMask)(a,0)
+#define iiWriteMask(a,b)      (*(a)->i2eWriteMask)(a,b)
+
+//-------------------------------------------
+// Manifests for i2eBordStr:
+//-------------------------------------------
+
+typedef void (*delayFunc_t)(unsigned int);
+
+// i2eValid
+//
+#define I2E_MAGIC       0x4251   // Structure is valid.
+#define I2E_INCOMPLETE  0x1122   // Structure failed during init.
+
+
+// i2eError
+//
+#define I2EE_GOOD       0	// Operation successful
+#define I2EE_BADADDR    1	// Address out of range
+#define I2EE_BADSTATE   2	// Attempt to perform a function when the board
+							// structure was in the incorrect state
+#define I2EE_BADMAGIC   3	// Bad magic number from Power On test (i2ePomSize
+							// reflects what was read
+#define I2EE_PORM_SHORT 4	// Power On message too short
+#define I2EE_PORM_LONG  5	// Power On message too long
+#define I2EE_BAD_FAMILY 6	// Un-supported board family type
+#define I2EE_INCONSIST  7	// Firmware reports something impossible,
+							// e.g. unexpected number of ports... Almost no
+							// excuse other than bad FIFO...
+#define I2EE_POSTERR    8	// Power-On self test reported a bad error
+#define I2EE_BADBUS     9	// Unknown Bus type declared in message
+#define I2EE_TXE_TIME   10	// Timed out waiting for TX Fifo to empty
+#define I2EE_INVALID    11	// i2eValid field does not indicate a valid and
+							// complete board structure (for functions which
+							// require this be so.)
+#define I2EE_BAD_PORT   12	// Discrepancy between channels actually found and
+							// what the product is supposed to have. Check
+							// i2eGoodMap vs i2eChannelMap for details.
+#define I2EE_BAD_IRQ    13	// Someone specified an unsupported IRQ
+#define I2EE_NOCHANNELS 14	// No channel structures have been defined (for
+							// functions requiring this).
+
+// i2eFifoStyle
+//
+#define FIFO_II   0  /* IntelliPort-II style: see also i2hw.h */
+#define FIFO_IIEX 1  /* IntelliPort-IIEX style */
+
+// i2eGetMail
+//
+#define NO_MAIL_HERE    0x1111	// Since mail is unsigned char, cannot possibly
+								// promote to 0x1111.
+// i2eState
+//
+#define II_STATE_COLD      0  // Addresses have been defined, but board not even
+							  // reset yet.
+#define II_STATE_RESET     1  // Board,if it exists, has just been reset
+#define II_STATE_READY     2  // Board ready for its first block
+#define II_STATE_LOADING   3  // Board continuing load
+#define II_STATE_LOADED    4  // Board has finished load: status ok
+#define II_STATE_BADLOAD   5  // Board has finished load: failed!
+#define II_STATE_STDLOADED 6  // Board has finished load: standard firmware
+
+// i2eUsingIrq
+//
+#define I2_IRQ_UNDEFINED	0x1352  /* No valid irq (or polling = 0) can
+					 * ever promote to this! */
+//------------------------------------------
+// Handy Macros for i2ellis.c and others
+// Note these are common to -II and -IIEX
+//------------------------------------------
+
+// Given a pointer to the board structure, does the input FIFO have any data or
+// not?
+//
+#define I2_HAS_INPUT(pB)	!(inb(pB->i2eStatus) & ST_IN_EMPTY)
+
+// Given a pointer to the board structure, is there anything in the incoming
+// mailbox?
+//
+#define I2_HAS_MAIL(pB)		(inb(pB->i2eStatus) & ST_IN_MAIL)
+
+#define I2_UPDATE_FIFO_ROOM(pB)	((pB)->i2eFifoRemains = (pB)->i2eFifoSize)
+
+//------------------------------------------
+// Function Declarations for i2ellis.c
+//------------------------------------------
+//
+// Functions called directly
+//
+// Initialization of a board & structure is in four (five!) parts:
+//
+// 1) iiSetAddress() - Define the board address & delay function for a board.
+// 2) iiReset()      - Reset the board   (provided it exists)
+//       -- Note you may do this to several boards --
+// 3) iiResetDelay() - Delay for 2 seconds (once for all boards)
+// 4) iiInitialize() - Attempt to read Power-up message; further initialize
+//                     accelerators
+//
+// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write
+// loadware.  To change loadware, you must begin again with step 2, resetting
+// the board again (step 1 not needed).
+
+static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
+static int iiReset(i2eBordStrPtr);
+static int iiResetDelay(i2eBordStrPtr);
+static int iiInitialize(i2eBordStrPtr);
+
+// Routine to validate that all channels expected are there.
+//
+extern int iiValidateChannels(i2eBordStrPtr);
+
+// Routine used to download a block of loadware.
+//
+static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int);
+
+// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile:
+//
+#define II_DOWN_BADVALID   0	// board structure is invalid
+#define II_DOWN_CONTINUING 1	// So far, so good, firmware expects more
+#define II_DOWN_GOOD       2	// Download complete, CRC good
+#define II_DOWN_BAD        3	// Download complete, but CRC bad
+#define II_DOWN_BADFILE    4	// Bad magic number in loadware file
+#define II_DOWN_BADSTATE   5	// Board is in an inappropriate state for
+								// downloading loadware. (see i2eState)
+#define II_DOWN_TIMEOUT    6	// Timeout waiting for firmware
+#define II_DOWN_OVER       7	// Too much data
+#define II_DOWN_UNDER      8	// Not enough data
+#define II_DOWN_NOFILE     9	// Loadware file not found
+
+// Routine to download an entire loadware module: Return values are a subset of
+// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING
+//
+static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);
+
+// Many functions defined here return True if good, False otherwise, with an
+// error code in i2eError field. Here is a handy macro for setting the error
+// code and returning.
+//
+#define I2_COMPLETE(pB,code) do { \
+		 pB->i2eError = code; \
+		 return (code == I2EE_GOOD);\
+	} while (0)
+
+#endif   // I2ELLIS_H
diff --git a/drivers/staging/tty/ip2/i2hw.h b/drivers/staging/tty/ip2/i2hw.h
new file mode 100644
index 0000000..c0ba6c0
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2hw.h
@@ -0,0 +1,652 @@
+/*******************************************************************************
+*
+*   (c) 1999 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Definitions limited to properties of the hardware or the
+*                bootstrap firmware. As such, they are applicable regardless of
+*                operating system or loadware (standard or diagnostic).
+*
+*******************************************************************************/
+#ifndef I2HW_H
+#define I2HW_H 1
+//------------------------------------------------------------------------------
+// Revision History:
+//
+// 23 September 1991 MAG   First Draft Started...through...
+// 11 October 1991   ...   Continuing development...
+//  6 August 1993          Added support for ISA-4 (asic) which is architected
+//                         as an ISA-CEX with a single 4-port box.
+//
+// 20 December 1996  AKM   Version for Linux
+//
+//------------------------------------------------------------------------------
+/*------------------------------------------------------------------------------
+
+HARDWARE DESCRIPTION:
+
+Introduction:
+
+The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8)
+addresses in the host's I/O space.
+
+Some addresses are used to transfer data to/from the board, some to transfer
+so-called "mailbox" messages, and some to read bit-mapped status information.
+While all the products in the line are functionally similar, some use a 16-bit
+data path to transfer data while others use an 8-bit path. Also, the use of
+command /status/mailbox registers differs slightly between the II and IIEX
+branches of the family.
+
+The host determines what type of board it is dealing with by reading a string of
+sixteen characters from the board. These characters are always placed in the
+fifo by the board's local processor whenever the board is reset (either from
+power-on or under software control) and are known as the "Power-on Reset
+Message." In order that this message can be read from either type of board, the
+hardware registers used in reading this message are the same. Once this message
+has been read by the host, then it has the information required to operate.
+
+General Differences between boards:
+
+The greatest structural difference is between the -II and -IIEX families of
+product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support
+the data path, mailbox registers, and status registers. This chip contains some
+features which are not used in the IntelliPort-II products; a description of
+these is omitted here. Because of these many features, it contains many
+registers, too many to access directly within a small address space. They are
+accessed by first writing a value to a "pointer" register. This value selects
+the register to be accessed.  The next read or write to that address accesses
+the selected register rather than the pointer register.
+
+The -IIEX boards use a proprietary design similar to the Am4701 in function. But
+because of a simpler, more streamlined design it doesn't require so many
+registers. This means they can be accessed directly in single operations rather
+than through a pointer register.
+
+Besides these differences, there are differences in whether 8-bit or 16-bit
+transfers are used to move data to the board.
+
+The -II boards are capable only of 8-bit data transfers, while the -IIEX boards
+may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP
+switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit
+transfers are supported (and will be expected by the standard loadware). The
+on-board firmware can determine the position of the switch, and whether the
+board is installed in a 16-bit slot; it supplies this information to the host as
+part of the power-up reset message.
+
+The configuration switch (#8) and slot selection do not directly configure the
+hardware. It is up to the on-board loadware and host-based drivers to act
+according to the selected options. That is, loadware and drivers could be
+written to perform 8-bit transfers regardless of the state of the DIP switch or
+slot (and in a diagnostic environment might well do so). Likewise, 16-bit
+transfers could be performed as long as the card is in a 16-bit slot.
+
+Note the slot selection and DIP switch selection are provided separately: a
+board running in 8-bit mode in a 16-bit slot has a greater range of possible
+interrupts to choose from; information of potential use to the host.
+
+All 8-bit data transfers are done in the same way, regardless of whether on a
+-II board or a -IIEX board.
+
+The host must consider two things then: 1) whether a -II or -IIEX product is
+being used, and 2) whether an 8-bit or 16-bit data path is used.
+
+A further difference is that -II boards always have a 512-byte fifo operating in
+each direction. -IIEX boards may use fifos of varying size; this size is
+reported as part of the power-up message.
+
+I/O Map Of IntelliPort-II and IntelliPort-IIEX boards:
+(Relative to the chosen base address)
+
+Addr  R/W      IntelliPort-II    IntelliPort-IIEX
+----  ---      --------------    ----------------
+0     R/W      Data Port (byte)  Data Port (byte or word)
+1     R/W      (Not used)        (MSB of word-wide data written to Data Port)
+2     R        Status Register   Status Register
+2     W        Pointer Register  Interrupt Mask Register
+3     R/W      (Not used)        Mailbox Registers (6 bits: 11111100)
+4,5   --       Reserved for future products
+6     --       Reserved for future products
+7     R        Guaranteed to have no effect
+7     W        Hardware reset of board.
+
+
+Rules:
+All data transfers are performed using the even i/o address. If byte-wide data
+transfers are being used, do INB/OUTB operations on the data port. If word-wide
+transfers are used, do INW/OUTW operations. In some circumstances (such as
+reading the power-up message) you will do INB from the data port, but in this
+case the MSB of each word read is lost. When accessing all other unreserved
+registers, use byte operations only.
+------------------------------------------------------------------------------*/
+
+//------------------------------------------------
+// Mandatory Includes:
+//------------------------------------------------
+//
+#include "ip2types.h"
+
+//-------------------------------------------------------------------------
+// Manifests for the I/O map:
+//-------------------------------------------------------------------------
+// R/W: Data port (byte) for IntelliPort-II,
+// R/W: Data port (byte or word) for IntelliPort-IIEX
+// Incoming or outgoing data passes through a FIFO, the status of which is
+// available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is
+// the primary means of transferring data, commands, flow-control, and status
+// information between the host and board.
+//
+#define FIFO_DATA 0
+
+// Another way of passing information between the board and the host is
+// through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of
+// data.  Writing data to the mailbox causes a status bit to be set, and
+// potentially interrupting the intended receiver. The sender has some way to
+// determine whether the data has been read yet; as soon as it has, it may send
+// more. The mailboxes are handled differently on -II and -IIEX products, as
+// suggested below.
+//------------------------------------------------------------------------------
+// Read: Status Register for IntelliPort-II or -IIEX
+// The presence of any bit set here will cause an interrupt to the host,
+// provided the corresponding bit has been unmasked in the interrupt mask
+// register. Furthermore, interrupts to the host are disabled globally until the
+// loadware selects the irq line to use. With the exception of STN_MR, the bits
+// remain set so long as the associated condition is true.
+//
+#define FIFO_STATUS 2
+
+// Bit map of status bits which are identical for -II and -IIEX
+//
+#define ST_OUT_FULL  0x40  // Outbound FIFO full
+#define ST_IN_EMPTY  0x20  // Inbound FIFO empty
+#define ST_IN_MAIL   0x04  // Inbound Mailbox full
+
+// The following exists only on the Intelliport-IIEX, and indicates that the
+// board has not read the last outgoing mailbox data yet. In the IntelliPort-II,
+// the outgoing mailbox may be read back: a zero indicates the board has read
+// the data.
+//
+#define STE_OUT_MAIL 0x80  // Outbound mailbox full (!)
+
+// The following bits are defined differently for -II and -IIEX boards. Code
+// which relies on these bits will need to be functionally different for the two
+// types of boards and should be generally avoided because of the additional
+// complexity this creates:
+
+// Bit map of status bits only on -II
+
+// Fifo has been RESET (cleared when the status register is read). Note that
+// this condition cannot be masked and would always interrupt the host, except
+// that the hardware reset also disables interrupts globally from the board
+// until re-enabled by loadware. This could also arise from the
+// Am4701-supported command to reset the chip, but this command is generally not
+// used here.
+//
+#define STN_MR       0x80
+
+// See the AMD Am4701 data sheet for details on the following four bits. They
+// are not presently used by Computone drivers.
+//
+#define STN_OUT_AF  0x10  // Outbound FIFO almost full (programmable)
+#define STN_IN_AE   0x08  // Inbound FIFO almost empty (programmable)
+#define STN_BD      0x02  // Inbound byte detected
+#define STN_PE      0x01  // Parity/Framing condition detected
+
+// Bit-map of status bits only on -IIEX
+//
+#define STE_OUT_HF  0x10  // Outbound FIFO half full
+#define STE_IN_HF   0x08  // Inbound FIFO half full
+#define STE_IN_FULL 0x02  // Inbound FIFO full
+#define STE_OUT_MT  0x01  // Outbound FIFO empty
+
+//------------------------------------------------------------------------------
+
+// Intelliport-II -- Write Only: the pointer register.
+// Values are written to this register to select the Am4701 internal register to
+// be accessed on the next operation.
+//
+#define FIFO_PTR    0x02
+
+// Values for the pointer register
+//
+#define SEL_COMMAND 0x1    // Selects the Am4701 command register
+
+// Some possible commands:
+//
+#define SEL_CMD_MR  0x80	// Am4701 command to reset the chip
+#define SEL_CMD_SH  0x40	// Am4701 command to map the "other" port into the
+							// status register.
+#define SEL_CMD_UNSH   0	// Am4701 command to "unshift": port maps into its
+							// own status register.
+#define SEL_MASK     0x2	// Selects the Am4701 interrupt mask register. The
+							// interrupt mask register is bit-mapped to match 
+							// the status register (FIFO_STATUS) except for
+							// STN_MR. (See above.)
+#define SEL_BYTE_DET 0x3	// Selects the Am4701 byte-detect register. (Not
+							// normally used except in diagnostics.)
+#define SEL_OUTMAIL  0x4	// Selects the outbound mailbox (R/W). Reading back
+							// a value of zero indicates that the mailbox has
+							// been read by the board and is available for more
+							// data./ Writing to the mailbox optionally
+							// interrupts the board, depending on the loadware's
+							// setting of its interrupt mask register.
+#define SEL_AEAF     0x5	// Selects AE/AF threshold register.
+#define SEL_INMAIL   0x6	// Selects the inbound mailbox (Read)
+
+//------------------------------------------------------------------------------
+// IntelliPort-IIEX --  Write Only: interrupt mask (and misc flags) register:
+// Unlike IntelliPort-II, bit assignments do NOT match those of the status
+// register.
+//
+#define FIFO_MASK    0x2
+
+// Mailbox readback select:
+// If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If
+// clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox.
+// This is the normal situation. The clearing of a mailbox is determined on
+// -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback
+// capability is provided for diagnostic purposes only.
+//
+#define  MX_OUTMAIL_RSEL   0x80
+
+#define  MX_IN_MAIL  0x40	// Enables interrupts when incoming mailbox goes
+							// full (ST_IN_MAIL set).
+#define  MX_IN_FULL  0x20	// Enables interrupts when incoming FIFO goes full
+							// (STE_IN_FULL).
+#define  MX_IN_MT    0x08	// Enables interrupts when incoming FIFO goes empty
+							// (ST_IN_MT).
+#define  MX_OUT_FULL 0x04	// Enables interrupts when outgoing FIFO goes full
+							// (ST_OUT_FULL).
+#define  MX_OUT_MT   0x01	// Enables interrupts when outgoing FIFO goes empty
+							// (STE_OUT_MT).
+
+// Any remaining bits are reserved, and should be written to ZERO for
+// compatibility with future Computone products.
+
+//------------------------------------------------------------------------------
+// IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two
+// bits always read back 0).
+// Read:  One of the mailboxes, usually Inbound.
+//        Inbound Mailbox (MX_OUTMAIL_RSEL = 0)
+//        Outbound Mailbox (MX_OUTMAIL_RSEL = 1)
+// Write: Outbound Mailbox
+// For the IntelliPort-II boards, the outbound mailbox is read back to determine
+// whether the board has read the data (0 --> data has been read). For the
+// IntelliPort-IIEX, this is done by reading a status register. To determine
+// whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit
+// in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by
+// setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the
+// case with the -II boards. For this reason, FIFO_MAIL is normally used to read
+// the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for
+// MX_OUTMAIL_RSEL description.)
+//
+#define  FIFO_MAIL   0x3
+
+//------------------------------------------------------------------------------
+// WRITE ONLY:  Resets the board. (Data doesn't matter).
+//
+#define  FIFO_RESET  0x7
+
+//------------------------------------------------------------------------------
+// READ ONLY:  Will have no effect. (Data is undefined.)
+// Actually, there will be an effect, in that the operation is sure to generate
+// a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short
+// delays when no comparable time constant is available.
+//
+#define  FIFO_NOP    0x7
+
+//------------------------------------------------------------------------------
+// RESET & POWER-ON RESET MESSAGE
+/*------------------------------------------------------------------------------
+RESET:
+
+The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel
+reset, and via a write to the reset register described above. For products using
+the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses,
+the Power-up and channel reset sources cause additional hardware initialization
+which should only occur at system startup time.
+
+The third type of reset, called a "command reset", is done by writing any data
+to the FIFO_RESET address described above. This resets the on-board processor,
+FIFO, UARTS, and associated hardware.
+
+This passes control of the board to the bootstrap firmware, which performs a
+Power-On Self Test and which detects its current configuration. For example,
+-IIEX products determine the size of FIFO which has been installed, and the
+number and type of expansion boxes attached.
+
+This and other information is then written to the FIFO in a 16-byte data block
+to be read by the host. This block is guaranteed to be present within two (2)
+seconds of having received the command reset. The firmware is now ready to
+receive loadware from the host.
+
+It is good practice to perform a command reset to the board explicitly as part
+of your software initialization.  This allows your code to properly restart from
+a soft boot. (Many systems do not issue channel reset on soft boot).
+
+Because of a hardware reset problem on some of the Cirrus Logic 1400's which are
+used on the product, it is recommended that you reset the board twice, separated
+by an approximately 50 milliseconds delay. (VERY approximately: probably ok to
+be off by a factor of five. The important point is that the first command reset
+in fact generates a reset pulse on the board. This pulse is guaranteed to last
+less than 10 milliseconds. The additional delay ensures the 1400 has had the
+chance to respond sufficiently to the first reset. Why not a longer delay? Much
+more than 50 milliseconds gets to be noticable, but the board would still work.
+
+Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap
+firmware is ready to receive loadware.
+
+Note on Power-on Reset Message format:
+The various fields have been designed with future expansion in view.
+Combinations of bitfields and values have been defined which define products
+which may not currently exist. This has been done to allow drivers to anticipate
+the possible introduction of products in a systematic fashion. This is not
+intended to suggest that each potential product is actually under consideration.
+------------------------------------------------------------------------------*/
+
+//----------------------------------------
+// Format of Power-on Reset Message
+//----------------------------------------
+
+typedef union _porStr		// "por" stands for Power On Reset
+{
+	unsigned char  c[16];	// array used when considering the message as a
+							// string of undifferentiated characters
+
+	struct					// Elements used when considering values
+	{
+		// The first two bytes out of the FIFO are two magic numbers. These are
+		// intended to establish that there is indeed a member of the
+		// IntelliPort-II(EX) family present. The remaining bytes may be 
+		// expected // to be valid. When reading the Power-on Reset message, 
+		// if the magic numbers do not match it is probably best to stop
+		// reading immediately. You are certainly not reading our board (unless
+		// hardware is faulty), and may in fact be reading some other piece of
+		// hardware.
+
+		unsigned char porMagic1;   // magic number: first byte == POR_MAGIC_1 
+		unsigned char porMagic2;   // magic number: second byte == POR_MAGIC_2 
+
+		// The Version, Revision, and Subrevision are stored as absolute numbers
+		// and would normally be displayed in the format V.R.S (e.g. 1.0.2)
+
+		unsigned char porVersion;  // Bootstrap firmware version number
+		unsigned char porRevision; // Bootstrap firmware revision number
+		unsigned char porSubRev;   // Bootstrap firmware sub-revision number
+
+		unsigned char porID;	// Product ID:  Bit-mapped according to
+								// conventions described below. Among other
+								// things, this allows us to distinguish
+								// IntelliPort-II boards from IntelliPort-IIEX
+								// boards.
+
+		unsigned char porBus;	// IntelliPort-II: Unused
+								// IntelliPort-IIEX: Bus Information:
+								// Bit-mapped below
+
+		unsigned char porMemory;	// On-board DRAM size: in 32k blocks
+
+		// porPorts1 (and porPorts2) are used to determine the ports which are
+		// available to the board. For non-expandable product, a single number 
+		// is sufficient. For expandable product, the board may be connected
+		// to as many as four boxes. Each box may be (so far) either a 16-port
+		// or an 8-port size. Whenever an 8-port box is used, the remaining 8
+		// ports leave gaps between existing channels. For that reason,
+		// expandable products must report a MAP of available channels. Since 
+		// each UART supports four ports, we represent each UART found by a
+		// single bit. Using two bytes to supply the mapping information we
+		// report the presense or absense of up to 16 UARTS, or 64 ports in
+		// steps of 4 ports. For -IIEX products, the ports are numbered
+		// starting at the box closest to the controller in the "chain".
+
+		// Interpreted Differently for IntelliPort-II and -IIEX.
+		// -II:   Number of ports (Derived actually from product ID). See
+		// Diag1&2 to indicate if uart was actually detected.
+		// -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This
+		//        bitmap is based on detecting the uarts themselves; 
+		//        see porFlags for information from the box i.d's.
+		unsigned char  porPorts1;
+
+		unsigned char  porDiag1;	// Results of on-board P.O.S.T, 1st byte
+		unsigned char  porDiag2;	// Results of on-board P.O.S.T, 2nd byte
+		unsigned char  porSpeed;	// Speed of local CPU: given as MHz x10
+									// e.g., 16.0 MHz CPU is reported as 160
+		unsigned char  porFlags;	// Misc information (see manifests below)
+									// Bit-mapped: CPU type, UART's present
+
+		unsigned char  porPorts2;	// -II:  Undefined
+									// -IIEX: Bit-map of UARTS found, MSB (see
+									//        above for LSB)
+
+		// IntelliPort-II: undefined
+		// IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the
+		// host interface FIFO, in each direction. When running the -IIEX in
+		// 8-bit mode, fifo capacity is halved. The bootstrap firmware will
+		// have already accounted for this fact in generating this number.
+		unsigned char  porFifoSize;
+
+		// IntelliPort-II: undefined
+		// IntelliPort-IIEX: The number of boxes connected. (Presently 1-4)
+		unsigned char  porNumBoxes;
+	} e;
+} porStr, *porStrPtr;
+
+//--------------------------
+// Values for porStr fields
+//--------------------------
+
+//---------------------
+// porMagic1, porMagic2
+//----------------------
+//
+#define  POR_MAGIC_1    0x96  // The only valid value for porMagic1
+#define  POR_MAGIC_2    0x35  // The only valid value for porMagic2
+#define  POR_1_INDEX    0     // Byte position of POR_MAGIC_1
+#define  POR_2_INDEX    1     // Ditto for POR_MAGIC_2
+
+//----------------------
+// porID
+//----------------------
+//
+#define  POR_ID_FAMILY  0xc0	// These bits indicate the general family of
+								// product.
+#define  POR_ID_FII     0x00	// Family is "IntelliPort-II"
+#define  POR_ID_FIIEX   0x40	// Family is "IntelliPort-IIEX"
+
+// These bits are reserved, presently zero. May be used at a later date to
+// convey other product information.
+//
+#define POR_ID_RESERVED 0x3c
+
+#define POR_ID_SIZE     0x03	// Remaining bits indicate number of ports &
+								// Connector information.
+#define POR_ID_II_8     0x00	// For IntelliPort-II, indicates 8-port using
+								// standard brick.
+#define POR_ID_II_8R    0x01	// For IntelliPort-II, indicates 8-port using
+								// RJ11's (no CTS)
+#define POR_ID_II_6     0x02	// For IntelliPort-II, indicates 6-port using
+								// RJ45's
+#define POR_ID_II_4     0x03	// For IntelliPort-II, indicates 4-port using
+								// 4xRJ45 connectors
+#define POR_ID_EX       0x00	// For IntelliPort-IIEX, indicates standard
+								// expandable controller (other values reserved)
+
+//----------------------
+// porBus
+//----------------------
+
+// IntelliPort-IIEX only: Board is installed in a 16-bit slot
+//
+#define POR_BUS_SLOT16  0x20
+
+// IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface
+// operation.
+// 
+#define POR_BUS_DIP16   0x10
+
+// Bits 0-2 indicate type of bus: This information is stored in the bootstrap
+// loadware, different loadware being used on different products for different
+// buses. For most situations, the drivers do not need this information; but it
+// is handy in a diagnostic environment. For example, on microchannel boards,
+// you would not want to try to test several interrupts, only the one for which
+// you were configured.
+//
+#define  POR_BUS_TYPE   0x07
+
+// Unknown:  this product doesn't know what bus it is running in. (e.g. if same
+// bootstrap firmware were wanted for two different buses.)
+//
+#define  POR_BUS_T_UNK  0
+
+// Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK
+// state, since the same bootstrap firmware is used for each.
+
+#define  POR_BUS_T_MCA  1  // MCA BUS */
+#define  POR_BUS_T_EISA 2  // EISA BUS */
+#define  POR_BUS_T_ISA  3  // ISA BUS */
+
+// Values 4-7 Reserved
+
+// Remaining bits are reserved
+
+//----------------------
+// porDiag1
+//----------------------
+
+#define  POR_BAD_MAPPER 0x80	// HW failure on P.O.S.T: Chip mapper failed
+
+// These two bits valid only for the IntelliPort-II
+//
+#define  POR_BAD_UART1  0x01	// First  1400 bad
+#define  POR_BAD_UART2  0x02	// Second 1400 bad
+
+//----------------------
+// porDiag2
+//----------------------
+
+#define  POR_DEBUG_PORT 0x80	// debug port was detected by the P.O.S.T
+#define  POR_DIAG_OK    0x00	// Indicates passage: Failure codes not yet
+								// available.
+								// Other bits undefined.
+//----------------------
+// porFlags
+//----------------------
+
+#define  POR_CPU     0x03	// These bits indicate supposed CPU type
+#define  POR_CPU_8   0x01	// Board uses an 80188 (no such thing yet)
+#define  POR_CPU_6   0x02	// Board uses an 80186 (all existing products)
+#define  POR_CEX4    0x04	// If set, this is an ISA-CEX/4: An ISA-4 (asic)
+							// which is architected like an ISA-CEX connected
+							// to a (hitherto impossible) 4-port box.
+#define POR_BOXES    0xf0	// Valid for IntelliPort-IIEX only: Map of Box
+							// sizes based on box I.D.
+#define POR_BOX_16   0x10	// Set indicates 16-port, clear 8-port
+
+//-------------------------------------
+// LOADWARE and DOWNLOADING CODE
+//-------------------------------------
+
+/*
+Loadware may be sent to the board in two ways:
+1) It may be read from a (binary image) data file block by block as each block
+	is sent to the board. This is only possible when the initialization is
+	performed by code which can access your file system. This is most suitable
+	for diagnostics and appications which use the interface library directly.
+
+2) It may be hard-coded into your source by including a .h file (typically
+	supplied by Computone), which declares a data array and initializes every
+	element. This achieves the same result as if an entire loadware file had 
+	been read into the array.
+
+	This requires more data space in your program, but access to the file system
+	is not required. This method is more suited to driver code, which typically
+	is running at a level too low to access the file system directly.
+
+At present, loadware can only be generated at Computone.
+
+All Loadware begins with a header area which has a particular format. This
+includes a magic number which identifies the file as being (purportedly)
+loadware, CRC (for the loader), and version information.
+*/
+
+
+//-----------------------------------------------------------------------------
+// Format of loadware block
+//
+// This is defined as a union so we can pass a pointer to one of these items
+// and (if it is the first block) pick out the version information, etc.
+//
+// Otherwise, to deal with this as a simple character array
+//------------------------------------------------------------------------------
+
+#define LOADWARE_BLOCK_SIZE   512   // Number of bytes in each block of loadware
+
+typedef union _loadHdrStr
+{
+	unsigned char c[LOADWARE_BLOCK_SIZE];  // Valid for every block
+
+	struct	// These fields are valid for only the first block of loadware.
+	{
+		unsigned char loadMagic;		// Magic number: see below
+		unsigned char loadBlocksMore;	// How many more blocks?
+		unsigned char loadCRC[2];		// Two CRC bytes: used by loader
+		unsigned char loadVersion;		// Version number
+		unsigned char loadRevision;		// Revision number
+		unsigned char loadSubRevision;	// Sub-revision number
+		unsigned char loadSpares[9];	// Presently unused
+		unsigned char loadDates[32];	// Null-terminated string which can give
+										// date and time of compilation
+	} e;
+} loadHdrStr, *loadHdrStrPtr;
+
+//------------------------------------
+// Defines for downloading code:
+//------------------------------------
+
+// The loadMagic field in the first block of the loadfile must be this, else the
+// file is not valid.
+//
+#define  MAGIC_LOADFILE 0x3c
+
+// How do we know the load was successful? On completion of the load, the
+// bootstrap firmware returns a code to indicate whether it thought the download
+// was valid and intends to execute it. These are the only possible valid codes:
+//
+#define  LOADWARE_OK    0xc3        // Download was ok
+#define  LOADWARE_BAD   0x5a        // Download was bad (CRC error)
+
+// Constants applicable to writing blocks of loadware:
+// The first block of loadware might take 600 mS to load, in extreme cases.
+// (Expandable board: worst case for sending startup messages to the LCD's).
+// The 600mS figure is not really a calculation, but a conservative
+// guess/guarantee. Usually this will be within 100 mS, like subsequent blocks.
+//
+#define  MAX_DLOAD_START_TIME 1000  // 1000 mS
+#define  MAX_DLOAD_READ_TIME  100   // 100 mS
+
+// Firmware should respond with status (see above) within this long of host
+// having sent the final block.
+//
+#define  MAX_DLOAD_ACK_TIME   100   // 100 mS, again!
+
+//------------------------------------------------------
+// MAXIMUM NUMBER OF PORTS PER BOARD:
+// This is fixed for now (with the expandable), but may
+// be expanding according to even newer products.
+//------------------------------------------------------
+//
+#define ABS_MAX_BOXES   4     // Absolute most boxes per board
+#define ABS_BIGGEST_BOX 16    // Absolute the most ports per box
+#define ABS_MOST_PORTS  (ABS_MAX_BOXES * ABS_BIGGEST_BOX)
+
+#define I2_OUTSW(port, addr, count)	outsw((port), (addr), (((count)+1)/2))
+#define I2_OUTSB(port, addr, count)	outsb((port), (addr), (((count)+1))&-2)
+#define I2_INSW(port, addr, count)	insw((port), (addr), (((count)+1)/2))
+#define I2_INSB(port, addr, count)	insb((port), (addr), (((count)+1))&-2)
+
+#endif   // I2HW_H
+
diff --git a/drivers/staging/tty/ip2/i2lib.c b/drivers/staging/tty/ip2/i2lib.c
new file mode 100644
index 0000000..0d10b89
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2lib.c
@@ -0,0 +1,2214 @@
+/*******************************************************************************
+*
+*   (c) 1999 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: High-level interface code for the device driver. Uses the
+*                Extremely Low Level Interface Support (i2ellis.c). Provides an
+*                interface to the standard loadware, to support drivers or
+*                application code. (This is included source code, not a separate
+*                compilation module.)
+*
+*******************************************************************************/
+//------------------------------------------------------------------------------
+// Note on Strategy:
+// Once the board has been initialized, it will interrupt us when:
+// 1) It has something in the fifo for us to read (incoming data, flow control
+// packets, or whatever).
+// 2) It has stripped whatever we have sent last time in the FIFO (and
+// consequently is ready for more).
+//
+// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This
+// worsens performance considerably, but is done so that a great many channels
+// might use only a little memory.
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// Revision History:
+//
+// 0.00 -  4/16/91 --- First Draft
+// 0.01 -  4/29/91 --- 1st beta release
+// 0.02 -  6/14/91 --- Changes to allow small model compilation
+// 0.03 -  6/17/91 MAG Break reporting protected from interrupts routines with
+//                     in-line asm added for moving data to/from ring buffers,
+//                     replacing a variety of methods used previously.
+// 0.04 -  6/21/91 MAG Initial flow-control packets not queued until
+//                     i2_enable_interrupts time. Former versions would enqueue
+//                     them at i2_init_channel time, before we knew how many
+//                     channels were supposed to exist!
+// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now;
+//                     supports new 16-bit protocol and expandable boards.
+//      - 10/24/91 MAG Most changes in place and stable.
+// 0.06 -  2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no
+//                     argument.
+// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt
+//                     level (mostly responses to specific commands.)
+// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet
+// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE
+//                     turning on the interrupt.
+// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check
+//                     some incoming.
+//
+// 1.1  - 12/25/96 AKM Linux version.
+//      - 10/09/98 DMC Revised Linux version.
+//------------------------------------------------------------------------------
+
+//************
+//* Includes *
+//************
+
+#include <linux/sched.h>
+#include "i2lib.h"
+
+
+//***********************
+//* Function Prototypes *
+//***********************
+static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int);
+static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int );
+static void i2StripFifo(i2eBordStrPtr);
+static void i2StuffFifoBypass(i2eBordStrPtr);
+static void i2StuffFifoFlow(i2eBordStrPtr);
+static void i2StuffFifoInline(i2eBordStrPtr);
+static int i2RetryFlushOutput(i2ChanStrPtr);
+
+// Not a documented part of the library routines (careful...) but the Diagnostic
+// i2diag.c finds them useful to help the throughput in certain limited
+// single-threaded operations.
+static void iiSendPendingMail(i2eBordStrPtr);
+static void serviceOutgoingFifo(i2eBordStrPtr);
+
+// Functions defined in ip2.c as part of interrupt handling
+static void do_input(struct work_struct *);
+static void do_status(struct work_struct *);
+
+//***************
+//* Debug  Data *
+//***************
+#ifdef DEBUG_FIFO
+
+unsigned char DBGBuf[0x4000];
+unsigned short I = 0;
+
+static void
+WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) 
+{
+	char *p = src;
+
+	// XXX: We need a spin lock here if we ever use this again
+
+	while (*s) {	// copy label
+		DBGBuf[I] = *s++;
+		I = I++ & 0x3fff;
+	}
+	while (n--) {	// copy data
+		DBGBuf[I] = *p++;
+		I = I++ & 0x3fff;
+	}
+}
+
+static void
+fatality(i2eBordStrPtr pB )
+{
+	int i;
+
+	for (i=0;i<sizeof(DBGBuf);i++) {
+		if ((i%16) == 0)
+			printk("\n%4x:",i);
+		printk("%02x ",DBGBuf[i]);
+	}
+	printk("\n");
+	for (i=0;i<sizeof(DBGBuf);i++) {
+		if ((i%16) == 0)
+			printk("\n%4x:",i);
+		if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') {
+			printk(" %c ",DBGBuf[i]);
+		} else {
+			printk(" . ");
+		}
+	}
+	printk("\n");
+	printk("Last index %x\n",I);
+}
+#endif /* DEBUG_FIFO */
+
+//********
+//* Code *
+//********
+
+static inline int
+i2Validate ( i2ChanStrPtr pCh )
+{
+	//ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity,
+	//	(CHANNEL_MAGIC | CHANNEL_SUPPORT));
+	return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) 
+			  == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
+}
+
+static void iiSendPendingMail_t(unsigned long data)
+{
+	i2eBordStrPtr pB = (i2eBordStrPtr)data;
+
+	iiSendPendingMail(pB);
+}
+
+//******************************************************************************
+// Function:   iiSendPendingMail(pB)
+// Parameters: Pointer to a board structure
+// Returns:    Nothing
+//
+// Description:
+// If any outgoing mail bits are set and there is outgoing mailbox is empty,
+// send the mail and clear the bits.
+//******************************************************************************
+static void
+iiSendPendingMail(i2eBordStrPtr pB)
+{
+	if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
+	{
+		if (iiTrySendMail(pB, pB->i2eOutMailWaiting))
+		{
+			/* If we were already waiting for fifo to empty,
+			 * or just sent MB_OUT_STUFFED, then we are
+			 * still waiting for it to empty, until we should
+			 * receive an MB_IN_STRIPPED from the board.
+			 */
+			pB->i2eWaitingForEmptyFifo |=
+				(pB->i2eOutMailWaiting & MB_OUT_STUFFED);
+			pB->i2eOutMailWaiting = 0;
+			pB->SendPendingRetry = 0;
+		} else {
+/*		The only time we hit this area is when "iiTrySendMail" has
+		failed.  That only occurs when the outbound mailbox is
+		still busy with the last message.  We take a short breather
+		to let the board catch up with itself and then try again.
+		16 Retries is the limit - then we got a borked board.
+			/\/\|=mhw=|\/\/				*/
+
+			if( ++pB->SendPendingRetry < 16 ) {
+				setup_timer(&pB->SendPendingTimer,
+					iiSendPendingMail_t, (unsigned long)pB);
+				mod_timer(&pB->SendPendingTimer, jiffies + 1);
+			} else {
+				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
+			}
+		}
+	}
+}
+
+//******************************************************************************
+// Function:   i2InitChannels(pB, nChannels, pCh)
+// Parameters: Pointer to Ellis Board structure
+//             Number of channels to initialize
+//             Pointer to first element in an array of channel structures
+// Returns:    Success or failure
+//
+// Description:
+//
+// This function patches pointers, back-pointers, and initializes all the
+// elements in the channel structure array.
+//
+// This should be run after the board structure is initialized, through having
+// loaded the standard loadware (otherwise it complains).
+//
+// In any case, it must be done before any serious work begins initializing the
+// irq's or sending commands...
+//
+//******************************************************************************
+static int
+i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
+{
+	int index, stuffIndex;
+	i2ChanStrPtr *ppCh;
+	
+	if (pB->i2eValid != I2E_MAGIC) {
+		I2_COMPLETE(pB, I2EE_BADMAGIC);
+	}
+	if (pB->i2eState != II_STATE_STDLOADED) {
+		I2_COMPLETE(pB, I2EE_BADSTATE);
+	}
+
+	rwlock_init(&pB->read_fifo_spinlock);
+	rwlock_init(&pB->write_fifo_spinlock);
+	rwlock_init(&pB->Dbuf_spinlock);
+	rwlock_init(&pB->Bbuf_spinlock);
+	rwlock_init(&pB->Fbuf_spinlock);
+	
+	// NO LOCK needed yet - this is init
+
+	pB->i2eChannelPtr = pCh;
+	pB->i2eChannelCnt = nChannels;
+
+	pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0;
+	pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0;
+	pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0;
+
+	pB->SendPendingRetry = 0;
+
+	memset ( pCh, 0, sizeof (i2ChanStr) * nChannels );
+
+	for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf);
+		  nChannels && index < ABS_MOST_PORTS;
+		  index++)
+	{
+		if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
+			continue;
+		}
+		rwlock_init(&pCh->Ibuf_spinlock);
+		rwlock_init(&pCh->Obuf_spinlock);
+		rwlock_init(&pCh->Cbuf_spinlock);
+		rwlock_init(&pCh->Pbuf_spinlock);
+		// NO LOCK needed yet - this is init
+		// Set up validity flag according to support level
+		if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
+			pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT;
+		} else {
+			pCh->validity = CHANNEL_MAGIC;
+		}
+		pCh->pMyBord = pB;      /* Back-pointer */
+
+		// Prepare an outgoing flow-control packet to send as soon as the chance
+		// occurs.
+		if ( pCh->validity & CHANNEL_SUPPORT ) {
+			pCh->infl.hd.i2sChannel = index;
+			pCh->infl.hd.i2sCount = 5;
+			pCh->infl.hd.i2sType = PTYPE_BYPASS;
+			pCh->infl.fcmd = 37;
+			pCh->infl.asof = 0;
+			pCh->infl.room = IBUF_SIZE - 1;
+
+			pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full
+
+		// The following is similar to calling i2QueueNeeds, except that this
+		// is done in longhand, since we are setting up initial conditions on
+		// many channels at once.
+			pCh->channelNeeds = NEED_FLOW;  // Since starting from scratch
+			pCh->sinceLastFlow = 0;         // No bytes received since last flow
+											// control packet was queued
+			stuffIndex++;
+			*ppCh++ = pCh;      // List this channel as needing
+								// initial flow control packet sent
+		}
+
+		// Don't allow anything to be sent until the status packets come in from
+		// the board.
+
+		pCh->outfl.asof = 0;
+		pCh->outfl.room = 0;
+
+		// Initialize all the ring buffers
+
+		pCh->Ibuf_stuff = pCh->Ibuf_strip = 0;
+		pCh->Obuf_stuff = pCh->Obuf_strip = 0;
+		pCh->Cbuf_stuff = pCh->Cbuf_strip = 0;
+
+		memset( &pCh->icount, 0, sizeof (struct async_icount) );
+		pCh->hotKeyIn       = HOT_CLEAR;
+		pCh->channelOptions = 0;
+		pCh->bookMarks      = 0;
+		init_waitqueue_head(&pCh->pBookmarkWait);
+
+		init_waitqueue_head(&pCh->open_wait);
+		init_waitqueue_head(&pCh->close_wait);
+		init_waitqueue_head(&pCh->delta_msr_wait);
+
+		// Set base and divisor so default custom rate is 9600
+		pCh->BaudBase    = 921600;	// MAX for ST654, changed after we get
+		pCh->BaudDivisor = 96;		// the boxids (UART types) later
+
+		pCh->dataSetIn   = 0;
+		pCh->dataSetOut  = 0;
+
+		pCh->wopen       = 0;
+		pCh->throttled   = 0;
+
+		pCh->speed       = CBR_9600;
+
+		pCh->flags    = 0;
+
+		pCh->ClosingDelay     = 5*HZ/10;
+		pCh->ClosingWaitTime  = 30*HZ;
+
+		// Initialize task queue objects
+		INIT_WORK(&pCh->tqueue_input, do_input);
+		INIT_WORK(&pCh->tqueue_status, do_status);
+
+#ifdef IP2DEBUG_TRACE
+		pCh->trace = ip2trace;
+#endif
+
+		++pCh;
+     	--nChannels;
+	}
+	// No need to check for wrap here; this is initialization.
+	pB->i2Fbuf_stuff = stuffIndex;
+	I2_COMPLETE(pB, I2EE_GOOD);
+
+}
+
+//******************************************************************************
+// Function:   i2DeQueueNeeds(pB, type)
+// Parameters: Pointer to a board structure
+//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
+// Returns:   
+//             Pointer to a channel structure
+//
+// Description: Returns pointer struct of next channel that needs service of
+//  the type specified. Otherwise returns a NULL reference.
+//
+//******************************************************************************
+static i2ChanStrPtr 
+i2DeQueueNeeds(i2eBordStrPtr pB, int type)
+{
+	unsigned short queueIndex;
+	unsigned long flags;
+
+	i2ChanStrPtr pCh = NULL;
+
+	switch(type) {
+
+	case  NEED_INLINE:
+
+		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
+		if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
+		{
+			queueIndex = pB->i2Dbuf_strip;
+			pCh = pB->i2Dbuf[queueIndex];
+			queueIndex++;
+			if (queueIndex >= CH_QUEUE_SIZE) {
+				queueIndex = 0;
+			}
+			pB->i2Dbuf_strip = queueIndex;
+			pCh->channelNeeds &= ~NEED_INLINE;
+		}
+		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
+		break;
+
+	case NEED_BYPASS:
+
+		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
+		if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
+		{
+			queueIndex = pB->i2Bbuf_strip;
+			pCh = pB->i2Bbuf[queueIndex];
+			queueIndex++;
+			if (queueIndex >= CH_QUEUE_SIZE) {
+				queueIndex = 0;
+			}
+			pB->i2Bbuf_strip = queueIndex;
+			pCh->channelNeeds &= ~NEED_BYPASS;
+		}
+		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
+		break;
+	
+	case NEED_FLOW:
+
+		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
+		if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
+		{
+			queueIndex = pB->i2Fbuf_strip;
+			pCh = pB->i2Fbuf[queueIndex];
+			queueIndex++;
+			if (queueIndex >= CH_QUEUE_SIZE) {
+				queueIndex = 0;
+			}
+			pB->i2Fbuf_strip = queueIndex;
+			pCh->channelNeeds &= ~NEED_FLOW;
+		}
+		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
+		break;
+	default:
+		printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type);
+		break;
+	}
+	return pCh;
+}
+
+//******************************************************************************
+// Function:   i2QueueNeeds(pB, pCh, type)
+// Parameters: Pointer to a board structure
+//             Pointer to a channel structure
+//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
+// Returns:    Nothing
+//
+// Description:
+// For each type of need selected, if the given channel is not already in the
+// queue, adds it, and sets the flag indicating it is in the queue.
+//******************************************************************************
+static void
+i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
+{
+	unsigned short queueIndex;
+	unsigned long flags;
+
+	// We turn off all the interrupts during this brief process, since the
+	// interrupt-level code might want to put things on the queue as well.
+
+	switch (type) {
+
+	case NEED_INLINE:
+
+		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
+		if ( !(pCh->channelNeeds & NEED_INLINE) )
+		{
+			pCh->channelNeeds |= NEED_INLINE;
+			queueIndex = pB->i2Dbuf_stuff;
+			pB->i2Dbuf[queueIndex++] = pCh;
+			if (queueIndex >= CH_QUEUE_SIZE)
+				queueIndex = 0;
+			pB->i2Dbuf_stuff = queueIndex;
+		}
+		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
+		break;
+
+	case NEED_BYPASS:
+
+		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
+		if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
+		{
+			pCh->channelNeeds |= NEED_BYPASS;
+			queueIndex = pB->i2Bbuf_stuff;
+			pB->i2Bbuf[queueIndex++] = pCh;
+			if (queueIndex >= CH_QUEUE_SIZE)
+				queueIndex = 0;
+			pB->i2Bbuf_stuff = queueIndex;
+		} 
+		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
+		break;
+
+	case NEED_FLOW:
+
+		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
+		if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
+		{
+			pCh->channelNeeds |= NEED_FLOW;
+			queueIndex = pB->i2Fbuf_stuff;
+			pB->i2Fbuf[queueIndex++] = pCh;
+			if (queueIndex >= CH_QUEUE_SIZE)
+				queueIndex = 0;
+			pB->i2Fbuf_stuff = queueIndex;
+		}
+		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
+		break;
+
+	case NEED_CREDIT:
+		pCh->channelNeeds |= NEED_CREDIT;
+		break;
+	default:
+		printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type);
+		break;
+	}
+	return;
+}
+
+//******************************************************************************
+// Function:   i2QueueCommands(type, pCh, timeout, nCommands, pCs,...)
+// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE
+//             pointer to the channel structure
+//             maximum period to wait
+//             number of commands (n)
+//             n commands
+// Returns:    Number of commands sent, or -1 for error
+//
+// get board lock before calling
+//
+// Description:
+// Queues up some commands to be sent to a channel. To send possibly several
+// bypass or inline commands to the given channel. The timeout parameter
+// indicates how many HUNDREDTHS OF SECONDS to wait until there is room:
+// 0 = return immediately if no room, -ive  = wait forever, +ive = number of
+// 1/100 seconds to wait. Return values:
+// -1 Some kind of nasty error: bad channel structure or invalid arguments.
+//  0 No room to send all the commands
+// (+)   Number of commands sent
+//******************************************************************************
+static int
+i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
+					 cmdSyntaxPtr pCs0,...)
+{
+	int totalsize = 0;
+	int blocksize;
+	int lastended;
+	cmdSyntaxPtr *ppCs;
+	cmdSyntaxPtr pCs;
+	int count;
+	int flag;
+	i2eBordStrPtr pB;
+
+	unsigned short maxBlock;
+	unsigned short maxBuff;
+	short bufroom;
+	unsigned short stuffIndex;
+	unsigned char *pBuf;
+	unsigned char *pInsert;
+	unsigned char *pDest, *pSource;
+	unsigned short channel;
+	int cnt;
+	unsigned long flags = 0;
+	rwlock_t *lock_var_p = NULL;
+
+	// Make sure the channel exists, otherwise do nothing
+	if ( !i2Validate ( pCh ) ) {
+		return -1;
+	}
+
+	ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );
+
+	pB = pCh->pMyBord;
+
+	// Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT
+	if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED)
+		return -2;
+	// If the board has gone fatal, return bad, and also hit the trap routine if
+	// it exists.
+	if (pB->i2eFatal) {
+		if ( pB->i2eFatalTrap ) {
+			(*(pB)->i2eFatalTrap)(pB);
+		}
+		return -3;
+	}
+	// Set up some variables, Which buffers are we using?  How big are they?
+	switch(type)
+	{
+	case PTYPE_INLINE:
+		flag = INL;
+		maxBlock = MAX_OBUF_BLOCK;
+		maxBuff = OBUF_SIZE;
+		pBuf = pCh->Obuf;
+		break;
+	case PTYPE_BYPASS:
+		flag = BYP;
+		maxBlock = MAX_CBUF_BLOCK;
+		maxBuff = CBUF_SIZE;
+		pBuf = pCh->Cbuf;
+		break;
+	default:
+		return -4;
+	}
+	// Determine the total size required for all the commands
+	totalsize = blocksize = sizeof(i2CmdHeader);
+	lastended = 0;
+	ppCs = &pCs0;
+	for ( count = nCommands; count; count--, ppCs++)
+	{
+		pCs = *ppCs;
+		cnt = pCs->length;
+		// Will a new block be needed for this one? 
+		// Two possible reasons: too
+		// big or previous command has to be at the end of a packet.
+		if ((blocksize + cnt > maxBlock) || lastended) {
+			blocksize = sizeof(i2CmdHeader);
+			totalsize += sizeof(i2CmdHeader);
+		}
+		totalsize += cnt;
+		blocksize += cnt;
+
+		// If this command had to end a block, then we will make sure to
+		// account for it should there be any more blocks.
+		lastended = pCs->flags & END;
+	}
+	for (;;) {
+		// Make sure any pending flush commands go out before we add more data.
+		if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {
+			// How much room (this time through) ?
+			switch(type) {
+			case PTYPE_INLINE:
+				lock_var_p = &pCh->Obuf_spinlock;
+				write_lock_irqsave(lock_var_p, flags);
+				stuffIndex = pCh->Obuf_stuff;
+				bufroom = pCh->Obuf_strip - stuffIndex;
+				break;
+			case PTYPE_BYPASS:
+				lock_var_p = &pCh->Cbuf_spinlock;
+				write_lock_irqsave(lock_var_p, flags);
+				stuffIndex = pCh->Cbuf_stuff;
+				bufroom = pCh->Cbuf_strip - stuffIndex;
+				break;
+			default:
+				return -5;
+			}
+			if (--bufroom < 0) {
+				bufroom += maxBuff;
+			}
+
+			ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );
+
+			// Check for overflow
+			if (totalsize <= bufroom) {
+				// Normal Expected path - We still hold LOCK
+				break; /* from for()- Enough room: goto proceed */
+			}
+			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
+			write_unlock_irqrestore(lock_var_p, flags);
+		} else
+			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
+
+		/* Prepare to wait for buffers to empty */
+		serviceOutgoingFifo(pB);	// Dump what we got
+
+		if (timeout == 0) {
+			return 0;   // Tired of waiting
+		}
+		if (timeout > 0)
+			timeout--;   // So negative values == forever
+		
+		if (!in_interrupt()) {
+			schedule_timeout_interruptible(1);	// short nap
+		} else {
+			// we cannot sched/sleep in interrupt silly
+			return 0;   
+		}
+		if (signal_pending(current)) {
+			return 0;   // Wake up! Time to die!!!
+		}
+
+		ip2trace (CHANN, ITRC_QUEUE, 4, 0 );
+
+	}	// end of for(;;)
+
+	// At this point we have room and the lock - stick them in.
+	channel = pCh->infl.hd.i2sChannel;
+	pInsert = &pBuf[stuffIndex];     // Pointer to start of packet
+	pDest = CMD_OF(pInsert);         // Pointer to start of command
+
+	// When we start counting, the block is the size of the header
+	for (blocksize = sizeof(i2CmdHeader), count = nCommands,
+			lastended = 0, ppCs = &pCs0;
+		count;
+		count--, ppCs++)
+	{
+		pCs = *ppCs;         // Points to command protocol structure
+
+		// If this is a bookmark request command, post the fact that a bookmark
+		// request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ
+		// has no parameters!  The more general solution would be to reference
+		// pCs->cmd[0].
+		if (pCs == CMD_BMARK_REQ) {
+			pCh->bookMarks++;
+
+			ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );
+
+		}
+		cnt = pCs->length;
+
+		// If this command would put us over the maximum block size or 
+		// if the last command had to be at the end of a block, we end
+		// the existing block here and start a new one.
+		if ((blocksize + cnt > maxBlock) || lastended) {
+
+			ip2trace (CHANN, ITRC_QUEUE, 5, 0 );
+
+			PTYPE_OF(pInsert) = type;
+			CHANNEL_OF(pInsert) = channel;
+			// count here does not include the header
+			CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
+			stuffIndex += blocksize;
+			if(stuffIndex >= maxBuff) {
+				stuffIndex = 0;
+				pInsert = pBuf;
+			}
+			pInsert = &pBuf[stuffIndex];  // Pointer to start of next pkt
+			pDest = CMD_OF(pInsert);
+			blocksize = sizeof(i2CmdHeader);
+		}
+		// Now we know there is room for this one in the current block
+
+		blocksize += cnt;       // Total bytes in this command
+		pSource = pCs->cmd;     // Copy the command into the buffer
+		while (cnt--) {
+			*pDest++ = *pSource++;
+		}
+		// If this command had to end a block, then we will make sure to account
+		// for it should there be any more blocks.
+		lastended = pCs->flags & END;
+	}	// end for
+	// Clean up the final block by writing header, etc
+
+	PTYPE_OF(pInsert) = type;
+	CHANNEL_OF(pInsert) = channel;
+	// count here does not include the header
+	CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
+	stuffIndex += blocksize;
+	if(stuffIndex >= maxBuff) {
+		stuffIndex = 0;
+		pInsert = pBuf;
+	}
+	// Updates the index, and post the need for service. When adding these to
+	// the queue of channels, we turn off the interrupt while doing so,
+	// because at interrupt level we might want to push a channel back to the
+	// end of the queue.
+	switch(type)
+	{
+	case PTYPE_INLINE:
+		pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer
+		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+
+		pB->debugInlineQueued++;
+		// Add the channel pointer to list of channels needing service (first
+		// come...), if it's not already there.
+		i2QueueNeeds(pB, pCh, NEED_INLINE);
+		break;
+
+	case PTYPE_BYPASS:
+		pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer
+		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
+
+		pB->debugBypassQueued++;
+		// Add the channel pointer to list of channels needing service (first
+		// come...), if it's not already there.
+		i2QueueNeeds(pB, pCh, NEED_BYPASS);
+		break;
+	}
+
+	ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );
+
+	return nCommands; // Good status: number of commands sent
+}
+
+//******************************************************************************
+// Function:   i2GetStatus(pCh,resetBits)
+// Parameters: Pointer to a channel structure
+//             Bit map of status bits to clear
+// Returns:    Bit map of current status bits
+//
+// Description:
+// Returns the state of data set signals, and whether a break has been received,
+// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status
+// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared
+// AFTER the condition is passed. If pCh does not point to a valid channel,
+// returns -1 (which would be impossible otherwise.
+//******************************************************************************
+static int
+i2GetStatus(i2ChanStrPtr pCh, int resetBits)
+{
+	unsigned short status;
+	i2eBordStrPtr pB;
+
+	ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );
+
+	// Make sure the channel exists, otherwise do nothing */
+	if ( !i2Validate ( pCh ) )
+		return -1;
+
+	pB = pCh->pMyBord;
+
+	status = pCh->dataSetIn;
+
+	// Clear any specified error bits: but note that only actual error bits can
+	// be cleared, regardless of the value passed.
+	if (resetBits)
+	{
+		pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));
+		pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);
+	}
+
+	ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );
+
+	return status;
+}
+
+//******************************************************************************
+// Function:   i2Input(pChpDest,count)
+// Parameters: Pointer to a channel structure
+//             Pointer to data buffer
+//             Number of bytes to read
+// Returns:    Number of bytes read, or -1 for error
+//
+// Description:
+// Strips data from the input buffer and writes it to pDest. If there is a
+// collosal blunder, (invalid structure pointers or the like), returns -1.
+// Otherwise, returns the number of bytes read.
+//******************************************************************************
+static int
+i2Input(i2ChanStrPtr pCh)
+{
+	int amountToMove;
+	unsigned short stripIndex;
+	int count;
+	unsigned long flags = 0;
+
+	ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);
+
+	// Ensure channel structure seems real
+	if ( !i2Validate( pCh ) ) {
+		count = -1;
+		goto i2Input_exit;
+	}
+	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
+
+	// initialize some accelerators and private copies
+	stripIndex = pCh->Ibuf_strip;
+
+	count = pCh->Ibuf_stuff - stripIndex;
+
+	// If buffer is empty or requested data count was 0, (trivial case) return
+	// without any further thought.
+	if ( count == 0 ) {
+		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+		goto i2Input_exit;
+	}
+	// Adjust for buffer wrap
+	if ( count < 0 ) {
+		count += IBUF_SIZE;
+	}
+	// Don't give more than can be taken by the line discipline
+	amountToMove = pCh->pTTY->receive_room;
+	if (count > amountToMove) {
+		count = amountToMove;
+	}
+	// How much could we copy without a wrap?
+	amountToMove = IBUF_SIZE - stripIndex;
+
+	if (amountToMove > count) {
+		amountToMove = count;
+	}
+	// Move the first block
+	pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
+		 &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
+	// If we needed to wrap, do the second data move
+	if (count > amountToMove) {
+		pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY,
+		 pCh->Ibuf, NULL, count - amountToMove );
+	}
+	// Bump and wrap the stripIndex all at once by the amount of data read. This
+	// method is good regardless of whether the data was in one or two pieces.
+	stripIndex += count;
+	if (stripIndex >= IBUF_SIZE) {
+		stripIndex -= IBUF_SIZE;
+	}
+	pCh->Ibuf_strip = stripIndex;
+
+	// Update our flow control information and possibly queue ourselves to send
+	// it, depending on how much data has been stripped since the last time a
+	// packet was sent.
+	pCh->infl.asof += count;
+
+	if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
+		pCh->sinceLastFlow -= pCh->whenSendFlow;
+		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
+	} else {
+		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+	}
+
+i2Input_exit:
+
+	ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);
+
+	return count;
+}
+
+//******************************************************************************
+// Function:   i2InputFlush(pCh)
+// Parameters: Pointer to a channel structure
+// Returns:    Number of bytes stripped, or -1 for error
+//
+// Description:
+// Strips any data from the input buffer. If there is a collosal blunder,
+// (invalid structure pointers or the like), returns -1. Otherwise, returns the
+// number of bytes stripped.
+//******************************************************************************
+static int
+i2InputFlush(i2ChanStrPtr pCh)
+{
+	int count;
+	unsigned long flags;
+
+	// Ensure channel structure seems real
+	if ( !i2Validate ( pCh ) )
+		return -1;
+
+	ip2trace (CHANN, ITRC_INPUT, 10, 0);
+
+	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
+	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
+
+	// Adjust for buffer wrap
+	if (count < 0) {
+		count += IBUF_SIZE;
+	}
+
+	// Expedient way to zero out the buffer
+	pCh->Ibuf_strip = pCh->Ibuf_stuff;
+
+
+	// Update our flow control information and possibly queue ourselves to send
+	// it, depending on how much data has been stripped since the last time a
+	// packet was sent.
+
+	pCh->infl.asof += count;
+
+	if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
+	{
+		pCh->sinceLastFlow -= pCh->whenSendFlow;
+		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
+	} else {
+		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+	}
+
+	ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
+
+	return count;
+}
+
+//******************************************************************************
+// Function:   i2InputAvailable(pCh)
+// Parameters: Pointer to a channel structure
+// Returns:    Number of bytes available, or -1 for error
+//
+// Description:
+// If there is a collosal blunder, (invalid structure pointers or the like),
+// returns -1. Otherwise, returns the number of bytes stripped. Otherwise,
+// returns the number of bytes available in the buffer.
+//******************************************************************************
+#if 0
+static int
+i2InputAvailable(i2ChanStrPtr pCh)
+{
+	int count;
+
+	// Ensure channel structure seems real
+	if ( !i2Validate ( pCh ) ) return -1;
+
+
+	// initialize some accelerators and private copies
+	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
+	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
+	read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+
+	// Adjust for buffer wrap
+	if (count < 0)
+	{
+		count += IBUF_SIZE;
+	}
+
+	return count;
+}
+#endif 
+
+//******************************************************************************
+// Function:   i2Output(pCh, pSource, count)
+// Parameters: Pointer to channel structure
+//             Pointer to source data
+//             Number of bytes to send
+// Returns:    Number of bytes sent, or -1 for error
+//
+// Description:
+// Queues the data at pSource to be sent as data packets to the board. If there
+// is a collosal blunder, (invalid structure pointers or the like), returns -1.
+// Otherwise, returns the number of bytes written. What if there is not enough
+// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then
+// we transfer as many characters as we can now, then return. If this bit is
+// clear (default), routine will spin along until all the data is buffered.
+// Should this occur, the 1-ms delay routine is called while waiting to avoid
+// applications that one cannot break out of.
+//******************************************************************************
+static int
+i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
+{
+	i2eBordStrPtr pB;
+	unsigned char *pInsert;
+	int amountToMove;
+	int countOriginal = count;
+	unsigned short channel;
+	unsigned short stuffIndex;
+	unsigned long flags;
+
+	int bailout = 10;
+
+	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 );
+
+	// Ensure channel structure seems real
+	if ( !i2Validate ( pCh ) ) 
+		return -1;
+
+	// initialize some accelerators and private copies
+	pB = pCh->pMyBord;
+	channel = pCh->infl.hd.i2sChannel;
+
+	// If the board has gone fatal, return bad, and also hit the trap routine if
+	// it exists.
+	if (pB->i2eFatal) {
+		if (pB->i2eFatalTrap) {
+			(*(pB)->i2eFatalTrap)(pB);
+		}
+		return -1;
+	}
+	// Proceed as though we would do everything
+	while ( count > 0 ) {
+
+		// How much room in output buffer is there?
+		read_lock_irqsave(&pCh->Obuf_spinlock, flags);
+		amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
+		read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+		if (amountToMove < 0) {
+			amountToMove += OBUF_SIZE;
+		}
+		// Subtract off the headers size and see how much room there is for real
+		// data. If this is negative, we will discover later.
+		amountToMove -= sizeof (i2DataHeader);
+
+		// Don't move more (now) than can go in a single packet
+		if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {
+			amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);
+		}
+		// Don't move more than the count we were given
+		if (amountToMove > count) {
+			amountToMove = count;
+		}
+		// Now we know how much we must move: NB because the ring buffers have
+		// an overflow area at the end, we needn't worry about wrapping in the
+		// middle of a packet.
+
+// Small WINDOW here with no LOCK but I can't call Flush with LOCK
+// We would be flushing (or ending flush) anyway
+
+		ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );
+
+		if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 
+				&& amountToMove > 0 )
+		{
+			write_lock_irqsave(&pCh->Obuf_spinlock, flags);
+			stuffIndex = pCh->Obuf_stuff;
+      
+			// Had room to move some data: don't know whether the block size,
+			// buffer space, or what was the limiting factor...
+			pInsert = &(pCh->Obuf[stuffIndex]);
+
+			// Set up the header
+			CHANNEL_OF(pInsert)     = channel;
+			PTYPE_OF(pInsert)       = PTYPE_DATA;
+			TAG_OF(pInsert)         = 0;
+			ID_OF(pInsert)          = ID_ORDINARY_DATA;
+			DATA_COUNT_OF(pInsert)  = amountToMove;
+
+			// Move the data
+			memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
+			// Adjust pointers and indices
+			pSource					+= amountToMove;
+			pCh->Obuf_char_count	+= amountToMove;
+			stuffIndex 				+= amountToMove + sizeof(i2DataHeader);
+			count 					-= amountToMove;
+
+			if (stuffIndex >= OBUF_SIZE) {
+				stuffIndex = 0;
+			}
+			pCh->Obuf_stuff = stuffIndex;
+
+			write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+
+			ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
+
+		} else {
+
+			// Cannot move data
+			// becuz we need to stuff a flush 
+			// or amount to move is <= 0
+
+			ip2trace(CHANN, ITRC_OUTPUT, 14, 3,
+				amountToMove,  pB->i2eFifoRemains,
+				pB->i2eWaitingForEmptyFifo );
+
+			// Put this channel back on queue
+			// this ultimatly gets more data or wakes write output
+			i2QueueNeeds(pB, pCh, NEED_INLINE);
+
+			if ( pB->i2eWaitingForEmptyFifo ) {
+
+				ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );
+
+				// or schedule
+				if (!in_interrupt()) {
+
+					ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
+
+					schedule_timeout_interruptible(2);
+					if (signal_pending(current)) {
+						break;
+					}
+					continue;
+				} else {
+
+					ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );
+
+					// let interrupt in = WAS restore_flags()
+					// We hold no lock nor is irq off anymore???
+					
+					break;
+				}
+				break;   // from while(count)
+			}
+			else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )
+			{
+				ip2trace (CHANN, ITRC_OUTPUT, 19, 2,
+					pB->i2eFifoRemains,
+					pB->i2eTxMailEmpty );
+
+				break;   // from while(count)
+			} else if ( pCh->channelNeeds & NEED_CREDIT ) {
+
+				ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );
+
+				break;   // from while(count)
+			} else if ( --bailout) {
+
+				// Try to throw more things (maybe not us) in the fifo if we're
+				// not already waiting for it.
+	
+				ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );
+
+				serviceOutgoingFifo(pB);
+				//break;  CONTINUE;
+			} else {
+				ip2trace (CHANN, ITRC_OUTPUT, 21, 3,
+					pB->i2eFifoRemains,
+					pB->i2eOutMailWaiting,
+					pB->i2eWaitingForEmptyFifo );
+
+				break;   // from while(count)
+			}
+		}
+	} // End of while(count)
+
+	i2QueueNeeds(pB, pCh, NEED_INLINE);
+
+	// We drop through either when the count expires, or when there is some
+	// count left, but there was a non-blocking write.
+	if (countOriginal > count) {
+
+		ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );
+
+		serviceOutgoingFifo( pB );
+	}
+
+	ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );
+
+	return countOriginal - count;
+}
+
+//******************************************************************************
+// Function:   i2FlushOutput(pCh)
+// Parameters: Pointer to a channel structure
+// Returns:    Nothing
+//
+// Description:
+// Sends bypass command to start flushing (waiting possibly forever until there
+// is room), then sends inline command to stop flushing output, (again waiting
+// possibly forever).
+//******************************************************************************
+static inline void
+i2FlushOutput(i2ChanStrPtr pCh)
+{
+
+	ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );
+
+	if (pCh->flush_flags)
+		return;
+
+	if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
+		pCh->flush_flags = STARTFL_FLAG;		// Failed - flag for later
+
+		ip2trace (CHANN, ITRC_FLUSH, 2, 0 );
+
+	} else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {
+		pCh->flush_flags = STOPFL_FLAG;		// Failed - flag for later
+
+		ip2trace (CHANN, ITRC_FLUSH, 3, 0 );
+	}
+}
+
+static int 
+i2RetryFlushOutput(i2ChanStrPtr pCh)
+{
+	int old_flags = pCh->flush_flags;
+
+	ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );
+
+	pCh->flush_flags = 0;	// Clear flag so we can avoid recursion
+									// and queue the commands
+
+	if ( old_flags & STARTFL_FLAG ) {
+		if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
+			old_flags = STOPFL_FLAG;	//Success - send stop flush
+		} else {
+			old_flags = STARTFL_FLAG;	//Failure - Flag for retry later
+		}
+
+		ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );
+
+	}
+	if ( old_flags & STOPFL_FLAG ) {
+		if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {
+			old_flags = 0;	// Success - clear flags
+		}
+
+		ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );
+	}
+	pCh->flush_flags = old_flags;
+
+	ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );
+
+	return old_flags;
+}
+
+//******************************************************************************
+// Function:   i2DrainOutput(pCh,timeout)
+// Parameters: Pointer to a channel structure
+//             Maximum period to wait
+// Returns:    ?
+//
+// Description:
+// Uses the bookmark request command to ask the board to send a bookmark back as
+// soon as all the data is completely sent.
+//******************************************************************************
+static void
+i2DrainWakeup(unsigned long d)
+{
+	i2ChanStrPtr pCh = (i2ChanStrPtr)d;
+
+	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
+
+	pCh->BookmarkTimer.expires = 0;
+	wake_up_interruptible( &pCh->pBookmarkWait );
+}
+
+static void
+i2DrainOutput(i2ChanStrPtr pCh, int timeout)
+{
+	wait_queue_t wait;
+	i2eBordStrPtr pB;
+
+	ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);
+
+	pB = pCh->pMyBord;
+	// If the board has gone fatal, return bad, 
+	// and also hit the trap routine if it exists.
+	if (pB->i2eFatal) {
+		if (pB->i2eFatalTrap) {
+			(*(pB)->i2eFatalTrap)(pB);
+		}
+		return;
+	}
+	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
+		// One per customer (channel)
+		setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
+				(unsigned long)pCh);
+
+		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
+
+		mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
+	}
+	
+	i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
+
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&(pCh->pBookmarkWait), &wait);
+	set_current_state( TASK_INTERRUPTIBLE );
+
+	serviceOutgoingFifo( pB );
+	
+	schedule();	// Now we take our interruptible sleep on
+
+	// Clean up the queue
+	set_current_state( TASK_RUNNING );
+	remove_wait_queue(&(pCh->pBookmarkWait), &wait);
+
+	// if expires == 0 then timer poped, then do not need to del_timer
+	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
+	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
+		del_timer( &(pCh->BookmarkTimer) );
+		pCh->BookmarkTimer.expires = 0;
+
+		ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires );
+
+	}
+	ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires );
+	return;
+}
+
+//******************************************************************************
+// Function:   i2OutputFree(pCh)
+// Parameters: Pointer to a channel structure
+// Returns:    Space in output buffer
+//
+// Description:
+// Returns -1 if very gross error. Otherwise returns the amount of bytes still
+// free in the output buffer.
+//******************************************************************************
+static int
+i2OutputFree(i2ChanStrPtr pCh)
+{
+	int amountToMove;
+	unsigned long flags;
+
+	// Ensure channel structure seems real
+	if ( !i2Validate ( pCh ) ) {
+		return -1;
+	}
+	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
+	amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
+	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+
+	if (amountToMove < 0) {
+		amountToMove += OBUF_SIZE;
+	}
+	// If this is negative, we will discover later
+	amountToMove -= sizeof(i2DataHeader);
+
+	return (amountToMove < 0) ? 0 : amountToMove;
+}
+static void
+
+ip2_owake( PTTY tp)
+{
+	i2ChanStrPtr  pCh;
+
+	if (tp == NULL) return;
+
+	pCh = tp->driver_data;
+
+	ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
+			(1 << TTY_DO_WRITE_WAKEUP) );
+
+	tty_wakeup(tp);
+}
+
+static inline void
+set_baud_params(i2eBordStrPtr pB) 
+{
+	int i,j;
+	i2ChanStrPtr  *pCh;
+
+	pCh = (i2ChanStrPtr *) pB->i2eChannelPtr;
+
+	for (i = 0; i < ABS_MAX_BOXES; i++) {
+		if (pB->channelBtypes.bid_value[i]) {
+			if (BID_HAS_654(pB->channelBtypes.bid_value[i])) {
+				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
+					if (pCh[i*16+j] == NULL)
+						break;
+					(pCh[i*16+j])->BaudBase    = 921600;	// MAX for ST654
+					(pCh[i*16+j])->BaudDivisor = 96;
+				}
+			} else {	// has cirrus cd1400
+				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
+					if (pCh[i*16+j] == NULL)
+						break;
+					(pCh[i*16+j])->BaudBase    = 115200;	// MAX for CD1400
+					(pCh[i*16+j])->BaudDivisor = 12;
+				}
+			}
+		}
+	}
+}
+
+//******************************************************************************
+// Function:   i2StripFifo(pB)
+// Parameters: Pointer to a board structure
+// Returns:    ?
+//
+// Description:
+// Strips all the available data from the incoming FIFO, identifies the type of
+// packet, and either buffers the data or does what needs to be done.
+//
+// Note there is no overflow checking here: if the board sends more data than it
+// ought to, we will not detect it here, but blindly overflow...
+//******************************************************************************
+
+// A buffer for reading in blocks for unknown channels
+static unsigned char junkBuffer[IBUF_SIZE];
+
+// A buffer to read in a status packet. Because of the size of the count field
+// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE
+static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4];
+
+// This table changes the bit order from MSR order given by STAT_MODEM packet to
+// status bits used in our library.
+static char xlatDss[16] = {
+0      | 0     | 0      | 0      ,
+0      | 0     | 0      | I2_CTS ,
+0      | 0     | I2_DSR | 0      ,
+0      | 0     | I2_DSR | I2_CTS ,
+0      | I2_RI | 0      | 0      ,
+0      | I2_RI | 0      | I2_CTS ,
+0      | I2_RI | I2_DSR | 0      ,
+0      | I2_RI | I2_DSR | I2_CTS ,
+I2_DCD | 0     | 0      | 0      ,
+I2_DCD | 0     | 0      | I2_CTS ,
+I2_DCD | 0     | I2_DSR | 0      ,
+I2_DCD | 0     | I2_DSR | I2_CTS ,
+I2_DCD | I2_RI | 0      | 0      ,
+I2_DCD | I2_RI | 0      | I2_CTS ,
+I2_DCD | I2_RI | I2_DSR | 0      ,
+I2_DCD | I2_RI | I2_DSR | I2_CTS };
+
+static inline void
+i2StripFifo(i2eBordStrPtr pB)
+{
+	i2ChanStrPtr pCh;
+	int channel;
+	int count;
+	unsigned short stuffIndex;
+	int amountToRead;
+	unsigned char *pc, *pcLimit;
+	unsigned char uc;
+	unsigned char dss_change;
+	unsigned long bflags,cflags;
+
+//	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 );
+
+	while (I2_HAS_INPUT(pB)) {
+//		ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 );
+
+		// Process packet from fifo a one atomic unit
+		write_lock_irqsave(&pB->read_fifo_spinlock, bflags);
+   
+		// The first word (or two bytes) will have channel number and type of
+		// packet, possibly other information
+		pB->i2eLeadoffWord[0] = iiReadWord(pB);
+
+		switch(PTYPE_OF(pB->i2eLeadoffWord))
+		{
+		case PTYPE_DATA:
+			pB->got_input = 1;
+
+//			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 );
+
+			channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */
+			count = iiReadWord(pB);          /* Count is in the next word */
+
+// NEW: Check the count for sanity! Should the hardware fail, our death
+// is more pleasant. While an oversize channel is acceptable (just more
+// than the driver supports), an over-length count clearly means we are
+// sick!
+			if ( ((unsigned int)count) > IBUF_SIZE ) {
+				pB->i2eFatal = 2;
+				write_unlock_irqrestore(&pB->read_fifo_spinlock,
+						bflags);
+				return;     /* Bail out ASAP */
+			}
+			// Channel is illegally big ?
+			if ((channel >= pB->i2eChannelCnt) ||
+				(NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
+			{
+				iiReadBuf(pB, junkBuffer, count);
+				write_unlock_irqrestore(&pB->read_fifo_spinlock,
+						bflags);
+				break;         /* From switch: ready for next packet */
+			}
+
+			// Channel should be valid, then
+
+			// If this is a hot-key, merely post its receipt for now. These are
+			// always supposed to be 1-byte packets, so we won't even check the
+			// count. Also we will post an acknowledgement to the board so that
+			// more data can be forthcoming. Note that we are not trying to use
+			// these sequences in this driver, merely to robustly ignore them.
+			if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
+			{
+				pCh->hotKeyIn = iiReadWord(pB) & 0xff;
+				write_unlock_irqrestore(&pB->read_fifo_spinlock,
+						bflags);
+				i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
+				break;   /* From the switch: ready for next packet */
+			}
+
+			// Normal data! We crudely assume there is room for the data in our
+			// buffer because the board wouldn't have exceeded his credit limit.
+			write_lock_irqsave(&pCh->Ibuf_spinlock, cflags);
+													// We have 2 locks now
+			stuffIndex = pCh->Ibuf_stuff;
+			amountToRead = IBUF_SIZE - stuffIndex;
+			if (amountToRead > count)
+				amountToRead = count;
+
+			// stuffIndex would have been already adjusted so there would 
+			// always be room for at least one, and count is always at least
+			// one.
+
+			iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
+			pCh->icount.rx += amountToRead;
+
+			// Update the stuffIndex by the amount of data moved. Note we could
+			// never ask for more data than would just fit. However, we might
+			// have read in one more byte than we wanted because the read
+			// rounds up to even bytes. If this byte is on the end of the
+			// packet, and is padding, we ignore it. If the byte is part of
+			// the actual data, we need to move it.
+
+			stuffIndex += amountToRead;
+
+			if (stuffIndex >= IBUF_SIZE) {
+				if ((amountToRead & 1) && (count > amountToRead)) {
+					pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE];
+					amountToRead++;
+					stuffIndex = 1;
+				} else {
+					stuffIndex = 0;
+				}
+			}
+
+			// If there is anything left over, read it as well
+			if (count > amountToRead) {
+				amountToRead = count - amountToRead;
+				iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
+				pCh->icount.rx += amountToRead;
+				stuffIndex += amountToRead;
+			}
+
+			// Update stuff index
+			pCh->Ibuf_stuff = stuffIndex;
+			write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags);
+			write_unlock_irqrestore(&pB->read_fifo_spinlock,
+					bflags);
+
+#ifdef USE_IQ
+			schedule_work(&pCh->tqueue_input);
+#else
+			do_input(&pCh->tqueue_input);
+#endif
+
+			// Note we do not need to maintain any flow-control credits at this
+			// time:  if we were to increment .asof and decrement .room, there
+			// would be no net effect. Instead, when we strip data, we will
+			// increment .asof and leave .room unchanged.
+
+			break;   // From switch: ready for next packet
+
+		case PTYPE_STATUS:
+			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 );
+      
+			count = CMD_COUNT_OF(pB->i2eLeadoffWord);
+
+			iiReadBuf(pB, cmdBuffer, count);
+			// We can release early with buffer grab
+			write_unlock_irqrestore(&pB->read_fifo_spinlock,
+					bflags);
+
+			pc = cmdBuffer;
+			pcLimit = &(cmdBuffer[count]);
+
+			while (pc < pcLimit) {
+				channel = *pc++;
+
+				ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc );
+
+				/* check for valid channel */
+				if (channel < pB->i2eChannelCnt
+					 && 
+					 (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL
+					)
+				{
+					dss_change = 0;
+
+					switch (uc = *pc++)
+					{
+					/* Breaks and modem signals are easy: just update status */
+					case STAT_CTS_UP:
+						if ( !(pCh->dataSetIn & I2_CTS) )
+						{
+							pCh->dataSetIn |= I2_DCTS;
+							pCh->icount.cts++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn |= I2_CTS;
+						break;
+
+					case STAT_CTS_DN:
+						if ( pCh->dataSetIn & I2_CTS )
+						{
+							pCh->dataSetIn |= I2_DCTS;
+							pCh->icount.cts++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn &= ~I2_CTS;
+						break;
+
+					case STAT_DCD_UP:
+						ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn );
+
+						if ( !(pCh->dataSetIn & I2_DCD) )
+						{
+							ip2trace (CHANN, ITRC_MODEM, 2, 0 );
+							pCh->dataSetIn |= I2_DDCD;
+							pCh->icount.dcd++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn |= I2_DCD;
+
+						ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn );
+						break;
+
+					case STAT_DCD_DN:
+						ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn );
+						if ( pCh->dataSetIn & I2_DCD )
+						{
+							ip2trace (channel, ITRC_MODEM, 5, 0 );
+							pCh->dataSetIn |= I2_DDCD;
+							pCh->icount.dcd++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn &= ~I2_DCD;
+
+						ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn );
+						break;
+
+					case STAT_DSR_UP:
+						if ( !(pCh->dataSetIn & I2_DSR) )
+						{
+							pCh->dataSetIn |= I2_DDSR;
+							pCh->icount.dsr++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn |= I2_DSR;
+						break;
+
+					case STAT_DSR_DN:
+						if ( pCh->dataSetIn & I2_DSR )
+						{
+							pCh->dataSetIn |= I2_DDSR;
+							pCh->icount.dsr++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn &= ~I2_DSR;
+						break;
+
+					case STAT_RI_UP:
+						if ( !(pCh->dataSetIn & I2_RI) )
+						{
+							pCh->dataSetIn |= I2_DRI;
+							pCh->icount.rng++;
+							dss_change = 1;
+						}
+						pCh->dataSetIn |= I2_RI ;
+						break;
+
+					case STAT_RI_DN:
+						// to be compat with serial.c
+						//if ( pCh->dataSetIn & I2_RI )
+						//{
+						//	pCh->dataSetIn |= I2_DRI;
+						//	pCh->icount.rng++; 
+						//	dss_change = 1;
+						//}
+						pCh->dataSetIn &= ~I2_RI ;
+						break;
+
+					case STAT_BRK_DET:
+						pCh->dataSetIn |= I2_BRK;
+						pCh->icount.brk++;
+						dss_change = 1;
+						break;
+
+					// Bookmarks? one less request we're waiting for
+					case STAT_BMARK:
+						pCh->bookMarks--;
+						if (pCh->bookMarks <= 0 ) {
+							pCh->bookMarks = 0;
+							wake_up_interruptible( &pCh->pBookmarkWait );
+
+						ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires );
+						}
+						break;
+
+					// Flow control packets? Update the new credits, and if
+					// someone was waiting for output, queue him up again.
+					case STAT_FLOW:
+						pCh->outfl.room =
+							((flowStatPtr)pc)->room -
+							(pCh->outfl.asof - ((flowStatPtr)pc)->asof);
+
+						ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room );
+
+						if (pCh->channelNeeds & NEED_CREDIT)
+						{
+							ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds);
+
+							pCh->channelNeeds &= ~NEED_CREDIT;
+							i2QueueNeeds(pB, pCh, NEED_INLINE);
+							if ( pCh->pTTY )
+								ip2_owake(pCh->pTTY);
+						}
+
+						ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds);
+
+						pc += sizeof(flowStat);
+						break;
+
+					/* Special packets: */
+					/* Just copy the information into the channel structure */
+
+					case STAT_STATUS:
+
+						pCh->channelStatus = *((debugStatPtr)pc);
+						pc += sizeof(debugStat);
+						break;
+
+					case STAT_TXCNT:
+
+						pCh->channelTcount = *((cntStatPtr)pc);
+						pc += sizeof(cntStat);
+						break;
+
+					case STAT_RXCNT:
+
+						pCh->channelRcount = *((cntStatPtr)pc);
+						pc += sizeof(cntStat);
+						break;
+
+					case STAT_BOXIDS:
+						pB->channelBtypes = *((bidStatPtr)pc);
+						pc += sizeof(bidStat);
+						set_baud_params(pB);
+						break;
+
+					case STAT_HWFAIL:
+						i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);
+						pCh->channelFail = *((failStatPtr)pc);
+						pc += sizeof(failStat);
+						break;
+
+					/* No explicit match? then
+					 * Might be an error packet...
+					 */
+					default:
+						switch (uc & STAT_MOD_ERROR)
+						{
+						case STAT_ERROR:
+							if (uc & STAT_E_PARITY) {
+								pCh->dataSetIn |= I2_PAR;
+								pCh->icount.parity++;
+							}
+							if (uc & STAT_E_FRAMING){
+								pCh->dataSetIn |= I2_FRA;
+								pCh->icount.frame++;
+							}
+							if (uc & STAT_E_OVERRUN){
+								pCh->dataSetIn |= I2_OVR;
+								pCh->icount.overrun++;
+							}
+							break;
+
+						case STAT_MODEM:
+							// the answer to DSS_NOW request (not change)
+							pCh->dataSetIn = (pCh->dataSetIn
+								& ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )
+								| xlatDss[uc & 0xf];
+							wake_up_interruptible ( &pCh->dss_now_wait );
+						default:
+							break;
+						}
+					}  /* End of switch on status type */
+					if (dss_change) {
+#ifdef USE_IQ
+						schedule_work(&pCh->tqueue_status);
+#else
+						do_status(&pCh->tqueue_status);
+#endif
+					}
+				}
+				else  /* Or else, channel is invalid */
+				{
+					// Even though the channel is invalid, we must test the
+					// status to see how much additional data it has (to be
+					// skipped)
+					switch (*pc++)
+					{
+					case STAT_FLOW:
+						pc += 4;    /* Skip the data */
+						break;
+
+					default:
+						break;
+					}
+				}
+			}  // End of while (there is still some status packet left)
+			break;
+
+		default: // Neither packet? should be impossible
+			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
+				PTYPE_OF(pB->i2eLeadoffWord) );
+			write_unlock_irqrestore(&pB->read_fifo_spinlock,
+					bflags);
+
+			break;
+		}  // End of switch on type of packets
+	}	/*while(board I2_HAS_INPUT)*/
+
+	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
+
+	// Send acknowledgement to the board even if there was no data!
+	pB->i2eOutMailWaiting |= MB_IN_STRIPPED;
+	return;
+}
+
+//******************************************************************************
+// Function:   i2Write2Fifo(pB,address,count)
+// Parameters: Pointer to a board structure, source address, byte count
+// Returns:    bytes written
+//
+// Description:
+//  Writes count bytes to board io address(implied) from source
+//  Adjusts count, leaves reserve for next time around bypass cmds
+//******************************************************************************
+static int
+i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
+{
+	int rc = 0;
+	unsigned long flags;
+	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
+	if (!pB->i2eWaitingForEmptyFifo) {
+		if (pB->i2eFifoRemains > (count+reserve)) {
+			pB->i2eFifoRemains -= count;
+			iiWriteBuf(pB, source, count);
+			pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
+			rc =  count;
+		}
+	}
+	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
+	return rc;
+}
+//******************************************************************************
+// Function:   i2StuffFifoBypass(pB)
+// Parameters: Pointer to a board structure
+// Returns:    Nothing
+//
+// Description:
+// Stuffs as many bypass commands into the fifo as possible. This is simpler
+// than stuffing data or inline commands to fifo, since we do not have
+// flow-control to deal with.
+//******************************************************************************
+static inline void
+i2StuffFifoBypass(i2eBordStrPtr pB)
+{
+	i2ChanStrPtr pCh;
+	unsigned char *pRemove;
+	unsigned short stripIndex;
+	unsigned short packetSize;
+	unsigned short paddedSize;
+	unsigned short notClogged = 1;
+	unsigned long flags;
+
+	int bailout = 1000;
+
+	// Continue processing so long as there are entries, or there is room in the
+	// fifo. Each entry represents a channel with something to do.
+	while ( --bailout && notClogged && 
+			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
+	{
+		write_lock_irqsave(&pCh->Cbuf_spinlock, flags);
+		stripIndex = pCh->Cbuf_strip;
+
+		// as long as there are packets for this channel...
+
+		while (stripIndex != pCh->Cbuf_stuff) {
+			pRemove = &(pCh->Cbuf[stripIndex]);
+			packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
+			paddedSize = roundup(packetSize, 2);
+
+			if (paddedSize > 0) {
+				if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
+					notClogged = 0;	/* fifo full */
+					i2QueueNeeds(pB, pCh, NEED_BYPASS);	// Put back on queue
+					break;   // Break from the channel
+				} 
+			}
+#ifdef DEBUG_FIFO
+WriteDBGBuf("BYPS", pRemove, paddedSize);
+#endif	/* DEBUG_FIFO */
+			pB->debugBypassCount++;
+
+			pRemove += packetSize;
+			stripIndex += packetSize;
+			if (stripIndex >= CBUF_SIZE) {
+				stripIndex = 0;
+				pRemove = pCh->Cbuf;
+			}
+		}
+		// Done with this channel. Move to next, removing this one from 
+		// the queue of channels if we cleaned it out (i.e., didn't get clogged.
+		pCh->Cbuf_strip = stripIndex;
+		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
+	}  // Either clogged or finished all the work
+
+#ifdef IP2DEBUG_TRACE
+	if ( !bailout ) {
+		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );
+	}
+#endif
+}
+
+//******************************************************************************
+// Function:   i2StuffFifoFlow(pB)
+// Parameters: Pointer to a board structure
+// Returns:    Nothing
+//
+// Description:
+// Stuffs as many flow control packets into the fifo as possible. This is easier
+// even than doing normal bypass commands, because there is always at most one
+// packet, already assembled, for each channel.
+//******************************************************************************
+static inline void
+i2StuffFifoFlow(i2eBordStrPtr pB)
+{
+	i2ChanStrPtr pCh;
+	unsigned short paddedSize = roundup(sizeof(flowIn), 2);
+
+	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
+		pB->i2eFifoRemains, paddedSize );
+
+	// Continue processing so long as there are entries, or there is room in the
+	// fifo. Each entry represents a channel with something to do.
+	while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {
+		pB->debugFlowCount++;
+
+		// NO Chan LOCK needed ???
+		if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {
+			break;
+		}
+#ifdef DEBUG_FIFO
+		WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);
+#endif /* DEBUG_FIFO */
+
+	}  // Either clogged or finished all the work
+
+	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );
+}
+
+//******************************************************************************
+// Function:   i2StuffFifoInline(pB)
+// Parameters: Pointer to a board structure
+// Returns:    Nothing
+//
+// Description:
+// Stuffs as much data and inline commands into the fifo as possible. This is
+// the most complex fifo-stuffing operation, since there if now the channel
+// flow-control issue to deal with.
+//******************************************************************************
+static inline void
+i2StuffFifoInline(i2eBordStrPtr pB)
+{
+	i2ChanStrPtr pCh;
+	unsigned char *pRemove;
+	unsigned short stripIndex;
+	unsigned short packetSize;
+	unsigned short paddedSize;
+	unsigned short notClogged = 1;
+	unsigned short flowsize;
+	unsigned long flags;
+
+	int bailout  = 1000;
+	int bailout2;
+
+	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 
+			pB->i2Dbuf_strip, pB->i2Dbuf_stuff );
+
+	// Continue processing so long as there are entries, or there is room in the
+	// fifo. Each entry represents a channel with something to do.
+	while ( --bailout && notClogged && 
+			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
+	{
+		write_lock_irqsave(&pCh->Obuf_spinlock, flags);
+		stripIndex = pCh->Obuf_strip;
+
+		ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
+
+		// as long as there are packets for this channel...
+		bailout2 = 1000;
+		while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {
+			pRemove = &(pCh->Obuf[stripIndex]);
+
+			// Must determine whether this be a data or command packet to
+			// calculate correctly the header size and the amount of
+			// flow-control credit this type of packet will use.
+			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
+				flowsize = DATA_COUNT_OF(pRemove);
+				packetSize = flowsize + sizeof(i2DataHeader);
+			} else {
+				flowsize = CMD_COUNT_OF(pRemove);
+				packetSize = flowsize + sizeof(i2CmdHeader);
+			}
+			flowsize = CREDIT_USAGE(flowsize);
+			paddedSize = roundup(packetSize, 2);
+
+			ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
+
+			// If we don't have enough credits from the board to send the data,
+			// flag the channel that we are waiting for flow control credit, and
+			// break out. This will clean up this channel and remove us from the
+			// queue of hot things to do.
+
+				ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );
+
+			if (pCh->outfl.room <= flowsize)	{
+				// Do Not have the credits to send this packet.
+				i2QueueNeeds(pB, pCh, NEED_CREDIT);
+				notClogged = 0;
+				break;   // So to do next channel
+			}
+			if ( (paddedSize > 0) 
+				&& ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {
+				// Do Not have room in fifo to send this packet.
+				notClogged = 0;
+				i2QueueNeeds(pB, pCh, NEED_INLINE);	
+				break;   // Break from the channel
+			}
+#ifdef DEBUG_FIFO
+WriteDBGBuf("DATA", pRemove, paddedSize);
+#endif /* DEBUG_FIFO */
+			pB->debugInlineCount++;
+
+			pCh->icount.tx += flowsize;
+			// Update current credits
+			pCh->outfl.room -= flowsize;
+			pCh->outfl.asof += flowsize;
+			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
+				pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);
+			}
+			pRemove += packetSize;
+			stripIndex += packetSize;
+
+			ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);
+
+			if (stripIndex >= OBUF_SIZE) {
+				stripIndex = 0;
+				pRemove = pCh->Obuf;
+
+				ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );
+
+			}
+		}	/* while */
+		if ( !bailout2 ) {
+			ip2trace (CHANN, ITRC_ERROR, 3, 0 );
+		}
+		// Done with this channel. Move to next, removing this one from the
+		// queue of channels if we cleaned it out (i.e., didn't get clogged.
+		pCh->Obuf_strip = stripIndex;
+		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+		if ( notClogged )
+		{
+
+			ip2trace (CHANN, ITRC_SICMD, 8, 0 );
+
+			if ( pCh->pTTY ) {
+				ip2_owake(pCh->pTTY);
+			}
+		}
+	}  // Either clogged or finished all the work
+
+	if ( !bailout ) {
+		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );
+	}
+
+	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);
+}
+
+//******************************************************************************
+// Function:   serviceOutgoingFifo(pB)
+// Parameters: Pointer to a board structure
+// Returns:    Nothing
+//
+// Description:
+// Helper routine to put data in the outgoing fifo, if we aren't already waiting
+// for something to be there. If the fifo has only room for a very little data,
+// go head and hit the board with a mailbox hit immediately. Otherwise, it will
+// have to happen later in the interrupt processing. Since this routine may be
+// called both at interrupt and foreground time, we must turn off interrupts
+// during the entire process.
+//******************************************************************************
+static void
+serviceOutgoingFifo(i2eBordStrPtr pB)
+{
+	// If we aren't currently waiting for the board to empty our fifo, service
+	// everything that is pending, in priority order (especially, Bypass before
+	// Inline).
+	if ( ! pB->i2eWaitingForEmptyFifo )
+	{
+		i2StuffFifoFlow(pB);
+		i2StuffFifoBypass(pB);
+		i2StuffFifoInline(pB);
+
+		iiSendPendingMail(pB);
+	} 
+}
+
+//******************************************************************************
+// Function:   i2ServiceBoard(pB)
+// Parameters: Pointer to a board structure
+// Returns:    Nothing
+//
+// Description:
+// Normally this is called from interrupt level, but there is deliberately
+// nothing in here specific to being called from interrupt level. All the
+// hardware-specific, interrupt-specific things happen at the outer levels.
+//
+// For example, a timer interrupt could drive this routine for some sort of
+// polled operation. The only requirement is that the programmer deal with any
+// atomiticity/concurrency issues that result.
+//
+// This routine responds to the board's having sent mailbox information to the
+// host (which would normally cause an interrupt). This routine reads the
+// incoming mailbox. If there is no data in it, this board did not create the
+// interrupt and/or has nothing to be done to it. (Except, if we have been
+// waiting to write mailbox data to it, we may do so.
+//
+// Based on the value in the mailbox, we may take various actions.
+//
+// No checking here of pB validity: after all, it shouldn't have been called by
+// the handler unless pB were on the list.
+//******************************************************************************
+static inline int
+i2ServiceBoard ( i2eBordStrPtr pB )
+{
+	unsigned inmail;
+	unsigned long flags;
+
+
+	/* This should be atomic because of the way we are called... */
+	if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {
+		inmail = iiGetMail(pB);
+	}
+	pB->i2eStartMail = NO_MAIL_HERE;
+
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );
+
+	if (inmail != NO_MAIL_HERE) {
+		// If the board has gone fatal, nothing to do but hit a bit that will
+		// alert foreground tasks to protest!
+		if ( inmail & MB_FATAL_ERROR ) {
+			pB->i2eFatal = 1;
+			goto exit_i2ServiceBoard;
+		}
+
+		/* Assuming no fatal condition, we proceed to do work */
+		if ( inmail & MB_IN_STUFFED ) {
+			pB->i2eFifoInInts++;
+			i2StripFifo(pB);     /* There might be incoming packets */
+		}
+
+		if (inmail & MB_OUT_STRIPPED) {
+			pB->i2eFifoOutInts++;
+			write_lock_irqsave(&pB->write_fifo_spinlock, flags);
+			pB->i2eFifoRemains = pB->i2eFifoSize;
+			pB->i2eWaitingForEmptyFifo = 0;
+			write_unlock_irqrestore(&pB->write_fifo_spinlock,
+					flags);
+
+			ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
+
+		}
+		serviceOutgoingFifo(pB);
+	}
+
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 );
+
+exit_i2ServiceBoard:
+
+	return 0;
+}
diff --git a/drivers/staging/tty/ip2/i2lib.h b/drivers/staging/tty/ip2/i2lib.h
new file mode 100644
index 0000000..e559e9b
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2lib.h
@@ -0,0 +1,351 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Header file for high level library functions
+*
+*******************************************************************************/
+#ifndef I2LIB_H
+#define I2LIB_H   1
+//------------------------------------------------------------------------------
+// I2LIB.H
+//
+// IntelliPort-II and IntelliPort-IIEX
+//
+// Defines, structure definitions, and external declarations for i2lib.c
+//------------------------------------------------------------------------------
+//--------------------------------------
+// Mandatory Includes:
+//--------------------------------------
+#include "ip2types.h"
+#include "i2ellis.h"
+#include "i2pack.h"
+#include "i2cmd.h"
+#include <linux/workqueue.h>
+
+//------------------------------------------------------------------------------
+// i2ChanStr -- Channel Structure:
+// Used to track per-channel information for the library routines using standard
+// loadware. Note also, a pointer to an array of these structures is patched
+// into the i2eBordStr (see i2ellis.h)
+//------------------------------------------------------------------------------
+//
+// If we make some limits on the maximum block sizes, we can avoid dealing with
+// buffer wrap. The wrapping of the buffer is based on where the start of the
+// packet is. Then there is always room for the packet contiguously.
+//
+// Maximum total length of an outgoing data or in-line command block. The limit
+// of 36 on data is quite arbitrary and based more on DOS memory limitations
+// than the board interface. However, for commands, the maximum packet length is
+// MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits
+// (see I2PACK.H) in such packets. For data packets, the count field size is not
+// the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE,
+// but be careful if wanting to modify either.
+//
+#define MAX_OBUF_BLOCK  36
+
+// Another note on maximum block sizes: we are buffering packets here. Data is
+// put into the buffer (if there is room) regardless of the credits from the
+// board. The board sends new credits whenever it has removed from his buffers a
+// number of characters equal to 80% of total buffer size. (Of course, the total
+// buffer size is what is reported when the very first set of flow control
+// status packets are received from the board. Therefore, to be robust, you must
+// always fill the board to at least 80% of the current credit limit, else you
+// might not give it enough to trigger a new report. These conditions are
+// obtained here so long as the maximum output block size is less than 20% the
+// size of the board's output buffers. This is true at present by "coincidence"
+// or "infernal knowledge": the board's output buffers are at least 700 bytes
+// long (20% = 140 bytes, at least). The 80% figure is "official", so the safest
+// strategy might be to trap the first flow control report and guarantee that
+// the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first
+// reported buffer credit.
+//
+#define MAX_CBUF_BLOCK  6	// Maximum total length of a bypass command block
+
+#define IBUF_SIZE       512	// character capacity of input buffer per channel
+#define OBUF_SIZE       1024// character capacity of output buffer per channel
+#define CBUF_SIZE       10	// character capacity of output bypass buffer
+
+typedef struct _i2ChanStr
+{
+	// First, back-pointers so that given a pointer to this structure, you can
+	// determine the correct board and channel number to reference, (say, when
+	// issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.)
+
+	int      port_index;    // Index of port in channel structure array attached
+							// to board structure.
+	PTTY     pTTY;          // Pointer to tty structure for port (OS specific)
+	USHORT   validity;      // Indicates whether the given channel has been
+							// initialized, really exists (or is a missing
+							// channel, e.g. channel 9 on an 8-port box.)
+
+	i2eBordStrPtr  pMyBord; // Back-pointer to this channel's board structure 
+
+	int      wopen;			// waiting fer carrier
+
+	int      throttled;		// Set if upper layer can take no data
+
+	int      flags;         // Defined in tty.h
+
+	PWAITQ   open_wait;     // Pointer for OS sleep function.
+	PWAITQ   close_wait;    // Pointer for OS sleep function.
+	PWAITQ   delta_msr_wait;// Pointer for OS sleep function.
+	PWAITQ   dss_now_wait;	// Pointer for OS sleep function.
+
+	struct timer_list  BookmarkTimer;   // Used by i2DrainOutput
+	wait_queue_head_t pBookmarkWait;   // Used by i2DrainOutput
+
+	int      BaudBase;
+	int      BaudDivisor;
+
+	USHORT   ClosingDelay;
+	USHORT   ClosingWaitTime;
+
+	volatile
+	flowIn   infl;	// This structure is initialized as a completely
+					// formed flow-control command packet, and as such
+					// has the channel number, also the capacity and
+					// "as-of" data needed continuously.
+
+	USHORT   sinceLastFlow; // Counts the number of characters read from input
+							// buffers, since the last time flow control info
+							// was sent.
+
+	USHORT   whenSendFlow;  // Determines when new flow control is to be sent to
+							// the board. Note unlike earlier manifestations of
+							// the driver, these packets can be sent from
+							// in-place.
+
+	USHORT   channelNeeds;  // Bit map of important things which must be done
+							// for this channel. (See bits below )
+
+	volatile
+	flowStat outfl;         // Same type of structure is used to hold current
+							// flow control information used to control our
+							// output. "asof" is kept updated as data is sent,
+							// and "room" never goes to zero.
+
+	// The incoming ring buffer
+	// Unlike the outgoing buffers, this holds raw data, not packets. The two
+	// extra bytes are used to hold the byte-padding when there is room for an
+	// odd number of bytes before we must wrap.
+	//
+	UCHAR    Ibuf[IBUF_SIZE + 2];
+	volatile
+	USHORT   Ibuf_stuff;     // Stuffing index
+	volatile
+	USHORT   Ibuf_strip;     // Stripping index
+
+	// The outgoing ring-buffer: Holds Data and command packets. N.B., even
+	// though these are in the channel structure, the channel is also written
+	// here, the easier to send it to the fifo when ready. HOWEVER, individual
+	// packets here are NOT padded to even length: the routines for writing
+	// blocks to the fifo will pad to even byte counts.
+	//
+	UCHAR	Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4];
+	volatile
+	USHORT	Obuf_stuff;     // Stuffing index
+	volatile
+	USHORT	Obuf_strip;     // Stripping index
+	int	Obuf_char_count;
+
+	// The outgoing bypass-command buffer. Unlike earlier manifestations, the
+	// flow control packets are sent directly from the structures. As above, the
+	// channel number is included in the packet, but they are NOT padded to even
+	// size.
+	//
+	UCHAR    Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2];
+	volatile
+	USHORT   Cbuf_stuff;     // Stuffing index
+	volatile
+	USHORT   Cbuf_strip;     // Stripping index
+
+	// The temporary buffer for the Linux tty driver PutChar entry.
+	//
+	UCHAR    Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)];
+	volatile
+	USHORT   Pbuf_stuff;     // Stuffing index
+
+	// The state of incoming data-set signals
+	//
+	USHORT   dataSetIn;     // Bit-mapped according to below. Also indicates
+							// whether a break has been detected since last
+							// inquiry.
+
+	// The state of outcoming data-set signals (as far as we can tell!)
+	//
+	USHORT   dataSetOut;     // Bit-mapped according to below. 
+
+	// Most recent hot-key identifier detected
+	//
+	USHORT   hotKeyIn;      // Hot key as sent by the board, HOT_CLEAR indicates
+				// no hot key detected since last examined.
+
+	// Counter of outstanding requests for bookmarks
+	//
+	short   bookMarks;	// Number of outstanding bookmark requests, (+ive
+						// whenever a bookmark request if queued up, -ive
+						// whenever a bookmark is received).
+
+	// Misc options
+	//
+	USHORT   channelOptions;   // See below
+
+	// To store various incoming special packets
+	//
+	debugStat   channelStatus;
+	cntStat     channelRcount;
+	cntStat     channelTcount;
+	failStat    channelFail;
+
+	// To store the last values for line characteristics we sent to the board.
+	//
+	int	speed;
+
+	int flush_flags;
+
+	void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...);
+
+	/*
+	 * Kernel counters for the 4 input interrupts 
+	 */
+	struct async_icount icount;
+
+	/*
+	 *	Task queues for processing input packets from the board.
+	 */
+	struct work_struct	tqueue_input;
+	struct work_struct	tqueue_status;
+	struct work_struct	tqueue_hangup;
+
+	rwlock_t Ibuf_spinlock;
+	rwlock_t Obuf_spinlock;
+	rwlock_t Cbuf_spinlock;
+	rwlock_t Pbuf_spinlock;
+
+} i2ChanStr, *i2ChanStrPtr;
+
+//---------------------------------------------------
+// Manifests and bit-maps for elements in i2ChanStr
+//---------------------------------------------------
+//
+// flush flags
+//
+#define STARTFL_FLAG 1
+#define STOPFL_FLAG  2
+
+// validity
+//
+#define CHANNEL_MAGIC_BITS 0xff00
+#define CHANNEL_MAGIC      0x5300   // (validity & CHANNEL_MAGIC_BITS) ==
+									// CHANNEL_MAGIC --> structure good
+
+#define CHANNEL_SUPPORT    0x0001   // Indicates channel is supported, exists,
+									// and passed P.O.S.T.
+
+// channelNeeds
+//
+#define NEED_FLOW    1  // Indicates flow control has been queued
+#define NEED_INLINE  2  // Indicates inline commands or data queued
+#define NEED_BYPASS  4  // Indicates bypass commands queued
+#define NEED_CREDIT  8  // Indicates would be sending except has not sufficient
+						// credit. The data is still in the channel structure,
+						// but the channel is not enqueued in the board
+						// structure again until there is a credit received from
+						// the board.
+
+// dataSetIn (Also the bits for i2GetStatus return value)
+//
+#define I2_DCD 1
+#define I2_CTS 2
+#define I2_DSR 4
+#define I2_RI  8
+
+// dataSetOut (Also the bits for i2GetStatus return value)
+//
+#define I2_DTR 1
+#define I2_RTS 2
+
+// i2GetStatus() can optionally clear these bits
+//
+#define I2_BRK    0x10  // A break was detected
+#define I2_PAR    0x20  // A parity error was received 
+#define I2_FRA    0x40  // A framing error was received
+#define I2_OVR    0x80  // An overrun error was received 
+
+// i2GetStatus() automatically clears these bits */
+//
+#define I2_DDCD   0x100 // DCD changed from its  former value
+#define I2_DCTS   0x200 // CTS changed from its former value 
+#define I2_DDSR   0x400 // DSR changed from its former value 
+#define I2_DRI    0x800 // RI changed from its former value 
+
+// hotKeyIn
+//
+#define HOT_CLEAR 0x1322   // Indicates that no hot-key has been detected
+
+// channelOptions
+//
+#define CO_NBLOCK_WRITE 1  	// Writes don't block waiting for buffer. (Default
+							// is, they do wait.)
+
+// fcmodes
+//
+#define I2_OUTFLOW_CTS  0x0001
+#define I2_INFLOW_RTS   0x0002
+#define I2_INFLOW_DSR   0x0004
+#define I2_INFLOW_DTR   0x0008
+#define I2_OUTFLOW_DSR  0x0010
+#define I2_OUTFLOW_DTR  0x0020
+#define I2_OUTFLOW_XON  0x0040
+#define I2_OUTFLOW_XANY 0x0080
+#define I2_INFLOW_XON   0x0100
+
+#define I2_CRTSCTS      (I2_OUTFLOW_CTS|I2_INFLOW_RTS)
+#define I2_IXANY_MODE   (I2_OUTFLOW_XON|I2_OUTFLOW_XANY)
+
+//-------------------------------------------
+// Macros used from user level like functions
+//-------------------------------------------
+
+// Macros to set and clear channel options
+//
+#define i2SetOption(pCh, option) pCh->channelOptions |= option
+#define i2ClrOption(pCh, option) pCh->channelOptions &= ~option
+
+// Macro to set fatal-error trap
+//
+#define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine
+
+//--------------------------------------------
+// Declarations and prototypes for i2lib.c
+//--------------------------------------------
+//
+static int  i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr);
+static int  i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...);
+static int  i2GetStatus(i2ChanStrPtr, int);
+static int  i2Input(i2ChanStrPtr);
+static int  i2InputFlush(i2ChanStrPtr);
+static int  i2Output(i2ChanStrPtr, const char *, int);
+static int  i2OutputFree(i2ChanStrPtr);
+static int  i2ServiceBoard(i2eBordStrPtr);
+static void i2DrainOutput(i2ChanStrPtr, int);
+
+#ifdef IP2DEBUG_TRACE
+void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);
+#else
+#define ip2trace(a,b,c,d...) do {} while (0)
+#endif
+
+// Argument to i2QueueCommands
+//
+#define C_IN_LINE 1
+#define C_BYPASS  0
+
+#endif   // I2LIB_H
diff --git a/drivers/staging/tty/ip2/i2pack.h b/drivers/staging/tty/ip2/i2pack.h
new file mode 100644
index 0000000..00342a6
--- /dev/null
+++ b/drivers/staging/tty/ip2/i2pack.h
@@ -0,0 +1,364 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Definitions of the packets used to transfer data and commands
+*                Host <--> Board. Information provided here is only applicable
+*                when the standard loadware is active.
+*
+*******************************************************************************/
+#ifndef I2PACK_H
+#define I2PACK_H  1
+
+//-----------------------------------------------
+// Revision History:
+//
+// 10 October 1991   MAG First draft
+// 24 February 1992  MAG Additions for 1.4.x loadware
+// 11 March 1992     MAG New status packets
+//
+//-----------------------------------------------
+
+//------------------------------------------------------------------------------
+// Packet Formats:
+//
+// Information passes between the host and board through the FIFO in packets.
+// These have headers which indicate the type of packet. Because the fifo data
+// path may be 16-bits wide, the protocol is constrained such that each packet
+// is always padded to an even byte count. (The lower-level interface routines
+// -- i2ellis.c -- are designed to do this).
+//
+// The sender (be it host or board) must place some number of complete packets
+// in the fifo, then place a message in the mailbox that packets are available.
+// Placing such a message interrupts the "receiver" (be it board or host), who
+// reads the mailbox message and determines that there are incoming packets
+// ready. Since there are no partial packets, and the length of a packet is
+// given in the header, the remainder of the packet can be read without checking
+// for FIFO empty condition. The process is repeated, packet by packet, until
+// the incoming FIFO is empty. Then the receiver uses the outbound mailbox to
+// signal the board that it has read the data. Only then can the sender place
+// additional data in the fifo.
+//------------------------------------------------------------------------------
+//
+//------------------------------------------------
+// Definition of Packet Header Area
+//------------------------------------------------
+//
+// Caution: these only define header areas. In actual use the data runs off
+// beyond the end of these structures.
+//
+// Since these structures are based on sequences of bytes which go to the board,
+// there cannot be ANY padding between the elements.
+#pragma pack(1)
+
+//----------------------------
+// DATA PACKETS
+//----------------------------
+
+typedef struct _i2DataHeader
+{
+	unsigned char i2sChannel;  /* The channel number: 0-255 */
+
+	// -- Bitfields are allocated LSB first --
+
+	// For incoming data, indicates whether this is an ordinary packet or a
+	// special one (e.g., hot key hit).
+	unsigned i2sId : 2 __attribute__ ((__packed__));
+
+	// For tagging data packets. There are flush commands which flush only data
+	// packets bearing a particular tag. (used in implementing IntelliView and
+	// IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has
+	// meaning internally to the loadware).
+	unsigned i2sTag : 4;
+
+	// These two bits determine the type of packet sent/received.
+	unsigned i2sType : 2;
+
+	// The count of data to follow: does not include the possible additional
+	// padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0.
+	unsigned short i2sCount;
+
+} i2DataHeader, *i2DataHeaderPtr;
+
+// Structure is immediately followed by the data, proper.
+
+//----------------------------
+// NON-DATA PACKETS
+//----------------------------
+
+typedef struct _i2CmdHeader
+{
+	unsigned char i2sChannel;	// The channel number: 0-255 (Except where noted
+								// - see below
+
+	// Number of bytes of commands, status or whatever to follow
+	unsigned i2sCount : 6;
+
+	// These two bits determine the type of packet sent/received.
+	unsigned i2sType : 2;
+
+} i2CmdHeader, *i2CmdHeaderPtr;
+
+// Structure is immediately followed by the applicable data.
+
+//---------------------------------------
+// Flow Control Packets (Outbound)
+//---------------------------------------
+
+// One type of outbound command packet is so important that the entire structure
+// is explicitly defined here. That is the flow-control packet. This is never
+// sent by user-level code (as would be the commands to raise/lower DTR, for
+// example). These are only sent by the library routines in response to reading
+// incoming data into the buffers.
+//
+// The parameters inside the command block are maintained in place, then the
+// block is sent at the appropriate time.
+
+typedef struct _flowIn
+{
+	i2CmdHeader    hd;      // Channel #, count, type (see above)
+	unsigned char  fcmd;    // The flow control command (37)
+	unsigned short asof;    // As of byte number "asof" (LSB first!) I have room
+							// for "room" bytes
+	unsigned short room;
+} flowIn, *flowInPtr;
+
+//----------------------------------------
+// (Incoming) Status Packets
+//----------------------------------------
+
+// Incoming packets which are non-data packets are status packets. In this case,
+// the channel number in the header is unimportant. What follows are one or more
+// sub-packets, the first word of which consists of the channel (first or low
+// byte) and the status indicator (second or high byte), followed by possibly
+// more data.
+
+#define STAT_CTS_UP     0  /* CTS raised  (no other bytes) */
+#define STAT_CTS_DN     1  /* CTS dropped (no other bytes) */
+#define STAT_DCD_UP     2  /* DCD raised  (no other bytes) */
+#define STAT_DCD_DN     3  /* DCD dropped (no other bytes) */
+#define STAT_DSR_UP     4  /* DSR raised  (no other bytes) */
+#define STAT_DSR_DN     5  /* DSR dropped (no other bytes) */
+#define STAT_RI_UP      6  /* RI  raised  (no other bytes) */
+#define STAT_RI_DN      7  /* RI  dropped (no other bytes) */
+#define STAT_BRK_DET    8  /* BRK detect  (no other bytes) */
+#define STAT_FLOW       9  /* Flow control(-- more: see below */
+#define STAT_BMARK      10 /* Bookmark    (no other bytes)
+							* Bookmark is sent as a response to
+							* a command 60: request for bookmark
+							*/
+#define STAT_STATUS     11 /* Special packet: see below */
+#define STAT_TXCNT      12 /* Special packet: see below */
+#define STAT_RXCNT      13 /* Special packet: see below */
+#define STAT_BOXIDS     14 /* Special packet: see below */
+#define STAT_HWFAIL     15 /* Special packet: see below */
+
+#define STAT_MOD_ERROR  0xc0
+#define STAT_MODEM      0xc0/* If status & STAT_MOD_ERROR:
+							 * == STAT_MODEM, then this is a modem
+							 * status packet, given in response to a
+							 * CMD_DSS_NOW command.
+							 * The low nibble has each data signal:
+							 */
+#define STAT_MOD_DCD    0x8
+#define STAT_MOD_RI     0x4
+#define STAT_MOD_DSR    0x2
+#define STAT_MOD_CTS    0x1
+
+#define STAT_ERROR      0x80/* If status & STAT_MOD_ERROR
+							 * == STAT_ERROR, then
+							 * sort of error on the channel.
+							 * The remaining seven bits indicate
+							 * what sort of error it is.
+							 */
+/* The low three bits indicate parity, framing, or overrun errors */
+
+#define STAT_E_PARITY   4     /* Parity error */
+#define STAT_E_FRAMING  2     /* Framing error */
+#define STAT_E_OVERRUN  1     /* (uxart) overrun error */
+
+//---------------------------------------
+// STAT_FLOW packets
+//---------------------------------------
+
+typedef struct _flowStat
+{
+	unsigned short asof;
+	unsigned short room;
+}flowStat, *flowStatPtr;
+
+// flowStat packets are received from the board to regulate the flow of outgoing
+// data. A local copy of this structure is also kept to track the amount of
+// credits used and credits remaining. "room" is the amount of space in the
+// board's buffers, "as of" having received a certain byte number. When sending
+// data to the fifo, you must calculate how much buffer space your packet will
+// use.  Add this to the current "asof" and subtract it from the current "room".
+//
+// The calculation for the board's buffer is given by CREDIT_USAGE, where size
+// is the un-rounded count of either data characters or command characters.
+// (Which is to say, the count rounded up, plus two).
+
+#define CREDIT_USAGE(size) (((size) + 3) & ~1)
+
+//---------------------------------------
+// STAT_STATUS packets
+//---------------------------------------
+
+typedef  struct   _debugStat
+{
+	unsigned char d_ccsr;
+	unsigned char d_txinh;
+	unsigned char d_stat1;
+	unsigned char d_stat2;
+} debugStat, *debugStatPtr;
+
+// debugStat packets are sent to the host in response to a CMD_GET_STATUS
+// command.  Each byte is bit-mapped as described below:
+
+#define D_CCSR_XON      2     /* Has received XON, ready to transmit */
+#define D_CCSR_XOFF     4     /* Has received XOFF, not transmitting */
+#define D_CCSR_TXENAB   8     /* Transmitter is enabled */
+#define D_CCSR_RXENAB   0x80  /* Receiver is enabled */
+
+#define D_TXINH_BREAK   1     /* We are sending a break */
+#define D_TXINH_EMPTY   2     /* No data to send */
+#define D_TXINH_SUSP    4     /* Output suspended via command 57 */
+#define D_TXINH_CMD     8     /* We are processing an in-line command */
+#define D_TXINH_LCD     0x10  /* LCD diagnostics are running */
+#define D_TXINH_PAUSE   0x20  /* We are processing a PAUSE command */
+#define D_TXINH_DCD     0x40  /* DCD is low, preventing transmission */
+#define D_TXINH_DSR     0x80  /* DSR is low, preventing transmission */
+
+#define D_STAT1_TXEN    1     /* Transmit INTERRUPTS enabled */
+#define D_STAT1_RXEN    2     /* Receiver INTERRUPTS enabled */
+#define D_STAT1_MDEN    4     /* Modem (data set sigs) interrupts enabled */
+#define D_STAT1_RLM     8     /* Remote loopback mode selected */
+#define D_STAT1_LLM     0x10  /* Local internal loopback mode selected */
+#define D_STAT1_CTS     0x20  /* CTS is low, preventing transmission */
+#define D_STAT1_DTR     0x40  /* DTR is low, to stop remote transmission */
+#define D_STAT1_RTS     0x80  /* RTS is low, to stop remote transmission */
+
+#define D_STAT2_TXMT    1     /* Transmit buffers are all empty */
+#define D_STAT2_RXMT    2     /* Receive buffers are all empty */
+#define D_STAT2_RXINH   4     /* Loadware has tried to inhibit remote
+							   * transmission:  dropped DTR, sent XOFF,
+							   * whatever...
+							   */
+#define D_STAT2_RXFLO   8     /* Loadware can send no more data to host
+							   * until it receives a flow-control packet
+							   */
+//-----------------------------------------
+// STAT_TXCNT and STAT_RXCNT packets
+//----------------------------------------
+
+typedef  struct   _cntStat
+{
+	unsigned short cs_time;    // (Assumes host is little-endian!)
+	unsigned short cs_count;
+} cntStat, *cntStatPtr;
+
+// These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT
+// bypass command. cs_time is a running 1 Millisecond counter which acts as a
+// time stamp. cs_count is a running counter of data sent or received from the
+// uxarts. (Not including data added by the chip itself, as with CRLF
+// processing).
+//------------------------------------------
+// STAT_HWFAIL packets
+//------------------------------------------
+
+typedef struct _failStat
+{
+	unsigned char fs_written;
+	unsigned char fs_read;
+	unsigned short fs_address;
+} failStat, *failStatPtr;
+
+// This packet is sent whenever the on-board diagnostic process detects an
+// error. At startup, this process is dormant. The host can wake it up by
+// issuing the bypass command CMD_HW_TEST. The process runs at low priority and
+// performs continuous hardware verification; writing data to certain on-board
+// registers, reading it back, and comparing. If it detects an error, this
+// packet is sent to the host, and the process goes dormant again until the host
+// sends another CMD_HW_TEST. It then continues with the next register to be
+// tested.
+
+//------------------------------------------------------------------------------
+// Macros to deal with the headers more easily! Note that these are defined so
+// they may be used as "left" as well as "right" expressions.
+//------------------------------------------------------------------------------
+
+// Given a pointer to the packet, reference the channel number
+//
+#define CHANNEL_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sChannel
+
+// Given a pointer to the packet, reference the Packet type
+//
+#define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType
+
+// The possible types of packets
+//
+#define PTYPE_DATA   0  /* Host <--> Board */
+#define PTYPE_BYPASS 1  /* Host ---> Board */
+#define PTYPE_INLINE 2  /* Host ---> Board */
+#define PTYPE_STATUS 2  /* Host <--- Board */
+
+// Given a pointer to a Data packet, reference the Tag
+//
+#define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag
+
+// Given a pointer to a Data packet, reference the data i.d.
+//
+#define ID_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sId
+
+// The possible types of ID's
+//
+#define ID_ORDINARY_DATA   0
+#define ID_HOT_KEY         1
+
+// Given a pointer to a Data packet, reference the count
+//
+#define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount
+
+// Given a pointer to a Data packet, reference the beginning of data
+//
+#define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header
+
+// Given a pointer to a Non-Data packet, reference the count
+//
+#define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount
+
+#define MAX_CMD_PACK_SIZE  62 // Maximum size of such a count
+
+// Given a pointer to a Non-Data packet, reference the beginning of data
+//
+#define CMD_OF(pP) &((unsigned char *)(pP))[2]  // 2 = size of header
+
+//--------------------------------
+// MailBox Bits:
+//--------------------------------
+
+//--------------------------
+// Outgoing (host to board)
+//--------------------------
+//
+#define MB_OUT_STUFFED     0x80  // Host has placed output in fifo 
+#define MB_IN_STRIPPED     0x40  // Host has read in all input from fifo 
+
+//--------------------------
+// Incoming (board to host)
+//--------------------------
+//
+#define MB_IN_STUFFED      0x80  // Board has placed input in fifo 
+#define MB_OUT_STRIPPED    0x40  // Board has read all output from fifo 
+#define MB_FATAL_ERROR     0x20  // Board has encountered a fatal error
+
+#pragma pack()                  // Reset padding to command-line default
+
+#endif      // I2PACK_H
+
diff --git a/drivers/staging/tty/ip2/ip2.h b/drivers/staging/tty/ip2/ip2.h
new file mode 100644
index 0000000..936ccc5
--- /dev/null
+++ b/drivers/staging/tty/ip2/ip2.h
@@ -0,0 +1,107 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Driver constants for configuration and tuning
+*
+*   NOTES:
+*
+*******************************************************************************/
+#ifndef IP2_H
+#define IP2_H
+
+#include "ip2types.h"
+#include "i2cmd.h"
+
+/*************/
+/* Constants */
+/*************/
+
+/* Device major numbers - since version 2.0.26. */
+#define IP2_TTY_MAJOR      71
+#define IP2_CALLOUT_MAJOR  72
+#define IP2_IPL_MAJOR      73
+
+/* Board configuration array.
+ * This array defines the hardware irq and address for up to IP2_MAX_BOARDS
+ * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified,
+ * PCI and EISA boards are probed for and automagicly configed
+ * iff the addresses are set to 1 and 2 respectivily.
+ *    0x0100 - 0x03f0 == ISA
+ *	         1        == PCI
+ *	         2        == EISA
+ *	         0        == (skip this board)
+ * This array defines the hardware addresses for them. Special 
+ * addresses are EISA and PCI which go sniffing for boards. 
+
+ * In a multiboard system the position in the array determines which port
+ * devices are assigned to each board: 
+ *		board 0 is assigned ttyF0.. to ttyF63, 
+ *		board 1 is assigned ttyF64  to ttyF127,
+ *		board 2 is assigned ttyF128 to ttyF191,
+ *		board 3 is assigned ttyF192 to ttyF255. 
+ *
+ * In PCI and EISA bus systems each range is mapped to card in 
+ * monotonically increasing slot number order, ISA position is as specified
+ * here.
+
+ * If the irqs are ALL set to 0,0,0,0 all boards operate in 
+ * polled mode. For interrupt operation ISA boards require that the IRQ be 
+ * specified, while PCI and EISA boards any nonzero entry 
+ * will enable interrupts using the BIOS configured irq for the board. 
+ * An invalid irq entry will default to polled mode for that card and print
+ * console warning.
+ 
+ * When the driver is loaded as a module these setting can be overridden on the 
+ * modprobe command line or on an option line in /etc/modprobe.conf.
+ * If the driver is built-in the configuration must be 
+ * set here for ISA cards and address set to 1 and 2 for PCI and EISA.
+ *
+ * Here is an example that shows most if not all possibe combinations:
+
+ *static ip2config_t ip2config =
+ *{
+ *	{11,1,0,0},		// irqs
+ *	{				// Addresses
+ *		0x0308,		// Board 0, ttyF0   - ttyF63// ISA card at io=0x308, irq=11
+ *		0x0001,		// Board 1, ttyF64  - ttyF127//PCI card configured by BIOS
+ *		0x0000,		// Board 2, ttyF128 - ttyF191// Slot skipped
+ *		0x0002		// Board 3, ttyF192 - ttyF255//EISA card configured by BIOS
+ *												 // but polled not irq driven
+ *	}
+ *};
+ */
+
+ /* this structure is zeroed out because the suggested method is to configure
+  * the driver as a module, set up the parameters with an options line in
+  * /etc/modprobe.conf and load with modprobe or kmod, the kernel
+  * module loader
+  */
+
+ /* This structure is NOW always initialized when the driver is initialized.
+  * Compiled in defaults MUST be added to the io and irq arrays in
+  * ip2.c.  Those values are configurable from insmod parameters in the
+  * case of modules or from command line parameters (ip2=io,irq) when
+  * compiled in.
+  */
+
+static ip2config_t ip2config =
+{
+	{0,0,0,0},		// irqs
+	{				// Addresses
+	/* Do NOT set compile time defaults HERE!  Use the arrays in
+		ip2.c!  These WILL be overwritten!  =mhw= */
+		0x0000,		// Board 0, ttyF0   - ttyF63
+		0x0000,		// Board 1, ttyF64  - ttyF127
+		0x0000,		// Board 2, ttyF128 - ttyF191
+		0x0000		// Board 3, ttyF192 - ttyF255
+	}
+};
+
+#endif
diff --git a/drivers/staging/tty/ip2/ip2ioctl.h b/drivers/staging/tty/ip2/ip2ioctl.h
new file mode 100644
index 0000000..aa0a9da
--- /dev/null
+++ b/drivers/staging/tty/ip2/ip2ioctl.h
@@ -0,0 +1,35 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Driver constants for configuration and tuning
+*
+*   NOTES:
+*
+*******************************************************************************/
+
+#ifndef IP2IOCTL_H
+#define IP2IOCTL_H
+
+//*************
+//* Constants *
+//*************
+
+// High baud rates (if not defined elsewhere.
+#ifndef B153600   
+#	define B153600   0010005
+#endif
+#ifndef B307200   
+#	define B307200   0010006
+#endif
+#ifndef B921600   
+#	define B921600   0010007
+#endif
+
+#endif
diff --git a/drivers/staging/tty/ip2/ip2main.c b/drivers/staging/tty/ip2/ip2main.c
new file mode 100644
index 0000000..ea7a8fb
--- /dev/null
+++ b/drivers/staging/tty/ip2/ip2main.c
@@ -0,0 +1,3234 @@
+/*
+*
+*   (c) 1999 by Computone Corporation
+*
+********************************************************************************
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Mainline code for the device driver
+*
+*******************************************************************************/
+// ToDo:
+//
+// Fix the immediate DSS_NOW problem.
+// Work over the channel stats return logic in ip2_ipl_ioctl so they
+//	make sense for all 256 possible channels and so the user space
+//	utilities will compile and work properly.
+//
+// Done:
+//
+// 1.2.14	/\/\|=mhw=|\/\/
+// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
+// Changed the definition of ip2trace to be more consistent with kernel style
+//	Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates
+//
+// 1.2.13	/\/\|=mhw=|\/\/
+// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform
+//	to agreed devfs serial device naming convention.
+//
+// 1.2.12	/\/\|=mhw=|\/\/
+// Cleaned up some remove queue cut and paste errors
+//
+// 1.2.11	/\/\|=mhw=|\/\/
+// Clean up potential NULL pointer dereferences
+// Clean up devfs registration
+// Add kernel command line parsing for io and irq
+//	Compile defaults for io and irq are now set in ip2.c not ip2.h!
+// Reworked poll_only hack for explicit parameter setting
+//	You must now EXPLICITLY set poll_only = 1 or set all irqs to 0
+// Merged ip2_loadmain and old_ip2_init
+// Converted all instances of interruptible_sleep_on into queue calls
+//	Most of these had no race conditions but better to clean up now
+//
+// 1.2.10	/\/\|=mhw=|\/\/
+// Fixed the bottom half interrupt handler and enabled USE_IQI
+//	to split the interrupt handler into a formal top-half / bottom-half
+// Fixed timing window on high speed processors that queued messages to
+// 	the outbound mail fifo faster than the board could handle.
+//
+// 1.2.9
+// Four box EX was barfing on >128k kmalloc, made structure smaller by
+// reducing output buffer size
+//
+// 1.2.8
+// Device file system support (MHW)
+//
+// 1.2.7 
+// Fixed
+// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
+//
+// 1.2.6
+//Fixes DCD problems
+//	DCD was not reported when CLOCAL was set on call to TIOCMGET
+//
+//Enhancements:
+//	TIOCMGET requests and waits for status return
+//	No DSS interrupts enabled except for DCD when needed
+//
+// For internal use only
+//
+//#define IP2DEBUG_INIT
+//#define IP2DEBUG_OPEN
+//#define IP2DEBUG_WRITE
+//#define IP2DEBUG_READ
+//#define IP2DEBUG_IOCTL
+//#define IP2DEBUG_IPL
+
+//#define IP2DEBUG_TRACE
+//#define DEBUG_FIFO
+
+/************/
+/* Includes */
+/************/
+
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/major.h>
+#include <linux/wait.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/termios.h>
+#include <linux/tty_driver.h>
+#include <linux/serial.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+
+#include <linux/cdk.h>
+#include <linux/comstats.h>
+#include <linux/delay.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+
+#include "ip2types.h"
+#include "ip2trace.h"
+#include "ip2ioctl.h"
+#include "ip2.h"
+#include "i2ellis.h"
+#include "i2lib.h"
+
+/*****************
+ * /proc/ip2mem  *
+ *****************/
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static DEFINE_MUTEX(ip2_mutex);
+static const struct file_operations ip2mem_proc_fops;
+static const struct file_operations ip2_proc_fops;
+
+/********************/
+/* Type Definitions */
+/********************/
+
+/*************/
+/* Constants */
+/*************/
+
+/* String constants to identify ourselves */
+static const char pcName[] = "Computone IntelliPort Plus multiport driver";
+static const char pcVersion[] = "1.2.14";
+
+/* String constants for port names */
+static const char pcDriver_name[] = "ip2";
+static const char pcIpl[] = "ip2ipl";
+
+/***********************/
+/* Function Prototypes */
+/***********************/
+
+/* Global module entry functions */
+
+/* Private (static) functions */
+static int  ip2_open(PTTY, struct file *);
+static void ip2_close(PTTY, struct file *);
+static int  ip2_write(PTTY, const unsigned char *, int);
+static int  ip2_putchar(PTTY, unsigned char);
+static void ip2_flush_chars(PTTY);
+static int  ip2_write_room(PTTY);
+static int  ip2_chars_in_buf(PTTY);
+static void ip2_flush_buffer(PTTY);
+static int  ip2_ioctl(PTTY, UINT, ULONG);
+static void ip2_set_termios(PTTY, struct ktermios *);
+static void ip2_set_line_discipline(PTTY);
+static void ip2_throttle(PTTY);
+static void ip2_unthrottle(PTTY);
+static void ip2_stop(PTTY);
+static void ip2_start(PTTY);
+static void ip2_hangup(PTTY);
+static int  ip2_tiocmget(struct tty_struct *tty);
+static int  ip2_tiocmset(struct tty_struct *tty,
+			 unsigned int set, unsigned int clear);
+static int ip2_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount);
+
+static void set_irq(int, int);
+static void ip2_interrupt_bh(struct work_struct *work);
+static irqreturn_t ip2_interrupt(int irq, void *dev_id);
+static void ip2_poll(unsigned long arg);
+static inline void service_all_boards(void);
+static void do_input(struct work_struct *);
+static void do_status(struct work_struct *);
+
+static void ip2_wait_until_sent(PTTY,int);
+
+static void set_params (i2ChanStrPtr, struct ktermios *);
+static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
+static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
+
+static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
+static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
+static int ip2_ipl_open(struct inode *, struct file *);
+
+static int DumpTraceBuffer(char __user *, int);
+static int DumpFifoBuffer( char __user *, int);
+
+static void ip2_init_board(int, const struct firmware *);
+static unsigned short find_eisa_board(int);
+static int ip2_setup(char *str);
+
+/***************/
+/* Static Data */
+/***************/
+
+static struct tty_driver *ip2_tty_driver;
+
+/* Here, then is a table of board pointers which the interrupt routine should
+ * scan through to determine who it must service.
+ */
+static unsigned short i2nBoards; // Number of boards here
+
+static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
+
+static i2ChanStrPtr  DevTable[IP2_MAX_PORTS];
+//DevTableMem just used to save addresses for kfree
+static void  *DevTableMem[IP2_MAX_BOARDS];
+
+/* This is the driver descriptor for the ip2ipl device, which is used to
+ * download the loadware to the boards.
+ */
+static const struct file_operations ip2_ipl = {
+	.owner		= THIS_MODULE,
+	.read		= ip2_ipl_read,
+	.write		= ip2_ipl_write,
+	.unlocked_ioctl	= ip2_ipl_ioctl,
+	.open		= ip2_ipl_open,
+	.llseek		= noop_llseek,
+}; 
+
+static unsigned long irq_counter;
+static unsigned long bh_counter;
+
+// Use immediate queue to service interrupts
+#define USE_IQI
+//#define USE_IQ	// PCI&2.2 needs work
+
+/* The timer_list entry for our poll routine. If interrupt operation is not
+ * selected, the board is serviced periodically to see if anything needs doing.
+ */
+#define  POLL_TIMEOUT   (jiffies + 1)
+static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
+
+#ifdef IP2DEBUG_TRACE
+/* Trace (debug) buffer data */
+#define TRACEMAX  1000
+static unsigned long tracebuf[TRACEMAX];
+static int tracestuff;
+static int tracestrip;
+static int tracewrap;
+#endif
+
+/**********/
+/* Macros */
+/**********/
+
+#ifdef IP2DEBUG_OPEN
+#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
+		    tty->name,(pCh->flags), \
+		    tty->count,/*GET_USE_COUNT(module)*/0,s)
+#else
+#define DBG_CNT(s)
+#endif
+
+/********/
+/* Code */
+/********/
+
+#include "i2ellis.c"    /* Extremely low-level interface services */
+#include "i2cmd.c"      /* Standard loadware command definitions */
+#include "i2lib.c"      /* High level interface services */
+
+/* Configuration area for modprobe */
+
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+MODULE_LICENSE("GPL");
+
+#define	MAX_CMD_STR	50
+
+static int poll_only;
+static char cmd[MAX_CMD_STR];
+
+static int Eisa_irq;
+static int Eisa_slot;
+
+static int iindx;
+static char rirqs[IP2_MAX_BOARDS];
+static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
+
+/* Note: Add compiled in defaults to these arrays, not to the structure
+	in ip2.h any longer.  That structure WILL get overridden
+	by these values, or command line values, or insmod values!!!  =mhw=
+*/
+static int io[IP2_MAX_BOARDS];
+static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
+
+MODULE_AUTHOR("Doug McNash");
+MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
+module_param(poll_only, bool, 0);
+MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
+module_param_string(ip2, cmd, MAX_CMD_STR, 0);
+MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
+
+/* for sysfs class support */
+static struct class *ip2_class;
+
+/* Some functions to keep track of what irqs we have */
+
+static int __init is_valid_irq(int irq)
+{
+	int *i = Valid_Irqs;
+	
+	while (*i != 0 && *i != irq)
+		i++;
+
+	return *i;
+}
+
+static void __init mark_requested_irq(char irq)
+{
+	rirqs[iindx++] = irq;
+}
+
+static int __exit clear_requested_irq(char irq)
+{
+	int i;
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		if (rirqs[i] == irq) {
+			rirqs[i] = 0;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+static int have_requested_irq(char irq)
+{
+	/* array init to zeros so 0 irq will not be requested as a side
+	 * effect */
+	int i;
+	for (i = 0; i < IP2_MAX_BOARDS; ++i)
+		if (rirqs[i] == irq)
+			return 1;
+	return 0;
+}
+
+/******************************************************************************/
+/* Function:   cleanup_module()                                               */
+/* Parameters: None                                                           */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/* This is a required entry point for an installable module. It has to return */
+/* the device and the driver to a passive state. It should not be necessary   */
+/* to reset the board fully, especially as the loadware is downloaded         */
+/* externally rather than in the driver. We just want to disable the board    */
+/* and clear the loadware to a reset state. To allow this there has to be a   */
+/* way to detect whether the board has the loadware running at init time to   */
+/* handle subsequent installations of the driver. All memory allocated by the */
+/* driver should be returned since it may be unloaded from memory.            */
+/******************************************************************************/
+static void __exit ip2_cleanup_module(void)
+{
+	int err;
+	int i;
+
+	del_timer_sync(&PollTimer);
+
+	/* Reset the boards we have. */
+	for (i = 0; i < IP2_MAX_BOARDS; i++)
+		if (i2BoardPtrTable[i])
+			iiReset(i2BoardPtrTable[i]);
+
+	/* The following is done at most once, if any boards were installed. */
+	for (i = 0; i < IP2_MAX_BOARDS; i++) {
+		if (i2BoardPtrTable[i]) {
+			iiResetDelay(i2BoardPtrTable[i]);
+			/* free io addresses and Tibet */
+			release_region(ip2config.addr[i], 8);
+			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
+			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
+						4 * i + 1));
+		}
+		/* Disable and remove interrupt handler. */
+		if (ip2config.irq[i] > 0 &&
+				have_requested_irq(ip2config.irq[i])) {
+			free_irq(ip2config.irq[i], (void *)&pcName);
+			clear_requested_irq(ip2config.irq[i]);
+		}
+	}
+	class_destroy(ip2_class);
+	err = tty_unregister_driver(ip2_tty_driver);
+	if (err)
+		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
+				err);
+	put_tty_driver(ip2_tty_driver);
+	unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
+	remove_proc_entry("ip2mem", NULL);
+
+	/* free memory */
+	for (i = 0; i < IP2_MAX_BOARDS; i++) {
+		void *pB;
+#ifdef CONFIG_PCI
+		if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
+			pci_disable_device(ip2config.pci_dev[i]);
+			pci_dev_put(ip2config.pci_dev[i]);
+			ip2config.pci_dev[i] = NULL;
+		}
+#endif
+		pB = i2BoardPtrTable[i];
+		if (pB != NULL) {
+			kfree(pB);
+			i2BoardPtrTable[i] = NULL;
+		}
+		if (DevTableMem[i] != NULL) {
+			kfree(DevTableMem[i]);
+			DevTableMem[i] = NULL;
+		}
+	}
+}
+module_exit(ip2_cleanup_module);
+
+static const struct tty_operations ip2_ops = {
+	.open            = ip2_open,
+	.close           = ip2_close,
+	.write           = ip2_write,
+	.put_char        = ip2_putchar,
+	.flush_chars     = ip2_flush_chars,
+	.write_room      = ip2_write_room,
+	.chars_in_buffer = ip2_chars_in_buf,
+	.flush_buffer    = ip2_flush_buffer,
+	.ioctl           = ip2_ioctl,
+	.throttle        = ip2_throttle,
+	.unthrottle      = ip2_unthrottle,
+	.set_termios     = ip2_set_termios,
+	.set_ldisc       = ip2_set_line_discipline,
+	.stop            = ip2_stop,
+	.start           = ip2_start,
+	.hangup          = ip2_hangup,
+	.tiocmget	 = ip2_tiocmget,
+	.tiocmset	 = ip2_tiocmset,
+	.get_icount	 = ip2_get_icount,
+	.proc_fops	 = &ip2_proc_fops,
+};
+
+/******************************************************************************/
+/* Function:   ip2_loadmain()                                                 */
+/* Parameters: irq, io from command line of insmod et. al.                    */
+/*		pointer to fip firmware and firmware size for boards	      */
+/* Returns:    Success (0)                                                    */
+/*                                                                            */
+/* Description:                                                               */
+/* This was the required entry point for all drivers (now in ip2.c)           */
+/* It performs all                                                            */
+/* initialisation of the devices and driver structures, and registers itself  */
+/* with the relevant kernel modules.                                          */
+/******************************************************************************/
+/* IRQF_DISABLED - if set blocks all interrupts else only this line */
+/* IRQF_SHARED    - for shared irq PCI or maybe EISA only */
+/* SA_RANDOM   - can be source for cert. random number generators */
+#define IP2_SA_FLAGS	0
+
+
+static const struct firmware *ip2_request_firmware(void)
+{
+	struct platform_device *pdev;
+	const struct firmware *fw;
+
+	pdev = platform_device_register_simple("ip2", 0, NULL, 0);
+	if (IS_ERR(pdev)) {
+		printk(KERN_ERR "Failed to register platform device for ip2\n");
+		return NULL;
+	}
+	if (request_firmware(&fw, "intelliport2.bin", &pdev->dev)) {
+		printk(KERN_ERR "Failed to load firmware 'intelliport2.bin'\n");
+		fw = NULL;
+	}
+	platform_device_unregister(pdev);
+	return fw;
+}
+
+/******************************************************************************
+ *	ip2_setup:
+ *		str: kernel command line string
+ *
+ *	Can't autoprobe the boards so user must specify configuration on
+ *	kernel command line.  Sane people build it modular but the others
+ *	come here.
+ *
+ *	Alternating pairs of io,irq for up to 4 boards.
+ *		ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
+ *
+ *		io=0 => No board
+ *		io=1 => PCI
+ *		io=2 => EISA
+ *		else => ISA I/O address
+ *
+ *		irq=0 or invalid for ISA will revert to polling mode
+ *
+ *		Any value = -1, do not overwrite compiled in value.
+ *
+ ******************************************************************************/
+static int __init ip2_setup(char *str)
+{
+	int j, ints[10];	/* 4 boards, 2 parameters + 2 */
+	unsigned int i;
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
+	for (i = 0, j = 1; i < 4; i++) {
+		if (j > ints[0])
+			break;
+		if (ints[j] >= 0)
+			io[i] = ints[j];
+		j++;
+		if (j > ints[0])
+			break;
+		if (ints[j] >= 0)
+			irq[i] = ints[j];
+		j++;
+	}
+	return 1;
+}
+__setup("ip2=", ip2_setup);
+
+static int __init ip2_loadmain(void)
+{
+	int i, j, box;
+	int err = 0;
+	i2eBordStrPtr pB = NULL;
+	int rc = -1;
+	const struct firmware *fw = NULL;
+	char *str;
+
+	str = cmd;
+
+	if (poll_only) {
+		/* Hard lock the interrupts to zero */
+		irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
+	}
+
+	/* Check module parameter with 'ip2=' has been passed or not */
+	if (!poll_only && (!strncmp(str, "ip2=", 4)))
+		ip2_setup(str);
+
+	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
+
+	/* process command line arguments to modprobe or
+		insmod i.e. iop & irqp */
+	/* irqp and iop should ALWAYS be specified now...  But we check
+		them individually just to be sure, anyways... */
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		ip2config.addr[i] = io[i];
+		if (irq[i] >= 0)
+			ip2config.irq[i] = irq[i];
+		else
+			ip2config.irq[i] = 0;
+	/* This is a little bit of a hack.  If poll_only=1 on command
+	   line back in ip2.c OR all IRQs on all specified boards are
+	   explicitly set to 0, then drop to poll only mode and override
+	   PCI or EISA interrupts.  This superceeds the old hack of
+	   triggering if all interrupts were zero (like da default).
+	   Still a hack but less prone to random acts of terrorism.
+
+	   What we really should do, now that the IRQ default is set
+	   to -1, is to use 0 as a hard coded, do not probe.
+
+		/\/\|=mhw=|\/\/
+	*/
+		poll_only |= irq[i];
+	}
+	poll_only = !poll_only;
+
+	/* Announce our presence */
+	printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
+
+	ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
+	if (!ip2_tty_driver)
+		return -ENOMEM;
+
+	/* Initialise all the boards we can find (up to the maximum). */
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		switch (ip2config.addr[i]) {
+		case 0:	/* skip this slot even if card is present */
+			break;
+		default: /* ISA */
+		   /* ISA address must be specified */
+			if (ip2config.addr[i] < 0x100 ||
+					ip2config.addr[i] > 0x3f8) {
+				printk(KERN_ERR "IP2: Bad ISA board %d "
+						"address %x\n", i,
+						ip2config.addr[i]);
+				ip2config.addr[i] = 0;
+				break;
+			}
+			ip2config.type[i] = ISA;
+
+			/* Check for valid irq argument, set for polling if
+			 * invalid */
+			if (ip2config.irq[i] &&
+					!is_valid_irq(ip2config.irq[i])) {
+				printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
+						ip2config.irq[i]);
+				/* 0 is polling and is valid in that sense */
+				ip2config.irq[i] = 0;
+			}
+			break;
+		case PCI:
+#ifdef CONFIG_PCI
+		{
+			struct pci_dev *pdev = NULL;
+			u32 addr;
+			int status;
+
+			pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
+					PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
+			if (pdev == NULL) {
+				ip2config.addr[i] = 0;
+				printk(KERN_ERR "IP2: PCI board %d not "
+						"found\n", i);
+				break;
+			}
+
+			if (pci_enable_device(pdev)) {
+				dev_err(&pdev->dev, "can't enable device\n");
+				goto out;
+			}
+			ip2config.type[i] = PCI;
+			ip2config.pci_dev[i] = pci_dev_get(pdev);
+			status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
+					&addr);
+			if (addr & 1)
+				ip2config.addr[i] = (USHORT)(addr & 0xfffe);
+			else
+				dev_err(&pdev->dev, "I/O address error\n");
+
+			ip2config.irq[i] = pdev->irq;
+out:
+			pci_dev_put(pdev);
+		}
+#else
+			printk(KERN_ERR "IP2: PCI card specified but PCI "
+					"support not enabled.\n");
+			printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
+					"defined!\n");
+#endif /* CONFIG_PCI */
+			break;
+		case EISA:
+			ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
+			if (ip2config.addr[i] != 0) {
+				/* Eisa_irq set as side effect, boo */
+				ip2config.type[i] = EISA;
+			} 
+			ip2config.irq[i] = Eisa_irq;
+			break;
+		}	/* switch */
+	}	/* for */
+
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		if (ip2config.addr[i]) {
+			pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
+			if (pB) {
+				i2BoardPtrTable[i] = pB;
+				iiSetAddress(pB, ip2config.addr[i],
+						ii2DelayTimer);
+				iiReset(pB);
+			} else
+				printk(KERN_ERR "IP2: board memory allocation "
+						"error\n");
+		}
+	}
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		pB = i2BoardPtrTable[i];
+		if (pB != NULL) {
+			iiResetDelay(pB);
+			break;
+		}
+	}
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		/* We don't want to request the firmware unless we have at
+		   least one board */
+		if (i2BoardPtrTable[i] != NULL) {
+			if (!fw)
+				fw = ip2_request_firmware();
+			if (!fw)
+				break;
+			ip2_init_board(i, fw);
+		}
+	}
+	if (fw)
+		release_firmware(fw);
+
+	ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
+
+	ip2_tty_driver->owner		    = THIS_MODULE;
+	ip2_tty_driver->name                 = "ttyF";
+	ip2_tty_driver->driver_name          = pcDriver_name;
+	ip2_tty_driver->major                = IP2_TTY_MAJOR;
+	ip2_tty_driver->minor_start          = 0;
+	ip2_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
+	ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
+	ip2_tty_driver->init_termios         = tty_std_termios;
+	ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+	ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
+		TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(ip2_tty_driver, &ip2_ops);
+
+	ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
+
+	err = tty_register_driver(ip2_tty_driver);
+	if (err) {
+		printk(KERN_ERR "IP2: failed to register tty driver\n");
+		put_tty_driver(ip2_tty_driver);
+		return err; /* leaking resources */
+	}
+
+	err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
+	if (err) {
+		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
+				err);
+	} else {
+		/* create the sysfs class */
+		ip2_class = class_create(THIS_MODULE, "ip2");
+		if (IS_ERR(ip2_class)) {
+			err = PTR_ERR(ip2_class);
+			goto out_chrdev;	
+		}
+	}
+	/* Register the read_procmem thing */
+	if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
+		printk(KERN_ERR "IP2: failed to register read_procmem\n");
+		return -EIO; /* leaking resources */
+	}
+
+	ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
+	/* Register the interrupt handler or poll handler, depending upon the
+	 * specified interrupt.
+	 */
+
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		if (ip2config.addr[i] == 0)
+			continue;
+
+		pB = i2BoardPtrTable[i];
+		if (pB != NULL) {
+			device_create(ip2_class, NULL,
+				      MKDEV(IP2_IPL_MAJOR, 4 * i),
+				      NULL, "ipl%d", i);
+			device_create(ip2_class, NULL,
+				      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
+				      NULL, "stat%d", i);
+
+			for (box = 0; box < ABS_MAX_BOXES; box++)
+				for (j = 0; j < ABS_BIGGEST_BOX; j++)
+					if (pB->i2eChannelMap[box] & (1 << j))
+						tty_register_device(
+							ip2_tty_driver,
+							j + ABS_BIGGEST_BOX *
+							(box+i*ABS_MAX_BOXES),
+							NULL);
+		}
+
+		if (poll_only) {
+			/* Poll only forces driver to only use polling and
+			   to ignore the probed PCI or EISA interrupts. */
+			ip2config.irq[i] = CIR_POLL;
+		}
+		if (ip2config.irq[i] == CIR_POLL) {
+retry:
+			if (!timer_pending(&PollTimer)) {
+				mod_timer(&PollTimer, POLL_TIMEOUT);
+				printk(KERN_INFO "IP2: polling\n");
+			}
+		} else {
+			if (have_requested_irq(ip2config.irq[i]))
+				continue;
+			rc = request_irq(ip2config.irq[i], ip2_interrupt,
+				IP2_SA_FLAGS |
+				(ip2config.type[i] == PCI ? IRQF_SHARED : 0),
+				pcName, i2BoardPtrTable[i]);
+			if (rc) {
+				printk(KERN_ERR "IP2: request_irq failed: "
+						"error %d\n", rc);
+				ip2config.irq[i] = CIR_POLL;
+				printk(KERN_INFO "IP2: Polling %ld/sec.\n",
+						(POLL_TIMEOUT - jiffies));
+				goto retry;
+			}
+			mark_requested_irq(ip2config.irq[i]);
+			/* Initialise the interrupt handler bottom half
+			 * (aka slih). */
+		}
+	}
+
+	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
+		if (i2BoardPtrTable[i]) {
+			/* set and enable board interrupt */
+			set_irq(i, ip2config.irq[i]);
+		}
+	}
+
+	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
+
+	return 0;
+
+out_chrdev:
+	unregister_chrdev(IP2_IPL_MAJOR, "ip2");
+	/* unregister and put tty here */
+	return err;
+}
+module_init(ip2_loadmain);
+
+/******************************************************************************/
+/* Function:   ip2_init_board()                                               */
+/* Parameters: Index of board in configuration structure                      */
+/* Returns:    Success (0)                                                    */
+/*                                                                            */
+/* Description:                                                               */
+/* This function initializes the specified board. The loadware is copied to   */
+/* the board, the channel structures are initialized, and the board details   */
+/* are reported on the console.                                               */
+/******************************************************************************/
+static void
+ip2_init_board(int boardnum, const struct firmware *fw)
+{
+	int i;
+	int nports = 0, nboxes = 0;
+	i2ChanStrPtr pCh;
+	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
+
+	if ( !iiInitialize ( pB ) ) {
+		printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
+			 pB->i2eBase, pB->i2eError );
+		goto err_initialize;
+	}
+	printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1,
+	       ip2config.addr[boardnum], ip2config.irq[boardnum] );
+
+	if (!request_region( ip2config.addr[boardnum], 8, pcName )) {
+		printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]);
+		goto err_initialize;
+	}
+
+	if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size )
+	    != II_DOWN_GOOD ) {
+		printk ( KERN_ERR "IP2: failed to download loadware\n" );
+		goto err_release_region;
+	} else {
+		printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n",
+			 pB->i2ePom.e.porVersion,
+			 pB->i2ePom.e.porRevision,
+			 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
+			 pB->i2eLRevision, pB->i2eLSub );
+	}
+
+	switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
+
+	default:
+		printk( KERN_ERR "IP2: Unknown board type, ID = %x\n",
+				pB->i2ePom.e.porID );
+		nports = 0;
+		goto err_release_region;
+		break;
+
+	case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
+		printk ( KERN_INFO "IP2: ISA-4\n" );
+		nports = 4;
+		break;
+
+	case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
+		printk ( KERN_INFO "IP2: ISA-8 std\n" );
+		nports = 8;
+		break;
+
+	case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
+		printk ( KERN_INFO "IP2: ISA-8 RJ11\n" );
+		nports = 8;
+		break;
+
+	case POR_ID_FIIEX: /* IntelliPort IIEX */
+	{
+		int portnum = IP2_PORTS_PER_BOARD * boardnum;
+		int            box;
+
+		for( box = 0; box < ABS_MAX_BOXES; ++box ) {
+			if ( pB->i2eChannelMap[box] != 0 ) {
+				++nboxes;
+			}
+			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
+				if ( pB->i2eChannelMap[box] & 1<< i ) {
+					++nports;
+				}
+			}
+		}
+		DevTableMem[boardnum] = pCh =
+			kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
+		if ( !pCh ) {
+			printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
+			goto err_release_region;
+		}
+		if ( !i2InitChannels( pB, nports, pCh ) ) {
+			printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
+			kfree ( pCh );
+			goto err_release_region;
+		}
+		pB->i2eChannelPtr = &DevTable[portnum];
+		pB->i2eChannelCnt = ABS_MOST_PORTS;
+
+		for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
+			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
+				if ( pB->i2eChannelMap[box] & (1 << i) ) {
+					DevTable[portnum + i] = pCh;
+					pCh->port_index = portnum + i;
+					pCh++;
+				}
+			}
+		}
+		printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n",
+			nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
+		}
+		goto ex_exit;
+	}
+	DevTableMem[boardnum] = pCh =
+		kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
+	if ( !pCh ) {
+		printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
+		goto err_release_region;
+	}
+	pB->i2eChannelPtr = pCh;
+	pB->i2eChannelCnt = nports;
+	if ( !i2InitChannels( pB, nports, pCh ) ) {
+		printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
+		kfree ( pCh );
+		goto err_release_region;
+	}
+	pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
+
+	for( i = 0; i < pB->i2eChannelCnt; ++i ) {
+		DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
+		pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
+		pCh++;
+	}
+ex_exit:
+	INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
+	return;
+
+err_release_region:
+	release_region(ip2config.addr[boardnum], 8);
+err_initialize:
+	kfree ( pB );
+	i2BoardPtrTable[boardnum] = NULL;
+	return;
+}
+
+/******************************************************************************/
+/* Function:   find_eisa_board ( int start_slot )                             */
+/* Parameters: First slot to check                                            */
+/* Returns:    Address of EISA IntelliPort II controller                      */
+/*                                                                            */
+/* Description:                                                               */
+/* This function searches for an EISA IntelliPort controller, starting        */
+/* from the specified slot number. If the motherboard is not identified as an */
+/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
+/* it returns the base address of the controller.                             */
+/******************************************************************************/
+static unsigned short
+find_eisa_board( int start_slot )
+{
+	int i, j;
+	unsigned int idm = 0;
+	unsigned int idp = 0;
+	unsigned int base = 0;
+	unsigned int value;
+	int setup_address;
+	int setup_irq;
+	int ismine = 0;
+
+	/*
+	 * First a check for an EISA motherboard, which we do by comparing the
+	 * EISA ID registers for the system board and the first couple of slots.
+	 * No slot ID should match the system board ID, but on an ISA or PCI
+	 * machine the odds are that an empty bus will return similar values for
+	 * each slot.
+	 */
+	i = 0x0c80;
+	value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
+	for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
+		j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
+		if ( value == j )
+			return 0;
+	}
+
+	/*
+	 * OK, so we are inclined to believe that this is an EISA machine. Find
+	 * an IntelliPort controller.
+	 */
+	for( i = start_slot; i < 16; i++ ) {
+		base = i << 12;
+		idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
+		idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
+		ismine = 0;
+		if ( idm == 0x0e8e ) {
+			if ( idp == 0x0281 || idp == 0x0218 ) {
+				ismine = 1;
+			} else if ( idp == 0x0282 || idp == 0x0283 ) {
+				ismine = 3;	/* Can do edge-trigger */
+			}
+			if ( ismine ) {
+				Eisa_slot = i;
+				break;
+			}
+		}
+	}
+	if ( !ismine )
+		return 0;
+
+	/* It's some sort of EISA card, but at what address is it configured? */
+
+	setup_address = base + 0xc88;
+	value = inb(base + 0xc86);
+	setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
+
+	if ( (ismine & 2) && !(value & 0x10) ) {
+		ismine = 1;	/* Could be edging, but not */
+	}
+
+	if ( Eisa_irq == 0 ) {
+		Eisa_irq = setup_irq;
+	} else if ( Eisa_irq != setup_irq ) {
+		printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
+	}
+
+#ifdef IP2DEBUG_INIT
+printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
+	       base >> 12, idm, idp, setup_address);
+	if ( Eisa_irq ) {
+		printk(KERN_DEBUG ", Interrupt %d %s\n",
+		       setup_irq, (ismine & 2) ? "(edge)" : "(level)");
+	} else {
+		printk(KERN_DEBUG ", (polled)\n");
+	}
+#endif
+	return setup_address;
+}
+
+/******************************************************************************/
+/* Function:   set_irq()                                                      */
+/* Parameters: index to board in board table                                  */
+/*             IRQ to use                                                     */
+/* Returns:    Success (0)                                                    */
+/*                                                                            */
+/* Description:                                                               */
+/******************************************************************************/
+static void
+set_irq( int boardnum, int boardIrq )
+{
+	unsigned char tempCommand[16];
+	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
+	unsigned long flags;
+
+	/*
+	 * Notify the boards they may generate interrupts. This is done by
+	 * sending an in-line command to channel 0 on each board. This is why
+	 * the channels have to be defined already. For each board, if the
+	 * interrupt has never been defined, we must do so NOW, directly, since
+	 * board will not send flow control or even give an interrupt until this
+	 * is done.  If polling we must send 0 as the interrupt parameter.
+	 */
+
+	// We will get an interrupt here at the end of this function
+
+	iiDisableMailIrq(pB);
+
+	/* We build up the entire packet header. */
+	CHANNEL_OF(tempCommand) = 0;
+	PTYPE_OF(tempCommand) = PTYPE_INLINE;
+	CMD_COUNT_OF(tempCommand) = 2;
+	(CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
+	(CMD_OF(tempCommand))[1] = boardIrq;
+	/*
+	 * Write to FIFO; don't bother to adjust fifo capacity for this, since
+	 * board will respond almost immediately after SendMail hit.
+	 */
+	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
+	iiWriteBuf(pB, tempCommand, 4);
+	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
+	pB->i2eUsingIrq = boardIrq;
+	pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
+
+	/* Need to update number of boards before you enable mailbox int */
+	++i2nBoards;
+
+	CHANNEL_OF(tempCommand) = 0;
+	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
+	CMD_COUNT_OF(tempCommand) = 6;
+	(CMD_OF(tempCommand))[0] = 88;	// SILO
+	(CMD_OF(tempCommand))[1] = 64;	// chars
+	(CMD_OF(tempCommand))[2] = 32;	// ms
+
+	(CMD_OF(tempCommand))[3] = 28;	// MAX_BLOCK
+	(CMD_OF(tempCommand))[4] = 64;	// chars
+
+	(CMD_OF(tempCommand))[5] = 87;	// HW_TEST
+	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
+	iiWriteBuf(pB, tempCommand, 8);
+	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
+
+	CHANNEL_OF(tempCommand) = 0;
+	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
+	CMD_COUNT_OF(tempCommand) = 1;
+	(CMD_OF(tempCommand))[0] = 84;	/* get BOX_IDS */
+	iiWriteBuf(pB, tempCommand, 3);
+
+#ifdef XXX
+	// enable heartbeat for test porpoises
+	CHANNEL_OF(tempCommand) = 0;
+	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
+	CMD_COUNT_OF(tempCommand) = 2;
+	(CMD_OF(tempCommand))[0] = 44;	/* get ping */
+	(CMD_OF(tempCommand))[1] = 200;	/* 200 ms */
+	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
+	iiWriteBuf(pB, tempCommand, 4);
+	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
+#endif
+
+	iiEnableMailIrq(pB);
+	iiSendPendingMail(pB);
+}
+
+/******************************************************************************/
+/* Interrupt Handler Section                                                  */
+/******************************************************************************/
+
+static inline void
+service_all_boards(void)
+{
+	int i;
+	i2eBordStrPtr  pB;
+
+	/* Service every board on the list */
+	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+		pB = i2BoardPtrTable[i];
+		if ( pB ) {
+			i2ServiceBoard( pB );
+		}
+	}
+}
+
+
+/******************************************************************************/
+/* Function:   ip2_interrupt_bh(work)                                         */
+/* Parameters: work - pointer to the board structure                          */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*	Service the board in a bottom half interrupt handler and then         */
+/*	reenable the board's interrupts if it has an IRQ number               */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_interrupt_bh(struct work_struct *work)
+{
+	i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
+//	pB better well be set or we have a problem!  We can only get
+//	here from the IMMEDIATE queue.  Here, we process the boards.
+//	Checking pB doesn't cost much and it saves us from the sanity checkers.
+
+	bh_counter++; 
+
+	if ( pB ) {
+		i2ServiceBoard( pB );
+		if( pB->i2eUsingIrq ) {
+//			Re-enable his interrupts
+			iiEnableMailIrq(pB);
+		}
+	}
+}
+
+
+/******************************************************************************/
+/* Function:   ip2_interrupt(int irq, void *dev_id)    */
+/* Parameters: irq - interrupt number                                         */
+/*             pointer to optional device ID structure                        */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*	Our task here is simply to identify each board which needs servicing. */
+/*	If we are queuing then, queue it to be serviced, and disable its irq  */
+/*	mask otherwise process the board directly.                            */
+/*                                                                            */
+/*	We could queue by IRQ but that just complicates things on both ends   */
+/*	with very little gain in performance (how many instructions does      */
+/*	it take to iterate on the immediate queue).                           */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_irq_work(i2eBordStrPtr pB)
+{
+#ifdef USE_IQI
+	if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
+//		Disable his interrupt (will be enabled when serviced)
+//		This is mostly to protect from reentrancy.
+		iiDisableMailIrq(pB);
+
+//		Park the board on the immediate queue for processing.
+		schedule_work(&pB->tqueue_interrupt);
+
+//		Make sure the immediate queue is flagged to fire.
+	}
+#else
+
+//	We are using immediate servicing here.  This sucks and can
+//	cause all sorts of havoc with ppp and others.  The failsafe
+//	check on iiSendPendingMail could also throw a hairball.
+
+	i2ServiceBoard( pB );
+
+#endif /* USE_IQI */
+}
+
+static void
+ip2_polled_interrupt(void)
+{
+	int i;
+	i2eBordStrPtr  pB;
+
+	ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
+
+	/* Service just the boards on the list using this irq */
+	for( i = 0; i < i2nBoards; ++i ) {
+		pB = i2BoardPtrTable[i];
+
+//		Only process those boards which match our IRQ.
+//			IRQ = 0 for polled boards, we won't poll "IRQ" boards
+
+		if (pB && pB->i2eUsingIrq == 0)
+			ip2_irq_work(pB);
+	}
+
+	++irq_counter;
+
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
+}
+
+static irqreturn_t
+ip2_interrupt(int irq, void *dev_id)
+{
+	i2eBordStrPtr pB = dev_id;
+
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
+
+	ip2_irq_work(pB);
+
+	++irq_counter;
+
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************/
+/* Function:   ip2_poll(unsigned long arg)                                    */
+/* Parameters: ?                                                              */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/* This function calls the library routine i2ServiceBoard for each board in   */
+/* the board table. This is used instead of the interrupt routine when polled */
+/* mode is specified.                                                         */
+/******************************************************************************/
+static void
+ip2_poll(unsigned long arg)
+{
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
+
+	// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
+	// It will NOT poll boards handled by hard interrupts.
+	// The issue of queued BH interrupts is handled in ip2_interrupt().
+	ip2_polled_interrupt();
+
+	mod_timer(&PollTimer, POLL_TIMEOUT);
+
+	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
+}
+
+static void do_input(struct work_struct *work)
+{
+	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
+	unsigned long flags;
+
+	ip2trace(CHANN, ITRC_INPUT, 21, 0 );
+
+	// Data input
+	if ( pCh->pTTY != NULL ) {
+		read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
+		if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
+			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+			i2Input( pCh );
+		} else
+			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+	} else {
+		ip2trace(CHANN, ITRC_INPUT, 22, 0 );
+
+		i2InputFlush( pCh );
+	}
+}
+
+// code duplicated from n_tty (ldisc)
+static inline void  isig(int sig, struct tty_struct *tty, int flush)
+{
+	/* FIXME: This is completely bogus */
+	if (tty->pgrp)
+		kill_pgrp(tty->pgrp, sig, 1);
+	if (flush || !L_NOFLSH(tty)) {
+		if ( tty->ldisc->ops->flush_buffer )  
+			tty->ldisc->ops->flush_buffer(tty);
+		i2InputFlush( tty->driver_data );
+	}
+}
+
+static void do_status(struct work_struct *work)
+{
+	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
+	int status;
+
+	status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
+
+	ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
+
+	if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
+		if ( (status & I2_BRK) ) {
+			// code duplicated from n_tty (ldisc)
+			if (I_IGNBRK(pCh->pTTY))
+				goto skip_this;
+			if (I_BRKINT(pCh->pTTY)) {
+				isig(SIGINT, pCh->pTTY, 1);
+				goto skip_this;
+			}
+			wake_up_interruptible(&pCh->pTTY->read_wait);
+		}
+#ifdef NEVER_HAPPENS_AS_SETUP_XXX
+	// and can't work because we don't know the_char
+	// as the_char is reported on a separate path
+	// The intelligent board does this stuff as setup
+	{
+	char brkf = TTY_NORMAL;
+	unsigned char brkc = '\0';
+	unsigned char tmp;
+		if ( (status & I2_BRK) ) {
+			brkf = TTY_BREAK;
+			brkc = '\0';
+		} 
+		else if (status & I2_PAR) {
+			brkf = TTY_PARITY;
+			brkc = the_char;
+		} else if (status & I2_FRA) {
+			brkf = TTY_FRAME;
+			brkc = the_char;
+		} else if (status & I2_OVR) {
+			brkf = TTY_OVERRUN;
+			brkc = the_char;
+		}
+		tmp = pCh->pTTY->real_raw;
+		pCh->pTTY->real_raw = 0;
+		pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
+		pCh->pTTY->real_raw = tmp;
+	}
+#endif /* NEVER_HAPPENS_AS_SETUP_XXX */
+	}
+skip_this:
+
+	if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
+		wake_up_interruptible(&pCh->delta_msr_wait);
+
+		if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
+			if ( status & I2_DCD ) {
+				if ( pCh->wopen ) {
+					wake_up_interruptible ( &pCh->open_wait );
+				}
+			} else {
+				if (pCh->pTTY &&  (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
+					tty_hangup( pCh->pTTY );
+				}
+			}
+		}
+	}
+
+	ip2trace (CHANN, ITRC_STATUS, 26, 0 );
+}
+
+/******************************************************************************/
+/* Device Open/Close/Ioctl Entry Point Section                                */
+/******************************************************************************/
+
+/******************************************************************************/
+/* Function:   open_sanity_check()                                            */
+/* Parameters: Pointer to tty structure                                       */
+/*             Pointer to file structure                                      */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description:                                                               */
+/* Verifies the structure magic numbers and cross links.                      */
+/******************************************************************************/
+#ifdef IP2DEBUG_OPEN
+static void 
+open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
+{
+	if ( pBrd->i2eValid != I2E_MAGIC ) {
+		printk(KERN_ERR "IP2: invalid board structure\n" );
+	} else if ( pBrd != pCh->pMyBord ) {
+		printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
+			 pCh->pMyBord );
+	} else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
+		printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
+	} else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
+	} else {
+		printk(KERN_INFO "IP2: all pointers check out!\n" );
+	}
+}
+#endif
+
+
+/******************************************************************************/
+/* Function:   ip2_open()                                                     */
+/* Parameters: Pointer to tty structure                                       */
+/*             Pointer to file structure                                      */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description: (MANDATORY)                                                   */
+/* A successful device open has to run a gauntlet of checks before it         */
+/* completes. After some sanity checking and pointer setup, the function      */
+/* blocks until all conditions are satisfied. It then initialises the port to */
+/* the default characteristics and returns.                                   */
+/******************************************************************************/
+static int
+ip2_open( PTTY tty, struct file *pFile )
+{
+	wait_queue_t wait;
+	int rc = 0;
+	int do_clocal = 0;
+	i2ChanStrPtr  pCh = DevTable[tty->index];
+
+	ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 );
+
+	if ( pCh == NULL ) {
+		return -ENODEV;
+	}
+	/* Setup pointer links in device and tty structures */
+	pCh->pTTY = tty;
+	tty->driver_data = pCh;
+
+#ifdef IP2DEBUG_OPEN
+	printk(KERN_DEBUG \
+			"IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n",
+	       tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index);
+	open_sanity_check ( pCh, pCh->pMyBord );
+#endif
+
+	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
+	pCh->dataSetOut |= (I2_DTR | I2_RTS);
+	serviceOutgoingFifo( pCh->pMyBord );
+
+	/* Block here until the port is ready (per serial and istallion) */
+	/*
+	 * 1. If the port is in the middle of closing wait for the completion
+	 *    and then return the appropriate error.
+	 */
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&pCh->close_wait, &wait);
+	set_current_state( TASK_INTERRUPTIBLE );
+
+	if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
+		if ( pCh->flags & ASYNC_CLOSING ) {
+			tty_unlock();
+			schedule();
+			tty_lock();
+		}
+		if ( tty_hung_up_p(pFile) ) {
+			set_current_state( TASK_RUNNING );
+			remove_wait_queue(&pCh->close_wait, &wait);
+			return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
+		}
+	}
+	set_current_state( TASK_RUNNING );
+	remove_wait_queue(&pCh->close_wait, &wait);
+
+	/*
+	 * 3. Handle a non-blocking open of a normal port.
+	 */
+	if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
+		pCh->flags |= ASYNC_NORMAL_ACTIVE;
+		goto noblock;
+	}
+	/*
+	 * 4. Now loop waiting for the port to be free and carrier present
+	 *    (if required).
+	 */
+	if ( tty->termios->c_cflag & CLOCAL )
+		do_clocal = 1;
+
+#ifdef IP2DEBUG_OPEN
+	printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
+#endif
+
+	++pCh->wopen;
+
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&pCh->open_wait, &wait);
+
+	for(;;) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
+		pCh->dataSetOut |= (I2_DTR | I2_RTS);
+		set_current_state( TASK_INTERRUPTIBLE );
+		serviceOutgoingFifo( pCh->pMyBord );
+		if ( tty_hung_up_p(pFile) ) {
+			set_current_state( TASK_RUNNING );
+			remove_wait_queue(&pCh->open_wait, &wait);
+			return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
+		}
+		if (!(pCh->flags & ASYNC_CLOSING) && 
+				(do_clocal || (pCh->dataSetIn & I2_DCD) )) {
+			rc = 0;
+			break;
+		}
+
+#ifdef IP2DEBUG_OPEN
+		printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
+			(pCh->flags & ASYNC_CLOSING)?"True":"False");
+		printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
+#endif
+		ip2trace (CHANN, ITRC_OPEN, 3, 2, 0,
+				(pCh->flags & ASYNC_CLOSING) );
+		/* check for signal */
+		if (signal_pending(current)) {
+			rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
+			break;
+		}
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+	set_current_state( TASK_RUNNING );
+	remove_wait_queue(&pCh->open_wait, &wait);
+
+	--pCh->wopen; //why count?
+
+	ip2trace (CHANN, ITRC_OPEN, 4, 0 );
+
+	if (rc != 0 ) {
+		return rc;
+	}
+	pCh->flags |= ASYNC_NORMAL_ACTIVE;
+
+noblock:
+
+	/* first open - Assign termios structure to port */
+	if ( tty->count == 1 ) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
+		/* Now we must send the termios settings to the loadware */
+		set_params( pCh, NULL );
+	}
+
+	/*
+	 * Now set any i2lib options. These may go away if the i2lib code ends
+	 * up rolled into the mainline.
+	 */
+	pCh->channelOptions |= CO_NBLOCK_WRITE;
+
+#ifdef IP2DEBUG_OPEN
+	printk (KERN_DEBUG "IP2: open completed\n" );
+#endif
+	serviceOutgoingFifo( pCh->pMyBord );
+
+	ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
+
+	return 0;
+}
+
+/******************************************************************************/
+/* Function:   ip2_close()                                                    */
+/* Parameters: Pointer to tty structure                                       */
+/*             Pointer to file structure                                      */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_close( PTTY tty, struct file *pFile )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+
+	if ( !pCh ) {
+		return;
+	}
+
+	ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
+
+#ifdef IP2DEBUG_OPEN
+	printk(KERN_DEBUG "IP2:close %s:\n",tty->name);
+#endif
+
+	if ( tty_hung_up_p ( pFile ) ) {
+
+		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
+
+		return;
+	}
+	if ( tty->count > 1 ) { /* not the last close */
+
+		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
+
+		return;
+	}
+	pCh->flags |= ASYNC_CLOSING;	// last close actually
+
+	tty->closing = 1;
+
+	if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
+		/*
+		 * Before we drop DTR, make sure the transmitter has completely drained.
+		 * This uses an timeout, after which the close
+		 * completes.
+		 */
+		ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
+	}
+	/*
+	 * At this point we stop accepting input. Here we flush the channel
+	 * input buffer which will allow the board to send up more data. Any
+	 * additional input is tossed at interrupt/poll time.
+	 */
+	i2InputFlush( pCh );
+
+	/* disable DSS reporting */
+	i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
+				CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
+	if (tty->termios->c_cflag & HUPCL) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
+		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
+		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
+	}
+
+	serviceOutgoingFifo ( pCh->pMyBord );
+
+	tty_ldisc_flush(tty);
+	tty_driver_flush_buffer(tty);
+	tty->closing = 0;
+	
+	pCh->pTTY = NULL;
+
+	if (pCh->wopen) {
+		if (pCh->ClosingDelay) {
+			msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay));
+		}
+		wake_up_interruptible(&pCh->open_wait);
+	}
+
+	pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+	wake_up_interruptible(&pCh->close_wait);
+
+#ifdef IP2DEBUG_OPEN
+	DBG_CNT("ip2_close: after wakeups--");
+#endif
+
+
+	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
+
+	return;
+}
+
+/******************************************************************************/
+/* Function:   ip2_hangup()                                                   */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_hangup ( PTTY tty )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+
+	if( !pCh ) {
+		return;
+	}
+
+	ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
+
+	ip2_flush_buffer(tty);
+
+	/* disable DSS reporting */
+
+	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
+	i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
+	if ( (tty->termios->c_cflag & HUPCL) ) {
+		i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
+		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
+		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
+	}
+	i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, 
+				CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
+	serviceOutgoingFifo ( pCh->pMyBord );
+
+	wake_up_interruptible ( &pCh->delta_msr_wait );
+
+	pCh->flags &= ~ASYNC_NORMAL_ACTIVE;
+	pCh->pTTY = NULL;
+	wake_up_interruptible ( &pCh->open_wait );
+
+	ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/* Device Output Section                                                      */
+/******************************************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/* Function:   ip2_write()                                                    */
+/* Parameters: Pointer to tty structure                                       */
+/*             Flag denoting data is in user (1) or kernel (0) space          */
+/*             Pointer to data                                                */
+/*             Number of bytes to write                                       */
+/* Returns:    Number of bytes actually written                               */
+/*                                                                            */
+/* Description: (MANDATORY)                                                   */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static int
+ip2_write( PTTY tty, const unsigned char *pData, int count)
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+	int bytesSent = 0;
+	unsigned long flags;
+
+	ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
+
+	/* Flush out any buffered data left over from ip2_putchar() calls. */
+	ip2_flush_chars( tty );
+
+	/* This is the actual move bit. Make sure it does what we need!!!!! */
+	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
+	bytesSent = i2Output( pCh, pData, count);
+	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+
+	ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
+
+	return bytesSent > 0 ? bytesSent : 0;
+}
+
+/******************************************************************************/
+/* Function:   ip2_putchar()                                                  */
+/* Parameters: Pointer to tty structure                                       */
+/*             Character to write                                             */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static int
+ip2_putchar( PTTY tty, unsigned char ch )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+	unsigned long flags;
+
+//	ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
+
+	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
+	pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
+	if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
+		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+		ip2_flush_chars( tty );
+	} else
+		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+	return 1;
+
+//	ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
+}
+
+/******************************************************************************/
+/* Function:   ip2_flush_chars()                                              */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_flush_chars( PTTY tty )
+{
+	int   strip;
+	i2ChanStrPtr  pCh = tty->driver_data;
+	unsigned long flags;
+
+	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
+	if ( pCh->Pbuf_stuff ) {
+
+//		ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
+
+		//
+		// We may need to restart i2Output if it does not fullfill this request
+		//
+		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
+		if ( strip != pCh->Pbuf_stuff ) {
+			memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
+		}
+		pCh->Pbuf_stuff -= strip;
+	}
+	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+}
+
+/******************************************************************************/
+/* Function:   ip2_write_room()                                               */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Number of bytes that the driver can accept                     */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/******************************************************************************/
+static int
+ip2_write_room ( PTTY tty )
+{
+	int bytesFree;
+	i2ChanStrPtr  pCh = tty->driver_data;
+	unsigned long flags;
+
+	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
+	bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
+	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+
+	ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
+
+	return ((bytesFree > 0) ? bytesFree : 0);
+}
+
+/******************************************************************************/
+/* Function:   ip2_chars_in_buf()                                             */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Number of bytes queued for transmission                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static int
+ip2_chars_in_buf ( PTTY tty )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+	int rc;
+	unsigned long flags;
+
+	ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
+
+#ifdef IP2DEBUG_WRITE
+	printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
+				 pCh->Obuf_char_count + pCh->Pbuf_stuff,
+				 pCh->Obuf_char_count, pCh->Pbuf_stuff );
+#endif
+	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
+	rc =  pCh->Obuf_char_count;
+	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
+	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
+	rc +=  pCh->Pbuf_stuff;
+	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+	return rc;
+}
+
+/******************************************************************************/
+/* Function:   ip2_flush_buffer()                                             */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_flush_buffer( PTTY tty )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+	unsigned long flags;
+
+	ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
+
+#ifdef IP2DEBUG_WRITE
+	printk (KERN_DEBUG "IP2: flush buffer\n" );
+#endif
+	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
+	pCh->Pbuf_stuff = 0;
+	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
+	i2FlushOutput( pCh );
+	ip2_owake(tty);
+
+	ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
+
+}
+
+/******************************************************************************/
+/* Function:   ip2_wait_until_sent()                                          */
+/* Parameters: Pointer to tty structure                                       */
+/*             Timeout for wait.                                              */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/* This function is used in place of the normal tty_wait_until_sent, which    */
+/* only waits for the driver buffers to be empty (or rather, those buffers    */
+/* reported by chars_in_buffer) which doesn't work for IP2 due to the         */
+/* indeterminate number of bytes buffered on the board.                       */
+/******************************************************************************/
+static void
+ip2_wait_until_sent ( PTTY tty, int timeout )
+{
+	int i = jiffies;
+	i2ChanStrPtr  pCh = tty->driver_data;
+
+	tty_wait_until_sent(tty, timeout );
+	if ( (i = timeout - (jiffies -i)) > 0)
+		i2DrainOutput( pCh, i );
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/* Device Input Section                                                       */
+/******************************************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/* Function:   ip2_throttle()                                                 */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_throttle ( PTTY tty )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+
+#ifdef IP2DEBUG_READ
+	printk (KERN_DEBUG "IP2: throttle\n" );
+#endif
+	/*
+	 * Signal the poll/interrupt handlers not to forward incoming data to
+	 * the line discipline. This will cause the buffers to fill up in the
+	 * library and thus cause the library routines to send the flow control
+	 * stuff.
+	 */
+	pCh->throttled = 1;
+}
+
+/******************************************************************************/
+/* Function:   ip2_unthrottle()                                               */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_unthrottle ( PTTY tty )
+{
+	i2ChanStrPtr  pCh = tty->driver_data;
+	unsigned long flags;
+
+#ifdef IP2DEBUG_READ
+	printk (KERN_DEBUG "IP2: unthrottle\n" );
+#endif
+
+	/* Pass incoming data up to the line discipline again. */
+	pCh->throttled = 0;
+ 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
+	serviceOutgoingFifo( pCh->pMyBord );
+	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
+	if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
+		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+#ifdef IP2DEBUG_READ
+		printk (KERN_DEBUG "i2Input called from unthrottle\n" );
+#endif
+		i2Input( pCh );
+	} else
+		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
+}
+
+static void
+ip2_start ( PTTY tty )
+{
+ 	i2ChanStrPtr  pCh = DevTable[tty->index];
+
+ 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
+ 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
+ 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
+#ifdef IP2DEBUG_WRITE
+	printk (KERN_DEBUG "IP2: start tx\n" );
+#endif
+}
+
+static void
+ip2_stop ( PTTY tty )
+{
+ 	i2ChanStrPtr  pCh = DevTable[tty->index];
+
+ 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
+#ifdef IP2DEBUG_WRITE
+	printk (KERN_DEBUG "IP2: stop tx\n" );
+#endif
+}
+
+/******************************************************************************/
+/* Device Ioctl Section                                                       */
+/******************************************************************************/
+
+static int ip2_tiocmget(struct tty_struct *tty)
+{
+	i2ChanStrPtr pCh = DevTable[tty->index];
+#ifdef	ENABLE_DSSNOW
+	wait_queue_t wait;
+#endif
+
+	if (pCh == NULL)
+		return -ENODEV;
+
+/*
+	FIXME - the following code is causing a NULL pointer dereference in
+	2.3.51 in an interrupt handler.  It's suppose to prompt the board
+	to return the DSS signal status immediately.  Why doesn't it do
+	the same thing in 2.2.14?
+*/
+
+/*	This thing is still busted in the 1.2.12 driver on 2.4.x
+	and even hoses the serial console so the oops can be trapped.
+		/\/\|=mhw=|\/\/			*/
+
+#ifdef	ENABLE_DSSNOW
+	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
+
+	init_waitqueue_entry(&wait, current);
+	add_wait_queue(&pCh->dss_now_wait, &wait);
+	set_current_state( TASK_INTERRUPTIBLE );
+
+	serviceOutgoingFifo( pCh->pMyBord );
+
+	schedule();
+
+	set_current_state( TASK_RUNNING );
+	remove_wait_queue(&pCh->dss_now_wait, &wait);
+
+	if (signal_pending(current)) {
+		return -EINTR;
+	}
+#endif
+	return  ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
+	      | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
+	      | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
+	      | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
+	      | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
+	      | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0);
+}
+
+static int ip2_tiocmset(struct tty_struct *tty,
+			unsigned int set, unsigned int clear)
+{
+	i2ChanStrPtr pCh = DevTable[tty->index];
+
+	if (pCh == NULL)
+		return -ENODEV;
+
+	if (set & TIOCM_RTS) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
+		pCh->dataSetOut |= I2_RTS;
+	}
+	if (set & TIOCM_DTR) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
+		pCh->dataSetOut |= I2_DTR;
+	}
+
+	if (clear & TIOCM_RTS) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
+		pCh->dataSetOut &= ~I2_RTS;
+	}
+	if (clear & TIOCM_DTR) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
+		pCh->dataSetOut &= ~I2_DTR;
+	}
+	serviceOutgoingFifo( pCh->pMyBord );
+	return 0;
+}
+
+/******************************************************************************/
+/* Function:   ip2_ioctl()                                                    */
+/* Parameters: Pointer to tty structure                                       */
+/*             Pointer to file structure                                      */
+/*             Command                                                        */
+/*             Argument                                                       */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static int
+ip2_ioctl ( PTTY tty, UINT cmd, ULONG arg )
+{
+	wait_queue_t wait;
+	i2ChanStrPtr pCh = DevTable[tty->index];
+	i2eBordStrPtr pB;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	int rc = 0;
+	unsigned long flags;
+	void __user *argp = (void __user *)arg;
+
+	if ( pCh == NULL )
+		return -ENODEV;
+
+	pB = pCh->pMyBord;
+
+	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
+
+#ifdef IP2DEBUG_IOCTL
+	printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
+#endif
+
+	switch(cmd) {
+	case TIOCGSERIAL:
+
+		ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
+
+		rc = get_serial_info(pCh, argp);
+		if (rc)
+			return rc;
+		break;
+
+	case TIOCSSERIAL:
+
+		ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
+
+		rc = set_serial_info(pCh, argp);
+		if (rc)
+			return rc;
+		break;
+
+	case TCXONC:
+		rc = tty_check_change(tty);
+		if (rc)
+			return rc;
+		switch (arg) {
+		case TCOOFF:
+			//return  -ENOIOCTLCMD;
+			break;
+		case TCOON:
+			//return  -ENOIOCTLCMD;
+			break;
+		case TCIOFF:
+			if (STOP_CHAR(tty) != __DISABLED_CHAR) {
+				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
+						CMD_XMIT_NOW(STOP_CHAR(tty)));
+			}
+			break;
+		case TCION:
+			if (START_CHAR(tty) != __DISABLED_CHAR) {
+				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
+						CMD_XMIT_NOW(START_CHAR(tty)));
+			}
+			break;
+		default:
+			return -EINVAL;
+		}
+		return 0;
+
+	case TCSBRK:   /* SVID version: non-zero arg --> no break */
+		rc = tty_check_change(tty);
+
+		ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
+
+		if (!rc) {
+			ip2_wait_until_sent(tty,0);
+			if (!arg) {
+				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
+				serviceOutgoingFifo( pCh->pMyBord );
+			}
+		}
+		break;
+
+	case TCSBRKP:  /* support for POSIX tcsendbreak() */
+		rc = tty_check_change(tty);
+
+		ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
+
+		if (!rc) {
+			ip2_wait_until_sent(tty,0);
+			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
+				CMD_SEND_BRK(arg ? arg*100 : 250));
+			serviceOutgoingFifo ( pCh->pMyBord );	
+		}
+		break;
+
+	case TIOCGSOFTCAR:
+
+		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
+
+			rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
+		if (rc)	
+			return rc;
+	break;
+
+	case TIOCSSOFTCAR:
+
+		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
+
+		rc = get_user(arg,(unsigned long __user *) argp);
+		if (rc) 
+			return rc;
+		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
+					 | (arg ? CLOCAL : 0));
+		
+		break;
+
+	/*
+	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
+	 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
+	 * for masking). Caller should use TIOCGICOUNT to see which one it was
+	 */
+	case TIOCMIWAIT:
+		write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+		cprev = pCh->icount;	 /* note the counters on entry */
+		write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
+						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
+		init_waitqueue_entry(&wait, current);
+		add_wait_queue(&pCh->delta_msr_wait, &wait);
+		set_current_state( TASK_INTERRUPTIBLE );
+
+		serviceOutgoingFifo( pCh->pMyBord );
+		for(;;) {
+			ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
+
+			schedule();
+
+			ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
+
+			/* see if a signal did it */
+			if (signal_pending(current)) {
+				rc = -ERESTARTSYS;
+				break;
+			}
+			write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+			cnow = pCh->icount; /* atomic copy */
+			write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+				rc =  -EIO; /* no change => rc */
+				break;
+			}
+			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+				rc =  0;
+				break;
+			}
+			cprev = cnow;
+		}
+		set_current_state( TASK_RUNNING );
+		remove_wait_queue(&pCh->delta_msr_wait, &wait);
+
+		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
+						 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
+		if ( ! (pCh->flags	& ASYNC_CHECK_CD)) {
+			i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
+		}
+		serviceOutgoingFifo( pCh->pMyBord );
+		return rc;
+		break;
+
+	/*
+	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
+	 * will be passed to the line discipline for it to handle.
+	 */
+	case TIOCSERCONFIG:
+	case TIOCSERGWILD:
+	case TIOCSERGETLSR:
+	case TIOCSERSWILD:
+	case TIOCSERGSTRUCT:
+	case TIOCSERGETMULTI:
+	case TIOCSERSETMULTI:
+
+	default:
+		ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
+
+		rc =  -ENOIOCTLCMD;
+		break;
+	}
+
+	ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
+
+	return rc;
+}
+
+static int ip2_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount)
+{
+	i2ChanStrPtr pCh = DevTable[tty->index];
+	i2eBordStrPtr pB;
+	struct async_icount cnow;	/* kernel counter temp */
+	unsigned long flags;
+
+	if ( pCh == NULL )
+		return -ENODEV;
+
+	pB = pCh->pMyBord;
+
+	/*
+	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+	 * Return: write counters to the user passed counter struct
+	 * NB: both 1->0 and 0->1 transitions are counted except for RI where
+	 * only 0->1 is counted. The controller is quite capable of counting
+	 * both, but this done to preserve compatibility with the standard
+	 * serial driver.
+	 */
+
+	write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+	cnow = pCh->icount;
+	write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
+/******************************************************************************/
+/* Function:   GetSerialInfo()                                                */
+/* Parameters: Pointer to channel structure                                   */
+/*             Pointer to old termios structure                               */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/* This is to support the setserial command, and requires processing of the   */
+/* standard Linux serial structure.                                           */
+/******************************************************************************/
+static int
+get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo )
+{
+	struct serial_struct tmp;
+
+	memset ( &tmp, 0, sizeof(tmp) );
+	tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
+	if (BID_HAS_654(tmp.type)) {
+		tmp.type = PORT_16650;
+	} else {
+		tmp.type = PORT_CIRRUS;
+	}
+	tmp.line = pCh->port_index;
+	tmp.port = pCh->pMyBord->i2eBase;
+	tmp.irq  = ip2config.irq[pCh->port_index/64];
+	tmp.flags = pCh->flags;
+	tmp.baud_base = pCh->BaudBase;
+	tmp.close_delay = pCh->ClosingDelay;
+	tmp.closing_wait = pCh->ClosingWaitTime;
+	tmp.custom_divisor = pCh->BaudDivisor;
+   	return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
+}
+
+/******************************************************************************/
+/* Function:   SetSerialInfo()                                                */
+/* Parameters: Pointer to channel structure                                   */
+/*             Pointer to old termios structure                               */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/* This function provides support for setserial, which uses the TIOCSSERIAL   */
+/* ioctl. Not all setserial parameters are relevant. If the user attempts to  */
+/* change the IRQ, address or type of the port the ioctl fails.               */
+/******************************************************************************/
+static int
+set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
+{
+	struct serial_struct ns;
+	int   old_flags, old_baud_divisor;
+
+	if (copy_from_user(&ns, new_info, sizeof (ns)))
+		return -EFAULT;
+
+	/*
+	 * We don't allow setserial to change IRQ, board address, type or baud
+	 * base. Also line nunber as such is meaningless but we use it for our
+	 * array index so it is fixed also.
+	 */
+	if ( (ns.irq  	    != ip2config.irq[pCh->port_index])
+	    || ((int) ns.port      != ((int) (pCh->pMyBord->i2eBase)))
+	    || (ns.baud_base != pCh->BaudBase)
+	    || (ns.line      != pCh->port_index) ) {
+		return -EINVAL;
+	}
+
+	old_flags = pCh->flags;
+	old_baud_divisor = pCh->BaudDivisor;
+
+	if ( !capable(CAP_SYS_ADMIN) ) {
+		if ( ( ns.close_delay != pCh->ClosingDelay ) ||
+		    ( (ns.flags & ~ASYNC_USR_MASK) !=
+		      (pCh->flags & ~ASYNC_USR_MASK) ) ) {
+			return -EPERM;
+		}
+
+		pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
+			       (ns.flags & ASYNC_USR_MASK);
+		pCh->BaudDivisor = ns.custom_divisor;
+	} else {
+		pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
+			       (ns.flags & ASYNC_FLAGS);
+		pCh->BaudDivisor = ns.custom_divisor;
+		pCh->ClosingDelay = ns.close_delay * HZ/100;
+		pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
+	}
+
+	if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
+	    || (old_baud_divisor != pCh->BaudDivisor) ) {
+		// Invalidate speed and reset parameters
+		set_params( pCh, NULL );
+	}
+
+	return 0;
+}
+
+/******************************************************************************/
+/* Function:   ip2_set_termios()                                              */
+/* Parameters: Pointer to tty structure                                       */
+/*             Pointer to old termios structure                               */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_set_termios( PTTY tty, struct ktermios *old_termios )
+{
+	i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
+
+#ifdef IP2DEBUG_IOCTL
+	printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
+#endif
+
+	set_params( pCh, old_termios );
+}
+
+/******************************************************************************/
+/* Function:   ip2_set_line_discipline()                                      */
+/* Parameters: Pointer to tty structure                                       */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:  Does nothing                                                 */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static void
+ip2_set_line_discipline ( PTTY tty )
+{
+#ifdef IP2DEBUG_IOCTL
+	printk (KERN_DEBUG "IP2: set line discipline\n" );
+#endif
+
+	ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
+
+}
+
+/******************************************************************************/
+/* Function:   SetLine Characteristics()                                      */
+/* Parameters: Pointer to channel structure                                   */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/* This routine is called to update the channel structure with the new line   */
+/* characteristics, and send the appropriate commands to the board when they  */
+/* change.                                                                    */
+/******************************************************************************/
+static void
+set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
+{
+	tcflag_t cflag, iflag, lflag;
+	char stop_char, start_char;
+	struct ktermios dummy;
+
+	lflag = pCh->pTTY->termios->c_lflag;
+	cflag = pCh->pTTY->termios->c_cflag;
+	iflag = pCh->pTTY->termios->c_iflag;
+
+	if (o_tios == NULL) {
+		dummy.c_lflag = ~lflag;
+		dummy.c_cflag = ~cflag;
+		dummy.c_iflag = ~iflag;
+		o_tios = &dummy;
+	}
+
+	{
+		switch ( cflag & CBAUD ) {
+		case B0:
+			i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
+			pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
+			i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
+			pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
+			goto service_it;
+			break;
+		case B38400:
+			/*
+			 * This is the speed that is overloaded with all the other high
+			 * speeds, depending upon the flag settings.
+			 */
+			if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
+				pCh->speed = CBR_57600;
+			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
+				pCh->speed = CBR_115200;
+			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
+				pCh->speed = CBR_C1;
+			} else {
+				pCh->speed = CBR_38400;
+			}
+			break;
+		case B50:      pCh->speed = CBR_50;      break;
+		case B75:      pCh->speed = CBR_75;      break;
+		case B110:     pCh->speed = CBR_110;     break;
+		case B134:     pCh->speed = CBR_134;     break;
+		case B150:     pCh->speed = CBR_150;     break;
+		case B200:     pCh->speed = CBR_200;     break;
+		case B300:     pCh->speed = CBR_300;     break;
+		case B600:     pCh->speed = CBR_600;     break;
+		case B1200:    pCh->speed = CBR_1200;    break;
+		case B1800:    pCh->speed = CBR_1800;    break;
+		case B2400:    pCh->speed = CBR_2400;    break;
+		case B4800:    pCh->speed = CBR_4800;    break;
+		case B9600:    pCh->speed = CBR_9600;    break;
+		case B19200:   pCh->speed = CBR_19200;   break;
+		case B57600:   pCh->speed = CBR_57600;   break;
+		case B115200:  pCh->speed = CBR_115200;  break;
+		case B153600:  pCh->speed = CBR_153600;  break;
+		case B230400:  pCh->speed = CBR_230400;  break;
+		case B307200:  pCh->speed = CBR_307200;  break;
+		case B460800:  pCh->speed = CBR_460800;  break;
+		case B921600:  pCh->speed = CBR_921600;  break;
+		default:       pCh->speed = CBR_9600;    break;
+		}
+		if ( pCh->speed == CBR_C1 ) {
+			// Process the custom speed parameters.
+			int bps = pCh->BaudBase / pCh->BaudDivisor;
+			if ( bps == 921600 ) {
+				pCh->speed = CBR_921600;
+			} else {
+				bps = bps/10;
+				i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
+			}
+		}
+		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
+		
+		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
+		pCh->dataSetOut |= (I2_DTR | I2_RTS);
+	}
+	if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) 
+	{
+		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, 
+			CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
+	}
+	if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) 
+	{
+		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
+			CMD_SETPAR( 
+				(cflag & PARENB ?  (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
+			)
+		);
+	}
+	/* byte size and parity */
+	if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) 
+	{
+		int datasize;
+		switch ( cflag & CSIZE ) {
+		case CS5: datasize = CSZ_5; break;
+		case CS6: datasize = CSZ_6; break;
+		case CS7: datasize = CSZ_7; break;
+		case CS8: datasize = CSZ_8; break;
+		default:  datasize = CSZ_5; break;	/* as per serial.c */
+		}
+		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
+	}
+	/* Process CTS flow control flag setting */
+	if ( (cflag & CRTSCTS) ) {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100,
+						2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
+	} else {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100,
+						2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
+	}
+	//
+	// Process XON/XOFF flow control flags settings
+	//
+	stop_char = STOP_CHAR(pCh->pTTY);
+	start_char = START_CHAR(pCh->pTTY);
+
+	//////////// can't be \000
+	if (stop_char == __DISABLED_CHAR ) 
+	{
+		stop_char = ~__DISABLED_CHAR; 
+	}
+	if (start_char == __DISABLED_CHAR ) 
+	{
+		start_char = ~__DISABLED_CHAR;
+	}
+	/////////////////////////////////
+
+	if ( o_tios->c_cc[VSTART] != start_char ) 
+	{
+		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
+	}
+	if ( o_tios->c_cc[VSTOP] != stop_char ) 
+	{
+		 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
+		 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
+	}
+	if (stop_char == __DISABLED_CHAR ) 
+	{
+		stop_char = ~__DISABLED_CHAR;  //TEST123
+		goto no_xoff;
+	}
+	if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) 
+	{
+		if ( iflag & IXOFF ) {	// Enable XOFF output flow control
+			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
+		} else {	// Disable XOFF output flow control
+no_xoff:
+			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
+		}
+	}
+	if (start_char == __DISABLED_CHAR ) 
+	{
+		goto no_xon;
+	}
+	if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) 
+	{
+		if ( iflag & IXON ) {
+			if ( iflag & IXANY ) { // Enable XON/XANY output flow control
+				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
+			} else { // Enable XON output flow control
+				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
+			}
+		} else { // Disable XON output flow control
+no_xon:
+			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
+		}
+	}
+	if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) 
+	{
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
+				CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
+	}
+	if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) 
+	{
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
+				CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
+	}
+
+	if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) 
+			^	( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) 
+	{
+		char brkrpt = 0;
+		char parrpt = 0;
+
+		if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
+			/* Ignore breaks altogether */
+			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
+		} else {
+			if ( iflag & BRKINT ) {
+				if ( iflag & PARMRK ) {
+					brkrpt = 0x0a;	// exception an inline triple
+				} else {
+					brkrpt = 0x1a;	// exception and NULL
+				}
+				brkrpt |= 0x04;	// flush input
+			} else {
+				if ( iflag & PARMRK ) {
+					brkrpt = 0x0b;	//POSIX triple \0377 \0 \0
+				} else {
+					brkrpt = 0x01;	// Null only
+				}
+			}
+			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
+		} 
+
+		if (iflag & IGNPAR) {
+			parrpt = 0x20;
+													/* would be 2 for not cirrus bug */
+													/* would be 0x20 cept for cirrus bug */
+		} else {
+			if ( iflag & PARMRK ) {
+				/*
+				 * Replace error characters with 3-byte sequence (\0377,\0,char)
+				 */
+				parrpt = 0x04 ;
+				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
+			} else {
+				parrpt = 0x03;
+			} 
+		}
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
+	}
+	if (cflag & CLOCAL) {
+		// Status reporting fails for DCD if this is off
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
+		pCh->flags &= ~ASYNC_CHECK_CD;
+	} else {
+		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
+		pCh->flags	|= ASYNC_CHECK_CD;
+	}
+
+service_it:
+	i2DrainOutput( pCh, 100 );		
+}
+
+/******************************************************************************/
+/* IPL Device Section                                                         */
+/******************************************************************************/
+
+/******************************************************************************/
+/* Function:   ip2_ipl_read()                                                  */
+/* Parameters: Pointer to device inode                                        */
+/*             Pointer to file structure                                      */
+/*             Pointer to data                                                */
+/*             Number of bytes to read                                        */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description:   Ugly                                                        */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+
+static 
+ssize_t
+ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
+{
+	unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
+	int rc = 0;
+
+#ifdef IP2DEBUG_IPL
+	printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
+#endif
+
+	switch( minor ) {
+	case 0:	    // IPL device
+		rc = -EINVAL;
+		break;
+	case 1:	    // Status dump
+		rc = -EINVAL;
+		break;
+	case 2:	    // Ping device
+		rc = -EINVAL;
+		break;
+	case 3:	    // Trace device
+		rc = DumpTraceBuffer ( pData, count );
+		break;
+	case 4:	    // Trace device
+		rc = DumpFifoBuffer ( pData, count );
+		break;
+	default:
+		rc = -ENODEV;
+		break;
+	}
+	return rc;
+}
+
+static int
+DumpFifoBuffer ( char __user *pData, int count )
+{
+#ifdef DEBUG_FIFO
+	int rc;
+	rc = copy_to_user(pData, DBGBuf, count);
+
+	printk(KERN_DEBUG "Last index %d\n", I );
+
+	return count;
+#endif	/* DEBUG_FIFO */
+	return 0;
+}
+
+static int
+DumpTraceBuffer ( char __user *pData, int count )
+{
+#ifdef IP2DEBUG_TRACE
+	int rc;
+	int dumpcount;
+	int chunk;
+	int *pIndex = (int __user *)pData;
+
+	if ( count < (sizeof(int) * 6) ) {
+		return -EIO;
+	}
+	rc = put_user(tracewrap, pIndex );
+	rc = put_user(TRACEMAX, ++pIndex );
+	rc = put_user(tracestrip, ++pIndex );
+	rc = put_user(tracestuff, ++pIndex );
+	pData += sizeof(int) * 6;
+	count -= sizeof(int) * 6;
+
+	dumpcount = tracestuff - tracestrip;
+	if ( dumpcount < 0 ) {
+		dumpcount += TRACEMAX;
+	}
+	if ( dumpcount > count ) {
+		dumpcount = count;
+	}
+	chunk = TRACEMAX - tracestrip;
+	if ( dumpcount > chunk ) {
+		rc = copy_to_user(pData, &tracebuf[tracestrip],
+			      chunk * sizeof(tracebuf[0]) );
+		pData += chunk * sizeof(tracebuf[0]);
+		tracestrip = 0;
+		chunk = dumpcount - chunk;
+	} else {
+		chunk = dumpcount;
+	}
+	rc = copy_to_user(pData, &tracebuf[tracestrip],
+		      chunk * sizeof(tracebuf[0]) );
+	tracestrip += chunk;
+	tracewrap = 0;
+
+	rc = put_user(tracestrip, ++pIndex );
+	rc = put_user(tracestuff, ++pIndex );
+
+	return dumpcount;
+#else
+	return 0;
+#endif
+}
+
+/******************************************************************************/
+/* Function:   ip2_ipl_write()                                                 */
+/* Parameters:                                                                */
+/*             Pointer to file structure                                      */
+/*             Pointer to data                                                */
+/*             Number of bytes to write                                       */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static ssize_t
+ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off)
+{
+#ifdef IP2DEBUG_IPL
+	printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
+#endif
+	return 0;
+}
+
+/******************************************************************************/
+/* Function:   ip2_ipl_ioctl()                                                */
+/* Parameters: Pointer to device inode                                        */
+/*             Pointer to file structure                                      */
+/*             Command                                                        */
+/*             Argument                                                       */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static long
+ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
+{
+	unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
+	int rc = 0;
+	void __user *argp = (void __user *)arg;
+	ULONG __user *pIndex = argp;
+	i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
+	i2ChanStrPtr pCh;
+
+#ifdef IP2DEBUG_IPL
+	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
+#endif
+
+	mutex_lock(&ip2_mutex);
+
+	switch ( iplminor ) {
+	case 0:	    // IPL device
+		rc = -EINVAL;
+		break;
+	case 1:	    // Status dump
+	case 5:
+	case 9:
+	case 13:
+		switch ( cmd ) {
+		case 64:	/* Driver - ip2stat */
+			rc = put_user(-1, pIndex++ );
+			rc = put_user(irq_counter, pIndex++  );
+			rc = put_user(bh_counter, pIndex++  );
+			break;
+
+		case 65:	/* Board  - ip2stat */
+			if ( pB ) {
+				rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
+				rc = put_user(inb(pB->i2eStatus),
+					(ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
+			} else {
+				rc = -ENODEV;
+			}
+			break;
+
+		default:
+			if (cmd < IP2_MAX_PORTS) {
+				pCh = DevTable[cmd];
+				if ( pCh )
+				{
+					rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
+					if (rc)
+						rc = -EFAULT;
+				} else {
+					rc = -ENODEV;
+				}
+			} else {
+				rc = -EINVAL;
+			}
+		}
+		break;
+
+	case 2:	    // Ping device
+		rc = -EINVAL;
+		break;
+	case 3:	    // Trace device
+		/*
+		 * akpm: This used to write a whole bunch of function addresses
+		 * to userspace, which generated lots of put_user() warnings.
+		 * I killed it all.  Just return "success" and don't do
+		 * anything.
+		 */
+		if (cmd == 1)
+			rc = 0;
+		else
+			rc = -EINVAL;
+		break;
+
+	default:
+		rc = -ENODEV;
+		break;
+	}
+	mutex_unlock(&ip2_mutex);
+	return rc;
+}
+
+/******************************************************************************/
+/* Function:   ip2_ipl_open()                                                 */
+/* Parameters: Pointer to device inode                                        */
+/*             Pointer to file structure                                      */
+/* Returns:    Success or failure                                             */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+static int
+ip2_ipl_open( struct inode *pInode, struct file *pFile )
+{
+
+#ifdef IP2DEBUG_IPL
+	printk (KERN_DEBUG "IP2IPL: open\n" );
+#endif
+	return 0;
+}
+
+static int
+proc_ip2mem_show(struct seq_file *m, void *v)
+{
+	i2eBordStrPtr  pB;
+	i2ChanStrPtr  pCh;
+	PTTY tty;
+	int i;
+
+#define FMTLINE	"%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
+#define FMTLIN2	"     0x%04x 0x%04x tx flow 0x%x\n"
+#define FMTLIN3	"     0x%04x 0x%04x rc flow\n"
+
+	seq_printf(m,"\n");
+
+	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+		pB = i2BoardPtrTable[i];
+		if ( pB ) {
+			seq_printf(m,"board %d:\n",i);
+			seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
+				pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
+		}
+	}
+
+	seq_printf(m,"#: tty flags, port flags,     cflags,     iflags\n");
+	for (i=0; i < IP2_MAX_PORTS; i++) {
+		pCh = DevTable[i];
+		if (pCh) {
+			tty = pCh->pTTY;
+			if (tty && tty->count) {
+				seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
+									tty->termios->c_cflag,tty->termios->c_iflag);
+
+				seq_printf(m,FMTLIN2,
+						pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
+				seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
+			}
+		}
+	}
+	return 0;
+}
+
+static int proc_ip2mem_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, proc_ip2mem_show, NULL);
+}
+
+static const struct file_operations ip2mem_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= proc_ip2mem_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*
+ * This is the handler for /proc/tty/driver/ip2
+ *
+ * This stretch of code has been largely plagerized from at least three
+ * different sources including ip2mkdev.c and a couple of other drivers.
+ * The bugs are all mine.  :-)	=mhw=
+ */
+static int ip2_proc_show(struct seq_file *m, void *v)
+{
+	int	i, j, box;
+	int	boxes = 0;
+	int	ports = 0;
+	int	tports = 0;
+	i2eBordStrPtr  pB;
+	char *sep;
+
+	seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion);
+	seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
+			IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
+			IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
+
+	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
+		/* This need to be reset for a board by board count... */
+		boxes = 0;
+		pB = i2BoardPtrTable[i];
+		if( pB ) {
+			switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) 
+			{
+			case POR_ID_FIIEX:
+				seq_printf(m, "Board %d: EX ports=", i);
+				sep = "";
+				for( box = 0; box < ABS_MAX_BOXES; ++box )
+				{
+					ports = 0;
+
+					if( pB->i2eChannelMap[box] != 0 ) ++boxes;
+					for( j = 0; j < ABS_BIGGEST_BOX; ++j ) 
+					{
+						if( pB->i2eChannelMap[box] & 1<< j ) {
+							++ports;
+						}
+					}
+					seq_printf(m, "%s%d", sep, ports);
+					sep = ",";
+					tports += ports;
+				}
+				seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8);
+				break;
+
+			case POR_ID_II_4:
+				seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i);
+				tports = ports = 4;
+				break;
+
+			case POR_ID_II_8:
+				seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i);
+				tports = ports = 8;
+				break;
+
+			case POR_ID_II_8R:
+				seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i);
+				tports = ports = 8;
+				break;
+
+			default:
+				seq_printf(m, "Board %d: unknown", i);
+				/* Don't try and probe for minor numbers */
+				tports = ports = 0;
+			}
+
+		} else {
+			/* Don't try and probe for minor numbers */
+			seq_printf(m, "Board %d: vacant", i);
+			tports = ports = 0;
+		}
+
+		if( tports ) {
+			seq_puts(m, " minors=");
+			sep = "";
+			for ( box = 0; box < ABS_MAX_BOXES; ++box )
+			{
+				for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
+				{
+					if ( pB->i2eChannelMap[box] & (1 << j) )
+					{
+						seq_printf(m, "%s%d", sep,
+							j + ABS_BIGGEST_BOX *
+							(box+i*ABS_MAX_BOXES));
+						sep = ",";
+					}
+				}
+			}
+		}
+		seq_putc(m, '\n');
+	}
+	return 0;
+ }
+
+static int ip2_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ip2_proc_show, NULL);
+}
+
+static const struct file_operations ip2_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= ip2_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+ 
+/******************************************************************************/
+/* Function:   ip2trace()                                                     */
+/* Parameters: Value to add to trace buffer                                   */
+/* Returns:    Nothing                                                        */
+/*                                                                            */
+/* Description:                                                               */
+/*                                                                            */
+/*                                                                            */
+/******************************************************************************/
+#ifdef IP2DEBUG_TRACE
+void
+ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
+{
+	long flags;
+	unsigned long *pCode = &codes;
+	union ip2breadcrumb bc;
+	i2ChanStrPtr  pCh;
+
+
+	tracebuf[tracestuff++] = jiffies;
+	if ( tracestuff == TRACEMAX ) {
+		tracestuff = 0;
+	}
+	if ( tracestuff == tracestrip ) {
+		if ( ++tracestrip == TRACEMAX ) {
+			tracestrip = 0;
+		}
+		++tracewrap;
+	}
+
+	bc.hdr.port  = 0xff & pn;
+	bc.hdr.cat   = cat;
+	bc.hdr.codes = (unsigned char)( codes & 0xff );
+	bc.hdr.label = label;
+	tracebuf[tracestuff++] = bc.value;
+
+	for (;;) {
+		if ( tracestuff == TRACEMAX ) {
+			tracestuff = 0;
+		}
+		if ( tracestuff == tracestrip ) {
+			if ( ++tracestrip == TRACEMAX ) {
+				tracestrip = 0;
+			}
+			++tracewrap;
+		}
+
+		if ( !codes-- )
+			break;
+
+		tracebuf[tracestuff++] = *++pCode;
+	}
+}
+#endif
+
+
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
+
+MODULE_FIRMWARE("intelliport2.bin");
diff --git a/drivers/staging/tty/ip2/ip2trace.h b/drivers/staging/tty/ip2/ip2trace.h
new file mode 100644
index 0000000..da20435
--- /dev/null
+++ b/drivers/staging/tty/ip2/ip2trace.h
@@ -0,0 +1,42 @@
+
+//
+union ip2breadcrumb 
+{
+	struct { 
+		unsigned char port, cat, codes, label;
+	} __attribute__ ((packed)) hdr;
+	unsigned long value;
+};
+
+#define ITRC_NO_PORT 	0xFF
+#define CHANN	(pCh->port_index)
+
+#define	ITRC_ERROR	'!'
+#define	ITRC_INIT 	'A'
+#define	ITRC_OPEN	'B'
+#define	ITRC_CLOSE	'C'
+#define	ITRC_DRAIN	'D'
+#define	ITRC_IOCTL	'E'
+#define	ITRC_FLUSH	'F'
+#define	ITRC_STATUS	'G'
+#define	ITRC_HANGUP	'H'
+#define	ITRC_INTR 	'I'
+#define	ITRC_SFLOW	'J'
+#define	ITRC_SBCMD	'K'
+#define	ITRC_SICMD	'L'
+#define	ITRC_MODEM	'M'
+#define	ITRC_INPUT	'N'
+#define	ITRC_OUTPUT	'O'
+#define	ITRC_PUTC	'P'
+#define	ITRC_QUEUE	'Q'
+#define	ITRC_STFLW	'R'
+#define	ITRC_SFIFO	'S'
+#define	ITRC_VERIFY	'V'
+#define	ITRC_WRITE	'W'
+
+#define	ITRC_ENTER	0x00
+#define	ITRC_RETURN	0xFF
+
+#define	ITRC_QUEUE_ROOM	2
+#define	ITRC_QUEUE_CMD	6
+
diff --git a/drivers/staging/tty/ip2/ip2types.h b/drivers/staging/tty/ip2/ip2types.h
new file mode 100644
index 0000000..9d67b26
--- /dev/null
+++ b/drivers/staging/tty/ip2/ip2types.h
@@ -0,0 +1,57 @@
+/*******************************************************************************
+*
+*   (c) 1998 by Computone Corporation
+*
+********************************************************************************
+*
+*
+*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
+*                serial I/O controllers.
+*
+*   DESCRIPTION: Driver constants and type definitions.
+*
+*   NOTES:
+*
+*******************************************************************************/
+#ifndef IP2TYPES_H
+#define IP2TYPES_H
+
+//*************
+//* Constants *
+//*************
+
+// Define some limits for this driver. Ports per board is a hardware limitation
+// that will not change. Current hardware limits this to 64 ports per board.
+// Boards per driver is a self-imposed limit.
+//
+#define IP2_MAX_BOARDS        4
+#define IP2_PORTS_PER_BOARD   ABS_MOST_PORTS
+#define IP2_MAX_PORTS         (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD)
+
+#define ISA    0
+#define PCI    1
+#define EISA   2
+
+//********************
+//* Type Definitions *
+//********************
+
+typedef struct tty_struct *   PTTY;
+typedef wait_queue_head_t   PWAITQ;
+
+typedef unsigned char         UCHAR;
+typedef unsigned int          UINT;
+typedef unsigned short        USHORT;
+typedef unsigned long         ULONG;
+
+typedef struct 
+{
+	short irq[IP2_MAX_BOARDS]; 
+	unsigned short addr[IP2_MAX_BOARDS];
+	int type[IP2_MAX_BOARDS];
+#ifdef CONFIG_PCI
+	struct pci_dev *pci_dev[IP2_MAX_BOARDS];
+#endif
+} ip2config_t;
+
+#endif
diff --git a/drivers/staging/tty/istallion.c b/drivers/staging/tty/istallion.c
new file mode 100644
index 0000000..0b26627
--- /dev/null
+++ b/drivers/staging/tty/istallion.c
@@ -0,0 +1,4507 @@
+/*****************************************************************************/
+
+/*
+ *	istallion.c  -- stallion intelligent multiport serial driver.
+ *
+ *	Copyright (C) 1996-1999  Stallion Technologies
+ *	Copyright (C) 1994-1996  Greg Ungerer.
+ *
+ *	This code is loosely based on the Linux serial driver, written by
+ *	Linus Torvalds, Theodore T'so and others.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/seq_file.h>
+#include <linux/cdk.h>
+#include <linux/comstats.h>
+#include <linux/istallion.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/eisa.h>
+#include <linux/ctype.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <linux/pci.h>
+
+/*****************************************************************************/
+
+/*
+ *	Define different board types. Not all of the following board types
+ *	are supported by this driver. But I will use the standard "assigned"
+ *	board numbers. Currently supported boards are abbreviated as:
+ *	ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
+ *	STAL = Stallion.
+ */
+#define	BRD_UNKNOWN	0
+#define	BRD_STALLION	1
+#define	BRD_BRUMBY4	2
+#define	BRD_ONBOARD2	3
+#define	BRD_ONBOARD	4
+#define	BRD_ONBOARDE	7
+#define	BRD_ECP		23
+#define BRD_ECPE	24
+#define	BRD_ECPMC	25
+#define	BRD_ECPPCI	29
+
+#define	BRD_BRUMBY	BRD_BRUMBY4
+
+/*
+ *	Define a configuration structure to hold the board configuration.
+ *	Need to set this up in the code (for now) with the boards that are
+ *	to be configured into the system. This is what needs to be modified
+ *	when adding/removing/modifying boards. Each line entry in the
+ *	stli_brdconf[] array is a board. Each line contains io/irq/memory
+ *	ranges for that board (as well as what type of board it is).
+ *	Some examples:
+ *		{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
+ *	This line will configure an EasyConnection 8/64 at io address 2a0,
+ *	and shared memory address of cc000. Multiple EasyConnection 8/64
+ *	boards can share the same shared memory address space. No interrupt
+ *	is required for this board type.
+ *	Another example:
+ *		{ BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 },
+ *	This line will configure an EasyConnection 8/64 EISA in slot 5 and
+ *	shared memory address of 0x80000000 (2 GByte). Multiple
+ *	EasyConnection 8/64 EISA boards can share the same shared memory
+ *	address space. No interrupt is required for this board type.
+ *	Another example:
+ *		{ BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 },
+ *	This line will configure an ONboard (ISA type) at io address 240,
+ *	and shared memory address of d0000. Multiple ONboards can share
+ *	the same shared memory address space. No interrupt required.
+ *	Another example:
+ *		{ BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 },
+ *	This line will configure a Brumby board (any number of ports!) at
+ *	io address 360 and shared memory address of c8000. All Brumby boards
+ *	configured into a system must have their own separate io and memory
+ *	addresses. No interrupt is required.
+ *	Another example:
+ *		{ BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 },
+ *	This line will configure an original Stallion board at io address 330
+ *	and shared memory address d0000 (this would only be valid for a "V4.0"
+ *	or Rev.O Stallion board). All Stallion boards configured into the
+ *	system must have their own separate io and memory addresses. No
+ *	interrupt is required.
+ */
+
+struct stlconf {
+	int		brdtype;
+	int		ioaddr1;
+	int		ioaddr2;
+	unsigned long	memaddr;
+	int		irq;
+	int		irqtype;
+};
+
+static unsigned int stli_nrbrds;
+
+/* stli_lock must NOT be taken holding brd_lock */
+static spinlock_t stli_lock;	/* TTY logic lock */
+static spinlock_t brd_lock;	/* Board logic lock */
+
+/*
+ *	There is some experimental EISA board detection code in this driver.
+ *	By default it is disabled, but for those that want to try it out,
+ *	then set the define below to be 1.
+ */
+#define	STLI_EISAPROBE	0
+
+/*****************************************************************************/
+
+/*
+ *	Define some important driver characteristics. Device major numbers
+ *	allocated as per Linux Device Registry.
+ */
+#ifndef	STL_SIOMEMMAJOR
+#define	STL_SIOMEMMAJOR		28
+#endif
+#ifndef	STL_SERIALMAJOR
+#define	STL_SERIALMAJOR		24
+#endif
+#ifndef	STL_CALLOUTMAJOR
+#define	STL_CALLOUTMAJOR	25
+#endif
+
+/*****************************************************************************/
+
+/*
+ *	Define our local driver identity first. Set up stuff to deal with
+ *	all the local structures required by a serial tty driver.
+ */
+static char	*stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
+static char	*stli_drvname = "istallion";
+static char	*stli_drvversion = "5.6.0";
+static char	*stli_serialname = "ttyE";
+
+static struct tty_driver	*stli_serial;
+static const struct tty_port_operations stli_port_ops;
+
+#define	STLI_TXBUFSIZE		4096
+
+/*
+ *	Use a fast local buffer for cooked characters. Typically a whole
+ *	bunch of cooked characters come in for a port, 1 at a time. So we
+ *	save those up into a local buffer, then write out the whole lot
+ *	with a large memcpy. Just use 1 buffer for all ports, since its
+ *	use it is only need for short periods of time by each port.
+ */
+static char			*stli_txcookbuf;
+static int			stli_txcooksize;
+static int			stli_txcookrealsize;
+static struct tty_struct	*stli_txcooktty;
+
+/*
+ *	Define a local default termios struct. All ports will be created
+ *	with this termios initially. Basically all it defines is a raw port
+ *	at 9600 baud, 8 data bits, no parity, 1 stop bit.
+ */
+static struct ktermios		stli_deftermios = {
+	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
+	.c_cc		= INIT_C_CC,
+	.c_ispeed	= 9600,
+	.c_ospeed	= 9600,
+};
+
+/*
+ *	Define global stats structures. Not used often, and can be
+ *	re-used for each stats call.
+ */
+static comstats_t	stli_comstats;
+static combrd_t		stli_brdstats;
+static struct asystats	stli_cdkstats;
+
+/*****************************************************************************/
+
+static DEFINE_MUTEX(stli_brdslock);
+static struct stlibrd	*stli_brds[STL_MAXBRDS];
+
+static int		stli_shared;
+
+/*
+ *	Per board state flags. Used with the state field of the board struct.
+ *	Not really much here... All we need to do is keep track of whether
+ *	the board has been detected, and whether it is actually running a slave
+ *	or not.
+ */
+#define	BST_FOUND	0
+#define	BST_STARTED	1
+#define	BST_PROBED	2
+
+/*
+ *	Define the set of port state flags. These are marked for internal
+ *	state purposes only, usually to do with the state of communications
+ *	with the slave. Most of them need to be updated atomically, so always
+ *	use the bit setting operations (unless protected by cli/sti).
+ */
+#define	ST_OPENING	2
+#define	ST_CLOSING	3
+#define	ST_CMDING	4
+#define	ST_TXBUSY	5
+#define	ST_RXING	6
+#define	ST_DOFLUSHRX	7
+#define	ST_DOFLUSHTX	8
+#define	ST_DOSIGS	9
+#define	ST_RXSTOP	10
+#define	ST_GETSIGS	11
+
+/*
+ *	Define an array of board names as printable strings. Handy for
+ *	referencing boards when printing trace and stuff.
+ */
+static char	*stli_brdnames[] = {
+	"Unknown",
+	"Stallion",
+	"Brumby",
+	"ONboard-MC",
+	"ONboard",
+	"Brumby",
+	"Brumby",
+	"ONboard-EI",
+	NULL,
+	"ONboard",
+	"ONboard-MC",
+	"ONboard-MC",
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"EasyIO",
+	"EC8/32-AT",
+	"EC8/32-MC",
+	"EC8/64-AT",
+	"EC8/64-EI",
+	"EC8/64-MC",
+	"EC8/32-PCI",
+	"EC8/64-PCI",
+	"EasyIO-PCI",
+	"EC/RA-PCI",
+};
+
+/*****************************************************************************/
+
+/*
+ *	Define some string labels for arguments passed from the module
+ *	load line. These allow for easy board definitions, and easy
+ *	modification of the io, memory and irq resoucres.
+ */
+
+static char	*board0[8];
+static char	*board1[8];
+static char	*board2[8];
+static char	*board3[8];
+
+static char	**stli_brdsp[] = {
+	(char **) &board0,
+	(char **) &board1,
+	(char **) &board2,
+	(char **) &board3
+};
+
+/*
+ *	Define a set of common board names, and types. This is used to
+ *	parse any module arguments.
+ */
+
+static struct stlibrdtype {
+	char	*name;
+	int	type;
+} stli_brdstr[] = {
+	{ "stallion", BRD_STALLION },
+	{ "1", BRD_STALLION },
+	{ "brumby", BRD_BRUMBY },
+	{ "brumby4", BRD_BRUMBY },
+	{ "brumby/4", BRD_BRUMBY },
+	{ "brumby-4", BRD_BRUMBY },
+	{ "brumby8", BRD_BRUMBY },
+	{ "brumby/8", BRD_BRUMBY },
+	{ "brumby-8", BRD_BRUMBY },
+	{ "brumby16", BRD_BRUMBY },
+	{ "brumby/16", BRD_BRUMBY },
+	{ "brumby-16", BRD_BRUMBY },
+	{ "2", BRD_BRUMBY },
+	{ "onboard2", BRD_ONBOARD2 },
+	{ "onboard-2", BRD_ONBOARD2 },
+	{ "onboard/2", BRD_ONBOARD2 },
+	{ "onboard-mc", BRD_ONBOARD2 },
+	{ "onboard/mc", BRD_ONBOARD2 },
+	{ "onboard-mca", BRD_ONBOARD2 },
+	{ "onboard/mca", BRD_ONBOARD2 },
+	{ "3", BRD_ONBOARD2 },
+	{ "onboard", BRD_ONBOARD },
+	{ "onboardat", BRD_ONBOARD },
+	{ "4", BRD_ONBOARD },
+	{ "onboarde", BRD_ONBOARDE },
+	{ "onboard-e", BRD_ONBOARDE },
+	{ "onboard/e", BRD_ONBOARDE },
+	{ "onboard-ei", BRD_ONBOARDE },
+	{ "onboard/ei", BRD_ONBOARDE },
+	{ "7", BRD_ONBOARDE },
+	{ "ecp", BRD_ECP },
+	{ "ecpat", BRD_ECP },
+	{ "ec8/64", BRD_ECP },
+	{ "ec8/64-at", BRD_ECP },
+	{ "ec8/64-isa", BRD_ECP },
+	{ "23", BRD_ECP },
+	{ "ecpe", BRD_ECPE },
+	{ "ecpei", BRD_ECPE },
+	{ "ec8/64-e", BRD_ECPE },
+	{ "ec8/64-ei", BRD_ECPE },
+	{ "24", BRD_ECPE },
+	{ "ecpmc", BRD_ECPMC },
+	{ "ec8/64-mc", BRD_ECPMC },
+	{ "ec8/64-mca", BRD_ECPMC },
+	{ "25", BRD_ECPMC },
+	{ "ecppci", BRD_ECPPCI },
+	{ "ec/ra", BRD_ECPPCI },
+	{ "ec/ra-pc", BRD_ECPPCI },
+	{ "ec/ra-pci", BRD_ECPPCI },
+	{ "29", BRD_ECPPCI },
+};
+
+/*
+ *	Define the module agruments.
+ */
+MODULE_AUTHOR("Greg Ungerer");
+MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
+MODULE_LICENSE("GPL");
+
+
+module_param_array(board0, charp, NULL, 0);
+MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
+module_param_array(board1, charp, NULL, 0);
+MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
+module_param_array(board2, charp, NULL, 0);
+MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
+module_param_array(board3, charp, NULL, 0);
+MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
+
+#if STLI_EISAPROBE != 0
+/*
+ *	Set up a default memory address table for EISA board probing.
+ *	The default addresses are all bellow 1Mbyte, which has to be the
+ *	case anyway. They should be safe, since we only read values from
+ *	them, and interrupts are disabled while we do it. If the higher
+ *	memory support is compiled in then we also try probing around
+ *	the 1Gb, 2Gb and 3Gb areas as well...
+ */
+static unsigned long	stli_eisamemprobeaddrs[] = {
+	0xc0000,    0xd0000,    0xe0000,    0xf0000,
+	0x80000000, 0x80010000, 0x80020000, 0x80030000,
+	0x40000000, 0x40010000, 0x40020000, 0x40030000,
+	0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000,
+	0xff000000, 0xff010000, 0xff020000, 0xff030000,
+};
+
+static int	stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
+#endif
+
+/*
+ *	Define the Stallion PCI vendor and device IDs.
+ */
+#ifndef PCI_DEVICE_ID_ECRA
+#define	PCI_DEVICE_ID_ECRA		0x0004
+#endif
+
+static struct pci_device_id istallion_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
+
+static struct pci_driver stli_pcidriver;
+
+/*****************************************************************************/
+
+/*
+ *	Hardware configuration info for ECP boards. These defines apply
+ *	to the directly accessible io ports of the ECP. There is a set of
+ *	defines for each ECP board type, ISA, EISA, MCA and PCI.
+ */
+#define	ECP_IOSIZE	4
+
+#define	ECP_MEMSIZE	(128 * 1024)
+#define	ECP_PCIMEMSIZE	(256 * 1024)
+
+#define	ECP_ATPAGESIZE	(4 * 1024)
+#define	ECP_MCPAGESIZE	(4 * 1024)
+#define	ECP_EIPAGESIZE	(64 * 1024)
+#define	ECP_PCIPAGESIZE	(64 * 1024)
+
+#define	STL_EISAID	0x8c4e
+
+/*
+ *	Important defines for the ISA class of ECP board.
+ */
+#define	ECP_ATIREG	0
+#define	ECP_ATCONFR	1
+#define	ECP_ATMEMAR	2
+#define	ECP_ATMEMPR	3
+#define	ECP_ATSTOP	0x1
+#define	ECP_ATINTENAB	0x10
+#define	ECP_ATENABLE	0x20
+#define	ECP_ATDISABLE	0x00
+#define	ECP_ATADDRMASK	0x3f000
+#define	ECP_ATADDRSHFT	12
+
+/*
+ *	Important defines for the EISA class of ECP board.
+ */
+#define	ECP_EIIREG	0
+#define	ECP_EIMEMARL	1
+#define	ECP_EICONFR	2
+#define	ECP_EIMEMARH	3
+#define	ECP_EIENABLE	0x1
+#define	ECP_EIDISABLE	0x0
+#define	ECP_EISTOP	0x4
+#define	ECP_EIEDGE	0x00
+#define	ECP_EILEVEL	0x80
+#define	ECP_EIADDRMASKL	0x00ff0000
+#define	ECP_EIADDRSHFTL	16
+#define	ECP_EIADDRMASKH	0xff000000
+#define	ECP_EIADDRSHFTH	24
+#define	ECP_EIBRDENAB	0xc84
+
+#define	ECP_EISAID	0x4
+
+/*
+ *	Important defines for the Micro-channel class of ECP board.
+ *	(It has a lot in common with the ISA boards.)
+ */
+#define	ECP_MCIREG	0
+#define	ECP_MCCONFR	1
+#define	ECP_MCSTOP	0x20
+#define	ECP_MCENABLE	0x80
+#define	ECP_MCDISABLE	0x00
+
+/*
+ *	Important defines for the PCI class of ECP board.
+ *	(It has a lot in common with the other ECP boards.)
+ */
+#define	ECP_PCIIREG	0
+#define	ECP_PCICONFR	1
+#define	ECP_PCISTOP	0x01
+
+/*
+ *	Hardware configuration info for ONboard and Brumby boards. These
+ *	defines apply to the directly accessible io ports of these boards.
+ */
+#define	ONB_IOSIZE	16
+#define	ONB_MEMSIZE	(64 * 1024)
+#define	ONB_ATPAGESIZE	(64 * 1024)
+#define	ONB_MCPAGESIZE	(64 * 1024)
+#define	ONB_EIMEMSIZE	(128 * 1024)
+#define	ONB_EIPAGESIZE	(64 * 1024)
+
+/*
+ *	Important defines for the ISA class of ONboard board.
+ */
+#define	ONB_ATIREG	0
+#define	ONB_ATMEMAR	1
+#define	ONB_ATCONFR	2
+#define	ONB_ATSTOP	0x4
+#define	ONB_ATENABLE	0x01
+#define	ONB_ATDISABLE	0x00
+#define	ONB_ATADDRMASK	0xff0000
+#define	ONB_ATADDRSHFT	16
+
+#define	ONB_MEMENABLO	0
+#define	ONB_MEMENABHI	0x02
+
+/*
+ *	Important defines for the EISA class of ONboard board.
+ */
+#define	ONB_EIIREG	0
+#define	ONB_EIMEMARL	1
+#define	ONB_EICONFR	2
+#define	ONB_EIMEMARH	3
+#define	ONB_EIENABLE	0x1
+#define	ONB_EIDISABLE	0x0
+#define	ONB_EISTOP	0x4
+#define	ONB_EIEDGE	0x00
+#define	ONB_EILEVEL	0x80
+#define	ONB_EIADDRMASKL	0x00ff0000
+#define	ONB_EIADDRSHFTL	16
+#define	ONB_EIADDRMASKH	0xff000000
+#define	ONB_EIADDRSHFTH	24
+#define	ONB_EIBRDENAB	0xc84
+
+#define	ONB_EISAID	0x1
+
+/*
+ *	Important defines for the Brumby boards. They are pretty simple,
+ *	there is not much that is programmably configurable.
+ */
+#define	BBY_IOSIZE	16
+#define	BBY_MEMSIZE	(64 * 1024)
+#define	BBY_PAGESIZE	(16 * 1024)
+
+#define	BBY_ATIREG	0
+#define	BBY_ATCONFR	1
+#define	BBY_ATSTOP	0x4
+
+/*
+ *	Important defines for the Stallion boards. They are pretty simple,
+ *	there is not much that is programmably configurable.
+ */
+#define	STAL_IOSIZE	16
+#define	STAL_MEMSIZE	(64 * 1024)
+#define	STAL_PAGESIZE	(64 * 1024)
+
+/*
+ *	Define the set of status register values for EasyConnection panels.
+ *	The signature will return with the status value for each panel. From
+ *	this we can determine what is attached to the board - before we have
+ *	actually down loaded any code to it.
+ */
+#define	ECH_PNLSTATUS	2
+#define	ECH_PNL16PORT	0x20
+#define	ECH_PNLIDMASK	0x07
+#define	ECH_PNLXPID	0x40
+#define	ECH_PNLINTRPEND	0x80
+
+/*
+ *	Define some macros to do things to the board. Even those these boards
+ *	are somewhat related there is often significantly different ways of
+ *	doing some operation on it (like enable, paging, reset, etc). So each
+ *	board class has a set of functions which do the commonly required
+ *	operations. The macros below basically just call these functions,
+ *	generally checking for a NULL function - which means that the board
+ *	needs nothing done to it to achieve this operation!
+ */
+#define	EBRDINIT(brdp)						\
+	if (brdp->init != NULL)					\
+		(* brdp->init)(brdp)
+
+#define	EBRDENABLE(brdp)					\
+	if (brdp->enable != NULL)				\
+		(* brdp->enable)(brdp);
+
+#define	EBRDDISABLE(brdp)					\
+	if (brdp->disable != NULL)				\
+		(* brdp->disable)(brdp);
+
+#define	EBRDINTR(brdp)						\
+	if (brdp->intr != NULL)					\
+		(* brdp->intr)(brdp);
+
+#define	EBRDRESET(brdp)						\
+	if (brdp->reset != NULL)				\
+		(* brdp->reset)(brdp);
+
+#define	EBRDGETMEMPTR(brdp,offset)				\
+	(* brdp->getmemptr)(brdp, offset, __LINE__)
+
+/*
+ *	Define the maximal baud rate, and the default baud base for ports.
+ */
+#define	STL_MAXBAUD	460800
+#define	STL_BAUDBASE	115200
+#define	STL_CLOSEDELAY	(5 * HZ / 10)
+
+/*****************************************************************************/
+
+/*
+ *	Define macros to extract a brd or port number from a minor number.
+ */
+#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
+#define	MINOR2PORT(min)		((min) & 0x3f)
+
+/*****************************************************************************/
+
+/*
+ *	Prototype all functions in this driver!
+ */
+
+static int	stli_parsebrd(struct stlconf *confp, char **argp);
+static int	stli_open(struct tty_struct *tty, struct file *filp);
+static void	stli_close(struct tty_struct *tty, struct file *filp);
+static int	stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
+static int	stli_putchar(struct tty_struct *tty, unsigned char ch);
+static void	stli_flushchars(struct tty_struct *tty);
+static int	stli_writeroom(struct tty_struct *tty);
+static int	stli_charsinbuffer(struct tty_struct *tty);
+static int	stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static void	stli_settermios(struct tty_struct *tty, struct ktermios *old);
+static void	stli_throttle(struct tty_struct *tty);
+static void	stli_unthrottle(struct tty_struct *tty);
+static void	stli_stop(struct tty_struct *tty);
+static void	stli_start(struct tty_struct *tty);
+static void	stli_flushbuffer(struct tty_struct *tty);
+static int	stli_breakctl(struct tty_struct *tty, int state);
+static void	stli_waituntilsent(struct tty_struct *tty, int timeout);
+static void	stli_sendxchar(struct tty_struct *tty, char ch);
+static void	stli_hangup(struct tty_struct *tty);
+
+static int	stli_brdinit(struct stlibrd *brdp);
+static int	stli_startbrd(struct stlibrd *brdp);
+static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
+static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
+static long	stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
+static void	stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
+static void	stli_poll(unsigned long arg);
+static int	stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
+static int	stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
+static int	stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
+static int	stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
+static int	stli_setport(struct tty_struct *tty);
+static int	stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void	stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void	__stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void	stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
+static void	stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
+static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
+static long	stli_mktiocm(unsigned long sigvalue);
+static void	stli_read(struct stlibrd *brdp, struct stliport *portp);
+static int	stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
+static int	stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
+static int	stli_getbrdstats(combrd_t __user *bp);
+static int	stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
+static int	stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
+static int	stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
+static int	stli_getportstruct(struct stliport __user *arg);
+static int	stli_getbrdstruct(struct stlibrd __user *arg);
+static struct stlibrd *stli_allocbrd(void);
+
+static void	stli_ecpinit(struct stlibrd *brdp);
+static void	stli_ecpenable(struct stlibrd *brdp);
+static void	stli_ecpdisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_ecpreset(struct stlibrd *brdp);
+static void	stli_ecpintr(struct stlibrd *brdp);
+static void	stli_ecpeiinit(struct stlibrd *brdp);
+static void	stli_ecpeienable(struct stlibrd *brdp);
+static void	stli_ecpeidisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_ecpeireset(struct stlibrd *brdp);
+static void	stli_ecpmcenable(struct stlibrd *brdp);
+static void	stli_ecpmcdisable(struct stlibrd *brdp);
+static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_ecpmcreset(struct stlibrd *brdp);
+static void	stli_ecppciinit(struct stlibrd *brdp);
+static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_ecppcireset(struct stlibrd *brdp);
+
+static void	stli_onbinit(struct stlibrd *brdp);
+static void	stli_onbenable(struct stlibrd *brdp);
+static void	stli_onbdisable(struct stlibrd *brdp);
+static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_onbreset(struct stlibrd *brdp);
+static void	stli_onbeinit(struct stlibrd *brdp);
+static void	stli_onbeenable(struct stlibrd *brdp);
+static void	stli_onbedisable(struct stlibrd *brdp);
+static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_onbereset(struct stlibrd *brdp);
+static void	stli_bbyinit(struct stlibrd *brdp);
+static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_bbyreset(struct stlibrd *brdp);
+static void	stli_stalinit(struct stlibrd *brdp);
+static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
+static void	stli_stalreset(struct stlibrd *brdp);
+
+static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
+
+static int	stli_initecp(struct stlibrd *brdp);
+static int	stli_initonb(struct stlibrd *brdp);
+#if STLI_EISAPROBE != 0
+static int	stli_eisamemprobe(struct stlibrd *brdp);
+#endif
+static int	stli_initports(struct stlibrd *brdp);
+
+/*****************************************************************************/
+
+/*
+ *	Define the driver info for a user level shared memory device. This
+ *	device will work sort of like the /dev/kmem device - except that it
+ *	will give access to the shared memory on the Stallion intelligent
+ *	board. This is also a very useful debugging tool.
+ */
+static const struct file_operations	stli_fsiomem = {
+	.owner		= THIS_MODULE,
+	.read		= stli_memread,
+	.write		= stli_memwrite,
+	.unlocked_ioctl	= stli_memioctl,
+	.llseek		= default_llseek,
+};
+
+/*****************************************************************************/
+
+/*
+ *	Define a timer_list entry for our poll routine. The slave board
+ *	is polled every so often to see if anything needs doing. This is
+ *	much cheaper on host cpu than using interrupts. It turns out to
+ *	not increase character latency by much either...
+ */
+static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
+
+static int	stli_timeron;
+
+/*
+ *	Define the calculation for the timeout routine.
+ */
+#define	STLI_TIMEOUT	(jiffies + 1)
+
+/*****************************************************************************/
+
+static struct class *istallion_class;
+
+static void stli_cleanup_ports(struct stlibrd *brdp)
+{
+	struct stliport *portp;
+	unsigned int j;
+	struct tty_struct *tty;
+
+	for (j = 0; j < STL_MAXPORTS; j++) {
+		portp = brdp->ports[j];
+		if (portp != NULL) {
+			tty = tty_port_tty_get(&portp->port);
+			if (tty != NULL) {
+				tty_hangup(tty);
+				tty_kref_put(tty);
+			}
+			kfree(portp);
+		}
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Parse the supplied argument string, into the board conf struct.
+ */
+
+static int stli_parsebrd(struct stlconf *confp, char **argp)
+{
+	unsigned int i;
+	char *sp;
+
+	if (argp[0] == NULL || *argp[0] == 0)
+		return 0;
+
+	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
+		*sp = tolower(*sp);
+
+	for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
+		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
+			break;
+	}
+	if (i == ARRAY_SIZE(stli_brdstr)) {
+		printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]);
+		return 0;
+	}
+
+	confp->brdtype = stli_brdstr[i].type;
+	if (argp[1] != NULL && *argp[1] != 0)
+		confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
+	if (argp[2] !=  NULL && *argp[2] != 0)
+		confp->memaddr = simple_strtoul(argp[2], NULL, 0);
+	return(1);
+}
+
+/*****************************************************************************/
+
+/*
+ *	On the first open of the device setup the port hardware, and
+ *	initialize the per port data structure. Since initializing the port
+ *	requires several commands to the board we will need to wait for any
+ *	other open that is already initializing the port.
+ *
+ *	Locking: protected by the port mutex.
+ */
+
+static int stli_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct stliport *portp = container_of(port, struct stliport, port);
+	struct stlibrd *brdp = stli_brds[portp->brdnr];
+	int rc;
+
+	if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
+		clear_bit(TTY_IO_ERROR, &tty->flags);
+	wake_up_interruptible(&portp->raw_wait);
+	return rc;
+}
+
+static int stli_open(struct tty_struct *tty, struct file *filp)
+{
+	struct stlibrd *brdp;
+	struct stliport *portp;
+	unsigned int minordev, brdnr, portnr;
+
+	minordev = tty->index;
+	brdnr = MINOR2BRD(minordev);
+	if (brdnr >= stli_nrbrds)
+		return -ENODEV;
+	brdp = stli_brds[brdnr];
+	if (brdp == NULL)
+		return -ENODEV;
+	if (!test_bit(BST_STARTED, &brdp->state))
+		return -ENODEV;
+	portnr = MINOR2PORT(minordev);
+	if (portnr > brdp->nrports)
+		return -ENODEV;
+
+	portp = brdp->ports[portnr];
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->devnr < 1)
+		return -ENODEV;
+
+	tty->driver_data = portp;
+	return tty_port_open(&portp->port, tty, filp);
+}
+
+
+/*****************************************************************************/
+
+static void stli_shutdown(struct tty_port *port)
+{
+	struct stlibrd *brdp;
+	unsigned long ftype;
+	unsigned long flags;
+	struct stliport *portp = container_of(port, struct stliport, port);
+
+	if (portp->brdnr >= stli_nrbrds)
+		return;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+	/*
+	 *	May want to wait for data to drain before closing. The BUSY
+	 *	flag keeps track of whether we are still transmitting or not.
+	 *	It is updated by messages from the slave - indicating when all
+	 *	chars really have drained.
+	 */
+
+	if (!test_bit(ST_CLOSING, &portp->state))
+		stli_rawclose(brdp, portp, 0, 0);
+
+ 	spin_lock_irqsave(&stli_lock, flags);
+	clear_bit(ST_TXBUSY, &portp->state);
+	clear_bit(ST_RXSTOP, &portp->state);
+	spin_unlock_irqrestore(&stli_lock, flags);
+
+	ftype = FLUSHTX | FLUSHRX;
+	stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
+}
+
+static void stli_close(struct tty_struct *tty, struct file *filp)
+{
+	struct stliport *portp = tty->driver_data;
+	unsigned long flags;
+	if (portp == NULL)
+		return;
+ 	spin_lock_irqsave(&stli_lock, flags);
+	/*	Flush any internal buffering out first */
+	if (tty == stli_txcooktty)
+		stli_flushchars(tty);
+	spin_unlock_irqrestore(&stli_lock, flags);
+	tty_port_close(&portp->port, tty, filp);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Carry out first open operations on a port. This involves a number of
+ *	commands to be sent to the slave. We need to open the port, set the
+ *	notification events, set the initial port settings, get and set the
+ *	initial signal values. We sleep and wait in between each one. But
+ *	this still all happens pretty quickly.
+ */
+
+static int stli_initopen(struct tty_struct *tty,
+				struct stlibrd *brdp, struct stliport *portp)
+{
+	asynotify_t nt;
+	asyport_t aport;
+	int rc;
+
+	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
+		return rc;
+
+	memset(&nt, 0, sizeof(asynotify_t));
+	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
+	nt.signal = SG_DCD;
+	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
+	    sizeof(asynotify_t), 0)) < 0)
+		return rc;
+
+	stli_mkasyport(tty, portp, &aport, tty->termios);
+	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
+	    sizeof(asyport_t), 0)) < 0)
+		return rc;
+
+	set_bit(ST_GETSIGS, &portp->state);
+	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
+	    sizeof(asysigs_t), 1)) < 0)
+		return rc;
+	if (test_and_clear_bit(ST_GETSIGS, &portp->state))
+		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
+	stli_mkasysigs(&portp->asig, 1, 1);
+	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+	    sizeof(asysigs_t), 0)) < 0)
+		return rc;
+
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Send an open message to the slave. This will sleep waiting for the
+ *	acknowledgement, so must have user context. We need to co-ordinate
+ *	with close events here, since we don't want open and close events
+ *	to overlap.
+ */
+
+static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
+{
+	cdkhdr_t __iomem *hdrp;
+	cdkctrl_t __iomem *cp;
+	unsigned char __iomem *bits;
+	unsigned long flags;
+	int rc;
+
+/*
+ *	Send a message to the slave to open this port.
+ */
+
+/*
+ *	Slave is already closing this port. This can happen if a hangup
+ *	occurs on this port. So we must wait until it is complete. The
+ *	order of opens and closes may not be preserved across shared
+ *	memory, so we must wait until it is complete.
+ */
+	wait_event_interruptible_tty(portp->raw_wait,
+			!test_bit(ST_CLOSING, &portp->state));
+	if (signal_pending(current)) {
+		return -ERESTARTSYS;
+	}
+
+/*
+ *	Everything is ready now, so write the open message into shared
+ *	memory. Once the message is in set the service bits to say that
+ *	this port wants service.
+ */
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
+	writel(arg, &cp->openarg);
+	writeb(1, &cp->open);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
+		portp->portidx;
+	writeb(readb(bits) | portp->portbit, bits);
+	EBRDDISABLE(brdp);
+
+	if (wait == 0) {
+		spin_unlock_irqrestore(&brd_lock, flags);
+		return 0;
+	}
+
+/*
+ *	Slave is in action, so now we must wait for the open acknowledgment
+ *	to come back.
+ */
+	rc = 0;
+	set_bit(ST_OPENING, &portp->state);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	wait_event_interruptible_tty(portp->raw_wait,
+			!test_bit(ST_OPENING, &portp->state));
+	if (signal_pending(current))
+		rc = -ERESTARTSYS;
+
+	if ((rc == 0) && (portp->rc != 0))
+		rc = -EIO;
+	return rc;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Send a close message to the slave. Normally this will sleep waiting
+ *	for the acknowledgement, but if wait parameter is 0 it will not. If
+ *	wait is true then must have user context (to sleep).
+ */
+
+static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
+{
+	cdkhdr_t __iomem *hdrp;
+	cdkctrl_t __iomem *cp;
+	unsigned char __iomem *bits;
+	unsigned long flags;
+	int rc;
+
+/*
+ *	Slave is already closing this port. This can happen if a hangup
+ *	occurs on this port.
+ */
+	if (wait) {
+		wait_event_interruptible_tty(portp->raw_wait,
+				!test_bit(ST_CLOSING, &portp->state));
+		if (signal_pending(current)) {
+			return -ERESTARTSYS;
+		}
+	}
+
+/*
+ *	Write the close command into shared memory.
+ */
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
+	writel(arg, &cp->closearg);
+	writeb(1, &cp->close);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
+		portp->portidx;
+	writeb(readb(bits) |portp->portbit, bits);
+	EBRDDISABLE(brdp);
+
+	set_bit(ST_CLOSING, &portp->state);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	if (wait == 0)
+		return 0;
+
+/*
+ *	Slave is in action, so now we must wait for the open acknowledgment
+ *	to come back.
+ */
+	rc = 0;
+	wait_event_interruptible_tty(portp->raw_wait,
+			!test_bit(ST_CLOSING, &portp->state));
+	if (signal_pending(current))
+		rc = -ERESTARTSYS;
+
+	if ((rc == 0) && (portp->rc != 0))
+		rc = -EIO;
+	return rc;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Send a command to the slave and wait for the response. This must
+ *	have user context (it sleeps). This routine is generic in that it
+ *	can send any type of command. Its purpose is to wait for that command
+ *	to complete (as opposed to initiating the command then returning).
+ */
+
+static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
+{
+	/*
+	 * no need for wait_event_tty because clearing ST_CMDING cannot block
+	 * on BTM
+	 */
+	wait_event_interruptible(portp->raw_wait,
+			!test_bit(ST_CMDING, &portp->state));
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+
+	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
+
+	wait_event_interruptible(portp->raw_wait,
+			!test_bit(ST_CMDING, &portp->state));
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+
+	if (portp->rc != 0)
+		return -EIO;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Send the termios settings for this port to the slave. This sleeps
+ *	waiting for the command to complete - so must have user context.
+ */
+
+static int stli_setport(struct tty_struct *tty)
+{
+	struct stliport *portp = tty->driver_data;
+	struct stlibrd *brdp;
+	asyport_t aport;
+
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr >= stli_nrbrds)
+		return -ENODEV;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return -ENODEV;
+
+	stli_mkasyport(tty, portp, &aport, tty->termios);
+	return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
+}
+
+/*****************************************************************************/
+
+static int stli_carrier_raised(struct tty_port *port)
+{
+	struct stliport *portp = container_of(port, struct stliport, port);
+	return (portp->sigs & TIOCM_CD) ? 1 : 0;
+}
+
+static void stli_dtr_rts(struct tty_port *port, int on)
+{
+	struct stliport *portp = container_of(port, struct stliport, port);
+	struct stlibrd *brdp = stli_brds[portp->brdnr];
+	stli_mkasysigs(&portp->asig, on, on);
+	if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+		sizeof(asysigs_t), 0) < 0)
+			printk(KERN_WARNING "istallion: dtr set failed.\n");
+}
+
+
+/*****************************************************************************/
+
+/*
+ *	Write routine. Take the data and put it in the shared memory ring
+ *	queue. If port is not already sending chars then need to mark the
+ *	service bits for this port.
+ */
+
+static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	cdkasy_t __iomem *ap;
+	cdkhdr_t __iomem *hdrp;
+	unsigned char __iomem *bits;
+	unsigned char __iomem *shbuf;
+	unsigned char *chbuf;
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	unsigned int len, stlen, head, tail, size;
+	unsigned long flags;
+
+	if (tty == stli_txcooktty)
+		stli_flushchars(tty);
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return 0;
+	if (portp->brdnr >= stli_nrbrds)
+		return 0;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return 0;
+	chbuf = (unsigned char *) buf;
+
+/*
+ *	All data is now local, shove as much as possible into shared memory.
+ */
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	head = (unsigned int) readw(&ap->txq.head);
+	tail = (unsigned int) readw(&ap->txq.tail);
+	if (tail != ((unsigned int) readw(&ap->txq.tail)))
+		tail = (unsigned int) readw(&ap->txq.tail);
+	size = portp->txsize;
+	if (head >= tail) {
+		len = size - (head - tail) - 1;
+		stlen = size - head;
+	} else {
+		len = tail - head - 1;
+		stlen = len;
+	}
+
+	len = min(len, (unsigned int)count);
+	count = 0;
+	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
+
+	while (len > 0) {
+		stlen = min(len, stlen);
+		memcpy_toio(shbuf + head, chbuf, stlen);
+		chbuf += stlen;
+		len -= stlen;
+		count += stlen;
+		head += stlen;
+		if (head >= size) {
+			head = 0;
+			stlen = tail;
+		}
+	}
+
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	writew(head, &ap->txq.head);
+	if (test_bit(ST_TXBUSY, &portp->state)) {
+		if (readl(&ap->changed.data) & DT_TXEMPTY)
+			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
+	}
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
+		portp->portidx;
+	writeb(readb(bits) | portp->portbit, bits);
+	set_bit(ST_TXBUSY, &portp->state);
+	EBRDDISABLE(brdp);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	return(count);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Output a single character. We put it into a temporary local buffer
+ *	(for speed) then write out that buffer when the flushchars routine
+ *	is called. There is a safety catch here so that if some other port
+ *	writes chars before the current buffer has been, then we write them
+ *	first them do the new ports.
+ */
+
+static int stli_putchar(struct tty_struct *tty, unsigned char ch)
+{
+	if (tty != stli_txcooktty) {
+		if (stli_txcooktty != NULL)
+			stli_flushchars(stli_txcooktty);
+		stli_txcooktty = tty;
+	}
+
+	stli_txcookbuf[stli_txcooksize++] = ch;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Transfer characters from the local TX cooking buffer to the board.
+ *	We sort of ignore the tty that gets passed in here. We rely on the
+ *	info stored with the TX cook buffer to tell us which port to flush
+ *	the data on. In any case we clean out the TX cook buffer, for re-use
+ *	by someone else.
+ */
+
+static void stli_flushchars(struct tty_struct *tty)
+{
+	cdkhdr_t __iomem *hdrp;
+	unsigned char __iomem *bits;
+	cdkasy_t __iomem *ap;
+	struct tty_struct *cooktty;
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	unsigned int len, stlen, head, tail, size, count, cooksize;
+	unsigned char *buf;
+	unsigned char __iomem *shbuf;
+	unsigned long flags;
+
+	cooksize = stli_txcooksize;
+	cooktty = stli_txcooktty;
+	stli_txcooksize = 0;
+	stli_txcookrealsize = 0;
+	stli_txcooktty = NULL;
+
+	if (cooktty == NULL)
+		return;
+	if (tty != cooktty)
+		tty = cooktty;
+	if (cooksize == 0)
+		return;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	if (portp->brdnr >= stli_nrbrds)
+		return;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	head = (unsigned int) readw(&ap->txq.head);
+	tail = (unsigned int) readw(&ap->txq.tail);
+	if (tail != ((unsigned int) readw(&ap->txq.tail)))
+		tail = (unsigned int) readw(&ap->txq.tail);
+	size = portp->txsize;
+	if (head >= tail) {
+		len = size - (head - tail) - 1;
+		stlen = size - head;
+	} else {
+		len = tail - head - 1;
+		stlen = len;
+	}
+
+	len = min(len, cooksize);
+	count = 0;
+	shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
+	buf = stli_txcookbuf;
+
+	while (len > 0) {
+		stlen = min(len, stlen);
+		memcpy_toio(shbuf + head, buf, stlen);
+		buf += stlen;
+		len -= stlen;
+		count += stlen;
+		head += stlen;
+		if (head >= size) {
+			head = 0;
+			stlen = tail;
+		}
+	}
+
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	writew(head, &ap->txq.head);
+
+	if (test_bit(ST_TXBUSY, &portp->state)) {
+		if (readl(&ap->changed.data) & DT_TXEMPTY)
+			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
+	}
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
+		portp->portidx;
+	writeb(readb(bits) | portp->portbit, bits);
+	set_bit(ST_TXBUSY, &portp->state);
+
+	EBRDDISABLE(brdp);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+static int stli_writeroom(struct tty_struct *tty)
+{
+	cdkasyrq_t __iomem *rp;
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	unsigned int head, tail, len;
+	unsigned long flags;
+
+	if (tty == stli_txcooktty) {
+		if (stli_txcookrealsize != 0) {
+			len = stli_txcookrealsize - stli_txcooksize;
+			return len;
+		}
+	}
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return 0;
+	if (portp->brdnr >= stli_nrbrds)
+		return 0;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return 0;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
+	head = (unsigned int) readw(&rp->head);
+	tail = (unsigned int) readw(&rp->tail);
+	if (tail != ((unsigned int) readw(&rp->tail)))
+		tail = (unsigned int) readw(&rp->tail);
+	len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head);
+	len--;
+	EBRDDISABLE(brdp);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	if (tty == stli_txcooktty) {
+		stli_txcookrealsize = len;
+		len -= stli_txcooksize;
+	}
+	return len;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the number of characters in the transmit buffer. Normally we
+ *	will return the number of chars in the shared memory ring queue.
+ *	We need to kludge around the case where the shared memory buffer is
+ *	empty but not all characters have drained yet, for this case just
+ *	return that there is 1 character in the buffer!
+ */
+
+static int stli_charsinbuffer(struct tty_struct *tty)
+{
+	cdkasyrq_t __iomem *rp;
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	unsigned int head, tail, len;
+	unsigned long flags;
+
+	if (tty == stli_txcooktty)
+		stli_flushchars(tty);
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return 0;
+	if (portp->brdnr >= stli_nrbrds)
+		return 0;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return 0;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
+	head = (unsigned int) readw(&rp->head);
+	tail = (unsigned int) readw(&rp->tail);
+	if (tail != ((unsigned int) readw(&rp->tail)))
+		tail = (unsigned int) readw(&rp->tail);
+	len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head));
+	if ((len == 0) && test_bit(ST_TXBUSY, &portp->state))
+		len = 1;
+	EBRDDISABLE(brdp);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	return len;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Generate the serial struct info.
+ */
+
+static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
+{
+	struct serial_struct sio;
+	struct stlibrd *brdp;
+
+	memset(&sio, 0, sizeof(struct serial_struct));
+	sio.type = PORT_UNKNOWN;
+	sio.line = portp->portnr;
+	sio.irq = 0;
+	sio.flags = portp->port.flags;
+	sio.baud_base = portp->baud_base;
+	sio.close_delay = portp->port.close_delay;
+	sio.closing_wait = portp->closing_wait;
+	sio.custom_divisor = portp->custom_divisor;
+	sio.xmit_fifo_size = 0;
+	sio.hub6 = 0;
+
+	brdp = stli_brds[portp->brdnr];
+	if (brdp != NULL)
+		sio.port = brdp->iobase;
+		
+	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ?
+			-EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set port according to the serial struct info.
+ *	At this point we do not do any auto-configure stuff, so we will
+ *	just quietly ignore any requests to change irq, etc.
+ */
+
+static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
+{
+	struct serial_struct sio;
+	int rc;
+	struct stliport *portp = tty->driver_data;
+
+	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
+		return -EFAULT;
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((sio.baud_base != portp->baud_base) ||
+		    (sio.close_delay != portp->port.close_delay) ||
+		    ((sio.flags & ~ASYNC_USR_MASK) !=
+		    (portp->port.flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+	} 
+
+	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
+		(sio.flags & ASYNC_USR_MASK);
+	portp->baud_base = sio.baud_base;
+	portp->port.close_delay = sio.close_delay;
+	portp->closing_wait = sio.closing_wait;
+	portp->custom_divisor = sio.custom_divisor;
+
+	if ((rc = stli_setport(tty)) < 0)
+		return rc;
+	return 0;
+}
+
+/*****************************************************************************/
+
+static int stli_tiocmget(struct tty_struct *tty)
+{
+	struct stliport *portp = tty->driver_data;
+	struct stlibrd *brdp;
+	int rc;
+
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr >= stli_nrbrds)
+		return 0;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return 0;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
+			       &portp->asig, sizeof(asysigs_t), 1)) < 0)
+		return rc;
+
+	return stli_mktiocm(portp->asig.sigvalue);
+}
+
+static int stli_tiocmset(struct tty_struct *tty,
+			 unsigned int set, unsigned int clear)
+{
+	struct stliport *portp = tty->driver_data;
+	struct stlibrd *brdp;
+	int rts = -1, dtr = -1;
+
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr >= stli_nrbrds)
+		return 0;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return 0;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	stli_mkasysigs(&portp->asig, dtr, rts);
+
+	return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+			    sizeof(asysigs_t), 0);
+}
+
+static int stli_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
+{
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	int rc;
+	void __user *argp = (void __user *)arg;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr >= stli_nrbrds)
+		return 0;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return 0;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+			return -EIO;
+	}
+
+	rc = 0;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		rc = stli_getserial(portp, argp);
+		break;
+	case TIOCSSERIAL:
+		rc = stli_setserial(tty, argp);
+		break;
+	case STL_GETPFLAG:
+		rc = put_user(portp->pflag, (unsigned __user *)argp);
+		break;
+	case STL_SETPFLAG:
+		if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
+			stli_setport(tty);
+		break;
+	case COM_GETPORTSTATS:
+		rc = stli_getportstats(tty, portp, argp);
+		break;
+	case COM_CLRPORTSTATS:
+		rc = stli_clrportstats(portp, argp);
+		break;
+	case TIOCSERCONFIG:
+	case TIOCSERGWILD:
+	case TIOCSERSWILD:
+	case TIOCSERGETLSR:
+	case TIOCSERGSTRUCT:
+	case TIOCSERGETMULTI:
+	case TIOCSERSETMULTI:
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+
+	return rc;
+}
+
+/*****************************************************************************/
+
+/*
+ *	This routine assumes that we have user context and can sleep.
+ *	Looks like it is true for the current ttys implementation..!!
+ */
+
+static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
+{
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	struct ktermios *tiosp;
+	asyport_t aport;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	if (portp->brdnr >= stli_nrbrds)
+		return;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+	tiosp = tty->termios;
+
+	stli_mkasyport(tty, portp, &aport, tiosp);
+	stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
+	stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
+	stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
+		sizeof(asysigs_t), 0);
+	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0))
+		tty->hw_stopped = 0;
+	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
+		wake_up_interruptible(&portp->port.open_wait);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Attempt to flow control who ever is sending us data. We won't really
+ *	do any flow control action here. We can't directly, and even if we
+ *	wanted to we would have to send a command to the slave. The slave
+ *	knows how to flow control, and will do so when its buffers reach its
+ *	internal high water marks. So what we will do is set a local state
+ *	bit that will stop us sending any RX data up from the poll routine
+ *	(which is the place where RX data from the slave is handled).
+ */
+
+static void stli_throttle(struct tty_struct *tty)
+{
+	struct stliport	*portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	set_bit(ST_RXSTOP, &portp->state);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Unflow control the device sending us data... That means that all
+ *	we have to do is clear the RXSTOP state bit. The next poll call
+ *	will then be able to pass the RX data back up.
+ */
+
+static void stli_unthrottle(struct tty_struct *tty)
+{
+	struct stliport	*portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	clear_bit(ST_RXSTOP, &portp->state);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Stop the transmitter.
+ */
+
+static void stli_stop(struct tty_struct *tty)
+{
+}
+
+/*****************************************************************************/
+
+/*
+ *	Start the transmitter again.
+ */
+
+static void stli_start(struct tty_struct *tty)
+{
+}
+
+/*****************************************************************************/
+
+
+/*
+ *	Hangup this port. This is pretty much like closing the port, only
+ *	a little more brutal. No waiting for data to drain. Shutdown the
+ *	port and maybe drop signals. This is rather tricky really. We want
+ *	to close the port as well.
+ */
+
+static void stli_hangup(struct tty_struct *tty)
+{
+	struct stliport *portp = tty->driver_data;
+	tty_port_hangup(&portp->port);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Flush characters from the lower buffer. We may not have user context
+ *	so we cannot sleep waiting for it to complete. Also we need to check
+ *	if there is chars for this port in the TX cook buffer, and flush them
+ *	as well.
+ */
+
+static void stli_flushbuffer(struct tty_struct *tty)
+{
+	struct stliport *portp;
+	struct stlibrd *brdp;
+	unsigned long ftype, flags;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	if (portp->brdnr >= stli_nrbrds)
+		return;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	if (tty == stli_txcooktty) {
+		stli_txcooktty = NULL;
+		stli_txcooksize = 0;
+		stli_txcookrealsize = 0;
+	}
+	if (test_bit(ST_CMDING, &portp->state)) {
+		set_bit(ST_DOFLUSHTX, &portp->state);
+	} else {
+		ftype = FLUSHTX;
+		if (test_bit(ST_DOFLUSHRX, &portp->state)) {
+			ftype |= FLUSHRX;
+			clear_bit(ST_DOFLUSHRX, &portp->state);
+		}
+		__stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
+	}
+	spin_unlock_irqrestore(&brd_lock, flags);
+	tty_wakeup(tty);
+}
+
+/*****************************************************************************/
+
+static int stli_breakctl(struct tty_struct *tty, int state)
+{
+	struct stlibrd	*brdp;
+	struct stliport	*portp;
+	long		arg;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -EINVAL;
+	if (portp->brdnr >= stli_nrbrds)
+		return -EINVAL;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return -EINVAL;
+
+	arg = (state == -1) ? BREAKON : BREAKOFF;
+	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
+	return 0;
+}
+
+/*****************************************************************************/
+
+static void stli_waituntilsent(struct tty_struct *tty, int timeout)
+{
+	struct stliport *portp;
+	unsigned long tend;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+
+	if (timeout == 0)
+		timeout = HZ;
+	tend = jiffies + timeout;
+
+	while (test_bit(ST_TXBUSY, &portp->state)) {
+		if (signal_pending(current))
+			break;
+		msleep_interruptible(20);
+		if (time_after_eq(jiffies, tend))
+			break;
+	}
+}
+
+/*****************************************************************************/
+
+static void stli_sendxchar(struct tty_struct *tty, char ch)
+{
+	struct stlibrd	*brdp;
+	struct stliport	*portp;
+	asyctrl_t	actrl;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	if (portp->brdnr >= stli_nrbrds)
+		return;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+	memset(&actrl, 0, sizeof(asyctrl_t));
+	if (ch == STOP_CHAR(tty)) {
+		actrl.rxctrl = CT_STOPFLOW;
+	} else if (ch == START_CHAR(tty)) {
+		actrl.rxctrl = CT_STARTFLOW;
+	} else {
+		actrl.txctrl = CT_SENDCHR;
+		actrl.tximdch = ch;
+	}
+	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
+}
+
+static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr)
+{
+	char *uart;
+	int rc;
+
+	rc = stli_portcmdstats(NULL, portp);
+
+	uart = "UNKNOWN";
+	if (test_bit(BST_STARTED, &brdp->state)) {
+		switch (stli_comstats.hwid) {
+		case 0:	uart = "2681"; break;
+		case 1:	uart = "SC26198"; break;
+		default:uart = "CD1400"; break;
+		}
+	}
+	seq_printf(m, "%d: uart:%s ", portnr, uart);
+
+	if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) {
+		char sep;
+
+		seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
+			(int) stli_comstats.rxtotal);
+
+		if (stli_comstats.rxframing)
+			seq_printf(m, " fe:%d",
+				(int) stli_comstats.rxframing);
+		if (stli_comstats.rxparity)
+			seq_printf(m, " pe:%d",
+				(int) stli_comstats.rxparity);
+		if (stli_comstats.rxbreaks)
+			seq_printf(m, " brk:%d",
+				(int) stli_comstats.rxbreaks);
+		if (stli_comstats.rxoverrun)
+			seq_printf(m, " oe:%d",
+				(int) stli_comstats.rxoverrun);
+
+		sep = ' ';
+		if (stli_comstats.signals & TIOCM_RTS) {
+			seq_printf(m, "%c%s", sep, "RTS");
+			sep = '|';
+		}
+		if (stli_comstats.signals & TIOCM_CTS) {
+			seq_printf(m, "%c%s", sep, "CTS");
+			sep = '|';
+		}
+		if (stli_comstats.signals & TIOCM_DTR) {
+			seq_printf(m, "%c%s", sep, "DTR");
+			sep = '|';
+		}
+		if (stli_comstats.signals & TIOCM_CD) {
+			seq_printf(m, "%c%s", sep, "DCD");
+			sep = '|';
+		}
+		if (stli_comstats.signals & TIOCM_DSR) {
+			seq_printf(m, "%c%s", sep, "DSR");
+			sep = '|';
+		}
+	}
+	seq_putc(m, '\n');
+}
+
+/*****************************************************************************/
+
+/*
+ *	Port info, read from the /proc file system.
+ */
+
+static int stli_proc_show(struct seq_file *m, void *v)
+{
+	struct stlibrd *brdp;
+	struct stliport *portp;
+	unsigned int brdnr, portnr, totalport;
+
+	totalport = 0;
+
+	seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion);
+
+/*
+ *	We scan through for each board, panel and port. The offset is
+ *	calculated on the fly, and irrelevant ports are skipped.
+ */
+	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
+		brdp = stli_brds[brdnr];
+		if (brdp == NULL)
+			continue;
+		if (brdp->state == 0)
+			continue;
+
+		totalport = brdnr * STL_MAXPORTS;
+		for (portnr = 0; (portnr < brdp->nrports); portnr++,
+		    totalport++) {
+			portp = brdp->ports[portnr];
+			if (portp == NULL)
+				continue;
+			stli_portinfo(m, brdp, portp, totalport);
+		}
+	}
+	return 0;
+}
+
+static int stli_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stli_proc_show, NULL);
+}
+
+static const struct file_operations stli_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= stli_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*****************************************************************************/
+
+/*
+ *	Generic send command routine. This will send a message to the slave,
+ *	of the specified type with the specified argument. Must be very
+ *	careful of data that will be copied out from shared memory -
+ *	containing command results. The command completion is all done from
+ *	a poll routine that does not have user context. Therefore you cannot
+ *	copy back directly into user space, or to the kernel stack of a
+ *	process. This routine does not sleep, so can be called from anywhere.
+ *
+ *	The caller must hold the brd_lock (see also stli_sendcmd the usual
+ *	entry point)
+ */
+
+static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
+{
+	cdkhdr_t __iomem *hdrp;
+	cdkctrl_t __iomem *cp;
+	unsigned char __iomem *bits;
+
+	if (test_bit(ST_CMDING, &portp->state)) {
+		printk(KERN_ERR "istallion: command already busy, cmd=%x!\n",
+				(int) cmd);
+		return;
+	}
+
+	EBRDENABLE(brdp);
+	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
+	if (size > 0) {
+		memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);
+		if (copyback) {
+			portp->argp = arg;
+			portp->argsize = size;
+		}
+	}
+	writel(0, &cp->status);
+	writel(cmd, &cp->cmd);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
+		portp->portidx;
+	writeb(readb(bits) | portp->portbit, bits);
+	set_bit(ST_CMDING, &portp->state);
+	EBRDDISABLE(brdp);
+}
+
+static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
+{
+	unsigned long		flags;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	__stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Read data from shared memory. This assumes that the shared memory
+ *	is enabled and that interrupts are off. Basically we just empty out
+ *	the shared memory buffer into the tty buffer. Must be careful to
+ *	handle the case where we fill up the tty buffer, but still have
+ *	more chars to unload.
+ */
+
+static void stli_read(struct stlibrd *brdp, struct stliport *portp)
+{
+	cdkasyrq_t __iomem *rp;
+	char __iomem *shbuf;
+	struct tty_struct	*tty;
+	unsigned int head, tail, size;
+	unsigned int len, stlen;
+
+	if (test_bit(ST_RXSTOP, &portp->state))
+		return;
+	tty = tty_port_tty_get(&portp->port);
+	if (tty == NULL)
+		return;
+
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
+	head = (unsigned int) readw(&rp->head);
+	if (head != ((unsigned int) readw(&rp->head)))
+		head = (unsigned int) readw(&rp->head);
+	tail = (unsigned int) readw(&rp->tail);
+	size = portp->rxsize;
+	if (head >= tail) {
+		len = head - tail;
+		stlen = len;
+	} else {
+		len = size - (tail - head);
+		stlen = size - tail;
+	}
+
+	len = tty_buffer_request_room(tty, len);
+
+	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);
+
+	while (len > 0) {
+		unsigned char *cptr;
+
+		stlen = min(len, stlen);
+		tty_prepare_flip_string(tty, &cptr, stlen);
+		memcpy_fromio(cptr, shbuf + tail, stlen);
+		len -= stlen;
+		tail += stlen;
+		if (tail >= size) {
+			tail = 0;
+			stlen = head;
+		}
+	}
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
+	writew(tail, &rp->tail);
+
+	if (head != tail)
+		set_bit(ST_RXING, &portp->state);
+
+	tty_schedule_flip(tty);
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set up and carry out any delayed commands. There is only a small set
+ *	of slave commands that can be done "off-level". So it is not too
+ *	difficult to deal with them here.
+ */
+
+static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
+{
+	int cmd;
+
+	if (test_bit(ST_DOSIGS, &portp->state)) {
+		if (test_bit(ST_DOFLUSHTX, &portp->state) &&
+		    test_bit(ST_DOFLUSHRX, &portp->state))
+			cmd = A_SETSIGNALSF;
+		else if (test_bit(ST_DOFLUSHTX, &portp->state))
+			cmd = A_SETSIGNALSFTX;
+		else if (test_bit(ST_DOFLUSHRX, &portp->state))
+			cmd = A_SETSIGNALSFRX;
+		else
+			cmd = A_SETSIGNALS;
+		clear_bit(ST_DOFLUSHTX, &portp->state);
+		clear_bit(ST_DOFLUSHRX, &portp->state);
+		clear_bit(ST_DOSIGS, &portp->state);
+		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,
+			sizeof(asysigs_t));
+		writel(0, &cp->status);
+		writel(cmd, &cp->cmd);
+		set_bit(ST_CMDING, &portp->state);
+	} else if (test_bit(ST_DOFLUSHTX, &portp->state) ||
+	    test_bit(ST_DOFLUSHRX, &portp->state)) {
+		cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0);
+		cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);
+		clear_bit(ST_DOFLUSHTX, &portp->state);
+		clear_bit(ST_DOFLUSHRX, &portp->state);
+		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int));
+		writel(0, &cp->status);
+		writel(A_FLUSH, &cp->cmd);
+		set_bit(ST_CMDING, &portp->state);
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Host command service checking. This handles commands or messages
+ *	coming from the slave to the host. Must have board shared memory
+ *	enabled and interrupts off when called. Notice that by servicing the
+ *	read data last we don't need to change the shared memory pointer
+ *	during processing (which is a slow IO operation).
+ *	Return value indicates if this port is still awaiting actions from
+ *	the slave (like open, command, or even TX data being sent). If 0
+ *	then port is still busy, otherwise no longer busy.
+ */
+
+static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
+{
+	cdkasy_t __iomem *ap;
+	cdkctrl_t __iomem *cp;
+	struct tty_struct *tty;
+	asynotify_t nt;
+	unsigned long oldsigs;
+	int rc, donerx;
+
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	cp = &ap->ctrl;
+
+/*
+ *	Check if we are waiting for an open completion message.
+ */
+	if (test_bit(ST_OPENING, &portp->state)) {
+		rc = readl(&cp->openarg);
+		if (readb(&cp->open) == 0 && rc != 0) {
+			if (rc > 0)
+				rc--;
+			writel(0, &cp->openarg);
+			portp->rc = rc;
+			clear_bit(ST_OPENING, &portp->state);
+			wake_up_interruptible(&portp->raw_wait);
+		}
+	}
+
+/*
+ *	Check if we are waiting for a close completion message.
+ */
+	if (test_bit(ST_CLOSING, &portp->state)) {
+		rc = (int) readl(&cp->closearg);
+		if (readb(&cp->close) == 0 && rc != 0) {
+			if (rc > 0)
+				rc--;
+			writel(0, &cp->closearg);
+			portp->rc = rc;
+			clear_bit(ST_CLOSING, &portp->state);
+			wake_up_interruptible(&portp->raw_wait);
+		}
+	}
+
+/*
+ *	Check if we are waiting for a command completion message. We may
+ *	need to copy out the command results associated with this command.
+ */
+	if (test_bit(ST_CMDING, &portp->state)) {
+		rc = readl(&cp->status);
+		if (readl(&cp->cmd) == 0 && rc != 0) {
+			if (rc > 0)
+				rc--;
+			if (portp->argp != NULL) {
+				memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]),
+					portp->argsize);
+				portp->argp = NULL;
+			}
+			writel(0, &cp->status);
+			portp->rc = rc;
+			clear_bit(ST_CMDING, &portp->state);
+			stli_dodelaycmd(portp, cp);
+			wake_up_interruptible(&portp->raw_wait);
+		}
+	}
+
+/*
+ *	Check for any notification messages ready. This includes lots of
+ *	different types of events - RX chars ready, RX break received,
+ *	TX data low or empty in the slave, modem signals changed state.
+ */
+	donerx = 0;
+
+	if (ap->notify) {
+		nt = ap->changed;
+		ap->notify = 0;
+		tty = tty_port_tty_get(&portp->port);
+
+		if (nt.signal & SG_DCD) {
+			oldsigs = portp->sigs;
+			portp->sigs = stli_mktiocm(nt.sigvalue);
+			clear_bit(ST_GETSIGS, &portp->state);
+			if ((portp->sigs & TIOCM_CD) &&
+			    ((oldsigs & TIOCM_CD) == 0))
+				wake_up_interruptible(&portp->port.open_wait);
+			if ((oldsigs & TIOCM_CD) &&
+			    ((portp->sigs & TIOCM_CD) == 0)) {
+				if (portp->port.flags & ASYNC_CHECK_CD) {
+					if (tty)
+						tty_hangup(tty);
+				}
+			}
+		}
+
+		if (nt.data & DT_TXEMPTY)
+			clear_bit(ST_TXBUSY, &portp->state);
+		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
+			if (tty != NULL) {
+				tty_wakeup(tty);
+				EBRDENABLE(brdp);
+			}
+		}
+
+		if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
+			if (tty != NULL) {
+				tty_insert_flip_char(tty, 0, TTY_BREAK);
+				if (portp->port.flags & ASYNC_SAK) {
+					do_SAK(tty);
+					EBRDENABLE(brdp);
+				}
+				tty_schedule_flip(tty);
+			}
+		}
+		tty_kref_put(tty);
+
+		if (nt.data & DT_RXBUSY) {
+			donerx++;
+			stli_read(brdp, portp);
+		}
+	}
+
+/*
+ *	It might seem odd that we are checking for more RX chars here.
+ *	But, we need to handle the case where the tty buffer was previously
+ *	filled, but we had more characters to pass up. The slave will not
+ *	send any more RX notify messages until the RX buffer has been emptied.
+ *	But it will leave the service bits on (since the buffer is not empty).
+ *	So from here we can try to process more RX chars.
+ */
+	if ((!donerx) && test_bit(ST_RXING, &portp->state)) {
+		clear_bit(ST_RXING, &portp->state);
+		stli_read(brdp, portp);
+	}
+
+	return((test_bit(ST_OPENING, &portp->state) ||
+		test_bit(ST_CLOSING, &portp->state) ||
+		test_bit(ST_CMDING, &portp->state) ||
+		test_bit(ST_TXBUSY, &portp->state) ||
+		test_bit(ST_RXING, &portp->state)) ? 0 : 1);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Service all ports on a particular board. Assumes that the boards
+ *	shared memory is enabled, and that the page pointer is pointed
+ *	at the cdk header structure.
+ */
+
+static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
+{
+	struct stliport *portp;
+	unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
+	unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
+	unsigned char __iomem *slavep;
+	int bitpos, bitat, bitsize;
+	int channr, nrdevs, slavebitchange;
+
+	bitsize = brdp->bitsize;
+	nrdevs = brdp->nrdevs;
+
+/*
+ *	Check if slave wants any service. Basically we try to do as
+ *	little work as possible here. There are 2 levels of service
+ *	bits. So if there is nothing to do we bail early. We check
+ *	8 service bits at a time in the inner loop, so we can bypass
+ *	the lot if none of them want service.
+ */
+	memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset),
+		bitsize);
+
+	memset(&slavebits[0], 0, bitsize);
+	slavebitchange = 0;
+
+	for (bitpos = 0; (bitpos < bitsize); bitpos++) {
+		if (hostbits[bitpos] == 0)
+			continue;
+		channr = bitpos * 8;
+		for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) {
+			if (hostbits[bitpos] & bitat) {
+				portp = brdp->ports[(channr - 1)];
+				if (stli_hostcmd(brdp, portp)) {
+					slavebitchange++;
+					slavebits[bitpos] |= bitat;
+				}
+			}
+		}
+	}
+
+/*
+ *	If any of the ports are no longer busy then update them in the
+ *	slave request bits. We need to do this after, since a host port
+ *	service may initiate more slave requests.
+ */
+	if (slavebitchange) {
+		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+		slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset;
+		for (bitpos = 0; (bitpos < bitsize); bitpos++) {
+			if (readb(slavebits + bitpos))
+				writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos);
+		}
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Driver poll routine. This routine polls the boards in use and passes
+ *	messages back up to host when necessary. This is actually very
+ *	CPU efficient, since we will always have the kernel poll clock, it
+ *	adds only a few cycles when idle (since board service can be
+ *	determined very easily), but when loaded generates no interrupts
+ *	(with their expensive associated context change).
+ */
+
+static void stli_poll(unsigned long arg)
+{
+	cdkhdr_t __iomem *hdrp;
+	struct stlibrd *brdp;
+	unsigned int brdnr;
+
+	mod_timer(&stli_timerlist, STLI_TIMEOUT);
+
+/*
+ *	Check each board and do any servicing required.
+ */
+	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
+		brdp = stli_brds[brdnr];
+		if (brdp == NULL)
+			continue;
+		if (!test_bit(BST_STARTED, &brdp->state))
+			continue;
+
+		spin_lock(&brd_lock);
+		EBRDENABLE(brdp);
+		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+		if (readb(&hdrp->hostreq))
+			stli_brdpoll(brdp, hdrp);
+		EBRDDISABLE(brdp);
+		spin_unlock(&brd_lock);
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Translate the termios settings into the port setting structure of
+ *	the slave.
+ */
+
+static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
+				asyport_t *pp, struct ktermios *tiosp)
+{
+	memset(pp, 0, sizeof(asyport_t));
+
+/*
+ *	Start of by setting the baud, char size, parity and stop bit info.
+ */
+	pp->baudout = tty_get_baud_rate(tty);
+	if ((tiosp->c_cflag & CBAUD) == B38400) {
+		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			pp->baudout = 57600;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			pp->baudout = 115200;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			pp->baudout = 230400;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			pp->baudout = 460800;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
+			pp->baudout = (portp->baud_base / portp->custom_divisor);
+	}
+	if (pp->baudout > STL_MAXBAUD)
+		pp->baudout = STL_MAXBAUD;
+	pp->baudin = pp->baudout;
+
+	switch (tiosp->c_cflag & CSIZE) {
+	case CS5:
+		pp->csize = 5;
+		break;
+	case CS6:
+		pp->csize = 6;
+		break;
+	case CS7:
+		pp->csize = 7;
+		break;
+	default:
+		pp->csize = 8;
+		break;
+	}
+
+	if (tiosp->c_cflag & CSTOPB)
+		pp->stopbs = PT_STOP2;
+	else
+		pp->stopbs = PT_STOP1;
+
+	if (tiosp->c_cflag & PARENB) {
+		if (tiosp->c_cflag & PARODD)
+			pp->parity = PT_ODDPARITY;
+		else
+			pp->parity = PT_EVENPARITY;
+	} else {
+		pp->parity = PT_NOPARITY;
+	}
+
+/*
+ *	Set up any flow control options enabled.
+ */
+	if (tiosp->c_iflag & IXON) {
+		pp->flow |= F_IXON;
+		if (tiosp->c_iflag & IXANY)
+			pp->flow |= F_IXANY;
+	}
+	if (tiosp->c_cflag & CRTSCTS)
+		pp->flow |= (F_RTSFLOW | F_CTSFLOW);
+
+	pp->startin = tiosp->c_cc[VSTART];
+	pp->stopin = tiosp->c_cc[VSTOP];
+	pp->startout = tiosp->c_cc[VSTART];
+	pp->stopout = tiosp->c_cc[VSTOP];
+
+/*
+ *	Set up the RX char marking mask with those RX error types we must
+ *	catch. We can get the slave to help us out a little here, it will
+ *	ignore parity errors and breaks for us, and mark parity errors in
+ *	the data stream.
+ */
+	if (tiosp->c_iflag & IGNPAR)
+		pp->iflag |= FI_IGNRXERRS;
+	if (tiosp->c_iflag & IGNBRK)
+		pp->iflag |= FI_IGNBREAK;
+
+	portp->rxmarkmsk = 0;
+	if (tiosp->c_iflag & (INPCK | PARMRK))
+		pp->iflag |= FI_1MARKRXERRS;
+	if (tiosp->c_iflag & BRKINT)
+		portp->rxmarkmsk |= BRKINT;
+
+/*
+ *	Set up clocal processing as required.
+ */
+	if (tiosp->c_cflag & CLOCAL)
+		portp->port.flags &= ~ASYNC_CHECK_CD;
+	else
+		portp->port.flags |= ASYNC_CHECK_CD;
+
+/*
+ *	Transfer any persistent flags into the asyport structure.
+ */
+	pp->pflag = (portp->pflag & 0xffff);
+	pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0;
+	pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0;
+	pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Construct a slave signals structure for setting the DTR and RTS
+ *	signals as specified.
+ */
+
+static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
+{
+	memset(sp, 0, sizeof(asysigs_t));
+	if (dtr >= 0) {
+		sp->signal |= SG_DTR;
+		sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
+	}
+	if (rts >= 0) {
+		sp->signal |= SG_RTS;
+		sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Convert the signals returned from the slave into a local TIOCM type
+ *	signals value. We keep them locally in TIOCM format.
+ */
+
+static long stli_mktiocm(unsigned long sigvalue)
+{
+	long	tiocm = 0;
+	tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
+	tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
+	tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
+	tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
+	tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
+	tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
+	return(tiocm);
+}
+
+/*****************************************************************************/
+
+/*
+ *	All panels and ports actually attached have been worked out. All
+ *	we need to do here is set up the appropriate per port data structures.
+ */
+
+static int stli_initports(struct stlibrd *brdp)
+{
+	struct stliport	*portp;
+	unsigned int i, panelnr, panelport;
+
+	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
+		portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
+		if (!portp) {
+			printk(KERN_WARNING "istallion: failed to allocate port structure\n");
+			continue;
+		}
+		tty_port_init(&portp->port);
+		portp->port.ops = &stli_port_ops;
+		portp->magic = STLI_PORTMAGIC;
+		portp->portnr = i;
+		portp->brdnr = brdp->brdnr;
+		portp->panelnr = panelnr;
+		portp->baud_base = STL_BAUDBASE;
+		portp->port.close_delay = STL_CLOSEDELAY;
+		portp->closing_wait = 30 * HZ;
+		init_waitqueue_head(&portp->port.open_wait);
+		init_waitqueue_head(&portp->port.close_wait);
+		init_waitqueue_head(&portp->raw_wait);
+		panelport++;
+		if (panelport >= brdp->panels[panelnr]) {
+			panelport = 0;
+			panelnr++;
+		}
+		brdp->ports[i] = portp;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	All the following routines are board specific hardware operations.
+ */
+
+static void stli_ecpinit(struct stlibrd *brdp)
+{
+	unsigned long	memconf;
+
+	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
+	udelay(10);
+	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
+	udelay(100);
+
+	memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
+	outb(memconf, (brdp->iobase + ECP_ATMEMAR));
+}
+
+/*****************************************************************************/
+
+static void stli_ecpenable(struct stlibrd *brdp)
+{	
+	outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
+}
+
+/*****************************************************************************/
+
+static void stli_ecpdisable(struct stlibrd *brdp)
+{	
+	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+	unsigned char val;
+
+	if (offset > brdp->memsize) {
+		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
+		ptr = NULL;
+		val = 0;
+	} else {
+		ptr = brdp->membase + (offset % ECP_ATPAGESIZE);
+		val = (unsigned char) (offset / ECP_ATPAGESIZE);
+	}
+	outb(val, (brdp->iobase + ECP_ATMEMPR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_ecpreset(struct stlibrd *brdp)
+{	
+	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
+	udelay(10);
+	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+static void stli_ecpintr(struct stlibrd *brdp)
+{	
+	outb(0x1, brdp->iobase);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following set of functions act on ECP EISA boards.
+ */
+
+static void stli_ecpeiinit(struct stlibrd *brdp)
+{
+	unsigned long	memconf;
+
+	outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
+	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
+	udelay(10);
+	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
+	udelay(500);
+
+	memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
+	outb(memconf, (brdp->iobase + ECP_EIMEMARL));
+	memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
+	outb(memconf, (brdp->iobase + ECP_EIMEMARH));
+}
+
+/*****************************************************************************/
+
+static void stli_ecpeienable(struct stlibrd *brdp)
+{	
+	outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
+}
+
+/*****************************************************************************/
+
+static void stli_ecpeidisable(struct stlibrd *brdp)
+{	
+	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+	unsigned char	val;
+
+	if (offset > brdp->memsize) {
+		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
+		ptr = NULL;
+		val = 0;
+	} else {
+		ptr = brdp->membase + (offset % ECP_EIPAGESIZE);
+		if (offset < ECP_EIPAGESIZE)
+			val = ECP_EIENABLE;
+		else
+			val = ECP_EIENABLE | 0x40;
+	}
+	outb(val, (brdp->iobase + ECP_EICONFR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_ecpeireset(struct stlibrd *brdp)
+{	
+	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
+	udelay(10);
+	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following set of functions act on ECP MCA boards.
+ */
+
+static void stli_ecpmcenable(struct stlibrd *brdp)
+{	
+	outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
+}
+
+/*****************************************************************************/
+
+static void stli_ecpmcdisable(struct stlibrd *brdp)
+{	
+	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+	unsigned char val;
+
+	if (offset > brdp->memsize) {
+		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
+		ptr = NULL;
+		val = 0;
+	} else {
+		ptr = brdp->membase + (offset % ECP_MCPAGESIZE);
+		val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
+	}
+	outb(val, (brdp->iobase + ECP_MCCONFR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_ecpmcreset(struct stlibrd *brdp)
+{	
+	outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
+	udelay(10);
+	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following set of functions act on ECP PCI boards.
+ */
+
+static void stli_ecppciinit(struct stlibrd *brdp)
+{
+	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
+	udelay(10);
+	outb(0, (brdp->iobase + ECP_PCICONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+	unsigned char	val;
+
+	if (offset > brdp->memsize) {
+		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
+				"range at line=%d(%d), board=%d\n",
+				(int) offset, line, __LINE__, brdp->brdnr);
+		ptr = NULL;
+		val = 0;
+	} else {
+		ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
+		val = (offset / ECP_PCIPAGESIZE) << 1;
+	}
+	outb(val, (brdp->iobase + ECP_PCICONFR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_ecppcireset(struct stlibrd *brdp)
+{	
+	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
+	udelay(10);
+	outb(0, (brdp->iobase + ECP_PCICONFR));
+	udelay(500);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following routines act on ONboards.
+ */
+
+static void stli_onbinit(struct stlibrd *brdp)
+{
+	unsigned long	memconf;
+
+	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
+	udelay(10);
+	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
+	mdelay(1000);
+
+	memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
+	outb(memconf, (brdp->iobase + ONB_ATMEMAR));
+	outb(0x1, brdp->iobase);
+	mdelay(1);
+}
+
+/*****************************************************************************/
+
+static void stli_onbenable(struct stlibrd *brdp)
+{	
+	outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
+}
+
+/*****************************************************************************/
+
+static void stli_onbdisable(struct stlibrd *brdp)
+{	
+	outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+
+	if (offset > brdp->memsize) {
+		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+				(int) offset, line, __LINE__, brdp->brdnr);
+		ptr = NULL;
+	} else {
+		ptr = brdp->membase + (offset % ONB_ATPAGESIZE);
+	}
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_onbreset(struct stlibrd *brdp)
+{	
+	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
+	udelay(10);
+	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
+	mdelay(1000);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following routines act on ONboard EISA.
+ */
+
+static void stli_onbeinit(struct stlibrd *brdp)
+{
+	unsigned long	memconf;
+
+	outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
+	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
+	udelay(10);
+	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
+	mdelay(1000);
+
+	memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
+	outb(memconf, (brdp->iobase + ONB_EIMEMARL));
+	memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
+	outb(memconf, (brdp->iobase + ONB_EIMEMARH));
+	outb(0x1, brdp->iobase);
+	mdelay(1);
+}
+
+/*****************************************************************************/
+
+static void stli_onbeenable(struct stlibrd *brdp)
+{	
+	outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
+}
+
+/*****************************************************************************/
+
+static void stli_onbedisable(struct stlibrd *brdp)
+{	
+	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+	unsigned char val;
+
+	if (offset > brdp->memsize) {
+		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
+				"range at line=%d(%d), brd=%d\n",
+			(int) offset, line, __LINE__, brdp->brdnr);
+		ptr = NULL;
+		val = 0;
+	} else {
+		ptr = brdp->membase + (offset % ONB_EIPAGESIZE);
+		if (offset < ONB_EIPAGESIZE)
+			val = ONB_EIENABLE;
+		else
+			val = ONB_EIENABLE | 0x40;
+	}
+	outb(val, (brdp->iobase + ONB_EICONFR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_onbereset(struct stlibrd *brdp)
+{	
+	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
+	udelay(10);
+	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
+	mdelay(1000);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following routines act on Brumby boards.
+ */
+
+static void stli_bbyinit(struct stlibrd *brdp)
+{
+	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
+	udelay(10);
+	outb(0, (brdp->iobase + BBY_ATCONFR));
+	mdelay(1000);
+	outb(0x1, brdp->iobase);
+	mdelay(1);
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	void __iomem *ptr;
+	unsigned char val;
+
+	BUG_ON(offset > brdp->memsize);
+
+	ptr = brdp->membase + (offset % BBY_PAGESIZE);
+	val = (unsigned char) (offset / BBY_PAGESIZE);
+	outb(val, (brdp->iobase + BBY_ATCONFR));
+	return(ptr);
+}
+
+/*****************************************************************************/
+
+static void stli_bbyreset(struct stlibrd *brdp)
+{	
+	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
+	udelay(10);
+	outb(0, (brdp->iobase + BBY_ATCONFR));
+	mdelay(1000);
+}
+
+/*****************************************************************************/
+
+/*
+ *	The following routines act on original old Stallion boards.
+ */
+
+static void stli_stalinit(struct stlibrd *brdp)
+{
+	outb(0x1, brdp->iobase);
+	mdelay(1000);
+}
+
+/*****************************************************************************/
+
+static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
+{	
+	BUG_ON(offset > brdp->memsize);
+	return brdp->membase + (offset % STAL_PAGESIZE);
+}
+
+/*****************************************************************************/
+
+static void stli_stalreset(struct stlibrd *brdp)
+{	
+	u32 __iomem *vecp;
+
+	vecp = (u32 __iomem *) (brdp->membase + 0x30);
+	writel(0xffff0000, vecp);
+	outb(0, brdp->iobase);
+	mdelay(1000);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Try to find an ECP board and initialize it. This handles only ECP
+ *	board types.
+ */
+
+static int stli_initecp(struct stlibrd *brdp)
+{
+	cdkecpsig_t sig;
+	cdkecpsig_t __iomem *sigsp;
+	unsigned int status, nxtid;
+	char *name;
+	int retval, panelnr, nrports;
+
+	if ((brdp->iobase == 0) || (brdp->memaddr == 0)) {
+		retval = -ENODEV;
+		goto err;
+	}
+
+	brdp->iosize = ECP_IOSIZE;
+
+	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
+		retval = -EIO;
+		goto err;
+	}
+
+/*
+ *	Based on the specific board type setup the common vars to access
+ *	and enable shared memory. Set all board specific information now
+ *	as well.
+ */
+	switch (brdp->brdtype) {
+	case BRD_ECP:
+		brdp->memsize = ECP_MEMSIZE;
+		brdp->pagesize = ECP_ATPAGESIZE;
+		brdp->init = stli_ecpinit;
+		brdp->enable = stli_ecpenable;
+		brdp->reenable = stli_ecpenable;
+		brdp->disable = stli_ecpdisable;
+		brdp->getmemptr = stli_ecpgetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_ecpreset;
+		name = "serial(EC8/64)";
+		break;
+
+	case BRD_ECPE:
+		brdp->memsize = ECP_MEMSIZE;
+		brdp->pagesize = ECP_EIPAGESIZE;
+		brdp->init = stli_ecpeiinit;
+		brdp->enable = stli_ecpeienable;
+		brdp->reenable = stli_ecpeienable;
+		brdp->disable = stli_ecpeidisable;
+		brdp->getmemptr = stli_ecpeigetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_ecpeireset;
+		name = "serial(EC8/64-EI)";
+		break;
+
+	case BRD_ECPMC:
+		brdp->memsize = ECP_MEMSIZE;
+		brdp->pagesize = ECP_MCPAGESIZE;
+		brdp->init = NULL;
+		brdp->enable = stli_ecpmcenable;
+		brdp->reenable = stli_ecpmcenable;
+		brdp->disable = stli_ecpmcdisable;
+		brdp->getmemptr = stli_ecpmcgetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_ecpmcreset;
+		name = "serial(EC8/64-MCA)";
+		break;
+
+	case BRD_ECPPCI:
+		brdp->memsize = ECP_PCIMEMSIZE;
+		brdp->pagesize = ECP_PCIPAGESIZE;
+		brdp->init = stli_ecppciinit;
+		brdp->enable = NULL;
+		brdp->reenable = NULL;
+		brdp->disable = NULL;
+		brdp->getmemptr = stli_ecppcigetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_ecppcireset;
+		name = "serial(EC/RA-PCI)";
+		break;
+
+	default:
+		retval = -EINVAL;
+		goto err_reg;
+	}
+
+/*
+ *	The per-board operations structure is all set up, so now let's go
+ *	and get the board operational. Firstly initialize board configuration
+ *	registers. Set the memory mapping info so we can get at the boards
+ *	shared memory.
+ */
+	EBRDINIT(brdp);
+
+	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
+	if (brdp->membase == NULL) {
+		retval = -ENOMEM;
+		goto err_reg;
+	}
+
+/*
+ *	Now that all specific code is set up, enable the shared memory and
+ *	look for the a signature area that will tell us exactly what board
+ *	this is, and what it is connected to it.
+ */
+	EBRDENABLE(brdp);
+	sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
+	memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
+	EBRDDISABLE(brdp);
+
+	if (sig.magic != cpu_to_le32(ECP_MAGIC)) {
+		retval = -ENODEV;
+		goto err_unmap;
+	}
+
+/*
+ *	Scan through the signature looking at the panels connected to the
+ *	board. Calculate the total number of ports as we go.
+ */
+	for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
+		status = sig.panelid[nxtid];
+		if ((status & ECH_PNLIDMASK) != nxtid)
+			break;
+
+		brdp->panelids[panelnr] = status;
+		nrports = (status & ECH_PNL16PORT) ? 16 : 8;
+		if ((nrports == 16) && ((status & ECH_PNLXPID) == 0))
+			nxtid++;
+		brdp->panels[panelnr] = nrports;
+		brdp->nrports += nrports;
+		nxtid++;
+		brdp->nrpanels++;
+	}
+
+
+	set_bit(BST_FOUND, &brdp->state);
+	return 0;
+err_unmap:
+	iounmap(brdp->membase);
+	brdp->membase = NULL;
+err_reg:
+	release_region(brdp->iobase, brdp->iosize);
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Try to find an ONboard, Brumby or Stallion board and initialize it.
+ *	This handles only these board types.
+ */
+
+static int stli_initonb(struct stlibrd *brdp)
+{
+	cdkonbsig_t sig;
+	cdkonbsig_t __iomem *sigsp;
+	char *name;
+	int i, retval;
+
+/*
+ *	Do a basic sanity check on the IO and memory addresses.
+ */
+	if (brdp->iobase == 0 || brdp->memaddr == 0) {
+		retval = -ENODEV;
+		goto err;
+	}
+
+	brdp->iosize = ONB_IOSIZE;
+	
+	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
+		retval = -EIO;
+		goto err;
+	}
+
+/*
+ *	Based on the specific board type setup the common vars to access
+ *	and enable shared memory. Set all board specific information now
+ *	as well.
+ */
+	switch (brdp->brdtype) {
+	case BRD_ONBOARD:
+	case BRD_ONBOARD2:
+		brdp->memsize = ONB_MEMSIZE;
+		brdp->pagesize = ONB_ATPAGESIZE;
+		brdp->init = stli_onbinit;
+		brdp->enable = stli_onbenable;
+		brdp->reenable = stli_onbenable;
+		brdp->disable = stli_onbdisable;
+		brdp->getmemptr = stli_onbgetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_onbreset;
+		if (brdp->memaddr > 0x100000)
+			brdp->enabval = ONB_MEMENABHI;
+		else
+			brdp->enabval = ONB_MEMENABLO;
+		name = "serial(ONBoard)";
+		break;
+
+	case BRD_ONBOARDE:
+		brdp->memsize = ONB_EIMEMSIZE;
+		brdp->pagesize = ONB_EIPAGESIZE;
+		brdp->init = stli_onbeinit;
+		brdp->enable = stli_onbeenable;
+		brdp->reenable = stli_onbeenable;
+		brdp->disable = stli_onbedisable;
+		brdp->getmemptr = stli_onbegetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_onbereset;
+		name = "serial(ONBoard/E)";
+		break;
+
+	case BRD_BRUMBY4:
+		brdp->memsize = BBY_MEMSIZE;
+		brdp->pagesize = BBY_PAGESIZE;
+		brdp->init = stli_bbyinit;
+		brdp->enable = NULL;
+		brdp->reenable = NULL;
+		brdp->disable = NULL;
+		brdp->getmemptr = stli_bbygetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_bbyreset;
+		name = "serial(Brumby)";
+		break;
+
+	case BRD_STALLION:
+		brdp->memsize = STAL_MEMSIZE;
+		brdp->pagesize = STAL_PAGESIZE;
+		brdp->init = stli_stalinit;
+		brdp->enable = NULL;
+		brdp->reenable = NULL;
+		brdp->disable = NULL;
+		brdp->getmemptr = stli_stalgetmemptr;
+		brdp->intr = stli_ecpintr;
+		brdp->reset = stli_stalreset;
+		name = "serial(Stallion)";
+		break;
+
+	default:
+		retval = -EINVAL;
+		goto err_reg;
+	}
+
+/*
+ *	The per-board operations structure is all set up, so now let's go
+ *	and get the board operational. Firstly initialize board configuration
+ *	registers. Set the memory mapping info so we can get at the boards
+ *	shared memory.
+ */
+	EBRDINIT(brdp);
+
+	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
+	if (brdp->membase == NULL) {
+		retval = -ENOMEM;
+		goto err_reg;
+	}
+
+/*
+ *	Now that all specific code is set up, enable the shared memory and
+ *	look for the a signature area that will tell us exactly what board
+ *	this is, and how many ports.
+ */
+	EBRDENABLE(brdp);
+	sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
+	memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t));
+	EBRDDISABLE(brdp);
+
+	if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
+	    sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
+	    sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
+	    sig.magic3 != cpu_to_le16(ONB_MAGIC3)) {
+		retval = -ENODEV;
+		goto err_unmap;
+	}
+
+/*
+ *	Scan through the signature alive mask and calculate how many ports
+ *	there are on this board.
+ */
+	brdp->nrpanels = 1;
+	if (sig.amask1) {
+		brdp->nrports = 32;
+	} else {
+		for (i = 0; (i < 16); i++) {
+			if (((sig.amask0 << i) & 0x8000) == 0)
+				break;
+		}
+		brdp->nrports = i;
+	}
+	brdp->panels[0] = brdp->nrports;
+
+
+	set_bit(BST_FOUND, &brdp->state);
+	return 0;
+err_unmap:
+	iounmap(brdp->membase);
+	brdp->membase = NULL;
+err_reg:
+	release_region(brdp->iobase, brdp->iosize);
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Start up a running board. This routine is only called after the
+ *	code has been down loaded to the board and is operational. It will
+ *	read in the memory map, and get the show on the road...
+ */
+
+static int stli_startbrd(struct stlibrd *brdp)
+{
+	cdkhdr_t __iomem *hdrp;
+	cdkmem_t __iomem *memp;
+	cdkasy_t __iomem *ap;
+	unsigned long flags;
+	unsigned int portnr, nrdevs, i;
+	struct stliport *portp;
+	int rc = 0;
+	u32 memoff;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	EBRDENABLE(brdp);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	nrdevs = hdrp->nrdevs;
+
+#if 0
+	printk("%s(%d): CDK version %d.%d.%d --> "
+		"nrdevs=%d memp=%x hostp=%x slavep=%x\n",
+		 __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification),
+		 readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp),
+		 readl(&hdrp->slavep));
+#endif
+
+	if (nrdevs < (brdp->nrports + 1)) {
+		printk(KERN_ERR "istallion: slave failed to allocate memory for "
+				"all devices, devices=%d\n", nrdevs);
+		brdp->nrports = nrdevs - 1;
+	}
+	brdp->nrdevs = nrdevs;
+	brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
+	brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
+	brdp->bitsize = (nrdevs + 7) / 8;
+	memoff = readl(&hdrp->memp);
+	if (memoff > brdp->memsize) {
+		printk(KERN_ERR "istallion: corrupted shared memory region?\n");
+		rc = -EIO;
+		goto stli_donestartup;
+	}
+	memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
+	if (readw(&memp->dtype) != TYP_ASYNCTRL) {
+		printk(KERN_ERR "istallion: no slave control device found\n");
+		goto stli_donestartup;
+	}
+	memp++;
+
+/*
+ *	Cycle through memory allocation of each port. We are guaranteed to
+ *	have all ports inside the first page of slave window, so no need to
+ *	change pages while reading memory map.
+ */
+	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
+		if (readw(&memp->dtype) != TYP_ASYNC)
+			break;
+		portp = brdp->ports[portnr];
+		if (portp == NULL)
+			break;
+		portp->devnr = i;
+		portp->addr = readl(&memp->offset);
+		portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs));
+		portp->portidx = (unsigned char) (i / 8);
+		portp->portbit = (unsigned char) (0x1 << (i % 8));
+	}
+
+	writeb(0xff, &hdrp->slavereq);
+
+/*
+ *	For each port setup a local copy of the RX and TX buffer offsets
+ *	and sizes. We do this separate from the above, because we need to
+ *	move the shared memory page...
+ */
+	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
+		portp = brdp->ports[portnr];
+		if (portp == NULL)
+			break;
+		if (portp->addr == 0)
+			break;
+		ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+		if (ap != NULL) {
+			portp->rxsize = readw(&ap->rxq.size);
+			portp->txsize = readw(&ap->txq.size);
+			portp->rxoffset = readl(&ap->rxq.offset);
+			portp->txoffset = readl(&ap->txq.offset);
+		}
+	}
+
+stli_donestartup:
+	EBRDDISABLE(brdp);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	if (rc == 0)
+		set_bit(BST_STARTED, &brdp->state);
+
+	if (! stli_timeron) {
+		stli_timeron++;
+		mod_timer(&stli_timerlist, STLI_TIMEOUT);
+	}
+
+	return rc;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Probe and initialize the specified board.
+ */
+
+static int __devinit stli_brdinit(struct stlibrd *brdp)
+{
+	int retval;
+
+	switch (brdp->brdtype) {
+	case BRD_ECP:
+	case BRD_ECPE:
+	case BRD_ECPMC:
+	case BRD_ECPPCI:
+		retval = stli_initecp(brdp);
+		break;
+	case BRD_ONBOARD:
+	case BRD_ONBOARDE:
+	case BRD_ONBOARD2:
+	case BRD_BRUMBY4:
+	case BRD_STALLION:
+		retval = stli_initonb(brdp);
+		break;
+	default:
+		printk(KERN_ERR "istallion: board=%d is unknown board "
+				"type=%d\n", brdp->brdnr, brdp->brdtype);
+		retval = -ENODEV;
+	}
+
+	if (retval)
+		return retval;
+
+	stli_initports(brdp);
+	printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x "
+		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
+		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
+		brdp->nrpanels, brdp->nrports);
+	return 0;
+}
+
+#if STLI_EISAPROBE != 0
+/*****************************************************************************/
+
+/*
+ *	Probe around trying to find where the EISA boards shared memory
+ *	might be. This is a bit if hack, but it is the best we can do.
+ */
+
+static int stli_eisamemprobe(struct stlibrd *brdp)
+{
+	cdkecpsig_t	ecpsig, __iomem *ecpsigp;
+	cdkonbsig_t	onbsig, __iomem *onbsigp;
+	int		i, foundit;
+
+/*
+ *	First up we reset the board, to get it into a known state. There
+ *	is only 2 board types here we need to worry about. Don;t use the
+ *	standard board init routine here, it programs up the shared
+ *	memory address, and we don't know it yet...
+ */
+	if (brdp->brdtype == BRD_ECPE) {
+		outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
+		outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
+		udelay(10);
+		outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
+		udelay(500);
+		stli_ecpeienable(brdp);
+	} else if (brdp->brdtype == BRD_ONBOARDE) {
+		outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
+		outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
+		udelay(10);
+		outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
+		mdelay(100);
+		outb(0x1, brdp->iobase);
+		mdelay(1);
+		stli_onbeenable(brdp);
+	} else {
+		return -ENODEV;
+	}
+
+	foundit = 0;
+	brdp->memsize = ECP_MEMSIZE;
+
+/*
+ *	Board shared memory is enabled, so now we have a poke around and
+ *	see if we can find it.
+ */
+	for (i = 0; (i < stli_eisamempsize); i++) {
+		brdp->memaddr = stli_eisamemprobeaddrs[i];
+		brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
+		if (brdp->membase == NULL)
+			continue;
+
+		if (brdp->brdtype == BRD_ECPE) {
+			ecpsigp = stli_ecpeigetmemptr(brdp,
+				CDK_SIGADDR, __LINE__);
+			memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
+			if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
+				foundit = 1;
+		} else {
+			onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp,
+				CDK_SIGADDR, __LINE__);
+			memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t));
+			if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) &&
+			    (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) &&
+			    (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) &&
+			    (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3)))
+				foundit = 1;
+		}
+
+		iounmap(brdp->membase);
+		if (foundit)
+			break;
+	}
+
+/*
+ *	Regardless of whether we found the shared memory or not we must
+ *	disable the region. After that return success or failure.
+ */
+	if (brdp->brdtype == BRD_ECPE)
+		stli_ecpeidisable(brdp);
+	else
+		stli_onbedisable(brdp);
+
+	if (! foundit) {
+		brdp->memaddr = 0;
+		brdp->membase = NULL;
+		printk(KERN_ERR "istallion: failed to probe shared memory "
+				"region for %s in EISA slot=%d\n",
+			stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
+		return -ENODEV;
+	}
+	return 0;
+}
+#endif
+
+static int stli_getbrdnr(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < STL_MAXBRDS; i++) {
+		if (!stli_brds[i]) {
+			if (i >= stli_nrbrds)
+				stli_nrbrds = i + 1;
+			return i;
+		}
+	}
+	return -1;
+}
+
+#if STLI_EISAPROBE != 0
+/*****************************************************************************/
+
+/*
+ *	Probe around and try to find any EISA boards in system. The biggest
+ *	problem here is finding out what memory address is associated with
+ *	an EISA board after it is found. The registers of the ECPE and
+ *	ONboardE are not readable - so we can't read them from there. We
+ *	don't have access to the EISA CMOS (or EISA BIOS) so we don't
+ *	actually have any way to find out the real value. The best we can
+ *	do is go probing around in the usual places hoping we can find it.
+ */
+
+static int __init stli_findeisabrds(void)
+{
+	struct stlibrd *brdp;
+	unsigned int iobase, eid, i;
+	int brdnr, found = 0;
+
+/*
+ *	Firstly check if this is an EISA system.  If this is not an EISA system then
+ *	don't bother going any further!
+ */
+	if (EISA_bus)
+		return 0;
+
+/*
+ *	Looks like an EISA system, so go searching for EISA boards.
+ */
+	for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) {
+		outb(0xff, (iobase + 0xc80));
+		eid = inb(iobase + 0xc80);
+		eid |= inb(iobase + 0xc81) << 8;
+		if (eid != STL_EISAID)
+			continue;
+
+/*
+ *		We have found a board. Need to check if this board was
+ *		statically configured already (just in case!).
+ */
+		for (i = 0; (i < STL_MAXBRDS); i++) {
+			brdp = stli_brds[i];
+			if (brdp == NULL)
+				continue;
+			if (brdp->iobase == iobase)
+				break;
+		}
+		if (i < STL_MAXBRDS)
+			continue;
+
+/*
+ *		We have found a Stallion board and it is not configured already.
+ *		Allocate a board structure and initialize it.
+ */
+		if ((brdp = stli_allocbrd()) == NULL)
+			return found ? : -ENOMEM;
+		brdnr = stli_getbrdnr();
+		if (brdnr < 0)
+			return found ? : -ENOMEM;
+		brdp->brdnr = (unsigned int)brdnr;
+		eid = inb(iobase + 0xc82);
+		if (eid == ECP_EISAID)
+			brdp->brdtype = BRD_ECPE;
+		else if (eid == ONB_EISAID)
+			brdp->brdtype = BRD_ONBOARDE;
+		else
+			brdp->brdtype = BRD_UNKNOWN;
+		brdp->iobase = iobase;
+		outb(0x1, (iobase + 0xc84));
+		if (stli_eisamemprobe(brdp))
+			outb(0, (iobase + 0xc84));
+		if (stli_brdinit(brdp) < 0) {
+			kfree(brdp);
+			continue;
+		}
+
+		stli_brds[brdp->brdnr] = brdp;
+		found++;
+
+		for (i = 0; i < brdp->nrports; i++)
+			tty_register_device(stli_serial,
+					brdp->brdnr * STL_MAXPORTS + i, NULL);
+	}
+
+	return found;
+}
+#else
+static inline int stli_findeisabrds(void) { return 0; }
+#endif
+
+/*****************************************************************************/
+
+/*
+ *	Find the next available board number that is free.
+ */
+
+/*****************************************************************************/
+
+/*
+ *	We have a Stallion board. Allocate a board structure and
+ *	initialize it. Read its IO and MEMORY resources from PCI
+ *	configuration space.
+ */
+
+static int __devinit stli_pciprobe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	struct stlibrd *brdp;
+	unsigned int i;
+	int brdnr, retval = -EIO;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err;
+	brdp = stli_allocbrd();
+	if (brdp == NULL) {
+		retval = -ENOMEM;
+		goto err;
+	}
+	mutex_lock(&stli_brdslock);
+	brdnr = stli_getbrdnr();
+	if (brdnr < 0) {
+		printk(KERN_INFO "istallion: too many boards found, "
+			"maximum supported %d\n", STL_MAXBRDS);
+		mutex_unlock(&stli_brdslock);
+		retval = -EIO;
+		goto err_fr;
+	}
+	brdp->brdnr = (unsigned int)brdnr;
+	stli_brds[brdp->brdnr] = brdp;
+	mutex_unlock(&stli_brdslock);
+	brdp->brdtype = BRD_ECPPCI;
+/*
+ *	We have all resources from the board, so lets setup the actual
+ *	board structure now.
+ */
+	brdp->iobase = pci_resource_start(pdev, 3);
+	brdp->memaddr = pci_resource_start(pdev, 2);
+	retval = stli_brdinit(brdp);
+	if (retval)
+		goto err_null;
+
+	set_bit(BST_PROBED, &brdp->state);
+	pci_set_drvdata(pdev, brdp);
+
+	EBRDENABLE(brdp);
+	brdp->enable = NULL;
+	brdp->disable = NULL;
+
+	for (i = 0; i < brdp->nrports; i++)
+		tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i,
+				&pdev->dev);
+
+	return 0;
+err_null:
+	stli_brds[brdp->brdnr] = NULL;
+err_fr:
+	kfree(brdp);
+err:
+	return retval;
+}
+
+static void __devexit stli_pciremove(struct pci_dev *pdev)
+{
+	struct stlibrd *brdp = pci_get_drvdata(pdev);
+
+	stli_cleanup_ports(brdp);
+
+	iounmap(brdp->membase);
+	if (brdp->iosize > 0)
+		release_region(brdp->iobase, brdp->iosize);
+
+	stli_brds[brdp->brdnr] = NULL;
+	kfree(brdp);
+}
+
+static struct pci_driver stli_pcidriver = {
+	.name = "istallion",
+	.id_table = istallion_pci_tbl,
+	.probe = stli_pciprobe,
+	.remove = __devexit_p(stli_pciremove)
+};
+/*****************************************************************************/
+
+/*
+ *	Allocate a new board structure. Fill out the basic info in it.
+ */
+
+static struct stlibrd *stli_allocbrd(void)
+{
+	struct stlibrd *brdp;
+
+	brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
+	if (!brdp) {
+		printk(KERN_ERR "istallion: failed to allocate memory "
+				"(size=%Zd)\n", sizeof(struct stlibrd));
+		return NULL;
+	}
+	brdp->magic = STLI_BOARDMAGIC;
+	return brdp;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Scan through all the boards in the configuration and see what we
+ *	can find.
+ */
+
+static int __init stli_initbrds(void)
+{
+	struct stlibrd *brdp, *nxtbrdp;
+	struct stlconf conf;
+	unsigned int i, j, found = 0;
+	int retval;
+
+	for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
+			stli_nrbrds++) {
+		memset(&conf, 0, sizeof(conf));
+		if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
+			continue;
+		if ((brdp = stli_allocbrd()) == NULL)
+			continue;
+		brdp->brdnr = stli_nrbrds;
+		brdp->brdtype = conf.brdtype;
+		brdp->iobase = conf.ioaddr1;
+		brdp->memaddr = conf.memaddr;
+		if (stli_brdinit(brdp) < 0) {
+			kfree(brdp);
+			continue;
+		}
+		stli_brds[brdp->brdnr] = brdp;
+		found++;
+
+		for (i = 0; i < brdp->nrports; i++)
+			tty_register_device(stli_serial,
+					brdp->brdnr * STL_MAXPORTS + i, NULL);
+	}
+
+	retval = stli_findeisabrds();
+	if (retval > 0)
+		found += retval;
+
+/*
+ *	All found boards are initialized. Now for a little optimization, if
+ *	no boards are sharing the "shared memory" regions then we can just
+ *	leave them all enabled. This is in fact the usual case.
+ */
+	stli_shared = 0;
+	if (stli_nrbrds > 1) {
+		for (i = 0; (i < stli_nrbrds); i++) {
+			brdp = stli_brds[i];
+			if (brdp == NULL)
+				continue;
+			for (j = i + 1; (j < stli_nrbrds); j++) {
+				nxtbrdp = stli_brds[j];
+				if (nxtbrdp == NULL)
+					continue;
+				if ((brdp->membase >= nxtbrdp->membase) &&
+				    (brdp->membase <= (nxtbrdp->membase +
+				    nxtbrdp->memsize - 1))) {
+					stli_shared++;
+					break;
+				}
+			}
+		}
+	}
+
+	if (stli_shared == 0) {
+		for (i = 0; (i < stli_nrbrds); i++) {
+			brdp = stli_brds[i];
+			if (brdp == NULL)
+				continue;
+			if (test_bit(BST_FOUND, &brdp->state)) {
+				EBRDENABLE(brdp);
+				brdp->enable = NULL;
+				brdp->disable = NULL;
+			}
+		}
+	}
+
+	retval = pci_register_driver(&stli_pcidriver);
+	if (retval && found == 0) {
+		printk(KERN_ERR "Neither isa nor eisa cards found nor pci "
+				"driver can be registered!\n");
+		goto err;
+	}
+
+	return 0;
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Code to handle an "staliomem" read operation. This device is the 
+ *	contents of the board shared memory. It is used for down loading
+ *	the slave image (and debugging :-)
+ */
+
+static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
+{
+	unsigned long flags;
+	void __iomem *memptr;
+	struct stlibrd *brdp;
+	unsigned int brdnr;
+	int size, n;
+	void *p;
+	loff_t off = *offp;
+
+	brdnr = iminor(fp->f_path.dentry->d_inode);
+	if (brdnr >= stli_nrbrds)
+		return -ENODEV;
+	brdp = stli_brds[brdnr];
+	if (brdp == NULL)
+		return -ENODEV;
+	if (brdp->state == 0)
+		return -ENODEV;
+	if (off >= brdp->memsize || off + count < off)
+		return 0;
+
+	size = min(count, (size_t)(brdp->memsize - off));
+
+	/*
+	 *	Copy the data a page at a time
+	 */
+
+	p = (void *)__get_free_page(GFP_KERNEL);
+	if(p == NULL)
+		return -ENOMEM;
+
+	while (size > 0) {
+		spin_lock_irqsave(&brd_lock, flags);
+		EBRDENABLE(brdp);
+		memptr = EBRDGETMEMPTR(brdp, off);
+		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+		n = min(n, (int)PAGE_SIZE);
+		memcpy_fromio(p, memptr, n);
+		EBRDDISABLE(brdp);
+		spin_unlock_irqrestore(&brd_lock, flags);
+		if (copy_to_user(buf, p, n)) {
+			count = -EFAULT;
+			goto out;
+		}
+		off += n;
+		buf += n;
+		size -= n;
+	}
+out:
+	*offp = off;
+	free_page((unsigned long)p);
+	return count;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Code to handle an "staliomem" write operation. This device is the 
+ *	contents of the board shared memory. It is used for down loading
+ *	the slave image (and debugging :-)
+ *
+ *	FIXME: copy under lock
+ */
+
+static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
+{
+	unsigned long flags;
+	void __iomem *memptr;
+	struct stlibrd *brdp;
+	char __user *chbuf;
+	unsigned int brdnr;
+	int size, n;
+	void *p;
+	loff_t off = *offp;
+
+	brdnr = iminor(fp->f_path.dentry->d_inode);
+
+	if (brdnr >= stli_nrbrds)
+		return -ENODEV;
+	brdp = stli_brds[brdnr];
+	if (brdp == NULL)
+		return -ENODEV;
+	if (brdp->state == 0)
+		return -ENODEV;
+	if (off >= brdp->memsize || off + count < off)
+		return 0;
+
+	chbuf = (char __user *) buf;
+	size = min(count, (size_t)(brdp->memsize - off));
+
+	/*
+	 *	Copy the data a page at a time
+	 */
+
+	p = (void *)__get_free_page(GFP_KERNEL);
+	if(p == NULL)
+		return -ENOMEM;
+
+	while (size > 0) {
+		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+		n = min(n, (int)PAGE_SIZE);
+		if (copy_from_user(p, chbuf, n)) {
+			if (count == 0)
+				count = -EFAULT;
+			goto out;
+		}
+		spin_lock_irqsave(&brd_lock, flags);
+		EBRDENABLE(brdp);
+		memptr = EBRDGETMEMPTR(brdp, off);
+		memcpy_toio(memptr, p, n);
+		EBRDDISABLE(brdp);
+		spin_unlock_irqrestore(&brd_lock, flags);
+		off += n;
+		chbuf += n;
+		size -= n;
+	}
+out:
+	free_page((unsigned long) p);
+	*offp = off;
+	return count;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the board stats structure to user app.
+ */
+
+static int stli_getbrdstats(combrd_t __user *bp)
+{
+	struct stlibrd *brdp;
+	unsigned int i;
+
+	if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
+		return -EFAULT;
+	if (stli_brdstats.brd >= STL_MAXBRDS)
+		return -ENODEV;
+	brdp = stli_brds[stli_brdstats.brd];
+	if (brdp == NULL)
+		return -ENODEV;
+
+	memset(&stli_brdstats, 0, sizeof(combrd_t));
+
+	stli_brdstats.brd = brdp->brdnr;
+	stli_brdstats.type = brdp->brdtype;
+	stli_brdstats.hwid = 0;
+	stli_brdstats.state = brdp->state;
+	stli_brdstats.ioaddr = brdp->iobase;
+	stli_brdstats.memaddr = brdp->memaddr;
+	stli_brdstats.nrpanels = brdp->nrpanels;
+	stli_brdstats.nrports = brdp->nrports;
+	for (i = 0; (i < brdp->nrpanels); i++) {
+		stli_brdstats.panels[i].panel = i;
+		stli_brdstats.panels[i].hwid = brdp->panelids[i];
+		stli_brdstats.panels[i].nrports = brdp->panels[i];
+	}
+
+	if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
+		return -EFAULT;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Resolve the referenced port number into a port struct pointer.
+ */
+
+static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
+		unsigned int portnr)
+{
+	struct stlibrd *brdp;
+	unsigned int i;
+
+	if (brdnr >= STL_MAXBRDS)
+		return NULL;
+	brdp = stli_brds[brdnr];
+	if (brdp == NULL)
+		return NULL;
+	for (i = 0; (i < panelnr); i++)
+		portnr += brdp->panels[i];
+	if (portnr >= brdp->nrports)
+		return NULL;
+	return brdp->ports[portnr];
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the port stats structure to user app. A NULL port struct
+ *	pointer passed in means that we need to find out from the app
+ *	what port to get stats for (used through board control device).
+ */
+
+static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
+{
+	unsigned long	flags;
+	struct stlibrd	*brdp;
+	int		rc;
+
+	memset(&stli_comstats, 0, sizeof(comstats_t));
+
+	if (portp == NULL)
+		return -ENODEV;
+	brdp = stli_brds[portp->brdnr];
+	if (brdp == NULL)
+		return -ENODEV;
+
+	mutex_lock(&portp->port.mutex);
+	if (test_bit(BST_STARTED, &brdp->state)) {
+		if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
+		    &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
+			mutex_unlock(&portp->port.mutex);
+			return rc;
+		}
+	} else {
+		memset(&stli_cdkstats, 0, sizeof(asystats_t));
+	}
+
+	stli_comstats.brd = portp->brdnr;
+	stli_comstats.panel = portp->panelnr;
+	stli_comstats.port = portp->portnr;
+	stli_comstats.state = portp->state;
+	stli_comstats.flags = portp->port.flags;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	if (tty != NULL) {
+		if (portp->port.tty == tty) {
+			stli_comstats.ttystate = tty->flags;
+			stli_comstats.rxbuffered = -1;
+			if (tty->termios != NULL) {
+				stli_comstats.cflags = tty->termios->c_cflag;
+				stli_comstats.iflags = tty->termios->c_iflag;
+				stli_comstats.oflags = tty->termios->c_oflag;
+				stli_comstats.lflags = tty->termios->c_lflag;
+			}
+		}
+	}
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	stli_comstats.txtotal = stli_cdkstats.txchars;
+	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
+	stli_comstats.txbuffered = stli_cdkstats.txringq;
+	stli_comstats.rxbuffered += stli_cdkstats.rxringq;
+	stli_comstats.rxoverrun = stli_cdkstats.overruns;
+	stli_comstats.rxparity = stli_cdkstats.parity;
+	stli_comstats.rxframing = stli_cdkstats.framing;
+	stli_comstats.rxlost = stli_cdkstats.ringover;
+	stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
+	stli_comstats.txbreaks = stli_cdkstats.txbreaks;
+	stli_comstats.txxon = stli_cdkstats.txstart;
+	stli_comstats.txxoff = stli_cdkstats.txstop;
+	stli_comstats.rxxon = stli_cdkstats.rxstart;
+	stli_comstats.rxxoff = stli_cdkstats.rxstop;
+	stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
+	stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
+	stli_comstats.modem = stli_cdkstats.dcdcnt;
+	stli_comstats.hwid = stli_cdkstats.hwid;
+	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
+	mutex_unlock(&portp->port.mutex);
+
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the port stats structure to user app. A NULL port struct
+ *	pointer passed in means that we need to find out from the app
+ *	what port to get stats for (used through board control device).
+ */
+
+static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
+							comstats_t __user *cp)
+{
+	struct stlibrd *brdp;
+	int rc;
+
+	if (!portp) {
+		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
+			return -EFAULT;
+		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
+			stli_comstats.port);
+		if (!portp)
+			return -ENODEV;
+	}
+
+	brdp = stli_brds[portp->brdnr];
+	if (!brdp)
+		return -ENODEV;
+
+	if ((rc = stli_portcmdstats(tty, portp)) < 0)
+		return rc;
+
+	return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
+			-EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Clear the port stats structure. We also return it zeroed out...
+ */
+
+static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
+{
+	struct stlibrd *brdp;
+	int rc;
+
+	if (!portp) {
+		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
+			return -EFAULT;
+		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
+			stli_comstats.port);
+		if (!portp)
+			return -ENODEV;
+	}
+
+	brdp = stli_brds[portp->brdnr];
+	if (!brdp)
+		return -ENODEV;
+
+	mutex_lock(&portp->port.mutex);
+
+	if (test_bit(BST_STARTED, &brdp->state)) {
+		if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
+			mutex_unlock(&portp->port.mutex);
+			return rc;
+		}
+	}
+
+	memset(&stli_comstats, 0, sizeof(comstats_t));
+	stli_comstats.brd = portp->brdnr;
+	stli_comstats.panel = portp->panelnr;
+	stli_comstats.port = portp->portnr;
+	mutex_unlock(&portp->port.mutex);
+
+	if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
+		return -EFAULT;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the entire driver ports structure to a user app.
+ */
+
+static int stli_getportstruct(struct stliport __user *arg)
+{
+	struct stliport stli_dummyport;
+	struct stliport *portp;
+
+	if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
+		return -EFAULT;
+	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
+		 stli_dummyport.portnr);
+	if (!portp)
+		return -ENODEV;
+	if (copy_to_user(arg, portp, sizeof(struct stliport)))
+		return -EFAULT;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the entire driver board structure to a user app.
+ */
+
+static int stli_getbrdstruct(struct stlibrd __user *arg)
+{
+	struct stlibrd stli_dummybrd;
+	struct stlibrd *brdp;
+
+	if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
+		return -EFAULT;
+	if (stli_dummybrd.brdnr >= STL_MAXBRDS)
+		return -ENODEV;
+	brdp = stli_brds[stli_dummybrd.brdnr];
+	if (!brdp)
+		return -ENODEV;
+	if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
+		return -EFAULT;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	The "staliomem" device is also required to do some special operations on
+ *	the board. We need to be able to send an interrupt to the board,
+ *	reset it, and start/stop it.
+ */
+
+static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	struct stlibrd *brdp;
+	int brdnr, rc, done;
+	void __user *argp = (void __user *)arg;
+
+/*
+ *	First up handle the board independent ioctls.
+ */
+	done = 0;
+	rc = 0;
+
+	switch (cmd) {
+	case COM_GETPORTSTATS:
+		rc = stli_getportstats(NULL, NULL, argp);
+		done++;
+		break;
+	case COM_CLRPORTSTATS:
+		rc = stli_clrportstats(NULL, argp);
+		done++;
+		break;
+	case COM_GETBRDSTATS:
+		rc = stli_getbrdstats(argp);
+		done++;
+		break;
+	case COM_READPORT:
+		rc = stli_getportstruct(argp);
+		done++;
+		break;
+	case COM_READBOARD:
+		rc = stli_getbrdstruct(argp);
+		done++;
+		break;
+	}
+	if (done)
+		return rc;
+
+/*
+ *	Now handle the board specific ioctls. These all depend on the
+ *	minor number of the device they were called from.
+ */
+	brdnr = iminor(fp->f_dentry->d_inode);
+	if (brdnr >= STL_MAXBRDS)
+		return -ENODEV;
+	brdp = stli_brds[brdnr];
+	if (!brdp)
+		return -ENODEV;
+	if (brdp->state == 0)
+		return -ENODEV;
+
+	switch (cmd) {
+	case STL_BINTR:
+		EBRDINTR(brdp);
+		break;
+	case STL_BSTART:
+		rc = stli_startbrd(brdp);
+		break;
+	case STL_BSTOP:
+		clear_bit(BST_STARTED, &brdp->state);
+		break;
+	case STL_BRESET:
+		clear_bit(BST_STARTED, &brdp->state);
+		EBRDRESET(brdp);
+		if (stli_shared == 0) {
+			if (brdp->reenable != NULL)
+				(* brdp->reenable)(brdp);
+		}
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
+static const struct tty_operations stli_ops = {
+	.open = stli_open,
+	.close = stli_close,
+	.write = stli_write,
+	.put_char = stli_putchar,
+	.flush_chars = stli_flushchars,
+	.write_room = stli_writeroom,
+	.chars_in_buffer = stli_charsinbuffer,
+	.ioctl = stli_ioctl,
+	.set_termios = stli_settermios,
+	.throttle = stli_throttle,
+	.unthrottle = stli_unthrottle,
+	.stop = stli_stop,
+	.start = stli_start,
+	.hangup = stli_hangup,
+	.flush_buffer = stli_flushbuffer,
+	.break_ctl = stli_breakctl,
+	.wait_until_sent = stli_waituntilsent,
+	.send_xchar = stli_sendxchar,
+	.tiocmget = stli_tiocmget,
+	.tiocmset = stli_tiocmset,
+	.proc_fops = &stli_proc_fops,
+};
+
+static const struct tty_port_operations stli_port_ops = {
+	.carrier_raised = stli_carrier_raised,
+	.dtr_rts = stli_dtr_rts,
+	.activate = stli_activate,
+	.shutdown = stli_shutdown,
+};
+
+/*****************************************************************************/
+/*
+ *	Loadable module initialization stuff.
+ */
+
+static void istallion_cleanup_isa(void)
+{
+	struct stlibrd	*brdp;
+	unsigned int j;
+
+	for (j = 0; (j < stli_nrbrds); j++) {
+		if ((brdp = stli_brds[j]) == NULL ||
+				test_bit(BST_PROBED, &brdp->state))
+			continue;
+
+		stli_cleanup_ports(brdp);
+
+		iounmap(brdp->membase);
+		if (brdp->iosize > 0)
+			release_region(brdp->iobase, brdp->iosize);
+		kfree(brdp);
+		stli_brds[j] = NULL;
+	}
+}
+
+static int __init istallion_module_init(void)
+{
+	unsigned int i;
+	int retval;
+
+	printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
+
+	spin_lock_init(&stli_lock);
+	spin_lock_init(&brd_lock);
+
+	stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
+	if (!stli_txcookbuf) {
+		printk(KERN_ERR "istallion: failed to allocate memory "
+				"(size=%d)\n", STLI_TXBUFSIZE);
+		retval = -ENOMEM;
+		goto err;
+	}
+
+	stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+	if (!stli_serial) {
+		retval = -ENOMEM;
+		goto err_free;
+	}
+
+	stli_serial->owner = THIS_MODULE;
+	stli_serial->driver_name = stli_drvname;
+	stli_serial->name = stli_serialname;
+	stli_serial->major = STL_SERIALMAJOR;
+	stli_serial->minor_start = 0;
+	stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
+	stli_serial->subtype = SERIAL_TYPE_NORMAL;
+	stli_serial->init_termios = stli_deftermios;
+	stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(stli_serial, &stli_ops);
+
+	retval = tty_register_driver(stli_serial);
+	if (retval) {
+		printk(KERN_ERR "istallion: failed to register serial driver\n");
+		goto err_ttyput;
+	}
+
+	retval = stli_initbrds();
+	if (retval)
+		goto err_ttyunr;
+
+/*
+ *	Set up a character driver for the shared memory region. We need this
+ *	to down load the slave code image. Also it is a useful debugging tool.
+ */
+	retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
+	if (retval) {
+		printk(KERN_ERR "istallion: failed to register serial memory "
+				"device\n");
+		goto err_deinit;
+	}
+
+	istallion_class = class_create(THIS_MODULE, "staliomem");
+	for (i = 0; i < 4; i++)
+		device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+			      NULL, "staliomem%d", i);
+
+	return 0;
+err_deinit:
+	pci_unregister_driver(&stli_pcidriver);
+	istallion_cleanup_isa();
+err_ttyunr:
+	tty_unregister_driver(stli_serial);
+err_ttyput:
+	put_tty_driver(stli_serial);
+err_free:
+	kfree(stli_txcookbuf);
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+static void __exit istallion_module_exit(void)
+{
+	unsigned int j;
+
+	printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
+		stli_drvversion);
+
+	if (stli_timeron) {
+		stli_timeron = 0;
+		del_timer_sync(&stli_timerlist);
+	}
+
+	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+
+	for (j = 0; j < 4; j++)
+		device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
+	class_destroy(istallion_class);
+
+	pci_unregister_driver(&stli_pcidriver);
+	istallion_cleanup_isa();
+
+	tty_unregister_driver(stli_serial);
+	put_tty_driver(stli_serial);
+
+	kfree(stli_txcookbuf);
+}
+
+module_init(istallion_module_init);
+module_exit(istallion_module_exit);
diff --git a/drivers/staging/tty/riscom8.c b/drivers/staging/tty/riscom8.c
new file mode 100644
index 0000000..602643a
--- /dev/null
+++ b/drivers/staging/tty/riscom8.c
@@ -0,0 +1,1560 @@
+/*
+ *      linux/drivers/char/riscom.c  -- RISCom/8 multiport serial driver.
+ *
+ *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
+ *
+ *      This code is loosely based on the Linux serial driver, written by
+ *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card
+ *      programming info was obtained from various drivers for other OSes
+ *	(FreeBSD, ISC, etc), but no source code from those drivers were
+ *	directly included in this driver.
+ *
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *	Revision 1.1
+ *
+ *	ChangeLog:
+ *	Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 27-Jun-2001
+ *	- get rid of check_region and several cleanups
+ */
+
+#include <linux/module.h>
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/tty_flip.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+#include <linux/uaccess.h>
+
+#include "riscom8.h"
+#include "riscom8_reg.h"
+
+/* Am I paranoid or not ? ;-) */
+#define RISCOM_PARANOIA_CHECK
+
+/*
+ * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
+ * You can slightly speed up things by #undefing the following option,
+ * if you are REALLY sure that your board is correct one.
+ */
+
+#define RISCOM_BRAIN_DAMAGED_CTS
+
+/*
+ * The following defines are mostly for testing purposes. But if you need
+ * some nice reporting in your syslog, you can define them also.
+ */
+#undef RC_REPORT_FIFO
+#undef RC_REPORT_OVERRUN
+
+
+#define RISCOM_LEGAL_FLAGS \
+	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
+	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
+	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
+
+static struct tty_driver *riscom_driver;
+
+static DEFINE_SPINLOCK(riscom_lock);
+
+static struct riscom_board rc_board[RC_NBOARD] =  {
+	{
+		.base	= RC_IOBASE1,
+	},
+	{
+		.base	= RC_IOBASE2,
+	},
+	{
+		.base	= RC_IOBASE3,
+	},
+	{
+		.base	= RC_IOBASE4,
+	},
+};
+
+static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
+
+/* RISCom/8 I/O ports addresses (without address translation) */
+static unsigned short rc_ioport[] =  {
+#if 1
+	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
+#else
+	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
+	0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
+	0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
+#endif
+};
+#define RC_NIOPORT	ARRAY_SIZE(rc_ioport)
+
+
+static int rc_paranoia_check(struct riscom_port const *port,
+				    char *name, const char *routine)
+{
+#ifdef RISCOM_PARANOIA_CHECK
+	static const char badmagic[] = KERN_INFO
+		"rc: Warning: bad riscom port magic number for device %s in %s\n";
+	static const char badinfo[] = KERN_INFO
+		"rc: Warning: null riscom port for device %s in %s\n";
+
+	if (!port) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (port->magic != RISCOM8_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/*
+ *
+ *  Service functions for RISCom/8 driver.
+ *
+ */
+
+/* Get board number from pointer */
+static inline int board_No(struct riscom_board const *bp)
+{
+	return bp - rc_board;
+}
+
+/* Get port number from pointer */
+static inline int port_No(struct riscom_port const *port)
+{
+	return RC_PORT(port - rc_port);
+}
+
+/* Get pointer to board from pointer to port */
+static inline struct riscom_board *port_Board(struct riscom_port const *port)
+{
+	return &rc_board[RC_BOARD(port - rc_port)];
+}
+
+/* Input Byte from CL CD180 register */
+static inline unsigned char rc_in(struct riscom_board const *bp,
+							unsigned short reg)
+{
+	return inb(bp->base + RC_TO_ISA(reg));
+}
+
+/* Output Byte to CL CD180 register */
+static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
+			  unsigned char val)
+{
+	outb(val, bp->base + RC_TO_ISA(reg));
+}
+
+/* Wait for Channel Command Register ready */
+static void rc_wait_CCR(struct riscom_board const *bp)
+{
+	unsigned long delay;
+
+	/* FIXME: need something more descriptive then 100000 :) */
+	for (delay = 100000; delay; delay--)
+		if (!rc_in(bp, CD180_CCR))
+			return;
+
+	printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
+}
+
+/*
+ *  RISCom/8 probe functions.
+ */
+
+static int rc_request_io_range(struct riscom_board * const bp)
+{
+	int i;
+
+	for (i = 0; i < RC_NIOPORT; i++)
+		if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
+				   "RISCom/8"))  {
+			goto out_release;
+		}
+	return 0;
+out_release:
+	printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
+			 board_No(bp), bp->base);
+	while (--i >= 0)
+		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
+	return 1;
+}
+
+static void rc_release_io_range(struct riscom_board * const bp)
+{
+	int i;
+
+	for (i = 0; i < RC_NIOPORT; i++)
+		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
+}
+
+/* Reset and setup CD180 chip */
+static void __init rc_init_CD180(struct riscom_board const *bp)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	rc_out(bp, RC_CTOUT, 0);     	           /* Clear timeout        */
+	rc_wait_CCR(bp);			   /* Wait for CCR ready   */
+	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip     */
+	spin_unlock_irqrestore(&riscom_lock, flags);
+	msleep(50);				   /* Delay 0.05 sec       */
+	spin_lock_irqsave(&riscom_lock, flags);
+	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip */
+	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits       */
+	rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr  */
+	rc_out(bp, CD180_PILR2, RC_ACK_TINT);      /* Prio for tx intr     */
+	rc_out(bp, CD180_PILR3, RC_ACK_RINT);      /* Prio for rx intr	   */
+
+	/* Setting up prescaler. We need 4 ticks per 1 ms */
+	rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
+	rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+/* Main probing routine, also sets irq. */
+static int __init rc_probe(struct riscom_board *bp)
+{
+	unsigned char val1, val2;
+	int irqs = 0;
+	int retries;
+
+	bp->irq = 0;
+
+	if (rc_request_io_range(bp))
+		return 1;
+
+	/* Are the I/O ports here ? */
+	rc_out(bp, CD180_PPRL, 0x5a);
+	outb(0xff, 0x80);
+	val1 = rc_in(bp, CD180_PPRL);
+	rc_out(bp, CD180_PPRL, 0xa5);
+	outb(0x00, 0x80);
+	val2 = rc_in(bp, CD180_PPRL);
+
+	if ((val1 != 0x5a) || (val2 != 0xa5))  {
+		printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
+		       board_No(bp), bp->base);
+		goto out_release;
+	}
+
+	/* It's time to find IRQ for this board */
+	for (retries = 0; retries < 5 && irqs <= 0; retries++) {
+		irqs = probe_irq_on();
+		rc_init_CD180(bp);		 /* Reset CD180 chip	     */
+		rc_out(bp, CD180_CAR, 2);	 /* Select port 2	     */
+		rc_wait_CCR(bp);
+		rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter	     */
+		rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr     */
+		msleep(50);
+		irqs = probe_irq_off(irqs);
+		val1 = rc_in(bp, RC_BSR);	/* Get Board Status reg	     */
+		val2 = rc_in(bp, RC_ACK_TINT);  /* ACK interrupt	     */
+		rc_init_CD180(bp);	       	/* Reset CD180 again	     */
+
+		if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX)))  {
+			printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
+					"found.\n", board_No(bp), bp->base);
+			goto out_release;
+		}
+	}
+
+	if (irqs <= 0)  {
+		printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
+				"at 0x%03x.\n", board_No(bp), bp->base);
+		goto out_release;
+	}
+	bp->irq = irqs;
+	bp->flags |= RC_BOARD_PRESENT;
+
+	printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
+			 "0x%03x, IRQ %d.\n",
+	       board_No(bp),
+	       (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A',   /* Board revision */
+	       bp->base, bp->irq);
+
+	return 0;
+out_release:
+	rc_release_io_range(bp);
+	return 1;
+}
+
+/*
+ *
+ *  Interrupt processing routines.
+ *
+ */
+
+static struct riscom_port *rc_get_port(struct riscom_board const *bp,
+					       unsigned char const *what)
+{
+	unsigned char channel;
+	struct riscom_port *port;
+
+	channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
+	if (channel < CD180_NCH)  {
+		port = &rc_port[board_No(bp) * RC_NPORT + channel];
+		if (port->port.flags & ASYNC_INITIALIZED)
+			return port;
+	}
+	printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
+	       board_No(bp), what, channel);
+	return NULL;
+}
+
+static void rc_receive_exc(struct riscom_board const *bp)
+{
+	struct riscom_port *port;
+	struct tty_struct *tty;
+	unsigned char status;
+	unsigned char ch, flag;
+
+	port = rc_get_port(bp, "Receive");
+	if (port == NULL)
+		return;
+
+	tty = tty_port_tty_get(&port->port);
+
+#ifdef RC_REPORT_OVERRUN
+	status = rc_in(bp, CD180_RCSR);
+	if (status & RCSR_OE)
+		port->overrun++;
+	status &= port->mark_mask;
+#else
+	status = rc_in(bp, CD180_RCSR) & port->mark_mask;
+#endif
+	ch = rc_in(bp, CD180_RDR);
+	if (!status)
+		goto out;
+	if (status & RCSR_TOUT)  {
+		printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
+				    "Hardware problems ?\n",
+		       board_No(bp), port_No(port));
+		goto out;
+
+	} else if (status & RCSR_BREAK)  {
+		printk(KERN_INFO "rc%d: port %d: Handling break...\n",
+		       board_No(bp), port_No(port));
+		flag = TTY_BREAK;
+		if (tty && (port->port.flags & ASYNC_SAK))
+			do_SAK(tty);
+
+	} else if (status & RCSR_PE)
+		flag = TTY_PARITY;
+
+	else if (status & RCSR_FE)
+		flag = TTY_FRAME;
+
+	else if (status & RCSR_OE)
+		flag = TTY_OVERRUN;
+	else
+		flag = TTY_NORMAL;
+
+	if (tty) {
+		tty_insert_flip_char(tty, ch, flag);
+		tty_flip_buffer_push(tty);
+	}
+out:
+	tty_kref_put(tty);
+}
+
+static void rc_receive(struct riscom_board const *bp)
+{
+	struct riscom_port *port;
+	struct tty_struct *tty;
+	unsigned char count;
+
+	port = rc_get_port(bp, "Receive");
+	if (port == NULL)
+		return;
+
+	tty = tty_port_tty_get(&port->port);
+
+	count = rc_in(bp, CD180_RDCR);
+
+#ifdef RC_REPORT_FIFO
+	port->hits[count > 8 ? 9 : count]++;
+#endif
+
+	while (count--)  {
+		u8 ch = rc_in(bp, CD180_RDR);
+		if (tty)
+			tty_insert_flip_char(tty, ch, TTY_NORMAL);
+	}
+	if (tty) {
+		tty_flip_buffer_push(tty);
+		tty_kref_put(tty);
+	}
+}
+
+static void rc_transmit(struct riscom_board const *bp)
+{
+	struct riscom_port *port;
+	struct tty_struct *tty;
+	unsigned char count;
+
+	port = rc_get_port(bp, "Transmit");
+	if (port == NULL)
+		return;
+
+	tty = tty_port_tty_get(&port->port);
+
+	if (port->IER & IER_TXEMPTY) {
+		/* FIFO drained */
+		rc_out(bp, CD180_CAR, port_No(port));
+		port->IER &= ~IER_TXEMPTY;
+		rc_out(bp, CD180_IER, port->IER);
+		goto out;
+	}
+
+	if ((port->xmit_cnt <= 0 && !port->break_length)
+	    || (tty && (tty->stopped || tty->hw_stopped)))  {
+		rc_out(bp, CD180_CAR, port_No(port));
+		port->IER &= ~IER_TXRDY;
+		rc_out(bp, CD180_IER, port->IER);
+		goto out;
+	}
+
+	if (port->break_length)  {
+		if (port->break_length > 0)  {
+			if (port->COR2 & COR2_ETC)  {
+				rc_out(bp, CD180_TDR, CD180_C_ESC);
+				rc_out(bp, CD180_TDR, CD180_C_SBRK);
+				port->COR2 &= ~COR2_ETC;
+			}
+			count = min_t(int, port->break_length, 0xff);
+			rc_out(bp, CD180_TDR, CD180_C_ESC);
+			rc_out(bp, CD180_TDR, CD180_C_DELAY);
+			rc_out(bp, CD180_TDR, count);
+			port->break_length -= count;
+			if (port->break_length == 0)
+				port->break_length--;
+		} else  {
+			rc_out(bp, CD180_TDR, CD180_C_ESC);
+			rc_out(bp, CD180_TDR, CD180_C_EBRK);
+			rc_out(bp, CD180_COR2, port->COR2);
+			rc_wait_CCR(bp);
+			rc_out(bp, CD180_CCR, CCR_CORCHG2);
+			port->break_length = 0;
+		}
+		goto out;
+	}
+
+	count = CD180_NFIFO;
+	do {
+		rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]);
+		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
+		if (--port->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+
+	if (port->xmit_cnt <= 0)  {
+		rc_out(bp, CD180_CAR, port_No(port));
+		port->IER &= ~IER_TXRDY;
+		rc_out(bp, CD180_IER, port->IER);
+	}
+	if (tty && port->xmit_cnt <= port->wakeup_chars)
+		tty_wakeup(tty);
+out:
+	tty_kref_put(tty);
+}
+
+static void rc_check_modem(struct riscom_board const *bp)
+{
+	struct riscom_port *port;
+	struct tty_struct *tty;
+	unsigned char mcr;
+
+	port = rc_get_port(bp, "Modem");
+	if (port == NULL)
+		return;
+
+	tty = tty_port_tty_get(&port->port);
+
+	mcr = rc_in(bp, CD180_MCR);
+	if (mcr & MCR_CDCHG) {
+		if (rc_in(bp, CD180_MSVR) & MSVR_CD)
+			wake_up_interruptible(&port->port.open_wait);
+		else if (tty)
+			tty_hangup(tty);
+	}
+
+#ifdef RISCOM_BRAIN_DAMAGED_CTS
+	if (mcr & MCR_CTSCHG)  {
+		if (rc_in(bp, CD180_MSVR) & MSVR_CTS)  {
+			port->IER |= IER_TXRDY;
+			if (tty) {
+				tty->hw_stopped = 0;
+				if (port->xmit_cnt <= port->wakeup_chars)
+					tty_wakeup(tty);
+			}
+		} else  {
+			if (tty)
+				tty->hw_stopped = 1;
+			port->IER &= ~IER_TXRDY;
+		}
+		rc_out(bp, CD180_IER, port->IER);
+	}
+	if (mcr & MCR_DSRCHG)  {
+		if (rc_in(bp, CD180_MSVR) & MSVR_DSR)  {
+			port->IER |= IER_TXRDY;
+			if (tty) {
+				tty->hw_stopped = 0;
+				if (port->xmit_cnt <= port->wakeup_chars)
+					tty_wakeup(tty);
+			}
+		} else  {
+			if (tty)
+				tty->hw_stopped = 1;
+			port->IER &= ~IER_TXRDY;
+		}
+		rc_out(bp, CD180_IER, port->IER);
+	}
+#endif /* RISCOM_BRAIN_DAMAGED_CTS */
+
+	/* Clear change bits */
+	rc_out(bp, CD180_MCR, 0);
+	tty_kref_put(tty);
+}
+
+/* The main interrupt processing routine */
+static irqreturn_t rc_interrupt(int dummy, void *dev_id)
+{
+	unsigned char status;
+	unsigned char ack;
+	struct riscom_board *bp = dev_id;
+	unsigned long loop = 0;
+	int handled = 0;
+
+	if (!(bp->flags & RC_BOARD_ACTIVE))
+		return IRQ_NONE;
+
+	while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &
+				 (RC_BSR_TOUT | RC_BSR_TINT |
+				  RC_BSR_MINT | RC_BSR_RINT))) {
+		handled = 1;
+		if (status & RC_BSR_TOUT)
+			printk(KERN_WARNING "rc%d: Got timeout. Hardware "
+					    "error?\n", board_No(bp));
+		else if (status & RC_BSR_RINT) {
+			ack = rc_in(bp, RC_ACK_RINT);
+			if (ack == (RC_ID | GIVR_IT_RCV))
+				rc_receive(bp);
+			else if (ack == (RC_ID | GIVR_IT_REXC))
+				rc_receive_exc(bp);
+			else
+				printk(KERN_WARNING "rc%d: Bad receive ack "
+						    "0x%02x.\n",
+				       board_No(bp), ack);
+		} else if (status & RC_BSR_TINT) {
+			ack = rc_in(bp, RC_ACK_TINT);
+			if (ack == (RC_ID | GIVR_IT_TX))
+				rc_transmit(bp);
+			else
+				printk(KERN_WARNING "rc%d: Bad transmit ack "
+						    "0x%02x.\n",
+				       board_No(bp), ack);
+		} else /* if (status & RC_BSR_MINT) */ {
+			ack = rc_in(bp, RC_ACK_MINT);
+			if (ack == (RC_ID | GIVR_IT_MODEM))
+				rc_check_modem(bp);
+			else
+				printk(KERN_WARNING "rc%d: Bad modem ack "
+						    "0x%02x.\n",
+				       board_No(bp), ack);
+		}
+		rc_out(bp, CD180_EOIR, 0);   /* Mark end of interrupt */
+		rc_out(bp, RC_CTOUT, 0);     /* Clear timeout flag    */
+	}
+	return IRQ_RETVAL(handled);
+}
+
+/*
+ *  Routines for open & close processing.
+ */
+
+/* Called with disabled interrupts */
+static int rc_setup_board(struct riscom_board *bp)
+{
+	int error;
+
+	if (bp->flags & RC_BOARD_ACTIVE)
+		return 0;
+
+	error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
+			    "RISCom/8", bp);
+	if (error)
+		return error;
+
+	rc_out(bp, RC_CTOUT, 0);       		/* Just in case         */
+	bp->DTR = ~0;
+	rc_out(bp, RC_DTR, bp->DTR);	        /* Drop DTR on all ports */
+
+	bp->flags |= RC_BOARD_ACTIVE;
+
+	return 0;
+}
+
+/* Called with disabled interrupts */
+static void rc_shutdown_board(struct riscom_board *bp)
+{
+	if (!(bp->flags & RC_BOARD_ACTIVE))
+		return;
+
+	bp->flags &= ~RC_BOARD_ACTIVE;
+
+	free_irq(bp->irq, NULL);
+
+	bp->DTR = ~0;
+	rc_out(bp, RC_DTR, bp->DTR);	       /* Drop DTR on all ports */
+
+}
+
+/*
+ * Setting up port characteristics.
+ * Must be called with disabled interrupts
+ */
+static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp,
+						struct riscom_port *port)
+{
+	unsigned long baud;
+	long tmp;
+	unsigned char cor1 = 0, cor3 = 0;
+	unsigned char mcor1 = 0, mcor2 = 0;
+
+	port->IER  = 0;
+	port->COR2 = 0;
+	port->MSVR = MSVR_RTS;
+
+	baud = tty_get_baud_rate(tty);
+
+	/* Select port on the board */
+	rc_out(bp, CD180_CAR, port_No(port));
+
+	if (!baud)  {
+		/* Drop DTR & exit */
+		bp->DTR |= (1u << port_No(port));
+		rc_out(bp, RC_DTR, bp->DTR);
+		return;
+	} else  {
+		/* Set DTR on */
+		bp->DTR &= ~(1u << port_No(port));
+		rc_out(bp, RC_DTR, bp->DTR);
+	}
+
+	/*
+	 * Now we must calculate some speed depended things
+	 */
+
+	/* Set baud rate for port */
+	tmp = (((RC_OSCFREQ + baud/2) / baud +
+		CD180_TPC/2) / CD180_TPC);
+
+	rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
+	rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
+	rc_out(bp, CD180_RBPRL, tmp & 0xff);
+	rc_out(bp, CD180_TBPRL, tmp & 0xff);
+
+	baud = (baud + 5) / 10;   /* Estimated CPS */
+
+	/* Two timer ticks seems enough to wakeup something like SLIP driver */
+	tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
+	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
+					      SERIAL_XMIT_SIZE - 1 : tmp);
+
+	/* Receiver timeout will be transmission time for 1.5 chars */
+	tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
+	tmp = (tmp > 0xff) ? 0xff : tmp;
+	rc_out(bp, CD180_RTPR, tmp);
+
+	switch (C_CSIZE(tty)) {
+	case CS5:
+		cor1 |= COR1_5BITS;
+		break;
+	case CS6:
+		cor1 |= COR1_6BITS;
+		break;
+	case CS7:
+		cor1 |= COR1_7BITS;
+		break;
+	case CS8:
+		cor1 |= COR1_8BITS;
+		break;
+	}
+	if (C_CSTOPB(tty))
+		cor1 |= COR1_2SB;
+
+	cor1 |= COR1_IGNORE;
+	if (C_PARENB(tty)) {
+		cor1 |= COR1_NORMPAR;
+		if (C_PARODD(tty))
+			cor1 |= COR1_ODDP;
+		if (I_INPCK(tty))
+			cor1 &= ~COR1_IGNORE;
+	}
+	/* Set marking of some errors */
+	port->mark_mask = RCSR_OE | RCSR_TOUT;
+	if (I_INPCK(tty))
+		port->mark_mask |= RCSR_FE | RCSR_PE;
+	if (I_BRKINT(tty) || I_PARMRK(tty))
+		port->mark_mask |= RCSR_BREAK;
+	if (I_IGNPAR(tty))
+		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
+	if (I_IGNBRK(tty)) {
+		port->mark_mask &= ~RCSR_BREAK;
+		if (I_IGNPAR(tty))
+			/* Real raw mode. Ignore all */
+			port->mark_mask &= ~RCSR_OE;
+	}
+	/* Enable Hardware Flow Control */
+	if (C_CRTSCTS(tty))  {
+#ifdef RISCOM_BRAIN_DAMAGED_CTS
+		port->IER |= IER_DSR | IER_CTS;
+		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
+		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
+		tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
+						(MSVR_CTS|MSVR_DSR));
+#else
+		port->COR2 |= COR2_CTSAE;
+#endif
+	}
+	/* Enable Software Flow Control. FIXME: I'm not sure about this */
+	/* Some people reported that it works, but I still doubt */
+	if (I_IXON(tty))  {
+		port->COR2 |= COR2_TXIBE;
+		cor3 |= (COR3_FCT | COR3_SCDE);
+		if (I_IXANY(tty))
+			port->COR2 |= COR2_IXM;
+		rc_out(bp, CD180_SCHR1, START_CHAR(tty));
+		rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));
+		rc_out(bp, CD180_SCHR3, START_CHAR(tty));
+		rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));
+	}
+	if (!C_CLOCAL(tty))  {
+		/* Enable CD check */
+		port->IER |= IER_CD;
+		mcor1 |= MCOR1_CDZD;
+		mcor2 |= MCOR2_CDOD;
+	}
+
+	if (C_CREAD(tty))
+		/* Enable receiver */
+		port->IER |= IER_RXD;
+
+	/* Set input FIFO size (1-8 bytes) */
+	cor3 |= RISCOM_RXFIFO;
+	/* Setting up CD180 channel registers */
+	rc_out(bp, CD180_COR1, cor1);
+	rc_out(bp, CD180_COR2, port->COR2);
+	rc_out(bp, CD180_COR3, cor3);
+	/* Make CD180 know about registers change */
+	rc_wait_CCR(bp);
+	rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
+	/* Setting up modem option registers */
+	rc_out(bp, CD180_MCOR1, mcor1);
+	rc_out(bp, CD180_MCOR2, mcor2);
+	/* Enable CD180 transmitter & receiver */
+	rc_wait_CCR(bp);
+	rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);
+	/* Enable interrupts */
+	rc_out(bp, CD180_IER, port->IER);
+	/* And finally set RTS on */
+	rc_out(bp, CD180_MSVR, port->MSVR);
+}
+
+/* Must be called with interrupts enabled */
+static int rc_activate_port(struct tty_port *port, struct tty_struct *tty)
+{
+	struct riscom_port *rp = container_of(port, struct riscom_port, port);
+	struct riscom_board *bp = port_Board(rp);
+	unsigned long flags;
+
+	if (tty_port_alloc_xmit_buf(port) < 0)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	clear_bit(TTY_IO_ERROR, &tty->flags);
+	bp->count++;
+	rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0;
+	rc_change_speed(tty, bp, rp);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+	return 0;
+}
+
+/* Must be called with interrupts disabled */
+static void rc_shutdown_port(struct tty_struct *tty,
+			struct riscom_board *bp, struct riscom_port *port)
+{
+#ifdef RC_REPORT_OVERRUN
+	printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
+	       board_No(bp), port_No(port), port->overrun);
+#endif
+#ifdef RC_REPORT_FIFO
+	{
+		int i;
+
+		printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
+		       board_No(bp), port_No(port));
+		for (i = 0; i < 10; i++)
+			printk("%ld ", port->hits[i]);
+		printk("].\n");
+	}
+#endif
+	tty_port_free_xmit_buf(&port->port);
+
+	/* Select port */
+	rc_out(bp, CD180_CAR, port_No(port));
+	/* Reset port */
+	rc_wait_CCR(bp);
+	rc_out(bp, CD180_CCR, CCR_SOFTRESET);
+	/* Disable all interrupts from this port */
+	port->IER = 0;
+	rc_out(bp, CD180_IER, port->IER);
+
+	set_bit(TTY_IO_ERROR, &tty->flags);
+
+	if (--bp->count < 0)  {
+		printk(KERN_INFO "rc%d: rc_shutdown_port: "
+				 "bad board count: %d\n",
+		       board_No(bp), bp->count);
+		bp->count = 0;
+	}
+	/*
+	 * If this is the last opened port on the board
+	 * shutdown whole board
+	 */
+	if (!bp->count)
+		rc_shutdown_board(bp);
+}
+
+static int carrier_raised(struct tty_port *port)
+{
+	struct riscom_port *p = container_of(port, struct riscom_port, port);
+	struct riscom_board *bp = port_Board(p);
+	unsigned long flags;
+	int CD;
+	
+	spin_lock_irqsave(&riscom_lock, flags);
+	rc_out(bp, CD180_CAR, port_No(p));
+	CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
+	rc_out(bp, CD180_MSVR, MSVR_RTS);
+	bp->DTR &= ~(1u << port_No(p));
+	rc_out(bp, RC_DTR, bp->DTR);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+	return CD;
+}
+
+static void dtr_rts(struct tty_port *port, int onoff)
+{
+	struct riscom_port *p = container_of(port, struct riscom_port, port);
+	struct riscom_board *bp = port_Board(p);
+	unsigned long flags;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	bp->DTR &= ~(1u << port_No(p));
+	if (onoff == 0)
+		bp->DTR |= (1u << port_No(p));
+	rc_out(bp, RC_DTR, bp->DTR);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static int rc_open(struct tty_struct *tty, struct file *filp)
+{
+	int board;
+	int error;
+	struct riscom_port *port;
+	struct riscom_board *bp;
+
+	board = RC_BOARD(tty->index);
+	if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
+		return -ENODEV;
+
+	bp = &rc_board[board];
+	port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
+	if (rc_paranoia_check(port, tty->name, "rc_open"))
+		return -ENODEV;
+
+	error = rc_setup_board(bp);
+	if (error)
+		return error;
+
+	tty->driver_data = port;
+	return tty_port_open(&port->port, tty, filp);
+}
+
+static void rc_flush_buffer(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
+		return;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
+	tty_wakeup(tty);
+}
+
+static void rc_close_port(struct tty_port *port)
+{
+	unsigned long flags;
+	struct riscom_port *rp = container_of(port, struct riscom_port, port);
+	struct riscom_board *bp = port_Board(rp);
+	unsigned long timeout;
+	
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	rp->IER &= ~IER_RXD;
+
+	rp->IER &= ~IER_TXRDY;
+	rp->IER |= IER_TXEMPTY;
+	rc_out(bp, CD180_CAR, port_No(rp));
+	rc_out(bp, CD180_IER, rp->IER);
+	/*
+	 * Before we drop DTR, make sure the UART transmitter
+	 * has completely drained; this is especially
+	 * important if there is a transmit FIFO!
+	 */
+	timeout = jiffies + HZ;
+	while (rp->IER & IER_TXEMPTY) {
+		spin_unlock_irqrestore(&riscom_lock, flags);
+		msleep_interruptible(jiffies_to_msecs(rp->timeout));
+		spin_lock_irqsave(&riscom_lock, flags);
+		if (time_after(jiffies, timeout))
+			break;
+	}
+	rc_shutdown_port(port->tty, bp, rp);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static void rc_close(struct tty_struct *tty, struct file *filp)
+{
+	struct riscom_port *port = tty->driver_data;
+
+	if (!port || rc_paranoia_check(port, tty->name, "close"))
+		return;
+	tty_port_close(&port->port, tty, filp);
+}
+
+static int rc_write(struct tty_struct *tty,
+		    const unsigned char *buf, int count)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp;
+	int c, total = 0;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_write"))
+		return 0;
+
+	bp = port_Board(port);
+
+	while (1) {
+		spin_lock_irqsave(&riscom_lock, flags);
+
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - port->xmit_head));
+		if (c <= 0)
+			break;	/* lock continues to be held */
+
+		memcpy(port->port.xmit_buf + port->xmit_head, buf, c);
+		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		port->xmit_cnt += c;
+
+		spin_unlock_irqrestore(&riscom_lock, flags);
+
+		buf += c;
+		count -= c;
+		total += c;
+	}
+
+	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
+	    !(port->IER & IER_TXRDY)) {
+		port->IER |= IER_TXRDY;
+		rc_out(bp, CD180_CAR, port_No(port));
+		rc_out(bp, CD180_IER, port->IER);
+	}
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
+	return total;
+}
+
+static int rc_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct riscom_port *port = tty->driver_data;
+	unsigned long flags;
+	int ret = 0;
+
+	if (rc_paranoia_check(port, tty->name, "rc_put_char"))
+		return 0;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
+		goto out;
+
+	port->port.xmit_buf[port->xmit_head++] = ch;
+	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
+	port->xmit_cnt++;
+	ret = 1;
+
+out:
+	spin_unlock_irqrestore(&riscom_lock, flags);
+	return ret;
+}
+
+static void rc_flush_chars(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
+		return;
+
+	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped)
+		return;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	port->IER |= IER_TXRDY;
+	rc_out(port_Board(port), CD180_CAR, port_No(port));
+	rc_out(port_Board(port), CD180_IER, port->IER);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static int rc_write_room(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	int	ret;
+
+	if (rc_paranoia_check(port, tty->name, "rc_write_room"))
+		return 0;
+
+	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}
+
+static int rc_chars_in_buffer(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+
+	if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
+		return 0;
+
+	return port->xmit_cnt;
+}
+
+static int rc_tiocmget(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp;
+	unsigned char status;
+	unsigned int result;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, __func__))
+		return -ENODEV;
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	rc_out(bp, CD180_CAR, port_No(port));
+	status = rc_in(bp, CD180_MSVR);
+	result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
+	result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
+		| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
+		| ((status & MSVR_CD)  ? TIOCM_CAR : 0)
+		| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
+		| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+	return result;
+}
+
+static int rc_tiocmset(struct tty_struct *tty,
+				       unsigned int set, unsigned int clear)
+{
+	struct riscom_port *port = tty->driver_data;
+	unsigned long flags;
+	struct riscom_board *bp;
+
+	if (rc_paranoia_check(port, tty->name, __func__))
+		return -ENODEV;
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	if (set & TIOCM_RTS)
+		port->MSVR |= MSVR_RTS;
+	if (set & TIOCM_DTR)
+		bp->DTR &= ~(1u << port_No(port));
+
+	if (clear & TIOCM_RTS)
+		port->MSVR &= ~MSVR_RTS;
+	if (clear & TIOCM_DTR)
+		bp->DTR |= (1u << port_No(port));
+
+	rc_out(bp, CD180_CAR, port_No(port));
+	rc_out(bp, CD180_MSVR, port->MSVR);
+	rc_out(bp, RC_DTR, bp->DTR);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
+	return 0;
+}
+
+static int rc_send_break(struct tty_struct *tty, int length)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp = port_Board(port);
+	unsigned long flags;
+
+	if (length == 0 || length == -1)
+		return -EOPNOTSUPP;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	port->break_length = RISCOM_TPS / HZ * length;
+	port->COR2 |= COR2_ETC;
+	port->IER  |= IER_TXRDY;
+	rc_out(bp, CD180_CAR, port_No(port));
+	rc_out(bp, CD180_COR2, port->COR2);
+	rc_out(bp, CD180_IER, port->IER);
+	rc_wait_CCR(bp);
+	rc_out(bp, CD180_CCR, CCR_CORCHG2);
+	rc_wait_CCR(bp);
+
+	spin_unlock_irqrestore(&riscom_lock, flags);
+	return 0;
+}
+
+static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
+				     struct serial_struct __user *newinfo)
+{
+	struct serial_struct tmp;
+	struct riscom_board *bp = port_Board(port);
+	int change_speed;
+
+	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
+		return -EFAULT;
+
+	mutex_lock(&port->port.mutex);
+	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
+			(tmp.flags & ASYNC_SPD_MASK));
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((tmp.close_delay != port->port.close_delay) ||
+		    (tmp.closing_wait != port->port.closing_wait) ||
+		    ((tmp.flags & ~ASYNC_USR_MASK) !=
+		     (port->port.flags & ~ASYNC_USR_MASK))) {
+			mutex_unlock(&port->port.mutex);
+			return -EPERM;
+		}
+		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
+			       (tmp.flags & ASYNC_USR_MASK));
+	} else  {
+		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
+			       (tmp.flags & ASYNC_FLAGS));
+		port->port.close_delay = tmp.close_delay;
+		port->port.closing_wait = tmp.closing_wait;
+	}
+	if (change_speed)  {
+		unsigned long flags;
+
+		spin_lock_irqsave(&riscom_lock, flags);
+		rc_change_speed(tty, bp, port);
+		spin_unlock_irqrestore(&riscom_lock, flags);
+	}
+	mutex_unlock(&port->port.mutex);
+	return 0;
+}
+
+static int rc_get_serial_info(struct riscom_port *port,
+				     struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+	struct riscom_board *bp = port_Board(port);
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = PORT_CIRRUS;
+	tmp.line = port - rc_port;
+
+	mutex_lock(&port->port.mutex);
+	tmp.port = bp->base;
+	tmp.irq  = bp->irq;
+	tmp.flags = port->port.flags;
+	tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
+	tmp.close_delay = port->port.close_delay * HZ/100;
+	tmp.closing_wait = port->port.closing_wait * HZ/100;
+	mutex_unlock(&port->port.mutex);
+	tmp.xmit_fifo_size = CD180_NFIFO;
+	return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+}
+
+static int rc_ioctl(struct tty_struct *tty,
+		    unsigned int cmd, unsigned long arg)
+{
+	struct riscom_port *port = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+	int retval;
+
+	if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
+		return -ENODEV;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		retval = rc_get_serial_info(port, argp);
+		break;
+	case TIOCSSERIAL:
+		retval = rc_set_serial_info(tty, port, argp);
+		break;
+	default:
+		retval = -ENOIOCTLCMD;
+	}
+	return retval;
+}
+
+static void rc_throttle(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_throttle"))
+		return;
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	port->MSVR &= ~MSVR_RTS;
+	rc_out(bp, CD180_CAR, port_No(port));
+	if (I_IXOFF(tty)) {
+		rc_wait_CCR(bp);
+		rc_out(bp, CD180_CCR, CCR_SSCH2);
+		rc_wait_CCR(bp);
+	}
+	rc_out(bp, CD180_MSVR, port->MSVR);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static void rc_unthrottle(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
+		return;
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	port->MSVR |= MSVR_RTS;
+	rc_out(bp, CD180_CAR, port_No(port));
+	if (I_IXOFF(tty))  {
+		rc_wait_CCR(bp);
+		rc_out(bp, CD180_CCR, CCR_SSCH1);
+		rc_wait_CCR(bp);
+	}
+	rc_out(bp, CD180_MSVR, port->MSVR);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static void rc_stop(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_stop"))
+		return;
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	port->IER &= ~IER_TXRDY;
+	rc_out(bp, CD180_CAR, port_No(port));
+	rc_out(bp, CD180_IER, port->IER);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static void rc_start(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+	struct riscom_board *bp;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_start"))
+		return;
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&riscom_lock, flags);
+
+	if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) {
+		port->IER |= IER_TXRDY;
+		rc_out(bp, CD180_CAR, port_No(port));
+		rc_out(bp, CD180_IER, port->IER);
+	}
+	spin_unlock_irqrestore(&riscom_lock, flags);
+}
+
+static void rc_hangup(struct tty_struct *tty)
+{
+	struct riscom_port *port = tty->driver_data;
+
+	if (rc_paranoia_check(port, tty->name, "rc_hangup"))
+		return;
+
+	tty_port_hangup(&port->port);
+}
+
+static void rc_set_termios(struct tty_struct *tty,
+					struct ktermios *old_termios)
+{
+	struct riscom_port *port = tty->driver_data;
+	unsigned long flags;
+
+	if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
+		return;
+
+	spin_lock_irqsave(&riscom_lock, flags);
+	rc_change_speed(tty, port_Board(port), port);
+	spin_unlock_irqrestore(&riscom_lock, flags);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rc_start(tty);
+	}
+}
+
+static const struct tty_operations riscom_ops = {
+	.open  = rc_open,
+	.close = rc_close,
+	.write = rc_write,
+	.put_char = rc_put_char,
+	.flush_chars = rc_flush_chars,
+	.write_room = rc_write_room,
+	.chars_in_buffer = rc_chars_in_buffer,
+	.flush_buffer = rc_flush_buffer,
+	.ioctl = rc_ioctl,
+	.throttle = rc_throttle,
+	.unthrottle = rc_unthrottle,
+	.set_termios = rc_set_termios,
+	.stop = rc_stop,
+	.start = rc_start,
+	.hangup = rc_hangup,
+	.tiocmget = rc_tiocmget,
+	.tiocmset = rc_tiocmset,
+	.break_ctl = rc_send_break,
+};
+
+static const struct tty_port_operations riscom_port_ops = {
+	.carrier_raised = carrier_raised,
+	.dtr_rts = dtr_rts,
+	.shutdown = rc_close_port,
+	.activate = rc_activate_port,
+};
+
+
+static int __init rc_init_drivers(void)
+{
+	int error;
+	int i;
+
+	riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
+	if (!riscom_driver)
+		return -ENOMEM;
+
+	riscom_driver->owner = THIS_MODULE;
+	riscom_driver->name = "ttyL";
+	riscom_driver->major = RISCOM8_NORMAL_MAJOR;
+	riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	riscom_driver->subtype = SERIAL_TYPE_NORMAL;
+	riscom_driver->init_termios = tty_std_termios;
+	riscom_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	riscom_driver->init_termios.c_ispeed = 9600;
+	riscom_driver->init_termios.c_ospeed = 9600;
+	riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
+	tty_set_operations(riscom_driver, &riscom_ops);
+	error = tty_register_driver(riscom_driver);
+	if (error != 0) {
+		put_tty_driver(riscom_driver);
+		printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
+				"error = %d\n", error);
+		return 1;
+	}
+	memset(rc_port, 0, sizeof(rc_port));
+	for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
+		tty_port_init(&rc_port[i].port);
+		rc_port[i].port.ops = &riscom_port_ops;
+		rc_port[i].magic = RISCOM8_MAGIC;
+	}
+	return 0;
+}
+
+static void rc_release_drivers(void)
+{
+	tty_unregister_driver(riscom_driver);
+	put_tty_driver(riscom_driver);
+}
+
+#ifndef MODULE
+/*
+ * Called at boot time.
+ *
+ * You can specify IO base for up to RC_NBOARD cards,
+ * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
+ * Note that there will be no probing at default
+ * addresses in this case.
+ *
+ */
+static int __init riscom8_setup(char *str)
+{
+	int ints[RC_NBOARD];
+	int i;
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
+	for (i = 0; i < RC_NBOARD; i++) {
+		if (i < ints[0])
+			rc_board[i].base = ints[i+1];
+		else
+			rc_board[i].base = 0;
+	}
+	return 1;
+}
+
+__setup("riscom8=", riscom8_setup);
+#endif
+
+static char banner[] __initdata =
+	KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin "
+		  "1994-1996.\n";
+static char no_boards_msg[] __initdata =
+	KERN_INFO "rc: No RISCom/8 boards detected.\n";
+
+/*
+ * This routine must be called by kernel at boot time
+ */
+static int __init riscom8_init(void)
+{
+	int i;
+	int found = 0;
+
+	printk(banner);
+
+	if (rc_init_drivers())
+		return -EIO;
+
+	for (i = 0; i < RC_NBOARD; i++)
+		if (rc_board[i].base && !rc_probe(&rc_board[i]))
+			found++;
+	if (!found)  {
+		rc_release_drivers();
+		printk(no_boards_msg);
+		return -EIO;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+static int iobase;
+static int iobase1;
+static int iobase2;
+static int iobase3;
+module_param(iobase, int, 0);
+module_param(iobase1, int, 0);
+module_param(iobase2, int, 0);
+module_param(iobase3, int, 0);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR);
+#endif /* MODULE */
+
+/*
+ * You can setup up to 4 boards (current value of RC_NBOARD)
+ * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
+ *
+ */
+static int __init riscom8_init_module(void)
+{
+#ifdef MODULE
+	int i;
+
+	if (iobase || iobase1 || iobase2 || iobase3) {
+		for (i = 0; i < RC_NBOARD; i++)
+			rc_board[i].base = 0;
+	}
+
+	if (iobase)
+		rc_board[0].base = iobase;
+	if (iobase1)
+		rc_board[1].base = iobase1;
+	if (iobase2)
+		rc_board[2].base = iobase2;
+	if (iobase3)
+		rc_board[3].base = iobase3;
+#endif /* MODULE */
+
+	return riscom8_init();
+}
+
+static void __exit riscom8_exit_module(void)
+{
+	int i;
+
+	rc_release_drivers();
+	for (i = 0; i < RC_NBOARD; i++)
+		if (rc_board[i].flags & RC_BOARD_PRESENT)
+			rc_release_io_range(&rc_board[i]);
+
+}
+
+module_init(riscom8_init_module);
+module_exit(riscom8_exit_module);
diff --git a/drivers/staging/tty/riscom8.h b/drivers/staging/tty/riscom8.h
new file mode 100644
index 0000000..c9876b3
--- /dev/null
+++ b/drivers/staging/tty/riscom8.h
@@ -0,0 +1,91 @@
+/*
+ *      linux/drivers/char/riscom8.h  -- RISCom/8 multiport serial driver.
+ *
+ *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
+ *
+ *      This code is loosely based on the Linux serial driver, written by
+ *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card 
+ *      programming info was obtained from various drivers for other OSes 
+ *	(FreeBSD, ISC, etc), but no source code from those drivers were 
+ *	directly included in this driver.
+ *
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __LINUX_RISCOM8_H
+#define __LINUX_RISCOM8_H
+
+#include <linux/serial.h>
+
+#ifdef __KERNEL__
+
+#define RC_NBOARD		4
+/* NOTE: RISCom decoder recognizes 16 addresses... */
+#define RC_NPORT        	8  
+#define RC_BOARD(line)		(((line) >> 3) & 0x07)
+#define RC_PORT(line)		((line) & (RC_NPORT - 1))
+
+/* Ticks per sec. Used for setting receiver timeout and break length */
+#define RISCOM_TPS		4000
+
+/* Yeah, after heavy testing I decided it must be 6.
+ * Sure, You can change it if needed.
+ */
+#define RISCOM_RXFIFO		6	/* Max. receiver FIFO size (1-8) */
+
+#define RISCOM8_MAGIC		0x0907
+
+#define RC_IOBASE1	0x220
+#define RC_IOBASE2	0x240
+#define RC_IOBASE3	0x250
+#define RC_IOBASE4	0x260
+
+struct riscom_board {
+	unsigned long   flags;
+	unsigned short	base;
+	unsigned char 	irq;
+	signed   char	count;
+	unsigned char	DTR;
+};
+
+#define RC_BOARD_PRESENT	0x00000001
+#define RC_BOARD_ACTIVE		0x00000002
+	
+struct riscom_port {
+	int			magic;
+	struct			tty_port port;
+	int			baud_base;
+	int			timeout;
+	int			custom_divisor;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	short			wakeup_chars;
+	short			break_length;
+	unsigned char		mark_mask;
+	unsigned char		IER;
+	unsigned char		MSVR;
+	unsigned char		COR2;
+#ifdef RC_REPORT_OVERRUN
+	unsigned long		overrun;
+#endif	
+#ifdef RC_REPORT_FIFO
+	unsigned long		hits[10];
+#endif
+};
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_RISCOM8_H */
diff --git a/drivers/staging/tty/riscom8_reg.h b/drivers/staging/tty/riscom8_reg.h
new file mode 100644
index 0000000..a32475e
--- /dev/null
+++ b/drivers/staging/tty/riscom8_reg.h
@@ -0,0 +1,254 @@
+/*
+ *      linux/drivers/char/riscom8_reg.h  -- RISCom/8 multiport serial driver.
+ */
+
+/*
+ * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc.
+ */
+
+/*
+ * Address mapping between Cirrus Logic CD180 chip internal registers
+ * and ISA port addresses:
+ *
+ *      CL-CD180                A6  A5   A4  A3                      A2 A1 A0
+ *      ISA             A15 A14 A13 A12  A11 A10 A9 A8  A7 A6 A5 A4  A3 A2 A1 A0
+ */
+#define RC_TO_ISA(r)    ((((r)&0x07)<<1) | (((r)&~0x07)<<7))
+
+
+/* RISCom/8 On-Board Registers (assuming address translation) */
+
+#define RC_RI           0x100   /* Ring Indicator Register (R/O)           */
+#define RC_DTR          0x100   /* DTR Register (W/O)                      */
+#define RC_BSR          0x101   /* Board Status Register (R/O)             */
+#define RC_CTOUT        0x101   /* Clear Timeout (W/O)                     */
+
+
+/* Board Status Register */
+
+#define RC_BSR_TOUT     0x08     /* Hardware Timeout                       */
+#define RC_BSR_RINT     0x04     /* Receiver Interrupt                     */
+#define RC_BSR_TINT     0x02     /* Transmitter Interrupt                  */
+#define RC_BSR_MINT     0x01     /* Modem Ctl Interrupt                    */
+
+
+/* On-board oscillator frequency (in Hz) */
+#define RC_OSCFREQ      9830400
+
+/* Values of choice for Interrupt ACKs */
+#define RC_ACK_MINT     0x81    /* goes to PILR1                           */
+#define RC_ACK_RINT     0x82    /* goes to PILR3                           */
+#define RC_ACK_TINT     0x84    /* goes to PILR2                           */
+
+/* Chip ID (sorry, only one chip now) */
+#define RC_ID           0x10
+
+/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */
+ 
+#define CD180_NCH       8       /* Total number of channels                */
+#define CD180_TPC       16      /* Ticks per character                     */
+#define CD180_NFIFO	8	/* TX FIFO size                            */
+
+
+/* Global registers */
+
+#define CD180_GIVR      0x40    /* Global Interrupt Vector Register        */
+#define CD180_GICR      0x41    /* Global Interrupting Channel Register    */
+#define CD180_PILR1     0x61    /* Priority Interrupt Level Register 1     */
+#define CD180_PILR2     0x62    /* Priority Interrupt Level Register 2     */
+#define CD180_PILR3     0x63    /* Priority Interrupt Level Register 3     */
+#define CD180_CAR       0x64    /* Channel Access Register                 */
+#define CD180_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
+#define CD180_PPRH      0x70    /* Prescaler Period Register High          */
+#define CD180_PPRL      0x71    /* Prescaler Period Register Low           */
+#define CD180_RDR       0x78    /* Receiver Data Register                  */
+#define CD180_RCSR      0x7a    /* Receiver Character Status Register      */
+#define CD180_TDR       0x7b    /* Transmit Data Register                  */
+#define CD180_EOIR      0x7f    /* End of Interrupt Register               */
+
+
+/* Channel Registers */
+
+#define CD180_CCR       0x01    /* Channel Command Register                */
+#define CD180_IER       0x02    /* Interrupt Enable Register               */
+#define CD180_COR1      0x03    /* Channel Option Register 1               */
+#define CD180_COR2      0x04    /* Channel Option Register 2               */
+#define CD180_COR3      0x05    /* Channel Option Register 3               */
+#define CD180_CCSR      0x06    /* Channel Control Status Register         */
+#define CD180_RDCR      0x07    /* Receive Data Count Register             */
+#define CD180_SCHR1     0x09    /* Special Character Register 1            */
+#define CD180_SCHR2     0x0a    /* Special Character Register 2            */
+#define CD180_SCHR3     0x0b    /* Special Character Register 3            */
+#define CD180_SCHR4     0x0c    /* Special Character Register 4            */
+#define CD180_MCOR1     0x10    /* Modem Change Option 1 Register          */
+#define CD180_MCOR2     0x11    /* Modem Change Option 2 Register          */
+#define CD180_MCR       0x12    /* Modem Change Register                   */
+#define CD180_RTPR      0x18    /* Receive Timeout Period Register         */
+#define CD180_MSVR      0x28    /* Modem Signal Value Register             */
+#define CD180_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
+#define CD180_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
+#define CD180_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
+#define CD180_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
+
+
+/* Global Interrupt Vector Register (R/W) */
+
+#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
+#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
+#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
+#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
+#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
+
+
+/* Global Interrupt Channel Register (R/W) */
+ 
+#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
+#define GICR_CHAN_OFF   2       /* Channel Number Offset                   */
+
+
+/* Channel Address Register (R/W) */
+
+#define CAR_CHAN        0x07    /* Channel Number Mask                     */
+#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
+
+
+/* Receive Character Status Register (R/O) */
+
+#define RCSR_TOUT       0x80    /* Rx Timeout                              */
+#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
+#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
+#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
+#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
+#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
+#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
+#define RCSR_BREAK      0x08    /* Break has been detected                 */
+#define RCSR_PE         0x04    /* Parity Error                            */
+#define RCSR_FE         0x02    /* Frame Error                             */
+#define RCSR_OE         0x01    /* Overrun Error                           */
+
+
+/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
+
+#define CCR_HARDRESET   0x81    /* Reset the chip                          */
+
+#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
+
+#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
+#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
+#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
+
+#define CCR_SSCH1       0x21    /* Send Special Character 1                */
+
+#define CCR_SSCH2       0x22    /* Send Special Character 2                */
+
+#define CCR_SSCH3       0x23    /* Send Special Character 3                */
+
+#define CCR_SSCH4       0x24    /* Send Special Character 4                */
+
+#define CCR_TXEN        0x18    /* Enable Transmitter                      */
+#define CCR_RXEN        0x12    /* Enable Receiver                         */
+
+#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
+#define CCR_RXDIS       0x11    /* Disable Receiver                        */
+
+
+/* Interrupt Enable Register (R/W) */
+
+#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
+#define IER_CD          0x40    /* Enable interrupt on CD change           */
+#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
+#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
+#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
+#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
+#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
+#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
+
+
+/* Channel Option Register 1 (R/W) */
+
+#define COR1_ODDP       0x80    /* Odd Parity                              */
+#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
+#define  COR1_NOPAR      0x00   /* No Parity                               */
+#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
+#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
+#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
+#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
+#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
+#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
+#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
+#define COR1_CHARLEN    0x03    /* Character Length                        */
+#define  COR1_5BITS      0x00   /* 5 bits                                  */
+#define  COR1_6BITS      0x01   /* 6 bits                                  */
+#define  COR1_7BITS      0x02   /* 7 bits                                  */
+#define  COR1_8BITS      0x03   /* 8 bits                                  */
+
+
+/* Channel Option Register 2 (R/W) */
+
+#define COR2_IXM        0x80    /* Implied XON mode                        */
+#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
+#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
+#define COR2_LLM        0x10    /* Local Loopback Mode                     */
+#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
+#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
+#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
+#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
+
+
+/* Channel Option Register 3 (R/W) */
+
+#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
+#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
+#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
+#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
+#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
+
+
+/* Channel Control Status Register (R/O) */
+
+#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
+#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
+#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
+#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
+#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
+#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
+
+
+/* Modem Change Option Register 1 (R/W) */
+
+#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
+#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
+#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
+#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
+#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
+
+
+/* Modem Change Option Register 2 (R/W) */
+
+#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
+#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
+#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
+
+
+/* Modem Change Register (R/W) */
+
+#define MCR_DSRCHG      0x80    /* DSR Changed                             */
+#define MCR_CDCHG       0x40    /* CD Changed                              */
+#define MCR_CTSCHG      0x20    /* CTS Changed                             */
+
+
+/* Modem Signal Value Register (R/W) */
+
+#define MSVR_DSR        0x80    /* Current state of DSR input              */
+#define MSVR_CD         0x40    /* Current state of CD input               */
+#define MSVR_CTS        0x20    /* Current state of CTS input              */
+#define MSVR_DTR        0x02    /* Current state of DTR output             */
+#define MSVR_RTS        0x01    /* Current state of RTS output             */
+
+
+/* Escape characters */
+
+#define CD180_C_ESC     0x00    /* Escape character                        */
+#define CD180_C_SBRK    0x81    /* Start sending BREAK                     */
+#define CD180_C_DELAY   0x82    /* Delay output                            */
+#define CD180_C_EBRK    0x83    /* Stop sending BREAK                      */
diff --git a/drivers/staging/tty/serial167.c b/drivers/staging/tty/serial167.c
new file mode 100644
index 0000000..674af69
--- /dev/null
+++ b/drivers/staging/tty/serial167.c
@@ -0,0 +1,2489 @@
+/*
+ * linux/drivers/char/serial167.c
+ *
+ * Driver for MVME166/7 board serial ports, which are via a CD2401.
+ * Based very much on cyclades.c.
+ *
+ * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
+ *
+ * ==============================================================
+ *
+ * static char rcsid[] =
+ * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
+ *
+ *  linux/kernel/cyclades.c
+ *
+ * Maintained by Marcio Saito (cyclades@netcom.com) and
+ * Randolph Bentson (bentson@grieg.seaslug.org)
+ *
+ * Much of the design and some of the code came from serial.c
+ * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
+ * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
+ * and then fixed as suggested by Michael K. Johnson 12/12/92.
+ *
+ * This version does not support shared irq's.
+ *
+ * $Log: cyclades.c,v $
+ * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
+ * disambiguate between Cyclom-16Y and Cyclom-32Ye;
+ *
+ * Changes:
+ *
+ * 200 lines of changes record removed - RGH 11-10-95, starting work on
+ * converting this to drive serial ports on mvme166 (cd2401).
+ *
+ * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
+ * - get rid of verify_area
+ * - use get_user to access memory from userspace in set_threshold,
+ *   set_default_threshold and set_timeout
+ * - don't use the panic function in serial167_init
+ * - do resource release on failure on serial167_init
+ * - include missing restore_flags in mvme167_serial_console_setup
+ *
+ * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
+ * - replace bottom half handler with task queue handler
+ */
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/serial167.h>
+#include <linux/delay.h>
+#include <linux/major.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/tty_flip.h>
+#include <linux/gfp.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/mvme16xhw.h>
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/uaccess.h>
+#include <linux/init.h>
+
+#define SERIAL_PARANOIA_CHECK
+#undef  SERIAL_DEBUG_OPEN
+#undef  SERIAL_DEBUG_THROTTLE
+#undef  SERIAL_DEBUG_OTHER
+#undef  SERIAL_DEBUG_IO
+#undef  SERIAL_DEBUG_COUNT
+#undef  SERIAL_DEBUG_DTR
+#undef  CYCLOM_16Y_HACK
+#define  CYCLOM_ENABLE_MONITORING
+
+#define WAKEUP_CHARS 256
+
+#define STD_COM_FLAGS (0)
+
+static struct tty_driver *cy_serial_driver;
+extern int serial_console;
+static struct cyclades_port *serial_console_info = NULL;
+static unsigned int serial_console_cflag = 0;
+u_char initial_console_speed;
+
+/* Base address of cd2401 chip on mvme166/7 */
+
+#define BASE_ADDR (0xfff45000)
+#define pcc2chip	((volatile u_char *)0xfff42000)
+#define PccSCCMICR	0x1d
+#define PccSCCTICR	0x1e
+#define PccSCCRICR	0x1f
+#define PccTPIACKR	0x25
+#define PccRPIACKR	0x27
+#define PccIMLR		0x3f
+
+/* This is the per-port data structure */
+struct cyclades_port cy_port[] = {
+	/* CARD#  */
+	{-1},			/* ttyS0 */
+	{-1},			/* ttyS1 */
+	{-1},			/* ttyS2 */
+	{-1},			/* ttyS3 */
+};
+
+#define NR_PORTS        ARRAY_SIZE(cy_port)
+
+/*
+ * This is used to look up the divisor speeds and the timeouts
+ * We're normally limited to 15 distinct baud rates.  The extra
+ * are accessed via settings in info->flags.
+ *         0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+ *        10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+ *                                                  HI            VHI
+ */
+static int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
+	0
+};
+
+#if 0
+static char baud_co[] = {	/* 25 MHz clock option table */
+	/* value =>    00    01   02    03    04 */
+	/* divide by    8    32   128   512  2048 */
+	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
+	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static char baud_bpr[] = {	/* 25 MHz baud rate period table */
+	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
+	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
+};
+#endif
+
+/* I think 166 brd clocks 2401 at 20MHz.... */
+
+/* These values are written directly to tcor, and >> 5 for writing to rcor */
+static u_char baud_co[] = {	/* 20 MHz clock option table */
+	0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
+	0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* These values written directly to tbpr/rbpr */
+static u_char baud_bpr[] = {	/* 20 MHz baud rate period table */
+	0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
+	0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
+};
+
+static u_char baud_cor4[] = {	/* receive threshold */
+	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
+};
+
+static void shutdown(struct cyclades_port *);
+static int startup(struct cyclades_port *);
+static void cy_throttle(struct tty_struct *);
+static void cy_unthrottle(struct tty_struct *);
+static void config_setup(struct cyclades_port *);
+#ifdef CYCLOM_SHOW_STATUS
+static void show_status(int);
+#endif
+
+/*
+ * I have my own version of udelay(), as it is needed when initialising
+ * the chip, before the delay loop has been calibrated.  Should probably
+ * reference one of the vmechip2 or pccchip2 counter for an accurate
+ * delay, but this wild guess will do for now.
+ */
+
+void my_udelay(long us)
+{
+	u_char x;
+	volatile u_char *p = &x;
+	int i;
+
+	while (us--)
+		for (i = 100; i; i--)
+			x |= *p;
+}
+
+static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
+		const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	if (!info) {
+		printk("Warning: null cyclades_port for (%s) in %s\n", name,
+				routine);
+		return 1;
+	}
+
+	if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
+		printk("Warning: cyclades_port out of range for (%s) in %s\n",
+				name, routine);
+		return 1;
+	}
+
+	if (info->magic != CYCLADES_MAGIC) {
+		printk("Warning: bad magic number for serial struct (%s) in "
+				"%s\n", name, routine);
+		return 1;
+	}
+#endif
+	return 0;
+}				/* serial_paranoia_check */
+
+#if 0
+/* The following diagnostic routines allow the driver to spew
+   information on the screen, even (especially!) during interrupts.
+ */
+void SP(char *data)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	printk(KERN_EMERG "%s", data);
+	local_irq_restore(flags);
+}
+
+char scrn[2];
+void CP(char data)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+	scrn[0] = data;
+	printk(KERN_EMERG "%c", scrn);
+	local_irq_restore(flags);
+}				/* CP */
+
+void CP1(int data)
+{
+	(data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
+}				/* CP1 */
+void CP2(int data)
+{
+	CP1((data >> 4) & 0x0f);
+	CP1(data & 0x0f);
+}				/* CP2 */
+void CP4(int data)
+{
+	CP2((data >> 8) & 0xff);
+	CP2(data & 0xff);
+}				/* CP4 */
+void CP8(long data)
+{
+	CP4((data >> 16) & 0xffff);
+	CP4(data & 0xffff);
+}				/* CP8 */
+#endif
+
+/* This routine waits up to 1000 micro-seconds for the previous
+   command to the Cirrus chip to complete and then issues the
+   new command.  An error is returned if the previous command
+   didn't finish within the time limit.
+ */
+u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
+{
+	unsigned long flags;
+	volatile int i;
+
+	local_irq_save(flags);
+	/* Check to see that the previous command has completed */
+	for (i = 0; i < 100; i++) {
+		if (base_addr[CyCCR] == 0) {
+			break;
+		}
+		my_udelay(10L);
+	}
+	/* if the CCR never cleared, the previous command
+	   didn't finish within the "reasonable time" */
+	if (i == 10) {
+		local_irq_restore(flags);
+		return (-1);
+	}
+
+	/* Issue the new command */
+	base_addr[CyCCR] = cmd;
+	local_irq_restore(flags);
+	return (0);
+}				/* write_cy_cmd */
+
+/* cy_start and cy_stop provide software output flow control as a
+   function of XON/XOFF, software CTS, and other such stuff. */
+
+static void cy_stop(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	unsigned long flags;
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_stop %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_stop"))
+		return;
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) (channel);	/* index channel */
+	base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+	local_irq_restore(flags);
+}				/* cy_stop */
+
+static void cy_start(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	unsigned long flags;
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_start %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_start"))
+		return;
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) (channel);
+	base_addr[CyIER] |= CyTxMpty;
+	local_irq_restore(flags);
+}				/* cy_start */
+
+/* The real interrupt service routines are called
+   whenever the card wants its hand held--chars
+   received, out buffer empty, modem change, etc.
+ */
+static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
+{
+	struct tty_struct *tty;
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	unsigned char err, rfoc;
+	int channel;
+	char data;
+
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+	info = &cy_port[channel];
+	info->last_active = jiffies;
+
+	if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
+		/* This is a receive timeout interrupt, ignore it */
+		base_addr[CyREOIR] = CyNOTRANS;
+		return IRQ_HANDLED;
+	}
+
+	/* Read a byte of data if there is any - assume the error
+	 * is associated with this character */
+
+	if ((rfoc = base_addr[CyRFOC]) != 0)
+		data = base_addr[CyRDR];
+	else
+		data = 0;
+
+	/* if there is nowhere to put the data, discard it */
+	if (info->tty == 0) {
+		base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
+		return IRQ_HANDLED;
+	} else {		/* there is an open port for this data */
+		tty = info->tty;
+		if (err & info->ignore_status_mask) {
+			base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
+			return IRQ_HANDLED;
+		}
+		if (tty_buffer_request_room(tty, 1) != 0) {
+			if (err & info->read_status_mask) {
+				if (err & CyBREAK) {
+					tty_insert_flip_char(tty, data,
+							     TTY_BREAK);
+					if (info->flags & ASYNC_SAK) {
+						do_SAK(tty);
+					}
+				} else if (err & CyFRAME) {
+					tty_insert_flip_char(tty, data,
+							     TTY_FRAME);
+				} else if (err & CyPARITY) {
+					tty_insert_flip_char(tty, data,
+							     TTY_PARITY);
+				} else if (err & CyOVERRUN) {
+					tty_insert_flip_char(tty, 0,
+							     TTY_OVERRUN);
+					/*
+					   If the flip buffer itself is
+					   overflowing, we still lose
+					   the next incoming character.
+					 */
+					if (tty_buffer_request_room(tty, 1) !=
+					    0) {
+						tty_insert_flip_char(tty, data,
+								     TTY_FRAME);
+					}
+					/* These two conditions may imply */
+					/* a normal read should be done. */
+					/* else if(data & CyTIMEOUT) */
+					/* else if(data & CySPECHAR) */
+				} else {
+					tty_insert_flip_char(tty, 0,
+							     TTY_NORMAL);
+				}
+			} else {
+				tty_insert_flip_char(tty, data, TTY_NORMAL);
+			}
+		} else {
+			/* there was a software buffer overrun
+			   and nothing could be done about it!!! */
+		}
+	}
+	tty_schedule_flip(tty);
+	/* end of service */
+	base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
+	return IRQ_HANDLED;
+}				/* cy_rxerr_interrupt */
+
+static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
+{
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	int mdm_change;
+	int mdm_status;
+
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+	info = &cy_port[channel];
+	info->last_active = jiffies;
+
+	mdm_change = base_addr[CyMISR];
+	mdm_status = base_addr[CyMSVR1];
+
+	if (info->tty == 0) {	/* nowhere to put the data, ignore it */
+		;
+	} else {
+		if ((mdm_change & CyDCD)
+		    && (info->flags & ASYNC_CHECK_CD)) {
+			if (mdm_status & CyDCD) {
+/* CP('!'); */
+				wake_up_interruptible(&info->open_wait);
+			} else {
+/* CP('@'); */
+				tty_hangup(info->tty);
+				wake_up_interruptible(&info->open_wait);
+				info->flags &= ~ASYNC_NORMAL_ACTIVE;
+			}
+		}
+		if ((mdm_change & CyCTS)
+		    && (info->flags & ASYNC_CTS_FLOW)) {
+			if (info->tty->stopped) {
+				if (mdm_status & CyCTS) {
+					/* !!! cy_start isn't used because... */
+					info->tty->stopped = 0;
+					base_addr[CyIER] |= CyTxMpty;
+					tty_wakeup(info->tty);
+				}
+			} else {
+				if (!(mdm_status & CyCTS)) {
+					/* !!! cy_stop isn't used because... */
+					info->tty->stopped = 1;
+					base_addr[CyIER] &=
+					    ~(CyTxMpty | CyTxRdy);
+				}
+			}
+		}
+		if (mdm_status & CyDSR) {
+		}
+	}
+	base_addr[CyMEOIR] = 0;
+	return IRQ_HANDLED;
+}				/* cy_modem_interrupt */
+
+static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
+{
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	int char_count, saved_cnt;
+	int outch;
+
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+
+	/* validate the port number (as configured and open) */
+	if ((channel < 0) || (NR_PORTS <= channel)) {
+		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+		base_addr[CyTEOIR] = CyNOTRANS;
+		return IRQ_HANDLED;
+	}
+	info = &cy_port[channel];
+	info->last_active = jiffies;
+	if (info->tty == 0) {
+		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+		base_addr[CyTEOIR] = CyNOTRANS;
+		return IRQ_HANDLED;
+	}
+
+	/* load the on-chip space available for outbound data */
+	saved_cnt = char_count = base_addr[CyTFTC];
+
+	if (info->x_char) {	/* send special char */
+		outch = info->x_char;
+		base_addr[CyTDR] = outch;
+		char_count--;
+		info->x_char = 0;
+	}
+
+	if (info->x_break) {
+		/*  The Cirrus chip requires the "Embedded Transmit
+		   Commands" of start break, delay, and end break
+		   sequences to be sent.  The duration of the
+		   break is given in TICs, which runs at HZ
+		   (typically 100) and the PPR runs at 200 Hz,
+		   so the delay is duration * 200/HZ, and thus a
+		   break can run from 1/100 sec to about 5/4 sec.
+		   Need to check these values - RGH 141095.
+		 */
+		base_addr[CyTDR] = 0;	/* start break */
+		base_addr[CyTDR] = 0x81;
+		base_addr[CyTDR] = 0;	/* delay a bit */
+		base_addr[CyTDR] = 0x82;
+		base_addr[CyTDR] = info->x_break * 200 / HZ;
+		base_addr[CyTDR] = 0;	/* terminate break */
+		base_addr[CyTDR] = 0x83;
+		char_count -= 7;
+		info->x_break = 0;
+	}
+
+	while (char_count > 0) {
+		if (!info->xmit_cnt) {
+			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+			break;
+		}
+		if (info->xmit_buf == 0) {
+			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+			break;
+		}
+		if (info->tty->stopped || info->tty->hw_stopped) {
+			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
+			break;
+		}
+		/* Because the Embedded Transmit Commands have been
+		   enabled, we must check to see if the escape
+		   character, NULL, is being sent.  If it is, we
+		   must ensure that there is room for it to be
+		   doubled in the output stream.  Therefore we
+		   no longer advance the pointer when the character
+		   is fetched, but rather wait until after the check
+		   for a NULL output character. (This is necessary
+		   because there may not be room for the two chars
+		   needed to send a NULL.
+		 */
+		outch = info->xmit_buf[info->xmit_tail];
+		if (outch) {
+			info->xmit_cnt--;
+			info->xmit_tail = (info->xmit_tail + 1)
+			    & (PAGE_SIZE - 1);
+			base_addr[CyTDR] = outch;
+			char_count--;
+		} else {
+			if (char_count > 1) {
+				info->xmit_cnt--;
+				info->xmit_tail = (info->xmit_tail + 1)
+				    & (PAGE_SIZE - 1);
+				base_addr[CyTDR] = outch;
+				base_addr[CyTDR] = 0;
+				char_count--;
+				char_count--;
+			} else {
+				break;
+			}
+		}
+	}
+
+	if (info->xmit_cnt < WAKEUP_CHARS)
+		tty_wakeup(info->tty);
+
+	base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
+	return IRQ_HANDLED;
+}				/* cy_tx_interrupt */
+
+static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
+{
+	struct tty_struct *tty;
+	struct cyclades_port *info;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+	char data;
+	int char_count;
+	int save_cnt;
+
+	/* determine the channel and change to that context */
+	channel = (u_short) (base_addr[CyLICR] >> 2);
+	info = &cy_port[channel];
+	info->last_active = jiffies;
+	save_cnt = char_count = base_addr[CyRFOC];
+
+		/* if there is nowhere to put the data, discard it */
+	if (info->tty == 0) {
+		while (char_count--) {
+			data = base_addr[CyRDR];
+		}
+	} else {		/* there is an open port for this data */
+		tty = info->tty;
+		/* load # characters available from the chip */
+
+#ifdef CYCLOM_ENABLE_MONITORING
+		++info->mon.int_count;
+		info->mon.char_count += char_count;
+		if (char_count > info->mon.char_max)
+			info->mon.char_max = char_count;
+		info->mon.char_last = char_count;
+#endif
+		while (char_count--) {
+			data = base_addr[CyRDR];
+			tty_insert_flip_char(tty, data, TTY_NORMAL);
+#ifdef CYCLOM_16Y_HACK
+			udelay(10L);
+#endif
+		}
+		tty_schedule_flip(tty);
+	}
+	/* end of service */
+	base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
+	return IRQ_HANDLED;
+}				/* cy_rx_interrupt */
+
+/* This is called whenever a port becomes active;
+   interrupts are enabled and DTR & RTS are turned on.
+ */
+static int startup(struct cyclades_port *info)
+{
+	unsigned long flags;
+	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
+	int channel;
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		return 0;
+	}
+
+	if (!info->type) {
+		if (info->tty) {
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		}
+		return 0;
+	}
+	if (!info->xmit_buf) {
+		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+		if (!info->xmit_buf) {
+			return -ENOMEM;
+		}
+	}
+
+	config_setup(info);
+
+	channel = info->line;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("startup channel %d\n", channel);
+#endif
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
+
+	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
+	base_addr[CyMSVR1] = CyRTS;
+/* CP('S');CP('1'); */
+	base_addr[CyMSVR2] = CyDTR;
+
+#ifdef SERIAL_DEBUG_DTR
+	printk("cyc: %d: raising DTR\n", __LINE__);
+	printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+	       base_addr[CyMSVR2]);
+#endif
+
+	base_addr[CyIER] |= CyRxData;
+	info->flags |= ASYNC_INITIALIZED;
+
+	if (info->tty) {
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	}
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	local_irq_restore(flags);
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk(" done\n");
+#endif
+	return 0;
+}				/* startup */
+
+void start_xmit(struct cyclades_port *info)
+{
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+
+	channel = info->line;
+	local_irq_save(flags);
+	base_addr[CyCAR] = channel;
+	base_addr[CyIER] |= CyTxMpty;
+	local_irq_restore(flags);
+}				/* start_xmit */
+
+/*
+ * This routine shuts down a serial port; interrupts are disabled,
+ * and DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct cyclades_port *info)
+{
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+
+	if (!(info->flags & ASYNC_INITIALIZED)) {
+/* CP('$'); */
+		return;
+	}
+
+	channel = info->line;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("shutdown channel %d\n", channel);
+#endif
+
+	/* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
+	   SENT BEFORE DROPPING THE LINE !!!  (Perhaps
+	   set some flag that is read when XMTY happens.)
+	   Other choices are to delay some fixed interval
+	   or schedule some later processing.
+	 */
+	local_irq_save(flags);
+	if (info->xmit_buf) {
+		free_page((unsigned long)info->xmit_buf);
+		info->xmit_buf = NULL;
+	}
+
+	base_addr[CyCAR] = (u_char) channel;
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+		base_addr[CyMSVR1] = 0;
+/* CP('C');CP('1'); */
+		base_addr[CyMSVR2] = 0;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: dropping DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+	}
+	write_cy_cmd(base_addr, CyDIS_RCVR);
+	/* it may be appropriate to clear _XMIT at
+	   some later date (after testing)!!! */
+
+	if (info->tty) {
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+	}
+	info->flags &= ~ASYNC_INITIALIZED;
+	local_irq_restore(flags);
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk(" done\n");
+#endif
+}				/* shutdown */
+
+/*
+ * This routine finds or computes the various line characteristics.
+ */
+static void config_setup(struct cyclades_port *info)
+{
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned cflag;
+	int i;
+	unsigned char ti, need_init_chan = 0;
+
+	if (!info->tty || !info->tty->termios) {
+		return;
+	}
+	if (info->line == -1) {
+		return;
+	}
+	cflag = info->tty->termios->c_cflag;
+
+	/* baud rate */
+	i = cflag & CBAUD;
+#ifdef CBAUDEX
+/* Starting with kernel 1.1.65, there is direct support for
+   higher baud rates.  The following code supports those
+   changes.  The conditional aspect allows this driver to be
+   used for earlier as well as later kernel versions.  (The
+   mapping is slightly different from serial.c because there
+   is still the possibility of supporting 75 kbit/sec with
+   the Cyclades board.)
+ */
+	if (i & CBAUDEX) {
+		if (i == B57600)
+			i = 16;
+		else if (i == B115200)
+			i = 18;
+#ifdef B78600
+		else if (i == B78600)
+			i = 17;
+#endif
+		else
+			info->tty->termios->c_cflag &= ~CBAUDEX;
+	}
+#endif
+	if (i == 15) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			i += 1;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			i += 3;
+	}
+	/* Don't ever change the speed of the console port.  It will
+	 * run at the speed specified in bootinfo, or at 19.2K */
+	/* Actually, it should run at whatever speed 166Bug was using */
+	/* Note info->timeout isn't used at present */
+	if (info != serial_console_info) {
+		info->tbpr = baud_bpr[i];	/* Tx BPR */
+		info->tco = baud_co[i];	/* Tx CO */
+		info->rbpr = baud_bpr[i];	/* Rx BPR */
+		info->rco = baud_co[i] >> 5;	/* Rx CO */
+		if (baud_table[i] == 134) {
+			info->timeout =
+			    (info->xmit_fifo_size * HZ * 30 / 269) + 2;
+			/* get it right for 134.5 baud */
+		} else if (baud_table[i]) {
+			info->timeout =
+			    (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
+			    2;
+			/* this needs to be propagated into the card info */
+		} else {
+			info->timeout = 0;
+		}
+	}
+	/* By tradition (is it a standard?) a baud rate of zero
+	   implies the line should be/has been closed.  A bit
+	   later in this routine such a test is performed. */
+
+	/* byte size and parity */
+	info->cor7 = 0;
+	info->cor6 = 0;
+	info->cor5 = 0;
+	info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]);	/* receive threshold */
+	/* Following two lines added 101295, RGH. */
+	/* It is obviously wrong to access CyCORx, and not info->corx here,
+	 * try and remember to fix it later! */
+	channel = info->line;
+	base_addr[CyCAR] = (u_char) channel;
+	if (C_CLOCAL(info->tty)) {
+		if (base_addr[CyIER] & CyMdmCh)
+			base_addr[CyIER] &= ~CyMdmCh;	/* without modem intr */
+		/* ignore 1->0 modem transitions */
+		if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
+		/* ignore 0->1 modem transitions */
+		if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
+	} else {
+		if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
+			base_addr[CyIER] |= CyMdmCh;	/* with modem intr */
+		/* act on 1->0 modem transitions */
+		if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
+		    (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
+		/* act on 0->1 modem transitions */
+		if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
+		    (CyDSR | CyCTS | CyDCD))
+			base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
+	}
+	info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
+	info->cor2 = CyETC;
+	switch (cflag & CSIZE) {
+	case CS5:
+		info->cor1 = Cy_5_BITS;
+		break;
+	case CS6:
+		info->cor1 = Cy_6_BITS;
+		break;
+	case CS7:
+		info->cor1 = Cy_7_BITS;
+		break;
+	case CS8:
+		info->cor1 = Cy_8_BITS;
+		break;
+	}
+	if (cflag & PARENB) {
+		if (cflag & PARODD) {
+			info->cor1 |= CyPARITY_O;
+		} else {
+			info->cor1 |= CyPARITY_E;
+		}
+	} else {
+		info->cor1 |= CyPARITY_NONE;
+	}
+
+	/* CTS flow control flag */
+#if 0
+	/* Don't complcate matters for now! RGH 141095 */
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->cor2 |= CyCtsAE;
+	} else {
+		info->flags &= ~ASYNC_CTS_FLOW;
+		info->cor2 &= ~CyCtsAE;
+	}
+#endif
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else
+		info->flags |= ASYNC_CHECK_CD;
+
+     /***********************************************
+	The hardware option, CyRtsAO, presents RTS when
+	the chip has characters to send.  Since most modems
+	use RTS as reverse (inbound) flow control, this
+	option is not used.  If inbound flow control is
+	necessary, DTR can be programmed to provide the
+	appropriate signals for use with a non-standard
+	cable.  Contact Marcio Saito for details.
+     ***********************************************/
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+
+	/* CyCMR set once only in mvme167_init_serial() */
+	if (base_addr[CyLICR] != channel << 2)
+		base_addr[CyLICR] = channel << 2;
+	if (base_addr[CyLIVR] != 0x5c)
+		base_addr[CyLIVR] = 0x5c;
+
+	/* tx and rx baud rate */
+
+	if (base_addr[CyCOR1] != info->cor1)
+		need_init_chan = 1;
+	if (base_addr[CyTCOR] != info->tco)
+		base_addr[CyTCOR] = info->tco;
+	if (base_addr[CyTBPR] != info->tbpr)
+		base_addr[CyTBPR] = info->tbpr;
+	if (base_addr[CyRCOR] != info->rco)
+		base_addr[CyRCOR] = info->rco;
+	if (base_addr[CyRBPR] != info->rbpr)
+		base_addr[CyRBPR] = info->rbpr;
+
+	/* set line characteristics  according configuration */
+
+	if (base_addr[CySCHR1] != START_CHAR(info->tty))
+		base_addr[CySCHR1] = START_CHAR(info->tty);
+	if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
+		base_addr[CySCHR2] = STOP_CHAR(info->tty);
+	if (base_addr[CySCRL] != START_CHAR(info->tty))
+		base_addr[CySCRL] = START_CHAR(info->tty);
+	if (base_addr[CySCRH] != START_CHAR(info->tty))
+		base_addr[CySCRH] = START_CHAR(info->tty);
+	if (base_addr[CyCOR1] != info->cor1)
+		base_addr[CyCOR1] = info->cor1;
+	if (base_addr[CyCOR2] != info->cor2)
+		base_addr[CyCOR2] = info->cor2;
+	if (base_addr[CyCOR3] != info->cor3)
+		base_addr[CyCOR3] = info->cor3;
+	if (base_addr[CyCOR4] != info->cor4)
+		base_addr[CyCOR4] = info->cor4;
+	if (base_addr[CyCOR5] != info->cor5)
+		base_addr[CyCOR5] = info->cor5;
+	if (base_addr[CyCOR6] != info->cor6)
+		base_addr[CyCOR6] = info->cor6;
+	if (base_addr[CyCOR7] != info->cor7)
+		base_addr[CyCOR7] = info->cor7;
+
+	if (need_init_chan)
+		write_cy_cmd(base_addr, CyINIT_CHAN);
+
+	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
+
+	/* 2ms default rx timeout */
+	ti = info->default_timeout ? info->default_timeout : 0x02;
+	if (base_addr[CyRTPRL] != ti)
+		base_addr[CyRTPRL] = ti;
+	if (base_addr[CyRTPRH] != 0)
+		base_addr[CyRTPRH] = 0;
+
+	/* Set up RTS here also ????? RGH 141095 */
+	if (i == 0) {		/* baud rate is zero, turn off line */
+		if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
+			base_addr[CyMSVR2] = 0;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: dropping DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+	} else {
+		if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
+			base_addr[CyMSVR2] = CyDTR;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: raising DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+	}
+
+	if (info->tty) {
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	}
+
+	local_irq_restore(flags);
+
+}				/* config_setup */
+
+static int cy_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+
+#ifdef SERIAL_DEBUG_IO
+	printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+		return 0;
+
+	if (!info->xmit_buf)
+		return 0;
+
+	local_irq_save(flags);
+	if (info->xmit_cnt >= PAGE_SIZE - 1) {
+		local_irq_restore(flags);
+		return 0;
+	}
+
+	info->xmit_buf[info->xmit_head++] = ch;
+	info->xmit_head &= PAGE_SIZE - 1;
+	info->xmit_cnt++;
+	local_irq_restore(flags);
+	return 1;
+}				/* cy_put_char */
+
+static void cy_flush_chars(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+
+#ifdef SERIAL_DEBUG_IO
+	printk("cy_flush_chars %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped
+	    || tty->hw_stopped || !info->xmit_buf)
+		return;
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = channel;
+	base_addr[CyIER] |= CyTxMpty;
+	local_irq_restore(flags);
+}				/* cy_flush_chars */
+
+/* This routine gets called when tty_write has put something into
+    the write_queue.  If the port is not already transmitting stuff,
+    start it off by enabling interrupts.  The interrupt service
+    routine will then ensure that the characters are sent.  If the
+    port is already active, there is no need to kick it.
+ */
+static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+	int c, total = 0;
+
+#ifdef SERIAL_DEBUG_IO
+	printk("cy_write %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_write")) {
+		return 0;
+	}
+
+	if (!info->xmit_buf) {
+		return 0;
+	}
+
+	while (1) {
+		local_irq_save(flags);
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
+		if (c <= 0) {
+			local_irq_restore(flags);
+			break;
+		}
+
+		memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		info->xmit_head =
+		    (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+		info->xmit_cnt += c;
+		local_irq_restore(flags);
+
+		buf += c;
+		count -= c;
+		total += c;
+	}
+
+	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+		start_xmit(info);
+	}
+	return total;
+}				/* cy_write */
+
+static int cy_write_room(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	int ret;
+
+#ifdef SERIAL_DEBUG_IO
+	printk("cy_write_room %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
+		return 0;
+	ret = PAGE_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}				/* cy_write_room */
+
+static int cy_chars_in_buffer(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+#ifdef SERIAL_DEBUG_IO
+	printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
+		return 0;
+
+	return info->xmit_cnt;
+}				/* cy_chars_in_buffer */
+
+static void cy_flush_buffer(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+
+#ifdef SERIAL_DEBUG_IO
+	printk("cy_flush_buffer %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+		return;
+	local_irq_save(flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	local_irq_restore(flags);
+	tty_wakeup(tty);
+}				/* cy_flush_buffer */
+
+/* This routine is called by the upper-layer tty layer to signal
+   that incoming characters should be throttled or that the
+   throttle should be released.
+ */
+static void cy_throttle(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+	char buf[64];
+
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+	printk("cy_throttle %s\n", tty->name);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
+		return;
+	}
+
+	if (I_IXOFF(tty)) {
+		info->x_char = STOP_CHAR(tty);
+		/* Should use the "Send Special Character" feature!!! */
+	}
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+	base_addr[CyMSVR1] = 0;
+	local_irq_restore(flags);
+}				/* cy_throttle */
+
+static void cy_unthrottle(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+
+#ifdef SERIAL_DEBUG_THROTTLE
+	char buf[64];
+
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+	printk("cy_unthrottle %s\n", tty->name);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
+		return;
+	}
+
+	if (I_IXOFF(tty)) {
+		info->x_char = START_CHAR(tty);
+		/* Should use the "Send Special Character" feature!!! */
+	}
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+	base_addr[CyMSVR1] = CyRTS;
+	local_irq_restore(flags);
+}				/* cy_unthrottle */
+
+static int
+get_serial_info(struct cyclades_port *info,
+		struct serial_struct __user * retinfo)
+{
+	struct serial_struct tmp;
+
+/* CP('g'); */
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->line;
+	tmp.port = info->line;
+	tmp.irq = 0;
+	tmp.flags = info->flags;
+	tmp.baud_base = 0;	/*!!! */
+	tmp.close_delay = info->close_delay;
+	tmp.custom_divisor = 0;	/*!!! */
+	tmp.hub6 = 0;		/*!!! */
+	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+}				/* get_serial_info */
+
+static int
+set_serial_info(struct cyclades_port *info,
+		struct serial_struct __user * new_info)
+{
+	struct serial_struct new_serial;
+	struct cyclades_port old_info;
+
+/* CP('s'); */
+	if (!new_info)
+		return -EFAULT;
+	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+		return -EFAULT;
+	old_info = *info;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((new_serial.close_delay != info->close_delay) ||
+		    ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
+		     (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		goto check_and_exit;
+	}
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	info->flags = ((info->flags & ~ASYNC_FLAGS) |
+		       (new_serial.flags & ASYNC_FLAGS));
+	info->close_delay = new_serial.close_delay;
+
+check_and_exit:
+	if (info->flags & ASYNC_INITIALIZED) {
+		config_setup(info);
+		return 0;
+	}
+	return startup(info);
+}				/* set_serial_info */
+
+static int cy_tiocmget(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	int channel;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long flags;
+	unsigned char status;
+
+	channel = info->line;
+
+	local_irq_save(flags);
+	base_addr[CyCAR] = (u_char) channel;
+	status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
+	local_irq_restore(flags);
+
+	return ((status & CyRTS) ? TIOCM_RTS : 0)
+	    | ((status & CyDTR) ? TIOCM_DTR : 0)
+	    | ((status & CyDCD) ? TIOCM_CAR : 0)
+	    | ((status & CyDSR) ? TIOCM_DSR : 0)
+	    | ((status & CyCTS) ? TIOCM_CTS : 0);
+}				/* cy_tiocmget */
+
+static int
+cy_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
+{
+	struct cyclades_port *info = tty->driver_data;
+	int channel;
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long flags;
+
+	channel = info->line;
+
+	if (set & TIOCM_RTS) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+		base_addr[CyMSVR1] = CyRTS;
+		local_irq_restore(flags);
+	}
+	if (set & TIOCM_DTR) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+/* CP('S');CP('2'); */
+		base_addr[CyMSVR2] = CyDTR;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: raising DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+		local_irq_restore(flags);
+	}
+
+	if (clear & TIOCM_RTS) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+		base_addr[CyMSVR1] = 0;
+		local_irq_restore(flags);
+	}
+	if (clear & TIOCM_DTR) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+/* CP('C');CP('2'); */
+		base_addr[CyMSVR2] = 0;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: dropping DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+		local_irq_restore(flags);
+	}
+
+	return 0;
+}				/* set_modem_info */
+
+static void send_break(struct cyclades_port *info, int duration)
+{				/* Let the transmit ISR take care of this (since it
+				   requires stuffing characters into the output stream).
+				 */
+	info->x_break = duration;
+	if (!info->xmit_cnt) {
+		start_xmit(info);
+	}
+}				/* send_break */
+
+static int
+get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
+{
+
+	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
+		return -EFAULT;
+	info->mon.int_count = 0;
+	info->mon.char_count = 0;
+	info->mon.char_max = 0;
+	info->mon.char_last = 0;
+	return 0;
+}
+
+static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long value;
+	int channel;
+
+	if (get_user(value, arg))
+		return -EFAULT;
+
+	channel = info->line;
+	info->cor4 &= ~CyREC_FIFO;
+	info->cor4 |= value & CyREC_FIFO;
+	base_addr[CyCOR4] = info->cor4;
+	return 0;
+}
+
+static int
+get_threshold(struct cyclades_port *info, unsigned long __user * value)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned long tmp;
+
+	channel = info->line;
+
+	tmp = base_addr[CyCOR4] & CyREC_FIFO;
+	return put_user(tmp, value);
+}
+
+static int
+set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
+{
+	unsigned long value;
+
+	if (get_user(value, arg))
+		return -EFAULT;
+
+	info->default_threshold = value & 0x0f;
+	return 0;
+}
+
+static int
+get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
+{
+	return put_user(info->default_threshold, value);
+}
+
+static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned long value;
+
+	if (get_user(value, arg))
+		return -EFAULT;
+
+	channel = info->line;
+
+	base_addr[CyRTPRL] = value & 0xff;
+	base_addr[CyRTPRH] = (value >> 8) & 0xff;
+	return 0;
+}
+
+static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	unsigned long tmp;
+
+	channel = info->line;
+
+	tmp = base_addr[CyRTPRL];
+	return put_user(tmp, value);
+}
+
+static int set_default_timeout(struct cyclades_port *info, unsigned long value)
+{
+	info->default_timeout = value & 0xff;
+	return 0;
+}
+
+static int
+get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
+{
+	return put_user(info->default_timeout, value);
+}
+
+static int
+cy_ioctl(struct tty_struct *tty,
+	 unsigned int cmd, unsigned long arg)
+{
+	struct cyclades_port *info = tty->driver_data;
+	int ret_val = 0;
+	void __user *argp = (void __user *)arg;
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);	/* */
+#endif
+
+	tty_lock();
+
+	switch (cmd) {
+	case CYGETMON:
+		ret_val = get_mon_info(info, argp);
+		break;
+	case CYGETTHRESH:
+		ret_val = get_threshold(info, argp);
+		break;
+	case CYSETTHRESH:
+		ret_val = set_threshold(info, argp);
+		break;
+	case CYGETDEFTHRESH:
+		ret_val = get_default_threshold(info, argp);
+		break;
+	case CYSETDEFTHRESH:
+		ret_val = set_default_threshold(info, argp);
+		break;
+	case CYGETTIMEOUT:
+		ret_val = get_timeout(info, argp);
+		break;
+	case CYSETTIMEOUT:
+		ret_val = set_timeout(info, argp);
+		break;
+	case CYGETDEFTIMEOUT:
+		ret_val = get_default_timeout(info, argp);
+		break;
+	case CYSETDEFTIMEOUT:
+		ret_val = set_default_timeout(info, (unsigned long)arg);
+		break;
+	case TCSBRK:		/* SVID version: non-zero arg --> no break */
+		ret_val = tty_check_change(tty);
+		if (ret_val)
+			break;
+		tty_wait_until_sent(tty, 0);
+		if (!arg)
+			send_break(info, HZ / 4);	/* 1/4 second */
+		break;
+	case TCSBRKP:		/* support for POSIX tcsendbreak() */
+		ret_val = tty_check_change(tty);
+		if (ret_val)
+			break;
+		tty_wait_until_sent(tty, 0);
+		send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
+		break;
+
+/* The following commands are incompletely implemented!!! */
+	case TIOCGSERIAL:
+		ret_val = get_serial_info(info, argp);
+		break;
+	case TIOCSSERIAL:
+		ret_val = set_serial_info(info, argp);
+		break;
+	default:
+		ret_val = -ENOIOCTLCMD;
+	}
+	tty_unlock();
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_ioctl done\n");
+#endif
+
+	return ret_val;
+}				/* cy_ioctl */
+
+static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_set_termios %s\n", tty->name);
+#endif
+
+	if (tty->termios->c_cflag == old_termios->c_cflag)
+		return;
+	config_setup(info);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->stopped = 0;
+		cy_start(tty);
+	}
+#ifdef tytso_patch_94Nov25_1726
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->open_wait);
+#endif
+}				/* cy_set_termios */
+
+static void cy_close(struct tty_struct *tty, struct file *filp)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+/* CP('C'); */
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_close %s\n", tty->name);
+#endif
+
+	if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
+		return;
+	}
+#ifdef SERIAL_DEBUG_OPEN
+	printk("cy_close %s, count = %d\n", tty->name, info->count);
+#endif
+
+	if ((tty->count == 1) && (info->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  Info->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("cy_close: bad serial port count; tty->count is 1, "
+		       "info->count is %d\n", info->count);
+		info->count = 1;
+	}
+#ifdef SERIAL_DEBUG_COUNT
+	printk("cyc: %d: decrementing count to %d\n", __LINE__,
+	       info->count - 1);
+#endif
+	if (--info->count < 0) {
+		printk("cy_close: bad serial port count for ttys%d: %d\n",
+		       info->line, info->count);
+#ifdef SERIAL_DEBUG_COUNT
+		printk("cyc: %d: setting count to 0\n", __LINE__);
+#endif
+		info->count = 0;
+	}
+	if (info->count)
+		return;
+	info->flags |= ASYNC_CLOSING;
+	if (info->flags & ASYNC_INITIALIZED)
+		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
+	shutdown(info);
+	cy_flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	info->tty = NULL;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			msleep_interruptible(jiffies_to_msecs
+					     (info->close_delay));
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_close done\n");
+#endif
+}				/* cy_close */
+
+/*
+ * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+void cy_hangup(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_hangup %s\n", tty->name);	/* */
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
+		return;
+
+	shutdown(info);
+#if 0
+	info->event = 0;
+	info->count = 0;
+#ifdef SERIAL_DEBUG_COUNT
+	printk("cyc: %d: setting count to 0\n", __LINE__);
+#endif
+	info->tty = 0;
+#endif
+	info->flags &= ~ASYNC_NORMAL_ACTIVE;
+	wake_up_interruptible(&info->open_wait);
+}				/* cy_hangup */
+
+/*
+ * ------------------------------------------------------------
+ * cy_open() and friends
+ * ------------------------------------------------------------
+ */
+
+static int
+block_til_ready(struct tty_struct *tty, struct file *filp,
+		struct cyclades_port *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int channel;
+	int retval;
+	volatile u_char *base_addr = (u_char *) BASE_ADDR;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (info->flags & ASYNC_CLOSING) {
+		interruptible_sleep_on(&info->close_wait);
+		if (info->flags & ASYNC_HUP_NOTIFY) {
+			return -EAGAIN;
+		} else {
+			return -ERESTARTSYS;
+		}
+	}
+
+	/*
+	 * If non-blocking mode is set, then make the check up front
+	 * and then exit.
+	 */
+	if (filp->f_flags & O_NONBLOCK) {
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * cy_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: %s, count = %d\n",
+	       tty->name, info->count);
+	/**/
+#endif
+	    info->count--;
+#ifdef SERIAL_DEBUG_COUNT
+	printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
+#endif
+	info->blocked_open++;
+
+	channel = info->line;
+
+	while (1) {
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+		base_addr[CyMSVR1] = CyRTS;
+/* CP('S');CP('4'); */
+		base_addr[CyMSVR2] = CyDTR;
+#ifdef SERIAL_DEBUG_DTR
+		printk("cyc: %d: raising DTR\n", __LINE__);
+		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
+		       base_addr[CyMSVR2]);
+#endif
+		local_irq_restore(flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp)
+		    || !(info->flags & ASYNC_INITIALIZED)) {
+			if (info->flags & ASYNC_HUP_NOTIFY) {
+				retval = -EAGAIN;
+			} else {
+				retval = -ERESTARTSYS;
+			}
+			break;
+		}
+		local_irq_save(flags);
+		base_addr[CyCAR] = (u_char) channel;
+/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
+		if (!(info->flags & ASYNC_CLOSING)
+		    && (C_CLOCAL(tty)
+			|| (base_addr[CyMSVR1] & CyDCD))) {
+			local_irq_restore(flags);
+			break;
+		}
+		local_irq_restore(flags);
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: %s, count = %d\n",
+		       tty->name, info->count);
+		/**/
+#endif
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp)) {
+		info->count++;
+#ifdef SERIAL_DEBUG_COUNT
+		printk("cyc: %d: incrementing count to %d\n", __LINE__,
+		       info->count);
+#endif
+	}
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: %s, count = %d\n",
+	       tty->name, info->count);
+	/**/
+#endif
+	    if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}				/* block_til_ready */
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * performs the serial-specific initialization for the tty structure.
+ */
+int cy_open(struct tty_struct *tty, struct file *filp)
+{
+	struct cyclades_port *info;
+	int retval, line;
+
+/* CP('O'); */
+	line = tty->index;
+	if ((line < 0) || (NR_PORTS <= line)) {
+		return -ENODEV;
+	}
+	info = &cy_port[line];
+	if (info->line < 0) {
+		return -ENODEV;
+	}
+#ifdef SERIAL_DEBUG_OTHER
+	printk("cy_open %s\n", tty->name);	/* */
+#endif
+	if (serial_paranoia_check(info, tty->name, "cy_open")) {
+		return -ENODEV;
+	}
+#ifdef SERIAL_DEBUG_OPEN
+	printk("cy_open %s, count = %d\n", tty->name, info->count);
+	/**/
+#endif
+	    info->count++;
+#ifdef SERIAL_DEBUG_COUNT
+	printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
+#endif
+	tty->driver_data = info;
+	info->tty = tty;
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval) {
+		return retval;
+	}
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("cy_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+#ifdef SERIAL_DEBUG_OPEN
+	printk("cy_open done\n");
+	/**/
+#endif
+	    return 0;
+}				/* cy_open */
+
+/*
+ * ---------------------------------------------------------------------
+ * serial167_init() and friends
+ *
+ * serial167_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static void show_version(void)
+{
+	printk("MVME166/167 cd2401 driver\n");
+}				/* show_version */
+
+/* initialize chips on card -- return number of valid
+   chips (which is number of ports/4) */
+
+/*
+ * This initialises the hardware to a reasonable state.  It should
+ * probe the chip first so as to copy 166-Bug setup as a default for
+ * port 0.  It initialises CMR to CyASYNC; that is never done again, so
+ * as to limit the number of CyINIT_CHAN commands in normal running.
+ *
+ * ... I wonder what I should do if this fails ...
+ */
+
+void mvme167_serial_console_setup(int cflag)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int ch;
+	u_char spd;
+	u_char rcor, rbpr, badspeed = 0;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/*
+	 * First probe channel zero of the chip, to see what speed has
+	 * been selected.
+	 */
+
+	base_addr[CyCAR] = 0;
+
+	rcor = base_addr[CyRCOR] << 5;
+	rbpr = base_addr[CyRBPR];
+
+	for (spd = 0; spd < sizeof(baud_bpr); spd++)
+		if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
+			break;
+	if (spd >= sizeof(baud_bpr)) {
+		spd = 14;	/* 19200 */
+		badspeed = 1;	/* Failed to identify speed */
+	}
+	initial_console_speed = spd;
+
+	/* OK, we have chosen a speed, now reset and reinitialise */
+
+	my_udelay(20000L);	/* Allow time for any active o/p to complete */
+	if (base_addr[CyCCR] != 0x00) {
+		local_irq_restore(flags);
+		/* printk(" chip is never idle (CCR != 0)\n"); */
+		return;
+	}
+
+	base_addr[CyCCR] = CyCHIP_RESET;	/* Reset the chip */
+	my_udelay(1000L);
+
+	if (base_addr[CyGFRCR] == 0x00) {
+		local_irq_restore(flags);
+		/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
+		return;
+	}
+
+	/*
+	 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
+	 * tick
+	 */
+
+	base_addr[CyTPR] = 10;
+
+	base_addr[CyPILR1] = 0x01;	/* Interrupt level for modem change */
+	base_addr[CyPILR2] = 0x02;	/* Interrupt level for tx ints */
+	base_addr[CyPILR3] = 0x03;	/* Interrupt level for rx ints */
+
+	/*
+	 * Attempt to set up all channels to something reasonable, and
+	 * bang out a INIT_CHAN command.  We should then be able to limit
+	 * the amount of fiddling we have to do in normal running.
+	 */
+
+	for (ch = 3; ch >= 0; ch--) {
+		base_addr[CyCAR] = (u_char) ch;
+		base_addr[CyIER] = 0;
+		base_addr[CyCMR] = CyASYNC;
+		base_addr[CyLICR] = (u_char) ch << 2;
+		base_addr[CyLIVR] = 0x5c;
+		base_addr[CyTCOR] = baud_co[spd];
+		base_addr[CyTBPR] = baud_bpr[spd];
+		base_addr[CyRCOR] = baud_co[spd] >> 5;
+		base_addr[CyRBPR] = baud_bpr[spd];
+		base_addr[CySCHR1] = 'Q' & 0x1f;
+		base_addr[CySCHR2] = 'X' & 0x1f;
+		base_addr[CySCRL] = 0;
+		base_addr[CySCRH] = 0;
+		base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
+		base_addr[CyCOR2] = 0;
+		base_addr[CyCOR3] = Cy_1_STOP;
+		base_addr[CyCOR4] = baud_cor4[spd];
+		base_addr[CyCOR5] = 0;
+		base_addr[CyCOR6] = 0;
+		base_addr[CyCOR7] = 0;
+		base_addr[CyRTPRL] = 2;
+		base_addr[CyRTPRH] = 0;
+		base_addr[CyMSVR1] = 0;
+		base_addr[CyMSVR2] = 0;
+		write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
+	}
+
+	/*
+	 * Now do specials for channel zero....
+	 */
+
+	base_addr[CyMSVR1] = CyRTS;
+	base_addr[CyMSVR2] = CyDTR;
+	base_addr[CyIER] = CyRxData;
+	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
+
+	local_irq_restore(flags);
+
+	my_udelay(20000L);	/* Let it all settle down */
+
+	printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
+	if (badspeed)
+		printk
+		    ("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
+		     rcor >> 5, rbpr);
+}				/* serial_console_init */
+
+static const struct tty_operations cy_ops = {
+	.open = cy_open,
+	.close = cy_close,
+	.write = cy_write,
+	.put_char = cy_put_char,
+	.flush_chars = cy_flush_chars,
+	.write_room = cy_write_room,
+	.chars_in_buffer = cy_chars_in_buffer,
+	.flush_buffer = cy_flush_buffer,
+	.ioctl = cy_ioctl,
+	.throttle = cy_throttle,
+	.unthrottle = cy_unthrottle,
+	.set_termios = cy_set_termios,
+	.stop = cy_stop,
+	.start = cy_start,
+	.hangup = cy_hangup,
+	.tiocmget = cy_tiocmget,
+	.tiocmset = cy_tiocmset,
+};
+
+/* The serial driver boot-time initialization code!
+    Hardware I/O ports are mapped to character special devices on a
+    first found, first allocated manner.  That is, this code searches
+    for Cyclom cards in the system.  As each is found, it is probed
+    to discover how many chips (and thus how many ports) are present.
+    These ports are mapped to the tty ports 64 and upward in monotonic
+    fashion.  If an 8-port card is replaced with a 16-port card, the
+    port mapping on a following card will shift.
+
+    This approach is different from what is used in the other serial
+    device driver because the Cyclom is more properly a multiplexer,
+    not just an aggregation of serial ports on one card.
+
+    If there are more cards with more ports than have been statically
+    allocated above, a warning is printed and the extra ports are ignored.
+ */
+static int __init serial167_init(void)
+{
+	struct cyclades_port *info;
+	int ret = 0;
+	int good_ports = 0;
+	int port_num = 0;
+	int index;
+	int DefSpeed;
+#ifdef notyet
+	struct sigaction sa;
+#endif
+
+	if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
+		return 0;
+
+	cy_serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!cy_serial_driver)
+		return -ENOMEM;
+
+#if 0
+	scrn[1] = '\0';
+#endif
+
+	show_version();
+
+	/* Has "console=0,9600n8" been used in bootinfo to change speed? */
+	if (serial_console_cflag)
+		DefSpeed = serial_console_cflag & 0017;
+	else {
+		DefSpeed = initial_console_speed;
+		serial_console_info = &cy_port[0];
+		serial_console_cflag = DefSpeed | CS8;
+#if 0
+		serial_console = 64;	/*callout_driver.minor_start */
+#endif
+	}
+
+	/* Initialize the tty_driver structure */
+
+	cy_serial_driver->owner = THIS_MODULE;
+	cy_serial_driver->name = "ttyS";
+	cy_serial_driver->major = TTY_MAJOR;
+	cy_serial_driver->minor_start = 64;
+	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	cy_serial_driver->init_termios = tty_std_termios;
+	cy_serial_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(cy_serial_driver, &cy_ops);
+
+	ret = tty_register_driver(cy_serial_driver);
+	if (ret) {
+		printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
+		put_tty_driver(cy_serial_driver);
+		return ret;
+	}
+
+	port_num = 0;
+	info = cy_port;
+	for (index = 0; index < 1; index++) {
+
+		good_ports = 4;
+
+		if (port_num < NR_PORTS) {
+			while (good_ports-- && port_num < NR_PORTS) {
+		/*** initialize port ***/
+				info->magic = CYCLADES_MAGIC;
+				info->type = PORT_CIRRUS;
+				info->card = index;
+				info->line = port_num;
+				info->flags = STD_COM_FLAGS;
+				info->tty = NULL;
+				info->xmit_fifo_size = 12;
+				info->cor1 = CyPARITY_NONE | Cy_8_BITS;
+				info->cor2 = CyETC;
+				info->cor3 = Cy_1_STOP;
+				info->cor4 = 0x08;	/* _very_ small receive threshold */
+				info->cor5 = 0;
+				info->cor6 = 0;
+				info->cor7 = 0;
+				info->tbpr = baud_bpr[DefSpeed];	/* Tx BPR */
+				info->tco = baud_co[DefSpeed];	/* Tx CO */
+				info->rbpr = baud_bpr[DefSpeed];	/* Rx BPR */
+				info->rco = baud_co[DefSpeed] >> 5;	/* Rx CO */
+				info->close_delay = 0;
+				info->x_char = 0;
+				info->count = 0;
+#ifdef SERIAL_DEBUG_COUNT
+				printk("cyc: %d: setting count to 0\n",
+				       __LINE__);
+#endif
+				info->blocked_open = 0;
+				info->default_threshold = 0;
+				info->default_timeout = 0;
+				init_waitqueue_head(&info->open_wait);
+				init_waitqueue_head(&info->close_wait);
+				/* info->session */
+				/* info->pgrp */
+/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
+				info->read_status_mask =
+				    CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
+				    CyFRAME | CyOVERRUN;
+				/* info->timeout */
+
+				printk("ttyS%d ", info->line);
+				port_num++;
+				info++;
+				if (!(port_num & 7)) {
+					printk("\n               ");
+				}
+			}
+		}
+		printk("\n");
+	}
+	while (port_num < NR_PORTS) {
+		info->line = -1;
+		port_num++;
+		info++;
+	}
+
+	ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
+			  "cd2401_errors", cd2401_rxerr_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_errors IRQ");
+		goto cleanup_serial_driver;
+	}
+
+	ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
+			  "cd2401_modem", cd2401_modem_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_modem IRQ");
+		goto cleanup_irq_cd2401_errors;
+	}
+
+	ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
+			  "cd2401_txints", cd2401_tx_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_txints IRQ");
+		goto cleanup_irq_cd2401_modem;
+	}
+
+	ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
+			  "cd2401_rxints", cd2401_rx_interrupt);
+	if (ret) {
+		printk(KERN_ERR "Could't get cd2401_rxints IRQ");
+		goto cleanup_irq_cd2401_txints;
+	}
+
+	/* Now we have registered the interrupt handlers, allow the interrupts */
+
+	pcc2chip[PccSCCMICR] = 0x15;	/* Serial ints are level 5 */
+	pcc2chip[PccSCCTICR] = 0x15;
+	pcc2chip[PccSCCRICR] = 0x15;
+
+	pcc2chip[PccIMLR] = 3;	/* Allow PCC2 ints above 3!? */
+
+	return 0;
+cleanup_irq_cd2401_txints:
+	free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
+cleanup_irq_cd2401_modem:
+	free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
+cleanup_irq_cd2401_errors:
+	free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
+cleanup_serial_driver:
+	if (tty_unregister_driver(cy_serial_driver))
+		printk(KERN_ERR
+		       "Couldn't unregister MVME166/7 serial driver\n");
+	put_tty_driver(cy_serial_driver);
+	return ret;
+}				/* serial167_init */
+
+module_init(serial167_init);
+
+#ifdef CYCLOM_SHOW_STATUS
+static void show_status(int line_num)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	int channel;
+	struct cyclades_port *info;
+	unsigned long flags;
+
+	info = &cy_port[line_num];
+	channel = info->line;
+	printk("  channel %d\n", channel);
+	/**/ printk(" cy_port\n");
+	printk("  card line flags = %d %d %x\n",
+	       info->card, info->line, info->flags);
+	printk
+	    ("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
+	     (long)info->tty, info->read_status_mask, info->timeout,
+	     info->xmit_fifo_size);
+	printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
+	       info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
+	       info->cor6, info->cor7);
+	printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
+	       info->rbpr, info->rco);
+	printk("  close_delay event count = %d %d %d\n", info->close_delay,
+	       info->event, info->count);
+	printk("  x_char blocked_open = %x %x\n", info->x_char,
+	       info->blocked_open);
+	printk("  open_wait = %lx %lx %lx\n", (long)info->open_wait);
+
+	local_irq_save(flags);
+
+/* Global Registers */
+
+	printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
+	printk(" CyCAR %x\n", base_addr[CyCAR]);
+	printk(" CyRISR %x\n", base_addr[CyRISR]);
+	printk(" CyTISR %x\n", base_addr[CyTISR]);
+	printk(" CyMISR %x\n", base_addr[CyMISR]);
+	printk(" CyRIR %x\n", base_addr[CyRIR]);
+	printk(" CyTIR %x\n", base_addr[CyTIR]);
+	printk(" CyMIR %x\n", base_addr[CyMIR]);
+	printk(" CyTPR %x\n", base_addr[CyTPR]);
+
+	base_addr[CyCAR] = (u_char) channel;
+
+/* Virtual Registers */
+
+#if 0
+	printk(" CyRIVR %x\n", base_addr[CyRIVR]);
+	printk(" CyTIVR %x\n", base_addr[CyTIVR]);
+	printk(" CyMIVR %x\n", base_addr[CyMIVR]);
+	printk(" CyMISR %x\n", base_addr[CyMISR]);
+#endif
+
+/* Channel Registers */
+
+	printk(" CyCCR %x\n", base_addr[CyCCR]);
+	printk(" CyIER %x\n", base_addr[CyIER]);
+	printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
+	printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
+	printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
+	printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
+	printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
+#if 0
+	printk(" CyCCSR %x\n", base_addr[CyCCSR]);
+	printk(" CyRDCR %x\n", base_addr[CyRDCR]);
+#endif
+	printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
+	printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
+#if 0
+	printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
+	printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
+	printk(" CySCRL %x\n", base_addr[CySCRL]);
+	printk(" CySCRH %x\n", base_addr[CySCRH]);
+	printk(" CyLNC %x\n", base_addr[CyLNC]);
+	printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
+	printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
+#endif
+	printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
+	printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
+	printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
+	printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
+	printk(" CyRBPR %x\n", base_addr[CyRBPR]);
+	printk(" CyRCOR %x\n", base_addr[CyRCOR]);
+	printk(" CyTBPR %x\n", base_addr[CyTBPR]);
+	printk(" CyTCOR %x\n", base_addr[CyTCOR]);
+
+	local_irq_restore(flags);
+}				/* show_status */
+#endif
+
+#if 0
+/* Dummy routine in mvme16x/config.c for now */
+
+/* Serial console setup. Called from linux/init/main.c */
+
+void console_setup(char *str, int *ints)
+{
+	char *s;
+	int baud, bits, parity;
+	int cflag = 0;
+
+	/* Sanity check. */
+	if (ints[0] > 3 || ints[1] > 3)
+		return;
+
+	/* Get baud, bits and parity */
+	baud = 2400;
+	bits = 8;
+	parity = 'n';
+	if (ints[2])
+		baud = ints[2];
+	if ((s = strchr(str, ','))) {
+		do {
+			s++;
+		} while (*s >= '0' && *s <= '9');
+		if (*s)
+			parity = *s++;
+		if (*s)
+			bits = *s - '0';
+	}
+
+	/* Now construct a cflag setting. */
+	switch (baud) {
+	case 1200:
+		cflag |= B1200;
+		break;
+	case 9600:
+		cflag |= B9600;
+		break;
+	case 19200:
+		cflag |= B19200;
+		break;
+	case 38400:
+		cflag |= B38400;
+		break;
+	case 2400:
+	default:
+		cflag |= B2400;
+		break;
+	}
+	switch (bits) {
+	case 7:
+		cflag |= CS7;
+		break;
+	default:
+	case 8:
+		cflag |= CS8;
+		break;
+	}
+	switch (parity) {
+	case 'o':
+	case 'O':
+		cflag |= PARODD;
+		break;
+	case 'e':
+	case 'E':
+		cflag |= PARENB;
+		break;
+	}
+
+	serial_console_info = &cy_port[ints[1]];
+	serial_console_cflag = cflag;
+	serial_console = ints[1] + 64;	/*callout_driver.minor_start */
+}
+#endif
+
+/*
+ * The following is probably out of date for 2.1.x serial console stuff.
+ *
+ * The console is registered early on from arch/m68k/kernel/setup.c, and
+ * it therefore relies on the chip being setup correctly by 166-Bug.  This
+ * seems reasonable, as the serial port has been used to invoke the system
+ * boot.  It also means that this function must not rely on any data
+ * initialisation performed by serial167_init() etc.
+ *
+ * Of course, once the console has been registered, we had better ensure
+ * that serial167_init() doesn't leave the chip non-functional.
+ *
+ * The console must be locked when we get here.
+ */
+
+void serial167_console_write(struct console *co, const char *str,
+			     unsigned count)
+{
+	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
+	unsigned long flags;
+	volatile u_char sink;
+	u_char ier;
+	int port;
+	u_char do_lf = 0;
+	int i = 0;
+
+	local_irq_save(flags);
+
+	/* Ensure transmitter is enabled! */
+
+	port = 0;
+	base_addr[CyCAR] = (u_char) port;
+	while (base_addr[CyCCR])
+		;
+	base_addr[CyCCR] = CyENB_XMTR;
+
+	ier = base_addr[CyIER];
+	base_addr[CyIER] = CyTxMpty;
+
+	while (1) {
+		if (pcc2chip[PccSCCTICR] & 0x20) {
+			/* We have a Tx int. Acknowledge it */
+			sink = pcc2chip[PccTPIACKR];
+			if ((base_addr[CyLICR] >> 2) == port) {
+				if (i == count) {
+					/* Last char of string is now output */
+					base_addr[CyTEOIR] = CyNOTRANS;
+					break;
+				}
+				if (do_lf) {
+					base_addr[CyTDR] = '\n';
+					str++;
+					i++;
+					do_lf = 0;
+				} else if (*str == '\n') {
+					base_addr[CyTDR] = '\r';
+					do_lf = 1;
+				} else {
+					base_addr[CyTDR] = *str++;
+					i++;
+				}
+				base_addr[CyTEOIR] = 0;
+			} else
+				base_addr[CyTEOIR] = CyNOTRANS;
+		}
+	}
+
+	base_addr[CyIER] = ier;
+
+	local_irq_restore(flags);
+}
+
+static struct tty_driver *serial167_console_device(struct console *c,
+						   int *index)
+{
+	*index = c->index;
+	return cy_serial_driver;
+}
+
+static struct console sercons = {
+	.name = "ttyS",
+	.write = serial167_console_write,
+	.device = serial167_console_device,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
+};
+
+static int __init serial167_console_init(void)
+{
+	if (vme_brdtype == VME_TYPE_MVME166 ||
+	    vme_brdtype == VME_TYPE_MVME167 ||
+	    vme_brdtype == VME_TYPE_MVME177) {
+		mvme167_serial_console_setup(0);
+		register_console(&sercons);
+	}
+	return 0;
+}
+
+console_initcall(serial167_console_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/tty/specialix.c b/drivers/staging/tty/specialix.c
new file mode 100644
index 0000000..47e5753
--- /dev/null
+++ b/drivers/staging/tty/specialix.c
@@ -0,0 +1,2368 @@
+/*
+ *      specialix.c  -- specialix IO8+ multiport serial driver.
+ *
+ *      Copyright (C) 1997  Roger Wolff (R.E.Wolff@BitWizard.nl)
+ *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
+ *
+ *      Specialix pays for the development and support of this driver.
+ *      Please DO contact io8-linux@specialix.co.uk if you require
+ *      support. But please read the documentation (specialix.txt)
+ *      first.
+ *
+ *      This driver was developped in the BitWizard linux device
+ *      driver service. If you require a linux device driver for your
+ *      product, please contact devices@BitWizard.nl for a quote.
+ *
+ *      This code is firmly based on the riscom/8 serial driver,
+ *      written by Dmitry Gorodchanin. The specialix IO8+ card
+ *      programming information was obtained from the CL-CD1865 Data
+ *      Book, and Specialix document number 6200059: IO8+ Hardware
+ *      Functional Specification.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be
+ *      useful, but WITHOUT ANY WARRANTY; without even the implied
+ *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *      PURPOSE.  See the GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public
+ *      License along with this program; if not, write to the Free
+ *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ *      USA.
+ *
+ * Revision history:
+ *
+ * Revision 1.0:  April 1st 1997.
+ *                Initial release for alpha testing.
+ * Revision 1.1:  April 14th 1997.
+ *                Incorporated Richard Hudsons suggestions,
+ *                removed some debugging printk's.
+ * Revision 1.2:  April 15th 1997.
+ *                Ported to 2.1.x kernels.
+ * Revision 1.3:  April 17th 1997
+ *                Backported to 2.0. (Compatibility macros).
+ * Revision 1.4:  April 18th 1997
+ *                Fixed DTR/RTS bug that caused the card to indicate
+ *                "don't send data" to a modem after the password prompt.
+ *                Fixed bug for premature (fake) interrupts.
+ * Revision 1.5:  April 19th 1997
+ *                fixed a minor typo in the header file, cleanup a little.
+ *                performance warnings are now MAXed at once per minute.
+ * Revision 1.6:  May 23 1997
+ *                Changed the specialix=... format to include interrupt.
+ * Revision 1.7:  May 27 1997
+ *                Made many more debug printk's a compile time option.
+ * Revision 1.8:  Jul 1  1997
+ *                port to linux-2.1.43 kernel.
+ * Revision 1.9:  Oct 9  1998
+ *                Added stuff for the IO8+/PCI version.
+ * Revision 1.10: Oct 22  1999 / Jan 21 2000.
+ *                Added stuff for setserial.
+ *                Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
+ *
+ */
+
+#define VERSION "1.11"
+
+
+/*
+ * There is a bunch of documentation about the card, jumpers, config
+ * settings, restrictions, cables, device names and numbers in
+ * Documentation/serial/specialix.txt
+ */
+
+#include <linux/module.h>
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/gfp.h>
+
+#include "specialix_io8.h"
+#include "cd1865.h"
+
+
+/*
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile...
+*/
+#define DEBUG
+
+static int sx_debug;
+static int sx_rxfifo = SPECIALIX_RXFIFO;
+static int sx_rtscts;
+
+#ifdef DEBUG
+#define dprintk(f, str...) if (sx_debug & f) printk(str)
+#else
+#define dprintk(f, str...) /* nothing */
+#endif
+
+#define SX_DEBUG_FLOW    0x0001
+#define SX_DEBUG_DATA    0x0002
+#define SX_DEBUG_PROBE   0x0004
+#define SX_DEBUG_CHAN    0x0008
+#define SX_DEBUG_INIT    0x0010
+#define SX_DEBUG_RX      0x0020
+#define SX_DEBUG_TX      0x0040
+#define SX_DEBUG_IRQ     0x0080
+#define SX_DEBUG_OPEN    0x0100
+#define SX_DEBUG_TERMIOS 0x0200
+#define SX_DEBUG_SIGNALS 0x0400
+#define SX_DEBUG_FIFO    0x0800
+
+
+#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
+#define func_exit()  dprintk(SX_DEBUG_FLOW, "io8: exit  %s\n", __func__)
+
+
+/* Configurable options: */
+
+/* Am I paranoid or not ? ;-) */
+#define SPECIALIX_PARANOIA_CHECK
+
+/*
+ * The following defines are mostly for testing purposes. But if you need
+ * some nice reporting in your syslog, you can define them also.
+ */
+#undef SX_REPORT_FIFO
+#undef SX_REPORT_OVERRUN
+
+
+
+
+#define SPECIALIX_LEGAL_FLAGS \
+	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
+	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
+	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
+
+static struct tty_driver *specialix_driver;
+
+static struct specialix_board sx_board[SX_NBOARD] =  {
+	{ 0, SX_IOBASE1,  9, },
+	{ 0, SX_IOBASE2, 11, },
+	{ 0, SX_IOBASE3, 12, },
+	{ 0, SX_IOBASE4, 15, },
+};
+
+static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
+
+
+static int sx_paranoia_check(struct specialix_port const *port,
+				    char *name, const char *routine)
+{
+#ifdef SPECIALIX_PARANOIA_CHECK
+	static const char *badmagic = KERN_ERR
+	  "sx: Warning: bad specialix port magic number for device %s in %s\n";
+	static const char *badinfo = KERN_ERR
+	  "sx: Warning: null specialix port for device %s in %s\n";
+
+	if (!port) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (port->magic != SPECIALIX_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+
+/*
+ *
+ *  Service functions for specialix IO8+ driver.
+ *
+ */
+
+/* Get board number from pointer */
+static inline int board_No(struct specialix_board *bp)
+{
+	return bp - sx_board;
+}
+
+
+/* Get port number from pointer */
+static inline int port_No(struct specialix_port const *port)
+{
+	return SX_PORT(port - sx_port);
+}
+
+
+/* Get pointer to board from pointer to port */
+static inline struct specialix_board *port_Board(
+					struct specialix_port const *port)
+{
+	return &sx_board[SX_BOARD(port - sx_port)];
+}
+
+
+/* Input Byte from CL CD186x register */
+static inline unsigned char sx_in(struct specialix_board *bp,
+							unsigned short reg)
+{
+	bp->reg = reg | 0x80;
+	outb(reg | 0x80, bp->base + SX_ADDR_REG);
+	return inb(bp->base + SX_DATA_REG);
+}
+
+
+/* Output Byte to CL CD186x register */
+static inline void sx_out(struct specialix_board *bp, unsigned short reg,
+			  unsigned char val)
+{
+	bp->reg = reg | 0x80;
+	outb(reg | 0x80, bp->base + SX_ADDR_REG);
+	outb(val, bp->base + SX_DATA_REG);
+}
+
+
+/* Input Byte from CL CD186x register */
+static inline unsigned char sx_in_off(struct specialix_board *bp,
+				unsigned short reg)
+{
+	bp->reg = reg;
+	outb(reg, bp->base + SX_ADDR_REG);
+	return inb(bp->base + SX_DATA_REG);
+}
+
+
+/* Output Byte to CL CD186x register */
+static inline void sx_out_off(struct specialix_board  *bp,
+				unsigned short reg, unsigned char val)
+{
+	bp->reg = reg;
+	outb(reg, bp->base + SX_ADDR_REG);
+	outb(val, bp->base + SX_DATA_REG);
+}
+
+
+/* Wait for Channel Command Register ready */
+static void sx_wait_CCR(struct specialix_board  *bp)
+{
+	unsigned long delay, flags;
+	unsigned char ccr;
+
+	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
+		spin_lock_irqsave(&bp->lock, flags);
+		ccr = sx_in(bp, CD186x_CCR);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		if (!ccr)
+			return;
+		udelay(1);
+	}
+
+	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
+}
+
+
+/* Wait for Channel Command Register ready */
+static void sx_wait_CCR_off(struct specialix_board  *bp)
+{
+	unsigned long delay;
+	unsigned char crr;
+	unsigned long flags;
+
+	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
+		spin_lock_irqsave(&bp->lock, flags);
+		crr = sx_in_off(bp, CD186x_CCR);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		if (!crr)
+			return;
+		udelay(1);
+	}
+
+	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
+}
+
+
+/*
+ *  specialix IO8+ IO range functions.
+ */
+
+static int sx_request_io_range(struct specialix_board *bp)
+{
+	return request_region(bp->base,
+		bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
+		"specialix IO8+") == NULL;
+}
+
+
+static void sx_release_io_range(struct specialix_board *bp)
+{
+	release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
+					SX_PCI_IO_SPACE : SX_IO_SPACE);
+}
+
+
+/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
+static int sx_set_irq(struct specialix_board *bp)
+{
+	int virq;
+	int i;
+	unsigned long flags;
+
+	if (bp->flags & SX_BOARD_IS_PCI)
+		return 1;
+	switch (bp->irq) {
+	/* In the same order as in the docs... */
+	case 15:
+		virq = 0;
+		break;
+	case 12:
+		virq = 1;
+		break;
+	case 11:
+		virq = 2;
+		break;
+	case 9:
+		virq = 3;
+		break;
+	default:printk(KERN_ERR
+			    "Speclialix: cannot set irq to %d.\n", bp->irq);
+		return 0;
+	}
+	spin_lock_irqsave(&bp->lock, flags);
+	for (i = 0; i < 2; i++) {
+		sx_out(bp, CD186x_CAR, i);
+		sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
+	}
+	spin_unlock_irqrestore(&bp->lock, flags);
+	return 1;
+}
+
+
+/* Reset and setup CD186x chip */
+static int sx_init_CD186x(struct specialix_board  *bp)
+{
+	unsigned long flags;
+	int scaler;
+	int rv = 1;
+
+	func_enter();
+	sx_wait_CCR_off(bp);			   /* Wait for CCR ready        */
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);      /* Reset CD186x chip          */
+	spin_unlock_irqrestore(&bp->lock, flags);
+	msleep(50);					/* Delay 0.05 sec            */
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out_off(bp, CD186x_GIVR, SX_ID);             /* Set ID for this chip      */
+	sx_out_off(bp, CD186x_GICR, 0);                 /* Clear all bits            */
+	sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT);      /* Prio for modem intr       */
+	sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT);      /* Prio for transmitter intr */
+	sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT);      /* Prio for receiver intr    */
+	/* Set RegAckEn */
+	sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
+
+	/* Setting up prescaler. We need 4 ticks per 1 ms */
+	scaler =  SX_OSCFREQ/SPECIALIX_TPS;
+
+	sx_out_off(bp, CD186x_PPRH, scaler >> 8);
+	sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	if (!sx_set_irq(bp)) {
+		/* Figure out how to pass this along... */
+		printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
+		rv = 0;
+	}
+
+	func_exit();
+	return rv;
+}
+
+
+static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
+{
+	int i;
+	int t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bp->lock, flags);
+	for (i = 0, t = 0; i < 8; i++) {
+		sx_out_off(bp, CD186x_CAR, i);
+		if (sx_in_off(bp, reg) & bit)
+			t |= 1 << i;
+	}
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	return t;
+}
+
+
+/* Main probing routine, also sets irq. */
+static int sx_probe(struct specialix_board *bp)
+{
+	unsigned char val1, val2;
+	int rev;
+	int chip;
+
+	func_enter();
+
+	if (sx_request_io_range(bp)) {
+		func_exit();
+		return 1;
+	}
+
+	/* Are the I/O ports here ? */
+	sx_out_off(bp, CD186x_PPRL, 0x5a);
+	udelay(1);
+	val1 = sx_in_off(bp, CD186x_PPRL);
+
+	sx_out_off(bp, CD186x_PPRL, 0xa5);
+	udelay(1);
+	val2 = sx_in_off(bp, CD186x_PPRL);
+
+
+	if (val1 != 0x5a || val2 != 0xa5) {
+		printk(KERN_INFO
+			"sx%d: specialix IO8+ Board at 0x%03x not found.\n",
+						board_No(bp), bp->base);
+		sx_release_io_range(bp);
+		func_exit();
+		return 1;
+	}
+
+	/* Check the DSR lines that Specialix uses as board
+	   identification */
+	val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
+	val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
+	dprintk(SX_DEBUG_INIT,
+			"sx%d: DSR lines are: %02x, rts lines are: %02x\n",
+					board_No(bp), val1, val2);
+
+	/* They managed to switch the bit order between the docs and
+	   the IO8+ card. The new PCI card now conforms to old docs.
+	   They changed the PCI docs to reflect the situation on the
+	   old card. */
+	val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
+	if (val1 != val2) {
+		printk(KERN_INFO
+		  "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
+		       board_No(bp), val2, bp->base, val1);
+		sx_release_io_range(bp);
+		func_exit();
+		return 1;
+	}
+
+
+	/* Reset CD186x again  */
+	if (!sx_init_CD186x(bp)) {
+		sx_release_io_range(bp);
+		func_exit();
+		return 1;
+	}
+
+	sx_request_io_range(bp);
+	bp->flags |= SX_BOARD_PRESENT;
+
+	/* Chip           revcode   pkgtype
+			  GFRCR     SRCR bit 7
+	   CD180 rev B    0x81      0
+	   CD180 rev C    0x82      0
+	   CD1864 rev A   0x82      1
+	   CD1865 rev A   0x83      1  -- Do not use!!! Does not work.
+	   CD1865 rev B   0x84      1
+	 -- Thanks to Gwen Wang, Cirrus Logic.
+	 */
+
+	switch (sx_in_off(bp, CD186x_GFRCR)) {
+	case 0x82:
+		chip = 1864;
+		rev = 'A';
+		break;
+	case 0x83:
+		chip = 1865;
+		rev = 'A';
+		break;
+	case 0x84:
+		chip = 1865;
+		rev = 'B';
+		break;
+	case 0x85:
+		chip = 1865;
+		rev = 'C';
+		break; /* Does not exist at this time */
+	default:
+		chip = -1;
+		rev = 'x';
+	}
+
+	dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
+
+	printk(KERN_INFO
+    "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
+				board_No(bp), bp->base, bp->irq, chip, rev);
+
+	func_exit();
+	return 0;
+}
+
+/*
+ *
+ *  Interrupt processing routines.
+ * */
+
+static struct specialix_port *sx_get_port(struct specialix_board *bp,
+					       unsigned char const *what)
+{
+	unsigned char channel;
+	struct specialix_port *port = NULL;
+
+	channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
+	dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
+	if (channel < CD186x_NCH) {
+		port = &sx_port[board_No(bp) * SX_NPORT + channel];
+		dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
+			board_No(bp) * SX_NPORT + channel,  port,
+			port->port.flags & ASYNC_INITIALIZED);
+
+		if (port->port.flags & ASYNC_INITIALIZED) {
+			dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
+			func_exit();
+			return port;
+		}
+	}
+	printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
+	       board_No(bp), what, channel);
+	return NULL;
+}
+
+
+static void sx_receive_exc(struct specialix_board *bp)
+{
+	struct specialix_port *port;
+	struct tty_struct *tty;
+	unsigned char status;
+	unsigned char ch, flag;
+
+	func_enter();
+
+	port = sx_get_port(bp, "Receive");
+	if (!port) {
+		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+		func_exit();
+		return;
+	}
+	tty = port->port.tty;
+
+	status = sx_in(bp, CD186x_RCSR);
+
+	dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
+	if (status & RCSR_OE) {
+		port->overrun++;
+		dprintk(SX_DEBUG_FIFO,
+			"sx%d: port %d: Overrun. Total %ld overruns.\n",
+				board_No(bp), port_No(port), port->overrun);
+	}
+	status &= port->mark_mask;
+
+	/* This flip buffer check needs to be below the reading of the
+	   status register to reset the chip's IRQ.... */
+	if (tty_buffer_request_room(tty, 1) == 0) {
+		dprintk(SX_DEBUG_FIFO,
+		    "sx%d: port %d: Working around flip buffer overflow.\n",
+					board_No(bp), port_No(port));
+		func_exit();
+		return;
+	}
+
+	ch = sx_in(bp, CD186x_RDR);
+	if (!status) {
+		func_exit();
+		return;
+	}
+	if (status & RCSR_TOUT) {
+		printk(KERN_INFO
+		    "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
+					board_No(bp), port_No(port));
+		func_exit();
+		return;
+
+	} else if (status & RCSR_BREAK) {
+		dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
+		       board_No(bp), port_No(port));
+		flag = TTY_BREAK;
+		if (port->port.flags & ASYNC_SAK)
+			do_SAK(tty);
+
+	} else if (status & RCSR_PE)
+		flag = TTY_PARITY;
+
+	else if (status & RCSR_FE)
+		flag = TTY_FRAME;
+
+	else if (status & RCSR_OE)
+		flag = TTY_OVERRUN;
+
+	else
+		flag = TTY_NORMAL;
+
+	if (tty_insert_flip_char(tty, ch, flag))
+		tty_flip_buffer_push(tty);
+	func_exit();
+}
+
+
+static void sx_receive(struct specialix_board *bp)
+{
+	struct specialix_port *port;
+	struct tty_struct *tty;
+	unsigned char count;
+
+	func_enter();
+
+	port = sx_get_port(bp, "Receive");
+	if (port == NULL) {
+		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
+		func_exit();
+		return;
+	}
+	tty = port->port.tty;
+
+	count = sx_in(bp, CD186x_RDCR);
+	dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
+	port->hits[count > 8 ? 9 : count]++;
+
+	while (count--)
+		tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
+	tty_flip_buffer_push(tty);
+	func_exit();
+}
+
+
+static void sx_transmit(struct specialix_board *bp)
+{
+	struct specialix_port *port;
+	struct tty_struct *tty;
+	unsigned char count;
+
+	func_enter();
+	port = sx_get_port(bp, "Transmit");
+	if (port == NULL) {
+		func_exit();
+		return;
+	}
+	dprintk(SX_DEBUG_TX, "port: %p\n", port);
+	tty = port->port.tty;
+
+	if (port->IER & IER_TXEMPTY) {
+		/* FIFO drained */
+		sx_out(bp, CD186x_CAR, port_No(port));
+		port->IER &= ~IER_TXEMPTY;
+		sx_out(bp, CD186x_IER, port->IER);
+		func_exit();
+		return;
+	}
+
+	if ((port->xmit_cnt <= 0 && !port->break_length)
+	    || tty->stopped || tty->hw_stopped) {
+		sx_out(bp, CD186x_CAR, port_No(port));
+		port->IER &= ~IER_TXRDY;
+		sx_out(bp, CD186x_IER, port->IER);
+		func_exit();
+		return;
+	}
+
+	if (port->break_length) {
+		if (port->break_length > 0) {
+			if (port->COR2 & COR2_ETC) {
+				sx_out(bp, CD186x_TDR, CD186x_C_ESC);
+				sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
+				port->COR2 &= ~COR2_ETC;
+			}
+			count = min_t(int, port->break_length, 0xff);
+			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
+			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
+			sx_out(bp, CD186x_TDR, count);
+			port->break_length -= count;
+			if (port->break_length == 0)
+				port->break_length--;
+		} else {
+			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
+			sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
+			sx_out(bp, CD186x_COR2, port->COR2);
+			sx_wait_CCR(bp);
+			sx_out(bp, CD186x_CCR, CCR_CORCHG2);
+			port->break_length = 0;
+		}
+
+		func_exit();
+		return;
+	}
+
+	count = CD186x_NFIFO;
+	do {
+		sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
+		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
+		if (--port->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+
+	if (port->xmit_cnt <= 0) {
+		sx_out(bp, CD186x_CAR, port_No(port));
+		port->IER &= ~IER_TXRDY;
+		sx_out(bp, CD186x_IER, port->IER);
+	}
+	if (port->xmit_cnt <= port->wakeup_chars)
+		tty_wakeup(tty);
+
+	func_exit();
+}
+
+
+static void sx_check_modem(struct specialix_board *bp)
+{
+	struct specialix_port *port;
+	struct tty_struct *tty;
+	unsigned char mcr;
+	int msvr_cd;
+
+	dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
+	port = sx_get_port(bp, "Modem");
+	if (port == NULL)
+		return;
+
+	tty = port->port.tty;
+
+	mcr = sx_in(bp, CD186x_MCR);
+
+	if ((mcr & MCR_CDCHG)) {
+		dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
+		msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
+		if (msvr_cd) {
+			dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
+			wake_up_interruptible(&port->port.open_wait);
+		} else {
+			dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
+			tty_hangup(tty);
+		}
+	}
+
+#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
+	if (mcr & MCR_CTSCHG) {
+		if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
+			tty->hw_stopped = 0;
+			port->IER |= IER_TXRDY;
+			if (port->xmit_cnt <= port->wakeup_chars)
+				tty_wakeup(tty);
+		} else {
+			tty->hw_stopped = 1;
+			port->IER &= ~IER_TXRDY;
+		}
+		sx_out(bp, CD186x_IER, port->IER);
+	}
+	if (mcr & MCR_DSSXHG) {
+		if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
+			tty->hw_stopped = 0;
+			port->IER |= IER_TXRDY;
+			if (port->xmit_cnt <= port->wakeup_chars)
+				tty_wakeup(tty);
+		} else {
+			tty->hw_stopped = 1;
+			port->IER &= ~IER_TXRDY;
+		}
+		sx_out(bp, CD186x_IER, port->IER);
+	}
+#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
+
+	/* Clear change bits */
+	sx_out(bp, CD186x_MCR, 0);
+}
+
+
+/* The main interrupt processing routine */
+static irqreturn_t sx_interrupt(int dummy, void *dev_id)
+{
+	unsigned char status;
+	unsigned char ack;
+	struct specialix_board *bp = dev_id;
+	unsigned long loop = 0;
+	int saved_reg;
+	unsigned long flags;
+
+	func_enter();
+
+	spin_lock_irqsave(&bp->lock, flags);
+
+	dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
+		port_No(sx_get_port(bp, "INT")),
+		SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
+	if (!(bp->flags & SX_BOARD_ACTIVE)) {
+		dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
+								bp->irq);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		func_exit();
+		return IRQ_NONE;
+	}
+
+	saved_reg = bp->reg;
+
+	while (++loop < 16) {
+		status = sx_in(bp, CD186x_SRSR) &
+				(SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
+		if (status == 0)
+			break;
+		if (status & SRSR_RREQint) {
+			ack = sx_in(bp, CD186x_RRAR);
+
+			if (ack == (SX_ID | GIVR_IT_RCV))
+				sx_receive(bp);
+			else if (ack == (SX_ID | GIVR_IT_REXC))
+				sx_receive_exc(bp);
+			else
+				printk(KERN_ERR
+				"sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
+						board_No(bp), status, ack);
+
+		} else if (status & SRSR_TREQint) {
+			ack = sx_in(bp, CD186x_TRAR);
+
+			if (ack == (SX_ID | GIVR_IT_TX))
+				sx_transmit(bp);
+			else
+				printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
+					board_No(bp), status, ack,
+					port_No(sx_get_port(bp, "Int")));
+		} else if (status & SRSR_MREQint) {
+			ack = sx_in(bp, CD186x_MRAR);
+
+			if (ack == (SX_ID | GIVR_IT_MODEM))
+				sx_check_modem(bp);
+			else
+				printk(KERN_ERR
+				  "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
+				       board_No(bp), status, ack);
+
+		}
+
+		sx_out(bp, CD186x_EOIR, 0);   /* Mark end of interrupt */
+	}
+	bp->reg = saved_reg;
+	outb(bp->reg, bp->base + SX_ADDR_REG);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	func_exit();
+	return IRQ_HANDLED;
+}
+
+
+/*
+ *  Routines for open & close processing.
+ */
+
+static void turn_ints_off(struct specialix_board *bp)
+{
+	unsigned long flags;
+
+	func_enter();
+	spin_lock_irqsave(&bp->lock, flags);
+	(void) sx_in_off(bp, 0); /* Turn off interrupts. */
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	func_exit();
+}
+
+static void turn_ints_on(struct specialix_board *bp)
+{
+	unsigned long flags;
+
+	func_enter();
+
+	spin_lock_irqsave(&bp->lock, flags);
+	(void) sx_in(bp, 0); /* Turn ON interrupts. */
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	func_exit();
+}
+
+
+/* Called with disabled interrupts */
+static int sx_setup_board(struct specialix_board *bp)
+{
+	int error;
+
+	if (bp->flags & SX_BOARD_ACTIVE)
+		return 0;
+
+	if (bp->flags & SX_BOARD_IS_PCI)
+		error = request_irq(bp->irq, sx_interrupt,
+			IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
+	else
+		error = request_irq(bp->irq, sx_interrupt,
+			IRQF_DISABLED, "specialix IO8+", bp);
+
+	if (error)
+		return error;
+
+	turn_ints_on(bp);
+	bp->flags |= SX_BOARD_ACTIVE;
+
+	return 0;
+}
+
+
+/* Called with disabled interrupts */
+static void sx_shutdown_board(struct specialix_board *bp)
+{
+	func_enter();
+
+	if (!(bp->flags & SX_BOARD_ACTIVE)) {
+		func_exit();
+		return;
+	}
+
+	bp->flags &= ~SX_BOARD_ACTIVE;
+
+	dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
+		 bp->irq, board_No(bp));
+	free_irq(bp->irq, bp);
+	turn_ints_off(bp);
+	func_exit();
+}
+
+static unsigned int sx_crtscts(struct tty_struct *tty)
+{
+	if (sx_rtscts)
+		return C_CRTSCTS(tty);
+	return 1;
+}
+
+/*
+ * Setting up port characteristics.
+ * Must be called with disabled interrupts
+ */
+static void sx_change_speed(struct specialix_board *bp,
+						struct specialix_port *port)
+{
+	struct tty_struct *tty;
+	unsigned long baud;
+	long tmp;
+	unsigned char cor1 = 0, cor3 = 0;
+	unsigned char mcor1 = 0, mcor2 = 0;
+	static unsigned long again;
+	unsigned long flags;
+
+	func_enter();
+
+	tty = port->port.tty;
+	if (!tty || !tty->termios) {
+		func_exit();
+		return;
+	}
+
+	port->IER  = 0;
+	port->COR2 = 0;
+	/* Select port on the board */
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CAR, port_No(port));
+
+	/* The Specialix board doens't implement the RTS lines.
+	   They are used to set the IRQ level. Don't touch them. */
+	if (sx_crtscts(tty))
+		port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
+	else
+		port->MSVR =  (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
+	baud = tty_get_baud_rate(tty);
+
+	if (baud == 38400) {
+		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			baud = 57600;
+		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			baud = 115200;
+	}
+
+	if (!baud) {
+		/* Drop DTR & exit */
+		dprintk(SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
+		if (!sx_crtscts(tty)) {
+			port->MSVR &= ~MSVR_DTR;
+			spin_lock_irqsave(&bp->lock, flags);
+			sx_out(bp, CD186x_MSVR, port->MSVR);
+			spin_unlock_irqrestore(&bp->lock, flags);
+		} else
+			dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
+		return;
+	} else {
+		/* Set DTR on */
+		if (!sx_crtscts(tty))
+			port->MSVR |= MSVR_DTR;
+	}
+
+	/*
+	 * Now we must calculate some speed depended things
+	 */
+
+	/* Set baud rate for port */
+	tmp = port->custom_divisor ;
+	if (tmp)
+		printk(KERN_INFO
+			"sx%d: Using custom baud rate divisor %ld. \n"
+			"This is an untested option, please be careful.\n",
+							port_No(port), tmp);
+	else
+		tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
+								CD186x_TPC);
+
+	if (tmp < 0x10 && time_before(again, jiffies)) {
+		again = jiffies + HZ * 60;
+		/* Page 48 of version 2.0 of the CL-CD1865 databook */
+		if (tmp >= 12) {
+			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+				"Performance degradation is possible.\n"
+				"Read specialix.txt for more info.\n",
+						port_No(port), tmp);
+		} else {
+			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
+		"Warning: overstressing Cirrus chip. This might not work.\n"
+		"Read specialix.txt for more info.\n", port_No(port), tmp);
+		}
+	}
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
+	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
+	sx_out(bp, CD186x_RBPRL, tmp & 0xff);
+	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	if (port->custom_divisor)
+		baud = (SX_OSCFREQ + port->custom_divisor/2) /
+							port->custom_divisor;
+	baud = (baud + 5) / 10;		/* Estimated CPS */
+
+	/* Two timer ticks seems enough to wakeup something like SLIP driver */
+	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
+	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
+					      SERIAL_XMIT_SIZE - 1 : tmp);
+
+	/* Receiver timeout will be transmission time for 1.5 chars */
+	tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
+	tmp = (tmp > 0xff) ? 0xff : tmp;
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_RTPR, tmp);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	switch (C_CSIZE(tty)) {
+	case CS5:
+		cor1 |= COR1_5BITS;
+		break;
+	case CS6:
+		cor1 |= COR1_6BITS;
+		break;
+	case CS7:
+		cor1 |= COR1_7BITS;
+		break;
+	case CS8:
+		cor1 |= COR1_8BITS;
+		break;
+	}
+
+	if (C_CSTOPB(tty))
+		cor1 |= COR1_2SB;
+
+	cor1 |= COR1_IGNORE;
+	if (C_PARENB(tty)) {
+		cor1 |= COR1_NORMPAR;
+		if (C_PARODD(tty))
+			cor1 |= COR1_ODDP;
+		if (I_INPCK(tty))
+			cor1 &= ~COR1_IGNORE;
+	}
+	/* Set marking of some errors */
+	port->mark_mask = RCSR_OE | RCSR_TOUT;
+	if (I_INPCK(tty))
+		port->mark_mask |= RCSR_FE | RCSR_PE;
+	if (I_BRKINT(tty) || I_PARMRK(tty))
+		port->mark_mask |= RCSR_BREAK;
+	if (I_IGNPAR(tty))
+		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
+	if (I_IGNBRK(tty)) {
+		port->mark_mask &= ~RCSR_BREAK;
+		if (I_IGNPAR(tty))
+			/* Real raw mode. Ignore all */
+			port->mark_mask &= ~RCSR_OE;
+	}
+	/* Enable Hardware Flow Control */
+	if (C_CRTSCTS(tty)) {
+#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
+		port->IER |= IER_DSR | IER_CTS;
+		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
+		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
+		spin_lock_irqsave(&bp->lock, flags);
+		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
+							(MSVR_CTS|MSVR_DSR));
+		spin_unlock_irqrestore(&bp->lock, flags);
+#else
+		port->COR2 |= COR2_CTSAE;
+#endif
+	}
+	/* Enable Software Flow Control. FIXME: I'm not sure about this */
+	/* Some people reported that it works, but I still doubt it */
+	if (I_IXON(tty)) {
+		port->COR2 |= COR2_TXIBE;
+		cor3 |= (COR3_FCT | COR3_SCDE);
+		if (I_IXANY(tty))
+			port->COR2 |= COR2_IXM;
+		spin_lock_irqsave(&bp->lock, flags);
+		sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
+		sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
+		sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
+		sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
+		spin_unlock_irqrestore(&bp->lock, flags);
+	}
+	if (!C_CLOCAL(tty)) {
+		/* Enable CD check */
+		port->IER |= IER_CD;
+		mcor1 |= MCOR1_CDZD;
+		mcor2 |= MCOR2_CDOD;
+	}
+
+	if (C_CREAD(tty))
+		/* Enable receiver */
+		port->IER |= IER_RXD;
+
+	/* Set input FIFO size (1-8 bytes) */
+	cor3 |= sx_rxfifo;
+	/* Setting up CD186x channel registers */
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_COR1, cor1);
+	sx_out(bp, CD186x_COR2, port->COR2);
+	sx_out(bp, CD186x_COR3, cor3);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	/* Make CD186x know about registers change */
+	sx_wait_CCR(bp);
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
+	/* Setting up modem option registers */
+	dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
+								mcor1, mcor2);
+	sx_out(bp, CD186x_MCOR1, mcor1);
+	sx_out(bp, CD186x_MCOR2, mcor2);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	/* Enable CD186x transmitter & receiver */
+	sx_wait_CCR(bp);
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
+	/* Enable interrupts */
+	sx_out(bp, CD186x_IER, port->IER);
+	/* And finally set the modem lines... */
+	sx_out(bp, CD186x_MSVR, port->MSVR);
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	func_exit();
+}
+
+
+/* Must be called with interrupts enabled */
+static int sx_setup_port(struct specialix_board *bp,
+						struct specialix_port *port)
+{
+	unsigned long flags;
+
+	func_enter();
+
+	if (port->port.flags & ASYNC_INITIALIZED) {
+		func_exit();
+		return 0;
+	}
+
+	if (!port->xmit_buf) {
+		/* We may sleep in get_zeroed_page() */
+		unsigned long tmp;
+
+		tmp = get_zeroed_page(GFP_KERNEL);
+		if (tmp == 0L) {
+			func_exit();
+			return -ENOMEM;
+		}
+
+		if (port->xmit_buf) {
+			free_page(tmp);
+			func_exit();
+			return -ERESTARTSYS;
+		}
+		port->xmit_buf = (unsigned char *) tmp;
+	}
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (port->port.tty)
+		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
+
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	sx_change_speed(bp, port);
+	port->port.flags |= ASYNC_INITIALIZED;
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+
+	func_exit();
+	return 0;
+}
+
+
+/* Must be called with interrupts disabled */
+static void sx_shutdown_port(struct specialix_board *bp,
+						struct specialix_port *port)
+{
+	struct tty_struct *tty;
+	int i;
+	unsigned long flags;
+
+	func_enter();
+
+	if (!(port->port.flags & ASYNC_INITIALIZED)) {
+		func_exit();
+		return;
+	}
+
+	if (sx_debug & SX_DEBUG_FIFO) {
+		dprintk(SX_DEBUG_FIFO,
+			"sx%d: port %d: %ld overruns, FIFO hits [ ",
+				board_No(bp), port_No(port), port->overrun);
+		for (i = 0; i < 10; i++)
+			dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
+		dprintk(SX_DEBUG_FIFO, "].\n");
+	}
+
+	if (port->xmit_buf) {
+		free_page((unsigned long) port->xmit_buf);
+		port->xmit_buf = NULL;
+	}
+
+	/* Select port */
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CAR, port_No(port));
+
+	tty = port->port.tty;
+	if (tty == NULL || C_HUPCL(tty)) {
+		/* Drop DTR */
+		sx_out(bp, CD186x_MSVDTR, 0);
+	}
+	spin_unlock_irqrestore(&bp->lock, flags);
+	/* Reset port */
+	sx_wait_CCR(bp);
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
+	/* Disable all interrupts from this port */
+	port->IER = 0;
+	sx_out(bp, CD186x_IER, port->IER);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	if (tty)
+		set_bit(TTY_IO_ERROR, &tty->flags);
+	port->port.flags &= ~ASYNC_INITIALIZED;
+
+	if (!bp->count)
+		sx_shutdown_board(bp);
+	func_exit();
+}
+
+
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+						struct specialix_port *port)
+{
+	DECLARE_WAITQUEUE(wait,  current);
+	struct specialix_board *bp = port_Board(port);
+	int    retval;
+	int    do_clocal = 0;
+	int    CD;
+	unsigned long flags;
+
+	func_enter();
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
+		interruptible_sleep_on(&port->port.close_wait);
+		if (port->port.flags & ASYNC_HUP_NOTIFY) {
+			func_exit();
+			return -EAGAIN;
+		} else {
+			func_exit();
+			return -ERESTARTSYS;
+		}
+	}
+
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		port->port.flags |= ASYNC_NORMAL_ACTIVE;
+		func_exit();
+		return 0;
+	}
+
+	if (C_CLOCAL(tty))
+		do_clocal = 1;
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&port->port.open_wait, &wait);
+	spin_lock_irqsave(&port->lock, flags);
+	if (!tty_hung_up_p(filp))
+		port->port.count--;
+	spin_unlock_irqrestore(&port->lock, flags);
+	port->port.blocked_open++;
+	while (1) {
+		spin_lock_irqsave(&bp->lock, flags);
+		sx_out(bp, CD186x_CAR, port_No(port));
+		CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
+		if (sx_crtscts(tty)) {
+			/* Activate RTS */
+			port->MSVR |= MSVR_DTR;		/* WTF? */
+			sx_out(bp, CD186x_MSVR, port->MSVR);
+		} else {
+			/* Activate DTR */
+			port->MSVR |= MSVR_DTR;
+			sx_out(bp, CD186x_MSVR, port->MSVR);
+		}
+		spin_unlock_irqrestore(&bp->lock, flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(port->port.flags & ASYNC_INITIALIZED)) {
+			if (port->port.flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+			break;
+		}
+		if (!(port->port.flags & ASYNC_CLOSING) &&
+		    (do_clocal || CD))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->port.open_wait, &wait);
+	spin_lock_irqsave(&port->lock, flags);
+	if (!tty_hung_up_p(filp))
+		port->port.count++;
+	port->port.blocked_open--;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (retval) {
+		func_exit();
+		return retval;
+	}
+
+	port->port.flags |= ASYNC_NORMAL_ACTIVE;
+	func_exit();
+	return 0;
+}
+
+
+static int sx_open(struct tty_struct *tty, struct file *filp)
+{
+	int board;
+	int error;
+	struct specialix_port *port;
+	struct specialix_board *bp;
+	int i;
+	unsigned long flags;
+
+	func_enter();
+
+	board = SX_BOARD(tty->index);
+
+	if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
+		func_exit();
+		return -ENODEV;
+	}
+
+	bp = &sx_board[board];
+	port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
+	port->overrun = 0;
+	for (i = 0; i < 10; i++)
+		port->hits[i] = 0;
+
+	dprintk(SX_DEBUG_OPEN,
+			"Board = %d, bp = %p, port = %p, portno = %d.\n",
+				 board, bp, port, SX_PORT(tty->index));
+
+	if (sx_paranoia_check(port, tty->name, "sx_open")) {
+		func_enter();
+		return -ENODEV;
+	}
+
+	error = sx_setup_board(bp);
+	if (error) {
+		func_exit();
+		return error;
+	}
+
+	spin_lock_irqsave(&bp->lock, flags);
+	port->port.count++;
+	bp->count++;
+	tty->driver_data = port;
+	port->port.tty = tty;
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	error = sx_setup_port(bp, port);
+	if (error) {
+		func_enter();
+		return error;
+	}
+
+	error = block_til_ready(tty, filp, port);
+	if (error) {
+		func_enter();
+		return error;
+	}
+
+	func_exit();
+	return 0;
+}
+
+static void sx_flush_buffer(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	unsigned long flags;
+	struct specialix_board  *bp;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+	spin_lock_irqsave(&port->lock, flags);
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	spin_unlock_irqrestore(&port->lock, flags);
+	tty_wakeup(tty);
+
+	func_exit();
+}
+
+static void sx_close(struct tty_struct *tty, struct file *filp)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned long flags;
+	unsigned long timeout;
+
+	func_enter();
+	if (!port || sx_paranoia_check(port, tty->name, "close")) {
+		func_exit();
+		return;
+	}
+	spin_lock_irqsave(&port->lock, flags);
+
+	if (tty_hung_up_p(filp)) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+	if (tty->count == 1 && port->port.count != 1) {
+		printk(KERN_ERR "sx%d: sx_close: bad port count;"
+		       " tty->count is 1, port count is %d\n",
+		       board_No(bp), port->port.count);
+		port->port.count = 1;
+	}
+
+	if (port->port.count > 1) {
+		port->port.count--;
+		bp->count--;
+
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		func_exit();
+		return;
+	}
+	port->port.flags |= ASYNC_CLOSING;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	spin_unlock_irqrestore(&port->lock, flags);
+	dprintk(SX_DEBUG_OPEN, "Closing\n");
+	if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, port->port.closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	dprintk(SX_DEBUG_OPEN, "Closed\n");
+	port->IER &= ~IER_RXD;
+	if (port->port.flags & ASYNC_INITIALIZED) {
+		port->IER &= ~IER_TXRDY;
+		port->IER |= IER_TXEMPTY;
+		spin_lock_irqsave(&bp->lock, flags);
+		sx_out(bp, CD186x_CAR, port_No(port));
+		sx_out(bp, CD186x_IER, port->IER);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		timeout = jiffies+HZ;
+		while (port->IER & IER_TXEMPTY) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			msleep_interruptible(jiffies_to_msecs(port->timeout));
+			if (time_after(jiffies, timeout)) {
+				printk(KERN_INFO "Timeout waiting for close\n");
+				break;
+			}
+		}
+
+	}
+
+	if (--bp->count < 0) {
+		printk(KERN_ERR
+		    "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
+				board_No(bp), bp->count, tty->index);
+		bp->count = 0;
+	}
+	if (--port->port.count < 0) {
+		printk(KERN_ERR
+			"sx%d: sx_close: bad port count for tty%d: %d\n",
+				board_No(bp), port_No(port), port->port.count);
+		port->port.count = 0;
+	}
+
+	sx_shutdown_port(bp, port);
+	sx_flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	spin_lock_irqsave(&port->lock, flags);
+	tty->closing = 0;
+	port->port.tty = NULL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	if (port->port.blocked_open) {
+		if (port->port.close_delay)
+			msleep_interruptible(
+				jiffies_to_msecs(port->port.close_delay));
+		wake_up_interruptible(&port->port.open_wait);
+	}
+	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+	wake_up_interruptible(&port->port.close_wait);
+
+	func_exit();
+}
+
+
+static int sx_write(struct tty_struct *tty,
+					const unsigned char *buf, int count)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	int c, total = 0;
+	unsigned long flags;
+
+	func_enter();
+	if (sx_paranoia_check(port, tty->name, "sx_write")) {
+		func_exit();
+		return 0;
+	}
+
+	bp = port_Board(port);
+
+	if (!port->xmit_buf) {
+		func_exit();
+		return 0;
+	}
+
+	while (1) {
+		spin_lock_irqsave(&port->lock, flags);
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+				   SERIAL_XMIT_SIZE - port->xmit_head));
+		if (c <= 0) {
+			spin_unlock_irqrestore(&port->lock, flags);
+			break;
+		}
+		memcpy(port->xmit_buf + port->xmit_head, buf, c);
+		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		port->xmit_cnt += c;
+		spin_unlock_irqrestore(&port->lock, flags);
+
+		buf += c;
+		count -= c;
+		total += c;
+	}
+
+	spin_lock_irqsave(&bp->lock, flags);
+	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
+	    !(port->IER & IER_TXRDY)) {
+		port->IER |= IER_TXRDY;
+		sx_out(bp, CD186x_CAR, port_No(port));
+		sx_out(bp, CD186x_IER, port->IER);
+	}
+	spin_unlock_irqrestore(&bp->lock, flags);
+	func_exit();
+
+	return total;
+}
+
+
+static int sx_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct specialix_port *port = tty->driver_data;
+	unsigned long flags;
+	struct specialix_board  *bp;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
+		func_exit();
+		return 0;
+	}
+	dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
+	if (!port->xmit_buf) {
+		func_exit();
+		return 0;
+	}
+	bp = port_Board(port);
+	spin_lock_irqsave(&port->lock, flags);
+
+	dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
+					port->xmit_cnt, port->xmit_buf);
+	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		dprintk(SX_DEBUG_TX, "Exit size\n");
+		func_exit();
+		return 0;
+	}
+	dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
+	port->xmit_buf[port->xmit_head++] = ch;
+	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
+	port->xmit_cnt++;
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	func_exit();
+	return 1;
+}
+
+
+static void sx_flush_chars(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	unsigned long flags;
+	struct specialix_board  *bp = port_Board(port);
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
+		func_exit();
+		return;
+	}
+	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !port->xmit_buf) {
+		func_exit();
+		return;
+	}
+	spin_lock_irqsave(&bp->lock, flags);
+	port->IER |= IER_TXRDY;
+	sx_out(port_Board(port), CD186x_CAR, port_No(port));
+	sx_out(port_Board(port), CD186x_IER, port->IER);
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	func_exit();
+}
+
+
+static int sx_write_room(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	int	ret;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
+		func_exit();
+		return 0;
+	}
+
+	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+
+	func_exit();
+	return ret;
+}
+
+
+static int sx_chars_in_buffer(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
+		func_exit();
+		return 0;
+	}
+	func_exit();
+	return port->xmit_cnt;
+}
+
+static int sx_tiocmget(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned char status;
+	unsigned int result;
+	unsigned long flags;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, __func__)) {
+		func_exit();
+		return -ENODEV;
+	}
+
+	bp = port_Board(port);
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CAR, port_No(port));
+	status = sx_in(bp, CD186x_MSVR);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
+			port_No(port), status, sx_in(bp, CD186x_CAR));
+	dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
+	if (sx_crtscts(port->port.tty)) {
+		result  = TIOCM_DTR | TIOCM_DSR
+			  |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
+			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
+			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+	} else {
+		result  = TIOCM_RTS | TIOCM_DSR
+			  |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
+			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
+			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
+	}
+
+	func_exit();
+
+	return result;
+}
+
+
+static int sx_tiocmset(struct tty_struct *tty,
+		       unsigned int set, unsigned int clear)
+{
+	struct specialix_port *port = tty->driver_data;
+	unsigned long flags;
+	struct specialix_board *bp;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, __func__)) {
+		func_exit();
+		return -ENODEV;
+	}
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (sx_crtscts(port->port.tty)) {
+		if (set & TIOCM_RTS)
+			port->MSVR |= MSVR_DTR;
+	} else {
+		if (set & TIOCM_DTR)
+			port->MSVR |= MSVR_DTR;
+	}
+	if (sx_crtscts(port->port.tty)) {
+		if (clear & TIOCM_RTS)
+			port->MSVR &= ~MSVR_DTR;
+	} else {
+		if (clear & TIOCM_DTR)
+			port->MSVR &= ~MSVR_DTR;
+	}
+	spin_lock(&bp->lock);
+	sx_out(bp, CD186x_CAR, port_No(port));
+	sx_out(bp, CD186x_MSVR, port->MSVR);
+	spin_unlock(&bp->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+	func_exit();
+	return 0;
+}
+
+
+static int sx_send_break(struct tty_struct *tty, int length)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp = port_Board(port);
+	unsigned long flags;
+
+	func_enter();
+	if (length == 0 || length == -1)
+		return -EOPNOTSUPP;
+
+	spin_lock_irqsave(&port->lock, flags);
+	port->break_length = SPECIALIX_TPS / HZ * length;
+	port->COR2 |= COR2_ETC;
+	port->IER  |= IER_TXRDY;
+	spin_lock(&bp->lock);
+	sx_out(bp, CD186x_CAR, port_No(port));
+	sx_out(bp, CD186x_COR2, port->COR2);
+	sx_out(bp, CD186x_IER, port->IER);
+	spin_unlock(&bp->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+	sx_wait_CCR(bp);
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CCR, CCR_CORCHG2);
+	spin_unlock_irqrestore(&bp->lock, flags);
+	sx_wait_CCR(bp);
+
+	func_exit();
+	return 0;
+}
+
+
+static int sx_set_serial_info(struct specialix_port *port,
+					struct serial_struct __user *newinfo)
+{
+	struct serial_struct tmp;
+	struct specialix_board *bp = port_Board(port);
+	int change_speed;
+
+	func_enter();
+
+	if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
+		func_enter();
+		return -EFAULT;
+	}
+
+	mutex_lock(&port->port.mutex);
+	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
+			(tmp.flags & ASYNC_SPD_MASK));
+	change_speed |= (tmp.custom_divisor != port->custom_divisor);
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((tmp.close_delay != port->port.close_delay) ||
+		    (tmp.closing_wait != port->port.closing_wait) ||
+		    ((tmp.flags & ~ASYNC_USR_MASK) !=
+		     (port->port.flags & ~ASYNC_USR_MASK))) {
+			func_exit();
+			mutex_unlock(&port->port.mutex);
+			return -EPERM;
+		}
+		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
+						(tmp.flags & ASYNC_USR_MASK));
+		port->custom_divisor = tmp.custom_divisor;
+	} else {
+		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
+						(tmp.flags & ASYNC_FLAGS));
+		port->port.close_delay = tmp.close_delay;
+		port->port.closing_wait = tmp.closing_wait;
+		port->custom_divisor = tmp.custom_divisor;
+	}
+	if (change_speed)
+		sx_change_speed(bp, port);
+
+	func_exit();
+	mutex_unlock(&port->port.mutex);
+	return 0;
+}
+
+
+static int sx_get_serial_info(struct specialix_port *port,
+				     struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+	struct specialix_board *bp = port_Board(port);
+
+	func_enter();
+
+	memset(&tmp, 0, sizeof(tmp));
+	mutex_lock(&port->port.mutex);
+	tmp.type = PORT_CIRRUS;
+	tmp.line = port - sx_port;
+	tmp.port = bp->base;
+	tmp.irq  = bp->irq;
+	tmp.flags = port->port.flags;
+	tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
+	tmp.close_delay = port->port.close_delay * HZ/100;
+	tmp.closing_wait = port->port.closing_wait * HZ/100;
+	tmp.custom_divisor =  port->custom_divisor;
+	tmp.xmit_fifo_size = CD186x_NFIFO;
+	mutex_unlock(&port->port.mutex);
+	if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
+		func_exit();
+		return -EFAULT;
+	}
+
+	func_exit();
+	return 0;
+}
+
+
+static int sx_ioctl(struct tty_struct *tty,
+				unsigned int cmd, unsigned long arg)
+{
+	struct specialix_port *port = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
+		func_exit();
+		return -ENODEV;
+	}
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		func_exit();
+		return sx_get_serial_info(port, argp);
+	case TIOCSSERIAL:
+		func_exit();
+		return sx_set_serial_info(port, argp);
+	default:
+		func_exit();
+		return -ENOIOCTLCMD;
+	}
+	func_exit();
+	return 0;
+}
+
+
+static void sx_throttle(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned long flags;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+
+	/* Use DTR instead of RTS ! */
+	if (sx_crtscts(tty))
+		port->MSVR &= ~MSVR_DTR;
+	else {
+		/* Auch!!! I think the system shouldn't call this then. */
+		/* Or maybe we're supposed (allowed?) to do our side of hw
+		   handshake anyway, even when hardware handshake is off.
+		   When you see this in your logs, please report.... */
+		printk(KERN_ERR
+		   "sx%d: Need to throttle, but can't (hardware hs is off)\n",
+							port_No(port));
+	}
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_CAR, port_No(port));
+	spin_unlock_irqrestore(&bp->lock, flags);
+	if (I_IXOFF(tty)) {
+		sx_wait_CCR(bp);
+		spin_lock_irqsave(&bp->lock, flags);
+		sx_out(bp, CD186x_CCR, CCR_SSCH2);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		sx_wait_CCR(bp);
+	}
+	spin_lock_irqsave(&bp->lock, flags);
+	sx_out(bp, CD186x_MSVR, port->MSVR);
+	spin_unlock_irqrestore(&bp->lock, flags);
+
+	func_exit();
+}
+
+
+static void sx_unthrottle(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned long flags;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&port->lock, flags);
+	/* XXXX Use DTR INSTEAD???? */
+	if (sx_crtscts(tty))
+		port->MSVR |= MSVR_DTR;
+	/* Else clause: see remark in "sx_throttle"... */
+	spin_lock(&bp->lock);
+	sx_out(bp, CD186x_CAR, port_No(port));
+	spin_unlock(&bp->lock);
+	if (I_IXOFF(tty)) {
+		spin_unlock_irqrestore(&port->lock, flags);
+		sx_wait_CCR(bp);
+		spin_lock_irqsave(&bp->lock, flags);
+		sx_out(bp, CD186x_CCR, CCR_SSCH1);
+		spin_unlock_irqrestore(&bp->lock, flags);
+		sx_wait_CCR(bp);
+		spin_lock_irqsave(&port->lock, flags);
+	}
+	spin_lock(&bp->lock);
+	sx_out(bp, CD186x_MSVR, port->MSVR);
+	spin_unlock(&bp->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	func_exit();
+}
+
+
+static void sx_stop(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned long flags;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_stop")) {
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&port->lock, flags);
+	port->IER &= ~IER_TXRDY;
+	spin_lock(&bp->lock);
+	sx_out(bp, CD186x_CAR, port_No(port));
+	sx_out(bp, CD186x_IER, port->IER);
+	spin_unlock(&bp->lock);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	func_exit();
+}
+
+
+static void sx_start(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned long flags;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_start")) {
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+
+	spin_lock_irqsave(&port->lock, flags);
+	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
+		port->IER |= IER_TXRDY;
+		spin_lock(&bp->lock);
+		sx_out(bp, CD186x_CAR, port_No(port));
+		sx_out(bp, CD186x_IER, port->IER);
+		spin_unlock(&bp->lock);
+	}
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	func_exit();
+}
+
+static void sx_hangup(struct tty_struct *tty)
+{
+	struct specialix_port *port = tty->driver_data;
+	struct specialix_board *bp;
+	unsigned long flags;
+
+	func_enter();
+
+	if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
+		func_exit();
+		return;
+	}
+
+	bp = port_Board(port);
+
+	sx_shutdown_port(bp, port);
+	spin_lock_irqsave(&port->lock, flags);
+	bp->count -= port->port.count;
+	if (bp->count < 0) {
+		printk(KERN_ERR
+			"sx%d: sx_hangup: bad board count: %d port: %d\n",
+					board_No(bp), bp->count, tty->index);
+		bp->count = 0;
+	}
+	port->port.count = 0;
+	port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+	port->port.tty = NULL;
+	spin_unlock_irqrestore(&port->lock, flags);
+	wake_up_interruptible(&port->port.open_wait);
+
+	func_exit();
+}
+
+
+static void sx_set_termios(struct tty_struct *tty,
+					struct ktermios *old_termios)
+{
+	struct specialix_port *port = tty->driver_data;
+	unsigned long flags;
+	struct specialix_board  *bp;
+
+	if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
+		return;
+
+	bp = port_Board(port);
+	spin_lock_irqsave(&port->lock, flags);
+	sx_change_speed(port_Board(port), port);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		sx_start(tty);
+	}
+}
+
+static const struct tty_operations sx_ops = {
+	.open  = sx_open,
+	.close = sx_close,
+	.write = sx_write,
+	.put_char = sx_put_char,
+	.flush_chars = sx_flush_chars,
+	.write_room = sx_write_room,
+	.chars_in_buffer = sx_chars_in_buffer,
+	.flush_buffer = sx_flush_buffer,
+	.ioctl = sx_ioctl,
+	.throttle = sx_throttle,
+	.unthrottle = sx_unthrottle,
+	.set_termios = sx_set_termios,
+	.stop = sx_stop,
+	.start = sx_start,
+	.hangup = sx_hangup,
+	.tiocmget = sx_tiocmget,
+	.tiocmset = sx_tiocmset,
+	.break_ctl = sx_send_break,
+};
+
+static int sx_init_drivers(void)
+{
+	int error;
+	int i;
+
+	func_enter();
+
+	specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
+	if (!specialix_driver) {
+		printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
+		func_exit();
+		return 1;
+	}
+
+	specialix_driver->owner = THIS_MODULE;
+	specialix_driver->name = "ttyW";
+	specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
+	specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	specialix_driver->subtype = SERIAL_TYPE_NORMAL;
+	specialix_driver->init_termios = tty_std_termios;
+	specialix_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	specialix_driver->init_termios.c_ispeed = 9600;
+	specialix_driver->init_termios.c_ospeed = 9600;
+	specialix_driver->flags = TTY_DRIVER_REAL_RAW |
+						TTY_DRIVER_HARDWARE_BREAK;
+	tty_set_operations(specialix_driver, &sx_ops);
+
+	error = tty_register_driver(specialix_driver);
+	if (error) {
+		put_tty_driver(specialix_driver);
+		printk(KERN_ERR
+		  "sx: Couldn't register specialix IO8+ driver, error = %d\n",
+								error);
+		func_exit();
+		return 1;
+	}
+	memset(sx_port, 0, sizeof(sx_port));
+	for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
+		sx_port[i].magic = SPECIALIX_MAGIC;
+		tty_port_init(&sx_port[i].port);
+		spin_lock_init(&sx_port[i].lock);
+	}
+
+	func_exit();
+	return 0;
+}
+
+static void sx_release_drivers(void)
+{
+	func_enter();
+
+	tty_unregister_driver(specialix_driver);
+	put_tty_driver(specialix_driver);
+	func_exit();
+}
+
+/*
+ * This routine must be called by kernel at boot time
+ */
+static int __init specialix_init(void)
+{
+	int i;
+	int found = 0;
+
+	func_enter();
+
+	printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
+	printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
+	if (sx_rtscts)
+		printk(KERN_INFO
+			"sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
+	else
+		printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
+
+	for (i = 0; i < SX_NBOARD; i++)
+		spin_lock_init(&sx_board[i].lock);
+
+	if (sx_init_drivers()) {
+		func_exit();
+		return -EIO;
+	}
+
+	for (i = 0; i < SX_NBOARD; i++)
+		if (sx_board[i].base && !sx_probe(&sx_board[i]))
+			found++;
+
+#ifdef CONFIG_PCI
+	{
+		struct pci_dev *pdev = NULL;
+
+		i = 0;
+		while (i < SX_NBOARD) {
+			if (sx_board[i].flags & SX_BOARD_PRESENT) {
+				i++;
+				continue;
+			}
+			pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
+					PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
+			if (!pdev)
+				break;
+
+			if (pci_enable_device(pdev))
+				continue;
+
+			sx_board[i].irq = pdev->irq;
+
+			sx_board[i].base = pci_resource_start(pdev, 2);
+
+			sx_board[i].flags |= SX_BOARD_IS_PCI;
+			if (!sx_probe(&sx_board[i]))
+				found++;
+		}
+		/* May exit pci_get sequence early with lots of boards */
+		if (pdev != NULL)
+			pci_dev_put(pdev);
+	}
+#endif
+
+	if (!found) {
+		sx_release_drivers();
+		printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
+		func_exit();
+		return -EIO;
+	}
+
+	func_exit();
+	return 0;
+}
+
+static int iobase[SX_NBOARD]  = {0,};
+static int irq[SX_NBOARD] = {0,};
+
+module_param_array(iobase, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param(sx_debug, int, 0);
+module_param(sx_rtscts, int, 0);
+module_param(sx_rxfifo, int, 0);
+
+/*
+ * You can setup up to 4 boards.
+ * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
+ * You should specify the IRQs too in that case "irq=....,...".
+ *
+ * More than 4 boards in one computer is not possible, as the card can
+ * only use 4 different interrupts.
+ *
+ */
+static int __init specialix_init_module(void)
+{
+	int i;
+
+	func_enter();
+
+	if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
+		for (i = 0; i < SX_NBOARD; i++) {
+			sx_board[i].base = iobase[i];
+			sx_board[i].irq = irq[i];
+			sx_board[i].count = 0;
+		}
+	}
+
+	func_exit();
+
+	return specialix_init();
+}
+
+static void __exit specialix_exit_module(void)
+{
+	int i;
+
+	func_enter();
+
+	sx_release_drivers();
+	for (i = 0; i < SX_NBOARD; i++)
+		if (sx_board[i].flags & SX_BOARD_PRESENT)
+			sx_release_io_range(&sx_board[i]);
+	func_exit();
+}
+
+static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
+
+module_init(specialix_init_module);
+module_exit(specialix_exit_module);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR);
diff --git a/drivers/staging/tty/specialix_io8.h b/drivers/staging/tty/specialix_io8.h
new file mode 100644
index 0000000..c630052
--- /dev/null
+++ b/drivers/staging/tty/specialix_io8.h
@@ -0,0 +1,140 @@
+/*
+ *      linux/drivers/char/specialix_io8.h  -- 
+ *                                   Specialix IO8+ multiport serial driver.
+ *
+ *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
+ *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
+ *
+ *
+ *      Specialix pays for the development and support of this driver.
+ *      Please DO contact io8-linux@specialix.co.uk if you require
+ *      support.
+ *
+ *      This driver was developped in the BitWizard linux device
+ *      driver service. If you require a linux device driver for your
+ *      product, please contact devices@BitWizard.nl for a quote.
+ *
+ *      This code is firmly based on the riscom/8 serial driver,
+ *      written by Dmitry Gorodchanin. The specialix IO8+ card
+ *      programming information was obtained from the CL-CD1865 Data
+ *      Book, and Specialix document number 6200059: IO8+ Hardware
+ *      Functional Specification.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License as
+ *      published by the Free Software Foundation; either version 2 of
+ *      the License, or (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be
+ *      useful, but WITHOUT ANY WARRANTY; without even the implied
+ *      warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ *      PURPOSE.  See the GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public
+ *      License along with this program; if not, write to the Free
+ *      Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ *      USA.
+ * */
+
+#ifndef __LINUX_SPECIALIX_H
+#define __LINUX_SPECIALIX_H
+
+#include <linux/serial.h>
+
+#ifdef __KERNEL__
+
+/* You can have max 4 ISA cards in one PC, and I recommend not much 
+more than a few  PCI versions of the card. */
+
+#define SX_NBOARD		8
+
+/* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */
+#define SX_IO_SPACE             4
+/* The PCI version decodes 8 addresses, but still only 2 are used. */
+#define SX_PCI_IO_SPACE         8
+
+/* eight ports per board. */
+#define SX_NPORT        	8
+#define SX_BOARD(line)		((line) / SX_NPORT)
+#define SX_PORT(line)		((line) & (SX_NPORT - 1))
+
+
+#define SX_DATA_REG 0     /* Base+0 : Data register */
+#define SX_ADDR_REG 1     /* base+1 : Address register. */
+
+#define MHz *1000000	/* I'm ashamed of myself. */
+
+/* On-board oscillator frequency */
+#define SX_OSCFREQ      (25 MHz/2)
+/* There is a 25MHz crystal on the board, but the chip is in /2 mode */
+
+
+/* Ticks per sec. Used for setting receiver timeout and break length */
+#define SPECIALIX_TPS		4000
+
+/* Yeah, after heavy testing I decided it must be 6.
+ * Sure, You can change it if needed.
+ */
+#define SPECIALIX_RXFIFO	6	/* Max. receiver FIFO size (1-8) */
+
+#define SPECIALIX_MAGIC		0x0907
+
+#define SX_CCR_TIMEOUT 10000   /* CCR timeout. You may need to wait upto
+                                  10 milliseconds before the internal
+                                  processor is available again after
+                                  you give it a command */
+
+#define SX_IOBASE1	0x100
+#define SX_IOBASE2	0x180
+#define SX_IOBASE3	0x250
+#define SX_IOBASE4	0x260
+
+struct specialix_board {
+	unsigned long   flags;
+	unsigned short	base;
+	unsigned char 	irq;
+	//signed   char	count;
+	int count;
+	unsigned char	DTR;
+        int reg;
+	spinlock_t lock;
+};
+
+#define SX_BOARD_PRESENT	0x00000001
+#define SX_BOARD_ACTIVE		0x00000002
+#define SX_BOARD_IS_PCI		0x00000004
+
+
+struct specialix_port {
+	int			magic;
+	struct tty_port		port;
+	int			baud_base;
+	int			flags;
+	int			timeout;
+	unsigned char 		* xmit_buf;
+	int			custom_divisor;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	short			wakeup_chars;
+	short			break_length;
+	unsigned char		mark_mask;
+	unsigned char		IER;
+	unsigned char		MSVR;
+	unsigned char		COR2;
+	unsigned long		overrun;
+	unsigned long		hits[10];
+	spinlock_t lock;
+};
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_SPECIALIX_H */
+
+
+
+
+
+
+
+
+
diff --git a/drivers/staging/tty/stallion.c b/drivers/staging/tty/stallion.c
new file mode 100644
index 0000000..4fff5cd
--- /dev/null
+++ b/drivers/staging/tty/stallion.c
@@ -0,0 +1,4651 @@
+/*****************************************************************************/
+
+/*
+ *	stallion.c  -- stallion multiport serial driver.
+ *
+ *	Copyright (C) 1996-1999  Stallion Technologies
+ *	Copyright (C) 1994-1996  Greg Ungerer.
+ *
+ *	This code is loosely based on the Linux serial driver, written by
+ *	Linus Torvalds, Theodore T'so and others.
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/seq_file.h>
+#include <linux/cd1400.h>
+#include <linux/sc26198.h>
+#include <linux/comstats.h>
+#include <linux/stallion.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <linux/pci.h>
+
+/*****************************************************************************/
+
+/*
+ *	Define different board types. Use the standard Stallion "assigned"
+ *	board numbers. Boards supported in this driver are abbreviated as
+ *	EIO = EasyIO and ECH = EasyConnection 8/32.
+ */
+#define	BRD_EASYIO	20
+#define	BRD_ECH		21
+#define	BRD_ECHMC	22
+#define	BRD_ECHPCI	26
+#define	BRD_ECH64PCI	27
+#define	BRD_EASYIOPCI	28
+
+struct stlconf {
+	unsigned int	brdtype;
+	int		ioaddr1;
+	int		ioaddr2;
+	unsigned long	memaddr;
+	int		irq;
+	int		irqtype;
+};
+
+static unsigned int stl_nrbrds;
+
+/*****************************************************************************/
+
+/*
+ *	Define some important driver characteristics. Device major numbers
+ *	allocated as per Linux Device Registry.
+ */
+#ifndef	STL_SIOMEMMAJOR
+#define	STL_SIOMEMMAJOR		28
+#endif
+#ifndef	STL_SERIALMAJOR
+#define	STL_SERIALMAJOR		24
+#endif
+#ifndef	STL_CALLOUTMAJOR
+#define	STL_CALLOUTMAJOR	25
+#endif
+
+/*
+ *	Set the TX buffer size. Bigger is better, but we don't want
+ *	to chew too much memory with buffers!
+ */
+#define	STL_TXBUFLOW		512
+#define	STL_TXBUFSIZE		4096
+
+/*****************************************************************************/
+
+/*
+ *	Define our local driver identity first. Set up stuff to deal with
+ *	all the local structures required by a serial tty driver.
+ */
+static char	*stl_drvtitle = "Stallion Multiport Serial Driver";
+static char	*stl_drvname = "stallion";
+static char	*stl_drvversion = "5.6.0";
+
+static struct tty_driver	*stl_serial;
+
+/*
+ *	Define a local default termios struct. All ports will be created
+ *	with this termios initially. Basically all it defines is a raw port
+ *	at 9600, 8 data bits, 1 stop bit.
+ */
+static struct ktermios		stl_deftermios = {
+	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
+	.c_cc		= INIT_C_CC,
+	.c_ispeed	= 9600,
+	.c_ospeed	= 9600,
+};
+
+/*
+ *	Define global place to put buffer overflow characters.
+ */
+static char		stl_unwanted[SC26198_RXFIFOSIZE];
+
+/*****************************************************************************/
+
+static DEFINE_MUTEX(stl_brdslock);
+static struct stlbrd		*stl_brds[STL_MAXBRDS];
+
+static const struct tty_port_operations stl_port_ops;
+
+/*
+ *	Per board state flags. Used with the state field of the board struct.
+ *	Not really much here!
+ */
+#define	BRD_FOUND	0x1
+#define STL_PROBED	0x2
+
+
+/*
+ *	Define the port structure istate flags. These set of flags are
+ *	modified at interrupt time - so setting and reseting them needs
+ *	to be atomic. Use the bit clear/setting routines for this.
+ */
+#define	ASYI_TXBUSY	1
+#define	ASYI_TXLOW	2
+#define	ASYI_TXFLOWED	3
+
+/*
+ *	Define an array of board names as printable strings. Handy for
+ *	referencing boards when printing trace and stuff.
+ */
+static char	*stl_brdnames[] = {
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	"EasyIO",
+	"EC8/32-AT",
+	"EC8/32-MC",
+	NULL,
+	NULL,
+	NULL,
+	"EC8/32-PCI",
+	"EC8/64-PCI",
+	"EasyIO-PCI",
+};
+
+/*****************************************************************************/
+
+/*
+ *	Define some string labels for arguments passed from the module
+ *	load line. These allow for easy board definitions, and easy
+ *	modification of the io, memory and irq resoucres.
+ */
+static unsigned int stl_nargs;
+static char	*board0[4];
+static char	*board1[4];
+static char	*board2[4];
+static char	*board3[4];
+
+static char	**stl_brdsp[] = {
+	(char **) &board0,
+	(char **) &board1,
+	(char **) &board2,
+	(char **) &board3
+};
+
+/*
+ *	Define a set of common board names, and types. This is used to
+ *	parse any module arguments.
+ */
+
+static struct {
+	char	*name;
+	int	type;
+} stl_brdstr[] = {
+	{ "easyio", BRD_EASYIO },
+	{ "eio", BRD_EASYIO },
+	{ "20", BRD_EASYIO },
+	{ "ec8/32", BRD_ECH },
+	{ "ec8/32-at", BRD_ECH },
+	{ "ec8/32-isa", BRD_ECH },
+	{ "ech", BRD_ECH },
+	{ "echat", BRD_ECH },
+	{ "21", BRD_ECH },
+	{ "ec8/32-mc", BRD_ECHMC },
+	{ "ec8/32-mca", BRD_ECHMC },
+	{ "echmc", BRD_ECHMC },
+	{ "echmca", BRD_ECHMC },
+	{ "22", BRD_ECHMC },
+	{ "ec8/32-pc", BRD_ECHPCI },
+	{ "ec8/32-pci", BRD_ECHPCI },
+	{ "26", BRD_ECHPCI },
+	{ "ec8/64-pc", BRD_ECH64PCI },
+	{ "ec8/64-pci", BRD_ECH64PCI },
+	{ "ech-pci", BRD_ECH64PCI },
+	{ "echpci", BRD_ECH64PCI },
+	{ "echpc", BRD_ECH64PCI },
+	{ "27", BRD_ECH64PCI },
+	{ "easyio-pc", BRD_EASYIOPCI },
+	{ "easyio-pci", BRD_EASYIOPCI },
+	{ "eio-pci", BRD_EASYIOPCI },
+	{ "eiopci", BRD_EASYIOPCI },
+	{ "28", BRD_EASYIOPCI },
+};
+
+/*
+ *	Define the module agruments.
+ */
+
+module_param_array(board0, charp, &stl_nargs, 0);
+MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
+module_param_array(board1, charp, &stl_nargs, 0);
+MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
+module_param_array(board2, charp, &stl_nargs, 0);
+MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
+module_param_array(board3, charp, &stl_nargs, 0);
+MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
+
+/*****************************************************************************/
+
+/*
+ *	Hardware ID bits for the EasyIO and ECH boards. These defines apply
+ *	to the directly accessible io ports of these boards (not the uarts -
+ *	they are in cd1400.h and sc26198.h).
+ */
+#define	EIO_8PORTRS	0x04
+#define	EIO_4PORTRS	0x05
+#define	EIO_8PORTDI	0x00
+#define	EIO_8PORTM	0x06
+#define	EIO_MK3		0x03
+#define	EIO_IDBITMASK	0x07
+
+#define	EIO_BRDMASK	0xf0
+#define	ID_BRD4		0x10
+#define	ID_BRD8		0x20
+#define	ID_BRD16	0x30
+
+#define	EIO_INTRPEND	0x08
+#define	EIO_INTEDGE	0x00
+#define	EIO_INTLEVEL	0x08
+#define	EIO_0WS		0x10
+
+#define	ECH_ID		0xa0
+#define	ECH_IDBITMASK	0xe0
+#define	ECH_BRDENABLE	0x08
+#define	ECH_BRDDISABLE	0x00
+#define	ECH_INTENABLE	0x01
+#define	ECH_INTDISABLE	0x00
+#define	ECH_INTLEVEL	0x02
+#define	ECH_INTEDGE	0x00
+#define	ECH_INTRPEND	0x01
+#define	ECH_BRDRESET	0x01
+
+#define	ECHMC_INTENABLE	0x01
+#define	ECHMC_BRDRESET	0x02
+
+#define	ECH_PNLSTATUS	2
+#define	ECH_PNL16PORT	0x20
+#define	ECH_PNLIDMASK	0x07
+#define	ECH_PNLXPID	0x40
+#define	ECH_PNLINTRPEND	0x80
+
+#define	ECH_ADDR2MASK	0x1e0
+
+/*
+ *	Define the vector mapping bits for the programmable interrupt board
+ *	hardware. These bits encode the interrupt for the board to use - it
+ *	is software selectable (except the EIO-8M).
+ */
+static unsigned char	stl_vecmap[] = {
+	0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
+	0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
+};
+
+/*
+ *	Lock ordering is that you may not take stallion_lock holding
+ *	brd_lock.
+ */
+
+static spinlock_t brd_lock; 		/* Guard the board mapping */
+static spinlock_t stallion_lock;	/* Guard the tty driver */
+
+/*
+ *	Set up enable and disable macros for the ECH boards. They require
+ *	the secondary io address space to be activated and deactivated.
+ *	This way all ECH boards can share their secondary io region.
+ *	If this is an ECH-PCI board then also need to set the page pointer
+ *	to point to the correct page.
+ */
+#define	BRDENABLE(brdnr,pagenr)						\
+	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
+		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE),	\
+			stl_brds[(brdnr)]->ioctrl);			\
+	else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI)		\
+		outb((pagenr), stl_brds[(brdnr)]->ioctrl);
+
+#define	BRDDISABLE(brdnr)						\
+	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
+		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE),	\
+			stl_brds[(brdnr)]->ioctrl);
+
+#define	STL_CD1400MAXBAUD	230400
+#define	STL_SC26198MAXBAUD	460800
+
+#define	STL_BAUDBASE		115200
+#define	STL_CLOSEDELAY		(5 * HZ / 10)
+
+/*****************************************************************************/
+
+/*
+ *	Define the Stallion PCI vendor and device IDs.
+ */
+#ifndef	PCI_VENDOR_ID_STALLION
+#define	PCI_VENDOR_ID_STALLION		0x124d
+#endif
+#ifndef PCI_DEVICE_ID_ECHPCI832
+#define	PCI_DEVICE_ID_ECHPCI832		0x0000
+#endif
+#ifndef PCI_DEVICE_ID_ECHPCI864
+#define	PCI_DEVICE_ID_ECHPCI864		0x0002
+#endif
+#ifndef PCI_DEVICE_ID_EIOPCI
+#define	PCI_DEVICE_ID_EIOPCI		0x0003
+#endif
+
+/*
+ *	Define structure to hold all Stallion PCI boards.
+ */
+
+static struct pci_device_id stl_pcibrds[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
+		.driver_data = BRD_ECH64PCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
+		.driver_data = BRD_EASYIOPCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
+		.driver_data = BRD_ECHPCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
+		.driver_data = BRD_ECHPCI },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, stl_pcibrds);
+
+/*****************************************************************************/
+
+/*
+ *	Define macros to extract a brd/port number from a minor number.
+ */
+#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
+#define	MINOR2PORT(min)		((min) & 0x3f)
+
+/*
+ *	Define a baud rate table that converts termios baud rate selector
+ *	into the actual baud rate value. All baud rate calculations are
+ *	based on the actual baud rate required.
+ */
+static unsigned int	stl_baudrates[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
+};
+
+/*****************************************************************************/
+
+/*
+ *	Declare all those functions in this driver!
+ */
+
+static long	stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
+static int	stl_brdinit(struct stlbrd *brdp);
+static int	stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
+static int	stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
+
+/*
+ *	CD1400 uart specific handling functions.
+ */
+static void	stl_cd1400setreg(struct stlport *portp, int regnr, int value);
+static int	stl_cd1400getreg(struct stlport *portp, int regnr);
+static int	stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
+static int	stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
+static void	stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+static void	stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
+static int	stl_cd1400getsignals(struct stlport *portp);
+static void	stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
+static void	stl_cd1400ccrwait(struct stlport *portp);
+static void	stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
+static void	stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
+static void	stl_cd1400disableintrs(struct stlport *portp);
+static void	stl_cd1400sendbreak(struct stlport *portp, int len);
+static void	stl_cd1400flowctrl(struct stlport *portp, int state);
+static void	stl_cd1400sendflow(struct stlport *portp, int state);
+static void	stl_cd1400flush(struct stlport *portp);
+static int	stl_cd1400datastate(struct stlport *portp);
+static void	stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
+static void	stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
+static void	stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
+static void	stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
+static void	stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
+
+static inline int	stl_cd1400breakisr(struct stlport *portp, int ioaddr);
+
+/*
+ *	SC26198 uart specific handling functions.
+ */
+static void	stl_sc26198setreg(struct stlport *portp, int regnr, int value);
+static int	stl_sc26198getreg(struct stlport *portp, int regnr);
+static int	stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
+static int	stl_sc26198getglobreg(struct stlport *portp, int regnr);
+static int	stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
+static void	stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+static void	stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
+static int	stl_sc26198getsignals(struct stlport *portp);
+static void	stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
+static void	stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
+static void	stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
+static void	stl_sc26198disableintrs(struct stlport *portp);
+static void	stl_sc26198sendbreak(struct stlport *portp, int len);
+static void	stl_sc26198flowctrl(struct stlport *portp, int state);
+static void	stl_sc26198sendflow(struct stlport *portp, int state);
+static void	stl_sc26198flush(struct stlport *portp);
+static int	stl_sc26198datastate(struct stlport *portp);
+static void	stl_sc26198wait(struct stlport *portp);
+static void	stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
+static void	stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
+static void	stl_sc26198txisr(struct stlport *port);
+static void	stl_sc26198rxisr(struct stlport *port, unsigned int iack);
+static void	stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
+static void	stl_sc26198rxbadchars(struct stlport *portp);
+static void	stl_sc26198otherisr(struct stlport *port, unsigned int iack);
+
+/*****************************************************************************/
+
+/*
+ *	Generic UART support structure.
+ */
+typedef struct uart {
+	int	(*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
+	void	(*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
+	void	(*setport)(struct stlport *portp, struct ktermios *tiosp);
+	int	(*getsignals)(struct stlport *portp);
+	void	(*setsignals)(struct stlport *portp, int dtr, int rts);
+	void	(*enablerxtx)(struct stlport *portp, int rx, int tx);
+	void	(*startrxtx)(struct stlport *portp, int rx, int tx);
+	void	(*disableintrs)(struct stlport *portp);
+	void	(*sendbreak)(struct stlport *portp, int len);
+	void	(*flowctrl)(struct stlport *portp, int state);
+	void	(*sendflow)(struct stlport *portp, int state);
+	void	(*flush)(struct stlport *portp);
+	int	(*datastate)(struct stlport *portp);
+	void	(*intr)(struct stlpanel *panelp, unsigned int iobase);
+} uart_t;
+
+/*
+ *	Define some macros to make calling these functions nice and clean.
+ */
+#define	stl_panelinit		(* ((uart_t *) panelp->uartp)->panelinit)
+#define	stl_portinit		(* ((uart_t *) portp->uartp)->portinit)
+#define	stl_setport		(* ((uart_t *) portp->uartp)->setport)
+#define	stl_getsignals		(* ((uart_t *) portp->uartp)->getsignals)
+#define	stl_setsignals		(* ((uart_t *) portp->uartp)->setsignals)
+#define	stl_enablerxtx		(* ((uart_t *) portp->uartp)->enablerxtx)
+#define	stl_startrxtx		(* ((uart_t *) portp->uartp)->startrxtx)
+#define	stl_disableintrs	(* ((uart_t *) portp->uartp)->disableintrs)
+#define	stl_sendbreak		(* ((uart_t *) portp->uartp)->sendbreak)
+#define	stl_flowctrl		(* ((uart_t *) portp->uartp)->flowctrl)
+#define	stl_sendflow		(* ((uart_t *) portp->uartp)->sendflow)
+#define	stl_flush		(* ((uart_t *) portp->uartp)->flush)
+#define	stl_datastate		(* ((uart_t *) portp->uartp)->datastate)
+
+/*****************************************************************************/
+
+/*
+ *	CD1400 UART specific data initialization.
+ */
+static uart_t stl_cd1400uart = {
+	stl_cd1400panelinit,
+	stl_cd1400portinit,
+	stl_cd1400setport,
+	stl_cd1400getsignals,
+	stl_cd1400setsignals,
+	stl_cd1400enablerxtx,
+	stl_cd1400startrxtx,
+	stl_cd1400disableintrs,
+	stl_cd1400sendbreak,
+	stl_cd1400flowctrl,
+	stl_cd1400sendflow,
+	stl_cd1400flush,
+	stl_cd1400datastate,
+	stl_cd1400eiointr
+};
+
+/*
+ *	Define the offsets within the register bank of a cd1400 based panel.
+ *	These io address offsets are common to the EasyIO board as well.
+ */
+#define	EREG_ADDR	0
+#define	EREG_DATA	4
+#define	EREG_RXACK	5
+#define	EREG_TXACK	6
+#define	EREG_MDACK	7
+
+#define	EREG_BANKSIZE	8
+
+#define	CD1400_CLK	25000000
+#define	CD1400_CLK8M	20000000
+
+/*
+ *	Define the cd1400 baud rate clocks. These are used when calculating
+ *	what clock and divisor to use for the required baud rate. Also
+ *	define the maximum baud rate allowed, and the default base baud.
+ */
+static int	stl_cd1400clkdivs[] = {
+	CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
+};
+
+/*****************************************************************************/
+
+/*
+ *	SC26198 UART specific data initization.
+ */
+static uart_t stl_sc26198uart = {
+	stl_sc26198panelinit,
+	stl_sc26198portinit,
+	stl_sc26198setport,
+	stl_sc26198getsignals,
+	stl_sc26198setsignals,
+	stl_sc26198enablerxtx,
+	stl_sc26198startrxtx,
+	stl_sc26198disableintrs,
+	stl_sc26198sendbreak,
+	stl_sc26198flowctrl,
+	stl_sc26198sendflow,
+	stl_sc26198flush,
+	stl_sc26198datastate,
+	stl_sc26198intr
+};
+
+/*
+ *	Define the offsets within the register bank of a sc26198 based panel.
+ */
+#define	XP_DATA		0
+#define	XP_ADDR		1
+#define	XP_MODID	2
+#define	XP_STATUS	2
+#define	XP_IACK		3
+
+#define	XP_BANKSIZE	4
+
+/*
+ *	Define the sc26198 baud rate table. Offsets within the table
+ *	represent the actual baud rate selector of sc26198 registers.
+ */
+static unsigned int	sc26198_baudtable[] = {
+	50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
+	4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
+	230400, 460800, 921600
+};
+
+#define	SC26198_NRBAUDS		ARRAY_SIZE(sc26198_baudtable)
+
+/*****************************************************************************/
+
+/*
+ *	Define the driver info for a user level control device. Used mainly
+ *	to get at port stats - only not using the port device itself.
+ */
+static const struct file_operations	stl_fsiomem = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= stl_memioctl,
+	.llseek		= noop_llseek,
+};
+
+static struct class *stallion_class;
+
+static void stl_cd_change(struct stlport *portp)
+{
+	unsigned int oldsigs = portp->sigs;
+	struct tty_struct *tty = tty_port_tty_get(&portp->port);
+
+	if (!tty)
+		return;
+
+	portp->sigs = stl_getsignals(portp);
+
+	if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
+		wake_up_interruptible(&portp->port.open_wait);
+
+	if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
+		if (portp->port.flags & ASYNC_CHECK_CD)
+			tty_hangup(tty);
+	tty_kref_put(tty);
+}
+
+/*
+ *	Check for any arguments passed in on the module load command line.
+ */
+
+/*****************************************************************************/
+
+/*
+ *	Parse the supplied argument string, into the board conf struct.
+ */
+
+static int __init stl_parsebrd(struct stlconf *confp, char **argp)
+{
+	char	*sp;
+	unsigned int i;
+
+	pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
+
+	if ((argp[0] == NULL) || (*argp[0] == 0))
+		return 0;
+
+	for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
+		*sp = tolower(*sp);
+
+	for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
+		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
+			break;
+
+	if (i == ARRAY_SIZE(stl_brdstr)) {
+		printk("STALLION: unknown board name, %s?\n", argp[0]);
+		return 0;
+	}
+
+	confp->brdtype = stl_brdstr[i].type;
+
+	i = 1;
+	if ((argp[i] != NULL) && (*argp[i] != 0))
+		confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
+	i++;
+	if (confp->brdtype == BRD_ECH) {
+		if ((argp[i] != NULL) && (*argp[i] != 0))
+			confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
+		i++;
+	}
+	if ((argp[i] != NULL) && (*argp[i] != 0))
+		confp->irq = simple_strtoul(argp[i], NULL, 0);
+	return 1;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Allocate a new board structure. Fill out the basic info in it.
+ */
+
+static struct stlbrd *stl_allocbrd(void)
+{
+	struct stlbrd	*brdp;
+
+	brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
+	if (!brdp) {
+		printk("STALLION: failed to allocate memory (size=%Zd)\n",
+			sizeof(struct stlbrd));
+		return NULL;
+	}
+
+	brdp->magic = STL_BOARDMAGIC;
+	return brdp;
+}
+
+/*****************************************************************************/
+
+static int stl_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct stlport *portp = container_of(port, struct stlport, port);
+	if (!portp->tx.buf) {
+		portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+		if (!portp->tx.buf)
+			return -ENOMEM;
+		portp->tx.head = portp->tx.buf;
+		portp->tx.tail = portp->tx.buf;
+	}
+	stl_setport(portp, tty->termios);
+	portp->sigs = stl_getsignals(portp);
+	stl_setsignals(portp, 1, 1);
+	stl_enablerxtx(portp, 1, 1);
+	stl_startrxtx(portp, 1, 0);
+	return 0;
+}
+
+static int stl_open(struct tty_struct *tty, struct file *filp)
+{
+	struct stlport	*portp;
+	struct stlbrd	*brdp;
+	unsigned int	minordev, brdnr, panelnr;
+	int		portnr;
+
+	pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
+
+	minordev = tty->index;
+	brdnr = MINOR2BRD(minordev);
+	if (brdnr >= stl_nrbrds)
+		return -ENODEV;
+	brdp = stl_brds[brdnr];
+	if (brdp == NULL)
+		return -ENODEV;
+
+	minordev = MINOR2PORT(minordev);
+	for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
+		if (brdp->panels[panelnr] == NULL)
+			break;
+		if (minordev < brdp->panels[panelnr]->nrports) {
+			portnr = minordev;
+			break;
+		}
+		minordev -= brdp->panels[panelnr]->nrports;
+	}
+	if (portnr < 0)
+		return -ENODEV;
+
+	portp = brdp->panels[panelnr]->ports[portnr];
+	if (portp == NULL)
+		return -ENODEV;
+
+	tty->driver_data = portp;
+	return tty_port_open(&portp->port, tty, filp);
+
+}
+
+/*****************************************************************************/
+
+static int stl_carrier_raised(struct tty_port *port)
+{
+	struct stlport *portp = container_of(port, struct stlport, port);
+	return (portp->sigs & TIOCM_CD) ? 1 : 0;
+}
+
+static void stl_dtr_rts(struct tty_port *port, int on)
+{
+	struct stlport *portp = container_of(port, struct stlport, port);
+	/* Takes brd_lock internally */
+	stl_setsignals(portp, on, on);
+}
+
+/*****************************************************************************/
+
+static void stl_flushbuffer(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_flushbuffer(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+
+	stl_flush(portp);
+	tty_wakeup(tty);
+}
+
+/*****************************************************************************/
+
+static void stl_waituntilsent(struct tty_struct *tty, int timeout)
+{
+	struct stlport	*portp;
+	unsigned long	tend;
+
+	pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+
+	if (timeout == 0)
+		timeout = HZ;
+	tend = jiffies + timeout;
+
+	while (stl_datastate(portp)) {
+		if (signal_pending(current))
+			break;
+		msleep_interruptible(20);
+		if (time_after_eq(jiffies, tend))
+			break;
+	}
+}
+
+/*****************************************************************************/
+
+static void stl_shutdown(struct tty_port *port)
+{
+	struct stlport *portp = container_of(port, struct stlport, port);
+	stl_disableintrs(portp);
+	stl_enablerxtx(portp, 0, 0);
+	stl_flush(portp);
+	portp->istate = 0;
+	if (portp->tx.buf != NULL) {
+		kfree(portp->tx.buf);
+		portp->tx.buf = NULL;
+		portp->tx.head = NULL;
+		portp->tx.tail = NULL;
+	}
+}
+
+static void stl_close(struct tty_struct *tty, struct file *filp)
+{
+	struct stlport*portp;
+	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
+
+	portp = tty->driver_data;
+	if(portp == NULL)
+		return;
+	tty_port_close(&portp->port, tty, filp);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Write routine. Take data and stuff it in to the TX ring queue.
+ *	If transmit interrupts are not running then start them.
+ */
+
+static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct stlport	*portp;
+	unsigned int	len, stlen;
+	unsigned char	*chbuf;
+	char		*head, *tail;
+
+	pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return 0;
+	if (portp->tx.buf == NULL)
+		return 0;
+
+/*
+ *	If copying direct from user space we must cater for page faults,
+ *	causing us to "sleep" here for a while. To handle this copy in all
+ *	the data we need now, into a local buffer. Then when we got it all
+ *	copy it into the TX buffer.
+ */
+	chbuf = (unsigned char *) buf;
+
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+	if (head >= tail) {
+		len = STL_TXBUFSIZE - (head - tail) - 1;
+		stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
+	} else {
+		len = tail - head - 1;
+		stlen = len;
+	}
+
+	len = min(len, (unsigned int)count);
+	count = 0;
+	while (len > 0) {
+		stlen = min(len, stlen);
+		memcpy(head, chbuf, stlen);
+		len -= stlen;
+		chbuf += stlen;
+		count += stlen;
+		head += stlen;
+		if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
+			head = portp->tx.buf;
+			stlen = tail - head;
+		}
+	}
+	portp->tx.head = head;
+
+	clear_bit(ASYI_TXLOW, &portp->istate);
+	stl_startrxtx(portp, -1, 1);
+
+	return count;
+}
+
+/*****************************************************************************/
+
+static int stl_putchar(struct tty_struct *tty, unsigned char ch)
+{
+	struct stlport	*portp;
+	unsigned int	len;
+	char		*head, *tail;
+
+	pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -EINVAL;
+	if (portp->tx.buf == NULL)
+		return -EINVAL;
+
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+
+	len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
+	len--;
+
+	if (len > 0) {
+		*head++ = ch;
+		if (head >= (portp->tx.buf + STL_TXBUFSIZE))
+			head = portp->tx.buf;
+	}	
+	portp->tx.head = head;
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	If there are any characters in the buffer then make sure that TX
+ *	interrupts are on and get'em out. Normally used after the putchar
+ *	routine has been called.
+ */
+
+static void stl_flushchars(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_flushchars(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	if (portp->tx.buf == NULL)
+		return;
+
+	stl_startrxtx(portp, -1, 1);
+}
+
+/*****************************************************************************/
+
+static int stl_writeroom(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+	char		*head, *tail;
+
+	pr_debug("stl_writeroom(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return 0;
+	if (portp->tx.buf == NULL)
+		return 0;
+
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+	return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return number of chars in the TX buffer. Normally we would just
+ *	calculate the number of chars in the buffer and return that, but if
+ *	the buffer is empty and TX interrupts are still on then we return
+ *	that the buffer still has 1 char in it. This way whoever called us
+ *	will not think that ALL chars have drained - since the UART still
+ *	must have some chars in it (we are busy after all).
+ */
+
+static int stl_charsinbuffer(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+	unsigned int	size;
+	char		*head, *tail;
+
+	pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return 0;
+	if (portp->tx.buf == NULL)
+		return 0;
+
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+	size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
+	if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
+		size = 1;
+	return size;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Generate the serial struct info.
+ */
+
+static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
+{
+	struct serial_struct	sio;
+	struct stlbrd		*brdp;
+
+	pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
+
+	memset(&sio, 0, sizeof(struct serial_struct));
+
+	mutex_lock(&portp->port.mutex);
+	sio.line = portp->portnr;
+	sio.port = portp->ioaddr;
+	sio.flags = portp->port.flags;
+	sio.baud_base = portp->baud_base;
+	sio.close_delay = portp->close_delay;
+	sio.closing_wait = portp->closing_wait;
+	sio.custom_divisor = portp->custom_divisor;
+	sio.hub6 = 0;
+	if (portp->uartp == &stl_cd1400uart) {
+		sio.type = PORT_CIRRUS;
+		sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
+	} else {
+		sio.type = PORT_UNKNOWN;
+		sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
+	}
+
+	brdp = stl_brds[portp->brdnr];
+	if (brdp != NULL)
+		sio.irq = brdp->irq;
+	mutex_unlock(&portp->port.mutex);
+
+	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set port according to the serial struct info.
+ *	At this point we do not do any auto-configure stuff, so we will
+ *	just quietly ignore any requests to change irq, etc.
+ */
+
+static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
+{
+	struct stlport *	portp = tty->driver_data;
+	struct serial_struct	sio;
+
+	pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
+
+	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
+		return -EFAULT;
+	mutex_lock(&portp->port.mutex);
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((sio.baud_base != portp->baud_base) ||
+		    (sio.close_delay != portp->close_delay) ||
+		    ((sio.flags & ~ASYNC_USR_MASK) !=
+		    (portp->port.flags & ~ASYNC_USR_MASK))) {
+			mutex_unlock(&portp->port.mutex);
+			return -EPERM;
+		}
+	} 
+
+	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
+		(sio.flags & ASYNC_USR_MASK);
+	portp->baud_base = sio.baud_base;
+	portp->close_delay = sio.close_delay;
+	portp->closing_wait = sio.closing_wait;
+	portp->custom_divisor = sio.custom_divisor;
+	mutex_unlock(&portp->port.mutex);
+	stl_setport(portp, tty->termios);
+	return 0;
+}
+
+/*****************************************************************************/
+
+static int stl_tiocmget(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	return stl_getsignals(portp);
+}
+
+static int stl_tiocmset(struct tty_struct *tty,
+			unsigned int set, unsigned int clear)
+{
+	struct stlport	*portp;
+	int rts = -1, dtr = -1;
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+
+	stl_setsignals(portp, dtr, rts);
+	return 0;
+}
+
+static int stl_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
+{
+	struct stlport	*portp;
+	int		rc;
+	void __user *argp = (void __user *)arg;
+
+	pr_debug("stl_ioctl(tty=%p,cmd=%x,arg=%lx)\n", tty, cmd, arg);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+ 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
+		if (tty->flags & (1 << TTY_IO_ERROR))
+			return -EIO;
+
+	rc = 0;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		rc = stl_getserial(portp, argp);
+		break;
+	case TIOCSSERIAL:
+		rc = stl_setserial(tty, argp);
+		break;
+	case COM_GETPORTSTATS:
+		rc = stl_getportstats(tty, portp, argp);
+		break;
+	case COM_CLRPORTSTATS:
+		rc = stl_clrportstats(portp, argp);
+		break;
+	case TIOCSERCONFIG:
+	case TIOCSERGWILD:
+	case TIOCSERSWILD:
+	case TIOCSERGETLSR:
+	case TIOCSERGSTRUCT:
+	case TIOCSERGETMULTI:
+	case TIOCSERSETMULTI:
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Start the transmitter again. Just turn TX interrupts back on.
+ */
+
+static void stl_start(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_start(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	stl_startrxtx(portp, -1, 1);
+}
+
+/*****************************************************************************/
+
+static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
+{
+	struct stlport	*portp;
+	struct ktermios	*tiosp;
+
+	pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+
+	tiosp = tty->termios;
+	if ((tiosp->c_cflag == old->c_cflag) &&
+	    (tiosp->c_iflag == old->c_iflag))
+		return;
+
+	stl_setport(portp, tiosp);
+	stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
+		-1);
+	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
+		tty->hw_stopped = 0;
+		stl_start(tty);
+	}
+	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
+		wake_up_interruptible(&portp->port.open_wait);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Attempt to flow control who ever is sending us data. Based on termios
+ *	settings use software or/and hardware flow control.
+ */
+
+static void stl_throttle(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_throttle(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	stl_flowctrl(portp, 0);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Unflow control the device sending us data...
+ */
+
+static void stl_unthrottle(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_unthrottle(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	stl_flowctrl(portp, 1);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Stop the transmitter. Basically to do this we will just turn TX
+ *	interrupts off.
+ */
+
+static void stl_stop(struct tty_struct *tty)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_stop(tty=%p)\n", tty);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+	stl_startrxtx(portp, -1, 0);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Hangup this port. This is pretty much like closing the port, only
+ *	a little more brutal. No waiting for data to drain. Shutdown the
+ *	port and maybe drop signals.
+ */
+
+static void stl_hangup(struct tty_struct *tty)
+{
+	struct stlport	*portp = tty->driver_data;
+	pr_debug("stl_hangup(tty=%p)\n", tty);
+
+	if (portp == NULL)
+		return;
+	tty_port_hangup(&portp->port);
+}
+
+/*****************************************************************************/
+
+static int stl_breakctl(struct tty_struct *tty, int state)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return -EINVAL;
+
+	stl_sendbreak(portp, ((state == -1) ? 1 : 2));
+	return 0;
+}
+
+/*****************************************************************************/
+
+static void stl_sendxchar(struct tty_struct *tty, char ch)
+{
+	struct stlport	*portp;
+
+	pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
+
+	portp = tty->driver_data;
+	if (portp == NULL)
+		return;
+
+	if (ch == STOP_CHAR(tty))
+		stl_sendflow(portp, 0);
+	else if (ch == START_CHAR(tty))
+		stl_sendflow(portp, 1);
+	else
+		stl_putchar(tty, ch);
+}
+
+static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
+{
+	int	sigs;
+	char sep;
+
+	seq_printf(m, "%d: uart:%s tx:%d rx:%d",
+		portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
+		(int) portp->stats.txtotal, (int) portp->stats.rxtotal);
+
+	if (portp->stats.rxframing)
+		seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
+	if (portp->stats.rxparity)
+		seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
+	if (portp->stats.rxbreaks)
+		seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
+	if (portp->stats.rxoverrun)
+		seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
+
+	sigs = stl_getsignals(portp);
+	sep = ' ';
+	if (sigs & TIOCM_RTS) {
+		seq_printf(m, "%c%s", sep, "RTS");
+		sep = '|';
+	}
+	if (sigs & TIOCM_CTS) {
+		seq_printf(m, "%c%s", sep, "CTS");
+		sep = '|';
+	}
+	if (sigs & TIOCM_DTR) {
+		seq_printf(m, "%c%s", sep, "DTR");
+		sep = '|';
+	}
+	if (sigs & TIOCM_CD) {
+		seq_printf(m, "%c%s", sep, "DCD");
+		sep = '|';
+	}
+	if (sigs & TIOCM_DSR) {
+		seq_printf(m, "%c%s", sep, "DSR");
+		sep = '|';
+	}
+	seq_putc(m, '\n');
+}
+
+/*****************************************************************************/
+
+/*
+ *	Port info, read from the /proc file system.
+ */
+
+static int stl_proc_show(struct seq_file *m, void *v)
+{
+	struct stlbrd	*brdp;
+	struct stlpanel	*panelp;
+	struct stlport	*portp;
+	unsigned int	brdnr, panelnr, portnr;
+	int		totalport;
+
+	totalport = 0;
+
+	seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
+
+/*
+ *	We scan through for each board, panel and port. The offset is
+ *	calculated on the fly, and irrelevant ports are skipped.
+ */
+	for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
+		brdp = stl_brds[brdnr];
+		if (brdp == NULL)
+			continue;
+		if (brdp->state == 0)
+			continue;
+
+		totalport = brdnr * STL_MAXPORTS;
+		for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
+			panelp = brdp->panels[panelnr];
+			if (panelp == NULL)
+				continue;
+
+			for (portnr = 0; portnr < panelp->nrports; portnr++,
+			    totalport++) {
+				portp = panelp->ports[portnr];
+				if (portp == NULL)
+					continue;
+				stl_portinfo(m, portp, totalport);
+			}
+		}
+	}
+	return 0;
+}
+
+static int stl_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, stl_proc_show, NULL);
+}
+
+static const struct file_operations stl_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= stl_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*****************************************************************************/
+
+/*
+ *	All board interrupts are vectored through here first. This code then
+ *	calls off to the approrpriate board interrupt handlers.
+ */
+
+static irqreturn_t stl_intr(int irq, void *dev_id)
+{
+	struct stlbrd *brdp = dev_id;
+
+	pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
+
+	return IRQ_RETVAL((* brdp->isr)(brdp));
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for EasyIO board types.
+ */
+
+static int stl_eiointr(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	iobase;
+	int		handled = 0;
+
+	spin_lock(&brd_lock);
+	panelp = brdp->panels[0];
+	iobase = panelp->iobase;
+	while (inb(brdp->iostatus) & EIO_INTRPEND) {
+		handled = 1;
+		(* panelp->isr)(panelp, iobase);
+	}
+	spin_unlock(&brd_lock);
+	return handled;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for ECH-AT board types.
+ */
+
+static int stl_echatintr(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	ioaddr, bnknr;
+	int		handled = 0;
+
+	outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
+
+	while (inb(brdp->iostatus) & ECH_INTRPEND) {
+		handled = 1;
+		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
+			ioaddr = brdp->bnkstataddr[bnknr];
+			if (inb(ioaddr) & ECH_PNLINTRPEND) {
+				panelp = brdp->bnk2panel[bnknr];
+				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
+			}
+		}
+	}
+
+	outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
+
+	return handled;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for ECH-MCA board types.
+ */
+
+static int stl_echmcaintr(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	ioaddr, bnknr;
+	int		handled = 0;
+
+	while (inb(brdp->iostatus) & ECH_INTRPEND) {
+		handled = 1;
+		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
+			ioaddr = brdp->bnkstataddr[bnknr];
+			if (inb(ioaddr) & ECH_PNLINTRPEND) {
+				panelp = brdp->bnk2panel[bnknr];
+				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
+			}
+		}
+	}
+	return handled;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for ECH-PCI board types.
+ */
+
+static int stl_echpciintr(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	ioaddr, bnknr, recheck;
+	int		handled = 0;
+
+	while (1) {
+		recheck = 0;
+		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
+			outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
+			ioaddr = brdp->bnkstataddr[bnknr];
+			if (inb(ioaddr) & ECH_PNLINTRPEND) {
+				panelp = brdp->bnk2panel[bnknr];
+				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
+				recheck++;
+				handled = 1;
+			}
+		}
+		if (! recheck)
+			break;
+	}
+	return handled;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for ECH-8/64-PCI board types.
+ */
+
+static int stl_echpci64intr(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	ioaddr, bnknr;
+	int		handled = 0;
+
+	while (inb(brdp->ioctrl) & 0x1) {
+		handled = 1;
+		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
+			ioaddr = brdp->bnkstataddr[bnknr];
+			if (inb(ioaddr) & ECH_PNLINTRPEND) {
+				panelp = brdp->bnk2panel[bnknr];
+				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
+			}
+		}
+	}
+
+	return handled;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Initialize all the ports on a panel.
+ */
+
+static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
+{
+	struct stlport *portp;
+	unsigned int i;
+	int chipmask;
+
+	pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
+
+	chipmask = stl_panelinit(brdp, panelp);
+
+/*
+ *	All UART's are initialized (if found!). Now go through and setup
+ *	each ports data structures.
+ */
+	for (i = 0; i < panelp->nrports; i++) {
+		portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
+		if (!portp) {
+			printk("STALLION: failed to allocate memory "
+				"(size=%Zd)\n", sizeof(struct stlport));
+			break;
+		}
+		tty_port_init(&portp->port);
+		portp->port.ops = &stl_port_ops;
+		portp->magic = STL_PORTMAGIC;
+		portp->portnr = i;
+		portp->brdnr = panelp->brdnr;
+		portp->panelnr = panelp->panelnr;
+		portp->uartp = panelp->uartp;
+		portp->clk = brdp->clk;
+		portp->baud_base = STL_BAUDBASE;
+		portp->close_delay = STL_CLOSEDELAY;
+		portp->closing_wait = 30 * HZ;
+		init_waitqueue_head(&portp->port.open_wait);
+		init_waitqueue_head(&portp->port.close_wait);
+		portp->stats.brd = portp->brdnr;
+		portp->stats.panel = portp->panelnr;
+		portp->stats.port = portp->portnr;
+		panelp->ports[i] = portp;
+		stl_portinit(brdp, panelp, portp);
+	}
+
+	return 0;
+}
+
+static void stl_cleanup_panels(struct stlbrd *brdp)
+{
+	struct stlpanel *panelp;
+	struct stlport *portp;
+	unsigned int j, k;
+	struct tty_struct *tty;
+
+	for (j = 0; j < STL_MAXPANELS; j++) {
+		panelp = brdp->panels[j];
+		if (panelp == NULL)
+			continue;
+		for (k = 0; k < STL_PORTSPERPANEL; k++) {
+			portp = panelp->ports[k];
+			if (portp == NULL)
+				continue;
+			tty = tty_port_tty_get(&portp->port);
+			if (tty != NULL) {
+				stl_hangup(tty);
+				tty_kref_put(tty);
+			}
+			kfree(portp->tx.buf);
+			kfree(portp);
+		}
+		kfree(panelp);
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Try to find and initialize an EasyIO board.
+ */
+
+static int __devinit stl_initeio(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	status;
+	char		*name;
+	int		retval;
+
+	pr_debug("stl_initeio(brdp=%p)\n", brdp);
+
+	brdp->ioctrl = brdp->ioaddr1 + 1;
+	brdp->iostatus = brdp->ioaddr1 + 2;
+
+	status = inb(brdp->iostatus);
+	if ((status & EIO_IDBITMASK) == EIO_MK3)
+		brdp->ioctrl++;
+
+/*
+ *	Handle board specific stuff now. The real difference is PCI
+ *	or not PCI.
+ */
+	if (brdp->brdtype == BRD_EASYIOPCI) {
+		brdp->iosize1 = 0x80;
+		brdp->iosize2 = 0x80;
+		name = "serial(EIO-PCI)";
+		outb(0x41, (brdp->ioaddr2 + 0x4c));
+	} else {
+		brdp->iosize1 = 8;
+		name = "serial(EIO)";
+		if ((brdp->irq < 0) || (brdp->irq > 15) ||
+		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
+			printk("STALLION: invalid irq=%d for brd=%d\n",
+				brdp->irq, brdp->brdnr);
+			retval = -EINVAL;
+			goto err;
+		}
+		outb((stl_vecmap[brdp->irq] | EIO_0WS |
+			((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
+			brdp->ioctrl);
+	}
+
+	retval = -EBUSY;
+	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
+		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
+			"%x conflicts with another device\n", brdp->brdnr, 
+			brdp->ioaddr1);
+		goto err;
+	}
+	
+	if (brdp->iosize2 > 0)
+		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
+			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
+				"address %x conflicts with another device\n",
+				brdp->brdnr, brdp->ioaddr2);
+			printk(KERN_WARNING "STALLION: Warning, also "
+				"releasing board %d I/O address %x \n", 
+				brdp->brdnr, brdp->ioaddr1);
+			goto err_rel1;
+		}
+
+/*
+ *	Everything looks OK, so let's go ahead and probe for the hardware.
+ */
+	brdp->clk = CD1400_CLK;
+	brdp->isr = stl_eiointr;
+
+	retval = -ENODEV;
+	switch (status & EIO_IDBITMASK) {
+	case EIO_8PORTM:
+		brdp->clk = CD1400_CLK8M;
+		/* fall thru */
+	case EIO_8PORTRS:
+	case EIO_8PORTDI:
+		brdp->nrports = 8;
+		break;
+	case EIO_4PORTRS:
+		brdp->nrports = 4;
+		break;
+	case EIO_MK3:
+		switch (status & EIO_BRDMASK) {
+		case ID_BRD4:
+			brdp->nrports = 4;
+			break;
+		case ID_BRD8:
+			brdp->nrports = 8;
+			break;
+		case ID_BRD16:
+			brdp->nrports = 16;
+			break;
+		default:
+			goto err_rel2;
+		}
+		break;
+	default:
+		goto err_rel2;
+	}
+
+/*
+ *	We have verified that the board is actually present, so now we
+ *	can complete the setup.
+ */
+
+	panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
+	if (!panelp) {
+		printk(KERN_WARNING "STALLION: failed to allocate memory "
+			"(size=%Zd)\n", sizeof(struct stlpanel));
+		retval = -ENOMEM;
+		goto err_rel2;
+	}
+
+	panelp->magic = STL_PANELMAGIC;
+	panelp->brdnr = brdp->brdnr;
+	panelp->panelnr = 0;
+	panelp->nrports = brdp->nrports;
+	panelp->iobase = brdp->ioaddr1;
+	panelp->hwid = status;
+	if ((status & EIO_IDBITMASK) == EIO_MK3) {
+		panelp->uartp = &stl_sc26198uart;
+		panelp->isr = stl_sc26198intr;
+	} else {
+		panelp->uartp = &stl_cd1400uart;
+		panelp->isr = stl_cd1400eiointr;
+	}
+
+	brdp->panels[0] = panelp;
+	brdp->nrpanels = 1;
+	brdp->state |= BRD_FOUND;
+	brdp->hwid = status;
+	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
+		printk("STALLION: failed to register interrupt "
+		    "routine for %s irq=%d\n", name, brdp->irq);
+		retval = -ENODEV;
+		goto err_fr;
+	}
+
+	return 0;
+err_fr:
+	stl_cleanup_panels(brdp);
+err_rel2:
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+	release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Try to find an ECH board and initialize it. This code is capable of
+ *	dealing with all types of ECH board.
+ */
+
+static int __devinit stl_initech(struct stlbrd *brdp)
+{
+	struct stlpanel	*panelp;
+	unsigned int	status, nxtid, ioaddr, conflict, panelnr, banknr, i;
+	int		retval;
+	char		*name;
+
+	pr_debug("stl_initech(brdp=%p)\n", brdp);
+
+	status = 0;
+	conflict = 0;
+
+/*
+ *	Set up the initial board register contents for boards. This varies a
+ *	bit between the different board types. So we need to handle each
+ *	separately. Also do a check that the supplied IRQ is good.
+ */
+	switch (brdp->brdtype) {
+
+	case BRD_ECH:
+		brdp->isr = stl_echatintr;
+		brdp->ioctrl = brdp->ioaddr1 + 1;
+		brdp->iostatus = brdp->ioaddr1 + 1;
+		status = inb(brdp->iostatus);
+		if ((status & ECH_IDBITMASK) != ECH_ID) {
+			retval = -ENODEV;
+			goto err;
+		}
+		if ((brdp->irq < 0) || (brdp->irq > 15) ||
+		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
+			printk("STALLION: invalid irq=%d for brd=%d\n",
+				brdp->irq, brdp->brdnr);
+			retval = -EINVAL;
+			goto err;
+		}
+		status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
+		status |= (stl_vecmap[brdp->irq] << 1);
+		outb((status | ECH_BRDRESET), brdp->ioaddr1);
+		brdp->ioctrlval = ECH_INTENABLE |
+			((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
+		for (i = 0; i < 10; i++)
+			outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
+		brdp->iosize1 = 2;
+		brdp->iosize2 = 32;
+		name = "serial(EC8/32)";
+		outb(status, brdp->ioaddr1);
+		break;
+
+	case BRD_ECHMC:
+		brdp->isr = stl_echmcaintr;
+		brdp->ioctrl = brdp->ioaddr1 + 0x20;
+		brdp->iostatus = brdp->ioctrl;
+		status = inb(brdp->iostatus);
+		if ((status & ECH_IDBITMASK) != ECH_ID) {
+			retval = -ENODEV;
+			goto err;
+		}
+		if ((brdp->irq < 0) || (brdp->irq > 15) ||
+		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
+			printk("STALLION: invalid irq=%d for brd=%d\n",
+				brdp->irq, brdp->brdnr);
+			retval = -EINVAL;
+			goto err;
+		}
+		outb(ECHMC_BRDRESET, brdp->ioctrl);
+		outb(ECHMC_INTENABLE, brdp->ioctrl);
+		brdp->iosize1 = 64;
+		name = "serial(EC8/32-MC)";
+		break;
+
+	case BRD_ECHPCI:
+		brdp->isr = stl_echpciintr;
+		brdp->ioctrl = brdp->ioaddr1 + 2;
+		brdp->iosize1 = 4;
+		brdp->iosize2 = 8;
+		name = "serial(EC8/32-PCI)";
+		break;
+
+	case BRD_ECH64PCI:
+		brdp->isr = stl_echpci64intr;
+		brdp->ioctrl = brdp->ioaddr2 + 0x40;
+		outb(0x43, (brdp->ioaddr1 + 0x4c));
+		brdp->iosize1 = 0x80;
+		brdp->iosize2 = 0x80;
+		name = "serial(EC8/64-PCI)";
+		break;
+
+	default:
+		printk("STALLION: unknown board type=%d\n", brdp->brdtype);
+		retval = -EINVAL;
+		goto err;
+	}
+
+/*
+ *	Check boards for possible IO address conflicts and return fail status 
+ * 	if an IO conflict found.
+ */
+	retval = -EBUSY;
+	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
+		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
+			"%x conflicts with another device\n", brdp->brdnr, 
+			brdp->ioaddr1);
+		goto err;
+	}
+	
+	if (brdp->iosize2 > 0)
+		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
+			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
+				"address %x conflicts with another device\n",
+				brdp->brdnr, brdp->ioaddr2);
+			printk(KERN_WARNING "STALLION: Warning, also "
+				"releasing board %d I/O address %x \n", 
+				brdp->brdnr, brdp->ioaddr1);
+			goto err_rel1;
+		}
+
+/*
+ *	Scan through the secondary io address space looking for panels.
+ *	As we find'em allocate and initialize panel structures for each.
+ */
+	brdp->clk = CD1400_CLK;
+	brdp->hwid = status;
+
+	ioaddr = brdp->ioaddr2;
+	banknr = 0;
+	panelnr = 0;
+	nxtid = 0;
+
+	for (i = 0; i < STL_MAXPANELS; i++) {
+		if (brdp->brdtype == BRD_ECHPCI) {
+			outb(nxtid, brdp->ioctrl);
+			ioaddr = brdp->ioaddr2;
+		}
+		status = inb(ioaddr + ECH_PNLSTATUS);
+		if ((status & ECH_PNLIDMASK) != nxtid)
+			break;
+		panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
+		if (!panelp) {
+			printk("STALLION: failed to allocate memory "
+				"(size=%Zd)\n", sizeof(struct stlpanel));
+			retval = -ENOMEM;
+			goto err_fr;
+		}
+		panelp->magic = STL_PANELMAGIC;
+		panelp->brdnr = brdp->brdnr;
+		panelp->panelnr = panelnr;
+		panelp->iobase = ioaddr;
+		panelp->pagenr = nxtid;
+		panelp->hwid = status;
+		brdp->bnk2panel[banknr] = panelp;
+		brdp->bnkpageaddr[banknr] = nxtid;
+		brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
+
+		if (status & ECH_PNLXPID) {
+			panelp->uartp = &stl_sc26198uart;
+			panelp->isr = stl_sc26198intr;
+			if (status & ECH_PNL16PORT) {
+				panelp->nrports = 16;
+				brdp->bnk2panel[banknr] = panelp;
+				brdp->bnkpageaddr[banknr] = nxtid;
+				brdp->bnkstataddr[banknr++] = ioaddr + 4 +
+					ECH_PNLSTATUS;
+			} else
+				panelp->nrports = 8;
+		} else {
+			panelp->uartp = &stl_cd1400uart;
+			panelp->isr = stl_cd1400echintr;
+			if (status & ECH_PNL16PORT) {
+				panelp->nrports = 16;
+				panelp->ackmask = 0x80;
+				if (brdp->brdtype != BRD_ECHPCI)
+					ioaddr += EREG_BANKSIZE;
+				brdp->bnk2panel[banknr] = panelp;
+				brdp->bnkpageaddr[banknr] = ++nxtid;
+				brdp->bnkstataddr[banknr++] = ioaddr +
+					ECH_PNLSTATUS;
+			} else {
+				panelp->nrports = 8;
+				panelp->ackmask = 0xc0;
+			}
+		}
+
+		nxtid++;
+		ioaddr += EREG_BANKSIZE;
+		brdp->nrports += panelp->nrports;
+		brdp->panels[panelnr++] = panelp;
+		if ((brdp->brdtype != BRD_ECHPCI) &&
+		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
+			retval = -EINVAL;
+			goto err_fr;
+		}
+	}
+
+	brdp->nrpanels = panelnr;
+	brdp->nrbnks = banknr;
+	if (brdp->brdtype == BRD_ECH)
+		outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
+
+	brdp->state |= BRD_FOUND;
+	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
+		printk("STALLION: failed to register interrupt "
+		    "routine for %s irq=%d\n", name, brdp->irq);
+		retval = -ENODEV;
+		goto err_fr;
+	}
+
+	return 0;
+err_fr:
+	stl_cleanup_panels(brdp);
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+err_rel1:
+	release_region(brdp->ioaddr1, brdp->iosize1);
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Initialize and configure the specified board.
+ *	Scan through all the boards in the configuration and see what we
+ *	can find. Handle EIO and the ECH boards a little differently here
+ *	since the initial search and setup is very different.
+ */
+
+static int __devinit stl_brdinit(struct stlbrd *brdp)
+{
+	int i, retval;
+
+	pr_debug("stl_brdinit(brdp=%p)\n", brdp);
+
+	switch (brdp->brdtype) {
+	case BRD_EASYIO:
+	case BRD_EASYIOPCI:
+		retval = stl_initeio(brdp);
+		if (retval)
+			goto err;
+		break;
+	case BRD_ECH:
+	case BRD_ECHMC:
+	case BRD_ECHPCI:
+	case BRD_ECH64PCI:
+		retval = stl_initech(brdp);
+		if (retval)
+			goto err;
+		break;
+	default:
+		printk("STALLION: board=%d is unknown board type=%d\n",
+			brdp->brdnr, brdp->brdtype);
+		retval = -ENODEV;
+		goto err;
+	}
+
+	if ((brdp->state & BRD_FOUND) == 0) {
+		printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
+			stl_brdnames[brdp->brdtype], brdp->brdnr,
+			brdp->ioaddr1, brdp->irq);
+		goto err_free;
+	}
+
+	for (i = 0; i < STL_MAXPANELS; i++)
+		if (brdp->panels[i] != NULL)
+			stl_initports(brdp, brdp->panels[i]);
+
+	printk("STALLION: %s found, board=%d io=%x irq=%d "
+		"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
+		brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
+		brdp->nrports);
+
+	return 0;
+err_free:
+	free_irq(brdp->irq, brdp);
+
+	stl_cleanup_panels(brdp);
+
+	release_region(brdp->ioaddr1, brdp->iosize1);
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+err:
+	return retval;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Find the next available board number that is free.
+ */
+
+static int __devinit stl_getbrdnr(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < STL_MAXBRDS; i++)
+		if (stl_brds[i] == NULL) {
+			if (i >= stl_nrbrds)
+				stl_nrbrds = i + 1;
+			return i;
+		}
+
+	return -1;
+}
+
+/*****************************************************************************/
+/*
+ *	We have a Stallion board. Allocate a board structure and
+ *	initialize it. Read its IO and IRQ resources from PCI
+ *	configuration space.
+ */
+
+static int __devinit stl_pciprobe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	struct stlbrd *brdp;
+	unsigned int i, brdtype = ent->driver_data;
+	int brdnr, retval = -ENODEV;
+
+	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
+		goto err;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err;
+	brdp = stl_allocbrd();
+	if (brdp == NULL) {
+		retval = -ENOMEM;
+		goto err;
+	}
+	mutex_lock(&stl_brdslock);
+	brdnr = stl_getbrdnr();
+	if (brdnr < 0) {
+		dev_err(&pdev->dev, "too many boards found, "
+			"maximum supported %d\n", STL_MAXBRDS);
+		mutex_unlock(&stl_brdslock);
+		retval = -ENODEV;
+		goto err_fr;
+	}
+	brdp->brdnr = (unsigned int)brdnr;
+	stl_brds[brdp->brdnr] = brdp;
+	mutex_unlock(&stl_brdslock);
+
+	brdp->brdtype = brdtype;
+	brdp->state |= STL_PROBED;
+
+/*
+ *	We have all resources from the board, so let's setup the actual
+ *	board structure now.
+ */
+	switch (brdtype) {
+	case BRD_ECHPCI:
+		brdp->ioaddr2 = pci_resource_start(pdev, 0);
+		brdp->ioaddr1 = pci_resource_start(pdev, 1);
+		break;
+	case BRD_ECH64PCI:
+		brdp->ioaddr2 = pci_resource_start(pdev, 2);
+		brdp->ioaddr1 = pci_resource_start(pdev, 1);
+		break;
+	case BRD_EASYIOPCI:
+		brdp->ioaddr1 = pci_resource_start(pdev, 2);
+		brdp->ioaddr2 = pci_resource_start(pdev, 1);
+		break;
+	default:
+		dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
+		break;
+	}
+
+	brdp->irq = pdev->irq;
+	retval = stl_brdinit(brdp);
+	if (retval)
+		goto err_null;
+
+	pci_set_drvdata(pdev, brdp);
+
+	for (i = 0; i < brdp->nrports; i++)
+		tty_register_device(stl_serial,
+				brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
+
+	return 0;
+err_null:
+	stl_brds[brdp->brdnr] = NULL;
+err_fr:
+	kfree(brdp);
+err:
+	return retval;
+}
+
+static void __devexit stl_pciremove(struct pci_dev *pdev)
+{
+	struct stlbrd *brdp = pci_get_drvdata(pdev);
+	unsigned int i;
+
+	free_irq(brdp->irq, brdp);
+
+	stl_cleanup_panels(brdp);
+
+	release_region(brdp->ioaddr1, brdp->iosize1);
+	if (brdp->iosize2 > 0)
+		release_region(brdp->ioaddr2, brdp->iosize2);
+
+	for (i = 0; i < brdp->nrports; i++)
+		tty_unregister_device(stl_serial,
+				brdp->brdnr * STL_MAXPORTS + i);
+
+	stl_brds[brdp->brdnr] = NULL;
+	kfree(brdp);
+}
+
+static struct pci_driver stl_pcidriver = {
+	.name = "stallion",
+	.id_table = stl_pcibrds,
+	.probe = stl_pciprobe,
+	.remove = __devexit_p(stl_pciremove)
+};
+
+/*****************************************************************************/
+
+/*
+ *	Return the board stats structure to user app.
+ */
+
+static int stl_getbrdstats(combrd_t __user *bp)
+{
+	combrd_t	stl_brdstats;
+	struct stlbrd	*brdp;
+	struct stlpanel	*panelp;
+	unsigned int i;
+
+	if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
+		return -EFAULT;
+	if (stl_brdstats.brd >= STL_MAXBRDS)
+		return -ENODEV;
+	brdp = stl_brds[stl_brdstats.brd];
+	if (brdp == NULL)
+		return -ENODEV;
+
+	memset(&stl_brdstats, 0, sizeof(combrd_t));
+	stl_brdstats.brd = brdp->brdnr;
+	stl_brdstats.type = brdp->brdtype;
+	stl_brdstats.hwid = brdp->hwid;
+	stl_brdstats.state = brdp->state;
+	stl_brdstats.ioaddr = brdp->ioaddr1;
+	stl_brdstats.ioaddr2 = brdp->ioaddr2;
+	stl_brdstats.irq = brdp->irq;
+	stl_brdstats.nrpanels = brdp->nrpanels;
+	stl_brdstats.nrports = brdp->nrports;
+	for (i = 0; i < brdp->nrpanels; i++) {
+		panelp = brdp->panels[i];
+		stl_brdstats.panels[i].panel = i;
+		stl_brdstats.panels[i].hwid = panelp->hwid;
+		stl_brdstats.panels[i].nrports = panelp->nrports;
+	}
+
+	return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Resolve the referenced port number into a port struct pointer.
+ */
+
+static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
+{
+	struct stlbrd	*brdp;
+	struct stlpanel	*panelp;
+
+	if (brdnr < 0 || brdnr >= STL_MAXBRDS)
+		return NULL;
+	brdp = stl_brds[brdnr];
+	if (brdp == NULL)
+		return NULL;
+	if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
+		return NULL;
+	panelp = brdp->panels[panelnr];
+	if (panelp == NULL)
+		return NULL;
+	if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
+		return NULL;
+	return panelp->ports[portnr];
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the port stats structure to user app. A NULL port struct
+ *	pointer passed in means that we need to find out from the app
+ *	what port to get stats for (used through board control device).
+ */
+
+static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
+{
+	comstats_t	stl_comstats;
+	unsigned char	*head, *tail;
+	unsigned long	flags;
+
+	if (!portp) {
+		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
+			return -EFAULT;
+		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
+			stl_comstats.port);
+		if (portp == NULL)
+			return -ENODEV;
+	}
+
+	mutex_lock(&portp->port.mutex);
+	portp->stats.state = portp->istate;
+	portp->stats.flags = portp->port.flags;
+	portp->stats.hwid = portp->hwid;
+
+	portp->stats.ttystate = 0;
+	portp->stats.cflags = 0;
+	portp->stats.iflags = 0;
+	portp->stats.oflags = 0;
+	portp->stats.lflags = 0;
+	portp->stats.rxbuffered = 0;
+
+	spin_lock_irqsave(&stallion_lock, flags);
+	if (tty != NULL && portp->port.tty == tty) {
+		portp->stats.ttystate = tty->flags;
+		/* No longer available as a statistic */
+		portp->stats.rxbuffered = 1; /*tty->flip.count; */
+		if (tty->termios != NULL) {
+			portp->stats.cflags = tty->termios->c_cflag;
+			portp->stats.iflags = tty->termios->c_iflag;
+			portp->stats.oflags = tty->termios->c_oflag;
+			portp->stats.lflags = tty->termios->c_lflag;
+		}
+	}
+	spin_unlock_irqrestore(&stallion_lock, flags);
+
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+	portp->stats.txbuffered = (head >= tail) ? (head - tail) :
+		(STL_TXBUFSIZE - (tail - head));
+
+	portp->stats.signals = (unsigned long) stl_getsignals(portp);
+	mutex_unlock(&portp->port.mutex);
+
+	return copy_to_user(cp, &portp->stats,
+			    sizeof(comstats_t)) ? -EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Clear the port stats structure. We also return it zeroed out...
+ */
+
+static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
+{
+	comstats_t	stl_comstats;
+
+	if (!portp) {
+		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
+			return -EFAULT;
+		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
+			stl_comstats.port);
+		if (portp == NULL)
+			return -ENODEV;
+	}
+
+	mutex_lock(&portp->port.mutex);
+	memset(&portp->stats, 0, sizeof(comstats_t));
+	portp->stats.brd = portp->brdnr;
+	portp->stats.panel = portp->panelnr;
+	portp->stats.port = portp->portnr;
+	mutex_unlock(&portp->port.mutex);
+	return copy_to_user(cp, &portp->stats,
+			    sizeof(comstats_t)) ? -EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the entire driver ports structure to a user app.
+ */
+
+static int stl_getportstruct(struct stlport __user *arg)
+{
+	struct stlport	stl_dummyport;
+	struct stlport	*portp;
+
+	if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
+		return -EFAULT;
+	portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
+		 stl_dummyport.portnr);
+	if (!portp)
+		return -ENODEV;
+	return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the entire driver board structure to a user app.
+ */
+
+static int stl_getbrdstruct(struct stlbrd __user *arg)
+{
+	struct stlbrd	stl_dummybrd;
+	struct stlbrd	*brdp;
+
+	if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
+		return -EFAULT;
+	if (stl_dummybrd.brdnr >= STL_MAXBRDS)
+		return -ENODEV;
+	brdp = stl_brds[stl_dummybrd.brdnr];
+	if (!brdp)
+		return -ENODEV;
+	return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	The "staliomem" device is also required to do some special operations
+ *	on the board and/or ports. In this driver it is mostly used for stats
+ *	collection.
+ */
+
+static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	int	brdnr, rc;
+	void __user *argp = (void __user *)arg;
+
+	pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
+
+	brdnr = iminor(fp->f_dentry->d_inode);
+	if (brdnr >= STL_MAXBRDS)
+		return -ENODEV;
+	rc = 0;
+
+	switch (cmd) {
+	case COM_GETPORTSTATS:
+		rc = stl_getportstats(NULL, NULL, argp);
+		break;
+	case COM_CLRPORTSTATS:
+		rc = stl_clrportstats(NULL, argp);
+		break;
+	case COM_GETBRDSTATS:
+		rc = stl_getbrdstats(argp);
+		break;
+	case COM_READPORT:
+		rc = stl_getportstruct(argp);
+		break;
+	case COM_READBOARD:
+		rc = stl_getbrdstruct(argp);
+		break;
+	default:
+		rc = -ENOIOCTLCMD;
+		break;
+	}
+	return rc;
+}
+
+static const struct tty_operations stl_ops = {
+	.open = stl_open,
+	.close = stl_close,
+	.write = stl_write,
+	.put_char = stl_putchar,
+	.flush_chars = stl_flushchars,
+	.write_room = stl_writeroom,
+	.chars_in_buffer = stl_charsinbuffer,
+	.ioctl = stl_ioctl,
+	.set_termios = stl_settermios,
+	.throttle = stl_throttle,
+	.unthrottle = stl_unthrottle,
+	.stop = stl_stop,
+	.start = stl_start,
+	.hangup = stl_hangup,
+	.flush_buffer = stl_flushbuffer,
+	.break_ctl = stl_breakctl,
+	.wait_until_sent = stl_waituntilsent,
+	.send_xchar = stl_sendxchar,
+	.tiocmget = stl_tiocmget,
+	.tiocmset = stl_tiocmset,
+	.proc_fops = &stl_proc_fops,
+};
+
+static const struct tty_port_operations stl_port_ops = {
+	.carrier_raised = stl_carrier_raised,
+	.dtr_rts = stl_dtr_rts,
+	.activate = stl_activate,
+	.shutdown = stl_shutdown,
+};
+
+/*****************************************************************************/
+/*                       CD1400 HARDWARE FUNCTIONS                           */
+/*****************************************************************************/
+
+/*
+ *	These functions get/set/update the registers of the cd1400 UARTs.
+ *	Access to the cd1400 registers is via an address/data io port pair.
+ *	(Maybe should make this inline...)
+ */
+
+static int stl_cd1400getreg(struct stlport *portp, int regnr)
+{
+	outb((regnr + portp->uartaddr), portp->ioaddr);
+	return inb(portp->ioaddr + EREG_DATA);
+}
+
+static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
+{
+	outb(regnr + portp->uartaddr, portp->ioaddr);
+	outb(value, portp->ioaddr + EREG_DATA);
+}
+
+static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
+{
+	outb(regnr + portp->uartaddr, portp->ioaddr);
+	if (inb(portp->ioaddr + EREG_DATA) != value) {
+		outb(value, portp->ioaddr + EREG_DATA);
+		return 1;
+	}
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Inbitialize the UARTs in a panel. We don't care what sort of board
+ *	these ports are on - since the port io registers are almost
+ *	identical when dealing with ports.
+ */
+
+static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
+{
+	unsigned int	gfrcr;
+	int		chipmask, i, j;
+	int		nrchips, uartaddr, ioaddr;
+	unsigned long   flags;
+
+	pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(panelp->brdnr, panelp->pagenr);
+
+/*
+ *	Check that each chip is present and started up OK.
+ */
+	chipmask = 0;
+	nrchips = panelp->nrports / CD1400_PORTS;
+	for (i = 0; i < nrchips; i++) {
+		if (brdp->brdtype == BRD_ECHPCI) {
+			outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
+			ioaddr = panelp->iobase;
+		} else
+			ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
+		uartaddr = (i & 0x01) ? 0x080 : 0;
+		outb((GFRCR + uartaddr), ioaddr);
+		outb(0, (ioaddr + EREG_DATA));
+		outb((CCR + uartaddr), ioaddr);
+		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
+		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
+		outb((GFRCR + uartaddr), ioaddr);
+		for (j = 0; j < CCR_MAXWAIT; j++)
+			if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
+				break;
+
+		if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
+			printk("STALLION: cd1400 not responding, "
+				"brd=%d panel=%d chip=%d\n",
+				panelp->brdnr, panelp->panelnr, i);
+			continue;
+		}
+		chipmask |= (0x1 << i);
+		outb((PPR + uartaddr), ioaddr);
+		outb(PPR_SCALAR, (ioaddr + EREG_DATA));
+	}
+
+	BRDDISABLE(panelp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+	return chipmask;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Initialize hardware specific port registers.
+ */
+
+static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
+{
+	unsigned long flags;
+	pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
+			panelp, portp);
+
+	if ((brdp == NULL) || (panelp == NULL) ||
+	    (portp == NULL))
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
+		(portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
+	portp->uartaddr = (portp->portnr & 0x04) << 5;
+	portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
+
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
+	portp->hwid = stl_cd1400getreg(portp, GFRCR);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Wait for the command register to be ready. We will poll this,
+ *	since it won't usually take too long to be ready.
+ */
+
+static void stl_cd1400ccrwait(struct stlport *portp)
+{
+	int	i;
+
+	for (i = 0; i < CCR_MAXWAIT; i++)
+		if (stl_cd1400getreg(portp, CCR) == 0)
+			return;
+
+	printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
+		portp->portnr, portp->panelnr, portp->brdnr);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set up the cd1400 registers for a port based on the termios port
+ *	settings.
+ */
+
+static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
+{
+	struct stlbrd	*brdp;
+	unsigned long	flags;
+	unsigned int	clkdiv, baudrate;
+	unsigned char	cor1, cor2, cor3;
+	unsigned char	cor4, cor5, ccr;
+	unsigned char	srer, sreron, sreroff;
+	unsigned char	mcor1, mcor2, rtpr;
+	unsigned char	clk, div;
+
+	cor1 = 0;
+	cor2 = 0;
+	cor3 = 0;
+	cor4 = 0;
+	cor5 = 0;
+	ccr = 0;
+	rtpr = 0;
+	clk = 0;
+	div = 0;
+	mcor1 = 0;
+	mcor2 = 0;
+	sreron = 0;
+	sreroff = 0;
+
+	brdp = stl_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+/*
+ *	Set up the RX char ignore mask with those RX error types we
+ *	can ignore. We can get the cd1400 to help us out a little here,
+ *	it will ignore parity errors and breaks for us.
+ */
+	portp->rxignoremsk = 0;
+	if (tiosp->c_iflag & IGNPAR) {
+		portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
+		cor1 |= COR1_PARIGNORE;
+	}
+	if (tiosp->c_iflag & IGNBRK) {
+		portp->rxignoremsk |= ST_BREAK;
+		cor4 |= COR4_IGNBRK;
+	}
+
+	portp->rxmarkmsk = ST_OVERRUN;
+	if (tiosp->c_iflag & (INPCK | PARMRK))
+		portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
+	if (tiosp->c_iflag & BRKINT)
+		portp->rxmarkmsk |= ST_BREAK;
+
+/*
+ *	Go through the char size, parity and stop bits and set all the
+ *	option register appropriately.
+ */
+	switch (tiosp->c_cflag & CSIZE) {
+	case CS5:
+		cor1 |= COR1_CHL5;
+		break;
+	case CS6:
+		cor1 |= COR1_CHL6;
+		break;
+	case CS7:
+		cor1 |= COR1_CHL7;
+		break;
+	default:
+		cor1 |= COR1_CHL8;
+		break;
+	}
+
+	if (tiosp->c_cflag & CSTOPB)
+		cor1 |= COR1_STOP2;
+	else
+		cor1 |= COR1_STOP1;
+
+	if (tiosp->c_cflag & PARENB) {
+		if (tiosp->c_cflag & PARODD)
+			cor1 |= (COR1_PARENB | COR1_PARODD);
+		else
+			cor1 |= (COR1_PARENB | COR1_PAREVEN);
+	} else {
+		cor1 |= COR1_PARNONE;
+	}
+
+/*
+ *	Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
+ *	space for hardware flow control and the like. This should be set to
+ *	VMIN. Also here we will set the RX data timeout to 10ms - this should
+ *	really be based on VTIME.
+ */
+	cor3 |= FIFO_RXTHRESHOLD;
+	rtpr = 2;
+
+/*
+ *	Calculate the baud rate timers. For now we will just assume that
+ *	the input and output baud are the same. Could have used a baud
+ *	table here, but this way we can generate virtually any baud rate
+ *	we like!
+ */
+	baudrate = tiosp->c_cflag & CBAUD;
+	if (baudrate & CBAUDEX) {
+		baudrate &= ~CBAUDEX;
+		if ((baudrate < 1) || (baudrate > 4))
+			tiosp->c_cflag &= ~CBAUDEX;
+		else
+			baudrate += 15;
+	}
+	baudrate = stl_baudrates[baudrate];
+	if ((tiosp->c_cflag & CBAUD) == B38400) {
+		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			baudrate = 57600;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			baudrate = 115200;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			baudrate = 230400;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			baudrate = 460800;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
+			baudrate = (portp->baud_base / portp->custom_divisor);
+	}
+	if (baudrate > STL_CD1400MAXBAUD)
+		baudrate = STL_CD1400MAXBAUD;
+
+	if (baudrate > 0) {
+		for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
+			clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
+			if (clkdiv < 0x100)
+				break;
+		}
+		div = (unsigned char) clkdiv;
+	}
+
+/*
+ *	Check what form of modem signaling is required and set it up.
+ */
+	if ((tiosp->c_cflag & CLOCAL) == 0) {
+		mcor1 |= MCOR1_DCD;
+		mcor2 |= MCOR2_DCD;
+		sreron |= SRER_MODEM;
+		portp->port.flags |= ASYNC_CHECK_CD;
+	} else
+		portp->port.flags &= ~ASYNC_CHECK_CD;
+
+/*
+ *	Setup cd1400 enhanced modes if we can. In particular we want to
+ *	handle as much of the flow control as possible automatically. As
+ *	well as saving a few CPU cycles it will also greatly improve flow
+ *	control reliability.
+ */
+	if (tiosp->c_iflag & IXON) {
+		cor2 |= COR2_TXIBE;
+		cor3 |= COR3_SCD12;
+		if (tiosp->c_iflag & IXANY)
+			cor2 |= COR2_IXM;
+	}
+
+	if (tiosp->c_cflag & CRTSCTS) {
+		cor2 |= COR2_CTSAE;
+		mcor1 |= FIFO_RTSTHRESHOLD;
+	}
+
+/*
+ *	All cd1400 register values calculated so go through and set
+ *	them all up.
+ */
+
+	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
+		portp->portnr, portp->panelnr, portp->brdnr);
+	pr_debug("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
+		cor1, cor2, cor3, cor4, cor5);
+	pr_debug("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
+		mcor1, mcor2, rtpr, sreron, sreroff);
+	pr_debug("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
+	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
+		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
+		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
+	srer = stl_cd1400getreg(portp, SRER);
+	stl_cd1400setreg(portp, SRER, 0);
+	if (stl_cd1400updatereg(portp, COR1, cor1))
+		ccr = 1;
+	if (stl_cd1400updatereg(portp, COR2, cor2))
+		ccr = 1;
+	if (stl_cd1400updatereg(portp, COR3, cor3))
+		ccr = 1;
+	if (ccr) {
+		stl_cd1400ccrwait(portp);
+		stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
+	}
+	stl_cd1400setreg(portp, COR4, cor4);
+	stl_cd1400setreg(portp, COR5, cor5);
+	stl_cd1400setreg(portp, MCOR1, mcor1);
+	stl_cd1400setreg(portp, MCOR2, mcor2);
+	if (baudrate > 0) {
+		stl_cd1400setreg(portp, TCOR, clk);
+		stl_cd1400setreg(portp, TBPR, div);
+		stl_cd1400setreg(portp, RCOR, clk);
+		stl_cd1400setreg(portp, RBPR, div);
+	}
+	stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
+	stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
+	stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
+	stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
+	stl_cd1400setreg(portp, RTPR, rtpr);
+	mcor1 = stl_cd1400getreg(portp, MSVR1);
+	if (mcor1 & MSVR1_DCD)
+		portp->sigs |= TIOCM_CD;
+	else
+		portp->sigs &= ~TIOCM_CD;
+	stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set the state of the DTR and RTS signals.
+ */
+
+static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
+{
+	unsigned char	msvr1, msvr2;
+	unsigned long	flags;
+
+	pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
+			portp, dtr, rts);
+
+	msvr1 = 0;
+	msvr2 = 0;
+	if (dtr > 0)
+		msvr1 = MSVR1_DTR;
+	if (rts > 0)
+		msvr2 = MSVR2_RTS;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	if (rts >= 0)
+		stl_cd1400setreg(portp, MSVR2, msvr2);
+	if (dtr >= 0)
+		stl_cd1400setreg(portp, MSVR1, msvr1);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the state of the signals.
+ */
+
+static int stl_cd1400getsignals(struct stlport *portp)
+{
+	unsigned char	msvr1, msvr2;
+	unsigned long	flags;
+	int		sigs;
+
+	pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	msvr1 = stl_cd1400getreg(portp, MSVR1);
+	msvr2 = stl_cd1400getreg(portp, MSVR2);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	sigs = 0;
+	sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
+	sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
+	sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
+	sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
+#if 0
+	sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
+	sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
+#else
+	sigs |= TIOCM_DSR;
+#endif
+	return sigs;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Enable/Disable the Transmitter and/or Receiver.
+ */
+
+static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
+{
+	unsigned char	ccr;
+	unsigned long	flags;
+
+	pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
+
+	ccr = 0;
+
+	if (tx == 0)
+		ccr |= CCR_TXDISABLE;
+	else if (tx > 0)
+		ccr |= CCR_TXENABLE;
+	if (rx == 0)
+		ccr |= CCR_RXDISABLE;
+	else if (rx > 0)
+		ccr |= CCR_RXENABLE;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	stl_cd1400ccrwait(portp);
+	stl_cd1400setreg(portp, CCR, ccr);
+	stl_cd1400ccrwait(portp);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Start/stop the Transmitter and/or Receiver.
+ */
+
+static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
+{
+	unsigned char	sreron, sreroff;
+	unsigned long	flags;
+
+	pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
+
+	sreron = 0;
+	sreroff = 0;
+	if (tx == 0)
+		sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
+	else if (tx == 1)
+		sreron |= SRER_TXDATA;
+	else if (tx >= 2)
+		sreron |= SRER_TXEMPTY;
+	if (rx == 0)
+		sreroff |= SRER_RXDATA;
+	else if (rx > 0)
+		sreron |= SRER_RXDATA;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	stl_cd1400setreg(portp, SRER,
+		((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
+	BRDDISABLE(portp->brdnr);
+	if (tx > 0)
+		set_bit(ASYI_TXBUSY, &portp->istate);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Disable all interrupts from this port.
+ */
+
+static void stl_cd1400disableintrs(struct stlport *portp)
+{
+	unsigned long	flags;
+
+	pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	stl_cd1400setreg(portp, SRER, 0);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+static void stl_cd1400sendbreak(struct stlport *portp, int len)
+{
+	unsigned long	flags;
+
+	pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	stl_cd1400setreg(portp, SRER,
+		((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
+		SRER_TXEMPTY));
+	BRDDISABLE(portp->brdnr);
+	portp->brklen = len;
+	if (len == 1)
+		portp->stats.txbreaks++;
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Take flow control actions...
+ */
+
+static void stl_cd1400flowctrl(struct stlport *portp, int state)
+{
+	struct tty_struct	*tty;
+	unsigned long		flags;
+
+	pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
+
+	if (portp == NULL)
+		return;
+	tty = tty_port_tty_get(&portp->port);
+	if (tty == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+
+	if (state) {
+		if (tty->termios->c_iflag & IXOFF) {
+			stl_cd1400ccrwait(portp);
+			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
+			portp->stats.rxxon++;
+			stl_cd1400ccrwait(portp);
+		}
+/*
+ *		Question: should we return RTS to what it was before? It may
+ *		have been set by an ioctl... Suppose not, since if you have
+ *		hardware flow control set then it is pretty silly to go and
+ *		set the RTS line by hand.
+ */
+		if (tty->termios->c_cflag & CRTSCTS) {
+			stl_cd1400setreg(portp, MCOR1,
+				(stl_cd1400getreg(portp, MCOR1) |
+				FIFO_RTSTHRESHOLD));
+			stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
+			portp->stats.rxrtson++;
+		}
+	} else {
+		if (tty->termios->c_iflag & IXOFF) {
+			stl_cd1400ccrwait(portp);
+			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
+			portp->stats.rxxoff++;
+			stl_cd1400ccrwait(portp);
+		}
+		if (tty->termios->c_cflag & CRTSCTS) {
+			stl_cd1400setreg(portp, MCOR1,
+				(stl_cd1400getreg(portp, MCOR1) & 0xf0));
+			stl_cd1400setreg(portp, MSVR2, 0);
+			portp->stats.rxrtsoff++;
+		}
+	}
+
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Send a flow control character...
+ */
+
+static void stl_cd1400sendflow(struct stlport *portp, int state)
+{
+	struct tty_struct	*tty;
+	unsigned long		flags;
+
+	pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
+
+	if (portp == NULL)
+		return;
+	tty = tty_port_tty_get(&portp->port);
+	if (tty == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	if (state) {
+		stl_cd1400ccrwait(portp);
+		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
+		portp->stats.rxxon++;
+		stl_cd1400ccrwait(portp);
+	} else {
+		stl_cd1400ccrwait(portp);
+		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
+		portp->stats.rxxoff++;
+		stl_cd1400ccrwait(portp);
+	}
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+static void stl_cd1400flush(struct stlport *portp)
+{
+	unsigned long	flags;
+
+	pr_debug("stl_cd1400flush(portp=%p)\n", portp);
+
+	if (portp == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
+	stl_cd1400ccrwait(portp);
+	stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
+	stl_cd1400ccrwait(portp);
+	portp->tx.tail = portp->tx.head;
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the current state of data flow on this port. This is only
+ *	really interesting when determining if data has fully completed
+ *	transmission or not... This is easy for the cd1400, it accurately
+ *	maintains the busy port flag.
+ */
+
+static int stl_cd1400datastate(struct stlport *portp)
+{
+	pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
+
+	if (portp == NULL)
+		return 0;
+
+	return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for cd1400 EasyIO boards.
+ */
+
+static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
+{
+	unsigned char	svrtype;
+
+	pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
+
+	spin_lock(&brd_lock);
+	outb(SVRR, iobase);
+	svrtype = inb(iobase + EREG_DATA);
+	if (panelp->nrports > 4) {
+		outb((SVRR + 0x80), iobase);
+		svrtype |= inb(iobase + EREG_DATA);
+	}
+
+	if (svrtype & SVRR_RX)
+		stl_cd1400rxisr(panelp, iobase);
+	else if (svrtype & SVRR_TX)
+		stl_cd1400txisr(panelp, iobase);
+	else if (svrtype & SVRR_MDM)
+		stl_cd1400mdmisr(panelp, iobase);
+
+	spin_unlock(&brd_lock);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for cd1400 panels.
+ */
+
+static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
+{
+	unsigned char	svrtype;
+
+	pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
+
+	outb(SVRR, iobase);
+	svrtype = inb(iobase + EREG_DATA);
+	outb((SVRR + 0x80), iobase);
+	svrtype |= inb(iobase + EREG_DATA);
+	if (svrtype & SVRR_RX)
+		stl_cd1400rxisr(panelp, iobase);
+	else if (svrtype & SVRR_TX)
+		stl_cd1400txisr(panelp, iobase);
+	else if (svrtype & SVRR_MDM)
+		stl_cd1400mdmisr(panelp, iobase);
+}
+
+
+/*****************************************************************************/
+
+/*
+ *	Unfortunately we need to handle breaks in the TX data stream, since
+ *	this is the only way to generate them on the cd1400.
+ */
+
+static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
+{
+	if (portp->brklen == 1) {
+		outb((COR2 + portp->uartaddr), ioaddr);
+		outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
+			(ioaddr + EREG_DATA));
+		outb((TDR + portp->uartaddr), ioaddr);
+		outb(ETC_CMD, (ioaddr + EREG_DATA));
+		outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
+		outb((SRER + portp->uartaddr), ioaddr);
+		outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
+			(ioaddr + EREG_DATA));
+		return 1;
+	} else if (portp->brklen > 1) {
+		outb((TDR + portp->uartaddr), ioaddr);
+		outb(ETC_CMD, (ioaddr + EREG_DATA));
+		outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
+		portp->brklen = -1;
+		return 1;
+	} else {
+		outb((COR2 + portp->uartaddr), ioaddr);
+		outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
+			(ioaddr + EREG_DATA));
+		portp->brklen = 0;
+	}
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Transmit interrupt handler. This has gotta be fast!  Handling TX
+ *	chars is pretty simple, stuff as many as possible from the TX buffer
+ *	into the cd1400 FIFO. Must also handle TX breaks here, since they
+ *	are embedded as commands in the data stream. Oh no, had to use a goto!
+ *	This could be optimized more, will do when I get time...
+ *	In practice it is possible that interrupts are enabled but that the
+ *	port has been hung up. Need to handle not having any TX buffer here,
+ *	this is done by using the side effect that head and tail will also
+ *	be NULL if the buffer has been freed.
+ */
+
+static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
+{
+	struct stlport	*portp;
+	int		len, stlen;
+	char		*head, *tail;
+	unsigned char	ioack, srer;
+	struct tty_struct *tty;
+
+	pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
+
+	ioack = inb(ioaddr + EREG_TXACK);
+	if (((ioack & panelp->ackmask) != 0) ||
+	    ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
+		printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
+		return;
+	}
+	portp = panelp->ports[(ioack >> 3)];
+
+/*
+ *	Unfortunately we need to handle breaks in the data stream, since
+ *	this is the only way to generate them on the cd1400. Do it now if
+ *	a break is to be sent.
+ */
+	if (portp->brklen != 0)
+		if (stl_cd1400breakisr(portp, ioaddr))
+			goto stl_txalldone;
+
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
+	if ((len == 0) || ((len < STL_TXBUFLOW) &&
+	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
+		set_bit(ASYI_TXLOW, &portp->istate);
+		tty = tty_port_tty_get(&portp->port);
+		if (tty) {
+			tty_wakeup(tty);
+			tty_kref_put(tty);
+		}
+	}
+
+	if (len == 0) {
+		outb((SRER + portp->uartaddr), ioaddr);
+		srer = inb(ioaddr + EREG_DATA);
+		if (srer & SRER_TXDATA) {
+			srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
+		} else {
+			srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
+			clear_bit(ASYI_TXBUSY, &portp->istate);
+		}
+		outb(srer, (ioaddr + EREG_DATA));
+	} else {
+		len = min(len, CD1400_TXFIFOSIZE);
+		portp->stats.txtotal += len;
+		stlen = min_t(unsigned int, len,
+				(portp->tx.buf + STL_TXBUFSIZE) - tail);
+		outb((TDR + portp->uartaddr), ioaddr);
+		outsb((ioaddr + EREG_DATA), tail, stlen);
+		len -= stlen;
+		tail += stlen;
+		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
+			tail = portp->tx.buf;
+		if (len > 0) {
+			outsb((ioaddr + EREG_DATA), tail, len);
+			tail += len;
+		}
+		portp->tx.tail = tail;
+	}
+
+stl_txalldone:
+	outb((EOSRR + portp->uartaddr), ioaddr);
+	outb(0, (ioaddr + EREG_DATA));
+}
+
+/*****************************************************************************/
+
+/*
+ *	Receive character interrupt handler. Determine if we have good chars
+ *	or bad chars and then process appropriately. Good chars are easy
+ *	just shove the lot into the RX buffer and set all status byte to 0.
+ *	If a bad RX char then process as required. This routine needs to be
+ *	fast!  In practice it is possible that we get an interrupt on a port
+ *	that is closed. This can happen on hangups - since they completely
+ *	shutdown a port not in user context. Need to handle this case.
+ */
+
+static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
+{
+	struct stlport		*portp;
+	struct tty_struct	*tty;
+	unsigned int		ioack, len, buflen;
+	unsigned char		status;
+	char			ch;
+
+	pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
+
+	ioack = inb(ioaddr + EREG_RXACK);
+	if ((ioack & panelp->ackmask) != 0) {
+		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
+		return;
+	}
+	portp = panelp->ports[(ioack >> 3)];
+	tty = tty_port_tty_get(&portp->port);
+
+	if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
+		outb((RDCR + portp->uartaddr), ioaddr);
+		len = inb(ioaddr + EREG_DATA);
+		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
+			len = min_t(unsigned int, len, sizeof(stl_unwanted));
+			outb((RDSR + portp->uartaddr), ioaddr);
+			insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
+			portp->stats.rxlost += len;
+			portp->stats.rxtotal += len;
+		} else {
+			len = min(len, buflen);
+			if (len > 0) {
+				unsigned char *ptr;
+				outb((RDSR + portp->uartaddr), ioaddr);
+				tty_prepare_flip_string(tty, &ptr, len);
+				insb((ioaddr + EREG_DATA), ptr, len);
+				tty_schedule_flip(tty);
+				portp->stats.rxtotal += len;
+			}
+		}
+	} else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
+		outb((RDSR + portp->uartaddr), ioaddr);
+		status = inb(ioaddr + EREG_DATA);
+		ch = inb(ioaddr + EREG_DATA);
+		if (status & ST_PARITY)
+			portp->stats.rxparity++;
+		if (status & ST_FRAMING)
+			portp->stats.rxframing++;
+		if (status & ST_OVERRUN)
+			portp->stats.rxoverrun++;
+		if (status & ST_BREAK)
+			portp->stats.rxbreaks++;
+		if (status & ST_SCHARMASK) {
+			if ((status & ST_SCHARMASK) == ST_SCHAR1)
+				portp->stats.txxon++;
+			if ((status & ST_SCHARMASK) == ST_SCHAR2)
+				portp->stats.txxoff++;
+			goto stl_rxalldone;
+		}
+		if (tty != NULL && (portp->rxignoremsk & status) == 0) {
+			if (portp->rxmarkmsk & status) {
+				if (status & ST_BREAK) {
+					status = TTY_BREAK;
+					if (portp->port.flags & ASYNC_SAK) {
+						do_SAK(tty);
+						BRDENABLE(portp->brdnr, portp->pagenr);
+					}
+				} else if (status & ST_PARITY)
+					status = TTY_PARITY;
+				else if (status & ST_FRAMING)
+					status = TTY_FRAME;
+				else if(status & ST_OVERRUN)
+					status = TTY_OVERRUN;
+				else
+					status = 0;
+			} else
+				status = 0;
+			tty_insert_flip_char(tty, ch, status);
+			tty_schedule_flip(tty);
+		}
+	} else {
+		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
+		tty_kref_put(tty);
+		return;
+	}
+
+stl_rxalldone:
+	tty_kref_put(tty);
+	outb((EOSRR + portp->uartaddr), ioaddr);
+	outb(0, (ioaddr + EREG_DATA));
+}
+
+/*****************************************************************************/
+
+/*
+ *	Modem interrupt handler. The is called when the modem signal line
+ *	(DCD) has changed state. Leave most of the work to the off-level
+ *	processing routine.
+ */
+
+static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
+{
+	struct stlport	*portp;
+	unsigned int	ioack;
+	unsigned char	misr;
+
+	pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
+
+	ioack = inb(ioaddr + EREG_MDACK);
+	if (((ioack & panelp->ackmask) != 0) ||
+	    ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
+		printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
+		return;
+	}
+	portp = panelp->ports[(ioack >> 3)];
+
+	outb((MISR + portp->uartaddr), ioaddr);
+	misr = inb(ioaddr + EREG_DATA);
+	if (misr & MISR_DCD) {
+		stl_cd_change(portp);
+		portp->stats.modem++;
+	}
+
+	outb((EOSRR + portp->uartaddr), ioaddr);
+	outb(0, (ioaddr + EREG_DATA));
+}
+
+/*****************************************************************************/
+/*                      SC26198 HARDWARE FUNCTIONS                           */
+/*****************************************************************************/
+
+/*
+ *	These functions get/set/update the registers of the sc26198 UARTs.
+ *	Access to the sc26198 registers is via an address/data io port pair.
+ *	(Maybe should make this inline...)
+ */
+
+static int stl_sc26198getreg(struct stlport *portp, int regnr)
+{
+	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
+	return inb(portp->ioaddr + XP_DATA);
+}
+
+static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
+{
+	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
+	outb(value, (portp->ioaddr + XP_DATA));
+}
+
+static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
+{
+	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
+	if (inb(portp->ioaddr + XP_DATA) != value) {
+		outb(value, (portp->ioaddr + XP_DATA));
+		return 1;
+	}
+	return 0;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Functions to get and set the sc26198 global registers.
+ */
+
+static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
+{
+	outb(regnr, (portp->ioaddr + XP_ADDR));
+	return inb(portp->ioaddr + XP_DATA);
+}
+
+#if 0
+static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
+{
+	outb(regnr, (portp->ioaddr + XP_ADDR));
+	outb(value, (portp->ioaddr + XP_DATA));
+}
+#endif
+
+/*****************************************************************************/
+
+/*
+ *	Inbitialize the UARTs in a panel. We don't care what sort of board
+ *	these ports are on - since the port io registers are almost
+ *	identical when dealing with ports.
+ */
+
+static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
+{
+	int	chipmask, i;
+	int	nrchips, ioaddr;
+
+	pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
+
+	BRDENABLE(panelp->brdnr, panelp->pagenr);
+
+/*
+ *	Check that each chip is present and started up OK.
+ */
+	chipmask = 0;
+	nrchips = (panelp->nrports + 4) / SC26198_PORTS;
+	if (brdp->brdtype == BRD_ECHPCI)
+		outb(panelp->pagenr, brdp->ioctrl);
+
+	for (i = 0; i < nrchips; i++) {
+		ioaddr = panelp->iobase + (i * 4); 
+		outb(SCCR, (ioaddr + XP_ADDR));
+		outb(CR_RESETALL, (ioaddr + XP_DATA));
+		outb(TSTR, (ioaddr + XP_ADDR));
+		if (inb(ioaddr + XP_DATA) != 0) {
+			printk("STALLION: sc26198 not responding, "
+				"brd=%d panel=%d chip=%d\n",
+				panelp->brdnr, panelp->panelnr, i);
+			continue;
+		}
+		chipmask |= (0x1 << i);
+		outb(GCCR, (ioaddr + XP_ADDR));
+		outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
+		outb(WDTRCR, (ioaddr + XP_ADDR));
+		outb(0xff, (ioaddr + XP_DATA));
+	}
+
+	BRDDISABLE(panelp->brdnr);
+	return chipmask;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Initialize hardware specific port registers.
+ */
+
+static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
+{
+	pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
+			panelp, portp);
+
+	if ((brdp == NULL) || (panelp == NULL) ||
+	    (portp == NULL))
+		return;
+
+	portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
+	portp->uartaddr = (portp->portnr & 0x07) << 4;
+	portp->pagenr = panelp->pagenr;
+	portp->hwid = 0x1;
+
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
+	BRDDISABLE(portp->brdnr);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set up the sc26198 registers for a port based on the termios port
+ *	settings.
+ */
+
+static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
+{
+	struct stlbrd	*brdp;
+	unsigned long	flags;
+	unsigned int	baudrate;
+	unsigned char	mr0, mr1, mr2, clk;
+	unsigned char	imron, imroff, iopr, ipr;
+
+	mr0 = 0;
+	mr1 = 0;
+	mr2 = 0;
+	clk = 0;
+	iopr = 0;
+	imron = 0;
+	imroff = 0;
+
+	brdp = stl_brds[portp->brdnr];
+	if (brdp == NULL)
+		return;
+
+/*
+ *	Set up the RX char ignore mask with those RX error types we
+ *	can ignore.
+ */
+	portp->rxignoremsk = 0;
+	if (tiosp->c_iflag & IGNPAR)
+		portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
+			SR_RXOVERRUN);
+	if (tiosp->c_iflag & IGNBRK)
+		portp->rxignoremsk |= SR_RXBREAK;
+
+	portp->rxmarkmsk = SR_RXOVERRUN;
+	if (tiosp->c_iflag & (INPCK | PARMRK))
+		portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
+	if (tiosp->c_iflag & BRKINT)
+		portp->rxmarkmsk |= SR_RXBREAK;
+
+/*
+ *	Go through the char size, parity and stop bits and set all the
+ *	option register appropriately.
+ */
+	switch (tiosp->c_cflag & CSIZE) {
+	case CS5:
+		mr1 |= MR1_CS5;
+		break;
+	case CS6:
+		mr1 |= MR1_CS6;
+		break;
+	case CS7:
+		mr1 |= MR1_CS7;
+		break;
+	default:
+		mr1 |= MR1_CS8;
+		break;
+	}
+
+	if (tiosp->c_cflag & CSTOPB)
+		mr2 |= MR2_STOP2;
+	else
+		mr2 |= MR2_STOP1;
+
+	if (tiosp->c_cflag & PARENB) {
+		if (tiosp->c_cflag & PARODD)
+			mr1 |= (MR1_PARENB | MR1_PARODD);
+		else
+			mr1 |= (MR1_PARENB | MR1_PAREVEN);
+	} else
+		mr1 |= MR1_PARNONE;
+
+	mr1 |= MR1_ERRBLOCK;
+
+/*
+ *	Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
+ *	space for hardware flow control and the like. This should be set to
+ *	VMIN.
+ */
+	mr2 |= MR2_RXFIFOHALF;
+
+/*
+ *	Calculate the baud rate timers. For now we will just assume that
+ *	the input and output baud are the same. The sc26198 has a fixed
+ *	baud rate table, so only discrete baud rates possible.
+ */
+	baudrate = tiosp->c_cflag & CBAUD;
+	if (baudrate & CBAUDEX) {
+		baudrate &= ~CBAUDEX;
+		if ((baudrate < 1) || (baudrate > 4))
+			tiosp->c_cflag &= ~CBAUDEX;
+		else
+			baudrate += 15;
+	}
+	baudrate = stl_baudrates[baudrate];
+	if ((tiosp->c_cflag & CBAUD) == B38400) {
+		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			baudrate = 57600;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			baudrate = 115200;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			baudrate = 230400;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			baudrate = 460800;
+		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
+			baudrate = (portp->baud_base / portp->custom_divisor);
+	}
+	if (baudrate > STL_SC26198MAXBAUD)
+		baudrate = STL_SC26198MAXBAUD;
+
+	if (baudrate > 0)
+		for (clk = 0; clk < SC26198_NRBAUDS; clk++)
+			if (baudrate <= sc26198_baudtable[clk])
+				break;
+
+/*
+ *	Check what form of modem signaling is required and set it up.
+ */
+	if (tiosp->c_cflag & CLOCAL) {
+		portp->port.flags &= ~ASYNC_CHECK_CD;
+	} else {
+		iopr |= IOPR_DCDCOS;
+		imron |= IR_IOPORT;
+		portp->port.flags |= ASYNC_CHECK_CD;
+	}
+
+/*
+ *	Setup sc26198 enhanced modes if we can. In particular we want to
+ *	handle as much of the flow control as possible automatically. As
+ *	well as saving a few CPU cycles it will also greatly improve flow
+ *	control reliability.
+ */
+	if (tiosp->c_iflag & IXON) {
+		mr0 |= MR0_SWFTX | MR0_SWFT;
+		imron |= IR_XONXOFF;
+	} else
+		imroff |= IR_XONXOFF;
+
+	if (tiosp->c_iflag & IXOFF)
+		mr0 |= MR0_SWFRX;
+
+	if (tiosp->c_cflag & CRTSCTS) {
+		mr2 |= MR2_AUTOCTS;
+		mr1 |= MR1_AUTORTS;
+	}
+
+/*
+ *	All sc26198 register values calculated so go through and set
+ *	them all up.
+ */
+
+	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
+		portp->portnr, portp->panelnr, portp->brdnr);
+	pr_debug("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
+	pr_debug("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
+	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
+		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
+		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_sc26198setreg(portp, IMR, 0);
+	stl_sc26198updatereg(portp, MR0, mr0);
+	stl_sc26198updatereg(portp, MR1, mr1);
+	stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
+	stl_sc26198updatereg(portp, MR2, mr2);
+	stl_sc26198updatereg(portp, IOPIOR,
+		((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
+
+	if (baudrate > 0) {
+		stl_sc26198setreg(portp, TXCSR, clk);
+		stl_sc26198setreg(portp, RXCSR, clk);
+	}
+
+	stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
+	stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
+
+	ipr = stl_sc26198getreg(portp, IPR);
+	if (ipr & IPR_DCD)
+		portp->sigs &= ~TIOCM_CD;
+	else
+		portp->sigs |= TIOCM_CD;
+
+	portp->imr = (portp->imr & ~imroff) | imron;
+	stl_sc26198setreg(portp, IMR, portp->imr);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Set the state of the DTR and RTS signals.
+ */
+
+static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
+{
+	unsigned char	iopioron, iopioroff;
+	unsigned long	flags;
+
+	pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
+			dtr, rts);
+
+	iopioron = 0;
+	iopioroff = 0;
+	if (dtr == 0)
+		iopioroff |= IPR_DTR;
+	else if (dtr > 0)
+		iopioron |= IPR_DTR;
+	if (rts == 0)
+		iopioroff |= IPR_RTS;
+	else if (rts > 0)
+		iopioron |= IPR_RTS;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_sc26198setreg(portp, IOPIOR,
+		((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the state of the signals.
+ */
+
+static int stl_sc26198getsignals(struct stlport *portp)
+{
+	unsigned char	ipr;
+	unsigned long	flags;
+	int		sigs;
+
+	pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	ipr = stl_sc26198getreg(portp, IPR);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	sigs = 0;
+	sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
+	sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
+	sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
+	sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
+	sigs |= TIOCM_DSR;
+	return sigs;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Enable/Disable the Transmitter and/or Receiver.
+ */
+
+static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
+{
+	unsigned char	ccr;
+	unsigned long	flags;
+
+	pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
+
+	ccr = portp->crenable;
+	if (tx == 0)
+		ccr &= ~CR_TXENABLE;
+	else if (tx > 0)
+		ccr |= CR_TXENABLE;
+	if (rx == 0)
+		ccr &= ~CR_RXENABLE;
+	else if (rx > 0)
+		ccr |= CR_RXENABLE;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_sc26198setreg(portp, SCCR, ccr);
+	BRDDISABLE(portp->brdnr);
+	portp->crenable = ccr;
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Start/stop the Transmitter and/or Receiver.
+ */
+
+static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
+{
+	unsigned char	imr;
+	unsigned long	flags;
+
+	pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
+
+	imr = portp->imr;
+	if (tx == 0)
+		imr &= ~IR_TXRDY;
+	else if (tx == 1)
+		imr |= IR_TXRDY;
+	if (rx == 0)
+		imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
+	else if (rx > 0)
+		imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_sc26198setreg(portp, IMR, imr);
+	BRDDISABLE(portp->brdnr);
+	portp->imr = imr;
+	if (tx > 0)
+		set_bit(ASYI_TXBUSY, &portp->istate);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Disable all interrupts from this port.
+ */
+
+static void stl_sc26198disableintrs(struct stlport *portp)
+{
+	unsigned long	flags;
+
+	pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	portp->imr = 0;
+	stl_sc26198setreg(portp, IMR, 0);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+static void stl_sc26198sendbreak(struct stlport *portp, int len)
+{
+	unsigned long	flags;
+
+	pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	if (len == 1) {
+		stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
+		portp->stats.txbreaks++;
+	} else
+		stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
+
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Take flow control actions...
+ */
+
+static void stl_sc26198flowctrl(struct stlport *portp, int state)
+{
+	struct tty_struct	*tty;
+	unsigned long		flags;
+	unsigned char		mr0;
+
+	pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
+
+	if (portp == NULL)
+		return;
+	tty = tty_port_tty_get(&portp->port);
+	if (tty == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+
+	if (state) {
+		if (tty->termios->c_iflag & IXOFF) {
+			mr0 = stl_sc26198getreg(portp, MR0);
+			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
+			stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
+			mr0 |= MR0_SWFRX;
+			portp->stats.rxxon++;
+			stl_sc26198wait(portp);
+			stl_sc26198setreg(portp, MR0, mr0);
+		}
+/*
+ *		Question: should we return RTS to what it was before? It may
+ *		have been set by an ioctl... Suppose not, since if you have
+ *		hardware flow control set then it is pretty silly to go and
+ *		set the RTS line by hand.
+ */
+		if (tty->termios->c_cflag & CRTSCTS) {
+			stl_sc26198setreg(portp, MR1,
+				(stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
+			stl_sc26198setreg(portp, IOPIOR,
+				(stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
+			portp->stats.rxrtson++;
+		}
+	} else {
+		if (tty->termios->c_iflag & IXOFF) {
+			mr0 = stl_sc26198getreg(portp, MR0);
+			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
+			stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
+			mr0 &= ~MR0_SWFRX;
+			portp->stats.rxxoff++;
+			stl_sc26198wait(portp);
+			stl_sc26198setreg(portp, MR0, mr0);
+		}
+		if (tty->termios->c_cflag & CRTSCTS) {
+			stl_sc26198setreg(portp, MR1,
+				(stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
+			stl_sc26198setreg(portp, IOPIOR,
+				(stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
+			portp->stats.rxrtsoff++;
+		}
+	}
+
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Send a flow control character.
+ */
+
+static void stl_sc26198sendflow(struct stlport *portp, int state)
+{
+	struct tty_struct	*tty;
+	unsigned long		flags;
+	unsigned char		mr0;
+
+	pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
+
+	if (portp == NULL)
+		return;
+	tty = tty_port_tty_get(&portp->port);
+	if (tty == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	if (state) {
+		mr0 = stl_sc26198getreg(portp, MR0);
+		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
+		stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
+		mr0 |= MR0_SWFRX;
+		portp->stats.rxxon++;
+		stl_sc26198wait(portp);
+		stl_sc26198setreg(portp, MR0, mr0);
+	} else {
+		mr0 = stl_sc26198getreg(portp, MR0);
+		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
+		stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
+		mr0 &= ~MR0_SWFRX;
+		portp->stats.rxxoff++;
+		stl_sc26198wait(portp);
+		stl_sc26198setreg(portp, MR0, mr0);
+	}
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+static void stl_sc26198flush(struct stlport *portp)
+{
+	unsigned long	flags;
+
+	pr_debug("stl_sc26198flush(portp=%p)\n", portp);
+
+	if (portp == NULL)
+		return;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	stl_sc26198setreg(portp, SCCR, CR_TXRESET);
+	stl_sc26198setreg(portp, SCCR, portp->crenable);
+	BRDDISABLE(portp->brdnr);
+	portp->tx.tail = portp->tx.head;
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Return the current state of data flow on this port. This is only
+ *	really interesting when determining if data has fully completed
+ *	transmission or not... The sc26198 interrupt scheme cannot
+ *	determine when all data has actually drained, so we need to
+ *	check the port statusy register to be sure.
+ */
+
+static int stl_sc26198datastate(struct stlport *portp)
+{
+	unsigned long	flags;
+	unsigned char	sr;
+
+	pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
+
+	if (portp == NULL)
+		return 0;
+	if (test_bit(ASYI_TXBUSY, &portp->istate))
+		return 1;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	BRDENABLE(portp->brdnr, portp->pagenr);
+	sr = stl_sc26198getreg(portp, SR);
+	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	return (sr & SR_TXEMPTY) ? 0 : 1;
+}
+
+/*****************************************************************************/
+
+/*
+ *	Delay for a small amount of time, to give the sc26198 a chance
+ *	to process a command...
+ */
+
+static void stl_sc26198wait(struct stlport *portp)
+{
+	int	i;
+
+	pr_debug("stl_sc26198wait(portp=%p)\n", portp);
+
+	if (portp == NULL)
+		return;
+
+	for (i = 0; i < 20; i++)
+		stl_sc26198getglobreg(portp, TSTR);
+}
+
+/*****************************************************************************/
+
+/*
+ *	If we are TX flow controlled and in IXANY mode then we may
+ *	need to unflow control here. We gotta do this because of the
+ *	automatic flow control modes of the sc26198.
+ */
+
+static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
+{
+	unsigned char	mr0;
+
+	mr0 = stl_sc26198getreg(portp, MR0);
+	stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
+	stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
+	stl_sc26198wait(portp);
+	stl_sc26198setreg(portp, MR0, mr0);
+	clear_bit(ASYI_TXFLOWED, &portp->istate);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Interrupt service routine for sc26198 panels.
+ */
+
+static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
+{
+	struct stlport	*portp;
+	unsigned int	iack;
+
+	spin_lock(&brd_lock);
+
+/* 
+ *	Work around bug in sc26198 chip... Cannot have A6 address
+ *	line of UART high, else iack will be returned as 0.
+ */
+	outb(0, (iobase + 1));
+
+	iack = inb(iobase + XP_IACK);
+	portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
+
+	if (iack & IVR_RXDATA)
+		stl_sc26198rxisr(portp, iack);
+	else if (iack & IVR_TXDATA)
+		stl_sc26198txisr(portp);
+	else
+		stl_sc26198otherisr(portp, iack);
+
+	spin_unlock(&brd_lock);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Transmit interrupt handler. This has gotta be fast!  Handling TX
+ *	chars is pretty simple, stuff as many as possible from the TX buffer
+ *	into the sc26198 FIFO.
+ *	In practice it is possible that interrupts are enabled but that the
+ *	port has been hung up. Need to handle not having any TX buffer here,
+ *	this is done by using the side effect that head and tail will also
+ *	be NULL if the buffer has been freed.
+ */
+
+static void stl_sc26198txisr(struct stlport *portp)
+{
+	struct tty_struct *tty;
+	unsigned int	ioaddr;
+	unsigned char	mr0;
+	int		len, stlen;
+	char		*head, *tail;
+
+	pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
+
+	ioaddr = portp->ioaddr;
+	head = portp->tx.head;
+	tail = portp->tx.tail;
+	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
+	if ((len == 0) || ((len < STL_TXBUFLOW) &&
+	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
+		set_bit(ASYI_TXLOW, &portp->istate);
+		tty = tty_port_tty_get(&portp->port);
+		if (tty) {
+			tty_wakeup(tty);
+			tty_kref_put(tty);
+		}
+	}
+
+	if (len == 0) {
+		outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
+		mr0 = inb(ioaddr + XP_DATA);
+		if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
+			portp->imr &= ~IR_TXRDY;
+			outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
+			outb(portp->imr, (ioaddr + XP_DATA));
+			clear_bit(ASYI_TXBUSY, &portp->istate);
+		} else {
+			mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
+			outb(mr0, (ioaddr + XP_DATA));
+		}
+	} else {
+		len = min(len, SC26198_TXFIFOSIZE);
+		portp->stats.txtotal += len;
+		stlen = min_t(unsigned int, len,
+				(portp->tx.buf + STL_TXBUFSIZE) - tail);
+		outb(GTXFIFO, (ioaddr + XP_ADDR));
+		outsb((ioaddr + XP_DATA), tail, stlen);
+		len -= stlen;
+		tail += stlen;
+		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
+			tail = portp->tx.buf;
+		if (len > 0) {
+			outsb((ioaddr + XP_DATA), tail, len);
+			tail += len;
+		}
+		portp->tx.tail = tail;
+	}
+}
+
+/*****************************************************************************/
+
+/*
+ *	Receive character interrupt handler. Determine if we have good chars
+ *	or bad chars and then process appropriately. Good chars are easy
+ *	just shove the lot into the RX buffer and set all status byte to 0.
+ *	If a bad RX char then process as required. This routine needs to be
+ *	fast!  In practice it is possible that we get an interrupt on a port
+ *	that is closed. This can happen on hangups - since they completely
+ *	shutdown a port not in user context. Need to handle this case.
+ */
+
+static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
+{
+	struct tty_struct	*tty;
+	unsigned int		len, buflen, ioaddr;
+
+	pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
+
+	tty = tty_port_tty_get(&portp->port);
+	ioaddr = portp->ioaddr;
+	outb(GIBCR, (ioaddr + XP_ADDR));
+	len = inb(ioaddr + XP_DATA) + 1;
+
+	if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
+		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
+			len = min_t(unsigned int, len, sizeof(stl_unwanted));
+			outb(GRXFIFO, (ioaddr + XP_ADDR));
+			insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
+			portp->stats.rxlost += len;
+			portp->stats.rxtotal += len;
+		} else {
+			len = min(len, buflen);
+			if (len > 0) {
+				unsigned char *ptr;
+				outb(GRXFIFO, (ioaddr + XP_ADDR));
+				tty_prepare_flip_string(tty, &ptr, len);
+				insb((ioaddr + XP_DATA), ptr, len);
+				tty_schedule_flip(tty);
+				portp->stats.rxtotal += len;
+			}
+		}
+	} else {
+		stl_sc26198rxbadchars(portp);
+	}
+
+/*
+ *	If we are TX flow controlled and in IXANY mode then we may need
+ *	to unflow control here. We gotta do this because of the automatic
+ *	flow control modes of the sc26198.
+ */
+	if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
+		if ((tty != NULL) &&
+		    (tty->termios != NULL) &&
+		    (tty->termios->c_iflag & IXANY)) {
+			stl_sc26198txunflow(portp, tty);
+		}
+	}
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Process an RX bad character.
+ */
+
+static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
+{
+	struct tty_struct	*tty;
+	unsigned int		ioaddr;
+
+	tty = tty_port_tty_get(&portp->port);
+	ioaddr = portp->ioaddr;
+
+	if (status & SR_RXPARITY)
+		portp->stats.rxparity++;
+	if (status & SR_RXFRAMING)
+		portp->stats.rxframing++;
+	if (status & SR_RXOVERRUN)
+		portp->stats.rxoverrun++;
+	if (status & SR_RXBREAK)
+		portp->stats.rxbreaks++;
+
+	if ((tty != NULL) &&
+	    ((portp->rxignoremsk & status) == 0)) {
+		if (portp->rxmarkmsk & status) {
+			if (status & SR_RXBREAK) {
+				status = TTY_BREAK;
+				if (portp->port.flags & ASYNC_SAK) {
+					do_SAK(tty);
+					BRDENABLE(portp->brdnr, portp->pagenr);
+				}
+			} else if (status & SR_RXPARITY)
+				status = TTY_PARITY;
+			else if (status & SR_RXFRAMING)
+				status = TTY_FRAME;
+			else if(status & SR_RXOVERRUN)
+				status = TTY_OVERRUN;
+			else
+				status = 0;
+		} else
+			status = 0;
+
+		tty_insert_flip_char(tty, ch, status);
+		tty_schedule_flip(tty);
+
+		if (status == 0)
+			portp->stats.rxtotal++;
+	}
+	tty_kref_put(tty);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Process all characters in the RX FIFO of the UART. Check all char
+ *	status bytes as well, and process as required. We need to check
+ *	all bytes in the FIFO, in case some more enter the FIFO while we
+ *	are here. To get the exact character error type we need to switch
+ *	into CHAR error mode (that is why we need to make sure we empty
+ *	the FIFO).
+ */
+
+static void stl_sc26198rxbadchars(struct stlport *portp)
+{
+	unsigned char	status, mr1;
+	char		ch;
+
+/*
+ *	To get the precise error type for each character we must switch
+ *	back into CHAR error mode.
+ */
+	mr1 = stl_sc26198getreg(portp, MR1);
+	stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
+
+	while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
+		stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
+		ch = stl_sc26198getreg(portp, RXFIFO);
+		stl_sc26198rxbadch(portp, status, ch);
+	}
+
+/*
+ *	To get correct interrupt class we must switch back into BLOCK
+ *	error mode.
+ */
+	stl_sc26198setreg(portp, MR1, mr1);
+}
+
+/*****************************************************************************/
+
+/*
+ *	Other interrupt handler. This includes modem signals, flow
+ *	control actions, etc. Most stuff is left to off-level interrupt
+ *	processing time.
+ */
+
+static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
+{
+	unsigned char	cir, ipr, xisr;
+
+	pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
+
+	cir = stl_sc26198getglobreg(portp, CIR);
+
+	switch (cir & CIR_SUBTYPEMASK) {
+	case CIR_SUBCOS:
+		ipr = stl_sc26198getreg(portp, IPR);
+		if (ipr & IPR_DCDCHANGE) {
+			stl_cd_change(portp);
+			portp->stats.modem++;
+		}
+		break;
+	case CIR_SUBXONXOFF:
+		xisr = stl_sc26198getreg(portp, XISR);
+		if (xisr & XISR_RXXONGOT) {
+			set_bit(ASYI_TXFLOWED, &portp->istate);
+			portp->stats.txxoff++;
+		}
+		if (xisr & XISR_RXXOFFGOT) {
+			clear_bit(ASYI_TXFLOWED, &portp->istate);
+			portp->stats.txxon++;
+		}
+		break;
+	case CIR_SUBBREAK:
+		stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
+		stl_sc26198rxbadchars(portp);
+		break;
+	default:
+		break;
+	}
+}
+
+static void stl_free_isabrds(void)
+{
+	struct stlbrd *brdp;
+	unsigned int i;
+
+	for (i = 0; i < stl_nrbrds; i++) {
+		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
+			continue;
+
+		free_irq(brdp->irq, brdp);
+
+		stl_cleanup_panels(brdp);
+
+		release_region(brdp->ioaddr1, brdp->iosize1);
+		if (brdp->iosize2 > 0)
+			release_region(brdp->ioaddr2, brdp->iosize2);
+
+		kfree(brdp);
+		stl_brds[i] = NULL;
+	}
+}
+
+/*
+ *	Loadable module initialization stuff.
+ */
+static int __init stallion_module_init(void)
+{
+	struct stlbrd	*brdp;
+	struct stlconf	conf;
+	unsigned int i, j;
+	int retval;
+
+	printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
+
+	spin_lock_init(&stallion_lock);
+	spin_lock_init(&brd_lock);
+
+	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
+	if (!stl_serial) {
+		retval = -ENOMEM;
+		goto err;
+	}
+
+	stl_serial->owner = THIS_MODULE;
+	stl_serial->driver_name = stl_drvname;
+	stl_serial->name = "ttyE";
+	stl_serial->major = STL_SERIALMAJOR;
+	stl_serial->minor_start = 0;
+	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
+	stl_serial->subtype = SERIAL_TYPE_NORMAL;
+	stl_serial->init_termios = stl_deftermios;
+	stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(stl_serial, &stl_ops);
+
+	retval = tty_register_driver(stl_serial);
+	if (retval) {
+		printk("STALLION: failed to register serial driver\n");
+		goto err_frtty;
+	}
+
+/*
+ *	Find any dynamically supported boards. That is via module load
+ *	line options.
+ */
+	for (i = stl_nrbrds; i < stl_nargs; i++) {
+		memset(&conf, 0, sizeof(conf));
+		if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
+			continue;
+		if ((brdp = stl_allocbrd()) == NULL)
+			continue;
+		brdp->brdnr = i;
+		brdp->brdtype = conf.brdtype;
+		brdp->ioaddr1 = conf.ioaddr1;
+		brdp->ioaddr2 = conf.ioaddr2;
+		brdp->irq = conf.irq;
+		brdp->irqtype = conf.irqtype;
+		stl_brds[brdp->brdnr] = brdp;
+		if (stl_brdinit(brdp)) {
+			stl_brds[brdp->brdnr] = NULL;
+			kfree(brdp);
+		} else {
+			for (j = 0; j < brdp->nrports; j++)
+				tty_register_device(stl_serial,
+					brdp->brdnr * STL_MAXPORTS + j, NULL);
+			stl_nrbrds = i + 1;
+		}
+	}
+
+	/* this has to be _after_ isa finding because of locking */
+	retval = pci_register_driver(&stl_pcidriver);
+	if (retval && stl_nrbrds == 0) {
+		printk(KERN_ERR "STALLION: can't register pci driver\n");
+		goto err_unrtty;
+	}
+
+/*
+ *	Set up a character driver for per board stuff. This is mainly used
+ *	to do stats ioctls on the ports.
+ */
+	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
+		printk("STALLION: failed to register serial board device\n");
+
+	stallion_class = class_create(THIS_MODULE, "staliomem");
+	if (IS_ERR(stallion_class))
+		printk("STALLION: failed to create class\n");
+	for (i = 0; i < 4; i++)
+		device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+			      NULL, "staliomem%d", i);
+
+	return 0;
+err_unrtty:
+	tty_unregister_driver(stl_serial);
+err_frtty:
+	put_tty_driver(stl_serial);
+err:
+	return retval;
+}
+
+static void __exit stallion_module_exit(void)
+{
+	struct stlbrd *brdp;
+	unsigned int i, j;
+
+	pr_debug("cleanup_module()\n");
+
+	printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
+		stl_drvversion);
+
+/*
+ *	Free up all allocated resources used by the ports. This includes
+ *	memory and interrupts. As part of this process we will also do
+ *	a hangup on every open port - to try to flush out any processes
+ *	hanging onto ports.
+ */
+	for (i = 0; i < stl_nrbrds; i++) {
+		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
+			continue;
+		for (j = 0; j < brdp->nrports; j++)
+			tty_unregister_device(stl_serial,
+				brdp->brdnr * STL_MAXPORTS + j);
+	}
+
+	for (i = 0; i < 4; i++)
+		device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
+	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
+	class_destroy(stallion_class);
+
+	pci_unregister_driver(&stl_pcidriver);
+
+	stl_free_isabrds();
+
+	tty_unregister_driver(stl_serial);
+	put_tty_driver(stl_serial);
+}
+
+module_init(stallion_module_init);
+module_exit(stallion_module_exit);
+
+MODULE_AUTHOR("Greg Ungerer");
+MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
index b11ec37..2c1d10a 100644
--- a/drivers/staging/usbip/Kconfig
+++ b/drivers/staging/usbip/Kconfig
@@ -1,6 +1,6 @@
 config USB_IP_COMMON
 	tristate "USB IP support (EXPERIMENTAL)"
-	depends on USB && NET && EXPERIMENTAL && BKL
+	depends on USB && NET && EXPERIMENTAL
 	default N
 	---help---
 	  This enables pushing USB packets over IP to allow remote
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
index d732679..6004fcd 100644
--- a/drivers/staging/usbip/stub.h
+++ b/drivers/staging/usbip/stub.h
@@ -95,13 +95,13 @@ extern struct kmem_cache *stub_priv_cache;
 
 /* stub_tx.c */
 void stub_complete(struct urb *);
-void stub_tx_loop(struct usbip_task *);
+int stub_tx_loop(void *data);
 
 /* stub_dev.c */
 extern struct usb_driver stub_driver;
 
 /* stub_rx.c */
-void stub_rx_loop(struct usbip_task *);
+int stub_rx_loop(void *data);
 void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);
 
 /* stub_main.c */
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
index a7ce51c..8214c35 100644
--- a/drivers/staging/usbip/stub_dev.c
+++ b/drivers/staging/usbip/stub_dev.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "stub.h"
@@ -138,7 +139,8 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
 
 		spin_unlock(&sdev->ud.lock);
 
-		usbip_start_threads(&sdev->ud);
+		sdev->ud.tcp_rx = kthread_run(stub_rx_loop, &sdev->ud, "stub_rx");
+		sdev->ud.tcp_tx = kthread_run(stub_tx_loop, &sdev->ud, "stub_tx");
 
 		spin_lock(&sdev->ud.lock);
 		sdev->ud.status = SDEV_ST_USED;
@@ -218,7 +220,8 @@ static void stub_shutdown_connection(struct usbip_device *ud)
 	}
 
 	/* 1. stop threads */
-	usbip_stop_threads(ud);
+	kthread_stop(ud->tcp_rx);
+	kthread_stop(ud->tcp_tx);
 
 	/* 2. close the socket */
 	/*
@@ -336,9 +339,6 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev,
 	 */
 	sdev->devid     = (busnum << 16) | devnum;
 
-	usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop);
-	usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop);
-
 	sdev->ud.side = USBIP_STUB;
 	sdev->ud.status = SDEV_ST_AVAILABLE;
 	/* sdev->ud.lock = SPIN_LOCK_UNLOCKED; */
@@ -543,7 +543,7 @@ static void stub_disconnect(struct usb_interface *interface)
 	stub_remove_files(&interface->dev);
 
 	/*If usb reset called from event handler*/
-	if (busid_priv->sdev->ud.eh.thread == current) {
+	if (busid_priv->sdev->ud.eh == current) {
 		busid_priv->interf_count--;
 		return;
 	}
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
index f3a4096..076a7e5 100644
--- a/drivers/staging/usbip/stub_main.c
+++ b/drivers/staging/usbip/stub_main.c
@@ -264,11 +264,9 @@ void stub_device_cleanup_urbs(struct stub_device *sdev)
 
 		kmem_cache_free(stub_priv_cache, priv);
 
-		if (urb->transfer_buffer != NULL)
-			kfree(urb->transfer_buffer);
+		kfree(urb->transfer_buffer);
 
-		if (urb->setup_packet != NULL)
-			kfree(urb->setup_packet);
+		kfree(urb->setup_packet);
 
 		usb_free_urb(urb);
 	}
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
index ae6ac82..6445f12 100644
--- a/drivers/staging/usbip/stub_rx.c
+++ b/drivers/staging/usbip/stub_rx.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "stub.h"
@@ -616,19 +617,15 @@ static void stub_rx_pdu(struct usbip_device *ud)
 
 }
 
-void stub_rx_loop(struct usbip_task *ut)
+int stub_rx_loop(void *data)
 {
-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
-
-	while (1) {
-		if (signal_pending(current)) {
-			usbip_dbg_stub_rx("signal caught!\n");
-			break;
-		}
+	struct usbip_device *ud = data;
 
+	while (!kthread_should_stop()) {
 		if (usbip_event_happened(ud))
 			break;
 
 		stub_rx_pdu(ud);
 	}
+	return 0;
 }
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
index d7136e2..5523f25 100644
--- a/drivers/staging/usbip/stub_tx.c
+++ b/drivers/staging/usbip/stub_tx.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "stub.h"
@@ -333,17 +334,12 @@ static int stub_send_ret_unlink(struct stub_device *sdev)
 
 /*-------------------------------------------------------------------------*/
 
-void stub_tx_loop(struct usbip_task *ut)
+int stub_tx_loop(void *data)
 {
-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
+	struct usbip_device *ud = data;
 	struct stub_device *sdev = container_of(ud, struct stub_device, ud);
 
-	while (1) {
-		if (signal_pending(current)) {
-			usbip_dbg_stub_tx("signal catched\n");
-			break;
-		}
-
+	while (!kthread_should_stop()) {
 		if (usbip_event_happened(ud))
 			break;
 
@@ -369,6 +365,9 @@ void stub_tx_loop(struct usbip_task *ut)
 
 		wait_event_interruptible(sdev->tx_waitq,
 				(!list_empty(&sdev->priv_tx) ||
-				 !list_empty(&sdev->unlink_tx)));
+				 !list_empty(&sdev->unlink_tx) ||
+				 kthread_should_stop()));
 	}
+
+	return 0;
 }
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index 210ef16..337abc4 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -18,7 +18,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/smp_lock.h>
 #include <linux/file.h>
 #include <linux/tcp.h>
 #include <linux/in.h>
@@ -349,110 +348,6 @@ void usbip_dump_header(struct usbip_header *pdu)
 }
 EXPORT_SYMBOL_GPL(usbip_dump_header);
 
-
-/*-------------------------------------------------------------------------*/
-/* thread routines */
-
-int usbip_thread(void *param)
-{
-	struct usbip_task *ut = param;
-
-	if (!ut)
-		return -EINVAL;
-
-	lock_kernel();
-	daemonize(ut->name);
-	allow_signal(SIGKILL);
-	ut->thread = current;
-	unlock_kernel();
-
-	/* srv.rb must wait for rx_thread starting */
-	complete(&ut->thread_done);
-
-	/* start of while loop */
-	ut->loop_ops(ut);
-
-	/* end of loop */
-	ut->thread = NULL;
-
-	complete_and_exit(&ut->thread_done, 0);
-}
-
-static void stop_rx_thread(struct usbip_device *ud)
-{
-	if (ud->tcp_rx.thread != NULL) {
-		send_sig(SIGKILL, ud->tcp_rx.thread, 1);
-		wait_for_completion(&ud->tcp_rx.thread_done);
-		usbip_udbg("rx_thread for ud %p has finished\n", ud);
-	}
-}
-
-static void stop_tx_thread(struct usbip_device *ud)
-{
-	if (ud->tcp_tx.thread != NULL) {
-		send_sig(SIGKILL, ud->tcp_tx.thread, 1);
-		wait_for_completion(&ud->tcp_tx.thread_done);
-		usbip_udbg("tx_thread for ud %p has finished\n", ud);
-	}
-}
-
-int usbip_start_threads(struct usbip_device *ud)
-{
-	/*
-	 * threads are invoked per one device (per one connection).
-	 */
-	struct task_struct *th;
-	int err = 0;
-
-	th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
-	if (IS_ERR(th)) {
-		printk(KERN_WARNING
-			"Unable to start control thread\n");
-		err = PTR_ERR(th);
-		goto ust_exit;
-	}
-
-	th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
-	if (IS_ERR(th)) {
-		printk(KERN_WARNING
-			"Unable to start control thread\n");
-		err = PTR_ERR(th);
-		goto tx_thread_err;
-	}
-
-	/* confirm threads are starting */
-	wait_for_completion(&ud->tcp_rx.thread_done);
-	wait_for_completion(&ud->tcp_tx.thread_done);
-
-	return 0;
-
-tx_thread_err:
-	stop_rx_thread(ud);
-
-ust_exit:
-	return err;
-}
-EXPORT_SYMBOL_GPL(usbip_start_threads);
-
-void usbip_stop_threads(struct usbip_device *ud)
-{
-	/* kill threads related to this sdev, if v.c. exists */
-	stop_rx_thread(ud);
-	stop_tx_thread(ud);
-}
-EXPORT_SYMBOL_GPL(usbip_stop_threads);
-
-void usbip_task_init(struct usbip_task *ut, char *name,
-		void (*loop_ops)(struct usbip_task *))
-{
-	ut->thread = NULL;
-	init_completion(&ut->thread_done);
-	ut->name = name;
-	ut->loop_ops = loop_ops;
-}
-EXPORT_SYMBOL_GPL(usbip_task_init);
-
-
 /*-------------------------------------------------------------------------*/
 /* socket routines */
 
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index d280e23..9f809c3 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -307,13 +307,6 @@ void usbip_dump_header(struct usbip_header *pdu);
 
 struct usbip_device;
 
-struct usbip_task {
-	struct task_struct *thread;
-	struct completion thread_done;
-	char *name;
-	void (*loop_ops)(struct usbip_task *);
-};
-
 enum usbip_side {
 	USBIP_VHCI,
 	USBIP_STUB,
@@ -346,8 +339,8 @@ struct usbip_device {
 
 	struct socket *tcp_socket;
 
-	struct usbip_task tcp_rx;
-	struct usbip_task tcp_tx;
+	struct task_struct *tcp_rx;
+	struct task_struct *tcp_tx;
 
 	/* event handler */
 #define USBIP_EH_SHUTDOWN	(1 << 0)
@@ -367,7 +360,7 @@ struct usbip_device {
 #define	VDEV_EVENT_ERROR_MALLOC	(USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
 
 	unsigned long event;
-	struct usbip_task eh;
+	struct task_struct *eh;
 	wait_queue_head_t eh_waitq;
 
 	struct eh_ops {
@@ -378,13 +371,6 @@ struct usbip_device {
 };
 
 
-void usbip_task_init(struct usbip_task *ut, char *,
-				void (*loop_ops)(struct usbip_task *));
-
-int usbip_start_threads(struct usbip_device *ud);
-void usbip_stop_threads(struct usbip_device *ud);
-int usbip_thread(void *param);
-
 void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
 								int pack);
 
diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c
index af3832b..f4b287e 100644
--- a/drivers/staging/usbip/usbip_event.c
+++ b/drivers/staging/usbip/usbip_event.c
@@ -62,55 +62,43 @@ static int event_handler(struct usbip_device *ud)
 	return 0;
 }
 
-static void event_handler_loop(struct usbip_task *ut)
+static int event_handler_loop(void *data)
 {
-	struct usbip_device *ud = container_of(ut, struct usbip_device, eh);
+	struct usbip_device *ud = data;
 
-	while (1) {
-		if (signal_pending(current)) {
-			usbip_dbg_eh("signal catched!\n");
-			break;
-		}
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(ud->eh_waitq,
+					usbip_event_happened(ud) ||
+					kthread_should_stop());
+		usbip_dbg_eh("wakeup\n");
 
 		if (event_handler(ud) < 0)
 			break;
-
-		wait_event_interruptible(ud->eh_waitq,
-					usbip_event_happened(ud));
-		usbip_dbg_eh("wakeup\n");
 	}
+	return 0;
 }
 
 int usbip_start_eh(struct usbip_device *ud)
 {
-	struct usbip_task *eh = &ud->eh;
-	struct task_struct *th;
-
 	init_waitqueue_head(&ud->eh_waitq);
 	ud->event = 0;
 
-	usbip_task_init(eh, "usbip_eh", event_handler_loop);
-
-	th = kthread_run(usbip_thread, (void *)eh, "usbip");
-	if (IS_ERR(th)) {
+	ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
+	if (IS_ERR(ud->eh)) {
 		printk(KERN_WARNING
 			"Unable to start control thread\n");
-		return PTR_ERR(th);
+		return PTR_ERR(ud->eh);
 	}
-
-	wait_for_completion(&eh->thread_done);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(usbip_start_eh);
 
 void usbip_stop_eh(struct usbip_device *ud)
 {
-	struct usbip_task *eh = &ud->eh;
-
-	if (eh->thread == current)
+	if (ud->eh == current)
 		return; /* do not wait for myself */
 
-	wait_for_completion(&eh->thread_done);
+	kthread_stop(ud->eh);
 	usbip_dbg_eh("usbip_eh has finished\n");
 }
 EXPORT_SYMBOL_GPL(usbip_stop_eh);
diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
index afc3b1a..d3f1e5f 100644
--- a/drivers/staging/usbip/vhci.h
+++ b/drivers/staging/usbip/vhci.h
@@ -113,8 +113,8 @@ extern struct attribute_group dev_attr_group;
 /* vhci_hcd.c */
 void rh_port_connect(int rhport, enum usb_device_speed speed);
 void rh_port_disconnect(int rhport);
-void vhci_rx_loop(struct usbip_task *ut);
-void vhci_tx_loop(struct usbip_task *ut);
+int vhci_rx_loop(void *data);
+int vhci_tx_loop(void *data);
 
 struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev,
 					    __u32 seqnum);
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
index a35fe61..e234849 100644
--- a/drivers/staging/usbip/vhci_hcd.c
+++ b/drivers/staging/usbip/vhci_hcd.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "vhci.h"
@@ -255,8 +256,8 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
 	desc->wHubCharacteristics = (__force __u16)
 		(__constant_cpu_to_le16(0x0001));
 	desc->bNbrPorts = VHCI_NPORTS;
-	desc->bitmap[0] = 0xff;
-	desc->bitmap[1] = 0xff;
+	desc->u.hs.DeviceRemovable[0] = 0xff;
+	desc->u.hs.DeviceRemovable[1] = 0xff;
 }
 
 static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
@@ -874,7 +875,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
 		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
 	}
 
-	usbip_stop_threads(&vdev->ud);
+	/* kill threads related to this sdev, if v.c. exists */
+	kthread_stop(vdev->ud.tcp_rx);
+	kthread_stop(vdev->ud.tcp_tx);
+
 	usbip_uinfo("stop threads\n");
 
 	/* active connection is closed */
@@ -945,8 +949,8 @@ static void vhci_device_init(struct vhci_device *vdev)
 {
 	memset(vdev, 0, sizeof(*vdev));
 
-	usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop);
-	usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop);
+	vdev->ud.tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
+	vdev->ud.tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
 
 	vdev->ud.side   = USBIP_VHCI;
 	vdev->ud.status = VDEV_ST_NULL;
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
index bf69914..09bf235 100644
--- a/drivers/staging/usbip/vhci_rx.c
+++ b/drivers/staging/usbip/vhci_rx.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "vhci.h"
@@ -269,22 +270,17 @@ static void vhci_rx_pdu(struct usbip_device *ud)
 
 /*-------------------------------------------------------------------------*/
 
-void vhci_rx_loop(struct usbip_task *ut)
+int vhci_rx_loop(void *data)
 {
-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
-
-
-	while (1) {
-		if (signal_pending(current)) {
-			usbip_dbg_vhci_rx("signal catched!\n");
-			break;
-		}
+	struct usbip_device *ud = data;
 
 
+	while (!kthread_should_stop()) {
 		if (usbip_event_happened(ud))
 			break;
 
 		vhci_rx_pdu(ud);
 	}
-}
 
+	return 0;
+}
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
index f6e34e0..3f2459f 100644
--- a/drivers/staging/usbip/vhci_sysfs.c
+++ b/drivers/staging/usbip/vhci_sysfs.c
@@ -220,16 +220,13 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
 	vdev->ud.tcp_socket = socket;
 	vdev->ud.status     = VDEV_ST_NOTASSIGNED;
 
+	wake_up_process(vdev->ud.tcp_rx);
+	wake_up_process(vdev->ud.tcp_tx);
+
 	spin_unlock(&vdev->ud.lock);
 	spin_unlock(&the_controller->lock);
 	/* end the lock */
 
-	/*
-	 * this function will sleep, so should be out of the lock. but, it's ok
-	 * because we already marked vdev as being used. really?
-	 */
-	usbip_start_threads(&vdev->ud);
-
 	rh_port_connect(rhport, speed);
 
 	return count;
diff --git a/drivers/staging/usbip/vhci_tx.c b/drivers/staging/usbip/vhci_tx.c
index e1c1f71..d9ab49d 100644
--- a/drivers/staging/usbip/vhci_tx.c
+++ b/drivers/staging/usbip/vhci_tx.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/kthread.h>
 
 #include "usbip_common.h"
 #include "vhci.h"
@@ -215,17 +216,12 @@ static int vhci_send_cmd_unlink(struct vhci_device *vdev)
 
 /*-------------------------------------------------------------------------*/
 
-void vhci_tx_loop(struct usbip_task *ut)
+int vhci_tx_loop(void *data)
 {
-	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
+	struct usbip_device *ud = data;
 	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
 
-	while (1) {
-		if (signal_pending(current)) {
-			usbip_uinfo("vhci_tx signal catched\n");
-			break;
-		}
-
+	while (!kthread_should_stop()) {
 		if (vhci_send_cmd_submit(vdev) < 0)
 			break;
 
@@ -234,8 +230,11 @@ void vhci_tx_loop(struct usbip_task *ut)
 
 		wait_event_interruptible(vdev->waitq_tx,
 				(!list_empty(&vdev->priv_tx) ||
-				 !list_empty(&vdev->unlink_tx)));
+				 !list_empty(&vdev->unlink_tx) ||
+				 kthread_should_stop()));
 
 		usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
 	}
+
+	return 0;
 }
diff --git a/drivers/staging/usbvideo/usbvideo.c b/drivers/staging/usbvideo/usbvideo.c
index f1fcf97..cd4c73a 100644
--- a/drivers/staging/usbvideo/usbvideo.c
+++ b/drivers/staging/usbvideo/usbvideo.c
@@ -24,7 +24,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 
-#include <asm/io.h>
+#include <linux/io.h>
 
 #include "usbvideo.h"
 
@@ -112,9 +112,9 @@ static void RingQueue_Allocate(struct RingQueue *rq, int rqLen)
 	assert(rq != NULL);
 	assert(rqLen > 0);
 
-	while(rqLen >> i)
+	while (rqLen >> i)
 		i++;
-	if(rqLen != 1 << (i-1))
+	if (rqLen != 1 << (i-1))
 		rqLen = 1 << i;
 
 	rq->length = rqLen;
@@ -148,15 +148,15 @@ int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len)
 	assert(dst != NULL);
 
 	rql = RingQueue_GetLength(rq);
-	if(!rql)
+	if (!rql)
 		return 0;
 
 	/* Clip requested length to available data */
-	if(len > rql)
+	if (len > rql)
 		len = rql;
 
 	toread = len;
-	if(rq->ri > rq->wi) {
+	if (rq->ri > rq->wi) {
 		/* Read data from tail */
 		int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri;
 		memcpy(dst, rq->queue + rq->ri, read);
@@ -164,7 +164,7 @@ int RingQueue_Dequeue(struct RingQueue *rq, unsigned char *dst, int len)
 		dst += read;
 		rq->ri = (rq->ri + read) & (rq->length-1);
 	}
-	if(toread) {
+	if (toread) {
 		/* Read data from head */
 		memcpy(dst, rq->queue + rq->ri, toread);
 		rq->ri = (rq->ri + toread) & (rq->length-1);
@@ -292,12 +292,11 @@ static void usbvideo_OverlayChar(struct uvd *uvd, struct usbvideo_frame *frame,
 		return;
 	digit = digits[value];
 
-	for (iy=0; iy < 5; iy++) {
-		for (ix=0; ix < 3; ix++) {
+	for (iy = 0; iy < 5; iy++) {
+		for (ix = 0; ix < 3; ix++) {
 			if (digit & 0x8000) {
-				if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24)) {
+				if (uvd->paletteBits & (1L << VIDEO_PALETTE_RGB24))
 /* TODO */				RGB24_PUTPIXEL(frame, x+ix, y+iy, 0xFF, 0xFF, 0xFF);
-				}
 			}
 			digit = digit << 1;
 		}
@@ -332,7 +331,7 @@ static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame)
 {
 	const int y_diff = 8;
 	char tmp[16];
-	int x = 10, y=10;
+	int x = 10, y = 10;
 	long i, j, barLength;
 	const int qi_x1 = 60, qi_y1 = 10;
 	const int qi_x2 = VIDEOSIZE_X(frame->request) - 10, qi_h = 10;
@@ -375,8 +374,8 @@ static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame)
 		m_lo = (u_lo > 0) ? (qi_x1 + ((barLength * u_lo) / uvd->dp.length)) : -1;
 		m_hi = qi_x1 + ((barLength * u_hi) / uvd->dp.length);
 
-		for (j=qi_y1; j < (qi_y1 + qi_h); j++) {
-			for (i=qi_x1; i < qi_x2; i++) {
+		for (j = qi_y1; j < (qi_y1 + qi_h); j++) {
+			for (i = qi_x1; i < qi_x2; i++) {
 				/* Draw border lines */
 				if ((j == qi_y1) || (j == (qi_y1 + qi_h - 1)) ||
 				    (i == qi_x1) || (i == (qi_x2 - 1))) {
@@ -384,11 +383,11 @@ static void usbvideo_OverlayStats(struct uvd *uvd, struct usbvideo_frame *frame)
 					continue;
 				}
 				/* For all other points the Y coordinate does not matter */
-				if ((i >= m_ri) && (i <= (m_ri + 3))) {
+				if ((i >= m_ri) && (i <= (m_ri + 3)))
 					RGB24_PUTPIXEL(frame, i, j, 0x00, 0xFF, 0x00);
-				} else if ((i >= m_wi) && (i <= (m_wi + 3))) {
+				else if ((i >= m_wi) && (i <= (m_wi + 3)))
 					RGB24_PUTPIXEL(frame, i, j, 0xFF, 0x00, 0x00);
-				} else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
+				else if ((i < m_lo) || ((i > m_ri) && (i < m_hi)))
 					RGB24_PUTPIXEL(frame, i, j, 0x00, 0x00, 0xFF);
 			}
 		}
@@ -551,8 +550,8 @@ void usbvideo_TestPattern(struct uvd *uvd, int fullframe, int pmode)
 		int i;
 		unsigned char *f = frame->data +
 			(VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL * frame->curline);
-		for (i=0; i < VIDEOSIZE_X(frame->request); i++) {
-			unsigned char cb=0x80;
+		for (i = 0; i < VIDEOSIZE_X(frame->request); i++) {
+			unsigned char cb = 0x80;
 			unsigned char cg = 0;
 			unsigned char cr = 0;
 
@@ -605,10 +604,10 @@ void usbvideo_HexDump(const unsigned char *data, int len)
 	char tmp[128]; /* 32*3 + 5 */
 	int i, k;
 
-	for (i=k=0; len > 0; i++, len--) {
+	for (i = k = 0; len > 0; i++, len--) {
 		if (i > 0 && ((i % bytes_per_line) == 0)) {
 			printk("%s\n", tmp);
-			k=0;
+			k = 0;
 		}
 		if ((i % bytes_per_line) == 0)
 			k += sprintf(&tmp[k], "%04x: ", i);
@@ -787,7 +786,7 @@ void usbvideo_Deregister(struct usbvideo **pCams)
 	usb_deregister(&cams->usbdrv);
 
 	dbg("%s: Deallocating cams=$%p (%d. cameras)", __func__, cams, cams->num_cameras);
-	for (i=0; i < cams->num_cameras; i++) {
+	for (i = 0; i < cams->num_cameras; i++) {
 		struct uvd *up = &cams->cam[i];
 		int warning = 0;
 
@@ -840,7 +839,7 @@ EXPORT_SYMBOL(usbvideo_Deregister);
  */
 static void usbvideo_Disconnect(struct usb_interface *intf)
 {
-	struct uvd *uvd = usb_get_intfdata (intf);
+	struct uvd *uvd = usb_get_intfdata(intf);
 	int i;
 
 	if (uvd == NULL) {
@@ -848,7 +847,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 		return;
 	}
 
-	usb_set_intfdata (intf, NULL);
+	usb_set_intfdata(intf, NULL);
 
 	usbvideo_ClientIncModCount(uvd);
 	if (uvd->debug > 0)
@@ -860,11 +859,11 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
 	/* At this time we ask to cancel outstanding URBs */
 	GET_CALLBACK(uvd, stopDataPump)(uvd);
 
-	for (i=0; i < USBVIDEO_NUMSBUF; i++)
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++)
 		usb_free_urb(uvd->sbuf[i].urb);
 
 	usb_put_dev(uvd->dev);
-	uvd->dev = NULL;    	    /* USB device is no more */
+	uvd->dev = NULL;	    /* USB device is no more */
 
 	video_unregister_device(&uvd->vdev);
 	if (uvd->debug > 0)
@@ -925,8 +924,7 @@ static int usbvideo_find_struct(struct usbvideo *cams)
 	mutex_lock(&cams->lock);
 	for (u = 0; u < cams->num_cameras; u++) {
 		struct uvd *uvd = &cams->cam[u];
-		if (!uvd->uvd_used) /* This one is free */
-		{
+		if (!uvd->uvd_used) { /* This one is free */
 			uvd->uvd_used = 1;	/* In use now */
 			mutex_init(&uvd->lock);	/* to 1 == available */
 			uvd->dev = NULL;
@@ -941,10 +939,10 @@ static int usbvideo_find_struct(struct usbvideo *cams)
 static const struct v4l2_file_operations usbvideo_fops = {
 	.owner =  THIS_MODULE,
 	.open =   usbvideo_v4l_open,
-	.release =usbvideo_v4l_close,
-	.read =   usbvideo_v4l_read,
-	.mmap =   usbvideo_v4l_mmap,
-	.ioctl =  usbvideo_v4l_ioctl,
+	.release = usbvideo_v4l_close,
+	.read =    usbvideo_v4l_read,
+	.mmap =    usbvideo_v4l_mmap,
+	.ioctl =   usbvideo_v4l_ioctl,
 };
 static const struct video_device usbvideo_template = {
 	.fops =       &usbvideo_fops,
@@ -972,7 +970,7 @@ struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams)
 	usbvideo_ClientIncModCount(uvd);
 
 	mutex_lock(&uvd->lock);
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 		uvd->sbuf[i].urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
 		if (uvd->sbuf[i].urb == NULL) {
 			err("usb_alloc_urb(%d.) failed.", FRAMES_PER_DESC);
@@ -981,7 +979,7 @@ struct uvd *usbvideo_AllocateDevice(struct usbvideo *cams)
 			goto allocate_done;
 		}
 	}
-	uvd->user=0;
+	uvd->user = 0;
 	uvd->remove_pending = 0;
 	uvd->last_error = 0;
 	RingQueue_Initialize(&uvd->dp);
@@ -1127,7 +1125,7 @@ static int usbvideo_v4l_open(struct file *file)
 		memset(&uvd->stats, 0, sizeof(uvd->stats));
 
 		/* Clean pointers so we know if we allocated something */
-		for (i=0; i < USBVIDEO_NUMSBUF; i++)
+		for (i = 0; i < USBVIDEO_NUMSBUF; i++)
 			uvd->sbuf[i].data = NULL;
 
 		/* Allocate memory for the frame buffers */
@@ -1140,7 +1138,7 @@ static int usbvideo_v4l_open(struct file *file)
 			errCode = -ENOMEM;
 		} else {
 			/* Allocate all buffers */
-			for (i=0; i < USBVIDEO_NUMFRAMES; i++) {
+			for (i = 0; i < USBVIDEO_NUMFRAMES; i++) {
 				uvd->frame[i].frameState = FrameState_Unused;
 				uvd->frame[i].data = uvd->fbuf + i*(uvd->max_frame_size);
 				/*
@@ -1150,7 +1148,7 @@ static int usbvideo_v4l_open(struct file *file)
 				uvd->frame[i].canvas = uvd->canvas;
 				uvd->frame[i].seqRead_Index = 0;
 			}
-			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+			for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 				uvd->sbuf[i].data = kmalloc(sb_size, GFP_KERNEL);
 				if (uvd->sbuf[i].data == NULL) {
 					errCode = -ENOMEM;
@@ -1165,7 +1163,7 @@ static int usbvideo_v4l_open(struct file *file)
 				uvd->fbuf = NULL;
 			}
 			RingQueue_Free(&uvd->dp);
-			for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+			for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 				kfree(uvd->sbuf[i].data);
 				uvd->sbuf[i].data = NULL;
 			}
@@ -1240,7 +1238,7 @@ static int usbvideo_v4l_close(struct file *file)
 	uvd->fbuf = NULL;
 	RingQueue_Free(&uvd->dp);
 
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 		kfree(uvd->sbuf[i].data);
 		uvd->sbuf[i].data = NULL;
 	}
@@ -1281,32 +1279,32 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 		return -EIO;
 
 	switch (cmd) {
-		case VIDIOCGCAP:
+	case VIDIOCGCAP:
 		{
 			struct video_capability *b = arg;
 			*b = uvd->vcap;
 			return 0;
 		}
-		case VIDIOCGCHAN:
+	case VIDIOCGCHAN:
 		{
 			struct video_channel *v = arg;
 			*v = uvd->vchan;
 			return 0;
 		}
-		case VIDIOCSCHAN:
+	case VIDIOCSCHAN:
 		{
 			struct video_channel *v = arg;
 			if (v->channel != 0)
 				return -EINVAL;
 			return 0;
 		}
-		case VIDIOCGPICT:
+	case VIDIOCGPICT:
 		{
 			struct video_picture *pic = arg;
 			*pic = uvd->vpic;
 			return 0;
 		}
-		case VIDIOCSPICT:
+	case VIDIOCSPICT:
 		{
 			struct video_picture *pic = arg;
 			/*
@@ -1321,13 +1319,12 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 			uvd->settingsAdjusted = 0;	/* Will force new settings */
 			return 0;
 		}
-		case VIDIOCSWIN:
+	case VIDIOCSWIN:
 		{
 			struct video_window *vw = arg;
 
-			if(VALID_CALLBACK(uvd, setVideoMode)) {
+			if (VALID_CALLBACK(uvd, setVideoMode))
 				return GET_CALLBACK(uvd, setVideoMode)(uvd, vw);
-			}
 
 			if (vw->flags)
 				return -EINVAL;
@@ -1340,7 +1337,7 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 
 			return 0;
 		}
-		case VIDIOCGWIN:
+	case VIDIOCGWIN:
 		{
 			struct video_window *vw = arg;
 
@@ -1355,7 +1352,7 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 				vw->flags = 10; /* FIXME: do better! */
 			return 0;
 		}
-		case VIDIOCGMBUF:
+	case VIDIOCGMBUF:
 		{
 			struct video_mbuf *vm = arg;
 			int i;
@@ -1363,12 +1360,12 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 			memset(vm, 0, sizeof(*vm));
 			vm->size = uvd->max_frame_size * USBVIDEO_NUMFRAMES;
 			vm->frames = USBVIDEO_NUMFRAMES;
-			for(i = 0; i < USBVIDEO_NUMFRAMES; i++)
-			  vm->offsets[i] = i * uvd->max_frame_size;
+			for (i = 0; i < USBVIDEO_NUMFRAMES; i++)
+				vm->offsets[i] = i * uvd->max_frame_size;
 
 			return 0;
 		}
-		case VIDIOCMCAPTURE:
+	case VIDIOCMCAPTURE:
 		{
 			struct video_mmap *vm = arg;
 
@@ -1429,7 +1426,7 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 
 			return usbvideo_NewFrame(uvd, vm->frame);
 		}
-		case VIDIOCSYNC:
+	case VIDIOCSYNC:
 		{
 			int *frameNum = arg;
 			int ret;
@@ -1445,9 +1442,8 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 				ret = usbvideo_GetFrame(uvd, *frameNum);
 			else if (VALID_CALLBACK(uvd, getFrame)) {
 				ret = GET_CALLBACK(uvd, getFrame)(uvd, *frameNum);
-				if ((ret < 0) && (uvd->debug >= 1)) {
+				if ((ret < 0) && (uvd->debug >= 1))
 					err("VIDIOCSYNC: getFrame() returned %d.", ret);
-				}
 			} else {
 				err("VIDIOCSYNC: getFrame is not set");
 				ret = -EFAULT;
@@ -1462,33 +1458,33 @@ static long usbvideo_v4l_do_ioctl(struct file *file, unsigned int cmd, void *arg
 			uvd->frame[*frameNum].frameState = FrameState_Unused;
 			return ret;
 		}
-		case VIDIOCGFBUF:
+	case VIDIOCGFBUF:
 		{
 			struct video_buffer *vb = arg;
 
 			memset(vb, 0, sizeof(*vb));
 			return 0;
 		}
-		case VIDIOCKEY:
-			return 0;
+	case VIDIOCKEY:
+		return 0;
 
-		case VIDIOCCAPTURE:
-			return -EINVAL;
+	case VIDIOCCAPTURE:
+		return -EINVAL;
 
-		case VIDIOCSFBUF:
+	case VIDIOCSFBUF:
 
-		case VIDIOCGTUNER:
-		case VIDIOCSTUNER:
+	case VIDIOCGTUNER:
+	case VIDIOCSTUNER:
 
-		case VIDIOCGFREQ:
-		case VIDIOCSFREQ:
+	case VIDIOCGFREQ:
+	case VIDIOCSFREQ:
 
-		case VIDIOCGAUDIO:
-		case VIDIOCSAUDIO:
-			return -EINVAL;
+	case VIDIOCGAUDIO:
+	case VIDIOCSAUDIO:
+		return -EINVAL;
 
-		default:
-			return -ENOIOCTLCMD;
+	default:
+		return -ENOIOCTLCMD;
 	}
 	return 0;
 }
@@ -1529,7 +1525,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
 	mutex_lock(&uvd->lock);
 
 	/* See if a frame is completed, then use it. */
-	for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
+	for (i = 0; i < USBVIDEO_NUMFRAMES; i++) {
 		if ((uvd->frame[i].frameState == FrameState_Done) ||
 		    (uvd->frame[i].frameState == FrameState_Done_Hold) ||
 		    (uvd->frame[i].frameState == FrameState_Error)) {
@@ -1550,7 +1546,7 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
 	 * We will need to wait until it becomes cooked, of course.
 	 */
 	if (frmx == -1) {
-		for(i = 0; i < USBVIDEO_NUMFRAMES; i++) {
+		for (i = 0; i < USBVIDEO_NUMFRAMES; i++) {
 			if (uvd->frame[i].frameState == FrameState_Grabbing) {
 				frmx = i;
 				break;
@@ -1653,9 +1649,8 @@ static ssize_t usbvideo_v4l_read(struct file *file, char __user *buf,
 
 		/* Mark it as available to be used again. */
 		uvd->frame[frmx].frameState = FrameState_Unused;
-		if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES)) {
+		if (usbvideo_NewFrame(uvd, (frmx + 1) % USBVIDEO_NUMFRAMES))
 			err("%s: usbvideo_NewFrame failed.", __func__);
-		}
 	}
 read_done:
 	mutex_unlock(&uvd->lock);
@@ -1744,8 +1739,8 @@ urb_done_with:
 	}
 	urb->status = 0;
 	urb->dev = uvd->dev;
-	ret = usb_submit_urb (urb, GFP_KERNEL);
-	if(ret)
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret)
 		err("usb_submit_urb error (%d)", ret);
 	return;
 }
@@ -1785,7 +1780,7 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
 		err("%s: videoStart not set", __func__);
 
 	/* We double buffer the Iso lists */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 		int j, k;
 		struct urb *urb = uvd->sbuf[i].urb;
 		urb->dev = dev;
@@ -1797,14 +1792,14 @@ static int usbvideo_StartDataPump(struct uvd *uvd)
 		urb->complete = usbvideo_IsocIrq;
 		urb->number_of_packets = FRAMES_PER_DESC;
 		urb->transfer_buffer_length = uvd->iso_packet_len * FRAMES_PER_DESC;
-		for (j=k=0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
+		for (j = k = 0; j < FRAMES_PER_DESC; j++, k += uvd->iso_packet_len) {
 			urb->iso_frame_desc[j].offset = k;
 			urb->iso_frame_desc[j].length = uvd->iso_packet_len;
 		}
 	}
 
 	/* Submit all URBs */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++) {
 		errFlag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
 		if (errFlag)
 			err("%s: usb_submit_isoc(%d) ret %d", __func__, i, errFlag);
@@ -1839,9 +1834,8 @@ static void usbvideo_StopDataPump(struct uvd *uvd)
 		dev_info(&uvd->dev->dev, "%s($%p)\n", __func__, uvd);
 
 	/* Unschedule all of the iso td's */
-	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+	for (i = 0; i < USBVIDEO_NUMSBUF; i++)
 		usb_kill_urb(uvd->sbuf[i].urb);
-	}
 	if (uvd->debug > 1)
 		dev_info(&uvd->dev->dev, "%s: streaming=0\n", __func__);
 	uvd->streaming = 0;
@@ -1995,7 +1989,7 @@ static int usbvideo_GetFrame(struct uvd *uvd, int frameNum)
 	case FrameState_Error:
 	{
 		int ntries, signalPending;
-	redo:
+redo:
 		if (!CAMERA_IS_OPERATIONAL(uvd)) {
 			if (uvd->debug >= 2)
 				dev_info(&uvd->dev->dev,
@@ -2133,8 +2127,7 @@ void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame)
 		return;
 
 	if ((frame->deinterlace == Deinterlace_FillEvenLines) ||
-	    (frame->deinterlace == Deinterlace_FillOddLines))
-	{
+	    (frame->deinterlace == Deinterlace_FillOddLines)) {
 		const int v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
 		int i = (frame->deinterlace == Deinterlace_FillEvenLines) ? 0 : 1;
 
@@ -2160,8 +2153,7 @@ void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame)
 			/* Sanity check */
 			if ((ip < 0) || (in < 0) ||
 			    (ip >= VIDEOSIZE_Y(frame->request)) ||
-			    (in >= VIDEOSIZE_Y(frame->request)))
-			{
+			    (in >= VIDEOSIZE_Y(frame->request))) {
 				err("Error: ip=%d. in=%d. req.height=%ld.",
 				    ip, in, VIDEOSIZE_Y(frame->request));
 				break;
@@ -2173,7 +2165,7 @@ void usbvideo_DeinterlaceFrame(struct uvd *uvd, struct usbvideo_frame *frame)
 			fd = frame->data + (v4l_linesize * i);
 
 			/* Average lines around destination */
-			for (j=0; j < v4l_linesize; j++) {
+			for (j = 0; j < v4l_linesize; j++) {
 				fd[j] = (unsigned char)((((unsigned) fs1[j]) +
 							 ((unsigned)fs2[j])) >> 1);
 			}
@@ -2215,9 +2207,9 @@ static void usbvideo_SoftwareContrastAdjustment(struct uvd *uvd,
 		return;
 	}
 	v4l_linesize = VIDEOSIZE_X(frame->request) * V4L_BYTES_PER_PIXEL;
-	for (i=0; i < VIDEOSIZE_Y(frame->request); i++) {
+	for (i = 0; i < VIDEOSIZE_Y(frame->request); i++) {
 		unsigned char *fd = frame->data + (v4l_linesize * i);
-		for (j=0; j < v4l_linesize; j++) {
+		for (j = 0; j < v4l_linesize; j++) {
 			signed long v = (signed long) fd[j];
 			/* Magnify up to 2 times, reduce down to zero */
 			v = 128 + ((ccm + adj) * (v - 128)) / ccm;
diff --git a/drivers/staging/usbvideo/vicam.c b/drivers/staging/usbvideo/vicam.c
index ecdb121..38a373a 100644
--- a/drivers/staging/usbvideo/vicam.c
+++ b/drivers/staging/usbvideo/vicam.c
@@ -48,13 +48,13 @@
 #include <linux/ihex.h>
 #include "usbvideo.h"
 
-// #define VICAM_DEBUG
+/* #define VICAM_DEBUG */
 
 #ifdef VICAM_DEBUG
-#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
-#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
+#define ADBG(lineno, fmt, args...) printk(fmt, jiffies, __func__, lineno, ##args)
+#define DBG(fmt, args...) ADBG((__LINE__), KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt, ##args)
 #else
-#define DBG(fmn,args...) do {} while(0)
+#define DBG(fmn, args...) do {} while (0)
 #endif
 
 #define DRIVER_AUTHOR           "Joe Burks, jburks@wavicle.org"
@@ -118,15 +118,15 @@ static void rvfree(void *mem, unsigned long size)
 }
 
 struct vicam_camera {
-	u16 shutter_speed;	// capture shutter speed
-	u16 gain;		// capture gain
+	u16 shutter_speed;	/* capture shutter speed */
+	u16 gain;		/* capture gain */
 
-	u8 *raw_image;		// raw data captured from the camera
-	u8 *framebuf;		// processed data in RGB24 format
-	u8 *cntrlbuf;		// area used to send control msgs
+	u8 *raw_image;		/* raw data captured from the camera */
+	u8 *framebuf;		/* processed data in RGB24 format */
+	u8 *cntrlbuf;		/* area used to send control msgs */
 
-	struct video_device vdev;	// v4l video device
-	struct usb_device *udev;	// usb device
+	struct video_device vdev;	/* v4l video device */
+	struct usb_device *udev;	/* usb device */
 
 	/* guard against simultaneous accesses to the camera */
 	struct mutex cam_lock;
@@ -137,7 +137,7 @@ struct vicam_camera {
 	int needsDummyRead;
 };
 
-static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
+static int vicam_probe(struct usb_interface *intf, const struct usb_device_id *id);
 static void vicam_disconnect(struct usb_interface *intf);
 static void read_frame(struct vicam_camera *cam, int framenum);
 static void vicam_decode_color(const u8 *, u8 *);
@@ -219,12 +219,12 @@ set_camera_power(struct vicam_camera *cam, int state)
 {
 	int status;
 
-	if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
+	status = send_control_msg(cam, 0x50, state, 0, NULL, 0);
+	if (status < 0)
 		return status;
 
-	if (state) {
+	if (state)
 		send_control_msg(cam, 0x55, 1, 0, NULL, 0);
-	}
 
 	return 0;
 }
@@ -307,11 +307,11 @@ vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 		{
 			struct video_picture vp;
 			DBG("VIDIOCGPICT\n");
-			memset(&vp, 0, sizeof (struct video_picture));
+			memset(&vp, 0, sizeof(struct video_picture));
 			vp.brightness = cam->gain << 8;
 			vp.depth = 24;
 			vp.palette = VIDEO_PALETTE_RGB24;
-			if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
+			if (copy_to_user(user_arg, &vp, sizeof(struct video_picture)))
 				retval = -EFAULT;
 			break;
 		}
@@ -355,8 +355,8 @@ vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 			if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
 				retval = -EFAULT;
 
-			// I'm not sure what the deal with a capture window is, it is very poorly described
-			// in the doc.  So I won't support it now.
+			/* I'm not sure what the deal with a capture window is, it is very poorly described
+			 * in the doc.  So I won't support it now. */
 			break;
 		}
 
@@ -372,7 +372,7 @@ vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 
 			DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
 
-			if ( vw.width != 320 || vw.height != 240 )
+			if (vw.width != 320 || vw.height != 240)
 				retval = -EFAULT;
 
 			break;
@@ -385,7 +385,7 @@ vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 			int i;
 
 			DBG("VIDIOCGMBUF\n");
-			memset(&vm, 0, sizeof (vm));
+			memset(&vm, 0, sizeof(vm));
 			vm.size =
 			    VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
 			vm.frames = VICAM_FRAMES;
@@ -401,23 +401,24 @@ vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 	case VIDIOCMCAPTURE:
 		{
 			struct video_mmap vm;
-			// int video_size;
+			/* int video_size; */
 
 			if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
 				retval = -EFAULT;
 				break;
 			}
 
-			DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
+			DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",
+			    vm.frame, vm.width, vm.height, vm.format);
 
-			if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
+			if (vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24)
 				retval = -EINVAL;
 
-			// in theory right here we'd start the image capturing
-			// (fill in a bulk urb and submit it asynchronously)
-			//
-			// Instead we're going to do a total hack job for now and
-			// retrieve the frame in VIDIOCSYNC
+			/* in theory right here we'd start the image capturing
+			 * (fill in a bulk urb and submit it asynchronously)
+			 *
+			 * Instead we're going to do a total hack job for now and
+			 * retrieve the frame in VIDIOCSYNC */
 
 			break;
 		}
@@ -435,7 +436,7 @@ vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
 			read_frame(cam, frame);
 			vicam_decode_color(cam->raw_image,
 					   cam->framebuf +
-					   frame * VICAM_MAX_FRAME_SIZE );
+					   frame * VICAM_MAX_FRAME_SIZE);
 
 			break;
 		}
@@ -522,7 +523,7 @@ vicam_open(struct file *file)
 	mutex_unlock(&cam->cam_lock);
 
 
-	// First upload firmware, then turn the camera on
+	/* First upload firmware, then turn the camera on */
 
 	if (!cam->is_initialized) {
 		initialize_camera(cam);
@@ -562,9 +563,8 @@ vicam_close(struct file *file)
 
 	mutex_unlock(&cam->cam_lock);
 
-	if (!open_count && !udev) {
+	if (!open_count && !udev)
 		kfree(cam);
-	}
 
 	return 0;
 }
@@ -582,57 +582,55 @@ static void vicam_decode_color(const u8 *data, u8 *rgb)
 
 	data += VICAM_HEADER_SIZE;
 
-	for( i = 0; i < 240; i++, data += 512 ) {
-		const int y = ( i * 242 ) / 240;
+	for (i = 0; i < 240; i++, data += 512) {
+		const int y = (i * 242) / 240;
 
 		int j, prevX, nextX;
 		int Y, Cr, Cb;
 
-		if ( y == 242 - 1 ) {
+		if (y == 242 - 1)
 			nextY = -512;
-		}
 
 		prevX = 1;
 		nextX = 1;
 
-		for ( j = 0; j < 320; j++, rgb += 3 ) {
-			const int x = ( j * 512 ) / 320;
+		for (j = 0; j < 320; j++, rgb += 3) {
+			const int x = (j * 512) / 320;
 			const u8 * const src = &data[x];
 
-			if ( x == 512 - 1 ) {
+			if (x == 512 - 1)
 				nextX = -1;
-			}
 
-			Cr = ( src[prevX] - src[0] ) +
-				( src[nextX] - src[0] );
+			Cr = (src[prevX] - src[0]) +
+				(src[nextX] - src[0]);
 			Cr /= 2;
 
-			Cb = ( src[prevY] - src[prevX + prevY] ) +
-				( src[prevY] - src[nextX + prevY] ) +
-				( src[nextY] - src[prevX + nextY] ) +
-				( src[nextY] - src[nextX + nextY] );
+			Cb = (src[prevY] - src[prevX + prevY]) +
+				(src[prevY] - src[nextX + prevY]) +
+				(src[nextY] - src[prevX + nextY]) +
+				(src[nextY] - src[nextX + nextY]);
 			Cb /= 4;
 
-			Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
+			Y = 1160 * (src[0] + (Cr / 2) - 16);
 
-			if ( i & 1 ) {
+			if (i & 1) {
 				int Ct = Cr;
 				Cr = Cb;
 				Cb = Ct;
 			}
 
-			if ( ( x ^ i ) & 1 ) {
+			if ((x ^ i) & 1) {
 				Cr = -Cr;
 				Cb = -Cb;
 			}
 
-			rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
-					500 ) / 900, 0, 255 );
-			rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
-					  ( 813 * Cr ) ) +
-					  500 ) / 1000, 0, 255 );
-			rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
-					500 ) / 1300, 0, 255 );
+			rgb[0] = clamp(((Y + (2017 * Cb)) +
+					500) / 900, 0, 255);
+			rgb[1] = clamp(((Y - (392 * Cb) -
+					  (813 * Cr)) +
+					  500) / 1000, 0, 255);
+			rgb[2] = clamp(((Y + (1594 * Cr)) +
+					500) / 1300, 0, 255);
 
 			prevX = -1;
 		}
@@ -655,15 +653,15 @@ read_frame(struct vicam_camera *cam, int framenum)
 	}
 
 	memset(request, 0, 16);
-	request[0] = cam->gain;	// 0 = 0% gain, FF = 100% gain
+	request[0] = cam->gain;	/* 0 = 0% gain, FF = 100% gain */
 
-	request[1] = 0;	// 512x242 capture
+	request[1] = 0;	/* 512x242 capture */
 
-	request[2] = 0x90;	// the function of these two bytes
-	request[3] = 0x07;	// is not yet understood
+	request[2] = 0x90;	/* the function of these two bytes */
+	request[3] = 0x07;	/* is not yet understood */
 
 	if (cam->shutter_speed > 60) {
-		// Short exposure
+		/* Short exposure */
 		realShutter =
 		    ((-15631900 / cam->shutter_speed) + 260533) / 1000;
 		request[4] = realShutter & 0xFF;
@@ -671,7 +669,7 @@ read_frame(struct vicam_camera *cam, int framenum)
 		request[6] = 0x03;
 		request[7] = 0x01;
 	} else {
-		// Long exposure
+		/* Long exposure */
 		realShutter = 15600 / cam->shutter_speed - 1;
 		request[4] = 0;
 		request[5] = 0;
@@ -679,15 +677,14 @@ read_frame(struct vicam_camera *cam, int framenum)
 		request[7] = realShutter >> 8;
 	}
 
-	// Per John Markus BjĂ¸rndalen, byte at index 8 causes problems if it isn't 0
+	/* Per John Markus BjĂ¸rndalen, byte at index 8 causes problems if it isn't 0*/
 	request[8] = 0;
-	// bytes 9-15 do not seem to affect exposure or image quality
+	/* bytes 9-15 do not seem to affect exposure or image quality */
 
 	mutex_lock(&cam->cam_lock);
 
-	if (!cam->udev) {
+	if (!cam->udev)
 		goto done;
-	}
 
 	n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
 
@@ -712,7 +709,7 @@ read_frame(struct vicam_camera *cam, int framenum)
 }
 
 static ssize_t
-vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
+vicam_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct vicam_camera *cam = file->private_data;
 
@@ -732,15 +729,13 @@ vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
 
 	count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
 
-	if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
+	if (copy_to_user(buf, &cam->framebuf[*ppos], count))
 		count = -EFAULT;
-	} else {
+	else
 		*ppos += count;
-	}
 
-	if (count == VICAM_MAX_FRAME_SIZE) {
+	if (count == VICAM_MAX_FRAME_SIZE)
 		*ppos = 0;
-	}
 
 	return count;
 }
@@ -749,7 +744,7 @@ vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
 static int
 vicam_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	// TODO: allocate the raw frame buffer if necessary
+	/* TODO: allocate the raw frame buffer if necessary */
 	unsigned long page, pos;
 	unsigned long start = vma->vm_start;
 	unsigned long size  = vma->vm_end-vma->vm_start;
@@ -793,9 +788,9 @@ static const struct v4l2_file_operations vicam_fops = {
 };
 
 static struct video_device vicam_template = {
-	.name 		= "ViCam-based USB Camera",
-	.fops 		= &vicam_fops,
-	.release 	= video_device_release_empty,
+	.name		= "ViCam-based USB Camera",
+	.fops		= &vicam_fops,
+	.release	= video_device_release_empty,
 };
 
 /* table of devices that work with this driver */
@@ -823,7 +818,7 @@ static struct usb_driver vicam_driver = {
  *	this driver might be interested in.
  */
 static int
-vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
+vicam_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	int bulkEndpoint = 0;
@@ -847,8 +842,8 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
 		       "No bulk in endpoint was found ?! (this is bad)\n");
 	}
 
-	if ((cam =
-	     kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
+	cam = kzalloc(sizeof(struct vicam_camera), GFP_KERNEL);
+	if (cam == NULL) {
 		printk(KERN_WARNING
 		       "could not allocate kernel memory for vicam_camera struct\n");
 		return -ENOMEM;
@@ -874,7 +869,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
 	printk(KERN_INFO "ViCam webcam driver now controlling device %s\n",
 		video_device_node_name(&cam->vdev));
 
-	usb_set_intfdata (intf, cam);
+	usb_set_intfdata(intf, cam);
 
 	return 0;
 }
@@ -883,8 +878,8 @@ static void
 vicam_disconnect(struct usb_interface *intf)
 {
 	int open_count;
-	struct vicam_camera *cam = usb_get_intfdata (intf);
-	usb_set_intfdata (intf, NULL);
+	struct vicam_camera *cam = usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
 
 	/* we must unregister the device before taking its
 	 * cam_lock. This is because the video open call
@@ -914,9 +909,8 @@ vicam_disconnect(struct usb_interface *intf)
 
 	mutex_unlock(&cam->cam_lock);
 
-	if (!open_count) {
+	if (!open_count)
 		kfree(cam);
-	}
 
 	printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
 }
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 42de83e..d4a48c4 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -516,8 +516,7 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
 	if (existing_size != 0) {
 		iounmap(image->kern_base);
 		image->kern_base = NULL;
-		if (image->bus_resource.name != NULL)
-			kfree(image->bus_resource.name);
+		kfree(image->bus_resource.name);
 		release_resource(&image->bus_resource);
 		memset(&image->bus_resource, 0, sizeof(struct resource));
 	}
@@ -560,8 +559,6 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
 
 	return 0;
 
-	iounmap(image->kern_base);
-	image->kern_base = NULL;
 err_remap:
 	release_resource(&image->bus_resource);
 err_resource:
@@ -1782,7 +1779,6 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
 	return 0;
 
-	vme_unregister_bridge(ca91cx42_bridge);
 err_reg:
 	ca91cx42_crcsr_exit(ca91cx42_bridge, pdev);
 err_lm:
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 26ea42f..b00a53e 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -821,8 +821,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
 	if (existing_size != 0) {
 		iounmap(image->kern_base);
 		image->kern_base = NULL;
-		if (image->bus_resource.name != NULL)
-			kfree(image->bus_resource.name);
+		kfree(image->bus_resource.name);
 		release_resource(&image->bus_resource);
 		memset(&image->bus_resource, 0, sizeof(struct resource));
 	}
@@ -869,8 +868,6 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
 
 	return 0;
 
-	iounmap(image->kern_base);
-	image->kern_base = NULL;
 err_remap:
 	release_resource(&image->bus_resource);
 err_resource:
diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
index d9fc864..c078ce3 100644
--- a/drivers/staging/vme/vme.c
+++ b/drivers/staging/vme/vme.c
@@ -441,7 +441,6 @@ struct vme_resource *vme_master_request(struct device *dev,
 
 	return resource;
 
-	kfree(resource);
 err_alloc:
 	/* Unlock image */
 	spin_lock(&master_image->lock);
@@ -768,7 +767,6 @@ struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern,
 
 	return attributes;
 
-	kfree(pattern_attr);
 err_pat:
 	kfree(attributes);
 err_attr:
@@ -809,7 +807,6 @@ struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address)
 
 	return attributes;
 
-	kfree(pci_attr);
 err_pci:
 	kfree(attributes);
 err_attr:
@@ -851,7 +848,6 @@ struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address,
 
 	return attributes;
 
-	kfree(vme_attr);
 err_vme:
 	kfree(attributes);
 err_attr:
@@ -1363,9 +1359,8 @@ int vme_register_bridge(struct vme_bridge *bridge)
 
 	return retval;
 
-	i = VME_SLOTS_MAX;
 err_reg:
-	while (i > -1) {
+	while (--i >= 0) {
 		dev = &bridge->dev[i];
 		device_unregister(dev);
 	}
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index f5028d9..efaf19b 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -312,9 +312,9 @@ static int device_notify_reboot(struct notifier_block *, unsigned long event, vo
 static int viawget_suspend(struct pci_dev *pcid, pm_message_t state);
 static int viawget_resume(struct pci_dev *pcid);
 struct notifier_block device_notifier = {
-        notifier_call:  device_notify_reboot,
-        next:           NULL,
-        priority:       0
+	.notifier_call = device_notify_reboot,
+	.next = NULL,
+	.priority = 0,
 };
 #endif
 
@@ -3032,7 +3032,7 @@ int Config_FileOperation(PSDevice pDevice,bool fwrite,unsigned char *Parameter)
 
 buffer = kmalloc(1024, GFP_KERNEL);
 if(buffer==NULL) {
-  printk("alllocate mem for file fail?\n");
+  printk("allocate mem for file fail?\n");
   result = -1;
   goto error1;
 }
@@ -3064,8 +3064,7 @@ else {
 }
 
 error1:
-  if(buffer)
-  	 kfree(buffer);
+  kfree(buffer);
 
   if(filp_close(filp,NULL))
        printk("Config_FileOperation:close file fail\n");
@@ -3606,13 +3605,13 @@ static int ethtool_ioctl(struct net_device *dev, void *useraddr)
 MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table);
 
 static struct pci_driver device_driver = {
-        name:       DEVICE_NAME,
-        id_table:   vt6655_pci_id_table,
-        probe:      vt6655_probe,
-        remove:     vt6655_remove,
+	.name = DEVICE_NAME,
+	.id_table = vt6655_pci_id_table,
+	.probe = vt6655_probe,
+	.remove = vt6655_remove,
 #ifdef CONFIG_PM
-        suspend:    viawget_suspend,
-        resume:     viawget_resume,
+	.suspend = viawget_suspend,
+	.resume = viawget_resume,
 #endif
 };
 
diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c
index 5b83f94..7735027 100644
--- a/drivers/staging/vt6655/hostap.c
+++ b/drivers/staging/vt6655/hostap.c
@@ -860,8 +860,7 @@ int vt6655_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
 	}
 
  out:
-	if (param != NULL)
-		kfree(param);
+	kfree(param);
 
 	return ret;
 }
diff --git a/drivers/staging/vt6655/wpactl.c b/drivers/staging/vt6655/wpactl.c
index 4bdb836..fbae16d 100644
--- a/drivers/staging/vt6655/wpactl.c
+++ b/drivers/staging/vt6655/wpactl.c
@@ -987,8 +987,7 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
 	}
 
 out:
-	if (param != NULL)
-		kfree(param);
+	kfree(param);
 
 	return ret;
 }
diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig
index 1055b52..a441ba5 100644
--- a/drivers/staging/vt6656/Kconfig
+++ b/drivers/staging/vt6656/Kconfig
@@ -3,6 +3,7 @@ config VT6656
 	depends on USB && WLAN
 	select WIRELESS_EXT
 	select WEXT_PRIV
+	select FW_LOADER
 	---help---
 	This is a vendor-written driver for VIA VT6656.
 
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
index e8d0b42..f1496ec 100644
--- a/drivers/staging/vt6656/device.h
+++ b/drivers/staging/vt6656/device.h
@@ -55,6 +55,7 @@
 #include <linux/reboot.h>
 #include <linux/usb.h>
 #include <linux/signal.h>
+#include <linux/firmware.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #ifdef SIOCETHTOOL
@@ -421,6 +422,8 @@ typedef struct __device_info {
     struct net_device*          dev;
     struct net_device_stats     stats;
 
+    const struct firmware	*firmware;
+
     OPTIONS                     sOpts;
 
 	struct tasklet_struct       CmdWorkItem;
diff --git a/drivers/staging/vt6656/firmware.c b/drivers/staging/vt6656/firmware.c
index d49ea70..8c8126a 100644
--- a/drivers/staging/vt6656/firmware.c
+++ b/drivers/staging/vt6656/firmware.c
@@ -39,6 +39,12 @@
 
 static int          msglevel                =MSG_LEVEL_INFO;
 //static int          msglevel                =MSG_LEVEL_DEBUG;
+
+#define FIRMWARE_VERSION	0x133		/* version 1.51 */
+#define FIRMWARE_NAME		"vntwusb.fw"
+
+#define FIRMWARE_CHUNK_SIZE	0x400
+
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
@@ -47,724 +53,6 @@ static int          msglevel                =MSG_LEVEL_INFO;
 
 /*---------------------  Export Variables  --------------------------*/
 
-/*
- *  This is firmware version 1.51
- */
-#define FIRMWARE_VERSION        0x133
-
-const BYTE abyFirmware[] = {
-
-0x02, 0x35, 0x62, 0x02, 0x3B, 0xED, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0x3E, 0x21, 0xD2, 0x04,
-0x90, 0x06, 0x24, 0x74, 0x08, 0xF0, 0x90, 0x06, 0x21, 0xE0, 0x90, 0x45, 0x39, 0xF0, 0xE0, 0x90,
-0x06, 0x21, 0xF0, 0x90, 0x06, 0x10, 0xE0, 0x54, 0x60, 0x60, 0x03, 0x02, 0x1A, 0xE9, 0xA3, 0xE0,
-0x12, 0x28, 0x7E, 0x18, 0x15, 0x00, 0x18, 0xF6, 0x01, 0x19, 0xD1, 0x03, 0x16, 0x79, 0x05, 0x12,
-0x52, 0x06, 0x17, 0xE5, 0x08, 0x16, 0xAF, 0x09, 0x17, 0x33, 0x0A, 0x17, 0x91, 0x0B, 0x00, 0x00,
-0x1A, 0xE1, 0x90, 0x06, 0x17, 0xE0, 0xFE, 0x90, 0x06, 0x16, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x31,
-0xF0, 0xED, 0xA3, 0xF0, 0x90, 0x10, 0x3D, 0x74, 0x05, 0xF0, 0x90, 0x06, 0x24, 0x74, 0x08, 0xF0,
-0x90, 0x06, 0x13, 0xE0, 0x24, 0xFE, 0x60, 0x47, 0x14, 0x70, 0x03, 0x02, 0x14, 0x79, 0x24, 0xFD,
-0x60, 0x25, 0x14, 0x70, 0x03, 0x02, 0x13, 0x9C, 0x24, 0x06, 0x60, 0x03, 0x02, 0x16, 0x54, 0x7B,
-0x01, 0x7A, 0x10, 0x79, 0x8B, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x4C, 0xE4, 0xF0,
-0xA3, 0x74, 0x12, 0xF0, 0x02, 0x16, 0x5C, 0x7B, 0x01, 0x7A, 0x10, 0x79, 0x81, 0x90, 0x10, 0x46,
-0x12, 0x27, 0xBA, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0x74, 0x0A, 0xF0, 0x02, 0x16, 0x5C, 0x7B,
-0x01, 0x7A, 0x10, 0x79, 0x51, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x52, 0x74, 0x02,
-0xF0, 0x90, 0x10, 0x54, 0xE0, 0xFE, 0x90, 0x10, 0x53, 0xE0, 0xFD, 0xEE, 0x90, 0x10, 0x4C, 0xF0,
-0xED, 0xA3, 0xF0, 0x30, 0x06, 0x5A, 0xE0, 0xFD, 0x24, 0x47, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5,
-0x83, 0xE4, 0xF0, 0x74, 0x48, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x02, 0xF0,
-0x74, 0x4E, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x4F, 0x2D, 0xF5,
-0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x02, 0xF0, 0x90, 0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10,
-0x97, 0xE0, 0xFB, 0xEE, 0xEB, 0xC3, 0x94, 0x20, 0xEE, 0x94, 0x01, 0x40, 0x03, 0x02, 0x16, 0x5C,
-0x74, 0x50, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x02, 0x16, 0x5C,
-0x90, 0x10, 0x4D, 0xE0, 0xFD, 0x24, 0x47, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x40,
-0xF0, 0x74, 0x48, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x4E, 0x2D,
-0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x40, 0xF0, 0x74, 0x4F, 0x2D, 0xF5, 0x82, 0xE4,
-0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10, 0x97, 0xE0, 0xFB,
-0xEE, 0xEB, 0xC3, 0x94, 0x20, 0xEE, 0x94, 0x01, 0x40, 0x03, 0x02, 0x16, 0x5C, 0x74, 0x50, 0x2D,
-0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x02, 0x16, 0x5C, 0x7B, 0x01, 0x7A, 0x10,
-0x79, 0x51, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x52, 0x74, 0x07, 0xF0, 0x90, 0x10,
-0x54, 0xE0, 0xFE, 0x90, 0x10, 0x53, 0xE0, 0xFD, 0xEE, 0x90, 0x10, 0x4C, 0xF0, 0xED, 0xA3, 0xF0,
-0x30, 0x06, 0x59, 0xE0, 0xFD, 0x24, 0x47, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x40,
-0xF0, 0x74, 0x48, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x4E, 0x2D,
-0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x40, 0xF0, 0x74, 0x4F, 0x2D, 0xF5, 0x82, 0xE4,
-0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x90, 0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10, 0x97, 0xE0, 0xFB,
-0xEE, 0xEB, 0xC3, 0x94, 0x20, 0xEE, 0x94, 0x01, 0x40, 0x03, 0x02, 0x16, 0x5C, 0x74, 0x50, 0x2D,
-0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x02, 0x16, 0x5C, 0x90, 0x10, 0x4D, 0xE0,
-0xFD, 0x24, 0x47, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x48, 0x2D, 0xF5,
-0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x02, 0xF0, 0x74, 0x4E, 0x2D, 0xF5, 0x82, 0xE4, 0x34,
-0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x74, 0x4F, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x10, 0xF5, 0x83, 0x74,
-0x02, 0xF0, 0x90, 0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10, 0x97, 0xE0, 0xFB, 0xEE, 0xEB, 0xC3, 0x94,
-0x20, 0xEE, 0x94, 0x01, 0x40, 0x03, 0x02, 0x16, 0x5C, 0x74, 0x50, 0x2D, 0xF5, 0x82, 0xE4, 0x34,
-0x10, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x02, 0x16, 0x5C, 0x90, 0x06, 0x12, 0xE0, 0x14, 0x60, 0x2F,
-0x14, 0x70, 0x03, 0x02, 0x15, 0x34, 0x14, 0x70, 0x03, 0x02, 0x15, 0xD5, 0x24, 0x03, 0x60, 0x03,
-0x02, 0x16, 0x4C, 0x7B, 0x01, 0x7A, 0x43, 0x79, 0x1A, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90,
-0x43, 0x1A, 0xE0, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0x16, 0x5C, 0x90,
-0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10, 0x97, 0xE0, 0xFD, 0xEE, 0xED, 0xC3, 0x94, 0x20, 0xEE, 0x94,
-0x01, 0x50, 0x1C, 0x7B, 0x01, 0x7A, 0x10, 0x79, 0x14, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90,
-0x10, 0x14, 0xE0, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0x16, 0x5C, 0x90,
-0x10, 0x3C, 0xE0, 0xC3, 0x94, 0x01, 0x50, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22,
-0x90, 0x10, 0x0D, 0xE0, 0x20, 0xE0, 0x1C, 0x7B, 0x01, 0x7A, 0x10, 0x79, 0x14, 0x90, 0x10, 0x46,
-0x12, 0x27, 0xBA, 0x90, 0x10, 0x14, 0xE0, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF, 0xF0,
-0x02, 0x16, 0x5C, 0x90, 0x10, 0x2E, 0x12, 0x27, 0x9A, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90,
-0x10, 0x2E, 0x12, 0x27, 0x9A, 0x12, 0x26, 0x36, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF,
-0xF0, 0x02, 0x16, 0x5C, 0x90, 0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10, 0x97, 0xE0, 0xFD, 0xEE, 0xED,
-0xC3, 0x94, 0x20, 0xEE, 0x94, 0x01, 0x50, 0x33, 0x90, 0x10, 0x99, 0xE0, 0x70, 0x0C, 0xA3, 0xE0,
-0x70, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x10, 0x2E, 0x12, 0x27, 0x9A,
-0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x2E, 0x12, 0x27, 0x9A, 0x12, 0x26, 0x36, 0xFF,
-0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0x16, 0x5C, 0x90, 0x10, 0x3C, 0xE0, 0xC3,
-0x94, 0x02, 0x50, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x10, 0x0D, 0xE0,
-0x20, 0xE0, 0x21, 0x90, 0x10, 0x2E, 0x12, 0x27, 0x9A, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90,
-0x10, 0x2E, 0x12, 0x27, 0x9A, 0x12, 0x26, 0x36, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF,
-0xF0, 0x02, 0x16, 0x5C, 0x90, 0x10, 0x31, 0x12, 0x27, 0x9A, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA,
-0x90, 0x10, 0x31, 0x12, 0x27, 0x9A, 0x12, 0x26, 0x36, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3,
-0xEF, 0xF0, 0x02, 0x16, 0x5C, 0x90, 0x10, 0x98, 0xE0, 0xFE, 0x90, 0x10, 0x97, 0xE0, 0xFD, 0xEE,
-0xED, 0xC3, 0x94, 0x20, 0xEE, 0x94, 0x01, 0x50, 0x32, 0x90, 0x10, 0x99, 0xE0, 0x60, 0x04, 0xA3,
-0xE0, 0x70, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x10, 0x31, 0x12, 0x27,
-0x9A, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x31, 0x12, 0x27, 0x9A, 0x12, 0x26, 0x36,
-0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF, 0xF0, 0x80, 0x41, 0x90, 0x10, 0x3C, 0xE0, 0xC3,
-0x94, 0x03, 0x50, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x10, 0x31, 0x12,
-0x27, 0x9A, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x31, 0x12, 0x27, 0x9A, 0x12, 0x26,
-0x36, 0xFF, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0xEF, 0xF0, 0x80, 0x10, 0x90, 0x06, 0x22, 0xE0,
-0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x45, 0x31, 0xE0,
-0xFE, 0xA3, 0xE0, 0xFF, 0xD3, 0x90, 0x10, 0x4D, 0xE0, 0x9F, 0x90, 0x10, 0x4C, 0xE0, 0x9E, 0x40,
-0x05, 0xEE, 0xF0, 0xA3, 0xEF, 0xF0, 0x02, 0x33, 0xF6, 0x90, 0x06, 0x12, 0xE0, 0x90, 0x10, 0x3E,
-0xF0, 0x90, 0x10, 0x3D, 0x74, 0x04, 0xF0, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08,
-0xF0, 0xA3, 0xF0, 0x90, 0x10, 0x3E, 0xE0, 0xFF, 0x44, 0x80, 0x90, 0x06, 0x06, 0xF0, 0xEF, 0x70,
-0x07, 0x90, 0x10, 0x38, 0x74, 0x07, 0xF0, 0x22, 0x90, 0x10, 0x38, 0x74, 0x0F, 0xF0, 0x22, 0x90,
-0x06, 0x13, 0xE0, 0xFE, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x35, 0xF0, 0xED, 0xA3,
-0xF0, 0x90, 0x45, 0x35, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x64, 0x01, 0x4E, 0x60, 0x0C, 0xEF, 0x4E,
-0x60, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x12, 0xE0, 0x90, 0x10,
-0x3A, 0xF0, 0x90, 0x10, 0x3D, 0x74, 0x08, 0xF0, 0x90, 0x06, 0x08, 0x74, 0x02, 0xF0, 0xA3, 0x04,
-0xF0, 0xA3, 0x74, 0x01, 0xF0, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3,
-0xF0, 0x90, 0x10, 0x3A, 0xE0, 0x70, 0x0D, 0x90, 0x10, 0x38, 0x74, 0x0F, 0xF0, 0x90, 0x06, 0x07,
-0x74, 0x02, 0xF0, 0x22, 0x90, 0x10, 0x38, 0x74, 0x1F, 0xF0, 0x90, 0x06, 0x07, 0xE0, 0x44, 0x1C,
-0xF0, 0x90, 0x06, 0x0B, 0x74, 0x70, 0xF0, 0xE4, 0x90, 0x10, 0x34, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0,
-0xA3, 0xF0, 0x22, 0x90, 0x10, 0x38, 0xE0, 0x64, 0x1F, 0x70, 0x4E, 0x90, 0x06, 0x15, 0xE0, 0xFE,
-0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x33, 0xF0, 0xED, 0xA3, 0xF0, 0x90, 0x10, 0x55,
-0xE0, 0xFF, 0xC3, 0x90, 0x45, 0x34, 0xE0, 0x9F, 0x90, 0x45, 0x33, 0xE0, 0x94, 0x00, 0x50, 0x21,
-0xE4, 0x90, 0x06, 0x60, 0xF0, 0x90, 0x10, 0x3D, 0x74, 0x09, 0xF0, 0xE4, 0x90, 0x10, 0x4C, 0xF0,
-0xA3, 0xF0, 0xC2, 0x04, 0x90, 0x06, 0x23, 0x74, 0x81, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0,
-0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0,
-0x22, 0x90, 0x06, 0x13, 0xE0, 0xFE, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x35, 0xF0,
-0xED, 0xA3, 0xF0, 0x90, 0x06, 0x15, 0xE0, 0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x45,
-0x33, 0xF0, 0xED, 0xA3, 0xF0, 0xA3, 0xE0, 0x70, 0x02, 0xA3, 0xE0, 0x70, 0x13, 0x90, 0x10, 0x55,
-0xE0, 0xFF, 0xC3, 0x90, 0x45, 0x34, 0xE0, 0x9F, 0x90, 0x45, 0x33, 0xE0, 0x94, 0x00, 0x40, 0x08,
-0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74,
-0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x10, 0x38, 0xE0, 0xB4, 0x1F, 0x08, 0x90, 0x06, 0x60, 0x74,
-0x01, 0xF0, 0x80, 0x05, 0xE4, 0x90, 0x06, 0x60, 0xF0, 0x90, 0x10, 0x3D, 0x74, 0x07, 0xF0, 0xE4,
-0x90, 0x10, 0x4C, 0xF0, 0xA3, 0xF0, 0xC2, 0x04, 0x90, 0x06, 0x23, 0x74, 0x81, 0xF0, 0xA3, 0x74,
-0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x06, 0x10, 0xE0, 0x24, 0x7F, 0x60, 0x14, 0x14, 0x60, 0x4E,
-0x24, 0x02, 0x60, 0x03, 0x02, 0x18, 0xD2, 0xE4, 0x90, 0x06, 0x60, 0xF0, 0xA3, 0xF0, 0x02, 0x18,
-0xDA, 0x90, 0x06, 0x15, 0xE0, 0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x33, 0xF0,
-0xED, 0xA3, 0xF0, 0x90, 0x10, 0x55, 0xE0, 0xFF, 0xC3, 0x90, 0x45, 0x34, 0xE0, 0x9F, 0x90, 0x45,
-0x33, 0xE0, 0x94, 0x00, 0x50, 0x07, 0x90, 0x10, 0x38, 0xE0, 0xB4, 0x0F, 0x08, 0x90, 0x06, 0x22,
-0xE0, 0x44, 0x08, 0xF0, 0x22, 0xE4, 0x90, 0x06, 0x60, 0xF0, 0xA3, 0xF0, 0x80, 0x6C, 0x90, 0x06,
-0x15, 0xE0, 0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x33, 0xF0, 0xED, 0xA3, 0xF0,
-0x90, 0x45, 0x33, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x64, 0x81, 0x4E, 0x60, 0x0C, 0xEF, 0x64, 0x82,
-0x4E, 0x60, 0x06, 0xEF, 0x64, 0x03, 0x4E, 0x70, 0x0B, 0x90, 0x10, 0x38, 0xE0, 0xB4, 0x0F, 0x0C,
-0xEF, 0x4E, 0x60, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x7E, 0x00, 0xEF, 0x54,
-0x7F, 0x24, 0x34, 0xF5, 0x82, 0xEE, 0x34, 0x10, 0xF5, 0x83, 0xE0, 0xB4, 0x01, 0x08, 0x90, 0x06,
-0x60, 0x74, 0x01, 0xF0, 0x80, 0x05, 0xE4, 0x90, 0x06, 0x60, 0xF0, 0xE4, 0x90, 0x06, 0x61, 0xF0,
-0x80, 0x08, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x10, 0x3D, 0x74, 0x01, 0xF0,
-0xE4, 0x90, 0x10, 0x4C, 0xF0, 0xA3, 0xF0, 0xC2, 0x04, 0x90, 0x06, 0x23, 0x74, 0x82, 0xF0, 0xA3,
-0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x06, 0x10, 0xE0, 0x24, 0xFE, 0x60, 0x03, 0x02, 0x19,
-0xBA, 0x90, 0x06, 0x15, 0xE0, 0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x33, 0xF0,
-0xED, 0xA3, 0xF0, 0x90, 0x06, 0x13, 0xE0, 0xFE, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x45,
-0x35, 0xF0, 0xED, 0xA3, 0xF0, 0x90, 0x10, 0x38, 0xE0, 0xF9, 0x64, 0x1F, 0x70, 0x76, 0x90, 0x45,
-0x33, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x64, 0x81, 0x4E, 0x70, 0x19, 0x90, 0x06, 0x0B, 0xE0, 0x54,
-0xFB, 0xF0, 0x7C, 0x00, 0xEF, 0x54, 0x7F, 0x24, 0x34, 0xF5, 0x82, 0xEC, 0x34, 0x10, 0xF5, 0x83,
-0xE4, 0xF0, 0x80, 0x6E, 0xEF, 0x64, 0x82, 0x4E, 0x70, 0x1C, 0x90, 0x06, 0x0B, 0xE0, 0x54, 0xFE,
-0xF0, 0x7E, 0x00, 0x90, 0x45, 0x34, 0xE0, 0x54, 0x7F, 0x24, 0x34, 0xF5, 0x82, 0xEE, 0x34, 0x10,
-0xF5, 0x83, 0xE4, 0xF0, 0x80, 0x4C, 0x90, 0x45, 0x33, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x64, 0x03,
-0x4E, 0x70, 0x19, 0x90, 0x06, 0x0B, 0xE0, 0x54, 0xFD, 0xF0, 0x7E, 0x00, 0xEF, 0x54, 0x7F, 0x24,
-0x34, 0xF5, 0x82, 0xEE, 0x34, 0x10, 0xF5, 0x83, 0xE4, 0xF0, 0x80, 0x26, 0x90, 0x06, 0x22, 0xE0,
-0x44, 0x08, 0xF0, 0x22, 0xE9, 0xB4, 0x0F, 0x1A, 0x90, 0x45, 0x33, 0xE0, 0x70, 0x02, 0xA3, 0xE0,
-0x60, 0x10, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08,
-0xF0, 0x22, 0xC2, 0x04, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0,
-0x22, 0x90, 0x06, 0x10, 0xE0, 0x24, 0xFE, 0x60, 0x44, 0x24, 0x02, 0x60, 0x03, 0x02, 0x1A, 0xCA,
-0x90, 0x06, 0x13, 0xE0, 0xFE, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x35, 0xF0, 0xED,
-0xA3, 0xF0, 0x90, 0x45, 0x35, 0xE0, 0x70, 0x04, 0xA3, 0xE0, 0x64, 0x02, 0x70, 0x17, 0x90, 0x06,
-0x14, 0xE0, 0x70, 0x11, 0x90, 0x10, 0x3D, 0x74, 0x0F, 0xF0, 0x90, 0x06, 0x15, 0xE0, 0x90, 0x10,
-0x50, 0xF0, 0x02, 0x1A, 0xD2, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x15,
-0xE0, 0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x33, 0xF0, 0xED, 0xA3, 0xF0, 0x90,
-0x06, 0x13, 0xE0, 0xFE, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x45, 0x35, 0xF0, 0xED, 0xA3,
-0xF0, 0x90, 0x10, 0x38, 0xE0, 0x64, 0x1F, 0x70, 0x79, 0x90, 0x45, 0x33, 0xE0, 0xFE, 0xA3, 0xE0,
-0xFF, 0x64, 0x81, 0x4E, 0x70, 0x1A, 0x90, 0x06, 0x0B, 0xE0, 0x44, 0x04, 0xF0, 0x7C, 0x00, 0xEF,
-0x54, 0x7F, 0x24, 0x34, 0xF5, 0x82, 0xEC, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x80, 0x62,
-0xEF, 0x64, 0x82, 0x4E, 0x70, 0x1D, 0x90, 0x06, 0x0B, 0xE0, 0x44, 0x01, 0xF0, 0x7E, 0x00, 0x90,
-0x45, 0x34, 0xE0, 0x54, 0x7F, 0x24, 0x34, 0xF5, 0x82, 0xEE, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x01,
-0xF0, 0x80, 0x3F, 0x90, 0x45, 0x33, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x64, 0x03, 0x4E, 0x70, 0x1A,
-0x90, 0x06, 0x0B, 0xE0, 0x44, 0x02, 0xF0, 0x7E, 0x00, 0xEF, 0x54, 0x7F, 0x24, 0x34, 0xF5, 0x82,
-0xEE, 0x34, 0x10, 0xF5, 0x83, 0x74, 0x01, 0xF0, 0x80, 0x18, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08,
-0xF0, 0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08,
-0xF0, 0x22, 0xC2, 0x04, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0,
-0x22, 0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x10, 0xE0, 0x64, 0x40, 0x60,
-0x03, 0x02, 0x1C, 0xA2, 0xE0, 0x90, 0x43, 0x1E, 0xF0, 0x90, 0x06, 0x11, 0xE0, 0x90, 0x43, 0x1F,
-0xF0, 0x90, 0x06, 0x13, 0xE0, 0xFE, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x43, 0x20, 0xF0,
-0xED, 0xA3, 0xF0, 0x90, 0x06, 0x15, 0xE0, 0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x43,
-0x22, 0xF0, 0xED, 0xA3, 0xF0, 0x90, 0x06, 0x17, 0xE0, 0xFE, 0x90, 0x06, 0x16, 0xE0, 0xFD, 0xEE,
-0x90, 0x43, 0x24, 0xF0, 0xED, 0xA3, 0xF0, 0xE4, 0x90, 0x10, 0x44, 0xF0, 0xA3, 0xF0, 0x90, 0x43,
-0x24, 0xE0, 0xFF, 0xA3, 0xE0, 0x90, 0x10, 0x42, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x90, 0x43, 0x1F,
-0xE0, 0x12, 0x28, 0x7E, 0x1B, 0x70, 0x00, 0x1B, 0xE6, 0x01, 0x1B, 0x79, 0x07, 0x1B, 0x8F, 0x0B,
-0x1B, 0xAF, 0x0C, 0x1B, 0xC9, 0x10, 0x1B, 0xD9, 0x12, 0x1B, 0xFE, 0x13, 0x00, 0x00, 0x1C, 0x6A,
-0x90, 0x10, 0x3D, 0x74, 0x0B, 0xF0, 0x02, 0x1C, 0x8E, 0x90, 0x10, 0x3D, 0x74, 0x0B, 0xF0, 0x12,
-0x3D, 0x31, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90,
-0x10, 0x3D, 0x74, 0x0B, 0xF0, 0x90, 0x43, 0x21, 0xE0, 0xFF, 0x90, 0x45, 0x45, 0xE0, 0xFD, 0x12,
-0x39, 0xB4, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90,
-0x45, 0x45, 0xE0, 0xFF, 0x90, 0x06, 0x12, 0xE0, 0xFD, 0x12, 0x39, 0x2D, 0x90, 0x06, 0x23, 0x74,
-0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x12, 0x3E, 0x03, 0x90, 0x06, 0x23, 0x74,
-0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3,
-0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x22, 0x90, 0x10, 0x3D, 0x74, 0x10, 0xF0, 0x90, 0x06, 0x23, 0x74,
-0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x12, 0x3D, 0xBA, 0x02, 0x1C, 0x8E, 0x90, 0x06,
-0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0xA3, 0xF0, 0x90, 0x04, 0x7A, 0xE0, 0x90, 0x45,
-0x39, 0xF0, 0xE0, 0x54, 0x7F, 0xF0, 0x44, 0x80, 0xF0, 0x90, 0x04, 0x7A, 0xF0, 0x7D, 0x17, 0x7F,
-0x0C, 0x12, 0x3D, 0x00, 0x7D, 0xB9, 0x7F, 0x0D, 0x12, 0x3D, 0x00, 0x90, 0x04, 0x54, 0x74, 0x01,
-0xF0, 0xE4, 0x90, 0x04, 0x78, 0xF0, 0xA3, 0xF0, 0x90, 0x06, 0x20, 0x74, 0x20, 0xF0, 0x90, 0x04,
-0x59, 0x74, 0x10, 0xF0, 0xE4, 0x90, 0x06, 0x05, 0xF0, 0x90, 0x06, 0x07, 0x74, 0x03, 0xF0, 0x75,
-0xA8, 0x81, 0x43, 0x87, 0x01, 0x90, 0x06, 0x20, 0x74, 0x21, 0xF0, 0x90, 0x04, 0x58, 0x74, 0x14,
-0xF0, 0xA3, 0x74, 0x50, 0xF0, 0x43, 0xA8, 0x81, 0x80, 0x24, 0x90, 0x10, 0x3D, 0x74, 0x0D, 0xF0,
-0x7B, 0x01, 0x7A, 0x43, 0x79, 0x26, 0x90, 0x10, 0x3F, 0x12, 0x27, 0xBA, 0x90, 0x06, 0x17, 0xE0,
-0xFE, 0x90, 0x06, 0x16, 0xE0, 0xFD, 0xEE, 0x90, 0x10, 0x42, 0xF0, 0xED, 0xA3, 0xF0, 0xE4, 0x90,
-0x06, 0x24, 0xF0, 0x90, 0x06, 0x23, 0x74, 0xC0, 0xF0, 0x90, 0x06, 0x25, 0x74, 0x08, 0xF0, 0xC2,
-0x04, 0x22, 0x90, 0x06, 0x10, 0xE0, 0x64, 0xC0, 0x60, 0x03, 0x02, 0x1E, 0x86, 0xE0, 0x90, 0x43,
-0x1E, 0xF0, 0x90, 0x06, 0x11, 0xE0, 0x90, 0x43, 0x1F, 0xF0, 0x90, 0x06, 0x13, 0xE0, 0xFE, 0x90,
-0x06, 0x12, 0xE0, 0xFD, 0xEE, 0x90, 0x43, 0x20, 0xF0, 0xED, 0xA3, 0xF0, 0x90, 0x06, 0x15, 0xE0,
-0xFE, 0x90, 0x06, 0x14, 0xE0, 0xFD, 0xEE, 0x90, 0x43, 0x22, 0xF0, 0xED, 0xA3, 0xF0, 0x90, 0x06,
-0x17, 0xE0, 0xFE, 0x90, 0x06, 0x16, 0xE0, 0xFD, 0xEE, 0x90, 0x43, 0x24, 0xF0, 0xED, 0xA3, 0xF0,
-0x90, 0x43, 0x24, 0xE0, 0xFF, 0xA3, 0xE0, 0x90, 0x10, 0x4C, 0xCF, 0xF0, 0xA3, 0xEF, 0xF0, 0x90,
-0x43, 0x1F, 0xE0, 0x24, 0xFA, 0x70, 0x03, 0x02, 0x1E, 0x58, 0x24, 0x05, 0x60, 0x03, 0x02, 0x1E,
-0x6F, 0x90, 0x43, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xEE, 0x60, 0x03, 0x02, 0x1E, 0x50, 0xEF,
-0x24, 0xFE, 0x70, 0x03, 0x02, 0x1D, 0xCD, 0x14, 0x60, 0x31, 0x14, 0x60, 0x4E, 0x24, 0xFC, 0x70,
-0x03, 0x02, 0x1E, 0x1A, 0x24, 0x07, 0x60, 0x03, 0x02, 0x1E, 0x50, 0x7B, 0x01, 0x7A, 0x00, 0x79,
-0x00, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x43, 0x20, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90,
-0x10, 0x47, 0xEE, 0x8F, 0xF0, 0x12, 0x26, 0xB0, 0x02, 0x1E, 0x77, 0x7B, 0x01, 0x7A, 0x04, 0x79,
-0x00, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0x90, 0x43, 0x20, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90,
-0x10, 0x47, 0xEE, 0x8F, 0xF0, 0x12, 0x26, 0xB0, 0x02, 0x1E, 0x77, 0x7B, 0x01, 0x7A, 0x43, 0x79,
-0x26, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0xE4, 0x90, 0x45, 0x37, 0xF0, 0xA3, 0xF0, 0x90, 0x43,
-0x24, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x90, 0x45, 0x38, 0xE0, 0x9F, 0x90, 0x45, 0x37, 0xE0,
-0x9E, 0x40, 0x03, 0x02, 0x1E, 0x77, 0xA3, 0xE0, 0xFF, 0x90, 0x43, 0x21, 0xE0, 0x2F, 0xFF, 0x12,
-0x3B, 0x25, 0x90, 0x45, 0x38, 0xE0, 0x24, 0x26, 0xF5, 0x82, 0xE4, 0x34, 0x43, 0xF5, 0x83, 0xEF,
-0xF0, 0x90, 0x45, 0x37, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x80, 0xC1, 0x7B, 0x01, 0x7A,
-0x43, 0x79, 0x26, 0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0xE4, 0x90, 0x45, 0x37, 0xF0, 0xA3, 0xF0,
-0x90, 0x43, 0x24, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x90, 0x45, 0x38, 0xE0, 0x9F, 0x90, 0x45,
-0x37, 0xE0, 0x9E, 0x40, 0x03, 0x02, 0x1E, 0x77, 0xA3, 0xE0, 0xFE, 0x90, 0x43, 0x21, 0xE0, 0x2E,
-0xFF, 0x74, 0x26, 0x2E, 0xF9, 0xE4, 0x34, 0x43, 0xFA, 0x7B, 0x01, 0x12, 0x3C, 0xCD, 0x90, 0x45,
-0x37, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x80, 0xC6, 0x7B, 0x01, 0x7A, 0x43, 0x79, 0x26,
-0x90, 0x10, 0x46, 0x12, 0x27, 0xBA, 0xD3, 0x90, 0x43, 0x25, 0xE0, 0x94, 0x02, 0x90, 0x43, 0x24,
-0xE0, 0x94, 0x00, 0x40, 0x0F, 0xE4, 0xF0, 0xA3, 0x74, 0x02, 0xF0, 0x90, 0x10, 0x4C, 0xE4, 0xF0,
-0xA3, 0x74, 0x02, 0xF0, 0x90, 0x43, 0x26, 0x74, 0x33, 0xF0, 0xA3, 0x74, 0x01, 0xF0, 0x80, 0x27,
-0x90, 0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x7B, 0x01, 0x7A, 0x44, 0x79, 0x2E, 0x90, 0x10,
-0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x4C, 0xE4, 0xF0, 0xA3, 0x74, 0x0A, 0xF0, 0x80, 0x08, 0x90,
-0x06, 0x22, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x24, 0x74, 0x08, 0xF0, 0x12, 0x33, 0xF6,
-0x90, 0x10, 0x3D, 0x74, 0x0C, 0xF0, 0x22, 0xD2, 0x00, 0x90, 0x43, 0x1F, 0xE0, 0x12, 0x28, 0x7E,
-0x1E, 0xAF, 0x04, 0x1F, 0xB1, 0x05, 0x1F, 0xC4, 0x08, 0x20, 0xE2, 0x09, 0x21, 0x37, 0x0A, 0x21,
-0xE9, 0x0D, 0x22, 0x7F, 0x0E, 0x22, 0xB1, 0x0F, 0x23, 0x3B, 0x11, 0x00, 0x00, 0x23, 0x4F, 0x90,
-0x43, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xEE, 0x60, 0x03, 0x02, 0x23, 0x4F, 0xEF, 0x24, 0xFE,
-0x70, 0x03, 0x02, 0x1F, 0x7D, 0x14, 0x60, 0x4B, 0x14, 0x70, 0x03, 0x02, 0x1F, 0x51, 0x24, 0x03,
-0x60, 0x03, 0x02, 0x23, 0x4F, 0x90, 0x43, 0x21, 0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34,
-0x00, 0xF5, 0x83, 0xC0, 0x83, 0xC0, 0x82, 0xE0, 0xFE, 0x90, 0x43, 0x27, 0xE0, 0xF4, 0xFD, 0xEE,
-0x5D, 0xD0, 0x82, 0xD0, 0x83, 0xF0, 0x74, 0x00, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x00, 0xF5, 0x83,
-0xC0, 0x83, 0xC0, 0x82, 0xE0, 0xFF, 0x90, 0x43, 0x26, 0xE0, 0xFE, 0xEF, 0x4E, 0xD0, 0x82, 0xD0,
-0x83, 0xF0, 0x22, 0x90, 0x43, 0x21, 0xE0, 0xFF, 0x24, 0x00, 0xF5, 0x82, 0xE4, 0x34, 0x04, 0xF5,
-0x83, 0xC0, 0x83, 0xC0, 0x82, 0xE0, 0xFE, 0x90, 0x43, 0x27, 0xE0, 0xF4, 0xFD, 0xEE, 0x5D, 0xD0,
-0x82, 0xD0, 0x83, 0xF0, 0x74, 0x00, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x04, 0xF5, 0x83, 0xC0, 0x83,
-0xC0, 0x82, 0xE0, 0xFF, 0x90, 0x43, 0x26, 0xE0, 0xFE, 0xEF, 0x4E, 0xD0, 0x82, 0xD0, 0x83, 0xF0,
-0x22, 0x90, 0x43, 0x21, 0xE0, 0xFF, 0x12, 0x3B, 0x25, 0x90, 0x45, 0x37, 0xEF, 0xF0, 0x90, 0x43,
-0x27, 0xE0, 0xF4, 0x5F, 0xFF, 0x90, 0x45, 0x37, 0xF0, 0xFE, 0x90, 0x43, 0x21, 0xE0, 0xFF, 0x90,
-0x43, 0x26, 0xE0, 0x4E, 0xFD, 0x12, 0x3A, 0x33, 0x72, 0x00, 0x92, 0x00, 0x22, 0x90, 0x43, 0x21,
-0xE0, 0xFF, 0x7B, 0x01, 0x7A, 0x45, 0x79, 0x37, 0x12, 0x3C, 0xCD, 0x90, 0x45, 0x37, 0xE0, 0xFF,
-0x90, 0x43, 0x27, 0xE0, 0xF4, 0xFE, 0xEF, 0x5E, 0xFF, 0x90, 0x45, 0x37, 0xF0, 0xFE, 0x90, 0x43,
-0x21, 0xE0, 0xFF, 0x90, 0x43, 0x26, 0xE0, 0x4E, 0xFD, 0x12, 0x3D, 0x00, 0x72, 0x00, 0x92, 0x00,
-0x22, 0x7B, 0x01, 0x7A, 0x44, 0x79, 0x2E, 0x90, 0x45, 0x3B, 0x12, 0x27, 0xBA, 0x7A, 0x43, 0x79,
-0x26, 0x02, 0x2A, 0xF6, 0x90, 0x43, 0x21, 0xE0, 0xFD, 0x90, 0x04, 0xBC, 0xF0, 0x90, 0x43, 0x20,
-0xE0, 0xFA, 0xA3, 0xE0, 0xFB, 0xEA, 0x90, 0x04, 0xBD, 0xF0, 0x90, 0x43, 0x26, 0xE0, 0x90, 0x04,
-0xC0, 0xF0, 0x90, 0x43, 0x27, 0xE0, 0x90, 0x04, 0xC1, 0xF0, 0x90, 0x43, 0x28, 0xE0, 0x90, 0x04,
-0xC2, 0xF0, 0x90, 0x43, 0x29, 0xE0, 0x90, 0x04, 0xC3, 0xF0, 0x90, 0x04, 0xBE, 0x74, 0x01, 0xF0,
-0xED, 0x04, 0x90, 0x04, 0xBC, 0xF0, 0xEB, 0x24, 0x01, 0xE4, 0x3A, 0xA3, 0xF0, 0x90, 0x43, 0x2A,
-0xE0, 0x90, 0x04, 0xC0, 0xF0, 0x90, 0x43, 0x2B, 0xE0, 0x90, 0x04, 0xC1, 0xF0, 0x90, 0x43, 0x2C,
-0xE0, 0x90, 0x04, 0xC2, 0xF0, 0x90, 0x43, 0x2D, 0xE0, 0x90, 0x04, 0xC3, 0xF0, 0x90, 0x04, 0xBE,
-0x74, 0x01, 0xF0, 0xE4, 0x90, 0x45, 0x35, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x35, 0xE0, 0xFE, 0xA3,
-0xE0, 0xFF, 0xC3, 0x94, 0x04, 0xEE, 0x64, 0x80, 0x94, 0x80, 0x40, 0x03, 0x02, 0x23, 0x4F, 0x90,
-0x43, 0x21, 0xE0, 0x24, 0x02, 0xFD, 0x90, 0x45, 0x36, 0xE0, 0xF9, 0x2D, 0xFD, 0x90, 0x43, 0x23,
-0xE0, 0x25, 0xE0, 0x25, 0xE0, 0x2D, 0x90, 0x04, 0xBC, 0xF0, 0x90, 0x43, 0x21, 0xE0, 0x24, 0x02,
-0xFD, 0x90, 0x43, 0x20, 0xE0, 0x34, 0x00, 0xCD, 0x2F, 0xCD, 0x3E, 0xFC, 0x90, 0x43, 0x22, 0xE0,
-0xFE, 0xA3, 0xE0, 0x78, 0x02, 0xC3, 0x33, 0xCE, 0x33, 0xCE, 0xD8, 0xF9, 0x2D, 0xEC, 0x3E, 0x90,
-0x04, 0xBD, 0xF0, 0x75, 0xF0, 0x04, 0xE9, 0x90, 0x43, 0x2E, 0x12, 0x27, 0x8E, 0xE0, 0x90, 0x04,
-0xC0, 0xF0, 0x75, 0xF0, 0x04, 0xE9, 0x90, 0x43, 0x2F, 0x12, 0x27, 0x8E, 0xE0, 0x90, 0x04, 0xC1,
-0xF0, 0x75, 0xF0, 0x04, 0xE9, 0x90, 0x43, 0x30, 0x12, 0x27, 0x8E, 0xE0, 0x90, 0x04, 0xC2, 0xF0,
-0x75, 0xF0, 0x04, 0xE9, 0x90, 0x43, 0x31, 0x12, 0x27, 0x8E, 0xE0, 0x90, 0x04, 0xC3, 0xF0, 0x90,
-0x04, 0xBE, 0x74, 0x01, 0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x02,
-0x20, 0x3A, 0xE4, 0x90, 0x04, 0xBD, 0xF0, 0x90, 0x04, 0xC0, 0xF0, 0xA3, 0xF0, 0xA3, 0xF0, 0xA3,
-0xF0, 0x90, 0x45, 0x35, 0xF0, 0xA3, 0xF0, 0x90, 0x43, 0x24, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3,
-0x90, 0x45, 0x36, 0xE0, 0x9F, 0x90, 0x45, 0x35, 0xE0, 0x9E, 0x40, 0x03, 0x02, 0x23, 0x4F, 0xA3,
-0xE0, 0x24, 0x26, 0xF5, 0x82, 0xE4, 0x34, 0x43, 0xF5, 0x83, 0xE0, 0x75, 0xF0, 0x16, 0xA4, 0x24,
-0x20, 0x90, 0x04, 0xBC, 0xF0, 0x90, 0x04, 0xBE, 0x74, 0x01, 0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75,
-0xF0, 0x01, 0x12, 0x26, 0xB0, 0x80, 0xC0, 0xE4, 0x90, 0x45, 0x35, 0xF0, 0xA3, 0xF0, 0xFD, 0xFC,
-0x90, 0x43, 0x24, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x90, 0x45, 0x36, 0xE0, 0x9F, 0x90, 0x45,
-0x35, 0xE0, 0x9E, 0x40, 0x03, 0x02, 0x23, 0x4F, 0x90, 0x43, 0x21, 0xE0, 0x2D, 0x90, 0x04, 0xBC,
-0xF0, 0x90, 0x43, 0x21, 0xE0, 0x2D, 0x90, 0x43, 0x20, 0xE0, 0x3C, 0x90, 0x04, 0xBD, 0xF0, 0x90,
-0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xFE, 0x74, 0x26, 0x25, 0xF0, 0xF5, 0x82,
-0x74, 0x43, 0x3E, 0xF5, 0x83, 0xE0, 0x90, 0x04, 0xC0, 0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0,
-0x01, 0x12, 0x26, 0xC6, 0xFE, 0x74, 0x26, 0x25, 0xF0, 0xF5, 0x82, 0x74, 0x43, 0x3E, 0xF5, 0x83,
-0xE0, 0x90, 0x04, 0xC1, 0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xFE,
-0x74, 0x26, 0x25, 0xF0, 0xF5, 0x82, 0x74, 0x43, 0x3E, 0xF5, 0x83, 0xE0, 0x90, 0x04, 0xC2, 0xF0,
-0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xFE, 0x74, 0x26, 0x25, 0xF0, 0xF5,
-0x82, 0x74, 0x43, 0x3E, 0xF5, 0x83, 0xE0, 0x90, 0x04, 0xC3, 0xF0, 0x90, 0x04, 0xBE, 0x74, 0x01,
-0xF0, 0x0D, 0xBD, 0x00, 0x01, 0x0C, 0x02, 0x21, 0x40, 0x90, 0x43, 0x20, 0xE0, 0xFE, 0xA3, 0xE0,
-0xFF, 0x64, 0x05, 0x4E, 0x70, 0x40, 0x90, 0x45, 0x35, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x36, 0xE0,
-0xFD, 0x24, 0x26, 0xF5, 0x82, 0xE4, 0x34, 0x43, 0xF5, 0x83, 0xE0, 0xFC, 0x74, 0x40, 0x2D, 0xF5,
-0x82, 0xE4, 0x34, 0x04, 0xF5, 0x83, 0xEC, 0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12,
-0x26, 0xB0, 0x90, 0x45, 0x35, 0xE0, 0x70, 0x04, 0xA3, 0xE0, 0x64, 0x08, 0x70, 0xCE, 0x90, 0x04,
-0x48, 0xE0, 0x44, 0x04, 0xF0, 0x22, 0xEF, 0x64, 0x06, 0x4E, 0x60, 0x03, 0x02, 0x23, 0x4F, 0x90,
-0x45, 0x35, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x36, 0xE0, 0xFF, 0x24, 0x26, 0xF5, 0x82, 0xE4, 0x34,
-0x43, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0x38, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x04, 0xF5, 0x83, 0xEE,
-0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x90, 0x45, 0x35, 0xE0, 0x70,
-0x04, 0xA3, 0xE0, 0x64, 0x08, 0x70, 0xCE, 0x90, 0x04, 0x48, 0xE0, 0x44, 0x08, 0xF0, 0x22, 0x90,
-0x43, 0x26, 0xE0, 0x90, 0x04, 0x22, 0xF0, 0x90, 0x43, 0x27, 0xE0, 0x90, 0x04, 0x23, 0xF0, 0x90,
-0x43, 0x28, 0xE0, 0x90, 0x04, 0x24, 0xF0, 0x90, 0x43, 0x29, 0xE0, 0x90, 0x04, 0x25, 0xF0, 0x90,
-0x43, 0x2A, 0xE0, 0x90, 0x04, 0x28, 0xF0, 0x90, 0x43, 0x2B, 0xE0, 0xFD, 0x7F, 0x0A, 0x02, 0x3D,
-0x00, 0x90, 0x43, 0x26, 0xE0, 0x90, 0x04, 0x22, 0xF0, 0x90, 0x43, 0x27, 0xE0, 0x90, 0x04, 0x23,
-0xF0, 0x90, 0x43, 0x28, 0xE0, 0x90, 0x04, 0x24, 0xF0, 0x90, 0x43, 0x29, 0xE0, 0x90, 0x04, 0x25,
-0xF0, 0x90, 0x43, 0x2A, 0xE0, 0x90, 0x04, 0x28, 0xF0, 0x90, 0x43, 0x2B, 0xE0, 0xFD, 0x7F, 0x0A,
-0x12, 0x3D, 0x00, 0x90, 0x43, 0x2C, 0xE0, 0xFD, 0x7F, 0x88, 0x12, 0x3D, 0x00, 0x90, 0x04, 0x4C,
-0xE0, 0x54, 0xFC, 0xF0, 0xE0, 0xFF, 0x90, 0x43, 0x2D, 0xE0, 0xFE, 0xEF, 0x4E, 0x90, 0x04, 0x4C,
-0xF0, 0xE4, 0x90, 0x45, 0x35, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x36, 0xE0, 0xFF, 0x24, 0x2E, 0xF5,
-0x82, 0xE4, 0x34, 0x43, 0xF5, 0x83, 0xE0, 0xFE, 0x74, 0xDC, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x04,
-0xF5, 0x83, 0xEE, 0xF0, 0x90, 0x45, 0x35, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x90, 0x45,
-0x35, 0xE0, 0x70, 0x04, 0xA3, 0xE0, 0x64, 0x22, 0x70, 0xCE, 0x22, 0x90, 0x43, 0x26, 0xE0, 0xFF,
-0xA3, 0xE0, 0xFD, 0xA3, 0xE0, 0xFB, 0xA3, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x12, 0x3C, 0x90, 0x22,
-0x90, 0x06, 0x30, 0x74, 0x70, 0xF0, 0x90, 0x06, 0x31, 0x74, 0xA0, 0xF0, 0xE0, 0x90, 0x06, 0x35,
-0xF0, 0x90, 0x06, 0x36, 0x74, 0xC0, 0xF0, 0x90, 0x06, 0x37, 0x74, 0x08, 0xF0, 0xE4, 0x90, 0x45,
-0x46, 0xF0, 0xA3, 0xF0, 0xC2, 0x05, 0x90, 0x06, 0x20, 0x74, 0x21, 0xF0, 0x90, 0x04, 0x58, 0x74,
-0x14, 0xF0, 0xA3, 0x74, 0x50, 0xF0, 0x12, 0x3C, 0x43, 0x75, 0xA8, 0x81, 0x90, 0x06, 0x05, 0x74,
-0x04, 0xF0, 0x90, 0x06, 0x0F, 0xE0, 0x30, 0xE4, 0x04, 0xD2, 0x06, 0x80, 0x02, 0xC2, 0x06, 0xE4,
-0x90, 0x43, 0x19, 0xF0, 0x20, 0x05, 0x03, 0x02, 0x25, 0xFB, 0xC2, 0x05, 0x90, 0x10, 0x39, 0xE0,
-0xFF, 0x20, 0xE5, 0x03, 0x02, 0x24, 0xCD, 0x54, 0xDF, 0xF0, 0x90, 0x06, 0x0E, 0xE0, 0x20, 0xE0,
-0x03, 0x02, 0x24, 0x4D, 0x7D, 0x17, 0x7F, 0x0C, 0x12, 0x3D, 0x00, 0x7D, 0xB9, 0x7F, 0x0D, 0x12,
-0x3D, 0x00, 0x90, 0x04, 0x54, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x45, 0x2F, 0xF0, 0xA3, 0xF0, 0x90,
-0x04, 0x54, 0xE0, 0x30, 0xE0, 0x16, 0x90, 0x45, 0x2F, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0,
-0x90, 0x45, 0x2F, 0xE0, 0xB4, 0x07, 0xE8, 0xA3, 0xE0, 0xB4, 0xFF, 0xE3, 0xE4, 0x90, 0x04, 0x78,
-0xF0, 0xA3, 0x74, 0x11, 0xF0, 0x90, 0x06, 0x0E, 0xE0, 0x54, 0x01, 0xF0, 0x90, 0x06, 0x30, 0x74,
-0x70, 0xF0, 0x90, 0x06, 0x31, 0x74, 0xA0, 0xF0, 0xE0, 0x90, 0x06, 0x35, 0xF0, 0x90, 0x06, 0x36,
-0x74, 0xC0, 0xF0, 0x90, 0x06, 0x37, 0x74, 0x08, 0xF0, 0x90, 0x06, 0x38, 0x74, 0x03, 0xF0, 0x90,
-0x06, 0x01, 0xE0, 0x44, 0x20, 0xF0, 0x90, 0x06, 0x07, 0x74, 0x02, 0xF0, 0x90, 0x10, 0x38, 0x74,
-0x07, 0xF0, 0x90, 0x06, 0x0E, 0xE0, 0x30, 0xE1, 0x04, 0xE0, 0x54, 0x02, 0xF0, 0x90, 0x06, 0x0E,
-0xE0, 0x30, 0xE3, 0x11, 0xE0, 0x54, 0x08, 0xF0, 0x90, 0x06, 0x0F, 0xE0, 0x30, 0xE4, 0x04, 0xD2,
-0x06, 0x80, 0x02, 0xC2, 0x06, 0x90, 0x06, 0x0E, 0xE0, 0x30, 0xE2, 0x0A, 0xE0, 0x54, 0x04, 0xF0,
-0x90, 0x04, 0x79, 0x74, 0x11, 0xF0, 0x90, 0x06, 0x0E, 0xE0, 0x30, 0xE1, 0x50, 0xE0, 0x20, 0xE0,
-0x4C, 0x7D, 0x17, 0x7F, 0x0C, 0x12, 0x3D, 0x00, 0x7D, 0xB9, 0x7F, 0x0D, 0x12, 0x3D, 0x00, 0x90,
-0x04, 0x54, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x04, 0x78, 0xF0, 0xA3, 0xF0, 0x90, 0x06, 0x0E, 0xE0,
-0x54, 0x02, 0xF0, 0x90, 0x06, 0x20, 0x74, 0x20, 0xF0, 0xE4, 0x90, 0x04, 0x58, 0xF0, 0x90, 0x06,
-0x07, 0x74, 0x03, 0xF0, 0x90, 0x04, 0x7A, 0xE0, 0x90, 0x45, 0x2E, 0xF0, 0xE0, 0x54, 0xF9, 0xF0,
-0x44, 0x02, 0xF0, 0x90, 0x04, 0x7A, 0xF0, 0x43, 0xA8, 0x81, 0x43, 0x87, 0x01, 0x90, 0x10, 0x39,
-0xE0, 0x30, 0xE0, 0x22, 0x90, 0x06, 0x24, 0xE0, 0x30, 0xE4, 0x05, 0x12, 0x12, 0x0E, 0x80, 0x0F,
-0x90, 0x06, 0x24, 0xE0, 0x30, 0xE3, 0x05, 0x12, 0x34, 0xB9, 0x80, 0x03, 0x12, 0x28, 0xF4, 0x90,
-0x10, 0x39, 0xE0, 0x54, 0xFE, 0xF0, 0x90, 0x45, 0x46, 0xE0, 0x54, 0x14, 0x70, 0x09, 0xA3, 0xE0,
-0xFF, 0x20, 0xE6, 0x03, 0x30, 0xE3, 0x4F, 0x7B, 0x01, 0x7A, 0x06, 0x79, 0x40, 0x12, 0x33, 0x2B,
-0x90, 0x45, 0x46, 0xE0, 0xFF, 0x90, 0x06, 0x48, 0xF0, 0x90, 0x45, 0x47, 0xE0, 0x90, 0x06, 0x49,
-0xF0, 0x90, 0x04, 0x2C, 0xE0, 0x90, 0x06, 0x4A, 0xF0, 0x90, 0x04, 0x2D, 0xE0, 0x90, 0x06, 0x4B,
-0xF0, 0x90, 0x04, 0x2E, 0xE0, 0x90, 0x06, 0x4C, 0xF0, 0x90, 0x04, 0x2F, 0xE0, 0x90, 0x06, 0x4D,
-0xF0, 0x90, 0x06, 0x3F, 0x74, 0x01, 0xF0, 0xEF, 0x54, 0xEB, 0x90, 0x45, 0x46, 0xF0, 0xA3, 0xE0,
-0x54, 0xBF, 0xF0, 0x54, 0xF7, 0xF0, 0x90, 0x45, 0x47, 0xE0, 0xFF, 0x20, 0xE4, 0x03, 0x02, 0x25,
-0xE8, 0x90, 0x04, 0x7A, 0xE0, 0x54, 0xDF, 0xF0, 0xE0, 0x90, 0x45, 0x2E, 0xF0, 0xE0, 0x20, 0xE6,
-0x54, 0x90, 0x04, 0x7A, 0xE0, 0x90, 0x45, 0x2E, 0xF0, 0xE0, 0x54, 0x7F, 0xF0, 0x44, 0x80, 0xF0,
-0x90, 0x04, 0x7A, 0xF0, 0xEF, 0x54, 0xEF, 0x90, 0x45, 0x47, 0xF0, 0x7D, 0x17, 0x7F, 0x0C, 0x12,
-0x3D, 0x00, 0x7D, 0xB9, 0x7F, 0x0D, 0x12, 0x3D, 0x00, 0x90, 0x04, 0x54, 0x74, 0x01, 0xF0, 0xE4,
-0x90, 0x04, 0x78, 0xF0, 0xA3, 0xF0, 0x90, 0x06, 0x20, 0x74, 0x20, 0xF0, 0x90, 0x04, 0x59, 0x74,
-0x10, 0xF0, 0xE4, 0x90, 0x06, 0x05, 0xF0, 0x90, 0x06, 0x07, 0x74, 0x03, 0xF0, 0x75, 0xA8, 0x81,
-0x43, 0x87, 0x01, 0x80, 0x23, 0x90, 0x04, 0x7A, 0xE0, 0x90, 0x45, 0x2E, 0xF0, 0xE0, 0x54, 0x7F,
-0xF0, 0x90, 0x04, 0x7A, 0xF0, 0x90, 0x10, 0x38, 0x74, 0x07, 0xF0, 0x90, 0x06, 0x05, 0x74, 0x04,
-0xF0, 0x90, 0x45, 0x47, 0xE0, 0x54, 0xEF, 0xF0, 0x90, 0x06, 0x20, 0x74, 0x21, 0xF0, 0x90, 0x04,
-0x58, 0x74, 0x14, 0xF0, 0xA3, 0x74, 0x50, 0xF0, 0x43, 0xA8, 0x81, 0x90, 0x43, 0x19, 0xE0, 0x64,
-0x01, 0x60, 0x03, 0x02, 0x23, 0xA4, 0xF0, 0x90, 0x06, 0x24, 0xE0, 0x30, 0xE3, 0x03, 0x02, 0x23,
-0xA4, 0x90, 0x06, 0x25, 0xE0, 0x54, 0xF7, 0xF0, 0x30, 0x04, 0x07, 0xE4, 0x90, 0x06, 0x23, 0xF0,
-0x80, 0x06, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0x90, 0x06, 0x24, 0x74, 0x08, 0xF0, 0x90, 0x06,
-0x25, 0xF0, 0x02, 0x23, 0xA4, 0x22, 0xBB, 0x01, 0x06, 0x89, 0x82, 0x8A, 0x83, 0xE0, 0x22, 0x50,
-0x02, 0xE7, 0x22, 0xBB, 0xFE, 0x02, 0xE3, 0x22, 0x89, 0x82, 0x8A, 0x83, 0xE4, 0x93, 0x22, 0xBB,
-0x01, 0x0C, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE0, 0x22, 0x50, 0x06,
-0xE9, 0x25, 0x82, 0xF8, 0xE6, 0x22, 0xBB, 0xFE, 0x06, 0xE9, 0x25, 0x82, 0xF8, 0xE2, 0x22, 0xE5,
-0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE4, 0x93, 0x22, 0xBB, 0x01, 0x06, 0x89,
-0x82, 0x8A, 0x83, 0xF0, 0x22, 0x50, 0x02, 0xF7, 0x22, 0xBB, 0xFE, 0x01, 0xF3, 0x22, 0xF8, 0xBB,
-0x01, 0x0D, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE8, 0xF0, 0x22, 0x50,
-0x06, 0xE9, 0x25, 0x82, 0xC8, 0xF6, 0x22, 0xBB, 0xFE, 0x05, 0xE9, 0x25, 0x82, 0xC8, 0xF2, 0x22,
-0xC5, 0xF0, 0xF8, 0xA3, 0xE0, 0x28, 0xF0, 0xC5, 0xF0, 0xF8, 0xE5, 0x82, 0x15, 0x82, 0x70, 0x02,
-0x15, 0x83, 0xE0, 0x38, 0xF0, 0x22, 0xA3, 0xF8, 0xE0, 0xC5, 0xF0, 0x25, 0xF0, 0xF0, 0xE5, 0x82,
-0x15, 0x82, 0x70, 0x02, 0x15, 0x83, 0xE0, 0xC8, 0x38, 0xF0, 0xE8, 0x22, 0xBB, 0x01, 0x10, 0xE5,
-0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE0, 0xF5, 0xF0, 0xA3, 0xE0, 0x22, 0x50,
-0x09, 0xE9, 0x25, 0x82, 0xF8, 0x86, 0xF0, 0x08, 0xE6, 0x22, 0xBB, 0xFE, 0x0A, 0xE9, 0x25, 0x82,
-0xF8, 0xE2, 0xF5, 0xF0, 0x08, 0xE2, 0x22, 0xE5, 0x83, 0x2A, 0xF5, 0x83, 0xE9, 0x93, 0xF5, 0xF0,
-0xA3, 0xE9, 0x93, 0x22, 0xBB, 0x01, 0x0D, 0xC5, 0x82, 0x29, 0xC5, 0x82, 0xC5, 0x83, 0x3A, 0xC5,
-0x83, 0x02, 0x26, 0xB0, 0x50, 0x11, 0xC5, 0x82, 0x29, 0xF8, 0x08, 0xE5, 0xF0, 0x26, 0xF6, 0x18,
-0xF5, 0xF0, 0xE5, 0x82, 0x36, 0xF6, 0x22, 0xBB, 0xFE, 0x11, 0xC5, 0x82, 0x29, 0xF8, 0x08, 0xE2,
-0x25, 0xF0, 0xF5, 0xF0, 0xF2, 0x18, 0xE2, 0x35, 0x82, 0xF2, 0x22, 0xF8, 0xE5, 0x82, 0x29, 0xF5,
-0x82, 0xE5, 0x83, 0x2A, 0xF5, 0x83, 0x74, 0x01, 0x93, 0x25, 0xF0, 0xF5, 0xF0, 0xE4, 0x93, 0x38,
-0x22, 0xF8, 0xBB, 0x01, 0x11, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83, 0xE8,
-0xF0, 0xE5, 0xF0, 0xA3, 0xF0, 0x22, 0x50, 0x09, 0xE9, 0x25, 0x82, 0xC8, 0xF6, 0x08, 0xA6, 0xF0,
-0x22, 0xBB, 0xFE, 0x09, 0xE9, 0x25, 0x82, 0xC8, 0xF2, 0xE5, 0xF0, 0x08, 0xF2, 0x22, 0xA4, 0x25,
-0x82, 0xF5, 0x82, 0xE5, 0xF0, 0x35, 0x83, 0xF5, 0x83, 0x22, 0xE0, 0xFB, 0xA3, 0xE0, 0xFA, 0xA3,
-0xE0, 0xF9, 0x22, 0xF8, 0xE0, 0xFB, 0xA3, 0xA3, 0xE0, 0xF9, 0x25, 0xF0, 0xF0, 0xE5, 0x82, 0x15,
-0x82, 0x70, 0x02, 0x15, 0x83, 0xE0, 0xFA, 0x38, 0xF0, 0x22, 0xEB, 0xF0, 0xA3, 0xEA, 0xF0, 0xA3,
-0xE9, 0xF0, 0x22, 0xBB, 0x01, 0x0D, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83,
-0x02, 0x27, 0x9A, 0x50, 0x07, 0xE9, 0x25, 0x82, 0xF8, 0x02, 0x28, 0xA4, 0xBB, 0xFE, 0x07, 0xE9,
-0x25, 0x82, 0xF8, 0x02, 0x28, 0xC6, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A, 0xF5, 0x83,
-0x02, 0x28, 0xE8, 0xBB, 0x01, 0x0D, 0xC5, 0x82, 0x29, 0xC5, 0x82, 0xC5, 0x83, 0x3A, 0xC5, 0x83,
-0x02, 0x27, 0xA3, 0x50, 0x08, 0xF8, 0xE9, 0x25, 0x82, 0xC8, 0x02, 0x28, 0xAD, 0xBB, 0xFE, 0x08,
-0xF8, 0xE9, 0x25, 0x82, 0xC8, 0x02, 0x28, 0xCF, 0xC5, 0x82, 0x29, 0xC5, 0x82, 0xC5, 0x83, 0x3A,
-0xC5, 0x83, 0x02, 0x28, 0xE8, 0xBB, 0x01, 0x20, 0xE5, 0x82, 0x29, 0xF5, 0x82, 0xE5, 0x83, 0x3A,
-0xF5, 0x83, 0xD0, 0xF0, 0xD0, 0xE0, 0xF8, 0xD0, 0xE0, 0xF9, 0xD0, 0xE0, 0xFA, 0xD0, 0xE0, 0xFB,
-0xE8, 0xC0, 0xE0, 0xC0, 0xF0, 0x02, 0x27, 0xBA, 0x50, 0x18, 0xE9, 0x25, 0x82, 0xF8, 0xD0, 0x83,
-0xD0, 0x82, 0xD0, 0xE0, 0xF9, 0xD0, 0xE0, 0xFA, 0xD0, 0xE0, 0xFB, 0xC0, 0x82, 0xC0, 0x83, 0x02,
-0x28, 0xBD, 0xBB, 0xFE, 0x18, 0xE9, 0x25, 0x82, 0xF8, 0xD0, 0x83, 0xD0, 0x82, 0xD0, 0xE0, 0xF9,
-0xD0, 0xE0, 0xFA, 0xD0, 0xE0, 0xFB, 0xC0, 0x82, 0xC0, 0x83, 0x02, 0x28, 0xDF, 0x22, 0xD0, 0x83,
-0xD0, 0x82, 0xF8, 0xE4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0D, 0xA3, 0xA3, 0x93, 0xF8,
-0x74, 0x01, 0x93, 0xF5, 0x82, 0x88, 0x83, 0xE4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xEF, 0xA3,
-0xA3, 0xA3, 0x80, 0xDF, 0xE6, 0xFB, 0x08, 0xE6, 0xFA, 0x08, 0xE6, 0xF9, 0x22, 0xFA, 0xE6, 0xFB,
-0x08, 0x08, 0xE6, 0xF9, 0x25, 0xF0, 0xF6, 0x18, 0xE6, 0xCA, 0x3A, 0xF6, 0x22, 0xEB, 0xF6, 0x08,
-0xEA, 0xF6, 0x08, 0xE9, 0xF6, 0x22, 0xE2, 0xFB, 0x08, 0xE2, 0xFA, 0x08, 0xE2, 0xF9, 0x22, 0xFA,
-0xE2, 0xFB, 0x08, 0x08, 0xE2, 0xF9, 0x25, 0xF0, 0xF2, 0x18, 0xE2, 0xCA, 0x3A, 0xF2, 0x22, 0xEB,
-0xF2, 0x08, 0xEA, 0xF2, 0x08, 0xE9, 0xF2, 0x22, 0xE4, 0x93, 0xFB, 0x74, 0x01, 0x93, 0xFA, 0x74,
-0x02, 0x93, 0xF9, 0x22, 0x90, 0x06, 0x23, 0xE0, 0x54, 0x7F, 0xFF, 0xC3, 0x74, 0x40, 0x9F, 0x90,
-0x45, 0x31, 0xF0, 0xE4, 0xA3, 0xF0, 0x90, 0x10, 0x3D, 0xE0, 0x64, 0x0B, 0x60, 0x03, 0x02, 0x2A,
-0x60, 0x90, 0x10, 0x44, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x43, 0x21, 0xE0, 0x2F, 0x90, 0x45,
-0x34, 0xF0, 0x90, 0x43, 0x20, 0xE0, 0x3E, 0x90, 0x45, 0x33, 0xF0, 0x90, 0x45, 0x31, 0xE0, 0x70,
-0x03, 0x02, 0x2A, 0xA6, 0x14, 0xF0, 0x90, 0x43, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xEE, 0x60,
-0x03, 0x02, 0x2A, 0x57, 0xEF, 0x12, 0x28, 0x7E, 0x29, 0x6A, 0x01, 0x29, 0x94, 0x02, 0x29, 0xB5,
-0x03, 0x29, 0xDE, 0x04, 0x29, 0xFE, 0x07, 0x2A, 0x31, 0x09, 0x2A, 0x31, 0x0A, 0x2A, 0x31, 0x0B,
-0x2A, 0x31, 0x0C, 0x2A, 0x31, 0x0D, 0x00, 0x00, 0x2A, 0x57, 0x90, 0x45, 0x32, 0xE0, 0x24, 0x60,
-0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x45, 0x33, 0xE4, 0x75, 0xF0, 0x01,
-0x12, 0x26, 0xC6, 0xFC, 0x74, 0x00, 0x25, 0xF0, 0xF5, 0x82, 0x74, 0x00, 0x3C, 0xF5, 0x83, 0xEF,
-0xF0, 0x02, 0x2A, 0x57, 0x90, 0x45, 0x33, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xAF, 0xF0,
-0x90, 0x45, 0x32, 0xE0, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xE0, 0xFD, 0x12,
-0x3D, 0x00, 0x02, 0x2A, 0x57, 0x90, 0x45, 0x32, 0xE0, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x06,
-0xF5, 0x83, 0xE0, 0xFF, 0x90, 0x45, 0x33, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xFC, 0x74,
-0x00, 0x25, 0xF0, 0xF5, 0x82, 0x74, 0x04, 0x3C, 0xF5, 0x83, 0xEF, 0xF0, 0x80, 0x79, 0x90, 0x45,
-0x33, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xAF, 0xF0, 0x90, 0x45, 0x32, 0xE0, 0x24, 0x60,
-0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xE0, 0xFD, 0x12, 0x3A, 0x33, 0x80, 0x59, 0x90, 0x45,
-0x32, 0xE0, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xE0, 0xFD, 0x7F, 0xF1, 0x12,
-0x3D, 0x00, 0x90, 0x45, 0x34, 0xE0, 0x44, 0x80, 0xFD, 0x7F, 0xF0, 0x12, 0x3D, 0x00, 0x90, 0x45,
-0x33, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xC6, 0xAD, 0xF0, 0x7F, 0xF0, 0x12, 0x3D, 0x00, 0x80,
-0x26, 0x90, 0x43, 0x22, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0x90, 0x45, 0x33, 0xE4, 0x75, 0xF0, 0x01,
-0x12, 0x26, 0xC6, 0xAD, 0xF0, 0x90, 0x45, 0x32, 0xE0, 0x24, 0x60, 0xF5, 0x82, 0xE4, 0x34, 0x06,
-0xF5, 0x83, 0xE0, 0xFB, 0x12, 0x3A, 0xAE, 0x90, 0x45, 0x32, 0xE0, 0x04, 0xF0, 0x02, 0x29, 0x2B,
-0x90, 0x10, 0x3D, 0xE0, 0xFF, 0xB4, 0x0D, 0x2D, 0x90, 0x45, 0x31, 0xE0, 0x60, 0x38, 0xA3, 0xE0,
-0xFE, 0x04, 0xF0, 0x74, 0x60, 0x2E, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xE0, 0xFE, 0x90,
-0x10, 0x3F, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3, 0xEE, 0x12, 0x26, 0x7C, 0x90, 0x45, 0x31,
-0xE0, 0x14, 0xF0, 0x80, 0xD3, 0xEF, 0xB4, 0x0C, 0x07, 0xC2, 0x8C, 0xE4, 0x90, 0x43, 0x19, 0xF0,
-0xE4, 0x90, 0x10, 0x3D, 0xF0, 0x22, 0x30, 0x04, 0x0A, 0xC2, 0x04, 0x90, 0x06, 0x23, 0x74, 0xC0,
-0xF0, 0x80, 0x08, 0xD2, 0x04, 0x90, 0x06, 0x23, 0x74, 0x40, 0xF0, 0x90, 0x45, 0x32, 0xE0, 0xFF,
-0x90, 0x10, 0x44, 0xE4, 0x8F, 0xF0, 0x12, 0x26, 0xB0, 0x90, 0x10, 0x42, 0xE0, 0xFE, 0xA3, 0xE0,
-0xFF, 0xA3, 0xE0, 0xB5, 0x06, 0x19, 0xA3, 0xE0, 0xB5, 0x07, 0x14, 0x90, 0x10, 0x3D, 0xE0, 0xB4,
-0x0D, 0x03, 0x12, 0x1E, 0x87, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xA3, 0x74, 0x08, 0xF0, 0x90,
-0x06, 0x25, 0x74, 0x08, 0xF0, 0x22, 0x90, 0x45, 0x38, 0x12, 0x27, 0xBA, 0x12, 0x26, 0x36, 0x60,
-0x03, 0x02, 0x2B, 0x8F, 0x7F, 0x1C, 0x12, 0x3B, 0x25, 0x90, 0x45, 0x3B, 0x12, 0x27, 0x9A, 0x90,
-0x00, 0x08, 0xEF, 0x12, 0x26, 0x8E, 0x7F, 0x1D, 0x12, 0x3B, 0x25, 0x90, 0x45, 0x3B, 0x12, 0x27,
-0x9A, 0x90, 0x00, 0x09, 0xEF, 0x12, 0x26, 0x8E, 0x7F, 0x1B, 0x12, 0x3B, 0x25, 0x90, 0x45, 0x3B,
-0x12, 0x27, 0x9A, 0x90, 0x00, 0x07, 0xEF, 0x12, 0x26, 0x8E, 0xE9, 0x24, 0x07, 0xF9, 0xE4, 0x3A,
-0xFA, 0x12, 0x26, 0x36, 0x54, 0x7F, 0x12, 0x26, 0x7C, 0x90, 0x45, 0x3B, 0x12, 0x27, 0x9A, 0x90,
-0x00, 0x07, 0x12, 0x26, 0x4F, 0x90, 0x45, 0x45, 0xF0, 0x90, 0x04, 0x2B, 0x74, 0xFF, 0xF0, 0x12,
-0x3C, 0x43, 0x90, 0x45, 0x3B, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x07, 0x12, 0x26, 0x4F, 0xFF, 0x12,
-0x3D, 0x62, 0x90, 0x45, 0x3B, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x08, 0x12, 0x26, 0x4F, 0xFD, 0x90,
-0x40, 0xC0, 0xF0, 0x90, 0x00, 0x07, 0x12, 0x26, 0x4F, 0xFF, 0x12, 0x39, 0x2D, 0x80, 0x1B, 0x12,
-0x3D, 0xE2, 0x90, 0x04, 0x54, 0xE0, 0x54, 0xFB, 0xF0, 0x90, 0x06, 0x38, 0x74, 0x03, 0xF0, 0x12,
-0x3D, 0x31, 0x90, 0x04, 0x48, 0x74, 0x02, 0xF0, 0x14, 0xF0, 0xE4, 0xFF, 0xFE, 0x74, 0xC4, 0x2F,
-0xF5, 0x82, 0xE4, 0x34, 0x04, 0xF5, 0x83, 0xE0, 0xFD, 0x90, 0x45, 0x3B, 0x12, 0x27, 0x9A, 0xE9,
-0x24, 0x01, 0xF9, 0xE4, 0x3A, 0xFA, 0xE9, 0x2F, 0xF9, 0xEA, 0x3E, 0xFA, 0xED, 0x12, 0x26, 0x7C,
-0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xEF, 0x64, 0x06, 0x4E, 0x70, 0xD2, 0x90, 0x45, 0x38, 0x12, 0x27,
-0x9A, 0x90, 0x00, 0x01, 0x12, 0x26, 0x4F, 0x60, 0x31, 0xE4, 0xFE, 0xFF, 0x90, 0x45, 0x38, 0x12,
-0x27, 0x9A, 0xE9, 0x24, 0x02, 0xF9, 0xE4, 0x3A, 0xFA, 0xE9, 0x2F, 0xF9, 0xEA, 0x3E, 0xFA, 0x12,
-0x26, 0x36, 0xFD, 0x74, 0xC4, 0x2F, 0xF5, 0x82, 0xE4, 0x34, 0x04, 0xF5, 0x83, 0xED, 0xF0, 0x0F,
-0xBF, 0x00, 0x01, 0x0E, 0xEF, 0x64, 0x06, 0x4E, 0x70, 0xD2, 0x90, 0x45, 0x38, 0x12, 0x27, 0x9A,
-0x90, 0x00, 0x08, 0x12, 0x26, 0x4F, 0x90, 0x04, 0x21, 0xF0, 0x90, 0x00, 0x09, 0x12, 0x26, 0x4F,
-0x90, 0x04, 0x20, 0xF0, 0x90, 0x04, 0x50, 0xE0, 0x44, 0x82, 0xF0, 0x90, 0x04, 0x54, 0x74, 0x0E,
-0xF0, 0x90, 0x45, 0x3B, 0x12, 0x27, 0x9A, 0xE4, 0x12, 0x26, 0x7C, 0xD3, 0x22, 0xAC, 0x07, 0xAA,
-0x05, 0xD2, 0x03, 0x90, 0x04, 0x78, 0xE0, 0x54, 0xFE, 0xF0, 0xEC, 0xD3, 0x94, 0x0E, 0x40, 0x03,
-0x02, 0x2C, 0xFA, 0xEA, 0x94, 0x0E, 0x50, 0x03, 0x02, 0x2C, 0xFA, 0x90, 0x40, 0xC9, 0xE0, 0xFD,
-0x90, 0x40, 0xC8, 0xE0, 0xFB, 0x90, 0x40, 0xC7, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90,
-0x40, 0xCC, 0xE0, 0xFD, 0x90, 0x40, 0xCB, 0xE0, 0xFB, 0x90, 0x40, 0xCA, 0x12, 0x3C, 0x89, 0x82,
-0x03, 0x92, 0x03, 0x90, 0x40, 0xD2, 0xE0, 0xFD, 0x90, 0x40, 0xD1, 0xE0, 0xFB, 0x90, 0x40, 0xD0,
-0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90, 0x40, 0xD8, 0xE0, 0xFD, 0x90, 0x40, 0xD7, 0xE0,
-0xFB, 0x90, 0x40, 0xD6, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90, 0x40, 0xE1, 0xE0, 0xFD,
-0x90, 0x40, 0xE0, 0xE0, 0xFB, 0x90, 0x40, 0xDF, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90,
-0x40, 0xE7, 0xE0, 0xFD, 0x90, 0x40, 0xE6, 0xE0, 0xFB, 0x90, 0x40, 0xE5, 0x12, 0x3C, 0x89, 0x82,
-0x03, 0x92, 0x03, 0x90, 0x40, 0xF0, 0xE0, 0xFD, 0x90, 0x40, 0xEF, 0xE0, 0xFB, 0x90, 0x40, 0xEE,
-0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x02, 0x2D, 0x98, 0xEC, 0xD3, 0x94, 0x0E, 0x50, 0x03,
-0x02, 0x2D, 0x98, 0xEA, 0xD3, 0x94, 0x0E, 0x40, 0x03, 0x02, 0x2D, 0x98, 0x90, 0x42, 0xF1, 0xE0,
-0xFD, 0x90, 0x42, 0xF0, 0xE0, 0xFB, 0x90, 0x42, 0xEF, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03,
-0x90, 0x42, 0xF4, 0xE0, 0xFD, 0x90, 0x42, 0xF3, 0xE0, 0xFB, 0x90, 0x42, 0xF2, 0x12, 0x3C, 0x89,
-0x82, 0x03, 0x92, 0x03, 0x90, 0x42, 0xFA, 0xE0, 0xFD, 0x90, 0x42, 0xF9, 0xE0, 0xFB, 0x90, 0x42,
-0xF8, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90, 0x43, 0x00, 0xE0, 0xFD, 0x90, 0x42, 0xFF,
-0xE0, 0xFB, 0x90, 0x42, 0xFE, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90, 0x43, 0x09, 0xE0,
-0xFD, 0x90, 0x43, 0x08, 0xE0, 0xFB, 0x90, 0x43, 0x07, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03,
-0x90, 0x43, 0x0F, 0xE0, 0xFD, 0x90, 0x43, 0x0E, 0xE0, 0xFB, 0x90, 0x43, 0x0D, 0x12, 0x3C, 0x89,
-0x82, 0x03, 0x92, 0x03, 0x90, 0x43, 0x18, 0xE0, 0xFD, 0x90, 0x43, 0x17, 0xE0, 0xFB, 0x90, 0x43,
-0x16, 0x12, 0x3C, 0x89, 0x82, 0x03, 0x92, 0x03, 0x90, 0x04, 0x78, 0xE0, 0x44, 0x01, 0xF0, 0xA2,
-0x03, 0x22, 0xAC, 0x07, 0xAA, 0x05, 0xD2, 0x03, 0xEC, 0xD3, 0x94, 0x0E, 0x40, 0x03, 0x02, 0x2E,
-0x43, 0xEA, 0x94, 0x0E, 0x50, 0x03, 0x02, 0x2E, 0x43, 0x90, 0x40, 0xC9, 0xE0, 0xFD, 0x90, 0x40,
-0xC8, 0xE0, 0xFB, 0x90, 0x40, 0xC7, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90,
-0x82, 0x03, 0x92, 0x03, 0x90, 0x40, 0xD8, 0xE0, 0xFD, 0x90, 0x40, 0xD7, 0xE0, 0xFB, 0x90, 0x40,
-0xD6, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92, 0x03, 0x90,
-0x40, 0xDE, 0xE0, 0xFD, 0x90, 0x40, 0xDD, 0xE0, 0xFB, 0x90, 0x40, 0xDC, 0xE0, 0x90, 0x45, 0x44,
-0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92, 0x03, 0x90, 0x40, 0xE7, 0xE0, 0xFD, 0x90,
-0x40, 0xE6, 0xE0, 0xFB, 0x90, 0x40, 0xE5, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C,
-0x90, 0x82, 0x03, 0x92, 0x03, 0x90, 0x40, 0xED, 0xE0, 0xFD, 0x90, 0x40, 0xEC, 0xE0, 0xFB, 0x90,
-0x40, 0xEB, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92, 0x03,
-0x02, 0x2E, 0xDC, 0xEC, 0xD3, 0x94, 0x0E, 0x50, 0x03, 0x02, 0x2E, 0xDC, 0xEA, 0xD3, 0x94, 0x0E,
-0x40, 0x03, 0x02, 0x2E, 0xDC, 0x90, 0x42, 0xF1, 0xE0, 0xFD, 0x90, 0x42, 0xF0, 0xE0, 0xFB, 0x90,
-0x42, 0xEF, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92, 0x03,
-0x90, 0x43, 0x00, 0xE0, 0xFD, 0x90, 0x42, 0xFF, 0xE0, 0xFB, 0x90, 0x42, 0xFE, 0xE0, 0x90, 0x45,
-0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92, 0x03, 0x90, 0x43, 0x06, 0xE0, 0xFD,
-0x90, 0x43, 0x05, 0xE0, 0xFB, 0x90, 0x43, 0x04, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12,
-0x3C, 0x90, 0x82, 0x03, 0x92, 0x03, 0x90, 0x43, 0x0F, 0xE0, 0xFD, 0x90, 0x43, 0x0E, 0xE0, 0xFB,
-0x90, 0x43, 0x0D, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92,
-0x03, 0x90, 0x43, 0x15, 0xE0, 0xFD, 0x90, 0x43, 0x14, 0xE0, 0xFB, 0x90, 0x43, 0x13, 0xE0, 0x90,
-0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x03, 0x92, 0x03, 0xA2, 0x03, 0x22, 0x90,
-0x45, 0x40, 0xEF, 0xF0, 0xD2, 0x02, 0x90, 0x40, 0xC0, 0xE0, 0xFF, 0x90, 0x45, 0x40, 0xE0, 0xFD,
-0x12, 0x2D, 0xA2, 0x82, 0x02, 0x92, 0x02, 0x90, 0x45, 0x40, 0xE0, 0xFC, 0xD3, 0x94, 0x0E, 0x50,
-0x10, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0x7B, 0x8A, 0x7D, 0xF1, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x80,
-0x3A, 0xEC, 0xD3, 0x94, 0x28, 0x50, 0x10, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0x7B, 0x8B, 0x7D, 0xF1,
-0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x80, 0x24, 0xEC, 0xD3, 0x94, 0x33, 0x50, 0x10, 0xE4, 0x90, 0x45,
-0x44, 0xF0, 0x7B, 0x8B, 0x7D, 0xB1, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x80, 0x0E, 0xE4, 0x90, 0x45,
-0x44, 0xF0, 0x7B, 0x8B, 0x7D, 0x91, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x90, 0x45, 0x40, 0xE0, 0xFF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0xF0, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFD, 0xEF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0xEF, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFB, 0xEF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0xEE, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0x90, 0x45,
-0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0x90, 0x45, 0x40, 0xE0, 0xFF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0x98, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFD, 0xEF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0x97, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFB, 0xEF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0x90, 0x45,
-0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0x90, 0x45, 0x40, 0xE0, 0xFF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0x40, 0xF5, 0x82, 0xE4, 0x34, 0x42, 0xF5, 0x83, 0xE0, 0xFD, 0xEF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0x3F, 0xF5, 0x82, 0xE4, 0x34, 0x42, 0xF5, 0x83, 0xE0, 0xFB, 0xEF,
-0x75, 0xF0, 0x03, 0xA4, 0x24, 0x3E, 0xF5, 0x82, 0xE4, 0x34, 0x42, 0xF5, 0x83, 0xE0, 0x90, 0x45,
-0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0xE4, 0x90, 0x45, 0x44, 0xF0,
-0xFB, 0xFD, 0x7F, 0xC8, 0x12, 0x3D, 0x90, 0xA2, 0x02, 0x22, 0xD2, 0x01, 0xE4, 0x90, 0x04, 0x78,
-0xF0, 0xA3, 0x74, 0x13, 0xF0, 0x7B, 0x01, 0x7A, 0x45, 0x79, 0x40, 0x7F, 0x0D, 0x12, 0x3C, 0xCD,
-0x90, 0x45, 0x40, 0xE0, 0x54, 0xFE, 0xFF, 0xF0, 0xFD, 0x7F, 0x0D, 0x12, 0x3D, 0x00, 0xE4, 0x90,
-0x45, 0x3E, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x3E, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x94, 0x10,
-0xEE, 0x64, 0x80, 0x94, 0x80, 0x50, 0x57, 0x90, 0x42, 0xEB, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27,
-0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0xFD, 0x90, 0x42, 0xEA, 0x75,
-0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0,
-0xFB, 0x90, 0x42, 0xE9, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4,
-0x25, 0x83, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x01,
-0x92, 0x01, 0x90, 0x45, 0x3E, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x80, 0x97, 0x90, 0x04,
-0x78, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0x96, 0x12, 0x3D, 0x90,
-0x90, 0x45, 0x44, 0x74, 0x9A, 0xF0, 0x7B, 0xBA, 0x7D, 0x8F, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82,
-0x01, 0x92, 0x01, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0x1E, 0x12, 0x3D, 0x90, 0x90,
-0x45, 0x44, 0x74, 0x3A, 0xF0, 0x7B, 0xBA, 0x7D, 0x8F, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x01,
-0x92, 0x01, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0x1E, 0x12, 0x3D, 0x90, 0x90, 0x43,
-0x18, 0xE0, 0xFD, 0x90, 0x43, 0x17, 0xE0, 0xFB, 0x90, 0x43, 0x16, 0xE0, 0x90, 0x45, 0x44, 0xF0,
-0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x01, 0x92, 0x01, 0x90, 0x04, 0x79, 0x74, 0x13, 0xF0, 0x90,
-0x04, 0x78, 0x74, 0x05, 0xF0, 0x7B, 0x01, 0x7A, 0x45, 0x79, 0x40, 0x7F, 0x0D, 0x12, 0x3C, 0xCD,
-0x90, 0x45, 0x40, 0xE0, 0x44, 0x01, 0xFF, 0xF0, 0xFD, 0x7F, 0x0D, 0x12, 0x3D, 0x00, 0x90, 0x04,
-0x62, 0x74, 0xC0, 0xF0, 0xA2, 0x01, 0x22, 0xD2, 0x01, 0xE4, 0x90, 0x04, 0x78, 0xF0, 0xA3, 0x74,
-0x13, 0xF0, 0xE4, 0x90, 0x45, 0x3E, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x3E, 0xE0, 0xFE, 0xA3, 0xE0,
-0xFF, 0xC3, 0x94, 0x0F, 0xEE, 0x64, 0x80, 0x94, 0x80, 0x50, 0x57, 0x90, 0x42, 0xEB, 0x75, 0xF0,
-0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0xFD,
-0x90, 0x42, 0xEA, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25,
-0x83, 0xF5, 0x83, 0xE0, 0xFB, 0x90, 0x42, 0xE9, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE,
-0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12,
-0x3C, 0x90, 0x82, 0x01, 0x92, 0x01, 0x90, 0x45, 0x3E, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0,
-0x80, 0x97, 0x90, 0x04, 0x78, 0x74, 0x01, 0xF0, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F,
-0x96, 0x12, 0x3D, 0x90, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0x7B, 0xD8, 0x7D, 0x0F, 0x7F, 0xB9, 0x12,
-0x3C, 0x90, 0x82, 0x01, 0x92, 0x01, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0x1E, 0x12,
-0x3D, 0x90, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0x7B, 0x78, 0x7D, 0x0F, 0x7F, 0xB9, 0x12, 0x3C, 0x90,
-0x82, 0x01, 0x92, 0x01, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0x1E, 0x12, 0x3D, 0x90,
-0x90, 0x43, 0x15, 0xE0, 0xFD, 0x90, 0x43, 0x14, 0xE0, 0xFB, 0x90, 0x43, 0x13, 0xE0, 0x90, 0x45,
-0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x01, 0x92, 0x01, 0x90, 0x04, 0x78, 0x74, 0x05,
-0xF0, 0x90, 0x04, 0x62, 0x74, 0xC0, 0xF0, 0xA2, 0x01, 0x22, 0x90, 0x45, 0x40, 0xEF, 0xF0, 0xD2,
-0x02, 0x90, 0x04, 0x78, 0xE0, 0x54, 0xFE, 0xF0, 0x90, 0x45, 0x40, 0xE0, 0xFF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0xF0, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFD, 0xEF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0xEF, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFB, 0xEF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0xEE, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F,
-0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0x90, 0x45, 0x40, 0xE0, 0xFF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0x98, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFD, 0xEF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0x97, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFB, 0xEF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F,
-0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0x90, 0x45, 0x40, 0xE0, 0xFF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0x40, 0xF5, 0x82, 0xE4, 0x34, 0x42, 0xF5, 0x83, 0xE0, 0xFD, 0xEF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0x3F, 0xF5, 0x82, 0xE4, 0x34, 0x42, 0xF5, 0x83, 0xE0, 0xFB, 0xEF, 0x75, 0xF0, 0x03,
-0xA4, 0x24, 0x3E, 0xF5, 0x82, 0xE4, 0x34, 0x42, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F,
-0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0x90, 0x04, 0x78, 0xE0, 0x44, 0x01, 0xF0, 0xE4,
-0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0xC8, 0x12, 0x3D, 0x90, 0x90, 0x40, 0xC0, 0xE0, 0xFF,
-0x90, 0x45, 0x40, 0xE0, 0xFD, 0x12, 0x2C, 0x4D, 0xA2, 0x02, 0x22, 0x90, 0x45, 0x31, 0x12, 0x27,
-0xBA, 0xE4, 0xFF, 0x90, 0x04, 0x48, 0xE0, 0x44, 0x10, 0xF0, 0xE4, 0xFD, 0xFC, 0x90, 0x04, 0x48,
-0xE0, 0xFF, 0x30, 0xE4, 0x0B, 0x0D, 0xBD, 0x00, 0x01, 0x0C, 0xBC, 0x07, 0xF0, 0xBD, 0xFF, 0xED,
-0xAE, 0x04, 0xAF, 0x05, 0xBE, 0x07, 0x05, 0xBF, 0xFF, 0x02, 0xC3, 0x22, 0x90, 0x04, 0x30, 0xE0,
-0xFF, 0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3, 0xEF, 0x12, 0x26, 0x7C, 0x90,
-0x04, 0x31, 0xE0, 0xFF, 0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3, 0xEF, 0x12,
-0x26, 0x7C, 0x90, 0x04, 0x32, 0xE0, 0xFF, 0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27,
-0xA3, 0xEF, 0x12, 0x26, 0x7C, 0x90, 0x04, 0x33, 0xE0, 0xFF, 0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0,
-0x01, 0x12, 0x27, 0xA3, 0xEF, 0x12, 0x26, 0x7C, 0x90, 0x04, 0x34, 0xE0, 0xFF, 0x90, 0x45, 0x31,
-0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3, 0xEF, 0x12, 0x26, 0x7C, 0x90, 0x04, 0x35, 0xE0, 0xFF,
-0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3, 0xEF, 0x12, 0x26, 0x7C, 0x90, 0x04,
-0x36, 0xE0, 0xFF, 0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3, 0xEF, 0x12, 0x26,
-0x7C, 0x90, 0x04, 0x37, 0xE0, 0xFF, 0x90, 0x45, 0x31, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xA3,
-0xEF, 0x12, 0x26, 0x7C, 0xD3, 0x22, 0x7B, 0x01, 0x7A, 0x10, 0x79, 0x34, 0x90, 0x45, 0x3A, 0x12,
-0x27, 0xBA, 0x90, 0x45, 0x3A, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x12, 0x12, 0x27, 0xC3, 0xC0, 0x03,
-0xC0, 0x02, 0xC0, 0x01, 0x90, 0x45, 0x3A, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x15, 0x12, 0x28, 0x25,
-0x90, 0x45, 0x3A, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x18, 0x12, 0x26, 0xDC, 0xFF, 0x90, 0x00, 0x1A,
-0xE5, 0xF0, 0x8F, 0xF0, 0x12, 0x27, 0x61, 0xE4, 0xFF, 0xEF, 0xC3, 0x94, 0x40, 0x50, 0x44, 0x90,
-0x45, 0x3A, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x18, 0x12, 0x26, 0xDC, 0xD3, 0x94, 0x00, 0xE5, 0xF0,
-0x94, 0x00, 0x40, 0x2F, 0x90, 0x00, 0x12, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x27, 0xF3, 0x12, 0x26,
-0x36, 0xFE, 0xAD, 0x07, 0x0F, 0x74, 0x60, 0x2D, 0xF5, 0x82, 0xE4, 0x34, 0x06, 0xF5, 0x83, 0xEE,
-0xF0, 0x90, 0x45, 0x3A, 0x12, 0x27, 0x9A, 0x90, 0x00, 0x18, 0x74, 0xFF, 0xF5, 0xF0, 0x12, 0x27,
-0x14, 0x80, 0xB6, 0xEF, 0x70, 0x17, 0x90, 0x06, 0x23, 0x74, 0x80, 0xF0, 0xE4, 0xA3, 0xF0, 0x90,
-0x10, 0x3D, 0xE0, 0xB4, 0x0C, 0x1C, 0x12, 0x3E, 0x36, 0xD2, 0x8C, 0x80, 0x15, 0x30, 0x04, 0x0B,
-0xC2, 0x04, 0xEF, 0x44, 0x80, 0x90, 0x06, 0x23, 0xF0, 0x80, 0x07, 0xD2, 0x04, 0x90, 0x06, 0x23,
-0xEF, 0xF0, 0x90, 0x06, 0x25, 0x74, 0x08, 0xF0, 0x22, 0x90, 0x06, 0x25, 0xE0, 0x30, 0xE0, 0x2F,
-0x90, 0x10, 0x3D, 0xE0, 0x24, 0xFB, 0x70, 0x1D, 0x90, 0x10, 0x49, 0x12, 0x27, 0x9A, 0x90, 0x10,
-0x46, 0x12, 0x27, 0xBA, 0x90, 0x10, 0x4E, 0xE0, 0xFF, 0xA3, 0xE0, 0x90, 0x10, 0x4C, 0xCF, 0xF0,
-0xA3, 0xEF, 0xF0, 0x80, 0x07, 0xE4, 0x90, 0x10, 0x4C, 0xF0, 0xA3, 0xF0, 0x02, 0x33, 0xF6, 0x90,
-0x10, 0x3D, 0xE0, 0x12, 0x28, 0x7E, 0x35, 0x12, 0x01, 0x35, 0x12, 0x05, 0x35, 0x12, 0x07, 0x35,
-0x12, 0x09, 0x35, 0x15, 0x0B, 0x35, 0x12, 0x0C, 0x35, 0x1B, 0x0D, 0x35, 0x21, 0x0F, 0x00, 0x00,
-0x35, 0x5C, 0x02, 0x33, 0xF6, 0xE4, 0x90, 0x10, 0x3D, 0xF0, 0x22, 0xE4, 0x90, 0x10, 0x3D, 0xF0,
-0x22, 0x90, 0x10, 0x50, 0xE0, 0xFF, 0xB4, 0x01, 0x07, 0x90, 0x06, 0x07, 0x74, 0x20, 0xF0, 0x22,
-0xEF, 0xB4, 0x02, 0x07, 0x90, 0x06, 0x07, 0x74, 0x40, 0xF0, 0x22, 0xEF, 0xB4, 0x03, 0x07, 0x90,
-0x06, 0x07, 0x74, 0x60, 0xF0, 0x22, 0xEF, 0xB4, 0x04, 0x07, 0x90, 0x06, 0x07, 0x74, 0x80, 0xF0,
-0x22, 0xEF, 0xB4, 0x05, 0x0C, 0x90, 0x06, 0x07, 0x74, 0xA0, 0xF0, 0x22, 0xE4, 0x90, 0x10, 0x3D,
-0xF0, 0x22, 0x78, 0x7F, 0xE4, 0xF6, 0xD8, 0xFD, 0x75, 0x81, 0x20, 0x02, 0x35, 0xA9, 0x02, 0x23,
-0x50, 0xE4, 0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0x40, 0x03, 0xF6, 0x80, 0x01, 0xF2, 0x08, 0xDF,
-0xF4, 0x80, 0x29, 0xE4, 0x93, 0xA3, 0xF8, 0x54, 0x07, 0x24, 0x0C, 0xC8, 0xC3, 0x33, 0xC4, 0x54,
-0x0F, 0x44, 0x20, 0xC8, 0x83, 0x40, 0x04, 0xF4, 0x56, 0x80, 0x01, 0x46, 0xF6, 0xDF, 0xE4, 0x80,
-0x0B, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x3E, 0x45, 0xE4, 0x7E, 0x01, 0x93,
-0x60, 0xBC, 0xA3, 0xFF, 0x54, 0x3F, 0x30, 0xE5, 0x09, 0x54, 0x1F, 0xFE, 0xE4, 0x93, 0xA3, 0x60,
-0x01, 0x0E, 0xCF, 0x54, 0xC0, 0x25, 0xE0, 0x60, 0xA8, 0x40, 0xB8, 0xE4, 0x93, 0xA3, 0xFA, 0xE4,
-0x93, 0xA3, 0xF8, 0xE4, 0x93, 0xA3, 0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xF0, 0xA3,
-0xC8, 0xC5, 0x82, 0xC8, 0xCA, 0xC5, 0x83, 0xCA, 0xDF, 0xE9, 0xDE, 0xE7, 0x80, 0xBE, 0xAC, 0x07,
-0xD2, 0x02, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xF0, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83,
-0xE0, 0xFD, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xEF, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83,
-0xE0, 0xFB, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xEE, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83,
-0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0xEC, 0x75,
-0xF0, 0x03, 0xA4, 0x24, 0x98, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFD, 0xEC, 0x75,
-0xF0, 0x03, 0xA4, 0x24, 0x97, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFB, 0xEC, 0x75,
-0xF0, 0x03, 0xA4, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44,
-0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB,
-0xFD, 0x7F, 0xC8, 0x12, 0x3D, 0x90, 0xA2, 0x02, 0x22, 0xAC, 0x07, 0xD2, 0x02, 0xEC, 0x75, 0xF0,
-0x03, 0xA4, 0x24, 0xF0, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFD, 0xEC, 0x75, 0xF0,
-0x03, 0xA4, 0x24, 0xEF, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFB, 0xEC, 0x75, 0xF0,
-0x03, 0xA4, 0x24, 0xEE, 0xF5, 0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0,
-0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x98,
-0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFD, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x97,
-0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0xFB, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x96,
-0xF5, 0x82, 0xE4, 0x34, 0x41, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C,
-0x90, 0x82, 0x02, 0x92, 0x02, 0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0xC8, 0x12, 0x3D,
-0x90, 0xA2, 0x02, 0x22, 0xAC, 0x07, 0xD2, 0x02, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xF0, 0xF5,
-0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFD, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xEF, 0xF5,
-0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0xFB, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0xEE, 0xF5,
-0x82, 0xE4, 0x34, 0x40, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90,
-0x82, 0x02, 0x92, 0x02, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x98, 0xF5, 0x82, 0xE4, 0x34, 0x41,
-0xF5, 0x83, 0xE0, 0xFD, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x97, 0xF5, 0x82, 0xE4, 0x34, 0x41,
-0xF5, 0x83, 0xE0, 0xFB, 0xEC, 0x75, 0xF0, 0x03, 0xA4, 0x24, 0x96, 0xF5, 0x82, 0xE4, 0x34, 0x41,
-0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x02, 0x92, 0x02,
-0xE4, 0x90, 0x45, 0x44, 0xF0, 0xFB, 0xFD, 0x7F, 0xC8, 0x12, 0x3D, 0x90, 0xA2, 0x02, 0x22, 0xD2,
-0x01, 0xE4, 0x90, 0x04, 0x78, 0xF0, 0xA3, 0x74, 0x1B, 0xF0, 0x90, 0x04, 0x78, 0x74, 0x05, 0xF0,
-0xE4, 0x90, 0x45, 0x3E, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x3E, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3,
-0x94, 0x0B, 0xEE, 0x64, 0x80, 0x94, 0x80, 0x50, 0x57, 0x90, 0x42, 0xEB, 0x75, 0xF0, 0x03, 0xEF,
-0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0xFD, 0x90, 0x42,
-0xEA, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5,
-0x83, 0xE0, 0xFB, 0x90, 0x42, 0xE9, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0,
-0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90,
-0x82, 0x01, 0x92, 0x01, 0x90, 0x45, 0x3E, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x80, 0x97,
-0x90, 0x04, 0x62, 0x74, 0xC0, 0xF0, 0xA2, 0x01, 0x22, 0xD2, 0x01, 0xE4, 0x90, 0x04, 0x78, 0xF0,
-0xA3, 0x74, 0x1B, 0xF0, 0x90, 0x04, 0x78, 0x74, 0x05, 0xF0, 0xE4, 0x90, 0x45, 0x3E, 0xF0, 0xA3,
-0xF0, 0x90, 0x45, 0x3E, 0xE0, 0xFE, 0xA3, 0xE0, 0xFF, 0xC3, 0x94, 0x0D, 0xEE, 0x64, 0x80, 0x94,
-0x80, 0x50, 0x57, 0x90, 0x42, 0xEB, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0,
-0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0xFD, 0x90, 0x42, 0xEA, 0x75, 0xF0, 0x03, 0xEF, 0x12,
-0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0xFB, 0x90, 0x42, 0xE9,
-0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83,
-0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9, 0x12, 0x3C, 0x90, 0x82, 0x01, 0x92, 0x01, 0x90, 0x45,
-0x3E, 0xE4, 0x75, 0xF0, 0x01, 0x12, 0x26, 0xB0, 0x80, 0x97, 0x90, 0x04, 0x62, 0x74, 0xC0, 0xF0,
-0xA2, 0x01, 0x22, 0xD2, 0x01, 0xE4, 0x90, 0x04, 0x78, 0xF0, 0xA3, 0x74, 0x1B, 0xF0, 0x90, 0x04,
-0x78, 0x74, 0x05, 0xF0, 0xE4, 0x90, 0x45, 0x3E, 0xF0, 0xA3, 0xF0, 0x90, 0x45, 0x3E, 0xE0, 0xFE,
-0xA3, 0xE0, 0xFF, 0xC3, 0x94, 0x0F, 0xEE, 0x64, 0x80, 0x94, 0x80, 0x50, 0x57, 0x90, 0x42, 0xEB,
-0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83,
-0xE0, 0xFD, 0x90, 0x42, 0xEA, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27, 0x8E, 0xEE, 0x75, 0xF0, 0x03,
-0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0xFB, 0x90, 0x42, 0xE9, 0x75, 0xF0, 0x03, 0xEF, 0x12, 0x27,
-0x8E, 0xEE, 0x75, 0xF0, 0x03, 0xA4, 0x25, 0x83, 0xF5, 0x83, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F,
-0xB9, 0x12, 0x3C, 0x90, 0x82, 0x01, 0x92, 0x01, 0x90, 0x45, 0x3E, 0xE4, 0x75, 0xF0, 0x01, 0x12,
-0x26, 0xB0, 0x80, 0x97, 0x90, 0x04, 0x62, 0x74, 0xC0, 0xF0, 0xA2, 0x01, 0x22, 0x90, 0x45, 0x3E,
-0xED, 0xF0, 0xD2, 0x01, 0x90, 0x04, 0x57, 0xE0, 0x90, 0x45, 0x3F, 0xF0, 0x90, 0x04, 0x57, 0xE0,
-0x54, 0xFE, 0xF0, 0xEF, 0x12, 0x28, 0x7E, 0x39, 0x60, 0x03, 0x39, 0x78, 0x09, 0x39, 0x6C, 0x0A,
-0x39, 0x78, 0x0C, 0x39, 0x84, 0x0D, 0x39, 0x60, 0x0E, 0x39, 0x90, 0x0F, 0x00, 0x00, 0x39, 0x9C,
-0x90, 0x45, 0x3E, 0xE0, 0xFF, 0x12, 0x35, 0xEE, 0x92, 0x01, 0x80, 0x32, 0x90, 0x45, 0x3E, 0xE0,
-0xFF, 0x12, 0x32, 0x3A, 0x92, 0x01, 0x80, 0x26, 0x90, 0x45, 0x3E, 0xE0, 0xFF, 0x12, 0x36, 0x79,
-0x92, 0x01, 0x80, 0x1A, 0x90, 0x45, 0x3E, 0xE0, 0xFF, 0x12, 0x37, 0x04, 0x92, 0x01, 0x80, 0x0E,
-0x90, 0x45, 0x3E, 0xE0, 0xFF, 0x12, 0x2E, 0xDF, 0x92, 0x01, 0x80, 0x02, 0xC2, 0x01, 0x12, 0x3D,
-0xE2, 0x90, 0x45, 0x3F, 0xE0, 0x90, 0x04, 0x57, 0xF0, 0x90, 0x45, 0x3E, 0xE0, 0x90, 0x40, 0xC0,
-0xF0, 0xA2, 0x01, 0x22, 0xAC, 0x07, 0xE4, 0x90, 0x45, 0x3A, 0xF0, 0xA3, 0xF0, 0xD2, 0x00, 0x7D,
-0x03, 0xEC, 0x70, 0x13, 0x12, 0x3C, 0xC5, 0x90, 0x45, 0x3B, 0xE0, 0x54, 0xF9, 0xFF, 0xF0, 0xFD,
-0x7F, 0x09, 0x12, 0x3D, 0x00, 0x80, 0x59, 0xEC, 0xB4, 0x01, 0x16, 0x12, 0x3C, 0xC5, 0x90, 0x45,
-0x3B, 0xE0, 0x54, 0xFD, 0xF0, 0x44, 0x04, 0xFF, 0xF0, 0xFD, 0x7F, 0x09, 0x12, 0x3D, 0x00, 0x80,
-0x3F, 0xEC, 0xB4, 0x02, 0x1B, 0x7B, 0x01, 0x7A, 0x45, 0x79, 0x3A, 0x7F, 0x0A, 0x12, 0x3C, 0xCD,
-0x90, 0x45, 0x3A, 0xE0, 0x54, 0xFC, 0xFF, 0xF0, 0xFD, 0x7F, 0x0A, 0x12, 0x3D, 0x00, 0x80, 0x20,
-0xEC, 0xB4, 0x03, 0x1C, 0x7B, 0x01, 0x7A, 0x45, 0x79, 0x3A, 0x7F, 0x0A, 0x12, 0x3C, 0xCD, 0x90,
-0x45, 0x3A, 0xE0, 0x54, 0xFE, 0xF0, 0x44, 0x02, 0xFF, 0xF0, 0xFD, 0x7F, 0x0A, 0x12, 0x3D, 0x00,
-0xA2, 0x00, 0x22, 0x90, 0x45, 0x38, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0x90, 0x04, 0x0B, 0xE0, 0xF9,
-0x54, 0xFB, 0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x09, 0x74, 0x50, 0xF0, 0x90, 0x45, 0x38, 0xE0,
-0x90, 0x04, 0x0A, 0xF0, 0x90, 0x45, 0x39, 0xE0, 0x90, 0x04, 0x0E, 0xF0, 0x90, 0x04, 0x08, 0x74,
-0x80, 0xF0, 0xE4, 0xFD, 0xFC, 0x90, 0x04, 0x08, 0xE0, 0x90, 0x45, 0x3A, 0xF0, 0xE0, 0x54, 0x03,
-0x70, 0x0B, 0x0D, 0xBD, 0x00, 0x01, 0x0C, 0xBC, 0x07, 0xEB, 0xBD, 0xFF, 0xE8, 0xC3, 0xED, 0x94,
-0xFF, 0xEC, 0x94, 0x07, 0x50, 0x07, 0x90, 0x45, 0x3A, 0xE0, 0x30, 0xE1, 0x0B, 0x0F, 0xBF, 0x00,
-0x01, 0x0E, 0xBE, 0x07, 0xB1, 0xBF, 0xFF, 0xAE, 0xBE, 0x07, 0x0A, 0xBF, 0xFF, 0x07, 0x90, 0x04,
-0x0B, 0xE9, 0xF0, 0xC3, 0x22, 0xAF, 0x01, 0x90, 0x04, 0x0B, 0xE9, 0xF0, 0xD3, 0x22, 0x90, 0x45,
-0x35, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0xEE, 0x70, 0x56, 0xEF, 0x24, 0xF6, 0x60, 0x1B, 0x14, 0x60,
-0x26, 0x14, 0x60, 0x31, 0x14, 0x60, 0x3C, 0x24, 0x04, 0x70, 0x44, 0x7B, 0x01, 0x7A, 0x42, 0x79,
-0xE9, 0x90, 0x45, 0x37, 0x12, 0x27, 0xBA, 0x80, 0x36, 0x7B, 0x01, 0x7A, 0x40, 0x79, 0xC1, 0x90,
-0x45, 0x37, 0x12, 0x27, 0xBA, 0x80, 0x28, 0x7B, 0x01, 0x7A, 0x40, 0x79, 0xF1, 0x90, 0x45, 0x37,
-0x12, 0x27, 0xBA, 0x80, 0x1A, 0x7B, 0x01, 0x7A, 0x41, 0x79, 0x99, 0x90, 0x45, 0x37, 0x12, 0x27,
-0xBA, 0x80, 0x0C, 0x7B, 0x01, 0x7A, 0x42, 0x79, 0x41, 0x90, 0x45, 0x37, 0x12, 0x27, 0xBA, 0x90,
-0x45, 0x36, 0xE0, 0xFF, 0xA3, 0x12, 0x27, 0x9A, 0x90, 0x45, 0x35, 0xE0, 0xF5, 0x82, 0x75, 0x83,
-0x00, 0xEF, 0x02, 0x26, 0x8E, 0x90, 0x45, 0x3F, 0xEF, 0xF0, 0xA3, 0x74, 0xFF, 0xF0, 0x90, 0x04,
-0x0B, 0xE0, 0x90, 0x45, 0x41, 0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x09, 0x74, 0x50, 0xF0, 0x90,
-0x45, 0x3F, 0xE0, 0x90, 0x04, 0x0A, 0xF0, 0x90, 0x04, 0x08, 0x74, 0x40, 0xF0, 0xE4, 0xFD, 0xFC,
-0x90, 0x04, 0x08, 0xE0, 0xF9, 0x54, 0x03, 0x70, 0x0B, 0x0D, 0xBD, 0x00, 0x01, 0x0C, 0xBC, 0x07,
-0xEF, 0xBD, 0xFF, 0xEC, 0xC3, 0xED, 0x94, 0xFF, 0xEC, 0x94, 0x07, 0x50, 0x04, 0xE9, 0x30, 0xE1,
-0x0B, 0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xBE, 0x07, 0xC0, 0xBF, 0xFF, 0xBD, 0x90, 0x04, 0x0C, 0xE0,
-0x90, 0x45, 0x40, 0xF0, 0xA3, 0xE0, 0x90, 0x04, 0x0B, 0xF0, 0x90, 0x45, 0x40, 0xE0, 0xFF, 0x22,
-0xE4, 0xFE, 0xEF, 0x30, 0xE5, 0x11, 0xE4, 0xFC, 0xFD, 0x7C, 0x08, 0x90, 0x04, 0xD4, 0xE4, 0xF0,
-0xA3, 0xDC, 0xFC, 0x7C, 0x00, 0x7D, 0x08, 0xEF, 0x54, 0xC0, 0x60, 0x12, 0xE4, 0xFC, 0xFD, 0x7C,
-0x08, 0x90, 0x04, 0xD4, 0x74, 0xFF, 0xF0, 0xA3, 0xDC, 0xFC, 0x7C, 0x00, 0x7D, 0x08, 0xEF, 0x30,
-0xE6, 0x07, 0xEE, 0x44, 0x78, 0xFE, 0x54, 0xFE, 0xFE, 0xEF, 0x54, 0x88, 0x60, 0x04, 0xEE, 0x44,
-0x08, 0xFE, 0xEF, 0x30, 0xE4, 0x04, 0xEE, 0x44, 0x10, 0xFE, 0xEF, 0x30, 0xE1, 0x04, 0xEE, 0x44,
-0x02, 0xFE, 0x90, 0x04, 0x56, 0xE0, 0xFF, 0x6E, 0x60, 0x02, 0xEE, 0xF0, 0x22, 0xC0, 0xE0, 0xC0,
-0x83, 0xC0, 0x82, 0xC0, 0xD0, 0x75, 0xD0, 0x00, 0xC0, 0x07, 0xD2, 0x05, 0x53, 0xA8, 0xFE, 0x90,
-0x06, 0x20, 0xE4, 0xF0, 0x90, 0x04, 0x58, 0xF0, 0xA3, 0xF0, 0x90, 0x06, 0x21, 0xE0, 0xFF, 0x90,
-0x10, 0x39, 0xE0, 0x4F, 0xF0, 0x90, 0x06, 0x21, 0xEF, 0xF0, 0x90, 0x04, 0x5C, 0xE0, 0xFF, 0x90,
-0x45, 0x46, 0xE0, 0x4F, 0xF0, 0x90, 0x04, 0x5C, 0xEF, 0xF0, 0xA3, 0xE0, 0xFF, 0x90, 0x45, 0x47,
-0xE0, 0x4F, 0xF0, 0x90, 0x04, 0x5D, 0xEF, 0xF0, 0xD0, 0x07, 0xD0, 0xD0, 0xD0, 0x82, 0xD0, 0x83,
-0xD0, 0xE0, 0x32, 0x90, 0x04, 0x79, 0x74, 0x11, 0xF0, 0x12, 0x3D, 0x31, 0xE4, 0x90, 0x45, 0x3E,
-0xF0, 0x90, 0x45, 0x3E, 0xE0, 0xFF, 0xC3, 0x94, 0x06, 0x50, 0x1A, 0x12, 0x3B, 0x25, 0x90, 0x45,
-0x3E, 0xE0, 0x24, 0xC4, 0xF5, 0x82, 0xE4, 0x34, 0x04, 0xF5, 0x83, 0xEF, 0xF0, 0x90, 0x45, 0x3E,
-0xE0, 0x04, 0xF0, 0x80, 0xDC, 0x90, 0x04, 0x48, 0x74, 0x02, 0xF0, 0x14, 0xF0, 0x7F, 0x30, 0x12,
-0x3B, 0x90, 0x90, 0x04, 0x54, 0x74, 0x02, 0xF0, 0x22, 0xE0, 0x90, 0x45, 0x44, 0xF0, 0x7F, 0xB9,
-0x90, 0x04, 0x71, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x45, 0x44, 0xE0, 0x90, 0x04, 0x73, 0xF0,
-0x90, 0x04, 0x70, 0xEF, 0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x70, 0xE0, 0xFD, 0x20, 0xE2, 0x0B,
-0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xBE, 0x07, 0xF0, 0xBF, 0xFF, 0xED, 0xBE, 0x07, 0x05, 0xBF, 0xFF,
-0x02, 0xC3, 0x22, 0xD3, 0x22, 0x7B, 0x01, 0x7A, 0x45, 0x79, 0x3B, 0x7F, 0x09, 0x90, 0x04, 0x6E,
-0xEF, 0xF0, 0x90, 0x04, 0x6C, 0xE0, 0x44, 0x02, 0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x6C, 0xE0,
-0xFD, 0x20, 0xE2, 0x0B, 0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xBE, 0x07, 0xF0, 0xBF, 0xFF, 0xED, 0x90,
-0x04, 0x6F, 0xE0, 0x12, 0x26, 0x7C, 0xBE, 0x07, 0x05, 0xBF, 0xFF, 0x02, 0xC3, 0x22, 0xD3, 0x22,
-0x90, 0x04, 0x6E, 0xEF, 0xF0, 0x90, 0x04, 0x6F, 0xED, 0xF0, 0x90, 0x04, 0x6C, 0xE0, 0x44, 0x01,
-0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x6C, 0xE0, 0xFD, 0x20, 0xE2, 0x0B, 0x0F, 0xBF, 0x00, 0x01,
-0x0E, 0xBE, 0x07, 0xF0, 0xBF, 0xFF, 0xED, 0xBE, 0x07, 0x05, 0xBF, 0xFF, 0x02, 0xC3, 0x22, 0xD3,
-0x22, 0x90, 0x04, 0x54, 0x74, 0x01, 0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x54, 0xE0, 0xFD, 0x30,
-0xE0, 0x0B, 0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xBE, 0x07, 0xF0, 0xBF, 0xFF, 0xED, 0xBE, 0x07, 0x05,
-0xBF, 0xFF, 0x02, 0xC3, 0x22, 0x90, 0x06, 0x38, 0xE0, 0x44, 0x02, 0xF0, 0xE0, 0x44, 0x01, 0xF0,
-0xD3, 0x22, 0xEF, 0x12, 0x28, 0x7E, 0x3D, 0x7F, 0x03, 0x3D, 0x85, 0x09, 0x3D, 0x82, 0x0A, 0x3D,
-0x85, 0x0C, 0x3D, 0x88, 0x0D, 0x3D, 0x7F, 0x0E, 0x3D, 0x8B, 0x0F, 0x00, 0x00, 0x3D, 0x8E, 0x02,
-0x31, 0x47, 0x02, 0x30, 0x1A, 0x02, 0x37, 0x8F, 0x02, 0x38, 0x19, 0x02, 0x38, 0xA3, 0xC3, 0x22,
-0x90, 0x04, 0x1C, 0xEF, 0xF0, 0xA3, 0xED, 0xF0, 0xA3, 0xEB, 0xF0, 0x90, 0x45, 0x44, 0xE0, 0x90,
-0x04, 0x1F, 0xF0, 0x90, 0x04, 0x18, 0x74, 0x03, 0xF0, 0x90, 0x04, 0x18, 0xE0, 0xFF, 0x60, 0x04,
-0xEF, 0x30, 0xE2, 0xF5, 0xE4, 0x90, 0x04, 0x18, 0xF0, 0x22, 0x7F, 0xFF, 0x90, 0x04, 0x14, 0xE0,
-0xFF, 0x14, 0x60, 0x0E, 0x14, 0x60, 0x0F, 0x14, 0x60, 0x10, 0x24, 0x03, 0x70, 0x10, 0x02, 0x0B,
-0xBE, 0x22, 0x02, 0x0B, 0xB5, 0x22, 0x02, 0x0B, 0xAE, 0x22, 0x02, 0x0B, 0xEF, 0x22, 0x02, 0x00,
-0x00, 0x22, 0xD2, 0x02, 0x7D, 0x40, 0x7F, 0x50, 0x12, 0x3D, 0x00, 0xE4, 0xFD, 0x7F, 0x50, 0x12,
-0x3D, 0x00, 0x7D, 0x01, 0x7F, 0x9C, 0x12, 0x3D, 0x00, 0xE4, 0xFD, 0x7F, 0x9C, 0x12, 0x3D, 0x00,
-0xA2, 0x02, 0x22, 0x90, 0x04, 0x61, 0xE0, 0x54, 0xFE, 0xF0, 0xE4, 0xFF, 0xFE, 0x90, 0x04, 0x61,
-0xE0, 0xFD, 0x20, 0xE5, 0x0B, 0x0F, 0xBF, 0x00, 0x01, 0x0E, 0xBE, 0x07, 0xF0, 0xBF, 0xFF, 0xED,
-0x22, 0xC0, 0xE0, 0xC0, 0x83, 0xC0, 0x82, 0xC2, 0x8C, 0x90, 0x43, 0x19, 0x74, 0x01, 0xF0, 0xD0,
-0x82, 0xD0, 0x83, 0xD0, 0xE0, 0x32, 0xC2, 0x8C, 0x75, 0x89, 0x01, 0x75, 0x8C, 0xF9, 0x75, 0x8A,
-0x7E, 0x43, 0xA8, 0x02, 0x22, 0x44, 0x43, 0x1A, 0x04, 0x03, 0x09, 0x04, 0x00,
-};
-
 /*---------------------  Export Functions  --------------------------*/
 
 
@@ -773,50 +61,60 @@ FIRMWAREbDownload(
      PSDevice pDevice
     )
 {
-    int NdisStatus;
-    PBYTE       pBuffer = NULL;
-    WORD        wLength;
-    int         ii;
-
-    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n");
-    spin_unlock_irq(&pDevice->lock);
-    pBuffer = kmalloc(sizeof(abyFirmware), GFP_KERNEL);
-    if (pBuffer != NULL) {
-
-        for (ii=0;ii<sizeof(abyFirmware);ii++)
-            pBuffer[ii] = abyFirmware[ii];
-
-        for (ii=0;ii<sizeof(abyFirmware);ii+=0x400) {
-
-            if ((sizeof(abyFirmware) - ii) < 0x400)
-                wLength = (sizeof(abyFirmware) - ii);
-            else
-                wLength = 0x400;
-
-            NdisStatus = CONTROLnsRequestOutAsyn(pDevice,
+	const struct firmware *fw;
+	int NdisStatus;
+	void *pBuffer = NULL;
+	BOOL result = FALSE;
+	u16 wLength;
+	int ii;
+
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n");
+	spin_unlock_irq(&pDevice->lock);
+
+	if (!pDevice->firmware) {
+		struct device *dev = &pDevice->usb->dev;
+		int rc;
+
+		rc = request_firmware(&pDevice->firmware, FIRMWARE_NAME, dev);
+		if (rc) {
+			dev_err(dev, "firmware file %s request failed (%d)\n",
+				FIRMWARE_NAME, rc);
+			goto out;
+		}
+	}
+	fw = pDevice->firmware;
+
+	pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
+	if (!pBuffer)
+		goto out;
+
+	for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
+		wLength = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
+		memcpy(pBuffer, fw->data + ii, wLength);
+
+		NdisStatus = CONTROLnsRequestOutAsyn(pDevice,
                                             0,
                                             0x1200+ii,
                                             0x0000,
                                             wLength,
-                                            &(pBuffer[ii])
+                                            pBuffer
                                             );
 
-            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Download firmware...%d %zu\n", ii, sizeof(abyFirmware));
-            if (NdisStatus != STATUS_SUCCESS) {
-                if (pBuffer)
-                    kfree(pBuffer);
-                spin_lock_irq(&pDevice->lock);
-		return FALSE;
-            }
+		DBG_PRT(MSG_LEVEL_DEBUG,
+			KERN_INFO"Download firmware...%d %zu\n", ii, fw->size);
+		if (NdisStatus != STATUS_SUCCESS)
+			goto out;
         }
-    }
 
-    if (pBuffer)
-        kfree(pBuffer);
+	result = TRUE;
+
+out:
+	kfree(pBuffer);
 
-    spin_lock_irq(&pDevice->lock);
-    return (TRUE);
+	spin_lock_irq(&pDevice->lock);
+	return result;
 }
+MODULE_FIRMWARE(FIRMWARE_NAME);
 
 BOOL
 FIRMWAREbBrach2Sram(
@@ -867,7 +165,7 @@ FIRMWAREbCheckVersion(
         return FALSE;
     }
     DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Firmware Version [%04x]\n", pDevice->wFirmwareVersion);
-    if (pDevice->wFirmwareVersion != FIRMWARE_VERSION) {
+    if (pDevice->wFirmwareVersion < FIRMWARE_VERSION) {
         // branch to loader for download new firmware
         FIRMWAREbBrach2Sram(pDevice);
         return FALSE;
diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c
index f70e922..51b5adf 100644
--- a/drivers/staging/vt6656/hostap.c
+++ b/drivers/staging/vt6656/hostap.c
@@ -858,8 +858,7 @@ int vt6656_hostap_ioctl(PSDevice pDevice, struct iw_point *p)
 	}
 
  out:
-	if (param != NULL)
-		kfree(param);
+	kfree(param);
 
 	return ret;
 }
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 7cc3d24..af14ab0 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -837,8 +837,7 @@ static void device_free_tx_bufs(PSDevice pDevice)
             usb_kill_urb(pTxContext->pUrb);
             usb_free_urb(pTxContext->pUrb);
         }
-        if (pTxContext)
-            kfree(pTxContext);
+        kfree(pTxContext);
     }
     return;
 }
@@ -861,8 +860,7 @@ static void device_free_rx_bufs(PSDevice pDevice)
         if (pRCB->skb)
             dev_kfree_skb(pRCB->skb);
     }
-    if (pDevice->pRCBMem)
-        kfree(pDevice->pRCBMem);
+    kfree(pDevice->pRCBMem);
 
     return;
 }
@@ -878,8 +876,7 @@ static void usb_device_reset(PSDevice pDevice)
 
 static void device_free_int_bufs(PSDevice pDevice)
 {
-    if (pDevice->intBuf.pDataBuf != NULL)
-        kfree(pDevice->intBuf.pDataBuf);
+    kfree(pDevice->intBuf.pDataBuf);
     return;
 }
 
@@ -1272,6 +1269,9 @@ static void __devexit vt6656_disconnect(struct usb_interface *intf)
 
 	device_release_WPADEV(device);
 
+	if (device->firmware)
+		release_firmware(device->firmware);
+
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
 
@@ -1454,7 +1454,7 @@ static unsigned char *Config_FileOperation(PSDevice pDevice)
 
     buffer = kmalloc(1024, GFP_KERNEL);
     if(buffer==NULL) {
-      printk("alllocate mem for file fail?\n");
+      printk("allocate mem for file fail?\n");
       result = -1;
       goto error1;
     }
@@ -1477,8 +1477,7 @@ error2:
   */
 
 if(result!=0) {
-    if(buffer)
-  	 kfree(buffer);
+    kfree(buffer);
     buffer=NULL;
 }
   return buffer;
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
index e8c1b35..b313677 100644
--- a/drivers/staging/vt6656/power.c
+++ b/drivers/staging/vt6656/power.c
@@ -53,14 +53,14 @@
 /*---------------------  Static Classes  ----------------------------*/
 
 /*---------------------  Static Variables  --------------------------*/
-static int          msglevel                =MSG_LEVEL_INFO;
+static int msglevel = MSG_LEVEL_INFO;
 /*---------------------  Static Functions  --------------------------*/
 
 /*---------------------  Export Variables  --------------------------*/
 
 /*---------------------  Export Functions  --------------------------*/
 
-/*+
+/*
  *
  * Routine Description:
  * Enable hw power saving functions
@@ -68,69 +68,65 @@ static int          msglevel                =MSG_LEVEL_INFO;
  * Return Value:
  *    None.
  *
--*/
+ */
 
 void PSvEnablePowerSaving(void *hDeviceContext,
 			  WORD wListenInterval)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
-    WORD            wAID = pMgmt->wCurrAID | BIT14 | BIT15;
+	PSDevice pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	WORD wAID = pMgmt->wCurrAID | BIT14 | BIT15;
+
+	/* set period of power up before TBTT */
+	MACvWriteWord(pDevice, MAC_REG_PWBT, C_PWBT);
 
-    /* set period of power up before TBTT */
-    MACvWriteWord(pDevice, MAC_REG_PWBT, C_PWBT);
+	if (pDevice->eOPMode != OP_MODE_ADHOC) {
+		/* set AID */
+		MACvWriteWord(pDevice, MAC_REG_AIDATIM, wAID);
+	} else {
+		/* set ATIM Window */
+		/* MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow); */
+	}
 
-    if (pDevice->eOPMode != OP_MODE_ADHOC) {
-	/* set AID */
-	MACvWriteWord(pDevice, MAC_REG_AIDATIM, wAID);
-    } else {
-    	// set ATIM Window
-        //MACvWriteATIMW(pDevice->PortOffset, pMgmt->wCurrATIMWindow);
-    }
+	/* Warren:06-18-2004,the sequence must follow PSEN->AUTOSLEEP->GO2DOZE */
+	/* enable power saving hw function */
+	MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN);
 
-    //Warren:06-18-2004,the sequence must follow PSEN->AUTOSLEEP->GO2DOZE
-    // enable power saving hw function
-    MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN);
-    // Set AutoSleep
-    MACvRegBitsOn(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
+	/* Set AutoSleep */
+	MACvRegBitsOn(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
 
-    //Warren:MUST turn on this once before turn on AUTOSLEEP ,or the AUTOSLEEP doesn't work
-    MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE);
+	/* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the AUTOSLEEP doesn't work */
+	MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE);
 
+	if (wListenInterval >= 2) {
 
-    if (wListenInterval >= 2) {
+		/* clear always listen beacon */
+		MACvRegBitsOff(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
 
-        // clear always listen beacon
-        MACvRegBitsOff(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
-        // first time set listen next beacon
-        MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
+		/* first time set listen next beacon */
+		MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
 
-        pMgmt->wCountToWakeUp = wListenInterval;
+		pMgmt->wCountToWakeUp = wListenInterval;
 
-    }
-    else {
+	} else {
 
-        // always listen beacon
-        MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
-        pMgmt->wCountToWakeUp = 0;
+		/* always listen beacon */
+		MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
 
-    }
+		pMgmt->wCountToWakeUp = 0;
+	}
 
-    pDevice->bEnablePSMode = TRUE;
+	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. */
+	if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)
+		PSbSendNullPacket(pDevice);
+
+	pDevice->bPWBitOn = TRUE;
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "PS:Power Saving Mode Enable...\n");
 }
 
-/*+
+/*
  *
  * Routine Description:
  * Disable hw power saving functions
@@ -138,39 +134,31 @@ void PSvEnablePowerSaving(void *hDeviceContext,
  * Return Value:
  *    None.
  *
--*/
+ */
 
 void PSvDisablePowerSaving(void *hDeviceContext)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-//    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
+	PSDevice pDevice = (PSDevice)hDeviceContext;
+	/* PSMgmtObject pMgmt = &(pDevice->sMgmtObj); */
 
+	/* disable power saving hw function */
+	CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_DISABLE_PS, 0,
+						0, 0, NULL);
 
-    // disable power saving hw function
-    CONTROLnsRequestOut(pDevice,
-                        MESSAGE_TYPE_DISABLE_PS,
-                        0,
-                        0,
-                        0,
-                        NULL
-                        );
+	/* clear AutoSleep */
+	MACvRegBitsOff(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
 
-    //clear AutoSleep
-    MACvRegBitsOff(pDevice, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
+	/* set always listen beacon */
+	MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
+	pDevice->bEnablePSMode = FALSE;
 
-    // set always listen beacon
-    MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_ALBCN);
+	if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE)
+		PSbSendNullPacket(pDevice);
 
-    pDevice->bEnablePSMode = FALSE;
-
-    if (pDevice->eOPMode == OP_MODE_INFRASTRUCTURE) {
-        PSbSendNullPacket(pDevice);
-    }
-    pDevice->bPWBitOn = FALSE;
-    return;
+	pDevice->bPWBitOn = FALSE;
 }
 
-/*+
+/*
  *
  * Routine Description:
  * Consider to power down when no more packets to tx or rx.
@@ -178,55 +166,56 @@ void PSvDisablePowerSaving(void *hDeviceContext)
  * Return Value:
  *    TRUE, if power down success
  *    FALSE, if fail
--*/
+ */
 
 BOOL PSbConsiderPowerDown(void *hDeviceContext,
 			  BOOL bCheckRxDMA,
 			  BOOL bCheckCountToWakeUp)
 {
-    PSDevice        pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
-    BYTE            byData;
-
-
-    // check if already in Doze mode
-    ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PSCTL, &byData);
-    if ( (byData & PSCTL_PS) != 0 )
-        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;
-
-    //Tx Burst
-    if ( pDevice->bPSModeTxBurst )
-        return FALSE;
-
-    // Froce PSEN on
-    MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN);
-
-    if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
-        if (bCheckCountToWakeUp &&
-            (pMgmt->wCountToWakeUp == 0 || pMgmt->wCountToWakeUp == 1)) {
-             return FALSE;
-        }
-    }
-
-    pDevice->bPSRxBeacon = TRUE;
-    // no Tx, no Rx isr, now go to Doze
-    MACvRegBitsOn(pDevice, 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->sMgmtObj);
+	BYTE byData;
+
+	/* check if already in Doze mode */
+	ControlvReadByte(pDevice, MESSAGE_REQUEST_MACREG,
+					MAC_REG_PSCTL, &byData);
+
+	if ((byData & PSCTL_PS) != 0)
+		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;
+
+	/* Tx Burst */
+	if (pDevice->bPSModeTxBurst)
+		return FALSE;
+
+	/* Froce PSEN on */
+	MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_PSEN);
+
+	if (pMgmt->eCurrMode != WMAC_MODE_IBSS_STA) {
+		if (bCheckCountToWakeUp && (pMgmt->wCountToWakeUp == 0
+			|| pMgmt->wCountToWakeUp == 1)) {
+				return FALSE;
+		}
+	}
+
+	pDevice->bPSRxBeacon = TRUE;
+
+	/* no Tx, no Rx isr, now go to Doze */
+	MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_GO2DOZE);
+	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Go to Doze ZZZZZZZZZZZZZZZ\n");
+	return TRUE;
 }
 
-/*+
+/*
  *
  * Routine Description:
  * Send PS-POLL packet
@@ -234,41 +223,37 @@ BOOL PSbConsiderPowerDown(void *hDeviceContext,
  * Return Value:
  *    None.
  *
--*/
+ */
 
 void PSvSendPSPOLL(void *hDeviceContext)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    PSTxMgmtPacket      pTxPacket = NULL;
-
-
-    memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN);
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)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;
+	PSDevice pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	PSTxMgmtPacket pTxPacket = NULL;
+
+	memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_HDR_ADDR2_LEN);
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)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;
+
+	/* log failure if sending failed */
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send PS-Poll packet failed..\n");
+	}
 }
 
-/*+
+/*
  *
  * Routine Description:
  * Send NULL packet to AP for notification power state of STA
@@ -276,70 +261,54 @@ void PSvSendPSPOLL(void *hDeviceContext)
  * Return Value:
  *    None.
  *
--*/
+ */
 
 BOOL PSbSendNullPacket(void *hDeviceContext)
 {
-    PSDevice            pDevice = (PSDevice)hDeviceContext;
-    PSTxMgmtPacket      pTxPacket = NULL;
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-
-
-
-    if (pDevice->bLinkPass == FALSE) {
-        return FALSE;
-    }
-
-     if ((pDevice->bEnablePSMode == FALSE) &&
-	  (pDevice->fTxDataInSleep == FALSE)){
-        return FALSE;
-    }
-
-    memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN);
-    pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
-    pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)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((WORD)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 ;
+	PSDevice pDevice = (PSDevice)hDeviceContext;
+	PSTxMgmtPacket pTxPacket = NULL;
+	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	u16 flags = 0;
+
+	if (pDevice->bLinkPass == FALSE)
+		return FALSE;
+
+	if ((pDevice->bEnablePSMode == FALSE) &&
+		(pDevice->fTxDataInSleep == FALSE)) {
+			return FALSE;
+	}
+
+	memset(pMgmt->pbyPSPacketPool, 0, sizeof(STxMgmtPacket) + WLAN_NULLDATA_FR_MAXLEN);
+	pTxPacket = (PSTxMgmtPacket)pMgmt->pbyPSPacketPool;
+	pTxPacket->p80211Header = (PUWLAN_80211HDR)((PBYTE)pTxPacket + sizeof(STxMgmtPacket));
+
+	flags = WLAN_SET_FC_FTYPE(WLAN_TYPE_DATA) |
+                        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_NULL);
+
+	if (pDevice->bEnablePSMode)
+		flags |= WLAN_SET_FC_PWRMGT(1);
+	else
+		flags |= WLAN_SET_FC_PWRMGT(0);
+
+	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));
+
+	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;
+	/* log error if sending failed */
+	if (csMgmt_xmit(pDevice, pTxPacket) != CMD_STATUS_PENDING) {
+		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Send Null Packet failed !\n");
+		return FALSE;
+	}
+	return TRUE;
 }
 
-/*+
+/*
  *
  * Routine Description:
  * Check if Next TBTT must wake up
@@ -347,36 +316,30 @@ BOOL PSbSendNullPacket(void *hDeviceContext)
  * Return Value:
  *    None.
  *
--*/
+ */
 
 BOOL PSbIsNextTBTTWakeUp(void *hDeviceContext)
 {
-
-    PSDevice         pDevice = (PSDevice)hDeviceContext;
-    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
-    BOOL                bWakeUp = FALSE;
-
-    if (pMgmt->wListenInterval >= 2) {
-        if (pMgmt->wCountToWakeUp == 0) {
-            pMgmt->wCountToWakeUp = pMgmt->wListenInterval;
-        }
-
-        pMgmt->wCountToWakeUp --;
-
-        if (pMgmt->wCountToWakeUp == 1) {
-
-            // Turn on wake up to listen next beacon
-            MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
-            pDevice->bPSRxBeacon = FALSE;
-            bWakeUp = TRUE;
-
-        } else if ( !pDevice->bPSRxBeacon ) {
-            //Listen until RxBeacon
-            MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
-        }
-
-    }
-
-    return bWakeUp;
+	PSDevice pDevice = (PSDevice)hDeviceContext;
+	PSMgmtObject pMgmt = &(pDevice->sMgmtObj);
+	BOOL bWakeUp = FALSE;
+
+	if (pMgmt->wListenInterval >= 2) {
+		if (pMgmt->wCountToWakeUp == 0)
+			pMgmt->wCountToWakeUp = pMgmt->wListenInterval;
+
+		pMgmt->wCountToWakeUp--;
+
+		if (pMgmt->wCountToWakeUp == 1) {
+			/* Turn on wake up to listen next beacon */
+			MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
+			pDevice->bPSRxBeacon = FALSE;
+			bWakeUp = TRUE;
+		} else if (!pDevice->bPSRxBeacon) {
+			/* Listen until RxBeacon */
+			MACvRegBitsOn(pDevice, MAC_REG_PSCTL, PSCTL_LNBCN);
+		}
+	}
+	return bWakeUp;
 }
 
diff --git a/drivers/staging/vt6656/wpactl.c b/drivers/staging/vt6656/wpactl.c
index 7fd300f..8752736 100644
--- a/drivers/staging/vt6656/wpactl.c
+++ b/drivers/staging/vt6656/wpactl.c
@@ -999,8 +999,7 @@ int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
 	}
 
 out:
-	if (param != NULL)
-		kfree(param);
+	kfree(param);
 
 	return ret;
 }
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasdma.c b/drivers/staging/westbridge/astoria/api/src/cyasdma.c
index de67e13..16b8ec1 100644
--- a/drivers/staging/westbridge/astoria/api/src/cyasdma.c
+++ b/drivers/staging/westbridge/astoria/api/src/cyasdma.c
@@ -653,7 +653,7 @@ cy_as_dma_stop(cy_as_device *dev_p)
 /*
  * CyAsDmaStart()
  *
- * This function intializes the DMA module to insure it is up and running.
+ * This function initializes the DMA module to insure it is up and running.
  */
 cy_as_return_status_t
 cy_as_dma_start(cy_as_device *dev_p)
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
index 10a52a1..7852410 100644
--- a/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
+++ b/drivers/staging/westbridge/astoria/api/src/cyasmisc.c
@@ -926,6 +926,8 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_get_firmware_version);
+
 static cy_as_return_status_t
 my_handle_response_read_m_c_u_register(cy_as_device *dev_p,
 				cy_as_ll_request_response *req_p,
@@ -1115,7 +1117,7 @@ destroy:
 
 	return ret;
 }
-
+EXPORT_SYMBOL(cy_as_misc_read_m_c_u_register);
 
 cy_as_return_status_t
 cy_as_misc_write_m_c_u_register(cy_as_device_handle handle,
@@ -1336,6 +1338,7 @@ cy_as_misc_reset(cy_as_device_handle handle,
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_reset);
 
 static cy_as_return_status_t
 get_unallocated_resource(cy_as_device *dev_p, cy_as_resource_type resource)
@@ -1508,6 +1511,8 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_acquire_resource);
+
 cy_as_return_status_t
 cy_as_misc_release_resource(cy_as_device_handle handle,
 	cy_as_resource_type resource)
@@ -1560,6 +1565,7 @@ cy_as_misc_release_resource(cy_as_device_handle handle,
 
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_misc_release_resource);
 
 cy_as_return_status_t
 cy_as_misc_set_trace_level(cy_as_device_handle handle,
@@ -1718,6 +1724,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_heart_beat_control);
 
 static cy_as_return_status_t
 my_set_sd_clock_freq(
@@ -1805,6 +1812,7 @@ cy_as_misc_set_low_speed_sd_freq(
 
 	return my_set_sd_clock_freq(dev_p, 0, (uint8_t)setting, cb, client);
 }
+EXPORT_SYMBOL(cy_as_misc_set_low_speed_sd_freq);
 
 cy_as_return_status_t
 cy_as_misc_set_high_speed_sd_freq(
@@ -1830,6 +1838,7 @@ cy_as_misc_set_high_speed_sd_freq(
 
 	return my_set_sd_clock_freq(dev_p, 1, (uint8_t)setting, cb, client);
 }
+EXPORT_SYMBOL(cy_as_misc_set_high_speed_sd_freq);
 
 cy_as_return_status_t
 cy_as_misc_get_gpio_value(cy_as_device_handle handle,
@@ -1921,7 +1930,7 @@ destroy:
 
 	return ret;
 }
-
+EXPORT_SYMBOL(cy_as_misc_get_gpio_value);
 
 cy_as_return_status_t
 cy_as_misc_set_gpio_value(cy_as_device_handle handle,
@@ -2020,6 +2029,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_set_gpio_value);
 
 static cy_as_return_status_t
 my_enter_standby(cy_as_device *dev_p, cy_bool pin)
@@ -2213,6 +2223,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_enter_standby);
 
 cy_as_return_status_t
 cy_as_misc_enter_standby_e_x_u(cy_as_device_handle handle,
@@ -2425,6 +2436,7 @@ try_wakeup_again:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_leave_standby);
 
 cy_as_return_status_t
 cy_as_misc_register_callback(
@@ -2526,7 +2538,7 @@ destroy:
 
 	return ret;
 }
-
+EXPORT_SYMBOL(cy_as_misc_storage_changed);
 
 cy_as_return_status_t
 cy_as_misc_enter_suspend(
@@ -2634,6 +2646,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_enter_suspend);
 
 cy_as_return_status_t
 cy_as_misc_leave_suspend(
@@ -2704,6 +2717,7 @@ cy_as_misc_leave_suspend(
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_misc_leave_suspend);
 
 cy_as_return_status_t
 cy_as_misc_reserve_l_n_a_boot_area(cy_as_device_handle handle,
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c
index d5a8e45..3689846 100644
--- a/drivers/staging/westbridge/astoria/api/src/cyasmtp.c
+++ b/drivers/staging/westbridge/astoria/api/src/cyasmtp.c
@@ -402,6 +402,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_mtp_start);
 
 static cy_as_return_status_t
 my_handle_response_mtp_stop(cy_as_device *dev_p,
@@ -744,6 +745,7 @@ cy_as_mtp_init_send_object(cy_as_device_handle handle,
 		client, CY_RQT_INIT_SEND_OBJECT);
 
 }
+EXPORT_SYMBOL(cy_as_mtp_init_send_object);
 
 cy_as_return_status_t
 cy_as_mtp_init_get_object(cy_as_device_handle handle,
@@ -763,6 +765,7 @@ cy_as_mtp_init_get_object(cy_as_device_handle handle,
 		transaction_id, cb, client, CY_RQT_INIT_GET_OBJECT);
 
 }
+EXPORT_SYMBOL(cy_as_mtp_init_get_object);
 
 static cy_as_return_status_t
 my_handle_response_cancel_send_object(cy_as_device *dev_p,
@@ -850,6 +853,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_mtp_cancel_send_object);
 
 static cy_as_return_status_t
 my_handle_response_cancel_get_object(cy_as_device *dev_p,
@@ -937,6 +941,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_mtp_cancel_get_object);
 
 cy_as_return_status_t
 cy_as_mtp_send_block_table(cy_as_device_handle handle,
@@ -1058,6 +1063,7 @@ cy_as_mtp_storage_only_start(cy_as_device_handle handle)
 	dev_p->is_storage_only_mode = cy_true;
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_mtp_storage_only_start);
 
 cy_as_return_status_t
 cy_as_mtp_storage_only_stop(cy_as_device_handle handle,
@@ -1126,3 +1132,5 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_mtp_storage_only_stop);
+
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c
index 083d869..2451404 100644
--- a/drivers/staging/westbridge/astoria/api/src/cyasstorage.c
+++ b/drivers/staging/westbridge/astoria/api/src/cyasstorage.c
@@ -522,7 +522,7 @@ destroy:
 
 	return ret;
 }
-
+EXPORT_SYMBOL(cy_as_storage_start);
 
 static cy_as_return_status_t
 my_handle_response_storage_stop(cy_as_device *dev_p,
@@ -632,6 +632,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_storage_stop);
 
 cy_as_return_status_t
 cy_as_storage_register_callback(cy_as_device_handle handle,
@@ -655,7 +656,7 @@ cy_as_storage_register_callback(cy_as_device_handle handle,
 
 	return CY_AS_ERROR_SUCCESS;
 }
-
+EXPORT_SYMBOL(cy_as_storage_register_callback);
 
 
 static cy_as_return_status_t
@@ -783,6 +784,7 @@ cy_as_storage_claim(cy_as_device_handle handle,
 	return my_storage_claim(dev_p, NULL, bus, device,
 		CY_AS_REQUEST_RESPONSE_MS, cb, client);
 }
+EXPORT_SYMBOL(cy_as_storage_claim);
 
 static cy_as_return_status_t
 my_handle_response_storage_release(cy_as_device *dev_p,
@@ -911,6 +913,7 @@ cy_as_storage_release(cy_as_device_handle handle,
 	return my_storage_release(dev_p, NULL, bus, device,
 		CY_AS_REQUEST_RESPONSE_MS, cb, client);
 }
+EXPORT_SYMBOL(cy_as_storage_release);
 
 static cy_as_return_status_t
 my_handle_response_storage_query_bus(cy_as_device *dev_p,
@@ -1059,6 +1062,7 @@ cy_as_storage_query_bus(cy_as_device_handle handle,
 	return my_storage_query_bus(dev_p, bus, cy_as_media_max_media_value,
 		CY_AS_REQUEST_RESPONSE_MS, count, cb, client);
 }
+EXPORT_SYMBOL(cy_as_storage_query_bus);
 
 cy_as_return_status_t
 cy_as_storage_query_media(cy_as_device_handle handle,
@@ -1086,6 +1090,7 @@ cy_as_storage_query_media(cy_as_device_handle handle,
 	return my_storage_query_bus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX,
 			count, cb, client);
 }
+EXPORT_SYMBOL(cy_as_storage_query_media);
 
 static cy_as_return_status_t
 my_handle_response_storage_query_device(cy_as_device *dev_p,
@@ -1260,6 +1265,7 @@ cy_as_storage_query_device(cy_as_device_handle handle,
 		CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
 			data_p->device, cb, client);
 }
+EXPORT_SYMBOL(cy_as_storage_query_device);
 
 static cy_as_return_status_t
 my_handle_response_storage_query_unit(cy_as_device *dev_p,
@@ -1434,7 +1440,7 @@ cy_as_storage_query_unit(cy_as_device_handle handle,
 	return my_storage_query_unit(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS,
 		data_p->bus, data_p->device, data_p->unit, cb, client);
 }
-
+EXPORT_SYMBOL(cy_as_storage_query_unit);
 
 static cy_as_return_status_t
 cy_as_get_block_size(cy_as_device *dev_p,
@@ -1615,6 +1621,7 @@ cy_as_storage_device_control(cy_as_device_handle handle,
 	return my_storage_device_control(dev_p, bus, device, card_detect_en,
 		write_prot_en, config_detect, cb, client);
 }
+EXPORT_SYMBOL(cy_as_storage_device_control);
 
 static void
 cy_as_async_storage_callback(cy_as_device *dev_p,
@@ -2069,6 +2076,7 @@ cy_as_storage_read(cy_as_device_handle handle,
 		CY_RQT_READ_BLOCK, bus, device,
 		unit, block, data_p, num_blocks);
 }
+EXPORT_SYMBOL(cy_as_storage_read);
 
 cy_as_return_status_t
 cy_as_storage_write(cy_as_device_handle handle,
@@ -2089,7 +2097,7 @@ cy_as_storage_write(cy_as_device_handle handle,
 		CY_RQT_WRITE_BLOCK, bus, device,
 		unit, block, data_p, num_blocks);
 }
-
+EXPORT_SYMBOL(cy_as_storage_write);
 
 cy_as_return_status_t
 cy_as_storage_read_async(cy_as_device_handle handle,
@@ -2110,6 +2118,7 @@ cy_as_storage_read_async(cy_as_device_handle handle,
 		CY_AS_REQUEST_RESPONSE_MS, bus, device, unit,
 		block, data_p, num_blocks, NULL, callback);
 }
+EXPORT_SYMBOL(cy_as_storage_read_async);
 
 cy_as_return_status_t
 cy_as_storage_write_async(cy_as_device_handle handle,
@@ -2133,7 +2142,7 @@ cy_as_storage_write_async(cy_as_device_handle handle,
 		CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block,
 		data_p, num_blocks, NULL, callback);
 }
-
+EXPORT_SYMBOL(cy_as_storage_write_async);
 
 static void
 my_storage_cancel_callback(
@@ -2196,6 +2205,7 @@ cy_as_storage_cancel_async(cy_as_device_handle handle)
 
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_storage_cancel_async);
 
 /*
  * This function does all the API side clean-up associated with
@@ -2374,6 +2384,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_storage_sd_register_read);
 
 cy_as_return_status_t
 cy_as_storage_create_p_partition(
@@ -2450,6 +2461,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_storage_create_p_partition);
 
 cy_as_return_status_t
 cy_as_storage_remove_p_partition(
@@ -2519,6 +2531,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_storage_remove_p_partition);
 
 static cy_as_return_status_t
 my_handle_response_get_transfer_amount(cy_as_device *dev_p,
@@ -2621,6 +2634,7 @@ destroy:
 	return ret;
 
 }
+EXPORT_SYMBOL(cy_as_storage_get_transfer_amount);
 
 cy_as_return_status_t
 cy_as_storage_erase(
@@ -2722,6 +2736,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_storage_erase);
 
 static void
 cy_as_storage_func_callback(cy_as_device *dev_p,
@@ -3005,6 +3020,7 @@ cy_as_sdio_direct_read(
 	return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
 		address, misc_buf, 0x00, cy_false, data_p);
 }
+EXPORT_SYMBOL(cy_as_sdio_direct_read);
 
 cy_as_return_status_t
 cy_as_sdio_direct_write(
@@ -3020,6 +3036,7 @@ cy_as_sdio_direct_write(
 	return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
 		address, misc_buf, argument, cy_true, data_p);
 }
+EXPORT_SYMBOL(cy_as_sdio_direct_write);
 
 /*Cmd53 IO*/
 cy_as_return_status_t
@@ -3403,6 +3420,7 @@ cy_as_sdio_extended_read(
 		n_function_no, address, misc_buf, argument, cy_false,
 		data_p, callback);
 }
+EXPORT_SYMBOL(cy_as_sdio_extended_read);
 
 /* CMD53 Extended Write*/
 cy_as_return_status_t
@@ -3426,7 +3444,7 @@ cy_as_sdio_extended_write(
 		n_function_no, address, misc_buf, argument, cy_true,
 		data_p, callback);
 }
-
+EXPORT_SYMBOL(cy_as_sdio_extended_write);
 
 /* Read the CIS info tuples for the given function and Tuple ID*/
 cy_as_return_status_t
@@ -3617,6 +3635,7 @@ destroy:
 		cy_as_ll_destroy_response(dev_p, reply_p);
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_sdio_query_card);
 
 /*Reset SDIO card. */
 cy_as_return_status_t
@@ -3767,6 +3786,7 @@ destroy:
 		cy_as_ll_destroy_response(dev_p, reply_p);
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_sdio_init_function);
 
 /*Query individual functions. */
 cy_as_return_status_t
@@ -4066,6 +4086,7 @@ cy_as_sdio_set_blocksize(
 			bus, n_function_no, blocksize);
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_sdio_set_blocksize);
 
 /* Deinitialize an SDIO function*/
 cy_as_return_status_t
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasusb.c b/drivers/staging/westbridge/astoria/api/src/cyasusb.c
index 7777d9a..92ea425 100644
--- a/drivers/staging/westbridge/astoria/api/src/cyasusb.c
+++ b/drivers/staging/westbridge/astoria/api/src/cyasusb.c
@@ -800,6 +800,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_start);
 
 void
 cy_as_usb_reset(cy_as_device *dev_p)
@@ -977,6 +978,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_stop);
 
 /*
 * This function registers a callback to be called when
@@ -1004,7 +1006,7 @@ cy_as_usb_register_callback(cy_as_device_handle handle,
 	dev_p->usb_event_cb_ms = callback;
 	return CY_AS_ERROR_SUCCESS;
 }
-
+EXPORT_SYMBOL(cy_as_usb_register_callback);
 
 static cy_as_return_status_t
 my_handle_response_no_data(cy_as_device *dev_p,
@@ -1056,8 +1058,8 @@ destroy:
 * This method asks the West Bridge device to connect the
 * internal USB D+ and D- signals to the USB pins, thus
 * starting the enumeration processes if the external pins
-* are connnected to a USB host. If the external pins are
-* not connect to a USB host, enumeration will begin as soon
+* are connected to a USB host. If the external pins are
+* not connected to a USB host, enumeration will begin as soon
 * as the USB pins are connected to a host.
 */
 cy_as_return_status_t
@@ -1124,6 +1126,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_connect);
 
 static cy_as_return_status_t
 my_handle_response_disconnect(cy_as_device *dev_p,
@@ -1222,6 +1225,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_disconnect);
 
 static cy_as_return_status_t
 my_handle_response_set_enum_config(cy_as_device *dev_p,
@@ -1437,7 +1441,7 @@ cy_as_usb_set_enum_config(cy_as_device_handle handle,
 			client
 		);
 }
-
+EXPORT_SYMBOL(cy_as_usb_set_enum_config);
 
 static cy_as_return_status_t
 my_handle_response_get_enum_config(cy_as_device *dev_p,
@@ -1622,7 +1626,7 @@ cy_as_usb_get_enum_config(cy_as_device_handle handle,
 	return my_usb_get_enum_config(handle,
 		CY_AS_REQUEST_RESPONSE_MS, config_p, cb, client);
 }
-
+EXPORT_SYMBOL(cy_as_usb_get_enum_config);
 
 /*
 * This method sets the USB descriptor for a given entity.
@@ -1705,6 +1709,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_set_descriptor);
 
 /*
  * This method clears all descriptors that were previously
@@ -1771,6 +1776,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_clear_descriptors);
 
 static cy_as_return_status_t
 my_handle_response_get_descriptor(cy_as_device *dev_p,
@@ -1881,6 +1887,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_get_descriptor);
 
 cy_as_return_status_t
 cy_as_usb_set_physical_configuration(cy_as_device_handle handle,
@@ -1910,6 +1917,7 @@ cy_as_usb_set_physical_configuration(cy_as_device_handle handle,
 
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_usb_set_physical_configuration);
 
 static cy_bool
 is_physical_valid(uint8_t config, cy_as_end_point_number_t ep)
@@ -2027,6 +2035,7 @@ cy_as_usb_set_end_point_config(cy_as_device_handle handle,
 	return cy_as_dma_enable_end_point(dev_p, ep,
 		config_p->enabled, (cy_as_dma_direction)config_p->dir);
 }
+EXPORT_SYMBOL(cy_as_usb_set_end_point_config);
 
 cy_as_return_status_t
 cy_as_usb_get_end_point_config(cy_as_device_handle handle,
@@ -2053,6 +2062,7 @@ cy_as_usb_get_end_point_config(cy_as_device_handle handle,
 
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_usb_get_end_point_config);
 
 /*
 * Commit the configuration of the various endpoints to the hardware.
@@ -2180,6 +2190,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_commit_config);
 
 static void
 sync_request_callback(cy_as_device *dev_p,
@@ -2381,6 +2392,7 @@ cy_as_usb_read_data(cy_as_device_handle handle,
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_read_data);
 
 cy_as_return_status_t
 cy_as_usb_read_data_async(cy_as_device_handle handle,
@@ -2459,6 +2471,7 @@ cy_as_usb_read_data_async(cy_as_device_handle handle,
 	}
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_read_data_async);
 
 cy_as_return_status_t
 cy_as_usb_write_data(cy_as_device_handle handle,
@@ -2571,6 +2584,7 @@ cy_as_usb_write_data(cy_as_device_handle handle,
 	ret = dev_p->usb_error;
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_write_data);
 
 static void
 mtp_write_callback(
@@ -2736,6 +2750,7 @@ cy_as_usb_write_data_async(cy_as_device_handle handle,
 
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_usb_write_data_async);
 
 static void
 my_usb_cancel_async_callback(
@@ -2827,6 +2842,7 @@ cy_as_usb_cancel_async(cy_as_device_handle handle,
 
 	return CY_AS_ERROR_SUCCESS;
 }
+EXPORT_SYMBOL(cy_as_usb_cancel_async);
 
 static void
 cy_as_usb_ack_callback(
@@ -3212,7 +3228,7 @@ cy_as_usb_set_nak(cy_as_device_handle handle,
 	return cy_as_usb_nak_stall_request(handle, ep,
 		CY_RQT_ENDPOINT_SET_NAK, cy_true, 0, cb, client);
 }
-
+EXPORT_SYMBOL(cy_as_usb_set_nak);
 
 cy_as_return_status_t
 cy_as_usb_clear_nak(cy_as_device_handle handle,
@@ -3238,6 +3254,7 @@ cy_as_usb_clear_nak(cy_as_device_handle handle,
 	return cy_as_usb_nak_stall_request(handle, ep,
 		CY_RQT_ENDPOINT_SET_NAK, cy_false, 0, cb, client);
 }
+EXPORT_SYMBOL(cy_as_usb_clear_nak);
 
 cy_as_return_status_t
 cy_as_usb_get_nak(cy_as_device_handle handle,
@@ -3265,7 +3282,7 @@ cy_as_usb_get_nak(cy_as_device_handle handle,
 		CY_RQT_GET_ENDPOINT_NAK, CY_RESP_ENDPOINT_NAK,
 		nak_p, cb, client);
 }
-
+EXPORT_SYMBOL(cy_as_usb_get_nak);
 
 cy_as_return_status_t
 cy_as_usb_set_stall(cy_as_device_handle handle,
@@ -3291,6 +3308,7 @@ cy_as_usb_set_stall(cy_as_device_handle handle,
 	return cy_as_usb_nak_stall_request(handle, ep,
 		CY_RQT_STALL_ENDPOINT, cy_true, 0, cb, client);
 }
+EXPORT_SYMBOL(cy_as_usb_set_stall);
 
 cy_as_return_status_t
 cy_as_usb_clear_stall(cy_as_device_handle handle,
@@ -3316,6 +3334,7 @@ cy_as_usb_clear_stall(cy_as_device_handle handle,
 	return cy_as_usb_nak_stall_request(handle, ep,
 		CY_RQT_STALL_ENDPOINT, cy_false, 0, cb, client);
 }
+EXPORT_SYMBOL(cy_as_usb_clear_stall);
 
 cy_as_return_status_t
 cy_as_usb_get_stall(cy_as_device_handle handle,
@@ -3342,6 +3361,7 @@ cy_as_usb_get_stall(cy_as_device_handle handle,
 	return cy_as_usb_get_nak_stall(handle, ep,
 		CY_RQT_GET_STALL, CY_RESP_ENDPOINT_STALL, stall_p, cb, client);
 }
+EXPORT_SYMBOL(cy_as_usb_get_stall);
 
 cy_as_return_status_t
 cy_as_usb_signal_remote_wakeup(cy_as_device_handle handle,
@@ -3405,6 +3425,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_signal_remote_wakeup);
 
 cy_as_return_status_t
 cy_as_usb_set_m_s_report_threshold(cy_as_device_handle handle,
@@ -3482,6 +3503,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_set_m_s_report_threshold);
 
 cy_as_return_status_t
 cy_as_usb_select_m_s_partitions(
@@ -3563,6 +3585,7 @@ destroy:
 
 	return ret;
 }
+EXPORT_SYMBOL(cy_as_usb_select_m_s_partitions);
 
 static void
 cy_as_usb_func_callback(
diff --git a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
index ad0c61d..ea9b733 100644
--- a/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
+++ b/drivers/staging/westbridge/astoria/arch/arm/mach-omap2/cyashalomap_kernel.c
@@ -347,11 +347,8 @@ static int cy_as_hal_gpmc_init(void)
 	u32 tmp32;
 	int err;
 	struct gpmc_timings	timings;
-	/*
-	 * get GPMC i/o registers base(already been i/o mapped
-	 * in kernel, no need for separate i/o remap)
-	 */
-	gpmc_base = phys_to_virt(OMAP34XX_GPMC_BASE);
+
+	gpmc_base = (u32)ioremap_nocache(OMAP34XX_GPMC_BASE, BLKSZ_4K);
 	DBGPRN(KERN_INFO "kernel has gpmc_base=%x , val@ the base=%x",
 		gpmc_base, __raw_readl(gpmc_base)
 	);
diff --git a/drivers/staging/westbridge/astoria/device/cyandevice_export.h b/drivers/staging/westbridge/astoria/device/cyandevice_export.h
deleted file mode 100644
index acb4e07..0000000
--- a/drivers/staging/westbridge/astoria/device/cyandevice_export.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-## cyandevice_export.h - Linux Antioch device driver file
-##
-## ===========================
-## Copyright (C) 2010  Cypress Semiconductor
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License
-## as published by the Free Software Foundation; either version 2
-## of the License, or (at your option) any later version.
-##
-## This program is distributed in the hope that it will be useful,
-## but WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-## GNU General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street
-## Fifth Floor, Boston, MA  02110-1301, USA.
-## ===========================
-*/
-
-/*
- * Export Misc APIs that can be used from the other driver modules.
- * The APIs to create a device handle and download firmware are not exported
- * because they are expected to be used only by this kernel module.
- */
-EXPORT_SYMBOL(cy_as_misc_get_firmware_version);
-EXPORT_SYMBOL(cy_as_misc_read_m_c_u_register);
-EXPORT_SYMBOL(cy_as_misc_reset);
-EXPORT_SYMBOL(cy_as_misc_acquire_resource);
-EXPORT_SYMBOL(cy_as_misc_release_resource);
-EXPORT_SYMBOL(cy_as_misc_enter_standby);
-EXPORT_SYMBOL(cy_as_misc_leave_standby);
-EXPORT_SYMBOL(cy_as_misc_enter_suspend);
-EXPORT_SYMBOL(cy_as_misc_leave_suspend);
-EXPORT_SYMBOL(cy_as_misc_storage_changed);
-EXPORT_SYMBOL(cy_as_misc_heart_beat_control);
-EXPORT_SYMBOL(cy_as_misc_get_gpio_value);
-EXPORT_SYMBOL(cy_as_misc_set_gpio_value);
-EXPORT_SYMBOL(cy_as_misc_set_low_speed_sd_freq);
-EXPORT_SYMBOL(cy_as_misc_set_high_speed_sd_freq);
-
-/*
- * Export the USB APIs that can be used by the dependent kernel modules.
- */
-EXPORT_SYMBOL(cy_as_usb_set_end_point_config);
-EXPORT_SYMBOL(cy_as_usb_read_data_async);
-EXPORT_SYMBOL(cy_as_usb_write_data_async);
-EXPORT_SYMBOL(cy_as_usb_cancel_async);
-EXPORT_SYMBOL(cy_as_usb_set_stall);
-EXPORT_SYMBOL(cy_as_usb_clear_stall);
-EXPORT_SYMBOL(cy_as_usb_connect);
-EXPORT_SYMBOL(cy_as_usb_disconnect);
-EXPORT_SYMBOL(cy_as_usb_start);
-EXPORT_SYMBOL(cy_as_usb_stop);
-EXPORT_SYMBOL(cy_as_usb_set_enum_config);
-EXPORT_SYMBOL(cy_as_usb_get_enum_config);
-EXPORT_SYMBOL(cy_as_usb_set_physical_configuration);
-EXPORT_SYMBOL(cy_as_usb_register_callback);
-EXPORT_SYMBOL(cy_as_usb_commit_config);
-EXPORT_SYMBOL(cy_as_usb_set_descriptor);
-EXPORT_SYMBOL(cy_as_usb_clear_descriptors);
-EXPORT_SYMBOL(cy_as_usb_get_descriptor);
-EXPORT_SYMBOL(cy_as_usb_get_end_point_config);
-EXPORT_SYMBOL(cy_as_usb_read_data);
-EXPORT_SYMBOL(cy_as_usb_write_data);
-EXPORT_SYMBOL(cy_as_usb_get_stall);
-EXPORT_SYMBOL(cy_as_usb_set_nak);
-EXPORT_SYMBOL(cy_as_usb_clear_nak);
-EXPORT_SYMBOL(cy_as_usb_get_nak);
-EXPORT_SYMBOL(cy_as_usb_signal_remote_wakeup);
-EXPORT_SYMBOL(cy_as_usb_set_m_s_report_threshold);
-EXPORT_SYMBOL(cy_as_usb_select_m_s_partitions);
-
-/*
- * Export all Storage APIs that can be used by dependent kernel modules.
- */
-EXPORT_SYMBOL(cy_as_storage_start);
-EXPORT_SYMBOL(cy_as_storage_stop);
-EXPORT_SYMBOL(cy_as_storage_register_callback);
-EXPORT_SYMBOL(cy_as_storage_query_bus);
-EXPORT_SYMBOL(cy_as_storage_query_media);
-EXPORT_SYMBOL(cy_as_storage_query_device);
-EXPORT_SYMBOL(cy_as_storage_query_unit);
-EXPORT_SYMBOL(cy_as_storage_device_control);
-EXPORT_SYMBOL(cy_as_storage_claim);
-EXPORT_SYMBOL(cy_as_storage_release);
-EXPORT_SYMBOL(cy_as_storage_read);
-EXPORT_SYMBOL(cy_as_storage_write);
-EXPORT_SYMBOL(cy_as_storage_read_async);
-EXPORT_SYMBOL(cy_as_storage_write_async);
-EXPORT_SYMBOL(cy_as_storage_cancel_async);
-EXPORT_SYMBOL(cy_as_storage_sd_register_read);
-EXPORT_SYMBOL(cy_as_storage_create_p_partition);
-EXPORT_SYMBOL(cy_as_storage_remove_p_partition);
-EXPORT_SYMBOL(cy_as_storage_get_transfer_amount);
-EXPORT_SYMBOL(cy_as_storage_erase);
-
-EXPORT_SYMBOL(cy_as_sdio_query_card);
-EXPORT_SYMBOL(cy_as_sdio_init_function);
-EXPORT_SYMBOL(cy_as_sdio_set_blocksize);
-EXPORT_SYMBOL(cy_as_sdio_direct_read);
-EXPORT_SYMBOL(cy_as_sdio_direct_write);
-EXPORT_SYMBOL(cy_as_sdio_extended_read);
-EXPORT_SYMBOL(cy_as_sdio_extended_write);
-
-EXPORT_SYMBOL(cy_as_hal_alloc);
-EXPORT_SYMBOL(cy_as_hal_free);
-EXPORT_SYMBOL(cy_as_hal_sleep);
-EXPORT_SYMBOL(cy_as_hal_create_sleep_channel);
-EXPORT_SYMBOL(cy_as_hal_destroy_sleep_channel);
-EXPORT_SYMBOL(cy_as_hal_sleep_on);
-EXPORT_SYMBOL(cy_as_hal_wake);
-EXPORT_SYMBOL(cy_as_hal_mem_set);
-
-EXPORT_SYMBOL(cy_as_mtp_storage_only_start);
-EXPORT_SYMBOL(cy_as_mtp_storage_only_stop);
-EXPORT_SYMBOL(cy_as_mtp_start);
-EXPORT_SYMBOL(cy_as_mtp_init_send_object);
-EXPORT_SYMBOL(cy_as_mtp_init_get_object);
-EXPORT_SYMBOL(cy_as_mtp_cancel_send_object);
-EXPORT_SYMBOL(cy_as_mtp_cancel_get_object);
-
-#ifdef __CY_ASTORIA_SCM_KERNEL_HAL__
-/* Functions in the SCM kernel HAL implementation only. */
-EXPORT_SYMBOL(cy_as_hal_enable_scatter_list);
-EXPORT_SYMBOL(cy_as_hal_disable_scatter_list);
-#endif
-
-/*[]*/
diff --git a/drivers/staging/westbridge/astoria/device/cyasdevice.c b/drivers/staging/westbridge/astoria/device/cyasdevice.c
index c76e383..7de35cc 100644
--- a/drivers/staging/westbridge/astoria/device/cyasdevice.c
+++ b/drivers/staging/westbridge/astoria/device/cyasdevice.c
@@ -40,9 +40,6 @@
 #include "../include/linux/westbridge/cyashal.h"
 #include "../include/linux/westbridge/cyasregs.h"
 
-/* API exports include file */
-#include "cyandevice_export.h"
-
 typedef struct cyasdevice {
 		/* Handle to the Antioch device */
 		cy_as_device_handle			dev_handle;
@@ -217,7 +214,7 @@ static int cyasdevice_initialize(void)
 	cy_as_dev = cy_as_hal_alloc(sizeof(cyasdevice));
 	if (cy_as_dev == NULL) {
 		cy_as_hal_print_message("<1>_cy_as_device: "
-			"memmory allocation failed\n");
+			"memory allocation failed\n");
 		return -ENOMEM;
 	}
 	memset(cy_as_dev, 0, sizeof(cyasdevice));
@@ -389,7 +386,7 @@ EXPORT_SYMBOL(cyasdevice_gethaltag);
 static int __init cyasdevice_init(void)
 {
 	if (cyasdevice_initialize() != 0)
-		return ENODEV;
+		return -ENODEV;
 
 	return 0;
 }
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h
index 6efb8b8..8dab5e9 100644
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h
+++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasdma.h
@@ -35,7 +35,7 @@
 	at some future time.
 
 	The DMA module must be started before it can be used.  It is
-	started by calling CyAsDmaStart().  This function intializes
+	started by calling CyAsDmaStart().  This function initializes
 	all of the endpoint data structures.
 
 	In order to perform DMA on a particular endpoint, the endpoint
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h
index b555c6c..2f07018 100644
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h
+++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasmisc.h
@@ -550,7 +550,7 @@ cy_as_misc_destroy_device(
    West Bridge.
 
    Description
-   This function intializes the hardware to establish basic
+   This function initializes the hardware to establish basic
    communication with the West Bridge device.  This is always the first
    function called to initialize communication with the West Bridge
    device.
diff --git a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h
index 9049c8d..4a549e1 100644
--- a/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h
+++ b/drivers/staging/westbridge/astoria/include/linux/westbridge/cyasusb.h
@@ -746,7 +746,7 @@ cy_as_usb_register_callback(
    the West Bridge device as a different
    device when necessary.  This function connects the D+ and D-
    signal physically to the USB host
-   if they have been previously disconnnected.
+   if they have been previously disconnected.
 
    * Valid In Asynchronous Callback: YES (if cb supplied)
    * Nestable: YES
diff --git a/drivers/staging/winbond/core.h b/drivers/staging/winbond/core.h
index d7b3aca..6160b2f 100644
--- a/drivers/staging/winbond/core.h
+++ b/drivers/staging/winbond/core.h
@@ -3,6 +3,7 @@
 
 #include <linux/wireless.h>
 #include <linux/types.h>
+#include <linux/delay.h>
 
 #include "wbhal.h"
 #include "mto.h"
diff --git a/drivers/staging/winbond/wb35reg.c b/drivers/staging/winbond/wb35reg.c
index 42ae610..da595f1 100644
--- a/drivers/staging/winbond/wb35reg.c
+++ b/drivers/staging/winbond/wb35reg.c
@@ -66,8 +66,7 @@ unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo, u32 *p
 	} else {
 		if (urb)
 			usb_free_urb(urb);
-		if (reg_queue)
-			kfree(reg_queue);
+		kfree(reg_queue);
 		return false;
 	}
    return false;
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 2163d60..3724e1e 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -118,13 +118,14 @@ static void wbsoft_configure_filter(struct ieee80211_hw *dev,
 	*total_flags = new_flags;
 }
 
-static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct wbsoft_priv *priv = dev->priv;
 
 	if (priv->sMlmeFrame.IsInUsed != PACKET_FREE_TO_USE) {
 		priv->sMlmeFrame.wNumTxMMPDUDiscarded++;
-		return NETDEV_TX_BUSY;
+		kfree_skb(skb);
+		return;
 	}
 
 	priv->sMlmeFrame.IsInUsed = PACKET_COME_FROM_MLME;
@@ -140,8 +141,6 @@ static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 	 */
 
 	Mds_Tx(priv);
-
-	return NETDEV_TX_OK;
 }
 
 static int wbsoft_start(struct ieee80211_hw *dev)
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index fa94a7c..5631ad0 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -352,12 +352,12 @@ PD Record codes
 typedef struct hfa384x_bytestr {
 	u16 len;
 	u8 data[0];
-} __attribute__ ((packed)) hfa384x_bytestr_t;
+} __packed hfa384x_bytestr_t;
 
 typedef struct hfa384x_bytestr32 {
 	u16 len;
 	u8 data[32];
-} __attribute__ ((packed)) hfa384x_bytestr32_t;
+} __packed hfa384x_bytestr32_t;
 
 /*--------------------------------------------------------------------
 Configuration Record Structures:
@@ -370,7 +370,7 @@ typedef struct hfa384x_compident {
 	u16 variant;
 	u16 major;
 	u16 minor;
-} __attribute__ ((packed)) hfa384x_compident_t;
+} __packed hfa384x_compident_t;
 
 typedef struct hfa384x_caplevel {
 	u16 role;
@@ -378,7 +378,7 @@ typedef struct hfa384x_caplevel {
 	u16 variant;
 	u16 bottom;
 	u16 top;
-} __attribute__ ((packed)) hfa384x_caplevel_t;
+} __packed hfa384x_caplevel_t;
 
 /*-- Configuration Record: cnfAuthentication --*/
 #define HFA384x_CNFAUTHENTICATION_OPENSYSTEM	0x0001
@@ -397,26 +397,26 @@ typedef struct hfa384x_HostScanRequest_data {
 	u16 channelList;
 	u16 txRate;
 	hfa384x_bytestr32_t ssid;
-} __attribute__ ((packed)) hfa384x_HostScanRequest_data_t;
+} __packed hfa384x_HostScanRequest_data_t;
 
 /*-- Configuration Record: JoinRequest (data portion only) --*/
 typedef struct hfa384x_JoinRequest_data {
 	u8 bssid[WLAN_BSSID_LEN];
 	u16 channel;
-} __attribute__ ((packed)) hfa384x_JoinRequest_data_t;
+} __packed hfa384x_JoinRequest_data_t;
 
 /*-- Configuration Record: authenticateStation (data portion only) --*/
 typedef struct hfa384x_authenticateStation_data {
 	u8 address[ETH_ALEN];
 	u16 status;
 	u16 algorithm;
-} __attribute__ ((packed)) hfa384x_authenticateStation_data_t;
+} __packed hfa384x_authenticateStation_data_t;
 
 /*-- Configuration Record: WPAData       (data portion only) --*/
 typedef struct hfa384x_WPAData {
 	u16 datalen;
 	u8 data[0];		/* max 80 */
-} __attribute__ ((packed)) hfa384x_WPAData_t;
+} __packed hfa384x_WPAData_t;
 
 /*--------------------------------------------------------------------
 Information Record Structures: NIC Information
@@ -428,7 +428,7 @@ typedef struct hfa384x_downloadbuffer {
 	u16 page;
 	u16 offset;
 	u16 len;
-} __attribute__ ((packed)) hfa384x_downloadbuffer_t;
+} __packed hfa384x_downloadbuffer_t;
 
 /*--------------------------------------------------------------------
 Information Record Structures: NIC Information
@@ -441,14 +441,14 @@ typedef struct hfa384x_commsquality {
 	u16 CQ_currBSS;
 	u16 ASL_currBSS;
 	u16 ANL_currFC;
-} __attribute__ ((packed)) hfa384x_commsquality_t;
+} __packed hfa384x_commsquality_t;
 
 /*-- Information Record: dmbcommsquality --*/
 typedef struct hfa384x_dbmcommsquality {
 	u16 CQdbm_currBSS;
 	u16 ASLdbm_currBSS;
 	u16 ANLdbm_currFC;
-} __attribute__ ((packed)) hfa384x_dbmcommsquality_t;
+} __packed hfa384x_dbmcommsquality_t;
 
 /*--------------------------------------------------------------------
 FRAME STRUCTURES: Communication Frames
@@ -481,7 +481,7 @@ typedef struct hfa384x_tx_frame {
 	u8 dest_addr[6];
 	u8 src_addr[6];
 	u16 data_length;	/* big endian format */
-} __attribute__ ((packed)) hfa384x_tx_frame_t;
+} __packed hfa384x_tx_frame_t;
 /*--------------------------------------------------------------------
 Communication Frames: Field Masks for Transmit Frames
 --------------------------------------------------------------------*/
@@ -543,7 +543,7 @@ typedef struct hfa384x_rx_frame {
 	u8 dest_addr[6];
 	u8 src_addr[6];
 	u16 data_length;	/* IEEE? (big endian) format */
-} __attribute__ ((packed)) hfa384x_rx_frame_t;
+} __packed hfa384x_rx_frame_t;
 /*--------------------------------------------------------------------
 Communication Frames: Field Masks for Receive Frames
 --------------------------------------------------------------------*/
@@ -607,7 +607,7 @@ typedef struct hfa384x_CommTallies16 {
 	u16 rxdiscardswepundecr;
 	u16 rxmsginmsgfrag;
 	u16 rxmsginbadmsgfrag;
-} __attribute__ ((packed)) hfa384x_CommTallies16_t;
+} __packed hfa384x_CommTallies16_t;
 
 typedef struct hfa384x_CommTallies32 {
 	u32 txunicastframes;
@@ -631,7 +631,7 @@ typedef struct hfa384x_CommTallies32 {
 	u32 rxdiscardswepundecr;
 	u32 rxmsginmsgfrag;
 	u32 rxmsginbadmsgfrag;
-} __attribute__ ((packed)) hfa384x_CommTallies32_t;
+} __packed hfa384x_CommTallies32_t;
 
 /*--  Inquiry Frame, Diagnose: Scan Results & Subfields--*/
 typedef struct hfa384x_ScanResultSub {
@@ -644,13 +644,13 @@ typedef struct hfa384x_ScanResultSub {
 	hfa384x_bytestr32_t ssid;
 	u8 supprates[10];	/* 802.11 info element */
 	u16 proberesp_rate;
-} __attribute__ ((packed)) hfa384x_ScanResultSub_t;
+} __packed hfa384x_ScanResultSub_t;
 
 typedef struct hfa384x_ScanResult {
 	u16 rsvd;
 	u16 scanreason;
 	hfa384x_ScanResultSub_t result[HFA384x_SCANRESULT_MAX];
-} __attribute__ ((packed)) hfa384x_ScanResult_t;
+} __packed hfa384x_ScanResult_t;
 
 /*--  Inquiry Frame, Diagnose: ChInfo Results & Subfields--*/
 typedef struct hfa384x_ChInfoResultSub {
@@ -658,7 +658,7 @@ typedef struct hfa384x_ChInfoResultSub {
 	u16 anl;
 	u16 pnl;
 	u16 active;
-} __attribute__ ((packed)) hfa384x_ChInfoResultSub_t;
+} __packed hfa384x_ChInfoResultSub_t;
 
 #define HFA384x_CHINFORESULT_BSSACTIVE	BIT(0)
 #define HFA384x_CHINFORESULT_PCFACTIVE	BIT(1)
@@ -666,7 +666,7 @@ typedef struct hfa384x_ChInfoResultSub {
 typedef struct hfa384x_ChInfoResult {
 	u16 scanchannels;
 	hfa384x_ChInfoResultSub_t result[HFA384x_CHINFORESULT_MAX];
-} __attribute__ ((packed)) hfa384x_ChInfoResult_t;
+} __packed hfa384x_ChInfoResult_t;
 
 /*--  Inquiry Frame, Diagnose: Host Scan Results & Subfields--*/
 typedef struct hfa384x_HScanResultSub {
@@ -680,13 +680,13 @@ typedef struct hfa384x_HScanResultSub {
 	u8 supprates[10];	/* 802.11 info element */
 	u16 proberesp_rate;
 	u16 atim;
-} __attribute__ ((packed)) hfa384x_HScanResultSub_t;
+} __packed hfa384x_HScanResultSub_t;
 
 typedef struct hfa384x_HScanResult {
 	u16 nresult;
 	u16 rsvd;
 	hfa384x_HScanResultSub_t result[HFA384x_HSCANRESULT_MAX];
-} __attribute__ ((packed)) hfa384x_HScanResult_t;
+} __packed hfa384x_HScanResult_t;
 
 /*--  Unsolicited Frame, MAC Mgmt: LinkStatus --*/
 
@@ -700,7 +700,7 @@ typedef struct hfa384x_HScanResult {
 
 typedef struct hfa384x_LinkStatus {
 	u16 linkstatus;
-} __attribute__ ((packed)) hfa384x_LinkStatus_t;
+} __packed hfa384x_LinkStatus_t;
 
 /*--  Unsolicited Frame, MAC Mgmt: AssociationStatus (--*/
 
@@ -715,25 +715,25 @@ typedef struct hfa384x_AssocStatus {
 	u8 old_ap_addr[ETH_ALEN];
 	u16 reason;
 	u16 reserved;
-} __attribute__ ((packed)) hfa384x_AssocStatus_t;
+} __packed hfa384x_AssocStatus_t;
 
 /*--  Unsolicited Frame, MAC Mgmt: AuthRequest (AP Only) --*/
 
 typedef struct hfa384x_AuthRequest {
 	u8 sta_addr[ETH_ALEN];
 	u16 algorithm;
-} __attribute__ ((packed)) hfa384x_AuthReq_t;
+} __packed hfa384x_AuthReq_t;
 
 /*--  Unsolicited Frame, MAC Mgmt: PSUserCount (AP Only) --*/
 
 typedef struct hfa384x_PSUserCount {
 	u16 usercnt;
-} __attribute__ ((packed)) hfa384x_PSUserCount_t;
+} __packed hfa384x_PSUserCount_t;
 
 typedef struct hfa384x_KeyIDChanged {
 	u8 sta_addr[ETH_ALEN];
 	u16 keyid;
-} __attribute__ ((packed)) hfa384x_KeyIDChanged_t;
+} __packed hfa384x_KeyIDChanged_t;
 
 /*--  Collection of all Inf frames ---------------*/
 typedef union hfa384x_infodata {
@@ -747,13 +747,13 @@ typedef union hfa384x_infodata {
 	hfa384x_AuthReq_t authreq;
 	hfa384x_PSUserCount_t psusercnt;
 	hfa384x_KeyIDChanged_t keyidchanged;
-} __attribute__ ((packed)) hfa384x_infodata_t;
+} __packed hfa384x_infodata_t;
 
 typedef struct hfa384x_InfFrame {
 	u16 framelen;
 	u16 infotype;
 	hfa384x_infodata_t info;
-} __attribute__ ((packed)) hfa384x_InfFrame_t;
+} __packed hfa384x_InfFrame_t;
 
 /*--------------------------------------------------------------------
 USB Packet structures and constants.
@@ -785,7 +785,7 @@ USB Packet structures and constants.
 typedef struct hfa384x_usb_txfrm {
 	hfa384x_tx_frame_t desc;
 	u8 data[WLAN_DATA_MAXLEN];
-} __attribute__ ((packed)) hfa384x_usb_txfrm_t;
+} __packed hfa384x_usb_txfrm_t;
 
 typedef struct hfa384x_usb_cmdreq {
 	u16 type;
@@ -794,21 +794,21 @@ typedef struct hfa384x_usb_cmdreq {
 	u16 parm1;
 	u16 parm2;
 	u8 pad[54];
-} __attribute__ ((packed)) hfa384x_usb_cmdreq_t;
+} __packed hfa384x_usb_cmdreq_t;
 
 typedef struct hfa384x_usb_wridreq {
 	u16 type;
 	u16 frmlen;
 	u16 rid;
 	u8 data[HFA384x_RIDDATA_MAXLEN];
-} __attribute__ ((packed)) hfa384x_usb_wridreq_t;
+} __packed hfa384x_usb_wridreq_t;
 
 typedef struct hfa384x_usb_rridreq {
 	u16 type;
 	u16 frmlen;
 	u16 rid;
 	u8 pad[58];
-} __attribute__ ((packed)) hfa384x_usb_rridreq_t;
+} __packed hfa384x_usb_rridreq_t;
 
 typedef struct hfa384x_usb_wmemreq {
 	u16 type;
@@ -816,7 +816,7 @@ typedef struct hfa384x_usb_wmemreq {
 	u16 offset;
 	u16 page;
 	u8 data[HFA384x_USB_RWMEM_MAXLEN];
-} __attribute__ ((packed)) hfa384x_usb_wmemreq_t;
+} __packed hfa384x_usb_wmemreq_t;
 
 typedef struct hfa384x_usb_rmemreq {
 	u16 type;
@@ -824,7 +824,7 @@ typedef struct hfa384x_usb_rmemreq {
 	u16 offset;
 	u16 page;
 	u8 pad[56];
-} __attribute__ ((packed)) hfa384x_usb_rmemreq_t;
+} __packed hfa384x_usb_rmemreq_t;
 
 /*------------------------------------*/
 /* Response (bulk IN) packet contents */
@@ -832,12 +832,12 @@ typedef struct hfa384x_usb_rmemreq {
 typedef struct hfa384x_usb_rxfrm {
 	hfa384x_rx_frame_t desc;
 	u8 data[WLAN_DATA_MAXLEN];
-} __attribute__ ((packed)) hfa384x_usb_rxfrm_t;
+} __packed hfa384x_usb_rxfrm_t;
 
 typedef struct hfa384x_usb_infofrm {
 	u16 type;
 	hfa384x_InfFrame_t info;
-} __attribute__ ((packed)) hfa384x_usb_infofrm_t;
+} __packed hfa384x_usb_infofrm_t;
 
 typedef struct hfa384x_usb_statusresp {
 	u16 type;
@@ -845,7 +845,7 @@ typedef struct hfa384x_usb_statusresp {
 	u16 resp0;
 	u16 resp1;
 	u16 resp2;
-} __attribute__ ((packed)) hfa384x_usb_cmdresp_t;
+} __packed hfa384x_usb_cmdresp_t;
 
 typedef hfa384x_usb_cmdresp_t hfa384x_usb_wridresp_t;
 
@@ -854,7 +854,7 @@ typedef struct hfa384x_usb_rridresp {
 	u16 frmlen;
 	u16 rid;
 	u8 data[HFA384x_RIDDATA_MAXLEN];
-} __attribute__ ((packed)) hfa384x_usb_rridresp_t;
+} __packed hfa384x_usb_rridresp_t;
 
 typedef hfa384x_usb_cmdresp_t hfa384x_usb_wmemresp_t;
 
@@ -862,17 +862,17 @@ typedef struct hfa384x_usb_rmemresp {
 	u16 type;
 	u16 frmlen;
 	u8 data[HFA384x_USB_RWMEM_MAXLEN];
-} __attribute__ ((packed)) hfa384x_usb_rmemresp_t;
+} __packed hfa384x_usb_rmemresp_t;
 
 typedef struct hfa384x_usb_bufavail {
 	u16 type;
 	u16 frmlen;
-} __attribute__ ((packed)) hfa384x_usb_bufavail_t;
+} __packed hfa384x_usb_bufavail_t;
 
 typedef struct hfa384x_usb_error {
 	u16 type;
 	u16 errortype;
-} __attribute__ ((packed)) hfa384x_usb_error_t;
+} __packed hfa384x_usb_error_t;
 
 /*----------------------------------------------------------*/
 /* Unions for packaging all the known packet types together */
@@ -885,7 +885,7 @@ typedef union hfa384x_usbout {
 	hfa384x_usb_rridreq_t rridreq;
 	hfa384x_usb_wmemreq_t wmemreq;
 	hfa384x_usb_rmemreq_t rmemreq;
-} __attribute__ ((packed)) hfa384x_usbout_t;
+} __packed hfa384x_usbout_t;
 
 typedef union hfa384x_usbin {
 	u16 type;
@@ -900,7 +900,7 @@ typedef union hfa384x_usbin {
 	hfa384x_usb_bufavail_t bufavail;
 	hfa384x_usb_error_t usberror;
 	u8 boguspad[3000];
-} __attribute__ ((packed)) hfa384x_usbin_t;
+} __packed hfa384x_usbin_t;
 
 /*--------------------------------------------------------------------
 PD record structures.
@@ -908,15 +908,15 @@ PD record structures.
 
 typedef struct hfa384x_pdr_pcb_partnum {
 	u8 num[8];
-} __attribute__ ((packed)) hfa384x_pdr_pcb_partnum_t;
+} __packed hfa384x_pdr_pcb_partnum_t;
 
 typedef struct hfa384x_pdr_pcb_tracenum {
 	u8 num[8];
-} __attribute__ ((packed)) hfa384x_pdr_pcb_tracenum_t;
+} __packed hfa384x_pdr_pcb_tracenum_t;
 
 typedef struct hfa384x_pdr_nic_serial {
 	u8 num[12];
-} __attribute__ ((packed)) hfa384x_pdr_nic_serial_t;
+} __packed hfa384x_pdr_nic_serial_t;
 
 typedef struct hfa384x_pdr_mkk_measurements {
 	double carrier_freq;
@@ -934,138 +934,138 @@ typedef struct hfa384x_pdr_mkk_measurements {
 	double rx_spur_f2;
 	double rx_spur_l1;
 	double rx_spur_l2;
-} __attribute__ ((packed)) hfa384x_pdr_mkk_measurements_t;
+} __packed hfa384x_pdr_mkk_measurements_t;
 
 typedef struct hfa384x_pdr_nic_ramsize {
 	u8 size[12];		/* units of KB */
-} __attribute__ ((packed)) hfa384x_pdr_nic_ramsize_t;
+} __packed hfa384x_pdr_nic_ramsize_t;
 
 typedef struct hfa384x_pdr_mfisuprange {
 	u16 id;
 	u16 variant;
 	u16 bottom;
 	u16 top;
-} __attribute__ ((packed)) hfa384x_pdr_mfisuprange_t;
+} __packed hfa384x_pdr_mfisuprange_t;
 
 typedef struct hfa384x_pdr_cfisuprange {
 	u16 id;
 	u16 variant;
 	u16 bottom;
 	u16 top;
-} __attribute__ ((packed)) hfa384x_pdr_cfisuprange_t;
+} __packed hfa384x_pdr_cfisuprange_t;
 
 typedef struct hfa384x_pdr_nicid {
 	u16 id;
 	u16 variant;
 	u16 major;
 	u16 minor;
-} __attribute__ ((packed)) hfa384x_pdr_nicid_t;
+} __packed hfa384x_pdr_nicid_t;
 
 typedef struct hfa384x_pdr_refdac_measurements {
 	u16 value[0];
-} __attribute__ ((packed)) hfa384x_pdr_refdac_measurements_t;
+} __packed hfa384x_pdr_refdac_measurements_t;
 
 typedef struct hfa384x_pdr_vgdac_measurements {
 	u16 value[0];
-} __attribute__ ((packed)) hfa384x_pdr_vgdac_measurements_t;
+} __packed hfa384x_pdr_vgdac_measurements_t;
 
 typedef struct hfa384x_pdr_level_comp_measurements {
 	u16 value[0];
-} __attribute__ ((packed)) hfa384x_pdr_level_compc_measurements_t;
+} __packed hfa384x_pdr_level_compc_measurements_t;
 
 typedef struct hfa384x_pdr_mac_address {
 	u8 addr[6];
-} __attribute__ ((packed)) hfa384x_pdr_mac_address_t;
+} __packed hfa384x_pdr_mac_address_t;
 
 typedef struct hfa384x_pdr_mkk_callname {
 	u8 callname[8];
-} __attribute__ ((packed)) hfa384x_pdr_mkk_callname_t;
+} __packed hfa384x_pdr_mkk_callname_t;
 
 typedef struct hfa384x_pdr_regdomain {
 	u16 numdomains;
 	u16 domain[5];
-} __attribute__ ((packed)) hfa384x_pdr_regdomain_t;
+} __packed hfa384x_pdr_regdomain_t;
 
 typedef struct hfa384x_pdr_allowed_channel {
 	u16 ch_bitmap;
-} __attribute__ ((packed)) hfa384x_pdr_allowed_channel_t;
+} __packed hfa384x_pdr_allowed_channel_t;
 
 typedef struct hfa384x_pdr_default_channel {
 	u16 channel;
-} __attribute__ ((packed)) hfa384x_pdr_default_channel_t;
+} __packed hfa384x_pdr_default_channel_t;
 
 typedef struct hfa384x_pdr_privacy_option {
 	u16 available;
-} __attribute__ ((packed)) hfa384x_pdr_privacy_option_t;
+} __packed hfa384x_pdr_privacy_option_t;
 
 typedef struct hfa384x_pdr_temptype {
 	u16 type;
-} __attribute__ ((packed)) hfa384x_pdr_temptype_t;
+} __packed hfa384x_pdr_temptype_t;
 
 typedef struct hfa384x_pdr_refdac_setup {
 	u16 ch_value[14];
-} __attribute__ ((packed)) hfa384x_pdr_refdac_setup_t;
+} __packed hfa384x_pdr_refdac_setup_t;
 
 typedef struct hfa384x_pdr_vgdac_setup {
 	u16 ch_value[14];
-} __attribute__ ((packed)) hfa384x_pdr_vgdac_setup_t;
+} __packed hfa384x_pdr_vgdac_setup_t;
 
 typedef struct hfa384x_pdr_level_comp_setup {
 	u16 ch_value[14];
-} __attribute__ ((packed)) hfa384x_pdr_level_comp_setup_t;
+} __packed hfa384x_pdr_level_comp_setup_t;
 
 typedef struct hfa384x_pdr_trimdac_setup {
 	u16 trimidac;
 	u16 trimqdac;
-} __attribute__ ((packed)) hfa384x_pdr_trimdac_setup_t;
+} __packed hfa384x_pdr_trimdac_setup_t;
 
 typedef struct hfa384x_pdr_ifr_setting {
 	u16 value[3];
-} __attribute__ ((packed)) hfa384x_pdr_ifr_setting_t;
+} __packed hfa384x_pdr_ifr_setting_t;
 
 typedef struct hfa384x_pdr_rfr_setting {
 	u16 value[3];
-} __attribute__ ((packed)) hfa384x_pdr_rfr_setting_t;
+} __packed hfa384x_pdr_rfr_setting_t;
 
 typedef struct hfa384x_pdr_hfa3861_baseline {
 	u16 value[50];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_baseline_t;
+} __packed hfa384x_pdr_hfa3861_baseline_t;
 
 typedef struct hfa384x_pdr_hfa3861_shadow {
 	u32 value[32];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_shadow_t;
+} __packed hfa384x_pdr_hfa3861_shadow_t;
 
 typedef struct hfa384x_pdr_hfa3861_ifrf {
 	u32 value[20];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_ifrf_t;
+} __packed hfa384x_pdr_hfa3861_ifrf_t;
 
 typedef struct hfa384x_pdr_hfa3861_chcalsp {
 	u16 value[14];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_chcalsp_t;
+} __packed hfa384x_pdr_hfa3861_chcalsp_t;
 
 typedef struct hfa384x_pdr_hfa3861_chcali {
 	u16 value[17];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_chcali_t;
+} __packed hfa384x_pdr_hfa3861_chcali_t;
 
 typedef struct hfa384x_pdr_hfa3861_nic_config {
 	u16 config_bitmap;
-} __attribute__ ((packed)) hfa384x_pdr_nic_config_t;
+} __packed hfa384x_pdr_nic_config_t;
 
 typedef struct hfa384x_pdr_hfo_delay {
 	u8 hfo_delay;
-} __attribute__ ((packed)) hfa384x_hfo_delay_t;
+} __packed hfa384x_hfo_delay_t;
 
 typedef struct hfa384x_pdr_hfa3861_manf_testsp {
 	u16 value[30];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_manf_testsp_t;
+} __packed hfa384x_pdr_hfa3861_manf_testsp_t;
 
 typedef struct hfa384x_pdr_hfa3861_manf_testi {
 	u16 value[30];
-} __attribute__ ((packed)) hfa384x_pdr_hfa3861_manf_testi_t;
+} __packed hfa384x_pdr_hfa3861_manf_testi_t;
 
 typedef struct hfa384x_end_of_pda {
 	u16 crc;
-} __attribute__ ((packed)) hfa384x_pdr_end_of_pda_t;
+} __packed hfa384x_pdr_end_of_pda_t;
 
 typedef struct hfa384x_pdrec {
 	u16 len;		/* in words */
@@ -1107,7 +1107,7 @@ typedef struct hfa384x_pdrec {
 		hfa384x_pdr_end_of_pda_t end_of_pda;
 
 	} data;
-} __attribute__ ((packed)) hfa384x_pdrec_t;
+} __packed hfa384x_pdrec_t;
 
 #ifdef __KERNEL__
 /*--------------------------------------------------------------------
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index a6efc03..7843dfd 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -612,10 +612,8 @@ void hfa384x_destroy(hfa384x_t *hw)
 		hfa384x_drvr_stop(hw);
 	hw->state = HFA384x_STATE_PREINIT;
 
-	if (hw->scanresults) {
-		kfree(hw->scanresults);
-		hw->scanresults = NULL;
-	}
+	kfree(hw->scanresults);
+	hw->scanresults = NULL;
 
 	/* Now to clean out the auth queue */
 	while ((skb = skb_dequeue(&hw->authq)))
diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c
index 146f365..f53a27a 100644
--- a/drivers/staging/wlan-ng/p80211conv.c
+++ b/drivers/staging/wlan-ng/p80211conv.c
@@ -379,7 +379,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv,
 
 	} else if ((payload_length >= sizeof(struct wlan_llc) +
 		sizeof(struct wlan_snap))
-		&&(e_llc->dsap == 0xaa)
+		&& (e_llc->dsap == 0xaa)
 		&& (e_llc->ssap == 0xaa)
 		&& (e_llc->ctl == 0x03)
 		   &&
@@ -415,7 +415,7 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv,
 
 	} else if ((payload_length >= sizeof(struct wlan_llc) +
 		sizeof(struct wlan_snap))
-		&&(e_llc->dsap == 0xaa)
+		&& (e_llc->dsap == 0xaa)
 		&& (e_llc->ssap == 0xaa)
 		&& (e_llc->ctl == 0x03)) {
 		pr_debug("802.1h/RFC1042 len: %d\n", payload_length);
diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h
index ea493aa..e031a74 100644
--- a/drivers/staging/wlan-ng/p80211conv.h
+++ b/drivers/staging/wlan-ng/p80211conv.h
@@ -134,20 +134,20 @@ struct wlan_ethhdr {
 	u8 daddr[WLAN_ETHADDR_LEN];
 	u8 saddr[WLAN_ETHADDR_LEN];
 	u16 type;
-} __attribute__ ((packed));
+} __packed;
 
 /* local llc header type */
 struct wlan_llc {
 	u8 dsap;
 	u8 ssap;
 	u8 ctl;
-} __attribute__ ((packed));
+} __packed;
 
 /* local snap header type */
 struct wlan_snap {
 	u8 oui[WLAN_IEEE_OUI_LEN];
 	u16 type;
-} __attribute__ ((packed));
+} __packed;
 
 /* Circular include trick */
 struct wlandevice;
diff --git a/drivers/staging/wlan-ng/p80211hdr.h b/drivers/staging/wlan-ng/p80211hdr.h
index 1f6e4eb..66b5e20 100644
--- a/drivers/staging/wlan-ng/p80211hdr.h
+++ b/drivers/staging/wlan-ng/p80211hdr.h
@@ -154,7 +154,7 @@ struct p80211_hdr_a3 {
 	u8 a2[ETH_ALEN];
 	u8 a3[ETH_ALEN];
 	u16 seq;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211_hdr_a4 {
 	u16 fc;
@@ -164,12 +164,12 @@ struct p80211_hdr_a4 {
 	u8 a3[ETH_ALEN];
 	u16 seq;
 	u8 a4[ETH_ALEN];
-} __attribute__ ((packed));
+} __packed;
 
 union p80211_hdr {
 	struct p80211_hdr_a3 a3;
 	struct p80211_hdr_a4 a4;
-} __attribute__ ((packed));
+} __packed;
 
 /* Frame and header length macros */
 
diff --git a/drivers/staging/wlan-ng/p80211ioctl.h b/drivers/staging/wlan-ng/p80211ioctl.h
index 0d47765..06c5e36 100644
--- a/drivers/staging/wlan-ng/p80211ioctl.h
+++ b/drivers/staging/wlan-ng/p80211ioctl.h
@@ -84,6 +84,6 @@ struct p80211ioctl_req {
 	u32 magic;
 	u16 len;
 	u32 result;
-} __attribute__ ((packed));
+} __packed;
 
 #endif /* _P80211IOCTL_H */
diff --git a/drivers/staging/wlan-ng/p80211metastruct.h b/drivers/staging/wlan-ng/p80211metastruct.h
index a8a4e3b..c501162 100644
--- a/drivers/staging/wlan-ng/p80211metastruct.h
+++ b/drivers/staging/wlan-ng/p80211metastruct.h
@@ -53,7 +53,7 @@ struct p80211msg_dot11req_mibget {
 	u8 devname[WLAN_DEVNAMELEN_MAX];
 	p80211item_unk392_t mibattribute;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_dot11req_mibset {
 	u32 msgcode;
@@ -61,7 +61,7 @@ struct p80211msg_dot11req_mibset {
 	u8 devname[WLAN_DEVNAMELEN_MAX];
 	p80211item_unk392_t mibattribute;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_dot11req_scan {
 	u32 msgcode;
@@ -81,7 +81,7 @@ struct p80211msg_dot11req_scan {
 	p80211item_uint32_t resultcode;
 	p80211item_uint32_t numbss;
 	p80211item_uint32_t append;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_dot11req_scan_results {
 	u32 msgcode;
@@ -130,7 +130,7 @@ struct p80211msg_dot11req_scan_results {
 	p80211item_uint32_t supprate6;
 	p80211item_uint32_t supprate7;
 	p80211item_uint32_t supprate8;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_dot11req_start {
 	u32 msgcode;
@@ -168,7 +168,7 @@ struct p80211msg_dot11req_start {
 	p80211item_uint32_t operationalrate7;
 	p80211item_uint32_t operationalrate8;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_lnxreq_ifstate {
 	u32 msgcode;
@@ -176,7 +176,7 @@ struct p80211msg_lnxreq_ifstate {
 	u8 devname[WLAN_DEVNAMELEN_MAX];
 	p80211item_uint32_t ifstate;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_lnxreq_wlansniff {
 	u32 msgcode;
@@ -190,7 +190,7 @@ struct p80211msg_lnxreq_wlansniff {
 	p80211item_uint32_t stripfcs;
 	p80211item_uint32_t packet_trunc;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_lnxreq_hostwep {
 	u32 msgcode;
@@ -199,7 +199,7 @@ struct p80211msg_lnxreq_hostwep {
 	p80211item_uint32_t resultcode;
 	p80211item_uint32_t decrypt;
 	p80211item_uint32_t encrypt;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_lnxreq_commsquality {
 	u32 msgcode;
@@ -211,7 +211,7 @@ struct p80211msg_lnxreq_commsquality {
 	p80211item_uint32_t level;
 	p80211item_uint32_t noise;
 	p80211item_uint32_t txrate;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_lnxreq_autojoin {
 	u32 msgcode;
@@ -221,7 +221,7 @@ struct p80211msg_lnxreq_autojoin {
 	u8 pad_19D[3];
 	p80211item_uint32_t authtype;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_p2req_readpda {
 	u32 msgcode;
@@ -229,7 +229,7 @@ struct p80211msg_p2req_readpda {
 	u8 devname[WLAN_DEVNAMELEN_MAX];
 	p80211item_unk1024_t pda;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_p2req_ramdl_state {
 	u32 msgcode;
@@ -238,7 +238,7 @@ struct p80211msg_p2req_ramdl_state {
 	p80211item_uint32_t enable;
 	p80211item_uint32_t exeaddr;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_p2req_ramdl_write {
 	u32 msgcode;
@@ -248,7 +248,7 @@ struct p80211msg_p2req_ramdl_write {
 	p80211item_uint32_t len;
 	p80211item_unk4096_t data;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_p2req_flashdl_state {
 	u32 msgcode;
@@ -256,7 +256,7 @@ struct p80211msg_p2req_flashdl_state {
 	u8 devname[WLAN_DEVNAMELEN_MAX];
 	p80211item_uint32_t enable;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 struct p80211msg_p2req_flashdl_write {
 	u32 msgcode;
@@ -266,6 +266,6 @@ struct p80211msg_p2req_flashdl_write {
 	p80211item_uint32_t len;
 	p80211item_unk4096_t data;
 	p80211item_uint32_t resultcode;
-} __attribute__ ((packed));
+} __packed;
 
 #endif
diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h
index 3b5e811..2610824 100644
--- a/drivers/staging/wlan-ng/p80211mgmt.h
+++ b/drivers/staging/wlan-ng/p80211mgmt.h
@@ -222,21 +222,21 @@
 typedef struct wlan_ie {
 	u8 eid;
 	u8 len;
-} __attribute__ ((packed)) wlan_ie_t;
+} __packed wlan_ie_t;
 
 /*-- Service Set Identity (SSID)  -----------------*/
 typedef struct wlan_ie_ssid {
 	u8 eid;
 	u8 len;
 	u8 ssid[1];		/* may be zero, ptrs may overlap */
-} __attribute__ ((packed)) wlan_ie_ssid_t;
+} __packed wlan_ie_ssid_t;
 
 /*-- Supported Rates  -----------------------------*/
 typedef struct wlan_ie_supp_rates {
 	u8 eid;
 	u8 len;
 	u8 rates[1];		/* had better be at LEAST one! */
-} __attribute__ ((packed)) wlan_ie_supp_rates_t;
+} __packed wlan_ie_supp_rates_t;
 
 /*-- FH Parameter Set  ----------------------------*/
 typedef struct wlan_ie_fh_parms {
@@ -246,14 +246,14 @@ typedef struct wlan_ie_fh_parms {
 	u8 hopset;
 	u8 hoppattern;
 	u8 hopindex;
-} __attribute__ ((packed)) wlan_ie_fh_parms_t;
+} __packed wlan_ie_fh_parms_t;
 
 /*-- DS Parameter Set  ----------------------------*/
 typedef struct wlan_ie_ds_parms {
 	u8 eid;
 	u8 len;
 	u8 curr_ch;
-} __attribute__ ((packed)) wlan_ie_ds_parms_t;
+} __packed wlan_ie_ds_parms_t;
 
 /*-- CF Parameter Set  ----------------------------*/
 
@@ -264,7 +264,7 @@ typedef struct wlan_ie_cf_parms {
 	u8 cfp_period;
 	u16 cfp_maxdur;
 	u16 cfp_durremaining;
-} __attribute__ ((packed)) wlan_ie_cf_parms_t;
+} __packed wlan_ie_cf_parms_t;
 
 /*-- TIM ------------------------------------------*/
 typedef struct wlan_ie_tim {
@@ -274,21 +274,21 @@ typedef struct wlan_ie_tim {
 	u8 dtim_period;
 	u8 bitmap_ctl;
 	u8 virt_bm[1];
-} __attribute__ ((packed)) wlan_ie_tim_t;
+} __packed wlan_ie_tim_t;
 
 /*-- IBSS Parameter Set ---------------------------*/
 typedef struct wlan_ie_ibss_parms {
 	u8 eid;
 	u8 len;
 	u16 atim_win;
-} __attribute__ ((packed)) wlan_ie_ibss_parms_t;
+} __packed wlan_ie_ibss_parms_t;
 
 /*-- Challenge Text  ------------------------------*/
 typedef struct wlan_ie_challenge {
 	u8 eid;
 	u8 len;
 	u8 challenge[1];
-} __attribute__ ((packed)) wlan_ie_challenge_t;
+} __packed wlan_ie_challenge_t;
 
 /*-------------------------------------------------*/
 /*  Frame Types  */
diff --git a/drivers/staging/wlan-ng/p80211msg.h b/drivers/staging/wlan-ng/p80211msg.h
index 8e0f9a0..43d2f97 100644
--- a/drivers/staging/wlan-ng/p80211msg.h
+++ b/drivers/staging/wlan-ng/p80211msg.h
@@ -54,6 +54,6 @@ struct p80211msg {
 	u32 msgcode;
 	u32 msglen;
 	u8 devname[WLAN_DEVNAMELEN_MAX];
-} __attribute__ ((packed));
+} __packed;
 
 #endif /* _P80211MSG_H */
diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h
index 9dec859..f043090 100644
--- a/drivers/staging/wlan-ng/p80211types.h
+++ b/drivers/staging/wlan-ng/p80211types.h
@@ -217,49 +217,49 @@ typedef struct p80211enum {
 /* Template pascal string */
 typedef struct p80211pstr {
 	u8 len;
-} __attribute__ ((packed)) p80211pstr_t;
+} __packed p80211pstr_t;
 
 typedef struct p80211pstrd {
 	u8 len;
 	u8 data[0];
-} __attribute__ ((packed)) p80211pstrd_t;
+} __packed p80211pstrd_t;
 
 /* Maximum pascal string */
 typedef struct p80211pstr255 {
 	u8 len;
 	u8 data[MAXLEN_PSTR255];
-} __attribute__ ((packed)) p80211pstr255_t;
+} __packed p80211pstr255_t;
 
 /* pascal string for macaddress and bssid */
 typedef struct p80211pstr6 {
 	u8 len;
 	u8 data[MAXLEN_PSTR6];
-} __attribute__ ((packed)) p80211pstr6_t;
+} __packed p80211pstr6_t;
 
 /* pascal string for channel list */
 typedef struct p80211pstr14 {
 	u8 len;
 	u8 data[MAXLEN_PSTR14];
-} __attribute__ ((packed)) p80211pstr14_t;
+} __packed p80211pstr14_t;
 
 /* pascal string for ssid */
 typedef struct p80211pstr32 {
 	u8 len;
 	u8 data[MAXLEN_PSTR32];
-} __attribute__ ((packed)) p80211pstr32_t;
+} __packed p80211pstr32_t;
 
 /* MAC address array */
 typedef struct p80211macarray {
 	u32 cnt;
 	u8 data[1][MAXLEN_PSTR6];
-} __attribute__ ((packed)) p80211macarray_t;
+} __packed p80211macarray_t;
 
 /* prototype template */
 typedef struct p80211item {
 	u32 did;
 	u16 status;
 	u16 len;
-} __attribute__ ((packed)) p80211item_t;
+} __packed p80211item_t;
 
 /* prototype template w/ data item */
 typedef struct p80211itemd {
@@ -267,7 +267,7 @@ typedef struct p80211itemd {
 	u16 status;
 	u16 len;
 	u8 data[0];
-} __attribute__ ((packed)) p80211itemd_t;
+} __packed p80211itemd_t;
 
 /* message data item for int, BOUNDEDINT, ENUMINT */
 typedef struct p80211item_uint32 {
@@ -275,7 +275,7 @@ typedef struct p80211item_uint32 {
 	u16 status;
 	u16 len;
 	u32 data;
-} __attribute__ ((packed)) p80211item_uint32_t;
+} __packed p80211item_uint32_t;
 
 /* message data item for OCTETSTR, DISPLAYSTR */
 typedef struct p80211item_pstr6 {
@@ -283,7 +283,7 @@ typedef struct p80211item_pstr6 {
 	u16 status;
 	u16 len;
 	p80211pstr6_t data;
-} __attribute__ ((packed)) p80211item_pstr6_t;
+} __packed p80211item_pstr6_t;
 
 /* message data item for OCTETSTR, DISPLAYSTR */
 typedef struct p80211item_pstr14 {
@@ -291,7 +291,7 @@ typedef struct p80211item_pstr14 {
 	u16 status;
 	u16 len;
 	p80211pstr14_t data;
-} __attribute__ ((packed)) p80211item_pstr14_t;
+} __packed p80211item_pstr14_t;
 
 /* message data item for OCTETSTR, DISPLAYSTR */
 typedef struct p80211item_pstr32 {
@@ -299,7 +299,7 @@ typedef struct p80211item_pstr32 {
 	u16 status;
 	u16 len;
 	p80211pstr32_t data;
-} __attribute__ ((packed)) p80211item_pstr32_t;
+} __packed p80211item_pstr32_t;
 
 /* message data item for OCTETSTR, DISPLAYSTR */
 typedef struct p80211item_pstr255 {
@@ -307,7 +307,7 @@ typedef struct p80211item_pstr255 {
 	u16 status;
 	u16 len;
 	p80211pstr255_t data;
-} __attribute__ ((packed)) p80211item_pstr255_t;
+} __packed p80211item_pstr255_t;
 
 /* message data item for UNK 392, namely mib items */
 typedef struct p80211item_unk392 {
@@ -315,7 +315,7 @@ typedef struct p80211item_unk392 {
 	u16 status;
 	u16 len;
 	u8 data[MAXLEN_MIBATTRIBUTE];
-} __attribute__ ((packed)) p80211item_unk392_t;
+} __packed p80211item_unk392_t;
 
 /* message data item for UNK 1025, namely p2 pdas */
 typedef struct p80211item_unk1024 {
@@ -323,7 +323,7 @@ typedef struct p80211item_unk1024 {
 	u16 status;
 	u16 len;
 	u8 data[1024];
-} __attribute__ ((packed)) p80211item_unk1024_t;
+} __packed p80211item_unk1024_t;
 
 /* message data item for UNK 4096, namely p2 download chunks */
 typedef struct p80211item_unk4096 {
@@ -331,7 +331,7 @@ typedef struct p80211item_unk4096 {
 	u16 status;
 	u16 len;
 	u8 data[4096];
-} __attribute__ ((packed)) p80211item_unk4096_t;
+} __packed p80211item_unk4096_t;
 
 struct catlistitem;
 
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index fd5ddb2..729d03d 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -443,8 +443,7 @@ void free_chunks(struct imgchunk *fchunk, unsigned int *nfchunks)
 {
 	int i;
 	for (i = 0; i < *nfchunks; i++) {
-		if (fchunk[i].data != NULL)
-			kfree(fchunk[i].data);
+		kfree(fchunk[i].data);
 	}
 	*nfchunks = 0;
 	memset(fchunk, 0, sizeof(*fchunk));
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
index f2ca6b1..3c8c7de 100644
--- a/drivers/staging/xgifb/Makefile
+++ b/drivers/staging/xgifb/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_FB_XGI)  += xgifb.o
 
-xgifb-y := XGI_main_26.o XGI_accel.o vb_init.o vb_setmode.o vb_util.o vb_ext.o
+xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o vb_util.o vb_ext.o
 
diff --git a/drivers/staging/xgifb/XGI_accel.c b/drivers/staging/xgifb/XGI_accel.c
deleted file mode 100644
index 7954974..0000000
--- a/drivers/staging/xgifb/XGI_accel.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * XGI 300/630/730/540/315/550/650/740 frame buffer driver
- * for Linux kernels 2.4.x and 2.5.x
- *
- * 2D acceleration part
- *
- * Based on the X driver's XGI300_accel.c which is
- *     Copyright Xavier Ducoin <x.ducoin@lectra.com>
- *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
- * and XGI310_accel.c which is
- *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
- *
- * Author: Thomas Winischhofer <thomas@winischhofer.net>
- *			(see http://www.winischhofer.net/
- *			for more information and updates)
- */
-
-//#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/selection.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/vt_kern.h>
-#include <linux/capability.h>
-#include <linux/fs.h>
-#include <linux/agp_backend.h>
-
-#include <linux/types.h>
-#include <asm/io.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "vgatypes.h"
-#include "vb_struct.h"
-#include "XGIfb.h"
-#include "XGI_accel.h"
-
-static const int XGIALUConv[] =
-{
-    0x00,       /* dest = 0;            0,      GXclear,        0 */
-    0x88,       /* dest &= src;         DSa,    GXand,          0x1 */
-    0x44,       /* dest = src & ~dest;  SDna,   GXandReverse,   0x2 */
-    0xCC,       /* dest = src;          S,      GXcopy,         0x3 */
-    0x22,       /* dest &= ~src;        DSna,   GXandInverted,  0x4 */
-    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
-    0x66,       /* dest = ^src;         DSx,    GXxor,          0x6 */
-    0xEE,       /* dest |= src;         DSo,    GXor,           0x7 */
-    0x11,       /* dest = ~src & ~dest; DSon,   GXnor,          0x8 */
-    0x99,       /* dest ^= ~src ;       DSxn,   GXequiv,        0x9 */
-    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
-    0xDD,       /* dest = src|~dest ;   SDno,   GXorReverse,    0xB */
-    0x33,       /* dest = ~src;         Sn,     GXcopyInverted, 0xC */
-    0xBB,       /* dest |= ~src;        DSno,   GXorInverted,   0xD */
-    0x77,       /* dest = ~src|~dest;   DSan,   GXnand,         0xE */
-    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
-};
-/* same ROP but with Pattern as Source */
-static const int XGIPatALUConv[] =
-{
-    0x00,       /* dest = 0;            0,      GXclear,        0 */
-    0xA0,       /* dest &= src;         DPa,    GXand,          0x1 */
-    0x50,       /* dest = src & ~dest;  PDna,   GXandReverse,   0x2 */
-    0xF0,       /* dest = src;          P,      GXcopy,         0x3 */
-    0x0A,       /* dest &= ~src;        DPna,   GXandInverted,  0x4 */
-    0xAA,       /* dest = dest;         D,      GXnoop,         0x5 */
-    0x5A,       /* dest = ^src;         DPx,    GXxor,          0x6 */
-    0xFA,       /* dest |= src;         DPo,    GXor,           0x7 */
-    0x05,       /* dest = ~src & ~dest; DPon,   GXnor,          0x8 */
-    0xA5,       /* dest ^= ~src ;       DPxn,   GXequiv,        0x9 */
-    0x55,       /* dest = ~dest;        Dn,     GXInvert,       0xA */
-    0xF5,       /* dest = src|~dest ;   PDno,   GXorReverse,    0xB */
-    0x0F,       /* dest = ~src;         Pn,     GXcopyInverted, 0xC */
-    0xAF,       /* dest |= ~src;        DPno,   GXorInverted,   0xD */
-    0x5F,       /* dest = ~src|~dest;   DPan,   GXnand,         0xE */
-    0xFF,       /* dest = 0xFF;         1,      GXset,          0xF */
-};
-
-static const unsigned char myrops[] = {
-   	3, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
-   };
-
-/* 300 series */
-static void
-XGI310Sync(void)
-{
-	XGI310Idle
-}
-
-/* 310/325 series ------------------------------------------------ */
-
-static void
-XGI310SetupForScreenToScreenCopy(int xdir, int ydir, int rop,
-                                unsigned int planemask, int trans_color)
-{
-	XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
-	XGI310SetupSRCPitch(xgi_video_info.video_linelength)
-	XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
-	if (trans_color != -1) {
-		XGI310SetupROP(0x0A)
-		XGI310SetupSRCTrans(trans_color)
-		XGI310SetupCMDFlag(TRANSPARENT_BITBLT)
-	} else {
-	        XGI310SetupROP(XGIALUConv[rop])
-		/* Set command - not needed, both 0 */
-		/* XGISetupCMDFlag(BITBLT | SRCVIDEO) */
-	}
-	XGI310SetupCMDFlag(xgi_video_info.XGI310_AccelDepth)
-	/* TW: The 310/325 series is smart enough to know the direction */
-}
-
-static void
-XGI310SubsequentScreenToScreenCopy(int src_x, int src_y, int dst_x, int dst_y,
-                                int width, int height)
-{
-	long srcbase, dstbase;
-	int mymin, mymax;
-
-	srcbase = dstbase = 0;
-	mymin = min(src_y, dst_y);
-	mymax = max(src_y, dst_y);
-
-	/* Although the chip knows the direction to use
-	 * if the source and destination areas overlap,
-	 * that logic fails if we fiddle with the bitmap
-	 * addresses. Therefore, we check if the source
-	 * and destination blitting areas overlap and
-	 * adapt the bitmap addresses synchronously
-	 * if the coordinates exceed the valid range.
-	 * The the areas do not overlap, we do our
-	 * normal check.
-	 */
-	if((mymax - mymin) < height) {
-	   if((src_y >= 2048) || (dst_y >= 2048)) {
-	      srcbase = xgi_video_info.video_linelength * mymin;
-	      dstbase = xgi_video_info.video_linelength * mymin;
-	      src_y -= mymin;
-	      dst_y -= mymin;
-	   }
-	} else {
-	   if(src_y >= 2048) {
-	      srcbase = xgi_video_info.video_linelength * src_y;
-	      src_y = 0;
-	   }
-	   if(dst_y >= 2048) {
-	      dstbase = xgi_video_info.video_linelength * dst_y;
-	      dst_y = 0;
-	   }
-	}
-
-	XGI310SetupSRCBase(srcbase);
-	XGI310SetupDSTBase(dstbase);
-	XGI310SetupRect(width, height)
-	XGI310SetupSRCXY(src_x, src_y)
-	XGI310SetupDSTXY(dst_x, dst_y)
-	XGI310DoCMD
-}
-
-static void
-XGI310SetupForSolidFill(int color, int rop, unsigned int planemask)
-{
-	XGI310SetupPATFG(color)
-	XGI310SetupDSTRect(xgi_video_info.video_linelength, 0xFFF)
-	XGI310SetupDSTColorDepth(xgi_video_info.DstColor);
-	XGI310SetupROP(XGIPatALUConv[rop])
-	XGI310SetupCMDFlag(PATFG | xgi_video_info.XGI310_AccelDepth)
-}
-
-static void
-XGI310SubsequentSolidFillRect(int x, int y, int w, int h)
-{
-	long dstbase;
-
-	dstbase = 0;
-	if(y >= 2048) {
-		dstbase = xgi_video_info.video_linelength * y;
-		y = 0;
-	}
-	XGI310SetupDSTBase(dstbase)
-	XGI310SetupDSTXY(x,y)
-	XGI310SetupRect(w,h)
-	XGI310SetupCMDFlag(BITBLT)
-	XGI310DoCMD
-}
-
-/* --------------------------------------------------------------------- */
-
-/* The exported routines */
-
-int XGIfb_initaccel(void)
-{
-#ifdef XGIFB_USE_SPINLOCKS
-    spin_lock_init(&xgi_video_info.lockaccel);
-#endif
-    return(0);
-}
-
-void XGIfb_syncaccel(void)
-{
-
-    XGI310Sync();
-
-}
-
-int fbcon_XGI_sync(struct fb_info *info)
-{
-    if(!XGIfb_accel) return 0;
-    CRITFLAGS
-
-    XGI310Sync();
-
-   CRITEND
-   return 0;
-}
-
-void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
-   int col=0;
-   CRITFLAGS
-
-
-   if(!rect->width || !rect->height)
-   	return;
-
-   if(!XGIfb_accel) {
-	cfb_fillrect(info, rect);
-	return;
-   }
-
-   switch(info->var.bits_per_pixel) {
-		case 8: col = rect->color;
-			break;
-		case 16: col = ((u32 *)(info->pseudo_palette))[rect->color];
-			 break;
-		case 32: col = ((u32 *)(info->pseudo_palette))[rect->color];
-			 break;
-	}
-
-
-	   CRITBEGIN
-	   XGI310SetupForSolidFill(col, myrops[rect->rop], 0);
-	   XGI310SubsequentSolidFillRect(rect->dx, rect->dy, rect->width, rect->height);
-	   CRITEND
-	   XGI310Sync();
-
-
-}
-
-void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
-   int xdir, ydir;
-   CRITFLAGS
-
-
-   if(!XGIfb_accel) {
-   	cfb_copyarea(info, area);
-	return;
-   }
-
-   if(!area->width || !area->height)
-   	return;
-
-   if(area->sx < area->dx) xdir = 0;
-   else                    xdir = 1;
-   if(area->sy < area->dy) ydir = 0;
-   else                    ydir = 1;
-
-      CRITBEGIN
-      XGI310SetupForScreenToScreenCopy(xdir, ydir, 3, 0, -1);
-      XGI310SubsequentScreenToScreenCopy(area->sx, area->sy, area->dx, area->dy, area->width, area->height);
-      CRITEND
-      XGI310Sync();
-
-}
-
-
-
diff --git a/drivers/staging/xgifb/XGI_accel.h b/drivers/staging/xgifb/XGI_accel.h
deleted file mode 100644
index 5a0395b..0000000
--- a/drivers/staging/xgifb/XGI_accel.h
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * XGI 300/630/730/540/315/550/650/740 frame buffer driver
- * for Linux kernels 2.4.x and 2.5.x
- *
- * 2D acceleration part
- *
- * Based on the X driver's XGI300_accel.h which is
- *     Copyright Xavier Ducoin <x.ducoin@lectra.com>
- *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
- * and XGI310_accel.h which is
- *     Copyright 2002 by Thomas Winischhofer, Vienna, Austria
- *
- * Author:   Thomas Winischhofer <thomas@winischhofer.net>:
- *			(see http://www.winischhofer.net/
- *			for more information and updates)
- */
-
-#ifndef _XGIFB_ACCEL_H
-#define _XGIFB_ACCEL_H
-
-/* Guard accelerator accesses with spin_lock_irqsave? Works well without. */
-#undef XGIFB_USE_SPINLOCKS
-
-#ifdef XGIFB_USE_SPINLOCKS
-#include <linux/spinlock.h>
-#define CRITBEGIN  spin_lock_irqsave(&xgi_video_info.lockaccel), critflags);
-#define CRITEND	   spin_unlock_irqrestore(&xgi_video_info.lockaccel), critflags);
-#define CRITFLAGS  unsigned long critflags;
-#else
-#define CRITBEGIN
-#define CRITEND
-#define CRITFLAGS
-#endif
-
-/* Definitions for the XGI engine communication. */
-
-#define PATREGSIZE      384  /* Pattern register size. 384 bytes @ 0x8300 */
-#define BR(x)   (0x8200 | (x) << 2)
-#define PBR(x)  (0x8300 | (x) << 2)
-
-/* XGI300 engine commands */
-#define BITBLT                  0x00000000  /* Blit */
-#define COLOREXP                0x00000001  /* Color expand */
-#define ENCOLOREXP              0x00000002  /* Enhanced color expand */
-#define MULTIPLE_SCANLINE       0x00000003  /* ? */
-#define LINE                    0x00000004  /* Draw line */
-#define TRAPAZOID_FILL          0x00000005  /* Fill trapezoid */
-#define TRANSPARENT_BITBLT      0x00000006  /* Transparent Blit */
-
-/* Additional engine commands for 310/325 */
-#define ALPHA_BLEND		0x00000007  /* Alpha blend ? */
-#define A3D_FUNCTION		0x00000008  /* 3D command ? */
-#define	CLEAR_Z_BUFFER		0x00000009  /* ? */
-#define GRADIENT_FILL		0x0000000A  /* Gradient fill */
-#define STRETCH_BITBLT		0x0000000B  /* Stretched Blit */
-
-/* source select */
-#define SRCVIDEO                0x00000000  /* source is video RAM */
-#define SRCSYSTEM               0x00000010  /* source is system memory */
-#define SRCCPUBLITBUF           SRCSYSTEM   /* source is CPU-driven BitBuffer (for color expand) */
-#define SRCAGP                  0x00000020  /* source is AGP memory (?) */
-
-/* Pattern flags */
-#define PATFG                   0x00000000  /* foreground color */
-#define PATPATREG               0x00000040  /* pattern in pattern buffer (0x8300) */
-#define PATMONO                 0x00000080  /* mono pattern */
-
-/* blitting direction (300 series only) */
-#define X_INC                   0x00010000
-#define X_DEC                   0x00000000
-#define Y_INC                   0x00020000
-#define Y_DEC                   0x00000000
-
-/* Clipping flags */
-#define NOCLIP                  0x00000000
-#define NOMERGECLIP             0x04000000
-#define CLIPENABLE              0x00040000
-#define CLIPWITHOUTMERGE        0x04040000
-
-/* Transparency */
-#define OPAQUE                  0x00000000
-#define TRANSPARENT             0x00100000
-
-/* ? */
-#define DSTAGP                  0x02000000
-#define DSTVIDEO                0x02000000
-
-/* Line */
-#define LINE_STYLE              0x00800000
-#define NO_RESET_COUNTER        0x00400000
-#define NO_LAST_PIXEL           0x00200000
-
-/* Subfunctions for Color/Enhanced Color Expansion (310/325 only) */
-#define COLOR_TO_MONO		0x00100000
-#define AA_TEXT			0x00200000
-
-/* Some general registers for 310/325 series */
-#define SRC_ADDR		0x8200
-#define SRC_PITCH		0x8204
-#define AGP_BASE		0x8206 /* color-depth dependent value */
-#define SRC_Y			0x8208
-#define SRC_X			0x820A
-#define DST_Y			0x820C
-#define DST_X			0x820E
-#define DST_ADDR		0x8210
-#define DST_PITCH		0x8214
-#define DST_HEIGHT		0x8216
-#define RECT_WIDTH		0x8218
-#define RECT_HEIGHT		0x821A
-#define PAT_FGCOLOR		0x821C
-#define PAT_BGCOLOR		0x8220
-#define SRC_FGCOLOR		0x8224
-#define SRC_BGCOLOR		0x8228
-#define MONO_MASK		0x822C
-#define LEFT_CLIP		0x8234
-#define TOP_CLIP		0x8236
-#define RIGHT_CLIP		0x8238
-#define BOTTOM_CLIP		0x823A
-#define COMMAND_READY		0x823C
-#define FIRE_TRIGGER      	0x8240
-
-#define PATTERN_REG		0x8300  /* 384 bytes pattern buffer */
-
-/* Line registers */
-#define LINE_X0			SRC_Y
-#define LINE_X1			DST_Y
-#define LINE_Y0			SRC_X
-#define LINE_Y1			DST_X
-#define LINE_COUNT		RECT_WIDTH
-#define LINE_STYLE_PERIOD	RECT_HEIGHT
-#define LINE_STYLE_0		MONO_MASK
-#define LINE_STYLE_1		0x8230
-#define LINE_XN			PATTERN_REG
-#define LINE_YN			PATTERN_REG+2
-
-/* Transparent bitblit registers */
-#define TRANS_DST_KEY_HIGH	PAT_FGCOLOR
-#define TRANS_DST_KEY_LOW	PAT_BGCOLOR
-#define TRANS_SRC_KEY_HIGH	SRC_FGCOLOR
-#define TRANS_SRC_KEY_LOW	SRC_BGCOLOR
-
-/* Queue */
-#define Q_BASE_ADDR		0x85C0  /* Base address of software queue (?) */
-#define Q_WRITE_PTR		0x85C4  /* Current write pointer (?) */
-#define Q_READ_PTR		0x85C8  /* Current read pointer (?) */
-#define Q_STATUS		0x85CC  /* queue status */
-
-
-#define MMIO_IN8(base, offset) \
-	*(volatile u8 *)(((u8*)(base)) + (offset))
-#define MMIO_IN16(base, offset) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_IN32(base, offset) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset))
-#define MMIO_OUT8(base, offset, val) \
-	*(volatile u8 *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT16(base, offset, val) \
-	*(volatile u16 *)(void *)(((u8*)(base)) + (offset)) = (val)
-#define MMIO_OUT32(base, offset, val) \
-	*(volatile u32 *)(void *)(((u8*)(base)) + (offset)) = (val)
-
-
-
-/* ------------- XGI 300 series -------------- */
-
-/* Macros to do useful things with the XGI BitBLT engine */
-
-/* BR(16) (0x8420):
-
-   bit 31 2D engine: 1 is idle,
-   bit 30 3D engine: 1 is idle,
-   bit 29 Command queue: 1 is empty
-
-   bits 28:24: Current CPU driven BitBlt buffer stage bit[4:0]
-
-   bits 15:0:  Current command queue length
-
-*/
-
-/* TW: BR(16)+2 = 0x8242 */
-
-static int     xgiCmdQueLen;
-
-#define XGI300Idle \
-  { \
-  while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  while( (MMIO_IN16(xgi_video_info.mmio_vbase, BR(16)+2) & 0xE000) != 0xE000){}; \
-  xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, 0x8240); \
-  }
-/* TW: (do three times, because 2D engine seems quite unsure about whether or not it's idle) */
-
-#define XGI300SetupSRCBase(base) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(0), base);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupSRCPitch(pitch) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1), pitch);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupSRCXY(x,y) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (x)<<16 | (y) );\
-                xgiCmdQueLen --;
-
-#define XGI300SetupDSTBase(base) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(4), base);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupDSTXY(x,y) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (x)<<16 | (y) );\
-                xgiCmdQueLen --;
-
-#define XGI300SetupDSTRect(x,y) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(5), (y)<<16 | (x) );\
-                xgiCmdQueLen --;
-
-#define XGI300SetupDSTColorDepth(bpp) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(1)+2, bpp);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupRect(w,h) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(6), (h)<<16 | (w) );\
-                xgiCmdQueLen --;
-
-#define XGI300SetupPATFG(color) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(7), color);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupPATBG(color) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(8), color);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupSRCFG(color) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(9), color);\
-                xgiCmdQueLen --;
-
-#define XGI300SetupSRCBG(color) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(10), color);\
-                xgiCmdQueLen --;
-
-/* 0x8224 src colorkey high */
-/* 0x8228 src colorkey low */
-/* 0x821c dest colorkey high */
-/* 0x8220 dest colorkey low */
-#define XGI300SetupSRCTrans(color) \
-                if (xgiCmdQueLen <= 1)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8224, color);\
-		MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8228, color);\
-		xgiCmdQueLen -= 2;
-
-#define XGI300SetupDSTTrans(color) \
-		if (xgiCmdQueLen <= 1)  XGI300Idle;\
-		MMIO_OUT32(xgi_video_info.mmio_vbase, 0x821C, color); \
-		MMIO_OUT32(xgi_video_info.mmio_vbase, 0x8220, color); \
-                xgiCmdQueLen -= 2;
-
-#define XGI300SetupMONOPAT(p0,p1) \
-                if (xgiCmdQueLen <= 1)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), p0);\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), p1);\
-                xgiCmdQueLen -= 2;
-
-#define XGI300SetupClipLT(left,top) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(13), ((left) & 0xFFFF) | (top)<<16 );\
-                xgiCmdQueLen--;
-
-#define XGI300SetupClipRB(right,bottom) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(14), ((right) & 0xFFFF) | (bottom)<<16 );\
-                xgiCmdQueLen--;
-
-/* General */
-#define XGI300SetupROP(rop) \
-                xgi_video_info.CommandReg = (rop) << 8;
-
-#define XGI300SetupCMDFlag(flags) \
-                xgi_video_info.CommandReg |= (flags);
-
-#define XGI300DoCMD \
-                if (xgiCmdQueLen <= 1)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(15), xgi_video_info.CommandReg); \
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(16), 0);\
-                xgiCmdQueLen -= 2;
-
-/* Line */
-#define XGI300SetupX0Y0(x,y) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(2), (y)<<16 | (x) );\
-                xgiCmdQueLen--;
-
-#define XGI300SetupX1Y1(x,y) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(3), (y)<<16 | (x) );\
-                xgiCmdQueLen--;
-
-#define XGI300SetupLineCount(c) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6), c);\
-                xgiCmdQueLen--;
-
-#define XGI300SetupStylePeriod(p) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT16(xgi_video_info.mmio_vbase, BR(6)+2, p);\
-                xgiCmdQueLen--;
-
-#define XGI300SetupStyleLow(ls) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(11), ls);\
-                xgiCmdQueLen--;
-
-#define XGI300SetupStyleHigh(ls) \
-                if (xgiCmdQueLen <= 0)  XGI300Idle;\
-                MMIO_OUT32(xgi_video_info.mmio_vbase, BR(12), ls);\
-                xgiCmdQueLen--;
-
-
-
-/* ----------- XGI 310/325 series --------------- */
-
-/* Q_STATUS:
-   bit 31 = 1: All engines idle and all queues empty
-   bit 30 = 1: Hardware Queue (=HW CQ, 2D queue, 3D queue) empty
-   bit 29 = 1: 2D engine is idle
-   bit 28 = 1: 3D engine is idle
-   bit 27 = 1: HW command queue empty
-   bit 26 = 1: 2D queue empty
-   bit 25 = 1: 3D queue empty
-   bit 24 = 1: SW command queue empty
-   bits 23:16: 2D counter 3
-   bits 15:8:  2D counter 2
-   bits 7:0:   2D counter 1
-
-   Where is the command queue length (current amount of commands the queue
-   can accept) on the 310/325 series? (The current implementation is taken
-   from 300 series and certainly wrong...)
-*/
-
-/* TW: FIXME: xgiCmdQueLen is... where....? */
-#define XGI310Idle \
-  { \
-  while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  while( (MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS+2) & 0x8000) != 0x8000){}; \
-  xgiCmdQueLen=MMIO_IN16(xgi_video_info.mmio_vbase, Q_STATUS); \
-  }
-
-#define XGI310SetupSRCBase(base) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_ADDR, base);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupSRCPitch(pitch) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT16(xgi_video_info.mmio_vbase, SRC_PITCH, pitch);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupSRCXY(x,y) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_Y, (x)<<16 | (y) );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupDSTBase(base) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, DST_ADDR, base);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupDSTXY(x,y) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, DST_Y, (x)<<16 | (y) );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupDSTRect(x,y) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, DST_PITCH, (y)<<16 | (x) );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupDSTColorDepth(bpp) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT16(xgi_video_info.mmio_vbase, AGP_BASE, bpp);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupRect(w,h) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, RECT_WIDTH, (h)<<16 | (w) );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupPATFG(color) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_FGCOLOR, color);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupPATBG(color) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, PAT_BGCOLOR, color);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupSRCFG(color) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_FGCOLOR, color);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupSRCBG(color) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, SRC_BGCOLOR, color);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupSRCTrans(color) \
-      if (xgiCmdQueLen <= 1)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_HIGH, color);\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_SRC_KEY_LOW, color);\
-      xgiCmdQueLen -= 2;
-
-#define XGI310SetupDSTTrans(color) \
-      if (xgiCmdQueLen <= 1)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_HIGH, color); \
-      MMIO_OUT32(xgi_video_info.mmio_vbase, TRANS_DST_KEY_LOW, color); \
-      xgiCmdQueLen -= 2;
-
-#define XGI310SetupMONOPAT(p0,p1) \
-      if (xgiCmdQueLen <= 1)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK, p0);\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, MONO_MASK+4, p1);\
-      xgiCmdQueLen -= 2;
-
-#define XGI310SetupClipLT(left,top) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, LEFT_CLIP, ((left) & 0xFFFF) | (top)<<16 );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupClipRB(right,bottom) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, RIGHT_CLIP, ((right) & 0xFFFF) | (bottom)<<16 );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupROP(rop) \
-      xgi_video_info.CommandReg = (rop) << 8;
-
-#define XGI310SetupCMDFlag(flags) \
-      xgi_video_info.CommandReg |= (flags);
-
-#define XGI310DoCMD \
-      if (xgiCmdQueLen <= 1)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, COMMAND_READY, xgi_video_info.CommandReg); \
-      MMIO_OUT32(xgi_video_info.mmio_vbase, FIRE_TRIGGER, 0); \
-      xgiCmdQueLen -= 2;
-
-#define XGI310SetupX0Y0(x,y) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X0, (y)<<16 | (x) );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupX1Y1(x,y) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_X1, (y)<<16 | (x) );\
-      xgiCmdQueLen--;
-
-#define XGI310SetupLineCount(c) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_COUNT, c);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupStylePeriod(p) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT16(xgi_video_info.mmio_vbase, LINE_STYLE_PERIOD, p);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupStyleLow(ls) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_0, ls);\
-      xgiCmdQueLen--;
-
-#define XGI310SetupStyleHigh(ls) \
-      if (xgiCmdQueLen <= 0)  XGI310Idle;\
-      MMIO_OUT32(xgi_video_info.mmio_vbase, LINE_STYLE_1, ls);\
-      xgiCmdQueLen--;
-
-int  XGIfb_initaccel(void);
-void XGIfb_syncaccel(void);
-int fbcon_XGI_sync(struct fb_info *info);
-
-extern struct video_info xgi_video_info;
-
-extern int XGIfb_accel;
-void fbcon_XGI_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-void fbcon_XGI_copyarea(struct fb_info *info, const struct fb_copyarea *area);
-
-
-#endif
diff --git a/drivers/staging/xgifb/XGI_main.h b/drivers/staging/xgifb/XGI_main.h
index 72448e8..46b5958 100644
--- a/drivers/staging/xgifb/XGI_main.h
+++ b/drivers/staging/xgifb/XGI_main.h
@@ -9,9 +9,6 @@
 #include "vb_struct.h"
 #include "vb_def.h"
 
-//#define LINUXBIOS   /* turn this on when compiling for LINUXBIOS */
-#define AGPOFF     /* default is turn off AGP */
-
 #define XGIFAIL(x) do { printk(x "\n"); return -EINVAL; } while(0)
 
 #define VER_MAJOR                 0
@@ -66,27 +63,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
 
 #define MAX_ROM_SCAN              0x10000
 
-#define HW_CURSOR_CAP             0x80
-#define TURBO_QUEUE_CAP           0x40
-#define AGP_CMD_QUEUE_CAP         0x20
-#define VM_CMD_QUEUE_CAP          0x10
-#define MMIO_CMD_QUEUE_CAP        0x08
-
-
-
-/* For 315 series */
-
-#define COMMAND_QUEUE_AREA_SIZE   0x80000 /* 512K */
-#define COMMAND_QUEUE_THRESHOLD   0x1F
-
-
-/* TW */
-#define HW_CURSOR_AREA_SIZE_315   0x4000  /* 16K */
-#define HW_CURSOR_AREA_SIZE_300   0x1000  /* 4K */
-
-#define OH_ALLOC_SIZE             4000
-#define SENTINEL                  0x7fffffff
-
 #define SEQ_ADR                   0x14
 #define SEQ_DATA                  0x15
 #define DAC_ADR                   0x18
@@ -195,16 +171,6 @@ MODULE_DEVICE_TABLE(pci, xgifb_pci_table);
 #define XGI_MEM_MAP_IO_ENABLE     0x01  /* SR20 */
 #define XGI_PCI_ADDR_ENABLE       0x80
 
-#define XGI_AGP_CMDQUEUE_ENABLE   0x80  /* 315/650/740 SR26 */
-#define XGI_VRAM_CMDQUEUE_ENABLE  0x40
-#define XGI_MMIO_CMD_ENABLE       0x20
-#define XGI_CMD_QUEUE_SIZE_512k   0x00
-#define XGI_CMD_QUEUE_SIZE_1M     0x04
-#define XGI_CMD_QUEUE_SIZE_2M     0x08
-#define XGI_CMD_QUEUE_SIZE_4M     0x0C
-#define XGI_CMD_QUEUE_RESET       0x01
-#define XGI_CMD_AUTO_CORR	  0x02
-
 #define XGI_SIMULTANEOUS_VIEW_ENABLE  0x01  /* CR30 */
 #define XGI_MODE_SELECT_CRT2      0x02
 #define XGI_VB_OUTPUT_COMPOSITE   0x04
@@ -337,27 +303,22 @@ static u32 pseudo_palette[17];
 static int XGIfb_off = 0;
 static int XGIfb_crt1off = 0;
 static int XGIfb_forcecrt1 = -1;
-static int XGIvga_enabled = 0;
 static int XGIfb_userom = 0;
 //static int XGIfb_useoem = -1;
 
 /* global flags */
 static int XGIfb_registered;
 static int XGIfb_tvmode = 0;
-static int XGIfb_mem = 0;
 static int XGIfb_pdc = 0;
 static int enable_dstn = 0;
 static int XGIfb_ypan = -1;
 
 
-static int XGIfb_hwcursor_size = 0;
 static int XGIfb_CRT2_write_enable = 0;
 
 static int XGIfb_crt2type = -1; /* TW: CRT2 type (for overriding autodetection) */
 static int XGIfb_tvplug = -1; /* PR: Tv plug type (for overriding autodetection) */
 
-static int XGIfb_queuemode = -1; /* TW: Use MMIO queue mode by default (310/325 series only) */
-
 static unsigned char XGIfb_detectedpdc = 0;
 
 static unsigned char XGIfb_detectedlcda = 0xff;
@@ -374,16 +335,6 @@ static struct xgi_hw_device_info XGIhw_ext;
 /* TW: XGI private structure */
 static struct vb_device_info  XGI_Pr;
 
-/* card parameters */
-static unsigned long XGIfb_mmio_size = 0;
-static u8            XGIfb_caps = 0;
-
-typedef enum _XGI_CMDTYPE {
-	MMIO_CMD = 0,
-	AGP_CMD_QUEUE,
-	VM_CMD_QUEUE,
-} XGI_CMDTYPE;
-
 #define MD_XGI300 1
 #define MD_XGI315 2
 
@@ -526,20 +477,6 @@ static const struct _XGI_crt2type {
 	{"\0",  	-1, 		-1}
 };
 
-/* Queue mode selection for 310 series */
-static const struct _XGI_queuemode {
-	char name[6];
-	int type_no;
-} XGI_queuemode[] = {
-	{"AGP",  	AGP_CMD_QUEUE},
-	{"VRAM", 	VM_CMD_QUEUE},
-	{"MMIO", 	MMIO_CMD},
-	{"agp",  	AGP_CMD_QUEUE},
-	{"vram", 	VM_CMD_QUEUE},
-	{"mmio", 	MMIO_CMD},
-	{"\0",   	-1}
-};
-
 /* TV standard */
 static const struct _XGI_tvtype {
 	char name[6];
@@ -594,33 +531,6 @@ static const struct _chswtable {
 	{ 0,      0,      ""       , ""       }
 };
 
-typedef struct _XGI_OH {
-	struct _XGI_OH *poh_next;
-	struct _XGI_OH *poh_prev;
-	unsigned long offset;
-	unsigned long size;
-} XGI_OH;
-
-typedef struct _XGI_OHALLOC {
-	struct _XGI_OHALLOC *poha_next;
-	XGI_OH aoh[1];
-} XGI_OHALLOC;
-
-typedef struct _XGI_HEAP {
-	XGI_OH oh_free;
-	XGI_OH oh_used;
-	XGI_OH *poh_freelist;
-	XGI_OHALLOC *poha_chain;
-	unsigned long max_freesize;
-} XGI_HEAP;
-
-static unsigned long XGIfb_hwcursor_vbase;
-
-static unsigned long XGIfb_heap_start;
-static unsigned long XGIfb_heap_end;
-static unsigned long XGIfb_heap_size;
-static XGI_HEAP      XGIfb_heap;
-
 // Eden Chen
 static const struct _XGI_TV_filter {
 	u8 filter[9][4];
@@ -794,14 +704,6 @@ static int      XGIfb_blank(int blank,
 /*static int 	XGIfb_mmap(struct fb_info *info, struct file *file,
 		           struct vm_area_struct *vma);
 */
-extern void     fbcon_XGI_fillrect(struct fb_info *info,
-                                   const struct fb_fillrect *rect);
-extern void     fbcon_XGI_copyarea(struct fb_info *info,
-                                   const struct fb_copyarea *area);
-extern int      fbcon_XGI_sync(struct fb_info *info);
-
-static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
-			    unsigned long arg);
 
 /*
 extern int	XGIfb_mode_rate_to_dclock(VB_DEVICE_INFO *XGI_Pr,
@@ -820,10 +722,6 @@ extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
 static int      XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
 			      struct fb_info *info);
 
-/* Internal 2D accelerator functions */
-extern int      XGIfb_initaccel(void);
-extern void     XGIfb_syncaccel(void);
-
 /* Internal general routines */
 static void     XGIfb_search_mode(const char *name);
 static int      XGIfb_validate_mode(int modeindex);
@@ -836,21 +734,6 @@ static int      XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 static void     XGIfb_pre_setmode(void);
 static void     XGIfb_post_setmode(void);
 
-static unsigned char  XGIfb_CheckVBRetrace(void);
-static unsigned char  XGIfbcheckvretracecrt2(void);
-static unsigned char  XGIfbcheckvretracecrt1(void);
-static unsigned char  XGIfb_bridgeisslave(void);
-
-struct XGI_memreq {
-	unsigned long offset;
-	unsigned long size;
-};
-
-/* XGI-specific Export functions */
-void            XGI_dispinfo(struct ap_data *rec);
-void            XGI_malloc(struct XGI_memreq *req);
-void            XGI_free(unsigned long base);
-
 /* Internal hardware access routines */
 void            XGIfb_set_reg4(u16 port, unsigned long data);
 u32             XGIfb_get_reg3(u16 port);
@@ -864,15 +747,6 @@ static void     XGIfb_get_VB_type(void);
 static int      XGIfb_has_VB(void);
 
 
-/* Internal heap routines */
-static int      XGIfb_heap_init(void);
-static XGI_OH   *XGIfb_poh_new_node(void);
-static XGI_OH   *XGIfb_poh_allocate(unsigned long size);
-static void     XGIfb_delete_node(XGI_OH *poh);
-static void     XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh);
-static XGI_OH   *XGIfb_poh_free(unsigned long base);
-static void     XGIfb_free_node(XGI_OH *poh);
-
 /* Internal routines to access PCI configuration space */
 unsigned char XGIfb_query_VGA_config_space(struct xgi_hw_device_info *pXGIhw_ext,
 					   unsigned long offset,
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index ee008e5..721bd25 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -43,8 +43,6 @@
 #include "XGI_main.h"
 #include "vb_util.h"
 
-int XGIfb_accel = 0;
-
 #define Index_CR_GPIO_Reg1 0x48
 #define Index_CR_GPIO_Reg2 0x49
 #define Index_CR_GPIO_Reg3 0x4a
@@ -54,6 +52,8 @@ int XGIfb_accel = 0;
 #define GPIOG_READ  (1<<1)
 int XGIfb_GetXG21DefaultLVDSModeIdx(void);
 
+#define XGIFB_ROM_SIZE	65536
+
 /* -------------------- Macro definitions ---------------------------- */
 
 #undef XGIFBDEBUG
@@ -182,8 +182,6 @@ static int XGIfb_mode_rate_to_dclock(struct vb_device_info *XGI_Pr,
 
 	*/
 	ClockIndex = XGI_Pr->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	if (HwDeviceExtension->jChipType < XGI_315H)
-		ClockIndex &= 0x3F;
 
 	Clock = XGI_Pr->VCLKData[ClockIndex].CLOCK * 1000;
 
@@ -859,12 +857,6 @@ static int XGIfb_validate_mode(int myindex)
 				if (XGIbios_mode[myindex].bpp == 32)
 					return -1;
 			}
-			/* TW: LVDS/CHRONTEL only supports < 800 (1024 on 650/Ch7019) */
-			if (xgi_video_info.hasVB == HASVB_LVDS_CHRONTEL
-					|| xgi_video_info.hasVB	== HASVB_CHRONTEL) {
-				if (xgi_video_info.chip < XGI_315H)
-					return -1;
-			}
 			break;
 		default:
 			return -1;
@@ -898,24 +890,6 @@ static void XGIfb_search_crt2type(const char *name)
 		printk(KERN_INFO "XGIfb: Invalid CRT2 type: %s\n", name);
 }
 
-static void XGIfb_search_queuemode(const char *name)
-{
-	int i = 0;
-
-	if (name == NULL)
-		return;
-
-	while (XGI_queuemode[i].type_no != -1) {
-		if (!strcmp(name, XGI_queuemode[i].name)) {
-			XGIfb_queuemode = XGI_queuemode[i].type_no;
-			break;
-		}
-		i++;
-	}
-	if (XGIfb_queuemode < 0)
-		printk(KERN_INFO "XGIfb: Invalid queuemode type: %s\n", name);
-}
-
 static u8 XGIfb_search_refresh_rate(unsigned int rate)
 {
 	u16 xres, yres;
@@ -982,61 +956,6 @@ static void XGIfb_search_tvstd(const char *name)
 	}
 }
 
-static unsigned char XGIfb_bridgeisslave(void)
-{
-	unsigned char usScratchP1_00;
-
-	if (xgi_video_info.hasVB == HASVB_NONE)
-		return 0;
-
-	inXGIIDXREG(XGIPART1, 0x00, usScratchP1_00);
-	if ((usScratchP1_00 & 0x50) == 0x10)
-		return 1;
-	else
-		return 0;
-}
-
-static unsigned char XGIfbcheckvretracecrt1(void)
-{
-	unsigned char temp;
-
-	inXGIIDXREG(XGICR, 0x17, temp);
-	if (!(temp & 0x80))
-		return 0;
-
-	inXGIIDXREG(XGISR, 0x1f, temp);
-	if (temp & 0xc0)
-		return 0;
-
-	if (inXGIREG(XGIINPSTAT) & 0x08)
-		return 1;
-	else
-		return 0;
-}
-
-static unsigned char XGIfbcheckvretracecrt2(void)
-{
-	unsigned char temp;
-	if (xgi_video_info.hasVB == HASVB_NONE)
-		return 0;
-	inXGIIDXREG(XGIPART1, 0x30, temp);
-	if (temp & 0x02)
-		return 0;
-	else
-		return 1;
-}
-
-static unsigned char XGIfb_CheckVBRetrace(void)
-{
-	if (xgi_video_info.disp_state & DISPTYPE_DISP2) {
-		if (XGIfb_bridgeisslave())
-			return XGIfbcheckvretracecrt1();
-		else
-			return XGIfbcheckvretracecrt2();
-	}
-	return XGIfbcheckvretracecrt1();
-}
-
 /* ----------- FBDev related routines for all series ----------- */
 
 static void XGIfb_bpp_to_var(struct fb_var_screeninfo *var)
@@ -1187,11 +1106,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		xgi_video_info.org_x = xgi_video_info.org_y = 0;
 		xgi_video_info.video_linelength = info->var.xres_virtual
 				* (xgi_video_info.video_bpp >> 3);
-		xgi_video_info.accel = 0;
-		if (XGIfb_accel) {
-			xgi_video_info.accel = (var->accel_flags
-					& FB_ACCELF_TEXT) ? -1 : 0;
-		}
 		switch (xgi_video_info.video_bpp) {
 		case 8:
 			xgi_video_info.DstColor = 0x0000;
@@ -1223,7 +1137,6 @@ static int XGIfb_do_set_var(struct fb_var_screeninfo *var, int isactive,
 		default:
 			xgi_video_info.video_cmap_len = 16;
 			printk(KERN_ERR "XGIfb: Unsupported depth %d", xgi_video_info.video_bpp);
-			xgi_video_info.accel = 0;
 			break;
 		}
 	}
@@ -1286,26 +1199,6 @@ static int XGIfb_pan_var(struct fb_var_screeninfo *var)
 }
 #endif
 
-void XGI_dispinfo(struct ap_data *rec)
-{
-	rec->minfo.bpp = xgi_video_info.video_bpp;
-	rec->minfo.xres = xgi_video_info.video_width;
-	rec->minfo.yres = xgi_video_info.video_height;
-	rec->minfo.v_xres = xgi_video_info.video_vwidth;
-	rec->minfo.v_yres = xgi_video_info.video_vheight;
-	rec->minfo.org_x = xgi_video_info.org_x;
-	rec->minfo.org_y = xgi_video_info.org_y;
-	rec->minfo.vrate = xgi_video_info.refresh_rate;
-	rec->iobase = xgi_video_info.vga_base - 0x30;
-	rec->mem_size = xgi_video_info.video_size;
-	rec->disp_state = xgi_video_info.disp_state;
-	rec->version = (VER_MAJOR << 24) | (VER_MINOR << 16) | VER_LEVEL;
-	rec->hasVB = xgi_video_info.hasVB;
-	rec->TV_type = xgi_video_info.TV_type;
-	rec->TV_plug = xgi_video_info.TV_plug;
-	rec->chip = xgi_video_info.chip;
-}
-
 static int XGIfb_open(struct fb_info *info, int user)
 {
 	return 0;
@@ -1580,109 +1473,6 @@ static int XGIfb_blank(int blank, struct fb_info *info)
 	return 0;
 }
 
-static int XGIfb_ioctl(struct fb_info *info, unsigned int cmd,
-		unsigned long arg)
-{
-	DEBUGPRN("inside ioctl");
-	switch (cmd) {
-	case FBIO_ALLOC:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		XGI_malloc((struct XGI_memreq *) arg);
-		break;
-	case FBIO_FREE:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		XGI_free(*(unsigned long *) arg);
-		break;
-	case FBIOGET_HWCINFO: {
-		unsigned long *hwc_offset = (unsigned long *) arg;
-
-		if (XGIfb_caps & HW_CURSOR_CAP)
-			*hwc_offset
-					= XGIfb_hwcursor_vbase
-							- (unsigned long) xgi_video_info.video_vbase;
-		else
-			*hwc_offset = 0;
-
-		break;
-	}
-	case FBIOPUT_MODEINFO: {
-		struct mode_info *x = (struct mode_info *) arg;
-
-		xgi_video_info.video_bpp = x->bpp;
-		xgi_video_info.video_width = x->xres;
-		xgi_video_info.video_height = x->yres;
-		xgi_video_info.video_vwidth = x->v_xres;
-		xgi_video_info.video_vheight = x->v_yres;
-		xgi_video_info.org_x = x->org_x;
-		xgi_video_info.org_y = x->org_y;
-		xgi_video_info.refresh_rate = x->vrate;
-		xgi_video_info.video_linelength = xgi_video_info.video_vwidth
-				* (xgi_video_info.video_bpp >> 3);
-		switch (xgi_video_info.video_bpp) {
-		case 8:
-			xgi_video_info.DstColor = 0x0000;
-			xgi_video_info.XGI310_AccelDepth = 0x00000000;
-			xgi_video_info.video_cmap_len = 256;
-			break;
-		case 16:
-			xgi_video_info.DstColor = 0x8000;
-			xgi_video_info.XGI310_AccelDepth = 0x00010000;
-			xgi_video_info.video_cmap_len = 16;
-			break;
-		case 32:
-			xgi_video_info.DstColor = 0xC000;
-			xgi_video_info.XGI310_AccelDepth = 0x00020000;
-			xgi_video_info.video_cmap_len = 16;
-			break;
-		default:
-			xgi_video_info.video_cmap_len = 16;
-			printk(KERN_ERR "XGIfb: Unsupported accel depth %d", xgi_video_info.video_bpp);
-			xgi_video_info.accel = 0;
-			break;
-		}
-
-		break;
-	}
-	case FBIOGET_DISPINFO:
-		XGI_dispinfo((struct ap_data *) arg);
-		break;
-	case XGIFB_GET_INFO: /* TW: New for communication with X driver */
-	{
-		struct XGIfb_info *x = (struct XGIfb_info *) arg;
-
-		/* x->XGIfb_id = XGIFB_ID; */
-		x->XGIfb_version = VER_MAJOR;
-		x->XGIfb_revision = VER_MINOR;
-		x->XGIfb_patchlevel = VER_LEVEL;
-		x->chip_id = xgi_video_info.chip_id;
-		x->memory = xgi_video_info.video_size / 1024;
-		x->heapstart = xgi_video_info.heapstart / 1024;
-		x->fbvidmode = XGIfb_mode_no;
-		x->XGIfb_caps = XGIfb_caps;
-		x->XGIfb_tqlen = 512; /* yet unused */
-		x->XGIfb_pcibus = xgi_video_info.pcibus;
-		x->XGIfb_pcislot = xgi_video_info.pcislot;
-		x->XGIfb_pcifunc = xgi_video_info.pcifunc;
-		x->XGIfb_lcdpdc = XGIfb_detectedpdc;
-		x->XGIfb_lcda = XGIfb_detectedlcda;
-		break;
-	}
-	case XGIFB_GET_VBRSTATUS: {
-		unsigned long *vbrstatus = (unsigned long *) arg;
-		if (XGIfb_CheckVBRetrace())
-			*vbrstatus = 1;
-		else
-			*vbrstatus = 0;
-	}
-	default:
-		return -EINVAL;
-	} DEBUGPRN("end of ioctl");
-	return 0;
-
-}
-
 /* ----------- FBDev related routines for all series ---------- */
 
 static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
@@ -1697,16 +1487,6 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
 
 	fix->smem_len = xgi_video_info.video_size;
 
-	/*        if((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size/1024))) {
-	 if (xgi_video_info.video_size > 0x1000000) {
-	 fix->smem_len = 0xD00000;
-	 } else if (xgi_video_info.video_size > 0x800000)
-	 fix->smem_len = 0x800000;
-	 else
-	 fix->smem_len = 0x400000;
-	 } else
-	 fix->smem_len = XGIfb_mem * 1024;
-	 */
 	fix->type = video_type;
 	fix->type_aux = 0;
 	if (xgi_video_info.video_bpp == 8)
@@ -1721,11 +1501,8 @@ static int XGIfb_get_fix(struct fb_fix_screeninfo *fix, int con,
 	fix->ywrapstep = 0;
 	fix->line_length = xgi_video_info.video_linelength;
 	fix->mmio_start = xgi_video_info.mmio_base;
-	fix->mmio_len = XGIfb_mmio_size;
-	if (xgi_video_info.chip >= XG40)
-		fix->accel = FB_ACCEL_XGI_XABRE;
-	else
-		fix->accel = FB_ACCEL_XGI_GLAMOUR_2;
+	fix->mmio_len = xgi_video_info.mmio_size;
+	fix->accel = FB_ACCEL_XGI_XABRE;
 
 	DEBUGPRN("end of get_fix");
 	return 0;
@@ -1742,11 +1519,9 @@ static struct fb_ops XGIfb_ops = {
 	.fb_pan_display = XGIfb_pan_display,
 #endif
 	.fb_blank = XGIfb_blank,
-	.fb_fillrect = fbcon_XGI_fillrect,
-	.fb_copyarea = fbcon_XGI_copyarea,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
 	.fb_imageblit = cfb_imageblit,
-	.fb_sync = fbcon_XGI_sync,
-	.fb_ioctl = XGIfb_ioctl,
 	/* .fb_mmap = XGIfb_mmap, */
 };
 
@@ -1898,24 +1673,11 @@ static void XGIfb_detect_VB(void)
 		xgi_video_info.TV_plug = TVPLUG_SCART;
 
 	if (xgi_video_info.TV_type == 0) {
-		/* TW: PAL/NTSC changed for 650 */
-		if ((xgi_video_info.chip <= XGI_315PRO) || (xgi_video_info.chip
-				>= XGI_330)) {
-
-			inXGIIDXREG(XGICR, 0x38, temp);
-			if (temp & 0x10)
-				xgi_video_info.TV_type = TVMODE_PAL;
-			else
-				xgi_video_info.TV_type = TVMODE_NTSC;
-
-		} else {
-
-			inXGIIDXREG(XGICR, 0x79, temp);
-			if (temp & 0x20)
-				xgi_video_info.TV_type = TVMODE_PAL;
-			else
-				xgi_video_info.TV_type = TVMODE_NTSC;
-		}
+		inXGIIDXREG(XGICR, 0x38, temp);
+		if (temp & 0x10)
+			xgi_video_info.TV_type = TVMODE_PAL;
+		else
+			xgi_video_info.TV_type = TVMODE_NTSC;
 	}
 
 	/* TW: Copy forceCRT1 option to CRT1off if option is given */
@@ -2087,495 +1849,6 @@ void XGI_Sense30x(void)
 	outXGIIDXREG(XGIPART4, 0x0d, backupP4_0d);
 }
 
-/* ------------------------ Heap routines -------------------------- */
-
-static int XGIfb_heap_init(void)
-{
-	XGI_OH *poh;
-	u8 temp = 0;
-
-	int agp_enabled = 1;
-	u32 agp_size;
-	unsigned long *cmdq_baseport = NULL;
-	unsigned long *read_port = NULL;
-	unsigned long *write_port = NULL;
-	XGI_CMDTYPE cmd_type;
-#ifndef AGPOFF
-	struct agp_kern_info *agp_info;
-	struct agp_memory *agp;
-	u32 agp_phys;
-#endif
-
-	/* TW: The heap start is either set manually using the "mem" parameter, or
-	 *     defaults as follows:
-	 *     -) If more than 16MB videoRAM available, let our heap start at 12MB.
-	 *     -) If more than  8MB videoRAM available, let our heap start at  8MB.
-	 *     -) If 4MB or less is available, let it start at 4MB.
-	 *     This is for avoiding a clash with X driver which uses the beginning
-	 *     of the videoRAM. To limit size of X framebuffer, use Option MaxXFBMem
-	 *     in XF86Config-4.
-	 *     The heap start can also be specified by parameter "mem" when starting the XGIfb
-	 *     driver. XGIfb mem=1024 lets heap starts at 1MB, etc.
-	 */
-	if ((!XGIfb_mem) || (XGIfb_mem > (xgi_video_info.video_size / 1024))) {
-		if (xgi_video_info.video_size > 0x1000000)
-			xgi_video_info.heapstart = 0xD00000;
-		else if (xgi_video_info.video_size > 0x800000)
-			xgi_video_info.heapstart = 0x800000;
-		else
-			xgi_video_info.heapstart = 0x400000;
-	} else {
-		xgi_video_info.heapstart = XGIfb_mem * 1024;
-	}
-	XGIfb_heap_start = (unsigned long) (xgi_video_info.video_vbase
-			+ xgi_video_info.heapstart);
-	printk(KERN_INFO "XGIfb: Memory heap starting at %dK\n",
-			(int)(xgi_video_info.heapstart / 1024));
-
-	XGIfb_heap_end = (unsigned long) xgi_video_info.video_vbase
-			+ xgi_video_info.video_size;
-	XGIfb_heap_size = XGIfb_heap_end - XGIfb_heap_start;
-
-	/* TW: Now initialize the 310 series' command queue mode.
-	 * On 310/325, there are three queue modes available which
-	 * are chosen by setting bits 7:5 in SR26:
-	 * 1. MMIO queue mode (bit 5, 0x20). The hardware will keep
-	 *    track of the queue, the FIFO, command parsing and so
-	 *    on. This is the one comparable to the 300 series.
-	 * 2. VRAM queue mode (bit 6, 0x40). In this case, one will
-	 *    have to do queue management himself. Register 0x85c4 will
-	 *    hold the location of the next free queue slot, 0x85c8
-	 *    is the "queue read pointer" whose way of working is
-	 *    unknown to me. Anyway, this mode would require a
-	 *    translation of the MMIO commands to some kind of
-	 *    accelerator assembly and writing these commands
-	 *    to the memory location pointed to by 0x85c4.
-	 *    We will not use this, as nobody knows how this
-	 *    "assembly" works, and as it would require a complete
-	 *    re-write of the accelerator code.
-	 * 3. AGP queue mode (bit 7, 0x80). Works as 2., but keeps the
-	 *    queue in AGP memory space.
-	 *
-	 * SR26 bit 4 is called "Bypass H/W queue".
-	 * SR26 bit 1 is called "Enable Command Queue Auto Correction"
-	 * SR26 bit 0 resets the queue
-	 * Size of queue memory is encoded in bits 3:2 like this:
-	 *    00  (0x00)  512K
-	 *    01  (0x04)  1M
-	 *    10  (0x08)  2M
-	 *    11  (0x0C)  4M
-	 * The queue location is to be written to 0x85C0.
-	 *
-	 */
-	cmdq_baseport = (unsigned long *) (xgi_video_info.mmio_vbase
-			+ MMIO_QUEUE_PHYBASE);
-	write_port = (unsigned long *) (xgi_video_info.mmio_vbase
-			+ MMIO_QUEUE_WRITEPORT);
-	read_port = (unsigned long *) (xgi_video_info.mmio_vbase
-			+ MMIO_QUEUE_READPORT);
-
-	DPRINTK("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port);
-
-	agp_size = COMMAND_QUEUE_AREA_SIZE;
-
-#ifndef AGPOFF
-	if (XGIfb_queuemode == AGP_CMD_QUEUE) {
-		agp_info = vzalloc(sizeof(*agp_info));
-		agp_copy_info(agp_info);
-
-		agp_backend_acquire();
-
-		agp = agp_allocate_memory(COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE,
-				AGP_NORMAL_MEMORY);
-		if (agp == NULL) {
-			DPRINTK("XGIfb: Allocating AGP buffer failed.\n");
-			agp_enabled = 0;
-		} else {
-			if (agp_bind_memory(agp, agp->pg_start) != 0) {
-				DPRINTK("XGIfb: AGP: Failed to bind memory\n");
-				/* TODO: Free AGP memory here */
-				agp_enabled = 0;
-			} else {
-				agp_enable(0);
-			}
-		}
-	}
-#else
-	agp_enabled = 0;
-#endif
-
-	/* TW: Now select the queue mode */
-
-	if ((agp_enabled) && (XGIfb_queuemode == AGP_CMD_QUEUE)) {
-		cmd_type = AGP_CMD_QUEUE;
-		printk(KERN_INFO "XGIfb: Using AGP queue mode\n");
-	/* } else if (XGIfb_heap_size >= COMMAND_QUEUE_AREA_SIZE)  */
-	} else if (XGIfb_queuemode == VM_CMD_QUEUE) {
-		cmd_type = VM_CMD_QUEUE;
-		printk(KERN_INFO "XGIfb: Using VRAM queue mode\n");
-	} else {
-		printk(KERN_INFO "XGIfb: Using MMIO queue mode\n");
-		cmd_type = MMIO_CMD;
-	}
-
-	switch (agp_size) {
-	case 0x80000:
-		temp = XGI_CMD_QUEUE_SIZE_512k;
-		break;
-	case 0x100000:
-		temp = XGI_CMD_QUEUE_SIZE_1M;
-		break;
-	case 0x200000:
-		temp = XGI_CMD_QUEUE_SIZE_2M;
-		break;
-	case 0x400000:
-		temp = XGI_CMD_QUEUE_SIZE_4M;
-		break;
-	}
-
-	switch (cmd_type) {
-	case AGP_CMD_QUEUE:
-#ifndef AGPOFF
-		DPRINTK("XGIfb: AGP buffer base = 0x%lx, offset = 0x%x, size = %dK\n",
-			agp_info->aper_base, agp->physical, agp_size/1024);
-
-		agp_phys = agp_info->aper_base + agp->physical;
-
-		outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, 0);
-		outXGIIDXREG(XGICR, IND_XGI_AGP_IO_PAD, XGI_AGP_2X);
-
-		outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-
-		outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		temp |= XGI_AGP_CMDQUEUE_ENABLE;
-		outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
-
-		*cmdq_baseport = agp_phys;
-
-		XGIfb_caps |= AGP_CMD_QUEUE_CAP;
-#endif
-		break;
-
-	case VM_CMD_QUEUE:
-		XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE;
-		XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE;
-
-		outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD);
-
-		outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET);
-
-		*write_port = *read_port;
-
-		temp |= XGI_VRAM_CMDQUEUE_ENABLE;
-		outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp);
-
-		*cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE;
-
-		XGIfb_caps |= VM_CMD_QUEUE_CAP;
-
-		DPRINTK("XGIfb: VM Cmd Queue offset = 0x%lx, size is %dK\n",
-			*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024);
-		break;
-
-	default: /* MMIO */
-
-		/* printk("%s:%d - I'm here\n", __FUNCTION__, __LINE__); */
-		/* TW: This previously only wrote XGI_MMIO_CMD_ENABLE
-		 * to IND_XGI_CMDQUEUE_SET. I doubt that this is
-		 * enough. Reserve memory in any way.
-		 */
-		/* FIXME XGIfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; */
-		/* FIXME XGIfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; */
-		/* FIXME */
-		/* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_THRESHOLD, COMMAND_QUEUE_THRESHOLD); */
-		/* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, XGI_CMD_QUEUE_RESET); */
-		/* FIXME */
-		/* FIXME *write_port = *read_port; */
-		/* FIXME */
-		/* FIXME *//* TW: Set Auto_Correction bit */
-		/* FIXME temp |= (XGI_MMIO_CMD_ENABLE | XGI_CMD_AUTO_CORR); */
-		/* FIXME outXGIIDXREG(XGISR, IND_XGI_CMDQUEUE_SET, temp); */
-		/* FIXME */
-		/* FIXME *cmdq_baseport = xgi_video_info.video_size - COMMAND_QUEUE_AREA_SIZE; */
-		/* FIXME */
-		/* FIXME XGIfb_caps |= MMIO_CMD_QUEUE_CAP; */
-		/* FIXME */
-		/* FIXME DPRINTK("XGIfb: MMIO Cmd Queue offset = 0x%lx, size is %dK\n", */
-		/* FIXME	*cmdq_baseport, COMMAND_QUEUE_AREA_SIZE/1024); */
-	break;
-}
-
-	/* TW: Now reserve memory for the HWCursor. It is always located at the very
-	top of the videoRAM, right below the TB memory area (if used). */
-	if (XGIfb_heap_size >= XGIfb_hwcursor_size) {
-		XGIfb_heap_end -= XGIfb_hwcursor_size;
-		XGIfb_heap_size -= XGIfb_hwcursor_size;
-		XGIfb_hwcursor_vbase = XGIfb_heap_end;
-
-		XGIfb_caps |= HW_CURSOR_CAP;
-
-		DPRINTK("XGIfb: Hardware Cursor start at 0x%lx, size is %dK\n",
-				XGIfb_heap_end, XGIfb_hwcursor_size/1024);
-	}
-
-	XGIfb_heap.poha_chain = NULL;
-	XGIfb_heap.poh_freelist = NULL;
-
-	poh = XGIfb_poh_new_node();
-
-	if (poh == NULL)
-		return 1;
-
-	poh->poh_next = &XGIfb_heap.oh_free;
-	poh->poh_prev = &XGIfb_heap.oh_free;
-	poh->size = XGIfb_heap_end - XGIfb_heap_start + 1;
-	poh->offset = XGIfb_heap_start - (unsigned long) xgi_video_info.video_vbase;
-
-	DPRINTK("XGIfb: Heap start:0x%p, end:0x%p, len=%dk\n",
-		(char *) XGIfb_heap_start, (char *) XGIfb_heap_end,
-		(unsigned int) poh->size / 1024);
-
-	DPRINTK("XGIfb: First Node offset:0x%x, size:%dk\n",
-		(unsigned int) poh->offset, (unsigned int) poh->size / 1024);
-
-	XGIfb_heap.oh_free.poh_next = poh;
-	XGIfb_heap.oh_free.poh_prev = poh;
-	XGIfb_heap.oh_free.size = 0;
-	XGIfb_heap.max_freesize = poh->size;
-
-	XGIfb_heap.oh_used.poh_next = &XGIfb_heap.oh_used;
-	XGIfb_heap.oh_used.poh_prev = &XGIfb_heap.oh_used;
-	XGIfb_heap.oh_used.size = SENTINEL;
-
-	return 0;
-}
-
-static XGI_OH *XGIfb_poh_new_node(void)
-{
-	int i;
-	unsigned long cOhs;
-	XGI_OHALLOC *poha;
-	XGI_OH *poh;
-
-	if (XGIfb_heap.poh_freelist == NULL) {
-		poha = kmalloc(OH_ALLOC_SIZE, GFP_KERNEL);
-		if (!poha)
-			return NULL;
-
-		poha->poha_next = XGIfb_heap.poha_chain;
-		XGIfb_heap.poha_chain = poha;
-
-		cOhs = (OH_ALLOC_SIZE - sizeof(XGI_OHALLOC)) / sizeof(XGI_OH)
-				+ 1;
-
-		poh = &poha->aoh[0];
-		for (i = cOhs - 1; i != 0; i--) {
-			poh->poh_next = poh + 1;
-			poh = poh + 1;
-		}
-
-		poh->poh_next = NULL;
-		XGIfb_heap.poh_freelist = &poha->aoh[0];
-	}
-
-	poh = XGIfb_heap.poh_freelist;
-	XGIfb_heap.poh_freelist = poh->poh_next;
-
-	return poh;
-}
-
-static XGI_OH *XGIfb_poh_allocate(unsigned long size)
-{
-	XGI_OH *pohThis;
-	XGI_OH *pohRoot;
-	int bAllocated = 0;
-
-	if (size > XGIfb_heap.max_freesize) {
-		DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
-				(unsigned int) size / 1024);
-		return NULL;
-	}
-
-	pohThis = XGIfb_heap.oh_free.poh_next;
-
-	while (pohThis != &XGIfb_heap.oh_free) {
-		if (size <= pohThis->size) {
-			bAllocated = 1;
-			break;
-		}
-		pohThis = pohThis->poh_next;
-	}
-
-	if (!bAllocated) {
-		DPRINTK("XGIfb: Can't allocate %dk size on offscreen\n",
-				(unsigned int) size / 1024);
-		return NULL;
-	}
-
-	if (size == pohThis->size) {
-		pohRoot = pohThis;
-		XGIfb_delete_node(pohThis);
-	} else {
-		pohRoot = XGIfb_poh_new_node();
-
-		if (pohRoot == NULL)
-			return NULL;
-
-		pohRoot->offset = pohThis->offset;
-		pohRoot->size = size;
-
-		pohThis->offset += size;
-		pohThis->size -= size;
-	}
-
-	XGIfb_heap.max_freesize -= size;
-
-	pohThis = &XGIfb_heap.oh_used;
-	XGIfb_insert_node(pohThis, pohRoot);
-
-	return pohRoot;
-}
-
-static void XGIfb_delete_node(XGI_OH *poh)
-{
-	XGI_OH *poh_prev;
-	XGI_OH *poh_next;
-
-	poh_prev = poh->poh_prev;
-	poh_next = poh->poh_next;
-
-	poh_prev->poh_next = poh_next;
-	poh_next->poh_prev = poh_prev;
-
-}
-
-static void XGIfb_insert_node(XGI_OH *pohList, XGI_OH *poh)
-{
-	XGI_OH *pohTemp;
-
-	pohTemp = pohList->poh_next;
-
-	pohList->poh_next = poh;
-	pohTemp->poh_prev = poh;
-
-	poh->poh_prev = pohList;
-	poh->poh_next = pohTemp;
-}
-
-static XGI_OH *XGIfb_poh_free(unsigned long base)
-{
-	XGI_OH *pohThis;
-	XGI_OH *poh_freed;
-	XGI_OH *poh_prev;
-	XGI_OH *poh_next;
-	unsigned long ulUpper;
-	unsigned long ulLower;
-	int foundNode = 0;
-
-	poh_freed = XGIfb_heap.oh_used.poh_next;
-
-	while (poh_freed != &XGIfb_heap.oh_used) {
-		if (poh_freed->offset == base) {
-			foundNode = 1;
-			break;
-		}
-
-		poh_freed = poh_freed->poh_next;
-	}
-
-	if (!foundNode)
-		return NULL;
-
-	XGIfb_heap.max_freesize += poh_freed->size;
-
-	poh_prev = poh_next = NULL;
-	ulUpper = poh_freed->offset + poh_freed->size;
-	ulLower = poh_freed->offset;
-
-	pohThis = XGIfb_heap.oh_free.poh_next;
-
-	while (pohThis != &XGIfb_heap.oh_free) {
-		if (pohThis->offset == ulUpper)
-			poh_next = pohThis;
-		else if ((pohThis->offset + pohThis->size) == ulLower)
-			poh_prev = pohThis;
-
-		pohThis = pohThis->poh_next;
-	}
-
-	XGIfb_delete_node(poh_freed);
-
-	if (poh_prev && poh_next) {
-		poh_prev->size += (poh_freed->size + poh_next->size);
-		XGIfb_delete_node(poh_next);
-		XGIfb_free_node(poh_freed);
-		XGIfb_free_node(poh_next);
-		return poh_prev;
-	}
-
-	if (poh_prev) {
-		poh_prev->size += poh_freed->size;
-		XGIfb_free_node(poh_freed);
-		return poh_prev;
-	}
-
-	if (poh_next) {
-		poh_next->size += poh_freed->size;
-		poh_next->offset = poh_freed->offset;
-		XGIfb_free_node(poh_freed);
-		return poh_next;
-	}
-
-	XGIfb_insert_node(&XGIfb_heap.oh_free, poh_freed);
-
-	return poh_freed;
-}
-
-static void XGIfb_free_node(XGI_OH *poh)
-{
-	if (poh == NULL)
-		return;
-
-	poh->poh_next = XGIfb_heap.poh_freelist;
-	XGIfb_heap.poh_freelist = poh;
-
-}
-
-void XGI_malloc(struct XGI_memreq *req)
-{
-	XGI_OH *poh;
-
-	poh = XGIfb_poh_allocate(req->size);
-
-	if (poh == NULL) {
-		req->offset = 0;
-		req->size = 0;
-		DPRINTK("XGIfb: Video RAM allocation failed\n");
-	} else {
-		DPRINTK("XGIfb: Video RAM allocation succeeded: 0x%p\n",
-				(char *) (poh->offset + (unsigned long) xgi_video_info.video_vbase));
-
-		req->offset = poh->offset;
-		req->size = poh->size;
-	}
-
-}
-
-void XGI_free(unsigned long base)
-{
-	XGI_OH *poh;
-
-	poh = XGIfb_poh_free(base);
-
-	if (poh == NULL) {
-		DPRINTK("XGIfb: XGIfb_poh_free() failed at base 0x%x\n",
-				(unsigned int) base);
-	}
-}
-
 /* --------------------- SetMode routines ------------------------- */
 
 static void XGIfb_pre_setmode(void)
@@ -2622,10 +1895,6 @@ static void XGIfb_pre_setmode(void)
 	outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR30, cr30);
 	outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR31, cr31);
 	outXGIIDXREG(XGICR, IND_XGI_SCRATCH_REG_CR33, (XGIfb_rate_idx & 0x0F));
-
-	if (xgi_video_info.accel)
-		XGIfb_syncaccel();
-
 }
 
 static void XGIfb_post_setmode(void)
@@ -2840,22 +2109,16 @@ XGIINITSTATIC int __init XGIfb_setup(char *options)
 			XGIfb_search_tvstd(this_opt + 7);
 		} else if (!strncmp(this_opt, "tvstandard:", 11)) {
 			XGIfb_search_tvstd(this_opt + 7);
-		} else if (!strncmp(this_opt, "mem:", 4)) {
-			XGIfb_mem = simple_strtoul(this_opt + 4, NULL, 0);
 		} else if (!strncmp(this_opt, "dstn", 4)) {
 			enable_dstn = 1;
 			/* TW: DSTN overrules forcecrt2type */
 			XGIfb_crt2type = DISPTYPE_LCD;
-		} else if (!strncmp(this_opt, "queuemode:", 10)) {
-			XGIfb_search_queuemode(this_opt + 10);
 		} else if (!strncmp(this_opt, "pdc:", 4)) {
 			XGIfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
 			if (XGIfb_pdc & ~0x3c) {
 				printk(KERN_INFO "XGIfb: Illegal pdc parameter\n");
 				XGIfb_pdc = 0;
 			}
-		} else if (!strncmp(this_opt, "noaccel", 7)) {
-			XGIfb_accel = 0;
 		} else if (!strncmp(this_opt, "noypan", 6)) {
 			XGIfb_ypan = 0;
 		} else if (!strncmp(this_opt, "userom:", 7)) {
@@ -2867,74 +2130,43 @@ XGIINITSTATIC int __init XGIfb_setup(char *options)
 			/* printk(KERN_INFO "XGIfb: Invalid option %s\n", this_opt); */
 		}
 
-		/* TW: Acceleration only with MMIO mode */
-		if ((XGIfb_queuemode != -1) && (XGIfb_queuemode != MMIO_CMD)) {
-			XGIfb_ypan = 0;
-			XGIfb_accel = 0;
-		}
 		/* TW: Panning only with acceleration */
-		if (XGIfb_accel == 0)
-			XGIfb_ypan = 0;
+		XGIfb_ypan = 0;
 
 	}
 	printk("\nxgifb: outa xgifb_setup 3450");
 	return 0;
 }
 
-static unsigned char VBIOS_BUF[65535];
-
-static unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
+static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
 {
-	u32 rom_size = 0;
-	u32 rom_address = 0;
-	int j;
-
-	/*  Get the size of the expansion rom */
-	pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
-	pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
-	if ((rom_size & 0x01) == 0) {
-		printk("No ROM\n");
-		return NULL;
-	}
+	void __iomem *rom_address;
+	unsigned char *rom_copy;
+	size_t rom_size;
 
-	rom_size &= 0xFFFFF800;
-	rom_size = (~rom_size) + 1;
-
-	rom_address = pci_resource_start(dev, 0);
-	if (rom_address == 0 || rom_address == 0xFFFFFFF0) {
-		printk("No suitable rom address found\n");
+	rom_address = pci_map_rom(dev, &rom_size);
+	if (rom_address == NULL)
 		return NULL;
-	}
 
-	printk("ROM Size is %dK, Address is %x\n", rom_size / 1024, rom_address);
+	rom_copy = vzalloc(XGIFB_ROM_SIZE);
+	if (rom_copy == NULL)
+		goto done;
 
-	/*  Map ROM */
-	pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address
-			| PCI_ROM_ADDRESS_ENABLE);
+	rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
+	memcpy_fromio(rom_copy, rom_address, rom_size);
 
-	/* memcpy(copy_address, rom_address, rom_size); */
-	{
-		unsigned char *virt_addr = ioremap(rom_address, 0x8000000);
-
-		unsigned char *from = (unsigned char *) virt_addr;
-		unsigned char *to = (unsigned char *) copy_address;
-		for (j = 0; j < 65536 /*rom_size*/; j++)
-			*to++ = *from++;
-	}
-
-	pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
-
-	printk("Copy is done\n");
-
-	return copy_address;
+done:
+	pci_unmap_rom(dev, rom_address);
+	return rom_copy;
 }
 
 static int __devinit xgifb_probe(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
-	u16 reg16;
 	u8 reg, reg1;
 	u8 CR48, CR38;
+	int ret;
+
 	if (XGIfb_off)
 		return -ENXIO;
 
@@ -2947,9 +2179,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 
 	xgi_video_info.chip_id = pdev->device;
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &xgi_video_info.revision_id);
-	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
 	XGIhw_ext.jChipRevision = xgi_video_info.revision_id;
-	XGIvga_enabled = reg16 & 0x01;
 
 	xgi_video_info.pcibus = pdev->bus->number;
 	xgi_video_info.pcislot = PCI_SLOT(pdev->devfn);
@@ -2959,15 +2189,17 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 
 	xgi_video_info.video_base = pci_resource_start(pdev, 0);
 	xgi_video_info.mmio_base = pci_resource_start(pdev, 1);
-	XGIfb_mmio_size = pci_resource_len(pdev, 1);
+	xgi_video_info.mmio_size = pci_resource_len(pdev, 1);
 	xgi_video_info.vga_base = pci_resource_start(pdev, 2) + 0x30;
 	XGIhw_ext.pjIOAddress = (unsigned char *)xgi_video_info.vga_base;
 	/* XGI_Pr.RelIO  = ioremap(pci_resource_start(pdev, 2), 128) + 0x30; */
 	printk("XGIfb: Relocate IO address: %lx [%08lx]\n",
 			(unsigned long)pci_resource_start(pdev, 2), XGI_Pr.RelIO);
 
-	if (pci_enable_device(pdev))
-		return -EIO;
+	if (pci_enable_device(pdev)) {
+		ret = -EIO;
+		goto error;
+	}
 
 	XGIRegInit(&XGI_Pr, (unsigned long)XGIhw_ext.pjIOAddress);
 
@@ -2976,7 +2208,8 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 
 	if (reg1 != 0xa1) { /*I/O error */
 		printk("\nXGIfb: I/O error!!!");
-		return -EIO;
+		ret = -EIO;
+		goto error;
 	}
 
 	switch (xgi_video_info.chip_id) {
@@ -2987,54 +2220,34 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 			xgi_video_info.chip = XG21;
 		else
 			xgi_video_info.chip = XG20;
-		XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
 		XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
 		break;
 	case PCI_DEVICE_ID_XG_40:
 		xgi_video_info.chip = XG40;
-		XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
 		XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
 		break;
 	case PCI_DEVICE_ID_XG_41:
 		xgi_video_info.chip = XG41;
-		XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
 		XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
 		break;
 	case PCI_DEVICE_ID_XG_42:
 		xgi_video_info.chip = XG42;
-		XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
 		XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
 		break;
 	case PCI_DEVICE_ID_XG_27:
 		xgi_video_info.chip = XG27;
-		XGIfb_hwcursor_size = HW_CURSOR_AREA_SIZE_315 * 2;
 		XGIfb_CRT2_write_enable = IND_XGI_CRT2_WRITE_ENABLE_315;
 		break;
 	default:
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error;
 	}
 
 	printk("XGIfb:chipid = %x\n", xgi_video_info.chip);
 	XGIhw_ext.jChipType = xgi_video_info.chip;
 
-	switch (xgi_video_info.chip) {
-	case XG40:
-	case XG41:
-	case XG42:
-	case XG45:
-	case XG20:
-	case XG21:
-	case XG27:
-		XGIhw_ext.bIntegratedMMEnabled = 1;
-		break;
-	default:
-		break;
-	}
-
-	XGIhw_ext.pDevice = NULL;
 	if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
-		XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);
-
+		XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
 		if (XGIhw_ext.pjVirtualRomBase)
 			printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
 		else
@@ -3043,64 +2256,12 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 		XGIhw_ext.pjVirtualRomBase = NULL;
 		printk(KERN_INFO "XGIfb: Video ROM usage disabled\n");
 	}
-	XGIhw_ext.pjCustomizedROMImage = NULL;
-	XGIhw_ext.bSkipDramSizing = 0;
 	XGIhw_ext.pQueryVGAConfigSpace = &XGIfb_query_VGA_config_space;
-	/* XGIhw_ext.pQueryNorthBridgeSpace = &XGIfb_query_north_bridge_space; */
-	strcpy(XGIhw_ext.szVBIOSVer, "0.84");
-
-	XGIhw_ext.pSR = vmalloc(sizeof(struct XGI_DSReg) * SR_BUFFER_SIZE);
-	if (XGIhw_ext.pSR == NULL) {
-		printk(KERN_ERR "XGIfb: Fatal error: Allocating SRReg space failed.\n");
-		return -ENODEV;
-	}
-	XGIhw_ext.pSR[0].jIdx = XGIhw_ext.pSR[0].jVal = 0xFF;
 
-	XGIhw_ext.pCR = vmalloc(sizeof(struct XGI_DSReg) * CR_BUFFER_SIZE);
-	if (XGIhw_ext.pCR == NULL) {
-		vfree(XGIhw_ext.pSR);
-		printk(KERN_ERR "XGIfb: Fatal error: Allocating CRReg space failed.\n");
-		return -ENODEV;
-	}
-	XGIhw_ext.pCR[0].jIdx = XGIhw_ext.pCR[0].jVal = 0xFF;
-
-	if (!XGIvga_enabled) {
-		/* Mapping Max FB Size for 315 Init */
-		XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
-		if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
-#ifdef LINUXBIOS
-			printk("XGIfb: XGIInit() ...");
-			/* XGIInitNewt for LINUXBIOS only */
-			if (XGIInitNew(&XGIhw_ext))
-				printk("OK\n");
-			else
-				printk("Fail\n");
-#endif
-
-			outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
-
-		}
-	}
-#ifdef LINUXBIOS
-	else {
-		XGIhw_ext.pjVideoMemoryAddress = ioremap(xgi_video_info.video_base, 0x10000000);
-		if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
-
-			outXGIIDXREG(XGISR, IND_XGI_PASSWORD, XGI_PASSWORD);
-
-			/* yilin Because no VBIOS DRAM Sizing, Dram size will error. */
-			/* Set SR13 ,14 temporarily for UDtech */
-			outXGIIDXREG(XGISR, 0x13, 0x45);
-			outXGIIDXREG(XGISR, 0x14, 0x51);
-
-		}
-	}
-#endif
 	if (XGIfb_get_dram_size()) {
-		vfree(XGIhw_ext.pSR);
-		vfree(XGIhw_ext.pCR);
 		printk(KERN_INFO "XGIfb: Fatal error: Unable to determine RAM size.\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error;
 	}
 
 	if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
@@ -3116,37 +2277,35 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 		printk("unable request memory size %x", xgi_video_info.video_size);
 		printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve frame buffer memory\n");
 		printk(KERN_ERR "XGIfb: Is there another framebuffer driver active?\n");
-		vfree(XGIhw_ext.pSR);
-		vfree(XGIhw_ext.pCR);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error;
 	}
 
-	if (!request_mem_region(xgi_video_info.mmio_base, XGIfb_mmio_size, "XGIfb MMIO")) {
+	if (!request_mem_region(xgi_video_info.mmio_base,
+				xgi_video_info.mmio_size,
+				"XGIfb MMIO")) {
 		printk(KERN_ERR "XGIfb: Fatal error: Unable to reserve MMIO region\n");
-		release_mem_region(xgi_video_info.video_base, xgi_video_info.video_size);
-		vfree(XGIhw_ext.pSR);
-		vfree(XGIhw_ext.pCR);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto error_0;
 	}
 
 	xgi_video_info.video_vbase = XGIhw_ext.pjVideoMemoryAddress =
 	ioremap(xgi_video_info.video_base, xgi_video_info.video_size);
-	xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base, XGIfb_mmio_size);
+	xgi_video_info.mmio_vbase = ioremap(xgi_video_info.mmio_base,
+					    xgi_video_info.mmio_size);
 
 	printk(KERN_INFO "XGIfb: Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
 			xgi_video_info.video_base, xgi_video_info.video_vbase, xgi_video_info.video_size / 1024);
 
 	printk(KERN_INFO "XGIfb: MMIO at 0x%lx, mapped to 0x%p, size %ldk\n",
-			xgi_video_info.mmio_base, xgi_video_info.mmio_vbase, XGIfb_mmio_size / 1024);
+	       xgi_video_info.mmio_base, xgi_video_info.mmio_vbase,
+	       xgi_video_info.mmio_size / 1024);
 	printk("XGIfb: XGIInitNew() ...");
 	if (XGIInitNew(&XGIhw_ext))
 		printk("OK\n");
 	else
 		printk("Fail\n");
 
-	if (XGIfb_heap_init())
-		printk(KERN_WARNING "XGIfb: Failed to initialize offscreen memory heap\n");
-
 	xgi_video_info.mtrr = (unsigned int) 0;
 
 	if ((xgifb_mode_idx < 0) || ((XGIbios_mode[xgifb_mode_idx].mode_no) != 0xFF)) {
@@ -3162,7 +2321,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 					for (m = 0; m < sizeof(XGI21_LCDCapList)/sizeof(struct XGI21_LVDSCapStruct); m++) {
 						if ((XGI21_LCDCapList[m].LVDSHDE == XGIbios_mode[xgifb_mode_idx].xres) &&
 								(XGI21_LCDCapList[m].LVDSVDE == XGIbios_mode[xgifb_mode_idx].yres)) {
-							XGINew_SetReg1(XGI_Pr.P3d4, 0x36, m);
+							xgifb_reg_set(XGI_Pr.P3d4, 0x36, m);
 						}
 					}
 				}
@@ -3265,7 +2424,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 		XGIfb_detectedpdc = 0;
 
 		XGIfb_detectedlcda = 0xff;
-#ifndef LINUXBIOS
 
 		/* TW: Try to find about LCDA */
 
@@ -3298,8 +2456,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 
 		}
 
-#endif
-
 		if (xgifb_mode_idx >= 0)
 			xgifb_mode_idx = XGIfb_validate_mode(xgifb_mode_idx);
 
@@ -3387,13 +2543,6 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 
 		}
 
-		xgi_video_info.accel = 0;
-		if (XGIfb_accel) {
-			xgi_video_info.accel = -1;
-			default_var.accel_flags |= FB_ACCELF_TEXT;
-			XGIfb_initaccel();
-		}
-
 		fb_info->flags = FBINFO_FLAG_DEFAULT;
 		fb_info->var = default_var;
 		fb_info->fix = XGIfb_fix;
@@ -3413,8 +2562,10 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 			printk(KERN_INFO "XGIfb: Added MTRRs\n");
 #endif
 
-		if (register_framebuffer(fb_info) < 0)
-			return -EINVAL;
+		if (register_framebuffer(fb_info) < 0) {
+			ret = -EINVAL;
+			goto error_1;
+		}
 
 		XGIfb_registered = 1;
 
@@ -3426,6 +2577,18 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 	dumpVGAReg();
 
 	return 0;
+
+error_1:
+	iounmap(xgi_video_info.mmio_vbase);
+	iounmap(xgi_video_info.video_vbase);
+	release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
+error_0:
+	release_mem_region(xgi_video_info.video_base,
+			   xgi_video_info.video_size);
+error:
+	vfree(XGIhw_ext.pjVirtualRomBase);
+	framebuffer_release(fb_info);
+	return ret;
 }
 
 /*****************************************************/
@@ -3434,15 +2597,16 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
 
 static void __devexit xgifb_remove(struct pci_dev *pdev)
 {
-	/* Unregister the framebuffer */
-	/* if (xgi_video_info.registered) { */
 	unregister_framebuffer(fb_info);
+	iounmap(xgi_video_info.mmio_vbase);
+	iounmap(xgi_video_info.video_vbase);
+	release_mem_region(xgi_video_info.mmio_base, xgi_video_info.mmio_size);
+	release_mem_region(xgi_video_info.video_base,
+			   xgi_video_info.video_size);
+	vfree(XGIhw_ext.pjVirtualRomBase);
 	framebuffer_release(fb_info);
-	/* } */
-
 	pci_set_drvdata(pdev, NULL);
-
-};
+}
 
 static struct pci_driver xgifb_driver = {
 	.name = "xgifb",
@@ -3480,9 +2644,7 @@ static char *forcecrt2type = NULL;
 static int forcecrt1 = -1;
 static int pdc = -1;
 static int pdc1 = -1;
-static int noaccel = -1;
 static int noypan = -1;
-static int nomax = -1;
 static int userom = -1;
 static int useoem = -1;
 static char *tvstandard = NULL;
@@ -3501,9 +2663,7 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("XGITECH , Others");
 
 module_param(mem, int, 0);
-module_param(noaccel, int, 0);
 module_param(noypan, int, 0);
-module_param(nomax, int, 0);
 module_param(userom, int, 0);
 module_param(useoem, int, 0);
 module_param(mode, charp, 0);
@@ -3526,30 +2686,10 @@ module_param(resetcard, int, 0);
 module_param(videoram, int, 0);
 #endif
 
-MODULE_PARM_DESC(mem,
-		"\nDetermines the beginning of the video memory heap in KB. This heap is used\n"
-		"for video RAM management for eg. DRM/DRI. On 300 series, the default depends\n"
-		"on the amount of video RAM available. If 8MB of video RAM or less is available,\n"
-		"the heap starts at 4096KB, if between 8 and 16MB are available at 8192KB,\n"
-		"otherwise at 12288KB. On 315 and Xabre series, the heap size is 32KB by default.\n"
-		"The value is to be specified without 'KB' and must match the MaxXFBMem setting\n"
-		"for XFree86 4.x/X.org 6.7 and later.\n");
-
-MODULE_PARM_DESC(noaccel,
-		"\nIf set to anything other than 0, 2D acceleration will be disabled.\n"
-		"(default: 0)\n");
-
 MODULE_PARM_DESC(noypan,
 		"\nIf set to anything other than 0, y-panning will be disabled and scrolling\n"
 		"will be performed by redrawing the screen. (default: 0)\n");
 
-MODULE_PARM_DESC(nomax,
-		"\nIf y-panning is enabled, xgifb will by default use the entire available video\n"
-		"memory for the virtual screen in order to optimize scrolling performance. If\n"
-		"this is set to anything other than 0, xgifb will not do this and thereby\n"
-		"enable the user to positively specify a virtual Y size of the screen using\n"
-		"fbset. (default: 0)\n");
-
 MODULE_PARM_DESC(mode,
 		"\nSelects the desired default display mode in the format XxYxDepth,\n"
 		"eg. 1024x768x16. Other formats supported include XxY-Depth and\n"
@@ -3647,7 +2787,3 @@ module_init(xgifb_init_module);
 module_exit(xgifb_remove_module);
 
 #endif	/*  /MODULE  */
-
-EXPORT_SYMBOL(XGI_malloc);
-EXPORT_SYMBOL(XGI_free);
-
diff --git a/drivers/staging/xgifb/XGIfb.h b/drivers/staging/xgifb/XGIfb.h
index ef86a64..b43a758 100644
--- a/drivers/staging/xgifb/XGIfb.h
+++ b/drivers/staging/xgifb/XGIfb.h
@@ -1,6 +1,5 @@
 #ifndef _LINUX_XGIFB
 #define _LINUX_XGIFB
-#include <linux/spinlock.h>
 #include <asm/ioctl.h>
 #include <asm/types.h>
 
@@ -28,23 +27,6 @@
 #endif
 
 enum XGI_CHIP_TYPE {
-    XGI_VGALegacy = 0,
-    XGI_300,
-    XGI_630,
-    XGI_730,
-    XGI_540,
-    XGI_315H,
-    XGI_315,
-    XGI_315PRO,
-    XGI_550,
-    XGI_640,
-    XGI_740,
-    XGI_650,
-    XGI_650M,
-    XGI_330 = 16,
-    XGI_660,
-    XGI_661,
-    XGI_760,
     XG40 = 32,
     XG41,
     XG42,
@@ -52,7 +34,6 @@ enum XGI_CHIP_TYPE {
     XG20 = 48,
     XG21,
     XG27,
-    MAX_XGI_CHIP
 };
 
 enum xgi_tvtype {
@@ -65,36 +46,6 @@ enum xgi_tvtype {
 	TVMODE_TOTAL
 };
 
-
-struct XGIfb_info {
-	unsigned long XGIfb_id;
- 	int    chip_id;			/* PCI ID of detected chip */
-	int    memory;			/* video memory in KB which XGIfb manages */
-	int    heapstart;               /* heap start (= XGIfb "mem" argument) in KB */
-	unsigned char fbvidmode;	/* current XGIfb mode */
-
-	unsigned char XGIfb_version;
-	unsigned char XGIfb_revision;
-	unsigned char XGIfb_patchlevel;
-
-	unsigned char XGIfb_caps;	/* XGIfb capabilities */
-
-	int    XGIfb_tqlen;		/* turbo queue length (in KB) */
-
-	unsigned int XGIfb_pcibus;      /* The card's PCI ID */
-	unsigned int XGIfb_pcislot;
-	unsigned int XGIfb_pcifunc;
-
-	unsigned char XGIfb_lcdpdc;	/* PanelDelayCompensation */
-
-	unsigned char XGIfb_lcda;	/* Detected status of LCDA for low res/text modes */
-
-	char reserved[235]; 		/* for future use */
-};
-
-
-
-
 enum xgi_tv_plug {	/* vicki@030226 */
 //	TVPLUG_Legacy = 0,
 //	TVPLUG_COMPOSITE,
@@ -113,58 +64,16 @@ enum xgi_tv_plug {	/* vicki@030226 */
 	TVPLUG_TOTAL
 };
 
-
-struct mode_info {
-	int    bpp;
-	int    xres;
-	int    yres;
-	int    v_xres;
-	int    v_yres;
-	int    org_x;
-	int    org_y;
-	unsigned int  vrate;
-};
-
-struct ap_data {
-	struct mode_info minfo;
-	unsigned long iobase;
-	unsigned int  mem_size;
-	unsigned long disp_state;
-	enum XGI_CHIP_TYPE chip;
-	unsigned char hasVB;
-	enum xgi_tvtype TV_type;
-	enum xgi_tv_plug TV_plug;
-	unsigned long version;
-	char reserved[256];
-};
-
-
-
-/*     If changing this, vgatypes.h must also be changed (for X driver)    */
-
-
-/*
- * NOTE! The ioctl types used to be "size_t" by mistake, but were
- * really meant to be __u32. Changed to "__u32" even though that
- * changes the value on 64-bit architectures, because the value
- * (with a 4-byte size) is also hardwired in vgatypes.h for user
- * space exports. So "__u32" is actually more compatible, duh!
- */
-#define XGIFB_GET_INFO	  	_IOR('n',0xF8,__u32)
-#define XGIFB_GET_VBRSTATUS  	_IOR('n',0xF9,__u32)
-
-
-
 struct video_info{
         int           chip_id;
         unsigned int  video_size;
         unsigned long video_base;
         char  *       video_vbase;
         unsigned long mmio_base;
+	unsigned long mmio_size;
         char  *       mmio_vbase;
         unsigned long vga_base;
         unsigned long mtrr;
-        unsigned long heapstart;
 
         int    video_bpp;
         int    video_cmap_len;
@@ -189,13 +98,10 @@ struct video_info{
         unsigned long  XGI310_AccelDepth;
         unsigned long  CommandReg;
 
-        spinlock_t     lockaccel;
-
         unsigned int   pcibus;
         unsigned int   pcislot;
         unsigned int   pcifunc;
 
-        int            accel;
         unsigned short subsysvendor;
         unsigned short subsysdevice;
 
diff --git a/drivers/staging/xgifb/vb_ext.c b/drivers/staging/xgifb/vb_ext.c
index 80c7818..d7c1b2e 100644
--- a/drivers/staging/xgifb/vb_ext.c
+++ b/drivers/staging/xgifb/vb_ext.c
@@ -9,41 +9,16 @@
 #include "vb_util.h"
 #include "vb_setmode.h"
 #include "vb_ext.h"
-extern unsigned char XGI330_SoftSetting;
-extern unsigned char XGI330_OutputSelect;
-extern unsigned short XGI330_RGBSenseData2;
-extern unsigned short XGI330_YCSenseData2;
-extern unsigned short XGI330_VideoSenseData2;
-void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo);
-unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo);
-unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
-		struct vb_device_info *pVBInfo);
-unsigned char XGINew_GetLCDDDCInfo(
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo);
-void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
-		unsigned long VESA_POWER_STATE);
-unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *,
-		struct vb_device_info *pVBInfo);
-unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx,
-		struct vb_device_info *pVBInfo);
-unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo);
 
 /**************************************************************
  *********************** Dynamic Sense ************************
  *************************************************************/
 
-void XGI_WaitDisplay(void);
-unsigned char XGI_Is301C(struct vb_device_info *);
-unsigned char XGI_Is301LV(struct vb_device_info *);
-
 static unsigned char XGINew_Is301B(struct vb_device_info *pVBInfo)
 {
 	unsigned short flag;
 
-	flag = XGINew_GetReg1(pVBInfo->Part4Port, 0x01);
+	flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01);
 
 	if (flag > 0x0B0)
 		return 0; /* 301b */
@@ -51,43 +26,21 @@ static unsigned char XGINew_Is301B(struct vb_device_info *pVBInfo)
 		return 1;
 }
 
-unsigned char XGI_Is301C(struct vb_device_info *pVBInfo)
-{
-	if ((XGINew_GetReg1(pVBInfo->Part4Port, 0x01) & 0xF0) == 0xC0)
-		return 1;
-
-	if (XGINew_GetReg1(pVBInfo->Part4Port, 0x01) >= 0xD0) {
-		if (XGINew_GetReg1(pVBInfo->Part4Port, 0x39) == 0xE0)
-			return 1;
-	}
-
-	return 0;
-}
-
-unsigned char XGI_Is301LV(struct vb_device_info *pVBInfo)
-{
-	if (XGINew_GetReg1(pVBInfo->Part4Port, 0x01) >= 0xD0) {
-		if (XGINew_GetReg1(pVBInfo->Part4Port, 0x39) == 0xFF)
-			return 1;
-	}
-	return 0;
-}
-
-unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx, struct vb_device_info *pVBInfo)
+static unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx, struct vb_device_info *pVBInfo)
 {
 	unsigned short temp, i, tempch;
 
 	temp = tempbx & 0xFF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x11, temp);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
 	temp = (tempbx & 0xFF00) >> 8;
 	temp |= (tempcx & 0x00FF);
-	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
+	xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
 
 	for (i = 0; i < 10; i++)
 		XGI_LongWait(pVBInfo);
 
 	tempch = (tempcx & 0x7F00) >> 8;
-	temp = XGINew_GetReg1(pVBInfo->Part4Port, 0x03);
+	temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
 	temp = temp ^ (0x0E);
 	temp &= tempch;
 
@@ -97,347 +50,7 @@ unsigned char XGINew_Sense(unsigned short tempbx, unsigned short tempcx, struct
 		return 0;
 }
 
-void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE, unsigned long VESA_POWER_STATE)
-{
-	unsigned short ModeNo, ModeIdIndex;
-	unsigned char temp;
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	pVBInfo->BaseAddr = (unsigned long) pXGIHWDE->pjIOAddress;
-	pVBInfo->ROMAddr = pXGIHWDE->pjVirtualRomBase;
-
-	pVBInfo->IF_DEF_LVDS = 0;
-	pVBInfo->IF_DEF_CH7005 = 0;
-	pVBInfo->IF_DEF_HiVision = 1;
-	pVBInfo->IF_DEF_LCDA = 1;
-	pVBInfo->IF_DEF_CH7017 = 0;
-	pVBInfo->IF_DEF_YPbPr = 1;
-	pVBInfo->IF_DEF_CRT2Monitor = 0;
-	pVBInfo->IF_DEF_VideoCapture = 0;
-	pVBInfo->IF_DEF_ScaleLCD = 0;
-	pVBInfo->IF_DEF_OEMUtil = 0;
-	pVBInfo->IF_DEF_PWD = 0;
-
-	InitTo330Pointer(pXGIHWDE->jChipType, pVBInfo);
-	ReadVBIOSTablData(pXGIHWDE->jChipType, pVBInfo);
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-
-	if (pXGIHWDE->jChipType == XG27) {
-		if ((XGINew_GetReg1(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0) {
-			if (XGINew_GetReg1(pVBInfo->P3d4, 0x30) & 0x20)
-				pVBInfo->IF_DEF_LVDS = 1;
-		}
-	}
-
-	if (pVBInfo->IF_DEF_CH7007 == 0)
-		XGINew_SetModeScratch(pXGIHWDE, pVBInfo);
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x05, 0x86); /* 1.Openkey */
-	XGI_UnLockCRT2(pXGIHWDE, pVBInfo);
-	ModeNo = XGINew_GetReg1(pVBInfo->P3d4, 0x34);
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
-	XGI_GetVGAType(pXGIHWDE, pVBInfo);
-
-	if ((pXGIHWDE->ujVBChipID == VB_CHIP_301) || (pXGIHWDE->ujVBChipID == VB_CHIP_302) || (pVBInfo->IF_DEF_CH7007 == 1)) {
-		XGI_GetVBType(pVBInfo);
-		XGI_GetVBInfo(ModeNo, ModeIdIndex, pXGIHWDE, pVBInfo);
-		XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo);
-		XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo);
-	}
-
-	if (VESA_POWER_STATE == 0x00000400)
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x31, (unsigned char) (XGINew_GetReg1(pVBInfo->Part4Port, 0x31) & 0xFE));
-	else
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x31, (unsigned char) (XGINew_GetReg1(pVBInfo->Part4Port, 0x31) | 0x01));
-
-	temp = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x1f);
-	temp &= 0x3f;
-	switch (VESA_POWER_STATE) {
-	case 0x00000000: /* on */
-		if ((pXGIHWDE->ujVBChipID == VB_CHIP_301) || (pXGIHWDE->ujVBChipID == VB_CHIP_302)) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char) (temp | 0x00));
-			XGI_EnableBridge(pXGIHWDE, pVBInfo);
-		} else {
-			if (pXGIHWDE->jChipType == XG21) {
-				if (pVBInfo->IF_DEF_LVDS == 1) {
-					XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo); /* LVDS VDD on */
-					XGI_XG21SetPanelDelay(2, pVBInfo);
-				}
-			}
-			if (pXGIHWDE->jChipType == XG27) {
-				if (pVBInfo->IF_DEF_LVDS == 1) {
-					XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo); /* LVDS VDD on */
-					XGI_XG21SetPanelDelay(2, pVBInfo);
-				}
-			}
-			XGINew_SetRegANDOR(pVBInfo->P3c4, 0x1F, ~0xC0, 0x00);
-			XGINew_SetRegAND(pVBInfo->P3c4, 0x01, ~0x20); /* CRT on */
-
-			if (pXGIHWDE->jChipType == XG21) {
-				temp = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
-				if (temp & 0xE0) {
-					XGINew_SetRegANDOR(pVBInfo->P3c4, 0x09, ~0x80, 0x80); /* DVO ON */
-					XGI_SetXG21FPBits(pVBInfo);
-					XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x20); /* Enable write GPIOF */
-					/* XGINew_SetRegANDOR(pVBInfo->P3d4, 0x48, ~0x20, 0x20); *//* LCD Display ON */
-				}
-				XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); /* LVDS signal on */
-				XGI_DisplayOn(pXGIHWDE, pVBInfo);
-			}
-			if (pXGIHWDE->jChipType == XG27) {
-				temp = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
-				if (temp & 0xE0) {
-					XGINew_SetRegANDOR(pVBInfo->P3c4, 0x09, ~0x80, 0x80); /* DVO ON */
-					XGI_SetXG27FPBits(pVBInfo);
-					XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x20); /* Enable write GPIOF */
-					/* XGINew_SetRegANDOR(pVBInfo->P3d4, 0x48, ~0x20, 0x20); *//* LCD Display ON */
-				}
-				XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); /* LVDS signal on */
-				XGI_DisplayOn(pXGIHWDE, pVBInfo);
-			}
-		}
-		break;
-
-	case 0x00000100: /* standby */
-		if (pXGIHWDE->jChipType >= XG21)
-			XGI_DisplayOff(pXGIHWDE, pVBInfo);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char) (temp | 0x40));
-		break;
-
-	case 0x00000200: /* suspend */
-		if (pXGIHWDE->jChipType == XG21) {
-			XGI_DisplayOff(pXGIHWDE, pVBInfo);
-			XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo); /* LVDS signal off */
-		}
-		if (pXGIHWDE->jChipType == XG27) {
-			XGI_DisplayOff(pXGIHWDE, pVBInfo);
-			XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo); /* LVDS signal off */
-		}
-		XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char) (temp | 0x80));
-		break;
-
-	case 0x00000400: /* off */
-		if ((pXGIHWDE->ujVBChipID == VB_CHIP_301) || (pXGIHWDE->ujVBChipID == VB_CHIP_302)) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x1f, (unsigned char) (temp | 0xc0));
-			XGI_DisableBridge(pXGIHWDE, pVBInfo);
-		} else {
-			if (pXGIHWDE->jChipType == XG21) {
-				XGI_DisplayOff(pXGIHWDE, pVBInfo);
-
-				XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo); /* LVDS signal off */
-
-				temp = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
-				if (temp & 0xE0) {
-					XGINew_SetRegAND(pVBInfo->P3c4, 0x09, ~0x80); /* DVO Off */
-					XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x20); /* Enable write GPIOF */
-					/* XGINew_SetRegAND(pVBInfo->P3d4, 0x48, ~0x20); *//* LCD Display OFF */
-				}
-			}
-			if (pXGIHWDE->jChipType == XG27) {
-				XGI_DisplayOff(pXGIHWDE, pVBInfo);
-
-				XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo); /* LVDS signal off */
-
-				temp = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
-				if (temp & 0xE0)
-					XGINew_SetRegAND(pVBInfo->P3c4, 0x09, ~0x80); /* DVO Off */
-			}
-			XGINew_SetRegANDOR(pVBInfo->P3c4, 0x1F, ~0xC0, 0xC0);
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x01, 0x20); /* CRT Off */
-
-			if ((pXGIHWDE->jChipType == XG21) && (pVBInfo->IF_DEF_LVDS == 1)) {
-				XGI_XG21SetPanelDelay(4, pVBInfo);
-				XGI_XG21BLSignalVDD(0x01, 0x00, pVBInfo); /* LVDS VDD off */
-				XGI_XG21SetPanelDelay(5, pVBInfo);
-			}
-			if ((pXGIHWDE->jChipType == XG27) && (pVBInfo->IF_DEF_LVDS == 1)) {
-				XGI_XG21SetPanelDelay(4, pVBInfo);
-				XGI_XG27BLSignalVDD(0x01, 0x00, pVBInfo); /* LVDS VDD off */
-				XGI_XG21SetPanelDelay(5, pVBInfo);
-			}
-		}
-		break;
-
-	default:
-		break;
-	}
-	XGI_LockCRT2(pXGIHWDE, pVBInfo);
-}
-
-void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
-{
-	unsigned short tempax = 0, tempbx, tempcx, temp, P2reg0 = 0, SenseModeNo = 0,
-			OutputSelect = *pVBInfo->pOutputSelect, ModeIdIndex, i;
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-
-	if (pVBInfo->IF_DEF_LVDS == 1) {
-		tempax = XGINew_GetReg1(pVBInfo->P3c4, 0x1A); /* ynlai 02/27/2002 */
-		tempbx = XGINew_GetReg1(pVBInfo->P3c4, 0x1B);
-		tempax = ((tempax & 0xFE) >> 1) | (tempbx << 8);
-		if (tempax == 0x00) { /* Get Panel id from DDC */
-			temp = XGINew_GetLCDDDCInfo(HwDeviceExtension, pVBInfo);
-			if (temp == 1) { /* LCD connect */
-				XGINew_SetRegANDOR(pVBInfo->P3d4, 0x39, 0xFF, 0x01); /* set CR39 bit0="1" */
-				XGINew_SetRegANDOR(pVBInfo->P3d4, 0x37, 0xEF, 0x00); /* clean CR37 bit4="0" */
-				temp = LCDSense;
-			} else { /* LCD don't connect */
-				temp = 0;
-			}
-		} else {
-			XGINew_GetPanelID(pVBInfo);
-			temp = LCDSense;
-		}
-
-		tempbx = ~(LCDSense | AVIDEOSense | SVIDEOSense);
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, tempbx, temp);
-	} else { /* for 301 */
-		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { /* for HiVision */
-			tempax = XGINew_GetReg1(pVBInfo->P3c4, 0x38);
-			temp = tempax & 0x01;
-			tempax = XGINew_GetReg1(pVBInfo->P3c4, 0x3A);
-			temp = temp | (tempax & 0x02);
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, 0xA0, temp);
-		} else {
-			if (XGI_BridgeIsOn(pVBInfo)) {
-				P2reg0 = XGINew_GetReg1(pVBInfo->Part2Port, 0x00);
-				if (!XGINew_BridgeIsEnable(HwDeviceExtension, pVBInfo)) {
-					SenseModeNo = 0x2e;
-					/* XGINew_SetReg1(pVBInfo->P3d4, 0x30, 0x41); */
-					/* XGISetModeNew(HwDeviceExtension, 0x2e); // ynlai InitMode */
-
-					temp = XGI_SearchModeID(SenseModeNo, &ModeIdIndex, pVBInfo);
-					XGI_GetVGAType(HwDeviceExtension, pVBInfo);
-					XGI_GetVBType(pVBInfo);
-					pVBInfo->SetFlag = 0x00;
-					pVBInfo->ModeType = ModeVGA;
-					pVBInfo->VBInfo = SetCRT2ToRAMDAC | LoadDACFlag | SetInSlaveMode;
-					XGI_GetLCDInfo(0x2e, ModeIdIndex, pVBInfo);
-					XGI_GetTVInfo(0x2e, ModeIdIndex, pVBInfo);
-					XGI_EnableBridge(HwDeviceExtension, pVBInfo);
-					XGI_SetCRT2Group301(SenseModeNo, HwDeviceExtension, pVBInfo);
-					XGI_SetCRT2ModeRegs(0x2e, HwDeviceExtension, pVBInfo);
-					/* XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; */
-					XGINew_SetRegANDOR(pVBInfo->P3c4, 0x01, 0xDF, 0x20); /* Display Off 0212 */
-					for (i = 0; i < 20; i++)
-						XGI_LongWait(pVBInfo);
-				}
-				XGINew_SetReg1(pVBInfo->Part2Port, 0x00, 0x1c);
-				tempax = 0;
-				tempbx = *pVBInfo->pRGBSenseData;
-
-				if (!(XGINew_Is301B(pVBInfo)))
-					tempbx = *pVBInfo->pRGBSenseData2;
-
-				tempcx = 0x0E08;
-				if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
-					if (XGINew_Sense(tempbx, tempcx, pVBInfo))
-						tempax |= Monitor2Sense;
-				}
-
-				if (pVBInfo->VBType & VB_XGI301C)
-					XGINew_SetRegOR(pVBInfo->Part4Port, 0x0d, 0x04);
-
-				if (XGINew_SenseHiTV(HwDeviceExtension, pVBInfo)) { /* add by kuku for Multi-adapter sense HiTV */
-					tempax |= HiTVSense;
-					if ((pVBInfo->VBType & VB_XGI301C))
-						tempax ^= (HiTVSense | YPbPrSense);
-				}
-
-				if (!(tempax & (HiTVSense | YPbPrSense))) { /* start */
-
-					tempbx = *pVBInfo->pYCSenseData;
-
-					if (!(XGINew_Is301B(pVBInfo)))
-						tempbx = *pVBInfo->pYCSenseData2;
-
-					tempcx = 0x0604;
-					if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
-						if (XGINew_Sense(tempbx, tempcx, pVBInfo))
-							tempax |= SVIDEOSense;
-					}
-
-					if (OutputSelect & BoardTVType) {
-						tempbx = *pVBInfo->pVideoSenseData;
-
-						if (!(XGINew_Is301B(pVBInfo)))
-							tempbx = *pVBInfo->pVideoSenseData2;
-
-						tempcx = 0x0804;
-						if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
-							if (XGINew_Sense(tempbx, tempcx, pVBInfo))
-								tempax |= AVIDEOSense;
-						}
-					} else {
-						if (!(tempax & SVIDEOSense)) {
-							tempbx = *pVBInfo->pVideoSenseData;
-
-							if (!(XGINew_Is301B(pVBInfo)))
-								tempbx = *pVBInfo->pVideoSenseData2;
-
-							tempcx = 0x0804;
-							if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
-								if (XGINew_Sense(tempbx, tempcx, pVBInfo))
-									tempax |= AVIDEOSense;
-							}
-						}
-					}
-				}
-			} /* end */
-			if (!(tempax & Monitor2Sense)) {
-				if (XGINew_SenseLCD(HwDeviceExtension, pVBInfo))
-					tempax |= LCDSense;
-			}
-			tempbx = 0;
-			tempcx = 0;
-			XGINew_Sense(tempbx, tempcx, pVBInfo);
-
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, ~0xDF, tempax);
-			XGINew_SetReg1(pVBInfo->Part2Port, 0x00, P2reg0);
-
-			if (!(P2reg0 & 0x20)) {
-				pVBInfo->VBInfo = DisableCRT2Display;
-				/* XGI_SetCRT2Group301(SenseModeNo, HwDeviceExtension, pVBInfo); */
-			}
-		}
-	}
-	XGI_DisableBridge(HwDeviceExtension, pVBInfo); /* shampoo 0226 */
-
-}
-
-unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
-{
-	/* unsigned short SoftSetting ; */
-	unsigned short temp;
-
-	if ((HwDeviceExtension->jChipType >= XG20) || (HwDeviceExtension->jChipType >= XG40))
-		temp = 0;
-	else
-		temp = XGINew_GetPanelID(pVBInfo);
-
-	if (!temp)
-		temp = XGINew_GetLCDDDCInfo(HwDeviceExtension, pVBInfo);
-
-	return temp;
-}
-
-unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+static unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
 {
 	unsigned short temp;
 
@@ -474,12 +87,12 @@ unsigned char XGINew_GetLCDDDCInfo(struct xgi_hw_device_info *HwDeviceExtension,
 		default:
 			break;
 		}
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x36, 0xF0, temp);
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x36, 0xF0, temp);
 		return 1;
 	}
 }
 
-unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
+static unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
 {
 	unsigned short PanelTypeTable[16] = { SyncNN | PanelRGB18Bit
 			| Panel800x600  | _PanelType00, SyncNN | PanelRGB18Bit
@@ -501,7 +114,7 @@ unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
 	unsigned short tempax, tempbx, temp;
 	/* unsigned short return_flag; */
 
-	tempax = XGINew_GetReg1(pVBInfo->P3c4, 0x1A);
+	tempax = xgifb_reg_get(pVBInfo->P3c4, 0x1A);
 	tempbx = tempax & 0x1E;
 
 	if (tempax == 0)
@@ -511,7 +124,7 @@ unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
 		if (!(tempax & 0x10)) {
 			if (pVBInfo->IF_DEF_LVDS == 1) {
 				tempbx = 0;
-				temp = XGINew_GetReg1(pVBInfo->P3c4, 0x38);
+				temp = xgifb_reg_get(pVBInfo->P3c4, 0x38);
 				if (temp & 0x40)
 					tempbx |= 0x08;
 				if (temp & 0x20)
@@ -519,7 +132,7 @@ unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
 				if (temp & 0x01)
 					tempbx |= 0x01;
 
-				temp = XGINew_GetReg1(pVBInfo->P3c4, 0x39);
+				temp = xgifb_reg_get(pVBInfo->P3c4, 0x39);
 				if (temp & 0x80)
 					tempbx |= 0x04;
 			 } else {
@@ -530,23 +143,23 @@ unsigned char XGINew_GetPanelID(struct vb_device_info *pVBInfo)
 
 		tempbx = tempbx >> 1;
 		temp = tempbx & 0x00F;
-		XGINew_SetReg1(pVBInfo->P3d4, 0x36, temp);
+		xgifb_reg_set(pVBInfo->P3d4, 0x36, temp);
 		tempbx--;
 		tempbx = PanelTypeTable[tempbx];
 
 		temp = (tempbx & 0xFF00) >> 8;
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x37, ~(LCDSyncBit
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~(LCDSyncBit
 				| LCDRGB18Bit), temp);
 		return 1;
 	}
 }
 
-unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+static unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
 {
 	unsigned short flag;
 
 	if (XGI_BridgeIsOn(pVBInfo) == 0) {
-		flag = XGINew_GetReg1(pVBInfo->Part1Port, 0x0);
+		flag = xgifb_reg_get(pVBInfo->Part1Port, 0x0);
 
 		if (flag & 0x050)
 			return 1;
@@ -557,7 +170,7 @@ unsigned char XGINew_BridgeIsEnable(struct xgi_hw_device_info *HwDeviceExtension
 	return 0;
 }
 
-unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
+static unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx, tempcx, temp, i, tempch;
 
@@ -566,16 +179,16 @@ unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, str
 	tempcx = 0x0604;
 
 	temp = tempbx & 0xFF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x11, temp);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
 	temp = (tempbx & 0xFF00) >> 8;
 	temp |= (tempcx & 0x00FF);
-	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
+	xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
 
 	for (i = 0; i < 10; i++)
 		XGI_LongWait(pVBInfo);
 
 	tempch = (tempcx & 0xFF00) >> 8;
-	temp = XGINew_GetReg1(pVBInfo->Part4Port, 0x03);
+	temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
 	temp = temp ^ (0x0E);
 	temp &= tempch;
 
@@ -586,16 +199,16 @@ unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, str
 
 	tempcx = 0x0804;
 	temp = tempbx & 0xFF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x11, temp);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
 	temp = (tempbx & 0xFF00) >> 8;
 	temp |= (tempcx & 0x00FF);
-	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
+	xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
 
 	for (i = 0; i < 10; i++)
 		XGI_LongWait(pVBInfo);
 
 	tempch = (tempcx & 0xFF00) >> 8;
-	temp = XGINew_GetReg1(pVBInfo->Part4Port, 0x03);
+	temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
 	temp = temp ^ (0x0E);
 	temp &= tempch;
 
@@ -605,16 +218,16 @@ unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, str
 		tempbx = 0x3FF;
 		tempcx = 0x0804;
 		temp = tempbx & 0xFF;
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x11, temp);
+		xgifb_reg_set(pVBInfo->Part4Port, 0x11, temp);
 		temp = (tempbx & 0xFF00) >> 8;
 		temp |= (tempcx & 0x00FF);
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
+		xgifb_reg_and_or(pVBInfo->Part4Port, 0x10, ~0x1F, temp);
 
 		for (i = 0; i < 10; i++)
 			XGI_LongWait(pVBInfo);
 
 		tempch = (tempcx & 0xFF00) >> 8;
-		temp = XGINew_GetReg1(pVBInfo->Part4Port, 0x03);
+		temp = xgifb_reg_get(pVBInfo->Part4Port, 0x03);
 		temp = temp ^ (0x0E);
 		temp &= tempch;
 
@@ -625,233 +238,152 @@ unsigned char XGINew_SenseHiTV(struct xgi_hw_device_info *HwDeviceExtension, str
 	}
 }
 
-/* ----------------------------------------------------------------------------
- *       Description: Get Panel support
- *	O/P	   :
- *            BL: Panel ID=81h for no scaler LVDS
- *		     BH: Panel enhanced Mode Count
- *		     CX: Panel H. resolution
- *		     DX: PAnel V. resolution
- * ----------------------------------------------------------------------------
- */
-static void XGI_XG21Fun14Sub70(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
+void XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
 {
-	unsigned short ModeIdIndex;
-	unsigned short ModeNo;
-
-	unsigned short EModeCount;
-	unsigned short lvdstableindex;
-
-	lvdstableindex = XGI_GetLVDSOEMTableIndex(pVBInfo);
-	pBiosArguments->h.bl = 0x81;
-	pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHDE;
-	pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
-	EModeCount = 0;
-
-	pBiosArguments->x.ax = 0x0014;
-	for (ModeIdIndex = 0;; ModeIdIndex++) {
-		ModeNo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeID;
-		if (pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeID == 0xFF) {
-			pBiosArguments->h.bh = (unsigned char) EModeCount;
-			return;
+	unsigned short tempax = 0, tempbx, tempcx, temp, P2reg0 = 0, SenseModeNo = 0,
+			OutputSelect = *pVBInfo->pOutputSelect, ModeIdIndex, i;
+	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
+
+	if (pVBInfo->IF_DEF_LVDS == 1) {
+		tempax = xgifb_reg_get(pVBInfo->P3c4, 0x1A); /* ynlai 02/27/2002 */
+		tempbx = xgifb_reg_get(pVBInfo->P3c4, 0x1B);
+		tempax = ((tempax & 0xFE) >> 1) | (tempbx << 8);
+		if (tempax == 0x00) { /* Get Panel id from DDC */
+			temp = XGINew_GetLCDDDCInfo(HwDeviceExtension, pVBInfo);
+			if (temp == 1) { /* LCD connect */
+				xgifb_reg_and_or(pVBInfo->P3d4, 0x39, 0xFF, 0x01); /* set CR39 bit0="1" */
+				xgifb_reg_and_or(pVBInfo->P3d4, 0x37, 0xEF, 0x00); /* clean CR37 bit4="0" */
+				temp = LCDSense;
+			} else { /* LCD don't connect */
+				temp = 0;
+			}
+		} else {
+			XGINew_GetPanelID(pVBInfo);
+			temp = LCDSense;
 		}
-		if (!XGI_XG21CheckLVDSMode(ModeNo, ModeIdIndex, pVBInfo))
-			continue;
 
-		EModeCount++;
-	}
-}
+		tempbx = ~(LCDSense | AVIDEOSense | SVIDEOSense);
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, tempbx, temp);
+	} else { /* for 301 */
+		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { /* for HiVision */
+			tempax = xgifb_reg_get(pVBInfo->P3c4, 0x38);
+			temp = tempax & 0x01;
+			tempax = xgifb_reg_get(pVBInfo->P3c4, 0x3A);
+			temp = temp | (tempax & 0x02);
+			xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xA0, temp);
+		} else {
+			if (XGI_BridgeIsOn(pVBInfo)) {
+				P2reg0 = xgifb_reg_get(pVBInfo->Part2Port, 0x00);
+				if (!XGINew_BridgeIsEnable(HwDeviceExtension, pVBInfo)) {
+					SenseModeNo = 0x2e;
+					/* xgifb_reg_set(pVBInfo->P3d4, 0x30, 0x41); */
+					/* XGISetModeNew(HwDeviceExtension, 0x2e); // ynlai InitMode */
 
-/* ----------------------------------------------------------------------------
- *
- *       Description: Get Panel mode ID for enhanced mode
- *	I/P	   : BH: EModeIndex ( which < Panel enhanced Mode Count )
- *	O/P	   :
- *            BL: Mode ID
- *		     CX: H. resolution of the assigned by the index
- *		     DX: V. resolution of the assigned by the index
- *
- * ----------------------------------------------------------------------------
- */
-
-static void XGI_XG21Fun14Sub71(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
-{
+					temp = XGI_SearchModeID(SenseModeNo, &ModeIdIndex, pVBInfo);
+					XGI_GetVGAType(HwDeviceExtension, pVBInfo);
+					XGI_GetVBType(pVBInfo);
+					pVBInfo->SetFlag = 0x00;
+					pVBInfo->ModeType = ModeVGA;
+					pVBInfo->VBInfo = SetCRT2ToRAMDAC | LoadDACFlag | SetInSlaveMode;
+					XGI_GetLCDInfo(0x2e, ModeIdIndex, pVBInfo);
+					XGI_GetTVInfo(0x2e, ModeIdIndex, pVBInfo);
+					XGI_EnableBridge(HwDeviceExtension, pVBInfo);
+					XGI_SetCRT2Group301(SenseModeNo, HwDeviceExtension, pVBInfo);
+					XGI_SetCRT2ModeRegs(0x2e, HwDeviceExtension, pVBInfo);
+					/* XGI_DisableBridge( HwDeviceExtension, pVBInfo ) ; */
+					xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x20); /* Display Off 0212 */
+					for (i = 0; i < 20; i++)
+						XGI_LongWait(pVBInfo);
+				}
+				xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1c);
+				tempax = 0;
+				tempbx = *pVBInfo->pRGBSenseData;
 
-	unsigned short EModeCount;
-	unsigned short ModeIdIndex, resindex;
-	unsigned short ModeNo;
-	unsigned short EModeIndex = pBiosArguments->h.bh;
-
-	EModeCount = 0;
-	for (ModeIdIndex = 0;; ModeIdIndex++) {
-		ModeNo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeID;
-		if (pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeID == 0xFF) {
-			pBiosArguments->x.ax = 0x0114;
-			return;
-		}
-		if (!XGI_XG21CheckLVDSMode(ModeNo, ModeIdIndex, pVBInfo))
-			continue;
-
-		if (EModeCount == EModeIndex) {
-			resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
-			pBiosArguments->h.bl = (unsigned char) ModeNo;
-			pBiosArguments->x.cx = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
-			pBiosArguments->x.dx = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
-			pBiosArguments->x.ax = 0x0014;
-		}
-		EModeCount++;
+				if (!(XGINew_Is301B(pVBInfo)))
+					tempbx = *pVBInfo->pRGBSenseData2;
 
-	}
+				tempcx = 0x0E08;
+				if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
+					if (XGINew_Sense(tempbx, tempcx, pVBInfo))
+						tempax |= Monitor2Sense;
+				}
 
-}
+				if (pVBInfo->VBType & VB_XGI301C)
+					xgifb_reg_or(pVBInfo->Part4Port, 0x0d, 0x04);
 
-/* ----------------------------------------------------------------------------
- *
- *       Description: Validate Panel modes ID support
- *	I/P	   :
- *            BL: ModeID
- *	O/P	   :
- *		     CX: H. resolution of the assigned by the index
- *		     DX: V. resolution of the assigned by the index
- *
- * ----------------------------------------------------------------------------
- */
-static void XGI_XG21Fun14Sub72(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
-{
-	unsigned short ModeIdIndex, resindex;
-	unsigned short ModeNo;
-
-	ModeNo = pBiosArguments->h.bl;
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
-	if (!XGI_XG21CheckLVDSMode(ModeNo, ModeIdIndex, pVBInfo)) {
-		pBiosArguments->x.cx = 0;
-		pBiosArguments->x.dx = 0;
-		pBiosArguments->x.ax = 0x0114;
-		return;
-	}
-	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
-	if (ModeNo <= 0x13) {
-		pBiosArguments->x.cx = pVBInfo->StResInfo[resindex].HTotal;
-		pBiosArguments->x.dx = pVBInfo->StResInfo[resindex].VTotal;
-	} else {
-		pBiosArguments->x.cx = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
-		pBiosArguments->x.dx = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
-	}
+				if (XGINew_SenseHiTV(HwDeviceExtension, pVBInfo)) { /* add by kuku for Multi-adapter sense HiTV */
+					tempax |= HiTVSense;
+					if ((pVBInfo->VBType & VB_XGI301C))
+						tempax ^= (HiTVSense | YPbPrSense);
+				}
 
-	pBiosArguments->x.ax = 0x0014;
+				if (!(tempax & (HiTVSense | YPbPrSense))) { /* start */
 
-}
+					tempbx = *pVBInfo->pYCSenseData;
 
-/* ----------------------------------------------------------------------------
- *
- *	Description: Get Customized Panel misc. information support
- *	I/P	   : Select
- *		     to get panel horizontal timing
- *			 to get panel vertical timing
- *			 to get channel clock parameter
- *            to get panel misc information
- *
- *	O/P	   :
- *		     BL: for input Select = 0 ;
- *                       BX: *Value1 = Horizontal total
- *                       CX: *Value2 = Horizontal front porch
- *                       DX: *Value2 = Horizontal sync width
- *		     BL: for input Select = 1 ;
- *                       BX: *Value1 = Vertical total
- *                       CX: *Value2 = Vertical front porch
- *                       DX: *Value2 = Vertical sync width
- *            BL: for input Select = 2 ;
- *                       BX: Value1 = The first CLK parameter
- *                       CX: Value2 = The second CLK parameter
- *		     BL: for input Select = 4 ;
- *                       BX[15]: *Value1 D[15] VESA V. Polarity
- *                       BX[14]: *Value1 D[14] VESA H. Polarity
- *                       BX[7]: *Value1 D[7] Panel V. Polarity
- *                       BX[6]: *Value1 D[6] Panel H. Polarity
- * ----------------------------------------------------------------------------
- */
-static void XGI_XG21Fun14Sub73(struct vb_device_info *pVBInfo, PX86_REGS pBiosArguments)
-{
-	unsigned char Select;
-
-	unsigned short lvdstableindex;
-
-	lvdstableindex = XGI_GetLVDSOEMTableIndex(pVBInfo);
-	Select = pBiosArguments->h.bl;
-
-	switch (Select) {
-	case 0:
-		pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHT;
-		pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHFP;
-		pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSHSYNC;
-		break;
-	case 1:
-		pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVT;
-		pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVFP;
-		pBiosArguments->x.dx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVSYNC;
-		break;
-	case 2:
-		pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1;
-		pBiosArguments->x.cx = pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2;
-		break;
-	case 4:
-		pBiosArguments->x.bx = pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability;
-		break;
+					if (!(XGINew_Is301B(pVBInfo)))
+						tempbx = *pVBInfo->pYCSenseData2;
+
+					tempcx = 0x0604;
+					if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
+						if (XGINew_Sense(tempbx, tempcx, pVBInfo))
+							tempax |= SVIDEOSense;
+					}
+
+					if (OutputSelect & BoardTVType) {
+						tempbx = *pVBInfo->pVideoSenseData;
+
+						if (!(XGINew_Is301B(pVBInfo)))
+							tempbx = *pVBInfo->pVideoSenseData2;
+
+						tempcx = 0x0804;
+						if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
+							if (XGINew_Sense(tempbx, tempcx, pVBInfo))
+								tempax |= AVIDEOSense;
+						}
+					} else {
+						if (!(tempax & SVIDEOSense)) {
+							tempbx = *pVBInfo->pVideoSenseData;
+
+							if (!(XGINew_Is301B(pVBInfo)))
+								tempbx = *pVBInfo->pVideoSenseData2;
+
+							tempcx = 0x0804;
+							if (XGINew_Sense(tempbx, tempcx, pVBInfo)) {
+								if (XGINew_Sense(tempbx, tempcx, pVBInfo))
+									tempax |= AVIDEOSense;
+							}
+						}
+					}
+				}
+			} /* end */
+			if (!(tempax & Monitor2Sense)) {
+				if (XGINew_SenseLCD(HwDeviceExtension, pVBInfo))
+					tempax |= LCDSense;
+			}
+			tempbx = 0;
+			tempcx = 0;
+			XGINew_Sense(tempbx, tempcx, pVBInfo);
+
+			xgifb_reg_and_or(pVBInfo->P3d4, 0x32, ~0xDF, tempax);
+			xgifb_reg_set(pVBInfo->Part2Port, 0x00, P2reg0);
+
+			if (!(P2reg0 & 0x20)) {
+				pVBInfo->VBInfo = DisableCRT2Display;
+				/* XGI_SetCRT2Group301(SenseModeNo, HwDeviceExtension, pVBInfo); */
+			}
+		}
 	}
+	XGI_DisableBridge(HwDeviceExtension, pVBInfo); /* shampoo 0226 */
 
-	pBiosArguments->x.ax = 0x0014;
 }
 
-void XGI_XG21Fun14(struct xgi_hw_device_info *pXGIHWDE, PX86_REGS pBiosArguments)
+unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo)
 {
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-
-	pVBInfo->IF_DEF_LVDS = 0;
-	pVBInfo->IF_DEF_CH7005 = 0;
-	pVBInfo->IF_DEF_HiVision = 1;
-	pVBInfo->IF_DEF_LCDA = 1;
-	pVBInfo->IF_DEF_CH7017 = 0;
-	pVBInfo->IF_DEF_YPbPr = 1;
-	pVBInfo->IF_DEF_CRT2Monitor = 0;
-	pVBInfo->IF_DEF_VideoCapture = 0;
-	pVBInfo->IF_DEF_ScaleLCD = 0;
-	pVBInfo->IF_DEF_OEMUtil = 0;
-	pVBInfo->IF_DEF_PWD = 0;
-
-	InitTo330Pointer(pXGIHWDE->jChipType, pVBInfo);
-	ReadVBIOSTablData(pXGIHWDE->jChipType, pVBInfo);
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-
-	switch (pBiosArguments->x.ax) {
-	case 0x1470:
-		XGI_XG21Fun14Sub70(pVBInfo, pBiosArguments);
-		break;
-	case 0x1471:
-		XGI_XG21Fun14Sub71(pVBInfo, pBiosArguments);
-		break;
-	case 0x1472:
-		XGI_XG21Fun14Sub72(pVBInfo, pBiosArguments);
-		break;
-	case 0x1473:
-		XGI_XG21Fun14Sub73(pVBInfo, pBiosArguments);
-		break;
-	}
+	/* unsigned short SoftSetting ; */
+	unsigned short temp;
+
+	temp = XGINew_GetLCDDDCInfo(HwDeviceExtension, pVBInfo);
+
+	return temp;
 }
diff --git a/drivers/staging/xgifb/vb_ext.h b/drivers/staging/xgifb/vb_ext.h
index 5cc4d12..cabe365 100644
--- a/drivers/staging/xgifb/vb_ext.h
+++ b/drivers/staging/xgifb/vb_ext.h
@@ -21,13 +21,7 @@ typedef union   _X86_REGS    {
     struct  BYTEREGS h;
 } X86_REGS, *PX86_REGS;
 
-extern   void     XGI_XG21Fun14(struct xgi_hw_device_info *pXGIHWDE, PX86_REGS pBiosArguments);
-extern void XGISetDPMS(struct xgi_hw_device_info *pXGIHWDE,
-		       unsigned long VESA_POWER_STATE);
 extern   void     XGI_GetSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-extern   void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
-extern void ReadVBIOSTablData(unsigned char ChipType,
-			      struct vb_device_info *pVBInfo);
 extern unsigned short XGINew_SenseLCD(struct xgi_hw_device_info *,
 				      struct vb_device_info *pVBInfo);
 
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 8d59182..61d1370 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -17,38 +17,6 @@
 
 static unsigned char XGINew_ChannelAB, XGINew_DataBusWidth;
 
-unsigned short XGINew_DRAMType[17][5] = {
-	{0x0C, 0x0A, 0x02, 0x40, 0x39}, {0x0D, 0x0A, 0x01, 0x40, 0x48},
-	{0x0C, 0x09, 0x02, 0x20, 0x35}, {0x0D, 0x09, 0x01, 0x20, 0x44},
-	{0x0C, 0x08, 0x02, 0x10, 0x31}, {0x0D, 0x08, 0x01, 0x10, 0x40},
-	{0x0C, 0x0A, 0x01, 0x20, 0x34}, {0x0C, 0x09, 0x01, 0x08, 0x32},
-	{0x0B, 0x08, 0x02, 0x08, 0x21}, {0x0C, 0x08, 0x01, 0x08, 0x30},
-	{0x0A, 0x08, 0x02, 0x04, 0x11}, {0x0B, 0x0A, 0x01, 0x10, 0x28},
-	{0x09, 0x08, 0x02, 0x02, 0x01}, {0x0B, 0x09, 0x01, 0x08, 0x24},
-	{0x0B, 0x08, 0x01, 0x04, 0x20}, {0x0A, 0x08, 0x01, 0x02, 0x10},
-	{0x09, 0x08, 0x01, 0x01, 0x00} };
-
-static unsigned short XGINew_SDRDRAM_TYPE[13][5] = {
-	{ 2, 12, 9, 64, 0x35},
-	{ 1, 13, 9, 64, 0x44},
-	{ 2, 12, 8, 32, 0x31},
-	{ 2, 11, 9, 32, 0x25},
-	{ 1, 12, 9, 32, 0x34},
-	{ 1, 13, 8, 32, 0x40},
-	{ 2, 11, 8, 16, 0x21},
-	{ 1, 12, 8, 16, 0x30},
-	{ 1, 11, 9, 16, 0x24},
-	{ 1, 11, 8,  8, 0x20},
-	{ 2,  9, 8,  4, 0x01},
-	{ 1, 10, 8,  4, 0x10},
-	{ 1,  9, 8,  2, 0x00} };
-
-static unsigned short XGINew_DDRDRAM_TYPE[4][5] = {
-	{ 2, 12, 9, 64, 0x35},
-	{ 2, 12, 8, 32, 0x31},
-	{ 2, 11, 8, 16, 0x21},
-	{ 2,  9, 8,  4, 0x01} };
-
 static unsigned short XGINew_DDRDRAM_TYPE340[4][5] = {
 	{ 2, 13, 9, 64, 0x45},
 	{ 2, 12, 9, 32, 0x35},
@@ -69,430 +37,9 @@ static unsigned short XGINew_DDRDRAM_TYPE20[12][5] = {
 	{ 2, 12,  9,  8, 0x35},
 	{ 2, 12,  8,  4, 0x31} };
 
-void     XGINew_SetDRAMSize_340(struct xgi_hw_device_info *, struct vb_device_info *);
-void     XGINew_SetDRAMSize_310(struct xgi_hw_device_info *, struct vb_device_info *);
-void     XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
-void     XGINew_SetDRAMModeRegister(struct vb_device_info *);
-void     XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension);
-void XGINew_SetDRAMDefaultRegister340(struct xgi_hw_device_info *HwDeviceExtension,
-				      unsigned long, struct vb_device_info *);
-unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
-				     struct vb_device_info *pVBInfo);
-unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension);
-
-int      XGINew_DDRSizing340(struct xgi_hw_device_info *, struct vb_device_info *);
-void     XGINew_DisableRefresh(struct xgi_hw_device_info *, struct vb_device_info *) ;
-void     XGINew_CheckBusWidth_310(struct vb_device_info *) ;
-int      XGINew_SDRSizing(struct vb_device_info *);
-int      XGINew_DDRSizing(struct vb_device_info *);
-void     XGINew_EnableRefresh(struct xgi_hw_device_info *, struct vb_device_info *);
-static int      XGINew_RAMType;		/*int      ModeIDOffset,StandTable,CRT1Table,ScreenOffset,REFIndex;*/
-#if 0
-static unsigned long	 UNIROM;
-#endif
-unsigned char  ChkLFB(struct vb_device_info *);
-void     XGINew_Delay15us(unsigned long);
-void     SetPowerConsume(struct xgi_hw_device_info *HwDeviceExtension,
-			 unsigned long XGI_P3d4Port);
-void     ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo);
-void     XGINew_DDR1x_MRS_XG20(unsigned long P3c4, struct vb_device_info *pVBInfo);
-void     XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtension);
-void     XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension);
-void     XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
-void     XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
-void     XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
-unsigned char    GetXG21FPBits(struct vb_device_info *pVBInfo);
-void     XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo) ;
-unsigned char    GetXG27FPBits(struct vb_device_info *pVBInfo);
-
-static void DelayUS(unsigned long MicroSeconds)
-{
-	udelay(MicroSeconds);
-}
-
-unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
-{
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	unsigned char i, temp = 0, temp1;
-	/* VBIOSVersion[5]; */
-	volatile unsigned char *pVideoMemory;
-
-	/* unsigned long j, k; */
-
-	struct XGI_DSReg *pSR;
-
-	unsigned long Temp;
-
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-
-	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-
-	pVideoMemory = (unsigned char *) pVBInfo->ROMAddr;
-
-	/* Newdebugcode(0x99); */
-
-
-	/* if (pVBInfo->ROMAddr == 0) */
-	/* return(0); */
-
-	if (pVBInfo->FBAddr == NULL) {
-		printk("\n pVBInfo->FBAddr == 0 ");
-		return 0;
-	}
-	printk("1");
-	if (pVBInfo->BaseAddr == 0) {
-		printk("\npVBInfo->BaseAddr == 0 ");
-		return 0;
-	}
-	printk("2");
-
-	XGINew_SetReg3((pVBInfo->BaseAddr + 0x12), 0x67); /* 3c2 <- 67 ,ynlai */
-
-	pVBInfo->ISXPDOS = 0;
-	printk("3");
-
-	if (!HwDeviceExtension->bIntegratedMMEnabled)
-		return 0; /* alan */
-
-	printk("4");
-
-	/* VBIOSVersion[4] = 0x0; */
-
-	/* 09/07/99 modify by domao */
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-	printk("5");
-
-	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */
-		XGI_GetVBType(pVBInfo); /* Run XGI_GetVBType before InitTo330Pointer */
-
-	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-
-	/* ReadVBIOSData */
-	ReadVBIOSTablData(HwDeviceExtension->jChipType, pVBInfo);
-
-	/* 1.Openkey */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x05, 0x86);
-	printk("6");
-
-	/* GetXG21Sense (GPIO) */
-	if (HwDeviceExtension->jChipType == XG21)
-		XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo);
-
-	if (HwDeviceExtension->jChipType == XG27)
-		XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo);
-
-	printk("7");
-
-	/* 2.Reset Extended register */
-
-	for (i = 0x06; i < 0x20; i++)
-		XGINew_SetReg1(pVBInfo->P3c4, i, 0);
-
-	for (i = 0x21; i <= 0x27; i++)
-		XGINew_SetReg1(pVBInfo->P3c4, i, 0);
-
-	/* for(i = 0x06; i <= 0x27; i++) */
-	/* XGINew_SetReg1(pVBInfo->P3c4, i, 0); */
-
-	printk("8");
-
-	if ((HwDeviceExtension->jChipType >= XG20) || (HwDeviceExtension->jChipType >= XG40)) {
-		for (i = 0x31; i <= 0x3B; i++)
-			XGINew_SetReg1(pVBInfo->P3c4, i, 0);
-	} else {
-		for (i = 0x31; i <= 0x3D; i++)
-			XGINew_SetReg1(pVBInfo->P3c4, i, 0);
-	}
-	printk("9");
-
-	if (HwDeviceExtension->jChipType == XG42) /* [Hsuan] 2004/08/20 Auto over driver for XG42 */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x3B, 0xC0);
-
-	/* for (i = 0x30; i <= 0x3F; i++) */
-	/* XGINew_SetReg1(pVBInfo->P3d4, i, 0); */
-
-	for (i = 0x79; i <= 0x7C; i++)
-		XGINew_SetReg1(pVBInfo->P3d4, i, 0); /* shampoo 0208 */
-
-	printk("10");
-
-	if (HwDeviceExtension->jChipType >= XG20)
-		XGINew_SetReg1(pVBInfo->P3d4, 0x97, *pVBInfo->pXGINew_CR97);
-
-	/* 3.SetMemoryClock
-
-	 if (HwDeviceExtension->jChipType >= XG40)
-	 XGINew_RAMType = (int)XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-
-	 if (HwDeviceExtension->jChipType < XG40)
-	 XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);  */
-
-	printk("11");
-
-	/* 4.SetDefExt1Regs begin */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x07, *pVBInfo->pSR07);
-	if (HwDeviceExtension->jChipType == XG27) {
-		XGINew_SetReg1(pVBInfo->P3c4, 0x40, *pVBInfo->pSR40);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x41, *pVBInfo->pSR41);
-	}
-	XGINew_SetReg1(pVBInfo->P3c4, 0x11, 0x0F);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1F, *pVBInfo->pSR1F);
-	/* XGINew_SetReg1(pVBInfo->P3c4, 0x20, 0x20); */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x20, 0xA0); /* alan, 2001/6/26 Frame buffer can read/write SR20 */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x36, 0x70); /* Hsuan, 2006/01/01 H/W request for slow corner chip */
-	if (HwDeviceExtension->jChipType == XG27) /* Alan 12/07/2006 */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x36, *pVBInfo->pSR36);
-
-	/* SR11 = 0x0F; */
-	/* XGINew_SetReg1(pVBInfo->P3c4, 0x11, SR11); */
-
-	printk("12");
-
-	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
-		/* Set AGP Rate */
-		/*
-		temp1 = XGINew_GetReg1(pVBInfo->P3c4, 0x3B);
-		temp1 &= 0x02;
-		if (temp1 == 0x02) {
-			XGINew_SetReg4(0xcf8, 0x80000000);
-			ChipsetID = XGINew_GetReg3(0x0cfc);
-			XGINew_SetReg4(0xcf8, 0x8000002C);
-			VendorID = XGINew_GetReg3(0x0cfc);
-			VendorID &= 0x0000FFFF;
-			XGINew_SetReg4(0xcf8, 0x8001002C);
-			GraphicVendorID = XGINew_GetReg3(0x0cfc);
-			GraphicVendorID &= 0x0000FFFF;
-
-			if (ChipsetID == 0x7301039)
-				XGINew_SetReg1(pVBInfo->P3d4, 0x5F, 0x09);
-
-			ChipsetID &= 0x0000FFFF;
-
-			if ((ChipsetID == 0x700E) || (ChipsetID == 0x1022) || (ChipsetID == 0x1106) || (ChipsetID == 0x10DE)) {
-				if (ChipsetID == 0x1106) {
-					if ((VendorID == 0x1019) && (GraphicVendorID == 0x1019))
-						XGINew_SetReg1(pVBInfo->P3d4, 0x5F, 0x0D);
-					else
-						XGINew_SetReg1(pVBInfo->P3d4, 0x5F, 0x0B);
-				} else {
-					XGINew_SetReg1(pVBInfo->P3d4, 0x5F, 0x0B);
-				}
-			}
-		}
-		*/
-
-		printk("13");
-
-		if (HwDeviceExtension->jChipType >= XG40) {
-			/* Set AGP customize registers (in SetDefAGPRegs) Start */
-			for (i = 0x47; i <= 0x4C; i++)
-				XGINew_SetReg1(pVBInfo->P3d4, i, pVBInfo->AGPReg[i - 0x47]);
-
-			for (i = 0x70; i <= 0x71; i++)
-				XGINew_SetReg1(pVBInfo->P3d4, i, pVBInfo->AGPReg[6 + i - 0x70]);
-
-			for (i = 0x74; i <= 0x77; i++)
-				XGINew_SetReg1(pVBInfo->P3d4, i, pVBInfo->AGPReg[8 + i - 0x74]);
-			/* Set AGP customize registers (in SetDefAGPRegs) End */
-			/* [Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */
-			/*        XGINew_SetReg4(0xcf8 , 0x80000000); */
-			/*        ChipsetID = XGINew_GetReg3(0x0cfc); */
-			/*        if (ChipsetID == 0x25308086) */
-			/*            XGINew_SetReg1(pVBInfo->P3d4, 0x77, 0xF0); */
-
-			HwDeviceExtension->pQueryVGAConfigSpace(HwDeviceExtension, 0x50, 0, &Temp); /* Get */
-			Temp >>= 20;
-			Temp &= 0xF;
-
-			if (Temp == 1)
-				XGINew_SetReg1(pVBInfo->P3d4, 0x48, 0x20); /* CR48 */
-		}
-		printk("14");
-
-		if (HwDeviceExtension->jChipType < XG40)
-			XGINew_SetReg1(pVBInfo->P3d4, 0x49, pVBInfo->CR49[0]);
-	} /* != XG20 */
-
-	/* Set PCI */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x23, *pVBInfo->pSR23);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x24, *pVBInfo->pSR24);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x25, pVBInfo->SR25[0]);
-	printk("15");
-
-	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
-		/* Set VB */
-		XGI_UnLockCRT2(HwDeviceExtension, pVBInfo);
-		XGINew_SetRegANDOR(pVBInfo->Part0Port, 0x3F, 0xEF, 0x00); /* alan, disable VideoCapture */
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x00, 0x00);
-		temp1 = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x7B); /* chk if BCLK>=100MHz */
-		temp = (unsigned char) ((temp1 >> 4) & 0x0F);
-
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x02, (*pVBInfo->pCRT2Data_1_2));
-
-		printk("16");
-
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x2E, 0x08); /* use VB */
-	} /* != XG20 */
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x27, 0x1F);
-
-	if ((HwDeviceExtension->jChipType == XG42)
-			&& XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) != 0) { /* Not DDR */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x31, (*pVBInfo->pSR31 & 0x3F) | 0x40);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x32, (*pVBInfo->pSR32 & 0xFC) | 0x01);
-	} else {
-		XGINew_SetReg1(pVBInfo->P3c4, 0x31, *pVBInfo->pSR31);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x32, *pVBInfo->pSR32);
-	}
-	XGINew_SetReg1(pVBInfo->P3c4, 0x33, *pVBInfo->pSR33);
-	printk("17");
-
-	/*
-	 if (HwDeviceExtension->jChipType >= XG40)
-	 SetPowerConsume (HwDeviceExtension, pVBInfo->P3c4);	*/
-
-	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
-		if (XGI_BridgeIsOn(pVBInfo) == 1) {
-			if (pVBInfo->IF_DEF_LVDS == 0) {
-				XGINew_SetReg1(pVBInfo->Part2Port, 0x00, 0x1C);
-				XGINew_SetReg1(pVBInfo->Part4Port, 0x0D, *pVBInfo->pCRT2Data_4_D);
-				XGINew_SetReg1(pVBInfo->Part4Port, 0x0E, *pVBInfo->pCRT2Data_4_E);
-				XGINew_SetReg1(pVBInfo->Part4Port, 0x10, *pVBInfo->pCRT2Data_4_10);
-				XGINew_SetReg1(pVBInfo->Part4Port, 0x0F, 0x3F);
-			}
-
-			XGI_LockCRT2(HwDeviceExtension, pVBInfo);
-		}
-	} /* != XG20 */
-	printk("18");
-
-	if (HwDeviceExtension->jChipType < XG40)
-		XGINew_SetReg1(pVBInfo->P3d4, 0x83, 0x00);
-	printk("181");
-
-	if (HwDeviceExtension->bSkipSense == 0) {
-		printk("182");
-
-		XGI_SenseCRT1(pVBInfo);
-
-		printk("183");
-		/* XGINew_DetectMonitor(HwDeviceExtension); */
-		pVBInfo->IF_DEF_CH7007 = 0;
-		if ((HwDeviceExtension->jChipType == XG21) && (pVBInfo->IF_DEF_CH7007)) {
-			printk("184");
-			XGI_GetSenseStatus(HwDeviceExtension, pVBInfo); /* sense CRT2 */
-			printk("185");
-
-		}
-		if (HwDeviceExtension->jChipType == XG21) {
-			printk("186");
-
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, ~Monitor1Sense, Monitor1Sense); /* Z9 default has CRT */
-			temp = GetXG21FPBits(pVBInfo);
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x37, ~0x01, temp);
-			printk("187");
-
-		}
-		if (HwDeviceExtension->jChipType == XG27) {
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, ~Monitor1Sense, Monitor1Sense); /* Z9 default has CRT */
-			temp = GetXG27FPBits(pVBInfo);
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x37, ~0x03, temp);
-		}
-	}
-	printk("19");
-
-	if (HwDeviceExtension->jChipType >= XG40) {
-		if (HwDeviceExtension->jChipType >= XG40)
-			XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-
-		XGINew_SetDRAMDefaultRegister340(HwDeviceExtension, pVBInfo->P3d4, pVBInfo);
-
-		if (HwDeviceExtension->bSkipDramSizing == 1) {
-			pSR = HwDeviceExtension->pSR;
-			if (pSR != NULL) {
-				while (pSR->jIdx != 0xFF) {
-					XGINew_SetReg1(pVBInfo->P3c4, pSR->jIdx, pSR->jVal);
-					pSR++;
-				}
-			}
-			/* XGINew_SetDRAMModeRegister340(pVBInfo); */
-		} /* SkipDramSizing */
-		else {
-			{
-				printk("20");
-				XGINew_SetDRAMSize_340(HwDeviceExtension, pVBInfo);
-			}
-			printk("21");
-
-		}
-	} /* XG40 */
-
-	printk("22");
-
-	/* SetDefExt2Regs begin */
-	/*
-	AGP = 1;
-	temp = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x3A);
-	temp &= 0x30;
-	if (temp == 0x30)
-		AGP = 0;
-
-	if (AGP == 0)
-		*pVBInfo->pSR21 &= 0xEF;
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x21, *pVBInfo->pSR21);
-	if (AGP == 1)
-		*pVBInfo->pSR22 &= 0x20;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x22, *pVBInfo->pSR22);
-	*/
-	/* base = 0x80000000; */
-	/* OutPortLong(0xcf8, base); */
-	/* Temp = (InPortLong(0xcfc) & 0xFFFF); */
-	/* if (Temp == 0x1039) { */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x22, (unsigned char) ((*pVBInfo->pSR22) & 0xFE));
-	/* } else { */
-	/*	XGINew_SetReg1(pVBInfo->P3c4, 0x22, *pVBInfo->pSR22); */
-	/* } */
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x21, *pVBInfo->pSR21);
-
-	printk("23");
-
-	XGINew_ChkSenseStatus(HwDeviceExtension, pVBInfo);
-	XGINew_SetModeScratch(HwDeviceExtension, pVBInfo);
-
-	printk("24");
-
-	XGINew_SetReg1(pVBInfo->P3d4, 0x8c, 0x87);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x31);
-	printk("25");
-
-	return 1;
-} /* end of init */
+static int XGINew_RAMType;
 
-/* ============== alan ====================== */
-
-unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
+static unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtension,
 					struct vb_device_info *pVBInfo)
 {
 	unsigned char data, temp;
@@ -502,10 +49,10 @@ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtensio
 			data = *pVBInfo->pSoftSetting & 0x07;
 			return data;
 		} else {
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x39) & 0x02;
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x39) & 0x02;
 
 			if (data == 0)
-				data = (XGINew_GetReg1(pVBInfo->P3c4, 0x3A) & 0x02) >> 1;
+				data = (xgifb_reg_get(pVBInfo->P3c4, 0x3A) & 0x02) >> 1;
 
 			return data;
 		}
@@ -514,7 +61,7 @@ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtensio
 			data = *pVBInfo->pSoftSetting & 0x07;
 			return data;
 		}
-		temp = XGINew_GetReg1(pVBInfo->P3c4, 0x3B);
+		temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
 
 		if ((temp & 0x88) == 0x80) /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
 			data = 0; /* DDR */
@@ -522,10 +69,10 @@ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtensio
 			data = 1; /* DDRII */
 		return data;
 	} else if (HwDeviceExtension->jChipType == XG21) {
-		XGINew_SetRegAND(pVBInfo->P3d4, 0xB4, ~0x02); /* Independent GPIO control */
-		DelayUS(800);
-		XGINew_SetRegOR(pVBInfo->P3d4, 0x4A, 0x80); /* Enable GPIOH read */
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48); /* GPIOF 0:DVI 1:DVO */
+		xgifb_reg_and(pVBInfo->P3d4, 0xB4, ~0x02); /* Independent GPIO control */
+		udelay(800);
+		xgifb_reg_or(pVBInfo->P3d4, 0x4A, 0x80); /* Enable GPIOH read */
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x48); /* GPIOF 0:DVI 1:DVO */
 		/* HOTPLUG_SUPPORT */
 		/* for current XG20 & XG21, GPIOH is floating, driver will fix DDR temporarily */
 		if (temp & 0x01) /* DVI read GPIOH */
@@ -533,10 +80,10 @@ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtensio
 		else
 			data = 0; /* DDR */
 		/* ~HOTPLUG_SUPPORT */
-		XGINew_SetRegOR(pVBInfo->P3d4, 0xB4, 0x02);
+		xgifb_reg_or(pVBInfo->P3d4, 0xB4, 0x02);
 		return data;
 	} else {
-		data = XGINew_GetReg1(pVBInfo->P3d4, 0x97) & 0x01;
+		data = xgifb_reg_get(pVBInfo->P3d4, 0x97) & 0x01;
 
 		if (data == 1)
 			data++;
@@ -545,91 +92,59 @@ unsigned char XGINew_GetXG20DRAMType(struct xgi_hw_device_info *HwDeviceExtensio
 	}
 }
 
-static unsigned char XGINew_Get310DRAMType(struct vb_device_info *pVBInfo)
+static void XGINew_DDR1x_MRS_340(unsigned long P3c4, struct vb_device_info *pVBInfo)
 {
-	unsigned char data;
+	xgifb_reg_set(P3c4, 0x18, 0x01);
+	xgifb_reg_set(P3c4, 0x19, 0x20);
+	xgifb_reg_set(P3c4, 0x16, 0x00);
+	xgifb_reg_set(P3c4, 0x16, 0x80);
 
-	/* index = XGINew_GetReg1(pVBInfo->P3c4, 0x1A); */
-	/* index &= 07; */
+	if (*pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C) { /* Samsung F Die */
+		mdelay(3);
+		xgifb_reg_set(P3c4, 0x18, 0x00);
+		xgifb_reg_set(P3c4, 0x19, 0x20);
+		xgifb_reg_set(P3c4, 0x16, 0x00);
+		xgifb_reg_set(P3c4, 0x16, 0x80);
+	}
 
-	if (*pVBInfo->pSoftSetting & SoftDRAMType)
-		data = *pVBInfo->pSoftSetting & 0x03;
-	else
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x3a) & 0x03;
-
-	return data;
+	udelay(60);
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x19, 0x01);
+	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[0]);
+	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[1]);
+	mdelay(1);
+	xgifb_reg_set(P3c4, 0x1B, 0x03);
+	udelay(500);
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x19, 0x00);
+	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[2]);
+	xgifb_reg_set(P3c4, 0x16, pVBInfo->SR16[3]);
+	xgifb_reg_set(P3c4, 0x1B, 0x00);
 }
 
-/*
-void XGINew_Delay15us(unsigned long ulMicrsoSec)
+static void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
 {
-}
-*/
 
-static void XGINew_SDR_MRS(struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
+	xgifb_reg_set(pVBInfo->P3c4, 0x28, pVBInfo->MCLKData[XGINew_RAMType].SR28);
+	xgifb_reg_set(pVBInfo->P3c4, 0x29, pVBInfo->MCLKData[XGINew_RAMType].SR29);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2A, pVBInfo->MCLKData[XGINew_RAMType].SR2A);
 
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x16);
-	data &= 0x3F; /* SR16 D7=0,D6=0 */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data); /* enable mode register set(MRS) low */
-	/* XGINew_Delay15us(0x100); */
-	data |= 0x80; /* SR16 D7=1,D6=0 */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data); /* enable mode register set(MRS) high */
-	/* XGINew_Delay15us(0x100); */
-}
+	xgifb_reg_set(pVBInfo->P3c4, 0x2E, pVBInfo->ECLKData[XGINew_RAMType].SR2E);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2F, pVBInfo->ECLKData[XGINew_RAMType].SR2F);
+	xgifb_reg_set(pVBInfo->P3c4, 0x30, pVBInfo->ECLKData[XGINew_RAMType].SR30);
 
-static void XGINew_DDR1x_MRS_340(unsigned long P3c4, struct vb_device_info *pVBInfo)
-{
-	XGINew_SetReg1(P3c4, 0x18, 0x01);
-	XGINew_SetReg1(P3c4, 0x19, 0x20);
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	if (*pVBInfo->pXGINew_DRAMTypeDefinition != 0x0C) { /* Samsung F Die */
-		DelayUS(3000); /* Delay 67 x 3 Delay15us */
-		XGINew_SetReg1(P3c4, 0x18, 0x00);
-		XGINew_SetReg1(P3c4, 0x19, 0x20);
-		XGINew_SetReg1(P3c4, 0x16, 0x00);
-		XGINew_SetReg1(P3c4, 0x16, 0x80);
+	/* [Vicent] 2004/07/07, When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
+	/* [Hsuan] 2004/08/20, Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, Set SR32 D[1:0] = 10b */
+	if (HwDeviceExtension->jChipType == XG42) {
+		if ((pVBInfo->MCLKData[XGINew_RAMType].SR28 == 0x1C)
+				&& (pVBInfo->MCLKData[XGINew_RAMType].SR29 == 0x01)
+				&& (((pVBInfo->ECLKData[XGINew_RAMType].SR2E == 0x1C)
+						&& (pVBInfo->ECLKData[XGINew_RAMType].SR2F == 0x01))
+					|| ((pVBInfo->ECLKData[XGINew_RAMType].SR2E == 0x22)
+						&& (pVBInfo->ECLKData[XGINew_RAMType].SR2F == 0x01))))
+			xgifb_reg_set(pVBInfo->P3c4, 0x32, ((unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x32) & 0xFC) | 0x02);
 	}
-
-	DelayUS(60);
-	XGINew_SetReg1(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
-	XGINew_SetReg1(P3c4, 0x19, 0x01);
-	XGINew_SetReg1(P3c4, 0x16, pVBInfo->SR16[0]);
-	XGINew_SetReg1(P3c4, 0x16, pVBInfo->SR16[1]);
-	DelayUS(1000);
-	XGINew_SetReg1(P3c4, 0x1B, 0x03);
-	DelayUS(500);
-	XGINew_SetReg1(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
-	XGINew_SetReg1(P3c4, 0x19, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, pVBInfo->SR16[2]);
-	XGINew_SetReg1(P3c4, 0x16, pVBInfo->SR16[3]);
-	XGINew_SetReg1(P3c4, 0x1B, 0x00);
-}
-
-static void XGINew_DDR2x_MRS_340(unsigned long P3c4, struct vb_device_info *pVBInfo)
-{
-	XGINew_SetReg1(P3c4, 0x18, 0x00);
-	XGINew_SetReg1(P3c4, 0x19, 0x20);
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-	DelayUS(60);
-	XGINew_SetReg1(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
-	/* XGINew_SetReg1(P3c4 ,0x18 ,0x31); */
-	XGINew_SetReg1(P3c4, 0x19, 0x01);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-	DelayUS(1000);
-	XGINew_SetReg1(P3c4, 0x1B, 0x03);
-	DelayUS(500);
-	/* XGINew_SetReg1(P3c4, 0x18, 0x31); */
-	XGINew_SetReg1(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
-	XGINew_SetReg1(P3c4, 0x19, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-	XGINew_SetReg1(P3c4, 0x1B, 0x00);
 }
 
 static void XGINew_DDRII_Bootup_XG27(
@@ -641,68 +156,68 @@ static void XGINew_DDRII_Bootup_XG27(
 	XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
 
 	/* Set Double Frequency */
-	/* XGINew_SetReg1(P3d4, 0x97, 0x11); *//* CR97 */
-	XGINew_SetReg1(P3d4, 0x97, *pVBInfo->pXGINew_CR97); /* CR97 */
-
-	DelayUS(200);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS2 */
-	XGINew_SetReg1(P3c4, 0x19, 0x80); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x20); /* Set SR16 */
-	DelayUS(15);
-	XGINew_SetReg1(P3c4, 0x16, 0xA0); /* Set SR16 */
-	DelayUS(15);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS3 */
-	XGINew_SetReg1(P3c4, 0x19, 0xC0); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x20); /* Set SR16 */
-	DelayUS(15);
-	XGINew_SetReg1(P3c4, 0x16, 0xA0); /* Set SR16 */
-	DelayUS(15);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x40); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x20); /* Set SR16 */
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0xA0); /* Set SR16 */
-	DelayUS(15);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x42); /* Set SR18 */ /* MRS, DLL Enable */
-	XGINew_SetReg1(P3c4, 0x19, 0x0A); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x00); /* Set SR16 */
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0x00); /* Set SR16 */
-	XGINew_SetReg1(P3c4, 0x16, 0x80); /* Set SR16 */
-	/* DelayUS(15); */
-
-	XGINew_SetReg1(P3c4, 0x1B, 0x04); /* Set SR1B */
-	DelayUS(60);
-	XGINew_SetReg1(P3c4, 0x1B, 0x00); /* Set SR1B */
-
-	XGINew_SetReg1(P3c4, 0x18, 0x42); /* Set SR18 */ /* MRS, DLL Reset */
-	XGINew_SetReg1(P3c4, 0x19, 0x08); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x00); /* Set SR16 */
-
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0x83); /* Set SR16 */
-	DelayUS(15);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x80); /* Set SR18 */ /* MRS, ODT */
-	XGINew_SetReg1(P3c4, 0x19, 0x46); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x20); /* Set SR16 */
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0xA0); /* Set SR16 */
-	DelayUS(15);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS */
-	XGINew_SetReg1(P3c4, 0x19, 0x40); /* Set SR19 */
-	XGINew_SetReg1(P3c4, 0x16, 0x20); /* Set SR16 */
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0xA0); /* Set SR16 */
-	DelayUS(15);
-
-	XGINew_SetReg1(P3c4, 0x1B, 0x04); /* Set SR1B refresh control 000:close; 010:open */
-	DelayUS(200);
+	/* xgifb_reg_set(P3d4, 0x97, 0x11); *//* CR97 */
+	xgifb_reg_set(P3d4, 0x97, *pVBInfo->pXGINew_CR97); /* CR97 */
+
+	udelay(200);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS2 */
+	xgifb_reg_set(P3c4, 0x19, 0x80); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
+	udelay(15);
+	xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
+	udelay(15);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS3 */
+	xgifb_reg_set(P3c4, 0x19, 0xC0); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
+	udelay(15);
+	xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
+	udelay(15);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS1 */
+	xgifb_reg_set(P3c4, 0x19, 0x40); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
+	udelay(30);
+	xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
+	udelay(15);
+
+	xgifb_reg_set(P3c4, 0x18, 0x42); /* Set SR18 */ /* MRS, DLL Enable */
+	xgifb_reg_set(P3c4, 0x19, 0x0A); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */
+	udelay(30);
+	xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */
+	xgifb_reg_set(P3c4, 0x16, 0x80); /* Set SR16 */
+	/* udelay(15); */
+
+	xgifb_reg_set(P3c4, 0x1B, 0x04); /* Set SR1B */
+	udelay(60);
+	xgifb_reg_set(P3c4, 0x1B, 0x00); /* Set SR1B */
+
+	xgifb_reg_set(P3c4, 0x18, 0x42); /* Set SR18 */ /* MRS, DLL Reset */
+	xgifb_reg_set(P3c4, 0x19, 0x08); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x00); /* Set SR16 */
+
+	udelay(30);
+	xgifb_reg_set(P3c4, 0x16, 0x83); /* Set SR16 */
+	udelay(15);
+
+	xgifb_reg_set(P3c4, 0x18, 0x80); /* Set SR18 */ /* MRS, ODT */
+	xgifb_reg_set(P3c4, 0x19, 0x46); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
+	udelay(30);
+	xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
+	udelay(15);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* Set SR18 */ /* EMRS */
+	xgifb_reg_set(P3c4, 0x19, 0x40); /* Set SR19 */
+	xgifb_reg_set(P3c4, 0x16, 0x20); /* Set SR16 */
+	udelay(30);
+	xgifb_reg_set(P3c4, 0x16, 0xA0); /* Set SR16 */
+	udelay(15);
+
+	xgifb_reg_set(P3c4, 0x1B, 0x04); /* Set SR1B refresh control 000:close; 010:open */
+	udelay(200);
 
 }
 
@@ -714,117 +229,74 @@ static void XGINew_DDR2_MRS_XG20(struct xgi_hw_device_info *HwDeviceExtension,
 	XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
 	XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
 
-	XGINew_SetReg1(P3d4, 0x97, 0x11); /* CR97 */
-
-	DelayUS(200);
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* EMRS2 */
-	XGINew_SetReg1(P3c4, 0x19, 0x80);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* EMRS3 */
-	XGINew_SetReg1(P3c4, 0x19, 0xC0);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* EMRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x40);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-
-	/* XGINew_SetReg1(P3c4, 0x18, 0x52); */ /* MRS1 */
-	XGINew_SetReg1(P3c4, 0x18, 0x42); /* MRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x02);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-
-	DelayUS(15);
-	XGINew_SetReg1(P3c4, 0x1B, 0x04); /* SR1B */
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x1B, 0x00); /* SR1B */
-	DelayUS(100);
-
-	/* XGINew_SetReg1(P3c4 ,0x18, 0x52); */ /* MRS2 */
-	XGINew_SetReg1(P3c4, 0x18, 0x42); /* MRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x05);
-	XGINew_SetReg1(P3c4, 0x16, 0x85);
-
-	DelayUS(200);
+	xgifb_reg_set(P3d4, 0x97, 0x11); /* CR97 */
+
+	udelay(200);
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS2 */
+	xgifb_reg_set(P3c4, 0x19, 0x80);
+	xgifb_reg_set(P3c4, 0x16, 0x05);
+	xgifb_reg_set(P3c4, 0x16, 0x85);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS3 */
+	xgifb_reg_set(P3c4, 0x19, 0xC0);
+	xgifb_reg_set(P3c4, 0x16, 0x05);
+	xgifb_reg_set(P3c4, 0x16, 0x85);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00); /* EMRS1 */
+	xgifb_reg_set(P3c4, 0x19, 0x40);
+	xgifb_reg_set(P3c4, 0x16, 0x05);
+	xgifb_reg_set(P3c4, 0x16, 0x85);
+
+	/* xgifb_reg_set(P3c4, 0x18, 0x52); */ /* MRS1 */
+	xgifb_reg_set(P3c4, 0x18, 0x42); /* MRS1 */
+	xgifb_reg_set(P3c4, 0x19, 0x02);
+	xgifb_reg_set(P3c4, 0x16, 0x05);
+	xgifb_reg_set(P3c4, 0x16, 0x85);
+
+	udelay(15);
+	xgifb_reg_set(P3c4, 0x1B, 0x04); /* SR1B */
+	udelay(30);
+	xgifb_reg_set(P3c4, 0x1B, 0x00); /* SR1B */
+	udelay(100);
+
+	/* xgifb_reg_set(P3c4 ,0x18, 0x52); */ /* MRS2 */
+	xgifb_reg_set(P3c4, 0x18, 0x42); /* MRS1 */
+	xgifb_reg_set(P3c4, 0x19, 0x00);
+	xgifb_reg_set(P3c4, 0x16, 0x05);
+	xgifb_reg_set(P3c4, 0x16, 0x85);
+
+	udelay(200);
 }
 
-#if 0
-static void XGINew_DDR2_MRS_XG27(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned long P3c4, struct vb_device_info *pVBInfo)
+static void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, struct vb_device_info *pVBInfo)
 {
-	unsigned long P3d4 = P3c4 + 0x10;
-
-	XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-	XGINew_SetMemoryClock(HwDeviceExtension , pVBInfo);
-
-	XGINew_SetReg1(P3d4, 0x97, 0x11); /* CR97 */
-	DelayUS(200);
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* EMRS2 */
-	XGINew_SetReg1(P3c4, 0x19, 0x80);
-
-	XGINew_SetReg1(P3c4, 0x16, 0x10);
-	DelayUS(15); /* 06/11/23 XG27 A0 for CKE enable */
-	XGINew_SetReg1(P3c4, 0x16, 0x90);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* EMRS3 */
-	XGINew_SetReg1(P3c4, 0x19, 0xC0);
-
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	DelayUS(15); /* 06/11/22 XG27 A0 */
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00); /* EMRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x40);
-
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	DelayUS(15); /* 06/11/22 XG27 A0 */
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x42); /* MRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x06); /* [Billy]06/11/22 DLL Reset for XG27 Hynix DRAM */
-
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	DelayUS(15); /* 06/11/23 XG27 A0 */
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	DelayUS(30); /* 06/11/23 XG27 A0 Start Auto-PreCharge */
-	XGINew_SetReg1(P3c4, 0x1B, 0x04); /* SR1B */
-	DelayUS(60);
-	XGINew_SetReg1(P3c4, 0x1B, 0x00); /* SR1B */
-
-	XGINew_SetReg1(P3c4, 0x18, 0x42); /* MRS1 */
-	XGINew_SetReg1(P3c4, 0x19, 0x04); /* DLL without Reset for XG27 Hynix DRAM */
-
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x80); /* XG27 OCD ON */
-	XGINew_SetReg1(P3c4, 0x19, 0x46);
-
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00);
-	XGINew_SetReg1(P3c4, 0x19, 0x40);
-
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	DelayUS(30);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-
-	DelayUS(15); /* Start Auto-PreCharge */
-	XGINew_SetReg1(P3c4, 0x1B, 0x04); /* SR1B */
-	DelayUS(200);
-	XGINew_SetReg1(P3c4, 0x1B, 0x03); /* SR1B */
 
+	xgifb_reg_set(P3c4, 0x18, 0x01);
+	xgifb_reg_set(P3c4, 0x19, 0x40);
+	xgifb_reg_set(P3c4, 0x16, 0x00);
+	xgifb_reg_set(P3c4, 0x16, 0x80);
+	udelay(60);
+
+	xgifb_reg_set(P3c4, 0x18, 0x00);
+	xgifb_reg_set(P3c4, 0x19, 0x40);
+	xgifb_reg_set(P3c4, 0x16, 0x00);
+	xgifb_reg_set(P3c4, 0x16, 0x80);
+	udelay(60);
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+	/* xgifb_reg_set(P3c4, 0x18, 0x31); */
+	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, 0x31); */
+	xgifb_reg_set(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
+	xgifb_reg_set(P3c4, 0x19, 0x00);
+	xgifb_reg_set(P3c4, 0x16, 0x03);
+	xgifb_reg_set(P3c4, 0x16, 0x83);
+	xgifb_reg_set(P3c4, 0x1B, 0x00);
 }
-#endif
 
 static void XGINew_DDR1x_DefaultRegister(
 		struct xgi_hw_device_info *HwDeviceExtension,
@@ -834,12 +306,12 @@ static void XGINew_DDR1x_DefaultRegister(
 
 	if (HwDeviceExtension->jChipType >= XG20) {
 		XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
-		XGINew_SetReg1(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
-		XGINew_SetReg1(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
-		XGINew_SetReg1(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
+		xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
+		xgifb_reg_set(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
+		xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
 
-		XGINew_SetReg1(P3d4, 0x98, 0x01);
-		XGINew_SetReg1(P3d4, 0x9A, 0x02);
+		xgifb_reg_set(P3d4, 0x98, 0x01);
+		xgifb_reg_set(P3d4, 0x9A, 0x02);
 
 		XGINew_DDR1x_MRS_XG20(P3c4, pVBInfo);
 	} else {
@@ -848,79 +320,34 @@ static void XGINew_DDR1x_DefaultRegister(
 		switch (HwDeviceExtension->jChipType) {
 		case XG41:
 		case XG42:
-			XGINew_SetReg1(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
-			XGINew_SetReg1(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
-			XGINew_SetReg1(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
+			xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
+			xgifb_reg_set(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
+			xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
 			break;
 		default:
-			XGINew_SetReg1(P3d4, 0x82, 0x88);
-			XGINew_SetReg1(P3d4, 0x86, 0x00);
-			XGINew_GetReg1(P3d4, 0x86); /* Insert read command for delay */
-			XGINew_SetReg1(P3d4, 0x86, 0x88);
-			XGINew_GetReg1(P3d4, 0x86);
-			XGINew_SetReg1(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]);
-			XGINew_SetReg1(P3d4, 0x82, 0x77);
-			XGINew_SetReg1(P3d4, 0x85, 0x00);
-			XGINew_GetReg1(P3d4, 0x85); /* Insert read command for delay */
-			XGINew_SetReg1(P3d4, 0x85, 0x88);
-			XGINew_GetReg1(P3d4, 0x85); /* Insert read command for delay */
-			XGINew_SetReg1(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
-			XGINew_SetReg1(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
+			xgifb_reg_set(P3d4, 0x82, 0x88);
+			xgifb_reg_set(P3d4, 0x86, 0x00);
+			xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */
+			xgifb_reg_set(P3d4, 0x86, 0x88);
+			xgifb_reg_get(P3d4, 0x86);
+			xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]);
+			xgifb_reg_set(P3d4, 0x82, 0x77);
+			xgifb_reg_set(P3d4, 0x85, 0x00);
+			xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
+			xgifb_reg_set(P3d4, 0x85, 0x88);
+			xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
+			xgifb_reg_set(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
+			xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
 			break;
 		}
 
-		XGINew_SetReg1(P3d4, 0x97, 0x00);
-		XGINew_SetReg1(P3d4, 0x98, 0x01);
-		XGINew_SetReg1(P3d4, 0x9A, 0x02);
+		xgifb_reg_set(P3d4, 0x97, 0x00);
+		xgifb_reg_set(P3d4, 0x98, 0x01);
+		xgifb_reg_set(P3d4, 0x9A, 0x02);
 		XGINew_DDR1x_MRS_340(P3c4, pVBInfo);
 	}
 }
 
-#if 0
-
-static void XGINew_DDR2x_DefaultRegister(
-		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned long Port, struct vb_device_info *pVBInfo)
-{
-	unsigned long P3d4 = Port ,
-	P3c4 = Port - 0x10;
-
-	XGINew_SetMemoryClock(HwDeviceExtension, pVBInfo);
-
-	/* 20040906 Hsuan modify CR82, CR85, CR86 for XG42 */
-	switch (HwDeviceExtension->jChipType) {
-	case XG41:
-	case XG42:
-		XGINew_SetReg1(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
-		XGINew_SetReg1(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
-		XGINew_SetReg1(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
-		break;
-	default:
-		/* keep following setting sequence, each setting in the same reg insert idle */
-		XGINew_SetReg1(P3d4, 0x82, 0x88);
-		XGINew_SetReg1(P3d4, 0x86, 0x00);
-		XGINew_GetReg1(P3d4, 0x86); /* Insert read command for delay */
-		XGINew_SetReg1(P3d4, 0x86, 0x88);
-		XGINew_SetReg1(P3d4, 0x82, 0x77);
-		XGINew_SetReg1(P3d4, 0x85, 0x00);
-		XGINew_GetReg1(P3d4, 0x85); /* Insert read command for delay */
-		XGINew_SetReg1(P3d4, 0x85, 0x88);
-		XGINew_GetReg1(P3d4, 0x85); /* Insert read command for delay */
-		XGINew_SetReg1(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
-		XGINew_SetReg1(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
-	}
-	XGINew_SetReg1(P3d4, 0x97, 0x11);
-	if (HwDeviceExtension->jChipType == XG42)
-		XGINew_SetReg1(P3d4, 0x98, 0x01);
-	else
-		XGINew_SetReg1(P3d4, 0x98, 0x03);
-
-	XGINew_SetReg1(P3d4, 0x9A, 0x02);
-
-	XGINew_DDR2x_MRS_340(P3c4, pVBInfo);
-}
-#endif
-
 static void XGINew_DDR2_DefaultRegister(
 		struct xgi_hw_device_info *HwDeviceExtension,
 		unsigned long Port, struct vb_device_info *pVBInfo)
@@ -928,32 +355,32 @@ static void XGINew_DDR2_DefaultRegister(
 	unsigned long P3d4 = Port, P3c4 = Port - 0x10;
 
 	/* keep following setting sequence, each setting in the same reg insert idle */
-	XGINew_SetReg1(P3d4, 0x82, 0x77);
-	XGINew_SetReg1(P3d4, 0x86, 0x00);
-	XGINew_GetReg1(P3d4, 0x86); /* Insert read command for delay */
-	XGINew_SetReg1(P3d4, 0x86, 0x88);
-	XGINew_GetReg1(P3d4, 0x86); /* Insert read command for delay */
-	XGINew_SetReg1(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
-	XGINew_SetReg1(P3d4, 0x82, 0x77);
-	XGINew_SetReg1(P3d4, 0x85, 0x00);
-	XGINew_GetReg1(P3d4, 0x85); /* Insert read command for delay */
-	XGINew_SetReg1(P3d4, 0x85, 0x88);
-	XGINew_GetReg1(P3d4, 0x85); /* Insert read command for delay */
-	XGINew_SetReg1(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
+	xgifb_reg_set(P3d4, 0x82, 0x77);
+	xgifb_reg_set(P3d4, 0x86, 0x00);
+	xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */
+	xgifb_reg_set(P3d4, 0x86, 0x88);
+	xgifb_reg_get(P3d4, 0x86); /* Insert read command for delay */
+	xgifb_reg_set(P3d4, 0x86, pVBInfo->CR40[13][XGINew_RAMType]); /* CR86 */
+	xgifb_reg_set(P3d4, 0x82, 0x77);
+	xgifb_reg_set(P3d4, 0x85, 0x00);
+	xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
+	xgifb_reg_set(P3d4, 0x85, 0x88);
+	xgifb_reg_get(P3d4, 0x85); /* Insert read command for delay */
+	xgifb_reg_set(P3d4, 0x85, pVBInfo->CR40[12][XGINew_RAMType]); /* CR85 */
 	if (HwDeviceExtension->jChipType == XG27)
-		XGINew_SetReg1(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
+		xgifb_reg_set(P3d4, 0x82, pVBInfo->CR40[11][XGINew_RAMType]); /* CR82 */
 	else
-		XGINew_SetReg1(P3d4, 0x82, 0xA8); /* CR82 */
+		xgifb_reg_set(P3d4, 0x82, 0xA8); /* CR82 */
 
-	XGINew_SetReg1(P3d4, 0x98, 0x01);
-	XGINew_SetReg1(P3d4, 0x9A, 0x02);
+	xgifb_reg_set(P3d4, 0x98, 0x01);
+	xgifb_reg_set(P3d4, 0x9A, 0x02);
 	if (HwDeviceExtension->jChipType == XG27)
 		XGINew_DDRII_Bootup_XG27(HwDeviceExtension, P3c4, pVBInfo);
 	else
 		XGINew_DDR2_MRS_XG20(HwDeviceExtension, P3c4, pVBInfo);
 }
 
-void XGINew_SetDRAMDefaultRegister340(
+static void XGINew_SetDRAMDefaultRegister340(
 		struct xgi_hw_device_info *HwDeviceExtension,
 		unsigned long Port, struct vb_device_info *pVBInfo)
 {
@@ -961,10 +388,10 @@ void XGINew_SetDRAMDefaultRegister340(
 
 	unsigned long P3d4 = Port, P3c4 = Port - 0x10;
 
-	XGINew_SetReg1(P3d4, 0x6D, pVBInfo->CR40[8][XGINew_RAMType]);
-	XGINew_SetReg1(P3d4, 0x68, pVBInfo->CR40[5][XGINew_RAMType]);
-	XGINew_SetReg1(P3d4, 0x69, pVBInfo->CR40[6][XGINew_RAMType]);
-	XGINew_SetReg1(P3d4, 0x6A, pVBInfo->CR40[7][XGINew_RAMType]);
+	xgifb_reg_set(P3d4, 0x6D, pVBInfo->CR40[8][XGINew_RAMType]);
+	xgifb_reg_set(P3d4, 0x68, pVBInfo->CR40[5][XGINew_RAMType]);
+	xgifb_reg_set(P3d4, 0x69, pVBInfo->CR40[6][XGINew_RAMType]);
+	xgifb_reg_set(P3d4, 0x6A, pVBInfo->CR40[7][XGINew_RAMType]);
 
 	temp2 = 0;
 	for (i = 0; i < 4; i++) {
@@ -972,8 +399,8 @@ void XGINew_SetDRAMDefaultRegister340(
 		for (j = 0; j < 4; j++) {
 			temp1 = ((temp >> (2 * j)) & 0x03) << 2;
 			temp2 |= temp1;
-			XGINew_SetReg1(P3d4, 0x6B, temp2);
-			XGINew_GetReg1(P3d4, 0x6B); /* Insert read command for delay */
+			xgifb_reg_set(P3d4, 0x6B, temp2);
+			xgifb_reg_get(P3d4, 0x6B); /* Insert read command for delay */
 			temp2 &= 0xF0;
 			temp2 += 0x10;
 		}
@@ -985,8 +412,8 @@ void XGINew_SetDRAMDefaultRegister340(
 		for (j = 0; j < 4; j++) {
 			temp1 = ((temp >> (2 * j)) & 0x03) << 2;
 			temp2 |= temp1;
-			XGINew_SetReg1(P3d4, 0x6E, temp2);
-			XGINew_GetReg1(P3d4, 0x6E); /* Insert read command for delay */
+			xgifb_reg_set(P3d4, 0x6E, temp2);
+			xgifb_reg_get(P3d4, 0x6E); /* Insert read command for delay */
 			temp2 &= 0xF0;
 			temp2 += 0x10;
 		}
@@ -994,15 +421,15 @@ void XGINew_SetDRAMDefaultRegister340(
 
 	temp3 = 0;
 	for (k = 0; k < 4; k++) {
-		XGINew_SetRegANDOR(P3d4, 0x6E, 0xFC, temp3); /* CR6E_D[1:0] select channel */
+		xgifb_reg_and_or(P3d4, 0x6E, 0xFC, temp3); /* CR6E_D[1:0] select channel */
 		temp2 = 0;
 		for (i = 0; i < 8; i++) {
 			temp = pVBInfo->CR6F[XGINew_RAMType][8 * k + i]; /* CR6F DQ fine tune delay */
 			for (j = 0; j < 4; j++) {
 				temp1 = (temp >> (2 * j)) & 0x03;
 				temp2 |= temp1;
-				XGINew_SetReg1(P3d4, 0x6F, temp2);
-				XGINew_GetReg1(P3d4, 0x6F); /* Insert read command for delay */
+				xgifb_reg_set(P3d4, 0x6F, temp2);
+				xgifb_reg_get(P3d4, 0x6F); /* Insert read command for delay */
 				temp2 &= 0xF8;
 				temp2 += 0x08;
 			}
@@ -1010,691 +437,88 @@ void XGINew_SetDRAMDefaultRegister340(
 		temp3 += 0x01;
 	}
 
-	XGINew_SetReg1(P3d4, 0x80, pVBInfo->CR40[9][XGINew_RAMType]); /* CR80 */
-	XGINew_SetReg1(P3d4, 0x81, pVBInfo->CR40[10][XGINew_RAMType]); /* CR81 */
+	xgifb_reg_set(P3d4, 0x80, pVBInfo->CR40[9][XGINew_RAMType]); /* CR80 */
+	xgifb_reg_set(P3d4, 0x81, pVBInfo->CR40[10][XGINew_RAMType]); /* CR81 */
 
 	temp2 = 0x80;
 	temp = pVBInfo->CR89[XGINew_RAMType][0]; /* CR89 terminator type select */
 	for (j = 0; j < 4; j++) {
 		temp1 = (temp >> (2 * j)) & 0x03;
 		temp2 |= temp1;
-		XGINew_SetReg1(P3d4, 0x89, temp2);
-		XGINew_GetReg1(P3d4, 0x89); /* Insert read command for delay */
+		xgifb_reg_set(P3d4, 0x89, temp2);
+		xgifb_reg_get(P3d4, 0x89); /* Insert read command for delay */
 		temp2 &= 0xF0;
 		temp2 += 0x10;
 	}
 
 	temp = pVBInfo->CR89[XGINew_RAMType][1];
-	temp1 = temp & 0x03;
-	temp2 |= temp1;
-	XGINew_SetReg1(P3d4, 0x89, temp2);
-
-	temp = pVBInfo->CR40[3][XGINew_RAMType];
-	temp1 = temp & 0x0F;
-	temp2 = (temp >> 4) & 0x07;
-	temp3 = temp & 0x80;
-	XGINew_SetReg1(P3d4, 0x45, temp1); /* CR45 */
-	XGINew_SetReg1(P3d4, 0x99, temp2); /* CR99 */
-	XGINew_SetRegOR(P3d4, 0x40, temp3); /* CR40_D[7] */
-	XGINew_SetReg1(P3d4, 0x41, pVBInfo->CR40[0][XGINew_RAMType]); /* CR41 */
-
-	if (HwDeviceExtension->jChipType == XG27)
-		XGINew_SetReg1(P3d4, 0x8F, *pVBInfo->pCR8F); /* CR8F */
-
-	for (j = 0; j <= 6; j++)
-		XGINew_SetReg1(P3d4, (0x90 + j),
-				pVBInfo->CR40[14 + j][XGINew_RAMType]); /* CR90 - CR96 */
-
-	for (j = 0; j <= 2; j++)
-		XGINew_SetReg1(P3d4, (0xC3 + j),
-				pVBInfo->CR40[21 + j][XGINew_RAMType]); /* CRC3 - CRC5 */
-
-	for (j = 0; j < 2; j++)
-		XGINew_SetReg1(P3d4, (0x8A + j),
-				pVBInfo->CR40[1 + j][XGINew_RAMType]); /* CR8A - CR8B */
-
-	if ((HwDeviceExtension->jChipType == XG41) || (HwDeviceExtension->jChipType == XG42))
-		XGINew_SetReg1(P3d4, 0x8C, 0x87);
-
-	XGINew_SetReg1(P3d4, 0x59, pVBInfo->CR40[4][XGINew_RAMType]); /* CR59 */
-
-	XGINew_SetReg1(P3d4, 0x83, 0x09); /* CR83 */
-	XGINew_SetReg1(P3d4, 0x87, 0x00); /* CR87 */
-	XGINew_SetReg1(P3d4, 0xCF, *pVBInfo->pCRCF); /* CRCF */
-	if (XGINew_RAMType) {
-		/* XGINew_SetReg1(P3c4, 0x17, 0xC0); */ /* SR17 DDRII */
-		XGINew_SetReg1(P3c4, 0x17, 0x80); /* SR17 DDRII */
-		if (HwDeviceExtension->jChipType == XG27)
-			XGINew_SetReg1(P3c4, 0x17, 0x02); /* SR17 DDRII */
-
-	} else {
-		XGINew_SetReg1(P3c4, 0x17, 0x00); /* SR17 DDR */
-	}
-	XGINew_SetReg1(P3c4, 0x1A, 0x87); /* SR1A */
-
-	temp = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
-	if (temp == 0) {
-		XGINew_DDR1x_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
-	} else {
-		XGINew_SetReg1(P3d4, 0xB0, 0x80); /* DDRII Dual frequency mode */
-		XGINew_DDR2_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
-	}
-	XGINew_SetReg1(P3c4, 0x1B, pVBInfo->SR15[3][XGINew_RAMType]); /* SR1B */
-}
-
-static void XGINew_DDR_MRS(struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-
-	volatile unsigned char *pVideoMemory = (unsigned char *) pVBInfo->ROMAddr;
-
-	/* SR16 <- 1F,DF,2F,AF */
-	/* yriver modified SR16 <- 0F,DF,0F,AF */
-	/* enable DLL of DDR SD/SGRAM , SR16 D4=1 */
-	data = pVideoMemory[0xFB];
-	/* data = XGINew_GetReg1(pVBInfo->P3c4, 0x16); */
-
-	data &= 0x0F;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data |= 0xC0;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data &= 0x0F;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data |= 0x80;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data &= 0x0F;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data |= 0xD0;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data &= 0x0F;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	data |= 0xA0;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, data);
-	/*
-	else {
-		data &= 0x0F;
-		data |= 0x10;
-		XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
-
-		if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10)) {
-			data &= 0x0F;
-		}
-
-		data |= 0xC0;
-		XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
-
-		data &= 0x0F;
-		data |= 0x20;
-		XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
-		if (!(pVBInfo->SR15[1][XGINew_RAMType] & 0x10)) {
-			data &= 0x0F;
-		}
-
-		data |= 0x80;
-		XGINew_SetReg1(pVBInfo->P3c4,0x16,data);
-	}
-	*/
-}
-
-/* check if read cache pointer is correct */
-
-static void XGINew_VerifyMclk(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned char *pVideoMemory = pVBInfo->FBAddr;
-	unsigned char i, j;
-	unsigned short Temp, SR21;
-
-	pVideoMemory[0] = 0xaa; /* alan */
-	pVideoMemory[16] = 0x55; /* note: PCI read cache is off */
-
-	if ((pVideoMemory[0] != 0xaa) || (pVideoMemory[16] != 0x55)) {
-		for (i = 0, j = 16; i < 2; i++, j += 16) {
-			SR21 = XGINew_GetReg1(pVBInfo->P3c4, 0x21);
-			Temp = SR21 & 0xFB; /* disable PCI post write buffer empty gating */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x21, Temp);
-
-			Temp = XGINew_GetReg1(pVBInfo->P3c4, 0x3C);
-			Temp |= 0x01; /* MCLK reset */
-
-			Temp = XGINew_GetReg1(pVBInfo->P3c4, 0x3C);
-			Temp &= 0xFE; /* MCLK normal operation */
-
-			XGINew_SetReg1(pVBInfo->P3c4, 0x21, SR21);
-
-			pVideoMemory[16 + j] = j;
-			if (pVideoMemory[16 + j] == j) {
-				pVideoMemory[j] = j;
-				break;
-			}
-		}
-	}
-}
-
-void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-
-	XGISetModeNew(HwDeviceExtension, 0x2e);
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x21);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short) (data & 0xDF)); /* disable read cache */
-	XGI_DisplayOff(HwDeviceExtension, pVBInfo);
-
-	/* data = XGINew_GetReg1(pVBInfo->P3c4, 0x1); */
-	/* data |= 0x20 ; */
-	/* XGINew_SetReg1(pVBInfo->P3c4, 0x01, data); *//* Turn OFF Display */
-	XGINew_DDRSizing340(HwDeviceExtension, pVBInfo);
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x21);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short) (data | 0x20)); /* enable read cache */
-}
-
-void XGINew_SetDRAMSize_310(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase, pVBInfo->FBAddr
-			= HwDeviceExtension->pjVideoMemoryAddress;
-#ifdef XGI301
-	/* XGINew_SetReg1(pVBInfo->P3d4, 0x30, 0x40); */
-#endif
-
-#ifdef XGI302	/* alan,should change value */
-	XGINew_SetReg1(pVBInfo->P3d4, 0x30, 0x4D);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x31, 0xc0);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x34, 0x3F);
-#endif
-
-	XGISetModeNew(HwDeviceExtension, 0x2e);
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x21);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short) (data & 0xDF)); /* disable read cache */
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x1);
-	data |= 0x20;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x01, data); /* Turn OFF Display */
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x16);
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, (unsigned short) (data | 0x0F)); /* assume lowest speed DRAM */
-
-	XGINew_SetDRAMModeRegister(pVBInfo);
-	XGINew_DisableRefresh(HwDeviceExtension, pVBInfo);
-	XGINew_CheckBusWidth_310(pVBInfo);
-	XGINew_VerifyMclk(HwDeviceExtension, pVBInfo); /* alan 2000/7/3 */
-
-	if (XGINew_Get310DRAMType(pVBInfo) < 2)
-		XGINew_SDRSizing(pVBInfo);
-	else
-		XGINew_DDRSizing(pVBInfo);
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x16, pVBInfo->SR15[1][XGINew_RAMType]); /* restore SR16 */
-
-	XGINew_EnableRefresh(HwDeviceExtension, pVBInfo);
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x21);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x21, (unsigned short) (data | 0x20)); /* enable read cache */
-}
-
-void XGINew_SetDRAMModeRegister340(struct xgi_hw_device_info *HwDeviceExtension)
-{
-	unsigned char data;
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-	pVBInfo->ISXPDOS = 0;
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */
-		XGI_GetVBType(pVBInfo); /* Run XGI_GetVBType before InitTo330Pointer */
-
-	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-
-	ReadVBIOSTablData(HwDeviceExtension->jChipType, pVBInfo);
-
-	if (XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) == 0) {
-		data = (XGINew_GetReg1(pVBInfo->P3c4, 0x39) & 0x02) >> 1;
-		if (data == 0x01)
-			XGINew_DDR2x_MRS_340(pVBInfo->P3c4, pVBInfo);
-		else
-			XGINew_DDR1x_MRS_340(pVBInfo->P3c4, pVBInfo);
-	} else {
-		XGINew_DDR2_MRS_XG20(HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
-	}
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1B, 0x03);
-}
-
-void XGINew_SetDRAMModeRegister(struct vb_device_info *pVBInfo)
-{
-	if (XGINew_Get310DRAMType(pVBInfo) < 2) {
-		XGINew_SDR_MRS(pVBInfo);
-	} else {
-		/* SR16 <- 0F,CF,0F,8F */
-		XGINew_DDR_MRS(pVBInfo);
-	}
-}
-
-void XGINew_DisableRefresh(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x1B);
-	data &= 0xF8;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1B, data);
-
-}
-
-void XGINew_EnableRefresh(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1B, pVBInfo->SR15[3][XGINew_RAMType]); /* SR1B */
-
-}
-
-static void XGINew_DisableChannelInterleaving(int index,
-		unsigned short XGINew_DDRDRAM_TYPE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x15);
-	data &= 0x1F;
-
-	switch (XGINew_DDRDRAM_TYPE[index][3]) {
-	case 64:
-		data |= 0;
-		break;
-	case 32:
-		data |= 0x20;
-		break;
-	case 16:
-		data |= 0x40;
-		break;
-	case 4:
-		data |= 0x60;
-		break;
-	default:
-		break;
-	}
-	XGINew_SetReg1(pVBInfo->P3c4, 0x15, data);
-}
-
-static void XGINew_SetDRAMSizingType(int index,
-		unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-
-	data = DRAMTYPE_TABLE[index][4];
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x13, 0x80, data);
-	DelayUS(15);
-	/* should delay 50 ns */
-}
-
-void XGINew_CheckBusWidth_310(struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-	volatile unsigned long *pVideoMemory;
-
-	pVideoMemory = (unsigned long *) pVBInfo->FBAddr;
-
-	if (XGINew_Get310DRAMType(pVBInfo) < 2) {
-		XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x00);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x12);
-		/* should delay */
-		XGINew_SDR_MRS(pVBInfo);
-
-		XGINew_ChannelAB = 0;
-		XGINew_DataBusWidth = 128;
-		pVideoMemory[0] = 0x01234567L;
-		pVideoMemory[1] = 0x456789ABL;
-		pVideoMemory[2] = 0x89ABCDEFL;
-		pVideoMemory[3] = 0xCDEF0123L;
-		pVideoMemory[4] = 0x55555555L;
-		pVideoMemory[5] = 0x55555555L;
-		pVideoMemory[6] = 0xFFFFFFFFL;
-		pVideoMemory[7] = 0xFFFFFFFFL;
-
-		if ((pVideoMemory[3] != 0xCDEF0123L) || (pVideoMemory[2]
-				!= 0x89ABCDEFL)) {
-			/* ChannelA64Bit */
-			XGINew_DataBusWidth = 64;
-			XGINew_ChannelAB = 0;
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x14);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14,
-					(unsigned short) (data & 0xFD));
-		}
-
-		if ((pVideoMemory[1] != 0x456789ABL) || (pVideoMemory[0]
-				!= 0x01234567L)) {
-			/* ChannelB64Bit */
-			XGINew_DataBusWidth = 64;
-			XGINew_ChannelAB = 1;
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x14);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14,
-					(unsigned short) ((data & 0xFD) | 0x01));
-		}
-
-		return;
-	} else {
-		/* DDR Dual channel */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x00);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x02); /* Channel A, 64bit */
-		/* should delay */
-		XGINew_DDR_MRS(pVBInfo);
-
-		XGINew_ChannelAB = 0;
-		XGINew_DataBusWidth = 64;
-		pVideoMemory[0] = 0x01234567L;
-		pVideoMemory[1] = 0x456789ABL;
-		pVideoMemory[2] = 0x89ABCDEFL;
-		pVideoMemory[3] = 0xCDEF0123L;
-		pVideoMemory[4] = 0x55555555L;
-		pVideoMemory[5] = 0x55555555L;
-		pVideoMemory[6] = 0xAAAAAAAAL;
-		pVideoMemory[7] = 0xAAAAAAAAL;
-
-		if (pVideoMemory[1] == 0x456789ABL) {
-			if (pVideoMemory[0] == 0x01234567L) {
-				/* Channel A 64bit */
-				return;
-			}
-		} else {
-			if (pVideoMemory[0] == 0x01234567L) {
-				/* Channel A 32bit */
-				XGINew_DataBusWidth = 32;
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x00);
-				return;
-			}
-		}
-
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x03); /* Channel B, 64bit */
-		XGINew_DDR_MRS(pVBInfo);
-
-		XGINew_ChannelAB = 1;
-		XGINew_DataBusWidth = 64;
-		pVideoMemory[0] = 0x01234567L;
-		pVideoMemory[1] = 0x456789ABL;
-		pVideoMemory[2] = 0x89ABCDEFL;
-		pVideoMemory[3] = 0xCDEF0123L;
-		pVideoMemory[4] = 0x55555555L;
-		pVideoMemory[5] = 0x55555555L;
-		pVideoMemory[6] = 0xAAAAAAAAL;
-		pVideoMemory[7] = 0xAAAAAAAAL;
-
-		if (pVideoMemory[1] == 0x456789ABL) {
-			/* Channel B 64 */
-			if (pVideoMemory[0] == 0x01234567L) {
-				/* Channel B 64bit */
-				return;
-			} else {
-				/* error */
-			}
-		} else {
-			if (pVideoMemory[0] == 0x01234567L) {
-				/* Channel B 32 */
-				XGINew_DataBusWidth = 32;
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x01);
-			} else {
-				/* error */
-			}
-		}
-	}
-}
-
-static int XGINew_SetRank(int index, unsigned char RankNo,
-		unsigned char XGINew_ChannelAB,
-		unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-	int RankSize;
-
-	if ((RankNo == 2) && (DRAMTYPE_TABLE[index][0] == 2))
-		return 0;
-
-	RankSize = DRAMTYPE_TABLE[index][3] / 2 * XGINew_DataBusWidth / 32;
-
-	if ((RankNo * RankSize) <= 128) {
-		data = 0;
-
-		while ((RankSize >>= 1) > 0)
-			data += 0x10;
-
-		data |= (RankNo - 1) << 2;
-		data |= (XGINew_DataBusWidth / 64) & 2;
-		data |= XGINew_ChannelAB;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, data);
-		/* should delay */
-		XGINew_SDR_MRS(pVBInfo);
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-static int XGINew_SetDDRChannel(int index, unsigned char ChannelNo,
-		unsigned char XGINew_ChannelAB,
-		unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
-	int RankSize;
-
-	RankSize = DRAMTYPE_TABLE[index][3] / 2 * XGINew_DataBusWidth / 32;
-	/* RankSize = DRAMTYPE_TABLE[index][3]; */
-	if (ChannelNo * RankSize <= 128) {
-		data = 0;
-		while ((RankSize >>= 1) > 0)
-			data += 0x10;
-
-		if (ChannelNo == 2)
-			data |= 0x0C;
-
-		data |= (XGINew_DataBusWidth / 32) & 2;
-		data |= XGINew_ChannelAB;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, data);
-		/* should delay */
-		XGINew_DDR_MRS(pVBInfo);
-		return 1;
-	} else {
-		return 0;
-	}
-}
-
-static int XGINew_CheckColumn(int index, unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	int i;
-	unsigned long Increment, Position;
-
-	/* Increment = 1 << (DRAMTYPE_TABLE[index][2] + XGINew_DataBusWidth / 64 + 1); */
-	Increment = 1 << (10 + XGINew_DataBusWidth / 64);
-
-	for (i = 0, Position = 0; i < 2; i++) {
-		*((unsigned long *) (pVBInfo->FBAddr + Position)) = Position;
-		Position += Increment;
-	}
-
-	for (i = 0, Position = 0; i < 2; i++) {
-		/* if ( pVBInfo->FBAddr[ Position ] != Position ) */
-		if ((*(unsigned long *) (pVBInfo->FBAddr + Position)) != Position)
-			return 0;
-		Position += Increment;
-	}
-	return 1;
-}
-
-static int XGINew_CheckBanks(int index, unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	int i;
-	unsigned long Increment, Position;
-
-	Increment = 1 << (DRAMTYPE_TABLE[index][2] + XGINew_DataBusWidth / 64 + 2);
-
-	for (i = 0, Position = 0; i < 4; i++) {
-		/* pVBInfo->FBAddr[Position] = Position; */
-		*((unsigned long *) (pVBInfo->FBAddr + Position)) = Position;
-		Position += Increment;
-	}
-
-	for (i = 0, Position = 0; i < 4; i++) {
-		/* if (pVBInfo->FBAddr[Position] != Position) */
-		if ((*(unsigned long *) (pVBInfo->FBAddr + Position)) != Position)
-			return 0;
-		Position += Increment;
-	}
-	return 1;
-}
-
-static int XGINew_CheckRank(int RankNo, int index,
-		unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	int i;
-	unsigned long Increment, Position;
-
-	Increment = 1 << (DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1]
-			+ DRAMTYPE_TABLE[index][0] + XGINew_DataBusWidth / 64
-			+ RankNo);
-
-	for (i = 0, Position = 0; i < 2; i++) {
-		/* pVBInfo->FBAddr[Position] = Position; */
-		/* *((unsigned long *)(pVBInfo->FBAddr)) = Position; */
-		*((unsigned long *) (pVBInfo->FBAddr + Position)) = Position;
-		Position += Increment;
-	}
-
-	for (i = 0, Position = 0; i < 2; i++) {
-		/* if (pVBInfo->FBAddr[Position] != Position) */
-		/* if ((*(unsigned long *)(pVBInfo->FBAddr)) != Position) */
-		if ((*(unsigned long *) (pVBInfo->FBAddr + Position)) != Position)
-			return 0;
-		Position += Increment;
-	}
-	return 1;
-}
-
-static int XGINew_CheckDDRRank(int RankNo, int index,
-		unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	unsigned long Increment, Position;
-	unsigned short data;
+	temp1 = temp & 0x03;
+	temp2 |= temp1;
+	xgifb_reg_set(P3d4, 0x89, temp2);
 
-	Increment = 1 << (DRAMTYPE_TABLE[index][2] + DRAMTYPE_TABLE[index][1]
-			+ DRAMTYPE_TABLE[index][0] + XGINew_DataBusWidth / 64
-			+ RankNo);
+	temp = pVBInfo->CR40[3][XGINew_RAMType];
+	temp1 = temp & 0x0F;
+	temp2 = (temp >> 4) & 0x07;
+	temp3 = temp & 0x80;
+	xgifb_reg_set(P3d4, 0x45, temp1); /* CR45 */
+	xgifb_reg_set(P3d4, 0x99, temp2); /* CR99 */
+	xgifb_reg_or(P3d4, 0x40, temp3); /* CR40_D[7] */
+	xgifb_reg_set(P3d4, 0x41, pVBInfo->CR40[0][XGINew_RAMType]); /* CR41 */
 
-	Increment += Increment / 2;
+	if (HwDeviceExtension->jChipType == XG27)
+		xgifb_reg_set(P3d4, 0x8F, *pVBInfo->pCR8F); /* CR8F */
 
-	Position = 0;
-	*((unsigned long *) (pVBInfo->FBAddr + Position + 0)) = 0x01234567;
-	*((unsigned long *) (pVBInfo->FBAddr + Position + 1)) = 0x456789AB;
-	*((unsigned long *) (pVBInfo->FBAddr + Position + 2)) = 0x55555555;
-	*((unsigned long *) (pVBInfo->FBAddr + Position + 3)) = 0x55555555;
-	*((unsigned long *) (pVBInfo->FBAddr + Position + 4)) = 0xAAAAAAAA;
-	*((unsigned long *) (pVBInfo->FBAddr + Position + 5)) = 0xAAAAAAAA;
+	for (j = 0; j <= 6; j++)
+		xgifb_reg_set(P3d4, (0x90 + j),
+				pVBInfo->CR40[14 + j][XGINew_RAMType]); /* CR90 - CR96 */
 
-	if ((*(unsigned long *) (pVBInfo->FBAddr + 1)) == 0x456789AB)
-		return 1;
+	for (j = 0; j <= 2; j++)
+		xgifb_reg_set(P3d4, (0xC3 + j),
+				pVBInfo->CR40[21 + j][XGINew_RAMType]); /* CRC3 - CRC5 */
 
-	if ((*(unsigned long *) (pVBInfo->FBAddr + 0)) == 0x01234567)
-		return 0;
+	for (j = 0; j < 2; j++)
+		xgifb_reg_set(P3d4, (0x8A + j),
+				pVBInfo->CR40[1 + j][XGINew_RAMType]); /* CR8A - CR8B */
 
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x14);
-	data &= 0xF3;
-	data |= 0x0E;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x14, data);
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x15);
-	data += 0x20;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x15, data);
+	if ((HwDeviceExtension->jChipType == XG41) || (HwDeviceExtension->jChipType == XG42))
+		xgifb_reg_set(P3d4, 0x8C, 0x87);
 
-	return 1;
-}
+	xgifb_reg_set(P3d4, 0x59, pVBInfo->CR40[4][XGINew_RAMType]); /* CR59 */
 
-static int XGINew_CheckRanks(int RankNo, int index,
-		unsigned short DRAMTYPE_TABLE[][5],
-		struct vb_device_info *pVBInfo)
-{
-	int r;
+	xgifb_reg_set(P3d4, 0x83, 0x09); /* CR83 */
+	xgifb_reg_set(P3d4, 0x87, 0x00); /* CR87 */
+	xgifb_reg_set(P3d4, 0xCF, *pVBInfo->pCRCF); /* CRCF */
+	if (XGINew_RAMType) {
+		/* xgifb_reg_set(P3c4, 0x17, 0xC0); */ /* SR17 DDRII */
+		xgifb_reg_set(P3c4, 0x17, 0x80); /* SR17 DDRII */
+		if (HwDeviceExtension->jChipType == XG27)
+			xgifb_reg_set(P3c4, 0x17, 0x02); /* SR17 DDRII */
 
-	for (r = RankNo; r >= 1; r--) {
-		if (!XGINew_CheckRank(r, index, DRAMTYPE_TABLE, pVBInfo))
-			return 0;
+	} else {
+		xgifb_reg_set(P3c4, 0x17, 0x00); /* SR17 DDR */
 	}
+	xgifb_reg_set(P3c4, 0x1A, 0x87); /* SR1A */
 
-	if (!XGINew_CheckBanks(index, DRAMTYPE_TABLE, pVBInfo))
-		return 0;
-
-	if (!XGINew_CheckColumn(index, DRAMTYPE_TABLE, pVBInfo))
-		return 0;
-
-	return 1;
+	temp = XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
+	if (temp == 0) {
+		XGINew_DDR1x_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
+	} else {
+		xgifb_reg_set(P3d4, 0xB0, 0x80); /* DDRII Dual frequency mode */
+		XGINew_DDR2_DefaultRegister(HwDeviceExtension, P3d4, pVBInfo);
+	}
+	xgifb_reg_set(P3c4, 0x1B, pVBInfo->SR15[3][XGINew_RAMType]); /* SR1B */
 }
 
-static int XGINew_CheckDDRRanks(int RankNo, int index,
+static void XGINew_SetDRAMSizingType(int index,
 		unsigned short DRAMTYPE_TABLE[][5],
 		struct vb_device_info *pVBInfo)
 {
-	int r;
-
-	for (r = RankNo; r >= 1; r--) {
-		if (!XGINew_CheckDDRRank(r, index, DRAMTYPE_TABLE, pVBInfo))
-			return 0;
-	}
-
-	if (!XGINew_CheckBanks(index, DRAMTYPE_TABLE, pVBInfo))
-		return 0;
-
-	if (!XGINew_CheckColumn(index, DRAMTYPE_TABLE, pVBInfo))
-		return 0;
-
-	return 1;
-}
-
-int XGINew_SDRSizing(struct vb_device_info *pVBInfo)
-{
-	int i;
-	unsigned char j;
-
-	for (i = 0; i < 13; i++) {
-		XGINew_SetDRAMSizingType(i, XGINew_SDRDRAM_TYPE, pVBInfo);
+	unsigned short data;
 
-		for (j = 2; j > 0; j--) {
-			if (!XGINew_SetRank(i, (unsigned char) j, XGINew_ChannelAB, XGINew_SDRDRAM_TYPE, pVBInfo)) {
-				continue;
-			} else {
-				if (XGINew_CheckRanks(j, i, XGINew_SDRDRAM_TYPE, pVBInfo))
-					return 1;
-			}
-		}
-	}
-	return 0;
+	data = DRAMTYPE_TABLE[index][4];
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x13, 0x80, data);
+	udelay(15);
+	/* should delay 50 ns */
 }
 
 static unsigned short XGINew_SetDRAMSizeReg(int index,
@@ -1706,7 +530,7 @@ static unsigned short XGINew_SetDRAMSizeReg(int index,
 	unsigned char ChannelNo;
 
 	RankSize = DRAMTYPE_TABLE[index][3] * XGINew_DataBusWidth / 32;
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x13);
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x13);
 	data &= 0x80;
 
 	if (data == 0x80)
@@ -1726,11 +550,11 @@ static unsigned short XGINew_SetDRAMSizeReg(int index,
 		memsize = data >> 4;
 
 		/* [2004/03/25] Vicent, Fix DRAM Sizing Error */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, (XGINew_GetReg1(pVBInfo->P3c4, 0x14) & 0x0F) | (data & 0xF0));
+		xgifb_reg_set(pVBInfo->P3c4, 0x14, (xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) | (data & 0xF0));
 
 		/* data |= XGINew_ChannelAB << 2; */
 		/* data |= (XGINew_DataBusWidth / 64) << 1; */
-		/* XGINew_SetReg1(pVBInfo->P3c4, 0x14, data); */
+		/* xgifb_reg_set(pVBInfo->P3c4, 0x14, data); */
 
 		/* should delay */
 		/* XGINew_SetDRAMModeRegister340(pVBInfo); */
@@ -1747,7 +571,7 @@ static unsigned short XGINew_SetDRAMSize20Reg(int index,
 	unsigned char ChannelNo;
 
 	RankSize = DRAMTYPE_TABLE[index][3] * XGINew_DataBusWidth / 8;
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x13);
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x13);
 	data &= 0x80;
 
 	if (data == 0x80)
@@ -1767,12 +591,12 @@ static unsigned short XGINew_SetDRAMSize20Reg(int index,
 		memsize = data >> 4;
 
 		/* [2004/03/25] Vicent, Fix DRAM Sizing Error */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, (XGINew_GetReg1(pVBInfo->P3c4, 0x14) & 0x0F) | (data & 0xF0));
-		DelayUS(15);
+		xgifb_reg_set(pVBInfo->P3c4, 0x14, (xgifb_reg_get(pVBInfo->P3c4, 0x14) & 0x0F) | (data & 0xF0));
+		udelay(15);
 
 		/* data |= XGINew_ChannelAB << 2; */
 		/* data |= (XGINew_DataBusWidth / 64) << 1; */
-		/* XGINew_SetReg1(pVBInfo->P3c4, 0x14, data); */
+		/* xgifb_reg_set(pVBInfo->P3c4, 0x14, data); */
 
 		/* should delay */
 		/* XGINew_SetDRAMModeRegister340(pVBInfo); */
@@ -1793,7 +617,7 @@ static int XGINew_ReadWriteRest(unsigned short StopAddr,
 		*((unsigned long *) (pVBInfo->FBAddr + Position)) = Position;
 	}
 
-	DelayUS(500); /* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */
+	udelay(500); /* [Vicent] 2004/04/16. Fix #1759 Memory Size error in Multi-Adapter. */
 
 	Position = 0;
 
@@ -1812,10 +636,10 @@ static unsigned char XGINew_CheckFrequence(struct vb_device_info *pVBInfo)
 {
 	unsigned char data;
 
-	data = XGINew_GetReg1(pVBInfo->P3d4, 0x97);
+	data = xgifb_reg_get(pVBInfo->P3d4, 0x97);
 
 	if ((data & 0x10) == 0) {
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x39);
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x39);
 		data = (data & 0x02) >> 1;
 		return data;
 	} else {
@@ -1831,7 +655,7 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 	switch (HwDeviceExtension->jChipType) {
 	case XG20:
 	case XG21:
-		data = XGINew_GetReg1(pVBInfo->P3d4, 0x97);
+		data = xgifb_reg_get(pVBInfo->P3d4, 0x97);
 		data = data & 0x01;
 		XGINew_ChannelAB = 1; /* XG20 "JUST" one channel */
 
@@ -1841,17 +665,17 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 					> 0x1000000) {
 
 				XGINew_DataBusWidth = 32; /* 32 bits */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xB1); /* 22bit + 2 rank + 32bit */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x52);
-				DelayUS(15);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1); /* 22bit + 2 rank + 32bit */
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
+				udelay(15);
 
 				if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 					return;
 
 				if ((HwDeviceExtension->ulVideoMemorySize - 1) > 0x800000) {
-					XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x31); /* 22bit + 1 rank + 32bit */
-					XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x42);
-					DelayUS(15);
+					xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x31); /* 22bit + 1 rank + 32bit */
+					xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x42);
+					udelay(15);
 
 					if (XGINew_ReadWriteRest(23, 23, pVBInfo) == 1)
 						return;
@@ -1860,32 +684,32 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 
 			if ((HwDeviceExtension->ulVideoMemorySize - 1) > 0x800000) {
 				XGINew_DataBusWidth = 16; /* 16 bits */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xB1); /* 22bit + 2 rank + 16bit */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x41);
-				DelayUS(15);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1); /* 22bit + 2 rank + 16bit */
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41);
+				udelay(15);
 
 				if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
 					return;
 				else
-					XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x31);
-				DelayUS(15);
+					xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x31);
+				udelay(15);
 			}
 
 		} else { /* Dual_16_8 */
 			if ((HwDeviceExtension->ulVideoMemorySize - 1) > 0x800000) {
 
 				XGINew_DataBusWidth = 16; /* 16 bits */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xB1); /* (0x31:12x8x2) 22bit + 2 rank */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x41); /* 0x41:16Mx16 bit*/
-				DelayUS(15);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1); /* (0x31:12x8x2) 22bit + 2 rank */
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x41); /* 0x41:16Mx16 bit*/
+				udelay(15);
 
 				if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
 					return;
 
 				if ((HwDeviceExtension->ulVideoMemorySize - 1) > 0x400000) {
-					XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x31); /* (0x31:12x8x2) 22bit + 1 rank */
-					XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x31); /* 0x31:8Mx16 bit*/
-					DelayUS(15);
+					xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x31); /* (0x31:12x8x2) 22bit + 1 rank */
+					xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x31); /* 0x31:8Mx16 bit*/
+					udelay(15);
 
 					if (XGINew_ReadWriteRest(22, 22, pVBInfo) == 1)
 						return;
@@ -1894,15 +718,15 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 
 			if ((HwDeviceExtension->ulVideoMemorySize - 1) > 0x400000) {
 				XGINew_DataBusWidth = 8; /* 8 bits */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xB1); /* (0x31:12x8x2) 22bit + 2 rank */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x30); /* 0x30:8Mx8 bit*/
-				DelayUS(15);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xB1); /* (0x31:12x8x2) 22bit + 2 rank */
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x30); /* 0x30:8Mx8 bit*/
+				udelay(15);
 
 				if (XGINew_ReadWriteRest(22, 21, pVBInfo) == 1)
 					return;
 				else
-					XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x31); /* (0x31:12x8x2) 22bit + 1 rank */
-				DelayUS(15);
+					xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x31); /* (0x31:12x8x2) 22bit + 1 rank */
+				udelay(15);
 			}
 		}
 		break;
@@ -1910,76 +734,76 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 	case XG27:
 		XGINew_DataBusWidth = 16; /* 16 bits */
 		XGINew_ChannelAB = 1; /* Single channel */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x51); /* 32Mx16 bit*/
+		xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x51); /* 32Mx16 bit*/
 		break;
 	case XG41:
 		if (XGINew_CheckFrequence(pVBInfo) == 1) {
 			XGINew_DataBusWidth = 32; /* 32 bits */
 			XGINew_ChannelAB = 3; /* Quad Channel */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x4C);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4C);
 
 			if (XGINew_ReadWriteRest(25, 23, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 2; /* Dual channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x48);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x48);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x49);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x49);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 3;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x3C);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x3C);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x38);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x38);
 
 			if (XGINew_ReadWriteRest(8, 4, pVBInfo) == 1)
 				return;
 			else
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x39);
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x39);
 		} else { /* DDR */
 			XGINew_DataBusWidth = 64; /* 64 bits */
 			XGINew_ChannelAB = 2; /* Dual channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x5A);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x5A);
 
 			if (XGINew_ReadWriteRest(25, 24, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 1; /* Single channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x52);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x53);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x53);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 2; /* Dual channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x4A);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4A);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 1; /* Single channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x42);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x42);
 
 			if (XGINew_ReadWriteRest(8, 4, pVBInfo) == 1)
 				return;
 			else
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x43);
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x43);
 		}
 
 		break;
@@ -1995,38 +819,38 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 		if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII, DDR2x */
 			XGINew_DataBusWidth = 32; /* 32 bits */
 			XGINew_ChannelAB = 2; /* 2 Channel */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x44);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x44);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x34);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x34);
 			if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 1; /* Single Channel */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x40);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x40);
 
 			if (XGINew_ReadWriteRest(23, 22, pVBInfo) == 1)
 				return;
 			else {
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x30);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x30);
 			}
 		} else { /* DDR */
 			XGINew_DataBusWidth = 64; /* 64 bits */
 			XGINew_ChannelAB = 1; /* 1 channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x52);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x52);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 			else {
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x42);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x42);
 			}
 		}
 
@@ -2037,52 +861,52 @@ static void XGINew_CheckChannel(struct xgi_hw_device_info *HwDeviceExtension,
 		if (XGINew_CheckFrequence(pVBInfo) == 1) { /* DDRII */
 			XGINew_DataBusWidth = 32; /* 32 bits */
 			XGINew_ChannelAB = 3;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x4C);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4C);
 
 			if (XGINew_ReadWriteRest(25, 23, pVBInfo) == 1)
 				return;
 
 			XGINew_ChannelAB = 2; /* 2 channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x48);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x48);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1)
 				return;
 
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x3C);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x3C);
 
 			if (XGINew_ReadWriteRest(24, 23, pVBInfo) == 1) {
 				XGINew_ChannelAB = 3; /* 4 channels */
 			} else {
 				XGINew_ChannelAB = 2; /* 2 channels */
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x38);
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x38);
 			}
 		} else { /* DDR */
 			XGINew_DataBusWidth = 64; /* 64 bits */
 			XGINew_ChannelAB = 2; /* 2 channels */
-			XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0xA1);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x5A);
+			xgifb_reg_set(pVBInfo->P3c4, 0x13, 0xA1);
+			xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x5A);
 
 			if (XGINew_ReadWriteRest(25, 24, pVBInfo) == 1) {
 				return;
 			} else {
-				XGINew_SetReg1(pVBInfo->P3c4, 0x13, 0x21);
-				XGINew_SetReg1(pVBInfo->P3c4, 0x14, 0x4A);
+				xgifb_reg_set(pVBInfo->P3c4, 0x13, 0x21);
+				xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x4A);
 			}
 		}
 		break;
 	}
 }
 
-int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
+static int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	int i;
 	unsigned short memsize, addr;
 
-	XGINew_SetReg1(pVBInfo->P3c4, 0x15, 0x00); /* noninterleaving */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1C, 0x00); /* nontiling */
+	xgifb_reg_set(pVBInfo->P3c4, 0x15, 0x00); /* noninterleaving */
+	xgifb_reg_set(pVBInfo->P3c4, 0x1C, 0x00); /* nontiling */
 	XGINew_CheckChannel(HwDeviceExtension, pVBInfo);
 
 	if (HwDeviceExtension->jChipType >= XG20) {
@@ -2118,136 +942,29 @@ int XGINew_DDRSizing340(struct xgi_hw_device_info *HwDeviceExtension,
 	return 0;
 }
 
-int XGINew_DDRSizing(struct vb_device_info *pVBInfo)
-{
-	int i;
-	unsigned char j;
-
-	for (i = 0; i < 4; i++) {
-		XGINew_SetDRAMSizingType(i, XGINew_DDRDRAM_TYPE, pVBInfo);
-		XGINew_DisableChannelInterleaving(i, XGINew_DDRDRAM_TYPE, pVBInfo);
-		for (j = 2; j > 0; j--) {
-			XGINew_SetDDRChannel(i, j, XGINew_ChannelAB, XGINew_DDRDRAM_TYPE, pVBInfo);
-			if (!XGINew_SetRank(i, (unsigned char) j, XGINew_ChannelAB, XGINew_DDRDRAM_TYPE, pVBInfo)) {
-				continue;
-			} else {
-				if (XGINew_CheckDDRRanks(j, i, XGINew_DDRDRAM_TYPE, pVBInfo))
-					return 1;
-			}
-		}
-	}
-	return 0;
-}
-
-void XGINew_SetMemoryClock(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x28, pVBInfo->MCLKData[XGINew_RAMType].SR28);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x29, pVBInfo->MCLKData[XGINew_RAMType].SR29);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2A, pVBInfo->MCLKData[XGINew_RAMType].SR2A);
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2E, pVBInfo->ECLKData[XGINew_RAMType].SR2E);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2F, pVBInfo->ECLKData[XGINew_RAMType].SR2F);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x30, pVBInfo->ECLKData[XGINew_RAMType].SR30);
-
-	/* [Vicent] 2004/07/07, When XG42 ECLK = MCLK = 207MHz, Set SR32 D[1:0] = 10b */
-	/* [Hsuan] 2004/08/20, Modify SR32 value, when MCLK=207MHZ, ELCK=250MHz, Set SR32 D[1:0] = 10b */
-	if (HwDeviceExtension->jChipType == XG42) {
-		if ((pVBInfo->MCLKData[XGINew_RAMType].SR28 == 0x1C)
-				&& (pVBInfo->MCLKData[XGINew_RAMType].SR29 == 0x01)
-				&& (((pVBInfo->ECLKData[XGINew_RAMType].SR2E == 0x1C)
-						&& (pVBInfo->ECLKData[XGINew_RAMType].SR2F == 0x01))
-					|| ((pVBInfo->ECLKData[XGINew_RAMType].SR2E == 0x22)
-						&& (pVBInfo->ECLKData[XGINew_RAMType].SR2F == 0x01))))
-			XGINew_SetReg1(pVBInfo->P3c4, 0x32, ((unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x32) & 0xFC) | 0x02);
-	}
-}
-
-unsigned char ChkLFB(struct vb_device_info *pVBInfo)
-{
-	if (LFBDRAMTrap & XGINew_GetReg1(pVBInfo->P3d4, 0x78))
-		return 1;
-	else
-		return 0;
-}
-
-/* --------------------------------------------------------------------- */
-/* input : dx ,valid value : CR or second chip's CR */
-/*  */
-/* SetPowerConsume : */
-/* Description: reduce 40/43 power consumption in first chip or */
-/* in second chip, assume CR A1 D[6]="1" in this case */
-/* output : none */
-/* --------------------------------------------------------------------- */
-void SetPowerConsume(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned long XGI_P3d4Port)
-{
-	unsigned long lTemp;
-	unsigned char bTemp;
-
-	HwDeviceExtension->pQueryVGAConfigSpace(HwDeviceExtension, 0x08, 0, &lTemp); /* Get */
-	if ((lTemp & 0xFF) == 0) {
-		/* set CR58 D[5]=0 D[3]=0 */
-		XGINew_SetRegAND(XGI_P3d4Port, 0x58, 0xD7);
-		bTemp = (unsigned char) XGINew_GetReg1(XGI_P3d4Port, 0xCB);
-		if (bTemp & 0x20) {
-			if (!(bTemp & 0x10))
-				XGINew_SetRegANDOR(XGI_P3d4Port, 0x58, 0xD7, 0x20); /* CR58 D[5]=1 D[3]=0 */
-			else
-				XGINew_SetRegANDOR(XGI_P3d4Port, 0x58, 0xD7, 0x08); /* CR58 D[5]=0 D[3]=1 */
-
-		}
-
-	}
-}
-
-#if 0
-static void XGINew_InitVBIOSData(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
+	unsigned short data;
 
-	/* unsigned long ROMAddr = (unsigned long) HwDeviceExtension->pjVirtualRomBase; */
 	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
 	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-	pVBInfo->ISXPDOS = 0;
 
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */
-	XGI_GetVBType(pVBInfo); /* Run XGI_GetVBType before InitTo330Pointer */
+	XGISetModeNew(HwDeviceExtension, 0x2e);
 
-	switch (HwDeviceExtension->jChipType) {
-	case XG40:
-	case XG41:
-	case XG42:
-	case XG20:
-	case XG21:
-	default:
-		InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-		return;
-	}
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x21);
+	xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data & 0xDF)); /* disable read cache */
+	XGI_DisplayOff(HwDeviceExtension, pVBInfo);
 
+	/* data = xgifb_reg_get(pVBInfo->P3c4, 0x1); */
+	/* data |= 0x20 ; */
+	/* xgifb_reg_set(pVBInfo->P3c4, 0x01, data); *//* Turn OFF Display */
+	XGINew_DDRSizing340(HwDeviceExtension, pVBInfo);
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x21);
+	xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data | 0x20)); /* enable read cache */
 }
-#endif
 
-void ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo)
+static void ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo)
 {
 	volatile unsigned char *pVideoMemory = (unsigned char *) pVBInfo->ROMAddr;
 	unsigned long i;
@@ -2318,185 +1035,31 @@ void ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo)
 						= pVideoMemory[i + 14] | (pVideoMemory[i + 15] << 8);
 				pVBInfo->XG21_LVDSCapList[0].LVDSVSYNC
 						= pVideoMemory[i + 16] | (pVideoMemory[i + 17] << 8);
-				pVBInfo->XG21_LVDSCapList[0].VCLKData1
-						= pVideoMemory[i + 18];
-				pVBInfo->XG21_LVDSCapList[0].VCLKData2
-						= pVideoMemory[i + 19];
-				pVBInfo->XG21_LVDSCapList[0].PSC_S1
-						= pVideoMemory[i + 20];
-				pVBInfo->XG21_LVDSCapList[0].PSC_S2
-						= pVideoMemory[i + 21];
-				pVBInfo->XG21_LVDSCapList[0].PSC_S3
-						= pVideoMemory[i + 22];
-				pVBInfo->XG21_LVDSCapList[0].PSC_S4
-						= pVideoMemory[i + 23];
-				pVBInfo->XG21_LVDSCapList[0].PSC_S5
-						= pVideoMemory[i + 24];
-			}
-		}
-	}
-}
-
-void XGINew_DDR1x_MRS_XG20(unsigned long P3c4, struct vb_device_info *pVBInfo)
-{
-
-	XGINew_SetReg1(P3c4, 0x18, 0x01);
-	XGINew_SetReg1(P3c4, 0x19, 0x40);
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-	DelayUS(60);
-
-	XGINew_SetReg1(P3c4, 0x18, 0x00);
-	XGINew_SetReg1(P3c4, 0x19, 0x40);
-	XGINew_SetReg1(P3c4, 0x16, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x80);
-	DelayUS(60);
-	XGINew_SetReg1(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
-	/* XGINew_SetReg1(P3c4, 0x18, 0x31); */
-	XGINew_SetReg1(P3c4, 0x19, 0x01);
-	XGINew_SetReg1(P3c4, 0x16, 0x03);
-	XGINew_SetReg1(P3c4, 0x16, 0x83);
-	DelayUS(1000);
-	XGINew_SetReg1(P3c4, 0x1B, 0x03);
-	DelayUS(500);
-	/* XGINew_SetReg1(P3c4, 0x18, 0x31); */
-	XGINew_SetReg1(P3c4, 0x18, pVBInfo->SR15[2][XGINew_RAMType]); /* SR18 */
-	XGINew_SetReg1(P3c4, 0x19, 0x00);
-	XGINew_SetReg1(P3c4, 0x16, 0x03);
-	XGINew_SetReg1(P3c4, 0x16, 0x83);
-	XGINew_SetReg1(P3c4, 0x1B, 0x00);
-}
-
-void XGINew_SetDRAMModeRegister_XG20(struct xgi_hw_device_info *HwDeviceExtension)
-{
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-	pVBInfo->ISXPDOS = 0;
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-
-	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-
-	ReadVBIOSTablData(HwDeviceExtension->jChipType, pVBInfo);
-
-	if (XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) == 0)
-		XGINew_DDR1x_MRS_XG20(pVBInfo->P3c4, pVBInfo);
-	else
-		XGINew_DDR2_MRS_XG20(HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1B, 0x03);
-}
-
-void XGINew_SetDRAMModeRegister_XG27(
-		struct xgi_hw_device_info *HwDeviceExtension)
-{
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-	pVBInfo->ISXPDOS = 0;
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-
-	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-
-	ReadVBIOSTablData(HwDeviceExtension->jChipType, pVBInfo);
-
-	if (XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) == 0)
-		XGINew_DDR1x_MRS_XG20(pVBInfo->P3c4, pVBInfo);
-	else
-		/* XGINew_DDR2_MRS_XG27(HwDeviceExtension, pVBInfo->P3c4, pVBInfo); */
-		XGINew_DDRII_Bootup_XG27(HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
-
-	/* XGINew_SetReg1(pVBInfo->P3c4, 0x1B, 0x03); */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1B, pVBInfo->SR15[3][XGINew_RAMType]); /* SR1B */
-
-}
-
-/*
-void XGINew_SetDRAMModeRegister_XG27(struct xgi_hw_device_info *HwDeviceExtension)
-{
-	unsigned char data;
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
-	pVBInfo->BaseAddr = HwDeviceExtension->pjIOAddress;
-	pVBInfo->ISXPDOS = 0;
-
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
-
-	InitTo330Pointer(HwDeviceExtension->jChipType,pVBInfo);
-
-	ReadVBIOSTablData(HwDeviceExtension->jChipType , pVBInfo);
-
-	if (XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) == 0)
-		XGINew_DDR1x_MRS_XG20(pVBInfo->P3c4, pVBInfo);
-	else
-		XGINew_DDR2_MRS_XG27(HwDeviceExtension, pVBInfo->P3c4, pVBInfo);
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1B, 0x03);
+				pVBInfo->XG21_LVDSCapList[0].VCLKData1
+						= pVideoMemory[i + 18];
+				pVBInfo->XG21_LVDSCapList[0].VCLKData2
+						= pVideoMemory[i + 19];
+				pVBInfo->XG21_LVDSCapList[0].PSC_S1
+						= pVideoMemory[i + 20];
+				pVBInfo->XG21_LVDSCapList[0].PSC_S2
+						= pVideoMemory[i + 21];
+				pVBInfo->XG21_LVDSCapList[0].PSC_S3
+						= pVideoMemory[i + 22];
+				pVBInfo->XG21_LVDSCapList[0].PSC_S4
+						= pVideoMemory[i + 23];
+				pVBInfo->XG21_LVDSCapList[0].PSC_S5
+						= pVideoMemory[i + 24];
+			}
+		}
+	}
 }
-*/
 
-void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short tempbx = 0, temp, tempcx, CR3CData;
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x32);
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x32);
 
 	if (temp & Monitor1Sense)
 		tempbx |= ActiveCRT1;
@@ -2518,11 +1081,11 @@ void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
 			tempbx |= (ActiveYPbPr << 8);
 	}
 
-	tempcx = XGINew_GetReg1(pVBInfo->P3d4, 0x3d);
-	tempcx |= (XGINew_GetReg1(pVBInfo->P3d4, 0x3e) << 8);
+	tempcx = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
+	tempcx |= (xgifb_reg_get(pVBInfo->P3d4, 0x3e) << 8);
 
 	if (tempbx & tempcx) {
-		CR3CData = XGINew_GetReg1(pVBInfo->P3d4, 0x3c);
+		CR3CData = xgifb_reg_get(pVBInfo->P3d4, 0x3c);
 		if (!(CR3CData & DisplayDeviceFromCMOS)) {
 			tempcx = 0x1FF0;
 			if (*pVBInfo->pSoftSetting & ModeSoftSetting)
@@ -2535,18 +1098,18 @@ void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,
 	}
 
 	tempbx &= tempcx;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x3d, (tempbx & 0x00FF));
-	XGINew_SetReg1(pVBInfo->P3d4, 0x3e, ((tempbx & 0xFF00) >> 8));
+	xgifb_reg_set(pVBInfo->P3d4, 0x3d, (tempbx & 0x00FF));
+	xgifb_reg_set(pVBInfo->P3d4, 0x3e, ((tempbx & 0xFF00) >> 8));
 }
 
-void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short temp, tempcl = 0, tempch = 0, CR31Data, CR38Data;
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x3d);
-	temp |= XGINew_GetReg1(pVBInfo->P3d4, 0x3e) << 8;
-	temp |= (XGINew_GetReg1(pVBInfo->P3d4, 0x31) & (DriverMode >> 8)) << 8;
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
+	temp |= xgifb_reg_get(pVBInfo->P3d4, 0x3e) << 8;
+	temp |= (xgifb_reg_get(pVBInfo->P3d4, 0x31) & (DriverMode >> 8)) << 8;
 
 	if (pVBInfo->IF_DEF_CRT2Monitor == 1) {
 		if (temp & ActiveCRT2)
@@ -2603,25 +1166,25 @@ void XGINew_SetModeScratch(struct xgi_hw_device_info *HwDeviceExtension,
 		tempcl ^= (SetSimuScanMode | SwitchToCRT2);
 	if ((temp & ActiveLCD) && (temp & ActiveTV))
 		tempcl ^= (SetSimuScanMode | SwitchToCRT2);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x30, tempcl);
+	xgifb_reg_set(pVBInfo->P3d4, 0x30, tempcl);
 
-	CR31Data = XGINew_GetReg1(pVBInfo->P3d4, 0x31);
+	CR31Data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
 	CR31Data &= ~(SetNotSimuMode >> 8);
 	if (!(temp & ActiveCRT1))
 		CR31Data |= (SetNotSimuMode >> 8);
 	CR31Data &= ~(DisableCRT2Display >> 8);
 	if (!((temp & ActiveLCD) || (temp & ActiveTV) || (temp & ActiveCRT2)))
 		CR31Data |= (DisableCRT2Display >> 8);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x31, CR31Data);
+	xgifb_reg_set(pVBInfo->P3d4, 0x31, CR31Data);
 
-	CR38Data = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
+	CR38Data = xgifb_reg_get(pVBInfo->P3d4, 0x38);
 	CR38Data &= ~SetYPbPr;
 	CR38Data |= tempch;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x38, CR38Data);
+	xgifb_reg_set(pVBInfo->P3d4, 0x38, CR38Data);
 
 }
 
-void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char Temp;
@@ -2633,83 +1196,421 @@ void XGINew_GetXG21Sense(struct xgi_hw_device_info *HwDeviceExtension,
 #if 1
 	if ((pVideoMemory[0x65] & 0x01)) { /* For XG21 LVDS */
 		pVBInfo->IF_DEF_LVDS = 1;
-		XGINew_SetRegOR(pVBInfo->P3d4, 0x32, LCDSense);
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0); /* LVDS on chip */
+		xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0); /* LVDS on chip */
 	} else {
 #endif
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x4A, ~0x03, 0x03); /* Enable GPIOA/B read  */
-		Temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48) & 0xC0;
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x03, 0x03); /* Enable GPIOA/B read  */
+		Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0xC0;
 		if (Temp == 0xC0) { /* DVI & DVO GPIOA/B pull high */
 			XGINew_SenseLCD(HwDeviceExtension, pVBInfo);
-			XGINew_SetRegOR(pVBInfo->P3d4, 0x32, LCDSense);
-			XGINew_SetRegANDOR(pVBInfo->P3d4, 0x4A, ~0x20, 0x20); /* Enable read GPIOF */
-			Temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48) & 0x04;
+			xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
+			xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x20, 0x20); /* Enable read GPIOF */
+			Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0x04;
 			if (!Temp)
-				XGINew_SetRegANDOR(pVBInfo->P3d4, 0x38, ~0xE0, 0x80); /* TMDS on chip */
+				xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0x80); /* TMDS on chip */
 			else
-				XGINew_SetRegANDOR(pVBInfo->P3d4, 0x38, ~0xE0, 0xA0); /* Only DVO on chip */
-			XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x20); /* Disable read GPIOF */
+				xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xA0); /* Only DVO on chip */
+			xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x20); /* Disable read GPIOF */
 		}
 #if 1
 	}
 #endif
 }
 
-void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGINew_GetXG27Sense(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char Temp, bCR4A;
 
 	pVBInfo->IF_DEF_LVDS = 0;
-	bCR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x4A, ~0x07, 0x07); /* Enable GPIOA/B/C read  */
-	Temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48) & 0x07;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4A, bCR4A);
+	bCR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x07, 0x07); /* Enable GPIOA/B/C read  */
+	Temp = xgifb_reg_get(pVBInfo->P3d4, 0x48) & 0x07;
+	xgifb_reg_set(pVBInfo->P3d4, 0x4A, bCR4A);
 
 	if (Temp <= 0x02) {
 		pVBInfo->IF_DEF_LVDS = 1;
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0); /* LVDS setting */
-		XGINew_SetReg1(pVBInfo->P3d4, 0x30, 0x21);
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xC0); /* LVDS setting */
+		xgifb_reg_set(pVBInfo->P3d4, 0x30, 0x21);
 	} else {
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x38, ~0xE0, 0xA0); /* TMDS/DVO setting */
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x38, ~0xE0, 0xA0); /* TMDS/DVO setting */
 	}
-	XGINew_SetRegOR(pVBInfo->P3d4, 0x32, LCDSense);
+	xgifb_reg_or(pVBInfo->P3d4, 0x32, LCDSense);
 
 }
 
-unsigned char GetXG21FPBits(struct vb_device_info *pVBInfo)
+static unsigned char GetXG21FPBits(struct vb_device_info *pVBInfo)
 {
 	unsigned char CR38, CR4A, temp;
 
-	CR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x4A, ~0x10, 0x10); /* enable GPIOE read */
-	CR38 = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
+	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x10, 0x10); /* enable GPIOE read */
+	CR38 = xgifb_reg_get(pVBInfo->P3d4, 0x38);
 	temp = 0;
 	if ((CR38 & 0xE0) > 0x80) {
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48);
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
 		temp &= 0x08;
 		temp >>= 3;
 	}
 
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4A, CR4A);
+	xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
 
 	return temp;
 }
 
-unsigned char GetXG27FPBits(struct vb_device_info *pVBInfo)
+static unsigned char GetXG27FPBits(struct vb_device_info *pVBInfo)
 {
 	unsigned char CR4A, temp;
 
-	CR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x4A, ~0x03, 0x03); /* enable GPIOA/B/C read */
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48);
+	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x4A, ~0x03, 0x03); /* enable GPIOA/B/C read */
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
 	if (temp <= 2)
 		temp &= 0x03;
 	else
 		temp = ((temp & 0x04) >> 1) || ((~temp) & 0x01);
 
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4A, CR4A);
+	xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
 
 	return temp;
 }
 
+unsigned char XGIInitNew(struct xgi_hw_device_info *HwDeviceExtension)
+{
+	struct vb_device_info VBINF;
+	struct vb_device_info *pVBInfo = &VBINF;
+	unsigned char i, temp = 0, temp1;
+	/* VBIOSVersion[5]; */
+	volatile unsigned char *pVideoMemory;
+
+	/* unsigned long j, k; */
+
+	unsigned long Temp;
+
+	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
+
+	pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress;
+
+	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
+
+	pVideoMemory = (unsigned char *) pVBInfo->ROMAddr;
+
+	/* Newdebugcode(0x99); */
+
+
+	/* if (pVBInfo->ROMAddr == 0) */
+	/* return(0); */
+
+	if (pVBInfo->FBAddr == NULL) {
+		printk("\n pVBInfo->FBAddr == 0 ");
+		return 0;
+	}
+	printk("1");
+	if (pVBInfo->BaseAddr == 0) {
+		printk("\npVBInfo->BaseAddr == 0 ");
+		return 0;
+	}
+	printk("2");
+
+	outb(0x67, (pVBInfo->BaseAddr + 0x12)); /* 3c2 <- 67 ,ynlai */
+
+	pVBInfo->ISXPDOS = 0;
+	printk("3");
+
+	printk("4");
+
+	/* VBIOSVersion[4] = 0x0; */
+
+	/* 09/07/99 modify by domao */
+
+	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
+	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
+	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
+	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
+	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
+	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
+	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
+	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
+	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
+	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
+	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
+	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
+	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
+	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
+	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
+	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
+	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
+	printk("5");
+
+	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */
+		XGI_GetVBType(pVBInfo); /* Run XGI_GetVBType before InitTo330Pointer */
+
+	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
+
+	/* ReadVBIOSData */
+	ReadVBIOSTablData(HwDeviceExtension->jChipType, pVBInfo);
+
+	/* 1.Openkey */
+	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
+	printk("6");
+
+	/* GetXG21Sense (GPIO) */
+	if (HwDeviceExtension->jChipType == XG21)
+		XGINew_GetXG21Sense(HwDeviceExtension, pVBInfo);
+
+	if (HwDeviceExtension->jChipType == XG27)
+		XGINew_GetXG27Sense(HwDeviceExtension, pVBInfo);
+
+	printk("7");
+
+	/* 2.Reset Extended register */
+
+	for (i = 0x06; i < 0x20; i++)
+		xgifb_reg_set(pVBInfo->P3c4, i, 0);
+
+	for (i = 0x21; i <= 0x27; i++)
+		xgifb_reg_set(pVBInfo->P3c4, i, 0);
+
+	/* for(i = 0x06; i <= 0x27; i++) */
+	/* xgifb_reg_set(pVBInfo->P3c4, i, 0); */
+
+	printk("8");
+
+	for (i = 0x31; i <= 0x3B; i++)
+		xgifb_reg_set(pVBInfo->P3c4, i, 0);
+	printk("9");
+
+	if (HwDeviceExtension->jChipType == XG42) /* [Hsuan] 2004/08/20 Auto over driver for XG42 */
+		xgifb_reg_set(pVBInfo->P3c4, 0x3B, 0xC0);
+
+	/* for (i = 0x30; i <= 0x3F; i++) */
+	/* xgifb_reg_set(pVBInfo->P3d4, i, 0); */
+
+	for (i = 0x79; i <= 0x7C; i++)
+		xgifb_reg_set(pVBInfo->P3d4, i, 0); /* shampoo 0208 */
+
+	printk("10");
+
+	if (HwDeviceExtension->jChipType >= XG20)
+		xgifb_reg_set(pVBInfo->P3d4, 0x97, *pVBInfo->pXGINew_CR97);
+
+	/* 3.SetMemoryClock
+
+	 XGINew_RAMType = (int)XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
+	*/
+
+	printk("11");
+
+	/* 4.SetDefExt1Regs begin */
+	xgifb_reg_set(pVBInfo->P3c4, 0x07, *pVBInfo->pSR07);
+	if (HwDeviceExtension->jChipType == XG27) {
+		xgifb_reg_set(pVBInfo->P3c4, 0x40, *pVBInfo->pSR40);
+		xgifb_reg_set(pVBInfo->P3c4, 0x41, *pVBInfo->pSR41);
+	}
+	xgifb_reg_set(pVBInfo->P3c4, 0x11, 0x0F);
+	xgifb_reg_set(pVBInfo->P3c4, 0x1F, *pVBInfo->pSR1F);
+	/* xgifb_reg_set(pVBInfo->P3c4, 0x20, 0x20); */
+	xgifb_reg_set(pVBInfo->P3c4, 0x20, 0xA0); /* alan, 2001/6/26 Frame buffer can read/write SR20 */
+	xgifb_reg_set(pVBInfo->P3c4, 0x36, 0x70); /* Hsuan, 2006/01/01 H/W request for slow corner chip */
+	if (HwDeviceExtension->jChipType == XG27) /* Alan 12/07/2006 */
+		xgifb_reg_set(pVBInfo->P3c4, 0x36, *pVBInfo->pSR36);
+
+	/* SR11 = 0x0F; */
+	/* xgifb_reg_set(pVBInfo->P3c4, 0x11, SR11); */
+
+	printk("12");
+
+	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
+		/* Set AGP Rate */
+		/*
+		temp1 = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
+		temp1 &= 0x02;
+		if (temp1 == 0x02) {
+			outl(0x80000000, 0xcf8);
+			ChipsetID = inl(0x0cfc);
+			outl(0x8000002C, 0xcf8);
+			VendorID = inl(0x0cfc);
+			VendorID &= 0x0000FFFF;
+			outl(0x8001002C, 0xcf8);
+			GraphicVendorID = inl(0x0cfc);
+			GraphicVendorID &= 0x0000FFFF;
+
+			if (ChipsetID == 0x7301039)
+				xgifb_reg_set(pVBInfo->P3d4, 0x5F, 0x09);
+
+			ChipsetID &= 0x0000FFFF;
+
+			if ((ChipsetID == 0x700E) || (ChipsetID == 0x1022) || (ChipsetID == 0x1106) || (ChipsetID == 0x10DE)) {
+				if (ChipsetID == 0x1106) {
+					if ((VendorID == 0x1019) && (GraphicVendorID == 0x1019))
+						xgifb_reg_set(pVBInfo->P3d4, 0x5F, 0x0D);
+					else
+						xgifb_reg_set(pVBInfo->P3d4, 0x5F, 0x0B);
+				} else {
+					xgifb_reg_set(pVBInfo->P3d4, 0x5F, 0x0B);
+				}
+			}
+		}
+		*/
+
+		printk("13");
+
+		/* Set AGP customize registers (in SetDefAGPRegs) Start */
+		for (i = 0x47; i <= 0x4C; i++)
+			xgifb_reg_set(pVBInfo->P3d4, i, pVBInfo->AGPReg[i - 0x47]);
+
+		for (i = 0x70; i <= 0x71; i++)
+			xgifb_reg_set(pVBInfo->P3d4, i, pVBInfo->AGPReg[6 + i - 0x70]);
+
+		for (i = 0x74; i <= 0x77; i++)
+			xgifb_reg_set(pVBInfo->P3d4, i, pVBInfo->AGPReg[8 + i - 0x74]);
+		/* Set AGP customize registers (in SetDefAGPRegs) End */
+		/* [Hsuan]2004/12/14 AGP Input Delay Adjustment on 850 */
+		/*        outl(0x80000000, 0xcf8); */
+		/*        ChipsetID = inl(0x0cfc); */
+		/*        if (ChipsetID == 0x25308086) */
+		/*            xgifb_reg_set(pVBInfo->P3d4, 0x77, 0xF0); */
+
+		HwDeviceExtension->pQueryVGAConfigSpace(HwDeviceExtension, 0x50, 0, &Temp); /* Get */
+		Temp >>= 20;
+		Temp &= 0xF;
+
+		if (Temp == 1)
+			xgifb_reg_set(pVBInfo->P3d4, 0x48, 0x20); /* CR48 */
+		printk("14");
+	} /* != XG20 */
+
+	/* Set PCI */
+	xgifb_reg_set(pVBInfo->P3c4, 0x23, *pVBInfo->pSR23);
+	xgifb_reg_set(pVBInfo->P3c4, 0x24, *pVBInfo->pSR24);
+	xgifb_reg_set(pVBInfo->P3c4, 0x25, pVBInfo->SR25[0]);
+	printk("15");
+
+	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
+		/* Set VB */
+		XGI_UnLockCRT2(HwDeviceExtension, pVBInfo);
+		xgifb_reg_and_or(pVBInfo->Part0Port, 0x3F, 0xEF, 0x00); /* alan, disable VideoCapture */
+		xgifb_reg_set(pVBInfo->Part1Port, 0x00, 0x00);
+		temp1 = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x7B); /* chk if BCLK>=100MHz */
+		temp = (unsigned char) ((temp1 >> 4) & 0x0F);
+
+		xgifb_reg_set(pVBInfo->Part1Port, 0x02, (*pVBInfo->pCRT2Data_1_2));
+
+		printk("16");
+
+		xgifb_reg_set(pVBInfo->Part1Port, 0x2E, 0x08); /* use VB */
+	} /* != XG20 */
+
+	xgifb_reg_set(pVBInfo->P3c4, 0x27, 0x1F);
+
+	if ((HwDeviceExtension->jChipType == XG42)
+			&& XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo) != 0) { /* Not DDR */
+		xgifb_reg_set(pVBInfo->P3c4, 0x31, (*pVBInfo->pSR31 & 0x3F) | 0x40);
+		xgifb_reg_set(pVBInfo->P3c4, 0x32, (*pVBInfo->pSR32 & 0xFC) | 0x01);
+	} else {
+		xgifb_reg_set(pVBInfo->P3c4, 0x31, *pVBInfo->pSR31);
+		xgifb_reg_set(pVBInfo->P3c4, 0x32, *pVBInfo->pSR32);
+	}
+	xgifb_reg_set(pVBInfo->P3c4, 0x33, *pVBInfo->pSR33);
+	printk("17");
+
+	/*
+	 SetPowerConsume (HwDeviceExtension, pVBInfo->P3c4);	*/
+
+	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
+		if (XGI_BridgeIsOn(pVBInfo) == 1) {
+			if (pVBInfo->IF_DEF_LVDS == 0) {
+				xgifb_reg_set(pVBInfo->Part2Port, 0x00, 0x1C);
+				xgifb_reg_set(pVBInfo->Part4Port, 0x0D, *pVBInfo->pCRT2Data_4_D);
+				xgifb_reg_set(pVBInfo->Part4Port, 0x0E, *pVBInfo->pCRT2Data_4_E);
+				xgifb_reg_set(pVBInfo->Part4Port, 0x10, *pVBInfo->pCRT2Data_4_10);
+				xgifb_reg_set(pVBInfo->Part4Port, 0x0F, 0x3F);
+			}
+
+			XGI_LockCRT2(HwDeviceExtension, pVBInfo);
+		}
+	} /* != XG20 */
+	printk("18");
+
+	printk("181");
+
+	printk("182");
+
+	XGI_SenseCRT1(pVBInfo);
+
+	printk("183");
+	/* XGINew_DetectMonitor(HwDeviceExtension); */
+	pVBInfo->IF_DEF_CH7007 = 0;
+	if ((HwDeviceExtension->jChipType == XG21) && (pVBInfo->IF_DEF_CH7007)) {
+		printk("184");
+		XGI_GetSenseStatus(HwDeviceExtension, pVBInfo); /* sense CRT2 */
+		printk("185");
+
+	}
+	if (HwDeviceExtension->jChipType == XG21) {
+		printk("186");
+
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, ~Monitor1Sense, Monitor1Sense); /* Z9 default has CRT */
+		temp = GetXG21FPBits(pVBInfo);
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~0x01, temp);
+		printk("187");
+
+	}
+	if (HwDeviceExtension->jChipType == XG27) {
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, ~Monitor1Sense, Monitor1Sense); /* Z9 default has CRT */
+		temp = GetXG27FPBits(pVBInfo);
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x37, ~0x03, temp);
+	}
+	printk("19");
+
+	XGINew_RAMType = (int) XGINew_GetXG20DRAMType(HwDeviceExtension, pVBInfo);
+
+	XGINew_SetDRAMDefaultRegister340(HwDeviceExtension, pVBInfo->P3d4, pVBInfo);
+
+	printk("20");
+	XGINew_SetDRAMSize_340(HwDeviceExtension, pVBInfo);
+	printk("21");
+
+	printk("22");
+
+	/* SetDefExt2Regs begin */
+	/*
+	AGP = 1;
+	temp = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x3A);
+	temp &= 0x30;
+	if (temp == 0x30)
+		AGP = 0;
+
+	if (AGP == 0)
+		*pVBInfo->pSR21 &= 0xEF;
+
+	xgifb_reg_set(pVBInfo->P3c4, 0x21, *pVBInfo->pSR21);
+	if (AGP == 1)
+		*pVBInfo->pSR22 &= 0x20;
+	xgifb_reg_set(pVBInfo->P3c4, 0x22, *pVBInfo->pSR22);
+	*/
+	/* base = 0x80000000; */
+	/* OutPortLong(0xcf8, base); */
+	/* Temp = (InPortLong(0xcfc) & 0xFFFF); */
+	/* if (Temp == 0x1039) { */
+	xgifb_reg_set(pVBInfo->P3c4, 0x22, (unsigned char) ((*pVBInfo->pSR22) & 0xFE));
+	/* } else { */
+	/*	xgifb_reg_set(pVBInfo->P3c4, 0x22, *pVBInfo->pSR22); */
+	/* } */
+
+	xgifb_reg_set(pVBInfo->P3c4, 0x21, *pVBInfo->pSR21);
+
+	printk("23");
+
+	XGINew_ChkSenseStatus(HwDeviceExtension, pVBInfo);
+	XGINew_SetModeScratch(HwDeviceExtension, pVBInfo);
+
+	printk("24");
+
+	xgifb_reg_set(pVBInfo->P3d4, 0x8c, 0x87);
+	xgifb_reg_set(pVBInfo->P3c4, 0x14, 0x31);
+	printk("25");
+
+	return 1;
+} /* end of init */
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index e19b932..8762a53 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -1,5 +1,6 @@
 
 #include <asm/io.h>
+#include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/version.h>
 #include "XGIfb.h"
@@ -10,7 +11,7 @@
 #include "vb_struct.h"
 #include "vb_util.h"
 #include "vb_table.h"
-
+#include "vb_setmode.h"
 
 
 #define  IndexMask 0xff
@@ -18,180 +19,6 @@
 #define XGI_MASK_DUAL_CHIP	  0x04  /* SR3A */
 #endif
 
-
-
-unsigned char  XGI_IsLCDDualLink(struct vb_device_info *pVBInfo);
-unsigned char  XGI_SetCRT2Group301(unsigned short ModeNo,
-			struct xgi_hw_device_info *HwDeviceExtension,
-			struct vb_device_info *pVBInfo);
-unsigned char  XGI_BacklightByDrv(struct vb_device_info *pVBInfo);
-
-unsigned char  XGI_IsLCDON(struct vb_device_info *pVBInfo);
-unsigned char  XGI_DisableChISLCD(struct vb_device_info *pVBInfo);
-unsigned char  XGI_EnableChISLCD(struct vb_device_info *pVBInfo);
-unsigned char  XGI_AjustCRT2Rate(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			unsigned short RefreshRateTableIndex,
-			unsigned short *i, struct vb_device_info *pVBInfo);
-unsigned char  XGI_SearchModeID(unsigned short ModeNo,
-			unsigned short *ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-unsigned char  XGI_GetLCDInfo(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-unsigned char  XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
-			unsigned short ModeNo);
-unsigned char  XGI_BridgeIsOn(struct vb_device_info *pVBInfo);
-unsigned char  XGI_GetModePtr(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-unsigned short XGI_GetOffset(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			unsigned short RefreshRateTableIndex,
-			struct xgi_hw_device_info *HwDeviceExtension,
-			struct vb_device_info *pVBInfo);
-unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
-			unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-unsigned short XGI_GetResInfo(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-unsigned short XGI_GetColorDepth(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo);
-unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			unsigned short RefreshRateTableIndex,
-			struct xgi_hw_device_info *HwDeviceExtension,
-			struct vb_device_info *pVBInfo);
-void     XGI_VBLongWait(struct vb_device_info *pVBInfo);
-void     XGI_SaveCRT2Info(unsigned short ModeNo, struct vb_device_info *pVBInfo);
-void     XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     *XGI_GetLcdPtr(unsigned short BX,  unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_FirePWDEnable(struct vb_device_info *pVBInfo);
-void     XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo);
-void     XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl, struct vb_device_info *pVBInfo);
-void     XGI_EnablePWD(struct vb_device_info *pVBInfo);
-void     XGI_DisablePWD(struct vb_device_info *pVBInfo);
-void     XGI_AutoThreshold(struct vb_device_info *pVBInfo);
-void     XGI_SetTap4Regs(struct vb_device_info *pVBInfo);
-
-void     XGI_DisplayOn(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGI_DisplayOff(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetXG21LCD(struct vb_device_info *pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
-void     XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetXG27LCD(struct vb_device_info *pVBInfo, unsigned short RefreshRateTableIndex, unsigned short ModeNo);
-void	 XGI_UpdateXG21CRTC(unsigned short ModeNo, struct vb_device_info *pVBInfo, unsigned short RefreshRateTableIndex);
-void     XGI_WaitDisply(struct vb_device_info *pVBInfo);
-void     XGI_SenseCRT1(struct vb_device_info *pVBInfo);
-void     XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetMiscRegs(unsigned short StandTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short StandTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetGRCRegs(unsigned short StandTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_ClearExt1Regs(struct vb_device_info *pVBInfo);
-
-void     XGI_SetSync(unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
-void     XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo, struct xgi_hw_device_info *HwDeviceExtension);
-void     XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1FIFO(unsigned short ModeNo, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-
-void     XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al, unsigned short dh, struct vb_device_info *pVBInfo);
-/*void     XGI_ClearBuffer(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, struct vb_device_info *pVBInfo);*/
-void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-void     XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo);
-void     XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
-			unsigned short RefreshRateTableIndex,
-			struct xgi_hw_device_info *HwDeviceExtension,
-			struct vb_device_info *pVBInfo);
-void     XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_GetVBType(struct vb_device_info *pVBInfo);
-void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     InitTo330Pointer(unsigned char, struct vb_device_info *pVBInfo);
-void     XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth, struct vb_device_info *pVBInfo);
-void     XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetDelayComp(struct vb_device_info *pVBInfo);
-void     XGI_SetLCDCap(struct vb_device_info *pVBInfo);
-void     XGI_SetLCDCap_A(unsigned short tempcx, struct vb_device_info *pVBInfo);
-void     XGI_SetLCDCap_B(unsigned short tempcx, struct vb_device_info *pVBInfo);
-void     SetSpectrum(struct vb_device_info *pVBInfo);
-void     XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetPhaseIncr(struct vb_device_info *pVBInfo);
-void     XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char* tempcl,
-			unsigned char *tempch, struct vb_device_info *pVBInfo);
-unsigned short   XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo);
-void     XGI_SetCRT2ModeRegs(unsigned short ModeNo, struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGI_CloseCRTC(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGI_OpenCRTC(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct vb_device_info *pVBInfo);
-void     XGI_UnLockCRT2(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGI_LockCRT2(struct xgi_hw_device_info *, struct vb_device_info *pVBInfo);
-void     XGINew_EnableCRT2(struct vb_device_info *pVBInfo);
-void     XGINew_LCD_Wait_Time(unsigned char DelayTime, struct vb_device_info *pVBInfo);
-void     XGI_LongWait(struct vb_device_info *pVBInfo);
-void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *pVBInfo);
-void     XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
-			struct vb_device_info *pVBInfo);
-unsigned char    XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
-			unsigned short ModeNo,
-			unsigned short ModeIdIndex,
-			struct vb_device_info *pVBInfo);
-void     XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
-			unsigned char *di_1, struct vb_device_info *pVBInfo);
-unsigned short   XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo);
-unsigned short   XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo);
-struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx, struct vb_device_info *pVBInfo);
-void     XGI_SetXG21FPBits(struct vb_device_info *pVBInfo);
-void     XGI_SetXG27FPBits(struct vb_device_info *pVBInfo);
-unsigned char    XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo);
-unsigned char    XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo);
-void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
-void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
-void     XGI_XG21SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo);
-unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-void     XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-unsigned char  XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo);
-
-extern void ReadVBIOSTablData(unsigned char ChipType, struct vb_device_info *pVBInfo);
-
-/* unsigned short XGINew_flag_clearbuffer; 0: no clear frame buffer 1:clear frame buffer */
-
-
 static unsigned short XGINew_MDA_DAC[] = {
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
@@ -247,18 +74,8 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 	/* XGINew_UBLCDDataTable = (struct XGI_LCDDataTablStruct *) XGI_LCDDataTable; */
 	/* XGINew_UBTVDataTable = (XGI_TVDataTablStruct *) XGI_TVDataTable; */
 
-	if (ChipType >= XG40) {
-		pVBInfo->MCLKData
-			= (struct XGI_MCLKDataStruct *) XGI340New_MCLKData;
-		pVBInfo->ECLKData
-			= (struct XGI_ECLKDataStruct *) XGI340_ECLKData;
-	} else {
-		pVBInfo->MCLKData
-			= (struct XGI_MCLKDataStruct *) XGI330New_MCLKData;
-		pVBInfo->ECLKData
-			= (struct XGI_ECLKDataStruct *) XGI330_ECLKData;
-	}
-
+	pVBInfo->MCLKData = (struct XGI_MCLKDataStruct *) XGI340New_MCLKData;
+	pVBInfo->ECLKData = (struct XGI_ECLKDataStruct *) XGI340_ECLKData;
 	pVBInfo->VCLKData = (struct XGI_VCLKDataStruct *) XGI_VCLKData;
 	pVBInfo->VBVCLKData = (struct XGI_VBVCLKDataStruct *) XGI_VBVCLKData;
 	pVBInfo->ScreenOffset = XGI330_ScreenOffset;
@@ -373,1582 +190,1382 @@ void InitTo330Pointer(unsigned char ChipType, struct vb_device_info *pVBInfo)
 
 }
 
-unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
-			unsigned short ModeNo)
+static unsigned char XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned short ModeIdIndex;
-	/* unsigned char *pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress; */
-	struct vb_device_info VBINF;
-	struct vb_device_info *pVBInfo = &VBINF;
-	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
-	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
-	pVBInfo->IF_DEF_LVDS = 0;
-	pVBInfo->IF_DEF_CH7005 = 0;
-	pVBInfo->IF_DEF_LCDA = 1;
-	pVBInfo->IF_DEF_CH7017 = 0;
-	pVBInfo->IF_DEF_CH7007 = 0; /* [Billy] 2007/05/14 */
-	pVBInfo->IF_DEF_VideoCapture = 0;
-	pVBInfo->IF_DEF_ScaleLCD = 0;
-	pVBInfo->IF_DEF_OEMUtil = 0;
-	pVBInfo->IF_DEF_PWD = 0;
+	unsigned char index;
 
-	if (HwDeviceExtension->jChipType >= XG20) { /* kuku 2004/06/25 */
-		pVBInfo->IF_DEF_YPbPr = 0;
-		pVBInfo->IF_DEF_HiVision = 0;
-		pVBInfo->IF_DEF_CRT2Monitor = 0;
-		pVBInfo->VBType = 0; /*set VBType default 0*/
-	} else if (HwDeviceExtension->jChipType >= XG40) {
-		pVBInfo->IF_DEF_YPbPr = 1;
-		pVBInfo->IF_DEF_HiVision = 1;
-		pVBInfo->IF_DEF_CRT2Monitor = 1;
-	} else {
-		pVBInfo->IF_DEF_YPbPr = 1;
-		pVBInfo->IF_DEF_HiVision = 1;
-		pVBInfo->IF_DEF_CRT2Monitor = 0;
+	if (ModeNo <= 0x13)
+		index = pVBInfo->SModeIDTable[ModeIdIndex].St_StTableIndex;
+	else {
+		if (pVBInfo->ModeType <= 0x02)
+			index = 0x1B; /* 02 -> ModeEGA */
+		else
+			index = 0x0F;
 	}
+	return index; /* Get pVBInfo->StandTable index */
+}
 
-	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
-	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
-	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
-	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
-	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
-	pVBInfo->P3cc = pVBInfo->BaseAddr + 0x1C;
-	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
-	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
-	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
-	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
-	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
-	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
-	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
-	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
-	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
-	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
-	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
-	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
+/*
+unsigned char XGI_SetBIOSData(unsigned short ModeNo, unsigned short ModeIdIndex) {
+	return (0);
+}
+*/
 
-	if (HwDeviceExtension->jChipType == XG21) { /* for x86 Linux, XG21 LVDS */
-		if ((XGINew_GetReg1(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0)
-			pVBInfo->IF_DEF_LVDS = 1;
-	}
-	if (HwDeviceExtension->jChipType == XG27) {
-		if ((XGINew_GetReg1(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0) {
-			if (XGINew_GetReg1(pVBInfo->P3d4, 0x30) & 0x20)
-				pVBInfo->IF_DEF_LVDS = 1;
+/* unsigned char XGI_ClearBankRegs(unsigned short ModeNo, unsigned short ModeIdIndex) {
+	return( 0 ) ;
+}
+*/
+
+static void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+{
+	unsigned char tempah, SRdata;
+
+	unsigned short i, modeflag;
+
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+	xgifb_reg_set(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */
+	tempah = pVBInfo->StandTable[StandTableIndex].SR[0];
+
+	i = SetCRT2ToLCDA;
+	if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+		tempah |= 0x01;
+	} else {
+		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
+			if (pVBInfo->VBInfo & SetInSlaveMode)
+				tempah |= 0x01;
 		}
 	}
 
-	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */
-		XGI_GetVBType(pVBInfo);
+	tempah |= 0x20; /* screen off */
+	xgifb_reg_set(pVBInfo->P3c4, 0x01, tempah); /* Set SR1 */
 
-	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
-	if (ModeNo & 0x80) {
-		ModeNo = ModeNo & 0x7F;
-		/* XGINew_flag_clearbuffer = 0; */
+	for (i = 02; i <= 04; i++) {
+		SRdata = pVBInfo->StandTable[StandTableIndex].SR[i - 1]; /* Get SR2,3,4 from file */
+		xgifb_reg_set(pVBInfo->P3c4, i, SRdata); /* Set SR2 3 4 */
 	}
-	/* else {
-		XGINew_flag_clearbuffer = 1;
+}
+
+static void XGI_SetMiscRegs(unsigned short StandTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned char Miscdata;
+
+	Miscdata = pVBInfo->StandTable[StandTableIndex].MISC; /* Get Misc from file */
+	/*
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
+		if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+			Miscdata |= 0x0C;
+		}
 	}
 	*/
-	XGINew_SetReg1(pVBInfo->P3c4, 0x05, 0x86);
 
-	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 1.Openkey */
-		XGI_UnLockCRT2(HwDeviceExtension, pVBInfo);
+	outb(Miscdata, pVBInfo->P3c2); /* Set Misc(3c2) */
+}
 
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
+static void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short StandTableIndex, struct vb_device_info *pVBInfo)
+{
+	unsigned char CRTCdata;
+	unsigned short i;
 
-	XGI_GetVGAType(HwDeviceExtension, pVBInfo);
+	CRTCdata = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
+	CRTCdata &= 0x7f;
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, CRTCdata); /* Unlock CRTC */
 
-	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
-		XGI_GetVBInfo(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo);
-		XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo);
-		XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo);
-		XGI_DisableBridge(HwDeviceExtension, pVBInfo);
-		/* XGI_OpenCRTC(HwDeviceExtension, pVBInfo); */
+	for (i = 0; i <= 0x18; i++) {
+		CRTCdata = pVBInfo->StandTable[StandTableIndex].CRTC[i]; /* Get CRTC from file */
+		xgifb_reg_set(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
+	}
+	/*
+	if ((HwDeviceExtension->jChipType == XGI_630) && (HwDeviceExtension->jChipRevision == 0x30)) {
+		if (pVBInfo->VBInfo & SetInSlaveMode) {
+			if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+				xgifb_reg_set(pVBInfo->P3d4, 0x18, 0xFE);
+			}
+		}
+	}
+	*/
+}
 
-		if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) {
-			XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
-					ModeIdIndex, pVBInfo);
+static void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
+		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+{
+	unsigned char ARdata;
+	unsigned short i, modeflag;
 
-			if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-				XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
-						HwDeviceExtension, pVBInfo);
-			}
-		} else {
-			if (!(pVBInfo->VBInfo & SwitchToCRT2)) {
-				XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
-						ModeIdIndex, pVBInfo);
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+
+	for (i = 0; i <= 0x13; i++) {
+		ARdata = pVBInfo->StandTable[StandTableIndex].ATTR[i];
+		if (modeflag & Charx8Dot) { /* ifndef Dot9 */
+			if (i == 0x13) {
 				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-					XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
-							HwDeviceExtension,
-							pVBInfo);
+					ARdata = 0;
+				} else {
+					if (pVBInfo->VBInfo & (SetCRT2ToTV
+							| SetCRT2ToLCD)) {
+						if (pVBInfo->VBInfo
+								& SetInSlaveMode)
+							ARdata = 0;
+					}
 				}
 			}
 		}
 
-		if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchToCRT2)) {
-			switch (HwDeviceExtension->ujVBChipID) {
-			case VB_CHIP_301:
-				XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
-						pVBInfo); /*add for CRT2 */
-				break;
+		inb(pVBInfo->P3da); /* reset 3da */
+		outb(i, pVBInfo->P3c0); /* set index */
+		outb(ARdata, pVBInfo->P3c0); /* set data */
+	}
 
-			case VB_CHIP_302:
-				XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
-						pVBInfo); /*add for CRT2 */
-				break;
+	inb(pVBInfo->P3da); /* reset 3da */
+	outb(0x14, pVBInfo->P3c0); /* set index */
+	outb(0x00, pVBInfo->P3c0); /* set data */
+	inb(pVBInfo->P3da); /* Enable Attribute */
+	outb(0x20, pVBInfo->P3c0);
+}
 
-			default:
-				break;
-			}
-		}
+static void XGI_SetGRCRegs(unsigned short StandTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned char GRdata;
+	unsigned short i;
 
-		XGI_SetCRT2ModeRegs(ModeNo, HwDeviceExtension, pVBInfo);
-		XGI_OEM310Setting(ModeNo, ModeIdIndex, pVBInfo); /*0212*/
-		XGI_CloseCRTC(HwDeviceExtension, pVBInfo);
-		XGI_EnableBridge(HwDeviceExtension, pVBInfo);
-	} /* !XG20 */
-	else {
-		if (pVBInfo->IF_DEF_LVDS == 1)
-			if (!XGI_XG21CheckLVDSMode(ModeNo, ModeIdIndex, pVBInfo))
-				return 0;
+	for (i = 0; i <= 0x08; i++) {
+		GRdata = pVBInfo->StandTable[StandTableIndex].GRC[i]; /* Get GR from file */
+		xgifb_reg_set(pVBInfo->P3ce, i, GRdata); /* Set GR(3ce) */
+	}
 
-		if (ModeNo <= 0x13) {
-			pVBInfo->ModeType
-					= pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag
-							& ModeInfoFlag;
-		} else {
-			pVBInfo->ModeType
-					= pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag
-							& ModeInfoFlag;
-		}
+	if (pVBInfo->ModeType > ModeVGA) {
+		GRdata = (unsigned char) xgifb_reg_get(pVBInfo->P3ce, 0x05);
+		GRdata &= 0xBF; /* 256 color disable */
+		xgifb_reg_set(pVBInfo->P3ce, 0x05, GRdata);
+	}
+}
 
-		pVBInfo->SetFlag = 0;
-		if (pVBInfo->IF_DEF_CH7007 != 1)
-			pVBInfo->VBInfo = DisableCRT2Display;
+static void XGI_ClearExt1Regs(struct vb_device_info *pVBInfo)
+{
+	unsigned short i;
 
-		XGI_DisplayOff(HwDeviceExtension, pVBInfo);
+	for (i = 0x0A; i <= 0x0E; i++)
+		xgifb_reg_set(pVBInfo->P3c4, i, 0x00); /* Clear SR0A-SR0E */
+}
 
-		XGI_SetCRT1Group(HwDeviceExtension, ModeNo, ModeIdIndex,
-				pVBInfo);
+static unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
+{
 
-		XGI_DisplayOn(HwDeviceExtension, pVBInfo);
-		/*
-		if (HwDeviceExtension->jChipType == XG21)
-			XGINew_SetRegANDOR(pVBInfo->P3c4, 0x09, ~0x80, 0x80);
-		*/
-	}
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x20);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2B, pVBInfo->VCLKData[0].SR2B);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[0].SR2C);
 
-	/*
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	}
-	pVBInfo->ModeType = modeflag&ModeInfoFlag;
-	pVBInfo->SetFlag = 0x00;
-	pVBInfo->VBInfo = DisableCRT2Display;
-	temp = XGINew_CheckMemorySize(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo);
-
-	if (temp == 0)
-		return (0);
-
-	XGI_DisplayOff(HwDeviceExtension, pVBInfo) ;
-	XGI_SetCRT1Group(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo);
-	XGI_DisplayOn(HwDeviceExtension, pVBInfo);
-	*/
-
-	XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, 0x10);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2B, pVBInfo->VCLKData[1].SR2B);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[1].SR2C);
 
-	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
-		XGI_LockCRT2(HwDeviceExtension, pVBInfo);
-	}
-
-	return 1;
+	xgifb_reg_and(pVBInfo->P3c4, 0x31, ~0x30);
+	return 0;
 }
 
-void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
+static unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
+		unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex, unsigned short *i,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short StandTableIndex, RefreshRateTableIndex, b3CC, temp;
-
-	unsigned short XGINew_P3cc = pVBInfo->P3cc;
+	unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
 
-	/* XGINew_CRT1Mode = ModeNo; // SaveModeID */
-	StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
-	/* XGI_SetBIOSData(ModeNo, ModeIdIndex); */
-	/* XGI_ClearBankRegs(ModeNo, ModeIdIndex); */
-	XGI_SetSeqRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
-	XGI_SetMiscRegs(StandTableIndex, pVBInfo);
-	XGI_SetCRTCRegs(HwDeviceExtension, StandTableIndex, pVBInfo);
-	XGI_SetATTRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
-	XGI_SetGRCRegs(StandTableIndex, pVBInfo);
-	XGI_ClearExt1Regs(pVBInfo);
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	/* if (pVBInfo->IF_DEF_ExpLink) */
-	if (HwDeviceExtension->jChipType == XG27) {
-		if (pVBInfo->IF_DEF_LVDS == 0)
-			XGI_SetDefaultVCLK(pVBInfo);
-	}
+	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+	tempbx = pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID;
+	tempax = 0;
 
-	temp = ~ProgrammingCRT2;
-	pVBInfo->SetFlag &= temp;
-	pVBInfo->SelectCRT2Rate = 0;
+	if (pVBInfo->IF_DEF_LVDS == 0) {
+		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
+			tempax |= SupportRAMDAC2;
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA
-				| SetInSlaveMode)) {
-			pVBInfo->SetFlag |= ProgrammingCRT2;
+			if (pVBInfo->VBType & VB_XGI301C)
+				tempax |= SupportCRT2in301C;
 		}
-	}
 
-	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
-			ModeIdIndex, pVBInfo);
-	if (RefreshRateTableIndex != 0xFFFF) {
-		XGI_SetSync(RefreshRateTableIndex, pVBInfo);
-		XGI_SetCRT1CRTC(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo, HwDeviceExtension);
-		XGI_SetCRT1DE(HwDeviceExtension, ModeNo, ModeIdIndex,
-				RefreshRateTableIndex, pVBInfo);
-		XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				HwDeviceExtension, pVBInfo);
-		XGI_SetCRT1VCLK(ModeNo, ModeIdIndex, HwDeviceExtension,
-				RefreshRateTableIndex, pVBInfo);
-	}
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* 301b */
+			tempax |= SupportLCD;
 
-	if ((HwDeviceExtension->jChipType >= XG20)
-			&& (HwDeviceExtension->jChipType < XG27)) { /* fix H/W DCLK/2 bug */
-		if ((ModeNo == 0x00) | (ModeNo == 0x01)) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2B, 0x4E);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2C, 0xE9);
-			b3CC = (unsigned char) XGINew_GetReg2(XGINew_P3cc);
-			XGINew_SetReg3(XGINew_P3cc, (b3CC |= 0x0C));
-		} else if ((ModeNo == 0x04) | (ModeNo == 0x05) | (ModeNo
-				== 0x0D)) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2B, 0x1B);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2C, 0xE3);
-			b3CC = (unsigned char) XGINew_GetReg2(XGINew_P3cc);
-			XGINew_SetReg3(XGINew_P3cc, (b3CC |= 0x0C));
+			if (pVBInfo->LCDResInfo != Panel1280x1024) {
+				if (pVBInfo->LCDResInfo != Panel1280x960) {
+					if (pVBInfo->LCDInfo & LCDNonExpanding) {
+						if (resinfo >= 9) {
+							tempax = 0;
+							return 0;
+						}
+					}
+				}
+			}
 		}
-	}
 
-	if (HwDeviceExtension->jChipType >= XG21) {
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
-		if (temp & 0xA0) {
+		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { /* for HiTV */
+			if ((pVBInfo->VBType & VB_XGI301LV)
+					&& (pVBInfo->VBExtInfo == VB_YPbPr1080i)) {
+				tempax |= SupportYPbPr;
+				if (pVBInfo->VBInfo & SetInSlaveMode) {
+					if (resinfo == 4)
+						return 0;
 
-			/* XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x20); *//* Enable write GPIOF */
-			/* XGINew_SetRegAND(pVBInfo->P3d4, 0x48, ~0x20); *//* P. DWN */
-			/* XG21 CRT1 Timing */
-			if (HwDeviceExtension->jChipType == XG27)
-				XGI_SetXG27CRTC(ModeNo, ModeIdIndex,
-						RefreshRateTableIndex, pVBInfo);
-			else
-				XGI_SetXG21CRTC(ModeNo, ModeIdIndex,
-						RefreshRateTableIndex, pVBInfo);
+					if (resinfo == 3)
+						return 0;
 
-			XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
-					RefreshRateTableIndex);
+					if (resinfo > 7)
+						return 0;
+				}
+			} else {
+				tempax |= SupportHiVisionTV;
+				if (pVBInfo->VBInfo & SetInSlaveMode) {
+					if (resinfo == 4)
+						return 0;
 
-			if (HwDeviceExtension->jChipType == XG27)
-				XGI_SetXG27LCD(pVBInfo, RefreshRateTableIndex,
-						ModeNo);
-			else
-				XGI_SetXG21LCD(pVBInfo, RefreshRateTableIndex,
-						ModeNo);
+					if (resinfo == 3) {
+						if (pVBInfo->SetFlag
+								& TVSimuMode)
+							return 0;
+					}
 
-			if (pVBInfo->IF_DEF_LVDS == 1) {
-				if (HwDeviceExtension->jChipType == XG27)
-					XGI_SetXG27LVDSPara(ModeNo,
-							ModeIdIndex, pVBInfo);
-				else
-					XGI_SetXG21LVDSPara(ModeNo,
-							ModeIdIndex, pVBInfo);
+					if (resinfo > 7)
+						return 0;
+				}
+			}
+		} else {
+			if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
+					| SetCRT2ToSVIDEO | SetCRT2ToSCART
+					| SetCRT2ToYPbPr | SetCRT2ToHiVisionTV)) {
+				tempax |= SupportTV;
+
+				if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
+						| VB_XGI301LV | VB_XGI302LV
+						| VB_XGI301C)) {
+					tempax |= SupportTV1024;
+				}
+
+				if (!(pVBInfo->VBInfo & SetPALTV)) {
+					if (modeflag & NoSupportSimuTV) {
+						if (pVBInfo->VBInfo
+								& SetInSlaveMode) {
+							if (!(pVBInfo->VBInfo
+									& SetNotSimuMode)) {
+								return 0;
+							}
+						}
+					}
+				}
 			}
-			/* XGINew_SetRegOR(pVBInfo->P3d4, 0x48, 0x20); *//* P. ON */
 		}
-	}
+	} else { /* for LVDS */
+		if (pVBInfo->IF_DEF_CH7005 == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToTV)
+				tempax |= SupportCHTV;
+		}
 
-	pVBInfo->SetFlag &= (~ProgrammingCRT2);
-	XGI_SetCRT1FIFO(ModeNo, HwDeviceExtension, pVBInfo);
-	XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeNo, ModeIdIndex,
-			RefreshRateTableIndex, pVBInfo);
+		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
+			tempax |= SupportLCD;
 
-	/* XGI_LoadCharacter(); //dif ifdef TVFont */
+			if (resinfo > 0x08)
+				return 0; /* 1024x768 */
 
-	XGI_LoadDAC(ModeNo, ModeIdIndex, pVBInfo);
-	/* XGI_ClearBuffer(HwDeviceExtension, ModeNo, pVBInfo); */
-}
+			if (pVBInfo->LCDResInfo < Panel1024x768) {
+				if (resinfo > 0x07)
+					return 0; /* 800x600 */
 
-unsigned char XGI_GetModePtr(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned char index;
+				if (resinfo == 0x04)
+					return 0; /* 512x384 */
+			}
+		}
+	}
 
-	if (ModeNo <= 0x13)
-		index = pVBInfo->SModeIDTable[ModeIdIndex].St_StTableIndex;
-	else {
-		if (pVBInfo->ModeType <= 0x02)
-			index = 0x1B; /* 02 -> ModeEGA */
-		else
-			index = 0x0F;
+	for (; pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID == tempbx; (*i)--) {
+		infoflag
+				= pVBInfo->RefIndex[RefreshRateTableIndex
+						+ (*i)].Ext_InfoFlag;
+		if (infoflag & tempax)
+			return 1;
+
+		if ((*i) == 0)
+			break;
 	}
-	return index; /* Get pVBInfo->StandTable index */
-}
 
-/*
-unsigned char XGI_SetBIOSData(unsigned short ModeNo, unsigned short ModeIdIndex) {
-	return (0);
-}
-*/
+	for ((*i) = 0;; (*i)++) {
+		infoflag
+				= pVBInfo->RefIndex[RefreshRateTableIndex
+						+ (*i)].Ext_InfoFlag;
+		if (pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID
+				!= tempbx) {
+			return 0;
+		}
 
-/* unsigned char XGI_ClearBankRegs(unsigned short ModeNo, unsigned short ModeIdIndex) {
-	return( 0 ) ;
+		if (infoflag & tempax)
+			return 1;
+	}
+	return 1;
 }
-*/
 
-void XGI_SetSeqRegs(unsigned short ModeNo, unsigned short StandTableIndex,
-		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+static void XGI_SetSync(unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned char tempah, SRdata;
+	unsigned short sync, temp;
 
-	unsigned short i, modeflag;
+	sync = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; /* di+0x00 */
+	sync &= 0xC0;
+	temp = 0x2F;
+	temp |= sync;
+	outb(temp, pVBInfo->P3c2); /* Set Misc(3c2) */
+}
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+static void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
+		struct xgi_hw_device_info *HwDeviceExtension)
+{
+	unsigned char data, data1, pushax;
+	unsigned short i, j;
 
-	XGINew_SetReg1(pVBInfo->P3c4, 0x00, 0x03); /* Set SR0 */
-	tempah = pVBInfo->StandTable[StandTableIndex].SR[0];
+	/* xgifb_reg_set(pVBInfo->P3d4, 0x51, 0); */
+	/* xgifb_reg_set(pVBInfo->P3d4, 0x56, 0); */
+	/* xgifb_reg_and_or(pVBInfo->P3d4, 0x11, 0x7f, 0x00); */
 
-	i = SetCRT2ToLCDA;
-	if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-		tempah |= 0x01;
-	} else {
-		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD)) {
-			if (pVBInfo->VBInfo & SetInSlaveMode)
-				tempah |= 0x01;
-		}
-	}
+	data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11); /* unlock cr0-7 */
+	data &= 0x7F;
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, data);
 
-	tempah |= 0x20; /* screen off */
-	XGINew_SetReg1(pVBInfo->P3c4, 0x01, tempah); /* Set SR1 */
+	data = pVBInfo->TimingH[0].data[0];
+	xgifb_reg_set(pVBInfo->P3d4, 0, data);
 
-	for (i = 02; i <= 04; i++) {
-		SRdata = pVBInfo->StandTable[StandTableIndex].SR[i - 1]; /* Get SR2,3,4 from file */
-		XGINew_SetReg1(pVBInfo->P3c4, i, SRdata); /* Set SR2 3 4 */
+	for (i = 0x01; i <= 0x04; i++) {
+		data = pVBInfo->TimingH[0].data[i];
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 1), data);
 	}
-}
 
-void XGI_SetMiscRegs(unsigned short StandTableIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned char Miscdata;
+	for (i = 0x05; i <= 0x06; i++) {
+		data = pVBInfo->TimingH[0].data[i];
+		xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i + 6), data);
+	}
 
-	Miscdata = pVBInfo->StandTable[StandTableIndex].MISC; /* Get Misc from file */
-	/*
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
-		if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-			Miscdata |= 0x0C;
+	j = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x0e);
+	j &= 0x1F;
+	data = pVBInfo->TimingH[0].data[7];
+	data &= 0xE0;
+	data |= j;
+	xgifb_reg_set(pVBInfo->P3c4, 0x0e, data);
+
+	if (HwDeviceExtension->jChipType >= XG20) {
+		data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x04);
+		data = data - 1;
+		xgifb_reg_set(pVBInfo->P3d4, 0x04, data);
+		data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x05);
+		data1 = data;
+		data1 &= 0xE0;
+		data &= 0x1F;
+		if (data == 0) {
+			pushax = data;
+			data = (unsigned char) xgifb_reg_get(pVBInfo->P3c4,
+					0x0c);
+			data &= 0xFB;
+			xgifb_reg_set(pVBInfo->P3c4, 0x0c, data);
+			data = pushax;
 		}
+		data = data - 1;
+		data |= data1;
+		xgifb_reg_set(pVBInfo->P3d4, 0x05, data);
+		data = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x0e);
+		data = data >> 5;
+		data = data + 3;
+		if (data > 7)
+			data = data - 7;
+		data = data << 5;
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x0e, ~0xE0, data);
 	}
-	*/
-
-	XGINew_SetReg3(pVBInfo->P3c2, Miscdata); /* Set Misc(3c2) */
 }
 
-void XGI_SetCRTCRegs(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short StandTableIndex, struct vb_device_info *pVBInfo)
+static void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned char CRTCdata;
-	unsigned short i;
+	unsigned char data;
+	unsigned short i, j;
 
-	CRTCdata = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11);
-	CRTCdata &= 0x7f;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, CRTCdata); /* Unlock CRTC */
+	/* xgifb_reg_set(pVBInfo->P3d4, 0x51, 0); */
+	/* xgifb_reg_set(pVBInfo->P3d4, 0x56, 0); */
+	/* xgifb_reg_and_or(pVBInfo->P3d4, 0x11, 0x7f, 0x00); */
 
-	for (i = 0; i <= 0x18; i++) {
-		CRTCdata = pVBInfo->StandTable[StandTableIndex].CRTC[i]; /* Get CRTC from file */
-		XGINew_SetReg1(pVBInfo->P3d4, i, CRTCdata); /* Set CRTC(3d4) */
+	for (i = 0x00; i <= 0x01; i++) {
+		data = pVBInfo->TimingV[0].data[i];
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 6), data);
 	}
-	/*
-	if ((HwDeviceExtension->jChipType == XGI_630) && (HwDeviceExtension->jChipRevision == 0x30)) {
-		if (pVBInfo->VBInfo & SetInSlaveMode) {
-			if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-				XGINew_SetReg1(pVBInfo->P3d4, 0x18, 0xFE);
-			}
-		}
+
+	for (i = 0x02; i <= 0x03; i++) {
+		data = pVBInfo->TimingV[0].data[i];
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x0e), data);
 	}
-	*/
-}
 
-void XGI_SetATTRegs(unsigned short ModeNo, unsigned short StandTableIndex,
-		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
-	unsigned char ARdata;
-	unsigned short i, modeflag;
+	for (i = 0x04; i <= 0x05; i++) {
+		data = pVBInfo->TimingV[0].data[i];
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 0x11), data);
+	}
+
+	j = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x0a);
+	j &= 0xC0;
+	data = pVBInfo->TimingV[0].data[6];
+	data &= 0x3F;
+	data |= j;
+	xgifb_reg_set(pVBInfo->P3c4, 0x0a, data);
+
+	data = pVBInfo->TimingV[0].data[6];
+	data &= 0x80;
+	data = data >> 2;
 
 	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+		i = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
 	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-
-	for (i = 0; i <= 0x13; i++) {
-		ARdata = pVBInfo->StandTable[StandTableIndex].ATTR[i];
-		if (modeflag & Charx8Dot) { /* ifndef Dot9 */
-			if (i == 0x13) {
-				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-					ARdata = 0;
-				} else {
-					if (pVBInfo->VBInfo & (SetCRT2ToTV
-							| SetCRT2ToLCD)) {
-						if (pVBInfo->VBInfo
-								& SetInSlaveMode)
-							ARdata = 0;
-					}
-				}
-			}
-		}
+		i = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-		XGINew_GetReg2(pVBInfo->P3da); /* reset 3da */
-		XGINew_SetReg3(pVBInfo->P3c0, i); /* set index */
-		XGINew_SetReg3(pVBInfo->P3c0, ARdata); /* set data */
-	}
+	i &= DoubleScanMode;
+	if (i)
+		data |= 0x80;
 
-	XGINew_GetReg2(pVBInfo->P3da); /* reset 3da */
-	XGINew_SetReg3(pVBInfo->P3c0, 0x14); /* set index */
-	XGINew_SetReg3(pVBInfo->P3c0, 0x00); /* set data */
-	XGINew_GetReg2(pVBInfo->P3da); /* Enable Attribute */
-	XGINew_SetReg3(pVBInfo->P3c0, 0x20);
+	j = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x09);
+	j &= 0x5F;
+	data |= j;
+	xgifb_reg_set(pVBInfo->P3d4, 0x09, data);
 }
 
-void XGI_SetGRCRegs(unsigned short StandTableIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo,
+		struct xgi_hw_device_info *HwDeviceExtension)
 {
-	unsigned char GRdata;
+	unsigned char index, data;
 	unsigned short i;
 
-	for (i = 0; i <= 0x08; i++) {
-		GRdata = pVBInfo->StandTable[StandTableIndex].GRC[i]; /* Get GR from file */
-		XGINew_SetReg1(pVBInfo->P3ce, i, GRdata); /* Set GR(3ce) */
-	}
-
-	if (pVBInfo->ModeType > ModeVGA) {
-		GRdata = (unsigned char) XGINew_GetReg1(pVBInfo->P3ce, 0x05);
-		GRdata &= 0xBF; /* 256 color disable */
-		XGINew_SetReg1(pVBInfo->P3ce, 0x05, GRdata);
-	}
-}
+	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; /* Get index */
+	index = index & IndexMask;
 
-void XGI_ClearExt1Regs(struct vb_device_info *pVBInfo)
-{
-	unsigned short i;
+	data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
+	data &= 0x7F;
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
 
-	for (i = 0x0A; i <= 0x0E; i++)
-		XGINew_SetReg1(pVBInfo->P3c4, i, 0x00); /* Clear SR0A-SR0E */
-}
+	for (i = 0; i < 8; i++)
+		pVBInfo->TimingH[0].data[i]
+				= pVBInfo->XGINEWUB_CRT1Table[index].CR[i];
 
-unsigned char XGI_SetDefaultVCLK(struct vb_device_info *pVBInfo)
-{
+	for (i = 0; i < 7; i++)
+		pVBInfo->TimingV[0].data[i]
+				= pVBInfo->XGINEWUB_CRT1Table[index].CR[i + 8];
 
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x31, ~0x30, 0x20);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2B, pVBInfo->VCLKData[0].SR2B);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[0].SR2C);
+	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
 
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x31, ~0x30, 0x10);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2B, pVBInfo->VCLKData[1].SR2B);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2C, pVBInfo->VCLKData[1].SR2C);
+	XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
 
-	XGINew_SetRegAND(pVBInfo->P3c4, 0x31, ~0x30);
-	return 0;
+	if (pVBInfo->ModeType > 0x03)
+		xgifb_reg_set(pVBInfo->P3d4, 0x14, 0x4F);
 }
 
-unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetXG21CRTC */
+/* Input : Stand or enhance CRTC table */
+/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
+/* Description : Set LCD timing */
+/* --------------------------------------------------------------------- */
+static void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	short LCDRefreshIndex[] = { 0x00, 0x00, 0x03, 0x01 },
-			LCDARefreshIndex[] = { 0x00, 0x00, 0x03, 0x01, 0x01,
-					0x01, 0x01 };
-
-	unsigned short RefreshRateTableIndex, i, modeflag, index, temp;
+	unsigned char StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+	unsigned short Temp1, Temp2, Temp3;
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	if (ModeNo <= 0x13) {
+		StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[4]; /* CR04 HRS */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E [7:0]->HRS */
+		Tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[5]; /* Tempbx: CR05 HRE */
+		Tempbx &= 0x1F; /* Tempbx: HRE[4:0] */
+		Tempcx = Tempax;
+		Tempcx &= 0xE0; /* Tempcx: HRS[7:5] */
+		Tempdx = Tempcx | Tempbx; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
+		if (Tempbx < (Tempax & 0x1F)) /* IF HRE < HRS */
+			Tempdx |= 0x20; /* Tempdx: HRE = HRE + 0x20 */
+		Tempdx <<= 2; /* Tempdx << 2 */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempdx); /* SR2F [7:2]->HRE */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
 
-	if (pVBInfo->IF_DEF_CH7005 == 1) {
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			if (modeflag & HalfDCLK)
-				return 0;
-		}
-	}
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[16]; /* Tempax: CR16 VRS */
+		Tempbx = Tempax; /* Tempbx=Tempax */
+		Tempax &= 0x01; /* Tempax: VRS[0] */
+		xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS */
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[7]; /* Tempax: CR7 VRS */
+		Tempdx = Tempbx >> 1; /* Tempdx: VRS[7:1] */
+		Tempcx = Tempax & 0x04; /* Tempcx: CR7[2] */
+		Tempcx <<= 5; /* Tempcx[7]: VRS[8] */
+		Tempdx |= Tempcx; /* Tempdx: VRS[8:1] */
+		xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempdx); /* SR34[7:0]: VRS[8:1] */
 
-	if (ModeNo < 0x14)
-		return 0xFFFF;
+		Temp1 = Tempcx << 1; /* Temp1[8]: VRS[8] unsigned char -> unsigned short */
+		Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
+		Tempax &= 0x80; /* Tempax[7]: CR7[7] */
+		Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
+		Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
 
-	index = XGINew_GetReg1(pVBInfo->P3d4, 0x33);
-	index = index >> pVBInfo->SelectCRT2Rate;
-	index &= 0x0F;
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[17]; /* CR16 VRE */
+		Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
+		Temp2 = Temp1 & 0x3F0; /* Temp2[9:4]: VRS[9:4] */
+		Temp2 |= Tempax; /* Temp2[9:0]: VRE[9:0] */
+		Temp3 = Temp1 & 0x0F; /* Temp3[3:0]: VRS[3:0] */
+		if (Tempax < Temp3) /* VRE[3:0]<VRS[3:0] */
+			Temp2 |= 0x10; /* Temp2: VRE + 0x10 */
+		Temp2 &= 0xFF; /* Temp2[7:0]: VRE[7:0] */
+		Tempax = (unsigned char) Temp2; /* Tempax[7:0]: VRE[7:0] */
+		Tempax <<= 2; /* Tempax << 2: VRE[5:0] */
+		Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
+		Temp1 >>= 9; /* [10:9]->[1:0] */
+		Tempbx = (unsigned char) Temp1; /* Tempbx[1:0]: VRS[10:9] */
+		Tempax |= Tempbx; /* VRE[5:0]VRS[10:9] */
+		Tempax &= 0x7F;
+		xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax); /* SR3F D[7:2]->VRE D[1:0]->VRS */
+	} else {
+		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3]; /* Tempax: CR4 HRS */
+		Tempcx = Tempax; /* Tempcx: HRS */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E[7:0]->HRS */
 
-	if (pVBInfo->LCDInfo & LCDNonExpanding)
-		index = 0;
+		Tempdx = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SRB */
+		Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
+		Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
+		Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
+		Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
 
-	if (index > 0)
-		index--;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
+		Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
 
-	if (pVBInfo->SetFlag & ProgrammingCRT2) {
-		if (pVBInfo->IF_DEF_CH7005 == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToTV)
-				index = 0;
-		}
+		Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
+		Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
+		Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
+		Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
 
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-			if (pVBInfo->IF_DEF_LVDS == 0) {
-				if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
-						| VB_XGI301LV | VB_XGI302LV
-						| VB_XGI301C))
-					temp
-							= LCDARefreshIndex[pVBInfo->LCDResInfo
-									& 0x0F]; /* 301b */
-				else
-					temp
-							= LCDRefreshIndex[pVBInfo->LCDResInfo
-									& 0x0F];
+		Temp2 = Temp1 & 0x3C0; /* Temp2[9:6]: HRS[9:6] */
+		Temp2 |= Tempax; /* Temp2[9:0]: HRE[9:0] */
 
-				if (index > temp)
-					index = temp;
-			} else {
-				index = 0;
-			}
-		}
-	}
+		Tempcx &= 0x3F; /* Tempcx[5:0]: HRS[5:0] */
+		if (Tempax < Tempcx) /* HRE < HRS */
+			Temp2 |= 0x40; /* Temp2 + 0x40 */
 
-	RefreshRateTableIndex = pVBInfo->EModeIDTable[ModeIdIndex].REFindex;
-	ModeNo = pVBInfo->RefIndex[RefreshRateTableIndex].ModeID;
-	if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
-		/*
-		if (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & XG2xNotSupport) {
-			index++;
-		}
-		*/
-		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 800)
-				&& (pVBInfo->RefIndex[RefreshRateTableIndex].YRes
-						== 600)) {
-			index++;
-		}
-		/* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */
-		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1024)
-				&& (pVBInfo->RefIndex[RefreshRateTableIndex].YRes
-						== 768)) {
-			index++;
-		}
-		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1280)
-				&& (pVBInfo->RefIndex[RefreshRateTableIndex].YRes
-						== 1024)) {
-			index++;
-		}
-	}
+		Temp2 &= 0xFF;
+		Tempax = (unsigned char) Temp2; /* Tempax: HRE[7:0] */
+		Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */
+		Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */
+		Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax); /* SR2F D[7:2]->HRE, D[1:0]->HRS */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
 
-	i = 0;
-	do {
-		if (pVBInfo->RefIndex[RefreshRateTableIndex + i].ModeID
-				!= ModeNo)
-			break;
-		temp
-				= pVBInfo->RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
-		temp &= ModeInfoFlag;
-		if (temp < pVBInfo->ModeType)
-			break;
-		i++;
-		index--;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10]; /* CR10 VRS */
+		Tempbx = Tempax; /* Tempbx: VRS */
+		Tempax &= 0x01; /* Tempax[0]: VRS[0] */
+		xgifb_reg_or(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9]; /* CR7[2][7] VRE */
+		Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
+		Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
+		Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
+		Tempcx |= Tempdx; /* Tempcx[7:0]: VRS[8:1] */
+		xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempcx); /* SR34[8:1]->VRS */
 
-	} while (index != 0xFFFF);
-	if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
-		if (pVBInfo->VBInfo & SetInSlaveMode) {
-			temp
-					= pVBInfo->RefIndex[RefreshRateTableIndex
-							+ i - 1].Ext_InfoFlag;
-			if (temp & InterlaceMode)
-				i++;
-		}
-	}
-	i--;
-	if ((pVBInfo->SetFlag & ProgrammingCRT2)) {
-		temp = XGI_AjustCRT2Rate(ModeNo, ModeIdIndex,
-				RefreshRateTableIndex, &i, pVBInfo);
+		Temp1 = Tempdx; /* Temp1[7]: Tempdx[7] */
+		Temp1 <<= 1; /* Temp1[8]: VRS[8] */
+		Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
+		Tempax &= 0x80;
+		Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
+		Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempax: SRA */
+		Tempax &= 0x08; /* Tempax[3]: VRS[3] */
+		Temp2 = Tempax;
+		Temp2 <<= 7; /* Temp2[10]: VRS[10] */
+		Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
+
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11]; /* Tempax: CR11 VRE */
+		Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
+		Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempbx: SRA */
+		Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
+		Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
+		Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
+		Temp2 = Temp1 & 0x7E0; /* Temp2[10:5]: VRS[10:5] */
+		Temp2 |= Tempax; /* Temp2[10:5]: VRE[10:5] */
+
+		Temp3 = Temp1 & 0x1F; /* Temp3[4:0]: VRS[4:0] */
+		if (Tempax < Temp3) /* VRE < VRS */
+			Temp2 |= 0x20; /* VRE + 0x20 */
+
+		Temp2 &= 0xFF;
+		Tempax = (unsigned char) Temp2; /* Tempax: VRE[7:0] */
+		Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */
+		Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
+		Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */
+		Tempbx = (unsigned char) Temp1;
+		Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
+		Tempax &= 0x7F;
+		xgifb_reg_set(pVBInfo->P3c4, 0x3F, Tempax); /* SR3F D[7:2]->VRE D[1:0]->VRS */
 	}
-	return RefreshRateTableIndex + i; /* return (0x01 | (temp1<<1)); */
 }
 
-unsigned char XGI_AjustCRT2Rate(unsigned short ModeNo,
-		unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex, unsigned short *i,
+static void XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempax, tempbx, resinfo, modeflag, infoflag;
+	unsigned short StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	if (ModeNo <= 0x13) {
+		StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[4]; /* CR04 HRS */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E [7:0]->HRS */
+		Tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[5]; /* Tempbx: CR05 HRE */
+		Tempbx &= 0x1F; /* Tempbx: HRE[4:0] */
+		Tempcx = Tempax;
+		Tempcx &= 0xE0; /* Tempcx: HRS[7:5] */
+		Tempdx = Tempcx | Tempbx; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
+		if (Tempbx < (Tempax & 0x1F)) /* IF HRE < HRS */
+			Tempdx |= 0x20; /* Tempdx: HRE = HRE + 0x20 */
+		Tempdx <<= 2; /* Tempdx << 2 */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempdx); /* SR2F [7:2]->HRE */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
 
-	resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-	tempbx = pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID;
-	tempax = 0;
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[16]; /* Tempax: CR10 VRS */
+		xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax); /* SR34[7:0]->VRS */
+		Tempcx = Tempax; /* Tempcx=Tempax=VRS[7:0] */
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[7]; /* Tempax[7][2]: CR7[7][2] VRS[9][8] */
+		Tempbx = Tempax; /* Tempbx=CR07 */
+		Tempax &= 0x04; /* Tempax[2]: CR07[2] VRS[8] */
+		Tempax >>= 2;
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax); /* SR35 D[0]->VRS D[8] */
+		Tempcx |= (Tempax << 8); /* Tempcx[8] |= VRS[8] */
+		Tempcx |= (Tempbx & 0x80) << 2; /* Tempcx[9] |= VRS[9] */
 
-	if (pVBInfo->IF_DEF_LVDS == 0) {
-		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-			tempax |= SupportRAMDAC2;
+		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[17]; /* CR11 VRE */
+		Tempax &= 0x0F; /* Tempax: VRE[3:0] */
+		Tempbx = Tempcx; /* Tempbx=Tempcx=VRS[9:0] */
+		Tempbx &= 0x3F0; /* Tempbx[9:4]: VRS[9:4] */
+		Tempbx |= Tempax; /* Tempbx[9:0]: VRE[9:0] */
+		if (Tempax <= (Tempcx & 0x0F)) /* VRE[3:0]<=VRS[3:0] */
+			Tempbx |= 0x10; /* Tempbx: VRE + 0x10 */
+		Tempax = (unsigned char) Tempbx & 0xFF; /* Tempax[7:0]: VRE[7:0] */
+		Tempax <<= 2; /* Tempax << 2: VRE[5:0] */
+		Tempcx = (Tempcx & 0x600) >> 8; /* Tempcx VRS[10:9] */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax); /* SR3F D[7:2]->VRE D[5:0] */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x06, Tempcx); /* SR35 D[2:1]->VRS[10:9] */
+	} else {
+		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3]; /* Tempax: CR4 HRS */
+		Tempbx = Tempax; /* Tempbx: HRS[7:0] */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E[7:0]->HRS */
 
-			if (pVBInfo->VBType & VB_XGI301C)
-				tempax |= SupportCRT2in301C;
-		}
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
+		Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+		Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
 
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /* 301b */
-			tempax |= SupportLCD;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
+		Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
+		Tempcx = Tempax; /* Tempcx: HRE[4:0] */
 
-			if (pVBInfo->LCDResInfo != Panel1280x1024) {
-				if (pVBInfo->LCDResInfo != Panel1280x960) {
-					if (pVBInfo->LCDInfo & LCDNonExpanding) {
-						if (resinfo >= 9) {
-							tempax = 0;
-							return 0;
-						}
-					}
-				}
-			}
-		}
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
+		Tempax &= 0x04; /* Tempax[2]: HRE[5] */
+		Tempax <<= 3; /* Tempax[5]: HRE[5] */
+		Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
 
-		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) { /* for HiTV */
-			if ((pVBInfo->VBType & VB_XGI301LV)
-					&& (pVBInfo->VBExtInfo == VB_YPbPr1080i)) {
-				tempax |= SupportYPbPr;
-				if (pVBInfo->VBInfo & SetInSlaveMode) {
-					if (resinfo == 4)
-						return 0;
+		Tempbx = Tempbx & 0x3C0; /* Tempbx[9:6]: HRS[9:6] */
+		Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
 
-					if (resinfo == 3)
-						return 0;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3]; /* Tempax: CR4 HRS */
+		Tempax &= 0x3F; /* Tempax: HRS[5:0] */
+		if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
+			Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
 
-					if (resinfo > 7)
-						return 0;
-				}
-			} else {
-				tempax |= SupportHiVisionTV;
-				if (pVBInfo->VBInfo & SetInSlaveMode) {
-					if (resinfo == 4)
-						return 0;
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
+		Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
+		Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
+		Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
+		xgifb_reg_set(pVBInfo->P3c4, 0x2F, Tempax); /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x30, 0xE3, 00);
 
-					if (resinfo == 3) {
-						if (pVBInfo->SetFlag
-								& TVSimuMode)
-							return 0;
-					}
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10]; /* CR10 VRS */
+		xgifb_reg_set(pVBInfo->P3c4, 0x34, Tempax); /* SR34[7:0]->VRS[7:0] */
 
-					if (resinfo > 7)
-						return 0;
-				}
-			}
-		} else {
-			if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
-					| SetCRT2ToSVIDEO | SetCRT2ToSCART
-					| SetCRT2ToYPbPr | SetCRT2ToHiVisionTV)) {
-				tempax |= SupportTV;
+		Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9]; /* CR7[7][2] VRS[9][8] */
+		Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
+		Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
+		Tempax >>= 2; /* Tempax[0]: VRS[8] */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x01, Tempax); /* SR35[0]: VRS[8] */
+		Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */
+		Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempax: SR0A */
+		Tempax &= 0x08; /* SR0A[3] VRS[10] */
+		Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */
 
-				if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
-						| VB_XGI301LV | VB_XGI302LV
-						| VB_XGI301C)) {
-					tempax |= SupportTV1024;
-				}
+		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11]; /* Tempax: CR11 VRE */
+		Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
+		Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempbx: SR0A */
+		Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
+		Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
+		Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
+		Tempbx = Tempcx; /* Tempbx: VRS[10:0] */
+		Tempbx &= 0x7E0; /* Tempbx[10:5]: VRS[10:5] */
+		Tempbx |= Tempax; /* Tempbx: VRS[10:5]VRE[4:0] */
 
-				if (!(pVBInfo->VBInfo & SetPALTV)) {
-					if (modeflag & NoSupportSimuTV) {
-						if (pVBInfo->VBInfo
-								& SetInSlaveMode) {
-							if (!(pVBInfo->VBInfo
-									& SetNotSimuMode)) {
-								return 0;
-							}
-						}
-					}
-				}
-			}
-		}
-	} else { /* for LVDS */
-		if (pVBInfo->IF_DEF_CH7005 == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToTV)
-				tempax |= SupportCHTV;
-		}
+		if (Tempbx <= Tempcx) /* VRE <= VRS */
+			Tempbx |= 0x20; /* VRE + 0x20 */
 
-		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
-			tempax |= SupportLCD;
+		Tempax = (Tempbx << 2) & 0xFF; /* Tempax: Tempax[7:0]; VRE[5:0]00 */
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax); /* SR3F[7:2]:VRE[5:0] */
+		Tempax = Tempcx >> 8;
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, Tempax); /* SR35[2:0]:VRS[10:8] */
+	}
+}
 
-			if (resinfo > 0x08)
-				return 0; /* 1024x768 */
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetXG21LCD */
+/* Input : */
+/* Output : FCLK duty cycle, FCLK delay compensation */
+/* Description : All values set zero */
+/* --------------------------------------------------------------------- */
+static void XGI_SetXG21LCD(struct vb_device_info *pVBInfo,
+		unsigned short RefreshRateTableIndex, unsigned short ModeNo)
+{
+	unsigned short Data, Temp, b3CC;
+	unsigned short XGI_P3cc;
 
-			if (pVBInfo->LCDResInfo < Panel1024x768) {
-				if (resinfo > 0x07)
-					return 0; /* 800x600 */
+	XGI_P3cc = pVBInfo->P3cc;
 
-				if (resinfo == 0x04)
-					return 0; /* 512x384 */
-			}
-		}
+	xgifb_reg_set(pVBInfo->P3d4, 0x2E, 0x00);
+	xgifb_reg_set(pVBInfo->P3d4, 0x2F, 0x00);
+	xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x00);
+	xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x00);
+	if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) {
+		xgifb_reg_set(pVBInfo->P3d4, 0x2E, *pVBInfo->pCR2E);
+		xgifb_reg_set(pVBInfo->P3d4, 0x2F, *pVBInfo->pCR2F);
+		xgifb_reg_set(pVBInfo->P3d4, 0x46, *pVBInfo->pCR46);
+		xgifb_reg_set(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47);
 	}
 
-	for (; pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID == tempbx; (*i)--) {
-		infoflag
-				= pVBInfo->RefIndex[RefreshRateTableIndex
-						+ (*i)].Ext_InfoFlag;
-		if (infoflag & tempax)
-			return 1;
+	Temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
 
-		if ((*i) == 0)
-			break;
+	if (Temp & 0x01) {
+		xgifb_reg_or(pVBInfo->P3c4, 0x06, 0x40); /* 18 bits FP */
+		xgifb_reg_or(pVBInfo->P3c4, 0x09, 0x40);
 	}
 
-	for ((*i) = 0;; (*i)++) {
-		infoflag
-				= pVBInfo->RefIndex[RefreshRateTableIndex
-						+ (*i)].Ext_InfoFlag;
-		if (pVBInfo->RefIndex[RefreshRateTableIndex + (*i)].ModeID
-				!= tempbx) {
-			return 0;
-		}
+	xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
 
-		if (infoflag & tempax)
-			return 1;
+	xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20);
+	xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80);
+
+	if (ModeNo <= 0x13) {
+		b3CC = (unsigned char) inb(XGI_P3cc);
+		if (b3CC & 0x40)
+			xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
+		if (b3CC & 0x80)
+			xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
+	} else {
+		Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+		if (Data & 0x4000)
+			xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
+		if (Data & 0x8000)
+			xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
 	}
-	return 1;
 }
 
-void XGI_SetSync(unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetXG27LCD(struct vb_device_info *pVBInfo,
+		unsigned short RefreshRateTableIndex, unsigned short ModeNo)
 {
-	unsigned short sync, temp;
-
-	sync = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag >> 8; /* di+0x00 */
-	sync &= 0xC0;
-	temp = 0x2F;
-	temp |= sync;
-	XGINew_SetReg3(pVBInfo->P3c2, temp); /* Set Misc(3c2) */
-}
+	unsigned short Data, Temp, b3CC;
+	unsigned short XGI_P3cc;
 
-void XGI_SetCRT1CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo,
-		struct xgi_hw_device_info *HwDeviceExtension)
-{
-	unsigned char index, data;
-	unsigned short i;
+	XGI_P3cc = pVBInfo->P3cc;
 
-	index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC; /* Get index */
-	index = index & IndexMask;
+	xgifb_reg_set(pVBInfo->P3d4, 0x2E, 0x00);
+	xgifb_reg_set(pVBInfo->P3d4, 0x2F, 0x00);
+	xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x00);
+	xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x00);
 
-	data = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11);
-	data &= 0x7F;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
+	Temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
+	if ((Temp & 0x03) == 0) { /* dual 12 */
+		xgifb_reg_set(pVBInfo->P3d4, 0x46, 0x13);
+		xgifb_reg_set(pVBInfo->P3d4, 0x47, 0x13);
+	}
 
-	for (i = 0; i < 8; i++)
-		pVBInfo->TimingH[0].data[i]
-				= pVBInfo->XGINEWUB_CRT1Table[index].CR[i];
+	if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) {
+		xgifb_reg_set(pVBInfo->P3d4, 0x2E, *pVBInfo->pCR2E);
+		xgifb_reg_set(pVBInfo->P3d4, 0x2F, *pVBInfo->pCR2F);
+		xgifb_reg_set(pVBInfo->P3d4, 0x46, *pVBInfo->pCR46);
+		xgifb_reg_set(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47);
+	}
 
-	for (i = 0; i < 7; i++)
-		pVBInfo->TimingV[0].data[i]
-				= pVBInfo->XGINEWUB_CRT1Table[index].CR[i + 8];
+	XGI_SetXG27FPBits(pVBInfo);
 
-	XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
+	xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
 
-	XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
+	xgifb_reg_and(pVBInfo->P3c4, 0x30, ~0x20); /* Hsync polarity */
+	xgifb_reg_and(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
 
-	if (pVBInfo->ModeType > 0x03)
-		XGINew_SetReg1(pVBInfo->P3d4, 0x14, 0x4F);
+	if (ModeNo <= 0x13) {
+		b3CC = (unsigned char) inb(XGI_P3cc);
+		if (b3CC & 0x40)
+			xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
+		if (b3CC & 0x80)
+			xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
+	} else {
+		Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+		if (Data & 0x4000)
+			xgifb_reg_or(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
+		if (Data & 0x8000)
+			xgifb_reg_or(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
+	}
 }
 
-void XGI_SetCRT1Timing_H(struct vb_device_info *pVBInfo,
-		struct xgi_hw_device_info *HwDeviceExtension)
+/* --------------------------------------------------------------------- */
+/* Function : XGI_UpdateXG21CRTC */
+/* Input : */
+/* Output : CRT1 CRTC */
+/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
+/* --------------------------------------------------------------------- */
+static void XGI_UpdateXG21CRTC(unsigned short ModeNo, struct vb_device_info *pVBInfo,
+		unsigned short RefreshRateTableIndex)
 {
-	unsigned char data, data1, pushax;
-	unsigned short i, j;
-
-	/* XGINew_SetReg1(pVBInfo->P3d4, 0x51, 0); */
-	/* XGINew_SetReg1(pVBInfo->P3d4, 0x56, 0); */
-	/* XGINew_SetRegANDOR(pVBInfo->P3d4, 0x11, 0x7f, 0x00); */
-
-	data = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11); /* unlock cr0-7 */
-	data &= 0x7F;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, data);
-
-	data = pVBInfo->TimingH[0].data[0];
-	XGINew_SetReg1(pVBInfo->P3d4, 0, data);
-
-	for (i = 0x01; i <= 0x04; i++) {
-		data = pVBInfo->TimingH[0].data[i];
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) (i + 1), data);
-	}
+	int i, index = -1;
 
-	for (i = 0x05; i <= 0x06; i++) {
-		data = pVBInfo->TimingH[0].data[i];
-		XGINew_SetReg1(pVBInfo->P3c4, (unsigned short) (i + 6), data);
+	xgifb_reg_and(pVBInfo->P3d4, 0x11, 0x7F); /* Unlock CR0~7 */
+	if (ModeNo <= 0x13) {
+		for (i = 0; i < 12; i++) {
+			if (ModeNo == pVBInfo->UpdateCRT1[i].ModeID)
+				index = i;
+		}
+	} else {
+		if (ModeNo == 0x2E
+				&& (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC
+						== RES640x480x60))
+			index = 12;
+		else if (ModeNo == 0x2E
+				&& (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC
+						== RES640x480x72))
+			index = 13;
+		else if (ModeNo == 0x2F)
+			index = 14;
+		else if (ModeNo == 0x50)
+			index = 15;
+		else if (ModeNo == 0x59)
+			index = 16;
 	}
 
-	j = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x0e);
-	j &= 0x1F;
-	data = pVBInfo->TimingH[0].data[7];
-	data &= 0xE0;
-	data |= j;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x0e, data);
-
-	if (HwDeviceExtension->jChipType >= XG20) {
-		data = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x04);
-		data = data - 1;
-		XGINew_SetReg1(pVBInfo->P3d4, 0x04, data);
-		data = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x05);
-		data1 = data;
-		data1 &= 0xE0;
-		data &= 0x1F;
-		if (data == 0) {
-			pushax = data;
-			data = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4,
-					0x0c);
-			data &= 0xFB;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x0c, data);
-			data = pushax;
-		}
-		data = data - 1;
-		data |= data1;
-		XGINew_SetReg1(pVBInfo->P3d4, 0x05, data);
-		data = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x0e);
-		data = data >> 5;
-		data = data + 3;
-		if (data > 7)
-			data = data - 7;
-		data = data << 5;
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0e, ~0xE0, data);
+	if (index != -1) {
+		xgifb_reg_set(pVBInfo->P3d4, 0x02,
+				pVBInfo->UpdateCRT1[index].CR02);
+		xgifb_reg_set(pVBInfo->P3d4, 0x03,
+				pVBInfo->UpdateCRT1[index].CR03);
+		xgifb_reg_set(pVBInfo->P3d4, 0x15,
+				pVBInfo->UpdateCRT1[index].CR15);
+		xgifb_reg_set(pVBInfo->P3d4, 0x16,
+				pVBInfo->UpdateCRT1[index].CR16);
 	}
 }
 
-void XGI_SetCRT1Timing_V(unsigned short ModeIdIndex, unsigned short ModeNo,
+static void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
+	unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
+
 	unsigned char data;
-	unsigned short i, j;
 
-	/* XGINew_SetReg1(pVBInfo->P3d4, 0x51, 0); */
-	/* XGINew_SetReg1(pVBInfo->P3d4, 0x56, 0); */
-	/* XGINew_SetRegANDOR(pVBInfo->P3d4, 0x11, 0x7f, 0x00); */
+	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
 
-	for (i = 0x00; i <= 0x01; i++) {
-		data = pVBInfo->TimingV[0].data[i];
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) (i + 6), data);
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+		tempax = pVBInfo->StResInfo[resindex].HTotal;
+		tempbx = pVBInfo->StResInfo[resindex].VTotal;
+	} else {
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		tempax = pVBInfo->ModeResInfo[resindex].HTotal;
+		tempbx = pVBInfo->ModeResInfo[resindex].VTotal;
 	}
 
-	for (i = 0x02; i <= 0x03; i++) {
-		data = pVBInfo->TimingV[0].data[i];
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) (i + 0x0e), data);
-	}
+	if (modeflag & HalfDCLK)
+		tempax = tempax >> 1;
 
-	for (i = 0x04; i <= 0x05; i++) {
-		data = pVBInfo->TimingV[0].data[i];
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) (i + 0x11), data);
+	if (ModeNo > 0x13) {
+		if (modeflag & HalfDCLK)
+			tempax = tempax << 1;
+
+		temp = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+
+		if (temp & InterlaceMode)
+			tempbx = tempbx >> 1;
+
+		if (modeflag & DoubleScanMode)
+			tempbx = tempbx << 1;
 	}
 
-	j = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x0a);
-	j &= 0xC0;
-	data = pVBInfo->TimingV[0].data[6];
-	data &= 0x3F;
-	data |= j;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x0a, data);
+	tempcx = 8;
 
-	data = pVBInfo->TimingV[0].data[6];
-	data &= 0x80;
-	data = data >> 2;
+	/* if (!(modeflag & Charx8Dot)) */
+	/* tempcx = 9; */
 
-	if (ModeNo <= 0x13)
-		i = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		i = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	tempax /= tempcx;
+	tempax -= 1;
+	tempbx -= 1;
+	tempcx = tempax;
+	temp = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
+	data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
+	data &= 0x7F;
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
+	xgifb_reg_set(pVBInfo->P3d4, 0x01, (unsigned short) (tempcx & 0xff));
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x0b, ~0x0c,
+			(unsigned short) ((tempcx & 0x0ff00) >> 10));
+	xgifb_reg_set(pVBInfo->P3d4, 0x12, (unsigned short) (tempbx & 0xff));
+	tempax = 0;
+	tempbx = tempbx >> 8;
 
-	i &= DoubleScanMode;
-	if (i)
-		data |= 0x80;
+	if (tempbx & 0x01)
+		tempax |= 0x02;
 
-	j = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x09);
-	j &= 0x5F;
-	data |= j;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x09, data);
+	if (tempbx & 0x02)
+		tempax |= 0x40;
+
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x42, tempax);
+	data = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x07);
+	data &= 0xFF;
+	tempax = 0;
+
+	if (tempbx & 0x04)
+		tempax |= 0x02;
+
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x0a, ~0x02, tempax);
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, temp);
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetXG21CRTC */
-/* Input : Stand or enhance CRTC table */
-/* Output : Fill CRT Hsync/Vsync to SR2E/SR2F/SR30/SR33/SR34/SR3F */
-/* Description : Set LCD timing */
-/* --------------------------------------------------------------------- */
-void XGI_SetXG21CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
+unsigned short XGI_GetResInfo(unsigned short ModeNo,
+		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
 {
-	unsigned char StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
-	unsigned short Temp1, Temp2, Temp3;
-
-	if (ModeNo <= 0x13) {
-		StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[4]; /* CR04 HRS */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E [7:0]->HRS */
-		Tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[5]; /* Tempbx: CR05 HRE */
-		Tempbx &= 0x1F; /* Tempbx: HRE[4:0] */
-		Tempcx = Tempax;
-		Tempcx &= 0xE0; /* Tempcx: HRS[7:5] */
-		Tempdx = Tempcx | Tempbx; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
-		if (Tempbx < (Tempax & 0x1F)) /* IF HRE < HRS */
-			Tempdx |= 0x20; /* Tempdx: HRE = HRE + 0x20 */
-		Tempdx <<= 2; /* Tempdx << 2 */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2F, Tempdx); /* SR2F [7:2]->HRE */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x30, 0xE3, 00);
+	unsigned short resindex;
 
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[16]; /* Tempax: CR16 VRS */
-		Tempbx = Tempax; /* Tempbx=Tempax */
-		Tempax &= 0x01; /* Tempax: VRS[0] */
-		XGINew_SetRegOR(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS */
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[7]; /* Tempax: CR7 VRS */
-		Tempdx = Tempbx >> 1; /* Tempdx: VRS[7:1] */
-		Tempcx = Tempax & 0x04; /* Tempcx: CR7[2] */
-		Tempcx <<= 5; /* Tempcx[7]: VRS[8] */
-		Tempdx |= Tempcx; /* Tempdx: VRS[8:1] */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x34, Tempdx); /* SR34[7:0]: VRS[8:1] */
+	if (ModeNo <= 0x13)
+		resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo; /* si+St_ResInfo */
+	else
+		resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo */
+	return resindex;
+}
 
-		Temp1 = Tempcx << 1; /* Temp1[8]: VRS[8] unsigned char -> unsigned short */
-		Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
-		Tempax &= 0x80; /* Tempax[7]: CR7[7] */
-		Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
-		Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
+static void XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short temp, ah, al, temp2, i, DisplayUnit;
 
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[17]; /* CR16 VRE */
-		Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
-		Temp2 = Temp1 & 0x3F0; /* Temp2[9:4]: VRS[9:4] */
-		Temp2 |= Tempax; /* Temp2[9:0]: VRE[9:0] */
-		Temp3 = Temp1 & 0x0F; /* Temp3[3:0]: VRS[3:0] */
-		if (Tempax < Temp3) /* VRE[3:0]<VRS[3:0] */
-			Temp2 |= 0x10; /* Temp2: VRE + 0x10 */
-		Temp2 &= 0xFF; /* Temp2[7:0]: VRE[7:0] */
-		Tempax = (unsigned char) Temp2; /* Tempax[7:0]: VRE[7:0] */
-		Tempax <<= 2; /* Tempax << 2: VRE[5:0] */
-		Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
-		Temp1 >>= 9; /* [10:9]->[1:0] */
-		Tempbx = (unsigned char) Temp1; /* Tempbx[1:0]: VRS[10:9] */
-		Tempax |= Tempbx; /* VRE[5:0]VRS[10:9] */
-		Tempax &= 0x7F;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x3F, Tempax); /* SR3F D[7:2]->VRE D[1:0]->VRS */
-	} else {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3]; /* Tempax: CR4 HRS */
-		Tempcx = Tempax; /* Tempcx: HRS */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E[7:0]->HRS */
+	/* GetOffset */
+	temp = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
+	temp = temp >> 8;
+	temp = pVBInfo->ScreenOffset[temp];
 
-		Tempdx = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SRB */
-		Tempdx &= 0xC0; /* Tempdx[7:6]: SRB[7:6] */
-		Temp1 = Tempdx; /* Temp1[7:6]: HRS[9:8] */
-		Temp1 <<= 2; /* Temp1[9:8]: HRS[9:8] */
-		Temp1 |= Tempax; /* Temp1[9:0]: HRS[9:0] */
+	temp2 = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	temp2 &= InterlaceMode;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
-		Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
+	if (temp2)
+		temp = temp << 1;
 
-		Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
-		Tempbx &= 0x04; /* Tempbx[2]: HRE[5] */
-		Tempbx <<= 3; /* Tempbx[5]: HRE[5] */
-		Tempax |= Tempbx; /* Tempax[5:0]: HRE[5:0] */
+	temp2 = pVBInfo->ModeType - ModeEGA;
 
-		Temp2 = Temp1 & 0x3C0; /* Temp2[9:6]: HRS[9:6] */
-		Temp2 |= Tempax; /* Temp2[9:0]: HRE[9:0] */
+	switch (temp2) {
+	case 0:
+		temp2 = 1;
+		break;
+	case 1:
+		temp2 = 2;
+		break;
+	case 2:
+		temp2 = 4;
+		break;
+	case 3:
+		temp2 = 4;
+		break;
+	case 4:
+		temp2 = 6;
+		break;
+	case 5:
+		temp2 = 8;
+		break;
+	default:
+		break;
+	}
 
-		Tempcx &= 0x3F; /* Tempcx[5:0]: HRS[5:0] */
-		if (Tempax < Tempcx) /* HRE < HRS */
-			Temp2 |= 0x40; /* Temp2 + 0x40 */
+	if ((ModeNo >= 0x26) && (ModeNo <= 0x28))
+		temp = temp * temp2 + temp2 / 2;
+	else
+		temp *= temp2;
 
-		Temp2 &= 0xFF;
-		Tempax = (unsigned char) Temp2; /* Tempax: HRE[7:0] */
-		Tempax <<= 2; /* Tempax[7:2]: HRE[5:0] */
-		Tempdx >>= 6; /* Tempdx[7:6]->[1:0] HRS[9:8] */
-		Tempax |= Tempdx; /* HRE[5:0]HRS[9:8] */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2F, Tempax); /* SR2F D[7:2]->HRE, D[1:0]->HRS */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x30, 0xE3, 00);
+	/* SetOffset */
+	DisplayUnit = temp;
+	temp2 = temp;
+	temp = temp >> 8; /* ah */
+	temp &= 0x0F;
+	i = xgifb_reg_get(pVBInfo->P3c4, 0x0E);
+	i &= 0xF0;
+	i |= temp;
+	xgifb_reg_set(pVBInfo->P3c4, 0x0E, i);
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10]; /* CR10 VRS */
-		Tempbx = Tempax; /* Tempbx: VRS */
-		Tempax &= 0x01; /* Tempax[0]: VRS[0] */
-		XGINew_SetRegOR(pVBInfo->P3c4, 0x33, Tempax); /* SR33[0]->VRS[0] */
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9]; /* CR7[2][7] VRE */
-		Tempcx = Tempbx >> 1; /* Tempcx[6:0]: VRS[7:1] */
-		Tempdx = Tempax & 0x04; /* Tempdx[2]: CR7[2] */
-		Tempdx <<= 5; /* Tempdx[7]: VRS[8] */
-		Tempcx |= Tempdx; /* Tempcx[7:0]: VRS[8:1] */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x34, Tempcx); /* SR34[8:1]->VRS */
+	temp = (unsigned char) temp2;
+	temp &= 0xFF; /* al */
+	xgifb_reg_set(pVBInfo->P3d4, 0x13, temp);
 
-		Temp1 = Tempdx; /* Temp1[7]: Tempdx[7] */
-		Temp1 <<= 1; /* Temp1[8]: VRS[8] */
-		Temp1 |= Tempbx; /* Temp1[8:0]: VRS[8:0] */
-		Tempax &= 0x80;
-		Temp2 = Tempax << 2; /* Temp2[9]: VRS[9] */
-		Temp1 |= Temp2; /* Temp1[9:0]: VRS[9:0] */
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempax: SRA */
-		Tempax &= 0x08; /* Tempax[3]: VRS[3] */
-		Temp2 = Tempax;
-		Temp2 <<= 7; /* Temp2[10]: VRS[10] */
-		Temp1 |= Temp2; /* Temp1[10:0]: VRS[10:0] */
+	/* SetDisplayUnit */
+	temp2 = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	temp2 &= InterlaceMode;
+	if (temp2)
+		DisplayUnit >>= 1;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11]; /* Tempax: CR11 VRE */
-		Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
-		Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempbx: SRA */
-		Tempbx &= 0x20; /* Tempbx[5]: VRE[5] */
-		Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
-		Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
-		Temp2 = Temp1 & 0x7E0; /* Temp2[10:5]: VRS[10:5] */
-		Temp2 |= Tempax; /* Temp2[10:5]: VRE[10:5] */
+	DisplayUnit = DisplayUnit << 5;
+	ah = (DisplayUnit & 0xff00) >> 8;
+	al = DisplayUnit & 0x00ff;
+	if (al == 0)
+		ah += 1;
+	else
+		ah += 2;
 
-		Temp3 = Temp1 & 0x1F; /* Temp3[4:0]: VRS[4:0] */
-		if (Tempax < Temp3) /* VRE < VRS */
-			Temp2 |= 0x20; /* VRE + 0x20 */
+	if (HwDeviceExtension->jChipType >= XG20)
+		if ((ModeNo == 0x4A) | (ModeNo == 0x49))
+			ah -= 1;
 
-		Temp2 &= 0xFF;
-		Tempax = (unsigned char) Temp2; /* Tempax: VRE[7:0] */
-		Tempax <<= 2; /* Tempax[7:0]; VRE[5:0]00 */
-		Temp1 &= 0x600; /* Temp1[10:9]: VRS[10:9] */
-		Temp1 >>= 9; /* Temp1[1:0]: VRS[10:9] */
-		Tempbx = (unsigned char) Temp1;
-		Tempax |= Tempbx; /* Tempax[7:0]: VRE[5:0]VRS[10:9] */
-		Tempax &= 0x7F;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x3F, Tempax); /* SR3F D[7:2]->VRE D[1:0]->VRS */
-	}
+	xgifb_reg_set(pVBInfo->P3c4, 0x10, ah);
 }
 
-void XGI_SetXG27CRTC(unsigned short ModeNo, unsigned short ModeIdIndex,
+static unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
+		unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short StandTableIndex, index, Tempax, Tempbx, Tempcx, Tempdx;
+	unsigned short tempbx;
 
-	if (ModeNo <= 0x13) {
-		StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[4]; /* CR04 HRS */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E [7:0]->HRS */
-		Tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[5]; /* Tempbx: CR05 HRE */
-		Tempbx &= 0x1F; /* Tempbx: HRE[4:0] */
-		Tempcx = Tempax;
-		Tempcx &= 0xE0; /* Tempcx: HRS[7:5] */
-		Tempdx = Tempcx | Tempbx; /* Tempdx(HRE): HRS[7:5]HRE[4:0] */
-		if (Tempbx < (Tempax & 0x1F)) /* IF HRE < HRS */
-			Tempdx |= 0x20; /* Tempdx: HRE = HRE + 0x20 */
-		Tempdx <<= 2; /* Tempdx << 2 */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2F, Tempdx); /* SR2F [7:2]->HRE */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x30, 0xE3, 00);
+	unsigned short LCDXlat1VCLK[4] = { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2,
+			VCLK65 + 2 };
+	unsigned short LCDXlat2VCLK[4] = { VCLK108_2 + 5, VCLK108_2 + 5,
+			VCLK108_2 + 5, VCLK108_2 + 5 };
+	unsigned short LVDSXlat1VCLK[4] = { VCLK40, VCLK40, VCLK40, VCLK40 };
+	unsigned short LVDSXlat2VCLK[4] = { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2,
+			VCLK65 + 2 };
+	unsigned short LVDSXlat3VCLK[4] = { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2,
+			VCLK65 + 2 };
 
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[16]; /* Tempax: CR10 VRS */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x34, Tempax); /* SR34[7:0]->VRS */
-		Tempcx = Tempax; /* Tempcx=Tempax=VRS[7:0] */
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[7]; /* Tempax[7][2]: CR7[7][2] VRS[9][8] */
-		Tempbx = Tempax; /* Tempbx=CR07 */
-		Tempax &= 0x04; /* Tempax[2]: CR07[2] VRS[8] */
-		Tempax >>= 2;
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x01, Tempax); /* SR35 D[0]->VRS D[8] */
-		Tempcx |= (Tempax << 8); /* Tempcx[8] |= VRS[8] */
-		Tempcx |= (Tempbx & 0x80) << 2; /* Tempcx[9] |= VRS[9] */
+	unsigned short CRT2Index, VCLKIndex;
+	unsigned short modeflag, resinfo;
+	unsigned char *CHTVVCLKPtr = NULL;
 
-		Tempax = pVBInfo->StandTable[StandTableIndex].CRTC[17]; /* CR11 VRE */
-		Tempax &= 0x0F; /* Tempax: VRE[3:0] */
-		Tempbx = Tempcx; /* Tempbx=Tempcx=VRS[9:0] */
-		Tempbx &= 0x3F0; /* Tempbx[9:4]: VRS[9:4] */
-		Tempbx |= Tempax; /* Tempbx[9:0]: VRE[9:0] */
-		if (Tempax <= (Tempcx & 0x0F)) /* VRE[3:0]<=VRS[3:0] */
-			Tempbx |= 0x10; /* Tempbx: VRE + 0x10 */
-		Tempax = (unsigned char) Tempbx & 0xFF; /* Tempax[7:0]: VRE[7:0] */
-		Tempax <<= 2; /* Tempax << 2: VRE[5:0] */
-		Tempcx = (Tempcx & 0x600) >> 8; /* Tempcx VRS[10:9] */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax); /* SR3F D[7:2]->VRE D[5:0] */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x06, Tempcx); /* SR35 D[2:1]->VRS[10:9] */
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
+		CRT2Index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
 	} else {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3]; /* Tempax: CR4 HRS */
-		Tempbx = Tempax; /* Tempbx: HRS[7:0] */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2E, Tempax); /* SR2E[7:0]->HRS */
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+		CRT2Index
+				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	}
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
-		Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
-		Tempbx |= (Tempax << 2); /* Tempbx: HRS[9:0] */
+	if (pVBInfo->IF_DEF_LVDS == 0) {
+		CRT2Index = CRT2Index >> 6; /*  for LCD */
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b*/
+			if (pVBInfo->LCDResInfo != Panel1024x768)
+				VCLKIndex = LCDXlat2VCLK[CRT2Index];
+			else
+				VCLKIndex = LCDXlat1VCLK[CRT2Index];
+		} else { /* for TV */
+			if (pVBInfo->VBInfo & SetCRT2ToTV) {
+				if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+					if (pVBInfo->SetFlag & RPLLDIV2XO) {
+						VCLKIndex = HiTVVCLKDIV2;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[4]; /* CR5 HRE */
-		Tempax &= 0x1F; /* Tempax[4:0]: HRE[4:0] */
-		Tempcx = Tempax; /* Tempcx: HRE[4:0] */
+						VCLKIndex += 25;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[6]; /* SRC */
-		Tempax &= 0x04; /* Tempax[2]: HRE[5] */
-		Tempax <<= 3; /* Tempax[5]: HRE[5] */
-		Tempcx |= Tempax; /* Tempcx[5:0]: HRE[5:0] */
+					} else {
+						VCLKIndex = HiTVVCLK;
 
-		Tempbx = Tempbx & 0x3C0; /* Tempbx[9:6]: HRS[9:6] */
-		Tempbx |= Tempcx; /* Tempbx: HRS[9:6]HRE[5:0] */
+						VCLKIndex += 25;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[3]; /* Tempax: CR4 HRS */
-		Tempax &= 0x3F; /* Tempax: HRS[5:0] */
-		if (Tempcx <= Tempax) /* HRE[5:0] < HRS[5:0] */
-			Tempbx += 0x40; /* Tempbx= Tempbx + 0x40 : HRE[9:0]*/
+					}
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[5]; /* SR0B */
-		Tempax &= 0xC0; /* Tempax[7:6]: SR0B[7:6]: HRS[9:8]*/
-		Tempax >>= 6; /* Tempax[1:0]: HRS[9:8]*/
-		Tempax |= ((Tempbx << 2) & 0xFF); /* Tempax[7:2]: HRE[5:0] */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2F, Tempax); /* SR2F [7:2][1:0]: HRE[5:0]HRS[9:8] */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x30, 0xE3, 00);
+					if (pVBInfo->SetFlag & TVSimuMode) {
+						if (modeflag & Charx8Dot) {
+							VCLKIndex
+									= HiTVSimuVCLK;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[10]; /* CR10 VRS */
-		XGINew_SetReg1(pVBInfo->P3c4, 0x34, Tempax); /* SR34[7:0]->VRS[7:0] */
+							VCLKIndex += 25;
 
-		Tempcx = Tempax; /* Tempcx <= VRS[7:0] */
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[9]; /* CR7[7][2] VRS[9][8] */
-		Tempbx = Tempax; /* Tempbx <= CR07[7:0] */
-		Tempax = Tempax & 0x04; /* Tempax[2]: CR7[2]: VRS[8] */
-		Tempax >>= 2; /* Tempax[0]: VRS[8] */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x01, Tempax); /* SR35[0]: VRS[8] */
-		Tempcx |= (Tempax << 8); /* Tempcx <= VRS[8:0] */
-		Tempcx |= ((Tempbx & 0x80) << 2); /* Tempcx <= VRS[9:0] */
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempax: SR0A */
-		Tempax &= 0x08; /* SR0A[3] VRS[10] */
-		Tempcx |= (Tempax << 7); /* Tempcx <= VRS[10:0] */
+						} else {
+							VCLKIndex
+									= HiTVTextVCLK;
 
-		Tempax = pVBInfo->XGINEWUB_CRT1Table[index].CR[11]; /* Tempax: CR11 VRE */
-		Tempax &= 0x0F; /* Tempax[3:0]: VRE[3:0] */
-		Tempbx = pVBInfo->XGINEWUB_CRT1Table[index].CR[14]; /* Tempbx: SR0A */
-		Tempbx &= 0x20; /* Tempbx[5]: SR0A[5]: VRE[4] */
-		Tempbx >>= 1; /* Tempbx[4]: VRE[4] */
-		Tempax |= Tempbx; /* Tempax[4:0]: VRE[4:0] */
-		Tempbx = Tempcx; /* Tempbx: VRS[10:0] */
-		Tempbx &= 0x7E0; /* Tempbx[10:5]: VRS[10:5] */
-		Tempbx |= Tempax; /* Tempbx: VRS[10:5]VRE[4:0] */
+							VCLKIndex += 25;
 
-		if (Tempbx <= Tempcx) /* VRE <= VRS */
-			Tempbx |= 0x20; /* VRE + 0x20 */
+						}
+					}
 
-		Tempax = (Tempbx << 2) & 0xFF; /* Tempax: Tempax[7:0]; VRE[5:0]00 */
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x3F, ~0xFC, Tempax); /* SR3F[7:2]:VRE[5:0] */
-		Tempax = Tempcx >> 8;
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x07, Tempax); /* SR35[2:0]:VRS[10:8] */
-	}
-}
+					if (pVBInfo->VBType & VB_XGI301LV) { /* 301lv */
+						if (!(pVBInfo->VBExtInfo
+								== VB_YPbPr1080i)) {
+							VCLKIndex
+									= YPbPr750pVCLK;
+							if (!(pVBInfo->VBExtInfo
+									== VB_YPbPr750p)) {
+								VCLKIndex
+										= YPbPr525pVCLK;
+								if (!(pVBInfo->VBExtInfo
+										== VB_YPbPr525p)) {
+									VCLKIndex
+											= YPbPr525iVCLK_2;
+									if (!(pVBInfo->SetFlag
+											& RPLLDIV2XO))
+										VCLKIndex
+												= YPbPr525iVCLK;
+								}
+							}
+						}
+					}
+				} else {
+					if (pVBInfo->VBInfo & SetCRT2ToTV) {
+						if (pVBInfo->SetFlag
+								& RPLLDIV2XO) {
+							VCLKIndex = TVVCLKDIV2;
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetXG21LCD */
-/* Input : */
-/* Output : FCLK duty cycle, FCLK delay compensation */
-/* Description : All values set zero */
-/* --------------------------------------------------------------------- */
-void XGI_SetXG21LCD(struct vb_device_info *pVBInfo,
-		unsigned short RefreshRateTableIndex, unsigned short ModeNo)
-{
-	unsigned short Data, Temp, b3CC;
-	unsigned short XGI_P3cc;
+							VCLKIndex += 25;
 
-	XGI_P3cc = pVBInfo->P3cc;
+						} else {
+							VCLKIndex = TVVCLK;
 
-	XGINew_SetReg1(pVBInfo->P3d4, 0x2E, 0x00);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x2F, 0x00);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x46, 0x00);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x47, 0x00);
-	if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) {
-		XGINew_SetReg1(pVBInfo->P3d4, 0x2E, *pVBInfo->pCR2E);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x2F, *pVBInfo->pCR2F);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x46, *pVBInfo->pCR46);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47);
-	}
+							VCLKIndex += 25;
+
+						}
+					}
+				}
+			} else { /* for CRT2 */
+				VCLKIndex = (unsigned char) inb(
+						(pVBInfo->P3ca + 0x02)); /* Port 3cch */
+				VCLKIndex = ((VCLKIndex >> 2) & 0x03);
+				if (ModeNo > 0x13) {
+					VCLKIndex
+							= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; /* di+Ext_CRTVCLK */
+					VCLKIndex &= IndexMask;
+				}
+			}
+		}
+	} else { /* LVDS */
+		if (ModeNo <= 0x13)
+			VCLKIndex = CRT2Index;
+		else
+			VCLKIndex = CRT2Index;
 
-	Temp = XGINew_GetReg1(pVBInfo->P3d4, 0x37);
+		if (pVBInfo->IF_DEF_CH7005 == 1) {
+			if (!(pVBInfo->VBInfo & SetCRT2ToLCD)) {
+				VCLKIndex &= 0x1f;
+				tempbx = 0;
 
-	if (Temp & 0x01) {
-		XGINew_SetRegOR(pVBInfo->P3c4, 0x06, 0x40); /* 18 bits FP */
-		XGINew_SetRegOR(pVBInfo->P3c4, 0x09, 0x40);
-	}
+				if (pVBInfo->VBInfo & SetPALTV)
+					tempbx += 2;
 
-	XGINew_SetRegOR(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
+				if (pVBInfo->VBInfo & SetCHTVOverScan)
+					tempbx += 1;
 
-	XGINew_SetRegAND(pVBInfo->P3c4, 0x30, ~0x20);
-	XGINew_SetRegAND(pVBInfo->P3c4, 0x35, ~0x80);
+				switch (tempbx) {
+				case 0:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC;
+					break;
+				case 1:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC;
+					break;
+				case 2:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL;
+					break;
+				case 3:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL;
+					break;
+				default:
+					break;
+				}
 
-	if (ModeNo <= 0x13) {
-		b3CC = (unsigned char) XGINew_GetReg2(XGI_P3cc);
-		if (b3CC & 0x40)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
-		if (b3CC & 0x80)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
-	} else {
-		Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-		if (Data & 0x4000)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
-		if (Data & 0x8000)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
+				VCLKIndex = CHTVVCLKPtr[VCLKIndex];
+			}
+		} else {
+			VCLKIndex = VCLKIndex >> 6;
+			if ((pVBInfo->LCDResInfo == Panel800x600)
+					|| (pVBInfo->LCDResInfo == Panel320x480))
+				VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
+			else if ((pVBInfo->LCDResInfo == Panel1024x768)
+					|| (pVBInfo->LCDResInfo
+							== Panel1024x768x75))
+				VCLKIndex = LVDSXlat2VCLK[VCLKIndex];
+			else
+				VCLKIndex = LVDSXlat3VCLK[VCLKIndex];
+		}
 	}
+	/* VCLKIndex = VCLKIndex&IndexMask; */
+
+	return VCLKIndex;
 }
 
-void XGI_SetXG27LCD(struct vb_device_info *pVBInfo,
-		unsigned short RefreshRateTableIndex, unsigned short ModeNo)
+static void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned short Data, Temp, b3CC;
-	unsigned short XGI_P3cc;
-
-	XGI_P3cc = pVBInfo->P3cc;
-
-	XGINew_SetReg1(pVBInfo->P3d4, 0x2E, 0x00);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x2F, 0x00);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x46, 0x00);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x47, 0x00);
+	unsigned char index, data;
+	unsigned short vclkindex;
 
-	Temp = XGINew_GetReg1(pVBInfo->P3d4, 0x37);
-	if ((Temp & 0x03) == 0) { /* dual 12 */
-		XGINew_SetReg1(pVBInfo->P3d4, 0x46, 0x13);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x47, 0x13);
+	if (pVBInfo->IF_DEF_LVDS == 1) {
+		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
+		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2B,
+				pVBInfo->VCLKData[index].SR2B);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2C,
+				pVBInfo->VCLKData[index].SR2C);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
+	} else if ((pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) && (pVBInfo->VBInfo
+			& SetCRT2ToLCDA)) {
+		vclkindex = XGI_GetVCLK2Ptr(ModeNo, ModeIdIndex,
+				RefreshRateTableIndex, HwDeviceExtension,
+				pVBInfo);
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
+		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
+		data = pVBInfo->VBVCLKData[vclkindex].Part4_A;
+		xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
+		data = pVBInfo->VBVCLKData[vclkindex].Part4_B;
+		xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
+	} else {
+		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x31) & 0xCF;
+		xgifb_reg_set(pVBInfo->P3c4, 0x31, data);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2B,
+				pVBInfo->VCLKData[index].SR2B);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2C,
+				pVBInfo->VCLKData[index].SR2C);
+		xgifb_reg_set(pVBInfo->P3c4, 0x2D, 0x01);
 	}
 
-	if (((*pVBInfo->pDVOSetting) & 0xC0) == 0xC0) {
-		XGINew_SetReg1(pVBInfo->P3d4, 0x2E, *pVBInfo->pCR2E);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x2F, *pVBInfo->pCR2F);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x46, *pVBInfo->pCR46);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x47, *pVBInfo->pCR47);
+	if (HwDeviceExtension->jChipType >= XG20) {
+		if (pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag & HalfDCLK) {
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x2B);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2B, data);
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x2C);
+			index = data;
+			index &= 0xE0;
+			data &= 0x1F;
+			data = data << 1;
+			data += 1;
+			data |= index;
+			xgifb_reg_set(pVBInfo->P3c4, 0x2C, data);
+		}
 	}
+}
 
-	XGI_SetXG27FPBits(pVBInfo);
-
-	XGINew_SetRegOR(pVBInfo->P3c4, 0x1E, 0x01); /* Negative blank polarity */
+static void XGI_SetCRT1FIFO(unsigned short ModeNo,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short data;
 
-	XGINew_SetRegAND(pVBInfo->P3c4, 0x30, ~0x20); /* Hsync polarity */
-	XGINew_SetRegAND(pVBInfo->P3c4, 0x35, ~0x80); /* Vsync polarity */
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
+	data &= 0xfe;
+	xgifb_reg_set(pVBInfo->P3c4, 0x3D, data); /* diable auto-threshold */
 
-	if (ModeNo <= 0x13) {
-		b3CC = (unsigned char) XGINew_GetReg2(XGI_P3cc);
-		if (b3CC & 0x40)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
-		if (b3CC & 0x80)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
+	if (ModeNo > 0x13) {
+		xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x34);
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
+		data &= 0xC0;
+		xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x30);
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x3D);
+		data |= 0x01;
+		xgifb_reg_set(pVBInfo->P3c4, 0x3D, data);
 	} else {
-		Data = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-		if (Data & 0x4000)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x30, 0x20); /* Hsync polarity */
-		if (Data & 0x8000)
-			XGINew_SetRegOR(pVBInfo->P3c4, 0x35, 0x80); /* Vsync polarity */
+		if (HwDeviceExtension->jChipType == XG27) {
+			xgifb_reg_set(pVBInfo->P3c4, 0x08, 0x0E);
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
+			data &= 0xC0;
+			xgifb_reg_set(pVBInfo->P3c4, 0x09, data | 0x20);
+		} else {
+			xgifb_reg_set(pVBInfo->P3c4, 0x08, 0xAE);
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x09);
+			data &= 0xF0;
+			xgifb_reg_set(pVBInfo->P3c4, 0x09, data);
+		}
 	}
+
+	if (HwDeviceExtension->jChipType == XG21)
+		XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_UpdateXG21CRTC */
-/* Input : */
-/* Output : CRT1 CRTC */
-/* Description : Modify CRT1 Hsync/Vsync to fix LCD mode timing */
-/* --------------------------------------------------------------------- */
-void XGI_UpdateXG21CRTC(unsigned short ModeNo, struct vb_device_info *pVBInfo,
-		unsigned short RefreshRateTableIndex)
+static void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short ModeNo, unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
 {
-	int i, index = -1;
+	unsigned short data, data2 = 0;
+	short VCLK;
 
-	XGINew_SetRegAND(pVBInfo->P3d4, 0x11, 0x7F); /* Unlock CR0~7 */
-	if (ModeNo <= 0x13) {
-		for (i = 0; i < 12; i++) {
-			if (ModeNo == pVBInfo->UpdateCRT1[i].ModeID)
-				index = i;
-		}
-	} else {
-		if (ModeNo == 0x2E
-				&& (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC
-						== RES640x480x60))
-			index = 12;
-		else if (ModeNo == 0x2E
-				&& (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC
-						== RES640x480x72))
-			index = 13;
-		else if (ModeNo == 0x2F)
-			index = 14;
-		else if (ModeNo == 0x50)
-			index = 15;
-		else if (ModeNo == 0x59)
-			index = 16;
-	}
-
-	if (index != -1) {
-		XGINew_SetReg1(pVBInfo->P3d4, 0x02,
-				pVBInfo->UpdateCRT1[index].CR02);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x03,
-				pVBInfo->UpdateCRT1[index].CR03);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x15,
-				pVBInfo->UpdateCRT1[index].CR15);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x16,
-				pVBInfo->UpdateCRT1[index].CR16);
-	}
-}
-
-void XGI_SetCRT1DE(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short resindex, tempax, tempbx, tempcx, temp, modeflag;
-
-	unsigned char data;
-
-	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
-
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-		tempax = pVBInfo->StResInfo[resindex].HTotal;
-		tempbx = pVBInfo->StResInfo[resindex].VTotal;
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		tempax = pVBInfo->ModeResInfo[resindex].HTotal;
-		tempbx = pVBInfo->ModeResInfo[resindex].VTotal;
-	}
-
-	if (modeflag & HalfDCLK)
-		tempax = tempax >> 1;
-
-	if (ModeNo > 0x13) {
-		if (modeflag & HalfDCLK)
-			tempax = tempax << 1;
-
-		temp = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-
-		if (temp & InterlaceMode)
-			tempbx = tempbx >> 1;
-
-		if (modeflag & DoubleScanMode)
-			tempbx = tempbx << 1;
-	}
-
-	tempcx = 8;
-
-	/* if (!(modeflag & Charx8Dot)) */
-	/* tempcx = 9; */
-
-	tempax /= tempcx;
-	tempax -= 1;
-	tempbx -= 1;
-	tempcx = tempax;
-	temp = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11);
-	data = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11);
-	data &= 0x7F;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, data); /* Unlock CRTC */
-	XGINew_SetReg1(pVBInfo->P3d4, 0x01, (unsigned short) (tempcx & 0xff));
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x0b, ~0x0c,
-			(unsigned short) ((tempcx & 0x0ff00) >> 10));
-	XGINew_SetReg1(pVBInfo->P3d4, 0x12, (unsigned short) (tempbx & 0xff));
-	tempax = 0;
-	tempbx = tempbx >> 8;
-
-	if (tempbx & 0x01)
-		tempax |= 0x02;
-
-	if (tempbx & 0x02)
-		tempax |= 0x40;
-
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x42, tempax);
-	data = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x07);
-	data &= 0xFF;
-	tempax = 0;
-
-	if (tempbx & 0x04)
-		tempax |= 0x02;
-
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x0a, ~0x02, tempax);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, temp);
-}
-
-unsigned short XGI_GetResInfo(unsigned short ModeNo,
-		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
-	unsigned short resindex;
+	unsigned char index;
 
 	if (ModeNo <= 0x13)
-		resindex = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo; /* si+St_ResInfo */
-	else
-		resindex = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo */
-	return resindex;
-}
-
-void XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short temp, ah, al, temp2, i, DisplayUnit;
-
-	/* GetOffset */
-	temp = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
-	temp = temp >> 8;
-	temp = pVBInfo->ScreenOffset[temp];
-
-	temp2 = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-	temp2 &= InterlaceMode;
-
-	if (temp2)
-		temp = temp << 1;
-
-	temp2 = pVBInfo->ModeType - ModeEGA;
-
-	switch (temp2) {
-	case 0:
-		temp2 = 1;
-		break;
-	case 1:
-		temp2 = 2;
-		break;
-	case 2:
-		temp2 = 4;
-		break;
-	case 3:
-		temp2 = 4;
-		break;
-	case 4:
-		temp2 = 6;
-		break;
-	case 5:
-		temp2 = 8;
-		break;
-	default:
-		break;
+		VCLK = 0;
+	else {
+		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+		index &= IndexMask;
+		VCLK = pVBInfo->VCLKData[index].CLOCK;
 	}
 
-	if ((ModeNo >= 0x26) && (ModeNo <= 0x28))
-		temp = temp * temp2 + temp2 / 2;
-	else
-		temp *= temp2;
-
-	/* SetOffset */
-	DisplayUnit = temp;
-	temp2 = temp;
-	temp = temp >> 8; /* ah */
-	temp &= 0x0F;
-	i = XGINew_GetReg1(pVBInfo->P3c4, 0x0E);
-	i &= 0xF0;
-	i |= temp;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x0E, i);
-
-	temp = (unsigned char) temp2;
-	temp &= 0xFF; /* al */
-	XGINew_SetReg1(pVBInfo->P3d4, 0x13, temp);
-
-	/* SetDisplayUnit */
-	temp2 = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
-	temp2 &= InterlaceMode;
-	if (temp2)
-		DisplayUnit >>= 1;
-
-	DisplayUnit = DisplayUnit << 5;
-	ah = (DisplayUnit & 0xff00) >> 8;
-	al = DisplayUnit & 0x00ff;
-	if (al == 0)
-		ah += 1;
-	else
-		ah += 2;
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x32);
+	data &= 0xf3;
+	if (VCLK >= 200)
+		data |= 0x0c; /* VCLK > 200 */
 
 	if (HwDeviceExtension->jChipType >= XG20)
-		if ((ModeNo == 0x4A) | (ModeNo == 0x49))
-			ah -= 1;
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x10, ah);
-}
-
-void XGI_SetCRT1VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned char index, data;
-	unsigned short vclkindex;
+		data &= ~0x04; /* 2 pixel mode */
 
-	if (pVBInfo->IF_DEF_LVDS == 1) {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x31) & 0xCF;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x31, data);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2B,
-				pVBInfo->VCLKData[index].SR2B);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2C,
-				pVBInfo->VCLKData[index].SR2C);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2D, 0x01);
-	} else if ((pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) && (pVBInfo->VBInfo
-			& SetCRT2ToLCDA)) {
-		vclkindex = XGI_GetVCLK2Ptr(ModeNo, ModeIdIndex,
-				RefreshRateTableIndex, HwDeviceExtension,
-				pVBInfo);
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x31) & 0xCF;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x31, data);
-		data = pVBInfo->VBVCLKData[vclkindex].Part4_A;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2B, data);
-		data = pVBInfo->VBVCLKData[vclkindex].Part4_B;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2C, data);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2D, 0x01);
-	} else {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x31) & 0xCF;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x31, data);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2B,
-				pVBInfo->VCLKData[index].SR2B);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2C,
-				pVBInfo->VCLKData[index].SR2C);
-		XGINew_SetReg1(pVBInfo->P3c4, 0x2D, 0x01);
-	}
+	xgifb_reg_set(pVBInfo->P3c4, 0x32, data);
 
-	if (HwDeviceExtension->jChipType >= XG20) {
-		if (pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag & HalfDCLK) {
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x2B);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2B, data);
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x2C);
-			index = data;
-			index &= 0xE0;
-			data &= 0x1F;
-			data = data << 1;
-			data += 1;
-			data |= index;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2C, data);
-		}
+	if (HwDeviceExtension->jChipType < XG20) {
+		data = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
+		data &= 0xE7;
+		if (VCLK < 200)
+			data |= 0x10;
+		xgifb_reg_set(pVBInfo->P3c4, 0x1F, data);
 	}
-}
-
-void XGI_SetCRT1FIFO(unsigned short ModeNo,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short data;
 
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x3D);
-	data &= 0xfe;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x3D, data); /* diable auto-threshold */
+	/*  Jong for Adavantech LCD ripple issue
+	if ((VCLK >= 0) && (VCLK < 135))
+		data2 = 0x03;
+	else if ((VCLK >= 135) && (VCLK < 160))
+		data2 = 0x02;
+	else if ((VCLK >= 160) && (VCLK < 260))
+		data2 = 0x01;
+	else if (VCLK > 260)
+		data2 = 0x00;
+	*/
+	data2 = 0x00;
 
-	if (ModeNo > 0x13) {
-		XGINew_SetReg1(pVBInfo->P3c4, 0x08, 0x34);
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x09);
-		data &= 0xC0;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x09, data | 0x30);
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x3D);
-		data |= 0x01;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x3D, data);
-	} else {
-		if (HwDeviceExtension->jChipType == XG27) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x08, 0x0E);
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x09);
-			data &= 0xC0;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x09, data | 0x20);
-		} else {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x08, 0xAE);
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x09);
-			data &= 0xF0;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x09, data);
-		}
-	}
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x07, 0xFC, data2);
+	if (HwDeviceExtension->jChipType >= XG27)
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x40, 0xFC, data2 & 0x03);
 
-	if (HwDeviceExtension->jChipType == XG21)
-		XGI_SetXG21FPBits(pVBInfo); /* Fix SR9[7:6] can't read back */
 }
 
-void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 		unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
@@ -1963,8 +1580,8 @@ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	} else
 		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
 
-	if (XGINew_GetReg1(pVBInfo->P3d4, 0x31) & 0x01)
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x1F, 0x3F, 0x00);
+	if (xgifb_reg_get(pVBInfo->P3d4, 0x31) & 0x01)
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x1F, 0x3F, 0x00);
 
 	if (ModeNo > 0x13)
 		data = infoflag;
@@ -1987,8 +1604,8 @@ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	if (data)
 		data2 |= 0x20;
 
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x06, ~0x3F, data2);
-	/* XGINew_SetReg1(pVBInfo->P3c4,0x06,data2); */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x3F, data2);
+	/* xgifb_reg_set(pVBInfo->P3c4,0x06,data2); */
 	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
 	if (ModeNo <= 0x13)
 		xres = pVBInfo->StResInfo[resindex].HTotal;
@@ -2004,12 +1621,12 @@ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	}
 
 	data2 = data & 0x00FF;
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x19, 0xFF, data2);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x19, 0xFF, data2);
 	data2 = (data & 0xFF00) >> 8;
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x19, 0xFC, data2);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x19, 0xFC, data2);
 
 	if (modeflag & HalfDCLK)
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x01, 0xF7, 0x08);
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xF7, 0x08);
 
 	data2 = 0;
 
@@ -2021,14 +1638,14 @@ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 			data2 |= 0x40;
 	}
 
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0F, ~0x48, data2);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0F, ~0x48, data2);
 	data = 0x60;
 	if (pVBInfo->ModeType != ModeText) {
 		data = data ^ 0x60;
 		if (pVBInfo->ModeType != ModeEGA)
 			data = data ^ 0xA0;
 	}
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x21, 0x1F, data);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x21, 0x1F, data);
 
 	XGI_SetVCLKState(HwDeviceExtension, ModeNo, RefreshRateTableIndex,
 			pVBInfo);
@@ -2037,95 +1654,41 @@ void XGI_SetCRT1ModeRegs(struct xgi_hw_device_info *HwDeviceExtension,
 	/* if (XGINew_IF_DEF_NEW_LOWRES) */
 	/* XGI_VesaLowResolution(ModeNo, ModeIdIndex); //030305 fix lowresolution bug */
 
-	data = XGINew_GetReg1(pVBInfo->P3d4, 0x31);
+	data = xgifb_reg_get(pVBInfo->P3d4, 0x31);
 
 	if (HwDeviceExtension->jChipType == XG27) {
 		if (data & 0x40)
 			data = 0x2c;
 		else
 			data = 0x6c;
-		XGINew_SetReg1(pVBInfo->P3d4, 0x52, data);
-		XGINew_SetRegOR(pVBInfo->P3d4, 0x51, 0x10);
+		xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
+		xgifb_reg_or(pVBInfo->P3d4, 0x51, 0x10);
 	} else if (HwDeviceExtension->jChipType >= XG20) {
 		if (data & 0x40)
 			data = 0x33;
 		else
 			data = 0x73;
-		XGINew_SetReg1(pVBInfo->P3d4, 0x52, data);
-		XGINew_SetReg1(pVBInfo->P3d4, 0x51, 0x02);
+		xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
+		xgifb_reg_set(pVBInfo->P3d4, 0x51, 0x02);
 	} else {
 		if (data & 0x40)
 			data = 0x2c;
 		else
 			data = 0x6c;
-		XGINew_SetReg1(pVBInfo->P3d4, 0x52, data);
+		xgifb_reg_set(pVBInfo->P3d4, 0x52, data);
 	}
 
 }
 
-void XGI_SetVCLKState(struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo, unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
+/*
+void XGI_VesaLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
 {
-	unsigned short data, data2 = 0;
-	short VCLK;
+	unsigned short modeflag;
 
-	unsigned char index;
-
-	if (ModeNo <= 0x13)
-		VCLK = 0;
-	else {
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-		index &= IndexMask;
-		VCLK = pVBInfo->VCLKData[index].CLOCK;
-	}
-
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x32);
-	data &= 0xf3;
-	if (VCLK >= 200)
-		data |= 0x0c; /* VCLK > 200 */
-
-	if (HwDeviceExtension->jChipType >= XG20)
-		data &= ~0x04; /* 2 pixel mode */
-
-	XGINew_SetReg1(pVBInfo->P3c4, 0x32, data);
-
-	if (HwDeviceExtension->jChipType < XG20) {
-		data = XGINew_GetReg1(pVBInfo->P3c4, 0x1F);
-		data &= 0xE7;
-		if (VCLK < 200)
-			data |= 0x10;
-		XGINew_SetReg1(pVBInfo->P3c4, 0x1F, data);
-	}
-
-	/*  Jong for Adavantech LCD ripple issue
-	if ((VCLK >= 0) && (VCLK < 135))
-		data2 = 0x03;
-	else if ((VCLK >= 135) && (VCLK < 160))
-		data2 = 0x02;
-	else if ((VCLK >= 160) && (VCLK < 260))
-		data2 = 0x01;
-	else if (VCLK > 260)
-		data2 = 0x00;
-	*/
-	data2 = 0x00;
-
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x07, 0xFC, data2);
-	if (HwDeviceExtension->jChipType >= XG27)
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x40, 0xFC, data2 & 0x03);
-
-}
-
-
-/*
-void XGI_VesaLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
-	unsigned short modeflag;
-
-	if (ModeNo > 0x13)
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	else
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	if (ModeNo > 0x13)
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	else
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
 
 	if (ModeNo > 0x13) {
 		if (modeflag & DoubleScanMode) {
@@ -2133,23 +1696,50 @@ void XGI_VesaLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, st
 				if (pVBInfo->VBType & VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
 					if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
 						if (pVBInfo->VBInfo & SetInSlaveMode) {
-							XGINew_SetRegANDOR(pVBInfo->P3c4, 0x01, 0xf7, 0x00);
-							XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0f, 0x7f, 0x00);
+							xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xf7, 0x00);
+							xgifb_reg_and_or(pVBInfo->P3c4, 0x0f, 0x7f, 0x00);
 							return;
 						}
 					}
 				}
-				XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0f, 0xff, 0x80);
-				XGINew_SetRegANDOR(pVBInfo->P3c4, 0x01, 0xf7, 0x00);
+				xgifb_reg_and_or(pVBInfo->P3c4, 0x0f, 0xff, 0x80);
+				xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xf7, 0x00);
 				return;
 			}
 		}
 	}
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0f, 0x7f, 0x00);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0f, 0x7f, 0x00);
 }
 */
 
-void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al,
+		unsigned short dh, struct vb_device_info *pVBInfo)
+{
+	unsigned short temp, bh, bl;
+
+	bh = ah;
+	bl = al;
+
+	if (dl != 0) {
+		temp = bh;
+		bh = dh;
+		dh = temp;
+		if (dl == 1) {
+			temp = bl;
+			bl = dh;
+			dh = temp;
+		} else {
+			temp = bl;
+			bl = bh;
+			bh = temp;
+		}
+	}
+	outb((unsigned short) dh, pVBInfo->P3c9);
+	outb((unsigned short) bh, pVBInfo->P3c9);
+	outb((unsigned short) bl, pVBInfo->P3c9);
+}
+
+static void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short data, data2, time, i, j, k, m, n, o, si, di, bx, dl, al,
@@ -2179,8 +1769,8 @@ void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	else
 		j = time;
 
-	XGINew_SetReg3(pVBInfo->P3c6, 0xFF);
-	XGINew_SetReg3(pVBInfo->P3c8, 0x00);
+	outb(0xFF, pVBInfo->P3c6);
+	outb(0x00, pVBInfo->P3c8);
 
 	for (i = 0; i < j; i++) {
 		data = table[i];
@@ -2194,7 +1784,7 @@ void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
 			if (data & 0x02)
 				data2 += 0x15;
 
-			XGINew_SetReg3(pVBInfo->P3c9, data2);
+			outb(data2, pVBInfo->P3c9);
 			data = data >> 2;
 		}
 	}
@@ -2204,7 +1794,7 @@ void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
 			data = table[i];
 
 			for (k = 0; k < 3; k++)
-				XGINew_SetReg3(pVBInfo->P3c9, data);
+				outb(data, pVBInfo->P3c9);
 		}
 
 		si = 32;
@@ -2241,54 +1831,7 @@ void XGI_LoadDAC(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-void XGI_WriteDAC(unsigned short dl, unsigned short ah, unsigned short al,
-		unsigned short dh, struct vb_device_info *pVBInfo)
-{
-	unsigned short temp, bh, bl;
-
-	bh = ah;
-	bl = al;
-
-	if (dl != 0) {
-		temp = bh;
-		bh = dh;
-		dh = temp;
-		if (dl == 1) {
-			temp = bl;
-			bl = dh;
-			dh = temp;
-		} else {
-			temp = bl;
-			bl = bh;
-			bh = temp;
-		}
-	}
-	XGINew_SetReg3(pVBInfo->P3c9, (unsigned short) dh);
-	XGINew_SetReg3(pVBInfo->P3c9, (unsigned short) bh);
-	XGINew_SetReg3(pVBInfo->P3c9, (unsigned short) bl);
-}
-
-void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short RefreshRateTableIndex;
-	/* unsigned short temp ; */
-
-	/* pVBInfo->SelectCRT2Rate = 0; */
-
-	pVBInfo->SetFlag |= ProgrammingCRT2;
-	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
-			ModeIdIndex, pVBInfo);
-	XGI_GetLVDSResInfo(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_GetLVDSData(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_ModCRT1Regs(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetLVDSRegs(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_SetCRT2ECLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-}
-
-void XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned short resindex, xres, yres, modeflag;
@@ -2337,4473 +1880,4401 @@ void XGI_GetLVDSResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 	pVBInfo->VDE = yres;
 }
 
-void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
+		unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx;
-	struct XGI330_LVDSDataStruct *LCDPtr = NULL;
-	struct XGI330_CHTVDataStruct *TVPtr = NULL;
+	unsigned short i, tempdx, tempcx, tempbx, tempal, modeflag, table;
 
-	tempbx = 2;
+	struct XGI330_LCDDataTablStruct *tempdi = NULL;
 
-	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-		LCDPtr = (struct XGI330_LVDSDataStruct *) XGI_GetLcdPtr(tempbx,
-				ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo);
-		pVBInfo->VGAHT = LCDPtr->VGAHT;
-		pVBInfo->VGAVT = LCDPtr->VGAVT;
-		pVBInfo->HT = LCDPtr->LCDHT;
-		pVBInfo->VT = LCDPtr->LCDVT;
-	}
-	if (pVBInfo->IF_DEF_CH7017 == 1) {
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			TVPtr = (struct XGI330_CHTVDataStruct *) XGI_GetTVPtr(
-					tempbx, ModeNo, ModeIdIndex,
-					RefreshRateTableIndex, pVBInfo);
-			pVBInfo->VGAHT = TVPtr->VGAHT;
-			pVBInfo->VGAVT = TVPtr->VGAVT;
-			pVBInfo->HT = TVPtr->LCDHT;
-			pVBInfo->VT = TVPtr->LCDVT;
-		}
-	}
+	tempbx = BX;
 
-	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-		if (!(pVBInfo->LCDInfo & (SetLCDtoNonExpanding
-				| EnableScalingLCD))) {
-			if ((pVBInfo->LCDResInfo == Panel1024x768)
-					|| (pVBInfo->LCDResInfo
-							== Panel1024x768x75)) {
-				pVBInfo->HDE = 1024;
-				pVBInfo->VDE = 768;
-			} else if ((pVBInfo->LCDResInfo == Panel1280x1024)
-					|| (pVBInfo->LCDResInfo
-							== Panel1280x1024x75)) {
-				pVBInfo->HDE = 1280;
-				pVBInfo->VDE = 1024;
-			} else if (pVBInfo->LCDResInfo == Panel1400x1050) {
-				pVBInfo->HDE = 1400;
-				pVBInfo->VDE = 1050;
-			} else {
-				pVBInfo->HDE = 1600;
-				pVBInfo->VDE = 1200;
-			}
-		}
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+		tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	} else {
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 	}
-}
-
-void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned char index;
-	unsigned short tempbx, i;
-	struct XGI_LVDSCRT1HDataStruct *LCDPtr = NULL;
-	struct XGI_LVDSCRT1VDataStruct *LCDPtr1 = NULL;
-	/* struct XGI330_CHTVDataStruct *TVPtr = NULL; */
-	struct XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
-	struct XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
-
-	if (ModeNo <= 0x13)
-		index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-	else
-		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-
-	index = index & IndexMask;
-
-	if ((pVBInfo->IF_DEF_ScaleLCD == 0) || ((pVBInfo->IF_DEF_ScaleLCD == 1)
-			&& (!(pVBInfo->LCDInfo & EnableScalingLCD)))) {
-		tempbx = 0;
 
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-			LCDPtr
-					= (struct XGI_LVDSCRT1HDataStruct *) XGI_GetLcdPtr(
-							tempbx, ModeNo,
-							ModeIdIndex,
-							RefreshRateTableIndex,
-							pVBInfo);
+	tempal = tempal & 0x0f;
 
-			for (i = 0; i < 8; i++)
-				pVBInfo->TimingH[0].data[i] = LCDPtr[0].Reg[i];
+	if (tempbx <= 1) { /* ExpLink */
+		if (ModeNo <= 0x13) {
+			tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC; /* find no Ext_CRT2CRTC2 */
+		} else {
+			tempal
+					= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 		}
 
-		if (pVBInfo->IF_DEF_CH7007 == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToTV) {
-				CH7007TV_TimingHPtr
-						= (struct XGI_CH7007TV_TimingHStruct *) XGI_GetTVPtr(
-								tempbx,
-								ModeNo,
-								ModeIdIndex,
-								RefreshRateTableIndex,
-								pVBInfo);
-
-				for (i = 0; i < 8; i++)
-					pVBInfo->TimingH[0].data[i]
-							= CH7007TV_TimingHPtr[0].data[i];
-			}
+		if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+			if (ModeNo <= 0x13)
+				tempal
+						= pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC2;
+			else
+				tempal
+						= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC2;
 		}
 
-		/* if (pVBInfo->IF_DEF_CH7017 == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToTV)
-				TVPtr = (struct XGI330_CHTVDataStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-		}
-		*/
+		if (tempbx & 0x01)
+			tempal = (tempal >> 4);
 
-		XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
+		tempal = (tempal & 0x0f);
+	}
 
-		if (pVBInfo->IF_DEF_CH7007 == 1) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2E,
-					CH7007TV_TimingHPtr[0].data[8]);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2F,
-					CH7007TV_TimingHPtr[0].data[9]);
-		}
+	tempcx = LCDLenList[tempbx]; /* mov cl,byte ptr cs:LCDLenList[bx] */
 
-		tempbx = 1;
+	if (pVBInfo->LCDInfo & EnableScalingLCD) { /* ScaleLCD */
+		if ((tempbx == 5) || (tempbx) == 7)
+			tempcx = LCDDesDataLen2;
+		else if ((tempbx == 3) || (tempbx == 8))
+			tempcx = LVDSDesDataLen2;
+	}
+	/* mov di, word ptr cs:LCDDataList[bx] */
+	/* tempdi = pVideoMemory[LCDDataList + tempbx * 2] | (pVideoMemory[LCDDataList + tempbx * 2 + 1] << 8); */
 
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-			LCDPtr1
-					= (struct XGI_LVDSCRT1VDataStruct *) XGI_GetLcdPtr(
-							tempbx, ModeNo,
-							ModeIdIndex,
-							RefreshRateTableIndex,
-							pVBInfo);
-			for (i = 0; i < 7; i++)
-				pVBInfo->TimingV[0].data[i] = LCDPtr1[0].Reg[i];
-		}
-
-		if (pVBInfo->IF_DEF_CH7007 == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToTV) {
-				CH7007TV_TimingVPtr
-						= (struct XGI_CH7007TV_TimingVStruct *) XGI_GetTVPtr(
-								tempbx,
-								ModeNo,
-								ModeIdIndex,
-								RefreshRateTableIndex,
-								pVBInfo);
-
-				for (i = 0; i < 7; i++)
-					pVBInfo->TimingV[0].data[i]
-							= CH7007TV_TimingVPtr[0].data[i];
-			}
-		}
-		/* if (pVBInfo->IF_DEF_CH7017 == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToTV)
-				TVPtr = (struct XGI330_CHTVDataStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-		}
-		*/
-
-		XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
-
-		if (pVBInfo->IF_DEF_CH7007 == 1) {
-			XGINew_SetRegANDOR(pVBInfo->P3c4, 0x33, ~0x01,
-					CH7007TV_TimingVPtr[0].data[7] & 0x01);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x34,
-					CH7007TV_TimingVPtr[0].data[8]);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x3F,
-					CH7007TV_TimingVPtr[0].data[9]);
-
-		}
+	switch (tempbx) {
+	case 0:
+		tempdi = XGI_EPLLCDCRT1Ptr_H;
+		break;
+	case 1:
+		tempdi = XGI_EPLLCDCRT1Ptr_V;
+		break;
+	case 2:
+		tempdi = XGI_EPLLCDDataPtr;
+		break;
+	case 3:
+		tempdi = XGI_EPLLCDDesDataPtr;
+		break;
+	case 4:
+		tempdi = XGI_LCDDataTable;
+		break;
+	case 5:
+		tempdi = XGI_LCDDesDataTable;
+		break;
+	case 6:
+		tempdi = XGI_EPLCHLCDRegPtr;
+		break;
+	case 7:
+	case 8:
+	case 9:
+		tempdi = NULL;
+		break;
+	default:
+		break;
 	}
-}
-
-void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
-	unsigned long temp, temp1, temp2, temp3, push3;
-	struct XGI330_LCDDataDesStruct *LCDPtr = NULL;
-	struct XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL;
-
-	if (ModeNo > 0x13)
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-	else
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-
-	if (!(pVBInfo->SetFlag & Win9xDOSMode)) {
-		if ((pVBInfo->IF_DEF_CH7017 == 0) || (pVBInfo->VBInfo
-				& (SetCRT2ToLCD | SetCRT2ToLCDA))) {
-			if (pVBInfo->IF_DEF_OEMUtil == 1) {
-				tempbx = 8;
-				LCDPtr
-						= (struct XGI330_LCDDataDesStruct *) XGI_GetLcdPtr(
-								tempbx,
-								ModeNo,
-								ModeIdIndex,
-								RefreshRateTableIndex,
-								pVBInfo);
-			}
-
-			if ((pVBInfo->IF_DEF_OEMUtil == 0) || (LCDPtr == NULL)) {
-				tempbx = 3;
-				if (pVBInfo->LCDInfo & EnableScalingLCD)
-					LCDPtr1
-							= (struct XGI330_LCDDataDesStruct2 *) XGI_GetLcdPtr(
-									tempbx,
-									ModeNo,
-									ModeIdIndex,
-									RefreshRateTableIndex,
-									pVBInfo);
-				else
-					LCDPtr
-							= (struct XGI330_LCDDataDesStruct *) XGI_GetLcdPtr(
-									tempbx,
-									ModeNo,
-									ModeIdIndex,
-									RefreshRateTableIndex,
-									pVBInfo);
-			}
-
-			XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
-			push1 = tempbx;
-			push2 = tempax;
-
-			/* GetLCDResInfo */
-			if ((pVBInfo->LCDResInfo == Panel1024x768)
-					|| (pVBInfo->LCDResInfo
-							== Panel1024x768x75)) {
-				tempax = 1024;
-				tempbx = 768;
-			} else if ((pVBInfo->LCDResInfo == Panel1280x1024)
-					|| (pVBInfo->LCDResInfo
-							== Panel1280x1024x75)) {
-				tempax = 1280;
-				tempbx = 1024;
-			} else if (pVBInfo->LCDResInfo == Panel1400x1050) {
-				tempax = 1400;
-				tempbx = 1050;
-			} else {
-				tempax = 1600;
-				tempbx = 1200;
-			}
-
-			if (pVBInfo->LCDInfo & SetLCDtoNonExpanding) {
-				pVBInfo->HDE = tempax;
-				pVBInfo->VDE = tempbx;
-				pVBInfo->VGAHDE = tempax;
-				pVBInfo->VGAVDE = tempbx;
-			}
-
-			if ((pVBInfo->IF_DEF_ScaleLCD == 1)
-					&& (pVBInfo->LCDInfo & EnableScalingLCD)) {
-				tempax = pVBInfo->HDE;
-				tempbx = pVBInfo->VDE;
-			}
-
-			tempax = pVBInfo->HT;
-
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				tempbx = LCDPtr1->LCDHDES;
-			else
-				tempbx = LCDPtr->LCDHDES;
-
-			tempcx = pVBInfo->HDE;
-			tempbx = tempbx & 0x0fff;
-			tempcx += tempbx;
-
-			if (tempcx >= tempax)
-				tempcx -= tempax;
-
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
-
-			tempcx = tempcx >> 3;
-			tempbx = tempbx >> 3;
-
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x16,
-					(unsigned short) (tempbx & 0xff));
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x17,
-					(unsigned short) (tempcx & 0xff));
-
-			tempax = pVBInfo->HT;
-
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				tempbx = LCDPtr1->LCDHRS;
-			else
-				tempbx = LCDPtr->LCDHRS;
-
-			tempcx = push2;
-
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				tempcx = LCDPtr1->LCDHSync;
-
-			tempcx += tempbx;
-
-			if (tempcx >= tempax)
-				tempcx -= tempax;
-
-			tempax = tempbx & 0x07;
-			tempax = tempax >> 5;
-			tempcx = tempcx >> 3;
-			tempbx = tempbx >> 3;
-
-			tempcx &= 0x1f;
-			tempax |= tempcx;
-
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x15, tempax);
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x14,
-					(unsigned short) (tempbx & 0xff));
-
-			tempax = pVBInfo->VT;
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				tempbx = LCDPtr1->LCDVDES;
-			else
-				tempbx = LCDPtr->LCDVDES;
-			tempcx = pVBInfo->VDE;
-
-			tempbx = tempbx & 0x0fff;
-			tempcx += tempbx;
-			if (tempcx >= tempax)
-				tempcx -= tempax;
 
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x1b,
-					(unsigned short) (tempbx & 0xff));
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x1c,
-					(unsigned short) (tempcx & 0xff));
+	if (tempdi == NULL) /* OEMUtil */
+		return NULL;
 
-			tempbx = (tempbx >> 8) & 0x07;
-			tempcx = (tempcx >> 8) & 0x07;
+	table = tempbx;
+	i = 0;
 
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x1d,
-					(unsigned short) ((tempcx << 3)
-							| tempbx));
+	while (tempdi[i].PANELID != 0xff) {
+		tempdx = pVBInfo->LCDResInfo;
+		if (tempbx & 0x0080) { /* OEMUtil */
+			tempbx &= (~0x0080);
+			tempdx = pVBInfo->LCDTypeInfo;
+		}
 
-			tempax = pVBInfo->VT;
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				tempbx = LCDPtr1->LCDVRS;
-			else
-				tempbx = LCDPtr->LCDVRS;
+		if (pVBInfo->LCDInfo & EnableScalingLCD)
+			tempdx &= (~PanelResInfo);
 
-			/* tempbx = tempbx >> 4; */
-			tempcx = push1;
+		if (tempdi[i].PANELID == tempdx) {
+			tempbx = tempdi[i].MASK;
+			tempdx = pVBInfo->LCDInfo;
 
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				tempcx = LCDPtr1->LCDVSync;
+			if (ModeNo <= 0x13) /* alan 09/10/2003 */
+				tempdx |= SetLCDStdMode;
 
-			tempcx += tempbx;
-			if (tempcx >= tempax)
-				tempcx -= tempax;
+			if (modeflag & HalfDCLK)
+				tempdx |= SetLCDLowResolution;
 
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x18,
-					(unsigned short) (tempbx & 0xff));
-			XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, ~0x0f,
-					(unsigned short) (tempcx & 0x0f));
+			tempbx &= tempdx;
+			if (tempbx == tempdi[i].CAP)
+				break;
+		}
+		i++;
+	}
 
-			tempax = ((tempbx >> 8) & 0x07) << 3;
+	if (table == 0) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_LVDSCRT11024x768_1_H[tempal];
+			break;
+		case 1:
+			return &XGI_LVDSCRT11024x768_2_H[tempal];
+			break;
+		case 2:
+			return &XGI_LVDSCRT11280x1024_1_H[tempal];
+			break;
+		case 3:
+			return &XGI_LVDSCRT11280x1024_2_H[tempal];
+			break;
+		case 4:
+			return &XGI_LVDSCRT11400x1050_1_H[tempal];
+			break;
+		case 5:
+			return &XGI_LVDSCRT11400x1050_2_H[tempal];
+			break;
+		case 6:
+			return &XGI_LVDSCRT11600x1200_1_H[tempal];
+			break;
+		case 7:
+			return &XGI_LVDSCRT11024x768_1_Hx75[tempal];
+			break;
+		case 8:
+			return &XGI_LVDSCRT11024x768_2_Hx75[tempal];
+			break;
+		case 9:
+			return &XGI_LVDSCRT11280x1024_1_Hx75[tempal];
+			break;
+		case 10:
+			return &XGI_LVDSCRT11280x1024_2_Hx75[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 1) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_LVDSCRT11024x768_1_V[tempal];
+			break;
+		case 1:
+			return &XGI_LVDSCRT11024x768_2_V[tempal];
+			break;
+		case 2:
+			return &XGI_LVDSCRT11280x1024_1_V[tempal];
+			break;
+		case 3:
+			return &XGI_LVDSCRT11280x1024_2_V[tempal];
+			break;
+		case 4:
+			return &XGI_LVDSCRT11400x1050_1_V[tempal];
+			break;
+		case 5:
+			return &XGI_LVDSCRT11400x1050_2_V[tempal];
+			break;
+		case 6:
+			return &XGI_LVDSCRT11600x1200_1_V[tempal];
+			break;
+		case 7:
+			return &XGI_LVDSCRT11024x768_1_Vx75[tempal];
+			break;
+		case 8:
+			return &XGI_LVDSCRT11024x768_2_Vx75[tempal];
+			break;
+		case 9:
+			return &XGI_LVDSCRT11280x1024_1_Vx75[tempal];
+			break;
+		case 10:
+			return &XGI_LVDSCRT11280x1024_2_Vx75[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 2) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_LVDS1024x768Data_1[tempal];
+			break;
+		case 1:
+			return &XGI_LVDS1024x768Data_2[tempal];
+			break;
+		case 2:
+			return &XGI_LVDS1280x1024Data_1[tempal];
+			break;
+		case 3:
+			return &XGI_LVDS1280x1024Data_2[tempal];
+			break;
+		case 4:
+			return &XGI_LVDS1400x1050Data_1[tempal];
+			break;
+		case 5:
+			return &XGI_LVDS1400x1050Data_2[tempal];
+			break;
+		case 6:
+			return &XGI_LVDS1600x1200Data_1[tempal];
+			break;
+		case 7:
+			return &XGI_LVDSNoScalingData[tempal];
+			break;
+		case 8:
+			return &XGI_LVDS1024x768Data_1x75[tempal];
+			break;
+		case 9:
+			return &XGI_LVDS1024x768Data_2x75[tempal];
+			break;
+		case 10:
+			return &XGI_LVDS1280x1024Data_1x75[tempal];
+			break;
+		case 11:
+			return &XGI_LVDS1280x1024Data_2x75[tempal];
+			break;
+		case 12:
+			return &XGI_LVDSNoScalingDatax75[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 3) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_LVDS1024x768Des_1[tempal];
+			break;
+		case 1:
+			return &XGI_LVDS1024x768Des_3[tempal];
+			break;
+		case 2:
+			return &XGI_LVDS1024x768Des_2[tempal];
+			break;
+		case 3:
+			return &XGI_LVDS1280x1024Des_1[tempal];
+			break;
+		case 4:
+			return &XGI_LVDS1280x1024Des_2[tempal];
+			break;
+		case 5:
+			return &XGI_LVDS1400x1050Des_1[tempal];
+			break;
+		case 6:
+			return &XGI_LVDS1400x1050Des_2[tempal];
+			break;
+		case 7:
+			return &XGI_LVDS1600x1200Des_1[tempal];
+			break;
+		case 8:
+			return &XGI_LVDSNoScalingDesData[tempal];
+			break;
+		case 9:
+			return &XGI_LVDS1024x768Des_1x75[tempal];
+			break;
+		case 10:
+			return &XGI_LVDS1024x768Des_3x75[tempal];
+			break;
+		case 11:
+			return &XGI_LVDS1024x768Des_2x75[tempal];
+			break;
+		case 12:
+			return &XGI_LVDS1280x1024Des_1x75[tempal];
+			break;
+		case 13:
+			return &XGI_LVDS1280x1024Des_2x75[tempal];
+			break;
+		case 14:
+			return &XGI_LVDSNoScalingDesDatax75[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 4) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_ExtLCD1024x768Data[tempal];
+			break;
+		case 1:
+			return &XGI_StLCD1024x768Data[tempal];
+			break;
+		case 2:
+			return &XGI_CetLCD1024x768Data[tempal];
+			break;
+		case 3:
+			return &XGI_ExtLCD1280x1024Data[tempal];
+			break;
+		case 4:
+			return &XGI_StLCD1280x1024Data[tempal];
+			break;
+		case 5:
+			return &XGI_CetLCD1280x1024Data[tempal];
+			break;
+		case 6:
+			return &XGI_ExtLCD1400x1050Data[tempal];
+			break;
+		case 7:
+			return &XGI_StLCD1400x1050Data[tempal];
+			break;
+		case 8:
+			return &XGI_CetLCD1400x1050Data[tempal];
+			break;
+		case 9:
+			return &XGI_ExtLCD1600x1200Data[tempal];
+			break;
+		case 10:
+			return &XGI_StLCD1600x1200Data[tempal];
+			break;
+		case 11:
+			return &XGI_NoScalingData[tempal];
+			break;
+		case 12:
+			return &XGI_ExtLCD1024x768x75Data[tempal];
+			break;
+		case 13:
+			return &XGI_ExtLCD1024x768x75Data[tempal];
+			break;
+		case 14:
+			return &XGI_CetLCD1024x768x75Data[tempal];
+			break;
+		case 15:
+			return &XGI_ExtLCD1280x1024x75Data[tempal];
+			break;
+		case 16:
+			return &XGI_StLCD1280x1024x75Data[tempal];
+			break;
+		case 17:
+			return &XGI_CetLCD1280x1024x75Data[tempal];
+			break;
+		case 18:
+			return &XGI_NoScalingDatax75[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 5) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_ExtLCDDes1024x768Data[tempal];
+			break;
+		case 1:
+			return &XGI_StLCDDes1024x768Data[tempal];
+			break;
+		case 2:
+			return &XGI_CetLCDDes1024x768Data[tempal];
+			break;
+		case 3:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_ExtLCDDLDes1280x1024Data[tempal];
+			else
+				return &XGI_ExtLCDDes1280x1024Data[tempal];
+			break;
+		case 4:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_StLCDDLDes1280x1024Data[tempal];
+			else
+				return &XGI_StLCDDes1280x1024Data[tempal];
+			break;
+		case 5:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_CetLCDDLDes1280x1024Data[tempal];
+			else
+				return &XGI_CetLCDDes1280x1024Data[tempal];
+			break;
+		case 6:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_ExtLCDDLDes1400x1050Data[tempal];
+			else
+				return &XGI_ExtLCDDes1400x1050Data[tempal];
+			break;
+		case 7:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_StLCDDLDes1400x1050Data[tempal];
+			else
+				return &XGI_StLCDDes1400x1050Data[tempal];
+			break;
+		case 8:
+			return &XGI_CetLCDDes1400x1050Data[tempal];
+			break;
+		case 9:
+			return &XGI_CetLCDDes1400x1050Data2[tempal];
+			break;
+		case 10:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_ExtLCDDLDes1600x1200Data[tempal];
+			else
+				return &XGI_ExtLCDDes1600x1200Data[tempal];
+			break;
+		case 11:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_StLCDDLDes1600x1200Data[tempal];
+			else
+				return &XGI_StLCDDes1600x1200Data[tempal];
+			break;
+		case 12:
+			return &XGI_NoScalingDesData[tempal];
+			break;
+		case 13:
+			return &XGI_ExtLCDDes1024x768x75Data[tempal];
+			break;
+		case 14:
+			return &XGI_StLCDDes1024x768x75Data[tempal];
+			break;
+		case 15:
+			return &XGI_CetLCDDes1024x768x75Data[tempal];
+			break;
+		case 16:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_ExtLCDDLDes1280x1024x75Data[tempal];
+			else
+				return &XGI_ExtLCDDes1280x1024x75Data[tempal];
+			break;
+		case 17:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_StLCDDLDes1280x1024x75Data[tempal];
+			else
+				return &XGI_StLCDDes1280x1024x75Data[tempal];
+			break;
+		case 18:
+			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV))
+				return &XGI_CetLCDDLDes1280x1024x75Data[tempal];
+			else
+				return &XGI_CetLCDDes1280x1024x75Data[tempal];
+			break;
+		case 19:
+			return &XGI_NoScalingDesDatax75[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 6) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_CH7017LV1024x768[tempal];
+			break;
+		case 1:
+			return &XGI_CH7017LV1400x1050[tempal];
+			break;
+		default:
+			break;
+		}
+	}
+	return NULL;
+}
 
-			tempbx = pVBInfo->VGAVDE;
-			if (tempbx != pVBInfo->VDE)
-				tempax |= 0x40;
+static void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
+		unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short i, tempdx, tempbx, tempal, modeflag, table;
+	struct XGI330_TVDataTablStruct *tempdi = NULL;
 
-			if (pVBInfo->LCDInfo & EnableLVDSDDA)
-				tempax |= 0x40;
+	tempbx = BX;
 
-			XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x1a, 0x07,
-					tempax);
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+		tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	} else {
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	}
 
-			tempcx = pVBInfo->VGAVT;
-			tempbx = pVBInfo->VDE;
-			tempax = pVBInfo->VGAVDE;
-			tempcx -= tempax;
+	tempal = tempal & 0x3f;
+	table = tempbx;
 
-			temp = tempax; /* 0430 ylshieh */
-			temp1 = (temp << 18) / tempbx;
+	switch (tempbx) {
+	case 0:
+		tempdi = NULL; /*EPLCHTVCRT1Ptr_H;*/
+		if (pVBInfo->IF_DEF_CH7007 == 1)
+			tempdi = XGI_EPLCHTVCRT1Ptr;
 
-			tempdx = (unsigned short) ((temp << 18) % tempbx);
+		break;
+	case 1:
+		tempdi = NULL; /*EPLCHTVCRT1Ptr_V;*/
+		if (pVBInfo->IF_DEF_CH7007 == 1)
+			tempdi = XGI_EPLCHTVCRT1Ptr;
+
+		break;
+	case 2:
+		tempdi = XGI_EPLCHTVDataPtr;
+		break;
+	case 3:
+		tempdi = NULL;
+		break;
+	case 4:
+		tempdi = XGI_TVDataTable;
+		break;
+	case 5:
+		tempdi = NULL;
+		break;
+	case 6:
+		tempdi = XGI_EPLCHTVRegPtr;
+		break;
+	default:
+		break;
+	}
+
+	if (tempdi == NULL) /* OEMUtil */
+		return NULL;
+
+	tempdx = pVBInfo->TVInfo;
+
+	if (pVBInfo->VBInfo & SetInSlaveMode)
+		tempdx = tempdx | SetTVLockMode;
+
+	if (modeflag & HalfDCLK)
+		tempdx = tempdx | SetTVLowResolution;
+
+	i = 0;
+
+	while (tempdi[i].MASK != 0xffff) {
+		if ((tempdx & tempdi[i].MASK) == tempdi[i].CAP)
+			break;
+		i++;
+	}
+
+	if (table == 0x00) { /* 07/05/22 */
+	} else if (table == 0x01) {
+	} else if (table == 0x04) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_ExtPALData[tempal];
+			break;
+		case 1:
+			return &XGI_ExtNTSCData[tempal];
+			break;
+		case 2:
+			return &XGI_StPALData[tempal];
+			break;
+		case 3:
+			return &XGI_StNTSCData[tempal];
+			break;
+		case 4:
+			return &XGI_ExtHiTVData[tempal];
+			break;
+		case 5:
+			return &XGI_St2HiTVData[tempal];
+			break;
+		case 6:
+			return &XGI_ExtYPbPr525iData[tempal];
+			break;
+		case 7:
+			return &XGI_ExtYPbPr525pData[tempal];
+			break;
+		case 8:
+			return &XGI_ExtYPbPr750pData[tempal];
+			break;
+		case 9:
+			return &XGI_StYPbPr525iData[tempal];
+			break;
+		case 10:
+			return &XGI_StYPbPr525pData[tempal];
+			break;
+		case 11:
+			return &XGI_StYPbPr750pData[tempal];
+			break;
+		case 12: /* avoid system hang */
+			return &XGI_ExtNTSCData[tempal];
+			break;
+		case 13:
+			return &XGI_St1HiTVData[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 0x02) {
+		switch (tempdi[i].DATAPTR) {
+		case 0:
+			return &XGI_CHTVUNTSCData[tempal];
+			break;
+		case 1:
+			return &XGI_CHTVONTSCData[tempal];
+			break;
+		case 2:
+			return &XGI_CHTVUPALData[tempal];
+			break;
+		case 3:
+			return &XGI_CHTVOPALData[tempal];
+			break;
+		default:
+			break;
+		}
+	} else if (table == 0x06) {
+	}
+	return NULL;
+}
+
+static void XGI_GetLVDSData(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx;
+	struct XGI330_LVDSDataStruct *LCDPtr = NULL;
+	struct XGI330_CHTVDataStruct *TVPtr = NULL;
+
+	tempbx = 2;
+
+	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+		LCDPtr = (struct XGI330_LVDSDataStruct *) XGI_GetLcdPtr(tempbx,
+				ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				pVBInfo);
+		pVBInfo->VGAHT = LCDPtr->VGAHT;
+		pVBInfo->VGAVT = LCDPtr->VGAVT;
+		pVBInfo->HT = LCDPtr->LCDHT;
+		pVBInfo->VT = LCDPtr->LCDVT;
+	}
+	if (pVBInfo->IF_DEF_CH7017 == 1) {
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			TVPtr = (struct XGI330_CHTVDataStruct *) XGI_GetTVPtr(
+					tempbx, ModeNo, ModeIdIndex,
+					RefreshRateTableIndex, pVBInfo);
+			pVBInfo->VGAHT = TVPtr->VGAHT;
+			pVBInfo->VGAVT = TVPtr->VGAVT;
+			pVBInfo->HT = TVPtr->LCDHT;
+			pVBInfo->VT = TVPtr->LCDVT;
+		}
+	}
+
+	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+		if (!(pVBInfo->LCDInfo & (SetLCDtoNonExpanding
+				| EnableScalingLCD))) {
+			if ((pVBInfo->LCDResInfo == Panel1024x768)
+					|| (pVBInfo->LCDResInfo
+							== Panel1024x768x75)) {
+				pVBInfo->HDE = 1024;
+				pVBInfo->VDE = 768;
+			} else if ((pVBInfo->LCDResInfo == Panel1280x1024)
+					|| (pVBInfo->LCDResInfo
+							== Panel1280x1024x75)) {
+				pVBInfo->HDE = 1280;
+				pVBInfo->VDE = 1024;
+			} else if (pVBInfo->LCDResInfo == Panel1400x1050) {
+				pVBInfo->HDE = 1400;
+				pVBInfo->VDE = 1050;
+			} else {
+				pVBInfo->HDE = 1600;
+				pVBInfo->VDE = 1200;
+			}
+		}
+	}
+}
 
-			if (tempdx != 0)
-				temp1 += 1;
+static void XGI_ModCRT1Regs(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned char index;
+	unsigned short tempbx, i;
+	struct XGI_LVDSCRT1HDataStruct *LCDPtr = NULL;
+	struct XGI_LVDSCRT1VDataStruct *LCDPtr1 = NULL;
+	/* struct XGI330_CHTVDataStruct *TVPtr = NULL; */
+	struct XGI_CH7007TV_TimingHStruct *CH7007TV_TimingHPtr = NULL;
+	struct XGI_CH7007TV_TimingVStruct *CH7007TV_TimingVPtr = NULL;
 
-			temp2 = temp1;
-			push3 = temp2;
+	if (ModeNo <= 0x13)
+		index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+	else
+		index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x37,
-					(unsigned short) (temp2 & 0xff));
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x36,
-					(unsigned short) ((temp2 >> 8) & 0xff));
+	index = index & IndexMask;
 
-			tempbx = (unsigned short) (temp2 >> 16);
-			tempax = tempbx & 0x03;
+	if ((pVBInfo->IF_DEF_ScaleLCD == 0) || ((pVBInfo->IF_DEF_ScaleLCD == 1)
+			&& (!(pVBInfo->LCDInfo & EnableScalingLCD)))) {
+		tempbx = 0;
 
-			tempbx = pVBInfo->VGAVDE;
-			if (tempbx == pVBInfo->VDE)
-				tempax |= 0x04;
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+			LCDPtr
+					= (struct XGI_LVDSCRT1HDataStruct *) XGI_GetLcdPtr(
+							tempbx, ModeNo,
+							ModeIdIndex,
+							RefreshRateTableIndex,
+							pVBInfo);
 
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x35, tempax);
+			for (i = 0; i < 8; i++)
+				pVBInfo->TimingH[0].data[i] = LCDPtr[0].Reg[i];
+		}
 
-			if (pVBInfo->VBType & VB_XGI301C) {
-				temp2 = push3;
-				XGINew_SetReg1(pVBInfo->Part4Port, 0x3c,
-						(unsigned short) (temp2 & 0xff));
-				XGINew_SetReg1(pVBInfo->Part4Port, 0x3b,
-						(unsigned short) ((temp2 >> 8)
-								& 0xff));
-				tempbx = (unsigned short) (temp2 >> 16);
-				XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x3a,
-						~0xc0,
-						(unsigned short) ((tempbx
-								& 0xff) << 6));
+		if (pVBInfo->IF_DEF_CH7007 == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToTV) {
+				CH7007TV_TimingHPtr
+						= (struct XGI_CH7007TV_TimingHStruct *) XGI_GetTVPtr(
+								tempbx,
+								ModeNo,
+								ModeIdIndex,
+								RefreshRateTableIndex,
+								pVBInfo);
 
-				tempcx = pVBInfo->VGAVDE;
-				if (tempcx == pVBInfo->VDE)
-					XGINew_SetRegANDOR(pVBInfo->Part4Port,
-							0x30, ~0x0c, 0x00);
-				else
-					XGINew_SetRegANDOR(pVBInfo->Part4Port,
-							0x30, ~0x0c, 0x08);
+				for (i = 0; i < 8; i++)
+					pVBInfo->TimingH[0].data[i]
+							= CH7007TV_TimingHPtr[0].data[i];
 			}
+		}
 
-			tempcx = pVBInfo->VGAHDE;
-			tempbx = pVBInfo->HDE;
-
-			temp1 = tempcx << 16;
-
-			tempax = (unsigned short) (temp1 / tempbx);
-
-			if ((tempbx & 0xffff) == (tempcx & 0xffff))
-				tempax = 65535;
-
-			temp3 = tempax;
-			temp1 = pVBInfo->VGAHDE << 16;
+		/* if (pVBInfo->IF_DEF_CH7017 == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToTV)
+				TVPtr = (struct XGI330_CHTVDataStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+		}
+		*/
 
-			temp1 /= temp3;
-			temp3 = temp3 << 16;
-			temp1 -= 1;
+		XGI_SetCRT1Timing_H(pVBInfo, HwDeviceExtension);
 
-			temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
+		if (pVBInfo->IF_DEF_CH7007 == 1) {
+			xgifb_reg_set(pVBInfo->P3c4, 0x2E,
+					CH7007TV_TimingHPtr[0].data[8]);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2F,
+					CH7007TV_TimingHPtr[0].data[9]);
+		}
 
-			tempax = (unsigned short) (temp3 & 0xff);
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x1f, tempax);
+		tempbx = 1;
 
-			temp1 = pVBInfo->VGAVDE << 18;
-			temp1 = temp1 / push3;
-			tempbx = (unsigned short) (temp1 & 0xffff);
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+			LCDPtr1
+					= (struct XGI_LVDSCRT1VDataStruct *) XGI_GetLcdPtr(
+							tempbx, ModeNo,
+							ModeIdIndex,
+							RefreshRateTableIndex,
+							pVBInfo);
+			for (i = 0; i < 7; i++)
+				pVBInfo->TimingV[0].data[i] = LCDPtr1[0].Reg[i];
+		}
 
-			if (pVBInfo->LCDResInfo == Panel1024x768)
-				tempbx -= 1;
+		if (pVBInfo->IF_DEF_CH7007 == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToTV) {
+				CH7007TV_TimingVPtr
+						= (struct XGI_CH7007TV_TimingVStruct *) XGI_GetTVPtr(
+								tempbx,
+								ModeNo,
+								ModeIdIndex,
+								RefreshRateTableIndex,
+								pVBInfo);
 
-			tempax = ((tempbx >> 8) & 0xff) << 3;
-			tempax |= (unsigned short) ((temp3 >> 8) & 0x07);
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x20,
-					(unsigned short) (tempax & 0xff));
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x21,
-					(unsigned short) (tempbx & 0xff));
+				for (i = 0; i < 7; i++)
+					pVBInfo->TimingV[0].data[i]
+							= CH7007TV_TimingVPtr[0].data[i];
+			}
+		}
+		/* if (pVBInfo->IF_DEF_CH7017 == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToTV)
+				TVPtr = (struct XGI330_CHTVDataStruct *)XGI_GetTVPtr(tempbx, ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+		}
+		*/
 
-			temp3 = temp3 >> 16;
+		XGI_SetCRT1Timing_V(ModeIdIndex, ModeNo, pVBInfo);
 
-			if (modeflag & HalfDCLK)
-				temp3 = temp3 >> 1;
+		if (pVBInfo->IF_DEF_CH7007 == 1) {
+			xgifb_reg_and_or(pVBInfo->P3c4, 0x33, ~0x01,
+					CH7007TV_TimingVPtr[0].data[7] & 0x01);
+			xgifb_reg_set(pVBInfo->P3c4, 0x34,
+					CH7007TV_TimingVPtr[0].data[8]);
+			xgifb_reg_set(pVBInfo->P3c4, 0x3F,
+					CH7007TV_TimingVPtr[0].data[9]);
 
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x22,
-					(unsigned short) ((temp3 >> 8) & 0xff));
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x23,
-					(unsigned short) (temp3 & 0xff));
 		}
 	}
 }
 
-void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
+static unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
 {
-	unsigned char di_0, di_1, tempal;
-	int i;
+	unsigned char tempal, tempah, tempbl, i;
 
-	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex,
-			pVBInfo);
-	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
-	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
+	tempah = xgifb_reg_get(pVBInfo->P3d4, 0x36);
+	tempal = tempah & 0x0F;
+	tempah = tempah & 0xF0;
+	i = 0;
+	tempbl = pVBInfo->LCDCapList[i].LCD_ID;
 
-	for (i = 0; i < 4; i++) {
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x31, ~0x30,
-				(unsigned short) (0x10 * i));
-		if (pVBInfo->IF_DEF_CH7007 == 1) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2b, di_0);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2c, di_1);
-		} else if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA))
-				&& (!(pVBInfo->VBInfo & SetInSlaveMode))) {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2e, di_0);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2f, di_1);
-		} else {
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2b, di_0);
-			XGINew_SetReg1(pVBInfo->P3c4, 0x2c, di_1);
+	while (tempbl != 0xFF) {
+		if (tempbl & 0x80) { /* OEMUtil */
+			tempal = tempah;
+			tempbl = tempbl & ~(0x80);
 		}
+
+		if (tempal == tempbl)
+			break;
+
+		i++;
+
+		tempbl = pVBInfo->LCDCapList[i].LCD_ID;
 	}
+
+	return i;
 }
 
-void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static unsigned short XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo)
 {
-	unsigned short tempcl, tempch, temp, tempbl, tempax;
+	unsigned short tempah, tempal, tempbl, i;
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		tempcl = 0;
-		tempch = 0;
-		temp = XGINew_GetReg1(pVBInfo->P3c4, 0x01);
+	tempal = pVBInfo->LCDResInfo;
+	tempah = pVBInfo->LCDTypeInfo;
 
-		if (!(temp & 0x20)) {
-			temp = XGINew_GetReg1(pVBInfo->P3d4, 0x17);
-			if (temp & 0x80) {
-				if ((HwDeviceExtension->jChipType >= XG20)
-						|| (HwDeviceExtension->jChipType
-								>= XG40))
-					temp = XGINew_GetReg1(pVBInfo->P3d4,
-							0x53);
-				else
-					temp = XGINew_GetReg1(pVBInfo->P3d4,
-							0x63);
+	i = 0;
+	tempbl = pVBInfo->LCDCapList[i].LCD_ID;
 
-				if (!(temp & 0x40))
-					tempcl |= ActiveCRT1;
-			}
+	while (tempbl != 0xFF) {
+		if ((tempbl & 0x80) && (tempbl != 0x80)) {
+			tempal = tempah;
+			tempbl &= ~0x80;
 		}
 
-		temp = XGINew_GetReg1(pVBInfo->Part1Port, 0x2e);
-		temp &= 0x0f;
+		if (tempal == tempbl)
+			break;
 
-		if (!(temp == 0x08)) {
-			tempax = XGINew_GetReg1(pVBInfo->Part1Port, 0x13); /* Check ChannelA by Part1_13 [2003/10/03] */
-			if (tempax & 0x04)
-				tempcl = tempcl | ActiveLCD;
+		i++;
+		tempbl = pVBInfo->LCDCapList[i].LCD_ID;
+	}
 
-			temp &= 0x05;
+	if (tempbl == 0xFF) {
+		pVBInfo->LCDResInfo = Panel1024x768;
+		pVBInfo->LCDTypeInfo = 0;
+		i = 0;
+	}
 
-			if (!(tempcl & ActiveLCD))
-				if (temp == 0x01)
-					tempcl |= ActiveCRT2;
+	return i;
+}
 
-			if (temp == 0x04)
-				tempcl |= ActiveLCD;
+static void XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short Index;
 
-			if (temp == 0x05) {
-				temp = XGINew_GetReg1(pVBInfo->Part2Port, 0x00);
+	Index = XGI_GetLCDCapPtr(pVBInfo);
+	*HSyncWidth = pVBInfo->LCDCapList[Index].LCD_HSyncWidth;
+	*VSyncWidth = pVBInfo->LCDCapList[Index].LCD_VSyncWidth;
 
-				if (!(temp & 0x08))
-					tempch |= ActiveAVideo;
+	return;
+}
 
-				if (!(temp & 0x04))
-					tempch |= ActiveSVideo;
+static void XGI_SetLVDSRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, tempax, tempcx, tempdx, push1, push2, modeflag;
+	unsigned long temp, temp1, temp2, temp3, push3;
+	struct XGI330_LCDDataDesStruct *LCDPtr = NULL;
+	struct XGI330_LCDDataDesStruct2 *LCDPtr1 = NULL;
 
-				if (temp & 0x02)
-					tempch |= ActiveSCART;
+	if (ModeNo > 0x13)
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	else
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+
+	if (!(pVBInfo->SetFlag & Win9xDOSMode)) {
+		if ((pVBInfo->IF_DEF_CH7017 == 0) || (pVBInfo->VBInfo
+				& (SetCRT2ToLCD | SetCRT2ToLCDA))) {
+			if (pVBInfo->IF_DEF_OEMUtil == 1) {
+				tempbx = 8;
+				LCDPtr
+						= (struct XGI330_LCDDataDesStruct *) XGI_GetLcdPtr(
+								tempbx,
+								ModeNo,
+								ModeIdIndex,
+								RefreshRateTableIndex,
+								pVBInfo);
+			}
 
-				if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-					if (temp & 0x01)
-						tempch |= ActiveHiTV;
-				}
+			if ((pVBInfo->IF_DEF_OEMUtil == 0) || (LCDPtr == NULL)) {
+				tempbx = 3;
+				if (pVBInfo->LCDInfo & EnableScalingLCD)
+					LCDPtr1
+							= (struct XGI330_LCDDataDesStruct2 *) XGI_GetLcdPtr(
+									tempbx,
+									ModeNo,
+									ModeIdIndex,
+									RefreshRateTableIndex,
+									pVBInfo);
+				else
+					LCDPtr
+							= (struct XGI330_LCDDataDesStruct *) XGI_GetLcdPtr(
+									tempbx,
+									ModeNo,
+									ModeIdIndex,
+									RefreshRateTableIndex,
+									pVBInfo);
+			}
 
-				if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
-					temp = XGINew_GetReg1(
-							pVBInfo->Part2Port,
-							0x4d);
+			XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
+			push1 = tempbx;
+			push2 = tempax;
 
-					if (temp & 0x10)
-						tempch |= ActiveYPbPr;
-				}
+			/* GetLCDResInfo */
+			if ((pVBInfo->LCDResInfo == Panel1024x768)
+					|| (pVBInfo->LCDResInfo
+							== Panel1024x768x75)) {
+				tempax = 1024;
+				tempbx = 768;
+			} else if ((pVBInfo->LCDResInfo == Panel1280x1024)
+					|| (pVBInfo->LCDResInfo
+							== Panel1280x1024x75)) {
+				tempax = 1280;
+				tempbx = 1024;
+			} else if (pVBInfo->LCDResInfo == Panel1400x1050) {
+				tempax = 1400;
+				tempbx = 1050;
+			} else {
+				tempax = 1600;
+				tempbx = 1200;
+			}
 
-				if (tempch != 0)
-					tempcl |= ActiveTV;
+			if (pVBInfo->LCDInfo & SetLCDtoNonExpanding) {
+				pVBInfo->HDE = tempax;
+				pVBInfo->VDE = tempbx;
+				pVBInfo->VGAHDE = tempax;
+				pVBInfo->VGAVDE = tempbx;
 			}
-		}
 
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x3d);
-		if (tempcl & ActiveLCD) {
-			if ((pVBInfo->SetFlag & ReserveTVOption)) {
-				if (temp & ActiveTV)
-					tempcl |= ActiveTV;
+			if ((pVBInfo->IF_DEF_ScaleLCD == 1)
+					&& (pVBInfo->LCDInfo & EnableScalingLCD)) {
+				tempax = pVBInfo->HDE;
+				tempbx = pVBInfo->VDE;
 			}
-		}
-		temp = tempcl;
-		tempbl = ~ModeSwitchStatus;
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x3d, tempbl, temp);
 
-		if (!(pVBInfo->SetFlag & ReserveTVOption))
-			XGINew_SetReg1(pVBInfo->P3d4, 0x3e, tempch);
-	} else {
-		return;
-	}
-}
+			tempax = pVBInfo->HT;
 
-void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	/*
-	if ( HwDeviceExtension->jChipType >= XG20 ) {
-		pVBInfo->Set_VGAType = XG20;
-	} else if (HwDeviceExtension->jChipType >= XG40) {
-		pVBInfo->Set_VGAType = VGA_XGI340;
-	}
-	*/
-	pVBInfo->Set_VGAType = HwDeviceExtension->jChipType;
-}
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				tempbx = LCDPtr1->LCDHDES;
+			else
+				tempbx = LCDPtr->LCDHDES;
 
-void XGI_GetVBType(struct vb_device_info *pVBInfo)
-{
-	unsigned short flag, tempbx, tempah;
+			tempcx = pVBInfo->HDE;
+			tempbx = tempbx & 0x0fff;
+			tempcx += tempbx;
 
-	if (pVBInfo->IF_DEF_CH7007 == 1) {
-		pVBInfo->VBType = VB_CH7007;
-		return;
-	}
-	if (pVBInfo->IF_DEF_LVDS == 0) {
-		tempbx = VB_XGI302B;
-		flag = XGINew_GetReg1(pVBInfo->Part4Port, 0x00);
-		if (flag != 0x02) {
-			tempbx = VB_XGI301;
-			flag = XGINew_GetReg1(pVBInfo->Part4Port, 0x01);
-			if (flag >= 0xB0) {
-				tempbx = VB_XGI301B;
-				if (flag >= 0xC0) {
-					tempbx = VB_XGI301C;
-					if (flag >= 0xD0) {
-						tempbx = VB_XGI301LV;
-						if (flag >= 0xE0) {
-							tempbx = VB_XGI302LV;
-							tempah
-									= XGINew_GetReg1(
-											pVBInfo->Part4Port,
-											0x39);
-							if (tempah != 0xFF)
-								tempbx
-										= VB_XGI301C;
-						}
-					}
-				}
+			if (tempcx >= tempax)
+				tempcx -= tempax;
 
-				if (tempbx & (VB_XGI301B | VB_XGI302B)) {
-					flag = XGINew_GetReg1(
-							pVBInfo->Part4Port,
-							0x23);
+			xgifb_reg_set(pVBInfo->Part1Port, 0x1A, tempbx & 0x07);
 
-					if (!(flag & 0x02))
-						tempbx = tempbx | VB_NoLCD;
-				}
-			}
-		}
-		pVBInfo->VBType = tempbx;
-	}
-	/*
-	else if (pVBInfo->IF_DEF_CH7017 == 1)
-		pVBInfo->VBType = VB_CH7017;
-	else //LVDS
-		pVBInfo->VBType = VB_LVDS_NS;
-	 */
+			tempcx = tempcx >> 3;
+			tempbx = tempbx >> 3;
 
-}
+			xgifb_reg_set(pVBInfo->Part1Port, 0x16,
+					(unsigned short) (tempbx & 0xff));
+			xgifb_reg_set(pVBInfo->Part1Port, 0x17,
+					(unsigned short) (tempcx & 0xff));
 
-void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short tempax, push, tempbx, temp, modeflag;
+			tempax = pVBInfo->HT;
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				tempbx = LCDPtr1->LCDHRS;
+			else
+				tempbx = LCDPtr->LCDHRS;
 
-	pVBInfo->SetFlag = 0;
-	pVBInfo->ModeType = modeflag & ModeInfoFlag;
-	tempbx = 0;
+			tempcx = push2;
 
-	if (pVBInfo->VBType & 0xFFFF) {
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x30); /* Check Display Device */
-		tempbx = tempbx | temp;
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x31);
-		push = temp;
-		push = push << 8;
-		tempax = temp << 8;
-		tempbx = tempbx | tempax;
-		temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA
-				| SetInSlaveMode | DisableCRT2Display);
-		temp = 0xFFFF ^ temp;
-		tempbx &= temp;
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				tempcx = LCDPtr1->LCDHSync;
 
-		temp = XGINew_GetReg1(pVBInfo->P3d4, 0x38);
+			tempcx += tempbx;
 
-		if (pVBInfo->IF_DEF_LCDA == 1) {
+			if (tempcx >= tempax)
+				tempcx -= tempax;
 
-			if ((pVBInfo->Set_VGAType >= XG20)
-					|| (pVBInfo->Set_VGAType >= XG40)) {
-				if (pVBInfo->IF_DEF_LVDS == 0) {
-					/* if ((pVBInfo->VBType & VB_XGI302B) || (pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType & VB_XGI301C)) */
-					if (pVBInfo->VBType & (VB_XGI302B
-							| VB_XGI301LV
-							| VB_XGI302LV
-							| VB_XGI301C)) {
-						if (temp & EnableDualEdge) {
-							tempbx
-									|= SetCRT2ToDualEdge;
+			tempax = tempbx & 0x07;
+			tempax = tempax >> 5;
+			tempcx = tempcx >> 3;
+			tempbx = tempbx >> 3;
 
-							if (temp & SetToLCDA)
-								tempbx
-										|= SetCRT2ToLCDA;
-						}
-					}
-				} else if (pVBInfo->IF_DEF_CH7017 == 1) {
-					if (pVBInfo->VBType & VB_CH7017) {
-						if (temp & EnableDualEdge) {
-							tempbx
-									|= SetCRT2ToDualEdge;
+			tempcx &= 0x1f;
+			tempax |= tempcx;
 
-							if (temp & SetToLCDA)
-								tempbx
-										|= SetCRT2ToLCDA;
-						}
-					}
-				}
-			}
-		}
+			xgifb_reg_set(pVBInfo->Part1Port, 0x15, tempax);
+			xgifb_reg_set(pVBInfo->Part1Port, 0x14,
+					(unsigned short) (tempbx & 0xff));
 
-		if (pVBInfo->IF_DEF_YPbPr == 1) {
-			if (((pVBInfo->IF_DEF_LVDS == 0) && ((pVBInfo->VBType
-					& VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV) || (pVBInfo->VBType
-					& VB_XGI301C)))
-					|| ((pVBInfo->IF_DEF_CH7017 == 1)
-							&& (pVBInfo->VBType
-									& VB_CH7017))
-					|| ((pVBInfo->IF_DEF_CH7007 == 1)
-							&& (pVBInfo->VBType
-									& VB_CH7007))) { /* [Billy] 07/05/04 */
-				if (temp & SetYPbPr) { /* temp = CR38 */
-					if (pVBInfo->IF_DEF_HiVision == 1) {
-						temp = XGINew_GetReg1(
-								pVBInfo->P3d4,
-								0x35); /* shampoo add for new scratch */
-						temp &= YPbPrMode;
-						tempbx |= SetCRT2ToHiVisionTV;
+			tempax = pVBInfo->VT;
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				tempbx = LCDPtr1->LCDVDES;
+			else
+				tempbx = LCDPtr->LCDVDES;
+			tempcx = pVBInfo->VDE;
+
+			tempbx = tempbx & 0x0fff;
+			tempcx += tempbx;
+			if (tempcx >= tempax)
+				tempcx -= tempax;
+
+			xgifb_reg_set(pVBInfo->Part1Port, 0x1b,
+					(unsigned short) (tempbx & 0xff));
+			xgifb_reg_set(pVBInfo->Part1Port, 0x1c,
+					(unsigned short) (tempcx & 0xff));
 
-						if (temp != YPbPrMode1080i) {
-							tempbx
-									&= (~SetCRT2ToHiVisionTV);
-							tempbx
-									|= SetCRT2ToYPbPr;
-						}
-					}
+			tempbx = (tempbx >> 8) & 0x07;
+			tempcx = (tempcx >> 8) & 0x07;
 
-					/* tempbx |= SetCRT2ToYPbPr; */
-				}
-			}
-		}
+			xgifb_reg_set(pVBInfo->Part1Port, 0x1d,
+					(unsigned short) ((tempcx << 3)
+							| tempbx));
 
-		tempax = push; /* restore CR31 */
+			tempax = pVBInfo->VT;
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				tempbx = LCDPtr1->LCDVRS;
+			else
+				tempbx = LCDPtr->LCDVRS;
 
-		if (pVBInfo->IF_DEF_LVDS == 0) {
-			if (pVBInfo->IF_DEF_YPbPr == 1) {
-				if (pVBInfo->IF_DEF_HiVision == 1)
-					temp = 0x09FC;
-				else
-					temp = 0x097C;
-			} else {
-				if (pVBInfo->IF_DEF_HiVision == 1)
-					temp = 0x01FC;
-				else
-					temp = 0x017C;
-			}
-		} else { /* 3nd party chip */
-			if (pVBInfo->IF_DEF_CH7017 == 1)
-				temp = (SetCRT2ToTV | SetCRT2ToLCD
-						| SetCRT2ToLCDA);
-			else if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/03 */
-				temp = SetCRT2ToTV;
-			} else
-				temp = SetCRT2ToLCD;
-		}
+			/* tempbx = tempbx >> 4; */
+			tempcx = push1;
 
-		if (!(tempbx & temp)) {
-			tempax |= DisableCRT2Display;
-			tempbx = 0;
-		}
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				tempcx = LCDPtr1->LCDVSync;
 
-		if (pVBInfo->IF_DEF_LCDA == 1) { /* Select Display Device */
-			if (!(pVBInfo->VBType & VB_NoLCD)) {
-				if (tempbx & SetCRT2ToLCDA) {
-					if (tempbx & SetSimuScanMode)
-						tempbx
-								&= (~(SetCRT2ToLCD
-										| SetCRT2ToRAMDAC
-										| SwitchToCRT2));
-					else
-						tempbx
-								&= (~(SetCRT2ToLCD
-										| SetCRT2ToRAMDAC
-										| SetCRT2ToTV
-										| SwitchToCRT2));
-				}
-			}
-		}
+			tempcx += tempbx;
+			if (tempcx >= tempax)
+				tempcx -= tempax;
 
-		/* shampoo add */
-		if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode))) { /* for driver abnormal */
-			if (pVBInfo->IF_DEF_CRT2Monitor == 1) {
-				if (tempbx & SetCRT2ToRAMDAC) {
-					tempbx &= (0xFF00 | SetCRT2ToRAMDAC
-							| SwitchToCRT2
-							| SetSimuScanMode);
-					tempbx &= (0x00FF | (~SetCRT2ToYPbPr));
-				}
-			} else {
-				tempbx &= (~(SetCRT2ToRAMDAC | SetCRT2ToLCD
-						| SetCRT2ToTV));
-			}
-		}
+			xgifb_reg_set(pVBInfo->Part1Port, 0x18,
+					(unsigned short) (tempbx & 0xff));
+			xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, ~0x0f,
+					(unsigned short) (tempcx & 0x0f));
 
-		if (!(pVBInfo->VBType & VB_NoLCD)) {
-			if (tempbx & SetCRT2ToLCD) {
-				tempbx &= (0xFF00 | SetCRT2ToLCD | SwitchToCRT2
-						| SetSimuScanMode);
-				tempbx &= (0x00FF | (~SetCRT2ToYPbPr));
-			}
-		}
+			tempax = ((tempbx >> 8) & 0x07) << 3;
 
-		if (tempbx & SetCRT2ToSCART) {
-			tempbx &= (0xFF00 | SetCRT2ToSCART | SwitchToCRT2
-					| SetSimuScanMode);
-			tempbx &= (0x00FF | (~SetCRT2ToYPbPr));
-		}
+			tempbx = pVBInfo->VGAVDE;
+			if (tempbx != pVBInfo->VDE)
+				tempax |= 0x40;
 
-		if (pVBInfo->IF_DEF_YPbPr == 1) {
-			if (tempbx & SetCRT2ToYPbPr)
-				tempbx &= (0xFF00 | SwitchToCRT2
-						| SetSimuScanMode);
-		}
+			if (pVBInfo->LCDInfo & EnableLVDSDDA)
+				tempax |= 0x40;
 
-		if (pVBInfo->IF_DEF_HiVision == 1) {
-			if (tempbx & SetCRT2ToHiVisionTV)
-				tempbx &= (0xFF00 | SetCRT2ToHiVisionTV
-						| SwitchToCRT2
-						| SetSimuScanMode);
-		}
+			xgifb_reg_and_or(pVBInfo->Part1Port, 0x1a, 0x07,
+					tempax);
 
-		if (tempax & DisableCRT2Display) { /* Set Display Device Info */
-			if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode)))
-				tempbx = DisableCRT2Display;
-		}
+			tempcx = pVBInfo->VGAVT;
+			tempbx = pVBInfo->VDE;
+			tempax = pVBInfo->VGAVDE;
+			tempcx -= tempax;
 
-		if (!(tempbx & DisableCRT2Display)) {
-			if ((!(tempbx & DriverMode))
-					|| (!(modeflag & CRT2Mode))) {
-				if (pVBInfo->IF_DEF_LCDA == 1) {
-					if (!(tempbx & SetCRT2ToLCDA))
-						tempbx
-								|= (SetInSlaveMode
-										| SetSimuScanMode);
-				}
+			temp = tempax; /* 0430 ylshieh */
+			temp1 = (temp << 18) / tempbx;
 
-				if (pVBInfo->IF_DEF_VideoCapture == 1) {
-					if (((HwDeviceExtension->jChipType
-							== XG40)
-							&& (pVBInfo->Set_VGAType
-									== XG40))
-							|| ((HwDeviceExtension->jChipType
-									== XG41)
-									&& (pVBInfo->Set_VGAType
-											== XG41))
-							|| ((HwDeviceExtension->jChipType
-									== XG42)
-									&& (pVBInfo->Set_VGAType
-											== XG42))
-							|| ((HwDeviceExtension->jChipType
-									== XG45)
-									&& (pVBInfo->Set_VGAType
-											== XG45))) {
-						if (ModeNo <= 13) {
-							if (!(tempbx
-									& SetCRT2ToRAMDAC)) { /*CRT2 not need to support*/
-								tempbx
-										&= (0x00FF
-												| (~SetInSlaveMode));
-								pVBInfo->SetFlag
-										|= EnableVCMode;
-							}
-						}
-					}
-				}
-			}
+			tempdx = (unsigned short) ((temp << 18) % tempbx);
 
-			/* LCD+TV can't support in slave mode (Force LCDA+TV->LCDB) */
-			if ((tempbx & SetInSlaveMode) && (tempbx
-					& SetCRT2ToLCDA)) {
-				tempbx ^= (SetCRT2ToLCD | SetCRT2ToLCDA
-						| SetCRT2ToDualEdge);
-				pVBInfo->SetFlag |= ReserveTVOption;
-			}
-		}
-	}
+			if (tempdx != 0)
+				temp1 += 1;
 
-	pVBInfo->VBInfo = tempbx;
-}
+			temp2 = temp1;
+			push3 = temp2;
 
-void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short temp, tempbx = 0, resinfo = 0, modeflag, index1;
+			xgifb_reg_set(pVBInfo->Part1Port, 0x37,
+					(unsigned short) (temp2 & 0xff));
+			xgifb_reg_set(pVBInfo->Part1Port, 0x36,
+					(unsigned short) ((temp2 >> 8) & 0xff));
 
-	tempbx = 0;
-	resinfo = 0;
+			tempbx = (unsigned short) (temp2 >> 16);
+			tempax = tempbx & 0x03;
 
-	if (pVBInfo->VBInfo & SetCRT2ToTV) {
-		if (ModeNo <= 0x13) {
-			modeflag
-					= pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
-			resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo; /* si+St_ResInfo */
-		} else {
-			modeflag
-					= pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-			resinfo
-					= pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo */
-		}
+			tempbx = pVBInfo->VGAVDE;
+			if (tempbx == pVBInfo->VDE)
+				tempax |= 0x04;
 
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			temp = XGINew_GetReg1(pVBInfo->P3d4, 0x35);
-			tempbx = temp;
-			if (tempbx & SetPALTV) {
-				tempbx &= (SetCHTVOverScan | SetPALMTV
-						| SetPALNTV | SetPALTV);
-				if (tempbx & SetPALMTV)
-					tempbx &= ~SetPALTV; /* set to NTSC if PAL-M */
-			} else
-				tempbx &= (SetCHTVOverScan | SetNTSCJ
-						| SetPALTV);
-			/*
-			if (pVBInfo->IF_DEF_LVDS == 0) {
-				index1 = XGINew_GetReg1(pVBInfo->P3d4, 0x38); //PAL-M/PAL-N Info
-				temp2 = (index1 & 0xC0) >> 5; //00:PAL, 01:PAL-M, 10:PAL-N
-				tempbx |= temp2;
-				if (temp2 & 0x02)          //PAL-M
-					tempbx &= (~SetPALTV);
+			xgifb_reg_set(pVBInfo->Part1Port, 0x35, tempax);
+
+			if (pVBInfo->VBType & VB_XGI301C) {
+				temp2 = push3;
+				xgifb_reg_set(pVBInfo->Part4Port, 0x3c,
+						(unsigned short) (temp2 & 0xff));
+				xgifb_reg_set(pVBInfo->Part4Port, 0x3b,
+						(unsigned short) ((temp2 >> 8)
+								& 0xff));
+				tempbx = (unsigned short) (temp2 >> 16);
+				xgifb_reg_and_or(pVBInfo->Part4Port, 0x3a,
+						~0xc0,
+						(unsigned short) ((tempbx
+								& 0xff) << 6));
+
+				tempcx = pVBInfo->VGAVDE;
+				if (tempcx == pVBInfo->VDE)
+					xgifb_reg_and_or(pVBInfo->Part4Port,
+							0x30, ~0x0c, 0x00);
+				else
+					xgifb_reg_and_or(pVBInfo->Part4Port,
+							0x30, ~0x0c, 0x08);
 			}
-			*/
-		}
 
-		if (pVBInfo->IF_DEF_CH7017 == 1) {
-			tempbx = XGINew_GetReg1(pVBInfo->P3d4, 0x35);
+			tempcx = pVBInfo->VGAHDE;
+			tempbx = pVBInfo->HDE;
 
-			if (tempbx & TVOverScan)
-				tempbx |= SetCHTVOverScan;
-		}
+			temp1 = tempcx << 16;
 
-		if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/04 */
-			tempbx = XGINew_GetReg1(pVBInfo->P3d4, 0x35);
+			tempax = (unsigned short) (temp1 / tempbx);
 
-			if (tempbx & TVOverScan)
-				tempbx |= SetCHTVOverScan;
-		}
+			if ((tempbx & 0xffff) == (tempcx & 0xffff))
+				tempax = 65535;
+
+			temp3 = tempax;
+			temp1 = pVBInfo->VGAHDE << 16;
 
-		if (pVBInfo->IF_DEF_LVDS == 0) {
-			if (pVBInfo->VBInfo & SetCRT2ToSCART)
-				tempbx |= SetPALTV;
-		}
+			temp1 /= temp3;
+			temp3 = temp3 << 16;
+			temp1 -= 1;
 
-		if (pVBInfo->IF_DEF_YPbPr == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
-				index1 = XGINew_GetReg1(pVBInfo->P3d4, 0x35);
-				index1 &= YPbPrMode;
+			temp3 = (temp3 & 0xffff0000) + (temp1 & 0xffff);
 
-				if (index1 == YPbPrMode525i)
-					tempbx |= SetYPbPrMode525i;
+			tempax = (unsigned short) (temp3 & 0xff);
+			xgifb_reg_set(pVBInfo->Part1Port, 0x1f, tempax);
 
-				if (index1 == YPbPrMode525p)
-					tempbx = tempbx | SetYPbPrMode525p;
-				if (index1 == YPbPrMode750p)
-					tempbx = tempbx | SetYPbPrMode750p;
-			}
-		}
+			temp1 = pVBInfo->VGAVDE << 18;
+			temp1 = temp1 / push3;
+			tempbx = (unsigned short) (temp1 & 0xffff);
 
-		if (pVBInfo->IF_DEF_HiVision == 1) {
-			if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
-				tempbx = tempbx | SetYPbPrMode1080i | SetPALTV;
-		}
+			if (pVBInfo->LCDResInfo == Panel1024x768)
+				tempbx -= 1;
 
-		if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */
-			if ((pVBInfo->VBInfo & SetInSlaveMode)
-					&& (!(pVBInfo->VBInfo & SetNotSimuMode)))
-				tempbx |= TVSimuMode;
+			tempax = ((tempbx >> 8) & 0xff) << 3;
+			tempax |= (unsigned short) ((temp3 >> 8) & 0x07);
+			xgifb_reg_set(pVBInfo->Part1Port, 0x20,
+					(unsigned short) (tempax & 0xff));
+			xgifb_reg_set(pVBInfo->Part1Port, 0x21,
+					(unsigned short) (tempbx & 0xff));
 
-			if (!(tempbx & SetPALTV) && (modeflag > 13) && (resinfo
-					== 8)) /* NTSC 1024x768, */
-				tempbx |= NTSC1024x768;
+			temp3 = temp3 >> 16;
 
-			tempbx |= RPLLDIV2XO;
+			if (modeflag & HalfDCLK)
+				temp3 = temp3 >> 1;
 
-			if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-				if (pVBInfo->VBInfo & SetInSlaveMode)
-					tempbx &= (~RPLLDIV2XO);
-			} else {
-				if (tempbx & (SetYPbPrMode525p
-						| SetYPbPrMode750p))
-					tempbx &= (~RPLLDIV2XO);
-				else if (!(pVBInfo->VBType & (VB_XGI301B
-						| VB_XGI302B | VB_XGI301LV
-						| VB_XGI302LV | VB_XGI301C))) {
-					if (tempbx & TVSimuMode)
-						tempbx &= (~RPLLDIV2XO);
-				}
-			}
+			xgifb_reg_set(pVBInfo->Part1Port, 0x22,
+					(unsigned short) ((temp3 >> 8) & 0xff));
+			xgifb_reg_set(pVBInfo->Part1Port, 0x23,
+					(unsigned short) (temp3 & 0xff));
 		}
 	}
-	pVBInfo->TVInfo = tempbx;
 }
 
-unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GETLCDVCLKPtr */
+/* Input : */
+/* Output : al -> VCLK Index */
+/* Description : */
+/* --------------------------------------------------------------------- */
+static void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short temp, tempax, tempbx, modeflag, resinfo = 0, LCDIdIndex;
-
-	pVBInfo->LCDResInfo = 0;
-	pVBInfo->LCDTypeInfo = 0;
-	pVBInfo->LCDInfo = 0;
-
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag // */
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo // */
-	}
-
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
-	tempbx = temp & 0x0F;
+	unsigned short index;
 
-	if (tempbx == 0)
-		tempbx = Panel1024x768; /* default */
+	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+		if (pVBInfo->IF_DEF_ScaleLCD == 1) {
+			if (pVBInfo->LCDInfo & EnableScalingLCD)
+				return;
+		}
 
-	/* LCD75 [2003/8/22] Vicent */
-	if ((tempbx == Panel1024x768) || (tempbx == Panel1280x1024)) {
-		if (pVBInfo->VBInfo & DriverMode) {
-			tempax = XGINew_GetReg1(pVBInfo->P3d4, 0x33);
-			if (pVBInfo->VBInfo & SetCRT2ToLCDA)
-				tempax &= 0x0F;
-			else
-				tempax = tempax >> 4;
+		/* index = XGI_GetLCDCapPtr(pVBInfo); */
+		index = XGI_GetLCDCapPtr1(pVBInfo);
 
-			if ((resinfo == 6) || (resinfo == 9)) {
-				if (tempax >= 3)
-					tempbx |= PanelRef75Hz;
-			} else if ((resinfo == 7) || (resinfo == 8)) {
-				if (tempax >= 4)
-					tempbx |= PanelRef75Hz;
-			}
+		if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* LCDB */
+			*di_0 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData1;
+			*di_1 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData2;
+		} else { /* LCDA */
+			*di_0 = pVBInfo->LCDCapList[index].LCDA_VCLKData1;
+			*di_1 = pVBInfo->LCDCapList[index].LCDA_VCLKData2;
 		}
 	}
+	return;
+}
 
-	pVBInfo->LCDResInfo = tempbx;
+static unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
+		unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
+{
 
-	/* End of LCD75 */
+	unsigned short index, modeflag;
+	unsigned short tempbx;
+	unsigned char tempal;
+	unsigned char *CHTVVCLKPtr = NULL;
 
-	if (pVBInfo->IF_DEF_OEMUtil == 1)
-		pVBInfo->LCDTypeInfo = (temp & 0xf0) >> 4;
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
 
-	if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)))
-		return 0;
+	if ((pVBInfo->SetFlag & ProgrammingCRT2) && (!(pVBInfo->LCDInfo
+			& EnableScalingLCD))) { /* {LCDA/LCDB} */
+		index = XGI_GetLCDCapPtr(pVBInfo);
+		tempal = pVBInfo->LCDCapList[index].LCD_VCLK;
 
-	tempbx = 0;
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))
+			return tempal;
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x37);
+		/* {TV} */
+		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)) {
+			if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+				tempal = HiTVVCLKDIV2;
+				if (!(pVBInfo->TVInfo & RPLLDIV2XO))
+					tempal = HiTVVCLK;
+				if (pVBInfo->TVInfo & TVSimuMode) {
+					tempal = HiTVSimuVCLK;
+					if (!(modeflag & Charx8Dot))
+						tempal = HiTVTextVCLK;
 
-	temp &= (ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable);
+				}
+				return tempal;
+			}
 
-	if ((pVBInfo->IF_DEF_ScaleLCD == 1) && (temp & LCDNonExpanding))
-		temp &= ~EnableScalingLCD;
+			if (pVBInfo->TVInfo & SetYPbPrMode750p) {
+				tempal = YPbPr750pVCLK;
+				return tempal;
+			}
 
-	tempbx |= temp;
+			if (pVBInfo->TVInfo & SetYPbPrMode525p) {
+				tempal = YPbPr525pVCLK;
+				return tempal;
+			}
 
-	LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo);
+			tempal = NTSC1024VCLK;
 
-	tempax = pVBInfo->LCDCapList[LCDIdIndex].LCD_Capability;
+			if (!(pVBInfo->TVInfo & NTSC1024x768)) {
+				tempal = TVVCLKDIV2;
+				if (!(pVBInfo->TVInfo & RPLLDIV2XO))
+					tempal = TVVCLK;
+			}
 
-	if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */
-		if (((pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType
-				& VB_XGI301C)) && (tempax & LCDDualLink)) {
-			tempbx |= SetLCDDualLink;
+			if (pVBInfo->VBInfo & SetCRT2ToTV)
+				return tempal;
 		}
-	}
+		/* else if ((pVBInfo->IF_DEF_CH7017==1)&&(pVBInfo->VBType&VB_CH7017)) {
+			if (ModeNo<=0x13)
+				*tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+			else
+				*tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+			*tempal = *tempal & 0x1F;
+			tempbx = 0;
+			if (pVBInfo->TVInfo & SetPALTV)
+				tempbx = tempbx + 2;
+			if (pVBInfo->TVInfo & SetCHTVOverScan)
+				tempbx++;
+			tempbx = tempbx << 1;
+		} */
+	} /* {End of VB} */
 
-	if (pVBInfo->IF_DEF_CH7017 == 1) {
-		if (tempax & LCDDualLink)
-			tempbx |= SetLCDDualLink;
-	}
+	if ((pVBInfo->IF_DEF_CH7007 == 1) && (pVBInfo->VBType & VB_CH7007)) { /* [Billy] 07/05/08 CH7007 */
+		/* VideoDebugPrint((0, "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
+		if ((pVBInfo->VBInfo & SetCRT2ToTV)) {
+			if (ModeNo <= 0x13) {
+				tempal
+						= pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+			} else {
+				tempal
+						= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+			}
 
-	if (pVBInfo->IF_DEF_LVDS == 0) {
-		if ((pVBInfo->LCDResInfo == Panel1400x1050) && (pVBInfo->VBInfo
-				& SetCRT2ToLCD) && (ModeNo > 0x13) && (resinfo
-				== 9) && (!(tempbx & EnableScalingLCD)))
-			tempbx |= SetLCDtoNonExpanding; /* set to center in 1280x1024 LCDB for Panel1400x1050 */
-	}
+			tempal = tempal & 0x0F;
+			tempbx = 0;
 
-	/*
-	if (tempax & LCDBToA) {
-		tempbx |= SetLCDBToA;
-	}
-	*/
+			if (pVBInfo->TVInfo & SetPALTV)
+				tempbx = tempbx + 2;
 
-	if (pVBInfo->IF_DEF_ExpLink == 1) {
-		if (modeflag & HalfDCLK) {
-			/* if (!(pVBInfo->LCDInfo&LCDNonExpanding)) */
-			if (!(tempbx & SetLCDtoNonExpanding)) {
-				tempbx |= EnableLVDSDDA;
-			} else {
-				if (ModeNo > 0x13) {
-					if (pVBInfo->LCDResInfo
-							== Panel1024x768) {
-						if (resinfo == 4) { /* 512x384  */
-							tempbx |= EnableLVDSDDA;
-						}
-					}
+			if (pVBInfo->TVInfo & SetCHTVOverScan)
+				tempbx++;
+
+			/** tempbx = tempbx << 1; CH7007 ? **/
+
+			/* [Billy]07/05/29 CH7007 */
+			if (pVBInfo->IF_DEF_CH7007 == 1) {
+				switch (tempbx) {
+				case 0:
+					CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC;
+					break;
+				case 1:
+					CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC;
+					break;
+				case 2:
+					CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL;
+					break;
+				case 3:
+					CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL;
+					break;
+				default:
+					break;
+
+				}
+			}
+			/* else {
+				switch(tempbx) {
+				case 0:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC;
+					break;
+				case 1:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC;
+					break;
+				case 2:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL;
+					break;
+				case 3:
+					CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL;
+					break;
+				default:
+					break;
 				}
 			}
+			*/
+
+			tempal = CHTVVCLKPtr[tempal];
+			return tempal;
 		}
-	}
 
-	if (pVBInfo->VBInfo & SetInSlaveMode) {
-		if (pVBInfo->VBInfo & SetNotSimuMode)
-			tempbx |= LCDVESATiming;
-	} else {
-		tempbx |= LCDVESATiming;
 	}
 
-	pVBInfo->LCDInfo = tempbx;
+	tempal = (unsigned char) inb((pVBInfo->P3ca + 0x02));
+	tempal = tempal >> 2;
+	tempal &= 0x03;
 
-	if (pVBInfo->IF_DEF_PWD == 1) {
-		if (pVBInfo->LCDInfo & SetPWDEnable) {
-			if ((pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType
-					& VB_XGI301C)) {
-				if (!(tempax & PWDEnable))
-					pVBInfo->LCDInfo &= ~SetPWDEnable;
-			}
-		}
-	}
+	if ((pVBInfo->LCDInfo & EnableScalingLCD) && (modeflag & Charx8Dot)) /* for Dot8 Scaling LCD */
+		tempal = tempal ^ tempal; /* ; set to VCLK25MHz always */
 
-	if (pVBInfo->IF_DEF_LVDS == 0) {
-		if (tempax & (LockLCDBToA | StLCDBToA)) {
-			if (pVBInfo->VBInfo & SetInSlaveMode) {
-				if (!(tempax & LockLCDBToA)) {
-					if (ModeNo <= 0x13) {
-						pVBInfo->VBInfo
-								&= ~(SetSimuScanMode
-										| SetInSlaveMode
-										| SetCRT2ToLCD);
-						pVBInfo->VBInfo
-								|= SetCRT2ToLCDA
-										| SetCRT2ToDualEdge;
-					}
-				}
-			}
-		}
-	}
+	if (ModeNo <= 0x13)
+		return tempal;
 
-	/*
-	if (pVBInfo->IF_DEF_LVDS == 0) {
-		if (tempax & (LockLCDBToA | StLCDBToA)) {
-			if (pVBInfo->VBInfo & SetInSlaveMode) {
-				if (!((!(tempax & LockLCDBToA)) && (ModeNo > 0x13))) {
-					pVBInfo->VBInfo&=~(SetSimuScanMode|SetInSlaveMode|SetCRT2ToLCD);
-					pVBInfo->VBInfo|=SetCRT2ToLCDA|SetCRT2ToDualEdge;
-				}
-			}
+	tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
+	return tempal;
+}
+
+static void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
+		unsigned char *di_1, struct vb_device_info *pVBInfo)
+{
+	if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 2007/05/16 */
+		/* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
+		*di_0 = (unsigned char) XGI_CH7007VCLKData[tempal].SR2B;
+		*di_1 = (unsigned char) XGI_CH7007VCLKData[tempal].SR2C;
+	} else if (pVBInfo->VBType & (VB_XGI301 | VB_XGI301B | VB_XGI302B
+			| VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
+		if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) && (pVBInfo->SetFlag
+				& ProgrammingCRT2)) {
+			*di_0 = (unsigned char) XGI_VBVCLKData[tempal].SR2B;
+			*di_1 = XGI_VBVCLKData[tempal].SR2C;
 		}
+	} else {
+		*di_0 = XGI_VCLKData[tempal].SR2B;
+		*di_1 = XGI_VCLKData[tempal].SR2C;
 	}
-	*/
-
-	return 1;
 }
 
-unsigned char XGI_SearchModeID(unsigned short ModeNo,
-		unsigned short *ModeIdIndex, struct vb_device_info *pVBInfo)
+static void XGI_SetCRT2ECLK(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
 {
-	if (ModeNo <= 5)
-		ModeNo |= 1;
-	if (ModeNo <= 0x13) {
-		/* for (*ModeIdIndex=0; *ModeIdIndex < sizeof(pVBInfo->SModeIDTable) / sizeof(struct XGI_StStruct); (*ModeIdIndex)++) */
-		for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
-			if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == ModeNo)
-				break;
-			if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF)
-				return 0;
-		}
+	unsigned char di_0, di_1, tempal;
+	int i;
 
-		if (ModeNo == 0x07)
-			(*ModeIdIndex)++; /* 400 lines */
-		if (ModeNo <= 3)
-			(*ModeIdIndex) += 2; /* 400 lines */
-		/* else 350 lines */
-	} else {
-		/* for (*ModeIdIndex=0; *ModeIdIndex < sizeof(pVBInfo->EModeIDTable) / sizeof(struct XGI_ExtStruct); (*ModeIdIndex)++) */
-		for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
-			if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
-				break;
-			if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
-				return 0;
+	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex,
+			pVBInfo);
+	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
+	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
+
+	for (i = 0; i < 4; i++) {
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x31, ~0x30,
+				(unsigned short) (0x10 * i));
+		if (pVBInfo->IF_DEF_CH7007 == 1) {
+			xgifb_reg_set(pVBInfo->P3c4, 0x2b, di_0);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2c, di_1);
+		} else if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA))
+				&& (!(pVBInfo->VBInfo & SetInSlaveMode))) {
+			xgifb_reg_set(pVBInfo->P3c4, 0x2e, di_0);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2f, di_1);
+		} else {
+			xgifb_reg_set(pVBInfo->P3c4, 0x2b, di_0);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2c, di_1);
 		}
 	}
-
-	return 1;
 }
 
-/* win2000 MM adapter not support standard mode! */
-
-#if 0
-static unsigned char XGINew_CheckMemorySize(
-		struct xgi_hw_device_info *HwDeviceExtension,
-		unsigned short ModeNo,
-		unsigned short ModeIdIndex,
+static void XGI_UpdateModeInfo(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short memorysize, modeflag, temp, temp1, tmp;
+	unsigned short tempcl, tempch, temp, tempbl, tempax;
 
-	/*
-	if ((HwDeviceExtension->jChipType == XGI_650) ||
-	(HwDeviceExtension->jChipType == XGI_650M)) {
-		return 1;
-	}
-	*/
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		tempcl = 0;
+		tempch = 0;
+		temp = xgifb_reg_get(pVBInfo->P3c4, 0x01);
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		if (!(temp & 0x20)) {
+			temp = xgifb_reg_get(pVBInfo->P3d4, 0x17);
+			if (temp & 0x80) {
+				temp = xgifb_reg_get(pVBInfo->P3d4, 0x53);
+				if (!(temp & 0x40))
+					tempcl |= ActiveCRT1;
+			}
+		}
 
-	/* ModeType = modeflag&ModeInfoFlag; // Get mode type */
+		temp = xgifb_reg_get(pVBInfo->Part1Port, 0x2e);
+		temp &= 0x0f;
 
-	memorysize = modeflag & MemoryInfoFlag;
-	memorysize = memorysize > MemorySizeShift;
-	memorysize++; /* Get memory size */
+		if (!(temp == 0x08)) {
+			tempax = xgifb_reg_get(pVBInfo->Part1Port, 0x13); /* Check ChannelA by Part1_13 [2003/10/03] */
+			if (tempax & 0x04)
+				tempcl = tempcl | ActiveLCD;
 
-	temp = XGINew_GetReg1(pVBInfo->P3c4, 0x14); /* Get DRAM Size */
-	tmp = temp;
+			temp &= 0x05;
 
-	if (HwDeviceExtension->jChipType == XG40) {
-		temp = 1 << ((temp & 0x0F0) >> 4); /* memory size per channel SR14[7:4] */
-		if ((tmp & 0x0c) == 0x0C) { /* Qual channels */
-			temp <<= 2;
-		} else if ((tmp & 0x0c) == 0x08) { /* Dual channels */
-			temp <<= 1;
-		}
-	} else if (HwDeviceExtension->jChipType == XG42) {
-		temp = 1 << ((temp & 0x0F0) >> 4); /* memory size per channel SR14[7:4] */
-		if ((tmp & 0x04) == 0x04) { /* Dual channels */
-			temp <<= 1;
-		}
-	} else if (HwDeviceExtension->jChipType == XG45) {
-		temp = 1 << ((temp & 0x0F0) >> 4); /* memory size per channel SR14[7:4] */
-		if ((tmp & 0x0c) == 0x0C) { /* Qual channels */
-			temp <<= 2;
-		} else if ((tmp & 0x0c) == 0x08) { /* triple channels */
-			temp1 = temp;
-			temp <<= 1;
-			temp += temp1;
-		} else if ((tmp & 0x0c) == 0x04) { /* Dual channels */
-			temp <<= 1;
-		}
-	}
-	if (temp < memorysize)
-		return 0;
-	else
-		return 1;
-}
-#endif
+			if (!(tempcl & ActiveLCD))
+				if (temp == 0x01)
+					tempcl |= ActiveCRT2;
 
-/*
-void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
-	unsigned short data ;
-	unsigned short ModeFlag ;
+			if (temp == 0x04)
+				tempcl |= ActiveLCD;
 
-	data = XGINew_GetReg1(pVBInfo->P3c4, 0x0F);
-	data &= 0x7F;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x0F, data);
+			if (temp == 0x05) {
+				temp = xgifb_reg_get(pVBInfo->Part2Port, 0x00);
 
-	if (ModeNo > 0x13) {
-		ModeFlag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		if ((ModeFlag & HalfDCLK) && (ModeFlag & DoubleScanMode)) {
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x0F);
-			data |= 0x80;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x0F, data);
-			data = XGINew_GetReg1(pVBInfo->P3c4, 0x01);
-			data &= 0xF7;
-			XGINew_SetReg1(pVBInfo->P3c4, 0x01, data);
-		}
-	}
-}
-*/
+				if (!(temp & 0x08))
+					tempch |= ActiveAVideo;
 
-void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
-		struct vb_device_info *pVBInfo)
-{
+				if (!(temp & 0x04))
+					tempch |= ActiveSVideo;
 
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x01, 0xDF, 0x00);
-	if (pXGIHWDE->jChipType == XG21) {
-		if (pVBInfo->IF_DEF_LVDS == 1) {
-			if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) {
-				XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo); /* LVDS VDD on */
-				XGI_XG21SetPanelDelay(2, pVBInfo);
-			}
-			if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20))
-				XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); /* LVDS signal on */
-			XGI_XG21SetPanelDelay(3, pVBInfo);
-			XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo); /* LVDS backlight on */
-		} else {
-			XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); /* DVO/DVI signal on */
-		}
+				if (temp & 0x02)
+					tempch |= ActiveSCART;
 
-	}
+				if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+					if (temp & 0x01)
+						tempch |= ActiveHiTV;
+				}
+
+				if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
+					temp = xgifb_reg_get(
+							pVBInfo->Part2Port,
+							0x4d);
 
-	if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/23 For CH7007 */
+					if (temp & 0x10)
+						tempch |= ActiveYPbPr;
+				}
 
-	}
+				if (tempch != 0)
+					tempcl |= ActiveTV;
+			}
+		}
 
-	if (pXGIHWDE->jChipType == XG27) {
-		if (pVBInfo->IF_DEF_LVDS == 1) {
-			if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
-				XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo); /* LVDS VDD on */
-				XGI_XG21SetPanelDelay(2, pVBInfo);
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x3d);
+		if (tempcl & ActiveLCD) {
+			if ((pVBInfo->SetFlag & ReserveTVOption)) {
+				if (temp & ActiveTV)
+					tempcl |= ActiveTV;
 			}
-			if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20))
-				XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); /* LVDS signal on */
-			XGI_XG21SetPanelDelay(3, pVBInfo);
-			XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo); /* LVDS backlight on */
-		} else {
-			XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); /* DVO/DVI signal on */
 		}
+		temp = tempcl;
+		tempbl = ~ModeSwitchStatus;
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x3d, tempbl, temp);
 
+		if (!(pVBInfo->SetFlag & ReserveTVOption))
+			xgifb_reg_set(pVBInfo->P3d4, 0x3e, tempch);
+	} else {
+		return;
 	}
 }
 
-void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE,
+void XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-
-	if (pXGIHWDE->jChipType == XG21) {
-		if (pVBInfo->IF_DEF_LVDS == 1) {
-			XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo); /* LVDS backlight off */
-			XGI_XG21SetPanelDelay(3, pVBInfo);
-		} else {
-			XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo); /* DVO/DVI signal off */
-		}
-	}
-
-	if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/23 For CH7007 */
-		/* if (IsCH7007TVMode(pVBInfo) == 0) */
-		{
-		}
+	/*
+	if ( HwDeviceExtension->jChipType >= XG20 ) {
+		pVBInfo->Set_VGAType = XG20;
+	} else {
+		pVBInfo->Set_VGAType = VGA_XGI340;
 	}
+	*/
+	pVBInfo->Set_VGAType = HwDeviceExtension->jChipType;
+}
 
-	if (pXGIHWDE->jChipType == XG27) {
-		if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
-			XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo); /* LVDS backlight off */
-			XGI_XG21SetPanelDelay(3, pVBInfo);
-		}
+void XGI_GetVBType(struct vb_device_info *pVBInfo)
+{
+	unsigned short flag, tempbx, tempah;
 
-		if (pVBInfo->IF_DEF_LVDS == 0)
-			XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo); /* DVO/DVI signal off */
+	if (pVBInfo->IF_DEF_CH7007 == 1) {
+		pVBInfo->VBType = VB_CH7007;
+		return;
 	}
+	if (pVBInfo->IF_DEF_LVDS == 0) {
+		tempbx = VB_XGI302B;
+		flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00);
+		if (flag != 0x02) {
+			tempbx = VB_XGI301;
+			flag = xgifb_reg_get(pVBInfo->Part4Port, 0x01);
+			if (flag >= 0xB0) {
+				tempbx = VB_XGI301B;
+				if (flag >= 0xC0) {
+					tempbx = VB_XGI301C;
+					if (flag >= 0xD0) {
+						tempbx = VB_XGI301LV;
+						if (flag >= 0xE0) {
+							tempbx = VB_XGI302LV;
+							tempah
+									= xgifb_reg_get(
+											pVBInfo->Part4Port,
+											0x39);
+							if (tempah != 0xFF)
+								tempbx
+										= VB_XGI301C;
+						}
+					}
+				}
 
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x01, 0xDF, 0x20);
-}
+				if (tempbx & (VB_XGI301B | VB_XGI302B)) {
+					flag = xgifb_reg_get(
+							pVBInfo->Part4Port,
+							0x23);
 
-void XGI_WaitDisply(struct vb_device_info *pVBInfo)
-{
-	while ((XGINew_GetReg2(pVBInfo->P3da) & 0x01))
-		break;
+					if (!(flag & 0x02))
+						tempbx = tempbx | VB_NoLCD;
+				}
+			}
+		}
+		pVBInfo->VBType = tempbx;
+	}
+	/*
+	else if (pVBInfo->IF_DEF_CH7017 == 1)
+		pVBInfo->VBType = VB_CH7017;
+	else //LVDS
+		pVBInfo->VBType = VB_LVDS_NS;
+	 */
 
-	while (!(XGINew_GetReg2(pVBInfo->P3da) & 0x01))
-		break;
 }
 
-void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
+void XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned char CRTCData[17] = { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81,
-			0x0B, 0x3E, 0xE9, 0x0B, 0xDF, 0xE7, 0x04, 0x00, 0x00,
-			0x05, 0x00 };
+	unsigned short tempax, push, tempbx, temp, modeflag;
 
-	unsigned char SR01 = 0, SR1F = 0, SR07 = 0, SR06 = 0;
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	unsigned char CR17, CR63, SR31;
-	unsigned short temp;
-	unsigned char DAC_TEST_PARMS[3] = { 0x0F, 0x0F, 0x0F };
+	pVBInfo->SetFlag = 0;
+	pVBInfo->ModeType = modeflag & ModeInfoFlag;
+	tempbx = 0;
 
-	int i;
-	XGINew_SetReg1(pVBInfo->P3c4, 0x05, 0x86);
+	if (pVBInfo->VBType & 0xFFFF) {
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x30); /* Check Display Device */
+		tempbx = tempbx | temp;
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x31);
+		push = temp;
+		push = push << 8;
+		tempax = temp << 8;
+		tempbx = tempbx | tempax;
+		temp = (SetCRT2ToDualEdge | SetCRT2ToYPbPr | SetCRT2ToLCDA
+				| SetInSlaveMode | DisableCRT2Display);
+		temp = 0xFFFF ^ temp;
+		tempbx &= temp;
 
-	/* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */
-	XGINew_SetReg1(pVBInfo->P3d4, 0x57, 0x4A);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x53, (unsigned char) (XGINew_GetReg1(
-			pVBInfo->P3d4, 0x53) | 0x02));
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
 
-	SR31 = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x31);
-	CR63 = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x63);
-	SR01 = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x01);
+		if (pVBInfo->IF_DEF_LCDA == 1) {
 
-	XGINew_SetReg1(pVBInfo->P3c4, 0x01, (unsigned char) (SR01 & 0xDF));
-	XGINew_SetReg1(pVBInfo->P3d4, 0x63, (unsigned char) (CR63 & 0xBF));
+			if ((pVBInfo->Set_VGAType >= XG20)
+					|| (pVBInfo->Set_VGAType >= XG40)) {
+				if (pVBInfo->IF_DEF_LVDS == 0) {
+					/* if ((pVBInfo->VBType & VB_XGI302B) || (pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType & VB_XGI301C)) */
+					if (pVBInfo->VBType & (VB_XGI302B
+							| VB_XGI301LV
+							| VB_XGI302LV
+							| VB_XGI301C)) {
+						if (temp & EnableDualEdge) {
+							tempbx
+									|= SetCRT2ToDualEdge;
 
-	CR17 = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x17);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x17, (unsigned char) (CR17 | 0x80));
+							if (temp & SetToLCDA)
+								tempbx
+										|= SetCRT2ToLCDA;
+						}
+					}
+				} else if (pVBInfo->IF_DEF_CH7017 == 1) {
+					if (pVBInfo->VBType & VB_CH7017) {
+						if (temp & EnableDualEdge) {
+							tempbx
+									|= SetCRT2ToDualEdge;
 
-	SR1F = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x1F);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1F, (unsigned char) (SR1F | 0x04));
+							if (temp & SetToLCDA)
+								tempbx
+										|= SetCRT2ToLCDA;
+						}
+					}
+				}
+			}
+		}
 
-	SR07 = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x07);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x07, (unsigned char) (SR07 & 0xFB));
-	SR06 = (unsigned char) XGINew_GetReg1(pVBInfo->P3c4, 0x06);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x06, (unsigned char) (SR06 & 0xC3));
+		if (pVBInfo->IF_DEF_YPbPr == 1) {
+			if (((pVBInfo->IF_DEF_LVDS == 0) && ((pVBInfo->VBType
+					& VB_XGI301LV) || (pVBInfo->VBType
+					& VB_XGI302LV) || (pVBInfo->VBType
+					& VB_XGI301C)))
+					|| ((pVBInfo->IF_DEF_CH7017 == 1)
+							&& (pVBInfo->VBType
+									& VB_CH7017))
+					|| ((pVBInfo->IF_DEF_CH7007 == 1)
+							&& (pVBInfo->VBType
+									& VB_CH7007))) { /* [Billy] 07/05/04 */
+				if (temp & SetYPbPr) { /* temp = CR38 */
+					if (pVBInfo->IF_DEF_HiVision == 1) {
+						temp = xgifb_reg_get(
+								pVBInfo->P3d4,
+								0x35); /* shampoo add for new scratch */
+						temp &= YPbPrMode;
+						tempbx |= SetCRT2ToHiVisionTV;
 
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, 0x00);
+						if (temp != YPbPrMode1080i) {
+							tempbx
+									&= (~SetCRT2ToHiVisionTV);
+							tempbx
+									|= SetCRT2ToYPbPr;
+						}
+					}
 
-	for (i = 0; i < 8; i++)
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) i, CRTCData[i]);
+					/* tempbx |= SetCRT2ToYPbPr; */
+				}
+			}
+		}
 
-	for (i = 8; i < 11; i++)
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) (i + 8),
-				CRTCData[i]);
+		tempax = push; /* restore CR31 */
 
-	for (i = 11; i < 13; i++)
-		XGINew_SetReg1(pVBInfo->P3d4, (unsigned short) (i + 4),
-				CRTCData[i]);
+		if (pVBInfo->IF_DEF_LVDS == 0) {
+			if (pVBInfo->IF_DEF_YPbPr == 1) {
+				if (pVBInfo->IF_DEF_HiVision == 1)
+					temp = 0x09FC;
+				else
+					temp = 0x097C;
+			} else {
+				if (pVBInfo->IF_DEF_HiVision == 1)
+					temp = 0x01FC;
+				else
+					temp = 0x017C;
+			}
+		} else { /* 3nd party chip */
+			if (pVBInfo->IF_DEF_CH7017 == 1)
+				temp = (SetCRT2ToTV | SetCRT2ToLCD
+						| SetCRT2ToLCDA);
+			else if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/03 */
+				temp = SetCRT2ToTV;
+			} else
+				temp = SetCRT2ToLCD;
+		}
 
-	for (i = 13; i < 16; i++)
-		XGINew_SetReg1(pVBInfo->P3c4, (unsigned short) (i - 3),
-				CRTCData[i]);
+		if (!(tempbx & temp)) {
+			tempax |= DisableCRT2Display;
+			tempbx = 0;
+		}
 
-	XGINew_SetReg1(pVBInfo->P3c4, 0x0E, (unsigned char) (CRTCData[16]
-			& 0xE0));
+		if (pVBInfo->IF_DEF_LCDA == 1) { /* Select Display Device */
+			if (!(pVBInfo->VBType & VB_NoLCD)) {
+				if (tempbx & SetCRT2ToLCDA) {
+					if (tempbx & SetSimuScanMode)
+						tempbx
+								&= (~(SetCRT2ToLCD
+										| SetCRT2ToRAMDAC
+										| SwitchToCRT2));
+					else
+						tempbx
+								&= (~(SetCRT2ToLCD
+										| SetCRT2ToRAMDAC
+										| SetCRT2ToTV
+										| SwitchToCRT2));
+				}
+			}
+		}
 
-	XGINew_SetReg1(pVBInfo->P3c4, 0x31, 0x00);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2B, 0x1B);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2C, 0xE1);
+		/* shampoo add */
+		if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode))) { /* for driver abnormal */
+			if (pVBInfo->IF_DEF_CRT2Monitor == 1) {
+				if (tempbx & SetCRT2ToRAMDAC) {
+					tempbx &= (0xFF00 | SetCRT2ToRAMDAC
+							| SwitchToCRT2
+							| SetSimuScanMode);
+					tempbx &= (0x00FF | (~SetCRT2ToYPbPr));
+				}
+			} else {
+				tempbx &= (~(SetCRT2ToRAMDAC | SetCRT2ToLCD
+						| SetCRT2ToTV));
+			}
+		}
 
-	XGINew_SetReg3(pVBInfo->P3c8, 0x00);
+		if (!(pVBInfo->VBType & VB_NoLCD)) {
+			if (tempbx & SetCRT2ToLCD) {
+				tempbx &= (0xFF00 | SetCRT2ToLCD | SwitchToCRT2
+						| SetSimuScanMode);
+				tempbx &= (0x00FF | (~SetCRT2ToYPbPr));
+			}
+		}
 
-	for (i = 0; i < 256; i++) {
-		XGINew_SetReg3((pVBInfo->P3c8 + 1),
-				(unsigned char) DAC_TEST_PARMS[0]);
-		XGINew_SetReg3((pVBInfo->P3c8 + 1),
-				(unsigned char) DAC_TEST_PARMS[1]);
-		XGINew_SetReg3((pVBInfo->P3c8 + 1),
-				(unsigned char) DAC_TEST_PARMS[2]);
-	}
+		if (tempbx & SetCRT2ToSCART) {
+			tempbx &= (0xFF00 | SetCRT2ToSCART | SwitchToCRT2
+					| SetSimuScanMode);
+			tempbx &= (0x00FF | (~SetCRT2ToYPbPr));
+		}
 
-	XGI_VBLongWait(pVBInfo);
-	XGI_VBLongWait(pVBInfo);
-	XGI_VBLongWait(pVBInfo);
+		if (pVBInfo->IF_DEF_YPbPr == 1) {
+			if (tempbx & SetCRT2ToYPbPr)
+				tempbx &= (0xFF00 | SwitchToCRT2
+						| SetSimuScanMode);
+		}
 
-	XGINew_LCD_Wait_Time(0x01, pVBInfo);
+		if (pVBInfo->IF_DEF_HiVision == 1) {
+			if (tempbx & SetCRT2ToHiVisionTV)
+				tempbx &= (0xFF00 | SetCRT2ToHiVisionTV
+						| SwitchToCRT2
+						| SetSimuScanMode);
+		}
 
-	XGI_WaitDisply(pVBInfo);
-	temp = XGINew_GetReg2(pVBInfo->P3c2);
+		if (tempax & DisableCRT2Display) { /* Set Display Device Info */
+			if (!(tempbx & (SwitchToCRT2 | SetSimuScanMode)))
+				tempbx = DisableCRT2Display;
+		}
 
-	if (temp & 0x10)
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, 0xDF, 0x20);
-	else
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0x32, 0xDF, 0x00);
+		if (!(tempbx & DisableCRT2Display)) {
+			if ((!(tempbx & DriverMode))
+					|| (!(modeflag & CRT2Mode))) {
+				if (pVBInfo->IF_DEF_LCDA == 1) {
+					if (!(tempbx & SetCRT2ToLCDA))
+						tempbx
+								|= (SetInSlaveMode
+										| SetSimuScanMode);
+				}
 
-	/* alan, avoid display something, set BLACK DAC if not restore DAC */
-	XGINew_SetReg3(pVBInfo->P3c8, 0x00);
+				if (pVBInfo->IF_DEF_VideoCapture == 1) {
+					if (((HwDeviceExtension->jChipType
+							== XG40)
+							&& (pVBInfo->Set_VGAType
+									== XG40))
+							|| ((HwDeviceExtension->jChipType
+									== XG41)
+									&& (pVBInfo->Set_VGAType
+											== XG41))
+							|| ((HwDeviceExtension->jChipType
+									== XG42)
+									&& (pVBInfo->Set_VGAType
+											== XG42))
+							|| ((HwDeviceExtension->jChipType
+									== XG45)
+									&& (pVBInfo->Set_VGAType
+											== XG45))) {
+						if (ModeNo <= 13) {
+							if (!(tempbx
+									& SetCRT2ToRAMDAC)) { /*CRT2 not need to support*/
+								tempbx
+										&= (0x00FF
+												| (~SetInSlaveMode));
+								pVBInfo->SetFlag
+										|= EnableVCMode;
+							}
+						}
+					}
+				}
+			}
 
-	for (i = 0; i < 256; i++) {
-		XGINew_SetReg3((pVBInfo->P3c8 + 1), 0);
-		XGINew_SetReg3((pVBInfo->P3c8 + 1), 0);
-		XGINew_SetReg3((pVBInfo->P3c8 + 1), 0);
+			/* LCD+TV can't support in slave mode (Force LCDA+TV->LCDB) */
+			if ((tempbx & SetInSlaveMode) && (tempbx
+					& SetCRT2ToLCDA)) {
+				tempbx ^= (SetCRT2ToLCD | SetCRT2ToLCDA
+						| SetCRT2ToDualEdge);
+				pVBInfo->SetFlag |= ReserveTVOption;
+			}
+		}
 	}
 
-	XGINew_SetReg1(pVBInfo->P3c4, 0x01, SR01);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x63, CR63);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x31, SR31);
-
-	/* [2004/05/11] Vicent */
-	XGINew_SetReg1(pVBInfo->P3d4, 0x53, (unsigned char) (XGINew_GetReg1(
-			pVBInfo->P3d4, 0x53) & 0xFD));
-	XGINew_SetReg1(pVBInfo->P3c4, 0x1F, (unsigned char) SR1F);
-}
-
-#if 0
-static void XGI_WaitDisplay(struct vb_device_info *pVBInfo)
-{
-	while (!(XGINew_GetReg2(pVBInfo->P3da) & 0x01));
-	while (XGINew_GetReg2(pVBInfo->P3da) & 0x01);
+	pVBInfo->VBInfo = tempbx;
 }
-#endif
 
-unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
-		struct xgi_hw_device_info *HwDeviceExtension,
+void XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx, ModeIdIndex, RefreshRateTableIndex;
-
-	tempbx = pVBInfo->VBInfo;
-	pVBInfo->SetFlag |= ProgrammingCRT2;
-	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
-	pVBInfo->SelectCRT2Rate = 4;
-	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
-			ModeIdIndex, pVBInfo);
-	XGI_SaveCRT2Info(ModeNo, pVBInfo);
-	XGI_GetCRT2ResInfo(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_GetCRT2Data(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_PreSetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetLockRegs(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetLCDRegs(ModeNo, ModeIdIndex, HwDeviceExtension,
-			RefreshRateTableIndex, pVBInfo);
-	XGI_SetTap4Regs(pVBInfo);
-	XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_SetGroup4(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	XGI_SetGroup5(ModeNo, ModeIdIndex, pVBInfo);
-	XGI_AutoThreshold(pVBInfo);
-	return 1;
-}
+	unsigned short temp, tempbx = 0, resinfo = 0, modeflag, index1;
 
-void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
-{
-	if (!(pVBInfo->SetFlag & Win9xDOSMode))
-		XGINew_SetRegOR(pVBInfo->Part1Port, 0x01, 0x40);
-}
+	tempbx = 0;
+	resinfo = 0;
 
-void XGI_SaveCRT2Info(unsigned short ModeNo, struct vb_device_info *pVBInfo)
-{
-	unsigned short temp1, temp2;
+	if (pVBInfo->VBInfo & SetCRT2ToTV) {
+		if (ModeNo <= 0x13) {
+			modeflag
+					= pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag */
+			resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo; /* si+St_ResInfo */
+		} else {
+			modeflag
+					= pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+			resinfo
+					= pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo */
+		}
 
-	XGINew_SetReg1(pVBInfo->P3d4, 0x34, ModeNo); /* reserve CR34 for CRT1 Mode No */
-	temp1 = (pVBInfo->VBInfo & SetInSlaveMode) >> 8;
-	temp2 = ~(SetInSlaveMode >> 8);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x31, temp2, temp1);
-}
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			temp = xgifb_reg_get(pVBInfo->P3d4, 0x35);
+			tempbx = temp;
+			if (tempbx & SetPALTV) {
+				tempbx &= (SetCHTVOverScan | SetPALMTV
+						| SetPALNTV | SetPALTV);
+				if (tempbx & SetPALMTV)
+					tempbx &= ~SetPALTV; /* set to NTSC if PAL-M */
+			} else
+				tempbx &= (SetCHTVOverScan | SetNTSCJ
+						| SetPALTV);
+			/*
+			if (pVBInfo->IF_DEF_LVDS == 0) {
+				index1 = xgifb_reg_get(pVBInfo->P3d4, 0x38); //PAL-M/PAL-N Info
+				temp2 = (index1 & 0xC0) >> 5; //00:PAL, 01:PAL-M, 10:PAL-N
+				tempbx |= temp2;
+				if (temp2 & 0x02)          //PAL-M
+					tempbx &= (~SetPALTV);
+			}
+			*/
+		}
 
-void XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short xres, yres, modeflag, resindex;
+		if (pVBInfo->IF_DEF_CH7017 == 1) {
+			tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
 
-	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
-	if (ModeNo <= 0x13) {
-		xres = pVBInfo->StResInfo[resindex].HTotal;
-		yres = pVBInfo->StResInfo[resindex].VTotal;
-		/* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; si+St_ResInfo */
-	} else {
-		xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
-		yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+St_ModeFlag */
+			if (tempbx & TVOverScan)
+				tempbx |= SetCHTVOverScan;
+		}
 
-		/*
-		if (pVBInfo->IF_DEF_FSTN) {
-			xres *= 2;
-			yres *= 2;
-		 } else {
-		*/
-		if (modeflag & HalfDCLK)
-			xres *= 2;
+		if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/04 */
+			tempbx = xgifb_reg_get(pVBInfo->P3d4, 0x35);
 
-		if (modeflag & DoubleScanMode)
-			yres *= 2;
-		/* } */
-	}
+			if (tempbx & TVOverScan)
+				tempbx |= SetCHTVOverScan;
+		}
 
-	if (pVBInfo->VBInfo & SetCRT2ToLCD) {
 		if (pVBInfo->IF_DEF_LVDS == 0) {
-			if (pVBInfo->LCDResInfo == Panel1600x1200) {
-				if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
-					if (yres == 1024)
-						yres = 1056;
-				}
-			}
+			if (pVBInfo->VBInfo & SetCRT2ToSCART)
+				tempbx |= SetPALTV;
+		}
 
-			if (pVBInfo->LCDResInfo == Panel1280x1024) {
-				if (yres == 400)
-					yres = 405;
-				else if (yres == 350)
-					yres = 360;
+		if (pVBInfo->IF_DEF_YPbPr == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
+				index1 = xgifb_reg_get(pVBInfo->P3d4, 0x35);
+				index1 &= YPbPrMode;
 
-				if (pVBInfo->LCDInfo & LCDVESATiming) {
-					if (yres == 360)
-						yres = 375;
-				}
-			}
+				if (index1 == YPbPrMode525i)
+					tempbx |= SetYPbPrMode525i;
 
-			if (pVBInfo->LCDResInfo == Panel1024x768) {
-				if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
-					if (!(pVBInfo->LCDInfo
-							& LCDNonExpanding)) {
-						if (yres == 350)
-							yres = 357;
-						else if (yres == 400)
-							yres = 420;
-						else if (yres == 480)
-							yres = 525;
-					}
-				}
+				if (index1 == YPbPrMode525p)
+					tempbx = tempbx | SetYPbPrMode525p;
+				if (index1 == YPbPrMode750p)
+					tempbx = tempbx | SetYPbPrMode750p;
 			}
 		}
 
-		if (xres == 720)
-			xres = 640;
-	}
+		if (pVBInfo->IF_DEF_HiVision == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
+				tempbx = tempbx | SetYPbPrMode1080i | SetPALTV;
+		}
 
-	pVBInfo->VGAHDE = xres;
-	pVBInfo->HDE = xres;
-	pVBInfo->VGAVDE = yres;
-	pVBInfo->VDE = yres;
-}
+		if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */
+			if ((pVBInfo->VBInfo & SetInSlaveMode)
+					&& (!(pVBInfo->VBInfo & SetNotSimuMode)))
+				tempbx |= TVSimuMode;
 
-unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
-{
+			if (!(tempbx & SetPALTV) && (modeflag > 13) && (resinfo
+					== 8)) /* NTSC 1024x768, */
+				tempbx |= NTSC1024x768;
 
-	if ((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
-			(pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */
-		return 1;
+			tempbx |= RPLLDIV2XO;
 
-	return 0;
+			if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+				if (pVBInfo->VBInfo & SetInSlaveMode)
+					tempbx &= (~RPLLDIV2XO);
+			} else {
+				if (tempbx & (SetYPbPrMode525p
+						| SetYPbPrMode750p))
+					tempbx &= (~RPLLDIV2XO);
+				else if (!(pVBInfo->VBType & (VB_XGI301B
+						| VB_XGI302B | VB_XGI301LV
+						| VB_XGI302LV | VB_XGI301C))) {
+					if (tempbx & TVSimuMode)
+						tempbx &= (~RPLLDIV2XO);
+				}
+			}
+		}
+	}
+	pVBInfo->TVInfo = tempbx;
 }
 
-void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
+unsigned char XGI_GetLCDInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempax = 0, tempbx, modeflag, resinfo;
+	unsigned short temp, tempax, tempbx, modeflag, resinfo = 0, LCDIdIndex;
 
-	struct XGI_LCDDataStruct *LCDPtr = NULL;
-	struct XGI_TVDataStruct *TVPtr = NULL;
+	pVBInfo->LCDResInfo = 0;
+	pVBInfo->LCDTypeInfo = 0;
+	pVBInfo->LCDInfo = 0;
 
 	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
-		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ModeFlag // */
 	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
-		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO; /* si+Ext_ResInfo // */
 	}
 
-	pVBInfo->NewFlickerMode = 0;
-	pVBInfo->RVBHRS = 50;
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x36); /* Get LCD Res.Info */
+	tempbx = temp & 0x0F;
 
-	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-		XGI_GetRAMDAC2DATA(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo);
-		return;
+	if (tempbx == 0)
+		tempbx = Panel1024x768; /* default */
+
+	/* LCD75 [2003/8/22] Vicent */
+	if ((tempbx == Panel1024x768) || (tempbx == Panel1280x1024)) {
+		if (pVBInfo->VBInfo & DriverMode) {
+			tempax = xgifb_reg_get(pVBInfo->P3d4, 0x33);
+			if (pVBInfo->VBInfo & SetCRT2ToLCDA)
+				tempax &= 0x0F;
+			else
+				tempax = tempax >> 4;
+
+			if ((resinfo == 6) || (resinfo == 9)) {
+				if (tempax >= 3)
+					tempbx |= PanelRef75Hz;
+			} else if ((resinfo == 7) || (resinfo == 8)) {
+				if (tempax >= 4)
+					tempbx |= PanelRef75Hz;
+			}
+		}
 	}
 
-	tempbx = 4;
+	pVBInfo->LCDResInfo = tempbx;
 
-	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-		LCDPtr = (struct XGI_LCDDataStruct *) XGI_GetLcdPtr(tempbx,
-				ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo);
+	/* End of LCD75 */
 
-		pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
-		pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT;
-		pVBInfo->VGAHT = LCDPtr->VGAHT;
-		pVBInfo->VGAVT = LCDPtr->VGAVT;
-		pVBInfo->HT = LCDPtr->LCDHT;
-		pVBInfo->VT = LCDPtr->LCDVT;
+	if (pVBInfo->IF_DEF_OEMUtil == 1)
+		pVBInfo->LCDTypeInfo = (temp & 0xf0) >> 4;
 
-		if (pVBInfo->LCDResInfo == Panel1024x768) {
-			tempax = 1024;
-			tempbx = 768;
+	if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)))
+		return 0;
 
-			if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
-				if (pVBInfo->VGAVDE == 357)
-					tempbx = 527;
-				else if (pVBInfo->VGAVDE == 420)
-					tempbx = 620;
-				else if (pVBInfo->VGAVDE == 525)
-					tempbx = 775;
-				else if (pVBInfo->VGAVDE == 600)
-					tempbx = 775;
-				/* else if (pVBInfo->VGAVDE==350) tempbx=560; */
-				/* else if (pVBInfo->VGAVDE==400) tempbx=640; */
-				else
-					tempbx = 768;
-			} else
-				tempbx = 768;
-		} else if (pVBInfo->LCDResInfo == Panel1024x768x75) {
-			tempax = 1024;
-			tempbx = 768;
-		} else if (pVBInfo->LCDResInfo == Panel1280x1024) {
-			tempax = 1280;
-			if (pVBInfo->VGAVDE == 360)
-				tempbx = 768;
-			else if (pVBInfo->VGAVDE == 375)
-				tempbx = 800;
-			else if (pVBInfo->VGAVDE == 405)
-				tempbx = 864;
-			else
-				tempbx = 1024;
-		} else if (pVBInfo->LCDResInfo == Panel1280x1024x75) {
-			tempax = 1280;
-			tempbx = 1024;
-		} else if (pVBInfo->LCDResInfo == Panel1280x960) {
-			tempax = 1280;
-			if (pVBInfo->VGAVDE == 350)
-				tempbx = 700;
-			else if (pVBInfo->VGAVDE == 400)
-				tempbx = 800;
-			else if (pVBInfo->VGAVDE == 1024)
-				tempbx = 960;
-			else
-				tempbx = 960;
-		} else if (pVBInfo->LCDResInfo == Panel1400x1050) {
-			tempax = 1400;
-			tempbx = 1050;
+	tempbx = 0;
 
-			if (pVBInfo->VGAVDE == 1024) {
-				tempax = 1280;
-				tempbx = 1024;
-			}
-		} else if (pVBInfo->LCDResInfo == Panel1600x1200) {
-			tempax = 1600;
-			tempbx = 1200; /* alan 10/14/2003 */
-			if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
-				if (pVBInfo->VGAVDE == 350)
-					tempbx = 875;
-				else if (pVBInfo->VGAVDE == 400)
-					tempbx = 1000;
-			}
-		}
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
 
-		if (pVBInfo->LCDInfo & LCDNonExpanding) {
-			tempax = pVBInfo->VGAHDE;
-			tempbx = pVBInfo->VGAVDE;
+	temp &= (ScalingLCD | LCDNonExpanding | LCDSyncBit | SetPWDEnable);
+
+	if ((pVBInfo->IF_DEF_ScaleLCD == 1) && (temp & LCDNonExpanding))
+		temp &= ~EnableScalingLCD;
+
+	tempbx |= temp;
+
+	LCDIdIndex = XGI_GetLCDCapPtr1(pVBInfo);
+
+	tempax = pVBInfo->LCDCapList[LCDIdIndex].LCD_Capability;
+
+	if (pVBInfo->IF_DEF_LVDS == 0) { /* shampoo */
+		if (((pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType
+				& VB_XGI301C)) && (tempax & LCDDualLink)) {
+			tempbx |= SetLCDDualLink;
 		}
+	}
 
-		pVBInfo->HDE = tempax;
-		pVBInfo->VDE = tempbx;
-		return;
+	if (pVBInfo->IF_DEF_CH7017 == 1) {
+		if (tempax & LCDDualLink)
+			tempbx |= SetLCDDualLink;
 	}
 
-	if (pVBInfo->VBInfo & (SetCRT2ToTV)) {
-		tempbx = 4;
-		TVPtr = (struct XGI_TVDataStruct *) XGI_GetTVPtr(tempbx,
-				ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo);
+	if (pVBInfo->IF_DEF_LVDS == 0) {
+		if ((pVBInfo->LCDResInfo == Panel1400x1050) && (pVBInfo->VBInfo
+				& SetCRT2ToLCD) && (ModeNo > 0x13) && (resinfo
+				== 9) && (!(tempbx & EnableScalingLCD)))
+			tempbx |= SetLCDtoNonExpanding; /* set to center in 1280x1024 LCDB for Panel1400x1050 */
+	}
 
-		pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX;
-		pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT;
-		pVBInfo->VGAHT = TVPtr->VGAHT;
-		pVBInfo->VGAVT = TVPtr->VGAVT;
-		pVBInfo->HDE = TVPtr->TVHDE;
-		pVBInfo->VDE = TVPtr->TVVDE;
-		pVBInfo->RVBHRS = TVPtr->RVBHRS;
-		pVBInfo->NewFlickerMode = TVPtr->FlickerMode;
+	/*
+	if (tempax & LCDBToA) {
+		tempbx |= SetLCDBToA;
+	}
+	*/
 
-		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-			if (resinfo == 0x08)
-				pVBInfo->NewFlickerMode = 0x40;
-			else if (resinfo == 0x09)
-				pVBInfo->NewFlickerMode = 0x40;
-			else if (resinfo == 0x12)
-				pVBInfo->NewFlickerMode = 0x40;
+	if (pVBInfo->IF_DEF_ExpLink == 1) {
+		if (modeflag & HalfDCLK) {
+			/* if (!(pVBInfo->LCDInfo&LCDNonExpanding)) */
+			if (!(tempbx & SetLCDtoNonExpanding)) {
+				tempbx |= EnableLVDSDDA;
+			} else {
+				if (ModeNo > 0x13) {
+					if (pVBInfo->LCDResInfo
+							== Panel1024x768) {
+						if (resinfo == 4) { /* 512x384  */
+							tempbx |= EnableLVDSDDA;
+						}
+					}
+				}
+			}
+		}
+	}
 
-			if (pVBInfo->VGAVDE == 350)
-				pVBInfo->TVInfo |= TVSimuMode;
+	if (pVBInfo->VBInfo & SetInSlaveMode) {
+		if (pVBInfo->VBInfo & SetNotSimuMode)
+			tempbx |= LCDVESATiming;
+	} else {
+		tempbx |= LCDVESATiming;
+	}
 
-			tempax = ExtHiTVHT;
-			tempbx = ExtHiTVVT;
+	pVBInfo->LCDInfo = tempbx;
 
-			if (pVBInfo->VBInfo & SetInSlaveMode) {
-				if (pVBInfo->TVInfo & TVSimuMode) {
-					tempax = StHiTVHT;
-					tempbx = StHiTVVT;
+	if (pVBInfo->IF_DEF_PWD == 1) {
+		if (pVBInfo->LCDInfo & SetPWDEnable) {
+			if ((pVBInfo->VBType & VB_XGI302LV) || (pVBInfo->VBType
+					& VB_XGI301C)) {
+				if (!(tempax & PWDEnable))
+					pVBInfo->LCDInfo &= ~SetPWDEnable;
+			}
+		}
+	}
 
-					if (!(modeflag & Charx8Dot)) {
-						tempax = StHiTextTVHT;
-						tempbx = StHiTextTVVT;
+	if (pVBInfo->IF_DEF_LVDS == 0) {
+		if (tempax & (LockLCDBToA | StLCDBToA)) {
+			if (pVBInfo->VBInfo & SetInSlaveMode) {
+				if (!(tempax & LockLCDBToA)) {
+					if (ModeNo <= 0x13) {
+						pVBInfo->VBInfo
+								&= ~(SetSimuScanMode
+										| SetInSlaveMode
+										| SetCRT2ToLCD);
+						pVBInfo->VBInfo
+								|= SetCRT2ToLCDA
+										| SetCRT2ToDualEdge;
 					}
 				}
 			}
-		} else if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
-			if (pVBInfo->TVInfo & SetYPbPrMode750p) {
-				tempax = YPbPrTV750pHT; /* Ext750pTVHT */
-				tempbx = YPbPrTV750pVT; /* Ext750pTVVT */
-			}
+		}
+	}
 
-			if (pVBInfo->TVInfo & SetYPbPrMode525p) {
-				tempax = YPbPrTV525pHT; /* Ext525pTVHT */
-				tempbx = YPbPrTV525pVT; /* Ext525pTVVT */
-			} else if (pVBInfo->TVInfo & SetYPbPrMode525i) {
-				tempax = YPbPrTV525iHT; /* Ext525iTVHT */
-				tempbx = YPbPrTV525iVT; /* Ext525iTVVT */
-				if (pVBInfo->TVInfo & NTSC1024x768)
-					tempax = NTSC1024x768HT;
-			}
-		} else {
-			tempax = PALHT;
-			tempbx = PALVT;
-			if (!(pVBInfo->TVInfo & SetPALTV)) {
-				tempax = NTSCHT;
-				tempbx = NTSCVT;
-				if (pVBInfo->TVInfo & NTSC1024x768)
-					tempax = NTSC1024x768HT;
+	/*
+	if (pVBInfo->IF_DEF_LVDS == 0) {
+		if (tempax & (LockLCDBToA | StLCDBToA)) {
+			if (pVBInfo->VBInfo & SetInSlaveMode) {
+				if (!((!(tempax & LockLCDBToA)) && (ModeNo > 0x13))) {
+					pVBInfo->VBInfo&=~(SetSimuScanMode|SetInSlaveMode|SetCRT2ToLCD);
+					pVBInfo->VBInfo|=SetCRT2ToLCDA|SetCRT2ToDualEdge;
+				}
 			}
 		}
+	}
+	*/
 
-		pVBInfo->HT = tempax;
-		pVBInfo->VT = tempbx;
-		return;
+	return 1;
+}
+
+unsigned char XGI_SearchModeID(unsigned short ModeNo,
+		unsigned short *ModeIdIndex, struct vb_device_info *pVBInfo)
+{
+	if (ModeNo <= 5)
+		ModeNo |= 1;
+	if (ModeNo <= 0x13) {
+		/* for (*ModeIdIndex=0; *ModeIdIndex < sizeof(pVBInfo->SModeIDTable) / sizeof(struct XGI_StStruct); (*ModeIdIndex)++) */
+		for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
+			if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == ModeNo)
+				break;
+			if (pVBInfo->SModeIDTable[*ModeIdIndex].St_ModeID == 0xFF)
+				return 0;
+		}
+
+		if (ModeNo == 0x07)
+			(*ModeIdIndex)++; /* 400 lines */
+		if (ModeNo <= 3)
+			(*ModeIdIndex) += 2; /* 400 lines */
+		/* else 350 lines */
+	} else {
+		/* for (*ModeIdIndex=0; *ModeIdIndex < sizeof(pVBInfo->EModeIDTable) / sizeof(struct XGI_ExtStruct); (*ModeIdIndex)++) */
+		for (*ModeIdIndex = 0;; (*ModeIdIndex)++) {
+			if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == ModeNo)
+				break;
+			if (pVBInfo->EModeIDTable[*ModeIdIndex].Ext_ModeID == 0xFF)
+				return 0;
+		}
 	}
+
+	return 1;
 }
 
-void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
+/* win2000 MM adapter not support standard mode! */
+
+#if 0
+static unsigned char XGINew_CheckMemorySize(
+		struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short ModeNo,
+		unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned char di_0, di_1, tempal;
-
-	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex,
-			pVBInfo);
-	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
-	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
+	unsigned short memorysize, modeflag, temp, temp1, tmp;
 
-	if (pVBInfo->VBType & VB_XGI301) { /* shampoo 0129 */
-		/* 301 */
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x0A, 0x10);
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x0B, di_1);
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x0A, di_0);
-	} else { /* 301b/302b/301lv/302lv */
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x0A, di_0);
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x0B, di_1);
+	/*
+	if ((HwDeviceExtension->jChipType == XGI_650) ||
+	(HwDeviceExtension->jChipType == XGI_650M)) {
+		return 1;
 	}
+	*/
 
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x00, 0x12);
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
-		XGINew_SetRegOR(pVBInfo->Part4Port, 0x12, 0x28);
+	/* ModeType = modeflag&ModeInfoFlag; // Get mode type */
+
+	memorysize = modeflag & MemoryInfoFlag;
+	memorysize = memorysize > MemorySizeShift;
+	memorysize++; /* Get memory size */
+
+	temp = xgifb_reg_get(pVBInfo->P3c4, 0x14); /* Get DRAM Size */
+	tmp = temp;
+
+	if (HwDeviceExtension->jChipType == XG40) {
+		temp = 1 << ((temp & 0x0F0) >> 4); /* memory size per channel SR14[7:4] */
+		if ((tmp & 0x0c) == 0x0C) { /* Qual channels */
+			temp <<= 2;
+		} else if ((tmp & 0x0c) == 0x08) { /* Dual channels */
+			temp <<= 1;
+		}
+	} else if (HwDeviceExtension->jChipType == XG42) {
+		temp = 1 << ((temp & 0x0F0) >> 4); /* memory size per channel SR14[7:4] */
+		if ((tmp & 0x04) == 0x04) { /* Dual channels */
+			temp <<= 1;
+		}
+	} else if (HwDeviceExtension->jChipType == XG45) {
+		temp = 1 << ((temp & 0x0F0) >> 4); /* memory size per channel SR14[7:4] */
+		if ((tmp & 0x0c) == 0x0C) { /* Qual channels */
+			temp <<= 2;
+		} else if ((tmp & 0x0c) == 0x08) { /* triple channels */
+			temp1 = temp;
+			temp <<= 1;
+			temp += temp1;
+		} else if ((tmp & 0x0c) == 0x04) { /* Dual channels */
+			temp <<= 1;
+		}
+	}
+	if (temp < memorysize)
+		return 0;
 	else
-		XGINew_SetRegOR(pVBInfo->Part4Port, 0x12, 0x08);
+		return 1;
 }
+#endif
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_GETLCDVCLKPtr */
-/* Input : */
-/* Output : al -> VCLK Index */
-/* Description : */
-/* --------------------------------------------------------------------- */
-void XGI_GetLCDVCLKPtr(unsigned char *di_0, unsigned char *di_1,
-		struct vb_device_info *pVBInfo)
+/*
+void XGINew_IsLowResolution(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGINew_CheckMemorySize(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
 {
-	unsigned short index;
-
-	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-		if (pVBInfo->IF_DEF_ScaleLCD == 1) {
-			if (pVBInfo->LCDInfo & EnableScalingLCD)
-				return;
-		}
+	unsigned short data ;
+	unsigned short ModeFlag ;
 
-		/* index = XGI_GetLCDCapPtr(pVBInfo); */
-		index = XGI_GetLCDCapPtr1(pVBInfo);
+	data = xgifb_reg_get(pVBInfo->P3c4, 0x0F);
+	data &= 0x7F;
+	xgifb_reg_set(pVBInfo->P3c4, 0x0F, data);
 
-		if (pVBInfo->VBInfo & SetCRT2ToLCD) { /* LCDB */
-			*di_0 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData1;
-			*di_1 = pVBInfo->LCDCapList[index].LCUCHAR_VCLKData2;
-		} else { /* LCDA */
-			*di_0 = pVBInfo->LCDCapList[index].LCDA_VCLKData1;
-			*di_1 = pVBInfo->LCDCapList[index].LCDA_VCLKData2;
+	if (ModeNo > 0x13) {
+		ModeFlag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		if ((ModeFlag & HalfDCLK) && (ModeFlag & DoubleScanMode)) {
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x0F);
+			data |= 0x80;
+			xgifb_reg_set(pVBInfo->P3c4, 0x0F, data);
+			data = xgifb_reg_get(pVBInfo->P3c4, 0x01);
+			data &= 0xF7;
+			xgifb_reg_set(pVBInfo->P3c4, 0x01, data);
 		}
 	}
-	return;
 }
+*/
 
-unsigned char XGI_GetVCLKPtr(unsigned short RefreshRateTableIndex,
-		unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
+static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
 {
+	unsigned char ujRet = 0;
+	unsigned char i = 0;
 
-	unsigned short index, modeflag;
-	unsigned short tempbx;
-	unsigned char tempal;
-	unsigned char *CHTVVCLKPtr = NULL;
+	for (i = 0; i < 8; i++) {
+		ujRet = ujRet << 1;
+		/* ujRet |= GETBITS(ujDate >> i, 0:0); */
+		ujRet |= (ujDate >> i) & 1;
+	}
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+	return ujRet;
+}
 
-	if ((pVBInfo->SetFlag & ProgrammingCRT2) && (!(pVBInfo->LCDInfo
-			& EnableScalingLCD))) { /* {LCDA/LCDB} */
-		index = XGI_GetLCDCapPtr(pVBInfo);
-		tempal = pVBInfo->LCDCapList[index].LCD_VCLK;
+/*----------------------------------------------------------------------------*/
+/* output                                                                     */
+/*      bl[5] : LVDS signal                                                   */
+/*      bl[1] : LVDS backlight                                                */
+/*      bl[0] : LVDS VDD                                                      */
+/*----------------------------------------------------------------------------*/
+static unsigned char XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo)
+{
+	unsigned char CR4A, temp;
 
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))
-			return tempal;
+	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x23); /* enable GPIO write */
 
-		/* {TV} */
-		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)) {
-			if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-				tempal = HiTVVCLKDIV2;
-				if (!(pVBInfo->TVInfo & RPLLDIV2XO))
-					tempal = HiTVVCLK;
-				if (pVBInfo->TVInfo & TVSimuMode) {
-					tempal = HiTVSimuVCLK;
-					if (!(modeflag & Charx8Dot))
-						tempal = HiTVTextVCLK;
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
 
-				}
-				return tempal;
-			}
+	temp = XG21GPIODataTransfer(temp);
+	temp &= 0x23;
+	xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
+	return temp;
+}
 
-			if (pVBInfo->TVInfo & SetYPbPrMode750p) {
-				tempal = YPbPr750pVCLK;
-				return tempal;
-			}
+/*----------------------------------------------------------------------------*/
+/* output                                                                     */
+/*      bl[5] : LVDS signal                                                   */
+/*      bl[1] : LVDS backlight                                                */
+/*      bl[0] : LVDS VDD                                                      */
+/*----------------------------------------------------------------------------*/
+static unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
+{
+	unsigned char CR4A, CRB4, temp;
 
-			if (pVBInfo->TVInfo & SetYPbPrMode525p) {
-				tempal = YPbPr525pVCLK;
-				return tempal;
-			}
+	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
+	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x0C); /* enable GPIO write */
 
-			tempal = NTSC1024VCLK;
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
 
-			if (!(pVBInfo->TVInfo & NTSC1024x768)) {
-				tempal = TVVCLKDIV2;
-				if (!(pVBInfo->TVInfo & RPLLDIV2XO))
-					tempal = TVVCLK;
-			}
+	temp &= 0x0C;
+	temp >>= 2;
+	xgifb_reg_set(pVBInfo->P3d4, 0x4A, CR4A);
+	CRB4 = xgifb_reg_get(pVBInfo->P3d4, 0xB4);
+	temp |= ((CRB4 & 0x04) << 3);
+	return temp;
+}
 
-			if (pVBInfo->VBInfo & SetCRT2ToTV)
-				return tempal;
-		}
-		/* else if ((pVBInfo->IF_DEF_CH7017==1)&&(pVBInfo->VBType&VB_CH7017)) {
-			if (ModeNo<=0x13)
-				*tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-			else
-				*tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-			*tempal = *tempal & 0x1F;
-			tempbx = 0;
-			if (pVBInfo->TVInfo & SetPALTV)
-				tempbx = tempbx + 2;
-			if (pVBInfo->TVInfo & SetCHTVOverScan)
-				tempbx++;
-			tempbx = tempbx << 1;
-		} */
-	} /* {End of VB} */
+void XGI_DisplayOn(struct xgi_hw_device_info *pXGIHWDE,
+		struct vb_device_info *pVBInfo)
+{
 
-	if ((pVBInfo->IF_DEF_CH7007 == 1) && (pVBInfo->VBType & VB_CH7007)) { /* [Billy] 07/05/08 CH7007 */
-		/* VideoDebugPrint((0, "XGI_GetVCLKPtr: pVBInfo->IF_DEF_CH7007==1\n")); */
-		if ((pVBInfo->VBInfo & SetCRT2ToTV)) {
-			if (ModeNo <= 0x13) {
-				tempal
-						= pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-			} else {
-				tempal
-						= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x00);
+	if (pXGIHWDE->jChipType == XG21) {
+		if (pVBInfo->IF_DEF_LVDS == 1) {
+			if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x1)) {
+				XGI_XG21BLSignalVDD(0x01, 0x01, pVBInfo); /* LVDS VDD on */
+				XGI_XG21SetPanelDelay(2, pVBInfo);
 			}
+			if (!(XGI_XG21GetPSCValue(pVBInfo) & 0x20))
+				XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); /* LVDS signal on */
+			XGI_XG21SetPanelDelay(3, pVBInfo);
+			XGI_XG21BLSignalVDD(0x02, 0x02, pVBInfo); /* LVDS backlight on */
+		} else {
+			XGI_XG21BLSignalVDD(0x20, 0x20, pVBInfo); /* DVO/DVI signal on */
+		}
 
-			tempal = tempal & 0x0F;
-			tempbx = 0;
+	}
 
-			if (pVBInfo->TVInfo & SetPALTV)
-				tempbx = tempbx + 2;
+	if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/23 For CH7007 */
 
-			if (pVBInfo->TVInfo & SetCHTVOverScan)
-				tempbx++;
+	}
 
-			/** tempbx = tempbx << 1; CH7007 ? **/
+	if (pXGIHWDE->jChipType == XG27) {
+		if (pVBInfo->IF_DEF_LVDS == 1) {
+			if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x1)) {
+				XGI_XG27BLSignalVDD(0x01, 0x01, pVBInfo); /* LVDS VDD on */
+				XGI_XG21SetPanelDelay(2, pVBInfo);
+			}
+			if (!(XGI_XG27GetPSCValue(pVBInfo) & 0x20))
+				XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); /* LVDS signal on */
+			XGI_XG21SetPanelDelay(3, pVBInfo);
+			XGI_XG27BLSignalVDD(0x02, 0x02, pVBInfo); /* LVDS backlight on */
+		} else {
+			XGI_XG27BLSignalVDD(0x20, 0x20, pVBInfo); /* DVO/DVI signal on */
+		}
 
-			/* [Billy]07/05/29 CH7007 */
-			if (pVBInfo->IF_DEF_CH7007 == 1) {
-				switch (tempbx) {
-				case 0:
-					CHTVVCLKPtr = XGI7007_CHTVVCLKUNTSC;
-					break;
-				case 1:
-					CHTVVCLKPtr = XGI7007_CHTVVCLKONTSC;
-					break;
-				case 2:
-					CHTVVCLKPtr = XGI7007_CHTVVCLKUPAL;
-					break;
-				case 3:
-					CHTVVCLKPtr = XGI7007_CHTVVCLKOPAL;
-					break;
-				default:
-					break;
+	}
+}
 
-				}
-			}
-			/* else {
-				switch(tempbx) {
-				case 0:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC;
-					break;
-				case 1:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC;
-					break;
-				case 2:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL;
-					break;
-				case 3:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL;
-					break;
-				default:
-					break;
-				}
-			}
-			*/
+void XGI_DisplayOff(struct xgi_hw_device_info *pXGIHWDE,
+		struct vb_device_info *pVBInfo)
+{
 
-			tempal = CHTVVCLKPtr[tempal];
-			return tempal;
+	if (pXGIHWDE->jChipType == XG21) {
+		if (pVBInfo->IF_DEF_LVDS == 1) {
+			XGI_XG21BLSignalVDD(0x02, 0x00, pVBInfo); /* LVDS backlight off */
+			XGI_XG21SetPanelDelay(3, pVBInfo);
+		} else {
+			XGI_XG21BLSignalVDD(0x20, 0x00, pVBInfo); /* DVO/DVI signal off */
 		}
+	}
 
+	if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 07/05/23 For CH7007 */
+		/* if (IsCH7007TVMode(pVBInfo) == 0) */
+		{
+		}
 	}
 
-	tempal = (unsigned char) XGINew_GetReg2((pVBInfo->P3ca + 0x02));
-	tempal = tempal >> 2;
-	tempal &= 0x03;
+	if (pXGIHWDE->jChipType == XG27) {
+		if ((XGI_XG27GetPSCValue(pVBInfo) & 0x2)) {
+			XGI_XG27BLSignalVDD(0x02, 0x00, pVBInfo); /* LVDS backlight off */
+			XGI_XG21SetPanelDelay(3, pVBInfo);
+		}
 
-	if ((pVBInfo->LCDInfo & EnableScalingLCD) && (modeflag & Charx8Dot)) /* for Dot8 Scaling LCD */
-		tempal = tempal ^ tempal; /* ; set to VCLK25MHz always */
+		if (pVBInfo->IF_DEF_LVDS == 0)
+			XGI_XG27BLSignalVDD(0x20, 0x00, pVBInfo); /* DVO/DVI signal off */
+	}
 
-	if (ModeNo <= 0x13)
-		return tempal;
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x01, 0xDF, 0x20);
+}
 
-	tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK;
-	return tempal;
+static void XGI_WaitDisply(struct vb_device_info *pVBInfo)
+{
+	while ((inb(pVBInfo->P3da) & 0x01))
+		break;
+
+	while (!(inb(pVBInfo->P3da) & 0x01))
+		break;
 }
 
-void XGI_GetVCLKLen(unsigned char tempal, unsigned char *di_0,
-		unsigned char *di_1, struct vb_device_info *pVBInfo)
+#if 0
+static void XGI_WaitDisplay(struct vb_device_info *pVBInfo)
 {
-	if (pVBInfo->IF_DEF_CH7007 == 1) { /* [Billy] 2007/05/16 */
-		/* VideoDebugPrint((0, "XGI_GetVCLKLen: pVBInfo->IF_DEF_CH7007==1\n")); */
-		*di_0 = (unsigned char) XGI_CH7007VCLKData[tempal].SR2B;
-		*di_1 = (unsigned char) XGI_CH7007VCLKData[tempal].SR2C;
-	} else if (pVBInfo->VBType & (VB_XGI301 | VB_XGI301B | VB_XGI302B
-			| VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
-		if ((!(pVBInfo->VBInfo & SetCRT2ToLCDA)) && (pVBInfo->SetFlag
-				& ProgrammingCRT2)) {
-			*di_0 = (unsigned char) XGI_VBVCLKData[tempal].SR2B;
-			*di_1 = XGI_VBVCLKData[tempal].SR2C;
-		}
-	} else {
-		*di_0 = XGI_VCLKData[tempal].SR2B;
-		*di_1 = XGI_VCLKData[tempal].SR2C;
-	}
+	while (!(inb(pVBInfo->P3da) & 0x01));
+	while (inb(pVBInfo->P3da) & 0x01);
 }
+#endif
 
-static void XGI_SetCRT2Offset(unsigned short ModeNo,
-		unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_AutoThreshold(struct vb_device_info *pVBInfo)
 {
-	unsigned short offset;
-	unsigned char temp;
+	if (!(pVBInfo->SetFlag & Win9xDOSMode))
+		xgifb_reg_or(pVBInfo->Part1Port, 0x01, 0x40);
+}
 
-	if (pVBInfo->VBInfo & SetInSlaveMode)
-		return;
+static void XGI_SaveCRT2Info(unsigned short ModeNo, struct vb_device_info *pVBInfo)
+{
+	unsigned short temp1, temp2;
 
-	offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	temp = (unsigned char) (offset & 0xFF);
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x07, temp);
-	temp = (unsigned char) ((offset & 0xFF00) >> 8);
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x09, temp);
-	temp = (unsigned char) (((offset >> 3) & 0xFF) + 1);
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x03, temp);
+	xgifb_reg_set(pVBInfo->P3d4, 0x34, ModeNo); /* reserve CR34 for CRT1 Mode No */
+	temp1 = (pVBInfo->VBInfo & SetInSlaveMode) >> 8;
+	temp2 = ~(SetInSlaveMode >> 8);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x31, temp2, temp1);
 }
 
-unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short temp, colordepth, modeinfo, index, infoflag,
-			ColorDepth[] = { 0x01, 0x02, 0x04 };
+	unsigned short xres, yres, modeflag, resindex;
 
-	modeinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
-	if (ModeNo <= 0x14)
-		infoflag = 0;
-	else
-		infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
+	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
+	if (ModeNo <= 0x13) {
+		xres = pVBInfo->StResInfo[resindex].HTotal;
+		yres = pVBInfo->StResInfo[resindex].VTotal;
+		/* modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; si+St_ResInfo */
+	} else {
+		xres = pVBInfo->ModeResInfo[resindex].HTotal; /* xres->ax */
+		yres = pVBInfo->ModeResInfo[resindex].VTotal; /* yres->bx */
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+St_ModeFlag */
 
-	index = (modeinfo >> 8) & 0xFF;
+		/*
+		if (pVBInfo->IF_DEF_FSTN) {
+			xres *= 2;
+			yres *= 2;
+		 } else {
+		*/
+		if (modeflag & HalfDCLK)
+			xres *= 2;
 
-	temp = pVBInfo->ScreenOffset[index];
+		if (modeflag & DoubleScanMode)
+			yres *= 2;
+		/* } */
+	}
 
-	if (infoflag & InterlaceMode)
-		temp = temp << 1;
+	if (pVBInfo->VBInfo & SetCRT2ToLCD) {
+		if (pVBInfo->IF_DEF_LVDS == 0) {
+			if (pVBInfo->LCDResInfo == Panel1600x1200) {
+				if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
+					if (yres == 1024)
+						yres = 1056;
+				}
+			}
 
-	colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo);
+			if (pVBInfo->LCDResInfo == Panel1280x1024) {
+				if (yres == 400)
+					yres = 405;
+				else if (yres == 350)
+					yres = 360;
 
-	if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
-		temp = ModeNo - 0x7C;
-		colordepth = ColorDepth[temp];
-		temp = 0x6B;
-		if (infoflag & InterlaceMode)
-			temp = temp << 1;
-		return temp * colordepth;
-	} else {
-		return temp * colordepth;
+				if (pVBInfo->LCDInfo & LCDVESATiming) {
+					if (yres == 360)
+						yres = 375;
+				}
+			}
+
+			if (pVBInfo->LCDResInfo == Panel1024x768) {
+				if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
+					if (!(pVBInfo->LCDInfo
+							& LCDNonExpanding)) {
+						if (yres == 350)
+							yres = 357;
+						else if (yres == 400)
+							yres = 420;
+						else if (yres == 480)
+							yres = 525;
+					}
+				}
+			}
+		}
+
+		if (xres == 720)
+			xres = 640;
 	}
+
+	pVBInfo->VGAHDE = xres;
+	pVBInfo->HDE = xres;
+	pVBInfo->VGAVDE = yres;
+	pVBInfo->VDE = yres;
 }
 
-static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
+static unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo)
 {
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x01, 0x3B); /* threshold high ,disable auto threshold */
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x02, ~(0x3F), 0x04); /* threshold low default 04h */
+
+	if ((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) &&
+			(pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */
+		return 1;
+
+	return 0;
 }
 
-void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempcx = 0, CRT1Index = 0, resinfo = 0;
+	unsigned short tempax, tempbx, temp1, temp2, modeflag = 0, tempcx,
+			StandTableIndex, CRT1Index;
 
-	if (ModeNo > 0x13) {
-		CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+	pVBInfo->RVBHCMAX = 1;
+	pVBInfo->RVBHCFACT = 1;
+
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+		StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
+		tempax = pVBInfo->StandTable[StandTableIndex].CRTC[0];
+		tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[6];
+		temp1 = pVBInfo->StandTable[StandTableIndex].CRTC[7];
+	} else {
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		CRT1Index
+				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
 		CRT1Index &= IndexMask;
-		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+		temp1
+				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[0];
+		temp2
+				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
+		tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
+		tempbx
+				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[8];
+		tempcx
+				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14]
+						<< 8;
+		tempcx &= 0x0100;
+		tempcx = tempcx << 2;
+		tempbx |= tempcx;
+		temp1
+				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
 	}
 
-	XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-			HwDeviceExtension, pVBInfo);
-	XGI_SetCRT2FIFO(pVBInfo);
-	/* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */
+	if (temp1 & 0x01)
+		tempbx |= 0x0100;
 
-	for (tempcx = 4; tempcx < 7; tempcx++)
-		XGINew_SetReg1(pVBInfo->Part1Port, tempcx, 0x0);
+	if (temp1 & 0x20)
+		tempbx |= 0x0200;
+	tempax += 5;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x50, 0x00);
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */
+	if (modeflag & Charx8Dot)
+		tempax *= 8;
+	else
+		tempax *= 9;
+
+	pVBInfo->VGAHT = tempax;
+	pVBInfo->HT = tempax;
+	tempbx++;
+	pVBInfo->VGAVT = tempbx;
+	pVBInfo->VT = tempbx;
 }
 
-void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_GetCRT2Data(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
-			pushbx = 0, CRT1Index = 0, modeflag, resinfo = 0;
+	unsigned short tempax = 0, tempbx, modeflag, resinfo;
 
-	if (ModeNo > 0x13) {
-		CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-		CRT1Index &= IndexMask;
+	struct XGI_LCDDataStruct *LCDPtr = NULL;
+	struct XGI_TVDataStruct *TVPtr = NULL;
+
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
+	} else {
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
 		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
 	}
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	pVBInfo->NewFlickerMode = 0;
+	pVBInfo->RVBHRS = 50;
 
-	/* bainy change table name */
-	if (modeflag & HalfDCLK) {
-		temp = (pVBInfo->VGAHT / 2 - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x08, temp);
-		temp = (((pVBInfo->VGAHT / 2 - 1) & 0xFF00) >> 8) << 4;
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
-		temp = (pVBInfo->VGAHDE / 2 + 16) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x0A, temp);
-		tempcx = ((pVBInfo->VGAHT - pVBInfo->VGAHDE) / 2) >> 2;
-		pushbx = pVBInfo->VGAHDE / 2 + 16;
-		tempcx = tempcx >> 1;
-		tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
-		tempcx += tempbx;
+	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
+		XGI_GetRAMDAC2DATA(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				pVBInfo);
+		return;
+	}
 
-		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-			tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[4];
-			tempbx |= ((pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14]
-							& 0xC0) << 2);
-			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
-			tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
-			tempcx &= 0x1F;
-			temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[15];
-			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
-			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
-		}
+	tempbx = 4;
 
-		tempbx += 4;
-		tempcx += 4;
+	if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+		LCDPtr = (struct XGI_LCDDataStruct *) XGI_GetLcdPtr(tempbx,
+				ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				pVBInfo);
 
-		if (tempcx > (pVBInfo->VGAHT / 2))
-			tempcx = pVBInfo->VGAHT / 2;
+		pVBInfo->RVBHCMAX = LCDPtr->RVBHCMAX;
+		pVBInfo->RVBHCFACT = LCDPtr->RVBHCFACT;
+		pVBInfo->VGAHT = LCDPtr->VGAHT;
+		pVBInfo->VGAVT = LCDPtr->VGAVT;
+		pVBInfo->HT = LCDPtr->LCDHT;
+		pVBInfo->VT = LCDPtr->LCDVT;
 
-		temp = tempbx & 0x00FF;
+		if (pVBInfo->LCDResInfo == Panel1024x768) {
+			tempax = 1024;
+			tempbx = 768;
 
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x0B, temp);
-	} else {
-		temp = (pVBInfo->VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x08, temp);
-		temp = (((pVBInfo->VGAHT - 1) & 0xFF00) >> 8) << 4;
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
-		temp = (pVBInfo->VGAHDE + 16) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x0A, temp);
-		tempcx = (pVBInfo->VGAHT - pVBInfo->VGAHDE) >> 2; /* cx */
-		pushbx = pVBInfo->VGAHDE + 16;
-		tempcx = tempcx >> 1;
-		tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
-		tempcx += tempbx;
+			if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
+				if (pVBInfo->VGAVDE == 357)
+					tempbx = 527;
+				else if (pVBInfo->VGAVDE == 420)
+					tempbx = 620;
+				else if (pVBInfo->VGAVDE == 525)
+					tempbx = 775;
+				else if (pVBInfo->VGAVDE == 600)
+					tempbx = 775;
+				/* else if (pVBInfo->VGAVDE==350) tempbx=560; */
+				/* else if (pVBInfo->VGAVDE==400) tempbx=640; */
+				else
+					tempbx = 768;
+			} else
+				tempbx = 768;
+		} else if (pVBInfo->LCDResInfo == Panel1024x768x75) {
+			tempax = 1024;
+			tempbx = 768;
+		} else if (pVBInfo->LCDResInfo == Panel1280x1024) {
+			tempax = 1280;
+			if (pVBInfo->VGAVDE == 360)
+				tempbx = 768;
+			else if (pVBInfo->VGAVDE == 375)
+				tempbx = 800;
+			else if (pVBInfo->VGAVDE == 405)
+				tempbx = 864;
+			else
+				tempbx = 1024;
+		} else if (pVBInfo->LCDResInfo == Panel1280x1024x75) {
+			tempax = 1280;
+			tempbx = 1024;
+		} else if (pVBInfo->LCDResInfo == Panel1280x960) {
+			tempax = 1280;
+			if (pVBInfo->VGAVDE == 350)
+				tempbx = 700;
+			else if (pVBInfo->VGAVDE == 400)
+				tempbx = 800;
+			else if (pVBInfo->VGAVDE == 1024)
+				tempbx = 960;
+			else
+				tempbx = 960;
+		} else if (pVBInfo->LCDResInfo == Panel1400x1050) {
+			tempax = 1400;
+			tempbx = 1050;
 
-		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-			tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[3];
-			tempbx |= ((pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5]
-							& 0xC0) << 2);
-			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
-			tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[4];
-			tempcx &= 0x1F;
-			temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[6];
-			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
-			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
-			tempbx += 16;
-			tempcx += 16;
+			if (pVBInfo->VGAVDE == 1024) {
+				tempax = 1280;
+				tempbx = 1024;
+			}
+		} else if (pVBInfo->LCDResInfo == Panel1600x1200) {
+			tempax = 1600;
+			tempbx = 1200; /* alan 10/14/2003 */
+			if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
+				if (pVBInfo->VGAVDE == 350)
+					tempbx = 875;
+				else if (pVBInfo->VGAVDE == 400)
+					tempbx = 1000;
+			}
 		}
 
-		if (tempcx > pVBInfo->VGAHT)
-			tempcx = pVBInfo->VGAHT;
-
-		temp = tempbx & 0x00FF;
-		XGINew_SetReg1(pVBInfo->Part1Port, 0x0B, temp);
-	}
-
-	tempax = (tempax & 0x00FF) | (tempbx & 0xFF00);
-	tempbx = pushbx;
-	tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
-	tempax |= (tempbx & 0xFF00);
-	temp = (tempax & 0xFF00) >> 8;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0C, temp);
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0D, temp);
-	tempcx = (pVBInfo->VGAVT - 1);
-	temp = tempcx & 0x00FF;
-
-	if (pVBInfo->IF_DEF_CH7005 == 1) {
-		if (pVBInfo->VBInfo & 0x0C)
-			temp--;
-	}
-
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0E, temp);
-	tempbx = pVBInfo->VGAVDE - 1;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0F, temp);
-	temp = ((tempbx & 0xFF00) << 3) >> 8;
-	temp |= ((tempcx & 0xFF00) >> 8);
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x12, temp);
-
-	tempax = pVBInfo->VGAVDE;
-	tempbx = pVBInfo->VGAVDE;
-	tempcx = pVBInfo->VGAVT;
-	tempbx = (pVBInfo->VGAVT + pVBInfo->VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
-	tempcx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
-
-	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
-		tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[10];
-		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
+		if (pVBInfo->LCDInfo & LCDNonExpanding) {
+			tempax = pVBInfo->VGAHDE;
+			tempbx = pVBInfo->VGAVDE;
+		}
 
-		if (temp & 0x04)
-			tempbx |= 0x0100;
+		pVBInfo->HDE = tempax;
+		pVBInfo->VDE = tempbx;
+		return;
+	}
 
-		if (temp & 0x080)
-			tempbx |= 0x0200;
+	if (pVBInfo->VBInfo & (SetCRT2ToTV)) {
+		tempbx = 4;
+		TVPtr = (struct XGI_TVDataStruct *) XGI_GetTVPtr(tempbx,
+				ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				pVBInfo);
 
-		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14];
+		pVBInfo->RVBHCMAX = TVPtr->RVBHCMAX;
+		pVBInfo->RVBHCFACT = TVPtr->RVBHCFACT;
+		pVBInfo->VGAHT = TVPtr->VGAHT;
+		pVBInfo->VGAVT = TVPtr->VGAVT;
+		pVBInfo->HDE = TVPtr->TVHDE;
+		pVBInfo->VDE = TVPtr->TVVDE;
+		pVBInfo->RVBHRS = TVPtr->RVBHRS;
+		pVBInfo->NewFlickerMode = TVPtr->FlickerMode;
 
-		if (temp & 0x08)
-			tempbx |= 0x0400;
+		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+			if (resinfo == 0x08)
+				pVBInfo->NewFlickerMode = 0x40;
+			else if (resinfo == 0x09)
+				pVBInfo->NewFlickerMode = 0x40;
+			else if (resinfo == 0x12)
+				pVBInfo->NewFlickerMode = 0x40;
 
-		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[11];
-		tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
-	}
+			if (pVBInfo->VGAVDE == 350)
+				pVBInfo->TVInfo |= TVSimuMode;
 
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x10, temp);
-	temp = ((tempbx & 0xFF00) >> 8) << 4;
-	temp = ((tempcx & 0x000F) | (temp));
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x11, temp);
-	tempax = 0;
+			tempax = ExtHiTVHT;
+			tempbx = ExtHiTVVT;
 
-	if (modeflag & DoubleScanMode)
-		tempax |= 0x80;
+			if (pVBInfo->VBInfo & SetInSlaveMode) {
+				if (pVBInfo->TVInfo & TVSimuMode) {
+					tempax = StHiTVHT;
+					tempbx = StHiTVVT;
 
-	if (modeflag & HalfDCLK)
-		tempax |= 0x40;
+					if (!(modeflag & Charx8Dot)) {
+						tempax = StHiTextTVHT;
+						tempbx = StHiTextTVVT;
+					}
+				}
+			}
+		} else if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
+			if (pVBInfo->TVInfo & SetYPbPrMode750p) {
+				tempax = YPbPrTV750pHT; /* Ext750pTVHT */
+				tempbx = YPbPrTV750pVT; /* Ext750pTVVT */
+			}
+
+			if (pVBInfo->TVInfo & SetYPbPrMode525p) {
+				tempax = YPbPrTV525pHT; /* Ext525pTVHT */
+				tempbx = YPbPrTV525pVT; /* Ext525pTVVT */
+			} else if (pVBInfo->TVInfo & SetYPbPrMode525i) {
+				tempax = YPbPrTV525iHT; /* Ext525iTVHT */
+				tempbx = YPbPrTV525iVT; /* Ext525iTVVT */
+				if (pVBInfo->TVInfo & NTSC1024x768)
+					tempax = NTSC1024x768HT;
+			}
+		} else {
+			tempax = PALHT;
+			tempbx = PALVT;
+			if (!(pVBInfo->TVInfo & SetPALTV)) {
+				tempax = NTSCHT;
+				tempbx = NTSCVT;
+				if (pVBInfo->TVInfo & NTSC1024x768)
+					tempax = NTSC1024x768HT;
+			}
+		}
 
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2C, ~0x0C0, tempax);
+		pVBInfo->HT = tempax;
+		pVBInfo->VT = tempbx;
+		return;
+	}
 }
 
-void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_SetCRT2VCLK(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
-			modeflag, CRT1Index;
+	unsigned char di_0, di_1, tempal;
 
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
-		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
-		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-		CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-		CRT1Index &= IndexMask;
+	tempal = XGI_GetVCLKPtr(RefreshRateTableIndex, ModeNo, ModeIdIndex,
+			pVBInfo);
+	XGI_GetVCLKLen(tempal, &di_0, &di_1, pVBInfo);
+	XGI_GetLCDVCLKPtr(&di_0, &di_1, pVBInfo);
+
+	if (pVBInfo->VBType & VB_XGI301) { /* shampoo 0129 */
+		/* 301 */
+		xgifb_reg_set(pVBInfo->Part4Port, 0x0A, 0x10);
+		xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
+		xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
+	} else { /* 301b/302b/301lv/302lv */
+		xgifb_reg_set(pVBInfo->Part4Port, 0x0A, di_0);
+		xgifb_reg_set(pVBInfo->Part4Port, 0x0B, di_1);
 	}
 
-	if (!(pVBInfo->VBInfo & SetInSlaveMode))
-		return;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x00, 0x12);
 
-	temp = 0xFF; /* set MAX HT */
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x03, temp);
-	/* if (modeflag & Charx8Dot) */
-	/*	tempcx = 0x08; */
-	/* else */
-	tempcx = 0x08;
+	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
+		xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x28);
+	else
+		xgifb_reg_or(pVBInfo->Part4Port, 0x12, 0x08);
+}
 
-	if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
-		modeflag |= Charx8Dot;
+static unsigned short XGI_GetColorDepth(unsigned short ModeNo,
+		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
+{
+	unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
+	short index;
+	unsigned short modeflag;
 
-	tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	if (modeflag & HalfDCLK)
-		tempax = tempax >> 1;
+	index = (modeflag & ModeInfoFlag) - ModeEGA;
 
-	tempax = (tempax / tempcx) - 1;
-	tempbx |= ((tempax & 0x00FF) << 8);
-	temp = tempax & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x04, temp);
+	if (index < 0)
+		index = 0;
 
-	temp = (tempbx & 0xFF00) >> 8;
+	return ColorDepth[index];
+}
 
-	if (pVBInfo->VBInfo & SetCRT2ToTV) {
-		if (!(pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)))
-			temp += 2;
+static unsigned short XGI_GetOffset(unsigned short ModeNo, unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short temp, colordepth, modeinfo, index, infoflag,
+			ColorDepth[] = { 0x01, 0x02, 0x04 };
 
-		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-			if (pVBInfo->VBType & VB_XGI301LV) {
-				if (pVBInfo->VBExtInfo == VB_YPbPr1080i) {
-					if (resinfo == 7)
-						temp -= 2;
-				}
-			} else if (resinfo == 7) {
-				temp -= 2;
-			}
-		}
-	}
+	modeinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeInfo;
+	if (ModeNo <= 0x14)
+		infoflag = 0;
+	else
+		infoflag = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x05, temp); /* 0x05 Horizontal Display Start */
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x06, 0x03); /* 0x06 Horizontal Blank end */
+	index = (modeinfo >> 8) & 0xFF;
 
-	if (!(pVBInfo->VBInfo & DisableCRT2Display)) { /* 030226 bainy */
-		if (pVBInfo->VBInfo & SetCRT2ToTV)
-			tempax = pVBInfo->VGAHT;
-		else
-			tempax = XGI_GetVGAHT2(pVBInfo);
-	}
+	temp = pVBInfo->ScreenOffset[index];
 
-	if (tempax >= pVBInfo->VGAHT)
-		tempax = pVBInfo->VGAHT;
+	if (infoflag & InterlaceMode)
+		temp = temp << 1;
 
-	if (modeflag & HalfDCLK)
-		tempax = tempax >> 1;
+	colordepth = XGI_GetColorDepth(ModeNo, ModeIdIndex, pVBInfo);
 
-	tempax = (tempax / tempcx) - 5;
-	tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-		temp = (tempbx & 0x00FF) - 1;
-		if (!(modeflag & HalfDCLK)) {
-			temp -= 6;
-			if (pVBInfo->TVInfo & TVSimuMode) {
-				temp -= 4;
-				if (ModeNo > 0x13)
-					temp -= 10;
-			}
-		}
+	if ((ModeNo >= 0x7C) && (ModeNo <= 0x7E)) {
+		temp = ModeNo - 0x7C;
+		colordepth = ColorDepth[temp];
+		temp = 0x6B;
+		if (infoflag & InterlaceMode)
+			temp = temp << 1;
+		return temp * colordepth;
 	} else {
-		/* tempcx = tempbx & 0x00FF ; */
-		tempbx = (tempbx & 0xFF00) >> 8;
-		tempcx = (tempcx + tempbx) >> 1;
-		temp = (tempcx & 0x00FF) + 2;
-
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			temp -= 1;
-			if (!(modeflag & HalfDCLK)) {
-				if ((modeflag & Charx8Dot)) {
-					temp += 4;
-					if (pVBInfo->VGAHDE >= 800)
-						temp -= 6;
-				}
-			}
-		} else {
-			if (!(modeflag & HalfDCLK)) {
-				temp -= 4;
-				if (pVBInfo->LCDResInfo != Panel1280x960) {
-					if (pVBInfo->VGAHDE >= 800) {
-						temp -= 7;
-						if (pVBInfo->ModeType
-								== ModeEGA) {
-							if (pVBInfo->VGAVDE
-									== 1024) {
-								temp += 15;
-								if (pVBInfo->LCDResInfo
-										!= Panel1280x1024) {
-									temp
-											+= 7;
-								}
-							}
-						}
-
-						if (pVBInfo->VGAHDE >= 1280) {
-							if (pVBInfo->LCDResInfo
-									!= Panel1280x960) {
-								if (pVBInfo->LCDInfo
-										& LCDNonExpanding) {
-									temp
-											+= 28;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
+		return temp * colordepth;
 	}
+}
+
+static void XGI_SetCRT2Offset(unsigned short ModeNo,
+		unsigned short ModeIdIndex,
+		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short offset;
+	unsigned char temp;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x07, temp); /* 0x07 Horizontal Retrace Start */
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x08, 0); /* 0x08 Horizontal Retrace End */
+	if (pVBInfo->VBInfo & SetInSlaveMode)
+		return;
 
-	if (pVBInfo->VBInfo & SetCRT2ToTV) {
-		if (pVBInfo->TVInfo & TVSimuMode) {
-			if ((ModeNo == 0x06) || (ModeNo == 0x10) || (ModeNo
-					== 0x11) || (ModeNo == 0x13) || (ModeNo
-					== 0x0F)) {
-				XGINew_SetReg1(pVBInfo->Part1Port, 0x07, 0x5b);
-				XGINew_SetReg1(pVBInfo->Part1Port, 0x08, 0x03);
-			}
+	offset = XGI_GetOffset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+			HwDeviceExtension, pVBInfo);
+	temp = (unsigned char) (offset & 0xFF);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp);
+	temp = (unsigned char) ((offset & 0xFF00) >> 8);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x09, temp);
+	temp = (unsigned char) (((offset >> 3) & 0xFF) + 1);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
+}
 
-			if ((ModeNo == 0x00) || (ModeNo == 0x01)) {
-				if (pVBInfo->TVInfo & SetNTSCTV) {
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x07, 0x2A);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x08, 0x61);
-				} else {
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x07, 0x2A);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x08, 0x41);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x0C, 0xF0);
-				}
-			}
+static void XGI_SetCRT2FIFO(struct vb_device_info *pVBInfo)
+{
+	xgifb_reg_set(pVBInfo->Part1Port, 0x01, 0x3B); /* threshold high ,disable auto threshold */
+	xgifb_reg_and_or(pVBInfo->Part1Port, 0x02, ~(0x3F), 0x04); /* threshold low default 04h */
+}
 
-			if ((ModeNo == 0x02) || (ModeNo == 0x03) || (ModeNo
-					== 0x07)) {
-				if (pVBInfo->TVInfo & SetNTSCTV) {
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x07, 0x54);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x08, 0x00);
-				} else {
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x07, 0x55);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x08, 0x00);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x0C, 0xF0);
-				}
-			}
+static void XGI_PreSetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempcx = 0, CRT1Index = 0, resinfo = 0;
 
-			if ((ModeNo == 0x04) || (ModeNo == 0x05) || (ModeNo
-					== 0x0D) || (ModeNo == 0x50)) {
-				if (pVBInfo->TVInfo & SetNTSCTV) {
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x07, 0x30);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x08, 0x03);
-				} else {
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x07, 0x2f);
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x08, 0x02);
-				}
-			}
-		}
+	if (ModeNo > 0x13) {
+		CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+		CRT1Index &= IndexMask;
+		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
 	}
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x18, 0x03); /* 0x18 SR0B */
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0xF0, 0x00);
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x09, 0xFF); /* 0x09 Set Max VT */
+	XGI_SetCRT2Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+			HwDeviceExtension, pVBInfo);
+	XGI_SetCRT2FIFO(pVBInfo);
+	/* XGI_SetCRT2Sync(ModeNo,RefreshRateTableIndex); */
 
-	tempbx = pVBInfo->VGAVT;
-	push1 = tempbx;
-	tempcx = 0x121;
-	tempbx = pVBInfo->VGAVDE; /* 0x0E Virtical Display End */
+	for (tempcx = 4; tempcx < 7; tempcx++)
+		xgifb_reg_set(pVBInfo->Part1Port, tempcx, 0x0);
 
-	if (tempbx == 357)
-		tempbx = 350;
-	if (tempbx == 360)
-		tempbx = 350;
-	if (tempbx == 375)
-		tempbx = 350;
-	if (tempbx == 405)
-		tempbx = 400;
-	if (tempbx == 525)
-		tempbx = 480;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x50, 0x00);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x02, 0x44); /* temp 0206 */
+}
 
-	push2 = tempbx;
+static void XGI_SetGroup1(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short RefreshRateTableIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short temp = 0, tempax = 0, tempbx = 0, tempcx = 0,
+			pushbx = 0, CRT1Index = 0, modeflag, resinfo = 0;
 
-	if (pVBInfo->VBInfo & SetCRT2ToLCD) {
-		if (pVBInfo->LCDResInfo == Panel1024x768) {
-			if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
-				if (tempbx == 350)
-					tempbx += 5;
-				if (tempbx == 480)
-					tempbx += 5;
-			}
-		}
+	if (ModeNo > 0x13) {
+		CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+		CRT1Index &= IndexMask;
+		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
 	}
-	tempbx--;
-	temp = tempbx & 0x00FF;
-	tempbx--;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x10, temp); /* 0x10 vertical Blank Start */
-	tempbx = push2;
-	tempbx--;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0E, temp);
 
-	if (tempbx & 0x0100)
-		tempcx |= 0x0002;
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	tempax = 0x000B;
+	/* bainy change table name */
+	if (modeflag & HalfDCLK) {
+		temp = (pVBInfo->VGAHT / 2 - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+		xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
+		temp = (((pVBInfo->VGAHT / 2 - 1) & 0xFF00) >> 8) << 4;
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
+		temp = (pVBInfo->VGAHDE / 2 + 16) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+		xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
+		tempcx = ((pVBInfo->VGAHT - pVBInfo->VGAHDE) / 2) >> 2;
+		pushbx = pVBInfo->VGAHDE / 2 + 16;
+		tempcx = tempcx >> 1;
+		tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
+		tempcx += tempbx;
 
-	if (modeflag & DoubleScanMode)
-		tempax |= 0x08000;
+		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
+			tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[4];
+			tempbx |= ((pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14]
+							& 0xC0) << 2);
+			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
+			tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
+			tempcx &= 0x1F;
+			temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[15];
+			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
+			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
+		}
 
-	if (tempbx & 0x0200)
-		tempcx |= 0x0040;
+		tempbx += 4;
+		tempcx += 4;
 
-	temp = (tempax & 0xFF00) >> 8;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0B, temp);
+		if (tempcx > (pVBInfo->VGAHT / 2))
+			tempcx = pVBInfo->VGAHT / 2;
 
-	if (tempbx & 0x0400)
-		tempcx |= 0x0600;
+		temp = tempbx & 0x00FF;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x11, 0x00); /* 0x11 Vertival Blank End */
+		xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
+	} else {
+		temp = (pVBInfo->VGAHT - 1) & 0x0FF; /* BTVGA2HT 0x08,0x09 */
+		xgifb_reg_set(pVBInfo->Part1Port, 0x08, temp);
+		temp = (((pVBInfo->VGAHT - 1) & 0xFF00) >> 8) << 4;
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x09, ~0x0F0, temp);
+		temp = (pVBInfo->VGAHDE + 16) & 0x0FF; /* BTVGA2HDEE 0x0A,0x0C */
+		xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp);
+		tempcx = (pVBInfo->VGAHT - pVBInfo->VGAHDE) >> 2; /* cx */
+		pushbx = pVBInfo->VGAHDE + 16;
+		tempcx = tempcx >> 1;
+		tempbx = pushbx + tempcx; /* bx BTVGA@HRS 0x0B,0x0C */
+		tempcx += tempbx;
 
-	tempax = push1;
-	tempax -= tempbx; /* 0x0C Vertical Retrace Start */
-	tempax = tempax >> 2;
-	push1 = tempax; /* push ax */
+		if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
+			tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[3];
+			tempbx |= ((pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5]
+							& 0xC0) << 2);
+			tempbx = (tempbx - 3) << 3; /* (VGAHRS-3)*8 */
+			tempcx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[4];
+			tempcx &= 0x1F;
+			temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[6];
+			temp = (temp & 0x04) << (5 - 2); /* VGAHRE D[5] */
+			tempcx = ((tempcx | temp) - 3) << 3; /* (VGAHRE-3)*8 */
+			tempbx += 16;
+			tempcx += 16;
+		}
 
-	if (resinfo != 0x09) {
-		tempax = tempax << 1;
-		tempbx += tempax;
-	}
+		if (tempcx > pVBInfo->VGAHT)
+			tempcx = pVBInfo->VGAHT;
 
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-		if (pVBInfo->VBType & VB_XGI301LV) {
-			if (pVBInfo->TVInfo & SetYPbPrMode1080i) {
-				tempbx -= 10;
-			} else {
-				if (pVBInfo->TVInfo & TVSimuMode) {
-					if (pVBInfo->TVInfo & SetPALTV) {
-						if (pVBInfo->VBType
-								& VB_XGI301LV) {
-							if (!(pVBInfo->TVInfo
-									& (SetYPbPrMode525p
-											| SetYPbPrMode750p
-											| SetYPbPrMode1080i)))
-								tempbx += 40;
-						} else {
-							tempbx += 40;
-						}
-					}
-				}
-			}
-		} else {
-			tempbx -= 10;
-		}
-	} else {
-		if (pVBInfo->TVInfo & TVSimuMode) {
-			if (pVBInfo->TVInfo & SetPALTV) {
-				if (pVBInfo->VBType & VB_XGI301LV) {
-					if (!(pVBInfo->TVInfo
-							& (SetYPbPrMode525p
-									| SetYPbPrMode750p
-									| SetYPbPrMode1080i)))
-						tempbx += 40;
-				} else {
-					tempbx += 40;
-				}
-			}
-		}
+		temp = tempbx & 0x00FF;
+		xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
 	}
-	tempax = push1;
-	tempax = tempax >> 2;
-	tempax++;
-	tempax += tempbx;
-	push1 = tempax; /* push ax */
 
-	if ((pVBInfo->TVInfo & SetPALTV)) {
-		if (tempbx <= 513) {
-			if (tempax >= 513)
-				tempbx = 513;
-		}
+	tempax = (tempax & 0x00FF) | (tempbx & 0xFF00);
+	tempbx = pushbx;
+	tempbx = (tempbx & 0x00FF) | ((tempbx & 0xFF00) << 4);
+	tempax |= (tempbx & 0xFF00);
+	temp = (tempax & 0xFF00) >> 8;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp);
+	tempcx = (pVBInfo->VGAVT - 1);
+	temp = tempcx & 0x00FF;
+
+	if (pVBInfo->IF_DEF_CH7005 == 1) {
+		if (pVBInfo->VBInfo & 0x0C)
+			temp--;
 	}
 
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
+	tempbx = pVBInfo->VGAVDE - 1;
 	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0C, temp);
-	tempbx--;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x10, temp);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0F, temp);
+	temp = ((tempbx & 0xFF00) << 3) >> 8;
+	temp |= ((tempcx & 0xFF00) >> 8);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x12, temp);
 
-	if (tempbx & 0x0100)
-		tempcx |= 0x0008;
+	tempax = pVBInfo->VGAVDE;
+	tempbx = pVBInfo->VGAVDE;
+	tempcx = pVBInfo->VGAVT;
+	tempbx = (pVBInfo->VGAVT + pVBInfo->VGAVDE) >> 1; /* BTVGA2VRS 0x10,0x11 */
+	tempcx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) >> 4) + tempbx + 1; /* BTVGA2VRE 0x11 */
 
-	if (tempbx & 0x0200)
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x0B, 0x0FF, 0x20);
+	if (pVBInfo->VBInfo & SetCRT2ToRAMDAC) {
+		tempbx = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[10];
+		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
+
+		if (temp & 0x04)
+			tempbx |= 0x0100;
 
-	tempbx++;
+		if (temp & 0x080)
+			tempbx |= 0x0200;
 
-	if (tempbx & 0x0100)
-		tempcx |= 0x0004;
+		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14];
 
-	if (tempbx & 0x0200)
-		tempcx |= 0x0080;
+		if (temp & 0x08)
+			tempbx |= 0x0400;
 
-	if (tempbx & 0x0400)
-		tempcx |= 0x0C00;
+		temp = pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[11];
+		tempcx = (tempcx & 0xFF00) | (temp & 0x00FF);
+	}
 
-	tempbx = push1; /* pop ax */
 	temp = tempbx & 0x00FF;
-	temp &= 0x0F;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0D, temp); /* 0x0D vertical Retrace End */
-
-	if (tempbx & 0x0010)
-		tempcx |= 0x2000;
-
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0A, temp); /* 0x0A CR07 */
-	temp = (tempcx & 0x0FF00) >> 8;
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x17, temp); /* 0x17 SR0A */
-	tempax = modeflag;
-	temp = (tempax & 0xFF00) >> 8;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
+	temp = ((tempbx & 0xFF00) >> 8) << 4;
+	temp = ((tempcx & 0x000F) | (temp));
+	xgifb_reg_set(pVBInfo->Part1Port, 0x11, temp);
+	tempax = 0;
 
-	temp = (temp >> 1) & 0x09;
+	if (modeflag & DoubleScanMode)
+		tempax |= 0x80;
 
-	if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
-		temp |= 0x01;
+	if (modeflag & HalfDCLK)
+		tempax |= 0x40;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x16, temp); /* 0x16 SR01 */
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x0F, 0); /* 0x0F CR14 */
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x12, 0); /* 0x12 CR17 */
+	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2C, ~0x0C0, tempax);
+}
 
-	if (pVBInfo->LCDInfo & LCDRGB18Bit)
-		temp = 0x80;
-	else
-		temp = 0x00;
+static unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
+{
+	unsigned long tempax, tempbx;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x1A, temp); /* 0x1A SR0E */
+	tempbx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) * pVBInfo->RVBHCMAX)
+			& 0xFFFF;
+	tempax = (pVBInfo->VT - pVBInfo->VDE) * pVBInfo->RVBHCFACT;
+	tempax = (tempax * pVBInfo->HT) / tempbx;
 
-	return;
+	return (unsigned short) tempax;
 }
 
-void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
+static void XGI_SetLockRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2,
-			modeflag, resinfo, crt2crtc;
-	unsigned char *TimingPoint;
-
-	unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
+	unsigned short push1, push2, tempax, tempbx = 0, tempcx, temp, resinfo,
+			modeflag, CRT1Index;
 
 	if (ModeNo <= 0x13) {
 		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
 		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
-		crt2crtc = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
 	} else {
 		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
 		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-		crt2crtc
-				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-	}
-
-	tempax = 0;
-
-	if (!(pVBInfo->VBInfo & SetCRT2ToAVIDEO))
-		tempax |= 0x0800;
-
-	if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
-		tempax |= 0x0400;
-
-	if (pVBInfo->VBInfo & SetCRT2ToSCART)
-		tempax |= 0x0200;
-
-	if (!(pVBInfo->TVInfo & SetPALTV))
-		tempax |= 0x1000;
-
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
-		tempax |= 0x0100;
-
-	if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))
-		tempax &= 0xfe00;
-
-	tempax = (tempax & 0xff00) >> 8;
-
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x0, tempax);
-	TimingPoint = pVBInfo->NTSCTiming;
-
-	if (pVBInfo->TVInfo & SetPALTV)
-		TimingPoint = pVBInfo->PALTiming;
-
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-		TimingPoint = pVBInfo->HiTVExtTiming;
-
-		if (pVBInfo->VBInfo & SetInSlaveMode)
-			TimingPoint = pVBInfo->HiTVSt2Timing;
-
-		if (pVBInfo->SetFlag & TVSimuMode)
-			TimingPoint = pVBInfo->HiTVSt1Timing;
-
-		if (!(modeflag & Charx8Dot))
-			TimingPoint = pVBInfo->HiTVTextTiming;
-	}
-
-	if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
-		if (pVBInfo->TVInfo & SetYPbPrMode525i)
-			TimingPoint = pVBInfo->YPbPr525iTiming;
-
-		if (pVBInfo->TVInfo & SetYPbPrMode525p)
-			TimingPoint = pVBInfo->YPbPr525pTiming;
-
-		if (pVBInfo->TVInfo & SetYPbPrMode750p)
-			TimingPoint = pVBInfo->YPbPr750pTiming;
+		CRT1Index = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+		CRT1Index &= IndexMask;
 	}
 
-	for (i = 0x01, j = 0; i <= 0x2D; i++, j++)
-		XGINew_SetReg1(pVBInfo->Part2Port, i, TimingPoint[j]);
-
-	for (i = 0x39; i <= 0x45; i++, j++)
-		XGINew_SetReg1(pVBInfo->Part2Port, i, TimingPoint[j]); /* di->temp2[j] */
+	if (!(pVBInfo->VBInfo & SetInSlaveMode))
+		return;
 
-	if (pVBInfo->VBInfo & SetCRT2ToTV)
-		XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x3A, 0x1F, 0x00);
+	temp = 0xFF; /* set MAX HT */
+	xgifb_reg_set(pVBInfo->Part1Port, 0x03, temp);
+	/* if (modeflag & Charx8Dot) */
+	/*	tempcx = 0x08; */
+	/* else */
+	tempcx = 0x08;
 
-	temp = pVBInfo->NewFlickerMode;
-	temp &= 0x80;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x0A, 0xFF, temp);
+	if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
+		modeflag |= Charx8Dot;
 
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
-		tempax = 950;
+	tempax = pVBInfo->VGAHDE; /* 0x04 Horizontal Display End */
 
-	if (pVBInfo->TVInfo & SetPALTV)
-		tempax = 520;
-	else
-		tempax = 440;
+	if (modeflag & HalfDCLK)
+		tempax = tempax >> 1;
 
-	if (pVBInfo->VDE <= tempax) {
-		tempax -= pVBInfo->VDE;
-		tempax = tempax >> 2;
-		tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
-		push1 = tempax;
-		temp = (tempax & 0xFF00) >> 8;
-		temp += (unsigned short) TimingPoint[0];
+	tempax = (tempax / tempcx) - 1;
+	tempbx |= ((tempax & 0x00FF) << 8);
+	temp = tempax & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x04, temp);
 
-		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)) {
-			if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
-					| SetCRT2ToSVIDEO | SetCRT2ToSCART
-					| SetCRT2ToYPbPr)) {
-				tempcx = pVBInfo->VGAHDE;
-				if (tempcx >= 1024) {
-					temp = 0x17; /* NTSC */
-					if (pVBInfo->TVInfo & SetPALTV)
-						temp = 0x19; /* PAL */
-				}
-			}
-		}
+	temp = (tempbx & 0xFF00) >> 8;
 
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x01, temp);
-		tempax = push1;
-		temp = (tempax & 0xFF00) >> 8;
-		temp += TimingPoint[1];
+	if (pVBInfo->VBInfo & SetCRT2ToTV) {
+		if (!(pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)))
+			temp += 2;
 
-		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)) {
-			if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO
-					| SetCRT2ToSVIDEO | SetCRT2ToSCART
-					| SetCRT2ToYPbPr))) {
-				tempcx = pVBInfo->VGAHDE;
-				if (tempcx >= 1024) {
-					temp = 0x1D; /* NTSC */
-					if (pVBInfo->TVInfo & SetPALTV)
-						temp = 0x52; /* PAL */
+		if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+			if (pVBInfo->VBType & VB_XGI301LV) {
+				if (pVBInfo->VBExtInfo == VB_YPbPr1080i) {
+					if (resinfo == 7)
+						temp -= 2;
 				}
+			} else if (resinfo == 7) {
+				temp -= 2;
 			}
 		}
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x02, temp);
 	}
 
-	/* 301b */
-	tempcx = pVBInfo->HT;
-
-	if (XGI_IsLCDDualLink(pVBInfo))
-		tempcx = tempcx >> 1;
-
-	tempcx -= 2;
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x1B, temp);
-
-	temp = (tempcx & 0xFF00) >> 8;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1D, ~0x0F, temp);
-
-	tempcx = pVBInfo->HT >> 1;
-	push1 = tempcx; /* push cx */
-	tempcx += 7;
-
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
-		tempcx -= 4;
-
-	temp = tempcx & 0x00FF;
-	temp = temp << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x22, 0x0F, temp);
-
-	tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
-	tempbx += tempcx;
-	push2 = tempbx;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x24, temp);
-	temp = (tempbx & 0xFF00) >> 8;
-	temp = temp << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x25, 0x0F, temp);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x05, temp); /* 0x05 Horizontal Display Start */
+	xgifb_reg_set(pVBInfo->Part1Port, 0x06, 0x03); /* 0x06 Horizontal Blank end */
 
-	tempbx = push2;
-	tempbx = tempbx + 8;
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-		tempbx = tempbx - 4;
-		tempcx = tempbx;
+	if (!(pVBInfo->VBInfo & DisableCRT2Display)) { /* 030226 bainy */
+		if (pVBInfo->VBInfo & SetCRT2ToTV)
+			tempax = pVBInfo->VGAHT;
+		else
+			tempax = XGI_GetVGAHT2(pVBInfo);
 	}
 
-	temp = (tempbx & 0x00FF) << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x29, 0x0F, temp);
-
-	j += 2;
-	tempcx += (TimingPoint[j] | ((TimingPoint[j + 1]) << 8));
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x27, temp);
-	temp = ((tempcx & 0xFF00) >> 8) << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x28, 0x0F, temp);
-
-	tempcx += 8;
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
-		tempcx -= 4;
+	if (tempax >= pVBInfo->VGAHT)
+		tempax = pVBInfo->VGAHT;
 
-	temp = tempcx & 0xFF;
-	temp = temp << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x2A, 0x0F, temp);
+	if (modeflag & HalfDCLK)
+		tempax = tempax >> 1;
 
-	tempcx = push1; /* pop cx */
-	j += 2;
-	temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
-	tempcx -= temp;
-	temp = tempcx & 0x00FF;
-	temp = temp << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x2D, 0x0F, temp);
+	tempax = (tempax / tempcx) - 5;
+	tempcx = tempax; /* 20030401 0x07 horizontal Retrace Start */
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+		temp = (tempbx & 0x00FF) - 1;
+		if (!(modeflag & HalfDCLK)) {
+			temp -= 6;
+			if (pVBInfo->TVInfo & TVSimuMode) {
+				temp -= 4;
+				if (ModeNo > 0x13)
+					temp -= 10;
+			}
+		}
+	} else {
+		/* tempcx = tempbx & 0x00FF ; */
+		tempbx = (tempbx & 0xFF00) >> 8;
+		tempcx = (tempcx + tempbx) >> 1;
+		temp = (tempcx & 0x00FF) + 2;
 
-	tempcx -= 11;
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			temp -= 1;
+			if (!(modeflag & HalfDCLK)) {
+				if ((modeflag & Charx8Dot)) {
+					temp += 4;
+					if (pVBInfo->VGAHDE >= 800)
+						temp -= 6;
+				}
+			}
+		} else {
+			if (!(modeflag & HalfDCLK)) {
+				temp -= 4;
+				if (pVBInfo->LCDResInfo != Panel1280x960) {
+					if (pVBInfo->VGAHDE >= 800) {
+						temp -= 7;
+						if (pVBInfo->ModeType
+								== ModeEGA) {
+							if (pVBInfo->VGAVDE
+									== 1024) {
+								temp += 15;
+								if (pVBInfo->LCDResInfo
+										!= Panel1280x1024) {
+									temp
+											+= 7;
+								}
+							}
+						}
 
-	if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
-		tempax = XGI_GetVGAHT2(pVBInfo);
-		tempcx = tempax - 1;
+						if (pVBInfo->VGAHDE >= 1280) {
+							if (pVBInfo->LCDResInfo
+									!= Panel1280x960) {
+								if (pVBInfo->LCDInfo
+										& LCDNonExpanding) {
+									temp
+											+= 28;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
 	}
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x2E, temp);
-
-	tempbx = pVBInfo->VDE;
 
-	if (pVBInfo->VGAVDE == 360)
-		tempbx = 746;
-	if (pVBInfo->VGAVDE == 375)
-		tempbx = 746;
-	if (pVBInfo->VGAVDE == 405)
-		tempbx = 853;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x07, temp); /* 0x07 Horizontal Retrace Start */
+	xgifb_reg_set(pVBInfo->Part1Port, 0x08, 0); /* 0x08 Horizontal Retrace End */
 
 	if (pVBInfo->VBInfo & SetCRT2ToTV) {
-		if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
-			if (!(pVBInfo->TVInfo & (SetYPbPrMode525p
-					| SetYPbPrMode750p)))
-				tempbx = tempbx >> 1;
-		} else
-			tempbx = tempbx >> 1;
-	}
+		if (pVBInfo->TVInfo & TVSimuMode) {
+			if ((ModeNo == 0x06) || (ModeNo == 0x10) || (ModeNo
+					== 0x11) || (ModeNo == 0x13) || (ModeNo
+					== 0x0F)) {
+				xgifb_reg_set(pVBInfo->Part1Port, 0x07, 0x5b);
+				xgifb_reg_set(pVBInfo->Part1Port, 0x08, 0x03);
+			}
 
-	tempbx -= 2;
-	temp = tempbx & 0x00FF;
+			if ((ModeNo == 0x00) || (ModeNo == 0x01)) {
+				if (pVBInfo->TVInfo & SetNTSCTV) {
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x07, 0x2A);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x08, 0x61);
+				} else {
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x07, 0x2A);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x08, 0x41);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x0C, 0xF0);
+				}
+			}
 
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-		if (pVBInfo->VBType & VB_XGI301LV) {
-			if (pVBInfo->TVInfo & SetYPbPrMode1080i) {
-				if (pVBInfo->VBInfo & SetInSlaveMode) {
-					if (ModeNo == 0x2f)
-						temp += 1;
+			if ((ModeNo == 0x02) || (ModeNo == 0x03) || (ModeNo
+					== 0x07)) {
+				if (pVBInfo->TVInfo & SetNTSCTV) {
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x07, 0x54);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x08, 0x00);
+				} else {
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x07, 0x55);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x08, 0x00);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x0C, 0xF0);
 				}
 			}
-		} else {
-			if (pVBInfo->VBInfo & SetInSlaveMode) {
-				if (ModeNo == 0x2f)
-					temp += 1;
+
+			if ((ModeNo == 0x04) || (ModeNo == 0x05) || (ModeNo
+					== 0x0D) || (ModeNo == 0x50)) {
+				if (pVBInfo->TVInfo & SetNTSCTV) {
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x07, 0x30);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x08, 0x03);
+				} else {
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x07, 0x2f);
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x08, 0x02);
+				}
 			}
 		}
 	}
 
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x2F, temp);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x18, 0x03); /* 0x18 SR0B */
+	xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0xF0, 0x00);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x09, 0xFF); /* 0x09 Set Max VT */
 
-	temp = (tempcx & 0xFF00) >> 8;
-	temp |= ((tempbx & 0xFF00) >> 8) << 6;
+	tempbx = pVBInfo->VGAVT;
+	push1 = tempbx;
+	tempcx = 0x121;
+	tempbx = pVBInfo->VGAVDE; /* 0x0E Virtical Display End */
 
-	if (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)) {
-		if (pVBInfo->VBType & VB_XGI301LV) {
-			if (pVBInfo->TVInfo & SetYPbPrMode1080i) {
-				temp |= 0x10;
+	if (tempbx == 357)
+		tempbx = 350;
+	if (tempbx == 360)
+		tempbx = 350;
+	if (tempbx == 375)
+		tempbx = 350;
+	if (tempbx == 405)
+		tempbx = 400;
+	if (tempbx == 525)
+		tempbx = 480;
 
-				if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
-					temp |= 0x20;
+	push2 = tempbx;
+
+	if (pVBInfo->VBInfo & SetCRT2ToLCD) {
+		if (pVBInfo->LCDResInfo == Panel1024x768) {
+			if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
+				if (tempbx == 350)
+					tempbx += 5;
+				if (tempbx == 480)
+					tempbx += 5;
 			}
-		} else {
-			temp |= 0x10;
-			if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
-				temp |= 0x20;
 		}
 	}
+	tempbx--;
+	temp = tempbx & 0x00FF;
+	tempbx--;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp); /* 0x10 vertical Blank Start */
+	tempbx = push2;
+	tempbx--;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0E, temp);
 
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x30, temp);
+	if (tempbx & 0x0100)
+		tempcx |= 0x0002;
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) { /* TV gatingno */
-		tempbx = pVBInfo->VDE;
-		tempcx = tempbx - 2;
+	tempax = 0x000B;
 
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			if (!(pVBInfo->TVInfo & (SetYPbPrMode525p
-					| SetYPbPrMode750p)))
-				tempbx = tempbx >> 1;
-		}
+	if (modeflag & DoubleScanMode)
+		tempax |= 0x08000;
 
-		if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
-			temp = 0;
-			if (tempcx & 0x0400)
-				temp |= 0x20;
+	if (tempbx & 0x0200)
+		tempcx |= 0x0040;
 
-			if (tempbx & 0x0400)
-				temp |= 0x40;
+	temp = (tempax & 0xFF00) >> 8;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0B, temp);
 
-			XGINew_SetReg1(pVBInfo->Part4Port, 0x10, temp);
-		}
+	if (tempbx & 0x0400)
+		tempcx |= 0x0600;
 
-		temp = (((tempbx - 3) & 0x0300) >> 8) << 5;
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x46, temp);
-		temp = (tempbx - 3) & 0x00FF;
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x47, temp);
-	}
+	xgifb_reg_set(pVBInfo->Part1Port, 0x11, 0x00); /* 0x11 Vertival Blank End */
 
-	tempbx = tempbx & 0x00FF;
+	tempax = push1;
+	tempax -= tempbx; /* 0x0C Vertical Retrace Start */
+	tempax = tempax >> 2;
+	push1 = tempax; /* push ax */
 
-	if (!(modeflag & HalfDCLK)) {
-		tempcx = pVBInfo->VGAHDE;
-		if (tempcx >= pVBInfo->HDE) {
-			tempbx |= 0x2000;
-			tempax &= 0x00FF;
-		}
+	if (resinfo != 0x09) {
+		tempax = tempax << 1;
+		tempbx += tempax;
 	}
 
-	tempcx = 0x0101;
-
-	if (pVBInfo->VBInfo & SetCRT2ToTV) { /*301b*/
-		if (pVBInfo->VGAHDE >= 1024) {
-			tempcx = 0x1920;
-			if (pVBInfo->VGAHDE >= 1280) {
-				tempcx = 0x1420;
-				tempbx = tempbx & 0xDFFF;
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+		if (pVBInfo->VBType & VB_XGI301LV) {
+			if (pVBInfo->TVInfo & SetYPbPrMode1080i) {
+				tempbx -= 10;
+			} else {
+				if (pVBInfo->TVInfo & TVSimuMode) {
+					if (pVBInfo->TVInfo & SetPALTV) {
+						if (pVBInfo->VBType
+								& VB_XGI301LV) {
+							if (!(pVBInfo->TVInfo
+									& (SetYPbPrMode525p
+											| SetYPbPrMode750p
+											| SetYPbPrMode1080i)))
+								tempbx += 40;
+						} else {
+							tempbx += 40;
+						}
+					}
+				}
 			}
+		} else {
+			tempbx -= 10;
 		}
-	}
-
-	if (!(tempbx & 0x2000)) {
-		if (modeflag & HalfDCLK)
-			tempcx = (tempcx & 0xFF00) | ((tempcx & 0x00FF) << 1);
-
-		push1 = tempbx;
-		tempeax = pVBInfo->VGAHDE;
-		tempebx = (tempcx & 0xFF00) >> 8;
-		longtemp = tempeax * tempebx;
-		tempecx = tempcx & 0x00FF;
-		longtemp = longtemp / tempecx;
-
-		/* 301b */
-		tempecx = 8 * 1024;
-
-		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)) {
-			tempecx = tempecx * 8;
+	} else {
+		if (pVBInfo->TVInfo & TVSimuMode) {
+			if (pVBInfo->TVInfo & SetPALTV) {
+				if (pVBInfo->VBType & VB_XGI301LV) {
+					if (!(pVBInfo->TVInfo
+							& (SetYPbPrMode525p
+									| SetYPbPrMode750p
+									| SetYPbPrMode1080i)))
+						tempbx += 40;
+				} else {
+					tempbx += 40;
+				}
+			}
 		}
+	}
+	tempax = push1;
+	tempax = tempax >> 2;
+	tempax++;
+	tempax += tempbx;
+	push1 = tempax; /* push ax */
 
-		longtemp = longtemp * tempecx;
-		tempecx = pVBInfo->HDE;
-		temp2 = longtemp % tempecx;
-		tempeax = longtemp / tempecx;
-		if (temp2 != 0)
-			tempeax += 1;
-
-		tempax = (unsigned short) tempeax;
-
-		/* 301b */
-		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)) {
-			tempcx = ((tempax & 0xFF00) >> 5) >> 8;
+	if ((pVBInfo->TVInfo & SetPALTV)) {
+		if (tempbx <= 513) {
+			if (tempax >= 513)
+				tempbx = 513;
 		}
-		/* end 301b */
-
-		tempbx = push1;
-		tempbx = (unsigned short) (((tempeax & 0x0000FF00) & 0x1F00)
-				| (tempbx & 0x00FF));
-		tempax = (unsigned short) (((tempeax & 0x000000FF) << 8)
-				| (tempax & 0x00FF));
-		temp = (tempax & 0xFF00) >> 8;
-	} else {
-		temp = (tempax & 0x00FF) >> 8;
 	}
 
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x44, temp);
-	temp = (tempbx & 0xFF00) >> 8;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x45, ~0x03F, temp);
-	temp = tempcx & 0x00FF;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0C, temp);
+	tempbx--;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x10, temp);
 
-	if (tempbx & 0x2000)
-		temp = 0;
+	if (tempbx & 0x0100)
+		tempcx |= 0x0008;
 
-	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
-		temp |= 0x18;
+	if (tempbx & 0x0200)
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x0B, 0x0FF, 0x20);
 
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x46, ~0x1F, temp);
-	if (pVBInfo->TVInfo & SetPALTV) {
-		tempbx = 0x0382;
-		tempcx = 0x007e;
-	} else {
-		tempbx = 0x0369;
-		tempcx = 0x0061;
-	}
+	tempbx++;
 
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x4b, temp);
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x4c, temp);
+	if (tempbx & 0x0100)
+		tempcx |= 0x0004;
 
-	temp = ((tempcx & 0xFF00) >> 8) & 0x03;
-	temp = temp << 2;
-	temp |= ((tempbx & 0xFF00) >> 8) & 0x03;
+	if (tempbx & 0x0200)
+		tempcx |= 0x0080;
 
-	if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
-		temp |= 0x10;
+	if (tempbx & 0x0400)
+		tempcx |= 0x0C00;
 
-		if (pVBInfo->TVInfo & SetYPbPrMode525p)
-			temp |= 0x20;
+	tempbx = push1; /* pop ax */
+	temp = tempbx & 0x00FF;
+	temp &= 0x0F;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0D, temp); /* 0x0D vertical Retrace End */
 
-		if (pVBInfo->TVInfo & SetYPbPrMode750p)
-			temp |= 0x60;
-	}
+	if (tempbx & 0x0010)
+		tempcx |= 0x2000;
 
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x4d, temp);
-	temp = XGINew_GetReg1(pVBInfo->Part2Port, 0x43); /* 301b change */
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x43, (unsigned short) (temp - 3));
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0A, temp); /* 0x0A CR07 */
+	temp = (tempcx & 0x0FF00) >> 8;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x17, temp); /* 0x17 SR0A */
+	tempax = modeflag;
+	temp = (tempax & 0xFF00) >> 8;
 
-	if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))) {
-		if (pVBInfo->TVInfo & NTSC1024x768) {
-			TimingPoint = XGI_NTSC1024AdjTime;
-			for (i = 0x1c, j = 0; i <= 0x30; i++, j++) {
-				XGINew_SetReg1(pVBInfo->Part2Port, i,
-						TimingPoint[j]);
-			}
-			XGINew_SetReg1(pVBInfo->Part2Port, 0x43, 0x72);
-		}
-	}
+	temp = (temp >> 1) & 0x09;
 
-	/* [ycchen] 01/14/03 Modify for 301C PALM Support */
-	if (pVBInfo->VBType & VB_XGI301C) {
-		if (pVBInfo->TVInfo & SetPALMTV)
-			XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x4E, ~0x08,
-					0x08); /* PALM Mode */
-	}
+	if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
+		temp |= 0x01;
 
-	if (pVBInfo->TVInfo & SetPALMTV) {
-		tempax = (unsigned char) XGINew_GetReg1(pVBInfo->Part2Port,
-				0x01);
-		tempax--;
-		XGINew_SetRegAND(pVBInfo->Part2Port, 0x01, tempax);
+	xgifb_reg_set(pVBInfo->Part1Port, 0x16, temp); /* 0x16 SR01 */
+	xgifb_reg_set(pVBInfo->Part1Port, 0x0F, 0); /* 0x0F CR14 */
+	xgifb_reg_set(pVBInfo->Part1Port, 0x12, 0); /* 0x12 CR17 */
 
-		/* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */
-		XGINew_SetRegAND(pVBInfo->Part2Port, 0x00, 0xEF);
-	}
+	if (pVBInfo->LCDInfo & LCDRGB18Bit)
+		temp = 0x80;
+	else
+		temp = 0x00;
 
-	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-		if (!(pVBInfo->VBInfo & SetInSlaveMode))
-			XGINew_SetReg1(pVBInfo->Part2Port, 0x0B, 0x00);
-	}
+	xgifb_reg_set(pVBInfo->Part1Port, 0x1A, temp); /* 0x1A SR0E */
 
-	if (pVBInfo->VBInfo & SetCRT2ToTV)
-		return;
+	return;
 }
 
-void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
+static void XGI_SetGroup2(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short push1, push2, pushbx, tempax, tempbx, tempcx, temp,
-			tempah, tempbh, tempch, resinfo, modeflag, CRT1Index;
+	unsigned short i, j, tempax, tempbx, tempcx, temp, push1, push2,
+			modeflag, resinfo, crt2crtc;
+	unsigned char *TimingPoint;
 
-	struct XGI_LCDDesStruct *LCDBDesPtr = NULL;
+	unsigned long longtemp, tempeax, tempebx, temp2, tempecx;
 
 	if (ModeNo <= 0x13) {
 		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
 		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
+		crt2crtc = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
 	} else {
 		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
 		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-		CRT1Index
-				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-		CRT1Index &= IndexMask;
+		crt2crtc
+				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
 	}
 
-	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
-		return;
-
-	tempbx = pVBInfo->HDE; /* RHACTE=HDE-1 */
-
-	if (XGI_IsLCDDualLink(pVBInfo))
-		tempbx = tempbx >> 1;
-
-	tempbx -= 1;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x2C, temp);
-	temp = (tempbx & 0xFF00) >> 8;
-	temp = temp << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
-	temp = 0x01;
+	tempax = 0;
 
-	if (pVBInfo->LCDResInfo == Panel1280x1024) {
-		if (pVBInfo->ModeType == ModeEGA) {
-			if (pVBInfo->VGAHDE >= 1024) {
-				temp = 0x02;
-				if (pVBInfo->LCDInfo & LCDVESATiming)
-					temp = 0x01;
-			}
-		}
-	}
+	if (!(pVBInfo->VBInfo & SetCRT2ToAVIDEO))
+		tempax |= 0x0800;
 
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x0B, temp);
-	tempbx = pVBInfo->VDE; /* RTVACTEO=(VDE-1)&0xFF */
-	push1 = tempbx;
-	tempbx--;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x03, temp);
-	temp = ((tempbx & 0xFF00) >> 8) & 0x07;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x0C, ~0x07, temp);
+	if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
+		tempax |= 0x0400;
 
-	tempcx = pVBInfo->VT - 1;
-	push2 = tempcx + 1;
-	temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x19, temp);
-	temp = (tempcx & 0xFF00) >> 8;
-	temp = temp << 5;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x1A, temp);
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x09, 0xF0, 0x00);
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x0A, 0xF0, 0x00);
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
+	if (pVBInfo->VBInfo & SetCRT2ToSCART)
+		tempax |= 0x0200;
 
-	/* Customized LCDB Des no add */
-	tempbx = 5;
-	LCDBDesPtr = (struct XGI_LCDDesStruct *) XGI_GetLcdPtr(tempbx, ModeNo,
-			ModeIdIndex, RefreshRateTableIndex, pVBInfo);
-	tempah = pVBInfo->LCDResInfo;
-	tempah &= PanelResInfo;
+	if (!(pVBInfo->TVInfo & SetPALTV))
+		tempax |= 0x1000;
 
-	if ((tempah == Panel1024x768) || (tempah == Panel1024x768x75)) {
-		tempbx = 1024;
-		tempcx = 768;
-	} else if ((tempah == Panel1280x1024) || (tempah == Panel1280x1024x75)) {
-		tempbx = 1280;
-		tempcx = 1024;
-	} else if (tempah == Panel1400x1050) {
-		tempbx = 1400;
-		tempcx = 1050;
-	} else {
-		tempbx = 1600;
-		tempcx = 1200;
-	}
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
+		tempax |= 0x0100;
 
-	if (pVBInfo->LCDInfo & EnableScalingLCD) {
-		tempbx = pVBInfo->HDE;
-		tempcx = pVBInfo->VDE;
-	}
+	if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))
+		tempax &= 0xfe00;
 
-	pushbx = tempbx;
-	tempax = pVBInfo->VT;
-	pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES;
-	pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS;
-	pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES;
-	pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS;
-	tempbx = pVBInfo->LCDVDES;
-	tempcx += tempbx;
+	tempax = (tempax & 0xff00) >> 8;
 
-	if (tempcx >= tempax)
-		tempcx -= tempax; /* lcdvdes */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x0, tempax);
+	TimingPoint = pVBInfo->NTSCTiming;
 
-	temp = tempbx & 0x00FF; /* RVEQ1EQ=lcdvdes */
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x05, temp);
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x06, temp);
-	tempch = ((tempcx & 0xFF00) >> 8) & 0x07;
-	tempbh = ((tempbx & 0xFF00) >> 8) & 0x07;
-	tempah = tempch;
-	tempah = tempah << 3;
-	tempah |= tempbh;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x02, tempah);
+	if (pVBInfo->TVInfo & SetPALTV)
+		TimingPoint = pVBInfo->PALTiming;
 
-	/* getlcdsync() */
-	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
-	tempcx = tempbx;
-	tempax = pVBInfo->VT;
-	tempbx = pVBInfo->LCDVRS;
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+		TimingPoint = pVBInfo->HiTVExtTiming;
 
-	/* if (SetLCD_Info & EnableScalingLCD) */
-	tempcx += tempbx;
-	if (tempcx >= tempax)
-		tempcx -= tempax;
+		if (pVBInfo->VBInfo & SetInSlaveMode)
+			TimingPoint = pVBInfo->HiTVSt2Timing;
 
-	temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x04, temp);
-	temp = (tempbx & 0xFF00) >> 8;
-	temp = temp << 4;
-	temp |= (tempcx & 0x000F);
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x01, temp);
-	tempcx = pushbx;
-	tempax = pVBInfo->HT;
-	tempbx = pVBInfo->LCDHDES;
-	tempbx &= 0x0FFF;
+		if (pVBInfo->SetFlag & TVSimuMode)
+			TimingPoint = pVBInfo->HiTVSt1Timing;
 
-	if (XGI_IsLCDDualLink(pVBInfo)) {
-		tempax = tempax >> 1;
-		tempbx = tempbx >> 1;
-		tempcx = tempcx >> 1;
+		if (!(modeflag & Charx8Dot))
+			TimingPoint = pVBInfo->HiTVTextTiming;
 	}
 
-	if (pVBInfo->VBType & VB_XGI302LV)
-		tempbx += 1;
-
-	if (pVBInfo->VBType & VB_XGI301C) /* tap4 */
-		tempbx += 1;
-
-	tempcx += tempbx;
-
-	if (tempcx >= tempax)
-		tempcx -= tempax;
+	if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
+		if (pVBInfo->TVInfo & SetYPbPrMode525i)
+			TimingPoint = pVBInfo->YPbPr525iTiming;
 
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x1F, temp); /* RHBLKE=lcdhdes */
-	temp = ((tempbx & 0xFF00) >> 8) << 4;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x20, temp);
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x23, temp); /* RHEQPLE=lcdhdee */
-	temp = (tempcx & 0xFF00) >> 8;
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x25, temp);
+		if (pVBInfo->TVInfo & SetYPbPrMode525p)
+			TimingPoint = pVBInfo->YPbPr525pTiming;
 
-	/* getlcdsync() */
-	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
-	tempcx = tempax;
-	tempax = pVBInfo->HT;
-	tempbx = pVBInfo->LCDHRS;
-	/* if ( SetLCD_Info & EnableScalingLCD) */
-	if (XGI_IsLCDDualLink(pVBInfo)) {
-		tempax = tempax >> 1;
-		tempbx = tempbx >> 1;
-		tempcx = tempcx >> 1;
+		if (pVBInfo->TVInfo & SetYPbPrMode750p)
+			TimingPoint = pVBInfo->YPbPr750pTiming;
 	}
 
-	if (pVBInfo->VBType & VB_XGI302LV)
-		tempbx += 1;
+	for (i = 0x01, j = 0; i <= 0x2D; i++, j++)
+		xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]);
 
-	tempcx += tempbx;
+	for (i = 0x39; i <= 0x45; i++, j++)
+		xgifb_reg_set(pVBInfo->Part2Port, i, TimingPoint[j]); /* di->temp2[j] */
 
-	if (tempcx >= tempax)
-		tempcx -= tempax;
+	if (pVBInfo->VBInfo & SetCRT2ToTV)
+		xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, 0x00);
 
-	temp = tempbx & 0x00FF; /* RHBURSTS=lcdhrs */
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x1C, temp);
+	temp = pVBInfo->NewFlickerMode;
+	temp &= 0x80;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xFF, temp);
 
-	temp = (tempbx & 0xFF00) >> 8;
-	temp = temp << 4;
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1D, ~0x0F0, temp);
-	temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x21, temp);
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
+		tempax = 950;
 
-	if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
-		if (pVBInfo->VGAVDE == 525) {
-			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
-					| VB_XGI301LV | VB_XGI302LV
-					| VB_XGI301C)) {
-				temp = 0xC6;
-			} else
-				temp = 0xC4;
+	if (pVBInfo->TVInfo & SetPALTV)
+		tempax = 520;
+	else
+		tempax = 440;
+
+	if (pVBInfo->VDE <= tempax) {
+		tempax -= pVBInfo->VDE;
+		tempax = tempax >> 2;
+		tempax = (tempax & 0x00FF) | ((tempax & 0x00FF) << 8);
+		push1 = tempax;
+		temp = (tempax & 0xFF00) >> 8;
+		temp += (unsigned short) TimingPoint[0];
 
-			XGINew_SetReg1(pVBInfo->Part2Port, 0x2f, temp);
-			XGINew_SetReg1(pVBInfo->Part2Port, 0x30, 0xB3);
+		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)) {
+			if (pVBInfo->VBInfo & (SetCRT2ToAVIDEO
+					| SetCRT2ToSVIDEO | SetCRT2ToSCART
+					| SetCRT2ToYPbPr)) {
+				tempcx = pVBInfo->VGAHDE;
+				if (tempcx >= 1024) {
+					temp = 0x17; /* NTSC */
+					if (pVBInfo->TVInfo & SetPALTV)
+						temp = 0x19; /* PAL */
+				}
+			}
 		}
 
-		if (pVBInfo->VGAVDE == 420) {
-			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
-					| VB_XGI301LV | VB_XGI302LV
-					| VB_XGI301C)) {
-				temp = 0x4F;
-			} else
-				temp = 0x4E;
-			XGINew_SetReg1(pVBInfo->Part2Port, 0x2f, temp);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
+		tempax = push1;
+		temp = (tempax & 0xFF00) >> 8;
+		temp += TimingPoint[1];
+
+		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)) {
+			if ((pVBInfo->VBInfo & (SetCRT2ToAVIDEO
+					| SetCRT2ToSVIDEO | SetCRT2ToSCART
+					| SetCRT2ToYPbPr))) {
+				tempcx = pVBInfo->VGAHDE;
+				if (tempcx >= 1024) {
+					temp = 0x1D; /* NTSC */
+					if (pVBInfo->TVInfo & SetPALTV)
+						temp = 0x52; /* PAL */
+				}
+			}
 		}
+		xgifb_reg_set(pVBInfo->Part2Port, 0x02, temp);
 	}
-}
-
-/* --------------------------------------------------------------------- */
-/* Function : XGI_GetTap4Ptr */
-/* Input : */
-/* Output : di -> Tap4 Reg. Setting Pointer */
-/* Description : */
-/* --------------------------------------------------------------------- */
-struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short tempax, tempbx, i;
 
-	struct XGI301C_Tap4TimingStruct *Tap4TimingPtr;
+	/* 301b */
+	tempcx = pVBInfo->HT;
 
-	if (tempcx == 0) {
-		tempax = pVBInfo->VGAHDE;
-		tempbx = pVBInfo->HDE;
-	} else {
-		tempax = pVBInfo->VGAVDE;
-		tempbx = pVBInfo->VDE;
-	}
+	if (XGI_IsLCDDualLink(pVBInfo))
+		tempcx = tempcx >> 1;
 
-	if (tempax < tempbx)
-		return &EnlargeTap4Timing[0];
-	else if (tempax == tempbx)
-		return &NoScaleTap4Timing[0]; /* 1:1 */
-	else
-		Tap4TimingPtr = NTSCTap4Timing; /* NTSC */
+	tempcx -= 2;
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x1B, temp);
 
-	if (pVBInfo->TVInfo & SetPALTV)
-		Tap4TimingPtr = PALTap4Timing;
+	temp = (tempcx & 0xFF00) >> 8;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F, temp);
 
-	if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
-		if (pVBInfo->TVInfo & SetYPbPrMode525i)
-			Tap4TimingPtr = YPbPr525iTap4Timing;
-		if (pVBInfo->TVInfo & SetYPbPrMode525p)
-			Tap4TimingPtr = YPbPr525pTap4Timing;
-		if (pVBInfo->TVInfo & SetYPbPrMode750p)
-			Tap4TimingPtr = YPbPr750pTap4Timing;
-	}
+	tempcx = pVBInfo->HT >> 1;
+	push1 = tempcx; /* push cx */
+	tempcx += 7;
 
 	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
-		Tap4TimingPtr = HiTVTap4Timing;
-
-	i = 0;
-	while (Tap4TimingPtr[i].DE != 0xFFFF) {
-		if (Tap4TimingPtr[i].DE == tempax)
-			break;
-		i++;
-	}
-	return &Tap4TimingPtr[i];
-}
+		tempcx -= 4;
 
-void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
-{
-	unsigned short i, j;
+	temp = tempcx & 0x00FF;
+	temp = temp << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x22, 0x0F, temp);
 
-	struct XGI301C_Tap4TimingStruct *Tap4TimingPtr;
+	tempbx = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
+	tempbx += tempcx;
+	push2 = tempbx;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x24, temp);
+	temp = (tempbx & 0xFF00) >> 8;
+	temp = temp << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x25, 0x0F, temp);
 
-	if (!(pVBInfo->VBType & VB_XGI301C))
-		return;
+	tempbx = push2;
+	tempbx = tempbx + 8;
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+		tempbx = tempbx - 4;
+		tempcx = tempbx;
+	}
 
-#ifndef Tap4
-	XGINew_SetRegAND(pVBInfo->Part2Port, 0x4E, 0xEB); /* Disable Tap4 */
-#else            /* Tap4 Setting */
+	temp = (tempbx & 0x00FF) << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x29, 0x0F, temp);
 
-	Tap4TimingPtr = XGI_GetTap4Ptr(0, pVBInfo); /* Set Horizontal Scaling */
-	for (i = 0x80, j = 0; i <= 0xBF; i++, j++)
-		XGINew_SetReg1(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
+	j += 2;
+	tempcx += (TimingPoint[j] | ((TimingPoint[j + 1]) << 8));
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x27, temp);
+	temp = ((tempcx & 0xFF00) >> 8) << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x28, 0x0F, temp);
 
-	if ((pVBInfo->VBInfo & SetCRT2ToTV) && (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV))) {
-		Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo); /* Set Vertical Scaling */
-		for (i = 0xC0, j = 0; i < 0xFF; i++, j++)
-			XGINew_SetReg1(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
-	}
+	tempcx += 8;
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
+		tempcx -= 4;
 
-	if ((pVBInfo->VBInfo & SetCRT2ToTV) && (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)))
-		XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04); /* Enable V.Scaling */
-	else
-		XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10); /* Enable H.Scaling */
-#endif
-}
+	temp = tempcx & 0xFF;
+	temp = temp << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x2A, 0x0F, temp);
 
-void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short i;
-	unsigned char *tempdi;
-	unsigned short modeflag;
+	tempcx = push1; /* pop cx */
+	j += 2;
+	temp = TimingPoint[j] | ((TimingPoint[j + 1]) << 8);
+	tempcx -= temp;
+	temp = tempcx & 0x00FF;
+	temp = temp << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x2D, 0x0F, temp);
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+	tempcx -= 11;
 
-	XGINew_SetReg1(pVBInfo->Part3Port, 0x00, 0x00);
-	if (pVBInfo->TVInfo & SetPALTV) {
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x13, 0xFA);
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x14, 0xC8);
-	} else {
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x13, 0xF5);
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x14, 0xB7);
+	if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
+		tempax = XGI_GetVGAHT2(pVBInfo);
+		tempcx = tempax - 1;
 	}
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x2E, temp);
 
-	if (!(pVBInfo->VBInfo & SetCRT2ToTV))
-		return;
+	tempbx = pVBInfo->VDE;
 
-	if (pVBInfo->TVInfo & SetPALMTV) {
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x13, 0xFA);
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x14, 0xC8);
-		XGINew_SetReg1(pVBInfo->Part3Port, 0x3D, 0xA8);
+	if (pVBInfo->VGAVDE == 360)
+		tempbx = 746;
+	if (pVBInfo->VGAVDE == 375)
+		tempbx = 746;
+	if (pVBInfo->VGAVDE == 405)
+		tempbx = 853;
+
+	if (pVBInfo->VBInfo & SetCRT2ToTV) {
+		if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
+			if (!(pVBInfo->TVInfo & (SetYPbPrMode525p
+					| SetYPbPrMode750p)))
+				tempbx = tempbx >> 1;
+		} else
+			tempbx = tempbx >> 1;
 	}
 
-	if ((pVBInfo->VBInfo & SetCRT2ToHiVisionTV) || (pVBInfo->VBInfo
-			& SetCRT2ToYPbPr)) {
-		if (pVBInfo->TVInfo & SetYPbPrMode525i)
-			return;
+	tempbx -= 2;
+	temp = tempbx & 0x00FF;
 
-		tempdi = pVBInfo->HiTVGroup3Data;
-		if (pVBInfo->SetFlag & TVSimuMode) {
-			tempdi = pVBInfo->HiTVGroup3Simu;
-			if (!(modeflag & Charx8Dot))
-				tempdi = pVBInfo->HiTVGroup3Text;
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+		if (pVBInfo->VBType & VB_XGI301LV) {
+			if (pVBInfo->TVInfo & SetYPbPrMode1080i) {
+				if (pVBInfo->VBInfo & SetInSlaveMode) {
+					if (ModeNo == 0x2f)
+						temp += 1;
+				}
+			}
+		} else {
+			if (pVBInfo->VBInfo & SetInSlaveMode) {
+				if (ModeNo == 0x2f)
+					temp += 1;
+			}
 		}
+	}
 
-		if (pVBInfo->TVInfo & SetYPbPrMode525p)
-			tempdi = pVBInfo->Ren525pGroup3;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x2F, temp);
 
-		if (pVBInfo->TVInfo & SetYPbPrMode750p)
-			tempdi = pVBInfo->Ren750pGroup3;
+	temp = (tempcx & 0xFF00) >> 8;
+	temp |= ((tempbx & 0xFF00) >> 8) << 6;
 
-		for (i = 0; i <= 0x3E; i++)
-			XGINew_SetReg1(pVBInfo->Part3Port, i, tempdi[i]);
+	if (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)) {
+		if (pVBInfo->VBType & VB_XGI301LV) {
+			if (pVBInfo->TVInfo & SetYPbPrMode1080i) {
+				temp |= 0x10;
 
-		if (pVBInfo->VBType & VB_XGI301C) { /* Marcovision */
-			if (pVBInfo->TVInfo & SetYPbPrMode525p)
-				XGINew_SetReg1(pVBInfo->Part3Port, 0x28, 0x3f);
+				if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
+					temp |= 0x20;
+			}
+		} else {
+			temp |= 0x10;
+			if (!(pVBInfo->VBInfo & SetCRT2ToSVIDEO))
+				temp |= 0x20;
 		}
 	}
-	return;
-} /* {end of XGI_SetGroup3} */
 
-void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x30, temp);
 
-	unsigned long tempebx, tempeax, templong;
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) { /* TV gatingno */
+		tempbx = pVBInfo->VDE;
+		tempcx = tempbx - 2;
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			if (!(pVBInfo->TVInfo & (SetYPbPrMode525p
+					| SetYPbPrMode750p)))
+				tempbx = tempbx >> 1;
+		}
 
-	temp = pVBInfo->RVBHCFACT;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x13, temp);
+		if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
+			temp = 0;
+			if (tempcx & 0x0400)
+				temp |= 0x20;
 
-	tempbx = pVBInfo->RVBHCMAX;
-	temp = tempbx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x14, temp);
-	temp2 = ((tempbx & 0xFF00) >> 8) << 7;
-	tempcx = pVBInfo->VGAHT - 1;
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x16, temp);
+			if (tempbx & 0x0400)
+				temp |= 0x40;
 
-	temp = ((tempcx & 0xFF00) >> 8) << 3;
-	temp2 |= temp;
+			xgifb_reg_set(pVBInfo->Part4Port, 0x10, temp);
+		}
 
-	tempcx = pVBInfo->VGAVT - 1;
-	if (!(pVBInfo->VBInfo & SetCRT2ToTV))
-		tempcx -= 5;
+		temp = (((tempbx - 3) & 0x0300) >> 8) << 5;
+		xgifb_reg_set(pVBInfo->Part2Port, 0x46, temp);
+		temp = (tempbx - 3) & 0x00FF;
+		xgifb_reg_set(pVBInfo->Part2Port, 0x47, temp);
+	}
 
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x17, temp);
-	temp = temp2 | ((tempcx & 0xFF00) >> 8);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x15, temp);
-	XGINew_SetRegOR(pVBInfo->Part4Port, 0x0D, 0x08);
-	tempcx = pVBInfo->VBInfo;
-	tempbx = pVBInfo->VGAHDE;
+	tempbx = tempbx & 0x00FF;
 
-	if (modeflag & HalfDCLK)
-		tempbx = tempbx >> 1;
+	if (!(modeflag & HalfDCLK)) {
+		tempcx = pVBInfo->VGAHDE;
+		if (tempcx >= pVBInfo->HDE) {
+			tempbx |= 0x2000;
+			tempax &= 0x00FF;
+		}
+	}
 
-	if (XGI_IsLCDDualLink(pVBInfo))
-		tempbx = tempbx >> 1;
+	tempcx = 0x0101;
 
-	if (tempcx & SetCRT2ToHiVisionTV) {
-		temp = 0;
-		if (tempbx <= 1024)
-			temp = 0xA0;
-		if (tempbx == 1280)
-			temp = 0xC0;
-	} else if (tempcx & SetCRT2ToTV) {
-		temp = 0xA0;
-		if (tempbx <= 800)
-			temp = 0x80;
-	} else {
-		temp = 0x80;
-		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
-			temp = 0;
-			if (tempbx > 800)
-				temp = 0x60;
+	if (pVBInfo->VBInfo & SetCRT2ToTV) { /*301b*/
+		if (pVBInfo->VGAHDE >= 1024) {
+			tempcx = 0x1920;
+			if (pVBInfo->VGAHDE >= 1280) {
+				tempcx = 0x1420;
+				tempbx = tempbx & 0xDFFF;
+			}
 		}
 	}
 
-	if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)) {
-		temp = 0x00;
-		if (pVBInfo->VGAHDE == 1280)
-			temp = 0x40;
-		if (pVBInfo->VGAHDE == 1024)
-			temp = 0x20;
-	}
-	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x0E, ~0xEF, temp);
+	if (!(tempbx & 0x2000)) {
+		if (modeflag & HalfDCLK)
+			tempcx = (tempcx & 0xFF00) | ((tempcx & 0x00FF) << 1);
 
-	tempebx = pVBInfo->VDE;
+		push1 = tempbx;
+		tempeax = pVBInfo->VGAHDE;
+		tempebx = (tempcx & 0xFF00) >> 8;
+		longtemp = tempeax * tempebx;
+		tempecx = tempcx & 0x00FF;
+		longtemp = longtemp / tempecx;
 
-	if (tempcx & SetCRT2ToHiVisionTV) {
-		if (!(temp & 0xE000))
-			tempbx = tempbx >> 1;
-	}
+		/* 301b */
+		tempecx = 8 * 1024;
 
-	tempcx = pVBInfo->RVBHRS;
-	temp = tempcx & 0x00FF;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x18, temp);
+		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)) {
+			tempecx = tempecx * 8;
+		}
 
-	tempeax = pVBInfo->VGAVDE;
-	tempcx |= 0x04000;
+		longtemp = longtemp * tempecx;
+		tempecx = pVBInfo->HDE;
+		temp2 = longtemp % tempecx;
+		tempeax = longtemp / tempecx;
+		if (temp2 != 0)
+			tempeax += 1;
 
-	if (tempeax <= tempebx) {
-		tempcx = (tempcx & (~0x4000));
-		tempeax = pVBInfo->VGAVDE;
+		tempax = (unsigned short) tempeax;
+
+		/* 301b */
+		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)) {
+			tempcx = ((tempax & 0xFF00) >> 5) >> 8;
+		}
+		/* end 301b */
+
+		tempbx = push1;
+		tempbx = (unsigned short) (((tempeax & 0x0000FF00) & 0x1F00)
+				| (tempbx & 0x00FF));
+		tempax = (unsigned short) (((tempeax & 0x000000FF) << 8)
+				| (tempax & 0x00FF));
+		temp = (tempax & 0xFF00) >> 8;
 	} else {
-		tempeax -= tempebx;
+		temp = (tempax & 0x00FF) >> 8;
 	}
 
-	templong = (tempeax * 256 * 1024) % tempebx;
-	tempeax = (tempeax * 256 * 1024) / tempebx;
-	tempebx = tempeax;
-
-	if (templong != 0)
-		tempebx++;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x44, temp);
+	temp = (tempbx & 0xFF00) >> 8;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x45, ~0x03F, temp);
+	temp = tempcx & 0x00FF;
 
-	temp = (unsigned short) (tempebx & 0x000000FF);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x1B, temp);
+	if (tempbx & 0x2000)
+		temp = 0;
 
-	temp = (unsigned short) ((tempebx & 0x0000FF00) >> 8);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x1A, temp);
-	tempbx = (unsigned short) (tempebx >> 16);
-	temp = tempbx & 0x00FF;
-	temp = temp << 4;
-	temp |= ((tempcx & 0xFF00) >> 8);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x19, temp);
+	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
+		temp |= 0x18;
 
-	/* 301b */
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		temp = 0x0028;
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x1C, temp);
-		tempax = pVBInfo->VGAHDE;
-		if (modeflag & HalfDCLK)
-			tempax = tempax >> 1;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x46, ~0x1F, temp);
+	if (pVBInfo->TVInfo & SetPALTV) {
+		tempbx = 0x0382;
+		tempcx = 0x007e;
+	} else {
+		tempbx = 0x0369;
+		tempcx = 0x0061;
+	}
 
-		if (XGI_IsLCDDualLink(pVBInfo))
-			tempax = tempax >> 1;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x4b, temp);
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x4c, temp);
 
-		/* if((pVBInfo->VBInfo&(SetCRT2ToLCD))||((pVBInfo->TVInfo&SetYPbPrMode525p)||(pVBInfo->TVInfo&SetYPbPrMode750p))) { */
-		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
-			if (tempax > 800)
-				tempax -= 800;
-		} else {
-			if (pVBInfo->VGAHDE > 800) {
-				if (pVBInfo->VGAHDE == 1024)
-					tempax = (tempax * 25 / 32) - 1;
-				else
-					tempax = (tempax * 20 / 32) - 1;
-			}
-		}
-		tempax -= 1;
+	temp = ((tempcx & 0xFF00) >> 8) & 0x03;
+	temp = temp << 2;
+	temp |= ((tempbx & 0xFF00) >> 8) & 0x03;
 
-		/*
-		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
-			if (pVBInfo->VBType & VB_XGI301LV) {
-				if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i))) {
-					if (pVBInfo->VGAHDE > 800) {
-						if (pVBInfo->VGAHDE == 1024)
-							tempax = (tempax * 25 / 32) - 1;
-						else
-							tempax = (tempax * 20 / 32) - 1;
-					}
-				}
-			} else {
-				if (pVBInfo->VGAHDE > 800) {
-					if (pVBInfo->VGAHDE == 1024)
-						tempax = (tempax * 25 / 32) - 1;
-					else
-						tempax = (tempax * 20 / 32) - 1;
-				}
-			}
-		}
-		*/
+	if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
+		temp |= 0x10;
 
-		temp = (tempax & 0xFF00) >> 8;
-		temp = ((temp & 0x0003) << 4);
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x1E, temp);
-		temp = (tempax & 0x00FF);
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x1D, temp);
+		if (pVBInfo->TVInfo & SetYPbPrMode525p)
+			temp |= 0x20;
 
-		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
-			if (pVBInfo->VGAHDE > 800)
-				XGINew_SetRegOR(pVBInfo->Part4Port, 0x1E, 0x08);
+		if (pVBInfo->TVInfo & SetYPbPrMode750p)
+			temp |= 0x60;
+	}
 
-		}
-		temp = 0x0036;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x4d, temp);
+	temp = xgifb_reg_get(pVBInfo->Part2Port, 0x43); /* 301b change */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x43, (unsigned short) (temp - 3));
 
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			if (!(pVBInfo->TVInfo & (NTSC1024x768
-					| SetYPbPrMode525p | SetYPbPrMode750p
-					| SetYPbPrMode1080i))) {
-				temp |= 0x0001;
-				if ((pVBInfo->VBInfo & SetInSlaveMode)
-						&& (!(pVBInfo->TVInfo
-								& TVSimuMode)))
-					temp &= (~0x0001);
+	if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))) {
+		if (pVBInfo->TVInfo & NTSC1024x768) {
+			TimingPoint = XGI_NTSC1024AdjTime;
+			for (i = 0x1c, j = 0; i <= 0x30; i++, j++) {
+				xgifb_reg_set(pVBInfo->Part2Port, i,
+						TimingPoint[j]);
 			}
+			xgifb_reg_set(pVBInfo->Part2Port, 0x43, 0x72);
 		}
+	}
 
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x1F, 0x00C0, temp);
-		tempbx = pVBInfo->HT;
-		if (XGI_IsLCDDualLink(pVBInfo))
-			tempbx = tempbx >> 1;
-		tempbx = (tempbx >> 1) - 2;
-		temp = ((tempbx & 0x0700) >> 8) << 3;
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x21, 0x00C0, temp);
-		temp = tempbx & 0x00FF;
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x22, temp);
+	/* [ycchen] 01/14/03 Modify for 301C PALM Support */
+	if (pVBInfo->VBType & VB_XGI301C) {
+		if (pVBInfo->TVInfo & SetPALMTV)
+			xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x08,
+					0x08); /* PALM Mode */
 	}
-	/* end 301b */
 
-	if (pVBInfo->ISXPDOS == 0)
-		XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex,
-				pVBInfo);
-}
+	if (pVBInfo->TVInfo & SetPALMTV) {
+		tempax = (unsigned char) xgifb_reg_get(pVBInfo->Part2Port,
+				0x01);
+		tempax--;
+		xgifb_reg_and(pVBInfo->Part2Port, 0x01, tempax);
 
-void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short Pindex, Pdata;
+		/* if ( !( pVBInfo->VBType & VB_XGI301C ) ) */
+		xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xEF);
+	}
 
-	Pindex = pVBInfo->Part5Port;
-	Pdata = pVBInfo->Part5Port + 1;
-	if (pVBInfo->ModeType == ModeVGA) {
-		if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
-				| CRT2DisplayFlag))) {
-			XGINew_EnableCRT2(pVBInfo);
-			/* LoadDAC2(pVBInfo->Part5Port, ModeNo, ModeIdIndex); */
-		}
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
+		if (!(pVBInfo->VBInfo & SetInSlaveMode))
+			xgifb_reg_set(pVBInfo->Part2Port, 0x0B, 0x00);
 	}
-	return;
+
+	if (pVBInfo->VBInfo & SetCRT2ToTV)
+		return;
 }
 
-void *XGI_GetLcdPtr(unsigned short BX, unsigned short ModeNo,
-		unsigned short ModeIdIndex,
+static void XGI_SetLCDRegs(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
 		unsigned short RefreshRateTableIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short i, tempdx, tempcx, tempbx, tempal, modeflag, table;
-
-	struct XGI330_LCDDataTablStruct *tempdi = NULL;
+	unsigned short push1, push2, pushbx, tempax, tempbx, tempcx, temp,
+			tempah, tempbh, tempch, resinfo, modeflag, CRT1Index;
 
-	tempbx = BX;
+	struct XGI_LCDDesStruct *LCDBDesPtr = NULL;
 
 	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-		tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
 	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
+		CRT1Index
+				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
+		CRT1Index &= IndexMask;
 	}
 
-	tempal = tempal & 0x0f;
+	if (!(pVBInfo->VBInfo & SetCRT2ToLCD))
+		return;
 
-	if (tempbx <= 1) { /* ExpLink */
-		if (ModeNo <= 0x13) {
-			tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC; /* find no Ext_CRT2CRTC2 */
-		} else {
-			tempal
-					= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-		}
+	tempbx = pVBInfo->HDE; /* RHACTE=HDE-1 */
 
-		if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-			if (ModeNo <= 0x13)
-				tempal
-						= pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC2;
-			else
-				tempal
-						= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC2;
-		}
+	if (XGI_IsLCDDualLink(pVBInfo))
+		tempbx = tempbx >> 1;
 
-		if (tempbx & 0x01)
-			tempal = (tempal >> 4);
+	tempbx -= 1;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x2C, temp);
+	temp = (tempbx & 0xFF00) >> 8;
+	temp = temp << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x2B, 0x0F, temp);
+	temp = 0x01;
 
-		tempal = (tempal & 0x0f);
+	if (pVBInfo->LCDResInfo == Panel1280x1024) {
+		if (pVBInfo->ModeType == ModeEGA) {
+			if (pVBInfo->VGAHDE >= 1024) {
+				temp = 0x02;
+				if (pVBInfo->LCDInfo & LCDVESATiming)
+					temp = 0x01;
+			}
+		}
 	}
 
-	tempcx = LCDLenList[tempbx]; /* mov cl,byte ptr cs:LCDLenList[bx] */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x0B, temp);
+	tempbx = pVBInfo->VDE; /* RTVACTEO=(VDE-1)&0xFF */
+	push1 = tempbx;
+	tempbx--;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x03, temp);
+	temp = ((tempbx & 0xFF00) >> 8) & 0x07;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0C, ~0x07, temp);
 
-	if (pVBInfo->LCDInfo & EnableScalingLCD) { /* ScaleLCD */
-		if ((tempbx == 5) || (tempbx) == 7)
-			tempcx = LCDDesDataLen2;
-		else if ((tempbx == 3) || (tempbx == 8))
-			tempcx = LVDSDesDataLen2;
+	tempcx = pVBInfo->VT - 1;
+	push2 = tempcx + 1;
+	temp = tempcx & 0x00FF; /* RVTVT=VT-1 */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x19, temp);
+	temp = (tempcx & 0xFF00) >> 8;
+	temp = temp << 5;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x1A, temp);
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x09, 0xF0, 0x00);
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0xF0, 0x00);
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x17, 0xFB, 0x00);
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x18, 0xDF, 0x00);
+
+	/* Customized LCDB Des no add */
+	tempbx = 5;
+	LCDBDesPtr = (struct XGI_LCDDesStruct *) XGI_GetLcdPtr(tempbx, ModeNo,
+			ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	tempah = pVBInfo->LCDResInfo;
+	tempah &= PanelResInfo;
+
+	if ((tempah == Panel1024x768) || (tempah == Panel1024x768x75)) {
+		tempbx = 1024;
+		tempcx = 768;
+	} else if ((tempah == Panel1280x1024) || (tempah == Panel1280x1024x75)) {
+		tempbx = 1280;
+		tempcx = 1024;
+	} else if (tempah == Panel1400x1050) {
+		tempbx = 1400;
+		tempcx = 1050;
+	} else {
+		tempbx = 1600;
+		tempcx = 1200;
 	}
-	/* mov di, word ptr cs:LCDDataList[bx] */
-	/* tempdi = pVideoMemory[LCDDataList + tempbx * 2] | (pVideoMemory[LCDDataList + tempbx * 2 + 1] << 8); */
 
-	switch (tempbx) {
-	case 0:
-		tempdi = XGI_EPLLCDCRT1Ptr_H;
-		break;
-	case 1:
-		tempdi = XGI_EPLLCDCRT1Ptr_V;
-		break;
-	case 2:
-		tempdi = XGI_EPLLCDDataPtr;
-		break;
-	case 3:
-		tempdi = XGI_EPLLCDDesDataPtr;
-		break;
-	case 4:
-		tempdi = XGI_LCDDataTable;
-		break;
-	case 5:
-		tempdi = XGI_LCDDesDataTable;
-		break;
-	case 6:
-		tempdi = XGI_EPLCHLCDRegPtr;
-		break;
-	case 7:
-	case 8:
-	case 9:
-		tempdi = NULL;
-		break;
-	default:
-		break;
+	if (pVBInfo->LCDInfo & EnableScalingLCD) {
+		tempbx = pVBInfo->HDE;
+		tempcx = pVBInfo->VDE;
 	}
 
-	if (tempdi == NULL) /* OEMUtil */
-		return NULL;
+	pushbx = tempbx;
+	tempax = pVBInfo->VT;
+	pVBInfo->LCDHDES = LCDBDesPtr->LCDHDES;
+	pVBInfo->LCDHRS = LCDBDesPtr->LCDHRS;
+	pVBInfo->LCDVDES = LCDBDesPtr->LCDVDES;
+	pVBInfo->LCDVRS = LCDBDesPtr->LCDVRS;
+	tempbx = pVBInfo->LCDVDES;
+	tempcx += tempbx;
 
-	table = tempbx;
-	i = 0;
+	if (tempcx >= tempax)
+		tempcx -= tempax; /* lcdvdes */
 
-	while (tempdi[i].PANELID != 0xff) {
-		tempdx = pVBInfo->LCDResInfo;
-		if (tempbx & 0x0080) { /* OEMUtil */
-			tempbx &= (~0x0080);
-			tempdx = pVBInfo->LCDTypeInfo;
-		}
+	temp = tempbx & 0x00FF; /* RVEQ1EQ=lcdvdes */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x05, temp);
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x06, temp);
+	tempch = ((tempcx & 0xFF00) >> 8) & 0x07;
+	tempbh = ((tempbx & 0xFF00) >> 8) & 0x07;
+	tempah = tempch;
+	tempah = tempah << 3;
+	tempah |= tempbh;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x02, tempah);
 
-		if (pVBInfo->LCDInfo & EnableScalingLCD)
-			tempdx &= (~PanelResInfo);
+	/* getlcdsync() */
+	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
+	tempcx = tempbx;
+	tempax = pVBInfo->VT;
+	tempbx = pVBInfo->LCDVRS;
+
+	/* if (SetLCD_Info & EnableScalingLCD) */
+	tempcx += tempbx;
+	if (tempcx >= tempax)
+		tempcx -= tempax;
+
+	temp = tempbx & 0x00FF; /* RTVACTEE=lcdvrs */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x04, temp);
+	temp = (tempbx & 0xFF00) >> 8;
+	temp = temp << 4;
+	temp |= (tempcx & 0x000F);
+	xgifb_reg_set(pVBInfo->Part2Port, 0x01, temp);
+	tempcx = pushbx;
+	tempax = pVBInfo->HT;
+	tempbx = pVBInfo->LCDHDES;
+	tempbx &= 0x0FFF;
+
+	if (XGI_IsLCDDualLink(pVBInfo)) {
+		tempax = tempax >> 1;
+		tempbx = tempbx >> 1;
+		tempcx = tempcx >> 1;
+	}
+
+	if (pVBInfo->VBType & VB_XGI302LV)
+		tempbx += 1;
+
+	if (pVBInfo->VBType & VB_XGI301C) /* tap4 */
+		tempbx += 1;
+
+	tempcx += tempbx;
+
+	if (tempcx >= tempax)
+		tempcx -= tempax;
+
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x1F, temp); /* RHBLKE=lcdhdes */
+	temp = ((tempbx & 0xFF00) >> 8) << 4;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x20, temp);
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x23, temp); /* RHEQPLE=lcdhdee */
+	temp = (tempcx & 0xFF00) >> 8;
+	xgifb_reg_set(pVBInfo->Part2Port, 0x25, temp);
+
+	/* getlcdsync() */
+	XGI_GetLCDSync(&tempax, &tempbx, pVBInfo);
+	tempcx = tempax;
+	tempax = pVBInfo->HT;
+	tempbx = pVBInfo->LCDHRS;
+	/* if ( SetLCD_Info & EnableScalingLCD) */
+	if (XGI_IsLCDDualLink(pVBInfo)) {
+		tempax = tempax >> 1;
+		tempbx = tempbx >> 1;
+		tempcx = tempcx >> 1;
+	}
+
+	if (pVBInfo->VBType & VB_XGI302LV)
+		tempbx += 1;
+
+	tempcx += tempbx;
+
+	if (tempcx >= tempax)
+		tempcx -= tempax;
 
-		if (tempdi[i].PANELID == tempdx) {
-			tempbx = tempdi[i].MASK;
-			tempdx = pVBInfo->LCDInfo;
+	temp = tempbx & 0x00FF; /* RHBURSTS=lcdhrs */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x1C, temp);
 
-			if (ModeNo <= 0x13) /* alan 09/10/2003 */
-				tempdx |= SetLCDStdMode;
+	temp = (tempbx & 0xFF00) >> 8;
+	temp = temp << 4;
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x1D, ~0x0F0, temp);
+	temp = tempcx & 0x00FF; /* RHSYEXP2S=lcdhre */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x21, temp);
 
-			if (modeflag & HalfDCLK)
-				tempdx |= SetLCDLowResolution;
+	if (!(pVBInfo->LCDInfo & LCDVESATiming)) {
+		if (pVBInfo->VGAVDE == 525) {
+			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
+					| VB_XGI301LV | VB_XGI302LV
+					| VB_XGI301C)) {
+				temp = 0xC6;
+			} else
+				temp = 0xC4;
 
-			tempbx &= tempdx;
-			if (tempbx == tempdi[i].CAP)
-				break;
+			xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
+			xgifb_reg_set(pVBInfo->Part2Port, 0x30, 0xB3);
 		}
-		i++;
-	}
 
-	if (table == 0) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDSCRT11024x768_1_H[tempal];
-			break;
-		case 1:
-			return &XGI_LVDSCRT11024x768_2_H[tempal];
-			break;
-		case 2:
-			return &XGI_LVDSCRT11280x1024_1_H[tempal];
-			break;
-		case 3:
-			return &XGI_LVDSCRT11280x1024_2_H[tempal];
-			break;
-		case 4:
-			return &XGI_LVDSCRT11400x1050_1_H[tempal];
-			break;
-		case 5:
-			return &XGI_LVDSCRT11400x1050_2_H[tempal];
-			break;
-		case 6:
-			return &XGI_LVDSCRT11600x1200_1_H[tempal];
-			break;
-		case 7:
-			return &XGI_LVDSCRT11024x768_1_Hx75[tempal];
-			break;
-		case 8:
-			return &XGI_LVDSCRT11024x768_2_Hx75[tempal];
-			break;
-		case 9:
-			return &XGI_LVDSCRT11280x1024_1_Hx75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDSCRT11280x1024_2_Hx75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 1) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDSCRT11024x768_1_V[tempal];
-			break;
-		case 1:
-			return &XGI_LVDSCRT11024x768_2_V[tempal];
-			break;
-		case 2:
-			return &XGI_LVDSCRT11280x1024_1_V[tempal];
-			break;
-		case 3:
-			return &XGI_LVDSCRT11280x1024_2_V[tempal];
-			break;
-		case 4:
-			return &XGI_LVDSCRT11400x1050_1_V[tempal];
-			break;
-		case 5:
-			return &XGI_LVDSCRT11400x1050_2_V[tempal];
-			break;
-		case 6:
-			return &XGI_LVDSCRT11600x1200_1_V[tempal];
-			break;
-		case 7:
-			return &XGI_LVDSCRT11024x768_1_Vx75[tempal];
-			break;
-		case 8:
-			return &XGI_LVDSCRT11024x768_2_Vx75[tempal];
-			break;
-		case 9:
-			return &XGI_LVDSCRT11280x1024_1_Vx75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDSCRT11280x1024_2_Vx75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 2) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDS1024x768Data_1[tempal];
-			break;
-		case 1:
-			return &XGI_LVDS1024x768Data_2[tempal];
-			break;
-		case 2:
-			return &XGI_LVDS1280x1024Data_1[tempal];
-			break;
-		case 3:
-			return &XGI_LVDS1280x1024Data_2[tempal];
-			break;
-		case 4:
-			return &XGI_LVDS1400x1050Data_1[tempal];
-			break;
-		case 5:
-			return &XGI_LVDS1400x1050Data_2[tempal];
-			break;
-		case 6:
-			return &XGI_LVDS1600x1200Data_1[tempal];
-			break;
-		case 7:
-			return &XGI_LVDSNoScalingData[tempal];
-			break;
-		case 8:
-			return &XGI_LVDS1024x768Data_1x75[tempal];
-			break;
-		case 9:
-			return &XGI_LVDS1024x768Data_2x75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDS1280x1024Data_1x75[tempal];
-			break;
-		case 11:
-			return &XGI_LVDS1280x1024Data_2x75[tempal];
-			break;
-		case 12:
-			return &XGI_LVDSNoScalingDatax75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 3) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_LVDS1024x768Des_1[tempal];
-			break;
-		case 1:
-			return &XGI_LVDS1024x768Des_3[tempal];
-			break;
-		case 2:
-			return &XGI_LVDS1024x768Des_2[tempal];
-			break;
-		case 3:
-			return &XGI_LVDS1280x1024Des_1[tempal];
-			break;
-		case 4:
-			return &XGI_LVDS1280x1024Des_2[tempal];
-			break;
-		case 5:
-			return &XGI_LVDS1400x1050Des_1[tempal];
-			break;
-		case 6:
-			return &XGI_LVDS1400x1050Des_2[tempal];
-			break;
-		case 7:
-			return &XGI_LVDS1600x1200Des_1[tempal];
-			break;
-		case 8:
-			return &XGI_LVDSNoScalingDesData[tempal];
-			break;
-		case 9:
-			return &XGI_LVDS1024x768Des_1x75[tempal];
-			break;
-		case 10:
-			return &XGI_LVDS1024x768Des_3x75[tempal];
-			break;
-		case 11:
-			return &XGI_LVDS1024x768Des_2x75[tempal];
-			break;
-		case 12:
-			return &XGI_LVDS1280x1024Des_1x75[tempal];
-			break;
-		case 13:
-			return &XGI_LVDS1280x1024Des_2x75[tempal];
-			break;
-		case 14:
-			return &XGI_LVDSNoScalingDesDatax75[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 4) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_ExtLCD1024x768Data[tempal];
-			break;
-		case 1:
-			return &XGI_StLCD1024x768Data[tempal];
-			break;
-		case 2:
-			return &XGI_CetLCD1024x768Data[tempal];
-			break;
-		case 3:
-			return &XGI_ExtLCD1280x1024Data[tempal];
-			break;
-		case 4:
-			return &XGI_StLCD1280x1024Data[tempal];
-			break;
-		case 5:
-			return &XGI_CetLCD1280x1024Data[tempal];
-			break;
-		case 6:
-			return &XGI_ExtLCD1400x1050Data[tempal];
-			break;
-		case 7:
-			return &XGI_StLCD1400x1050Data[tempal];
-			break;
-		case 8:
-			return &XGI_CetLCD1400x1050Data[tempal];
-			break;
-		case 9:
-			return &XGI_ExtLCD1600x1200Data[tempal];
-			break;
-		case 10:
-			return &XGI_StLCD1600x1200Data[tempal];
-			break;
-		case 11:
-			return &XGI_NoScalingData[tempal];
-			break;
-		case 12:
-			return &XGI_ExtLCD1024x768x75Data[tempal];
-			break;
-		case 13:
-			return &XGI_ExtLCD1024x768x75Data[tempal];
-			break;
-		case 14:
-			return &XGI_CetLCD1024x768x75Data[tempal];
-			break;
-		case 15:
-			return &XGI_ExtLCD1280x1024x75Data[tempal];
-			break;
-		case 16:
-			return &XGI_StLCD1280x1024x75Data[tempal];
-			break;
-		case 17:
-			return &XGI_CetLCD1280x1024x75Data[tempal];
-			break;
-		case 18:
-			return &XGI_NoScalingDatax75[tempal];
-			break;
-		default:
-			break;
+		if (pVBInfo->VGAVDE == 420) {
+			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
+					| VB_XGI301LV | VB_XGI302LV
+					| VB_XGI301C)) {
+				temp = 0x4F;
+			} else
+				temp = 0x4E;
+			xgifb_reg_set(pVBInfo->Part2Port, 0x2f, temp);
 		}
-	} else if (table == 5) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_ExtLCDDes1024x768Data[tempal];
-			break;
-		case 1:
-			return &XGI_StLCDDes1024x768Data[tempal];
-			break;
-		case 2:
-			return &XGI_CetLCDDes1024x768Data[tempal];
-			break;
-		case 3:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_ExtLCDDLDes1280x1024Data[tempal];
-			else
-				return &XGI_ExtLCDDes1280x1024Data[tempal];
-			break;
-		case 4:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_StLCDDLDes1280x1024Data[tempal];
-			else
-				return &XGI_StLCDDes1280x1024Data[tempal];
-			break;
-		case 5:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_CetLCDDLDes1280x1024Data[tempal];
-			else
-				return &XGI_CetLCDDes1280x1024Data[tempal];
-			break;
-		case 6:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_ExtLCDDLDes1400x1050Data[tempal];
-			else
-				return &XGI_ExtLCDDes1400x1050Data[tempal];
-			break;
-		case 7:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_StLCDDLDes1400x1050Data[tempal];
-			else
-				return &XGI_StLCDDes1400x1050Data[tempal];
-			break;
-		case 8:
-			return &XGI_CetLCDDes1400x1050Data[tempal];
-			break;
-		case 9:
-			return &XGI_CetLCDDes1400x1050Data2[tempal];
-			break;
-		case 10:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_ExtLCDDLDes1600x1200Data[tempal];
-			else
-				return &XGI_ExtLCDDes1600x1200Data[tempal];
-			break;
-		case 11:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_StLCDDLDes1600x1200Data[tempal];
-			else
-				return &XGI_StLCDDes1600x1200Data[tempal];
-			break;
-		case 12:
-			return &XGI_NoScalingDesData[tempal];
-			break;
-		case 13:
-			return &XGI_ExtLCDDes1024x768x75Data[tempal];
-			break;
-		case 14:
-			return &XGI_StLCDDes1024x768x75Data[tempal];
-			break;
-		case 15:
-			return &XGI_CetLCDDes1024x768x75Data[tempal];
-			break;
-		case 16:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_ExtLCDDLDes1280x1024x75Data[tempal];
-			else
-				return &XGI_ExtLCDDes1280x1024x75Data[tempal];
-			break;
-		case 17:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_StLCDDLDes1280x1024x75Data[tempal];
-			else
-				return &XGI_StLCDDes1280x1024x75Data[tempal];
-			break;
-		case 18:
-			if ((pVBInfo->VBType & VB_XGI301LV) || (pVBInfo->VBType
-					& VB_XGI302LV))
-				return &XGI_CetLCDDLDes1280x1024x75Data[tempal];
-			else
-				return &XGI_CetLCDDes1280x1024x75Data[tempal];
-			break;
-		case 19:
-			return &XGI_NoScalingDesDatax75[tempal];
-			break;
-		default:
+	}
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_GetTap4Ptr */
+/* Input : */
+/* Output : di -> Tap4 Reg. Setting Pointer */
+/* Description : */
+/* --------------------------------------------------------------------- */
+static struct XGI301C_Tap4TimingStruct *XGI_GetTap4Ptr(unsigned short tempcx,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempax, tempbx, i;
+
+	struct XGI301C_Tap4TimingStruct *Tap4TimingPtr;
+
+	if (tempcx == 0) {
+		tempax = pVBInfo->VGAHDE;
+		tempbx = pVBInfo->HDE;
+	} else {
+		tempax = pVBInfo->VGAVDE;
+		tempbx = pVBInfo->VDE;
+	}
+
+	if (tempax < tempbx)
+		return &EnlargeTap4Timing[0];
+	else if (tempax == tempbx)
+		return &NoScaleTap4Timing[0]; /* 1:1 */
+	else
+		Tap4TimingPtr = NTSCTap4Timing; /* NTSC */
+
+	if (pVBInfo->TVInfo & SetPALTV)
+		Tap4TimingPtr = PALTap4Timing;
+
+	if (pVBInfo->VBInfo & SetCRT2ToYPbPr) {
+		if (pVBInfo->TVInfo & SetYPbPrMode525i)
+			Tap4TimingPtr = YPbPr525iTap4Timing;
+		if (pVBInfo->TVInfo & SetYPbPrMode525p)
+			Tap4TimingPtr = YPbPr525pTap4Timing;
+		if (pVBInfo->TVInfo & SetYPbPrMode750p)
+			Tap4TimingPtr = YPbPr750pTap4Timing;
+	}
+
+	if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV)
+		Tap4TimingPtr = HiTVTap4Timing;
+
+	i = 0;
+	while (Tap4TimingPtr[i].DE != 0xFFFF) {
+		if (Tap4TimingPtr[i].DE == tempax)
 			break;
+		i++;
+	}
+	return &Tap4TimingPtr[i];
+}
+
+static void XGI_SetTap4Regs(struct vb_device_info *pVBInfo)
+{
+	unsigned short i, j;
+
+	struct XGI301C_Tap4TimingStruct *Tap4TimingPtr;
+
+	if (!(pVBInfo->VBType & VB_XGI301C))
+		return;
+
+#ifndef Tap4
+	xgifb_reg_and(pVBInfo->Part2Port, 0x4E, 0xEB); /* Disable Tap4 */
+#else            /* Tap4 Setting */
+
+	Tap4TimingPtr = XGI_GetTap4Ptr(0, pVBInfo); /* Set Horizontal Scaling */
+	for (i = 0x80, j = 0; i <= 0xBF; i++, j++)
+		xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
+
+	if ((pVBInfo->VBInfo & SetCRT2ToTV) && (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV))) {
+		Tap4TimingPtr = XGI_GetTap4Ptr(1, pVBInfo); /* Set Vertical Scaling */
+		for (i = 0xC0, j = 0; i < 0xFF; i++, j++)
+			xgifb_reg_set(pVBInfo->Part2Port, i, Tap4TimingPtr->Reg[j]);
+	}
+
+	if ((pVBInfo->VBInfo & SetCRT2ToTV) && (!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)))
+		xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x04); /* Enable V.Scaling */
+	else
+		xgifb_reg_and_or(pVBInfo->Part2Port, 0x4E, ~0x14, 0x10); /* Enable H.Scaling */
+#endif
+}
+
+static void XGI_SetGroup3(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short i;
+	unsigned char *tempdi;
+	unsigned short modeflag;
+
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+
+	xgifb_reg_set(pVBInfo->Part3Port, 0x00, 0x00);
+	if (pVBInfo->TVInfo & SetPALTV) {
+		xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
+		xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
+	} else {
+		xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xF5);
+		xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xB7);
+	}
+
+	if (!(pVBInfo->VBInfo & SetCRT2ToTV))
+		return;
+
+	if (pVBInfo->TVInfo & SetPALMTV) {
+		xgifb_reg_set(pVBInfo->Part3Port, 0x13, 0xFA);
+		xgifb_reg_set(pVBInfo->Part3Port, 0x14, 0xC8);
+		xgifb_reg_set(pVBInfo->Part3Port, 0x3D, 0xA8);
+	}
+
+	if ((pVBInfo->VBInfo & SetCRT2ToHiVisionTV) || (pVBInfo->VBInfo
+			& SetCRT2ToYPbPr)) {
+		if (pVBInfo->TVInfo & SetYPbPrMode525i)
+			return;
+
+		tempdi = pVBInfo->HiTVGroup3Data;
+		if (pVBInfo->SetFlag & TVSimuMode) {
+			tempdi = pVBInfo->HiTVGroup3Simu;
+			if (!(modeflag & Charx8Dot))
+				tempdi = pVBInfo->HiTVGroup3Text;
 		}
-	} else if (table == 6) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_CH7017LV1024x768[tempal];
-			break;
-		case 1:
-			return &XGI_CH7017LV1400x1050[tempal];
-			break;
-		default:
-			break;
+
+		if (pVBInfo->TVInfo & SetYPbPrMode525p)
+			tempdi = pVBInfo->Ren525pGroup3;
+
+		if (pVBInfo->TVInfo & SetYPbPrMode750p)
+			tempdi = pVBInfo->Ren750pGroup3;
+
+		for (i = 0; i <= 0x3E; i++)
+			xgifb_reg_set(pVBInfo->Part3Port, i, tempdi[i]);
+
+		if (pVBInfo->VBType & VB_XGI301C) { /* Marcovision */
+			if (pVBInfo->TVInfo & SetYPbPrMode525p)
+				xgifb_reg_set(pVBInfo->Part3Port, 0x28, 0x3f);
 		}
 	}
-	return NULL;
-}
+	return;
+} /* {end of XGI_SetGroup3} */
 
-void *XGI_GetTVPtr(unsigned short BX, unsigned short ModeNo,
-		unsigned short ModeIdIndex,
+static void XGI_SetGroup4(unsigned short ModeNo, unsigned short ModeIdIndex,
 		unsigned short RefreshRateTableIndex,
+		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short i, tempdx, tempbx, tempal, modeflag, table;
-	struct XGI330_TVDataTablStruct *tempdi = NULL;
+	unsigned short tempax, tempcx, tempbx, modeflag, temp, temp2;
+
+	unsigned long tempebx, tempeax, templong;
+
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
+	else
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
+
+	temp = pVBInfo->RVBHCFACT;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x13, temp);
 
-	tempbx = BX;
+	tempbx = pVBInfo->RVBHCMAX;
+	temp = tempbx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x14, temp);
+	temp2 = ((tempbx & 0xFF00) >> 8) << 7;
+	tempcx = pVBInfo->VGAHT - 1;
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x16, temp);
 
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-		tempal = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		tempal = pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
-	}
+	temp = ((tempcx & 0xFF00) >> 8) << 3;
+	temp2 |= temp;
 
-	tempal = tempal & 0x3f;
-	table = tempbx;
+	tempcx = pVBInfo->VGAVT - 1;
+	if (!(pVBInfo->VBInfo & SetCRT2ToTV))
+		tempcx -= 5;
 
-	switch (tempbx) {
-	case 0:
-		tempdi = NULL; /*EPLCHTVCRT1Ptr_H;*/
-		if (pVBInfo->IF_DEF_CH7007 == 1)
-			tempdi = XGI_EPLCHTVCRT1Ptr;
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x17, temp);
+	temp = temp2 | ((tempcx & 0xFF00) >> 8);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x15, temp);
+	xgifb_reg_or(pVBInfo->Part4Port, 0x0D, 0x08);
+	tempcx = pVBInfo->VBInfo;
+	tempbx = pVBInfo->VGAHDE;
 
-		break;
-	case 1:
-		tempdi = NULL; /*EPLCHTVCRT1Ptr_V;*/
-		if (pVBInfo->IF_DEF_CH7007 == 1)
-			tempdi = XGI_EPLCHTVCRT1Ptr;
+	if (modeflag & HalfDCLK)
+		tempbx = tempbx >> 1;
 
-		break;
-	case 2:
-		tempdi = XGI_EPLCHTVDataPtr;
-		break;
-	case 3:
-		tempdi = NULL;
-		break;
-	case 4:
-		tempdi = XGI_TVDataTable;
-		break;
-	case 5:
-		tempdi = NULL;
-		break;
-	case 6:
-		tempdi = XGI_EPLCHTVRegPtr;
-		break;
-	default:
-		break;
+	if (XGI_IsLCDDualLink(pVBInfo))
+		tempbx = tempbx >> 1;
+
+	if (tempcx & SetCRT2ToHiVisionTV) {
+		temp = 0;
+		if (tempbx <= 1024)
+			temp = 0xA0;
+		if (tempbx == 1280)
+			temp = 0xC0;
+	} else if (tempcx & SetCRT2ToTV) {
+		temp = 0xA0;
+		if (tempbx <= 800)
+			temp = 0x80;
+	} else {
+		temp = 0x80;
+		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
+			temp = 0;
+			if (tempbx > 800)
+				temp = 0x60;
+		}
 	}
 
-	if (tempdi == NULL) /* OEMUtil */
-		return NULL;
+	if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)) {
+		temp = 0x00;
+		if (pVBInfo->VGAHDE == 1280)
+			temp = 0x40;
+		if (pVBInfo->VGAHDE == 1024)
+			temp = 0x20;
+	}
+	xgifb_reg_and_or(pVBInfo->Part4Port, 0x0E, ~0xEF, temp);
 
-	tempdx = pVBInfo->TVInfo;
+	tempebx = pVBInfo->VDE;
 
-	if (pVBInfo->VBInfo & SetInSlaveMode)
-		tempdx = tempdx | SetTVLockMode;
+	if (tempcx & SetCRT2ToHiVisionTV) {
+		if (!(temp & 0xE000))
+			tempbx = tempbx >> 1;
+	}
 
-	if (modeflag & HalfDCLK)
-		tempdx = tempdx | SetTVLowResolution;
+	tempcx = pVBInfo->RVBHRS;
+	temp = tempcx & 0x00FF;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x18, temp);
 
-	i = 0;
+	tempeax = pVBInfo->VGAVDE;
+	tempcx |= 0x04000;
 
-	while (tempdi[i].MASK != 0xffff) {
-		if ((tempdx & tempdi[i].MASK) == tempdi[i].CAP)
-			break;
-		i++;
+	if (tempeax <= tempebx) {
+		tempcx = (tempcx & (~0x4000));
+		tempeax = pVBInfo->VGAVDE;
+	} else {
+		tempeax -= tempebx;
 	}
 
-	if (table == 0x00) { /* 07/05/22 */
-	} else if (table == 0x01) {
-	} else if (table == 0x04) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_ExtPALData[tempal];
-			break;
-		case 1:
-			return &XGI_ExtNTSCData[tempal];
-			break;
-		case 2:
-			return &XGI_StPALData[tempal];
-			break;
-		case 3:
-			return &XGI_StNTSCData[tempal];
-			break;
-		case 4:
-			return &XGI_ExtHiTVData[tempal];
-			break;
-		case 5:
-			return &XGI_St2HiTVData[tempal];
-			break;
-		case 6:
-			return &XGI_ExtYPbPr525iData[tempal];
-			break;
-		case 7:
-			return &XGI_ExtYPbPr525pData[tempal];
-			break;
-		case 8:
-			return &XGI_ExtYPbPr750pData[tempal];
-			break;
-		case 9:
-			return &XGI_StYPbPr525iData[tempal];
-			break;
-		case 10:
-			return &XGI_StYPbPr525pData[tempal];
-			break;
-		case 11:
-			return &XGI_StYPbPr750pData[tempal];
-			break;
-		case 12: /* avoid system hang */
-			return &XGI_ExtNTSCData[tempal];
-			break;
-		case 13:
-			return &XGI_St1HiTVData[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 0x02) {
-		switch (tempdi[i].DATAPTR) {
-		case 0:
-			return &XGI_CHTVUNTSCData[tempal];
-			break;
-		case 1:
-			return &XGI_CHTVONTSCData[tempal];
-			break;
-		case 2:
-			return &XGI_CHTVUPALData[tempal];
-			break;
-		case 3:
-			return &XGI_CHTVOPALData[tempal];
-			break;
-		default:
-			break;
-		}
-	} else if (table == 0x06) {
-	}
-	return NULL;
-}
+	templong = (tempeax * 256 * 1024) % tempebx;
+	tempeax = (tempeax * 256 * 1024) / tempebx;
+	tempebx = tempeax;
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_BacklightByDrv */
-/* Input : */
-/* Output : 1 -> Skip backlight control */
-/* Description : */
-/* --------------------------------------------------------------------- */
-unsigned char XGI_BacklightByDrv(struct vb_device_info *pVBInfo)
-{
-	unsigned char tempah;
+	if (templong != 0)
+		tempebx++;
 
-	tempah = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x3A);
-	if (tempah & BacklightControlBit)
-		return 1;
-	else
-		return 0;
-}
+	temp = (unsigned short) (tempebx & 0x000000FF);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x1B, temp);
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_FirePWDDisable */
-/* Input : */
-/* Output : */
-/* Description : Turn off VDD & Backlight : Fire disable procedure */
-/* --------------------------------------------------------------------- */
-/*
-void XGI_FirePWDDisable(struct vb_device_info *pVBInfo)
-{
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x26, 0x00, 0xFC);
-}
-*/
+	temp = (unsigned short) ((tempebx & 0x0000FF00) >> 8);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x1A, temp);
+	tempbx = (unsigned short) (tempebx >> 16);
+	temp = tempbx & 0x00FF;
+	temp = temp << 4;
+	temp |= ((tempcx & 0xFF00) >> 8);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x19, temp);
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_FirePWDEnable */
-/* Input : */
-/* Output : */
-/* Description : Turn on VDD & Backlight : Fire enable procedure */
-/* --------------------------------------------------------------------- */
-void XGI_FirePWDEnable(struct vb_device_info *pVBInfo)
-{
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x26, 0x03, 0xFC);
-}
+	/* 301b */
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		temp = 0x0028;
+		xgifb_reg_set(pVBInfo->Part4Port, 0x1C, temp);
+		tempax = pVBInfo->VGAHDE;
+		if (modeflag & HalfDCLK)
+			tempax = tempax >> 1;
 
-void XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x63, 0xBF, 0x40);
-}
+		if (XGI_IsLCDDualLink(pVBInfo))
+			tempax = tempax >> 1;
 
-void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
+		/* if((pVBInfo->VBInfo&(SetCRT2ToLCD))||((pVBInfo->TVInfo&SetYPbPrMode525p)||(pVBInfo->TVInfo&SetYPbPrMode750p))) { */
+		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
+			if (tempax > 800)
+				tempax -= 800;
+		} else {
+			if (pVBInfo->VGAHDE > 800) {
+				if (pVBInfo->VGAHDE == 1024)
+					tempax = (tempax * 25 / 32) - 1;
+				else
+					tempax = (tempax * 20 / 32) - 1;
+			}
+		}
+		tempax -= 1;
 
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
-}
+		/*
+		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
+			if (pVBInfo->VBType & VB_XGI301LV) {
+				if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p | SetYPbPrMode1080i))) {
+					if (pVBInfo->VGAHDE > 800) {
+						if (pVBInfo->VGAHDE == 1024)
+							tempax = (tempax * 25 / 32) - 1;
+						else
+							tempax = (tempax * 20 / 32) - 1;
+					}
+				}
+			} else {
+				if (pVBInfo->VGAHDE > 800) {
+					if (pVBInfo->VGAHDE == 1024)
+						tempax = (tempax * 25 / 32) - 1;
+					else
+						tempax = (tempax * 20 / 32) - 1;
+				}
+			}
+		}
+		*/
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetPanelDelay */
-/* Input : */
-/* Output : */
-/* Description : */
-/* I/P : bl : 1 ; T1 : the duration between CPL on and signal on */
-/* : bl : 2 ; T2 : the duration signal on and Vdd on */
-/* : bl : 3 ; T3 : the duration between CPL off and signal off */
-/* : bl : 4 ; T4 : the duration signal off and Vdd off */
-/* --------------------------------------------------------------------- */
-void XGI_SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo)
-{
-	unsigned short index;
+		temp = (tempax & 0xFF00) >> 8;
+		temp = ((temp & 0x0003) << 4);
+		xgifb_reg_set(pVBInfo->Part4Port, 0x1E, temp);
+		temp = (tempax & 0x00FF);
+		xgifb_reg_set(pVBInfo->Part4Port, 0x1D, temp);
 
-	index = XGI_GetLCDCapPtr(pVBInfo);
+		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToHiVisionTV)) {
+			if (pVBInfo->VGAHDE > 800)
+				xgifb_reg_or(pVBInfo->Part4Port, 0x1E, 0x08);
 
-	if (tempbl == 1)
-		XGINew_LCD_Wait_Time(pVBInfo->LCDCapList[index].PSC_S1, pVBInfo);
+		}
+		temp = 0x0036;
 
-	if (tempbl == 2)
-		XGINew_LCD_Wait_Time(pVBInfo->LCDCapList[index].PSC_S2, pVBInfo);
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			if (!(pVBInfo->TVInfo & (NTSC1024x768
+					| SetYPbPrMode525p | SetYPbPrMode750p
+					| SetYPbPrMode1080i))) {
+				temp |= 0x0001;
+				if ((pVBInfo->VBInfo & SetInSlaveMode)
+						&& (!(pVBInfo->TVInfo
+								& TVSimuMode)))
+					temp &= (~0x0001);
+			}
+		}
 
-	if (tempbl == 3)
-		XGINew_LCD_Wait_Time(pVBInfo->LCDCapList[index].PSC_S3, pVBInfo);
+		xgifb_reg_and_or(pVBInfo->Part4Port, 0x1F, 0x00C0, temp);
+		tempbx = pVBInfo->HT;
+		if (XGI_IsLCDDualLink(pVBInfo))
+			tempbx = tempbx >> 1;
+		tempbx = (tempbx >> 1) - 2;
+		temp = ((tempbx & 0x0700) >> 8) << 3;
+		xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, 0x00C0, temp);
+		temp = tempbx & 0x00FF;
+		xgifb_reg_set(pVBInfo->Part4Port, 0x22, temp);
+	}
+	/* end 301b */
 
-	if (tempbl == 4)
-		XGINew_LCD_Wait_Time(pVBInfo->LCDCapList[index].PSC_S4, pVBInfo);
+	if (pVBInfo->ISXPDOS == 0)
+		XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				pVBInfo);
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetPanelPower */
-/* Input : */
-/* Output : */
-/* Description : */
-/* I/O : ah = 0011b = 03h ; Backlight on, Power on */
-/* = 0111b = 07h ; Backlight on, Power off */
-/* = 1011b = 0Bh ; Backlight off, Power on */
-/* = 1111b = 0Fh ; Backlight off, Power off */
-/* --------------------------------------------------------------------- */
-void XGI_SetPanelPower(unsigned short tempah, unsigned short tempbl,
-		struct vb_device_info *pVBInfo)
+static void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
 {
-	if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x26, tempbl, tempah);
-	else
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x11, tempbl, tempah);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x1E, 0xFF, 0x20);
 }
 
-static unsigned char XG21GPIODataTransfer(unsigned char ujDate)
+static void XGI_SetGroup5(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned char ujRet = 0;
-	unsigned char i = 0;
+	unsigned short Pindex, Pdata;
 
-	for (i = 0; i < 8; i++) {
-		ujRet = ujRet << 1;
-		/* ujRet |= GETBITS(ujDate >> i, 0:0); */
-		ujRet |= (ujDate >> i) & 1;
+	Pindex = pVBInfo->Part5Port;
+	Pdata = pVBInfo->Part5Port + 1;
+	if (pVBInfo->ModeType == ModeVGA) {
+		if (!(pVBInfo->VBInfo & (SetInSlaveMode | LoadDACFlag
+				| CRT2DisplayFlag))) {
+			XGINew_EnableCRT2(pVBInfo);
+			/* LoadDAC2(pVBInfo->Part5Port, ModeNo, ModeIdIndex); */
+		}
 	}
-
-	return ujRet;
+	return;
 }
 
-/*----------------------------------------------------------------------------*/
-/* output                                                                     */
-/*      bl[5] : LVDS signal                                                   */
-/*      bl[1] : LVDS backlight                                                */
-/*      bl[0] : LVDS VDD                                                      */
-/*----------------------------------------------------------------------------*/
-unsigned char XGI_XG21GetPSCValue(struct vb_device_info *pVBInfo)
+static void XGI_EnableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned char CR4A, temp;
-
-	CR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
-	XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x23); /* enable GPIO write */
-
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48);
-
-	temp = XG21GPIODataTransfer(temp);
-	temp &= 0x23;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4A, CR4A);
-	return temp;
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x40);
 }
 
-/*----------------------------------------------------------------------------*/
-/* output                                                                     */
-/*      bl[5] : LVDS signal                                                   */
-/*      bl[1] : LVDS backlight                                                */
-/*      bl[0] : LVDS VDD                                                      */
-/*----------------------------------------------------------------------------*/
-unsigned char XGI_XG27GetPSCValue(struct vb_device_info *pVBInfo)
+static void XGI_DisableGatingCRT(struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned char CR4A, CRB4, temp;
-
-	CR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
-	XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~0x0C); /* enable GPIO write */
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48);
-
-	temp &= 0x0C;
-	temp >>= 2;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4A, CR4A);
-	CRB4 = XGINew_GetReg1(pVBInfo->P3d4, 0xB4);
-	temp |= ((CRB4 & 0x04) << 3);
-	return temp;
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x63, 0xBF, 0x00);
 }
+
 /*----------------------------------------------------------------------------*/
 /* input                                                                      */
 /*      bl[5] : 1;LVDS signal on                                              */
@@ -6818,24 +6289,24 @@ void XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
 {
 	unsigned char CR4A, temp;
 
-	CR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
+	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
 	tempbh &= 0x23;
 	tempbl &= 0x23;
-	XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
+	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
 
 	if (tempbh & 0x20) {
 		temp = (tempbl >> 4) & 0x02;
 
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0xB4, ~0x02, temp); /* CR B4[1] */
+		xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp); /* CR B4[1] */
 
 	}
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x48);
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x48);
 
 	temp = XG21GPIODataTransfer(temp);
 	temp &= ~tempbh;
 	temp |= tempbl;
-	XGINew_SetReg1(pVBInfo->P3d4, 0x48, temp);
+	xgifb_reg_set(pVBInfo->P3d4, 0x48, temp);
 }
 
 void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
@@ -6854,18 +6325,18 @@ void XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl,
 	if (tempbh & 0x20) {
 		temp = (tempbl >> 4) & 0x02;
 
-		XGINew_SetRegANDOR(pVBInfo->P3d4, 0xB4, ~0x02, temp); /* CR B4[1] */
+		xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~0x02, temp); /* CR B4[1] */
 
 	}
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0xB4, ~tempbh0, tempbl0);
 
-	CR4A = XGINew_GetReg1(pVBInfo->P3d4, 0x4A);
+	CR4A = xgifb_reg_get(pVBInfo->P3d4, 0x4A);
 	tempbh &= 0x03;
 	tempbl &= 0x03;
 	tempbh <<= 2;
 	tempbl <<= 2; /* GPIOC,GPIOD */
-	XGINew_SetRegAND(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
+	xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~tempbh); /* enable GPIO write */
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x48, ~tempbh, tempbl);
 }
 
 /* --------------------------------------------------------------------- */
@@ -6873,7 +6344,7 @@ unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo)
 {
 	unsigned short index;
 
-	index = XGINew_GetReg1(pVBInfo->P3d4, 0x36);
+	index = xgifb_reg_get(pVBInfo->P3d4, 0x36);
 	if (index < sizeof(XGI21_LCDCapList)
 			/ sizeof(struct XGI21_LVDSCapStruct))
 		return index;
@@ -6897,20 +6368,16 @@ void XGI_XG21SetPanelDelay(unsigned short tempbl,
 
 	index = XGI_GetLVDSOEMTableIndex(pVBInfo);
 	if (tempbl == 1)
-		XGINew_LCD_Wait_Time(pVBInfo->XG21_LVDSCapList[index].PSC_S1,
-				pVBInfo);
+		mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S1);
 
 	if (tempbl == 2)
-		XGINew_LCD_Wait_Time(pVBInfo->XG21_LVDSCapList[index].PSC_S2,
-				pVBInfo);
+		mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S2);
 
 	if (tempbl == 3)
-		XGINew_LCD_Wait_Time(pVBInfo->XG21_LVDSCapList[index].PSC_S3,
-				pVBInfo);
+		mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S3);
 
 	if (tempbl == 4)
-		XGINew_LCD_Wait_Time(pVBInfo->XG21_LVDSCapList[index].PSC_S4,
-				pVBInfo);
+		mdelay(pVBInfo->XG21_LVDSCapList[index].PSC_S4);
 }
 
 unsigned char XGI_XG21CheckLVDSMode(unsigned short ModeNo,
@@ -6970,10 +6437,10 @@ void XGI_SetXG21FPBits(struct vb_device_info *pVBInfo)
 {
 	unsigned char temp;
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x37); /* D[0] 1: 18bit */
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37); /* D[0] 1: 18bit */
 	temp = (temp & 1) << 6;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x06, ~0x40, temp); /* SR06[6] 18bit Dither */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80); /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0x40, temp); /* SR06[6] 18bit Dither */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80); /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: dual 12bits */
 
 }
 
@@ -6981,14 +6448,14 @@ void XGI_SetXG27FPBits(struct vb_device_info *pVBInfo)
 {
 	unsigned char temp;
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x37); /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37); /* D[1:0] 01: 18bit, 00: dual 12, 10: single 24 */
 	temp = (temp & 3) << 6;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80); /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80); /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x06, ~0xc0, temp & 0x80); /* SR06[7]0: dual 12/1: single 24 [6] 18bit Dither <= 0 h/w recommend */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0xc0, temp | 0x80); /* SR09[7] enable FP output, SR09[6] 1: sigle 18bits, 0: 24bits */
 
 }
 
-void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char temp, Miscdata;
@@ -7002,14 +6469,14 @@ void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
 	temp = (unsigned char) ((pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability
 					& (LCDPolarity << 8)) >> 8);
 	temp &= LCDPolarity;
-	Miscdata = (unsigned char) XGINew_GetReg2(pVBInfo->P3cc);
+	Miscdata = (unsigned char) inb(pVBInfo->P3cc);
 
-	XGINew_SetReg3(pVBInfo->P3c2, (Miscdata & 0x3F) | temp);
+	outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
 
 	temp = (unsigned char) (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability
 					& LCDPolarity);
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80); /* SR35[7] FP VSync polarity */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1); /* SR30[5] FP HSync polarity */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80); /* SR35[7] FP VSync polarity */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1); /* SR30[5] FP HSync polarity */
 
 	XGI_SetXG21FPBits(pVBInfo);
 	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
@@ -7068,113 +6535,113 @@ void XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
 	LVDSVBE = LVDSVBS + LVDSVT
 			- pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
 
-	temp = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
+	temp = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
 
 	if (!(modeflag & Charx8Dot))
-		XGINew_SetRegOR(pVBInfo->P3c4, 0x1, 0x1);
+		xgifb_reg_or(pVBInfo->P3c4, 0x1, 0x1);
 
 	/* HT SR0B[1:0] CR00 */
 	value = (LVDSHT >> 3) - 5;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x0, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
+	xgifb_reg_set(pVBInfo->P3d4, 0x0, (value & 0xFF));
 
 	/* HBS SR0B[5:4] CR02 */
 	value = (LVDSHBS >> 3) - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x2, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
+	xgifb_reg_set(pVBInfo->P3d4, 0x2, (value & 0xFF));
 
 	/* HBE SR0C[1:0] CR05[7] CR03[4:0] */
 	value = (LVDSHBE >> 3) - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
 
 	/* HRS SR0B[7:6] CR04 */
 	value = (LVDSHRS >> 3) + 2;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
+	xgifb_reg_set(pVBInfo->P3d4, 0x4, (value & 0xFF));
 
 	/* Panel HRS SR2F[1:0] SR2E[7:0]  */
 	value--;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2E, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2E, (value & 0xFF));
 
 	/* HRE SR0C[2] CR05[4:0] */
 	value = (LVDSHRE >> 3) + 2;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
 
 	/* Panel HRE SR2F[7:2]  */
 	value--;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
 
 	/* VT SR0A[0] CR07[5][0] CR06 */
 	value = LVDSVT - 2;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x06, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
+	xgifb_reg_set(pVBInfo->P3d4, 0x06, (value & 0xFF));
 
 	/* VBS SR0A[2] CR09[5] CR07[3] CR15 */
 	value = LVDSVBS - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x15, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
+	xgifb_reg_set(pVBInfo->P3d4, 0x15, (value & 0xFF));
 
 	/* VBE SR0A[4] CR16 */
 	value = LVDSVBE - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x16, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
+	xgifb_reg_set(pVBInfo->P3d4, 0x16, (value & 0xFF));
 
 	/* VRS SR0A[3] CR7[7][2] CR10 */
 	value = LVDSVRS - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x10, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
+	xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
 
 	/* Panel VRS SR3F[1:0] SR34[7:0] SR33[0] */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x3F, ~0x03, (value & 0x600) >> 9);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0x03, (value & 0x600) >> 9);
+	xgifb_reg_set(pVBInfo->P3c4, 0x34, (value >> 1) & 0xFF);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x33, ~0x01, value & 0x01);
 
 	/* VRE SR0A[5] CR11[3:0] */
 	value = LVDSVRE - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
 
 	/* Panel VRE SR3F[7:2] *//* SR3F[7] has to be 0, h/w bug */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x3F, ~0xFC, (value << 2) & 0x7C);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, (value << 2) & 0x7C);
 
 	for (temp = 0, value = 0; temp < 3; temp++) {
 
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x31, ~0x30, value);
-		XGINew_SetReg1(pVBInfo->P3c4,
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
+		xgifb_reg_set(pVBInfo->P3c4,
 				0x2B,
 				pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1);
-		XGINew_SetReg1(pVBInfo->P3c4,
+		xgifb_reg_set(pVBInfo->P3c4,
 				0x2C,
 				pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2);
 		value += 0x10;
 	}
 
 	if (!(modeflag & Charx8Dot)) {
-		XGINew_GetReg2(pVBInfo->P3da); /* reset 3da */
-		XGINew_SetReg3(pVBInfo->P3c0, 0x13); /* set index */
-		XGINew_SetReg3(pVBInfo->P3c0, 0x00); /* set data, panning = 0, shift left 1 dot*/
+		inb(pVBInfo->P3da); /* reset 3da */
+		outb(0x13, pVBInfo->P3c0); /* set index */
+		outb(0x00, pVBInfo->P3c0); /* set data, panning = 0, shift left 1 dot*/
 
-		XGINew_GetReg2(pVBInfo->P3da); /* Enable Attribute */
-		XGINew_SetReg3(pVBInfo->P3c0, 0x20);
+		inb(pVBInfo->P3da); /* Enable Attribute */
+		outb(0x20, pVBInfo->P3c0);
 
-		XGINew_GetReg2(pVBInfo->P3da); /* reset 3da */
+		inb(pVBInfo->P3da); /* reset 3da */
 	}
 
 }
 
 /* no shadow case */
-void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	unsigned char temp, Miscdata;
@@ -7187,14 +6654,14 @@ void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
 	temp = (unsigned char) ((pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability
 					& (LCDPolarity << 8)) >> 8);
 	temp &= LCDPolarity;
-	Miscdata = (unsigned char) XGINew_GetReg2(pVBInfo->P3cc);
+	Miscdata = (unsigned char) inb(pVBInfo->P3cc);
 
-	XGINew_SetReg3(pVBInfo->P3c2, (Miscdata & 0x3F) | temp);
+	outb((Miscdata & 0x3F) | temp, pVBInfo->P3c2);
 
 	temp = (unsigned char) (pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDS_Capability
 					& LCDPolarity);
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80); /* SR35[7] FP VSync polarity */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1); /* SR30[5] FP HSync polarity */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x80, temp & 0x80); /* SR35[7] FP VSync polarity */
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x30, ~0x20, (temp & 0x40) >> 1); /* SR30[5] FP HSync polarity */
 
 	XGI_SetXG27FPBits(pVBInfo);
 	resindex = XGI_GetResInfo(ModeNo, ModeIdIndex, pVBInfo);
@@ -7253,651 +6720,702 @@ void XGI_SetXG27LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex,
 	LVDSVBE = LVDSVBS + LVDSVT
 			- pVBInfo->XG21_LVDSCapList[lvdstableindex].LVDSVDE;
 
-	temp = (unsigned char) XGINew_GetReg1(pVBInfo->P3d4, 0x11);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
+	temp = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x11);
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, temp & 0x7f); /* Unlock CRTC */
 
 	if (!(modeflag & Charx8Dot))
-		XGINew_SetRegOR(pVBInfo->P3c4, 0x1, 0x1);
+		xgifb_reg_or(pVBInfo->P3c4, 0x1, 0x1);
 
 	/* HT SR0B[1:0] CR00 */
 	value = (LVDSHT >> 3) - 5;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x0, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x03, (value & 0x300) >> 8);
+	xgifb_reg_set(pVBInfo->P3d4, 0x0, (value & 0xFF));
 
 	/* HBS SR0B[5:4] CR02 */
 	value = (LVDSHBS >> 3) - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x2, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0x30, (value & 0x300) >> 4);
+	xgifb_reg_set(pVBInfo->P3d4, 0x2, (value & 0xFF));
 
 	/* HBE SR0C[1:0] CR05[7] CR03[4:0] */
 	value = (LVDSHBE >> 3) - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x03, (value & 0xC0) >> 6);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x80, (value & 0x20) << 2);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x03, ~0x1F, value & 0x1F);
 
 	/* HRS SR0B[7:6] CR04 */
 	value = (LVDSHRS >> 3) + 2;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x4, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0B, ~0xC0, (value & 0x300) >> 2);
+	xgifb_reg_set(pVBInfo->P3d4, 0x4, (value & 0xFF));
 
 	/* Panel HRS SR2F[1:0] SR2E[7:0]  */
 	value--;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x2E, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0x03, (value & 0x300) >> 8);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2E, (value & 0xFF));
 
 	/* HRE SR0C[2] CR05[4:0] */
 	value = (LVDSHRE >> 3) + 2;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0C, ~0x04, (value & 0x20) >> 3);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x05, ~0x1F, value & 0x1F);
 
 	/* Panel HRE SR2F[7:2]  */
 	value--;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x2F, ~0xFC, value << 2);
 
 	/* VT SR0A[0] CR07[5][0] CR06 */
 	value = LVDSVT - 2;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x06, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x01, (value & 0x400) >> 10);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x20, (value & 0x200) >> 4);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x01, (value & 0x100) >> 8);
+	xgifb_reg_set(pVBInfo->P3d4, 0x06, (value & 0xFF));
 
 	/* VBS SR0A[2] CR09[5] CR07[3] CR15 */
 	value = LVDSVBS - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x15, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x04, (value & 0x400) >> 8);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x09, ~0x20, (value & 0x200) >> 4);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x08, (value & 0x100) >> 5);
+	xgifb_reg_set(pVBInfo->P3d4, 0x15, (value & 0xFF));
 
 	/* VBE SR0A[4] CR16 */
 	value = LVDSVBE - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x16, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x10, (value & 0x100) >> 4);
+	xgifb_reg_set(pVBInfo->P3d4, 0x16, (value & 0xFF));
 
 	/* VRS SR0A[3] CR7[7][2] CR10 */
 	value = LVDSVRS - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
-	XGINew_SetReg1(pVBInfo->P3d4, 0x10, (value & 0xFF));
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x08, (value & 0x400) >> 7);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x80, (value & 0x200) >> 2);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x07, ~0x04, (value & 0x100) >> 6);
+	xgifb_reg_set(pVBInfo->P3d4, 0x10, (value & 0xFF));
 
 	/* Panel VRS SR35[2:0] SR34[7:0] */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x35, ~0x07, (value & 0x700) >> 8);
-	XGINew_SetReg1(pVBInfo->P3c4, 0x34, value & 0xFF);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x35, ~0x07, (value & 0x700) >> 8);
+	xgifb_reg_set(pVBInfo->P3c4, 0x34, value & 0xFF);
 
 	/* VRE SR0A[5] CR11[3:0] */
 	value = LVDSVRE - 1;
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
-	XGINew_SetRegANDOR(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x0A, ~0x20, (value & 0x10) << 1);
+	xgifb_reg_and_or(pVBInfo->P3d4, 0x11, ~0x0F, value & 0x0F);
 
 	/* Panel VRE SR3F[7:2] */
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x3F, ~0xFC, (value << 2) & 0xFC);
+	xgifb_reg_and_or(pVBInfo->P3c4, 0x3F, ~0xFC, (value << 2) & 0xFC);
 
 	for (temp = 0, value = 0; temp < 3; temp++) {
 
-		XGINew_SetRegANDOR(pVBInfo->P3c4, 0x31, ~0x30, value);
-		XGINew_SetReg1(pVBInfo->P3c4,
+		xgifb_reg_and_or(pVBInfo->P3c4, 0x31, ~0x30, value);
+		xgifb_reg_set(pVBInfo->P3c4,
 				0x2B,
 				pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData1);
-		XGINew_SetReg1(pVBInfo->P3c4,
+		xgifb_reg_set(pVBInfo->P3c4,
 				0x2C,
 				pVBInfo->XG21_LVDSCapList[lvdstableindex].VCLKData2);
 		value += 0x10;
 	}
 
 	if (!(modeflag & Charx8Dot)) {
-		XGINew_GetReg2(pVBInfo->P3da); /* reset 3da */
-		XGINew_SetReg3(pVBInfo->P3c0, 0x13); /* set index */
-		XGINew_SetReg3(pVBInfo->P3c0, 0x00); /* set data, panning = 0, shift left 1 dot*/
+		inb(pVBInfo->P3da); /* reset 3da */
+		outb(0x13, pVBInfo->P3c0); /* set index */
+		outb(0x00, pVBInfo->P3c0); /* set data, panning = 0, shift left 1 dot*/
+
+		inb(pVBInfo->P3da); /* Enable Attribute */
+		outb(0x20, pVBInfo->P3c0);
+
+		inb(pVBInfo->P3da); /* reset 3da */
+	}
+
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_IsLCDON */
+/* Input : */
+/* Output : 0 : Skip PSC Control */
+/* 1: Disable PSC */
+/* Description : */
+/* --------------------------------------------------------------------- */
+static unsigned char XGI_IsLCDON(struct vb_device_info *pVBInfo)
+{
+	unsigned short tempax;
+
+	tempax = pVBInfo->VBInfo;
+	if (tempax & SetCRT2ToDualEdge)
+		return 0;
+	else if (tempax & (DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode))
+		return 1;
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_DisableChISLCD */
+/* Input : */
+/* Output : 0 -> Not LCD Mode */
+/* Description : */
+/* --------------------------------------------------------------------- */
+static unsigned char XGI_DisableChISLCD(struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, tempah;
+
+	tempbx = pVBInfo->SetFlag & (DisableChA | DisableChB);
+	tempah = ~((unsigned short) xgifb_reg_get(pVBInfo->Part1Port, 0x2E));
+
+	if (tempbx & (EnableChA | DisableChA)) {
+		if (!(tempah & 0x08)) /* Chk LCDA Mode */
+			return 0;
+	}
+
+	if (!(tempbx & (EnableChB | DisableChB)))
+		return 0;
+
+	if (tempah & 0x01) /* Chk LCDB Mode */
+		return 1;
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/* Function : XGI_EnableChISLCD */
+/* Input : */
+/* Output : 0 -> Not LCD mode */
+/* Description : */
+/* --------------------------------------------------------------------- */
+static unsigned char XGI_EnableChISLCD(struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, tempah;
+
+	tempbx = pVBInfo->SetFlag & (EnableChA | EnableChB);
+	tempah = ~((unsigned short) xgifb_reg_get(pVBInfo->Part1Port, 0x2E));
+
+	if (tempbx & (EnableChA | DisableChA)) {
+		if (!(tempah & 0x08)) /* Chk LCDA Mode */
+			return 0;
+	}
+
+	if (!(tempbx & (EnableChB | DisableChB)))
+		return 0;
+
+	if (tempah & 0x01) /* Chk LCDB Mode */
+		return 1;
+
+	return 0;
+}
+
+void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempah = 0;
+
+	if (pVBInfo->SetFlag == Win9xDOSMode)
+		return;
+
+	/*
+	if (CH7017) {
+		if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2toLCDA)) || (XGI_DisableChISLCD(pVBInfo))) {
+			if (!XGI_IsLCDON(pVBInfo)) {
+				if (DISCHARGE) {
+					tempbx = XGINew_GetCH7005(0x61);
+					if (tempbx < 0x01) // first time we power up
+						XGINew_SetCH7005(0x0066); // and disable power sequence
+					else
+						XGINew_SetCH7005(0x5f66); // leave VDD on - disable power
+				}
+			}
+		}
+	}
+	*/
+
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		tempah = 0x3F;
+		if (!(pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode))) {
+			if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+				if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
+					tempah = 0x7F; /* Disable Channel A */
+					if (!(pVBInfo->VBInfo & SetCRT2ToLCDA))
+						tempah = 0xBF; /* Disable Channel B */
+
+					if (pVBInfo->SetFlag & DisableChB)
+						tempah &= 0xBF; /* force to disable Cahnnel */
+
+					if (pVBInfo->SetFlag & DisableChA)
+						tempah &= 0x7F; /* Force to disable Channel B */
+				}
+			}
+		}
+
+		xgifb_reg_and(pVBInfo->Part4Port, 0x1F, tempah); /* disable part4_1f */
+
+		if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
+			if (((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)))
+					|| (XGI_DisableChISLCD(pVBInfo))
+					|| (XGI_IsLCDON(pVBInfo)))
+				xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x80); /* LVDS Driver power down */
+		}
+
+		if ((pVBInfo->SetFlag & DisableChA) || (pVBInfo->VBInfo
+				& (DisableCRT2Display | SetCRT2ToLCDA
+						| SetSimuScanMode))) {
+			if (pVBInfo->SetFlag & GatingCRT)
+				XGI_EnableGatingCRT(HwDeviceExtension, pVBInfo);
+			XGI_DisplayOff(HwDeviceExtension, pVBInfo);
+		}
+
+		if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+			if ((pVBInfo->SetFlag & DisableChA) || (pVBInfo->VBInfo
+					& SetCRT2ToLCDA))
+				xgifb_reg_and(pVBInfo->Part1Port, 0x1e, 0xdf); /* Power down */
+		}
+
+		xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xdf); /* disable TV as primary VGA swap */
+
+		if ((pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToDualEdge)))
+			xgifb_reg_and(pVBInfo->Part2Port, 0x00, 0xdf);
+
+		if ((pVBInfo->SetFlag & DisableChB) || (pVBInfo->VBInfo
+				& (DisableCRT2Display | SetSimuScanMode))
+				|| ((!(pVBInfo->VBInfo & SetCRT2ToLCDA))
+						&& (pVBInfo->VBInfo
+								& (SetCRT2ToRAMDAC
+										| SetCRT2ToLCD
+										| SetCRT2ToTV))))
+			xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80); /* BScreenOff=1 */
 
-		XGINew_GetReg2(pVBInfo->P3da); /* Enable Attribute */
-		XGINew_SetReg3(pVBInfo->P3c0, 0x20);
+		if ((pVBInfo->SetFlag & DisableChB) || (pVBInfo->VBInfo
+				& (DisableCRT2Display | SetSimuScanMode))
+				|| (!(pVBInfo->VBInfo & SetCRT2ToLCDA))
+				|| (pVBInfo->VBInfo & (SetCRT2ToRAMDAC
+						| SetCRT2ToLCD | SetCRT2ToTV))) {
+			tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00); /* save Part1 index 0 */
+			xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x10); /* BTDAC = 1, avoid VB reset */
+			xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF); /* disable CRT2 */
+			xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah); /* restore Part1 index 0 */
+		}
+	} else { /* {301} */
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
+			xgifb_reg_or(pVBInfo->Part1Port, 0x00, 0x80); /* BScreenOff=1 */
+			xgifb_reg_and(pVBInfo->Part1Port, 0x1E, 0xDF); /* Disable CRT2 */
+			xgifb_reg_and(pVBInfo->P3c4, 0x32, 0xDF); /* Disable TV asPrimary VGA swap */
+		}
 
-		XGINew_GetReg2(pVBInfo->P3da); /* reset 3da */
+		if (pVBInfo->VBInfo & (DisableCRT2Display | SetCRT2ToLCDA
+				| SetSimuScanMode))
+			XGI_DisplayOff(HwDeviceExtension, pVBInfo);
 	}
-
 }
 
 /* --------------------------------------------------------------------- */
-/* Function : XGI_IsLCDON */
+/* Function : XGI_GetTVPtrIndex */
 /* Input : */
-/* Output : 0 : Skip PSC Control */
-/* 1: Disable PSC */
-/* Description : */
+/* Output : */
+/* Description : bx 0 : ExtNTSC */
+/* 1 : StNTSC */
+/* 2 : ExtPAL */
+/* 3 : StPAL */
+/* 4 : ExtHiTV */
+/* 5 : StHiTV */
+/* 6 : Ext525i */
+/* 7 : St525i */
+/* 8 : Ext525p */
+/* 9 : St525p */
+/* A : Ext750p */
+/* B : St750p */
 /* --------------------------------------------------------------------- */
-unsigned char XGI_IsLCDON(struct vb_device_info *pVBInfo)
-{
-	unsigned short tempax;
-
-	tempax = pVBInfo->VBInfo;
-	if (tempax & SetCRT2ToDualEdge)
-		return 0;
-	else if (tempax & (DisableCRT2Display | SwitchToCRT2 | SetSimuScanMode))
-		return 1;
-
-	return 0;
-}
-
-void XGI_EnablePWD(struct vb_device_info *pVBInfo)
+static unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
 {
-	unsigned short index, temp;
+	unsigned short tempbx = 0;
 
-	index = XGI_GetLCDCapPtr(pVBInfo);
-	temp = pVBInfo->LCDCapList[index].PWD_2B;
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x2B, temp);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x2C,
-			pVBInfo->LCDCapList[index].PWD_2C);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x2D,
-			pVBInfo->LCDCapList[index].PWD_2D);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x2E,
-			pVBInfo->LCDCapList[index].PWD_2E);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x2F,
-			pVBInfo->LCDCapList[index].PWD_2F);
-	XGINew_SetRegOR(pVBInfo->Part4Port, 0x27, 0x80); /* enable PWD */
-}
+	if (pVBInfo->TVInfo & SetPALTV)
+		tempbx = 2;
+	if (pVBInfo->TVInfo & SetYPbPrMode1080i)
+		tempbx = 4;
+	if (pVBInfo->TVInfo & SetYPbPrMode525i)
+		tempbx = 6;
+	if (pVBInfo->TVInfo & SetYPbPrMode525p)
+		tempbx = 8;
+	if (pVBInfo->TVInfo & SetYPbPrMode750p)
+		tempbx = 10;
+	if (pVBInfo->TVInfo & TVSimuMode)
+		tempbx++;
 
-void XGI_DisablePWD(struct vb_device_info *pVBInfo)
-{
-	XGINew_SetRegAND(pVBInfo->Part4Port, 0x27, 0x7F); /* disable PWD */
+	return tempbx;
 }
 
 /* --------------------------------------------------------------------- */
-/* Function : XGI_DisableChISLCD */
+/* Function : XGI_GetTVPtrIndex2 */
 /* Input : */
-/* Output : 0 -> Not LCD Mode */
+/* Output : bx 0 : NTSC */
+/* 1 : PAL */
+/* 2 : PALM */
+/* 3 : PALN */
+/* 4 : NTSC1024x768 */
+/* 5 : PAL-M 1024x768 */
+/* 6-7: reserved */
+/* cl 0 : YFilter1 */
+/* 1 : YFilter2 */
+/* ch 0 : 301A */
+/* 1 : 301B/302B/301LV/302LV */
 /* Description : */
 /* --------------------------------------------------------------------- */
-unsigned char XGI_DisableChISLCD(struct vb_device_info *pVBInfo)
+static void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
+		unsigned char *tempch, struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx, tempah;
+	*tempbx = 0;
+	*tempcl = 0;
+	*tempch = 0;
 
-	tempbx = pVBInfo->SetFlag & (DisableChA | DisableChB);
-	tempah = ~((unsigned short) XGINew_GetReg1(pVBInfo->Part1Port, 0x2E));
+	if (pVBInfo->TVInfo & SetPALTV)
+		*tempbx = 1;
 
-	if (tempbx & (EnableChA | DisableChA)) {
-		if (!(tempah & 0x08)) /* Chk LCDA Mode */
-			return 0;
-	}
+	if (pVBInfo->TVInfo & SetPALMTV)
+		*tempbx = 2;
 
-	if (!(tempbx & (EnableChB | DisableChB)))
-		return 0;
+	if (pVBInfo->TVInfo & SetPALNTV)
+		*tempbx = 3;
 
-	if (tempah & 0x01) /* Chk LCDB Mode */
-		return 1;
+	if (pVBInfo->TVInfo & NTSC1024x768) {
+		*tempbx = 4;
+		if (pVBInfo->TVInfo & SetPALMTV)
+			*tempbx = 5;
+	}
 
-	return 0;
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo
+				& TVSimuMode)) {
+			*tempbx += 8;
+			*tempcl += 1;
+		}
+	}
+
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C))
+		(*tempch)++;
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_EnableChISLCD */
-/* Input : */
-/* Output : 0 -> Not LCD mode */
-/* Description : */
-/* --------------------------------------------------------------------- */
-unsigned char XGI_EnableChISLCD(struct vb_device_info *pVBInfo)
+static void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx, tempah;
-
-	tempbx = pVBInfo->SetFlag & (EnableChA | EnableChB);
-	tempah = ~((unsigned short) XGINew_GetReg1(pVBInfo->Part1Port, 0x2E));
-
-	if (tempbx & (EnableChA | DisableChA)) {
-		if (!(tempah & 0x08)) /* Chk LCDA Mode */
-			return 0;
-	}
+	unsigned short index;
 
-	if (!(tempbx & (EnableChB | DisableChB)))
-		return 0;
+	unsigned char tempah, tempbl, tempbh;
 
-	if (tempah & 0x01) /* Chk LCDB Mode */
-		return 1;
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA
+				| SetCRT2ToTV | SetCRT2ToRAMDAC)) {
+			tempbl = 0;
+			tempbh = 0;
 
-	return 0;
-}
+			index = XGI_GetTVPtrIndex(pVBInfo); /* Get TV Delay */
+			tempbl = pVBInfo->XGI_TVDelayList[index];
 
-unsigned short XGI_GetLCDCapPtr(struct vb_device_info *pVBInfo)
-{
-	unsigned char tempal, tempah, tempbl, i;
+			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
+					| VB_XGI301LV | VB_XGI302LV
+					| VB_XGI301C))
+				tempbl = pVBInfo->XGI_TVDelayList2[index];
 
-	tempah = XGINew_GetReg1(pVBInfo->P3d4, 0x36);
-	tempal = tempah & 0x0F;
-	tempah = tempah & 0xF0;
-	i = 0;
-	tempbl = pVBInfo->LCDCapList[i].LCD_ID;
+			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
+				tempbl = tempbl >> 4;
+			/*
+			if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
+				tempbl = CRT2Delay1;	// Get CRT2 Delay
+			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
+				tempbl = CRT2Delay2;
+			*/
+			if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+				index = XGI_GetLCDCapPtr(pVBInfo); /* Get LCD Delay */
+				tempbh = pVBInfo->LCDCapList[index].LCD_DelayCompensation;
 
-	while (tempbl != 0xFF) {
-		if (tempbl & 0x80) { /* OEMUtil */
-			tempal = tempah;
-			tempbl = tempbl & ~(0x80);
-		}
+				if (!(pVBInfo->VBInfo & SetCRT2ToLCDA))
+					tempbl = tempbh;
+			}
 
-		if (tempal == tempbl)
-			break;
+			tempbl &= 0x0F;
+			tempbh &= 0xF0;
+			tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x2D);
 
-		i++;
+			if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD
+					| SetCRT2ToTV)) { /* Channel B */
+				tempah &= 0xF0;
+				tempah |= tempbl;
+			}
 
-		tempbl = pVBInfo->LCDCapList[i].LCD_ID;
+			if (pVBInfo->VBInfo & SetCRT2ToLCDA) { /* Channel A */
+				tempah &= 0x0F;
+				tempah |= tempbh;
+			}
+			xgifb_reg_set(pVBInfo->Part1Port, 0x2D, tempah);
+		}
+	} else if (pVBInfo->IF_DEF_LVDS == 1) {
+		tempbl = 0;
+		tempbh = 0;
+		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
+			tempah
+					= pVBInfo->LCDCapList[XGI_GetLCDCapPtr(
+							pVBInfo)].LCD_DelayCompensation; /* / Get LCD Delay */
+			tempah &= 0x0f;
+			tempah = tempah << 4;
+			xgifb_reg_and_or(pVBInfo->Part1Port, 0x2D, 0x0f,
+					tempah);
+		}
 	}
-
-	return i;
 }
 
-unsigned short XGI_GetLCDCapPtr1(struct vb_device_info *pVBInfo)
+static void XGI_SetLCDCap_A(unsigned short tempcx, struct vb_device_info *pVBInfo)
 {
-	unsigned short tempah, tempal, tempbl, i;
-
-	tempal = pVBInfo->LCDResInfo;
-	tempah = pVBInfo->LCDTypeInfo;
-
-	i = 0;
-	tempbl = pVBInfo->LCDCapList[i].LCD_ID;
-
-	while (tempbl != 0xFF) {
-		if ((tempbl & 0x80) && (tempbl != 0x80)) {
-			tempal = tempah;
-			tempbl &= ~0x80;
-		}
+	unsigned short temp;
 
-		if (tempal == tempbl)
-			break;
+	temp = xgifb_reg_get(pVBInfo->P3d4, 0x37);
 
-		i++;
-		tempbl = pVBInfo->LCDCapList[i].LCD_ID;
+	if (temp & LCDRGB18Bit) {
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
+				(unsigned short) (0x20 | (tempcx & 0x00C0))); /* Enable Dither */
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
+	} else {
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F,
+				(unsigned short) (0x30 | (tempcx & 0x00C0)));
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
 	}
 
-	if (tempbl == 0xFF) {
-		pVBInfo->LCDResInfo = Panel1024x768;
-		pVBInfo->LCDTypeInfo = 0;
-		i = 0;
+	/*
+	if (tempcx & EnableLCD24bpp) {	// 24bits
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F, (unsigned short)(0x30 | (tempcx&0x00C0)));
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
+	} else {
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x19, 0x0F, (unsigned short)(0x20 | (tempcx&0x00C0))); // Enable Dither
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
 	}
+	*/
+}
 
-	return i;
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetLCDCap_B */
+/* Input : cx -> LCD Capability */
+/* Output : */
+/* Description : */
+/* --------------------------------------------------------------------- */
+static void XGI_SetLCDCap_B(unsigned short tempcx, struct vb_device_info *pVBInfo)
+{
+	if (tempcx & EnableLCD24bpp) /* 24bits */
+		xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
+				(unsigned short) (((tempcx & 0x00ff) >> 6)
+						| 0x0c));
+	else
+		xgifb_reg_and_or(pVBInfo->Part2Port, 0x1A, 0xE0,
+				(unsigned short) (((tempcx & 0x00ff) >> 6)
+						| 0x18)); /* Enable Dither */
 }
 
-void XGI_GetLCDSync(unsigned short *HSyncWidth, unsigned short *VSyncWidth,
-		struct vb_device_info *pVBInfo)
+static void SetSpectrum(struct vb_device_info *pVBInfo)
 {
-	unsigned short Index;
+	unsigned short index;
 
-	Index = XGI_GetLCDCapPtr(pVBInfo);
-	*HSyncWidth = pVBInfo->LCDCapList[Index].LCD_HSyncWidth;
-	*VSyncWidth = pVBInfo->LCDCapList[Index].LCD_VSyncWidth;
+	index = XGI_GetLCDCapPtr(pVBInfo);
+
+	xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x8F); /* disable down spectrum D[4] */
+	XGI_LongWait(pVBInfo);
+	xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x20); /* reset spectrum */
+	XGI_LongWait(pVBInfo);
 
-	return;
+	xgifb_reg_set(pVBInfo->Part4Port, 0x31,
+			pVBInfo->LCDCapList[index].Spectrum_31);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x32,
+			pVBInfo->LCDCapList[index].Spectrum_32);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x33,
+			pVBInfo->LCDCapList[index].Spectrum_33);
+	xgifb_reg_set(pVBInfo->Part4Port, 0x34,
+			pVBInfo->LCDCapList[index].Spectrum_34);
+	XGI_LongWait(pVBInfo);
+	xgifb_reg_or(pVBInfo->Part4Port, 0x30, 0x40); /* enable spectrum */
 }
 
-void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbl, tempah;
-
-	if (pVBInfo->SetFlag == Win9xDOSMode) {
-		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-				| VB_XGI302LV | VB_XGI301C)) {
-			XGI_DisplayOn(HwDeviceExtension, pVBInfo);
-			return;
-		} else
-			/* LVDS or CH7017 */
-			return;
-	}
-
-	if (HwDeviceExtension->jChipType < XG40) {
-		if (!XGI_DisableChISLCD(pVBInfo)) {
-			if ((XGI_EnableChISLCD(pVBInfo)) || (pVBInfo->VBInfo
-					& (SetCRT2ToLCD | SetCRT2ToLCDA))) {
-				if (pVBInfo->LCDInfo & SetPWDEnable) {
-					XGI_EnablePWD(pVBInfo);
-				} else {
-					pVBInfo->LCDInfo &= (~SetPWDEnable);
-					if (pVBInfo->VBType & (VB_XGI301LV
-							| VB_XGI302LV
-							| VB_XGI301C)) {
-						tempbl = 0xFD;
-						tempah = 0x02;
-					} else {
-						tempbl = 0xFB;
-						tempah = 0x00;
-					}
+	unsigned short tempcx;
 
-					XGI_SetPanelPower(tempah, tempbl,
-							pVBInfo);
-					XGI_SetPanelDelay(1, pVBInfo);
-				}
-			}
-		}
-	} /* Not 340 */
+	tempcx = pVBInfo->LCDCapList[XGI_GetLCDCapPtr(pVBInfo)].LCD_Capability;
 
 	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
 			| VB_XGI302LV | VB_XGI301C)) {
-		if (!(pVBInfo->SetFlag & DisableChA)) {
-			if (pVBInfo->SetFlag & EnableChA) {
-				XGINew_SetReg1(pVBInfo->Part1Port, 0x1E, 0x20); /* Power on */
-			} else {
-				if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { /* SetCRT2ToLCDA ) */
-					XGINew_SetReg1(pVBInfo->Part1Port,
-							0x1E, 0x20); /* Power on */
-				}
-			}
+		if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { /* 301LV/302LV only */
+			/* Set 301LV Capability */
+			xgifb_reg_set(pVBInfo->Part4Port, 0x24,
+					(unsigned char) (tempcx & 0x1F));
 		}
+		/* VB Driving */
+		xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D,
+				~((EnableVBCLKDRVLOW | EnablePLLSPLOW) >> 8),
+				(unsigned short) ((tempcx & (EnableVBCLKDRVLOW
+						| EnablePLLSPLOW)) >> 8));
+	}
 
-		if (!(pVBInfo->SetFlag & DisableChB)) {
-			if ((pVBInfo->SetFlag & EnableChB) || (pVBInfo->VBInfo
-					& (SetCRT2ToLCD | SetCRT2ToTV
-							| SetCRT2ToRAMDAC))) {
-				tempah = (unsigned char) XGINew_GetReg1(
-						pVBInfo->P3c4, 0x32);
-				tempah &= 0xDF;
-				if (pVBInfo->VBInfo & SetInSlaveMode) {
-					if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC))
-						tempah |= 0x20;
-				}
-				XGINew_SetReg1(pVBInfo->P3c4, 0x32, tempah);
-				XGINew_SetRegOR(pVBInfo->P3c4, 0x1E, 0x20);
-
-				tempah = (unsigned char) XGINew_GetReg1(
-						pVBInfo->Part1Port, 0x2E);
-
-				if (!(tempah & 0x80))
-					XGINew_SetRegOR(pVBInfo->Part1Port,
-							0x2E, 0x80); /* BVBDOENABLE = 1 */
-
-				XGINew_SetRegAND(pVBInfo->Part1Port, 0x00, 0x7F); /* BScreenOFF = 0 */
-			}
-		}
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		if (pVBInfo->VBInfo & SetCRT2ToLCD)
+			XGI_SetLCDCap_B(tempcx, pVBInfo);
+		else if (pVBInfo->VBInfo & SetCRT2ToLCDA)
+			XGI_SetLCDCap_A(tempcx, pVBInfo);
 
-		if ((pVBInfo->SetFlag & (EnableChA | EnableChB))
-				|| (!(pVBInfo->VBInfo & DisableCRT2Display))) {
-			XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x00, ~0xE0,
-					0x20); /* shampoo 0129 */
-			if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
-				if (!XGI_DisableChISLCD(pVBInfo)) {
-					if (XGI_EnableChISLCD(pVBInfo)
-							|| (pVBInfo->VBInfo
-									& (SetCRT2ToLCD
-											| SetCRT2ToLCDA)))
-						XGINew_SetRegAND(
-								pVBInfo->Part4Port,
-								0x2A, 0x7F); /* LVDS PLL power on */
-				}
-				XGINew_SetRegAND(pVBInfo->Part4Port, 0x30, 0x7F); /* LVDS Driver power on */
-			}
+		if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
+			if (tempcx & EnableSpectrum)
+				SetSpectrum(pVBInfo);
 		}
+	} else {
+		/* LVDS,CH7017 */
+		XGI_SetLCDCap_A(tempcx, pVBInfo);
+	}
+}
 
-		tempah = 0x00;
-
-		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
-			tempah = 0xc0;
-
-			if (!(pVBInfo->VBInfo & SetSimuScanMode)) {
-				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-					if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
-						tempah = tempah & 0x40;
-						if (pVBInfo->VBInfo
-								& SetCRT2ToLCDA)
-							tempah = tempah ^ 0xC0;
-
-						if (pVBInfo->SetFlag
-								& DisableChB)
-							tempah &= 0xBF;
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetAntiFlicker */
+/* Input : */
+/* Output : */
+/* Description : Set TV Customized Param. */
+/* --------------------------------------------------------------------- */
+static void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, index;
 
-						if (pVBInfo->SetFlag
-								& DisableChA)
-							tempah &= 0x7F;
+	unsigned char tempah;
 
-						if (pVBInfo->SetFlag
-								& EnableChB)
-							tempah |= 0x40;
+	if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))
+		return;
 
-						if (pVBInfo->SetFlag
-								& EnableChA)
-							tempah |= 0x80;
-					}
-				}
-			}
-		}
+	tempbx = XGI_GetTVPtrIndex(pVBInfo);
+	tempbx &= 0xFE;
 
-		XGINew_SetRegOR(pVBInfo->Part4Port, 0x1F, tempah); /* EnablePart4_1F */
+	if (ModeNo <= 0x13)
+		index = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
+	else
+		index = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
 
-		if (pVBInfo->SetFlag & Win9xDOSMode) {
-			XGI_DisplayOn(HwDeviceExtension, pVBInfo);
-			return;
-		}
+	tempbx += index;
+	tempah = TVAntiFlickList[tempbx];
+	tempah = tempah << 4;
 
-		if (!(pVBInfo->SetFlag & DisableChA)) {
-			XGI_VBLongWait(pVBInfo);
-			if (!(pVBInfo->SetFlag & GatingCRT)) {
-				XGI_DisableGatingCRT(HwDeviceExtension, pVBInfo);
-				XGI_DisplayOn(HwDeviceExtension, pVBInfo);
-				XGI_VBLongWait(pVBInfo);
-			}
-		}
-	} /* 301 */
-	else { /* LVDS */
-		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD
-				| SetCRT2ToLCDA))
-			XGINew_SetRegOR(pVBInfo->Part1Port, 0x1E, 0x20); /* enable CRT2 */
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
+}
 
-		tempah = (unsigned char) XGINew_GetReg1(pVBInfo->Part1Port,
-				0x2E);
-		if (!(tempah & 0x80))
-			XGINew_SetRegOR(pVBInfo->Part1Port, 0x2E, 0x80); /* BVBDOENABLE = 1 */
+static void XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, index;
 
-		XGINew_SetRegAND(pVBInfo->Part1Port, 0x00, 0x7F);
-		XGI_DisplayOn(HwDeviceExtension, pVBInfo);
-	} /* End of VB */
+	unsigned char tempah;
 
-	if (HwDeviceExtension->jChipType < XG40) {
-		if (!XGI_EnableChISLCD(pVBInfo)) {
-			if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-				if (XGI_BacklightByDrv(pVBInfo))
-					return;
-			} else
-				return;
-		}
+	tempbx = XGI_GetTVPtrIndex(pVBInfo);
+	tempbx &= 0xFE;
 
-		if (pVBInfo->LCDInfo & SetPWDEnable) {
-			XGI_FirePWDEnable(pVBInfo);
-			return;
-		}
+	if (ModeNo <= 0x13)
+		index = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
+	else
+		index = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
 
-		XGI_SetPanelDelay(2, pVBInfo);
+	tempbx += index;
+	tempah = TVEdgeList[tempbx];
+	tempah = tempah << 5;
 
-		if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) {
-			tempah = 0x01;
-			tempbl = 0xFE; /* turn on backlght */
-		} else {
-			tempbl = 0xF7;
-			tempah = 0x00;
-		}
-		XGI_SetPanelPower(tempah, tempbl, pVBInfo);
-	}
+	xgifb_reg_and_or(pVBInfo->Part2Port, 0x3A, 0x1F, tempah);
 }
 
-void XGI_DisableBridge(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+static void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
 {
-	unsigned short tempax, tempbx, tempah = 0, tempbl = 0;
+	unsigned short tempbx;
 
-	if (pVBInfo->SetFlag == Win9xDOSMode)
-		return;
+	unsigned char tempcl, tempch;
 
-	if (HwDeviceExtension->jChipType < XG40) {
-		if ((!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)))
-				|| (XGI_DisableChISLCD(pVBInfo))) {
-			if (!XGI_IsLCDON(pVBInfo)) {
-				if (pVBInfo->LCDInfo & SetPWDEnable)
-					XGI_EnablePWD(pVBInfo);
-				else {
-					pVBInfo->LCDInfo &= ~SetPWDEnable;
-					XGI_DisablePWD(pVBInfo);
-					if (pVBInfo->VBType & (VB_XGI301LV
-							| VB_XGI302LV
-							| VB_XGI301C)) {
-						tempbx = 0xFE; /* not 01h */
-						tempax = 0;
-					} else {
-						tempbx = 0xF7; /* not 08h */
-						tempax = 0x08;
-					}
-					XGI_SetPanelPower(tempax, tempbx,
-							pVBInfo);
-					XGI_SetPanelDelay(3, pVBInfo);
-				}
-			} /* end if (!XGI_IsLCDON(pVBInfo)) */
-		}
-	}
+	unsigned long tempData;
 
-	/*
-	if (CH7017) {
-		if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2toLCDA)) || (XGI_DisableChISLCD(pVBInfo))) {
-			if (!XGI_IsLCDON(pVBInfo)) {
-				if (DISCHARGE) {
-					tempbx = XGINew_GetCH7005(0x61);
-					if (tempbx < 0x01) // first time we power up
-						XGINew_SetCH7005(0x0066); // and disable power sequence
-					else
-						XGINew_SetCH7005(0x5f66); // leave VDD on - disable power
-				}
-			}
-		}
-	}
-	*/
+	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
+	tempData = TVPhaseList[tempbx];
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		tempah = 0x3F;
-		if (!(pVBInfo->VBInfo & (DisableCRT2Display | SetSimuScanMode))) {
-			if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-				if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
-					tempah = 0x7F; /* Disable Channel A */
-					if (!(pVBInfo->VBInfo & SetCRT2ToLCDA))
-						tempah = 0xBF; /* Disable Channel B */
+	xgifb_reg_set(pVBInfo->Part2Port, 0x31, (unsigned short) (tempData
+			& 0x000000FF));
+	xgifb_reg_set(pVBInfo->Part2Port, 0x32, (unsigned short) ((tempData
+			& 0x0000FF00) >> 8));
+	xgifb_reg_set(pVBInfo->Part2Port, 0x33, (unsigned short) ((tempData
+			& 0x00FF0000) >> 16));
+	xgifb_reg_set(pVBInfo->Part2Port, 0x34, (unsigned short) ((tempData
+			& 0xFF000000) >> 24));
+}
 
-					if (pVBInfo->SetFlag & DisableChB)
-						tempah &= 0xBF; /* force to disable Cahnnel */
+static void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, index;
 
-					if (pVBInfo->SetFlag & DisableChA)
-						tempah &= 0x7F; /* Force to disable Channel B */
-				}
-			}
-		}
+	unsigned char tempcl, tempch, tempal, *filterPtr;
 
-		XGINew_SetRegAND(pVBInfo->Part4Port, 0x1F, tempah); /* disable part4_1f */
+	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
 
-		if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
-			if (((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)))
-					|| (XGI_DisableChISLCD(pVBInfo))
-					|| (XGI_IsLCDON(pVBInfo)))
-				XGINew_SetRegOR(pVBInfo->Part4Port, 0x30, 0x80); /* LVDS Driver power down */
-		}
+	switch (tempbx) {
+	case 0x00:
+	case 0x04:
+		filterPtr = NTSCYFilter1;
+		break;
 
-		if ((pVBInfo->SetFlag & DisableChA) || (pVBInfo->VBInfo
-				& (DisableCRT2Display | SetCRT2ToLCDA
-						| SetSimuScanMode))) {
-			if (pVBInfo->SetFlag & GatingCRT)
-				XGI_EnableGatingCRT(HwDeviceExtension, pVBInfo);
-			XGI_DisplayOff(HwDeviceExtension, pVBInfo);
-		}
+	case 0x01:
+		filterPtr = PALYFilter1;
+		break;
 
-		if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-			if ((pVBInfo->SetFlag & DisableChA) || (pVBInfo->VBInfo
-					& SetCRT2ToLCDA))
-				XGINew_SetRegAND(pVBInfo->Part1Port, 0x1e, 0xdf); /* Power down */
-		}
+	case 0x02:
+	case 0x05:
+	case 0x0D:
+		filterPtr = PALMYFilter1;
+		break;
 
-		XGINew_SetRegAND(pVBInfo->P3c4, 0x32, 0xdf); /* disable TV as primary VGA swap */
+	case 0x03:
+		filterPtr = PALNYFilter1;
+		break;
 
-		if ((pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToDualEdge)))
-			XGINew_SetRegAND(pVBInfo->Part2Port, 0x00, 0xdf);
+	case 0x08:
+	case 0x0C:
+		filterPtr = NTSCYFilter2;
+		break;
 
-		if ((pVBInfo->SetFlag & DisableChB) || (pVBInfo->VBInfo
-				& (DisableCRT2Display | SetSimuScanMode))
-				|| ((!(pVBInfo->VBInfo & SetCRT2ToLCDA))
-						&& (pVBInfo->VBInfo
-								& (SetCRT2ToRAMDAC
-										| SetCRT2ToLCD
-										| SetCRT2ToTV))))
-			XGINew_SetRegOR(pVBInfo->Part1Port, 0x00, 0x80); /* BScreenOff=1 */
+	case 0x0A:
+		filterPtr = PALMYFilter2;
+		break;
 
-		if ((pVBInfo->SetFlag & DisableChB) || (pVBInfo->VBInfo
-				& (DisableCRT2Display | SetSimuScanMode))
-				|| (!(pVBInfo->VBInfo & SetCRT2ToLCDA))
-				|| (pVBInfo->VBInfo & (SetCRT2ToRAMDAC
-						| SetCRT2ToLCD | SetCRT2ToTV))) {
-			tempah = XGINew_GetReg1(pVBInfo->Part1Port, 0x00); /* save Part1 index 0 */
-			XGINew_SetRegOR(pVBInfo->Part1Port, 0x00, 0x10); /* BTDAC = 1, avoid VB reset */
-			XGINew_SetRegAND(pVBInfo->Part1Port, 0x1E, 0xDF); /* disable CRT2 */
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x00, tempah); /* restore Part1 index 0 */
-		}
-	} else { /* {301} */
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToTV)) {
-			XGINew_SetRegOR(pVBInfo->Part1Port, 0x00, 0x80); /* BScreenOff=1 */
-			XGINew_SetRegAND(pVBInfo->Part1Port, 0x1E, 0xDF); /* Disable CRT2 */
-			XGINew_SetRegAND(pVBInfo->P3c4, 0x32, 0xDF); /* Disable TV asPrimary VGA swap */
-		}
+	case 0x0B:
+		filterPtr = PALNYFilter2;
+		break;
 
-		if (pVBInfo->VBInfo & (DisableCRT2Display | SetCRT2ToLCDA
-				| SetSimuScanMode))
-			XGI_DisplayOff(HwDeviceExtension, pVBInfo);
-	}
+	case 0x09:
+		filterPtr = PALYFilter2;
+		break;
 
-	if (HwDeviceExtension->jChipType < XG40) {
-		if (!(pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA))
-				|| (XGI_DisableChISLCD(pVBInfo))
-				|| (XGI_IsLCDON(pVBInfo))) {
-			if (pVBInfo->LCDInfo & SetPWDEnable) {
-				if (pVBInfo->LCDInfo & SetPWDEnable)
-					XGI_BacklightByDrv(pVBInfo);
-				else {
-					XGI_SetPanelDelay(4, pVBInfo);
-					if (pVBInfo->VBType & VB_XGI301LV) {
-						tempbl = 0xFD;
-						tempah = 0x00;
-					} else {
-						tempbl = 0xFB;
-						tempah = 0x04;
-					}
-				}
-			}
-			XGI_SetPanelPower(tempah, tempbl, pVBInfo);
-		}
+	default:
+		return;
 	}
-}
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_GetTVPtrIndex */
-/* Input : */
-/* Output : */
-/* Description : bx 0 : ExtNTSC */
-/* 1 : StNTSC */
-/* 2 : ExtPAL */
-/* 3 : StPAL */
-/* 4 : ExtHiTV */
-/* 5 : StHiTV */
-/* 6 : Ext525i */
-/* 7 : St525i */
-/* 8 : Ext525p */
-/* 9 : St525p */
-/* A : Ext750p */
-/* B : St750p */
-/* --------------------------------------------------------------------- */
-unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
-{
-	unsigned short tempbx = 0;
+	if (ModeNo <= 0x13)
+		tempal = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
+	else
+		tempal
+				= pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
 
-	if (pVBInfo->TVInfo & SetPALTV)
-		tempbx = 2;
-	if (pVBInfo->TVInfo & SetYPbPrMode1080i)
-		tempbx = 4;
-	if (pVBInfo->TVInfo & SetYPbPrMode525i)
-		tempbx = 6;
-	if (pVBInfo->TVInfo & SetYPbPrMode525p)
-		tempbx = 8;
-	if (pVBInfo->TVInfo & SetYPbPrMode750p)
-		tempbx = 10;
-	if (pVBInfo->TVInfo & TVSimuMode)
-		tempbx++;
+	if (tempcl == 0)
+		index = tempal * 4;
+	else
+		index = tempal * 7;
 
-	return tempbx;
+	if ((tempcl == 0) && (tempch == 1)) {
+		xgifb_reg_set(pVBInfo->Part2Port, 0x35, 0);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x36, 0);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x37, 0);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
+	} else {
+		xgifb_reg_set(pVBInfo->Part2Port, 0x35, filterPtr[index++]);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x36, filterPtr[index++]);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x37, filterPtr[index++]);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
+	}
+
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		xgifb_reg_set(pVBInfo->Part2Port, 0x48, filterPtr[index++]);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x49, filterPtr[index++]);
+		xgifb_reg_set(pVBInfo->Part2Port, 0x4A, filterPtr[index++]);
+	}
 }
 
 /* --------------------------------------------------------------------- */
@@ -7906,7 +7424,7 @@ unsigned short XGI_GetTVPtrIndex(struct vb_device_info *pVBInfo)
 /* Output : */
 /* Description : Customized Param. for 301 */
 /* --------------------------------------------------------------------- */
-void XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
 	if (pVBInfo->SetFlag & Win9xDOSMode)
@@ -7929,985 +7447,1029 @@ void XGI_OEM310Setting(unsigned short ModeNo, unsigned short ModeIdIndex,
 	}
 }
 
-void XGI_SetDelayComp(struct vb_device_info *pVBInfo)
+/* --------------------------------------------------------------------- */
+/* Function : XGI_SetCRT2ModeRegs */
+/* Input : */
+/* Output : */
+/* Description : Origin code for crt2group */
+/* --------------------------------------------------------------------- */
+void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned short index;
+	unsigned short tempbl;
+	short tempcl;
 
-	unsigned char tempah, tempbl, tempbh;
+	unsigned char tempah;
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA
-				| SetCRT2ToTV | SetCRT2ToRAMDAC)) {
-			tempbl = 0;
-			tempbh = 0;
+	/* xgifb_reg_set(pVBInfo->Part1Port, 0x03, 0x00); // fix write part1 index 0 BTDRAM bit Bug */
+	tempah = 0;
+	if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
+		tempah = xgifb_reg_get(pVBInfo->Part1Port, 0x00);
+		tempah &= ~0x10; /* BTRAMDAC */
+		tempah |= 0x40; /* BTRAM */
 
-			index = XGI_GetTVPtrIndex(pVBInfo); /* Get TV Delay */
-			tempbl = pVBInfo->XGI_TVDelayList[index];
+		if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
+				| SetCRT2ToLCD)) {
+			tempah = 0x40; /* BTDRAM */
+			if (ModeNo > 0x13) {
+				tempcl = pVBInfo->ModeType;
+				tempcl -= ModeVGA;
+				if (tempcl >= 0) {
+					tempah = (0x008 >> tempcl); /* BT Color */
+					if (tempah == 0)
+						tempah = 1;
+					tempah |= 0x040;
+				}
+			}
+			if (pVBInfo->VBInfo & SetInSlaveMode)
+				tempah ^= 0x50; /* BTDAC */
+		}
+	}
 
-			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
-					| VB_XGI301LV | VB_XGI302LV
-					| VB_XGI301C))
-				tempbl = pVBInfo->XGI_TVDelayList2[index];
+	/* 0210 shampoo
+	if (pVBInfo->VBInfo & DisableCRT2Display) {
+		tempah = 0;
+	}
 
-			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
-				tempbl = tempbl >> 4;
-			/*
-			if (pVBInfo->VBInfo & SetCRT2ToRAMDAC)
-				tempbl = CRT2Delay1;	// Get CRT2 Delay
-			if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV | VB_XGI302LV | VB_XGI301C))
-				tempbl = CRT2Delay2;
-			*/
-			if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
-				index = XGI_GetLCDCapPtr(pVBInfo); /* Get LCD Delay */
-				tempbh = pVBInfo->LCDCapList[index].LCD_DelayCompensation;
+	xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
+	if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD)) {
+		tempcl = pVBInfo->ModeType;
+		if (ModeNo > 0x13) {
+			tempcl -= ModeVGA;
+			if ((tempcl > 0) || (tempcl == 0)) {
+				tempah=(0x008>>tempcl) ;
+				if (tempah == 0)
+					tempah = 1;
+				tempah |= 0x040;
+			}
+		} else {
+			tempah = 0x040;
+		}
 
-				if (!(pVBInfo->VBInfo & SetCRT2ToLCDA))
-					tempbl = tempbh;
+		if (pVBInfo->VBInfo & SetInSlaveMode) {
+			tempah = (tempah ^ 0x050);
+		}
+	}
+	*/
+
+	xgifb_reg_set(pVBInfo->Part1Port, 0x00, tempah);
+	tempah = 0x08;
+	tempbl = 0xf0;
+
+	if (pVBInfo->VBInfo & DisableCRT2Display) {
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl, tempah);
+	} else {
+		tempah = 0x00;
+		tempbl = 0xff;
+
+		if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
+				| SetCRT2ToLCD | SetCRT2ToLCDA)) {
+			if ((pVBInfo->VBInfo & SetCRT2ToLCDA)
+					&& (!(pVBInfo->VBInfo & SetSimuScanMode))) {
+				tempbl &= 0xf7;
+				tempah |= 0x01;
+				xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e,
+						tempbl, tempah);
+			} else {
+				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+					tempbl &= 0xf7;
+					tempah |= 0x01;
+				}
+
+				if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC
+						| SetCRT2ToTV | SetCRT2ToLCD)) {
+					tempbl &= 0xf8;
+					tempah = 0x01;
+
+					if (!(pVBInfo->VBInfo & SetInSlaveMode))
+						tempah |= 0x02;
+
+					if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
+						tempah = tempah ^ 0x05;
+						if (!(pVBInfo->VBInfo
+								& SetCRT2ToLCD))
+							tempah = tempah ^ 0x01;
+					}
+
+					if (!(pVBInfo->VBInfo
+							& SetCRT2ToDualEdge))
+						tempah |= 0x08;
+					xgifb_reg_and_or(pVBInfo->Part1Port,
+							0x2e, tempbl, tempah);
+				} else {
+					xgifb_reg_and_or(pVBInfo->Part1Port,
+							0x2e, tempbl, tempah);
+				}
+			}
+		} else {
+			xgifb_reg_and_or(pVBInfo->Part1Port, 0x2e, tempbl,
+					tempah);
+		}
+	}
+
+	if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD
+			| SetCRT2ToLCDA)) {
+		tempah &= (~0x08);
+		if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo
+				& SetInSlaveMode))) {
+			tempah |= 0x010;
+		}
+		tempah |= 0x080;
+
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			/* if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))) { */
+			tempah |= 0x020;
+			if (ModeNo > 0x13) {
+				if (pVBInfo->VBInfo & DriverMode)
+					tempah = tempah ^ 0x20;
 			}
+			/* } */
+		}
 
-			tempbl &= 0x0F;
-			tempbh &= 0xF0;
-			tempah = XGINew_GetReg1(pVBInfo->Part1Port, 0x2D);
+		xgifb_reg_and_or(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
+		tempah = 0;
 
-			if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToLCD
-					| SetCRT2ToTV)) { /* Channel B */
-				tempah &= 0xF0;
-				tempah |= tempbl;
-			}
+		if (pVBInfo->LCDInfo & SetLCDDualLink)
+			tempah |= 0x40;
 
-			if (pVBInfo->VBInfo & SetCRT2ToLCDA) { /* Channel A */
-				tempah &= 0x0F;
-				tempah |= tempbh;
-			}
-			XGINew_SetReg1(pVBInfo->Part1Port, 0x2D, tempah);
-		}
-	} else if (pVBInfo->IF_DEF_LVDS == 1) {
-		tempbl = 0;
-		tempbh = 0;
-		if (pVBInfo->VBInfo & SetCRT2ToLCD) {
-			tempah
-					= pVBInfo->LCDCapList[XGI_GetLCDCapPtr(
-							pVBInfo)].LCD_DelayCompensation; /* / Get LCD Delay */
-			tempah &= 0x0f;
-			tempah = tempah << 4;
-			XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2D, 0x0f,
-					tempah);
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			/* if ((!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)) && (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)))) { */
+			if (pVBInfo->TVInfo & RPLLDIV2XO)
+				tempah |= 0x40;
+			/* } */
 		}
-	}
-}
 
-void XGI_SetLCDCap(struct vb_device_info *pVBInfo)
-{
-	unsigned short tempcx;
+		if ((pVBInfo->LCDResInfo == Panel1280x1024)
+				|| (pVBInfo->LCDResInfo == Panel1280x1024x75))
+			tempah |= 0x80;
 
-	tempcx = pVBInfo->LCDCapList[XGI_GetLCDCapPtr(pVBInfo)].LCD_Capability;
+		if (pVBInfo->LCDResInfo == Panel1280x960)
+			tempah |= 0x80;
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		if (pVBInfo->VBType & (VB_XGI301LV | VB_XGI302LV | VB_XGI301C)) { /* 301LV/302LV only */
-			/* Set 301LV Capability */
-			XGINew_SetReg1(pVBInfo->Part4Port, 0x24,
-					(unsigned char) (tempcx & 0x1F));
-		}
-		/* VB Driving */
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x0D,
-				~((EnableVBCLKDRVLOW | EnablePLLSPLOW) >> 8),
-				(unsigned short) ((tempcx & (EnableVBCLKDRVLOW
-						| EnablePLLSPLOW)) >> 8));
+		xgifb_reg_set(pVBInfo->Part4Port, 0x0C, tempah);
 	}
 
 	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
 			| VB_XGI302LV | VB_XGI301C)) {
-		if (pVBInfo->VBInfo & SetCRT2ToLCD)
-			XGI_SetLCDCap_B(tempcx, pVBInfo);
-		else if (pVBInfo->VBInfo & SetCRT2ToLCDA)
-			XGI_SetLCDCap_A(tempcx, pVBInfo);
+		tempah = 0;
+		tempbl = 0xfb;
 
-		if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
-			if (tempcx & EnableSpectrum)
-				SetSpectrum(pVBInfo);
+		if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
+			tempbl = 0xff;
+			if (pVBInfo->VBInfo & SetCRT2ToLCDA)
+				tempah |= 0x04; /* shampoo 0129 */
 		}
-	} else {
-		/* LVDS,CH7017 */
-		XGI_SetLCDCap_A(tempcx, pVBInfo);
-	}
-}
 
-void XGI_SetLCDCap_A(unsigned short tempcx, struct vb_device_info *pVBInfo)
-{
-	unsigned short temp;
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x13, tempbl, tempah);
+		tempah = 0x00;
+		tempbl = 0xcf;
+		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
+			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
+				tempah |= 0x30;
+		}
 
-	temp = XGINew_GetReg1(pVBInfo->P3d4, 0x37);
+		xgifb_reg_and_or(pVBInfo->Part1Port, 0x2c, tempbl, tempah);
+		tempah = 0;
+		tempbl = 0x3f;
 
-	if (temp & LCDRGB18Bit) {
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0x0F,
-				(unsigned short) (0x20 | (tempcx & 0x00C0))); /* Enable Dither */
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
-	} else {
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0x0F,
-				(unsigned short) (0x30 | (tempcx & 0x00C0)));
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
+		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
+			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
+				tempah |= 0xc0;
+		}
+		xgifb_reg_and_or(pVBInfo->Part4Port, 0x21, tempbl, tempah);
 	}
 
-	/*
-	if (tempcx & EnableLCD24bpp) {	// 24bits
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0x0F, (unsigned short)(0x30 | (tempcx&0x00C0)));
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x1A, 0x7F, 0x00);
-	} else {
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x19, 0x0F, (unsigned short)(0x20 | (tempcx&0x00C0))); // Enable Dither
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x1A, 0x7F, 0x80);
+	tempah = 0;
+	tempbl = 0x7f;
+	if (!(pVBInfo->VBInfo & SetCRT2ToLCDA)) {
+		tempbl = 0xff;
+		if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
+			tempah |= 0x80;
 	}
-	*/
-}
-
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetLCDCap_B */
-/* Input : cx -> LCD Capability */
-/* Output : */
-/* Description : */
-/* --------------------------------------------------------------------- */
-void XGI_SetLCDCap_B(unsigned short tempcx, struct vb_device_info *pVBInfo)
-{
-	if (tempcx & EnableLCD24bpp) /* 24bits */
-		XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1A, 0xE0,
-				(unsigned short) (((tempcx & 0x00ff) >> 6)
-						| 0x0c));
-	else
-		XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x1A, 0xE0,
-				(unsigned short) (((tempcx & 0x00ff) >> 6)
-						| 0x18)); /* Enable Dither */
-}
-
-void SetSpectrum(struct vb_device_info *pVBInfo)
-{
-	unsigned short index;
-
-	index = XGI_GetLCDCapPtr(pVBInfo);
 
-	XGINew_SetRegAND(pVBInfo->Part4Port, 0x30, 0x8F); /* disable down spectrum D[4] */
-	XGI_LongWait(pVBInfo);
-	XGINew_SetRegOR(pVBInfo->Part4Port, 0x30, 0x20); /* reset spectrum */
-	XGI_LongWait(pVBInfo);
+	xgifb_reg_and_or(pVBInfo->Part4Port, 0x23, tempbl, tempah);
 
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x31,
-			pVBInfo->LCDCapList[index].Spectrum_31);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x32,
-			pVBInfo->LCDCapList[index].Spectrum_32);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x33,
-			pVBInfo->LCDCapList[index].Spectrum_33);
-	XGINew_SetReg1(pVBInfo->Part4Port, 0x34,
-			pVBInfo->LCDCapList[index].Spectrum_34);
-	XGI_LongWait(pVBInfo);
-	XGINew_SetRegOR(pVBInfo->Part4Port, 0x30, 0x40); /* enable spectrum */
+	if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
+		if (pVBInfo->LCDInfo & SetLCDDualLink) {
+			xgifb_reg_or(pVBInfo->Part4Port, 0x27, 0x20);
+			xgifb_reg_or(pVBInfo->Part4Port, 0x34, 0x10);
+		}
+	}
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetAntiFlicker */
-/* Input : */
-/* Output : */
-/* Description : Set TV Customized Param. */
-/* --------------------------------------------------------------------- */
-void XGI_SetAntiFlicker(unsigned short ModeNo, unsigned short ModeIdIndex,
+static void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx, index;
-
-	unsigned char tempah;
-
-	if (pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))
-		return;
-
-	tempbx = XGI_GetTVPtrIndex(pVBInfo);
-	tempbx &= 0xFE;
+	unsigned short tempbx;
 
-	if (ModeNo <= 0x13)
-		index = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVFlickerIndex;
-	else
-		index = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVFlickerIndex;
+	tempbx = 0;
 
-	tempbx += index;
-	tempah = TVAntiFlickList[tempbx];
-	tempah = tempah << 4;
+	if (pVBInfo->VBInfo & SetCRT2ToLCDA)
+		tempbx = 0x08A0;
 
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x0A, 0x8F, tempah);
 }
 
-void XGI_SetEdgeEnhance(unsigned short ModeNo, unsigned short ModeIdIndex,
+void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx, index;
-
-	unsigned char tempah;
-
-	tempbx = XGI_GetTVPtrIndex(pVBInfo);
-	tempbx &= 0xFE;
-
-	if (ModeNo <= 0x13)
-		index = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVEdgeIndex;
-	else
-		index = pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVEdgeIndex;
-
-	tempbx += index;
-	tempah = TVEdgeList[tempbx];
-	tempah = tempah << 5;
-
-	XGINew_SetRegANDOR(pVBInfo->Part2Port, 0x3A, 0x1F, tempah);
+	unsigned short tempbx;
+	tempbx = 0;
 }
 
-void XGI_SetPhaseIncr(struct vb_device_info *pVBInfo)
+void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx;
-
-	unsigned char tempcl, tempch;
 
-	unsigned long tempData;
-
-	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
-	tempData = TVPhaseList[tempbx];
+	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01);
 
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x31, (unsigned short) (tempData
-			& 0x000000FF));
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x32, (unsigned short) ((tempData
-			& 0x0000FF00) >> 8));
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x33, (unsigned short) ((tempData
-			& 0x00FF0000) >> 16));
-	XGINew_SetReg1(pVBInfo->Part2Port, 0x34, (unsigned short) ((tempData
-			& 0xFF000000) >> 24));
 }
 
-void XGI_SetYFilter(unsigned short ModeNo, unsigned short ModeIdIndex,
+void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx, index;
 
-	unsigned char tempcl, tempch, tempal, *filterPtr;
+	xgifb_reg_and_or(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00);
 
-	XGI_GetTVPtrIndex2(&tempbx, &tempcl, &tempch, pVBInfo); /* bx, cl, ch */
+}
 
-	switch (tempbx) {
-	case 0x00:
-	case 0x04:
-		filterPtr = NTSCYFilter1;
-		break;
+unsigned char XGI_BridgeIsOn(struct vb_device_info *pVBInfo)
+{
+	unsigned short flag;
 
-	case 0x01:
-		filterPtr = PALYFilter1;
-		break;
+	if (pVBInfo->IF_DEF_LVDS == 1) {
+		return 1;
+	} else {
+		flag = xgifb_reg_get(pVBInfo->Part4Port, 0x00);
+		if ((flag == 1) || (flag == 2))
+			return 1; /* 301b */
+		else
+			return 0;
+	}
+}
 
-	case 0x02:
-	case 0x05:
-	case 0x0D:
-		filterPtr = PALMYFilter1;
-		break;
+void XGI_LongWait(struct vb_device_info *pVBInfo)
+{
+	unsigned short i;
 
-	case 0x03:
-		filterPtr = PALNYFilter1;
-		break;
+	i = xgifb_reg_get(pVBInfo->P3c4, 0x1F);
 
-	case 0x08:
-	case 0x0C:
-		filterPtr = NTSCYFilter2;
-		break;
+	if (!(i & 0xC0)) {
+		for (i = 0; i < 0xFFFF; i++) {
+			if (!(inb(pVBInfo->P3da) & 0x08))
+				break;
+		}
 
-	case 0x0A:
-		filterPtr = PALMYFilter2;
-		break;
+		for (i = 0; i < 0xFFFF; i++) {
+			if ((inb(pVBInfo->P3da) & 0x08))
+				break;
+		}
+	}
+}
 
-	case 0x0B:
-		filterPtr = PALNYFilter2;
-		break;
+static void XGI_VBLongWait(struct vb_device_info *pVBInfo)
+{
+	unsigned short tempal, temp, i, j;
+	return;
+	if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
+		temp = 0;
+		for (i = 0; i < 3; i++) {
+			for (j = 0; j < 100; j++) {
+				tempal = inb(pVBInfo->P3da);
+				if (temp & 0x01) { /* VBWaitMode2 */
+					if ((tempal & 0x08))
+						continue;
 
-	case 0x09:
-		filterPtr = PALYFilter2;
-		break;
+					if (!(tempal & 0x08))
+						break;
 
-	default:
-		return;
+				} else { /* VBWaitMode1 */
+					if (!(tempal & 0x08))
+						continue;
+
+					if ((tempal & 0x08))
+						break;
+				}
+			}
+			temp = temp ^ 0x01;
+		}
+	} else {
+		XGI_LongWait(pVBInfo);
 	}
+	return;
+}
 
-	if (ModeNo <= 0x13)
-		tempal = pVBInfo->SModeIDTable[ModeIdIndex].VB_StTVYFilterIndex;
-	else
-		tempal
-				= pVBInfo->EModeIDTable[ModeIdIndex].VB_ExtTVYFilterIndex;
+unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+		unsigned short ModeNo, unsigned short ModeIdIndex,
+		struct vb_device_info *pVBInfo)
+{
+	short LCDRefreshIndex[] = { 0x00, 0x00, 0x03, 0x01 },
+			LCDARefreshIndex[] = { 0x00, 0x00, 0x03, 0x01, 0x01,
+					0x01, 0x01 };
 
-	if (tempcl == 0)
-		index = tempal * 4;
+	unsigned short RefreshRateTableIndex, i, modeflag, index, temp;
+
+	if (ModeNo <= 0x13)
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
 	else
-		index = tempal * 7;
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
 
-	if ((tempcl == 0) && (tempch == 1)) {
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x35, 0);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x36, 0);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x37, 0);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
-	} else {
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x35, filterPtr[index++]);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x36, filterPtr[index++]);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x37, filterPtr[index++]);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x38, filterPtr[index++]);
+	if (pVBInfo->IF_DEF_CH7005 == 1) {
+		if (pVBInfo->VBInfo & SetCRT2ToTV) {
+			if (modeflag & HalfDCLK)
+				return 0;
+		}
 	}
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x48, filterPtr[index++]);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x49, filterPtr[index++]);
-		XGINew_SetReg1(pVBInfo->Part2Port, 0x4A, filterPtr[index++]);
-	}
-}
+	if (ModeNo < 0x14)
+		return 0xFFFF;
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_GetTVPtrIndex2 */
-/* Input : */
-/* Output : bx 0 : NTSC */
-/* 1 : PAL */
-/* 2 : PALM */
-/* 3 : PALN */
-/* 4 : NTSC1024x768 */
-/* 5 : PAL-M 1024x768 */
-/* 6-7: reserved */
-/* cl 0 : YFilter1 */
-/* 1 : YFilter2 */
-/* ch 0 : 301A */
-/* 1 : 301B/302B/301LV/302LV */
-/* Description : */
-/* --------------------------------------------------------------------- */
-void XGI_GetTVPtrIndex2(unsigned short *tempbx, unsigned char *tempcl,
-		unsigned char *tempch, struct vb_device_info *pVBInfo)
-{
-	*tempbx = 0;
-	*tempcl = 0;
-	*tempch = 0;
+	index = xgifb_reg_get(pVBInfo->P3d4, 0x33);
+	index = index >> pVBInfo->SelectCRT2Rate;
+	index &= 0x0F;
 
-	if (pVBInfo->TVInfo & SetPALTV)
-		*tempbx = 1;
+	if (pVBInfo->LCDInfo & LCDNonExpanding)
+		index = 0;
 
-	if (pVBInfo->TVInfo & SetPALMTV)
-		*tempbx = 2;
+	if (index > 0)
+		index--;
 
-	if (pVBInfo->TVInfo & SetPALNTV)
-		*tempbx = 3;
+	if (pVBInfo->SetFlag & ProgrammingCRT2) {
+		if (pVBInfo->IF_DEF_CH7005 == 1) {
+			if (pVBInfo->VBInfo & SetCRT2ToTV)
+				index = 0;
+		}
 
-	if (pVBInfo->TVInfo & NTSC1024x768) {
-		*tempbx = 4;
-		if (pVBInfo->TVInfo & SetPALMTV)
-			*tempbx = 5;
+		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) {
+			if (pVBInfo->IF_DEF_LVDS == 0) {
+				if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B
+						| VB_XGI301LV | VB_XGI302LV
+						| VB_XGI301C))
+					temp
+							= LCDARefreshIndex[pVBInfo->LCDResInfo
+									& 0x0F]; /* 301b */
+				else
+					temp
+							= LCDRefreshIndex[pVBInfo->LCDResInfo
+									& 0x0F];
+
+				if (index > temp)
+					index = temp;
+			} else {
+				index = 0;
+			}
+		}
 	}
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		if ((!(pVBInfo->VBInfo & SetInSlaveMode)) || (pVBInfo->TVInfo
-				& TVSimuMode)) {
-			*tempbx += 8;
-			*tempcl += 1;
+	RefreshRateTableIndex = pVBInfo->EModeIDTable[ModeIdIndex].REFindex;
+	ModeNo = pVBInfo->RefIndex[RefreshRateTableIndex].ModeID;
+	if (pXGIHWDE->jChipType >= XG20) { /* for XG20, XG21, XG27 */
+		/*
+		if (pVBInfo->RefIndex[RefreshRateTableIndex].Ext_InfoFlag & XG2xNotSupport) {
+			index++;
+		}
+		*/
+		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 800)
+				&& (pVBInfo->RefIndex[RefreshRateTableIndex].YRes
+						== 600)) {
+			index++;
+		}
+		/* Alan 10/19/2007; do the similiar adjustment like XGISearchCRT1Rate() */
+		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1024)
+				&& (pVBInfo->RefIndex[RefreshRateTableIndex].YRes
+						== 768)) {
+			index++;
+		}
+		if ((pVBInfo->RefIndex[RefreshRateTableIndex].XRes == 1280)
+				&& (pVBInfo->RefIndex[RefreshRateTableIndex].YRes
+						== 1024)) {
+			index++;
 		}
 	}
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C))
-		(*tempch)++;
+	i = 0;
+	do {
+		if (pVBInfo->RefIndex[RefreshRateTableIndex + i].ModeID
+				!= ModeNo)
+			break;
+		temp
+				= pVBInfo->RefIndex[RefreshRateTableIndex + i].Ext_InfoFlag;
+		temp &= ModeInfoFlag;
+		if (temp < pVBInfo->ModeType)
+			break;
+		i++;
+		index--;
+
+	} while (index != 0xFFFF);
+	if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
+		if (pVBInfo->VBInfo & SetInSlaveMode) {
+			temp
+					= pVBInfo->RefIndex[RefreshRateTableIndex
+							+ i - 1].Ext_InfoFlag;
+			if (temp & InterlaceMode)
+				i++;
+		}
+	}
+	i--;
+	if ((pVBInfo->SetFlag & ProgrammingCRT2)) {
+		temp = XGI_AjustCRT2Rate(ModeNo, ModeIdIndex,
+				RefreshRateTableIndex, &i, pVBInfo);
+	}
+	return RefreshRateTableIndex + i; /* return (0x01 | (temp1<<1)); */
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGI_SetCRT2ModeRegs */
-/* Input : */
-/* Output : */
-/* Description : Origin code for crt2group */
-/* --------------------------------------------------------------------- */
-void XGI_SetCRT2ModeRegs(unsigned short ModeNo,
+static void XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbl;
-	short tempcl;
+	unsigned short RefreshRateTableIndex;
+	/* unsigned short temp ; */
 
-	unsigned char tempah;
+	/* pVBInfo->SelectCRT2Rate = 0; */
 
-	/* XGINew_SetReg1(pVBInfo->Part1Port, 0x03, 0x00); // fix write part1 index 0 BTDRAM bit Bug */
-	tempah = 0;
-	if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
-		tempah = XGINew_GetReg1(pVBInfo->Part1Port, 0x00);
-		tempah &= ~0x10; /* BTRAMDAC */
-		tempah |= 0x40; /* BTRAM */
+	pVBInfo->SetFlag |= ProgrammingCRT2;
+	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
+			ModeIdIndex, pVBInfo);
+	XGI_GetLVDSResInfo(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_GetLVDSData(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_ModCRT1Regs(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+			HwDeviceExtension, pVBInfo);
+	XGI_SetLVDSRegs(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetCRT2ECLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+}
 
-		if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
-				| SetCRT2ToLCD)) {
-			tempah = 0x40; /* BTDRAM */
-			if (ModeNo > 0x13) {
-				tempcl = pVBInfo->ModeType;
-				tempcl -= ModeVGA;
-				if (tempcl >= 0) {
-					tempah = (0x008 >> tempcl); /* BT Color */
-					if (tempah == 0)
-						tempah = 1;
-					tempah |= 0x040;
-				}
-			}
-			if (pVBInfo->VBInfo & SetInSlaveMode)
-				tempah ^= 0x50; /* BTDAC */
-		}
-	}
+unsigned char XGI_SetCRT2Group301(unsigned short ModeNo,
+		struct xgi_hw_device_info *HwDeviceExtension,
+		struct vb_device_info *pVBInfo)
+{
+	unsigned short tempbx, ModeIdIndex, RefreshRateTableIndex;
 
-	/* 0210 shampoo
-	if (pVBInfo->VBInfo & DisableCRT2Display) {
-		tempah = 0;
-	}
+	tempbx = pVBInfo->VBInfo;
+	pVBInfo->SetFlag |= ProgrammingCRT2;
+	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
+	pVBInfo->SelectCRT2Rate = 4;
+	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
+			ModeIdIndex, pVBInfo);
+	XGI_SaveCRT2Info(ModeNo, pVBInfo);
+	XGI_GetCRT2ResInfo(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_GetCRT2Data(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_PreSetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension,
+			RefreshRateTableIndex, pVBInfo);
+	XGI_SetGroup1(ModeNo, ModeIdIndex, HwDeviceExtension,
+			RefreshRateTableIndex, pVBInfo);
+	XGI_SetLockRegs(ModeNo, ModeIdIndex, HwDeviceExtension,
+			RefreshRateTableIndex, pVBInfo);
+	XGI_SetGroup2(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+			HwDeviceExtension, pVBInfo);
+	XGI_SetLCDRegs(ModeNo, ModeIdIndex, HwDeviceExtension,
+			RefreshRateTableIndex, pVBInfo);
+	XGI_SetTap4Regs(pVBInfo);
+	XGI_SetGroup3(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_SetGroup4(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+			HwDeviceExtension, pVBInfo);
+	XGI_SetCRT2VCLK(ModeNo, ModeIdIndex, RefreshRateTableIndex, pVBInfo);
+	XGI_SetGroup5(ModeNo, ModeIdIndex, pVBInfo);
+	XGI_AutoThreshold(pVBInfo);
+	return 1;
+}
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x00, tempah);
-	if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD)) {
-		tempcl = pVBInfo->ModeType;
-		if (ModeNo > 0x13) {
-			tempcl -= ModeVGA;
-			if ((tempcl > 0) || (tempcl == 0)) {
-				tempah=(0x008>>tempcl) ;
-				if (tempah == 0)
-					tempah = 1;
-				tempah |= 0x040;
-			}
-		} else {
-			tempah = 0x040;
-		}
+void XGI_SenseCRT1(struct vb_device_info *pVBInfo)
+{
+	unsigned char CRTCData[17] = { 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81,
+			0x0B, 0x3E, 0xE9, 0x0B, 0xDF, 0xE7, 0x04, 0x00, 0x00,
+			0x05, 0x00 };
 
-		if (pVBInfo->VBInfo & SetInSlaveMode) {
-			tempah = (tempah ^ 0x050);
-		}
-	}
-	*/
+	unsigned char SR01 = 0, SR1F = 0, SR07 = 0, SR06 = 0;
 
-	XGINew_SetReg1(pVBInfo->Part1Port, 0x00, tempah);
-	tempah = 0x08;
-	tempbl = 0xf0;
+	unsigned char CR17, CR63, SR31;
+	unsigned short temp;
+	unsigned char DAC_TEST_PARMS[3] = { 0x0F, 0x0F, 0x0F };
 
-	if (pVBInfo->VBInfo & DisableCRT2Display) {
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2e, tempbl, tempah);
-	} else {
-		tempah = 0x00;
-		tempbl = 0xff;
+	int i;
+	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
 
-		if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV
-				| SetCRT2ToLCD | SetCRT2ToLCDA)) {
-			if ((pVBInfo->VBInfo & SetCRT2ToLCDA)
-					&& (!(pVBInfo->VBInfo & SetSimuScanMode))) {
-				tempbl &= 0xf7;
-				tempah |= 0x01;
-				XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2e,
-						tempbl, tempah);
-			} else {
-				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
-					tempbl &= 0xf7;
-					tempah |= 0x01;
-				}
+	/* [2004/05/06] Vicent to fix XG42 single LCD sense to CRT+LCD */
+	xgifb_reg_set(pVBInfo->P3d4, 0x57, 0x4A);
+	xgifb_reg_set(pVBInfo->P3d4, 0x53, (unsigned char) (xgifb_reg_get(
+			pVBInfo->P3d4, 0x53) | 0x02));
 
-				if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC
-						| SetCRT2ToTV | SetCRT2ToLCD)) {
-					tempbl &= 0xf8;
-					tempah = 0x01;
+	SR31 = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x31);
+	CR63 = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x63);
+	SR01 = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x01);
 
-					if (!(pVBInfo->VBInfo & SetInSlaveMode))
-						tempah |= 0x02;
+	xgifb_reg_set(pVBInfo->P3c4, 0x01, (unsigned char) (SR01 & 0xDF));
+	xgifb_reg_set(pVBInfo->P3d4, 0x63, (unsigned char) (CR63 & 0xBF));
 
-					if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC)) {
-						tempah = tempah ^ 0x05;
-						if (!(pVBInfo->VBInfo
-								& SetCRT2ToLCD))
-							tempah = tempah ^ 0x01;
-					}
+	CR17 = (unsigned char) xgifb_reg_get(pVBInfo->P3d4, 0x17);
+	xgifb_reg_set(pVBInfo->P3d4, 0x17, (unsigned char) (CR17 | 0x80));
 
-					if (!(pVBInfo->VBInfo
-							& SetCRT2ToDualEdge))
-						tempah |= 0x08;
-					XGINew_SetRegANDOR(pVBInfo->Part1Port,
-							0x2e, tempbl, tempah);
-				} else {
-					XGINew_SetRegANDOR(pVBInfo->Part1Port,
-							0x2e, tempbl, tempah);
-				}
-			}
-		} else {
-			XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2e, tempbl,
-					tempah);
-		}
-	}
+	SR1F = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x1F);
+	xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) (SR1F | 0x04));
 
-	if (pVBInfo->VBInfo & (SetCRT2ToRAMDAC | SetCRT2ToTV | SetCRT2ToLCD
-			| SetCRT2ToLCDA)) {
-		tempah &= (~0x08);
-		if ((pVBInfo->ModeType == ModeVGA) && (!(pVBInfo->VBInfo
-				& SetInSlaveMode))) {
-			tempah |= 0x010;
-		}
-		tempah |= 0x080;
+	SR07 = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x07);
+	xgifb_reg_set(pVBInfo->P3c4, 0x07, (unsigned char) (SR07 & 0xFB));
+	SR06 = (unsigned char) xgifb_reg_get(pVBInfo->P3c4, 0x06);
+	xgifb_reg_set(pVBInfo->P3c4, 0x06, (unsigned char) (SR06 & 0xC3));
 
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			/* if (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p))) { */
-			tempah |= 0x020;
-			if (ModeNo > 0x13) {
-				if (pVBInfo->VBInfo & DriverMode)
-					tempah = tempah ^ 0x20;
-			}
-			/* } */
-		}
+	xgifb_reg_set(pVBInfo->P3d4, 0x11, 0x00);
 
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x0D, ~0x0BF, tempah);
-		tempah = 0;
+	for (i = 0; i < 8; i++)
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) i, CRTCData[i]);
 
-		if (pVBInfo->LCDInfo & SetLCDDualLink)
-			tempah |= 0x40;
+	for (i = 8; i < 11; i++)
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 8),
+				CRTCData[i]);
 
-		if (pVBInfo->VBInfo & SetCRT2ToTV) {
-			/* if ((!(pVBInfo->VBInfo & SetCRT2ToHiVisionTV)) && (!(pVBInfo->TVInfo & (SetYPbPrMode525p | SetYPbPrMode750p)))) { */
-			if (pVBInfo->TVInfo & RPLLDIV2XO)
-				tempah |= 0x40;
-			/* } */
-		}
+	for (i = 11; i < 13; i++)
+		xgifb_reg_set(pVBInfo->P3d4, (unsigned short) (i + 4),
+				CRTCData[i]);
 
-		if ((pVBInfo->LCDResInfo == Panel1280x1024)
-				|| (pVBInfo->LCDResInfo == Panel1280x1024x75))
-			tempah |= 0x80;
+	for (i = 13; i < 16; i++)
+		xgifb_reg_set(pVBInfo->P3c4, (unsigned short) (i - 3),
+				CRTCData[i]);
 
-		if (pVBInfo->LCDResInfo == Panel1280x960)
-			tempah |= 0x80;
+	xgifb_reg_set(pVBInfo->P3c4, 0x0E, (unsigned char) (CRTCData[16]
+			& 0xE0));
 
-		XGINew_SetReg1(pVBInfo->Part4Port, 0x0C, tempah);
-	}
+	xgifb_reg_set(pVBInfo->P3c4, 0x31, 0x00);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x1B);
+	xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE1);
 
-	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
-			| VB_XGI302LV | VB_XGI301C)) {
-		tempah = 0;
-		tempbl = 0xfb;
+	outb(0x00, pVBInfo->P3c8);
 
-		if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
-			tempbl = 0xff;
-			if (pVBInfo->VBInfo & SetCRT2ToLCDA)
-				tempah |= 0x04; /* shampoo 0129 */
-		}
+	for (i = 0; i < 256; i++) {
+		outb((unsigned char) DAC_TEST_PARMS[0], (pVBInfo->P3c8 + 1));
+		outb((unsigned char) DAC_TEST_PARMS[1], (pVBInfo->P3c8 + 1));
+		outb((unsigned char) DAC_TEST_PARMS[2], (pVBInfo->P3c8 + 1));
+	}
 
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x13, tempbl, tempah);
-		tempah = 0x00;
-		tempbl = 0xcf;
-		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
-			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
-				tempah |= 0x30;
-		}
+	XGI_VBLongWait(pVBInfo);
+	XGI_VBLongWait(pVBInfo);
+	XGI_VBLongWait(pVBInfo);
 
-		XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2c, tempbl, tempah);
-		tempah = 0;
-		tempbl = 0x3f;
+	mdelay(1);
 
-		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
-			if (pVBInfo->VBInfo & SetCRT2ToDualEdge)
-				tempah |= 0xc0;
-		}
-		XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x21, tempbl, tempah);
-	}
+	XGI_WaitDisply(pVBInfo);
+	temp = inb(pVBInfo->P3c2);
 
-	tempah = 0;
-	tempbl = 0x7f;
-	if (!(pVBInfo->VBInfo & SetCRT2ToLCDA)) {
-		tempbl = 0xff;
-		if (!(pVBInfo->VBInfo & SetCRT2ToDualEdge))
-			tempah |= 0x80;
-	}
+	if (temp & 0x10)
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x20);
+	else
+		xgifb_reg_and_or(pVBInfo->P3d4, 0x32, 0xDF, 0x00);
 
-	XGINew_SetRegANDOR(pVBInfo->Part4Port, 0x23, tempbl, tempah);
+	/* alan, avoid display something, set BLACK DAC if not restore DAC */
+	outb(0x00, pVBInfo->P3c8);
 
-	if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
-		if (pVBInfo->LCDInfo & SetLCDDualLink) {
-			XGINew_SetRegOR(pVBInfo->Part4Port, 0x27, 0x20);
-			XGINew_SetRegOR(pVBInfo->Part4Port, 0x34, 0x10);
-		}
+	for (i = 0; i < 256; i++) {
+		outb(0, (pVBInfo->P3c8 + 1));
+		outb(0, (pVBInfo->P3c8 + 1));
+		outb(0, (pVBInfo->P3c8 + 1));
 	}
-}
-
-void XGI_CloseCRTC(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short tempbx;
-
-	tempbx = 0;
 
-	if (pVBInfo->VBInfo & SetCRT2ToLCDA)
-		tempbx = 0x08A0;
+	xgifb_reg_set(pVBInfo->P3c4, 0x01, SR01);
+	xgifb_reg_set(pVBInfo->P3d4, 0x63, CR63);
+	xgifb_reg_set(pVBInfo->P3c4, 0x31, SR31);
 
+	/* [2004/05/11] Vicent */
+	xgifb_reg_set(pVBInfo->P3d4, 0x53, (unsigned char) (xgifb_reg_get(
+			pVBInfo->P3d4, 0x53) & 0xFD));
+	xgifb_reg_set(pVBInfo->P3c4, 0x1F, (unsigned char) SR1F);
 }
 
-void XGI_OpenCRTC(struct xgi_hw_device_info *HwDeviceExtension,
+void XGI_EnableBridge(struct xgi_hw_device_info *HwDeviceExtension,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short tempbx;
-	tempbx = 0;
-}
+	unsigned short tempah;
 
-void XGI_GetRAMDAC2DATA(unsigned short ModeNo, unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct vb_device_info *pVBInfo)
-{
-	unsigned short tempax, tempbx, temp1, temp2, modeflag = 0, tempcx,
-			StandTableIndex, CRT1Index;
+	if (pVBInfo->SetFlag == Win9xDOSMode) {
+		if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+				| VB_XGI302LV | VB_XGI301C)) {
+			XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+			return;
+		} else
+			/* LVDS or CH7017 */
+			return;
+	}
 
-	pVBInfo->RVBHCMAX = 1;
-	pVBInfo->RVBHCFACT = 1;
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		if (!(pVBInfo->SetFlag & DisableChA)) {
+			if (pVBInfo->SetFlag & EnableChA) {
+				xgifb_reg_set(pVBInfo->Part1Port, 0x1E, 0x20); /* Power on */
+			} else {
+				if (pVBInfo->VBInfo & SetCRT2ToDualEdge) { /* SetCRT2ToLCDA ) */
+					xgifb_reg_set(pVBInfo->Part1Port,
+							0x1E, 0x20); /* Power on */
+				}
+			}
+		}
 
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-		StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
-		tempax = pVBInfo->StandTable[StandTableIndex].CRTC[0];
-		tempbx = pVBInfo->StandTable[StandTableIndex].CRTC[6];
-		temp1 = pVBInfo->StandTable[StandTableIndex].CRTC[7];
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
-		CRT1Index
-				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT1CRTC;
-		CRT1Index &= IndexMask;
-		temp1
-				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[0];
-		temp2
-				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[5];
-		tempax = (temp1 & 0xFF) | ((temp2 & 0x03) << 8);
-		tempbx
-				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[8];
-		tempcx
-				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[14]
-						<< 8;
-		tempcx &= 0x0100;
-		tempcx = tempcx << 2;
-		tempbx |= tempcx;
-		temp1
-				= (unsigned short) pVBInfo->XGINEWUB_CRT1Table[CRT1Index].CR[9];
-	}
+		if (!(pVBInfo->SetFlag & DisableChB)) {
+			if ((pVBInfo->SetFlag & EnableChB) || (pVBInfo->VBInfo
+					& (SetCRT2ToLCD | SetCRT2ToTV
+							| SetCRT2ToRAMDAC))) {
+				tempah = (unsigned char) xgifb_reg_get(
+						pVBInfo->P3c4, 0x32);
+				tempah &= 0xDF;
+				if (pVBInfo->VBInfo & SetInSlaveMode) {
+					if (!(pVBInfo->VBInfo & SetCRT2ToRAMDAC))
+						tempah |= 0x20;
+				}
+				xgifb_reg_set(pVBInfo->P3c4, 0x32, tempah);
+				xgifb_reg_or(pVBInfo->P3c4, 0x1E, 0x20);
 
-	if (temp1 & 0x01)
-		tempbx |= 0x0100;
+				tempah = (unsigned char) xgifb_reg_get(
+						pVBInfo->Part1Port, 0x2E);
 
-	if (temp1 & 0x20)
-		tempbx |= 0x0200;
-	tempax += 5;
+				if (!(tempah & 0x80))
+					xgifb_reg_or(pVBInfo->Part1Port,
+							0x2E, 0x80); /* BVBDOENABLE = 1 */
 
-	if (modeflag & Charx8Dot)
-		tempax *= 8;
-	else
-		tempax *= 9;
+				xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F); /* BScreenOFF = 0 */
+			}
+		}
 
-	pVBInfo->VGAHT = tempax;
-	pVBInfo->HT = tempax;
-	tempbx++;
-	pVBInfo->VGAVT = tempbx;
-	pVBInfo->VT = tempbx;
-}
+		if ((pVBInfo->SetFlag & (EnableChA | EnableChB))
+				|| (!(pVBInfo->VBInfo & DisableCRT2Display))) {
+			xgifb_reg_and_or(pVBInfo->Part2Port, 0x00, ~0xE0,
+					0x20); /* shampoo 0129 */
+			if (pVBInfo->VBType & (VB_XGI302LV | VB_XGI301C)) {
+				if (!XGI_DisableChISLCD(pVBInfo)) {
+					if (XGI_EnableChISLCD(pVBInfo)
+							|| (pVBInfo->VBInfo
+									& (SetCRT2ToLCD
+											| SetCRT2ToLCDA)))
+						xgifb_reg_and(
+								pVBInfo->Part4Port,
+								0x2A, 0x7F); /* LVDS PLL power on */
+				}
+				xgifb_reg_and(pVBInfo->Part4Port, 0x30, 0x7F); /* LVDS Driver power on */
+			}
+		}
 
-unsigned short XGI_GetColorDepth(unsigned short ModeNo,
-		unsigned short ModeIdIndex, struct vb_device_info *pVBInfo)
-{
-	unsigned short ColorDepth[6] = { 1, 2, 4, 4, 6, 8 };
-	short index;
-	unsigned short modeflag;
+		tempah = 0x00;
 
-	if (ModeNo <= 0x13)
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
-	else
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+		if (!(pVBInfo->VBInfo & DisableCRT2Display)) {
+			tempah = 0xc0;
 
-	index = (modeflag & ModeInfoFlag) - ModeEGA;
+			if (!(pVBInfo->VBInfo & SetSimuScanMode)) {
+				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+					if (pVBInfo->VBInfo & SetCRT2ToDualEdge) {
+						tempah = tempah & 0x40;
+						if (pVBInfo->VBInfo
+								& SetCRT2ToLCDA)
+							tempah = tempah ^ 0xC0;
 
-	if (index < 0)
-		index = 0;
+						if (pVBInfo->SetFlag
+								& DisableChB)
+							tempah &= 0xBF;
 
-	return ColorDepth[index];
-}
+						if (pVBInfo->SetFlag
+								& DisableChA)
+							tempah &= 0x7F;
 
-void XGI_UnLockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
+						if (pVBInfo->SetFlag
+								& EnableChB)
+							tempah |= 0x40;
 
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2f, 0xFF, 0x01);
+						if (pVBInfo->SetFlag
+								& EnableChA)
+							tempah |= 0x80;
+					}
+				}
+			}
+		}
 
-}
+		xgifb_reg_or(pVBInfo->Part4Port, 0x1F, tempah); /* EnablePart4_1F */
 
-void XGI_LockCRT2(struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
-{
+		if (pVBInfo->SetFlag & Win9xDOSMode) {
+			XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+			return;
+		}
 
-	XGINew_SetRegANDOR(pVBInfo->Part1Port, 0x2F, 0xFE, 0x00);
+		if (!(pVBInfo->SetFlag & DisableChA)) {
+			XGI_VBLongWait(pVBInfo);
+			if (!(pVBInfo->SetFlag & GatingCRT)) {
+				XGI_DisableGatingCRT(HwDeviceExtension, pVBInfo);
+				XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+				XGI_VBLongWait(pVBInfo);
+			}
+		}
+	} /* 301 */
+	else { /* LVDS */
+		if (pVBInfo->VBInfo & (SetCRT2ToTV | SetCRT2ToLCD
+				| SetCRT2ToLCDA))
+			xgifb_reg_or(pVBInfo->Part1Port, 0x1E, 0x20); /* enable CRT2 */
 
-}
+		tempah = (unsigned char) xgifb_reg_get(pVBInfo->Part1Port,
+				0x2E);
+		if (!(tempah & 0x80))
+			xgifb_reg_or(pVBInfo->Part1Port, 0x2E, 0x80); /* BVBDOENABLE = 1 */
 
-void XGINew_EnableCRT2(struct vb_device_info *pVBInfo)
-{
-	XGINew_SetRegANDOR(pVBInfo->P3c4, 0x1E, 0xFF, 0x20);
+		xgifb_reg_and(pVBInfo->Part1Port, 0x00, 0x7F);
+		XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+	} /* End of VB */
 }
 
-void XGINew_LCD_Wait_Time(unsigned char DelayTime,
+static void XGI_SetCRT1Group(struct xgi_hw_device_info *HwDeviceExtension,
+		unsigned short ModeNo, unsigned short ModeIdIndex,
 		struct vb_device_info *pVBInfo)
 {
-	unsigned short i, j;
+	unsigned short StandTableIndex, RefreshRateTableIndex, b3CC, temp;
 
-	unsigned long temp, flag;
+	unsigned short XGINew_P3cc = pVBInfo->P3cc;
 
-	flag = 0;
-	/* printk("XGINew_LCD_Wait_Time"); */
-	/* return; */
-	for (i = 0; i < DelayTime; i++) {
-		for (j = 0; j < 66; j++) {
-			temp = XGINew_GetReg3(0x61);
-			/* temp &= 0x10000000; */
-			temp &= 0x10;
-			if (temp == flag)
-				continue;
+	/* XGINew_CRT1Mode = ModeNo; // SaveModeID */
+	StandTableIndex = XGI_GetModePtr(ModeNo, ModeIdIndex, pVBInfo);
+	/* XGI_SetBIOSData(ModeNo, ModeIdIndex); */
+	/* XGI_ClearBankRegs(ModeNo, ModeIdIndex); */
+	XGI_SetSeqRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
+	XGI_SetMiscRegs(StandTableIndex, pVBInfo);
+	XGI_SetCRTCRegs(HwDeviceExtension, StandTableIndex, pVBInfo);
+	XGI_SetATTRegs(ModeNo, StandTableIndex, ModeIdIndex, pVBInfo);
+	XGI_SetGRCRegs(StandTableIndex, pVBInfo);
+	XGI_ClearExt1Regs(pVBInfo);
 
-			flag = temp;
-		}
+	/* if (pVBInfo->IF_DEF_ExpLink) */
+	if (HwDeviceExtension->jChipType == XG27) {
+		if (pVBInfo->IF_DEF_LVDS == 0)
+			XGI_SetDefaultVCLK(pVBInfo);
 	}
-}
 
-unsigned char XGI_BridgeIsOn(struct vb_device_info *pVBInfo)
-{
-	unsigned short flag;
+	temp = ~ProgrammingCRT2;
+	pVBInfo->SetFlag &= temp;
+	pVBInfo->SelectCRT2Rate = 0;
 
-	if (pVBInfo->IF_DEF_LVDS == 1) {
-		return 1;
-	} else {
-		flag = XGINew_GetReg1(pVBInfo->Part4Port, 0x00);
-		if ((flag == 1) || (flag == 2))
-			return 1; /* 301b */
-		else
-			return 0;
+	if (pVBInfo->VBType & (VB_XGI301B | VB_XGI302B | VB_XGI301LV
+			| VB_XGI302LV | VB_XGI301C)) {
+		if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA
+				| SetInSlaveMode)) {
+			pVBInfo->SetFlag |= ProgrammingCRT2;
+		}
 	}
-}
-
-void XGI_LongWait(struct vb_device_info *pVBInfo)
-{
-	unsigned short i;
 
-	i = XGINew_GetReg1(pVBInfo->P3c4, 0x1F);
-
-	if (!(i & 0xC0)) {
-		for (i = 0; i < 0xFFFF; i++) {
-			if (!(XGINew_GetReg2(pVBInfo->P3da) & 0x08))
-				break;
-		}
+	RefreshRateTableIndex = XGI_GetRatePtrCRT2(HwDeviceExtension, ModeNo,
+			ModeIdIndex, pVBInfo);
+	if (RefreshRateTableIndex != 0xFFFF) {
+		XGI_SetSync(RefreshRateTableIndex, pVBInfo);
+		XGI_SetCRT1CRTC(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				pVBInfo, HwDeviceExtension);
+		XGI_SetCRT1DE(HwDeviceExtension, ModeNo, ModeIdIndex,
+				RefreshRateTableIndex, pVBInfo);
+		XGI_SetCRT1Offset(ModeNo, ModeIdIndex, RefreshRateTableIndex,
+				HwDeviceExtension, pVBInfo);
+		XGI_SetCRT1VCLK(ModeNo, ModeIdIndex, HwDeviceExtension,
+				RefreshRateTableIndex, pVBInfo);
+	}
 
-		for (i = 0; i < 0xFFFF; i++) {
-			if ((XGINew_GetReg2(pVBInfo->P3da) & 0x08))
-				break;
+	if ((HwDeviceExtension->jChipType >= XG20)
+			&& (HwDeviceExtension->jChipType < XG27)) { /* fix H/W DCLK/2 bug */
+		if ((ModeNo == 0x00) | (ModeNo == 0x01)) {
+			xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x4E);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE9);
+			b3CC = (unsigned char) inb(XGINew_P3cc);
+			outb((b3CC |= 0x0C), XGINew_P3cc);
+		} else if ((ModeNo == 0x04) | (ModeNo == 0x05) | (ModeNo
+				== 0x0D)) {
+			xgifb_reg_set(pVBInfo->P3c4, 0x2B, 0x1B);
+			xgifb_reg_set(pVBInfo->P3c4, 0x2C, 0xE3);
+			b3CC = (unsigned char) inb(XGINew_P3cc);
+			outb((b3CC |= 0x0C), XGINew_P3cc);
 		}
 	}
-}
 
-void XGI_VBLongWait(struct vb_device_info *pVBInfo)
-{
-	unsigned short tempal, temp, i, j;
-	return;
-	if (!(pVBInfo->VBInfo & SetCRT2ToTV)) {
-		temp = 0;
-		for (i = 0; i < 3; i++) {
-			for (j = 0; j < 100; j++) {
-				tempal = XGINew_GetReg2(pVBInfo->P3da);
-				if (temp & 0x01) { /* VBWaitMode2 */
-					if ((tempal & 0x08))
-						continue;
+	if (HwDeviceExtension->jChipType >= XG21) {
+		temp = xgifb_reg_get(pVBInfo->P3d4, 0x38);
+		if (temp & 0xA0) {
 
-					if (!(tempal & 0x08))
-						break;
+			/* xgifb_reg_and(pVBInfo->P3d4, 0x4A, ~0x20); *//* Enable write GPIOF */
+			/* xgifb_reg_and(pVBInfo->P3d4, 0x48, ~0x20); *//* P. DWN */
+			/* XG21 CRT1 Timing */
+			if (HwDeviceExtension->jChipType == XG27)
+				XGI_SetXG27CRTC(ModeNo, ModeIdIndex,
+						RefreshRateTableIndex, pVBInfo);
+			else
+				XGI_SetXG21CRTC(ModeNo, ModeIdIndex,
+						RefreshRateTableIndex, pVBInfo);
 
-				} else { /* VBWaitMode1 */
-					if (!(tempal & 0x08))
-						continue;
+			XGI_UpdateXG21CRTC(ModeNo, pVBInfo,
+					RefreshRateTableIndex);
 
-					if ((tempal & 0x08))
-						break;
-				}
+			if (HwDeviceExtension->jChipType == XG27)
+				XGI_SetXG27LCD(pVBInfo, RefreshRateTableIndex,
+						ModeNo);
+			else
+				XGI_SetXG21LCD(pVBInfo, RefreshRateTableIndex,
+						ModeNo);
+
+			if (pVBInfo->IF_DEF_LVDS == 1) {
+				if (HwDeviceExtension->jChipType == XG27)
+					XGI_SetXG27LVDSPara(ModeNo,
+							ModeIdIndex, pVBInfo);
+				else
+					XGI_SetXG21LVDSPara(ModeNo,
+							ModeIdIndex, pVBInfo);
 			}
-			temp = temp ^ 0x01;
+			/* xgifb_reg_or(pVBInfo->P3d4, 0x48, 0x20); *//* P. ON */
 		}
-	} else {
-		XGI_LongWait(pVBInfo);
 	}
-	return;
-}
 
-unsigned short XGI_GetVGAHT2(struct vb_device_info *pVBInfo)
-{
-	unsigned long tempax, tempbx;
+	pVBInfo->SetFlag &= (~ProgrammingCRT2);
+	XGI_SetCRT1FIFO(ModeNo, HwDeviceExtension, pVBInfo);
+	XGI_SetCRT1ModeRegs(HwDeviceExtension, ModeNo, ModeIdIndex,
+			RefreshRateTableIndex, pVBInfo);
 
-	tempbx = ((pVBInfo->VGAVT - pVBInfo->VGAVDE) * pVBInfo->RVBHCMAX)
-			& 0xFFFF;
-	tempax = (pVBInfo->VT - pVBInfo->VDE) * pVBInfo->RVBHCFACT;
-	tempax = (tempax * pVBInfo->HT) / tempbx;
+	/* XGI_LoadCharacter(); //dif ifdef TVFont */
 
-	return (unsigned short) tempax;
+	XGI_LoadDAC(ModeNo, ModeIdIndex, pVBInfo);
+	/* XGI_ClearBuffer(HwDeviceExtension, ModeNo, pVBInfo); */
 }
 
-unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo,
-		unsigned short ModeIdIndex,
-		unsigned short RefreshRateTableIndex,
-		struct xgi_hw_device_info *HwDeviceExtension,
-		struct vb_device_info *pVBInfo)
+unsigned char XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension,
+			unsigned short ModeNo)
 {
-	unsigned short tempbx;
+	unsigned short ModeIdIndex;
+	/* unsigned char *pVBInfo->FBAddr = HwDeviceExtension->pjVideoMemoryAddress; */
+	struct vb_device_info VBINF;
+	struct vb_device_info *pVBInfo = &VBINF;
+	pVBInfo->ROMAddr = HwDeviceExtension->pjVirtualRomBase;
+	pVBInfo->BaseAddr = (unsigned long) HwDeviceExtension->pjIOAddress;
+	pVBInfo->IF_DEF_LVDS = 0;
+	pVBInfo->IF_DEF_CH7005 = 0;
+	pVBInfo->IF_DEF_LCDA = 1;
+	pVBInfo->IF_DEF_CH7017 = 0;
+	pVBInfo->IF_DEF_CH7007 = 0; /* [Billy] 2007/05/14 */
+	pVBInfo->IF_DEF_VideoCapture = 0;
+	pVBInfo->IF_DEF_ScaleLCD = 0;
+	pVBInfo->IF_DEF_OEMUtil = 0;
+	pVBInfo->IF_DEF_PWD = 0;
+
+	if (HwDeviceExtension->jChipType >= XG20) { /* kuku 2004/06/25 */
+		pVBInfo->IF_DEF_YPbPr = 0;
+		pVBInfo->IF_DEF_HiVision = 0;
+		pVBInfo->IF_DEF_CRT2Monitor = 0;
+		pVBInfo->VBType = 0; /*set VBType default 0*/
+	} else {
+		pVBInfo->IF_DEF_YPbPr = 1;
+		pVBInfo->IF_DEF_HiVision = 1;
+		pVBInfo->IF_DEF_CRT2Monitor = 1;
+	}
+
+	pVBInfo->P3c4 = pVBInfo->BaseAddr + 0x14;
+	pVBInfo->P3d4 = pVBInfo->BaseAddr + 0x24;
+	pVBInfo->P3c0 = pVBInfo->BaseAddr + 0x10;
+	pVBInfo->P3ce = pVBInfo->BaseAddr + 0x1e;
+	pVBInfo->P3c2 = pVBInfo->BaseAddr + 0x12;
+	pVBInfo->P3cc = pVBInfo->BaseAddr + 0x1C;
+	pVBInfo->P3ca = pVBInfo->BaseAddr + 0x1a;
+	pVBInfo->P3c6 = pVBInfo->BaseAddr + 0x16;
+	pVBInfo->P3c7 = pVBInfo->BaseAddr + 0x17;
+	pVBInfo->P3c8 = pVBInfo->BaseAddr + 0x18;
+	pVBInfo->P3c9 = pVBInfo->BaseAddr + 0x19;
+	pVBInfo->P3da = pVBInfo->BaseAddr + 0x2A;
+	pVBInfo->Part0Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_00;
+	pVBInfo->Part1Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_04;
+	pVBInfo->Part2Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_10;
+	pVBInfo->Part3Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_12;
+	pVBInfo->Part4Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14;
+	pVBInfo->Part5Port = pVBInfo->BaseAddr + XGI_CRT2_PORT_14 + 2;
 
-	unsigned short LCDXlat1VCLK[4] = { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2,
-			VCLK65 + 2 };
-	unsigned short LCDXlat2VCLK[4] = { VCLK108_2 + 5, VCLK108_2 + 5,
-			VCLK108_2 + 5, VCLK108_2 + 5 };
-	unsigned short LVDSXlat1VCLK[4] = { VCLK40, VCLK40, VCLK40, VCLK40 };
-	unsigned short LVDSXlat2VCLK[4] = { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2,
-			VCLK65 + 2 };
-	unsigned short LVDSXlat3VCLK[4] = { VCLK65 + 2, VCLK65 + 2, VCLK65 + 2,
-			VCLK65 + 2 };
+	if (HwDeviceExtension->jChipType == XG21) { /* for x86 Linux, XG21 LVDS */
+		if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0)
+			pVBInfo->IF_DEF_LVDS = 1;
+	}
+	if (HwDeviceExtension->jChipType == XG27) {
+		if ((xgifb_reg_get(pVBInfo->P3d4, 0x38) & 0xE0) == 0xC0) {
+			if (xgifb_reg_get(pVBInfo->P3d4, 0x30) & 0x20)
+				pVBInfo->IF_DEF_LVDS = 1;
+		}
+	}
 
-	unsigned short CRT2Index, VCLKIndex;
-	unsigned short modeflag, resinfo;
-	unsigned char *CHTVVCLKPtr = NULL;
+	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 */
+		XGI_GetVBType(pVBInfo);
 
-	if (ModeNo <= 0x13) {
-		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag; /* si+St_ResInfo */
-		resinfo = pVBInfo->SModeIDTable[ModeIdIndex].St_ResInfo;
-		CRT2Index = pVBInfo->SModeIDTable[ModeIdIndex].St_CRT2CRTC;
-	} else {
-		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag; /* si+Ext_ResInfo */
-		resinfo = pVBInfo->EModeIDTable[ModeIdIndex].Ext_RESINFO;
-		CRT2Index
-				= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRT2CRTC;
+	InitTo330Pointer(HwDeviceExtension->jChipType, pVBInfo);
+	if (ModeNo & 0x80) {
+		ModeNo = ModeNo & 0x7F;
+		/* XGINew_flag_clearbuffer = 0; */
 	}
+	/* else {
+		XGINew_flag_clearbuffer = 1;
+	}
+	*/
+	xgifb_reg_set(pVBInfo->P3c4, 0x05, 0x86);
 
-	if (pVBInfo->IF_DEF_LVDS == 0) {
-		CRT2Index = CRT2Index >> 6; /*  for LCD */
-		if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b*/
-			if (pVBInfo->LCDResInfo != Panel1024x768)
-				VCLKIndex = LCDXlat2VCLK[CRT2Index];
-			else
-				VCLKIndex = LCDXlat1VCLK[CRT2Index];
-		} else { /* for TV */
-			if (pVBInfo->VBInfo & SetCRT2ToTV) {
-				if (pVBInfo->VBInfo & SetCRT2ToHiVisionTV) {
-					if (pVBInfo->SetFlag & RPLLDIV2XO) {
-						VCLKIndex = HiTVVCLKDIV2;
+	if (HwDeviceExtension->jChipType < XG20) /* kuku 2004/06/25 1.Openkey */
+		XGI_UnLockCRT2(HwDeviceExtension, pVBInfo);
 
-						VCLKIndex += 25;
+	XGI_SearchModeID(ModeNo, &ModeIdIndex, pVBInfo);
 
-					} else {
-						VCLKIndex = HiTVVCLK;
+	XGI_GetVGAType(HwDeviceExtension, pVBInfo);
 
-						VCLKIndex += 25;
+	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
+		XGI_GetVBInfo(ModeNo, ModeIdIndex, HwDeviceExtension, pVBInfo);
+		XGI_GetTVInfo(ModeNo, ModeIdIndex, pVBInfo);
+		XGI_GetLCDInfo(ModeNo, ModeIdIndex, pVBInfo);
+		XGI_DisableBridge(HwDeviceExtension, pVBInfo);
+		/* XGI_OpenCRTC(HwDeviceExtension, pVBInfo); */
 
-					}
+		if (pVBInfo->VBInfo & (SetSimuScanMode | SetCRT2ToLCDA)) {
+			XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
+					ModeIdIndex, pVBInfo);
 
-					if (pVBInfo->SetFlag & TVSimuMode) {
-						if (modeflag & Charx8Dot) {
-							VCLKIndex
-									= HiTVSimuVCLK;
+			if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+				XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
+						HwDeviceExtension, pVBInfo);
+			}
+		} else {
+			if (!(pVBInfo->VBInfo & SwitchToCRT2)) {
+				XGI_SetCRT1Group(HwDeviceExtension, ModeNo,
+						ModeIdIndex, pVBInfo);
+				if (pVBInfo->VBInfo & SetCRT2ToLCDA) {
+					XGI_SetLCDAGroup(ModeNo, ModeIdIndex,
+							HwDeviceExtension,
+							pVBInfo);
+				}
+			}
+		}
 
-							VCLKIndex += 25;
+		if (pVBInfo->VBInfo & (SetSimuScanMode | SwitchToCRT2)) {
+			switch (HwDeviceExtension->ujVBChipID) {
+			case VB_CHIP_301:
+				XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
+						pVBInfo); /*add for CRT2 */
+				break;
 
-						} else {
-							VCLKIndex
-									= HiTVTextVCLK;
+			case VB_CHIP_302:
+				XGI_SetCRT2Group301(ModeNo, HwDeviceExtension,
+						pVBInfo); /*add for CRT2 */
+				break;
 
-							VCLKIndex += 25;
+			default:
+				break;
+			}
+		}
 
-						}
-					}
+		XGI_SetCRT2ModeRegs(ModeNo, HwDeviceExtension, pVBInfo);
+		XGI_OEM310Setting(ModeNo, ModeIdIndex, pVBInfo); /*0212*/
+		XGI_CloseCRTC(HwDeviceExtension, pVBInfo);
+		XGI_EnableBridge(HwDeviceExtension, pVBInfo);
+	} /* !XG20 */
+	else {
+		if (pVBInfo->IF_DEF_LVDS == 1)
+			if (!XGI_XG21CheckLVDSMode(ModeNo, ModeIdIndex, pVBInfo))
+				return 0;
 
-					if (pVBInfo->VBType & VB_XGI301LV) { /* 301lv */
-						if (!(pVBInfo->VBExtInfo
-								== VB_YPbPr1080i)) {
-							VCLKIndex
-									= YPbPr750pVCLK;
-							if (!(pVBInfo->VBExtInfo
-									== VB_YPbPr750p)) {
-								VCLKIndex
-										= YPbPr525pVCLK;
-								if (!(pVBInfo->VBExtInfo
-										== VB_YPbPr525p)) {
-									VCLKIndex
-											= YPbPr525iVCLK_2;
-									if (!(pVBInfo->SetFlag
-											& RPLLDIV2XO))
-										VCLKIndex
-												= YPbPr525iVCLK;
-								}
-							}
-						}
-					}
-				} else {
-					if (pVBInfo->VBInfo & SetCRT2ToTV) {
-						if (pVBInfo->SetFlag
-								& RPLLDIV2XO) {
-							VCLKIndex = TVVCLKDIV2;
+		if (ModeNo <= 0x13) {
+			pVBInfo->ModeType
+					= pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag
+							& ModeInfoFlag;
+		} else {
+			pVBInfo->ModeType
+					= pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag
+							& ModeInfoFlag;
+		}
 
-							VCLKIndex += 25;
+		pVBInfo->SetFlag = 0;
+		if (pVBInfo->IF_DEF_CH7007 != 1)
+			pVBInfo->VBInfo = DisableCRT2Display;
 
-						} else {
-							VCLKIndex = TVVCLK;
+		XGI_DisplayOff(HwDeviceExtension, pVBInfo);
 
-							VCLKIndex += 25;
+		XGI_SetCRT1Group(HwDeviceExtension, ModeNo, ModeIdIndex,
+				pVBInfo);
 
-						}
-					}
-				}
-			} else { /* for CRT2 */
-				VCLKIndex = (unsigned char) XGINew_GetReg2(
-						(pVBInfo->P3ca + 0x02)); /* Port 3cch */
-				VCLKIndex = ((VCLKIndex >> 2) & 0x03);
-				if (ModeNo > 0x13) {
-					VCLKIndex
-							= pVBInfo->RefIndex[RefreshRateTableIndex].Ext_CRTVCLK; /* di+Ext_CRTVCLK */
-					VCLKIndex &= IndexMask;
-				}
-			}
-		}
-	} else { /* LVDS */
-		if (ModeNo <= 0x13)
-			VCLKIndex = CRT2Index;
-		else
-			VCLKIndex = CRT2Index;
+		XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+		/*
+		if (HwDeviceExtension->jChipType == XG21)
+			xgifb_reg_and_or(pVBInfo->P3c4, 0x09, ~0x80, 0x80);
+		*/
+	}
 
-		if (pVBInfo->IF_DEF_CH7005 == 1) {
-			if (!(pVBInfo->VBInfo & SetCRT2ToLCD)) {
-				VCLKIndex &= 0x1f;
-				tempbx = 0;
+	/*
+	if (ModeNo <= 0x13) {
+		modeflag = pVBInfo->SModeIDTable[ModeIdIndex].St_ModeFlag;
+	} else {
+		modeflag = pVBInfo->EModeIDTable[ModeIdIndex].Ext_ModeFlag;
+	}
+	pVBInfo->ModeType = modeflag&ModeInfoFlag;
+	pVBInfo->SetFlag = 0x00;
+	pVBInfo->VBInfo = DisableCRT2Display;
+	temp = XGINew_CheckMemorySize(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo);
 
-				if (pVBInfo->VBInfo & SetPALTV)
-					tempbx += 2;
+	if (temp == 0)
+		return (0);
 
-				if (pVBInfo->VBInfo & SetCHTVOverScan)
-					tempbx += 1;
+	XGI_DisplayOff(HwDeviceExtension, pVBInfo) ;
+	XGI_SetCRT1Group(HwDeviceExtension, ModeNo, ModeIdIndex, pVBInfo);
+	XGI_DisplayOn(HwDeviceExtension, pVBInfo);
+	*/
 
-				switch (tempbx) {
-				case 0:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKUNTSC;
-					break;
-				case 1:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKONTSC;
-					break;
-				case 2:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKUPAL;
-					break;
-				case 3:
-					CHTVVCLKPtr = pVBInfo->CHTVVCLKOPAL;
-					break;
-				default:
-					break;
-				}
+	XGI_UpdateModeInfo(HwDeviceExtension, pVBInfo);
 
-				VCLKIndex = CHTVVCLKPtr[VCLKIndex];
-			}
-		} else {
-			VCLKIndex = VCLKIndex >> 6;
-			if ((pVBInfo->LCDResInfo == Panel800x600)
-					|| (pVBInfo->LCDResInfo == Panel320x480))
-				VCLKIndex = LVDSXlat1VCLK[VCLKIndex];
-			else if ((pVBInfo->LCDResInfo == Panel1024x768)
-					|| (pVBInfo->LCDResInfo
-							== Panel1024x768x75))
-				VCLKIndex = LVDSXlat2VCLK[VCLKIndex];
-			else
-				VCLKIndex = LVDSXlat3VCLK[VCLKIndex];
-		}
+	if (HwDeviceExtension->jChipType < XG20) { /* kuku 2004/06/25 */
+		XGI_LockCRT2(HwDeviceExtension, pVBInfo);
 	}
-	/* VCLKIndex = VCLKIndex&IndexMask; */
 
-	return VCLKIndex;
+	return 1;
 }
-
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
index 0dcc297..7a2e564 100644
--- a/drivers/staging/xgifb/vb_setmode.h
+++ b/drivers/staging/xgifb/vb_setmode.h
@@ -17,9 +17,6 @@ extern   void     XGI_SenseCRT1(struct vb_device_info *);
 extern   void     XGI_GetVGAType(struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
 extern   void     XGI_GetVBInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
 extern   void     XGI_GetTVInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *);
-extern   void     XGI_SetCRT1Offset(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned short RefreshRateTableIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
-extern   void     XGI_SetLCDAGroup(unsigned short ModeNo, unsigned short ModeIdIndex, struct xgi_hw_device_info *HwDeviceExtension, struct vb_device_info *);
-extern   void     XGI_WaitDisply(struct vb_device_info *);
 extern   unsigned short   XGI_GetResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
 
 extern   unsigned char  XGISetModeNew(struct xgi_hw_device_info *HwDeviceExtension, unsigned short ModeNo) ;
@@ -36,7 +33,6 @@ extern   void     XGI_XG21BLSignalVDD(unsigned short tempbh, unsigned short temp
 extern   void     XGI_XG27BLSignalVDD(unsigned short tempbh, unsigned short tempbl, struct vb_device_info *pVBInfo);
 extern   void     XGI_XG21SetPanelDelay(unsigned short tempbl, struct vb_device_info *pVBInfo);
 extern   unsigned char  XGI_XG21CheckLVDSMode(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
-extern   void     XGI_SetXG21LVDSPara(unsigned short ModeNo, unsigned short ModeIdIndex, struct vb_device_info *pVBInfo);
 extern   unsigned short XGI_GetLVDSOEMTableIndex(struct vb_device_info *pVBInfo);
 
 #endif
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index 78b1c79..d71cd55 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -1,17 +1,5 @@
 #define  Tap4
 
-
-static struct XGI_MCLKDataStruct XGI330New_MCLKData[] =
-{
- { 0x5c,0x23,0x01,166},
- { 0x5c,0x23,0x01,166},
- { 0x7C,0x08,0x80,200},
- { 0x79,0x06,0x80,250},
- { 0x29,0x01,0x81,300},
- { 0x29,0x01,0x81,300},
- { 0x29,0x01,0x81,300},
- { 0x29,0x01,0x81,300}
-};
 //yilin modify for xgi20
 static struct XGI_MCLKDataStruct XGI340New_MCLKData[] =
 {
@@ -37,17 +25,6 @@ static struct XGI_MCLKDataStruct XGI27New_MCLKData[] =
  { 0x5c,0x23,0x01,166}
 };
 
-static struct XGI_ECLKDataStruct XGI330_ECLKData[] =
-{
- { 0x7c,0x08,0x01,200},
- { 0x7c,0x08,0x01,200},
- { 0x7C,0x08,0x80,200},
- { 0x79,0x06,0x80,250},
- { 0x29,0x01,0x81,300},
- { 0x29,0x01,0x81,300},
- { 0x29,0x01,0x81,300},
- { 0x29,0x01,0x81,300}
-};
 //yilin modify for xgi20
 static struct XGI_ECLKDataStruct XGI340_ECLKData[] =
 {
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
index 65b3954..a97e44f 100644
--- a/drivers/staging/xgifb/vb_util.c
+++ b/drivers/staging/xgifb/vb_util.c
@@ -6,131 +6,47 @@
 #include <asm/io.h>
 #include <linux/types.h>
 
-void XGINew_SetReg1(unsigned long, unsigned short, unsigned short);
-void XGINew_SetReg2(unsigned long, unsigned short, unsigned short);
-void XGINew_SetReg3(unsigned long, unsigned short);
-void XGINew_SetReg4(unsigned long, unsigned long);
-unsigned char XGINew_GetReg1(unsigned long, unsigned short);
-unsigned char XGINew_GetReg2(unsigned long);
-unsigned long XGINew_GetReg3(unsigned long);
-void XGINew_ClearDAC(unsigned char *);
-void XGINew_SetRegANDOR(unsigned long Port, unsigned short Index,
-		unsigned short DataAND, unsigned short DataOR);
-void XGINew_SetRegOR(unsigned long Port, unsigned short Index,
-		unsigned short DataOR);
-void XGINew_SetRegAND(unsigned long Port, unsigned short Index,
-		unsigned short DataAND);
+#include "vb_util.h"
 
-/* --------------------------------------------------------------------- */
-/* Function : XGINew_SetReg1 */
-/* Input : */
-/* Output : */
-/* Description : SR CRTC GR */
-/* --------------------------------------------------------------------- */
-void XGINew_SetReg1(unsigned long port, unsigned short index,
-		unsigned short data)
+void xgifb_reg_set(unsigned long port, u8 index, u8 data)
 {
 	outb(index, port);
 	outb(data, port + 1);
 }
 
-/* --------------------------------------------------------------------- */
-/* Function : XGINew_SetReg2 */
-/* Input : */
-/* Output : */
-/* Description : AR( 3C0 ) */
-/* --------------------------------------------------------------------- */
-/*
-void XGINew_SetReg2(unsigned long port, unsigned short index, unsigned short data)
+u8 xgifb_reg_get(unsigned long port, u8 index)
 {
-	InPortByte((P unsigned char)port + 0x3da - 0x3c0) ;
-	OutPortByte(XGINew_P3c0, index);
-	OutPortByte(XGINew_P3c0, data);
-	OutPortByte(XGINew_P3c0, 0x20);
-}
-*/
-
-void XGINew_SetReg3(unsigned long port, unsigned short data)
-{
-	outb(data, port);
-}
-
-void XGINew_SetReg4(unsigned long port, unsigned long data)
-{
-	outl(data, port);
-}
-
-unsigned char XGINew_GetReg1(unsigned long port, unsigned short index)
-{
-	unsigned char data;
+	u8 data;
 
 	outb(index, port);
 	data = inb(port + 1);
 	return data;
 }
 
-unsigned char XGINew_GetReg2(unsigned long port)
+void xgifb_reg_and_or(unsigned long port, u8 index,
+		unsigned data_and, unsigned data_or)
 {
-	unsigned char data;
-
-	data = inb(port);
+	u8 temp;
 
-	return data;
+	temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
+	temp = (temp & data_and) | data_or;
+	xgifb_reg_set(port, index, temp);
 }
 
-unsigned long XGINew_GetReg3(unsigned long port)
+void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and)
 {
-	unsigned long data;
-
-	data = inl(port);
+	u8 temp;
 
-	return data;
+	temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
+	temp &= data_and;
+	xgifb_reg_set(port, index, temp);
 }
 
-void XGINew_SetRegANDOR(unsigned long Port, unsigned short Index,
-		unsigned short DataAND, unsigned short DataOR)
+void xgifb_reg_or(unsigned long port, u8 index, unsigned data_or)
 {
-	unsigned short temp;
-
-	temp = XGINew_GetReg1(Port, Index); /* XGINew_Part1Port index 02 */
-	temp = (temp & (DataAND)) | DataOR;
-	XGINew_SetReg1(Port, Index, temp);
-}
+	u8 temp;
 
-void XGINew_SetRegAND(unsigned long Port, unsigned short Index,
-		unsigned short DataAND)
-{
-	unsigned short temp;
-
-	temp = XGINew_GetReg1(Port, Index); /* XGINew_Part1Port index 02 */
-	temp &= DataAND;
-	XGINew_SetReg1(Port, Index, temp);
-}
-
-void XGINew_SetRegOR(unsigned long Port, unsigned short Index,
-		unsigned short DataOR)
-{
-	unsigned short temp;
-
-	temp = XGINew_GetReg1(Port, Index); /* XGINew_Part1Port index 02 */
-	temp |= DataOR;
-	XGINew_SetReg1(Port, Index, temp);
-}
-
-#if 0
-void NewDelaySeconds(int seconds)
-{
-	int i;
-
-	for (i = 0; i < seconds; i++) {
-
-	}
-}
-
-void Newdebugcode(unsigned char code)
-{
-	/* OutPortByte(0x80, code); */
-	/* OutPortByte(0x300, code); */
-	/* NewDelaySeconds(0x3); */
+	temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
+	temp |= data_or;
+	xgifb_reg_set(port, index, temp);
 }
-#endif
diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
index 156f644..9161de1 100644
--- a/drivers/staging/xgifb/vb_util.h
+++ b/drivers/staging/xgifb/vb_util.h
@@ -1,15 +1,9 @@
 #ifndef _VBUTIL_
 #define _VBUTIL_
-extern   void     NewDelaySeconds( int );
-extern   void     Newdebugcode(unsigned char);
-extern   void     XGINew_SetReg1(unsigned long, unsigned short, unsigned short);
-extern   void     XGINew_SetReg3(unsigned long, unsigned short);
-extern    unsigned char     XGINew_GetReg1(unsigned long, unsigned short);
-extern    unsigned char     XGINew_GetReg2(unsigned long);
-extern   void     XGINew_SetReg4(unsigned long, unsigned long);
-extern   unsigned long    XGINew_GetReg3(unsigned long);
-extern   void     XGINew_SetRegOR(unsigned long Port,unsigned short Index,unsigned short DataOR);
-extern   void     XGINew_SetRegAND(unsigned long Port,unsigned short Index,unsigned short DataAND);
-extern   void     XGINew_SetRegANDOR(unsigned long Port,unsigned short Index,unsigned short DataAND,unsigned short DataOR);
+extern void xgifb_reg_set(unsigned long, u8, u8);
+extern u8 xgifb_reg_get(unsigned long, u8);
+extern void xgifb_reg_or(unsigned long, u8, unsigned);
+extern void xgifb_reg_and(unsigned long, u8, unsigned);
+extern void xgifb_reg_and_or(unsigned long, u8, unsigned, unsigned);
 #endif
 
diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h
index df839ee..4b87951 100644
--- a/drivers/staging/xgifb/vgatypes.h
+++ b/drivers/staging/xgifb/vgatypes.h
@@ -4,10 +4,6 @@
 
 #include <linux/ioctl.h>
 
-#ifndef VBIOS_VER_MAX_LENGTH
-#define VBIOS_VER_MAX_LENGTH    5
-#endif
-
 #ifndef XGI_VB_CHIP_TYPE
 enum XGI_VB_CHIP_TYPE {
     VB_CHIP_Legacy = 0,
@@ -65,10 +61,6 @@ struct xgi_hw_device_info
 
     unsigned char *pjVirtualRomBase;    /* ROM image */
 
-    unsigned char UseROM;		 /* Use the ROM image if provided */
-
-    void *pDevice;
-
     unsigned char *pjVideoMemoryAddress;/* base virtual memory address */
                                  /* of Linear VGA memory */
 
@@ -76,12 +68,6 @@ struct xgi_hw_device_info
 
     unsigned char *pjIOAddress;          /* base I/O address of VGA ports (0x3B0) */
 
-    unsigned char *pjCustomizedROMImage;
-
-    unsigned char *pj2ndVideoMemoryAddress;
-    unsigned long  ul2ndVideoMemorySize;
-
-    unsigned char *pj2ndIOAddress;
     unsigned char  jChipType;            /* Used to Identify Graphics Chip */
                                  /* defined in the data structure type  */
                                  /* "XGI_CHIP_TYPE" */
@@ -92,42 +78,11 @@ struct xgi_hw_device_info
                                  /* defined in the data structure type */
                                  /* "XGI_VB_CHIP_TYPE" */
 
-    unsigned char    bNewScratch;
-
     unsigned long  ulCRT2LCDType;        /* defined in the data structure type */
 
-    unsigned long usExternalChip;       /* NO VB or other video bridge (other than  */
-                                 /*  video bridge) */
-
-    unsigned char bIntegratedMMEnabled;/* supporting integration MM enable */
-
-    unsigned char bSkipDramSizing;     /* True: Skip video memory sizing. */
-
-    unsigned char bSkipSense;
-
-    unsigned char bIsPowerSaving;     /* True: XGIInit() is invoked by power management,
-                                   otherwise by 2nd adapter's initialzation */
-
-    struct XGI_DSReg  *pSR;             /* restore SR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF). */
-                                 /* Note : restore SR registers if  */
-                                 /* bSkipDramSizing = 1 */
-
-    struct XGI_DSReg  *pCR;             /* restore CR registers in initial function. */
-                                 /* end data :(idx, val) =  (FF, FF) */
-                                 /* Note : restore cR registers if  */
-                                 /* bSkipDramSizing = 1 */
-
 	unsigned char(*pQueryVGAConfigSpace)(struct xgi_hw_device_info *,
 					    unsigned long, unsigned long,
 					    unsigned long *);
-
-	unsigned char(*pQueryNorthBridgeSpace)(struct xgi_hw_device_info *,
-					      unsigned long, unsigned long,
-					      unsigned long *);
-
-    unsigned char szVBIOSVer[VBIOS_VER_MAX_LENGTH];
-
 };
 
 /* Addtional IOCTL for communication xgifb <> X driver        */
diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig
new file mode 100644
index 0000000..7fabcb2
--- /dev/null
+++ b/drivers/staging/zcache/Kconfig
@@ -0,0 +1,13 @@
+config ZCACHE
+	tristate "Dynamic compression of swap pages and clean pagecache pages"
+	depends on CLEANCACHE || FRONTSWAP
+	select XVMALLOC
+	select LZO_COMPRESS
+	select LZO_DECOMPRESS
+	default n
+	help
+	  Zcache doubles RAM efficiency while providing a significant
+	  performance boosts on many workloads.  Zcache uses lzo1x
+	  compression and an in-kernel implementation of transcendent
+	  memory to store clean page cache pages and swap in RAM,
+	  providing a noticeable reduction in disk I/O.
diff --git a/drivers/staging/zcache/Makefile b/drivers/staging/zcache/Makefile
new file mode 100644
index 0000000..f5ec64f
--- /dev/null
+++ b/drivers/staging/zcache/Makefile
@@ -0,0 +1,3 @@
+zcache-y	:=	tmem.o
+
+obj-$(CONFIG_ZCACHE)	+=	zcache.o
diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c
new file mode 100644
index 0000000..e954d40
--- /dev/null
+++ b/drivers/staging/zcache/tmem.c
@@ -0,0 +1,710 @@
+/*
+ * In-kernel transcendent memory (generic implementation)
+ *
+ * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp.
+ *
+ * The primary purpose of Transcedent Memory ("tmem") is to map object-oriented
+ * "handles" (triples containing a pool id, and object id, and an index), to
+ * pages in a page-accessible memory (PAM).  Tmem references the PAM pages via
+ * an abstract "pampd" (PAM page-descriptor), which can be operated on by a
+ * set of functions (pamops).  Each pampd contains some representation of
+ * PAGE_SIZE bytes worth of data. Tmem must support potentially millions of
+ * pages and must be able to insert, find, and delete these pages at a
+ * potential frequency of thousands per second concurrently across many CPUs,
+ * (and, if used with KVM, across many vcpus across many guests).
+ * Tmem is tracked with a hierarchy of data structures, organized by
+ * the elements in a handle-tuple: pool_id, object_id, and page index.
+ * One or more "clients" (e.g. guests) each provide one or more tmem_pools.
+ * Each pool, contains a hash table of rb_trees of tmem_objs.  Each
+ * tmem_obj contains a radix-tree-like tree of pointers, with intermediate
+ * nodes called tmem_objnodes.  Each leaf pointer in this tree points to
+ * a pampd, which is accessible only through a small set of callbacks
+ * registered by the PAM implementation (see tmem_register_pamops). Tmem
+ * does all memory allocation via a set of callbacks registered by the tmem
+ * host implementation (e.g. see tmem_register_hostops).
+ */
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/atomic.h>
+
+#include "tmem.h"
+
+/* data structure sentinels used for debugging... see tmem.h */
+#define POOL_SENTINEL 0x87658765
+#define OBJ_SENTINEL 0x12345678
+#define OBJNODE_SENTINEL 0xfedcba09
+
+/*
+ * A tmem host implementation must use this function to register callbacks
+ * for memory allocation.
+ */
+static struct tmem_hostops tmem_hostops;
+
+static void tmem_objnode_tree_init(void);
+
+void tmem_register_hostops(struct tmem_hostops *m)
+{
+	tmem_objnode_tree_init();
+	tmem_hostops = *m;
+}
+
+/*
+ * A tmem host implementation must use this function to register
+ * callbacks for a page-accessible memory (PAM) implementation
+ */
+static struct tmem_pamops tmem_pamops;
+
+void tmem_register_pamops(struct tmem_pamops *m)
+{
+	tmem_pamops = *m;
+}
+
+/*
+ * Oid's are potentially very sparse and tmem_objs may have an indeterminately
+ * short life, being added and deleted at a relatively high frequency.
+ * So an rb_tree is an ideal data structure to manage tmem_objs.  But because
+ * of the potentially huge number of tmem_objs, each pool manages a hashtable
+ * of rb_trees to reduce search, insert, delete, and rebalancing time.
+ * Each hashbucket also has a lock to manage concurrent access.
+ *
+ * The following routines manage tmem_objs.  When any tmem_obj is accessed,
+ * the hashbucket lock must be held.
+ */
+
+/* searches for object==oid in pool, returns locked object if found */
+static struct tmem_obj *tmem_obj_find(struct tmem_hashbucket *hb,
+					struct tmem_oid *oidp)
+{
+	struct rb_node *rbnode;
+	struct tmem_obj *obj;
+
+	rbnode = hb->obj_rb_root.rb_node;
+	while (rbnode) {
+		BUG_ON(RB_EMPTY_NODE(rbnode));
+		obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node);
+		switch (tmem_oid_compare(oidp, &obj->oid)) {
+		case 0: /* equal */
+			goto out;
+		case -1:
+			rbnode = rbnode->rb_left;
+			break;
+		case 1:
+			rbnode = rbnode->rb_right;
+			break;
+		}
+	}
+	obj = NULL;
+out:
+	return obj;
+}
+
+static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *);
+
+/* free an object that has no more pampds in it */
+static void tmem_obj_free(struct tmem_obj *obj, struct tmem_hashbucket *hb)
+{
+	struct tmem_pool *pool;
+
+	BUG_ON(obj == NULL);
+	ASSERT_SENTINEL(obj, OBJ);
+	BUG_ON(obj->pampd_count > 0);
+	pool = obj->pool;
+	BUG_ON(pool == NULL);
+	if (obj->objnode_tree_root != NULL) /* may be "stump" with no leaves */
+		tmem_pampd_destroy_all_in_obj(obj);
+	BUG_ON(obj->objnode_tree_root != NULL);
+	BUG_ON((long)obj->objnode_count != 0);
+	atomic_dec(&pool->obj_count);
+	BUG_ON(atomic_read(&pool->obj_count) < 0);
+	INVERT_SENTINEL(obj, OBJ);
+	obj->pool = NULL;
+	tmem_oid_set_invalid(&obj->oid);
+	rb_erase(&obj->rb_tree_node, &hb->obj_rb_root);
+}
+
+/*
+ * initialize, and insert an tmem_object_root (called only if find failed)
+ */
+static void tmem_obj_init(struct tmem_obj *obj, struct tmem_hashbucket *hb,
+					struct tmem_pool *pool,
+					struct tmem_oid *oidp)
+{
+	struct rb_root *root = &hb->obj_rb_root;
+	struct rb_node **new = &(root->rb_node), *parent = NULL;
+	struct tmem_obj *this;
+
+	BUG_ON(pool == NULL);
+	atomic_inc(&pool->obj_count);
+	obj->objnode_tree_height = 0;
+	obj->objnode_tree_root = NULL;
+	obj->pool = pool;
+	obj->oid = *oidp;
+	obj->objnode_count = 0;
+	obj->pampd_count = 0;
+	SET_SENTINEL(obj, OBJ);
+	while (*new) {
+		BUG_ON(RB_EMPTY_NODE(*new));
+		this = rb_entry(*new, struct tmem_obj, rb_tree_node);
+		parent = *new;
+		switch (tmem_oid_compare(oidp, &this->oid)) {
+		case 0:
+			BUG(); /* already present; should never happen! */
+			break;
+		case -1:
+			new = &(*new)->rb_left;
+			break;
+		case 1:
+			new = &(*new)->rb_right;
+			break;
+		}
+	}
+	rb_link_node(&obj->rb_tree_node, parent, new);
+	rb_insert_color(&obj->rb_tree_node, root);
+}
+
+/*
+ * Tmem is managed as a set of tmem_pools with certain attributes, such as
+ * "ephemeral" vs "persistent".  These attributes apply to all tmem_objs
+ * and all pampds that belong to a tmem_pool.  A tmem_pool is created
+ * or deleted relatively rarely (for example, when a filesystem is
+ * mounted or unmounted.
+ */
+
+/* flush all data from a pool and, optionally, free it */
+static void tmem_pool_flush(struct tmem_pool *pool, bool destroy)
+{
+	struct rb_node *rbnode;
+	struct tmem_obj *obj;
+	struct tmem_hashbucket *hb = &pool->hashbucket[0];
+	int i;
+
+	BUG_ON(pool == NULL);
+	for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) {
+		spin_lock(&hb->lock);
+		rbnode = rb_first(&hb->obj_rb_root);
+		while (rbnode != NULL) {
+			obj = rb_entry(rbnode, struct tmem_obj, rb_tree_node);
+			rbnode = rb_next(rbnode);
+			tmem_pampd_destroy_all_in_obj(obj);
+			tmem_obj_free(obj, hb);
+			(*tmem_hostops.obj_free)(obj, pool);
+		}
+		spin_unlock(&hb->lock);
+	}
+	if (destroy)
+		list_del(&pool->pool_list);
+}
+
+/*
+ * A tmem_obj contains a radix-tree-like tree in which the intermediate
+ * nodes are called tmem_objnodes.  (The kernel lib/radix-tree.c implementation
+ * is very specialized and tuned for specific uses and is not particularly
+ * suited for use from this code, though some code from the core algorithms has
+ * been reused, thus the copyright notices below).  Each tmem_objnode contains
+ * a set of pointers which point to either a set of intermediate tmem_objnodes
+ * or a set of of pampds.
+ *
+ * Portions Copyright (C) 2001 Momchil Velikov
+ * Portions Copyright (C) 2001 Christoph Hellwig
+ * Portions Copyright (C) 2005 SGI, Christoph Lameter <clameter@sgi.com>
+ */
+
+struct tmem_objnode_tree_path {
+	struct tmem_objnode *objnode;
+	int offset;
+};
+
+/* objnode height_to_maxindex translation */
+static unsigned long tmem_objnode_tree_h2max[OBJNODE_TREE_MAX_PATH + 1];
+
+static void tmem_objnode_tree_init(void)
+{
+	unsigned int ht, tmp;
+
+	for (ht = 0; ht < ARRAY_SIZE(tmem_objnode_tree_h2max); ht++) {
+		tmp = ht * OBJNODE_TREE_MAP_SHIFT;
+		if (tmp >= OBJNODE_TREE_INDEX_BITS)
+			tmem_objnode_tree_h2max[ht] = ~0UL;
+		else
+			tmem_objnode_tree_h2max[ht] =
+			    (~0UL >> (OBJNODE_TREE_INDEX_BITS - tmp - 1)) >> 1;
+	}
+}
+
+static struct tmem_objnode *tmem_objnode_alloc(struct tmem_obj *obj)
+{
+	struct tmem_objnode *objnode;
+
+	ASSERT_SENTINEL(obj, OBJ);
+	BUG_ON(obj->pool == NULL);
+	ASSERT_SENTINEL(obj->pool, POOL);
+	objnode = (*tmem_hostops.objnode_alloc)(obj->pool);
+	if (unlikely(objnode == NULL))
+		goto out;
+	objnode->obj = obj;
+	SET_SENTINEL(objnode, OBJNODE);
+	memset(&objnode->slots, 0, sizeof(objnode->slots));
+	objnode->slots_in_use = 0;
+	obj->objnode_count++;
+out:
+	return objnode;
+}
+
+static void tmem_objnode_free(struct tmem_objnode *objnode)
+{
+	struct tmem_pool *pool;
+	int i;
+
+	BUG_ON(objnode == NULL);
+	for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++)
+		BUG_ON(objnode->slots[i] != NULL);
+	ASSERT_SENTINEL(objnode, OBJNODE);
+	INVERT_SENTINEL(objnode, OBJNODE);
+	BUG_ON(objnode->obj == NULL);
+	ASSERT_SENTINEL(objnode->obj, OBJ);
+	pool = objnode->obj->pool;
+	BUG_ON(pool == NULL);
+	ASSERT_SENTINEL(pool, POOL);
+	objnode->obj->objnode_count--;
+	objnode->obj = NULL;
+	(*tmem_hostops.objnode_free)(objnode, pool);
+}
+
+/*
+ * lookup index in object and return associated pampd (or NULL if not found)
+ */
+static void *tmem_pampd_lookup_in_obj(struct tmem_obj *obj, uint32_t index)
+{
+	unsigned int height, shift;
+	struct tmem_objnode **slot = NULL;
+
+	BUG_ON(obj == NULL);
+	ASSERT_SENTINEL(obj, OBJ);
+	BUG_ON(obj->pool == NULL);
+	ASSERT_SENTINEL(obj->pool, POOL);
+
+	height = obj->objnode_tree_height;
+	if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height])
+		goto out;
+	if (height == 0 && obj->objnode_tree_root) {
+		slot = &obj->objnode_tree_root;
+		goto out;
+	}
+	shift = (height-1) * OBJNODE_TREE_MAP_SHIFT;
+	slot = &obj->objnode_tree_root;
+	while (height > 0) {
+		if (*slot == NULL)
+			goto out;
+		slot = (struct tmem_objnode **)
+			((*slot)->slots +
+			 ((index >> shift) & OBJNODE_TREE_MAP_MASK));
+		shift -= OBJNODE_TREE_MAP_SHIFT;
+		height--;
+	}
+out:
+	return slot != NULL ? *slot : NULL;
+}
+
+static int tmem_pampd_add_to_obj(struct tmem_obj *obj, uint32_t index,
+					void *pampd)
+{
+	int ret = 0;
+	struct tmem_objnode *objnode = NULL, *newnode, *slot;
+	unsigned int height, shift;
+	int offset = 0;
+
+	/* if necessary, extend the tree to be higher  */
+	if (index > tmem_objnode_tree_h2max[obj->objnode_tree_height]) {
+		height = obj->objnode_tree_height + 1;
+		if (index > tmem_objnode_tree_h2max[height])
+			while (index > tmem_objnode_tree_h2max[height])
+				height++;
+		if (obj->objnode_tree_root == NULL) {
+			obj->objnode_tree_height = height;
+			goto insert;
+		}
+		do {
+			newnode = tmem_objnode_alloc(obj);
+			if (!newnode) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			newnode->slots[0] = obj->objnode_tree_root;
+			newnode->slots_in_use = 1;
+			obj->objnode_tree_root = newnode;
+			obj->objnode_tree_height++;
+		} while (height > obj->objnode_tree_height);
+	}
+insert:
+	slot = obj->objnode_tree_root;
+	height = obj->objnode_tree_height;
+	shift = (height-1) * OBJNODE_TREE_MAP_SHIFT;
+	while (height > 0) {
+		if (slot == NULL) {
+			/* add a child objnode.  */
+			slot = tmem_objnode_alloc(obj);
+			if (!slot) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			if (objnode) {
+
+				objnode->slots[offset] = slot;
+				objnode->slots_in_use++;
+			} else
+				obj->objnode_tree_root = slot;
+		}
+		/* go down a level */
+		offset = (index >> shift) & OBJNODE_TREE_MAP_MASK;
+		objnode = slot;
+		slot = objnode->slots[offset];
+		shift -= OBJNODE_TREE_MAP_SHIFT;
+		height--;
+	}
+	BUG_ON(slot != NULL);
+	if (objnode) {
+		objnode->slots_in_use++;
+		objnode->slots[offset] = pampd;
+	} else
+		obj->objnode_tree_root = pampd;
+	obj->pampd_count++;
+out:
+	return ret;
+}
+
+static void *tmem_pampd_delete_from_obj(struct tmem_obj *obj, uint32_t index)
+{
+	struct tmem_objnode_tree_path path[OBJNODE_TREE_MAX_PATH + 1];
+	struct tmem_objnode_tree_path *pathp = path;
+	struct tmem_objnode *slot = NULL;
+	unsigned int height, shift;
+	int offset;
+
+	BUG_ON(obj == NULL);
+	ASSERT_SENTINEL(obj, OBJ);
+	BUG_ON(obj->pool == NULL);
+	ASSERT_SENTINEL(obj->pool, POOL);
+	height = obj->objnode_tree_height;
+	if (index > tmem_objnode_tree_h2max[height])
+		goto out;
+	slot = obj->objnode_tree_root;
+	if (height == 0 && obj->objnode_tree_root) {
+		obj->objnode_tree_root = NULL;
+		goto out;
+	}
+	shift = (height - 1) * OBJNODE_TREE_MAP_SHIFT;
+	pathp->objnode = NULL;
+	do {
+		if (slot == NULL)
+			goto out;
+		pathp++;
+		offset = (index >> shift) & OBJNODE_TREE_MAP_MASK;
+		pathp->offset = offset;
+		pathp->objnode = slot;
+		slot = slot->slots[offset];
+		shift -= OBJNODE_TREE_MAP_SHIFT;
+		height--;
+	} while (height > 0);
+	if (slot == NULL)
+		goto out;
+	while (pathp->objnode) {
+		pathp->objnode->slots[pathp->offset] = NULL;
+		pathp->objnode->slots_in_use--;
+		if (pathp->objnode->slots_in_use) {
+			if (pathp->objnode == obj->objnode_tree_root) {
+				while (obj->objnode_tree_height > 0 &&
+				  obj->objnode_tree_root->slots_in_use == 1 &&
+				  obj->objnode_tree_root->slots[0]) {
+					struct tmem_objnode *to_free =
+						obj->objnode_tree_root;
+
+					obj->objnode_tree_root =
+							to_free->slots[0];
+					obj->objnode_tree_height--;
+					to_free->slots[0] = NULL;
+					to_free->slots_in_use = 0;
+					tmem_objnode_free(to_free);
+				}
+			}
+			goto out;
+		}
+		tmem_objnode_free(pathp->objnode); /* 0 slots used, free it */
+		pathp--;
+	}
+	obj->objnode_tree_height = 0;
+	obj->objnode_tree_root = NULL;
+
+out:
+	if (slot != NULL)
+		obj->pampd_count--;
+	BUG_ON(obj->pampd_count < 0);
+	return slot;
+}
+
+/* recursively walk the objnode_tree destroying pampds and objnodes */
+static void tmem_objnode_node_destroy(struct tmem_obj *obj,
+					struct tmem_objnode *objnode,
+					unsigned int ht)
+{
+	int i;
+
+	if (ht == 0)
+		return;
+	for (i = 0; i < OBJNODE_TREE_MAP_SIZE; i++) {
+		if (objnode->slots[i]) {
+			if (ht == 1) {
+				obj->pampd_count--;
+				(*tmem_pamops.free)(objnode->slots[i],
+								obj->pool);
+				objnode->slots[i] = NULL;
+				continue;
+			}
+			tmem_objnode_node_destroy(obj, objnode->slots[i], ht-1);
+			tmem_objnode_free(objnode->slots[i]);
+			objnode->slots[i] = NULL;
+		}
+	}
+}
+
+static void tmem_pampd_destroy_all_in_obj(struct tmem_obj *obj)
+{
+	if (obj->objnode_tree_root == NULL)
+		return;
+	if (obj->objnode_tree_height == 0) {
+		obj->pampd_count--;
+		(*tmem_pamops.free)(obj->objnode_tree_root, obj->pool);
+	} else {
+		tmem_objnode_node_destroy(obj, obj->objnode_tree_root,
+					obj->objnode_tree_height);
+		tmem_objnode_free(obj->objnode_tree_root);
+		obj->objnode_tree_height = 0;
+	}
+	obj->objnode_tree_root = NULL;
+}
+
+/*
+ * Tmem is operated on by a set of well-defined actions:
+ * "put", "get", "flush", "flush_object", "new pool" and "destroy pool".
+ * (The tmem ABI allows for subpages and exchanges but these operations
+ * are not included in this implementation.)
+ *
+ * These "tmem core" operations are implemented in the following functions.
+ */
+
+/*
+ * "Put" a page, e.g. copy a page from the kernel into newly allocated
+ * PAM space (if such space is available).  Tmem_put is complicated by
+ * a corner case: What if a page with matching handle already exists in
+ * tmem?  To guarantee coherency, one of two actions is necessary: Either
+ * the data for the page must be overwritten, or the page must be
+ * "flushed" so that the data is not accessible to a subsequent "get".
+ * Since these "duplicate puts" are relatively rare, this implementation
+ * always flushes for simplicity.
+ */
+int tmem_put(struct tmem_pool *pool, struct tmem_oid *oidp, uint32_t index,
+		struct page *page)
+{
+	struct tmem_obj *obj = NULL, *objfound = NULL, *objnew = NULL;
+	void *pampd = NULL, *pampd_del = NULL;
+	int ret = -ENOMEM;
+	bool ephemeral;
+	struct tmem_hashbucket *hb;
+
+	ephemeral = is_ephemeral(pool);
+	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
+	spin_lock(&hb->lock);
+	obj = objfound = tmem_obj_find(hb, oidp);
+	if (obj != NULL) {
+		pampd = tmem_pampd_lookup_in_obj(objfound, index);
+		if (pampd != NULL) {
+			/* if found, is a dup put, flush the old one */
+			pampd_del = tmem_pampd_delete_from_obj(obj, index);
+			BUG_ON(pampd_del != pampd);
+			(*tmem_pamops.free)(pampd, pool);
+			if (obj->pampd_count == 0) {
+				objnew = obj;
+				objfound = NULL;
+			}
+			pampd = NULL;
+		}
+	} else {
+		obj = objnew = (*tmem_hostops.obj_alloc)(pool);
+		if (unlikely(obj == NULL)) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		tmem_obj_init(obj, hb, pool, oidp);
+	}
+	BUG_ON(obj == NULL);
+	BUG_ON(((objnew != obj) && (objfound != obj)) || (objnew == objfound));
+	pampd = (*tmem_pamops.create)(obj->pool, &obj->oid, index, page);
+	if (unlikely(pampd == NULL))
+		goto free;
+	ret = tmem_pampd_add_to_obj(obj, index, pampd);
+	if (unlikely(ret == -ENOMEM))
+		/* may have partially built objnode tree ("stump") */
+		goto delete_and_free;
+	goto out;
+
+delete_and_free:
+	(void)tmem_pampd_delete_from_obj(obj, index);
+free:
+	if (pampd)
+		(*tmem_pamops.free)(pampd, pool);
+	if (objnew) {
+		tmem_obj_free(objnew, hb);
+		(*tmem_hostops.obj_free)(objnew, pool);
+	}
+out:
+	spin_unlock(&hb->lock);
+	return ret;
+}
+
+/*
+ * "Get" a page, e.g. if one can be found, copy the tmem page with the
+ * matching handle from PAM space to the kernel.  By tmem definition,
+ * when a "get" is successful on an ephemeral page, the page is "flushed",
+ * and when a "get" is successful on a persistent page, the page is retained
+ * in tmem.  Note that to preserve
+ * coherency, "get" can never be skipped if tmem contains the data.
+ * That is, if a get is done with a certain handle and fails, any
+ * subsequent "get" must also fail (unless of course there is a
+ * "put" done with the same handle).
+
+ */
+int tmem_get(struct tmem_pool *pool, struct tmem_oid *oidp,
+				uint32_t index, struct page *page)
+{
+	struct tmem_obj *obj;
+	void *pampd;
+	bool ephemeral = is_ephemeral(pool);
+	uint32_t ret = -1;
+	struct tmem_hashbucket *hb;
+
+	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
+	spin_lock(&hb->lock);
+	obj = tmem_obj_find(hb, oidp);
+	if (obj == NULL)
+		goto out;
+	ephemeral = is_ephemeral(pool);
+	if (ephemeral)
+		pampd = tmem_pampd_delete_from_obj(obj, index);
+	else
+		pampd = tmem_pampd_lookup_in_obj(obj, index);
+	if (pampd == NULL)
+		goto out;
+	ret = (*tmem_pamops.get_data)(page, pampd, pool);
+	if (ret < 0)
+		goto out;
+	if (ephemeral) {
+		(*tmem_pamops.free)(pampd, pool);
+		if (obj->pampd_count == 0) {
+			tmem_obj_free(obj, hb);
+			(*tmem_hostops.obj_free)(obj, pool);
+			obj = NULL;
+		}
+	}
+	ret = 0;
+out:
+	spin_unlock(&hb->lock);
+	return ret;
+}
+
+/*
+ * If a page in tmem matches the handle, "flush" this page from tmem such
+ * that any subsequent "get" does not succeed (unless, of course, there
+ * was another "put" with the same handle).
+ */
+int tmem_flush_page(struct tmem_pool *pool,
+				struct tmem_oid *oidp, uint32_t index)
+{
+	struct tmem_obj *obj;
+	void *pampd;
+	int ret = -1;
+	struct tmem_hashbucket *hb;
+
+	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
+	spin_lock(&hb->lock);
+	obj = tmem_obj_find(hb, oidp);
+	if (obj == NULL)
+		goto out;
+	pampd = tmem_pampd_delete_from_obj(obj, index);
+	if (pampd == NULL)
+		goto out;
+	(*tmem_pamops.free)(pampd, pool);
+	if (obj->pampd_count == 0) {
+		tmem_obj_free(obj, hb);
+		(*tmem_hostops.obj_free)(obj, pool);
+	}
+	ret = 0;
+
+out:
+	spin_unlock(&hb->lock);
+	return ret;
+}
+
+/*
+ * "Flush" all pages in tmem matching this oid.
+ */
+int tmem_flush_object(struct tmem_pool *pool, struct tmem_oid *oidp)
+{
+	struct tmem_obj *obj;
+	struct tmem_hashbucket *hb;
+	int ret = -1;
+
+	hb = &pool->hashbucket[tmem_oid_hash(oidp)];
+	spin_lock(&hb->lock);
+	obj = tmem_obj_find(hb, oidp);
+	if (obj == NULL)
+		goto out;
+	tmem_pampd_destroy_all_in_obj(obj);
+	tmem_obj_free(obj, hb);
+	(*tmem_hostops.obj_free)(obj, pool);
+	ret = 0;
+
+out:
+	spin_unlock(&hb->lock);
+	return ret;
+}
+
+/*
+ * "Flush" all pages (and tmem_objs) from this tmem_pool and disable
+ * all subsequent access to this tmem_pool.
+ */
+int tmem_destroy_pool(struct tmem_pool *pool)
+{
+	int ret = -1;
+
+	if (pool == NULL)
+		goto out;
+	tmem_pool_flush(pool, 1);
+	ret = 0;
+out:
+	return ret;
+}
+
+static LIST_HEAD(tmem_global_pool_list);
+
+/*
+ * Create a new tmem_pool with the provided flag and return
+ * a pool id provided by the tmem host implementation.
+ */
+void tmem_new_pool(struct tmem_pool *pool, uint32_t flags)
+{
+	int persistent = flags & TMEM_POOL_PERSIST;
+	int shared = flags & TMEM_POOL_SHARED;
+	struct tmem_hashbucket *hb = &pool->hashbucket[0];
+	int i;
+
+	for (i = 0; i < TMEM_HASH_BUCKETS; i++, hb++) {
+		hb->obj_rb_root = RB_ROOT;
+		spin_lock_init(&hb->lock);
+	}
+	INIT_LIST_HEAD(&pool->pool_list);
+	atomic_set(&pool->obj_count, 0);
+	SET_SENTINEL(pool, POOL);
+	list_add_tail(&pool->pool_list, &tmem_global_pool_list);
+	pool->persistent = persistent;
+	pool->shared = shared;
+}
diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h
new file mode 100644
index 0000000..2e07e21
--- /dev/null
+++ b/drivers/staging/zcache/tmem.h
@@ -0,0 +1,195 @@
+/*
+ * tmem.h
+ *
+ * Transcendent memory
+ *
+ * Copyright (c) 2009-2011, Dan Magenheimer, Oracle Corp.
+ */
+
+#ifndef _TMEM_H_
+#define _TMEM_H_
+
+#include <linux/types.h>
+#include <linux/highmem.h>
+#include <linux/hash.h>
+#include <linux/atomic.h>
+
+/*
+ * These are pre-defined by the Xen<->Linux ABI
+ */
+#define TMEM_PUT_PAGE			4
+#define TMEM_GET_PAGE			5
+#define TMEM_FLUSH_PAGE			6
+#define TMEM_FLUSH_OBJECT		7
+#define TMEM_POOL_PERSIST		1
+#define TMEM_POOL_SHARED		2
+#define TMEM_POOL_PRECOMPRESSED		4
+#define TMEM_POOL_PAGESIZE_SHIFT	4
+#define TMEM_POOL_PAGESIZE_MASK		0xf
+#define TMEM_POOL_RESERVED_BITS		0x00ffff00
+
+/*
+ * sentinels have proven very useful for debugging but can be removed
+ * or disabled before final merge.
+ */
+#define SENTINELS
+#ifdef SENTINELS
+#define DECL_SENTINEL uint32_t sentinel;
+#define SET_SENTINEL(_x, _y) (_x->sentinel = _y##_SENTINEL)
+#define INVERT_SENTINEL(_x, _y) (_x->sentinel = ~_y##_SENTINEL)
+#define ASSERT_SENTINEL(_x, _y) WARN_ON(_x->sentinel != _y##_SENTINEL)
+#define ASSERT_INVERTED_SENTINEL(_x, _y) WARN_ON(_x->sentinel != ~_y##_SENTINEL)
+#else
+#define DECL_SENTINEL
+#define SET_SENTINEL(_x, _y) do { } while (0)
+#define INVERT_SENTINEL(_x, _y) do { } while (0)
+#define ASSERT_SENTINEL(_x, _y) do { } while (0)
+#define ASSERT_INVERTED_SENTINEL(_x, _y) do { } while (0)
+#endif
+
+#define ASSERT_SPINLOCK(_l)	WARN_ON(!spin_is_locked(_l))
+
+/*
+ * A pool is the highest-level data structure managed by tmem and
+ * usually corresponds to a large independent set of pages such as
+ * a filesystem.  Each pool has an id, and certain attributes and counters.
+ * It also contains a set of hash buckets, each of which contains an rbtree
+ * of objects and a lock to manage concurrency within the pool.
+ */
+
+#define TMEM_HASH_BUCKET_BITS	8
+#define TMEM_HASH_BUCKETS	(1<<TMEM_HASH_BUCKET_BITS)
+
+struct tmem_hashbucket {
+	struct rb_root obj_rb_root;
+	spinlock_t lock;
+};
+
+struct tmem_pool {
+	void *client; /* "up" for some clients, avoids table lookup */
+	struct list_head pool_list;
+	uint32_t pool_id;
+	bool persistent;
+	bool shared;
+	atomic_t obj_count;
+	atomic_t refcount;
+	struct tmem_hashbucket hashbucket[TMEM_HASH_BUCKETS];
+	DECL_SENTINEL
+};
+
+#define is_persistent(_p)  (_p->persistent)
+#define is_ephemeral(_p)   (!(_p->persistent))
+
+/*
+ * An object id ("oid") is large: 192-bits (to ensure, for example, files
+ * in a modern filesystem can be uniquely identified).
+ */
+
+struct tmem_oid {
+	uint64_t oid[3];
+};
+
+static inline void tmem_oid_set_invalid(struct tmem_oid *oidp)
+{
+	oidp->oid[0] = oidp->oid[1] = oidp->oid[2] = -1UL;
+}
+
+static inline bool tmem_oid_valid(struct tmem_oid *oidp)
+{
+	return oidp->oid[0] != -1UL || oidp->oid[1] != -1UL ||
+		oidp->oid[2] != -1UL;
+}
+
+static inline int tmem_oid_compare(struct tmem_oid *left,
+					struct tmem_oid *right)
+{
+	int ret;
+
+	if (left->oid[2] == right->oid[2]) {
+		if (left->oid[1] == right->oid[1]) {
+			if (left->oid[0] == right->oid[0])
+				ret = 0;
+			else if (left->oid[0] < right->oid[0])
+				ret = -1;
+			else
+				return 1;
+		} else if (left->oid[1] < right->oid[1])
+			ret = -1;
+		else
+			ret = 1;
+	} else if (left->oid[2] < right->oid[2])
+		ret = -1;
+	else
+		ret = 1;
+	return ret;
+}
+
+static inline unsigned tmem_oid_hash(struct tmem_oid *oidp)
+{
+	return hash_long(oidp->oid[0] ^ oidp->oid[1] ^ oidp->oid[2],
+				TMEM_HASH_BUCKET_BITS);
+}
+
+/*
+ * A tmem_obj contains an identifier (oid), pointers to the parent
+ * pool and the rb_tree to which it belongs, counters, and an ordered
+ * set of pampds, structured in a radix-tree-like tree.  The intermediate
+ * nodes of the tree are called tmem_objnodes.
+ */
+
+struct tmem_objnode;
+
+struct tmem_obj {
+	struct tmem_oid oid;
+	struct tmem_pool *pool;
+	struct rb_node rb_tree_node;
+	struct tmem_objnode *objnode_tree_root;
+	unsigned int objnode_tree_height;
+	unsigned long objnode_count;
+	long pampd_count;
+	DECL_SENTINEL
+};
+
+#define OBJNODE_TREE_MAP_SHIFT 6
+#define OBJNODE_TREE_MAP_SIZE (1UL << OBJNODE_TREE_MAP_SHIFT)
+#define OBJNODE_TREE_MAP_MASK (OBJNODE_TREE_MAP_SIZE-1)
+#define OBJNODE_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long))
+#define OBJNODE_TREE_MAX_PATH \
+		(OBJNODE_TREE_INDEX_BITS/OBJNODE_TREE_MAP_SHIFT + 2)
+
+struct tmem_objnode {
+	struct tmem_obj *obj;
+	DECL_SENTINEL
+	void *slots[OBJNODE_TREE_MAP_SIZE];
+	unsigned int slots_in_use;
+};
+
+/* pampd abstract datatype methods provided by the PAM implementation */
+struct tmem_pamops {
+	void *(*create)(struct tmem_pool *, struct tmem_oid *, uint32_t,
+			struct page *);
+	int (*get_data)(struct page *, void *, struct tmem_pool *);
+	void (*free)(void *, struct tmem_pool *);
+};
+extern void tmem_register_pamops(struct tmem_pamops *m);
+
+/* memory allocation methods provided by the host implementation */
+struct tmem_hostops {
+	struct tmem_obj *(*obj_alloc)(struct tmem_pool *);
+	void (*obj_free)(struct tmem_obj *, struct tmem_pool *);
+	struct tmem_objnode *(*objnode_alloc)(struct tmem_pool *);
+	void (*objnode_free)(struct tmem_objnode *, struct tmem_pool *);
+};
+extern void tmem_register_hostops(struct tmem_hostops *m);
+
+/* core tmem accessor functions */
+extern int tmem_put(struct tmem_pool *, struct tmem_oid *, uint32_t index,
+			struct page *page);
+extern int tmem_get(struct tmem_pool *, struct tmem_oid *, uint32_t index,
+			struct page *page);
+extern int tmem_flush_page(struct tmem_pool *, struct tmem_oid *,
+			uint32_t index);
+extern int tmem_flush_object(struct tmem_pool *, struct tmem_oid *);
+extern int tmem_destroy_pool(struct tmem_pool *);
+extern void tmem_new_pool(struct tmem_pool *, uint32_t);
+#endif /* _TMEM_H */
diff --git a/drivers/staging/zcache/zcache.c b/drivers/staging/zcache/zcache.c
new file mode 100644
index 0000000..b8a2b30
--- /dev/null
+++ b/drivers/staging/zcache/zcache.c
@@ -0,0 +1,1658 @@
+/*
+ * zcache.c
+ *
+ * Copyright (c) 2010,2011, Dan Magenheimer, Oracle Corp.
+ * Copyright (c) 2010,2011, Nitin Gupta
+ *
+ * Zcache provides an in-kernel "host implementation" for transcendent memory
+ * and, thus indirectly, for cleancache and frontswap.  Zcache includes two
+ * page-accessible memory [1] interfaces, both utilizing lzo1x compression:
+ * 1) "compression buddies" ("zbud") is used for ephemeral pages
+ * 2) xvmalloc is used for persistent pages.
+ * Xvmalloc (based on the TLSF allocator) has very low fragmentation
+ * so maximizes space efficiency, while zbud allows pairs (and potentially,
+ * in the future, more than a pair of) compressed pages to be closely linked
+ * so that reclaiming can be done via the kernel's physical-page-oriented
+ * "shrinker" interface.
+ *
+ * [1] For a definition of page-accessible memory (aka PAM), see:
+ *   http://marc.info/?l=linux-mm&m=127811271605009
+ */
+
+#include <linux/cpu.h>
+#include <linux/highmem.h>
+#include <linux/list.h>
+#include <linux/lzo.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include "tmem.h"
+
+#include "../zram/xvmalloc.h" /* if built in drivers/staging */
+
+#if (!defined(CONFIG_CLEANCACHE) && !defined(CONFIG_FRONTSWAP))
+#error "zcache is useless without CONFIG_CLEANCACHE or CONFIG_FRONTSWAP"
+#endif
+#ifdef CONFIG_CLEANCACHE
+#include <linux/cleancache.h>
+#endif
+#ifdef CONFIG_FRONTSWAP
+#include <linux/frontswap.h>
+#endif
+
+#if 0
+/* this is more aggressive but may cause other problems? */
+#define ZCACHE_GFP_MASK	(GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN)
+#else
+#define ZCACHE_GFP_MASK \
+	(__GFP_FS | __GFP_NORETRY | __GFP_NOWARN | __GFP_NOMEMALLOC)
+#endif
+
+/**********
+ * Compression buddies ("zbud") provides for packing two (or, possibly
+ * in the future, more) compressed ephemeral pages into a single "raw"
+ * (physical) page and tracking them with data structures so that
+ * the raw pages can be easily reclaimed.
+ *
+ * A zbud page ("zbpg") is an aligned page containing a list_head,
+ * a lock, and two "zbud headers".  The remainder of the physical
+ * page is divided up into aligned 64-byte "chunks" which contain
+ * the compressed data for zero, one, or two zbuds.  Each zbpg
+ * resides on: (1) an "unused list" if it has no zbuds; (2) a
+ * "buddied" list if it is fully populated  with two zbuds; or
+ * (3) one of PAGE_SIZE/64 "unbuddied" lists indexed by how many chunks
+ * the one unbuddied zbud uses.  The data inside a zbpg cannot be
+ * read or written unless the zbpg's lock is held.
+ */
+
+#define ZBH_SENTINEL  0x43214321
+#define ZBPG_SENTINEL  0xdeadbeef
+
+#define ZBUD_MAX_BUDS 2
+
+struct zbud_hdr {
+	uint32_t pool_id;
+	struct tmem_oid oid;
+	uint32_t index;
+	uint16_t size; /* compressed size in bytes, zero means unused */
+	DECL_SENTINEL
+};
+
+struct zbud_page {
+	struct list_head bud_list;
+	spinlock_t lock;
+	struct zbud_hdr buddy[ZBUD_MAX_BUDS];
+	DECL_SENTINEL
+	/* followed by NUM_CHUNK aligned CHUNK_SIZE-byte chunks */
+};
+
+#define CHUNK_SHIFT	6
+#define CHUNK_SIZE	(1 << CHUNK_SHIFT)
+#define CHUNK_MASK	(~(CHUNK_SIZE-1))
+#define NCHUNKS		(((PAGE_SIZE - sizeof(struct zbud_page)) & \
+				CHUNK_MASK) >> CHUNK_SHIFT)
+#define MAX_CHUNK	(NCHUNKS-1)
+
+static struct {
+	struct list_head list;
+	unsigned count;
+} zbud_unbuddied[NCHUNKS];
+/* list N contains pages with N chunks USED and NCHUNKS-N unused */
+/* element 0 is never used but optimizing that isn't worth it */
+static unsigned long zbud_cumul_chunk_counts[NCHUNKS];
+
+struct list_head zbud_buddied_list;
+static unsigned long zcache_zbud_buddied_count;
+
+/* protects the buddied list and all unbuddied lists */
+static DEFINE_SPINLOCK(zbud_budlists_spinlock);
+
+static LIST_HEAD(zbpg_unused_list);
+static unsigned long zcache_zbpg_unused_list_count;
+
+/* protects the unused page list */
+static DEFINE_SPINLOCK(zbpg_unused_list_spinlock);
+
+static atomic_t zcache_zbud_curr_raw_pages;
+static atomic_t zcache_zbud_curr_zpages;
+static unsigned long zcache_zbud_curr_zbytes;
+static unsigned long zcache_zbud_cumul_zpages;
+static unsigned long zcache_zbud_cumul_zbytes;
+static unsigned long zcache_compress_poor;
+
+/* forward references */
+static void *zcache_get_free_page(void);
+static void zcache_free_page(void *p);
+
+/*
+ * zbud helper functions
+ */
+
+static inline unsigned zbud_max_buddy_size(void)
+{
+	return MAX_CHUNK << CHUNK_SHIFT;
+}
+
+static inline unsigned zbud_size_to_chunks(unsigned size)
+{
+	BUG_ON(size == 0 || size > zbud_max_buddy_size());
+	return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT;
+}
+
+static inline int zbud_budnum(struct zbud_hdr *zh)
+{
+	unsigned offset = (unsigned long)zh & (PAGE_SIZE - 1);
+	struct zbud_page *zbpg = NULL;
+	unsigned budnum = -1U;
+	int i;
+
+	for (i = 0; i < ZBUD_MAX_BUDS; i++)
+		if (offset == offsetof(typeof(*zbpg), buddy[i])) {
+			budnum = i;
+			break;
+		}
+	BUG_ON(budnum == -1U);
+	return budnum;
+}
+
+static char *zbud_data(struct zbud_hdr *zh, unsigned size)
+{
+	struct zbud_page *zbpg;
+	char *p;
+	unsigned budnum;
+
+	ASSERT_SENTINEL(zh, ZBH);
+	budnum = zbud_budnum(zh);
+	BUG_ON(size == 0 || size > zbud_max_buddy_size());
+	zbpg = container_of(zh, struct zbud_page, buddy[budnum]);
+	ASSERT_SPINLOCK(&zbpg->lock);
+	p = (char *)zbpg;
+	if (budnum == 0)
+		p += ((sizeof(struct zbud_page) + CHUNK_SIZE - 1) &
+							CHUNK_MASK);
+	else if (budnum == 1)
+		p += PAGE_SIZE - ((size + CHUNK_SIZE - 1) & CHUNK_MASK);
+	return p;
+}
+
+/*
+ * zbud raw page management
+ */
+
+static struct zbud_page *zbud_alloc_raw_page(void)
+{
+	struct zbud_page *zbpg = NULL;
+	struct zbud_hdr *zh0, *zh1;
+	bool recycled = 0;
+
+	/* if any pages on the zbpg list, use one */
+	spin_lock(&zbpg_unused_list_spinlock);
+	if (!list_empty(&zbpg_unused_list)) {
+		zbpg = list_first_entry(&zbpg_unused_list,
+				struct zbud_page, bud_list);
+		list_del_init(&zbpg->bud_list);
+		zcache_zbpg_unused_list_count--;
+		recycled = 1;
+	}
+	spin_unlock(&zbpg_unused_list_spinlock);
+	if (zbpg == NULL)
+		/* none on zbpg list, try to get a kernel page */
+		zbpg = zcache_get_free_page();
+	if (likely(zbpg != NULL)) {
+		INIT_LIST_HEAD(&zbpg->bud_list);
+		zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1];
+		spin_lock_init(&zbpg->lock);
+		if (recycled) {
+			ASSERT_INVERTED_SENTINEL(zbpg, ZBPG);
+			SET_SENTINEL(zbpg, ZBPG);
+			BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid));
+			BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid));
+		} else {
+			atomic_inc(&zcache_zbud_curr_raw_pages);
+			INIT_LIST_HEAD(&zbpg->bud_list);
+			SET_SENTINEL(zbpg, ZBPG);
+			zh0->size = 0; zh1->size = 0;
+			tmem_oid_set_invalid(&zh0->oid);
+			tmem_oid_set_invalid(&zh1->oid);
+		}
+	}
+	return zbpg;
+}
+
+static void zbud_free_raw_page(struct zbud_page *zbpg)
+{
+	struct zbud_hdr *zh0 = &zbpg->buddy[0], *zh1 = &zbpg->buddy[1];
+
+	ASSERT_SENTINEL(zbpg, ZBPG);
+	BUG_ON(!list_empty(&zbpg->bud_list));
+	ASSERT_SPINLOCK(&zbpg->lock);
+	BUG_ON(zh0->size != 0 || tmem_oid_valid(&zh0->oid));
+	BUG_ON(zh1->size != 0 || tmem_oid_valid(&zh1->oid));
+	INVERT_SENTINEL(zbpg, ZBPG);
+	spin_unlock(&zbpg->lock);
+	spin_lock(&zbpg_unused_list_spinlock);
+	list_add(&zbpg->bud_list, &zbpg_unused_list);
+	zcache_zbpg_unused_list_count++;
+	spin_unlock(&zbpg_unused_list_spinlock);
+}
+
+/*
+ * core zbud handling routines
+ */
+
+static unsigned zbud_free(struct zbud_hdr *zh)
+{
+	unsigned size;
+
+	ASSERT_SENTINEL(zh, ZBH);
+	BUG_ON(!tmem_oid_valid(&zh->oid));
+	size = zh->size;
+	BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size());
+	zh->size = 0;
+	tmem_oid_set_invalid(&zh->oid);
+	INVERT_SENTINEL(zh, ZBH);
+	zcache_zbud_curr_zbytes -= size;
+	atomic_dec(&zcache_zbud_curr_zpages);
+	return size;
+}
+
+static void zbud_free_and_delist(struct zbud_hdr *zh)
+{
+	unsigned chunks;
+	struct zbud_hdr *zh_other;
+	unsigned budnum = zbud_budnum(zh), size;
+	struct zbud_page *zbpg =
+		container_of(zh, struct zbud_page, buddy[budnum]);
+
+	spin_lock(&zbpg->lock);
+	if (list_empty(&zbpg->bud_list)) {
+		/* ignore zombie page... see zbud_evict_pages() */
+		spin_unlock(&zbpg->lock);
+		return;
+	}
+	size = zbud_free(zh);
+	ASSERT_SPINLOCK(&zbpg->lock);
+	zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0];
+	if (zh_other->size == 0) { /* was unbuddied: unlist and free */
+		chunks = zbud_size_to_chunks(size) ;
+		spin_lock(&zbud_budlists_spinlock);
+		BUG_ON(list_empty(&zbud_unbuddied[chunks].list));
+		list_del_init(&zbpg->bud_list);
+		zbud_unbuddied[chunks].count--;
+		spin_unlock(&zbud_budlists_spinlock);
+		zbud_free_raw_page(zbpg);
+	} else { /* was buddied: move remaining buddy to unbuddied list */
+		chunks = zbud_size_to_chunks(zh_other->size) ;
+		spin_lock(&zbud_budlists_spinlock);
+		list_del_init(&zbpg->bud_list);
+		zcache_zbud_buddied_count--;
+		list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list);
+		zbud_unbuddied[chunks].count++;
+		spin_unlock(&zbud_budlists_spinlock);
+		spin_unlock(&zbpg->lock);
+	}
+}
+
+static struct zbud_hdr *zbud_create(uint32_t pool_id, struct tmem_oid *oid,
+					uint32_t index, struct page *page,
+					void *cdata, unsigned size)
+{
+	struct zbud_hdr *zh0, *zh1, *zh = NULL;
+	struct zbud_page *zbpg = NULL, *ztmp;
+	unsigned nchunks;
+	char *to;
+	int i, found_good_buddy = 0;
+
+	nchunks = zbud_size_to_chunks(size) ;
+	for (i = MAX_CHUNK - nchunks + 1; i > 0; i--) {
+		spin_lock(&zbud_budlists_spinlock);
+		if (!list_empty(&zbud_unbuddied[i].list)) {
+			list_for_each_entry_safe(zbpg, ztmp,
+				    &zbud_unbuddied[i].list, bud_list) {
+				if (spin_trylock(&zbpg->lock)) {
+					found_good_buddy = i;
+					goto found_unbuddied;
+				}
+			}
+		}
+		spin_unlock(&zbud_budlists_spinlock);
+	}
+	/* didn't find a good buddy, try allocating a new page */
+	zbpg = zbud_alloc_raw_page();
+	if (unlikely(zbpg == NULL))
+		goto out;
+	/* ok, have a page, now compress the data before taking locks */
+	spin_lock(&zbpg->lock);
+	spin_lock(&zbud_budlists_spinlock);
+	list_add_tail(&zbpg->bud_list, &zbud_unbuddied[nchunks].list);
+	zbud_unbuddied[nchunks].count++;
+	zh = &zbpg->buddy[0];
+	goto init_zh;
+
+found_unbuddied:
+	ASSERT_SPINLOCK(&zbpg->lock);
+	zh0 = &zbpg->buddy[0]; zh1 = &zbpg->buddy[1];
+	BUG_ON(!((zh0->size == 0) ^ (zh1->size == 0)));
+	if (zh0->size != 0) { /* buddy0 in use, buddy1 is vacant */
+		ASSERT_SENTINEL(zh0, ZBH);
+		zh = zh1;
+	} else if (zh1->size != 0) { /* buddy1 in use, buddy0 is vacant */
+		ASSERT_SENTINEL(zh1, ZBH);
+		zh = zh0;
+	} else
+		BUG();
+	list_del_init(&zbpg->bud_list);
+	zbud_unbuddied[found_good_buddy].count--;
+	list_add_tail(&zbpg->bud_list, &zbud_buddied_list);
+	zcache_zbud_buddied_count++;
+
+init_zh:
+	SET_SENTINEL(zh, ZBH);
+	zh->size = size;
+	zh->index = index;
+	zh->oid = *oid;
+	zh->pool_id = pool_id;
+	/* can wait to copy the data until the list locks are dropped */
+	spin_unlock(&zbud_budlists_spinlock);
+
+	to = zbud_data(zh, size);
+	memcpy(to, cdata, size);
+	spin_unlock(&zbpg->lock);
+	zbud_cumul_chunk_counts[nchunks]++;
+	atomic_inc(&zcache_zbud_curr_zpages);
+	zcache_zbud_cumul_zpages++;
+	zcache_zbud_curr_zbytes += size;
+	zcache_zbud_cumul_zbytes += size;
+out:
+	return zh;
+}
+
+static int zbud_decompress(struct page *page, struct zbud_hdr *zh)
+{
+	struct zbud_page *zbpg;
+	unsigned budnum = zbud_budnum(zh);
+	size_t out_len = PAGE_SIZE;
+	char *to_va, *from_va;
+	unsigned size;
+	int ret = 0;
+
+	zbpg = container_of(zh, struct zbud_page, buddy[budnum]);
+	spin_lock(&zbpg->lock);
+	if (list_empty(&zbpg->bud_list)) {
+		/* ignore zombie page... see zbud_evict_pages() */
+		ret = -EINVAL;
+		goto out;
+	}
+	ASSERT_SENTINEL(zh, ZBH);
+	BUG_ON(zh->size == 0 || zh->size > zbud_max_buddy_size());
+	to_va = kmap_atomic(page, KM_USER0);
+	size = zh->size;
+	from_va = zbud_data(zh, size);
+	ret = lzo1x_decompress_safe(from_va, size, to_va, &out_len);
+	BUG_ON(ret != LZO_E_OK);
+	BUG_ON(out_len != PAGE_SIZE);
+	kunmap_atomic(to_va, KM_USER0);
+out:
+	spin_unlock(&zbpg->lock);
+	return ret;
+}
+
+/*
+ * The following routines handle shrinking of ephemeral pages by evicting
+ * pages "least valuable" first.
+ */
+
+static unsigned long zcache_evicted_raw_pages;
+static unsigned long zcache_evicted_buddied_pages;
+static unsigned long zcache_evicted_unbuddied_pages;
+
+static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid);
+static void zcache_put_pool(struct tmem_pool *pool);
+
+/*
+ * Flush and free all zbuds in a zbpg, then free the pageframe
+ */
+static void zbud_evict_zbpg(struct zbud_page *zbpg)
+{
+	struct zbud_hdr *zh;
+	int i, j;
+	uint32_t pool_id[ZBUD_MAX_BUDS], index[ZBUD_MAX_BUDS];
+	struct tmem_oid oid[ZBUD_MAX_BUDS];
+	struct tmem_pool *pool;
+
+	ASSERT_SPINLOCK(&zbpg->lock);
+	BUG_ON(!list_empty(&zbpg->bud_list));
+	for (i = 0, j = 0; i < ZBUD_MAX_BUDS; i++) {
+		zh = &zbpg->buddy[i];
+		if (zh->size) {
+			pool_id[j] = zh->pool_id;
+			oid[j] = zh->oid;
+			index[j] = zh->index;
+			j++;
+			zbud_free(zh);
+		}
+	}
+	spin_unlock(&zbpg->lock);
+	for (i = 0; i < j; i++) {
+		pool = zcache_get_pool_by_id(pool_id[i]);
+		if (pool != NULL) {
+			tmem_flush_page(pool, &oid[i], index[i]);
+			zcache_put_pool(pool);
+		}
+	}
+	ASSERT_SENTINEL(zbpg, ZBPG);
+	spin_lock(&zbpg->lock);
+	zbud_free_raw_page(zbpg);
+}
+
+/*
+ * Free nr pages.  This code is funky because we want to hold the locks
+ * protecting various lists for as short a time as possible, and in some
+ * circumstances the list may change asynchronously when the list lock is
+ * not held.  In some cases we also trylock not only to avoid waiting on a
+ * page in use by another cpu, but also to avoid potential deadlock due to
+ * lock inversion.
+ */
+static void zbud_evict_pages(int nr)
+{
+	struct zbud_page *zbpg;
+	int i;
+
+	/* first try freeing any pages on unused list */
+retry_unused_list:
+	spin_lock_bh(&zbpg_unused_list_spinlock);
+	if (!list_empty(&zbpg_unused_list)) {
+		/* can't walk list here, since it may change when unlocked */
+		zbpg = list_first_entry(&zbpg_unused_list,
+				struct zbud_page, bud_list);
+		list_del_init(&zbpg->bud_list);
+		zcache_zbpg_unused_list_count--;
+		atomic_dec(&zcache_zbud_curr_raw_pages);
+		spin_unlock_bh(&zbpg_unused_list_spinlock);
+		zcache_free_page(zbpg);
+		zcache_evicted_raw_pages++;
+		if (--nr <= 0)
+			goto out;
+		goto retry_unused_list;
+	}
+	spin_unlock_bh(&zbpg_unused_list_spinlock);
+
+	/* now try freeing unbuddied pages, starting with least space avail */
+	for (i = 0; i < MAX_CHUNK; i++) {
+retry_unbud_list_i:
+		spin_lock_bh(&zbud_budlists_spinlock);
+		if (list_empty(&zbud_unbuddied[i].list)) {
+			spin_unlock_bh(&zbud_budlists_spinlock);
+			continue;
+		}
+		list_for_each_entry(zbpg, &zbud_unbuddied[i].list, bud_list) {
+			if (unlikely(!spin_trylock(&zbpg->lock)))
+				continue;
+			list_del_init(&zbpg->bud_list);
+			zbud_unbuddied[i].count--;
+			spin_unlock(&zbud_budlists_spinlock);
+			zcache_evicted_unbuddied_pages++;
+			/* want budlists unlocked when doing zbpg eviction */
+			zbud_evict_zbpg(zbpg);
+			local_bh_enable();
+			if (--nr <= 0)
+				goto out;
+			goto retry_unbud_list_i;
+		}
+		spin_unlock_bh(&zbud_budlists_spinlock);
+	}
+
+	/* as a last resort, free buddied pages */
+retry_bud_list:
+	spin_lock_bh(&zbud_budlists_spinlock);
+	if (list_empty(&zbud_buddied_list)) {
+		spin_unlock_bh(&zbud_budlists_spinlock);
+		goto out;
+	}
+	list_for_each_entry(zbpg, &zbud_buddied_list, bud_list) {
+		if (unlikely(!spin_trylock(&zbpg->lock)))
+			continue;
+		list_del_init(&zbpg->bud_list);
+		zcache_zbud_buddied_count--;
+		spin_unlock(&zbud_budlists_spinlock);
+		zcache_evicted_buddied_pages++;
+		/* want budlists unlocked when doing zbpg eviction */
+		zbud_evict_zbpg(zbpg);
+		local_bh_enable();
+		if (--nr <= 0)
+			goto out;
+		goto retry_bud_list;
+	}
+	spin_unlock_bh(&zbud_budlists_spinlock);
+out:
+	return;
+}
+
+static void zbud_init(void)
+{
+	int i;
+
+	INIT_LIST_HEAD(&zbud_buddied_list);
+	zcache_zbud_buddied_count = 0;
+	for (i = 0; i < NCHUNKS; i++) {
+		INIT_LIST_HEAD(&zbud_unbuddied[i].list);
+		zbud_unbuddied[i].count = 0;
+	}
+}
+
+#ifdef CONFIG_SYSFS
+/*
+ * These sysfs routines show a nice distribution of how many zbpg's are
+ * currently (and have ever been placed) in each unbuddied list.  It's fun
+ * to watch but can probably go away before final merge.
+ */
+static int zbud_show_unbuddied_list_counts(char *buf)
+{
+	int i;
+	char *p = buf;
+
+	for (i = 0; i < NCHUNKS - 1; i++)
+		p += sprintf(p, "%u ", zbud_unbuddied[i].count);
+	p += sprintf(p, "%d\n", zbud_unbuddied[i].count);
+	return p - buf;
+}
+
+static int zbud_show_cumul_chunk_counts(char *buf)
+{
+	unsigned long i, chunks = 0, total_chunks = 0, sum_total_chunks = 0;
+	unsigned long total_chunks_lte_21 = 0, total_chunks_lte_32 = 0;
+	unsigned long total_chunks_lte_42 = 0;
+	char *p = buf;
+
+	for (i = 0; i < NCHUNKS; i++) {
+		p += sprintf(p, "%lu ", zbud_cumul_chunk_counts[i]);
+		chunks += zbud_cumul_chunk_counts[i];
+		total_chunks += zbud_cumul_chunk_counts[i];
+		sum_total_chunks += i * zbud_cumul_chunk_counts[i];
+		if (i == 21)
+			total_chunks_lte_21 = total_chunks;
+		if (i == 32)
+			total_chunks_lte_32 = total_chunks;
+		if (i == 42)
+			total_chunks_lte_42 = total_chunks;
+	}
+	p += sprintf(p, "<=21:%lu <=32:%lu <=42:%lu, mean:%lu\n",
+		total_chunks_lte_21, total_chunks_lte_32, total_chunks_lte_42,
+		chunks == 0 ? 0 : sum_total_chunks / chunks);
+	return p - buf;
+}
+#endif
+
+/**********
+ * This "zv" PAM implementation combines the TLSF-based xvMalloc
+ * with lzo1x compression to maximize the amount of data that can
+ * be packed into a physical page.
+ *
+ * Zv represents a PAM page with the index and object (plus a "size" value
+ * necessary for decompression) immediately preceding the compressed data.
+ */
+
+#define ZVH_SENTINEL  0x43214321
+
+struct zv_hdr {
+	uint32_t pool_id;
+	struct tmem_oid oid;
+	uint32_t index;
+	DECL_SENTINEL
+};
+
+static const int zv_max_page_size = (PAGE_SIZE / 8) * 7;
+
+static struct zv_hdr *zv_create(struct xv_pool *xvpool, uint32_t pool_id,
+				struct tmem_oid *oid, uint32_t index,
+				void *cdata, unsigned clen)
+{
+	struct page *page;
+	struct zv_hdr *zv = NULL;
+	uint32_t offset;
+	int ret;
+
+	BUG_ON(!irqs_disabled());
+	ret = xv_malloc(xvpool, clen + sizeof(struct zv_hdr),
+			&page, &offset, ZCACHE_GFP_MASK);
+	if (unlikely(ret))
+		goto out;
+	zv = kmap_atomic(page, KM_USER0) + offset;
+	zv->index = index;
+	zv->oid = *oid;
+	zv->pool_id = pool_id;
+	SET_SENTINEL(zv, ZVH);
+	memcpy((char *)zv + sizeof(struct zv_hdr), cdata, clen);
+	kunmap_atomic(zv, KM_USER0);
+out:
+	return zv;
+}
+
+static void zv_free(struct xv_pool *xvpool, struct zv_hdr *zv)
+{
+	unsigned long flags;
+	struct page *page;
+	uint32_t offset;
+	uint16_t size;
+
+	ASSERT_SENTINEL(zv, ZVH);
+	size = xv_get_object_size(zv) - sizeof(*zv);
+	BUG_ON(size == 0 || size > zv_max_page_size);
+	INVERT_SENTINEL(zv, ZVH);
+	page = virt_to_page(zv);
+	offset = (unsigned long)zv & ~PAGE_MASK;
+	local_irq_save(flags);
+	xv_free(xvpool, page, offset);
+	local_irq_restore(flags);
+}
+
+static void zv_decompress(struct page *page, struct zv_hdr *zv)
+{
+	size_t clen = PAGE_SIZE;
+	char *to_va;
+	unsigned size;
+	int ret;
+
+	ASSERT_SENTINEL(zv, ZVH);
+	size = xv_get_object_size(zv) - sizeof(*zv);
+	BUG_ON(size == 0 || size > zv_max_page_size);
+	to_va = kmap_atomic(page, KM_USER0);
+	ret = lzo1x_decompress_safe((char *)zv + sizeof(*zv),
+					size, to_va, &clen);
+	kunmap_atomic(to_va, KM_USER0);
+	BUG_ON(ret != LZO_E_OK);
+	BUG_ON(clen != PAGE_SIZE);
+}
+
+/*
+ * zcache core code starts here
+ */
+
+/* useful stats not collected by cleancache or frontswap */
+static unsigned long zcache_flush_total;
+static unsigned long zcache_flush_found;
+static unsigned long zcache_flobj_total;
+static unsigned long zcache_flobj_found;
+static unsigned long zcache_failed_eph_puts;
+static unsigned long zcache_failed_pers_puts;
+
+#define MAX_POOLS_PER_CLIENT 16
+
+static struct {
+	struct tmem_pool *tmem_pools[MAX_POOLS_PER_CLIENT];
+	struct xv_pool *xvpool;
+} zcache_client;
+
+/*
+ * Tmem operations assume the poolid implies the invoking client.
+ * Zcache only has one client (the kernel itself), so translate
+ * the poolid into the tmem_pool allocated for it.  A KVM version
+ * of zcache would have one client per guest and each client might
+ * have a poolid==N.
+ */
+static struct tmem_pool *zcache_get_pool_by_id(uint32_t poolid)
+{
+	struct tmem_pool *pool = NULL;
+
+	if (poolid >= 0) {
+		pool = zcache_client.tmem_pools[poolid];
+		if (pool != NULL)
+			atomic_inc(&pool->refcount);
+	}
+	return pool;
+}
+
+static void zcache_put_pool(struct tmem_pool *pool)
+{
+	if (pool != NULL)
+		atomic_dec(&pool->refcount);
+}
+
+/* counters for debugging */
+static unsigned long zcache_failed_get_free_pages;
+static unsigned long zcache_failed_alloc;
+static unsigned long zcache_put_to_flush;
+static unsigned long zcache_aborted_preload;
+static unsigned long zcache_aborted_shrink;
+
+/*
+ * Ensure that memory allocation requests in zcache don't result
+ * in direct reclaim requests via the shrinker, which would cause
+ * an infinite loop.  Maybe a GFP flag would be better?
+ */
+static DEFINE_SPINLOCK(zcache_direct_reclaim_lock);
+
+/*
+ * for now, used named slabs so can easily track usage; later can
+ * either just use kmalloc, or perhaps add a slab-like allocator
+ * to more carefully manage total memory utilization
+ */
+static struct kmem_cache *zcache_objnode_cache;
+static struct kmem_cache *zcache_obj_cache;
+static atomic_t zcache_curr_obj_count = ATOMIC_INIT(0);
+static unsigned long zcache_curr_obj_count_max;
+static atomic_t zcache_curr_objnode_count = ATOMIC_INIT(0);
+static unsigned long zcache_curr_objnode_count_max;
+
+/*
+ * to avoid memory allocation recursion (e.g. due to direct reclaim), we
+ * preload all necessary data structures so the hostops callbacks never
+ * actually do a malloc
+ */
+struct zcache_preload {
+	void *page;
+	struct tmem_obj *obj;
+	int nr;
+	struct tmem_objnode *objnodes[OBJNODE_TREE_MAX_PATH];
+};
+static DEFINE_PER_CPU(struct zcache_preload, zcache_preloads) = { 0, };
+
+static int zcache_do_preload(struct tmem_pool *pool)
+{
+	struct zcache_preload *kp;
+	struct tmem_objnode *objnode;
+	struct tmem_obj *obj;
+	void *page;
+	int ret = -ENOMEM;
+
+	if (unlikely(zcache_objnode_cache == NULL))
+		goto out;
+	if (unlikely(zcache_obj_cache == NULL))
+		goto out;
+	if (!spin_trylock(&zcache_direct_reclaim_lock)) {
+		zcache_aborted_preload++;
+		goto out;
+	}
+	preempt_disable();
+	kp = &__get_cpu_var(zcache_preloads);
+	while (kp->nr < ARRAY_SIZE(kp->objnodes)) {
+		preempt_enable_no_resched();
+		objnode = kmem_cache_alloc(zcache_objnode_cache,
+				ZCACHE_GFP_MASK);
+		if (unlikely(objnode == NULL)) {
+			zcache_failed_alloc++;
+			goto unlock_out;
+		}
+		preempt_disable();
+		kp = &__get_cpu_var(zcache_preloads);
+		if (kp->nr < ARRAY_SIZE(kp->objnodes))
+			kp->objnodes[kp->nr++] = objnode;
+		else
+			kmem_cache_free(zcache_objnode_cache, objnode);
+	}
+	preempt_enable_no_resched();
+	obj = kmem_cache_alloc(zcache_obj_cache, ZCACHE_GFP_MASK);
+	if (unlikely(obj == NULL)) {
+		zcache_failed_alloc++;
+		goto unlock_out;
+	}
+	page = (void *)__get_free_page(ZCACHE_GFP_MASK);
+	if (unlikely(page == NULL)) {
+		zcache_failed_get_free_pages++;
+		kmem_cache_free(zcache_obj_cache, obj);
+		goto unlock_out;
+	}
+	preempt_disable();
+	kp = &__get_cpu_var(zcache_preloads);
+	if (kp->obj == NULL)
+		kp->obj = obj;
+	else
+		kmem_cache_free(zcache_obj_cache, obj);
+	if (kp->page == NULL)
+		kp->page = page;
+	else
+		free_page((unsigned long)page);
+	ret = 0;
+unlock_out:
+	spin_unlock(&zcache_direct_reclaim_lock);
+out:
+	return ret;
+}
+
+static void *zcache_get_free_page(void)
+{
+	struct zcache_preload *kp;
+	void *page;
+
+	kp = &__get_cpu_var(zcache_preloads);
+	page = kp->page;
+	BUG_ON(page == NULL);
+	kp->page = NULL;
+	return page;
+}
+
+static void zcache_free_page(void *p)
+{
+	free_page((unsigned long)p);
+}
+
+/*
+ * zcache implementation for tmem host ops
+ */
+
+static struct tmem_objnode *zcache_objnode_alloc(struct tmem_pool *pool)
+{
+	struct tmem_objnode *objnode = NULL;
+	unsigned long count;
+	struct zcache_preload *kp;
+
+	kp = &__get_cpu_var(zcache_preloads);
+	if (kp->nr <= 0)
+		goto out;
+	objnode = kp->objnodes[kp->nr - 1];
+	BUG_ON(objnode == NULL);
+	kp->objnodes[kp->nr - 1] = NULL;
+	kp->nr--;
+	count = atomic_inc_return(&zcache_curr_objnode_count);
+	if (count > zcache_curr_objnode_count_max)
+		zcache_curr_objnode_count_max = count;
+out:
+	return objnode;
+}
+
+static void zcache_objnode_free(struct tmem_objnode *objnode,
+					struct tmem_pool *pool)
+{
+	atomic_dec(&zcache_curr_objnode_count);
+	BUG_ON(atomic_read(&zcache_curr_objnode_count) < 0);
+	kmem_cache_free(zcache_objnode_cache, objnode);
+}
+
+static struct tmem_obj *zcache_obj_alloc(struct tmem_pool *pool)
+{
+	struct tmem_obj *obj = NULL;
+	unsigned long count;
+	struct zcache_preload *kp;
+
+	kp = &__get_cpu_var(zcache_preloads);
+	obj = kp->obj;
+	BUG_ON(obj == NULL);
+	kp->obj = NULL;
+	count = atomic_inc_return(&zcache_curr_obj_count);
+	if (count > zcache_curr_obj_count_max)
+		zcache_curr_obj_count_max = count;
+	return obj;
+}
+
+static void zcache_obj_free(struct tmem_obj *obj, struct tmem_pool *pool)
+{
+	atomic_dec(&zcache_curr_obj_count);
+	BUG_ON(atomic_read(&zcache_curr_obj_count) < 0);
+	kmem_cache_free(zcache_obj_cache, obj);
+}
+
+static struct tmem_hostops zcache_hostops = {
+	.obj_alloc = zcache_obj_alloc,
+	.obj_free = zcache_obj_free,
+	.objnode_alloc = zcache_objnode_alloc,
+	.objnode_free = zcache_objnode_free,
+};
+
+/*
+ * zcache implementations for PAM page descriptor ops
+ */
+
+static atomic_t zcache_curr_eph_pampd_count = ATOMIC_INIT(0);
+static unsigned long zcache_curr_eph_pampd_count_max;
+static atomic_t zcache_curr_pers_pampd_count = ATOMIC_INIT(0);
+static unsigned long zcache_curr_pers_pampd_count_max;
+
+/* forward reference */
+static int zcache_compress(struct page *from, void **out_va, size_t *out_len);
+
+static void *zcache_pampd_create(struct tmem_pool *pool, struct tmem_oid *oid,
+				 uint32_t index, struct page *page)
+{
+	void *pampd = NULL, *cdata;
+	size_t clen;
+	int ret;
+	bool ephemeral = is_ephemeral(pool);
+	unsigned long count;
+
+	if (ephemeral) {
+		ret = zcache_compress(page, &cdata, &clen);
+		if (ret == 0)
+
+			goto out;
+		if (clen == 0 || clen > zbud_max_buddy_size()) {
+			zcache_compress_poor++;
+			goto out;
+		}
+		pampd = (void *)zbud_create(pool->pool_id, oid, index,
+						page, cdata, clen);
+		if (pampd != NULL) {
+			count = atomic_inc_return(&zcache_curr_eph_pampd_count);
+			if (count > zcache_curr_eph_pampd_count_max)
+				zcache_curr_eph_pampd_count_max = count;
+		}
+	} else {
+		/*
+		 * FIXME: This is all the "policy" there is for now.
+		 * 3/4 totpages should allow ~37% of RAM to be filled with
+		 * compressed frontswap pages
+		 */
+		if (atomic_read(&zcache_curr_pers_pampd_count) >
+							3 * totalram_pages / 4)
+			goto out;
+		ret = zcache_compress(page, &cdata, &clen);
+		if (ret == 0)
+			goto out;
+		if (clen > zv_max_page_size) {
+			zcache_compress_poor++;
+			goto out;
+		}
+		pampd = (void *)zv_create(zcache_client.xvpool, pool->pool_id,
+						oid, index, cdata, clen);
+		if (pampd == NULL)
+			goto out;
+		count = atomic_inc_return(&zcache_curr_pers_pampd_count);
+		if (count > zcache_curr_pers_pampd_count_max)
+			zcache_curr_pers_pampd_count_max = count;
+	}
+out:
+	return pampd;
+}
+
+/*
+ * fill the pageframe corresponding to the struct page with the data
+ * from the passed pampd
+ */
+static int zcache_pampd_get_data(struct page *page, void *pampd,
+						struct tmem_pool *pool)
+{
+	int ret = 0;
+
+	if (is_ephemeral(pool))
+		ret = zbud_decompress(page, pampd);
+	else
+		zv_decompress(page, pampd);
+	return ret;
+}
+
+/*
+ * free the pampd and remove it from any zcache lists
+ * pampd must no longer be pointed to from any tmem data structures!
+ */
+static void zcache_pampd_free(void *pampd, struct tmem_pool *pool)
+{
+	if (is_ephemeral(pool)) {
+		zbud_free_and_delist((struct zbud_hdr *)pampd);
+		atomic_dec(&zcache_curr_eph_pampd_count);
+		BUG_ON(atomic_read(&zcache_curr_eph_pampd_count) < 0);
+	} else {
+		zv_free(zcache_client.xvpool, (struct zv_hdr *)pampd);
+		atomic_dec(&zcache_curr_pers_pampd_count);
+		BUG_ON(atomic_read(&zcache_curr_pers_pampd_count) < 0);
+	}
+}
+
+static struct tmem_pamops zcache_pamops = {
+	.create = zcache_pampd_create,
+	.get_data = zcache_pampd_get_data,
+	.free = zcache_pampd_free,
+};
+
+/*
+ * zcache compression/decompression and related per-cpu stuff
+ */
+
+#define LZO_WORKMEM_BYTES LZO1X_1_MEM_COMPRESS
+#define LZO_DSTMEM_PAGE_ORDER 1
+static DEFINE_PER_CPU(unsigned char *, zcache_workmem);
+static DEFINE_PER_CPU(unsigned char *, zcache_dstmem);
+
+static int zcache_compress(struct page *from, void **out_va, size_t *out_len)
+{
+	int ret = 0;
+	unsigned char *dmem = __get_cpu_var(zcache_dstmem);
+	unsigned char *wmem = __get_cpu_var(zcache_workmem);
+	char *from_va;
+
+	BUG_ON(!irqs_disabled());
+	if (unlikely(dmem == NULL || wmem == NULL))
+		goto out;  /* no buffer, so can't compress */
+	from_va = kmap_atomic(from, KM_USER0);
+	mb();
+	ret = lzo1x_1_compress(from_va, PAGE_SIZE, dmem, out_len, wmem);
+	BUG_ON(ret != LZO_E_OK);
+	*out_va = dmem;
+	kunmap_atomic(from_va, KM_USER0);
+	ret = 1;
+out:
+	return ret;
+}
+
+
+static int zcache_cpu_notifier(struct notifier_block *nb,
+				unsigned long action, void *pcpu)
+{
+	int cpu = (long)pcpu;
+	struct zcache_preload *kp;
+
+	switch (action) {
+	case CPU_UP_PREPARE:
+		per_cpu(zcache_dstmem, cpu) = (void *)__get_free_pages(
+			GFP_KERNEL | __GFP_REPEAT,
+			LZO_DSTMEM_PAGE_ORDER),
+		per_cpu(zcache_workmem, cpu) =
+			kzalloc(LZO1X_MEM_COMPRESS,
+				GFP_KERNEL | __GFP_REPEAT);
+		break;
+	case CPU_DEAD:
+	case CPU_UP_CANCELED:
+		free_pages((unsigned long)per_cpu(zcache_dstmem, cpu),
+				LZO_DSTMEM_PAGE_ORDER);
+		per_cpu(zcache_dstmem, cpu) = NULL;
+		kfree(per_cpu(zcache_workmem, cpu));
+		per_cpu(zcache_workmem, cpu) = NULL;
+		kp = &per_cpu(zcache_preloads, cpu);
+		while (kp->nr) {
+			kmem_cache_free(zcache_objnode_cache,
+					kp->objnodes[kp->nr - 1]);
+			kp->objnodes[kp->nr - 1] = NULL;
+			kp->nr--;
+		}
+		kmem_cache_free(zcache_obj_cache, kp->obj);
+		free_page((unsigned long)kp->page);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static struct notifier_block zcache_cpu_notifier_block = {
+	.notifier_call = zcache_cpu_notifier
+};
+
+#ifdef CONFIG_SYSFS
+#define ZCACHE_SYSFS_RO(_name) \
+	static ssize_t zcache_##_name##_show(struct kobject *kobj, \
+				struct kobj_attribute *attr, char *buf) \
+	{ \
+		return sprintf(buf, "%lu\n", zcache_##_name); \
+	} \
+	static struct kobj_attribute zcache_##_name##_attr = { \
+		.attr = { .name = __stringify(_name), .mode = 0444 }, \
+		.show = zcache_##_name##_show, \
+	}
+
+#define ZCACHE_SYSFS_RO_ATOMIC(_name) \
+	static ssize_t zcache_##_name##_show(struct kobject *kobj, \
+				struct kobj_attribute *attr, char *buf) \
+	{ \
+	    return sprintf(buf, "%d\n", atomic_read(&zcache_##_name)); \
+	} \
+	static struct kobj_attribute zcache_##_name##_attr = { \
+		.attr = { .name = __stringify(_name), .mode = 0444 }, \
+		.show = zcache_##_name##_show, \
+	}
+
+#define ZCACHE_SYSFS_RO_CUSTOM(_name, _func) \
+	static ssize_t zcache_##_name##_show(struct kobject *kobj, \
+				struct kobj_attribute *attr, char *buf) \
+	{ \
+	    return _func(buf); \
+	} \
+	static struct kobj_attribute zcache_##_name##_attr = { \
+		.attr = { .name = __stringify(_name), .mode = 0444 }, \
+		.show = zcache_##_name##_show, \
+	}
+
+ZCACHE_SYSFS_RO(curr_obj_count_max);
+ZCACHE_SYSFS_RO(curr_objnode_count_max);
+ZCACHE_SYSFS_RO(flush_total);
+ZCACHE_SYSFS_RO(flush_found);
+ZCACHE_SYSFS_RO(flobj_total);
+ZCACHE_SYSFS_RO(flobj_found);
+ZCACHE_SYSFS_RO(failed_eph_puts);
+ZCACHE_SYSFS_RO(failed_pers_puts);
+ZCACHE_SYSFS_RO(zbud_curr_zbytes);
+ZCACHE_SYSFS_RO(zbud_cumul_zpages);
+ZCACHE_SYSFS_RO(zbud_cumul_zbytes);
+ZCACHE_SYSFS_RO(zbud_buddied_count);
+ZCACHE_SYSFS_RO(zbpg_unused_list_count);
+ZCACHE_SYSFS_RO(evicted_raw_pages);
+ZCACHE_SYSFS_RO(evicted_unbuddied_pages);
+ZCACHE_SYSFS_RO(evicted_buddied_pages);
+ZCACHE_SYSFS_RO(failed_get_free_pages);
+ZCACHE_SYSFS_RO(failed_alloc);
+ZCACHE_SYSFS_RO(put_to_flush);
+ZCACHE_SYSFS_RO(aborted_preload);
+ZCACHE_SYSFS_RO(aborted_shrink);
+ZCACHE_SYSFS_RO(compress_poor);
+ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_raw_pages);
+ZCACHE_SYSFS_RO_ATOMIC(zbud_curr_zpages);
+ZCACHE_SYSFS_RO_ATOMIC(curr_obj_count);
+ZCACHE_SYSFS_RO_ATOMIC(curr_objnode_count);
+ZCACHE_SYSFS_RO_CUSTOM(zbud_unbuddied_list_counts,
+			zbud_show_unbuddied_list_counts);
+ZCACHE_SYSFS_RO_CUSTOM(zbud_cumul_chunk_counts,
+			zbud_show_cumul_chunk_counts);
+
+static struct attribute *zcache_attrs[] = {
+	&zcache_curr_obj_count_attr.attr,
+	&zcache_curr_obj_count_max_attr.attr,
+	&zcache_curr_objnode_count_attr.attr,
+	&zcache_curr_objnode_count_max_attr.attr,
+	&zcache_flush_total_attr.attr,
+	&zcache_flobj_total_attr.attr,
+	&zcache_flush_found_attr.attr,
+	&zcache_flobj_found_attr.attr,
+	&zcache_failed_eph_puts_attr.attr,
+	&zcache_failed_pers_puts_attr.attr,
+	&zcache_compress_poor_attr.attr,
+	&zcache_zbud_curr_raw_pages_attr.attr,
+	&zcache_zbud_curr_zpages_attr.attr,
+	&zcache_zbud_curr_zbytes_attr.attr,
+	&zcache_zbud_cumul_zpages_attr.attr,
+	&zcache_zbud_cumul_zbytes_attr.attr,
+	&zcache_zbud_buddied_count_attr.attr,
+	&zcache_zbpg_unused_list_count_attr.attr,
+	&zcache_evicted_raw_pages_attr.attr,
+	&zcache_evicted_unbuddied_pages_attr.attr,
+	&zcache_evicted_buddied_pages_attr.attr,
+	&zcache_failed_get_free_pages_attr.attr,
+	&zcache_failed_alloc_attr.attr,
+	&zcache_put_to_flush_attr.attr,
+	&zcache_aborted_preload_attr.attr,
+	&zcache_aborted_shrink_attr.attr,
+	&zcache_zbud_unbuddied_list_counts_attr.attr,
+	&zcache_zbud_cumul_chunk_counts_attr.attr,
+	NULL,
+};
+
+static struct attribute_group zcache_attr_group = {
+	.attrs = zcache_attrs,
+	.name = "zcache",
+};
+
+#endif /* CONFIG_SYSFS */
+/*
+ * When zcache is disabled ("frozen"), pools can be created and destroyed,
+ * but all puts (and thus all other operations that require memory allocation)
+ * must fail.  If zcache is unfrozen, accepts puts, then frozen again,
+ * data consistency requires all puts while frozen to be converted into
+ * flushes.
+ */
+static bool zcache_freeze;
+
+/*
+ * zcache shrinker interface (only useful for ephemeral pages, so zbud only)
+ */
+static int shrink_zcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask)
+{
+	int ret = -1;
+
+	if (nr >= 0) {
+		if (!(gfp_mask & __GFP_FS))
+			/* does this case really need to be skipped? */
+			goto out;
+		if (spin_trylock(&zcache_direct_reclaim_lock)) {
+			zbud_evict_pages(nr);
+			spin_unlock(&zcache_direct_reclaim_lock);
+		} else
+			zcache_aborted_shrink++;
+	}
+	ret = (int)atomic_read(&zcache_zbud_curr_raw_pages);
+out:
+	return ret;
+}
+
+static struct shrinker zcache_shrinker = {
+	.shrink = shrink_zcache_memory,
+	.seeks = DEFAULT_SEEKS,
+};
+
+/*
+ * zcache shims between cleancache/frontswap ops and tmem
+ */
+
+static int zcache_put_page(int pool_id, struct tmem_oid *oidp,
+				uint32_t index, struct page *page)
+{
+	struct tmem_pool *pool;
+	int ret = -1;
+
+	BUG_ON(!irqs_disabled());
+	pool = zcache_get_pool_by_id(pool_id);
+	if (unlikely(pool == NULL))
+		goto out;
+	if (!zcache_freeze && zcache_do_preload(pool) == 0) {
+		/* preload does preempt_disable on success */
+		ret = tmem_put(pool, oidp, index, page);
+		if (ret < 0) {
+			if (is_ephemeral(pool))
+				zcache_failed_eph_puts++;
+			else
+				zcache_failed_pers_puts++;
+		}
+		zcache_put_pool(pool);
+		preempt_enable_no_resched();
+	} else {
+		zcache_put_to_flush++;
+		if (atomic_read(&pool->obj_count) > 0)
+			/* the put fails whether the flush succeeds or not */
+			(void)tmem_flush_page(pool, oidp, index);
+		zcache_put_pool(pool);
+	}
+out:
+	return ret;
+}
+
+static int zcache_get_page(int pool_id, struct tmem_oid *oidp,
+				uint32_t index, struct page *page)
+{
+	struct tmem_pool *pool;
+	int ret = -1;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	pool = zcache_get_pool_by_id(pool_id);
+	if (likely(pool != NULL)) {
+		if (atomic_read(&pool->obj_count) > 0)
+			ret = tmem_get(pool, oidp, index, page);
+		zcache_put_pool(pool);
+	}
+	local_irq_restore(flags);
+	return ret;
+}
+
+static int zcache_flush_page(int pool_id, struct tmem_oid *oidp, uint32_t index)
+{
+	struct tmem_pool *pool;
+	int ret = -1;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	zcache_flush_total++;
+	pool = zcache_get_pool_by_id(pool_id);
+	if (likely(pool != NULL)) {
+		if (atomic_read(&pool->obj_count) > 0)
+			ret = tmem_flush_page(pool, oidp, index);
+		zcache_put_pool(pool);
+	}
+	if (ret >= 0)
+		zcache_flush_found++;
+	local_irq_restore(flags);
+	return ret;
+}
+
+static int zcache_flush_object(int pool_id, struct tmem_oid *oidp)
+{
+	struct tmem_pool *pool;
+	int ret = -1;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	zcache_flobj_total++;
+	pool = zcache_get_pool_by_id(pool_id);
+	if (likely(pool != NULL)) {
+		if (atomic_read(&pool->obj_count) > 0)
+			ret = tmem_flush_object(pool, oidp);
+		zcache_put_pool(pool);
+	}
+	if (ret >= 0)
+		zcache_flobj_found++;
+	local_irq_restore(flags);
+	return ret;
+}
+
+static int zcache_destroy_pool(int pool_id)
+{
+	struct tmem_pool *pool = NULL;
+	int ret = -1;
+
+	if (pool_id < 0)
+		goto out;
+	pool = zcache_client.tmem_pools[pool_id];
+	if (pool == NULL)
+		goto out;
+	zcache_client.tmem_pools[pool_id] = NULL;
+	/* wait for pool activity on other cpus to quiesce */
+	while (atomic_read(&pool->refcount) != 0)
+		;
+	local_bh_disable();
+	ret = tmem_destroy_pool(pool);
+	local_bh_enable();
+	kfree(pool);
+	pr_info("zcache: destroyed pool id=%d\n", pool_id);
+out:
+	return ret;
+}
+
+static int zcache_new_pool(uint32_t flags)
+{
+	int poolid = -1;
+	struct tmem_pool *pool;
+
+	pool = kmalloc(sizeof(struct tmem_pool), GFP_KERNEL);
+	if (pool == NULL) {
+		pr_info("zcache: pool creation failed: out of memory\n");
+		goto out;
+	}
+
+	for (poolid = 0; poolid < MAX_POOLS_PER_CLIENT; poolid++)
+		if (zcache_client.tmem_pools[poolid] == NULL)
+			break;
+	if (poolid >= MAX_POOLS_PER_CLIENT) {
+		pr_info("zcache: pool creation failed: max exceeded\n");
+		kfree(pool);
+		poolid = -1;
+		goto out;
+	}
+	atomic_set(&pool->refcount, 0);
+	pool->client = &zcache_client;
+	pool->pool_id = poolid;
+	tmem_new_pool(pool, flags);
+	zcache_client.tmem_pools[poolid] = pool;
+	pr_info("zcache: created %s tmem pool, id=%d\n",
+		flags & TMEM_POOL_PERSIST ? "persistent" : "ephemeral",
+		poolid);
+out:
+	return poolid;
+}
+
+/**********
+ * Two kernel functionalities currently can be layered on top of tmem.
+ * These are "cleancache" which is used as a second-chance cache for clean
+ * page cache pages; and "frontswap" which is used for swap pages
+ * to avoid writes to disk.  A generic "shim" is provided here for each
+ * to translate in-kernel semantics to zcache semantics.
+ */
+
+#ifdef CONFIG_CLEANCACHE
+static void zcache_cleancache_put_page(int pool_id,
+					struct cleancache_filekey key,
+					pgoff_t index, struct page *page)
+{
+	u32 ind = (u32) index;
+	struct tmem_oid oid = *(struct tmem_oid *)&key;
+
+	if (likely(ind == index))
+		(void)zcache_put_page(pool_id, &oid, index, page);
+}
+
+static int zcache_cleancache_get_page(int pool_id,
+					struct cleancache_filekey key,
+					pgoff_t index, struct page *page)
+{
+	u32 ind = (u32) index;
+	struct tmem_oid oid = *(struct tmem_oid *)&key;
+	int ret = -1;
+
+	if (likely(ind == index))
+		ret = zcache_get_page(pool_id, &oid, index, page);
+	return ret;
+}
+
+static void zcache_cleancache_flush_page(int pool_id,
+					struct cleancache_filekey key,
+					pgoff_t index)
+{
+	u32 ind = (u32) index;
+	struct tmem_oid oid = *(struct tmem_oid *)&key;
+
+	if (likely(ind == index))
+		(void)zcache_flush_page(pool_id, &oid, ind);
+}
+
+static void zcache_cleancache_flush_inode(int pool_id,
+					struct cleancache_filekey key)
+{
+	struct tmem_oid oid = *(struct tmem_oid *)&key;
+
+	(void)zcache_flush_object(pool_id, &oid);
+}
+
+static void zcache_cleancache_flush_fs(int pool_id)
+{
+	if (pool_id >= 0)
+		(void)zcache_destroy_pool(pool_id);
+}
+
+static int zcache_cleancache_init_fs(size_t pagesize)
+{
+	BUG_ON(sizeof(struct cleancache_filekey) !=
+				sizeof(struct tmem_oid));
+	BUG_ON(pagesize != PAGE_SIZE);
+	return zcache_new_pool(0);
+}
+
+static int zcache_cleancache_init_shared_fs(char *uuid, size_t pagesize)
+{
+	/* shared pools are unsupported and map to private */
+	BUG_ON(sizeof(struct cleancache_filekey) !=
+				sizeof(struct tmem_oid));
+	BUG_ON(pagesize != PAGE_SIZE);
+	return zcache_new_pool(0);
+}
+
+static struct cleancache_ops zcache_cleancache_ops = {
+	.put_page = zcache_cleancache_put_page,
+	.get_page = zcache_cleancache_get_page,
+	.flush_page = zcache_cleancache_flush_page,
+	.flush_inode = zcache_cleancache_flush_inode,
+	.flush_fs = zcache_cleancache_flush_fs,
+	.init_shared_fs = zcache_cleancache_init_shared_fs,
+	.init_fs = zcache_cleancache_init_fs
+};
+
+struct cleancache_ops zcache_cleancache_register_ops(void)
+{
+	struct cleancache_ops old_ops =
+		cleancache_register_ops(&zcache_cleancache_ops);
+
+	return old_ops;
+}
+#endif
+
+#ifdef CONFIG_FRONTSWAP
+/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
+static int zcache_frontswap_poolid = -1;
+
+/*
+ * Swizzling increases objects per swaptype, increasing tmem concurrency
+ * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS
+ */
+#define SWIZ_BITS		4
+#define SWIZ_MASK		((1 << SWIZ_BITS) - 1)
+#define _oswiz(_type, _ind)	((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
+#define iswiz(_ind)		(_ind >> SWIZ_BITS)
+
+static inline struct tmem_oid oswiz(unsigned type, u32 ind)
+{
+	struct tmem_oid oid = { .oid = { 0 } };
+	oid.oid[0] = _oswiz(type, ind);
+	return oid;
+}
+
+static int zcache_frontswap_put_page(unsigned type, pgoff_t offset,
+				   struct page *page)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	struct tmem_oid oid = oswiz(type, ind);
+	int ret = -1;
+	unsigned long flags;
+
+	BUG_ON(!PageLocked(page));
+	if (likely(ind64 == ind)) {
+		local_irq_save(flags);
+		ret = zcache_put_page(zcache_frontswap_poolid, &oid,
+					iswiz(ind), page);
+		local_irq_restore(flags);
+	}
+	return ret;
+}
+
+/* returns 0 if the page was successfully gotten from frontswap, -1 if
+ * was not present (should never happen!) */
+static int zcache_frontswap_get_page(unsigned type, pgoff_t offset,
+				   struct page *page)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	struct tmem_oid oid = oswiz(type, ind);
+	int ret = -1;
+
+	BUG_ON(!PageLocked(page));
+	if (likely(ind64 == ind))
+		ret = zcache_get_page(zcache_frontswap_poolid, &oid,
+					iswiz(ind), page);
+	return ret;
+}
+
+/* flush a single page from frontswap */
+static void zcache_frontswap_flush_page(unsigned type, pgoff_t offset)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	struct tmem_oid oid = oswiz(type, ind);
+
+	if (likely(ind64 == ind))
+		(void)zcache_flush_page(zcache_frontswap_poolid, &oid,
+					iswiz(ind));
+}
+
+/* flush all pages from the passed swaptype */
+static void zcache_frontswap_flush_area(unsigned type)
+{
+	struct tmem_oid oid;
+	int ind;
+
+	for (ind = SWIZ_MASK; ind >= 0; ind--) {
+		oid = oswiz(type, ind);
+		(void)zcache_flush_object(zcache_frontswap_poolid, &oid);
+	}
+}
+
+static void zcache_frontswap_init(unsigned ignored)
+{
+	/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
+	if (zcache_frontswap_poolid < 0)
+		zcache_frontswap_poolid = zcache_new_pool(TMEM_POOL_PERSIST);
+}
+
+static struct frontswap_ops zcache_frontswap_ops = {
+	.put_page = zcache_frontswap_put_page,
+	.get_page = zcache_frontswap_get_page,
+	.flush_page = zcache_frontswap_flush_page,
+	.flush_area = zcache_frontswap_flush_area,
+	.init = zcache_frontswap_init
+};
+
+struct frontswap_ops zcache_frontswap_register_ops(void)
+{
+	struct frontswap_ops old_ops =
+		frontswap_register_ops(&zcache_frontswap_ops);
+
+	return old_ops;
+}
+#endif
+
+/*
+ * zcache initialization
+ * NOTE FOR NOW zcache MUST BE PROVIDED AS A KERNEL BOOT PARAMETER OR
+ * NOTHING HAPPENS!
+ */
+
+static int zcache_enabled;
+
+static int __init enable_zcache(char *s)
+{
+	zcache_enabled = 1;
+	return 1;
+}
+__setup("zcache", enable_zcache);
+
+/* allow independent dynamic disabling of cleancache and frontswap */
+
+static int use_cleancache = 1;
+
+static int __init no_cleancache(char *s)
+{
+	use_cleancache = 0;
+	return 1;
+}
+
+__setup("nocleancache", no_cleancache);
+
+static int use_frontswap = 1;
+
+static int __init no_frontswap(char *s)
+{
+	use_frontswap = 0;
+	return 1;
+}
+
+__setup("nofrontswap", no_frontswap);
+
+static int __init zcache_init(void)
+{
+#ifdef CONFIG_SYSFS
+	int ret = 0;
+
+	ret = sysfs_create_group(mm_kobj, &zcache_attr_group);
+	if (ret) {
+		pr_err("zcache: can't create sysfs\n");
+		goto out;
+	}
+#endif /* CONFIG_SYSFS */
+#if defined(CONFIG_CLEANCACHE) || defined(CONFIG_FRONTSWAP)
+	if (zcache_enabled) {
+		unsigned int cpu;
+
+		tmem_register_hostops(&zcache_hostops);
+		tmem_register_pamops(&zcache_pamops);
+		ret = register_cpu_notifier(&zcache_cpu_notifier_block);
+		if (ret) {
+			pr_err("zcache: can't register cpu notifier\n");
+			goto out;
+		}
+		for_each_online_cpu(cpu) {
+			void *pcpu = (void *)(long)cpu;
+			zcache_cpu_notifier(&zcache_cpu_notifier_block,
+				CPU_UP_PREPARE, pcpu);
+		}
+	}
+	zcache_objnode_cache = kmem_cache_create("zcache_objnode",
+				sizeof(struct tmem_objnode), 0, 0, NULL);
+	zcache_obj_cache = kmem_cache_create("zcache_obj",
+				sizeof(struct tmem_obj), 0, 0, NULL);
+#endif
+#ifdef CONFIG_CLEANCACHE
+	if (zcache_enabled && use_cleancache) {
+		struct cleancache_ops old_ops;
+
+		zbud_init();
+		register_shrinker(&zcache_shrinker);
+		old_ops = zcache_cleancache_register_ops();
+		pr_info("zcache: cleancache enabled using kernel "
+			"transcendent memory and compression buddies\n");
+		if (old_ops.init_fs != NULL)
+			pr_warning("zcache: cleancache_ops overridden");
+	}
+#endif
+#ifdef CONFIG_FRONTSWAP
+	if (zcache_enabled && use_frontswap) {
+		struct frontswap_ops old_ops;
+
+		zcache_client.xvpool = xv_create_pool();
+		if (zcache_client.xvpool == NULL) {
+			pr_err("zcache: can't create xvpool\n");
+			goto out;
+		}
+		old_ops = zcache_frontswap_register_ops();
+		pr_info("zcache: frontswap enabled using kernel "
+			"transcendent memory and xvmalloc\n");
+		if (old_ops.init != NULL)
+			pr_warning("ktmem: frontswap_ops overridden");
+	}
+#endif
+out:
+	return ret;
+}
+
+module_init(zcache_init)
diff --git a/drivers/staging/zram/Kconfig b/drivers/staging/zram/Kconfig
index da079f8..3bec4db 100644
--- a/drivers/staging/zram/Kconfig
+++ b/drivers/staging/zram/Kconfig
@@ -1,6 +1,11 @@
+config XVMALLOC
+	bool
+	default n
+
 config ZRAM
 	tristate "Compressed RAM block device support"
-	depends on BLOCK
+	depends on BLOCK && SYSFS
+	select XVMALLOC
 	select LZO_COMPRESS
 	select LZO_DECOMPRESS
 	default n
@@ -15,3 +20,11 @@ config ZRAM
 
 	  See zram.txt for more information.
 	  Project home: http://compcache.googlecode.com/
+
+config ZRAM_DEBUG
+	bool "Compressed RAM block device debug support"
+	depends on ZRAM
+	default n
+	help
+	  This option adds additional debugging code to the compressed
+	  RAM block device driver.
diff --git a/drivers/staging/zram/Makefile b/drivers/staging/zram/Makefile
index b1709c5..2a6d321 100644
--- a/drivers/staging/zram/Makefile
+++ b/drivers/staging/zram/Makefile
@@ -1,3 +1,4 @@
-zram-y	:=	zram_drv.o zram_sysfs.o xvmalloc.o
+zram-y	:=	zram_drv.o zram_sysfs.o
 
 obj-$(CONFIG_ZRAM)	+=	zram.o
+obj-$(CONFIG_XVMALLOC)	+=	xvmalloc.o
\ No newline at end of file
diff --git a/drivers/staging/zram/xvmalloc.c b/drivers/staging/zram/xvmalloc.c
index b644067..1f9c508 100644
--- a/drivers/staging/zram/xvmalloc.c
+++ b/drivers/staging/zram/xvmalloc.c
@@ -10,6 +10,12 @@
  * Released under the terms of GNU General Public License Version 2.0
  */
 
+#ifdef CONFIG_ZRAM_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/highmem.h>
@@ -46,7 +52,7 @@ static void clear_flag(struct block_header *block, enum blockflags flag)
 }
 
 /*
- * Given <page, offset> pair, provide a derefrencable pointer.
+ * Given <page, offset> pair, provide a dereferencable pointer.
  * This is called from xv_malloc/xv_free path, so it
  * needs to be fast.
  */
@@ -200,6 +206,8 @@ static void insert_block(struct xv_pool *pool, struct page *page, u32 offset,
 		nextblock->link.prev_page = page;
 		nextblock->link.prev_offset = offset;
 		put_ptr_atomic(nextblock, KM_USER1);
+		/* If there was a next page then the free bits are set. */
+		return;
 	}
 
 	__set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]);
@@ -207,54 +215,14 @@ static void insert_block(struct xv_pool *pool, struct page *page, u32 offset,
 }
 
 /*
- * Remove block from head of freelist. Index 'slindex' identifies the freelist.
- */
-static void remove_block_head(struct xv_pool *pool,
-			struct block_header *block, u32 slindex)
-{
-	struct block_header *tmpblock;
-	u32 flindex = slindex / BITS_PER_LONG;
-
-	pool->freelist[slindex].page = block->link.next_page;
-	pool->freelist[slindex].offset = block->link.next_offset;
-	block->link.prev_page = NULL;
-	block->link.prev_offset = 0;
-
-	if (!pool->freelist[slindex].page) {
-		__clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]);
-		if (!pool->slbitmap[flindex])
-			__clear_bit(flindex, &pool->flbitmap);
-	} else {
-		/*
-		 * DEBUG ONLY: We need not reinitialize freelist head previous
-		 * pointer to 0 - we never depend on its value. But just for
-		 * sanity, lets do it.
-		 */
-		tmpblock = get_ptr_atomic(pool->freelist[slindex].page,
-				pool->freelist[slindex].offset, KM_USER1);
-		tmpblock->link.prev_page = NULL;
-		tmpblock->link.prev_offset = 0;
-		put_ptr_atomic(tmpblock, KM_USER1);
-	}
-}
-
-/*
  * Remove block from freelist. Index 'slindex' identifies the freelist.
  */
 static void remove_block(struct xv_pool *pool, struct page *page, u32 offset,
 			struct block_header *block, u32 slindex)
 {
-	u32 flindex;
+	u32 flindex = slindex / BITS_PER_LONG;
 	struct block_header *tmpblock;
 
-	if (pool->freelist[slindex].page == page
-	   && pool->freelist[slindex].offset == offset) {
-		remove_block_head(pool, block, slindex);
-		return;
-	}
-
-	flindex = slindex / BITS_PER_LONG;
-
 	if (block->link.prev_page) {
 		tmpblock = get_ptr_atomic(block->link.prev_page,
 				block->link.prev_offset, KM_USER1);
@@ -270,6 +238,35 @@ static void remove_block(struct xv_pool *pool, struct page *page, u32 offset,
 		tmpblock->link.prev_offset = block->link.prev_offset;
 		put_ptr_atomic(tmpblock, KM_USER1);
 	}
+
+	/* Is this block is at the head of the freelist? */
+	if (pool->freelist[slindex].page == page
+	   && pool->freelist[slindex].offset == offset) {
+
+		pool->freelist[slindex].page = block->link.next_page;
+		pool->freelist[slindex].offset = block->link.next_offset;
+
+		if (pool->freelist[slindex].page) {
+			struct block_header *tmpblock;
+			tmpblock = get_ptr_atomic(pool->freelist[slindex].page,
+					pool->freelist[slindex].offset,
+					KM_USER1);
+			tmpblock->link.prev_page = NULL;
+			tmpblock->link.prev_offset = 0;
+			put_ptr_atomic(tmpblock, KM_USER1);
+		} else {
+			/* This freelist bucket is empty */
+			__clear_bit(slindex % BITS_PER_LONG,
+				    &pool->slbitmap[flindex]);
+			if (!pool->slbitmap[flindex])
+				__clear_bit(flindex, &pool->flbitmap);
+		}
+	}
+
+	block->link.prev_page = NULL;
+	block->link.prev_offset = 0;
+	block->link.next_page = NULL;
+	block->link.next_offset = 0;
 }
 
 /*
@@ -320,11 +317,13 @@ struct xv_pool *xv_create_pool(void)
 
 	return pool;
 }
+EXPORT_SYMBOL_GPL(xv_create_pool);
 
 void xv_destroy_pool(struct xv_pool *pool)
 {
 	kfree(pool);
 }
+EXPORT_SYMBOL_GPL(xv_destroy_pool);
 
 /**
  * xv_malloc - Allocate block of given size from pool.
@@ -378,7 +377,7 @@ int xv_malloc(struct xv_pool *pool, u32 size, struct page **page,
 
 	block = get_ptr_atomic(*page, *offset, KM_USER0);
 
-	remove_block_head(pool, block, index);
+	remove_block(pool, *page, *offset, block, index);
 
 	/* Split the block if required */
 	tmpoffset = *offset + size + XV_ALIGN;
@@ -413,6 +412,7 @@ int xv_malloc(struct xv_pool *pool, u32 size, struct page **page,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(xv_malloc);
 
 /*
  * Free block identified with <page, offset>
@@ -489,6 +489,7 @@ void xv_free(struct xv_pool *pool, struct page *page, u32 offset)
 	put_ptr_atomic(page_start, KM_USER0);
 	spin_unlock(&pool->lock);
 }
+EXPORT_SYMBOL_GPL(xv_free);
 
 u32 xv_get_object_size(void *obj)
 {
@@ -497,6 +498,7 @@ u32 xv_get_object_size(void *obj)
 	blk = (struct block_header *)((char *)(obj) - XV_ALIGN);
 	return blk->size;
 }
+EXPORT_SYMBOL_GPL(xv_get_object_size);
 
 /*
  * Returns total memory used by allocator (userdata + metadata)
@@ -505,3 +507,4 @@ u64 xv_get_total_size_bytes(struct xv_pool *pool)
 {
 	return pool->total_pages << PAGE_SHIFT;
 }
+EXPORT_SYMBOL_GPL(xv_get_total_size_bytes);
diff --git a/drivers/staging/zram/xvmalloc_int.h b/drivers/staging/zram/xvmalloc_int.h
index e23ed5c..b5f1f7f 100644
--- a/drivers/staging/zram/xvmalloc_int.h
+++ b/drivers/staging/zram/xvmalloc_int.h
@@ -19,7 +19,11 @@
 /* User configurable params */
 
 /* Must be power of two */
+#ifdef CONFIG_64BIT
+#define XV_ALIGN_SHIFT 3
+#else
 #define XV_ALIGN_SHIFT	2
+#endif
 #define XV_ALIGN	(1 << XV_ALIGN_SHIFT)
 #define XV_ALIGN_MASK	(XV_ALIGN - 1)
 
@@ -27,8 +31,16 @@
 #define XV_MIN_ALLOC_SIZE	32
 #define XV_MAX_ALLOC_SIZE	(PAGE_SIZE - XV_ALIGN)
 
-/* Free lists are separated by FL_DELTA bytes */
-#define FL_DELTA_SHIFT	3
+/*
+ * Free lists are separated by FL_DELTA bytes
+ * This value is 3 for 4k pages and 4 for 64k pages, for any
+ * other page size, a conservative (PAGE_SHIFT - 9) is used.
+ */
+#if PAGE_SHIFT == 16
+#define FL_DELTA_SHIFT 4
+#else
+#define FL_DELTA_SHIFT (PAGE_SHIFT - 9)
+#endif
 #define FL_DELTA	(1 << FL_DELTA_SHIFT)
 #define FL_DELTA_MASK	(FL_DELTA - 1)
 #define NUM_FREE_LISTS	((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \
@@ -75,12 +87,9 @@ struct block_header {
 struct xv_pool {
 	ulong flbitmap;
 	ulong slbitmap[MAX_FLI];
-	spinlock_t lock;
-
+	u64 total_pages;	/* stats */
 	struct freelist_entry freelist[NUM_FREE_LISTS];
-
-	/* stats */
-	u64 total_pages;
+	spinlock_t lock;
 };
 
 #endif
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index 4bd8cbd..aab4ec4 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -15,6 +15,10 @@
 #define KMSG_COMPONENT "zram"
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
+#ifdef CONFIG_ZRAM_DEBUG
+#define DEBUG
+#endif
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/bio.h>
@@ -200,19 +204,13 @@ static void handle_uncompressed_page(struct zram *zram,
 	flush_dcache_page(page);
 }
 
-static int zram_read(struct zram *zram, struct bio *bio)
+static void zram_read(struct zram *zram, struct bio *bio)
 {
 
 	int i;
 	u32 index;
 	struct bio_vec *bvec;
 
-	if (unlikely(!zram->init_done)) {
-		set_bit(BIO_UPTODATE, &bio->bi_flags);
-		bio_endio(bio, 0);
-		return 0;
-	}
-
 	zram_stat64_inc(zram, &zram->stats.num_reads);
 	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
 
@@ -235,7 +233,7 @@ static int zram_read(struct zram *zram, struct bio *bio)
 		if (unlikely(!zram->table[index].page)) {
 			pr_debug("Read before write: sector=%lu, size=%u",
 				(ulong)(bio->bi_sector), bio->bi_size);
-			/* Do nothing */
+			handle_zero_page(page);
 			index++;
 			continue;
 		}
@@ -275,29 +273,23 @@ static int zram_read(struct zram *zram, struct bio *bio)
 
 	set_bit(BIO_UPTODATE, &bio->bi_flags);
 	bio_endio(bio, 0);
-	return 0;
+	return;
 
 out:
 	bio_io_error(bio);
-	return 0;
 }
 
-static int zram_write(struct zram *zram, struct bio *bio)
+static void zram_write(struct zram *zram, struct bio *bio)
 {
-	int i, ret;
+	int i;
 	u32 index;
 	struct bio_vec *bvec;
 
-	if (unlikely(!zram->init_done)) {
-		ret = zram_init_device(zram);
-		if (ret)
-			goto out;
-	}
-
 	zram_stat64_inc(zram, &zram->stats.num_writes);
 	index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
 
 	bio_for_each_segment(bvec, bio, i) {
+		int ret;
 		u32 offset;
 		size_t clen;
 		struct zobj_header *zheader;
@@ -407,11 +399,10 @@ memstore:
 
 	set_bit(BIO_UPTODATE, &bio->bi_flags);
 	bio_endio(bio, 0);
-	return 0;
+	return;
 
 out:
 	bio_io_error(bio);
-	return 0;
 }
 
 /*
@@ -436,7 +427,6 @@ static inline int valid_io_request(struct zram *zram, struct bio *bio)
  */
 static int zram_make_request(struct request_queue *queue, struct bio *bio)
 {
-	int ret = 0;
 	struct zram *zram = queue->queuedata;
 
 	if (!valid_io_request(zram, bio)) {
@@ -445,17 +435,22 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
 		return 0;
 	}
 
+	if (unlikely(!zram->init_done) && zram_init_device(zram)) {
+		bio_io_error(bio);
+		return 0;
+	}
+
 	switch (bio_data_dir(bio)) {
 	case READ:
-		ret = zram_read(zram, bio);
+		zram_read(zram, bio);
 		break;
 
 	case WRITE:
-		ret = zram_write(zram, bio);
+		zram_write(zram, bio);
 		break;
 	}
 
-	return ret;
+	return 0;
 }
 
 void zram_reset_device(struct zram *zram)
@@ -624,20 +619,19 @@ static int create_device(struct zram *zram, int device_id)
 	 * and n*PAGE_SIZED sized I/O requests.
 	 */
 	blk_queue_physical_block_size(zram->disk->queue, PAGE_SIZE);
-	blk_queue_logical_block_size(zram->disk->queue, PAGE_SIZE);
+	blk_queue_logical_block_size(zram->disk->queue,
+					ZRAM_LOGICAL_BLOCK_SIZE);
 	blk_queue_io_min(zram->disk->queue, PAGE_SIZE);
 	blk_queue_io_opt(zram->disk->queue, PAGE_SIZE);
 
 	add_disk(zram->disk);
 
-#ifdef CONFIG_SYSFS
 	ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj,
 				&zram_disk_attr_group);
 	if (ret < 0) {
 		pr_warning("Error creating sysfs group");
 		goto out;
 	}
-#endif
 
 	zram->init_done = 0;
 
@@ -647,10 +641,8 @@ out:
 
 static void destroy_device(struct zram *zram)
 {
-#ifdef CONFIG_SYSFS
 	sysfs_remove_group(&disk_to_dev(zram->disk)->kobj,
 			&zram_disk_attr_group);
-#endif
 
 	if (zram->disk) {
 		del_gendisk(zram->disk);
diff --git a/drivers/staging/zram/zram_drv.h b/drivers/staging/zram/zram_drv.h
index a481551..408b2c0 100644
--- a/drivers/staging/zram/zram_drv.h
+++ b/drivers/staging/zram/zram_drv.h
@@ -61,6 +61,7 @@ static const unsigned max_zpage_size = PAGE_SIZE / 4 * 3;
 #define SECTOR_SIZE		(1 << SECTOR_SHIFT)
 #define SECTORS_PER_PAGE_SHIFT	(PAGE_SHIFT - SECTOR_SHIFT)
 #define SECTORS_PER_PAGE	(1 << SECTORS_PER_PAGE_SHIFT)
+#define ZRAM_LOGICAL_BLOCK_SIZE	4096
 
 /* Flags for zram pages (table[page_no].flags) */
 enum zram_pageflags {
diff --git a/drivers/staging/zram/zram_sysfs.c b/drivers/staging/zram/zram_sysfs.c
index 6b3cf00..a70cc01 100644
--- a/drivers/staging/zram/zram_sysfs.c
+++ b/drivers/staging/zram/zram_sysfs.c
@@ -14,11 +14,10 @@
 
 #include <linux/device.h>
 #include <linux/genhd.h>
+#include <linux/mm.h>
 
 #include "zram_drv.h"
 
-#ifdef CONFIG_SYSFS
-
 static u64 zram_stat64_read(struct zram *zram, u64 *v)
 {
 	u64 val;
@@ -67,7 +66,7 @@ static ssize_t disksize_store(struct device *dev,
 	if (ret)
 		return ret;
 
-	zram->disksize &= PAGE_MASK;
+	zram->disksize = PAGE_ALIGN(zram->disksize);
 	set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT);
 
 	return len;
@@ -220,5 +219,3 @@ static struct attribute *zram_disk_attrs[] = {
 struct attribute_group zram_disk_attr_group = {
 	.attrs = zram_disk_attrs,
 };
-
-#endif	/* CONFIG_SYSFS */
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 366080b..7f19c8b 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -667,7 +667,13 @@ target_emulate_readcapacity(struct se_cmd *cmd)
 {
 	struct se_device *dev = SE_DEV(cmd);
 	unsigned char *buf = cmd->t_task->t_task_buf;
-	u32 blocks = dev->transport->get_blocks(dev);
+	unsigned long long blocks_long = dev->transport->get_blocks(dev);
+	u32 blocks;
+
+	if (blocks_long >= 0x00000000ffffffff)
+		blocks = 0xffffffff;
+	else
+		blocks = (u32)blocks_long;
 
 	buf[0] = (blocks >> 24) & 0xff;
 	buf[1] = (blocks >> 16) & 0xff;
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index 5da051a..350ed40 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -33,7 +33,6 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/kthread.h>
 #include <linux/in.h>
 #include <net/sock.h>
diff --git a/drivers/target/target_core_fabric_lib.c b/drivers/target/target_core_fabric_lib.c
index 2628564..a3c695a 100644
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -28,7 +28,6 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 0aaca88..190ca8a 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -33,7 +33,6 @@
 #include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c
index 4bbe820..6ec51cb 100644
--- a/drivers/target/target_core_hba.c
+++ b/drivers/target/target_core_hba.c
@@ -31,14 +31,12 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/in.h>
 #include <net/sock.h>
 #include <net/tcp.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_device.h>
-#include <target/target_core_device.h>
 #include <target/target_core_tpg.h>
 #include <target/target_core_transport.h>
 
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 67f0c09..3df570d 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -35,7 +35,6 @@
 #include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/bio.h>
 #include <linux/genhd.h>
 #include <linux/file.h>
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index f2a0847..5a9d2ba 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -34,7 +34,6 @@
 #include <linux/blk_types.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/genhd.h>
 #include <linux/cdrom.h>
 #include <linux/file.h>
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 979aebf..8dc6d74 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -34,7 +34,6 @@
 #include <linux/blkdev.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c
index c26f674..5ec745f 100644
--- a/drivers/target/target_core_tpg.c
+++ b/drivers/target/target_core_tpg.c
@@ -31,7 +31,6 @@
 #include <linux/timer.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/in.h>
 #include <net/sock.h>
 #include <net/tcp.h>
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4bbf6c1..ff9ace0 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -34,7 +34,6 @@
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/spinlock.h>
-#include <linux/smp_lock.h>
 #include <linux/kthread.h>
 #include <linux/in.h>
 #include <linux/cdrom.h>
diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig
new file mode 100644
index 0000000..3fd7199
--- /dev/null
+++ b/drivers/tty/Kconfig
@@ -0,0 +1,321 @@
+config VT
+	bool "Virtual terminal" if EXPERT
+	depends on !S390
+	select INPUT
+	default y
+	---help---
+	  If you say Y here, you will get support for terminal devices with
+	  display and keyboard devices. These are called "virtual" because you
+	  can run several virtual terminals (also called virtual consoles) on
+	  one physical terminal. This is rather useful, for example one
+	  virtual terminal can collect system messages and warnings, another
+	  one can be used for a text-mode user session, and a third could run
+	  an X session, all in parallel. Switching between virtual terminals
+	  is done with certain key combinations, usually Alt-<function key>.
+
+	  The setterm command ("man setterm") can be used to change the
+	  properties (such as colors or beeping) of a virtual terminal. The
+	  man page console_codes(4) ("man console_codes") contains the special
+	  character sequences that can be used to change those properties
+	  directly. The fonts used on virtual terminals can be changed with
+	  the setfont ("man setfont") command and the key bindings are defined
+	  with the loadkeys ("man loadkeys") command.
+
+	  You need at least one virtual terminal device in order to make use
+	  of your keyboard and monitor. Therefore, only people configuring an
+	  embedded system would want to say N here in order to save some
+	  memory; the only way to log into such a system is then via a serial
+	  or network connection.
+
+	  If unsure, say Y, or else you won't be able to do much with your new
+	  shiny Linux system :-)
+
+config CONSOLE_TRANSLATIONS
+	depends on VT
+	default y
+	bool "Enable character translations in console" if EXPERT
+	---help---
+	  This enables support for font mapping and Unicode translation
+	  on virtual consoles.
+
+config VT_CONSOLE
+	bool "Support for console on virtual terminal" if EXPERT
+	depends on VT
+	default y
+	---help---
+	  The system console is the device which receives all kernel messages
+	  and warnings and which allows logins in single user mode. If you
+	  answer Y here, a virtual terminal (the device used to interact with
+	  a physical terminal) can be used as system console. This is the most
+	  common mode of operations, so you should say Y here unless you want
+	  the kernel messages be output only to a serial port (in which case
+	  you should say Y to "Console on serial port", below).
+
+	  If you do say Y here, by default the currently visible virtual
+	  terminal (/dev/tty0) will be used as system console. You can change
+	  that with a kernel command line option such as "console=tty3" which
+	  would use the third virtual terminal as system console. (Try "man
+	  bootparam" or see the documentation of your boot loader (lilo or
+	  loadlin) about how to pass options to the kernel at boot time.)
+
+	  If unsure, say Y.
+
+config HW_CONSOLE
+	bool
+	depends on VT && !S390 && !UML
+	default y
+
+config VT_HW_CONSOLE_BINDING
+       bool "Support for binding and unbinding console drivers"
+       depends on HW_CONSOLE
+       default n
+       ---help---
+         The virtual terminal is the device that interacts with the physical
+         terminal through console drivers. On these systems, at least one
+         console driver is loaded. In other configurations, additional console
+         drivers may be enabled, such as the framebuffer console. If more than
+         1 console driver is enabled, setting this to 'y' will allow you to
+         select the console driver that will serve as the backend for the
+         virtual terminals.
+
+	 See <file:Documentation/console/console.txt> for more
+	 information. For framebuffer console users, please refer to
+	 <file:Documentation/fb/fbcon.txt>.
+
+config UNIX98_PTYS
+	bool "Unix98 PTY support" if EXPERT
+	default y
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx for
+	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
+	  has a number of problems. The GNU C library glibc 2.1 and later,
+	  however, supports the Unix98 naming standard: in order to acquire a
+	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
+	  terminal is then made available to the process and the pseudo
+	  terminal slave can be accessed as /dev/pts/<number>. What was
+	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
+
+	  All modern Linux systems use the Unix98 ptys.  Say Y unless
+	  you're on an embedded system and want to conserve memory.
+
+config DEVPTS_MULTIPLE_INSTANCES
+	bool "Support multiple instances of devpts"
+	depends on UNIX98_PTYS
+	default n
+	---help---
+	  Enable support for multiple instances of devpts filesystem.
+	  If you want to have isolated PTY namespaces (eg: in containers),
+	  say Y here.  Otherwise, say N. If enabled, each mount of devpts
+	  filesystem with the '-o newinstance' option will create an
+	  independent PTY namespace.
+
+config LEGACY_PTYS
+	bool "Legacy (BSD) PTY support"
+	default y
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx
+	  for masters and /dev/ttyxx for slaves of pseudo
+	  terminals. This scheme has a number of problems, including
+	  security.  This option enables these legacy devices; on most
+	  systems, it is safe to say N.
+
+
+config LEGACY_PTY_COUNT
+	int "Maximum number of legacy PTY in use"
+	depends on LEGACY_PTYS
+	range 0 256
+	default "256"
+	---help---
+	  The maximum number of legacy PTYs that can be used at any one time.
+	  The default is 256, and should be more than enough.  Embedded
+	  systems may want to reduce this to save memory.
+
+	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
+	  architectures and 24 bytes on 64-bit architectures.
+
+config BFIN_JTAG_COMM
+	tristate "Blackfin JTAG Communication"
+	depends on BLACKFIN
+	help
+	  Add support for emulating a TTY device over the Blackfin JTAG.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called bfin_jtag_comm.
+
+config BFIN_JTAG_COMM_CONSOLE
+	bool "Console on Blackfin JTAG"
+	depends on BFIN_JTAG_COMM=y
+
+config SERIAL_NONSTANDARD
+	bool "Non-standard serial port support"
+	depends on HAS_IOMEM
+	---help---
+	  Say Y here if you have any non-standard serial boards -- boards
+	  which aren't supported using the standard "dumb" serial driver.
+	  This includes intelligent serial boards such as Cyclades,
+	  Digiboards, etc. These are usually used for systems that need many
+	  serial ports because they serve many terminals or dial-in
+	  connections.
+
+	  Note that the answer to this question won't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about non-standard serial boards.
+
+	  Most people can say N here.
+
+config ROCKETPORT
+	tristate "Comtrol RocketPort support"
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
+	help
+	  This driver supports Comtrol RocketPort and RocketModem PCI boards.   
+          These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
+          modems.  For information about the RocketPort/RocketModem  boards
+          and this driver read <file:Documentation/serial/rocket.txt>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rocket.
+
+	  If you want to compile this driver into the kernel, say Y here.  If
+          you don't have a Comtrol RocketPort/RocketModem card installed, say N.
+
+config CYCLADES
+	tristate "Cyclades async mux support"
+	depends on SERIAL_NONSTANDARD && (PCI || ISA)
+	select FW_LOADER
+	---help---
+	  This driver supports Cyclades Z and Y multiserial boards.
+	  You would need something like this to connect more than two modems to
+	  your Linux box, for instance in order to become a dial-in server.
+
+	  For information about the Cyclades-Z card, read
+	  <file:Documentation/serial/README.cycladesZ>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cyclades.
+
+	  If you haven't heard about it, it's safe to say N.
+
+config CYZ_INTR
+	bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && CYCLADES
+	help
+	  The Cyclades-Z family of multiport cards allows 2 (two) driver op
+	  modes: polling and interrupt. In polling mode, the driver will check
+	  the status of the Cyclades-Z ports every certain amount of time
+	  (which is called polling cycle and is configurable). In interrupt
+	  mode, it will use an interrupt line (IRQ) in order to check the
+	  status of the Cyclades-Z ports. The default op mode is polling. If
+	  unsure, say N.
+
+config MOXA_INTELLIO
+	tristate "Moxa Intellio support"
+	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
+	select FW_LOADER
+	help
+	  Say Y here if you have a Moxa Intellio multiport serial card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called moxa.
+
+config MOXA_SMARTIO
+	tristate "Moxa SmartIO support v. 2.0"
+	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
+	help
+	  Say Y here if you have a Moxa SmartIO multiport serial card and/or
+	  want to help develop a new version of this driver.
+
+	  This is upgraded (1.9.1) driver from original Moxa drivers with
+	  changes finally resulting in PCI probing.
+
+	  This driver can also be built as a module. The module will be called
+	  mxser. If you want to do that, say M here.
+
+config SYNCLINK
+	tristate "Microgate SyncLink card support"
+	depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API
+	help
+	  Provides support for the SyncLink ISA and PCI multiprotocol serial
+	  adapters. These adapters support asynchronous and HDLC bit
+	  synchronous communication up to 10Mbps (PCI adapter).
+
+	  This driver can only be built as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called synclink.  If you want to do that, say M
+	  here.
+
+config SYNCLINKMP
+	tristate "SyncLink Multiport support"
+	depends on SERIAL_NONSTANDARD && PCI
+	help
+	  Enable support for the SyncLink Multiport (2 or 4 ports)
+	  serial adapter, running asynchronous and HDLC communications up
+	  to 2.048Mbps. Each ports is independently selectable for
+	  RS-232, V.35, RS-449, RS-530, and X.21
+
+	  This driver may be built as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called synclinkmp.  If you want to do that, say M
+	  here.
+
+config SYNCLINK_GT
+	tristate "SyncLink GT/AC support"
+	depends on SERIAL_NONSTANDARD && PCI
+	help
+	  Support for SyncLink GT and SyncLink AC families of
+	  synchronous and asynchronous serial adapters
+	  manufactured by Microgate Systems, Ltd. (www.microgate.com)
+
+config NOZOMI
+	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter"
+	depends on PCI && EXPERIMENTAL
+	help
+	  If you have a HSDPA driver Broadband Wireless Data Card -
+	  Globe Trotter PCMCIA card, say Y here.
+
+	  To compile this driver as a module, choose M here, the module
+	  will be called nozomi.
+
+config ISI
+	tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
+	depends on SERIAL_NONSTANDARD && PCI
+	select FW_LOADER
+	help
+	  This is a driver for the Multi-Tech cards which provide several
+	  serial ports.  The driver is experimental and can currently only be
+	  built as a module. The module will be called isicom.
+	  If you want to do that, choose M here.
+
+config N_HDLC
+	tristate "HDLC line discipline support"
+	depends on SERIAL_NONSTANDARD
+	help
+	  Allows synchronous HDLC communications with tty device drivers that
+	  support synchronous HDLC such as the Microgate SyncLink adapter.
+
+	  This driver can be built as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want).
+	  The module will be called n_hdlc. If you want to do that, say M
+	  here.
+
+config N_GSM
+	tristate "GSM MUX line discipline support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on NET
+	help
+	  This line discipline provides support for the GSM MUX protocol and
+	  presents the mux as a set of 61 individual tty devices.
+
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 3962772..690522f 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -11,3 +11,18 @@ obj-$(CONFIG_R3964)		+= n_r3964.o
 obj-y				+= vt/
 obj-$(CONFIG_HVC_DRIVER)	+= hvc/
 obj-y				+= serial/
+
+# tty drivers
+obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
+obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
+obj-$(CONFIG_CYCLADES)		+= cyclades.o
+obj-$(CONFIG_ISI)		+= isicom.o
+obj-$(CONFIG_MOXA_INTELLIO)	+= moxa.o
+obj-$(CONFIG_MOXA_SMARTIO)	+= mxser.o
+obj-$(CONFIG_NOZOMI)		+= nozomi.o
+obj-$(CONFIG_ROCKETPORT)	+= rocket.o
+obj-$(CONFIG_SYNCLINK_GT)	+= synclink_gt.o
+obj-$(CONFIG_SYNCLINKMP)	+= synclinkmp.o
+obj-$(CONFIG_SYNCLINK)		+= synclink.o
+
+obj-y += ipwireless/
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
new file mode 100644
index 0000000..f214e50
--- /dev/null
+++ b/drivers/tty/amiserial.c
@@ -0,0 +1,2178 @@
+/*
+ *  linux/drivers/char/amiserial.c
+ *
+ * Serial driver for the amiga builtin port.
+ *
+ * This code was created by taking serial.c version 4.30 from kernel
+ * release 2.3.22, replacing all hardware related stuff with the
+ * corresponding amiga hardware actions, and removing all irrelevant
+ * code. As a consequence, it uses many of the constants and names
+ * associated with the registers and bits of 16550 compatible UARTS -
+ * but only to keep track of status, etc in the state variables. It
+ * was done this was to make it easier to keep the code in line with
+ * (non hardware specific) changes to serial.c.
+ *
+ * The port is registered with the tty driver as minor device 64, and
+ * therefore other ports should should only use 65 upwards.
+ *
+ * Richard Lucock 28/12/99
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
+ * 		1998, 1999  Theodore Ts'o
+ *
+ */
+
+/*
+ * Serial driver configuration section.  Here are the various options:
+ *
+ * SERIAL_PARANOIA_CHECK
+ * 		Check the magic number for the async_structure where
+ * 		ever possible.
+ */
+
+#include <linux/delay.h>
+
+#undef SERIAL_PARANOIA_CHECK
+#define SERIAL_DO_RESTART
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+
+/* Sanity checks */
+
+#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
+#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
+ tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s)
+#else
+#define DBG_CNT(s)
+#endif
+
+/*
+ * End of serial driver configuration section.
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+static char *serial_version = "4.30";
+
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/console.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+
+#include <asm/setup.h>
+
+#include <asm/system.h>
+
+#include <asm/irq.h>
+
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+#define custom amiga_custom
+static char *serial_name = "Amiga-builtin serial driver";
+
+static struct tty_driver *serial_driver;
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+static struct async_struct *IRQ_ports;
+
+static unsigned char current_ctl_bits;
+
+static void change_speed(struct async_struct *info, struct ktermios *old);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+
+
+static struct serial_state rs_table[1];
+
+#define NR_PORTS ARRAY_SIZE(rs_table)
+
+#include <asm/uaccess.h>
+
+#define serial_isroot()	(capable(CAP_SYS_ADMIN))
+
+
+static inline int serial_paranoia_check(struct async_struct *info,
+					char *name, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null async_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/* some serial hardware definitions */
+#define SDR_OVRUN   (1<<15)
+#define SDR_RBF     (1<<14)
+#define SDR_TBE     (1<<13)
+#define SDR_TSRE    (1<<12)
+
+#define SERPER_PARENB    (1<<15)
+
+#define AC_SETCLR   (1<<15)
+#define AC_UARTBRK  (1<<11)
+
+#define SER_DTR     (1<<7)
+#define SER_RTS     (1<<6)
+#define SER_DCD     (1<<5)
+#define SER_CTS     (1<<4)
+#define SER_DSR     (1<<3)
+
+static __inline__ void rtsdtr_ctrl(int bits)
+{
+    ciab.pra = ((bits & (SER_RTS | SER_DTR)) ^ (SER_RTS | SER_DTR)) | (ciab.pra & ~(SER_RTS | SER_DTR));
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rs_stop(struct tty_struct *tty)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_stop"))
+		return;
+
+	local_irq_save(flags);
+	if (info->IER & UART_IER_THRI) {
+		info->IER &= ~UART_IER_THRI;
+		/* disable Tx interrupt and remove any pending interrupts */
+		custom.intena = IF_TBE;
+		mb();
+		custom.intreq = IF_TBE;
+		mb();
+	}
+	local_irq_restore(flags);
+}
+
+static void rs_start(struct tty_struct *tty)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_start"))
+		return;
+
+	local_irq_save(flags);
+	if (info->xmit.head != info->xmit.tail
+	    && info->xmit.buf
+	    && !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		custom.intena = IF_SETCLR | IF_TBE;
+		mb();
+		/* set a pending Tx Interrupt, transmitter should restart now */
+		custom.intreq = IF_SETCLR | IF_TBE;
+		mb();
+	}
+	local_irq_restore(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static void rs_sched_event(struct async_struct *info,
+			   int event)
+{
+	info->event |= 1 << event;
+	tasklet_schedule(&info->tlet);
+}
+
+static void receive_chars(struct async_struct *info)
+{
+        int status;
+	int serdatr;
+	struct tty_struct *tty = info->tty;
+	unsigned char ch, flag;
+	struct	async_icount *icount;
+	int oe = 0;
+
+	icount = &info->state->icount;
+
+	status = UART_LSR_DR; /* We obviously have a character! */
+	serdatr = custom.serdatr;
+	mb();
+	custom.intreq = IF_RBF;
+	mb();
+
+	if((serdatr & 0x1ff) == 0)
+	    status |= UART_LSR_BI;
+	if(serdatr & SDR_OVRUN)
+	    status |= UART_LSR_OE;
+
+	ch = serdatr & 0xff;
+	icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("DR%02x:%02x...", ch, status);
+#endif
+	flag = TTY_NORMAL;
+
+	/*
+	 * We don't handle parity or frame errors - but I have left
+	 * the code in, since I'm not sure that the errors can't be
+	 * detected.
+	 */
+
+	if (status & (UART_LSR_BI | UART_LSR_PE |
+		      UART_LSR_FE | UART_LSR_OE)) {
+	  /*
+	   * For statistics only
+	   */
+	  if (status & UART_LSR_BI) {
+	    status &= ~(UART_LSR_FE | UART_LSR_PE);
+	    icount->brk++;
+	  } else if (status & UART_LSR_PE)
+	    icount->parity++;
+	  else if (status & UART_LSR_FE)
+	    icount->frame++;
+	  if (status & UART_LSR_OE)
+	    icount->overrun++;
+
+	  /*
+	   * Now check to see if character should be
+	   * ignored, and mask off conditions which
+	   * should be ignored.
+	   */
+	  if (status & info->ignore_status_mask)
+	    goto out;
+
+	  status &= info->read_status_mask;
+
+	  if (status & (UART_LSR_BI)) {
+#ifdef SERIAL_DEBUG_INTR
+	    printk("handling break....");
+#endif
+	    flag = TTY_BREAK;
+	    if (info->flags & ASYNC_SAK)
+	      do_SAK(tty);
+	  } else if (status & UART_LSR_PE)
+	    flag = TTY_PARITY;
+	  else if (status & UART_LSR_FE)
+	    flag = TTY_FRAME;
+	  if (status & UART_LSR_OE) {
+	    /*
+	     * Overrun is special, since it's
+	     * reported immediately, and doesn't
+	     * affect the current character
+	     */
+	     oe = 1;
+	  }
+	}
+	tty_insert_flip_char(tty, ch, flag);
+	if (oe == 1)
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+	tty_flip_buffer_push(tty);
+out:
+	return;
+}
+
+static void transmit_chars(struct async_struct *info)
+{
+	custom.intreq = IF_TBE;
+	mb();
+	if (info->x_char) {
+	        custom.serdat = info->x_char | 0x100;
+		mb();
+		info->state->icount.tx++;
+		info->x_char = 0;
+		return;
+	}
+	if (info->xmit.head == info->xmit.tail
+	    || info->tty->stopped
+	    || info->tty->hw_stopped) {
+		info->IER &= ~UART_IER_THRI;
+	        custom.intena = IF_TBE;
+		mb();
+		return;
+	}
+
+	custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
+	mb();
+	info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
+	info->state->icount.tx++;
+
+	if (CIRC_CNT(info->xmit.head,
+		     info->xmit.tail,
+		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+	if (info->xmit.head == info->xmit.tail) {
+	        custom.intena = IF_TBE;
+		mb();
+		info->IER &= ~UART_IER_THRI;
+	}
+}
+
+static void check_modem_status(struct async_struct *info)
+{
+	unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
+	unsigned char dstatus;
+	struct	async_icount *icount;
+
+	/* Determine bits that have changed */
+	dstatus = status ^ current_ctl_bits;
+	current_ctl_bits = status;
+
+	if (dstatus) {
+		icount = &info->state->icount;
+		/* update input line counters */
+		if (dstatus & SER_DSR)
+			icount->dsr++;
+		if (dstatus & SER_DCD) {
+			icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+			if ((info->flags & ASYNC_HARDPPS_CD) &&
+			    !(status & SER_DCD))
+				hardpps();
+#endif
+		}
+		if (dstatus & SER_CTS)
+			icount->cts++;
+		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttyS%d CD now %s...", info->line,
+		       (!(status & SER_DCD)) ? "on" : "off");
+#endif
+		if (!(status & SER_DCD))
+			wake_up_interruptible(&info->open_wait);
+		else {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("doing serial hangup...");
+#endif
+			if (info->tty)
+				tty_hangup(info->tty);
+		}
+	}
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (!(status & SER_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				custom.intena = IF_SETCLR | IF_TBE;
+				mb();
+				/* set a pending Tx Interrupt, transmitter should restart now */
+				custom.intreq = IF_SETCLR | IF_TBE;
+				mb();
+				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if ((status & SER_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				/* disable Tx interrupt and remove any pending interrupts */
+				custom.intena = IF_TBE;
+				mb();
+				custom.intreq = IF_TBE;
+				mb();
+			}
+		}
+	}
+}
+
+static irqreturn_t ser_vbl_int( int irq, void *data)
+{
+        /* vbl is just a periodic interrupt we tie into to update modem status */
+	struct async_struct * info = IRQ_ports;
+	/*
+	 * TBD - is it better to unregister from this interrupt or to
+	 * ignore it if MSI is clear ?
+	 */
+	if(info->IER & UART_IER_MSI)
+	  check_modem_status(info);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ser_rx_int(int irq, void *dev_id)
+{
+	struct async_struct * info;
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("ser_rx_int...");
+#endif
+
+	info = IRQ_ports;
+	if (!info || !info->tty)
+		return IRQ_NONE;
+
+	receive_chars(info);
+	info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ser_tx_int(int irq, void *dev_id)
+{
+	struct async_struct * info;
+
+	if (custom.serdatr & SDR_TBE) {
+#ifdef SERIAL_DEBUG_INTR
+	  printk("ser_tx_int...");
+#endif
+
+	  info = IRQ_ports;
+	  if (!info || !info->tty)
+		return IRQ_NONE;
+
+	  transmit_chars(info);
+	  info->last_active = jiffies;
+#ifdef SERIAL_DEBUG_INTR
+	  printk("end.\n");
+#endif
+	}
+	return IRQ_HANDLED;
+}
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+
+static void do_softint(unsigned long private_)
+{
+	struct async_struct	*info = (struct async_struct *) private_;
+	struct tty_struct	*tty;
+
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
+		tty_wakeup(tty);
+}
+
+/*
+ * ---------------------------------------------------------------
+ * Low level utility subroutines for the serial driver:  routines to
+ * figure out the appropriate timeout for an interrupt chain, routines
+ * to initialize and startup a serial port, and routines to shutdown a
+ * serial port.  Useful stuff like that.
+ * ---------------------------------------------------------------
+ */
+
+static int startup(struct async_struct * info)
+{
+	unsigned long flags;
+	int	retval=0;
+	unsigned long page;
+
+	page = get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	local_irq_save(flags);
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		free_page(page);
+		goto errout;
+	}
+
+	if (info->xmit.buf)
+		free_page(page);
+	else
+		info->xmit.buf = (unsigned char *) page;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("starting up ttys%d ...", info->line);
+#endif
+
+	/* Clear anything in the input buffer */
+
+	custom.intreq = IF_RBF;
+	mb();
+
+	retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
+	if (retval) {
+	  if (serial_isroot()) {
+	    if (info->tty)
+	      set_bit(TTY_IO_ERROR,
+		      &info->tty->flags);
+	    retval = 0;
+	  }
+	  goto errout;
+	}
+
+	/* enable both Rx and Tx interrupts */
+	custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
+	mb();
+	info->IER = UART_IER_MSI;
+
+	/* remember current state of the DCD and CTS bits */
+	current_ctl_bits = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
+
+	IRQ_ports = info;
+
+	info->MCR = 0;
+	if (info->tty->termios->c_cflag & CBAUD)
+	  info->MCR = SER_DTR | SER_RTS;
+	rtsdtr_ctrl(info->MCR);
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	info->xmit.head = info->xmit.tail = 0;
+
+	/*
+	 * Set up the tty->alt_speed kludge
+	 */
+	if (info->tty) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			info->tty->alt_speed = 57600;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			info->tty->alt_speed = 115200;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			info->tty->alt_speed = 230400;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			info->tty->alt_speed = 460800;
+	}
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(info, NULL);
+
+	info->flags |= ASYNC_INITIALIZED;
+	local_irq_restore(flags);
+	return 0;
+
+errout:
+	local_irq_restore(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct async_struct * info)
+{
+	unsigned long	flags;
+	struct serial_state *state;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	state = info->state;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("Shutting down serial port %d ....\n", info->line);
+#endif
+
+	local_irq_save(flags); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->delta_msr_wait);
+
+	IRQ_ports = NULL;
+
+	/*
+	 * Free the IRQ, if necessary
+	 */
+	free_irq(IRQ_AMIGA_VERTB, info);
+
+	if (info->xmit.buf) {
+		free_page((unsigned long) info->xmit.buf);
+		info->xmit.buf = NULL;
+	}
+
+	info->IER = 0;
+	custom.intena = IF_RBF | IF_TBE;
+	mb();
+
+	/* disable break condition */
+	custom.adkcon = AC_UARTBRK;
+	mb();
+
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+		info->MCR &= ~(SER_DTR|SER_RTS);
+	rtsdtr_ctrl(info->MCR);
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ASYNC_INITIALIZED;
+	local_irq_restore(flags);
+}
+
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct async_struct *info,
+			 struct ktermios *old_termios)
+{
+	int	quot = 0, baud_base, baud;
+	unsigned cflag, cval = 0;
+	int	bits;
+	unsigned long	flags;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+
+	/* Byte size is always 8 bits plus parity bit if requested */
+
+	cval = 3; bits = 10;
+	if (cflag & CSTOPB) {
+		cval |= 0x04;
+		bits++;
+	}
+	if (cflag & PARENB) {
+		cval |= UART_LCR_PARITY;
+		bits++;
+	}
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+	if (cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+#endif
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(info->tty);
+	if (!baud)
+		baud = 9600;	/* B0 transition handled in rs_set_termios */
+	baud_base = info->state->baud_base;
+	if (baud == 38400 &&
+	    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+		quot = info->state->custom_divisor;
+	else {
+		if (baud == 134)
+			/* Special case since 134 is really 134.5 */
+			quot = (2*baud_base / 269);
+		else if (baud)
+			quot = baud_base / baud;
+	}
+	/* If the quotient is zero refuse the change */
+	if (!quot && old_termios) {
+		/* FIXME: Will need updating for new tty in the end */
+		info->tty->termios->c_cflag &= ~CBAUD;
+		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+		baud = tty_get_baud_rate(info->tty);
+		if (!baud)
+			baud = 9600;
+		if (baud == 38400 &&
+		    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+			quot = info->state->custom_divisor;
+		else {
+			if (baud == 134)
+				/* Special case since 134 is really 134.5 */
+				quot = (2*baud_base / 269);
+			else if (baud)
+				quot = baud_base / baud;
+		}
+	}
+	/* As a last resort, if the quotient is zero, default to 9600 bps */
+	if (!quot)
+		quot = baud_base / 9600;
+	info->quot = quot;
+	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	if (info->flags & ASYNC_HARDPPS_CD)
+		info->IER |= UART_IER_MSI;
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+	} else
+		info->flags &= ~ASYNC_CTS_FLOW;
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else {
+		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	/* TBD:
+	 * Does clearing IER_MSI imply that we should disable the VBL interrupt ?
+	 */
+
+	/*
+	 * Set up parity check flag
+	 */
+
+	info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(info->tty))
+		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty))
+			info->ignore_status_mask |= UART_LSR_OE;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		info->ignore_status_mask |= UART_LSR_DR;
+	local_irq_save(flags);
+
+	{
+	  short serper;
+
+	/* Set up the baud rate */
+	  serper = quot - 1;
+
+	/* Enable or disable parity bit */
+
+	if(cval & UART_LCR_PARITY)
+	  serper |= (SERPER_PARENB);
+
+	custom.serper = serper;
+	mb();
+	}
+
+	info->LCR = cval;				/* Save LCR */
+	local_irq_restore(flags);
+}
+
+static int rs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct async_struct *info;
+	unsigned long flags;
+
+	info = tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->name, "rs_put_char"))
+		return 0;
+
+	if (!info->xmit.buf)
+		return 0;
+
+	local_irq_save(flags);
+	if (CIRC_SPACE(info->xmit.head,
+		       info->xmit.tail,
+		       SERIAL_XMIT_SIZE) == 0) {
+		local_irq_restore(flags);
+		return 0;
+	}
+
+	info->xmit.buf[info->xmit.head++] = ch;
+	info->xmit.head &= SERIAL_XMIT_SIZE-1;
+	local_irq_restore(flags);
+	return 1;
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
+		return;
+
+	if (info->xmit.head == info->xmit.tail
+	    || tty->stopped
+	    || tty->hw_stopped
+	    || !info->xmit.buf)
+		return;
+
+	local_irq_save(flags);
+	info->IER |= UART_IER_THRI;
+	custom.intena = IF_SETCLR | IF_TBE;
+	mb();
+	/* set a pending Tx Interrupt, transmitter should restart now */
+	custom.intreq = IF_SETCLR | IF_TBE;
+	mb();
+	local_irq_restore(flags);
+}
+
+static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	struct async_struct *info;
+	unsigned long flags;
+
+	info = tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->name, "rs_write"))
+		return 0;
+
+	if (!info->xmit.buf)
+		return 0;
+
+	local_irq_save(flags);
+	while (1) {
+		c = CIRC_SPACE_TO_END(info->xmit.head,
+				      info->xmit.tail,
+				      SERIAL_XMIT_SIZE);
+		if (count < c)
+			c = count;
+		if (c <= 0) {
+			break;
+		}
+		memcpy(info->xmit.buf + info->xmit.head, buf, c);
+		info->xmit.head = ((info->xmit.head + c) &
+				   (SERIAL_XMIT_SIZE-1));
+		buf += c;
+		count -= c;
+		ret += c;
+	}
+	local_irq_restore(flags);
+
+	if (info->xmit.head != info->xmit.tail
+	    && !tty->stopped
+	    && !tty->hw_stopped
+	    && !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		local_irq_disable();
+		custom.intena = IF_SETCLR | IF_TBE;
+		mb();
+		/* set a pending Tx Interrupt, transmitter should restart now */
+		custom.intreq = IF_SETCLR | IF_TBE;
+		mb();
+		local_irq_restore(flags);
+	}
+	return ret;
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+	struct async_struct *info = tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->name, "rs_write_room"))
+		return 0;
+	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct async_struct *info = tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
+		return 0;
+	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+static void rs_flush_buffer(struct tty_struct *tty)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
+		return;
+	local_irq_save(flags);
+	info->xmit.head = info->xmit.tail = 0;
+	local_irq_restore(flags);
+	tty_wakeup(tty);
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void rs_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct async_struct *info = tty->driver_data;
+        unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_send_char"))
+		return;
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+
+	        /* Check this ! */
+	        local_irq_save(flags);
+		if(!(custom.intenar & IF_TBE)) {
+		    custom.intena = IF_SETCLR | IF_TBE;
+		    mb();
+		    /* set a pending Tx Interrupt, transmitter should restart now */
+		    custom.intreq = IF_SETCLR | IF_TBE;
+		    mb();
+		}
+		local_irq_restore(flags);
+
+		info->IER |= UART_IER_THRI;
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void rs_throttle(struct tty_struct * tty)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
+		return;
+
+	if (I_IXOFF(tty))
+		rs_send_xchar(tty, STOP_CHAR(tty));
+
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR &= ~SER_RTS;
+
+	local_irq_save(flags);
+	rtsdtr_ctrl(info->MCR);
+	local_irq_restore(flags);
+}
+
+static void rs_unthrottle(struct tty_struct * tty)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+
+	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			rs_send_xchar(tty, START_CHAR(tty));
+	}
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR |= SER_RTS;
+	local_irq_save(flags);
+	rtsdtr_ctrl(info->MCR);
+	local_irq_restore(flags);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int get_serial_info(struct async_struct * info,
+			   struct serial_struct __user * retinfo)
+{
+	struct serial_struct tmp;
+	struct serial_state *state = info->state;
+   
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tty_lock();
+	tmp.type = state->type;
+	tmp.line = state->line;
+	tmp.port = state->port;
+	tmp.irq = state->irq;
+	tmp.flags = state->flags;
+	tmp.xmit_fifo_size = state->xmit_fifo_size;
+	tmp.baud_base = state->baud_base;
+	tmp.close_delay = state->close_delay;
+	tmp.closing_wait = state->closing_wait;
+	tmp.custom_divisor = state->custom_divisor;
+	tty_unlock();
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_serial_info(struct async_struct * info,
+			   struct serial_struct __user * new_info)
+{
+	struct serial_struct new_serial;
+ 	struct serial_state old_state, *state;
+	unsigned int		change_irq,change_port;
+	int 			retval = 0;
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+
+	tty_lock();
+	state = info->state;
+	old_state = *state;
+  
+	change_irq = new_serial.irq != state->irq;
+	change_port = (new_serial.port != state->port);
+	if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
+	  tty_unlock();
+	  return -EINVAL;
+	}
+  
+	if (!serial_isroot()) {
+		if ((new_serial.baud_base != state->baud_base) ||
+		    (new_serial.close_delay != state->close_delay) ||
+		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (state->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		state->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	if (new_serial.baud_base < 9600) {
+		tty_unlock();
+		return -EINVAL;
+	}
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	state->baud_base = new_serial.baud_base;
+	state->flags = ((state->flags & ~ASYNC_FLAGS) |
+			(new_serial.flags & ASYNC_FLAGS));
+	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
+		       (info->flags & ASYNC_INTERNAL_FLAGS));
+	state->custom_divisor = new_serial.custom_divisor;
+	state->close_delay = new_serial.close_delay * HZ/100;
+	state->closing_wait = new_serial.closing_wait * HZ/100;
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+check_and_exit:
+	if (info->flags & ASYNC_INITIALIZED) {
+		if (((old_state.flags & ASYNC_SPD_MASK) !=
+		     (state->flags & ASYNC_SPD_MASK)) ||
+		    (old_state.custom_divisor != state->custom_divisor)) {
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+				info->tty->alt_speed = 57600;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+				info->tty->alt_speed = 115200;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+				info->tty->alt_speed = 230400;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+				info->tty->alt_speed = 460800;
+			change_speed(info, NULL);
+		}
+	} else
+		retval = startup(info);
+	tty_unlock();
+	return retval;
+}
+
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space. 
+ */
+static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
+{
+	unsigned char status;
+	unsigned int result;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	status = custom.serdatr;
+	mb();
+	local_irq_restore(flags);
+	result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+
+static int rs_tiocmget(struct tty_struct *tty)
+{
+	struct async_struct * info = tty->driver_data;
+	unsigned char control, status;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	control = info->MCR;
+	local_irq_save(flags);
+	status = ciab.pra;
+	local_irq_restore(flags);
+	return    ((control & SER_RTS) ? TIOCM_RTS : 0)
+		| ((control & SER_DTR) ? TIOCM_DTR : 0)
+		| (!(status  & SER_DCD) ? TIOCM_CAR : 0)
+		| (!(status  & SER_DSR) ? TIOCM_DSR : 0)
+		| (!(status  & SER_CTS) ? TIOCM_CTS : 0);
+}
+
+static int rs_tiocmset(struct tty_struct *tty, unsigned int set,
+						unsigned int clear)
+{
+	struct async_struct * info = tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+		return -ENODEV;
+	if (tty->flags & (1 << TTY_IO_ERROR))
+		return -EIO;
+
+	local_irq_save(flags);
+	if (set & TIOCM_RTS)
+		info->MCR |= SER_RTS;
+	if (set & TIOCM_DTR)
+		info->MCR |= SER_DTR;
+	if (clear & TIOCM_RTS)
+		info->MCR &= ~SER_RTS;
+	if (clear & TIOCM_DTR)
+		info->MCR &= ~SER_DTR;
+	rtsdtr_ctrl(info->MCR);
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*
+ * rs_break() --- routine which turns the break handling on or off
+ */
+static int rs_break(struct tty_struct *tty, int break_state)
+{
+	struct async_struct * info = tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_break"))
+		return -EINVAL;
+
+	local_irq_save(flags);
+	if (break_state == -1)
+	  custom.adkcon = AC_SETCLR | AC_UARTBRK;
+	else
+	  custom.adkcon = AC_UARTBRK;
+	mb();
+	local_irq_restore(flags);
+	return 0;
+}
+
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ *     RI where only 0->1 is counted.
+ */
+static int rs_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct async_struct *info = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	cnow = info->state->icount;
+	local_irq_restore(flags);
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
+static int rs_ioctl(struct tty_struct *tty,
+		    unsigned int cmd, unsigned long arg)
+{
+	struct async_struct * info = tty->driver_data;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	void __user *argp = (void __user *)arg;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+		case TIOCGSERIAL:
+			return get_serial_info(info, argp);
+		case TIOCSSERIAL:
+			return set_serial_info(info, argp);
+		case TIOCSERCONFIG:
+			return 0;
+
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, argp);
+
+		case TIOCSERGSTRUCT:
+			if (copy_to_user(argp,
+					 info, sizeof(struct async_struct)))
+				return -EFAULT;
+			return 0;
+
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		case TIOCMIWAIT:
+			local_irq_save(flags);
+			/* note the counters on entry */
+			cprev = info->state->icount;
+			local_irq_restore(flags);
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				local_irq_save(flags);
+				cnow = info->state->icount; /* atomic copy */
+				local_irq_restore(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;
+			}
+			/* NOTREACHED */
+
+		case TIOCSERGWILD:
+		case TIOCSERSWILD:
+			/* "setserial -W" is called in Debian boot */
+			printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+		}
+	return 0;
+}
+
+static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct async_struct *info = tty->driver_data;
+	unsigned long flags;
+	unsigned int cflag = tty->termios->c_cflag;
+
+	change_speed(info, old_termios);
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(cflag & CBAUD)) {
+		info->MCR &= ~(SER_DTR|SER_RTS);
+		local_irq_save(flags);
+		rtsdtr_ctrl(info->MCR);
+		local_irq_restore(flags);
+	}
+
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (cflag & CBAUD)) {
+		info->MCR |= SER_DTR;
+		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			info->MCR |= SER_RTS;
+		}
+		local_irq_save(flags);
+		rtsdtr_ctrl(info->MCR);
+		local_irq_restore(flags);
+	}
+
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rs_start(tty);
+	}
+
+#if 0
+	/*
+	 * No need to wake up processes in open wait, since they
+	 * sample the CLOCAL flag once, and don't recheck it.
+	 * XXX  It's not clear whether the current behavior is correct
+	 * or not.  Hence, this may change.....
+	 */
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ * 
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+	struct async_struct * info = tty->driver_data;
+	struct serial_state *state;
+	unsigned long flags;
+
+	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
+		return;
+
+	state = info->state;
+
+	local_irq_save(flags);
+
+	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		local_irq_restore(flags);
+		return;
+	}
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
+#endif
+	if ((tty->count == 1) && (state->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  state->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("rs_close: bad serial port count; tty->count is 1, "
+		       "state->count is %d\n", state->count);
+		state->count = 1;
+	}
+	if (--state->count < 0) {
+		printk("rs_close: bad serial port count for ttys%d: %d\n",
+		       info->line, state->count);
+		state->count = 0;
+	}
+	if (state->count) {
+		DBG_CNT("before DEC-2");
+		local_irq_restore(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->read_status_mask &= ~UART_LSR_DR;
+	if (info->flags & ASYNC_INITIALIZED) {
+	        /* disable receive interrupts */
+	        custom.intena = IF_RBF;
+		mb();
+		/* clear any pending receive interrupt */
+		custom.intreq = IF_RBF;
+		mb();
+
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		rs_wait_until_sent(tty, info->timeout);
+	}
+	shutdown(info);
+	rs_flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = NULL;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			msleep_interruptible(jiffies_to_msecs(info->close_delay));
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	local_irq_restore(flags);
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct async_struct * info = tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	int tty_was_locked = tty_locked();
+	int lsr;
+
+	if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
+		return;
+
+	if (info->xmit_fifo_size == 0)
+		return; /* Just in case.... */
+
+	orig_jiffies = jiffies;
+
+	/*
+	 * tty_wait_until_sent is called from lots of places,
+	 * with or without the BTM.
+	 */
+	if (!tty_was_locked)
+		tty_lock();
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 * 
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout)
+	  char_time = min_t(unsigned long, char_time, timeout);
+	/*
+	 * If the transmitter hasn't cleared in twice the approximate
+	 * amount of time to send the entire FIFO, it probably won't
+	 * ever clear.  This assumes the UART isn't doing flow
+	 * control, which is currently the case.  Hence, if it ever
+	 * takes longer than info->timeout, this is probably due to a
+	 * UART bug of some kind.  So, we clamp the timeout parameter at
+	 * 2*info->timeout.
+	 */
+	if (!timeout || timeout > 2*info->timeout)
+		timeout = 2*info->timeout;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+	printk("jiff=%lu...", jiffies);
+#endif
+	while(!((lsr = custom.serdatr) & SDR_TSRE)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		msleep_interruptible(jiffies_to_msecs(char_time));
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+	__set_current_state(TASK_RUNNING);
+	if (!tty_was_locked)
+		tty_unlock();
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rs_hangup(struct tty_struct *tty)
+{
+	struct async_struct * info = tty->driver_data;
+	struct serial_state *state = info->state;
+
+	if (serial_paranoia_check(info, tty->name, "rs_hangup"))
+		return;
+
+	state = info->state;
+
+	rs_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	state->count = 0;
+	info->flags &= ~ASYNC_NORMAL_ACTIVE;
+	info->tty = NULL;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   struct async_struct *info)
+{
+#ifdef DECLARE_WAITQUEUE
+	DECLARE_WAITQUEUE(wait, current);
+#else
+	struct wait_queue wait = { current, NULL };
+#endif
+	struct serial_state *state = info->state;
+	int		retval;
+	int		do_clocal = 0, extra_count = 0;
+	unsigned long	flags;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (tty->termios->c_cflag & CLOCAL)
+		do_clocal = 1;
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, state->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);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       state->line, state->count);
+#endif
+	local_irq_save(flags);
+	if (!tty_hung_up_p(filp)) {
+		extra_count = 1;
+		state->count--;
+	}
+	local_irq_restore(flags);
+	info->blocked_open++;
+	while (1) {
+		local_irq_save(flags);
+		if (tty->termios->c_cflag & CBAUD)
+		        rtsdtr_ctrl(SER_DTR|SER_RTS);
+		local_irq_restore(flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (!(ciab.pra & SER_DCD)) ))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, state->count);
+#endif
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&info->open_wait, &wait);
+	if (extra_count)
+		state->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, state->count);
+#endif
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+
+static int get_async_struct(int line, struct async_struct **ret_info)
+{
+	struct async_struct *info;
+	struct serial_state *sstate;
+
+	sstate = rs_table + line;
+	sstate->count++;
+	if (sstate->info) {
+		*ret_info = sstate->info;
+		return 0;
+	}
+	info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
+	if (!info) {
+		sstate->count--;
+		return -ENOMEM;
+	}
+#ifdef DECLARE_WAITQUEUE
+	init_waitqueue_head(&info->open_wait);
+	init_waitqueue_head(&info->close_wait);
+	init_waitqueue_head(&info->delta_msr_wait);
+#endif
+	info->magic = SERIAL_MAGIC;
+	info->port = sstate->port;
+	info->flags = sstate->flags;
+	info->xmit_fifo_size = sstate->xmit_fifo_size;
+	info->line = line;
+	tasklet_init(&info->tlet, do_softint, (unsigned long)info);
+	info->state = sstate;
+	if (sstate->info) {
+		kfree(info);
+		*ret_info = sstate->info;
+		return 0;
+	}
+	*ret_info = sstate->info = info;
+	return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+	struct async_struct	*info;
+	int 			retval, line;
+
+	line = tty->index;
+	if ((line < 0) || (line >= NR_PORTS)) {
+		return -ENODEV;
+	}
+	retval = get_async_struct(line, &info);
+	if (retval) {
+		return retval;
+	}
+	tty->driver_data = info;
+	info->tty = tty;
+	if (serial_paranoia_check(info, tty->name, "rs_open"))
+		return -ENODEV;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open %s, count = %d\n", tty->name, info->state->count);
+#endif
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval) {
+		return retval;
+	}
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("rs_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open %s successful...", tty->name);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline void line_info(struct seq_file *m, struct serial_state *state)
+{
+	struct async_struct *info = state->info, scr_info;
+	char	stat_buf[30], control, status;
+	unsigned long flags;
+
+	seq_printf(m, "%d: uart:amiga_builtin",state->line);
+
+	/*
+	 * Figure out the current RS-232 lines
+	 */
+	if (!info) {
+		info = &scr_info;	/* This is just for serial_{in,out} */
+
+		info->magic = SERIAL_MAGIC;
+		info->flags = state->flags;
+		info->quot = 0;
+		info->tty = NULL;
+	}
+	local_irq_save(flags);
+	status = ciab.pra;
+	control = info ? info->MCR : status;
+	local_irq_restore(flags);
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if(!(control & SER_RTS))
+		strcat(stat_buf, "|RTS");
+	if(!(status & SER_CTS))
+		strcat(stat_buf, "|CTS");
+	if(!(control & SER_DTR))
+		strcat(stat_buf, "|DTR");
+	if(!(status & SER_DSR))
+		strcat(stat_buf, "|DSR");
+	if(!(status & SER_DCD))
+		strcat(stat_buf, "|CD");
+
+	if (info->quot) {
+		seq_printf(m, " baud:%d", state->baud_base / info->quot);
+	}
+
+	seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx);
+
+	if (state->icount.frame)
+		seq_printf(m, " fe:%d", state->icount.frame);
+
+	if (state->icount.parity)
+		seq_printf(m, " pe:%d", state->icount.parity);
+
+	if (state->icount.brk)
+		seq_printf(m, " brk:%d", state->icount.brk);
+
+	if (state->icount.overrun)
+		seq_printf(m, " oe:%d", state->icount.overrun);
+
+	/*
+	 * Last thing is the RS-232 status lines
+	 */
+	seq_printf(m, " %s\n", stat_buf+1);
+}
+
+static int rs_proc_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
+	line_info(m, &rs_table[0]);
+	return 0;
+}
+
+static int rs_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, rs_proc_show, NULL);
+}
+
+static const struct file_operations rs_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= rs_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*
+ * ---------------------------------------------------------------------
+ * rs_init() and friends
+ *
+ * rs_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static void show_serial_version(void)
+{
+ 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
+}
+
+
+static const struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.flush_buffer = rs_flush_buffer,
+	.ioctl = rs_ioctl,
+	.throttle = rs_throttle,
+	.unthrottle = rs_unthrottle,
+	.set_termios = rs_set_termios,
+	.stop = rs_stop,
+	.start = rs_start,
+	.hangup = rs_hangup,
+	.break_ctl = rs_break,
+	.send_xchar = rs_send_xchar,
+	.wait_until_sent = rs_wait_until_sent,
+	.tiocmget = rs_tiocmget,
+	.tiocmset = rs_tiocmset,
+	.get_icount = rs_get_icount,
+	.proc_fops = &rs_proc_fops,
+};
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+static int __init amiga_serial_probe(struct platform_device *pdev)
+{
+	unsigned long flags;
+	struct serial_state * state;
+	int error;
+
+	serial_driver = alloc_tty_driver(1);
+	if (!serial_driver)
+		return -ENOMEM;
+
+	IRQ_ports = NULL;
+
+	show_serial_version();
+
+	/* Initialize the tty_driver structure */
+
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "amiserial";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &serial_ops);
+
+	error = tty_register_driver(serial_driver);
+	if (error)
+		goto fail_put_tty_driver;
+
+	state = rs_table;
+	state->magic = SSTATE_MAGIC;
+	state->port = (int)&custom.serdatr; /* Just to give it a value */
+	state->line = 0;
+	state->custom_divisor = 0;
+	state->close_delay = 5*HZ/10;
+	state->closing_wait = 30*HZ;
+	state->icount.cts = state->icount.dsr = 
+	  state->icount.rng = state->icount.dcd = 0;
+	state->icount.rx = state->icount.tx = 0;
+	state->icount.frame = state->icount.parity = 0;
+	state->icount.overrun = state->icount.brk = 0;
+
+	printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
+		       state->line);
+
+	/* Hardware set up */
+
+	state->baud_base = amiga_colorclock;
+	state->xmit_fifo_size = 1;
+
+	/* set ISRs, and then disable the rx interrupts */
+	error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
+	if (error)
+		goto fail_unregister;
+
+	error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED,
+			    "serial RX", state);
+	if (error)
+		goto fail_free_irq;
+
+	local_irq_save(flags);
+
+	/* turn off Rx and Tx interrupts */
+	custom.intena = IF_RBF | IF_TBE;
+	mb();
+
+	/* clear any pending interrupt */
+	custom.intreq = IF_RBF | IF_TBE;
+	mb();
+
+	local_irq_restore(flags);
+
+	/*
+	 * set the appropriate directions for the modem control flags,
+	 * and clear RTS and DTR
+	 */
+	ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
+	ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
+
+	platform_set_drvdata(pdev, state);
+
+	return 0;
+
+fail_free_irq:
+	free_irq(IRQ_AMIGA_TBE, state);
+fail_unregister:
+	tty_unregister_driver(serial_driver);
+fail_put_tty_driver:
+	put_tty_driver(serial_driver);
+	return error;
+}
+
+static int __exit amiga_serial_remove(struct platform_device *pdev)
+{
+	int error;
+	struct serial_state *state = platform_get_drvdata(pdev);
+	struct async_struct *info = state->info;
+
+	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
+	tasklet_kill(&info->tlet);
+	if ((error = tty_unregister_driver(serial_driver)))
+		printk("SERIAL: failed to unregister serial driver (%d)\n",
+		       error);
+	put_tty_driver(serial_driver);
+
+	rs_table[0].info = NULL;
+	kfree(info);
+
+	free_irq(IRQ_AMIGA_TBE, rs_table);
+	free_irq(IRQ_AMIGA_RBF, rs_table);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return error;
+}
+
+static struct platform_driver amiga_serial_driver = {
+	.remove = __exit_p(amiga_serial_remove),
+	.driver   = {
+		.name	= "amiga-serial",
+		.owner	= THIS_MODULE,
+	},
+};
+
+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);
+
+
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+
+static void amiga_serial_putc(char c)
+{
+	custom.serdat = (unsigned char)c | 0x100;
+	while (!(custom.serdatr & 0x2000))
+		barrier();
+}
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	The console must be locked when we get here.
+ */
+static void serial_console_write(struct console *co, const char *s,
+				unsigned count)
+{
+	unsigned short intena = custom.intenar;
+
+	custom.intena = IF_TBE;
+
+	while (count--) {
+		if (*s == '\n')
+			amiga_serial_putc('\r');
+		amiga_serial_putc(*s++);
+	}
+
+	custom.intena = IF_SETCLR | (intena & IF_TBE);
+}
+
+static struct tty_driver *serial_console_device(struct console *c, int *index)
+{
+	*index = 0;
+	return serial_driver;
+}
+
+static struct console sercons = {
+	.name =		"ttyS",
+	.write =	serial_console_write,
+	.device =	serial_console_device,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+/*
+ *	Register console.
+ */
+static int __init amiserial_console_init(void)
+{
+	register_console(&sercons);
+	return 0;
+}
+console_initcall(amiserial_console_init);
+
+#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:amiga-serial");
diff --git a/drivers/tty/bfin_jtag_comm.c b/drivers/tty/bfin_jtag_comm.c
new file mode 100644
index 0000000..1640244
--- /dev/null
+++ b/drivers/tty/bfin_jtag_comm.c
@@ -0,0 +1,366 @@
+/*
+ * TTY over Blackfin JTAG Communication
+ *
+ * Copyright 2008-2009 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#define DRV_NAME "bfin-jtag-comm"
+#define DEV_NAME "ttyBFJC"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+#include <linux/circ_buf.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <asm/atomic.h>
+
+#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); })
+
+/* See the Debug/Emulation chapter in the HRM */
+#define EMUDOF   0x00000001	/* EMUDAT_OUT full & valid */
+#define EMUDIF   0x00000002	/* EMUDAT_IN full & valid */
+#define EMUDOOVF 0x00000004	/* EMUDAT_OUT overflow */
+#define EMUDIOVF 0x00000008	/* EMUDAT_IN overflow */
+
+static inline uint32_t bfin_write_emudat(uint32_t emudat)
+{
+	__asm__ __volatile__("emudat = %0;" : : "d"(emudat));
+	return emudat;
+}
+
+static inline uint32_t bfin_read_emudat(void)
+{
+	uint32_t emudat;
+	__asm__ __volatile__("%0 = emudat;" : "=d"(emudat));
+	return emudat;
+}
+
+static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d)
+{
+	return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24));
+}
+
+#define CIRC_SIZE 2048	/* see comment in tty_io.c:do_tty_write() */
+#define CIRC_MASK (CIRC_SIZE - 1)
+#define circ_empty(circ)     ((circ)->head == (circ)->tail)
+#define circ_free(circ)      CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE)
+#define circ_cnt(circ)       CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE)
+#define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK])
+
+static struct tty_driver *bfin_jc_driver;
+static struct task_struct *bfin_jc_kthread;
+static struct tty_struct * volatile bfin_jc_tty;
+static unsigned long bfin_jc_count;
+static DEFINE_MUTEX(bfin_jc_tty_mutex);
+static volatile struct circ_buf bfin_jc_write_buf;
+
+static int
+bfin_jc_emudat_manager(void *arg)
+{
+	uint32_t inbound_len = 0, outbound_len = 0;
+
+	while (!kthread_should_stop()) {
+		/* no one left to give data to, so sleep */
+		if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) {
+			pr_debug("waiting for readers\n");
+			__set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule();
+			__set_current_state(TASK_RUNNING);
+		}
+
+		/* no data available, so just chill */
+		if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) {
+			pr_debug("waiting for data (in_len = %i) (circ: %i %i)\n",
+				inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head);
+			if (inbound_len)
+				schedule();
+			else
+				schedule_timeout_interruptible(HZ);
+			continue;
+		}
+
+		/* if incoming data is ready, eat it */
+		if (bfin_read_DBGSTAT() & EMUDIF) {
+			struct tty_struct *tty;
+			mutex_lock(&bfin_jc_tty_mutex);
+			tty = (struct tty_struct *)bfin_jc_tty;
+			if (tty != NULL) {
+				uint32_t emudat = bfin_read_emudat();
+				if (inbound_len == 0) {
+					pr_debug("incoming length: 0x%08x\n", emudat);
+					inbound_len = emudat;
+				} else {
+					size_t num_chars = (4 <= inbound_len ? 4 : inbound_len);
+					pr_debug("  incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars);
+					inbound_len -= num_chars;
+					tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars);
+					tty_flip_buffer_push(tty);
+				}
+			}
+			mutex_unlock(&bfin_jc_tty_mutex);
+		}
+
+		/* if outgoing data is ready, post it */
+		if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) {
+			if (outbound_len == 0) {
+				outbound_len = circ_cnt(&bfin_jc_write_buf);
+				bfin_write_emudat(outbound_len);
+				pr_debug("outgoing length: 0x%08x\n", outbound_len);
+			} else {
+				struct tty_struct *tty;
+				int tail = bfin_jc_write_buf.tail;
+				size_t ate = (4 <= outbound_len ? 4 : outbound_len);
+				uint32_t emudat =
+				bfin_write_emudat_chars(
+					circ_byte(&bfin_jc_write_buf, tail + 0),
+					circ_byte(&bfin_jc_write_buf, tail + 1),
+					circ_byte(&bfin_jc_write_buf, tail + 2),
+					circ_byte(&bfin_jc_write_buf, tail + 3)
+				);
+				bfin_jc_write_buf.tail += ate;
+				outbound_len -= ate;
+				mutex_lock(&bfin_jc_tty_mutex);
+				tty = (struct tty_struct *)bfin_jc_tty;
+				if (tty)
+					tty_wakeup(tty);
+				mutex_unlock(&bfin_jc_tty_mutex);
+				pr_debug("  outgoing data: 0x%08x (pushing %zu)\n", emudat, ate);
+			}
+		}
+	}
+
+	__set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+static int
+bfin_jc_open(struct tty_struct *tty, struct file *filp)
+{
+	mutex_lock(&bfin_jc_tty_mutex);
+	pr_debug("open %lu\n", bfin_jc_count);
+	++bfin_jc_count;
+	bfin_jc_tty = tty;
+	wake_up_process(bfin_jc_kthread);
+	mutex_unlock(&bfin_jc_tty_mutex);
+	return 0;
+}
+
+static void
+bfin_jc_close(struct tty_struct *tty, struct file *filp)
+{
+	mutex_lock(&bfin_jc_tty_mutex);
+	pr_debug("close %lu\n", bfin_jc_count);
+	if (--bfin_jc_count == 0)
+		bfin_jc_tty = NULL;
+	wake_up_process(bfin_jc_kthread);
+	mutex_unlock(&bfin_jc_tty_mutex);
+}
+
+/* XXX: we dont handle the put_char() case where we must handle count = 1 */
+static int
+bfin_jc_circ_write(const unsigned char *buf, int count)
+{
+	int i;
+	count = min(count, circ_free(&bfin_jc_write_buf));
+	pr_debug("going to write chunk of %i bytes\n", count);
+	for (i = 0; i < count; ++i)
+		circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i];
+	bfin_jc_write_buf.head += i;
+	return i;
+}
+
+#ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE
+# define console_lock()
+# define console_unlock()
+#endif
+static int
+bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	int i;
+	console_lock();
+	i = bfin_jc_circ_write(buf, count);
+	console_unlock();
+	wake_up_process(bfin_jc_kthread);
+	return i;
+}
+
+static void
+bfin_jc_flush_chars(struct tty_struct *tty)
+{
+	wake_up_process(bfin_jc_kthread);
+}
+
+static int
+bfin_jc_write_room(struct tty_struct *tty)
+{
+	return circ_free(&bfin_jc_write_buf);
+}
+
+static int
+bfin_jc_chars_in_buffer(struct tty_struct *tty)
+{
+	return circ_cnt(&bfin_jc_write_buf);
+}
+
+static void
+bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	unsigned long expire = jiffies + timeout;
+	while (!circ_empty(&bfin_jc_write_buf)) {
+		if (signal_pending(current))
+			break;
+		if (time_after(jiffies, expire))
+			break;
+	}
+}
+
+static const struct tty_operations bfin_jc_ops = {
+	.open            = bfin_jc_open,
+	.close           = bfin_jc_close,
+	.write           = bfin_jc_write,
+	/*.put_char        = bfin_jc_put_char,*/
+	.flush_chars     = bfin_jc_flush_chars,
+	.write_room      = bfin_jc_write_room,
+	.chars_in_buffer = bfin_jc_chars_in_buffer,
+	.wait_until_sent = bfin_jc_wait_until_sent,
+};
+
+static int __init bfin_jc_init(void)
+{
+	int ret;
+
+	bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME);
+	if (IS_ERR(bfin_jc_kthread))
+		return PTR_ERR(bfin_jc_kthread);
+
+	ret = -ENOMEM;
+
+	bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0;
+	bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL);
+	if (!bfin_jc_write_buf.buf)
+		goto err;
+
+	bfin_jc_driver = alloc_tty_driver(1);
+	if (!bfin_jc_driver)
+		goto err;
+
+	bfin_jc_driver->owner        = THIS_MODULE;
+	bfin_jc_driver->driver_name  = DRV_NAME;
+	bfin_jc_driver->name         = DEV_NAME;
+	bfin_jc_driver->type         = TTY_DRIVER_TYPE_SERIAL;
+	bfin_jc_driver->subtype      = SERIAL_TYPE_NORMAL;
+	bfin_jc_driver->init_termios = tty_std_termios;
+	tty_set_operations(bfin_jc_driver, &bfin_jc_ops);
+
+	ret = tty_register_driver(bfin_jc_driver);
+	if (ret)
+		goto err;
+
+	pr_init(KERN_INFO DRV_NAME ": initialized\n");
+
+	return 0;
+
+ err:
+	put_tty_driver(bfin_jc_driver);
+	kfree(bfin_jc_write_buf.buf);
+	kthread_stop(bfin_jc_kthread);
+	return ret;
+}
+module_init(bfin_jc_init);
+
+static void __exit bfin_jc_exit(void)
+{
+	kthread_stop(bfin_jc_kthread);
+	kfree(bfin_jc_write_buf.buf);
+	tty_unregister_driver(bfin_jc_driver);
+	put_tty_driver(bfin_jc_driver);
+}
+module_exit(bfin_jc_exit);
+
+#if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK)
+static void
+bfin_jc_straight_buffer_write(const char *buf, unsigned count)
+{
+	unsigned ate = 0;
+	while (bfin_read_DBGSTAT() & EMUDOF)
+		continue;
+	bfin_write_emudat(count);
+	while (ate < count) {
+		while (bfin_read_DBGSTAT() & EMUDOF)
+			continue;
+		bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]);
+		ate += 4;
+	}
+}
+#endif
+
+#ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE
+static void
+bfin_jc_console_write(struct console *co, const char *buf, unsigned count)
+{
+	if (bfin_jc_kthread == NULL)
+		bfin_jc_straight_buffer_write(buf, count);
+	else
+		bfin_jc_circ_write(buf, count);
+}
+
+static struct tty_driver *
+bfin_jc_console_device(struct console *co, int *index)
+{
+	*index = co->index;
+	return bfin_jc_driver;
+}
+
+static struct console bfin_jc_console = {
+	.name    = DEV_NAME,
+	.write   = bfin_jc_console_write,
+	.device  = bfin_jc_console_device,
+	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
+	.index   = -1,
+};
+
+static int __init bfin_jc_console_init(void)
+{
+	register_console(&bfin_jc_console);
+	return 0;
+}
+console_initcall(bfin_jc_console_init);
+#endif
+
+#ifdef CONFIG_EARLY_PRINTK
+static void __init
+bfin_jc_early_write(struct console *co, const char *buf, unsigned int count)
+{
+	bfin_jc_straight_buffer_write(buf, count);
+}
+
+static struct __initdata console bfin_jc_early_console = {
+	.name   = "early_BFJC",
+	.write   = bfin_jc_early_write,
+	.flags   = CON_ANYTIME | CON_PRINTBUFFER,
+	.index   = -1,
+};
+
+struct console * __init
+bfin_jc_early_init(unsigned int port, unsigned int cflag)
+{
+	return &bfin_jc_early_console;
+}
+#endif
+
+MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>");
+MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication");
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
new file mode 100644
index 0000000..c99728f
--- /dev/null
+++ b/drivers/tty/cyclades.c
@@ -0,0 +1,4200 @@
+#undef	BLOCKMOVE
+#define	Z_WAKE
+#undef	Z_EXT_CHARS_IN_BUFFER
+
+/*
+ *  linux/drivers/char/cyclades.c
+ *
+ * This file contains the driver for the Cyclades async multiport
+ * serial boards.
+ *
+ * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
+ * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
+ *
+ * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Much of the design and some of the code came from serial.c
+ * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
+ * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
+ * and then fixed as suggested by Michael K. Johnson 12/12/92.
+ * Converted to pci probing and cleaned up by Jiri Slaby.
+ *
+ */
+
+#define CY_VERSION	"2.6"
+
+/* If you need to install more boards than NR_CARDS, change the constant
+   in the definition below. No other change is necessary to support up to
+   eight boards. Beyond that you'll have to extend cy_isa_addresses. */
+
+#define NR_CARDS	4
+
+/*
+   If the total number of ports is larger than NR_PORTS, change this
+   constant in the definition below. No other change is necessary to
+   support more boards/ports. */
+
+#define NR_PORTS	256
+
+#define ZO_V1	0
+#define ZO_V2	1
+#define ZE_V1	2
+
+#define	SERIAL_PARANOIA_CHECK
+#undef	CY_DEBUG_OPEN
+#undef	CY_DEBUG_THROTTLE
+#undef	CY_DEBUG_OTHER
+#undef	CY_DEBUG_IO
+#undef	CY_DEBUG_COUNT
+#undef	CY_DEBUG_DTR
+#undef	CY_DEBUG_WAIT_UNTIL_SENT
+#undef	CY_DEBUG_INTERRUPTS
+#undef	CY_16Y_HACK
+#undef	CY_ENABLE_MONITORING
+#undef	CY_PCI_DEBUG
+
+/*
+ * Include section
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/cyclades.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/firmware.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+static void cy_send_xchar(struct tty_struct *tty, char ch);
+
+#ifndef SERIAL_XMIT_SIZE
+#define	SERIAL_XMIT_SIZE	(min(PAGE_SIZE, 4096))
+#endif
+
+#define STD_COM_FLAGS (0)
+
+/* firmware stuff */
+#define ZL_MAX_BLOCKS	16
+#define DRIVER_VERSION	0x02010203
+#define RAM_SIZE 0x80000
+
+enum zblock_type {
+	ZBLOCK_PRG = 0,
+	ZBLOCK_FPGA = 1
+};
+
+struct zfile_header {
+	char name[64];
+	char date[32];
+	char aux[32];
+	u32 n_config;
+	u32 config_offset;
+	u32 n_blocks;
+	u32 block_offset;
+	u32 reserved[9];
+} __attribute__ ((packed));
+
+struct zfile_config {
+	char name[64];
+	u32 mailbox;
+	u32 function;
+	u32 n_blocks;
+	u32 block_list[ZL_MAX_BLOCKS];
+} __attribute__ ((packed));
+
+struct zfile_block {
+	u32 type;
+	u32 file_offset;
+	u32 ram_offset;
+	u32 size;
+} __attribute__ ((packed));
+
+static struct tty_driver *cy_serial_driver;
+
+#ifdef CONFIG_ISA
+/* This is the address lookup table. The driver will probe for
+   Cyclom-Y/ISA boards at all addresses in here. If you want the
+   driver to probe addresses at a different address, add it to
+   this table.  If the driver is probing some other board and
+   causing problems, remove the offending address from this table.
+*/
+
+static unsigned int cy_isa_addresses[] = {
+	0xD0000,
+	0xD2000,
+	0xD4000,
+	0xD6000,
+	0xD8000,
+	0xDA000,
+	0xDC000,
+	0xDE000,
+	0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
+
+static long maddr[NR_CARDS];
+static int irq[NR_CARDS];
+
+module_param_array(maddr, long, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+
+#endif				/* CONFIG_ISA */
+
+/* This is the per-card data structure containing address, irq, number of
+   channels, etc. This driver supports a maximum of NR_CARDS cards.
+*/
+static struct cyclades_card cy_card[NR_CARDS];
+
+static int cy_next_channel;	/* next minor available */
+
+/*
+ * This is used to look up the divisor speeds and the timeouts
+ * We're normally limited to 15 distinct baud rates.  The extra
+ * are accessed via settings in info->port.flags.
+ *      0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+ *     10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
+ *                                               HI            VHI
+ *     20
+ */
+static const int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
+	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
+	230400, 0
+};
+
+static const char baud_co_25[] = {	/* 25 MHz clock option table */
+	/* value =>    00    01   02    03    04 */
+	/* divide by    8    32   128   512  2048 */
+	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
+	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const char baud_bpr_25[] = {	/* 25 MHz baud rate period table */
+	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
+	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
+};
+
+static const char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
+	/* value =>    00    01   02    03    04 */
+	/* divide by    8    32   128   512  2048 */
+	0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
+	0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00
+};
+
+static const char baud_bpr_60[] = {	/* 60 MHz baud rate period table (CD1400 J) */
+	0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
+	0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
+	0x21
+};
+
+static const char baud_cor3[] = {	/* receive threshold */
+	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
+	0x07
+};
+
+/*
+ * The Cyclades driver implements HW flow control as any serial driver.
+ * The cyclades_port structure member rflow and the vector rflow_thr
+ * allows us to take advantage of a special feature in the CD1400 to avoid
+ * data loss even when the system interrupt latency is too high. These flags
+ * are to be used only with very special applications. Setting these flags
+ * requires the use of a special cable (DTR and RTS reversed). In the new
+ * CD1400-based boards (rev. 6.00 or later), there is no need for special
+ * cables.
+ */
+
+static const char rflow_thr[] = {	/* rflow threshold */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
+	0x0a
+};
+
+/*  The Cyclom-Ye has placed the sequential chips in non-sequential
+ *  address order.  This look-up table overcomes that problem.
+ */
+static const unsigned int cy_chip_offset[] = { 0x0000,
+	0x0400,
+	0x0800,
+	0x0C00,
+	0x0200,
+	0x0600,
+	0x0A00,
+	0x0E00
+};
+
+/* PCI related definitions */
+
+#ifdef CONFIG_PCI
+static const struct pci_device_id cy_pci_dev_id[] = {
+	/* PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
+	/* PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
+	/* 4Y PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
+	/* 4Y PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
+	/* 8Y PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
+	/* 8Y PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
+	/* Z PCI < 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
+	/* Z PCI > 1Mb */
+	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
+	{ }			/* end of table */
+};
+MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
+#endif
+
+static void cy_start(struct tty_struct *);
+static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
+static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
+#ifdef CONFIG_ISA
+static unsigned detect_isa_irq(void __iomem *);
+#endif				/* CONFIG_ISA */
+
+#ifndef CONFIG_CYZ_INTR
+static void cyz_poll(unsigned long);
+
+/* The Cyclades-Z polling cycle is defined by this variable */
+static long cyz_polling_cycle = CZ_DEF_POLL;
+
+static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
+
+#else				/* CONFIG_CYZ_INTR */
+static void cyz_rx_restart(unsigned long);
+static struct timer_list cyz_rx_full_timer[NR_PORTS];
+#endif				/* CONFIG_CYZ_INTR */
+
+static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
+{
+	struct cyclades_card *card = port->card;
+
+	cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
+}
+
+static inline u8 cyy_readb(struct cyclades_port *port, u32 reg)
+{
+	struct cyclades_card *card = port->card;
+
+	return readb(port->u.cyy.base_addr + (reg << card->bus_index));
+}
+
+static inline bool cy_is_Z(struct cyclades_card *card)
+{
+	return card->num_chips == (unsigned int)-1;
+}
+
+static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr)
+{
+	return readl(&ctl_addr->init_ctrl) & (1 << 17);
+}
+
+static inline bool cyz_fpga_loaded(struct cyclades_card *card)
+{
+	return __cyz_fpga_loaded(card->ctl_addr.p9060);
+}
+
+static inline bool cyz_is_loaded(struct cyclades_card *card)
+{
+	struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS;
+
+	return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) &&
+			readl(&fw_id->signature) == ZFIRM_ID;
+}
+
+static inline int serial_paranoia_check(struct cyclades_port *info,
+		const char *name, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	if (!info) {
+		printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
+				"in %s\n", name, routine);
+		return 1;
+	}
+
+	if (info->magic != CYCLADES_MAGIC) {
+		printk(KERN_WARNING "cyc Warning: bad magic number for serial "
+				"struct (%s) in %s\n", name, routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+/***********************************************************/
+/********* Start of block of Cyclom-Y specific code ********/
+
+/* This routine waits up to 1000 micro-seconds for the previous
+   command to the Cirrus chip to complete and then issues the
+   new command.  An error is returned if the previous command
+   didn't finish within the time limit.
+
+   This function is only called from inside spinlock-protected code.
+ */
+static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index)
+{
+	void __iomem *ccr = base_addr + (CyCCR << index);
+	unsigned int i;
+
+	/* Check to see that the previous command has completed */
+	for (i = 0; i < 100; i++) {
+		if (readb(ccr) == 0)
+			break;
+		udelay(10L);
+	}
+	/* if the CCR never cleared, the previous command
+	   didn't finish within the "reasonable time" */
+	if (i == 100)
+		return -1;
+
+	/* Issue the new command */
+	cy_writeb(ccr, cmd);
+
+	return 0;
+}
+
+static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd)
+{
+	return __cyy_issue_cmd(port->u.cyy.base_addr, cmd,
+			port->card->bus_index);
+}
+
+#ifdef CONFIG_ISA
+/* ISA interrupt detection code */
+static unsigned detect_isa_irq(void __iomem *address)
+{
+	int irq;
+	unsigned long irqs, flags;
+	int save_xir, save_car;
+	int index = 0;		/* IRQ probing is only for ISA */
+
+	/* forget possible initially masked and pending IRQ */
+	irq = probe_irq_off(probe_irq_on());
+
+	/* Clear interrupts on the board first */
+	cy_writeb(address + (Cy_ClrIntr << index), 0);
+	/* Cy_ClrIntr is 0x1800 */
+
+	irqs = probe_irq_on();
+	/* Wait ... */
+	msleep(5);
+
+	/* Enable the Tx interrupts on the CD1400 */
+	local_irq_save(flags);
+	cy_writeb(address + (CyCAR << index), 0);
+	__cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
+
+	cy_writeb(address + (CyCAR << index), 0);
+	cy_writeb(address + (CySRER << index),
+		  readb(address + (CySRER << index)) | CyTxRdy);
+	local_irq_restore(flags);
+
+	/* Wait ... */
+	msleep(5);
+
+	/* Check which interrupt is in use */
+	irq = probe_irq_off(irqs);
+
+	/* Clean up */
+	save_xir = (u_char) readb(address + (CyTIR << index));
+	save_car = readb(address + (CyCAR << index));
+	cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
+	cy_writeb(address + (CySRER << index),
+		  readb(address + (CySRER << index)) & ~CyTxRdy);
+	cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
+	cy_writeb(address + (CyCAR << index), (save_car));
+	cy_writeb(address + (Cy_ClrIntr << index), 0);
+	/* Cy_ClrIntr is 0x1800 */
+
+	return (irq > 0) ? irq : 0;
+}
+#endif				/* CONFIG_ISA */
+
+static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
+		void __iomem *base_addr)
+{
+	struct cyclades_port *info;
+	struct tty_struct *tty;
+	int len, index = cinfo->bus_index;
+	u8 ivr, save_xir, channel, save_car, data, char_count;
+
+#ifdef CY_DEBUG_INTERRUPTS
+	printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
+#endif
+	/* determine the channel & change to that context */
+	save_xir = readb(base_addr + (CyRIR << index));
+	channel = save_xir & CyIRChannel;
+	info = &cinfo->ports[channel + chip * 4];
+	save_car = cyy_readb(info, CyCAR);
+	cyy_writeb(info, CyCAR, save_xir);
+	ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
+
+	tty = tty_port_tty_get(&info->port);
+	/* if there is nowhere to put the data, discard it */
+	if (tty == NULL) {
+		if (ivr == CyIVRRxEx) {	/* exception */
+			data = cyy_readb(info, CyRDSR);
+		} else {	/* normal character reception */
+			char_count = cyy_readb(info, CyRDCR);
+			while (char_count--)
+				data = cyy_readb(info, CyRDSR);
+		}
+		goto end;
+	}
+	/* there is an open port for this data */
+	if (ivr == CyIVRRxEx) {	/* exception */
+		data = cyy_readb(info, CyRDSR);
+
+		/* For statistics only */
+		if (data & CyBREAK)
+			info->icount.brk++;
+		else if (data & CyFRAME)
+			info->icount.frame++;
+		else if (data & CyPARITY)
+			info->icount.parity++;
+		else if (data & CyOVERRUN)
+			info->icount.overrun++;
+
+		if (data & info->ignore_status_mask) {
+			info->icount.rx++;
+			tty_kref_put(tty);
+			return;
+		}
+		if (tty_buffer_request_room(tty, 1)) {
+			if (data & info->read_status_mask) {
+				if (data & CyBREAK) {
+					tty_insert_flip_char(tty,
+						cyy_readb(info, CyRDSR),
+						TTY_BREAK);
+					info->icount.rx++;
+					if (info->port.flags & ASYNC_SAK)
+						do_SAK(tty);
+				} else if (data & CyFRAME) {
+					tty_insert_flip_char(tty,
+						cyy_readb(info, CyRDSR),
+						TTY_FRAME);
+					info->icount.rx++;
+					info->idle_stats.frame_errs++;
+				} else if (data & CyPARITY) {
+					/* Pieces of seven... */
+					tty_insert_flip_char(tty,
+						cyy_readb(info, CyRDSR),
+						TTY_PARITY);
+					info->icount.rx++;
+					info->idle_stats.parity_errs++;
+				} else if (data & CyOVERRUN) {
+					tty_insert_flip_char(tty, 0,
+							TTY_OVERRUN);
+					info->icount.rx++;
+					/* If the flip buffer itself is
+					   overflowing, we still lose
+					   the next incoming character.
+					 */
+					tty_insert_flip_char(tty,
+						cyy_readb(info, CyRDSR),
+						TTY_FRAME);
+					info->icount.rx++;
+					info->idle_stats.overruns++;
+				/* These two conditions may imply */
+				/* a normal read should be done. */
+				/* } else if(data & CyTIMEOUT) { */
+				/* } else if(data & CySPECHAR) { */
+				} else {
+					tty_insert_flip_char(tty, 0,
+							TTY_NORMAL);
+					info->icount.rx++;
+				}
+			} else {
+				tty_insert_flip_char(tty, 0, TTY_NORMAL);
+				info->icount.rx++;
+			}
+		} else {
+			/* there was a software buffer overrun and nothing
+			 * could be done about it!!! */
+			info->icount.buf_overrun++;
+			info->idle_stats.overruns++;
+		}
+	} else {	/* normal character reception */
+		/* load # chars available from the chip */
+		char_count = cyy_readb(info, CyRDCR);
+
+#ifdef CY_ENABLE_MONITORING
+		++info->mon.int_count;
+		info->mon.char_count += char_count;
+		if (char_count > info->mon.char_max)
+			info->mon.char_max = char_count;
+		info->mon.char_last = char_count;
+#endif
+		len = tty_buffer_request_room(tty, char_count);
+		while (len--) {
+			data = cyy_readb(info, CyRDSR);
+			tty_insert_flip_char(tty, data, TTY_NORMAL);
+			info->idle_stats.recv_bytes++;
+			info->icount.rx++;
+#ifdef CY_16Y_HACK
+			udelay(10L);
+#endif
+		}
+		info->idle_stats.recv_idle = jiffies;
+	}
+	tty_schedule_flip(tty);
+	tty_kref_put(tty);
+end:
+	/* end of service */
+	cyy_writeb(info, CyRIR, save_xir & 0x3f);
+	cyy_writeb(info, CyCAR, save_car);
+}
+
+static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
+		void __iomem *base_addr)
+{
+	struct cyclades_port *info;
+	struct tty_struct *tty;
+	int char_count, index = cinfo->bus_index;
+	u8 save_xir, channel, save_car, outch;
+
+	/* Since we only get here when the transmit buffer
+	   is empty, we know we can always stuff a dozen
+	   characters. */
+#ifdef CY_DEBUG_INTERRUPTS
+	printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
+#endif
+
+	/* determine the channel & change to that context */
+	save_xir = readb(base_addr + (CyTIR << index));
+	channel = save_xir & CyIRChannel;
+	save_car = readb(base_addr + (CyCAR << index));
+	cy_writeb(base_addr + (CyCAR << index), save_xir);
+
+	info = &cinfo->ports[channel + chip * 4];
+	tty = tty_port_tty_get(&info->port);
+	if (tty == NULL) {
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
+		goto end;
+	}
+
+	/* load the on-chip space for outbound data */
+	char_count = info->xmit_fifo_size;
+
+	if (info->x_char) {	/* send special char */
+		outch = info->x_char;
+		cyy_writeb(info, CyTDR, outch);
+		char_count--;
+		info->icount.tx++;
+		info->x_char = 0;
+	}
+
+	if (info->breakon || info->breakoff) {
+		if (info->breakon) {
+			cyy_writeb(info, CyTDR, 0);
+			cyy_writeb(info, CyTDR, 0x81);
+			info->breakon = 0;
+			char_count -= 2;
+		}
+		if (info->breakoff) {
+			cyy_writeb(info, CyTDR, 0);
+			cyy_writeb(info, CyTDR, 0x83);
+			info->breakoff = 0;
+			char_count -= 2;
+		}
+	}
+
+	while (char_count-- > 0) {
+		if (!info->xmit_cnt) {
+			if (cyy_readb(info, CySRER) & CyTxMpty) {
+				cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) & ~CyTxMpty);
+			} else {
+				cyy_writeb(info, CySRER, CyTxMpty |
+					(cyy_readb(info, CySRER) & ~CyTxRdy));
+			}
+			goto done;
+		}
+		if (info->port.xmit_buf == NULL) {
+			cyy_writeb(info, CySRER,
+				cyy_readb(info, CySRER) & ~CyTxRdy);
+			goto done;
+		}
+		if (tty->stopped || tty->hw_stopped) {
+			cyy_writeb(info, CySRER,
+				cyy_readb(info, CySRER) & ~CyTxRdy);
+			goto done;
+		}
+		/* Because the Embedded Transmit Commands have been enabled,
+		 * we must check to see if the escape character, NULL, is being
+		 * sent. If it is, we must ensure that there is room for it to
+		 * be doubled in the output stream.  Therefore we no longer
+		 * advance the pointer when the character is fetched, but
+		 * rather wait until after the check for a NULL output
+		 * character. This is necessary because there may not be room
+		 * for the two chars needed to send a NULL.)
+		 */
+		outch = info->port.xmit_buf[info->xmit_tail];
+		if (outch) {
+			info->xmit_cnt--;
+			info->xmit_tail = (info->xmit_tail + 1) &
+					(SERIAL_XMIT_SIZE - 1);
+			cyy_writeb(info, CyTDR, outch);
+			info->icount.tx++;
+		} else {
+			if (char_count > 1) {
+				info->xmit_cnt--;
+				info->xmit_tail = (info->xmit_tail + 1) &
+					(SERIAL_XMIT_SIZE - 1);
+				cyy_writeb(info, CyTDR, outch);
+				cyy_writeb(info, CyTDR, 0);
+				info->icount.tx++;
+				char_count--;
+			}
+		}
+	}
+
+done:
+	tty_wakeup(tty);
+	tty_kref_put(tty);
+end:
+	/* end of service */
+	cyy_writeb(info, CyTIR, save_xir & 0x3f);
+	cyy_writeb(info, CyCAR, save_car);
+}
+
+static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
+		void __iomem *base_addr)
+{
+	struct cyclades_port *info;
+	struct tty_struct *tty;
+	int index = cinfo->bus_index;
+	u8 save_xir, channel, save_car, mdm_change, mdm_status;
+
+	/* determine the channel & change to that context */
+	save_xir = readb(base_addr + (CyMIR << index));
+	channel = save_xir & CyIRChannel;
+	info = &cinfo->ports[channel + chip * 4];
+	save_car = cyy_readb(info, CyCAR);
+	cyy_writeb(info, CyCAR, save_xir);
+
+	mdm_change = cyy_readb(info, CyMISR);
+	mdm_status = cyy_readb(info, CyMSVR1);
+
+	tty = tty_port_tty_get(&info->port);
+	if (!tty)
+		goto end;
+
+	if (mdm_change & CyANY_DELTA) {
+		/* For statistics only */
+		if (mdm_change & CyDCD)
+			info->icount.dcd++;
+		if (mdm_change & CyCTS)
+			info->icount.cts++;
+		if (mdm_change & CyDSR)
+			info->icount.dsr++;
+		if (mdm_change & CyRI)
+			info->icount.rng++;
+
+		wake_up_interruptible(&info->port.delta_msr_wait);
+	}
+
+	if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
+		if (mdm_status & CyDCD)
+			wake_up_interruptible(&info->port.open_wait);
+		else
+			tty_hangup(tty);
+	}
+	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
+		if (tty->hw_stopped) {
+			if (mdm_status & CyCTS) {
+				/* cy_start isn't used
+				   because... !!! */
+				tty->hw_stopped = 0;
+				cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) | CyTxRdy);
+				tty_wakeup(tty);
+			}
+		} else {
+			if (!(mdm_status & CyCTS)) {
+				/* cy_stop isn't used
+				   because ... !!! */
+				tty->hw_stopped = 1;
+				cyy_writeb(info, CySRER,
+					cyy_readb(info, CySRER) & ~CyTxRdy);
+			}
+		}
+	}
+/*	if (mdm_change & CyDSR) {
+	}
+	if (mdm_change & CyRI) {
+	}*/
+	tty_kref_put(tty);
+end:
+	/* end of service */
+	cyy_writeb(info, CyMIR, save_xir & 0x3f);
+	cyy_writeb(info, CyCAR, save_car);
+}
+
+/* The real interrupt service routine is called
+   whenever the card wants its hand held--chars
+   received, out buffer empty, modem change, etc.
+ */
+static irqreturn_t cyy_interrupt(int irq, void *dev_id)
+{
+	int status;
+	struct cyclades_card *cinfo = dev_id;
+	void __iomem *base_addr, *card_base_addr;
+	unsigned int chip, too_many, had_work;
+	int index;
+
+	if (unlikely(cinfo == NULL)) {
+#ifdef CY_DEBUG_INTERRUPTS
+		printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
+				irq);
+#endif
+		return IRQ_NONE;	/* spurious interrupt */
+	}
+
+	card_base_addr = cinfo->base_addr;
+	index = cinfo->bus_index;
+
+	/* card was not initialized yet (e.g. DEBUG_SHIRQ) */
+	if (unlikely(card_base_addr == NULL))
+		return IRQ_HANDLED;
+
+	/* This loop checks all chips in the card.  Make a note whenever
+	   _any_ chip had some work to do, as this is considered an
+	   indication that there will be more to do.  Only when no chip
+	   has any work does this outermost loop exit.
+	 */
+	do {
+		had_work = 0;
+		for (chip = 0; chip < cinfo->num_chips; chip++) {
+			base_addr = cinfo->base_addr +
+					(cy_chip_offset[chip] << index);
+			too_many = 0;
+			while ((status = readb(base_addr +
+						(CySVRR << index))) != 0x00) {
+				had_work++;
+			/* The purpose of the following test is to ensure that
+			   no chip can monopolize the driver.  This forces the
+			   chips to be checked in a round-robin fashion (after
+			   draining each of a bunch (1000) of characters).
+			 */
+				if (1000 < too_many++)
+					break;
+				spin_lock(&cinfo->card_lock);
+				if (status & CySRReceive) /* rx intr */
+					cyy_chip_rx(cinfo, chip, base_addr);
+				if (status & CySRTransmit) /* tx intr */
+					cyy_chip_tx(cinfo, chip, base_addr);
+				if (status & CySRModem) /* modem intr */
+					cyy_chip_modem(cinfo, chip, base_addr);
+				spin_unlock(&cinfo->card_lock);
+			}
+		}
+	} while (had_work);
+
+	/* clear interrupts */
+	spin_lock(&cinfo->card_lock);
+	cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
+	/* Cy_ClrIntr is 0x1800 */
+	spin_unlock(&cinfo->card_lock);
+	return IRQ_HANDLED;
+}				/* cyy_interrupt */
+
+static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
+		unsigned int clear)
+{
+	struct cyclades_card *card = info->card;
+	int channel = info->line - card->first_line;
+	u32 rts, dtr, msvrr, msvrd;
+
+	channel &= 0x03;
+
+	if (info->rtsdtr_inv) {
+		msvrr = CyMSVR2;
+		msvrd = CyMSVR1;
+		rts = CyDTR;
+		dtr = CyRTS;
+	} else {
+		msvrr = CyMSVR1;
+		msvrd = CyMSVR2;
+		rts = CyRTS;
+		dtr = CyDTR;
+	}
+	if (set & TIOCM_RTS) {
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrr, rts);
+	}
+	if (clear & TIOCM_RTS) {
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrr, ~rts);
+	}
+	if (set & TIOCM_DTR) {
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrd, dtr);
+#ifdef CY_DEBUG_DTR
+		printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
+		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+			cyy_readb(info, CyMSVR1),
+			cyy_readb(info, CyMSVR2));
+#endif
+	}
+	if (clear & TIOCM_DTR) {
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, msvrd, ~dtr);
+#ifdef CY_DEBUG_DTR
+		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
+		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
+			cyy_readb(info, CyMSVR1),
+			cyy_readb(info, CyMSVR2));
+#endif
+	}
+}
+
+/***********************************************************/
+/********* End of block of Cyclom-Y specific code **********/
+/******** Start of block of Cyclades-Z specific code *******/
+/***********************************************************/
+
+static int
+cyz_fetch_msg(struct cyclades_card *cinfo,
+		__u32 *channel, __u8 *cmd, __u32 *param)
+{
+	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
+	unsigned long loc_doorbell;
+
+	loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell);
+	if (loc_doorbell) {
+		*cmd = (char)(0xff & loc_doorbell);
+		*channel = readl(&board_ctrl->fwcmd_channel);
+		*param = (__u32) readl(&board_ctrl->fwcmd_param);
+		cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
+		return 1;
+	}
+	return 0;
+}				/* cyz_fetch_msg */
+
+static int
+cyz_issue_cmd(struct cyclades_card *cinfo,
+		__u32 channel, __u8 cmd, __u32 param)
+{
+	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
+	__u32 __iomem *pci_doorbell;
+	unsigned int index;
+
+	if (!cyz_is_loaded(cinfo))
+		return -1;
+
+	index = 0;
+	pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
+	while ((readl(pci_doorbell) & 0xff) != 0) {
+		if (index++ == 1000)
+			return (int)(readl(pci_doorbell) & 0xff);
+		udelay(50L);
+	}
+	cy_writel(&board_ctrl->hcmd_channel, channel);
+	cy_writel(&board_ctrl->hcmd_param, param);
+	cy_writel(pci_doorbell, (long)cmd);
+
+	return 0;
+}				/* cyz_issue_cmd */
+
+static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
+{
+	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
+	struct cyclades_card *cinfo = info->card;
+	unsigned int char_count;
+	int len;
+#ifdef BLOCKMOVE
+	unsigned char *buf;
+#else
+	char data;
+#endif
+	__u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
+
+	rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
+	rx_put = readl(&buf_ctrl->rx_put);
+	rx_bufsize = readl(&buf_ctrl->rx_bufsize);
+	rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
+	if (rx_put >= rx_get)
+		char_count = rx_put - rx_get;
+	else
+		char_count = rx_put - rx_get + rx_bufsize;
+
+	if (char_count) {
+#ifdef CY_ENABLE_MONITORING
+		info->mon.int_count++;
+		info->mon.char_count += char_count;
+		if (char_count > info->mon.char_max)
+			info->mon.char_max = char_count;
+		info->mon.char_last = char_count;
+#endif
+		if (tty == NULL) {
+			/* flush received characters */
+			new_rx_get = (new_rx_get + char_count) &
+					(rx_bufsize - 1);
+			info->rflush_count++;
+		} else {
+#ifdef BLOCKMOVE
+		/* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+		   for performance, but because of buffer boundaries, there
+		   may be several steps to the operation */
+			while (1) {
+				len = tty_prepare_flip_string(tty, &buf,
+						char_count);
+				if (!len)
+					break;
+
+				len = min_t(unsigned int, min(len, char_count),
+						rx_bufsize - new_rx_get);
+
+				memcpy_fromio(buf, cinfo->base_addr +
+						rx_bufaddr + new_rx_get, len);
+
+				new_rx_get = (new_rx_get + len) &
+						(rx_bufsize - 1);
+				char_count -= len;
+				info->icount.rx += len;
+				info->idle_stats.recv_bytes += len;
+			}
+#else
+			len = tty_buffer_request_room(tty, char_count);
+			while (len--) {
+				data = readb(cinfo->base_addr + rx_bufaddr +
+						new_rx_get);
+				new_rx_get = (new_rx_get + 1) &
+							(rx_bufsize - 1);
+				tty_insert_flip_char(tty, data, TTY_NORMAL);
+				info->idle_stats.recv_bytes++;
+				info->icount.rx++;
+			}
+#endif
+#ifdef CONFIG_CYZ_INTR
+		/* Recalculate the number of chars in the RX buffer and issue
+		   a cmd in case it's higher than the RX high water mark */
+			rx_put = readl(&buf_ctrl->rx_put);
+			if (rx_put >= rx_get)
+				char_count = rx_put - rx_get;
+			else
+				char_count = rx_put - rx_get + rx_bufsize;
+			if (char_count >= readl(&buf_ctrl->rx_threshold) &&
+					!timer_pending(&cyz_rx_full_timer[
+							info->line]))
+				mod_timer(&cyz_rx_full_timer[info->line],
+						jiffies + 1);
+#endif
+			info->idle_stats.recv_idle = jiffies;
+			tty_schedule_flip(tty);
+		}
+		/* Update rx_get */
+		cy_writel(&buf_ctrl->rx_get, new_rx_get);
+	}
+}
+
+static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
+{
+	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
+	struct cyclades_card *cinfo = info->card;
+	u8 data;
+	unsigned int char_count;
+#ifdef BLOCKMOVE
+	int small_count;
+#endif
+	__u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
+
+	if (info->xmit_cnt <= 0)	/* Nothing to transmit */
+		return;
+
+	tx_get = readl(&buf_ctrl->tx_get);
+	tx_put = readl(&buf_ctrl->tx_put);
+	tx_bufsize = readl(&buf_ctrl->tx_bufsize);
+	tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
+	if (tx_put >= tx_get)
+		char_count = tx_get - tx_put - 1 + tx_bufsize;
+	else
+		char_count = tx_get - tx_put - 1;
+
+	if (char_count) {
+
+		if (tty == NULL)
+			goto ztxdone;
+
+		if (info->x_char) {	/* send special char */
+			data = info->x_char;
+
+			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+			tx_put = (tx_put + 1) & (tx_bufsize - 1);
+			info->x_char = 0;
+			char_count--;
+			info->icount.tx++;
+		}
+#ifdef BLOCKMOVE
+		while (0 < (small_count = min_t(unsigned int,
+				tx_bufsize - tx_put, min_t(unsigned int,
+					(SERIAL_XMIT_SIZE - info->xmit_tail),
+					min_t(unsigned int, info->xmit_cnt,
+						char_count))))) {
+
+			memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
+					tx_put),
+					&info->port.xmit_buf[info->xmit_tail],
+					small_count);
+
+			tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+			char_count -= small_count;
+			info->icount.tx += small_count;
+			info->xmit_cnt -= small_count;
+			info->xmit_tail = (info->xmit_tail + small_count) &
+					(SERIAL_XMIT_SIZE - 1);
+		}
+#else
+		while (info->xmit_cnt && char_count) {
+			data = info->port.xmit_buf[info->xmit_tail];
+			info->xmit_cnt--;
+			info->xmit_tail = (info->xmit_tail + 1) &
+					(SERIAL_XMIT_SIZE - 1);
+
+			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+			tx_put = (tx_put + 1) & (tx_bufsize - 1);
+			char_count--;
+			info->icount.tx++;
+		}
+#endif
+		tty_wakeup(tty);
+ztxdone:
+		/* Update tx_put */
+		cy_writel(&buf_ctrl->tx_put, tx_put);
+	}
+}
+
+static void cyz_handle_cmd(struct cyclades_card *cinfo)
+{
+	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
+	struct tty_struct *tty;
+	struct cyclades_port *info;
+	__u32 channel, param, fw_ver;
+	__u8 cmd;
+	int special_count;
+	int delta_count;
+
+	fw_ver = readl(&board_ctrl->fw_version);
+
+	while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
+		special_count = 0;
+		delta_count = 0;
+		info = &cinfo->ports[channel];
+		tty = tty_port_tty_get(&info->port);
+		if (tty == NULL)
+			continue;
+
+		switch (cmd) {
+		case C_CM_PR_ERROR:
+			tty_insert_flip_char(tty, 0, TTY_PARITY);
+			info->icount.rx++;
+			special_count++;
+			break;
+		case C_CM_FR_ERROR:
+			tty_insert_flip_char(tty, 0, TTY_FRAME);
+			info->icount.rx++;
+			special_count++;
+			break;
+		case C_CM_RXBRK:
+			tty_insert_flip_char(tty, 0, TTY_BREAK);
+			info->icount.rx++;
+			special_count++;
+			break;
+		case C_CM_MDCD:
+			info->icount.dcd++;
+			delta_count++;
+			if (info->port.flags & ASYNC_CHECK_CD) {
+				u32 dcd = fw_ver > 241 ? param :
+					readl(&info->u.cyz.ch_ctrl->rs_status);
+				if (dcd & C_RS_DCD)
+					wake_up_interruptible(&info->port.open_wait);
+				else
+					tty_hangup(tty);
+			}
+			break;
+		case C_CM_MCTS:
+			info->icount.cts++;
+			delta_count++;
+			break;
+		case C_CM_MRI:
+			info->icount.rng++;
+			delta_count++;
+			break;
+		case C_CM_MDSR:
+			info->icount.dsr++;
+			delta_count++;
+			break;
+#ifdef Z_WAKE
+		case C_CM_IOCTLW:
+			complete(&info->shutdown_wait);
+			break;
+#endif
+#ifdef CONFIG_CYZ_INTR
+		case C_CM_RXHIWM:
+		case C_CM_RXNNDT:
+		case C_CM_INTBACK2:
+			/* Reception Interrupt */
+#ifdef CY_DEBUG_INTERRUPTS
+			printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
+					"port %ld\n", info->card, channel);
+#endif
+			cyz_handle_rx(info, tty);
+			break;
+		case C_CM_TXBEMPTY:
+		case C_CM_TXLOWWM:
+		case C_CM_INTBACK:
+			/* Transmission Interrupt */
+#ifdef CY_DEBUG_INTERRUPTS
+			printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
+					"port %ld\n", info->card, channel);
+#endif
+			cyz_handle_tx(info, tty);
+			break;
+#endif				/* CONFIG_CYZ_INTR */
+		case C_CM_FATAL:
+			/* should do something with this !!! */
+			break;
+		default:
+			break;
+		}
+		if (delta_count)
+			wake_up_interruptible(&info->port.delta_msr_wait);
+		if (special_count)
+			tty_schedule_flip(tty);
+		tty_kref_put(tty);
+	}
+}
+
+#ifdef CONFIG_CYZ_INTR
+static irqreturn_t cyz_interrupt(int irq, void *dev_id)
+{
+	struct cyclades_card *cinfo = dev_id;
+
+	if (unlikely(!cyz_is_loaded(cinfo))) {
+#ifdef CY_DEBUG_INTERRUPTS
+		printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
+				"(IRQ%d).\n", irq);
+#endif
+		return IRQ_NONE;
+	}
+
+	/* Handle the interrupts */
+	cyz_handle_cmd(cinfo);
+
+	return IRQ_HANDLED;
+}				/* cyz_interrupt */
+
+static void cyz_rx_restart(unsigned long arg)
+{
+	struct cyclades_port *info = (struct cyclades_port *)arg;
+	struct cyclades_card *card = info->card;
+	int retval;
+	__u32 channel = info->line - card->first_line;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+	retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
+	if (retval != 0) {
+		printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
+			info->line, retval);
+	}
+	spin_unlock_irqrestore(&card->card_lock, flags);
+}
+
+#else				/* CONFIG_CYZ_INTR */
+
+static void cyz_poll(unsigned long arg)
+{
+	struct cyclades_card *cinfo;
+	struct cyclades_port *info;
+	unsigned long expires = jiffies + HZ;
+	unsigned int port, card;
+
+	for (card = 0; card < NR_CARDS; card++) {
+		cinfo = &cy_card[card];
+
+		if (!cy_is_Z(cinfo))
+			continue;
+		if (!cyz_is_loaded(cinfo))
+			continue;
+
+	/* Skip first polling cycle to avoid racing conditions with the FW */
+		if (!cinfo->intr_enabled) {
+			cinfo->intr_enabled = 1;
+			continue;
+		}
+
+		cyz_handle_cmd(cinfo);
+
+		for (port = 0; port < cinfo->nports; port++) {
+			struct tty_struct *tty;
+
+			info = &cinfo->ports[port];
+			tty = tty_port_tty_get(&info->port);
+			/* OK to pass NULL to the handle functions below.
+			   They need to drop the data in that case. */
+
+			if (!info->throttle)
+				cyz_handle_rx(info, tty);
+			cyz_handle_tx(info, tty);
+			tty_kref_put(tty);
+		}
+		/* poll every 'cyz_polling_cycle' period */
+		expires = jiffies + cyz_polling_cycle;
+	}
+	mod_timer(&cyz_timerlist, expires);
+}				/* cyz_poll */
+
+#endif				/* CONFIG_CYZ_INTR */
+
+/********** End of block of Cyclades-Z specific code *********/
+/***********************************************************/
+
+/* This is called whenever a port becomes active;
+   interrupts are enabled and DTR & RTS are turned on.
+ */
+static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
+{
+	struct cyclades_card *card;
+	unsigned long flags;
+	int retval = 0;
+	int channel;
+	unsigned long page;
+
+	card = info->card;
+	channel = info->line - card->first_line;
+
+	page = get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+
+	if (info->port.flags & ASYNC_INITIALIZED)
+		goto errout;
+
+	if (!info->type) {
+		set_bit(TTY_IO_ERROR, &tty->flags);
+		goto errout;
+	}
+
+	if (info->port.xmit_buf)
+		free_page(page);
+	else
+		info->port.xmit_buf = (unsigned char *)page;
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+	cy_set_line_char(info, tty);
+
+	if (!cy_is_Z(card)) {
+		channel &= 0x03;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+
+		cyy_writeb(info, CyCAR, channel);
+
+		cyy_writeb(info, CyRTPR,
+			(info->default_timeout ? info->default_timeout : 0x02));
+		/* 10ms rx timeout */
+
+		cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR);
+
+		cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
+
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData);
+	} else {
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
+
+		if (!cyz_is_loaded(card))
+			return -ENODEV;
+
+#ifdef CY_DEBUG_OPEN
+		printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
+			"base_addr %p\n", card, channel, card->base_addr);
+#endif
+		spin_lock_irqsave(&card->card_lock, flags);
+
+		cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE);
+#ifdef Z_WAKE
+#ifdef CONFIG_CYZ_INTR
+		cy_writel(&ch_ctrl->intr_enable,
+			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
+			  C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
+#else
+		cy_writel(&ch_ctrl->intr_enable,
+			  C_IN_IOCTLW | C_IN_MDCD);
+#endif				/* CONFIG_CYZ_INTR */
+#else
+#ifdef CONFIG_CYZ_INTR
+		cy_writel(&ch_ctrl->intr_enable,
+			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
+			  C_IN_RXNNDT | C_IN_MDCD);
+#else
+		cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD);
+#endif				/* CONFIG_CYZ_INTR */
+#endif				/* Z_WAKE */
+
+		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
+				"%x\n", info->line, retval);
+		}
+
+		/* Flush RX buffers before raising DTR and RTS */
+		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
+				"%x\n", info->line, retval);
+		}
+
+		/* set timeout !!! */
+		/* set RTS and DTR !!! */
+		tty_port_raise_dtr_rts(&info->port);
+
+		/* enable send, recv, modem !!! */
+	}
+
+	info->port.flags |= ASYNC_INITIALIZED;
+
+	clear_bit(TTY_IO_ERROR, &tty->flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	info->breakon = info->breakoff = 0;
+	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
+	info->idle_stats.in_use =
+	info->idle_stats.recv_idle =
+	info->idle_stats.xmit_idle = jiffies;
+
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+#ifdef CY_DEBUG_OPEN
+	printk(KERN_DEBUG "cyc startup done\n");
+#endif
+	return 0;
+
+errout:
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	free_page(page);
+	return retval;
+}				/* startup */
+
+static void start_xmit(struct cyclades_port *info)
+{
+	struct cyclades_card *card = info->card;
+	unsigned long flags;
+	int channel = info->line - card->first_line;
+
+	if (!cy_is_Z(card)) {
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	} else {
+#ifdef CONFIG_CYZ_INTR
+		int retval;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+		retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
+				"%x\n", info->line, retval);
+		}
+		spin_unlock_irqrestore(&card->card_lock, flags);
+#else				/* CONFIG_CYZ_INTR */
+		/* Don't have to do anything at this time */
+#endif				/* CONFIG_CYZ_INTR */
+	}
+}				/* start_xmit */
+
+/*
+ * This routine shuts down a serial port; interrupts are disabled,
+ * and DTR is dropped if the hangup on close termio flag is on.
+ */
+static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
+{
+	struct cyclades_card *card;
+	unsigned long flags;
+	int channel;
+
+	if (!(info->port.flags & ASYNC_INITIALIZED))
+		return;
+
+	card = info->card;
+	channel = info->line - card->first_line;
+	if (!cy_is_Z(card)) {
+		spin_lock_irqsave(&card->card_lock, flags);
+
+		/* Clear delta_msr_wait queue to avoid mem leaks. */
+		wake_up_interruptible(&info->port.delta_msr_wait);
+
+		if (info->port.xmit_buf) {
+			unsigned char *temp;
+			temp = info->port.xmit_buf;
+			info->port.xmit_buf = NULL;
+			free_page((unsigned long)temp);
+		}
+		if (tty->termios->c_cflag & HUPCL)
+			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
+
+		cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
+		/* it may be appropriate to clear _XMIT at
+		   some later date (after testing)!!! */
+
+		set_bit(TTY_IO_ERROR, &tty->flags);
+		info->port.flags &= ~ASYNC_INITIALIZED;
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	} else {
+#ifdef CY_DEBUG_OPEN
+		printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
+			"base_addr %p\n", card, channel, card->base_addr);
+#endif
+
+		if (!cyz_is_loaded(card))
+			return;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+
+		if (info->port.xmit_buf) {
+			unsigned char *temp;
+			temp = info->port.xmit_buf;
+			info->port.xmit_buf = NULL;
+			free_page((unsigned long)temp);
+		}
+
+		if (tty->termios->c_cflag & HUPCL)
+			tty_port_lower_dtr_rts(&info->port);
+
+		set_bit(TTY_IO_ERROR, &tty->flags);
+		info->port.flags &= ~ASYNC_INITIALIZED;
+
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	}
+
+#ifdef CY_DEBUG_OPEN
+	printk(KERN_DEBUG "cyc shutdown done\n");
+#endif
+}				/* shutdown */
+
+/*
+ * ------------------------------------------------------------
+ * cy_open() and friends
+ * ------------------------------------------------------------
+ */
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * performs the serial-specific initialization for the tty structure.
+ */
+static int cy_open(struct tty_struct *tty, struct file *filp)
+{
+	struct cyclades_port *info;
+	unsigned int i, line;
+	int retval;
+
+	line = tty->index;
+	if (tty->index < 0 || NR_PORTS <= line)
+		return -ENODEV;
+
+	for (i = 0; i < NR_CARDS; i++)
+		if (line < cy_card[i].first_line + cy_card[i].nports &&
+				line >= cy_card[i].first_line)
+			break;
+	if (i >= NR_CARDS)
+		return -ENODEV;
+	info = &cy_card[i].ports[line - cy_card[i].first_line];
+	if (info->line < 0)
+		return -ENODEV;
+
+	/* If the card's firmware hasn't been loaded,
+	   treat it as absent from the system.  This
+	   will make the user pay attention.
+	 */
+	if (cy_is_Z(info->card)) {
+		struct cyclades_card *cinfo = info->card;
+		struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
+
+		if (!cyz_is_loaded(cinfo)) {
+			if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) &&
+					readl(&firm_id->signature) ==
+					ZFIRM_HLT) {
+				printk(KERN_ERR "cyc:Cyclades-Z Error: you "
+					"need an external power supply for "
+					"this number of ports.\nFirmware "
+					"halted.\n");
+			} else {
+				printk(KERN_ERR "cyc:Cyclades-Z firmware not "
+					"yet loaded\n");
+			}
+			return -ENODEV;
+		}
+#ifdef CONFIG_CYZ_INTR
+		else {
+		/* In case this Z board is operating in interrupt mode, its
+		   interrupts should be enabled as soon as the first open
+		   happens to one of its ports. */
+			if (!cinfo->intr_enabled) {
+				u16 intr;
+
+				/* Enable interrupts on the PLX chip */
+				intr = readw(&cinfo->ctl_addr.p9060->
+						intr_ctrl_stat) | 0x0900;
+				cy_writew(&cinfo->ctl_addr.p9060->
+						intr_ctrl_stat, intr);
+				/* Enable interrupts on the FW */
+				retval = cyz_issue_cmd(cinfo, 0,
+						C_CM_IRQ_ENBL, 0L);
+				if (retval != 0) {
+					printk(KERN_ERR "cyc:IRQ enable retval "
+						"was %x\n", retval);
+				}
+				cinfo->intr_enabled = 1;
+			}
+		}
+#endif				/* CONFIG_CYZ_INTR */
+		/* Make sure this Z port really exists in hardware */
+		if (info->line > (cinfo->first_line + cinfo->nports - 1))
+			return -ENODEV;
+	}
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
+#endif
+	tty->driver_data = info;
+	if (serial_paranoia_check(info, tty->name, "cy_open"))
+		return -ENODEV;
+
+#ifdef CY_DEBUG_OPEN
+	printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
+			info->port.count);
+#endif
+	info->port.count++;
+#ifdef CY_DEBUG_COUNT
+	printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
+		current->pid, info->port.count);
+#endif
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
+		wait_event_interruptible_tty(info->port.close_wait,
+				!(info->port.flags & ASYNC_CLOSING));
+		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
+	}
+
+	/*
+	 * Start up serial port
+	 */
+	retval = cy_startup(info, tty);
+	if (retval)
+		return retval;
+
+	retval = tty_port_block_til_ready(&info->port, tty, filp);
+	if (retval) {
+#ifdef CY_DEBUG_OPEN
+		printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
+			"with %d\n", retval);
+#endif
+		return retval;
+	}
+
+	info->throttle = 0;
+	tty_port_tty_set(&info->port, tty);
+
+#ifdef CY_DEBUG_OPEN
+	printk(KERN_DEBUG "cyc:cy_open done\n");
+#endif
+	return 0;
+}				/* cy_open */
+
+/*
+ * cy_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct cyclades_card *card;
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long orig_jiffies;
+	int char_time;
+
+	if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
+		return;
+
+	if (info->xmit_fifo_size == 0)
+		return;		/* Just in case.... */
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 *
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time <= 0)
+		char_time = 1;
+	if (timeout < 0)
+		timeout = 0;
+	if (timeout)
+		char_time = min(char_time, timeout);
+	/*
+	 * If the transmitter hasn't cleared in twice the approximate
+	 * amount of time to send the entire FIFO, it probably won't
+	 * ever clear.  This assumes the UART isn't doing flow
+	 * control, which is currently the case.  Hence, if it ever
+	 * takes longer than info->timeout, this is probably due to a
+	 * UART bug of some kind.  So, we clamp the timeout parameter at
+	 * 2*info->timeout.
+	 */
+	if (!timeout || timeout > 2 * info->timeout)
+		timeout = 2 * info->timeout;
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+	printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...",
+		timeout, char_time, jiffies);
+#endif
+	card = info->card;
+	if (!cy_is_Z(card)) {
+		while (cyy_readb(info, CySRER) & CyTxRdy) {
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+			printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies);
+#endif
+			if (msleep_interruptible(jiffies_to_msecs(char_time)))
+				break;
+			if (timeout && time_after(jiffies, orig_jiffies +
+					timeout))
+				break;
+		}
+	}
+	/* Run one more char cycle */
+	msleep_interruptible(jiffies_to_msecs(char_time * 5));
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+	printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
+#endif
+}
+
+static void cy_flush_buffer(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	int channel, retval;
+	unsigned long flags;
+
+#ifdef CY_DEBUG_IO
+	printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+		return;
+
+	card = info->card;
+	channel = info->line - card->first_line;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+	if (cy_is_Z(card)) {	/* If it is a Z card, flush the on-board
+					   buffers as well */
+		spin_lock_irqsave(&card->card_lock, flags);
+		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
+				"was %x\n", info->line, retval);
+		}
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	}
+	tty_wakeup(tty);
+}				/* cy_flush_buffer */
+
+
+static void cy_do_close(struct tty_port *port)
+{
+	struct cyclades_port *info = container_of(port, struct cyclades_port,
+								port);
+	struct cyclades_card *card;
+	unsigned long flags;
+	int channel;
+
+	card = info->card;
+	channel = info->line - card->first_line;
+	spin_lock_irqsave(&card->card_lock, flags);
+
+	if (!cy_is_Z(card)) {
+		/* Stop accepting input */
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData);
+		if (info->port.flags & ASYNC_INITIALIZED) {
+			/* Waiting for on-board buffers to be empty before
+			   closing the port */
+			spin_unlock_irqrestore(&card->card_lock, flags);
+			cy_wait_until_sent(port->tty, info->timeout);
+			spin_lock_irqsave(&card->card_lock, flags);
+		}
+	} else {
+#ifdef Z_WAKE
+		/* Waiting for on-board buffers to be empty before closing
+		   the port */
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
+		int retval;
+
+		if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
+			retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
+			if (retval != 0) {
+				printk(KERN_DEBUG "cyc:cy_close retval on "
+					"ttyC%d was %x\n", info->line, retval);
+			}
+			spin_unlock_irqrestore(&card->card_lock, flags);
+			wait_for_completion_interruptible(&info->shutdown_wait);
+			spin_lock_irqsave(&card->card_lock, flags);
+		}
+#endif
+	}
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	cy_shutdown(info, port->tty);
+}
+
+/*
+ * This routine is called when a particular tty device is closed.
+ */
+static void cy_close(struct tty_struct *tty, struct file *filp)
+{
+	struct cyclades_port *info = tty->driver_data;
+	if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
+		return;
+	tty_port_close(&info->port, tty, filp);
+}				/* cy_close */
+
+/* This routine gets called when tty_write has put something into
+ * the write_queue.  The characters may come from user space or
+ * kernel space.
+ *
+ * This routine will return the number of characters actually
+ * accepted for writing.
+ *
+ * If the port is not already transmitting stuff, start it off by
+ * enabling interrupts.  The interrupt service routine will then
+ * ensure that the characters are sent.
+ * If the port is already active, there is no need to kick it.
+ *
+ */
+static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+	int c, ret = 0;
+
+#ifdef CY_DEBUG_IO
+	printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_write"))
+		return 0;
+
+	if (!info->port.xmit_buf)
+		return 0;
+
+	spin_lock_irqsave(&info->card->card_lock, flags);
+	while (1) {
+		c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
+		c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
+
+		if (c <= 0)
+			break;
+
+		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
+		info->xmit_head = (info->xmit_head + c) &
+			(SERIAL_XMIT_SIZE - 1);
+		info->xmit_cnt += c;
+		buf += c;
+		count -= c;
+		ret += c;
+	}
+	spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+	info->idle_stats.xmit_bytes += ret;
+	info->idle_stats.xmit_idle = jiffies;
+
+	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
+		start_xmit(info);
+
+	return ret;
+}				/* cy_write */
+
+/*
+ * This routine is called by the kernel to write a single
+ * character to the tty device.  If the kernel uses this routine,
+ * it must call the flush_chars() routine (if defined) when it is
+ * done stuffing characters into the driver.  If there is no room
+ * in the queue, the character is ignored.
+ */
+static int cy_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct cyclades_port *info = tty->driver_data;
+	unsigned long flags;
+
+#ifdef CY_DEBUG_IO
+	printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
+		return 0;
+
+	if (!info->port.xmit_buf)
+		return 0;
+
+	spin_lock_irqsave(&info->card->card_lock, flags);
+	if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
+		spin_unlock_irqrestore(&info->card->card_lock, flags);
+		return 0;
+	}
+
+	info->port.xmit_buf[info->xmit_head++] = ch;
+	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+	info->xmit_cnt++;
+	info->idle_stats.xmit_bytes++;
+	info->idle_stats.xmit_idle = jiffies;
+	spin_unlock_irqrestore(&info->card->card_lock, flags);
+	return 1;
+}				/* cy_put_char */
+
+/*
+ * This routine is called by the kernel after it has written a
+ * series of characters to the tty device using put_char().
+ */
+static void cy_flush_chars(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+#ifdef CY_DEBUG_IO
+	printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+			!info->port.xmit_buf)
+		return;
+
+	start_xmit(info);
+}				/* cy_flush_chars */
+
+/*
+ * This routine returns the numbers of characters the tty driver
+ * will accept for queuing to be written.  This number is subject
+ * to change as output buffers get emptied, or if the output flow
+ * control is activated.
+ */
+static int cy_write_room(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	int ret;
+
+#ifdef CY_DEBUG_IO
+	printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
+		return 0;
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}				/* cy_write_room */
+
+static int cy_chars_in_buffer(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
+		return 0;
+
+#ifdef Z_EXT_CHARS_IN_BUFFER
+	if (!cy_is_Z(info->card)) {
+#endif				/* Z_EXT_CHARS_IN_BUFFER */
+#ifdef CY_DEBUG_IO
+		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
+			info->line, info->xmit_cnt);
+#endif
+		return info->xmit_cnt;
+#ifdef Z_EXT_CHARS_IN_BUFFER
+	} else {
+		struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
+		int char_count;
+		__u32 tx_put, tx_get, tx_bufsize;
+
+		tx_get = readl(&buf_ctrl->tx_get);
+		tx_put = readl(&buf_ctrl->tx_put);
+		tx_bufsize = readl(&buf_ctrl->tx_bufsize);
+		if (tx_put >= tx_get)
+			char_count = tx_put - tx_get;
+		else
+			char_count = tx_put - tx_get + tx_bufsize;
+#ifdef CY_DEBUG_IO
+		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
+			info->line, info->xmit_cnt + char_count);
+#endif
+		return info->xmit_cnt + char_count;
+	}
+#endif				/* Z_EXT_CHARS_IN_BUFFER */
+}				/* cy_chars_in_buffer */
+
+/*
+ * ------------------------------------------------------------
+ * cy_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
+{
+	int co, co_val, bpr;
+	__u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
+			25000000);
+
+	if (baud == 0) {
+		info->tbpr = info->tco = info->rbpr = info->rco = 0;
+		return;
+	}
+
+	/* determine which prescaler to use */
+	for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
+		if (cy_clock / co_val / baud > 63)
+			break;
+	}
+
+	bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
+	if (bpr > 255)
+		bpr = 255;
+
+	info->tbpr = info->rbpr = bpr;
+	info->tco = info->rco = co;
+}
+
+/*
+ * This routine finds or computes the various line characteristics.
+ * It used to be called config_setup
+ */
+static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
+{
+	struct cyclades_card *card;
+	unsigned long flags;
+	int channel;
+	unsigned cflag, iflag;
+	int baud, baud_rate = 0;
+	int i;
+
+	if (!tty->termios) /* XXX can this happen at all? */
+		return;
+
+	if (info->line == -1)
+		return;
+
+	cflag = tty->termios->c_cflag;
+	iflag = tty->termios->c_iflag;
+
+	/*
+	 * Set up the tty->alt_speed kludge
+	 */
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+		tty->alt_speed = 57600;
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+		tty->alt_speed = 115200;
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+		tty->alt_speed = 230400;
+	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+		tty->alt_speed = 460800;
+
+	card = info->card;
+	channel = info->line - card->first_line;
+
+	if (!cy_is_Z(card)) {
+		u32 cflags;
+
+		/* baud rate */
+		baud = tty_get_baud_rate(tty);
+		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
+				ASYNC_SPD_CUST) {
+			if (info->custom_divisor)
+				baud_rate = info->baud / info->custom_divisor;
+			else
+				baud_rate = info->baud;
+		} else if (baud > CD1400_MAX_SPEED) {
+			baud = CD1400_MAX_SPEED;
+		}
+		/* find the baud index */
+		for (i = 0; i < 20; i++) {
+			if (baud == baud_table[i])
+				break;
+		}
+		if (i == 20)
+			i = 19;	/* CD1400_MAX_SPEED */
+
+		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
+				ASYNC_SPD_CUST) {
+			cyy_baud_calc(info, baud_rate);
+		} else {
+			if (info->chip_rev >= CD1400_REV_J) {
+				/* It is a CD1400 rev. J or later */
+				info->tbpr = baud_bpr_60[i];	/* Tx BPR */
+				info->tco = baud_co_60[i];	/* Tx CO */
+				info->rbpr = baud_bpr_60[i];	/* Rx BPR */
+				info->rco = baud_co_60[i];	/* Rx CO */
+			} else {
+				info->tbpr = baud_bpr_25[i];	/* Tx BPR */
+				info->tco = baud_co_25[i];	/* Tx CO */
+				info->rbpr = baud_bpr_25[i];	/* Rx BPR */
+				info->rco = baud_co_25[i];	/* Rx CO */
+			}
+		}
+		if (baud_table[i] == 134) {
+			/* get it right for 134.5 baud */
+			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
+					2;
+		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
+				ASYNC_SPD_CUST) {
+			info->timeout = (info->xmit_fifo_size * HZ * 15 /
+					baud_rate) + 2;
+		} else if (baud_table[i]) {
+			info->timeout = (info->xmit_fifo_size * HZ * 15 /
+					baud_table[i]) + 2;
+			/* this needs to be propagated into the card info */
+		} else {
+			info->timeout = 0;
+		}
+		/* By tradition (is it a standard?) a baud rate of zero
+		   implies the line should be/has been closed.  A bit
+		   later in this routine such a test is performed. */
+
+		/* byte size and parity */
+		info->cor5 = 0;
+		info->cor4 = 0;
+		/* receive threshold */
+		info->cor3 = (info->default_threshold ?
+				info->default_threshold : baud_cor3[i]);
+		info->cor2 = CyETC;
+		switch (cflag & CSIZE) {
+		case CS5:
+			info->cor1 = Cy_5_BITS;
+			break;
+		case CS6:
+			info->cor1 = Cy_6_BITS;
+			break;
+		case CS7:
+			info->cor1 = Cy_7_BITS;
+			break;
+		case CS8:
+			info->cor1 = Cy_8_BITS;
+			break;
+		}
+		if (cflag & CSTOPB)
+			info->cor1 |= Cy_2_STOP;
+
+		if (cflag & PARENB) {
+			if (cflag & PARODD)
+				info->cor1 |= CyPARITY_O;
+			else
+				info->cor1 |= CyPARITY_E;
+		} else
+			info->cor1 |= CyPARITY_NONE;
+
+		/* CTS flow control flag */
+		if (cflag & CRTSCTS) {
+			info->port.flags |= ASYNC_CTS_FLOW;
+			info->cor2 |= CyCtsAE;
+		} else {
+			info->port.flags &= ~ASYNC_CTS_FLOW;
+			info->cor2 &= ~CyCtsAE;
+		}
+		if (cflag & CLOCAL)
+			info->port.flags &= ~ASYNC_CHECK_CD;
+		else
+			info->port.flags |= ASYNC_CHECK_CD;
+
+	 /***********************************************
+	    The hardware option, CyRtsAO, presents RTS when
+	    the chip has characters to send.  Since most modems
+	    use RTS as reverse (inbound) flow control, this
+	    option is not used.  If inbound flow control is
+	    necessary, DTR can be programmed to provide the
+	    appropriate signals for use with a non-standard
+	    cable.  Contact Marcio Saito for details.
+	 ***********************************************/
+
+		channel &= 0x03;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_writeb(info, CyCAR, channel);
+
+		/* tx and rx baud rate */
+
+		cyy_writeb(info, CyTCOR, info->tco);
+		cyy_writeb(info, CyTBPR, info->tbpr);
+		cyy_writeb(info, CyRCOR, info->rco);
+		cyy_writeb(info, CyRBPR, info->rbpr);
+
+		/* set line characteristics  according configuration */
+
+		cyy_writeb(info, CySCHR1, START_CHAR(tty));
+		cyy_writeb(info, CySCHR2, STOP_CHAR(tty));
+		cyy_writeb(info, CyCOR1, info->cor1);
+		cyy_writeb(info, CyCOR2, info->cor2);
+		cyy_writeb(info, CyCOR3, info->cor3);
+		cyy_writeb(info, CyCOR4, info->cor4);
+		cyy_writeb(info, CyCOR5, info->cor5);
+
+		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
+				CyCOR3ch);
+
+		/* !!! Is this needed? */
+		cyy_writeb(info, CyCAR, channel);
+		cyy_writeb(info, CyRTPR,
+			(info->default_timeout ? info->default_timeout : 0x02));
+		/* 10ms rx timeout */
+
+		cflags = CyCTS;
+		if (!C_CLOCAL(tty))
+			cflags |= CyDSR | CyRI | CyDCD;
+		/* without modem intr */
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
+		/* act on 1->0 modem transitions */
+		if ((cflag & CRTSCTS) && info->rflow)
+			cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
+		else
+			cyy_writeb(info, CyMCOR1, cflags);
+		/* act on 0->1 modem transitions */
+		cyy_writeb(info, CyMCOR2, cflags);
+
+		if (i == 0)	/* baud rate is zero, turn off line */
+			cyy_change_rts_dtr(info, 0, TIOCM_DTR);
+		else
+			cyy_change_rts_dtr(info, TIOCM_DTR, 0);
+
+		clear_bit(TTY_IO_ERROR, &tty->flags);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+
+	} else {
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
+		__u32 sw_flow;
+		int retval;
+
+		if (!cyz_is_loaded(card))
+			return;
+
+		/* baud rate */
+		baud = tty_get_baud_rate(tty);
+		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
+				ASYNC_SPD_CUST) {
+			if (info->custom_divisor)
+				baud_rate = info->baud / info->custom_divisor;
+			else
+				baud_rate = info->baud;
+		} else if (baud > CYZ_MAX_SPEED) {
+			baud = CYZ_MAX_SPEED;
+		}
+		cy_writel(&ch_ctrl->comm_baud, baud);
+
+		if (baud == 134) {
+			/* get it right for 134.5 baud */
+			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
+					2;
+		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
+				ASYNC_SPD_CUST) {
+			info->timeout = (info->xmit_fifo_size * HZ * 15 /
+					baud_rate) + 2;
+		} else if (baud) {
+			info->timeout = (info->xmit_fifo_size * HZ * 15 /
+					baud) + 2;
+			/* this needs to be propagated into the card info */
+		} else {
+			info->timeout = 0;
+		}
+
+		/* byte size and parity */
+		switch (cflag & CSIZE) {
+		case CS5:
+			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
+			break;
+		case CS6:
+			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
+			break;
+		case CS7:
+			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
+			break;
+		case CS8:
+			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
+			break;
+		}
+		if (cflag & CSTOPB) {
+			cy_writel(&ch_ctrl->comm_data_l,
+				  readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
+		} else {
+			cy_writel(&ch_ctrl->comm_data_l,
+				  readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
+		}
+		if (cflag & PARENB) {
+			if (cflag & PARODD)
+				cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
+			else
+				cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
+		} else
+			cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
+
+		/* CTS flow control flag */
+		if (cflag & CRTSCTS) {
+			cy_writel(&ch_ctrl->hw_flow,
+				readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
+		} else {
+			cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
+					~(C_RS_CTS | C_RS_RTS));
+		}
+		/* As the HW flow control is done in firmware, the driver
+		   doesn't need to care about it */
+		info->port.flags &= ~ASYNC_CTS_FLOW;
+
+		/* XON/XOFF/XANY flow control flags */
+		sw_flow = 0;
+		if (iflag & IXON) {
+			sw_flow |= C_FL_OXX;
+			if (iflag & IXANY)
+				sw_flow |= C_FL_OIXANY;
+		}
+		cy_writel(&ch_ctrl->sw_flow, sw_flow);
+
+		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
+				"was %x\n", info->line, retval);
+		}
+
+		/* CD sensitivity */
+		if (cflag & CLOCAL)
+			info->port.flags &= ~ASYNC_CHECK_CD;
+		else
+			info->port.flags |= ASYNC_CHECK_CD;
+
+		if (baud == 0) {	/* baud rate is zero, turn off line */
+			cy_writel(&ch_ctrl->rs_control,
+				  readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
+#ifdef CY_DEBUG_DTR
+			printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n");
+#endif
+		} else {
+			cy_writel(&ch_ctrl->rs_control,
+				  readl(&ch_ctrl->rs_control) | C_RS_DTR);
+#ifdef CY_DEBUG_DTR
+			printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n");
+#endif
+		}
+
+		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
+				"was %x\n", info->line, retval);
+		}
+
+		clear_bit(TTY_IO_ERROR, &tty->flags);
+	}
+}				/* set_line_char */
+
+static int cy_get_serial_info(struct cyclades_port *info,
+		struct serial_struct __user *retinfo)
+{
+	struct cyclades_card *cinfo = info->card;
+	struct serial_struct tmp = {
+		.type = info->type,
+		.line = info->line,
+		.port = (info->card - cy_card) * 0x100 + info->line -
+			cinfo->first_line,
+		.irq = cinfo->irq,
+		.flags = info->port.flags,
+		.close_delay = info->port.close_delay,
+		.closing_wait = info->port.closing_wait,
+		.baud_base = info->baud,
+		.custom_divisor = info->custom_divisor,
+		.hub6 = 0,		/*!!! */
+	};
+	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+}
+
+static int
+cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
+		struct serial_struct __user *new_info)
+{
+	struct serial_struct new_serial;
+	int ret;
+
+	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+		return -EFAULT;
+
+	mutex_lock(&info->port.mutex);
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (new_serial.close_delay != info->port.close_delay ||
+				new_serial.baud_base != info->baud ||
+				(new_serial.flags & ASYNC_FLAGS &
+					~ASYNC_USR_MASK) !=
+				(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
+		{
+			mutex_unlock(&info->port.mutex);
+			return -EPERM;
+		}
+		info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
+				(new_serial.flags & ASYNC_USR_MASK);
+		info->baud = new_serial.baud_base;
+		info->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	info->baud = new_serial.baud_base;
+	info->custom_divisor = new_serial.custom_divisor;
+	info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
+			(new_serial.flags & ASYNC_FLAGS);
+	info->port.close_delay = new_serial.close_delay * HZ / 100;
+	info->port.closing_wait = new_serial.closing_wait * HZ / 100;
+
+check_and_exit:
+	if (info->port.flags & ASYNC_INITIALIZED) {
+		cy_set_line_char(info, tty);
+		ret = 0;
+	} else {
+		ret = cy_startup(info, tty);
+	}
+	mutex_unlock(&info->port.mutex);
+	return ret;
+}				/* set_serial_info */
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *	    is emptied.  On bus types like RS485, the transmitter must
+ *	    release the bus after transmitting. This must be done when
+ *	    the transmit shift register is empty, not be done when the
+ *	    transmit holding register is empty.  This functionality
+ *	    allows an RS485 driver to be written in user space.
+ */
+static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
+{
+	struct cyclades_card *card = info->card;
+	unsigned int result;
+	unsigned long flags;
+	u8 status;
+
+	if (!cy_is_Z(card)) {
+		spin_lock_irqsave(&card->card_lock, flags);
+		status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+		result = (status ? 0 : TIOCSER_TEMT);
+	} else {
+		/* Not supported yet */
+		return -EINVAL;
+	}
+	return put_user(result, (unsigned long __user *)value);
+}
+
+static int cy_tiocmget(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	int result;
+
+	if (serial_paranoia_check(info, tty->name, __func__))
+		return -ENODEV;
+
+	card = info->card;
+
+	if (!cy_is_Z(card)) {
+		unsigned long flags;
+		int channel = info->line - card->first_line;
+		u8 status;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		status = cyy_readb(info, CyMSVR1);
+		status |= cyy_readb(info, CyMSVR2);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+
+		if (info->rtsdtr_inv) {
+			result = ((status & CyRTS) ? TIOCM_DTR : 0) |
+				((status & CyDTR) ? TIOCM_RTS : 0);
+		} else {
+			result = ((status & CyRTS) ? TIOCM_RTS : 0) |
+				((status & CyDTR) ? TIOCM_DTR : 0);
+		}
+		result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
+			((status & CyRI) ? TIOCM_RNG : 0) |
+			((status & CyDSR) ? TIOCM_DSR : 0) |
+			((status & CyCTS) ? TIOCM_CTS : 0);
+	} else {
+		u32 lstatus;
+
+		if (!cyz_is_loaded(card)) {
+			result = -ENODEV;
+			goto end;
+		}
+
+		lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
+		result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
+			((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
+			((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
+			((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
+			((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
+			((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
+	}
+end:
+	return result;
+}				/* cy_tiomget */
+
+static int
+cy_tiocmset(struct tty_struct *tty,
+		unsigned int set, unsigned int clear)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->name, __func__))
+		return -ENODEV;
+
+	card = info->card;
+	if (!cy_is_Z(card)) {
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_change_rts_dtr(info, set, clear);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	} else {
+		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
+		int retval, channel = info->line - card->first_line;
+		u32 rs;
+
+		if (!cyz_is_loaded(card))
+			return -ENODEV;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+		rs = readl(&ch_ctrl->rs_control);
+		if (set & TIOCM_RTS)
+			rs |= C_RS_RTS;
+		if (clear & TIOCM_RTS)
+			rs &= ~C_RS_RTS;
+		if (set & TIOCM_DTR) {
+			rs |= C_RS_DTR;
+#ifdef CY_DEBUG_DTR
+			printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n");
+#endif
+		}
+		if (clear & TIOCM_DTR) {
+			rs &= ~C_RS_DTR;
+#ifdef CY_DEBUG_DTR
+			printk(KERN_DEBUG "cyc:set_modem_info clearing "
+				"Z DTR\n");
+#endif
+		}
+		cy_writel(&ch_ctrl->rs_control, rs);
+		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+		if (retval != 0) {
+			printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
+				"was %x\n", info->line, retval);
+		}
+	}
+	return 0;
+}
+
+/*
+ * cy_break() --- routine which turns the break handling on or off
+ */
+static int cy_break(struct tty_struct *tty, int break_state)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	unsigned long flags;
+	int retval = 0;
+
+	if (serial_paranoia_check(info, tty->name, "cy_break"))
+		return -EINVAL;
+
+	card = info->card;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+	if (!cy_is_Z(card)) {
+		/* Let the transmit ISR take care of this (since it
+		   requires stuffing characters into the output stream).
+		 */
+		if (break_state == -1) {
+			if (!info->breakon) {
+				info->breakon = 1;
+				if (!info->xmit_cnt) {
+					spin_unlock_irqrestore(&card->card_lock, flags);
+					start_xmit(info);
+					spin_lock_irqsave(&card->card_lock, flags);
+				}
+			}
+		} else {
+			if (!info->breakoff) {
+				info->breakoff = 1;
+				if (!info->xmit_cnt) {
+					spin_unlock_irqrestore(&card->card_lock, flags);
+					start_xmit(info);
+					spin_lock_irqsave(&card->card_lock, flags);
+				}
+			}
+		}
+	} else {
+		if (break_state == -1) {
+			retval = cyz_issue_cmd(card,
+				info->line - card->first_line,
+				C_CM_SET_BREAK, 0L);
+			if (retval != 0) {
+				printk(KERN_ERR "cyc:cy_break (set) retval on "
+					"ttyC%d was %x\n", info->line, retval);
+			}
+		} else {
+			retval = cyz_issue_cmd(card,
+				info->line - card->first_line,
+				C_CM_CLR_BREAK, 0L);
+			if (retval != 0) {
+				printk(KERN_DEBUG "cyc:cy_break (clr) retval "
+					"on ttyC%d was %x\n", info->line,
+					retval);
+			}
+		}
+	}
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	return retval;
+}				/* cy_break */
+
+static int set_threshold(struct cyclades_port *info, unsigned long value)
+{
+	struct cyclades_card *card = info->card;
+	unsigned long flags;
+
+	if (!cy_is_Z(card)) {
+		info->cor3 &= ~CyREC_FIFO;
+		info->cor3 |= value & CyREC_FIFO;
+
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_writeb(info, CyCOR3, info->cor3);
+		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	}
+	return 0;
+}				/* set_threshold */
+
+static int get_threshold(struct cyclades_port *info,
+						unsigned long __user *value)
+{
+	struct cyclades_card *card = info->card;
+
+	if (!cy_is_Z(card)) {
+		u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO;
+		return put_user(tmp, value);
+	}
+	return 0;
+}				/* get_threshold */
+
+static int set_timeout(struct cyclades_port *info, unsigned long value)
+{
+	struct cyclades_card *card = info->card;
+	unsigned long flags;
+
+	if (!cy_is_Z(card)) {
+		spin_lock_irqsave(&card->card_lock, flags);
+		cyy_writeb(info, CyRTPR, value & 0xff);
+		spin_unlock_irqrestore(&card->card_lock, flags);
+	}
+	return 0;
+}				/* set_timeout */
+
+static int get_timeout(struct cyclades_port *info,
+						unsigned long __user *value)
+{
+	struct cyclades_card *card = info->card;
+
+	if (!cy_is_Z(card)) {
+		u8 tmp = cyy_readb(info, CyRTPR);
+		return put_user(tmp, value);
+	}
+	return 0;
+}				/* get_timeout */
+
+static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg,
+		struct cyclades_icount *cprev)
+{
+	struct cyclades_icount cnow;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&info->card->card_lock, flags);
+	cnow = info->icount;	/* atomic copy */
+	spin_unlock_irqrestore(&info->card->card_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;
+}
+
+/*
+ * This routine allows the tty driver to implement device-
+ * specific ioctl's.  If the ioctl number passed in cmd is
+ * not recognized by the driver, it should return ENOIOCTLCMD.
+ */
+static int
+cy_ioctl(struct tty_struct *tty,
+	 unsigned int cmd, unsigned long arg)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_icount cnow;	/* kernel counter temps */
+	int ret_val = 0;
+	unsigned long flags;
+	void __user *argp = (void __user *)arg;
+
+	if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
+		return -ENODEV;
+
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
+		info->line, cmd, arg);
+#endif
+
+	switch (cmd) {
+	case CYGETMON:
+		if (copy_to_user(argp, &info->mon, sizeof(info->mon))) {
+			ret_val = -EFAULT;
+			break;
+		}
+		memset(&info->mon, 0, sizeof(info->mon));
+		break;
+	case CYGETTHRESH:
+		ret_val = get_threshold(info, argp);
+		break;
+	case CYSETTHRESH:
+		ret_val = set_threshold(info, arg);
+		break;
+	case CYGETDEFTHRESH:
+		ret_val = put_user(info->default_threshold,
+				(unsigned long __user *)argp);
+		break;
+	case CYSETDEFTHRESH:
+		info->default_threshold = arg & 0x0f;
+		break;
+	case CYGETTIMEOUT:
+		ret_val = get_timeout(info, argp);
+		break;
+	case CYSETTIMEOUT:
+		ret_val = set_timeout(info, arg);
+		break;
+	case CYGETDEFTIMEOUT:
+		ret_val = put_user(info->default_timeout,
+				(unsigned long __user *)argp);
+		break;
+	case CYSETDEFTIMEOUT:
+		info->default_timeout = arg & 0xff;
+		break;
+	case CYSETRFLOW:
+		info->rflow = (int)arg;
+		break;
+	case CYGETRFLOW:
+		ret_val = info->rflow;
+		break;
+	case CYSETRTSDTR_INV:
+		info->rtsdtr_inv = (int)arg;
+		break;
+	case CYGETRTSDTR_INV:
+		ret_val = info->rtsdtr_inv;
+		break;
+	case CYGETCD1400VER:
+		ret_val = info->chip_rev;
+		break;
+#ifndef CONFIG_CYZ_INTR
+	case CYZSETPOLLCYCLE:
+		cyz_polling_cycle = (arg * HZ) / 1000;
+		break;
+	case CYZGETPOLLCYCLE:
+		ret_val = (cyz_polling_cycle * 1000) / HZ;
+		break;
+#endif				/* CONFIG_CYZ_INTR */
+	case CYSETWAIT:
+		info->port.closing_wait = (unsigned short)arg * HZ / 100;
+		break;
+	case CYGETWAIT:
+		ret_val = info->port.closing_wait / (HZ / 100);
+		break;
+	case TIOCGSERIAL:
+		ret_val = cy_get_serial_info(info, argp);
+		break;
+	case TIOCSSERIAL:
+		ret_val = cy_set_serial_info(info, tty, argp);
+		break;
+	case TIOCSERGETLSR:	/* Get line status register */
+		ret_val = get_lsr_info(info, argp);
+		break;
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+	case TIOCMIWAIT:
+		spin_lock_irqsave(&info->card->card_lock, flags);
+		/* note the counters on entry */
+		cnow = info->icount;
+		spin_unlock_irqrestore(&info->card->card_lock, flags);
+		ret_val = wait_event_interruptible(info->port.delta_msr_wait,
+				cy_cflags_changed(info, arg, &cnow));
+		break;
+
+		/*
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+	default:
+		ret_val = -ENOIOCTLCMD;
+	}
+
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_ioctl done\n");
+#endif
+	return ret_val;
+}				/* cy_ioctl */
+
+static int cy_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *sic)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_icount cnow;	/* Used to snapshot */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->card->card_lock, flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+	sic->cts = cnow.cts;
+	sic->dsr = cnow.dsr;
+	sic->rng = cnow.rng;
+	sic->dcd = cnow.dcd;
+	sic->rx = cnow.rx;
+	sic->tx = cnow.tx;
+	sic->frame = cnow.frame;
+	sic->overrun = cnow.overrun;
+	sic->parity = cnow.parity;
+	sic->brk = cnow.brk;
+	sic->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
+/*
+ * This routine allows the tty driver to be notified when
+ * device's termios settings have changed.  Note that a
+ * well-designed tty driver should be prepared to accept the case
+ * where old == NULL, and try to do something rational.
+ */
+static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
+#endif
+
+	cy_set_line_char(info, tty);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		cy_start(tty);
+	}
+#if 0
+	/*
+	 * No need to wake up processes in open wait, since they
+	 * sample the CLOCAL flag once, and don't recheck it.
+	 * XXX  It's not clear whether the current behavior is correct
+	 * or not.  Hence, this may change.....
+	 */
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->port.open_wait);
+#endif
+}				/* cy_set_termios */
+
+/* This function is used to send a high-priority XON/XOFF character to
+   the device.
+*/
+static void cy_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	int channel;
+
+	if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
+		return;
+
+	info->x_char = ch;
+
+	if (ch)
+		cy_start(tty);
+
+	card = info->card;
+	channel = info->line - card->first_line;
+
+	if (cy_is_Z(card)) {
+		if (ch == STOP_CHAR(tty))
+			cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L);
+		else if (ch == START_CHAR(tty))
+			cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
+	}
+}
+
+/* This routine is called by the upper-layer tty layer to signal
+   that incoming characters should be throttled because the input
+   buffers are close to full.
+ */
+static void cy_throttle(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	unsigned long flags;
+
+#ifdef CY_DEBUG_THROTTLE
+	char buf[64];
+
+	printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf),
+			tty->ldisc.chars_in_buffer(tty), info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_throttle"))
+		return;
+
+	card = info->card;
+
+	if (I_IXOFF(tty)) {
+		if (!cy_is_Z(card))
+			cy_send_xchar(tty, STOP_CHAR(tty));
+		else
+			info->throttle = 1;
+	}
+
+	if (tty->termios->c_cflag & CRTSCTS) {
+		if (!cy_is_Z(card)) {
+			spin_lock_irqsave(&card->card_lock, flags);
+			cyy_change_rts_dtr(info, 0, TIOCM_RTS);
+			spin_unlock_irqrestore(&card->card_lock, flags);
+		} else {
+			info->throttle = 1;
+		}
+	}
+}				/* cy_throttle */
+
+/*
+ * This routine notifies the tty driver that it should signal
+ * that characters can now be sent to the tty without fear of
+ * overrunning the input buffers of the line disciplines.
+ */
+static void cy_unthrottle(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+	struct cyclades_card *card;
+	unsigned long flags;
+
+#ifdef CY_DEBUG_THROTTLE
+	char buf[64];
+
+	printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
+		tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			cy_send_xchar(tty, START_CHAR(tty));
+	}
+
+	if (tty->termios->c_cflag & CRTSCTS) {
+		card = info->card;
+		if (!cy_is_Z(card)) {
+			spin_lock_irqsave(&card->card_lock, flags);
+			cyy_change_rts_dtr(info, TIOCM_RTS, 0);
+			spin_unlock_irqrestore(&card->card_lock, flags);
+		} else {
+			info->throttle = 0;
+		}
+	}
+}				/* cy_unthrottle */
+
+/* cy_start and cy_stop provide software output flow control as a
+   function of XON/XOFF, software CTS, and other such stuff.
+*/
+static void cy_stop(struct tty_struct *tty)
+{
+	struct cyclades_card *cinfo;
+	struct cyclades_port *info = tty->driver_data;
+	int channel;
+	unsigned long flags;
+
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_stop"))
+		return;
+
+	cinfo = info->card;
+	channel = info->line - cinfo->first_line;
+	if (!cy_is_Z(cinfo)) {
+		spin_lock_irqsave(&cinfo->card_lock, flags);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
+		spin_unlock_irqrestore(&cinfo->card_lock, flags);
+	}
+}				/* cy_stop */
+
+static void cy_start(struct tty_struct *tty)
+{
+	struct cyclades_card *cinfo;
+	struct cyclades_port *info = tty->driver_data;
+	int channel;
+	unsigned long flags;
+
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_start"))
+		return;
+
+	cinfo = info->card;
+	channel = info->line - cinfo->first_line;
+	if (!cy_is_Z(cinfo)) {
+		spin_lock_irqsave(&cinfo->card_lock, flags);
+		cyy_writeb(info, CyCAR, channel & 0x03);
+		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
+		spin_unlock_irqrestore(&cinfo->card_lock, flags);
+	}
+}				/* cy_start */
+
+/*
+ * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void cy_hangup(struct tty_struct *tty)
+{
+	struct cyclades_port *info = tty->driver_data;
+
+#ifdef CY_DEBUG_OTHER
+	printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line);
+#endif
+
+	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
+		return;
+
+	cy_flush_buffer(tty);
+	cy_shutdown(info, tty);
+	tty_port_hangup(&info->port);
+}				/* cy_hangup */
+
+static int cyy_carrier_raised(struct tty_port *port)
+{
+	struct cyclades_port *info = container_of(port, struct cyclades_port,
+			port);
+	struct cyclades_card *cinfo = info->card;
+	unsigned long flags;
+	int channel = info->line - cinfo->first_line;
+	u32 cd;
+
+	spin_lock_irqsave(&cinfo->card_lock, flags);
+	cyy_writeb(info, CyCAR, channel & 0x03);
+	cd = cyy_readb(info, CyMSVR1) & CyDCD;
+	spin_unlock_irqrestore(&cinfo->card_lock, flags);
+
+	return cd;
+}
+
+static void cyy_dtr_rts(struct tty_port *port, int raise)
+{
+	struct cyclades_port *info = container_of(port, struct cyclades_port,
+			port);
+	struct cyclades_card *cinfo = info->card;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cinfo->card_lock, flags);
+	cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
+			raise ? 0 : TIOCM_RTS | TIOCM_DTR);
+	spin_unlock_irqrestore(&cinfo->card_lock, flags);
+}
+
+static int cyz_carrier_raised(struct tty_port *port)
+{
+	struct cyclades_port *info = container_of(port, struct cyclades_port,
+			port);
+
+	return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD;
+}
+
+static void cyz_dtr_rts(struct tty_port *port, int raise)
+{
+	struct cyclades_port *info = container_of(port, struct cyclades_port,
+			port);
+	struct cyclades_card *cinfo = info->card;
+	struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
+	int ret, channel = info->line - cinfo->first_line;
+	u32 rs;
+
+	rs = readl(&ch_ctrl->rs_control);
+	if (raise)
+		rs |= C_RS_RTS | C_RS_DTR;
+	else
+		rs &= ~(C_RS_RTS | C_RS_DTR);
+	cy_writel(&ch_ctrl->rs_control, rs);
+	ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L);
+	if (ret != 0)
+		printk(KERN_ERR "%s: retval on ttyC%d was %x\n",
+				__func__, info->line, ret);
+#ifdef CY_DEBUG_DTR
+	printk(KERN_DEBUG "%s: raising Z DTR\n", __func__);
+#endif
+}
+
+static const struct tty_port_operations cyy_port_ops = {
+	.carrier_raised = cyy_carrier_raised,
+	.dtr_rts = cyy_dtr_rts,
+	.shutdown = cy_do_close,
+};
+
+static const struct tty_port_operations cyz_port_ops = {
+	.carrier_raised = cyz_carrier_raised,
+	.dtr_rts = cyz_dtr_rts,
+	.shutdown = cy_do_close,
+};
+
+/*
+ * ---------------------------------------------------------------------
+ * cy_init() and friends
+ *
+ * cy_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+static int __devinit cy_init_card(struct cyclades_card *cinfo)
+{
+	struct cyclades_port *info;
+	unsigned int channel, port;
+
+	spin_lock_init(&cinfo->card_lock);
+	cinfo->intr_enabled = 0;
+
+	cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
+			GFP_KERNEL);
+	if (cinfo->ports == NULL) {
+		printk(KERN_ERR "Cyclades: cannot allocate ports\n");
+		return -ENOMEM;
+	}
+
+	for (channel = 0, port = cinfo->first_line; channel < cinfo->nports;
+			channel++, port++) {
+		info = &cinfo->ports[channel];
+		tty_port_init(&info->port);
+		info->magic = CYCLADES_MAGIC;
+		info->card = cinfo;
+		info->line = port;
+
+		info->port.closing_wait = CLOSING_WAIT_DELAY;
+		info->port.close_delay = 5 * HZ / 10;
+		info->port.flags = STD_COM_FLAGS;
+		init_completion(&info->shutdown_wait);
+
+		if (cy_is_Z(cinfo)) {
+			struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
+			struct ZFW_CTRL *zfw_ctrl;
+
+			info->port.ops = &cyz_port_ops;
+			info->type = PORT_STARTECH;
+
+			zfw_ctrl = cinfo->base_addr +
+				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
+			info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel];
+			info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
+
+			if (cinfo->hw_ver == ZO_V1)
+				info->xmit_fifo_size = CYZ_FIFO_SIZE;
+			else
+				info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
+#ifdef CONFIG_CYZ_INTR
+			setup_timer(&cyz_rx_full_timer[port],
+				cyz_rx_restart, (unsigned long)info);
+#endif
+		} else {
+			unsigned short chip_number;
+			int index = cinfo->bus_index;
+
+			info->port.ops = &cyy_port_ops;
+			info->type = PORT_CIRRUS;
+			info->xmit_fifo_size = CyMAX_CHAR_FIFO;
+			info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
+			info->cor2 = CyETC;
+			info->cor3 = 0x08;	/* _very_ small rcv threshold */
+
+			chip_number = channel / CyPORTS_PER_CHIP;
+			info->u.cyy.base_addr = cinfo->base_addr +
+				(cy_chip_offset[chip_number] << index);
+			info->chip_rev = cyy_readb(info, CyGFRCR);
+
+			if (info->chip_rev >= CD1400_REV_J) {
+				/* It is a CD1400 rev. J or later */
+				info->tbpr = baud_bpr_60[13];	/* Tx BPR */
+				info->tco = baud_co_60[13];	/* Tx CO */
+				info->rbpr = baud_bpr_60[13];	/* Rx BPR */
+				info->rco = baud_co_60[13];	/* Rx CO */
+				info->rtsdtr_inv = 1;
+			} else {
+				info->tbpr = baud_bpr_25[13];	/* Tx BPR */
+				info->tco = baud_co_25[13];	/* Tx CO */
+				info->rbpr = baud_bpr_25[13];	/* Rx BPR */
+				info->rco = baud_co_25[13];	/* Rx CO */
+				info->rtsdtr_inv = 0;
+			}
+			info->read_status_mask = CyTIMEOUT | CySPECHAR |
+				CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
+		}
+
+	}
+
+#ifndef CONFIG_CYZ_INTR
+	if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) {
+		mod_timer(&cyz_timerlist, jiffies + 1);
+#ifdef CY_PCI_DEBUG
+		printk(KERN_DEBUG "Cyclades-Z polling initialized\n");
+#endif
+	}
+#endif
+	return 0;
+}
+
+/* initialize chips on Cyclom-Y card -- return number of valid
+   chips (which is number of ports/4) */
+static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
+		int index)
+{
+	unsigned int chip_number;
+	void __iomem *base_addr;
+
+	cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
+	/* Cy_HwReset is 0x1400 */
+	cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
+	/* Cy_ClrIntr is 0x1800 */
+	udelay(500L);
+
+	for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
+							chip_number++) {
+		base_addr =
+		    true_base_addr + (cy_chip_offset[chip_number] << index);
+		mdelay(1);
+		if (readb(base_addr + (CyCCR << index)) != 0x00) {
+			/*************
+			printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
+			chip_number, (unsigned long)base_addr);
+			*************/
+			return chip_number;
+		}
+
+		cy_writeb(base_addr + (CyGFRCR << index), 0);
+		udelay(10L);
+
+		/* The Cyclom-16Y does not decode address bit 9 and therefore
+		   cannot distinguish between references to chip 0 and a non-
+		   existent chip 4.  If the preceding clearing of the supposed
+		   chip 4 GFRCR register appears at chip 0, there is no chip 4
+		   and this must be a Cyclom-16Y, not a Cyclom-32Ye.
+		 */
+		if (chip_number == 4 && readb(true_base_addr +
+				(cy_chip_offset[0] << index) +
+				(CyGFRCR << index)) == 0) {
+			return chip_number;
+		}
+
+		cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
+		mdelay(1);
+
+		if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
+			/*
+			   printk(" chip #%d at %#6lx is not responding ",
+			   chip_number, (unsigned long)base_addr);
+			   printk("(GFRCR stayed 0)\n",
+			 */
+			return chip_number;
+		}
+		if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
+				0x40) {
+			/*
+			printk(" chip #%d at %#6lx is not valid (GFRCR == "
+					"%#2x)\n",
+					chip_number, (unsigned long)base_addr,
+					base_addr[CyGFRCR<<index]);
+			 */
+			return chip_number;
+		}
+		cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
+		if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
+			/* It is a CD1400 rev. J or later */
+			/* Impossible to reach 5ms with this chip.
+			   Changed to 2ms instead (f = 500 Hz). */
+			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
+		} else {
+			/* f = 200 Hz */
+			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
+		}
+
+		/*
+		   printk(" chip #%d at %#6lx is rev 0x%2x\n",
+		   chip_number, (unsigned long)base_addr,
+		   readb(base_addr+(CyGFRCR<<index)));
+		 */
+	}
+	return chip_number;
+}				/* cyy_init_card */
+
+/*
+ * ---------------------------------------------------------------------
+ * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
+ * sets global variables and return the number of ISA boards found.
+ * ---------------------------------------------------------------------
+ */
+static int __init cy_detect_isa(void)
+{
+#ifdef CONFIG_ISA
+	unsigned short cy_isa_irq, nboard;
+	void __iomem *cy_isa_address;
+	unsigned short i, j, cy_isa_nchan;
+	int isparam = 0;
+
+	nboard = 0;
+
+	/* Check for module parameters */
+	for (i = 0; i < NR_CARDS; i++) {
+		if (maddr[i] || i) {
+			isparam = 1;
+			cy_isa_addresses[i] = maddr[i];
+		}
+		if (!maddr[i])
+			break;
+	}
+
+	/* scan the address table probing for Cyclom-Y/ISA boards */
+	for (i = 0; i < NR_ISA_ADDRS; i++) {
+		unsigned int isa_address = cy_isa_addresses[i];
+		if (isa_address == 0x0000)
+			return nboard;
+
+		/* probe for CD1400... */
+		cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
+		if (cy_isa_address == NULL) {
+			printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
+					"address\n");
+			continue;
+		}
+		cy_isa_nchan = CyPORTS_PER_CHIP *
+			cyy_init_card(cy_isa_address, 0);
+		if (cy_isa_nchan == 0) {
+			iounmap(cy_isa_address);
+			continue;
+		}
+
+		if (isparam && i < NR_CARDS && irq[i])
+			cy_isa_irq = irq[i];
+		else
+			/* find out the board's irq by probing */
+			cy_isa_irq = detect_isa_irq(cy_isa_address);
+		if (cy_isa_irq == 0) {
+			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
+				"IRQ could not be detected.\n",
+				(unsigned long)cy_isa_address);
+			iounmap(cy_isa_address);
+			continue;
+		}
+
+		if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
+			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
+				"more channels are available. Change NR_PORTS "
+				"in cyclades.c and recompile kernel.\n",
+				(unsigned long)cy_isa_address);
+			iounmap(cy_isa_address);
+			return nboard;
+		}
+		/* fill the next cy_card structure available */
+		for (j = 0; j < NR_CARDS; j++) {
+			if (cy_card[j].base_addr == NULL)
+				break;
+		}
+		if (j == NR_CARDS) {	/* no more cy_cards available */
+			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
+				"more cards can be used. Change NR_CARDS in "
+				"cyclades.c and recompile kernel.\n",
+				(unsigned long)cy_isa_address);
+			iounmap(cy_isa_address);
+			return nboard;
+		}
+
+		/* allocate IRQ */
+		if (request_irq(cy_isa_irq, cyy_interrupt,
+				IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
+			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
+				"could not allocate IRQ#%d.\n",
+				(unsigned long)cy_isa_address, cy_isa_irq);
+			iounmap(cy_isa_address);
+			return nboard;
+		}
+
+		/* set cy_card */
+		cy_card[j].base_addr = cy_isa_address;
+		cy_card[j].ctl_addr.p9050 = NULL;
+		cy_card[j].irq = (int)cy_isa_irq;
+		cy_card[j].bus_index = 0;
+		cy_card[j].first_line = cy_next_channel;
+		cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
+		cy_card[j].nports = cy_isa_nchan;
+		if (cy_init_card(&cy_card[j])) {
+			cy_card[j].base_addr = NULL;
+			free_irq(cy_isa_irq, &cy_card[j]);
+			iounmap(cy_isa_address);
+			continue;
+		}
+		nboard++;
+
+		printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
+			"%d channels starting from port %d\n",
+			j + 1, (unsigned long)cy_isa_address,
+			(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
+			cy_isa_irq, cy_isa_nchan, cy_next_channel);
+
+		for (j = cy_next_channel;
+				j < cy_next_channel + cy_isa_nchan; j++)
+			tty_register_device(cy_serial_driver, j, NULL);
+		cy_next_channel += cy_isa_nchan;
+	}
+	return nboard;
+#else
+	return 0;
+#endif				/* CONFIG_ISA */
+}				/* cy_detect_isa */
+
+#ifdef CONFIG_PCI
+static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
+{
+	unsigned int a;
+
+	for (a = 0; a < size && *str; a++, str++)
+		if (*str & 0x80)
+			return -EINVAL;
+
+	for (; a < size; a++, str++)
+		if (*str)
+			return -EINVAL;
+
+	return 0;
+}
+
+static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
+		unsigned int size)
+{
+	for (; size > 0; size--) {
+		cy_writel(fpga, *data++);
+		udelay(10);
+	}
+}
+
+static void __devinit plx_init(struct pci_dev *pdev, int irq,
+		struct RUNTIME_9060 __iomem *addr)
+{
+	/* Reset PLX */
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
+	udelay(100L);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
+
+	/* Reload Config. Registers from EEPROM */
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
+	udelay(100L);
+	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
+
+	/* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
+	 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
+	 * registers. This will remain here until we find a permanent fix.
+	 */
+	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
+}
+
+static int __devinit __cyz_load_fw(const struct firmware *fw,
+		const char *name, const u32 mailbox, void __iomem *base,
+		void __iomem *fpga)
+{
+	const void *ptr = fw->data;
+	const struct zfile_header *h = ptr;
+	const struct zfile_config *c, *cs;
+	const struct zfile_block *b, *bs;
+	unsigned int a, tmp, len = fw->size;
+#define BAD_FW KERN_ERR "Bad firmware: "
+	if (len < sizeof(*h)) {
+		printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
+		return -EINVAL;
+	}
+
+	cs = ptr + h->config_offset;
+	bs = ptr + h->block_offset;
+
+	if ((void *)(cs + h->n_config) > ptr + len ||
+			(void *)(bs + h->n_blocks) > ptr + len) {
+		printk(BAD_FW "too short");
+		return  -EINVAL;
+	}
+
+	if (cyc_isfwstr(h->name, sizeof(h->name)) ||
+			cyc_isfwstr(h->date, sizeof(h->date))) {
+		printk(BAD_FW "bad formatted header string\n");
+		return -EINVAL;
+	}
+
+	if (strncmp(name, h->name, sizeof(h->name))) {
+		printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
+		return -EINVAL;
+	}
+
+	tmp = 0;
+	for (c = cs; c < cs + h->n_config; c++) {
+		for (a = 0; a < c->n_blocks; a++)
+			if (c->block_list[a] > h->n_blocks) {
+				printk(BAD_FW "bad block ref number in cfgs\n");
+				return -EINVAL;
+			}
+		if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
+			tmp++;
+	}
+	if (!tmp) {
+		printk(BAD_FW "nothing appropriate\n");
+		return -EINVAL;
+	}
+
+	for (b = bs; b < bs + h->n_blocks; b++)
+		if (b->file_offset + b->size > len) {
+			printk(BAD_FW "bad block data offset\n");
+			return -EINVAL;
+		}
+
+	/* everything is OK, let's seek'n'load it */
+	for (c = cs; c < cs + h->n_config; c++)
+		if (c->mailbox == mailbox && c->function == 0)
+			break;
+
+	for (a = 0; a < c->n_blocks; a++) {
+		b = &bs[c->block_list[a]];
+		if (b->type == ZBLOCK_FPGA) {
+			if (fpga != NULL)
+				cyz_fpga_copy(fpga, ptr + b->file_offset,
+						b->size);
+		} else {
+			if (base != NULL)
+				memcpy_toio(base + b->ram_offset,
+					       ptr + b->file_offset, b->size);
+		}
+	}
+#undef BAD_FW
+	return 0;
+}
+
+static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
+		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
+{
+	const struct firmware *fw;
+	struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
+	struct CUSTOM_REG __iomem *cust = base_addr;
+	struct ZFW_CTRL __iomem *pt_zfwctrl;
+	void __iomem *tmp;
+	u32 mailbox, status, nchan;
+	unsigned int i;
+	int retval;
+
+	retval = request_firmware(&fw, "cyzfirm.bin", &pdev->dev);
+	if (retval) {
+		dev_err(&pdev->dev, "can't get firmware\n");
+		goto err;
+	}
+
+	/* Check whether the firmware is already loaded and running. If
+	   positive, skip this board */
+	if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
+		u32 cntval = readl(base_addr + 0x190);
+
+		udelay(100);
+		if (cntval != readl(base_addr + 0x190)) {
+			/* FW counter is working, FW is running */
+			dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
+					"Skipping board.\n");
+			retval = 0;
+			goto err_rel;
+		}
+	}
+
+	/* start boot */
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
+			~0x00030800UL);
+
+	mailbox = readl(&ctl_addr->mail_box_0);
+
+	if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) {
+		/* stops CPU and set window to beginning of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+		cy_writel(&cust->cpu_stop, 0);
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+		udelay(100);
+	}
+
+	plx_init(pdev, irq, ctl_addr);
+
+	if (mailbox != 0) {
+		/* load FPGA */
+		retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
+				base_addr);
+		if (retval)
+			goto err_rel;
+		if (!__cyz_fpga_loaded(ctl_addr)) {
+			dev_err(&pdev->dev, "fw upload successful, but fw is "
+					"not loaded\n");
+			goto err_rel;
+		}
+	}
+
+	/* stops CPU and set window to beginning of RAM */
+	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+	cy_writel(&cust->cpu_stop, 0);
+	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	udelay(100);
+
+	/* clear memory */
+	for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+		cy_writeb(tmp, 255);
+	if (mailbox != 0) {
+		/* set window to last 512K of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
+		for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
+			cy_writeb(tmp, 255);
+		/* set window to beginning of RAM */
+		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	}
+
+	retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
+	release_firmware(fw);
+	if (retval)
+		goto err;
+
+	/* finish boot and start boards */
+	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+	cy_writel(&cust->cpu_start, 0);
+	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+	i = 0;
+	while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
+		msleep(100);
+	if (status != ZFIRM_ID) {
+		if (status == ZFIRM_HLT) {
+			dev_err(&pdev->dev, "you need an external power supply "
+				"for this number of ports. Firmware halted and "
+				"board reset.\n");
+			retval = -EIO;
+			goto err;
+		}
+		dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
+				"some more time\n", status);
+		while ((status = readl(&fid->signature)) != ZFIRM_ID &&
+				i++ < 200)
+			msleep(100);
+		if (status != ZFIRM_ID) {
+			dev_err(&pdev->dev, "Board not started in 20 seconds! "
+					"Giving up. (fid->signature = 0x%x)\n",
+					status);
+			dev_info(&pdev->dev, "*** Warning ***: if you are "
+				"upgrading the FW, please power cycle the "
+				"system before loading the new FW to the "
+				"Cyclades-Z.\n");
+
+			if (__cyz_fpga_loaded(ctl_addr))
+				plx_init(pdev, irq, ctl_addr);
+
+			retval = -EIO;
+			goto err;
+		}
+		dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
+				i / 10);
+	}
+	pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
+
+	dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
+			base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
+			base_addr + readl(&fid->zfwctrl_addr));
+
+	nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
+	dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
+		readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
+
+	if (nchan == 0) {
+		dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
+			"check the connection between the Z host card and the "
+			"serial expanders.\n");
+
+		if (__cyz_fpga_loaded(ctl_addr))
+			plx_init(pdev, irq, ctl_addr);
+
+		dev_info(&pdev->dev, "Null number of ports detected. Board "
+				"reset.\n");
+		retval = 0;
+		goto err;
+	}
+
+	cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
+	cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
+
+	/*
+	   Early firmware failed to start looking for commands.
+	   This enables firmware interrupts for those commands.
+	 */
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+			(1 << 17));
+	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
+			0x00030800UL);
+
+	return nchan;
+err_rel:
+	release_firmware(fw);
+err:
+	return retval;
+}
+
+static int __devinit cy_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	void __iomem *addr0 = NULL, *addr2 = NULL;
+	char *card_name = NULL;
+	u32 uninitialized_var(mailbox);
+	unsigned int device_id, nchan = 0, card_no, i;
+	unsigned char plx_ver;
+	int retval, irq;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "cannot enable device\n");
+		goto err;
+	}
+
+	/* read PCI configuration area */
+	irq = pdev->irq;
+	device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
+
+#if defined(__alpha__)
+	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {	/* below 1M? */
+		dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
+			"addresses on Alpha systems.\n");
+		retval = -EIO;
+		goto err_dis;
+	}
+#endif
+	if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
+		dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
+			"addresses\n");
+		retval = -EIO;
+		goto err_dis;
+	}
+
+	if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
+		dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
+				"it...\n");
+		pdev->resource[2].flags &= ~IORESOURCE_IO;
+	}
+
+	retval = pci_request_regions(pdev, "cyclades");
+	if (retval) {
+		dev_err(&pdev->dev, "failed to reserve resources\n");
+		goto err_dis;
+	}
+
+	retval = -EIO;
+	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
+		card_name = "Cyclom-Y";
+
+		addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+				CyPCI_Yctl);
+		if (addr0 == NULL) {
+			dev_err(&pdev->dev, "can't remap ctl region\n");
+			goto err_reg;
+		}
+		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+				CyPCI_Ywin);
+		if (addr2 == NULL) {
+			dev_err(&pdev->dev, "can't remap base region\n");
+			goto err_unmap;
+		}
+
+		nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
+		if (nchan == 0) {
+			dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
+					"Serial-Modules\n");
+			goto err_unmap;
+		}
+	} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
+		struct RUNTIME_9060 __iomem *ctl_addr;
+
+		ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
+				CyPCI_Zctl);
+		if (addr0 == NULL) {
+			dev_err(&pdev->dev, "can't remap ctl region\n");
+			goto err_reg;
+		}
+
+		/* Disable interrupts on the PLX before resetting it */
+		cy_writew(&ctl_addr->intr_ctrl_stat,
+				readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
+
+		plx_init(pdev, irq, addr0);
+
+		mailbox = readl(&ctl_addr->mail_box_0);
+
+		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
+				mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
+		if (addr2 == NULL) {
+			dev_err(&pdev->dev, "can't remap base region\n");
+			goto err_unmap;
+		}
+
+		if (mailbox == ZE_V1) {
+			card_name = "Cyclades-Ze";
+		} else {
+			card_name = "Cyclades-8Zo";
+#ifdef CY_PCI_DEBUG
+			if (mailbox == ZO_V1) {
+				cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
+				dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
+					"id %lx, ver %lx\n", (ulong)(0xff &
+					readl(&((struct CUSTOM_REG *)addr2)->
+						fpga_id)), (ulong)(0xff &
+					readl(&((struct CUSTOM_REG *)addr2)->
+						fpga_version)));
+				cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
+			} else {
+				dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
+					"Cyclades-Z board.  FPGA not loaded\n");
+			}
+#endif
+			/* The following clears the firmware id word.  This
+			   ensures that the driver will not attempt to talk to
+			   the board until it has been properly initialized.
+			 */
+			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
+				cy_writel(addr2 + ID_ADDRESS, 0L);
+		}
+
+		retval = cyz_load_fw(pdev, addr2, addr0, irq);
+		if (retval <= 0)
+			goto err_unmap;
+		nchan = retval;
+	}
+
+	if ((cy_next_channel + nchan) > NR_PORTS) {
+		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
+			"channels are available. Change NR_PORTS in "
+			"cyclades.c and recompile kernel.\n");
+		goto err_unmap;
+	}
+	/* fill the next cy_card structure available */
+	for (card_no = 0; card_no < NR_CARDS; card_no++) {
+		if (cy_card[card_no].base_addr == NULL)
+			break;
+	}
+	if (card_no == NR_CARDS) {	/* no more cy_cards available */
+		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
+			"more cards can be used. Change NR_CARDS in "
+			"cyclades.c and recompile kernel.\n");
+		goto err_unmap;
+	}
+
+	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
+		/* allocate IRQ */
+		retval = request_irq(irq, cyy_interrupt,
+				IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
+		if (retval) {
+			dev_err(&pdev->dev, "could not allocate IRQ\n");
+			goto err_unmap;
+		}
+		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
+	} else {
+		struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
+		struct ZFW_CTRL __iomem *zfw_ctrl;
+
+		zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
+
+		cy_card[card_no].hw_ver = mailbox;
+		cy_card[card_no].num_chips = (unsigned int)-1;
+		cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
+#ifdef CONFIG_CYZ_INTR
+		/* allocate IRQ only if board has an IRQ */
+		if (irq != 0 && irq != 255) {
+			retval = request_irq(irq, cyz_interrupt,
+					IRQF_SHARED, "Cyclades-Z",
+					&cy_card[card_no]);
+			if (retval) {
+				dev_err(&pdev->dev, "could not allocate IRQ\n");
+				goto err_unmap;
+			}
+		}
+#endif				/* CONFIG_CYZ_INTR */
+	}
+
+	/* set cy_card */
+	cy_card[card_no].base_addr = addr2;
+	cy_card[card_no].ctl_addr.p9050 = addr0;
+	cy_card[card_no].irq = irq;
+	cy_card[card_no].bus_index = 1;
+	cy_card[card_no].first_line = cy_next_channel;
+	cy_card[card_no].nports = nchan;
+	retval = cy_init_card(&cy_card[card_no]);
+	if (retval)
+		goto err_null;
+
+	pci_set_drvdata(pdev, &cy_card[card_no]);
+
+	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
+			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
+		/* enable interrupts in the PCI interface */
+		plx_ver = readb(addr2 + CyPLX_VER) & 0x0f;
+		switch (plx_ver) {
+		case PLX_9050:
+			cy_writeb(addr0 + 0x4c, 0x43);
+			break;
+
+		case PLX_9060:
+		case PLX_9080:
+		default:	/* Old boards, use PLX_9060 */
+		{
+			struct RUNTIME_9060 __iomem *ctl_addr = addr0;
+			plx_init(pdev, irq, ctl_addr);
+			cy_writew(&ctl_addr->intr_ctrl_stat,
+				readw(&ctl_addr->intr_ctrl_stat) | 0x0900);
+			break;
+		}
+		}
+	}
+
+	dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from "
+		"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
+	for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
+		tty_register_device(cy_serial_driver, i, &pdev->dev);
+	cy_next_channel += nchan;
+
+	return 0;
+err_null:
+	cy_card[card_no].base_addr = NULL;
+	free_irq(irq, &cy_card[card_no]);
+err_unmap:
+	iounmap(addr0);
+	if (addr2)
+		iounmap(addr2);
+err_reg:
+	pci_release_regions(pdev);
+err_dis:
+	pci_disable_device(pdev);
+err:
+	return retval;
+}
+
+static void __devexit cy_pci_remove(struct pci_dev *pdev)
+{
+	struct cyclades_card *cinfo = pci_get_drvdata(pdev);
+	unsigned int i;
+
+	/* non-Z with old PLX */
+	if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
+			PLX_9050)
+		cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
+	else
+#ifndef CONFIG_CYZ_INTR
+		if (!cy_is_Z(cinfo))
+#endif
+		cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat,
+			readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) &
+			~0x0900);
+
+	iounmap(cinfo->base_addr);
+	if (cinfo->ctl_addr.p9050)
+		iounmap(cinfo->ctl_addr.p9050);
+	if (cinfo->irq
+#ifndef CONFIG_CYZ_INTR
+		&& !cy_is_Z(cinfo)
+#endif /* CONFIG_CYZ_INTR */
+		)
+		free_irq(cinfo->irq, cinfo);
+	pci_release_regions(pdev);
+
+	cinfo->base_addr = NULL;
+	for (i = cinfo->first_line; i < cinfo->first_line +
+			cinfo->nports; i++)
+		tty_unregister_device(cy_serial_driver, i);
+	cinfo->nports = 0;
+	kfree(cinfo->ports);
+}
+
+static struct pci_driver cy_pci_driver = {
+	.name = "cyclades",
+	.id_table = cy_pci_dev_id,
+	.probe = cy_pci_probe,
+	.remove = __devexit_p(cy_pci_remove)
+};
+#endif
+
+static int cyclades_proc_show(struct seq_file *m, void *v)
+{
+	struct cyclades_port *info;
+	unsigned int i, j;
+	__u32 cur_jifs = jiffies;
+
+	seq_puts(m, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
+			"IdleIn  Overruns  Ldisc\n");
+
+	/* Output one line for each known port */
+	for (i = 0; i < NR_CARDS; i++)
+		for (j = 0; j < cy_card[i].nports; j++) {
+			info = &cy_card[i].ports[j];
+
+			if (info->port.count) {
+				/* XXX is the ldisc num worth this? */
+				struct tty_struct *tty;
+				struct tty_ldisc *ld;
+				int num = 0;
+				tty = tty_port_tty_get(&info->port);
+				if (tty) {
+					ld = tty_ldisc_ref(tty);
+					if (ld) {
+						num = ld->ops->num;
+						tty_ldisc_deref(ld);
+					}
+					tty_kref_put(tty);
+				}
+				seq_printf(m, "%3d %8lu %10lu %8lu "
+					"%10lu %8lu %9lu %6d\n", info->line,
+					(cur_jifs - info->idle_stats.in_use) /
+					HZ, info->idle_stats.xmit_bytes,
+					(cur_jifs - info->idle_stats.xmit_idle)/
+					HZ, info->idle_stats.recv_bytes,
+					(cur_jifs - info->idle_stats.recv_idle)/
+					HZ, info->idle_stats.overruns,
+					num);
+			} else
+				seq_printf(m, "%3d %8lu %10lu %8lu "
+					"%10lu %8lu %9lu %6ld\n",
+					info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
+		}
+	return 0;
+}
+
+static int cyclades_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, cyclades_proc_show, NULL);
+}
+
+static const struct file_operations cyclades_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= cyclades_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/* The serial driver boot-time initialization code!
+    Hardware I/O ports are mapped to character special devices on a
+    first found, first allocated manner.  That is, this code searches
+    for Cyclom cards in the system.  As each is found, it is probed
+    to discover how many chips (and thus how many ports) are present.
+    These ports are mapped to the tty ports 32 and upward in monotonic
+    fashion.  If an 8-port card is replaced with a 16-port card, the
+    port mapping on a following card will shift.
+
+    This approach is different from what is used in the other serial
+    device driver because the Cyclom is more properly a multiplexer,
+    not just an aggregation of serial ports on one card.
+
+    If there are more cards with more ports than have been
+    statically allocated above, a warning is printed and the
+    extra ports are ignored.
+ */
+
+static const struct tty_operations cy_ops = {
+	.open = cy_open,
+	.close = cy_close,
+	.write = cy_write,
+	.put_char = cy_put_char,
+	.flush_chars = cy_flush_chars,
+	.write_room = cy_write_room,
+	.chars_in_buffer = cy_chars_in_buffer,
+	.flush_buffer = cy_flush_buffer,
+	.ioctl = cy_ioctl,
+	.throttle = cy_throttle,
+	.unthrottle = cy_unthrottle,
+	.set_termios = cy_set_termios,
+	.stop = cy_stop,
+	.start = cy_start,
+	.hangup = cy_hangup,
+	.break_ctl = cy_break,
+	.wait_until_sent = cy_wait_until_sent,
+	.tiocmget = cy_tiocmget,
+	.tiocmset = cy_tiocmset,
+	.get_icount = cy_get_icount,
+	.proc_fops = &cyclades_proc_fops,
+};
+
+static int __init cy_init(void)
+{
+	unsigned int nboards;
+	int retval = -ENOMEM;
+
+	cy_serial_driver = alloc_tty_driver(NR_PORTS);
+	if (!cy_serial_driver)
+		goto err;
+
+	printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n",
+			__DATE__, __TIME__);
+
+	/* Initialize the tty_driver structure */
+
+	cy_serial_driver->owner = THIS_MODULE;
+	cy_serial_driver->driver_name = "cyclades";
+	cy_serial_driver->name = "ttyC";
+	cy_serial_driver->major = CYCLADES_MAJOR;
+	cy_serial_driver->minor_start = 0;
+	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	cy_serial_driver->init_termios = tty_std_termios;
+	cy_serial_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(cy_serial_driver, &cy_ops);
+
+	retval = tty_register_driver(cy_serial_driver);
+	if (retval) {
+		printk(KERN_ERR "Couldn't register Cyclades serial driver\n");
+		goto err_frtty;
+	}
+
+	/* the code below is responsible to find the boards. Each different
+	   type of board has its own detection routine. If a board is found,
+	   the next cy_card structure available is set by the detection
+	   routine. These functions are responsible for checking the
+	   availability of cy_card and cy_port data structures and updating
+	   the cy_next_channel. */
+
+	/* look for isa boards */
+	nboards = cy_detect_isa();
+
+#ifdef CONFIG_PCI
+	/* look for pci boards */
+	retval = pci_register_driver(&cy_pci_driver);
+	if (retval && !nboards) {
+		tty_unregister_driver(cy_serial_driver);
+		goto err_frtty;
+	}
+#endif
+
+	return 0;
+err_frtty:
+	put_tty_driver(cy_serial_driver);
+err:
+	return retval;
+}				/* cy_init */
+
+static void __exit cy_cleanup_module(void)
+{
+	struct cyclades_card *card;
+	unsigned int i, e1;
+
+#ifndef CONFIG_CYZ_INTR
+	del_timer_sync(&cyz_timerlist);
+#endif /* CONFIG_CYZ_INTR */
+
+	e1 = tty_unregister_driver(cy_serial_driver);
+	if (e1)
+		printk(KERN_ERR "failed to unregister Cyclades serial "
+				"driver(%d)\n", e1);
+
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&cy_pci_driver);
+#endif
+
+	for (i = 0; i < NR_CARDS; i++) {
+		card = &cy_card[i];
+		if (card->base_addr) {
+			/* clear interrupt */
+			cy_writeb(card->base_addr + Cy_ClrIntr, 0);
+			iounmap(card->base_addr);
+			if (card->ctl_addr.p9050)
+				iounmap(card->ctl_addr.p9050);
+			if (card->irq
+#ifndef CONFIG_CYZ_INTR
+				&& !cy_is_Z(card)
+#endif /* CONFIG_CYZ_INTR */
+				)
+				free_irq(card->irq, card);
+			for (e1 = card->first_line; e1 < card->first_line +
+					card->nports; e1++)
+				tty_unregister_device(cy_serial_driver, e1);
+			kfree(card->ports);
+		}
+	}
+
+	put_tty_driver(cy_serial_driver);
+} /* cy_cleanup_module */
+
+module_init(cy_init);
+module_exit(cy_cleanup_module);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(CY_VERSION);
+MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
+MODULE_FIRMWARE("cyzfirm.bin");
diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig
new file mode 100644
index 0000000..6f2c980
--- /dev/null
+++ b/drivers/tty/hvc/Kconfig
@@ -0,0 +1,105 @@
+config HVC_DRIVER
+	bool
+	help
+	  Generic "hypervisor virtual console" infrastructure for various
+	  hypervisors (pSeries, iSeries, Xen, lguest).
+	  It will automatically be selected if one of the back-end console drivers
+	  is selected.
+
+config HVC_IRQ
+	bool
+
+config HVC_CONSOLE
+	bool "pSeries Hypervisor Virtual Console support"
+	depends on PPC_PSERIES
+	select HVC_DRIVER
+	select HVC_IRQ
+	help
+	  pSeries machines when partitioned support a hypervisor virtual
+	  console. This driver allows each pSeries partition to have a console
+	  which is accessed via the HMC.
+
+config HVC_ISERIES
+	bool "iSeries Hypervisor Virtual Console support"
+	depends on PPC_ISERIES
+	default y
+	select HVC_DRIVER
+	select HVC_IRQ
+	select VIOPATH
+	help
+	  iSeries machines support a hypervisor virtual console.
+
+config HVC_RTAS
+	bool "IBM RTAS Console support"
+	depends on PPC_RTAS
+	select HVC_DRIVER
+	help
+	  IBM Console device driver which makes use of RTAS
+
+config HVC_BEAT
+	bool "Toshiba's Beat Hypervisor Console support"
+	depends on PPC_CELLEB
+	select HVC_DRIVER
+	help
+	  Toshiba's Cell Reference Set Beat Console device driver
+
+config HVC_IUCV
+	bool "z/VM IUCV Hypervisor console support (VM only)"
+	depends on S390
+	select HVC_DRIVER
+	select IUCV
+	default y
+	help
+	  This driver provides a Hypervisor console (HVC) back-end to access
+	  a Linux (console) terminal via a z/VM IUCV communication path.
+
+config HVC_XEN
+	bool "Xen Hypervisor Console support"
+	depends on XEN
+	select HVC_DRIVER
+	select HVC_IRQ
+	default y
+	help
+	  Xen virtual console device driver
+
+config HVC_UDBG
+       bool "udbg based fake hypervisor console"
+       depends on PPC && EXPERIMENTAL
+       select HVC_DRIVER
+       default n
+
+config HVC_DCC
+       bool "ARM JTAG DCC console"
+       depends on ARM
+       select HVC_DRIVER
+       help
+         This console uses the JTAG DCC on ARM to create a console under the HVC
+	 driver. This console is used through a JTAG only on ARM. If you don't have
+	 a JTAG then you probably don't want this option.
+
+config HVC_BFIN_JTAG
+	bool "Blackfin JTAG console"
+	depends on BLACKFIN
+	select HVC_DRIVER
+	help
+	 This console uses the Blackfin JTAG to create a console under the
+	 the HVC driver.  If you don't have JTAG, then you probably don't
+	 want this option.
+
+config HVCS
+	tristate "IBM Hypervisor Virtual Console Server support"
+	depends on PPC_PSERIES && HVC_CONSOLE
+	help
+	  Partitionable IBM Power5 ppc64 machines allow hosting of
+	  firmware virtual consoles from one Linux partition by
+	  another Linux partition.  This driver allows console data
+	  from Linux partitions to be accessed through TTY device
+	  interfaces in the device tree of a Linux partition running
+	  this driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hvcs.  Additionally, this module
+	  will depend on arch specific APIs exported from hvcserver.ko
+	  which will also be compiled when this driver is built as a
+	  module.
+
diff --git a/drivers/tty/hvc/Makefile b/drivers/tty/hvc/Makefile
index d79e7e9..40a25d9 100644
--- a/drivers/tty/hvc/Makefile
+++ b/drivers/tty/hvc/Makefile
@@ -9,4 +9,5 @@ obj-$(CONFIG_HVC_IRQ)		+= hvc_irq.o
 obj-$(CONFIG_HVC_XEN)		+= hvc_xen.o
 obj-$(CONFIG_HVC_IUCV)		+= hvc_iucv.o
 obj-$(CONFIG_HVC_UDBG)		+= hvc_udbg.o
+obj-$(CONFIG_HVC_BFIN_JTAG)	+= hvc_bfin_jtag.o
 obj-$(CONFIG_HVCS)		+= hvcs.o
diff --git a/drivers/tty/hvc/hvc_bfin_jtag.c b/drivers/tty/hvc/hvc_bfin_jtag.c
new file mode 100644
index 0000000..31d6cc6
--- /dev/null
+++ b/drivers/tty/hvc/hvc_bfin_jtag.c
@@ -0,0 +1,105 @@
+/*
+ * Console via Blackfin JTAG Communication
+ *
+ * Copyright 2008-2011 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+
+#include "hvc_console.h"
+
+/* See the Debug/Emulation chapter in the HRM */
+#define EMUDOF   0x00000001	/* EMUDAT_OUT full & valid */
+#define EMUDIF   0x00000002	/* EMUDAT_IN full & valid */
+#define EMUDOOVF 0x00000004	/* EMUDAT_OUT overflow */
+#define EMUDIOVF 0x00000008	/* EMUDAT_IN overflow */
+
+/* Helper functions to glue the register API to simple C operations */
+static inline uint32_t bfin_write_emudat(uint32_t emudat)
+{
+	__asm__ __volatile__("emudat = %0;" : : "d"(emudat));
+	return emudat;
+}
+
+static inline uint32_t bfin_read_emudat(void)
+{
+	uint32_t emudat;
+	__asm__ __volatile__("%0 = emudat;" : "=d"(emudat));
+	return emudat;
+}
+
+/* Send data to the host */
+static int hvc_bfin_put_chars(uint32_t vt, const char *buf, int count)
+{
+	static uint32_t outbound_len;
+	uint32_t emudat;
+	int ret;
+
+	if (bfin_read_DBGSTAT() & EMUDOF)
+		return 0;
+
+	if (!outbound_len) {
+		outbound_len = count;
+		bfin_write_emudat(outbound_len);
+		return 0;
+	}
+
+	ret = min(outbound_len, (uint32_t)4);
+	memcpy(&emudat, buf, ret);
+	bfin_write_emudat(emudat);
+	outbound_len -= ret;
+
+	return ret;
+}
+
+/* Receive data from the host */
+static int hvc_bfin_get_chars(uint32_t vt, char *buf, int count)
+{
+	static uint32_t inbound_len;
+	uint32_t emudat;
+	int ret;
+
+	if (!(bfin_read_DBGSTAT() & EMUDIF))
+		return 0;
+	emudat = bfin_read_emudat();
+
+	if (!inbound_len) {
+		inbound_len = emudat;
+		return 0;
+	}
+
+	ret = min(inbound_len, (uint32_t)4);
+	memcpy(buf, &emudat, ret);
+	inbound_len -= ret;
+
+	return ret;
+}
+
+/* Glue the HVC layers to the Blackfin layers */
+static const struct hv_ops hvc_bfin_get_put_ops = {
+	.get_chars = hvc_bfin_get_chars,
+	.put_chars = hvc_bfin_put_chars,
+};
+
+static int __init hvc_bfin_console_init(void)
+{
+	hvc_instantiate(0, 0, &hvc_bfin_get_put_ops);
+	return 0;
+}
+console_initcall(hvc_bfin_console_init);
+
+static int __init hvc_bfin_init(void)
+{
+	hvc_alloc(0, 0, &hvc_bfin_get_put_ops, 128);
+	return 0;
+}
+device_initcall(hvc_bfin_init);
diff --git a/drivers/tty/hvc/hvc_dcc.c b/drivers/tty/hvc/hvc_dcc.c
index 6470f63..435f6fa 100644
--- a/drivers/tty/hvc/hvc_dcc.c
+++ b/drivers/tty/hvc/hvc_dcc.c
@@ -33,54 +33,29 @@
 static inline u32 __dcc_getstatus(void)
 {
 	u32 __ret;
-
-	asm("mrc p14, 0, %0, c0, c1, 0	@ read comms ctrl reg"
+	asm volatile("mrc p14, 0, %0, c0, c1, 0	@ read comms ctrl reg"
 		: "=r" (__ret) : : "cc");
 
 	return __ret;
 }
 
 
-#if defined(CONFIG_CPU_V7)
 static inline char __dcc_getchar(void)
 {
 	char __c;
 
-	asm("get_wait:	mrc p14, 0, pc, c0, c1, 0                          \n\
-			bne get_wait                                       \n\
-			mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
-		: "=r" (__c) : : "cc");
-
-	return __c;
-}
-#else
-static inline char __dcc_getchar(void)
-{
-	char __c;
-
-	asm("mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
+	asm volatile("mrc p14, 0, %0, c0, c5, 0	@ read comms data reg"
 		: "=r" (__c));
 
 	return __c;
 }
-#endif
 
-#if defined(CONFIG_CPU_V7)
-static inline void __dcc_putchar(char c)
-{
-	asm("put_wait:	mrc p14, 0, pc, c0, c1, 0                 \n\
-			bcs put_wait                              \n\
-			mcr p14, 0, %0, c0, c5, 0                   "
-	: : "r" (c) : "cc");
-}
-#else
 static inline void __dcc_putchar(char c)
 {
-	asm("mcr p14, 0, %0, c0, c5, 0	@ write a char"
+	asm volatile("mcr p14, 0, %0, c0, c5, 0	@ write a char"
 		: /* no output register */
 		: "r" (c));
 }
-#endif
 
 static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
 {
@@ -90,7 +65,7 @@ static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
 		while (__dcc_getstatus() & DCC_STATUS_TX)
 			cpu_relax();
 
-		__dcc_putchar((char)(buf[i] & 0xFF));
+		__dcc_putchar(buf[i]);
 	}
 
 	return count;
@@ -100,15 +75,11 @@ static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
 {
 	int i;
 
-	for (i = 0; i < count; ++i) {
-		int c = -1;
-
+	for (i = 0; i < count; ++i)
 		if (__dcc_getstatus() & DCC_STATUS_RX)
-			c = __dcc_getchar();
-		if (c < 0)
+			buf[i] = __dcc_getchar();
+		else
 			break;
-		buf[i] = c;
-	}
 
 	return i;
 }
diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index 3740e32..c35f1a7 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -177,6 +177,8 @@ static int __init xen_hvc_init(void)
 	}
 	if (xencons_irq < 0)
 		xencons_irq = 0; /* NO_IRQ */
+	else
+		set_irq_noprobe(xencons_irq);
 
 	hp = hvc_alloc(HVC_COOKIE, xencons_irq, ops, 256);
 	if (IS_ERR(hp))
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index bedc6c1..bef238f 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -292,7 +292,7 @@ struct hvcs_struct {
 	/*
 	 * Any variable below the kref is valid before a tty is connected and
 	 * stays valid after the tty is disconnected.  These shouldn't be
-	 * whacked until the koject refcount reaches zero though some entries
+	 * whacked until the kobject refcount reaches zero though some entries
 	 * may be changed via sysfs initiatives.
 	 */
 	struct kref kref; /* ref count & hvcs_struct lifetime */
@@ -309,6 +309,7 @@ struct hvcs_struct {
 
 static LIST_HEAD(hvcs_structs);
 static DEFINE_SPINLOCK(hvcs_structs_lock);
+static DEFINE_MUTEX(hvcs_init_mutex);
 
 static void hvcs_unthrottle(struct tty_struct *tty);
 static void hvcs_throttle(struct tty_struct *tty);
@@ -340,6 +341,7 @@ static int __devinit hvcs_probe(struct vio_dev *dev,
 static int __devexit hvcs_remove(struct vio_dev *dev);
 static int __init hvcs_module_init(void);
 static void __exit hvcs_module_exit(void);
+static int __devinit hvcs_initialize(void);
 
 #define HVCS_SCHED_READ	0x00000001
 #define HVCS_QUICK_READ	0x00000002
@@ -762,7 +764,7 @@ static int __devinit hvcs_probe(
 	const struct vio_device_id *id)
 {
 	struct hvcs_struct *hvcsd;
-	int index;
+	int index, rc;
 	int retval;
 
 	if (!dev || !id) {
@@ -770,6 +772,13 @@ static int __devinit hvcs_probe(
 		return -EPERM;
 	}
 
+	/* Make sure we are properly initialized */
+	rc = hvcs_initialize();
+	if (rc) {
+		pr_err("HVCS: Failed to initialize core driver.\n");
+		return rc;
+	}
+
 	/* early to avoid cleanup on failure */
 	index = hvcs_get_index();
 	if (index < 0) {
@@ -1464,12 +1473,15 @@ static void hvcs_free_index_list(void)
 	hvcs_index_count = 0;
 }
 
-static int __init hvcs_module_init(void)
+static int __devinit hvcs_initialize(void)
 {
-	int rc;
-	int num_ttys_to_alloc;
+	int rc, num_ttys_to_alloc;
 
-	printk(KERN_INFO "Initializing %s\n", hvcs_driver_string);
+	mutex_lock(&hvcs_init_mutex);
+	if (hvcs_task) {
+		mutex_unlock(&hvcs_init_mutex);
+		return 0;
+	}
 
 	/* Has the user specified an overload with an insmod param? */
 	if (hvcs_parm_num_devs <= 0 ||
@@ -1528,35 +1540,13 @@ static int __init hvcs_module_init(void)
 
 	hvcs_task = kthread_run(khvcsd, NULL, "khvcsd");
 	if (IS_ERR(hvcs_task)) {
-		printk(KERN_ERR "HVCS: khvcsd creation failed.  Driver not loaded.\n");
+		printk(KERN_ERR "HVCS: khvcsd creation failed.\n");
 		rc = -EIO;
 		goto kthread_fail;
 	}
-
-	rc = vio_register_driver(&hvcs_vio_driver);
-	if (rc) {
-		printk(KERN_ERR "HVCS: can't register vio driver\n");
-		goto vio_fail;
-	}
-
-	/*
-	 * This needs to be done AFTER the vio_register_driver() call or else
-	 * the kobjects won't be initialized properly.
-	 */
-	rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
-	if (rc) {
-		printk(KERN_ERR "HVCS: sysfs attr create failed\n");
-		goto attr_fail;
-	}
-
-	printk(KERN_INFO "HVCS: driver module inserted.\n");
-
+	mutex_unlock(&hvcs_init_mutex);
 	return 0;
 
-attr_fail:
-	vio_unregister_driver(&hvcs_vio_driver);
-vio_fail:
-	kthread_stop(hvcs_task);
 kthread_fail:
 	kfree(hvcs_pi_buff);
 buff_alloc_fail:
@@ -1566,15 +1556,39 @@ register_fail:
 index_fail:
 	put_tty_driver(hvcs_tty_driver);
 	hvcs_tty_driver = NULL;
+	mutex_unlock(&hvcs_init_mutex);
 	return rc;
 }
 
+static int __init hvcs_module_init(void)
+{
+	int rc = vio_register_driver(&hvcs_vio_driver);
+	if (rc) {
+		printk(KERN_ERR "HVCS: can't register vio driver\n");
+		return rc;
+	}
+
+	pr_info("HVCS: Driver registered.\n");
+
+	/* This needs to be done AFTER the vio_register_driver() call or else
+	 * the kobjects won't be initialized properly.
+	 */
+	rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
+	if (rc)
+		pr_warning(KERN_ERR "HVCS: Failed to create rescan file (err %d)\n", rc);
+
+	return 0;
+}
+
 static void __exit hvcs_module_exit(void)
 {
 	/*
 	 * This driver receives hvcs_remove callbacks for each device upon
 	 * module removal.
 	 */
+	vio_unregister_driver(&hvcs_vio_driver);
+	if (!hvcs_task)
+		return;
 
 	/*
 	 * This synchronous operation  will wake the khvcsd kthread if it is
@@ -1589,8 +1603,6 @@ static void __exit hvcs_module_exit(void)
 
 	driver_remove_file(&hvcs_vio_driver.driver, &driver_attr_rescan);
 
-	vio_unregister_driver(&hvcs_vio_driver);
-
 	tty_unregister_driver(hvcs_tty_driver);
 
 	hvcs_free_index_list();
diff --git a/drivers/tty/hvc/hvsi.c b/drivers/tty/hvc/hvsi.c
index 67a75a5..8a8d637 100644
--- a/drivers/tty/hvc/hvsi.c
+++ b/drivers/tty/hvc/hvsi.c
@@ -1095,7 +1095,7 @@ static void hvsi_unthrottle(struct tty_struct *tty)
 	h_vio_signal(hp->vtermno, VIO_IRQ_ENABLE);
 }
 
-static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
+static int hvsi_tiocmget(struct tty_struct *tty)
 {
 	struct hvsi_struct *hp = tty->driver_data;
 
@@ -1103,8 +1103,8 @@ static int hvsi_tiocmget(struct tty_struct *tty, struct file *file)
 	return hp->mctrl;
 }
 
-static int hvsi_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
+static int hvsi_tiocmset(struct tty_struct *tty,
+				unsigned int set, unsigned int clear)
 {
 	struct hvsi_struct *hp = tty->driver_data;
 	unsigned long flags;
diff --git a/drivers/tty/ipwireless/Makefile b/drivers/tty/ipwireless/Makefile
new file mode 100644
index 0000000..db80873
--- /dev/null
+++ b/drivers/tty/ipwireless/Makefile
@@ -0,0 +1,10 @@
+#
+# drivers/char/pcmcia/ipwireless/Makefile
+#
+# Makefile for the IPWireless driver
+#
+
+obj-$(CONFIG_IPWIRELESS) += ipwireless.o
+
+ipwireless-y := hardware.o main.o network.o tty.o
+
diff --git a/drivers/tty/ipwireless/hardware.c b/drivers/tty/ipwireless/hardware.c
new file mode 100644
index 0000000..0aeb5a3
--- /dev/null
+++ b/drivers/tty/ipwireless/hardware.c
@@ -0,0 +1,1764 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "hardware.h"
+#include "setup_protocol.h"
+#include "network.h"
+#include "main.h"
+
+static void ipw_send_setup_packet(struct ipw_hardware *hw);
+static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
+					 unsigned int address,
+					 const unsigned char *data, int len,
+					 int is_last);
+static void ipwireless_setup_timer(unsigned long data);
+static void handle_received_CTRL_packet(struct ipw_hardware *hw,
+		unsigned int channel_idx, const unsigned char *data, int len);
+
+/*#define TIMING_DIAGNOSTICS*/
+
+#ifdef TIMING_DIAGNOSTICS
+
+static struct timing_stats {
+	unsigned long last_report_time;
+	unsigned long read_time;
+	unsigned long write_time;
+	unsigned long read_bytes;
+	unsigned long write_bytes;
+	unsigned long start_time;
+};
+
+static void start_timing(void)
+{
+	timing_stats.start_time = jiffies;
+}
+
+static void end_read_timing(unsigned length)
+{
+	timing_stats.read_time += (jiffies - start_time);
+	timing_stats.read_bytes += length + 2;
+	report_timing();
+}
+
+static void end_write_timing(unsigned length)
+{
+	timing_stats.write_time += (jiffies - start_time);
+	timing_stats.write_bytes += length + 2;
+	report_timing();
+}
+
+static void report_timing(void)
+{
+	unsigned long since = jiffies - timing_stats.last_report_time;
+
+	/* If it's been more than one second... */
+	if (since >= HZ) {
+		int first = (timing_stats.last_report_time == 0);
+
+		timing_stats.last_report_time = jiffies;
+		if (!first)
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n",
+			       jiffies_to_usecs(since),
+			       timing_stats.read_bytes,
+			       jiffies_to_usecs(timing_stats.read_time),
+			       timing_stats.write_bytes,
+			       jiffies_to_usecs(timing_stats.write_time));
+
+		timing_stats.read_time = 0;
+		timing_stats.write_time = 0;
+		timing_stats.read_bytes = 0;
+		timing_stats.write_bytes = 0;
+	}
+}
+#else
+static void start_timing(void) { }
+static void end_read_timing(unsigned length) { }
+static void end_write_timing(unsigned length) { }
+#endif
+
+/* Imported IPW definitions */
+
+#define LL_MTU_V1 318
+#define LL_MTU_V2 250
+#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2)
+
+#define PRIO_DATA  2
+#define PRIO_CTRL  1
+#define PRIO_SETUP 0
+
+/* Addresses */
+#define ADDR_SETUP_PROT 0
+
+/* Protocol ids */
+enum {
+	/* Identifier for the Com Data protocol */
+	TL_PROTOCOLID_COM_DATA = 0,
+
+	/* Identifier for the Com Control protocol */
+	TL_PROTOCOLID_COM_CTRL = 1,
+
+	/* Identifier for the Setup protocol */
+	TL_PROTOCOLID_SETUP = 2
+};
+
+/* Number of bytes in NL packet header (cannot do
+ * sizeof(nl_packet_header) since it's a bitfield) */
+#define NL_FIRST_PACKET_HEADER_SIZE        3
+
+/* Number of bytes in NL packet header (cannot do
+ * sizeof(nl_packet_header) since it's a bitfield) */
+#define NL_FOLLOWING_PACKET_HEADER_SIZE    1
+
+struct nl_first_packet_header {
+	unsigned char protocol:3;
+	unsigned char address:3;
+	unsigned char packet_rank:2;
+	unsigned char length_lsb;
+	unsigned char length_msb;
+};
+
+struct nl_packet_header {
+	unsigned char protocol:3;
+	unsigned char address:3;
+	unsigned char packet_rank:2;
+};
+
+/* Value of 'packet_rank' above */
+#define NL_INTERMEDIATE_PACKET    0x0
+#define NL_LAST_PACKET            0x1
+#define NL_FIRST_PACKET           0x2
+
+union nl_packet {
+	/* Network packet header of the first packet (a special case) */
+	struct nl_first_packet_header hdr_first;
+	/* Network packet header of the following packets (if any) */
+	struct nl_packet_header hdr;
+	/* Complete network packet (header + data) */
+	unsigned char rawpkt[LL_MTU_MAX];
+} __attribute__ ((__packed__));
+
+#define HW_VERSION_UNKNOWN -1
+#define HW_VERSION_1 1
+#define HW_VERSION_2 2
+
+/* IPW I/O ports */
+#define IOIER 0x00		/* Interrupt Enable Register */
+#define IOIR  0x02		/* Interrupt Source/ACK register */
+#define IODCR 0x04		/* Data Control Register */
+#define IODRR 0x06		/* Data Read Register */
+#define IODWR 0x08		/* Data Write Register */
+#define IOESR 0x0A		/* Embedded Driver Status Register */
+#define IORXR 0x0C		/* Rx Fifo Register (Host to Embedded) */
+#define IOTXR 0x0E		/* Tx Fifo Register (Embedded to Host) */
+
+/* I/O ports and bit definitions for version 1 of the hardware */
+
+/* IER bits*/
+#define IER_RXENABLED   0x1
+#define IER_TXENABLED   0x2
+
+/* ISR bits */
+#define IR_RXINTR       0x1
+#define IR_TXINTR       0x2
+
+/* DCR bits */
+#define DCR_RXDONE      0x1
+#define DCR_TXDONE      0x2
+#define DCR_RXRESET     0x4
+#define DCR_TXRESET     0x8
+
+/* I/O ports and bit definitions for version 2 of the hardware */
+
+struct MEMCCR {
+	unsigned short reg_config_option;	/* PCCOR: Configuration Option Register */
+	unsigned short reg_config_and_status;	/* PCCSR: Configuration and Status Register */
+	unsigned short reg_pin_replacement;	/* PCPRR: Pin Replacemant Register */
+	unsigned short reg_socket_and_copy;	/* PCSCR: Socket and Copy Register */
+	unsigned short reg_ext_status;		/* PCESR: Extendend Status Register */
+	unsigned short reg_io_base;		/* PCIOB: I/O Base Register */
+};
+
+struct MEMINFREG {
+	unsigned short memreg_tx_old;	/* TX Register (R/W) */
+	unsigned short pad1;
+	unsigned short memreg_rx_done;	/* RXDone Register (R/W) */
+	unsigned short pad2;
+	unsigned short memreg_rx;	/* RX Register (R/W) */
+	unsigned short pad3;
+	unsigned short memreg_pc_interrupt_ack;	/* PC intr Ack Register (W) */
+	unsigned short pad4;
+	unsigned long memreg_card_present;/* Mask for Host to check (R) for
+					   * CARD_PRESENT_VALUE */
+	unsigned short memreg_tx_new;	/* TX2 (new) Register (R/W) */
+};
+
+#define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
+
+#define MEMTX_TX                       0x0001
+#define MEMRX_RX                       0x0001
+#define MEMRX_RX_DONE                  0x0001
+#define MEMRX_PCINTACKK                0x0001
+
+#define NL_NUM_OF_PRIORITIES       3
+#define NL_NUM_OF_PROTOCOLS        3
+#define NL_NUM_OF_ADDRESSES        NO_OF_IPW_CHANNELS
+
+struct ipw_hardware {
+	unsigned int base_port;
+	short hw_version;
+	unsigned short ll_mtu;
+	spinlock_t lock;
+
+	int initializing;
+	int init_loops;
+	struct timer_list setup_timer;
+
+	/* Flag if hw is ready to send next packet */
+	int tx_ready;
+	/* Count of pending packets to be sent */
+	int tx_queued;
+	struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
+
+	int rx_bytes_queued;
+	struct list_head rx_queue;
+	/* Pool of rx_packet structures that are not currently used. */
+	struct list_head rx_pool;
+	int rx_pool_size;
+	/* True if reception of data is blocked while userspace processes it. */
+	int blocking_rx;
+	/* True if there is RX data ready on the hardware. */
+	int rx_ready;
+	unsigned short last_memtx_serial;
+	/*
+	 * Newer versions of the V2 card firmware send serial numbers in the
+	 * MemTX register. 'serial_number_detected' is set true when we detect
+	 * a non-zero serial number (indicating the new firmware).  Thereafter,
+	 * the driver can safely ignore the Timer Recovery re-sends to avoid
+	 * out-of-sync problems.
+	 */
+	int serial_number_detected;
+	struct work_struct work_rx;
+
+	/* True if we are to send the set-up data to the hardware. */
+	int to_setup;
+
+	/* Card has been removed */
+	int removed;
+	/* Saved irq value when we disable the interrupt. */
+	int irq;
+	/* True if this driver is shutting down. */
+	int shutting_down;
+	/* Modem control lines */
+	unsigned int control_lines[NL_NUM_OF_ADDRESSES];
+	struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES];
+
+	struct tasklet_struct tasklet;
+
+	/* The handle for the network layer, for the sending of events to it. */
+	struct ipw_network *network;
+	struct MEMINFREG __iomem *memory_info_regs;
+	struct MEMCCR __iomem *memregs_CCR;
+	void (*reboot_callback) (void *data);
+	void *reboot_callback_data;
+
+	unsigned short __iomem *memreg_tx;
+};
+
+/*
+ * Packet info structure for tx packets.
+ * Note: not all the fields defined here are required for all protocols
+ */
+struct ipw_tx_packet {
+	struct list_head queue;
+	/* channel idx + 1 */
+	unsigned char dest_addr;
+	/* SETUP, CTRL or DATA */
+	unsigned char protocol;
+	/* Length of data block, which starts at the end of this structure */
+	unsigned short length;
+	/* Sending state */
+	/* Offset of where we've sent up to so far */
+	unsigned long offset;
+	/* Count of packet fragments, starting at 0 */
+	int fragment_count;
+
+	/* Called after packet is sent and before is freed */
+	void (*packet_callback) (void *cb_data, unsigned int packet_length);
+	void *callback_data;
+};
+
+/* Signals from DTE */
+#define COMCTRL_RTS	0
+#define COMCTRL_DTR	1
+
+/* Signals from DCE */
+#define COMCTRL_CTS	2
+#define COMCTRL_DCD	3
+#define COMCTRL_DSR	4
+#define COMCTRL_RI	5
+
+struct ipw_control_packet_body {
+	/* DTE signal or DCE signal */
+	unsigned char sig_no;
+	/* 0: set signal, 1: clear signal */
+	unsigned char value;
+} __attribute__ ((__packed__));
+
+struct ipw_control_packet {
+	struct ipw_tx_packet header;
+	struct ipw_control_packet_body body;
+};
+
+struct ipw_rx_packet {
+	struct list_head queue;
+	unsigned int capacity;
+	unsigned int length;
+	unsigned int protocol;
+	unsigned int channel_idx;
+};
+
+static char *data_type(const unsigned char *buf, unsigned length)
+{
+	struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
+
+	if (length == 0)
+		return "     ";
+
+	if (hdr->packet_rank & NL_FIRST_PACKET) {
+		switch (hdr->protocol) {
+		case TL_PROTOCOLID_COM_DATA:	return "DATA ";
+		case TL_PROTOCOLID_COM_CTRL:	return "CTRL ";
+		case TL_PROTOCOLID_SETUP:	return "SETUP";
+		default: return "???? ";
+		}
+	} else
+		return "     ";
+}
+
+#define DUMP_MAX_BYTES 64
+
+static void dump_data_bytes(const char *type, const unsigned char *data,
+			    unsigned length)
+{
+	char prefix[56];
+
+	sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ",
+			type, data_type(data, length));
+	print_hex_dump_bytes(prefix, 0, (void *)data,
+			length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
+}
+
+static void swap_packet_bitfield_to_le(unsigned char *data)
+{
+#ifdef __BIG_ENDIAN_BITFIELD
+	unsigned char tmp = *data, ret = 0;
+
+	/*
+	 * transform bits from aa.bbb.ccc to ccc.bbb.aa
+	 */
+	ret |= tmp & 0xc0 >> 6;
+	ret |= tmp & 0x38 >> 1;
+	ret |= tmp & 0x07 << 5;
+	*data = ret & 0xff;
+#endif
+}
+
+static void swap_packet_bitfield_from_le(unsigned char *data)
+{
+#ifdef __BIG_ENDIAN_BITFIELD
+	unsigned char tmp = *data, ret = 0;
+
+	/*
+	 * transform bits from ccc.bbb.aa to aa.bbb.ccc
+	 */
+	ret |= tmp & 0xe0 >> 5;
+	ret |= tmp & 0x1c << 1;
+	ret |= tmp & 0x03 << 6;
+	*data = ret & 0xff;
+#endif
+}
+
+static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data,
+			    unsigned length)
+{
+	unsigned i;
+	unsigned long flags;
+
+	start_timing();
+	BUG_ON(length > hw->ll_mtu);
+
+	if (ipwireless_debug)
+		dump_data_bytes("send", data, length);
+
+	spin_lock_irqsave(&hw->lock, flags);
+
+	hw->tx_ready = 0;
+	swap_packet_bitfield_to_le(data);
+
+	if (hw->hw_version == HW_VERSION_1) {
+		outw((unsigned short) length, hw->base_port + IODWR);
+
+		for (i = 0; i < length; i += 2) {
+			unsigned short d = data[i];
+			__le16 raw_data;
+
+			if (i + 1 < length)
+				d |= data[i + 1] << 8;
+			raw_data = cpu_to_le16(d);
+			outw(raw_data, hw->base_port + IODWR);
+		}
+
+		outw(DCR_TXDONE, hw->base_port + IODCR);
+	} else if (hw->hw_version == HW_VERSION_2) {
+		outw((unsigned short) length, hw->base_port);
+
+		for (i = 0; i < length; i += 2) {
+			unsigned short d = data[i];
+			__le16 raw_data;
+
+			if (i + 1 < length)
+				d |= data[i + 1] << 8;
+			raw_data = cpu_to_le16(d);
+			outw(raw_data, hw->base_port);
+		}
+		while ((i & 3) != 2) {
+			outw((unsigned short) 0xDEAD, hw->base_port);
+			i += 2;
+		}
+		writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
+	}
+
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	end_write_timing(length);
+}
+
+static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
+{
+	unsigned short fragment_data_len;
+	unsigned short data_left = packet->length - packet->offset;
+	unsigned short header_size;
+	union nl_packet pkt;
+
+	header_size =
+	    (packet->fragment_count == 0)
+	    ? NL_FIRST_PACKET_HEADER_SIZE
+	    : NL_FOLLOWING_PACKET_HEADER_SIZE;
+	fragment_data_len = hw->ll_mtu - header_size;
+	if (data_left < fragment_data_len)
+		fragment_data_len = data_left;
+
+	/*
+	 * hdr_first is now in machine bitfield order, which will be swapped
+	 * to le just before it goes to hw
+	 */
+	pkt.hdr_first.protocol = packet->protocol;
+	pkt.hdr_first.address = packet->dest_addr;
+	pkt.hdr_first.packet_rank = 0;
+
+	/* First packet? */
+	if (packet->fragment_count == 0) {
+		pkt.hdr_first.packet_rank |= NL_FIRST_PACKET;
+		pkt.hdr_first.length_lsb = (unsigned char) packet->length;
+		pkt.hdr_first.length_msb =
+			(unsigned char) (packet->length >> 8);
+	}
+
+	memcpy(pkt.rawpkt + header_size,
+	       ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) +
+	       packet->offset, fragment_data_len);
+	packet->offset += fragment_data_len;
+	packet->fragment_count++;
+
+	/* Last packet? (May also be first packet.) */
+	if (packet->offset == packet->length)
+		pkt.hdr_first.packet_rank |= NL_LAST_PACKET;
+	do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len);
+
+	/* If this packet has unsent data, then re-queue it. */
+	if (packet->offset < packet->length) {
+		/*
+		 * Re-queue it at the head of the highest priority queue so
+		 * it goes before all other packets
+		 */
+		unsigned long flags;
+
+		spin_lock_irqsave(&hw->lock, flags);
+		list_add(&packet->queue, &hw->tx_queue[0]);
+		hw->tx_queued++;
+		spin_unlock_irqrestore(&hw->lock, flags);
+	} else {
+		if (packet->packet_callback)
+			packet->packet_callback(packet->callback_data,
+					packet->length);
+		kfree(packet);
+	}
+}
+
+static void ipw_setup_hardware(struct ipw_hardware *hw)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	if (hw->hw_version == HW_VERSION_1) {
+		/* Reset RX FIFO */
+		outw(DCR_RXRESET, hw->base_port + IODCR);
+		/* SB: Reset TX FIFO */
+		outw(DCR_TXRESET, hw->base_port + IODCR);
+
+		/* Enable TX and RX interrupts. */
+		outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER);
+	} else {
+		/*
+		 * Set INTRACK bit (bit 0), which means we must explicitly
+		 * acknowledge interrupts by clearing bit 2 of reg_config_and_status.
+		 */
+		unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
+
+		csr |= 1;
+		writew(csr, &hw->memregs_CCR->reg_config_and_status);
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+/*
+ * If 'packet' is NULL, then this function allocates a new packet, setting its
+ * length to 0 and ensuring it has the specified minimum amount of free space.
+ *
+ * If 'packet' is not NULL, then this function enlarges it if it doesn't
+ * have the specified minimum amount of free space.
+ *
+ */
+static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
+					   struct ipw_rx_packet *packet,
+					   int minimum_free_space)
+{
+
+	if (!packet) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&hw->lock, flags);
+		if (!list_empty(&hw->rx_pool)) {
+			packet = list_first_entry(&hw->rx_pool,
+					struct ipw_rx_packet, queue);
+			hw->rx_pool_size--;
+			spin_unlock_irqrestore(&hw->lock, flags);
+			list_del(&packet->queue);
+		} else {
+			const int min_capacity =
+				ipwireless_ppp_mru(hw->network) + 2;
+			int new_capacity;
+
+			spin_unlock_irqrestore(&hw->lock, flags);
+			new_capacity =
+				(minimum_free_space > min_capacity
+				 ? minimum_free_space
+				 : min_capacity);
+			packet = kmalloc(sizeof(struct ipw_rx_packet)
+					+ new_capacity, GFP_ATOMIC);
+			if (!packet)
+				return NULL;
+			packet->capacity = new_capacity;
+		}
+		packet->length = 0;
+	}
+
+	if (packet->length + minimum_free_space > packet->capacity) {
+		struct ipw_rx_packet *old_packet = packet;
+
+		packet = kmalloc(sizeof(struct ipw_rx_packet) +
+				old_packet->length + minimum_free_space,
+				GFP_ATOMIC);
+		if (!packet) {
+			kfree(old_packet);
+			return NULL;
+		}
+		memcpy(packet, old_packet,
+				sizeof(struct ipw_rx_packet)
+					+ old_packet->length);
+		packet->capacity = old_packet->length + minimum_free_space;
+		kfree(old_packet);
+	}
+
+	return packet;
+}
+
+static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet)
+{
+	if (hw->rx_pool_size > 6)
+		kfree(packet);
+	else {
+		hw->rx_pool_size++;
+		list_add(&packet->queue, &hw->rx_pool);
+	}
+}
+
+static void queue_received_packet(struct ipw_hardware *hw,
+				  unsigned int protocol,
+				  unsigned int address,
+				  const unsigned char *data, int length,
+				  int is_last)
+{
+	unsigned int channel_idx = address - 1;
+	struct ipw_rx_packet *packet = NULL;
+	unsigned long flags;
+
+	/* Discard packet if channel index is out of range. */
+	if (channel_idx >= NL_NUM_OF_ADDRESSES) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": data packet has bad address %u\n", address);
+		return;
+	}
+
+	/*
+	 * ->packet_assembler is safe to touch unlocked, this is the only place
+	 */
+	if (protocol == TL_PROTOCOLID_COM_DATA) {
+		struct ipw_rx_packet **assem =
+			&hw->packet_assembler[channel_idx];
+
+		/*
+		 * Create a new packet, or assembler already contains one
+		 * enlarge it by 'length' bytes.
+		 */
+		(*assem) = pool_allocate(hw, *assem, length);
+		if (!(*assem)) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+				": no memory for incomming data packet, dropped!\n");
+			return;
+		}
+		(*assem)->protocol = protocol;
+		(*assem)->channel_idx = channel_idx;
+
+		/* Append this packet data onto existing data. */
+		memcpy((unsigned char *)(*assem) +
+			       sizeof(struct ipw_rx_packet)
+				+ (*assem)->length, data, length);
+		(*assem)->length += length;
+		if (is_last) {
+			packet = *assem;
+			*assem = NULL;
+			/* Count queued DATA bytes only */
+			spin_lock_irqsave(&hw->lock, flags);
+			hw->rx_bytes_queued += packet->length;
+			spin_unlock_irqrestore(&hw->lock, flags);
+		}
+	} else {
+		/* If it's a CTRL packet, don't assemble, just queue it. */
+		packet = pool_allocate(hw, NULL, length);
+		if (!packet) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+				": no memory for incomming ctrl packet, dropped!\n");
+			return;
+		}
+		packet->protocol = protocol;
+		packet->channel_idx = channel_idx;
+		memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet),
+				data, length);
+		packet->length = length;
+	}
+
+	/*
+	 * If this is the last packet, then send the assembled packet on to the
+	 * network layer.
+	 */
+	if (packet) {
+		spin_lock_irqsave(&hw->lock, flags);
+		list_add_tail(&packet->queue, &hw->rx_queue);
+		/* Block reception of incoming packets if queue is full. */
+		hw->blocking_rx =
+			(hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE);
+
+		spin_unlock_irqrestore(&hw->lock, flags);
+		schedule_work(&hw->work_rx);
+	}
+}
+
+/*
+ * Workqueue callback
+ */
+static void ipw_receive_data_work(struct work_struct *work_rx)
+{
+	struct ipw_hardware *hw =
+	    container_of(work_rx, struct ipw_hardware, work_rx);
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	while (!list_empty(&hw->rx_queue)) {
+		struct ipw_rx_packet *packet =
+			list_first_entry(&hw->rx_queue,
+					struct ipw_rx_packet, queue);
+
+		if (hw->shutting_down)
+			break;
+		list_del(&packet->queue);
+
+		/*
+		 * Note: ipwireless_network_packet_received must be called in a
+		 * process context (i.e. via schedule_work) because the tty
+		 * output code can sleep in the tty_flip_buffer_push call.
+		 */
+		if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
+			if (hw->network != NULL) {
+				/* If the network hasn't been disconnected. */
+				spin_unlock_irqrestore(&hw->lock, flags);
+				/*
+				 * This must run unlocked due to tty processing
+				 * and mutex locking
+				 */
+				ipwireless_network_packet_received(
+						hw->network,
+						packet->channel_idx,
+						(unsigned char *)packet
+						+ sizeof(struct ipw_rx_packet),
+						packet->length);
+				spin_lock_irqsave(&hw->lock, flags);
+			}
+			/* Count queued DATA bytes only */
+			hw->rx_bytes_queued -= packet->length;
+		} else {
+			/*
+			 * This is safe to be called locked, callchain does
+			 * not block
+			 */
+			handle_received_CTRL_packet(hw, packet->channel_idx,
+					(unsigned char *)packet
+					+ sizeof(struct ipw_rx_packet),
+					packet->length);
+		}
+		pool_free(hw, packet);
+		/*
+		 * Unblock reception of incoming packets if queue is no longer
+		 * full.
+		 */
+		hw->blocking_rx =
+			hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
+		if (hw->shutting_down)
+			break;
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+static void handle_received_CTRL_packet(struct ipw_hardware *hw,
+					unsigned int channel_idx,
+					const unsigned char *data, int len)
+{
+	const struct ipw_control_packet_body *body =
+		(const struct ipw_control_packet_body *) data;
+	unsigned int changed_mask;
+
+	if (len != sizeof(struct ipw_control_packet_body)) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": control packet was %d bytes - wrong size!\n",
+		       len);
+		return;
+	}
+
+	switch (body->sig_no) {
+	case COMCTRL_CTS:
+		changed_mask = IPW_CONTROL_LINE_CTS;
+		break;
+	case COMCTRL_DCD:
+		changed_mask = IPW_CONTROL_LINE_DCD;
+		break;
+	case COMCTRL_DSR:
+		changed_mask = IPW_CONTROL_LINE_DSR;
+		break;
+	case COMCTRL_RI:
+		changed_mask = IPW_CONTROL_LINE_RI;
+		break;
+	default:
+		changed_mask = 0;
+	}
+
+	if (changed_mask != 0) {
+		if (body->value)
+			hw->control_lines[channel_idx] |= changed_mask;
+		else
+			hw->control_lines[channel_idx] &= ~changed_mask;
+		if (hw->network)
+			ipwireless_network_notify_control_line_change(
+					hw->network,
+					channel_idx,
+					hw->control_lines[channel_idx],
+					changed_mask);
+	}
+}
+
+static void handle_received_packet(struct ipw_hardware *hw,
+				   const union nl_packet *packet,
+				   unsigned short len)
+{
+	unsigned int protocol = packet->hdr.protocol;
+	unsigned int address = packet->hdr.address;
+	unsigned int header_length;
+	const unsigned char *data;
+	unsigned int data_len;
+	int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
+
+	if (packet->hdr.packet_rank & NL_FIRST_PACKET)
+		header_length = NL_FIRST_PACKET_HEADER_SIZE;
+	else
+		header_length = NL_FOLLOWING_PACKET_HEADER_SIZE;
+
+	data = packet->rawpkt + header_length;
+	data_len = len - header_length;
+	switch (protocol) {
+	case TL_PROTOCOLID_COM_DATA:
+	case TL_PROTOCOLID_COM_CTRL:
+		queue_received_packet(hw, protocol, address, data, data_len,
+				is_last);
+		break;
+	case TL_PROTOCOLID_SETUP:
+		handle_received_SETUP_packet(hw, address, data, data_len,
+				is_last);
+		break;
+	}
+}
+
+static void acknowledge_data_read(struct ipw_hardware *hw)
+{
+	if (hw->hw_version == HW_VERSION_1)
+		outw(DCR_RXDONE, hw->base_port + IODCR);
+	else
+		writew(MEMRX_PCINTACKK,
+				&hw->memory_info_regs->memreg_pc_interrupt_ack);
+}
+
+/*
+ * Retrieve a packet from the IPW hardware.
+ */
+static void do_receive_packet(struct ipw_hardware *hw)
+{
+	unsigned len;
+	unsigned i;
+	unsigned char pkt[LL_MTU_MAX];
+
+	start_timing();
+
+	if (hw->hw_version == HW_VERSION_1) {
+		len = inw(hw->base_port + IODRR);
+		if (len > hw->ll_mtu) {
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": received a packet of %u bytes - longer than the MTU!\n", len);
+			outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
+			return;
+		}
+
+		for (i = 0; i < len; i += 2) {
+			__le16 raw_data = inw(hw->base_port + IODRR);
+			unsigned short data = le16_to_cpu(raw_data);
+
+			pkt[i] = (unsigned char) data;
+			pkt[i + 1] = (unsigned char) (data >> 8);
+		}
+	} else {
+		len = inw(hw->base_port);
+		if (len > hw->ll_mtu) {
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": received a packet of %u bytes - longer than the MTU!\n", len);
+			writew(MEMRX_PCINTACKK,
+				&hw->memory_info_regs->memreg_pc_interrupt_ack);
+			return;
+		}
+
+		for (i = 0; i < len; i += 2) {
+			__le16 raw_data = inw(hw->base_port);
+			unsigned short data = le16_to_cpu(raw_data);
+
+			pkt[i] = (unsigned char) data;
+			pkt[i + 1] = (unsigned char) (data >> 8);
+		}
+
+		while ((i & 3) != 2) {
+			inw(hw->base_port);
+			i += 2;
+		}
+	}
+
+	acknowledge_data_read(hw);
+
+	swap_packet_bitfield_from_le(pkt);
+
+	if (ipwireless_debug)
+		dump_data_bytes("recv", pkt, len);
+
+	handle_received_packet(hw, (union nl_packet *) pkt, len);
+
+	end_read_timing(len);
+}
+
+static int get_current_packet_priority(struct ipw_hardware *hw)
+{
+	/*
+	 * If we're initializing, don't send anything of higher priority than
+	 * PRIO_SETUP.  The network layer therefore need not care about
+	 * hardware initialization - any of its stuff will simply be queued
+	 * until setup is complete.
+	 */
+	return (hw->to_setup || hw->initializing
+			? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES);
+}
+
+/*
+ * return 1 if something has been received from hw
+ */
+static int get_packets_from_hw(struct ipw_hardware *hw)
+{
+	int received = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	while (hw->rx_ready && !hw->blocking_rx) {
+		received = 1;
+		hw->rx_ready--;
+		spin_unlock_irqrestore(&hw->lock, flags);
+
+		do_receive_packet(hw);
+
+		spin_lock_irqsave(&hw->lock, flags);
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	return received;
+}
+
+/*
+ * Send pending packet up to given priority, prioritize SETUP data until
+ * hardware is fully setup.
+ *
+ * return 1 if more packets can be sent
+ */
+static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
+{
+	int more_to_send = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	if (hw->tx_queued && hw->tx_ready) {
+		int priority;
+		struct ipw_tx_packet *packet = NULL;
+
+		/* Pick a packet */
+		for (priority = 0; priority < priority_limit; priority++) {
+			if (!list_empty(&hw->tx_queue[priority])) {
+				packet = list_first_entry(
+						&hw->tx_queue[priority],
+						struct ipw_tx_packet,
+						queue);
+
+				hw->tx_queued--;
+				list_del(&packet->queue);
+
+				break;
+			}
+		}
+		if (!packet) {
+			hw->tx_queued = 0;
+			spin_unlock_irqrestore(&hw->lock, flags);
+			return 0;
+		}
+
+		spin_unlock_irqrestore(&hw->lock, flags);
+
+		/* Send */
+		do_send_packet(hw, packet);
+
+		/* Check if more to send */
+		spin_lock_irqsave(&hw->lock, flags);
+		for (priority = 0; priority < priority_limit; priority++)
+			if (!list_empty(&hw->tx_queue[priority])) {
+				more_to_send = 1;
+				break;
+			}
+
+		if (!more_to_send)
+			hw->tx_queued = 0;
+	}
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	return more_to_send;
+}
+
+/*
+ * Send and receive all queued packets.
+ */
+static void ipwireless_do_tasklet(unsigned long hw_)
+{
+	struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	if (hw->shutting_down) {
+		spin_unlock_irqrestore(&hw->lock, flags);
+		return;
+	}
+
+	if (hw->to_setup == 1) {
+		/*
+		 * Initial setup data sent to hardware
+		 */
+		hw->to_setup = 2;
+		spin_unlock_irqrestore(&hw->lock, flags);
+
+		ipw_setup_hardware(hw);
+		ipw_send_setup_packet(hw);
+
+		send_pending_packet(hw, PRIO_SETUP + 1);
+		get_packets_from_hw(hw);
+	} else {
+		int priority_limit = get_current_packet_priority(hw);
+		int again;
+
+		spin_unlock_irqrestore(&hw->lock, flags);
+
+		do {
+			again = send_pending_packet(hw, priority_limit);
+			again |= get_packets_from_hw(hw);
+		} while (again);
+	}
+}
+
+/*
+ * return true if the card is physically present.
+ */
+static int is_card_present(struct ipw_hardware *hw)
+{
+	if (hw->hw_version == HW_VERSION_1)
+		return inw(hw->base_port + IOIR) != 0xFFFF;
+	else
+		return readl(&hw->memory_info_regs->memreg_card_present) ==
+		    CARD_PRESENT_VALUE;
+}
+
+static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
+						  struct ipw_hardware *hw)
+{
+	unsigned short irqn;
+
+	irqn = inw(hw->base_port + IOIR);
+
+	/* Check if card is present */
+	if (irqn == 0xFFFF)
+		return IRQ_NONE;
+	else if (irqn != 0) {
+		unsigned short ack = 0;
+		unsigned long flags;
+
+		/* Transmit complete. */
+		if (irqn & IR_TXINTR) {
+			ack |= IR_TXINTR;
+			spin_lock_irqsave(&hw->lock, flags);
+			hw->tx_ready = 1;
+			spin_unlock_irqrestore(&hw->lock, flags);
+		}
+		/* Received data */
+		if (irqn & IR_RXINTR) {
+			ack |= IR_RXINTR;
+			spin_lock_irqsave(&hw->lock, flags);
+			hw->rx_ready++;
+			spin_unlock_irqrestore(&hw->lock, flags);
+		}
+		if (ack != 0) {
+			outw(ack, hw->base_port + IOIR);
+			tasklet_schedule(&hw->tasklet);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw)
+{
+	unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
+
+	csr &= 0xfffd;
+	writew(csr, &hw->memregs_CCR->reg_config_and_status);
+}
+
+static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
+						     struct ipw_hardware *hw)
+{
+	int tx = 0;
+	int rx = 0;
+	int rx_repeat = 0;
+	int try_mem_tx_old;
+	unsigned long flags;
+
+	do {
+
+	unsigned short memtx = readw(hw->memreg_tx);
+	unsigned short memtx_serial;
+	unsigned short memrxdone =
+		readw(&hw->memory_info_regs->memreg_rx_done);
+
+	try_mem_tx_old = 0;
+
+	/* check whether the interrupt was generated by ipwireless card */
+	if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) {
+
+		/* check if the card uses memreg_tx_old register */
+		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
+			memtx = readw(&hw->memory_info_regs->memreg_tx_old);
+			if (memtx & MEMTX_TX) {
+				printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+					": Using memreg_tx_old\n");
+				hw->memreg_tx =
+					&hw->memory_info_regs->memreg_tx_old;
+			} else {
+				return IRQ_NONE;
+			}
+		} else
+			return IRQ_NONE;
+	}
+
+	/*
+	 * See if the card is physically present. Note that while it is
+	 * powering up, it appears not to be present.
+	 */
+	if (!is_card_present(hw)) {
+		acknowledge_pcmcia_interrupt(hw);
+		return IRQ_HANDLED;
+	}
+
+	memtx_serial = memtx & (unsigned short) 0xff00;
+	if (memtx & MEMTX_TX) {
+		writew(memtx_serial, hw->memreg_tx);
+
+		if (hw->serial_number_detected) {
+			if (memtx_serial != hw->last_memtx_serial) {
+				hw->last_memtx_serial = memtx_serial;
+				spin_lock_irqsave(&hw->lock, flags);
+				hw->rx_ready++;
+				spin_unlock_irqrestore(&hw->lock, flags);
+				rx = 1;
+			} else
+				/* Ignore 'Timer Recovery' duplicates. */
+				rx_repeat = 1;
+		} else {
+			/*
+			 * If a non-zero serial number is seen, then enable
+			 * serial number checking.
+			 */
+			if (memtx_serial != 0) {
+				hw->serial_number_detected = 1;
+				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+					": memreg_tx serial num detected\n");
+
+				spin_lock_irqsave(&hw->lock, flags);
+				hw->rx_ready++;
+				spin_unlock_irqrestore(&hw->lock, flags);
+			}
+			rx = 1;
+		}
+	}
+	if (memrxdone & MEMRX_RX_DONE) {
+		writew(0, &hw->memory_info_regs->memreg_rx_done);
+		spin_lock_irqsave(&hw->lock, flags);
+		hw->tx_ready = 1;
+		spin_unlock_irqrestore(&hw->lock, flags);
+		tx = 1;
+	}
+	if (tx)
+		writew(MEMRX_PCINTACKK,
+				&hw->memory_info_regs->memreg_pc_interrupt_ack);
+
+	acknowledge_pcmcia_interrupt(hw);
+
+	if (tx || rx)
+		tasklet_schedule(&hw->tasklet);
+	else if (!rx_repeat) {
+		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
+			if (hw->serial_number_detected)
+				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
+					": spurious interrupt - new_tx mode\n");
+			else {
+				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
+					": no valid memreg_tx value - switching to the old memreg_tx\n");
+				hw->memreg_tx =
+					&hw->memory_info_regs->memreg_tx_old;
+				try_mem_tx_old = 1;
+			}
+		} else
+			printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
+					": spurious interrupt - old_tx mode\n");
+	}
+
+	} while (try_mem_tx_old == 1);
+
+	return IRQ_HANDLED;
+}
+
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id)
+{
+	struct ipw_dev *ipw = dev_id;
+
+	if (ipw->hardware->hw_version == HW_VERSION_1)
+		return ipwireless_handle_v1_interrupt(irq, ipw->hardware);
+	else
+		return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware);
+}
+
+static void flush_packets_to_hw(struct ipw_hardware *hw)
+{
+	int priority_limit;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	priority_limit = get_current_packet_priority(hw);
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	while (send_pending_packet(hw, priority_limit));
+}
+
+static void send_packet(struct ipw_hardware *hw, int priority,
+			struct ipw_tx_packet *packet)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	list_add_tail(&packet->queue, &hw->tx_queue[priority]);
+	hw->tx_queued++;
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	flush_packets_to_hw(hw);
+}
+
+/* Create data packet, non-atomic allocation */
+static void *alloc_data_packet(int data_size,
+				unsigned char dest_addr,
+				unsigned char protocol)
+{
+	struct ipw_tx_packet *packet = kzalloc(
+			sizeof(struct ipw_tx_packet) + data_size,
+			GFP_ATOMIC);
+
+	if (!packet)
+		return NULL;
+
+	INIT_LIST_HEAD(&packet->queue);
+	packet->dest_addr = dest_addr;
+	packet->protocol = protocol;
+	packet->length = data_size;
+
+	return packet;
+}
+
+static void *alloc_ctrl_packet(int header_size,
+			       unsigned char dest_addr,
+			       unsigned char protocol,
+			       unsigned char sig_no)
+{
+	/*
+	 * sig_no is located right after ipw_tx_packet struct in every
+	 * CTRL or SETUP packets, we can use ipw_control_packet as a
+	 * common struct
+	 */
+	struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC);
+
+	if (!packet)
+		return NULL;
+
+	INIT_LIST_HEAD(&packet->header.queue);
+	packet->header.dest_addr = dest_addr;
+	packet->header.protocol = protocol;
+	packet->header.length = header_size - sizeof(struct ipw_tx_packet);
+	packet->body.sig_no = sig_no;
+
+	return packet;
+}
+
+int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
+			    const unsigned char *data, unsigned int length,
+			    void (*callback) (void *cb, unsigned int length),
+			    void *callback_data)
+{
+	struct ipw_tx_packet *packet;
+
+	packet = alloc_data_packet(length, (channel_idx + 1),
+			TL_PROTOCOLID_COM_DATA);
+	if (!packet)
+		return -ENOMEM;
+	packet->packet_callback = callback;
+	packet->callback_data = callback_data;
+	memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data,
+			length);
+
+	send_packet(hw, PRIO_DATA, packet);
+	return 0;
+}
+
+static int set_control_line(struct ipw_hardware *hw, int prio,
+			   unsigned int channel_idx, int line, int state)
+{
+	struct ipw_control_packet *packet;
+	int protocolid = TL_PROTOCOLID_COM_CTRL;
+
+	if (prio == PRIO_SETUP)
+		protocolid = TL_PROTOCOLID_SETUP;
+
+	packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
+			(channel_idx + 1), protocolid, line);
+	if (!packet)
+		return -ENOMEM;
+	packet->header.length = sizeof(struct ipw_control_packet_body);
+	packet->body.value = (state == 0 ? 0 : 1);
+	send_packet(hw, prio, &packet->header);
+	return 0;
+}
+
+
+static int set_DTR(struct ipw_hardware *hw, int priority,
+		   unsigned int channel_idx, int state)
+{
+	if (state != 0)
+		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR;
+	else
+		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR;
+
+	return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state);
+}
+
+static int set_RTS(struct ipw_hardware *hw, int priority,
+		   unsigned int channel_idx, int state)
+{
+	if (state != 0)
+		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS;
+	else
+		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS;
+
+	return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state);
+}
+
+int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
+		       int state)
+{
+	return set_DTR(hw, PRIO_CTRL, channel_idx, state);
+}
+
+int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
+		       int state)
+{
+	return set_RTS(hw, PRIO_CTRL, channel_idx, state);
+}
+
+struct ipw_setup_get_version_query_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_get_version_qry body;
+};
+
+struct ipw_setup_config_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_config_msg body;
+};
+
+struct ipw_setup_config_done_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_config_done_msg body;
+};
+
+struct ipw_setup_open_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_open_msg body;
+};
+
+struct ipw_setup_info_packet {
+	struct ipw_tx_packet header;
+	struct tl_setup_info_msg body;
+};
+
+struct ipw_setup_reboot_msg_ack {
+	struct ipw_tx_packet header;
+	struct TlSetupRebootMsgAck body;
+};
+
+/* This handles the actual initialization of the card */
+static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
+{
+	struct ipw_setup_config_packet *config_packet;
+	struct ipw_setup_config_done_packet *config_done_packet;
+	struct ipw_setup_open_packet *open_packet;
+	struct ipw_setup_info_packet *info_packet;
+	int port;
+	unsigned int channel_idx;
+
+	/* generate config packet */
+	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
+		config_packet = alloc_ctrl_packet(
+				sizeof(struct ipw_setup_config_packet),
+				ADDR_SETUP_PROT,
+				TL_PROTOCOLID_SETUP,
+				TL_SETUP_SIGNO_CONFIG_MSG);
+		if (!config_packet)
+			goto exit_nomem;
+		config_packet->header.length = sizeof(struct tl_setup_config_msg);
+		config_packet->body.port_no = port;
+		config_packet->body.prio_data = PRIO_DATA;
+		config_packet->body.prio_ctrl = PRIO_CTRL;
+		send_packet(hw, PRIO_SETUP, &config_packet->header);
+	}
+	config_done_packet = alloc_ctrl_packet(
+			sizeof(struct ipw_setup_config_done_packet),
+			ADDR_SETUP_PROT,
+			TL_PROTOCOLID_SETUP,
+			TL_SETUP_SIGNO_CONFIG_DONE_MSG);
+	if (!config_done_packet)
+		goto exit_nomem;
+	config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg);
+	send_packet(hw, PRIO_SETUP, &config_done_packet->header);
+
+	/* generate open packet */
+	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
+		open_packet = alloc_ctrl_packet(
+				sizeof(struct ipw_setup_open_packet),
+				ADDR_SETUP_PROT,
+				TL_PROTOCOLID_SETUP,
+				TL_SETUP_SIGNO_OPEN_MSG);
+		if (!open_packet)
+			goto exit_nomem;
+		open_packet->header.length = sizeof(struct tl_setup_open_msg);
+		open_packet->body.port_no = port;
+		send_packet(hw, PRIO_SETUP, &open_packet->header);
+	}
+	for (channel_idx = 0;
+			channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) {
+		int ret;
+
+		ret = set_DTR(hw, PRIO_SETUP, channel_idx,
+			(hw->control_lines[channel_idx] &
+			 IPW_CONTROL_LINE_DTR) != 0);
+		if (ret) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+					": error setting DTR (%d)\n", ret);
+			return;
+		}
+
+		set_RTS(hw, PRIO_SETUP, channel_idx,
+			(hw->control_lines [channel_idx] &
+			 IPW_CONTROL_LINE_RTS) != 0);
+		if (ret) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+					": error setting RTS (%d)\n", ret);
+			return;
+		}
+	}
+	/*
+	 * For NDIS we assume that we are using sync PPP frames, for COM async.
+	 * This driver uses NDIS mode too. We don't bother with translation
+	 * from async -> sync PPP.
+	 */
+	info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet),
+			ADDR_SETUP_PROT,
+			TL_PROTOCOLID_SETUP,
+			TL_SETUP_SIGNO_INFO_MSG);
+	if (!info_packet)
+		goto exit_nomem;
+	info_packet->header.length = sizeof(struct tl_setup_info_msg);
+	info_packet->body.driver_type = NDISWAN_DRIVER;
+	info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION;
+	info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION;
+	send_packet(hw, PRIO_SETUP, &info_packet->header);
+
+	/* Initialization is now complete, so we clear the 'to_setup' flag */
+	hw->to_setup = 0;
+
+	return;
+
+exit_nomem:
+	printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+			": not enough memory to alloc control packet\n");
+	hw->to_setup = -1;
+}
+
+static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
+		unsigned char vers_no)
+{
+	del_timer(&hw->setup_timer);
+	hw->initializing = 0;
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n");
+
+	if (vers_no == TL_SETUP_VERSION)
+		__handle_setup_get_version_rsp(hw);
+	else
+		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+				": invalid hardware version no %u\n",
+				(unsigned int) vers_no);
+}
+
+static void ipw_send_setup_packet(struct ipw_hardware *hw)
+{
+	struct ipw_setup_get_version_query_packet *ver_packet;
+
+	ver_packet = alloc_ctrl_packet(
+			sizeof(struct ipw_setup_get_version_query_packet),
+			ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
+			TL_SETUP_SIGNO_GET_VERSION_QRY);
+	ver_packet->header.length = sizeof(struct tl_setup_get_version_qry);
+
+	/*
+	 * Response is handled in handle_received_SETUP_packet
+	 */
+	send_packet(hw, PRIO_SETUP, &ver_packet->header);
+}
+
+static void handle_received_SETUP_packet(struct ipw_hardware *hw,
+					 unsigned int address,
+					 const unsigned char *data, int len,
+					 int is_last)
+{
+	const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data;
+
+	if (address != ADDR_SETUP_PROT) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": setup packet has bad address %d\n", address);
+		return;
+	}
+
+	switch (rx_msg->sig_no) {
+	case TL_SETUP_SIGNO_GET_VERSION_RSP:
+		if (hw->to_setup)
+			handle_setup_get_version_rsp(hw,
+					rx_msg->version_rsp_msg.version);
+		break;
+
+	case TL_SETUP_SIGNO_OPEN_MSG:
+		if (ipwireless_debug) {
+			unsigned int channel_idx = rx_msg->open_msg.port_no - 1;
+
+			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			       ": OPEN_MSG [channel %u] reply received\n",
+			       channel_idx);
+		}
+		break;
+
+	case TL_SETUP_SIGNO_INFO_MSG_ACK:
+		if (ipwireless_debug)
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+			       ": card successfully configured as NDISWAN\n");
+		break;
+
+	case TL_SETUP_SIGNO_REBOOT_MSG:
+		if (hw->to_setup)
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+			       ": Setup not completed - ignoring reboot msg\n");
+		else {
+			struct ipw_setup_reboot_msg_ack *packet;
+
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+			       ": Acknowledging REBOOT message\n");
+			packet = alloc_ctrl_packet(
+					sizeof(struct ipw_setup_reboot_msg_ack),
+					ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
+					TL_SETUP_SIGNO_REBOOT_MSG_ACK);
+			packet->header.length =
+				sizeof(struct TlSetupRebootMsgAck);
+			send_packet(hw, PRIO_SETUP, &packet->header);
+			if (hw->reboot_callback)
+				hw->reboot_callback(hw->reboot_callback_data);
+		}
+		break;
+
+	default:
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": unknown setup message %u received\n",
+		       (unsigned int) rx_msg->sig_no);
+	}
+}
+
+static void do_close_hardware(struct ipw_hardware *hw)
+{
+	unsigned int irqn;
+
+	if (hw->hw_version == HW_VERSION_1) {
+		/* Disable TX and RX interrupts. */
+		outw(0, hw->base_port + IOIER);
+
+		/* Acknowledge any outstanding interrupt requests */
+		irqn = inw(hw->base_port + IOIR);
+		if (irqn & IR_TXINTR)
+			outw(IR_TXINTR, hw->base_port + IOIR);
+		if (irqn & IR_RXINTR)
+			outw(IR_RXINTR, hw->base_port + IOIR);
+
+		synchronize_irq(hw->irq);
+	}
+}
+
+struct ipw_hardware *ipwireless_hardware_create(void)
+{
+	int i;
+	struct ipw_hardware *hw =
+		kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL);
+
+	if (!hw)
+		return NULL;
+
+	hw->irq = -1;
+	hw->initializing = 1;
+	hw->tx_ready = 1;
+	hw->rx_bytes_queued = 0;
+	hw->rx_pool_size = 0;
+	hw->last_memtx_serial = (unsigned short) 0xffff;
+	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
+		INIT_LIST_HEAD(&hw->tx_queue[i]);
+
+	INIT_LIST_HEAD(&hw->rx_queue);
+	INIT_LIST_HEAD(&hw->rx_pool);
+	spin_lock_init(&hw->lock);
+	tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
+	INIT_WORK(&hw->work_rx, ipw_receive_data_work);
+	setup_timer(&hw->setup_timer, ipwireless_setup_timer,
+			(unsigned long) hw);
+
+	return hw;
+}
+
+void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
+		unsigned int base_port,
+		void __iomem *attr_memory,
+		void __iomem *common_memory,
+		int is_v2_card,
+		void (*reboot_callback) (void *data),
+		void *reboot_callback_data)
+{
+	if (hw->removed) {
+		hw->removed = 0;
+		enable_irq(hw->irq);
+	}
+	hw->base_port = base_port;
+	hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1);
+	hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2);
+	hw->memregs_CCR = (struct MEMCCR __iomem *)
+			((unsigned short __iomem *) attr_memory + 0x200);
+	hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
+	hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new;
+	hw->reboot_callback = reboot_callback;
+	hw->reboot_callback_data = reboot_callback_data;
+}
+
+void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw)
+{
+	hw->initializing = 1;
+	hw->init_loops = 0;
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+	       ": waiting for card to start up...\n");
+	ipwireless_setup_timer((unsigned long) hw);
+}
+
+static void ipwireless_setup_timer(unsigned long data)
+{
+	struct ipw_hardware *hw = (struct ipw_hardware *) data;
+
+	hw->init_loops++;
+
+	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY &&
+			hw->hw_version == HW_VERSION_2 &&
+			hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+				": failed to startup using TX2, trying TX\n");
+
+		hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old;
+		hw->init_loops = 0;
+	}
+	/* Give up after a certain number of retries */
+	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) {
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		       ": card failed to start up!\n");
+		hw->initializing = 0;
+	} else {
+		/* Do not attempt to write to the board if it is not present. */
+		if (is_card_present(hw)) {
+			unsigned long flags;
+
+			spin_lock_irqsave(&hw->lock, flags);
+			hw->to_setup = 1;
+			hw->tx_ready = 1;
+			spin_unlock_irqrestore(&hw->lock, flags);
+			tasklet_schedule(&hw->tasklet);
+		}
+
+		mod_timer(&hw->setup_timer,
+			jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO));
+	}
+}
+
+/*
+ * Stop any interrupts from executing so that, once this function returns,
+ * other layers of the driver can be sure they won't get any more callbacks.
+ * Thus must be called on a proper process context.
+ */
+void ipwireless_stop_interrupts(struct ipw_hardware *hw)
+{
+	if (!hw->shutting_down) {
+		/* Tell everyone we are going down. */
+		hw->shutting_down = 1;
+		del_timer(&hw->setup_timer);
+
+		/* Prevent the hardware from sending any more interrupts */
+		do_close_hardware(hw);
+	}
+}
+
+void ipwireless_hardware_free(struct ipw_hardware *hw)
+{
+	int i;
+	struct ipw_rx_packet *rp, *rq;
+	struct ipw_tx_packet *tp, *tq;
+
+	ipwireless_stop_interrupts(hw);
+
+	flush_work_sync(&hw->work_rx);
+
+	for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
+		if (hw->packet_assembler[i] != NULL)
+			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) {
+			list_del(&tp->queue);
+			kfree(tp);
+		}
+
+	list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) {
+		list_del(&rp->queue);
+		kfree(rp);
+	}
+
+	list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) {
+		list_del(&rp->queue);
+		kfree(rp);
+	}
+	kfree(hw);
+}
+
+/*
+ * Associate the specified network with this hardware, so it will receive events
+ * from it.
+ */
+void ipwireless_associate_network(struct ipw_hardware *hw,
+				  struct ipw_network *network)
+{
+	hw->network = network;
+}
diff --git a/drivers/tty/ipwireless/hardware.h b/drivers/tty/ipwireless/hardware.h
new file mode 100644
index 0000000..90a8590
--- /dev/null
+++ b/drivers/tty/ipwireless/hardware.h
@@ -0,0 +1,62 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_HARDWARE_H_
+#define _IPWIRELESS_CS_HARDWARE_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#define IPW_CONTROL_LINE_CTS 0x0001
+#define IPW_CONTROL_LINE_DCD 0x0002
+#define IPW_CONTROL_LINE_DSR 0x0004
+#define IPW_CONTROL_LINE_RI  0x0008
+#define IPW_CONTROL_LINE_DTR 0x0010
+#define IPW_CONTROL_LINE_RTS 0x0020
+
+struct ipw_hardware;
+struct ipw_network;
+
+struct ipw_hardware *ipwireless_hardware_create(void);
+void ipwireless_hardware_free(struct ipw_hardware *hw);
+irqreturn_t ipwireless_interrupt(int irq, void *dev_id);
+int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
+		int state);
+int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
+		int state);
+int ipwireless_send_packet(struct ipw_hardware *hw,
+			    unsigned int channel_idx,
+			    const unsigned char *data,
+			    unsigned int length,
+			    void (*packet_sent_callback) (void *cb,
+							  unsigned int length),
+			    void *sent_cb_data);
+void ipwireless_associate_network(struct ipw_hardware *hw,
+		struct ipw_network *net);
+void ipwireless_stop_interrupts(struct ipw_hardware *hw);
+void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
+				 unsigned int base_port,
+				 void __iomem *attr_memory,
+				 void __iomem *common_memory,
+				 int is_v2_card,
+				 void (*reboot_cb) (void *data),
+				 void *reboot_cb_data);
+void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
+void ipwireless_sleep(unsigned int tenths);
+
+#endif
diff --git a/drivers/tty/ipwireless/main.c b/drivers/tty/ipwireless/main.c
new file mode 100644
index 0000000..444155a
--- /dev/null
+++ b/drivers/tty/ipwireless/main.c
@@ -0,0 +1,347 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include "hardware.h"
+#include "network.h"
+#include "main.h"
+#include "tty.h"
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <pcmcia/cisreg.h>
+#include <pcmcia/device_id.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/ds.h>
+
+static struct pcmcia_device_id ipw_ids[] = {
+	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
+	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
+	PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
+
+static void ipwireless_detach(struct pcmcia_device *link);
+
+/*
+ * Module params
+ */
+/* Debug mode: more verbose, print sent/recv bytes */
+int ipwireless_debug;
+int ipwireless_loopback;
+int ipwireless_out_queue = 10;
+
+module_param_named(debug, ipwireless_debug, int, 0);
+module_param_named(loopback, ipwireless_loopback, int, 0);
+module_param_named(out_queue, ipwireless_out_queue, int, 0);
+MODULE_PARM_DESC(debug, "switch on debug messages [0]");
+MODULE_PARM_DESC(loopback,
+		"debug: enable ras_raw channel [0]");
+MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
+
+/* Executes in process context. */
+static void signalled_reboot_work(struct work_struct *work_reboot)
+{
+	struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
+			work_reboot);
+	struct pcmcia_device *link = ipw->link;
+	pcmcia_reset_card(link->socket);
+}
+
+static void signalled_reboot_callback(void *callback_data)
+{
+	struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
+
+	/* Delegate to process context. */
+	schedule_work(&ipw->work_reboot);
+}
+
+static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
+{
+	struct ipw_dev *ipw = priv_data;
+	int ret;
+
+	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
+	/* 0x40 causes it to generate level mode interrupts. */
+	/* 0x04 enables IREQ pin. */
+	p_dev->config_index |= 0x44;
+	p_dev->io_lines = 16;
+	ret = pcmcia_request_io(p_dev);
+	if (ret)
+		return ret;
+
+	if (!request_region(p_dev->resource[0]->start,
+			    resource_size(p_dev->resource[0]),
+			    IPWIRELESS_PCCARD_NAME)) {
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	p_dev->resource[2]->flags |=
+		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
+
+	ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
+	if (ret != 0)
+		goto exit1;
+
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
+	if (ret != 0)
+		goto exit1;
+
+	ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
+
+	ipw->common_memory = ioremap(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]));
+	if (!request_mem_region(p_dev->resource[2]->start,
+				resource_size(p_dev->resource[2]),
+				IPWIRELESS_PCCARD_NAME)) {
+		ret = -EBUSY;
+		goto exit2;
+	}
+
+	p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
+					WIN_ENABLE;
+	p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
+	ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
+	if (ret != 0)
+		goto exit3;
+
+	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
+	if (ret != 0)
+		goto exit3;
+
+	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+				resource_size(p_dev->resource[3]));
+	if (!request_mem_region(p_dev->resource[3]->start,
+				resource_size(p_dev->resource[3]),
+				IPWIRELESS_PCCARD_NAME)) {
+		ret = -EBUSY;
+		goto exit4;
+	}
+
+	return 0;
+
+exit4:
+	iounmap(ipw->attr_memory);
+exit3:
+	release_mem_region(p_dev->resource[2]->start,
+			resource_size(p_dev->resource[2]));
+exit2:
+	iounmap(ipw->common_memory);
+exit1:
+	release_region(p_dev->resource[0]->start,
+		       resource_size(p_dev->resource[0]));
+exit:
+	pcmcia_disable_device(p_dev);
+	return ret;
+}
+
+static int config_ipwireless(struct ipw_dev *ipw)
+{
+	struct pcmcia_device *link = ipw->link;
+	int ret = 0;
+
+	ipw->is_v2_card = 0;
+	link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
+		CONF_ENABLE_IRQ;
+
+	ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
+	if (ret != 0)
+		return ret;
+
+	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
+
+	ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
+				    ipw->attr_memory, ipw->common_memory,
+				    ipw->is_v2_card, signalled_reboot_callback,
+				    ipw);
+
+	ret = pcmcia_request_irq(link, ipwireless_interrupt);
+	if (ret != 0)
+		goto exit;
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
+			ipw->is_v2_card ? "V2/V3" : "V1");
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+		": I/O ports %pR, irq %d\n", link->resource[0],
+			(unsigned int) link->irq);
+	if (ipw->attr_memory && ipw->common_memory)
+		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+			": attr memory %pR, common memory %pR\n",
+			link->resource[3],
+			link->resource[2]);
+
+	ipw->network = ipwireless_network_create(ipw->hardware);
+	if (!ipw->network)
+		goto exit;
+
+	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network);
+	if (!ipw->tty)
+		goto exit;
+
+	ipwireless_init_hardware_v2_v3(ipw->hardware);
+
+	/*
+	 * Do the RequestConfiguration last, because it enables interrupts.
+	 * Then we don't get any interrupts before we're ready for them.
+	 */
+	ret = pcmcia_enable_device(link);
+	if (ret != 0)
+		goto exit;
+
+	return 0;
+
+exit:
+	if (ipw->common_memory) {
+		release_mem_region(link->resource[2]->start,
+				resource_size(link->resource[2]));
+		iounmap(ipw->common_memory);
+	}
+	if (ipw->attr_memory) {
+		release_mem_region(link->resource[3]->start,
+				resource_size(link->resource[3]));
+		iounmap(ipw->attr_memory);
+	}
+	pcmcia_disable_device(link);
+	return -1;
+}
+
+static void release_ipwireless(struct ipw_dev *ipw)
+{
+	release_region(ipw->link->resource[0]->start,
+		       resource_size(ipw->link->resource[0]));
+	if (ipw->common_memory) {
+		release_mem_region(ipw->link->resource[2]->start,
+				resource_size(ipw->link->resource[2]));
+		iounmap(ipw->common_memory);
+	}
+	if (ipw->attr_memory) {
+		release_mem_region(ipw->link->resource[3]->start,
+				resource_size(ipw->link->resource[3]));
+		iounmap(ipw->attr_memory);
+	}
+	pcmcia_disable_device(ipw->link);
+}
+
+/*
+ * ipwireless_attach() creates an "instance" of the driver, allocating
+ * local data structures for one device (one interface).  The device
+ * is registered with Card Services.
+ *
+ * The pcmcia_device structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a
+ * card insertion event.
+ */
+static int ipwireless_attach(struct pcmcia_device *link)
+{
+	struct ipw_dev *ipw;
+	int ret;
+
+	ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
+	if (!ipw)
+		return -ENOMEM;
+
+	ipw->link = link;
+	link->priv = ipw;
+
+	ipw->hardware = ipwireless_hardware_create();
+	if (!ipw->hardware) {
+		kfree(ipw);
+		return -ENOMEM;
+	}
+	/* RegisterClient will call config_ipwireless */
+
+	ret = config_ipwireless(ipw);
+
+	if (ret != 0) {
+		ipwireless_detach(link);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * This deletes a driver "instance".  The device is de-registered with
+ * Card Services.  If it has been released, all local data structures
+ * are freed.  Otherwise, the structures will be freed when the device
+ * is released.
+ */
+static void ipwireless_detach(struct pcmcia_device *link)
+{
+	struct ipw_dev *ipw = link->priv;
+
+	release_ipwireless(ipw);
+
+	if (ipw->tty != NULL)
+		ipwireless_tty_free(ipw->tty);
+	if (ipw->network != NULL)
+		ipwireless_network_free(ipw->network);
+	if (ipw->hardware != NULL)
+		ipwireless_hardware_free(ipw->hardware);
+	kfree(ipw);
+}
+
+static struct pcmcia_driver me = {
+	.owner		= THIS_MODULE,
+	.probe          = ipwireless_attach,
+	.remove         = ipwireless_detach,
+	.name		= IPWIRELESS_PCCARD_NAME,
+	.id_table       = ipw_ids
+};
+
+/*
+ * Module insertion : initialisation of the module.
+ * Register the card with cardmgr...
+ */
+static int __init init_ipwireless(void)
+{
+	int ret;
+
+	ret = ipwireless_tty_init();
+	if (ret != 0)
+		return ret;
+
+	ret = pcmcia_register_driver(&me);
+	if (ret != 0)
+		ipwireless_tty_release();
+
+	return ret;
+}
+
+/*
+ * Module removal
+ */
+static void __exit exit_ipwireless(void)
+{
+	pcmcia_unregister_driver(&me);
+	ipwireless_tty_release();
+}
+
+module_init(init_ipwireless);
+module_exit(exit_ipwireless);
+
+MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
+MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/tty/ipwireless/main.h b/drivers/tty/ipwireless/main.h
new file mode 100644
index 0000000..f2cbb11
--- /dev/null
+++ b/drivers/tty/ipwireless/main.h
@@ -0,0 +1,68 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_H_
+#define _IPWIRELESS_CS_H_
+
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+#include "hardware.h"
+
+#define IPWIRELESS_PCCARD_NAME		"ipwireless"
+#define IPWIRELESS_PCMCIA_VERSION	"1.1"
+#define IPWIRELESS_PCMCIA_AUTHOR        \
+	"Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba"
+
+#define IPWIRELESS_TX_QUEUE_SIZE  262144
+#define IPWIRELESS_RX_QUEUE_SIZE  262144
+
+#define IPWIRELESS_STATE_DEBUG
+
+struct ipw_hardware;
+struct ipw_network;
+struct ipw_tty;
+
+struct ipw_dev {
+	struct pcmcia_device *link;
+	int is_v2_card;
+
+	void __iomem *attr_memory;
+
+	void __iomem *common_memory;
+
+	/* Reference to attribute memory, containing CIS data */
+	void *attribute_memory;
+
+	/* Hardware context */
+	struct ipw_hardware *hardware;
+	/* Network layer context */
+	struct ipw_network *network;
+	/* TTY device context */
+	struct ipw_tty *tty;
+	struct work_struct work_reboot;
+};
+
+/* Module parametres */
+extern int ipwireless_debug;
+extern int ipwireless_loopback;
+extern int ipwireless_out_queue;
+
+#endif
diff --git a/drivers/tty/ipwireless/network.c b/drivers/tty/ipwireless/network.c
new file mode 100644
index 0000000..f7daeea
--- /dev/null
+++ b/drivers/tty/ipwireless/network.c
@@ -0,0 +1,508 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/netdevice.h>
+#include <linux/ppp_channel.h>
+#include <linux/ppp_defs.h>
+#include <linux/slab.h>
+#include <linux/if_ppp.h>
+#include <linux/skbuff.h>
+
+#include "network.h"
+#include "hardware.h"
+#include "main.h"
+#include "tty.h"
+
+#define MAX_ASSOCIATED_TTYS 2
+
+#define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+struct ipw_network {
+	/* Hardware context, used for calls to hardware layer. */
+	struct ipw_hardware *hardware;
+	/* Context for kernel 'generic_ppp' functionality */
+	struct ppp_channel *ppp_channel;
+	/* tty context connected with IPW console */
+	struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
+	/* True if ppp needs waking up once we're ready to xmit */
+	int ppp_blocked;
+	/* Number of packets queued up in hardware module. */
+	int outgoing_packets_queued;
+	/* Spinlock to avoid interrupts during shutdown */
+	spinlock_t lock;
+	struct mutex close_lock;
+
+	/* PPP ioctl data, not actually used anywere */
+	unsigned int flags;
+	unsigned int rbits;
+	u32 xaccm[8];
+	u32 raccm;
+	int mru;
+
+	int shutting_down;
+	unsigned int ras_control_lines;
+
+	struct work_struct work_go_online;
+	struct work_struct work_go_offline;
+};
+
+static void notify_packet_sent(void *callback_data, unsigned int packet_length)
+{
+	struct ipw_network *network = callback_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->lock, flags);
+	network->outgoing_packets_queued--;
+	if (network->ppp_channel != NULL) {
+		if (network->ppp_blocked) {
+			network->ppp_blocked = 0;
+			spin_unlock_irqrestore(&network->lock, flags);
+			ppp_output_wakeup(network->ppp_channel);
+			if (ipwireless_debug)
+				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+				       ": ppp unblocked\n");
+		} else
+			spin_unlock_irqrestore(&network->lock, flags);
+	} else
+		spin_unlock_irqrestore(&network->lock, flags);
+}
+
+/*
+ * Called by the ppp system when it has a packet to send to the hardware.
+ */
+static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
+				     struct sk_buff *skb)
+{
+	struct ipw_network *network = ppp_channel->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->lock, flags);
+	if (network->outgoing_packets_queued < ipwireless_out_queue) {
+		unsigned char *buf;
+		static unsigned char header[] = {
+			PPP_ALLSTATIONS, /* 0xff */
+			PPP_UI,		 /* 0x03 */
+		};
+		int ret;
+
+		network->outgoing_packets_queued++;
+		spin_unlock_irqrestore(&network->lock, flags);
+
+		/*
+		 * If we have the requested amount of headroom in the skb we
+		 * were handed, then we can add the header efficiently.
+		 */
+		if (skb_headroom(skb) >= 2) {
+			memcpy(skb_push(skb, 2), header, 2);
+			ret = ipwireless_send_packet(network->hardware,
+					       IPW_CHANNEL_RAS, skb->data,
+					       skb->len,
+					       notify_packet_sent,
+					       network);
+			if (ret == -1) {
+				skb_pull(skb, 2);
+				return 0;
+			}
+		} else {
+			/* Otherwise (rarely) we do it inefficiently. */
+			buf = kmalloc(skb->len + 2, GFP_ATOMIC);
+			if (!buf)
+				return 0;
+			memcpy(buf + 2, skb->data, skb->len);
+			memcpy(buf, header, 2);
+			ret = ipwireless_send_packet(network->hardware,
+					       IPW_CHANNEL_RAS, buf,
+					       skb->len + 2,
+					       notify_packet_sent,
+					       network);
+			kfree(buf);
+			if (ret == -1)
+				return 0;
+		}
+		kfree_skb(skb);
+		return 1;
+	} else {
+		/*
+		 * Otherwise reject the packet, and flag that the ppp system
+		 * needs to be unblocked once we are ready to send.
+		 */
+		network->ppp_blocked = 1;
+		spin_unlock_irqrestore(&network->lock, flags);
+		if (ipwireless_debug)
+			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
+		return 0;
+	}
+}
+
+/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
+static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
+				unsigned int cmd, unsigned long arg)
+{
+	struct ipw_network *network = ppp_channel->private;
+	int err, val;
+	u32 accm[8];
+	int __user *user_arg = (int __user *) arg;
+
+	err = -EFAULT;
+	switch (cmd) {
+	case PPPIOCGFLAGS:
+		val = network->flags | network->rbits;
+		if (put_user(val, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSFLAGS:
+		if (get_user(val, user_arg))
+			break;
+		network->flags = val & ~SC_RCV_BITS;
+		network->rbits = val & SC_RCV_BITS;
+		err = 0;
+		break;
+
+	case PPPIOCGASYNCMAP:
+		if (put_user(network->xaccm[0], user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSASYNCMAP:
+		if (get_user(network->xaccm[0], user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGRASYNCMAP:
+		if (put_user(network->raccm, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSRASYNCMAP:
+		if (get_user(network->raccm, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGXASYNCMAP:
+		if (copy_to_user((void __user *) arg, network->xaccm,
+					sizeof(network->xaccm)))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSXASYNCMAP:
+		if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
+			break;
+		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
+		accm[3] |= 0x60000000U;	/* must escape 0x7d, 0x7e */
+		memcpy(network->xaccm, accm, sizeof(network->xaccm));
+		err = 0;
+		break;
+
+	case PPPIOCGMRU:
+		if (put_user(network->mru, user_arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCSMRU:
+		if (get_user(val, user_arg))
+			break;
+		if (val < PPP_MRU)
+			val = PPP_MRU;
+		network->mru = val;
+		err = 0;
+		break;
+
+	default:
+		err = -ENOTTY;
+	}
+
+	return err;
+}
+
+static const struct ppp_channel_ops ipwireless_ppp_channel_ops = {
+	.start_xmit = ipwireless_ppp_start_xmit,
+	.ioctl      = ipwireless_ppp_ioctl
+};
+
+static void do_go_online(struct work_struct *work_go_online)
+{
+	struct ipw_network *network =
+		container_of(work_go_online, struct ipw_network,
+				work_go_online);
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->lock, flags);
+	if (!network->ppp_channel) {
+		struct ppp_channel *channel;
+
+		spin_unlock_irqrestore(&network->lock, flags);
+		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
+		if (!channel) {
+			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+					": unable to allocate PPP channel\n");
+			return;
+		}
+		channel->private = network;
+		channel->mtu = 16384;	/* Wild guess */
+		channel->hdrlen = 2;
+		channel->ops = &ipwireless_ppp_channel_ops;
+
+		network->flags = 0;
+		network->rbits = 0;
+		network->mru = PPP_MRU;
+		memset(network->xaccm, 0, sizeof(network->xaccm));
+		network->xaccm[0] = ~0U;
+		network->xaccm[3] = 0x60000000U;
+		network->raccm = ~0U;
+		ppp_register_channel(channel);
+		spin_lock_irqsave(&network->lock, flags);
+		network->ppp_channel = channel;
+	}
+	spin_unlock_irqrestore(&network->lock, flags);
+}
+
+static void do_go_offline(struct work_struct *work_go_offline)
+{
+	struct ipw_network *network =
+		container_of(work_go_offline, struct ipw_network,
+				work_go_offline);
+	unsigned long flags;
+
+	mutex_lock(&network->close_lock);
+	spin_lock_irqsave(&network->lock, flags);
+	if (network->ppp_channel != NULL) {
+		struct ppp_channel *channel = network->ppp_channel;
+
+		network->ppp_channel = NULL;
+		spin_unlock_irqrestore(&network->lock, flags);
+		mutex_unlock(&network->close_lock);
+		ppp_unregister_channel(channel);
+	} else {
+		spin_unlock_irqrestore(&network->lock, flags);
+		mutex_unlock(&network->close_lock);
+	}
+}
+
+void ipwireless_network_notify_control_line_change(struct ipw_network *network,
+						   unsigned int channel_idx,
+						   unsigned int control_lines,
+						   unsigned int changed_mask)
+{
+	int i;
+
+	if (channel_idx == IPW_CHANNEL_RAS)
+		network->ras_control_lines = control_lines;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
+		struct ipw_tty *tty =
+			network->associated_ttys[channel_idx][i];
+
+		/*
+		 * If it's associated with a tty (other than the RAS channel
+		 * when we're online), then send the data to that tty.  The RAS
+		 * channel's data is handled above - it always goes through
+		 * ppp_generic.
+		 */
+		if (tty)
+			ipwireless_tty_notify_control_line_change(tty,
+								  channel_idx,
+								  control_lines,
+								  changed_mask);
+	}
+}
+
+/*
+ * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
+ * bytes, which are required on sent packet, but not always present on received
+ * packets
+ */
+static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
+					       unsigned int length)
+{
+	struct sk_buff *skb;
+
+	if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
+		length -= 2;
+		data += 2;
+	}
+
+	skb = dev_alloc_skb(length + 4);
+	skb_reserve(skb, 2);
+	memcpy(skb_put(skb, length), data, length);
+
+	return skb;
+}
+
+void ipwireless_network_packet_received(struct ipw_network *network,
+					unsigned int channel_idx,
+					unsigned char *data,
+					unsigned int length)
+{
+	int i;
+	unsigned long flags;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
+		struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
+
+		if (!tty)
+			continue;
+
+		/*
+		 * If it's associated with a tty (other than the RAS channel
+		 * when we're online), then send the data to that tty.  The RAS
+		 * channel's data is handled above - it always goes through
+		 * ppp_generic.
+		 */
+		if (channel_idx == IPW_CHANNEL_RAS
+				&& (network->ras_control_lines &
+					IPW_CONTROL_LINE_DCD) != 0
+				&& ipwireless_tty_is_modem(tty)) {
+			/*
+			 * If data came in on the RAS channel and this tty is
+			 * the modem tty, and we are online, then we send it to
+			 * the PPP layer.
+			 */
+			mutex_lock(&network->close_lock);
+			spin_lock_irqsave(&network->lock, flags);
+			if (network->ppp_channel != NULL) {
+				struct sk_buff *skb;
+
+				spin_unlock_irqrestore(&network->lock,
+						flags);
+
+				/* Send the data to the ppp_generic module. */
+				skb = ipw_packet_received_skb(data, length);
+				ppp_input(network->ppp_channel, skb);
+			} else
+				spin_unlock_irqrestore(&network->lock,
+						flags);
+			mutex_unlock(&network->close_lock);
+		}
+		/* Otherwise we send it out the tty. */
+		else
+			ipwireless_tty_received(tty, data, length);
+	}
+}
+
+struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
+{
+	struct ipw_network *network =
+		kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
+
+	if (!network)
+		return NULL;
+
+	spin_lock_init(&network->lock);
+	mutex_init(&network->close_lock);
+
+	network->hardware = hw;
+
+	INIT_WORK(&network->work_go_online, do_go_online);
+	INIT_WORK(&network->work_go_offline, do_go_offline);
+
+	ipwireless_associate_network(hw, network);
+
+	return network;
+}
+
+void ipwireless_network_free(struct ipw_network *network)
+{
+	network->shutting_down = 1;
+
+	ipwireless_ppp_close(network);
+	flush_work_sync(&network->work_go_online);
+	flush_work_sync(&network->work_go_offline);
+
+	ipwireless_stop_interrupts(network->hardware);
+	ipwireless_associate_network(network->hardware, NULL);
+
+	kfree(network);
+}
+
+void ipwireless_associate_network_tty(struct ipw_network *network,
+				      unsigned int channel_idx,
+				      struct ipw_tty *tty)
+{
+	int i;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
+		if (network->associated_ttys[channel_idx][i] == NULL) {
+			network->associated_ttys[channel_idx][i] = tty;
+			break;
+		}
+}
+
+void ipwireless_disassociate_network_ttys(struct ipw_network *network,
+					  unsigned int channel_idx)
+{
+	int i;
+
+	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
+		network->associated_ttys[channel_idx][i] = NULL;
+}
+
+void ipwireless_ppp_open(struct ipw_network *network)
+{
+	if (ipwireless_debug)
+		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
+	schedule_work(&network->work_go_online);
+}
+
+void ipwireless_ppp_close(struct ipw_network *network)
+{
+	/* Disconnect from the wireless network. */
+	if (ipwireless_debug)
+		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
+	schedule_work(&network->work_go_offline);
+}
+
+int ipwireless_ppp_channel_index(struct ipw_network *network)
+{
+	int ret = -1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->lock, flags);
+	if (network->ppp_channel != NULL)
+		ret = ppp_channel_index(network->ppp_channel);
+	spin_unlock_irqrestore(&network->lock, flags);
+
+	return ret;
+}
+
+int ipwireless_ppp_unit_number(struct ipw_network *network)
+{
+	int ret = -1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&network->lock, flags);
+	if (network->ppp_channel != NULL)
+		ret = ppp_unit_number(network->ppp_channel);
+	spin_unlock_irqrestore(&network->lock, flags);
+
+	return ret;
+}
+
+int ipwireless_ppp_mru(const struct ipw_network *network)
+{
+	return network->mru;
+}
diff --git a/drivers/tty/ipwireless/network.h b/drivers/tty/ipwireless/network.h
new file mode 100644
index 0000000..561f765
--- /dev/null
+++ b/drivers/tty/ipwireless/network.h
@@ -0,0 +1,53 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_NETWORK_H_
+#define _IPWIRELESS_CS_NETWORK_H_
+
+#include <linux/types.h>
+
+struct ipw_network;
+struct ipw_tty;
+struct ipw_hardware;
+
+/* Definitions of the different channels on the PCMCIA UE */
+#define IPW_CHANNEL_RAS      0
+#define IPW_CHANNEL_DIALLER  1
+#define IPW_CHANNEL_CONSOLE  2
+#define NO_OF_IPW_CHANNELS   5
+
+void ipwireless_network_notify_control_line_change(struct ipw_network *net,
+		unsigned int channel_idx, unsigned int control_lines,
+		unsigned int control_mask);
+void ipwireless_network_packet_received(struct ipw_network *net,
+		unsigned int channel_idx, unsigned char *data,
+		unsigned int length);
+struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw);
+void ipwireless_network_free(struct ipw_network *net);
+void ipwireless_associate_network_tty(struct ipw_network *net,
+		unsigned int channel_idx, struct ipw_tty *tty);
+void ipwireless_disassociate_network_ttys(struct ipw_network *net,
+		unsigned int channel_idx);
+
+void ipwireless_ppp_open(struct ipw_network *net);
+
+void ipwireless_ppp_close(struct ipw_network *net);
+int ipwireless_ppp_channel_index(struct ipw_network *net);
+int ipwireless_ppp_unit_number(struct ipw_network *net);
+int ipwireless_ppp_mru(const struct ipw_network *net);
+
+#endif
diff --git a/drivers/tty/ipwireless/setup_protocol.h b/drivers/tty/ipwireless/setup_protocol.h
new file mode 100644
index 0000000..9d6bcc7
--- /dev/null
+++ b/drivers/tty/ipwireless/setup_protocol.h
@@ -0,0 +1,108 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_
+#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_
+
+/* Version of the setup protocol and transport protocols */
+#define TL_SETUP_VERSION		1
+
+#define TL_SETUP_VERSION_QRY_TMO	1000
+#define TL_SETUP_MAX_VERSION_QRY	30
+
+/* Message numbers 0-9 are obsoleted and must not be reused! */
+#define TL_SETUP_SIGNO_GET_VERSION_QRY	10
+#define TL_SETUP_SIGNO_GET_VERSION_RSP	11
+#define TL_SETUP_SIGNO_CONFIG_MSG	12
+#define TL_SETUP_SIGNO_CONFIG_DONE_MSG	13
+#define TL_SETUP_SIGNO_OPEN_MSG		14
+#define TL_SETUP_SIGNO_CLOSE_MSG	15
+
+#define TL_SETUP_SIGNO_INFO_MSG     20
+#define TL_SETUP_SIGNO_INFO_MSG_ACK 21
+
+#define TL_SETUP_SIGNO_REBOOT_MSG      22
+#define TL_SETUP_SIGNO_REBOOT_MSG_ACK  23
+
+/* Synchronous start-messages */
+struct tl_setup_get_version_qry {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_QRY */
+} __attribute__ ((__packed__));
+
+struct tl_setup_get_version_rsp {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_RSP */
+	unsigned char version;		/* TL_SETUP_VERSION */
+} __attribute__ ((__packed__));
+
+struct tl_setup_config_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_MSG */
+	unsigned char port_no;
+	unsigned char prio_data;
+	unsigned char prio_ctrl;
+} __attribute__ ((__packed__));
+
+struct tl_setup_config_done_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
+} __attribute__ ((__packed__));
+
+/* Asyncronous messages */
+struct tl_setup_open_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_OPEN_MSG */
+	unsigned char port_no;
+} __attribute__ ((__packed__));
+
+struct tl_setup_close_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_CLOSE_MSG */
+	unsigned char port_no;
+} __attribute__ ((__packed__));
+
+/* Driver type  - for use in tl_setup_info_msg.driver_type */
+#define COMM_DRIVER     0
+#define NDISWAN_DRIVER  1
+#define NDISWAN_DRIVER_MAJOR_VERSION  2
+#define NDISWAN_DRIVER_MINOR_VERSION  0
+
+/*
+ * It should not matter when this message comes over as we just store the
+ * results and send the ACK.
+ */
+struct tl_setup_info_msg {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG */
+	unsigned char driver_type;
+	unsigned char major_version;
+	unsigned char minor_version;
+} __attribute__ ((__packed__));
+
+struct tl_setup_info_msgAck {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG_ACK */
+} __attribute__ ((__packed__));
+
+struct TlSetupRebootMsgAck {
+	unsigned char sig_no;		/* TL_SETUP_SIGNO_REBOOT_MSG_ACK */
+} __attribute__ ((__packed__));
+
+/* Define a union of all the msgs that the driver can receive from the card.*/
+union ipw_setup_rx_msg {
+	unsigned char sig_no;
+	struct tl_setup_get_version_rsp version_rsp_msg;
+	struct tl_setup_open_msg open_msg;
+	struct tl_setup_close_msg close_msg;
+	struct tl_setup_info_msg InfoMsg;
+	struct tl_setup_info_msgAck info_msg_ack;
+} __attribute__ ((__packed__));
+
+#endif				/* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */
diff --git a/drivers/tty/ipwireless/tty.c b/drivers/tty/ipwireless/tty.c
new file mode 100644
index 0000000..ef92869
--- /dev/null
+++ b/drivers/tty/ipwireless/tty.c
@@ -0,0 +1,679 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/ppp_defs.h>
+#include <linux/if.h>
+#include <linux/if_ppp.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/uaccess.h>
+
+#include "tty.h"
+#include "network.h"
+#include "hardware.h"
+#include "main.h"
+
+#define IPWIRELESS_PCMCIA_START 	(0)
+#define IPWIRELESS_PCMCIA_MINORS	(24)
+#define IPWIRELESS_PCMCIA_MINOR_RANGE	(8)
+
+#define TTYTYPE_MODEM    (0)
+#define TTYTYPE_MONITOR  (1)
+#define TTYTYPE_RAS_RAW  (2)
+
+struct ipw_tty {
+	int index;
+	struct ipw_hardware *hardware;
+	unsigned int channel_idx;
+	unsigned int secondary_channel_idx;
+	int tty_type;
+	struct ipw_network *network;
+	struct tty_struct *linux_tty;
+	int open_count;
+	unsigned int control_lines;
+	struct mutex ipw_tty_mutex;
+	int tx_bytes_queued;
+	int closing;
+};
+
+static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS];
+
+static struct tty_driver *ipw_tty_driver;
+
+static char *tty_type_name(int tty_type)
+{
+	static char *channel_names[] = {
+		"modem",
+		"monitor",
+		"RAS-raw"
+	};
+
+	return channel_names[tty_type];
+}
+
+static void report_registering(struct ipw_tty *tty)
+{
+	char *iftype = tty_type_name(tty->tty_type);
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+	       ": registering %s device ttyIPWp%d\n", iftype, tty->index);
+}
+
+static void report_deregistering(struct ipw_tty *tty)
+{
+	char *iftype = tty_type_name(tty->tty_type);
+
+	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
+	       ": deregistering %s device ttyIPWp%d\n", iftype,
+	       tty->index);
+}
+
+static struct ipw_tty *get_tty(int minor)
+{
+	if (minor < ipw_tty_driver->minor_start
+			|| minor >= ipw_tty_driver->minor_start +
+			IPWIRELESS_PCMCIA_MINORS)
+		return NULL;
+	else {
+		int minor_offset = minor - ipw_tty_driver->minor_start;
+
+		/*
+		 * The 'ras_raw' channel is only available when 'loopback' mode
+		 * is enabled.
+		 * Number of minor starts with 16 (_RANGE * _RAS_RAW).
+		 */
+		if (!ipwireless_loopback &&
+				minor_offset >=
+				 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
+			return NULL;
+
+		return ttys[minor_offset];
+	}
+}
+
+static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
+{
+	int minor = linux_tty->index;
+	struct ipw_tty *tty = get_tty(minor);
+
+	if (!tty)
+		return -ENODEV;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+
+	if (tty->closing) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return -ENODEV;
+	}
+	if (tty->open_count == 0)
+		tty->tx_bytes_queued = 0;
+
+	tty->open_count++;
+
+	tty->linux_tty = linux_tty;
+	linux_tty->driver_data = tty;
+	linux_tty->low_latency = 1;
+
+	if (tty->tty_type == TTYTYPE_MODEM)
+		ipwireless_ppp_open(tty->network);
+
+	mutex_unlock(&tty->ipw_tty_mutex);
+
+	return 0;
+}
+
+static void do_ipw_close(struct ipw_tty *tty)
+{
+	tty->open_count--;
+
+	if (tty->open_count == 0) {
+		struct tty_struct *linux_tty = tty->linux_tty;
+
+		if (linux_tty != NULL) {
+			tty->linux_tty = NULL;
+			linux_tty->driver_data = NULL;
+
+			if (tty->tty_type == TTYTYPE_MODEM)
+				ipwireless_ppp_close(tty->network);
+		}
+	}
+}
+
+static void ipw_hangup(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+	if (tty->open_count == 0) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return;
+	}
+
+	do_ipw_close(tty);
+
+	mutex_unlock(&tty->ipw_tty_mutex);
+}
+
+static void ipw_close(struct tty_struct *linux_tty, struct file *filp)
+{
+	ipw_hangup(linux_tty);
+}
+
+/* Take data received from hardware, and send it out the tty */
+void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
+			unsigned int length)
+{
+	struct tty_struct *linux_tty;
+	int work = 0;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+	linux_tty = tty->linux_tty;
+	if (linux_tty == NULL) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return;
+	}
+
+	if (!tty->open_count) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return;
+	}
+	mutex_unlock(&tty->ipw_tty_mutex);
+
+	work = tty_insert_flip_string(linux_tty, data, length);
+
+	if (work != length)
+		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
+				": %d chars not inserted to flip buffer!\n",
+				length - work);
+
+	/*
+	 * This may sleep if ->low_latency is set
+	 */
+	if (work)
+		tty_flip_buffer_push(linux_tty);
+}
+
+static void ipw_write_packet_sent_callback(void *callback_data,
+					   unsigned int packet_length)
+{
+	struct ipw_tty *tty = callback_data;
+
+	/*
+	 * Packet has been sent, so we subtract the number of bytes from our
+	 * tally of outstanding TX bytes.
+	 */
+	tty->tx_bytes_queued -= packet_length;
+}
+
+static int ipw_write(struct tty_struct *linux_tty,
+		     const unsigned char *buf, int count)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+	int room, ret;
+
+	if (!tty)
+		return -ENODEV;
+
+	mutex_lock(&tty->ipw_tty_mutex);
+	if (!tty->open_count) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return -EINVAL;
+	}
+
+	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
+	if (room < 0)
+		room = 0;
+	/* Don't allow caller to write any more than we have room for */
+	if (count > room)
+		count = room;
+
+	if (count == 0) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return 0;
+	}
+
+	ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
+			       buf, count,
+			       ipw_write_packet_sent_callback, tty);
+	if (ret == -1) {
+		mutex_unlock(&tty->ipw_tty_mutex);
+		return 0;
+	}
+
+	tty->tx_bytes_queued += count;
+	mutex_unlock(&tty->ipw_tty_mutex);
+
+	return count;
+}
+
+static int ipw_write_room(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+	int room;
+
+	/* FIXME: Exactly how is the tty object locked here .. */
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
+	if (room < 0)
+		room = 0;
+
+	return room;
+}
+
+static int ipwireless_get_serial_info(struct ipw_tty *tty,
+				      struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return (-EFAULT);
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = PORT_UNKNOWN;
+	tmp.line = tty->index;
+	tmp.port = 0;
+	tmp.irq = 0;
+	tmp.flags = 0;
+	tmp.baud_base = 115200;
+	tmp.close_delay = 0;
+	tmp.closing_wait = 0;
+	tmp.custom_divisor = 0;
+	tmp.hub6 = 0;
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return 0;
+
+	if (!tty->open_count)
+		return 0;
+
+	return tty->tx_bytes_queued;
+}
+
+static int get_control_lines(struct ipw_tty *tty)
+{
+	unsigned int my = tty->control_lines;
+	unsigned int out = 0;
+
+	if (my & IPW_CONTROL_LINE_RTS)
+		out |= TIOCM_RTS;
+	if (my & IPW_CONTROL_LINE_DTR)
+		out |= TIOCM_DTR;
+	if (my & IPW_CONTROL_LINE_CTS)
+		out |= TIOCM_CTS;
+	if (my & IPW_CONTROL_LINE_DSR)
+		out |= TIOCM_DSR;
+	if (my & IPW_CONTROL_LINE_DCD)
+		out |= TIOCM_CD;
+
+	return out;
+}
+
+static int set_control_lines(struct ipw_tty *tty, unsigned int set,
+			     unsigned int clear)
+{
+	int ret;
+
+	if (set & TIOCM_RTS) {
+		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1);
+		if (ret)
+			return ret;
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_RTS(tty->hardware,
+					  tty->secondary_channel_idx, 1);
+			if (ret)
+				return ret;
+		}
+	}
+	if (set & TIOCM_DTR) {
+		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1);
+		if (ret)
+			return ret;
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_DTR(tty->hardware,
+					  tty->secondary_channel_idx, 1);
+			if (ret)
+				return ret;
+		}
+	}
+	if (clear & TIOCM_RTS) {
+		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0);
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_RTS(tty->hardware,
+					  tty->secondary_channel_idx, 0);
+			if (ret)
+				return ret;
+		}
+	}
+	if (clear & TIOCM_DTR) {
+		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0);
+		if (tty->secondary_channel_idx != -1) {
+			ret = ipwireless_set_DTR(tty->hardware,
+					  tty->secondary_channel_idx, 0);
+			if (ret)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+static int ipw_tiocmget(struct tty_struct *linux_tty)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+	/* FIXME: Exactly how is the tty object locked here .. */
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	return get_control_lines(tty);
+}
+
+static int
+ipw_tiocmset(struct tty_struct *linux_tty,
+	     unsigned int set, unsigned int clear)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+	/* FIXME: Exactly how is the tty object locked here .. */
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	return set_control_lines(tty, set, clear);
+}
+
+static int ipw_ioctl(struct tty_struct *linux_tty,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct ipw_tty *tty = linux_tty->driver_data;
+
+	if (!tty)
+		return -ENODEV;
+
+	if (!tty->open_count)
+		return -EINVAL;
+
+	/* FIXME: Exactly how is the tty object locked here .. */
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		return ipwireless_get_serial_info(tty, (void __user *) arg);
+
+	case TIOCSSERIAL:
+		return 0;	/* Keeps the PCMCIA scripts happy. */
+	}
+
+	if (tty->tty_type == TTYTYPE_MODEM) {
+		switch (cmd) {
+		case PPPIOCGCHAN:
+			{
+				int chan = ipwireless_ppp_channel_index(
+							tty->network);
+
+				if (chan < 0)
+					return -ENODEV;
+				if (put_user(chan, (int __user *) arg))
+					return -EFAULT;
+			}
+			return 0;
+
+		case PPPIOCGUNIT:
+			{
+				int unit = ipwireless_ppp_unit_number(
+						tty->network);
+
+				if (unit < 0)
+					return -ENODEV;
+				if (put_user(unit, (int __user *) arg))
+					return -EFAULT;
+			}
+			return 0;
+
+		case FIONREAD:
+			{
+				int val = 0;
+
+				if (put_user(val, (int __user *) arg))
+					return -EFAULT;
+			}
+			return 0;
+		case TCFLSH:
+			return tty_perform_flush(linux_tty, arg);
+		}
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int add_tty(int j,
+		    struct ipw_hardware *hardware,
+		    struct ipw_network *network, int channel_idx,
+		    int secondary_channel_idx, int tty_type)
+{
+	ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL);
+	if (!ttys[j])
+		return -ENOMEM;
+	ttys[j]->index = j;
+	ttys[j]->hardware = hardware;
+	ttys[j]->channel_idx = channel_idx;
+	ttys[j]->secondary_channel_idx = secondary_channel_idx;
+	ttys[j]->network = network;
+	ttys[j]->tty_type = tty_type;
+	mutex_init(&ttys[j]->ipw_tty_mutex);
+
+	tty_register_device(ipw_tty_driver, j, NULL);
+	ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
+
+	if (secondary_channel_idx != -1)
+		ipwireless_associate_network_tty(network,
+						 secondary_channel_idx,
+						 ttys[j]);
+	if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j])
+		report_registering(ttys[j]);
+	return 0;
+}
+
+struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware,
+				      struct ipw_network *network)
+{
+	int i, j;
+
+	for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) {
+		int allfree = 1;
+
+		for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
+				j += IPWIRELESS_PCMCIA_MINOR_RANGE)
+			if (ttys[j] != NULL) {
+				allfree = 0;
+				break;
+			}
+
+		if (allfree) {
+			j = i;
+
+			if (add_tty(j, hardware, network,
+					IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
+					TTYTYPE_MODEM))
+				return NULL;
+
+			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
+			if (add_tty(j, hardware, network,
+					IPW_CHANNEL_DIALLER, -1,
+					TTYTYPE_MONITOR))
+				return NULL;
+
+			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
+			if (add_tty(j, hardware, network,
+					IPW_CHANNEL_RAS, -1,
+					TTYTYPE_RAS_RAW))
+				return NULL;
+
+			return ttys[i];
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Must be called before ipwireless_network_free().
+ */
+void ipwireless_tty_free(struct ipw_tty *tty)
+{
+	int j;
+	struct ipw_network *network = ttys[tty->index]->network;
+
+	for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS;
+			j += IPWIRELESS_PCMCIA_MINOR_RANGE) {
+		struct ipw_tty *ttyj = ttys[j];
+
+		if (ttyj) {
+			mutex_lock(&ttyj->ipw_tty_mutex);
+			if (get_tty(j + ipw_tty_driver->minor_start) == ttyj)
+				report_deregistering(ttyj);
+			ttyj->closing = 1;
+			if (ttyj->linux_tty != NULL) {
+				mutex_unlock(&ttyj->ipw_tty_mutex);
+				tty_hangup(ttyj->linux_tty);
+				/* Wait till the tty_hangup has completed */
+				flush_work_sync(&ttyj->linux_tty->hangup_work);
+				/* FIXME: Exactly how is the tty object locked here
+				   against a parallel ioctl etc */
+				mutex_lock(&ttyj->ipw_tty_mutex);
+			}
+			while (ttyj->open_count)
+				do_ipw_close(ttyj);
+			ipwireless_disassociate_network_ttys(network,
+							     ttyj->channel_idx);
+			tty_unregister_device(ipw_tty_driver, j);
+			ttys[j] = NULL;
+			mutex_unlock(&ttyj->ipw_tty_mutex);
+			kfree(ttyj);
+		}
+	}
+}
+
+static const struct tty_operations tty_ops = {
+	.open = ipw_open,
+	.close = ipw_close,
+	.hangup = ipw_hangup,
+	.write = ipw_write,
+	.write_room = ipw_write_room,
+	.ioctl = ipw_ioctl,
+	.chars_in_buffer = ipw_chars_in_buffer,
+	.tiocmget = ipw_tiocmget,
+	.tiocmset = ipw_tiocmset,
+};
+
+int ipwireless_tty_init(void)
+{
+	int result;
+
+	ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
+	if (!ipw_tty_driver)
+		return -ENOMEM;
+
+	ipw_tty_driver->owner = THIS_MODULE;
+	ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
+	ipw_tty_driver->name = "ttyIPWp";
+	ipw_tty_driver->major = 0;
+	ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
+	ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	ipw_tty_driver->init_termios = tty_std_termios;
+	ipw_tty_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	ipw_tty_driver->init_termios.c_ispeed = 9600;
+	ipw_tty_driver->init_termios.c_ospeed = 9600;
+	tty_set_operations(ipw_tty_driver, &tty_ops);
+	result = tty_register_driver(ipw_tty_driver);
+	if (result) {
+		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+		       ": failed to register tty driver\n");
+		put_tty_driver(ipw_tty_driver);
+		return result;
+	}
+
+	return 0;
+}
+
+void ipwireless_tty_release(void)
+{
+	int ret;
+
+	ret = tty_unregister_driver(ipw_tty_driver);
+	put_tty_driver(ipw_tty_driver);
+	if (ret != 0)
+		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
+			": tty_unregister_driver failed with code %d\n", ret);
+}
+
+int ipwireless_tty_is_modem(struct ipw_tty *tty)
+{
+	return tty->tty_type == TTYTYPE_MODEM;
+}
+
+void
+ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
+					  unsigned int channel_idx,
+					  unsigned int control_lines,
+					  unsigned int changed_mask)
+{
+	unsigned int old_control_lines = tty->control_lines;
+
+	tty->control_lines = (tty->control_lines & ~changed_mask)
+		| (control_lines & changed_mask);
+
+	/*
+	 * If DCD is de-asserted, we close the tty so pppd can tell that we
+	 * have gone offline.
+	 */
+	if ((old_control_lines & IPW_CONTROL_LINE_DCD)
+			&& !(tty->control_lines & IPW_CONTROL_LINE_DCD)
+			&& tty->linux_tty) {
+		tty_hangup(tty->linux_tty);
+	}
+}
+
diff --git a/drivers/tty/ipwireless/tty.h b/drivers/tty/ipwireless/tty.h
new file mode 100644
index 0000000..747b2d6
--- /dev/null
+++ b/drivers/tty/ipwireless/tty.h
@@ -0,0 +1,45 @@
+/*
+ * IPWireless 3G PCMCIA Network Driver
+ *
+ * Original code
+ *   by Stephen Blackheath <stephen@blacksapphire.com>,
+ *      Ben Martel <benm@symmetric.co.nz>
+ *
+ * Copyrighted as follows:
+ *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
+ *
+ * Various driver changes and rewrites, port to new kernels
+ *   Copyright (C) 2006-2007 Jiri Kosina
+ *
+ * Misc code cleanups and updates
+ *   Copyright (C) 2007 David Sterba
+ */
+
+#ifndef _IPWIRELESS_CS_TTY_H_
+#define _IPWIRELESS_CS_TTY_H_
+
+#include <linux/types.h>
+#include <linux/sched.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+struct ipw_tty;
+struct ipw_network;
+struct ipw_hardware;
+
+int ipwireless_tty_init(void);
+void ipwireless_tty_release(void);
+
+struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw,
+				      struct ipw_network *net);
+void ipwireless_tty_free(struct ipw_tty *tty);
+void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
+			     unsigned int length);
+int ipwireless_tty_is_modem(struct ipw_tty *tty);
+void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
+					       unsigned int channel_idx,
+					       unsigned int control_lines,
+					       unsigned int changed_mask);
+
+#endif
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
new file mode 100644
index 0000000..db1cf9c
--- /dev/null
+++ b/drivers/tty/isicom.c
@@ -0,0 +1,1736 @@
+/*
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ *	Original driver code supplied by Multi-Tech
+ *
+ *	Changes
+ *	1/9/98	alan@lxorguk.ukuu.org.uk
+ *					Merge to 2.0.x kernel tree
+ *					Obtain and use official major/minors
+ *					Loader switched to a misc device
+ *					(fixed range check bug as a side effect)
+ *					Printk clean up
+ *	9/12/98	alan@lxorguk.ukuu.org.uk
+ *					Rough port to 2.1.x
+ *
+ *	10/6/99 sameer			Merged the ISA and PCI drivers to
+ *					a new unified driver.
+ *
+ *	3/9/99	sameer			Added support for ISI4616 cards.
+ *
+ *	16/9/99	sameer			We do not force RTS low anymore.
+ *					This is to prevent the firmware
+ *					from getting confused.
+ *
+ *	26/10/99 sameer			Cosmetic changes:The driver now
+ *					dumps the Port Count information
+ *					along with I/O address and IRQ.
+ *
+ *	13/12/99 sameer			Fixed the problem with IRQ sharing.
+ *
+ *	10/5/00  sameer			Fixed isicom_shutdown_board()
+ *					to not lower DTR on all the ports
+ *					when the last port on the card is
+ *					closed.
+ *
+ *	10/5/00  sameer			Signal mask setup command added
+ *					to  isicom_setup_port and
+ *					isicom_shutdown_port.
+ *
+ *	24/5/00  sameer			The driver is now SMP aware.
+ *
+ *
+ *	27/11/00 Vinayak P Risbud	Fixed the Driver Crash Problem
+ *
+ *
+ *	03/01/01  anil .s		Added support for resetting the
+ *					internal modems on ISI cards.
+ *
+ *	08/02/01  anil .s		Upgraded the driver for kernel
+ *					2.4.x
+ *
+ *	11/04/01  Kevin			Fixed firmware load problem with
+ *					ISIHP-4X card
+ *
+ *	30/04/01  anil .s		Fixed the remote login through
+ *					ISI port problem. Now the link
+ *					does not go down before password
+ *					prompt.
+ *
+ *	03/05/01  anil .s		Fixed the problem with IRQ sharing
+ *					among ISI-PCI cards.
+ *
+ *	03/05/01  anil .s		Added support to display the version
+ *					info during insmod as well as module
+ *					listing by lsmod.
+ *
+ *	10/05/01  anil .s		Done the modifications to the source
+ *					file and Install script so that the
+ *					same installation can be used for
+ *					2.2.x and 2.4.x kernel.
+ *
+ *	06/06/01  anil .s		Now we drop both dtr and rts during
+ *					shutdown_port as well as raise them
+ *					during isicom_config_port.
+ *
+ *	09/06/01 acme@conectiva.com.br	use capable, not suser, do
+ *					restore_flags on failure in
+ *					isicom_send_break, verify put_user
+ *					result
+ *
+ *	11/02/03  ranjeeth		Added support for 230 Kbps and 460 Kbps
+ *					Baud index extended to 21
+ *
+ *	20/03/03  ranjeeth		Made to work for Linux Advanced server.
+ *					Taken care of license warning.
+ *
+ *	10/12/03  Ravindra		Made to work for Fedora Core 1 of
+ *					Red Hat Distribution
+ *
+ *	06/01/05  Alan Cox 		Merged the ISI and base kernel strands
+ *					into a single 2.6 driver
+ *
+ *	***********************************************************
+ *
+ *	To use this driver you also need the support package. You
+ *	can find this in RPM format on
+ *		ftp://ftp.linux.org.uk/pub/linux/alan
+ *
+ *	You can find the original tools for this direct from Multitech
+ *		ftp://ftp.multitech.com/ISI-Cards/
+ *
+ *	Having installed the cards the module options (/etc/modprobe.conf)
+ *
+ *	options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
+ *
+ *	Omit those entries for boards you don't have installed.
+ *
+ *	TODO
+ *		Merge testing
+ *		64-bit verification
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/termios.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/system.h>
+
+#include <linux/pci.h>
+
+#include <linux/isicom.h>
+
+#define InterruptTheCard(base) outw(0, (base) + 0xc)
+#define ClearInterrupt(base) inw((base) + 0x0a)
+
+#ifdef DEBUG
+#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
+#else
+#define isicom_paranoia_check(a, b, c) 0
+#endif
+
+static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
+static void __devexit isicom_remove(struct pci_dev *);
+
+static struct pci_device_id isicom_pci_tbl[] = {
+	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2051) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2052) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2053) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2054) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2055) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2056) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2057) },
+	{ PCI_DEVICE(VENDOR_ID, 0x2058) },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
+
+static struct pci_driver isicom_driver = {
+	.name		= "isicom",
+	.id_table	= isicom_pci_tbl,
+	.probe		= isicom_probe,
+	.remove		= __devexit_p(isicom_remove)
+};
+
+static int prev_card = 3;	/*	start servicing isi_card[0]	*/
+static struct tty_driver *isicom_normal;
+
+static void isicom_tx(unsigned long _data);
+static void isicom_start(struct tty_struct *tty);
+
+static DEFINE_TIMER(tx, isicom_tx, 0, 0);
+
+/*   baud index mappings from linux defns to isi */
+
+static signed char linuxb_to_isib[] = {
+	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
+};
+
+struct	isi_board {
+	unsigned long		base;
+	int			irq;
+	unsigned char		port_count;
+	unsigned short		status;
+	unsigned short		port_status; /* each bit for each port */
+	unsigned short		shift_count;
+	struct isi_port		*ports;
+	signed char		count;
+	spinlock_t		card_lock; /* Card wide lock 11/5/00 -sameer */
+	unsigned long		flags;
+	unsigned int		index;
+};
+
+struct	isi_port {
+	unsigned short		magic;
+	struct tty_port		port;
+	u16			channel;
+	u16			status;
+	struct isi_board	*card;
+	unsigned char		*xmit_buf;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+};
+
+static struct isi_board isi_card[BOARD_COUNT];
+static struct isi_port  isi_ports[PORT_COUNT];
+
+/*
+ *	Locking functions for card level locking. We need to own both
+ *	the kernel lock for the card and have the card in a position that
+ *	it wants to talk.
+ */
+
+static inline int WaitTillCardIsFree(unsigned long base)
+{
+	unsigned int count = 0;
+	unsigned int a = in_atomic(); /* do we run under spinlock? */
+
+	while (!(inw(base + 0xe) & 0x1) && count++ < 100)
+		if (a)
+			mdelay(1);
+		else
+			msleep(1);
+
+	return !(inw(base + 0xe) & 0x1);
+}
+
+static int lock_card(struct isi_board *card)
+{
+	unsigned long base = card->base;
+	unsigned int retries, a;
+
+	for (retries = 0; retries < 10; retries++) {
+		spin_lock_irqsave(&card->card_lock, card->flags);
+		for (a = 0; a < 10; a++) {
+			if (inw(base + 0xe) & 0x1)
+				return 1;
+			udelay(10);
+		}
+		spin_unlock_irqrestore(&card->card_lock, card->flags);
+		msleep(10);
+	}
+	pr_warning("Failed to lock Card (0x%lx)\n", card->base);
+
+	return 0;	/* Failed to acquire the card! */
+}
+
+static void unlock_card(struct isi_board *card)
+{
+	spin_unlock_irqrestore(&card->card_lock, card->flags);
+}
+
+/*
+ *  ISI Card specific ops ...
+ */
+
+/* card->lock HAS to be held */
+static void raise_dtr(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
+
+	if (WaitTillCardIsFree(base))
+		return;
+
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+	outw(0x0504, base);
+	InterruptTheCard(base);
+	port->status |= ISI_DTR;
+}
+
+/* card->lock HAS to be held */
+static inline void drop_dtr(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
+
+	if (WaitTillCardIsFree(base))
+		return;
+
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+	outw(0x0404, base);
+	InterruptTheCard(base);
+	port->status &= ~ISI_DTR;
+}
+
+/* card->lock HAS to be held */
+static inline void raise_rts(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
+
+	if (WaitTillCardIsFree(base))
+		return;
+
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+	outw(0x0a04, base);
+	InterruptTheCard(base);
+	port->status |= ISI_RTS;
+}
+
+/* card->lock HAS to be held */
+static inline void drop_rts(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
+
+	if (WaitTillCardIsFree(base))
+		return;
+
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+	outw(0x0804, base);
+	InterruptTheCard(base);
+	port->status &= ~ISI_RTS;
+}
+
+/* card->lock MUST NOT be held */
+
+static void isicom_dtr_rts(struct tty_port *port, int on)
+{
+	struct isi_port *ip = container_of(port, struct isi_port, port);
+	struct isi_board *card = ip->card;
+	unsigned long base = card->base;
+	u16 channel = ip->channel;
+
+	if (!lock_card(card))
+		return;
+
+	if (on) {
+		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+		outw(0x0f04, base);
+		InterruptTheCard(base);
+		ip->status |= (ISI_DTR | ISI_RTS);
+	} else {
+		outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+		outw(0x0C04, base);
+		InterruptTheCard(base);
+		ip->status &= ~(ISI_DTR | ISI_RTS);
+	}
+	unlock_card(card);
+}
+
+/* card->lock HAS to be held */
+static void drop_dtr_rts(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+	u16 channel = port->channel;
+
+	if (WaitTillCardIsFree(base))
+		return;
+
+	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
+	outw(0x0c04, base);
+	InterruptTheCard(base);
+	port->status &= ~(ISI_RTS | ISI_DTR);
+}
+
+/*
+ *	ISICOM Driver specific routines ...
+ *
+ */
+
+static inline int __isicom_paranoia_check(struct isi_port const *port,
+	char *name, const char *routine)
+{
+	if (!port) {
+		pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
+			   name, routine);
+		return 1;
+	}
+	if (port->magic != ISICOM_MAGIC) {
+		pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
+			   name, routine);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ *	Transmitter.
+ *
+ *	We shovel data into the card buffers on a regular basis. The card
+ *	will do the rest of the work for us.
+ */
+
+static void isicom_tx(unsigned long _data)
+{
+	unsigned long flags, base;
+	unsigned int retries;
+	short count = (BOARD_COUNT-1), card;
+	short txcount, wrd, residue, word_count, cnt;
+	struct isi_port *port;
+	struct tty_struct *tty;
+
+	/*	find next active board	*/
+	card = (prev_card + 1) & 0x0003;
+	while (count-- > 0) {
+		if (isi_card[card].status & BOARD_ACTIVE)
+			break;
+		card = (card + 1) & 0x0003;
+	}
+	if (!(isi_card[card].status & BOARD_ACTIVE))
+		goto sched_again;
+
+	prev_card = card;
+
+	count = isi_card[card].port_count;
+	port = isi_card[card].ports;
+	base = isi_card[card].base;
+
+	spin_lock_irqsave(&isi_card[card].card_lock, flags);
+	for (retries = 0; retries < 100; retries++) {
+		if (inw(base + 0xe) & 0x1)
+			break;
+		udelay(2);
+	}
+	if (retries >= 100)
+		goto unlock;
+
+	tty = tty_port_tty_get(&port->port);
+	if (tty == NULL)
+		goto put_unlock;
+
+	for (; count > 0; count--, port++) {
+		/* port not active or tx disabled to force flow control */
+		if (!(port->port.flags & ASYNC_INITIALIZED) ||
+				!(port->status & ISI_TXOK))
+			continue;
+
+		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
+		if (txcount <= 0 || tty->stopped || tty->hw_stopped)
+			continue;
+
+		if (!(inw(base + 0x02) & (1 << port->channel)))
+			continue;
+
+		pr_debug("txing %d bytes, port%d.\n",
+			 txcount, port->channel + 1);
+		outw((port->channel << isi_card[card].shift_count) | txcount,
+			base);
+		residue = NO;
+		wrd = 0;
+		while (1) {
+			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
+					- port->xmit_tail));
+			if (residue == YES) {
+				residue = NO;
+				if (cnt > 0) {
+					wrd |= (port->port.xmit_buf[port->xmit_tail]
+									<< 8);
+					port->xmit_tail = (port->xmit_tail + 1)
+						& (SERIAL_XMIT_SIZE - 1);
+					port->xmit_cnt--;
+					txcount--;
+					cnt--;
+					outw(wrd, base);
+				} else {
+					outw(wrd, base);
+					break;
+				}
+			}
+			if (cnt <= 0)
+				break;
+			word_count = cnt >> 1;
+			outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
+			port->xmit_tail = (port->xmit_tail
+				+ (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
+			txcount -= (word_count << 1);
+			port->xmit_cnt -= (word_count << 1);
+			if (cnt & 0x0001) {
+				residue = YES;
+				wrd = port->port.xmit_buf[port->xmit_tail];
+				port->xmit_tail = (port->xmit_tail + 1)
+					& (SERIAL_XMIT_SIZE - 1);
+				port->xmit_cnt--;
+				txcount--;
+			}
+		}
+
+		InterruptTheCard(base);
+		if (port->xmit_cnt <= 0)
+			port->status &= ~ISI_TXOK;
+		if (port->xmit_cnt <= WAKEUP_CHARS)
+			tty_wakeup(tty);
+	}
+
+put_unlock:
+	tty_kref_put(tty);
+unlock:
+	spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
+	/*	schedule another tx for hopefully in about 10ms	*/
+sched_again:
+	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
+}
+
+/*
+ *	Main interrupt handler routine
+ */
+
+static irqreturn_t isicom_interrupt(int irq, void *dev_id)
+{
+	struct isi_board *card = dev_id;
+	struct isi_port *port;
+	struct tty_struct *tty;
+	unsigned long base;
+	u16 header, word_count, count, channel;
+	short byte_count;
+	unsigned char *rp;
+
+	if (!card || !(card->status & FIRMWARE_LOADED))
+		return IRQ_NONE;
+
+	base = card->base;
+
+	/* did the card interrupt us? */
+	if (!(inw(base + 0x0e) & 0x02))
+		return IRQ_NONE;
+
+	spin_lock(&card->card_lock);
+
+	/*
+	 * disable any interrupts from the PCI card and lower the
+	 * interrupt line
+	 */
+	outw(0x8000, base+0x04);
+	ClearInterrupt(base);
+
+	inw(base);		/* get the dummy word out */
+	header = inw(base);
+	channel = (header & 0x7800) >> card->shift_count;
+	byte_count = header & 0xff;
+
+	if (channel + 1 > card->port_count) {
+		pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
+			   __func__, base, channel+1);
+		outw(0x0000, base+0x04); /* enable interrupts */
+		spin_unlock(&card->card_lock);
+		return IRQ_HANDLED;
+	}
+	port = card->ports + channel;
+	if (!(port->port.flags & ASYNC_INITIALIZED)) {
+		outw(0x0000, base+0x04); /* enable interrupts */
+		spin_unlock(&card->card_lock);
+		return IRQ_HANDLED;
+	}
+
+	tty = tty_port_tty_get(&port->port);
+	if (tty == NULL) {
+		word_count = byte_count >> 1;
+		while (byte_count > 1) {
+			inw(base);
+			byte_count -= 2;
+		}
+		if (byte_count & 0x01)
+			inw(base);
+		outw(0x0000, base+0x04); /* enable interrupts */
+		spin_unlock(&card->card_lock);
+		return IRQ_HANDLED;
+	}
+
+	if (header & 0x8000) {		/* Status Packet */
+		header = inw(base);
+		switch (header & 0xff) {
+		case 0:	/* Change in EIA signals */
+			if (port->port.flags & ASYNC_CHECK_CD) {
+				if (port->status & ISI_DCD) {
+					if (!(header & ISI_DCD)) {
+					/* Carrier has been lost  */
+						pr_debug("%s: DCD->low.\n",
+							 __func__);
+						port->status &= ~ISI_DCD;
+						tty_hangup(tty);
+					}
+				} else if (header & ISI_DCD) {
+				/* Carrier has been detected */
+					pr_debug("%s: DCD->high.\n",
+						__func__);
+					port->status |= ISI_DCD;
+					wake_up_interruptible(&port->port.open_wait);
+				}
+			} else {
+				if (header & ISI_DCD)
+					port->status |= ISI_DCD;
+				else
+					port->status &= ~ISI_DCD;
+			}
+
+			if (port->port.flags & ASYNC_CTS_FLOW) {
+				if (tty->hw_stopped) {
+					if (header & ISI_CTS) {
+						port->port.tty->hw_stopped = 0;
+						/* start tx ing */
+						port->status |= (ISI_TXOK
+							| ISI_CTS);
+						tty_wakeup(tty);
+					}
+				} else if (!(header & ISI_CTS)) {
+					tty->hw_stopped = 1;
+					/* stop tx ing */
+					port->status &= ~(ISI_TXOK | ISI_CTS);
+				}
+			} else {
+				if (header & ISI_CTS)
+					port->status |= ISI_CTS;
+				else
+					port->status &= ~ISI_CTS;
+			}
+
+			if (header & ISI_DSR)
+				port->status |= ISI_DSR;
+			else
+				port->status &= ~ISI_DSR;
+
+			if (header & ISI_RI)
+				port->status |= ISI_RI;
+			else
+				port->status &= ~ISI_RI;
+
+			break;
+
+		case 1:	/* Received Break !!! */
+			tty_insert_flip_char(tty, 0, TTY_BREAK);
+			if (port->port.flags & ASYNC_SAK)
+				do_SAK(tty);
+			tty_flip_buffer_push(tty);
+			break;
+
+		case 2:	/* Statistics		 */
+			pr_debug("%s: stats!!!\n", __func__);
+			break;
+
+		default:
+			pr_debug("%s: Unknown code in status packet.\n",
+				 __func__);
+			break;
+		}
+	} else {				/* Data   Packet */
+
+		count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
+		pr_debug("%s: Can rx %d of %d bytes.\n",
+			 __func__, count, byte_count);
+		word_count = count >> 1;
+		insw(base, rp, word_count);
+		byte_count -= (word_count << 1);
+		if (count & 0x0001) {
+			tty_insert_flip_char(tty,  inw(base) & 0xff,
+				TTY_NORMAL);
+			byte_count -= 2;
+		}
+		if (byte_count > 0) {
+			pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
+				 __func__, base, channel + 1);
+		/* drain out unread xtra data */
+		while (byte_count > 0) {
+				inw(base);
+				byte_count -= 2;
+			}
+		}
+		tty_flip_buffer_push(tty);
+	}
+	outw(0x0000, base+0x04); /* enable interrupts */
+	spin_unlock(&card->card_lock);
+	tty_kref_put(tty);
+
+	return IRQ_HANDLED;
+}
+
+static void isicom_config_port(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+	unsigned long baud;
+	unsigned long base = card->base;
+	u16 channel_setup, channel = port->channel,
+		shift_count = card->shift_count;
+	unsigned char flow_ctrl;
+
+	/* FIXME: Switch to new tty baud API */
+	baud = C_BAUD(tty);
+	if (baud & CBAUDEX) {
+		baud &= ~CBAUDEX;
+
+		/*  if CBAUDEX bit is on and the baud is set to either 50 or 75
+		 *  then the card is programmed for 57.6Kbps or 115Kbps
+		 *  respectively.
+		 */
+
+		/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
+		if (baud < 1 || baud > 4)
+			tty->termios->c_cflag &= ~CBAUDEX;
+		else
+			baud += 15;
+	}
+	if (baud == 15) {
+
+		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
+		 *  by the set_serial_info ioctl ... this is done by
+		 *  the 'setserial' utility.
+		 */
+
+		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			baud++; /*  57.6 Kbps */
+		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			baud += 2; /*  115  Kbps */
+		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			baud += 3; /* 230 kbps*/
+		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			baud += 4; /* 460 kbps*/
+	}
+	if (linuxb_to_isib[baud] == -1) {
+		/* hang up */
+		drop_dtr(port);
+		return;
+	} else
+		raise_dtr(port);
+
+	if (WaitTillCardIsFree(base) == 0) {
+		outw(0x8000 | (channel << shift_count) | 0x03, base);
+		outw(linuxb_to_isib[baud] << 8 | 0x03, base);
+		channel_setup = 0;
+		switch (C_CSIZE(tty)) {
+		case CS5:
+			channel_setup |= ISICOM_CS5;
+			break;
+		case CS6:
+			channel_setup |= ISICOM_CS6;
+			break;
+		case CS7:
+			channel_setup |= ISICOM_CS7;
+			break;
+		case CS8:
+			channel_setup |= ISICOM_CS8;
+			break;
+		}
+
+		if (C_CSTOPB(tty))
+			channel_setup |= ISICOM_2SB;
+		if (C_PARENB(tty)) {
+			channel_setup |= ISICOM_EVPAR;
+			if (C_PARODD(tty))
+				channel_setup |= ISICOM_ODPAR;
+		}
+		outw(channel_setup, base);
+		InterruptTheCard(base);
+	}
+	if (C_CLOCAL(tty))
+		port->port.flags &= ~ASYNC_CHECK_CD;
+	else
+		port->port.flags |= ASYNC_CHECK_CD;
+
+	/* flow control settings ...*/
+	flow_ctrl = 0;
+	port->port.flags &= ~ASYNC_CTS_FLOW;
+	if (C_CRTSCTS(tty)) {
+		port->port.flags |= ASYNC_CTS_FLOW;
+		flow_ctrl |= ISICOM_CTSRTS;
+	}
+	if (I_IXON(tty))
+		flow_ctrl |= ISICOM_RESPOND_XONXOFF;
+	if (I_IXOFF(tty))
+		flow_ctrl |= ISICOM_INITIATE_XONXOFF;
+
+	if (WaitTillCardIsFree(base) == 0) {
+		outw(0x8000 | (channel << shift_count) | 0x04, base);
+		outw(flow_ctrl << 8 | 0x05, base);
+		outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
+		InterruptTheCard(base);
+	}
+
+	/*	rx enabled -> enable port for rx on the card	*/
+	if (C_CREAD(tty)) {
+		card->port_status |= (1 << channel);
+		outw(card->port_status, base + 0x02);
+	}
+}
+
+/* open et all */
+
+static inline void isicom_setup_board(struct isi_board *bp)
+{
+	int channel;
+	struct isi_port *port;
+
+	bp->count++;
+	if (!(bp->status & BOARD_INIT)) {
+		port = bp->ports;
+		for (channel = 0; channel < bp->port_count; channel++, port++)
+			drop_dtr_rts(port);
+	}
+	bp->status |= BOARD_ACTIVE | BOARD_INIT;
+}
+
+/* Activate and thus setup board are protected from races against shutdown
+   by the tty_port mutex */
+
+static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
+{
+	struct isi_port *port = container_of(tport, struct isi_port, port);
+	struct isi_board *card = port->card;
+	unsigned long flags;
+
+	if (tty_port_alloc_xmit_buf(tport) < 0)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+	isicom_setup_board(card);
+
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+
+	/*	discard any residual data	*/
+	if (WaitTillCardIsFree(card->base) == 0) {
+		outw(0x8000 | (port->channel << card->shift_count) | 0x02,
+				card->base);
+		outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
+		InterruptTheCard(card->base);
+	}
+	isicom_config_port(tty);
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+	return 0;
+}
+
+static int isicom_carrier_raised(struct tty_port *port)
+{
+	struct isi_port *ip = container_of(port, struct isi_port, port);
+	return (ip->status & ISI_DCD)?1 : 0;
+}
+
+static struct tty_port *isicom_find_port(struct tty_struct *tty)
+{
+	struct isi_port *port;
+	struct isi_board *card;
+	unsigned int board;
+	int line = tty->index;
+
+	if (line < 0 || line > PORT_COUNT-1)
+		return NULL;
+	board = BOARD(line);
+	card = &isi_card[board];
+
+	if (!(card->status & FIRMWARE_LOADED))
+		return NULL;
+
+	/*  open on a port greater than the port count for the card !!! */
+	if (line > ((board * 16) + card->port_count - 1))
+		return NULL;
+
+	port = &isi_ports[line];
+	if (isicom_paranoia_check(port, tty->name, "isicom_open"))
+		return NULL;
+
+	return &port->port;
+}
+
+static int isicom_open(struct tty_struct *tty, struct file *filp)
+{
+	struct isi_port *port;
+	struct tty_port *tport;
+
+	tport = isicom_find_port(tty);
+	if (tport == NULL)
+		return -ENODEV;
+	port = container_of(tport, struct isi_port, port);
+
+	tty->driver_data = port;
+	return tty_port_open(tport, tty, filp);
+}
+
+/* close et all */
+
+/* card->lock HAS to be held */
+static void isicom_shutdown_port(struct isi_port *port)
+{
+	struct isi_board *card = port->card;
+
+	if (--card->count < 0) {
+		pr_debug("%s: bad board(0x%lx) count %d.\n",
+			 __func__, card->base, card->count);
+		card->count = 0;
+	}
+	/* last port was closed, shutdown that board too */
+	if (!card->count)
+		card->status &= BOARD_ACTIVE;
+}
+
+static void isicom_flush_buffer(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+	unsigned long flags;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
+		return;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	spin_unlock_irqrestore(&card->card_lock, flags);
+
+	tty_wakeup(tty);
+}
+
+static void isicom_shutdown(struct tty_port *port)
+{
+	struct isi_port *ip = container_of(port, struct isi_port, port);
+	struct isi_board *card = ip->card;
+	unsigned long flags;
+
+	/* indicate to the card that no more data can be received
+	   on this port */
+	spin_lock_irqsave(&card->card_lock, flags);
+	card->port_status &= ~(1 << ip->channel);
+	outw(card->port_status, card->base + 0x02);
+	isicom_shutdown_port(ip);
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	tty_port_free_xmit_buf(port);
+}
+
+static void isicom_close(struct tty_struct *tty, struct file *filp)
+{
+	struct isi_port *ip = tty->driver_data;
+	struct tty_port *port;
+
+	if (ip == NULL)
+		return;
+
+	port = &ip->port;
+	if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
+		return;
+	tty_port_close(port, tty, filp);
+}
+
+/* write et all */
+static int isicom_write(struct tty_struct *tty,	const unsigned char *buf,
+	int count)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+	unsigned long flags;
+	int cnt, total = 0;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_write"))
+		return 0;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+
+	while (1) {
+		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
+				- 1, SERIAL_XMIT_SIZE - port->xmit_head));
+		if (cnt <= 0)
+			break;
+
+		memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
+		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
+			- 1);
+		port->xmit_cnt += cnt;
+		buf += cnt;
+		count -= cnt;
+		total += cnt;
+	}
+	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
+		port->status |= ISI_TXOK;
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	return total;
+}
+
+/* put_char et all */
+static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+	unsigned long flags;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
+		return 0;
+
+	spin_lock_irqsave(&card->card_lock, flags);
+	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+		spin_unlock_irqrestore(&card->card_lock, flags);
+		return 0;
+	}
+
+	port->port.xmit_buf[port->xmit_head++] = ch;
+	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
+	port->xmit_cnt++;
+	spin_unlock_irqrestore(&card->card_lock, flags);
+	return 1;
+}
+
+/* flush_chars et all */
+static void isicom_flush_chars(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
+		return;
+
+	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+			!port->port.xmit_buf)
+		return;
+
+	/* this tells the transmitter to consider this port for
+	   data output to the card ... that's the best we can do. */
+	port->status |= ISI_TXOK;
+}
+
+/* write_room et all */
+static int isicom_write_room(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	int free;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
+		return 0;
+
+	free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+	if (free < 0)
+		free = 0;
+	return free;
+}
+
+/* chars_in_buffer et all */
+static int isicom_chars_in_buffer(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
+		return 0;
+	return port->xmit_cnt;
+}
+
+/* ioctl et all */
+static int isicom_send_break(struct tty_struct *tty, int length)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+	unsigned long base = card->base;
+
+	if (length == -1)
+		return -EOPNOTSUPP;
+
+	if (!lock_card(card))
+		return -EINVAL;
+
+	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
+	outw((length & 0xff) << 8 | 0x00, base);
+	outw((length & 0xff00), base);
+	InterruptTheCard(base);
+
+	unlock_card(card);
+	return 0;
+}
+
+static int isicom_tiocmget(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	/* just send the port status */
+	u16 status = port->status;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+		return -ENODEV;
+
+	return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
+		((status & ISI_DTR) ? TIOCM_DTR : 0) |
+		((status & ISI_DCD) ? TIOCM_CAR : 0) |
+		((status & ISI_DSR) ? TIOCM_DSR : 0) |
+		((status & ISI_CTS) ? TIOCM_CTS : 0) |
+		((status & ISI_RI ) ? TIOCM_RI  : 0);
+}
+
+static int isicom_tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear)
+{
+	struct isi_port *port = tty->driver_data;
+	unsigned long flags;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+		return -ENODEV;
+
+	spin_lock_irqsave(&port->card->card_lock, flags);
+	if (set & TIOCM_RTS)
+		raise_rts(port);
+	if (set & TIOCM_DTR)
+		raise_dtr(port);
+
+	if (clear & TIOCM_RTS)
+		drop_rts(port);
+	if (clear & TIOCM_DTR)
+		drop_dtr(port);
+	spin_unlock_irqrestore(&port->card->card_lock, flags);
+
+	return 0;
+}
+
+static int isicom_set_serial_info(struct tty_struct *tty,
+					struct serial_struct __user *info)
+{
+	struct isi_port *port = tty->driver_data;
+	struct serial_struct newinfo;
+	int reconfig_port;
+
+	if (copy_from_user(&newinfo, info, sizeof(newinfo)))
+		return -EFAULT;
+
+	mutex_lock(&port->port.mutex);
+	reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
+		(newinfo.flags & ASYNC_SPD_MASK));
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((newinfo.close_delay != port->port.close_delay) ||
+				(newinfo.closing_wait != port->port.closing_wait) ||
+				((newinfo.flags & ~ASYNC_USR_MASK) !=
+				(port->port.flags & ~ASYNC_USR_MASK))) {
+			mutex_unlock(&port->port.mutex);
+			return -EPERM;
+		}
+		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
+				(newinfo.flags & ASYNC_USR_MASK));
+	} else {
+		port->port.close_delay = newinfo.close_delay;
+		port->port.closing_wait = newinfo.closing_wait;
+		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
+				(newinfo.flags & ASYNC_FLAGS));
+	}
+	if (reconfig_port) {
+		unsigned long flags;
+		spin_lock_irqsave(&port->card->card_lock, flags);
+		isicom_config_port(tty);
+		spin_unlock_irqrestore(&port->card->card_lock, flags);
+	}
+	mutex_unlock(&port->port.mutex);
+	return 0;
+}
+
+static int isicom_get_serial_info(struct isi_port *port,
+	struct serial_struct __user *info)
+{
+	struct serial_struct out_info;
+
+	mutex_lock(&port->port.mutex);
+	memset(&out_info, 0, sizeof(out_info));
+/*	out_info.type = ? */
+	out_info.line = port - isi_ports;
+	out_info.port = port->card->base;
+	out_info.irq = port->card->irq;
+	out_info.flags = port->port.flags;
+/*	out_info.baud_base = ? */
+	out_info.close_delay = port->port.close_delay;
+	out_info.closing_wait = port->port.closing_wait;
+	mutex_unlock(&port->port.mutex);
+	if (copy_to_user(info, &out_info, sizeof(out_info)))
+		return -EFAULT;
+	return 0;
+}
+
+static int isicom_ioctl(struct tty_struct *tty,
+	unsigned int cmd, unsigned long arg)
+{
+	struct isi_port *port = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
+		return -ENODEV;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		return isicom_get_serial_info(port, argp);
+
+	case TIOCSSERIAL:
+		return isicom_set_serial_info(tty, argp);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+/* set_termios et all */
+static void isicom_set_termios(struct tty_struct *tty,
+	struct ktermios *old_termios)
+{
+	struct isi_port *port = tty->driver_data;
+	unsigned long flags;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
+		return;
+
+	if (tty->termios->c_cflag == old_termios->c_cflag &&
+			tty->termios->c_iflag == old_termios->c_iflag)
+		return;
+
+	spin_lock_irqsave(&port->card->card_lock, flags);
+	isicom_config_port(tty);
+	spin_unlock_irqrestore(&port->card->card_lock, flags);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		isicom_start(tty);
+	}
+}
+
+/* throttle et all */
+static void isicom_throttle(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
+		return;
+
+	/* tell the card that this port cannot handle any more data for now */
+	card->port_status &= ~(1 << port->channel);
+	outw(card->port_status, card->base + 0x02);
+}
+
+/* unthrottle et all */
+static void isicom_unthrottle(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+	struct isi_board *card = port->card;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
+		return;
+
+	/* tell the card that this port is ready to accept more data */
+	card->port_status |= (1 << port->channel);
+	outw(card->port_status, card->base + 0x02);
+}
+
+/* stop et all */
+static void isicom_stop(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
+		return;
+
+	/* this tells the transmitter not to consider this port for
+	   data output to the card. */
+	port->status &= ~ISI_TXOK;
+}
+
+/* start et all */
+static void isicom_start(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_start"))
+		return;
+
+	/* this tells the transmitter to consider this port for
+	   data output to the card. */
+	port->status |= ISI_TXOK;
+}
+
+static void isicom_hangup(struct tty_struct *tty)
+{
+	struct isi_port *port = tty->driver_data;
+
+	if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
+		return;
+	tty_port_hangup(&port->port);
+}
+
+
+/*
+ * Driver init and deinit functions
+ */
+
+static const struct tty_operations isicom_ops = {
+	.open			= isicom_open,
+	.close			= isicom_close,
+	.write			= isicom_write,
+	.put_char		= isicom_put_char,
+	.flush_chars		= isicom_flush_chars,
+	.write_room		= isicom_write_room,
+	.chars_in_buffer	= isicom_chars_in_buffer,
+	.ioctl			= isicom_ioctl,
+	.set_termios		= isicom_set_termios,
+	.throttle		= isicom_throttle,
+	.unthrottle		= isicom_unthrottle,
+	.stop			= isicom_stop,
+	.start			= isicom_start,
+	.hangup			= isicom_hangup,
+	.flush_buffer		= isicom_flush_buffer,
+	.tiocmget		= isicom_tiocmget,
+	.tiocmset		= isicom_tiocmset,
+	.break_ctl		= isicom_send_break,
+};
+
+static const struct tty_port_operations isicom_port_ops = {
+	.carrier_raised		= isicom_carrier_raised,
+	.dtr_rts		= isicom_dtr_rts,
+	.activate		= isicom_activate,
+	.shutdown		= isicom_shutdown,
+};
+
+static int __devinit reset_card(struct pci_dev *pdev,
+	const unsigned int card, unsigned int *signature)
+{
+	struct isi_board *board = pci_get_drvdata(pdev);
+	unsigned long base = board->base;
+	unsigned int sig, portcount = 0;
+	int retval = 0;
+
+	dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
+		base);
+
+	inw(base + 0x8);
+
+	msleep(10);
+
+	outw(0, base + 0x8); /* Reset */
+
+	msleep(1000);
+
+	sig = inw(base + 0x4) & 0xff;
+
+	if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
+			sig != 0xee) {
+		dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
+			"bad I/O Port Address 0x%lx).\n", card + 1, base);
+		dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
+		retval = -EIO;
+		goto end;
+	}
+
+	msleep(10);
+
+	portcount = inw(base + 0x2);
+	if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
+				portcount != 8 && portcount != 16)) {
+		dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
+			card + 1);
+		retval = -EIO;
+		goto end;
+	}
+
+	switch (sig) {
+	case 0xa5:
+	case 0xbb:
+	case 0xdd:
+		board->port_count = (portcount == 4) ? 4 : 8;
+		board->shift_count = 12;
+		break;
+	case 0xcc:
+	case 0xee:
+		board->port_count = 16;
+		board->shift_count = 11;
+		break;
+	}
+	dev_info(&pdev->dev, "-Done\n");
+	*signature = sig;
+
+end:
+	return retval;
+}
+
+static int __devinit load_firmware(struct pci_dev *pdev,
+	const unsigned int index, const unsigned int signature)
+{
+	struct isi_board *board = pci_get_drvdata(pdev);
+	const struct firmware *fw;
+	unsigned long base = board->base;
+	unsigned int a;
+	u16 word_count, status;
+	int retval = -EIO;
+	char *name;
+	u8 *data;
+
+	struct stframe {
+		u16	addr;
+		u16	count;
+		u8	data[0];
+	} *frame;
+
+	switch (signature) {
+	case 0xa5:
+		name = "isi608.bin";
+		break;
+	case 0xbb:
+		name = "isi608em.bin";
+		break;
+	case 0xcc:
+		name = "isi616em.bin";
+		break;
+	case 0xdd:
+		name = "isi4608.bin";
+		break;
+	case 0xee:
+		name = "isi4616.bin";
+		break;
+	default:
+		dev_err(&pdev->dev, "Unknown signature.\n");
+		goto end;
+	}
+
+	retval = request_firmware(&fw, name, &pdev->dev);
+	if (retval)
+		goto end;
+
+	retval = -EIO;
+
+	for (frame = (struct stframe *)fw->data;
+			frame < (struct stframe *)(fw->data + fw->size);
+			frame = (struct stframe *)((u8 *)(frame + 1) +
+				frame->count)) {
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		outw(0xf0, base);	/* start upload sequence */
+		outw(0x00, base);
+		outw(frame->addr, base); /* lsb of address */
+
+		word_count = frame->count / 2 + frame->count % 2;
+		outw(word_count, base);
+		InterruptTheCard(base);
+
+		udelay(100); /* 0x2f */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		status = inw(base + 0x4);
+		if (status != 0) {
+			dev_warn(&pdev->dev, "Card%d rejected load header:\n"
+				 "Address:0x%x\n"
+				 "Count:0x%x\n"
+				 "Status:0x%x\n",
+				 index + 1, frame->addr, frame->count, status);
+			goto errrelfw;
+		}
+		outsw(base, frame->data, word_count);
+
+		InterruptTheCard(base);
+
+		udelay(50); /* 0x0f */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		status = inw(base + 0x4);
+		if (status != 0) {
+			dev_err(&pdev->dev, "Card%d got out of sync.Card "
+				"Status:0x%x\n", index + 1, status);
+			goto errrelfw;
+		}
+	}
+
+/* XXX: should we test it by reading it back and comparing with original like
+ * in load firmware package? */
+	for (frame = (struct stframe *)fw->data;
+			frame < (struct stframe *)(fw->data + fw->size);
+			frame = (struct stframe *)((u8 *)(frame + 1) +
+				frame->count)) {
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		outw(0xf1, base); /* start download sequence */
+		outw(0x00, base);
+		outw(frame->addr, base); /* lsb of address */
+
+		word_count = (frame->count >> 1) + frame->count % 2;
+		outw(word_count + 1, base);
+		InterruptTheCard(base);
+
+		udelay(50); /* 0xf */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		status = inw(base + 0x4);
+		if (status != 0) {
+			dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
+				 "Address:0x%x\n"
+				 "Count:0x%x\n"
+				 "Status: 0x%x\n",
+				 index + 1, frame->addr, frame->count, status);
+			goto errrelfw;
+		}
+
+		data = kmalloc(word_count * 2, GFP_KERNEL);
+		if (data == NULL) {
+			dev_err(&pdev->dev, "Card%d, firmware upload "
+				"failed, not enough memory\n", index + 1);
+			goto errrelfw;
+		}
+		inw(base);
+		insw(base, data, word_count);
+		InterruptTheCard(base);
+
+		for (a = 0; a < frame->count; a++)
+			if (data[a] != frame->data[a]) {
+				kfree(data);
+				dev_err(&pdev->dev, "Card%d, firmware upload "
+					"failed\n", index + 1);
+				goto errrelfw;
+			}
+		kfree(data);
+
+		udelay(50); /* 0xf */
+
+		if (WaitTillCardIsFree(base))
+			goto errrelfw;
+
+		status = inw(base + 0x4);
+		if (status != 0) {
+			dev_err(&pdev->dev, "Card%d verify got out of sync. "
+				"Card Status:0x%x\n", index + 1, status);
+			goto errrelfw;
+		}
+	}
+
+	/* xfer ctrl */
+	if (WaitTillCardIsFree(base))
+		goto errrelfw;
+
+	outw(0xf2, base);
+	outw(0x800, base);
+	outw(0x0, base);
+	outw(0x0, base);
+	InterruptTheCard(base);
+	outw(0x0, base + 0x4); /* for ISI4608 cards */
+
+	board->status |= FIRMWARE_LOADED;
+	retval = 0;
+
+errrelfw:
+	release_firmware(fw);
+end:
+	return retval;
+}
+
+/*
+ *	Insmod can set static symbols so keep these static
+ */
+static unsigned int card_count;
+
+static int __devinit isicom_probe(struct pci_dev *pdev,
+	const struct pci_device_id *ent)
+{
+	unsigned int uninitialized_var(signature), index;
+	int retval = -EPERM;
+	struct isi_board *board = NULL;
+
+	if (card_count >= BOARD_COUNT)
+		goto err;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "failed to enable\n");
+		goto err;
+	}
+
+	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
+
+	/* allot the first empty slot in the array */
+	for (index = 0; index < BOARD_COUNT; index++) {
+		if (isi_card[index].base == 0) {
+			board = &isi_card[index];
+			break;
+		}
+	}
+	if (index == BOARD_COUNT) {
+		retval = -ENODEV;
+		goto err_disable;
+	}
+
+	board->index = index;
+	board->base = pci_resource_start(pdev, 3);
+	board->irq = pdev->irq;
+	card_count++;
+
+	pci_set_drvdata(pdev, board);
+
+	retval = pci_request_region(pdev, 3, ISICOM_NAME);
+	if (retval) {
+		dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
+			"will be disabled.\n", board->base, board->base + 15,
+			index + 1);
+		retval = -EBUSY;
+		goto errdec;
+	}
+
+	retval = request_irq(board->irq, isicom_interrupt,
+			IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
+	if (retval < 0) {
+		dev_err(&pdev->dev, "Could not install handler at Irq %d. "
+			"Card%d will be disabled.\n", board->irq, index + 1);
+		goto errunrr;
+	}
+
+	retval = reset_card(pdev, index, &signature);
+	if (retval < 0)
+		goto errunri;
+
+	retval = load_firmware(pdev, index, signature);
+	if (retval < 0)
+		goto errunri;
+
+	for (index = 0; index < board->port_count; index++)
+		tty_register_device(isicom_normal, board->index * 16 + index,
+				&pdev->dev);
+
+	return 0;
+
+errunri:
+	free_irq(board->irq, board);
+errunrr:
+	pci_release_region(pdev, 3);
+errdec:
+	board->base = 0;
+	card_count--;
+err_disable:
+	pci_disable_device(pdev);
+err:
+	return retval;
+}
+
+static void __devexit isicom_remove(struct pci_dev *pdev)
+{
+	struct isi_board *board = pci_get_drvdata(pdev);
+	unsigned int i;
+
+	for (i = 0; i < board->port_count; i++)
+		tty_unregister_device(isicom_normal, board->index * 16 + i);
+
+	free_irq(board->irq, board);
+	pci_release_region(pdev, 3);
+	board->base = 0;
+	card_count--;
+	pci_disable_device(pdev);
+}
+
+static int __init isicom_init(void)
+{
+	int retval, idx, channel;
+	struct isi_port *port;
+
+	for (idx = 0; idx < BOARD_COUNT; idx++) {
+		port = &isi_ports[idx * 16];
+		isi_card[idx].ports = port;
+		spin_lock_init(&isi_card[idx].card_lock);
+		for (channel = 0; channel < 16; channel++, port++) {
+			tty_port_init(&port->port);
+			port->port.ops = &isicom_port_ops;
+			port->magic = ISICOM_MAGIC;
+			port->card = &isi_card[idx];
+			port->channel = channel;
+			port->port.close_delay = 50 * HZ/100;
+			port->port.closing_wait = 3000 * HZ/100;
+			port->status = 0;
+			/*  . . .  */
+		}
+		isi_card[idx].base = 0;
+		isi_card[idx].irq = 0;
+	}
+
+	/* tty driver structure initialization */
+	isicom_normal = alloc_tty_driver(PORT_COUNT);
+	if (!isicom_normal) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	isicom_normal->owner			= THIS_MODULE;
+	isicom_normal->name 			= "ttyM";
+	isicom_normal->major			= ISICOM_NMAJOR;
+	isicom_normal->minor_start		= 0;
+	isicom_normal->type			= TTY_DRIVER_TYPE_SERIAL;
+	isicom_normal->subtype			= SERIAL_TYPE_NORMAL;
+	isicom_normal->init_termios		= tty_std_termios;
+	isicom_normal->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL |
+		CLOCAL;
+	isicom_normal->flags			= TTY_DRIVER_REAL_RAW |
+		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
+	tty_set_operations(isicom_normal, &isicom_ops);
+
+	retval = tty_register_driver(isicom_normal);
+	if (retval) {
+		pr_debug("Couldn't register the dialin driver\n");
+		goto err_puttty;
+	}
+
+	retval = pci_register_driver(&isicom_driver);
+	if (retval < 0) {
+		pr_err("Unable to register pci driver.\n");
+		goto err_unrtty;
+	}
+
+	mod_timer(&tx, jiffies + 1);
+
+	return 0;
+err_unrtty:
+	tty_unregister_driver(isicom_normal);
+err_puttty:
+	put_tty_driver(isicom_normal);
+error:
+	return retval;
+}
+
+static void __exit isicom_exit(void)
+{
+	del_timer_sync(&tx);
+
+	pci_unregister_driver(&isicom_driver);
+	tty_unregister_driver(isicom_normal);
+	put_tty_driver(isicom_normal);
+}
+
+module_init(isicom_init);
+module_exit(isicom_exit);
+
+MODULE_AUTHOR("MultiTech");
+MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("isi608.bin");
+MODULE_FIRMWARE("isi608em.bin");
+MODULE_FIRMWARE("isi616em.bin");
+MODULE_FIRMWARE("isi4608.bin");
+MODULE_FIRMWARE("isi4616.bin");
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
new file mode 100644
index 0000000..35b0c38
--- /dev/null
+++ b/drivers/tty/moxa.c
@@ -0,0 +1,2092 @@
+/*****************************************************************************/
+/*
+ *           moxa.c  -- MOXA Intellio family multiport serial driver.
+ *
+ *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com).
+ *      Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ *
+ *      This code is loosely based on the Linux serial driver, written by
+ *      Linus Torvalds, Theodore T'so and others.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ */
+
+/*
+ *    MOXA Intellio Series Driver
+ *      for             : LINUX
+ *      date            : 1999/1/7
+ *      version         : 5.1
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/firmware.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/serial.h>
+#include <linux/tty_driver.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "moxa.h"
+
+#define MOXA_VERSION		"6.0k"
+
+#define MOXA_FW_HDRLEN		32
+
+#define MOXAMAJOR		172
+
+#define MAX_BOARDS		4	/* Don't change this value */
+#define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
+#define MAX_PORTS		(MAX_BOARDS * MAX_PORTS_PER_BOARD)
+
+#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
+		(brd)->boardType == MOXA_BOARD_C320_PCI)
+
+/*
+ *    Define the Moxa PCI vendor and device IDs.
+ */
+#define MOXA_BUS_TYPE_ISA	0
+#define MOXA_BUS_TYPE_PCI	1
+
+enum {
+	MOXA_BOARD_C218_PCI = 1,
+	MOXA_BOARD_C218_ISA,
+	MOXA_BOARD_C320_PCI,
+	MOXA_BOARD_C320_ISA,
+	MOXA_BOARD_CP204J,
+};
+
+static char *moxa_brdname[] =
+{
+	"C218 Turbo PCI series",
+	"C218 Turbo ISA series",
+	"C320 Turbo PCI series",
+	"C320 Turbo ISA series",
+	"CP-204J series",
+};
+
+#ifdef CONFIG_PCI
+static struct pci_device_id moxa_pcibrds[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218),
+		.driver_data = MOXA_BOARD_C218_PCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320),
+		.driver_data = MOXA_BOARD_C320_PCI },
+	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J),
+		.driver_data = MOXA_BOARD_CP204J },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
+#endif /* CONFIG_PCI */
+
+struct moxa_port;
+
+static struct moxa_board_conf {
+	int boardType;
+	int numPorts;
+	int busType;
+
+	unsigned int ready;
+
+	struct moxa_port *ports;
+
+	void __iomem *basemem;
+	void __iomem *intNdx;
+	void __iomem *intPend;
+	void __iomem *intTable;
+} moxa_boards[MAX_BOARDS];
+
+struct mxser_mstatus {
+	tcflag_t cflag;
+	int cts;
+	int dsr;
+	int ri;
+	int dcd;
+};
+
+struct moxaq_str {
+	int inq;
+	int outq;
+};
+
+struct moxa_port {
+	struct tty_port port;
+	struct moxa_board_conf *board;
+	void __iomem *tableAddr;
+
+	int type;
+	int cflag;
+	unsigned long statusflags;
+
+	u8 DCDState;		/* Protected by the port lock */
+	u8 lineCtrl;
+	u8 lowChkFlag;
+};
+
+struct mon_str {
+	int tick;
+	int rxcnt[MAX_PORTS];
+	int txcnt[MAX_PORTS];
+};
+
+/* statusflags */
+#define TXSTOPPED	1
+#define LOWWAIT 	2
+#define EMPTYWAIT	3
+
+#define SERIAL_DO_RESTART
+
+#define WAKEUP_CHARS		256
+
+static int ttymajor = MOXAMAJOR;
+static struct mon_str moxaLog;
+static unsigned int moxaFuncTout = HZ / 2;
+static unsigned int moxaLowWaterChk;
+static DEFINE_MUTEX(moxa_openlock);
+static DEFINE_SPINLOCK(moxa_lock);
+
+static unsigned long baseaddr[MAX_BOARDS];
+static unsigned int type[MAX_BOARDS];
+static unsigned int numports[MAX_BOARDS];
+
+MODULE_AUTHOR("William Chen");
+MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("c218tunx.cod");
+MODULE_FIRMWARE("cp204unx.cod");
+MODULE_FIRMWARE("c320tunx.cod");
+
+module_param_array(type, uint, NULL, 0);
+MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
+module_param_array(baseaddr, ulong, NULL, 0);
+MODULE_PARM_DESC(baseaddr, "base address");
+module_param_array(numports, uint, NULL, 0);
+MODULE_PARM_DESC(numports, "numports (ignored for C218)");
+
+module_param(ttymajor, int, 0);
+
+/*
+ * static functions:
+ */
+static int moxa_open(struct tty_struct *, struct file *);
+static void moxa_close(struct tty_struct *, struct file *);
+static int moxa_write(struct tty_struct *, const unsigned char *, int);
+static int moxa_write_room(struct tty_struct *);
+static void moxa_flush_buffer(struct tty_struct *);
+static int moxa_chars_in_buffer(struct tty_struct *);
+static void moxa_set_termios(struct tty_struct *, struct ktermios *);
+static void moxa_stop(struct tty_struct *);
+static void moxa_start(struct tty_struct *);
+static void moxa_hangup(struct tty_struct *);
+static int moxa_tiocmget(struct tty_struct *tty);
+static int moxa_tiocmset(struct tty_struct *tty,
+			 unsigned int set, unsigned int clear);
+static void moxa_poll(unsigned long);
+static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
+static void moxa_shutdown(struct tty_port *);
+static int moxa_carrier_raised(struct tty_port *);
+static void moxa_dtr_rts(struct tty_port *, int);
+/*
+ * moxa board interface functions:
+ */
+static void MoxaPortEnable(struct moxa_port *);
+static void MoxaPortDisable(struct moxa_port *);
+static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
+static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
+static void MoxaPortLineCtrl(struct moxa_port *, int, int);
+static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
+static int MoxaPortLineStatus(struct moxa_port *);
+static void MoxaPortFlushData(struct moxa_port *, int);
+static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
+static int MoxaPortReadData(struct moxa_port *);
+static int MoxaPortTxQueue(struct moxa_port *);
+static int MoxaPortRxQueue(struct moxa_port *);
+static int MoxaPortTxFree(struct moxa_port *);
+static void MoxaPortTxDisable(struct moxa_port *);
+static void MoxaPortTxEnable(struct moxa_port *);
+static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
+static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
+static void MoxaSetFifo(struct moxa_port *port, int enable);
+
+/*
+ * I/O functions
+ */
+
+static DEFINE_SPINLOCK(moxafunc_lock);
+
+static void moxa_wait_finish(void __iomem *ofsAddr)
+{
+	unsigned long end = jiffies + moxaFuncTout;
+
+	while (readw(ofsAddr + FuncCode) != 0)
+		if (time_after(jiffies, end))
+			return;
+	if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
+		printk(KERN_WARNING "moxa function expired\n");
+}
+
+static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
+{
+        unsigned long flags;
+        spin_lock_irqsave(&moxafunc_lock, flags);
+	writew(arg, ofsAddr + FuncArg);
+	writew(cmd, ofsAddr + FuncCode);
+	moxa_wait_finish(ofsAddr);
+	spin_unlock_irqrestore(&moxafunc_lock, flags);
+}
+
+static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg)
+{
+        unsigned long flags;
+        u16 ret;
+        spin_lock_irqsave(&moxafunc_lock, flags);
+	writew(arg, ofsAddr + FuncArg);
+	writew(cmd, ofsAddr + FuncCode);
+	moxa_wait_finish(ofsAddr);
+	ret = readw(ofsAddr + FuncArg);
+	spin_unlock_irqrestore(&moxafunc_lock, flags);
+	return ret;
+}
+
+static void moxa_low_water_check(void __iomem *ofsAddr)
+{
+	u16 rptr, wptr, mask, len;
+
+	if (readb(ofsAddr + FlagStat) & Xoff_state) {
+		rptr = readw(ofsAddr + RXrptr);
+		wptr = readw(ofsAddr + RXwptr);
+		mask = readw(ofsAddr + RX_mask);
+		len = (wptr - rptr) & mask;
+		if (len <= Low_water)
+			moxafunc(ofsAddr, FC_SendXon, 0);
+	}
+}
+
+/*
+ * TTY operations
+ */
+
+static int moxa_ioctl(struct tty_struct *tty,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct moxa_port *ch = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+	int status, ret = 0;
+
+	if (tty->index == MAX_PORTS) {
+		if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
+				cmd != MOXA_GETMSTATUS)
+			return -EINVAL;
+	} else if (!ch)
+		return -ENODEV;
+
+	switch (cmd) {
+	case MOXA_GETDATACOUNT:
+		moxaLog.tick = jiffies;
+		if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
+			ret = -EFAULT;
+		break;
+	case MOXA_FLUSH_QUEUE:
+		MoxaPortFlushData(ch, arg);
+		break;
+	case MOXA_GET_IOQUEUE: {
+		struct moxaq_str __user *argm = argp;
+		struct moxaq_str tmp;
+		struct moxa_port *p;
+		unsigned int i, j;
+
+		for (i = 0; i < MAX_BOARDS; i++) {
+			p = moxa_boards[i].ports;
+			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+				memset(&tmp, 0, sizeof(tmp));
+				spin_lock_bh(&moxa_lock);
+				if (moxa_boards[i].ready) {
+					tmp.inq = MoxaPortRxQueue(p);
+					tmp.outq = MoxaPortTxQueue(p);
+				}
+				spin_unlock_bh(&moxa_lock);
+				if (copy_to_user(argm, &tmp, sizeof(tmp)))
+					return -EFAULT;
+			}
+		}
+		break;
+	} case MOXA_GET_OQUEUE:
+		status = MoxaPortTxQueue(ch);
+		ret = put_user(status, (unsigned long __user *)argp);
+		break;
+	case MOXA_GET_IQUEUE:
+		status = MoxaPortRxQueue(ch);
+		ret = put_user(status, (unsigned long __user *)argp);
+		break;
+	case MOXA_GETMSTATUS: {
+		struct mxser_mstatus __user *argm = argp;
+		struct mxser_mstatus tmp;
+		struct moxa_port *p;
+		unsigned int i, j;
+
+		for (i = 0; i < MAX_BOARDS; i++) {
+			p = moxa_boards[i].ports;
+			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+				struct tty_struct *ttyp;
+				memset(&tmp, 0, sizeof(tmp));
+				spin_lock_bh(&moxa_lock);
+				if (!moxa_boards[i].ready) {
+				        spin_unlock_bh(&moxa_lock);
+					goto copy;
+                                }
+
+				status = MoxaPortLineStatus(p);
+				spin_unlock_bh(&moxa_lock);
+
+				if (status & 1)
+					tmp.cts = 1;
+				if (status & 2)
+					tmp.dsr = 1;
+				if (status & 4)
+					tmp.dcd = 1;
+
+				ttyp = tty_port_tty_get(&p->port);
+				if (!ttyp || !ttyp->termios)
+					tmp.cflag = p->cflag;
+				else
+					tmp.cflag = ttyp->termios->c_cflag;
+				tty_kref_put(tty);
+copy:
+				if (copy_to_user(argm, &tmp, sizeof(tmp)))
+					return -EFAULT;
+			}
+		}
+		break;
+	}
+	case TIOCGSERIAL:
+	        mutex_lock(&ch->port.mutex);
+		ret = moxa_get_serial_info(ch, argp);
+		mutex_unlock(&ch->port.mutex);
+		break;
+	case TIOCSSERIAL:
+	        mutex_lock(&ch->port.mutex);
+		ret = moxa_set_serial_info(ch, argp);
+		mutex_unlock(&ch->port.mutex);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static int moxa_break_ctl(struct tty_struct *tty, int state)
+{
+	struct moxa_port *port = tty->driver_data;
+
+	moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
+			Magic_code);
+	return 0;
+}
+
+static const struct tty_operations moxa_ops = {
+	.open = moxa_open,
+	.close = moxa_close,
+	.write = moxa_write,
+	.write_room = moxa_write_room,
+	.flush_buffer = moxa_flush_buffer,
+	.chars_in_buffer = moxa_chars_in_buffer,
+	.ioctl = moxa_ioctl,
+	.set_termios = moxa_set_termios,
+	.stop = moxa_stop,
+	.start = moxa_start,
+	.hangup = moxa_hangup,
+	.break_ctl = moxa_break_ctl,
+	.tiocmget = moxa_tiocmget,
+	.tiocmset = moxa_tiocmset,
+};
+
+static const struct tty_port_operations moxa_port_ops = {
+	.carrier_raised = moxa_carrier_raised,
+	.dtr_rts = moxa_dtr_rts,
+	.shutdown = moxa_shutdown,
+};
+
+static struct tty_driver *moxaDriver;
+static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
+
+/*
+ * HW init
+ */
+
+static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
+{
+	switch (brd->boardType) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		if (model != 1)
+			goto err;
+		break;
+	case MOXA_BOARD_CP204J:
+		if (model != 3)
+			goto err;
+		break;
+	default:
+		if (model != 2)
+			goto err;
+		break;
+	}
+	return 0;
+err:
+	return -EINVAL;
+}
+
+static int moxa_check_fw(const void *ptr)
+{
+	const __le16 *lptr = ptr;
+
+	if (*lptr != cpu_to_le16(0x7980))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
+		size_t len)
+{
+	void __iomem *baseAddr = brd->basemem;
+	u16 tmp;
+
+	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
+	msleep(10);
+	memset_io(baseAddr, 0, 4096);
+	memcpy_toio(baseAddr, buf, len);	/* download BIOS */
+	writeb(0, baseAddr + Control_reg);	/* restart */
+
+	msleep(2000);
+
+	switch (brd->boardType) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		tmp = readw(baseAddr + C218_key);
+		if (tmp != C218_KeyCode)
+			goto err;
+		break;
+	case MOXA_BOARD_CP204J:
+		tmp = readw(baseAddr + C218_key);
+		if (tmp != CP204J_KeyCode)
+			goto err;
+		break;
+	default:
+		tmp = readw(baseAddr + C320_key);
+		if (tmp != C320_KeyCode)
+			goto err;
+		tmp = readw(baseAddr + C320_status);
+		if (tmp != STS_init) {
+			printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
+					"module not found\n");
+			return -EIO;
+		}
+		break;
+	}
+
+	return 0;
+err:
+	printk(KERN_ERR "MOXA: bios upload failed -- board not found\n");
+	return -EIO;
+}
+
+static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
+		size_t len)
+{
+	void __iomem *baseAddr = brd->basemem;
+
+	if (len < 7168) {
+		printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n");
+		return -EINVAL;
+	}
+
+	writew(len - 7168 - 2, baseAddr + C320bapi_len);
+	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
+	memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
+	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
+	memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
+
+	return 0;
+}
+
+static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
+		size_t len)
+{
+	void __iomem *baseAddr = brd->basemem;
+	const __le16 *uptr = ptr;
+	size_t wlen, len2, j;
+	unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
+	unsigned int i, retry;
+	u16 usum, keycode;
+
+	keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
+				C218_KeyCode;
+
+	switch (brd->boardType) {
+	case MOXA_BOARD_CP204J:
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		key = C218_key;
+		loadbuf = C218_LoadBuf;
+		loadlen = C218DLoad_len;
+		checksum = C218check_sum;
+		checksum_ok = C218chksum_ok;
+		break;
+	default:
+		key = C320_key;
+		keycode = C320_KeyCode;
+		loadbuf = C320_LoadBuf;
+		loadlen = C320DLoad_len;
+		checksum = C320check_sum;
+		checksum_ok = C320chksum_ok;
+		break;
+	}
+
+	usum = 0;
+	wlen = len >> 1;
+	for (i = 0; i < wlen; i++)
+		usum += le16_to_cpu(uptr[i]);
+	retry = 0;
+	do {
+		wlen = len >> 1;
+		j = 0;
+		while (wlen) {
+			len2 = (wlen > 2048) ? 2048 : wlen;
+			wlen -= len2;
+			memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
+			j += len2 << 1;
+
+			writew(len2, baseAddr + loadlen);
+			writew(0, baseAddr + key);
+			for (i = 0; i < 100; i++) {
+				if (readw(baseAddr + key) == keycode)
+					break;
+				msleep(10);
+			}
+			if (readw(baseAddr + key) != keycode)
+				return -EIO;
+		}
+		writew(0, baseAddr + loadlen);
+		writew(usum, baseAddr + checksum);
+		writew(0, baseAddr + key);
+		for (i = 0; i < 100; i++) {
+			if (readw(baseAddr + key) == keycode)
+				break;
+			msleep(10);
+		}
+		retry++;
+	} while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
+	if (readb(baseAddr + checksum_ok) != 1)
+		return -EIO;
+
+	writew(0, baseAddr + key);
+	for (i = 0; i < 600; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		msleep(10);
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code)
+		return -EIO;
+
+	if (MOXA_IS_320(brd)) {
+		if (brd->busType == MOXA_BUS_TYPE_PCI) {	/* ASIC board */
+			writew(0x3800, baseAddr + TMS320_PORT1);
+			writew(0x3900, baseAddr + TMS320_PORT2);
+			writew(28499, baseAddr + TMS320_CLOCK);
+		} else {
+			writew(0x3200, baseAddr + TMS320_PORT1);
+			writew(0x3400, baseAddr + TMS320_PORT2);
+			writew(19999, baseAddr + TMS320_CLOCK);
+		}
+	}
+	writew(1, baseAddr + Disable_IRQ);
+	writew(0, baseAddr + Magic_no);
+	for (i = 0; i < 500; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		msleep(10);
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code)
+		return -EIO;
+
+	if (MOXA_IS_320(brd)) {
+		j = readw(baseAddr + Module_cnt);
+		if (j <= 0)
+			return -EIO;
+		brd->numPorts = j * 8;
+		writew(j, baseAddr + Module_no);
+		writew(0, baseAddr + Magic_no);
+		for (i = 0; i < 600; i++) {
+			if (readw(baseAddr + Magic_no) == Magic_code)
+				break;
+			msleep(10);
+		}
+		if (readw(baseAddr + Magic_no) != Magic_code)
+			return -EIO;
+	}
+	brd->intNdx = baseAddr + IRQindex;
+	brd->intPend = baseAddr + IRQpending;
+	brd->intTable = baseAddr + IRQtable;
+
+	return 0;
+}
+
+static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
+		size_t len)
+{
+	void __iomem *ofsAddr, *baseAddr = brd->basemem;
+	struct moxa_port *port;
+	int retval, i;
+
+	if (len % 2) {
+		printk(KERN_ERR "MOXA: bios length is not even\n");
+		return -EINVAL;
+	}
+
+	retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
+	if (retval)
+		return retval;
+
+	switch (brd->boardType) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+	case MOXA_BOARD_CP204J:
+		port = brd->ports;
+		for (i = 0; i < brd->numPorts; i++, port++) {
+			port->board = brd;
+			port->DCDState = 0;
+			port->tableAddr = baseAddr + Extern_table +
+					Extern_size * i;
+			ofsAddr = port->tableAddr;
+			writew(C218rx_mask, ofsAddr + RX_mask);
+			writew(C218tx_mask, ofsAddr + TX_mask);
+			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
+			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
+
+			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
+			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
+
+		}
+		break;
+	default:
+		port = brd->ports;
+		for (i = 0; i < brd->numPorts; i++, port++) {
+			port->board = brd;
+			port->DCDState = 0;
+			port->tableAddr = baseAddr + Extern_table +
+					Extern_size * i;
+			ofsAddr = port->tableAddr;
+			switch (brd->numPorts) {
+			case 8:
+				writew(C320p8rx_mask, ofsAddr + RX_mask);
+				writew(C320p8tx_mask, ofsAddr + TX_mask);
+				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
+				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
+				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
+
+				break;
+			case 16:
+				writew(C320p16rx_mask, ofsAddr + RX_mask);
+				writew(C320p16tx_mask, ofsAddr + TX_mask);
+				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
+				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
+				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
+				break;
+
+			case 24:
+				writew(C320p24rx_mask, ofsAddr + RX_mask);
+				writew(C320p24tx_mask, ofsAddr + TX_mask);
+				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
+				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
+				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+				break;
+			case 32:
+				writew(C320p32rx_mask, ofsAddr + RX_mask);
+				writew(C320p32tx_mask, ofsAddr + TX_mask);
+				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
+				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
+				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
+				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+				break;
+			}
+		}
+		break;
+	}
+	return 0;
+}
+
+static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
+{
+	const void *ptr = fw->data;
+	char rsn[64];
+	u16 lens[5];
+	size_t len;
+	unsigned int a, lenp, lencnt;
+	int ret = -EINVAL;
+	struct {
+		__le32 magic;	/* 0x34303430 */
+		u8 reserved1[2];
+		u8 type;	/* UNIX = 3 */
+		u8 model;	/* C218T=1, C320T=2, CP204=3 */
+		u8 reserved2[8];
+		__le16 len[5];
+	} const *hdr = ptr;
+
+	BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
+
+	if (fw->size < MOXA_FW_HDRLEN) {
+		strcpy(rsn, "too short (even header won't fit)");
+		goto err;
+	}
+	if (hdr->magic != cpu_to_le32(0x30343034)) {
+		sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
+		goto err;
+	}
+	if (hdr->type != 3) {
+		sprintf(rsn, "not for linux, type is %u", hdr->type);
+		goto err;
+	}
+	if (moxa_check_fw_model(brd, hdr->model)) {
+		sprintf(rsn, "not for this card, model is %u", hdr->model);
+		goto err;
+	}
+
+	len = MOXA_FW_HDRLEN;
+	lencnt = hdr->model == 2 ? 5 : 3;
+	for (a = 0; a < ARRAY_SIZE(lens); a++) {
+		lens[a] = le16_to_cpu(hdr->len[a]);
+		if (lens[a] && len + lens[a] <= fw->size &&
+				moxa_check_fw(&fw->data[len]))
+			printk(KERN_WARNING "MOXA firmware: unexpected input "
+				"at offset %u, but going on\n", (u32)len);
+		if (!lens[a] && a < lencnt) {
+			sprintf(rsn, "too few entries in fw file");
+			goto err;
+		}
+		len += lens[a];
+	}
+
+	if (len != fw->size) {
+		sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
+				(u32)len);
+		goto err;
+	}
+
+	ptr += MOXA_FW_HDRLEN;
+	lenp = 0; /* bios */
+
+	strcpy(rsn, "read above");
+
+	ret = moxa_load_bios(brd, ptr, lens[lenp]);
+	if (ret)
+		goto err;
+
+	/* we skip the tty section (lens[1]), since we don't need it */
+	ptr += lens[lenp] + lens[lenp + 1];
+	lenp += 2; /* comm */
+
+	if (hdr->model == 2) {
+		ret = moxa_load_320b(brd, ptr, lens[lenp]);
+		if (ret)
+			goto err;
+		/* skip another tty */
+		ptr += lens[lenp] + lens[lenp + 1];
+		lenp += 2;
+	}
+
+	ret = moxa_load_code(brd, ptr, lens[lenp]);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
+	return ret;
+}
+
+static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
+{
+	const struct firmware *fw;
+	const char *file;
+	struct moxa_port *p;
+	unsigned int i;
+	int ret;
+
+	brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
+			GFP_KERNEL);
+	if (brd->ports == NULL) {
+		printk(KERN_ERR "cannot allocate memory for ports\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
+		tty_port_init(&p->port);
+		p->port.ops = &moxa_port_ops;
+		p->type = PORT_16550A;
+		p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	}
+
+	switch (brd->boardType) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		file = "c218tunx.cod";
+		break;
+	case MOXA_BOARD_CP204J:
+		file = "cp204unx.cod";
+		break;
+	default:
+		file = "c320tunx.cod";
+		break;
+	}
+
+	ret = request_firmware(&fw, file, dev);
+	if (ret) {
+		printk(KERN_ERR "MOXA: request_firmware failed. Make sure "
+				"you've placed '%s' file into your firmware "
+				"loader directory (e.g. /lib/firmware)\n",
+				file);
+		goto err_free;
+	}
+
+	ret = moxa_load_fw(brd, fw);
+
+	release_firmware(fw);
+
+	if (ret)
+		goto err_free;
+
+	spin_lock_bh(&moxa_lock);
+	brd->ready = 1;
+	if (!timer_pending(&moxaTimer))
+		mod_timer(&moxaTimer, jiffies + HZ / 50);
+	spin_unlock_bh(&moxa_lock);
+
+	return 0;
+err_free:
+	kfree(brd->ports);
+err:
+	return ret;
+}
+
+static void moxa_board_deinit(struct moxa_board_conf *brd)
+{
+	unsigned int a, opened;
+
+	mutex_lock(&moxa_openlock);
+	spin_lock_bh(&moxa_lock);
+	brd->ready = 0;
+	spin_unlock_bh(&moxa_lock);
+
+	/* 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);
+			}
+		}
+	while (1) {
+		opened = 0;
+		for (a = 0; a < brd->numPorts; a++)
+			if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
+				opened++;
+		mutex_unlock(&moxa_openlock);
+		if (!opened)
+			break;
+		msleep(50);
+		mutex_lock(&moxa_openlock);
+	}
+
+	iounmap(brd->basemem);
+	brd->basemem = NULL;
+	kfree(brd->ports);
+}
+
+#ifdef CONFIG_PCI
+static int __devinit moxa_pci_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+	struct moxa_board_conf *board;
+	unsigned int i;
+	int board_type = ent->driver_data;
+	int retval;
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "can't enable pci device\n");
+		goto err;
+	}
+
+	for (i = 0; i < MAX_BOARDS; i++)
+		if (moxa_boards[i].basemem == NULL)
+			break;
+
+	retval = -ENODEV;
+	if (i >= MAX_BOARDS) {
+		dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
+				"found. Board is ignored.\n", MAX_BOARDS);
+		goto err;
+	}
+
+	board = &moxa_boards[i];
+
+	retval = pci_request_region(pdev, 2, "moxa-base");
+	if (retval) {
+		dev_err(&pdev->dev, "can't request pci region 2\n");
+		goto err;
+	}
+
+	board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
+	if (board->basemem == NULL) {
+		dev_err(&pdev->dev, "can't remap io space 2\n");
+		goto err_reg;
+	}
+
+	board->boardType = board_type;
+	switch (board_type) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		board->numPorts = 8;
+		break;
+
+	case MOXA_BOARD_CP204J:
+		board->numPorts = 4;
+		break;
+	default:
+		board->numPorts = 0;
+		break;
+	}
+	board->busType = MOXA_BUS_TYPE_PCI;
+
+	retval = moxa_init_board(board, &pdev->dev);
+	if (retval)
+		goto err_base;
+
+	pci_set_drvdata(pdev, board);
+
+	dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n",
+			moxa_brdname[board_type - 1], board->numPorts);
+
+	return 0;
+err_base:
+	iounmap(board->basemem);
+	board->basemem = NULL;
+err_reg:
+	pci_release_region(pdev, 2);
+err:
+	return retval;
+}
+
+static void __devexit moxa_pci_remove(struct pci_dev *pdev)
+{
+	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
+
+	moxa_board_deinit(brd);
+
+	pci_release_region(pdev, 2);
+}
+
+static struct pci_driver moxa_pci_driver = {
+	.name = "moxa",
+	.id_table = moxa_pcibrds,
+	.probe = moxa_pci_probe,
+	.remove = __devexit_p(moxa_pci_remove)
+};
+#endif /* CONFIG_PCI */
+
+static int __init moxa_init(void)
+{
+	unsigned int isabrds = 0;
+	int retval = 0;
+	struct moxa_board_conf *brd = moxa_boards;
+	unsigned int i;
+
+	printk(KERN_INFO "MOXA Intellio family driver version %s\n",
+			MOXA_VERSION);
+	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
+	if (!moxaDriver)
+		return -ENOMEM;
+
+	moxaDriver->owner = THIS_MODULE;
+	moxaDriver->name = "ttyMX";
+	moxaDriver->major = ttymajor;
+	moxaDriver->minor_start = 0;
+	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
+	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
+	moxaDriver->init_termios = tty_std_termios;
+	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	moxaDriver->init_termios.c_ispeed = 9600;
+	moxaDriver->init_termios.c_ospeed = 9600;
+	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(moxaDriver, &moxa_ops);
+
+	if (tty_register_driver(moxaDriver)) {
+		printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
+		put_tty_driver(moxaDriver);
+		return -1;
+	}
+
+	/* Find the boards defined from module args. */
+
+	for (i = 0; i < MAX_BOARDS; i++) {
+		if (!baseaddr[i])
+			break;
+		if (type[i] == MOXA_BOARD_C218_ISA ||
+				type[i] == MOXA_BOARD_C320_ISA) {
+			pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
+					isabrds + 1, moxa_brdname[type[i] - 1],
+					baseaddr[i]);
+			brd->boardType = type[i];
+			brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
+					numports[i];
+			brd->busType = MOXA_BUS_TYPE_ISA;
+			brd->basemem = ioremap_nocache(baseaddr[i], 0x4000);
+			if (!brd->basemem) {
+				printk(KERN_ERR "MOXA: can't remap %lx\n",
+						baseaddr[i]);
+				continue;
+			}
+			if (moxa_init_board(brd, NULL)) {
+				iounmap(brd->basemem);
+				brd->basemem = NULL;
+				continue;
+			}
+
+			printk(KERN_INFO "MOXA isa board found at 0x%.8lu and "
+					"ready (%u ports, firmware loaded)\n",
+					baseaddr[i], brd->numPorts);
+
+			brd++;
+			isabrds++;
+		}
+	}
+
+#ifdef CONFIG_PCI
+	retval = pci_register_driver(&moxa_pci_driver);
+	if (retval) {
+		printk(KERN_ERR "Can't register MOXA pci driver!\n");
+		if (isabrds)
+			retval = 0;
+	}
+#endif
+
+	return retval;
+}
+
+static void __exit moxa_exit(void)
+{
+	unsigned int i;
+
+#ifdef CONFIG_PCI
+	pci_unregister_driver(&moxa_pci_driver);
+#endif
+
+	for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
+		if (moxa_boards[i].ready)
+			moxa_board_deinit(&moxa_boards[i]);
+
+	del_timer_sync(&moxaTimer);
+
+	if (tty_unregister_driver(moxaDriver))
+		printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
+				"serial driver\n");
+	put_tty_driver(moxaDriver);
+}
+
+module_init(moxa_init);
+module_exit(moxa_exit);
+
+static void moxa_shutdown(struct tty_port *port)
+{
+	struct moxa_port *ch = container_of(port, struct moxa_port, port);
+        MoxaPortDisable(ch);
+	MoxaPortFlushData(ch, 2);
+	clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
+}
+
+static int moxa_carrier_raised(struct tty_port *port)
+{
+	struct moxa_port *ch = container_of(port, struct moxa_port, port);
+	int dcd;
+
+	spin_lock_irq(&port->lock);
+	dcd = ch->DCDState;
+	spin_unlock_irq(&port->lock);
+	return dcd;
+}
+
+static void moxa_dtr_rts(struct tty_port *port, int onoff)
+{
+	struct moxa_port *ch = container_of(port, struct moxa_port, port);
+	MoxaPortLineCtrl(ch, onoff, onoff);
+}
+
+
+static int moxa_open(struct tty_struct *tty, struct file *filp)
+{
+	struct moxa_board_conf *brd;
+	struct moxa_port *ch;
+	int port;
+	int retval;
+
+	port = tty->index;
+	if (port == MAX_PORTS) {
+		return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
+	}
+	if (mutex_lock_interruptible(&moxa_openlock))
+		return -ERESTARTSYS;
+	brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
+	if (!brd->ready) {
+		mutex_unlock(&moxa_openlock);
+		return -ENODEV;
+	}
+
+	if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) {
+		mutex_unlock(&moxa_openlock);
+		return -ENODEV;
+	}
+
+	ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
+	ch->port.count++;
+	tty->driver_data = ch;
+	tty_port_tty_set(&ch->port, tty);
+	mutex_lock(&ch->port.mutex);
+	if (!(ch->port.flags & ASYNC_INITIALIZED)) {
+		ch->statusflags = 0;
+		moxa_set_tty_param(tty, tty->termios);
+		MoxaPortLineCtrl(ch, 1, 1);
+		MoxaPortEnable(ch);
+		MoxaSetFifo(ch, ch->type == PORT_16550A);
+		ch->port.flags |= ASYNC_INITIALIZED;
+	}
+	mutex_unlock(&ch->port.mutex);
+	mutex_unlock(&moxa_openlock);
+
+	retval = tty_port_block_til_ready(&ch->port, tty, filp);
+	if (retval == 0)
+	        set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags);
+	return retval;
+}
+
+static void moxa_close(struct tty_struct *tty, struct file *filp)
+{
+	struct moxa_port *ch = tty->driver_data;
+	ch->cflag = tty->termios->c_cflag;
+	tty_port_close(&ch->port, tty, filp);
+}
+
+static int moxa_write(struct tty_struct *tty,
+		      const unsigned char *buf, int count)
+{
+	struct moxa_port *ch = tty->driver_data;
+	int len;
+
+	if (ch == NULL)
+		return 0;
+
+	spin_lock_bh(&moxa_lock);
+	len = MoxaPortWriteData(tty, buf, count);
+	spin_unlock_bh(&moxa_lock);
+
+	set_bit(LOWWAIT, &ch->statusflags);
+	return len;
+}
+
+static int moxa_write_room(struct tty_struct *tty)
+{
+	struct moxa_port *ch;
+
+	if (tty->stopped)
+		return 0;
+	ch = tty->driver_data;
+	if (ch == NULL)
+		return 0;
+	return MoxaPortTxFree(ch);
+}
+
+static void moxa_flush_buffer(struct tty_struct *tty)
+{
+	struct moxa_port *ch = tty->driver_data;
+
+	if (ch == NULL)
+		return;
+	MoxaPortFlushData(ch, 1);
+	tty_wakeup(tty);
+}
+
+static int moxa_chars_in_buffer(struct tty_struct *tty)
+{
+	struct moxa_port *ch = tty->driver_data;
+	int chars;
+
+	chars = MoxaPortTxQueue(ch);
+	if (chars)
+		/*
+		 * Make it possible to wakeup anything waiting for output
+		 * in tty_ioctl.c, etc.
+		 */
+        	set_bit(EMPTYWAIT, &ch->statusflags);
+	return chars;
+}
+
+static int moxa_tiocmget(struct tty_struct *tty)
+{
+	struct moxa_port *ch = tty->driver_data;
+	int flag = 0, dtr, rts;
+
+	MoxaPortGetLineOut(ch, &dtr, &rts);
+	if (dtr)
+		flag |= TIOCM_DTR;
+	if (rts)
+		flag |= TIOCM_RTS;
+	dtr = MoxaPortLineStatus(ch);
+	if (dtr & 1)
+		flag |= TIOCM_CTS;
+	if (dtr & 2)
+		flag |= TIOCM_DSR;
+	if (dtr & 4)
+		flag |= TIOCM_CD;
+	return flag;
+}
+
+static int moxa_tiocmset(struct tty_struct *tty,
+			 unsigned int set, unsigned int clear)
+{
+	struct moxa_port *ch;
+	int port;
+	int dtr, rts;
+
+	port = tty->index;
+	mutex_lock(&moxa_openlock);
+	ch = tty->driver_data;
+	if (!ch) {
+		mutex_unlock(&moxa_openlock);
+		return -EINVAL;
+	}
+
+	MoxaPortGetLineOut(ch, &dtr, &rts);
+	if (set & TIOCM_RTS)
+		rts = 1;
+	if (set & TIOCM_DTR)
+		dtr = 1;
+	if (clear & TIOCM_RTS)
+		rts = 0;
+	if (clear & TIOCM_DTR)
+		dtr = 0;
+	MoxaPortLineCtrl(ch, dtr, rts);
+	mutex_unlock(&moxa_openlock);
+	return 0;
+}
+
+static void moxa_set_termios(struct tty_struct *tty,
+		struct ktermios *old_termios)
+{
+	struct moxa_port *ch = tty->driver_data;
+
+	if (ch == NULL)
+		return;
+	moxa_set_tty_param(tty, old_termios);
+	if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
+		wake_up_interruptible(&ch->port.open_wait);
+}
+
+static void moxa_stop(struct tty_struct *tty)
+{
+	struct moxa_port *ch = tty->driver_data;
+
+	if (ch == NULL)
+		return;
+	MoxaPortTxDisable(ch);
+	set_bit(TXSTOPPED, &ch->statusflags);
+}
+
+
+static void moxa_start(struct tty_struct *tty)
+{
+	struct moxa_port *ch = tty->driver_data;
+
+	if (ch == NULL)
+		return;
+
+	if (!(ch->statusflags & TXSTOPPED))
+		return;
+
+	MoxaPortTxEnable(ch);
+	clear_bit(TXSTOPPED, &ch->statusflags);
+}
+
+static void moxa_hangup(struct tty_struct *tty)
+{
+	struct moxa_port *ch = tty->driver_data;
+	tty_port_hangup(&ch->port);
+}
+
+static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
+{
+	struct tty_struct *tty;
+	unsigned long flags;
+	dcd = !!dcd;
+
+	spin_lock_irqsave(&p->port.lock, flags);
+	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);
+	}
+	else
+		spin_unlock_irqrestore(&p->port.lock, flags);
+}
+
+static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
+		u16 __iomem *ip)
+{
+	struct tty_struct *tty = tty_port_tty_get(&p->port);
+	void __iomem *ofsAddr;
+	unsigned int inited = p->port.flags & ASYNC_INITIALIZED;
+	u16 intr;
+
+	if (tty) {
+		if (test_bit(EMPTYWAIT, &p->statusflags) &&
+				MoxaPortTxQueue(p) == 0) {
+			clear_bit(EMPTYWAIT, &p->statusflags);
+			tty_wakeup(tty);
+		}
+		if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped &&
+				MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
+			clear_bit(LOWWAIT, &p->statusflags);
+			tty_wakeup(tty);
+		}
+
+		if (inited && !test_bit(TTY_THROTTLED, &tty->flags) &&
+				MoxaPortRxQueue(p) > 0) { /* RX */
+			MoxaPortReadData(p);
+			tty_schedule_flip(tty);
+		}
+	} else {
+		clear_bit(EMPTYWAIT, &p->statusflags);
+		MoxaPortFlushData(p, 0); /* flush RX */
+	}
+
+	if (!handle) /* nothing else to do */
+		goto put;
+
+	intr = readw(ip); /* port irq status */
+	if (intr == 0)
+		goto put;
+
+	writew(0, ip); /* ACK port */
+	ofsAddr = p->tableAddr;
+	if (intr & IntrTx) /* disable tx intr */
+		writew(readw(ofsAddr + HostStat) & ~WakeupTx,
+				ofsAddr + HostStat);
+
+	if (!inited)
+		goto put;
+
+	if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
+		tty_insert_flip_char(tty, 0, TTY_BREAK);
+		tty_schedule_flip(tty);
+	}
+
+	if (intr & IntrLine)
+		moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
+put:
+	tty_kref_put(tty);
+
+	return 0;
+}
+
+static void moxa_poll(unsigned long ignored)
+{
+	struct moxa_board_conf *brd;
+	u16 __iomem *ip;
+	unsigned int card, port, served = 0;
+
+	spin_lock(&moxa_lock);
+	for (card = 0; card < MAX_BOARDS; card++) {
+		brd = &moxa_boards[card];
+		if (!brd->ready)
+			continue;
+
+		served++;
+
+		ip = NULL;
+		if (readb(brd->intPend) == 0xff)
+			ip = brd->intTable + readb(brd->intNdx);
+
+		for (port = 0; port < brd->numPorts; port++)
+			moxa_poll_port(&brd->ports[port], !!ip, ip + port);
+
+		if (ip)
+			writeb(0, brd->intPend); /* ACK */
+
+		if (moxaLowWaterChk) {
+			struct moxa_port *p = brd->ports;
+			for (port = 0; port < brd->numPorts; port++, p++)
+				if (p->lowChkFlag) {
+					p->lowChkFlag = 0;
+					moxa_low_water_check(p->tableAddr);
+				}
+		}
+	}
+	moxaLowWaterChk = 0;
+
+	if (served)
+		mod_timer(&moxaTimer, jiffies + HZ / 50);
+	spin_unlock(&moxa_lock);
+}
+
+/******************************************************************************/
+
+static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	register struct ktermios *ts = tty->termios;
+	struct moxa_port *ch = tty->driver_data;
+	int rts, cts, txflow, rxflow, xany, baud;
+
+	rts = cts = txflow = rxflow = xany = 0;
+	if (ts->c_cflag & CRTSCTS)
+		rts = cts = 1;
+	if (ts->c_iflag & IXON)
+		txflow = 1;
+	if (ts->c_iflag & IXOFF)
+		rxflow = 1;
+	if (ts->c_iflag & IXANY)
+		xany = 1;
+
+	/* Clear the features we don't support */
+	ts->c_cflag &= ~CMSPAR;
+	MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
+	baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
+	if (baud == -1)
+		baud = tty_termios_baud_rate(old_termios);
+	/* Not put the baud rate into the termios data */
+	tty_encode_baud_rate(tty, baud, baud);
+}
+
+/*****************************************************************************
+ *	Driver level functions: 					     *
+ *****************************************************************************/
+
+static void MoxaPortFlushData(struct moxa_port *port, int mode)
+{
+	void __iomem *ofsAddr;
+	if (mode < 0 || mode > 2)
+		return;
+	ofsAddr = port->tableAddr;
+	moxafunc(ofsAddr, FC_FlushQueue, mode);
+	if (mode != 1) {
+		port->lowChkFlag = 0;
+		moxa_low_water_check(ofsAddr);
+	}
+}
+
+/*
+ *    Moxa Port Number Description:
+ *
+ *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
+ *      the port number using in MOXA driver functions will be 0 to 31 for
+ *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
+ *      to 127 for fourth. For example, if you setup three MOXA boards,
+ *      first board is C218, second board is C320-16 and third board is
+ *      C320-32. The port number of first board (C218 - 8 ports) is from
+ *      0 to 7. The port number of second board (C320 - 16 ports) is form
+ *      32 to 47. The port number of third board (C320 - 32 ports) is from
+ *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
+ *      127 will be invalid.
+ *
+ *
+ *      Moxa Functions Description:
+ *
+ *      Function 1:     Driver initialization routine, this routine must be
+ *                      called when initialized driver.
+ *      Syntax:
+ *      void MoxaDriverInit();
+ *
+ *
+ *      Function 2:     Moxa driver private IOCTL command processing.
+ *      Syntax:
+ *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
+ *
+ *           unsigned int cmd   : IOCTL command
+ *           unsigned long arg  : IOCTL argument
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0  (OK)
+ *                      -EINVAL
+ *                      -ENOIOCTLCMD
+ *
+ *
+ *      Function 6:     Enable this port to start Tx/Rx data.
+ *      Syntax:
+ *      void MoxaPortEnable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 7:     Disable this port
+ *      Syntax:
+ *      void MoxaPortDisable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 10:    Setting baud rate of this port.
+ *      Syntax:
+ *      speed_t MoxaPortSetBaud(int port, speed_t baud);
+ *           int port           : port number (0 - 127)
+ *           long baud          : baud rate (50 - 115200)
+ *
+ *           return:    0       : this port is invalid or baud < 50
+ *                      50 - 115200 : the real baud rate set to the port, if
+ *                                    the argument baud is large than maximun
+ *                                    available baud rate, the real setting
+ *                                    baud rate will be the maximun baud rate.
+ *
+ *
+ *      Function 12:    Configure the port.
+ *      Syntax:
+ *      int  MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
+ *           int port           : port number (0 - 127)
+ *           struct ktermios * termio : termio structure pointer
+ *	     speed_t baud	: baud rate
+ *
+ *           return:    -1      : this port is invalid or termio == NULL
+ *                      0       : setting O.K.
+ *
+ *
+ *      Function 13:    Get the DTR/RTS state of this port.
+ *      Syntax:
+ *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
+ *           int port           : port number (0 - 127)
+ *           int * dtrState     : pointer to INT to receive the current DTR
+ *                                state. (if NULL, this function will not
+ *                                write to this address)
+ *           int * rtsState     : pointer to INT to receive the current RTS
+ *                                state. (if NULL, this function will not
+ *                                write to this address)
+ *
+ *           return:    -1      : this port is invalid
+ *                      0       : O.K.
+ *
+ *
+ *      Function 14:    Setting the DTR/RTS output state of this port.
+ *      Syntax:
+ *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
+ *           int port           : port number (0 - 127)
+ *           int dtrState       : DTR output state (0: off, 1: on)
+ *           int rtsState       : RTS output state (0: off, 1: on)
+ *
+ *
+ *      Function 15:    Setting the flow control of this port.
+ *      Syntax:
+ *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
+ *                            int txFlow,int xany);
+ *           int port           : port number (0 - 127)
+ *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
+ *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
+ *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
+ *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
+ *           int xany           : S/W XANY flow control (0: no, 1: yes)
+ *
+ *
+ *      Function 16:    Get ths line status of this port
+ *      Syntax:
+ *      int  MoxaPortLineStatus(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    Bit 0 - CTS state (0: off, 1: on)
+ *                      Bit 1 - DSR state (0: off, 1: on)
+ *                      Bit 2 - DCD state (0: off, 1: on)
+ *
+ *
+ *      Function 19:    Flush the Rx/Tx buffer data of this port.
+ *      Syntax:
+ *      void MoxaPortFlushData(int port, int mode);
+ *           int port           : port number (0 - 127)
+ *           int mode    
+ *                      0       : flush the Rx buffer 
+ *                      1       : flush the Tx buffer 
+ *                      2       : flush the Rx and Tx buffer 
+ *
+ *
+ *      Function 20:    Write data.
+ *      Syntax:
+ *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
+ *           int port           : port number (0 - 127)
+ *           unsigned char * buffer     : pointer to write data buffer.
+ *           int length         : write data length
+ *
+ *           return:    0 - length      : real write data length
+ *
+ *
+ *      Function 21:    Read data.
+ *      Syntax:
+ *      int  MoxaPortReadData(int port, struct tty_struct *tty);
+ *           int port           : port number (0 - 127)
+ *	     struct tty_struct *tty : tty for data
+ *
+ *           return:    0 - length      : real read data length
+ *
+ *
+ *      Function 24:    Get the Tx buffer current queued data bytes
+ *      Syntax:
+ *      int  MoxaPortTxQueue(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Tx buffer current queued data bytes
+ *
+ *
+ *      Function 25:    Get the Tx buffer current free space
+ *      Syntax:
+ *      int  MoxaPortTxFree(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Tx buffer current free space
+ *
+ *
+ *      Function 26:    Get the Rx buffer current queued data bytes
+ *      Syntax:
+ *      int  MoxaPortRxQueue(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Rx buffer current queued data bytes
+ *
+ *
+ *      Function 28:    Disable port data transmission.
+ *      Syntax:
+ *      void MoxaPortTxDisable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 29:    Enable port data transmission.
+ *      Syntax:
+ *      void MoxaPortTxEnable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 31:    Get the received BREAK signal count and reset it.
+ *      Syntax:
+ *      int  MoxaPortResetBrkCnt(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0 - ..  : BREAK signal count
+ *
+ *
+ */
+
+static void MoxaPortEnable(struct moxa_port *port)
+{
+	void __iomem *ofsAddr;
+	u16 lowwater = 512;
+
+	ofsAddr = port->tableAddr;
+	writew(lowwater, ofsAddr + Low_water);
+	if (MOXA_IS_320(port->board))
+		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
+	else
+		writew(readw(ofsAddr + HostStat) | WakeupBreak,
+				ofsAddr + HostStat);
+
+	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
+	moxafunc(ofsAddr, FC_FlushQueue, 2);
+
+	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
+	MoxaPortLineStatus(port);
+}
+
+static void MoxaPortDisable(struct moxa_port *port)
+{
+	void __iomem *ofsAddr = port->tableAddr;
+
+	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
+	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
+	writew(0, ofsAddr + HostStat);
+	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
+}
+
+static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
+{
+	void __iomem *ofsAddr = port->tableAddr;
+	unsigned int clock, val;
+	speed_t max;
+
+	max = MOXA_IS_320(port->board) ? 460800 : 921600;
+	if (baud < 50)
+		return 0;
+	if (baud > max)
+		baud = max;
+	clock = 921600;
+	val = clock / baud;
+	moxafunc(ofsAddr, FC_SetBaud, val);
+	baud = clock / val;
+	return baud;
+}
+
+static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
+		speed_t baud)
+{
+	void __iomem *ofsAddr;
+	tcflag_t cflag;
+	tcflag_t mode = 0;
+
+	ofsAddr = port->tableAddr;
+	cflag = termio->c_cflag;	/* termio->c_cflag */
+
+	mode = termio->c_cflag & CSIZE;
+	if (mode == CS5)
+		mode = MX_CS5;
+	else if (mode == CS6)
+		mode = MX_CS6;
+	else if (mode == CS7)
+		mode = MX_CS7;
+	else if (mode == CS8)
+		mode = MX_CS8;
+
+	if (termio->c_cflag & CSTOPB) {
+		if (mode == MX_CS5)
+			mode |= MX_STOP15;
+		else
+			mode |= MX_STOP2;
+	} else
+		mode |= MX_STOP1;
+
+	if (termio->c_cflag & PARENB) {
+		if (termio->c_cflag & PARODD)
+			mode |= MX_PARODD;
+		else
+			mode |= MX_PAREVEN;
+	} else
+		mode |= MX_PARNONE;
+
+	moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
+
+	if (MOXA_IS_320(port->board) && baud >= 921600)
+		return -1;
+
+	baud = MoxaPortSetBaud(port, baud);
+
+	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
+	        spin_lock_irq(&moxafunc_lock);
+		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
+		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
+		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
+		moxa_wait_finish(ofsAddr);
+		spin_unlock_irq(&moxafunc_lock);
+
+	}
+	return baud;
+}
+
+static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
+		int *rtsState)
+{
+	if (dtrState)
+		*dtrState = !!(port->lineCtrl & DTR_ON);
+	if (rtsState)
+		*rtsState = !!(port->lineCtrl & RTS_ON);
+
+	return 0;
+}
+
+static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
+{
+	u8 mode = 0;
+
+	if (dtr)
+		mode |= DTR_ON;
+	if (rts)
+		mode |= RTS_ON;
+	port->lineCtrl = mode;
+	moxafunc(port->tableAddr, FC_LineControl, mode);
+}
+
+static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
+		int txflow, int rxflow, int txany)
+{
+	int mode = 0;
+
+	if (rts)
+		mode |= RTS_FlowCtl;
+	if (cts)
+		mode |= CTS_FlowCtl;
+	if (txflow)
+		mode |= Tx_FlowCtl;
+	if (rxflow)
+		mode |= Rx_FlowCtl;
+	if (txany)
+		mode |= IXM_IXANY;
+	moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
+}
+
+static int MoxaPortLineStatus(struct moxa_port *port)
+{
+	void __iomem *ofsAddr;
+	int val;
+
+	ofsAddr = port->tableAddr;
+	if (MOXA_IS_320(port->board))
+		val = moxafuncret(ofsAddr, FC_LineStatus, 0);
+	else
+		val = readw(ofsAddr + FlagStat) >> 4;
+	val &= 0x0B;
+	if (val & 8)
+		val |= 4;
+	moxa_new_dcdstate(port, val & 8);
+	val &= 7;
+	return val;
+}
+
+static int MoxaPortWriteData(struct tty_struct *tty,
+		const unsigned char *buffer, int len)
+{
+	struct moxa_port *port = tty->driver_data;
+	void __iomem *baseAddr, *ofsAddr, *ofs;
+	unsigned int c, total;
+	u16 head, tail, tx_mask, spage, epage;
+	u16 pageno, pageofs, bufhead;
+
+	ofsAddr = port->tableAddr;
+	baseAddr = port->board->basemem;
+	tx_mask = readw(ofsAddr + TX_mask);
+	spage = readw(ofsAddr + Page_txb);
+	epage = readw(ofsAddr + EndPage_txb);
+	tail = readw(ofsAddr + TXwptr);
+	head = readw(ofsAddr + TXrptr);
+	c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
+	if (c > len)
+		c = len;
+	moxaLog.txcnt[port->port.tty->index] += c;
+	total = c;
+	if (spage == epage) {
+		bufhead = readw(ofsAddr + Ofs_txb);
+		writew(spage, baseAddr + Control_reg);
+		while (c > 0) {
+			if (head > tail)
+				len = head - tail - 1;
+			else
+				len = tx_mask + 1 - tail;
+			len = (c > len) ? len : c;
+			ofs = baseAddr + DynPage_addr + bufhead + tail;
+			memcpy_toio(ofs, buffer, len);
+			buffer += len;
+			tail = (tail + len) & tx_mask;
+			c -= len;
+		}
+	} else {
+		pageno = spage + (tail >> 13);
+		pageofs = tail & Page_mask;
+		while (c > 0) {
+			len = Page_size - pageofs;
+			if (len > c)
+				len = c;
+			writeb(pageno, baseAddr + Control_reg);
+			ofs = baseAddr + DynPage_addr + pageofs;
+			memcpy_toio(ofs, buffer, len);
+			buffer += len;
+			if (++pageno == epage)
+				pageno = spage;
+			pageofs = 0;
+			c -= len;
+		}
+		tail = (tail + total) & tx_mask;
+	}
+	writew(tail, ofsAddr + TXwptr);
+	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
+	return total;
+}
+
+static int MoxaPortReadData(struct moxa_port *port)
+{
+	struct tty_struct *tty = port->port.tty;
+	unsigned char *dst;
+	void __iomem *baseAddr, *ofsAddr, *ofs;
+	unsigned int count, len, total;
+	u16 tail, rx_mask, spage, epage;
+	u16 pageno, pageofs, bufhead, head;
+
+	ofsAddr = port->tableAddr;
+	baseAddr = port->board->basemem;
+	head = readw(ofsAddr + RXrptr);
+	tail = readw(ofsAddr + RXwptr);
+	rx_mask = readw(ofsAddr + RX_mask);
+	spage = readw(ofsAddr + Page_rxb);
+	epage = readw(ofsAddr + EndPage_rxb);
+	count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
+	if (count == 0)
+		return 0;
+
+	total = count;
+	moxaLog.rxcnt[tty->index] += total;
+	if (spage == epage) {
+		bufhead = readw(ofsAddr + Ofs_rxb);
+		writew(spage, baseAddr + Control_reg);
+		while (count > 0) {
+			ofs = baseAddr + DynPage_addr + bufhead + head;
+			len = (tail >= head) ? (tail - head) :
+					(rx_mask + 1 - head);
+			len = tty_prepare_flip_string(tty, &dst,
+					min(len, count));
+			memcpy_fromio(dst, ofs, len);
+			head = (head + len) & rx_mask;
+			count -= len;
+		}
+	} else {
+		pageno = spage + (head >> 13);
+		pageofs = head & Page_mask;
+		while (count > 0) {
+			writew(pageno, baseAddr + Control_reg);
+			ofs = baseAddr + DynPage_addr + pageofs;
+			len = tty_prepare_flip_string(tty, &dst,
+					min(Page_size - pageofs, count));
+			memcpy_fromio(dst, ofs, len);
+
+			count -= len;
+			pageofs = (pageofs + len) & Page_mask;
+			if (pageofs == 0 && ++pageno == epage)
+				pageno = spage;
+		}
+		head = (head + total) & rx_mask;
+	}
+	writew(head, ofsAddr + RXrptr);
+	if (readb(ofsAddr + FlagStat) & Xoff_state) {
+		moxaLowWaterChk = 1;
+		port->lowChkFlag = 1;
+	}
+	return total;
+}
+
+
+static int MoxaPortTxQueue(struct moxa_port *port)
+{
+	void __iomem *ofsAddr = port->tableAddr;
+	u16 rptr, wptr, mask;
+
+	rptr = readw(ofsAddr + TXrptr);
+	wptr = readw(ofsAddr + TXwptr);
+	mask = readw(ofsAddr + TX_mask);
+	return (wptr - rptr) & mask;
+}
+
+static int MoxaPortTxFree(struct moxa_port *port)
+{
+	void __iomem *ofsAddr = port->tableAddr;
+	u16 rptr, wptr, mask;
+
+	rptr = readw(ofsAddr + TXrptr);
+	wptr = readw(ofsAddr + TXwptr);
+	mask = readw(ofsAddr + TX_mask);
+	return mask - ((wptr - rptr) & mask);
+}
+
+static int MoxaPortRxQueue(struct moxa_port *port)
+{
+	void __iomem *ofsAddr = port->tableAddr;
+	u16 rptr, wptr, mask;
+
+	rptr = readw(ofsAddr + RXrptr);
+	wptr = readw(ofsAddr + RXwptr);
+	mask = readw(ofsAddr + RX_mask);
+	return (wptr - rptr) & mask;
+}
+
+static void MoxaPortTxDisable(struct moxa_port *port)
+{
+	moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
+}
+
+static void MoxaPortTxEnable(struct moxa_port *port)
+{
+	moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
+}
+
+static int moxa_get_serial_info(struct moxa_port *info,
+		struct serial_struct __user *retinfo)
+{
+	struct serial_struct tmp = {
+		.type = info->type,
+		.line = info->port.tty->index,
+		.flags = info->port.flags,
+		.baud_base = 921600,
+		.close_delay = info->port.close_delay
+	};
+	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
+}
+
+
+static int moxa_set_serial_info(struct moxa_port *info,
+		struct serial_struct __user *new_info)
+{
+	struct serial_struct new_serial;
+
+	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+		return -EFAULT;
+
+	if (new_serial.irq != 0 || new_serial.port != 0 ||
+			new_serial.custom_divisor != 0 ||
+			new_serial.baud_base != 921600)
+		return -EPERM;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (info->port.flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+	} else
+		info->port.close_delay = new_serial.close_delay * HZ / 100;
+
+	new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
+	new_serial.flags |= (info->port.flags & ASYNC_FLAGS);
+
+	MoxaSetFifo(info, new_serial.type == PORT_16550A);
+
+	info->type = new_serial.type;
+	return 0;
+}
+
+
+
+/*****************************************************************************
+ *	Static local functions: 					     *
+ *****************************************************************************/
+
+static void MoxaSetFifo(struct moxa_port *port, int enable)
+{
+	void __iomem *ofsAddr = port->tableAddr;
+
+	if (!enable) {
+		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
+		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
+	} else {
+		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
+		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
+	}
+}
diff --git a/drivers/tty/moxa.h b/drivers/tty/moxa.h
new file mode 100644
index 0000000..87d16ce
--- /dev/null
+++ b/drivers/tty/moxa.h
@@ -0,0 +1,304 @@
+#ifndef MOXA_H_FILE
+#define MOXA_H_FILE
+
+#define	MOXA		0x400
+#define MOXA_GET_IQUEUE 	(MOXA + 1)	/* get input buffered count */
+#define MOXA_GET_OQUEUE 	(MOXA + 2)	/* get output buffered count */
+#define MOXA_GETDATACOUNT       (MOXA + 23)
+#define MOXA_GET_IOQUEUE	(MOXA + 27)
+#define MOXA_FLUSH_QUEUE	(MOXA + 28)
+#define MOXA_GETMSTATUS         (MOXA + 65)
+
+/*
+ *    System Configuration
+ */
+
+#define Magic_code	0x404
+
+/*
+ *    for C218 BIOS initialization
+ */
+#define C218_ConfBase	0x800
+#define C218_status	(C218_ConfBase + 0)	/* BIOS running status    */
+#define C218_diag	(C218_ConfBase + 2)	/* diagnostic status      */
+#define C218_key	(C218_ConfBase + 4)	/* WORD (0x218 for C218) */
+#define C218DLoad_len	(C218_ConfBase + 6)	/* WORD           */
+#define C218check_sum	(C218_ConfBase + 8)	/* BYTE           */
+#define C218chksum_ok	(C218_ConfBase + 0x0a)	/* BYTE (1:ok)            */
+#define C218_TestRx	(C218_ConfBase + 0x10)	/* 8 bytes for 8 ports    */
+#define C218_TestTx	(C218_ConfBase + 0x18)	/* 8 bytes for 8 ports    */
+#define C218_RXerr	(C218_ConfBase + 0x20)	/* 8 bytes for 8 ports    */
+#define C218_ErrFlag	(C218_ConfBase + 0x28)	/* 8 bytes for 8 ports    */
+
+#define C218_LoadBuf	0x0F00
+#define C218_KeyCode	0x218
+#define CP204J_KeyCode	0x204
+
+/*
+ *    for C320 BIOS initialization
+ */
+#define C320_ConfBase	0x800
+#define C320_LoadBuf	0x0f00
+#define STS_init	0x05	/* for C320_status        */
+
+#define C320_status	C320_ConfBase + 0	/* BIOS running status    */
+#define C320_diag	C320_ConfBase + 2	/* diagnostic status      */
+#define C320_key	C320_ConfBase + 4	/* WORD (0320H for C320) */
+#define C320DLoad_len	C320_ConfBase + 6	/* WORD           */
+#define C320check_sum	C320_ConfBase + 8	/* WORD           */
+#define C320chksum_ok	C320_ConfBase + 0x0a	/* WORD (1:ok)            */
+#define C320bapi_len	C320_ConfBase + 0x0c	/* WORD           */
+#define C320UART_no	C320_ConfBase + 0x0e	/* WORD           */
+
+#define C320_KeyCode	0x320
+
+#define FixPage_addr	0x0000	/* starting addr of static page  */
+#define DynPage_addr	0x2000	/* starting addr of dynamic page */
+#define C218_start	0x3000	/* starting addr of C218 BIOS prg */
+#define Control_reg	0x1ff0	/* select page and reset control */
+#define HW_reset	0x80
+
+/*
+ *    Function Codes
+ */
+#define FC_CardReset	0x80
+#define FC_ChannelReset 1	/* C320 firmware not supported */
+#define FC_EnableCH	2
+#define FC_DisableCH	3
+#define FC_SetParam	4
+#define FC_SetMode	5
+#define FC_SetRate	6
+#define FC_LineControl	7
+#define FC_LineStatus	8
+#define FC_XmitControl	9
+#define FC_FlushQueue	10
+#define FC_SendBreak	11
+#define FC_StopBreak	12
+#define FC_LoopbackON	13
+#define FC_LoopbackOFF	14
+#define FC_ClrIrqTable	15
+#define FC_SendXon	16
+#define FC_SetTermIrq	17	/* C320 firmware not supported */
+#define FC_SetCntIrq	18	/* C320 firmware not supported */
+#define FC_SetBreakIrq	19
+#define FC_SetLineIrq	20
+#define FC_SetFlowCtl	21
+#define FC_GenIrq	22
+#define FC_InCD180	23
+#define FC_OutCD180	24
+#define FC_InUARTreg	23
+#define FC_OutUARTreg	24
+#define FC_SetXonXoff	25
+#define FC_OutCD180CCR	26
+#define FC_ExtIQueue	27
+#define FC_ExtOQueue	28
+#define FC_ClrLineIrq	29
+#define FC_HWFlowCtl	30
+#define FC_GetClockRate 35
+#define FC_SetBaud	36
+#define FC_SetDataMode  41
+#define FC_GetCCSR      43
+#define FC_GetDataError 45
+#define FC_RxControl	50
+#define FC_ImmSend	51
+#define FC_SetXonState	52
+#define FC_SetXoffState	53
+#define FC_SetRxFIFOTrig 54
+#define FC_SetTxFIFOCnt 55
+#define FC_UnixRate	56
+#define FC_UnixResetTimer 57
+
+#define	RxFIFOTrig1	0
+#define	RxFIFOTrig4	1
+#define	RxFIFOTrig8	2
+#define	RxFIFOTrig14	3
+
+/*
+ *    Dual-Ported RAM
+ */
+#define DRAM_global	0
+#define INT_data	(DRAM_global + 0)
+#define Config_base	(DRAM_global + 0x108)
+
+#define IRQindex	(INT_data + 0)
+#define IRQpending	(INT_data + 4)
+#define IRQtable	(INT_data + 8)
+
+/*
+ *    Interrupt Status
+ */
+#define IntrRx		0x01	/* receiver data O.K.             */
+#define IntrTx		0x02	/* transmit buffer empty  */
+#define IntrFunc	0x04	/* function complete              */
+#define IntrBreak	0x08	/* received break         */
+#define IntrLine	0x10	/* line status change
+				   for transmitter                */
+#define IntrIntr	0x20	/* received INTR code             */
+#define IntrQuit	0x40	/* received QUIT code             */
+#define IntrEOF 	0x80	/* received EOF code              */
+
+#define IntrRxTrigger 	0x100	/* rx data count reach tigger value */
+#define IntrTxTrigger 	0x200	/* tx data count below trigger value */
+
+#define Magic_no	(Config_base + 0)
+#define Card_model_no	(Config_base + 2)
+#define Total_ports	(Config_base + 4)
+#define Module_cnt	(Config_base + 8)
+#define Module_no	(Config_base + 10)
+#define Timer_10ms	(Config_base + 14)
+#define Disable_IRQ	(Config_base + 20)
+#define TMS320_PORT1	(Config_base + 22)
+#define TMS320_PORT2	(Config_base + 24)
+#define TMS320_CLOCK	(Config_base + 26)
+
+/*
+ *    DATA BUFFER in DRAM
+ */
+#define Extern_table	0x400	/* Base address of the external table
+				   (24 words *    64) total 3K bytes
+				   (24 words * 128) total 6K bytes */
+#define Extern_size	0x60	/* 96 bytes                       */
+#define RXrptr		0x00	/* read pointer for RX buffer     */
+#define RXwptr		0x02	/* write pointer for RX buffer    */
+#define TXrptr		0x04	/* read pointer for TX buffer     */
+#define TXwptr		0x06	/* write pointer for TX buffer    */
+#define HostStat	0x08	/* IRQ flag and general flag      */
+#define FlagStat	0x0A
+#define FlowControl	0x0C	/* B7 B6 B5 B4 B3 B2 B1 B0              */
+				/*  x  x  x  x  |  |  |  |            */
+				/*              |  |  |  + CTS flow   */
+				/*              |  |  +--- RTS flow   */
+				/*              |  +------ TX Xon/Xoff */
+				/*              +--------- RX Xon/Xoff */
+#define Break_cnt	0x0E	/* received break count   */
+#define CD180TXirq	0x10	/* if non-0: enable TX irq        */
+#define RX_mask 	0x12
+#define TX_mask 	0x14
+#define Ofs_rxb 	0x16
+#define Ofs_txb 	0x18
+#define Page_rxb	0x1A
+#define Page_txb	0x1C
+#define EndPage_rxb	0x1E
+#define EndPage_txb	0x20
+#define Data_error	0x22
+#define RxTrigger	0x28
+#define TxTrigger	0x2a
+
+#define rRXwptr 	0x34
+#define Low_water	0x36
+
+#define FuncCode	0x40
+#define FuncArg 	0x42
+#define FuncArg1	0x44
+
+#define C218rx_size	0x2000	/* 8K bytes */
+#define C218tx_size	0x8000	/* 32K bytes */
+
+#define C218rx_mask	(C218rx_size - 1)
+#define C218tx_mask	(C218tx_size - 1)
+
+#define C320p8rx_size	0x2000
+#define C320p8tx_size	0x8000
+#define C320p8rx_mask	(C320p8rx_size - 1)
+#define C320p8tx_mask	(C320p8tx_size - 1)
+
+#define C320p16rx_size	0x2000
+#define C320p16tx_size	0x4000
+#define C320p16rx_mask	(C320p16rx_size - 1)
+#define C320p16tx_mask	(C320p16tx_size - 1)
+
+#define C320p24rx_size	0x2000
+#define C320p24tx_size	0x2000
+#define C320p24rx_mask	(C320p24rx_size - 1)
+#define C320p24tx_mask	(C320p24tx_size - 1)
+
+#define C320p32rx_size	0x1000
+#define C320p32tx_size	0x1000
+#define C320p32rx_mask	(C320p32rx_size - 1)
+#define C320p32tx_mask	(C320p32tx_size - 1)
+
+#define Page_size	0x2000U
+#define Page_mask	(Page_size - 1)
+#define C218rx_spage	3
+#define C218tx_spage	4
+#define C218rx_pageno	1
+#define C218tx_pageno	4
+#define C218buf_pageno	5
+
+#define C320p8rx_spage	3
+#define C320p8tx_spage	4
+#define C320p8rx_pgno	1
+#define C320p8tx_pgno	4
+#define C320p8buf_pgno	5
+
+#define C320p16rx_spage 3
+#define C320p16tx_spage 4
+#define C320p16rx_pgno	1
+#define C320p16tx_pgno	2
+#define C320p16buf_pgno 3
+
+#define C320p24rx_spage 3
+#define C320p24tx_spage 4
+#define C320p24rx_pgno	1
+#define C320p24tx_pgno	1
+#define C320p24buf_pgno 2
+
+#define C320p32rx_spage 3
+#define C320p32tx_ofs	C320p32rx_size
+#define C320p32tx_spage 3
+#define C320p32buf_pgno 1
+
+/*
+ *    Host Status
+ */
+#define WakeupRx	0x01
+#define WakeupTx	0x02
+#define WakeupBreak	0x08
+#define WakeupLine	0x10
+#define WakeupIntr	0x20
+#define WakeupQuit	0x40
+#define WakeupEOF	0x80	/* used in VTIME control */
+#define WakeupRxTrigger	0x100
+#define WakeupTxTrigger	0x200
+/*
+ *    Flag status
+ */
+#define Rx_over		0x01
+#define Xoff_state	0x02
+#define Tx_flowOff	0x04
+#define Tx_enable	0x08
+#define CTS_state	0x10
+#define DSR_state	0x20
+#define DCD_state	0x80
+/*
+ *    FlowControl
+ */
+#define CTS_FlowCtl	1
+#define RTS_FlowCtl	2
+#define Tx_FlowCtl	4
+#define Rx_FlowCtl	8
+#define IXM_IXANY	0x10
+
+#define LowWater	128
+
+#define DTR_ON		1
+#define RTS_ON		2
+#define CTS_ON		1
+#define DSR_ON		2
+#define DCD_ON		8
+
+/* mode definition */
+#define	MX_CS8		0x03
+#define	MX_CS7		0x02
+#define	MX_CS6		0x01
+#define	MX_CS5		0x00
+
+#define	MX_STOP1	0x00
+#define	MX_STOP15	0x04
+#define	MX_STOP2	0x08
+
+#define	MX_PARNONE	0x00
+#define	MX_PAREVEN	0x40
+#define	MX_PARODD	0xC0
+
+#endif
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
new file mode 100644
index 0000000..d188f37
--- /dev/null
+++ b/drivers/tty/mxser.c
@@ -0,0 +1,2757 @@
+/*
+ *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver.
+ *
+ *      Copyright (C) 1999-2006  Moxa Technologies (support@moxa.com).
+ *	Copyright (C) 2006-2008  Jiri Slaby <jirislaby@gmail.com>
+ *
+ *      This code is loosely based on the 1.8 moxa driver which is based on
+ *	Linux serial driver, written by Linus Torvalds, Theodore T'so and
+ *	others.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *	Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
+ *	<alan@lxorguk.ukuu.org.uk>. The original 1.8 code is available on
+ *	www.moxa.com.
+ *	- Fixed x86_64 cleanness
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "mxser.h"
+
+#define	MXSER_VERSION	"2.0.5"		/* 1.14 */
+#define	MXSERMAJOR	 174
+
+#define MXSER_BOARDS		4	/* Max. boards */
+#define MXSER_PORTS_PER_BOARD	8	/* Max. ports per board */
+#define MXSER_PORTS		(MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
+#define MXSER_ISR_PASS_LIMIT	100
+
+/*CheckIsMoxaMust return value*/
+#define MOXA_OTHER_UART		0x00
+#define MOXA_MUST_MU150_HWID	0x01
+#define MOXA_MUST_MU860_HWID	0x02
+
+#define WAKEUP_CHARS		256
+
+#define UART_MCR_AFE		0x20
+#define UART_LSR_SPECIAL	0x1E
+
+#define PCI_DEVICE_ID_POS104UL	0x1044
+#define PCI_DEVICE_ID_CB108	0x1080
+#define PCI_DEVICE_ID_CP102UF	0x1023
+#define PCI_DEVICE_ID_CP112UL	0x1120
+#define PCI_DEVICE_ID_CB114	0x1142
+#define PCI_DEVICE_ID_CP114UL	0x1143
+#define PCI_DEVICE_ID_CB134I	0x1341
+#define PCI_DEVICE_ID_CP138U	0x1380
+
+
+#define C168_ASIC_ID    1
+#define C104_ASIC_ID    2
+#define C102_ASIC_ID	0xB
+#define CI132_ASIC_ID	4
+#define CI134_ASIC_ID	3
+#define CI104J_ASIC_ID  5
+
+#define MXSER_HIGHBAUD	1
+#define MXSER_HAS2	2
+
+/* This is only for PCI */
+static const struct {
+	int type;
+	int tx_fifo;
+	int rx_fifo;
+	int xmit_fifo_size;
+	int rx_high_water;
+	int rx_trigger;
+	int rx_low_water;
+	long max_baud;
+} Gpci_uart_info[] = {
+	{MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
+	{MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
+	{MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
+};
+#define UART_INFO_NUM	ARRAY_SIZE(Gpci_uart_info)
+
+struct mxser_cardinfo {
+	char *name;
+	unsigned int nports;
+	unsigned int flags;
+};
+
+static const struct mxser_cardinfo mxser_cards[] = {
+/* 0*/	{ "C168 series",	8, },
+	{ "C104 series",	4, },
+	{ "CI-104J series",	4, },
+	{ "C168H/PCI series",	8, },
+	{ "C104H/PCI series",	4, },
+/* 5*/	{ "C102 series",	4, MXSER_HAS2 },	/* C102-ISA */
+	{ "CI-132 series",	4, MXSER_HAS2 },
+	{ "CI-134 series",	4, },
+	{ "CP-132 series",	2, },
+	{ "CP-114 series",	4, },
+/*10*/	{ "CT-114 series",	4, },
+	{ "CP-102 series",	2, MXSER_HIGHBAUD },
+	{ "CP-104U series",	4, },
+	{ "CP-168U series",	8, },
+	{ "CP-132U series",	2, },
+/*15*/	{ "CP-134U series",	4, },
+	{ "CP-104JU series",	4, },
+	{ "Moxa UC7000 Serial",	8, },		/* RC7000 */
+	{ "CP-118U series",	8, },
+	{ "CP-102UL series",	2, },
+/*20*/	{ "CP-102U series",	2, },
+	{ "CP-118EL series",	8, },
+	{ "CP-168EL series",	8, },
+	{ "CP-104EL series",	4, },
+	{ "CB-108 series",	8, },
+/*25*/	{ "CB-114 series",	4, },
+	{ "CB-134I series",	4, },
+	{ "CP-138U series",	8, },
+	{ "POS-104UL series",	4, },
+	{ "CP-114UL series",	4, },
+/*30*/	{ "CP-102UF series",	2, },
+	{ "CP-112UL series",	2, },
+};
+
+/* driver_data correspond to the lines in the structure above
+   see also ISA probe function before you change something */
+static struct pci_device_id mxser_pcibrds[] = {
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168),	.driver_data = 3 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104),	.driver_data = 4 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132),	.driver_data = 8 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114),	.driver_data = 9 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114),	.driver_data = 10 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102),	.driver_data = 11 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U),	.driver_data = 12 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U),	.driver_data = 13 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U),	.driver_data = 14 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U),	.driver_data = 15 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000),	.driver_data = 17 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U),	.driver_data = 18 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U),	.driver_data = 20 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108),	.driver_data = 24 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114),	.driver_data = 25 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I),	.driver_data = 26 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U),	.driver_data = 27 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL),	.driver_data = 28 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL),	.driver_data = 29 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF),	.driver_data = 30 },
+	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL),	.driver_data = 31 },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
+
+static unsigned long ioaddr[MXSER_BOARDS];
+static int ttymajor = MXSERMAJOR;
+
+/* Variables for insmod */
+
+MODULE_AUTHOR("Casper Yang");
+MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
+module_param_array(ioaddr, ulong, NULL, 0);
+MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");
+module_param(ttymajor, int, 0);
+MODULE_LICENSE("GPL");
+
+struct mxser_log {
+	int tick;
+	unsigned long rxcnt[MXSER_PORTS];
+	unsigned long txcnt[MXSER_PORTS];
+};
+
+struct mxser_mon {
+	unsigned long rxcnt;
+	unsigned long txcnt;
+	unsigned long up_rxcnt;
+	unsigned long up_txcnt;
+	int modem_status;
+	unsigned char hold_reason;
+};
+
+struct mxser_mon_ext {
+	unsigned long rx_cnt[32];
+	unsigned long tx_cnt[32];
+	unsigned long up_rxcnt[32];
+	unsigned long up_txcnt[32];
+	int modem_status[32];
+
+	long baudrate[32];
+	int databits[32];
+	int stopbits[32];
+	int parity[32];
+	int flowctrl[32];
+	int fifo[32];
+	int iftype[32];
+};
+
+struct mxser_board;
+
+struct mxser_port {
+	struct tty_port port;
+	struct mxser_board *board;
+
+	unsigned long ioaddr;
+	unsigned long opmode_ioaddr;
+	int max_baud;
+
+	int rx_high_water;
+	int rx_trigger;		/* Rx fifo trigger level */
+	int rx_low_water;
+	int baud_base;		/* max. speed */
+	int type;		/* UART type */
+
+	int x_char;		/* xon/xoff character */
+	int IER;		/* Interrupt Enable Register */
+	int MCR;		/* Modem control register */
+
+	unsigned char stop_rx;
+	unsigned char ldisc_stop_rx;
+
+	int custom_divisor;
+	unsigned char err_shadow;
+
+	struct async_icount icount; /* kernel counters for 4 input interrupts */
+	int timeout;
+
+	int read_status_mask;
+	int ignore_status_mask;
+	int xmit_fifo_size;
+	int xmit_head;
+	int xmit_tail;
+	int xmit_cnt;
+
+	struct ktermios normal_termios;
+
+	struct mxser_mon mon_data;
+
+	spinlock_t slock;
+};
+
+struct mxser_board {
+	unsigned int idx;
+	int irq;
+	const struct mxser_cardinfo *info;
+	unsigned long vector;
+	unsigned long vector_mask;
+
+	int chip_flag;
+	int uart_type;
+
+	struct mxser_port ports[MXSER_PORTS_PER_BOARD];
+};
+
+struct mxser_mstatus {
+	tcflag_t cflag;
+	int cts;
+	int dsr;
+	int ri;
+	int dcd;
+};
+
+static struct mxser_board mxser_boards[MXSER_BOARDS];
+static struct tty_driver *mxvar_sdriver;
+static struct mxser_log mxvar_log;
+static int mxser_set_baud_method[MXSER_PORTS + 1];
+
+static void mxser_enable_must_enchance_mode(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr |= MOXA_MUST_EFR_EFRB_ENABLE;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+#ifdef	CONFIG_PCI
+static void mxser_disable_must_enchance_mode(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+#endif
+
+static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_BANK_MASK;
+	efr |= MOXA_MUST_EFR_BANK0;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(value, baseio + MOXA_MUST_XON1_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_BANK_MASK;
+	efr |= MOXA_MUST_EFR_BANK0;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(value, baseio + MOXA_MUST_XOFF1_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_set_must_fifo_value(struct mxser_port *info)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(info->ioaddr + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR);
+
+	efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_BANK_MASK;
+	efr |= MOXA_MUST_EFR_BANK1;
+
+	outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER);
+	outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER);
+	outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER);
+	outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER);
+	outb(oldlcr, info->ioaddr + UART_LCR);
+}
+
+static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_BANK_MASK;
+	efr |= MOXA_MUST_EFR_BANK2;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(value, baseio + MOXA_MUST_ENUM_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+#ifdef CONFIG_PCI
+static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_BANK_MASK;
+	efr |= MOXA_MUST_EFR_BANK2;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	*pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+#endif
+
+static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_SF_MASK;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_enable_must_tx_software_flow_control(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
+	efr |= MOXA_MUST_EFR_SF_TX1;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_disable_must_tx_software_flow_control(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_enable_must_rx_software_flow_control(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
+	efr |= MOXA_MUST_EFR_SF_RX1;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
+{
+	u8 oldlcr;
+	u8 efr;
+
+	oldlcr = inb(baseio + UART_LCR);
+	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
+
+	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
+	efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
+
+	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
+	outb(oldlcr, baseio + UART_LCR);
+}
+
+#ifdef CONFIG_PCI
+static int __devinit CheckIsMoxaMust(unsigned long io)
+{
+	u8 oldmcr, hwid;
+	int i;
+
+	outb(0, io + UART_LCR);
+	mxser_disable_must_enchance_mode(io);
+	oldmcr = inb(io + UART_MCR);
+	outb(0, io + UART_MCR);
+	mxser_set_must_xon1_value(io, 0x11);
+	if ((hwid = inb(io + UART_MCR)) != 0) {
+		outb(oldmcr, io + UART_MCR);
+		return MOXA_OTHER_UART;
+	}
+
+	mxser_get_must_hardware_id(io, &hwid);
+	for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
+		if (hwid == Gpci_uart_info[i].type)
+			return (int)hwid;
+	}
+	return MOXA_OTHER_UART;
+}
+#endif
+
+static void process_txrx_fifo(struct mxser_port *info)
+{
+	int i;
+
+	if ((info->type == PORT_16450) || (info->type == PORT_8250)) {
+		info->rx_trigger = 1;
+		info->rx_high_water = 1;
+		info->rx_low_water = 1;
+		info->xmit_fifo_size = 1;
+	} else
+		for (i = 0; i < UART_INFO_NUM; i++)
+			if (info->board->chip_flag == Gpci_uart_info[i].type) {
+				info->rx_trigger = Gpci_uart_info[i].rx_trigger;
+				info->rx_low_water = Gpci_uart_info[i].rx_low_water;
+				info->rx_high_water = Gpci_uart_info[i].rx_high_water;
+				info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;
+				break;
+			}
+}
+
+static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
+{
+	static unsigned char mxser_msr[MXSER_PORTS + 1];
+	unsigned char status = 0;
+
+	status = inb(baseaddr + UART_MSR);
+
+	mxser_msr[port] &= 0x0F;
+	mxser_msr[port] |= status;
+	status = mxser_msr[port];
+	if (mode)
+		mxser_msr[port] = 0;
+
+	return status;
+}
+
+static int mxser_carrier_raised(struct tty_port *port)
+{
+	struct mxser_port *mp = container_of(port, struct mxser_port, port);
+	return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
+}
+
+static void mxser_dtr_rts(struct tty_port *port, int on)
+{
+	struct mxser_port *mp = container_of(port, struct mxser_port, port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mp->slock, flags);
+	if (on)
+		outb(inb(mp->ioaddr + UART_MCR) |
+			UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR);
+	else
+		outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS),
+			mp->ioaddr + UART_MCR);
+	spin_unlock_irqrestore(&mp->slock, flags);
+}
+
+static int mxser_set_baud(struct tty_struct *tty, long newspd)
+{
+	struct mxser_port *info = tty->driver_data;
+	int quot = 0, baud;
+	unsigned char cval;
+
+	if (!info->ioaddr)
+		return -1;
+
+	if (newspd > info->max_baud)
+		return -1;
+
+	if (newspd == 134) {
+		quot = 2 * info->baud_base / 269;
+		tty_encode_baud_rate(tty, 134, 134);
+	} else if (newspd) {
+		quot = info->baud_base / newspd;
+		if (quot == 0)
+			quot = 1;
+		baud = info->baud_base/quot;
+		tty_encode_baud_rate(tty, baud, baud);
+	} else {
+		quot = 0;
+	}
+
+	info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
+	info->timeout += HZ / 50;	/* Add .02 seconds of slop */
+
+	if (quot) {
+		info->MCR |= UART_MCR_DTR;
+		outb(info->MCR, info->ioaddr + UART_MCR);
+	} else {
+		info->MCR &= ~UART_MCR_DTR;
+		outb(info->MCR, info->ioaddr + UART_MCR);
+		return 0;
+	}
+
+	cval = inb(info->ioaddr + UART_LCR);
+
+	outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR);	/* set DLAB */
+
+	outb(quot & 0xff, info->ioaddr + UART_DLL);	/* LS of divisor */
+	outb(quot >> 8, info->ioaddr + UART_DLM);	/* MS of divisor */
+	outb(cval, info->ioaddr + UART_LCR);	/* reset DLAB */
+
+#ifdef BOTHER
+	if (C_BAUD(tty) == BOTHER) {
+		quot = info->baud_base % newspd;
+		quot *= 8;
+		if (quot % newspd > newspd / 2) {
+			quot /= newspd;
+			quot++;
+		} else
+			quot /= newspd;
+
+		mxser_set_must_enum_value(info->ioaddr, quot);
+	} else
+#endif
+		mxser_set_must_enum_value(info->ioaddr, 0);
+
+	return 0;
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static int mxser_change_speed(struct tty_struct *tty,
+					struct ktermios *old_termios)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned cflag, cval, fcr;
+	int ret = 0;
+	unsigned char status;
+
+	cflag = tty->termios->c_cflag;
+	if (!info->ioaddr)
+		return ret;
+
+	if (mxser_set_baud_method[tty->index] == 0)
+		mxser_set_baud(tty, tty_get_baud_rate(tty));
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	case CS5:
+		cval = 0x00;
+		break;
+	case CS6:
+		cval = 0x01;
+		break;
+	case CS7:
+		cval = 0x02;
+		break;
+	case CS8:
+		cval = 0x03;
+		break;
+	default:
+		cval = 0x00;
+		break;		/* too keep GCC shut... */
+	}
+	if (cflag & CSTOPB)
+		cval |= 0x04;
+	if (cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+	if (cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+
+	if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
+		if (info->board->chip_flag) {
+			fcr = UART_FCR_ENABLE_FIFO;
+			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+			mxser_set_must_fifo_value(info);
+		} else
+			fcr = 0;
+	} else {
+		fcr = UART_FCR_ENABLE_FIFO;
+		if (info->board->chip_flag) {
+			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
+			mxser_set_must_fifo_value(info);
+		} else {
+			switch (info->rx_trigger) {
+			case 1:
+				fcr |= UART_FCR_TRIGGER_1;
+				break;
+			case 4:
+				fcr |= UART_FCR_TRIGGER_4;
+				break;
+			case 8:
+				fcr |= UART_FCR_TRIGGER_8;
+				break;
+			default:
+				fcr |= UART_FCR_TRIGGER_14;
+				break;
+			}
+		}
+	}
+
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	info->MCR &= ~UART_MCR_AFE;
+	if (cflag & CRTSCTS) {
+		info->port.flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+		if ((info->type == PORT_16550A) || (info->board->chip_flag)) {
+			info->MCR |= UART_MCR_AFE;
+		} else {
+			status = inb(info->ioaddr + UART_MSR);
+			if (tty->hw_stopped) {
+				if (status & UART_MSR_CTS) {
+					tty->hw_stopped = 0;
+					if (info->type != PORT_16550A &&
+							!info->board->chip_flag) {
+						outb(info->IER & ~UART_IER_THRI,
+							info->ioaddr +
+							UART_IER);
+						info->IER |= UART_IER_THRI;
+						outb(info->IER, info->ioaddr +
+								UART_IER);
+					}
+					tty_wakeup(tty);
+				}
+			} else {
+				if (!(status & UART_MSR_CTS)) {
+					tty->hw_stopped = 1;
+					if ((info->type != PORT_16550A) &&
+							(!info->board->chip_flag)) {
+						info->IER &= ~UART_IER_THRI;
+						outb(info->IER, info->ioaddr +
+								UART_IER);
+					}
+				}
+			}
+		}
+	} else {
+		info->port.flags &= ~ASYNC_CTS_FLOW;
+	}
+	outb(info->MCR, info->ioaddr + UART_MCR);
+	if (cflag & CLOCAL) {
+		info->port.flags &= ~ASYNC_CHECK_CD;
+	} else {
+		info->port.flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	outb(info->IER, info->ioaddr + UART_IER);
+
+	/*
+	 * Set up parity check flag
+	 */
+	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (I_INPCK(tty))
+		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (I_BRKINT(tty) || I_PARMRK(tty))
+		info->read_status_mask |= UART_LSR_BI;
+
+	info->ignore_status_mask = 0;
+
+	if (I_IGNBRK(tty)) {
+		info->ignore_status_mask |= UART_LSR_BI;
+		info->read_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(tty)) {
+			info->ignore_status_mask |=
+						UART_LSR_OE |
+						UART_LSR_PE |
+						UART_LSR_FE;
+			info->read_status_mask |=
+						UART_LSR_OE |
+						UART_LSR_PE |
+						UART_LSR_FE;
+		}
+	}
+	if (info->board->chip_flag) {
+		mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty));
+		mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty));
+		if (I_IXON(tty)) {
+			mxser_enable_must_rx_software_flow_control(
+					info->ioaddr);
+		} else {
+			mxser_disable_must_rx_software_flow_control(
+					info->ioaddr);
+		}
+		if (I_IXOFF(tty)) {
+			mxser_enable_must_tx_software_flow_control(
+					info->ioaddr);
+		} else {
+			mxser_disable_must_tx_software_flow_control(
+					info->ioaddr);
+		}
+	}
+
+
+	outb(fcr, info->ioaddr + UART_FCR);	/* set fcr */
+	outb(cval, info->ioaddr + UART_LCR);
+
+	return ret;
+}
+
+static void mxser_check_modem_status(struct tty_struct *tty,
+				struct mxser_port *port, int status)
+{
+	/* update input line counters */
+	if (status & UART_MSR_TERI)
+		port->icount.rng++;
+	if (status & UART_MSR_DDSR)
+		port->icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		port->icount.dcd++;
+	if (status & UART_MSR_DCTS)
+		port->icount.cts++;
+	port->mon_data.modem_status = status;
+	wake_up_interruptible(&port->port.delta_msr_wait);
+
+	if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&port->port.open_wait);
+	}
+
+	if (port->port.flags & ASYNC_CTS_FLOW) {
+		if (tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+				tty->hw_stopped = 0;
+
+				if ((port->type != PORT_16550A) &&
+						(!port->board->chip_flag)) {
+					outb(port->IER & ~UART_IER_THRI,
+						port->ioaddr + UART_IER);
+					port->IER |= UART_IER_THRI;
+					outb(port->IER, port->ioaddr +
+							UART_IER);
+				}
+				tty_wakeup(tty);
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+				tty->hw_stopped = 1;
+				if (port->type != PORT_16550A &&
+						!port->board->chip_flag) {
+					port->IER &= ~UART_IER_THRI;
+					outb(port->IER, port->ioaddr +
+							UART_IER);
+				}
+			}
+		}
+	}
+}
+
+static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
+{
+	struct mxser_port *info = container_of(port, struct mxser_port, port);
+	unsigned long page;
+	unsigned long flags;
+
+	page = __get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&info->slock, flags);
+
+	if (!info->ioaddr || !info->type) {
+		set_bit(TTY_IO_ERROR, &tty->flags);
+		free_page(page);
+		spin_unlock_irqrestore(&info->slock, flags);
+		return 0;
+	}
+	info->port.xmit_buf = (unsigned char *) page;
+
+	/*
+	 * Clear the FIFO buffers and disable them
+	 * (they will be reenabled in mxser_change_speed())
+	 */
+	if (info->board->chip_flag)
+		outb((UART_FCR_CLEAR_RCVR |
+			UART_FCR_CLEAR_XMIT |
+			MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
+	else
+		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+			info->ioaddr + UART_FCR);
+
+	/*
+	 * At this point there's no way the LSR could still be 0xFF;
+	 * if it is, then bail out, because there's likely no UART
+	 * here.
+	 */
+	if (inb(info->ioaddr + UART_LSR) == 0xff) {
+		spin_unlock_irqrestore(&info->slock, flags);
+		if (capable(CAP_SYS_ADMIN)) {
+			set_bit(TTY_IO_ERROR, &tty->flags);
+			return 0;
+		} else
+			return -ENODEV;
+	}
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) inb(info->ioaddr + UART_LSR);
+	(void) inb(info->ioaddr + UART_RX);
+	(void) inb(info->ioaddr + UART_IIR);
+	(void) inb(info->ioaddr + UART_MSR);
+
+	/*
+	 * Now, initialize the UART
+	 */
+	outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR);	/* reset DLAB */
+	info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+	outb(info->MCR, info->ioaddr + UART_MCR);
+
+	/*
+	 * Finally, enable interrupts
+	 */
+	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+
+	if (info->board->chip_flag)
+		info->IER |= MOXA_MUST_IER_EGDAI;
+	outb(info->IER, info->ioaddr + UART_IER);	/* enable interrupts */
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void) inb(info->ioaddr + UART_LSR);
+	(void) inb(info->ioaddr + UART_RX);
+	(void) inb(info->ioaddr + UART_IIR);
+	(void) inb(info->ioaddr + UART_MSR);
+
+	clear_bit(TTY_IO_ERROR, &tty->flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	mxser_change_speed(tty, NULL);
+	spin_unlock_irqrestore(&info->slock, flags);
+
+	return 0;
+}
+
+/*
+ * This routine will shutdown a serial port
+ */
+static void mxser_shutdown_port(struct tty_port *port)
+{
+	struct mxser_port *info = container_of(port, struct mxser_port, port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->port.delta_msr_wait);
+
+	/*
+	 * Free the xmit buffer, if necessary
+	 */
+	if (info->port.xmit_buf) {
+		free_page((unsigned long) info->port.xmit_buf);
+		info->port.xmit_buf = NULL;
+	}
+
+	info->IER = 0;
+	outb(0x00, info->ioaddr + UART_IER);
+
+	/* clear Rx/Tx FIFO's */
+	if (info->board->chip_flag)
+		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
+				MOXA_MUST_FCR_GDA_MODE_ENABLE,
+				info->ioaddr + UART_FCR);
+	else
+		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+			info->ioaddr + UART_FCR);
+
+	/* read data port to reset things */
+	(void) inb(info->ioaddr + UART_RX);
+
+
+	if (info->board->chip_flag)
+		SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
+
+	spin_unlock_irqrestore(&info->slock, flags);
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+static int mxser_open(struct tty_struct *tty, struct file *filp)
+{
+	struct mxser_port *info;
+	int line;
+
+	line = tty->index;
+	if (line == MXSER_PORTS)
+		return 0;
+	if (line < 0 || line > MXSER_PORTS)
+		return -ENODEV;
+	info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD];
+	if (!info->ioaddr)
+		return -ENODEV;
+
+	tty->driver_data = info;
+	return tty_port_open(&info->port, tty, filp);
+}
+
+static void mxser_flush_buffer(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	char fcr;
+	unsigned long flags;
+
+
+	spin_lock_irqsave(&info->slock, flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	fcr = inb(info->ioaddr + UART_FCR);
+	outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+		info->ioaddr + UART_FCR);
+	outb(fcr, info->ioaddr + UART_FCR);
+
+	spin_unlock_irqrestore(&info->slock, flags);
+
+	tty_wakeup(tty);
+}
+
+
+static void mxser_close_port(struct tty_port *port)
+{
+	struct mxser_port *info = container_of(port, struct mxser_port, port);
+	unsigned long timeout;
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->IER &= ~UART_IER_RLSI;
+	if (info->board->chip_flag)
+		info->IER &= ~MOXA_MUST_RECV_ISR;
+
+	outb(info->IER, info->ioaddr + UART_IER);
+	/*
+	 * Before we drop DTR, make sure the UART transmitter
+	 * has completely drained; this is especially
+	 * important if there is a transmit FIFO!
+	 */
+	timeout = jiffies + HZ;
+	while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
+		schedule_timeout_interruptible(5);
+		if (time_after(jiffies, timeout))
+			break;
+	}
+}
+
+/*
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ */
+static void mxser_close(struct tty_struct *tty, struct file *filp)
+{
+	struct mxser_port *info = tty->driver_data;
+	struct tty_port *port = &info->port;
+
+	if (tty->index == MXSER_PORTS || info == NULL)
+		return;
+	if (tty_port_close_start(port, tty, filp) == 0)
+		return;
+	mutex_lock(&port->mutex);
+	mxser_close_port(port);
+	mxser_flush_buffer(tty);
+	mxser_shutdown_port(port);
+	clear_bit(ASYNCB_INITIALIZED, &port->flags);
+	mutex_unlock(&port->mutex);
+	/* Right now the tty_port set is done outside of the close_end helper
+	   as we don't yet have everyone using refcounts */	
+	tty_port_close_end(port, tty);
+	tty_port_tty_set(port, NULL);
+}
+
+static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+	int c, total = 0;
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	if (!info->port.xmit_buf)
+		return 0;
+
+	while (1) {
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
+		if (c <= 0)
+			break;
+
+		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
+		spin_lock_irqsave(&info->slock, flags);
+		info->xmit_head = (info->xmit_head + c) &
+				  (SERIAL_XMIT_SIZE - 1);
+		info->xmit_cnt += c;
+		spin_unlock_irqrestore(&info->slock, flags);
+
+		buf += c;
+		count -= c;
+		total += c;
+	}
+
+	if (info->xmit_cnt && !tty->stopped) {
+		if (!tty->hw_stopped ||
+				(info->type == PORT_16550A) ||
+				(info->board->chip_flag)) {
+			spin_lock_irqsave(&info->slock, flags);
+			outb(info->IER & ~UART_IER_THRI, info->ioaddr +
+					UART_IER);
+			info->IER |= UART_IER_THRI;
+			outb(info->IER, info->ioaddr + UART_IER);
+			spin_unlock_irqrestore(&info->slock, flags);
+		}
+	}
+	return total;
+}
+
+static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	if (!info->port.xmit_buf)
+		return 0;
+
+	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
+		return 0;
+
+	spin_lock_irqsave(&info->slock, flags);
+	info->port.xmit_buf[info->xmit_head++] = ch;
+	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+	info->xmit_cnt++;
+	spin_unlock_irqrestore(&info->slock, flags);
+	if (!tty->stopped) {
+		if (!tty->hw_stopped ||
+				(info->type == PORT_16550A) ||
+				info->board->chip_flag) {
+			spin_lock_irqsave(&info->slock, flags);
+			outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+			info->IER |= UART_IER_THRI;
+			outb(info->IER, info->ioaddr + UART_IER);
+			spin_unlock_irqrestore(&info->slock, flags);
+		}
+	}
+	return 1;
+}
+
+
+static void mxser_flush_chars(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf ||
+			(tty->hw_stopped && info->type != PORT_16550A &&
+			 !info->board->chip_flag))
+		return;
+
+	spin_lock_irqsave(&info->slock, flags);
+
+	outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+	info->IER |= UART_IER_THRI;
+	outb(info->IER, info->ioaddr + UART_IER);
+
+	spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static int mxser_write_room(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	int ret;
+
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	return ret < 0 ? 0 : ret;
+}
+
+static int mxser_chars_in_buffer(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	return info->xmit_cnt;
+}
+
+/*
+ * ------------------------------------------------------------
+ * friends of mxser_ioctl()
+ * ------------------------------------------------------------
+ */
+static int mxser_get_serial_info(struct tty_struct *tty,
+		struct serial_struct __user *retinfo)
+{
+	struct mxser_port *info = tty->driver_data;
+	struct serial_struct tmp = {
+		.type = info->type,
+		.line = tty->index,
+		.port = info->ioaddr,
+		.irq = info->board->irq,
+		.flags = info->port.flags,
+		.baud_base = info->baud_base,
+		.close_delay = info->port.close_delay,
+		.closing_wait = info->port.closing_wait,
+		.custom_divisor = info->custom_divisor,
+		.hub6 = 0
+	};
+	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int mxser_set_serial_info(struct tty_struct *tty,
+		struct serial_struct __user *new_info)
+{
+	struct mxser_port *info = tty->driver_data;
+	struct tty_port *port = &info->port;
+	struct serial_struct new_serial;
+	speed_t baud;
+	unsigned long sl_flags;
+	unsigned int flags;
+	int retval = 0;
+
+	if (!new_info || !info->ioaddr)
+		return -ENODEV;
+	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+		return -EFAULT;
+
+	if (new_serial.irq != info->board->irq ||
+			new_serial.port != info->ioaddr)
+		return -EINVAL;
+
+	flags = port->flags & ASYNC_SPD_MASK;
+
+	if (!capable(CAP_SYS_ADMIN)) {
+		if ((new_serial.baud_base != info->baud_base) ||
+				(new_serial.close_delay != info->port.close_delay) ||
+				((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
+				(new_serial.flags & ASYNC_USR_MASK));
+	} else {
+		/*
+		 * OK, past this point, all the error checking has been done.
+		 * At this point, we start making changes.....
+		 */
+		port->flags = ((port->flags & ~ASYNC_FLAGS) |
+				(new_serial.flags & ASYNC_FLAGS));
+		port->close_delay = new_serial.close_delay * HZ / 100;
+		port->closing_wait = new_serial.closing_wait * HZ / 100;
+		tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
+				(new_serial.baud_base != info->baud_base ||
+				new_serial.custom_divisor !=
+				info->custom_divisor)) {
+			if (new_serial.custom_divisor == 0)
+				return -EINVAL;
+			baud = new_serial.baud_base / new_serial.custom_divisor;
+			tty_encode_baud_rate(tty, baud, baud);
+		}
+	}
+
+	info->type = new_serial.type;
+
+	process_txrx_fifo(info);
+
+	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		if (flags != (port->flags & ASYNC_SPD_MASK)) {
+			spin_lock_irqsave(&info->slock, sl_flags);
+			mxser_change_speed(tty, NULL);
+			spin_unlock_irqrestore(&info->slock, sl_flags);
+		}
+	} else {
+		retval = mxser_activate(port, tty);
+		if (retval == 0)
+			set_bit(ASYNCB_INITIALIZED, &port->flags);
+	}
+	return retval;
+}
+
+/*
+ * mxser_get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *	    is emptied.  On bus types like RS485, the transmitter must
+ *	    release the bus after transmitting. This must be done when
+ *	    the transmit shift register is empty, not be done when the
+ *	    transmit holding register is empty.  This functionality
+ *	    allows an RS485 driver to be written in user space.
+ */
+static int mxser_get_lsr_info(struct mxser_port *info,
+		unsigned int __user *value)
+{
+	unsigned char status;
+	unsigned int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	status = inb(info->ioaddr + UART_LSR);
+	spin_unlock_irqrestore(&info->slock, flags);
+	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+	return put_user(result, value);
+}
+
+static int mxser_tiocmget(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned char control, status;
+	unsigned long flags;
+
+
+	if (tty->index == MXSER_PORTS)
+		return -ENOIOCTLCMD;
+	if (test_bit(TTY_IO_ERROR, &tty->flags))
+		return -EIO;
+
+	control = info->MCR;
+
+	spin_lock_irqsave(&info->slock, flags);
+	status = inb(info->ioaddr + UART_MSR);
+	if (status & UART_MSR_ANY_DELTA)
+		mxser_check_modem_status(tty, info, status);
+	spin_unlock_irqrestore(&info->slock, flags);
+	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
+		    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
+		    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+		    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
+		    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+		    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+}
+
+static int mxser_tiocmset(struct tty_struct *tty,
+		unsigned int set, unsigned int clear)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+
+	if (tty->index == MXSER_PORTS)
+		return -ENOIOCTLCMD;
+	if (test_bit(TTY_IO_ERROR, &tty->flags))
+		return -EIO;
+
+	spin_lock_irqsave(&info->slock, flags);
+
+	if (set & TIOCM_RTS)
+		info->MCR |= UART_MCR_RTS;
+	if (set & TIOCM_DTR)
+		info->MCR |= UART_MCR_DTR;
+
+	if (clear & TIOCM_RTS)
+		info->MCR &= ~UART_MCR_RTS;
+	if (clear & TIOCM_DTR)
+		info->MCR &= ~UART_MCR_DTR;
+
+	outb(info->MCR, info->ioaddr + UART_MCR);
+	spin_unlock_irqrestore(&info->slock, flags);
+	return 0;
+}
+
+static int __init mxser_program_mode(int port)
+{
+	int id, i, j, n;
+
+	outb(0, port);
+	outb(0, port);
+	outb(0, port);
+	(void)inb(port);
+	(void)inb(port);
+	outb(0, port);
+	(void)inb(port);
+
+	id = inb(port + 1) & 0x1F;
+	if ((id != C168_ASIC_ID) &&
+			(id != C104_ASIC_ID) &&
+			(id != C102_ASIC_ID) &&
+			(id != CI132_ASIC_ID) &&
+			(id != CI134_ASIC_ID) &&
+			(id != CI104J_ASIC_ID))
+		return -1;
+	for (i = 0, j = 0; i < 4; i++) {
+		n = inb(port + 2);
+		if (n == 'M') {
+			j = 1;
+		} else if ((j == 1) && (n == 1)) {
+			j = 2;
+			break;
+		} else
+			j = 0;
+	}
+	if (j != 2)
+		id = -2;
+	return id;
+}
+
+static void __init mxser_normal_mode(int port)
+{
+	int i, n;
+
+	outb(0xA5, port + 1);
+	outb(0x80, port + 3);
+	outb(12, port + 0);	/* 9600 bps */
+	outb(0, port + 1);
+	outb(0x03, port + 3);	/* 8 data bits */
+	outb(0x13, port + 4);	/* loop back mode */
+	for (i = 0; i < 16; i++) {
+		n = inb(port + 5);
+		if ((n & 0x61) == 0x60)
+			break;
+		if ((n & 1) == 1)
+			(void)inb(port);
+	}
+	outb(0x00, port + 4);
+}
+
+#define CHIP_SK 	0x01	/* Serial Data Clock  in Eprom */
+#define CHIP_DO 	0x02	/* Serial Data Output in Eprom */
+#define CHIP_CS 	0x04	/* Serial Chip Select in Eprom */
+#define CHIP_DI 	0x08	/* Serial Data Input  in Eprom */
+#define EN_CCMD 	0x000	/* Chip's command register     */
+#define EN0_RSARLO	0x008	/* Remote start address reg 0  */
+#define EN0_RSARHI	0x009	/* Remote start address reg 1  */
+#define EN0_RCNTLO	0x00A	/* Remote byte count reg WR    */
+#define EN0_RCNTHI	0x00B	/* Remote byte count reg WR    */
+#define EN0_DCFG	0x00E	/* Data configuration reg WR   */
+#define EN0_PORT	0x010	/* Rcv missed frame error counter RD */
+#define ENC_PAGE0	0x000	/* Select page 0 of chip registers   */
+#define ENC_PAGE3	0x0C0	/* Select page 3 of chip registers   */
+static int __init mxser_read_register(int port, unsigned short *regs)
+{
+	int i, k, value, id;
+	unsigned int j;
+
+	id = mxser_program_mode(port);
+	if (id < 0)
+		return id;
+	for (i = 0; i < 14; i++) {
+		k = (i & 0x3F) | 0x180;
+		for (j = 0x100; j > 0; j >>= 1) {
+			outb(CHIP_CS, port);
+			if (k & j) {
+				outb(CHIP_CS | CHIP_DO, port);
+				outb(CHIP_CS | CHIP_DO | CHIP_SK, port);	/* A? bit of read */
+			} else {
+				outb(CHIP_CS, port);
+				outb(CHIP_CS | CHIP_SK, port);	/* A? bit of read */
+			}
+		}
+		(void)inb(port);
+		value = 0;
+		for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
+			outb(CHIP_CS, port);
+			outb(CHIP_CS | CHIP_SK, port);
+			if (inb(port) & CHIP_DI)
+				value |= j;
+		}
+		regs[i] = value;
+		outb(0, port);
+	}
+	mxser_normal_mode(port);
+	return id;
+}
+
+static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
+{
+	struct mxser_port *ip;
+	struct tty_port *port;
+	struct tty_struct *tty;
+	int result, status;
+	unsigned int i, j;
+	int ret = 0;
+
+	switch (cmd) {
+	case MOXA_GET_MAJOR:
+		if (printk_ratelimit())
+			printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
+					"%x (GET_MAJOR), fix your userspace\n",
+					current->comm, cmd);
+		return put_user(ttymajor, (int __user *)argp);
+
+	case MOXA_CHKPORTENABLE:
+		result = 0;
+		for (i = 0; i < MXSER_BOARDS; i++)
+			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
+				if (mxser_boards[i].ports[j].ioaddr)
+					result |= (1 << i);
+		return put_user(result, (unsigned long __user *)argp);
+	case MOXA_GETDATACOUNT:
+		/* The receive side is locked by port->slock but it isn't
+		   clear that an exact snapshot is worth copying here */
+		if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
+			ret = -EFAULT;
+		return ret;
+	case MOXA_GETMSTATUS: {
+		struct mxser_mstatus ms, __user *msu = argp;
+		for (i = 0; i < MXSER_BOARDS; i++)
+			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
+				ip = &mxser_boards[i].ports[j];
+				port = &ip->port;
+				memset(&ms, 0, sizeof(ms));
+
+				mutex_lock(&port->mutex);
+				if (!ip->ioaddr)
+					goto copy;
+				
+				tty = tty_port_tty_get(port);
+
+				if (!tty || !tty->termios)
+					ms.cflag = ip->normal_termios.c_cflag;
+				else
+					ms.cflag = tty->termios->c_cflag;
+				tty_kref_put(tty);
+				spin_lock_irq(&ip->slock);
+				status = inb(ip->ioaddr + UART_MSR);
+				spin_unlock_irq(&ip->slock);
+				if (status & UART_MSR_DCD)
+					ms.dcd = 1;
+				if (status & UART_MSR_DSR)
+					ms.dsr = 1;
+				if (status & UART_MSR_CTS)
+					ms.cts = 1;
+			copy:
+				mutex_unlock(&port->mutex);
+				if (copy_to_user(msu, &ms, sizeof(ms)))
+					return -EFAULT;
+				msu++;
+			}
+		return 0;
+	}
+	case MOXA_ASPP_MON_EXT: {
+		struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */
+		unsigned int cflag, iflag, p;
+		u8 opmode;
+
+		me = kzalloc(sizeof(*me), GFP_KERNEL);
+		if (!me)
+			return -ENOMEM;
+
+		for (i = 0, p = 0; i < MXSER_BOARDS; i++) {
+			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) {
+				if (p >= ARRAY_SIZE(me->rx_cnt)) {
+					i = MXSER_BOARDS;
+					break;
+				}
+				ip = &mxser_boards[i].ports[j];
+				port = &ip->port;
+
+				mutex_lock(&port->mutex);
+				if (!ip->ioaddr) {
+					mutex_unlock(&port->mutex);
+					continue;
+				}
+
+				spin_lock_irq(&ip->slock);
+				status = mxser_get_msr(ip->ioaddr, 0, p);
+
+				if (status & UART_MSR_TERI)
+					ip->icount.rng++;
+				if (status & UART_MSR_DDSR)
+					ip->icount.dsr++;
+				if (status & UART_MSR_DDCD)
+					ip->icount.dcd++;
+				if (status & UART_MSR_DCTS)
+					ip->icount.cts++;
+
+				ip->mon_data.modem_status = status;
+				me->rx_cnt[p] = ip->mon_data.rxcnt;
+				me->tx_cnt[p] = ip->mon_data.txcnt;
+				me->up_rxcnt[p] = ip->mon_data.up_rxcnt;
+				me->up_txcnt[p] = ip->mon_data.up_txcnt;
+				me->modem_status[p] =
+					ip->mon_data.modem_status;
+				spin_unlock_irq(&ip->slock);
+
+				tty = tty_port_tty_get(&ip->port);
+
+				if (!tty || !tty->termios) {
+					cflag = ip->normal_termios.c_cflag;
+					iflag = ip->normal_termios.c_iflag;
+					me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
+				} else {
+					cflag = tty->termios->c_cflag;
+					iflag = tty->termios->c_iflag;
+					me->baudrate[p] = tty_get_baud_rate(tty);
+				}
+				tty_kref_put(tty);
+
+				me->databits[p] = cflag & CSIZE;
+				me->stopbits[p] = cflag & CSTOPB;
+				me->parity[p] = cflag & (PARENB | PARODD |
+						CMSPAR);
+
+				if (cflag & CRTSCTS)
+					me->flowctrl[p] |= 0x03;
+
+				if (iflag & (IXON | IXOFF))
+					me->flowctrl[p] |= 0x0C;
+
+				if (ip->type == PORT_16550A)
+					me->fifo[p] = 1;
+
+				opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
+				opmode &= OP_MODE_MASK;
+				me->iftype[p] = opmode;
+				mutex_unlock(&port->mutex);
+			}
+		}
+		if (copy_to_user(argp, me, sizeof(*me)))
+			ret = -EFAULT;
+		kfree(me);
+		return ret;
+	}
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg,
+		struct async_icount *cprev)
+{
+	struct async_icount cnow;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&info->slock, flags);
+	cnow = info->icount;	/* atomic copy */
+	spin_unlock_irqrestore(&info->slock, 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;
+}
+
+static int mxser_ioctl(struct tty_struct *tty,
+		unsigned int cmd, unsigned long arg)
+{
+	struct mxser_port *info = tty->driver_data;
+	struct tty_port *port = &info->port;
+	struct async_icount cnow;
+	unsigned long flags;
+	void __user *argp = (void __user *)arg;
+	int retval;
+
+	if (tty->index == MXSER_PORTS)
+		return mxser_ioctl_special(cmd, argp);
+
+	if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
+		int p;
+		unsigned long opmode;
+		static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
+		int shiftbit;
+		unsigned char val, mask;
+
+		p = tty->index % 4;
+		if (cmd == MOXA_SET_OP_MODE) {
+			if (get_user(opmode, (int __user *) argp))
+				return -EFAULT;
+			if (opmode != RS232_MODE &&
+					opmode != RS485_2WIRE_MODE &&
+					opmode != RS422_MODE &&
+					opmode != RS485_4WIRE_MODE)
+				return -EFAULT;
+			mask = ModeMask[p];
+			shiftbit = p * 2;
+			spin_lock_irq(&info->slock);
+			val = inb(info->opmode_ioaddr);
+			val &= mask;
+			val |= (opmode << shiftbit);
+			outb(val, info->opmode_ioaddr);
+			spin_unlock_irq(&info->slock);
+		} else {
+			shiftbit = p * 2;
+			spin_lock_irq(&info->slock);
+			opmode = inb(info->opmode_ioaddr) >> shiftbit;
+			spin_unlock_irq(&info->slock);
+			opmode &= OP_MODE_MASK;
+			if (put_user(opmode, (int __user *)argp))
+				return -EFAULT;
+		}
+		return 0;
+	}
+
+	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
+			test_bit(TTY_IO_ERROR, &tty->flags))
+		return -EIO;
+
+	switch (cmd) {
+	case TIOCGSERIAL:
+		mutex_lock(&port->mutex);
+		retval = mxser_get_serial_info(tty, argp);
+		mutex_unlock(&port->mutex);
+		return retval;
+	case TIOCSSERIAL:
+		mutex_lock(&port->mutex);
+		retval = mxser_set_serial_info(tty, argp);
+		mutex_unlock(&port->mutex);
+		return retval;
+	case TIOCSERGETLSR:	/* Get line status register */
+		return  mxser_get_lsr_info(info, argp);
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+	case TIOCMIWAIT:
+		spin_lock_irqsave(&info->slock, flags);
+		cnow = info->icount;	/* note the counters on entry */
+		spin_unlock_irqrestore(&info->slock, flags);
+
+		return wait_event_interruptible(info->port.delta_msr_wait,
+				mxser_cflags_changed(info, arg, &cnow));
+	case MOXA_HighSpeedOn:
+		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
+	case MOXA_SDS_RSTICOUNTER:
+		spin_lock_irq(&info->slock);
+		info->mon_data.rxcnt = 0;
+		info->mon_data.txcnt = 0;
+		spin_unlock_irq(&info->slock);
+		return 0;
+
+	case MOXA_ASPP_OQUEUE:{
+		int len, lsr;
+
+		len = mxser_chars_in_buffer(tty);
+		spin_lock_irq(&info->slock);
+		lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE;
+		spin_unlock_irq(&info->slock);
+		len += (lsr ? 0 : 1);
+
+		return put_user(len, (int __user *)argp);
+	}
+	case MOXA_ASPP_MON: {
+		int mcr, status;
+
+		spin_lock_irq(&info->slock);
+		status = mxser_get_msr(info->ioaddr, 1, tty->index);
+		mxser_check_modem_status(tty, info, status);
+
+		mcr = inb(info->ioaddr + UART_MCR);
+		spin_unlock_irq(&info->slock);
+
+		if (mcr & MOXA_MUST_MCR_XON_FLAG)
+			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
+		else
+			info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;
+
+		if (mcr & MOXA_MUST_MCR_TX_XON)
+			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;
+		else
+			info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
+
+		if (tty->hw_stopped)
+			info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
+		else
+			info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
+
+		if (copy_to_user(argp, &info->mon_data,
+				sizeof(struct mxser_mon)))
+			return -EFAULT;
+
+		return 0;
+	}
+	case MOXA_ASPP_LSTATUS: {
+		if (put_user(info->err_shadow, (unsigned char __user *)argp))
+			return -EFAULT;
+
+		info->err_shadow = 0;
+		return 0;
+	}
+	case MOXA_SET_BAUD_METHOD: {
+		int method;
+
+		if (get_user(method, (int __user *)argp))
+			return -EFAULT;
+		mxser_set_baud_method[tty->index] = method;
+		return put_user(method, (int __user *)argp);
+	}
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+	/*
+	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+	 * Return: write counters to the user passed counter struct
+	 * NB: both 1->0 and 0->1 transitions are counted except for
+	 *     RI where only 0->1 is counted.
+	 */
+
+static int mxser_get_icount(struct tty_struct *tty,
+		struct serial_icounter_struct *icount)
+
+{
+	struct mxser_port *info = tty->driver_data;
+	struct async_icount cnow;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->slock, flags);
+
+	icount->frame = cnow.frame;
+	icount->brk = cnow.brk;
+	icount->overrun = cnow.overrun;
+	icount->buf_overrun = cnow.buf_overrun;
+	icount->parity = cnow.parity;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	return 0;
+}
+
+static void mxser_stoprx(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+
+	info->ldisc_stop_rx = 1;
+	if (I_IXOFF(tty)) {
+		if (info->board->chip_flag) {
+			info->IER &= ~MOXA_MUST_RECV_ISR;
+			outb(info->IER, info->ioaddr + UART_IER);
+		} else {
+			info->x_char = STOP_CHAR(tty);
+			outb(0, info->ioaddr + UART_IER);
+			info->IER |= UART_IER_THRI;
+			outb(info->IER, info->ioaddr + UART_IER);
+		}
+	}
+
+	if (tty->termios->c_cflag & CRTSCTS) {
+		info->MCR &= ~UART_MCR_RTS;
+		outb(info->MCR, info->ioaddr + UART_MCR);
+	}
+}
+
+/*
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ */
+static void mxser_throttle(struct tty_struct *tty)
+{
+	mxser_stoprx(tty);
+}
+
+static void mxser_unthrottle(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+
+	/* startrx */
+	info->ldisc_stop_rx = 0;
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else {
+			if (info->board->chip_flag) {
+				info->IER |= MOXA_MUST_RECV_ISR;
+				outb(info->IER, info->ioaddr + UART_IER);
+			} else {
+				info->x_char = START_CHAR(tty);
+				outb(0, info->ioaddr + UART_IER);
+				info->IER |= UART_IER_THRI;
+				outb(info->IER, info->ioaddr + UART_IER);
+			}
+		}
+	}
+
+	if (tty->termios->c_cflag & CRTSCTS) {
+		info->MCR |= UART_MCR_RTS;
+		outb(info->MCR, info->ioaddr + UART_MCR);
+	}
+}
+
+/*
+ * mxser_stop() and mxser_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ */
+static void mxser_stop(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	if (info->IER & UART_IER_THRI) {
+		info->IER &= ~UART_IER_THRI;
+		outb(info->IER, info->ioaddr + UART_IER);
+	}
+	spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_start(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	if (info->xmit_cnt && info->port.xmit_buf) {
+		outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
+		info->IER |= UART_IER_THRI;
+		outb(info->IER, info->ioaddr + UART_IER);
+	}
+	spin_unlock_irqrestore(&info->slock, flags);
+}
+
+static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	mxser_change_speed(tty, old_termios);
+	spin_unlock_irqrestore(&info->slock, flags);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+			!(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		mxser_start(tty);
+	}
+
+	/* Handle sw stopped */
+	if ((old_termios->c_iflag & IXON) &&
+			!(tty->termios->c_iflag & IXON)) {
+		tty->stopped = 0;
+
+		if (info->board->chip_flag) {
+			spin_lock_irqsave(&info->slock, flags);
+			mxser_disable_must_rx_software_flow_control(
+					info->ioaddr);
+			spin_unlock_irqrestore(&info->slock, flags);
+		}
+
+		mxser_start(tty);
+	}
+}
+
+/*
+ * mxser_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	unsigned long flags;
+	int lsr;
+
+	if (info->type == PORT_UNKNOWN)
+		return;
+
+	if (info->xmit_fifo_size == 0)
+		return;		/* Just in case.... */
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 *
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout && timeout < char_time)
+		char_time = timeout;
+	/*
+	 * If the transmitter hasn't cleared in twice the approximate
+	 * amount of time to send the entire FIFO, it probably won't
+	 * ever clear.  This assumes the UART isn't doing flow
+	 * control, which is currently the case.  Hence, if it ever
+	 * takes longer than info->timeout, this is probably due to a
+	 * UART bug of some kind.  So, we clamp the timeout parameter at
+	 * 2*info->timeout.
+	 */
+	if (!timeout || timeout > 2 * info->timeout)
+		timeout = 2 * info->timeout;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
+		timeout, char_time);
+	printk("jiff=%lu...", jiffies);
+#endif
+	spin_lock_irqsave(&info->slock, flags);
+	while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		spin_unlock_irqrestore(&info->slock, flags);
+		schedule_timeout_interruptible(char_time);
+		spin_lock_irqsave(&info->slock, flags);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+	spin_unlock_irqrestore(&info->slock, flags);
+	set_current_state(TASK_RUNNING);
+
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * This routine is called by tty_hangup() when a hangup is signaled.
+ */
+static void mxser_hangup(struct tty_struct *tty)
+{
+	struct mxser_port *info = tty->driver_data;
+
+	mxser_flush_buffer(tty);
+	tty_port_hangup(&info->port);
+}
+
+/*
+ * mxser_rs_break() --- routine which turns the break handling on or off
+ */
+static int mxser_rs_break(struct tty_struct *tty, int break_state)
+{
+	struct mxser_port *info = tty->driver_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->slock, flags);
+	if (break_state == -1)
+		outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
+			info->ioaddr + UART_LCR);
+	else
+		outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
+			info->ioaddr + UART_LCR);
+	spin_unlock_irqrestore(&info->slock, flags);
+	return 0;
+}
+
+static void mxser_receive_chars(struct tty_struct *tty,
+				struct mxser_port *port, int *status)
+{
+	unsigned char ch, gdl;
+	int ignored = 0;
+	int cnt = 0;
+	int recv_room;
+	int max = 256;
+
+	recv_room = tty->receive_room;
+	if (recv_room == 0 && !port->ldisc_stop_rx)
+		mxser_stoprx(tty);
+	if (port->board->chip_flag != MOXA_OTHER_UART) {
+
+		if (*status & UART_LSR_SPECIAL)
+			goto intr_old;
+		if (port->board->chip_flag == MOXA_MUST_MU860_HWID &&
+				(*status & MOXA_MUST_LSR_RERR))
+			goto intr_old;
+		if (*status & MOXA_MUST_LSR_RERR)
+			goto intr_old;
+
+		gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
+
+		if (port->board->chip_flag == MOXA_MUST_MU150_HWID)
+			gdl &= MOXA_MUST_GDL_MASK;
+		if (gdl >= recv_room) {
+			if (!port->ldisc_stop_rx)
+				mxser_stoprx(tty);
+		}
+		while (gdl--) {
+			ch = inb(port->ioaddr + UART_RX);
+			tty_insert_flip_char(tty, ch, 0);
+			cnt++;
+		}
+		goto end_intr;
+	}
+intr_old:
+
+	do {
+		if (max-- < 0)
+			break;
+
+		ch = inb(port->ioaddr + UART_RX);
+		if (port->board->chip_flag && (*status & UART_LSR_OE))
+			outb(0x23, port->ioaddr + UART_FCR);
+		*status &= port->read_status_mask;
+		if (*status & port->ignore_status_mask) {
+			if (++ignored > 100)
+				break;
+		} else {
+			char flag = 0;
+			if (*status & UART_LSR_SPECIAL) {
+				if (*status & UART_LSR_BI) {
+					flag = TTY_BREAK;
+					port->icount.brk++;
+
+					if (port->port.flags & ASYNC_SAK)
+						do_SAK(tty);
+				} else if (*status & UART_LSR_PE) {
+					flag = TTY_PARITY;
+					port->icount.parity++;
+				} else if (*status & UART_LSR_FE) {
+					flag = TTY_FRAME;
+					port->icount.frame++;
+				} else if (*status & UART_LSR_OE) {
+					flag = TTY_OVERRUN;
+					port->icount.overrun++;
+				} else
+					flag = TTY_BREAK;
+			}
+			tty_insert_flip_char(tty, ch, flag);
+			cnt++;
+			if (cnt >= recv_room) {
+				if (!port->ldisc_stop_rx)
+					mxser_stoprx(tty);
+				break;
+			}
+
+		}
+
+		if (port->board->chip_flag)
+			break;
+
+		*status = inb(port->ioaddr + UART_LSR);
+	} while (*status & UART_LSR_DR);
+
+end_intr:
+	mxvar_log.rxcnt[tty->index] += cnt;
+	port->mon_data.rxcnt += cnt;
+	port->mon_data.up_rxcnt += cnt;
+
+	/*
+	 * We are called from an interrupt context with &port->slock
+	 * being held. Drop it temporarily in order to prevent
+	 * recursive locking.
+	 */
+	spin_unlock(&port->slock);
+	tty_flip_buffer_push(tty);
+	spin_lock(&port->slock);
+}
+
+static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
+{
+	int count, cnt;
+
+	if (port->x_char) {
+		outb(port->x_char, port->ioaddr + UART_TX);
+		port->x_char = 0;
+		mxvar_log.txcnt[tty->index]++;
+		port->mon_data.txcnt++;
+		port->mon_data.up_txcnt++;
+		port->icount.tx++;
+		return;
+	}
+
+	if (port->port.xmit_buf == NULL)
+		return;
+
+	if (port->xmit_cnt <= 0 || tty->stopped ||
+			(tty->hw_stopped &&
+			(port->type != PORT_16550A) &&
+			(!port->board->chip_flag))) {
+		port->IER &= ~UART_IER_THRI;
+		outb(port->IER, port->ioaddr + UART_IER);
+		return;
+	}
+
+	cnt = port->xmit_cnt;
+	count = port->xmit_fifo_size;
+	do {
+		outb(port->port.xmit_buf[port->xmit_tail++],
+			port->ioaddr + UART_TX);
+		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+		if (--port->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+	mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt);
+
+	port->mon_data.txcnt += (cnt - port->xmit_cnt);
+	port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
+	port->icount.tx += (cnt - port->xmit_cnt);
+
+	if (port->xmit_cnt < WAKEUP_CHARS)
+		tty_wakeup(tty);
+
+	if (port->xmit_cnt <= 0) {
+		port->IER &= ~UART_IER_THRI;
+		outb(port->IER, port->ioaddr + UART_IER);
+	}
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static irqreturn_t mxser_interrupt(int irq, void *dev_id)
+{
+	int status, iir, i;
+	struct mxser_board *brd = NULL;
+	struct mxser_port *port;
+	int max, irqbits, bits, msr;
+	unsigned int int_cnt, pass_counter = 0;
+	int handled = IRQ_NONE;
+	struct tty_struct *tty;
+
+	for (i = 0; i < MXSER_BOARDS; i++)
+		if (dev_id == &mxser_boards[i]) {
+			brd = dev_id;
+			break;
+		}
+
+	if (i == MXSER_BOARDS)
+		goto irq_stop;
+	if (brd == NULL)
+		goto irq_stop;
+	max = brd->info->nports;
+	while (pass_counter++ < MXSER_ISR_PASS_LIMIT) {
+		irqbits = inb(brd->vector) & brd->vector_mask;
+		if (irqbits == brd->vector_mask)
+			break;
+
+		handled = IRQ_HANDLED;
+		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+			if (irqbits == brd->vector_mask)
+				break;
+			if (bits & irqbits)
+				continue;
+			port = &brd->ports[i];
+
+			int_cnt = 0;
+			spin_lock(&port->slock);
+			do {
+				iir = inb(port->ioaddr + UART_IIR);
+				if (iir & UART_IIR_NO_INT)
+					break;
+				iir &= MOXA_MUST_IIR_MASK;
+				tty = tty_port_tty_get(&port->port);
+				if (!tty ||
+						(port->port.flags & ASYNC_CLOSING) ||
+						!(port->port.flags &
+							ASYNC_INITIALIZED)) {
+					status = inb(port->ioaddr + UART_LSR);
+					outb(0x27, port->ioaddr + UART_FCR);
+					inb(port->ioaddr + UART_MSR);
+					tty_kref_put(tty);
+					break;
+				}
+
+				status = inb(port->ioaddr + UART_LSR);
+
+				if (status & UART_LSR_PE)
+					port->err_shadow |= NPPI_NOTIFY_PARITY;
+				if (status & UART_LSR_FE)
+					port->err_shadow |= NPPI_NOTIFY_FRAMING;
+				if (status & UART_LSR_OE)
+					port->err_shadow |=
+						NPPI_NOTIFY_HW_OVERRUN;
+				if (status & UART_LSR_BI)
+					port->err_shadow |= NPPI_NOTIFY_BREAK;
+
+				if (port->board->chip_flag) {
+					if (iir == MOXA_MUST_IIR_GDA ||
+					    iir == MOXA_MUST_IIR_RDA ||
+					    iir == MOXA_MUST_IIR_RTO ||
+					    iir == MOXA_MUST_IIR_LSR)
+						mxser_receive_chars(tty, port,
+								&status);
+
+				} else {
+					status &= port->read_status_mask;
+					if (status & UART_LSR_DR)
+						mxser_receive_chars(tty, port,
+								&status);
+				}
+				msr = inb(port->ioaddr + UART_MSR);
+				if (msr & UART_MSR_ANY_DELTA)
+					mxser_check_modem_status(tty, port, msr);
+
+				if (port->board->chip_flag) {
+					if (iir == 0x02 && (status &
+								UART_LSR_THRE))
+						mxser_transmit_chars(tty, port);
+				} else {
+					if (status & UART_LSR_THRE)
+						mxser_transmit_chars(tty, port);
+				}
+				tty_kref_put(tty);
+			} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
+			spin_unlock(&port->slock);
+		}
+	}
+
+irq_stop:
+	return handled;
+}
+
+static const struct tty_operations mxser_ops = {
+	.open = mxser_open,
+	.close = mxser_close,
+	.write = mxser_write,
+	.put_char = mxser_put_char,
+	.flush_chars = mxser_flush_chars,
+	.write_room = mxser_write_room,
+	.chars_in_buffer = mxser_chars_in_buffer,
+	.flush_buffer = mxser_flush_buffer,
+	.ioctl = mxser_ioctl,
+	.throttle = mxser_throttle,
+	.unthrottle = mxser_unthrottle,
+	.set_termios = mxser_set_termios,
+	.stop = mxser_stop,
+	.start = mxser_start,
+	.hangup = mxser_hangup,
+	.break_ctl = mxser_rs_break,
+	.wait_until_sent = mxser_wait_until_sent,
+	.tiocmget = mxser_tiocmget,
+	.tiocmset = mxser_tiocmset,
+	.get_icount = mxser_get_icount,
+};
+
+struct tty_port_operations mxser_port_ops = {
+	.carrier_raised = mxser_carrier_raised,
+	.dtr_rts = mxser_dtr_rts,
+	.activate = mxser_activate,
+	.shutdown = mxser_shutdown_port,
+};
+
+/*
+ * The MOXA Smartio/Industio serial driver boot-time initialization code!
+ */
+
+static void mxser_release_ISA_res(struct mxser_board *brd)
+{
+	free_irq(brd->irq, brd);
+	release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+	release_region(brd->vector, 1);
+}
+
+static int __devinit mxser_initbrd(struct mxser_board *brd,
+		struct pci_dev *pdev)
+{
+	struct mxser_port *info;
+	unsigned int i;
+	int retval;
+
+	printk(KERN_INFO "mxser: max. baud rate = %d bps\n",
+			brd->ports[0].max_baud);
+
+	for (i = 0; i < brd->info->nports; i++) {
+		info = &brd->ports[i];
+		tty_port_init(&info->port);
+		info->port.ops = &mxser_port_ops;
+		info->board = brd;
+		info->stop_rx = 0;
+		info->ldisc_stop_rx = 0;
+
+		/* Enhance mode enabled here */
+		if (brd->chip_flag != MOXA_OTHER_UART)
+			mxser_enable_must_enchance_mode(info->ioaddr);
+
+		info->port.flags = ASYNC_SHARE_IRQ;
+		info->type = brd->uart_type;
+
+		process_txrx_fifo(info);
+
+		info->custom_divisor = info->baud_base * 16;
+		info->port.close_delay = 5 * HZ / 10;
+		info->port.closing_wait = 30 * HZ;
+		info->normal_termios = mxvar_sdriver->init_termios;
+		memset(&info->mon_data, 0, sizeof(struct mxser_mon));
+		info->err_shadow = 0;
+		spin_lock_init(&info->slock);
+
+		/* before set INT ISR, disable all int */
+		outb(inb(info->ioaddr + UART_IER) & 0xf0,
+			info->ioaddr + UART_IER);
+	}
+
+	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
+			brd);
+	if (retval)
+		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
+			"conflict with another device.\n",
+			brd->info->name, brd->irq);
+
+	return retval;
+}
+
+static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
+{
+	int id, i, bits;
+	unsigned short regs[16], irq;
+	unsigned char scratch, scratch2;
+
+	brd->chip_flag = MOXA_OTHER_UART;
+
+	id = mxser_read_register(cap, regs);
+	switch (id) {
+	case C168_ASIC_ID:
+		brd->info = &mxser_cards[0];
+		break;
+	case C104_ASIC_ID:
+		brd->info = &mxser_cards[1];
+		break;
+	case CI104J_ASIC_ID:
+		brd->info = &mxser_cards[2];
+		break;
+	case C102_ASIC_ID:
+		brd->info = &mxser_cards[5];
+		break;
+	case CI132_ASIC_ID:
+		brd->info = &mxser_cards[6];
+		break;
+	case CI134_ASIC_ID:
+		brd->info = &mxser_cards[7];
+		break;
+	default:
+		return 0;
+	}
+
+	irq = 0;
+	/* some ISA cards have 2 ports, but we want to see them as 4-port (why?)
+	   Flag-hack checks if configuration should be read as 2-port here. */
+	if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) {
+		irq = regs[9] & 0xF000;
+		irq = irq | (irq >> 4);
+		if (irq != (regs[9] & 0xFF00))
+			goto err_irqconflict;
+	} else if (brd->info->nports == 4) {
+		irq = regs[9] & 0xF000;
+		irq = irq | (irq >> 4);
+		irq = irq | (irq >> 8);
+		if (irq != regs[9])
+			goto err_irqconflict;
+	} else if (brd->info->nports == 8) {
+		irq = regs[9] & 0xF000;
+		irq = irq | (irq >> 4);
+		irq = irq | (irq >> 8);
+		if ((irq != regs[9]) || (irq != regs[10]))
+			goto err_irqconflict;
+	}
+
+	if (!irq) {
+		printk(KERN_ERR "mxser: interrupt number unset\n");
+		return -EIO;
+	}
+	brd->irq = ((int)(irq & 0xF000) >> 12);
+	for (i = 0; i < 8; i++)
+		brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
+	if ((regs[12] & 0x80) == 0) {
+		printk(KERN_ERR "mxser: invalid interrupt vector\n");
+		return -EIO;
+	}
+	brd->vector = (int)regs[11];	/* interrupt vector */
+	if (id == 1)
+		brd->vector_mask = 0x00FF;
+	else
+		brd->vector_mask = 0x000F;
+	for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
+		if (regs[12] & bits) {
+			brd->ports[i].baud_base = 921600;
+			brd->ports[i].max_baud = 921600;
+		} else {
+			brd->ports[i].baud_base = 115200;
+			brd->ports[i].max_baud = 115200;
+		}
+	}
+	scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
+	outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
+	outb(0, cap + UART_EFR);	/* EFR is the same as FCR */
+	outb(scratch2, cap + UART_LCR);
+	outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
+	scratch = inb(cap + UART_IIR);
+
+	if (scratch & 0xC0)
+		brd->uart_type = PORT_16550A;
+	else
+		brd->uart_type = PORT_16450;
+	if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
+			"mxser(IO)")) {
+		printk(KERN_ERR "mxser: can't request ports I/O region: "
+				"0x%.8lx-0x%.8lx\n",
+				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
+				8 * brd->info->nports - 1);
+		return -EIO;
+	}
+	if (!request_region(brd->vector, 1, "mxser(vector)")) {
+		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+		printk(KERN_ERR "mxser: can't request interrupt vector region: "
+				"0x%.8lx-0x%.8lx\n",
+				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
+				8 * brd->info->nports - 1);
+		return -EIO;
+	}
+	return brd->info->nports;
+
+err_irqconflict:
+	printk(KERN_ERR "mxser: invalid interrupt number\n");
+	return -EIO;
+}
+
+static int __devinit mxser_probe(struct pci_dev *pdev,
+		const struct pci_device_id *ent)
+{
+#ifdef CONFIG_PCI
+	struct mxser_board *brd;
+	unsigned int i, j;
+	unsigned long ioaddress;
+	int retval = -EINVAL;
+
+	for (i = 0; i < MXSER_BOARDS; i++)
+		if (mxser_boards[i].info == NULL)
+			break;
+
+	if (i >= MXSER_BOARDS) {
+		dev_err(&pdev->dev, "too many boards found (maximum %d), board "
+				"not configured\n", MXSER_BOARDS);
+		goto err;
+	}
+
+	brd = &mxser_boards[i];
+	brd->idx = i * MXSER_PORTS_PER_BOARD;
+	dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n",
+		mxser_cards[ent->driver_data].name,
+		pdev->bus->number, PCI_SLOT(pdev->devfn));
+
+	retval = pci_enable_device(pdev);
+	if (retval) {
+		dev_err(&pdev->dev, "PCI enable failed\n");
+		goto err;
+	}
+
+	/* io address */
+	ioaddress = pci_resource_start(pdev, 2);
+	retval = pci_request_region(pdev, 2, "mxser(IO)");
+	if (retval)
+		goto err_dis;
+
+	brd->info = &mxser_cards[ent->driver_data];
+	for (i = 0; i < brd->info->nports; i++)
+		brd->ports[i].ioaddr = ioaddress + 8 * i;
+
+	/* vector */
+	ioaddress = pci_resource_start(pdev, 3);
+	retval = pci_request_region(pdev, 3, "mxser(vector)");
+	if (retval)
+		goto err_zero;
+	brd->vector = ioaddress;
+
+	/* irq */
+	brd->irq = pdev->irq;
+
+	brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr);
+	brd->uart_type = PORT_16550A;
+	brd->vector_mask = 0;
+
+	for (i = 0; i < brd->info->nports; i++) {
+		for (j = 0; j < UART_INFO_NUM; j++) {
+			if (Gpci_uart_info[j].type == brd->chip_flag) {
+				brd->ports[i].max_baud =
+					Gpci_uart_info[j].max_baud;
+
+				/* exception....CP-102 */
+				if (brd->info->flags & MXSER_HIGHBAUD)
+					brd->ports[i].max_baud = 921600;
+				break;
+			}
+		}
+	}
+
+	if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
+		for (i = 0; i < brd->info->nports; i++) {
+			if (i < 4)
+				brd->ports[i].opmode_ioaddr = ioaddress + 4;
+			else
+				brd->ports[i].opmode_ioaddr = ioaddress + 0x0c;
+		}
+		outb(0, ioaddress + 4);	/* default set to RS232 mode */
+		outb(0, ioaddress + 0x0c);	/* default set to RS232 mode */
+	}
+
+	for (i = 0; i < brd->info->nports; i++) {
+		brd->vector_mask |= (1 << i);
+		brd->ports[i].baud_base = 921600;
+	}
+
+	/* mxser_initbrd will hook ISR. */
+	retval = mxser_initbrd(brd, pdev);
+	if (retval)
+		goto err_rel3;
+
+	for (i = 0; i < brd->info->nports; i++)
+		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
+
+	pci_set_drvdata(pdev, brd);
+
+	return 0;
+err_rel3:
+	pci_release_region(pdev, 3);
+err_zero:
+	brd->info = NULL;
+	pci_release_region(pdev, 2);
+err_dis:
+	pci_disable_device(pdev);
+err:
+	return retval;
+#else
+	return -ENODEV;
+#endif
+}
+
+static void __devexit mxser_remove(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PCI
+	struct mxser_board *brd = pci_get_drvdata(pdev);
+	unsigned int i;
+
+	for (i = 0; i < brd->info->nports; i++)
+		tty_unregister_device(mxvar_sdriver, brd->idx + i);
+
+	free_irq(pdev->irq, brd);
+	pci_release_region(pdev, 2);
+	pci_release_region(pdev, 3);
+	pci_disable_device(pdev);
+	brd->info = NULL;
+#endif
+}
+
+static struct pci_driver mxser_driver = {
+	.name = "mxser",
+	.id_table = mxser_pcibrds,
+	.probe = mxser_probe,
+	.remove = __devexit_p(mxser_remove)
+};
+
+static int __init mxser_module_init(void)
+{
+	struct mxser_board *brd;
+	unsigned int b, i, m;
+	int retval;
+
+	mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
+	if (!mxvar_sdriver)
+		return -ENOMEM;
+
+	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
+		MXSER_VERSION);
+
+	/* Initialize the tty_driver structure */
+	mxvar_sdriver->owner = THIS_MODULE;
+	mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
+	mxvar_sdriver->name = "ttyMI";
+	mxvar_sdriver->major = ttymajor;
+	mxvar_sdriver->minor_start = 0;
+	mxvar_sdriver->num = MXSER_PORTS + 1;
+	mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
+	mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
+	mxvar_sdriver->init_termios = tty_std_termios;
+	mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+	mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(mxvar_sdriver, &mxser_ops);
+
+	retval = tty_register_driver(mxvar_sdriver);
+	if (retval) {
+		printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family "
+				"tty driver !\n");
+		goto err_put;
+	}
+
+	/* Start finding ISA boards here */
+	for (m = 0, b = 0; b < MXSER_BOARDS; b++) {
+		if (!ioaddr[b])
+			continue;
+
+		brd = &mxser_boards[m];
+		retval = mxser_get_ISA_conf(ioaddr[b], brd);
+		if (retval <= 0) {
+			brd->info = NULL;
+			continue;
+		}
+
+		printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n",
+				brd->info->name, ioaddr[b]);
+
+		/* mxser_initbrd will hook ISR. */
+		if (mxser_initbrd(brd, NULL) < 0) {
+			brd->info = NULL;
+			continue;
+		}
+
+		brd->idx = m * MXSER_PORTS_PER_BOARD;
+		for (i = 0; i < brd->info->nports; i++)
+			tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
+
+		m++;
+	}
+
+	retval = pci_register_driver(&mxser_driver);
+	if (retval) {
+		printk(KERN_ERR "mxser: can't register pci driver\n");
+		if (!m) {
+			retval = -ENODEV;
+			goto err_unr;
+		} /* else: we have some ISA cards under control */
+	}
+
+	return 0;
+err_unr:
+	tty_unregister_driver(mxvar_sdriver);
+err_put:
+	put_tty_driver(mxvar_sdriver);
+	return retval;
+}
+
+static void __exit mxser_module_exit(void)
+{
+	unsigned int i, j;
+
+	pci_unregister_driver(&mxser_driver);
+
+	for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
+		if (mxser_boards[i].info != NULL)
+			for (j = 0; j < mxser_boards[i].info->nports; j++)
+				tty_unregister_device(mxvar_sdriver,
+						mxser_boards[i].idx + j);
+	tty_unregister_driver(mxvar_sdriver);
+	put_tty_driver(mxvar_sdriver);
+
+	for (i = 0; i < MXSER_BOARDS; i++)
+		if (mxser_boards[i].info != NULL)
+			mxser_release_ISA_res(&mxser_boards[i]);
+}
+
+module_init(mxser_module_init);
+module_exit(mxser_module_exit);
diff --git a/drivers/tty/mxser.h b/drivers/tty/mxser.h
new file mode 100644
index 0000000..41878a6
--- /dev/null
+++ b/drivers/tty/mxser.h
@@ -0,0 +1,150 @@
+#ifndef _MXSER_H
+#define _MXSER_H
+
+/*
+ *	Semi-public control interfaces
+ */
+
+/*
+ *	MOXA ioctls
+ */
+
+#define MOXA			0x400
+#define MOXA_GETDATACOUNT	(MOXA + 23)
+#define MOXA_DIAGNOSE		(MOXA + 50)
+#define MOXA_CHKPORTENABLE	(MOXA + 60)
+#define MOXA_HighSpeedOn	(MOXA + 61)
+#define MOXA_GET_MAJOR		(MOXA + 63)
+#define MOXA_GETMSTATUS		(MOXA + 65)
+#define MOXA_SET_OP_MODE	(MOXA + 66)
+#define MOXA_GET_OP_MODE	(MOXA + 67)
+
+#define RS232_MODE		0
+#define RS485_2WIRE_MODE	1
+#define RS422_MODE		2
+#define RS485_4WIRE_MODE	3
+#define OP_MODE_MASK		3
+
+#define MOXA_SDS_RSTICOUNTER	(MOXA + 69)
+#define MOXA_ASPP_OQUEUE  	(MOXA + 70)
+#define MOXA_ASPP_MON     	(MOXA + 73)
+#define MOXA_ASPP_LSTATUS 	(MOXA + 74)
+#define MOXA_ASPP_MON_EXT 	(MOXA + 75)
+#define MOXA_SET_BAUD_METHOD	(MOXA + 76)
+
+/* --------------------------------------------------- */
+
+#define NPPI_NOTIFY_PARITY	0x01
+#define NPPI_NOTIFY_FRAMING	0x02
+#define NPPI_NOTIFY_HW_OVERRUN	0x04
+#define NPPI_NOTIFY_SW_OVERRUN	0x08
+#define NPPI_NOTIFY_BREAK	0x10
+
+#define NPPI_NOTIFY_CTSHOLD         0x01	/* Tx hold by CTS low */
+#define NPPI_NOTIFY_DSRHOLD         0x02	/* Tx hold by DSR low */
+#define NPPI_NOTIFY_XOFFHOLD        0x08	/* Tx hold by Xoff received */
+#define NPPI_NOTIFY_XOFFXENT        0x10	/* Xoff Sent */
+
+/* follow just for Moxa Must chip define. */
+/* */
+/* when LCR register (offset 0x03) write following value, */
+/* the Must chip will enter enchance mode. And write value */
+/* on EFR (offset 0x02) bit 6,7 to change bank. */
+#define MOXA_MUST_ENTER_ENCHANCE	0xBF
+
+/* when enhance mode enable, access on general bank register */
+#define MOXA_MUST_GDL_REGISTER		0x07
+#define MOXA_MUST_GDL_MASK		0x7F
+#define MOXA_MUST_GDL_HAS_BAD_DATA	0x80
+
+#define MOXA_MUST_LSR_RERR		0x80	/* error in receive FIFO */
+/* enchance register bank select and enchance mode setting register */
+/* when LCR register equal to 0xBF */
+#define MOXA_MUST_EFR_REGISTER		0x02
+/* enchance mode enable */
+#define MOXA_MUST_EFR_EFRB_ENABLE	0x10
+/* enchance reister bank set 0, 1, 2 */
+#define MOXA_MUST_EFR_BANK0		0x00
+#define MOXA_MUST_EFR_BANK1		0x40
+#define MOXA_MUST_EFR_BANK2		0x80
+#define MOXA_MUST_EFR_BANK3		0xC0
+#define MOXA_MUST_EFR_BANK_MASK		0xC0
+
+/* set XON1 value register, when LCR=0xBF and change to bank0 */
+#define MOXA_MUST_XON1_REGISTER		0x04
+
+/* set XON2 value register, when LCR=0xBF and change to bank0 */
+#define MOXA_MUST_XON2_REGISTER		0x05
+
+/* set XOFF1 value register, when LCR=0xBF and change to bank0 */
+#define MOXA_MUST_XOFF1_REGISTER	0x06
+
+/* set XOFF2 value register, when LCR=0xBF and change to bank0 */
+#define MOXA_MUST_XOFF2_REGISTER	0x07
+
+#define MOXA_MUST_RBRTL_REGISTER	0x04
+#define MOXA_MUST_RBRTH_REGISTER	0x05
+#define MOXA_MUST_RBRTI_REGISTER	0x06
+#define MOXA_MUST_THRTL_REGISTER	0x07
+#define MOXA_MUST_ENUM_REGISTER		0x04
+#define MOXA_MUST_HWID_REGISTER		0x05
+#define MOXA_MUST_ECR_REGISTER		0x06
+#define MOXA_MUST_CSR_REGISTER		0x07
+
+/* good data mode enable */
+#define MOXA_MUST_FCR_GDA_MODE_ENABLE	0x20
+/* only good data put into RxFIFO */
+#define MOXA_MUST_FCR_GDA_ONLY_ENABLE	0x10
+
+/* enable CTS interrupt */
+#define MOXA_MUST_IER_ECTSI		0x80
+/* enable RTS interrupt */
+#define MOXA_MUST_IER_ERTSI		0x40
+/* enable Xon/Xoff interrupt */
+#define MOXA_MUST_IER_XINT		0x20
+/* enable GDA interrupt */
+#define MOXA_MUST_IER_EGDAI		0x10
+
+#define MOXA_MUST_RECV_ISR		(UART_IER_RDI | MOXA_MUST_IER_EGDAI)
+
+/* GDA interrupt pending */
+#define MOXA_MUST_IIR_GDA		0x1C
+#define MOXA_MUST_IIR_RDA		0x04
+#define MOXA_MUST_IIR_RTO		0x0C
+#define MOXA_MUST_IIR_LSR		0x06
+
+/* recieved Xon/Xoff or specical interrupt pending */
+#define MOXA_MUST_IIR_XSC		0x10
+
+/* RTS/CTS change state interrupt pending */
+#define MOXA_MUST_IIR_RTSCTS		0x20
+#define MOXA_MUST_IIR_MASK		0x3E
+
+#define MOXA_MUST_MCR_XON_FLAG		0x40
+#define MOXA_MUST_MCR_XON_ANY		0x80
+#define MOXA_MUST_MCR_TX_XON		0x08
+
+/* software flow control on chip mask value */
+#define MOXA_MUST_EFR_SF_MASK		0x0F
+/* send Xon1/Xoff1 */
+#define MOXA_MUST_EFR_SF_TX1		0x08
+/* send Xon2/Xoff2 */
+#define MOXA_MUST_EFR_SF_TX2		0x04
+/* send Xon1,Xon2/Xoff1,Xoff2 */
+#define MOXA_MUST_EFR_SF_TX12		0x0C
+/* don't send Xon/Xoff */
+#define MOXA_MUST_EFR_SF_TX_NO		0x00
+/* Tx software flow control mask */
+#define MOXA_MUST_EFR_SF_TX_MASK	0x0C
+/* don't receive Xon/Xoff */
+#define MOXA_MUST_EFR_SF_RX_NO		0x00
+/* receive Xon1/Xoff1 */
+#define MOXA_MUST_EFR_SF_RX1		0x02
+/* receive Xon2/Xoff2 */
+#define MOXA_MUST_EFR_SF_RX2		0x01
+/* receive Xon1,Xon2/Xoff1,Xoff2 */
+#define MOXA_MUST_EFR_SF_RX12		0x03
+/* Rx software flow control mask */
+#define MOXA_MUST_EFR_SF_RX_MASK	0x03
+
+#endif
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index aa2e5d3..176f632 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -1250,8 +1250,7 @@ static void gsm_control_response(struct gsm_mux *gsm, unsigned int command,
 
 static void gsm_control_transmit(struct gsm_mux *gsm, struct gsm_control *ctrl)
 {
-	struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1,
-							gsm->ftype|PF);
+	struct gsm_msg *msg = gsm_data_alloc(gsm, 0, ctrl->len + 1, gsm->ftype);
 	if (msg == NULL)
 		return;
 	msg->data[0] = (ctrl->cmd << 1) | 2 | EA;	/* command */
@@ -2649,13 +2648,13 @@ static void gsmtty_wait_until_sent(struct tty_struct *tty, int timeout)
 	   to do here */
 }
 
-static int gsmtty_tiocmget(struct tty_struct *tty, struct file *filp)
+static int gsmtty_tiocmget(struct tty_struct *tty)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
 	return dlci->modem_rx;
 }
 
-static int gsmtty_tiocmset(struct tty_struct *tty, struct file *filp,
+static int gsmtty_tiocmset(struct tty_struct *tty,
 	unsigned int set, unsigned int clear)
 {
 	struct gsm_dlci *dlci = tty->driver_data;
@@ -2672,7 +2671,7 @@ static int gsmtty_tiocmset(struct tty_struct *tty, struct file *filp,
 }
 
 
-static int gsmtty_ioctl(struct tty_struct *tty, struct file *filp,
+static int gsmtty_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	return -ENOIOCTLCMD;
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index 52fc0c9..cea5603 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -97,7 +97,6 @@
 #include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
 #include <linux/string.h>	/* used in new tty drivers */
 #include <linux/signal.h>	/* used in new tty drivers */
 #include <linux/if.h>
diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c
index 88dda0c..5c6c314 100644
--- a/drivers/tty/n_r3964.c
+++ b/drivers/tty/n_r3964.c
@@ -57,7 +57,6 @@
 #include <linux/ioport.h>
 #include <linux/in.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>	/* used in new tty drivers */
diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c
new file mode 100644
index 0000000..f4f1116
--- /dev/null
+++ b/drivers/tty/nozomi.c
@@ -0,0 +1,1991 @@
+/*
+ * nozomi.c  -- HSDPA driver Broadband Wireless Data Card - Globe Trotter
+ *
+ * Written by: Ulf Jakobsson,
+ *             Jan Ăkerfeldt,
+ *             Stefan Thomasson,
+ *
+ * Maintained by: Paul Hardwick (p.hardwick@option.com)
+ *
+ * Patches:
+ *          Locking code changes for Vodafone by Sphere Systems Ltd,
+ *                              Andrew Bird (ajb@spheresystems.co.uk )
+ *                              & Phil Sanderson
+ *
+ * Source has been ported from an implementation made by Filip Aben @ Option
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Copyright (c) 2005,2006 Option Wireless Sweden AB
+ * Copyright (c) 2006 Sphere Systems Ltd
+ * Copyright (c) 2006 Option Wireless n/v
+ * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * --------------------------------------------------------------------------
+ */
+
+/* Enable this to have a lot of debug printouts */
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/interrupt.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <asm/byteorder.h>
+
+#include <linux/delay.h>
+
+
+#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \
+					__DATE__ " " __TIME__ ")"
+
+/*    Macros definitions */
+
+/* Default debug printout level */
+#define NOZOMI_DEBUG_LEVEL 0x00
+
+#define P_BUF_SIZE 128
+#define NFO(_err_flag_, args...)				\
+do {								\
+	char tmp[P_BUF_SIZE];					\
+	snprintf(tmp, sizeof(tmp), ##args);			\
+	printk(_err_flag_ "[%d] %s(): %s\n", __LINE__,		\
+		__func__, tmp);				\
+} while (0)
+
+#define DBG1(args...) D_(0x01, ##args)
+#define DBG2(args...) D_(0x02, ##args)
+#define DBG3(args...) D_(0x04, ##args)
+#define DBG4(args...) D_(0x08, ##args)
+#define DBG5(args...) D_(0x10, ##args)
+#define DBG6(args...) D_(0x20, ##args)
+#define DBG7(args...) D_(0x40, ##args)
+#define DBG8(args...) D_(0x80, ##args)
+
+#ifdef DEBUG
+/* Do we need this settable at runtime? */
+static int debug = NOZOMI_DEBUG_LEVEL;
+
+#define D(lvl, args...)  do \
+			{if (lvl & debug) NFO(KERN_DEBUG, ##args); } \
+			while (0)
+#define D_(lvl, args...) D(lvl, ##args)
+
+/* These printouts are always printed */
+
+#else
+static int debug;
+#define D_(lvl, args...)
+#endif
+
+/* TODO: rewrite to optimize macros... */
+
+#define TMP_BUF_MAX 256
+
+#define DUMP(buf__,len__) \
+  do {  \
+    char tbuf[TMP_BUF_MAX] = {0};\
+    if (len__ > 1) {\
+	snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\
+	if (tbuf[len__-2] == '\r') {\
+		tbuf[len__-2] = 'r';\
+	} \
+	DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\
+    } else {\
+	DBG1("SENDING: '%s' (%d)", tbuf, len__);\
+    } \
+} while (0)
+
+/*    Defines */
+#define NOZOMI_NAME		"nozomi"
+#define NOZOMI_NAME_TTY		"nozomi_tty"
+#define DRIVER_DESC		"Nozomi driver"
+
+#define NTTY_TTY_MAXMINORS	256
+#define NTTY_FIFO_BUFFER_SIZE	8192
+
+/* Must be power of 2 */
+#define FIFO_BUFFER_SIZE_UL	8192
+
+/* Size of tmp send buffer to card */
+#define SEND_BUF_MAX		1024
+#define RECEIVE_BUF_MAX		4
+
+
+#define R_IIR		0x0000	/* Interrupt Identity Register */
+#define R_FCR		0x0000	/* Flow Control Register */
+#define R_IER		0x0004	/* Interrupt Enable Register */
+
+#define CONFIG_MAGIC	0xEFEFFEFE
+#define TOGGLE_VALID	0x0000
+
+/* Definition of interrupt tokens */
+#define MDM_DL1		0x0001
+#define MDM_UL1		0x0002
+#define MDM_DL2		0x0004
+#define MDM_UL2		0x0008
+#define DIAG_DL1	0x0010
+#define DIAG_DL2	0x0020
+#define DIAG_UL		0x0040
+#define APP1_DL		0x0080
+#define APP1_UL		0x0100
+#define APP2_DL		0x0200
+#define APP2_UL		0x0400
+#define CTRL_DL		0x0800
+#define CTRL_UL		0x1000
+#define RESET		0x8000
+
+#define MDM_DL		(MDM_DL1  | MDM_DL2)
+#define MDM_UL		(MDM_UL1  | MDM_UL2)
+#define DIAG_DL		(DIAG_DL1 | DIAG_DL2)
+
+/* modem signal definition */
+#define CTRL_DSR	0x0001
+#define CTRL_DCD	0x0002
+#define CTRL_RI		0x0004
+#define CTRL_CTS	0x0008
+
+#define CTRL_DTR	0x0001
+#define CTRL_RTS	0x0002
+
+#define MAX_PORT		4
+#define NOZOMI_MAX_PORTS	5
+#define NOZOMI_MAX_CARDS	(NTTY_TTY_MAXMINORS / MAX_PORT)
+
+/*    Type definitions */
+
+/*
+ * There are two types of nozomi cards,
+ * one with 2048 memory and with 8192 memory
+ */
+enum card_type {
+	F32_2 = 2048,	/* 512 bytes downlink + uplink * 2 -> 2048 */
+	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
+};
+
+/* Initialization states a card can be in */
+enum card_state {
+	NOZOMI_STATE_UKNOWN	= 0,
+	NOZOMI_STATE_ENABLED	= 1,	/* pci device enabled */
+	NOZOMI_STATE_ALLOCATED	= 2,	/* config setup done */
+	NOZOMI_STATE_READY	= 3,	/* flowcontrols received */
+};
+
+/* Two different toggle channels exist */
+enum channel_type {
+	CH_A = 0,
+	CH_B = 1,
+};
+
+/* Port definition for the card regarding flow control */
+enum ctrl_port_type {
+	CTRL_CMD	= 0,
+	CTRL_MDM	= 1,
+	CTRL_DIAG	= 2,
+	CTRL_APP1	= 3,
+	CTRL_APP2	= 4,
+	CTRL_ERROR	= -1,
+};
+
+/* Ports that the nozomi has */
+enum port_type {
+	PORT_MDM	= 0,
+	PORT_DIAG	= 1,
+	PORT_APP1	= 2,
+	PORT_APP2	= 3,
+	PORT_CTRL	= 4,
+	PORT_ERROR	= -1,
+};
+
+#ifdef __BIG_ENDIAN
+/* Big endian */
+
+struct toggles {
+	unsigned int enabled:5;	/*
+				 * Toggle fields are valid if enabled is 0,
+				 * else A-channels must always be used.
+				 */
+	unsigned int diag_dl:1;
+	unsigned int mdm_dl:1;
+	unsigned int mdm_ul:1;
+} __attribute__ ((packed));
+
+/* Configuration table to read at startup of card */
+/* Is for now only needed during initialization phase */
+struct config_table {
+	u32 signature;
+	u16 product_information;
+	u16 version;
+	u8 pad3[3];
+	struct toggles toggle;
+	u8 pad1[4];
+	u16 dl_mdm_len1;	/*
+				 * If this is 64, it can hold
+				 * 60 bytes + 4 that is length field
+				 */
+	u16 dl_start;
+
+	u16 dl_diag_len1;
+	u16 dl_mdm_len2;	/*
+				 * If this is 64, it can hold
+				 * 60 bytes + 4 that is length field
+				 */
+	u16 dl_app1_len;
+
+	u16 dl_diag_len2;
+	u16 dl_ctrl_len;
+	u16 dl_app2_len;
+	u8 pad2[16];
+	u16 ul_mdm_len1;
+	u16 ul_start;
+	u16 ul_diag_len;
+	u16 ul_mdm_len2;
+	u16 ul_app1_len;
+	u16 ul_app2_len;
+	u16 ul_ctrl_len;
+} __attribute__ ((packed));
+
+/* This stores all control downlink flags */
+struct ctrl_dl {
+	u8 port;
+	unsigned int reserved:4;
+	unsigned int CTS:1;
+	unsigned int RI:1;
+	unsigned int DCD:1;
+	unsigned int DSR:1;
+} __attribute__ ((packed));
+
+/* This stores all control uplink flags */
+struct ctrl_ul {
+	u8 port;
+	unsigned int reserved:6;
+	unsigned int RTS:1;
+	unsigned int DTR:1;
+} __attribute__ ((packed));
+
+#else
+/* Little endian */
+
+/* This represents the toggle information */
+struct toggles {
+	unsigned int mdm_ul:1;
+	unsigned int mdm_dl:1;
+	unsigned int diag_dl:1;
+	unsigned int enabled:5;	/*
+				 * Toggle fields are valid if enabled is 0,
+				 * else A-channels must always be used.
+				 */
+} __attribute__ ((packed));
+
+/* Configuration table to read at startup of card */
+struct config_table {
+	u32 signature;
+	u16 version;
+	u16 product_information;
+	struct toggles toggle;
+	u8 pad1[7];
+	u16 dl_start;
+	u16 dl_mdm_len1;	/*
+				 * If this is 64, it can hold
+				 * 60 bytes + 4 that is length field
+				 */
+	u16 dl_mdm_len2;
+	u16 dl_diag_len1;
+	u16 dl_diag_len2;
+	u16 dl_app1_len;
+	u16 dl_app2_len;
+	u16 dl_ctrl_len;
+	u8 pad2[16];
+	u16 ul_start;
+	u16 ul_mdm_len2;
+	u16 ul_mdm_len1;
+	u16 ul_diag_len;
+	u16 ul_app1_len;
+	u16 ul_app2_len;
+	u16 ul_ctrl_len;
+} __attribute__ ((packed));
+
+/* This stores all control downlink flags */
+struct ctrl_dl {
+	unsigned int DSR:1;
+	unsigned int DCD:1;
+	unsigned int RI:1;
+	unsigned int CTS:1;
+	unsigned int reserverd:4;
+	u8 port;
+} __attribute__ ((packed));
+
+/* This stores all control uplink flags */
+struct ctrl_ul {
+	unsigned int DTR:1;
+	unsigned int RTS:1;
+	unsigned int reserved:6;
+	u8 port;
+} __attribute__ ((packed));
+#endif
+
+/* This holds all information that is needed regarding a port */
+struct port {
+	struct tty_port port;
+	u8 update_flow_control;
+	struct ctrl_ul ctrl_ul;
+	struct ctrl_dl ctrl_dl;
+	struct kfifo fifo_ul;
+	void __iomem *dl_addr[2];
+	u32 dl_size[2];
+	u8 toggle_dl;
+	void __iomem *ul_addr[2];
+	u32 ul_size[2];
+	u8 toggle_ul;
+	u16 token_dl;
+
+	/* mutex to ensure one access patch to this port */
+	struct mutex tty_sem;
+	wait_queue_head_t tty_wait;
+	struct async_icount tty_icount;
+
+	struct nozomi *dc;
+};
+
+/* Private data one for each card in the system */
+struct nozomi {
+	void __iomem *base_addr;
+	unsigned long flip;
+
+	/* Pointers to registers */
+	void __iomem *reg_iir;
+	void __iomem *reg_fcr;
+	void __iomem *reg_ier;
+
+	u16 last_ier;
+	enum card_type card_type;
+	struct config_table config_table;	/* Configuration table */
+	struct pci_dev *pdev;
+	struct port port[NOZOMI_MAX_PORTS];
+	u8 *send_buf;
+
+	spinlock_t spin_mutex;	/* secures access to registers and tty */
+
+	unsigned int index_start;
+	enum card_state state;
+	u32 open_ttys;
+};
+
+/* This is a data packet that is read or written to/from card */
+struct buffer {
+	u32 size;		/* size is the length of the data buffer */
+	u8 *data;
+} __attribute__ ((packed));
+
+/*    Global variables */
+static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
+	{PCI_DEVICE(0x1931, 0x000c)},	/* Nozomi HSDPA */
+	{},
+};
+
+MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
+
+static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
+static struct tty_driver *ntty_driver;
+
+static const struct tty_port_operations noz_tty_port_ops;
+
+/*
+ * find card by tty_index
+ */
+static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
+{
+	return tty ? ndevs[tty->index / MAX_PORT] : NULL;
+}
+
+static inline struct port *get_port_by_tty(const struct tty_struct *tty)
+{
+	struct nozomi *ndev = get_dc_by_tty(tty);
+	return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL;
+}
+
+/*
+ * TODO:
+ * -Optimize
+ * -Rewrite cleaner
+ */
+
+static void read_mem32(u32 *buf, const void __iomem *mem_addr_start,
+			u32 size_bytes)
+{
+	u32 i = 0;
+	const u32 __iomem *ptr = mem_addr_start;
+	u16 *buf16;
+
+	if (unlikely(!ptr || !buf))
+		goto out;
+
+	/* shortcut for extremely often used cases */
+	switch (size_bytes) {
+	case 2:	/* 2 bytes */
+		buf16 = (u16 *) buf;
+		*buf16 = __le16_to_cpu(readw(ptr));
+		goto out;
+		break;
+	case 4:	/* 4 bytes */
+		*(buf) = __le32_to_cpu(readl(ptr));
+		goto out;
+		break;
+	}
+
+	while (i < size_bytes) {
+		if (size_bytes - i == 2) {
+			/* Handle 2 bytes in the end */
+			buf16 = (u16 *) buf;
+			*(buf16) = __le16_to_cpu(readw(ptr));
+			i += 2;
+		} else {
+			/* Read 4 bytes */
+			*(buf) = __le32_to_cpu(readl(ptr));
+			i += 4;
+		}
+		buf++;
+		ptr++;
+	}
+out:
+	return;
+}
+
+/*
+ * TODO:
+ * -Optimize
+ * -Rewrite cleaner
+ */
+static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf,
+			u32 size_bytes)
+{
+	u32 i = 0;
+	u32 __iomem *ptr = mem_addr_start;
+	const u16 *buf16;
+
+	if (unlikely(!ptr || !buf))
+		return 0;
+
+	/* shortcut for extremely often used cases */
+	switch (size_bytes) {
+	case 2:	/* 2 bytes */
+		buf16 = (const u16 *)buf;
+		writew(__cpu_to_le16(*buf16), ptr);
+		return 2;
+		break;
+	case 1: /*
+		 * also needs to write 4 bytes in this case
+		 * so falling through..
+		 */
+	case 4: /* 4 bytes */
+		writel(__cpu_to_le32(*buf), ptr);
+		return 4;
+		break;
+	}
+
+	while (i < size_bytes) {
+		if (size_bytes - i == 2) {
+			/* 2 bytes */
+			buf16 = (const u16 *)buf;
+			writew(__cpu_to_le16(*buf16), ptr);
+			i += 2;
+		} else {
+			/* 4 bytes */
+			writel(__cpu_to_le32(*buf), ptr);
+			i += 4;
+		}
+		buf++;
+		ptr++;
+	}
+	return i;
+}
+
+/* Setup pointers to different channels and also setup buffer sizes. */
+static void setup_memory(struct nozomi *dc)
+{
+	void __iomem *offset = dc->base_addr + dc->config_table.dl_start;
+	/* The length reported is including the length field of 4 bytes,
+	 * hence subtract with 4.
+	 */
+	const u16 buff_offset = 4;
+
+	/* Modem port dl configuration */
+	dc->port[PORT_MDM].dl_addr[CH_A] = offset;
+	dc->port[PORT_MDM].dl_addr[CH_B] =
+				(offset += dc->config_table.dl_mdm_len1);
+	dc->port[PORT_MDM].dl_size[CH_A] =
+				dc->config_table.dl_mdm_len1 - buff_offset;
+	dc->port[PORT_MDM].dl_size[CH_B] =
+				dc->config_table.dl_mdm_len2 - buff_offset;
+
+	/* Diag port dl configuration */
+	dc->port[PORT_DIAG].dl_addr[CH_A] =
+				(offset += dc->config_table.dl_mdm_len2);
+	dc->port[PORT_DIAG].dl_size[CH_A] =
+				dc->config_table.dl_diag_len1 - buff_offset;
+	dc->port[PORT_DIAG].dl_addr[CH_B] =
+				(offset += dc->config_table.dl_diag_len1);
+	dc->port[PORT_DIAG].dl_size[CH_B] =
+				dc->config_table.dl_diag_len2 - buff_offset;
+
+	/* App1 port dl configuration */
+	dc->port[PORT_APP1].dl_addr[CH_A] =
+				(offset += dc->config_table.dl_diag_len2);
+	dc->port[PORT_APP1].dl_size[CH_A] =
+				dc->config_table.dl_app1_len - buff_offset;
+
+	/* App2 port dl configuration */
+	dc->port[PORT_APP2].dl_addr[CH_A] =
+				(offset += dc->config_table.dl_app1_len);
+	dc->port[PORT_APP2].dl_size[CH_A] =
+				dc->config_table.dl_app2_len - buff_offset;
+
+	/* Ctrl dl configuration */
+	dc->port[PORT_CTRL].dl_addr[CH_A] =
+				(offset += dc->config_table.dl_app2_len);
+	dc->port[PORT_CTRL].dl_size[CH_A] =
+				dc->config_table.dl_ctrl_len - buff_offset;
+
+	offset = dc->base_addr + dc->config_table.ul_start;
+
+	/* Modem Port ul configuration */
+	dc->port[PORT_MDM].ul_addr[CH_A] = offset;
+	dc->port[PORT_MDM].ul_size[CH_A] =
+				dc->config_table.ul_mdm_len1 - buff_offset;
+	dc->port[PORT_MDM].ul_addr[CH_B] =
+				(offset += dc->config_table.ul_mdm_len1);
+	dc->port[PORT_MDM].ul_size[CH_B] =
+				dc->config_table.ul_mdm_len2 - buff_offset;
+
+	/* Diag port ul configuration */
+	dc->port[PORT_DIAG].ul_addr[CH_A] =
+				(offset += dc->config_table.ul_mdm_len2);
+	dc->port[PORT_DIAG].ul_size[CH_A] =
+				dc->config_table.ul_diag_len - buff_offset;
+
+	/* App1 port ul configuration */
+	dc->port[PORT_APP1].ul_addr[CH_A] =
+				(offset += dc->config_table.ul_diag_len);
+	dc->port[PORT_APP1].ul_size[CH_A] =
+				dc->config_table.ul_app1_len - buff_offset;
+
+	/* App2 port ul configuration */
+	dc->port[PORT_APP2].ul_addr[CH_A] =
+				(offset += dc->config_table.ul_app1_len);
+	dc->port[PORT_APP2].ul_size[CH_A] =
+				dc->config_table.ul_app2_len - buff_offset;
+
+	/* Ctrl ul configuration */
+	dc->port[PORT_CTRL].ul_addr[CH_A] =
+				(offset += dc->config_table.ul_app2_len);
+	dc->port[PORT_CTRL].ul_size[CH_A] =
+				dc->config_table.ul_ctrl_len - buff_offset;
+}
+
+/* Dump config table under initalization phase */
+#ifdef DEBUG
+static void dump_table(const struct nozomi *dc)
+{
+	DBG3("signature: 0x%08X", dc->config_table.signature);
+	DBG3("version: 0x%04X", dc->config_table.version);
+	DBG3("product_information: 0x%04X", \
+				dc->config_table.product_information);
+	DBG3("toggle enabled: %d", dc->config_table.toggle.enabled);
+	DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul);
+	DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl);
+	DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl);
+
+	DBG3("dl_start: 0x%04X", dc->config_table.dl_start);
+	DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1,
+	   dc->config_table.dl_mdm_len1);
+	DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2,
+	   dc->config_table.dl_mdm_len2);
+	DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1,
+	   dc->config_table.dl_diag_len1);
+	DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2,
+	   dc->config_table.dl_diag_len2);
+	DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len,
+	   dc->config_table.dl_app1_len);
+	DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len,
+	   dc->config_table.dl_app2_len);
+	DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len,
+	   dc->config_table.dl_ctrl_len);
+	DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start,
+	   dc->config_table.ul_start);
+	DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1,
+	   dc->config_table.ul_mdm_len1);
+	DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2,
+	   dc->config_table.ul_mdm_len2);
+	DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len,
+	   dc->config_table.ul_diag_len);
+	DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len,
+	   dc->config_table.ul_app1_len);
+	DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len,
+	   dc->config_table.ul_app2_len);
+	DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len,
+	   dc->config_table.ul_ctrl_len);
+}
+#else
+static inline void dump_table(const struct nozomi *dc) { }
+#endif
+
+/*
+ * Read configuration table from card under intalization phase
+ * Returns 1 if ok, else 0
+ */
+static int nozomi_read_config_table(struct nozomi *dc)
+{
+	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
+						sizeof(struct config_table));
+
+	if (dc->config_table.signature != CONFIG_MAGIC) {
+		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
+			dc->config_table.signature, CONFIG_MAGIC);
+		return 0;
+	}
+
+	if ((dc->config_table.version == 0)
+	    || (dc->config_table.toggle.enabled == TOGGLE_VALID)) {
+		int i;
+		DBG1("Second phase, configuring card");
+
+		setup_memory(dc);
+
+		dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
+		dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
+		dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl;
+		DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d",
+		   dc->port[PORT_MDM].toggle_ul,
+		   dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl);
+
+		dump_table(dc);
+
+		for (i = PORT_MDM; i < MAX_PORT; i++) {
+			memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
+			memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
+		}
+
+		/* Enable control channel */
+		dc->last_ier = dc->last_ier | CTRL_DL;
+		writew(dc->last_ier, dc->reg_ier);
+
+		dc->state = NOZOMI_STATE_ALLOCATED;
+		dev_info(&dc->pdev->dev, "Initialization OK!\n");
+		return 1;
+	}
+
+	if ((dc->config_table.version > 0)
+	    && (dc->config_table.toggle.enabled != TOGGLE_VALID)) {
+		u32 offset = 0;
+		DBG1("First phase: pushing upload buffers, clearing download");
+
+		dev_info(&dc->pdev->dev, "Version of card: %d\n",
+			 dc->config_table.version);
+
+		/* Here we should disable all I/O over F32. */
+		setup_memory(dc);
+
+		/*
+		 * We should send ALL channel pair tokens back along
+		 * with reset token
+		 */
+
+		/* push upload modem buffers */
+		write_mem32(dc->port[PORT_MDM].ul_addr[CH_A],
+			(u32 *) &offset, 4);
+		write_mem32(dc->port[PORT_MDM].ul_addr[CH_B],
+			(u32 *) &offset, 4);
+
+		writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr);
+
+		DBG1("First phase done");
+	}
+
+	return 1;
+}
+
+/* Enable uplink interrupts  */
+static void enable_transmit_ul(enum port_type port, struct nozomi *dc)
+{
+	static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL};
+
+	if (port < NOZOMI_MAX_PORTS) {
+		dc->last_ier |= mask[port];
+		writew(dc->last_ier, dc->reg_ier);
+	} else {
+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
+	}
+}
+
+/* Disable uplink interrupts  */
+static void disable_transmit_ul(enum port_type port, struct nozomi *dc)
+{
+	static const u16 mask[] =
+		{~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL};
+
+	if (port < NOZOMI_MAX_PORTS) {
+		dc->last_ier &= mask[port];
+		writew(dc->last_ier, dc->reg_ier);
+	} else {
+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
+	}
+}
+
+/* Enable downlink interrupts */
+static void enable_transmit_dl(enum port_type port, struct nozomi *dc)
+{
+	static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL};
+
+	if (port < NOZOMI_MAX_PORTS) {
+		dc->last_ier |= mask[port];
+		writew(dc->last_ier, dc->reg_ier);
+	} else {
+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
+	}
+}
+
+/* Disable downlink interrupts */
+static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
+{
+	static const u16 mask[] =
+		{~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL};
+
+	if (port < NOZOMI_MAX_PORTS) {
+		dc->last_ier &= mask[port];
+		writew(dc->last_ier, dc->reg_ier);
+	} else {
+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
+	}
+}
+
+/*
+ * Return 1 - send buffer to card and ack.
+ * Return 0 - don't ack, don't send buffer to card.
+ */
+static int send_data(enum port_type index, struct nozomi *dc)
+{
+	u32 size = 0;
+	struct port *port = &dc->port[index];
+	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,
+			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
+
+	if (size == 0) {
+		DBG4("No more data to send, disable link:");
+		tty_kref_put(tty);
+		return 0;
+	}
+
+	/* DUMP(buf, size); */
+
+	/* Write length + data */
+	write_mem32(addr, (u32 *) &size, 4);
+	write_mem32(addr + 4, (u32 *) dc->send_buf, size);
+
+	if (tty)
+		tty_wakeup(tty);
+
+	tty_kref_put(tty);
+	return 1;
+}
+
+/* If all data has been read, return 1, else 0 */
+static int receive_data(enum port_type index, struct nozomi *dc)
+{
+	u8 buf[RECEIVE_BUF_MAX] = { 0 };
+	int size;
+	u32 offset = 4;
+	struct port *port = &dc->port[index];
+	void __iomem *addr = port->dl_addr[port->toggle_dl];
+	struct tty_struct *tty = tty_port_tty_get(&port->port);
+	int i, ret;
+
+	if (unlikely(!tty)) {
+		DBG1("tty not open for port: %d?", index);
+		return 1;
+	}
+
+	read_mem32((u32 *) &size, addr, 4);
+	/*  DBG1( "%d bytes port: %d", size, index); */
+
+	if (test_bit(TTY_THROTTLED, &tty->flags)) {
+		DBG1("No room in tty, don't read data, don't ack interrupt, "
+			"disable interrupt");
+
+		/* disable interrupt in downlink... */
+		disable_transmit_dl(index, dc);
+		ret = 0;
+		goto put;
+	}
+
+	if (unlikely(size == 0)) {
+		dev_err(&dc->pdev->dev, "size == 0?\n");
+		ret = 1;
+		goto put;
+	}
+
+	while (size > 0) {
+		read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
+
+		if (size == 1) {
+			tty_insert_flip_char(tty, buf[0], TTY_NORMAL);
+			size = 0;
+		} else if (size < RECEIVE_BUF_MAX) {
+			size -= tty_insert_flip_string(tty, (char *) buf, size);
+		} else {
+			i = tty_insert_flip_string(tty, \
+						(char *) buf, RECEIVE_BUF_MAX);
+			size -= i;
+			offset += i;
+		}
+	}
+
+	set_bit(index, &dc->flip);
+	ret = 1;
+put:
+	tty_kref_put(tty);
+	return ret;
+}
+
+/* Debug for interrupts */
+#ifdef DEBUG
+static char *interrupt2str(u16 interrupt)
+{
+	static char buf[TMP_BUF_MAX];
+	char *p = buf;
+
+	interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL;
+	interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"MDM_DL2 ") : NULL;
+
+	interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"MDM_UL1 ") : NULL;
+	interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"MDM_UL2 ") : NULL;
+
+	interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"DIAG_DL1 ") : NULL;
+	interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"DIAG_DL2 ") : NULL;
+
+	interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"DIAG_UL ") : NULL;
+
+	interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"APP1_DL ") : NULL;
+	interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"APP2_DL ") : NULL;
+
+	interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"APP1_UL ") : NULL;
+	interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"APP2_UL ") : NULL;
+
+	interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"CTRL_DL ") : NULL;
+	interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"CTRL_UL ") : NULL;
+
+	interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
+					"RESET ") : NULL;
+
+	return buf;
+}
+#endif
+
+/*
+ * Receive flow control
+ * Return 1 - If ok, else 0
+ */
+static int receive_flow_control(struct nozomi *dc)
+{
+	enum port_type port = PORT_MDM;
+	struct ctrl_dl ctrl_dl;
+	struct ctrl_dl old_ctrl;
+	u16 enable_ier = 0;
+
+	read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2);
+
+	switch (ctrl_dl.port) {
+	case CTRL_CMD:
+		DBG1("The Base Band sends this value as a response to a "
+			"request for IMSI detach sent over the control "
+			"channel uplink (see section 7.6.1).");
+		break;
+	case CTRL_MDM:
+		port = PORT_MDM;
+		enable_ier = MDM_DL;
+		break;
+	case CTRL_DIAG:
+		port = PORT_DIAG;
+		enable_ier = DIAG_DL;
+		break;
+	case CTRL_APP1:
+		port = PORT_APP1;
+		enable_ier = APP1_DL;
+		break;
+	case CTRL_APP2:
+		port = PORT_APP2;
+		enable_ier = APP2_DL;
+		if (dc->state == NOZOMI_STATE_ALLOCATED) {
+			/*
+			 * After card initialization the flow control
+			 * received for APP2 is always the last
+			 */
+			dc->state = NOZOMI_STATE_READY;
+			dev_info(&dc->pdev->dev, "Device READY!\n");
+		}
+		break;
+	default:
+		dev_err(&dc->pdev->dev,
+			"ERROR: flow control received for non-existing port\n");
+		return 0;
+	};
+
+	DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
+	   *((u16 *)&ctrl_dl));
+
+	old_ctrl = dc->port[port].ctrl_dl;
+	dc->port[port].ctrl_dl = ctrl_dl;
+
+	if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) {
+		DBG1("Disable interrupt (0x%04X) on port: %d",
+			enable_ier, port);
+		disable_transmit_ul(port, dc);
+
+	} else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
+
+		if (kfifo_len(&dc->port[port].fifo_ul)) {
+			DBG1("Enable interrupt (0x%04X) on port: %d",
+				enable_ier, port);
+			DBG1("Data in buffer [%d], enable transmit! ",
+				kfifo_len(&dc->port[port].fifo_ul));
+			enable_transmit_ul(port, dc);
+		} else {
+			DBG1("No data in buffer...");
+		}
+	}
+
+	if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) {
+		DBG1(" No change in mctrl");
+		return 1;
+	}
+	/* Update statistics */
+	if (old_ctrl.CTS != ctrl_dl.CTS)
+		dc->port[port].tty_icount.cts++;
+	if (old_ctrl.DSR != ctrl_dl.DSR)
+		dc->port[port].tty_icount.dsr++;
+	if (old_ctrl.RI != ctrl_dl.RI)
+		dc->port[port].tty_icount.rng++;
+	if (old_ctrl.DCD != ctrl_dl.DCD)
+		dc->port[port].tty_icount.dcd++;
+
+	wake_up_interruptible(&dc->port[port].tty_wait);
+
+	DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)",
+	   port,
+	   dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts,
+	   dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr);
+
+	return 1;
+}
+
+static enum ctrl_port_type port2ctrl(enum port_type port,
+					const struct nozomi *dc)
+{
+	switch (port) {
+	case PORT_MDM:
+		return CTRL_MDM;
+	case PORT_DIAG:
+		return CTRL_DIAG;
+	case PORT_APP1:
+		return CTRL_APP1;
+	case PORT_APP2:
+		return CTRL_APP2;
+	default:
+		dev_err(&dc->pdev->dev,
+			"ERROR: send flow control " \
+			"received for non-existing port\n");
+	};
+	return CTRL_ERROR;
+}
+
+/*
+ * Send flow control, can only update one channel at a time
+ * Return 0 - If we have updated all flow control
+ * Return 1 - If we need to update more flow control, ack current enable more
+ */
+static int send_flow_control(struct nozomi *dc)
+{
+	u32 i, more_flow_control_to_be_updated = 0;
+	u16 *ctrl;
+
+	for (i = PORT_MDM; i < MAX_PORT; i++) {
+		if (dc->port[i].update_flow_control) {
+			if (more_flow_control_to_be_updated) {
+				/* We have more flow control to be updated */
+				return 1;
+			}
+			dc->port[i].ctrl_ul.port = port2ctrl(i, dc);
+			ctrl = (u16 *)&dc->port[i].ctrl_ul;
+			write_mem32(dc->port[PORT_CTRL].ul_addr[0], \
+				(u32 *) ctrl, 2);
+			dc->port[i].update_flow_control = 0;
+			more_flow_control_to_be_updated = 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Handle downlink data, ports that are handled are modem and diagnostics
+ * Return 1 - ok
+ * Return 0 - toggle fields are out of sync
+ */
+static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle,
+			u16 read_iir, u16 mask1, u16 mask2)
+{
+	if (*toggle == 0 && read_iir & mask1) {
+		if (receive_data(port, dc)) {
+			writew(mask1, dc->reg_fcr);
+			*toggle = !(*toggle);
+		}
+
+		if (read_iir & mask2) {
+			if (receive_data(port, dc)) {
+				writew(mask2, dc->reg_fcr);
+				*toggle = !(*toggle);
+			}
+		}
+	} else if (*toggle == 1 && read_iir & mask2) {
+		if (receive_data(port, dc)) {
+			writew(mask2, dc->reg_fcr);
+			*toggle = !(*toggle);
+		}
+
+		if (read_iir & mask1) {
+			if (receive_data(port, dc)) {
+				writew(mask1, dc->reg_fcr);
+				*toggle = !(*toggle);
+			}
+		}
+	} else {
+		dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n",
+			*toggle);
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * Handle uplink data, this is currently for the modem port
+ * Return 1 - ok
+ * Return 0 - toggle field are out of sync
+ */
+static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir)
+{
+	u8 *toggle = &(dc->port[port].toggle_ul);
+
+	if (*toggle == 0 && read_iir & MDM_UL1) {
+		dc->last_ier &= ~MDM_UL;
+		writew(dc->last_ier, dc->reg_ier);
+		if (send_data(port, dc)) {
+			writew(MDM_UL1, dc->reg_fcr);
+			dc->last_ier = dc->last_ier | MDM_UL;
+			writew(dc->last_ier, dc->reg_ier);
+			*toggle = !*toggle;
+		}
+
+		if (read_iir & MDM_UL2) {
+			dc->last_ier &= ~MDM_UL;
+			writew(dc->last_ier, dc->reg_ier);
+			if (send_data(port, dc)) {
+				writew(MDM_UL2, dc->reg_fcr);
+				dc->last_ier = dc->last_ier | MDM_UL;
+				writew(dc->last_ier, dc->reg_ier);
+				*toggle = !*toggle;
+			}
+		}
+
+	} else if (*toggle == 1 && read_iir & MDM_UL2) {
+		dc->last_ier &= ~MDM_UL;
+		writew(dc->last_ier, dc->reg_ier);
+		if (send_data(port, dc)) {
+			writew(MDM_UL2, dc->reg_fcr);
+			dc->last_ier = dc->last_ier | MDM_UL;
+			writew(dc->last_ier, dc->reg_ier);
+			*toggle = !*toggle;
+		}
+
+		if (read_iir & MDM_UL1) {
+			dc->last_ier &= ~MDM_UL;
+			writew(dc->last_ier, dc->reg_ier);
+			if (send_data(port, dc)) {
+				writew(MDM_UL1, dc->reg_fcr);
+				dc->last_ier = dc->last_ier | MDM_UL;
+				writew(dc->last_ier, dc->reg_ier);
+				*toggle = !*toggle;
+			}
+		}
+	} else {
+		writew(read_iir & MDM_UL, dc->reg_fcr);
+		dev_err(&dc->pdev->dev, "port out of sync!\n");
+		return 0;
+	}
+	return 1;
+}
+
+static irqreturn_t interrupt_handler(int irq, void *dev_id)
+{
+	struct nozomi *dc = dev_id;
+	unsigned int a;
+	u16 read_iir;
+
+	if (!dc)
+		return IRQ_NONE;
+
+	spin_lock(&dc->spin_mutex);
+	read_iir = readw(dc->reg_iir);
+
+	/* Card removed */
+	if (read_iir == (u16)-1)
+		goto none;
+	/*
+	 * Just handle interrupt enabled in IER
+	 * (by masking with dc->last_ier)
+	 */
+	read_iir &= dc->last_ier;
+
+	if (read_iir == 0)
+		goto none;
+
+
+	DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir,
+		dc->last_ier);
+
+	if (read_iir & RESET) {
+		if (unlikely(!nozomi_read_config_table(dc))) {
+			dc->last_ier = 0x0;
+			writew(dc->last_ier, dc->reg_ier);
+			dev_err(&dc->pdev->dev, "Could not read status from "
+				"card, we should disable interface\n");
+		} else {
+			writew(RESET, dc->reg_fcr);
+		}
+		/* No more useful info if this was the reset interrupt. */
+		goto exit_handler;
+	}
+	if (read_iir & CTRL_UL) {
+		DBG1("CTRL_UL");
+		dc->last_ier &= ~CTRL_UL;
+		writew(dc->last_ier, dc->reg_ier);
+		if (send_flow_control(dc)) {
+			writew(CTRL_UL, dc->reg_fcr);
+			dc->last_ier = dc->last_ier | CTRL_UL;
+			writew(dc->last_ier, dc->reg_ier);
+		}
+	}
+	if (read_iir & CTRL_DL) {
+		receive_flow_control(dc);
+		writew(CTRL_DL, dc->reg_fcr);
+	}
+	if (read_iir & MDM_DL) {
+		if (!handle_data_dl(dc, PORT_MDM,
+				&(dc->port[PORT_MDM].toggle_dl), read_iir,
+				MDM_DL1, MDM_DL2)) {
+			dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n");
+			goto exit_handler;
+		}
+	}
+	if (read_iir & MDM_UL) {
+		if (!handle_data_ul(dc, PORT_MDM, read_iir)) {
+			dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n");
+			goto exit_handler;
+		}
+	}
+	if (read_iir & DIAG_DL) {
+		if (!handle_data_dl(dc, PORT_DIAG,
+				&(dc->port[PORT_DIAG].toggle_dl), read_iir,
+				DIAG_DL1, DIAG_DL2)) {
+			dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n");
+			goto exit_handler;
+		}
+	}
+	if (read_iir & DIAG_UL) {
+		dc->last_ier &= ~DIAG_UL;
+		writew(dc->last_ier, dc->reg_ier);
+		if (send_data(PORT_DIAG, dc)) {
+			writew(DIAG_UL, dc->reg_fcr);
+			dc->last_ier = dc->last_ier | DIAG_UL;
+			writew(dc->last_ier, dc->reg_ier);
+		}
+	}
+	if (read_iir & APP1_DL) {
+		if (receive_data(PORT_APP1, dc))
+			writew(APP1_DL, dc->reg_fcr);
+	}
+	if (read_iir & APP1_UL) {
+		dc->last_ier &= ~APP1_UL;
+		writew(dc->last_ier, dc->reg_ier);
+		if (send_data(PORT_APP1, dc)) {
+			writew(APP1_UL, dc->reg_fcr);
+			dc->last_ier = dc->last_ier | APP1_UL;
+			writew(dc->last_ier, dc->reg_ier);
+		}
+	}
+	if (read_iir & APP2_DL) {
+		if (receive_data(PORT_APP2, dc))
+			writew(APP2_DL, dc->reg_fcr);
+	}
+	if (read_iir & APP2_UL) {
+		dc->last_ier &= ~APP2_UL;
+		writew(dc->last_ier, dc->reg_ier);
+		if (send_data(PORT_APP2, dc)) {
+			writew(APP2_UL, dc->reg_fcr);
+			dc->last_ier = dc->last_ier | APP2_UL;
+			writew(dc->last_ier, dc->reg_ier);
+		}
+	}
+
+exit_handler:
+	spin_unlock(&dc->spin_mutex);
+	for (a = 0; a < NOZOMI_MAX_PORTS; a++) {
+		struct tty_struct *tty;
+		if (test_and_clear_bit(a, &dc->flip)) {
+			tty = tty_port_tty_get(&dc->port[a].port);
+			if (tty)
+				tty_flip_buffer_push(tty);
+			tty_kref_put(tty);
+		}
+	}
+	return IRQ_HANDLED;
+none:
+	spin_unlock(&dc->spin_mutex);
+	return IRQ_NONE;
+}
+
+static void nozomi_get_card_type(struct nozomi *dc)
+{
+	int i;
+	u32 size = 0;
+
+	for (i = 0; i < 6; i++)
+		size += pci_resource_len(dc->pdev, i);
+
+	/* Assume card type F32_8 if no match */
+	dc->card_type = size == 2048 ? F32_2 : F32_8;
+
+	dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type);
+}
+
+static void nozomi_setup_private_data(struct nozomi *dc)
+{
+	void __iomem *offset = dc->base_addr + dc->card_type / 2;
+	unsigned int i;
+
+	dc->reg_fcr = (void __iomem *)(offset + R_FCR);
+	dc->reg_iir = (void __iomem *)(offset + R_IIR);
+	dc->reg_ier = (void __iomem *)(offset + R_IER);
+	dc->last_ier = 0;
+	dc->flip = 0;
+
+	dc->port[PORT_MDM].token_dl = MDM_DL;
+	dc->port[PORT_DIAG].token_dl = DIAG_DL;
+	dc->port[PORT_APP1].token_dl = APP1_DL;
+	dc->port[PORT_APP2].token_dl = APP2_DL;
+
+	for (i = 0; i < MAX_PORT; i++)
+		init_waitqueue_head(&dc->port[i].tty_wait);
+}
+
+static ssize_t card_type_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
+
+	return sprintf(buf, "%d\n", dc->card_type);
+}
+static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL);
+
+static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
+
+	return sprintf(buf, "%u\n", dc->open_ttys);
+}
+static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL);
+
+static void make_sysfs_files(struct nozomi *dc)
+{
+	if (device_create_file(&dc->pdev->dev, &dev_attr_card_type))
+		dev_err(&dc->pdev->dev,
+			"Could not create sysfs file for card_type\n");
+	if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys))
+		dev_err(&dc->pdev->dev,
+			"Could not create sysfs file for open_ttys\n");
+}
+
+static void remove_sysfs_files(struct nozomi *dc)
+{
+	device_remove_file(&dc->pdev->dev, &dev_attr_card_type);
+	device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys);
+}
+
+/* Allocate memory for one device */
+static int __devinit nozomi_card_init(struct pci_dev *pdev,
+				      const struct pci_device_id *ent)
+{
+	resource_size_t start;
+	int ret;
+	struct nozomi *dc = NULL;
+	int ndev_idx;
+	int i;
+
+	dev_dbg(&pdev->dev, "Init, new card found\n");
+
+	for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
+		if (!ndevs[ndev_idx])
+			break;
+
+	if (ndev_idx >= ARRAY_SIZE(ndevs)) {
+		dev_err(&pdev->dev, "no free tty range for this card left\n");
+		ret = -EIO;
+		goto err;
+	}
+
+	dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
+	if (unlikely(!dc)) {
+		dev_err(&pdev->dev, "Could not allocate memory\n");
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	dc->pdev = pdev;
+
+	ret = pci_enable_device(dc->pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
+		goto err_free;
+	}
+
+	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
+	if (ret) {
+		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
+			(int) /* nozomi_private.io_addr */ 0);
+		goto err_disable_device;
+	}
+
+	start = pci_resource_start(dc->pdev, 0);
+	if (start == 0) {
+		dev_err(&pdev->dev, "No I/O address for card detected\n");
+		ret = -ENODEV;
+		goto err_rel_regs;
+	}
+
+	/* Find out what card type it is */
+	nozomi_get_card_type(dc);
+
+	dc->base_addr = ioremap_nocache(start, dc->card_type);
+	if (!dc->base_addr) {
+		dev_err(&pdev->dev, "Unable to map card MMIO\n");
+		ret = -ENODEV;
+		goto err_rel_regs;
+	}
+
+	dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL);
+	if (!dc->send_buf) {
+		dev_err(&pdev->dev, "Could not allocate send buffer?\n");
+		ret = -ENOMEM;
+		goto err_free_sbuf;
+	}
+
+	for (i = PORT_MDM; i < MAX_PORT; i++) {
+		if (kfifo_alloc(&dc->port[i].fifo_ul,
+		      FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) {
+			dev_err(&pdev->dev,
+					"Could not allocate kfifo buffer\n");
+			ret = -ENOMEM;
+			goto err_free_kfifo;
+		}
+	}
+
+	spin_lock_init(&dc->spin_mutex);
+
+	nozomi_setup_private_data(dc);
+
+	/* Disable all interrupts */
+	dc->last_ier = 0;
+	writew(dc->last_ier, dc->reg_ier);
+
+	ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
+			NOZOMI_NAME, dc);
+	if (unlikely(ret)) {
+		dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
+		goto err_free_kfifo;
+	}
+
+	DBG1("base_addr: %p", dc->base_addr);
+
+	make_sysfs_files(dc);
+
+	dc->index_start = ndev_idx * MAX_PORT;
+	ndevs[ndev_idx] = dc;
+
+	pci_set_drvdata(pdev, dc);
+
+	/* Enable RESET interrupt */
+	dc->last_ier = RESET;
+	iowrite16(dc->last_ier, dc->reg_ier);
+
+	dc->state = NOZOMI_STATE_ENABLED;
+
+	for (i = 0; i < MAX_PORT; i++) {
+		struct device *tty_dev;
+		struct port *port = &dc->port[i];
+		port->dc = dc;
+		mutex_init(&port->tty_sem);
+		tty_port_init(&port->port);
+		port->port.ops = &noz_tty_port_ops;
+		tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
+							&pdev->dev);
+
+		if (IS_ERR(tty_dev)) {
+			ret = PTR_ERR(tty_dev);
+			dev_err(&pdev->dev, "Could not allocate tty?\n");
+			goto err_free_tty;
+		}
+	}
+
+	return 0;
+
+err_free_tty:
+	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
+		tty_unregister_device(ntty_driver, i);
+err_free_kfifo:
+	for (i = 0; i < MAX_PORT; i++)
+		kfifo_free(&dc->port[i].fifo_ul);
+err_free_sbuf:
+	kfree(dc->send_buf);
+	iounmap(dc->base_addr);
+err_rel_regs:
+	pci_release_regions(pdev);
+err_disable_device:
+	pci_disable_device(pdev);
+err_free:
+	kfree(dc);
+err:
+	return ret;
+}
+
+static void __devexit tty_exit(struct nozomi *dc)
+{
+	unsigned int i;
+
+	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);
+	}
+	/* Racy below - surely should wait for scheduled work to be done or
+	   complete off a hangup method ? */
+	while (dc->open_ttys)
+		msleep(1);
+	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
+		tty_unregister_device(ntty_driver, i);
+}
+
+/* Deallocate memory for one device */
+static void __devexit nozomi_card_exit(struct pci_dev *pdev)
+{
+	int i;
+	struct ctrl_ul ctrl;
+	struct nozomi *dc = pci_get_drvdata(pdev);
+
+	/* Disable all interrupts */
+	dc->last_ier = 0;
+	writew(dc->last_ier, dc->reg_ier);
+
+	tty_exit(dc);
+
+	/* Send 0x0001, command card to resend the reset token.  */
+	/* This is to get the reset when the module is reloaded. */
+	ctrl.port = 0x00;
+	ctrl.reserved = 0;
+	ctrl.RTS = 0;
+	ctrl.DTR = 1;
+	DBG1("sending flow control 0x%04X", *((u16 *)&ctrl));
+
+	/* Setup dc->reg addresses to we can use defines here */
+	write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2);
+	writew(CTRL_UL, dc->reg_fcr);	/* push the token to the card. */
+
+	remove_sysfs_files(dc);
+
+	free_irq(pdev->irq, dc);
+
+	for (i = 0; i < MAX_PORT; i++)
+		kfifo_free(&dc->port[i].fifo_ul);
+
+	kfree(dc->send_buf);
+
+	iounmap(dc->base_addr);
+
+	pci_release_regions(pdev);
+
+	pci_disable_device(pdev);
+
+	ndevs[dc->index_start / MAX_PORT] = NULL;
+
+	kfree(dc);
+}
+
+static void set_rts(const struct tty_struct *tty, int rts)
+{
+	struct port *port = get_port_by_tty(tty);
+
+	port->ctrl_ul.RTS = rts;
+	port->update_flow_control = 1;
+	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
+}
+
+static void set_dtr(const struct tty_struct *tty, int dtr)
+{
+	struct port *port = get_port_by_tty(tty);
+
+	DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr);
+
+	port->ctrl_ul.DTR = dtr;
+	port->update_flow_control = 1;
+	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
+}
+
+/*
+ * ----------------------------------------------------------------------------
+ * TTY code
+ * ----------------------------------------------------------------------------
+ */
+
+static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
+{
+	struct port *port = get_port_by_tty(tty);
+	struct nozomi *dc = get_dc_by_tty(tty);
+	int ret;
+	if (!port || !dc || dc->state != NOZOMI_STATE_READY)
+		return -ENODEV;
+	ret = tty_init_termios(tty);
+	if (ret == 0) {
+		tty_driver_kref_get(driver);
+		tty->count++;
+		tty->driver_data = port;
+		driver->ttys[tty->index] = tty;
+	}
+	return ret;
+}
+
+static void ntty_cleanup(struct tty_struct *tty)
+{
+	tty->driver_data = NULL;
+}
+
+static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
+{
+	struct port *port = container_of(tport, struct port, port);
+	struct nozomi *dc = port->dc;
+	unsigned long flags;
+
+	DBG1("open: %d", port->token_dl);
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	dc->last_ier = dc->last_ier | port->token_dl;
+	writew(dc->last_ier, dc->reg_ier);
+	dc->open_ttys++;
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+	printk("noz: activated %d: %p\n", tty->index, tport);
+	return 0;
+}
+
+static int ntty_open(struct tty_struct *tty, struct file *filp)
+{
+	struct port *port = tty->driver_data;
+	return tty_port_open(&port->port, tty, filp);
+}
+
+static void ntty_shutdown(struct tty_port *tport)
+{
+	struct port *port = container_of(tport, struct port, port);
+	struct nozomi *dc = port->dc;
+	unsigned long flags;
+
+	DBG1("close: %d", port->token_dl);
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	dc->last_ier &= ~(port->token_dl);
+	writew(dc->last_ier, dc->reg_ier);
+	dc->open_ttys--;
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+	printk("noz: shutdown %p\n", tport);
+}
+
+static void ntty_close(struct tty_struct *tty, struct file *filp)
+{
+	struct port *port = tty->driver_data;
+	if (port)
+		tty_port_close(&port->port, tty, filp);
+}
+
+static void ntty_hangup(struct tty_struct *tty)
+{
+	struct port *port = tty->driver_data;
+	tty_port_hangup(&port->port);
+}
+
+/*
+ * called when the userspace process writes to the tty (/dev/noz*).
+ * Data is inserted into a fifo, which is then read and transfered to the modem.
+ */
+static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
+		      int count)
+{
+	int rval = -EINVAL;
+	struct nozomi *dc = get_dc_by_tty(tty);
+	struct port *port = tty->driver_data;
+	unsigned long flags;
+
+	/* DBG1( "WRITEx: %d, index = %d", count, index); */
+
+	if (!dc || !port)
+		return -ENODEV;
+
+	mutex_lock(&port->tty_sem);
+
+	if (unlikely(!port->port.count)) {
+		DBG1(" ");
+		goto exit;
+	}
+
+	rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
+
+	/* notify card */
+	if (unlikely(dc == NULL)) {
+		DBG1("No device context?");
+		goto exit;
+	}
+
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	/* CTS is only valid on the modem channel */
+	if (port == &(dc->port[PORT_MDM])) {
+		if (port->ctrl_dl.CTS) {
+			DBG4("Enable interrupt");
+			enable_transmit_ul(tty->index % MAX_PORT, dc);
+		} else {
+			dev_err(&dc->pdev->dev,
+				"CTS not active on modem port?\n");
+		}
+	} else {
+		enable_transmit_ul(tty->index % MAX_PORT, dc);
+	}
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+
+exit:
+	mutex_unlock(&port->tty_sem);
+	return rval;
+}
+
+/*
+ * Calculate how much is left in device
+ * This method is called by the upper tty layer.
+ *   #according to sources N_TTY.c it expects a value >= 0 and
+ *    does not check for negative values.
+ *
+ * If the port is unplugged report lots of room and let the bits
+ * dribble away so we don't block anything.
+ */
+static int ntty_write_room(struct tty_struct *tty)
+{
+	struct port *port = tty->driver_data;
+	int room = 4096;
+	const struct nozomi *dc = get_dc_by_tty(tty);
+
+	if (dc) {
+		mutex_lock(&port->tty_sem);
+		if (port->port.count)
+			room = kfifo_avail(&port->fifo_ul);
+		mutex_unlock(&port->tty_sem);
+	}
+	return room;
+}
+
+/* Gets io control parameters */
+static int ntty_tiocmget(struct tty_struct *tty)
+{
+	const struct port *port = tty->driver_data;
+	const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
+	const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
+
+	/* Note: these could change under us but it is not clear this
+	   matters if so */
+	return	(ctrl_ul->RTS ? TIOCM_RTS : 0) |
+		(ctrl_ul->DTR ? TIOCM_DTR : 0) |
+		(ctrl_dl->DCD ? TIOCM_CAR : 0) |
+		(ctrl_dl->RI  ? TIOCM_RNG : 0) |
+		(ctrl_dl->DSR ? TIOCM_DSR : 0) |
+		(ctrl_dl->CTS ? TIOCM_CTS : 0);
+}
+
+/* Sets io controls parameters */
+static int ntty_tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear)
+{
+	struct nozomi *dc = get_dc_by_tty(tty);
+	unsigned long flags;
+
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	if (set & TIOCM_RTS)
+		set_rts(tty, 1);
+	else if (clear & TIOCM_RTS)
+		set_rts(tty, 0);
+
+	if (set & TIOCM_DTR)
+		set_dtr(tty, 1);
+	else if (clear & TIOCM_DTR)
+		set_dtr(tty, 0);
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+
+	return 0;
+}
+
+static int ntty_cflags_changed(struct port *port, unsigned long flags,
+		struct async_icount *cprev)
+{
+	const struct async_icount cnow = port->tty_icount;
+	int ret;
+
+	ret =	((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
+		((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
+		((flags & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
+		((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
+
+	*cprev = cnow;
+
+	return ret;
+}
+
+static int ntty_tiocgicount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	struct port *port = tty->driver_data;
+	const struct async_icount cnow = port->tty_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 ntty_ioctl(struct tty_struct *tty,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct port *port = tty->driver_data;
+	int rval = -ENOIOCTLCMD;
+
+	DBG1("******** IOCTL, cmd: %d", cmd);
+
+	switch (cmd) {
+	case TIOCMIWAIT: {
+		struct async_icount cprev = port->tty_icount;
+
+		rval = wait_event_interruptible(port->tty_wait,
+				ntty_cflags_changed(port, arg, &cprev));
+		break;
+	}
+	default:
+		DBG1("ERR: 0x%08X, %d", cmd, cmd);
+		break;
+	};
+
+	return rval;
+}
+
+/*
+ * Called by the upper tty layer when tty buffers are ready
+ * to receive data again after a call to throttle.
+ */
+static void ntty_unthrottle(struct tty_struct *tty)
+{
+	struct nozomi *dc = get_dc_by_tty(tty);
+	unsigned long flags;
+
+	DBG1("UNTHROTTLE");
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	enable_transmit_dl(tty->index % MAX_PORT, dc);
+	set_rts(tty, 1);
+
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+}
+
+/*
+ * Called by the upper tty layer when the tty buffers are almost full.
+ * The driver should stop send more data.
+ */
+static void ntty_throttle(struct tty_struct *tty)
+{
+	struct nozomi *dc = get_dc_by_tty(tty);
+	unsigned long flags;
+
+	DBG1("THROTTLE");
+	spin_lock_irqsave(&dc->spin_mutex, flags);
+	set_rts(tty, 0);
+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
+}
+
+/* Returns number of chars in buffer, called by tty layer */
+static s32 ntty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct port *port = tty->driver_data;
+	struct nozomi *dc = get_dc_by_tty(tty);
+	s32 rval = 0;
+
+	if (unlikely(!dc || !port)) {
+		goto exit_in_buffer;
+	}
+
+	if (unlikely(!port->port.count)) {
+		dev_err(&dc->pdev->dev, "No tty open?\n");
+		goto exit_in_buffer;
+	}
+
+	rval = kfifo_len(&port->fifo_ul);
+
+exit_in_buffer:
+	return rval;
+}
+
+static const struct tty_port_operations noz_tty_port_ops = {
+	.activate = ntty_activate,
+	.shutdown = ntty_shutdown,
+};
+
+static const struct tty_operations tty_ops = {
+	.ioctl = ntty_ioctl,
+	.open = ntty_open,
+	.close = ntty_close,
+	.hangup = ntty_hangup,
+	.write = ntty_write,
+	.write_room = ntty_write_room,
+	.unthrottle = ntty_unthrottle,
+	.throttle = ntty_throttle,
+	.chars_in_buffer = ntty_chars_in_buffer,
+	.tiocmget = ntty_tiocmget,
+	.tiocmset = ntty_tiocmset,
+	.get_icount = ntty_tiocgicount,
+	.install = ntty_install,
+	.cleanup = ntty_cleanup,
+};
+
+/* Module initialization */
+static struct pci_driver nozomi_driver = {
+	.name = NOZOMI_NAME,
+	.id_table = nozomi_pci_tbl,
+	.probe = nozomi_card_init,
+	.remove = __devexit_p(nozomi_card_exit),
+};
+
+static __init int nozomi_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
+
+	ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
+	if (!ntty_driver)
+		return -ENOMEM;
+
+	ntty_driver->owner = THIS_MODULE;
+	ntty_driver->driver_name = NOZOMI_NAME_TTY;
+	ntty_driver->name = "noz";
+	ntty_driver->major = 0;
+	ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	ntty_driver->subtype = SERIAL_TYPE_NORMAL;
+	ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	ntty_driver->init_termios = tty_std_termios;
+	ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
+						HUPCL | CLOCAL;
+	ntty_driver->init_termios.c_ispeed = 115200;
+	ntty_driver->init_termios.c_ospeed = 115200;
+	tty_set_operations(ntty_driver, &tty_ops);
+
+	ret = tty_register_driver(ntty_driver);
+	if (ret) {
+		printk(KERN_ERR "Nozomi: failed to register ntty driver\n");
+		goto free_tty;
+	}
+
+	ret = pci_register_driver(&nozomi_driver);
+	if (ret) {
+		printk(KERN_ERR "Nozomi: can't register pci driver\n");
+		goto unr_tty;
+	}
+
+	return 0;
+unr_tty:
+	tty_unregister_driver(ntty_driver);
+free_tty:
+	put_tty_driver(ntty_driver);
+	return ret;
+}
+
+static __exit void nozomi_exit(void)
+{
+	printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
+	pci_unregister_driver(&nozomi_driver);
+	tty_unregister_driver(ntty_driver);
+	put_tty_driver(ntty_driver);
+}
+
+module_init(nozomi_init);
+module_exit(nozomi_exit);
+
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 923a485..2107747 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -23,7 +23,6 @@
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/init.h>
-#include <linux/smp_lock.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
 #include <linux/uaccess.h>
@@ -334,7 +333,7 @@ free_mem_out:
 	return -ENOMEM;
 }
 
-static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file,
+static int pty_bsd_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	switch (cmd) {
@@ -489,7 +488,7 @@ static struct ctl_table pty_root_table[] = {
 };
 
 
-static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file,
+static int pty_unix98_ioctl(struct tty_struct *tty,
 			    unsigned int cmd, unsigned long arg)
 {
 	switch (cmd) {
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
new file mode 100644
index 0000000..3780da8
--- /dev/null
+++ b/drivers/tty/rocket.c
@@ -0,0 +1,3199 @@
+/*
+ * RocketPort device driver for Linux
+ *
+ * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
+ * 
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, 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.
+ */
+
+/*
+ * Kernel Synchronization:
+ *
+ * This driver has 2 kernel control paths - exception handlers (calls into the driver
+ * from user mode) and the timer bottom half (tasklet).  This is a polled driver, interrupts
+ * are not used.
+ *
+ * Critical data: 
+ * -  rp_table[], accessed through passed "info" pointers, is a global (static) array of 
+ *    serial port state information and the xmit_buf circular buffer.  Protected by 
+ *    a per port spinlock.
+ * -  xmit_flags[], an array of ints indexed by line (port) number, indicating that there
+ *    is data to be transmitted.  Protected by atomic bit operations.
+ * -  rp_num_ports, int indicating number of open ports, protected by atomic operations.
+ * 
+ * rp_write() and rp_write_char() functions use a per port semaphore to protect against
+ * simultaneous access to the same port by more than one process.
+ */
+
+/****** Defines ******/
+#define ROCKET_PARANOIA_CHECK
+#define ROCKET_DISABLE_SIMUSAGE
+
+#undef ROCKET_SOFT_FLOW
+#undef ROCKET_DEBUG_OPEN
+#undef ROCKET_DEBUG_INTR
+#undef ROCKET_DEBUG_WRITE
+#undef ROCKET_DEBUG_FLOW
+#undef ROCKET_DEBUG_THROTTLE
+#undef ROCKET_DEBUG_WAIT_UNTIL_SENT
+#undef ROCKET_DEBUG_RECEIVE
+#undef ROCKET_DEBUG_HANGUP
+#undef REV_PCI_ORDER
+#undef ROCKET_DEBUG_IO
+
+#define POLL_PERIOD HZ/100	/*  Polling period .01 seconds (10ms) */
+
+/****** Kernel includes ******/
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/mutex.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <linux/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/unaligned.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+/****** RocketPort includes ******/
+
+#include "rocket_int.h"
+#include "rocket.h"
+
+#define ROCKET_VERSION "2.09"
+#define ROCKET_DATE "12-June-2003"
+
+/****** RocketPort Local Variables ******/
+
+static void rp_do_poll(unsigned long dummy);
+
+static struct tty_driver *rocket_driver;
+
+static struct rocket_version driver_version = {	
+	ROCKET_VERSION, ROCKET_DATE
+};
+
+static struct r_port *rp_table[MAX_RP_PORTS];	       /*  The main repository of serial port state information. */
+static unsigned int xmit_flags[NUM_BOARDS];	       /*  Bit significant, indicates port had data to transmit. */
+						       /*  eg.  Bit 0 indicates port 0 has xmit data, ...        */
+static atomic_t rp_num_ports_open;	               /*  Number of serial ports open                           */
+static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0);
+
+static unsigned long board1;	                       /* ISA addresses, retrieved from rocketport.conf          */
+static unsigned long board2;
+static unsigned long board3;
+static unsigned long board4;
+static unsigned long controller;
+static int support_low_speed;
+static unsigned long modem1;
+static unsigned long modem2;
+static unsigned long modem3;
+static unsigned long modem4;
+static unsigned long pc104_1[8];
+static unsigned long pc104_2[8];
+static unsigned long pc104_3[8];
+static unsigned long pc104_4[8];
+static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
+
+static int rp_baud_base[NUM_BOARDS];	               /*  Board config info (Someday make a per-board structure)  */
+static unsigned long rcktpt_io_addr[NUM_BOARDS];
+static int rcktpt_type[NUM_BOARDS];
+static int is_PCI[NUM_BOARDS];
+static rocketModel_t rocketModel[NUM_BOARDS];
+static int max_board;
+static const struct tty_port_operations rocket_port_ops;
+
+/*
+ * The following arrays define the interrupt bits corresponding to each AIOP.
+ * These bits are different between the ISA and regular PCI boards and the
+ * Universal PCI boards.
+ */
+
+static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
+	AIOP_INTR_BIT_0,
+	AIOP_INTR_BIT_1,
+	AIOP_INTR_BIT_2,
+	AIOP_INTR_BIT_3
+};
+
+static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
+	UPCI_AIOP_INTR_BIT_0,
+	UPCI_AIOP_INTR_BIT_1,
+	UPCI_AIOP_INTR_BIT_2,
+	UPCI_AIOP_INTR_BIT_3
+};
+
+static Byte_t RData[RDATASIZE] = {
+	0x00, 0x09, 0xf6, 0x82,
+	0x02, 0x09, 0x86, 0xfb,
+	0x04, 0x09, 0x00, 0x0a,
+	0x06, 0x09, 0x01, 0x0a,
+	0x08, 0x09, 0x8a, 0x13,
+	0x0a, 0x09, 0xc5, 0x11,
+	0x0c, 0x09, 0x86, 0x85,
+	0x0e, 0x09, 0x20, 0x0a,
+	0x10, 0x09, 0x21, 0x0a,
+	0x12, 0x09, 0x41, 0xff,
+	0x14, 0x09, 0x82, 0x00,
+	0x16, 0x09, 0x82, 0x7b,
+	0x18, 0x09, 0x8a, 0x7d,
+	0x1a, 0x09, 0x88, 0x81,
+	0x1c, 0x09, 0x86, 0x7a,
+	0x1e, 0x09, 0x84, 0x81,
+	0x20, 0x09, 0x82, 0x7c,
+	0x22, 0x09, 0x0a, 0x0a
+};
+
+static Byte_t RRegData[RREGDATASIZE] = {
+	0x00, 0x09, 0xf6, 0x82,	/* 00: Stop Rx processor */
+	0x08, 0x09, 0x8a, 0x13,	/* 04: Tx software flow control */
+	0x0a, 0x09, 0xc5, 0x11,	/* 08: XON char */
+	0x0c, 0x09, 0x86, 0x85,	/* 0c: XANY */
+	0x12, 0x09, 0x41, 0xff,	/* 10: Rx mask char */
+	0x14, 0x09, 0x82, 0x00,	/* 14: Compare/Ignore #0 */
+	0x16, 0x09, 0x82, 0x7b,	/* 18: Compare #1 */
+	0x18, 0x09, 0x8a, 0x7d,	/* 1c: Compare #2 */
+	0x1a, 0x09, 0x88, 0x81,	/* 20: Interrupt #1 */
+	0x1c, 0x09, 0x86, 0x7a,	/* 24: Ignore/Replace #1 */
+	0x1e, 0x09, 0x84, 0x81,	/* 28: Interrupt #2 */
+	0x20, 0x09, 0x82, 0x7c,	/* 2c: Ignore/Replace #2 */
+	0x22, 0x09, 0x0a, 0x0a	/* 30: Rx FIFO Enable */
+};
+
+static CONTROLLER_T sController[CTL_SIZE] = {
+	{-1, -1, 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, 0, 0, 0}},
+	{-1, -1, 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, 0, 0, 0}},
+	{-1, -1, 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, 0, 0, 0}},
+	{-1, -1, 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, 0, 0, 0}}
+};
+
+static Byte_t sBitMapClrTbl[8] = {
+	0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
+};
+
+static Byte_t sBitMapSetTbl[8] = {
+	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
+
+static int sClockPrescale = 0x14;
+
+/*
+ *  Line number is the ttySIx number (x), the Minor number.  We 
+ *  assign them sequentially, starting at zero.  The following 
+ *  array keeps track of the line number assigned to a given board/aiop/channel.
+ */
+static unsigned char lineNumbers[MAX_RP_PORTS];
+static unsigned long nextLineNumber;
+
+/*****  RocketPort Static Prototypes   *********/
+static int __init init_ISA(int i);
+static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
+static void rp_flush_buffer(struct tty_struct *tty);
+static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
+static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
+static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
+static void rp_start(struct tty_struct *tty);
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+		     int ChanNum);
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
+static void sFlushRxFIFO(CHANNEL_T * ChP);
+static void sFlushTxFIFO(CHANNEL_T * ChP);
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+			      ByteIO_t * AiopIOList, int AiopIOListSize,
+			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+			      int PeriodicOnly, int altChanRingIndicator,
+			      int UPCIRingInd);
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+			   ByteIO_t * AiopIOList, int AiopIOListSize,
+			   int IRQNum, Byte_t Frequency, int PeriodicOnly);
+static int sReadAiopID(ByteIO_t io);
+static int sReadAiopNumChan(WordIO_t io);
+
+MODULE_AUTHOR("Theodore Ts'o");
+MODULE_DESCRIPTION("Comtrol RocketPort driver");
+module_param(board1, ulong, 0);
+MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
+module_param(board2, ulong, 0);
+MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
+module_param(board3, ulong, 0);
+MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
+module_param(board4, ulong, 0);
+MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
+module_param(controller, ulong, 0);
+MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
+module_param(support_low_speed, bool, 0);
+MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
+module_param(modem1, ulong, 0);
+MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
+module_param(modem2, ulong, 0);
+MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
+module_param(modem3, ulong, 0);
+MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
+module_param(modem4, ulong, 0);
+MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
+module_param_array(pc104_1, ulong, NULL, 0);
+MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
+module_param_array(pc104_2, ulong, NULL, 0);
+MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
+module_param_array(pc104_3, ulong, NULL, 0);
+MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
+module_param_array(pc104_4, ulong, NULL, 0);
+MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
+
+static int rp_init(void);
+static void rp_cleanup_module(void);
+
+module_init(rp_init);
+module_exit(rp_cleanup_module);
+
+
+MODULE_LICENSE("Dual BSD/GPL");
+
+/*************************************************************************/
+/*                     Module code starts here                           */
+
+static inline int rocket_paranoia_check(struct r_port *info,
+					const char *routine)
+{
+#ifdef ROCKET_PARANOIA_CHECK
+	if (!info)
+		return 1;
+	if (info->magic != RPORT_MAGIC) {
+		printk(KERN_WARNING "Warning: bad magic number for rocketport "
+				"struct in %s\n", routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+
+/*  Serial port receive data function.  Called (from timer poll) when an AIOPIC signals 
+ *  that receive data is present on a serial port.  Pulls data from FIFO, moves it into the 
+ *  tty layer.  
+ */
+static void rp_do_receive(struct r_port *info,
+			  struct tty_struct *tty,
+			  CHANNEL_t * cp, unsigned int ChanStatus)
+{
+	unsigned int CharNStat;
+	int ToRecv, wRecv, space;
+	unsigned char *cbuf;
+
+	ToRecv = sGetRxCnt(cp);
+#ifdef ROCKET_DEBUG_INTR
+	printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv);
+#endif
+	if (ToRecv == 0)
+		return;
+
+	/*
+	 * if status indicates there are errored characters in the
+	 * FIFO, then enter status mode (a word in FIFO holds
+	 * character and status).
+	 */
+	if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
+		if (!(ChanStatus & STATMODE)) {
+#ifdef ROCKET_DEBUG_RECEIVE
+			printk(KERN_INFO "Entering STATMODE...\n");
+#endif
+			ChanStatus |= STATMODE;
+			sEnRxStatusMode(cp);
+		}
+	}
+
+	/* 
+	 * if we previously entered status mode, then read down the
+	 * FIFO one word at a time, pulling apart the character and
+	 * the status.  Update error counters depending on status
+	 */
+	if (ChanStatus & STATMODE) {
+#ifdef ROCKET_DEBUG_RECEIVE
+		printk(KERN_INFO "Ignore %x, read %x...\n",
+			info->ignore_status_mask, info->read_status_mask);
+#endif
+		while (ToRecv) {
+			char flag;
+
+			CharNStat = sInW(sGetTxRxDataIO(cp));
+#ifdef ROCKET_DEBUG_RECEIVE
+			printk(KERN_INFO "%x...\n", CharNStat);
+#endif
+			if (CharNStat & STMBREAKH)
+				CharNStat &= ~(STMFRAMEH | STMPARITYH);
+			if (CharNStat & info->ignore_status_mask) {
+				ToRecv--;
+				continue;
+			}
+			CharNStat &= info->read_status_mask;
+			if (CharNStat & STMBREAKH)
+				flag = TTY_BREAK;
+			else if (CharNStat & STMPARITYH)
+				flag = TTY_PARITY;
+			else if (CharNStat & STMFRAMEH)
+				flag = TTY_FRAME;
+			else if (CharNStat & STMRCVROVRH)
+				flag = TTY_OVERRUN;
+			else
+				flag = TTY_NORMAL;
+			tty_insert_flip_char(tty, CharNStat & 0xff, flag);
+			ToRecv--;
+		}
+
+		/*
+		 * after we've emptied the FIFO in status mode, turn
+		 * status mode back off
+		 */
+		if (sGetRxCnt(cp) == 0) {
+#ifdef ROCKET_DEBUG_RECEIVE
+			printk(KERN_INFO "Status mode off.\n");
+#endif
+			sDisRxStatusMode(cp);
+		}
+	} else {
+		/*
+		 * we aren't in status mode, so read down the FIFO two
+		 * characters at time by doing repeated word IO
+		 * transfer.
+		 */
+		space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
+		if (space < ToRecv) {
+#ifdef ROCKET_DEBUG_RECEIVE
+			printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
+#endif
+			if (space <= 0)
+				return;
+			ToRecv = space;
+		}
+		wRecv = ToRecv >> 1;
+		if (wRecv)
+			sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
+		if (ToRecv & 1)
+			cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
+	}
+	/*  Push the data up to the tty layer */
+	tty_flip_buffer_push(tty);
+}
+
+/*
+ *  Serial port transmit data function.  Called from the timer polling loop as a 
+ *  result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
+ *  to be sent out the serial port.  Data is buffered in rp_table[line].xmit_buf, it is 
+ *  moved to the port's xmit FIFO.  *info is critical data, protected by spinlocks.
+ */
+static void rp_do_transmit(struct r_port *info)
+{
+	int c;
+	CHANNEL_t *cp = &info->channel;
+	struct tty_struct *tty;
+	unsigned long flags;
+
+#ifdef ROCKET_DEBUG_INTR
+	printk(KERN_DEBUG "%s\n", __func__);
+#endif
+	if (!info)
+		return;
+	tty = tty_port_tty_get(&info->port);
+
+	if (tty == NULL) {
+		printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__);
+		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+		return;
+	}
+
+	spin_lock_irqsave(&info->slock, flags);
+	info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
+
+	/*  Loop sending data to FIFO until done or FIFO full */
+	while (1) {
+		if (tty->stopped || tty->hw_stopped)
+			break;
+		c = min(info->xmit_fifo_room, info->xmit_cnt);
+		c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
+		if (c <= 0 || info->xmit_fifo_room <= 0)
+			break;
+		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
+		if (c & 1)
+			sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
+		info->xmit_tail += c;
+		info->xmit_tail &= XMIT_BUF_SIZE - 1;
+		info->xmit_cnt -= c;
+		info->xmit_fifo_room -= c;
+#ifdef ROCKET_DEBUG_INTR
+		printk(KERN_INFO "tx %d chars...\n", c);
+#endif
+	}
+
+	if (info->xmit_cnt == 0)
+		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
+	if (info->xmit_cnt < WAKEUP_CHARS) {
+		tty_wakeup(tty);
+#ifdef ROCKETPORT_HAVE_POLL_WAIT
+		wake_up_interruptible(&tty->poll_wait);
+#endif
+	}
+
+	spin_unlock_irqrestore(&info->slock, flags);
+	tty_kref_put(tty);
+
+#ifdef ROCKET_DEBUG_INTR
+	printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head,
+	       info->xmit_tail, info->xmit_fifo_room);
+#endif
+}
+
+/*
+ *  Called when a serial port signals it has read data in it's RX FIFO.
+ *  It checks what interrupts are pending and services them, including
+ *  receiving serial data.  
+ */
+static void rp_handle_port(struct r_port *info)
+{
+	CHANNEL_t *cp;
+	struct tty_struct *tty;
+	unsigned int IntMask, ChanStatus;
+
+	if (!info)
+		return;
+
+	if ((info->port.flags & ASYNC_INITIALIZED) == 0) {
+		printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
+				"info->flags & NOT_INIT\n");
+		return;
+	}
+	tty = tty_port_tty_get(&info->port);
+	if (!tty) {
+		printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
+				"tty==NULL\n");
+		return;
+	}
+	cp = &info->channel;
+
+	IntMask = sGetChanIntID(cp) & info->intmask;
+#ifdef ROCKET_DEBUG_INTR
+	printk(KERN_INFO "rp_interrupt %02x...\n", IntMask);
+#endif
+	ChanStatus = sGetChanStatus(cp);
+	if (IntMask & RXF_TRIG) {	/* Rx FIFO trigger level */
+		rp_do_receive(info, tty, cp, ChanStatus);
+	}
+	if (IntMask & DELTA_CD) {	/* CD change  */
+#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
+		printk(KERN_INFO "ttyR%d CD now %s...\n", info->line,
+		       (ChanStatus & CD_ACT) ? "on" : "off");
+#endif
+		if (!(ChanStatus & CD_ACT) && info->cd_status) {
+#ifdef ROCKET_DEBUG_HANGUP
+			printk(KERN_INFO "CD drop, calling hangup.\n");
+#endif
+			tty_hangup(tty);
+		}
+		info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
+		wake_up_interruptible(&info->port.open_wait);
+	}
+#ifdef ROCKET_DEBUG_INTR
+	if (IntMask & DELTA_CTS) {	/* CTS change */
+		printk(KERN_INFO "CTS change...\n");
+	}
+	if (IntMask & DELTA_DSR) {	/* DSR change */
+		printk(KERN_INFO "DSR change...\n");
+	}
+#endif
+	tty_kref_put(tty);
+}
+
+/*
+ *  The top level polling routine.  Repeats every 1/100 HZ (10ms).
+ */
+static void rp_do_poll(unsigned long dummy)
+{
+	CONTROLLER_t *ctlp;
+	int ctrl, aiop, ch, line;
+	unsigned int xmitmask, i;
+	unsigned int CtlMask;
+	unsigned char AiopMask;
+	Word_t bit;
+
+	/*  Walk through all the boards (ctrl's) */
+	for (ctrl = 0; ctrl < max_board; ctrl++) {
+		if (rcktpt_io_addr[ctrl] <= 0)
+			continue;
+
+		/*  Get a ptr to the board's control struct */
+		ctlp = sCtlNumToCtlPtr(ctrl);
+
+		/*  Get the interrupt status from the board */
+#ifdef CONFIG_PCI
+		if (ctlp->BusType == isPCI)
+			CtlMask = sPCIGetControllerIntStatus(ctlp);
+		else
+#endif
+			CtlMask = sGetControllerIntStatus(ctlp);
+
+		/*  Check if any AIOP read bits are set */
+		for (aiop = 0; CtlMask; aiop++) {
+			bit = ctlp->AiopIntrBits[aiop];
+			if (CtlMask & bit) {
+				CtlMask &= ~bit;
+				AiopMask = sGetAiopIntStatus(ctlp, aiop);
+
+				/*  Check if any port read bits are set */
+				for (ch = 0; AiopMask;  AiopMask >>= 1, ch++) {
+					if (AiopMask & 1) {
+
+						/*  Get the line number (/dev/ttyRx number). */
+						/*  Read the data from the port. */
+						line = GetLineNumber(ctrl, aiop, ch);
+						rp_handle_port(rp_table[line]);
+					}
+				}
+			}
+		}
+
+		xmitmask = xmit_flags[ctrl];
+
+		/*
+		 *  xmit_flags contains bit-significant flags, indicating there is data
+		 *  to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port 
+		 *  1, ... (32 total possible).  The variable i has the aiop and ch 
+		 *  numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
+		 */
+		if (xmitmask) {
+			for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
+				if (xmitmask & (1 << i)) {
+					aiop = (i & 0x18) >> 3;
+					ch = i & 0x07;
+					line = GetLineNumber(ctrl, aiop, ch);
+					rp_do_transmit(rp_table[line]);
+				}
+			}
+		}
+	}
+
+	/*
+	 * Reset the timer so we get called at the next clock tick (10ms).
+	 */
+	if (atomic_read(&rp_num_ports_open))
+		mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
+}
+
+/*
+ *  Initializes the r_port structure for a port, as well as enabling the port on 
+ *  the board.  
+ *  Inputs:  board, aiop, chan numbers
+ */
+static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
+{
+	unsigned rocketMode;
+	struct r_port *info;
+	int line;
+	CONTROLLER_T *ctlp;
+
+	/*  Get the next available line number */
+	line = SetLineNumber(board, aiop, chan);
+
+	ctlp = sCtlNumToCtlPtr(board);
+
+	/*  Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
+	info = kzalloc(sizeof (struct r_port), GFP_KERNEL);
+	if (!info) {
+		printk(KERN_ERR "Couldn't allocate info struct for line #%d\n",
+				line);
+		return;
+	}
+
+	info->magic = RPORT_MAGIC;
+	info->line = line;
+	info->ctlp = ctlp;
+	info->board = board;
+	info->aiop = aiop;
+	info->chan = chan;
+	tty_port_init(&info->port);
+	info->port.ops = &rocket_port_ops;
+	init_completion(&info->close_wait);
+	info->flags &= ~ROCKET_MODE_MASK;
+	switch (pc104[board][line]) {
+	case 422:
+		info->flags |= ROCKET_MODE_RS422;
+		break;
+	case 485:
+		info->flags |= ROCKET_MODE_RS485;
+		break;
+	case 232:
+	default:
+		info->flags |= ROCKET_MODE_RS232;
+		break;
+	}
+
+	info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
+	if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
+		printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
+				board, aiop, chan);
+		kfree(info);
+		return;
+	}
+
+	rocketMode = info->flags & ROCKET_MODE_MASK;
+
+	if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
+		sEnRTSToggle(&info->channel);
+	else
+		sDisRTSToggle(&info->channel);
+
+	if (ctlp->boardType == ROCKET_TYPE_PC104) {
+		switch (rocketMode) {
+		case ROCKET_MODE_RS485:
+			sSetInterfaceMode(&info->channel, InterfaceModeRS485);
+			break;
+		case ROCKET_MODE_RS422:
+			sSetInterfaceMode(&info->channel, InterfaceModeRS422);
+			break;
+		case ROCKET_MODE_RS232:
+		default:
+			if (info->flags & ROCKET_RTS_TOGGLE)
+				sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
+			else
+				sSetInterfaceMode(&info->channel, InterfaceModeRS232);
+			break;
+		}
+	}
+	spin_lock_init(&info->slock);
+	mutex_init(&info->write_mtx);
+	rp_table[line] = info;
+	tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
+			NULL);
+}
+
+/*
+ *  Configures a rocketport port according to its termio settings.  Called from 
+ *  user mode into the driver (exception handler).  *info CD manipulation is spinlock protected.
+ */
+static void configure_r_port(struct tty_struct *tty, struct r_port *info,
+			     struct ktermios *old_termios)
+{
+	unsigned cflag;
+	unsigned long flags;
+	unsigned rocketMode;
+	int bits, baud, divisor;
+	CHANNEL_t *cp;
+	struct ktermios *t = tty->termios;
+
+	cp = &info->channel;
+	cflag = t->c_cflag;
+
+	/* Byte size and parity */
+	if ((cflag & CSIZE) == CS8) {
+		sSetData8(cp);
+		bits = 10;
+	} else {
+		sSetData7(cp);
+		bits = 9;
+	}
+	if (cflag & CSTOPB) {
+		sSetStop2(cp);
+		bits++;
+	} else {
+		sSetStop1(cp);
+	}
+
+	if (cflag & PARENB) {
+		sEnParity(cp);
+		bits++;
+		if (cflag & PARODD) {
+			sSetOddParity(cp);
+		} else {
+			sSetEvenParity(cp);
+		}
+	} else {
+		sDisParity(cp);
+	}
+
+	/* baud rate */
+	baud = tty_get_baud_rate(tty);
+	if (!baud)
+		baud = 9600;
+	divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
+	if ((divisor >= 8192 || divisor < 0) && old_termios) {
+		baud = tty_termios_baud_rate(old_termios);
+		if (!baud)
+			baud = 9600;
+		divisor = (rp_baud_base[info->board] / baud) - 1;
+	}
+	if (divisor >= 8192 || divisor < 0) {
+		baud = 9600;
+		divisor = (rp_baud_base[info->board] / baud) - 1;
+	}
+	info->cps = baud / bits;
+	sSetBaud(cp, divisor);
+
+	/* FIXME: Should really back compute a baud rate from the divisor */
+	tty_encode_baud_rate(tty, baud, baud);
+
+	if (cflag & CRTSCTS) {
+		info->intmask |= DELTA_CTS;
+		sEnCTSFlowCtl(cp);
+	} else {
+		info->intmask &= ~DELTA_CTS;
+		sDisCTSFlowCtl(cp);
+	}
+	if (cflag & CLOCAL) {
+		info->intmask &= ~DELTA_CD;
+	} else {
+		spin_lock_irqsave(&info->slock, flags);
+		if (sGetChanStatus(cp) & CD_ACT)
+			info->cd_status = 1;
+		else
+			info->cd_status = 0;
+		info->intmask |= DELTA_CD;
+		spin_unlock_irqrestore(&info->slock, flags);
+	}
+
+	/*
+	 * Handle software flow control in the board
+	 */
+#ifdef ROCKET_SOFT_FLOW
+	if (I_IXON(tty)) {
+		sEnTxSoftFlowCtl(cp);
+		if (I_IXANY(tty)) {
+			sEnIXANY(cp);
+		} else {
+			sDisIXANY(cp);
+		}
+		sSetTxXONChar(cp, START_CHAR(tty));
+		sSetTxXOFFChar(cp, STOP_CHAR(tty));
+	} else {
+		sDisTxSoftFlowCtl(cp);
+		sDisIXANY(cp);
+		sClrTxXOFF(cp);
+	}
+#endif
+
+	/*
+	 * Set up ignore/read mask words
+	 */
+	info->read_status_mask = STMRCVROVRH | 0xFF;
+	if (I_INPCK(tty))
+		info->read_status_mask |= STMFRAMEH | STMPARITYH;
+	if (I_BRKINT(tty) || I_PARMRK(tty))
+		info->read_status_mask |= STMBREAKH;
+
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(tty))
+		info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
+	if (I_IGNBRK(tty)) {
+		info->ignore_status_mask |= STMBREAKH;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(tty))
+			info->ignore_status_mask |= STMRCVROVRH;
+	}
+
+	rocketMode = info->flags & ROCKET_MODE_MASK;
+
+	if ((info->flags & ROCKET_RTS_TOGGLE)
+	    || (rocketMode == ROCKET_MODE_RS485))
+		sEnRTSToggle(cp);
+	else
+		sDisRTSToggle(cp);
+
+	sSetRTS(&info->channel);
+
+	if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
+		switch (rocketMode) {
+		case ROCKET_MODE_RS485:
+			sSetInterfaceMode(cp, InterfaceModeRS485);
+			break;
+		case ROCKET_MODE_RS422:
+			sSetInterfaceMode(cp, InterfaceModeRS422);
+			break;
+		case ROCKET_MODE_RS232:
+		default:
+			if (info->flags & ROCKET_RTS_TOGGLE)
+				sSetInterfaceMode(cp, InterfaceModeRS232T);
+			else
+				sSetInterfaceMode(cp, InterfaceModeRS232);
+			break;
+		}
+	}
+}
+
+static int carrier_raised(struct tty_port *port)
+{
+	struct r_port *info = container_of(port, struct r_port, port);
+	return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
+}
+
+static void dtr_rts(struct tty_port *port, int on)
+{
+	struct r_port *info = container_of(port, struct r_port, port);
+	if (on) {
+		sSetDTR(&info->channel);
+		sSetRTS(&info->channel);
+	} else {
+		sClrDTR(&info->channel);
+		sClrRTS(&info->channel);
+	}
+}
+
+/*
+ *  Exception handler that opens a serial port.  Creates xmit_buf storage, fills in 
+ *  port's r_port struct.  Initializes the port hardware.  
+ */
+static int rp_open(struct tty_struct *tty, struct file *filp)
+{
+	struct r_port *info;
+	struct tty_port *port;
+	int line = 0, retval;
+	CHANNEL_t *cp;
+	unsigned long page;
+
+	line = tty->index;
+	if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL))
+		return -ENXIO;
+	port = &info->port;
+	
+	page = __get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	if (port->flags & ASYNC_CLOSING) {
+		retval = wait_for_completion_interruptible(&info->close_wait);
+		free_page(page);
+		if (retval)
+			return retval;
+		return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
+	}
+
+	/*
+	 * We must not sleep from here until the port is marked fully in use.
+	 */
+	if (info->xmit_buf)
+		free_page(page);
+	else
+		info->xmit_buf = (unsigned char *) page;
+
+	tty->driver_data = info;
+	tty_port_tty_set(port, tty);
+
+	if (port->count++ == 0) {
+		atomic_inc(&rp_num_ports_open);
+
+#ifdef ROCKET_DEBUG_OPEN
+		printk(KERN_INFO "rocket mod++ = %d...\n",
+				atomic_read(&rp_num_ports_open));
+#endif
+	}
+#ifdef ROCKET_DEBUG_OPEN
+	printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count);
+#endif
+
+	/*
+	 * Info->count is now 1; so it's safe to sleep now.
+	 */
+	if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
+		cp = &info->channel;
+		sSetRxTrigger(cp, TRIG_1);
+		if (sGetChanStatus(cp) & CD_ACT)
+			info->cd_status = 1;
+		else
+			info->cd_status = 0;
+		sDisRxStatusMode(cp);
+		sFlushRxFIFO(cp);
+		sFlushTxFIFO(cp);
+
+		sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
+		sSetRxTrigger(cp, TRIG_1);
+
+		sGetChanStatus(cp);
+		sDisRxStatusMode(cp);
+		sClrTxXOFF(cp);
+
+		sDisCTSFlowCtl(cp);
+		sDisTxSoftFlowCtl(cp);
+
+		sEnRxFIFO(cp);
+		sEnTransmit(cp);
+
+		set_bit(ASYNCB_INITIALIZED, &info->port.flags);
+
+		/*
+		 * Set up the tty->alt_speed kludge
+		 */
+		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
+			tty->alt_speed = 57600;
+		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
+			tty->alt_speed = 115200;
+		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
+			tty->alt_speed = 230400;
+		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
+			tty->alt_speed = 460800;
+
+		configure_r_port(tty, info, NULL);
+		if (tty->termios->c_cflag & CBAUD) {
+			sSetDTR(cp);
+			sSetRTS(cp);
+		}
+	}
+	/*  Starts (or resets) the maint polling loop */
+	mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
+
+	retval = tty_port_block_til_ready(port, tty, filp);
+	if (retval) {
+#ifdef ROCKET_DEBUG_OPEN
+		printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
+#endif
+		return retval;
+	}
+	return 0;
+}
+
+/*
+ *  Exception handler that closes a serial port. info->port.count is considered critical.
+ */
+static void rp_close(struct tty_struct *tty, struct file *filp)
+{
+	struct r_port *info = tty->driver_data;
+	struct tty_port *port = &info->port;
+	int timeout;
+	CHANNEL_t *cp;
+	
+	if (rocket_paranoia_check(info, "rp_close"))
+		return;
+
+#ifdef ROCKET_DEBUG_OPEN
+	printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count);
+#endif
+
+	if (tty_port_close_start(port, tty, filp) == 0)
+		return;
+
+	mutex_lock(&port->mutex);
+	cp = &info->channel;
+	/*
+	 * Before we drop DTR, make sure the UART transmitter
+	 * has completely drained; this is especially
+	 * important if there is a transmit FIFO!
+	 */
+	timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
+	if (timeout == 0)
+		timeout = 1;
+	rp_wait_until_sent(tty, timeout);
+	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
+	sDisTransmit(cp);
+	sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
+	sDisCTSFlowCtl(cp);
+	sDisTxSoftFlowCtl(cp);
+	sClrTxXOFF(cp);
+	sFlushRxFIFO(cp);
+	sFlushTxFIFO(cp);
+	sClrRTS(cp);
+	if (C_HUPCL(tty))
+		sClrDTR(cp);
+
+	rp_flush_buffer(tty);
+		
+	tty_ldisc_flush(tty);
+
+	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+
+	/* We can't yet use tty_port_close_end as the buffer handling in this
+	   driver is a bit different to the usual */
+
+	if (port->blocked_open) {
+		if (port->close_delay) {
+			msleep_interruptible(jiffies_to_msecs(port->close_delay));
+		}
+		wake_up_interruptible(&port->open_wait);
+	} else {
+		if (info->xmit_buf) {
+			free_page((unsigned long) info->xmit_buf);
+			info->xmit_buf = NULL;
+		}
+	}
+	spin_lock_irq(&port->lock);
+	info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE);
+	tty->closing = 0;
+	spin_unlock_irq(&port->lock);
+	mutex_unlock(&port->mutex);
+	tty_port_tty_set(port, NULL);
+
+	wake_up_interruptible(&port->close_wait);
+	complete_all(&info->close_wait);
+	atomic_dec(&rp_num_ports_open);
+
+#ifdef ROCKET_DEBUG_OPEN
+	printk(KERN_INFO "rocket mod-- = %d...\n",
+			atomic_read(&rp_num_ports_open));
+	printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
+#endif
+
+}
+
+static void rp_set_termios(struct tty_struct *tty,
+			   struct ktermios *old_termios)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+	unsigned cflag;
+
+	if (rocket_paranoia_check(info, "rp_set_termios"))
+		return;
+
+	cflag = tty->termios->c_cflag;
+
+	/*
+	 * This driver doesn't support CS5 or CS6
+	 */
+	if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
+		tty->termios->c_cflag =
+		    ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
+	/* Or CMSPAR */
+	tty->termios->c_cflag &= ~CMSPAR;
+
+	configure_r_port(tty, info, old_termios);
+
+	cp = &info->channel;
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
+		sClrDTR(cp);
+		sClrRTS(cp);
+	}
+
+	/* 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);
+		sSetDTR(cp);
+	}
+
+	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rp_start(tty);
+	}
+}
+
+static int rp_break(struct tty_struct *tty, int break_state)
+{
+	struct r_port *info = tty->driver_data;
+	unsigned long flags;
+
+	if (rocket_paranoia_check(info, "rp_break"))
+		return -EINVAL;
+
+	spin_lock_irqsave(&info->slock, flags);
+	if (break_state == -1)
+		sSendBreak(&info->channel);
+	else
+		sClrBreak(&info->channel);
+	spin_unlock_irqrestore(&info->slock, flags);
+	return 0;
+}
+
+/*
+ * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
+ * the UPCI boards was added, it was decided to make this a function because
+ * the macro was getting too complicated. All cases except the first one
+ * (UPCIRingInd) are taken directly from the original macro.
+ */
+static int sGetChanRI(CHANNEL_T * ChP)
+{
+	CONTROLLER_t *CtlP = ChP->CtlP;
+	int ChanNum = ChP->ChanNum;
+	int RingInd = 0;
+
+	if (CtlP->UPCIRingInd)
+		RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
+	else if (CtlP->AltChanRingIndicator)
+		RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
+	else if (CtlP->boardType == ROCKET_TYPE_PC104)
+		RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
+
+	return RingInd;
+}
+
+/********************************************************************************************/
+/*  Here are the routines used by rp_ioctl.  These are all called from exception handlers.  */
+
+/*
+ *  Returns the state of the serial modem control lines.  These next 2 functions 
+ *  are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
+ */
+static int rp_tiocmget(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+	unsigned int control, result, ChanStatus;
+
+	ChanStatus = sGetChanStatusLo(&info->channel);
+	control = info->channel.TxControl[3];
+	result = ((control & SET_RTS) ? TIOCM_RTS : 0) | 
+		((control & SET_DTR) ?  TIOCM_DTR : 0) |
+		((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
+		(sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
+		((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
+		((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
+
+	return result;
+}
+
+/* 
+ *  Sets the modem control lines
+ */
+static int rp_tiocmset(struct tty_struct *tty,
+				unsigned int set, unsigned int clear)
+{
+	struct r_port *info = tty->driver_data;
+
+	if (set & TIOCM_RTS)
+		info->channel.TxControl[3] |= SET_RTS;
+	if (set & TIOCM_DTR)
+		info->channel.TxControl[3] |= SET_DTR;
+	if (clear & TIOCM_RTS)
+		info->channel.TxControl[3] &= ~SET_RTS;
+	if (clear & TIOCM_DTR)
+		info->channel.TxControl[3] &= ~SET_DTR;
+
+	out32(info->channel.IndexAddr, info->channel.TxControl);
+	return 0;
+}
+
+static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
+{
+	struct rocket_config tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof (tmp));
+	mutex_lock(&info->port.mutex);
+	tmp.line = info->line;
+	tmp.flags = info->flags;
+	tmp.close_delay = info->port.close_delay;
+	tmp.closing_wait = info->port.closing_wait;
+	tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
+	mutex_unlock(&info->port.mutex);
+
+	if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_config(struct tty_struct *tty, struct r_port *info,
+					struct rocket_config __user *new_info)
+{
+	struct rocket_config new_serial;
+
+	if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
+		return -EFAULT;
+
+	mutex_lock(&info->port.mutex);
+	if (!capable(CAP_SYS_ADMIN))
+	{
+		if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) {
+			mutex_unlock(&info->port.mutex);
+			return -EPERM;
+		}
+		info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
+		configure_r_port(tty, info, NULL);
+		mutex_unlock(&info->port.mutex);
+		return 0;
+	}
+
+	info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
+	info->port.close_delay = new_serial.close_delay;
+	info->port.closing_wait = new_serial.closing_wait;
+
+	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
+		tty->alt_speed = 57600;
+	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
+		tty->alt_speed = 115200;
+	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
+		tty->alt_speed = 230400;
+	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
+		tty->alt_speed = 460800;
+	mutex_unlock(&info->port.mutex);
+
+	configure_r_port(tty, info, NULL);
+	return 0;
+}
+
+/*
+ *  This function fills in a rocket_ports struct with information
+ *  about what boards/ports are in the system.  This info is passed
+ *  to user space.  See setrocket.c where the info is used to create
+ *  the /dev/ttyRx ports.
+ */
+static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
+{
+	struct rocket_ports tmp;
+	int board;
+
+	if (!retports)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof (tmp));
+	tmp.tty_major = rocket_driver->major;
+
+	for (board = 0; board < 4; board++) {
+		tmp.rocketModel[board].model = rocketModel[board].model;
+		strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
+		tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
+		tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
+		tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
+	}
+	if (copy_to_user(retports, &tmp, sizeof (*retports)))
+		return -EFAULT;
+	return 0;
+}
+
+static int reset_rm2(struct r_port *info, void __user *arg)
+{
+	int reset;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (copy_from_user(&reset, arg, sizeof (int)))
+		return -EFAULT;
+	if (reset)
+		reset = 1;
+
+	if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
+            rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
+		return -EINVAL;
+
+	if (info->ctlp->BusType == isISA)
+		sModemReset(info->ctlp, info->chan, reset);
+	else
+		sPCIModemReset(info->ctlp, info->chan, reset);
+
+	return 0;
+}
+
+static int get_version(struct r_port *info, struct rocket_version __user *retvers)
+{
+	if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
+		return -EFAULT;
+	return 0;
+}
+
+/*  IOCTL call handler into the driver */
+static int rp_ioctl(struct tty_struct *tty,
+		    unsigned int cmd, unsigned long arg)
+{
+	struct r_port *info = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+	int ret = 0;
+
+	if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
+		return -ENXIO;
+
+	switch (cmd) {
+	case RCKP_GET_STRUCT:
+		if (copy_to_user(argp, info, sizeof (struct r_port)))
+			ret = -EFAULT;
+		break;
+	case RCKP_GET_CONFIG:
+		ret = get_config(info, argp);
+		break;
+	case RCKP_SET_CONFIG:
+		ret = set_config(tty, info, argp);
+		break;
+	case RCKP_GET_PORTS:
+		ret = get_ports(info, argp);
+		break;
+	case RCKP_RESET_RM2:
+		ret = reset_rm2(info, argp);
+		break;
+	case RCKP_GET_VERSION:
+		ret = get_version(info, argp);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static void rp_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+
+	if (rocket_paranoia_check(info, "rp_send_xchar"))
+		return;
+
+	cp = &info->channel;
+	if (sGetTxCnt(cp))
+		sWriteTxPrioByte(cp, ch);
+	else
+		sWriteTxByte(sGetTxRxDataIO(cp), ch);
+}
+
+static void rp_throttle(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+
+#ifdef ROCKET_DEBUG_THROTTLE
+	printk(KERN_INFO "throttle %s: %d....\n", tty->name,
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (rocket_paranoia_check(info, "rp_throttle"))
+		return;
+
+	cp = &info->channel;
+	if (I_IXOFF(tty))
+		rp_send_xchar(tty, STOP_CHAR(tty));
+
+	sClrRTS(&info->channel);
+}
+
+static void rp_unthrottle(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+#ifdef ROCKET_DEBUG_THROTTLE
+	printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (rocket_paranoia_check(info, "rp_throttle"))
+		return;
+
+	cp = &info->channel;
+	if (I_IXOFF(tty))
+		rp_send_xchar(tty, START_CHAR(tty));
+
+	sSetRTS(&info->channel);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rp_stop() and rp_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void rp_stop(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+
+#ifdef ROCKET_DEBUG_FLOW
+	printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
+	       info->xmit_cnt, info->xmit_fifo_room);
+#endif
+
+	if (rocket_paranoia_check(info, "rp_stop"))
+		return;
+
+	if (sGetTxCnt(&info->channel))
+		sDisTransmit(&info->channel);
+}
+
+static void rp_start(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+
+#ifdef ROCKET_DEBUG_FLOW
+	printk(KERN_INFO "start %s: %d %d....\n", tty->name,
+	       info->xmit_cnt, info->xmit_fifo_room);
+#endif
+
+	if (rocket_paranoia_check(info, "rp_stop"))
+		return;
+
+	sEnTransmit(&info->channel);
+	set_bit((info->aiop * 8) + info->chan,
+		(void *) &xmit_flags[info->board]);
+}
+
+/*
+ * rp_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+	unsigned long orig_jiffies;
+	int check_time, exit_time;
+	int txcnt;
+
+	if (rocket_paranoia_check(info, "rp_wait_until_sent"))
+		return;
+
+	cp = &info->channel;
+
+	orig_jiffies = jiffies;
+#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
+	printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout,
+	       jiffies);
+	printk(KERN_INFO "cps=%d...\n", info->cps);
+#endif
+	while (1) {
+		txcnt = sGetTxCnt(cp);
+		if (!txcnt) {
+			if (sGetChanStatusLo(cp) & TXSHRMT)
+				break;
+			check_time = (HZ / info->cps) / 5;
+		} else {
+			check_time = HZ * txcnt / info->cps;
+		}
+		if (timeout) {
+			exit_time = orig_jiffies + timeout - jiffies;
+			if (exit_time <= 0)
+				break;
+			if (exit_time < check_time)
+				check_time = exit_time;
+		}
+		if (check_time == 0)
+			check_time = 1;
+#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
+		printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt,
+				jiffies, check_time);
+#endif
+		msleep_interruptible(jiffies_to_msecs(check_time));
+		if (signal_pending(current))
+			break;
+	}
+	__set_current_state(TASK_RUNNING);
+#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
+	printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
+#endif
+}
+
+/*
+ * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void rp_hangup(struct tty_struct *tty)
+{
+	CHANNEL_t *cp;
+	struct r_port *info = tty->driver_data;
+	unsigned long flags;
+
+	if (rocket_paranoia_check(info, "rp_hangup"))
+		return;
+
+#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
+	printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
+#endif
+	rp_flush_buffer(tty);
+	spin_lock_irqsave(&info->port.lock, flags);
+	if (info->port.flags & ASYNC_CLOSING) {
+		spin_unlock_irqrestore(&info->port.lock, flags);
+		return;
+	}
+	if (info->port.count)
+		atomic_dec(&rp_num_ports_open);
+	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+	spin_unlock_irqrestore(&info->port.lock, flags);
+
+	tty_port_hangup(&info->port);
+
+	cp = &info->channel;
+	sDisRxFIFO(cp);
+	sDisTransmit(cp);
+	sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
+	sDisCTSFlowCtl(cp);
+	sDisTxSoftFlowCtl(cp);
+	sClrTxXOFF(cp);
+	clear_bit(ASYNCB_INITIALIZED, &info->port.flags);
+
+	wake_up_interruptible(&info->port.open_wait);
+}
+
+/*
+ *  Exception handler - write char routine.  The RocketPort driver uses a
+ *  double-buffering strategy, with the twist that if the in-memory CPU
+ *  buffer is empty, and there's space in the transmit FIFO, the
+ *  writing routines will write directly to transmit FIFO.
+ *  Write buffer and counters protected by spinlocks
+ */
+static int rp_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+	unsigned long flags;
+
+	if (rocket_paranoia_check(info, "rp_put_char"))
+		return 0;
+
+	/*
+	 * Grab the port write mutex, locking out other processes that try to
+	 * write to this port
+	 */
+	mutex_lock(&info->write_mtx);
+
+#ifdef ROCKET_DEBUG_WRITE
+	printk(KERN_INFO "rp_put_char %c...\n", ch);
+#endif
+
+	spin_lock_irqsave(&info->slock, flags);
+	cp = &info->channel;
+
+	if (!tty->stopped && !tty->hw_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) {
+		info->xmit_buf[info->xmit_head++] = ch;
+		info->xmit_head &= XMIT_BUF_SIZE - 1;
+		info->xmit_cnt++;
+		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+	} else {
+		sOutB(sGetTxRxDataIO(cp), ch);
+		info->xmit_fifo_room--;
+	}
+	spin_unlock_irqrestore(&info->slock, flags);
+	mutex_unlock(&info->write_mtx);
+	return 1;
+}
+
+/*
+ *  Exception handler - write routine, called when user app writes to the device.
+ *  A per port write mutex is used to protect from another process writing to
+ *  this port at the same time.  This other process could be running on the other CPU
+ *  or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). 
+ *  Spinlocks protect the info xmit members.
+ */
+static int rp_write(struct tty_struct *tty,
+		    const unsigned char *buf, int count)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+	const unsigned char *b;
+	int c, retval = 0;
+	unsigned long flags;
+
+	if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
+		return 0;
+
+	if (mutex_lock_interruptible(&info->write_mtx))
+		return -ERESTARTSYS;
+
+#ifdef ROCKET_DEBUG_WRITE
+	printk(KERN_INFO "rp_write %d chars...\n", count);
+#endif
+	cp = &info->channel;
+
+	if (!tty->stopped && !tty->hw_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) {
+		c = min(count, info->xmit_fifo_room);
+		b = buf;
+
+		/*  Push data into FIFO, 2 bytes at a time */
+		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
+
+		/*  If there is a byte remaining, write it */
+		if (c & 1)
+			sOutB(sGetTxRxDataIO(cp), b[c - 1]);
+
+		retval += c;
+		buf += c;
+		count -= c;
+
+		spin_lock_irqsave(&info->slock, flags);
+		info->xmit_fifo_room -= c;
+		spin_unlock_irqrestore(&info->slock, flags);
+	}
+
+	/* If count is zero, we wrote it all and are done */
+	if (!count)
+		goto end;
+
+	/*  Write remaining data into the port's xmit_buf */
+	while (1) {
+		/* Hung up ? */
+		if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags))
+			goto end;
+		c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
+		c = min(c, XMIT_BUF_SIZE - info->xmit_head);
+		if (c <= 0)
+			break;
+
+		b = buf;
+		memcpy(info->xmit_buf + info->xmit_head, b, c);
+
+		spin_lock_irqsave(&info->slock, flags);
+		info->xmit_head =
+		    (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
+		info->xmit_cnt += c;
+		spin_unlock_irqrestore(&info->slock, flags);
+
+		buf += c;
+		count -= c;
+		retval += c;
+	}
+
+	if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
+		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
+	
+end:
+ 	if (info->xmit_cnt < WAKEUP_CHARS) {
+ 		tty_wakeup(tty);
+#ifdef ROCKETPORT_HAVE_POLL_WAIT
+		wake_up_interruptible(&tty->poll_wait);
+#endif
+	}
+	mutex_unlock(&info->write_mtx);
+	return retval;
+}
+
+/*
+ * Return the number of characters that can be sent.  We estimate
+ * only using the in-memory transmit buffer only, and ignore the
+ * potential space in the transmit FIFO.
+ */
+static int rp_write_room(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+	int ret;
+
+	if (rocket_paranoia_check(info, "rp_write_room"))
+		return 0;
+
+	ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+#ifdef ROCKET_DEBUG_WRITE
+	printk(KERN_INFO "rp_write_room returns %d...\n", ret);
+#endif
+	return ret;
+}
+
+/*
+ * Return the number of characters in the buffer.  Again, this only
+ * counts those characters in the in-memory transmit buffer.
+ */
+static int rp_chars_in_buffer(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+
+	if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
+		return 0;
+
+	cp = &info->channel;
+
+#ifdef ROCKET_DEBUG_WRITE
+	printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
+#endif
+	return info->xmit_cnt;
+}
+
+/*
+ *  Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
+ *  r_port struct for the port.  Note that spinlock are used to protect info members,
+ *  do not call this function if the spinlock is already held.
+ */
+static void rp_flush_buffer(struct tty_struct *tty)
+{
+	struct r_port *info = tty->driver_data;
+	CHANNEL_t *cp;
+	unsigned long flags;
+
+	if (rocket_paranoia_check(info, "rp_flush_buffer"))
+		return;
+
+	spin_lock_irqsave(&info->slock, flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	spin_unlock_irqrestore(&info->slock, flags);
+
+#ifdef ROCKETPORT_HAVE_POLL_WAIT
+	wake_up_interruptible(&tty->poll_wait);
+#endif
+	tty_wakeup(tty);
+
+	cp = &info->channel;
+	sFlushTxFIFO(cp);
+}
+
+#ifdef CONFIG_PCI
+
+static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
+
+/*
+ *  Called when a PCI card is found.  Retrieves and stores model information,
+ *  init's aiopic and serial port hardware.
+ *  Inputs:  i is the board number (0-n)
+ */
+static __init int register_PCI(int i, struct pci_dev *dev)
+{
+	int num_aiops, aiop, max_num_aiops, num_chan, chan;
+	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
+	char *str, *board_type;
+	CONTROLLER_t *ctlp;
+
+	int fast_clock = 0;
+	int altChanRingIndicator = 0;
+	int ports_per_aiop = 8;
+	WordIO_t ConfigIO = 0;
+	ByteIO_t UPCIRingInd = 0;
+
+	if (!dev || pci_enable_device(dev))
+		return 0;
+
+	rcktpt_io_addr[i] = pci_resource_start(dev, 0);
+
+	rcktpt_type[i] = ROCKET_TYPE_NORMAL;
+	rocketModel[i].loadrm2 = 0;
+	rocketModel[i].startingPortNumber = nextLineNumber;
+
+	/*  Depending on the model, set up some config variables */
+	switch (dev->device) {
+	case PCI_DEVICE_ID_RP4QUAD:
+		str = "Quadcable";
+		max_num_aiops = 1;
+		ports_per_aiop = 4;
+		rocketModel[i].model = MODEL_RP4QUAD;
+		strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
+		rocketModel[i].numPorts = 4;
+		break;
+	case PCI_DEVICE_ID_RP8OCTA:
+		str = "Octacable";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_RP8OCTA;
+		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_URP8OCTA:
+		str = "Octacable";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_UPCI_RP8OCTA;
+		strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_RP8INTF:
+		str = "8";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_RP8INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_URP8INTF:
+		str = "8";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_UPCI_RP8INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_RP8J:
+		str = "8J";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_RP8J;
+		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_RP4J:
+		str = "4J";
+		max_num_aiops = 1;
+		ports_per_aiop = 4;
+		rocketModel[i].model = MODEL_RP4J;
+		strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
+		rocketModel[i].numPorts = 4;
+		break;
+	case PCI_DEVICE_ID_RP8SNI:
+		str = "8 (DB78 Custom)";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_RP8SNI;
+		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_RP16SNI:
+		str = "16 (DB78 Custom)";
+		max_num_aiops = 2;
+		rocketModel[i].model = MODEL_RP16SNI;
+		strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
+		rocketModel[i].numPorts = 16;
+		break;
+	case PCI_DEVICE_ID_RP16INTF:
+		str = "16";
+		max_num_aiops = 2;
+		rocketModel[i].model = MODEL_RP16INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
+		rocketModel[i].numPorts = 16;
+		break;
+	case PCI_DEVICE_ID_URP16INTF:
+		str = "16";
+		max_num_aiops = 2;
+		rocketModel[i].model = MODEL_UPCI_RP16INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
+		rocketModel[i].numPorts = 16;
+		break;
+	case PCI_DEVICE_ID_CRP16INTF:
+		str = "16";
+		max_num_aiops = 2;
+		rocketModel[i].model = MODEL_CPCI_RP16INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
+		rocketModel[i].numPorts = 16;
+		break;
+	case PCI_DEVICE_ID_RP32INTF:
+		str = "32";
+		max_num_aiops = 4;
+		rocketModel[i].model = MODEL_RP32INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
+		rocketModel[i].numPorts = 32;
+		break;
+	case PCI_DEVICE_ID_URP32INTF:
+		str = "32";
+		max_num_aiops = 4;
+		rocketModel[i].model = MODEL_UPCI_RP32INTF;
+		strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
+		rocketModel[i].numPorts = 32;
+		break;
+	case PCI_DEVICE_ID_RPP4:
+		str = "Plus Quadcable";
+		max_num_aiops = 1;
+		ports_per_aiop = 4;
+		altChanRingIndicator++;
+		fast_clock++;
+		rocketModel[i].model = MODEL_RPP4;
+		strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
+		rocketModel[i].numPorts = 4;
+		break;
+	case PCI_DEVICE_ID_RPP8:
+		str = "Plus Octacable";
+		max_num_aiops = 2;
+		ports_per_aiop = 4;
+		altChanRingIndicator++;
+		fast_clock++;
+		rocketModel[i].model = MODEL_RPP8;
+		strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
+		rocketModel[i].numPorts = 8;
+		break;
+	case PCI_DEVICE_ID_RP2_232:
+		str = "Plus 2 (RS-232)";
+		max_num_aiops = 1;
+		ports_per_aiop = 2;
+		altChanRingIndicator++;
+		fast_clock++;
+		rocketModel[i].model = MODEL_RP2_232;
+		strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
+		rocketModel[i].numPorts = 2;
+		break;
+	case PCI_DEVICE_ID_RP2_422:
+		str = "Plus 2 (RS-422)";
+		max_num_aiops = 1;
+		ports_per_aiop = 2;
+		altChanRingIndicator++;
+		fast_clock++;
+		rocketModel[i].model = MODEL_RP2_422;
+		strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
+		rocketModel[i].numPorts = 2;
+		break;
+	case PCI_DEVICE_ID_RP6M:
+
+		max_num_aiops = 1;
+		ports_per_aiop = 6;
+		str = "6-port";
+
+		/*  If revision is 1, the rocketmodem flash must be loaded.
+		 *  If it is 2 it is a "socketed" version. */
+		if (dev->revision == 1) {
+			rcktpt_type[i] = ROCKET_TYPE_MODEMII;
+			rocketModel[i].loadrm2 = 1;
+		} else {
+			rcktpt_type[i] = ROCKET_TYPE_MODEM;
+		}
+
+		rocketModel[i].model = MODEL_RP6M;
+		strcpy(rocketModel[i].modelString, "RocketModem 6 port");
+		rocketModel[i].numPorts = 6;
+		break;
+	case PCI_DEVICE_ID_RP4M:
+		max_num_aiops = 1;
+		ports_per_aiop = 4;
+		str = "4-port";
+		if (dev->revision == 1) {
+			rcktpt_type[i] = ROCKET_TYPE_MODEMII;
+			rocketModel[i].loadrm2 = 1;
+		} else {
+			rcktpt_type[i] = ROCKET_TYPE_MODEM;
+		}
+
+		rocketModel[i].model = MODEL_RP4M;
+		strcpy(rocketModel[i].modelString, "RocketModem 4 port");
+		rocketModel[i].numPorts = 4;
+		break;
+	default:
+		str = "(unknown/unsupported)";
+		max_num_aiops = 0;
+		break;
+	}
+
+	/*
+	 * Check for UPCI boards.
+	 */
+
+	switch (dev->device) {
+	case PCI_DEVICE_ID_URP32INTF:
+	case PCI_DEVICE_ID_URP8INTF:
+	case PCI_DEVICE_ID_URP16INTF:
+	case PCI_DEVICE_ID_CRP16INTF:
+	case PCI_DEVICE_ID_URP8OCTA:
+		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
+		ConfigIO = pci_resource_start(dev, 1);
+		if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
+			UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
+
+			/*
+			 * Check for octa or quad cable.
+			 */
+			if (!
+			    (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
+			     PCI_GPIO_CTRL_8PORT)) {
+				str = "Quadcable";
+				ports_per_aiop = 4;
+				rocketModel[i].numPorts = 4;
+			}
+		}
+		break;
+	case PCI_DEVICE_ID_UPCI_RM3_8PORT:
+		str = "8 ports";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
+		strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
+		rocketModel[i].numPorts = 8;
+		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
+		UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
+		ConfigIO = pci_resource_start(dev, 1);
+		rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
+		break;
+	case PCI_DEVICE_ID_UPCI_RM3_4PORT:
+		str = "4 ports";
+		max_num_aiops = 1;
+		rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
+		strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
+		rocketModel[i].numPorts = 4;
+		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
+		UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
+		ConfigIO = pci_resource_start(dev, 1);
+		rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
+		break;
+	default:
+		break;
+	}
+
+	switch (rcktpt_type[i]) {
+	case ROCKET_TYPE_MODEM:
+		board_type = "RocketModem";
+		break;
+	case ROCKET_TYPE_MODEMII:
+		board_type = "RocketModem II";
+		break;
+	case ROCKET_TYPE_MODEMIII:
+		board_type = "RocketModem III";
+		break;
+	default:
+		board_type = "RocketPort";
+		break;
+	}
+
+	if (fast_clock) {
+		sClockPrescale = 0x12;	/* mod 2 (divide by 3) */
+		rp_baud_base[i] = 921600;
+	} else {
+		/*
+		 * If support_low_speed is set, use the slow clock
+		 * prescale, which supports 50 bps
+		 */
+		if (support_low_speed) {
+			/* mod 9 (divide by 10) prescale */
+			sClockPrescale = 0x19;
+			rp_baud_base[i] = 230400;
+		} else {
+			/* mod 4 (devide by 5) prescale */
+			sClockPrescale = 0x14;
+			rp_baud_base[i] = 460800;
+		}
+	}
+
+	for (aiop = 0; aiop < max_num_aiops; aiop++)
+		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
+	ctlp = sCtlNumToCtlPtr(i);
+	num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
+	for (aiop = 0; aiop < max_num_aiops; aiop++)
+		ctlp->AiopNumChan[aiop] = ports_per_aiop;
+
+	dev_info(&dev->dev, "comtrol PCI controller #%d found at "
+		"address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n",
+		i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString,
+		rocketModel[i].startingPortNumber,
+		rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1);
+
+	if (num_aiops <= 0) {
+		rcktpt_io_addr[i] = 0;
+		return (0);
+	}
+	is_PCI[i] = 1;
+
+	/*  Reset the AIOPIC, init the serial ports */
+	for (aiop = 0; aiop < num_aiops; aiop++) {
+		sResetAiopByNum(ctlp, aiop);
+		num_chan = ports_per_aiop;
+		for (chan = 0; chan < num_chan; chan++)
+			init_r_port(i, aiop, chan, dev);
+	}
+
+	/*  Rocket modems must be reset */
+	if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
+	    (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
+	    (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
+		num_chan = ports_per_aiop;
+		for (chan = 0; chan < num_chan; chan++)
+			sPCIModemReset(ctlp, chan, 1);
+		msleep(500);
+		for (chan = 0; chan < num_chan; chan++)
+			sPCIModemReset(ctlp, chan, 0);
+		msleep(500);
+		rmSpeakerReset(ctlp, rocketModel[i].model);
+	}
+	return (1);
+}
+
+/*
+ *  Probes for PCI cards, inits them if found
+ *  Input:   board_found = number of ISA boards already found, or the
+ *           starting board number
+ *  Returns: Number of PCI boards found
+ */
+static int __init init_PCI(int boards_found)
+{
+	struct pci_dev *dev = NULL;
+	int count = 0;
+
+	/*  Work through the PCI device list, pulling out ours */
+	while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
+		if (register_PCI(count + boards_found, dev))
+			count++;
+	}
+	return (count);
+}
+
+#endif				/* CONFIG_PCI */
+
+/*
+ *  Probes for ISA cards
+ *  Input:   i = the board number to look for
+ *  Returns: 1 if board found, 0 else
+ */
+static int __init init_ISA(int i)
+{
+	int num_aiops, num_chan = 0, total_num_chan = 0;
+	int aiop, chan;
+	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
+	CONTROLLER_t *ctlp;
+	char *type_string;
+
+	/*  If io_addr is zero, no board configured */
+	if (rcktpt_io_addr[i] == 0)
+		return (0);
+
+	/*  Reserve the IO region */
+	if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
+		printk(KERN_ERR "Unable to reserve IO region for configured "
+				"ISA RocketPort at address 0x%lx, board not "
+				"installed...\n", rcktpt_io_addr[i]);
+		rcktpt_io_addr[i] = 0;
+		return (0);
+	}
+
+	ctlp = sCtlNumToCtlPtr(i);
+
+	ctlp->boardType = rcktpt_type[i];
+
+	switch (rcktpt_type[i]) {
+	case ROCKET_TYPE_PC104:
+		type_string = "(PC104)";
+		break;
+	case ROCKET_TYPE_MODEM:
+		type_string = "(RocketModem)";
+		break;
+	case ROCKET_TYPE_MODEMII:
+		type_string = "(RocketModem II)";
+		break;
+	default:
+		type_string = "";
+		break;
+	}
+
+	/*
+	 * If support_low_speed is set, use the slow clock prescale,
+	 * which supports 50 bps
+	 */
+	if (support_low_speed) {
+		sClockPrescale = 0x19;	/* mod 9 (divide by 10) prescale */
+		rp_baud_base[i] = 230400;
+	} else {
+		sClockPrescale = 0x14;	/* mod 4 (devide by 5) prescale */
+		rp_baud_base[i] = 460800;
+	}
+
+	for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
+		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
+
+	num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio,  MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
+
+	if (ctlp->boardType == ROCKET_TYPE_PC104) {
+		sEnAiop(ctlp, 2);	/* only one AIOPIC, but these */
+		sEnAiop(ctlp, 3);	/* CSels used for other stuff */
+	}
+
+	/*  If something went wrong initing the AIOP's release the ISA IO memory */
+	if (num_aiops <= 0) {
+		release_region(rcktpt_io_addr[i], 64);
+		rcktpt_io_addr[i] = 0;
+		return (0);
+	}
+  
+	rocketModel[i].startingPortNumber = nextLineNumber;
+
+	for (aiop = 0; aiop < num_aiops; aiop++) {
+		sResetAiopByNum(ctlp, aiop);
+		sEnAiop(ctlp, aiop);
+		num_chan = sGetAiopNumChan(ctlp, aiop);
+		total_num_chan += num_chan;
+		for (chan = 0; chan < num_chan; chan++)
+			init_r_port(i, aiop, chan, NULL);
+	}
+	is_PCI[i] = 0;
+	if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
+		num_chan = sGetAiopNumChan(ctlp, 0);
+		total_num_chan = num_chan;
+		for (chan = 0; chan < num_chan; chan++)
+			sModemReset(ctlp, chan, 1);
+		msleep(500);
+		for (chan = 0; chan < num_chan; chan++)
+			sModemReset(ctlp, chan, 0);
+		msleep(500);
+		strcpy(rocketModel[i].modelString, "RocketModem ISA");
+	} else {
+		strcpy(rocketModel[i].modelString, "RocketPort ISA");
+	}
+	rocketModel[i].numPorts = total_num_chan;
+	rocketModel[i].model = MODEL_ISA;
+
+	printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n", 
+	       i, rcktpt_io_addr[i], num_aiops, type_string);
+
+	printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
+	       rocketModel[i].modelString,
+	       rocketModel[i].startingPortNumber,
+	       rocketModel[i].startingPortNumber +
+	       rocketModel[i].numPorts - 1);
+
+	return (1);
+}
+
+static const struct tty_operations rocket_ops = {
+	.open = rp_open,
+	.close = rp_close,
+	.write = rp_write,
+	.put_char = rp_put_char,
+	.write_room = rp_write_room,
+	.chars_in_buffer = rp_chars_in_buffer,
+	.flush_buffer = rp_flush_buffer,
+	.ioctl = rp_ioctl,
+	.throttle = rp_throttle,
+	.unthrottle = rp_unthrottle,
+	.set_termios = rp_set_termios,
+	.stop = rp_stop,
+	.start = rp_start,
+	.hangup = rp_hangup,
+	.break_ctl = rp_break,
+	.send_xchar = rp_send_xchar,
+	.wait_until_sent = rp_wait_until_sent,
+	.tiocmget = rp_tiocmget,
+	.tiocmset = rp_tiocmset,
+};
+
+static const struct tty_port_operations rocket_port_ops = {
+	.carrier_raised = carrier_raised,
+	.dtr_rts = dtr_rts,
+};
+
+/*
+ * The module "startup" routine; it's run when the module is loaded.
+ */
+static int __init rp_init(void)
+{
+	int ret = -ENOMEM, pci_boards_found, isa_boards_found, i;
+
+	printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
+	       ROCKET_VERSION, ROCKET_DATE);
+
+	rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
+	if (!rocket_driver)
+		goto err;
+
+	/*
+	 *  If board 1 is non-zero, there is at least one ISA configured.  If controller is 
+	 *  zero, use the default controller IO address of board1 + 0x40.
+	 */
+	if (board1) {
+		if (controller == 0)
+			controller = board1 + 0x40;
+	} else {
+		controller = 0;  /*  Used as a flag, meaning no ISA boards */
+	}
+
+	/*  If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
+	if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
+		printk(KERN_ERR "Unable to reserve IO region for first "
+			"configured ISA RocketPort controller 0x%lx.  "
+			"Driver exiting\n", controller);
+		ret = -EBUSY;
+		goto err_tty;
+	}
+
+	/*  Store ISA variable retrieved from command line or .conf file. */
+	rcktpt_io_addr[0] = board1;
+	rcktpt_io_addr[1] = board2;
+	rcktpt_io_addr[2] = board3;
+	rcktpt_io_addr[3] = board4;
+
+	rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+	rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
+	rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+	rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
+	rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+	rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
+	rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
+	rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
+
+	/*
+	 * Set up the tty driver structure and then register this
+	 * driver with the tty layer.
+	 */
+
+	rocket_driver->owner = THIS_MODULE;
+	rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV;
+	rocket_driver->name = "ttyR";
+	rocket_driver->driver_name = "Comtrol RocketPort";
+	rocket_driver->major = TTY_ROCKET_MAJOR;
+	rocket_driver->minor_start = 0;
+	rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	rocket_driver->subtype = SERIAL_TYPE_NORMAL;
+	rocket_driver->init_termios = tty_std_termios;
+	rocket_driver->init_termios.c_cflag =
+	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	rocket_driver->init_termios.c_ispeed = 9600;
+	rocket_driver->init_termios.c_ospeed = 9600;
+#ifdef ROCKET_SOFT_FLOW
+	rocket_driver->flags |= TTY_DRIVER_REAL_RAW;
+#endif
+	tty_set_operations(rocket_driver, &rocket_ops);
+
+	ret = tty_register_driver(rocket_driver);
+	if (ret < 0) {
+		printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
+		goto err_controller;
+	}
+
+#ifdef ROCKET_DEBUG_OPEN
+	printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
+#endif
+
+	/*
+	 *  OK, let's probe each of the controllers looking for boards.  Any boards found
+         *  will be initialized here.
+	 */
+	isa_boards_found = 0;
+	pci_boards_found = 0;
+
+	for (i = 0; i < NUM_BOARDS; i++) {
+		if (init_ISA(i))
+			isa_boards_found++;
+	}
+
+#ifdef CONFIG_PCI
+	if (isa_boards_found < NUM_BOARDS)
+		pci_boards_found = init_PCI(isa_boards_found);
+#endif
+
+	max_board = pci_boards_found + isa_boards_found;
+
+	if (max_board == 0) {
+		printk(KERN_ERR "No rocketport ports found; unloading driver\n");
+		ret = -ENXIO;
+		goto err_ttyu;
+	}
+
+	return 0;
+err_ttyu:
+	tty_unregister_driver(rocket_driver);
+err_controller:
+	if (controller)
+		release_region(controller, 4);
+err_tty:
+	put_tty_driver(rocket_driver);
+err:
+	return ret;
+}
+
+
+static void rp_cleanup_module(void)
+{
+	int retval;
+	int i;
+
+	del_timer_sync(&rocket_timer);
+
+	retval = tty_unregister_driver(rocket_driver);
+	if (retval)
+		printk(KERN_ERR "Error %d while trying to unregister "
+		       "rocketport driver\n", -retval);
+
+	for (i = 0; i < MAX_RP_PORTS; i++)
+		if (rp_table[i]) {
+			tty_unregister_device(rocket_driver, i);
+			kfree(rp_table[i]);
+		}
+
+	put_tty_driver(rocket_driver);
+
+	for (i = 0; i < NUM_BOARDS; i++) {
+		if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
+			continue;
+		release_region(rcktpt_io_addr[i], 64);
+	}
+	if (controller)
+		release_region(controller, 4);
+}
+
+/***************************************************************************
+Function: sInitController
+Purpose:  Initialization of controller global registers and controller
+          structure.
+Call:     sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
+                          IRQNum,Frequency,PeriodicOnly)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int CtlNum; Controller number
+          ByteIO_t MudbacIO; Mudbac base I/O address.
+          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
+             This list must be in the order the AIOPs will be found on the
+             controller.  Once an AIOP in the list is not found, it is
+             assumed that there are no more AIOPs on the controller.
+          int AiopIOListSize; Number of addresses in AiopIOList
+          int IRQNum; Interrupt Request number.  Can be any of the following:
+                         0: Disable global interrupts
+                         3: IRQ 3
+                         4: IRQ 4
+                         5: IRQ 5
+                         9: IRQ 9
+                         10: IRQ 10
+                         11: IRQ 11
+                         12: IRQ 12
+                         15: IRQ 15
+          Byte_t Frequency: A flag identifying the frequency
+                   of the periodic interrupt, can be any one of the following:
+                      FREQ_DIS - periodic interrupt disabled
+                      FREQ_137HZ - 137 Hertz
+                      FREQ_69HZ - 69 Hertz
+                      FREQ_34HZ - 34 Hertz
+                      FREQ_17HZ - 17 Hertz
+                      FREQ_9HZ - 9 Hertz
+                      FREQ_4HZ - 4 Hertz
+                   If IRQNum is set to 0 the Frequency parameter is
+                   overidden, it is forced to a value of FREQ_DIS.
+          int PeriodicOnly: 1 if all interrupts except the periodic
+                               interrupt are to be blocked.
+                            0 is both the periodic interrupt and
+                               other channel interrupts are allowed.
+                            If IRQNum is set to 0 the PeriodicOnly parameter is
+                               overidden, it is forced to a value of 0.
+Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
+               initialization failed.
+
+Comments:
+          If periodic interrupts are to be disabled but AIOP interrupts
+          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
+
+          If interrupts are to be completely disabled set IRQNum to 0.
+
+          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
+          invalid combination.
+
+          This function performs initialization of global interrupt modes,
+          but it does not actually enable global interrupts.  To enable
+          and disable global interrupts use functions sEnGlobalInt() and
+          sDisGlobalInt().  Enabling of global interrupts is normally not
+          done until all other initializations are complete.
+
+          Even if interrupts are globally enabled, they must also be
+          individually enabled for each channel that is to generate
+          interrupts.
+
+Warnings: No range checking on any of the parameters is done.
+
+          No context switches are allowed while executing this function.
+
+          After this function all AIOPs on the controller are disabled,
+          they can be enabled with sEnAiop().
+*/
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+			   ByteIO_t * AiopIOList, int AiopIOListSize,
+			   int IRQNum, Byte_t Frequency, int PeriodicOnly)
+{
+	int i;
+	ByteIO_t io;
+	int done;
+
+	CtlP->AiopIntrBits = aiop_intr_bits;
+	CtlP->AltChanRingIndicator = 0;
+	CtlP->CtlNum = CtlNum;
+	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
+	CtlP->BusType = isISA;
+	CtlP->MBaseIO = MudbacIO;
+	CtlP->MReg1IO = MudbacIO + 1;
+	CtlP->MReg2IO = MudbacIO + 2;
+	CtlP->MReg3IO = MudbacIO + 3;
+#if 1
+	CtlP->MReg2 = 0;	/* interrupt disable */
+	CtlP->MReg3 = 0;	/* no periodic interrupts */
+#else
+	if (sIRQMap[IRQNum] == 0) {	/* interrupts globally disabled */
+		CtlP->MReg2 = 0;	/* interrupt disable */
+		CtlP->MReg3 = 0;	/* no periodic interrupts */
+	} else {
+		CtlP->MReg2 = sIRQMap[IRQNum];	/* set IRQ number */
+		CtlP->MReg3 = Frequency;	/* set frequency */
+		if (PeriodicOnly) {	/* periodic interrupt only */
+			CtlP->MReg3 |= PERIODIC_ONLY;
+		}
+	}
+#endif
+	sOutB(CtlP->MReg2IO, CtlP->MReg2);
+	sOutB(CtlP->MReg3IO, CtlP->MReg3);
+	sControllerEOI(CtlP);	/* clear EOI if warm init */
+	/* Init AIOPs */
+	CtlP->NumAiop = 0;
+	for (i = done = 0; i < AiopIOListSize; i++) {
+		io = AiopIOList[i];
+		CtlP->AiopIO[i] = (WordIO_t) io;
+		CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
+		sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03));	/* AIOP index */
+		sOutB(MudbacIO, (Byte_t) (io >> 6));	/* set up AIOP I/O in MUDBAC */
+		if (done)
+			continue;
+		sEnAiop(CtlP, i);	/* enable the AIOP */
+		CtlP->AiopID[i] = sReadAiopID(io);	/* read AIOP ID */
+		if (CtlP->AiopID[i] == AIOPID_NULL)	/* if AIOP does not exist */
+			done = 1;	/* done looking for AIOPs */
+		else {
+			CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io);	/* num channels in AIOP */
+			sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);	/* clock prescaler */
+			sOutB(io + _INDX_DATA, sClockPrescale);
+			CtlP->NumAiop++;	/* bump count of AIOPs */
+		}
+		sDisAiop(CtlP, i);	/* disable AIOP */
+	}
+
+	if (CtlP->NumAiop == 0)
+		return (-1);
+	else
+		return (CtlP->NumAiop);
+}
+
+/***************************************************************************
+Function: sPCIInitController
+Purpose:  Initialization of controller global registers and controller
+          structure.
+Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
+                          IRQNum,Frequency,PeriodicOnly)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int CtlNum; Controller number
+          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
+             This list must be in the order the AIOPs will be found on the
+             controller.  Once an AIOP in the list is not found, it is
+             assumed that there are no more AIOPs on the controller.
+          int AiopIOListSize; Number of addresses in AiopIOList
+          int IRQNum; Interrupt Request number.  Can be any of the following:
+                         0: Disable global interrupts
+                         3: IRQ 3
+                         4: IRQ 4
+                         5: IRQ 5
+                         9: IRQ 9
+                         10: IRQ 10
+                         11: IRQ 11
+                         12: IRQ 12
+                         15: IRQ 15
+          Byte_t Frequency: A flag identifying the frequency
+                   of the periodic interrupt, can be any one of the following:
+                      FREQ_DIS - periodic interrupt disabled
+                      FREQ_137HZ - 137 Hertz
+                      FREQ_69HZ - 69 Hertz
+                      FREQ_34HZ - 34 Hertz
+                      FREQ_17HZ - 17 Hertz
+                      FREQ_9HZ - 9 Hertz
+                      FREQ_4HZ - 4 Hertz
+                   If IRQNum is set to 0 the Frequency parameter is
+                   overidden, it is forced to a value of FREQ_DIS.
+          int PeriodicOnly: 1 if all interrupts except the periodic
+                               interrupt are to be blocked.
+                            0 is both the periodic interrupt and
+                               other channel interrupts are allowed.
+                            If IRQNum is set to 0 the PeriodicOnly parameter is
+                               overidden, it is forced to a value of 0.
+Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
+               initialization failed.
+
+Comments:
+          If periodic interrupts are to be disabled but AIOP interrupts
+          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
+
+          If interrupts are to be completely disabled set IRQNum to 0.
+
+          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
+          invalid combination.
+
+          This function performs initialization of global interrupt modes,
+          but it does not actually enable global interrupts.  To enable
+          and disable global interrupts use functions sEnGlobalInt() and
+          sDisGlobalInt().  Enabling of global interrupts is normally not
+          done until all other initializations are complete.
+
+          Even if interrupts are globally enabled, they must also be
+          individually enabled for each channel that is to generate
+          interrupts.
+
+Warnings: No range checking on any of the parameters is done.
+
+          No context switches are allowed while executing this function.
+
+          After this function all AIOPs on the controller are disabled,
+          they can be enabled with sEnAiop().
+*/
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+			      ByteIO_t * AiopIOList, int AiopIOListSize,
+			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+			      int PeriodicOnly, int altChanRingIndicator,
+			      int UPCIRingInd)
+{
+	int i;
+	ByteIO_t io;
+
+	CtlP->AltChanRingIndicator = altChanRingIndicator;
+	CtlP->UPCIRingInd = UPCIRingInd;
+	CtlP->CtlNum = CtlNum;
+	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
+	CtlP->BusType = isPCI;	/* controller release 1 */
+
+	if (ConfigIO) {
+		CtlP->isUPCI = 1;
+		CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
+		CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
+		CtlP->AiopIntrBits = upci_aiop_intr_bits;
+	} else {
+		CtlP->isUPCI = 0;
+		CtlP->PCIIO =
+		    (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
+		CtlP->AiopIntrBits = aiop_intr_bits;
+	}
+
+	sPCIControllerEOI(CtlP);	/* clear EOI if warm init */
+	/* Init AIOPs */
+	CtlP->NumAiop = 0;
+	for (i = 0; i < AiopIOListSize; i++) {
+		io = AiopIOList[i];
+		CtlP->AiopIO[i] = (WordIO_t) io;
+		CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
+
+		CtlP->AiopID[i] = sReadAiopID(io);	/* read AIOP ID */
+		if (CtlP->AiopID[i] == AIOPID_NULL)	/* if AIOP does not exist */
+			break;	/* done looking for AIOPs */
+
+		CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io);	/* num channels in AIOP */
+		sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);	/* clock prescaler */
+		sOutB(io + _INDX_DATA, sClockPrescale);
+		CtlP->NumAiop++;	/* bump count of AIOPs */
+	}
+
+	if (CtlP->NumAiop == 0)
+		return (-1);
+	else
+		return (CtlP->NumAiop);
+}
+
+/***************************************************************************
+Function: sReadAiopID
+Purpose:  Read the AIOP idenfication number directly from an AIOP.
+Call:     sReadAiopID(io)
+          ByteIO_t io: AIOP base I/O address
+Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
+                 is replace by an identifying number.
+          Flag AIOPID_NULL if no valid AIOP is found
+Warnings: No context switches are allowed while executing this function.
+
+*/
+static int sReadAiopID(ByteIO_t io)
+{
+	Byte_t AiopID;		/* ID byte from AIOP */
+
+	sOutB(io + _CMD_REG, RESET_ALL);	/* reset AIOP */
+	sOutB(io + _CMD_REG, 0x0);
+	AiopID = sInW(io + _CHN_STAT0) & 0x07;
+	if (AiopID == 0x06)
+		return (1);
+	else			/* AIOP does not exist */
+		return (-1);
+}
+
+/***************************************************************************
+Function: sReadAiopNumChan
+Purpose:  Read the number of channels available in an AIOP directly from
+          an AIOP.
+Call:     sReadAiopNumChan(io)
+          WordIO_t io: AIOP base I/O address
+Return:   int: The number of channels available
+Comments: The number of channels is determined by write/reads from identical
+          offsets within the SRAM address spaces for channels 0 and 4.
+          If the channel 4 space is mirrored to channel 0 it is a 4 channel
+          AIOP, otherwise it is an 8 channel.
+Warnings: No context switches are allowed while executing this function.
+*/
+static int sReadAiopNumChan(WordIO_t io)
+{
+	Word_t x;
+	static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
+
+	/* write to chan 0 SRAM */
+	out32((DWordIO_t) io + _INDX_ADDR, R);
+	sOutW(io + _INDX_ADDR, 0);	/* read from SRAM, chan 0 */
+	x = sInW(io + _INDX_DATA);
+	sOutW(io + _INDX_ADDR, 0x4000);	/* read from SRAM, chan 4 */
+	if (x != sInW(io + _INDX_DATA))	/* if different must be 8 chan */
+		return (8);
+	else
+		return (4);
+}
+
+/***************************************************************************
+Function: sInitChan
+Purpose:  Initialization of a channel and channel structure
+Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          CHANNEL_T *ChP; Ptr to channel structure
+          int AiopNum; AIOP number within controller
+          int ChanNum; Channel number within AIOP
+Return:   int: 1 if initialization succeeded, 0 if it fails because channel
+               number exceeds number of channels available in AIOP.
+Comments: This function must be called before a channel can be used.
+Warnings: No range checking on any of the parameters is done.
+
+          No context switches are allowed while executing this function.
+*/
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+		     int ChanNum)
+{
+	int i;
+	WordIO_t AiopIO;
+	WordIO_t ChIOOff;
+	Byte_t *ChR;
+	Word_t ChOff;
+	static Byte_t R[4];
+	int brd9600;
+
+	if (ChanNum >= CtlP->AiopNumChan[AiopNum])
+		return 0;	/* exceeds num chans in AIOP */
+
+	/* Channel, AIOP, and controller identifiers */
+	ChP->CtlP = CtlP;
+	ChP->ChanID = CtlP->AiopID[AiopNum];
+	ChP->AiopNum = AiopNum;
+	ChP->ChanNum = ChanNum;
+
+	/* Global direct addresses */
+	AiopIO = CtlP->AiopIO[AiopNum];
+	ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
+	ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
+	ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
+	ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
+	ChP->IndexData = AiopIO + _INDX_DATA;
+
+	/* Channel direct addresses */
+	ChIOOff = AiopIO + ChP->ChanNum * 2;
+	ChP->TxRxData = ChIOOff + _TD0;
+	ChP->ChanStat = ChIOOff + _CHN_STAT0;
+	ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
+	ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
+
+	/* Initialize the channel from the RData array */
+	for (i = 0; i < RDATASIZE; i += 4) {
+		R[0] = RData[i];
+		R[1] = RData[i + 1] + 0x10 * ChanNum;
+		R[2] = RData[i + 2];
+		R[3] = RData[i + 3];
+		out32(ChP->IndexAddr, R);
+	}
+
+	ChR = ChP->R;
+	for (i = 0; i < RREGDATASIZE; i += 4) {
+		ChR[i] = RRegData[i];
+		ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
+		ChR[i + 2] = RRegData[i + 2];
+		ChR[i + 3] = RRegData[i + 3];
+	}
+
+	/* Indexed registers */
+	ChOff = (Word_t) ChanNum *0x1000;
+
+	if (sClockPrescale == 0x14)
+		brd9600 = 47;
+	else
+		brd9600 = 23;
+
+	ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
+	ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
+	ChP->BaudDiv[2] = (Byte_t) brd9600;
+	ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
+	out32(ChP->IndexAddr, ChP->BaudDiv);
+
+	ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
+	ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
+	ChP->TxControl[2] = 0;
+	ChP->TxControl[3] = 0;
+	out32(ChP->IndexAddr, ChP->TxControl);
+
+	ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
+	ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
+	ChP->RxControl[2] = 0;
+	ChP->RxControl[3] = 0;
+	out32(ChP->IndexAddr, ChP->RxControl);
+
+	ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
+	ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
+	ChP->TxEnables[2] = 0;
+	ChP->TxEnables[3] = 0;
+	out32(ChP->IndexAddr, ChP->TxEnables);
+
+	ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
+	ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
+	ChP->TxCompare[2] = 0;
+	ChP->TxCompare[3] = 0;
+	out32(ChP->IndexAddr, ChP->TxCompare);
+
+	ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
+	ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
+	ChP->TxReplace1[2] = 0;
+	ChP->TxReplace1[3] = 0;
+	out32(ChP->IndexAddr, ChP->TxReplace1);
+
+	ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
+	ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
+	ChP->TxReplace2[2] = 0;
+	ChP->TxReplace2[3] = 0;
+	out32(ChP->IndexAddr, ChP->TxReplace2);
+
+	ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
+	ChP->TxFIFO = ChOff + _TX_FIFO;
+
+	sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT);	/* apply reset Tx FIFO count */
+	sOutB(ChP->Cmd, (Byte_t) ChanNum);	/* remove reset Tx FIFO count */
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs);	/* clear Tx in/out ptrs */
+	sOutW(ChP->IndexData, 0);
+	ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
+	ChP->RxFIFO = ChOff + _RX_FIFO;
+
+	sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT);	/* apply reset Rx FIFO count */
+	sOutB(ChP->Cmd, (Byte_t) ChanNum);	/* remove reset Rx FIFO count */
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs);	/* clear Rx out ptr */
+	sOutW(ChP->IndexData, 0);
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2);	/* clear Rx in ptr */
+	sOutW(ChP->IndexData, 0);
+	ChP->TxPrioCnt = ChOff + _TXP_CNT;
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
+	sOutB(ChP->IndexData, 0);
+	ChP->TxPrioPtr = ChOff + _TXP_PNTR;
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
+	sOutB(ChP->IndexData, 0);
+	ChP->TxPrioBuf = ChOff + _TXP_BUF;
+	sEnRxProcessor(ChP);	/* start the Rx processor */
+
+	return 1;
+}
+
+/***************************************************************************
+Function: sStopRxProcessor
+Purpose:  Stop the receive processor from processing a channel.
+Call:     sStopRxProcessor(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+
+Comments: The receive processor can be started again with sStartRxProcessor().
+          This function causes the receive processor to skip over the
+          stopped channel.  It does not stop it from processing other channels.
+
+Warnings: No context switches are allowed while executing this function.
+
+          Do not leave the receive processor stopped for more than one
+          character time.
+
+          After calling this function a delay of 4 uS is required to ensure
+          that the receive processor is no longer processing this channel.
+*/
+static void sStopRxProcessor(CHANNEL_T * ChP)
+{
+	Byte_t R[4];
+
+	R[0] = ChP->R[0];
+	R[1] = ChP->R[1];
+	R[2] = 0x0a;
+	R[3] = ChP->R[3];
+	out32(ChP->IndexAddr, R);
+}
+
+/***************************************************************************
+Function: sFlushRxFIFO
+Purpose:  Flush the Rx FIFO
+Call:     sFlushRxFIFO(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   void
+Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
+          while it is being flushed the receive processor is stopped
+          and the transmitter is disabled.  After these operations a
+          4 uS delay is done before clearing the pointers to allow
+          the receive processor to stop.  These items are handled inside
+          this function.
+Warnings: No context switches are allowed while executing this function.
+*/
+static void sFlushRxFIFO(CHANNEL_T * ChP)
+{
+	int i;
+	Byte_t Ch;		/* channel number within AIOP */
+	int RxFIFOEnabled;	/* 1 if Rx FIFO enabled */
+
+	if (sGetRxCnt(ChP) == 0)	/* Rx FIFO empty */
+		return;		/* don't need to flush */
+
+	RxFIFOEnabled = 0;
+	if (ChP->R[0x32] == 0x08) {	/* Rx FIFO is enabled */
+		RxFIFOEnabled = 1;
+		sDisRxFIFO(ChP);	/* disable it */
+		for (i = 0; i < 2000 / 200; i++)	/* delay 2 uS to allow proc to disable FIFO */
+			sInB(ChP->IntChan);	/* depends on bus i/o timing */
+	}
+	sGetChanStatus(ChP);	/* clear any pending Rx errors in chan stat */
+	Ch = (Byte_t) sGetChanNum(ChP);
+	sOutB(ChP->Cmd, Ch | RESRXFCNT);	/* apply reset Rx FIFO count */
+	sOutB(ChP->Cmd, Ch);	/* remove reset Rx FIFO count */
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs);	/* clear Rx out ptr */
+	sOutW(ChP->IndexData, 0);
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2);	/* clear Rx in ptr */
+	sOutW(ChP->IndexData, 0);
+	if (RxFIFOEnabled)
+		sEnRxFIFO(ChP);	/* enable Rx FIFO */
+}
+
+/***************************************************************************
+Function: sFlushTxFIFO
+Purpose:  Flush the Tx FIFO
+Call:     sFlushTxFIFO(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   void
+Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
+          while it is being flushed the receive processor is stopped
+          and the transmitter is disabled.  After these operations a
+          4 uS delay is done before clearing the pointers to allow
+          the receive processor to stop.  These items are handled inside
+          this function.
+Warnings: No context switches are allowed while executing this function.
+*/
+static void sFlushTxFIFO(CHANNEL_T * ChP)
+{
+	int i;
+	Byte_t Ch;		/* channel number within AIOP */
+	int TxEnabled;		/* 1 if transmitter enabled */
+
+	if (sGetTxCnt(ChP) == 0)	/* Tx FIFO empty */
+		return;		/* don't need to flush */
+
+	TxEnabled = 0;
+	if (ChP->TxControl[3] & TX_ENABLE) {
+		TxEnabled = 1;
+		sDisTransmit(ChP);	/* disable transmitter */
+	}
+	sStopRxProcessor(ChP);	/* stop Rx processor */
+	for (i = 0; i < 4000 / 200; i++)	/* delay 4 uS to allow proc to stop */
+		sInB(ChP->IntChan);	/* depends on bus i/o timing */
+	Ch = (Byte_t) sGetChanNum(ChP);
+	sOutB(ChP->Cmd, Ch | RESTXFCNT);	/* apply reset Tx FIFO count */
+	sOutB(ChP->Cmd, Ch);	/* remove reset Tx FIFO count */
+	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs);	/* clear Tx in/out ptrs */
+	sOutW(ChP->IndexData, 0);
+	if (TxEnabled)
+		sEnTransmit(ChP);	/* enable transmitter */
+	sStartRxProcessor(ChP);	/* restart Rx processor */
+}
+
+/***************************************************************************
+Function: sWriteTxPrioByte
+Purpose:  Write a byte of priority transmit data to a channel
+Call:     sWriteTxPrioByte(ChP,Data)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Byte_t Data; The transmit data byte
+
+Return:   int: 1 if the bytes is successfully written, otherwise 0.
+
+Comments: The priority byte is transmitted before any data in the Tx FIFO.
+
+Warnings: No context switches are allowed while executing this function.
+*/
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
+{
+	Byte_t DWBuf[4];	/* buffer for double word writes */
+	Word_t *WordPtr;	/* must be far because Win SS != DS */
+	register DWordIO_t IndexAddr;
+
+	if (sGetTxCnt(ChP) > 1) {	/* write it to Tx priority buffer */
+		IndexAddr = ChP->IndexAddr;
+		sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt);	/* get priority buffer status */
+		if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND)	/* priority buffer busy */
+			return (0);	/* nothing sent */
+
+		WordPtr = (Word_t *) (&DWBuf[0]);
+		*WordPtr = ChP->TxPrioBuf;	/* data byte address */
+
+		DWBuf[2] = Data;	/* data byte value */
+		out32(IndexAddr, DWBuf);	/* write it out */
+
+		*WordPtr = ChP->TxPrioCnt;	/* Tx priority count address */
+
+		DWBuf[2] = PRI_PEND + 1;	/* indicate 1 byte pending */
+		DWBuf[3] = 0;	/* priority buffer pointer */
+		out32(IndexAddr, DWBuf);	/* write it out */
+	} else {		/* write it to Tx FIFO */
+
+		sWriteTxByte(sGetTxRxDataIO(ChP), Data);
+	}
+	return (1);		/* 1 byte sent */
+}
+
+/***************************************************************************
+Function: sEnInterrupts
+Purpose:  Enable one or more interrupts for a channel
+Call:     sEnInterrupts(ChP,Flags)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Word_t Flags: Interrupt enable flags, can be any combination
+             of the following flags:
+                TXINT_EN:   Interrupt on Tx FIFO empty
+                RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
+                            sSetRxTrigger())
+                SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
+                MCINT_EN:   Interrupt on modem input change
+                CHANINT_EN: Allow channel interrupt signal to the AIOP's
+                            Interrupt Channel Register.
+Return:   void
+Comments: If an interrupt enable flag is set in Flags, that interrupt will be
+          enabled.  If an interrupt enable flag is not set in Flags, that
+          interrupt will not be changed.  Interrupts can be disabled with
+          function sDisInterrupts().
+
+          This function sets the appropriate bit for the channel in the AIOP's
+          Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
+          this channel's bit to be set in the AIOP's Interrupt Channel Register.
+
+          Interrupts must also be globally enabled before channel interrupts
+          will be passed on to the host.  This is done with function
+          sEnGlobalInt().
+
+          In some cases it may be desirable to disable interrupts globally but
+          enable channel interrupts.  This would allow the global interrupt
+          status register to be used to determine which AIOPs need service.
+*/
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
+{
+	Byte_t Mask;		/* Interrupt Mask Register */
+
+	ChP->RxControl[2] |=
+	    ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
+
+	out32(ChP->IndexAddr, ChP->RxControl);
+
+	ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
+
+	out32(ChP->IndexAddr, ChP->TxControl);
+
+	if (Flags & CHANINT_EN) {
+		Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
+		sOutB(ChP->IntMask, Mask);
+	}
+}
+
+/***************************************************************************
+Function: sDisInterrupts
+Purpose:  Disable one or more interrupts for a channel
+Call:     sDisInterrupts(ChP,Flags)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Word_t Flags: Interrupt flags, can be any combination
+             of the following flags:
+                TXINT_EN:   Interrupt on Tx FIFO empty
+                RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
+                            sSetRxTrigger())
+                SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
+                MCINT_EN:   Interrupt on modem input change
+                CHANINT_EN: Disable channel interrupt signal to the
+                            AIOP's Interrupt Channel Register.
+Return:   void
+Comments: If an interrupt flag is set in Flags, that interrupt will be
+          disabled.  If an interrupt flag is not set in Flags, that
+          interrupt will not be changed.  Interrupts can be enabled with
+          function sEnInterrupts().
+
+          This function clears the appropriate bit for the channel in the AIOP's
+          Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
+          this channel's bit from being set in the AIOP's Interrupt Channel
+          Register.
+*/
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
+{
+	Byte_t Mask;		/* Interrupt Mask Register */
+
+	ChP->RxControl[2] &=
+	    ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
+	out32(ChP->IndexAddr, ChP->RxControl);
+	ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
+	out32(ChP->IndexAddr, ChP->TxControl);
+
+	if (Flags & CHANINT_EN) {
+		Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
+		sOutB(ChP->IntMask, Mask);
+	}
+}
+
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
+{
+	sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
+}
+
+/*
+ *  Not an official SSCI function, but how to reset RocketModems.
+ *  ISA bus version
+ */
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
+{
+	ByteIO_t addr;
+	Byte_t val;
+
+	addr = CtlP->AiopIO[0] + 0x400;
+	val = sInB(CtlP->MReg3IO);
+	/* if AIOP[1] is not enabled, enable it */
+	if ((val & 2) == 0) {
+		val = sInB(CtlP->MReg2IO);
+		sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
+		sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
+	}
+
+	sEnAiop(CtlP, 1);
+	if (!on)
+		addr += 8;
+	sOutB(addr + chan, 0);	/* apply or remove reset */
+	sDisAiop(CtlP, 1);
+}
+
+/*
+ *  Not an official SSCI function, but how to reset RocketModems.
+ *  PCI bus version
+ */
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
+{
+	ByteIO_t addr;
+
+	addr = CtlP->AiopIO[0] + 0x40;	/* 2nd AIOP */
+	if (!on)
+		addr += 8;
+	sOutB(addr + chan, 0);	/* apply or remove reset */
+}
+
+/*  Resets the speaker controller on RocketModem II and III devices */
+static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
+{
+	ByteIO_t addr;
+
+	/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
+	if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
+		addr = CtlP->AiopIO[0] + 0x4F;
+		sOutB(addr, 0);
+	}
+
+	/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
+	if ((model == MODEL_UPCI_RM3_8PORT)
+	    || (model == MODEL_UPCI_RM3_4PORT)) {
+		addr = CtlP->AiopIO[0] + 0x88;
+		sOutB(addr, 0);
+	}
+}
+
+/*  Returns the line number given the controller (board), aiop and channel number */
+static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
+{
+	return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
+}
+
+/*
+ *  Stores the line number associated with a given controller (board), aiop
+ *  and channel number.  
+ *  Returns:  The line number assigned 
+ */
+static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
+{
+	lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
+	return (nextLineNumber - 1);
+}
diff --git a/drivers/tty/rocket.h b/drivers/tty/rocket.h
new file mode 100644
index 0000000..ec863f3
--- /dev/null
+++ b/drivers/tty/rocket.h
@@ -0,0 +1,111 @@
+/*
+ * rocket.h --- the exported interface of the rocket driver to its configuration program.
+ *
+ * Written by Theodore Ts'o, Copyright 1997.
+ * Copyright 1997 Comtrol Corporation. 
+ *
+ */
+
+/*  Model Information Struct */
+typedef struct {
+	unsigned long model;
+	char modelString[80];
+	unsigned long numPorts;
+	int loadrm2;
+	int startingPortNumber;
+} rocketModel_t;
+
+struct rocket_config {
+	int line;
+	int flags;
+	int closing_wait;
+	int close_delay;
+	int port;
+	int reserved[32];
+};
+
+struct rocket_ports {
+	int tty_major;
+	int callout_major;
+	rocketModel_t rocketModel[8];
+};
+
+struct rocket_version {
+	char rocket_version[32];
+	char rocket_date[32];
+	char reserved[64];
+};
+
+/*
+ * Rocketport flags
+ */
+/*#define ROCKET_CALLOUT_NOHUP    0x00000001 */
+#define ROCKET_FORCE_CD		0x00000002
+#define ROCKET_HUP_NOTIFY	0x00000004
+#define ROCKET_SPLIT_TERMIOS	0x00000008
+#define ROCKET_SPD_MASK		0x00000070
+#define ROCKET_SPD_HI		0x00000010	/* Use 56000 instead of 38400 bps */
+#define ROCKET_SPD_VHI		0x00000020	/* Use 115200 instead of 38400 bps */
+#define ROCKET_SPD_SHI		0x00000030	/* Use 230400 instead of 38400 bps */
+#define ROCKET_SPD_WARP	        0x00000040	/* Use 460800 instead of 38400 bps */
+#define ROCKET_SAK		0x00000080
+#define ROCKET_SESSION_LOCKOUT	0x00000100
+#define ROCKET_PGRP_LOCKOUT	0x00000200
+#define ROCKET_RTS_TOGGLE	0x00000400
+#define ROCKET_MODE_MASK        0x00003000
+#define ROCKET_MODE_RS232       0x00000000
+#define ROCKET_MODE_RS485       0x00001000
+#define ROCKET_MODE_RS422       0x00002000
+#define ROCKET_FLAGS		0x00003FFF
+
+#define ROCKET_USR_MASK 0x0071	/* Legal flags that non-privileged
+				 * users can set or reset */
+
+/*
+ * For closing_wait and closing_wait2
+ */
+#define ROCKET_CLOSING_WAIT_NONE	ASYNC_CLOSING_WAIT_NONE
+#define ROCKET_CLOSING_WAIT_INF		ASYNC_CLOSING_WAIT_INF
+
+/*
+ * Rocketport ioctls -- "RP"
+ */
+#define RCKP_GET_STRUCT		0x00525001
+#define RCKP_GET_CONFIG		0x00525002
+#define RCKP_SET_CONFIG		0x00525003
+#define RCKP_GET_PORTS		0x00525004
+#define RCKP_RESET_RM2		0x00525005
+#define RCKP_GET_VERSION	0x00525006
+
+/*  Rocketport Models */
+#define MODEL_RP32INTF        0x0001	/* RP 32 port w/external I/F   */
+#define MODEL_RP8INTF         0x0002	/* RP 8 port w/external I/F    */
+#define MODEL_RP16INTF        0x0003	/* RP 16 port w/external I/F   */
+#define MODEL_RP8OCTA         0x0005	/* RP 8 port w/octa cable      */
+#define MODEL_RP4QUAD         0x0004	/* RP 4 port w/quad cable      */
+#define MODEL_RP8J            0x0006	/* RP 8 port w/RJ11 connectors */
+#define MODEL_RP4J            0x0007	/* RP 4 port w/RJ45 connectors */
+#define MODEL_RP8SNI          0x0008	/* RP 8 port w/ DB78 SNI connector */
+#define MODEL_RP16SNI         0x0009	/* RP 16 port w/ DB78 SNI connector */
+#define MODEL_RPP4            0x000A	/* RP Plus 4 port              */
+#define MODEL_RPP8            0x000B	/* RP Plus 8 port              */
+#define MODEL_RP2_232         0x000E	/* RP Plus 2 port RS232        */
+#define MODEL_RP2_422         0x000F	/* RP Plus 2 port RS232        */
+
+/*  Rocketmodem II Models */
+#define MODEL_RP6M            0x000C	/* RM 6 port                   */
+#define MODEL_RP4M            0x000D	/* RM 4 port                   */
+
+/* Universal PCI boards */
+#define MODEL_UPCI_RP32INTF   0x0801	/* RP UPCI 32 port w/external I/F     */
+#define MODEL_UPCI_RP8INTF    0x0802	/* RP UPCI 8 port w/external I/F      */
+#define MODEL_UPCI_RP16INTF   0x0803	/* RP UPCI 16 port w/external I/F     */
+#define MODEL_UPCI_RP8OCTA    0x0805	/* RP UPCI 8 port w/octa cable        */ 
+#define MODEL_UPCI_RM3_8PORT  0x080C	/* RP UPCI Rocketmodem III 8 port     */
+#define MODEL_UPCI_RM3_4PORT  0x080C	/* RP UPCI Rocketmodem III 4 port     */
+
+/*  Compact PCI 16 port  */
+#define MODEL_CPCI_RP16INTF   0x0903	/* RP Compact PCI 16 port w/external I/F */
+
+/* All ISA boards */
+#define MODEL_ISA             0x1000
diff --git a/drivers/tty/rocket_int.h b/drivers/tty/rocket_int.h
new file mode 100644
index 0000000..67e0f1e
--- /dev/null
+++ b/drivers/tty/rocket_int.h
@@ -0,0 +1,1214 @@
+/*
+ * rocket_int.h --- internal header file for rocket.c
+ *
+ * Written by Theodore Ts'o, Copyright 1997.
+ * Copyright 1997 Comtrol Corporation.  
+ * 
+ */
+
+/*
+ * Definition of the types in rcktpt_type
+ */
+#define ROCKET_TYPE_NORMAL	0
+#define ROCKET_TYPE_MODEM	1
+#define ROCKET_TYPE_MODEMII	2
+#define ROCKET_TYPE_MODEMIII	3
+#define ROCKET_TYPE_PC104       4
+
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+typedef unsigned char Byte_t;
+typedef unsigned int ByteIO_t;
+
+typedef unsigned int Word_t;
+typedef unsigned int WordIO_t;
+
+typedef unsigned int DWordIO_t;
+
+/*
+ * Note!  Normally the Linux I/O macros already take care of
+ * byte-swapping the I/O instructions.  However, all accesses using
+ * sOutDW aren't really 32-bit accesses, but should be handled in byte
+ * order.  Hence the use of the cpu_to_le32() macro to byte-swap
+ * things to no-op the byte swapping done by the big-endian outl()
+ * instruction.
+ */
+
+static inline void sOutB(unsigned short port, unsigned char value)
+{
+#ifdef ROCKET_DEBUG_IO
+	printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value);
+#endif
+	outb_p(value, port);
+}
+
+static inline void sOutW(unsigned short port, unsigned short value)
+{
+#ifdef ROCKET_DEBUG_IO
+	printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value);
+#endif
+	outw_p(value, port);
+}
+
+static inline void out32(unsigned short port, Byte_t *p)
+{
+	u32 value = get_unaligned_le32(p);
+#ifdef ROCKET_DEBUG_IO
+	printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value);
+#endif
+	outl_p(value, port);
+}
+
+static inline unsigned char sInB(unsigned short port)
+{
+	return inb_p(port);
+}
+
+static inline unsigned short sInW(unsigned short port)
+{
+	return inw_p(port);
+}
+
+/* This is used to move arrays of bytes so byte swapping isn't appropriate. */
+#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count)
+#define sInStrW(port, addr, count) if (count) insw(port, addr, count)
+
+#define CTL_SIZE 8
+#define AIOP_CTL_SIZE 4
+#define CHAN_AIOP_SIZE 8
+#define MAX_PORTS_PER_AIOP 8
+#define MAX_AIOPS_PER_BOARD 4
+#define MAX_PORTS_PER_BOARD 32
+
+/* Bus type ID */
+#define	isISA	0
+#define	isPCI	1
+#define	isMC	2
+
+/* Controller ID numbers */
+#define CTLID_NULL  -1		/* no controller exists */
+#define CTLID_0001  0x0001	/* controller release 1 */
+
+/* AIOP ID numbers, identifies AIOP type implementing channel */
+#define AIOPID_NULL -1		/* no AIOP or channel exists */
+#define AIOPID_0001 0x0001	/* AIOP release 1 */
+
+/************************************************************************
+ Global Register Offsets - Direct Access - Fixed values
+************************************************************************/
+
+#define _CMD_REG   0x38		/* Command Register            8    Write */
+#define _INT_CHAN  0x39		/* Interrupt Channel Register  8    Read */
+#define _INT_MASK  0x3A		/* Interrupt Mask Register     8    Read / Write */
+#define _UNUSED    0x3B		/* Unused                      8 */
+#define _INDX_ADDR 0x3C		/* Index Register Address      16   Write */
+#define _INDX_DATA 0x3E		/* Index Register Data         8/16 Read / Write */
+
+/************************************************************************
+ Channel Register Offsets for 1st channel in AIOP - Direct Access
+************************************************************************/
+#define _TD0       0x00		/* Transmit Data               16   Write */
+#define _RD0       0x00		/* Receive Data                16   Read */
+#define _CHN_STAT0 0x20		/* Channel Status              8/16 Read / Write */
+#define _FIFO_CNT0 0x10		/* Transmit/Receive FIFO Count 16   Read */
+#define _INT_ID0   0x30		/* Interrupt Identification    8    Read */
+
+/************************************************************************
+ Tx Control Register Offsets - Indexed - External - Fixed
+************************************************************************/
+#define _TX_ENBLS  0x980	/* Tx Processor Enables Register 8 Read / Write */
+#define _TXCMP1    0x988	/* Transmit Compare Value #1     8 Read / Write */
+#define _TXCMP2    0x989	/* Transmit Compare Value #2     8 Read / Write */
+#define _TXREP1B1  0x98A	/* Tx Replace Value #1 - Byte 1  8 Read / Write */
+#define _TXREP1B2  0x98B	/* Tx Replace Value #1 - Byte 2  8 Read / Write */
+#define _TXREP2    0x98C	/* Transmit Replace Value #2     8 Read / Write */
+
+/************************************************************************
+Memory Controller Register Offsets - Indexed - External - Fixed
+************************************************************************/
+#define _RX_FIFO    0x000	/* Rx FIFO */
+#define _TX_FIFO    0x800	/* Tx FIFO */
+#define _RXF_OUTP   0x990	/* Rx FIFO OUT pointer        16 Read / Write */
+#define _RXF_INP    0x992	/* Rx FIFO IN pointer         16 Read / Write */
+#define _TXF_OUTP   0x994	/* Tx FIFO OUT pointer        8  Read / Write */
+#define _TXF_INP    0x995	/* Tx FIFO IN pointer         8  Read / Write */
+#define _TXP_CNT    0x996	/* Tx Priority Count          8  Read / Write */
+#define _TXP_PNTR   0x997	/* Tx Priority Pointer        8  Read / Write */
+
+#define PRI_PEND    0x80	/* Priority data pending (bit7, Tx pri cnt) */
+#define TXFIFO_SIZE 255		/* size of Tx FIFO */
+#define RXFIFO_SIZE 1023	/* size of Rx FIFO */
+
+/************************************************************************
+Tx Priority Buffer - Indexed - External - Fixed
+************************************************************************/
+#define _TXP_BUF    0x9C0	/* Tx Priority Buffer  32  Bytes   Read / Write */
+#define TXP_SIZE    0x20	/* 32 bytes */
+
+/************************************************************************
+Channel Register Offsets - Indexed - Internal - Fixed
+************************************************************************/
+
+#define _TX_CTRL    0xFF0	/* Transmit Control               16  Write */
+#define _RX_CTRL    0xFF2	/* Receive Control                 8  Write */
+#define _BAUD       0xFF4	/* Baud Rate                      16  Write */
+#define _CLK_PRE    0xFF6	/* Clock Prescaler                 8  Write */
+
+#define STMBREAK   0x08		/* BREAK */
+#define STMFRAME   0x04		/* framing error */
+#define STMRCVROVR 0x02		/* receiver over run error */
+#define STMPARITY  0x01		/* parity error */
+#define STMERROR   (STMBREAK | STMFRAME | STMPARITY)
+#define STMBREAKH   0x800	/* BREAK */
+#define STMFRAMEH   0x400	/* framing error */
+#define STMRCVROVRH 0x200	/* receiver over run error */
+#define STMPARITYH  0x100	/* parity error */
+#define STMERRORH   (STMBREAKH | STMFRAMEH | STMPARITYH)
+
+#define CTS_ACT   0x20		/* CTS input asserted */
+#define DSR_ACT   0x10		/* DSR input asserted */
+#define CD_ACT    0x08		/* CD input asserted */
+#define TXFIFOMT  0x04		/* Tx FIFO is empty */
+#define TXSHRMT   0x02		/* Tx shift register is empty */
+#define RDA       0x01		/* Rx data available */
+#define DRAINED (TXFIFOMT | TXSHRMT)	/* indicates Tx is drained */
+
+#define STATMODE  0x8000	/* status mode enable bit */
+#define RXFOVERFL 0x2000	/* receive FIFO overflow */
+#define RX2MATCH  0x1000	/* receive compare byte 2 match */
+#define RX1MATCH  0x0800	/* receive compare byte 1 match */
+#define RXBREAK   0x0400	/* received BREAK */
+#define RXFRAME   0x0200	/* received framing error */
+#define RXPARITY  0x0100	/* received parity error */
+#define STATERROR (RXBREAK | RXFRAME | RXPARITY)
+
+#define CTSFC_EN  0x80		/* CTS flow control enable bit */
+#define RTSTOG_EN 0x40		/* RTS toggle enable bit */
+#define TXINT_EN  0x10		/* transmit interrupt enable */
+#define STOP2     0x08		/* enable 2 stop bits (0 = 1 stop) */
+#define PARITY_EN 0x04		/* enable parity (0 = no parity) */
+#define EVEN_PAR  0x02		/* even parity (0 = odd parity) */
+#define DATA8BIT  0x01		/* 8 bit data (0 = 7 bit data) */
+
+#define SETBREAK  0x10		/* send break condition (must clear) */
+#define LOCALLOOP 0x08		/* local loopback set for test */
+#define SET_DTR   0x04		/* assert DTR */
+#define SET_RTS   0x02		/* assert RTS */
+#define TX_ENABLE 0x01		/* enable transmitter */
+
+#define RTSFC_EN  0x40		/* RTS flow control enable */
+#define RXPROC_EN 0x20		/* receive processor enable */
+#define TRIG_NO   0x00		/* Rx FIFO trigger level 0 (no trigger) */
+#define TRIG_1    0x08		/* trigger level 1 char */
+#define TRIG_1_2  0x10		/* trigger level 1/2 */
+#define TRIG_7_8  0x18		/* trigger level 7/8 */
+#define TRIG_MASK 0x18		/* trigger level mask */
+#define SRCINT_EN 0x04		/* special Rx condition interrupt enable */
+#define RXINT_EN  0x02		/* Rx interrupt enable */
+#define MCINT_EN  0x01		/* modem change interrupt enable */
+
+#define RXF_TRIG  0x20		/* Rx FIFO trigger level interrupt */
+#define TXFIFO_MT 0x10		/* Tx FIFO empty interrupt */
+#define SRC_INT   0x08		/* special receive condition interrupt */
+#define DELTA_CD  0x04		/* CD change interrupt */
+#define DELTA_CTS 0x02		/* CTS change interrupt */
+#define DELTA_DSR 0x01		/* DSR change interrupt */
+
+#define REP1W2_EN 0x10		/* replace byte 1 with 2 bytes enable */
+#define IGN2_EN   0x08		/* ignore byte 2 enable */
+#define IGN1_EN   0x04		/* ignore byte 1 enable */
+#define COMP2_EN  0x02		/* compare byte 2 enable */
+#define COMP1_EN  0x01		/* compare byte 1 enable */
+
+#define RESET_ALL 0x80		/* reset AIOP (all channels) */
+#define TXOVERIDE 0x40		/* Transmit software off override */
+#define RESETUART 0x20		/* reset channel's UART */
+#define RESTXFCNT 0x10		/* reset channel's Tx FIFO count register */
+#define RESRXFCNT 0x08		/* reset channel's Rx FIFO count register */
+
+#define INTSTAT0  0x01		/* AIOP 0 interrupt status */
+#define INTSTAT1  0x02		/* AIOP 1 interrupt status */
+#define INTSTAT2  0x04		/* AIOP 2 interrupt status */
+#define INTSTAT3  0x08		/* AIOP 3 interrupt status */
+
+#define INTR_EN   0x08		/* allow interrupts to host */
+#define INT_STROB 0x04		/* strobe and clear interrupt line (EOI) */
+
+/**************************************************************************
+ MUDBAC remapped for PCI
+**************************************************************************/
+
+#define _CFG_INT_PCI  0x40
+#define _PCI_INT_FUNC 0x3A
+
+#define PCI_STROB 0x2000	/* bit 13 of int aiop register */
+#define INTR_EN_PCI   0x0010	/* allow interrupts to host */
+
+/*
+ * Definitions for Universal PCI board registers
+ */
+#define _PCI_9030_INT_CTRL	0x4c          /* Offsets from BAR1 */
+#define _PCI_9030_GPIO_CTRL	0x54
+#define PCI_INT_CTRL_AIOP	0x0001
+#define PCI_GPIO_CTRL_8PORT	0x4000
+#define _PCI_9030_RING_IND	0xc0          /* Offsets from BAR1 */
+
+#define CHAN3_EN  0x08		/* enable AIOP 3 */
+#define CHAN2_EN  0x04		/* enable AIOP 2 */
+#define CHAN1_EN  0x02		/* enable AIOP 1 */
+#define CHAN0_EN  0x01		/* enable AIOP 0 */
+#define FREQ_DIS  0x00
+#define FREQ_274HZ 0x60
+#define FREQ_137HZ 0x50
+#define FREQ_69HZ  0x40
+#define FREQ_34HZ  0x30
+#define FREQ_17HZ  0x20
+#define FREQ_9HZ   0x10
+#define PERIODIC_ONLY 0x80	/* only PERIODIC interrupt */
+
+#define CHANINT_EN 0x0100	/* flags to enable/disable channel ints */
+
+#define RDATASIZE 72
+#define RREGDATASIZE 52
+
+/*
+ * AIOP interrupt bits for ISA/PCI boards and UPCI boards.
+ */
+#define AIOP_INTR_BIT_0		0x0001
+#define AIOP_INTR_BIT_1		0x0002
+#define AIOP_INTR_BIT_2		0x0004
+#define AIOP_INTR_BIT_3		0x0008
+
+#define AIOP_INTR_BITS ( \
+	AIOP_INTR_BIT_0 \
+	| AIOP_INTR_BIT_1 \
+	| AIOP_INTR_BIT_2 \
+	| AIOP_INTR_BIT_3)
+
+#define UPCI_AIOP_INTR_BIT_0	0x0004
+#define UPCI_AIOP_INTR_BIT_1	0x0020
+#define UPCI_AIOP_INTR_BIT_2	0x0100
+#define UPCI_AIOP_INTR_BIT_3	0x0800
+
+#define UPCI_AIOP_INTR_BITS ( \
+	UPCI_AIOP_INTR_BIT_0 \
+	| UPCI_AIOP_INTR_BIT_1 \
+	| UPCI_AIOP_INTR_BIT_2 \
+	| UPCI_AIOP_INTR_BIT_3)
+
+/* Controller level information structure */
+typedef struct {
+	int CtlID;
+	int CtlNum;
+	int BusType;
+	int boardType;
+	int isUPCI;
+	WordIO_t PCIIO;
+	WordIO_t PCIIO2;
+	ByteIO_t MBaseIO;
+	ByteIO_t MReg1IO;
+	ByteIO_t MReg2IO;
+	ByteIO_t MReg3IO;
+	Byte_t MReg2;
+	Byte_t MReg3;
+	int NumAiop;
+	int AltChanRingIndicator;
+	ByteIO_t UPCIRingInd;
+	WordIO_t AiopIO[AIOP_CTL_SIZE];
+	ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE];
+	int AiopID[AIOP_CTL_SIZE];
+	int AiopNumChan[AIOP_CTL_SIZE];
+	Word_t *AiopIntrBits;
+} CONTROLLER_T;
+
+typedef CONTROLLER_T CONTROLLER_t;
+
+/* Channel level information structure */
+typedef struct {
+	CONTROLLER_T *CtlP;
+	int AiopNum;
+	int ChanID;
+	int ChanNum;
+	int rtsToggle;
+
+	ByteIO_t Cmd;
+	ByteIO_t IntChan;
+	ByteIO_t IntMask;
+	DWordIO_t IndexAddr;
+	WordIO_t IndexData;
+
+	WordIO_t TxRxData;
+	WordIO_t ChanStat;
+	WordIO_t TxRxCount;
+	ByteIO_t IntID;
+
+	Word_t TxFIFO;
+	Word_t TxFIFOPtrs;
+	Word_t RxFIFO;
+	Word_t RxFIFOPtrs;
+	Word_t TxPrioCnt;
+	Word_t TxPrioPtr;
+	Word_t TxPrioBuf;
+
+	Byte_t R[RREGDATASIZE];
+
+	Byte_t BaudDiv[4];
+	Byte_t TxControl[4];
+	Byte_t RxControl[4];
+	Byte_t TxEnables[4];
+	Byte_t TxCompare[4];
+	Byte_t TxReplace1[4];
+	Byte_t TxReplace2[4];
+} CHANNEL_T;
+
+typedef CHANNEL_T CHANNEL_t;
+typedef CHANNEL_T *CHANPTR_T;
+
+#define InterfaceModeRS232  0x00
+#define InterfaceModeRS422  0x08
+#define InterfaceModeRS485  0x10
+#define InterfaceModeRS232T 0x18
+
+/***************************************************************************
+Function: sClrBreak
+Purpose:  Stop sending a transmit BREAK signal
+Call:     sClrBreak(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sClrBreak(ChP) \
+do { \
+   (ChP)->TxControl[3] &= ~SETBREAK; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sClrDTR
+Purpose:  Clr the DTR output
+Call:     sClrDTR(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sClrDTR(ChP) \
+do { \
+   (ChP)->TxControl[3] &= ~SET_DTR; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sClrRTS
+Purpose:  Clr the RTS output
+Call:     sClrRTS(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sClrRTS(ChP) \
+do { \
+   if ((ChP)->rtsToggle) break; \
+   (ChP)->TxControl[3] &= ~SET_RTS; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sClrTxXOFF
+Purpose:  Clear any existing transmit software flow control off condition
+Call:     sClrTxXOFF(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sClrTxXOFF(ChP) \
+do { \
+   sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \
+   sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \
+} while (0)
+
+/***************************************************************************
+Function: sCtlNumToCtlPtr
+Purpose:  Convert a controller number to controller structure pointer
+Call:     sCtlNumToCtlPtr(CtlNum)
+          int CtlNum; Controller number
+Return:   CONTROLLER_T *: Ptr to controller structure
+*/
+#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM]
+
+/***************************************************************************
+Function: sControllerEOI
+Purpose:  Strobe the MUDBAC's End Of Interrupt bit.
+Call:     sControllerEOI(CtlP)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+*/
+#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB)
+
+/***************************************************************************
+Function: sPCIControllerEOI
+Purpose:  Strobe the PCI End Of Interrupt bit.
+          For the UPCI boards, toggle the AIOP interrupt enable bit
+	  (this was taken from the Windows driver).
+Call:     sPCIControllerEOI(CtlP)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+*/
+#define sPCIControllerEOI(CTLP) \
+do { \
+    if ((CTLP)->isUPCI) { \
+	Word_t w = sInW((CTLP)->PCIIO); \
+	sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \
+	sOutW((CTLP)->PCIIO, w); \
+    } \
+    else { \
+	sOutW((CTLP)->PCIIO, PCI_STROB); \
+    } \
+} while (0)
+
+/***************************************************************************
+Function: sDisAiop
+Purpose:  Disable I/O access to an AIOP
+Call:     sDisAiop(CltP)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int AiopNum; Number of AIOP on controller
+*/
+#define sDisAiop(CTLP,AIOPNUM) \
+do { \
+   (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \
+   sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
+} while (0)
+
+/***************************************************************************
+Function: sDisCTSFlowCtl
+Purpose:  Disable output flow control using CTS
+Call:     sDisCTSFlowCtl(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sDisCTSFlowCtl(ChP) \
+do { \
+   (ChP)->TxControl[2] &= ~CTSFC_EN; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sDisIXANY
+Purpose:  Disable IXANY Software Flow Control
+Call:     sDisIXANY(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sDisIXANY(ChP) \
+do { \
+   (ChP)->R[0x0e] = 0x86; \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
+} while (0)
+
+/***************************************************************************
+Function: DisParity
+Purpose:  Disable parity
+Call:     sDisParity(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: Function sSetParity() can be used in place of functions sEnParity(),
+          sDisParity(), sSetOddParity(), and sSetEvenParity().
+*/
+#define sDisParity(ChP) \
+do { \
+   (ChP)->TxControl[2] &= ~PARITY_EN; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sDisRTSToggle
+Purpose:  Disable RTS toggle
+Call:     sDisRTSToggle(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sDisRTSToggle(ChP) \
+do { \
+   (ChP)->TxControl[2] &= ~RTSTOG_EN; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+   (ChP)->rtsToggle = 0; \
+} while (0)
+
+/***************************************************************************
+Function: sDisRxFIFO
+Purpose:  Disable Rx FIFO
+Call:     sDisRxFIFO(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sDisRxFIFO(ChP) \
+do { \
+   (ChP)->R[0x32] = 0x0a; \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
+} while (0)
+
+/***************************************************************************
+Function: sDisRxStatusMode
+Purpose:  Disable the Rx status mode
+Call:     sDisRxStatusMode(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: This takes the channel out of the receive status mode.  All
+          subsequent reads of receive data using sReadRxWord() will return
+          two data bytes.
+*/
+#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0)
+
+/***************************************************************************
+Function: sDisTransmit
+Purpose:  Disable transmit
+Call:     sDisTransmit(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+          This disables movement of Tx data from the Tx FIFO into the 1 byte
+          Tx buffer.  Therefore there could be up to a 2 byte latency
+          between the time sDisTransmit() is called and the transmit buffer
+          and transmit shift register going completely empty.
+*/
+#define sDisTransmit(ChP) \
+do { \
+   (ChP)->TxControl[3] &= ~TX_ENABLE; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sDisTxSoftFlowCtl
+Purpose:  Disable Tx Software Flow Control
+Call:     sDisTxSoftFlowCtl(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sDisTxSoftFlowCtl(ChP) \
+do { \
+   (ChP)->R[0x06] = 0x8a; \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
+} while (0)
+
+/***************************************************************************
+Function: sEnAiop
+Purpose:  Enable I/O access to an AIOP
+Call:     sEnAiop(CltP)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int AiopNum; Number of AIOP on controller
+*/
+#define sEnAiop(CTLP,AIOPNUM) \
+do { \
+   (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \
+   sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
+} while (0)
+
+/***************************************************************************
+Function: sEnCTSFlowCtl
+Purpose:  Enable output flow control using CTS
+Call:     sEnCTSFlowCtl(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sEnCTSFlowCtl(ChP) \
+do { \
+   (ChP)->TxControl[2] |= CTSFC_EN; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sEnIXANY
+Purpose:  Enable IXANY Software Flow Control
+Call:     sEnIXANY(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sEnIXANY(ChP) \
+do { \
+   (ChP)->R[0x0e] = 0x21; \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
+} while (0)
+
+/***************************************************************************
+Function: EnParity
+Purpose:  Enable parity
+Call:     sEnParity(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: Function sSetParity() can be used in place of functions sEnParity(),
+          sDisParity(), sSetOddParity(), and sSetEvenParity().
+
+Warnings: Before enabling parity odd or even parity should be chosen using
+          functions sSetOddParity() or sSetEvenParity().
+*/
+#define sEnParity(ChP) \
+do { \
+   (ChP)->TxControl[2] |= PARITY_EN; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sEnRTSToggle
+Purpose:  Enable RTS toggle
+Call:     sEnRTSToggle(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: This function will disable RTS flow control and clear the RTS
+          line to allow operation of RTS toggle.
+*/
+#define sEnRTSToggle(ChP) \
+do { \
+   (ChP)->RxControl[2] &= ~RTSFC_EN; \
+   out32((ChP)->IndexAddr,(ChP)->RxControl); \
+   (ChP)->TxControl[2] |= RTSTOG_EN; \
+   (ChP)->TxControl[3] &= ~SET_RTS; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+   (ChP)->rtsToggle = 1; \
+} while (0)
+
+/***************************************************************************
+Function: sEnRxFIFO
+Purpose:  Enable Rx FIFO
+Call:     sEnRxFIFO(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sEnRxFIFO(ChP) \
+do { \
+   (ChP)->R[0x32] = 0x08; \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
+} while (0)
+
+/***************************************************************************
+Function: sEnRxProcessor
+Purpose:  Enable the receive processor
+Call:     sEnRxProcessor(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: This function is used to start the receive processor.  When
+          the channel is in the reset state the receive processor is not
+          running.  This is done to prevent the receive processor from
+          executing invalid microcode instructions prior to the
+          downloading of the microcode.
+
+Warnings: This function must be called after valid microcode has been
+          downloaded to the AIOP, and it must not be called before the
+          microcode has been downloaded.
+*/
+#define sEnRxProcessor(ChP) \
+do { \
+   (ChP)->RxControl[2] |= RXPROC_EN; \
+   out32((ChP)->IndexAddr,(ChP)->RxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sEnRxStatusMode
+Purpose:  Enable the Rx status mode
+Call:     sEnRxStatusMode(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: This places the channel in the receive status mode.  All subsequent
+          reads of receive data using sReadRxWord() will return a data byte
+          in the low word and a status byte in the high word.
+
+*/
+#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE)
+
+/***************************************************************************
+Function: sEnTransmit
+Purpose:  Enable transmit
+Call:     sEnTransmit(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sEnTransmit(ChP) \
+do { \
+   (ChP)->TxControl[3] |= TX_ENABLE; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sEnTxSoftFlowCtl
+Purpose:  Enable Tx Software Flow Control
+Call:     sEnTxSoftFlowCtl(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sEnTxSoftFlowCtl(ChP) \
+do { \
+   (ChP)->R[0x06] = 0xc5; \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
+} while (0)
+
+/***************************************************************************
+Function: sGetAiopIntStatus
+Purpose:  Get the AIOP interrupt status
+Call:     sGetAiopIntStatus(CtlP,AiopNum)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int AiopNum; AIOP number
+Return:   Byte_t: The AIOP interrupt status.  Bits 0 through 7
+                         represent channels 0 through 7 respectively.  If a
+                         bit is set that channel is interrupting.
+*/
+#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM])
+
+/***************************************************************************
+Function: sGetAiopNumChan
+Purpose:  Get the number of channels supported by an AIOP
+Call:     sGetAiopNumChan(CtlP,AiopNum)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+          int AiopNum; AIOP number
+Return:   int: The number of channels supported by the AIOP
+*/
+#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM]
+
+/***************************************************************************
+Function: sGetChanIntID
+Purpose:  Get a channel's interrupt identification byte
+Call:     sGetChanIntID(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   Byte_t: The channel interrupt ID.  Can be any
+             combination of the following flags:
+                RXF_TRIG:     Rx FIFO trigger level interrupt
+                TXFIFO_MT:    Tx FIFO empty interrupt
+                SRC_INT:      Special receive condition interrupt
+                DELTA_CD:     CD change interrupt
+                DELTA_CTS:    CTS change interrupt
+                DELTA_DSR:    DSR change interrupt
+*/
+#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR))
+
+/***************************************************************************
+Function: sGetChanNum
+Purpose:  Get the number of a channel within an AIOP
+Call:     sGetChanNum(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   int: Channel number within AIOP, or NULLCHAN if channel does
+               not exist.
+*/
+#define sGetChanNum(ChP) (ChP)->ChanNum
+
+/***************************************************************************
+Function: sGetChanStatus
+Purpose:  Get the channel status
+Call:     sGetChanStatus(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   Word_t: The channel status.  Can be any combination of
+             the following flags:
+                LOW BYTE FLAGS
+                CTS_ACT:      CTS input asserted
+                DSR_ACT:      DSR input asserted
+                CD_ACT:       CD input asserted
+                TXFIFOMT:     Tx FIFO is empty
+                TXSHRMT:      Tx shift register is empty
+                RDA:          Rx data available
+
+                HIGH BYTE FLAGS
+                STATMODE:     status mode enable bit
+                RXFOVERFL:    receive FIFO overflow
+                RX2MATCH:     receive compare byte 2 match
+                RX1MATCH:     receive compare byte 1 match
+                RXBREAK:      received BREAK
+                RXFRAME:      received framing error
+                RXPARITY:     received parity error
+Warnings: This function will clear the high byte flags in the Channel
+          Status Register.
+*/
+#define sGetChanStatus(ChP) sInW((ChP)->ChanStat)
+
+/***************************************************************************
+Function: sGetChanStatusLo
+Purpose:  Get the low byte only of the channel status
+Call:     sGetChanStatusLo(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   Byte_t: The channel status low byte.  Can be any combination
+             of the following flags:
+                CTS_ACT:      CTS input asserted
+                DSR_ACT:      DSR input asserted
+                CD_ACT:       CD input asserted
+                TXFIFOMT:     Tx FIFO is empty
+                TXSHRMT:      Tx shift register is empty
+                RDA:          Rx data available
+*/
+#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat)
+
+/**********************************************************************
+ * Get RI status of channel
+ * Defined as a function in rocket.c   -aes
+ */
+#if 0
+#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \
+                          (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \
+                            (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \
+                               (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \
+                             0))
+#endif
+
+/***************************************************************************
+Function: sGetControllerIntStatus
+Purpose:  Get the controller interrupt status
+Call:     sGetControllerIntStatus(CtlP)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+Return:   Byte_t: The controller interrupt status in the lower 4
+                         bits.  Bits 0 through 3 represent AIOP's 0
+                         through 3 respectively.  If a bit is set that
+                         AIOP is interrupting.  Bits 4 through 7 will
+                         always be cleared.
+*/
+#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f)
+
+/***************************************************************************
+Function: sPCIGetControllerIntStatus
+Purpose:  Get the controller interrupt status
+Call:     sPCIGetControllerIntStatus(CtlP)
+          CONTROLLER_T *CtlP; Ptr to controller structure
+Return:   unsigned char: The controller interrupt status in the lower 4
+                         bits and bit 4.  Bits 0 through 3 represent AIOP's 0
+                         through 3 respectively. Bit 4 is set if the int 
+			 was generated from periodic. If a bit is set the
+			 AIOP is interrupting.
+*/
+#define sPCIGetControllerIntStatus(CTLP) \
+	((CTLP)->isUPCI ? \
+	  (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \
+	  ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS))
+
+/***************************************************************************
+
+Function: sGetRxCnt
+Purpose:  Get the number of data bytes in the Rx FIFO
+Call:     sGetRxCnt(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   int: The number of data bytes in the Rx FIFO.
+Comments: Byte read of count register is required to obtain Rx count.
+
+*/
+#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount)
+
+/***************************************************************************
+Function: sGetTxCnt
+Purpose:  Get the number of data bytes in the Tx FIFO
+Call:     sGetTxCnt(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   Byte_t: The number of data bytes in the Tx FIFO.
+Comments: Byte read of count register is required to obtain Tx count.
+
+*/
+#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount)
+
+/*****************************************************************************
+Function: sGetTxRxDataIO
+Purpose:  Get the I/O address of a channel's TxRx Data register
+Call:     sGetTxRxDataIO(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Return:   WordIO_t: I/O address of a channel's TxRx Data register
+*/
+#define sGetTxRxDataIO(ChP) (ChP)->TxRxData
+
+/***************************************************************************
+Function: sInitChanDefaults
+Purpose:  Initialize a channel structure to it's default state.
+Call:     sInitChanDefaults(ChP)
+          CHANNEL_T *ChP; Ptr to the channel structure
+Comments: This function must be called once for every channel structure
+          that exists before any other SSCI calls can be made.
+
+*/
+#define sInitChanDefaults(ChP) \
+do { \
+   (ChP)->CtlP = NULLCTLPTR; \
+   (ChP)->AiopNum = NULLAIOP; \
+   (ChP)->ChanID = AIOPID_NULL; \
+   (ChP)->ChanNum = NULLCHAN; \
+} while (0)
+
+/***************************************************************************
+Function: sResetAiopByNum
+Purpose:  Reset the AIOP by number
+Call:     sResetAiopByNum(CTLP,AIOPNUM)
+	CONTROLLER_T CTLP; Ptr to controller structure
+	AIOPNUM; AIOP index 
+*/
+#define sResetAiopByNum(CTLP,AIOPNUM) \
+do { \
+   sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \
+   sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \
+} while (0)
+
+/***************************************************************************
+Function: sSendBreak
+Purpose:  Send a transmit BREAK signal
+Call:     sSendBreak(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSendBreak(ChP) \
+do { \
+   (ChP)->TxControl[3] |= SETBREAK; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetBaud
+Purpose:  Set baud rate
+Call:     sSetBaud(ChP,Divisor)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Word_t Divisor; 16 bit baud rate divisor for channel
+*/
+#define sSetBaud(ChP,DIVISOR) \
+do { \
+   (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \
+   (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \
+   out32((ChP)->IndexAddr,(ChP)->BaudDiv); \
+} while (0)
+
+/***************************************************************************
+Function: sSetData7
+Purpose:  Set data bits to 7
+Call:     sSetData7(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSetData7(ChP) \
+do { \
+   (ChP)->TxControl[2] &= ~DATA8BIT; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetData8
+Purpose:  Set data bits to 8
+Call:     sSetData8(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSetData8(ChP) \
+do { \
+   (ChP)->TxControl[2] |= DATA8BIT; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetDTR
+Purpose:  Set the DTR output
+Call:     sSetDTR(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSetDTR(ChP) \
+do { \
+   (ChP)->TxControl[3] |= SET_DTR; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetEvenParity
+Purpose:  Set even parity
+Call:     sSetEvenParity(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: Function sSetParity() can be used in place of functions sEnParity(),
+          sDisParity(), sSetOddParity(), and sSetEvenParity().
+
+Warnings: This function has no effect unless parity is enabled with function
+          sEnParity().
+*/
+#define sSetEvenParity(ChP) \
+do { \
+   (ChP)->TxControl[2] |= EVEN_PAR; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetOddParity
+Purpose:  Set odd parity
+Call:     sSetOddParity(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: Function sSetParity() can be used in place of functions sEnParity(),
+          sDisParity(), sSetOddParity(), and sSetEvenParity().
+
+Warnings: This function has no effect unless parity is enabled with function
+          sEnParity().
+*/
+#define sSetOddParity(ChP) \
+do { \
+   (ChP)->TxControl[2] &= ~EVEN_PAR; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetRTS
+Purpose:  Set the RTS output
+Call:     sSetRTS(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSetRTS(ChP) \
+do { \
+   if ((ChP)->rtsToggle) break; \
+   (ChP)->TxControl[3] |= SET_RTS; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetRxTrigger
+Purpose:  Set the Rx FIFO trigger level
+Call:     sSetRxProcessor(ChP,Level)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Byte_t Level; Number of characters in Rx FIFO at which the
+             interrupt will be generated.  Can be any of the following flags:
+
+             TRIG_NO:   no trigger
+             TRIG_1:    1 character in FIFO
+             TRIG_1_2:  FIFO 1/2 full
+             TRIG_7_8:  FIFO 7/8 full
+Comments: An interrupt will be generated when the trigger level is reached
+          only if function sEnInterrupt() has been called with flag
+          RXINT_EN set.  The RXF_TRIG flag in the Interrupt Idenfification
+          register will be set whenever the trigger level is reached
+          regardless of the setting of RXINT_EN.
+
+*/
+#define sSetRxTrigger(ChP,LEVEL) \
+do { \
+   (ChP)->RxControl[2] &= ~TRIG_MASK; \
+   (ChP)->RxControl[2] |= LEVEL; \
+   out32((ChP)->IndexAddr,(ChP)->RxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetStop1
+Purpose:  Set stop bits to 1
+Call:     sSetStop1(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSetStop1(ChP) \
+do { \
+   (ChP)->TxControl[2] &= ~STOP2; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetStop2
+Purpose:  Set stop bits to 2
+Call:     sSetStop2(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+*/
+#define sSetStop2(ChP) \
+do { \
+   (ChP)->TxControl[2] |= STOP2; \
+   out32((ChP)->IndexAddr,(ChP)->TxControl); \
+} while (0)
+
+/***************************************************************************
+Function: sSetTxXOFFChar
+Purpose:  Set the Tx XOFF flow control character
+Call:     sSetTxXOFFChar(ChP,Ch)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Byte_t Ch; The value to set the Tx XOFF character to
+*/
+#define sSetTxXOFFChar(ChP,CH) \
+do { \
+   (ChP)->R[0x07] = (CH); \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
+} while (0)
+
+/***************************************************************************
+Function: sSetTxXONChar
+Purpose:  Set the Tx XON flow control character
+Call:     sSetTxXONChar(ChP,Ch)
+          CHANNEL_T *ChP; Ptr to channel structure
+          Byte_t Ch; The value to set the Tx XON character to
+*/
+#define sSetTxXONChar(ChP,CH) \
+do { \
+   (ChP)->R[0x0b] = (CH); \
+   out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \
+} while (0)
+
+/***************************************************************************
+Function: sStartRxProcessor
+Purpose:  Start a channel's receive processor
+Call:     sStartRxProcessor(ChP)
+          CHANNEL_T *ChP; Ptr to channel structure
+Comments: This function is used to start a Rx processor after it was
+          stopped with sStopRxProcessor() or sStopSWInFlowCtl().  It
+          will restart both the Rx processor and software input flow control.
+
+*/
+#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0])
+
+/***************************************************************************
+Function: sWriteTxByte
+Purpose:  Write a transmit data byte to a channel.
+          ByteIO_t io: Channel transmit register I/O address.  This can
+                           be obtained with sGetTxRxDataIO().
+          Byte_t Data; The transmit data byte.
+Warnings: This function writes the data byte without checking to see if
+          sMaxTxSize is exceeded in the Tx FIFO.
+*/
+#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
+
+/*
+ * Begin Linux specific definitions for the Rocketport driver
+ *
+ * This code is Copyright Theodore Ts'o, 1995-1997
+ */
+
+struct r_port {
+	int magic;
+	struct tty_port port;
+	int line;
+	int flags;		/* Don't yet match the ASY_ flags!! */
+	unsigned int board:3;
+	unsigned int aiop:2;
+	unsigned int chan:3;
+	CONTROLLER_t *ctlp;
+	CHANNEL_t channel;
+	int intmask;
+	int xmit_fifo_room;	/* room in xmit fifo */
+	unsigned char *xmit_buf;
+	int xmit_head;
+	int xmit_tail;
+	int xmit_cnt;
+	int cd_status;
+	int ignore_status_mask;
+	int read_status_mask;
+	int cps;
+
+	struct completion close_wait;	/* Not yet matching the core */
+	spinlock_t slock;
+	struct mutex write_mtx;
+};
+
+#define RPORT_MAGIC 0x525001
+
+#define NUM_BOARDS 8
+#define MAX_RP_PORTS (32*NUM_BOARDS)
+
+/*
+ * The size of the xmit buffer is 1 page, or 4096 bytes
+ */
+#define XMIT_BUF_SIZE 4096
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/*
+ * Assigned major numbers for the Comtrol Rocketport
+ */
+#define TTY_ROCKET_MAJOR	46
+#define CUA_ROCKET_MAJOR	47
+
+#ifdef PCI_VENDOR_ID_RP
+#undef PCI_VENDOR_ID_RP
+#undef PCI_DEVICE_ID_RP8OCTA
+#undef PCI_DEVICE_ID_RP8INTF
+#undef PCI_DEVICE_ID_RP16INTF
+#undef PCI_DEVICE_ID_RP32INTF
+#undef PCI_DEVICE_ID_URP8OCTA
+#undef PCI_DEVICE_ID_URP8INTF
+#undef PCI_DEVICE_ID_URP16INTF
+#undef PCI_DEVICE_ID_CRP16INTF
+#undef PCI_DEVICE_ID_URP32INTF
+#endif
+
+/*  Comtrol PCI Vendor ID */
+#define PCI_VENDOR_ID_RP		0x11fe
+
+/*  Comtrol Device ID's */
+#define PCI_DEVICE_ID_RP32INTF		0x0001	/* Rocketport 32 port w/external I/F     */
+#define PCI_DEVICE_ID_RP8INTF		0x0002	/* Rocketport 8 port w/external I/F      */
+#define PCI_DEVICE_ID_RP16INTF		0x0003	/* Rocketport 16 port w/external I/F     */
+#define PCI_DEVICE_ID_RP4QUAD		0x0004	/* Rocketport 4 port w/quad cable        */
+#define PCI_DEVICE_ID_RP8OCTA		0x0005	/* Rocketport 8 port w/octa cable        */
+#define PCI_DEVICE_ID_RP8J		0x0006	/* Rocketport 8 port w/RJ11 connectors   */
+#define PCI_DEVICE_ID_RP4J		0x0007	/* Rocketport 4 port w/RJ11 connectors   */
+#define PCI_DEVICE_ID_RP8SNI		0x0008	/* Rocketport 8 port w/ DB78 SNI (Siemens) connector */
+#define PCI_DEVICE_ID_RP16SNI		0x0009	/* Rocketport 16 port w/ DB78 SNI (Siemens) connector   */
+#define PCI_DEVICE_ID_RPP4		0x000A	/* Rocketport Plus 4 port                */
+#define PCI_DEVICE_ID_RPP8		0x000B	/* Rocketport Plus 8 port                */
+#define PCI_DEVICE_ID_RP6M		0x000C	/* RocketModem 6 port                    */
+#define PCI_DEVICE_ID_RP4M		0x000D	/* RocketModem 4 port                    */
+#define PCI_DEVICE_ID_RP2_232           0x000E	/* Rocketport Plus 2 port RS232          */
+#define PCI_DEVICE_ID_RP2_422           0x000F	/* Rocketport Plus 2 port RS422          */ 
+
+/* Universal PCI boards  */
+#define PCI_DEVICE_ID_URP32INTF		0x0801	/* Rocketport UPCI 32 port w/external I/F */ 
+#define PCI_DEVICE_ID_URP8INTF		0x0802	/* Rocketport UPCI 8 port w/external I/F  */
+#define PCI_DEVICE_ID_URP16INTF		0x0803	/* Rocketport UPCI 16 port w/external I/F */
+#define PCI_DEVICE_ID_URP8OCTA		0x0805	/* Rocketport UPCI 8 port w/octa cable    */
+#define PCI_DEVICE_ID_UPCI_RM3_8PORT    0x080C	/* Rocketmodem III 8 port                 */
+#define PCI_DEVICE_ID_UPCI_RM3_4PORT    0x080D	/* Rocketmodem III 4 port                 */
+
+/* Compact PCI device */ 
+#define PCI_DEVICE_ID_CRP16INTF		0x0903	/* Rocketport Compact PCI 16 port w/external I/F */
+
diff --git a/drivers/tty/serial/68328serial.c b/drivers/tty/serial/68328serial.c
index de0160e..d5bfd41 100644
--- a/drivers/tty/serial/68328serial.c
+++ b/drivers/tty/serial/68328serial.c
@@ -393,28 +393,6 @@ static void do_softint(struct work_struct *work)
 #endif   
 }
 
-/*
- * This routine is called from the scheduler tqueue when the interrupt
- * routine has signalled that a hangup has occurred.  The path of
- * hangup processing is:
- *
- * 	serial interrupt routine -> (scheduler tqueue) ->
- * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
- * 
- */
-static void do_serial_hangup(struct work_struct *work)
-{
-	struct m68k_serial	*info = container_of(work, struct m68k_serial, tqueue_hangup);
-	struct tty_struct	*tty;
-	
-	tty = info->tty;
-	if (!tty)
-		return;
-
-	tty_hangup(tty);
-}
-
-
 static int startup(struct m68k_serial * info)
 {
 	m68328_uart *uart = &uart_addr[info->line];
@@ -967,7 +945,7 @@ static void send_break(struct m68k_serial * info, unsigned int duration)
         local_irq_restore(flags);
 }
 
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
+static int rs_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct m68k_serial * info = (struct m68k_serial *)tty->driver_data;
@@ -1347,7 +1325,6 @@ rs68328_init(void)
 	    info->count = 0;
 	    info->blocked_open = 0;
 	    INIT_WORK(&info->tqueue, do_softint);
-	    INIT_WORK(&info->tqueue_hangup, do_serial_hangup);
 	    init_waitqueue_head(&info->open_wait);
 	    init_waitqueue_head(&info->close_wait);
 	    info->line = i;
diff --git a/drivers/tty/serial/68328serial.h b/drivers/tty/serial/68328serial.h
index 664ceb0..8c9c3c0 100644
--- a/drivers/tty/serial/68328serial.h
+++ b/drivers/tty/serial/68328serial.h
@@ -159,7 +159,6 @@ struct m68k_serial {
 	int			xmit_tail;
 	int			xmit_cnt;
 	struct work_struct	tqueue;
-	struct work_struct	tqueue_hangup;
 	wait_queue_head_t	open_wait;
 	wait_queue_head_t	close_wait;
 };
diff --git a/drivers/tty/serial/68360serial.c b/drivers/tty/serial/68360serial.c
index bc21eea..0a3e878 100644
--- a/drivers/tty/serial/68360serial.c
+++ b/drivers/tty/serial/68360serial.c
@@ -1240,7 +1240,7 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value)
 }
 #endif
 
-static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
+static int rs_360_tiocmget(struct tty_struct *tty)
 {
 	ser_info_t *info = (ser_info_t *)tty->driver_data;
 	unsigned int result = 0;
@@ -1271,7 +1271,7 @@ static int rs_360_tiocmget(struct tty_struct *tty, struct file *file)
 	return result;
 }
 
-static int rs_360_tiocmset(struct tty_struct *tty, struct file *file,
+static int rs_360_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear)
 {
 #ifdef modem_control
@@ -1405,7 +1405,7 @@ static int rs_360_get_icount(struct tty_struct *tty,
 	return 0;
 }
 
-static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
+static int rs_360_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
 	int error;
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c
index 3975df6..b3b881b 100644
--- a/drivers/tty/serial/8250.c
+++ b/drivers/tty/serial/8250.c
@@ -954,6 +954,23 @@ static int broken_efr(struct uart_8250_port *up)
 	return 0;
 }
 
+static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+{
+	unsigned char status;
+
+	status = serial_in(up, 0x04); /* EXCR2 */
+#define PRESL(x) ((x) & 0x30)
+	if (PRESL(status) == 0x10) {
+		/* already in high speed mode */
+		return 0;
+	} else {
+		status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
+		status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
+		serial_outp(up, 0x04, status);
+	}
+	return 1;
+}
+
 /*
  * We know that the chip has FIFOs.  Does it have an EFR?  The
  * EFR is located in the same register position as the IIR and
@@ -1025,12 +1042,8 @@ static void autoconfig_16550a(struct uart_8250_port *up)
 			quot = serial_dl_read(up);
 			quot <<= 3;
 
-			status1 = serial_in(up, 0x04); /* EXCR2 */
-			status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-			status1 |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
-			serial_outp(up, 0x04, status1);
-
-			serial_dl_write(up, quot);
+			if (ns16550a_goto_highspeed(up))
+				serial_dl_write(up, quot);
 
 			serial_outp(up, UART_LCR, 0);
 
@@ -3025,17 +3038,13 @@ void serial8250_resume_port(int line)
 	struct uart_8250_port *up = &serial8250_ports[line];
 
 	if (up->capabilities & UART_NATSEMI) {
-		unsigned char tmp;
-
 		/* Ensure it's still in high speed mode */
 		serial_outp(up, UART_LCR, 0xE0);
 
-		tmp = serial_in(up, 0x04); /* EXCR2 */
-		tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
-		tmp |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
-		serial_outp(up, 0x04, tmp);
+		ns16550a_goto_highspeed(up);
 
 		serial_outp(up, UART_LCR, 0);
+		up->port.uartclk = 921600*16;
 	}
 	uart_resume_port(&serial8250_reg, &up->port);
 }
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 2b83346..e1aee37 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -537,8 +537,8 @@ config SERIAL_S3C6400
 
 config SERIAL_S5PV210
 	tristate "Samsung S5PV210 Serial port support"
-	depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_S5PV310)
-	select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_S5PV310)
+	depends on SERIAL_SAMSUNG && (CPU_S5PV210 || CPU_S5P6442 || CPU_EXYNOS4210)
+	select SERIAL_SAMSUNG_UARTS_4 if (CPU_S5PV210 || CPU_EXYNOS4210)
 	default y
 	help
 	  Serial port support for Samsung's S5P Family of SoC's
@@ -1110,29 +1110,6 @@ config SERIAL_PMACZILOG_CONSOLE
 	  on your (Power)Mac as the console, you can do so by answering
 	  Y to this option.
 
-config SERIAL_LH7A40X
-	tristate "Sharp LH7A40X embedded UART support"
-	depends on ARM && ARCH_LH7A40X
-	select SERIAL_CORE
-	help
-	  This enables support for the three on-board UARTs of the
-	  Sharp LH7A40X series CPUs.  Choose Y or M.
-
-config SERIAL_LH7A40X_CONSOLE
-	bool "Support for console on Sharp LH7A40X serial port"
-	depends on SERIAL_LH7A40X=y
-	select SERIAL_CORE_CONSOLE
-	help
-	  Say Y here if you wish to use one of the serial ports as the
-	  system console--the system console is the device which
-	  receives all kernel messages and warnings and which allows
-	  logins in single user mode.
-
-	  Even if you say Y here, the currently visible framebuffer console
-	  (/dev/tty0) will still be used as the default system console, but
-	  you can alter that using a kernel command line, for example
-	  "console=ttyAM1".
-
 config SERIAL_CPM
 	tristate "CPM SCC/SMC serial port support"
 	depends on CPM2 || 8xx
@@ -1319,6 +1296,18 @@ config SERIAL_MSM_CONSOLE
 	depends on SERIAL_MSM=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_MSM_HS
+	tristate "MSM UART High Speed: Serial Driver"
+	depends on ARCH_MSM
+	select SERIAL_CORE
+	help
+	  If you have a machine based on MSM family of SoCs, you
+	  can enable its onboard high speed serial port by enabling
+	  this option.
+
+	  Choose M here to compile it as a module. The module will be
+	  called msm_serial_hs.
+
 config SERIAL_VT8500
 	bool "VIA VT8500 on-chip serial port support"
 	depends on ARM && ARCH_VT8500
@@ -1588,12 +1577,39 @@ config SERIAL_IFX6X60
 	  Support for the IFX6x60 modem devices on Intel MID platforms.
 
 config SERIAL_PCH_UART
-	tristate "Intel EG20T PCH UART"
-	depends on PCI && DMADEVICES
+	tristate "Intel EG20T PCH UART/OKI SEMICONDUCTOR ML7213 IOH"
+	depends on PCI
 	select SERIAL_CORE
-	select PCH_DMA
 	help
 	  This driver is for PCH(Platform controller Hub) UART of Intel EG20T
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
 	  Enabling PCH_DMA, this PCH UART works as DMA mode.
+
+	  This driver also can be used for OKI SEMICONDUCTOR ML7213 IOH(Input/
+	  Output Hub) which is for IVI(In-Vehicle Infotainment) use.
+	  ML7213 is companion chip for Intel Atom E6xx series.
+	  ML7213 is completely compatible for Intel EG20T PCH.
+
+config SERIAL_MSM_SMD
+	bool "Enable tty device interface for some SMD ports"
+	default n
+	depends on MSM_SMD
+	help
+	  Enables userspace clients to read and write to some streaming SMD
+	  ports via tty device interface for MSM chipset.
+
+config SERIAL_MXS_AUART
+	depends on ARCH_MXS
+	tristate "MXS AUART support"
+	select SERIAL_CORE
+	help
+	  This driver supports the MXS Application UART (AUART) port.
+
+config SERIAL_MXS_AUART_CONSOLE
+	bool "MXS AUART console support"
+	depends on SERIAL_MXS_AUART=y
+	select SERIAL_CORE_CONSOLE
+	help
+	  Enable a MXS AUART port to be the system console.
+
 endmenu
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index 8ea92e9..fee0690 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_SERIAL_68328) += 68328serial.o
 obj-$(CONFIG_SERIAL_68360) += 68360serial.o
 obj-$(CONFIG_SERIAL_MCF) += mcf.o
 obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o
-obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o
 obj-$(CONFIG_SERIAL_DZ) += dz.o
 obj-$(CONFIG_SERIAL_ZS) += zs.o
 obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
@@ -76,6 +75,7 @@ obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
 obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
 obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
 obj-$(CONFIG_SERIAL_MSM) += msm_serial.o
+obj-$(CONFIG_SERIAL_MSM_HS) += msm_serial_hs.o
 obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
 obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o
@@ -92,3 +92,5 @@ obj-$(CONFIG_SERIAL_MRST_MAX3110)	+= mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
 obj-$(CONFIG_SERIAL_IFX6X60)  	+= ifx6x60.o
 obj-$(CONFIG_SERIAL_PCH_UART)	+= pch_uart.o
+obj-$(CONFIG_SERIAL_MSM_SMD)	+= msm_smd_tty.o
+obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index f9b49b5..60e049b 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -305,28 +305,6 @@ static struct altera_jtaguart altera_jtaguart_ports[ALTERA_JTAGUART_MAXPORTS];
 
 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
 
-int __init early_altera_jtaguart_setup(struct altera_jtaguart_platform_uart
-				       *platp)
-{
-	struct uart_port *port;
-	int i;
-
-	for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
-		port = &altera_jtaguart_ports[i].port;
-
-		port->line = i;
-		port->type = PORT_ALTERA_JTAGUART;
-		port->mapbase = platp[i].mapbase;
-		port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
-		port->iotype = SERIAL_IO_MEM;
-		port->irq = platp[i].irq;
-		port->flags = ASYNC_BOOT_AUTOCONF;
-		port->ops = &altera_jtaguart_ops;
-	}
-
-	return 0;
-}
-
 #if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
 static void altera_jtaguart_console_putc(struct console *co, const char c)
 {
@@ -384,7 +362,7 @@ static int __init altera_jtaguart_console_setup(struct console *co,
 	if (co->index < 0 || co->index >= ALTERA_JTAGUART_MAXPORTS)
 		return -EINVAL;
 	port = &altera_jtaguart_ports[co->index].port;
-	if (port->membase == 0)
+	if (port->membase == NULL)
 		return -ENODEV;
 	return 0;
 }
@@ -431,22 +409,45 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
 {
 	struct altera_jtaguart_platform_uart *platp = pdev->dev.platform_data;
 	struct uart_port *port;
-	int i;
+	struct resource *res_irq, *res_mem;
+	int i = pdev->id;
 
-	for (i = 0; i < ALTERA_JTAGUART_MAXPORTS && platp[i].mapbase; i++) {
-		port = &altera_jtaguart_ports[i].port;
+	/* -1 emphasizes that the platform must have one port, no .N suffix */
+	if (i == -1)
+		i = 0;
 
-		port->line = i;
-		port->type = PORT_ALTERA_JTAGUART;
-		port->mapbase = platp[i].mapbase;
-		port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
-		port->iotype = SERIAL_IO_MEM;
-		port->irq = platp[i].irq;
-		port->ops = &altera_jtaguart_ops;
-		port->flags = ASYNC_BOOT_AUTOCONF;
+	if (i >= ALTERA_JTAGUART_MAXPORTS)
+		return -EINVAL;
 
-		uart_add_one_port(&altera_jtaguart_driver, port);
-	}
+	port = &altera_jtaguart_ports[i].port;
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res_mem)
+		port->mapbase = res_mem->start;
+	else if (platp)
+		port->mapbase = platp->mapbase;
+	else
+		return -ENODEV;
+
+	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res_irq)
+		port->irq = res_irq->start;
+	else if (platp)
+		port->irq = platp->irq;
+	else
+		return -ENODEV;
+
+	port->membase = ioremap(port->mapbase, ALTERA_JTAGUART_SIZE);
+	if (!port->membase)
+		return -ENOMEM;
+
+	port->line = i;
+	port->type = PORT_ALTERA_JTAGUART;
+	port->iotype = SERIAL_IO_MEM;
+	port->ops = &altera_jtaguart_ops;
+	port->flags = UPF_BOOT_AUTOCONF;
+
+	uart_add_one_port(&altera_jtaguart_driver, port);
 
 	return 0;
 }
@@ -454,23 +455,34 @@ static int __devinit altera_jtaguart_probe(struct platform_device *pdev)
 static int __devexit altera_jtaguart_remove(struct platform_device *pdev)
 {
 	struct uart_port *port;
-	int i;
+	int i = pdev->id;
 
-	for (i = 0; i < ALTERA_JTAGUART_MAXPORTS; i++) {
-		port = &altera_jtaguart_ports[i].port;
-		if (port)
-			uart_remove_one_port(&altera_jtaguart_driver, port);
-	}
+	if (i == -1)
+		i = 0;
+
+	port = &altera_jtaguart_ports[i].port;
+	uart_remove_one_port(&altera_jtaguart_driver, port);
 
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id altera_jtaguart_match[] = {
+	{ .compatible = "ALTR,juart-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
+#else
+#define altera_jtaguart_match NULL
+#endif /* CONFIG_OF */
+
 static struct platform_driver altera_jtaguart_platform_driver = {
 	.probe	= altera_jtaguart_probe,
 	.remove	= __devexit_p(altera_jtaguart_remove),
 	.driver	= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
+		.name		= DRV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= altera_jtaguart_match,
 	},
 };
 
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 7212162..6d5b036 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -24,6 +24,7 @@
 #include <linux/serial.h>
 #include <linux/serial_core.h>
 #include <linux/platform_device.h>
+#include <linux/of.h>
 #include <linux/io.h>
 #include <linux/altera_uart.h>
 
@@ -86,16 +87,12 @@ struct altera_uart {
 
 static u32 altera_uart_readl(struct uart_port *port, int reg)
 {
-	struct altera_uart_platform_uart *platp = port->private_data;
-
-	return readl(port->membase + (reg << platp->bus_shift));
+	return readl(port->membase + (reg << port->regshift));
 }
 
 static void altera_uart_writel(struct uart_port *port, u32 dat, int reg)
 {
-	struct altera_uart_platform_uart *platp = port->private_data;
-
-	writel(dat, port->membase + (reg << platp->bus_shift));
+	writel(dat, port->membase + (reg << port->regshift));
 }
 
 static unsigned int altera_uart_tx_empty(struct uart_port *port)
@@ -511,6 +508,29 @@ static struct uart_driver altera_uart_driver = {
 	.cons		= ALTERA_UART_CONSOLE,
 };
 
+#ifdef CONFIG_OF
+static int altera_uart_get_of_uartclk(struct platform_device *pdev,
+				      struct uart_port *port)
+{
+	int len;
+	const __be32 *clk;
+
+	clk = of_get_property(pdev->dev.of_node, "clock-frequency", &len);
+	if (!clk || len < sizeof(__be32))
+		return -ENODEV;
+
+	port->uartclk = be32_to_cpup(clk);
+
+	return 0;
+}
+#else
+static int altera_uart_get_of_uartclk(struct platform_device *pdev,
+				      struct uart_port *port)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_OF */
+
 static int __devinit altera_uart_probe(struct platform_device *pdev)
 {
 	struct altera_uart_platform_uart *platp = pdev->dev.platform_data;
@@ -518,6 +538,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 	struct resource *res_mem;
 	struct resource *res_irq;
 	int i = pdev->id;
+	int ret;
 
 	/* -1 emphasizes that the platform must have one port, no .N suffix */
 	if (i == -1)
@@ -542,17 +563,29 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 	else if (platp->irq)
 		port->irq = platp->irq;
 
+	/* Check platform data first so we can override device node data */
+	if (platp)
+		port->uartclk = platp->uartclk;
+	else {
+		ret = altera_uart_get_of_uartclk(pdev, port);
+		if (ret)
+			return ret;
+	}
+
 	port->membase = ioremap(port->mapbase, ALTERA_UART_SIZE);
 	if (!port->membase)
 		return -ENOMEM;
 
+	if (platp)
+		port->regshift = platp->bus_shift;
+	else
+		port->regshift = 0;
+
 	port->line = i;
 	port->type = PORT_ALTERA_UART;
 	port->iotype = SERIAL_IO_MEM;
-	port->uartclk = platp->uartclk;
 	port->ops = &altera_uart_ops;
 	port->flags = UPF_BOOT_AUTOCONF;
-	port->private_data = platp;
 
 	uart_add_one_port(&altera_uart_driver, port);
 
@@ -561,19 +594,35 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
 
 static int __devexit altera_uart_remove(struct platform_device *pdev)
 {
-	struct uart_port *port = &altera_uart_ports[pdev->id].port;
+	struct uart_port *port;
+	int i = pdev->id;
+
+	if (i == -1)
+		i = 0;
 
+	port = &altera_uart_ports[i].port;
 	uart_remove_one_port(&altera_uart_driver, port);
+
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static struct of_device_id altera_uart_match[] = {
+	{ .compatible = "ALTR,uart-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_uart_match);
+#else
+#define altera_uart_match NULL
+#endif /* CONFIG_OF */
+
 static struct platform_driver altera_uart_platform_driver = {
 	.probe	= altera_uart_probe,
 	.remove	= __devexit_p(altera_uart_remove),
 	.driver	= {
-		.name	= DRV_NAME,
-		.owner	= THIS_MODULE,
-		.pm	= NULL,
+		.name		= DRV_NAME,
+		.owner		= THIS_MODULE,
+		.of_match_table	= altera_uart_match,
 	},
 };
 
diff --git a/drivers/tty/serial/amba-pl010.c b/drivers/tty/serial/amba-pl010.c
index 2904aa0..d742dd2 100644
--- a/drivers/tty/serial/amba-pl010.c
+++ b/drivers/tty/serial/amba-pl010.c
@@ -676,7 +676,7 @@ static struct uart_driver amba_reg = {
 	.cons			= AMBA_CONSOLE,
 };
 
-static int pl010_probe(struct amba_device *dev, struct amba_id *id)
+static int pl010_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct uart_amba_port *uap;
 	void __iomem *base;
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index e76d7d0..57731e8 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -96,6 +96,22 @@ static struct vendor_data vendor_st = {
 };
 
 /* Deals with DMA transactions */
+
+struct pl011_sgbuf {
+	struct scatterlist sg;
+	char *buf;
+};
+
+struct pl011_dmarx_data {
+	struct dma_chan		*chan;
+	struct completion	complete;
+	bool			use_buf_b;
+	struct pl011_sgbuf	sgbuf_a;
+	struct pl011_sgbuf	sgbuf_b;
+	dma_cookie_t		cookie;
+	bool			running;
+};
+
 struct pl011_dmatx_data {
 	struct dma_chan		*chan;
 	struct scatterlist	sg;
@@ -120,12 +136,70 @@ struct uart_amba_port {
 	char			type[12];
 #ifdef CONFIG_DMA_ENGINE
 	/* DMA stuff */
-	bool			using_dma;
+	bool			using_tx_dma;
+	bool			using_rx_dma;
+	struct pl011_dmarx_data dmarx;
 	struct pl011_dmatx_data	dmatx;
 #endif
 };
 
 /*
+ * Reads up to 256 characters from the FIFO or until it's empty and
+ * inserts them into the TTY layer. Returns the number of characters
+ * read from the FIFO.
+ */
+static int pl011_fifo_to_tty(struct uart_amba_port *uap)
+{
+	u16 status, ch;
+	unsigned int flag, max_count = 256;
+	int fifotaken = 0;
+
+	while (max_count--) {
+		status = readw(uap->port.membase + UART01x_FR);
+		if (status & UART01x_FR_RXFE)
+			break;
+
+		/* Take chars from the FIFO and update status */
+		ch = readw(uap->port.membase + UART01x_DR) |
+			UART_DUMMY_DR_RX;
+		flag = TTY_NORMAL;
+		uap->port.icount.rx++;
+		fifotaken++;
+
+		if (unlikely(ch & UART_DR_ERROR)) {
+			if (ch & UART011_DR_BE) {
+				ch &= ~(UART011_DR_FE | UART011_DR_PE);
+				uap->port.icount.brk++;
+				if (uart_handle_break(&uap->port))
+					continue;
+			} else if (ch & UART011_DR_PE)
+				uap->port.icount.parity++;
+			else if (ch & UART011_DR_FE)
+				uap->port.icount.frame++;
+			if (ch & UART011_DR_OE)
+				uap->port.icount.overrun++;
+
+			ch &= uap->port.read_status_mask;
+
+			if (ch & UART011_DR_BE)
+				flag = TTY_BREAK;
+			else if (ch & UART011_DR_PE)
+				flag = TTY_PARITY;
+			else if (ch & UART011_DR_FE)
+				flag = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(&uap->port, ch & 255))
+			continue;
+
+		uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
+	}
+
+	return fifotaken;
+}
+
+
+/*
  * All the DMA operation mode stuff goes inside this ifdef.
  * This assumes that you have a generic DMA device interface,
  * no custom DMA interfaces are supported.
@@ -134,6 +208,31 @@ struct uart_amba_port {
 
 #define PL011_DMA_BUFFER_SIZE PAGE_SIZE
 
+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);
+	if (!sg->buf)
+		return -ENOMEM;
+
+	sg_init_one(&sg->sg, sg->buf, PL011_DMA_BUFFER_SIZE);
+
+	if (dma_map_sg(chan->device->dev, &sg->sg, 1, dir) != 1) {
+		kfree(sg->buf);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+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);
+	}
+}
+
 static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 {
 	/* DMA is the sole user of the platform data right now */
@@ -153,7 +252,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 		return;
 	}
 
-	/* Try to acquire a generic DMA engine slave channel */
+	/* Try to acquire a generic DMA engine slave TX channel */
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 
@@ -168,6 +267,28 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
 
 	dev_info(uap->port.dev, "DMA channel TX %s\n",
 		 dma_chan_name(uap->dmatx.chan));
+
+	/* Optionally make use of an RX channel as well */
+	if (plat->dma_rx_param) {
+		struct dma_slave_config rx_conf = {
+			.src_addr = uap->port.mapbase + UART01x_DR,
+			.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+			.direction = DMA_FROM_DEVICE,
+			.src_maxburst = uap->fifosize >> 1,
+		};
+
+		chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
+		if (!chan) {
+			dev_err(uap->port.dev, "no RX DMA channel!\n");
+			return;
+		}
+
+		dmaengine_slave_config(chan, &rx_conf);
+		uap->dmarx.chan = chan;
+
+		dev_info(uap->port.dev, "DMA channel RX %s\n",
+			 dma_chan_name(uap->dmarx.chan));
+	}
 }
 
 #ifndef MODULE
@@ -219,9 +340,10 @@ static void pl011_dma_remove(struct uart_amba_port *uap)
 	/* TODO: remove the initcall if it has not yet executed */
 	if (uap->dmatx.chan)
 		dma_release_channel(uap->dmatx.chan);
+	if (uap->dmarx.chan)
+		dma_release_channel(uap->dmarx.chan);
 }
 
-
 /* Forward declare this for the refill routine */
 static int pl011_dma_tx_refill(struct uart_amba_port *uap);
 
@@ -380,7 +502,7 @@ static int pl011_dma_tx_refill(struct uart_amba_port *uap)
  */
 static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
 {
-	if (!uap->using_dma)
+	if (!uap->using_tx_dma)
 		return false;
 
 	/*
@@ -432,7 +554,7 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 {
 	u16 dmacr;
 
-	if (!uap->using_dma)
+	if (!uap->using_tx_dma)
 		return false;
 
 	if (!uap->port.x_char) {
@@ -492,7 +614,7 @@ static void pl011_dma_flush_buffer(struct uart_port *port)
 {
 	struct uart_amba_port *uap = (struct uart_amba_port *)port;
 
-	if (!uap->using_dma)
+	if (!uap->using_tx_dma)
 		return;
 
 	/* Avoid deadlock with the DMA engine callback */
@@ -508,9 +630,219 @@ static void pl011_dma_flush_buffer(struct uart_port *port)
 	}
 }
 
+static void pl011_dma_rx_callback(void *data);
+
+static int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
+{
+	struct dma_chan *rxchan = uap->dmarx.chan;
+	struct dma_device *dma_dev;
+	struct pl011_dmarx_data *dmarx = &uap->dmarx;
+	struct dma_async_tx_descriptor *desc;
+	struct pl011_sgbuf *sgbuf;
+
+	if (!rxchan)
+		return -EIO;
+
+	/* Start the RX DMA job */
+	sgbuf = uap->dmarx.use_buf_b ?
+		&uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
+	dma_dev = rxchan->device;
+	desc = rxchan->device->device_prep_slave_sg(rxchan, &sgbuf->sg, 1,
+					DMA_FROM_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	/*
+	 * If the DMA engine is busy and cannot prepare a
+	 * channel, no big deal, the driver will fall back
+	 * to interrupt mode as a result of this error code.
+	 */
+	if (!desc) {
+		uap->dmarx.running = false;
+		dmaengine_terminate_all(rxchan);
+		return -EBUSY;
+	}
+
+	/* Some data to go along to the callback */
+	desc->callback = pl011_dma_rx_callback;
+	desc->callback_param = uap;
+	dmarx->cookie = dmaengine_submit(desc);
+	dma_async_issue_pending(rxchan);
+
+	uap->dmacr |= UART011_RXDMAE;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+	uap->dmarx.running = true;
+
+	uap->im &= ~UART011_RXIM;
+	writew(uap->im, uap->port.membase + UART011_IMSC);
+
+	return 0;
+}
+
+/*
+ * This is called when either the DMA job is complete, or
+ * the FIFO timeout interrupt occurred. This must be called
+ * with the port spinlock uap->port.lock held.
+ */
+static void pl011_dma_rx_chars(struct uart_amba_port *uap,
+			       u32 pending, bool use_buf_b,
+			       bool readfifo)
+{
+	struct tty_struct *tty = uap->port.state->port.tty;
+	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 */
+	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(uap->port.state->port.tty,
+						   sgbuf->buf, pending);
+
+		/* Return buffer to device */
+		dma_sync_sg_for_device(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
+
+		uap->port.icount.rx += dma_count;
+		if (dma_count < pending)
+			dev_warn(uap->port.dev,
+				 "couldn't insert all characters (TTY is full?)\n");
+	}
+
+	/*
+	 * Only continue with trying to read the FIFO if all DMA chars have
+	 * been taken first.
+	 */
+	if (dma_count == pending && readfifo) {
+		/* Clear any error flags */
+		writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
+		       uap->port.membase + UART011_ICR);
+
+		/*
+		 * If we read all the DMA'd characters, and we had an
+		 * incomplete buffer, that could be due to an rx error, or
+		 * maybe we just timed out. Read any pending chars and check
+		 * the error status.
+		 *
+		 * Error conditions will only occur in the FIFO, these will
+		 * trigger an immediate interrupt and stop the DMA job, so we
+		 * will always find the error in the FIFO, never in the DMA
+		 * buffer.
+		 */
+		fifotaken = pl011_fifo_to_tty(uap);
+	}
+
+	spin_unlock(&uap->port.lock);
+	dev_vdbg(uap->port.dev,
+		 "Took %d chars from DMA buffer and %d chars from the FIFO\n",
+		 dma_count, fifotaken);
+	tty_flip_buffer_push(tty);
+	spin_lock(&uap->port.lock);
+}
+
+static void pl011_dma_rx_irq(struct uart_amba_port *uap)
+{
+	struct pl011_dmarx_data *dmarx = &uap->dmarx;
+	struct dma_chan *rxchan = dmarx->chan;
+	struct pl011_sgbuf *sgbuf = dmarx->use_buf_b ?
+		&dmarx->sgbuf_b : &dmarx->sgbuf_a;
+	size_t pending;
+	struct dma_tx_state state;
+	enum dma_status dmastat;
+
+	/*
+	 * Pause the transfer so we can trust the current counter,
+	 * do this before we pause the PL011 block, else we may
+	 * overflow the FIFO.
+	 */
+	if (dmaengine_pause(rxchan))
+		dev_err(uap->port.dev, "unable to pause DMA transfer\n");
+	dmastat = rxchan->device->device_tx_status(rxchan,
+						   dmarx->cookie, &state);
+	if (dmastat != DMA_PAUSED)
+		dev_err(uap->port.dev, "unable to pause DMA transfer\n");
+
+	/* Disable RX DMA - incoming data will wait in the FIFO */
+	uap->dmacr &= ~UART011_RXDMAE;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+	uap->dmarx.running = false;
+
+	pending = sgbuf->sg.length - state.residue;
+	BUG_ON(pending > PL011_DMA_BUFFER_SIZE);
+	/* Then we terminate the transfer - we now know our residue */
+	dmaengine_terminate_all(rxchan);
+
+	/*
+	 * This will take the chars we have so far and insert
+	 * into the framework.
+	 */
+	pl011_dma_rx_chars(uap, pending, dmarx->use_buf_b, true);
+
+	/* Switch buffer & re-trigger DMA job */
+	dmarx->use_buf_b = !dmarx->use_buf_b;
+	if (pl011_dma_rx_trigger_dma(uap)) {
+		dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
+			"fall back to interrupt mode\n");
+		uap->im |= UART011_RXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+	}
+}
+
+static void pl011_dma_rx_callback(void *data)
+{
+	struct uart_amba_port *uap = data;
+	struct pl011_dmarx_data *dmarx = &uap->dmarx;
+	bool lastbuf = dmarx->use_buf_b;
+	int ret;
+
+	/*
+	 * This completion interrupt occurs typically when the
+	 * RX buffer is totally stuffed but no timeout has yet
+	 * occurred. When that happens, we just want the RX
+	 * routine to flush out the secondary DMA buffer while
+	 * we immediately trigger the next DMA job.
+	 */
+	spin_lock_irq(&uap->port.lock);
+	uap->dmarx.running = false;
+	dmarx->use_buf_b = !lastbuf;
+	ret = pl011_dma_rx_trigger_dma(uap);
+
+	pl011_dma_rx_chars(uap, PL011_DMA_BUFFER_SIZE, lastbuf, false);
+	spin_unlock_irq(&uap->port.lock);
+	/*
+	 * Do this check after we picked the DMA chars so we don't
+	 * get some IRQ immediately from RX.
+	 */
+	if (ret) {
+		dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
+			"fall back to interrupt mode\n");
+		uap->im |= UART011_RXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+	}
+}
+
+/*
+ * Stop accepting received characters, when we're shutting down or
+ * suspending this port.
+ * Locking: called with port lock held and IRQs disabled.
+ */
+static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
+{
+	/* FIXME.  Just disable the DMA enable */
+	uap->dmacr &= ~UART011_RXDMAE;
+	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+}
 
 static void pl011_dma_startup(struct uart_amba_port *uap)
 {
+	int ret;
+
 	if (!uap->dmatx.chan)
 		return;
 
@@ -525,8 +857,33 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 
 	/* The DMA buffer is now the FIFO the TTY subsystem can use */
 	uap->port.fifosize = PL011_DMA_BUFFER_SIZE;
-	uap->using_dma = true;
+	uap->using_tx_dma = true;
+
+	if (!uap->dmarx.chan)
+		goto skip_rx;
+
+	/* Allocate and map DMA RX buffers */
+	ret = pl011_sgbuf_init(uap->dmarx.chan, &uap->dmarx.sgbuf_a,
+			       DMA_FROM_DEVICE);
+	if (ret) {
+		dev_err(uap->port.dev, "failed to init DMA %s: %d\n",
+			"RX buffer A", ret);
+		goto skip_rx;
+	}
+
+	ret = pl011_sgbuf_init(uap->dmarx.chan, &uap->dmarx.sgbuf_b,
+			       DMA_FROM_DEVICE);
+	if (ret) {
+		dev_err(uap->port.dev, "failed to init DMA %s: %d\n",
+			"RX buffer B", ret);
+		pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a,
+				 DMA_FROM_DEVICE);
+		goto skip_rx;
+	}
 
+	uap->using_rx_dma = true;
+
+skip_rx:
 	/* Turn on DMA error (RX/TX will be enabled on demand) */
 	uap->dmacr |= UART011_DMAONERR;
 	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
@@ -539,11 +896,17 @@ static void pl011_dma_startup(struct uart_amba_port *uap)
 	if (uap->vendor->dma_threshold)
 		writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
 			       uap->port.membase + ST_UART011_DMAWM);
+
+	if (uap->using_rx_dma) {
+		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");
+	}
 }
 
 static void pl011_dma_shutdown(struct uart_amba_port *uap)
 {
-	if (!uap->using_dma)
+	if (!(uap->using_tx_dma || uap->using_rx_dma))
 		return;
 
 	/* Disable RX and TX DMA */
@@ -555,19 +918,39 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
 	writew(uap->dmacr, uap->port.membase + UART011_DMACR);
 	spin_unlock_irq(&uap->port.lock);
 
-	/* In theory, this should already be done by pl011_dma_flush_buffer */
-	dmaengine_terminate_all(uap->dmatx.chan);
-	if (uap->dmatx.queued) {
-		dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
-			     DMA_TO_DEVICE);
-		uap->dmatx.queued = false;
+	if (uap->using_tx_dma) {
+		/* In theory, this should already be done by pl011_dma_flush_buffer */
+		dmaengine_terminate_all(uap->dmatx.chan);
+		if (uap->dmatx.queued) {
+			dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
+				     DMA_TO_DEVICE);
+			uap->dmatx.queued = false;
+		}
+
+		kfree(uap->dmatx.buf);
+		uap->using_tx_dma = false;
 	}
 
-	kfree(uap->dmatx.buf);
+	if (uap->using_rx_dma) {
+		dmaengine_terminate_all(uap->dmarx.chan);
+		/* 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);
+		uap->using_rx_dma = false;
+	}
+}
 
-	uap->using_dma = false;
+static inline bool pl011_dma_rx_available(struct uart_amba_port *uap)
+{
+	return uap->using_rx_dma;
 }
 
+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)
@@ -600,6 +983,29 @@ static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
 	return false;
 }
 
+static inline void pl011_dma_rx_irq(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
+{
+}
+
+static inline int pl011_dma_rx_trigger_dma(struct uart_amba_port *uap)
+{
+	return -EIO;
+}
+
+static inline bool pl011_dma_rx_available(struct uart_amba_port *uap)
+{
+	return false;
+}
+
+static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
+{
+	return false;
+}
+
 #define pl011_dma_flush_buffer	NULL
 #endif
 
@@ -630,6 +1036,8 @@ static void pl011_stop_rx(struct uart_port *port)
 	uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
 		     UART011_PEIM|UART011_BEIM|UART011_OEIM);
 	writew(uap->im, uap->port.membase + UART011_IMSC);
+
+	pl011_dma_rx_stop(uap);
 }
 
 static void pl011_enable_ms(struct uart_port *port)
@@ -643,51 +1051,24 @@ static void pl011_enable_ms(struct uart_port *port)
 static void pl011_rx_chars(struct uart_amba_port *uap)
 {
 	struct tty_struct *tty = uap->port.state->port.tty;
-	unsigned int status, ch, flag, max_count = 256;
-
-	status = readw(uap->port.membase + UART01x_FR);
-	while ((status & UART01x_FR_RXFE) == 0 && max_count--) {
-		ch = readw(uap->port.membase + UART01x_DR) | UART_DUMMY_DR_RX;
-		flag = TTY_NORMAL;
-		uap->port.icount.rx++;
-
-		/*
-		 * Note that the error handling code is
-		 * out of the main execution path
-		 */
-		if (unlikely(ch & UART_DR_ERROR)) {
-			if (ch & UART011_DR_BE) {
-				ch &= ~(UART011_DR_FE | UART011_DR_PE);
-				uap->port.icount.brk++;
-				if (uart_handle_break(&uap->port))
-					goto ignore_char;
-			} else if (ch & UART011_DR_PE)
-				uap->port.icount.parity++;
-			else if (ch & UART011_DR_FE)
-				uap->port.icount.frame++;
-			if (ch & UART011_DR_OE)
-				uap->port.icount.overrun++;
-
-			ch &= uap->port.read_status_mask;
-
-			if (ch & UART011_DR_BE)
-				flag = TTY_BREAK;
-			else if (ch & UART011_DR_PE)
-				flag = TTY_PARITY;
-			else if (ch & UART011_DR_FE)
-				flag = TTY_FRAME;
-		}
 
-		if (uart_handle_sysrq_char(&uap->port, ch & 255))
-			goto ignore_char;
-
-		uart_insert_char(&uap->port, ch, UART011_DR_OE, ch, flag);
+	pl011_fifo_to_tty(uap);
 
-	ignore_char:
-		status = readw(uap->port.membase + UART01x_FR);
-	}
 	spin_unlock(&uap->port.lock);
 	tty_flip_buffer_push(tty);
+	/*
+	 * If we were temporarily out of DMA mode for a while,
+	 * attempt to switch back to DMA mode again.
+	 */
+	if (pl011_dma_rx_available(uap)) {
+		if (pl011_dma_rx_trigger_dma(uap)) {
+			dev_dbg(uap->port.dev, "could not trigger RX DMA job "
+				"fall back to interrupt mode again\n");
+			uap->im |= UART011_RXIM;
+		} else
+			uap->im &= ~UART011_RXIM;
+		writew(uap->im, uap->port.membase + UART011_IMSC);
+	}
 	spin_lock(&uap->port.lock);
 }
 
@@ -767,8 +1148,12 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
 					  UART011_RXIS),
 			       uap->port.membase + UART011_ICR);
 
-			if (status & (UART011_RTIS|UART011_RXIS))
-				pl011_rx_chars(uap);
+			if (status & (UART011_RTIS|UART011_RXIS)) {
+				if (pl011_dma_rx_running(uap))
+					pl011_dma_rx_irq(uap);
+				else
+					pl011_rx_chars(uap);
+			}
 			if (status & (UART011_DSRMIS|UART011_DCDMIS|
 				      UART011_CTSMIS|UART011_RIMIS))
 				pl011_modem_status(uap);
@@ -945,10 +1330,14 @@ static int pl011_startup(struct uart_port *port)
 	pl011_dma_startup(uap);
 
 	/*
-	 * Finally, enable interrupts
+	 * Finally, enable interrupts, only timeouts when using DMA
+	 * if initial RX DMA job failed, start in interrupt mode
+	 * as well.
 	 */
 	spin_lock_irq(&uap->port.lock);
-	uap->im = UART011_RXIM | UART011_RTIM;
+	uap->im = UART011_RTIM;
+	if (!pl011_dma_rx_running(uap))
+		uap->im |= UART011_RXIM;
 	writew(uap->im, uap->port.membase + UART011_IMSC);
 	spin_unlock_irq(&uap->port.lock);
 
@@ -1349,7 +1738,7 @@ static struct uart_driver amba_reg = {
 	.cons			= AMBA_CONSOLE,
 };
 
-static int pl011_probe(struct amba_device *dev, struct amba_id *id)
+static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct uart_amba_port *uap;
 	struct vendor_data *vendor = id->data;
diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c
index 095a5d5..1ab999b 100644
--- a/drivers/tty/serial/apbuart.c
+++ b/drivers/tty/serial/apbuart.c
@@ -553,8 +553,7 @@ static struct uart_driver grlib_apbuart_driver = {
 /* OF Platform Driver                                                       */
 /* ======================================================================== */
 
-static int __devinit apbuart_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static int __devinit apbuart_probe(struct platform_device *op)
 {
 	int i = -1;
 	struct uart_port *port = NULL;
@@ -587,7 +586,7 @@ static struct of_device_id __initdata apbuart_match[] = {
 	{},
 };
 
-static struct of_platform_driver grlib_apbuart_of_driver = {
+static struct platform_driver grlib_apbuart_of_driver = {
 	.probe = apbuart_probe,
 	.driver = {
 		.owner = THIS_MODULE,
@@ -676,10 +675,10 @@ static int __init grlib_apbuart_init(void)
 		return ret;
 	}
 
-	ret = of_register_platform_driver(&grlib_apbuart_of_driver);
+	ret = platform_driver_register(&grlib_apbuart_of_driver);
 	if (ret) {
 		printk(KERN_ERR
-		       "%s: of_register_platform_driver failed (%i)\n",
+		       "%s: platform_driver_register failed (%i)\n",
 		       __FILE__, ret);
 		uart_unregister_driver(&grlib_apbuart_driver);
 		return ret;
@@ -697,7 +696,7 @@ static void __exit grlib_apbuart_exit(void)
 				     &grlib_apbuart_ports[i]);
 
 	uart_unregister_driver(&grlib_apbuart_driver);
-	of_unregister_platform_driver(&grlib_apbuart_of_driver);
+	platform_driver_unregister(&grlib_apbuart_of_driver);
 }
 
 module_init(grlib_apbuart_init);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2a1d52f..f119d17 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1240,6 +1240,21 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	spin_unlock_irqrestore(&port->lock, flags);
 }
 
+static void atmel_set_ldisc(struct uart_port *port, int new)
+{
+	int line = port->line;
+
+	if (line >= port->state->port.tty->driver->num)
+		return;
+
+	if (port->state->port.tty->ldisc->ops->num == N_PPS) {
+		port->flags |= UPF_HARDPPS_CD;
+		atmel_enable_ms(port);
+	} else {
+		port->flags &= ~UPF_HARDPPS_CD;
+	}
+}
+
 /*
  * Return string describing the specified port
  */
@@ -1380,6 +1395,7 @@ static struct uart_ops atmel_pops = {
 	.shutdown	= atmel_shutdown,
 	.flush_buffer	= atmel_flush_buffer,
 	.set_termios	= atmel_set_termios,
+	.set_ldisc	= atmel_set_ldisc,
 	.type		= atmel_type,
 	.release_port	= atmel_release_port,
 	.request_port	= atmel_request_port,
diff --git a/drivers/tty/serial/bfin_sport_uart.c b/drivers/tty/serial/bfin_sport_uart.c
index e95c524..c3ec0a6 100644
--- a/drivers/tty/serial/bfin_sport_uart.c
+++ b/drivers/tty/serial/bfin_sport_uart.c
@@ -788,7 +788,7 @@ static int __devinit sport_uart_probe(struct platform_device *pdev)
 		sport->port.mapbase = res->start;
 
 		sport->port.irq = platform_get_irq(pdev, 0);
-		if (sport->port.irq < 0) {
+		if ((int)sport->port.irq < 0) {
 			dev_err(&pdev->dev, "No sport RX/TX IRQ specified\n");
 			ret = -ENOENT;
 			goto out_error_unmap;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 8692ff9..a9a6a5f 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1359,8 +1359,7 @@ static struct uart_driver cpm_reg = {
 
 static int probe_index;
 
-static int __devinit cpm_uart_probe(struct platform_device *ofdev,
-                                    const struct of_device_id *match)
+static int __devinit cpm_uart_probe(struct platform_device *ofdev)
 {
 	int index = probe_index++;
 	struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
@@ -1405,7 +1404,7 @@ static struct of_device_id cpm_uart_match[] = {
 	{}
 };
 
-static struct of_platform_driver cpm_uart_driver = {
+static struct platform_driver cpm_uart_driver = {
 	.driver = {
 		.name = "cpm_uart",
 		.owner = THIS_MODULE,
@@ -1421,7 +1420,7 @@ static int __init cpm_uart_init(void)
 	if (ret)
 		return ret;
 
-	ret = of_register_platform_driver(&cpm_uart_driver);
+	ret = platform_driver_register(&cpm_uart_driver);
 	if (ret)
 		uart_unregister_driver(&cpm_reg);
 
@@ -1430,7 +1429,7 @@ static int __init cpm_uart_init(void)
 
 static void __exit cpm_uart_exit(void)
 {
-	of_unregister_platform_driver(&cpm_uart_driver);
+	platform_driver_unregister(&cpm_uart_driver);
 	uart_unregister_driver(&cpm_reg);
 }
 
diff --git a/drivers/tty/serial/crisv10.c b/drivers/tty/serial/crisv10.c
index bcc31f2..225123b 100644
--- a/drivers/tty/serial/crisv10.c
+++ b/drivers/tty/serial/crisv10.c
@@ -3581,8 +3581,7 @@ rs_break(struct tty_struct *tty, int break_state)
 }
 
 static int
-rs_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
+rs_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
 {
 	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 	unsigned long flags;
@@ -3614,7 +3613,7 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
 }
 
 static int
-rs_tiocmget(struct tty_struct *tty, struct file *file)
+rs_tiocmget(struct tty_struct *tty)
 {
 	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 	unsigned int result;
@@ -3648,7 +3647,7 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
 
 
 static int
-rs_ioctl(struct tty_struct *tty, struct file * file,
+rs_ioctl(struct tty_struct *tty,
 	 unsigned int cmd, unsigned long arg)
 {
 	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index ab93763..8ee5a41 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -8,7 +8,7 @@
  *		      Jan Dumon <j.dumon@option.com>
  *
  * Copyright (C) 2009, 2010 Intel Corp
- * Russ Gorby <richardx.r.gorby@intel.com>
+ * Russ Gorby <russ.gorby@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
@@ -67,6 +67,7 @@
 #define IFX_SPI_MORE_MASK		0x10
 #define IFX_SPI_MORE_BIT		12	/* bit position in u16 */
 #define IFX_SPI_CTS_BIT			13	/* bit position in u16 */
+#define IFX_SPI_MODE			SPI_MODE_1
 #define IFX_SPI_TTY_ID			0
 #define IFX_SPI_TIMEOUT_SEC		2
 #define IFX_SPI_HEADER_0		(-1)
@@ -76,7 +77,7 @@
 static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev);
 
 /* local variables */
-static int spi_b16 = 1;			/* 8 or 16 bit word length */
+static int spi_bpw = 16;		/* 8, 16 or 32 bit word length */
 static struct tty_driver *tty_drv;
 static struct ifx_spi_device *saved_ifx_dev;
 static struct lock_class_key ifx_spi_key;
@@ -244,7 +245,7 @@ static void ifx_spi_timeout(unsigned long arg)
  *	Map the signal state into Linux modem flags and report the value
  *	in Linux terms
  */
-static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp)
+static int ifx_spi_tiocmget(struct tty_struct *tty)
 {
 	unsigned int value;
 	struct ifx_spi_device *ifx_dev = tty->driver_data;
@@ -262,7 +263,6 @@ static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp)
 /**
  *	ifx_spi_tiocmset	-	set modem bits
  *	@tty: the tty structure
- *	@filp: file handle issuing the request
  *	@set: bits to set
  *	@clear: bits to clear
  *
@@ -271,7 +271,7 @@ static int ifx_spi_tiocmget(struct tty_struct *tty, struct file *filp)
  *
  *	FIXME: do we need to kick the tranfers when we do this ?
  */
-static int ifx_spi_tiocmset(struct tty_struct *tty, struct file *filp,
+static int ifx_spi_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct ifx_spi_device *ifx_dev = tty->driver_data;
@@ -722,9 +722,9 @@ static void ifx_spi_io(unsigned long data)
 		/* note len is BYTES, not transfers */
 		ifx_dev->spi_xfer.len = IFX_SPI_TRANSFER_SIZE;
 		ifx_dev->spi_xfer.cs_change = 0;
-		ifx_dev->spi_xfer.speed_hz = 12500000;
+		ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz;
 		/* ifx_dev->spi_xfer.speed_hz = 390625; */
-		ifx_dev->spi_xfer.bits_per_word = spi_b16 ? 16 : 8;
+		ifx_dev->spi_xfer.bits_per_word = spi_bpw;
 
 		ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer;
 		ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer;
@@ -732,7 +732,7 @@ static void ifx_spi_io(unsigned long data)
 		/*
 		 * setup dma pointers
 		 */
-		if (ifx_dev->is_6160) {
+		if (ifx_dev->use_dma) {
 			ifx_dev->spi_msg.is_dma_mapped = 1;
 			ifx_dev->tx_dma = ifx_dev->tx_bus;
 			ifx_dev->rx_dma = ifx_dev->rx_bus;
@@ -798,8 +798,8 @@ static int ifx_spi_create_port(struct ifx_spi_device *ifx_dev)
 		goto error_ret;
 	}
 
-	pport->ops = &ifx_tty_port_ops;
 	tty_port_init(pport);
+	pport->ops = &ifx_tty_port_ops;
 	ifx_dev->minor = IFX_SPI_TTY_ID;
 	ifx_dev->tty_dev = tty_register_device(tty_drv, ifx_dev->minor,
 					       &ifx_dev->spi_dev->dev);
@@ -960,7 +960,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 {
 	int ret;
 	int srdy;
-	struct ifx_modem_platform_data *pl_data = NULL;
+	struct ifx_modem_platform_data *pl_data;
 	struct ifx_spi_device *ifx_dev;
 
 	if (saved_ifx_dev) {
@@ -968,6 +968,12 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 		return -ENODEV;
 	}
 
+	pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data;
+	if (!pl_data) {
+		dev_err(&spi->dev, "missing platform data!");
+		return -ENODEV;
+	}
+
 	/* initialize structure to hold our device variables */
 	ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL);
 	if (!ifx_dev) {
@@ -983,14 +989,25 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 	init_timer(&ifx_dev->spi_timer);
 	ifx_dev->spi_timer.function = ifx_spi_timeout;
 	ifx_dev->spi_timer.data = (unsigned long)ifx_dev;
-	ifx_dev->is_6160 = pl_data->is_6160;
+	ifx_dev->modem = pl_data->modem_type;
+	ifx_dev->use_dma = pl_data->use_dma;
+	ifx_dev->max_hz = pl_data->max_hz;
+	/* initialize spi mode, etc */
+	spi->max_speed_hz = ifx_dev->max_hz;
+	spi->mode = IFX_SPI_MODE | (SPI_LOOP & spi->mode);
+	spi->bits_per_word = spi_bpw;
+	ret = spi_setup(spi);
+	if (ret) {
+		dev_err(&spi->dev, "SPI setup wasn't successful %d", ret);
+		return -ENODEV;
+	}
 
 	/* ensure SPI protocol flags are initialized to enable transfer */
 	ifx_dev->spi_more = 0;
 	ifx_dev->spi_slave_cts = 0;
 
 	/*initialize transfer and dma buffers */
-	ifx_dev->tx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev,
+	ifx_dev->tx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent,
 				IFX_SPI_TRANSFER_SIZE,
 				&ifx_dev->tx_bus,
 				GFP_KERNEL);
@@ -999,7 +1016,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 		ret = -ENOMEM;
 		goto error_ret;
 	}
-	ifx_dev->rx_buffer = dma_alloc_coherent(&ifx_dev->spi_dev->dev,
+	ifx_dev->rx_buffer = dma_alloc_coherent(ifx_dev->spi_dev->dev.parent,
 				IFX_SPI_TRANSFER_SIZE,
 				&ifx_dev->rx_bus,
 				GFP_KERNEL);
@@ -1025,18 +1042,11 @@ static int ifx_spi_spi_probe(struct spi_device *spi)
 		goto error_ret;
 	}
 
-	pl_data = (struct ifx_modem_platform_data *)spi->dev.platform_data;
-	if (pl_data) {
-		ifx_dev->gpio.reset = pl_data->rst_pmu;
-		ifx_dev->gpio.po = pl_data->pwr_on;
-		ifx_dev->gpio.mrdy = pl_data->mrdy;
-		ifx_dev->gpio.srdy = pl_data->srdy;
-		ifx_dev->gpio.reset_out = pl_data->rst_out;
-	} else {
-		dev_err(&spi->dev, "missing platform data!");
-		ret = -ENODEV;
-		goto error_ret;
-	}
+	ifx_dev->gpio.reset = pl_data->rst_pmu;
+	ifx_dev->gpio.po = pl_data->pwr_on;
+	ifx_dev->gpio.mrdy = pl_data->mrdy;
+	ifx_dev->gpio.srdy = pl_data->srdy;
+	ifx_dev->gpio.reset_out = pl_data->rst_out;
 
 	dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d",
 		 ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy,
@@ -1322,9 +1332,9 @@ static const struct spi_device_id ifx_id_table[] = {
 MODULE_DEVICE_TABLE(spi, ifx_id_table);
 
 /* spi operations */
-static const struct spi_driver ifx_spi_driver_6160 = {
+static const struct spi_driver ifx_spi_driver = {
 	.driver = {
-		.name = "ifx6160",
+		.name = DRVNAME,
 		.bus = &spi_bus_type,
 		.pm = &ifx_spi_pm,
 		.owner = THIS_MODULE},
@@ -1346,7 +1356,7 @@ static void __exit ifx_spi_exit(void)
 {
 	/* unregister */
 	tty_unregister_driver(tty_drv);
-	spi_unregister_driver((void *)&ifx_spi_driver_6160);
+	spi_unregister_driver((void *)&ifx_spi_driver);
 }
 
 /**
@@ -1388,7 +1398,7 @@ static int __init ifx_spi_init(void)
 		return result;
 	}
 
-	result = spi_register_driver((void *)&ifx_spi_driver_6160);
+	result = spi_register_driver((void *)&ifx_spi_driver);
 	if (result) {
 		pr_err("%s: spi_register_driver failed(%d)",
 			DRVNAME, result);
diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h
index deb7b8d..e8464ba 100644
--- a/drivers/tty/serial/ifx6x60.h
+++ b/drivers/tty/serial/ifx6x60.h
@@ -29,8 +29,6 @@
 #define DRVNAME				"ifx6x60"
 #define TTYNAME				"ttyIFX"
 
-/* #define IFX_THROTTLE_CODE */
-
 #define IFX_SPI_MAX_MINORS		1
 #define IFX_SPI_TRANSFER_SIZE		2048
 #define IFX_SPI_FIFO_SIZE		4096
@@ -88,7 +86,9 @@ struct ifx_spi_device {
 	dma_addr_t rx_dma;
 	dma_addr_t tx_dma;
 
-	int is_6160;				/* Modem type */
+	int modem;		/* Modem type */
+	int use_dma;		/* provide dma-able addrs in SPI msg */
+	long max_hz;		/* max SPI frequency */
 
 	spinlock_t write_lock;
 	int write_pending;
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index d40010a..c111f36 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -16,9 +16,7 @@
  *    2/3 chan to port 1, 4/5 chan to port 3. Even number chans
  *    are used for RX, odd chans for TX
  *
- * 2. In A0 stepping, UART will not support TX half empty flag
- *
- * 3. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
+ * 2. The RI/DSR/DCD/DTR are not pinned out, DCD & DSR are always
  *    asserted, only when the HW is reset the DDCD and DDSR will
  *    be triggered
  */
@@ -41,8 +39,6 @@
 #include <linux/io.h>
 #include <linux/debugfs.h>
 
-#define  MFD_HSU_A0_STEPPING	1
-
 #define HSU_DMA_BUF_SIZE	2048
 
 #define chan_readl(chan, offset)	readl(chan->reg + offset)
@@ -51,7 +47,10 @@
 #define mfd_readl(obj, offset)		readl(obj->reg + offset)
 #define mfd_writel(obj, offset, val)	writel(val, obj->reg + offset)
 
-#define HSU_DMA_TIMEOUT_CHECK_FREQ	(HZ/10)
+static int hsu_dma_enable;
+module_param(hsu_dma_enable, int, 0);
+MODULE_PARM_DESC(hsu_dma_enable, "It is a bitmap to set working mode, if \
+bit[x] is 1, then port[x] will work in DMA mode, otherwise in PIO mode.");
 
 struct hsu_dma_buffer {
 	u8		*buf;
@@ -65,7 +64,6 @@ struct hsu_dma_chan {
 	enum dma_data_direction	dirt;
 	struct uart_hsu_port	*uport;
 	void __iomem		*reg;
-	struct timer_list	rx_timer; /* only needed by RX channel */
 };
 
 struct uart_hsu_port {
@@ -355,8 +353,6 @@ void hsu_dma_start_rx_chan(struct hsu_dma_chan *rxc, struct hsu_dma_buffer *dbuf
 					 | (0x1 << 24)	/* timeout bit, see HSU Errata 1 */
 					 );
 	chan_writel(rxc, HSU_CH_CR, 0x3);
-
-	mod_timer(&rxc->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
 }
 
 /* Protected by spin_lock_irqsave(port->lock) */
@@ -420,7 +416,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
 		chan_writel(chan, HSU_CH_CR, 0x3);
 		return;
 	}
-	del_timer(&chan->rx_timer);
 
 	dma_sync_single_for_cpu(port->dev, dbuf->dma_addr,
 			dbuf->dma_size, DMA_FROM_DEVICE);
@@ -448,8 +443,6 @@ void hsu_dma_rx(struct uart_hsu_port *up, u32 int_sts)
 	tty_flip_buffer_push(tty);
 
 	chan_writel(chan, HSU_CH_CR, 0x3);
-	chan->rx_timer.expires = jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ;
-	add_timer(&chan->rx_timer);
 
 }
 
@@ -551,16 +544,9 @@ static void transmit_chars(struct uart_hsu_port *up)
 		return;
 	}
 
-#ifndef MFD_HSU_A0_STEPPING
+	/* The IRQ is for TX FIFO half-empty */
 	count = up->port.fifosize / 2;
-#else
-	/*
-	 * A0 only supports fully empty IRQ, and the first char written
-	 * into it won't clear the EMPT bit, so we may need be cautious
-	 * by useing a shorter buffer
-	 */
-	count = up->port.fifosize - 4;
-#endif
+
 	do {
 		serial_out(up, UART_TX, xmit->buf[xmit->tail]);
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -769,9 +755,8 @@ static void serial_hsu_break_ctl(struct uart_port *port, int break_state)
 /*
  * What special to do:
  * 1. chose the 64B fifo mode
- * 2. make sure not to select half empty mode for A0 stepping
- * 3. start dma or pio depends on configuration
- * 4. we only allocate dma memory when needed
+ * 2. start dma or pio depends on configuration
+ * 3. we only allocate dma memory when needed
  */
 static int serial_hsu_startup(struct uart_port *port)
 {
@@ -870,8 +855,6 @@ static void serial_hsu_shutdown(struct uart_port *port)
 		container_of(port, struct uart_hsu_port, port);
 	unsigned long flags;
 
-	del_timer_sync(&up->rxc->rx_timer);
-
 	/* Disable interrupts from this port */
 	up->ier = 0;
 	serial_out(up, UART_IER, 0);
@@ -977,10 +960,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
 		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_HSU_64_32B;
 
 	fcr |= UART_FCR_HSU_64B_FIFO;
-#ifdef MFD_HSU_A0_STEPPING
-	/* A0 doesn't support half empty IRQ */
-	fcr |= UART_FCR_FULL_EMPT_TXI;
-#endif
 
 	/*
 	 * Ok, we're now changing the port state.  Do it with
@@ -1343,28 +1322,6 @@ err_disable:
 	return ret;
 }
 
-static void hsu_dma_rx_timeout(unsigned long data)
-{
-	struct hsu_dma_chan *chan = (void *)data;
-	struct uart_hsu_port *up = chan->uport;
-	struct hsu_dma_buffer *dbuf = &up->rxbuf;
-	int count = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&up->port.lock, flags);
-
-	count = chan_readl(chan, HSU_CH_D0SAR) - dbuf->dma_addr;
-
-	if (!count) {
-		mod_timer(&chan->rx_timer, jiffies + HSU_DMA_TIMEOUT_CHECK_FREQ);
-		goto exit;
-	}
-
-	hsu_dma_rx(up, 0);
-exit:
-	spin_unlock_irqrestore(&up->port.lock, flags);
-}
-
 static void hsu_global_init(void)
 {
 	struct hsu_port *hsu;
@@ -1415,6 +1372,12 @@ static void hsu_global_init(void)
 
 		serial_hsu_ports[i] = uport;
 		uport->index = i;
+
+		if (hsu_dma_enable & (1<<i))
+			uport->use_dma = 1;
+		else
+			uport->use_dma = 0;
+
 		uport++;
 	}
 
@@ -1427,12 +1390,6 @@ static void hsu_global_init(void)
 		dchan->reg = hsu->reg + HSU_DMA_CHANS_REG_OFFSET +
 				i * HSU_DMA_CHANS_REG_LENGTH;
 
-		/* Work around for RX */
-		if (dchan->dirt == DMA_FROM_DEVICE) {
-			init_timer(&dchan->rx_timer);
-			dchan->rx_timer.function = hsu_dma_rx_timeout;
-			dchan->rx_timer.data = (unsigned long)dchan;
-		}
 		dchan++;
 	}
 
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 126ec7f..a0bcd8a 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1302,8 +1302,7 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
 	{},
 };
 
-static int __devinit
-mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit mpc52xx_uart_of_probe(struct platform_device *op)
 {
 	int idx = -1;
 	unsigned int uartclk;
@@ -1311,8 +1310,6 @@ mpc52xx_uart_of_probe(struct platform_device *op, const struct of_device_id *mat
 	struct resource res;
 	int ret;
 
-	dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match);
-
 	/* Check validity & presence */
 	for (idx = 0; idx < MPC52xx_PSC_MAXNUM; idx++)
 		if (mpc52xx_uart_nodes[idx] == op->dev.of_node)
@@ -1453,7 +1450,7 @@ mpc52xx_uart_of_enumerate(void)
 
 MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);
 
-static struct of_platform_driver mpc52xx_uart_of_driver = {
+static struct platform_driver mpc52xx_uart_of_driver = {
 	.probe		= mpc52xx_uart_of_probe,
 	.remove		= mpc52xx_uart_of_remove,
 #ifdef CONFIG_PM
@@ -1497,9 +1494,9 @@ mpc52xx_uart_init(void)
 			return ret;
 	}
 
-	ret = of_register_platform_driver(&mpc52xx_uart_of_driver);
+	ret = platform_driver_register(&mpc52xx_uart_of_driver);
 	if (ret) {
-		printk(KERN_ERR "%s: of_register_platform_driver failed (%i)\n",
+		printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
 		       __FILE__, ret);
 		uart_unregister_driver(&mpc52xx_uart_driver);
 		return ret;
@@ -1514,7 +1511,7 @@ mpc52xx_uart_exit(void)
 	if (psc_ops->fifoc_uninit)
 		psc_ops->fifoc_uninit();
 
-	of_unregister_platform_driver(&mpc52xx_uart_of_driver);
+	platform_driver_unregister(&mpc52xx_uart_of_driver);
 	uart_unregister_driver(&mpc52xx_uart_driver);
 }
 
diff --git a/drivers/tty/serial/mrst_max3110.c b/drivers/tty/serial/mrst_max3110.c
index b62857b..37e13c3 100644
--- a/drivers/tty/serial/mrst_max3110.c
+++ b/drivers/tty/serial/mrst_max3110.c
@@ -51,7 +51,7 @@
 struct uart_max3110 {
 	struct uart_port port;
 	struct spi_device *spi;
-	char name[24];
+	char name[SPI_NAME_SIZE];
 
 	wait_queue_head_t wq;
 	struct task_struct *main_thread;
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 8e43a7b..bfee9b4 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2007 Google, Inc.
  * Author: Robert Love <rlove@google.com>
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -31,6 +32,7 @@
 #include <linux/serial.h>
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 #include "msm_serial.h"
 
@@ -38,9 +40,20 @@ struct msm_port {
 	struct uart_port	uart;
 	char			name[16];
 	struct clk		*clk;
+	struct clk		*pclk;
 	unsigned int		imr;
+	unsigned int            *gsbi_base;
+	int			is_uartdm;
+	unsigned int		old_snap_state;
 };
 
+static inline void wait_for_xmitr(struct uart_port *port, int bits)
+{
+	if (!(msm_read(port, UART_SR) & UART_SR_TX_EMPTY))
+		while ((msm_read(port, UART_ISR) & bits) != bits)
+			cpu_relax();
+}
+
 static void msm_stop_tx(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
@@ -73,6 +86,61 @@ static void msm_enable_ms(struct uart_port *port)
 	msm_write(port, msm_port->imr, UART_IMR);
 }
 
+static void handle_rx_dm(struct uart_port *port, unsigned int misr)
+{
+	struct tty_struct *tty = port->state->port.tty;
+	unsigned int sr;
+	int count = 0;
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
+	if ((msm_read(port, UART_SR) & UART_SR_OVERRUN)) {
+		port->icount.overrun++;
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
+	}
+
+	if (misr & UART_IMR_RXSTALE) {
+		count = msm_read(port, UARTDM_RX_TOTAL_SNAP) -
+			msm_port->old_snap_state;
+		msm_port->old_snap_state = 0;
+	} else {
+		count = 4 * (msm_read(port, UART_RFWR));
+		msm_port->old_snap_state += count;
+	}
+
+	/* TODO: Precise error reporting */
+
+	port->icount.rx += count;
+
+	while (count > 0) {
+		unsigned int c;
+
+		sr = msm_read(port, UART_SR);
+		if ((sr & UART_SR_RX_READY) == 0) {
+			msm_port->old_snap_state -= count;
+			break;
+		}
+		c = msm_read(port, UARTDM_RF);
+		if (sr & UART_SR_RX_BREAK) {
+			port->icount.brk++;
+			if (uart_handle_break(port))
+				continue;
+		} else if (sr & UART_SR_PAR_FRAME_ERR)
+			port->icount.frame++;
+
+		/* TODO: handle sysrq */
+		tty_insert_flip_string(tty, (char *) &c,
+				       (count > 4) ? 4 : count);
+		count -= 4;
+	}
+
+	tty_flip_buffer_push(tty);
+	if (misr & (UART_IMR_RXSTALE))
+		msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
+	msm_write(port, 0xFFFFFF, UARTDM_DMRX);
+	msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+}
+
 static void handle_rx(struct uart_port *port)
 {
 	struct tty_struct *tty = port->state->port.tty;
@@ -121,6 +189,12 @@ static void handle_rx(struct uart_port *port)
 	tty_flip_buffer_push(tty);
 }
 
+static void reset_dm_count(struct uart_port *port)
+{
+	wait_for_xmitr(port, UART_ISR_TX_READY);
+	msm_write(port, 1, UARTDM_NCF_TX);
+}
+
 static void handle_tx(struct uart_port *port)
 {
 	struct circ_buf *xmit = &port->state->xmit;
@@ -128,11 +202,18 @@ static void handle_tx(struct uart_port *port)
 	int sent_tx;
 
 	if (port->x_char) {
-		msm_write(port, port->x_char, UART_TF);
+		if (msm_port->is_uartdm)
+			reset_dm_count(port);
+
+		msm_write(port, port->x_char,
+			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 		port->icount.tx++;
 		port->x_char = 0;
 	}
 
+	if (msm_port->is_uartdm)
+		reset_dm_count(port);
+
 	while (msm_read(port, UART_SR) & UART_SR_TX_READY) {
 		if (uart_circ_empty(xmit)) {
 			/* disable tx interrupts */
@@ -140,8 +221,11 @@ static void handle_tx(struct uart_port *port)
 			msm_write(port, msm_port->imr, UART_IMR);
 			break;
 		}
+		msm_write(port, xmit->buf[xmit->tail],
+			  msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 
-		msm_write(port, xmit->buf[xmit->tail], UART_TF);
+		if (msm_port->is_uartdm)
+			reset_dm_count(port);
 
 		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 		port->icount.tx++;
@@ -169,8 +253,12 @@ static irqreturn_t msm_irq(int irq, void *dev_id)
 	misr = msm_read(port, UART_MISR);
 	msm_write(port, 0, UART_IMR); /* disable interrupt */
 
-	if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE))
-		handle_rx(port);
+	if (misr & (UART_IMR_RXLEV | UART_IMR_RXSTALE)) {
+		if (msm_port->is_uartdm)
+			handle_rx_dm(port, misr);
+		else
+			handle_rx(port);
+	}
 	if (misr & UART_IMR_TXLEV)
 		handle_tx(port);
 	if (misr & UART_IMR_DELTA_CTS)
@@ -192,10 +280,21 @@ static unsigned int msm_get_mctrl(struct uart_port *port)
 	return TIOCM_CAR | TIOCM_CTS | TIOCM_DSR | TIOCM_RTS;
 }
 
-static void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
+
+static void msm_reset(struct uart_port *port)
 {
-	unsigned int mr;
+	/* reset everything */
+	msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
+	msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
+	msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
+	msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
+	msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
+	msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
+}
 
+void msm_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	unsigned int mr;
 	mr = msm_read(port, UART_MR1);
 
 	if (!(mctrl & TIOCM_RTS)) {
@@ -219,6 +318,7 @@ static void msm_break_ctl(struct uart_port *port, int break_ctl)
 static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
 {
 	unsigned int baud_code, rxstale, watermark;
+	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	switch (baud) {
 	case 300:
@@ -273,6 +373,9 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
 		break;
 	}
 
+	if (msm_port->is_uartdm)
+		msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
+
 	msm_write(port, baud_code, UART_CSR);
 
 	/* RX stale watermark */
@@ -288,25 +391,23 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud)
 	/* set TX watermark */
 	msm_write(port, 10, UART_TFWR);
 
+	if (msm_port->is_uartdm) {
+		msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
+		msm_write(port, 0xFFFFFF, UARTDM_DMRX);
+		msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+	}
+
 	return baud;
 }
 
-static void msm_reset(struct uart_port *port)
-{
-	/* reset everything */
-	msm_write(port, UART_CR_CMD_RESET_RX, UART_CR);
-	msm_write(port, UART_CR_CMD_RESET_TX, UART_CR);
-	msm_write(port, UART_CR_CMD_RESET_ERR, UART_CR);
-	msm_write(port, UART_CR_CMD_RESET_BREAK_INT, UART_CR);
-	msm_write(port, UART_CR_CMD_RESET_CTS, UART_CR);
-	msm_write(port, UART_CR_CMD_SET_RFR, UART_CR);
-}
 
 static void msm_init_clock(struct uart_port *port)
 {
 	struct msm_port *msm_port = UART_TO_MSM(port);
 
 	clk_enable(msm_port->clk);
+	if (!IS_ERR(msm_port->pclk))
+		clk_enable(msm_port->pclk);
 	msm_serial_set_mnd_regs(port);
 }
 
@@ -347,15 +448,31 @@ static int msm_startup(struct uart_port *port)
 		msm_write(port, data, UART_IPR);
 	}
 
-	msm_reset(port);
+	data = 0;
+	if (!port->cons || (port->cons && !(port->cons->flags & CON_ENABLED))) {
+		msm_write(port, UART_CR_CMD_PROTECTION_EN, UART_CR);
+		msm_reset(port);
+		data = UART_CR_TX_ENABLE;
+	}
+
+	data |= UART_CR_RX_ENABLE;
+	msm_write(port, data, UART_CR);	/* enable TX & RX */
 
-	msm_write(port, 0x05, UART_CR);	/* enable TX & RX */
+	/* Make sure IPR is not 0 to start with*/
+	if (msm_port->is_uartdm)
+		msm_write(port, UART_IPR_STALE_LSB, UART_IPR);
 
 	/* turn on RX and CTS interrupts */
 	msm_port->imr = UART_IMR_RXLEV | UART_IMR_RXSTALE |
 			UART_IMR_CURRENT_CTS;
-	msm_write(port, msm_port->imr, UART_IMR);
 
+	if (msm_port->is_uartdm) {
+		msm_write(port, 0xFFFFFF, UARTDM_DMRX);
+		msm_write(port, UART_CR_CMD_RESET_STALE_INT, UART_CR);
+		msm_write(port, UART_CR_CMD_STALE_EVENT_ENABLE, UART_CR);
+	}
+
+	msm_write(port, msm_port->imr, UART_IMR);
 	return 0;
 }
 
@@ -384,7 +501,7 @@ static void msm_set_termios(struct uart_port *port, struct ktermios *termios,
 	baud = msm_set_baud_rate(port, baud);
 	if (tty_termios_baud_rate(termios))
 		tty_termios_encode_baud_rate(termios, baud, baud);
-	
+
 	/* calculate parity */
 	mr = msm_read(port, UART_MR2);
 	mr &= ~UART_MR2_PARITY_MODE;
@@ -454,48 +571,105 @@ static const char *msm_type(struct uart_port *port)
 static void msm_release_port(struct uart_port *port)
 {
 	struct platform_device *pdev = to_platform_device(port->dev);
-	struct resource *resource;
+	struct msm_port *msm_port = UART_TO_MSM(port);
+	struct resource *uart_resource;
+	struct resource *gsbi_resource;
 	resource_size_t size;
 
-	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (unlikely(!resource))
+	uart_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!uart_resource))
 		return;
-	size = resource->end - resource->start + 1;
+	size = resource_size(uart_resource);
 
 	release_mem_region(port->mapbase, size);
 	iounmap(port->membase);
 	port->membase = NULL;
+
+	if (msm_port->gsbi_base) {
+		iowrite32(GSBI_PROTOCOL_IDLE, msm_port->gsbi_base +
+			  GSBI_CONTROL);
+
+		gsbi_resource = platform_get_resource_byname(pdev,
+							     IORESOURCE_MEM,
+							     "gsbi_resource");
+
+		if (unlikely(!gsbi_resource))
+			return;
+
+		size = resource_size(gsbi_resource);
+		release_mem_region(gsbi_resource->start, size);
+		iounmap(msm_port->gsbi_base);
+		msm_port->gsbi_base = NULL;
+	}
 }
 
 static int msm_request_port(struct uart_port *port)
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
 	struct platform_device *pdev = to_platform_device(port->dev);
-	struct resource *resource;
+	struct resource *uart_resource;
+	struct resource *gsbi_resource;
 	resource_size_t size;
+	int ret;
 
-	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (unlikely(!resource))
+	uart_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						     "uart_resource");
+	if (unlikely(!uart_resource))
 		return -ENXIO;
-	size = resource->end - resource->start + 1;
 
-	if (unlikely(!request_mem_region(port->mapbase, size, "msm_serial")))
+	size = resource_size(uart_resource);
+
+	if (!request_mem_region(port->mapbase, size, "msm_serial"))
 		return -EBUSY;
 
 	port->membase = ioremap(port->mapbase, size);
 	if (!port->membase) {
-		release_mem_region(port->mapbase, size);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto fail_release_port;
+	}
+
+	gsbi_resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						     "gsbi_resource");
+	/* Is this a GSBI-based port? */
+	if (gsbi_resource) {
+		size = resource_size(gsbi_resource);
+
+		if (!request_mem_region(gsbi_resource->start, size,
+						 "msm_serial")) {
+			ret = -EBUSY;
+			goto fail_release_port;
+		}
+
+		msm_port->gsbi_base = ioremap(gsbi_resource->start, size);
+		if (!msm_port->gsbi_base) {
+			ret = -EBUSY;
+			goto fail_release_gsbi;
+		}
 	}
 
 	return 0;
+
+fail_release_gsbi:
+	release_mem_region(gsbi_resource->start, size);
+fail_release_port:
+	release_mem_region(port->mapbase, size);
+	return ret;
 }
 
 static void msm_config_port(struct uart_port *port, int flags)
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
+	int ret;
 	if (flags & UART_CONFIG_TYPE) {
 		port->type = PORT_MSM;
-		msm_request_port(port);
+		ret = msm_request_port(port);
+		if (ret)
+			return;
 	}
+
+	if (msm_port->is_uartdm)
+		iowrite32(GSBI_PROTOCOL_UART, msm_port->gsbi_base +
+			  GSBI_CONTROL);
 }
 
 static int msm_verify_port(struct uart_port *port, struct serial_struct *ser)
@@ -515,9 +689,13 @@ static void msm_power(struct uart_port *port, unsigned int state,
 	switch (state) {
 	case 0:
 		clk_enable(msm_port->clk);
+		if (!IS_ERR(msm_port->pclk))
+			clk_enable(msm_port->pclk);
 		break;
 	case 3:
 		clk_disable(msm_port->clk);
+		if (!IS_ERR(msm_port->pclk))
+			clk_disable(msm_port->pclk);
 		break;
 	default:
 		printk(KERN_ERR "msm_serial: Unknown PM state %d\n", state);
@@ -550,7 +728,7 @@ static struct msm_port msm_uart_ports[] = {
 			.iotype = UPIO_MEM,
 			.ops = &msm_uart_pops,
 			.flags = UPF_BOOT_AUTOCONF,
-			.fifosize = 512,
+			.fifosize = 64,
 			.line = 0,
 		},
 	},
@@ -559,7 +737,7 @@ static struct msm_port msm_uart_ports[] = {
 			.iotype = UPIO_MEM,
 			.ops = &msm_uart_pops,
 			.flags = UPF_BOOT_AUTOCONF,
-			.fifosize = 512,
+			.fifosize = 64,
 			.line = 1,
 		},
 	},
@@ -585,9 +763,14 @@ static inline struct uart_port *get_port_from_line(unsigned int line)
 
 static void msm_console_putchar(struct uart_port *port, int c)
 {
+	struct msm_port *msm_port = UART_TO_MSM(port);
+
+	if (msm_port->is_uartdm)
+		reset_dm_count(port);
+
 	while (!(msm_read(port, UART_SR) & UART_SR_TX_READY))
 		;
-	msm_write(port, c, UART_TF);
+	msm_write(port, c, msm_port->is_uartdm ? UARTDM_TF : UART_TF);
 }
 
 static void msm_console_write(struct console *co, const char *s,
@@ -609,12 +792,14 @@ static void msm_console_write(struct console *co, const char *s,
 static int __init msm_console_setup(struct console *co, char *options)
 {
 	struct uart_port *port;
+	struct msm_port *msm_port;
 	int baud, flow, bits, parity;
 
 	if (unlikely(co->index >= UART_NR || co->index < 0))
 		return -ENXIO;
 
 	port = get_port_from_line(co->index);
+	msm_port = UART_TO_MSM(port);
 
 	if (unlikely(!port->membase))
 		return -ENXIO;
@@ -638,6 +823,11 @@ static int __init msm_console_setup(struct console *co, char *options)
 
 	msm_reset(port);
 
+	if (msm_port->is_uartdm) {
+		msm_write(port, UART_CR_CMD_PROTECTION_EN, UART_CR);
+		msm_write(port, UART_CR_TX_ENABLE, UART_CR);
+	}
+
 	printk(KERN_INFO "msm_serial: console setup on port #%d\n", port->line);
 
 	return uart_set_options(port, co, baud, parity, bits, flow);
@@ -685,14 +875,32 @@ static int __init msm_serial_probe(struct platform_device *pdev)
 	port->dev = &pdev->dev;
 	msm_port = UART_TO_MSM(port);
 
-	msm_port->clk = clk_get(&pdev->dev, "uart_clk");
-	if (IS_ERR(msm_port->clk))
-		return PTR_ERR(msm_port->clk);
+	if (platform_get_resource_byname(pdev, IORESOURCE_MEM, "gsbi_resource"))
+		msm_port->is_uartdm = 1;
+	else
+		msm_port->is_uartdm = 0;
+
+	if (msm_port->is_uartdm) {
+		msm_port->clk = clk_get(&pdev->dev, "gsbi_uart_clk");
+		msm_port->pclk = clk_get(&pdev->dev, "gsbi_pclk");
+	} else {
+		msm_port->clk = clk_get(&pdev->dev, "uart_clk");
+		msm_port->pclk = ERR_PTR(-ENOENT);
+	}
+
+	if (unlikely(IS_ERR(msm_port->clk) || (IS_ERR(msm_port->pclk) &&
+					       msm_port->is_uartdm)))
+			return PTR_ERR(msm_port->clk);
+
+	if (msm_port->is_uartdm)
+		clk_set_rate(msm_port->clk, 7372800);
+
 	port->uartclk = clk_get_rate(msm_port->clk);
 	printk(KERN_INFO "uartclk = %d\n", port->uartclk);
 
 
-	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						     "uart_resource");
 	if (unlikely(!resource))
 		return -ENXIO;
 	port->mapbase = resource->start;
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
index f6ca9ca..9b8dc5d 100644
--- a/drivers/tty/serial/msm_serial.h
+++ b/drivers/tty/serial/msm_serial.h
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2007 Google, Inc.
  * Author: Robert Love <rlove@google.com>
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -54,6 +55,7 @@
 #define UART_CSR_300	0x22
 
 #define UART_TF		0x000C
+#define UARTDM_TF	0x0070
 
 #define UART_CR				0x0010
 #define UART_CR_CMD_NULL		(0 << 4)
@@ -64,14 +66,17 @@
 #define UART_CR_CMD_START_BREAK		(5 << 4)
 #define UART_CR_CMD_STOP_BREAK		(6 << 4)
 #define UART_CR_CMD_RESET_CTS		(7 << 4)
+#define UART_CR_CMD_RESET_STALE_INT	(8 << 4)
 #define UART_CR_CMD_PACKET_MODE		(9 << 4)
 #define UART_CR_CMD_MODE_RESET		(12 << 4)
 #define UART_CR_CMD_SET_RFR		(13 << 4)
 #define UART_CR_CMD_RESET_RFR		(14 << 4)
+#define UART_CR_CMD_PROTECTION_EN	(16 << 4)
+#define UART_CR_CMD_STALE_EVENT_ENABLE	(80 << 4)
 #define UART_CR_TX_DISABLE		(1 << 3)
-#define UART_CR_TX_ENABLE		(1 << 3)
-#define UART_CR_RX_DISABLE		(1 << 3)
-#define UART_CR_RX_ENABLE		(1 << 3)
+#define UART_CR_TX_ENABLE		(1 << 2)
+#define UART_CR_RX_DISABLE		(1 << 1)
+#define UART_CR_RX_ENABLE		(1 << 0)
 
 #define UART_IMR		0x0014
 #define UART_IMR_TXLEV		(1 << 0)
@@ -110,9 +115,20 @@
 #define UART_SR_RX_FULL		(1 << 1)
 #define UART_SR_RX_READY	(1 << 0)
 
-#define UART_RF		0x000C
-#define UART_MISR	0x0010
-#define UART_ISR	0x0014
+#define UART_RF			0x000C
+#define UARTDM_RF		0x0070
+#define UART_MISR		0x0010
+#define UART_ISR		0x0014
+#define UART_ISR_TX_READY	(1 << 7)
+
+#define GSBI_CONTROL		0x0
+#define GSBI_PROTOCOL_CODE	0x30
+#define GSBI_PROTOCOL_UART	0x40
+#define GSBI_PROTOCOL_IDLE	0x0
+
+#define UARTDM_DMRX		0x34
+#define UARTDM_NCF_TX		0x40
+#define UARTDM_RX_TOTAL_SNAP	0x38
 
 #define UART_TO_MSM(uart_port)	((struct msm_port *) uart_port)
 
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
new file mode 100644
index 0000000..2e7fc9c
--- /dev/null
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -0,0 +1,1880 @@
+/*
+ * MSM 7k/8k High speed uart driver
+ *
+ * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008 Google Inc.
+ * Modified: Nick Pelly <npelly@google.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.
+ *
+ * Has optional support for uart power management independent of linux
+ * suspend/resume:
+ *
+ * RX wakeup.
+ * UART wakeup can be triggered by RX activity (using a wakeup GPIO on the
+ * UART RX pin). This should only be used if there is not a wakeup
+ * GPIO on the UART CTS, and the first RX byte is known (for example, with the
+ * Bluetooth Texas Instruments HCILL protocol), since the first RX byte will
+ * always be lost. RTS will be asserted even while the UART is off in this mode
+ * of operation. See msm_serial_hs_platform_data.rx_wakeup_irq.
+ */
+
+#include <linux/module.h>
+
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+#include <linux/atomic.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include <mach/hardware.h>
+#include <mach/dma.h>
+#include <linux/platform_data/msm_serial_hs.h>
+
+/* HSUART Registers */
+#define UARTDM_MR1_ADDR 0x0
+#define UARTDM_MR2_ADDR 0x4
+
+/* Data Mover result codes */
+#define RSLT_FIFO_CNTR_BMSK (0xE << 28)
+#define RSLT_VLD            BIT(1)
+
+/* write only register */
+#define UARTDM_CSR_ADDR 0x8
+#define UARTDM_CSR_115200 0xFF
+#define UARTDM_CSR_57600  0xEE
+#define UARTDM_CSR_38400  0xDD
+#define UARTDM_CSR_28800  0xCC
+#define UARTDM_CSR_19200  0xBB
+#define UARTDM_CSR_14400  0xAA
+#define UARTDM_CSR_9600   0x99
+#define UARTDM_CSR_7200   0x88
+#define UARTDM_CSR_4800   0x77
+#define UARTDM_CSR_3600   0x66
+#define UARTDM_CSR_2400   0x55
+#define UARTDM_CSR_1200   0x44
+#define UARTDM_CSR_600    0x33
+#define UARTDM_CSR_300    0x22
+#define UARTDM_CSR_150    0x11
+#define UARTDM_CSR_75     0x00
+
+/* write only register */
+#define UARTDM_TF_ADDR 0x70
+#define UARTDM_TF2_ADDR 0x74
+#define UARTDM_TF3_ADDR 0x78
+#define UARTDM_TF4_ADDR 0x7C
+
+/* write only register */
+#define UARTDM_CR_ADDR 0x10
+#define UARTDM_IMR_ADDR 0x14
+
+#define UARTDM_IPR_ADDR 0x18
+#define UARTDM_TFWR_ADDR 0x1c
+#define UARTDM_RFWR_ADDR 0x20
+#define UARTDM_HCR_ADDR 0x24
+#define UARTDM_DMRX_ADDR 0x34
+#define UARTDM_IRDA_ADDR 0x38
+#define UARTDM_DMEN_ADDR 0x3c
+
+/* UART_DM_NO_CHARS_FOR_TX */
+#define UARTDM_NCF_TX_ADDR 0x40
+
+#define UARTDM_BADR_ADDR 0x44
+
+#define UARTDM_SIM_CFG_ADDR 0x80
+/* Read Only register */
+#define UARTDM_SR_ADDR 0x8
+
+/* Read Only register */
+#define UARTDM_RF_ADDR  0x70
+#define UARTDM_RF2_ADDR 0x74
+#define UARTDM_RF3_ADDR 0x78
+#define UARTDM_RF4_ADDR 0x7C
+
+/* Read Only register */
+#define UARTDM_MISR_ADDR 0x10
+
+/* Read Only register */
+#define UARTDM_ISR_ADDR 0x14
+#define UARTDM_RX_TOTAL_SNAP_ADDR 0x38
+
+#define UARTDM_RXFS_ADDR 0x50
+
+/* Register field Mask Mapping */
+#define UARTDM_SR_PAR_FRAME_BMSK        BIT(5)
+#define UARTDM_SR_OVERRUN_BMSK          BIT(4)
+#define UARTDM_SR_TXEMT_BMSK            BIT(3)
+#define UARTDM_SR_TXRDY_BMSK            BIT(2)
+#define UARTDM_SR_RXRDY_BMSK            BIT(0)
+
+#define UARTDM_CR_TX_DISABLE_BMSK       BIT(3)
+#define UARTDM_CR_RX_DISABLE_BMSK       BIT(1)
+#define UARTDM_CR_TX_EN_BMSK            BIT(2)
+#define UARTDM_CR_RX_EN_BMSK            BIT(0)
+
+/* UARTDM_CR channel_comman bit value (register field is bits 8:4) */
+#define RESET_RX                0x10
+#define RESET_TX                0x20
+#define RESET_ERROR_STATUS      0x30
+#define RESET_BREAK_INT         0x40
+#define START_BREAK             0x50
+#define STOP_BREAK              0x60
+#define RESET_CTS               0x70
+#define RESET_STALE_INT         0x80
+#define RFR_LOW                 0xD0
+#define RFR_HIGH                0xE0
+#define CR_PROTECTION_EN        0x100
+#define STALE_EVENT_ENABLE      0x500
+#define STALE_EVENT_DISABLE     0x600
+#define FORCE_STALE_EVENT       0x400
+#define CLEAR_TX_READY          0x300
+#define RESET_TX_ERROR          0x800
+#define RESET_TX_DONE           0x810
+
+#define UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK 0xffffff00
+#define UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK 0x3f
+#define UARTDM_MR1_CTS_CTL_BMSK 0x40
+#define UARTDM_MR1_RX_RDY_CTL_BMSK 0x80
+
+#define UARTDM_MR2_ERROR_MODE_BMSK 0x40
+#define UARTDM_MR2_BITS_PER_CHAR_BMSK 0x30
+
+/* bits per character configuration */
+#define FIVE_BPC  (0 << 4)
+#define SIX_BPC   (1 << 4)
+#define SEVEN_BPC (2 << 4)
+#define EIGHT_BPC (3 << 4)
+
+#define UARTDM_MR2_STOP_BIT_LEN_BMSK 0xc
+#define STOP_BIT_ONE (1 << 2)
+#define STOP_BIT_TWO (3 << 2)
+
+#define UARTDM_MR2_PARITY_MODE_BMSK 0x3
+
+/* Parity configuration */
+#define NO_PARITY 0x0
+#define EVEN_PARITY 0x1
+#define ODD_PARITY 0x2
+#define SPACE_PARITY 0x3
+
+#define UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK 0xffffff80
+#define UARTDM_IPR_STALE_LSB_BMSK 0x1f
+
+/* These can be used for both ISR and IMR register */
+#define UARTDM_ISR_TX_READY_BMSK        BIT(7)
+#define UARTDM_ISR_CURRENT_CTS_BMSK     BIT(6)
+#define UARTDM_ISR_DELTA_CTS_BMSK       BIT(5)
+#define UARTDM_ISR_RXLEV_BMSK           BIT(4)
+#define UARTDM_ISR_RXSTALE_BMSK         BIT(3)
+#define UARTDM_ISR_RXBREAK_BMSK         BIT(2)
+#define UARTDM_ISR_RXHUNT_BMSK          BIT(1)
+#define UARTDM_ISR_TXLEV_BMSK           BIT(0)
+
+/* Field definitions for UART_DM_DMEN*/
+#define UARTDM_TX_DM_EN_BMSK 0x1
+#define UARTDM_RX_DM_EN_BMSK 0x2
+
+#define UART_FIFOSIZE 64
+#define UARTCLK 7372800
+
+/* Rx DMA request states */
+enum flush_reason {
+	FLUSH_NONE,
+	FLUSH_DATA_READY,
+	FLUSH_DATA_INVALID,  /* values after this indicate invalid data */
+	FLUSH_IGNORE = FLUSH_DATA_INVALID,
+	FLUSH_STOP,
+	FLUSH_SHUTDOWN,
+};
+
+/* UART clock states */
+enum msm_hs_clk_states_e {
+	MSM_HS_CLK_PORT_OFF,     /* port not in use */
+	MSM_HS_CLK_OFF,          /* clock disabled */
+	MSM_HS_CLK_REQUEST_OFF,  /* disable after TX and RX flushed */
+	MSM_HS_CLK_ON,           /* clock enabled */
+};
+
+/* Track the forced RXSTALE flush during clock off sequence.
+ * These states are only valid during MSM_HS_CLK_REQUEST_OFF */
+enum msm_hs_clk_req_off_state_e {
+	CLK_REQ_OFF_START,
+	CLK_REQ_OFF_RXSTALE_ISSUED,
+	CLK_REQ_OFF_FLUSH_ISSUED,
+	CLK_REQ_OFF_RXSTALE_FLUSHED,
+};
+
+/**
+ * struct msm_hs_tx
+ * @tx_ready_int_en: ok to dma more tx?
+ * @dma_in_flight: tx dma in progress
+ * @xfer: top level DMA command pointer structure
+ * @command_ptr: third level command struct pointer
+ * @command_ptr_ptr: second level command list struct pointer
+ * @mapped_cmd_ptr: DMA view of third level command struct
+ * @mapped_cmd_ptr_ptr: DMA view of second level command list struct
+ * @tx_count: number of bytes to transfer in DMA transfer
+ * @dma_base: DMA view of UART xmit buffer
+ *
+ * This structure describes a single Tx DMA transaction. MSM DMA
+ * commands have two levels of indirection. The top level command
+ * ptr points to a list of command ptr which in turn points to a
+ * single DMA 'command'. In our case each Tx transaction consists
+ * of a single second level pointer pointing to a 'box type' command.
+ */
+struct msm_hs_tx {
+	unsigned int tx_ready_int_en;
+	unsigned int dma_in_flight;
+	struct msm_dmov_cmd xfer;
+	dmov_box *command_ptr;
+	u32 *command_ptr_ptr;
+	dma_addr_t mapped_cmd_ptr;
+	dma_addr_t mapped_cmd_ptr_ptr;
+	int tx_count;
+	dma_addr_t dma_base;
+};
+
+/**
+ * struct msm_hs_rx
+ * @flush: Rx DMA request state
+ * @xfer: top level DMA command pointer structure
+ * @cmdptr_dmaaddr: DMA view of second level command structure
+ * @command_ptr: third level DMA command pointer structure
+ * @command_ptr_ptr: second level DMA command list pointer
+ * @mapped_cmd_ptr: DMA view of the third level command structure
+ * @wait: wait for DMA completion before shutdown
+ * @buffer: destination buffer for RX DMA
+ * @rbuffer: DMA view of buffer
+ * @pool: dma pool out of which coherent rx buffer is allocated
+ * @tty_work: private work-queue for tty flip buffer push task
+ *
+ * This structure describes a single Rx DMA transaction. Rx DMA
+ * transactions use box mode DMA commands.
+ */
+struct msm_hs_rx {
+	enum flush_reason flush;
+	struct msm_dmov_cmd xfer;
+	dma_addr_t cmdptr_dmaaddr;
+	dmov_box *command_ptr;
+	u32 *command_ptr_ptr;
+	dma_addr_t mapped_cmd_ptr;
+	wait_queue_head_t wait;
+	dma_addr_t rbuffer;
+	unsigned char *buffer;
+	struct dma_pool *pool;
+	struct work_struct tty_work;
+};
+
+/**
+ * struct msm_hs_rx_wakeup
+ * @irq: IRQ line to be configured as interrupt source on Rx activity
+ * @ignore: boolean value. 1 = ignore the wakeup interrupt
+ * @rx_to_inject: extra character to be inserted to Rx tty on wakeup
+ * @inject_rx: 1 = insert rx_to_inject. 0 = do not insert extra character
+ *
+ * This is an optional structure required for UART Rx GPIO IRQ based
+ * wakeup from low power state. UART wakeup can be triggered by RX activity
+ * (using a wakeup GPIO on the UART RX pin). This should only be used if
+ * there is not a wakeup GPIO on the UART CTS, and the first RX byte is
+ * known (eg., with the Bluetooth Texas Instruments HCILL protocol),
+ * since the first RX byte will always be lost. RTS will be asserted even
+ * while the UART is clocked off in this mode of operation.
+ */
+struct msm_hs_rx_wakeup {
+	int irq;  /* < 0 indicates low power wakeup disabled */
+	unsigned char ignore;
+	unsigned char inject_rx;
+	char rx_to_inject;
+};
+
+/**
+ * struct msm_hs_port
+ * @uport: embedded uart port structure
+ * @imr_reg: shadow value of UARTDM_IMR
+ * @clk: uart input clock handle
+ * @tx: Tx transaction related data structure
+ * @rx: Rx transaction related data structure
+ * @dma_tx_channel: Tx DMA command channel
+ * @dma_rx_channel Rx DMA command channel
+ * @dma_tx_crci: Tx channel rate control interface number
+ * @dma_rx_crci: Rx channel rate control interface number
+ * @clk_off_timer: Timer to poll DMA event completion before clock off
+ * @clk_off_delay: clk_off_timer poll interval
+ * @clk_state: overall clock state
+ * @clk_req_off_state: post flush clock states
+ * @rx_wakeup: optional rx_wakeup feature related data
+ * @exit_lpm_cb: optional callback to exit low power mode
+ *
+ * Low level serial port structure.
+ */
+struct msm_hs_port {
+	struct uart_port uport;
+	unsigned long imr_reg;
+	struct clk *clk;
+	struct msm_hs_tx tx;
+	struct msm_hs_rx rx;
+
+	int dma_tx_channel;
+	int dma_rx_channel;
+	int dma_tx_crci;
+	int dma_rx_crci;
+
+	struct hrtimer clk_off_timer;
+	ktime_t clk_off_delay;
+	enum msm_hs_clk_states_e clk_state;
+	enum msm_hs_clk_req_off_state_e clk_req_off_state;
+
+	struct msm_hs_rx_wakeup rx_wakeup;
+	void (*exit_lpm_cb)(struct uart_port *);
+};
+
+#define MSM_UARTDM_BURST_SIZE 16   /* DM burst size (in bytes) */
+#define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
+#define UARTDM_RX_BUF_SIZE 512
+
+#define UARTDM_NR 2
+
+static struct msm_hs_port q_uart_port[UARTDM_NR];
+static struct platform_driver msm_serial_hs_platform_driver;
+static struct uart_driver msm_hs_driver;
+static struct uart_ops msm_hs_ops;
+static struct workqueue_struct *msm_hs_workqueue;
+
+#define UARTDM_TO_MSM(uart_port) \
+	container_of((uart_port), struct msm_hs_port, uport)
+
+static unsigned int use_low_power_rx_wakeup(struct msm_hs_port
+						   *msm_uport)
+{
+	return (msm_uport->rx_wakeup.irq >= 0);
+}
+
+static unsigned int msm_hs_read(struct uart_port *uport,
+				       unsigned int offset)
+{
+	return ioread32(uport->membase + offset);
+}
+
+static void msm_hs_write(struct uart_port *uport, unsigned int offset,
+				 unsigned int value)
+{
+	iowrite32(value, uport->membase + offset);
+}
+
+static void msm_hs_release_port(struct uart_port *port)
+{
+	iounmap(port->membase);
+}
+
+static int msm_hs_request_port(struct uart_port *port)
+{
+	port->membase = ioremap(port->mapbase, PAGE_SIZE);
+	if (unlikely(!port->membase))
+		return -ENOMEM;
+
+	/* configure the CR Protection to Enable */
+	msm_hs_write(port, UARTDM_CR_ADDR, CR_PROTECTION_EN);
+	return 0;
+}
+
+static int __devexit msm_hs_remove(struct platform_device *pdev)
+{
+
+	struct msm_hs_port *msm_uport;
+	struct device *dev;
+
+	if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
+		printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	msm_uport = &q_uart_port[pdev->id];
+	dev = msm_uport->uport.dev;
+
+	dma_unmap_single(dev, msm_uport->rx.mapped_cmd_ptr, sizeof(dmov_box),
+			 DMA_TO_DEVICE);
+	dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
+		      msm_uport->rx.rbuffer);
+	dma_pool_destroy(msm_uport->rx.pool);
+
+	dma_unmap_single(dev, msm_uport->rx.cmdptr_dmaaddr, sizeof(u32 *),
+			 DMA_TO_DEVICE);
+	dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr_ptr, sizeof(u32 *),
+			 DMA_TO_DEVICE);
+	dma_unmap_single(dev, msm_uport->tx.mapped_cmd_ptr, sizeof(dmov_box),
+			 DMA_TO_DEVICE);
+
+	uart_remove_one_port(&msm_hs_driver, &msm_uport->uport);
+	clk_put(msm_uport->clk);
+
+	/* Free the tx resources */
+	kfree(msm_uport->tx.command_ptr);
+	kfree(msm_uport->tx.command_ptr_ptr);
+
+	/* Free the rx resources */
+	kfree(msm_uport->rx.command_ptr);
+	kfree(msm_uport->rx.command_ptr_ptr);
+
+	iounmap(msm_uport->uport.membase);
+
+	return 0;
+}
+
+static int msm_hs_init_clk_locked(struct uart_port *uport)
+{
+	int ret;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	ret = clk_enable(msm_uport->clk);
+	if (ret) {
+		printk(KERN_ERR "Error could not turn on UART clk\n");
+		return ret;
+	}
+
+	/* Set up the MREG/NREG/DREG/MNDREG */
+	ret = clk_set_rate(msm_uport->clk, uport->uartclk);
+	if (ret) {
+		printk(KERN_WARNING "Error setting clock rate on UART\n");
+		clk_disable(msm_uport->clk);
+		return ret;
+	}
+
+	msm_uport->clk_state = MSM_HS_CLK_ON;
+	return 0;
+}
+
+/* Enable and Disable clocks  (Used for power management) */
+static void msm_hs_pm(struct uart_port *uport, unsigned int state,
+		      unsigned int oldstate)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	if (use_low_power_rx_wakeup(msm_uport) ||
+	    msm_uport->exit_lpm_cb)
+		return;  /* ignore linux PM states,
+			    use msm_hs_request_clock API */
+
+	switch (state) {
+	case 0:
+		clk_enable(msm_uport->clk);
+		break;
+	case 3:
+		clk_disable(msm_uport->clk);
+		break;
+	default:
+		dev_err(uport->dev, "msm_serial: Unknown PM state %d\n",
+			state);
+	}
+}
+
+/*
+ * programs the UARTDM_CSR register with correct bit rates
+ *
+ * Interrupts should be disabled before we are called, as
+ * we modify Set Baud rate
+ * Set receive stale interrupt level, dependant on Bit Rate
+ * Goal is to have around 8 ms before indicate stale.
+ * roundup (((Bit Rate * .008) / 10) + 1
+ */
+static void msm_hs_set_bps_locked(struct uart_port *uport,
+				  unsigned int bps)
+{
+	unsigned long rxstale;
+	unsigned long data;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	switch (bps) {
+	case 300:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_75);
+		rxstale = 1;
+		break;
+	case 600:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_150);
+		rxstale = 1;
+		break;
+	case 1200:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_300);
+		rxstale = 1;
+		break;
+	case 2400:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_600);
+		rxstale = 1;
+		break;
+	case 4800:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_1200);
+		rxstale = 1;
+		break;
+	case 9600:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_2400);
+		rxstale = 2;
+		break;
+	case 14400:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_3600);
+		rxstale = 3;
+		break;
+	case 19200:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_4800);
+		rxstale = 4;
+		break;
+	case 28800:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_7200);
+		rxstale = 6;
+		break;
+	case 38400:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_9600);
+		rxstale = 8;
+		break;
+	case 57600:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_14400);
+		rxstale = 16;
+		break;
+	case 76800:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_19200);
+		rxstale = 16;
+		break;
+	case 115200:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_28800);
+		rxstale = 31;
+		break;
+	case 230400:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_57600);
+		rxstale = 31;
+		break;
+	case 460800:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_115200);
+		rxstale = 31;
+		break;
+	case 4000000:
+	case 3686400:
+	case 3200000:
+	case 3500000:
+	case 3000000:
+	case 2500000:
+	case 1500000:
+	case 1152000:
+	case 1000000:
+	case 921600:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_115200);
+		rxstale = 31;
+		break;
+	default:
+		msm_hs_write(uport, UARTDM_CSR_ADDR, UARTDM_CSR_2400);
+		/* default to 9600 */
+		bps = 9600;
+		rxstale = 2;
+		break;
+	}
+	if (bps > 460800)
+		uport->uartclk = bps * 16;
+	else
+		uport->uartclk = UARTCLK;
+
+	if (clk_set_rate(msm_uport->clk, uport->uartclk)) {
+		printk(KERN_WARNING "Error setting clock rate on UART\n");
+		return;
+	}
+
+	data = rxstale & UARTDM_IPR_STALE_LSB_BMSK;
+	data |= UARTDM_IPR_STALE_TIMEOUT_MSB_BMSK & (rxstale << 2);
+
+	msm_hs_write(uport, UARTDM_IPR_ADDR, data);
+}
+
+/*
+ * termios :  new ktermios
+ * oldtermios:  old ktermios previous setting
+ *
+ * Configure the serial port
+ */
+static void msm_hs_set_termios(struct uart_port *uport,
+			       struct ktermios *termios,
+			       struct ktermios *oldtermios)
+{
+	unsigned int bps;
+	unsigned long data;
+	unsigned long flags;
+	unsigned int c_cflag = termios->c_cflag;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	spin_lock_irqsave(&uport->lock, flags);
+	clk_enable(msm_uport->clk);
+
+	/* 300 is the minimum baud support by the driver  */
+	bps = uart_get_baud_rate(uport, termios, oldtermios, 200, 4000000);
+
+	/* Temporary remapping  200 BAUD to 3.2 mbps */
+	if (bps == 200)
+		bps = 3200000;
+
+	msm_hs_set_bps_locked(uport, bps);
+
+	data = msm_hs_read(uport, UARTDM_MR2_ADDR);
+	data &= ~UARTDM_MR2_PARITY_MODE_BMSK;
+	/* set parity */
+	if (PARENB == (c_cflag & PARENB)) {
+		if (PARODD == (c_cflag & PARODD))
+			data |= ODD_PARITY;
+		else if (CMSPAR == (c_cflag & CMSPAR))
+			data |= SPACE_PARITY;
+		else
+			data |= EVEN_PARITY;
+	}
+
+	/* Set bits per char */
+	data &= ~UARTDM_MR2_BITS_PER_CHAR_BMSK;
+
+	switch (c_cflag & CSIZE) {
+	case CS5:
+		data |= FIVE_BPC;
+		break;
+	case CS6:
+		data |= SIX_BPC;
+		break;
+	case CS7:
+		data |= SEVEN_BPC;
+		break;
+	default:
+		data |= EIGHT_BPC;
+		break;
+	}
+	/* stop bits */
+	if (c_cflag & CSTOPB) {
+		data |= STOP_BIT_TWO;
+	} else {
+		/* otherwise 1 stop bit */
+		data |= STOP_BIT_ONE;
+	}
+	data |= UARTDM_MR2_ERROR_MODE_BMSK;
+	/* write parity/bits per char/stop bit configuration */
+	msm_hs_write(uport, UARTDM_MR2_ADDR, data);
+
+	/* Configure HW flow control */
+	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
+
+	data &= ~(UARTDM_MR1_CTS_CTL_BMSK | UARTDM_MR1_RX_RDY_CTL_BMSK);
+
+	if (c_cflag & CRTSCTS) {
+		data |= UARTDM_MR1_CTS_CTL_BMSK;
+		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
+	}
+
+	msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+
+	uport->ignore_status_mask = termios->c_iflag & INPCK;
+	uport->ignore_status_mask |= termios->c_iflag & IGNPAR;
+	uport->read_status_mask = (termios->c_cflag & CREAD);
+
+	msm_hs_write(uport, UARTDM_IMR_ADDR, 0);
+
+	/* Set Transmit software time out */
+	uart_update_timeout(uport, c_cflag, bps);
+
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
+
+	if (msm_uport->rx.flush == FLUSH_NONE) {
+		msm_uport->rx.flush = FLUSH_IGNORE;
+		msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1);
+	}
+
+	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+
+	clk_disable(msm_uport->clk);
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+/*
+ *  Standard API, Transmitter
+ *  Any character in the transmit shift register is sent
+ */
+static unsigned int msm_hs_tx_empty(struct uart_port *uport)
+{
+	unsigned int data;
+	unsigned int ret = 0;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	clk_enable(msm_uport->clk);
+
+	data = msm_hs_read(uport, UARTDM_SR_ADDR);
+	if (data & UARTDM_SR_TXEMT_BMSK)
+		ret = TIOCSER_TEMT;
+
+	clk_disable(msm_uport->clk);
+
+	return ret;
+}
+
+/*
+ *  Standard API, Stop transmitter.
+ *  Any character in the transmit shift register is sent as
+ *  well as the current data mover transfer .
+ */
+static void msm_hs_stop_tx_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	msm_uport->tx.tx_ready_int_en = 0;
+}
+
+/*
+ *  Standard API, Stop receiver as soon as possible.
+ *
+ *  Function immediately terminates the operation of the
+ *  channel receiver and any incoming characters are lost. None
+ *  of the receiver status bits are affected by this command and
+ *  characters that are already in the receive FIFO there.
+ */
+static void msm_hs_stop_rx_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	unsigned int data;
+
+	clk_enable(msm_uport->clk);
+
+	/* disable dlink */
+	data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+	data &= ~UARTDM_RX_DM_EN_BMSK;
+	msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+
+	/* Disable the receiver */
+	if (msm_uport->rx.flush == FLUSH_NONE)
+		msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1);
+
+	if (msm_uport->rx.flush != FLUSH_SHUTDOWN)
+		msm_uport->rx.flush = FLUSH_STOP;
+
+	clk_disable(msm_uport->clk);
+}
+
+/*  Transmit the next chunk of data */
+static void msm_hs_submit_tx_locked(struct uart_port *uport)
+{
+	int left;
+	int tx_count;
+	dma_addr_t src_addr;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	struct msm_hs_tx *tx = &msm_uport->tx;
+	struct circ_buf *tx_buf = &msm_uport->uport.state->xmit;
+
+	if (uart_circ_empty(tx_buf) || uport->state->port.tty->stopped) {
+		msm_hs_stop_tx_locked(uport);
+		return;
+	}
+
+	tx->dma_in_flight = 1;
+
+	tx_count = uart_circ_chars_pending(tx_buf);
+
+	if (UARTDM_TX_BUF_SIZE < tx_count)
+		tx_count = UARTDM_TX_BUF_SIZE;
+
+	left = UART_XMIT_SIZE - tx_buf->tail;
+
+	if (tx_count > left)
+		tx_count = left;
+
+	src_addr = tx->dma_base + tx_buf->tail;
+	dma_sync_single_for_device(uport->dev, src_addr, tx_count,
+				   DMA_TO_DEVICE);
+
+	tx->command_ptr->num_rows = (((tx_count + 15) >> 4) << 16) |
+				     ((tx_count + 15) >> 4);
+	tx->command_ptr->src_row_addr = src_addr;
+
+	dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr,
+				   sizeof(dmov_box), DMA_TO_DEVICE);
+
+	*tx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(tx->mapped_cmd_ptr);
+
+	dma_sync_single_for_device(uport->dev, tx->mapped_cmd_ptr_ptr,
+				   sizeof(u32 *), DMA_TO_DEVICE);
+
+	/* Save tx_count to use in Callback */
+	tx->tx_count = tx_count;
+	msm_hs_write(uport, UARTDM_NCF_TX_ADDR, tx_count);
+
+	/* Disable the tx_ready interrupt */
+	msm_uport->imr_reg &= ~UARTDM_ISR_TX_READY_BMSK;
+	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer);
+}
+
+/* Start to receive the next chunk of data */
+static void msm_hs_start_rx_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
+	msm_hs_write(uport, UARTDM_DMRX_ADDR, UARTDM_RX_BUF_SIZE);
+	msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_ENABLE);
+	msm_uport->imr_reg |= UARTDM_ISR_RXLEV_BMSK;
+	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+
+	msm_uport->rx.flush = FLUSH_NONE;
+	msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel, &msm_uport->rx.xfer);
+
+	/* might have finished RX and be ready to clock off */
+	hrtimer_start(&msm_uport->clk_off_timer, msm_uport->clk_off_delay,
+			HRTIMER_MODE_REL);
+}
+
+/* Enable the transmitter Interrupt */
+static void msm_hs_start_tx_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	clk_enable(msm_uport->clk);
+
+	if (msm_uport->exit_lpm_cb)
+		msm_uport->exit_lpm_cb(uport);
+
+	if (msm_uport->tx.tx_ready_int_en == 0) {
+		msm_uport->tx.tx_ready_int_en = 1;
+		msm_hs_submit_tx_locked(uport);
+	}
+
+	clk_disable(msm_uport->clk);
+}
+
+/*
+ *  This routine is called when we are done with a DMA transfer
+ *
+ *  This routine is registered with Data mover when we set
+ *  up a Data Mover transfer. It is called from Data mover ISR
+ *  when the DMA transfer is done.
+ */
+static void msm_hs_dmov_tx_callback(struct msm_dmov_cmd *cmd_ptr,
+					unsigned int result,
+					struct msm_dmov_errdata *err)
+{
+	unsigned long flags;
+	struct msm_hs_port *msm_uport;
+
+	/* DMA did not finish properly */
+	WARN_ON((((result & RSLT_FIFO_CNTR_BMSK) >> 28) == 1) &&
+		!(result & RSLT_VLD));
+
+	msm_uport = container_of(cmd_ptr, struct msm_hs_port, tx.xfer);
+
+	spin_lock_irqsave(&msm_uport->uport.lock, flags);
+	clk_enable(msm_uport->clk);
+
+	msm_uport->imr_reg |= UARTDM_ISR_TX_READY_BMSK;
+	msm_hs_write(&msm_uport->uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+
+	clk_disable(msm_uport->clk);
+	spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
+}
+
+/*
+ * This routine is called when we are done with a DMA transfer or the
+ * a flush has been sent to the data mover driver.
+ *
+ * This routine is registered with Data mover when we set up a Data Mover
+ *  transfer. It is called from Data mover ISR when the DMA transfer is done.
+ */
+static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
+					unsigned int result,
+					struct msm_dmov_errdata *err)
+{
+	int retval;
+	int rx_count;
+	unsigned long status;
+	unsigned int error_f = 0;
+	unsigned long flags;
+	unsigned int flush;
+	struct tty_struct *tty;
+	struct uart_port *uport;
+	struct msm_hs_port *msm_uport;
+
+	msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer);
+	uport = &msm_uport->uport;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	clk_enable(msm_uport->clk);
+
+	tty = uport->state->port.tty;
+
+	msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
+
+	status = msm_hs_read(uport, UARTDM_SR_ADDR);
+
+	/* overflow is not connect to data in a FIFO */
+	if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) &&
+		     (uport->read_status_mask & CREAD))) {
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		uport->icount.buf_overrun++;
+		error_f = 1;
+	}
+
+	if (!(uport->ignore_status_mask & INPCK))
+		status = status & ~(UARTDM_SR_PAR_FRAME_BMSK);
+
+	if (unlikely(status & UARTDM_SR_PAR_FRAME_BMSK)) {
+		/* Can not tell difference between parity & frame error */
+		uport->icount.parity++;
+		error_f = 1;
+		if (uport->ignore_status_mask & IGNPAR)
+			tty_insert_flip_char(tty, 0, TTY_PARITY);
+	}
+
+	if (error_f)
+		msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
+
+	if (msm_uport->clk_req_off_state == CLK_REQ_OFF_FLUSH_ISSUED)
+		msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_FLUSHED;
+
+	flush = msm_uport->rx.flush;
+	if (flush == FLUSH_IGNORE)
+		msm_hs_start_rx_locked(uport);
+	if (flush == FLUSH_STOP)
+		msm_uport->rx.flush = FLUSH_SHUTDOWN;
+	if (flush >= FLUSH_DATA_INVALID)
+		goto out;
+
+	rx_count = msm_hs_read(uport, UARTDM_RX_TOTAL_SNAP_ADDR);
+
+	if (0 != (uport->read_status_mask & CREAD)) {
+		retval = tty_insert_flip_string(tty, msm_uport->rx.buffer,
+						rx_count);
+		BUG_ON(retval != rx_count);
+	}
+
+	msm_hs_start_rx_locked(uport);
+
+out:
+	clk_disable(msm_uport->clk);
+
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	if (flush < FLUSH_DATA_INVALID)
+		queue_work(msm_hs_workqueue, &msm_uport->rx.tty_work);
+}
+
+static void msm_hs_tty_flip_buffer_work(struct work_struct *work)
+{
+	struct msm_hs_port *msm_uport =
+			container_of(work, struct msm_hs_port, rx.tty_work);
+	struct tty_struct *tty = msm_uport->uport.state->port.tty;
+
+	tty_flip_buffer_push(tty);
+}
+
+/*
+ *  Standard API, Current states of modem control inputs
+ *
+ * Since CTS can be handled entirely by HARDWARE we always
+ * indicate clear to send and count on the TX FIFO to block when
+ * it fills up.
+ *
+ * - TIOCM_DCD
+ * - TIOCM_CTS
+ * - TIOCM_DSR
+ * - TIOCM_RI
+ *  (Unsupported) DCD and DSR will return them high. RI will return low.
+ */
+static unsigned int msm_hs_get_mctrl_locked(struct uart_port *uport)
+{
+	return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
+}
+
+/*
+ * True enables UART auto RFR, which indicates we are ready for data if the RX
+ * buffer is not full. False disables auto RFR, and deasserts RFR to indicate
+ * we are not ready for data. Must be called with UART clock on.
+ */
+static void set_rfr_locked(struct uart_port *uport, int auto_rfr)
+{
+	unsigned int data;
+
+	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
+
+	if (auto_rfr) {
+		/* enable auto ready-for-receiving */
+		data |= UARTDM_MR1_RX_RDY_CTL_BMSK;
+		msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+	} else {
+		/* disable auto ready-for-receiving */
+		data &= ~UARTDM_MR1_RX_RDY_CTL_BMSK;
+		msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+		/* RFR is active low, set high */
+		msm_hs_write(uport, UARTDM_CR_ADDR, RFR_HIGH);
+	}
+}
+
+/*
+ *  Standard API, used to set or clear RFR
+ */
+static void msm_hs_set_mctrl_locked(struct uart_port *uport,
+				    unsigned int mctrl)
+{
+	unsigned int auto_rfr;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	clk_enable(msm_uport->clk);
+
+	auto_rfr = TIOCM_RTS & mctrl ? 1 : 0;
+	set_rfr_locked(uport, auto_rfr);
+
+	clk_disable(msm_uport->clk);
+}
+
+/* Standard API, Enable modem status (CTS) interrupt  */
+static void msm_hs_enable_ms_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	clk_enable(msm_uport->clk);
+
+	/* Enable DELTA_CTS Interrupt */
+	msm_uport->imr_reg |= UARTDM_ISR_DELTA_CTS_BMSK;
+	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+
+	clk_disable(msm_uport->clk);
+
+}
+
+/*
+ *  Standard API, Break Signal
+ *
+ * Control the transmission of a break signal. ctl eq 0 => break
+ * signal terminate ctl ne 0 => start break signal
+ */
+static void msm_hs_break_ctl(struct uart_port *uport, int ctl)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	clk_enable(msm_uport->clk);
+	msm_hs_write(uport, UARTDM_CR_ADDR, ctl ? START_BREAK : STOP_BREAK);
+	clk_disable(msm_uport->clk);
+}
+
+static void msm_hs_config_port(struct uart_port *uport, int cfg_flags)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	if (cfg_flags & UART_CONFIG_TYPE) {
+		uport->type = PORT_MSM;
+		msm_hs_request_port(uport);
+	}
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+/*  Handle CTS changes (Called from interrupt handler) */
+static void msm_hs_handle_delta_cts(struct uart_port *uport)
+{
+	unsigned long flags;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	spin_lock_irqsave(&uport->lock, flags);
+	clk_enable(msm_uport->clk);
+
+	/* clear interrupt */
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
+	uport->icount.cts++;
+
+	clk_disable(msm_uport->clk);
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	/* clear the IOCTL TIOCMIWAIT if called */
+	wake_up_interruptible(&uport->state->port.delta_msr_wait);
+}
+
+/* check if the TX path is flushed, and if so clock off
+ * returns 0 did not clock off, need to retry (still sending final byte)
+ *        -1 did not clock off, do not retry
+ *         1 if we clocked off
+ */
+static int msm_hs_check_clock_off_locked(struct uart_port *uport)
+{
+	unsigned long sr_status;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	struct circ_buf *tx_buf = &uport->state->xmit;
+
+	/* Cancel if tx tty buffer is not empty, dma is in flight,
+	 * or tx fifo is not empty, or rx fifo is not empty */
+	if (msm_uport->clk_state != MSM_HS_CLK_REQUEST_OFF ||
+	    !uart_circ_empty(tx_buf) || msm_uport->tx.dma_in_flight ||
+	    (msm_uport->imr_reg & UARTDM_ISR_TXLEV_BMSK) ||
+	    !(msm_uport->imr_reg & UARTDM_ISR_RXLEV_BMSK))  {
+		return -1;
+	}
+
+	/* Make sure the uart is finished with the last byte */
+	sr_status = msm_hs_read(uport, UARTDM_SR_ADDR);
+	if (!(sr_status & UARTDM_SR_TXEMT_BMSK))
+		return 0;  /* retry */
+
+	/* Make sure forced RXSTALE flush complete */
+	switch (msm_uport->clk_req_off_state) {
+	case CLK_REQ_OFF_START:
+		msm_uport->clk_req_off_state = CLK_REQ_OFF_RXSTALE_ISSUED;
+		msm_hs_write(uport, UARTDM_CR_ADDR, FORCE_STALE_EVENT);
+		return 0;  /* RXSTALE flush not complete - retry */
+	case CLK_REQ_OFF_RXSTALE_ISSUED:
+	case CLK_REQ_OFF_FLUSH_ISSUED:
+		return 0;  /* RXSTALE flush not complete - retry */
+	case CLK_REQ_OFF_RXSTALE_FLUSHED:
+		break;  /* continue */
+	}
+
+	if (msm_uport->rx.flush != FLUSH_SHUTDOWN) {
+		if (msm_uport->rx.flush == FLUSH_NONE)
+			msm_hs_stop_rx_locked(uport);
+		return 0;  /* come back later to really clock off */
+	}
+
+	/* we really want to clock off */
+	clk_disable(msm_uport->clk);
+	msm_uport->clk_state = MSM_HS_CLK_OFF;
+
+	if (use_low_power_rx_wakeup(msm_uport)) {
+		msm_uport->rx_wakeup.ignore = 1;
+		enable_irq(msm_uport->rx_wakeup.irq);
+	}
+	return 1;
+}
+
+static enum hrtimer_restart msm_hs_clk_off_retry(struct hrtimer *timer)
+{
+	unsigned long flags;
+	int ret = HRTIMER_NORESTART;
+	struct msm_hs_port *msm_uport = container_of(timer, struct msm_hs_port,
+						     clk_off_timer);
+	struct uart_port *uport = &msm_uport->uport;
+
+	spin_lock_irqsave(&uport->lock, flags);
+
+	if (!msm_hs_check_clock_off_locked(uport)) {
+		hrtimer_forward_now(timer, msm_uport->clk_off_delay);
+		ret = HRTIMER_RESTART;
+	}
+
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	return ret;
+}
+
+static irqreturn_t msm_hs_isr(int irq, void *dev)
+{
+	unsigned long flags;
+	unsigned long isr_status;
+	struct msm_hs_port *msm_uport = dev;
+	struct uart_port *uport = &msm_uport->uport;
+	struct circ_buf *tx_buf = &uport->state->xmit;
+	struct msm_hs_tx *tx = &msm_uport->tx;
+	struct msm_hs_rx *rx = &msm_uport->rx;
+
+	spin_lock_irqsave(&uport->lock, flags);
+
+	isr_status = msm_hs_read(uport, UARTDM_MISR_ADDR);
+
+	/* Uart RX starting */
+	if (isr_status & UARTDM_ISR_RXLEV_BMSK) {
+		msm_uport->imr_reg &= ~UARTDM_ISR_RXLEV_BMSK;
+		msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	}
+	/* Stale rx interrupt */
+	if (isr_status & UARTDM_ISR_RXSTALE_BMSK) {
+		msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);
+		msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
+
+		if (msm_uport->clk_req_off_state == CLK_REQ_OFF_RXSTALE_ISSUED)
+			msm_uport->clk_req_off_state =
+					CLK_REQ_OFF_FLUSH_ISSUED;
+		if (rx->flush == FLUSH_NONE) {
+			rx->flush = FLUSH_DATA_READY;
+			msm_dmov_stop_cmd(msm_uport->dma_rx_channel, NULL, 1);
+		}
+	}
+	/* tx ready interrupt */
+	if (isr_status & UARTDM_ISR_TX_READY_BMSK) {
+		/* Clear  TX Ready */
+		msm_hs_write(uport, UARTDM_CR_ADDR, CLEAR_TX_READY);
+
+		if (msm_uport->clk_state == MSM_HS_CLK_REQUEST_OFF) {
+			msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
+			msm_hs_write(uport, UARTDM_IMR_ADDR,
+				     msm_uport->imr_reg);
+		}
+
+		/* Complete DMA TX transactions and submit new transactions */
+		tx_buf->tail = (tx_buf->tail + tx->tx_count) & ~UART_XMIT_SIZE;
+
+		tx->dma_in_flight = 0;
+
+		uport->icount.tx += tx->tx_count;
+		if (tx->tx_ready_int_en)
+			msm_hs_submit_tx_locked(uport);
+
+		if (uart_circ_chars_pending(tx_buf) < WAKEUP_CHARS)
+			uart_write_wakeup(uport);
+	}
+	if (isr_status & UARTDM_ISR_TXLEV_BMSK) {
+		/* TX FIFO is empty */
+		msm_uport->imr_reg &= ~UARTDM_ISR_TXLEV_BMSK;
+		msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+		if (!msm_hs_check_clock_off_locked(uport))
+			hrtimer_start(&msm_uport->clk_off_timer,
+				      msm_uport->clk_off_delay,
+				      HRTIMER_MODE_REL);
+	}
+
+	/* Change in CTS interrupt */
+	if (isr_status & UARTDM_ISR_DELTA_CTS_BMSK)
+		msm_hs_handle_delta_cts(uport);
+
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+void msm_hs_request_clock_off_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	if (msm_uport->clk_state == MSM_HS_CLK_ON) {
+		msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF;
+		msm_uport->clk_req_off_state = CLK_REQ_OFF_START;
+		if (!use_low_power_rx_wakeup(msm_uport))
+			set_rfr_locked(uport, 0);
+		msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
+		msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+	}
+}
+
+/**
+ * msm_hs_request_clock_off - request to (i.e. asynchronously) turn off uart
+ * clock once pending TX is flushed and Rx DMA command is terminated.
+ * @uport: uart_port structure for the device instance.
+ *
+ * This functions puts the device into a partially active low power mode. It
+ * waits to complete all pending tx transactions, flushes ongoing Rx DMA
+ * command and terminates UART side Rx transaction, puts UART HW in non DMA
+ * mode and then clocks off the device. A client calls this when no UART
+ * data is expected. msm_request_clock_on() must be called before any further
+ * UART can be sent or received.
+ */
+void msm_hs_request_clock_off(struct uart_port *uport)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	msm_hs_request_clock_off_locked(uport);
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+void msm_hs_request_clock_on_locked(struct uart_port *uport)
+{
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	unsigned int data;
+
+	switch (msm_uport->clk_state) {
+	case MSM_HS_CLK_OFF:
+		clk_enable(msm_uport->clk);
+		disable_irq_nosync(msm_uport->rx_wakeup.irq);
+		/* fall-through */
+	case MSM_HS_CLK_REQUEST_OFF:
+		if (msm_uport->rx.flush == FLUSH_STOP ||
+		    msm_uport->rx.flush == FLUSH_SHUTDOWN) {
+			msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
+			data = msm_hs_read(uport, UARTDM_DMEN_ADDR);
+			data |= UARTDM_RX_DM_EN_BMSK;
+			msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+		}
+		hrtimer_try_to_cancel(&msm_uport->clk_off_timer);
+		if (msm_uport->rx.flush == FLUSH_SHUTDOWN)
+			msm_hs_start_rx_locked(uport);
+		if (!use_low_power_rx_wakeup(msm_uport))
+			set_rfr_locked(uport, 1);
+		if (msm_uport->rx.flush == FLUSH_STOP)
+			msm_uport->rx.flush = FLUSH_IGNORE;
+		msm_uport->clk_state = MSM_HS_CLK_ON;
+		break;
+	case MSM_HS_CLK_ON:
+		break;
+	case MSM_HS_CLK_PORT_OFF:
+		break;
+	}
+}
+
+/**
+ * msm_hs_request_clock_on - Switch the device from partially active low
+ * power mode to fully active (i.e. clock on) mode.
+ * @uport: uart_port structure for the device.
+ *
+ * This function switches on the input clock, puts UART HW into DMA mode
+ * and enqueues an Rx DMA command if the device was in partially active
+ * mode. It has no effect if called with the device in inactive state.
+ */
+void msm_hs_request_clock_on(struct uart_port *uport)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	msm_hs_request_clock_on_locked(uport);
+	spin_unlock_irqrestore(&uport->lock, flags);
+}
+
+static irqreturn_t msm_hs_rx_wakeup_isr(int irq, void *dev)
+{
+	unsigned int wakeup = 0;
+	unsigned long flags;
+	struct msm_hs_port *msm_uport = dev;
+	struct uart_port *uport = &msm_uport->uport;
+	struct tty_struct *tty = NULL;
+
+	spin_lock_irqsave(&uport->lock, flags);
+	if (msm_uport->clk_state == MSM_HS_CLK_OFF) {
+		/* ignore the first irq - it is a pending irq that occured
+		 * before enable_irq() */
+		if (msm_uport->rx_wakeup.ignore)
+			msm_uport->rx_wakeup.ignore = 0;
+		else
+			wakeup = 1;
+	}
+
+	if (wakeup) {
+		/* the uart was clocked off during an rx, wake up and
+		 * optionally inject char into tty rx */
+		msm_hs_request_clock_on_locked(uport);
+		if (msm_uport->rx_wakeup.inject_rx) {
+			tty = uport->state->port.tty;
+			tty_insert_flip_char(tty,
+					     msm_uport->rx_wakeup.rx_to_inject,
+					     TTY_NORMAL);
+			queue_work(msm_hs_workqueue, &msm_uport->rx.tty_work);
+		}
+	}
+
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static const char *msm_hs_type(struct uart_port *port)
+{
+	return (port->type == PORT_MSM) ? "MSM_HS_UART" : NULL;
+}
+
+/* Called when port is opened */
+static int msm_hs_startup(struct uart_port *uport)
+{
+	int ret;
+	int rfr_level;
+	unsigned long flags;
+	unsigned int data;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	struct circ_buf *tx_buf = &uport->state->xmit;
+	struct msm_hs_tx *tx = &msm_uport->tx;
+	struct msm_hs_rx *rx = &msm_uport->rx;
+
+	rfr_level = uport->fifosize;
+	if (rfr_level > 16)
+		rfr_level -= 16;
+
+	tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE,
+				      DMA_TO_DEVICE);
+
+	/* do not let tty layer execute RX in global workqueue, use a
+	 * dedicated workqueue managed by this driver */
+	uport->state->port.tty->low_latency = 1;
+
+	/* turn on uart clk */
+	ret = msm_hs_init_clk_locked(uport);
+	if (unlikely(ret)) {
+		printk(KERN_ERR "Turning uartclk failed!\n");
+		goto err_msm_hs_init_clk;
+	}
+
+	/* Set auto RFR Level */
+	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
+	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
+	data &= ~UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK;
+	data |= (UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK & (rfr_level << 2));
+	data |= (UARTDM_MR1_AUTO_RFR_LEVEL0_BMSK & rfr_level);
+	msm_hs_write(uport, UARTDM_MR1_ADDR, data);
+
+	/* Make sure RXSTALE count is non-zero */
+	data = msm_hs_read(uport, UARTDM_IPR_ADDR);
+	if (!data) {
+		data |= 0x1f & UARTDM_IPR_STALE_LSB_BMSK;
+		msm_hs_write(uport, UARTDM_IPR_ADDR, data);
+	}
+
+	/* Enable Data Mover Mode */
+	data = UARTDM_TX_DM_EN_BMSK | UARTDM_RX_DM_EN_BMSK;
+	msm_hs_write(uport, UARTDM_DMEN_ADDR, data);
+
+	/* Reset TX */
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_TX);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_RX);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_ERROR_STATUS);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_BREAK_INT);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_STALE_INT);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RESET_CTS);
+	msm_hs_write(uport, UARTDM_CR_ADDR, RFR_LOW);
+	/* Turn on Uart Receiver */
+	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_EN_BMSK);
+
+	/* Turn on Uart Transmitter */
+	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_EN_BMSK);
+
+	/* Initialize the tx */
+	tx->tx_ready_int_en = 0;
+	tx->dma_in_flight = 0;
+
+	tx->xfer.complete_func = msm_hs_dmov_tx_callback;
+	tx->xfer.execute_func = NULL;
+
+	tx->command_ptr->cmd = CMD_LC |
+	    CMD_DST_CRCI(msm_uport->dma_tx_crci) | CMD_MODE_BOX;
+
+	tx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
+					   | (MSM_UARTDM_BURST_SIZE);
+
+	tx->command_ptr->row_offset = (MSM_UARTDM_BURST_SIZE << 16);
+
+	tx->command_ptr->dst_row_addr =
+	    msm_uport->uport.mapbase + UARTDM_TF_ADDR;
+
+
+	/* Turn on Uart Receive */
+	rx->xfer.complete_func = msm_hs_dmov_rx_callback;
+	rx->xfer.execute_func = NULL;
+
+	rx->command_ptr->cmd = CMD_LC |
+	    CMD_SRC_CRCI(msm_uport->dma_rx_crci) | CMD_MODE_BOX;
+
+	rx->command_ptr->src_dst_len = (MSM_UARTDM_BURST_SIZE << 16)
+					   | (MSM_UARTDM_BURST_SIZE);
+	rx->command_ptr->row_offset =  MSM_UARTDM_BURST_SIZE;
+	rx->command_ptr->src_row_addr = uport->mapbase + UARTDM_RF_ADDR;
+
+
+	msm_uport->imr_reg |= UARTDM_ISR_RXSTALE_BMSK;
+	/* Enable reading the current CTS, no harm even if CTS is ignored */
+	msm_uport->imr_reg |= UARTDM_ISR_CURRENT_CTS_BMSK;
+
+	msm_hs_write(uport, UARTDM_TFWR_ADDR, 0);  /* TXLEV on empty TX fifo */
+
+
+	ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
+			  "msm_hs_uart", msm_uport);
+	if (unlikely(ret)) {
+		printk(KERN_ERR "Request msm_hs_uart IRQ failed!\n");
+		goto err_request_irq;
+	}
+	if (use_low_power_rx_wakeup(msm_uport)) {
+		ret = request_irq(msm_uport->rx_wakeup.irq,
+				  msm_hs_rx_wakeup_isr,
+				  IRQF_TRIGGER_FALLING,
+				  "msm_hs_rx_wakeup", msm_uport);
+		if (unlikely(ret)) {
+			printk(KERN_ERR "Request msm_hs_rx_wakeup IRQ failed!\n");
+			free_irq(uport->irq, msm_uport);
+			goto err_request_irq;
+		}
+		disable_irq(msm_uport->rx_wakeup.irq);
+	}
+
+	spin_lock_irqsave(&uport->lock, flags);
+
+	msm_hs_write(uport, UARTDM_RFWR_ADDR, 0);
+	msm_hs_start_rx_locked(uport);
+
+	spin_unlock_irqrestore(&uport->lock, flags);
+	ret = pm_runtime_set_active(uport->dev);
+	if (ret)
+		dev_err(uport->dev, "set active error:%d\n", ret);
+	pm_runtime_enable(uport->dev);
+
+	return 0;
+
+err_request_irq:
+err_msm_hs_init_clk:
+	dma_unmap_single(uport->dev, tx->dma_base,
+				UART_XMIT_SIZE, DMA_TO_DEVICE);
+	return ret;
+}
+
+/* Initialize tx and rx data structures */
+static int __devinit uartdm_init_port(struct uart_port *uport)
+{
+	int ret = 0;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+	struct msm_hs_tx *tx = &msm_uport->tx;
+	struct msm_hs_rx *rx = &msm_uport->rx;
+
+	/* Allocate the command pointer. Needs to be 64 bit aligned */
+	tx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
+	if (!tx->command_ptr)
+		return -ENOMEM;
+
+	tx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA);
+	if (!tx->command_ptr_ptr) {
+		ret = -ENOMEM;
+		goto err_tx_command_ptr_ptr;
+	}
+
+	tx->mapped_cmd_ptr = dma_map_single(uport->dev, tx->command_ptr,
+					    sizeof(dmov_box), DMA_TO_DEVICE);
+	tx->mapped_cmd_ptr_ptr = dma_map_single(uport->dev,
+						tx->command_ptr_ptr,
+						sizeof(u32 *), DMA_TO_DEVICE);
+	tx->xfer.cmdptr = DMOV_CMD_ADDR(tx->mapped_cmd_ptr_ptr);
+
+	init_waitqueue_head(&rx->wait);
+
+	rx->pool = dma_pool_create("rx_buffer_pool", uport->dev,
+				   UARTDM_RX_BUF_SIZE, 16, 0);
+	if (!rx->pool) {
+		pr_err("%s(): cannot allocate rx_buffer_pool", __func__);
+		ret = -ENOMEM;
+		goto err_dma_pool_create;
+	}
+
+	rx->buffer = dma_pool_alloc(rx->pool, GFP_KERNEL, &rx->rbuffer);
+	if (!rx->buffer) {
+		pr_err("%s(): cannot allocate rx->buffer", __func__);
+		ret = -ENOMEM;
+		goto err_dma_pool_alloc;
+	}
+
+	/* Allocate the command pointer. Needs to be 64 bit aligned */
+	rx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
+	if (!rx->command_ptr) {
+		pr_err("%s(): cannot allocate rx->command_ptr", __func__);
+		ret = -ENOMEM;
+		goto err_rx_command_ptr;
+	}
+
+	rx->command_ptr_ptr = kmalloc(sizeof(u32 *), GFP_KERNEL | __GFP_DMA);
+	if (!rx->command_ptr_ptr) {
+		pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__);
+		ret = -ENOMEM;
+		goto err_rx_command_ptr_ptr;
+	}
+
+	rx->command_ptr->num_rows = ((UARTDM_RX_BUF_SIZE >> 4) << 16) |
+					 (UARTDM_RX_BUF_SIZE >> 4);
+
+	rx->command_ptr->dst_row_addr = rx->rbuffer;
+
+	rx->mapped_cmd_ptr = dma_map_single(uport->dev, rx->command_ptr,
+					    sizeof(dmov_box), DMA_TO_DEVICE);
+
+	*rx->command_ptr_ptr = CMD_PTR_LP | DMOV_CMD_ADDR(rx->mapped_cmd_ptr);
+
+	rx->cmdptr_dmaaddr = dma_map_single(uport->dev, rx->command_ptr_ptr,
+					    sizeof(u32 *), DMA_TO_DEVICE);
+	rx->xfer.cmdptr = DMOV_CMD_ADDR(rx->cmdptr_dmaaddr);
+
+	INIT_WORK(&rx->tty_work, msm_hs_tty_flip_buffer_work);
+
+	return ret;
+
+err_rx_command_ptr_ptr:
+	kfree(rx->command_ptr);
+err_rx_command_ptr:
+	dma_pool_free(msm_uport->rx.pool, msm_uport->rx.buffer,
+						msm_uport->rx.rbuffer);
+err_dma_pool_alloc:
+	dma_pool_destroy(msm_uport->rx.pool);
+err_dma_pool_create:
+	dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr_ptr,
+				sizeof(u32 *), DMA_TO_DEVICE);
+	dma_unmap_single(uport->dev, msm_uport->tx.mapped_cmd_ptr,
+				sizeof(dmov_box), DMA_TO_DEVICE);
+	kfree(msm_uport->tx.command_ptr_ptr);
+err_tx_command_ptr_ptr:
+	kfree(msm_uport->tx.command_ptr);
+	return ret;
+}
+
+static int __devinit msm_hs_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct uart_port *uport;
+	struct msm_hs_port *msm_uport;
+	struct resource *resource;
+	const struct msm_serial_hs_platform_data *pdata =
+						pdev->dev.platform_data;
+
+	if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
+		printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	msm_uport = &q_uart_port[pdev->id];
+	uport = &msm_uport->uport;
+
+	uport->dev = &pdev->dev;
+
+	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!resource))
+		return -ENXIO;
+
+	uport->mapbase = resource->start;
+	uport->irq = platform_get_irq(pdev, 0);
+	if (unlikely(uport->irq < 0))
+		return -ENXIO;
+
+	if (unlikely(set_irq_wake(uport->irq, 1)))
+		return -ENXIO;
+
+	if (pdata == NULL || pdata->rx_wakeup_irq < 0)
+		msm_uport->rx_wakeup.irq = -1;
+	else {
+		msm_uport->rx_wakeup.irq = pdata->rx_wakeup_irq;
+		msm_uport->rx_wakeup.ignore = 1;
+		msm_uport->rx_wakeup.inject_rx = pdata->inject_rx_on_wakeup;
+		msm_uport->rx_wakeup.rx_to_inject = pdata->rx_to_inject;
+
+		if (unlikely(msm_uport->rx_wakeup.irq < 0))
+			return -ENXIO;
+
+		if (unlikely(set_irq_wake(msm_uport->rx_wakeup.irq, 1)))
+			return -ENXIO;
+	}
+
+	if (pdata == NULL)
+		msm_uport->exit_lpm_cb = NULL;
+	else
+		msm_uport->exit_lpm_cb = pdata->exit_lpm_cb;
+
+	resource = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+						"uartdm_channels");
+	if (unlikely(!resource))
+		return -ENXIO;
+
+	msm_uport->dma_tx_channel = resource->start;
+	msm_uport->dma_rx_channel = resource->end;
+
+	resource = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+						"uartdm_crci");
+	if (unlikely(!resource))
+		return -ENXIO;
+
+	msm_uport->dma_tx_crci = resource->start;
+	msm_uport->dma_rx_crci = resource->end;
+
+	uport->iotype = UPIO_MEM;
+	uport->fifosize = UART_FIFOSIZE;
+	uport->ops = &msm_hs_ops;
+	uport->flags = UPF_BOOT_AUTOCONF;
+	uport->uartclk = UARTCLK;
+	msm_uport->imr_reg = 0x0;
+	msm_uport->clk = clk_get(&pdev->dev, "uartdm_clk");
+	if (IS_ERR(msm_uport->clk))
+		return PTR_ERR(msm_uport->clk);
+
+	ret = uartdm_init_port(uport);
+	if (unlikely(ret))
+		return ret;
+
+	msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
+	hrtimer_init(&msm_uport->clk_off_timer, CLOCK_MONOTONIC,
+		     HRTIMER_MODE_REL);
+	msm_uport->clk_off_timer.function = msm_hs_clk_off_retry;
+	msm_uport->clk_off_delay = ktime_set(0, 1000000);  /* 1ms */
+
+	uport->line = pdev->id;
+	return uart_add_one_port(&msm_hs_driver, uport);
+}
+
+static int __init msm_serial_hs_init(void)
+{
+	int ret, i;
+
+	/* Init all UARTS as non-configured */
+	for (i = 0; i < UARTDM_NR; i++)
+		q_uart_port[i].uport.type = PORT_UNKNOWN;
+
+	msm_hs_workqueue = create_singlethread_workqueue("msm_serial_hs");
+	if (unlikely(!msm_hs_workqueue))
+		return -ENOMEM;
+
+	ret = uart_register_driver(&msm_hs_driver);
+	if (unlikely(ret)) {
+		printk(KERN_ERR "%s failed to load\n", __func__);
+		goto err_uart_register_driver;
+	}
+
+	ret = platform_driver_register(&msm_serial_hs_platform_driver);
+	if (ret) {
+		printk(KERN_ERR "%s failed to load\n", __func__);
+		goto err_platform_driver_register;
+	}
+
+	return ret;
+
+err_platform_driver_register:
+	uart_unregister_driver(&msm_hs_driver);
+err_uart_register_driver:
+	destroy_workqueue(msm_hs_workqueue);
+	return ret;
+}
+module_init(msm_serial_hs_init);
+
+/*
+ *  Called by the upper layer when port is closed.
+ *     - Disables the port
+ *     - Unhook the ISR
+ */
+static void msm_hs_shutdown(struct uart_port *uport)
+{
+	unsigned long flags;
+	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
+
+	BUG_ON(msm_uport->rx.flush < FLUSH_STOP);
+
+	spin_lock_irqsave(&uport->lock, flags);
+	clk_enable(msm_uport->clk);
+
+	/* Disable the transmitter */
+	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_TX_DISABLE_BMSK);
+	/* Disable the receiver */
+	msm_hs_write(uport, UARTDM_CR_ADDR, UARTDM_CR_RX_DISABLE_BMSK);
+
+	pm_runtime_disable(uport->dev);
+	pm_runtime_set_suspended(uport->dev);
+
+	/* Free the interrupt */
+	free_irq(uport->irq, msm_uport);
+	if (use_low_power_rx_wakeup(msm_uport))
+		free_irq(msm_uport->rx_wakeup.irq, msm_uport);
+
+	msm_uport->imr_reg = 0;
+	msm_hs_write(uport, UARTDM_IMR_ADDR, msm_uport->imr_reg);
+
+	wait_event(msm_uport->rx.wait, msm_uport->rx.flush == FLUSH_SHUTDOWN);
+
+	clk_disable(msm_uport->clk);  /* to balance local clk_enable() */
+	if (msm_uport->clk_state != MSM_HS_CLK_OFF)
+		clk_disable(msm_uport->clk);  /* to balance clk_state */
+	msm_uport->clk_state = MSM_HS_CLK_PORT_OFF;
+
+	dma_unmap_single(uport->dev, msm_uport->tx.dma_base,
+			 UART_XMIT_SIZE, DMA_TO_DEVICE);
+
+	spin_unlock_irqrestore(&uport->lock, flags);
+
+	if (cancel_work_sync(&msm_uport->rx.tty_work))
+		msm_hs_tty_flip_buffer_work(&msm_uport->rx.tty_work);
+}
+
+static void __exit msm_serial_hs_exit(void)
+{
+	flush_workqueue(msm_hs_workqueue);
+	destroy_workqueue(msm_hs_workqueue);
+	platform_driver_unregister(&msm_serial_hs_platform_driver);
+	uart_unregister_driver(&msm_hs_driver);
+}
+module_exit(msm_serial_hs_exit);
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_hs_runtime_idle(struct device *dev)
+{
+	/*
+	 * returning success from idle results in runtime suspend to be
+	 * called
+	 */
+	return 0;
+}
+
+static int msm_hs_runtime_resume(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev, struct
+						    platform_device, dev);
+	struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
+
+	msm_hs_request_clock_on(&msm_uport->uport);
+	return 0;
+}
+
+static int msm_hs_runtime_suspend(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev, struct
+						    platform_device, dev);
+	struct msm_hs_port *msm_uport = &q_uart_port[pdev->id];
+
+	msm_hs_request_clock_off(&msm_uport->uport);
+	return 0;
+}
+#else
+#define msm_hs_runtime_idle NULL
+#define msm_hs_runtime_resume NULL
+#define msm_hs_runtime_suspend NULL
+#endif
+
+static const struct dev_pm_ops msm_hs_dev_pm_ops = {
+	.runtime_suspend = msm_hs_runtime_suspend,
+	.runtime_resume  = msm_hs_runtime_resume,
+	.runtime_idle    = msm_hs_runtime_idle,
+};
+
+static struct platform_driver msm_serial_hs_platform_driver = {
+	.probe = msm_hs_probe,
+	.remove = __devexit_p(msm_hs_remove),
+	.driver = {
+		.name = "msm_serial_hs",
+		.owner = THIS_MODULE,
+		.pm   = &msm_hs_dev_pm_ops,
+	},
+};
+
+static struct uart_driver msm_hs_driver = {
+	.owner = THIS_MODULE,
+	.driver_name = "msm_serial_hs",
+	.dev_name = "ttyHS",
+	.nr = UARTDM_NR,
+	.cons = 0,
+};
+
+static struct uart_ops msm_hs_ops = {
+	.tx_empty = msm_hs_tx_empty,
+	.set_mctrl = msm_hs_set_mctrl_locked,
+	.get_mctrl = msm_hs_get_mctrl_locked,
+	.stop_tx = msm_hs_stop_tx_locked,
+	.start_tx = msm_hs_start_tx_locked,
+	.stop_rx = msm_hs_stop_rx_locked,
+	.enable_ms = msm_hs_enable_ms_locked,
+	.break_ctl = msm_hs_break_ctl,
+	.startup = msm_hs_startup,
+	.shutdown = msm_hs_shutdown,
+	.set_termios = msm_hs_set_termios,
+	.pm = msm_hs_pm,
+	.type = msm_hs_type,
+	.config_port = msm_hs_config_port,
+	.release_port = msm_hs_release_port,
+	.request_port = msm_hs_request_port,
+};
+
+MODULE_DESCRIPTION("High Speed UART Driver for the MSM chipset");
+MODULE_VERSION("1.2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/msm_smd_tty.c b/drivers/tty/serial/msm_smd_tty.c
new file mode 100644
index 0000000..beeff1e
--- /dev/null
+++ b/drivers/tty/serial/msm_smd_tty.c
@@ -0,0 +1,236 @@
+/* drivers/tty/serial/msm_smd_tty.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+
+#include <mach/msm_smd.h>
+
+#define MAX_SMD_TTYS 32
+
+struct smd_tty_info {
+	struct tty_port port;
+	smd_channel_t *ch;
+};
+
+struct smd_tty_channel_desc {
+	int id;
+	const char *name;
+};
+
+static struct smd_tty_info smd_tty[MAX_SMD_TTYS];
+
+static const struct smd_tty_channel_desc smd_default_tty_channels[] = {
+	{ .id = 0, .name = "SMD_DS" },
+	{ .id = 27, .name = "SMD_GPSNMEA" },
+};
+
+static const struct smd_tty_channel_desc *smd_tty_channels =
+		smd_default_tty_channels;
+static int smd_tty_channels_len = ARRAY_SIZE(smd_default_tty_channels);
+
+static void smd_tty_notify(void *priv, unsigned event)
+{
+	unsigned char *ptr;
+	int avail;
+	struct smd_tty_info *info = priv;
+	struct tty_struct *tty;
+
+	if (event != SMD_EVENT_DATA)
+		return;
+
+	tty = tty_port_tty_get(&info->port);
+	if (!tty)
+		return;
+
+	for (;;) {
+		if (test_bit(TTY_THROTTLED, &tty->flags))
+			break;
+		avail = smd_read_avail(info->ch);
+		if (avail == 0)
+			break;
+
+		avail = tty_prepare_flip_string(tty, &ptr, avail);
+
+		if (smd_read(info->ch, ptr, avail) != avail) {
+			/* shouldn't be possible since we're in interrupt
+			** context here and nobody else could 'steal' our
+			** characters.
+			*/
+			pr_err("OOPS - smd_tty_buffer mismatch?!");
+		}
+
+		tty_flip_buffer_push(tty);
+	}
+
+	/* XXX only when writable and necessary */
+	tty_wakeup(tty);
+	tty_kref_put(tty);
+}
+
+static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
+{
+	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) {
+			name = smd_tty_channels[i].name;
+			break;
+		}
+	}
+	if (!name)
+		return -ENODEV;
+
+	if (info->ch)
+		smd_kick(info->ch);
+	else
+		res = smd_open(name, &info->ch, info, smd_tty_notify);
+
+	if (!res)
+		tty->driver_data = info;
+
+	return res;
+}
+
+static void smd_tty_port_shutdown(struct tty_port *tport)
+{
+	struct smd_tty_info *info;
+	struct tty_struct *tty = tty_port_tty_get(tport);
+
+	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)
+{
+	struct smd_tty_info *info = smd_tty + tty->index;
+
+	return tty_port_open(&info->port, tty, f);
+}
+
+static void smd_tty_close(struct tty_struct *tty, struct file *f)
+{
+	struct smd_tty_info *info = tty->driver_data;
+
+	tty_port_close(&info->port, tty, f);
+}
+
+static int smd_tty_write(struct tty_struct *tty,
+			 const unsigned char *buf, int len)
+{
+	struct smd_tty_info *info = tty->driver_data;
+	int avail;
+
+	/* if we're writing to a packet channel we will
+	** never be able to write more data than there
+	** is currently space for
+	*/
+	avail = smd_write_avail(info->ch);
+	if (len > avail)
+		len = avail;
+
+	return smd_write(info->ch, buf, len);
+}
+
+static int smd_tty_write_room(struct tty_struct *tty)
+{
+	struct smd_tty_info *info = tty->driver_data;
+	return smd_write_avail(info->ch);
+}
+
+static int smd_tty_chars_in_buffer(struct tty_struct *tty)
+{
+	struct smd_tty_info *info = tty->driver_data;
+	return smd_read_avail(info->ch);
+}
+
+static void smd_tty_unthrottle(struct tty_struct *tty)
+{
+	struct smd_tty_info *info = tty->driver_data;
+	smd_kick(info->ch);
+}
+
+static const struct tty_port_operations smd_tty_port_ops = {
+	.shutdown = smd_tty_port_shutdown,
+	.activate = smd_tty_port_activate,
+};
+
+static const struct tty_operations smd_tty_ops = {
+	.open = smd_tty_open,
+	.close = smd_tty_close,
+	.write = smd_tty_write,
+	.write_room = smd_tty_write_room,
+	.chars_in_buffer = smd_tty_chars_in_buffer,
+	.unthrottle = smd_tty_unthrottle,
+};
+
+static struct tty_driver *smd_tty_driver;
+
+static int __init smd_tty_init(void)
+{
+	int ret, i;
+
+	smd_tty_driver = alloc_tty_driver(MAX_SMD_TTYS);
+	if (smd_tty_driver == 0)
+		return -ENOMEM;
+
+	smd_tty_driver->owner = THIS_MODULE;
+	smd_tty_driver->driver_name = "smd_tty_driver";
+	smd_tty_driver->name = "smd";
+	smd_tty_driver->major = 0;
+	smd_tty_driver->minor_start = 0;
+	smd_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	smd_tty_driver->subtype = SERIAL_TYPE_NORMAL;
+	smd_tty_driver->init_termios = tty_std_termios;
+	smd_tty_driver->init_termios.c_iflag = 0;
+	smd_tty_driver->init_termios.c_oflag = 0;
+	smd_tty_driver->init_termios.c_cflag = B38400 | CS8 | CREAD;
+	smd_tty_driver->init_termios.c_lflag = 0;
+	smd_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+		TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(smd_tty_driver, &smd_tty_ops);
+
+	ret = tty_register_driver(smd_tty_driver);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < smd_tty_channels_len; i++) {
+		tty_port_init(&smd_tty[smd_tty_channels[i].id].port);
+		smd_tty[smd_tty_channels[i].id].port.ops = &smd_tty_port_ops;
+		tty_register_device(smd_tty_driver, smd_tty_channels[i].id, 0);
+	}
+
+	return 0;
+}
+
+module_init(smd_tty_init);
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
new file mode 100644
index 0000000..7e02c9c
--- /dev/null
+++ b/drivers/tty/serial/mxs-auart.c
@@ -0,0 +1,798 @@
+/*
+ * Freescale STMP37XX/STMP378X Application UART driver
+ *
+ * Author: dmitry pervushin <dimka@embeddedalley.com>
+ *
+ * Copyright 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+
+#define MXS_AUART_PORTS 5
+
+#define AUART_CTRL0			0x00000000
+#define AUART_CTRL0_SET			0x00000004
+#define AUART_CTRL0_CLR			0x00000008
+#define AUART_CTRL0_TOG			0x0000000c
+#define AUART_CTRL1			0x00000010
+#define AUART_CTRL1_SET			0x00000014
+#define AUART_CTRL1_CLR			0x00000018
+#define AUART_CTRL1_TOG			0x0000001c
+#define AUART_CTRL2			0x00000020
+#define AUART_CTRL2_SET			0x00000024
+#define AUART_CTRL2_CLR			0x00000028
+#define AUART_CTRL2_TOG			0x0000002c
+#define AUART_LINECTRL			0x00000030
+#define AUART_LINECTRL_SET		0x00000034
+#define AUART_LINECTRL_CLR		0x00000038
+#define AUART_LINECTRL_TOG		0x0000003c
+#define AUART_LINECTRL2			0x00000040
+#define AUART_LINECTRL2_SET		0x00000044
+#define AUART_LINECTRL2_CLR		0x00000048
+#define AUART_LINECTRL2_TOG		0x0000004c
+#define AUART_INTR			0x00000050
+#define AUART_INTR_SET			0x00000054
+#define AUART_INTR_CLR			0x00000058
+#define AUART_INTR_TOG			0x0000005c
+#define AUART_DATA			0x00000060
+#define AUART_STAT			0x00000070
+#define AUART_DEBUG			0x00000080
+#define AUART_VERSION			0x00000090
+#define AUART_AUTOBAUD			0x000000a0
+
+#define AUART_CTRL0_SFTRST			(1 << 31)
+#define AUART_CTRL0_CLKGATE			(1 << 30)
+
+#define AUART_CTRL2_CTSEN			(1 << 15)
+#define AUART_CTRL2_RTS				(1 << 11)
+#define AUART_CTRL2_RXE				(1 << 9)
+#define AUART_CTRL2_TXE				(1 << 8)
+#define AUART_CTRL2_UARTEN			(1 << 0)
+
+#define AUART_LINECTRL_BAUD_DIVINT_SHIFT	16
+#define AUART_LINECTRL_BAUD_DIVINT_MASK		0xffff0000
+#define AUART_LINECTRL_BAUD_DIVINT(v)		(((v) & 0xffff) << 16)
+#define AUART_LINECTRL_BAUD_DIVFRAC_SHIFT	8
+#define AUART_LINECTRL_BAUD_DIVFRAC_MASK	0x00003f00
+#define AUART_LINECTRL_BAUD_DIVFRAC(v)		(((v) & 0x3f) << 8)
+#define AUART_LINECTRL_WLEN_MASK		0x00000060
+#define AUART_LINECTRL_WLEN(v)			(((v) & 0x3) << 5)
+#define AUART_LINECTRL_FEN			(1 << 4)
+#define AUART_LINECTRL_STP2			(1 << 3)
+#define AUART_LINECTRL_EPS			(1 << 2)
+#define AUART_LINECTRL_PEN			(1 << 1)
+#define AUART_LINECTRL_BRK			(1 << 0)
+
+#define AUART_INTR_RTIEN			(1 << 22)
+#define AUART_INTR_TXIEN			(1 << 21)
+#define AUART_INTR_RXIEN			(1 << 20)
+#define AUART_INTR_CTSMIEN			(1 << 17)
+#define AUART_INTR_RTIS				(1 << 6)
+#define AUART_INTR_TXIS				(1 << 5)
+#define AUART_INTR_RXIS				(1 << 4)
+#define AUART_INTR_CTSMIS			(1 << 1)
+
+#define AUART_STAT_BUSY				(1 << 29)
+#define AUART_STAT_CTS				(1 << 28)
+#define AUART_STAT_TXFE				(1 << 27)
+#define AUART_STAT_TXFF				(1 << 25)
+#define AUART_STAT_RXFE				(1 << 24)
+#define AUART_STAT_OERR				(1 << 19)
+#define AUART_STAT_BERR				(1 << 18)
+#define AUART_STAT_PERR				(1 << 17)
+#define AUART_STAT_FERR				(1 << 16)
+
+static struct uart_driver auart_driver;
+
+struct mxs_auart_port {
+	struct uart_port port;
+
+	unsigned int flags;
+	unsigned int ctrl;
+
+	unsigned int irq;
+
+	struct clk *clk;
+	struct device *dev;
+};
+
+static void mxs_auart_stop_tx(struct uart_port *u);
+
+#define to_auart_port(u) container_of(u, struct mxs_auart_port, port)
+
+static inline void mxs_auart_tx_chars(struct mxs_auart_port *s)
+{
+	struct circ_buf *xmit = &s->port.state->xmit;
+
+	while (!(readl(s->port.membase + AUART_STAT) &
+		 AUART_STAT_TXFF)) {
+		if (s->port.x_char) {
+			s->port.icount.tx++;
+			writel(s->port.x_char,
+				     s->port.membase + AUART_DATA);
+			s->port.x_char = 0;
+			continue;
+		}
+		if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {
+			s->port.icount.tx++;
+			writel(xmit->buf[xmit->tail],
+				     s->port.membase + AUART_DATA);
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+			if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+				uart_write_wakeup(&s->port);
+		} else
+			break;
+	}
+	if (uart_circ_empty(&(s->port.state->xmit)))
+		writel(AUART_INTR_TXIEN,
+			     s->port.membase + AUART_INTR_CLR);
+	else
+		writel(AUART_INTR_TXIEN,
+			     s->port.membase + AUART_INTR_SET);
+
+	if (uart_tx_stopped(&s->port))
+		mxs_auart_stop_tx(&s->port);
+}
+
+static void mxs_auart_rx_char(struct mxs_auart_port *s)
+{
+	int flag;
+	u32 stat;
+	u8 c;
+
+	c = readl(s->port.membase + AUART_DATA);
+	stat = readl(s->port.membase + AUART_STAT);
+
+	flag = TTY_NORMAL;
+	s->port.icount.rx++;
+
+	if (stat & AUART_STAT_BERR) {
+		s->port.icount.brk++;
+		if (uart_handle_break(&s->port))
+			goto out;
+	} else if (stat & AUART_STAT_PERR) {
+		s->port.icount.parity++;
+	} else if (stat & AUART_STAT_FERR) {
+		s->port.icount.frame++;
+	}
+
+	/*
+	 * Mask off conditions which should be ingored.
+	 */
+	stat &= s->port.read_status_mask;
+
+	if (stat & AUART_STAT_BERR) {
+		flag = TTY_BREAK;
+	} else if (stat & AUART_STAT_PERR)
+		flag = TTY_PARITY;
+	else if (stat & AUART_STAT_FERR)
+		flag = TTY_FRAME;
+
+	if (stat & AUART_STAT_OERR)
+		s->port.icount.overrun++;
+
+	if (uart_handle_sysrq_char(&s->port, c))
+		goto out;
+
+	uart_insert_char(&s->port, stat, AUART_STAT_OERR, c, flag);
+out:
+	writel(stat, s->port.membase + AUART_STAT);
+}
+
+static void mxs_auart_rx_chars(struct mxs_auart_port *s)
+{
+	struct tty_struct *tty = s->port.state->port.tty;
+	u32 stat = 0;
+
+	for (;;) {
+		stat = readl(s->port.membase + AUART_STAT);
+		if (stat & AUART_STAT_RXFE)
+			break;
+		mxs_auart_rx_char(s);
+	}
+
+	writel(stat, s->port.membase + AUART_STAT);
+	tty_flip_buffer_push(tty);
+}
+
+static int mxs_auart_request_port(struct uart_port *u)
+{
+	return 0;
+}
+
+static int mxs_auart_verify_port(struct uart_port *u,
+				    struct serial_struct *ser)
+{
+	if (u->type != PORT_UNKNOWN && u->type != PORT_IMX)
+		return -EINVAL;
+	return 0;
+}
+
+static void mxs_auart_config_port(struct uart_port *u, int flags)
+{
+}
+
+static const char *mxs_auart_type(struct uart_port *u)
+{
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	return dev_name(s->dev);
+}
+
+static void mxs_auart_release_port(struct uart_port *u)
+{
+}
+
+static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl)
+{
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	u32 ctrl = readl(u->membase + AUART_CTRL2);
+
+	ctrl &= ~AUART_CTRL2_RTS;
+	if (mctrl & TIOCM_RTS)
+		ctrl |= AUART_CTRL2_RTS;
+	s->ctrl = mctrl;
+	writel(ctrl, u->membase + AUART_CTRL2);
+}
+
+static u32 mxs_auart_get_mctrl(struct uart_port *u)
+{
+	struct mxs_auart_port *s = to_auart_port(u);
+	u32 stat = readl(u->membase + AUART_STAT);
+	int ctrl2 = readl(u->membase + AUART_CTRL2);
+	u32 mctrl = s->ctrl;
+
+	mctrl &= ~TIOCM_CTS;
+	if (stat & AUART_STAT_CTS)
+		mctrl |= TIOCM_CTS;
+
+	if (ctrl2 & AUART_CTRL2_RTS)
+		mctrl |= TIOCM_RTS;
+
+	return mctrl;
+}
+
+static void mxs_auart_settermios(struct uart_port *u,
+				 struct ktermios *termios,
+				 struct ktermios *old)
+{
+	u32 bm, ctrl, ctrl2, div;
+	unsigned int cflag, baud;
+
+	cflag = termios->c_cflag;
+
+	ctrl = AUART_LINECTRL_FEN;
+	ctrl2 = readl(u->membase + AUART_CTRL2);
+
+	/* byte size */
+	switch (cflag & CSIZE) {
+	case CS5:
+		bm = 0;
+		break;
+	case CS6:
+		bm = 1;
+		break;
+	case CS7:
+		bm = 2;
+		break;
+	case CS8:
+		bm = 3;
+		break;
+	default:
+		return;
+	}
+
+	ctrl |= AUART_LINECTRL_WLEN(bm);
+
+	/* parity */
+	if (cflag & PARENB) {
+		ctrl |= AUART_LINECTRL_PEN;
+		if ((cflag & PARODD) == 0)
+			ctrl |= AUART_LINECTRL_EPS;
+	}
+
+	u->read_status_mask = 0;
+
+	if (termios->c_iflag & INPCK)
+		u->read_status_mask |= AUART_STAT_PERR;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		u->read_status_mask |= AUART_STAT_BERR;
+
+	/*
+	 * Characters to ignore
+	 */
+	u->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		u->ignore_status_mask |= AUART_STAT_PERR;
+	if (termios->c_iflag & IGNBRK) {
+		u->ignore_status_mask |= AUART_STAT_BERR;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			u->ignore_status_mask |= AUART_STAT_OERR;
+	}
+
+	/*
+	 * ignore all characters if CREAD is not set
+	 */
+	if (cflag & CREAD)
+		ctrl2 |= AUART_CTRL2_RXE;
+	else
+		ctrl2 &= ~AUART_CTRL2_RXE;
+
+	/* figure out the stop bits requested */
+	if (cflag & CSTOPB)
+		ctrl |= AUART_LINECTRL_STP2;
+
+	/* figure out the hardware flow control settings */
+	if (cflag & CRTSCTS)
+		ctrl2 |= AUART_CTRL2_CTSEN;
+	else
+		ctrl2 &= ~AUART_CTRL2_CTSEN;
+
+	/* set baud rate */
+	baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
+	div = u->uartclk * 32 / baud;
+	ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
+	ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
+
+	writel(ctrl, u->membase + AUART_LINECTRL);
+	writel(ctrl2, u->membase + AUART_CTRL2);
+}
+
+static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
+{
+	u32 istatus, istat;
+	struct mxs_auart_port *s = context;
+	u32 stat = readl(s->port.membase + AUART_STAT);
+
+	istatus = istat = readl(s->port.membase + AUART_INTR);
+
+	if (istat & AUART_INTR_CTSMIS) {
+		uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS);
+		writel(AUART_INTR_CTSMIS,
+				s->port.membase + AUART_INTR_CLR);
+		istat &= ~AUART_INTR_CTSMIS;
+	}
+
+	if (istat & (AUART_INTR_RTIS | AUART_INTR_RXIS)) {
+		mxs_auart_rx_chars(s);
+		istat &= ~(AUART_INTR_RTIS | AUART_INTR_RXIS);
+	}
+
+	if (istat & AUART_INTR_TXIS) {
+		mxs_auart_tx_chars(s);
+		istat &= ~AUART_INTR_TXIS;
+	}
+
+	writel(istatus & (AUART_INTR_RTIS
+		| AUART_INTR_TXIS
+		| AUART_INTR_RXIS
+		| AUART_INTR_CTSMIS),
+			s->port.membase + AUART_INTR_CLR);
+
+	return IRQ_HANDLED;
+}
+
+static void mxs_auart_reset(struct uart_port *u)
+{
+	int i;
+	unsigned int reg;
+
+	writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_CLR);
+
+	for (i = 0; i < 10000; i++) {
+		reg = readl(u->membase + AUART_CTRL0);
+		if (!(reg & AUART_CTRL0_SFTRST))
+			break;
+		udelay(3);
+	}
+	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+}
+
+static int mxs_auart_startup(struct uart_port *u)
+{
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	clk_enable(s->clk);
+
+	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+
+	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
+
+	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
+			u->membase + AUART_INTR);
+
+	/*
+	 * Enable fifo so all four bytes of a DMA word are written to
+	 * output (otherwise, only the LSB is written, ie. 1 in 4 bytes)
+	 */
+	writel(AUART_LINECTRL_FEN, u->membase + AUART_LINECTRL_SET);
+
+	return 0;
+}
+
+static void mxs_auart_shutdown(struct uart_port *u)
+{
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
+
+	writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+
+	writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
+			u->membase + AUART_INTR_CLR);
+
+	clk_disable(s->clk);
+}
+
+static unsigned int mxs_auart_tx_empty(struct uart_port *u)
+{
+	if (readl(u->membase + AUART_STAT) & AUART_STAT_TXFE)
+		return TIOCSER_TEMT;
+	else
+		return 0;
+}
+
+static void mxs_auart_start_tx(struct uart_port *u)
+{
+	struct mxs_auart_port *s = to_auart_port(u);
+
+	/* enable transmitter */
+	writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_SET);
+
+	mxs_auart_tx_chars(s);
+}
+
+static void mxs_auart_stop_tx(struct uart_port *u)
+{
+	writel(AUART_CTRL2_TXE, u->membase + AUART_CTRL2_CLR);
+}
+
+static void mxs_auart_stop_rx(struct uart_port *u)
+{
+	writel(AUART_CTRL2_RXE, u->membase + AUART_CTRL2_CLR);
+}
+
+static void mxs_auart_break_ctl(struct uart_port *u, int ctl)
+{
+	if (ctl)
+		writel(AUART_LINECTRL_BRK,
+			     u->membase + AUART_LINECTRL_SET);
+	else
+		writel(AUART_LINECTRL_BRK,
+			     u->membase + AUART_LINECTRL_CLR);
+}
+
+static void mxs_auart_enable_ms(struct uart_port *port)
+{
+	/* just empty */
+}
+
+static struct uart_ops mxs_auart_ops = {
+	.tx_empty       = mxs_auart_tx_empty,
+	.start_tx       = mxs_auart_start_tx,
+	.stop_tx	= mxs_auart_stop_tx,
+	.stop_rx	= mxs_auart_stop_rx,
+	.enable_ms      = mxs_auart_enable_ms,
+	.break_ctl      = mxs_auart_break_ctl,
+	.set_mctrl	= mxs_auart_set_mctrl,
+	.get_mctrl      = mxs_auart_get_mctrl,
+	.startup	= mxs_auart_startup,
+	.shutdown       = mxs_auart_shutdown,
+	.set_termios    = mxs_auart_settermios,
+	.type	   	= mxs_auart_type,
+	.release_port   = mxs_auart_release_port,
+	.request_port   = mxs_auart_request_port,
+	.config_port    = mxs_auart_config_port,
+	.verify_port    = mxs_auart_verify_port,
+};
+
+static struct mxs_auart_port *auart_port[MXS_AUART_PORTS];
+
+#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
+static void mxs_auart_console_putchar(struct uart_port *port, int ch)
+{
+	unsigned int to = 1000;
+
+	while (readl(port->membase + AUART_STAT) & AUART_STAT_TXFF) {
+		if (!to--)
+			break;
+		udelay(1);
+	}
+
+	writel(ch, port->membase + AUART_DATA);
+}
+
+static void
+auart_console_write(struct console *co, const char *str, unsigned int count)
+{
+	struct mxs_auart_port *s;
+	struct uart_port *port;
+	unsigned int old_ctrl0, old_ctrl2;
+	unsigned int to = 1000;
+
+	if (co->index >	MXS_AUART_PORTS || co->index < 0)
+		return;
+
+	s = auart_port[co->index];
+	port = &s->port;
+
+	clk_enable(s->clk);
+
+	/* First save the CR then disable the interrupts */
+	old_ctrl2 = readl(port->membase + AUART_CTRL2);
+	old_ctrl0 = readl(port->membase + AUART_CTRL0);
+
+	writel(AUART_CTRL0_CLKGATE,
+		     port->membase + AUART_CTRL0_CLR);
+	writel(AUART_CTRL2_UARTEN | AUART_CTRL2_TXE,
+		     port->membase + AUART_CTRL2_SET);
+
+	uart_console_write(port, str, count, mxs_auart_console_putchar);
+
+	/*
+	 * Finally, wait for transmitter to become empty
+	 * and restore the TCR
+	 */
+	while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) {
+		if (!to--)
+			break;
+		udelay(1);
+	}
+
+	writel(old_ctrl0, port->membase + AUART_CTRL0);
+	writel(old_ctrl2, port->membase + AUART_CTRL2);
+
+	clk_disable(s->clk);
+}
+
+static void __init
+auart_console_get_options(struct uart_port *port, int *baud,
+			  int *parity, int *bits)
+{
+	unsigned int lcr_h, quot;
+
+	if (!(readl(port->membase + AUART_CTRL2) & AUART_CTRL2_UARTEN))
+		return;
+
+	lcr_h = readl(port->membase + AUART_LINECTRL);
+
+	*parity = 'n';
+	if (lcr_h & AUART_LINECTRL_PEN) {
+		if (lcr_h & AUART_LINECTRL_EPS)
+			*parity = 'e';
+		else
+			*parity = 'o';
+	}
+
+	if ((lcr_h & AUART_LINECTRL_WLEN_MASK) == AUART_LINECTRL_WLEN(2))
+		*bits = 7;
+	else
+		*bits = 8;
+
+	quot = ((readl(port->membase + AUART_LINECTRL)
+			& AUART_LINECTRL_BAUD_DIVINT_MASK))
+			    >> (AUART_LINECTRL_BAUD_DIVINT_SHIFT - 6);
+	quot |= ((readl(port->membase + AUART_LINECTRL)
+			& AUART_LINECTRL_BAUD_DIVFRAC_MASK))
+				>> AUART_LINECTRL_BAUD_DIVFRAC_SHIFT;
+	if (quot == 0)
+		quot = 1;
+
+	*baud = (port->uartclk << 2) / quot;
+}
+
+static int __init
+auart_console_setup(struct console *co, char *options)
+{
+	struct mxs_auart_port *s;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret;
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index == -1 || co->index >= ARRAY_SIZE(auart_port))
+		co->index = 0;
+	s = auart_port[co->index];
+	if (!s)
+		return -ENODEV;
+
+	clk_enable(s->clk);
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	else
+		auart_console_get_options(&s->port, &baud, &parity, &bits);
+
+	ret = uart_set_options(&s->port, co, baud, parity, bits, flow);
+
+	clk_disable(s->clk);
+
+	return ret;
+}
+
+static struct console auart_console = {
+	.name		= "ttyAPP",
+	.write		= auart_console_write,
+	.device		= uart_console_device,
+	.setup		= auart_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &auart_driver,
+};
+#endif
+
+static struct uart_driver auart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "ttyAPP",
+	.dev_name	= "ttyAPP",
+	.major		= 0,
+	.minor		= 0,
+	.nr		= MXS_AUART_PORTS,
+#ifdef CONFIG_SERIAL_MXS_AUART_CONSOLE
+	.cons =		&auart_console,
+#endif
+};
+
+static int __devinit mxs_auart_probe(struct platform_device *pdev)
+{
+	struct mxs_auart_port *s;
+	u32 version;
+	int ret = 0;
+	struct resource *r;
+
+	s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL);
+	if (!s) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	s->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(s->clk)) {
+		ret = PTR_ERR(s->clk);
+		goto out_free;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!r) {
+		ret = -ENXIO;
+		goto out_free_clk;
+	}
+
+	s->port.mapbase = r->start;
+	s->port.membase = ioremap(r->start, resource_size(r));
+	s->port.ops = &mxs_auart_ops;
+	s->port.iotype = UPIO_MEM;
+	s->port.line = pdev->id < 0 ? 0 : pdev->id;
+	s->port.fifosize = 16;
+	s->port.uartclk = clk_get_rate(s->clk);
+	s->port.type = PORT_IMX;
+	s->port.dev = s->dev = get_device(&pdev->dev);
+
+	s->flags = 0;
+	s->ctrl = 0;
+
+	s->irq = platform_get_irq(pdev, 0);
+	s->port.irq = s->irq;
+	ret = request_irq(s->irq, mxs_auart_irq_handle, 0, dev_name(&pdev->dev), s);
+	if (ret)
+		goto out_free_clk;
+
+	platform_set_drvdata(pdev, s);
+
+	auart_port[pdev->id] = s;
+
+	mxs_auart_reset(&s->port);
+
+	ret = uart_add_one_port(&auart_driver, &s->port);
+	if (ret)
+		goto out_free_irq;
+
+	version = readl(s->port.membase + AUART_VERSION);
+	dev_info(&pdev->dev, "Found APPUART %d.%d.%d\n",
+	       (version >> 24) & 0xff,
+	       (version >> 16) & 0xff, version & 0xffff);
+
+	return 0;
+
+out_free_irq:
+	auart_port[pdev->id] = NULL;
+	free_irq(s->irq, s);
+out_free_clk:
+	clk_put(s->clk);
+out_free:
+	kfree(s);
+out:
+	return ret;
+}
+
+static int __devexit mxs_auart_remove(struct platform_device *pdev)
+{
+	struct mxs_auart_port *s = platform_get_drvdata(pdev);
+
+	uart_remove_one_port(&auart_driver, &s->port);
+
+	auart_port[pdev->id] = NULL;
+
+	clk_put(s->clk);
+	free_irq(s->irq, s);
+	kfree(s);
+
+	return 0;
+}
+
+static struct platform_driver mxs_auart_driver = {
+	.probe = mxs_auart_probe,
+	.remove = __devexit_p(mxs_auart_remove),
+	.driver = {
+		.name = "mxs-auart",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mxs_auart_init(void)
+{
+	int r;
+
+	r = uart_register_driver(&auart_driver);
+	if (r)
+		goto out;
+
+	r = platform_driver_register(&mxs_auart_driver);
+	if (r)
+		goto out_err;
+
+	return 0;
+out_err:
+	uart_unregister_driver(&auart_driver);
+out:
+	return r;
+}
+
+static void __exit mxs_auart_exit(void)
+{
+	platform_driver_unregister(&mxs_auart_driver);
+	uart_unregister_driver(&auart_driver);
+}
+
+module_init(mxs_auart_init);
+module_exit(mxs_auart_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Freescale MXS application uart driver");
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 5c7abe4..0e8eec5 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -80,14 +80,16 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 /*
  * Try to register a serial port
  */
-static int __devinit of_platform_serial_probe(struct platform_device *ofdev,
-						const struct of_device_id *id)
+static int __devinit of_platform_serial_probe(struct platform_device *ofdev)
 {
 	struct of_serial_info *info;
 	struct uart_port port;
 	int port_type;
 	int ret;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+
 	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
 		return -EBUSY;
 
@@ -95,7 +97,7 @@ static int __devinit of_platform_serial_probe(struct platform_device *ofdev,
 	if (info == NULL)
 		return -ENOMEM;
 
-	port_type = (unsigned long)id->data;
+	port_type = (unsigned long)ofdev->dev.of_match->data;
 	ret = of_platform_serial_setup(ofdev, port_type, &port);
 	if (ret)
 		goto out;
@@ -160,21 +162,21 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
  * A few common types, add more as needed.
  */
 static struct of_device_id __devinitdata of_platform_serial_table[] = {
-	{ .type = "serial", .compatible = "ns8250",   .data = (void *)PORT_8250, },
-	{ .type = "serial", .compatible = "ns16450",  .data = (void *)PORT_16450, },
-	{ .type = "serial", .compatible = "ns16550a", .data = (void *)PORT_16550A, },
-	{ .type = "serial", .compatible = "ns16550",  .data = (void *)PORT_16550, },
-	{ .type = "serial", .compatible = "ns16750",  .data = (void *)PORT_16750, },
-	{ .type = "serial", .compatible = "ns16850",  .data = (void *)PORT_16850, },
+	{ .compatible = "ns8250",   .data = (void *)PORT_8250, },
+	{ .compatible = "ns16450",  .data = (void *)PORT_16450, },
+	{ .compatible = "ns16550a", .data = (void *)PORT_16550A, },
+	{ .compatible = "ns16550",  .data = (void *)PORT_16550, },
+	{ .compatible = "ns16750",  .data = (void *)PORT_16750, },
+	{ .compatible = "ns16850",  .data = (void *)PORT_16850, },
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
-	{ .type = "serial", .compatible = "ibm,qpace-nwp-serial",
-					.data = (void *)PORT_NWPSERIAL, },
+	{ .compatible = "ibm,qpace-nwp-serial",
+		.data = (void *)PORT_NWPSERIAL, },
 #endif
-	{ .type = "serial",			      .data = (void *)PORT_UNKNOWN, },
+	{ .type = "serial",         .data = (void *)PORT_UNKNOWN, },
 	{ /* end of list */ },
 };
 
-static struct of_platform_driver of_platform_serial_driver = {
+static struct platform_driver of_platform_serial_driver = {
 	.driver = {
 		.name = "of_serial",
 		.owner = THIS_MODULE,
@@ -186,13 +188,13 @@ static struct of_platform_driver of_platform_serial_driver = {
 
 static int __init of_platform_serial_init(void)
 {
-	return of_register_platform_driver(&of_platform_serial_driver);
+	return platform_driver_register(&of_platform_serial_driver);
 }
 module_init(of_platform_serial_init);
 
 static void __exit of_platform_serial_exit(void)
 {
-	return of_unregister_platform_driver(&of_platform_serial_driver);
+	return platform_driver_unregister(&of_platform_serial_driver);
 };
 module_exit(of_platform_serial_exit);
 
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7f2f010..7635379 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -20,6 +20,10 @@
  * this driver as required for the omap-platform.
  */
 
+#if defined(CONFIG_SERIAL_OMAP_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/console.h>
@@ -190,7 +194,6 @@ static inline void receive_chars(struct uart_omap_port *up, int *status)
 			if (up->port.line == up->port.cons->index) {
 				/* Recover the break flag from console xmit */
 				lsr |= up->lsr_break_flag;
-				up->lsr_break_flag = 0;
 			}
 #endif
 			if (lsr & UART_LSR_BI)
@@ -517,6 +520,9 @@ static int serial_omap_startup(struct uart_port *port)
 	up->ier = UART_IER_RLSI | UART_IER_RDI;
 	serial_out(up, UART_IER, up->ier);
 
+	/* Enable module level wake up */
+	serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
+
 	up->port_activity = jiffies;
 	return 0;
 }
@@ -824,9 +830,6 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
 	serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
 	serial_out(up, UART_EFR, efr);
 	serial_out(up, UART_LCR, 0);
-	/* Enable module level wake up */
-	serial_out(up, UART_OMAP_WER,
-		(state != 0) ? OMAP_UART_WER_MOD_WKUP : 0);
 }
 
 static void serial_omap_release_port(struct uart_port *port)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 70a6145..26403b8 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -15,12 +15,12 @@
  *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/serial_reg.h>
-#include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/serial_core.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/dmi.h>
 
 #include <linux/dmaengine.h>
 #include <linux/pch_dma.h>
@@ -40,10 +40,11 @@ enum {
 
 #define PCH_UART_DRIVER_DEVICE "ttyPCH"
 
-#define PCH_UART_NR_GE_256FIFO		1
-#define PCH_UART_NR_GE_64FIFO		3
-#define PCH_UART_NR_GE	(PCH_UART_NR_GE_256FIFO+PCH_UART_NR_GE_64FIFO)
-#define PCH_UART_NR	PCH_UART_NR_GE
+/* Set the max number of UART port
+ * Intel EG20T PCH: 4 port
+ * OKI SEMICONDUCTOR ML7213 IOH: 3 port
+*/
+#define PCH_UART_NR	4
 
 #define PCH_UART_HANDLED_RX_INT	(1<<((PCH_UART_HANDLED_RX_INT_SHIFT)<<1))
 #define PCH_UART_HANDLED_TX_INT	(1<<((PCH_UART_HANDLED_TX_INT_SHIFT)<<1))
@@ -192,6 +193,8 @@ enum {
 #define PCH_UART_HAL_LOOP		(PCH_UART_MCR_LOOP)
 #define PCH_UART_HAL_AFE		(PCH_UART_MCR_AFE)
 
+#define PCI_VENDOR_ID_ROHM		0x10DB
+
 struct pch_uart_buffer {
 	unsigned char *buf;
 	int size;
@@ -215,6 +218,7 @@ struct eg20t_port {
 	struct pch_uart_buffer rxbuf;
 	unsigned int dmsr;
 	unsigned int fcr;
+	unsigned int mcr;
 	unsigned int use_dma;
 	unsigned int use_dma_flag;
 	struct dma_async_tx_descriptor	*desc_tx;
@@ -223,13 +227,44 @@ struct eg20t_port {
 	struct pch_dma_slave		param_rx;
 	struct dma_chan			*chan_tx;
 	struct dma_chan			*chan_rx;
-	struct scatterlist		sg_tx;
+	struct scatterlist		*sg_tx_p;
+	int				nent;
 	struct scatterlist		sg_rx;
 	int				tx_dma_use;
 	void				*rx_buf_virt;
 	dma_addr_t			rx_buf_dma;
 };
 
+/**
+ * struct pch_uart_driver_data - private data structure for UART-DMA
+ * @port_type:			The number of DMA channel
+ * @line_no:			UART port line number (0, 1, 2...)
+ */
+struct pch_uart_driver_data {
+	int port_type;
+	int line_no;
+};
+
+enum pch_uart_num_t {
+	pch_et20t_uart0 = 0,
+	pch_et20t_uart1,
+	pch_et20t_uart2,
+	pch_et20t_uart3,
+	pch_ml7213_uart0,
+	pch_ml7213_uart1,
+	pch_ml7213_uart2,
+};
+
+static struct pch_uart_driver_data drv_dat[] = {
+	[pch_et20t_uart0] = {PCH_UART_8LINE, 0},
+	[pch_et20t_uart1] = {PCH_UART_2LINE, 1},
+	[pch_et20t_uart2] = {PCH_UART_2LINE, 2},
+	[pch_et20t_uart3] = {PCH_UART_2LINE, 3},
+	[pch_ml7213_uart0] = {PCH_UART_8LINE, 0},
+	[pch_ml7213_uart1] = {PCH_UART_2LINE, 1},
+	[pch_ml7213_uart2] = {PCH_UART_2LINE, 2},
+};
+
 static unsigned int default_baud = 9600;
 static const int trigger_level_256[4] = { 1, 64, 128, 224 };
 static const int trigger_level_64[4] = { 1, 16, 32, 56 };
@@ -278,7 +313,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
 
 	div = DIV_ROUND(priv->base_baud / 16, baud);
 	if (div < 0 || USHRT_MAX <= div) {
-		pr_err("Invalid Baud(div=0x%x)\n", div);
+		dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div);
 		return -EINVAL;
 	}
 
@@ -286,17 +321,17 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
 	dlm = ((unsigned int)div >> 8) & 0x00FFU;
 
 	if (parity & ~(PCH_UART_LCR_PEN | PCH_UART_LCR_EPS | PCH_UART_LCR_SP)) {
-		pr_err("Invalid parity(0x%x)\n", parity);
+		dev_err(priv->port.dev, "Invalid parity(0x%x)\n", parity);
 		return -EINVAL;
 	}
 
 	if (bits & ~PCH_UART_LCR_WLS) {
-		pr_err("Invalid bits(0x%x)\n", bits);
+		dev_err(priv->port.dev, "Invalid bits(0x%x)\n", bits);
 		return -EINVAL;
 	}
 
 	if (stb & ~PCH_UART_LCR_STB) {
-		pr_err("Invalid STB(0x%x)\n", stb);
+		dev_err(priv->port.dev, "Invalid STB(0x%x)\n", stb);
 		return -EINVAL;
 	}
 
@@ -304,7 +339,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
 	lcr |= bits;
 	lcr |= stb;
 
-	pr_debug("%s:baud = %d, div = %04x, lcr = %02x (%lu)\n",
+	dev_dbg(priv->port.dev, "%s:baud = %d, div = %04x, lcr = %02x (%lu)\n",
 		 __func__, baud, div, lcr, jiffies);
 	iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR);
 	iowrite8(dll, priv->membase + PCH_UART_DLL);
@@ -318,7 +353,8 @@ static int pch_uart_hal_fifo_reset(struct eg20t_port *priv,
 				    unsigned int flag)
 {
 	if (flag & ~(PCH_UART_FCR_TFR | PCH_UART_FCR_RFR)) {
-		pr_err("%s:Invalid flag(0x%x)\n", __func__, flag);
+		dev_err(priv->port.dev, "%s:Invalid flag(0x%x)\n",
+			__func__, flag);
 		return -EINVAL;
 	}
 
@@ -337,17 +373,20 @@ static int pch_uart_hal_set_fifo(struct eg20t_port *priv,
 	u8 fcr;
 
 	if (dmamode & ~PCH_UART_FCR_DMS) {
-		pr_err("%s:Invalid DMA Mode(0x%x)\n", __func__, dmamode);
+		dev_err(priv->port.dev, "%s:Invalid DMA Mode(0x%x)\n",
+			__func__, dmamode);
 		return -EINVAL;
 	}
 
 	if (fifo_size & ~(PCH_UART_FCR_FIFOE | PCH_UART_FCR_FIFO256)) {
-		pr_err("%s:Invalid FIFO SIZE(0x%x)\n", __func__, fifo_size);
+		dev_err(priv->port.dev, "%s:Invalid FIFO SIZE(0x%x)\n",
+			__func__, fifo_size);
 		return -EINVAL;
 	}
 
 	if (trigger & ~PCH_UART_FCR_RFTL) {
-		pr_err("%s:Invalid TRIGGER(0x%x)\n", __func__, trigger);
+		dev_err(priv->port.dev, "%s:Invalid TRIGGER(0x%x)\n",
+			__func__, trigger);
 		return -EINVAL;
 	}
 
@@ -386,7 +425,7 @@ static u8 pch_uart_hal_get_modem(struct eg20t_port *priv)
 	return get_msr(priv, priv->membase);
 }
 
-static int pch_uart_hal_write(struct eg20t_port *priv,
+static void pch_uart_hal_write(struct eg20t_port *priv,
 			      const unsigned char *buf, int tx_size)
 {
 	int i;
@@ -396,7 +435,6 @@ static int pch_uart_hal_write(struct eg20t_port *priv,
 		thr = buf[i++];
 		iowrite8(thr, priv->membase + PCH_UART_THR);
 	}
-	return i;
 }
 
 static int pch_uart_hal_read(struct eg20t_port *priv, unsigned char *buf,
@@ -452,7 +490,7 @@ static int push_rx(struct eg20t_port *priv, const unsigned char *buf,
 	port = &priv->port;
 	tty = tty_port_tty_get(&port->state->port);
 	if (!tty) {
-		pr_debug("%s:tty is busy now", __func__);
+		dev_dbg(priv->port.dev, "%s:tty is busy now", __func__);
 		return -EBUSY;
 	}
 
@@ -469,8 +507,8 @@ static int pop_tx_x(struct eg20t_port *priv, unsigned char *buf)
 	struct uart_port *port = &priv->port;
 
 	if (port->x_char) {
-		pr_debug("%s:X character send %02x (%lu)\n", __func__,
-			port->x_char, jiffies);
+		dev_dbg(priv->port.dev, "%s:X character send %02x (%lu)\n",
+			__func__, port->x_char, jiffies);
 		buf[0] = port->x_char;
 		port->x_char = 0;
 		ret = 1;
@@ -490,7 +528,7 @@ static int dma_push_rx(struct eg20t_port *priv, int size)
 	port = &priv->port;
 	tty = tty_port_tty_get(&port->state->port);
 	if (!tty) {
-		pr_debug("%s:tty is busy now", __func__);
+		dev_dbg(priv->port.dev, "%s:tty is busy now", __func__);
 		return 0;
 	}
 
@@ -560,11 +598,13 @@ static void pch_request_dma(struct uart_port *port)
 	/* Set Tx DMA */
 	param = &priv->param_tx;
 	param->dma_dev = &dma_dev->dev;
-	param->chan_id = priv->port.line;
+	param->chan_id = priv->port.line * 2; /* Tx = 0, 2, 4, ... */
+
 	param->tx_reg = port->mapbase + UART_TX;
 	chan = dma_request_channel(mask, filter, param);
 	if (!chan) {
-		pr_err("%s:dma_request_channel FAILS(Tx)\n", __func__);
+		dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n",
+			__func__);
 		return;
 	}
 	priv->chan_tx = chan;
@@ -572,11 +612,13 @@ static void pch_request_dma(struct uart_port *port)
 	/* Set Rx DMA */
 	param = &priv->param_rx;
 	param->dma_dev = &dma_dev->dev;
-	param->chan_id = priv->port.line + 1; /* Rx = Tx + 1 */
+	param->chan_id = priv->port.line * 2 + 1; /* Rx = Tx + 1 */
+
 	param->rx_reg = port->mapbase + UART_RX;
 	chan = dma_request_channel(mask, filter, param);
 	if (!chan) {
-		pr_err("%s:dma_request_channel FAILS(Rx)\n", __func__);
+		dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
+			__func__);
 		dma_release_channel(priv->chan_tx);
 		return;
 	}
@@ -592,16 +634,20 @@ static void pch_dma_rx_complete(void *arg)
 	struct eg20t_port *priv = arg;
 	struct uart_port *port = &priv->port;
 	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+	int count;
 
 	if (!tty) {
-		pr_debug("%s:tty is busy now", __func__);
+		dev_dbg(priv->port.dev, "%s:tty is busy now", __func__);
 		return;
 	}
 
-	if (dma_push_rx(priv, priv->trigger_level))
+	dma_sync_sg_for_cpu(port->dev, &priv->sg_rx, 1, DMA_FROM_DEVICE);
+	count = dma_push_rx(priv, priv->trigger_level);
+	if (count)
 		tty_flip_buffer_push(tty);
-
 	tty_kref_put(tty);
+	async_tx_ack(priv->desc_rx);
+	pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT);
 }
 
 static void pch_dma_tx_complete(void *arg)
@@ -609,16 +655,23 @@ static void pch_dma_tx_complete(void *arg)
 	struct eg20t_port *priv = arg;
 	struct uart_port *port = &priv->port;
 	struct circ_buf *xmit = &port->state->xmit;
+	struct scatterlist *sg = priv->sg_tx_p;
+	int i;
 
-	xmit->tail += sg_dma_len(&priv->sg_tx);
+	for (i = 0; i < priv->nent; i++, sg++) {
+		xmit->tail += sg_dma_len(sg);
+		port->icount.tx += sg_dma_len(sg);
+	}
 	xmit->tail &= UART_XMIT_SIZE - 1;
-	port->icount.tx += sg_dma_len(&priv->sg_tx);
-
 	async_tx_ack(priv->desc_tx);
+	dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE);
 	priv->tx_dma_use = 0;
+	priv->nent = 0;
+	kfree(priv->sg_tx_p);
+	pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
 }
 
-static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size)
+static int pop_tx(struct eg20t_port *priv, int size)
 {
 	int count = 0;
 	struct uart_port *port = &priv->port;
@@ -631,13 +684,13 @@ static int pop_tx(struct eg20t_port *priv, unsigned char *buf, int size)
 		int cnt_to_end =
 		    CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
 		int sz = min(size - count, cnt_to_end);
-		memcpy(&buf[count], &xmit->buf[xmit->tail], sz);
+		pch_uart_hal_write(priv, &xmit->buf[xmit->tail], sz);
 		xmit->tail = (xmit->tail + sz) & (UART_XMIT_SIZE - 1);
 		count += sz;
 	} while (!uart_circ_empty(xmit) && count < size);
 
 pop_tx_end:
-	pr_debug("%d characters. Remained %d characters. (%lu)\n",
+	dev_dbg(priv->port.dev, "%d characters. Remained %d characters.(%lu)\n",
 		 count, size - count, jiffies);
 
 	return count;
@@ -679,7 +732,7 @@ static int dma_handle_rx(struct eg20t_port *priv)
 
 	sg_init_table(&priv->sg_rx, 1); /* Initialize SG table */
 
-	sg_dma_len(sg) = priv->fifo_size;
+	sg_dma_len(sg) = priv->trigger_level;
 
 	sg_set_page(&priv->sg_rx, virt_to_page(priv->rx_buf_virt),
 		     sg_dma_len(sg), (unsigned long)priv->rx_buf_virt &
@@ -689,7 +742,8 @@ static int dma_handle_rx(struct eg20t_port *priv)
 
 	desc = priv->chan_rx->device->device_prep_slave_sg(priv->chan_rx,
 			sg, 1, DMA_FROM_DEVICE,
-			DMA_PREP_INTERRUPT);
+			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
 	if (!desc)
 		return 0;
 
@@ -706,14 +760,14 @@ static unsigned int handle_tx(struct eg20t_port *priv)
 {
 	struct uart_port *port = &priv->port;
 	struct circ_buf *xmit = &port->state->xmit;
-	int ret;
 	int fifo_size;
 	int tx_size;
 	int size;
 	int tx_empty;
 
 	if (!priv->start_tx) {
-		pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
+		dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
+			__func__, jiffies);
 		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
 		priv->tx_empty = 1;
 		return 0;
@@ -728,17 +782,21 @@ static unsigned int handle_tx(struct eg20t_port *priv)
 		fifo_size--;
 	}
 	size = min(xmit->head - xmit->tail, fifo_size);
-	tx_size = pop_tx(priv, xmit->buf, size);
+	if (size < 0)
+		size = fifo_size;
+
+	tx_size = pop_tx(priv, size);
 	if (tx_size > 0) {
-		ret = pch_uart_hal_write(priv, xmit->buf, tx_size);
-		port->icount.tx += ret;
+		port->icount.tx += tx_size;
 		tx_empty = 0;
 	}
 
 	priv->tx_empty = tx_empty;
 
-	if (tx_empty)
+	if (tx_empty) {
 		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+		uart_write_wakeup(port);
+	}
 
 	return PCH_UART_HANDLED_TX_INT;
 }
@@ -747,14 +805,28 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
 {
 	struct uart_port *port = &priv->port;
 	struct circ_buf *xmit = &port->state->xmit;
-	struct scatterlist *sg = &priv->sg_tx;
+	struct scatterlist *sg;
 	int nent;
 	int fifo_size;
 	int tx_empty;
 	struct dma_async_tx_descriptor *desc;
+	int num;
+	int i;
+	int bytes;
+	int size;
+	int rem;
 
 	if (!priv->start_tx) {
-		pr_info("%s:Tx isn't started. (%lu)\n", __func__, jiffies);
+		dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
+			__func__, jiffies);
+		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+		priv->tx_empty = 1;
+		return 0;
+	}
+
+	if (priv->tx_dma_use) {
+		dev_dbg(priv->port.dev, "%s:Tx is not completed. (%lu)\n",
+			__func__, jiffies);
 		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
 		priv->tx_empty = 1;
 		return 0;
@@ -769,37 +841,73 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
 		fifo_size--;
 	}
 
-	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+	bytes = min((int)CIRC_CNT(xmit->head, xmit->tail,
+			     UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
+			     xmit->tail, UART_XMIT_SIZE));
+	if (!bytes) {
+		dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__);
+		pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_TX_INT);
+		uart_write_wakeup(port);
+		return 0;
+	}
+
+	if (bytes > fifo_size) {
+		num = bytes / fifo_size + 1;
+		size = fifo_size;
+		rem = bytes % fifo_size;
+	} else {
+		num = 1;
+		size = bytes;
+		rem = bytes;
+	}
+
+	dev_dbg(priv->port.dev, "%s num=%d size=%d rem=%d\n",
+		__func__, num, size, rem);
 
 	priv->tx_dma_use = 1;
 
-	sg_init_table(&priv->sg_tx, 1); /* Initialize SG table */
+	priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
 
-	sg_set_page(&priv->sg_tx, virt_to_page(xmit->buf),
-		    UART_XMIT_SIZE, (int)xmit->buf & ~PAGE_MASK);
+	sg_init_table(priv->sg_tx_p, num); /* Initialize SG table */
+	sg = priv->sg_tx_p;
 
-	nent = dma_map_sg(port->dev, &priv->sg_tx, 1, DMA_TO_DEVICE);
+	for (i = 0; i < num; i++, sg++) {
+		if (i == (num - 1))
+			sg_set_page(sg, virt_to_page(xmit->buf),
+				    rem, fifo_size * i);
+		else
+			sg_set_page(sg, virt_to_page(xmit->buf),
+				    size, fifo_size * i);
+	}
+
+	sg = priv->sg_tx_p;
+	nent = dma_map_sg(port->dev, sg, num, DMA_TO_DEVICE);
 	if (!nent) {
-		pr_err("%s:dma_map_sg Failed\n", __func__);
+		dev_err(priv->port.dev, "%s:dma_map_sg Failed\n", __func__);
 		return 0;
 	}
-
-	sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
-	sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
-			      sg->offset;
-	sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail,
-			     UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
-			     xmit->tail, UART_XMIT_SIZE));
+	priv->nent = nent;
+
+	for (i = 0; i < nent; i++, sg++) {
+		sg->offset = (xmit->tail & (UART_XMIT_SIZE - 1)) +
+			      fifo_size * i;
+		sg_dma_address(sg) = (sg_dma_address(sg) &
+				    ~(UART_XMIT_SIZE - 1)) + sg->offset;
+		if (i == (nent - 1))
+			sg_dma_len(sg) = rem;
+		else
+			sg_dma_len(sg) = size;
+	}
 
 	desc = priv->chan_tx->device->device_prep_slave_sg(priv->chan_tx,
-		sg, nent, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+					priv->sg_tx_p, nent, DMA_TO_DEVICE,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc) {
-		pr_err("%s:device_prep_slave_sg Failed\n", __func__);
+		dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
+			__func__);
 		return 0;
 	}
-
-	dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
-
+	dma_sync_sg_for_device(port->dev, priv->sg_tx_p, nent, DMA_TO_DEVICE);
 	priv->desc_tx = desc;
 	desc->callback = pch_dma_tx_complete;
 	desc->callback_param = priv;
@@ -854,10 +962,16 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
 			}
 			break;
 		case PCH_UART_IID_RDR:	/* Received Data Ready */
-			if (priv->use_dma)
+			if (priv->use_dma) {
+				pch_uart_hal_disable_interrupt(priv,
+							PCH_UART_HAL_RX_INT);
 				ret = dma_handle_rx(priv);
-			else
+				if (!ret)
+					pch_uart_hal_enable_interrupt(priv,
+							PCH_UART_HAL_RX_INT);
+			} else {
 				ret = handle_rx(priv);
+			}
 			break;
 		case PCH_UART_IID_RDR_TO:	/* Received Data Ready
 						   (FIFO Timeout) */
@@ -874,7 +988,8 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id)
 			ret = PCH_UART_HANDLED_MS_INT;
 			break;
 		default:	/* Never junp to this label */
-			pr_err("%s:iid=%d (%lu)\n", __func__, iid, jiffies);
+			dev_err(priv->port.dev, "%s:iid=%d (%lu)\n", __func__,
+				iid, jiffies);
 			ret = -1;
 			break;
 		}
@@ -932,7 +1047,6 @@ static unsigned int pch_uart_get_mctrl(struct uart_port *port)
 static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
 	u32 mcr = 0;
-	unsigned int dat;
 	struct eg20t_port *priv = container_of(port, struct eg20t_port, port);
 
 	if (mctrl & TIOCM_DTR)
@@ -942,11 +1056,11 @@ static void pch_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 	if (mctrl & TIOCM_LOOP)
 		mcr |= UART_MCR_LOOP;
 
-	if (mctrl) {
-		dat = pch_uart_get_mctrl(port);
-		dat |= mcr;
-		iowrite8(dat, priv->membase + UART_MCR);
-	}
+	if (priv->mcr & UART_MCR_AFE)
+		mcr |= UART_MCR_AFE;
+
+	if (mctrl)
+		iowrite8(mcr, priv->membase + UART_MCR);
 }
 
 static void pch_uart_stop_tx(struct uart_port *port)
@@ -963,9 +1077,13 @@ static void pch_uart_start_tx(struct uart_port *port)
 
 	priv = container_of(port, struct eg20t_port, port);
 
-	if (priv->use_dma)
-		if (priv->tx_dma_use)
+	if (priv->use_dma) {
+		if (priv->tx_dma_use) {
+			dev_dbg(priv->port.dev, "%s : Tx DMA is NOT empty.\n",
+				__func__);
 			return;
+		}
+	}
 
 	priv->start_tx = 1;
 	pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_TX_INT);
@@ -1010,7 +1128,12 @@ static int pch_uart_startup(struct uart_port *port)
 
 	priv = container_of(port, struct eg20t_port, port);
 	priv->tx_empty = 1;
-	port->uartclk = priv->base_baud;
+
+	if (port->uartclk)
+		priv->base_baud = port->uartclk;
+	else
+		port->uartclk = priv->base_baud;
+
 	pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
 	ret = pch_uart_hal_set_line(priv, default_baud,
 			      PCH_UART_HAL_PARITY_NONE, PCH_UART_HAL_8BIT,
@@ -1081,7 +1204,8 @@ static void pch_uart_shutdown(struct uart_port *port)
 	ret = pch_uart_hal_set_fifo(priv, PCH_UART_HAL_DMA_MODE0,
 			      PCH_UART_HAL_FIFO_DIS, PCH_UART_HAL_TRIGGER1);
 	if (ret)
-		pr_err("pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
+		dev_err(priv->port.dev,
+			"pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
 
 	if (priv->use_dma_flag)
 		pch_free_dma(port);
@@ -1130,6 +1254,13 @@ static void pch_uart_set_termios(struct uart_port *port,
 	} else {
 		parity = PCH_UART_HAL_PARITY_NONE;
 	}
+
+	/* Only UART0 has auto hardware flow function */
+	if ((termios->c_cflag & CRTSCTS) && (priv->fifo_size == 256))
+		priv->mcr |= UART_MCR_AFE;
+	else
+		priv->mcr &= ~UART_MCR_AFE;
+
 	termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
 
 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
@@ -1202,17 +1333,19 @@ static int pch_uart_verify_port(struct uart_port *port,
 
 	priv = container_of(port, struct eg20t_port, port);
 	if (serinfo->flags & UPF_LOW_LATENCY) {
-		pr_info("PCH UART : Use PIO Mode (without DMA)\n");
+		dev_info(priv->port.dev,
+			"PCH UART : Use PIO Mode (without DMA)\n");
 		priv->use_dma = 0;
 		serinfo->flags &= ~UPF_LOW_LATENCY;
 	} else {
 #ifndef CONFIG_PCH_DMA
-		pr_err("%s : PCH DMA is not Loaded.\n", __func__);
+		dev_err(priv->port.dev, "%s : PCH DMA is not Loaded.\n",
+			__func__);
 		return -EOPNOTSUPP;
 #endif
 		priv->use_dma = 1;
 		priv->use_dma_flag = 1;
-		pr_info("PCH UART : Use DMA Mode\n");
+		dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
 	}
 
 	return 0;
@@ -1249,7 +1382,7 @@ static struct uart_driver pch_uart_driver = {
 };
 
 static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
-						int port_type)
+					     const struct pci_device_id *id)
 {
 	struct eg20t_port *priv;
 	int ret;
@@ -1257,7 +1390,11 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
 	unsigned int mapbase;
 	unsigned char *rxbuf;
 	int fifosize, base_baud;
-	static int num;
+	int port_type;
+	struct pch_uart_driver_data *board;
+
+	board = &drv_dat[id->driver_data];
+	port_type = board->port_type;
 
 	priv = kzalloc(sizeof(struct eg20t_port), GFP_KERNEL);
 	if (priv == NULL)
@@ -1267,14 +1404,18 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
 	if (!rxbuf)
 		goto init_port_free_txbuf;
 
+	base_baud = 1843200; /* 1.8432MHz */
+
+	/* quirk for CM-iTC board */
+	if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+		base_baud = 192000000; /* 192.0MHz */
+
 	switch (port_type) {
 	case PORT_UNKNOWN:
-		fifosize = 256; /* UART0 */
-		base_baud = 1843200; /* 1.8432MHz */
+		fifosize = 256; /* EG20T/ML7213: UART0 */
 		break;
 	case PORT_8250:
-		fifosize = 64; /* UART1~3 */
-		base_baud = 1843200; /* 1.8432MHz */
+		fifosize = 64; /* EG20T:UART1~3  ML7213: UART1~2*/
 		break;
 	default:
 		dev_err(&pdev->dev, "Invalid Port Type(=%d)\n", port_type);
@@ -1302,11 +1443,14 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
 	priv->port.ops = &pch_uart_ops;
 	priv->port.flags = UPF_BOOT_AUTOCONF;
 	priv->port.fifosize = fifosize;
-	priv->port.line = num++;
+	priv->port.line = board->line_no;
 	priv->trigger = PCH_UART_HAL_TRIGGER_M;
 
+	spin_lock_init(&priv->port.lock);
+
 	pci_set_drvdata(pdev, priv);
 	pch_uart_hal_request(pdev, fifosize, base_baud);
+
 	ret = uart_add_one_port(&pch_uart_driver, &priv->port);
 	if (ret < 0)
 		goto init_port_hal_free;
@@ -1377,13 +1521,19 @@ static int pch_uart_pci_resume(struct pci_dev *pdev)
 
 static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
-	 .driver_data = PCH_UART_8LINE},
+	 .driver_data = pch_et20t_uart0},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8812),
-	 .driver_data = PCH_UART_2LINE},
+	 .driver_data = pch_et20t_uart1},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8813),
-	 .driver_data = PCH_UART_2LINE},
+	 .driver_data = pch_et20t_uart2},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8814),
-	 .driver_data = PCH_UART_2LINE},
+	 .driver_data = pch_et20t_uart3},
+	{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8027),
+	 .driver_data = pch_ml7213_uart0},
+	{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8028),
+	 .driver_data = pch_ml7213_uart1},
+	{PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8029),
+	 .driver_data = pch_ml7213_uart2},
 	{0,},
 };
 
@@ -1397,7 +1547,7 @@ static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
 	if (ret < 0)
 		goto probe_error;
 
-	priv = pch_uart_init_port(pdev, id->driver_data);
+	priv = pch_uart_init_port(pdev, id);
 	if (!priv) {
 		ret = -EBUSY;
 		goto probe_disable_device;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 460a72d..733fe8e 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -905,7 +905,7 @@ static int uart_get_lsr_info(struct tty_struct *tty,
 	return put_user(result, value);
 }
 
-static int uart_tiocmget(struct tty_struct *tty, struct file *file)
+static int uart_tiocmget(struct tty_struct *tty)
 {
 	struct uart_state *state = tty->driver_data;
 	struct tty_port *port = &state->port;
@@ -913,10 +913,8 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
 	int result = -EIO;
 
 	mutex_lock(&port->mutex);
-	if ((!file || !tty_hung_up_p(file)) &&
-	    !(tty->flags & (1 << TTY_IO_ERROR))) {
+	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
 		result = uport->mctrl;
-
 		spin_lock_irq(&uport->lock);
 		result |= uport->ops->get_mctrl(uport);
 		spin_unlock_irq(&uport->lock);
@@ -927,8 +925,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 static int
-uart_tiocmset(struct tty_struct *tty, struct file *file,
-	      unsigned int set, unsigned int clear)
+uart_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
 {
 	struct uart_state *state = tty->driver_data;
 	struct uart_port *uport = state->uart_port;
@@ -936,8 +933,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
 	int ret = -EIO;
 
 	mutex_lock(&port->mutex);
-	if ((!file || !tty_hung_up_p(file)) &&
-	    !(tty->flags & (1 << TTY_IO_ERROR))) {
+	if (!(tty->flags & (1 << TTY_IO_ERROR))) {
 		uart_update_mctrl(uport, set, clear);
 		ret = 0;
 	}
@@ -1103,7 +1099,7 @@ static int uart_get_icount(struct tty_struct *tty,
  * Called via sys_ioctl.  We can use spin_lock_irq() here.
  */
 static int
-uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
+uart_ioctl(struct tty_struct *tty, unsigned int cmd,
 	   unsigned long arg)
 {
 	struct uart_state *state = tty->driver_data;
@@ -1156,7 +1152,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
 
 	mutex_lock(&port->mutex);
 
-	if (tty_hung_up_p(filp)) {
+	if (tty->flags & (1 << TTY_IO_ERROR)) {
 		ret = -EIO;
 		goto out_up;
 	}
@@ -2064,7 +2060,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
 	/*
 	 * Re-enable the console device after suspending.
 	 */
-	if (console_suspend_enabled && uart_console(uport)) {
+	if (uart_console(uport)) {
 		/*
 		 * First try to use the console cflag setting.
 		 */
@@ -2077,9 +2073,9 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
 		if (port->tty && port->tty->termios && termios.c_cflag == 0)
 			termios = *(port->tty->termios);
 
-		uart_change_pm(state, 0);
 		uport->ops->set_termios(uport, &termios, NULL);
-		console_start(uport->cons);
+		if (console_suspend_enabled)
+			console_start(uport->cons);
 	}
 
 	if (port->flags & ASYNC_SUSPENDED) {
diff --git a/drivers/tty/serial/serial_lh7a40x.c b/drivers/tty/serial/serial_lh7a40x.c
deleted file mode 100644
index ea74470..0000000
--- a/drivers/tty/serial/serial_lh7a40x.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/* drivers/serial/serial_lh7a40x.c
- *
- *  Copyright (C) 2004 Coastal Environmental 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.
- *
- */
-
-/* Driver for Sharp LH7A40X embedded serial ports
- *
- *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
- *  Based on drivers/serial/amba.c, by Deep Blue Solutions Ltd.
- *
- *  ---
- *
- * This driver supports the embedded UARTs of the Sharp LH7A40X series
- * CPUs.  While similar to the 16550 and other UART chips, there is
- * nothing close to register compatibility.  Moreover, some of the
- * modem control lines are not available, either in the chip or they
- * are lacking in the board-level implementation.
- *
- * - Use of SIRDIS
- *   For simplicity, we disable the IR functions of any UART whenever
- *   we enable it.
- *
- */
-
-
-#if defined(CONFIG_SERIAL_LH7A40X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
-#include <linux/module.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/sysrq.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#define DEV_MAJOR	204
-#define DEV_MINOR	16
-#define DEV_NR		3
-
-#define ISR_LOOP_LIMIT	256
-
-#define UR(p,o)	_UR ((p)->membase, o)
-#define _UR(b,o) (*((volatile unsigned int*)(((unsigned char*) b) + (o))))
-#define BIT_CLR(p,o,m)	UR(p,o) = UR(p,o) & (~(unsigned int)m)
-#define BIT_SET(p,o,m)	UR(p,o) = UR(p,o) | ( (unsigned int)m)
-
-#define UART_REG_SIZE	32
-
-#define UART_R_DATA	(0x00)
-#define UART_R_FCON	(0x04)
-#define UART_R_BRCON	(0x08)
-#define UART_R_CON	(0x0c)
-#define UART_R_STATUS	(0x10)
-#define UART_R_RAWISR	(0x14)
-#define UART_R_INTEN	(0x18)
-#define UART_R_ISR	(0x1c)
-
-#define UARTEN		(0x01)		/* UART enable */
-#define SIRDIS		(0x02)		/* Serial IR disable (UART1 only) */
-
-#define RxEmpty		(0x10)
-#define TxEmpty		(0x80)
-#define TxFull		(0x20)
-#define nRxRdy		RxEmpty
-#define nTxRdy		TxFull
-#define TxBusy		(0x08)
-
-#define RxBreak		(0x0800)
-#define RxOverrunError	(0x0400)
-#define RxParityError	(0x0200)
-#define RxFramingError	(0x0100)
-#define RxError     (RxBreak | RxOverrunError | RxParityError | RxFramingError)
-
-#define DCD		(0x04)
-#define DSR		(0x02)
-#define CTS		(0x01)
-
-#define RxInt		(0x01)
-#define TxInt		(0x02)
-#define ModemInt	(0x04)
-#define RxTimeoutInt	(0x08)
-
-#define MSEOI		(0x10)
-
-#define WLEN_8		(0x60)
-#define WLEN_7		(0x40)
-#define WLEN_6		(0x20)
-#define WLEN_5		(0x00)
-#define WLEN		(0x60)	/* Mask for all word-length bits */
-#define STP2		(0x08)
-#define PEN		(0x02)	/* Parity Enable */
-#define EPS		(0x04)	/* Even Parity Set */
-#define FEN		(0x10)	/* FIFO Enable */
-#define BRK		(0x01)	/* Send Break */
-
-
-struct uart_port_lh7a40x {
-	struct uart_port port;
-	unsigned int statusPrev; /* Most recently read modem status */
-};
-
-static void lh7a40xuart_stop_tx (struct uart_port* port)
-{
-	BIT_CLR (port, UART_R_INTEN, TxInt);
-}
-
-static void lh7a40xuart_start_tx (struct uart_port* port)
-{
-	BIT_SET (port, UART_R_INTEN, TxInt);
-
-	/* *** FIXME: do I need to check for startup of the
-		      transmitter?  The old driver did, but AMBA
-		      doesn't . */
-}
-
-static void lh7a40xuart_stop_rx (struct uart_port* port)
-{
-	BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
-}
-
-static void lh7a40xuart_enable_ms (struct uart_port* port)
-{
-	BIT_SET (port, UART_R_INTEN, ModemInt);
-}
-
-static void lh7a40xuart_rx_chars (struct uart_port* port)
-{
-	struct tty_struct* tty = port->state->port.tty;
-	int cbRxMax = 256;	/* (Gross) limit on receive */
-	unsigned int data;	/* Received data and status */
-	unsigned int flag;
-
-	while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
-		data = UR (port, UART_R_DATA);
-		flag = TTY_NORMAL;
-		++port->icount.rx;
-
-		if (unlikely(data & RxError)) {
-			if (data & RxBreak) {
-				data &= ~(RxFramingError | RxParityError);
-				++port->icount.brk;
-				if (uart_handle_break (port))
-					continue;
-			}
-			else if (data & RxParityError)
-				++port->icount.parity;
-			else if (data & RxFramingError)
-				++port->icount.frame;
-			if (data & RxOverrunError)
-				++port->icount.overrun;
-
-				/* Mask by termios, leave Rx'd byte */
-			data &= port->read_status_mask | 0xff;
-
-			if (data & RxBreak)
-				flag = TTY_BREAK;
-			else if (data & RxParityError)
-				flag = TTY_PARITY;
-			else if (data & RxFramingError)
-				flag = TTY_FRAME;
-		}
-
-		if (uart_handle_sysrq_char (port, (unsigned char) data))
-			continue;
-
-		uart_insert_char(port, data, RxOverrunError, data, flag);
-	}
-	tty_flip_buffer_push (tty);
-	return;
-}
-
-static void lh7a40xuart_tx_chars (struct uart_port* port)
-{
-	struct circ_buf* xmit = &port->state->xmit;
-	int cbTxMax = port->fifosize;
-
-	if (port->x_char) {
-		UR (port, UART_R_DATA) = port->x_char;
-		++port->icount.tx;
-		port->x_char = 0;
-		return;
-	}
-	if (uart_circ_empty (xmit) || uart_tx_stopped (port)) {
-		lh7a40xuart_stop_tx (port);
-		return;
-	}
-
-	/* Unlike the AMBA UART, the lh7a40x UART does not guarantee
-	   that at least half of the FIFO is empty.  Instead, we check
-	   status for every character.  Using the AMBA method causes
-	   the transmitter to drop characters. */
-
-	do {
-		UR (port, UART_R_DATA) = xmit->buf[xmit->tail];
-		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
-		++port->icount.tx;
-		if (uart_circ_empty(xmit))
-			break;
-	} while (!(UR (port, UART_R_STATUS) & nTxRdy)
-		 && cbTxMax--);
-
-	if (uart_circ_chars_pending (xmit) < WAKEUP_CHARS)
-		uart_write_wakeup (port);
-
-	if (uart_circ_empty (xmit))
-		lh7a40xuart_stop_tx (port);
-}
-
-static void lh7a40xuart_modem_status (struct uart_port* port)
-{
-	unsigned int status = UR (port, UART_R_STATUS);
-	unsigned int delta
-		= status ^ ((struct uart_port_lh7a40x*) port)->statusPrev;
-
-	BIT_SET (port, UART_R_RAWISR, MSEOI); /* Clear modem status intr */
-
-	if (!delta)		/* Only happens if we missed 2 transitions */
-		return;
-
-	((struct uart_port_lh7a40x*) port)->statusPrev = status;
-
-	if (delta & DCD)
-		uart_handle_dcd_change (port, status & DCD);
-
-	if (delta & DSR)
-		++port->icount.dsr;
-
-	if (delta & CTS)
-		uart_handle_cts_change (port, status & CTS);
-
-	wake_up_interruptible (&port->state->port.delta_msr_wait);
-}
-
-static irqreturn_t lh7a40xuart_int (int irq, void* dev_id)
-{
-	struct uart_port* port = dev_id;
-	unsigned int cLoopLimit = ISR_LOOP_LIMIT;
-	unsigned int isr = UR (port, UART_R_ISR);
-
-
-	do {
-		if (isr & (RxInt | RxTimeoutInt))
-			lh7a40xuart_rx_chars(port);
-		if (isr & ModemInt)
-			lh7a40xuart_modem_status (port);
-		if (isr & TxInt)
-			lh7a40xuart_tx_chars (port);
-
-		if (--cLoopLimit == 0)
-			break;
-
-		isr = UR (port, UART_R_ISR);
-	} while (isr & (RxInt | TxInt | RxTimeoutInt));
-
-	return IRQ_HANDLED;
-}
-
-static unsigned int lh7a40xuart_tx_empty (struct uart_port* port)
-{
-	return (UR (port, UART_R_STATUS) & TxEmpty) ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int lh7a40xuart_get_mctrl (struct uart_port* port)
-{
-	unsigned int result = 0;
-	unsigned int status = UR (port, UART_R_STATUS);
-
-	if (status & DCD)
-		result |= TIOCM_CAR;
-	if (status & DSR)
-		result |= TIOCM_DSR;
-	if (status & CTS)
-		result |= TIOCM_CTS;
-
-	return result;
-}
-
-static void lh7a40xuart_set_mctrl (struct uart_port* port, unsigned int mctrl)
-{
-	/* None of the ports supports DTR. UART1 supports RTS through GPIO. */
-	/* Note, kernel appears to be setting DTR and RTS on console. */
-
-	/* *** FIXME: this deserves more work.  There's some work in
-	       tracing all of the IO pins. */
-#if 0
-	if( port->mapbase == UART1_PHYS) {
-		gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
-
-		if (mctrl & TIOCM_RTS)
-			gpio->pbdr &= ~GPIOB_UART1_RTS;
-		else
-			gpio->pbdr |= GPIOB_UART1_RTS;
-	}
-#endif
-}
-
-static void lh7a40xuart_break_ctl (struct uart_port* port, int break_state)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (break_state == -1)
-		BIT_SET (port, UART_R_FCON, BRK); /* Assert break */
-	else
-		BIT_CLR (port, UART_R_FCON, BRK); /* Deassert break */
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static int lh7a40xuart_startup (struct uart_port* port)
-{
-	int retval;
-
-	retval = request_irq (port->irq, lh7a40xuart_int, 0,
-			      "serial_lh7a40x", port);
-	if (retval)
-		return retval;
-
-				/* Initial modem control-line settings */
-	((struct uart_port_lh7a40x*) port)->statusPrev
-		= UR (port, UART_R_STATUS);
-
-	/* There is presently no configuration option to enable IR.
-	   Thus, we always disable it. */
-
-	BIT_SET (port, UART_R_CON, UARTEN | SIRDIS);
-	BIT_SET (port, UART_R_INTEN, RxTimeoutInt | RxInt);
-
-	return 0;
-}
-
-static void lh7a40xuart_shutdown (struct uart_port* port)
-{
-	free_irq (port->irq, port);
-	BIT_CLR (port, UART_R_FCON, BRK | FEN);
-	BIT_CLR (port, UART_R_CON, UARTEN);
-}
-
-static void lh7a40xuart_set_termios (struct uart_port* port,
-				     struct ktermios* termios,
-				     struct ktermios* old)
-{
-	unsigned int con;
-	unsigned int inten;
-	unsigned int fcon;
-	unsigned long flags;
-	unsigned int baud;
-	unsigned int quot;
-
-	baud = uart_get_baud_rate (port, termios, old, 8, port->uartclk/16);
-	quot = uart_get_divisor (port, baud); /* -1 performed elsewhere */
-
-	switch (termios->c_cflag & CSIZE) {
-	case CS5:
-		fcon = WLEN_5;
-		break;
-	case CS6:
-		fcon = WLEN_6;
-		break;
-	case CS7:
-		fcon = WLEN_7;
-		break;
-	case CS8:
-	default:
-		fcon = WLEN_8;
-		break;
-	}
-	if (termios->c_cflag & CSTOPB)
-		fcon |= STP2;
-	if (termios->c_cflag & PARENB) {
-		fcon |= PEN;
-		if (!(termios->c_cflag & PARODD))
-			fcon |= EPS;
-	}
-	if (port->fifosize > 1)
-		fcon |= FEN;
-
-	spin_lock_irqsave (&port->lock, flags);
-
-	uart_update_timeout (port, termios->c_cflag, baud);
-
-	port->read_status_mask = RxOverrunError;
-	if (termios->c_iflag & INPCK)
-		port->read_status_mask |= RxFramingError | RxParityError;
-	if (termios->c_iflag & (BRKINT | PARMRK))
-		port->read_status_mask |= RxBreak;
-
-		/* Figure mask for status we ignore */
-	port->ignore_status_mask = 0;
-	if (termios->c_iflag & IGNPAR)
-		port->ignore_status_mask |= RxFramingError | RxParityError;
-	if (termios->c_iflag & IGNBRK) {
-		port->ignore_status_mask |= RxBreak;
-		/* Ignore overrun when ignorning parity */
-		/* *** FIXME: is this in the right place? */
-		if (termios->c_iflag & IGNPAR)
-			port->ignore_status_mask |= RxOverrunError;
-	}
-
-		/* Ignore all receive errors when receive disabled */
-	if ((termios->c_cflag & CREAD) == 0)
-		port->ignore_status_mask |= RxError;
-
-	con   = UR (port, UART_R_CON);
-	inten = (UR (port, UART_R_INTEN) & ~ModemInt);
-
-	if (UART_ENABLE_MS (port, termios->c_cflag))
-		inten |= ModemInt;
-
-	BIT_CLR (port, UART_R_CON, UARTEN);	/* Disable UART */
-	UR (port, UART_R_INTEN) = 0;		/* Disable interrupts */
-	UR (port, UART_R_BRCON) = quot - 1;	/* Set baud rate divisor */
-	UR (port, UART_R_FCON)  = fcon;		/* Set FIFO and frame ctrl */
-	UR (port, UART_R_INTEN) = inten;	/* Enable interrupts */
-	UR (port, UART_R_CON)   = con;		/* Restore UART mode */
-
-	spin_unlock_irqrestore(&port->lock, flags);
-}
-
-static const char* lh7a40xuart_type (struct uart_port* port)
-{
-	return port->type == PORT_LH7A40X ? "LH7A40X" : NULL;
-}
-
-static void lh7a40xuart_release_port (struct uart_port* port)
-{
-	release_mem_region (port->mapbase, UART_REG_SIZE);
-}
-
-static int lh7a40xuart_request_port (struct uart_port* port)
-{
-	return request_mem_region (port->mapbase, UART_REG_SIZE,
-				   "serial_lh7a40x") != NULL
-		? 0 : -EBUSY;
-}
-
-static void lh7a40xuart_config_port (struct uart_port* port, int flags)
-{
-	if (flags & UART_CONFIG_TYPE) {
-		port->type = PORT_LH7A40X;
-		lh7a40xuart_request_port (port);
-	}
-}
-
-static int lh7a40xuart_verify_port (struct uart_port* port,
-				    struct serial_struct* ser)
-{
-	int ret = 0;
-
-	if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
-		ret = -EINVAL;
-	if (ser->irq < 0 || ser->irq >= nr_irqs)
-		ret = -EINVAL;
-	if (ser->baud_base < 9600) /* *** FIXME: is this true? */
-		ret = -EINVAL;
-	return ret;
-}
-
-static struct uart_ops lh7a40x_uart_ops = {
-	.tx_empty	= lh7a40xuart_tx_empty,
-	.set_mctrl	= lh7a40xuart_set_mctrl,
-	.get_mctrl	= lh7a40xuart_get_mctrl,
-	.stop_tx	= lh7a40xuart_stop_tx,
-	.start_tx	= lh7a40xuart_start_tx,
-	.stop_rx	= lh7a40xuart_stop_rx,
-	.enable_ms	= lh7a40xuart_enable_ms,
-	.break_ctl	= lh7a40xuart_break_ctl,
-	.startup	= lh7a40xuart_startup,
-	.shutdown	= lh7a40xuart_shutdown,
-	.set_termios	= lh7a40xuart_set_termios,
-	.type		= lh7a40xuart_type,
-	.release_port	= lh7a40xuart_release_port,
-	.request_port	= lh7a40xuart_request_port,
-	.config_port	= lh7a40xuart_config_port,
-	.verify_port	= lh7a40xuart_verify_port,
-};
-
-static struct uart_port_lh7a40x lh7a40x_ports[DEV_NR] = {
-	{
-		.port = {
-			.membase	= (void*) io_p2v (UART1_PHYS),
-			.mapbase	= UART1_PHYS,
-			.iotype		= UPIO_MEM,
-			.irq		= IRQ_UART1INTR,
-			.uartclk	= 14745600/2,
-			.fifosize	= 16,
-			.ops		= &lh7a40x_uart_ops,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 0,
-		},
-	},
-	{
-		.port = {
-			.membase	= (void*) io_p2v (UART2_PHYS),
-			.mapbase	= UART2_PHYS,
-			.iotype		= UPIO_MEM,
-			.irq		= IRQ_UART2INTR,
-			.uartclk	= 14745600/2,
-			.fifosize	= 16,
-			.ops		= &lh7a40x_uart_ops,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 1,
-		},
-	},
-	{
-		.port = {
-			.membase	= (void*) io_p2v (UART3_PHYS),
-			.mapbase	= UART3_PHYS,
-			.iotype		= UPIO_MEM,
-			.irq		= IRQ_UART3INTR,
-			.uartclk	= 14745600/2,
-			.fifosize	= 16,
-			.ops		= &lh7a40x_uart_ops,
-			.flags		= UPF_BOOT_AUTOCONF,
-			.line		= 2,
-		},
-	},
-};
-
-#ifndef CONFIG_SERIAL_LH7A40X_CONSOLE
-# define LH7A40X_CONSOLE NULL
-#else
-# define LH7A40X_CONSOLE &lh7a40x_console
-
-static void lh7a40xuart_console_putchar(struct uart_port *port, int ch)
-{
-	while (UR(port, UART_R_STATUS) & nTxRdy)
-		;
-	UR(port, UART_R_DATA) = ch;
-}
-
-static void lh7a40xuart_console_write (struct console* co,
-				       const char* s,
-				       unsigned int count)
-{
-	struct uart_port* port = &lh7a40x_ports[co->index].port;
-	unsigned int con = UR (port, UART_R_CON);
-	unsigned int inten = UR (port, UART_R_INTEN);
-
-
-	UR (port, UART_R_INTEN) = 0;		/* Disable all interrupts */
-	BIT_SET (port, UART_R_CON, UARTEN | SIRDIS); /* Enable UART */
-
-	uart_console_write(port, s, count, lh7a40xuart_console_putchar);
-
-				/* Wait until all characters are sent */
-	while (UR (port, UART_R_STATUS) & TxBusy)
-		;
-
-				/* Restore control and interrupt mask */
-	UR (port, UART_R_CON) = con;
-	UR (port, UART_R_INTEN) = inten;
-}
-
-static void __init lh7a40xuart_console_get_options (struct uart_port* port,
-						    int* baud,
-						    int* parity,
-						    int* bits)
-{
-	if (UR (port, UART_R_CON) & UARTEN) {
-		unsigned int fcon = UR (port, UART_R_FCON);
-		unsigned int quot = UR (port, UART_R_BRCON) + 1;
-
-		switch (fcon & (PEN | EPS)) {
-		default:        *parity = 'n'; break;
-		case PEN:       *parity = 'o'; break;
-		case PEN | EPS: *parity = 'e'; break;
-		}
-
-		switch (fcon & WLEN) {
-		default:
-		case WLEN_8: *bits = 8; break;
-		case WLEN_7: *bits = 7; break;
-		case WLEN_6: *bits = 6; break;
-		case WLEN_5: *bits = 5; break;
-		}
-
-		*baud = port->uartclk/(16*quot);
-	}
-}
-
-static int __init lh7a40xuart_console_setup (struct console* co, char* options)
-{
-	struct uart_port* port;
-	int baud = 38400;
-	int bits = 8;
-	int parity = 'n';
-	int flow = 'n';
-
-	if (co->index >= DEV_NR) /* Bounds check on device number */
-		co->index = 0;
-	port = &lh7a40x_ports[co->index].port;
-
-	if (options)
-		uart_parse_options (options, &baud, &parity, &bits, &flow);
-	else
-		lh7a40xuart_console_get_options (port, &baud, &parity, &bits);
-
-	return uart_set_options (port, co, baud, parity, bits, flow);
-}
-
-static struct uart_driver lh7a40x_reg;
-static struct console lh7a40x_console = {
-	.name		= "ttyAM",
-	.write		= lh7a40xuart_console_write,
-	.device		= uart_console_device,
-	.setup		= lh7a40xuart_console_setup,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-	.data		= &lh7a40x_reg,
-};
-
-static int __init lh7a40xuart_console_init(void)
-{
-	register_console (&lh7a40x_console);
-	return 0;
-}
-
-console_initcall (lh7a40xuart_console_init);
-
-#endif
-
-static struct uart_driver lh7a40x_reg = {
-	.owner			= THIS_MODULE,
-	.driver_name		= "ttyAM",
-	.dev_name		= "ttyAM",
-	.major			= DEV_MAJOR,
-	.minor			= DEV_MINOR,
-	.nr			= DEV_NR,
-	.cons			= LH7A40X_CONSOLE,
-};
-
-static int __init lh7a40xuart_init(void)
-{
-	int ret;
-
-	printk (KERN_INFO "serial: LH7A40X serial driver\n");
-
-	ret = uart_register_driver (&lh7a40x_reg);
-
-	if (ret == 0) {
-		int i;
-
-		for (i = 0; i < DEV_NR; i++) {
-			/* UART3, when used, requires GPIO pin reallocation */
-			if (lh7a40x_ports[i].port.mapbase == UART3_PHYS)
-				GPIO_PINMUX |= 1<<3;
-			uart_add_one_port (&lh7a40x_reg,
-					   &lh7a40x_ports[i].port);
-		}
-	}
-	return ret;
-}
-
-static void __exit lh7a40xuart_exit(void)
-{
-	int i;
-
-	for (i = 0; i < DEV_NR; i++)
-		uart_remove_one_port (&lh7a40x_reg, &lh7a40x_ports[i].port);
-
-	uart_unregister_driver (&lh7a40x_reg);
-}
-
-module_init (lh7a40xuart_init);
-module_exit (lh7a40xuart_exit);
-
-MODULE_AUTHOR ("Marc Singer");
-MODULE_DESCRIPTION ("Sharp LH7A40X serial port driver");
-MODULE_LICENSE ("GPL");
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index 92c91c8..eb7958c 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -47,7 +47,6 @@
 #include <linux/clk.h>
 #include <linux/ctype.h>
 #include <linux/err.h>
-#include <linux/list.h>
 #include <linux/dmaengine.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -65,11 +64,8 @@
 struct sci_port {
 	struct uart_port	port;
 
-	/* Port type */
-	unsigned int		type;
-
-	/* Port IRQs: ERI, RXI, TXI, BRI (optional) */
-	unsigned int		irqs[SCIx_NR_IRQS];
+	/* Platform configuration */
+	struct plat_sci_port	*cfg;
 
 	/* Port enable callback */
 	void			(*enable)(struct uart_port *port);
@@ -81,26 +77,15 @@ struct sci_port {
 	struct timer_list	break_timer;
 	int			break_flag;
 
-	/* SCSCR initialization */
-	unsigned int		scscr;
-
-	/* SCBRR calculation algo */
-	unsigned int		scbrr_algo_id;
-
 	/* Interface clock */
 	struct clk		*iclk;
 	/* Function clock */
 	struct clk		*fclk;
 
-	struct list_head	node;
-
 	struct dma_chan			*chan_tx;
 	struct dma_chan			*chan_rx;
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
-	struct device			*dma_dev;
-	unsigned int			slave_tx;
-	unsigned int			slave_rx;
 	struct dma_async_tx_descriptor	*desc_tx;
 	struct dma_async_tx_descriptor	*desc_rx[2];
 	dma_cookie_t			cookie_tx;
@@ -117,16 +102,14 @@ struct sci_port {
 	struct timer_list		rx_timer;
 	unsigned int			rx_timeout;
 #endif
-};
 
-struct sh_sci_priv {
-	spinlock_t lock;
-	struct list_head ports;
-	struct notifier_block clk_nb;
+	struct notifier_block		freq_transition;
 };
 
 /* Function prototypes */
+static void sci_start_tx(struct uart_port *port);
 static void sci_stop_tx(struct uart_port *port);
+static void sci_start_rx(struct uart_port *port);
 
 #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
 
@@ -142,12 +125,6 @@ to_sci_port(struct uart_port *uart)
 #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
 
 #ifdef CONFIG_CONSOLE_POLL
-static inline void handle_error(struct uart_port *port)
-{
-	/* Clear error flags */
-	sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
-}
-
 static int sci_poll_get_char(struct uart_port *port)
 {
 	unsigned short status;
@@ -156,7 +133,7 @@ static int sci_poll_get_char(struct uart_port *port)
 	do {
 		status = sci_in(port, SCxSR);
 		if (status & SCxSR_ERRORS(port)) {
-			handle_error(port);
+			sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
 			continue;
 		}
 		break;
@@ -475,7 +452,7 @@ static void sci_transmit_chars(struct uart_port *port)
 /* On SH3, SCIF may read end-of-break as a space->mark char */
 #define STEPFN(c)  ({int __c = (c); (((__c-1)|(__c)) == -1); })
 
-static inline void sci_receive_chars(struct uart_port *port)
+static void sci_receive_chars(struct uart_port *port)
 {
 	struct sci_port *sci_port = to_sci_port(port);
 	struct tty_struct *tty = port->state->port.tty;
@@ -566,18 +543,20 @@ static inline void sci_receive_chars(struct uart_port *port)
 }
 
 #define SCI_BREAK_JIFFIES (HZ/20)
-/* The sci generates interrupts during the break,
+
+/*
+ * The sci generates interrupts during the break,
  * 1 per millisecond or so during the break period, for 9600 baud.
  * So dont bother disabling interrupts.
  * But dont want more than 1 break event.
  * Use a kernel timer to periodically poll the rx line until
  * the break is finished.
  */
-static void sci_schedule_break_timer(struct sci_port *port)
+static inline void sci_schedule_break_timer(struct sci_port *port)
 {
-	port->break_timer.expires = jiffies + SCI_BREAK_JIFFIES;
-	add_timer(&port->break_timer);
+	mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES);
 }
+
 /* Ensure that two consecutive samples find the break over. */
 static void sci_break_timer(unsigned long data)
 {
@@ -594,7 +573,7 @@ static void sci_break_timer(unsigned long data)
 		port->break_flag = 0;
 }
 
-static inline int sci_handle_errors(struct uart_port *port)
+static int sci_handle_errors(struct uart_port *port)
 {
 	int copied = 0;
 	unsigned short status = sci_in(port, SCxSR);
@@ -650,7 +629,7 @@ static inline int sci_handle_errors(struct uart_port *port)
 	return copied;
 }
 
-static inline int sci_handle_fifo_overrun(struct uart_port *port)
+static int sci_handle_fifo_overrun(struct uart_port *port)
 {
 	struct tty_struct *tty = port->state->port.tty;
 	int copied = 0;
@@ -671,7 +650,7 @@ static inline int sci_handle_fifo_overrun(struct uart_port *port)
 	return copied;
 }
 
-static inline int sci_handle_breaks(struct uart_port *port)
+static int sci_handle_breaks(struct uart_port *port)
 {
 	int copied = 0;
 	unsigned short status = sci_in(port, SCxSR);
@@ -794,7 +773,7 @@ static inline unsigned long port_rx_irq_mask(struct uart_port *port)
 	 * it's unset, it's logically inferred that there's no point in
 	 * testing for it.
 	 */
-	return SCSCR_RIE | (to_sci_port(port)->scscr & SCSCR_REIE);
+	return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
 }
 
 static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
@@ -839,17 +818,18 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 static int sci_notifier(struct notifier_block *self,
 			unsigned long phase, void *p)
 {
-	struct sh_sci_priv *priv = container_of(self,
-						struct sh_sci_priv, clk_nb);
 	struct sci_port *sci_port;
 	unsigned long flags;
 
+	sci_port = container_of(self, struct sci_port, freq_transition);
+
 	if ((phase == CPUFREQ_POSTCHANGE) ||
 	    (phase == CPUFREQ_RESUMECHANGE)) {
-		spin_lock_irqsave(&priv->lock, flags);
-		list_for_each_entry(sci_port, &priv->ports, node)
-			sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
-		spin_unlock_irqrestore(&priv->lock, flags);
+		struct uart_port *port = &sci_port->port;
+
+		spin_lock_irqsave(&port->lock, flags);
+		port->uartclk = clk_get_rate(sci_port->iclk);
+		spin_unlock_irqrestore(&port->lock, flags);
 	}
 
 	return NOTIFY_OK;
@@ -882,21 +862,21 @@ static int sci_request_irq(struct sci_port *port)
 	const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
 			       "SCI Transmit Data Empty", "SCI Break" };
 
-	if (port->irqs[0] == port->irqs[1]) {
-		if (unlikely(!port->irqs[0]))
+	if (port->cfg->irqs[0] == port->cfg->irqs[1]) {
+		if (unlikely(!port->cfg->irqs[0]))
 			return -ENODEV;
 
-		if (request_irq(port->irqs[0], sci_mpxed_interrupt,
+		if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt,
 				IRQF_DISABLED, "sci", port)) {
 			dev_err(port->port.dev, "Can't allocate IRQ\n");
 			return -ENODEV;
 		}
 	} else {
 		for (i = 0; i < ARRAY_SIZE(handlers); i++) {
-			if (unlikely(!port->irqs[i]))
+			if (unlikely(!port->cfg->irqs[i]))
 				continue;
 
-			if (request_irq(port->irqs[i], handlers[i],
+			if (request_irq(port->cfg->irqs[i], handlers[i],
 					IRQF_DISABLED, desc[i], port)) {
 				dev_err(port->port.dev, "Can't allocate IRQ\n");
 				return -ENODEV;
@@ -911,14 +891,14 @@ static void sci_free_irq(struct sci_port *port)
 {
 	int i;
 
-	if (port->irqs[0] == port->irqs[1])
-		free_irq(port->irqs[0], port);
+	if (port->cfg->irqs[0] == port->cfg->irqs[1])
+		free_irq(port->cfg->irqs[0], port);
 	else {
-		for (i = 0; i < ARRAY_SIZE(port->irqs); i++) {
-			if (!port->irqs[i])
+		for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) {
+			if (!port->cfg->irqs[i])
 				continue;
 
-			free_irq(port->irqs[i], port);
+			free_irq(port->cfg->irqs[i], port);
 		}
 	}
 }
@@ -1037,9 +1017,6 @@ static void sci_dma_rx_complete(void *arg)
 	schedule_work(&s->work_rx);
 }
 
-static void sci_start_rx(struct uart_port *port);
-static void sci_start_tx(struct uart_port *port);
-
 static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
 {
 	struct dma_chan *chan = s->chan_rx;
@@ -1325,7 +1302,7 @@ static void rx_timer_fn(unsigned long arg)
 
 	if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
 		scr &= ~0x4000;
-		enable_irq(s->irqs[1]);
+		enable_irq(s->cfg->irqs[1]);
 	}
 	sci_out(port, SCSCR, scr | SCSCR_RIE);
 	dev_dbg(port->dev, "DMA Rx timed out\n");
@@ -1341,9 +1318,9 @@ static void sci_request_dma(struct uart_port *port)
 	int nent;
 
 	dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
-		port->line, s->dma_dev);
+		port->line, s->cfg->dma_dev);
 
-	if (!s->dma_dev)
+	if (!s->cfg->dma_dev)
 		return;
 
 	dma_cap_zero(mask);
@@ -1352,8 +1329,8 @@ static void sci_request_dma(struct uart_port *port)
 	param = &s->param_tx;
 
 	/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
-	param->slave_id = s->slave_tx;
-	param->dma_dev = s->dma_dev;
+	param->slave_id = s->cfg->dma_slave_tx;
+	param->dma_dev = s->cfg->dma_dev;
 
 	s->cookie_tx = -EINVAL;
 	chan = dma_request_channel(mask, filter, param);
@@ -1381,8 +1358,8 @@ static void sci_request_dma(struct uart_port *port)
 	param = &s->param_rx;
 
 	/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
-	param->slave_id = s->slave_rx;
-	param->dma_dev = s->dma_dev;
+	param->slave_id = s->cfg->dma_slave_rx;
+	param->dma_dev = s->cfg->dma_dev;
 
 	chan = dma_request_channel(mask, filter, param);
 	dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
@@ -1427,7 +1404,7 @@ static void sci_free_dma(struct uart_port *port)
 {
 	struct sci_port *s = to_sci_port(port);
 
-	if (!s->dma_dev)
+	if (!s->cfg->dma_dev)
 		return;
 
 	if (s->chan_tx)
@@ -1435,21 +1412,32 @@ static void sci_free_dma(struct uart_port *port)
 	if (s->chan_rx)
 		sci_rx_dma_release(s, false);
 }
+#else
+static inline void sci_request_dma(struct uart_port *port)
+{
+}
+
+static inline void sci_free_dma(struct uart_port *port)
+{
+}
 #endif
 
 static int sci_startup(struct uart_port *port)
 {
 	struct sci_port *s = to_sci_port(port);
+	int ret;
 
 	dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
 	if (s->enable)
 		s->enable(port);
 
-	sci_request_irq(s);
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
+	ret = sci_request_irq(s);
+	if (unlikely(ret < 0))
+		return ret;
+
 	sci_request_dma(port);
-#endif
+
 	sci_start_tx(port);
 	sci_start_rx(port);
 
@@ -1464,9 +1452,8 @@ static void sci_shutdown(struct uart_port *port)
 
 	sci_stop_rx(port);
 	sci_stop_tx(port);
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
+
 	sci_free_dma(port);
-#endif
 	sci_free_irq(s);
 
 	if (s->disable)
@@ -1491,6 +1478,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
 
 	/* Warn, but use a safe default */
 	WARN_ON(1);
+
 	return ((freq + 16 * bps) / (32 * bps) - 1);
 }
 
@@ -1514,7 +1502,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
 	if (likely(baud && port->uartclk))
-		t = sci_scbrr_calc(s->scbrr_algo_id, baud, port->uartclk);
+		t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk);
+
+	if (s->enable)
+		s->enable(port);
 
 	do {
 		status = sci_in(port, SCxSR);
@@ -1526,6 +1517,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 		sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
 
 	smr_val = sci_in(port, SCSMR) & 3;
+
 	if ((termios->c_cflag & CSIZE) == CS7)
 		smr_val |= 0x40;
 	if (termios->c_cflag & PARENB)
@@ -1540,7 +1532,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	sci_out(port, SCSMR, smr_val);
 
 	dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
-		s->scscr);
+		s->cfg->scscr);
 
 	if (t > 0) {
 		if (t >= 256) {
@@ -1556,7 +1548,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 	sci_init_pins(port, termios->c_cflag);
 	sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
 
-	sci_out(port, SCSCR, s->scscr);
+	sci_out(port, SCSCR, s->cfg->scscr);
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
 	/*
@@ -1582,6 +1574,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	if ((termios->c_cflag & CREAD) != 0)
 		sci_start_rx(port);
+
+	if (s->disable)
+		s->disable(port);
 }
 
 static const char *sci_type(struct uart_port *port)
@@ -1602,31 +1597,33 @@ static const char *sci_type(struct uart_port *port)
 	return NULL;
 }
 
-static void sci_release_port(struct uart_port *port)
+static inline unsigned long sci_port_size(struct uart_port *port)
 {
-	/* Nothing here yet .. */
-}
-
-static int sci_request_port(struct uart_port *port)
-{
-	/* Nothing here yet .. */
-	return 0;
+	/*
+	 * Pick an arbitrary size that encapsulates all of the base
+	 * registers by default. This can be optimized later, or derived
+	 * from platform resource data at such a time that ports begin to
+	 * behave more erratically.
+	 */
+	return 64;
 }
 
-static void sci_config_port(struct uart_port *port, int flags)
+static int sci_remap_port(struct uart_port *port)
 {
-	struct sci_port *s = to_sci_port(port);
-
-	port->type = s->type;
+	unsigned long size = sci_port_size(port);
 
+	/*
+	 * Nothing to do if there's already an established membase.
+	 */
 	if (port->membase)
-		return;
+		return 0;
 
 	if (port->flags & UPF_IOREMAP) {
-		port->membase = ioremap_nocache(port->mapbase, 0x40);
-
-		if (IS_ERR(port->membase))
+		port->membase = ioremap_nocache(port->mapbase, size);
+		if (unlikely(!port->membase)) {
 			dev_err(port->dev, "can't remap port#%d\n", port->line);
+			return -ENXIO;
+		}
 	} else {
 		/*
 		 * For the simple (and majority of) cases where we don't
@@ -1635,13 +1632,54 @@ static void sci_config_port(struct uart_port *port, int flags)
 		 */
 		port->membase = (void __iomem *)port->mapbase;
 	}
+
+	return 0;
+}
+
+static void sci_release_port(struct uart_port *port)
+{
+	if (port->flags & UPF_IOREMAP) {
+		iounmap(port->membase);
+		port->membase = NULL;
+	}
+
+	release_mem_region(port->mapbase, sci_port_size(port));
+}
+
+static int sci_request_port(struct uart_port *port)
+{
+	unsigned long size = sci_port_size(port);
+	struct resource *res;
+	int ret;
+
+	res = request_mem_region(port->mapbase, size, dev_name(port->dev));
+	if (unlikely(res == NULL))
+		return -EBUSY;
+
+	ret = sci_remap_port(port);
+	if (unlikely(ret != 0)) {
+		release_resource(res);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void sci_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE) {
+		struct sci_port *sport = to_sci_port(port);
+
+		port->type = sport->cfg->type;
+		sci_request_port(port);
+	}
 }
 
 static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
 	struct sci_port *s = to_sci_port(port);
 
-	if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
+	if (ser->irq != s->cfg->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
 		return -EINVAL;
 	if (ser->baud_base < 2400)
 		/* No paper tape reader for Mitch.. */
@@ -1726,36 +1764,29 @@ static int __devinit sci_init_single(struct platform_device *dev,
 	sci_port->break_timer.function = sci_break_timer;
 	init_timer(&sci_port->break_timer);
 
-	port->mapbase	= p->mapbase;
-	port->membase	= p->membase;
+	sci_port->cfg		= p;
 
-	port->irq		= p->irqs[SCIx_TXI_IRQ];
+	port->mapbase		= p->mapbase;
+	port->type		= p->type;
 	port->flags		= p->flags;
-	sci_port->type		= port->type = p->type;
-	sci_port->scscr		= p->scscr;
-	sci_port->scbrr_algo_id	= p->scbrr_algo_id;
 
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-	sci_port->dma_dev	= p->dma_dev;
-	sci_port->slave_tx	= p->dma_slave_tx;
-	sci_port->slave_rx	= p->dma_slave_rx;
+	/*
+	 * The UART port needs an IRQ value, so we peg this to the TX IRQ
+	 * for the multi-IRQ ports, which is where we are primarily
+	 * concerned with the shutdown path synchronization.
+	 *
+	 * For the muxed case there's nothing more to do.
+	 */
+	port->irq		= p->irqs[SCIx_TXI_IRQ];
 
-	dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__,
-		p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
-#endif
+	if (p->dma_dev)
+		dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
+			p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
 
-	memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
 	return 0;
 }
 
 #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-static struct tty_driver *serial_console_device(struct console *co, int *index)
-{
-	struct uart_driver *p = &sci_uart_driver;
-	*index = co->index;
-	return p->tty_driver;
-}
-
 static void serial_console_putchar(struct uart_port *port, int ch)
 {
 	sci_poll_put_char(port, ch);
@@ -1768,8 +1799,8 @@ static void serial_console_putchar(struct uart_port *port, int ch)
 static void serial_console_write(struct console *co, const char *s,
 				 unsigned count)
 {
-	struct uart_port *port = co->data;
-	struct sci_port *sci_port = to_sci_port(port);
+	struct sci_port *sci_port = &sci_ports[co->index];
+	struct uart_port *port = &sci_port->port;
 	unsigned short bits;
 
 	if (sci_port->enable)
@@ -1797,32 +1828,17 @@ static int __devinit serial_console_setup(struct console *co, char *options)
 	int ret;
 
 	/*
-	 * Check whether an invalid uart number has been specified, and
-	 * if so, search for the first available port that does have
-	 * console support.
-	 */
-	if (co->index >= SCI_NPORTS)
-		co->index = 0;
-
-	if (co->data) {
-		port = co->data;
-		sci_port = to_sci_port(port);
-	} else {
-		sci_port = &sci_ports[co->index];
-		port = &sci_port->port;
-		co->data = port;
-	}
-
-	/*
-	 * Also need to check port->type, we don't actually have any
-	 * UPIO_PORT ports, but uart_report_port() handily misreports
-	 * it anyways if we don't have a port available by the time this is
-	 * called.
+	 * Refuse to handle any bogus ports.
 	 */
-	if (!port->type)
+	if (co->index < 0 || co->index >= SCI_NPORTS)
 		return -ENODEV;
 
-	sci_config_port(port, 0);
+	sci_port = &sci_ports[co->index];
+	port = &sci_port->port;
+
+	ret = sci_remap_port(port);
+	if (unlikely(ret != 0))
+		return ret;
 
 	if (sci_port->enable)
 		sci_port->enable(port);
@@ -1842,11 +1858,12 @@ static int __devinit serial_console_setup(struct console *co, char *options)
 
 static struct console serial_console = {
 	.name		= "ttySC",
-	.device		= serial_console_device,
+	.device		= uart_console_device,
 	.write		= serial_console_write,
 	.setup		= serial_console_setup,
 	.flags		= CON_PRINTBUFFER,
 	.index		= -1,
+	.data		= &sci_uart_driver,
 };
 
 static int __init sci_console_init(void)
@@ -1856,14 +1873,39 @@ static int __init sci_console_init(void)
 }
 console_initcall(sci_console_init);
 
-static struct sci_port early_serial_port;
 static struct console early_serial_console = {
 	.name           = "early_ttySC",
 	.write          = serial_console_write,
 	.flags          = CON_PRINTBUFFER,
+	.index		= -1,
 };
+
 static char early_serial_buf[32];
 
+static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+{
+	struct plat_sci_port *cfg = pdev->dev.platform_data;
+
+	if (early_serial_console.data)
+		return -EEXIST;
+
+	early_serial_console.index = pdev->id;
+
+	sci_init_single(NULL, &sci_ports[pdev->id], pdev->id, cfg);
+
+	serial_console_setup(&early_serial_console, early_serial_buf);
+
+	if (!strstr(early_serial_buf, "keep"))
+		early_serial_console.flags |= CON_BOOT;
+
+	register_console(&early_serial_console);
+	return 0;
+}
+#else
+static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
+{
+	return -EINVAL;
+}
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
 #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
@@ -1885,24 +1927,18 @@ static struct uart_driver sci_uart_driver = {
 	.cons		= SCI_CONSOLE,
 };
 
-
 static int sci_remove(struct platform_device *dev)
 {
-	struct sh_sci_priv *priv = platform_get_drvdata(dev);
-	struct sci_port *p;
-	unsigned long flags;
+	struct sci_port *port = platform_get_drvdata(dev);
 
-	cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
+	cpufreq_unregister_notifier(&port->freq_transition,
+				    CPUFREQ_TRANSITION_NOTIFIER);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry(p, &priv->ports, node) {
-		uart_remove_one_port(&sci_uart_driver, &p->port);
-		clk_put(p->iclk);
-		clk_put(p->fclk);
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
+	uart_remove_one_port(&sci_uart_driver, &port->port);
+
+	clk_put(port->iclk);
+	clk_put(port->fclk);
 
-	kfree(priv);
 	return 0;
 }
 
@@ -1911,8 +1947,6 @@ static int __devinit sci_probe_single(struct platform_device *dev,
 				      struct plat_sci_port *p,
 				      struct sci_port *sciport)
 {
-	struct sh_sci_priv *priv = platform_get_drvdata(dev);
-	unsigned long flags;
 	int ret;
 
 	/* Sanity check */
@@ -1929,68 +1963,35 @@ static int __devinit sci_probe_single(struct platform_device *dev,
 	if (ret)
 		return ret;
 
-	ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
-	if (ret)
-		return ret;
-
-	INIT_LIST_HEAD(&sciport->node);
-
-	spin_lock_irqsave(&priv->lock, flags);
-	list_add(&sciport->node, &priv->ports);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
+	return uart_add_one_port(&sci_uart_driver, &sciport->port);
 }
 
-/*
- * Register a set of serial devices attached to a platform device.  The
- * list is terminated with a zero flags entry, which means we expect
- * all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need
- * remapping (such as sh64) should also set UPF_IOREMAP.
- */
 static int __devinit sci_probe(struct platform_device *dev)
 {
 	struct plat_sci_port *p = dev->dev.platform_data;
-	struct sh_sci_priv *priv;
-	int i, ret = -EINVAL;
+	struct sci_port *sp = &sci_ports[dev->id];
+	int ret;
 
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-	if (is_early_platform_device(dev)) {
-		if (dev->id == -1)
-			return -ENOTSUPP;
-		early_serial_console.index = dev->id;
-		early_serial_console.data = &early_serial_port.port;
-		sci_init_single(NULL, &early_serial_port, dev->id, p);
-		serial_console_setup(&early_serial_console, early_serial_buf);
-		if (!strstr(early_serial_buf, "keep"))
-			early_serial_console.flags |= CON_BOOT;
-		register_console(&early_serial_console);
-		return 0;
-	}
-#endif
+	/*
+	 * If we've come here via earlyprintk initialization, head off to
+	 * the special early probe. We don't have sufficient device state
+	 * to make it beyond this yet.
+	 */
+	if (is_early_platform_device(dev))
+		return sci_probe_earlyprintk(dev);
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
+	platform_set_drvdata(dev, sp);
 
-	INIT_LIST_HEAD(&priv->ports);
-	spin_lock_init(&priv->lock);
-	platform_set_drvdata(dev, priv);
+	ret = sci_probe_single(dev, dev->id, p, sp);
+	if (ret)
+		goto err_unreg;
 
-	priv->clk_nb.notifier_call = sci_notifier;
-	cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
+	sp->freq_transition.notifier_call = sci_notifier;
 
-	if (dev->id != -1) {
-		ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
-		if (ret)
-			goto err_unreg;
-	} else {
-		for (i = 0; p && p->flags != 0; p++, i++) {
-			ret = sci_probe_single(dev, i, p, &sci_ports[i]);
-			if (ret)
-				goto err_unreg;
-		}
-	}
+	ret = cpufreq_register_notifier(&sp->freq_transition,
+					CPUFREQ_TRANSITION_NOTIFIER);
+	if (unlikely(ret < 0))
+		goto err_unreg;
 
 #ifdef CONFIG_SH_STANDARD_BIOS
 	sh_bios_gdb_detach();
@@ -2005,28 +2006,20 @@ err_unreg:
 
 static int sci_suspend(struct device *dev)
 {
-	struct sh_sci_priv *priv = dev_get_drvdata(dev);
-	struct sci_port *p;
-	unsigned long flags;
+	struct sci_port *sport = dev_get_drvdata(dev);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry(p, &priv->ports, node)
-		uart_suspend_port(&sci_uart_driver, &p->port);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	if (sport)
+		uart_suspend_port(&sci_uart_driver, &sport->port);
 
 	return 0;
 }
 
 static int sci_resume(struct device *dev)
 {
-	struct sh_sci_priv *priv = dev_get_drvdata(dev);
-	struct sci_port *p;
-	unsigned long flags;
+	struct sci_port *sport = dev_get_drvdata(dev);
 
-	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry(p, &priv->ports, node)
-		uart_resume_port(&sci_uart_driver, &p->port);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	if (sport)
+		uart_resume_port(&sci_uart_driver, &sport->port);
 
 	return 0;
 }
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index b223d6c..5fefed5 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -54,9 +54,6 @@
 # define PBCR 0xa4050102
 #elif defined(CONFIG_CPU_SUBTYPE_SH7343)
 # define SCSPTR0 0xffe00010	/* 16 bit SCIF */
-# define SCSPTR1 0xffe10010	/* 16 bit SCIF */
-# define SCSPTR2 0xffe20010	/* 16 bit SCIF */
-# define SCSPTR3 0xffe30010	/* 16 bit SCIF */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7722)
 # define PADR			0xA4050120
 # define PSDR			0xA405013e
@@ -69,77 +66,42 @@
 # define SCIF_ORER		0x0001  /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7723)
 # define SCSPTR0                0xa4050160
-# define SCSPTR1                0xa405013e
-# define SCSPTR2                0xa4050160
-# define SCSPTR3                0xa405013e
-# define SCSPTR4                0xa4050128
-# define SCSPTR5                0xa4050128
 # define SCIF_ORER              0x0001  /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7724)
 # define SCIF_ORER              0x0001  /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
-#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-# define SCIF_PTR2_OFFS    0x0000020
-# define SCSPTR2           ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
 #elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
 # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
 #elif defined(CONFIG_H8S2678)
 # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
 # define SCSPTR0 0xfe4b0020
-# define SCSPTR1 0xfe4b0020
-# define SCSPTR2 0xfe4b0020
 # define SCIF_ORER 0x0001
-# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 # define SCSPTR0 0xffe00024 /* 16 bit SCIF */
-# define SCSPTR1 0xffe08024 /* 16 bit SCIF */
-# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */
 # define SCIF_ORER 0x0001  /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7770)
 # define SCSPTR0 0xff923020 /* 16 bit SCIF */
-# define SCSPTR1 0xff924020 /* 16 bit SCIF */
-# define SCSPTR2 0xff925020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001  /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define SCSPTR0	0xffe00024	/* 16 bit SCIF */
-# define SCSPTR1	0xffe10024	/* 16 bit SCIF */
 # define SCIF_ORER	0x0001		/* Overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
       defined(CONFIG_CPU_SUBTYPE_SH7786)
 # define SCSPTR0	0xffea0024	/* 16 bit SCIF */
-# define SCSPTR1	0xffeb0024	/* 16 bit SCIF */
-# define SCSPTR2	0xffec0024	/* 16 bit SCIF */
-# define SCSPTR3	0xffed0024	/* 16 bit SCIF */
-# define SCSPTR4	0xffee0024	/* 16 bit SCIF */
-# define SCSPTR5	0xffef0024	/* 16 bit SCIF */
 # define SCIF_ORER	0x0001		/* Overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
       defined(CONFIG_CPU_SUBTYPE_SH7203) || \
       defined(CONFIG_CPU_SUBTYPE_SH7206) || \
       defined(CONFIG_CPU_SUBTYPE_SH7263)
 # define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
-# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
-# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */
-# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */
-# if defined(CONFIG_CPU_SUBTYPE_SH7201)
-#  define SCSPTR4 0xfffeA020 /* 16 bit SCIF */
-#  define SCSPTR5 0xfffeA820 /* 16 bit SCIF */
-#  define SCSPTR6 0xfffeB020 /* 16 bit SCIF */
-#  define SCSPTR7 0xfffeB820 /* 16 bit SCIF */
-# endif
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
 # define SCSPTR0 0xf8400020 /* 16 bit SCIF */
-# define SCSPTR1 0xf8410020 /* 16 bit SCIF */
-# define SCSPTR2 0xf8420020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001  /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SHX3)
 # define SCSPTR0 0xffc30020		/* 16 bit SCIF */
-# define SCSPTR1 0xffc40020		/* 16 bit SCIF */
-# define SCSPTR2 0xffc50020		/* 16 bit SCIF */
-# define SCSPTR3 0xffc60020		/* 16 bit SCIF */
 # define SCIF_ORER 0x0001		/* Overrun error bit */
 #else
 # error CPU subtype not defined
@@ -411,7 +373,6 @@ SCIF_FNS(SCSPTR,			0,  0, 0x24, 16)
 SCIF_FNS(SCLSR,				0,  0, 0x28, 16)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 SCIF_FNS(SCFDR,				0,  0, 0x1C, 16)
-SCIF_FNS(SCSPTR2,			0,  0, 0x20, 16)
 SCIF_FNS(SCTFDR,		     0x0e, 16, 0x1C, 16)
 SCIF_FNS(SCRFDR,		     0x0e, 16, 0x20, 16)
 SCIF_FNS(SCSPTR,			0,  0, 0x24, 16)
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index c901486..c0b7246 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -519,7 +519,7 @@ static struct console sunhv_console = {
 	.data	=	&sunhv_reg,
 };
 
-static int __devinit hv_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit hv_probe(struct platform_device *op)
 {
 	struct uart_port *port;
 	unsigned long minor;
@@ -629,7 +629,7 @@ static const struct of_device_id hv_match[] = {
 };
 MODULE_DEVICE_TABLE(of, hv_match);
 
-static struct of_platform_driver hv_driver = {
+static struct platform_driver hv_driver = {
 	.driver = {
 		.name = "hv",
 		.owner = THIS_MODULE,
@@ -644,12 +644,12 @@ static int __init sunhv_init(void)
 	if (tlb_type != hypervisor)
 		return -ENODEV;
 
-	return of_register_platform_driver(&hv_driver);
+	return platform_driver_register(&hv_driver);
 }
 
 static void __exit sunhv_exit(void)
 {
-	of_unregister_platform_driver(&hv_driver);
+	platform_driver_unregister(&hv_driver);
 }
 
 module_init(sunhv_init);
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index 5b246b1..b5fa2a5 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -1006,7 +1006,7 @@ static int __devinit sunsab_init_one(struct uart_sunsab_port *up,
 	return 0;
 }
 
-static int __devinit sab_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit sab_probe(struct platform_device *op)
 {
 	static int inst;
 	struct uart_sunsab_port *up;
@@ -1092,7 +1092,7 @@ static const struct of_device_id sab_match[] = {
 };
 MODULE_DEVICE_TABLE(of, sab_match);
 
-static struct of_platform_driver sab_driver = {
+static struct platform_driver sab_driver = {
 	.driver = {
 		.name = "sab",
 		.owner = THIS_MODULE,
@@ -1130,12 +1130,12 @@ static int __init sunsab_init(void)
 		}
 	}
 
-	return of_register_platform_driver(&sab_driver);
+	return platform_driver_register(&sab_driver);
 }
 
 static void __exit sunsab_exit(void)
 {
-	of_unregister_platform_driver(&sab_driver);
+	platform_driver_unregister(&sab_driver);
 	if (sunsab_reg.nr) {
 		sunserial_unregister_minors(&sunsab_reg, sunsab_reg.nr);
 	}
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 551ebfe..92aa545 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1406,7 +1406,7 @@ static enum su_type __devinit su_get_type(struct device_node *dp)
 	return SU_PORT_PORT;
 }
 
-static int __devinit su_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit su_probe(struct platform_device *op)
 {
 	static int inst;
 	struct device_node *dp = op->dev.of_node;
@@ -1543,7 +1543,7 @@ static const struct of_device_id su_match[] = {
 };
 MODULE_DEVICE_TABLE(of, su_match);
 
-static struct of_platform_driver su_driver = {
+static struct platform_driver su_driver = {
 	.driver = {
 		.name = "su",
 		.owner = THIS_MODULE,
@@ -1586,7 +1586,7 @@ static int __init sunsu_init(void)
 			return err;
 	}
 
-	err = of_register_platform_driver(&su_driver);
+	err = platform_driver_register(&su_driver);
 	if (err && num_uart)
 		sunserial_unregister_minors(&sunsu_reg, num_uart);
 
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index c1967ac..99ff9ab 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1399,7 +1399,7 @@ static void __devinit sunzilog_init_hw(struct uart_sunzilog_port *up)
 
 static int zilog_irq = -1;
 
-static int __devinit zs_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit zs_probe(struct platform_device *op)
 {
 	static int kbm_inst, uart_inst;
 	int inst;
@@ -1540,7 +1540,7 @@ static const struct of_device_id zs_match[] = {
 };
 MODULE_DEVICE_TABLE(of, zs_match);
 
-static struct of_platform_driver zs_driver = {
+static struct platform_driver zs_driver = {
 	.driver = {
 		.name = "zs",
 		.owner = THIS_MODULE,
@@ -1576,7 +1576,7 @@ static int __init sunzilog_init(void)
 			goto out_free_tables;
 	}
 
-	err = of_register_platform_driver(&zs_driver);
+	err = platform_driver_register(&zs_driver);
 	if (err)
 		goto out_unregister_uart;
 
@@ -1604,7 +1604,7 @@ out:
 	return err;
 
 out_unregister_driver:
-	of_unregister_platform_driver(&zs_driver);
+	platform_driver_unregister(&zs_driver);
 
 out_unregister_uart:
 	if (num_sunzilog) {
@@ -1619,7 +1619,7 @@ out_free_tables:
 
 static void __exit sunzilog_exit(void)
 {
-	of_unregister_platform_driver(&zs_driver);
+	platform_driver_unregister(&zs_driver);
 
 	if (zilog_irq != -1) {
 		struct uart_sunzilog_port *up = sunzilog_irq_chain;
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index d2fce86..8af1ed8 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -19,22 +19,11 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <asm/io.h>
-#if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE))
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 
-/* Match table for of_platform binding */
-static struct of_device_id ulite_of_match[] __devinitdata = {
-	{ .compatible = "xlnx,opb-uartlite-1.00.b", },
-	{ .compatible = "xlnx,xps-uartlite-1.00.a", },
-	{}
-};
-MODULE_DEVICE_TABLE(of, ulite_of_match);
-
-#endif
-
 #define ULITE_NAME		"ttyUL"
 #define ULITE_MAJOR		204
 #define ULITE_MINOR		187
@@ -571,9 +560,29 @@ static int __devexit ulite_release(struct device *dev)
  * Platform bus binding
  */
 
+#if defined(CONFIG_OF)
+/* Match table for of_platform binding */
+static struct of_device_id ulite_of_match[] __devinitdata = {
+	{ .compatible = "xlnx,opb-uartlite-1.00.b", },
+	{ .compatible = "xlnx,xps-uartlite-1.00.a", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, ulite_of_match);
+#else /* CONFIG_OF */
+#define ulite_of_match NULL
+#endif /* CONFIG_OF */
+
 static int __devinit ulite_probe(struct platform_device *pdev)
 {
 	struct resource *res, *res2;
+	int id = pdev->id;
+#ifdef CONFIG_OF
+	const __be32 *prop;
+
+	prop = of_get_property(pdev->dev.of_node, "port-number", NULL);
+	if (prop)
+		id = be32_to_cpup(prop);
+#endif
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -583,7 +592,7 @@ static int __devinit ulite_probe(struct platform_device *pdev)
 	if (!res2)
 		return -ENODEV;
 
-	return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start);
+	return ulite_assign(&pdev->dev, id, res->start, res2->start);
 }
 
 static int __devexit ulite_remove(struct platform_device *pdev)
@@ -595,72 +604,15 @@ static int __devexit ulite_remove(struct platform_device *pdev)
 MODULE_ALIAS("platform:uartlite");
 
 static struct platform_driver ulite_platform_driver = {
-	.probe	= ulite_probe,
-	.remove	= __devexit_p(ulite_remove),
-	.driver	= {
-		   .owner = THIS_MODULE,
-		   .name  = "uartlite",
-		   },
-};
-
-/* ---------------------------------------------------------------------
- * OF bus bindings
- */
-#if defined(CONFIG_OF) && (defined(CONFIG_PPC32) || defined(CONFIG_MICROBLAZE))
-static int __devinit
-ulite_of_probe(struct platform_device *op, const struct of_device_id *match)
-{
-	struct resource res;
-	const unsigned int *id;
-	int irq, rc;
-
-	dev_dbg(&op->dev, "%s(%p, %p)\n", __func__, op, match);
-
-	rc = of_address_to_resource(op->dev.of_node, 0, &res);
-	if (rc) {
-		dev_err(&op->dev, "invalid address\n");
-		return rc;
-	}
-
-	irq = irq_of_parse_and_map(op->dev.of_node, 0);
-
-	id = of_get_property(op->dev.of_node, "port-number", NULL);
-
-	return ulite_assign(&op->dev, id ? *id : -1, res.start, irq);
-}
-
-static int __devexit ulite_of_remove(struct platform_device *op)
-{
-	return ulite_release(&op->dev);
-}
-
-static struct of_platform_driver ulite_of_driver = {
-	.probe = ulite_of_probe,
-	.remove = __devexit_p(ulite_of_remove),
+	.probe = ulite_probe,
+	.remove = __devexit_p(ulite_remove),
 	.driver = {
-		.name = "uartlite",
 		.owner = THIS_MODULE,
+		.name  = "uartlite",
 		.of_match_table = ulite_of_match,
 	},
 };
 
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init ulite_of_register(void)
-{
-	pr_debug("uartlite: calling of_register_platform_driver()\n");
-	return of_register_platform_driver(&ulite_of_driver);
-}
-
-static inline void __exit ulite_of_unregister(void)
-{
-	of_unregister_platform_driver(&ulite_of_driver);
-}
-#else /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */
-/* Appropriate config not enabled; do nothing helpers */
-static inline int __init ulite_of_register(void) { return 0; }
-static inline void __exit ulite_of_unregister(void) { }
-#endif /* CONFIG_OF && (CONFIG_PPC32 || CONFIG_MICROBLAZE) */
-
 /* ---------------------------------------------------------------------
  * Module setup/teardown
  */
@@ -674,10 +626,6 @@ int __init ulite_init(void)
 	if (ret)
 		goto err_uart;
 
-	ret = ulite_of_register();
-	if (ret)
-		goto err_of;
-
 	pr_debug("uartlite: calling platform_driver_register()\n");
 	ret = platform_driver_register(&ulite_platform_driver);
 	if (ret)
@@ -686,8 +634,6 @@ int __init ulite_init(void)
 	return 0;
 
 err_plat:
-	ulite_of_unregister();
-err_of:
 	uart_unregister_driver(&ulite_uart_driver);
 err_uart:
 	printk(KERN_ERR "registering uartlite driver failed: err=%i", ret);
@@ -697,7 +643,6 @@ err_uart:
 void __exit ulite_exit(void)
 {
 	platform_driver_unregister(&ulite_platform_driver);
-	ulite_of_unregister();
 	uart_unregister_driver(&ulite_uart_driver);
 }
 
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 3f4848e..c327218 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1194,8 +1194,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context)
 	release_firmware(fw);
 }
 
-static int ucc_uart_probe(struct platform_device *ofdev,
-	const struct of_device_id *match)
+static int ucc_uart_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	const unsigned int *iprop;      /* Integer OF properties */
@@ -1270,13 +1269,12 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	ret = of_address_to_resource(np, 0, &res);
 	if (ret) {
 		dev_err(&ofdev->dev, "missing 'reg' property in device tree\n");
-		kfree(qe_port);
-		return ret;
+		goto out_free;
 	}
 	if (!res.start) {
 		dev_err(&ofdev->dev, "invalid 'reg' property in device tree\n");
-		kfree(qe_port);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_free;
 	}
 	qe_port->port.mapbase = res.start;
 
@@ -1286,17 +1284,17 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	if (!iprop) {
 		iprop = of_get_property(np, "device-id", NULL);
 		if (!iprop) {
-			kfree(qe_port);
 			dev_err(&ofdev->dev, "UCC is unspecified in "
 				"device tree\n");
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out_free;
 		}
 	}
 
 	if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
 		dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
-		kfree(qe_port);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_free;
 	}
 	qe_port->ucc_num = *iprop - 1;
 
@@ -1310,16 +1308,16 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	sprop = of_get_property(np, "rx-clock-name", NULL);
 	if (!sprop) {
 		dev_err(&ofdev->dev, "missing rx-clock-name in device tree\n");
-		kfree(qe_port);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_free;
 	}
 
 	qe_port->us_info.rx_clock = qe_clock_source(sprop);
 	if ((qe_port->us_info.rx_clock < QE_BRG1) ||
 	    (qe_port->us_info.rx_clock > QE_BRG16)) {
 		dev_err(&ofdev->dev, "rx-clock-name must be a BRG for UART\n");
-		kfree(qe_port);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_free;
 	}
 
 #ifdef LOOPBACK
@@ -1329,39 +1327,39 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	sprop = of_get_property(np, "tx-clock-name", NULL);
 	if (!sprop) {
 		dev_err(&ofdev->dev, "missing tx-clock-name in device tree\n");
-		kfree(qe_port);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_free;
 	}
 	qe_port->us_info.tx_clock = qe_clock_source(sprop);
 #endif
 	if ((qe_port->us_info.tx_clock < QE_BRG1) ||
 	    (qe_port->us_info.tx_clock > QE_BRG16)) {
 		dev_err(&ofdev->dev, "tx-clock-name must be a BRG for UART\n");
-		kfree(qe_port);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_free;
 	}
 
 	/* Get the port number, numbered 0-3 */
 	iprop = of_get_property(np, "port-number", NULL);
 	if (!iprop) {
 		dev_err(&ofdev->dev, "missing port-number in device tree\n");
-		kfree(qe_port);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_free;
 	}
 	qe_port->port.line = *iprop;
 	if (qe_port->port.line >= UCC_MAX_UART) {
 		dev_err(&ofdev->dev, "port-number must be 0-%u\n",
 			UCC_MAX_UART - 1);
-		kfree(qe_port);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_free;
 	}
 
 	qe_port->port.irq = irq_of_parse_and_map(np, 0);
 	if (qe_port->port.irq == NO_IRQ) {
 		dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n",
 		       qe_port->ucc_num + 1);
-		kfree(qe_port);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_free;
 	}
 
 	/*
@@ -1373,8 +1371,8 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 		np = of_find_node_by_type(NULL, "qe");
 		if (!np) {
 			dev_err(&ofdev->dev, "could not find 'qe' node\n");
-			kfree(qe_port);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out_free;
 		}
 	}
 
@@ -1382,8 +1380,8 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	if (!iprop) {
 		dev_err(&ofdev->dev,
 		       "missing brg-frequency in device tree\n");
-		kfree(qe_port);
-		return -EINVAL;
+		ret = -EINVAL;
+		goto out_np;
 	}
 
 	if (*iprop)
@@ -1398,16 +1396,16 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 		if (!iprop) {
 			dev_err(&ofdev->dev,
 				"missing QE bus-frequency in device tree\n");
-			kfree(qe_port);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out_np;
 		}
 		if (*iprop)
 			qe_port->port.uartclk = *iprop / 2;
 		else {
 			dev_err(&ofdev->dev,
 				"invalid QE bus-frequency in device tree\n");
-			kfree(qe_port);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto out_np;
 		}
 	}
 
@@ -1445,8 +1443,7 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	if (ret) {
 		dev_err(&ofdev->dev, "could not add /dev/ttyQE%u\n",
 		       qe_port->port.line);
-		kfree(qe_port);
-		return ret;
+		goto out_np;
 	}
 
 	dev_set_drvdata(&ofdev->dev, qe_port);
@@ -1460,6 +1457,11 @@ static int ucc_uart_probe(struct platform_device *ofdev,
 	       SERIAL_QE_MINOR + qe_port->port.line);
 
 	return 0;
+out_np:
+	of_node_put(np);
+out_free:
+	kfree(qe_port);
+	return ret;
 }
 
 static int ucc_uart_remove(struct platform_device *ofdev)
@@ -1485,7 +1487,7 @@ static struct of_device_id ucc_uart_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ucc_uart_match);
 
-static struct of_platform_driver ucc_uart_of_driver = {
+static struct platform_driver ucc_uart_of_driver = {
 	.driver = {
 		.name = "ucc_uart",
 		.owner = THIS_MODULE,
@@ -1510,7 +1512,7 @@ static int __init ucc_uart_init(void)
 		return ret;
 	}
 
-	ret = of_register_platform_driver(&ucc_uart_of_driver);
+	ret = platform_driver_register(&ucc_uart_of_driver);
 	if (ret)
 		printk(KERN_ERR
 		       "ucc-uart: could not register platform driver\n");
@@ -1523,7 +1525,7 @@ static void __exit ucc_uart_exit(void)
 	printk(KERN_INFO
 	       "Freescale QUICC Engine UART device driver unloading\n");
 
-	of_unregister_platform_driver(&ucc_uart_of_driver);
+	platform_driver_unregister(&ucc_uart_of_driver);
 	uart_unregister_driver(&ucc_uart_driver);
 }
 
diff --git a/drivers/tty/synclink.c b/drivers/tty/synclink.c
new file mode 100644
index 0000000..18888d0
--- /dev/null
+++ b/drivers/tty/synclink.c
@@ -0,0 +1,8119 @@
+/*
+ * linux/drivers/char/synclink.c
+ *
+ * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $
+ *
+ * Device driver for Microgate SyncLink ISA and PCI
+ * high speed multiprotocol serial adapters.
+ *
+ * written by Paul Fulghum for Microgate Corporation
+ * paulkf@microgate.com
+ *
+ * Microgate and SyncLink are trademarks of Microgate Corporation
+ *
+ * Derived from serial.c written by Theodore Ts'o and Linus Torvalds
+ *
+ * Original release 01/11/99
+ *
+ * This code is released under the GNU General Public License (GPL)
+ *
+ * This driver is primarily intended for use in synchronous
+ * HDLC mode. Asynchronous mode is also provided.
+ *
+ * When operating in synchronous mode, each call to mgsl_write()
+ * contains exactly one complete HDLC frame. Calling mgsl_put_char
+ * will start assembling an HDLC frame that will not be sent until
+ * mgsl_flush_chars or mgsl_write is called.
+ * 
+ * Synchronous receive data is reported as complete frames. To accomplish
+ * this, the TTY flip buffer is bypassed (too small to hold largest
+ * frame and may fragment frames) and the line discipline
+ * receive entry point is called directly.
+ *
+ * This driver has been tested with a slightly modified ppp.c driver
+ * for synchronous PPP.
+ *
+ * 2000/02/16
+ * Added interface for syncppp.c driver (an alternate synchronous PPP
+ * implementation that also supports Cisco HDLC). Each device instance
+ * registers as a tty device AND a network device (if dosyncppp option
+ * is set for the device). The functionality is determined by which
+ * device interface is opened.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(__i386__)
+#  define BREAKPOINT() asm("   int $3");
+#else
+#  define BREAKPOINT() { }
+#endif
+
+#define MAX_ISA_DEVICES 10
+#define MAX_PCI_DEVICES 10
+#define MAX_TOTAL_DEVICES 20
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/synclink.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/bitops.h>
+#include <asm/types.h>
+#include <linux/termios.h>
+#include <linux/workqueue.h>
+#include <linux/hdlc.h>
+#include <linux/dma-mapping.h>
+
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
+#endif
+
+#define GET_USER(error,value,addr) error = get_user(value,addr)
+#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
+#define PUT_USER(error,value,addr) error = put_user(value,addr)
+#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
+
+#include <asm/uaccess.h>
+
+#define RCLRVALUE 0xffff
+
+static MGSL_PARAMS default_params = {
+	MGSL_MODE_HDLC,			/* unsigned long mode */
+	0,				/* unsigned char loopback; */
+	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */
+	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */
+	0,				/* unsigned long clock_speed; */
+	0xff,				/* unsigned char addr_filter; */
+	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */
+	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */
+	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */
+	9600,				/* unsigned long data_rate; */
+	8,				/* unsigned char data_bits; */
+	1,				/* unsigned char stop_bits; */
+	ASYNC_PARITY_NONE		/* unsigned char parity; */
+};
+
+#define SHARED_MEM_ADDRESS_SIZE 0x40000
+#define BUFFERLISTSIZE 4096
+#define DMABUFFERSIZE 4096
+#define MAXRXFRAMES 7
+
+typedef struct _DMABUFFERENTRY
+{
+	u32 phys_addr;	/* 32-bit flat physical address of data buffer */
+	volatile u16 count;	/* buffer size/data count */
+	volatile u16 status;	/* Control/status field */
+	volatile u16 rcc;	/* character count field */
+	u16 reserved;	/* padding required by 16C32 */
+	u32 link;	/* 32-bit flat link to next buffer entry */
+	char *virt_addr;	/* virtual address of data buffer */
+	u32 phys_entry;	/* physical address of this buffer entry */
+	dma_addr_t dma_addr;
+} DMABUFFERENTRY, *DMAPBUFFERENTRY;
+
+/* The queue of BH actions to be performed */
+
+#define BH_RECEIVE  1
+#define BH_TRANSMIT 2
+#define BH_STATUS   4
+
+#define IO_PIN_SHUTDOWN_LIMIT 100
+
+struct	_input_signal_events {
+	int	ri_up;	
+	int	ri_down;
+	int	dsr_up;
+	int	dsr_down;
+	int	dcd_up;
+	int	dcd_down;
+	int	cts_up;
+	int	cts_down;
+};
+
+/* transmit holding buffer definitions*/
+#define MAX_TX_HOLDING_BUFFERS 5
+struct tx_holding_buffer {
+	int	buffer_size;
+	unsigned char *	buffer;
+};
+
+
+/*
+ * Device instance data structure
+ */
+ 
+struct mgsl_struct {
+	int			magic;
+	struct tty_port		port;
+	int			line;
+	int                     hw_version;
+	
+	struct mgsl_icount	icount;
+	
+	int			timeout;
+	int			x_char;		/* xon/xoff character */
+	u16			read_status_mask;
+	u16			ignore_status_mask;	
+	unsigned char 		*xmit_buf;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	
+	wait_queue_head_t	status_event_wait_q;
+	wait_queue_head_t	event_wait_q;
+	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
+	struct mgsl_struct	*next_device;	/* device list link */
+	
+	spinlock_t irq_spinlock;		/* spinlock for synchronizing with ISR */
+	struct work_struct task;		/* task structure for scheduling bh */
+
+	u32 EventMask;			/* event trigger mask */
+	u32 RecordedEvents;		/* pending events */
+
+	u32 max_frame_size;		/* as set by device config */
+
+	u32 pending_bh;
+
+	bool bh_running;		/* Protection from multiple */
+	int isr_overflow;
+	bool bh_requested;
+	
+	int dcd_chkcount;		/* check counts to prevent */
+	int cts_chkcount;		/* too many IRQs if a signal */
+	int dsr_chkcount;		/* is floating */
+	int ri_chkcount;
+
+	char *buffer_list;		/* virtual address of Rx & Tx buffer lists */
+	u32 buffer_list_phys;
+	dma_addr_t buffer_list_dma_addr;
+
+	unsigned int rx_buffer_count;	/* count of total allocated Rx buffers */
+	DMABUFFERENTRY *rx_buffer_list;	/* list of receive buffer entries */
+	unsigned int current_rx_buffer;
+
+	int num_tx_dma_buffers;		/* number of tx dma frames required */
+ 	int tx_dma_buffers_used;
+	unsigned int tx_buffer_count;	/* count of total allocated Tx buffers */
+	DMABUFFERENTRY *tx_buffer_list;	/* list of transmit buffer entries */
+	int start_tx_dma_buffer;	/* tx dma buffer to start tx dma operation */
+	int current_tx_buffer;          /* next tx dma buffer to be loaded */
+	
+	unsigned char *intermediate_rxbuffer;
+
+	int num_tx_holding_buffers;	/* number of tx holding buffer allocated */
+	int get_tx_holding_index;  	/* next tx holding buffer for adapter to load */
+	int put_tx_holding_index;  	/* next tx holding buffer to store user request */
+	int tx_holding_count;		/* number of tx holding buffers waiting */
+	struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS];
+
+	bool rx_enabled;
+	bool rx_overflow;
+	bool rx_rcc_underrun;
+
+	bool tx_enabled;
+	bool tx_active;
+	u32 idle_mode;
+
+	u16 cmr_value;
+	u16 tcsr_value;
+
+	char device_name[25];		/* device instance name */
+
+	unsigned int bus_type;	/* expansion bus type (ISA,EISA,PCI) */
+	unsigned char bus;		/* expansion bus number (zero based) */
+	unsigned char function;		/* PCI device number */
+
+	unsigned int io_base;		/* base I/O address of adapter */
+	unsigned int io_addr_size;	/* size of the I/O address range */
+	bool io_addr_requested;		/* true if I/O address requested */
+	
+	unsigned int irq_level;		/* interrupt level */
+	unsigned long irq_flags;
+	bool irq_requested;		/* true if IRQ requested */
+	
+	unsigned int dma_level;		/* DMA channel */
+	bool dma_requested;		/* true if dma channel requested */
+
+	u16 mbre_bit;
+	u16 loopback_bits;
+	u16 usc_idle_mode;
+
+	MGSL_PARAMS params;		/* communications parameters */
+
+	unsigned char serial_signals;	/* current serial signal states */
+
+	bool irq_occurred;		/* for diagnostics use */
+	unsigned int init_error;	/* Initialization startup error 		(DIAGS)	*/
+	int	fDiagnosticsmode;	/* Driver in Diagnostic mode?			(DIAGS)	*/
+
+	u32 last_mem_alloc;
+	unsigned char* memory_base;	/* shared memory address (PCI only) */
+	u32 phys_memory_base;
+	bool shared_mem_requested;
+
+	unsigned char* lcr_base;	/* local config registers (PCI only) */
+	u32 phys_lcr_base;
+	u32 lcr_offset;
+	bool lcr_mem_requested;
+
+	u32 misc_ctrl_value;
+	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+	char char_buf[MAX_ASYNC_BUFFER_SIZE];	
+	bool drop_rts_on_tx_done;
+
+	bool loopmode_insert_requested;
+	bool loopmode_send_done_requested;
+	
+	struct	_input_signal_events	input_signal_events;
+
+	/* generic HDLC device parts */
+	int netcount;
+	spinlock_t netlock;
+
+#if SYNCLINK_GENERIC_HDLC
+	struct net_device *netdev;
+#endif
+};
+
+#define MGSL_MAGIC 0x5401
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#ifndef SERIAL_XMIT_SIZE
+#define SERIAL_XMIT_SIZE 4096
+#endif
+
+/*
+ * These macros define the offsets used in calculating the
+ * I/O address of the specified USC registers.
+ */
+
+
+#define DCPIN 2		/* Bit 1 of I/O address */
+#define SDPIN 4		/* Bit 2 of I/O address */
+
+#define DCAR 0		/* DMA command/address register */
+#define CCAR SDPIN		/* channel command/address register */
+#define DATAREG DCPIN + SDPIN	/* serial data register */
+#define MSBONLY 0x41
+#define LSBONLY 0x40
+
+/*
+ * These macros define the register address (ordinal number)
+ * used for writing address/value pairs to the USC.
+ */
+
+#define CMR	0x02	/* Channel mode Register */
+#define CCSR	0x04	/* Channel Command/status Register */
+#define CCR	0x06	/* Channel Control Register */
+#define PSR	0x08	/* Port status Register */
+#define PCR	0x0a	/* Port Control Register */
+#define TMDR	0x0c	/* Test mode Data Register */
+#define TMCR	0x0e	/* Test mode Control Register */
+#define CMCR	0x10	/* Clock mode Control Register */
+#define HCR	0x12	/* Hardware Configuration Register */
+#define IVR	0x14	/* Interrupt Vector Register */
+#define IOCR	0x16	/* Input/Output Control Register */
+#define ICR	0x18	/* Interrupt Control Register */
+#define DCCR	0x1a	/* Daisy Chain Control Register */
+#define MISR	0x1c	/* Misc Interrupt status Register */
+#define SICR	0x1e	/* status Interrupt Control Register */
+#define RDR	0x20	/* Receive Data Register */
+#define RMR	0x22	/* Receive mode Register */
+#define RCSR	0x24	/* Receive Command/status Register */
+#define RICR	0x26	/* Receive Interrupt Control Register */
+#define RSR	0x28	/* Receive Sync Register */
+#define RCLR	0x2a	/* Receive count Limit Register */
+#define RCCR	0x2c	/* Receive Character count Register */
+#define TC0R	0x2e	/* Time Constant 0 Register */
+#define TDR	0x30	/* Transmit Data Register */
+#define TMR	0x32	/* Transmit mode Register */
+#define TCSR	0x34	/* Transmit Command/status Register */
+#define TICR	0x36	/* Transmit Interrupt Control Register */
+#define TSR	0x38	/* Transmit Sync Register */
+#define TCLR	0x3a	/* Transmit count Limit Register */
+#define TCCR	0x3c	/* Transmit Character count Register */
+#define TC1R	0x3e	/* Time Constant 1 Register */
+
+
+/*
+ * MACRO DEFINITIONS FOR DMA REGISTERS
+ */
+
+#define DCR	0x06	/* DMA Control Register (shared) */
+#define DACR	0x08	/* DMA Array count Register (shared) */
+#define BDCR	0x12	/* Burst/Dwell Control Register (shared) */
+#define DIVR	0x14	/* DMA Interrupt Vector Register (shared) */	
+#define DICR	0x18	/* DMA Interrupt Control Register (shared) */
+#define CDIR	0x1a	/* Clear DMA Interrupt Register (shared) */
+#define SDIR	0x1c	/* Set DMA Interrupt Register (shared) */
+
+#define TDMR	0x02	/* Transmit DMA mode Register */
+#define TDIAR	0x1e	/* Transmit DMA Interrupt Arm Register */
+#define TBCR	0x2a	/* Transmit Byte count Register */
+#define TARL	0x2c	/* Transmit Address Register (low) */
+#define TARU	0x2e	/* Transmit Address Register (high) */
+#define NTBCR	0x3a	/* Next Transmit Byte count Register */
+#define NTARL	0x3c	/* Next Transmit Address Register (low) */
+#define NTARU	0x3e	/* Next Transmit Address Register (high) */
+
+#define RDMR	0x82	/* Receive DMA mode Register (non-shared) */
+#define RDIAR	0x9e	/* Receive DMA Interrupt Arm Register */
+#define RBCR	0xaa	/* Receive Byte count Register */
+#define RARL	0xac	/* Receive Address Register (low) */
+#define RARU	0xae	/* Receive Address Register (high) */
+#define NRBCR	0xba	/* Next Receive Byte count Register */
+#define NRARL	0xbc	/* Next Receive Address Register (low) */
+#define NRARU	0xbe	/* Next Receive Address Register (high) */
+
+
+/*
+ * MACRO DEFINITIONS FOR MODEM STATUS BITS
+ */
+
+#define MODEMSTATUS_DTR 0x80
+#define MODEMSTATUS_DSR 0x40
+#define MODEMSTATUS_RTS 0x20
+#define MODEMSTATUS_CTS 0x10
+#define MODEMSTATUS_RI  0x04
+#define MODEMSTATUS_DCD 0x01
+
+
+/*
+ * Channel Command/Address Register (CCAR) Command Codes
+ */
+
+#define RTCmd_Null			0x0000
+#define RTCmd_ResetHighestIus		0x1000
+#define RTCmd_TriggerChannelLoadDma	0x2000
+#define RTCmd_TriggerRxDma		0x2800
+#define RTCmd_TriggerTxDma		0x3000
+#define RTCmd_TriggerRxAndTxDma		0x3800
+#define RTCmd_PurgeRxFifo		0x4800
+#define RTCmd_PurgeTxFifo		0x5000
+#define RTCmd_PurgeRxAndTxFifo		0x5800
+#define RTCmd_LoadRcc			0x6800
+#define RTCmd_LoadTcc			0x7000
+#define RTCmd_LoadRccAndTcc		0x7800
+#define RTCmd_LoadTC0			0x8800
+#define RTCmd_LoadTC1			0x9000
+#define RTCmd_LoadTC0AndTC1		0x9800
+#define RTCmd_SerialDataLSBFirst	0xa000
+#define RTCmd_SerialDataMSBFirst	0xa800
+#define RTCmd_SelectBigEndian		0xb000
+#define RTCmd_SelectLittleEndian	0xb800
+
+
+/*
+ * DMA Command/Address Register (DCAR) Command Codes
+ */
+
+#define DmaCmd_Null			0x0000
+#define DmaCmd_ResetTxChannel		0x1000
+#define DmaCmd_ResetRxChannel		0x1200
+#define DmaCmd_StartTxChannel		0x2000
+#define DmaCmd_StartRxChannel		0x2200
+#define DmaCmd_ContinueTxChannel	0x3000
+#define DmaCmd_ContinueRxChannel	0x3200
+#define DmaCmd_PauseTxChannel		0x4000
+#define DmaCmd_PauseRxChannel		0x4200
+#define DmaCmd_AbortTxChannel		0x5000
+#define DmaCmd_AbortRxChannel		0x5200
+#define DmaCmd_InitTxChannel		0x7000
+#define DmaCmd_InitRxChannel		0x7200
+#define DmaCmd_ResetHighestDmaIus	0x8000
+#define DmaCmd_ResetAllChannels		0x9000
+#define DmaCmd_StartAllChannels		0xa000
+#define DmaCmd_ContinueAllChannels	0xb000
+#define DmaCmd_PauseAllChannels		0xc000
+#define DmaCmd_AbortAllChannels		0xd000
+#define DmaCmd_InitAllChannels		0xf000
+
+#define TCmd_Null			0x0000
+#define TCmd_ClearTxCRC			0x2000
+#define TCmd_SelectTicrTtsaData		0x4000
+#define TCmd_SelectTicrTxFifostatus	0x5000
+#define TCmd_SelectTicrIntLevel		0x6000
+#define TCmd_SelectTicrdma_level		0x7000
+#define TCmd_SendFrame			0x8000
+#define TCmd_SendAbort			0x9000
+#define TCmd_EnableDleInsertion		0xc000
+#define TCmd_DisableDleInsertion	0xd000
+#define TCmd_ClearEofEom		0xe000
+#define TCmd_SetEofEom			0xf000
+
+#define RCmd_Null			0x0000
+#define RCmd_ClearRxCRC			0x2000
+#define RCmd_EnterHuntmode		0x3000
+#define RCmd_SelectRicrRtsaData		0x4000
+#define RCmd_SelectRicrRxFifostatus	0x5000
+#define RCmd_SelectRicrIntLevel		0x6000
+#define RCmd_SelectRicrdma_level		0x7000
+
+/*
+ * Bits for enabling and disabling IRQs in Interrupt Control Register (ICR)
+ */
+ 
+#define RECEIVE_STATUS		BIT5
+#define RECEIVE_DATA		BIT4
+#define TRANSMIT_STATUS		BIT3
+#define TRANSMIT_DATA		BIT2
+#define IO_PIN			BIT1
+#define MISC			BIT0
+
+
+/*
+ * Receive status Bits in Receive Command/status Register RCSR
+ */
+
+#define RXSTATUS_SHORT_FRAME		BIT8
+#define RXSTATUS_CODE_VIOLATION		BIT8
+#define RXSTATUS_EXITED_HUNT		BIT7
+#define RXSTATUS_IDLE_RECEIVED		BIT6
+#define RXSTATUS_BREAK_RECEIVED		BIT5
+#define RXSTATUS_ABORT_RECEIVED		BIT5
+#define RXSTATUS_RXBOUND		BIT4
+#define RXSTATUS_CRC_ERROR		BIT3
+#define RXSTATUS_FRAMING_ERROR		BIT3
+#define RXSTATUS_ABORT			BIT2
+#define RXSTATUS_PARITY_ERROR		BIT2
+#define RXSTATUS_OVERRUN		BIT1
+#define RXSTATUS_DATA_AVAILABLE		BIT0
+#define RXSTATUS_ALL			0x01f6
+#define usc_UnlatchRxstatusBits(a,b) usc_OutReg( (a), RCSR, (u16)((b) & RXSTATUS_ALL) )
+
+/*
+ * Values for setting transmit idle mode in 
+ * Transmit Control/status Register (TCSR)
+ */
+#define IDLEMODE_FLAGS			0x0000
+#define IDLEMODE_ALT_ONE_ZERO		0x0100
+#define IDLEMODE_ZERO			0x0200
+#define IDLEMODE_ONE			0x0300
+#define IDLEMODE_ALT_MARK_SPACE		0x0500
+#define IDLEMODE_SPACE			0x0600
+#define IDLEMODE_MARK			0x0700
+#define IDLEMODE_MASK			0x0700
+
+/*
+ * IUSC revision identifiers
+ */
+#define	IUSC_SL1660			0x4d44
+#define IUSC_PRE_SL1660			0x4553
+
+/*
+ * Transmit status Bits in Transmit Command/status Register (TCSR)
+ */
+
+#define TCSR_PRESERVE			0x0F00
+
+#define TCSR_UNDERWAIT			BIT11
+#define TXSTATUS_PREAMBLE_SENT		BIT7
+#define TXSTATUS_IDLE_SENT		BIT6
+#define TXSTATUS_ABORT_SENT		BIT5
+#define TXSTATUS_EOF_SENT		BIT4
+#define TXSTATUS_EOM_SENT		BIT4
+#define TXSTATUS_CRC_SENT		BIT3
+#define TXSTATUS_ALL_SENT		BIT2
+#define TXSTATUS_UNDERRUN		BIT1
+#define TXSTATUS_FIFO_EMPTY		BIT0
+#define TXSTATUS_ALL			0x00fa
+#define usc_UnlatchTxstatusBits(a,b) usc_OutReg( (a), TCSR, (u16)((a)->tcsr_value + ((b) & 0x00FF)) )
+				
+
+#define MISCSTATUS_RXC_LATCHED		BIT15
+#define MISCSTATUS_RXC			BIT14
+#define MISCSTATUS_TXC_LATCHED		BIT13
+#define MISCSTATUS_TXC			BIT12
+#define MISCSTATUS_RI_LATCHED		BIT11
+#define MISCSTATUS_RI			BIT10
+#define MISCSTATUS_DSR_LATCHED		BIT9
+#define MISCSTATUS_DSR			BIT8
+#define MISCSTATUS_DCD_LATCHED		BIT7
+#define MISCSTATUS_DCD			BIT6
+#define MISCSTATUS_CTS_LATCHED		BIT5
+#define MISCSTATUS_CTS			BIT4
+#define MISCSTATUS_RCC_UNDERRUN		BIT3
+#define MISCSTATUS_DPLL_NO_SYNC		BIT2
+#define MISCSTATUS_BRG1_ZERO		BIT1
+#define MISCSTATUS_BRG0_ZERO		BIT0
+
+#define usc_UnlatchIostatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0xaaa0))
+#define usc_UnlatchMiscstatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0x000f))
+
+#define SICR_RXC_ACTIVE			BIT15
+#define SICR_RXC_INACTIVE		BIT14
+#define SICR_RXC			(BIT15+BIT14)
+#define SICR_TXC_ACTIVE			BIT13
+#define SICR_TXC_INACTIVE		BIT12
+#define SICR_TXC			(BIT13+BIT12)
+#define SICR_RI_ACTIVE			BIT11
+#define SICR_RI_INACTIVE		BIT10
+#define SICR_RI				(BIT11+BIT10)
+#define SICR_DSR_ACTIVE			BIT9
+#define SICR_DSR_INACTIVE		BIT8
+#define SICR_DSR			(BIT9+BIT8)
+#define SICR_DCD_ACTIVE			BIT7
+#define SICR_DCD_INACTIVE		BIT6
+#define SICR_DCD			(BIT7+BIT6)
+#define SICR_CTS_ACTIVE			BIT5
+#define SICR_CTS_INACTIVE		BIT4
+#define SICR_CTS			(BIT5+BIT4)
+#define SICR_RCC_UNDERFLOW		BIT3
+#define SICR_DPLL_NO_SYNC		BIT2
+#define SICR_BRG1_ZERO			BIT1
+#define SICR_BRG0_ZERO			BIT0
+
+void usc_DisableMasterIrqBit( struct mgsl_struct *info );
+void usc_EnableMasterIrqBit( struct mgsl_struct *info );
+void usc_EnableInterrupts( struct mgsl_struct *info, u16 IrqMask );
+void usc_DisableInterrupts( struct mgsl_struct *info, u16 IrqMask );
+void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask );
+
+#define usc_EnableInterrupts( a, b ) \
+	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0xc0 + (b)) )
+
+#define usc_DisableInterrupts( a, b ) \
+	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0x80 + (b)) )
+
+#define usc_EnableMasterIrqBit(a) \
+	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0x0f00) + 0xb000) )
+
+#define usc_DisableMasterIrqBit(a) \
+	usc_OutReg( (a), ICR, (u16)(usc_InReg((a),ICR) & 0x7f00) )
+
+#define usc_ClearIrqPendingBits( a, b ) usc_OutReg( (a), DCCR, 0x40 + (b) )
+
+/*
+ * Transmit status Bits in Transmit Control status Register (TCSR)
+ * and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0)
+ */
+
+#define TXSTATUS_PREAMBLE_SENT	BIT7
+#define TXSTATUS_IDLE_SENT	BIT6
+#define TXSTATUS_ABORT_SENT	BIT5
+#define TXSTATUS_EOF		BIT4
+#define TXSTATUS_CRC_SENT	BIT3
+#define TXSTATUS_ALL_SENT	BIT2
+#define TXSTATUS_UNDERRUN	BIT1
+#define TXSTATUS_FIFO_EMPTY	BIT0
+
+#define DICR_MASTER		BIT15
+#define DICR_TRANSMIT		BIT0
+#define DICR_RECEIVE		BIT1
+
+#define usc_EnableDmaInterrupts(a,b) \
+	usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) | (b)) )
+
+#define usc_DisableDmaInterrupts(a,b) \
+	usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) & ~(b)) )
+
+#define usc_EnableStatusIrqs(a,b) \
+	usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) | (b)) )
+
+#define usc_DisablestatusIrqs(a,b) \
+	usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) & ~(b)) )
+
+/* Transmit status Bits in Transmit Control status Register (TCSR) */
+/* and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) */
+
+
+#define DISABLE_UNCONDITIONAL    0
+#define DISABLE_END_OF_FRAME     1
+#define ENABLE_UNCONDITIONAL     2
+#define ENABLE_AUTO_CTS          3
+#define ENABLE_AUTO_DCD          3
+#define usc_EnableTransmitter(a,b) \
+	usc_OutReg( (a), TMR, (u16)((usc_InReg((a),TMR) & 0xfffc) | (b)) )
+#define usc_EnableReceiver(a,b) \
+	usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) )
+
+static u16  usc_InDmaReg( struct mgsl_struct *info, u16 Port );
+static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
+static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
+
+static u16  usc_InReg( struct mgsl_struct *info, u16 Port );
+static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
+static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
+void usc_RCmd( struct mgsl_struct *info, u16 Cmd );
+void usc_TCmd( struct mgsl_struct *info, u16 Cmd );
+
+#define usc_TCmd(a,b) usc_OutReg((a), TCSR, (u16)((a)->tcsr_value + (b)))
+#define usc_RCmd(a,b) usc_OutReg((a), RCSR, (b))
+
+#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1))
+
+static void usc_process_rxoverrun_sync( struct mgsl_struct *info );
+static void usc_start_receiver( struct mgsl_struct *info );
+static void usc_stop_receiver( struct mgsl_struct *info );
+
+static void usc_start_transmitter( struct mgsl_struct *info );
+static void usc_stop_transmitter( struct mgsl_struct *info );
+static void usc_set_txidle( struct mgsl_struct *info );
+static void usc_load_txfifo( struct mgsl_struct *info );
+
+static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
+static void usc_enable_loopback( struct mgsl_struct *info, int enable );
+
+static void usc_get_serial_signals( struct mgsl_struct *info );
+static void usc_set_serial_signals( struct mgsl_struct *info );
+
+static void usc_reset( struct mgsl_struct *info );
+
+static void usc_set_sync_mode( struct mgsl_struct *info );
+static void usc_set_sdlc_mode( struct mgsl_struct *info );
+static void usc_set_async_mode( struct mgsl_struct *info );
+static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
+
+static void usc_loopback_frame( struct mgsl_struct *info );
+
+static void mgsl_tx_timeout(unsigned long context);
+
+
+static void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
+static void usc_loopmode_insert_request( struct mgsl_struct * info );
+static int usc_loopmode_active( struct mgsl_struct * info);
+static void usc_loopmode_send_done( struct mgsl_struct * info );
+
+static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
+
+#if SYNCLINK_GENERIC_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct mgsl_struct *info);
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
+static int  hdlcdev_init(struct mgsl_struct *info);
+static void hdlcdev_exit(struct mgsl_struct *info);
+#endif
+
+/*
+ * Defines a BUS descriptor value for the PCI adapter
+ * local bus address ranges.
+ */
+
+#define BUS_DESCRIPTOR( WrHold, WrDly, RdDly, Nwdd, Nwad, Nxda, Nrdd, Nrad ) \
+(0x00400020 + \
+((WrHold) << 30) + \
+((WrDly)  << 28) + \
+((RdDly)  << 26) + \
+((Nwdd)   << 20) + \
+((Nwad)   << 15) + \
+((Nxda)   << 13) + \
+((Nrdd)   << 11) + \
+((Nrad)   <<  6) )
+
+static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
+
+/*
+ * Adapter diagnostic routines
+ */
+static bool mgsl_register_test( struct mgsl_struct *info );
+static bool mgsl_irq_test( struct mgsl_struct *info );
+static bool mgsl_dma_test( struct mgsl_struct *info );
+static bool mgsl_memory_test( struct mgsl_struct *info );
+static int mgsl_adapter_test( struct mgsl_struct *info );
+
+/*
+ * device and resource management routines
+ */
+static int mgsl_claim_resources(struct mgsl_struct *info);
+static void mgsl_release_resources(struct mgsl_struct *info);
+static void mgsl_add_device(struct mgsl_struct *info);
+static struct mgsl_struct* mgsl_allocate_device(void);
+
+/*
+ * DMA buffer manupulation functions.
+ */
+static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
+static bool mgsl_get_rx_frame( struct mgsl_struct *info );
+static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info );
+static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
+static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
+static int num_free_tx_dma_buffers(struct mgsl_struct *info);
+static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
+static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
+
+/*
+ * DMA and Shared Memory buffer allocation and formatting
+ */
+static int  mgsl_allocate_dma_buffers(struct mgsl_struct *info);
+static void mgsl_free_dma_buffers(struct mgsl_struct *info);
+static int  mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
+static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
+static int  mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
+static void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
+static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
+static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
+static bool load_next_tx_holding_buffer(struct mgsl_struct *info);
+static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
+
+/*
+ * Bottom half interrupt handlers
+ */
+static void mgsl_bh_handler(struct work_struct *work);
+static void mgsl_bh_receive(struct mgsl_struct *info);
+static void mgsl_bh_transmit(struct mgsl_struct *info);
+static void mgsl_bh_status(struct mgsl_struct *info);
+
+/*
+ * Interrupt handler routines and dispatch table.
+ */
+static void mgsl_isr_null( struct mgsl_struct *info );
+static void mgsl_isr_transmit_data( struct mgsl_struct *info );
+static void mgsl_isr_receive_data( struct mgsl_struct *info );
+static void mgsl_isr_receive_status( struct mgsl_struct *info );
+static void mgsl_isr_transmit_status( struct mgsl_struct *info );
+static void mgsl_isr_io_pin( struct mgsl_struct *info );
+static void mgsl_isr_misc( struct mgsl_struct *info );
+static void mgsl_isr_receive_dma( struct mgsl_struct *info );
+static void mgsl_isr_transmit_dma( struct mgsl_struct *info );
+
+typedef void (*isr_dispatch_func)(struct mgsl_struct *);
+
+static isr_dispatch_func UscIsrTable[7] =
+{
+	mgsl_isr_null,
+	mgsl_isr_misc,
+	mgsl_isr_io_pin,
+	mgsl_isr_transmit_data,
+	mgsl_isr_transmit_status,
+	mgsl_isr_receive_data,
+	mgsl_isr_receive_status
+};
+
+/*
+ * ioctl call handlers
+ */
+static int tiocmget(struct tty_struct *tty);
+static int tiocmset(struct tty_struct *tty,
+		    unsigned int set, unsigned int clear);
+static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount
+	__user *user_icount);
+static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS  __user *user_params);
+static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS  __user *new_params);
+static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode);
+static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode);
+static int mgsl_txenable(struct mgsl_struct * info, int enable);
+static int mgsl_txabort(struct mgsl_struct * info);
+static int mgsl_rxenable(struct mgsl_struct * info, int enable);
+static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
+static int mgsl_loopmode_send_done( struct mgsl_struct * info );
+
+/* set non-zero on successful registration with PCI subsystem */
+static bool pci_registered;
+
+/*
+ * Global linked list of SyncLink devices
+ */
+static struct mgsl_struct *mgsl_device_list;
+static int mgsl_device_count;
+
+/*
+ * Set this param to non-zero to load eax with the
+ * .text section address and breakpoint on module load.
+ * This is useful for use with gdb and add-symbol-file command.
+ */
+static int break_on_load;
+
+/*
+ * Driver major number, defaults to zero to get auto
+ * assigned major number. May be forced as module parameter.
+ */
+static int ttymajor;
+
+/*
+ * Array of user specified options for ISA adapters.
+ */
+static int io[MAX_ISA_DEVICES];
+static int irq[MAX_ISA_DEVICES];
+static int dma[MAX_ISA_DEVICES];
+static int debug_level;
+static int maxframe[MAX_TOTAL_DEVICES];
+static int txdmabufs[MAX_TOTAL_DEVICES];
+static int txholdbufs[MAX_TOTAL_DEVICES];
+	
+module_param(break_on_load, bool, 0);
+module_param(ttymajor, int, 0);
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(dma, int, NULL, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+module_param_array(txdmabufs, int, NULL, 0);
+module_param_array(txholdbufs, int, NULL, 0);
+
+static char *driver_name = "SyncLink serial driver";
+static char *driver_version = "$Revision: 4.38 $";
+
+static int synclink_init_one (struct pci_dev *dev,
+				     const struct pci_device_id *ent);
+static void synclink_remove_one (struct pci_dev *dev);
+
+static struct pci_device_id synclink_pci_tbl[] = {
+	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
+
+MODULE_LICENSE("GPL");
+
+static struct pci_driver synclink_pci_driver = {
+	.name		= "synclink",
+	.id_table	= synclink_pci_tbl,
+	.probe		= synclink_init_one,
+	.remove		= __devexit_p(synclink_remove_one),
+};
+
+static struct tty_driver *serial_driver;
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+
+static void mgsl_change_params(struct mgsl_struct *info);
+static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
+
+/*
+ * 1st function defined in .text section. Calling this function in
+ * init_module() followed by a breakpoint allows a remote debugger
+ * (gdb) to get the .text address for the add-symbol-file command.
+ * This allows remote debugging of dynamically loadable modules.
+ */
+static void* mgsl_get_text_ptr(void)
+{
+	return mgsl_get_text_ptr;
+}
+
+static inline int mgsl_paranoia_check(struct mgsl_struct *info,
+					char *name, const char *routine)
+{
+#ifdef MGSL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for mgsl struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null mgsl_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (info->magic != MGSL_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+#else
+	if (!info)
+		return 1;
+#endif
+	return 0;
+}
+
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->ops->receive_buf)
+			ld->ops->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
+/* mgsl_stop()		throttle (stop) transmitter
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static void mgsl_stop(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_stop"))
+		return;
+	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("mgsl_stop(%s)\n",info->device_name);	
+		
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (info->tx_enabled)
+	 	usc_stop_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+}	/* end of mgsl_stop() */
+
+/* mgsl_start()		release (start) transmitter
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static void mgsl_start(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_start"))
+		return;
+	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("mgsl_start(%s)\n",info->device_name);	
+		
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (!info->tx_enabled)
+	 	usc_start_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+}	/* end of mgsl_start() */
+
+/*
+ * Bottom half work queue access functions
+ */
+
+/* mgsl_bh_action()	Return next bottom half action to perform.
+ * Return Value:	BH action code or 0 if nothing to do.
+ */
+static int mgsl_bh_action(struct mgsl_struct *info)
+{
+	unsigned long flags;
+	int rc = 0;
+	
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+
+	if (info->pending_bh & BH_RECEIVE) {
+		info->pending_bh &= ~BH_RECEIVE;
+		rc = BH_RECEIVE;
+	} else if (info->pending_bh & BH_TRANSMIT) {
+		info->pending_bh &= ~BH_TRANSMIT;
+		rc = BH_TRANSMIT;
+	} else if (info->pending_bh & BH_STATUS) {
+		info->pending_bh &= ~BH_STATUS;
+		rc = BH_STATUS;
+	}
+
+	if (!rc) {
+		/* Mark BH routine as complete */
+		info->bh_running = false;
+		info->bh_requested = false;
+	}
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+	return rc;
+}
+
+/*
+ * 	Perform bottom half processing of work items queued by ISR.
+ */
+static void mgsl_bh_handler(struct work_struct *work)
+{
+	struct mgsl_struct *info =
+		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);
+	
+	info->bh_running = true;
+
+	while((action = mgsl_bh_action(info)) != 0) {
+	
+		/* Process work item */
+		if ( debug_level >= DEBUG_LEVEL_BH )
+			printk( "%s(%d):mgsl_bh_handler() work item action=%d\n",
+				__FILE__,__LINE__,action);
+
+		switch (action) {
+		
+		case BH_RECEIVE:
+			mgsl_bh_receive(info);
+			break;
+		case BH_TRANSMIT:
+			mgsl_bh_transmit(info);
+			break;
+		case BH_STATUS:
+			mgsl_bh_status(info);
+			break;
+		default:
+			/* unknown work item ID */
+			printk("Unknown work item ID=%08X!\n", action);
+			break;
+		}
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):mgsl_bh_handler(%s) exit\n",
+			__FILE__,__LINE__,info->device_name);
+}
+
+static void mgsl_bh_receive(struct mgsl_struct *info)
+{
+	bool (*get_rx_frame)(struct mgsl_struct *info) =
+		(info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):mgsl_bh_receive(%s)\n",
+			__FILE__,__LINE__,info->device_name);
+	
+	do
+	{
+		if (info->rx_rcc_underrun) {
+			unsigned long flags;
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			usc_start_receiver(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			return;
+		}
+	} while(get_rx_frame(info));
+}
+
+static void mgsl_bh_transmit(struct mgsl_struct *info)
+{
+	struct tty_struct *tty = info->port.tty;
+	unsigned long flags;
+	
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):mgsl_bh_transmit() entry on %s\n",
+			__FILE__,__LINE__,info->device_name);
+
+	if (tty)
+		tty_wakeup(tty);
+
+	/* if transmitter idle and loopmode_send_done_requested
+	 * then start echoing RxD to TxD
+	 */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+ 	if ( !info->tx_active && info->loopmode_send_done_requested )
+ 		usc_loopmode_send_done( info );
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+}
+
+static void mgsl_bh_status(struct mgsl_struct *info)
+{
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):mgsl_bh_status() entry on %s\n",
+			__FILE__,__LINE__,info->device_name);
+
+	info->ri_chkcount = 0;
+	info->dsr_chkcount = 0;
+	info->dcd_chkcount = 0;
+	info->cts_chkcount = 0;
+}
+
+/* mgsl_isr_receive_status()
+ * 
+ *	Service a receive status interrupt. The type of status
+ *	interrupt is indicated by the state of the RCSR.
+ *	This is only used for HDLC mode.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_receive_status( struct mgsl_struct *info )
+{
+	u16 status = usc_InReg( info, RCSR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_receive_status status=%04X\n",
+			__FILE__,__LINE__,status);
+			
+ 	if ( (status & RXSTATUS_ABORT_RECEIVED) && 
+		info->loopmode_insert_requested &&
+ 		usc_loopmode_active(info) )
+ 	{
+		++info->icount.rxabort;
+	 	info->loopmode_insert_requested = false;
+ 
+ 		/* clear CMR:13 to start echoing RxD to TxD */
+		info->cmr_value &= ~BIT13;
+ 		usc_OutReg(info, CMR, info->cmr_value);
+ 
+		/* disable received abort irq (no longer required) */
+	 	usc_OutReg(info, RICR,
+ 			(usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED));
+ 	}
+
+	if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) {
+		if (status & RXSTATUS_EXITED_HUNT)
+			info->icount.exithunt++;
+		if (status & RXSTATUS_IDLE_RECEIVED)
+			info->icount.rxidle++;
+		wake_up_interruptible(&info->event_wait_q);
+	}
+
+	if (status & RXSTATUS_OVERRUN){
+		info->icount.rxover++;
+		usc_process_rxoverrun_sync( info );
+	}
+
+	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
+	usc_UnlatchRxstatusBits( info, status );
+
+}	/* end of mgsl_isr_receive_status() */
+
+/* mgsl_isr_transmit_status()
+ * 
+ * 	Service a transmit status interrupt
+ *	HDLC mode :end of transmit frame
+ *	Async mode:all data is sent
+ * 	transmit status is indicated by bits in the TCSR.
+ * 
+ * Arguments:		info	       pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_transmit_status( struct mgsl_struct *info )
+{
+	u16 status = usc_InReg( info, TCSR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_transmit_status status=%04X\n",
+			__FILE__,__LINE__,status);
+	
+	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
+	usc_UnlatchTxstatusBits( info, status );
+	
+	if ( status & (TXSTATUS_UNDERRUN | TXSTATUS_ABORT_SENT) )
+	{
+		/* finished sending HDLC abort. This may leave	*/
+		/* the TxFifo with data from the aborted frame	*/
+		/* so purge the TxFifo. Also shutdown the DMA	*/
+		/* channel in case there is data remaining in 	*/
+		/* the DMA buffer				*/
+ 		usc_DmaCmd( info, DmaCmd_ResetTxChannel );
+ 		usc_RTCmd( info, RTCmd_PurgeTxFifo );
+	}
+ 
+	if ( status & TXSTATUS_EOF_SENT )
+		info->icount.txok++;
+	else if ( status & TXSTATUS_UNDERRUN )
+		info->icount.txunder++;
+	else if ( status & TXSTATUS_ABORT_SENT )
+		info->icount.txabort++;
+	else
+		info->icount.txunder++;
+			
+	info->tx_active = false;
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	del_timer(&info->tx_timer);	
+	
+	if ( info->drop_rts_on_tx_done ) {
+		usc_get_serial_signals( info );
+		if ( info->serial_signals & SerialSignal_RTS ) {
+			info->serial_signals &= ~SerialSignal_RTS;
+			usc_set_serial_signals( info );
+		}
+		info->drop_rts_on_tx_done = false;
+	}
+
+#if SYNCLINK_GENERIC_HDLC
+	if (info->netcount)
+		hdlcdev_tx_done(info);
+	else 
+#endif
+	{
+		if (info->port.tty->stopped || info->port.tty->hw_stopped) {
+			usc_stop_transmitter(info);
+			return;
+		}
+		info->pending_bh |= BH_TRANSMIT;
+	}
+
+}	/* end of mgsl_isr_transmit_status() */
+
+/* mgsl_isr_io_pin()
+ * 
+ * 	Service an Input/Output pin interrupt. The type of
+ * 	interrupt is indicated by bits in the MISR
+ * 	
+ * Arguments:		info	       pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_io_pin( struct mgsl_struct *info )
+{
+ 	struct	mgsl_icount *icount;
+	u16 status = usc_InReg( info, MISR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_io_pin status=%04X\n",
+			__FILE__,__LINE__,status);
+			
+	usc_ClearIrqPendingBits( info, IO_PIN );
+	usc_UnlatchIostatusBits( info, status );
+
+	if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED |
+	              MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) {
+		icount = &info->icount;
+		/* update input line counters */
+		if (status & MISCSTATUS_RI_LATCHED) {
+			if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
+				usc_DisablestatusIrqs(info,SICR_RI);
+			icount->rng++;
+			if ( status & MISCSTATUS_RI )
+				info->input_signal_events.ri_up++;	
+			else
+				info->input_signal_events.ri_down++;	
+		}
+		if (status & MISCSTATUS_DSR_LATCHED) {
+			if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
+				usc_DisablestatusIrqs(info,SICR_DSR);
+			icount->dsr++;
+			if ( status & MISCSTATUS_DSR )
+				info->input_signal_events.dsr_up++;
+			else
+				info->input_signal_events.dsr_down++;
+		}
+		if (status & MISCSTATUS_DCD_LATCHED) {
+			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
+				usc_DisablestatusIrqs(info,SICR_DCD);
+			icount->dcd++;
+			if (status & MISCSTATUS_DCD) {
+				info->input_signal_events.dcd_up++;
+			} else
+				info->input_signal_events.dcd_down++;
+#if SYNCLINK_GENERIC_HDLC
+			if (info->netcount) {
+				if (status & MISCSTATUS_DCD)
+					netif_carrier_on(info->netdev);
+				else
+					netif_carrier_off(info->netdev);
+			}
+#endif
+		}
+		if (status & MISCSTATUS_CTS_LATCHED)
+		{
+			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
+				usc_DisablestatusIrqs(info,SICR_CTS);
+			icount->cts++;
+			if ( status & MISCSTATUS_CTS )
+				info->input_signal_events.cts_up++;
+			else
+				info->input_signal_events.cts_down++;
+		}
+		wake_up_interruptible(&info->status_event_wait_q);
+		wake_up_interruptible(&info->event_wait_q);
+
+		if ( (info->port.flags & ASYNC_CHECK_CD) && 
+		     (status & MISCSTATUS_DCD_LATCHED) ) {
+			if ( debug_level >= DEBUG_LEVEL_ISR )
+				printk("%s CD now %s...", info->device_name,
+				       (status & MISCSTATUS_DCD) ? "on" : "off");
+			if (status & MISCSTATUS_DCD)
+				wake_up_interruptible(&info->port.open_wait);
+			else {
+				if ( debug_level >= DEBUG_LEVEL_ISR )
+					printk("doing serial hangup...");
+				if (info->port.tty)
+					tty_hangup(info->port.tty);
+			}
+		}
+	
+		if ( (info->port.flags & ASYNC_CTS_FLOW) && 
+		     (status & MISCSTATUS_CTS_LATCHED) ) {
+			if (info->port.tty->hw_stopped) {
+				if (status & MISCSTATUS_CTS) {
+					if ( debug_level >= DEBUG_LEVEL_ISR )
+						printk("CTS tx start...");
+					if (info->port.tty)
+						info->port.tty->hw_stopped = 0;
+					usc_start_transmitter(info);
+					info->pending_bh |= BH_TRANSMIT;
+					return;
+				}
+			} else {
+				if (!(status & MISCSTATUS_CTS)) {
+					if ( debug_level >= DEBUG_LEVEL_ISR )
+						printk("CTS tx stop...");
+					if (info->port.tty)
+						info->port.tty->hw_stopped = 1;
+					usc_stop_transmitter(info);
+				}
+			}
+		}
+	}
+
+	info->pending_bh |= BH_STATUS;
+	
+	/* for diagnostics set IRQ flag */
+	if ( status & MISCSTATUS_TXC_LATCHED ){
+		usc_OutReg( info, SICR,
+			(unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) );
+		usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED );
+		info->irq_occurred = true;
+	}
+
+}	/* end of mgsl_isr_io_pin() */
+
+/* mgsl_isr_transmit_data()
+ * 
+ * 	Service a transmit data interrupt (async mode only).
+ * 
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_transmit_data( struct mgsl_struct *info )
+{
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n",
+			__FILE__,__LINE__,info->xmit_cnt);
+			
+	usc_ClearIrqPendingBits( info, TRANSMIT_DATA );
+	
+	if (info->port.tty->stopped || info->port.tty->hw_stopped) {
+		usc_stop_transmitter(info);
+		return;
+	}
+	
+	if ( info->xmit_cnt )
+		usc_load_txfifo( info );
+	else
+		info->tx_active = false;
+		
+	if (info->xmit_cnt < WAKEUP_CHARS)
+		info->pending_bh |= BH_TRANSMIT;
+
+}	/* end of mgsl_isr_transmit_data() */
+
+/* mgsl_isr_receive_data()
+ * 
+ * 	Service a receive data interrupt. This occurs
+ * 	when operating in asynchronous interrupt transfer mode.
+ *	The receive data FIFO is flushed to the receive data buffers. 
+ * 
+ * Arguments:		info		pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_receive_data( struct mgsl_struct *info )
+{
+	int Fifocount;
+	u16 status;
+	int work = 0;
+	unsigned char DataByte;
+ 	struct tty_struct *tty = info->port.tty;
+ 	struct	mgsl_icount *icount = &info->icount;
+	
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_receive_data\n",
+			__FILE__,__LINE__);
+
+	usc_ClearIrqPendingBits( info, RECEIVE_DATA );
+	
+	/* select FIFO status for RICR readback */
+	usc_RCmd( info, RCmd_SelectRicrRxFifostatus );
+
+	/* clear the Wordstatus bit so that status readback */
+	/* only reflects the status of this byte */
+	usc_OutReg( info, RICR+LSBONLY, (u16)(usc_InReg(info, RICR+LSBONLY) & ~BIT3 ));
+
+	/* flush the receive FIFO */
+
+	while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
+		int flag;
+
+		/* read one byte from RxFIFO */
+		outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
+		      info->io_base + CCAR );
+		DataByte = inb( info->io_base + CCAR );
+
+		/* get the status of the received byte */
+		status = usc_InReg(info, RCSR);
+		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
+				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
+			usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
+		
+		icount->rx++;
+		
+		flag = 0;
+		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
+				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
+			printk("rxerr=%04X\n",status);					
+			/* update error statistics */
+			if ( status & RXSTATUS_BREAK_RECEIVED ) {
+				status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR);
+				icount->brk++;
+			} else if (status & RXSTATUS_PARITY_ERROR) 
+				icount->parity++;
+			else if (status & RXSTATUS_FRAMING_ERROR)
+				icount->frame++;
+			else if (status & RXSTATUS_OVERRUN) {
+				/* must issue purge fifo cmd before */
+				/* 16C32 accepts more receive chars */
+				usc_RTCmd(info,RTCmd_PurgeRxFifo);
+				icount->overrun++;
+			}
+
+			/* discard char if tty control flags say so */					
+			if (status & info->ignore_status_mask)
+				continue;
+				
+			status &= info->read_status_mask;
+		
+			if (status & RXSTATUS_BREAK_RECEIVED) {
+				flag = TTY_BREAK;
+				if (info->port.flags & ASYNC_SAK)
+					do_SAK(tty);
+			} else if (status & RXSTATUS_PARITY_ERROR)
+				flag = TTY_PARITY;
+			else if (status & RXSTATUS_FRAMING_ERROR)
+				flag = TTY_FRAME;
+		}	/* end of if (error) */
+		tty_insert_flip_char(tty, DataByte, flag);
+		if (status & RXSTATUS_OVERRUN) {
+			/* Overrun is special, since it's
+			 * reported immediately, and doesn't
+			 * affect the current character
+			 */
+			work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		}
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_ISR ) {
+		printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
+			__FILE__,__LINE__,icount->rx,icount->brk,
+			icount->parity,icount->frame,icount->overrun);
+	}
+			
+	if(work)
+		tty_flip_buffer_push(tty);
+}
+
+/* mgsl_isr_misc()
+ * 
+ * 	Service a miscellaneous interrupt source.
+ * 	
+ * Arguments:		info		pointer to device extension (instance data)
+ * Return Value:	None
+ */
+static void mgsl_isr_misc( struct mgsl_struct *info )
+{
+	u16 status = usc_InReg( info, MISR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_misc status=%04X\n",
+			__FILE__,__LINE__,status);
+			
+	if ((status & MISCSTATUS_RCC_UNDERRUN) &&
+	    (info->params.mode == MGSL_MODE_HDLC)) {
+
+		/* turn off receiver and rx DMA */
+		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
+		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
+		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
+
+		/* schedule BH handler to restart receiver */
+		info->pending_bh |= BH_RECEIVE;
+		info->rx_rcc_underrun = true;
+	}
+
+	usc_ClearIrqPendingBits( info, MISC );
+	usc_UnlatchMiscstatusBits( info, status );
+
+}	/* end of mgsl_isr_misc() */
+
+/* mgsl_isr_null()
+ *
+ * 	Services undefined interrupt vectors from the
+ * 	USC. (hence this function SHOULD never be called)
+ * 
+ * Arguments:		info		pointer to device extension (instance data)
+ * Return Value:	None
+ */
+static void mgsl_isr_null( struct mgsl_struct *info )
+{
+
+}	/* end of mgsl_isr_null() */
+
+/* mgsl_isr_receive_dma()
+ * 
+ * 	Service a receive DMA channel interrupt.
+ * 	For this driver there are two sources of receive DMA interrupts
+ * 	as identified in the Receive DMA mode Register (RDMR):
+ * 
+ * 	BIT3	EOA/EOL		End of List, all receive buffers in receive
+ * 				buffer list have been filled (no more free buffers
+ * 				available). The DMA controller has shut down.
+ * 
+ * 	BIT2	EOB		End of Buffer. This interrupt occurs when a receive
+ * 				DMA buffer is terminated in response to completion
+ * 				of a good frame or a frame with errors. The status
+ * 				of the frame is stored in the buffer entry in the
+ * 				list of receive buffer entries.
+ * 
+ * Arguments:		info		pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_receive_dma( struct mgsl_struct *info )
+{
+	u16 status;
+	
+	/* clear interrupt pending and IUS bit for Rx DMA IRQ */
+	usc_OutDmaReg( info, CDIR, BIT9+BIT1 );
+
+	/* Read the receive DMA status to identify interrupt type. */
+	/* This also clears the status bits. */
+	status = usc_InDmaReg( info, RDMR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk("%s(%d):mgsl_isr_receive_dma(%s) status=%04X\n",
+			__FILE__,__LINE__,info->device_name,status);
+			
+	info->pending_bh |= BH_RECEIVE;
+	
+	if ( status & BIT3 ) {
+		info->rx_overflow = true;
+		info->icount.buf_overrun++;
+	}
+
+}	/* end of mgsl_isr_receive_dma() */
+
+/* mgsl_isr_transmit_dma()
+ *
+ *	This function services a transmit DMA channel interrupt.
+ *
+ *	For this driver there is one source of transmit DMA interrupts
+ *	as identified in the Transmit DMA Mode Register (TDMR):
+ *
+ *     	BIT2  EOB       End of Buffer. This interrupt occurs when a
+ *     			transmit DMA buffer has been emptied.
+ *
+ *     	The driver maintains enough transmit DMA buffers to hold at least
+ *     	one max frame size transmit frame. When operating in a buffered
+ *     	transmit mode, there may be enough transmit DMA buffers to hold at
+ *     	least two or more max frame size frames. On an EOB condition,
+ *     	determine if there are any queued transmit buffers and copy into
+ *     	transmit DMA buffers if we have room.
+ *
+ * Arguments:		info		pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+{
+	u16 status;
+
+	/* clear interrupt pending and IUS bit for Tx DMA IRQ */
+	usc_OutDmaReg(info, CDIR, BIT8+BIT0 );
+
+	/* Read the transmit DMA status to identify interrupt type. */
+	/* This also clears the status bits. */
+
+	status = usc_InDmaReg( info, TDMR );
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n",
+			__FILE__,__LINE__,info->device_name,status);
+
+	if ( status & BIT2 ) {
+		--info->tx_dma_buffers_used;
+
+		/* if there are transmit frames queued,
+		 *  try to load the next one
+		 */
+		if ( load_next_tx_holding_buffer(info) ) {
+			/* if call returns non-zero value, we have
+			 * at least one free tx holding buffer
+			 */
+			info->pending_bh |= BH_TRANSMIT;
+		}
+	}
+
+}	/* end of mgsl_isr_transmit_dma() */
+
+/* mgsl_interrupt()
+ * 
+ * 	Interrupt service routine entry point.
+ * 	
+ * Arguments:
+ * 
+ * 	irq		interrupt number that caused interrupt
+ * 	dev_id		device ID supplied during interrupt registration
+ * 	
+ * Return Value: None
+ */
+static irqreturn_t mgsl_interrupt(int dummy, void *dev_id)
+{
+	struct mgsl_struct *info = dev_id;
+	u16 UscVector;
+	u16 DmaVector;
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n",
+			__FILE__, __LINE__, info->irq_level);
+
+	spin_lock(&info->irq_spinlock);
+
+	for(;;) {
+		/* Read the interrupt vectors from hardware. */
+		UscVector = usc_InReg(info, IVR) >> 9;
+		DmaVector = usc_InDmaReg(info, DIVR);
+		
+		if ( debug_level >= DEBUG_LEVEL_ISR )	
+			printk("%s(%d):%s UscVector=%08X DmaVector=%08X\n",
+				__FILE__,__LINE__,info->device_name,UscVector,DmaVector);
+			
+		if ( !UscVector && !DmaVector )
+			break;
+			
+		/* Dispatch interrupt vector */
+		if ( UscVector )
+			(*UscIsrTable[UscVector])(info);
+		else if ( (DmaVector&(BIT10|BIT9)) == BIT10)
+			mgsl_isr_transmit_dma(info);
+		else
+			mgsl_isr_receive_dma(info);
+
+		if ( info->isr_overflow ) {
+			printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n",
+				__FILE__, __LINE__, info->device_name, info->irq_level);
+			usc_DisableMasterIrqBit(info);
+			usc_DisableDmaInterrupts(info,DICR_MASTER);
+			break;
+		}
+	}
+	
+	/* Request bottom half processing if there's something 
+	 * for it to do and the bh is not already running
+	 */
+
+	if ( info->pending_bh && !info->bh_running && !info->bh_requested ) {
+		if ( debug_level >= DEBUG_LEVEL_ISR )	
+			printk("%s(%d):%s queueing bh task.\n",
+				__FILE__,__LINE__,info->device_name);
+		schedule_work(&info->task);
+		info->bh_requested = true;
+	}
+
+	spin_unlock(&info->irq_spinlock);
+	
+	if ( debug_level >= DEBUG_LEVEL_ISR )	
+		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n",
+			__FILE__, __LINE__, info->irq_level);
+
+	return IRQ_HANDLED;
+}	/* end of mgsl_interrupt() */
+
+/* startup()
+ * 
+ * 	Initialize and start device.
+ * 	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	0 if success, otherwise error code
+ */
+static int startup(struct mgsl_struct * info)
+{
+	int retval = 0;
+	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name);
+		
+	if (info->port.flags & ASYNC_INITIALIZED)
+		return 0;
+	
+	if (!info->xmit_buf) {
+		/* allocate a page of memory for a transmit buffer */
+		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+		if (!info->xmit_buf) {
+			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
+				__FILE__,__LINE__,info->device_name);
+			return -ENOMEM;
+		}
+	}
+
+	info->pending_bh = 0;
+	
+	memset(&info->icount, 0, sizeof(info->icount));
+
+	setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info);
+	
+	/* Allocate and claim adapter resources */
+	retval = mgsl_claim_resources(info);
+	
+	/* perform existence check and diagnostics */
+	if ( !retval )
+		retval = mgsl_adapter_test(info);
+		
+	if ( retval ) {
+  		if (capable(CAP_SYS_ADMIN) && info->port.tty)
+			set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+		mgsl_release_resources(info);
+  		return retval;
+  	}
+
+	/* program hardware for current parameters */
+	mgsl_change_params(info);
+	
+	if (info->port.tty)
+		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+
+	info->port.flags |= ASYNC_INITIALIZED;
+	
+	return 0;
+	
+}	/* end of startup() */
+
+/* shutdown()
+ *
+ * Called by mgsl_close() and mgsl_hangup() to shutdown hardware
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void shutdown(struct mgsl_struct * info)
+{
+	unsigned long flags;
+	
+	if (!(info->port.flags & ASYNC_INITIALIZED))
+		return;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_shutdown(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	/* clear status wait queue because status changes */
+	/* can't happen after shutting down the hardware */
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+
+	del_timer_sync(&info->tx_timer);
+
+	if (info->xmit_buf) {
+		free_page((unsigned long) info->xmit_buf);
+		info->xmit_buf = NULL;
+	}
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_DisableMasterIrqBit(info);
+	usc_stop_receiver(info);
+	usc_stop_transmitter(info);
+	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
+		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
+	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
+	
+	/* Disable DMAEN (Port 7, Bit 14) */
+	/* This disconnects the DMA request signal from the ISA bus */
+	/* on the ISA adapter. This has no effect for the PCI adapter */
+	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
+	
+	/* Disable INTEN (Port 6, Bit12) */
+	/* This disconnects the IRQ request signal to the ISA bus */
+	/* on the ISA adapter. This has no effect for the PCI adapter */
+	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));
+	
+ 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+ 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+		usc_set_serial_signals(info);
+	}
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	mgsl_release_resources(info);	
+	
+	if (info->port.tty)
+		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+
+	info->port.flags &= ~ASYNC_INITIALIZED;
+	
+}	/* end of shutdown() */
+
+static void mgsl_program_hw(struct mgsl_struct *info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	
+	usc_stop_receiver(info);
+	usc_stop_transmitter(info);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	
+	if (info->params.mode == MGSL_MODE_HDLC ||
+	    info->params.mode == MGSL_MODE_RAW ||
+	    info->netcount)
+		usc_set_sync_mode(info);
+	else
+		usc_set_async_mode(info);
+		
+	usc_set_serial_signals(info);
+	
+	info->dcd_chkcount = 0;
+	info->cts_chkcount = 0;
+	info->ri_chkcount = 0;
+	info->dsr_chkcount = 0;
+
+	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);		
+	usc_EnableInterrupts(info, IO_PIN);
+	usc_get_serial_signals(info);
+		
+	if (info->netcount || info->port.tty->termios->c_cflag & CREAD)
+		usc_start_receiver(info);
+		
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+}
+
+/* Reconfigure adapter based on new parameters
+ */
+static void mgsl_change_params(struct mgsl_struct *info)
+{
+	unsigned cflag;
+	int bits_per_char;
+
+	if (!info->port.tty || !info->port.tty->termios)
+		return;
+		
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_change_params(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+	cflag = info->port.tty->termios->c_cflag;
+
+	/* if B0 rate (hangup) specified then negate DTR and RTS */
+	/* otherwise assert DTR and RTS */
+ 	if (cflag & CBAUD)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+	
+	/* byte size and parity */
+	
+	switch (cflag & CSIZE) {
+	      case CS5: info->params.data_bits = 5; break;
+	      case CS6: info->params.data_bits = 6; break;
+	      case CS7: info->params.data_bits = 7; break;
+	      case CS8: info->params.data_bits = 8; break;
+	      /* Never happens, but GCC is too dumb to figure it out */
+	      default:  info->params.data_bits = 7; break;
+	      }
+	      
+	if (cflag & CSTOPB)
+		info->params.stop_bits = 2;
+	else
+		info->params.stop_bits = 1;
+
+	info->params.parity = ASYNC_PARITY_NONE;
+	if (cflag & PARENB) {
+		if (cflag & PARODD)
+			info->params.parity = ASYNC_PARITY_ODD;
+		else
+			info->params.parity = ASYNC_PARITY_EVEN;
+#ifdef CMSPAR
+		if (cflag & CMSPAR)
+			info->params.parity = ASYNC_PARITY_SPACE;
+#endif
+	}
+
+	/* calculate number of jiffies to transmit a full
+	 * FIFO (32 bytes) at specified data rate
+	 */
+	bits_per_char = info->params.data_bits + 
+			info->params.stop_bits + 1;
+
+	/* if port data rate is set to 460800 or less then
+	 * allow tty settings to override, otherwise keep the
+	 * current data rate.
+	 */
+	if (info->params.data_rate <= 460800)
+		info->params.data_rate = tty_get_baud_rate(info->port.tty);
+	
+	if ( info->params.data_rate ) {
+		info->timeout = (32*HZ*bits_per_char) / 
+				info->params.data_rate;
+	}
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	if (cflag & CRTSCTS)
+		info->port.flags |= ASYNC_CTS_FLOW;
+	else
+		info->port.flags &= ~ASYNC_CTS_FLOW;
+		
+	if (cflag & CLOCAL)
+		info->port.flags &= ~ASYNC_CHECK_CD;
+	else
+		info->port.flags |= ASYNC_CHECK_CD;
+
+	/* process tty input control flags */
+	
+	info->read_status_mask = RXSTATUS_OVERRUN;
+	if (I_INPCK(info->port.tty))
+		info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;
+ 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
+ 		info->read_status_mask |= RXSTATUS_BREAK_RECEIVED;
+	
+	if (I_IGNPAR(info->port.tty))
+		info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;
+	if (I_IGNBRK(info->port.tty)) {
+		info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED;
+		/* If ignoring parity and break indicators, ignore 
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->port.tty))
+			info->ignore_status_mask |= RXSTATUS_OVERRUN;
+	}
+
+	mgsl_program_hw(info);
+
+}	/* end of mgsl_change_params() */
+
+/* mgsl_put_char()
+ * 
+ * 	Add a character to the transmit buffer.
+ * 	
+ * Arguments:		tty	pointer to tty information structure
+ * 			ch	character to add to transmit buffer
+ * 		
+ * Return Value:	None
+ */
+static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	int ret = 0;
+
+	if (debug_level >= DEBUG_LEVEL_INFO) {
+		printk(KERN_DEBUG "%s(%d):mgsl_put_char(%d) on %s\n",
+			__FILE__, __LINE__, ch, info->device_name);
+	}		
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
+		return 0;
+
+	if (!info->xmit_buf)
+		return 0;
+
+	spin_lock_irqsave(&info->irq_spinlock, flags);
+	
+	if ((info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active) {
+		if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
+			info->xmit_buf[info->xmit_head++] = ch;
+			info->xmit_head &= SERIAL_XMIT_SIZE-1;
+			info->xmit_cnt++;
+			ret = 1;
+		}
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
+	return ret;
+	
+}	/* end of mgsl_put_char() */
+
+/* mgsl_flush_chars()
+ * 
+ * 	Enable transmitter so remaining characters in the
+ * 	transmit buffer are sent.
+ * 	
+ * Arguments:		tty	pointer to tty information structure
+ * Return Value:	None
+ */
+static void mgsl_flush_chars(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+				
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n",
+			__FILE__,__LINE__,info->device_name,info->xmit_cnt);
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !info->xmit_buf)
+		return;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n",
+			__FILE__,__LINE__,info->device_name );
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	
+	if (!info->tx_active) {
+		if ( (info->params.mode == MGSL_MODE_HDLC ||
+			info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) {
+			/* operating in synchronous (frame oriented) mode */
+			/* copy data from circular xmit_buf to */
+			/* transmit DMA buffer. */
+			mgsl_load_tx_dma_buffer(info,
+				 info->xmit_buf,info->xmit_cnt);
+		}
+	 	usc_start_transmitter(info);
+	}
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+}	/* end of mgsl_flush_chars() */
+
+/* mgsl_write()
+ * 
+ * 	Send a block of data
+ * 	
+ * Arguments:
+ * 
+ * 	tty		pointer to tty information structure
+ * 	buf		pointer to buffer containing send data
+ * 	count		size of send data in bytes
+ * 	
+ * Return Value:	number of characters written
+ */
+static int mgsl_write(struct tty_struct * tty,
+		    const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_write(%s) count=%d\n",
+			__FILE__,__LINE__,info->device_name,count);
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
+		goto cleanup;
+
+	if (!info->xmit_buf)
+		goto cleanup;
+
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+			info->params.mode == MGSL_MODE_RAW ) {
+		/* operating in synchronous (frame oriented) mode */
+		/* operating in synchronous (frame oriented) mode */
+		if (info->tx_active) {
+
+			if ( info->params.mode == MGSL_MODE_HDLC ) {
+				ret = 0;
+				goto cleanup;
+			}
+			/* transmitter is actively sending data -
+			 * if we have multiple transmit dma and
+			 * holding buffers, attempt to queue this
+			 * frame for transmission at a later time.
+			 */
+			if (info->tx_holding_count >= info->num_tx_holding_buffers ) {
+				/* no tx holding buffers available */
+				ret = 0;
+				goto cleanup;
+			}
+
+			/* queue transmit frame request */
+			ret = count;
+			save_tx_buffer_request(info,buf,count);
+
+			/* if we have sufficient tx dma buffers,
+			 * load the next buffered tx request
+			 */
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			load_next_tx_holding_buffer(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			goto cleanup;
+		}
+	
+		/* if operating in HDLC LoopMode and the adapter  */
+		/* has yet to be inserted into the loop, we can't */
+		/* transmit					  */
+
+		if ( (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) &&
+			!usc_loopmode_active(info) )
+		{
+			ret = 0;
+			goto cleanup;
+		}
+
+		if ( info->xmit_cnt ) {
+			/* Send accumulated from send_char() calls */
+			/* as frame and wait before accepting more data. */
+			ret = 0;
+			
+			/* copy data from circular xmit_buf to */
+			/* transmit DMA buffer. */
+			mgsl_load_tx_dma_buffer(info,
+				info->xmit_buf,info->xmit_cnt);
+			if ( debug_level >= DEBUG_LEVEL_INFO )
+				printk( "%s(%d):mgsl_write(%s) sync xmit_cnt flushing\n",
+					__FILE__,__LINE__,info->device_name);
+		} else {
+			if ( debug_level >= DEBUG_LEVEL_INFO )
+				printk( "%s(%d):mgsl_write(%s) sync transmit accepted\n",
+					__FILE__,__LINE__,info->device_name);
+			ret = count;
+			info->xmit_cnt = count;
+			mgsl_load_tx_dma_buffer(info,buf,count);
+		}
+	} else {
+		while (1) {
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			c = min_t(int, count,
+				min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				spin_unlock_irqrestore(&info->irq_spinlock,flags);
+				break;
+			}
+			memcpy(info->xmit_buf + info->xmit_head, buf, c);
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+	}	
+	
+ 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		if (!info->tx_active)
+		 	usc_start_transmitter(info);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ 	}
+cleanup:	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_write(%s) returning=%d\n",
+			__FILE__,__LINE__,info->device_name,ret);
+			
+	return ret;
+	
+}	/* end of mgsl_write() */
+
+/* mgsl_write_room()
+ *
+ *	Return the count of free bytes in transmit buffer
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static int mgsl_write_room(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	int	ret;
+				
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room"))
+		return 0;
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+		
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_write_room(%s)=%d\n",
+			 __FILE__,__LINE__, info->device_name,ret );
+			 
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
+		/* operating in synchronous (frame oriented) mode */
+		if ( info->tx_active )
+			return 0;
+		else
+			return HDLC_MAX_FRAME_SIZE;
+	}
+	
+	return ret;
+	
+}	/* end of mgsl_write_room() */
+
+/* mgsl_chars_in_buffer()
+ *
+ *	Return the count of bytes in transmit buffer
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static int mgsl_chars_in_buffer(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+			 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_chars_in_buffer(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_chars_in_buffer"))
+		return 0;
+		
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_chars_in_buffer(%s)=%d\n",
+			 __FILE__,__LINE__, info->device_name,info->xmit_cnt );
+			 
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
+		/* operating in synchronous (frame oriented) mode */
+		if ( info->tx_active )
+			return info->max_frame_size;
+		else
+			return 0;
+	}
+			 
+	return info->xmit_cnt;
+}	/* end of mgsl_chars_in_buffer() */
+
+/* mgsl_flush_buffer()
+ *
+ *	Discard all data in the send buffer
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static void mgsl_flush_buffer(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_flush_buffer(%s) entry\n",
+			 __FILE__,__LINE__, info->device_name );
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_buffer"))
+		return;
+		
+	spin_lock_irqsave(&info->irq_spinlock,flags); 
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	del_timer(&info->tx_timer);	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+	tty_wakeup(tty);
+}
+
+/* mgsl_send_xchar()
+ *
+ *	Send a high-priority XON/XOFF character
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ *			ch	character to send
+ * Return Value:	None
+ */
+static void mgsl_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_send_xchar(%s,%d)\n",
+			 __FILE__,__LINE__, info->device_name, ch );
+			 
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_send_xchar"))
+		return;
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		if (!info->tx_enabled)
+		 	usc_start_transmitter(info);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	}
+}	/* end of mgsl_send_xchar() */
+
+/* mgsl_throttle()
+ * 
+ * 	Signal remote device to throttle send data (our receive data)
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static void mgsl_throttle(struct tty_struct * tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_throttle(%s) entry\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_throttle"))
+		return;
+	
+	if (I_IXOFF(tty))
+		mgsl_send_xchar(tty, STOP_CHAR(tty));
+ 
+ 	if (tty->termios->c_cflag & CRTSCTS) {
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		info->serial_signals &= ~SerialSignal_RTS;
+	 	usc_set_serial_signals(info);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	}
+}	/* end of mgsl_throttle() */
+
+/* mgsl_unthrottle()
+ * 
+ * 	Signal remote device to stop throttling send data (our receive data)
+ * 	
+ * Arguments:		tty	pointer to tty info structure
+ * Return Value:	None
+ */
+static void mgsl_unthrottle(struct tty_struct * tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_unthrottle(%s) entry\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_unthrottle"))
+		return;
+	
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			mgsl_send_xchar(tty, START_CHAR(tty));
+	}
+	
+ 	if (tty->termios->c_cflag & CRTSCTS) {
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		info->serial_signals |= SerialSignal_RTS;
+	 	usc_set_serial_signals(info);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	}
+	
+}	/* end of mgsl_unthrottle() */
+
+/* mgsl_get_stats()
+ * 
+ * 	get the current serial parameters information
+ *
+ * Arguments:	info		pointer to device instance data
+ * 		user_icount	pointer to buffer to hold returned stats
+ * 	
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount)
+{
+	int err;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_get_params(%s)\n",
+			 __FILE__,__LINE__, info->device_name);
+			
+	if (!user_icount) {
+		memset(&info->icount, 0, sizeof(info->icount));
+	} else {
+		mutex_lock(&info->port.mutex);
+		COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+		mutex_unlock(&info->port.mutex);
+		if (err)
+			return -EFAULT;
+	}
+	
+	return 0;
+	
+}	/* end of mgsl_get_stats() */
+
+/* mgsl_get_params()
+ * 
+ * 	get the current serial parameters information
+ *
+ * Arguments:	info		pointer to device instance data
+ * 		user_params	pointer to buffer to hold returned params
+ * 	
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params)
+{
+	int err;
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_get_params(%s)\n",
+			 __FILE__,__LINE__, info->device_name);
+			
+	mutex_lock(&info->port.mutex);
+	COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
+	mutex_unlock(&info->port.mutex);
+	if (err) {
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n",
+				__FILE__,__LINE__,info->device_name);
+		return -EFAULT;
+	}
+	
+	return 0;
+	
+}	/* end of mgsl_get_params() */
+
+/* mgsl_set_params()
+ * 
+ * 	set the serial parameters
+ * 	
+ * Arguments:
+ * 
+ * 	info		pointer to device instance data
+ * 	new_params	user buffer containing new serial params
+ *
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params)
+{
+ 	unsigned long flags;
+	MGSL_PARAMS tmp_params;
+	int err;
+ 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_set_params %s\n", __FILE__,__LINE__,
+			info->device_name );
+	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));
+	if (err) {
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk( "%s(%d):mgsl_set_params(%s) user buffer copy failed\n",
+				__FILE__,__LINE__,info->device_name);
+		return -EFAULT;
+	}
+	
+	mutex_lock(&info->port.mutex);
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+ 	mgsl_change_params(info);
+	mutex_unlock(&info->port.mutex);
+	
+	return 0;
+	
+}	/* end of mgsl_set_params() */
+
+/* mgsl_get_txidle()
+ * 
+ * 	get the current transmit idle mode
+ *
+ * Arguments:	info		pointer to device instance data
+ * 		idle_mode	pointer to buffer to hold returned idle mode
+ * 	
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode)
+{
+	int err;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_get_txidle(%s)=%d\n",
+			 __FILE__,__LINE__, info->device_name, info->idle_mode);
+			
+	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));
+	if (err) {
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk( "%s(%d):mgsl_get_txidle(%s) user buffer copy failed\n",
+				__FILE__,__LINE__,info->device_name);
+		return -EFAULT;
+	}
+	
+	return 0;
+	
+}	/* end of mgsl_get_txidle() */
+
+/* mgsl_set_txidle()	service ioctl to set transmit idle mode
+ * 	
+ * Arguments:	 	info		pointer to device instance data
+ * 			idle_mode	new idle mode
+ *
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode)
+{
+ 	unsigned long flags;
+ 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_set_txidle(%s,%d)\n", __FILE__,__LINE__,
+			info->device_name, idle_mode );
+			
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	info->idle_mode = idle_mode;
+	usc_set_txidle( info );
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	return 0;
+	
+}	/* end of mgsl_set_txidle() */
+
+/* mgsl_txenable()
+ * 
+ * 	enable or disable the transmitter
+ * 	
+ * Arguments:
+ * 
+ * 	info		pointer to device instance data
+ * 	enable		1 = enable, 0 = disable
+ *
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_txenable(struct mgsl_struct * info, int enable)
+{
+ 	unsigned long flags;
+ 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_txenable(%s,%d)\n", __FILE__,__LINE__,
+			info->device_name, enable);
+			
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if ( enable ) {
+		if ( !info->tx_enabled ) {
+
+			usc_start_transmitter(info);
+			/*--------------------------------------------------
+			 * if HDLC/SDLC Loop mode, attempt to insert the
+			 * station in the 'loop' by setting CMR:13. Upon
+			 * receipt of the next GoAhead (RxAbort) sequence,
+			 * the OnLoop indicator (CCSR:7) should go active
+			 * to indicate that we are on the loop
+			 *--------------------------------------------------*/
+			if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+				usc_loopmode_insert_request( info );
+		}
+	} else {
+		if ( info->tx_enabled )
+			usc_stop_transmitter(info);
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	return 0;
+	
+}	/* end of mgsl_txenable() */
+
+/* mgsl_txabort()	abort send HDLC frame
+ * 	
+ * Arguments:	 	info		pointer to device instance data
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_txabort(struct mgsl_struct * info)
+{
+ 	unsigned long flags;
+ 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_txabort(%s)\n", __FILE__,__LINE__,
+			info->device_name);
+			
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC )
+	{
+		if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+			usc_loopmode_cancel_transmit( info );
+		else
+			usc_TCmd(info,TCmd_SendAbort);
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	return 0;
+	
+}	/* end of mgsl_txabort() */
+
+/* mgsl_rxenable() 	enable or disable the receiver
+ * 	
+ * Arguments:	 	info		pointer to device instance data
+ * 			enable		1 = enable, 0 = disable
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_rxenable(struct mgsl_struct * info, int enable)
+{
+ 	unsigned long flags;
+ 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_rxenable(%s,%d)\n", __FILE__,__LINE__,
+			info->device_name, enable);
+			
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if ( enable ) {
+		if ( !info->rx_enabled )
+			usc_start_receiver(info);
+	} else {
+		if ( info->rx_enabled )
+			usc_stop_receiver(info);
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	return 0;
+	
+}	/* end of mgsl_rxenable() */
+
+/* mgsl_wait_event() 	wait for specified event to occur
+ * 	
+ * Arguments:	 	info	pointer to device instance data
+ * 			mask	pointer to bitmask of events to wait for
+ * Return Value:	0 	if successful and bit mask updated with
+ *				of events triggerred,
+ * 			otherwise error code
+ */
+static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
+{
+ 	unsigned long flags;
+	int s;
+	int rc=0;
+	struct mgsl_icount cprev, cnow;
+	int events;
+	int mask;
+	struct	_input_signal_events oldsigs, newsigs;
+	DECLARE_WAITQUEUE(wait, current);
+
+	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
+	if (rc) {
+		return  -EFAULT;
+	}
+		 
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_wait_event(%s,%d)\n", __FILE__,__LINE__,
+			info->device_name, mask);
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+
+	/* return immediately if state matches requested events */
+	usc_get_serial_signals(info);
+	s = info->serial_signals;
+	events = mask &
+		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
+ 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
+		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
+		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
+	if (events) {
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		goto exit;
+	}
+
+	/* save current irq counts */
+	cprev = info->icount;
+	oldsigs = info->input_signal_events;
+	
+	/* enable hunt and idle irqs if needed */
+	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+		u16 oldreg = usc_InReg(info,RICR);
+		u16 newreg = oldreg +
+			 (mask & MgslEvent_ExitHuntMode ? RXSTATUS_EXITED_HUNT:0) +
+			 (mask & MgslEvent_IdleReceived ? RXSTATUS_IDLE_RECEIVED:0);
+		if (oldreg != newreg)
+			usc_OutReg(info, RICR, newreg);
+	}
+	
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&info->event_wait_q, &wait);
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+			
+		/* get current irq counts */
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		cnow = info->icount;
+		newsigs = info->input_signal_events;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
+		    newsigs.dsr_down == oldsigs.dsr_down &&
+		    newsigs.dcd_up   == oldsigs.dcd_up   &&
+		    newsigs.dcd_down == oldsigs.dcd_down &&
+		    newsigs.cts_up   == oldsigs.cts_up   &&
+		    newsigs.cts_down == oldsigs.cts_down &&
+		    newsigs.ri_up    == oldsigs.ri_up    &&
+		    newsigs.ri_down  == oldsigs.ri_down  &&
+		    cnow.exithunt    == cprev.exithunt   &&
+		    cnow.rxidle      == cprev.rxidle) {
+			rc = -EIO;
+			break;
+		}
+
+		events = mask &
+			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
+			(newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
+			(newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
+			(newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
+			(newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
+			(newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
+			(newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
+			(newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
+			(cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
+			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
+		if (events)
+			break;
+		
+		cprev = cnow;
+		oldsigs = newsigs;
+	}
+	
+	remove_wait_queue(&info->event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+
+	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		if (!waitqueue_active(&info->event_wait_q)) {
+			/* disable enable exit hunt mode/idle rcvd IRQs */
+			usc_OutReg(info, RICR, usc_InReg(info,RICR) &
+				~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED));
+		}
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	}
+exit:
+	if ( rc == 0 )
+		PUT_USER(rc, events, mask_ptr);
+		
+	return rc;
+	
+}	/* end of mgsl_wait_event() */
+
+static int modem_input_wait(struct mgsl_struct *info,int arg)
+{
+ 	unsigned long flags;
+	int rc;
+	struct mgsl_icount cprev, cnow;
+	DECLARE_WAITQUEUE(wait, current);
+
+	/* save current irq counts */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	cprev = info->icount;
+	add_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+
+		/* get new irq counts */
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		cnow = info->icount;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+			rc = -EIO;
+			break;
+		}
+
+		/* check for change in caller specified modem input */
+		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
+		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
+		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
+		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
+			rc = 0;
+			break;
+		}
+
+		cprev = cnow;
+	}
+	remove_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+	return rc;
+}
+
+/* return the state of the serial control and status signals
+ */
+static int tiocmget(struct tty_struct *tty)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned int result;
+ 	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+ 	usc_get_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
+		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
+		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
+		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
+		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
+		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s tiocmget() value=%08X\n",
+			 __FILE__,__LINE__, info->device_name, result );
+	return result;
+}
+
+/* set modem control signals (DTR/RTS)
+ */
+static int tiocmset(struct tty_struct *tty,
+				    unsigned int set, unsigned int clear)
+{
+	struct mgsl_struct *info = tty->driver_data;
+ 	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s tiocmset(%x,%x)\n",
+			__FILE__,__LINE__,info->device_name, set, clear);
+
+	if (set & TIOCM_RTS)
+		info->serial_signals |= SerialSignal_RTS;
+	if (set & TIOCM_DTR)
+		info->serial_signals |= SerialSignal_DTR;
+	if (clear & TIOCM_RTS)
+		info->serial_signals &= ~SerialSignal_RTS;
+	if (clear & TIOCM_DTR)
+		info->serial_signals &= ~SerialSignal_DTR;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+ 	usc_set_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return 0;
+}
+
+/* mgsl_break()		Set or clear transmit break condition
+ *
+ * Arguments:		tty		pointer to tty instance data
+ *			break_state	-1=set break condition, 0=clear
+ * Return Value:	error code
+ */
+static int mgsl_break(struct tty_struct *tty, int break_state)
+{
+	struct mgsl_struct * info = tty->driver_data;
+	unsigned long flags;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_break(%s,%d)\n",
+			 __FILE__,__LINE__, info->device_name, break_state);
+			 
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
+		return -EINVAL;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+ 	if (break_state == -1)
+		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) | BIT7));
+	else 
+		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	return 0;
+	
+}	/* end of mgsl_break() */
+
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ *     RI where only 0->1 is counted.
+ */
+static int msgl_get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+
+{
+	struct mgsl_struct * info = tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+	return 0;
+}
+
+/* mgsl_ioctl()	Service an IOCTL request
+ * 	
+ * Arguments:
+ * 
+ * 	tty	pointer to tty instance data
+ * 	cmd	IOCTL command code
+ * 	arg	command argument/context
+ * 	
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_ioctl(struct tty_struct *tty,
+		    unsigned int cmd, unsigned long arg)
+{
+	struct mgsl_struct * info = tty->driver_data;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
+			info->device_name, cmd );
+	
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCMIWAIT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	return mgsl_ioctl_common(info, cmd, arg);
+}
+
+static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	
+	switch (cmd) {
+		case MGSL_IOCGPARAMS:
+			return mgsl_get_params(info, argp);
+		case MGSL_IOCSPARAMS:
+			return mgsl_set_params(info, argp);
+		case MGSL_IOCGTXIDLE:
+			return mgsl_get_txidle(info, argp);
+		case MGSL_IOCSTXIDLE:
+			return mgsl_set_txidle(info,(int)arg);
+		case MGSL_IOCTXENABLE:
+			return mgsl_txenable(info,(int)arg);
+		case MGSL_IOCRXENABLE:
+			return mgsl_rxenable(info,(int)arg);
+		case MGSL_IOCTXABORT:
+			return mgsl_txabort(info);
+		case MGSL_IOCGSTATS:
+			return mgsl_get_stats(info, argp);
+		case MGSL_IOCWAITEVENT:
+			return mgsl_wait_event(info, argp);
+		case MGSL_IOCLOOPTXDONE:
+			return mgsl_loopmode_send_done(info);
+		/* Wait for modem input (DCD,RI,DSR,CTS) change
+		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
+		 */
+		case TIOCMIWAIT:
+			return modem_input_wait(info,(int)arg);
+
+		default:
+			return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+/* mgsl_set_termios()
+ * 
+ * 	Set new termios settings
+ * 	
+ * Arguments:
+ * 
+ * 	tty		pointer to tty structure
+ * 	termios		pointer to buffer to hold returned old termios
+ * 	
+ * Return Value:		None
+ */
+static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct mgsl_struct *info = tty->driver_data;
+	unsigned long flags;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
+			tty->driver->name );
+	
+	mgsl_change_params(info);
+
+	/* Handle transition to B0 status */
+	if (old_termios->c_cflag & CBAUD &&
+	    !(tty->termios->c_cflag & CBAUD)) {
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+	 	usc_set_serial_signals(info);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	}
+	
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    tty->termios->c_cflag & CBAUD) {
+		info->serial_signals |= SerialSignal_DTR;
+ 		if (!(tty->termios->c_cflag & CRTSCTS) || 
+ 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			info->serial_signals |= SerialSignal_RTS;
+ 		}
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+	 	usc_set_serial_signals(info);
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	}
+	
+	/* Handle turning off CRTSCTS */
+	if (old_termios->c_cflag & CRTSCTS &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		mgsl_start(tty);
+	}
+
+}	/* end of mgsl_set_termios() */
+
+/* mgsl_close()
+ * 
+ * 	Called when port is closed. Wait for remaining data to be
+ * 	sent. Disable port and free resources.
+ * 	
+ * Arguments:
+ * 
+ * 	tty	pointer to open tty structure
+ * 	filp	pointer to open file object
+ * 	
+ * Return Value:	None
+ */
+static void mgsl_close(struct tty_struct *tty, struct file * filp)
+{
+	struct mgsl_struct * info = tty->driver_data;
+
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_close"))
+		return;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
+			 __FILE__,__LINE__, info->device_name, info->port.count);
+
+	if (tty_port_close_start(&info->port, tty, filp) == 0)			 
+		goto cleanup;
+
+	mutex_lock(&info->port.mutex);
+ 	if (info->port.flags & ASYNC_INITIALIZED)
+ 		mgsl_wait_until_sent(tty, info->timeout);
+	mgsl_flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	shutdown(info);
+	mutex_unlock(&info->port.mutex);
+
+	tty_port_close_end(&info->port, tty);	
+	info->port.tty = NULL;
+cleanup:			
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__,
+			tty->driver->name, info->port.count);
+			
+}	/* end of mgsl_close() */
+
+/* mgsl_wait_until_sent()
+ *
+ *	Wait until the transmitter is empty.
+ *
+ * Arguments:
+ *
+ *	tty		pointer to tty info structure
+ *	timeout		time to wait for send completion
+ *
+ * Return Value:	None
+ */
+static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct mgsl_struct * info = tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+
+	if (!info )
+		return;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_wait_until_sent(%s) entry\n",
+			 __FILE__,__LINE__, info->device_name );
+      
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_wait_until_sent"))
+		return;
+
+	if (!(info->port.flags & ASYNC_INITIALIZED))
+		goto exit;
+	 
+	orig_jiffies = jiffies;
+      
+	/* Set check interval to 1/5 of estimated time to
+	 * send a character, and make it at least 1. The check
+	 * interval should also be less than the timeout.
+	 * Note: use tight timings here to satisfy the NIST-PCTS.
+	 */ 
+
+	if ( info->params.data_rate ) {
+	       	char_time = info->timeout/(32 * 5);
+		if (!char_time)
+			char_time++;
+	} else
+		char_time = 1;
+		
+	if (timeout)
+		char_time = min_t(unsigned long, char_time, timeout);
+		
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
+		while (info->tx_active) {
+			msleep_interruptible(jiffies_to_msecs(char_time));
+			if (signal_pending(current))
+				break;
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
+				break;
+		}
+	} else {
+		while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) &&
+			info->tx_enabled) {
+			msleep_interruptible(jiffies_to_msecs(char_time));
+			if (signal_pending(current))
+				break;
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
+				break;
+		}
+	}
+      
+exit:
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_wait_until_sent(%s) exit\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+}	/* end of mgsl_wait_until_sent() */
+
+/* mgsl_hangup()
+ *
+ *	Called by tty_hangup() when a hangup is signaled.
+ *	This is the same as to closing all open files for the port.
+ *
+ * Arguments:		tty	pointer to associated tty object
+ * Return Value:	None
+ */
+static void mgsl_hangup(struct tty_struct *tty)
+{
+	struct mgsl_struct * info = tty->driver_data;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_hangup(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_hangup"))
+		return;
+
+	mgsl_flush_buffer(tty);
+	shutdown(info);
+	
+	info->port.count = 0;	
+	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+	info->port.tty = NULL;
+
+	wake_up_interruptible(&info->port.open_wait);
+	
+}	/* end of mgsl_hangup() */
+
+/*
+ * carrier_raised()
+ *
+ *	Return true if carrier is raised
+ */
+
+static int carrier_raised(struct tty_port *port)
+{
+	unsigned long flags;
+	struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
+	
+	spin_lock_irqsave(&info->irq_spinlock, flags);
+ 	usc_get_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
+	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
+}
+
+static void dtr_rts(struct tty_port *port, int on)
+{
+	struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (on)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+ 	usc_set_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+}
+
+
+/* block_til_ready()
+ * 
+ * 	Block the current process until the specified port
+ * 	is ready to be opened.
+ * 	
+ * Arguments:
+ * 
+ * 	tty		pointer to tty info structure
+ * 	filp		pointer to open file object
+ * 	info		pointer to device instance data
+ * 	
+ * Return Value:	0 if success, otherwise error code
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   struct mgsl_struct *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int		retval;
+	bool		do_clocal = false;
+	bool		extra_count = false;
+	unsigned long	flags;
+	int		dcd;
+	struct tty_port *port = &info->port;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):block_til_ready on %s\n",
+			 __FILE__,__LINE__, tty->driver->name );
+
+	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+		/* nonblock mode is set or port is not enabled */
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (tty->termios->c_cflag & CLOCAL)
+		do_clocal = true;
+
+	/* Wait for carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, port->count is dropped by one, so that
+	 * mgsl_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	 
+	retval = 0;
+	add_wait_queue(&port->open_wait, &wait);
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):block_til_ready before block on %s count=%d\n",
+			 __FILE__,__LINE__, tty->driver->name, port->count );
+
+	spin_lock_irqsave(&info->irq_spinlock, flags);
+	if (!tty_hung_up_p(filp)) {
+		extra_count = true;
+		port->count--;
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
+	port->blocked_open++;
+	
+	while (1) {
+		if (tty->termios->c_cflag & CBAUD)
+			tty_port_raise_dtr_rts(port);
+		
+		set_current_state(TASK_INTERRUPTIBLE);
+		
+		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
+			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
+					-EAGAIN : -ERESTARTSYS;
+			break;
+		}
+		
+		dcd = tty_port_carrier_raised(&info->port);
+		
+ 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
+ 			break;
+			
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		
+		if (debug_level >= DEBUG_LEVEL_INFO)
+			printk("%s(%d):block_til_ready blocking on %s count=%d\n",
+				 __FILE__,__LINE__, tty->driver->name, port->count );
+				 
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+	
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->open_wait, &wait);
+	
+	/* FIXME: Racy on hangup during close wait */
+	if (extra_count)
+		port->count++;
+	port->blocked_open--;
+	
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
+			 __FILE__,__LINE__, tty->driver->name, port->count );
+			 
+	if (!retval)
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+		
+	return retval;
+	
+}	/* end of block_til_ready() */
+
+/* mgsl_open()
+ *
+ *	Called when a port is opened.  Init and enable port.
+ *	Perform serial-specific initialization for the tty structure.
+ *
+ * Arguments:		tty	pointer to tty info structure
+ *			filp	associated file pointer
+ *
+ * Return Value:	0 if success, otherwise error code
+ */
+static int mgsl_open(struct tty_struct *tty, struct file * filp)
+{
+	struct mgsl_struct	*info;
+	int 			retval, line;
+	unsigned long flags;
+
+	/* verify range of specified line number */	
+	line = tty->index;
+	if ((line < 0) || (line >= mgsl_device_count)) {
+		printk("%s(%d):mgsl_open with invalid line #%d.\n",
+			__FILE__,__LINE__,line);
+		return -ENODEV;
+	}
+
+	/* find the info structure for the specified line */
+	info = mgsl_device_list;
+	while(info && info->line != line)
+		info = info->next_device;
+	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
+		return -ENODEV;
+	
+	tty->driver_data = info;
+	info->port.tty = tty;
+		
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
+			 __FILE__,__LINE__,tty->driver->name, info->port.count);
+
+	/* If port is closing, signal caller to try again */
+	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
+		if (info->port.flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->port.close_wait);
+		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+		goto cleanup;
+	}
+	
+	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	spin_lock_irqsave(&info->netlock, flags);
+	if (info->netcount) {
+		retval = -EBUSY;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		goto cleanup;
+	}
+	info->port.count++;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	if (info->port.count == 1) {
+		/* 1st open on this device, init hardware */
+		retval = startup(info);
+		if (retval < 0)
+			goto cleanup;
+	}
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+		if (debug_level >= DEBUG_LEVEL_INFO)
+			printk("%s(%d):block_til_ready(%s) returned %d\n",
+				 __FILE__,__LINE__, info->device_name, retval);
+		goto cleanup;
+	}
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):mgsl_open(%s) success\n",
+			 __FILE__,__LINE__, info->device_name);
+	retval = 0;
+	
+cleanup:			
+	if (retval) {
+		if (tty->count == 1)
+			info->port.tty = NULL; /* tty layer will release tty struct */
+		if(info->port.count)
+			info->port.count--;
+	}
+	
+	return retval;
+	
+}	/* end of mgsl_open() */
+
+/*
+ * /proc fs routines....
+ */
+
+static inline void line_info(struct seq_file *m, struct mgsl_struct *info)
+{
+	char	stat_buf[30];
+	unsigned long flags;
+
+	if (info->bus_type == MGSL_BUS_TYPE_PCI) {
+		seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
+			info->device_name, info->io_base, info->irq_level,
+			info->phys_memory_base, info->phys_lcr_base);
+	} else {
+		seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d",
+			info->device_name, info->io_base, 
+			info->irq_level, info->dma_level);
+	}
+
+	/* output current serial signal states */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+ 	usc_get_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (info->serial_signals & SerialSignal_RTS)
+		strcat(stat_buf, "|RTS");
+	if (info->serial_signals & SerialSignal_CTS)
+		strcat(stat_buf, "|CTS");
+	if (info->serial_signals & SerialSignal_DTR)
+		strcat(stat_buf, "|DTR");
+	if (info->serial_signals & SerialSignal_DSR)
+		strcat(stat_buf, "|DSR");
+	if (info->serial_signals & SerialSignal_DCD)
+		strcat(stat_buf, "|CD");
+	if (info->serial_signals & SerialSignal_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->params.mode == MGSL_MODE_HDLC ||
+	    info->params.mode == MGSL_MODE_RAW ) {
+		seq_printf(m, " HDLC txok:%d rxok:%d",
+			      info->icount.txok, info->icount.rxok);
+		if (info->icount.txunder)
+			seq_printf(m, " txunder:%d", info->icount.txunder);
+		if (info->icount.txabort)
+			seq_printf(m, " txabort:%d", info->icount.txabort);
+		if (info->icount.rxshort)
+			seq_printf(m, " rxshort:%d", info->icount.rxshort);
+		if (info->icount.rxlong)
+			seq_printf(m, " rxlong:%d", info->icount.rxlong);
+		if (info->icount.rxover)
+			seq_printf(m, " rxover:%d", info->icount.rxover);
+		if (info->icount.rxcrc)
+			seq_printf(m, " rxcrc:%d", info->icount.rxcrc);
+	} else {
+		seq_printf(m, " ASYNC tx:%d rx:%d",
+			      info->icount.tx, info->icount.rx);
+		if (info->icount.frame)
+			seq_printf(m, " fe:%d", info->icount.frame);
+		if (info->icount.parity)
+			seq_printf(m, " pe:%d", info->icount.parity);
+		if (info->icount.brk)
+			seq_printf(m, " brk:%d", info->icount.brk);
+		if (info->icount.overrun)
+			seq_printf(m, " oe:%d", info->icount.overrun);
+	}
+	
+	/* Append serial signal status to end */
+	seq_printf(m, " %s\n", stat_buf+1);
+	
+	seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
+	 info->tx_active,info->bh_requested,info->bh_running,
+	 info->pending_bh);
+	 
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	{	
+	u16 Tcsr = usc_InReg( info, TCSR );
+	u16 Tdmr = usc_InDmaReg( info, TDMR );
+	u16 Ticr = usc_InReg( info, TICR );
+	u16 Rscr = usc_InReg( info, RCSR );
+	u16 Rdmr = usc_InDmaReg( info, RDMR );
+	u16 Ricr = usc_InReg( info, RICR );
+	u16 Icr = usc_InReg( info, ICR );
+	u16 Dccr = usc_InReg( info, DCCR );
+	u16 Tmr = usc_InReg( info, TMR );
+	u16 Tccr = usc_InReg( info, TCCR );
+	u16 Ccar = inw( info->io_base + CCAR );
+	seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n"
+                        "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n",
+	 		Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar );
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+}
+
+/* Called to print information about devices */
+static int mgsl_proc_show(struct seq_file *m, void *v)
+{
+	struct mgsl_struct *info;
+	
+	seq_printf(m, "synclink driver:%s\n", driver_version);
+	
+	info = mgsl_device_list;
+	while( info ) {
+		line_info(m, info);
+		info = info->next_device;
+	}
+	return 0;
+}
+
+static int mgsl_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mgsl_proc_show, NULL);
+}
+
+static const struct file_operations mgsl_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mgsl_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/* mgsl_allocate_dma_buffers()
+ * 
+ * 	Allocate and format DMA buffers (ISA adapter)
+ * 	or format shared memory buffers (PCI adapter).
+ * 
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	0 if success, otherwise error
+ */
+static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
+{
+	unsigned short BuffersPerFrame;
+
+	info->last_mem_alloc = 0;
+
+	/* Calculate the number of DMA buffers necessary to hold the */
+	/* largest allowable frame size. Note: If the max frame size is */
+	/* not an even multiple of the DMA buffer size then we need to */
+	/* round the buffer count per frame up one. */
+
+	BuffersPerFrame = (unsigned short)(info->max_frame_size/DMABUFFERSIZE);
+	if ( info->max_frame_size % DMABUFFERSIZE )
+		BuffersPerFrame++;
+
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		/*
+		 * The PCI adapter has 256KBytes of shared memory to use.
+		 * This is 64 PAGE_SIZE buffers.
+		 *
+		 * The first page is used for padding at this time so the
+		 * buffer list does not begin at offset 0 of the PCI
+		 * adapter's shared memory.
+		 *
+		 * The 2nd page is used for the buffer list. A 4K buffer
+		 * list can hold 128 DMA_BUFFER structures at 32 bytes
+		 * each.
+		 *
+		 * This leaves 62 4K pages.
+		 *
+		 * The next N pages are used for transmit frame(s). We
+		 * reserve enough 4K page blocks to hold the required
+		 * number of transmit dma buffers (num_tx_dma_buffers),
+		 * each of MaxFrameSize size.
+		 *
+		 * Of the remaining pages (62-N), determine how many can
+		 * be used to receive full MaxFrameSize inbound frames
+		 */
+		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
+		info->rx_buffer_count = 62 - info->tx_buffer_count;
+	} else {
+		/* Calculate the number of PAGE_SIZE buffers needed for */
+		/* receive and transmit DMA buffers. */
+
+
+		/* Calculate the number of DMA buffers necessary to */
+		/* hold 7 max size receive frames and one max size transmit frame. */
+		/* The receive buffer count is bumped by one so we avoid an */
+		/* End of List condition if all receive buffers are used when */
+		/* using linked list DMA buffers. */
+
+		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
+		info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
+		
+		/* 
+		 * limit total TxBuffers & RxBuffers to 62 4K total 
+		 * (ala PCI Allocation) 
+		 */
+		
+		if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 )
+			info->rx_buffer_count = 62 - info->tx_buffer_count;
+
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",
+			__FILE__,__LINE__, info->tx_buffer_count,info->rx_buffer_count);
+	
+	if ( mgsl_alloc_buffer_list_memory( info ) < 0 ||
+		  mgsl_alloc_frame_memory(info, info->rx_buffer_list, info->rx_buffer_count) < 0 || 
+		  mgsl_alloc_frame_memory(info, info->tx_buffer_list, info->tx_buffer_count) < 0 || 
+		  mgsl_alloc_intermediate_rxbuffer_memory(info) < 0  ||
+		  mgsl_alloc_intermediate_txbuffer_memory(info) < 0 ) {
+		printk("%s(%d):Can't allocate DMA buffer memory\n",__FILE__,__LINE__);
+		return -ENOMEM;
+	}
+	
+	mgsl_reset_rx_dma_buffers( info );
+  	mgsl_reset_tx_dma_buffers( info );
+
+	return 0;
+
+}	/* end of mgsl_allocate_dma_buffers() */
+
+/*
+ * mgsl_alloc_buffer_list_memory()
+ * 
+ * Allocate a common DMA buffer for use as the
+ * receive and transmit buffer lists.
+ * 
+ * A buffer list is a set of buffer entries where each entry contains
+ * a pointer to an actual buffer and a pointer to the next buffer entry
+ * (plus some other info about the buffer).
+ * 
+ * The buffer entries for a list are built to form a circular list so
+ * that when the entire list has been traversed you start back at the
+ * beginning.
+ * 
+ * This function allocates memory for just the buffer entries.
+ * The links (pointer to next entry) are filled in with the physical
+ * address of the next entry so the adapter can navigate the list
+ * using bus master DMA. The pointers to the actual buffers are filled
+ * out later when the actual buffers are allocated.
+ * 
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	0 if success, otherwise error
+ */
+static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
+{
+	unsigned int i;
+
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		/* PCI adapter uses shared memory. */
+		info->buffer_list = info->memory_base + info->last_mem_alloc;
+		info->buffer_list_phys = info->last_mem_alloc;
+		info->last_mem_alloc += BUFFERLISTSIZE;
+	} else {
+		/* ISA adapter uses system memory. */
+		/* The buffer lists are allocated as a common buffer that both */
+		/* the processor and adapter can access. This allows the driver to */
+		/* inspect portions of the buffer while other portions are being */
+		/* updated by the adapter using Bus Master DMA. */
+
+		info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL);
+		if (info->buffer_list == NULL)
+			return -ENOMEM;
+		info->buffer_list_phys = (u32)(info->buffer_list_dma_addr);
+	}
+
+	/* We got the memory for the buffer entry lists. */
+	/* Initialize the memory block to all zeros. */
+	memset( info->buffer_list, 0, BUFFERLISTSIZE );
+
+	/* Save virtual address pointers to the receive and */
+	/* transmit buffer lists. (Receive 1st). These pointers will */
+	/* be used by the processor to access the lists. */
+	info->rx_buffer_list = (DMABUFFERENTRY *)info->buffer_list;
+	info->tx_buffer_list = (DMABUFFERENTRY *)info->buffer_list;
+	info->tx_buffer_list += info->rx_buffer_count;
+
+	/*
+	 * Build the links for the buffer entry lists such that
+	 * two circular lists are built. (Transmit and Receive).
+	 *
+	 * Note: the links are physical addresses
+	 * which are read by the adapter to determine the next
+	 * buffer entry to use.
+	 */
+
+	for ( i = 0; i < info->rx_buffer_count; i++ ) {
+		/* calculate and store physical address of this buffer entry */
+		info->rx_buffer_list[i].phys_entry =
+			info->buffer_list_phys + (i * sizeof(DMABUFFERENTRY));
+
+		/* calculate and store physical address of */
+		/* next entry in cirular list of entries */
+
+		info->rx_buffer_list[i].link = info->buffer_list_phys;
+
+		if ( i < info->rx_buffer_count - 1 )
+			info->rx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY);
+	}
+
+	for ( i = 0; i < info->tx_buffer_count; i++ ) {
+		/* calculate and store physical address of this buffer entry */
+		info->tx_buffer_list[i].phys_entry = info->buffer_list_phys +
+			((info->rx_buffer_count + i) * sizeof(DMABUFFERENTRY));
+
+		/* calculate and store physical address of */
+		/* next entry in cirular list of entries */
+
+		info->tx_buffer_list[i].link = info->buffer_list_phys +
+			info->rx_buffer_count * sizeof(DMABUFFERENTRY);
+
+		if ( i < info->tx_buffer_count - 1 )
+			info->tx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY);
+	}
+
+	return 0;
+
+}	/* end of mgsl_alloc_buffer_list_memory() */
+
+/* Free DMA buffers allocated for use as the
+ * receive and transmit buffer lists.
+ * Warning:
+ * 
+ * 	The data transfer buffers associated with the buffer list
+ * 	MUST be freed before freeing the buffer list itself because
+ * 	the buffer list contains the information necessary to free
+ * 	the individual buffers!
+ */
+static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
+{
+	if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI)
+		dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr);
+		
+	info->buffer_list = NULL;
+	info->rx_buffer_list = NULL;
+	info->tx_buffer_list = NULL;
+
+}	/* end of mgsl_free_buffer_list_memory() */
+
+/*
+ * mgsl_alloc_frame_memory()
+ * 
+ * 	Allocate the frame DMA buffers used by the specified buffer list.
+ * 	Each DMA buffer will be one memory page in size. This is necessary
+ * 	because memory can fragment enough that it may be impossible
+ * 	contiguous pages.
+ * 
+ * Arguments:
+ * 
+ *	info		pointer to device instance data
+ * 	BufferList	pointer to list of buffer entries
+ * 	Buffercount	count of buffer entries in buffer list
+ * 
+ * Return Value:	0 if success, otherwise -ENOMEM
+ */
+static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
+{
+	int i;
+	u32 phys_addr;
+
+	/* Allocate page sized buffers for the receive buffer list */
+
+	for ( i = 0; i < Buffercount; i++ ) {
+		if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+			/* PCI adapter uses shared memory buffers. */
+			BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
+			phys_addr = info->last_mem_alloc;
+			info->last_mem_alloc += DMABUFFERSIZE;
+		} else {
+			/* ISA adapter uses system memory. */
+			BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL);
+			if (BufferList[i].virt_addr == NULL)
+				return -ENOMEM;
+			phys_addr = (u32)(BufferList[i].dma_addr);
+		}
+		BufferList[i].phys_addr = phys_addr;
+	}
+
+	return 0;
+
+}	/* end of mgsl_alloc_frame_memory() */
+
+/*
+ * mgsl_free_frame_memory()
+ * 
+ * 	Free the buffers associated with
+ * 	each buffer entry of a buffer list.
+ * 
+ * Arguments:
+ * 
+ *	info		pointer to device instance data
+ * 	BufferList	pointer to list of buffer entries
+ * 	Buffercount	count of buffer entries in buffer list
+ * 
+ * Return Value:	None
+ */
+static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
+{
+	int i;
+
+	if ( BufferList ) {
+		for ( i = 0 ; i < Buffercount ; i++ ) {
+			if ( BufferList[i].virt_addr ) {
+				if ( info->bus_type != MGSL_BUS_TYPE_PCI )
+					dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr);
+				BufferList[i].virt_addr = NULL;
+			}
+		}
+	}
+
+}	/* end of mgsl_free_frame_memory() */
+
+/* mgsl_free_dma_buffers()
+ * 
+ * 	Free DMA buffers
+ * 	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_free_dma_buffers( struct mgsl_struct *info )
+{
+	mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count );
+	mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count );
+	mgsl_free_buffer_list_memory( info );
+
+}	/* end of mgsl_free_dma_buffers() */
+
+
+/*
+ * mgsl_alloc_intermediate_rxbuffer_memory()
+ * 
+ * 	Allocate a buffer large enough to hold max_frame_size. This buffer
+ *	is used to pass an assembled frame to the line discipline.
+ * 
+ * Arguments:
+ * 
+ *	info		pointer to device instance data
+ * 
+ * Return Value:	0 if success, otherwise -ENOMEM
+ */
+static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
+{
+	info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA);
+	if ( info->intermediate_rxbuffer == NULL )
+		return -ENOMEM;
+
+	return 0;
+
+}	/* end of mgsl_alloc_intermediate_rxbuffer_memory() */
+
+/*
+ * mgsl_free_intermediate_rxbuffer_memory()
+ * 
+ * 
+ * Arguments:
+ * 
+ *	info		pointer to device instance data
+ * 
+ * Return Value:	None
+ */
+static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
+{
+	kfree(info->intermediate_rxbuffer);
+	info->intermediate_rxbuffer = NULL;
+
+}	/* end of mgsl_free_intermediate_rxbuffer_memory() */
+
+/*
+ * mgsl_alloc_intermediate_txbuffer_memory()
+ *
+ * 	Allocate intermdiate transmit buffer(s) large enough to hold max_frame_size.
+ * 	This buffer is used to load transmit frames into the adapter's dma transfer
+ * 	buffers when there is sufficient space.
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ *
+ * Return Value:	0 if success, otherwise -ENOMEM
+ */
+static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
+{
+	int i;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s %s(%d)  allocating %d tx holding buffers\n",
+				info->device_name, __FILE__,__LINE__,info->num_tx_holding_buffers);
+
+	memset(info->tx_holding_buffers,0,sizeof(info->tx_holding_buffers));
+
+	for ( i=0; i<info->num_tx_holding_buffers; ++i) {
+		info->tx_holding_buffers[i].buffer =
+			kmalloc(info->max_frame_size, GFP_KERNEL);
+		if (info->tx_holding_buffers[i].buffer == NULL) {
+			for (--i; i >= 0; i--) {
+				kfree(info->tx_holding_buffers[i].buffer);
+				info->tx_holding_buffers[i].buffer = NULL;
+			}
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+
+}	/* end of mgsl_alloc_intermediate_txbuffer_memory() */
+
+/*
+ * mgsl_free_intermediate_txbuffer_memory()
+ *
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ *
+ * Return Value:	None
+ */
+static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
+{
+	int i;
+
+	for ( i=0; i<info->num_tx_holding_buffers; ++i ) {
+		kfree(info->tx_holding_buffers[i].buffer);
+		info->tx_holding_buffers[i].buffer = NULL;
+	}
+
+	info->get_tx_holding_index = 0;
+	info->put_tx_holding_index = 0;
+	info->tx_holding_count = 0;
+
+}	/* end of mgsl_free_intermediate_txbuffer_memory() */
+
+
+/*
+ * load_next_tx_holding_buffer()
+ *
+ * attempts to load the next buffered tx request into the
+ * tx dma buffers
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ *
+ * Return Value:	true if next buffered tx request loaded
+ * 			into adapter's tx dma buffer,
+ * 			false otherwise
+ */
+static bool load_next_tx_holding_buffer(struct mgsl_struct *info)
+{
+	bool ret = false;
+
+	if ( info->tx_holding_count ) {
+		/* determine if we have enough tx dma buffers
+		 * to accommodate the next tx frame
+		 */
+		struct tx_holding_buffer *ptx =
+			&info->tx_holding_buffers[info->get_tx_holding_index];
+		int num_free = num_free_tx_dma_buffers(info);
+		int num_needed = ptx->buffer_size / DMABUFFERSIZE;
+		if ( ptx->buffer_size % DMABUFFERSIZE )
+			++num_needed;
+
+		if (num_needed <= num_free) {
+			info->xmit_cnt = ptx->buffer_size;
+			mgsl_load_tx_dma_buffer(info,ptx->buffer,ptx->buffer_size);
+
+			--info->tx_holding_count;
+			if ( ++info->get_tx_holding_index >= info->num_tx_holding_buffers)
+				info->get_tx_holding_index=0;
+
+			/* restart transmit timer */
+			mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
+
+			ret = true;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * save_tx_buffer_request()
+ *
+ * attempt to store transmit frame request for later transmission
+ *
+ * Arguments:
+ *
+ *	info		pointer to device instance data
+ * 	Buffer		pointer to buffer containing frame to load
+ * 	BufferSize	size in bytes of frame in Buffer
+ *
+ * Return Value:	1 if able to store, 0 otherwise
+ */
+static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
+{
+	struct tx_holding_buffer *ptx;
+
+	if ( info->tx_holding_count >= info->num_tx_holding_buffers ) {
+		return 0;	        /* all buffers in use */
+	}
+
+	ptx = &info->tx_holding_buffers[info->put_tx_holding_index];
+	ptx->buffer_size = BufferSize;
+	memcpy( ptx->buffer, Buffer, BufferSize);
+
+	++info->tx_holding_count;
+	if ( ++info->put_tx_holding_index >= info->num_tx_holding_buffers)
+		info->put_tx_holding_index=0;
+
+	return 1;
+}
+
+static int mgsl_claim_resources(struct mgsl_struct *info)
+{
+	if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) {
+		printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->io_base);
+		return -ENODEV;
+	}
+	info->io_addr_requested = true;
+	
+	if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags,
+		info->device_name, info ) < 0 ) {
+		printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n",
+			__FILE__,__LINE__,info->device_name, info->irq_level );
+		goto errout;
+	}
+	info->irq_requested = true;
+	
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
+			printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
+				__FILE__,__LINE__,info->device_name, info->phys_memory_base);
+			goto errout;
+		}
+		info->shared_mem_requested = true;
+		if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
+			printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
+				__FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
+			goto errout;
+		}
+		info->lcr_mem_requested = true;
+
+		info->memory_base = ioremap_nocache(info->phys_memory_base,
+								0x40000);
+		if (!info->memory_base) {
+			printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
+				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+			goto errout;
+		}
+		
+		if ( !mgsl_memory_test(info) ) {
+			printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
+				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+			goto errout;
+		}
+		
+		info->lcr_base = ioremap_nocache(info->phys_lcr_base,
+								PAGE_SIZE);
+		if (!info->lcr_base) {
+			printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
+				__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+			goto errout;
+		}
+		info->lcr_base += info->lcr_offset;
+		
+	} else {
+		/* claim DMA channel */
+		
+		if (request_dma(info->dma_level,info->device_name) < 0){
+			printk( "%s(%d):Cant request DMA channel on device %s DMA=%d\n",
+				__FILE__,__LINE__,info->device_name, info->dma_level );
+			mgsl_release_resources( info );
+			return -ENODEV;
+		}
+		info->dma_requested = true;
+
+		/* ISA adapter uses bus master DMA */		
+		set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
+		enable_dma(info->dma_level);
+	}
+	
+	if ( mgsl_allocate_dma_buffers(info) < 0 ) {
+		printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n",
+			__FILE__,__LINE__,info->device_name, info->dma_level );
+		goto errout;
+	}	
+	
+	return 0;
+errout:
+	mgsl_release_resources(info);
+	return -ENODEV;
+
+}	/* end of mgsl_claim_resources() */
+
+static void mgsl_release_resources(struct mgsl_struct *info)
+{
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_release_resources(%s) entry\n",
+			__FILE__,__LINE__,info->device_name );
+			
+	if ( info->irq_requested ) {
+		free_irq(info->irq_level, info);
+		info->irq_requested = false;
+	}
+	if ( info->dma_requested ) {
+		disable_dma(info->dma_level);
+		free_dma(info->dma_level);
+		info->dma_requested = false;
+	}
+	mgsl_free_dma_buffers(info);
+	mgsl_free_intermediate_rxbuffer_memory(info);
+     	mgsl_free_intermediate_txbuffer_memory(info);
+	
+	if ( info->io_addr_requested ) {
+		release_region(info->io_base,info->io_addr_size);
+		info->io_addr_requested = false;
+	}
+	if ( info->shared_mem_requested ) {
+		release_mem_region(info->phys_memory_base,0x40000);
+		info->shared_mem_requested = false;
+	}
+	if ( info->lcr_mem_requested ) {
+		release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
+		info->lcr_mem_requested = false;
+	}
+	if (info->memory_base){
+		iounmap(info->memory_base);
+		info->memory_base = NULL;
+	}
+	if (info->lcr_base){
+		iounmap(info->lcr_base - info->lcr_offset);
+		info->lcr_base = NULL;
+	}
+	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_release_resources(%s) exit\n",
+			__FILE__,__LINE__,info->device_name );
+			
+}	/* end of mgsl_release_resources() */
+
+/* mgsl_add_device()
+ * 
+ * 	Add the specified device instance data structure to the
+ * 	global linked list of devices and increment the device count.
+ * 	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_add_device( struct mgsl_struct *info )
+{
+	info->next_device = NULL;
+	info->line = mgsl_device_count;
+	sprintf(info->device_name,"ttySL%d",info->line);
+	
+	if (info->line < MAX_TOTAL_DEVICES) {
+		if (maxframe[info->line])
+			info->max_frame_size = maxframe[info->line];
+
+		if (txdmabufs[info->line]) {
+			info->num_tx_dma_buffers = txdmabufs[info->line];
+			if (info->num_tx_dma_buffers < 1)
+				info->num_tx_dma_buffers = 1;
+		}
+
+		if (txholdbufs[info->line]) {
+			info->num_tx_holding_buffers = txholdbufs[info->line];
+			if (info->num_tx_holding_buffers < 1)
+				info->num_tx_holding_buffers = 1;
+			else if (info->num_tx_holding_buffers > MAX_TX_HOLDING_BUFFERS)
+				info->num_tx_holding_buffers = MAX_TX_HOLDING_BUFFERS;
+		}
+	}
+
+	mgsl_device_count++;
+	
+	if ( !mgsl_device_list )
+		mgsl_device_list = info;
+	else {	
+		struct mgsl_struct *current_dev = mgsl_device_list;
+		while( current_dev->next_device )
+			current_dev = current_dev->next_device;
+		current_dev->next_device = info;
+	}
+	
+	if ( info->max_frame_size < 4096 )
+		info->max_frame_size = 4096;
+	else if ( info->max_frame_size > 65535 )
+		info->max_frame_size = 65535;
+	
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
+			info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
+			info->phys_memory_base, info->phys_lcr_base,
+		     	info->max_frame_size );
+	} else {
+		printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
+			info->device_name, info->io_base, info->irq_level, info->dma_level,
+		     	info->max_frame_size );
+	}
+
+#if SYNCLINK_GENERIC_HDLC
+	hdlcdev_init(info);
+#endif
+
+}	/* end of mgsl_add_device() */
+
+static const struct tty_port_operations mgsl_port_ops = {
+	.carrier_raised = carrier_raised,
+	.dtr_rts = dtr_rts,
+};
+
+
+/* mgsl_allocate_device()
+ * 
+ * 	Allocate and initialize a device instance structure
+ * 	
+ * Arguments:		none
+ * Return Value:	pointer to mgsl_struct if success, otherwise NULL
+ */
+static struct mgsl_struct* mgsl_allocate_device(void)
+{
+	struct mgsl_struct *info;
+	
+	info = kzalloc(sizeof(struct mgsl_struct),
+		 GFP_KERNEL);
+		 
+	if (!info) {
+		printk("Error can't allocate device instance data\n");
+	} else {
+		tty_port_init(&info->port);
+		info->port.ops = &mgsl_port_ops;
+		info->magic = MGSL_MAGIC;
+		INIT_WORK(&info->task, mgsl_bh_handler);
+		info->max_frame_size = 4096;
+		info->port.close_delay = 5*HZ/10;
+		info->port.closing_wait = 30*HZ;
+		init_waitqueue_head(&info->status_event_wait_q);
+		init_waitqueue_head(&info->event_wait_q);
+		spin_lock_init(&info->irq_spinlock);
+		spin_lock_init(&info->netlock);
+		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+		info->idle_mode = HDLC_TXIDLE_FLAGS;		
+		info->num_tx_dma_buffers = 1;
+		info->num_tx_holding_buffers = 0;
+	}
+	
+	return info;
+
+}	/* end of mgsl_allocate_device()*/
+
+static const struct tty_operations mgsl_ops = {
+	.open = mgsl_open,
+	.close = mgsl_close,
+	.write = mgsl_write,
+	.put_char = mgsl_put_char,
+	.flush_chars = mgsl_flush_chars,
+	.write_room = mgsl_write_room,
+	.chars_in_buffer = mgsl_chars_in_buffer,
+	.flush_buffer = mgsl_flush_buffer,
+	.ioctl = mgsl_ioctl,
+	.throttle = mgsl_throttle,
+	.unthrottle = mgsl_unthrottle,
+	.send_xchar = mgsl_send_xchar,
+	.break_ctl = mgsl_break,
+	.wait_until_sent = mgsl_wait_until_sent,
+	.set_termios = mgsl_set_termios,
+	.stop = mgsl_stop,
+	.start = mgsl_start,
+	.hangup = mgsl_hangup,
+	.tiocmget = tiocmget,
+	.tiocmset = tiocmset,
+	.get_icount = msgl_get_icount,
+	.proc_fops = &mgsl_proc_fops,
+};
+
+/*
+ * perform tty device initialization
+ */
+static int mgsl_init_tty(void)
+{
+	int rc;
+
+	serial_driver = alloc_tty_driver(128);
+	if (!serial_driver)
+		return -ENOMEM;
+	
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "synclink";
+	serial_driver->name = "ttySL";
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver->init_termios.c_ispeed = 9600;
+	serial_driver->init_termios.c_ospeed = 9600;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &mgsl_ops);
+	if ((rc = tty_register_driver(serial_driver)) < 0) {
+		printk("%s(%d):Couldn't register serial driver\n",
+			__FILE__,__LINE__);
+		put_tty_driver(serial_driver);
+		serial_driver = NULL;
+		return rc;
+	}
+			
+ 	printk("%s %s, tty major#%d\n",
+		driver_name, driver_version,
+		serial_driver->major);
+	return 0;
+}
+
+/* enumerate user specified ISA adapters
+ */
+static void mgsl_enum_isa_devices(void)
+{
+	struct mgsl_struct *info;
+	int i;
+		
+	/* Check for user specified ISA devices */
+	
+	for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk("ISA device specified io=%04X,irq=%d,dma=%d\n",
+				io[i], irq[i], dma[i] );
+		
+		info = mgsl_allocate_device();
+		if ( !info ) {
+			/* error allocating device instance data */
+			if ( debug_level >= DEBUG_LEVEL_ERROR )
+				printk( "can't allocate device instance data.\n");
+			continue;
+		}
+		
+		/* Copy user configuration info to device instance data */
+		info->io_base = (unsigned int)io[i];
+		info->irq_level = (unsigned int)irq[i];
+		info->irq_level = irq_canonicalize(info->irq_level);
+		info->dma_level = (unsigned int)dma[i];
+		info->bus_type = MGSL_BUS_TYPE_ISA;
+		info->io_addr_size = 16;
+		info->irq_flags = 0;
+		
+		mgsl_add_device( info );
+	}
+}
+
+static void synclink_cleanup(void)
+{
+	int rc;
+	struct mgsl_struct *info;
+	struct mgsl_struct *tmp;
+
+	printk("Unloading %s: %s\n", driver_name, driver_version);
+
+	if (serial_driver) {
+		if ((rc = tty_unregister_driver(serial_driver)))
+			printk("%s(%d) failed to unregister tty driver err=%d\n",
+			       __FILE__,__LINE__,rc);
+		put_tty_driver(serial_driver);
+	}
+
+	info = mgsl_device_list;
+	while(info) {
+#if SYNCLINK_GENERIC_HDLC
+		hdlcdev_exit(info);
+#endif
+		mgsl_release_resources(info);
+		tmp = info;
+		info = info->next_device;
+		kfree(tmp);
+	}
+	
+	if (pci_registered)
+		pci_unregister_driver(&synclink_pci_driver);
+}
+
+static int __init synclink_init(void)
+{
+	int rc;
+
+	if (break_on_load) {
+	 	mgsl_get_text_ptr();
+  		BREAKPOINT();
+	}
+
+ 	printk("%s %s\n", driver_name, driver_version);
+
+	mgsl_enum_isa_devices();
+	if ((rc = pci_register_driver(&synclink_pci_driver)) < 0)
+		printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
+	else
+		pci_registered = true;
+
+	if ((rc = mgsl_init_tty()) < 0)
+		goto error;
+
+	return 0;
+
+error:
+	synclink_cleanup();
+	return rc;
+}
+
+static void __exit synclink_exit(void)
+{
+	synclink_cleanup();
+}
+
+module_init(synclink_init);
+module_exit(synclink_exit);
+
+/*
+ * usc_RTCmd()
+ *
+ * Issue a USC Receive/Transmit command to the
+ * Channel Command/Address Register (CCAR).
+ *
+ * Notes:
+ *
+ *    The command is encoded in the most significant 5 bits <15..11>
+ *    of the CCAR value. Bits <10..7> of the CCAR must be preserved
+ *    and Bits <6..0> must be written as zeros.
+ *
+ * Arguments:
+ *
+ *    info   pointer to device information structure
+ *    Cmd    command mask (use symbolic macros)
+ *
+ * Return Value:
+ *
+ *    None
+ */
+static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
+{
+	/* output command to CCAR in bits <15..11> */
+	/* preserve bits <10..7>, bits <6..0> must be zero */
+
+	outw( Cmd + info->loopback_bits, info->io_base + CCAR );
+
+	/* Read to flush write to CCAR */
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+		inw( info->io_base + CCAR );
+
+}	/* end of usc_RTCmd() */
+
+/*
+ * usc_DmaCmd()
+ *
+ *    Issue a DMA command to the DMA Command/Address Register (DCAR).
+ *
+ * Arguments:
+ *
+ *    info   pointer to device information structure
+ *    Cmd    DMA command mask (usc_DmaCmd_XX Macros)
+ *
+ * Return Value:
+ *
+ *       None
+ */
+static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
+{
+	/* write command mask to DCAR */
+	outw( Cmd + info->mbre_bit, info->io_base );
+
+	/* Read to flush write to DCAR */
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+		inw( info->io_base );
+
+}	/* end of usc_DmaCmd() */
+
+/*
+ * usc_OutDmaReg()
+ *
+ *    Write a 16-bit value to a USC DMA register
+ *
+ * Arguments:
+ *
+ *    info      pointer to device info structure
+ *    RegAddr   register address (number) for write
+ *    RegValue  16-bit value to write to register
+ *
+ * Return Value:
+ *
+ *    None
+ *
+ */
+static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
+{
+	/* Note: The DCAR is located at the adapter base address */
+	/* Note: must preserve state of BIT8 in DCAR */
+
+	outw( RegAddr + info->mbre_bit, info->io_base );
+	outw( RegValue, info->io_base );
+
+	/* Read to flush write to DCAR */
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+		inw( info->io_base );
+
+}	/* end of usc_OutDmaReg() */
+ 
+/*
+ * usc_InDmaReg()
+ *
+ *    Read a 16-bit value from a DMA register
+ *
+ * Arguments:
+ *
+ *    info     pointer to device info structure
+ *    RegAddr  register address (number) to read from
+ *
+ * Return Value:
+ *
+ *    The 16-bit value read from register
+ *
+ */
+static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
+{
+	/* Note: The DCAR is located at the adapter base address */
+	/* Note: must preserve state of BIT8 in DCAR */
+
+	outw( RegAddr + info->mbre_bit, info->io_base );
+	return inw( info->io_base );
+
+}	/* end of usc_InDmaReg() */
+
+/*
+ *
+ * usc_OutReg()
+ *
+ *    Write a 16-bit value to a USC serial channel register 
+ *
+ * Arguments:
+ *
+ *    info      pointer to device info structure
+ *    RegAddr   register address (number) to write to
+ *    RegValue  16-bit value to write to register
+ *
+ * Return Value:
+ *
+ *    None
+ *
+ */
+static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
+{
+	outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
+	outw( RegValue, info->io_base + CCAR );
+
+	/* Read to flush write to CCAR */
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+		inw( info->io_base + CCAR );
+
+}	/* end of usc_OutReg() */
+
+/*
+ * usc_InReg()
+ *
+ *    Reads a 16-bit value from a USC serial channel register
+ *
+ * Arguments:
+ *
+ *    info       pointer to device extension
+ *    RegAddr    register address (number) to read from
+ *
+ * Return Value:
+ *
+ *    16-bit value read from register
+ */
+static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
+{
+	outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
+	return inw( info->io_base + CCAR );
+
+}	/* end of usc_InReg() */
+
+/* usc_set_sdlc_mode()
+ *
+ *    Set up the adapter for SDLC DMA communications.
+ *
+ * Arguments:		info    pointer to device instance data
+ * Return Value: 	NONE
+ */
+static void usc_set_sdlc_mode( struct mgsl_struct *info )
+{
+	u16 RegValue;
+	bool PreSL1660;
+	
+	/*
+	 * determine if the IUSC on the adapter is pre-SL1660. If
+	 * not, take advantage of the UnderWait feature of more
+	 * modern chips. If an underrun occurs and this bit is set,
+	 * the transmitter will idle the programmed idle pattern
+	 * until the driver has time to service the underrun. Otherwise,
+	 * the dma controller may get the cycles previously requested
+	 * and begin transmitting queued tx data.
+	 */
+	usc_OutReg(info,TMCR,0x1f);
+	RegValue=usc_InReg(info,TMDR);
+	PreSL1660 = (RegValue == IUSC_PRE_SL1660);
+
+ 	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+ 	{
+ 	   /*
+ 	   ** Channel Mode Register (CMR)
+ 	   **
+ 	   ** <15..14>    10    Tx Sub Modes, Send Flag on Underrun
+ 	   ** <13>        0     0 = Transmit Disabled (initially)
+ 	   ** <12>        0     1 = Consecutive Idles share common 0
+ 	   ** <11..8>     1110  Transmitter Mode = HDLC/SDLC Loop
+ 	   ** <7..4>      0000  Rx Sub Modes, addr/ctrl field handling
+ 	   ** <3..0>      0110  Receiver Mode = HDLC/SDLC
+ 	   **
+ 	   ** 1000 1110 0000 0110 = 0x8e06
+ 	   */
+ 	   RegValue = 0x8e06;
+ 
+ 	   /*--------------------------------------------------
+ 	    * ignore user options for UnderRun Actions and
+ 	    * preambles
+ 	    *--------------------------------------------------*/
+ 	}
+ 	else
+ 	{	
+		/* Channel mode Register (CMR)
+		 *
+		 * <15..14>  00    Tx Sub modes, Underrun Action
+		 * <13>      0     1 = Send Preamble before opening flag
+		 * <12>      0     1 = Consecutive Idles share common 0
+		 * <11..8>   0110  Transmitter mode = HDLC/SDLC
+		 * <7..4>    0000  Rx Sub modes, addr/ctrl field handling
+		 * <3..0>    0110  Receiver mode = HDLC/SDLC
+		 *
+		 * 0000 0110 0000 0110 = 0x0606
+		 */
+		if (info->params.mode == MGSL_MODE_RAW) {
+			RegValue = 0x0001;		/* Set Receive mode = external sync */
+
+			usc_OutReg( info, IOCR,		/* Set IOCR DCD is RxSync Detect Input */
+				(unsigned short)((usc_InReg(info, IOCR) & ~(BIT13|BIT12)) | BIT12));
+
+			/*
+			 * TxSubMode:
+			 * 	CMR <15>		0	Don't send CRC on Tx Underrun
+			 * 	CMR <14>		x	undefined
+			 * 	CMR <13>		0	Send preamble before openning sync
+			 * 	CMR <12>		0	Send 8-bit syncs, 1=send Syncs per TxLength
+			 *
+			 * TxMode:
+			 * 	CMR <11-8)	0100	MonoSync
+			 *
+			 * 	0x00 0100 xxxx xxxx  04xx
+			 */
+			RegValue |= 0x0400;
+		}
+		else {
+
+		RegValue = 0x0606;
+
+		if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 )
+			RegValue |= BIT14;
+		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
+			RegValue |= BIT15;
+		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
+			RegValue |= BIT15 + BIT14;
+		}
+
+		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
+			RegValue |= BIT13;
+	}
+
+	if ( info->params.mode == MGSL_MODE_HDLC &&
+		(info->params.flags & HDLC_FLAG_SHARE_ZERO) )
+		RegValue |= BIT12;
+
+	if ( info->params.addr_filter != 0xff )
+	{
+		/* set up receive address filtering */
+		usc_OutReg( info, RSR, info->params.addr_filter );
+		RegValue |= BIT4;
+	}
+
+	usc_OutReg( info, CMR, RegValue );
+	info->cmr_value = RegValue;
+
+	/* Receiver mode Register (RMR)
+	 *
+	 * <15..13>  000    encoding
+	 * <12..11>  00     FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1)
+	 * <10>      1      1 = Set CRC to all 1s (use for SDLC/HDLC)
+	 * <9>       0      1 = Include Receive chars in CRC
+	 * <8>       1      1 = Use Abort/PE bit as abort indicator
+	 * <7..6>    00     Even parity
+	 * <5>       0      parity disabled
+	 * <4..2>    000    Receive Char Length = 8 bits
+	 * <1..0>    00     Disable Receiver
+	 *
+	 * 0000 0101 0000 0000 = 0x0500
+	 */
+
+	RegValue = 0x0500;
+
+	switch ( info->params.encoding ) {
+	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
+	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
+	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 + BIT13; break;
+	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
+	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
+	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
+	}
+
+	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
+		RegValue |= BIT9;
+	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
+		RegValue |= ( BIT12 | BIT10 | BIT9 );
+
+	usc_OutReg( info, RMR, RegValue );
+
+	/* Set the Receive count Limit Register (RCLR) to 0xffff. */
+	/* When an opening flag of an SDLC frame is recognized the */
+	/* Receive Character count (RCC) is loaded with the value in */
+	/* RCLR. The RCC is decremented for each received byte.  The */
+	/* value of RCC is stored after the closing flag of the frame */
+	/* allowing the frame size to be computed. */
+
+	usc_OutReg( info, RCLR, RCLRVALUE );
+
+	usc_RCmd( info, RCmd_SelectRicrdma_level );
+
+	/* Receive Interrupt Control Register (RICR)
+	 *
+	 * <15..8>	?	RxFIFO DMA Request Level
+	 * <7>		0	Exited Hunt IA (Interrupt Arm)
+	 * <6>		0	Idle Received IA
+	 * <5>		0	Break/Abort IA
+	 * <4>		0	Rx Bound IA
+	 * <3>		1	Queued status reflects oldest 2 bytes in FIFO
+	 * <2>		0	Abort/PE IA
+	 * <1>		1	Rx Overrun IA
+	 * <0>		0	Select TC0 value for readback
+	 *
+	 *	0000 0000 0000 1000 = 0x000a
+	 */
+
+	/* Carry over the Exit Hunt and Idle Received bits */
+	/* in case they have been armed by usc_ArmEvents.   */
+
+	RegValue = usc_InReg( info, RICR ) & 0xc0;
+
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+		usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
+	else
+		usc_OutReg( info, RICR, (u16)(0x140a | RegValue) );
+
+	/* Unlatch all Rx status bits and clear Rx status IRQ Pending */
+
+	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
+
+	/* Transmit mode Register (TMR)
+	 *	
+	 * <15..13>	000	encoding
+	 * <12..11>	00	FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1)
+	 * <10>		1	1 = Start CRC as all 1s (use for SDLC/HDLC)
+	 * <9>		0	1 = Tx CRC Enabled
+	 * <8>		0	1 = Append CRC to end of transmit frame
+	 * <7..6>	00	Transmit parity Even
+	 * <5>		0	Transmit parity Disabled
+	 * <4..2>	000	Tx Char Length = 8 bits
+	 * <1..0>	00	Disable Transmitter
+	 *
+	 * 	0000 0100 0000 0000 = 0x0400
+	 */
+
+	RegValue = 0x0400;
+
+	switch ( info->params.encoding ) {
+	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
+	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
+	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 + BIT13; break;
+	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
+	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
+	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
+	}
+
+	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
+		RegValue |= BIT9 + BIT8;
+	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
+		RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8);
+
+	usc_OutReg( info, TMR, RegValue );
+
+	usc_set_txidle( info );
+
+
+	usc_TCmd( info, TCmd_SelectTicrdma_level );
+
+	/* Transmit Interrupt Control Register (TICR)
+	 *
+	 * <15..8>	?	Transmit FIFO DMA Level
+	 * <7>		0	Present IA (Interrupt Arm)
+	 * <6>		0	Idle Sent IA
+	 * <5>		1	Abort Sent IA
+	 * <4>		1	EOF/EOM Sent IA
+	 * <3>		0	CRC Sent IA
+	 * <2>		1	1 = Wait for SW Trigger to Start Frame
+	 * <1>		1	Tx Underrun IA
+	 * <0>		0	TC0 constant on read back
+	 *
+	 *	0000 0000 0011 0110 = 0x0036
+	 */
+
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+		usc_OutReg( info, TICR, 0x0736 );
+	else								
+		usc_OutReg( info, TICR, 0x1436 );
+
+	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
+	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
+
+	/*
+	** Transmit Command/Status Register (TCSR)
+	**
+	** <15..12>	0000	TCmd
+	** <11> 	0/1	UnderWait
+	** <10..08>	000	TxIdle
+	** <7>		x	PreSent
+	** <6>         	x	IdleSent
+	** <5>         	x	AbortSent
+	** <4>         	x	EOF/EOM Sent
+	** <3>         	x	CRC Sent
+	** <2>         	x	All Sent
+	** <1>         	x	TxUnder
+	** <0>         	x	TxEmpty
+	** 
+	** 0000 0000 0000 0000 = 0x0000
+	*/
+	info->tcsr_value = 0;
+
+	if ( !PreSL1660 )
+		info->tcsr_value |= TCSR_UNDERWAIT;
+		
+	usc_OutReg( info, TCSR, info->tcsr_value );
+
+	/* Clock mode Control Register (CMCR)
+	 *
+	 * <15..14>	00	counter 1 Source = Disabled
+	 * <13..12> 	00	counter 0 Source = Disabled
+	 * <11..10> 	11	BRG1 Input is TxC Pin
+	 * <9..8>	11	BRG0 Input is TxC Pin
+	 * <7..6>	01	DPLL Input is BRG1 Output
+	 * <5..3>	XXX	TxCLK comes from Port 0
+	 * <2..0>   	XXX	RxCLK comes from Port 1
+	 *
+	 *	0000 1111 0111 0111 = 0x0f77
+	 */
+
+	RegValue = 0x0f40;
+
+	if ( info->params.flags & HDLC_FLAG_RXC_DPLL )
+		RegValue |= 0x0003;	/* RxCLK from DPLL */
+	else if ( info->params.flags & HDLC_FLAG_RXC_BRG )
+		RegValue |= 0x0004;	/* RxCLK from BRG0 */
+ 	else if ( info->params.flags & HDLC_FLAG_RXC_TXCPIN)
+ 		RegValue |= 0x0006;	/* RxCLK from TXC Input */
+	else
+		RegValue |= 0x0007;	/* RxCLK from Port1 */
+
+	if ( info->params.flags & HDLC_FLAG_TXC_DPLL )
+		RegValue |= 0x0018;	/* TxCLK from DPLL */
+	else if ( info->params.flags & HDLC_FLAG_TXC_BRG )
+		RegValue |= 0x0020;	/* TxCLK from BRG0 */
+ 	else if ( info->params.flags & HDLC_FLAG_TXC_RXCPIN)
+ 		RegValue |= 0x0038;	/* RxCLK from TXC Input */
+	else
+		RegValue |= 0x0030;	/* TxCLK from Port0 */
+
+	usc_OutReg( info, CMCR, RegValue );
+
+
+	/* Hardware Configuration Register (HCR)
+	 *
+	 * <15..14>	00	CTR0 Divisor:00=32,01=16,10=8,11=4
+	 * <13>		0	CTR1DSel:0=CTR0Div determines CTR0Div
+	 * <12>		0	CVOK:0=report code violation in biphase
+	 * <11..10>	00	DPLL Divisor:00=32,01=16,10=8,11=4
+	 * <9..8>	XX	DPLL mode:00=disable,01=NRZ,10=Biphase,11=Biphase Level
+	 * <7..6>	00	reserved
+	 * <5>		0	BRG1 mode:0=continuous,1=single cycle
+	 * <4>		X	BRG1 Enable
+	 * <3..2>	00	reserved
+	 * <1>		0	BRG0 mode:0=continuous,1=single cycle
+	 * <0>		0	BRG0 Enable
+	 */
+
+	RegValue = 0x0000;
+
+	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) {
+		u32 XtalSpeed;
+		u32 DpllDivisor;
+		u16 Tc;
+
+		/*  DPLL is enabled. Use BRG1 to provide continuous reference clock  */
+		/*  for DPLL. DPLL mode in HCR is dependent on the encoding used. */
+
+		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+			XtalSpeed = 11059200;
+		else
+			XtalSpeed = 14745600;
+
+		if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
+			DpllDivisor = 16;
+			RegValue |= BIT10;
+		}
+		else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) {
+			DpllDivisor = 8;
+			RegValue |= BIT11;
+		}
+		else
+			DpllDivisor = 32;
+
+		/*  Tc = (Xtal/Speed) - 1 */
+		/*  If twice the remainder of (Xtal/Speed) is greater than Speed */
+		/*  then rounding up gives a more precise time constant. Instead */
+		/*  of rounding up and then subtracting 1 we just don't subtract */
+		/*  the one in this case. */
+
+ 		/*--------------------------------------------------
+ 		 * ejz: for DPLL mode, application should use the
+ 		 * same clock speed as the partner system, even 
+ 		 * though clocking is derived from the input RxData.
+ 		 * In case the user uses a 0 for the clock speed,
+ 		 * default to 0xffffffff and don't try to divide by
+ 		 * zero
+ 		 *--------------------------------------------------*/
+ 		if ( info->params.clock_speed )
+ 		{
+			Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed);
+			if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2)
+			       / info->params.clock_speed) )
+				Tc--;
+ 		}
+ 		else
+ 			Tc = -1;
+ 				  
+
+		/* Write 16-bit Time Constant for BRG1 */
+		usc_OutReg( info, TC1R, Tc );
+
+		RegValue |= BIT4;		/* enable BRG1 */
+
+		switch ( info->params.encoding ) {
+		case HDLC_ENCODING_NRZ:
+		case HDLC_ENCODING_NRZB:
+		case HDLC_ENCODING_NRZI_MARK:
+		case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT8; break;
+		case HDLC_ENCODING_BIPHASE_MARK:
+		case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break;
+		case HDLC_ENCODING_BIPHASE_LEVEL:
+		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break;
+		}
+	}
+
+	usc_OutReg( info, HCR, RegValue );
+
+
+	/* Channel Control/status Register (CCSR)
+	 *
+	 * <15>		X	RCC FIFO Overflow status (RO)
+	 * <14>		X	RCC FIFO Not Empty status (RO)
+	 * <13>		0	1 = Clear RCC FIFO (WO)
+	 * <12>		X	DPLL Sync (RW)
+	 * <11>		X	DPLL 2 Missed Clocks status (RO)
+	 * <10>		X	DPLL 1 Missed Clock status (RO)
+	 * <9..8>	00	DPLL Resync on rising and falling edges (RW)
+	 * <7>		X	SDLC Loop On status (RO)
+	 * <6>		X	SDLC Loop Send status (RO)
+	 * <5>		1	Bypass counters for TxClk and RxClk (RW)
+	 * <4..2>   	000	Last Char of SDLC frame has 8 bits (RW)
+	 * <1..0>   	00	reserved
+	 *
+	 *	0000 0000 0010 0000 = 0x0020
+	 */
+
+	usc_OutReg( info, CCSR, 0x1020 );
+
+
+	if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) {
+		usc_OutReg( info, SICR,
+			    (u16)(usc_InReg(info,SICR) | SICR_CTS_INACTIVE) );
+	}
+	
+
+	/* enable Master Interrupt Enable bit (MIE) */
+	usc_EnableMasterIrqBit( info );
+
+	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
+				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
+
+	/* arm RCC underflow interrupt */
+	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
+	usc_EnableInterrupts(info, MISC);
+
+	info->mbre_bit = 0;
+	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
+	usc_DmaCmd( info, DmaCmd_ResetAllChannels );	/* disable both DMA channels */
+	info->mbre_bit = BIT8;
+	outw( BIT8, info->io_base );			/* set Master Bus Enable (DCAR) */
+
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable DMAEN (Port 7, Bit 14) */
+		/* This connects the DMA request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14));
+	}
+
+	/* DMA Control Register (DCR)
+	 *
+	 * <15..14>	10	Priority mode = Alternating Tx/Rx
+	 *		01	Rx has priority
+	 *		00	Tx has priority
+	 *
+	 * <13>		1	Enable Priority Preempt per DCR<15..14>
+	 *			(WARNING DCR<11..10> must be 00 when this is 1)
+	 *		0	Choose activate channel per DCR<11..10>
+	 *
+	 * <12>		0	Little Endian for Array/List
+	 * <11..10>	00	Both Channels can use each bus grant
+	 * <9..6>	0000	reserved
+	 * <5>		0	7 CLK - Minimum Bus Re-request Interval
+	 * <4>		0	1 = drive D/C and S/D pins
+	 * <3>		1	1 = Add one wait state to all DMA cycles.
+	 * <2>		0	1 = Strobe /UAS on every transfer.
+	 * <1..0>	11	Addr incrementing only affects LS24 bits
+	 *
+	 *	0110 0000 0000 1011 = 0x600b
+	 */
+
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		/* PCI adapter does not need DMA wait state */
+		usc_OutDmaReg( info, DCR, 0xa00b );
+	}
+	else
+		usc_OutDmaReg( info, DCR, 0x800b );
+
+
+	/* Receive DMA mode Register (RDMR)
+	 *
+	 * <15..14>	11	DMA mode = Linked List Buffer mode
+	 * <13>		1	RSBinA/L = store Rx status Block in Arrary/List entry
+	 * <12>		1	Clear count of List Entry after fetching
+	 * <11..10>	00	Address mode = Increment
+	 * <9>		1	Terminate Buffer on RxBound
+	 * <8>		0	Bus Width = 16bits
+	 * <7..0>	?	status Bits (write as 0s)
+	 *
+	 * 1111 0010 0000 0000 = 0xf200
+	 */
+
+	usc_OutDmaReg( info, RDMR, 0xf200 );
+
+
+	/* Transmit DMA mode Register (TDMR)
+	 *
+	 * <15..14>	11	DMA mode = Linked List Buffer mode
+	 * <13>		1	TCBinA/L = fetch Tx Control Block from List entry
+	 * <12>		1	Clear count of List Entry after fetching
+	 * <11..10>	00	Address mode = Increment
+	 * <9>		1	Terminate Buffer on end of frame
+	 * <8>		0	Bus Width = 16bits
+	 * <7..0>	?	status Bits (Read Only so write as 0)
+	 *
+	 *	1111 0010 0000 0000 = 0xf200
+	 */
+
+	usc_OutDmaReg( info, TDMR, 0xf200 );
+
+
+	/* DMA Interrupt Control Register (DICR)
+	 *
+	 * <15>		1	DMA Interrupt Enable
+	 * <14>		0	1 = Disable IEO from USC
+	 * <13>		0	1 = Don't provide vector during IntAck
+	 * <12>		1	1 = Include status in Vector
+	 * <10..2>	0	reserved, Must be 0s
+	 * <1>		0	1 = Rx DMA Interrupt Enabled
+	 * <0>		0	1 = Tx DMA Interrupt Enabled
+	 *
+	 *	1001 0000 0000 0000 = 0x9000
+	 */
+
+	usc_OutDmaReg( info, DICR, 0x9000 );
+
+	usc_InDmaReg( info, RDMR );		/* clear pending receive DMA IRQ bits */
+	usc_InDmaReg( info, TDMR );		/* clear pending transmit DMA IRQ bits */
+	usc_OutDmaReg( info, CDIR, 0x0303 );	/* clear IUS and Pending for Tx and Rx */
+
+	/* Channel Control Register (CCR)
+	 *
+	 * <15..14>	10	Use 32-bit Tx Control Blocks (TCBs)
+	 * <13>		0	Trigger Tx on SW Command Disabled
+	 * <12>		0	Flag Preamble Disabled
+	 * <11..10>	00	Preamble Length
+	 * <9..8>	00	Preamble Pattern
+	 * <7..6>	10	Use 32-bit Rx status Blocks (RSBs)
+	 * <5>		0	Trigger Rx on SW Command Disabled
+	 * <4..0>	0	reserved
+	 *
+	 *	1000 0000 1000 0000 = 0x8080
+	 */
+
+	RegValue = 0x8080;
+
+	switch ( info->params.preamble_length ) {
+	case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break;
+	case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break;
+	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break;
+	}
+
+	switch ( info->params.preamble ) {
+	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break;
+	case HDLC_PREAMBLE_PATTERN_ONES:  RegValue |= BIT8; break;
+	case HDLC_PREAMBLE_PATTERN_10:    RegValue |= BIT9; break;
+	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 + BIT8; break;
+	}
+
+	usc_OutReg( info, CCR, RegValue );
+
+
+	/*
+	 * Burst/Dwell Control Register
+	 *
+	 * <15..8>	0x20	Maximum number of transfers per bus grant
+	 * <7..0>	0x00	Maximum number of clock cycles per bus grant
+	 */
+
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		/* don't limit bus occupancy on PCI adapter */
+		usc_OutDmaReg( info, BDCR, 0x0000 );
+	}
+	else
+		usc_OutDmaReg( info, BDCR, 0x2000 );
+
+	usc_stop_transmitter(info);
+	usc_stop_receiver(info);
+	
+}	/* end of usc_set_sdlc_mode() */
+
+/* usc_enable_loopback()
+ *
+ * Set the 16C32 for internal loopback mode.
+ * The TxCLK and RxCLK signals are generated from the BRG0 and
+ * the TxD is looped back to the RxD internally.
+ *
+ * Arguments:		info	pointer to device instance data
+ *			enable	1 = enable loopback, 0 = disable
+ * Return Value:	None
+ */
+static void usc_enable_loopback(struct mgsl_struct *info, int enable)
+{
+	if (enable) {
+		/* blank external TXD output */
+		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6));
+	
+		/* Clock mode Control Register (CMCR)
+		 *
+		 * <15..14>	00	counter 1 Disabled
+		 * <13..12> 	00	counter 0 Disabled
+		 * <11..10> 	11	BRG1 Input is TxC Pin
+		 * <9..8>	11	BRG0 Input is TxC Pin
+		 * <7..6>	01	DPLL Input is BRG1 Output
+		 * <5..3>	100	TxCLK comes from BRG0
+		 * <2..0>   	100	RxCLK comes from BRG0
+		 *
+		 * 0000 1111 0110 0100 = 0x0f64
+		 */
+
+		usc_OutReg( info, CMCR, 0x0f64 );
+
+		/* Write 16-bit Time Constant for BRG0 */
+		/* use clock speed if available, otherwise use 8 for diagnostics */
+		if (info->params.clock_speed) {
+			if (info->bus_type == MGSL_BUS_TYPE_PCI)
+				usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
+			else
+				usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1));
+		} else
+			usc_OutReg(info, TC0R, (u16)8);
+
+		/* Hardware Configuration Register (HCR) Clear Bit 1, BRG0
+		   mode = Continuous Set Bit 0 to enable BRG0.  */
+		usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
+
+		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
+		usc_OutReg(info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004));
+
+		/* set Internal Data loopback mode */
+		info->loopback_bits = 0x300;
+		outw( 0x0300, info->io_base + CCAR );
+	} else {
+		/* enable external TXD output */
+		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6));
+	
+		/* clear Internal Data loopback mode */
+		info->loopback_bits = 0;
+		outw( 0,info->io_base + CCAR );
+	}
+	
+}	/* end of usc_enable_loopback() */
+
+/* usc_enable_aux_clock()
+ *
+ * Enabled the AUX clock output at the specified frequency.
+ *
+ * Arguments:
+ *
+ *	info		pointer to device extension
+ *	data_rate	data rate of clock in bits per second
+ *			A data rate of 0 disables the AUX clock.
+ *
+ * Return Value:	None
+ */
+static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
+{
+	u32 XtalSpeed;
+	u16 Tc;
+
+	if ( data_rate ) {
+		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+			XtalSpeed = 11059200;
+		else
+			XtalSpeed = 14745600;
+
+
+		/* Tc = (Xtal/Speed) - 1 */
+		/* If twice the remainder of (Xtal/Speed) is greater than Speed */
+		/* then rounding up gives a more precise time constant. Instead */
+		/* of rounding up and then subtracting 1 we just don't subtract */
+		/* the one in this case. */
+
+
+		Tc = (u16)(XtalSpeed/data_rate);
+		if ( !(((XtalSpeed % data_rate) * 2) / data_rate) )
+			Tc--;
+
+		/* Write 16-bit Time Constant for BRG0 */
+		usc_OutReg( info, TC0R, Tc );
+
+		/*
+		 * Hardware Configuration Register (HCR)
+		 * Clear Bit 1, BRG0 mode = Continuous
+		 * Set Bit 0 to enable BRG0.
+		 */
+
+		usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
+
+		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
+		usc_OutReg( info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) );
+	} else {
+		/* data rate == 0 so turn off BRG0 */
+		usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) );
+	}
+
+}	/* end of usc_enable_aux_clock() */
+
+/*
+ *
+ * usc_process_rxoverrun_sync()
+ *
+ *		This function processes a receive overrun by resetting the
+ *		receive DMA buffers and issuing a Purge Rx FIFO command
+ *		to allow the receiver to continue receiving.
+ *
+ * Arguments:
+ *
+ *	info		pointer to device extension
+ *
+ * Return Value: None
+ */
+static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+{
+	int start_index;
+	int end_index;
+	int frame_start_index;
+	bool start_of_frame_found = false;
+	bool end_of_frame_found = false;
+	bool reprogram_dma = false;
+
+	DMABUFFERENTRY *buffer_list = info->rx_buffer_list;
+	u32 phys_addr;
+
+	usc_DmaCmd( info, DmaCmd_PauseRxChannel );
+	usc_RCmd( info, RCmd_EnterHuntmode );
+	usc_RTCmd( info, RTCmd_PurgeRxFifo );
+
+	/* CurrentRxBuffer points to the 1st buffer of the next */
+	/* possibly available receive frame. */
+	
+	frame_start_index = start_index = end_index = info->current_rx_buffer;
+
+	/* Search for an unfinished string of buffers. This means */
+	/* that a receive frame started (at least one buffer with */
+	/* count set to zero) but there is no terminiting buffer */
+	/* (status set to non-zero). */
+
+	while( !buffer_list[end_index].count )
+	{
+		/* Count field has been reset to zero by 16C32. */
+		/* This buffer is currently in use. */
+
+		if ( !start_of_frame_found )
+		{
+			start_of_frame_found = true;
+			frame_start_index = end_index;
+			end_of_frame_found = false;
+		}
+
+		if ( buffer_list[end_index].status )
+		{
+			/* Status field has been set by 16C32. */
+			/* This is the last buffer of a received frame. */
+
+			/* We want to leave the buffers for this frame intact. */
+			/* Move on to next possible frame. */
+
+			start_of_frame_found = false;
+			end_of_frame_found = true;
+		}
+
+  		/* advance to next buffer entry in linked list */
+  		end_index++;
+  		if ( end_index == info->rx_buffer_count )
+  			end_index = 0;
+
+		if ( start_index == end_index )
+		{
+			/* The entire list has been searched with all Counts == 0 and */
+			/* all Status == 0. The receive buffers are */
+			/* completely screwed, reset all receive buffers! */
+			mgsl_reset_rx_dma_buffers( info );
+			frame_start_index = 0;
+			start_of_frame_found = false;
+			reprogram_dma = true;
+			break;
+		}
+	}
+
+	if ( start_of_frame_found && !end_of_frame_found )
+	{
+		/* There is an unfinished string of receive DMA buffers */
+		/* as a result of the receiver overrun. */
+
+		/* Reset the buffers for the unfinished frame */
+		/* and reprogram the receive DMA controller to start */
+		/* at the 1st buffer of unfinished frame. */
+
+		start_index = frame_start_index;
+
+		do
+		{
+			*((unsigned long *)&(info->rx_buffer_list[start_index++].count)) = DMABUFFERSIZE;
+
+  			/* Adjust index for wrap around. */
+  			if ( start_index == info->rx_buffer_count )
+  				start_index = 0;
+
+		} while( start_index != end_index );
+
+		reprogram_dma = true;
+	}
+
+	if ( reprogram_dma )
+	{
+		usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA|RECEIVE_STATUS);
+		usc_UnlatchRxstatusBits(info, RECEIVE_DATA|RECEIVE_STATUS);
+		
+		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+		
+		/* This empties the receive FIFO and loads the RCC with RCLR */
+		usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
+
+		/* program 16C32 with physical address of 1st DMA buffer entry */
+		phys_addr = info->rx_buffer_list[frame_start_index].phys_entry;
+		usc_OutDmaReg( info, NRARL, (u16)phys_addr );
+		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
+
+		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
+		usc_EnableInterrupts( info, RECEIVE_STATUS );
+
+		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
+		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
+
+		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
+		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
+		usc_DmaCmd( info, DmaCmd_InitRxChannel );
+		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
+			usc_EnableReceiver(info,ENABLE_AUTO_DCD);
+		else
+			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
+	}
+	else
+	{
+		/* This empties the receive FIFO and loads the RCC with RCLR */
+		usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
+		usc_RTCmd( info, RTCmd_PurgeRxFifo );
+	}
+
+}	/* end of usc_process_rxoverrun_sync() */
+
+/* usc_stop_receiver()
+ *
+ *	Disable USC receiver
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_stop_receiver( struct mgsl_struct *info )
+{
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):usc_stop_receiver(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+	/* Disable receive DMA channel. */
+	/* This also disables receive DMA channel interrupts */
+	usc_DmaCmd( info, DmaCmd_ResetRxChannel );
+
+	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+	usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
+	usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS );
+
+	usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
+
+	/* This empties the receive FIFO and loads the RCC with RCLR */
+	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
+	usc_RTCmd( info, RTCmd_PurgeRxFifo );
+
+	info->rx_enabled = false;
+	info->rx_overflow = false;
+	info->rx_rcc_underrun = false;
+	
+}	/* end of stop_receiver() */
+
+/* usc_start_receiver()
+ *
+ *	Enable the USC receiver 
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_start_receiver( struct mgsl_struct *info )
+{
+	u32 phys_addr;
+	
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):usc_start_receiver(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	mgsl_reset_rx_dma_buffers( info );
+	usc_stop_receiver( info );
+
+	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
+	usc_RTCmd( info, RTCmd_PurgeRxFifo );
+
+	if ( info->params.mode == MGSL_MODE_HDLC ||
+		info->params.mode == MGSL_MODE_RAW ) {
+		/* DMA mode Transfers */
+		/* Program the DMA controller. */
+		/* Enable the DMA controller end of buffer interrupt. */
+
+		/* program 16C32 with physical address of 1st DMA buffer entry */
+		phys_addr = info->rx_buffer_list[0].phys_entry;
+		usc_OutDmaReg( info, NRARL, (u16)phys_addr );
+		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
+
+		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
+		usc_EnableInterrupts( info, RECEIVE_STATUS );
+
+		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
+		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
+
+		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
+		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
+		usc_DmaCmd( info, DmaCmd_InitRxChannel );
+		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
+			usc_EnableReceiver(info,ENABLE_AUTO_DCD);
+		else
+			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
+	} else {
+		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
+		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
+		usc_EnableInterrupts(info, RECEIVE_DATA);
+
+		usc_RTCmd( info, RTCmd_PurgeRxFifo );
+		usc_RCmd( info, RCmd_EnterHuntmode );
+
+		usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
+	}
+
+	usc_OutReg( info, CCSR, 0x1020 );
+
+	info->rx_enabled = true;
+
+}	/* end of usc_start_receiver() */
+
+/* usc_start_transmitter()
+ *
+ *	Enable the USC transmitter and send a transmit frame if
+ *	one is loaded in the DMA buffers.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_start_transmitter( struct mgsl_struct *info )
+{
+	u32 phys_addr;
+	unsigned int FrameSize;
+
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):usc_start_transmitter(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+	if ( info->xmit_cnt ) {
+
+		/* If auto RTS enabled and RTS is inactive, then assert */
+		/* RTS and set a flag indicating that the driver should */
+		/* negate RTS when the transmission completes. */
+
+		info->drop_rts_on_tx_done = false;
+
+		if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
+			usc_get_serial_signals( info );
+			if ( !(info->serial_signals & SerialSignal_RTS) ) {
+				info->serial_signals |= SerialSignal_RTS;
+				usc_set_serial_signals( info );
+				info->drop_rts_on_tx_done = true;
+			}
+		}
+
+
+		if ( info->params.mode == MGSL_MODE_ASYNC ) {
+			if ( !info->tx_active ) {
+				usc_UnlatchTxstatusBits(info, TXSTATUS_ALL);
+				usc_ClearIrqPendingBits(info, TRANSMIT_STATUS + TRANSMIT_DATA);
+				usc_EnableInterrupts(info, TRANSMIT_DATA);
+				usc_load_txfifo(info);
+			}
+		} else {
+			/* Disable transmit DMA controller while programming. */
+			usc_DmaCmd( info, DmaCmd_ResetTxChannel );
+			
+			/* Transmit DMA buffer is loaded, so program USC */
+			/* to send the frame contained in the buffers.	 */
+
+			FrameSize = info->tx_buffer_list[info->start_tx_dma_buffer].rcc;
+
+			/* if operating in Raw sync mode, reset the rcc component
+			 * of the tx dma buffer entry, otherwise, the serial controller
+			 * will send a closing sync char after this count.
+			 */
+	    		if ( info->params.mode == MGSL_MODE_RAW )
+				info->tx_buffer_list[info->start_tx_dma_buffer].rcc = 0;
+
+			/* Program the Transmit Character Length Register (TCLR) */
+			/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
+			usc_OutReg( info, TCLR, (u16)FrameSize );
+
+			usc_RTCmd( info, RTCmd_PurgeTxFifo );
+
+			/* Program the address of the 1st DMA Buffer Entry in linked list */
+			phys_addr = info->tx_buffer_list[info->start_tx_dma_buffer].phys_entry;
+			usc_OutDmaReg( info, NTARL, (u16)phys_addr );
+			usc_OutDmaReg( info, NTARU, (u16)(phys_addr >> 16) );
+
+			usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
+			usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
+			usc_EnableInterrupts( info, TRANSMIT_STATUS );
+
+			if ( info->params.mode == MGSL_MODE_RAW &&
+					info->num_tx_dma_buffers > 1 ) {
+			   /* When running external sync mode, attempt to 'stream' transmit  */
+			   /* by filling tx dma buffers as they become available. To do this */
+			   /* we need to enable Tx DMA EOB Status interrupts :               */
+			   /*                                                                */
+			   /* 1. Arm End of Buffer (EOB) Transmit DMA Interrupt (BIT2 of TDIAR) */
+			   /* 2. Enable Transmit DMA Interrupts (BIT0 of DICR) */
+
+			   usc_OutDmaReg( info, TDIAR, BIT2|BIT3 );
+			   usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT0) );
+			}
+
+			/* Initialize Transmit DMA Channel */
+			usc_DmaCmd( info, DmaCmd_InitTxChannel );
+			
+			usc_TCmd( info, TCmd_SendFrame );
+			
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
+		}
+		info->tx_active = true;
+	}
+
+	if ( !info->tx_enabled ) {
+		info->tx_enabled = true;
+		if ( info->params.flags & HDLC_FLAG_AUTO_CTS )
+			usc_EnableTransmitter(info,ENABLE_AUTO_CTS);
+		else
+			usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL);
+	}
+
+}	/* end of usc_start_transmitter() */
+
+/* usc_stop_transmitter()
+ *
+ *	Stops the transmitter and DMA
+ *
+ * Arguments:		info	pointer to device isntance data
+ * Return Value:	None
+ */
+static void usc_stop_transmitter( struct mgsl_struct *info )
+{
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):usc_stop_transmitter(%s)\n",
+			 __FILE__,__LINE__, info->device_name );
+			 
+	del_timer(&info->tx_timer);	
+			 
+	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
+	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA );
+	usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA );
+
+	usc_EnableTransmitter(info,DISABLE_UNCONDITIONAL);
+	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
+	usc_RTCmd( info, RTCmd_PurgeTxFifo );
+
+	info->tx_enabled = false;
+	info->tx_active = false;
+
+}	/* end of usc_stop_transmitter() */
+
+/* usc_load_txfifo()
+ *
+ *	Fill the transmit FIFO until the FIFO is full or
+ *	there is no more data to load.
+ *
+ * Arguments:		info	pointer to device extension (instance data)
+ * Return Value:	None
+ */
+static void usc_load_txfifo( struct mgsl_struct *info )
+{
+	int Fifocount;
+	u8 TwoBytes[2];
+	
+	if ( !info->xmit_cnt && !info->x_char )
+		return; 
+		
+	/* Select transmit FIFO status readback in TICR */
+	usc_TCmd( info, TCmd_SelectTicrTxFifostatus );
+
+	/* load the Transmit FIFO until FIFOs full or all data sent */
+
+	while( (Fifocount = usc_InReg(info, TICR) >> 8) && info->xmit_cnt ) {
+		/* there is more space in the transmit FIFO and */
+		/* there is more data in transmit buffer */
+
+		if ( (info->xmit_cnt > 1) && (Fifocount > 1) && !info->x_char ) {
+ 			/* write a 16-bit word from transmit buffer to 16C32 */
+				
+			TwoBytes[0] = info->xmit_buf[info->xmit_tail++];
+			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+			TwoBytes[1] = info->xmit_buf[info->xmit_tail++];
+			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+			
+			outw( *((u16 *)TwoBytes), info->io_base + DATAREG);
+				
+			info->xmit_cnt -= 2;
+			info->icount.tx += 2;
+		} else {
+			/* only 1 byte left to transmit or 1 FIFO slot left */
+			
+			outw( (inw( info->io_base + CCAR) & 0x0780) | (TDR+LSBONLY),
+				info->io_base + CCAR );
+			
+			if (info->x_char) {
+				/* transmit pending high priority char */
+				outw( info->x_char,info->io_base + CCAR );
+				info->x_char = 0;
+			} else {
+				outw( info->xmit_buf[info->xmit_tail++],info->io_base + CCAR );
+				info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+				info->xmit_cnt--;
+			}
+			info->icount.tx++;
+		}
+	}
+
+}	/* end of usc_load_txfifo() */
+
+/* usc_reset()
+ *
+ *	Reset the adapter to a known state and prepare it for further use.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_reset( struct mgsl_struct *info )
+{
+	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
+		int i;
+		u32 readval;
+
+		/* Set BIT30 of Misc Control Register */
+		/* (Local Control Register 0x50) to force reset of USC. */
+
+		volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
+		u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);
+
+		info->misc_ctrl_value |= BIT30;
+		*MiscCtrl = info->misc_ctrl_value;
+
+		/*
+		 * Force at least 170ns delay before clearing 
+		 * reset bit. Each read from LCR takes at least 
+		 * 30ns so 10 times for 300ns to be safe.
+		 */
+		for(i=0;i<10;i++)
+			readval = *MiscCtrl;
+
+		info->misc_ctrl_value &= ~BIT30;
+		*MiscCtrl = info->misc_ctrl_value;
+
+		*LCR0BRDR = BUS_DESCRIPTOR(
+			1,		// Write Strobe Hold (0-3)
+			2,		// Write Strobe Delay (0-3)
+			2,		// Read Strobe Delay  (0-3)
+			0,		// NWDD (Write data-data) (0-3)
+			4,		// NWAD (Write Addr-data) (0-31)
+			0,		// NXDA (Read/Write Data-Addr) (0-3)
+			0,		// NRDD (Read Data-Data) (0-3)
+			5		// NRAD (Read Addr-Data) (0-31)
+			);
+	} else {
+		/* do HW reset */
+		outb( 0,info->io_base + 8 );
+	}
+
+	info->mbre_bit = 0;
+	info->loopback_bits = 0;
+	info->usc_idle_mode = 0;
+
+	/*
+	 * Program the Bus Configuration Register (BCR)
+	 *
+	 * <15>		0	Don't use separate address
+	 * <14..6>	0	reserved
+	 * <5..4>	00	IAckmode = Default, don't care
+	 * <3>		1	Bus Request Totem Pole output
+	 * <2>		1	Use 16 Bit data bus
+	 * <1>		0	IRQ Totem Pole output
+	 * <0>		0	Don't Shift Right Addr
+	 *
+	 * 0000 0000 0000 1100 = 0x000c
+	 *
+	 * By writing to io_base + SDPIN the Wait/Ack pin is
+	 * programmed to work as a Wait pin.
+	 */
+	
+	outw( 0x000c,info->io_base + SDPIN );
+
+
+	outw( 0,info->io_base );
+	outw( 0,info->io_base + CCAR );
+
+	/* select little endian byte ordering */
+	usc_RTCmd( info, RTCmd_SelectLittleEndian );
+
+
+	/* Port Control Register (PCR)
+	 *
+	 * <15..14>	11	Port 7 is Output (~DMAEN, Bit 14 : 0 = Enabled)
+	 * <13..12>	11	Port 6 is Output (~INTEN, Bit 12 : 0 = Enabled)
+	 * <11..10> 	00	Port 5 is Input (No Connect, Don't Care)
+	 * <9..8> 	00	Port 4 is Input (No Connect, Don't Care)
+	 * <7..6>	11	Port 3 is Output (~RTS, Bit 6 : 0 = Enabled )
+	 * <5..4>	11	Port 2 is Output (~DTR, Bit 4 : 0 = Enabled )
+	 * <3..2>	01	Port 1 is Input (Dedicated RxC)
+	 * <1..0>	01	Port 0 is Input (Dedicated TxC)
+	 *
+	 *	1111 0000 1111 0101 = 0xf0f5
+	 */
+
+	usc_OutReg( info, PCR, 0xf0f5 );
+
+
+	/*
+	 * Input/Output Control Register
+	 *
+	 * <15..14>	00	CTS is active low input
+	 * <13..12>	00	DCD is active low input
+	 * <11..10>	00	TxREQ pin is input (DSR)
+	 * <9..8>	00	RxREQ pin is input (RI)
+	 * <7..6>	00	TxD is output (Transmit Data)
+	 * <5..3>	000	TxC Pin in Input (14.7456MHz Clock)
+	 * <2..0>	100	RxC is Output (drive with BRG0)
+	 *
+	 *	0000 0000 0000 0100 = 0x0004
+	 */
+
+	usc_OutReg( info, IOCR, 0x0004 );
+
+}	/* end of usc_reset() */
+
+/* usc_set_async_mode()
+ *
+ *	Program adapter for asynchronous communications.
+ *
+ * Arguments:		info		pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_set_async_mode( struct mgsl_struct *info )
+{
+	u16 RegValue;
+
+	/* disable interrupts while programming USC */
+	usc_DisableMasterIrqBit( info );
+
+	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
+	usc_DmaCmd( info, DmaCmd_ResetAllChannels );	/* disable both DMA channels */
+
+	usc_loopback_frame( info );
+
+	/* Channel mode Register (CMR)
+	 *
+	 * <15..14>	00	Tx Sub modes, 00 = 1 Stop Bit
+	 * <13..12>	00	              00 = 16X Clock
+	 * <11..8>	0000	Transmitter mode = Asynchronous
+	 * <7..6>	00	reserved?
+	 * <5..4>	00	Rx Sub modes, 00 = 16X Clock
+	 * <3..0>	0000	Receiver mode = Asynchronous
+	 *
+	 * 0000 0000 0000 0000 = 0x0
+	 */
+
+	RegValue = 0;
+	if ( info->params.stop_bits != 1 )
+		RegValue |= BIT14;
+	usc_OutReg( info, CMR, RegValue );
+
+	
+	/* Receiver mode Register (RMR)
+	 *
+	 * <15..13>	000	encoding = None
+	 * <12..08>	00000	reserved (Sync Only)
+	 * <7..6>   	00	Even parity
+	 * <5>		0	parity disabled
+	 * <4..2>	000	Receive Char Length = 8 bits
+	 * <1..0>	00	Disable Receiver
+	 *
+	 * 0000 0000 0000 0000 = 0x0
+	 */
+
+	RegValue = 0;
+
+	if ( info->params.data_bits != 8 )
+		RegValue |= BIT4+BIT3+BIT2;
+
+	if ( info->params.parity != ASYNC_PARITY_NONE ) {
+		RegValue |= BIT5;
+		if ( info->params.parity != ASYNC_PARITY_ODD )
+			RegValue |= BIT6;
+	}
+
+	usc_OutReg( info, RMR, RegValue );
+
+
+	/* Set IRQ trigger level */
+
+	usc_RCmd( info, RCmd_SelectRicrIntLevel );
+
+	
+	/* Receive Interrupt Control Register (RICR)
+	 *
+	 * <15..8>	?		RxFIFO IRQ Request Level
+	 *
+	 * Note: For async mode the receive FIFO level must be set
+	 * to 0 to avoid the situation where the FIFO contains fewer bytes
+	 * than the trigger level and no more data is expected.
+	 *
+	 * <7>		0		Exited Hunt IA (Interrupt Arm)
+	 * <6>		0		Idle Received IA
+	 * <5>		0		Break/Abort IA
+	 * <4>		0		Rx Bound IA
+	 * <3>		0		Queued status reflects oldest byte in FIFO
+	 * <2>		0		Abort/PE IA
+	 * <1>		0		Rx Overrun IA
+	 * <0>		0		Select TC0 value for readback
+	 *
+	 * 0000 0000 0100 0000 = 0x0000 + (FIFOLEVEL in MSB)
+	 */
+	
+	usc_OutReg( info, RICR, 0x0000 );
+
+	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
+	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
+
+	
+	/* Transmit mode Register (TMR)
+	 *
+	 * <15..13>	000	encoding = None
+	 * <12..08>	00000	reserved (Sync Only)
+	 * <7..6>	00	Transmit parity Even
+	 * <5>		0	Transmit parity Disabled
+	 * <4..2>	000	Tx Char Length = 8 bits
+	 * <1..0>	00	Disable Transmitter
+	 *
+	 * 0000 0000 0000 0000 = 0x0
+	 */
+
+	RegValue = 0;
+
+	if ( info->params.data_bits != 8 )
+		RegValue |= BIT4+BIT3+BIT2;
+
+	if ( info->params.parity != ASYNC_PARITY_NONE ) {
+		RegValue |= BIT5;
+		if ( info->params.parity != ASYNC_PARITY_ODD )
+			RegValue |= BIT6;
+	}
+
+	usc_OutReg( info, TMR, RegValue );
+
+	usc_set_txidle( info );
+
+
+	/* Set IRQ trigger level */
+
+	usc_TCmd( info, TCmd_SelectTicrIntLevel );
+
+	
+	/* Transmit Interrupt Control Register (TICR)
+	 *
+	 * <15..8>	?	Transmit FIFO IRQ Level
+	 * <7>		0	Present IA (Interrupt Arm)
+	 * <6>		1	Idle Sent IA
+	 * <5>		0	Abort Sent IA
+	 * <4>		0	EOF/EOM Sent IA
+	 * <3>		0	CRC Sent IA
+	 * <2>		0	1 = Wait for SW Trigger to Start Frame
+	 * <1>		0	Tx Underrun IA
+	 * <0>		0	TC0 constant on read back
+	 *
+	 *	0000 0000 0100 0000 = 0x0040
+	 */
+
+	usc_OutReg( info, TICR, 0x1f40 );
+
+	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
+	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
+
+	usc_enable_async_clock( info, info->params.data_rate );
+
+	
+	/* Channel Control/status Register (CCSR)
+	 *
+	 * <15>		X	RCC FIFO Overflow status (RO)
+	 * <14>		X	RCC FIFO Not Empty status (RO)
+	 * <13>		0	1 = Clear RCC FIFO (WO)
+	 * <12>		X	DPLL in Sync status (RO)
+	 * <11>		X	DPLL 2 Missed Clocks status (RO)
+	 * <10>		X	DPLL 1 Missed Clock status (RO)
+	 * <9..8>	00	DPLL Resync on rising and falling edges (RW)
+	 * <7>		X	SDLC Loop On status (RO)
+	 * <6>		X	SDLC Loop Send status (RO)
+	 * <5>		1	Bypass counters for TxClk and RxClk (RW)
+	 * <4..2>   	000	Last Char of SDLC frame has 8 bits (RW)
+	 * <1..0>   	00	reserved
+	 *
+	 *	0000 0000 0010 0000 = 0x0020
+	 */
+	
+	usc_OutReg( info, CCSR, 0x0020 );
+
+	usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA +
+			      RECEIVE_DATA + RECEIVE_STATUS );
+
+	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA +
+				RECEIVE_DATA + RECEIVE_STATUS );
+
+	usc_EnableMasterIrqBit( info );
+
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable INTEN (Port 6, Bit12) */
+		/* This connects the IRQ request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	}
+
+	if (info->params.loopback) {
+		info->loopback_bits = 0x300;
+		outw(0x0300, info->io_base + CCAR);
+	}
+
+}	/* end of usc_set_async_mode() */
+
+/* usc_loopback_frame()
+ *
+ *	Loop back a small (2 byte) dummy SDLC frame.
+ *	Interrupts and DMA are NOT used. The purpose of this is to
+ *	clear any 'stale' status info left over from running in	async mode.
+ *
+ *	The 16C32 shows the strange behaviour of marking the 1st
+ *	received SDLC frame with a CRC error even when there is no
+ *	CRC error. To get around this a small dummy from of 2 bytes
+ *	is looped back when switching from async to sync mode.
+ *
+ * Arguments:		info		pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_loopback_frame( struct mgsl_struct *info )
+{
+	int i;
+	unsigned long oldmode = info->params.mode;
+
+	info->params.mode = MGSL_MODE_HDLC;
+	
+	usc_DisableMasterIrqBit( info );
+
+	usc_set_sdlc_mode( info );
+	usc_enable_loopback( info, 1 );
+
+	/* Write 16-bit Time Constant for BRG0 */
+	usc_OutReg( info, TC0R, 0 );
+	
+	/* Channel Control Register (CCR)
+	 *
+	 * <15..14>	00	Don't use 32-bit Tx Control Blocks (TCBs)
+	 * <13>		0	Trigger Tx on SW Command Disabled
+	 * <12>		0	Flag Preamble Disabled
+	 * <11..10>	00	Preamble Length = 8-Bits
+	 * <9..8>	01	Preamble Pattern = flags
+	 * <7..6>	10	Don't use 32-bit Rx status Blocks (RSBs)
+	 * <5>		0	Trigger Rx on SW Command Disabled
+	 * <4..0>	0	reserved
+	 *
+	 *	0000 0001 0000 0000 = 0x0100
+	 */
+
+	usc_OutReg( info, CCR, 0x0100 );
+
+	/* SETUP RECEIVER */
+	usc_RTCmd( info, RTCmd_PurgeRxFifo );
+	usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
+
+	/* SETUP TRANSMITTER */
+	/* Program the Transmit Character Length Register (TCLR) */
+	/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
+	usc_OutReg( info, TCLR, 2 );
+	usc_RTCmd( info, RTCmd_PurgeTxFifo );
+
+	/* unlatch Tx status bits, and start transmit channel. */
+	usc_UnlatchTxstatusBits(info,TXSTATUS_ALL);
+	outw(0,info->io_base + DATAREG);
+
+	/* ENABLE TRANSMITTER */
+	usc_TCmd( info, TCmd_SendFrame );
+	usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL);
+							
+	/* WAIT FOR RECEIVE COMPLETE */
+	for (i=0 ; i<1000 ; i++)
+		if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1))
+			break;
+
+	/* clear Internal Data loopback mode */
+	usc_enable_loopback(info, 0);
+
+	usc_EnableMasterIrqBit(info);
+
+	info->params.mode = oldmode;
+
+}	/* end of usc_loopback_frame() */
+
+/* usc_set_sync_mode()	Programs the USC for SDLC communications.
+ *
+ * Arguments:		info	pointer to adapter info structure
+ * Return Value:	None
+ */
+static void usc_set_sync_mode( struct mgsl_struct *info )
+{
+	usc_loopback_frame( info );
+	usc_set_sdlc_mode( info );
+
+	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
+		/* Enable INTEN (Port 6, Bit12) */
+		/* This connects the IRQ request signal to the ISA bus */
+		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
+	}
+
+	usc_enable_aux_clock(info, info->params.clock_speed);
+
+	if (info->params.loopback)
+		usc_enable_loopback(info,1);
+
+}	/* end of mgsl_set_sync_mode() */
+
+/* usc_set_txidle()	Set the HDLC idle mode for the transmitter.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_set_txidle( struct mgsl_struct *info )
+{
+	u16 usc_idle_mode = IDLEMODE_FLAGS;
+
+	/* Map API idle mode to USC register bits */
+
+	switch( info->idle_mode ){
+	case HDLC_TXIDLE_FLAGS:			usc_idle_mode = IDLEMODE_FLAGS; break;
+	case HDLC_TXIDLE_ALT_ZEROS_ONES:	usc_idle_mode = IDLEMODE_ALT_ONE_ZERO; break;
+	case HDLC_TXIDLE_ZEROS:			usc_idle_mode = IDLEMODE_ZERO; break;
+	case HDLC_TXIDLE_ONES:			usc_idle_mode = IDLEMODE_ONE; break;
+	case HDLC_TXIDLE_ALT_MARK_SPACE:	usc_idle_mode = IDLEMODE_ALT_MARK_SPACE; break;
+	case HDLC_TXIDLE_SPACE:			usc_idle_mode = IDLEMODE_SPACE; break;
+	case HDLC_TXIDLE_MARK:			usc_idle_mode = IDLEMODE_MARK; break;
+	}
+
+	info->usc_idle_mode = usc_idle_mode;
+	//usc_OutReg(info, TCSR, usc_idle_mode);
+	info->tcsr_value &= ~IDLEMODE_MASK;	/* clear idle mode bits */
+	info->tcsr_value += usc_idle_mode;
+	usc_OutReg(info, TCSR, info->tcsr_value);
+
+	/*
+	 * if SyncLink WAN adapter is running in external sync mode, the
+	 * transmitter has been set to Monosync in order to try to mimic
+	 * a true raw outbound bit stream. Monosync still sends an open/close
+	 * sync char at the start/end of a frame. Try to match those sync
+	 * patterns to the idle mode set here
+	 */
+	if ( info->params.mode == MGSL_MODE_RAW ) {
+		unsigned char syncpat = 0;
+		switch( info->idle_mode ) {
+		case HDLC_TXIDLE_FLAGS:
+			syncpat = 0x7e;
+			break;
+		case HDLC_TXIDLE_ALT_ZEROS_ONES:
+			syncpat = 0x55;
+			break;
+		case HDLC_TXIDLE_ZEROS:
+		case HDLC_TXIDLE_SPACE:
+			syncpat = 0x00;
+			break;
+		case HDLC_TXIDLE_ONES:
+		case HDLC_TXIDLE_MARK:
+			syncpat = 0xff;
+			break;
+		case HDLC_TXIDLE_ALT_MARK_SPACE:
+			syncpat = 0xaa;
+			break;
+		}
+
+		usc_SetTransmitSyncChars(info,syncpat,syncpat);
+	}
+
+}	/* end of usc_set_txidle() */
+
+/* usc_get_serial_signals()
+ *
+ *	Query the adapter for the state of the V24 status (input) signals.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_get_serial_signals( struct mgsl_struct *info )
+{
+	u16 status;
+
+	/* clear all serial signals except DTR and RTS */
+	info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
+
+	/* Read the Misc Interrupt status Register (MISR) to get */
+	/* the V24 status signals. */
+
+	status = usc_InReg( info, MISR );
+
+	/* set serial signal bits to reflect MISR */
+
+	if ( status & MISCSTATUS_CTS )
+		info->serial_signals |= SerialSignal_CTS;
+
+	if ( status & MISCSTATUS_DCD )
+		info->serial_signals |= SerialSignal_DCD;
+
+	if ( status & MISCSTATUS_RI )
+		info->serial_signals |= SerialSignal_RI;
+
+	if ( status & MISCSTATUS_DSR )
+		info->serial_signals |= SerialSignal_DSR;
+
+}	/* end of usc_get_serial_signals() */
+
+/* usc_set_serial_signals()
+ *
+ *	Set the state of DTR and RTS based on contents of
+ *	serial_signals member of device extension.
+ *	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void usc_set_serial_signals( struct mgsl_struct *info )
+{
+	u16 Control;
+	unsigned char V24Out = info->serial_signals;
+
+	/* get the current value of the Port Control Register (PCR) */
+
+	Control = usc_InReg( info, PCR );
+
+	if ( V24Out & SerialSignal_RTS )
+		Control &= ~(BIT6);
+	else
+		Control |= BIT6;
+
+	if ( V24Out & SerialSignal_DTR )
+		Control &= ~(BIT4);
+	else
+		Control |= BIT4;
+
+	usc_OutReg( info, PCR, Control );
+
+}	/* end of usc_set_serial_signals() */
+
+/* usc_enable_async_clock()
+ *
+ *	Enable the async clock at the specified frequency.
+ *
+ * Arguments:		info		pointer to device instance data
+ *			data_rate	data rate of clock in bps
+ *					0 disables the AUX clock.
+ * Return Value:	None
+ */
+static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
+{
+	if ( data_rate )	{
+		/*
+		 * Clock mode Control Register (CMCR)
+		 * 
+		 * <15..14>     00      counter 1 Disabled
+		 * <13..12>     00      counter 0 Disabled
+		 * <11..10>     11      BRG1 Input is TxC Pin
+		 * <9..8>       11      BRG0 Input is TxC Pin
+		 * <7..6>       01      DPLL Input is BRG1 Output
+		 * <5..3>       100     TxCLK comes from BRG0
+		 * <2..0>       100     RxCLK comes from BRG0
+		 *
+		 * 0000 1111 0110 0100 = 0x0f64
+		 */
+		
+		usc_OutReg( info, CMCR, 0x0f64 );
+
+
+		/*
+		 * Write 16-bit Time Constant for BRG0
+		 * Time Constant = (ClkSpeed / data_rate) - 1
+		 * ClkSpeed = 921600 (ISA), 691200 (PCI)
+		 */
+
+		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+			usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
+		else
+			usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) );
+
+		
+		/*
+		 * Hardware Configuration Register (HCR)
+		 * Clear Bit 1, BRG0 mode = Continuous
+		 * Set Bit 0 to enable BRG0.
+		 */
+
+		usc_OutReg( info, HCR,
+			    (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
+
+
+		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
+
+		usc_OutReg( info, IOCR,
+			    (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) );
+	} else {
+		/* data rate == 0 so turn off BRG0 */
+		usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) );
+	}
+
+}	/* end of usc_enable_async_clock() */
+
+/*
+ * Buffer Structures:
+ *
+ * Normal memory access uses virtual addresses that can make discontiguous
+ * physical memory pages appear to be contiguous in the virtual address
+ * space (the processors memory mapping handles the conversions).
+ *
+ * DMA transfers require physically contiguous memory. This is because
+ * the DMA system controller and DMA bus masters deal with memory using
+ * only physical addresses.
+ *
+ * This causes a problem under Windows NT when large DMA buffers are
+ * needed. Fragmentation of the nonpaged pool prevents allocations of
+ * physically contiguous buffers larger than the PAGE_SIZE.
+ *
+ * However the 16C32 supports Bus Master Scatter/Gather DMA which
+ * allows DMA transfers to physically discontiguous buffers. Information
+ * about each data transfer buffer is contained in a memory structure
+ * called a 'buffer entry'. A list of buffer entries is maintained
+ * to track and control the use of the data transfer buffers.
+ *
+ * To support this strategy we will allocate sufficient PAGE_SIZE
+ * contiguous memory buffers to allow for the total required buffer
+ * space.
+ *
+ * The 16C32 accesses the list of buffer entries using Bus Master
+ * DMA. Control information is read from the buffer entries by the
+ * 16C32 to control data transfers. status information is written to
+ * the buffer entries by the 16C32 to indicate the status of completed
+ * transfers.
+ *
+ * The CPU writes control information to the buffer entries to control
+ * the 16C32 and reads status information from the buffer entries to
+ * determine information about received and transmitted frames.
+ *
+ * Because the CPU and 16C32 (adapter) both need simultaneous access
+ * to the buffer entries, the buffer entry memory is allocated with
+ * HalAllocateCommonBuffer(). This restricts the size of the buffer
+ * entry list to PAGE_SIZE.
+ *
+ * The actual data buffers on the other hand will only be accessed
+ * by the CPU or the adapter but not by both simultaneously. This allows
+ * Scatter/Gather packet based DMA procedures for using physically
+ * discontiguous pages.
+ */
+
+/*
+ * mgsl_reset_tx_dma_buffers()
+ *
+ * 	Set the count for all transmit buffers to 0 to indicate the
+ * 	buffer is available for use and set the current buffer to the
+ * 	first buffer. This effectively makes all buffers free and
+ * 	discards any data in buffers.
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
+{
+	unsigned int i;
+
+	for ( i = 0; i < info->tx_buffer_count; i++ ) {
+		*((unsigned long *)&(info->tx_buffer_list[i].count)) = 0;
+	}
+
+	info->current_tx_buffer = 0;
+	info->start_tx_dma_buffer = 0;
+	info->tx_dma_buffers_used = 0;
+
+	info->get_tx_holding_index = 0;
+	info->put_tx_holding_index = 0;
+	info->tx_holding_count = 0;
+
+}	/* end of mgsl_reset_tx_dma_buffers() */
+
+/*
+ * num_free_tx_dma_buffers()
+ *
+ * 	returns the number of free tx dma buffers available
+ *
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	number of free tx dma buffers
+ */
+static int num_free_tx_dma_buffers(struct mgsl_struct *info)
+{
+	return info->tx_buffer_count - info->tx_dma_buffers_used;
+}
+
+/*
+ * mgsl_reset_rx_dma_buffers()
+ * 
+ * 	Set the count for all receive buffers to DMABUFFERSIZE
+ * 	and set the current buffer to the first buffer. This effectively
+ * 	makes all buffers free and discards any data in buffers.
+ * 
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
+{
+	unsigned int i;
+
+	for ( i = 0; i < info->rx_buffer_count; i++ ) {
+		*((unsigned long *)&(info->rx_buffer_list[i].count)) = DMABUFFERSIZE;
+//		info->rx_buffer_list[i].count = DMABUFFERSIZE;
+//		info->rx_buffer_list[i].status = 0;
+	}
+
+	info->current_rx_buffer = 0;
+
+}	/* end of mgsl_reset_rx_dma_buffers() */
+
+/*
+ * mgsl_free_rx_frame_buffers()
+ * 
+ * 	Free the receive buffers used by a received SDLC
+ * 	frame such that the buffers can be reused.
+ * 
+ * Arguments:
+ * 
+ * 	info			pointer to device instance data
+ * 	StartIndex		index of 1st receive buffer of frame
+ * 	EndIndex		index of last receive buffer of frame
+ * 
+ * Return Value:	None
+ */
+static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
+{
+	bool Done = false;
+	DMABUFFERENTRY *pBufEntry;
+	unsigned int Index;
+
+	/* Starting with 1st buffer entry of the frame clear the status */
+	/* field and set the count field to DMA Buffer Size. */
+
+	Index = StartIndex;
+
+	while( !Done ) {
+		pBufEntry = &(info->rx_buffer_list[Index]);
+
+		if ( Index == EndIndex ) {
+			/* This is the last buffer of the frame! */
+			Done = true;
+		}
+
+		/* reset current buffer for reuse */
+//		pBufEntry->status = 0;
+//		pBufEntry->count = DMABUFFERSIZE;
+		*((unsigned long *)&(pBufEntry->count)) = DMABUFFERSIZE;
+
+		/* advance to next buffer entry in linked list */
+		Index++;
+		if ( Index == info->rx_buffer_count )
+			Index = 0;
+	}
+
+	/* set current buffer to next buffer after last buffer of frame */
+	info->current_rx_buffer = Index;
+
+}	/* end of free_rx_frame_buffers() */
+
+/* mgsl_get_rx_frame()
+ * 
+ * 	This function attempts to return a received SDLC frame from the
+ * 	receive DMA buffers. Only frames received without errors are returned.
+ *
+ * Arguments:	 	info	pointer to device extension
+ * Return Value:	true if frame returned, otherwise false
+ */
+static bool mgsl_get_rx_frame(struct mgsl_struct *info)
+{
+	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
+	unsigned short status;
+	DMABUFFERENTRY *pBufEntry;
+	unsigned int framesize = 0;
+	bool ReturnCode = false;
+	unsigned long flags;
+	struct tty_struct *tty = info->port.tty;
+	bool return_frame = false;
+	
+	/*
+	 * current_rx_buffer points to the 1st buffer of the next available
+	 * receive frame. To find the last buffer of the frame look for
+	 * a non-zero status field in the buffer entries. (The status
+	 * field is set by the 16C32 after completing a receive frame.
+	 */
+
+	StartIndex = EndIndex = info->current_rx_buffer;
+
+	while( !info->rx_buffer_list[EndIndex].status ) {
+		/*
+		 * If the count field of the buffer entry is non-zero then
+		 * this buffer has not been used. (The 16C32 clears the count
+		 * field when it starts using the buffer.) If an unused buffer
+		 * is encountered then there are no frames available.
+		 */
+
+		if ( info->rx_buffer_list[EndIndex].count )
+			goto Cleanup;
+
+		/* advance to next buffer entry in linked list */
+		EndIndex++;
+		if ( EndIndex == info->rx_buffer_count )
+			EndIndex = 0;
+
+		/* if entire list searched then no frame available */
+		if ( EndIndex == StartIndex ) {
+			/* If this occurs then something bad happened,
+			 * all buffers have been 'used' but none mark
+			 * the end of a frame. Reset buffers and receiver.
+			 */
+
+			if ( info->rx_enabled ){
+				spin_lock_irqsave(&info->irq_spinlock,flags);
+				usc_start_receiver(info);
+				spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			}
+			goto Cleanup;
+		}
+	}
+
+
+	/* check status of receive frame */
+	
+	status = info->rx_buffer_list[EndIndex].status;
+
+	if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
+			RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
+		if ( status & RXSTATUS_SHORT_FRAME )
+			info->icount.rxshort++;
+		else if ( status & RXSTATUS_ABORT )
+			info->icount.rxabort++;
+		else if ( status & RXSTATUS_OVERRUN )
+			info->icount.rxover++;
+		else {
+			info->icount.rxcrc++;
+			if ( info->params.crc_type & HDLC_CRC_RETURN_EX )
+				return_frame = true;
+		}
+		framesize = 0;
+#if SYNCLINK_GENERIC_HDLC
+		{
+			info->netdev->stats.rx_errors++;
+			info->netdev->stats.rx_frame_errors++;
+		}
+#endif
+	} else
+		return_frame = true;
+
+	if ( return_frame ) {
+		/* receive frame has no errors, get frame size.
+		 * The frame size is the starting value of the RCC (which was
+		 * set to 0xffff) minus the ending value of the RCC (decremented
+		 * once for each receive character) minus 2 for the 16-bit CRC.
+		 */
+
+		framesize = RCLRVALUE - info->rx_buffer_list[EndIndex].rcc;
+
+		/* adjust frame size for CRC if any */
+		if ( info->params.crc_type == HDLC_CRC_16_CCITT )
+			framesize -= 2;
+		else if ( info->params.crc_type == HDLC_CRC_32_CCITT )
+			framesize -= 4;		
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk("%s(%d):mgsl_get_rx_frame(%s) status=%04X size=%d\n",
+			__FILE__,__LINE__,info->device_name,status,framesize);
+			
+	if ( debug_level >= DEBUG_LEVEL_DATA )
+		mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
+			min_t(int, framesize, DMABUFFERSIZE),0);
+		
+	if (framesize) {
+		if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
+				((framesize+1) > info->max_frame_size) ) ||
+			(framesize > info->max_frame_size) )
+			info->icount.rxlong++;
+		else {
+			/* copy dma buffer(s) to contiguous intermediate buffer */
+			int copy_count = framesize;
+			int index = StartIndex;
+			unsigned char *ptmp = info->intermediate_rxbuffer;
+
+			if ( !(status & RXSTATUS_CRC_ERROR))
+			info->icount.rxok++;
+			
+			while(copy_count) {
+				int partial_count;
+				if ( copy_count > DMABUFFERSIZE )
+					partial_count = DMABUFFERSIZE;
+				else
+					partial_count = copy_count;
+			
+				pBufEntry = &(info->rx_buffer_list[index]);
+				memcpy( ptmp, pBufEntry->virt_addr, partial_count );
+				ptmp += partial_count;
+				copy_count -= partial_count;
+				
+				if ( ++index == info->rx_buffer_count )
+					index = 0;
+			}
+
+			if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) {
+				++framesize;
+				*ptmp = (status & RXSTATUS_CRC_ERROR ?
+						RX_CRC_ERROR :
+						RX_OK);
+
+				if ( debug_level >= DEBUG_LEVEL_DATA )
+					printk("%s(%d):mgsl_get_rx_frame(%s) rx frame status=%d\n",
+						__FILE__,__LINE__,info->device_name,
+						*ptmp);
+			}
+
+#if SYNCLINK_GENERIC_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
+			else
+#endif
+				ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+		}
+	}
+	/* Free the buffers used by this frame. */
+	mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex );
+
+	ReturnCode = true;
+
+Cleanup:
+
+	if ( info->rx_enabled && info->rx_overflow ) {
+		/* The receiver needs to restarted because of 
+		 * a receive overflow (buffer or FIFO). If the 
+		 * receive buffers are now empty, then restart receiver.
+		 */
+
+		if ( !info->rx_buffer_list[EndIndex].status &&
+			info->rx_buffer_list[EndIndex].count ) {
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			usc_start_receiver(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		}
+	}
+
+	return ReturnCode;
+
+}	/* end of mgsl_get_rx_frame() */
+
+/* mgsl_get_raw_rx_frame()
+ *
+ *     	This function attempts to return a received frame from the
+ *	receive DMA buffers when running in external loop mode. In this mode,
+ *	we will return at most one DMABUFFERSIZE frame to the application.
+ *	The USC receiver is triggering off of DCD going active to start a new
+ *	frame, and DCD going inactive to terminate the frame (similar to
+ *	processing a closing flag character).
+ *
+ *	In this routine, we will return DMABUFFERSIZE "chunks" at a time.
+ *	If DCD goes inactive, the last Rx DMA Buffer will have a non-zero
+ * 	status field and the RCC field will indicate the length of the
+ *	entire received frame. We take this RCC field and get the modulus
+ *	of RCC and DMABUFFERSIZE to determine if number of bytes in the
+ *	last Rx DMA buffer and return that last portion of the frame.
+ *
+ * Arguments:	 	info	pointer to device extension
+ * Return Value:	true if frame returned, otherwise false
+ */
+static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+{
+	unsigned int CurrentIndex, NextIndex;
+	unsigned short status;
+	DMABUFFERENTRY *pBufEntry;
+	unsigned int framesize = 0;
+	bool ReturnCode = false;
+	unsigned long flags;
+	struct tty_struct *tty = info->port.tty;
+
+	/*
+ 	 * current_rx_buffer points to the 1st buffer of the next available
+	 * receive frame. The status field is set by the 16C32 after
+	 * completing a receive frame. If the status field of this buffer
+	 * is zero, either the USC is still filling this buffer or this
+	 * is one of a series of buffers making up a received frame.
+	 *
+	 * If the count field of this buffer is zero, the USC is either
+	 * using this buffer or has used this buffer. Look at the count
+	 * field of the next buffer. If that next buffer's count is
+	 * non-zero, the USC is still actively using the current buffer.
+	 * Otherwise, if the next buffer's count field is zero, the
+	 * current buffer is complete and the USC is using the next
+	 * buffer.
+	 */
+	CurrentIndex = NextIndex = info->current_rx_buffer;
+	++NextIndex;
+	if ( NextIndex == info->rx_buffer_count )
+		NextIndex = 0;
+
+	if ( info->rx_buffer_list[CurrentIndex].status != 0 ||
+		(info->rx_buffer_list[CurrentIndex].count == 0 &&
+			info->rx_buffer_list[NextIndex].count == 0)) {
+		/*
+	 	 * Either the status field of this dma buffer is non-zero
+		 * (indicating the last buffer of a receive frame) or the next
+	 	 * buffer is marked as in use -- implying this buffer is complete
+		 * and an intermediate buffer for this received frame.
+	 	 */
+
+		status = info->rx_buffer_list[CurrentIndex].status;
+
+		if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
+				RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
+			if ( status & RXSTATUS_SHORT_FRAME )
+				info->icount.rxshort++;
+			else if ( status & RXSTATUS_ABORT )
+				info->icount.rxabort++;
+			else if ( status & RXSTATUS_OVERRUN )
+				info->icount.rxover++;
+			else
+				info->icount.rxcrc++;
+			framesize = 0;
+		} else {
+			/*
+			 * A receive frame is available, get frame size and status.
+			 *
+			 * The frame size is the starting value of the RCC (which was
+			 * set to 0xffff) minus the ending value of the RCC (decremented
+			 * once for each receive character) minus 2 or 4 for the 16-bit
+			 * or 32-bit CRC.
+			 *
+			 * If the status field is zero, this is an intermediate buffer.
+			 * It's size is 4K.
+			 *
+			 * If the DMA Buffer Entry's Status field is non-zero, the
+			 * receive operation completed normally (ie: DCD dropped). The
+			 * RCC field is valid and holds the received frame size.
+			 * It is possible that the RCC field will be zero on a DMA buffer
+			 * entry with a non-zero status. This can occur if the total
+			 * frame size (number of bytes between the time DCD goes active
+			 * to the time DCD goes inactive) exceeds 65535 bytes. In this
+			 * case the 16C32 has underrun on the RCC count and appears to
+			 * stop updating this counter to let us know the actual received
+			 * frame size. If this happens (non-zero status and zero RCC),
+			 * simply return the entire RxDMA Buffer
+			 */
+			if ( status ) {
+				/*
+				 * In the event that the final RxDMA Buffer is
+				 * terminated with a non-zero status and the RCC
+				 * field is zero, we interpret this as the RCC
+				 * having underflowed (received frame > 65535 bytes).
+				 *
+				 * Signal the event to the user by passing back
+				 * a status of RxStatus_CrcError returning the full
+				 * buffer and let the app figure out what data is
+				 * actually valid
+				 */
+				if ( info->rx_buffer_list[CurrentIndex].rcc )
+					framesize = RCLRVALUE - info->rx_buffer_list[CurrentIndex].rcc;
+				else
+					framesize = DMABUFFERSIZE;
+			}
+			else
+				framesize = DMABUFFERSIZE;
+		}
+
+		if ( framesize > DMABUFFERSIZE ) {
+			/*
+			 * if running in raw sync mode, ISR handler for
+			 * End Of Buffer events terminates all buffers at 4K.
+			 * If this frame size is said to be >4K, get the
+			 * actual number of bytes of the frame in this buffer.
+			 */
+			framesize = framesize % DMABUFFERSIZE;
+		}
+
+
+		if ( debug_level >= DEBUG_LEVEL_BH )
+			printk("%s(%d):mgsl_get_raw_rx_frame(%s) status=%04X size=%d\n",
+				__FILE__,__LINE__,info->device_name,status,framesize);
+
+		if ( debug_level >= DEBUG_LEVEL_DATA )
+			mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
+				min_t(int, framesize, DMABUFFERSIZE),0);
+
+		if (framesize) {
+			/* copy dma buffer(s) to contiguous intermediate buffer */
+			/* NOTE: we never copy more than DMABUFFERSIZE bytes	*/
+
+			pBufEntry = &(info->rx_buffer_list[CurrentIndex]);
+			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
+			info->icount.rxok++;
+
+			ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+		}
+
+		/* Free the buffers used by this frame. */
+		mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex );
+
+		ReturnCode = true;
+	}
+
+
+	if ( info->rx_enabled && info->rx_overflow ) {
+		/* The receiver needs to restarted because of
+		 * a receive overflow (buffer or FIFO). If the
+		 * receive buffers are now empty, then restart receiver.
+		 */
+
+		if ( !info->rx_buffer_list[CurrentIndex].status &&
+			info->rx_buffer_list[CurrentIndex].count ) {
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			usc_start_receiver(info);
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		}
+	}
+
+	return ReturnCode;
+
+}	/* end of mgsl_get_raw_rx_frame() */
+
+/* mgsl_load_tx_dma_buffer()
+ * 
+ * 	Load the transmit DMA buffer with the specified data.
+ * 
+ * Arguments:
+ * 
+ * 	info		pointer to device extension
+ * 	Buffer		pointer to buffer containing frame to load
+ * 	BufferSize	size in bytes of frame in Buffer
+ * 
+ * Return Value: 	None
+ */
+static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
+		const char *Buffer, unsigned int BufferSize)
+{
+	unsigned short Copycount;
+	unsigned int i = 0;
+	DMABUFFERENTRY *pBufEntry;
+	
+	if ( debug_level >= DEBUG_LEVEL_DATA )
+		mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
+
+	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
+		/* set CMR:13 to start transmit when
+		 * next GoAhead (abort) is received
+		 */
+	 	info->cmr_value |= BIT13;			  
+	}
+		
+	/* begin loading the frame in the next available tx dma
+	 * buffer, remember it's starting location for setting
+	 * up tx dma operation
+	 */
+	i = info->current_tx_buffer;
+	info->start_tx_dma_buffer = i;
+
+	/* Setup the status and RCC (Frame Size) fields of the 1st */
+	/* buffer entry in the transmit DMA buffer list. */
+
+	info->tx_buffer_list[i].status = info->cmr_value & 0xf000;
+	info->tx_buffer_list[i].rcc    = BufferSize;
+	info->tx_buffer_list[i].count  = BufferSize;
+
+	/* Copy frame data from 1st source buffer to the DMA buffers. */
+	/* The frame data may span multiple DMA buffers. */
+
+	while( BufferSize ){
+		/* Get a pointer to next DMA buffer entry. */
+		pBufEntry = &info->tx_buffer_list[i++];
+			
+		if ( i == info->tx_buffer_count )
+			i=0;
+
+		/* Calculate the number of bytes that can be copied from */
+		/* the source buffer to this DMA buffer. */
+		if ( BufferSize > DMABUFFERSIZE )
+			Copycount = DMABUFFERSIZE;
+		else
+			Copycount = BufferSize;
+
+		/* Actually copy data from source buffer to DMA buffer. */
+		/* Also set the data count for this individual DMA buffer. */
+		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
+			mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
+		else
+			memcpy(pBufEntry->virt_addr, Buffer, Copycount);
+
+		pBufEntry->count = Copycount;
+
+		/* Advance source pointer and reduce remaining data count. */
+		Buffer += Copycount;
+		BufferSize -= Copycount;
+
+		++info->tx_dma_buffers_used;
+	}
+
+	/* remember next available tx dma buffer */
+	info->current_tx_buffer = i;
+
+}	/* end of mgsl_load_tx_dma_buffer() */
+
+/*
+ * mgsl_register_test()
+ * 
+ * 	Performs a register test of the 16C32.
+ * 	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:		true if test passed, otherwise false
+ */
+static bool mgsl_register_test( struct mgsl_struct *info )
+{
+	static unsigned short BitPatterns[] =
+		{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
+	static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
+	unsigned int i;
+	bool rc = true;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_reset(info);
+
+	/* Verify the reset state of some registers. */
+
+	if ( (usc_InReg( info, SICR ) != 0) ||
+		  (usc_InReg( info, IVR  ) != 0) ||
+		  (usc_InDmaReg( info, DIVR ) != 0) ){
+		rc = false;
+	}
+
+	if ( rc ){
+		/* Write bit patterns to various registers but do it out of */
+		/* sync, then read back and verify values. */
+
+		for ( i = 0 ; i < Patterncount ; i++ ) {
+			usc_OutReg( info, TC0R, BitPatterns[i] );
+			usc_OutReg( info, TC1R, BitPatterns[(i+1)%Patterncount] );
+			usc_OutReg( info, TCLR, BitPatterns[(i+2)%Patterncount] );
+			usc_OutReg( info, RCLR, BitPatterns[(i+3)%Patterncount] );
+			usc_OutReg( info, RSR,  BitPatterns[(i+4)%Patterncount] );
+			usc_OutDmaReg( info, TBCR, BitPatterns[(i+5)%Patterncount] );
+
+			if ( (usc_InReg( info, TC0R ) != BitPatterns[i]) ||
+				  (usc_InReg( info, TC1R ) != BitPatterns[(i+1)%Patterncount]) ||
+				  (usc_InReg( info, TCLR ) != BitPatterns[(i+2)%Patterncount]) ||
+				  (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) ||
+				  (usc_InReg( info, RSR )  != BitPatterns[(i+4)%Patterncount]) ||
+				  (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){
+				rc = false;
+				break;
+			}
+		}
+	}
+
+	usc_reset(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return rc;
+
+}	/* end of mgsl_register_test() */
+
+/* mgsl_irq_test() 	Perform interrupt test of the 16C32.
+ * 
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	true if test passed, otherwise false
+ */
+static bool mgsl_irq_test( struct mgsl_struct *info )
+{
+	unsigned long EndTime;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_reset(info);
+
+	/*
+	 * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition. 
+	 * The ISR sets irq_occurred to true.
+	 */
+
+	info->irq_occurred = false;
+
+	/* Enable INTEN gate for ISA adapter (Port 6, Bit12) */
+	/* Enable INTEN (Port 6, Bit12) */
+	/* This connects the IRQ request signal to the ISA bus */
+	/* on the ISA adapter. This has no effect for the PCI adapter */
+	usc_OutReg( info, PCR, (unsigned short)((usc_InReg(info, PCR) | BIT13) & ~BIT12) );
+
+	usc_EnableMasterIrqBit(info);
+	usc_EnableInterrupts(info, IO_PIN);
+	usc_ClearIrqPendingBits(info, IO_PIN);
+	
+	usc_UnlatchIostatusBits(info, MISCSTATUS_TXC_LATCHED);
+	usc_EnableStatusIrqs(info, SICR_TXC_ACTIVE + SICR_TXC_INACTIVE);
+
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	EndTime=100;
+	while( EndTime-- && !info->irq_occurred ) {
+		msleep_interruptible(10);
+	}
+	
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_reset(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+	return info->irq_occurred;
+
+}	/* end of mgsl_irq_test() */
+
+/* mgsl_dma_test()
+ * 
+ * 	Perform a DMA test of the 16C32. A small frame is
+ * 	transmitted via DMA from a transmit buffer to a receive buffer
+ * 	using single buffer DMA mode.
+ * 	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	true if test passed, otherwise false
+ */
+static bool mgsl_dma_test( struct mgsl_struct *info )
+{
+	unsigned short FifoLevel;
+	unsigned long phys_addr;
+	unsigned int FrameSize;
+	unsigned int i;
+	char *TmpPtr;
+	bool rc = true;
+	unsigned short status=0;
+	unsigned long EndTime;
+	unsigned long flags;
+	MGSL_PARAMS tmp_params;
+
+	/* save current port options */
+	memcpy(&tmp_params,&info->params,sizeof(MGSL_PARAMS));
+	/* load default port options */
+	memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+	
+#define TESTFRAMESIZE 40
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	
+	/* setup 16C32 for SDLC DMA transfer mode */
+
+	usc_reset(info);
+	usc_set_sdlc_mode(info);
+	usc_enable_loopback(info,1);
+	
+	/* Reprogram the RDMR so that the 16C32 does NOT clear the count
+	 * field of the buffer entry after fetching buffer address. This
+	 * way we can detect a DMA failure for a DMA read (which should be
+	 * non-destructive to system memory) before we try and write to
+	 * memory (where a failure could corrupt system memory).
+	 */
+
+	/* Receive DMA mode Register (RDMR)
+	 * 
+	 * <15..14>	11	DMA mode = Linked List Buffer mode
+	 * <13>		1	RSBinA/L = store Rx status Block in List entry
+	 * <12>		0	1 = Clear count of List Entry after fetching
+	 * <11..10>	00	Address mode = Increment
+	 * <9>		1	Terminate Buffer on RxBound
+	 * <8>		0	Bus Width = 16bits
+	 * <7..0>		?	status Bits (write as 0s)
+	 * 
+	 * 1110 0010 0000 0000 = 0xe200
+	 */
+
+	usc_OutDmaReg( info, RDMR, 0xe200 );
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+
+	/* SETUP TRANSMIT AND RECEIVE DMA BUFFERS */
+
+	FrameSize = TESTFRAMESIZE;
+
+	/* setup 1st transmit buffer entry: */
+	/* with frame size and transmit control word */
+
+	info->tx_buffer_list[0].count  = FrameSize;
+	info->tx_buffer_list[0].rcc    = FrameSize;
+	info->tx_buffer_list[0].status = 0x4000;
+
+	/* build a transmit frame in 1st transmit DMA buffer */
+
+	TmpPtr = info->tx_buffer_list[0].virt_addr;
+	for (i = 0; i < FrameSize; i++ )
+		*TmpPtr++ = i;
+
+	/* setup 1st receive buffer entry: */
+	/* clear status, set max receive buffer size */
+
+	info->rx_buffer_list[0].status = 0;
+	info->rx_buffer_list[0].count = FrameSize + 4;
+
+	/* zero out the 1st receive buffer */
+
+	memset( info->rx_buffer_list[0].virt_addr, 0, FrameSize + 4 );
+
+	/* Set count field of next buffer entries to prevent */
+	/* 16C32 from using buffers after the 1st one. */
+
+	info->tx_buffer_list[1].count = 0;
+	info->rx_buffer_list[1].count = 0;
+	
+
+	/***************************/
+	/* Program 16C32 receiver. */
+	/***************************/
+	
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+
+	/* setup DMA transfers */
+	usc_RTCmd( info, RTCmd_PurgeRxFifo );
+
+	/* program 16C32 receiver with physical address of 1st DMA buffer entry */
+	phys_addr = info->rx_buffer_list[0].phys_entry;
+	usc_OutDmaReg( info, NRARL, (unsigned short)phys_addr );
+	usc_OutDmaReg( info, NRARU, (unsigned short)(phys_addr >> 16) );
+
+	/* Clear the Rx DMA status bits (read RDMR) and start channel */
+	usc_InDmaReg( info, RDMR );
+	usc_DmaCmd( info, DmaCmd_InitRxChannel );
+
+	/* Enable Receiver (RMR <1..0> = 10) */
+	usc_OutReg( info, RMR, (unsigned short)((usc_InReg(info, RMR) & 0xfffc) | 0x0002) );
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+
+	/*************************************************************/
+	/* WAIT FOR RECEIVER TO DMA ALL PARAMETERS FROM BUFFER ENTRY */
+	/*************************************************************/
+
+	/* Wait 100ms for interrupt. */
+	EndTime = jiffies + msecs_to_jiffies(100);
+
+	for(;;) {
+		if (time_after(jiffies, EndTime)) {
+			rc = false;
+			break;
+		}
+
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		status = usc_InDmaReg( info, RDMR );
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+		if ( !(status & BIT4) && (status & BIT5) ) {
+			/* INITG (BIT 4) is inactive (no entry read in progress) AND */
+			/* BUSY  (BIT 5) is active (channel still active). */
+			/* This means the buffer entry read has completed. */
+			break;
+		}
+	}
+
+
+	/******************************/
+	/* Program 16C32 transmitter. */
+	/******************************/
+	
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+
+	/* Program the Transmit Character Length Register (TCLR) */
+	/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
+
+	usc_OutReg( info, TCLR, (unsigned short)info->tx_buffer_list[0].count );
+	usc_RTCmd( info, RTCmd_PurgeTxFifo );
+
+	/* Program the address of the 1st DMA Buffer Entry in linked list */
+
+	phys_addr = info->tx_buffer_list[0].phys_entry;
+	usc_OutDmaReg( info, NTARL, (unsigned short)phys_addr );
+	usc_OutDmaReg( info, NTARU, (unsigned short)(phys_addr >> 16) );
+
+	/* unlatch Tx status bits, and start transmit channel. */
+
+	usc_OutReg( info, TCSR, (unsigned short)(( usc_InReg(info, TCSR) & 0x0f00) | 0xfa) );
+	usc_DmaCmd( info, DmaCmd_InitTxChannel );
+
+	/* wait for DMA controller to fill transmit FIFO */
+
+	usc_TCmd( info, TCmd_SelectTicrTxFifostatus );
+	
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+
+	/**********************************/
+	/* WAIT FOR TRANSMIT FIFO TO FILL */
+	/**********************************/
+	
+	/* Wait 100ms */
+	EndTime = jiffies + msecs_to_jiffies(100);
+
+	for(;;) {
+		if (time_after(jiffies, EndTime)) {
+			rc = false;
+			break;
+		}
+
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		FifoLevel = usc_InReg(info, TICR) >> 8;
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+			
+		if ( FifoLevel < 16 )
+			break;
+		else
+			if ( FrameSize < 32 ) {
+				/* This frame is smaller than the entire transmit FIFO */
+				/* so wait for the entire frame to be loaded. */
+				if ( FifoLevel <= (32 - FrameSize) )
+					break;
+			}
+	}
+
+
+	if ( rc )
+	{
+		/* Enable 16C32 transmitter. */
+
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		
+		/* Transmit mode Register (TMR), <1..0> = 10, Enable Transmitter */
+		usc_TCmd( info, TCmd_SendFrame );
+		usc_OutReg( info, TMR, (unsigned short)((usc_InReg(info, TMR) & 0xfffc) | 0x0002) );
+		
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+						
+		/******************************/
+		/* WAIT FOR TRANSMIT COMPLETE */
+		/******************************/
+
+		/* Wait 100ms */
+		EndTime = jiffies + msecs_to_jiffies(100);
+
+		/* While timer not expired wait for transmit complete */
+
+		spin_lock_irqsave(&info->irq_spinlock,flags);
+		status = usc_InReg( info, TCSR );
+		spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
+			if (time_after(jiffies, EndTime)) {
+				rc = false;
+				break;
+			}
+
+			spin_lock_irqsave(&info->irq_spinlock,flags);
+			status = usc_InReg( info, TCSR );
+			spin_unlock_irqrestore(&info->irq_spinlock,flags);
+		}
+	}
+
+
+	if ( rc ){
+		/* CHECK FOR TRANSMIT ERRORS */
+		if ( status & (BIT5 + BIT1) ) 
+			rc = false;
+	}
+
+	if ( rc ) {
+		/* WAIT FOR RECEIVE COMPLETE */
+
+		/* Wait 100ms */
+		EndTime = jiffies + msecs_to_jiffies(100);
+
+		/* Wait for 16C32 to write receive status to buffer entry. */
+		status=info->rx_buffer_list[0].status;
+		while ( status == 0 ) {
+			if (time_after(jiffies, EndTime)) {
+				rc = false;
+				break;
+			}
+			status=info->rx_buffer_list[0].status;
+		}
+	}
+
+
+	if ( rc ) {
+		/* CHECK FOR RECEIVE ERRORS */
+		status = info->rx_buffer_list[0].status;
+
+		if ( status & (BIT8 + BIT3 + BIT1) ) {
+			/* receive error has occurred */
+			rc = false;
+		} else {
+			if ( memcmp( info->tx_buffer_list[0].virt_addr ,
+				info->rx_buffer_list[0].virt_addr, FrameSize ) ){
+				rc = false;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_reset( info );
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	/* restore current port options */
+	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
+	
+	return rc;
+
+}	/* end of mgsl_dma_test() */
+
+/* mgsl_adapter_test()
+ * 
+ * 	Perform the register, IRQ, and DMA tests for the 16C32.
+ * 	
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	0 if success, otherwise -ENODEV
+ */
+static int mgsl_adapter_test( struct mgsl_struct *info )
+{
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):Testing device %s\n",
+			__FILE__,__LINE__,info->device_name );
+			
+	if ( !mgsl_register_test( info ) ) {
+		info->init_error = DiagStatus_AddressFailure;
+		printk( "%s(%d):Register test failure for device %s Addr=%04X\n",
+			__FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) );
+		return -ENODEV;
+	}
+
+	if ( !mgsl_irq_test( info ) ) {
+		info->init_error = DiagStatus_IrqFailure;
+		printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",
+			__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );
+		return -ENODEV;
+	}
+
+	if ( !mgsl_dma_test( info ) ) {
+		info->init_error = DiagStatus_DmaFailure;
+		printk( "%s(%d):DMA test failure for device %s DMA=%d\n",
+			__FILE__,__LINE__,info->device_name, (unsigned short)(info->dma_level) );
+		return -ENODEV;
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):device %s passed diagnostics\n",
+			__FILE__,__LINE__,info->device_name );
+			
+	return 0;
+
+}	/* end of mgsl_adapter_test() */
+
+/* mgsl_memory_test()
+ * 
+ * 	Test the shared memory on a PCI adapter.
+ * 
+ * Arguments:		info	pointer to device instance data
+ * Return Value:	true if test passed, otherwise false
+ */
+static bool mgsl_memory_test( struct mgsl_struct *info )
+{
+	static unsigned long BitPatterns[] =
+		{ 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+	unsigned long Patterncount = ARRAY_SIZE(BitPatterns);
+	unsigned long i;
+	unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
+	unsigned long * TestAddr;
+
+	if ( info->bus_type != MGSL_BUS_TYPE_PCI )
+		return true;
+
+	TestAddr = (unsigned long *)info->memory_base;
+
+	/* Test data lines with test pattern at one location. */
+
+	for ( i = 0 ; i < Patterncount ; i++ ) {
+		*TestAddr = BitPatterns[i];
+		if ( *TestAddr != BitPatterns[i] )
+			return false;
+	}
+
+	/* Test address lines with incrementing pattern over */
+	/* entire address range. */
+
+	for ( i = 0 ; i < TestLimit ; i++ ) {
+		*TestAddr = i * 4;
+		TestAddr++;
+	}
+
+	TestAddr = (unsigned long *)info->memory_base;
+
+	for ( i = 0 ; i < TestLimit ; i++ ) {
+		if ( *TestAddr != i * 4 )
+			return false;
+		TestAddr++;
+	}
+
+	memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE );
+
+	return true;
+
+}	/* End Of mgsl_memory_test() */
+
+
+/* mgsl_load_pci_memory()
+ * 
+ * 	Load a large block of data into the PCI shared memory.
+ * 	Use this instead of memcpy() or memmove() to move data
+ * 	into the PCI shared memory.
+ * 
+ * Notes:
+ * 
+ * 	This function prevents the PCI9050 interface chip from hogging
+ * 	the adapter local bus, which can starve the 16C32 by preventing
+ * 	16C32 bus master cycles.
+ * 
+ * 	The PCI9050 documentation says that the 9050 will always release
+ * 	control of the local bus after completing the current read
+ * 	or write operation.
+ * 
+ * 	It appears that as long as the PCI9050 write FIFO is full, the
+ * 	PCI9050 treats all of the writes as a single burst transaction
+ * 	and will not release the bus. This causes DMA latency problems
+ * 	at high speeds when copying large data blocks to the shared
+ * 	memory.
+ * 
+ * 	This function in effect, breaks the a large shared memory write
+ * 	into multiple transations by interleaving a shared memory read
+ * 	which will flush the write FIFO and 'complete' the write
+ * 	transation. This allows any pending DMA request to gain control
+ * 	of the local bus in a timely fasion.
+ * 
+ * Arguments:
+ * 
+ * 	TargetPtr	pointer to target address in PCI shared memory
+ * 	SourcePtr	pointer to source buffer for data
+ * 	count		count in bytes of data to copy
+ *
+ * Return Value:	None
+ */
+static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
+	unsigned short count )
+{
+	/* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */
+#define PCI_LOAD_INTERVAL 64
+
+	unsigned short Intervalcount = count / PCI_LOAD_INTERVAL;
+	unsigned short Index;
+	unsigned long Dummy;
+
+	for ( Index = 0 ; Index < Intervalcount ; Index++ )
+	{
+		memcpy(TargetPtr, SourcePtr, PCI_LOAD_INTERVAL);
+		Dummy = *((volatile unsigned long *)TargetPtr);
+		TargetPtr += PCI_LOAD_INTERVAL;
+		SourcePtr += PCI_LOAD_INTERVAL;
+	}
+
+	memcpy( TargetPtr, SourcePtr, count % PCI_LOAD_INTERVAL );
+
+}	/* End Of mgsl_load_pci_memory() */
+
+static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
+{
+	int i;
+	int linecount;
+	if (xmit)
+		printk("%s tx data:\n",info->device_name);
+	else
+		printk("%s rx data:\n",info->device_name);
+		
+	while(count) {
+		if (count > 16)
+			linecount = 16;
+		else
+			linecount = count;
+			
+		for(i=0;i<linecount;i++)
+			printk("%02X ",(unsigned char)data[i]);
+		for(;i<17;i++)
+			printk("   ");
+		for(i=0;i<linecount;i++) {
+			if (data[i]>=040 && data[i]<=0176)
+				printk("%c",data[i]);
+			else
+				printk(".");
+		}
+		printk("\n");
+		
+		data  += linecount;
+		count -= linecount;
+	}
+}	/* end of mgsl_trace_block() */
+
+/* mgsl_tx_timeout()
+ * 
+ * 	called when HDLC frame times out
+ * 	update stats and do tx completion processing
+ * 	
+ * Arguments:	context		pointer to device instance data
+ * Return Value:	None
+ */
+static void mgsl_tx_timeout(unsigned long context)
+{
+	struct mgsl_struct *info = (struct mgsl_struct*)context;
+	unsigned long flags;
+	
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):mgsl_tx_timeout(%s)\n",
+			__FILE__,__LINE__,info->device_name);
+	if(info->tx_active &&
+	   (info->params.mode == MGSL_MODE_HDLC ||
+	    info->params.mode == MGSL_MODE_RAW) ) {
+		info->icount.txtimeout++;
+	}
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	info->tx_active = false;
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
+		usc_loopmode_cancel_transmit( info );
+
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+	
+#if SYNCLINK_GENERIC_HDLC
+	if (info->netcount)
+		hdlcdev_tx_done(info);
+	else
+#endif
+		mgsl_bh_transmit(info);
+	
+}	/* end of mgsl_tx_timeout() */
+
+/* signal that there are no more frames to send, so that
+ * line is 'released' by echoing RxD to TxD when current
+ * transmission is complete (or immediately if no tx in progress).
+ */
+static int mgsl_loopmode_send_done( struct mgsl_struct * info )
+{
+	unsigned long flags;
+	
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
+		if (info->tx_active)
+			info->loopmode_send_done_requested = true;
+		else
+			usc_loopmode_send_done(info);
+	}
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return 0;
+}
+
+/* release the line by echoing RxD to TxD
+ * upon completion of a transmit frame
+ */
+static void usc_loopmode_send_done( struct mgsl_struct * info )
+{
+ 	info->loopmode_send_done_requested = false;
+ 	/* clear CMR:13 to 0 to start echoing RxData to TxData */
+ 	info->cmr_value &= ~BIT13;			  
+ 	usc_OutReg(info, CMR, info->cmr_value);
+}
+
+/* abort a transmit in progress while in HDLC LoopMode
+ */
+static void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
+{
+ 	/* reset tx dma channel and purge TxFifo */
+ 	usc_RTCmd( info, RTCmd_PurgeTxFifo );
+ 	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
+  	usc_loopmode_send_done( info );
+}
+
+/* for HDLC/SDLC LoopMode, setting CMR:13 after the transmitter is enabled
+ * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort)
+ * we must clear CMR:13 to begin repeating TxData to RxData
+ */
+static void usc_loopmode_insert_request( struct mgsl_struct * info )
+{
+ 	info->loopmode_insert_requested = true;
+ 
+ 	/* enable RxAbort irq. On next RxAbort, clear CMR:13 to
+ 	 * begin repeating TxData on RxData (complete insertion)
+	 */
+ 	usc_OutReg( info, RICR, 
+		(usc_InReg( info, RICR ) | RXSTATUS_ABORT_RECEIVED ) );
+		
+	/* set CMR:13 to insert into loop on next GoAhead (RxAbort) */
+	info->cmr_value |= BIT13;
+ 	usc_OutReg(info, CMR, info->cmr_value);
+}
+
+/* return 1 if station is inserted into the loop, otherwise 0
+ */
+static int usc_loopmode_active( struct mgsl_struct * info)
+{
+ 	return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
+}
+
+#if SYNCLINK_GENERIC_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
+{
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
+
+	/* return error if TTY interface open */
+	if (info->port.count)
+		return -EBUSY;
+
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
+	}
+
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
+
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;
+
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		mgsl_program_hw(info);
+
+	return 0;
+}
+
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ */
+static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	info->xmit_cnt = skb->len;
+	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
+
+	/* update network statistics */
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	if (!info->tx_active)
+	 	usc_start_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
+{
+	struct mgsl_struct *info = dev_to_port(dev);
+	int rc;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
+
+	/* arbitrate between network and tty opens */
+	spin_lock_irqsave(&info->netlock, flags);
+	if (info->port.count != 0 || info->netcount != 0) {
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return -EBUSY;
+	}
+	info->netcount=1;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	/* claim resources and init adapter */
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
+	}
+
+	/* assert DTR and RTS, apply hardware settings */
+	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	mgsl_program_hw(info);
+
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
+
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->irq_spinlock, flags);
+	usc_get_serial_signals(info);
+	spin_unlock_irqrestore(&info->irq_spinlock, flags);
+	if (info->serial_signals & SerialSignal_DCD)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
+	return 0;
+}
+
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
+{
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
+
+	netif_stop_queue(dev);
+
+	/* shutdown adapter and release resources */
+	shutdown(info);
+
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
+}
+
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned int flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
+
+	/* return error if TTY interface open */
+	if (info->port.count)
+		return -EBUSY;
+
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
+
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
+
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
+
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			mgsl_program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
+}
+
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
+{
+	struct mgsl_struct *info = dev_to_port(dev);
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
+
+	dev->stats.tx_errors++;
+	dev->stats.tx_aborted_errors++;
+
+	spin_lock_irqsave(&info->irq_spinlock,flags);
+	usc_stop_transmitter(info);
+	spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+	netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct mgsl_struct *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
+{
+	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("hdlcdev_rx(%s)\n", dev->name);
+
+	if (skb == NULL) {
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
+		       dev->name);
+		dev->stats.rx_dropped++;
+		return;
+	}
+
+	memcpy(skb_put(skb, size), buf, size);
+
+	skb->protocol = hdlc_type_trans(skb, dev);
+
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += size;
+
+	netif_rx(skb);
+}
+
+static const struct net_device_ops hdlcdev_ops = {
+	.ndo_open       = hdlcdev_open,
+	.ndo_stop       = hdlcdev_close,
+	.ndo_change_mtu = hdlc_change_mtu,
+	.ndo_start_xmit = hdlc_start_xmit,
+	.ndo_do_ioctl   = hdlcdev_ioctl,
+	.ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct mgsl_struct *info)
+{
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->base_addr = info->io_base;
+	dev->irq       = info->irq_level;
+	dev->dma       = info->dma_level;
+
+	/* network layer callbacks and settings */
+	dev->netdev_ops     = &hdlcdev_ops;
+	dev->watchdog_timeo = 10 * HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
+}
+
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(struct mgsl_struct *info)
+{
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
+}
+
+#endif /* CONFIG_HDLC */
+
+
+static int __devinit synclink_init_one (struct pci_dev *dev,
+					const struct pci_device_id *ent)
+{
+	struct mgsl_struct *info;
+
+	if (pci_enable_device(dev)) {
+		printk("error enabling pci device %p\n", dev);
+		return -EIO;
+	}
+
+	if (!(info = mgsl_allocate_device())) {
+		printk("can't allocate device instance data.\n");
+		return -EIO;
+	}
+
+        /* Copy user configuration info to device instance data */
+		
+	info->io_base = pci_resource_start(dev, 2);
+	info->irq_level = dev->irq;
+	info->phys_memory_base = pci_resource_start(dev, 3);
+				
+        /* Because veremap only works on page boundaries we must map
+	 * a larger area than is actually implemented for the LCR
+	 * memory range. We map a full page starting at the page boundary.
+	 */
+	info->phys_lcr_base = pci_resource_start(dev, 0);
+	info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
+	info->phys_lcr_base &= ~(PAGE_SIZE-1);
+				
+	info->bus_type = MGSL_BUS_TYPE_PCI;
+	info->io_addr_size = 8;
+	info->irq_flags = IRQF_SHARED;
+
+	if (dev->device == 0x0210) {
+		/* Version 1 PCI9030 based universal PCI adapter */
+		info->misc_ctrl_value = 0x007c4080;
+		info->hw_version = 1;
+	} else {
+		/* Version 0 PCI9050 based 5V PCI adapter
+		 * A PCI9050 bug prevents reading LCR registers if 
+		 * LCR base address bit 7 is set. Maintain shadow
+		 * value so we can write to LCR misc control reg.
+		 */
+		info->misc_ctrl_value = 0x087e4546;
+		info->hw_version = 0;
+	}
+				
+	mgsl_add_device(info);
+
+	return 0;
+}
+
+static void __devexit synclink_remove_one (struct pci_dev *dev)
+{
+}
+
diff --git a/drivers/tty/synclink_gt.c b/drivers/tty/synclink_gt.c
new file mode 100644
index 0000000..a35dd54
--- /dev/null
+++ b/drivers/tty/synclink_gt.c
@@ -0,0 +1,5161 @@
+/*
+ * Device driver for Microgate SyncLink GT serial adapters.
+ *
+ * written by Paul Fulghum for Microgate Corporation
+ * paulkf@microgate.com
+ *
+ * Microgate and SyncLink are trademarks of Microgate Corporation
+ *
+ * This code is released under the GNU General Public License (GPL)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * DEBUG OUTPUT DEFINITIONS
+ *
+ * uncomment lines below to enable specific types of debug output
+ *
+ * DBGINFO   information - most verbose output
+ * DBGERR    serious errors
+ * DBGBH     bottom half service routine debugging
+ * DBGISR    interrupt service routine debugging
+ * DBGDATA   output receive and transmit data
+ * DBGTBUF   output transmit DMA buffers and registers
+ * DBGRBUF   output receive DMA buffers and registers
+ */
+
+#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt
+#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt
+#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
+#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
+#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
+/*#define DBGTBUF(info) dump_tbufs(info)*/
+/*#define DBGRBUF(info) dump_rbufs(info)*/
+
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+#include <linux/termios.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
+#include <linux/hdlc.h>
+#include <linux/synclink.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
+#endif
+
+/*
+ * module identification
+ */
+static char *driver_name     = "SyncLink GT";
+static char *tty_driver_name = "synclink_gt";
+static char *tty_dev_prefix  = "ttySLG";
+MODULE_LICENSE("GPL");
+#define MGSL_MAGIC 0x5401
+#define MAX_DEVICES 32
+
+static struct pci_device_id pci_table[] = {
+	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{0,}, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_table);
+
+static int  init_one(struct pci_dev *dev,const struct pci_device_id *ent);
+static void remove_one(struct pci_dev *dev);
+static struct pci_driver pci_driver = {
+	.name		= "synclink_gt",
+	.id_table	= pci_table,
+	.probe		= init_one,
+	.remove		= __devexit_p(remove_one),
+};
+
+static bool pci_registered;
+
+/*
+ * module configuration and status
+ */
+static struct slgt_info *slgt_device_list;
+static int slgt_device_count;
+
+static int ttymajor;
+static int debug_level;
+static int maxframe[MAX_DEVICES];
+
+module_param(ttymajor, int, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+
+MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned");
+MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail");
+MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
+
+/*
+ * tty support and callbacks
+ */
+static struct tty_driver *serial_driver;
+
+static int  open(struct tty_struct *tty, struct file * filp);
+static void close(struct tty_struct *tty, struct file * filp);
+static void hangup(struct tty_struct *tty);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+
+static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
+static int put_char(struct tty_struct *tty, unsigned char ch);
+static void send_xchar(struct tty_struct *tty, char ch);
+static void wait_until_sent(struct tty_struct *tty, int timeout);
+static int  write_room(struct tty_struct *tty);
+static void flush_chars(struct tty_struct *tty);
+static void flush_buffer(struct tty_struct *tty);
+static void tx_hold(struct tty_struct *tty);
+static void tx_release(struct tty_struct *tty);
+
+static int  ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static int  chars_in_buffer(struct tty_struct *tty);
+static void throttle(struct tty_struct * tty);
+static void unthrottle(struct tty_struct * tty);
+static int set_break(struct tty_struct *tty, int break_state);
+
+/*
+ * generic HDLC support and callbacks
+ */
+#if SYNCLINK_GENERIC_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct slgt_info *info);
+static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
+static int  hdlcdev_init(struct slgt_info *info);
+static void hdlcdev_exit(struct slgt_info *info);
+#endif
+
+
+/*
+ * device specific structures, macros and functions
+ */
+
+#define SLGT_MAX_PORTS 4
+#define SLGT_REG_SIZE  256
+
+/*
+ * conditional wait facility
+ */
+struct cond_wait {
+	struct cond_wait *next;
+	wait_queue_head_t q;
+	wait_queue_t wait;
+	unsigned int data;
+};
+static void init_cond_wait(struct cond_wait *w, unsigned int data);
+static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
+static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
+static void flush_cond_wait(struct cond_wait **head);
+
+/*
+ * DMA buffer descriptor and access macros
+ */
+struct slgt_desc
+{
+	__le16 count;
+	__le16 status;
+	__le32 pbuf;  /* physical address of data buffer */
+	__le32 next;  /* physical address of next descriptor */
+
+	/* driver book keeping */
+	char *buf;          /* virtual  address of data buffer */
+    	unsigned int pdesc; /* physical address of this descriptor */
+	dma_addr_t buf_dma_addr;
+	unsigned short buf_count;
+};
+
+#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
+#define set_desc_next(a,b) (a).next   = cpu_to_le32((unsigned int)(b))
+#define set_desc_count(a,b)(a).count  = cpu_to_le16((unsigned short)(b))
+#define set_desc_eof(a,b)  (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0))
+#define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b))
+#define desc_count(a)      (le16_to_cpu((a).count))
+#define desc_status(a)     (le16_to_cpu((a).status))
+#define desc_complete(a)   (le16_to_cpu((a).status) & BIT15)
+#define desc_eof(a)        (le16_to_cpu((a).status) & BIT2)
+#define desc_crc_error(a)  (le16_to_cpu((a).status) & BIT1)
+#define desc_abort(a)      (le16_to_cpu((a).status) & BIT0)
+#define desc_residue(a)    ((le16_to_cpu((a).status) & 0x38) >> 3)
+
+struct _input_signal_events {
+	int ri_up;
+	int ri_down;
+	int dsr_up;
+	int dsr_down;
+	int dcd_up;
+	int dcd_down;
+	int cts_up;
+	int cts_down;
+};
+
+/*
+ * device instance data structure
+ */
+struct slgt_info {
+	void *if_ptr;		/* General purpose pointer (used by SPPP) */
+	struct tty_port port;
+
+	struct slgt_info *next_device;	/* device list link */
+
+	int magic;
+
+	char device_name[25];
+	struct pci_dev *pdev;
+
+	int port_count;  /* count of ports on adapter */
+	int adapter_num; /* adapter instance number */
+	int port_num;    /* port instance number */
+
+	/* array of pointers to port contexts on this adapter */
+	struct slgt_info *port_array[SLGT_MAX_PORTS];
+
+	int			line;		/* tty line instance number */
+
+	struct mgsl_icount	icount;
+
+	int			timeout;
+	int			x_char;		/* xon/xoff character */
+	unsigned int		read_status_mask;
+	unsigned int 		ignore_status_mask;
+
+	wait_queue_head_t	status_event_wait_q;
+	wait_queue_head_t	event_wait_q;
+	struct timer_list	tx_timer;
+	struct timer_list	rx_timer;
+
+	unsigned int            gpio_present;
+	struct cond_wait        *gpio_wait_q;
+
+	spinlock_t lock;	/* spinlock for synchronizing with ISR */
+
+	struct work_struct task;
+	u32 pending_bh;
+	bool bh_requested;
+	bool bh_running;
+
+	int isr_overflow;
+	bool irq_requested;	/* true if IRQ requested */
+	bool irq_occurred;	/* for diagnostics use */
+
+	/* device configuration */
+
+	unsigned int bus_type;
+	unsigned int irq_level;
+	unsigned long irq_flags;
+
+	unsigned char __iomem * reg_addr;  /* memory mapped registers address */
+	u32 phys_reg_addr;
+	bool reg_addr_requested;
+
+	MGSL_PARAMS params;       /* communications parameters */
+	u32 idle_mode;
+	u32 max_frame_size;       /* as set by device config */
+
+	unsigned int rbuf_fill_level;
+	unsigned int rx_pio;
+	unsigned int if_mode;
+	unsigned int base_clock;
+	unsigned int xsync;
+	unsigned int xctrl;
+
+	/* device status */
+
+	bool rx_enabled;
+	bool rx_restart;
+
+	bool tx_enabled;
+	bool tx_active;
+
+	unsigned char signals;    /* serial signal states */
+	int init_error;  /* initialization error */
+
+	unsigned char *tx_buf;
+	int tx_count;
+
+	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+	char char_buf[MAX_ASYNC_BUFFER_SIZE];
+	bool drop_rts_on_tx_done;
+	struct	_input_signal_events	input_signal_events;
+
+	int dcd_chkcount;	/* check counts to prevent */
+	int cts_chkcount;	/* too many IRQs if a signal */
+	int dsr_chkcount;	/* is floating */
+	int ri_chkcount;
+
+	char *bufs;		/* virtual address of DMA buffer lists */
+	dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */
+
+	unsigned int rbuf_count;
+	struct slgt_desc *rbufs;
+	unsigned int rbuf_current;
+	unsigned int rbuf_index;
+	unsigned int rbuf_fill_index;
+	unsigned short rbuf_fill_count;
+
+	unsigned int tbuf_count;
+	struct slgt_desc *tbufs;
+	unsigned int tbuf_current;
+	unsigned int tbuf_start;
+
+	unsigned char *tmp_rbuf;
+	unsigned int tmp_rbuf_count;
+
+	/* SPPP/Cisco HDLC device parts */
+
+	int netcount;
+	spinlock_t netlock;
+#if SYNCLINK_GENERIC_HDLC
+	struct net_device *netdev;
+#endif
+
+};
+
+static MGSL_PARAMS default_params = {
+	.mode            = MGSL_MODE_HDLC,
+	.loopback        = 0,
+	.flags           = HDLC_FLAG_UNDERRUN_ABORT15,
+	.encoding        = HDLC_ENCODING_NRZI_SPACE,
+	.clock_speed     = 0,
+	.addr_filter     = 0xff,
+	.crc_type        = HDLC_CRC_16_CCITT,
+	.preamble_length = HDLC_PREAMBLE_LENGTH_8BITS,
+	.preamble        = HDLC_PREAMBLE_PATTERN_NONE,
+	.data_rate       = 9600,
+	.data_bits       = 8,
+	.stop_bits       = 1,
+	.parity          = ASYNC_PARITY_NONE
+};
+
+
+#define BH_RECEIVE  1
+#define BH_TRANSMIT 2
+#define BH_STATUS   4
+#define IO_PIN_SHUTDOWN_LIMIT 100
+
+#define DMABUFSIZE 256
+#define DESC_LIST_SIZE 4096
+
+#define MASK_PARITY  BIT1
+#define MASK_FRAMING BIT0
+#define MASK_BREAK   BIT14
+#define MASK_OVERRUN BIT4
+
+#define GSR   0x00 /* global status */
+#define JCR   0x04 /* JTAG control */
+#define IODR  0x08 /* GPIO direction */
+#define IOER  0x0c /* GPIO interrupt enable */
+#define IOVR  0x10 /* GPIO value */
+#define IOSR  0x14 /* GPIO interrupt status */
+#define TDR   0x80 /* tx data */
+#define RDR   0x80 /* rx data */
+#define TCR   0x82 /* tx control */
+#define TIR   0x84 /* tx idle */
+#define TPR   0x85 /* tx preamble */
+#define RCR   0x86 /* rx control */
+#define VCR   0x88 /* V.24 control */
+#define CCR   0x89 /* clock control */
+#define BDR   0x8a /* baud divisor */
+#define SCR   0x8c /* serial control */
+#define SSR   0x8e /* serial status */
+#define RDCSR 0x90 /* rx DMA control/status */
+#define TDCSR 0x94 /* tx DMA control/status */
+#define RDDAR 0x98 /* rx DMA descriptor address */
+#define TDDAR 0x9c /* tx DMA descriptor address */
+#define XSR   0x40 /* extended sync pattern */
+#define XCR   0x44 /* extended control */
+
+#define RXIDLE      BIT14
+#define RXBREAK     BIT14
+#define IRQ_TXDATA  BIT13
+#define IRQ_TXIDLE  BIT12
+#define IRQ_TXUNDER BIT11 /* HDLC */
+#define IRQ_RXDATA  BIT10
+#define IRQ_RXIDLE  BIT9  /* HDLC */
+#define IRQ_RXBREAK BIT9  /* async */
+#define IRQ_RXOVER  BIT8
+#define IRQ_DSR     BIT7
+#define IRQ_CTS     BIT6
+#define IRQ_DCD     BIT5
+#define IRQ_RI      BIT4
+#define IRQ_ALL     0x3ff0
+#define IRQ_MASTER  BIT0
+
+#define slgt_irq_on(info, mask) \
+	wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask)))
+#define slgt_irq_off(info, mask) \
+	wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask)))
+
+static __u8  rd_reg8(struct slgt_info *info, unsigned int addr);
+static void  wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value);
+static __u16 rd_reg16(struct slgt_info *info, unsigned int addr);
+static void  wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value);
+static __u32 rd_reg32(struct slgt_info *info, unsigned int addr);
+static void  wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
+
+static void  msc_set_vcr(struct slgt_info *info);
+
+static int  startup(struct slgt_info *info);
+static int  block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
+static void shutdown(struct slgt_info *info);
+static void program_hw(struct slgt_info *info);
+static void change_params(struct slgt_info *info);
+
+static int  register_test(struct slgt_info *info);
+static int  irq_test(struct slgt_info *info);
+static int  loopback_test(struct slgt_info *info);
+static int  adapter_test(struct slgt_info *info);
+
+static void reset_adapter(struct slgt_info *info);
+static void reset_port(struct slgt_info *info);
+static void async_mode(struct slgt_info *info);
+static void sync_mode(struct slgt_info *info);
+
+static void rx_stop(struct slgt_info *info);
+static void rx_start(struct slgt_info *info);
+static void reset_rbufs(struct slgt_info *info);
+static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
+static void rdma_reset(struct slgt_info *info);
+static bool rx_get_frame(struct slgt_info *info);
+static bool rx_get_buf(struct slgt_info *info);
+
+static void tx_start(struct slgt_info *info);
+static void tx_stop(struct slgt_info *info);
+static void tx_set_idle(struct slgt_info *info);
+static unsigned int free_tbuf_count(struct slgt_info *info);
+static unsigned int tbuf_bytes(struct slgt_info *info);
+static void reset_tbufs(struct slgt_info *info);
+static void tdma_reset(struct slgt_info *info);
+static bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
+
+static void get_signals(struct slgt_info *info);
+static void set_signals(struct slgt_info *info);
+static void enable_loopback(struct slgt_info *info);
+static void set_rate(struct slgt_info *info, u32 data_rate);
+
+static int  bh_action(struct slgt_info *info);
+static void bh_handler(struct work_struct *work);
+static void bh_transmit(struct slgt_info *info);
+static void isr_serial(struct slgt_info *info);
+static void isr_rdma(struct slgt_info *info);
+static void isr_txeom(struct slgt_info *info, unsigned short status);
+static void isr_tdma(struct slgt_info *info);
+
+static int  alloc_dma_bufs(struct slgt_info *info);
+static void free_dma_bufs(struct slgt_info *info);
+static int  alloc_desc(struct slgt_info *info);
+static void free_desc(struct slgt_info *info);
+static int  alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
+static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
+
+static int  alloc_tmp_rbuf(struct slgt_info *info);
+static void free_tmp_rbuf(struct slgt_info *info);
+
+static void tx_timeout(unsigned long context);
+static void rx_timeout(unsigned long context);
+
+/*
+ * ioctl handlers
+ */
+static int  get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount);
+static int  get_params(struct slgt_info *info, MGSL_PARAMS __user *params);
+static int  set_params(struct slgt_info *info, MGSL_PARAMS __user *params);
+static int  get_txidle(struct slgt_info *info, int __user *idle_mode);
+static int  set_txidle(struct slgt_info *info, int idle_mode);
+static int  tx_enable(struct slgt_info *info, int enable);
+static int  tx_abort(struct slgt_info *info);
+static int  rx_enable(struct slgt_info *info, int enable);
+static int  modem_input_wait(struct slgt_info *info,int arg);
+static int  wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
+static int  tiocmget(struct tty_struct *tty);
+static int  tiocmset(struct tty_struct *tty,
+				unsigned int set, unsigned int clear);
+static int set_break(struct tty_struct *tty, int break_state);
+static int  get_interface(struct slgt_info *info, int __user *if_mode);
+static int  set_interface(struct slgt_info *info, int if_mode);
+static int  set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int  get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int  wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
+static int  get_xsync(struct slgt_info *info, int __user *if_mode);
+static int  set_xsync(struct slgt_info *info, int if_mode);
+static int  get_xctrl(struct slgt_info *info, int __user *if_mode);
+static int  set_xctrl(struct slgt_info *info, int if_mode);
+
+/*
+ * driver functions
+ */
+static void add_device(struct slgt_info *info);
+static void device_init(int adapter_num, struct pci_dev *pdev);
+static int  claim_resources(struct slgt_info *info);
+static void release_resources(struct slgt_info *info);
+
+/*
+ * DEBUG OUTPUT CODE
+ */
+#ifndef DBGINFO
+#define DBGINFO(fmt)
+#endif
+#ifndef DBGERR
+#define DBGERR(fmt)
+#endif
+#ifndef DBGBH
+#define DBGBH(fmt)
+#endif
+#ifndef DBGISR
+#define DBGISR(fmt)
+#endif
+
+#ifdef DBGDATA
+static void trace_block(struct slgt_info *info, const char *data, int count, const char *label)
+{
+	int i;
+	int linecount;
+	printk("%s %s data:\n",info->device_name, label);
+	while(count) {
+		linecount = (count > 16) ? 16 : count;
+		for(i=0; i < linecount; i++)
+			printk("%02X ",(unsigned char)data[i]);
+		for(;i<17;i++)
+			printk("   ");
+		for(i=0;i<linecount;i++) {
+			if (data[i]>=040 && data[i]<=0176)
+				printk("%c",data[i]);
+			else
+				printk(".");
+		}
+		printk("\n");
+		data  += linecount;
+		count -= linecount;
+	}
+}
+#else
+#define DBGDATA(info, buf, size, label)
+#endif
+
+#ifdef DBGTBUF
+static void dump_tbufs(struct slgt_info *info)
+{
+	int i;
+	printk("tbuf_current=%d\n", info->tbuf_current);
+	for (i=0 ; i < info->tbuf_count ; i++) {
+		printk("%d: count=%04X status=%04X\n",
+			i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status));
+	}
+}
+#else
+#define DBGTBUF(info)
+#endif
+
+#ifdef DBGRBUF
+static void dump_rbufs(struct slgt_info *info)
+{
+	int i;
+	printk("rbuf_current=%d\n", info->rbuf_current);
+	for (i=0 ; i < info->rbuf_count ; i++) {
+		printk("%d: count=%04X status=%04X\n",
+			i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status));
+	}
+}
+#else
+#define DBGRBUF(info)
+#endif
+
+static inline int sanity_check(struct slgt_info *info, char *devname, const char *name)
+{
+#ifdef SANITY_CHECK
+	if (!info) {
+		printk("null struct slgt_info for (%s) in %s\n", devname, name);
+		return 1;
+	}
+	if (info->magic != MGSL_MAGIC) {
+		printk("bad magic number struct slgt_info (%s) in %s\n", devname, name);
+		return 1;
+	}
+#else
+	if (!info)
+		return 1;
+#endif
+	return 0;
+}
+
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->ops->receive_buf)
+			ld->ops->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
+/* tty callbacks */
+
+static int open(struct tty_struct *tty, struct file *filp)
+{
+	struct slgt_info *info;
+	int retval, line;
+	unsigned long flags;
+
+	line = tty->index;
+	if ((line < 0) || (line >= slgt_device_count)) {
+		DBGERR(("%s: open with invalid line #%d.\n", driver_name, line));
+		return -ENODEV;
+	}
+
+	info = slgt_device_list;
+	while(info && info->line != line)
+		info = info->next_device;
+	if (sanity_check(info, tty->name, "open"))
+		return -ENODEV;
+	if (info->init_error) {
+		DBGERR(("%s init error=%d\n", info->device_name, info->init_error));
+		return -ENODEV;
+	}
+
+	tty->driver_data = info;
+	info->port.tty = tty;
+
+	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
+
+	/* If port is closing, signal caller to try again */
+	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
+		if (info->port.flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->port.close_wait);
+		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+		goto cleanup;
+	}
+
+	mutex_lock(&info->port.mutex);
+	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	spin_lock_irqsave(&info->netlock, flags);
+	if (info->netcount) {
+		retval = -EBUSY;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		mutex_unlock(&info->port.mutex);
+		goto cleanup;
+	}
+	info->port.count++;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	if (info->port.count == 1) {
+		/* 1st open on this device, init hardware */
+		retval = startup(info);
+		if (retval < 0) {
+			mutex_unlock(&info->port.mutex);
+			goto cleanup;
+		}
+	}
+	mutex_unlock(&info->port.mutex);
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+		DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
+		goto cleanup;
+	}
+
+	retval = 0;
+
+cleanup:
+	if (retval) {
+		if (tty->count == 1)
+			info->port.tty = NULL; /* tty layer will release tty struct */
+		if(info->port.count)
+			info->port.count--;
+	}
+
+	DBGINFO(("%s open rc=%d\n", info->device_name, retval));
+	return retval;
+}
+
+static void close(struct tty_struct *tty, struct file *filp)
+{
+	struct slgt_info *info = tty->driver_data;
+
+	if (sanity_check(info, tty->name, "close"))
+		return;
+	DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count));
+
+	if (tty_port_close_start(&info->port, tty, filp) == 0)
+		goto cleanup;
+
+	mutex_lock(&info->port.mutex);
+ 	if (info->port.flags & ASYNC_INITIALIZED)
+ 		wait_until_sent(tty, info->timeout);
+	flush_buffer(tty);
+	tty_ldisc_flush(tty);
+
+	shutdown(info);
+	mutex_unlock(&info->port.mutex);
+
+	tty_port_close_end(&info->port, tty);
+	info->port.tty = NULL;
+cleanup:
+	DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count));
+}
+
+static void hangup(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "hangup"))
+		return;
+	DBGINFO(("%s hangup\n", info->device_name));
+
+	flush_buffer(tty);
+
+	mutex_lock(&info->port.mutex);
+	shutdown(info);
+
+	spin_lock_irqsave(&info->port.lock, flags);
+	info->port.count = 0;
+	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+	info->port.tty = NULL;
+	spin_unlock_irqrestore(&info->port.lock, flags);
+	mutex_unlock(&info->port.mutex);
+
+	wake_up_interruptible(&info->port.open_wait);
+}
+
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	DBGINFO(("%s set_termios\n", tty->driver->name));
+
+	change_params(info);
+
+	/* Handle transition to B0 status */
+	if (old_termios->c_cflag & CBAUD &&
+	    !(tty->termios->c_cflag & CBAUD)) {
+		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+		spin_lock_irqsave(&info->lock,flags);
+		set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    tty->termios->c_cflag & CBAUD) {
+		info->signals |= SerialSignal_DTR;
+ 		if (!(tty->termios->c_cflag & CRTSCTS) ||
+ 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			info->signals |= SerialSignal_RTS;
+ 		}
+		spin_lock_irqsave(&info->lock,flags);
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+
+	/* Handle turning off CRTSCTS */
+	if (old_termios->c_cflag & CRTSCTS &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		tx_release(tty);
+	}
+}
+
+static void update_tx_timer(struct slgt_info *info)
+{
+	/*
+	 * use worst case speed of 1200bps to calculate transmit timeout
+	 * based on data in buffers (tbuf_bytes) and FIFO (128 bytes)
+	 */
+	if (info->params.mode == MGSL_MODE_HDLC) {
+		int timeout  = (tbuf_bytes(info) * 7) + 1000;
+		mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout));
+	}
+}
+
+static int write(struct tty_struct *tty,
+		 const unsigned char *buf, int count)
+{
+	int ret = 0;
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "write"))
+		return -EIO;
+
+	DBGINFO(("%s write count=%d\n", info->device_name, count));
+
+	if (!info->tx_buf || (count > info->max_frame_size))
+		return -EIO;
+
+	if (!count || tty->stopped || tty->hw_stopped)
+		return 0;
+
+	spin_lock_irqsave(&info->lock, flags);
+
+	if (info->tx_count) {
+		/* send accumulated data from send_char() */
+		if (!tx_load(info, info->tx_buf, info->tx_count))
+			goto cleanup;
+		info->tx_count = 0;
+	}
+
+	if (tx_load(info, buf, count))
+		ret = count;
+
+cleanup:
+	spin_unlock_irqrestore(&info->lock, flags);
+	DBGINFO(("%s write rc=%d\n", info->device_name, ret));
+	return ret;
+}
+
+static int put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+	int ret = 0;
+
+	if (sanity_check(info, tty->name, "put_char"))
+		return 0;
+	DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
+	if (!info->tx_buf)
+		return 0;
+	spin_lock_irqsave(&info->lock,flags);
+	if (info->tx_count < info->max_frame_size) {
+		info->tx_buf[info->tx_count++] = ch;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&info->lock,flags);
+	return ret;
+}
+
+static void send_xchar(struct tty_struct *tty, char ch)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "send_xchar"))
+		return;
+	DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch));
+	info->x_char = ch;
+	if (ch) {
+		spin_lock_irqsave(&info->lock,flags);
+		if (!info->tx_enabled)
+		 	tx_start(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+}
+
+static void wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+
+	if (!info )
+		return;
+	if (sanity_check(info, tty->name, "wait_until_sent"))
+		return;
+	DBGINFO(("%s wait_until_sent entry\n", info->device_name));
+	if (!(info->port.flags & ASYNC_INITIALIZED))
+		goto exit;
+
+	orig_jiffies = jiffies;
+
+	/* Set check interval to 1/5 of estimated time to
+	 * send a character, and make it at least 1. The check
+	 * interval should also be less than the timeout.
+	 * Note: use tight timings here to satisfy the NIST-PCTS.
+	 */
+
+	if (info->params.data_rate) {
+	       	char_time = info->timeout/(32 * 5);
+		if (!char_time)
+			char_time++;
+	} else
+		char_time = 1;
+
+	if (timeout)
+		char_time = min_t(unsigned long, char_time, timeout);
+
+	while (info->tx_active) {
+		msleep_interruptible(jiffies_to_msecs(char_time));
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+exit:
+	DBGINFO(("%s wait_until_sent exit\n", info->device_name));
+}
+
+static int write_room(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	int ret;
+
+	if (sanity_check(info, tty->name, "write_room"))
+		return 0;
+	ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
+	DBGINFO(("%s write_room=%d\n", info->device_name, ret));
+	return ret;
+}
+
+static void flush_chars(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "flush_chars"))
+		return;
+	DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));
+
+	if (info->tx_count <= 0 || tty->stopped ||
+	    tty->hw_stopped || !info->tx_buf)
+		return;
+
+	DBGINFO(("%s flush_chars start transmit\n", info->device_name));
+
+	spin_lock_irqsave(&info->lock,flags);
+	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
+		info->tx_count = 0;
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+static void flush_buffer(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "flush_buffer"))
+		return;
+	DBGINFO(("%s flush_buffer\n", info->device_name));
+
+	spin_lock_irqsave(&info->lock, flags);
+	info->tx_count = 0;
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	tty_wakeup(tty);
+}
+
+/*
+ * throttle (stop) transmitter
+ */
+static void tx_hold(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "tx_hold"))
+		return;
+	DBGINFO(("%s tx_hold\n", info->device_name));
+	spin_lock_irqsave(&info->lock,flags);
+	if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)
+	 	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * release (start) transmitter
+ */
+static void tx_release(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "tx_release"))
+		return;
+	DBGINFO(("%s tx_release\n", info->device_name));
+	spin_lock_irqsave(&info->lock, flags);
+	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
+		info->tx_count = 0;
+	spin_unlock_irqrestore(&info->lock, flags);
+}
+
+/*
+ * Service an IOCTL request
+ *
+ * Arguments
+ *
+ * 	tty	pointer to tty instance data
+ * 	cmd	IOCTL command code
+ * 	arg	command argument/context
+ *
+ * Return 0 if success, otherwise error code
+ */
+static int ioctl(struct tty_struct *tty,
+		 unsigned int cmd, unsigned long arg)
+{
+	struct slgt_info *info = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+	int ret;
+
+	if (sanity_check(info, tty->name, "ioctl"))
+		return -ENODEV;
+	DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCMIWAIT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+	case MGSL_IOCWAITEVENT:
+		return wait_mgsl_event(info, argp);
+	case TIOCMIWAIT:
+		return modem_input_wait(info,(int)arg);
+	case MGSL_IOCSGPIO:
+		return set_gpio(info, argp);
+	case MGSL_IOCGGPIO:
+		return get_gpio(info, argp);
+	case MGSL_IOCWAITGPIO:
+		return wait_gpio(info, argp);
+	case MGSL_IOCGXSYNC:
+		return get_xsync(info, argp);
+	case MGSL_IOCSXSYNC:
+		return set_xsync(info, (int)arg);
+	case MGSL_IOCGXCTRL:
+		return get_xctrl(info, argp);
+	case MGSL_IOCSXCTRL:
+		return set_xctrl(info, (int)arg);
+	}
+	mutex_lock(&info->port.mutex);
+	switch (cmd) {
+	case MGSL_IOCGPARAMS:
+		ret = get_params(info, argp);
+		break;
+	case MGSL_IOCSPARAMS:
+		ret = set_params(info, argp);
+		break;
+	case MGSL_IOCGTXIDLE:
+		ret = get_txidle(info, argp);
+		break;
+	case MGSL_IOCSTXIDLE:
+		ret = set_txidle(info, (int)arg);
+		break;
+	case MGSL_IOCTXENABLE:
+		ret = tx_enable(info, (int)arg);
+		break;
+	case MGSL_IOCRXENABLE:
+		ret = rx_enable(info, (int)arg);
+		break;
+	case MGSL_IOCTXABORT:
+		ret = tx_abort(info);
+		break;
+	case MGSL_IOCGSTATS:
+		ret = get_stats(info, argp);
+		break;
+	case MGSL_IOCGIF:
+		ret = get_interface(info, argp);
+		break;
+	case MGSL_IOCSIF:
+		ret = set_interface(info,(int)arg);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	mutex_unlock(&info->port.mutex);
+	return ret;
+}
+
+static int get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+
+{
+	struct slgt_info *info = tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
+/*
+ * support for 32 bit ioctl calls on 64 bit systems
+ */
+#ifdef CONFIG_COMPAT
+static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params)
+{
+	struct MGSL_PARAMS32 tmp_params;
+
+	DBGINFO(("%s get_params32\n", info->device_name));
+	memset(&tmp_params, 0, sizeof(tmp_params));
+	tmp_params.mode            = (compat_ulong_t)info->params.mode;
+	tmp_params.loopback        = info->params.loopback;
+	tmp_params.flags           = info->params.flags;
+	tmp_params.encoding        = info->params.encoding;
+	tmp_params.clock_speed     = (compat_ulong_t)info->params.clock_speed;
+	tmp_params.addr_filter     = info->params.addr_filter;
+	tmp_params.crc_type        = info->params.crc_type;
+	tmp_params.preamble_length = info->params.preamble_length;
+	tmp_params.preamble        = info->params.preamble;
+	tmp_params.data_rate       = (compat_ulong_t)info->params.data_rate;
+	tmp_params.data_bits       = info->params.data_bits;
+	tmp_params.stop_bits       = info->params.stop_bits;
+	tmp_params.parity          = info->params.parity;
+	if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32)))
+		return -EFAULT;
+	return 0;
+}
+
+static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params)
+{
+	struct MGSL_PARAMS32 tmp_params;
+
+	DBGINFO(("%s set_params32\n", info->device_name));
+	if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32)))
+		return -EFAULT;
+
+	spin_lock(&info->lock);
+	if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) {
+		info->base_clock = tmp_params.clock_speed;
+	} else {
+		info->params.mode            = tmp_params.mode;
+		info->params.loopback        = tmp_params.loopback;
+		info->params.flags           = tmp_params.flags;
+		info->params.encoding        = tmp_params.encoding;
+		info->params.clock_speed     = tmp_params.clock_speed;
+		info->params.addr_filter     = tmp_params.addr_filter;
+		info->params.crc_type        = tmp_params.crc_type;
+		info->params.preamble_length = tmp_params.preamble_length;
+		info->params.preamble        = tmp_params.preamble;
+		info->params.data_rate       = tmp_params.data_rate;
+		info->params.data_bits       = tmp_params.data_bits;
+		info->params.stop_bits       = tmp_params.stop_bits;
+		info->params.parity          = tmp_params.parity;
+	}
+	spin_unlock(&info->lock);
+
+	program_hw(info);
+
+	return 0;
+}
+
+static long slgt_compat_ioctl(struct tty_struct *tty,
+			 unsigned int cmd, unsigned long arg)
+{
+	struct slgt_info *info = tty->driver_data;
+	int rc = -ENOIOCTLCMD;
+
+	if (sanity_check(info, tty->name, "compat_ioctl"))
+		return -ENODEV;
+	DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
+
+	switch (cmd) {
+
+	case MGSL_IOCSPARAMS32:
+		rc = set_params32(info, compat_ptr(arg));
+		break;
+
+	case MGSL_IOCGPARAMS32:
+		rc = get_params32(info, compat_ptr(arg));
+		break;
+
+	case MGSL_IOCGPARAMS:
+	case MGSL_IOCSPARAMS:
+	case MGSL_IOCGTXIDLE:
+	case MGSL_IOCGSTATS:
+	case MGSL_IOCWAITEVENT:
+	case MGSL_IOCGIF:
+	case MGSL_IOCSGPIO:
+	case MGSL_IOCGGPIO:
+	case MGSL_IOCWAITGPIO:
+	case MGSL_IOCGXSYNC:
+	case MGSL_IOCGXCTRL:
+	case MGSL_IOCSTXIDLE:
+	case MGSL_IOCTXENABLE:
+	case MGSL_IOCRXENABLE:
+	case MGSL_IOCTXABORT:
+	case TIOCMIWAIT:
+	case MGSL_IOCSIF:
+	case MGSL_IOCSXSYNC:
+	case MGSL_IOCSXCTRL:
+		rc = ioctl(tty, cmd, arg);
+		break;
+	}
+
+	DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
+	return rc;
+}
+#else
+#define slgt_compat_ioctl NULL
+#endif /* ifdef CONFIG_COMPAT */
+
+/*
+ * proc fs support
+ */
+static inline void line_info(struct seq_file *m, struct slgt_info *info)
+{
+	char stat_buf[30];
+	unsigned long flags;
+
+	seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n",
+		      info->device_name, info->phys_reg_addr,
+		      info->irq_level, info->max_frame_size);
+
+	/* output current serial signal states */
+	spin_lock_irqsave(&info->lock,flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (info->signals & SerialSignal_RTS)
+		strcat(stat_buf, "|RTS");
+	if (info->signals & SerialSignal_CTS)
+		strcat(stat_buf, "|CTS");
+	if (info->signals & SerialSignal_DTR)
+		strcat(stat_buf, "|DTR");
+	if (info->signals & SerialSignal_DSR)
+		strcat(stat_buf, "|DSR");
+	if (info->signals & SerialSignal_DCD)
+		strcat(stat_buf, "|CD");
+	if (info->signals & SerialSignal_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		seq_printf(m, "\tHDLC txok:%d rxok:%d",
+			       info->icount.txok, info->icount.rxok);
+		if (info->icount.txunder)
+			seq_printf(m, " txunder:%d", info->icount.txunder);
+		if (info->icount.txabort)
+			seq_printf(m, " txabort:%d", info->icount.txabort);
+		if (info->icount.rxshort)
+			seq_printf(m, " rxshort:%d", info->icount.rxshort);
+		if (info->icount.rxlong)
+			seq_printf(m, " rxlong:%d", info->icount.rxlong);
+		if (info->icount.rxover)
+			seq_printf(m, " rxover:%d", info->icount.rxover);
+		if (info->icount.rxcrc)
+			seq_printf(m, " rxcrc:%d", info->icount.rxcrc);
+	} else {
+		seq_printf(m, "\tASYNC tx:%d rx:%d",
+			       info->icount.tx, info->icount.rx);
+		if (info->icount.frame)
+			seq_printf(m, " fe:%d", info->icount.frame);
+		if (info->icount.parity)
+			seq_printf(m, " pe:%d", info->icount.parity);
+		if (info->icount.brk)
+			seq_printf(m, " brk:%d", info->icount.brk);
+		if (info->icount.overrun)
+			seq_printf(m, " oe:%d", info->icount.overrun);
+	}
+
+	/* Append serial signal status to end */
+	seq_printf(m, " %s\n", stat_buf+1);
+
+	seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
+		       info->tx_active,info->bh_requested,info->bh_running,
+		       info->pending_bh);
+}
+
+/* Called to print information about devices
+ */
+static int synclink_gt_proc_show(struct seq_file *m, void *v)
+{
+	struct slgt_info *info;
+
+	seq_puts(m, "synclink_gt driver\n");
+
+	info = slgt_device_list;
+	while( info ) {
+		line_info(m, info);
+		info = info->next_device;
+	}
+	return 0;
+}
+
+static int synclink_gt_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, synclink_gt_proc_show, NULL);
+}
+
+static const struct file_operations synclink_gt_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= synclink_gt_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/*
+ * return count of bytes in transmit buffer
+ */
+static int chars_in_buffer(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	int count;
+	if (sanity_check(info, tty->name, "chars_in_buffer"))
+		return 0;
+	count = tbuf_bytes(info);
+	DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count));
+	return count;
+}
+
+/*
+ * signal remote device to throttle send data (our receive data)
+ */
+static void throttle(struct tty_struct * tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "throttle"))
+		return;
+	DBGINFO(("%s throttle\n", info->device_name));
+	if (I_IXOFF(tty))
+		send_xchar(tty, STOP_CHAR(tty));
+ 	if (tty->termios->c_cflag & CRTSCTS) {
+		spin_lock_irqsave(&info->lock,flags);
+		info->signals &= ~SerialSignal_RTS;
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+}
+
+/*
+ * signal remote device to stop throttling send data (our receive data)
+ */
+static void unthrottle(struct tty_struct * tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "unthrottle"))
+		return;
+	DBGINFO(("%s unthrottle\n", info->device_name));
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			send_xchar(tty, START_CHAR(tty));
+	}
+ 	if (tty->termios->c_cflag & CRTSCTS) {
+		spin_lock_irqsave(&info->lock,flags);
+		info->signals |= SerialSignal_RTS;
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+}
+
+/*
+ * set or clear transmit break condition
+ * break_state	-1=set break condition, 0=clear
+ */
+static int set_break(struct tty_struct *tty, int break_state)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned short value;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "set_break"))
+		return -EINVAL;
+	DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
+
+	spin_lock_irqsave(&info->lock,flags);
+	value = rd_reg16(info, TCR);
+ 	if (break_state == -1)
+		value |= BIT6;
+	else
+		value &= ~BIT6;
+	wr_reg16(info, TCR, value);
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+#if SYNCLINK_GENERIC_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
+{
+	struct slgt_info *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
+
+	/* return error if TTY interface open */
+	if (info->port.count)
+		return -EBUSY;
+
+	DBGINFO(("%s hdlcdev_attach\n", info->device_name));
+
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
+	}
+
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
+
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;
+
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		program_hw(info);
+
+	return 0;
+}
+
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ */
+static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	struct slgt_info *info = dev_to_port(dev);
+	unsigned long flags;
+
+	DBGINFO(("%s hdlc_xmit\n", dev->name));
+
+	if (!skb->len)
+		return NETDEV_TX_OK;
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* update network statistics */
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	spin_lock_irqsave(&info->lock, flags);
+	tx_load(info, skb->data, skb->len);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
+{
+	struct slgt_info *info = dev_to_port(dev);
+	int rc;
+	unsigned long flags;
+
+	if (!try_module_get(THIS_MODULE))
+		return -EBUSY;
+
+	DBGINFO(("%s hdlcdev_open\n", dev->name));
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
+
+	/* arbitrate between network and tty opens */
+	spin_lock_irqsave(&info->netlock, flags);
+	if (info->port.count != 0 || info->netcount != 0) {
+		DBGINFO(("%s hdlc_open busy\n", dev->name));
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return -EBUSY;
+	}
+	info->netcount=1;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	/* claim resources and init adapter */
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
+	}
+
+	/* assert DTR and RTS, apply hardware settings */
+	info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+	program_hw(info);
+
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
+
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->lock, flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock, flags);
+	if (info->signals & SerialSignal_DCD)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
+	return 0;
+}
+
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
+{
+	struct slgt_info *info = dev_to_port(dev);
+	unsigned long flags;
+
+	DBGINFO(("%s hdlcdev_close\n", dev->name));
+
+	netif_stop_queue(dev);
+
+	/* shutdown adapter and release resources */
+	shutdown(info);
+
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	module_put(THIS_MODULE);
+	return 0;
+}
+
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	struct slgt_info *info = dev_to_port(dev);
+	unsigned int flags;
+
+	DBGINFO(("%s hdlcdev_ioctl\n", dev->name));
+
+	/* return error if TTY interface open */
+	if (info->port.count)
+		return -EBUSY;
+
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
+
+	memset(&new_line, 0, sizeof(new_line));
+
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
+
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
+
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
+}
+
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
+{
+	struct slgt_info *info = dev_to_port(dev);
+	unsigned long flags;
+
+	DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name));
+
+	dev->stats.tx_errors++;
+	dev->stats.tx_aborted_errors++;
+
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct slgt_info *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
+{
+	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+
+	DBGINFO(("%s hdlcdev_rx\n", dev->name));
+
+	if (skb == NULL) {
+		DBGERR(("%s: can't alloc skb, drop packet\n", dev->name));
+		dev->stats.rx_dropped++;
+		return;
+	}
+
+	memcpy(skb_put(skb, size), buf, size);
+
+	skb->protocol = hdlc_type_trans(skb, dev);
+
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += size;
+
+	netif_rx(skb);
+}
+
+static const struct net_device_ops hdlcdev_ops = {
+	.ndo_open       = hdlcdev_open,
+	.ndo_stop       = hdlcdev_close,
+	.ndo_change_mtu = hdlc_change_mtu,
+	.ndo_start_xmit = hdlc_start_xmit,
+	.ndo_do_ioctl   = hdlcdev_ioctl,
+	.ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct slgt_info *info)
+{
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->mem_start = info->phys_reg_addr;
+	dev->mem_end   = info->phys_reg_addr + SLGT_REG_SIZE - 1;
+	dev->irq       = info->irq_level;
+
+	/* network layer callbacks and settings */
+	dev->netdev_ops	    = &hdlcdev_ops;
+	dev->watchdog_timeo = 10 * HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
+}
+
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(struct slgt_info *info)
+{
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
+}
+
+#endif /* ifdef CONFIG_HDLC */
+
+/*
+ * get async data from rx DMA buffers
+ */
+static void rx_async(struct slgt_info *info)
+{
+ 	struct tty_struct *tty = info->port.tty;
+ 	struct mgsl_icount *icount = &info->icount;
+	unsigned int start, end;
+	unsigned char *p;
+	unsigned char status;
+	struct slgt_desc *bufs = info->rbufs;
+	int i, count;
+	int chars = 0;
+	int stat;
+	unsigned char ch;
+
+	start = end = info->rbuf_current;
+
+	while(desc_complete(bufs[end])) {
+		count = desc_count(bufs[end]) - info->rbuf_index;
+		p     = bufs[end].buf + info->rbuf_index;
+
+		DBGISR(("%s rx_async count=%d\n", info->device_name, count));
+		DBGDATA(info, p, count, "rx");
+
+		for(i=0 ; i < count; i+=2, p+=2) {
+			ch = *p;
+			icount->rx++;
+
+			stat = 0;
+
+			if ((status = *(p+1) & (BIT1 + BIT0))) {
+				if (status & BIT1)
+					icount->parity++;
+				else if (status & BIT0)
+					icount->frame++;
+				/* discard char if tty control flags say so */
+				if (status & info->ignore_status_mask)
+					continue;
+				if (status & BIT1)
+					stat = TTY_PARITY;
+				else if (status & BIT0)
+					stat = TTY_FRAME;
+			}
+			if (tty) {
+				tty_insert_flip_char(tty, ch, stat);
+				chars++;
+			}
+		}
+
+		if (i < count) {
+			/* receive buffer not completed */
+			info->rbuf_index += i;
+			mod_timer(&info->rx_timer, jiffies + 1);
+			break;
+		}
+
+		info->rbuf_index = 0;
+		free_rbufs(info, end, end);
+
+		if (++end == info->rbuf_count)
+			end = 0;
+
+		/* if entire list searched then no frame available */
+		if (end == start)
+			break;
+	}
+
+	if (tty && chars)
+		tty_flip_buffer_push(tty);
+}
+
+/*
+ * return next bottom half action to perform
+ */
+static int bh_action(struct slgt_info *info)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	if (info->pending_bh & BH_RECEIVE) {
+		info->pending_bh &= ~BH_RECEIVE;
+		rc = BH_RECEIVE;
+	} else if (info->pending_bh & BH_TRANSMIT) {
+		info->pending_bh &= ~BH_TRANSMIT;
+		rc = BH_TRANSMIT;
+	} else if (info->pending_bh & BH_STATUS) {
+		info->pending_bh &= ~BH_STATUS;
+		rc = BH_STATUS;
+	} else {
+		/* Mark BH routine as complete */
+		info->bh_running = false;
+		info->bh_requested = false;
+		rc = 0;
+	}
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return rc;
+}
+
+/*
+ * perform bottom half processing
+ */
+static void bh_handler(struct work_struct *work)
+{
+	struct slgt_info *info = container_of(work, struct slgt_info, task);
+	int action;
+
+	if (!info)
+		return;
+	info->bh_running = true;
+
+	while((action = bh_action(info))) {
+		switch (action) {
+		case BH_RECEIVE:
+			DBGBH(("%s bh receive\n", info->device_name));
+			switch(info->params.mode) {
+			case MGSL_MODE_ASYNC:
+				rx_async(info);
+				break;
+			case MGSL_MODE_HDLC:
+				while(rx_get_frame(info));
+				break;
+			case MGSL_MODE_RAW:
+			case MGSL_MODE_MONOSYNC:
+			case MGSL_MODE_BISYNC:
+			case MGSL_MODE_XSYNC:
+				while(rx_get_buf(info));
+				break;
+			}
+			/* restart receiver if rx DMA buffers exhausted */
+			if (info->rx_restart)
+				rx_start(info);
+			break;
+		case BH_TRANSMIT:
+			bh_transmit(info);
+			break;
+		case BH_STATUS:
+			DBGBH(("%s bh status\n", info->device_name));
+			info->ri_chkcount = 0;
+			info->dsr_chkcount = 0;
+			info->dcd_chkcount = 0;
+			info->cts_chkcount = 0;
+			break;
+		default:
+			DBGBH(("%s unknown action\n", info->device_name));
+			break;
+		}
+	}
+	DBGBH(("%s bh_handler exit\n", info->device_name));
+}
+
+static void bh_transmit(struct slgt_info *info)
+{
+	struct tty_struct *tty = info->port.tty;
+
+	DBGBH(("%s bh_transmit\n", info->device_name));
+	if (tty)
+		tty_wakeup(tty);
+}
+
+static void dsr_change(struct slgt_info *info, unsigned short status)
+{
+	if (status & BIT3) {
+		info->signals |= SerialSignal_DSR;
+		info->input_signal_events.dsr_up++;
+	} else {
+		info->signals &= ~SerialSignal_DSR;
+		info->input_signal_events.dsr_down++;
+	}
+	DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
+	if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+		slgt_irq_off(info, IRQ_DSR);
+		return;
+	}
+	info->icount.dsr++;
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+	info->pending_bh |= BH_STATUS;
+}
+
+static void cts_change(struct slgt_info *info, unsigned short status)
+{
+	if (status & BIT2) {
+		info->signals |= SerialSignal_CTS;
+		info->input_signal_events.cts_up++;
+	} else {
+		info->signals &= ~SerialSignal_CTS;
+		info->input_signal_events.cts_down++;
+	}
+	DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
+	if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+		slgt_irq_off(info, IRQ_CTS);
+		return;
+	}
+	info->icount.cts++;
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+	info->pending_bh |= BH_STATUS;
+
+	if (info->port.flags & ASYNC_CTS_FLOW) {
+		if (info->port.tty) {
+			if (info->port.tty->hw_stopped) {
+				if (info->signals & SerialSignal_CTS) {
+		 			info->port.tty->hw_stopped = 0;
+					info->pending_bh |= BH_TRANSMIT;
+					return;
+				}
+			} else {
+				if (!(info->signals & SerialSignal_CTS))
+		 			info->port.tty->hw_stopped = 1;
+			}
+		}
+	}
+}
+
+static void dcd_change(struct slgt_info *info, unsigned short status)
+{
+	if (status & BIT1) {
+		info->signals |= SerialSignal_DCD;
+		info->input_signal_events.dcd_up++;
+	} else {
+		info->signals &= ~SerialSignal_DCD;
+		info->input_signal_events.dcd_down++;
+	}
+	DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
+	if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+		slgt_irq_off(info, IRQ_DCD);
+		return;
+	}
+	info->icount.dcd++;
+#if SYNCLINK_GENERIC_HDLC
+	if (info->netcount) {
+		if (info->signals & SerialSignal_DCD)
+			netif_carrier_on(info->netdev);
+		else
+			netif_carrier_off(info->netdev);
+	}
+#endif
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+	info->pending_bh |= BH_STATUS;
+
+	if (info->port.flags & ASYNC_CHECK_CD) {
+		if (info->signals & SerialSignal_DCD)
+			wake_up_interruptible(&info->port.open_wait);
+		else {
+			if (info->port.tty)
+				tty_hangup(info->port.tty);
+		}
+	}
+}
+
+static void ri_change(struct slgt_info *info, unsigned short status)
+{
+	if (status & BIT0) {
+		info->signals |= SerialSignal_RI;
+		info->input_signal_events.ri_up++;
+	} else {
+		info->signals &= ~SerialSignal_RI;
+		info->input_signal_events.ri_down++;
+	}
+	DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
+	if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
+		slgt_irq_off(info, IRQ_RI);
+		return;
+	}
+	info->icount.rng++;
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+	info->pending_bh |= BH_STATUS;
+}
+
+static void isr_rxdata(struct slgt_info *info)
+{
+	unsigned int count = info->rbuf_fill_count;
+	unsigned int i = info->rbuf_fill_index;
+	unsigned short reg;
+
+	while (rd_reg16(info, SSR) & IRQ_RXDATA) {
+		reg = rd_reg16(info, RDR);
+		DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg));
+		if (desc_complete(info->rbufs[i])) {
+			/* all buffers full */
+			rx_stop(info);
+			info->rx_restart = 1;
+			continue;
+		}
+		info->rbufs[i].buf[count++] = (unsigned char)reg;
+		/* async mode saves status byte to buffer for each data byte */
+		if (info->params.mode == MGSL_MODE_ASYNC)
+			info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8);
+		if (count == info->rbuf_fill_level || (reg & BIT10)) {
+			/* buffer full or end of frame */
+			set_desc_count(info->rbufs[i], count);
+			set_desc_status(info->rbufs[i], BIT15 | (reg >> 8));
+			info->rbuf_fill_count = count = 0;
+			if (++i == info->rbuf_count)
+				i = 0;
+			info->pending_bh |= BH_RECEIVE;
+		}
+	}
+
+	info->rbuf_fill_index = i;
+	info->rbuf_fill_count = count;
+}
+
+static void isr_serial(struct slgt_info *info)
+{
+	unsigned short status = rd_reg16(info, SSR);
+
+	DBGISR(("%s isr_serial status=%04X\n", info->device_name, status));
+
+	wr_reg16(info, SSR, status); /* clear pending */
+
+	info->irq_occurred = true;
+
+	if (info->params.mode == MGSL_MODE_ASYNC) {
+		if (status & IRQ_TXIDLE) {
+			if (info->tx_active)
+				isr_txeom(info, status);
+		}
+		if (info->rx_pio && (status & IRQ_RXDATA))
+			isr_rxdata(info);
+		if ((status & IRQ_RXBREAK) && (status & RXBREAK)) {
+			info->icount.brk++;
+			/* process break detection if tty control allows */
+			if (info->port.tty) {
+				if (!(status & info->ignore_status_mask)) {
+					if (info->read_status_mask & MASK_BREAK) {
+						tty_insert_flip_char(info->port.tty, 0, TTY_BREAK);
+						if (info->port.flags & ASYNC_SAK)
+							do_SAK(info->port.tty);
+					}
+				}
+			}
+		}
+	} else {
+		if (status & (IRQ_TXIDLE + IRQ_TXUNDER))
+			isr_txeom(info, status);
+		if (info->rx_pio && (status & IRQ_RXDATA))
+			isr_rxdata(info);
+		if (status & IRQ_RXIDLE) {
+			if (status & RXIDLE)
+				info->icount.rxidle++;
+			else
+				info->icount.exithunt++;
+			wake_up_interruptible(&info->event_wait_q);
+		}
+
+		if (status & IRQ_RXOVER)
+			rx_start(info);
+	}
+
+	if (status & IRQ_DSR)
+		dsr_change(info, status);
+	if (status & IRQ_CTS)
+		cts_change(info, status);
+	if (status & IRQ_DCD)
+		dcd_change(info, status);
+	if (status & IRQ_RI)
+		ri_change(info, status);
+}
+
+static void isr_rdma(struct slgt_info *info)
+{
+	unsigned int status = rd_reg32(info, RDCSR);
+
+	DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status));
+
+	/* RDCSR (rx DMA control/status)
+	 *
+	 * 31..07  reserved
+	 * 06      save status byte to DMA buffer
+	 * 05      error
+	 * 04      eol (end of list)
+	 * 03      eob (end of buffer)
+	 * 02      IRQ enable
+	 * 01      reset
+	 * 00      enable
+	 */
+	wr_reg32(info, RDCSR, status);	/* clear pending */
+
+	if (status & (BIT5 + BIT4)) {
+		DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
+		info->rx_restart = true;
+	}
+	info->pending_bh |= BH_RECEIVE;
+}
+
+static void isr_tdma(struct slgt_info *info)
+{
+	unsigned int status = rd_reg32(info, TDCSR);
+
+	DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status));
+
+	/* TDCSR (tx DMA control/status)
+	 *
+	 * 31..06  reserved
+	 * 05      error
+	 * 04      eol (end of list)
+	 * 03      eob (end of buffer)
+	 * 02      IRQ enable
+	 * 01      reset
+	 * 00      enable
+	 */
+	wr_reg32(info, TDCSR, status);	/* clear pending */
+
+	if (status & (BIT5 + BIT4 + BIT3)) {
+		// another transmit buffer has completed
+		// run bottom half to get more send data from user
+		info->pending_bh |= BH_TRANSMIT;
+	}
+}
+
+/*
+ * return true if there are unsent tx DMA buffers, otherwise false
+ *
+ * if there are unsent buffers then info->tbuf_start
+ * is set to index of first unsent buffer
+ */
+static bool unsent_tbufs(struct slgt_info *info)
+{
+	unsigned int i = info->tbuf_current;
+	bool rc = false;
+
+	/*
+	 * search backwards from last loaded buffer (precedes tbuf_current)
+	 * for first unsent buffer (desc_count > 0)
+	 */
+
+	do {
+		if (i)
+			i--;
+		else
+			i = info->tbuf_count - 1;
+		if (!desc_count(info->tbufs[i]))
+			break;
+		info->tbuf_start = i;
+		rc = true;
+	} while (i != info->tbuf_current);
+
+	return rc;
+}
+
+static void isr_txeom(struct slgt_info *info, unsigned short status)
+{
+	DBGISR(("%s txeom status=%04x\n", info->device_name, status));
+
+	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+	tdma_reset(info);
+	if (status & IRQ_TXUNDER) {
+		unsigned short val = rd_reg16(info, TCR);
+		wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+		wr_reg16(info, TCR, val); /* clear reset bit */
+	}
+
+	if (info->tx_active) {
+		if (info->params.mode != MGSL_MODE_ASYNC) {
+			if (status & IRQ_TXUNDER)
+				info->icount.txunder++;
+			else if (status & IRQ_TXIDLE)
+				info->icount.txok++;
+		}
+
+		if (unsent_tbufs(info)) {
+			tx_start(info);
+			update_tx_timer(info);
+			return;
+		}
+		info->tx_active = false;
+
+		del_timer(&info->tx_timer);
+
+		if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
+			info->signals &= ~SerialSignal_RTS;
+			info->drop_rts_on_tx_done = false;
+			set_signals(info);
+		}
+
+#if SYNCLINK_GENERIC_HDLC
+		if (info->netcount)
+			hdlcdev_tx_done(info);
+		else
+#endif
+		{
+			if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
+				tx_stop(info);
+				return;
+			}
+			info->pending_bh |= BH_TRANSMIT;
+		}
+	}
+}
+
+static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state)
+{
+	struct cond_wait *w, *prev;
+
+	/* wake processes waiting for specific transitions */
+	for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) {
+		if (w->data & changed) {
+			w->data = state;
+			wake_up_interruptible(&w->q);
+			if (prev != NULL)
+				prev->next = w->next;
+			else
+				info->gpio_wait_q = w->next;
+		} else
+			prev = w;
+	}
+}
+
+/* interrupt service routine
+ *
+ * 	irq	interrupt number
+ * 	dev_id	device ID supplied during interrupt registration
+ */
+static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
+{
+	struct slgt_info *info = dev_id;
+	unsigned int gsr;
+	unsigned int i;
+
+	DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
+
+	while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
+		DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
+		info->irq_occurred = true;
+		for(i=0; i < info->port_count ; i++) {
+			if (info->port_array[i] == NULL)
+				continue;
+			spin_lock(&info->port_array[i]->lock);
+			if (gsr & (BIT8 << i))
+				isr_serial(info->port_array[i]);
+			if (gsr & (BIT16 << (i*2)))
+				isr_rdma(info->port_array[i]);
+			if (gsr & (BIT17 << (i*2)))
+				isr_tdma(info->port_array[i]);
+			spin_unlock(&info->port_array[i]->lock);
+		}
+	}
+
+	if (info->gpio_present) {
+		unsigned int state;
+		unsigned int changed;
+		spin_lock(&info->lock);
+		while ((changed = rd_reg32(info, IOSR)) != 0) {
+			DBGISR(("%s iosr=%08x\n", info->device_name, changed));
+			/* read latched state of GPIO signals */
+			state = rd_reg32(info, IOVR);
+			/* clear pending GPIO interrupt bits */
+			wr_reg32(info, IOSR, changed);
+			for (i=0 ; i < info->port_count ; i++) {
+				if (info->port_array[i] != NULL)
+					isr_gpio(info->port_array[i], changed, state);
+			}
+		}
+		spin_unlock(&info->lock);
+	}
+
+	for(i=0; i < info->port_count ; i++) {
+		struct slgt_info *port = info->port_array[i];
+		if (port == NULL)
+			continue;
+		spin_lock(&port->lock);
+		if ((port->port.count || port->netcount) &&
+		    port->pending_bh && !port->bh_running &&
+		    !port->bh_requested) {
+			DBGISR(("%s bh queued\n", port->device_name));
+			schedule_work(&port->task);
+			port->bh_requested = true;
+		}
+		spin_unlock(&port->lock);
+	}
+
+	DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
+	return IRQ_HANDLED;
+}
+
+static int startup(struct slgt_info *info)
+{
+	DBGINFO(("%s startup\n", info->device_name));
+
+	if (info->port.flags & ASYNC_INITIALIZED)
+		return 0;
+
+	if (!info->tx_buf) {
+		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
+		if (!info->tx_buf) {
+			DBGERR(("%s can't allocate tx buffer\n", info->device_name));
+			return -ENOMEM;
+		}
+	}
+
+	info->pending_bh = 0;
+
+	memset(&info->icount, 0, sizeof(info->icount));
+
+	/* program hardware for current parameters */
+	change_params(info);
+
+	if (info->port.tty)
+		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+
+	info->port.flags |= ASYNC_INITIALIZED;
+
+	return 0;
+}
+
+/*
+ *  called by close() and hangup() to shutdown hardware
+ */
+static void shutdown(struct slgt_info *info)
+{
+	unsigned long flags;
+
+	if (!(info->port.flags & ASYNC_INITIALIZED))
+		return;
+
+	DBGINFO(("%s shutdown\n", info->device_name));
+
+	/* clear status wait queue because status changes */
+	/* can't happen after shutting down the hardware */
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+
+	del_timer_sync(&info->tx_timer);
+	del_timer_sync(&info->rx_timer);
+
+	kfree(info->tx_buf);
+	info->tx_buf = NULL;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	tx_stop(info);
+	rx_stop(info);
+
+	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+
+ 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+ 		info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+		set_signals(info);
+	}
+
+	flush_cond_wait(&info->gpio_wait_q);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	if (info->port.tty)
+		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+
+	info->port.flags &= ~ASYNC_INITIALIZED;
+}
+
+static void program_hw(struct slgt_info *info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	rx_stop(info);
+	tx_stop(info);
+
+	if (info->params.mode != MGSL_MODE_ASYNC ||
+	    info->netcount)
+		sync_mode(info);
+	else
+		async_mode(info);
+
+	set_signals(info);
+
+	info->dcd_chkcount = 0;
+	info->cts_chkcount = 0;
+	info->ri_chkcount = 0;
+	info->dsr_chkcount = 0;
+
+	slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI);
+	get_signals(info);
+
+	if (info->netcount ||
+	    (info->port.tty && info->port.tty->termios->c_cflag & CREAD))
+		rx_start(info);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/*
+ * reconfigure adapter based on new parameters
+ */
+static void change_params(struct slgt_info *info)
+{
+	unsigned cflag;
+	int bits_per_char;
+
+	if (!info->port.tty || !info->port.tty->termios)
+		return;
+	DBGINFO(("%s change_params\n", info->device_name));
+
+	cflag = info->port.tty->termios->c_cflag;
+
+	/* if B0 rate (hangup) specified then negate DTR and RTS */
+	/* otherwise assert DTR and RTS */
+ 	if (cflag & CBAUD)
+		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+
+	/* byte size and parity */
+
+	switch (cflag & CSIZE) {
+	case CS5: info->params.data_bits = 5; break;
+	case CS6: info->params.data_bits = 6; break;
+	case CS7: info->params.data_bits = 7; break;
+	case CS8: info->params.data_bits = 8; break;
+	default:  info->params.data_bits = 7; break;
+	}
+
+	info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1;
+
+	if (cflag & PARENB)
+		info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN;
+	else
+		info->params.parity = ASYNC_PARITY_NONE;
+
+	/* calculate number of jiffies to transmit a full
+	 * FIFO (32 bytes) at specified data rate
+	 */
+	bits_per_char = info->params.data_bits +
+			info->params.stop_bits + 1;
+
+	info->params.data_rate = tty_get_baud_rate(info->port.tty);
+
+	if (info->params.data_rate) {
+		info->timeout = (32*HZ*bits_per_char) /
+				info->params.data_rate;
+	}
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	if (cflag & CRTSCTS)
+		info->port.flags |= ASYNC_CTS_FLOW;
+	else
+		info->port.flags &= ~ASYNC_CTS_FLOW;
+
+	if (cflag & CLOCAL)
+		info->port.flags &= ~ASYNC_CHECK_CD;
+	else
+		info->port.flags |= ASYNC_CHECK_CD;
+
+	/* process tty input control flags */
+
+	info->read_status_mask = IRQ_RXOVER;
+	if (I_INPCK(info->port.tty))
+		info->read_status_mask |= MASK_PARITY | MASK_FRAMING;
+ 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
+ 		info->read_status_mask |= MASK_BREAK;
+	if (I_IGNPAR(info->port.tty))
+		info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING;
+	if (I_IGNBRK(info->port.tty)) {
+		info->ignore_status_mask |= MASK_BREAK;
+		/* If ignoring parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->port.tty))
+			info->ignore_status_mask |= MASK_OVERRUN;
+	}
+
+	program_hw(info);
+}
+
+static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount)
+{
+	DBGINFO(("%s get_stats\n",  info->device_name));
+	if (!user_icount) {
+		memset(&info->icount, 0, sizeof(info->icount));
+	} else {
+		if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params)
+{
+	DBGINFO(("%s get_params\n", info->device_name));
+	if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params)
+{
+ 	unsigned long flags;
+	MGSL_PARAMS tmp_params;
+
+	DBGINFO(("%s set_params\n", info->device_name));
+	if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS)))
+		return -EFAULT;
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (tmp_params.mode == MGSL_MODE_BASE_CLOCK)
+		info->base_clock = tmp_params.clock_speed;
+	else
+		memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS));
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	program_hw(info);
+
+	return 0;
+}
+
+static int get_txidle(struct slgt_info *info, int __user *idle_mode)
+{
+	DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode));
+	if (put_user(info->idle_mode, idle_mode))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_txidle(struct slgt_info *info, int idle_mode)
+{
+ 	unsigned long flags;
+	DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
+	spin_lock_irqsave(&info->lock,flags);
+	info->idle_mode = idle_mode;
+	if (info->params.mode != MGSL_MODE_ASYNC)
+		tx_set_idle(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+static int tx_enable(struct slgt_info *info, int enable)
+{
+ 	unsigned long flags;
+	DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable));
+	spin_lock_irqsave(&info->lock,flags);
+	if (enable) {
+		if (!info->tx_enabled)
+			tx_start(info);
+	} else {
+		if (info->tx_enabled)
+			tx_stop(info);
+	}
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+/*
+ * abort transmit HDLC frame
+ */
+static int tx_abort(struct slgt_info *info)
+{
+ 	unsigned long flags;
+	DBGINFO(("%s tx_abort\n", info->device_name));
+	spin_lock_irqsave(&info->lock,flags);
+	tdma_reset(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+static int rx_enable(struct slgt_info *info, int enable)
+{
+ 	unsigned long flags;
+	unsigned int rbuf_fill_level;
+	DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable));
+	spin_lock_irqsave(&info->lock,flags);
+	/*
+	 * enable[31..16] = receive DMA buffer fill level
+	 * 0 = noop (leave fill level unchanged)
+	 * fill level must be multiple of 4 and <= buffer size
+	 */
+	rbuf_fill_level = ((unsigned int)enable) >> 16;
+	if (rbuf_fill_level) {
+		if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) {
+			spin_unlock_irqrestore(&info->lock, flags);
+			return -EINVAL;
+		}
+		info->rbuf_fill_level = rbuf_fill_level;
+		if (rbuf_fill_level < 128)
+			info->rx_pio = 1; /* PIO mode */
+		else
+			info->rx_pio = 0; /* DMA mode */
+		rx_stop(info); /* restart receiver to use new fill level */
+	}
+
+	/*
+	 * enable[1..0] = receiver enable command
+	 * 0 = disable
+	 * 1 = enable
+	 * 2 = enable or force hunt mode if already enabled
+	 */
+	enable &= 3;
+	if (enable) {
+		if (!info->rx_enabled)
+			rx_start(info);
+		else if (enable == 2) {
+			/* force hunt mode (write 1 to RCR[3]) */
+			wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
+		}
+	} else {
+		if (info->rx_enabled)
+			rx_stop(info);
+	}
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+/*
+ *  wait for specified event to occur
+ */
+static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr)
+{
+ 	unsigned long flags;
+	int s;
+	int rc=0;
+	struct mgsl_icount cprev, cnow;
+	int events;
+	int mask;
+	struct	_input_signal_events oldsigs, newsigs;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (get_user(mask, mask_ptr))
+		return -EFAULT;
+
+	DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask));
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	/* return immediately if state matches requested events */
+	get_signals(info);
+	s = info->signals;
+
+	events = mask &
+		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
+ 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
+		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
+		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
+	if (events) {
+		spin_unlock_irqrestore(&info->lock,flags);
+		goto exit;
+	}
+
+	/* save current irq counts */
+	cprev = info->icount;
+	oldsigs = info->input_signal_events;
+
+	/* enable hunt and idle irqs if needed */
+	if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
+		unsigned short val = rd_reg16(info, SCR);
+		if (!(val & IRQ_RXIDLE))
+			wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE));
+	}
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&info->event_wait_q, &wait);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+
+		/* get current irq counts */
+		spin_lock_irqsave(&info->lock,flags);
+		cnow = info->icount;
+		newsigs = info->input_signal_events;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->lock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
+		    newsigs.dsr_down == oldsigs.dsr_down &&
+		    newsigs.dcd_up   == oldsigs.dcd_up   &&
+		    newsigs.dcd_down == oldsigs.dcd_down &&
+		    newsigs.cts_up   == oldsigs.cts_up   &&
+		    newsigs.cts_down == oldsigs.cts_down &&
+		    newsigs.ri_up    == oldsigs.ri_up    &&
+		    newsigs.ri_down  == oldsigs.ri_down  &&
+		    cnow.exithunt    == cprev.exithunt   &&
+		    cnow.rxidle      == cprev.rxidle) {
+			rc = -EIO;
+			break;
+		}
+
+		events = mask &
+			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
+			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
+			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
+			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
+			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
+			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
+			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
+			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
+			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
+			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
+		if (events)
+			break;
+
+		cprev = cnow;
+		oldsigs = newsigs;
+	}
+
+	remove_wait_queue(&info->event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+
+
+	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+		spin_lock_irqsave(&info->lock,flags);
+		if (!waitqueue_active(&info->event_wait_q)) {
+			/* disable enable exit hunt mode/idle rcvd IRQs */
+			wr_reg16(info, SCR,
+				(unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE));
+		}
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+exit:
+	if (rc == 0)
+		rc = put_user(events, mask_ptr);
+	return rc;
+}
+
+static int get_interface(struct slgt_info *info, int __user *if_mode)
+{
+	DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode));
+	if (put_user(info->if_mode, if_mode))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_interface(struct slgt_info *info, int if_mode)
+{
+ 	unsigned long flags;
+	unsigned short val;
+
+	DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
+	spin_lock_irqsave(&info->lock,flags);
+	info->if_mode = if_mode;
+
+	msc_set_vcr(info);
+
+	/* TCR (tx control) 07  1=RTS driver control */
+	val = rd_reg16(info, TCR);
+	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+		val |= BIT7;
+	else
+		val &= ~BIT7;
+	wr_reg16(info, TCR, val);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+static int get_xsync(struct slgt_info *info, int __user *xsync)
+{
+	DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync));
+	if (put_user(info->xsync, xsync))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * set extended sync pattern (1 to 4 bytes) for extended sync mode
+ *
+ * sync pattern is contained in least significant bytes of value
+ * most significant byte of sync pattern is oldest (1st sent/detected)
+ */
+static int set_xsync(struct slgt_info *info, int xsync)
+{
+	unsigned long flags;
+
+	DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync));
+	spin_lock_irqsave(&info->lock, flags);
+	info->xsync = xsync;
+	wr_reg32(info, XSR, xsync);
+	spin_unlock_irqrestore(&info->lock, flags);
+	return 0;
+}
+
+static int get_xctrl(struct slgt_info *info, int __user *xctrl)
+{
+	DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl));
+	if (put_user(info->xctrl, xctrl))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * set extended control options
+ *
+ * xctrl[31:19] reserved, must be zero
+ * xctrl[18:17] extended sync pattern length in bytes
+ *              00 = 1 byte  in xsr[7:0]
+ *              01 = 2 bytes in xsr[15:0]
+ *              10 = 3 bytes in xsr[23:0]
+ *              11 = 4 bytes in xsr[31:0]
+ * xctrl[16]    1 = enable terminal count, 0=disabled
+ * xctrl[15:0]  receive terminal count for fixed length packets
+ *              value is count minus one (0 = 1 byte packet)
+ *              when terminal count is reached, receiver
+ *              automatically returns to hunt mode and receive
+ *              FIFO contents are flushed to DMA buffers with
+ *              end of frame (EOF) status
+ */
+static int set_xctrl(struct slgt_info *info, int xctrl)
+{
+	unsigned long flags;
+
+	DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl));
+	spin_lock_irqsave(&info->lock, flags);
+	info->xctrl = xctrl;
+	wr_reg32(info, XCR, xctrl);
+	spin_unlock_irqrestore(&info->lock, flags);
+	return 0;
+}
+
+/*
+ * set general purpose IO pin state and direction
+ *
+ * user_gpio fields:
+ * state   each bit indicates a pin state
+ * smask   set bit indicates pin state to set
+ * dir     each bit indicates a pin direction (0=input, 1=output)
+ * dmask   set bit indicates pin direction to set
+ */
+static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ 	unsigned long flags;
+	struct gpio_desc gpio;
+	__u32 data;
+
+	if (!info->gpio_present)
+		return -EINVAL;
+	if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
+		return -EFAULT;
+	DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n",
+		 info->device_name, gpio.state, gpio.smask,
+		 gpio.dir, gpio.dmask));
+
+	spin_lock_irqsave(&info->port_array[0]->lock, flags);
+	if (gpio.dmask) {
+		data = rd_reg32(info, IODR);
+		data |= gpio.dmask & gpio.dir;
+		data &= ~(gpio.dmask & ~gpio.dir);
+		wr_reg32(info, IODR, data);
+	}
+	if (gpio.smask) {
+		data = rd_reg32(info, IOVR);
+		data |= gpio.smask & gpio.state;
+		data &= ~(gpio.smask & ~gpio.state);
+		wr_reg32(info, IOVR, data);
+	}
+	spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
+
+	return 0;
+}
+
+/*
+ * get general purpose IO pin state and direction
+ */
+static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+	struct gpio_desc gpio;
+	if (!info->gpio_present)
+		return -EINVAL;
+	gpio.state = rd_reg32(info, IOVR);
+	gpio.smask = 0xffffffff;
+	gpio.dir   = rd_reg32(info, IODR);
+	gpio.dmask = 0xffffffff;
+	if (copy_to_user(user_gpio, &gpio, sizeof(gpio)))
+		return -EFAULT;
+	DBGINFO(("%s get_gpio state=%08x dir=%08x\n",
+		 info->device_name, gpio.state, gpio.dir));
+	return 0;
+}
+
+/*
+ * conditional wait facility
+ */
+static void init_cond_wait(struct cond_wait *w, unsigned int data)
+{
+	init_waitqueue_head(&w->q);
+	init_waitqueue_entry(&w->wait, current);
+	w->data = data;
+}
+
+static void add_cond_wait(struct cond_wait **head, struct cond_wait *w)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&w->q, &w->wait);
+	w->next = *head;
+	*head = w;
+}
+
+static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw)
+{
+	struct cond_wait *w, *prev;
+	remove_wait_queue(&cw->q, &cw->wait);
+	set_current_state(TASK_RUNNING);
+	for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) {
+		if (w == cw) {
+			if (prev != NULL)
+				prev->next = w->next;
+			else
+				*head = w->next;
+			break;
+		}
+	}
+}
+
+static void flush_cond_wait(struct cond_wait **head)
+{
+	while (*head != NULL) {
+		wake_up_interruptible(&(*head)->q);
+		*head = (*head)->next;
+	}
+}
+
+/*
+ * wait for general purpose I/O pin(s) to enter specified state
+ *
+ * user_gpio fields:
+ * state - bit indicates target pin state
+ * smask - set bit indicates watched pin
+ *
+ * The wait ends when at least one watched pin enters the specified
+ * state. When 0 (no error) is returned, user_gpio->state is set to the
+ * state of all GPIO pins when the wait ends.
+ *
+ * Note: Each pin may be a dedicated input, dedicated output, or
+ * configurable input/output. The number and configuration of pins
+ * varies with the specific adapter model. Only input pins (dedicated
+ * or configured) can be monitored with this function.
+ */
+static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
+{
+ 	unsigned long flags;
+	int rc = 0;
+	struct gpio_desc gpio;
+	struct cond_wait wait;
+	u32 state;
+
+	if (!info->gpio_present)
+		return -EINVAL;
+	if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
+		return -EFAULT;
+	DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n",
+		 info->device_name, gpio.state, gpio.smask));
+	/* ignore output pins identified by set IODR bit */
+	if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0)
+		return -EINVAL;
+	init_cond_wait(&wait, gpio.smask);
+
+	spin_lock_irqsave(&info->port_array[0]->lock, flags);
+	/* enable interrupts for watched pins */
+	wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
+	/* get current pin states */
+	state = rd_reg32(info, IOVR);
+
+	if (gpio.smask & ~(state ^ gpio.state)) {
+		/* already in target state */
+		gpio.state = state;
+	} else {
+		/* wait for target state */
+		add_cond_wait(&info->gpio_wait_q, &wait);
+		spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
+		schedule();
+		if (signal_pending(current))
+			rc = -ERESTARTSYS;
+		else
+			gpio.state = wait.data;
+		spin_lock_irqsave(&info->port_array[0]->lock, flags);
+		remove_cond_wait(&info->gpio_wait_q, &wait);
+	}
+
+	/* disable all GPIO interrupts if no waiting processes */
+	if (info->gpio_wait_q == NULL)
+		wr_reg32(info, IOER, 0);
+	spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
+
+	if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
+		rc = -EFAULT;
+	return rc;
+}
+
+static int modem_input_wait(struct slgt_info *info,int arg)
+{
+ 	unsigned long flags;
+	int rc;
+	struct mgsl_icount cprev, cnow;
+	DECLARE_WAITQUEUE(wait, current);
+
+	/* save current irq counts */
+	spin_lock_irqsave(&info->lock,flags);
+	cprev = info->icount;
+	add_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+
+		/* get new irq counts */
+		spin_lock_irqsave(&info->lock,flags);
+		cnow = info->icount;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->lock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+			rc = -EIO;
+			break;
+		}
+
+		/* check for change in caller specified modem input */
+		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
+		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
+		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
+		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
+			rc = 0;
+			break;
+		}
+
+		cprev = cnow;
+	}
+	remove_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+	return rc;
+}
+
+/*
+ *  return state of serial control and status signals
+ */
+static int tiocmget(struct tty_struct *tty)
+{
+	struct slgt_info *info = tty->driver_data;
+	unsigned int result;
+ 	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+ 	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
+		((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
+		((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
+		((info->signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
+		((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
+		((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0);
+
+	DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result));
+	return result;
+}
+
+/*
+ * set modem control signals (DTR/RTS)
+ *
+ * 	cmd	signal command: TIOCMBIS = set bit TIOCMBIC = clear bit
+ *		TIOCMSET = set/clear signal values
+ * 	value	bit mask for command
+ */
+static int tiocmset(struct tty_struct *tty,
+		    unsigned int set, unsigned int clear)
+{
+	struct slgt_info *info = tty->driver_data;
+ 	unsigned long flags;
+
+	DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear));
+
+	if (set & TIOCM_RTS)
+		info->signals |= SerialSignal_RTS;
+	if (set & TIOCM_DTR)
+		info->signals |= SerialSignal_DTR;
+	if (clear & TIOCM_RTS)
+		info->signals &= ~SerialSignal_RTS;
+	if (clear & TIOCM_DTR)
+		info->signals &= ~SerialSignal_DTR;
+
+	spin_lock_irqsave(&info->lock,flags);
+ 	set_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+static int carrier_raised(struct tty_port *port)
+{
+	unsigned long flags;
+	struct slgt_info *info = container_of(port, struct slgt_info, port);
+
+	spin_lock_irqsave(&info->lock,flags);
+ 	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+	return (info->signals & SerialSignal_DCD) ? 1 : 0;
+}
+
+static void dtr_rts(struct tty_port *port, int on)
+{
+	unsigned long flags;
+	struct slgt_info *info = container_of(port, struct slgt_info, port);
+
+	spin_lock_irqsave(&info->lock,flags);
+	if (on)
+		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+ 	set_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+
+/*
+ *  block current process until the device is ready to open
+ */
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+			   struct slgt_info *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int		retval;
+	bool		do_clocal = false;
+	bool		extra_count = false;
+	unsigned long	flags;
+	int		cd;
+	struct tty_port *port = &info->port;
+
+	DBGINFO(("%s block_til_ready\n", tty->driver->name));
+
+	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+		/* nonblock mode is set or port is not enabled */
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (tty->termios->c_cflag & CLOCAL)
+		do_clocal = true;
+
+	/* Wait for carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, port->count is dropped by one, so that
+	 * close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+
+	retval = 0;
+	add_wait_queue(&port->open_wait, &wait);
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (!tty_hung_up_p(filp)) {
+		extra_count = true;
+		port->count--;
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
+	port->blocked_open++;
+
+	while (1) {
+		if ((tty->termios->c_cflag & CBAUD))
+			tty_port_raise_dtr_rts(port);
+
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
+			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
+					-EAGAIN : -ERESTARTSYS;
+			break;
+		}
+
+		cd = tty_port_carrier_raised(port);
+
+ 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
+ 			break;
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+
+		DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->open_wait, &wait);
+
+	if (extra_count)
+		port->count++;
+	port->blocked_open--;
+
+	if (!retval)
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+
+	DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
+	return retval;
+}
+
+static int alloc_tmp_rbuf(struct slgt_info *info)
+{
+	info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
+	if (info->tmp_rbuf == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void free_tmp_rbuf(struct slgt_info *info)
+{
+	kfree(info->tmp_rbuf);
+	info->tmp_rbuf = NULL;
+}
+
+/*
+ * allocate DMA descriptor lists.
+ */
+static int alloc_desc(struct slgt_info *info)
+{
+	unsigned int i;
+	unsigned int pbufs;
+
+	/* allocate memory to hold descriptor lists */
+	info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr);
+	if (info->bufs == NULL)
+		return -ENOMEM;
+
+	memset(info->bufs, 0, DESC_LIST_SIZE);
+
+	info->rbufs = (struct slgt_desc*)info->bufs;
+	info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count;
+
+	pbufs = (unsigned int)info->bufs_dma_addr;
+
+	/*
+	 * Build circular lists of descriptors
+	 */
+
+	for (i=0; i < info->rbuf_count; i++) {
+		/* physical address of this descriptor */
+		info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc));
+
+		/* physical address of next descriptor */
+		if (i == info->rbuf_count - 1)
+			info->rbufs[i].next = cpu_to_le32(pbufs);
+		else
+			info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc)));
+		set_desc_count(info->rbufs[i], DMABUFSIZE);
+	}
+
+	for (i=0; i < info->tbuf_count; i++) {
+		/* physical address of this descriptor */
+		info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc));
+
+		/* physical address of next descriptor */
+		if (i == info->tbuf_count - 1)
+			info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc));
+		else
+			info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc)));
+	}
+
+	return 0;
+}
+
+static void free_desc(struct slgt_info *info)
+{
+	if (info->bufs != NULL) {
+		pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr);
+		info->bufs  = NULL;
+		info->rbufs = NULL;
+		info->tbufs = NULL;
+	}
+}
+
+static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
+{
+	int i;
+	for (i=0; i < count; i++) {
+		if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL)
+			return -ENOMEM;
+		bufs[i].pbuf  = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr);
+	}
+	return 0;
+}
+
+static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
+{
+	int i;
+	for (i=0; i < count; i++) {
+		if (bufs[i].buf == NULL)
+			continue;
+		pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr);
+		bufs[i].buf = NULL;
+	}
+}
+
+static int alloc_dma_bufs(struct slgt_info *info)
+{
+	info->rbuf_count = 32;
+	info->tbuf_count = 32;
+
+	if (alloc_desc(info) < 0 ||
+	    alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 ||
+	    alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 ||
+	    alloc_tmp_rbuf(info) < 0) {
+		DBGERR(("%s DMA buffer alloc fail\n", info->device_name));
+		return -ENOMEM;
+	}
+	reset_rbufs(info);
+	return 0;
+}
+
+static void free_dma_bufs(struct slgt_info *info)
+{
+	if (info->bufs) {
+		free_bufs(info, info->rbufs, info->rbuf_count);
+		free_bufs(info, info->tbufs, info->tbuf_count);
+		free_desc(info);
+	}
+	free_tmp_rbuf(info);
+}
+
+static int claim_resources(struct slgt_info *info)
+{
+	if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) {
+		DBGERR(("%s reg addr conflict, addr=%08X\n",
+			info->device_name, info->phys_reg_addr));
+		info->init_error = DiagStatus_AddressConflict;
+		goto errout;
+	}
+	else
+		info->reg_addr_requested = true;
+
+	info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE);
+	if (!info->reg_addr) {
+		DBGERR(("%s cant map device registers, addr=%08X\n",
+			info->device_name, info->phys_reg_addr));
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	return 0;
+
+errout:
+	release_resources(info);
+	return -ENODEV;
+}
+
+static void release_resources(struct slgt_info *info)
+{
+	if (info->irq_requested) {
+		free_irq(info->irq_level, info);
+		info->irq_requested = false;
+	}
+
+	if (info->reg_addr_requested) {
+		release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
+		info->reg_addr_requested = false;
+	}
+
+	if (info->reg_addr) {
+		iounmap(info->reg_addr);
+		info->reg_addr = NULL;
+	}
+}
+
+/* Add the specified device instance data structure to the
+ * global linked list of devices and increment the device count.
+ */
+static void add_device(struct slgt_info *info)
+{
+	char *devstr;
+
+	info->next_device = NULL;
+	info->line = slgt_device_count;
+	sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line);
+
+	if (info->line < MAX_DEVICES) {
+		if (maxframe[info->line])
+			info->max_frame_size = maxframe[info->line];
+	}
+
+	slgt_device_count++;
+
+	if (!slgt_device_list)
+		slgt_device_list = info;
+	else {
+		struct slgt_info *current_dev = slgt_device_list;
+		while(current_dev->next_device)
+			current_dev = current_dev->next_device;
+		current_dev->next_device = info;
+	}
+
+	if (info->max_frame_size < 4096)
+		info->max_frame_size = 4096;
+	else if (info->max_frame_size > 65535)
+		info->max_frame_size = 65535;
+
+	switch(info->pdev->device) {
+	case SYNCLINK_GT_DEVICE_ID:
+		devstr = "GT";
+		break;
+	case SYNCLINK_GT2_DEVICE_ID:
+		devstr = "GT2";
+		break;
+	case SYNCLINK_GT4_DEVICE_ID:
+		devstr = "GT4";
+		break;
+	case SYNCLINK_AC_DEVICE_ID:
+		devstr = "AC";
+		info->params.mode = MGSL_MODE_ASYNC;
+		break;
+	default:
+		devstr = "(unknown model)";
+	}
+	printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n",
+		devstr, info->device_name, info->phys_reg_addr,
+		info->irq_level, info->max_frame_size);
+
+#if SYNCLINK_GENERIC_HDLC
+	hdlcdev_init(info);
+#endif
+}
+
+static const struct tty_port_operations slgt_port_ops = {
+	.carrier_raised = carrier_raised,
+	.dtr_rts = dtr_rts,
+};
+
+/*
+ *  allocate device instance structure, return NULL on failure
+ */
+static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
+{
+	struct slgt_info *info;
+
+	info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL);
+
+	if (!info) {
+		DBGERR(("%s device alloc failed adapter=%d port=%d\n",
+			driver_name, adapter_num, port_num));
+	} else {
+		tty_port_init(&info->port);
+		info->port.ops = &slgt_port_ops;
+		info->magic = MGSL_MAGIC;
+		INIT_WORK(&info->task, bh_handler);
+		info->max_frame_size = 4096;
+		info->base_clock = 14745600;
+		info->rbuf_fill_level = DMABUFSIZE;
+		info->port.close_delay = 5*HZ/10;
+		info->port.closing_wait = 30*HZ;
+		init_waitqueue_head(&info->status_event_wait_q);
+		init_waitqueue_head(&info->event_wait_q);
+		spin_lock_init(&info->netlock);
+		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+		info->idle_mode = HDLC_TXIDLE_FLAGS;
+		info->adapter_num = adapter_num;
+		info->port_num = port_num;
+
+		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
+		setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info);
+
+		/* Copy configuration info to device instance data */
+		info->pdev = pdev;
+		info->irq_level = pdev->irq;
+		info->phys_reg_addr = pci_resource_start(pdev,0);
+
+		info->bus_type = MGSL_BUS_TYPE_PCI;
+		info->irq_flags = IRQF_SHARED;
+
+		info->init_error = -1; /* assume error, set to 0 on successful init */
+	}
+
+	return info;
+}
+
+static void device_init(int adapter_num, struct pci_dev *pdev)
+{
+	struct slgt_info *port_array[SLGT_MAX_PORTS];
+	int i;
+	int port_count = 1;
+
+	if (pdev->device == SYNCLINK_GT2_DEVICE_ID)
+		port_count = 2;
+	else if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
+		port_count = 4;
+
+	/* allocate device instances for all ports */
+	for (i=0; i < port_count; ++i) {
+		port_array[i] = alloc_dev(adapter_num, i, pdev);
+		if (port_array[i] == NULL) {
+			for (--i; i >= 0; --i)
+				kfree(port_array[i]);
+			return;
+		}
+	}
+
+	/* give copy of port_array to all ports and add to device list  */
+	for (i=0; i < port_count; ++i) {
+		memcpy(port_array[i]->port_array, port_array, sizeof(port_array));
+		add_device(port_array[i]);
+		port_array[i]->port_count = port_count;
+		spin_lock_init(&port_array[i]->lock);
+	}
+
+	/* Allocate and claim adapter resources */
+	if (!claim_resources(port_array[0])) {
+
+		alloc_dma_bufs(port_array[0]);
+
+		/* copy resource information from first port to others */
+		for (i = 1; i < port_count; ++i) {
+			port_array[i]->irq_level = port_array[0]->irq_level;
+			port_array[i]->reg_addr  = port_array[0]->reg_addr;
+			alloc_dma_bufs(port_array[i]);
+		}
+
+		if (request_irq(port_array[0]->irq_level,
+					slgt_interrupt,
+					port_array[0]->irq_flags,
+					port_array[0]->device_name,
+					port_array[0]) < 0) {
+			DBGERR(("%s request_irq failed IRQ=%d\n",
+				port_array[0]->device_name,
+				port_array[0]->irq_level));
+		} else {
+			port_array[0]->irq_requested = true;
+			adapter_test(port_array[0]);
+			for (i=1 ; i < port_count ; i++) {
+				port_array[i]->init_error = port_array[0]->init_error;
+				port_array[i]->gpio_present = port_array[0]->gpio_present;
+			}
+		}
+	}
+
+	for (i=0; i < port_count; ++i)
+		tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
+}
+
+static int __devinit init_one(struct pci_dev *dev,
+			      const struct pci_device_id *ent)
+{
+	if (pci_enable_device(dev)) {
+		printk("error enabling pci device %p\n", dev);
+		return -EIO;
+	}
+	pci_set_master(dev);
+	device_init(slgt_device_count, dev);
+	return 0;
+}
+
+static void __devexit remove_one(struct pci_dev *dev)
+{
+}
+
+static const struct tty_operations ops = {
+	.open = open,
+	.close = close,
+	.write = write,
+	.put_char = put_char,
+	.flush_chars = flush_chars,
+	.write_room = write_room,
+	.chars_in_buffer = chars_in_buffer,
+	.flush_buffer = flush_buffer,
+	.ioctl = ioctl,
+	.compat_ioctl = slgt_compat_ioctl,
+	.throttle = throttle,
+	.unthrottle = unthrottle,
+	.send_xchar = send_xchar,
+	.break_ctl = set_break,
+	.wait_until_sent = wait_until_sent,
+	.set_termios = set_termios,
+	.stop = tx_hold,
+	.start = tx_release,
+	.hangup = hangup,
+	.tiocmget = tiocmget,
+	.tiocmset = tiocmset,
+	.get_icount = get_icount,
+	.proc_fops = &synclink_gt_proc_fops,
+};
+
+static void slgt_cleanup(void)
+{
+	int rc;
+	struct slgt_info *info;
+	struct slgt_info *tmp;
+
+	printk(KERN_INFO "unload %s\n", driver_name);
+
+	if (serial_driver) {
+		for (info=slgt_device_list ; info != NULL ; info=info->next_device)
+			tty_unregister_device(serial_driver, info->line);
+		if ((rc = tty_unregister_driver(serial_driver)))
+			DBGERR(("tty_unregister_driver error=%d\n", rc));
+		put_tty_driver(serial_driver);
+	}
+
+	/* reset devices */
+	info = slgt_device_list;
+	while(info) {
+		reset_port(info);
+		info = info->next_device;
+	}
+
+	/* release devices */
+	info = slgt_device_list;
+	while(info) {
+#if SYNCLINK_GENERIC_HDLC
+		hdlcdev_exit(info);
+#endif
+		free_dma_bufs(info);
+		free_tmp_rbuf(info);
+		if (info->port_num == 0)
+			release_resources(info);
+		tmp = info;
+		info = info->next_device;
+		kfree(tmp);
+	}
+
+	if (pci_registered)
+		pci_unregister_driver(&pci_driver);
+}
+
+/*
+ *  Driver initialization entry point.
+ */
+static int __init slgt_init(void)
+{
+	int rc;
+
+	printk(KERN_INFO "%s\n", driver_name);
+
+	serial_driver = alloc_tty_driver(MAX_DEVICES);
+	if (!serial_driver) {
+		printk("%s can't allocate tty driver\n", driver_name);
+		return -ENOMEM;
+	}
+
+	/* Initialize the tty_driver structure */
+
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = tty_driver_name;
+	serial_driver->name = tty_dev_prefix;
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver->init_termios.c_ispeed = 9600;
+	serial_driver->init_termios.c_ospeed = 9600;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+	tty_set_operations(serial_driver, &ops);
+	if ((rc = tty_register_driver(serial_driver)) < 0) {
+		DBGERR(("%s can't register serial driver\n", driver_name));
+		put_tty_driver(serial_driver);
+		serial_driver = NULL;
+		goto error;
+	}
+
+	printk(KERN_INFO "%s, tty major#%d\n",
+	       driver_name, serial_driver->major);
+
+	slgt_device_count = 0;
+	if ((rc = pci_register_driver(&pci_driver)) < 0) {
+		printk("%s pci_register_driver error=%d\n", driver_name, rc);
+		goto error;
+	}
+	pci_registered = true;
+
+	if (!slgt_device_list)
+		printk("%s no devices found\n",driver_name);
+
+	return 0;
+
+error:
+	slgt_cleanup();
+	return rc;
+}
+
+static void __exit slgt_exit(void)
+{
+	slgt_cleanup();
+}
+
+module_init(slgt_init);
+module_exit(slgt_exit);
+
+/*
+ * register access routines
+ */
+
+#define CALC_REGADDR() \
+	unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
+	if (addr >= 0x80) \
+		reg_addr += (info->port_num) * 32; \
+	else if (addr >= 0x40)	\
+		reg_addr += (info->port_num) * 16;
+
+static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
+{
+	CALC_REGADDR();
+	return readb((void __iomem *)reg_addr);
+}
+
+static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value)
+{
+	CALC_REGADDR();
+	writeb(value, (void __iomem *)reg_addr);
+}
+
+static __u16 rd_reg16(struct slgt_info *info, unsigned int addr)
+{
+	CALC_REGADDR();
+	return readw((void __iomem *)reg_addr);
+}
+
+static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value)
+{
+	CALC_REGADDR();
+	writew(value, (void __iomem *)reg_addr);
+}
+
+static __u32 rd_reg32(struct slgt_info *info, unsigned int addr)
+{
+	CALC_REGADDR();
+	return readl((void __iomem *)reg_addr);
+}
+
+static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value)
+{
+	CALC_REGADDR();
+	writel(value, (void __iomem *)reg_addr);
+}
+
+static void rdma_reset(struct slgt_info *info)
+{
+	unsigned int i;
+
+	/* set reset bit */
+	wr_reg32(info, RDCSR, BIT1);
+
+	/* wait for enable bit cleared */
+	for(i=0 ; i < 1000 ; i++)
+		if (!(rd_reg32(info, RDCSR) & BIT0))
+			break;
+}
+
+static void tdma_reset(struct slgt_info *info)
+{
+	unsigned int i;
+
+	/* set reset bit */
+	wr_reg32(info, TDCSR, BIT1);
+
+	/* wait for enable bit cleared */
+	for(i=0 ; i < 1000 ; i++)
+		if (!(rd_reg32(info, TDCSR) & BIT0))
+			break;
+}
+
+/*
+ * enable internal loopback
+ * TxCLK and RxCLK are generated from BRG
+ * and TxD is looped back to RxD internally.
+ */
+static void enable_loopback(struct slgt_info *info)
+{
+	/* SCR (serial control) BIT2=looopback enable */
+	wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2));
+
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		/* CCR (clock control)
+		 * 07..05  tx clock source (010 = BRG)
+		 * 04..02  rx clock source (010 = BRG)
+		 * 01      auxclk enable   (0 = disable)
+		 * 00      BRG enable      (1 = enable)
+		 *
+		 * 0100 1001
+		 */
+		wr_reg8(info, CCR, 0x49);
+
+		/* set speed if available, otherwise use default */
+		if (info->params.clock_speed)
+			set_rate(info, info->params.clock_speed);
+		else
+			set_rate(info, 3686400);
+	}
+}
+
+/*
+ *  set baud rate generator to specified rate
+ */
+static void set_rate(struct slgt_info *info, u32 rate)
+{
+	unsigned int div;
+	unsigned int osc = info->base_clock;
+
+	/* div = osc/rate - 1
+	 *
+	 * Round div up if osc/rate is not integer to
+	 * force to next slowest rate.
+	 */
+
+	if (rate) {
+		div = osc/rate;
+		if (!(osc % rate) && div)
+			div--;
+		wr_reg16(info, BDR, (unsigned short)div);
+	}
+}
+
+static void rx_stop(struct slgt_info *info)
+{
+	unsigned short val;
+
+	/* disable and reset receiver */
+	val = rd_reg16(info, RCR) & ~BIT1;          /* clear enable bit */
+	wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
+	wr_reg16(info, RCR, val);                  /* clear reset bit */
+
+	slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE);
+
+	/* clear pending rx interrupts */
+	wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER);
+
+	rdma_reset(info);
+
+	info->rx_enabled = false;
+	info->rx_restart = false;
+}
+
+static void rx_start(struct slgt_info *info)
+{
+	unsigned short val;
+
+	slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA);
+
+	/* clear pending rx overrun IRQ */
+	wr_reg16(info, SSR, IRQ_RXOVER);
+
+	/* reset and disable receiver */
+	val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
+	wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
+	wr_reg16(info, RCR, val);                  /* clear reset bit */
+
+	rdma_reset(info);
+	reset_rbufs(info);
+
+	if (info->rx_pio) {
+		/* rx request when rx FIFO not empty */
+		wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14));
+		slgt_irq_on(info, IRQ_RXDATA);
+		if (info->params.mode == MGSL_MODE_ASYNC) {
+			/* enable saving of rx status */
+			wr_reg32(info, RDCSR, BIT6);
+		}
+	} else {
+		/* rx request when rx FIFO half full */
+		wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14));
+		/* set 1st descriptor address */
+		wr_reg32(info, RDDAR, info->rbufs[0].pdesc);
+
+		if (info->params.mode != MGSL_MODE_ASYNC) {
+			/* enable rx DMA and DMA interrupt */
+			wr_reg32(info, RDCSR, (BIT2 + BIT0));
+		} else {
+			/* enable saving of rx status, rx DMA and DMA interrupt */
+			wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0));
+		}
+	}
+
+	slgt_irq_on(info, IRQ_RXOVER);
+
+	/* enable receiver */
+	wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
+
+	info->rx_restart = false;
+	info->rx_enabled = true;
+}
+
+static void tx_start(struct slgt_info *info)
+{
+	if (!info->tx_enabled) {
+		wr_reg16(info, TCR,
+			 (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
+		info->tx_enabled = true;
+	}
+
+	if (desc_count(info->tbufs[info->tbuf_start])) {
+		info->drop_rts_on_tx_done = false;
+
+		if (info->params.mode != MGSL_MODE_ASYNC) {
+			if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
+				get_signals(info);
+				if (!(info->signals & SerialSignal_RTS)) {
+					info->signals |= SerialSignal_RTS;
+					set_signals(info);
+					info->drop_rts_on_tx_done = true;
+				}
+			}
+
+			slgt_irq_off(info, IRQ_TXDATA);
+			slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE);
+			/* clear tx idle and underrun status bits */
+			wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
+		} else {
+			slgt_irq_off(info, IRQ_TXDATA);
+			slgt_irq_on(info, IRQ_TXIDLE);
+			/* clear tx idle status bit */
+			wr_reg16(info, SSR, IRQ_TXIDLE);
+		}
+		/* set 1st descriptor address and start DMA */
+		wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
+		wr_reg32(info, TDCSR, BIT2 + BIT0);
+		info->tx_active = true;
+	}
+}
+
+static void tx_stop(struct slgt_info *info)
+{
+	unsigned short val;
+
+	del_timer(&info->tx_timer);
+
+	tdma_reset(info);
+
+	/* reset and disable transmitter */
+	val = rd_reg16(info, TCR) & ~BIT1;          /* clear enable bit */
+	wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
+
+	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
+
+	/* clear tx idle and underrun status bit */
+	wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
+
+	reset_tbufs(info);
+
+	info->tx_enabled = false;
+	info->tx_active = false;
+}
+
+static void reset_port(struct slgt_info *info)
+{
+	if (!info->reg_addr)
+		return;
+
+	tx_stop(info);
+	rx_stop(info);
+
+	info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+	set_signals(info);
+
+	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+}
+
+static void reset_adapter(struct slgt_info *info)
+{
+	int i;
+	for (i=0; i < info->port_count; ++i) {
+		if (info->port_array[i])
+			reset_port(info->port_array[i]);
+	}
+}
+
+static void async_mode(struct slgt_info *info)
+{
+  	unsigned short val;
+
+	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+	tx_stop(info);
+	rx_stop(info);
+
+	/* TCR (tx control)
+	 *
+	 * 15..13  mode, 010=async
+	 * 12..10  encoding, 000=NRZ
+	 * 09      parity enable
+	 * 08      1=odd parity, 0=even parity
+	 * 07      1=RTS driver control
+	 * 06      1=break enable
+	 * 05..04  character length
+	 *         00=5 bits
+	 *         01=6 bits
+	 *         10=7 bits
+	 *         11=8 bits
+	 * 03      0=1 stop bit, 1=2 stop bits
+	 * 02      reset
+	 * 01      enable
+	 * 00      auto-CTS enable
+	 */
+	val = 0x4000;
+
+	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+		val |= BIT7;
+
+	if (info->params.parity != ASYNC_PARITY_NONE) {
+		val |= BIT9;
+		if (info->params.parity == ASYNC_PARITY_ODD)
+			val |= BIT8;
+	}
+
+	switch (info->params.data_bits)
+	{
+	case 6: val |= BIT4; break;
+	case 7: val |= BIT5; break;
+	case 8: val |= BIT5 + BIT4; break;
+	}
+
+	if (info->params.stop_bits != 1)
+		val |= BIT3;
+
+	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+		val |= BIT0;
+
+	wr_reg16(info, TCR, val);
+
+	/* RCR (rx control)
+	 *
+	 * 15..13  mode, 010=async
+	 * 12..10  encoding, 000=NRZ
+	 * 09      parity enable
+	 * 08      1=odd parity, 0=even parity
+	 * 07..06  reserved, must be 0
+	 * 05..04  character length
+	 *         00=5 bits
+	 *         01=6 bits
+	 *         10=7 bits
+	 *         11=8 bits
+	 * 03      reserved, must be zero
+	 * 02      reset
+	 * 01      enable
+	 * 00      auto-DCD enable
+	 */
+	val = 0x4000;
+
+	if (info->params.parity != ASYNC_PARITY_NONE) {
+		val |= BIT9;
+		if (info->params.parity == ASYNC_PARITY_ODD)
+			val |= BIT8;
+	}
+
+	switch (info->params.data_bits)
+	{
+	case 6: val |= BIT4; break;
+	case 7: val |= BIT5; break;
+	case 8: val |= BIT5 + BIT4; break;
+	}
+
+	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+		val |= BIT0;
+
+	wr_reg16(info, RCR, val);
+
+	/* CCR (clock control)
+	 *
+	 * 07..05  011 = tx clock source is BRG/16
+	 * 04..02  010 = rx clock source is BRG
+	 * 01      0 = auxclk disabled
+	 * 00      1 = BRG enabled
+	 *
+	 * 0110 1001
+	 */
+	wr_reg8(info, CCR, 0x69);
+
+	msc_set_vcr(info);
+
+	/* SCR (serial control)
+	 *
+	 * 15  1=tx req on FIFO half empty
+	 * 14  1=rx req on FIFO half full
+	 * 13  tx data  IRQ enable
+	 * 12  tx idle  IRQ enable
+	 * 11  rx break on IRQ enable
+	 * 10  rx data  IRQ enable
+	 * 09  rx break off IRQ enable
+	 * 08  overrun  IRQ enable
+	 * 07  DSR      IRQ enable
+	 * 06  CTS      IRQ enable
+	 * 05  DCD      IRQ enable
+	 * 04  RI       IRQ enable
+	 * 03  0=16x sampling, 1=8x sampling
+	 * 02  1=txd->rxd internal loopback enable
+	 * 01  reserved, must be zero
+	 * 00  1=master IRQ enable
+	 */
+	val = BIT15 + BIT14 + BIT0;
+	/* JCR[8] : 1 = x8 async mode feature available */
+	if ((rd_reg32(info, JCR) & BIT8) && info->params.data_rate &&
+	    ((info->base_clock < (info->params.data_rate * 16)) ||
+	     (info->base_clock % (info->params.data_rate * 16)))) {
+		/* use 8x sampling */
+		val |= BIT3;
+		set_rate(info, info->params.data_rate * 8);
+	} else {
+		/* use 16x sampling */
+		set_rate(info, info->params.data_rate * 16);
+	}
+	wr_reg16(info, SCR, val);
+
+	slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER);
+
+	if (info->params.loopback)
+		enable_loopback(info);
+}
+
+static void sync_mode(struct slgt_info *info)
+{
+	unsigned short val;
+
+	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
+	tx_stop(info);
+	rx_stop(info);
+
+	/* TCR (tx control)
+	 *
+	 * 15..13  mode
+	 *         000=HDLC/SDLC
+	 *         001=raw bit synchronous
+	 *         010=asynchronous/isochronous
+	 *         011=monosync byte synchronous
+	 *         100=bisync byte synchronous
+	 *         101=xsync byte synchronous
+	 * 12..10  encoding
+	 * 09      CRC enable
+	 * 08      CRC32
+	 * 07      1=RTS driver control
+	 * 06      preamble enable
+	 * 05..04  preamble length
+	 * 03      share open/close flag
+	 * 02      reset
+	 * 01      enable
+	 * 00      auto-CTS enable
+	 */
+	val = BIT2;
+
+	switch(info->params.mode) {
+	case MGSL_MODE_XSYNC:
+		val |= BIT15 + BIT13;
+		break;
+	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+	case MGSL_MODE_BISYNC:   val |= BIT15; break;
+	case MGSL_MODE_RAW:      val |= BIT13; break;
+	}
+	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
+		val |= BIT7;
+
+	switch(info->params.encoding)
+	{
+	case HDLC_ENCODING_NRZB:          val |= BIT10; break;
+	case HDLC_ENCODING_NRZI_MARK:     val |= BIT11; break;
+	case HDLC_ENCODING_NRZI:          val |= BIT11 + BIT10; break;
+	case HDLC_ENCODING_BIPHASE_MARK:  val |= BIT12; break;
+	case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
+	case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
+	}
+
+	switch (info->params.crc_type & HDLC_CRC_MASK)
+	{
+	case HDLC_CRC_16_CCITT: val |= BIT9; break;
+	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
+	}
+
+	if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
+		val |= BIT6;
+
+	switch (info->params.preamble_length)
+	{
+	case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break;
+	case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break;
+	case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break;
+	}
+
+	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+		val |= BIT0;
+
+	wr_reg16(info, TCR, val);
+
+	/* TPR (transmit preamble) */
+
+	switch (info->params.preamble)
+	{
+	case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break;
+	case HDLC_PREAMBLE_PATTERN_ONES:  val = 0xff; break;
+	case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break;
+	case HDLC_PREAMBLE_PATTERN_10:    val = 0x55; break;
+	case HDLC_PREAMBLE_PATTERN_01:    val = 0xaa; break;
+	default:                          val = 0x7e; break;
+	}
+	wr_reg8(info, TPR, (unsigned char)val);
+
+	/* RCR (rx control)
+	 *
+	 * 15..13  mode
+	 *         000=HDLC/SDLC
+	 *         001=raw bit synchronous
+	 *         010=asynchronous/isochronous
+	 *         011=monosync byte synchronous
+	 *         100=bisync byte synchronous
+	 *         101=xsync byte synchronous
+	 * 12..10  encoding
+	 * 09      CRC enable
+	 * 08      CRC32
+	 * 07..03  reserved, must be 0
+	 * 02      reset
+	 * 01      enable
+	 * 00      auto-DCD enable
+	 */
+	val = 0;
+
+	switch(info->params.mode) {
+	case MGSL_MODE_XSYNC:
+		val |= BIT15 + BIT13;
+		break;
+	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+	case MGSL_MODE_BISYNC:   val |= BIT15; break;
+	case MGSL_MODE_RAW:      val |= BIT13; break;
+	}
+
+	switch(info->params.encoding)
+	{
+	case HDLC_ENCODING_NRZB:          val |= BIT10; break;
+	case HDLC_ENCODING_NRZI_MARK:     val |= BIT11; break;
+	case HDLC_ENCODING_NRZI:          val |= BIT11 + BIT10; break;
+	case HDLC_ENCODING_BIPHASE_MARK:  val |= BIT12; break;
+	case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
+	case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
+	}
+
+	switch (info->params.crc_type & HDLC_CRC_MASK)
+	{
+	case HDLC_CRC_16_CCITT: val |= BIT9; break;
+	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
+	}
+
+	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+		val |= BIT0;
+
+	wr_reg16(info, RCR, val);
+
+	/* CCR (clock control)
+	 *
+	 * 07..05  tx clock source
+	 * 04..02  rx clock source
+	 * 01      auxclk enable
+	 * 00      BRG enable
+	 */
+	val = 0;
+
+	if (info->params.flags & HDLC_FLAG_TXC_BRG)
+	{
+		// when RxC source is DPLL, BRG generates 16X DPLL
+		// reference clock, so take TxC from BRG/16 to get
+		// transmit clock at actual data rate
+		if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+			val |= BIT6 + BIT5;	/* 011, txclk = BRG/16 */
+		else
+			val |= BIT6;	/* 010, txclk = BRG */
+	}
+	else if (info->params.flags & HDLC_FLAG_TXC_DPLL)
+		val |= BIT7;	/* 100, txclk = DPLL Input */
+	else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN)
+		val |= BIT5;	/* 001, txclk = RXC Input */
+
+	if (info->params.flags & HDLC_FLAG_RXC_BRG)
+		val |= BIT3;	/* 010, rxclk = BRG */
+	else if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+		val |= BIT4;	/* 100, rxclk = DPLL */
+	else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN)
+		val |= BIT2;	/* 001, rxclk = TXC Input */
+
+	if (info->params.clock_speed)
+		val |= BIT1 + BIT0;
+
+	wr_reg8(info, CCR, (unsigned char)val);
+
+	if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL))
+	{
+		// program DPLL mode
+		switch(info->params.encoding)
+		{
+		case HDLC_ENCODING_BIPHASE_MARK:
+		case HDLC_ENCODING_BIPHASE_SPACE:
+			val = BIT7; break;
+		case HDLC_ENCODING_BIPHASE_LEVEL:
+		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL:
+			val = BIT7 + BIT6; break;
+		default: val = BIT6;	// NRZ encodings
+		}
+		wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val));
+
+		// DPLL requires a 16X reference clock from BRG
+		set_rate(info, info->params.clock_speed * 16);
+	}
+	else
+		set_rate(info, info->params.clock_speed);
+
+	tx_set_idle(info);
+
+	msc_set_vcr(info);
+
+	/* SCR (serial control)
+	 *
+	 * 15  1=tx req on FIFO half empty
+	 * 14  1=rx req on FIFO half full
+	 * 13  tx data  IRQ enable
+	 * 12  tx idle  IRQ enable
+	 * 11  underrun IRQ enable
+	 * 10  rx data  IRQ enable
+	 * 09  rx idle  IRQ enable
+	 * 08  overrun  IRQ enable
+	 * 07  DSR      IRQ enable
+	 * 06  CTS      IRQ enable
+	 * 05  DCD      IRQ enable
+	 * 04  RI       IRQ enable
+	 * 03  reserved, must be zero
+	 * 02  1=txd->rxd internal loopback enable
+	 * 01  reserved, must be zero
+	 * 00  1=master IRQ enable
+	 */
+	wr_reg16(info, SCR, BIT15 + BIT14 + BIT0);
+
+	if (info->params.loopback)
+		enable_loopback(info);
+}
+
+/*
+ *  set transmit idle mode
+ */
+static void tx_set_idle(struct slgt_info *info)
+{
+	unsigned char val;
+	unsigned short tcr;
+
+	/* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits
+	 * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits
+	 */
+	tcr = rd_reg16(info, TCR);
+	if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) {
+		/* disable preamble, set idle size to 16 bits */
+		tcr = (tcr & ~(BIT6 + BIT5)) | BIT4;
+		/* MSB of 16 bit idle specified in tx preamble register (TPR) */
+		wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff));
+	} else if (!(tcr & BIT6)) {
+		/* preamble is disabled, set idle size to 8 bits */
+		tcr &= ~(BIT5 + BIT4);
+	}
+	wr_reg16(info, TCR, tcr);
+
+	if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) {
+		/* LSB of custom tx idle specified in tx idle register */
+		val = (unsigned char)(info->idle_mode & 0xff);
+	} else {
+		/* standard 8 bit idle patterns */
+		switch(info->idle_mode)
+		{
+		case HDLC_TXIDLE_FLAGS:          val = 0x7e; break;
+		case HDLC_TXIDLE_ALT_ZEROS_ONES:
+		case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
+		case HDLC_TXIDLE_ZEROS:
+		case HDLC_TXIDLE_SPACE:          val = 0x00; break;
+		default:                         val = 0xff;
+		}
+	}
+
+	wr_reg8(info, TIR, val);
+}
+
+/*
+ * get state of V24 status (input) signals
+ */
+static void get_signals(struct slgt_info *info)
+{
+	unsigned short status = rd_reg16(info, SSR);
+
+	/* clear all serial signals except DTR and RTS */
+	info->signals &= SerialSignal_DTR + SerialSignal_RTS;
+
+	if (status & BIT3)
+		info->signals |= SerialSignal_DSR;
+	if (status & BIT2)
+		info->signals |= SerialSignal_CTS;
+	if (status & BIT1)
+		info->signals |= SerialSignal_DCD;
+	if (status & BIT0)
+		info->signals |= SerialSignal_RI;
+}
+
+/*
+ * set V.24 Control Register based on current configuration
+ */
+static void msc_set_vcr(struct slgt_info *info)
+{
+	unsigned char val = 0;
+
+	/* VCR (V.24 control)
+	 *
+	 * 07..04  serial IF select
+	 * 03      DTR
+	 * 02      RTS
+	 * 01      LL
+	 * 00      RL
+	 */
+
+	switch(info->if_mode & MGSL_INTERFACE_MASK)
+	{
+	case MGSL_INTERFACE_RS232:
+		val |= BIT5; /* 0010 */
+		break;
+	case MGSL_INTERFACE_V35:
+		val |= BIT7 + BIT6 + BIT5; /* 1110 */
+		break;
+	case MGSL_INTERFACE_RS422:
+		val |= BIT6; /* 0100 */
+		break;
+	}
+
+	if (info->if_mode & MGSL_INTERFACE_MSB_FIRST)
+		val |= BIT4;
+	if (info->signals & SerialSignal_DTR)
+		val |= BIT3;
+	if (info->signals & SerialSignal_RTS)
+		val |= BIT2;
+	if (info->if_mode & MGSL_INTERFACE_LL)
+		val |= BIT1;
+	if (info->if_mode & MGSL_INTERFACE_RL)
+		val |= BIT0;
+	wr_reg8(info, VCR, val);
+}
+
+/*
+ * set state of V24 control (output) signals
+ */
+static void set_signals(struct slgt_info *info)
+{
+	unsigned char val = rd_reg8(info, VCR);
+	if (info->signals & SerialSignal_DTR)
+		val |= BIT3;
+	else
+		val &= ~BIT3;
+	if (info->signals & SerialSignal_RTS)
+		val |= BIT2;
+	else
+		val &= ~BIT2;
+	wr_reg8(info, VCR, val);
+}
+
+/*
+ * free range of receive DMA buffers (i to last)
+ */
+static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last)
+{
+	int done = 0;
+
+	while(!done) {
+		/* reset current buffer for reuse */
+		info->rbufs[i].status = 0;
+		set_desc_count(info->rbufs[i], info->rbuf_fill_level);
+		if (i == last)
+			done = 1;
+		if (++i == info->rbuf_count)
+			i = 0;
+	}
+	info->rbuf_current = i;
+}
+
+/*
+ * mark all receive DMA buffers as free
+ */
+static void reset_rbufs(struct slgt_info *info)
+{
+	free_rbufs(info, 0, info->rbuf_count - 1);
+	info->rbuf_fill_index = 0;
+	info->rbuf_fill_count = 0;
+}
+
+/*
+ * pass receive HDLC frame to upper layer
+ *
+ * return true if frame available, otherwise false
+ */
+static bool rx_get_frame(struct slgt_info *info)
+{
+	unsigned int start, end;
+	unsigned short status;
+	unsigned int framesize = 0;
+	unsigned long flags;
+	struct tty_struct *tty = info->port.tty;
+	unsigned char addr_field = 0xff;
+	unsigned int crc_size = 0;
+
+	switch (info->params.crc_type & HDLC_CRC_MASK) {
+	case HDLC_CRC_16_CCITT: crc_size = 2; break;
+	case HDLC_CRC_32_CCITT: crc_size = 4; break;
+	}
+
+check_again:
+
+	framesize = 0;
+	addr_field = 0xff;
+	start = end = info->rbuf_current;
+
+	for (;;) {
+		if (!desc_complete(info->rbufs[end]))
+			goto cleanup;
+
+		if (framesize == 0 && info->params.addr_filter != 0xff)
+			addr_field = info->rbufs[end].buf[0];
+
+		framesize += desc_count(info->rbufs[end]);
+
+		if (desc_eof(info->rbufs[end]))
+			break;
+
+		if (++end == info->rbuf_count)
+			end = 0;
+
+		if (end == info->rbuf_current) {
+			if (info->rx_enabled){
+				spin_lock_irqsave(&info->lock,flags);
+				rx_start(info);
+				spin_unlock_irqrestore(&info->lock,flags);
+			}
+			goto cleanup;
+		}
+	}
+
+	/* status
+	 *
+	 * 15      buffer complete
+	 * 14..06  reserved
+	 * 05..04  residue
+	 * 02      eof (end of frame)
+	 * 01      CRC error
+	 * 00      abort
+	 */
+	status = desc_status(info->rbufs[end]);
+
+	/* ignore CRC bit if not using CRC (bit is undefined) */
+	if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE)
+		status &= ~BIT1;
+
+	if (framesize == 0 ||
+		 (addr_field != 0xff && addr_field != info->params.addr_filter)) {
+		free_rbufs(info, start, end);
+		goto check_again;
+	}
+
+	if (framesize < (2 + crc_size) || status & BIT0) {
+		info->icount.rxshort++;
+		framesize = 0;
+	} else if (status & BIT1) {
+		info->icount.rxcrc++;
+		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX))
+			framesize = 0;
+	}
+
+#if SYNCLINK_GENERIC_HDLC
+	if (framesize == 0) {
+		info->netdev->stats.rx_errors++;
+		info->netdev->stats.rx_frame_errors++;
+	}
+#endif
+
+	DBGBH(("%s rx frame status=%04X size=%d\n",
+		info->device_name, status, framesize));
+	DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
+
+	if (framesize) {
+		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
+			framesize -= crc_size;
+			crc_size = 0;
+		}
+
+		if (framesize > info->max_frame_size + crc_size)
+			info->icount.rxlong++;
+		else {
+			/* copy dma buffer(s) to contiguous temp buffer */
+			int copy_count = framesize;
+			int i = start;
+			unsigned char *p = info->tmp_rbuf;
+			info->tmp_rbuf_count = framesize;
+
+			info->icount.rxok++;
+
+			while(copy_count) {
+				int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
+				memcpy(p, info->rbufs[i].buf, partial_count);
+				p += partial_count;
+				copy_count -= partial_count;
+				if (++i == info->rbuf_count)
+					i = 0;
+			}
+
+			if (info->params.crc_type & HDLC_CRC_RETURN_EX) {
+				*p = (status & BIT1) ? RX_CRC_ERROR : RX_OK;
+				framesize++;
+			}
+
+#if SYNCLINK_GENERIC_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->tmp_rbuf, framesize);
+			else
+#endif
+				ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize);
+		}
+	}
+	free_rbufs(info, start, end);
+	return true;
+
+cleanup:
+	return false;
+}
+
+/*
+ * pass receive buffer (RAW synchronous mode) to tty layer
+ * return true if buffer available, otherwise false
+ */
+static bool rx_get_buf(struct slgt_info *info)
+{
+	unsigned int i = info->rbuf_current;
+	unsigned int count;
+
+	if (!desc_complete(info->rbufs[i]))
+		return false;
+	count = desc_count(info->rbufs[i]);
+	switch(info->params.mode) {
+	case MGSL_MODE_MONOSYNC:
+	case MGSL_MODE_BISYNC:
+	case MGSL_MODE_XSYNC:
+		/* ignore residue in byte synchronous modes */
+		if (desc_residue(info->rbufs[i]))
+			count--;
+		break;
+	}
+	DBGDATA(info, info->rbufs[i].buf, count, "rx");
+	DBGINFO(("rx_get_buf size=%d\n", count));
+	if (count)
+		ldisc_receive_buf(info->port.tty, info->rbufs[i].buf,
+				  info->flag_buf, count);
+	free_rbufs(info, i, i);
+	return true;
+}
+
+static void reset_tbufs(struct slgt_info *info)
+{
+	unsigned int i;
+	info->tbuf_current = 0;
+	for (i=0 ; i < info->tbuf_count ; i++) {
+		info->tbufs[i].status = 0;
+		info->tbufs[i].count  = 0;
+	}
+}
+
+/*
+ * return number of free transmit DMA buffers
+ */
+static unsigned int free_tbuf_count(struct slgt_info *info)
+{
+	unsigned int count = 0;
+	unsigned int i = info->tbuf_current;
+
+	do
+	{
+		if (desc_count(info->tbufs[i]))
+			break; /* buffer in use */
+		++count;
+		if (++i == info->tbuf_count)
+			i=0;
+	} while (i != info->tbuf_current);
+
+	/* if tx DMA active, last zero count buffer is in use */
+	if (count && (rd_reg32(info, TDCSR) & BIT0))
+		--count;
+
+	return count;
+}
+
+/*
+ * return number of bytes in unsent transmit DMA buffers
+ * and the serial controller tx FIFO
+ */
+static unsigned int tbuf_bytes(struct slgt_info *info)
+{
+	unsigned int total_count = 0;
+	unsigned int i = info->tbuf_current;
+	unsigned int reg_value;
+	unsigned int count;
+	unsigned int active_buf_count = 0;
+
+	/*
+	 * Add descriptor counts for all tx DMA buffers.
+	 * If count is zero (cleared by DMA controller after read),
+	 * the buffer is complete or is actively being read from.
+	 *
+	 * Record buf_count of last buffer with zero count starting
+	 * from current ring position. buf_count is mirror
+	 * copy of count and is not cleared by serial controller.
+	 * If DMA controller is active, that buffer is actively
+	 * being read so add to total.
+	 */
+	do {
+		count = desc_count(info->tbufs[i]);
+		if (count)
+			total_count += count;
+		else if (!total_count)
+			active_buf_count = info->tbufs[i].buf_count;
+		if (++i == info->tbuf_count)
+			i = 0;
+	} while (i != info->tbuf_current);
+
+	/* read tx DMA status register */
+	reg_value = rd_reg32(info, TDCSR);
+
+	/* if tx DMA active, last zero count buffer is in use */
+	if (reg_value & BIT0)
+		total_count += active_buf_count;
+
+	/* add tx FIFO count = reg_value[15..8] */
+	total_count += (reg_value >> 8) & 0xff;
+
+	/* if transmitter active add one byte for shift register */
+	if (info->tx_active)
+		total_count++;
+
+	return total_count;
+}
+
+/*
+ * load data into transmit DMA buffer ring and start transmitter if needed
+ * return true if data accepted, otherwise false (buffers full)
+ */
+static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size)
+{
+	unsigned short count;
+	unsigned int i;
+	struct slgt_desc *d;
+
+	/* check required buffer space */
+	if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info))
+		return false;
+
+	DBGDATA(info, buf, size, "tx");
+
+	/*
+	 * copy data to one or more DMA buffers in circular ring
+	 * tbuf_start   = first buffer for this data
+	 * tbuf_current = next free buffer
+	 *
+	 * Copy all data before making data visible to DMA controller by
+	 * setting descriptor count of the first buffer.
+	 * This prevents an active DMA controller from reading the first DMA
+	 * buffers of a frame and stopping before the final buffers are filled.
+	 */
+
+	info->tbuf_start = i = info->tbuf_current;
+
+	while (size) {
+		d = &info->tbufs[i];
+
+		count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
+		memcpy(d->buf, buf, count);
+
+		size -= count;
+		buf  += count;
+
+		/*
+		 * set EOF bit for last buffer of HDLC frame or
+		 * for every buffer in raw mode
+		 */
+		if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
+		    info->params.mode == MGSL_MODE_RAW)
+			set_desc_eof(*d, 1);
+		else
+			set_desc_eof(*d, 0);
+
+		/* set descriptor count for all but first buffer */
+		if (i != info->tbuf_start)
+			set_desc_count(*d, count);
+		d->buf_count = count;
+
+		if (++i == info->tbuf_count)
+			i = 0;
+	}
+
+	info->tbuf_current = i;
+
+	/* set first buffer count to make new data visible to DMA controller */
+	d = &info->tbufs[info->tbuf_start];
+	set_desc_count(*d, d->buf_count);
+
+	/* start transmitter if needed and update transmit timeout */
+	if (!info->tx_active)
+		tx_start(info);
+	update_tx_timer(info);
+
+	return true;
+}
+
+static int register_test(struct slgt_info *info)
+{
+	static unsigned short patterns[] =
+		{0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696};
+	static unsigned int count = ARRAY_SIZE(patterns);
+	unsigned int i;
+	int rc = 0;
+
+	for (i=0 ; i < count ; i++) {
+		wr_reg16(info, TIR, patterns[i]);
+		wr_reg16(info, BDR, patterns[(i+1)%count]);
+		if ((rd_reg16(info, TIR) != patterns[i]) ||
+		    (rd_reg16(info, BDR) != patterns[(i+1)%count])) {
+			rc = -ENODEV;
+			break;
+		}
+	}
+	info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0;
+	info->init_error = rc ? 0 : DiagStatus_AddressFailure;
+	return rc;
+}
+
+static int irq_test(struct slgt_info *info)
+{
+	unsigned long timeout;
+	unsigned long flags;
+	struct tty_struct *oldtty = info->port.tty;
+	u32 speed = info->params.data_rate;
+
+	info->params.data_rate = 921600;
+	info->port.tty = NULL;
+
+	spin_lock_irqsave(&info->lock, flags);
+	async_mode(info);
+	slgt_irq_on(info, IRQ_TXIDLE);
+
+	/* enable transmitter */
+	wr_reg16(info, TCR,
+		(unsigned short)(rd_reg16(info, TCR) | BIT1));
+
+	/* write one byte and wait for tx idle */
+	wr_reg16(info, TDR, 0);
+
+	/* assume failure */
+	info->init_error = DiagStatus_IrqFailure;
+	info->irq_occurred = false;
+
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	timeout=100;
+	while(timeout-- && !info->irq_occurred)
+		msleep_interruptible(10);
+
+	spin_lock_irqsave(&info->lock,flags);
+	reset_port(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	info->params.data_rate = speed;
+	info->port.tty = oldtty;
+
+	info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure;
+	return info->irq_occurred ? 0 : -ENODEV;
+}
+
+static int loopback_test_rx(struct slgt_info *info)
+{
+	unsigned char *src, *dest;
+	int count;
+
+	if (desc_complete(info->rbufs[0])) {
+		count = desc_count(info->rbufs[0]);
+		src   = info->rbufs[0].buf;
+		dest  = info->tmp_rbuf;
+
+		for( ; count ; count-=2, src+=2) {
+			/* src=data byte (src+1)=status byte */
+			if (!(*(src+1) & (BIT9 + BIT8))) {
+				*dest = *src;
+				dest++;
+				info->tmp_rbuf_count++;
+			}
+		}
+		DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx");
+		return 1;
+	}
+	return 0;
+}
+
+static int loopback_test(struct slgt_info *info)
+{
+#define TESTFRAMESIZE 20
+
+	unsigned long timeout;
+	u16 count = TESTFRAMESIZE;
+	unsigned char buf[TESTFRAMESIZE];
+	int rc = -ENODEV;
+	unsigned long flags;
+
+	struct tty_struct *oldtty = info->port.tty;
+	MGSL_PARAMS params;
+
+	memcpy(&params, &info->params, sizeof(params));
+
+	info->params.mode = MGSL_MODE_ASYNC;
+	info->params.data_rate = 921600;
+	info->params.loopback = 1;
+	info->port.tty = NULL;
+
+	/* build and send transmit frame */
+	for (count = 0; count < TESTFRAMESIZE; ++count)
+		buf[count] = (unsigned char)count;
+
+	info->tmp_rbuf_count = 0;
+	memset(info->tmp_rbuf, 0, TESTFRAMESIZE);
+
+	/* program hardware for HDLC and enabled receiver */
+	spin_lock_irqsave(&info->lock,flags);
+	async_mode(info);
+	rx_start(info);
+	tx_load(info, buf, count);
+	spin_unlock_irqrestore(&info->lock, flags);
+
+	/* wait for receive complete */
+	for (timeout = 100; timeout; --timeout) {
+		msleep_interruptible(10);
+		if (loopback_test_rx(info)) {
+			rc = 0;
+			break;
+		}
+	}
+
+	/* verify received frame length and contents */
+	if (!rc && (info->tmp_rbuf_count != count ||
+		  memcmp(buf, info->tmp_rbuf, count))) {
+		rc = -ENODEV;
+	}
+
+	spin_lock_irqsave(&info->lock,flags);
+	reset_adapter(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	memcpy(&info->params, &params, sizeof(info->params));
+	info->port.tty = oldtty;
+
+	info->init_error = rc ? DiagStatus_DmaFailure : 0;
+	return rc;
+}
+
+static int adapter_test(struct slgt_info *info)
+{
+	DBGINFO(("testing %s\n", info->device_name));
+	if (register_test(info) < 0) {
+		printk("register test failure %s addr=%08X\n",
+			info->device_name, info->phys_reg_addr);
+	} else if (irq_test(info) < 0) {
+		printk("IRQ test failure %s IRQ=%d\n",
+			info->device_name, info->irq_level);
+	} else if (loopback_test(info) < 0) {
+		printk("loopback test failure %s\n", info->device_name);
+	}
+	return info->init_error;
+}
+
+/*
+ * transmit timeout handler
+ */
+static void tx_timeout(unsigned long context)
+{
+	struct slgt_info *info = (struct slgt_info*)context;
+	unsigned long flags;
+
+	DBGINFO(("%s tx_timeout\n", info->device_name));
+	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
+		info->icount.txtimeout++;
+	}
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+#if SYNCLINK_GENERIC_HDLC
+	if (info->netcount)
+		hdlcdev_tx_done(info);
+	else
+#endif
+		bh_transmit(info);
+}
+
+/*
+ * receive buffer polling timer
+ */
+static void rx_timeout(unsigned long context)
+{
+	struct slgt_info *info = (struct slgt_info*)context;
+	unsigned long flags;
+
+	DBGINFO(("%s rx_timeout\n", info->device_name));
+	spin_lock_irqsave(&info->lock, flags);
+	info->pending_bh |= BH_RECEIVE;
+	spin_unlock_irqrestore(&info->lock, flags);
+	bh_handler(&info->task);
+}
+
diff --git a/drivers/tty/synclinkmp.c b/drivers/tty/synclinkmp.c
new file mode 100644
index 0000000..3273436
--- /dev/null
+++ b/drivers/tty/synclinkmp.c
@@ -0,0 +1,5600 @@
+/*
+ * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $
+ *
+ * Device driver for Microgate SyncLink Multiport
+ * high speed multiprotocol serial adapter.
+ *
+ * written by Paul Fulghum for Microgate Corporation
+ * paulkf@microgate.com
+ *
+ * Microgate and SyncLink are trademarks of Microgate Corporation
+ *
+ * Derived from serial.c written by Theodore Ts'o and Linus Torvalds
+ * This code is released under the GNU General Public License (GPL)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
+#if defined(__i386__)
+#  define BREAKPOINT() asm("   int $3");
+#else
+#  define BREAKPOINT() { }
+#endif
+
+#define MAX_DEVICES 12
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/ioctl.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <linux/bitops.h>
+#include <asm/types.h>
+#include <linux/termios.h>
+#include <linux/workqueue.h>
+#include <linux/hdlc.h>
+#include <linux/synclink.h>
+
+#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE))
+#define SYNCLINK_GENERIC_HDLC 1
+#else
+#define SYNCLINK_GENERIC_HDLC 0
+#endif
+
+#define GET_USER(error,value,addr) error = get_user(value,addr)
+#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
+#define PUT_USER(error,value,addr) error = put_user(value,addr)
+#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
+
+#include <asm/uaccess.h>
+
+static MGSL_PARAMS default_params = {
+	MGSL_MODE_HDLC,			/* unsigned long mode */
+	0,				/* unsigned char loopback; */
+	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */
+	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */
+	0,				/* unsigned long clock_speed; */
+	0xff,				/* unsigned char addr_filter; */
+	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */
+	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */
+	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */
+	9600,				/* unsigned long data_rate; */
+	8,				/* unsigned char data_bits; */
+	1,				/* unsigned char stop_bits; */
+	ASYNC_PARITY_NONE		/* unsigned char parity; */
+};
+
+/* size in bytes of DMA data buffers */
+#define SCABUFSIZE 	1024
+#define SCA_MEM_SIZE	0x40000
+#define SCA_BASE_SIZE   512
+#define SCA_REG_SIZE    16
+#define SCA_MAX_PORTS   4
+#define SCAMAXDESC 	128
+
+#define	BUFFERLISTSIZE	4096
+
+/* SCA-I style DMA buffer descriptor */
+typedef struct _SCADESC
+{
+	u16	next;		/* lower l6 bits of next descriptor addr */
+	u16	buf_ptr;	/* lower 16 bits of buffer addr */
+	u8	buf_base;	/* upper 8 bits of buffer addr */
+	u8	pad1;
+	u16	length;		/* length of buffer */
+	u8	status;		/* status of buffer */
+	u8	pad2;
+} SCADESC, *PSCADESC;
+
+typedef struct _SCADESC_EX
+{
+	/* device driver bookkeeping section */
+	char 	*virt_addr;    	/* virtual address of data buffer */
+	u16	phys_entry;	/* lower 16-bits of physical address of this descriptor */
+} SCADESC_EX, *PSCADESC_EX;
+
+/* The queue of BH actions to be performed */
+
+#define BH_RECEIVE  1
+#define BH_TRANSMIT 2
+#define BH_STATUS   4
+
+#define IO_PIN_SHUTDOWN_LIMIT 100
+
+struct	_input_signal_events {
+	int	ri_up;
+	int	ri_down;
+	int	dsr_up;
+	int	dsr_down;
+	int	dcd_up;
+	int	dcd_down;
+	int	cts_up;
+	int	cts_down;
+};
+
+/*
+ * Device instance data structure
+ */
+typedef struct _synclinkmp_info {
+	void *if_ptr;				/* General purpose pointer (used by SPPP) */
+	int			magic;
+	struct tty_port		port;
+	int			line;
+	unsigned short		close_delay;
+	unsigned short		closing_wait;	/* time to wait before closing */
+
+	struct mgsl_icount	icount;
+
+	int			timeout;
+	int			x_char;		/* xon/xoff character */
+	u16			read_status_mask1;  /* break detection (SR1 indications) */
+	u16			read_status_mask2;  /* parity/framing/overun (SR2 indications) */
+	unsigned char 		ignore_status_mask1;  /* break detection (SR1 indications) */
+	unsigned char		ignore_status_mask2;  /* parity/framing/overun (SR2 indications) */
+	unsigned char 		*tx_buf;
+	int			tx_put;
+	int			tx_get;
+	int			tx_count;
+
+	wait_queue_head_t	status_event_wait_q;
+	wait_queue_head_t	event_wait_q;
+	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
+	struct _synclinkmp_info	*next_device;	/* device list link */
+	struct timer_list	status_timer;	/* input signal status check timer */
+
+	spinlock_t lock;		/* spinlock for synchronizing with ISR */
+	struct work_struct task;	 		/* task structure for scheduling bh */
+
+	u32 max_frame_size;			/* as set by device config */
+
+	u32 pending_bh;
+
+	bool bh_running;				/* Protection from multiple */
+	int isr_overflow;
+	bool bh_requested;
+
+	int dcd_chkcount;			/* check counts to prevent */
+	int cts_chkcount;			/* too many IRQs if a signal */
+	int dsr_chkcount;			/* is floating */
+	int ri_chkcount;
+
+	char *buffer_list;			/* virtual address of Rx & Tx buffer lists */
+	unsigned long buffer_list_phys;
+
+	unsigned int rx_buf_count;		/* count of total allocated Rx buffers */
+	SCADESC *rx_buf_list;   		/* list of receive buffer entries */
+	SCADESC_EX rx_buf_list_ex[SCAMAXDESC]; /* list of receive buffer entries */
+	unsigned int current_rx_buf;
+
+	unsigned int tx_buf_count;		/* count of total allocated Tx buffers */
+	SCADESC *tx_buf_list;		/* list of transmit buffer entries */
+	SCADESC_EX tx_buf_list_ex[SCAMAXDESC]; /* list of transmit buffer entries */
+	unsigned int last_tx_buf;
+
+	unsigned char *tmp_rx_buf;
+	unsigned int tmp_rx_buf_count;
+
+	bool rx_enabled;
+	bool rx_overflow;
+
+	bool tx_enabled;
+	bool tx_active;
+	u32 idle_mode;
+
+	unsigned char ie0_value;
+	unsigned char ie1_value;
+	unsigned char ie2_value;
+	unsigned char ctrlreg_value;
+	unsigned char old_signals;
+
+	char device_name[25];			/* device instance name */
+
+	int port_count;
+	int adapter_num;
+	int port_num;
+
+	struct _synclinkmp_info *port_array[SCA_MAX_PORTS];
+
+	unsigned int bus_type;			/* expansion bus type (ISA,EISA,PCI) */
+
+	unsigned int irq_level;			/* interrupt level */
+	unsigned long irq_flags;
+	bool irq_requested;			/* true if IRQ requested */
+
+	MGSL_PARAMS params;			/* communications parameters */
+
+	unsigned char serial_signals;		/* current serial signal states */
+
+	bool irq_occurred;			/* for diagnostics use */
+	unsigned int init_error;		/* Initialization startup error */
+
+	u32 last_mem_alloc;
+	unsigned char* memory_base;		/* shared memory address (PCI only) */
+	u32 phys_memory_base;
+    	int shared_mem_requested;
+
+	unsigned char* sca_base;		/* HD64570 SCA Memory address */
+	u32 phys_sca_base;
+	u32 sca_offset;
+	bool sca_base_requested;
+
+	unsigned char* lcr_base;		/* local config registers (PCI only) */
+	u32 phys_lcr_base;
+	u32 lcr_offset;
+	int lcr_mem_requested;
+
+	unsigned char* statctrl_base;		/* status/control register memory */
+	u32 phys_statctrl_base;
+	u32 statctrl_offset;
+	bool sca_statctrl_requested;
+
+	u32 misc_ctrl_value;
+	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
+	char char_buf[MAX_ASYNC_BUFFER_SIZE];
+	bool drop_rts_on_tx_done;
+
+	struct	_input_signal_events	input_signal_events;
+
+	/* SPPP/Cisco HDLC device parts */
+	int netcount;
+	spinlock_t netlock;
+
+#if SYNCLINK_GENERIC_HDLC
+	struct net_device *netdev;
+#endif
+
+} SLMP_INFO;
+
+#define MGSL_MAGIC 0x5401
+
+/*
+ * define serial signal status change macros
+ */
+#define	MISCSTATUS_DCD_LATCHED	(SerialSignal_DCD<<8)	/* indicates change in DCD */
+#define MISCSTATUS_RI_LATCHED	(SerialSignal_RI<<8)	/* indicates change in RI */
+#define MISCSTATUS_CTS_LATCHED	(SerialSignal_CTS<<8)	/* indicates change in CTS */
+#define MISCSTATUS_DSR_LATCHED	(SerialSignal_DSR<<8)	/* change in DSR */
+
+/* Common Register macros */
+#define LPR	0x00
+#define PABR0	0x02
+#define PABR1	0x03
+#define WCRL	0x04
+#define WCRM	0x05
+#define WCRH	0x06
+#define DPCR	0x08
+#define DMER	0x09
+#define ISR0	0x10
+#define ISR1	0x11
+#define ISR2	0x12
+#define IER0	0x14
+#define IER1	0x15
+#define IER2	0x16
+#define ITCR	0x18
+#define INTVR 	0x1a
+#define IMVR	0x1c
+
+/* MSCI Register macros */
+#define TRB	0x20
+#define TRBL	0x20
+#define TRBH	0x21
+#define SR0	0x22
+#define SR1	0x23
+#define SR2	0x24
+#define SR3	0x25
+#define FST	0x26
+#define IE0	0x28
+#define IE1	0x29
+#define IE2	0x2a
+#define FIE	0x2b
+#define CMD	0x2c
+#define MD0	0x2e
+#define MD1	0x2f
+#define MD2	0x30
+#define CTL	0x31
+#define SA0	0x32
+#define SA1	0x33
+#define IDL	0x34
+#define TMC	0x35
+#define RXS	0x36
+#define TXS	0x37
+#define TRC0	0x38
+#define TRC1	0x39
+#define RRC	0x3a
+#define CST0	0x3c
+#define CST1	0x3d
+
+/* Timer Register Macros */
+#define TCNT	0x60
+#define TCNTL	0x60
+#define TCNTH	0x61
+#define TCONR	0x62
+#define TCONRL	0x62
+#define TCONRH	0x63
+#define TMCS	0x64
+#define TEPR	0x65
+
+/* DMA Controller Register macros */
+#define DARL	0x80
+#define DARH	0x81
+#define DARB	0x82
+#define BAR	0x80
+#define BARL	0x80
+#define BARH	0x81
+#define BARB	0x82
+#define SAR	0x84
+#define SARL	0x84
+#define SARH	0x85
+#define SARB	0x86
+#define CPB	0x86
+#define CDA	0x88
+#define CDAL	0x88
+#define CDAH	0x89
+#define EDA	0x8a
+#define EDAL	0x8a
+#define EDAH	0x8b
+#define BFL	0x8c
+#define BFLL	0x8c
+#define BFLH	0x8d
+#define BCR	0x8e
+#define BCRL	0x8e
+#define BCRH	0x8f
+#define DSR	0x90
+#define DMR	0x91
+#define FCT	0x93
+#define DIR	0x94
+#define DCMD	0x95
+
+/* combine with timer or DMA register address */
+#define TIMER0	0x00
+#define TIMER1	0x08
+#define TIMER2	0x10
+#define TIMER3	0x18
+#define RXDMA 	0x00
+#define TXDMA 	0x20
+
+/* SCA Command Codes */
+#define NOOP		0x00
+#define TXRESET		0x01
+#define TXENABLE	0x02
+#define TXDISABLE	0x03
+#define TXCRCINIT	0x04
+#define TXCRCEXCL	0x05
+#define TXEOM		0x06
+#define TXABORT		0x07
+#define MPON		0x08
+#define TXBUFCLR	0x09
+#define RXRESET		0x11
+#define RXENABLE	0x12
+#define RXDISABLE	0x13
+#define RXCRCINIT	0x14
+#define RXREJECT	0x15
+#define SEARCHMP	0x16
+#define RXCRCEXCL	0x17
+#define RXCRCCALC	0x18
+#define CHRESET		0x21
+#define HUNT		0x31
+
+/* DMA command codes */
+#define SWABORT		0x01
+#define FEICLEAR	0x02
+
+/* IE0 */
+#define TXINTE 		BIT7
+#define RXINTE 		BIT6
+#define TXRDYE 		BIT1
+#define RXRDYE 		BIT0
+
+/* IE1 & SR1 */
+#define UDRN   	BIT7
+#define IDLE   	BIT6
+#define SYNCD  	BIT4
+#define FLGD   	BIT4
+#define CCTS   	BIT3
+#define CDCD   	BIT2
+#define BRKD   	BIT1
+#define ABTD   	BIT1
+#define GAPD   	BIT1
+#define BRKE   	BIT0
+#define IDLD	BIT0
+
+/* IE2 & SR2 */
+#define EOM	BIT7
+#define PMP	BIT6
+#define SHRT	BIT6
+#define PE	BIT5
+#define ABT	BIT5
+#define FRME	BIT4
+#define RBIT	BIT4
+#define OVRN	BIT3
+#define CRCE	BIT2
+
+
+/*
+ * Global linked list of SyncLink devices
+ */
+static SLMP_INFO *synclinkmp_device_list = NULL;
+static int synclinkmp_adapter_count = -1;
+static int synclinkmp_device_count = 0;
+
+/*
+ * Set this param to non-zero to load eax with the
+ * .text section address and breakpoint on module load.
+ * This is useful for use with gdb and add-symbol-file command.
+ */
+static int break_on_load = 0;
+
+/*
+ * Driver major number, defaults to zero to get auto
+ * assigned major number. May be forced as module parameter.
+ */
+static int ttymajor = 0;
+
+/*
+ * Array of user specified options for ISA adapters.
+ */
+static int debug_level = 0;
+static int maxframe[MAX_DEVICES] = {0,};
+
+module_param(break_on_load, bool, 0);
+module_param(ttymajor, int, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+
+static char *driver_name = "SyncLink MultiPort driver";
+static char *driver_version = "$Revision: 4.38 $";
+
+static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
+static void synclinkmp_remove_one(struct pci_dev *dev);
+
+static struct pci_device_id synclinkmp_pci_tbl[] = {
+	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_SCA, PCI_ANY_ID, PCI_ANY_ID, },
+	{ 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
+
+MODULE_LICENSE("GPL");
+
+static struct pci_driver synclinkmp_pci_driver = {
+	.name		= "synclinkmp",
+	.id_table	= synclinkmp_pci_tbl,
+	.probe		= synclinkmp_init_one,
+	.remove		= __devexit_p(synclinkmp_remove_one),
+};
+
+
+static struct tty_driver *serial_driver;
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+
+/* tty callbacks */
+
+static int  open(struct tty_struct *tty, struct file * filp);
+static void close(struct tty_struct *tty, struct file * filp);
+static void hangup(struct tty_struct *tty);
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
+
+static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
+static int put_char(struct tty_struct *tty, unsigned char ch);
+static void send_xchar(struct tty_struct *tty, char ch);
+static void wait_until_sent(struct tty_struct *tty, int timeout);
+static int  write_room(struct tty_struct *tty);
+static void flush_chars(struct tty_struct *tty);
+static void flush_buffer(struct tty_struct *tty);
+static void tx_hold(struct tty_struct *tty);
+static void tx_release(struct tty_struct *tty);
+
+static int  ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
+static int  chars_in_buffer(struct tty_struct *tty);
+static void throttle(struct tty_struct * tty);
+static void unthrottle(struct tty_struct * tty);
+static int set_break(struct tty_struct *tty, int break_state);
+
+#if SYNCLINK_GENERIC_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(SLMP_INFO *info);
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
+static int  hdlcdev_init(SLMP_INFO *info);
+static void hdlcdev_exit(SLMP_INFO *info);
+#endif
+
+/* ioctl handlers */
+
+static int  get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount);
+static int  get_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
+static int  set_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
+static int  get_txidle(SLMP_INFO *info, int __user *idle_mode);
+static int  set_txidle(SLMP_INFO *info, int idle_mode);
+static int  tx_enable(SLMP_INFO *info, int enable);
+static int  tx_abort(SLMP_INFO *info);
+static int  rx_enable(SLMP_INFO *info, int enable);
+static int  modem_input_wait(SLMP_INFO *info,int arg);
+static int  wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
+static int  tiocmget(struct tty_struct *tty);
+static int  tiocmset(struct tty_struct *tty,
+			unsigned int set, unsigned int clear);
+static int  set_break(struct tty_struct *tty, int break_state);
+
+static void add_device(SLMP_INFO *info);
+static void device_init(int adapter_num, struct pci_dev *pdev);
+static int  claim_resources(SLMP_INFO *info);
+static void release_resources(SLMP_INFO *info);
+
+static int  startup(SLMP_INFO *info);
+static int  block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info);
+static int carrier_raised(struct tty_port *port);
+static void shutdown(SLMP_INFO *info);
+static void program_hw(SLMP_INFO *info);
+static void change_params(SLMP_INFO *info);
+
+static bool init_adapter(SLMP_INFO *info);
+static bool register_test(SLMP_INFO *info);
+static bool irq_test(SLMP_INFO *info);
+static bool loopback_test(SLMP_INFO *info);
+static int  adapter_test(SLMP_INFO *info);
+static bool memory_test(SLMP_INFO *info);
+
+static void reset_adapter(SLMP_INFO *info);
+static void reset_port(SLMP_INFO *info);
+static void async_mode(SLMP_INFO *info);
+static void hdlc_mode(SLMP_INFO *info);
+
+static void rx_stop(SLMP_INFO *info);
+static void rx_start(SLMP_INFO *info);
+static void rx_reset_buffers(SLMP_INFO *info);
+static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last);
+static bool rx_get_frame(SLMP_INFO *info);
+
+static void tx_start(SLMP_INFO *info);
+static void tx_stop(SLMP_INFO *info);
+static void tx_load_fifo(SLMP_INFO *info);
+static void tx_set_idle(SLMP_INFO *info);
+static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count);
+
+static void get_signals(SLMP_INFO *info);
+static void set_signals(SLMP_INFO *info);
+static void enable_loopback(SLMP_INFO *info, int enable);
+static void set_rate(SLMP_INFO *info, u32 data_rate);
+
+static int  bh_action(SLMP_INFO *info);
+static void bh_handler(struct work_struct *work);
+static void bh_receive(SLMP_INFO *info);
+static void bh_transmit(SLMP_INFO *info);
+static void bh_status(SLMP_INFO *info);
+static void isr_timer(SLMP_INFO *info);
+static void isr_rxint(SLMP_INFO *info);
+static void isr_rxrdy(SLMP_INFO *info);
+static void isr_txint(SLMP_INFO *info);
+static void isr_txrdy(SLMP_INFO *info);
+static void isr_rxdmaok(SLMP_INFO *info);
+static void isr_rxdmaerror(SLMP_INFO *info);
+static void isr_txdmaok(SLMP_INFO *info);
+static void isr_txdmaerror(SLMP_INFO *info);
+static void isr_io_pin(SLMP_INFO *info, u16 status);
+
+static int  alloc_dma_bufs(SLMP_INFO *info);
+static void free_dma_bufs(SLMP_INFO *info);
+static int  alloc_buf_list(SLMP_INFO *info);
+static int  alloc_frame_bufs(SLMP_INFO *info, SCADESC *list, SCADESC_EX *list_ex,int count);
+static int  alloc_tmp_rx_buf(SLMP_INFO *info);
+static void free_tmp_rx_buf(SLMP_INFO *info);
+
+static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count);
+static void trace_block(SLMP_INFO *info, const char* data, int count, int xmit);
+static void tx_timeout(unsigned long context);
+static void status_timeout(unsigned long context);
+
+static unsigned char read_reg(SLMP_INFO *info, unsigned char addr);
+static void write_reg(SLMP_INFO *info, unsigned char addr, unsigned char val);
+static u16 read_reg16(SLMP_INFO *info, unsigned char addr);
+static void write_reg16(SLMP_INFO *info, unsigned char addr, u16 val);
+static unsigned char read_status_reg(SLMP_INFO * info);
+static void write_control_reg(SLMP_INFO * info);
+
+
+static unsigned char rx_active_fifo_level = 16;	// rx request FIFO activation level in bytes
+static unsigned char tx_active_fifo_level = 16;	// tx request FIFO activation level in bytes
+static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
+
+static u32 misc_ctrl_value = 0x007e4040;
+static u32 lcr1_brdr_value = 0x00800028;
+
+static u32 read_ahead_count = 8;
+
+/* DPCR, DMA Priority Control
+ *
+ * 07..05  Not used, must be 0
+ * 04      BRC, bus release condition: 0=all transfers complete
+ *              1=release after 1 xfer on all channels
+ * 03      CCC, channel change condition: 0=every cycle
+ *              1=after each channel completes all xfers
+ * 02..00  PR<2..0>, priority 100=round robin
+ *
+ * 00000100 = 0x00
+ */
+static unsigned char dma_priority = 0x04;
+
+// Number of bytes that can be written to shared RAM
+// in a single write operation
+static u32 sca_pci_load_interval = 64;
+
+/*
+ * 1st function defined in .text section. Calling this function in
+ * init_module() followed by a breakpoint allows a remote debugger
+ * (gdb) to get the .text address for the add-symbol-file command.
+ * This allows remote debugging of dynamically loadable modules.
+ */
+static void* synclinkmp_get_text_ptr(void);
+static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;}
+
+static inline int sanity_check(SLMP_INFO *info,
+			       char *name, const char *routine)
+{
+#ifdef SANITY_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for synclinkmp_struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null synclinkmp_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, name, routine);
+		return 1;
+	}
+	if (info->magic != MGSL_MAGIC) {
+		printk(badmagic, name, routine);
+		return 1;
+	}
+#else
+	if (!info)
+		return 1;
+#endif
+	return 0;
+}
+
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf  - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+			      const __u8 *data, char *flags, int count)
+{
+	struct tty_ldisc *ld;
+	if (!tty)
+		return;
+	ld = tty_ldisc_ref(tty);
+	if (ld) {
+		if (ld->ops->receive_buf)
+			ld->ops->receive_buf(tty, data, flags, count);
+		tty_ldisc_deref(ld);
+	}
+}
+
+/* tty callbacks */
+
+/* Called when a port is opened.  Init and enable port.
+ */
+static int open(struct tty_struct *tty, struct file *filp)
+{
+	SLMP_INFO *info;
+	int retval, line;
+	unsigned long flags;
+
+	line = tty->index;
+	if ((line < 0) || (line >= synclinkmp_device_count)) {
+		printk("%s(%d): open with invalid line #%d.\n",
+			__FILE__,__LINE__,line);
+		return -ENODEV;
+	}
+
+	info = synclinkmp_device_list;
+	while(info && info->line != line)
+		info = info->next_device;
+	if (sanity_check(info, tty->name, "open"))
+		return -ENODEV;
+	if ( info->init_error ) {
+		printk("%s(%d):%s device is not allocated, init error=%d\n",
+			__FILE__,__LINE__,info->device_name,info->init_error);
+		return -ENODEV;
+	}
+
+	tty->driver_data = info;
+	info->port.tty = tty;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s open(), old ref count = %d\n",
+			 __FILE__,__LINE__,tty->driver->name, info->port.count);
+
+	/* If port is closing, signal caller to try again */
+	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
+		if (info->port.flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->port.close_wait);
+		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+		goto cleanup;
+	}
+
+	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	spin_lock_irqsave(&info->netlock, flags);
+	if (info->netcount) {
+		retval = -EBUSY;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		goto cleanup;
+	}
+	info->port.count++;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	if (info->port.count == 1) {
+		/* 1st open on this device, init hardware */
+		retval = startup(info);
+		if (retval < 0)
+			goto cleanup;
+	}
+
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+		if (debug_level >= DEBUG_LEVEL_INFO)
+			printk("%s(%d):%s block_til_ready() returned %d\n",
+				 __FILE__,__LINE__, info->device_name, retval);
+		goto cleanup;
+	}
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s open() success\n",
+			 __FILE__,__LINE__, info->device_name);
+	retval = 0;
+
+cleanup:
+	if (retval) {
+		if (tty->count == 1)
+			info->port.tty = NULL; /* tty layer will release tty struct */
+		if(info->port.count)
+			info->port.count--;
+	}
+
+	return retval;
+}
+
+/* Called when port is closed. Wait for remaining data to be
+ * sent. Disable port and free resources.
+ */
+static void close(struct tty_struct *tty, struct file *filp)
+{
+	SLMP_INFO * info = tty->driver_data;
+
+	if (sanity_check(info, tty->name, "close"))
+		return;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s close() entry, count=%d\n",
+			 __FILE__,__LINE__, info->device_name, info->port.count);
+
+	if (tty_port_close_start(&info->port, tty, filp) == 0)
+		goto cleanup;
+
+	mutex_lock(&info->port.mutex);
+ 	if (info->port.flags & ASYNC_INITIALIZED)
+ 		wait_until_sent(tty, info->timeout);
+
+	flush_buffer(tty);
+	tty_ldisc_flush(tty);
+	shutdown(info);
+	mutex_unlock(&info->port.mutex);
+
+	tty_port_close_end(&info->port, tty);
+	info->port.tty = NULL;
+cleanup:
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__,
+			tty->driver->name, info->port.count);
+}
+
+/* Called by tty_hangup() when a hangup is signaled.
+ * This is the same as closing all open descriptors for the port.
+ */
+static void hangup(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s hangup()\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (sanity_check(info, tty->name, "hangup"))
+		return;
+
+	mutex_lock(&info->port.mutex);
+	flush_buffer(tty);
+	shutdown(info);
+
+	spin_lock_irqsave(&info->port.lock, flags);
+	info->port.count = 0;
+	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
+	info->port.tty = NULL;
+	spin_unlock_irqrestore(&info->port.lock, flags);
+	mutex_unlock(&info->port.mutex);
+
+	wake_up_interruptible(&info->port.open_wait);
+}
+
+/* Set new termios settings
+ */
+static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
+			tty->driver->name );
+
+	change_params(info);
+
+	/* Handle transition to B0 status */
+	if (old_termios->c_cflag & CBAUD &&
+	    !(tty->termios->c_cflag & CBAUD)) {
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+		spin_lock_irqsave(&info->lock,flags);
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    tty->termios->c_cflag & CBAUD) {
+		info->serial_signals |= SerialSignal_DTR;
+ 		if (!(tty->termios->c_cflag & CRTSCTS) ||
+ 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			info->serial_signals |= SerialSignal_RTS;
+ 		}
+		spin_lock_irqsave(&info->lock,flags);
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+
+	/* Handle turning off CRTSCTS */
+	if (old_termios->c_cflag & CRTSCTS &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		tx_release(tty);
+	}
+}
+
+/* Send a block of data
+ *
+ * Arguments:
+ *
+ * 	tty		pointer to tty information structure
+ * 	buf		pointer to buffer containing send data
+ * 	count		size of send data in bytes
+ *
+ * Return Value:	number of characters written
+ */
+static int write(struct tty_struct *tty,
+		 const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s write() count=%d\n",
+		       __FILE__,__LINE__,info->device_name,count);
+
+	if (sanity_check(info, tty->name, "write"))
+		goto cleanup;
+
+	if (!info->tx_buf)
+		goto cleanup;
+
+	if (info->params.mode == MGSL_MODE_HDLC) {
+		if (count > info->max_frame_size) {
+			ret = -EIO;
+			goto cleanup;
+		}
+		if (info->tx_active)
+			goto cleanup;
+		if (info->tx_count) {
+			/* send accumulated data from send_char() calls */
+			/* as frame and wait before accepting more data. */
+			tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
+			goto start;
+		}
+		ret = info->tx_count = count;
+		tx_load_dma_buffer(info, buf, count);
+		goto start;
+	}
+
+	for (;;) {
+		c = min_t(int, count,
+			min(info->max_frame_size - info->tx_count - 1,
+			    info->max_frame_size - info->tx_put));
+		if (c <= 0)
+			break;
+			
+		memcpy(info->tx_buf + info->tx_put, buf, c);
+
+		spin_lock_irqsave(&info->lock,flags);
+		info->tx_put += c;
+		if (info->tx_put >= info->max_frame_size)
+			info->tx_put -= info->max_frame_size;
+		info->tx_count += c;
+		spin_unlock_irqrestore(&info->lock,flags);
+
+		buf += c;
+		count -= c;
+		ret += c;
+	}
+
+	if (info->params.mode == MGSL_MODE_HDLC) {
+		if (count) {
+			ret = info->tx_count = 0;
+			goto cleanup;
+		}
+		tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
+	}
+start:
+ 	if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
+		spin_lock_irqsave(&info->lock,flags);
+		if (!info->tx_active)
+		 	tx_start(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+ 	}
+
+cleanup:
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk( "%s(%d):%s write() returning=%d\n",
+			__FILE__,__LINE__,info->device_name,ret);
+	return ret;
+}
+
+/* Add a character to the transmit buffer.
+ */
+static int put_char(struct tty_struct *tty, unsigned char ch)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+	int ret = 0;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO ) {
+		printk( "%s(%d):%s put_char(%d)\n",
+			__FILE__,__LINE__,info->device_name,ch);
+	}
+
+	if (sanity_check(info, tty->name, "put_char"))
+		return 0;
+
+	if (!info->tx_buf)
+		return 0;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	if ( (info->params.mode != MGSL_MODE_HDLC) ||
+	     !info->tx_active ) {
+
+		if (info->tx_count < info->max_frame_size - 1) {
+			info->tx_buf[info->tx_put++] = ch;
+			if (info->tx_put >= info->max_frame_size)
+				info->tx_put -= info->max_frame_size;
+			info->tx_count++;
+			ret = 1;
+		}
+	}
+
+	spin_unlock_irqrestore(&info->lock,flags);
+	return ret;
+}
+
+/* Send a high-priority XON/XOFF character
+ */
+static void send_xchar(struct tty_struct *tty, char ch)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s send_xchar(%d)\n",
+			 __FILE__,__LINE__, info->device_name, ch );
+
+	if (sanity_check(info, tty->name, "send_xchar"))
+		return;
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+		spin_lock_irqsave(&info->lock,flags);
+		if (!info->tx_enabled)
+		 	tx_start(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+}
+
+/* Wait until the transmitter is empty.
+ */
+static void wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	SLMP_INFO * info = tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+
+	if (!info )
+		return;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s wait_until_sent() entry\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (sanity_check(info, tty->name, "wait_until_sent"))
+		return;
+
+	if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags))
+		goto exit;
+
+	orig_jiffies = jiffies;
+
+	/* Set check interval to 1/5 of estimated time to
+	 * send a character, and make it at least 1. The check
+	 * interval should also be less than the timeout.
+	 * Note: use tight timings here to satisfy the NIST-PCTS.
+	 */
+
+	if ( info->params.data_rate ) {
+	       	char_time = info->timeout/(32 * 5);
+		if (!char_time)
+			char_time++;
+	} else
+		char_time = 1;
+
+	if (timeout)
+		char_time = min_t(unsigned long, char_time, timeout);
+
+	if ( info->params.mode == MGSL_MODE_HDLC ) {
+		while (info->tx_active) {
+			msleep_interruptible(jiffies_to_msecs(char_time));
+			if (signal_pending(current))
+				break;
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
+				break;
+		}
+	} else {
+		/*
+		 * TODO: determine if there is something similar to USC16C32
+		 * 	 TXSTATUS_ALL_SENT status
+		 */
+		while ( info->tx_active && info->tx_enabled) {
+			msleep_interruptible(jiffies_to_msecs(char_time));
+			if (signal_pending(current))
+				break;
+			if (timeout && time_after(jiffies, orig_jiffies + timeout))
+				break;
+		}
+	}
+
+exit:
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s wait_until_sent() exit\n",
+			 __FILE__,__LINE__, info->device_name );
+}
+
+/* Return the count of free bytes in transmit buffer
+ */
+static int write_room(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	int ret;
+
+	if (sanity_check(info, tty->name, "write_room"))
+		return 0;
+
+	if (info->params.mode == MGSL_MODE_HDLC) {
+		ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
+	} else {
+		ret = info->max_frame_size - info->tx_count - 1;
+		if (ret < 0)
+			ret = 0;
+	}
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s write_room()=%d\n",
+		       __FILE__, __LINE__, info->device_name, ret);
+
+	return ret;
+}
+
+/* enable transmitter and send remaining buffered characters
+ */
+static void flush_chars(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):%s flush_chars() entry tx_count=%d\n",
+			__FILE__,__LINE__,info->device_name,info->tx_count);
+
+	if (sanity_check(info, tty->name, "flush_chars"))
+		return;
+
+	if (info->tx_count <= 0 || tty->stopped || tty->hw_stopped ||
+	    !info->tx_buf)
+		return;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):%s flush_chars() entry, starting transmitter\n",
+			__FILE__,__LINE__,info->device_name );
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	if (!info->tx_active) {
+		if ( (info->params.mode == MGSL_MODE_HDLC) &&
+			info->tx_count ) {
+			/* operating in synchronous (frame oriented) mode */
+			/* copy data from circular tx_buf to */
+			/* transmit DMA buffer. */
+			tx_load_dma_buffer(info,
+				 info->tx_buf,info->tx_count);
+		}
+	 	tx_start(info);
+	}
+
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/* Discard all data in the send buffer
+ */
+static void flush_buffer(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s flush_buffer() entry\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (sanity_check(info, tty->name, "flush_buffer"))
+		return;
+
+	spin_lock_irqsave(&info->lock,flags);
+	info->tx_count = info->tx_put = info->tx_get = 0;
+	del_timer(&info->tx_timer);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	tty_wakeup(tty);
+}
+
+/* throttle (stop) transmitter
+ */
+static void tx_hold(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "tx_hold"))
+		return;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s(%d):%s tx_hold()\n",
+			__FILE__,__LINE__,info->device_name);
+
+	spin_lock_irqsave(&info->lock,flags);
+	if (info->tx_enabled)
+	 	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/* release (start) transmitter
+ */
+static void tx_release(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (sanity_check(info, tty->name, "tx_release"))
+		return;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s(%d):%s tx_release()\n",
+			__FILE__,__LINE__,info->device_name);
+
+	spin_lock_irqsave(&info->lock,flags);
+	if (!info->tx_enabled)
+	 	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/* Service an IOCTL request
+ *
+ * Arguments:
+ *
+ * 	tty	pointer to tty instance data
+ * 	cmd	IOCTL command code
+ * 	arg	command argument/context
+ *
+ * Return Value:	0 if success, otherwise error code
+ */
+static int ioctl(struct tty_struct *tty,
+		 unsigned int cmd, unsigned long arg)
+{
+	SLMP_INFO *info = tty->driver_data;
+	void __user *argp = (void __user *)arg;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__,
+			info->device_name, cmd );
+
+	if (sanity_check(info, tty->name, "ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCMIWAIT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+	case MGSL_IOCGPARAMS:
+		return get_params(info, argp);
+	case MGSL_IOCSPARAMS:
+		return set_params(info, argp);
+	case MGSL_IOCGTXIDLE:
+		return get_txidle(info, argp);
+	case MGSL_IOCSTXIDLE:
+		return set_txidle(info, (int)arg);
+	case MGSL_IOCTXENABLE:
+		return tx_enable(info, (int)arg);
+	case MGSL_IOCRXENABLE:
+		return rx_enable(info, (int)arg);
+	case MGSL_IOCTXABORT:
+		return tx_abort(info);
+	case MGSL_IOCGSTATS:
+		return get_stats(info, argp);
+	case MGSL_IOCWAITEVENT:
+		return wait_mgsl_event(info, argp);
+	case MGSL_IOCLOOPTXDONE:
+		return 0; // TODO: Not supported, need to document
+		/* Wait for modem input (DCD,RI,DSR,CTS) change
+		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
+		 */
+	case TIOCMIWAIT:
+		return modem_input_wait(info,(int)arg);
+		
+		/*
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static int get_icount(struct tty_struct *tty,
+				struct serial_icounter_struct *icount)
+{
+	SLMP_INFO *info = tty->driver_data;
+	struct mgsl_icount cnow;	/* kernel counter temps */
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	cnow = info->icount;
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	icount->cts = cnow.cts;
+	icount->dsr = cnow.dsr;
+	icount->rng = cnow.rng;
+	icount->dcd = cnow.dcd;
+	icount->rx = cnow.rx;
+	icount->tx = cnow.tx;
+	icount->frame = cnow.frame;
+	icount->overrun = cnow.overrun;
+	icount->parity = cnow.parity;
+	icount->brk = cnow.brk;
+	icount->buf_overrun = cnow.buf_overrun;
+
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline void line_info(struct seq_file *m, SLMP_INFO *info)
+{
+	char	stat_buf[30];
+	unsigned long flags;
+
+	seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n"
+		       "\tIRQ=%d MaxFrameSize=%u\n",
+		info->device_name,
+		info->phys_sca_base,
+		info->phys_memory_base,
+		info->phys_statctrl_base,
+		info->phys_lcr_base,
+		info->irq_level,
+		info->max_frame_size );
+
+	/* output current serial signal states */
+	spin_lock_irqsave(&info->lock,flags);
+ 	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (info->serial_signals & SerialSignal_RTS)
+		strcat(stat_buf, "|RTS");
+	if (info->serial_signals & SerialSignal_CTS)
+		strcat(stat_buf, "|CTS");
+	if (info->serial_signals & SerialSignal_DTR)
+		strcat(stat_buf, "|DTR");
+	if (info->serial_signals & SerialSignal_DSR)
+		strcat(stat_buf, "|DSR");
+	if (info->serial_signals & SerialSignal_DCD)
+		strcat(stat_buf, "|CD");
+	if (info->serial_signals & SerialSignal_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->params.mode == MGSL_MODE_HDLC) {
+		seq_printf(m, "\tHDLC txok:%d rxok:%d",
+			      info->icount.txok, info->icount.rxok);
+		if (info->icount.txunder)
+			seq_printf(m, " txunder:%d", info->icount.txunder);
+		if (info->icount.txabort)
+			seq_printf(m, " txabort:%d", info->icount.txabort);
+		if (info->icount.rxshort)
+			seq_printf(m, " rxshort:%d", info->icount.rxshort);
+		if (info->icount.rxlong)
+			seq_printf(m, " rxlong:%d", info->icount.rxlong);
+		if (info->icount.rxover)
+			seq_printf(m, " rxover:%d", info->icount.rxover);
+		if (info->icount.rxcrc)
+			seq_printf(m, " rxlong:%d", info->icount.rxcrc);
+	} else {
+		seq_printf(m, "\tASYNC tx:%d rx:%d",
+			      info->icount.tx, info->icount.rx);
+		if (info->icount.frame)
+			seq_printf(m, " fe:%d", info->icount.frame);
+		if (info->icount.parity)
+			seq_printf(m, " pe:%d", info->icount.parity);
+		if (info->icount.brk)
+			seq_printf(m, " brk:%d", info->icount.brk);
+		if (info->icount.overrun)
+			seq_printf(m, " oe:%d", info->icount.overrun);
+	}
+
+	/* Append serial signal status to end */
+	seq_printf(m, " %s\n", stat_buf+1);
+
+	seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
+	 info->tx_active,info->bh_requested,info->bh_running,
+	 info->pending_bh);
+}
+
+/* Called to print information about devices
+ */
+static int synclinkmp_proc_show(struct seq_file *m, void *v)
+{
+	SLMP_INFO *info;
+
+	seq_printf(m, "synclinkmp driver:%s\n", driver_version);
+
+	info = synclinkmp_device_list;
+	while( info ) {
+		line_info(m, info);
+		info = info->next_device;
+	}
+	return 0;
+}
+
+static int synclinkmp_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, synclinkmp_proc_show, NULL);
+}
+
+static const struct file_operations synclinkmp_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= synclinkmp_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/* Return the count of bytes in transmit buffer
+ */
+static int chars_in_buffer(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+
+	if (sanity_check(info, tty->name, "chars_in_buffer"))
+		return 0;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s chars_in_buffer()=%d\n",
+		       __FILE__, __LINE__, info->device_name, info->tx_count);
+
+	return info->tx_count;
+}
+
+/* Signal remote device to throttle send data (our receive data)
+ */
+static void throttle(struct tty_struct * tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s throttle() entry\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (sanity_check(info, tty->name, "throttle"))
+		return;
+
+	if (I_IXOFF(tty))
+		send_xchar(tty, STOP_CHAR(tty));
+
+ 	if (tty->termios->c_cflag & CRTSCTS) {
+		spin_lock_irqsave(&info->lock,flags);
+		info->serial_signals &= ~SerialSignal_RTS;
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+}
+
+/* Signal remote device to stop throttling send data (our receive data)
+ */
+static void unthrottle(struct tty_struct * tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s unthrottle() entry\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	if (sanity_check(info, tty->name, "unthrottle"))
+		return;
+
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			send_xchar(tty, START_CHAR(tty));
+	}
+
+ 	if (tty->termios->c_cflag & CRTSCTS) {
+		spin_lock_irqsave(&info->lock,flags);
+		info->serial_signals |= SerialSignal_RTS;
+	 	set_signals(info);
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+}
+
+/* set or clear transmit break condition
+ * break_state	-1=set break condition, 0=clear
+ */
+static int set_break(struct tty_struct *tty, int break_state)
+{
+	unsigned char RegValue;
+	SLMP_INFO * info = tty->driver_data;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s set_break(%d)\n",
+			 __FILE__,__LINE__, info->device_name, break_state);
+
+	if (sanity_check(info, tty->name, "set_break"))
+		return -EINVAL;
+
+	spin_lock_irqsave(&info->lock,flags);
+	RegValue = read_reg(info, CTL);
+ 	if (break_state == -1)
+		RegValue |= BIT3;
+	else
+		RegValue &= ~BIT3;
+	write_reg(info, CTL, RegValue);
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+#if SYNCLINK_GENERIC_HDLC
+
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev       pointer to network device structure
+ * encoding  serial encoding setting
+ * parity    FCS setting
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+			  unsigned short parity)
+{
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned char  new_encoding;
+	unsigned short new_crctype;
+
+	/* return error if TTY interface open */
+	if (info->port.count)
+		return -EBUSY;
+
+	switch (encoding)
+	{
+	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
+	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+	default: return -EINVAL;
+	}
+
+	switch (parity)
+	{
+	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
+	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+	default: return -EINVAL;
+	}
+
+	info->params.encoding = new_encoding;
+	info->params.crc_type = new_crctype;
+
+	/* if network interface up, reprogram hardware */
+	if (info->netcount)
+		program_hw(info);
+
+	return 0;
+}
+
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb  socket buffer containing HDLC frame
+ * dev  pointer to network device structure
+ */
+static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
+				      struct net_device *dev)
+{
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+	/* stop sending until this frame completes */
+	netif_stop_queue(dev);
+
+	/* copy data to device buffers */
+	info->tx_count = skb->len;
+	tx_load_dma_buffer(info, skb->data, skb->len);
+
+	/* update network statistics */
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += skb->len;
+
+	/* done with socket buffer, so free it */
+	dev_kfree_skb(skb);
+
+	/* save start time for transmit timeout detection */
+	dev->trans_start = jiffies;
+
+	/* start hardware transmitter if necessary */
+	spin_lock_irqsave(&info->lock,flags);
+	if (!info->tx_active)
+	 	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return NETDEV_TX_OK;
+}
+
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
+{
+	SLMP_INFO *info = dev_to_port(dev);
+	int rc;
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+	/* generic HDLC layer open processing */
+	if ((rc = hdlc_open(dev)))
+		return rc;
+
+	/* arbitrate between network and tty opens */
+	spin_lock_irqsave(&info->netlock, flags);
+	if (info->port.count != 0 || info->netcount != 0) {
+		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return -EBUSY;
+	}
+	info->netcount=1;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	/* claim resources and init adapter */
+	if ((rc = startup(info)) != 0) {
+		spin_lock_irqsave(&info->netlock, flags);
+		info->netcount=0;
+		spin_unlock_irqrestore(&info->netlock, flags);
+		return rc;
+	}
+
+	/* assert DTR and RTS, apply hardware settings */
+	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	program_hw(info);
+
+	/* enable network layer transmit */
+	dev->trans_start = jiffies;
+	netif_start_queue(dev);
+
+	/* inform generic HDLC layer of current DCD status */
+	spin_lock_irqsave(&info->lock, flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock, flags);
+	if (info->serial_signals & SerialSignal_DCD)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
+	return 0;
+}
+
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev  pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
+{
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
+
+	netif_stop_queue(dev);
+
+	/* shutdown adapter and release resources */
+	shutdown(info);
+
+	hdlc_close(dev);
+
+	spin_lock_irqsave(&info->netlock, flags);
+	info->netcount=0;
+	spin_unlock_irqrestore(&info->netlock, flags);
+
+	return 0;
+}
+
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev  pointer to network device structure
+ * ifr  pointer to network interface request structure
+ * cmd  IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	const size_t size = sizeof(sync_serial_settings);
+	sync_serial_settings new_line;
+	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned int flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
+
+	/* return error if TTY interface open */
+	if (info->port.count)
+		return -EBUSY;
+
+	if (cmd != SIOCWANDEV)
+		return hdlc_ioctl(dev, ifr, cmd);
+
+	switch(ifr->ifr_settings.type) {
+	case IF_GET_IFACE: /* return current sync_serial_settings */
+
+		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+		if (ifr->ifr_settings.size < size) {
+			ifr->ifr_settings.size = size; /* data size wanted */
+			return -ENOBUFS;
+		}
+
+		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+
+		switch (flags){
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
+		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+		default: new_line.clock_type = CLOCK_DEFAULT;
+		}
+
+		new_line.clock_rate = info->params.clock_speed;
+		new_line.loopback   = info->params.loopback ? 1:0;
+
+		if (copy_to_user(line, &new_line, size))
+			return -EFAULT;
+		return 0;
+
+	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (copy_from_user(&new_line, line, size))
+			return -EFAULT;
+
+		switch (new_line.clock_type)
+		{
+		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
+		case CLOCK_DEFAULT:  flags = info->params.flags &
+					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
+		default: return -EINVAL;
+		}
+
+		if (new_line.loopback != 0 && new_line.loopback != 1)
+			return -EINVAL;
+
+		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
+					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
+		info->params.flags |= flags;
+
+		info->params.loopback = new_line.loopback;
+
+		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+			info->params.clock_speed = new_line.clock_rate;
+		else
+			info->params.clock_speed = 0;
+
+		/* if network interface up, reprogram hardware */
+		if (info->netcount)
+			program_hw(info);
+		return 0;
+
+	default:
+		return hdlc_ioctl(dev, ifr, cmd);
+	}
+}
+
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev  pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
+{
+	SLMP_INFO *info = dev_to_port(dev);
+	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
+
+	dev->stats.tx_errors++;
+	dev->stats.tx_aborted_errors++;
+
+	spin_lock_irqsave(&info->lock,flags);
+	tx_stop(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_tx_done(SLMP_INFO *info)
+{
+	if (netif_queue_stopped(info->netdev))
+		netif_wake_queue(info->netdev);
+}
+
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info  pointer to device instance information
+ * buf   pointer to buffer contianing frame data
+ * size  count of data bytes in buf
+ */
+static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
+{
+	struct sk_buff *skb = dev_alloc_skb(size);
+	struct net_device *dev = info->netdev;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("hdlcdev_rx(%s)\n",dev->name);
+
+	if (skb == NULL) {
+		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
+		       dev->name);
+		dev->stats.rx_dropped++;
+		return;
+	}
+
+	memcpy(skb_put(skb, size), buf, size);
+
+	skb->protocol = hdlc_type_trans(skb, dev);
+
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += size;
+
+	netif_rx(skb);
+}
+
+static const struct net_device_ops hdlcdev_ops = {
+	.ndo_open       = hdlcdev_open,
+	.ndo_stop       = hdlcdev_close,
+	.ndo_change_mtu = hdlc_change_mtu,
+	.ndo_start_xmit = hdlc_start_xmit,
+	.ndo_do_ioctl   = hdlcdev_ioctl,
+	.ndo_tx_timeout = hdlcdev_tx_timeout,
+};
+
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info  pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(SLMP_INFO *info)
+{
+	int rc;
+	struct net_device *dev;
+	hdlc_device *hdlc;
+
+	/* allocate and initialize network and HDLC layer objects */
+
+	if (!(dev = alloc_hdlcdev(info))) {
+		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+		return -ENOMEM;
+	}
+
+	/* for network layer reporting purposes only */
+	dev->mem_start = info->phys_sca_base;
+	dev->mem_end   = info->phys_sca_base + SCA_BASE_SIZE - 1;
+	dev->irq       = info->irq_level;
+
+	/* network layer callbacks and settings */
+	dev->netdev_ops	    = &hdlcdev_ops;
+	dev->watchdog_timeo = 10 * HZ;
+	dev->tx_queue_len   = 50;
+
+	/* generic HDLC layer callbacks and settings */
+	hdlc         = dev_to_hdlc(dev);
+	hdlc->attach = hdlcdev_attach;
+	hdlc->xmit   = hdlcdev_xmit;
+
+	/* register objects with HDLC layer */
+	if ((rc = register_hdlc_device(dev))) {
+		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+		free_netdev(dev);
+		return rc;
+	}
+
+	info->netdev = dev;
+	return 0;
+}
+
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info  pointer to device instance information
+ */
+static void hdlcdev_exit(SLMP_INFO *info)
+{
+	unregister_hdlc_device(info->netdev);
+	free_netdev(info->netdev);
+	info->netdev = NULL;
+}
+
+#endif /* CONFIG_HDLC */
+
+
+/* Return next bottom half action to perform.
+ * Return Value:	BH action code or 0 if nothing to do.
+ */
+static int bh_action(SLMP_INFO *info)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	if (info->pending_bh & BH_RECEIVE) {
+		info->pending_bh &= ~BH_RECEIVE;
+		rc = BH_RECEIVE;
+	} else if (info->pending_bh & BH_TRANSMIT) {
+		info->pending_bh &= ~BH_TRANSMIT;
+		rc = BH_TRANSMIT;
+	} else if (info->pending_bh & BH_STATUS) {
+		info->pending_bh &= ~BH_STATUS;
+		rc = BH_STATUS;
+	}
+
+	if (!rc) {
+		/* Mark BH routine as complete */
+		info->bh_running = false;
+		info->bh_requested = false;
+	}
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return rc;
+}
+
+/* Perform bottom half processing of work items queued by ISR.
+ */
+static void bh_handler(struct work_struct *work)
+{
+	SLMP_INFO *info = container_of(work, SLMP_INFO, task);
+	int action;
+
+	if (!info)
+		return;
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):%s bh_handler() entry\n",
+			__FILE__,__LINE__,info->device_name);
+
+	info->bh_running = true;
+
+	while((action = bh_action(info)) != 0) {
+
+		/* Process work item */
+		if ( debug_level >= DEBUG_LEVEL_BH )
+			printk( "%s(%d):%s bh_handler() work item action=%d\n",
+				__FILE__,__LINE__,info->device_name, action);
+
+		switch (action) {
+
+		case BH_RECEIVE:
+			bh_receive(info);
+			break;
+		case BH_TRANSMIT:
+			bh_transmit(info);
+			break;
+		case BH_STATUS:
+			bh_status(info);
+			break;
+		default:
+			/* unknown work item ID */
+			printk("%s(%d):%s Unknown work item ID=%08X!\n",
+				__FILE__,__LINE__,info->device_name,action);
+			break;
+		}
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):%s bh_handler() exit\n",
+			__FILE__,__LINE__,info->device_name);
+}
+
+static void bh_receive(SLMP_INFO *info)
+{
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):%s bh_receive()\n",
+			__FILE__,__LINE__,info->device_name);
+
+	while( rx_get_frame(info) );
+}
+
+static void bh_transmit(SLMP_INFO *info)
+{
+	struct tty_struct *tty = info->port.tty;
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):%s bh_transmit() entry\n",
+			__FILE__,__LINE__,info->device_name);
+
+	if (tty)
+		tty_wakeup(tty);
+}
+
+static void bh_status(SLMP_INFO *info)
+{
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk( "%s(%d):%s bh_status() entry\n",
+			__FILE__,__LINE__,info->device_name);
+
+	info->ri_chkcount = 0;
+	info->dsr_chkcount = 0;
+	info->dcd_chkcount = 0;
+	info->cts_chkcount = 0;
+}
+
+static void isr_timer(SLMP_INFO * info)
+{
+	unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
+
+	/* IER2<7..4> = timer<3..0> interrupt enables (0=disabled) */
+	write_reg(info, IER2, 0);
+
+	/* TMCS, Timer Control/Status Register
+	 *
+	 * 07      CMF, Compare match flag (read only) 1=match
+	 * 06      ECMI, CMF Interrupt Enable: 0=disabled
+	 * 05      Reserved, must be 0
+	 * 04      TME, Timer Enable
+	 * 03..00  Reserved, must be 0
+	 *
+	 * 0000 0000
+	 */
+	write_reg(info, (unsigned char)(timer + TMCS), 0);
+
+	info->irq_occurred = true;
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_timer()\n",
+			__FILE__,__LINE__,info->device_name);
+}
+
+static void isr_rxint(SLMP_INFO * info)
+{
+ 	struct tty_struct *tty = info->port.tty;
+ 	struct	mgsl_icount *icount = &info->icount;
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
+	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
+
+	/* clear status bits */
+	if (status)
+		write_reg(info, SR1, status);
+
+	if (status2)
+		write_reg(info, SR2, status2);
+	
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
+			__FILE__,__LINE__,info->device_name,status,status2);
+
+	if (info->params.mode == MGSL_MODE_ASYNC) {
+		if (status & BRKD) {
+			icount->brk++;
+
+			/* process break detection if tty control
+			 * is not set to ignore it
+			 */
+			if ( tty ) {
+				if (!(status & info->ignore_status_mask1)) {
+					if (info->read_status_mask1 & BRKD) {
+						tty_insert_flip_char(tty, 0, TTY_BREAK);
+						if (info->port.flags & ASYNC_SAK)
+							do_SAK(tty);
+					}
+				}
+			}
+		}
+	}
+	else {
+		if (status & (FLGD|IDLD)) {
+			if (status & FLGD)
+				info->icount.exithunt++;
+			else if (status & IDLD)
+				info->icount.rxidle++;
+			wake_up_interruptible(&info->event_wait_q);
+		}
+	}
+
+	if (status & CDCD) {
+		/* simulate a common modem status change interrupt
+		 * for our handler
+		 */
+		get_signals( info );
+		isr_io_pin(info,
+			MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD));
+	}
+}
+
+/*
+ * handle async rx data interrupts
+ */
+static void isr_rxrdy(SLMP_INFO * info)
+{
+	u16 status;
+	unsigned char DataByte;
+ 	struct tty_struct *tty = info->port.tty;
+ 	struct	mgsl_icount *icount = &info->icount;
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_rxrdy\n",
+			__FILE__,__LINE__,info->device_name);
+
+	while((status = read_reg(info,CST0)) & BIT0)
+	{
+		int flag = 0;
+		bool over = false;
+		DataByte = read_reg(info,TRB);
+
+		icount->rx++;
+
+		if ( status & (PE + FRME + OVRN) ) {
+			printk("%s(%d):%s rxerr=%04X\n",
+				__FILE__,__LINE__,info->device_name,status);
+
+			/* update error statistics */
+			if (status & PE)
+				icount->parity++;
+			else if (status & FRME)
+				icount->frame++;
+			else if (status & OVRN)
+				icount->overrun++;
+
+			/* discard char if tty control flags say so */
+			if (status & info->ignore_status_mask2)
+				continue;
+
+			status &= info->read_status_mask2;
+
+			if ( tty ) {
+				if (status & PE)
+					flag = TTY_PARITY;
+				else if (status & FRME)
+					flag = TTY_FRAME;
+				if (status & OVRN) {
+					/* Overrun is special, since it's
+					 * reported immediately, and doesn't
+					 * affect the current character
+					 */
+					over = true;
+				}
+			}
+		}	/* end of if (error) */
+
+		if ( tty ) {
+			tty_insert_flip_char(tty, DataByte, flag);
+			if (over)
+				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+		}
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_ISR ) {
+		printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
+			__FILE__,__LINE__,info->device_name,
+			icount->rx,icount->brk,icount->parity,
+			icount->frame,icount->overrun);
+	}
+
+	if ( tty )
+		tty_flip_buffer_push(tty);
+}
+
+static void isr_txeom(SLMP_INFO * info, unsigned char status)
+{
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_txeom status=%02x\n",
+			__FILE__,__LINE__,info->device_name,status);
+
+	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
+	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
+	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
+
+	if (status & UDRN) {
+		write_reg(info, CMD, TXRESET);
+		write_reg(info, CMD, TXENABLE);
+	} else
+		write_reg(info, CMD, TXBUFCLR);
+
+	/* disable and clear tx interrupts */
+	info->ie0_value &= ~TXRDYE;
+	info->ie1_value &= ~(IDLE + UDRN);
+	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
+
+	if ( info->tx_active ) {
+		if (info->params.mode != MGSL_MODE_ASYNC) {
+			if (status & UDRN)
+				info->icount.txunder++;
+			else if (status & IDLE)
+				info->icount.txok++;
+		}
+
+		info->tx_active = false;
+		info->tx_count = info->tx_put = info->tx_get = 0;
+
+		del_timer(&info->tx_timer);
+
+		if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) {
+			info->serial_signals &= ~SerialSignal_RTS;
+			info->drop_rts_on_tx_done = false;
+			set_signals(info);
+		}
+
+#if SYNCLINK_GENERIC_HDLC
+		if (info->netcount)
+			hdlcdev_tx_done(info);
+		else
+#endif
+		{
+			if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
+				tx_stop(info);
+				return;
+			}
+			info->pending_bh |= BH_TRANSMIT;
+		}
+	}
+}
+
+
+/*
+ * handle tx status interrupts
+ */
+static void isr_txint(SLMP_INFO * info)
+{
+	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
+
+	/* clear status bits */
+	write_reg(info, SR1, status);
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_txint status=%02x\n",
+			__FILE__,__LINE__,info->device_name,status);
+
+	if (status & (UDRN + IDLE))
+		isr_txeom(info, status);
+
+	if (status & CCTS) {
+		/* simulate a common modem status change interrupt
+		 * for our handler
+		 */
+		get_signals( info );
+		isr_io_pin(info,
+			MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS));
+
+	}
+}
+
+/*
+ * handle async tx data interrupts
+ */
+static void isr_txrdy(SLMP_INFO * info)
+{
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
+			__FILE__,__LINE__,info->device_name,info->tx_count);
+
+	if (info->params.mode != MGSL_MODE_ASYNC) {
+		/* disable TXRDY IRQ, enable IDLE IRQ */
+		info->ie0_value &= ~TXRDYE;
+		info->ie1_value |= IDLE;
+		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
+		return;
+	}
+
+	if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
+		tx_stop(info);
+		return;
+	}
+
+	if ( info->tx_count )
+		tx_load_fifo( info );
+	else {
+		info->tx_active = false;
+		info->ie0_value &= ~TXRDYE;
+		write_reg(info, IE0, info->ie0_value);
+	}
+
+	if (info->tx_count < WAKEUP_CHARS)
+		info->pending_bh |= BH_TRANSMIT;
+}
+
+static void isr_rxdmaok(SLMP_INFO * info)
+{
+	/* BIT7 = EOT (end of transfer)
+	 * BIT6 = EOM (end of message/frame)
+	 */
+	unsigned char status = read_reg(info,RXDMA + DSR) & 0xc0;
+
+	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
+	write_reg(info, RXDMA + DSR, (unsigned char)(status | 1));
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_rxdmaok(), status=%02x\n",
+			__FILE__,__LINE__,info->device_name,status);
+
+	info->pending_bh |= BH_RECEIVE;
+}
+
+static void isr_rxdmaerror(SLMP_INFO * info)
+{
+	/* BIT5 = BOF (buffer overflow)
+	 * BIT4 = COF (counter overflow)
+	 */
+	unsigned char status = read_reg(info,RXDMA + DSR) & 0x30;
+
+	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
+	write_reg(info, RXDMA + DSR, (unsigned char)(status | 1));
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n",
+			__FILE__,__LINE__,info->device_name,status);
+
+	info->rx_overflow = true;
+	info->pending_bh |= BH_RECEIVE;
+}
+
+static void isr_txdmaok(SLMP_INFO * info)
+{
+	unsigned char status_reg1 = read_reg(info, SR1);
+
+	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
+	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
+	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
+			__FILE__,__LINE__,info->device_name,status_reg1);
+
+	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
+	write_reg16(info, TRC0, 0);
+	info->ie0_value |= TXRDYE;
+	write_reg(info, IE0, info->ie0_value);
+}
+
+static void isr_txdmaerror(SLMP_INFO * info)
+{
+	/* BIT5 = BOF (buffer overflow)
+	 * BIT4 = COF (counter overflow)
+	 */
+	unsigned char status = read_reg(info,TXDMA + DSR) & 0x30;
+
+	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
+	write_reg(info, TXDMA + DSR, (unsigned char)(status | 1));
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):%s isr_txdmaerror(), status=%02x\n",
+			__FILE__,__LINE__,info->device_name,status);
+}
+
+/* handle input serial signal changes
+ */
+static void isr_io_pin( SLMP_INFO *info, u16 status )
+{
+ 	struct	mgsl_icount *icount;
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk("%s(%d):isr_io_pin status=%04X\n",
+			__FILE__,__LINE__,status);
+
+	if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED |
+	              MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) {
+		icount = &info->icount;
+		/* update input line counters */
+		if (status & MISCSTATUS_RI_LATCHED) {
+			icount->rng++;
+			if ( status & SerialSignal_RI )
+				info->input_signal_events.ri_up++;
+			else
+				info->input_signal_events.ri_down++;
+		}
+		if (status & MISCSTATUS_DSR_LATCHED) {
+			icount->dsr++;
+			if ( status & SerialSignal_DSR )
+				info->input_signal_events.dsr_up++;
+			else
+				info->input_signal_events.dsr_down++;
+		}
+		if (status & MISCSTATUS_DCD_LATCHED) {
+			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) {
+				info->ie1_value &= ~CDCD;
+				write_reg(info, IE1, info->ie1_value);
+			}
+			icount->dcd++;
+			if (status & SerialSignal_DCD) {
+				info->input_signal_events.dcd_up++;
+			} else
+				info->input_signal_events.dcd_down++;
+#if SYNCLINK_GENERIC_HDLC
+			if (info->netcount) {
+				if (status & SerialSignal_DCD)
+					netif_carrier_on(info->netdev);
+				else
+					netif_carrier_off(info->netdev);
+			}
+#endif
+		}
+		if (status & MISCSTATUS_CTS_LATCHED)
+		{
+			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) {
+				info->ie1_value &= ~CCTS;
+				write_reg(info, IE1, info->ie1_value);
+			}
+			icount->cts++;
+			if ( status & SerialSignal_CTS )
+				info->input_signal_events.cts_up++;
+			else
+				info->input_signal_events.cts_down++;
+		}
+		wake_up_interruptible(&info->status_event_wait_q);
+		wake_up_interruptible(&info->event_wait_q);
+
+		if ( (info->port.flags & ASYNC_CHECK_CD) &&
+		     (status & MISCSTATUS_DCD_LATCHED) ) {
+			if ( debug_level >= DEBUG_LEVEL_ISR )
+				printk("%s CD now %s...", info->device_name,
+				       (status & SerialSignal_DCD) ? "on" : "off");
+			if (status & SerialSignal_DCD)
+				wake_up_interruptible(&info->port.open_wait);
+			else {
+				if ( debug_level >= DEBUG_LEVEL_ISR )
+					printk("doing serial hangup...");
+				if (info->port.tty)
+					tty_hangup(info->port.tty);
+			}
+		}
+
+		if ( (info->port.flags & ASYNC_CTS_FLOW) &&
+		     (status & MISCSTATUS_CTS_LATCHED) ) {
+			if ( info->port.tty ) {
+				if (info->port.tty->hw_stopped) {
+					if (status & SerialSignal_CTS) {
+						if ( debug_level >= DEBUG_LEVEL_ISR )
+							printk("CTS tx start...");
+			 			info->port.tty->hw_stopped = 0;
+						tx_start(info);
+						info->pending_bh |= BH_TRANSMIT;
+						return;
+					}
+				} else {
+					if (!(status & SerialSignal_CTS)) {
+						if ( debug_level >= DEBUG_LEVEL_ISR )
+							printk("CTS tx stop...");
+			 			info->port.tty->hw_stopped = 1;
+						tx_stop(info);
+					}
+				}
+			}
+		}
+	}
+
+	info->pending_bh |= BH_STATUS;
+}
+
+/* Interrupt service routine entry point.
+ *
+ * Arguments:
+ * 	irq		interrupt number that caused interrupt
+ * 	dev_id		device ID supplied during interrupt registration
+ * 	regs		interrupted processor context
+ */
+static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id)
+{
+	SLMP_INFO *info = dev_id;
+	unsigned char status, status0, status1=0;
+	unsigned char dmastatus, dmastatus0, dmastatus1=0;
+	unsigned char timerstatus0, timerstatus1=0;
+	unsigned char shift;
+	unsigned int i;
+	unsigned short tmp;
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n",
+			__FILE__, __LINE__, info->irq_level);
+
+	spin_lock(&info->lock);
+
+	for(;;) {
+
+		/* get status for SCA0 (ports 0-1) */
+		tmp = read_reg16(info, ISR0);	/* get ISR0 and ISR1 in one read */
+		status0 = (unsigned char)tmp;
+		dmastatus0 = (unsigned char)(tmp>>8);
+		timerstatus0 = read_reg(info, ISR2);
+
+		if ( debug_level >= DEBUG_LEVEL_ISR )
+			printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
+				__FILE__, __LINE__, info->device_name,
+				status0, dmastatus0, timerstatus0);
+
+		if (info->port_count == 4) {
+			/* get status for SCA1 (ports 2-3) */
+			tmp = read_reg16(info->port_array[2], ISR0);
+			status1 = (unsigned char)tmp;
+			dmastatus1 = (unsigned char)(tmp>>8);
+			timerstatus1 = read_reg(info->port_array[2], ISR2);
+
+			if ( debug_level >= DEBUG_LEVEL_ISR )
+				printk("%s(%d):%s status1=%02x, dmastatus1=%02x, timerstatus1=%02x\n",
+					__FILE__,__LINE__,info->device_name,
+					status1,dmastatus1,timerstatus1);
+		}
+
+		if (!status0 && !dmastatus0 && !timerstatus0 &&
+			 !status1 && !dmastatus1 && !timerstatus1)
+			break;
+
+		for(i=0; i < info->port_count ; i++) {
+			if (info->port_array[i] == NULL)
+				continue;
+			if (i < 2) {
+				status = status0;
+				dmastatus = dmastatus0;
+			} else {
+				status = status1;
+				dmastatus = dmastatus1;
+			}
+
+			shift = i & 1 ? 4 :0;
+
+			if (status & BIT0 << shift)
+				isr_rxrdy(info->port_array[i]);
+			if (status & BIT1 << shift)
+				isr_txrdy(info->port_array[i]);
+			if (status & BIT2 << shift)
+				isr_rxint(info->port_array[i]);
+			if (status & BIT3 << shift)
+				isr_txint(info->port_array[i]);
+
+			if (dmastatus & BIT0 << shift)
+				isr_rxdmaerror(info->port_array[i]);
+			if (dmastatus & BIT1 << shift)
+				isr_rxdmaok(info->port_array[i]);
+			if (dmastatus & BIT2 << shift)
+				isr_txdmaerror(info->port_array[i]);
+			if (dmastatus & BIT3 << shift)
+				isr_txdmaok(info->port_array[i]);
+		}
+
+		if (timerstatus0 & (BIT5 | BIT4))
+			isr_timer(info->port_array[0]);
+		if (timerstatus0 & (BIT7 | BIT6))
+			isr_timer(info->port_array[1]);
+		if (timerstatus1 & (BIT5 | BIT4))
+			isr_timer(info->port_array[2]);
+		if (timerstatus1 & (BIT7 | BIT6))
+			isr_timer(info->port_array[3]);
+	}
+
+	for(i=0; i < info->port_count ; i++) {
+		SLMP_INFO * port = info->port_array[i];
+
+		/* Request bottom half processing if there's something
+		 * for it to do and the bh is not already running.
+		 *
+		 * Note: startup adapter diags require interrupts.
+		 * do not request bottom half processing if the
+		 * device is not open in a normal mode.
+		 */
+		if ( port && (port->port.count || port->netcount) &&
+		     port->pending_bh && !port->bh_running &&
+		     !port->bh_requested ) {
+			if ( debug_level >= DEBUG_LEVEL_ISR )
+				printk("%s(%d):%s queueing bh task.\n",
+					__FILE__,__LINE__,port->device_name);
+			schedule_work(&port->task);
+			port->bh_requested = true;
+		}
+	}
+
+	spin_unlock(&info->lock);
+
+	if ( debug_level >= DEBUG_LEVEL_ISR )
+		printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n",
+			__FILE__, __LINE__, info->irq_level);
+	return IRQ_HANDLED;
+}
+
+/* Initialize and start device.
+ */
+static int startup(SLMP_INFO * info)
+{
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s(%d):%s tx_releaseup()\n",__FILE__,__LINE__,info->device_name);
+
+	if (info->port.flags & ASYNC_INITIALIZED)
+		return 0;
+
+	if (!info->tx_buf) {
+		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
+		if (!info->tx_buf) {
+			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
+				__FILE__,__LINE__,info->device_name);
+			return -ENOMEM;
+		}
+	}
+
+	info->pending_bh = 0;
+
+	memset(&info->icount, 0, sizeof(info->icount));
+
+	/* program hardware for current parameters */
+	reset_port(info);
+
+	change_params(info);
+
+	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
+
+	if (info->port.tty)
+		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
+
+	info->port.flags |= ASYNC_INITIALIZED;
+
+	return 0;
+}
+
+/* Called by close() and hangup() to shutdown hardware
+ */
+static void shutdown(SLMP_INFO * info)
+{
+	unsigned long flags;
+
+	if (!(info->port.flags & ASYNC_INITIALIZED))
+		return;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s synclinkmp_shutdown()\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	/* clear status wait queue because status changes */
+	/* can't happen after shutting down the hardware */
+	wake_up_interruptible(&info->status_event_wait_q);
+	wake_up_interruptible(&info->event_wait_q);
+
+	del_timer(&info->tx_timer);
+	del_timer(&info->status_timer);
+
+	kfree(info->tx_buf);
+	info->tx_buf = NULL;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	reset_port(info);
+
+ 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
+ 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+		set_signals(info);
+	}
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	if (info->port.tty)
+		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
+
+	info->port.flags &= ~ASYNC_INITIALIZED;
+}
+
+static void program_hw(SLMP_INFO *info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	rx_stop(info);
+	tx_stop(info);
+
+	info->tx_count = info->tx_put = info->tx_get = 0;
+
+	if (info->params.mode == MGSL_MODE_HDLC || info->netcount)
+		hdlc_mode(info);
+	else
+		async_mode(info);
+
+	set_signals(info);
+
+	info->dcd_chkcount = 0;
+	info->cts_chkcount = 0;
+	info->ri_chkcount = 0;
+	info->dsr_chkcount = 0;
+
+	info->ie1_value |= (CDCD|CCTS);
+	write_reg(info, IE1, info->ie1_value);
+
+	get_signals(info);
+
+	if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) )
+		rx_start(info);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/* Reconfigure adapter based on new parameters
+ */
+static void change_params(SLMP_INFO *info)
+{
+	unsigned cflag;
+	int bits_per_char;
+
+	if (!info->port.tty || !info->port.tty->termios)
+		return;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s change_params()\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	cflag = info->port.tty->termios->c_cflag;
+
+	/* if B0 rate (hangup) specified then negate DTR and RTS */
+	/* otherwise assert DTR and RTS */
+ 	if (cflag & CBAUD)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+
+	/* byte size and parity */
+
+	switch (cflag & CSIZE) {
+	      case CS5: info->params.data_bits = 5; break;
+	      case CS6: info->params.data_bits = 6; break;
+	      case CS7: info->params.data_bits = 7; break;
+	      case CS8: info->params.data_bits = 8; break;
+	      /* Never happens, but GCC is too dumb to figure it out */
+	      default:  info->params.data_bits = 7; break;
+	      }
+
+	if (cflag & CSTOPB)
+		info->params.stop_bits = 2;
+	else
+		info->params.stop_bits = 1;
+
+	info->params.parity = ASYNC_PARITY_NONE;
+	if (cflag & PARENB) {
+		if (cflag & PARODD)
+			info->params.parity = ASYNC_PARITY_ODD;
+		else
+			info->params.parity = ASYNC_PARITY_EVEN;
+#ifdef CMSPAR
+		if (cflag & CMSPAR)
+			info->params.parity = ASYNC_PARITY_SPACE;
+#endif
+	}
+
+	/* calculate number of jiffies to transmit a full
+	 * FIFO (32 bytes) at specified data rate
+	 */
+	bits_per_char = info->params.data_bits +
+			info->params.stop_bits + 1;
+
+	/* if port data rate is set to 460800 or less then
+	 * allow tty settings to override, otherwise keep the
+	 * current data rate.
+	 */
+	if (info->params.data_rate <= 460800) {
+		info->params.data_rate = tty_get_baud_rate(info->port.tty);
+	}
+
+	if ( info->params.data_rate ) {
+		info->timeout = (32*HZ*bits_per_char) /
+				info->params.data_rate;
+	}
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	if (cflag & CRTSCTS)
+		info->port.flags |= ASYNC_CTS_FLOW;
+	else
+		info->port.flags &= ~ASYNC_CTS_FLOW;
+
+	if (cflag & CLOCAL)
+		info->port.flags &= ~ASYNC_CHECK_CD;
+	else
+		info->port.flags |= ASYNC_CHECK_CD;
+
+	/* process tty input control flags */
+
+	info->read_status_mask2 = OVRN;
+	if (I_INPCK(info->port.tty))
+		info->read_status_mask2 |= PE | FRME;
+ 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
+ 		info->read_status_mask1 |= BRKD;
+	if (I_IGNPAR(info->port.tty))
+		info->ignore_status_mask2 |= PE | FRME;
+	if (I_IGNBRK(info->port.tty)) {
+		info->ignore_status_mask1 |= BRKD;
+		/* If ignoring parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->port.tty))
+			info->ignore_status_mask2 |= OVRN;
+	}
+
+	program_hw(info);
+}
+
+static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
+{
+	int err;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s get_params()\n",
+			 __FILE__,__LINE__, info->device_name);
+
+	if (!user_icount) {
+		memset(&info->icount, 0, sizeof(info->icount));
+	} else {
+		mutex_lock(&info->port.mutex);
+		COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
+		mutex_unlock(&info->port.mutex);
+		if (err)
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)
+{
+	int err;
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s get_params()\n",
+			 __FILE__,__LINE__, info->device_name);
+
+	mutex_lock(&info->port.mutex);
+	COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
+	mutex_unlock(&info->port.mutex);
+	if (err) {
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk( "%s(%d):%s get_params() user buffer copy failed\n",
+				__FILE__,__LINE__,info->device_name);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)
+{
+ 	unsigned long flags;
+	MGSL_PARAMS tmp_params;
+	int err;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s set_params\n",
+			__FILE__,__LINE__,info->device_name );
+	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));
+	if (err) {
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk( "%s(%d):%s set_params() user buffer copy failed\n",
+				__FILE__,__LINE__,info->device_name);
+		return -EFAULT;
+	}
+
+	mutex_lock(&info->port.mutex);
+	spin_lock_irqsave(&info->lock,flags);
+	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
+	spin_unlock_irqrestore(&info->lock,flags);
+
+ 	change_params(info);
+	mutex_unlock(&info->port.mutex);
+
+	return 0;
+}
+
+static int get_txidle(SLMP_INFO * info, int __user *idle_mode)
+{
+	int err;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s get_txidle()=%d\n",
+			 __FILE__,__LINE__, info->device_name, info->idle_mode);
+
+	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));
+	if (err) {
+		if ( debug_level >= DEBUG_LEVEL_INFO )
+			printk( "%s(%d):%s get_txidle() user buffer copy failed\n",
+				__FILE__,__LINE__,info->device_name);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int set_txidle(SLMP_INFO * info, int idle_mode)
+{
+ 	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s set_txidle(%d)\n",
+			__FILE__,__LINE__,info->device_name, idle_mode );
+
+	spin_lock_irqsave(&info->lock,flags);
+	info->idle_mode = idle_mode;
+	tx_set_idle( info );
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+static int tx_enable(SLMP_INFO * info, int enable)
+{
+ 	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s tx_enable(%d)\n",
+			__FILE__,__LINE__,info->device_name, enable);
+
+	spin_lock_irqsave(&info->lock,flags);
+	if ( enable ) {
+		if ( !info->tx_enabled ) {
+			tx_start(info);
+		}
+	} else {
+		if ( info->tx_enabled )
+			tx_stop(info);
+	}
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+/* abort send HDLC frame
+ */
+static int tx_abort(SLMP_INFO * info)
+{
+ 	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s tx_abort()\n",
+			__FILE__,__LINE__,info->device_name);
+
+	spin_lock_irqsave(&info->lock,flags);
+	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) {
+		info->ie1_value &= ~UDRN;
+		info->ie1_value |= IDLE;
+		write_reg(info, IE1, info->ie1_value);	/* disable tx status interrupts */
+		write_reg(info, SR1, (unsigned char)(IDLE + UDRN));	/* clear pending */
+
+		write_reg(info, TXDMA + DSR, 0);		/* disable DMA channel */
+		write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
+
+   		write_reg(info, CMD, TXABORT);
+	}
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+static int rx_enable(SLMP_INFO * info, int enable)
+{
+ 	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s rx_enable(%d)\n",
+			__FILE__,__LINE__,info->device_name,enable);
+
+	spin_lock_irqsave(&info->lock,flags);
+	if ( enable ) {
+		if ( !info->rx_enabled )
+			rx_start(info);
+	} else {
+		if ( info->rx_enabled )
+			rx_stop(info);
+	}
+	spin_unlock_irqrestore(&info->lock,flags);
+	return 0;
+}
+
+/* wait for specified event to occur
+ */
+static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
+{
+ 	unsigned long flags;
+	int s;
+	int rc=0;
+	struct mgsl_icount cprev, cnow;
+	int events;
+	int mask;
+	struct	_input_signal_events oldsigs, newsigs;
+	DECLARE_WAITQUEUE(wait, current);
+
+	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
+	if (rc) {
+		return  -EFAULT;
+	}
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s wait_mgsl_event(%d)\n",
+			__FILE__,__LINE__,info->device_name,mask);
+
+	spin_lock_irqsave(&info->lock,flags);
+
+	/* return immediately if state matches requested events */
+	get_signals(info);
+	s = info->serial_signals;
+
+	events = mask &
+		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
+ 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
+		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
+		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
+	if (events) {
+		spin_unlock_irqrestore(&info->lock,flags);
+		goto exit;
+	}
+
+	/* save current irq counts */
+	cprev = info->icount;
+	oldsigs = info->input_signal_events;
+
+	/* enable hunt and idle irqs if needed */
+	if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
+		unsigned char oldval = info->ie1_value;
+		unsigned char newval = oldval +
+			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
+			 (mask & MgslEvent_IdleReceived ? IDLD:0);
+		if ( oldval != newval ) {
+			info->ie1_value = newval;
+			write_reg(info, IE1, info->ie1_value);
+		}
+	}
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&info->event_wait_q, &wait);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+
+		/* get current irq counts */
+		spin_lock_irqsave(&info->lock,flags);
+		cnow = info->icount;
+		newsigs = info->input_signal_events;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->lock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
+		    newsigs.dsr_down == oldsigs.dsr_down &&
+		    newsigs.dcd_up   == oldsigs.dcd_up   &&
+		    newsigs.dcd_down == oldsigs.dcd_down &&
+		    newsigs.cts_up   == oldsigs.cts_up   &&
+		    newsigs.cts_down == oldsigs.cts_down &&
+		    newsigs.ri_up    == oldsigs.ri_up    &&
+		    newsigs.ri_down  == oldsigs.ri_down  &&
+		    cnow.exithunt    == cprev.exithunt   &&
+		    cnow.rxidle      == cprev.rxidle) {
+			rc = -EIO;
+			break;
+		}
+
+		events = mask &
+			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
+			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
+			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
+			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
+			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
+			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
+			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
+			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
+			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
+			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
+		if (events)
+			break;
+
+		cprev = cnow;
+		oldsigs = newsigs;
+	}
+
+	remove_wait_queue(&info->event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+
+
+	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
+		spin_lock_irqsave(&info->lock,flags);
+		if (!waitqueue_active(&info->event_wait_q)) {
+			/* disable enable exit hunt mode/idle rcvd IRQs */
+			info->ie1_value &= ~(FLGD|IDLD);
+			write_reg(info, IE1, info->ie1_value);
+		}
+		spin_unlock_irqrestore(&info->lock,flags);
+	}
+exit:
+	if ( rc == 0 )
+		PUT_USER(rc, events, mask_ptr);
+
+	return rc;
+}
+
+static int modem_input_wait(SLMP_INFO *info,int arg)
+{
+ 	unsigned long flags;
+	int rc;
+	struct mgsl_icount cprev, cnow;
+	DECLARE_WAITQUEUE(wait, current);
+
+	/* save current irq counts */
+	spin_lock_irqsave(&info->lock,flags);
+	cprev = info->icount;
+	add_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	for(;;) {
+		schedule();
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			break;
+		}
+
+		/* get new irq counts */
+		spin_lock_irqsave(&info->lock,flags);
+		cnow = info->icount;
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_irqrestore(&info->lock,flags);
+
+		/* if no change, wait aborted for some reason */
+		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
+			rc = -EIO;
+			break;
+		}
+
+		/* check for change in caller specified modem input */
+		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
+		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
+		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
+		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
+			rc = 0;
+			break;
+		}
+
+		cprev = cnow;
+	}
+	remove_wait_queue(&info->status_event_wait_q, &wait);
+	set_current_state(TASK_RUNNING);
+	return rc;
+}
+
+/* return the state of the serial control and status signals
+ */
+static int tiocmget(struct tty_struct *tty)
+{
+	SLMP_INFO *info = tty->driver_data;
+	unsigned int result;
+ 	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+ 	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
+		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
+		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
+		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
+		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
+		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s tiocmget() value=%08X\n",
+			 __FILE__,__LINE__, info->device_name, result );
+	return result;
+}
+
+/* set modem control signals (DTR/RTS)
+ */
+static int tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear)
+{
+	SLMP_INFO *info = tty->driver_data;
+ 	unsigned long flags;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s tiocmset(%x,%x)\n",
+			__FILE__,__LINE__,info->device_name, set, clear);
+
+	if (set & TIOCM_RTS)
+		info->serial_signals |= SerialSignal_RTS;
+	if (set & TIOCM_DTR)
+		info->serial_signals |= SerialSignal_DTR;
+	if (clear & TIOCM_RTS)
+		info->serial_signals &= ~SerialSignal_RTS;
+	if (clear & TIOCM_DTR)
+		info->serial_signals &= ~SerialSignal_DTR;
+
+	spin_lock_irqsave(&info->lock,flags);
+ 	set_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return 0;
+}
+
+static int carrier_raised(struct tty_port *port)
+{
+	SLMP_INFO *info = container_of(port, SLMP_INFO, port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+ 	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
+}
+
+static void dtr_rts(struct tty_port *port, int on)
+{
+	SLMP_INFO *info = container_of(port, SLMP_INFO, port);
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	if (on)
+		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
+	else
+		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
+ 	set_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+}
+
+/* Block the current process until the specified port is ready to open.
+ */
+static int block_til_ready(struct tty_struct *tty, struct file *filp,
+			   SLMP_INFO *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int		retval;
+	bool		do_clocal = false;
+	bool		extra_count = false;
+	unsigned long	flags;
+	int		cd;
+	struct tty_port *port = &info->port;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s block_til_ready()\n",
+			 __FILE__,__LINE__, tty->driver->name );
+
+	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
+		/* nonblock mode is set or port is not enabled */
+		/* just verify that callout device is not active */
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (tty->termios->c_cflag & CLOCAL)
+		do_clocal = true;
+
+	/* Wait for carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, port->count is dropped by one, so that
+	 * close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+
+	retval = 0;
+	add_wait_queue(&port->open_wait, &wait);
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s block_til_ready() before block, count=%d\n",
+			 __FILE__,__LINE__, tty->driver->name, port->count );
+
+	spin_lock_irqsave(&info->lock, flags);
+	if (!tty_hung_up_p(filp)) {
+		extra_count = true;
+		port->count--;
+	}
+	spin_unlock_irqrestore(&info->lock, flags);
+	port->blocked_open++;
+
+	while (1) {
+		if (tty->termios->c_cflag & CBAUD)
+			tty_port_raise_dtr_rts(port);
+
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
+			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
+					-EAGAIN : -ERESTARTSYS;
+			break;
+		}
+
+		cd = tty_port_carrier_raised(port);
+
+ 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
+ 			break;
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+
+		if (debug_level >= DEBUG_LEVEL_INFO)
+			printk("%s(%d):%s block_til_ready() count=%d\n",
+				 __FILE__,__LINE__, tty->driver->name, port->count );
+
+		tty_unlock();
+		schedule();
+		tty_lock();
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&port->open_wait, &wait);
+
+	if (extra_count)
+		port->count++;
+	port->blocked_open--;
+
+	if (debug_level >= DEBUG_LEVEL_INFO)
+		printk("%s(%d):%s block_til_ready() after, count=%d\n",
+			 __FILE__,__LINE__, tty->driver->name, port->count );
+
+	if (!retval)
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+
+	return retval;
+}
+
+static int alloc_dma_bufs(SLMP_INFO *info)
+{
+	unsigned short BuffersPerFrame;
+	unsigned short BufferCount;
+
+	// Force allocation to start at 64K boundary for each port.
+	// This is necessary because *all* buffer descriptors for a port
+	// *must* be in the same 64K block. All descriptors on a port
+	// share a common 'base' address (upper 8 bits of 24 bits) programmed
+	// into the CBP register.
+	info->port_array[0]->last_mem_alloc = (SCA_MEM_SIZE/4) * info->port_num;
+
+	/* Calculate the number of DMA buffers necessary to hold the */
+	/* largest allowable frame size. Note: If the max frame size is */
+	/* not an even multiple of the DMA buffer size then we need to */
+	/* round the buffer count per frame up one. */
+
+	BuffersPerFrame = (unsigned short)(info->max_frame_size/SCABUFSIZE);
+	if ( info->max_frame_size % SCABUFSIZE )
+		BuffersPerFrame++;
+
+	/* calculate total number of data buffers (SCABUFSIZE) possible
+	 * in one ports memory (SCA_MEM_SIZE/4) after allocating memory
+	 * for the descriptor list (BUFFERLISTSIZE).
+	 */
+	BufferCount = (SCA_MEM_SIZE/4 - BUFFERLISTSIZE)/SCABUFSIZE;
+
+	/* limit number of buffers to maximum amount of descriptors */
+	if (BufferCount > BUFFERLISTSIZE/sizeof(SCADESC))
+		BufferCount = BUFFERLISTSIZE/sizeof(SCADESC);
+
+	/* use enough buffers to transmit one max size frame */
+	info->tx_buf_count = BuffersPerFrame + 1;
+
+	/* never use more than half the available buffers for transmit */
+	if (info->tx_buf_count > (BufferCount/2))
+		info->tx_buf_count = BufferCount/2;
+
+	if (info->tx_buf_count > SCAMAXDESC)
+		info->tx_buf_count = SCAMAXDESC;
+
+	/* use remaining buffers for receive */
+	info->rx_buf_count = BufferCount - info->tx_buf_count;
+
+	if (info->rx_buf_count > SCAMAXDESC)
+		info->rx_buf_count = SCAMAXDESC;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk("%s(%d):%s Allocating %d TX and %d RX DMA buffers.\n",
+			__FILE__,__LINE__, info->device_name,
+			info->tx_buf_count,info->rx_buf_count);
+
+	if ( alloc_buf_list( info ) < 0 ||
+		alloc_frame_bufs(info,
+		  			info->rx_buf_list,
+		  			info->rx_buf_list_ex,
+					info->rx_buf_count) < 0 ||
+		alloc_frame_bufs(info,
+					info->tx_buf_list,
+					info->tx_buf_list_ex,
+					info->tx_buf_count) < 0 ||
+		alloc_tmp_rx_buf(info) < 0 ) {
+		printk("%s(%d):%s Can't allocate DMA buffer memory\n",
+			__FILE__,__LINE__, info->device_name);
+		return -ENOMEM;
+	}
+
+	rx_reset_buffers( info );
+
+	return 0;
+}
+
+/* Allocate DMA buffers for the transmit and receive descriptor lists.
+ */
+static int alloc_buf_list(SLMP_INFO *info)
+{
+	unsigned int i;
+
+	/* build list in adapter shared memory */
+	info->buffer_list = info->memory_base + info->port_array[0]->last_mem_alloc;
+	info->buffer_list_phys = info->port_array[0]->last_mem_alloc;
+	info->port_array[0]->last_mem_alloc += BUFFERLISTSIZE;
+
+	memset(info->buffer_list, 0, BUFFERLISTSIZE);
+
+	/* Save virtual address pointers to the receive and */
+	/* transmit buffer lists. (Receive 1st). These pointers will */
+	/* be used by the processor to access the lists. */
+	info->rx_buf_list = (SCADESC *)info->buffer_list;
+
+	info->tx_buf_list = (SCADESC *)info->buffer_list;
+	info->tx_buf_list += info->rx_buf_count;
+
+	/* Build links for circular buffer entry lists (tx and rx)
+	 *
+	 * Note: links are physical addresses read by the SCA device
+	 * to determine the next buffer entry to use.
+	 */
+
+	for ( i = 0; i < info->rx_buf_count; i++ ) {
+		/* calculate and store physical address of this buffer entry */
+		info->rx_buf_list_ex[i].phys_entry =
+			info->buffer_list_phys + (i * sizeof(SCABUFSIZE));
+
+		/* calculate and store physical address of */
+		/* next entry in cirular list of entries */
+		info->rx_buf_list[i].next = info->buffer_list_phys;
+		if ( i < info->rx_buf_count - 1 )
+			info->rx_buf_list[i].next += (i + 1) * sizeof(SCADESC);
+
+		info->rx_buf_list[i].length = SCABUFSIZE;
+	}
+
+	for ( i = 0; i < info->tx_buf_count; i++ ) {
+		/* calculate and store physical address of this buffer entry */
+		info->tx_buf_list_ex[i].phys_entry = info->buffer_list_phys +
+			((info->rx_buf_count + i) * sizeof(SCADESC));
+
+		/* calculate and store physical address of */
+		/* next entry in cirular list of entries */
+
+		info->tx_buf_list[i].next = info->buffer_list_phys +
+			info->rx_buf_count * sizeof(SCADESC);
+
+		if ( i < info->tx_buf_count - 1 )
+			info->tx_buf_list[i].next += (i + 1) * sizeof(SCADESC);
+	}
+
+	return 0;
+}
+
+/* Allocate the frame DMA buffers used by the specified buffer list.
+ */
+static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count)
+{
+	int i;
+	unsigned long phys_addr;
+
+	for ( i = 0; i < count; i++ ) {
+		buf_list_ex[i].virt_addr = info->memory_base + info->port_array[0]->last_mem_alloc;
+		phys_addr = info->port_array[0]->last_mem_alloc;
+		info->port_array[0]->last_mem_alloc += SCABUFSIZE;
+
+		buf_list[i].buf_ptr  = (unsigned short)phys_addr;
+		buf_list[i].buf_base = (unsigned char)(phys_addr >> 16);
+	}
+
+	return 0;
+}
+
+static void free_dma_bufs(SLMP_INFO *info)
+{
+	info->buffer_list = NULL;
+	info->rx_buf_list = NULL;
+	info->tx_buf_list = NULL;
+}
+
+/* allocate buffer large enough to hold max_frame_size.
+ * This buffer is used to pass an assembled frame to the line discipline.
+ */
+static int alloc_tmp_rx_buf(SLMP_INFO *info)
+{
+	info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
+	if (info->tmp_rx_buf == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+static void free_tmp_rx_buf(SLMP_INFO *info)
+{
+	kfree(info->tmp_rx_buf);
+	info->tmp_rx_buf = NULL;
+}
+
+static int claim_resources(SLMP_INFO *info)
+{
+	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
+		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
+		info->init_error = DiagStatus_AddressConflict;
+		goto errout;
+	}
+	else
+		info->shared_mem_requested = true;
+
+	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
+		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
+		info->init_error = DiagStatus_AddressConflict;
+		goto errout;
+	}
+	else
+		info->lcr_mem_requested = true;
+
+	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
+		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
+		info->init_error = DiagStatus_AddressConflict;
+		goto errout;
+	}
+	else
+		info->sca_base_requested = true;
+
+	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
+		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
+		info->init_error = DiagStatus_AddressConflict;
+		goto errout;
+	}
+	else
+		info->sca_statctrl_requested = true;
+
+	info->memory_base = ioremap_nocache(info->phys_memory_base,
+								SCA_MEM_SIZE);
+	if (!info->memory_base) {
+		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+
+	info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE);
+	if (!info->lcr_base) {
+		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->lcr_base += info->lcr_offset;
+
+	info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE);
+	if (!info->sca_base) {
+		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->sca_base += info->sca_offset;
+
+	info->statctrl_base = ioremap_nocache(info->phys_statctrl_base,
+								PAGE_SIZE);
+	if (!info->statctrl_base) {
+		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
+		info->init_error = DiagStatus_CantAssignPciResources;
+		goto errout;
+	}
+	info->statctrl_base += info->statctrl_offset;
+
+	if ( !memory_test(info) ) {
+		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
+			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
+		info->init_error = DiagStatus_MemoryError;
+		goto errout;
+	}
+
+	return 0;
+
+errout:
+	release_resources( info );
+	return -ENODEV;
+}
+
+static void release_resources(SLMP_INFO *info)
+{
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):%s release_resources() entry\n",
+			__FILE__,__LINE__,info->device_name );
+
+	if ( info->irq_requested ) {
+		free_irq(info->irq_level, info);
+		info->irq_requested = false;
+	}
+
+	if ( info->shared_mem_requested ) {
+		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
+		info->shared_mem_requested = false;
+	}
+	if ( info->lcr_mem_requested ) {
+		release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
+		info->lcr_mem_requested = false;
+	}
+	if ( info->sca_base_requested ) {
+		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
+		info->sca_base_requested = false;
+	}
+	if ( info->sca_statctrl_requested ) {
+		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
+		info->sca_statctrl_requested = false;
+	}
+
+	if (info->memory_base){
+		iounmap(info->memory_base);
+		info->memory_base = NULL;
+	}
+
+	if (info->sca_base) {
+		iounmap(info->sca_base - info->sca_offset);
+		info->sca_base=NULL;
+	}
+
+	if (info->statctrl_base) {
+		iounmap(info->statctrl_base - info->statctrl_offset);
+		info->statctrl_base=NULL;
+	}
+
+	if (info->lcr_base){
+		iounmap(info->lcr_base - info->lcr_offset);
+		info->lcr_base = NULL;
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):%s release_resources() exit\n",
+			__FILE__,__LINE__,info->device_name );
+}
+
+/* Add the specified device instance data structure to the
+ * global linked list of devices and increment the device count.
+ */
+static void add_device(SLMP_INFO *info)
+{
+	info->next_device = NULL;
+	info->line = synclinkmp_device_count;
+	sprintf(info->device_name,"ttySLM%dp%d",info->adapter_num,info->port_num);
+
+	if (info->line < MAX_DEVICES) {
+		if (maxframe[info->line])
+			info->max_frame_size = maxframe[info->line];
+	}
+
+	synclinkmp_device_count++;
+
+	if ( !synclinkmp_device_list )
+		synclinkmp_device_list = info;
+	else {
+		SLMP_INFO *current_dev = synclinkmp_device_list;
+		while( current_dev->next_device )
+			current_dev = current_dev->next_device;
+		current_dev->next_device = info;
+	}
+
+	if ( info->max_frame_size < 4096 )
+		info->max_frame_size = 4096;
+	else if ( info->max_frame_size > 65535 )
+		info->max_frame_size = 65535;
+
+	printk( "SyncLink MultiPort %s: "
+		"Mem=(%08x %08X %08x %08X) IRQ=%d MaxFrameSize=%u\n",
+		info->device_name,
+		info->phys_sca_base,
+		info->phys_memory_base,
+		info->phys_statctrl_base,
+		info->phys_lcr_base,
+		info->irq_level,
+		info->max_frame_size );
+
+#if SYNCLINK_GENERIC_HDLC
+	hdlcdev_init(info);
+#endif
+}
+
+static const struct tty_port_operations port_ops = {
+	.carrier_raised = carrier_raised,
+	.dtr_rts = dtr_rts,
+};
+
+/* Allocate and initialize a device instance structure
+ *
+ * Return Value:	pointer to SLMP_INFO if success, otherwise NULL
+ */
+static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
+{
+	SLMP_INFO *info;
+
+	info = kzalloc(sizeof(SLMP_INFO),
+		 GFP_KERNEL);
+
+	if (!info) {
+		printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n",
+			__FILE__,__LINE__, adapter_num, port_num);
+	} else {
+		tty_port_init(&info->port);
+		info->port.ops = &port_ops;
+		info->magic = MGSL_MAGIC;
+		INIT_WORK(&info->task, bh_handler);
+		info->max_frame_size = 4096;
+		info->port.close_delay = 5*HZ/10;
+		info->port.closing_wait = 30*HZ;
+		init_waitqueue_head(&info->status_event_wait_q);
+		init_waitqueue_head(&info->event_wait_q);
+		spin_lock_init(&info->netlock);
+		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
+		info->idle_mode = HDLC_TXIDLE_FLAGS;
+		info->adapter_num = adapter_num;
+		info->port_num = port_num;
+
+		/* Copy configuration info to device instance data */
+		info->irq_level = pdev->irq;
+		info->phys_lcr_base = pci_resource_start(pdev,0);
+		info->phys_sca_base = pci_resource_start(pdev,2);
+		info->phys_memory_base = pci_resource_start(pdev,3);
+		info->phys_statctrl_base = pci_resource_start(pdev,4);
+
+		/* Because veremap only works on page boundaries we must map
+		 * a larger area than is actually implemented for the LCR
+		 * memory range. We map a full page starting at the page boundary.
+		 */
+		info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
+		info->phys_lcr_base &= ~(PAGE_SIZE-1);
+
+		info->sca_offset    = info->phys_sca_base & (PAGE_SIZE-1);
+		info->phys_sca_base &= ~(PAGE_SIZE-1);
+
+		info->statctrl_offset    = info->phys_statctrl_base & (PAGE_SIZE-1);
+		info->phys_statctrl_base &= ~(PAGE_SIZE-1);
+
+		info->bus_type = MGSL_BUS_TYPE_PCI;
+		info->irq_flags = IRQF_SHARED;
+
+		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
+		setup_timer(&info->status_timer, status_timeout,
+				(unsigned long)info);
+
+		/* Store the PCI9050 misc control register value because a flaw
+		 * in the PCI9050 prevents LCR registers from being read if
+		 * BIOS assigns an LCR base address with bit 7 set.
+		 *
+		 * Only the misc control register is accessed for which only
+		 * write access is needed, so set an initial value and change
+		 * bits to the device instance data as we write the value
+		 * to the actual misc control register.
+		 */
+		info->misc_ctrl_value = 0x087e4546;
+
+		/* initial port state is unknown - if startup errors
+		 * occur, init_error will be set to indicate the
+		 * problem. Once the port is fully initialized,
+		 * this value will be set to 0 to indicate the
+		 * port is available.
+		 */
+		info->init_error = -1;
+	}
+
+	return info;
+}
+
+static void device_init(int adapter_num, struct pci_dev *pdev)
+{
+	SLMP_INFO *port_array[SCA_MAX_PORTS];
+	int port;
+
+	/* allocate device instances for up to SCA_MAX_PORTS devices */
+	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
+		port_array[port] = alloc_dev(adapter_num,port,pdev);
+		if( port_array[port] == NULL ) {
+			for ( --port; port >= 0; --port )
+				kfree(port_array[port]);
+			return;
+		}
+	}
+
+	/* give copy of port_array to all ports and add to device list  */
+	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
+		memcpy(port_array[port]->port_array,port_array,sizeof(port_array));
+		add_device( port_array[port] );
+		spin_lock_init(&port_array[port]->lock);
+	}
+
+	/* Allocate and claim adapter resources */
+	if ( !claim_resources(port_array[0]) ) {
+
+		alloc_dma_bufs(port_array[0]);
+
+		/* copy resource information from first port to others */
+		for ( port = 1; port < SCA_MAX_PORTS; ++port ) {
+			port_array[port]->lock  = port_array[0]->lock;
+			port_array[port]->irq_level     = port_array[0]->irq_level;
+			port_array[port]->memory_base   = port_array[0]->memory_base;
+			port_array[port]->sca_base      = port_array[0]->sca_base;
+			port_array[port]->statctrl_base = port_array[0]->statctrl_base;
+			port_array[port]->lcr_base      = port_array[0]->lcr_base;
+			alloc_dma_bufs(port_array[port]);
+		}
+
+		if ( request_irq(port_array[0]->irq_level,
+					synclinkmp_interrupt,
+					port_array[0]->irq_flags,
+					port_array[0]->device_name,
+					port_array[0]) < 0 ) {
+			printk( "%s(%d):%s Cant request interrupt, IRQ=%d\n",
+				__FILE__,__LINE__,
+				port_array[0]->device_name,
+				port_array[0]->irq_level );
+		}
+		else {
+			port_array[0]->irq_requested = true;
+			adapter_test(port_array[0]);
+		}
+	}
+}
+
+static const struct tty_operations ops = {
+	.open = open,
+	.close = close,
+	.write = write,
+	.put_char = put_char,
+	.flush_chars = flush_chars,
+	.write_room = write_room,
+	.chars_in_buffer = chars_in_buffer,
+	.flush_buffer = flush_buffer,
+	.ioctl = ioctl,
+	.throttle = throttle,
+	.unthrottle = unthrottle,
+	.send_xchar = send_xchar,
+	.break_ctl = set_break,
+	.wait_until_sent = wait_until_sent,
+	.set_termios = set_termios,
+	.stop = tx_hold,
+	.start = tx_release,
+	.hangup = hangup,
+	.tiocmget = tiocmget,
+	.tiocmset = tiocmset,
+	.get_icount = get_icount,
+	.proc_fops = &synclinkmp_proc_fops,
+};
+
+
+static void synclinkmp_cleanup(void)
+{
+	int rc;
+	SLMP_INFO *info;
+	SLMP_INFO *tmp;
+
+	printk("Unloading %s %s\n", driver_name, driver_version);
+
+	if (serial_driver) {
+		if ((rc = tty_unregister_driver(serial_driver)))
+			printk("%s(%d) failed to unregister tty driver err=%d\n",
+			       __FILE__,__LINE__,rc);
+		put_tty_driver(serial_driver);
+	}
+
+	/* reset devices */
+	info = synclinkmp_device_list;
+	while(info) {
+		reset_port(info);
+		info = info->next_device;
+	}
+
+	/* release devices */
+	info = synclinkmp_device_list;
+	while(info) {
+#if SYNCLINK_GENERIC_HDLC
+		hdlcdev_exit(info);
+#endif
+		free_dma_bufs(info);
+		free_tmp_rx_buf(info);
+		if ( info->port_num == 0 ) {
+			if (info->sca_base)
+				write_reg(info, LPR, 1); /* set low power mode */
+			release_resources(info);
+		}
+		tmp = info;
+		info = info->next_device;
+		kfree(tmp);
+	}
+
+	pci_unregister_driver(&synclinkmp_pci_driver);
+}
+
+/* Driver initialization entry point.
+ */
+
+static int __init synclinkmp_init(void)
+{
+	int rc;
+
+	if (break_on_load) {
+	 	synclinkmp_get_text_ptr();
+  		BREAKPOINT();
+	}
+
+ 	printk("%s %s\n", driver_name, driver_version);
+
+	if ((rc = pci_register_driver(&synclinkmp_pci_driver)) < 0) {
+		printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
+		return rc;
+	}
+
+	serial_driver = alloc_tty_driver(128);
+	if (!serial_driver) {
+		rc = -ENOMEM;
+		goto error;
+	}
+
+	/* Initialize the tty_driver structure */
+
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "synclinkmp";
+	serial_driver->name = "ttySLM";
+	serial_driver->major = ttymajor;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver->init_termios.c_ispeed = 9600;
+	serial_driver->init_termios.c_ospeed = 9600;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+	tty_set_operations(serial_driver, &ops);
+	if ((rc = tty_register_driver(serial_driver)) < 0) {
+		printk("%s(%d):Couldn't register serial driver\n",
+			__FILE__,__LINE__);
+		put_tty_driver(serial_driver);
+		serial_driver = NULL;
+		goto error;
+	}
+
+ 	printk("%s %s, tty major#%d\n",
+		driver_name, driver_version,
+		serial_driver->major);
+
+	return 0;
+
+error:
+	synclinkmp_cleanup();
+	return rc;
+}
+
+static void __exit synclinkmp_exit(void)
+{
+	synclinkmp_cleanup();
+}
+
+module_init(synclinkmp_init);
+module_exit(synclinkmp_exit);
+
+/* Set the port for internal loopback mode.
+ * The TxCLK and RxCLK signals are generated from the BRG and
+ * the TxD is looped back to the RxD internally.
+ */
+static void enable_loopback(SLMP_INFO *info, int enable)
+{
+	if (enable) {
+		/* MD2 (Mode Register 2)
+		 * 01..00  CNCT<1..0> Channel Connection 11=Local Loopback
+		 */
+		write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) | (BIT1 + BIT0)));
+
+		/* degate external TxC clock source */
+		info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
+		write_control_reg(info);
+
+		/* RXS/TXS (Rx/Tx clock source)
+		 * 07      Reserved, must be 0
+		 * 06..04  Clock Source, 100=BRG
+		 * 03..00  Clock Divisor, 0000=1
+		 */
+		write_reg(info, RXS, 0x40);
+		write_reg(info, TXS, 0x40);
+
+	} else {
+		/* MD2 (Mode Register 2)
+	 	 * 01..00  CNCT<1..0> Channel connection, 0=normal
+		 */
+		write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) & ~(BIT1 + BIT0)));
+
+		/* RXS/TXS (Rx/Tx clock source)
+		 * 07      Reserved, must be 0
+		 * 06..04  Clock Source, 000=RxC/TxC Pin
+		 * 03..00  Clock Divisor, 0000=1
+		 */
+		write_reg(info, RXS, 0x00);
+		write_reg(info, TXS, 0x00);
+	}
+
+	/* set LinkSpeed if available, otherwise default to 2Mbps */
+	if (info->params.clock_speed)
+		set_rate(info, info->params.clock_speed);
+	else
+		set_rate(info, 3686400);
+}
+
+/* Set the baud rate register to the desired speed
+ *
+ *	data_rate	data rate of clock in bits per second
+ *			A data rate of 0 disables the AUX clock.
+ */
+static void set_rate( SLMP_INFO *info, u32 data_rate )
+{
+       	u32 TMCValue;
+       	unsigned char BRValue;
+	u32 Divisor=0;
+
+	/* fBRG = fCLK/(TMC * 2^BR)
+	 */
+	if (data_rate != 0) {
+		Divisor = 14745600/data_rate;
+		if (!Divisor)
+			Divisor = 1;
+
+		TMCValue = Divisor;
+
+		BRValue = 0;
+		if (TMCValue != 1 && TMCValue != 2) {
+			/* BRValue of 0 provides 50/50 duty cycle *only* when
+			 * TMCValue is 1 or 2. BRValue of 1 to 9 always provides
+			 * 50/50 duty cycle.
+			 */
+			BRValue = 1;
+			TMCValue >>= 1;
+		}
+
+		/* while TMCValue is too big for TMC register, divide
+		 * by 2 and increment BR exponent.
+		 */
+		for(; TMCValue > 256 && BRValue < 10; BRValue++)
+			TMCValue >>= 1;
+
+		write_reg(info, TXS,
+			(unsigned char)((read_reg(info, TXS) & 0xf0) | BRValue));
+		write_reg(info, RXS,
+			(unsigned char)((read_reg(info, RXS) & 0xf0) | BRValue));
+		write_reg(info, TMC, (unsigned char)TMCValue);
+	}
+	else {
+		write_reg(info, TXS,0);
+		write_reg(info, RXS,0);
+		write_reg(info, TMC, 0);
+	}
+}
+
+/* Disable receiver
+ */
+static void rx_stop(SLMP_INFO *info)
+{
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):%s rx_stop()\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	write_reg(info, CMD, RXRESET);
+
+	info->ie0_value &= ~RXRDYE;
+	write_reg(info, IE0, info->ie0_value);	/* disable Rx data interrupts */
+
+	write_reg(info, RXDMA + DSR, 0);	/* disable Rx DMA */
+	write_reg(info, RXDMA + DCMD, SWABORT);	/* reset/init Rx DMA */
+	write_reg(info, RXDMA + DIR, 0);	/* disable Rx DMA interrupts */
+
+	info->rx_enabled = false;
+	info->rx_overflow = false;
+}
+
+/* enable the receiver
+ */
+static void rx_start(SLMP_INFO *info)
+{
+	int i;
+
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):%s rx_start()\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	write_reg(info, CMD, RXRESET);
+
+	if ( info->params.mode == MGSL_MODE_HDLC ) {
+		/* HDLC, disabe IRQ on rxdata */
+		info->ie0_value &= ~RXRDYE;
+		write_reg(info, IE0, info->ie0_value);
+
+		/* Reset all Rx DMA buffers and program rx dma */
+		write_reg(info, RXDMA + DSR, 0);		/* disable Rx DMA */
+		write_reg(info, RXDMA + DCMD, SWABORT);	/* reset/init Rx DMA */
+
+		for (i = 0; i < info->rx_buf_count; i++) {
+			info->rx_buf_list[i].status = 0xff;
+
+			// throttle to 4 shared memory writes at a time to prevent
+			// hogging local bus (keep latency time for DMA requests low).
+			if (!(i % 4))
+				read_status_reg(info);
+		}
+		info->current_rx_buf = 0;
+
+		/* set current/1st descriptor address */
+		write_reg16(info, RXDMA + CDA,
+			info->rx_buf_list_ex[0].phys_entry);
+
+		/* set new last rx descriptor address */
+		write_reg16(info, RXDMA + EDA,
+			info->rx_buf_list_ex[info->rx_buf_count - 1].phys_entry);
+
+		/* set buffer length (shared by all rx dma data buffers) */
+		write_reg16(info, RXDMA + BFL, SCABUFSIZE);
+
+		write_reg(info, RXDMA + DIR, 0x60);	/* enable Rx DMA interrupts (EOM/BOF) */
+		write_reg(info, RXDMA + DSR, 0xf2);	/* clear Rx DMA IRQs, enable Rx DMA */
+	} else {
+		/* async, enable IRQ on rxdata */
+		info->ie0_value |= RXRDYE;
+		write_reg(info, IE0, info->ie0_value);
+	}
+
+	write_reg(info, CMD, RXENABLE);
+
+	info->rx_overflow = false;
+	info->rx_enabled = true;
+}
+
+/* Enable the transmitter and send a transmit frame if
+ * one is loaded in the DMA buffers.
+ */
+static void tx_start(SLMP_INFO *info)
+{
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):%s tx_start() tx_count=%d\n",
+			 __FILE__,__LINE__, info->device_name,info->tx_count );
+
+	if (!info->tx_enabled ) {
+		write_reg(info, CMD, TXRESET);
+		write_reg(info, CMD, TXENABLE);
+		info->tx_enabled = true;
+	}
+
+	if ( info->tx_count ) {
+
+		/* If auto RTS enabled and RTS is inactive, then assert */
+		/* RTS and set a flag indicating that the driver should */
+		/* negate RTS when the transmission completes. */
+
+		info->drop_rts_on_tx_done = false;
+
+		if (info->params.mode != MGSL_MODE_ASYNC) {
+
+			if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
+				get_signals( info );
+				if ( !(info->serial_signals & SerialSignal_RTS) ) {
+					info->serial_signals |= SerialSignal_RTS;
+					set_signals( info );
+					info->drop_rts_on_tx_done = true;
+				}
+			}
+
+			write_reg16(info, TRC0,
+				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
+
+			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
+			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
+	
+			/* set TX CDA (current descriptor address) */
+			write_reg16(info, TXDMA + CDA,
+				info->tx_buf_list_ex[0].phys_entry);
+	
+			/* set TX EDA (last descriptor address) */
+			write_reg16(info, TXDMA + EDA,
+				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
+	
+			/* enable underrun IRQ */
+			info->ie1_value &= ~IDLE;
+			info->ie1_value |= UDRN;
+			write_reg(info, IE1, info->ie1_value);
+			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
+	
+			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
+			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
+	
+			mod_timer(&info->tx_timer, jiffies +
+					msecs_to_jiffies(5000));
+		}
+		else {
+			tx_load_fifo(info);
+			/* async, enable IRQ on txdata */
+			info->ie0_value |= TXRDYE;
+			write_reg(info, IE0, info->ie0_value);
+		}
+
+		info->tx_active = true;
+	}
+}
+
+/* stop the transmitter and DMA
+ */
+static void tx_stop( SLMP_INFO *info )
+{
+	if (debug_level >= DEBUG_LEVEL_ISR)
+		printk("%s(%d):%s tx_stop()\n",
+			 __FILE__,__LINE__, info->device_name );
+
+	del_timer(&info->tx_timer);
+
+	write_reg(info, TXDMA + DSR, 0);		/* disable DMA channel */
+	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
+
+	write_reg(info, CMD, TXRESET);
+
+	info->ie1_value &= ~(UDRN + IDLE);
+	write_reg(info, IE1, info->ie1_value);	/* disable tx status interrupts */
+	write_reg(info, SR1, (unsigned char)(IDLE + UDRN));	/* clear pending */
+
+	info->ie0_value &= ~TXRDYE;
+	write_reg(info, IE0, info->ie0_value);	/* disable tx data interrupts */
+
+	info->tx_enabled = false;
+	info->tx_active = false;
+}
+
+/* Fill the transmit FIFO until the FIFO is full or
+ * there is no more data to load.
+ */
+static void tx_load_fifo(SLMP_INFO *info)
+{
+	u8 TwoBytes[2];
+
+	/* do nothing is now tx data available and no XON/XOFF pending */
+
+	if ( !info->tx_count && !info->x_char )
+		return;
+
+	/* load the Transmit FIFO until FIFOs full or all data sent */
+
+	while( info->tx_count && (read_reg(info,SR0) & BIT1) ) {
+
+		/* there is more space in the transmit FIFO and */
+		/* there is more data in transmit buffer */
+
+		if ( (info->tx_count > 1) && !info->x_char ) {
+ 			/* write 16-bits */
+			TwoBytes[0] = info->tx_buf[info->tx_get++];
+			if (info->tx_get >= info->max_frame_size)
+				info->tx_get -= info->max_frame_size;
+			TwoBytes[1] = info->tx_buf[info->tx_get++];
+			if (info->tx_get >= info->max_frame_size)
+				info->tx_get -= info->max_frame_size;
+
+			write_reg16(info, TRB, *((u16 *)TwoBytes));
+
+			info->tx_count -= 2;
+			info->icount.tx += 2;
+		} else {
+			/* only 1 byte left to transmit or 1 FIFO slot left */
+
+			if (info->x_char) {
+				/* transmit pending high priority char */
+				write_reg(info, TRB, info->x_char);
+				info->x_char = 0;
+			} else {
+				write_reg(info, TRB, info->tx_buf[info->tx_get++]);
+				if (info->tx_get >= info->max_frame_size)
+					info->tx_get -= info->max_frame_size;
+				info->tx_count--;
+			}
+			info->icount.tx++;
+		}
+	}
+}
+
+/* Reset a port to a known state
+ */
+static void reset_port(SLMP_INFO *info)
+{
+	if (info->sca_base) {
+
+		tx_stop(info);
+		rx_stop(info);
+
+		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
+		set_signals(info);
+
+		/* disable all port interrupts */
+		info->ie0_value = 0;
+		info->ie1_value = 0;
+		info->ie2_value = 0;
+		write_reg(info, IE0, info->ie0_value);
+		write_reg(info, IE1, info->ie1_value);
+		write_reg(info, IE2, info->ie2_value);
+
+		write_reg(info, CMD, CHRESET);
+	}
+}
+
+/* Reset all the ports to a known state.
+ */
+static void reset_adapter(SLMP_INFO *info)
+{
+	int i;
+
+	for ( i=0; i < SCA_MAX_PORTS; ++i) {
+		if (info->port_array[i])
+			reset_port(info->port_array[i]);
+	}
+}
+
+/* Program port for asynchronous communications.
+ */
+static void async_mode(SLMP_INFO *info)
+{
+
+  	unsigned char RegValue;
+
+	tx_stop(info);
+	rx_stop(info);
+
+	/* MD0, Mode Register 0
+	 *
+	 * 07..05  PRCTL<2..0>, Protocol Mode, 000=async
+	 * 04      AUTO, Auto-enable (RTS/CTS/DCD)
+	 * 03      Reserved, must be 0
+	 * 02      CRCCC, CRC Calculation, 0=disabled
+	 * 01..00  STOP<1..0> Stop bits (00=1,10=2)
+	 *
+	 * 0000 0000
+	 */
+	RegValue = 0x00;
+	if (info->params.stop_bits != 1)
+		RegValue |= BIT1;
+	write_reg(info, MD0, RegValue);
+
+	/* MD1, Mode Register 1
+	 *
+	 * 07..06  BRATE<1..0>, bit rate, 00=1/1 01=1/16 10=1/32 11=1/64
+	 * 05..04  TXCHR<1..0>, tx char size, 00=8 bits,01=7,10=6,11=5
+	 * 03..02  RXCHR<1..0>, rx char size
+	 * 01..00  PMPM<1..0>, Parity mode, 00=none 10=even 11=odd
+	 *
+	 * 0100 0000
+	 */
+	RegValue = 0x40;
+	switch (info->params.data_bits) {
+	case 7: RegValue |= BIT4 + BIT2; break;
+	case 6: RegValue |= BIT5 + BIT3; break;
+	case 5: RegValue |= BIT5 + BIT4 + BIT3 + BIT2; break;
+	}
+	if (info->params.parity != ASYNC_PARITY_NONE) {
+		RegValue |= BIT1;
+		if (info->params.parity == ASYNC_PARITY_ODD)
+			RegValue |= BIT0;
+	}
+	write_reg(info, MD1, RegValue);
+
+	/* MD2, Mode Register 2
+	 *
+	 * 07..02  Reserved, must be 0
+	 * 01..00  CNCT<1..0> Channel connection, 00=normal 11=local loopback
+	 *
+	 * 0000 0000
+	 */
+	RegValue = 0x00;
+	if (info->params.loopback)
+		RegValue |= (BIT1 + BIT0);
+	write_reg(info, MD2, RegValue);
+
+	/* RXS, Receive clock source
+	 *
+	 * 07      Reserved, must be 0
+	 * 06..04  RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL
+	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
+	 */
+	RegValue=BIT6;
+	write_reg(info, RXS, RegValue);
+
+	/* TXS, Transmit clock source
+	 *
+	 * 07      Reserved, must be 0
+	 * 06..04  RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock
+	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
+	 */
+	RegValue=BIT6;
+	write_reg(info, TXS, RegValue);
+
+	/* Control Register
+	 *
+	 * 6,4,2,0  CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out
+	 */
+	info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
+	write_control_reg(info);
+
+	tx_set_idle(info);
+
+	/* RRC Receive Ready Control 0
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04..00  RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte
+	 */
+	write_reg(info, RRC, 0x00);
+
+	/* TRC0 Transmit Ready Control 0
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04..00  TRC<4..0> Tx FIFO trigger active 0x10 = 16 bytes
+	 */
+	write_reg(info, TRC0, 0x10);
+
+	/* TRC1 Transmit Ready Control 1
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04..00  TRC<4..0> Tx FIFO trigger inactive 0x1e = 31 bytes (full-1)
+	 */
+	write_reg(info, TRC1, 0x1e);
+
+	/* CTL, MSCI control register
+	 *
+	 * 07..06  Reserved, set to 0
+	 * 05      UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC)
+	 * 04      IDLC, idle control, 0=mark 1=idle register
+	 * 03      BRK, break, 0=off 1 =on (async)
+	 * 02      SYNCLD, sync char load enable (BSC) 1=enabled
+	 * 01      GOP, go active on poll (LOOP mode) 1=enabled
+	 * 00      RTS, RTS output control, 0=active 1=inactive
+	 *
+	 * 0001 0001
+	 */
+	RegValue = 0x10;
+	if (!(info->serial_signals & SerialSignal_RTS))
+		RegValue |= 0x01;
+	write_reg(info, CTL, RegValue);
+
+	/* enable status interrupts */
+	info->ie0_value |= TXINTE + RXINTE;
+	write_reg(info, IE0, info->ie0_value);
+
+	/* enable break detect interrupt */
+	info->ie1_value = BRKD;
+	write_reg(info, IE1, info->ie1_value);
+
+	/* enable rx overrun interrupt */
+	info->ie2_value = OVRN;
+	write_reg(info, IE2, info->ie2_value);
+
+	set_rate( info, info->params.data_rate * 16 );
+}
+
+/* Program the SCA for HDLC communications.
+ */
+static void hdlc_mode(SLMP_INFO *info)
+{
+	unsigned char RegValue;
+	u32 DpllDivisor;
+
+	// Can't use DPLL because SCA outputs recovered clock on RxC when
+	// DPLL mode selected. This causes output contention with RxC receiver.
+	// Use of DPLL would require external hardware to disable RxC receiver
+	// when DPLL mode selected.
+	info->params.flags &= ~(HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL);
+
+	/* disable DMA interrupts */
+	write_reg(info, TXDMA + DIR, 0);
+	write_reg(info, RXDMA + DIR, 0);
+
+	/* MD0, Mode Register 0
+	 *
+	 * 07..05  PRCTL<2..0>, Protocol Mode, 100=HDLC
+	 * 04      AUTO, Auto-enable (RTS/CTS/DCD)
+	 * 03      Reserved, must be 0
+	 * 02      CRCCC, CRC Calculation, 1=enabled
+	 * 01      CRC1, CRC selection, 0=CRC-16,1=CRC-CCITT-16
+	 * 00      CRC0, CRC initial value, 1 = all 1s
+	 *
+	 * 1000 0001
+	 */
+	RegValue = 0x81;
+	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
+		RegValue |= BIT4;
+	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
+		RegValue |= BIT4;
+	if (info->params.crc_type == HDLC_CRC_16_CCITT)
+		RegValue |= BIT2 + BIT1;
+	write_reg(info, MD0, RegValue);
+
+	/* MD1, Mode Register 1
+	 *
+	 * 07..06  ADDRS<1..0>, Address detect, 00=no addr check
+	 * 05..04  TXCHR<1..0>, tx char size, 00=8 bits
+	 * 03..02  RXCHR<1..0>, rx char size, 00=8 bits
+	 * 01..00  PMPM<1..0>, Parity mode, 00=no parity
+	 *
+	 * 0000 0000
+	 */
+	RegValue = 0x00;
+	write_reg(info, MD1, RegValue);
+
+	/* MD2, Mode Register 2
+	 *
+	 * 07      NRZFM, 0=NRZ, 1=FM
+	 * 06..05  CODE<1..0> Encoding, 00=NRZ
+	 * 04..03  DRATE<1..0> DPLL Divisor, 00=8
+	 * 02      Reserved, must be 0
+	 * 01..00  CNCT<1..0> Channel connection, 0=normal
+	 *
+	 * 0000 0000
+	 */
+	RegValue = 0x00;
+	switch(info->params.encoding) {
+	case HDLC_ENCODING_NRZI:	  RegValue |= BIT5; break;
+	case HDLC_ENCODING_BIPHASE_MARK:  RegValue |= BIT7 + BIT5; break; /* aka FM1 */
+	case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT7 + BIT6; break; /* aka FM0 */
+	case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT7; break; 	/* aka Manchester */
+#if 0
+	case HDLC_ENCODING_NRZB:	       				/* not supported */
+	case HDLC_ENCODING_NRZI_MARK:          				/* not supported */
+	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: 				/* not supported */
+#endif
+	}
+	if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
+		DpllDivisor = 16;
+		RegValue |= BIT3;
+	} else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) {
+		DpllDivisor = 8;
+	} else {
+		DpllDivisor = 32;
+		RegValue |= BIT4;
+	}
+	write_reg(info, MD2, RegValue);
+
+
+	/* RXS, Receive clock source
+	 *
+	 * 07      Reserved, must be 0
+	 * 06..04  RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL
+	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
+	 */
+	RegValue=0;
+	if (info->params.flags & HDLC_FLAG_RXC_BRG)
+		RegValue |= BIT6;
+	if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+		RegValue |= BIT6 + BIT5;
+	write_reg(info, RXS, RegValue);
+
+	/* TXS, Transmit clock source
+	 *
+	 * 07      Reserved, must be 0
+	 * 06..04  RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock
+	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
+	 */
+	RegValue=0;
+	if (info->params.flags & HDLC_FLAG_TXC_BRG)
+		RegValue |= BIT6;
+	if (info->params.flags & HDLC_FLAG_TXC_DPLL)
+		RegValue |= BIT6 + BIT5;
+	write_reg(info, TXS, RegValue);
+
+	if (info->params.flags & HDLC_FLAG_RXC_DPLL)
+		set_rate(info, info->params.clock_speed * DpllDivisor);
+	else
+		set_rate(info, info->params.clock_speed);
+
+	/* GPDATA (General Purpose I/O Data Register)
+	 *
+	 * 6,4,2,0  CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out
+	 */
+	if (info->params.flags & HDLC_FLAG_TXC_BRG)
+		info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
+	else
+		info->port_array[0]->ctrlreg_value &= ~(BIT0 << (info->port_num * 2));
+	write_control_reg(info);
+
+	/* RRC Receive Ready Control 0
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04..00  RRC<4..0> Rx FIFO trigger active
+	 */
+	write_reg(info, RRC, rx_active_fifo_level);
+
+	/* TRC0 Transmit Ready Control 0
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04..00  TRC<4..0> Tx FIFO trigger active
+	 */
+	write_reg(info, TRC0, tx_active_fifo_level);
+
+	/* TRC1 Transmit Ready Control 1
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04..00  TRC<4..0> Tx FIFO trigger inactive 0x1f = 32 bytes (full)
+	 */
+	write_reg(info, TRC1, (unsigned char)(tx_negate_fifo_level - 1));
+
+	/* DMR, DMA Mode Register
+	 *
+	 * 07..05  Reserved, must be 0
+	 * 04      TMOD, Transfer Mode: 1=chained-block
+	 * 03      Reserved, must be 0
+	 * 02      NF, Number of Frames: 1=multi-frame
+	 * 01      CNTE, Frame End IRQ Counter enable: 0=disabled
+	 * 00      Reserved, must be 0
+	 *
+	 * 0001 0100
+	 */
+	write_reg(info, TXDMA + DMR, 0x14);
+	write_reg(info, RXDMA + DMR, 0x14);
+
+	/* Set chain pointer base (upper 8 bits of 24 bit addr) */
+	write_reg(info, RXDMA + CPB,
+		(unsigned char)(info->buffer_list_phys >> 16));
+
+	/* Set chain pointer base (upper 8 bits of 24 bit addr) */
+	write_reg(info, TXDMA + CPB,
+		(unsigned char)(info->buffer_list_phys >> 16));
+
+	/* enable status interrupts. other code enables/disables
+	 * the individual sources for these two interrupt classes.
+	 */
+	info->ie0_value |= TXINTE + RXINTE;
+	write_reg(info, IE0, info->ie0_value);
+
+	/* CTL, MSCI control register
+	 *
+	 * 07..06  Reserved, set to 0
+	 * 05      UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC)
+	 * 04      IDLC, idle control, 0=mark 1=idle register
+	 * 03      BRK, break, 0=off 1 =on (async)
+	 * 02      SYNCLD, sync char load enable (BSC) 1=enabled
+	 * 01      GOP, go active on poll (LOOP mode) 1=enabled
+	 * 00      RTS, RTS output control, 0=active 1=inactive
+	 *
+	 * 0001 0001
+	 */
+	RegValue = 0x10;
+	if (!(info->serial_signals & SerialSignal_RTS))
+		RegValue |= 0x01;
+	write_reg(info, CTL, RegValue);
+
+	/* preamble not supported ! */
+
+	tx_set_idle(info);
+	tx_stop(info);
+	rx_stop(info);
+
+	set_rate(info, info->params.clock_speed);
+
+	if (info->params.loopback)
+		enable_loopback(info,1);
+}
+
+/* Set the transmit HDLC idle mode
+ */
+static void tx_set_idle(SLMP_INFO *info)
+{
+	unsigned char RegValue = 0xff;
+
+	/* Map API idle mode to SCA register bits */
+	switch(info->idle_mode) {
+	case HDLC_TXIDLE_FLAGS:			RegValue = 0x7e; break;
+	case HDLC_TXIDLE_ALT_ZEROS_ONES:	RegValue = 0xaa; break;
+	case HDLC_TXIDLE_ZEROS:			RegValue = 0x00; break;
+	case HDLC_TXIDLE_ONES:			RegValue = 0xff; break;
+	case HDLC_TXIDLE_ALT_MARK_SPACE:	RegValue = 0xaa; break;
+	case HDLC_TXIDLE_SPACE:			RegValue = 0x00; break;
+	case HDLC_TXIDLE_MARK:			RegValue = 0xff; break;
+	}
+
+	write_reg(info, IDL, RegValue);
+}
+
+/* Query the adapter for the state of the V24 status (input) signals.
+ */
+static void get_signals(SLMP_INFO *info)
+{
+	u16 status = read_reg(info, SR3);
+	u16 gpstatus = read_status_reg(info);
+	u16 testbit;
+
+	/* clear all serial signals except DTR and RTS */
+	info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
+
+	/* set serial signal bits to reflect MISR */
+
+	if (!(status & BIT3))
+		info->serial_signals |= SerialSignal_CTS;
+
+	if ( !(status & BIT2))
+		info->serial_signals |= SerialSignal_DCD;
+
+	testbit = BIT1 << (info->port_num * 2); // Port 0..3 RI is GPDATA<1,3,5,7>
+	if (!(gpstatus & testbit))
+		info->serial_signals |= SerialSignal_RI;
+
+	testbit = BIT0 << (info->port_num * 2); // Port 0..3 DSR is GPDATA<0,2,4,6>
+	if (!(gpstatus & testbit))
+		info->serial_signals |= SerialSignal_DSR;
+}
+
+/* Set the state of DTR and RTS based on contents of
+ * serial_signals member of device context.
+ */
+static void set_signals(SLMP_INFO *info)
+{
+	unsigned char RegValue;
+	u16 EnableBit;
+
+	RegValue = read_reg(info, CTL);
+	if (info->serial_signals & SerialSignal_RTS)
+		RegValue &= ~BIT0;
+	else
+		RegValue |= BIT0;
+	write_reg(info, CTL, RegValue);
+
+	// Port 0..3 DTR is ctrl reg <1,3,5,7>
+	EnableBit = BIT1 << (info->port_num*2);
+	if (info->serial_signals & SerialSignal_DTR)
+		info->port_array[0]->ctrlreg_value &= ~EnableBit;
+	else
+		info->port_array[0]->ctrlreg_value |= EnableBit;
+	write_control_reg(info);
+}
+
+/*******************/
+/* DMA Buffer Code */
+/*******************/
+
+/* Set the count for all receive buffers to SCABUFSIZE
+ * and set the current buffer to the first buffer. This effectively
+ * makes all buffers free and discards any data in buffers.
+ */
+static void rx_reset_buffers(SLMP_INFO *info)
+{
+	rx_free_frame_buffers(info, 0, info->rx_buf_count - 1);
+}
+
+/* Free the buffers used by a received frame
+ *
+ * info   pointer to device instance data
+ * first  index of 1st receive buffer of frame
+ * last   index of last receive buffer of frame
+ */
+static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last)
+{
+	bool done = false;
+
+	while(!done) {
+	        /* reset current buffer for reuse */
+		info->rx_buf_list[first].status = 0xff;
+
+	        if (first == last) {
+	                done = true;
+	                /* set new last rx descriptor address */
+			write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry);
+	        }
+
+	        first++;
+		if (first == info->rx_buf_count)
+			first = 0;
+	}
+
+	/* set current buffer to next buffer after last buffer of frame */
+	info->current_rx_buf = first;
+}
+
+/* Return a received frame from the receive DMA buffers.
+ * Only frames received without errors are returned.
+ *
+ * Return Value:	true if frame returned, otherwise false
+ */
+static bool rx_get_frame(SLMP_INFO *info)
+{
+	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
+	unsigned short status;
+	unsigned int framesize = 0;
+	bool ReturnCode = false;
+	unsigned long flags;
+	struct tty_struct *tty = info->port.tty;
+	unsigned char addr_field = 0xff;
+   	SCADESC *desc;
+	SCADESC_EX *desc_ex;
+
+CheckAgain:
+	/* assume no frame returned, set zero length */
+	framesize = 0;
+	addr_field = 0xff;
+
+	/*
+	 * current_rx_buf points to the 1st buffer of the next available
+	 * receive frame. To find the last buffer of the frame look for
+	 * a non-zero status field in the buffer entries. (The status
+	 * field is set by the 16C32 after completing a receive frame.
+	 */
+	StartIndex = EndIndex = info->current_rx_buf;
+
+	for ( ;; ) {
+		desc = &info->rx_buf_list[EndIndex];
+		desc_ex = &info->rx_buf_list_ex[EndIndex];
+
+		if (desc->status == 0xff)
+			goto Cleanup;	/* current desc still in use, no frames available */
+
+		if (framesize == 0 && info->params.addr_filter != 0xff)
+			addr_field = desc_ex->virt_addr[0];
+
+		framesize += desc->length;
+
+		/* Status != 0 means last buffer of frame */
+		if (desc->status)
+			break;
+
+		EndIndex++;
+		if (EndIndex == info->rx_buf_count)
+			EndIndex = 0;
+
+		if (EndIndex == info->current_rx_buf) {
+			/* all buffers have been 'used' but none mark	   */
+			/* the end of a frame. Reset buffers and receiver. */
+			if ( info->rx_enabled ){
+				spin_lock_irqsave(&info->lock,flags);
+				rx_start(info);
+				spin_unlock_irqrestore(&info->lock,flags);
+			}
+			goto Cleanup;
+		}
+
+	}
+
+	/* check status of receive frame */
+
+	/* frame status is byte stored after frame data
+	 *
+	 * 7 EOM (end of msg), 1 = last buffer of frame
+	 * 6 Short Frame, 1 = short frame
+	 * 5 Abort, 1 = frame aborted
+	 * 4 Residue, 1 = last byte is partial
+	 * 3 Overrun, 1 = overrun occurred during frame reception
+	 * 2 CRC,     1 = CRC error detected
+	 *
+	 */
+	status = desc->status;
+
+	/* ignore CRC bit if not using CRC (bit is undefined) */
+	/* Note:CRC is not save to data buffer */
+	if (info->params.crc_type == HDLC_CRC_NONE)
+		status &= ~BIT2;
+
+	if (framesize == 0 ||
+		 (addr_field != 0xff && addr_field != info->params.addr_filter)) {
+		/* discard 0 byte frames, this seems to occur sometime
+		 * when remote is idling flags.
+		 */
+		rx_free_frame_buffers(info, StartIndex, EndIndex);
+		goto CheckAgain;
+	}
+
+	if (framesize < 2)
+		status |= BIT6;
+
+	if (status & (BIT6+BIT5+BIT3+BIT2)) {
+		/* received frame has errors,
+		 * update counts and mark frame size as 0
+		 */
+		if (status & BIT6)
+			info->icount.rxshort++;
+		else if (status & BIT5)
+			info->icount.rxabort++;
+		else if (status & BIT3)
+			info->icount.rxover++;
+		else
+			info->icount.rxcrc++;
+
+		framesize = 0;
+#if SYNCLINK_GENERIC_HDLC
+		{
+			info->netdev->stats.rx_errors++;
+			info->netdev->stats.rx_frame_errors++;
+		}
+#endif
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_BH )
+		printk("%s(%d):%s rx_get_frame() status=%04X size=%d\n",
+			__FILE__,__LINE__,info->device_name,status,framesize);
+
+	if ( debug_level >= DEBUG_LEVEL_DATA )
+		trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr,
+			min_t(int, framesize,SCABUFSIZE),0);
+
+	if (framesize) {
+		if (framesize > info->max_frame_size)
+			info->icount.rxlong++;
+		else {
+			/* copy dma buffer(s) to contiguous intermediate buffer */
+			int copy_count = framesize;
+			int index = StartIndex;
+			unsigned char *ptmp = info->tmp_rx_buf;
+			info->tmp_rx_buf_count = framesize;
+
+			info->icount.rxok++;
+
+			while(copy_count) {
+				int partial_count = min(copy_count,SCABUFSIZE);
+				memcpy( ptmp,
+					info->rx_buf_list_ex[index].virt_addr,
+					partial_count );
+				ptmp += partial_count;
+				copy_count -= partial_count;
+
+				if ( ++index == info->rx_buf_count )
+					index = 0;
+			}
+
+#if SYNCLINK_GENERIC_HDLC
+			if (info->netcount)
+				hdlcdev_rx(info,info->tmp_rx_buf,framesize);
+			else
+#endif
+				ldisc_receive_buf(tty,info->tmp_rx_buf,
+						  info->flag_buf, framesize);
+		}
+	}
+	/* Free the buffers used by this frame. */
+	rx_free_frame_buffers( info, StartIndex, EndIndex );
+
+	ReturnCode = true;
+
+Cleanup:
+	if ( info->rx_enabled && info->rx_overflow ) {
+		/* Receiver is enabled, but needs to restarted due to
+		 * rx buffer overflow. If buffers are empty, restart receiver.
+		 */
+		if (info->rx_buf_list[EndIndex].status == 0xff) {
+			spin_lock_irqsave(&info->lock,flags);
+			rx_start(info);
+			spin_unlock_irqrestore(&info->lock,flags);
+		}
+	}
+
+	return ReturnCode;
+}
+
+/* load the transmit DMA buffer with data
+ */
+static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
+{
+	unsigned short copy_count;
+	unsigned int i = 0;
+	SCADESC *desc;
+	SCADESC_EX *desc_ex;
+
+	if ( debug_level >= DEBUG_LEVEL_DATA )
+		trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1);
+
+	/* Copy source buffer to one or more DMA buffers, starting with
+	 * the first transmit dma buffer.
+	 */
+	for(i=0;;)
+	{
+		copy_count = min_t(unsigned short,count,SCABUFSIZE);
+
+		desc = &info->tx_buf_list[i];
+		desc_ex = &info->tx_buf_list_ex[i];
+
+		load_pci_memory(info, desc_ex->virt_addr,buf,copy_count);
+
+		desc->length = copy_count;
+		desc->status = 0;
+
+		buf += copy_count;
+		count -= copy_count;
+
+		if (!count)
+			break;
+
+		i++;
+		if (i >= info->tx_buf_count)
+			i = 0;
+	}
+
+	info->tx_buf_list[i].status = 0x81;	/* set EOM and EOT status */
+	info->last_tx_buf = ++i;
+}
+
+static bool register_test(SLMP_INFO *info)
+{
+	static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
+	static unsigned int count = ARRAY_SIZE(testval);
+	unsigned int i;
+	bool rc = true;
+	unsigned long flags;
+
+	spin_lock_irqsave(&info->lock,flags);
+	reset_port(info);
+
+	/* assume failure */
+	info->init_error = DiagStatus_AddressFailure;
+
+	/* Write bit patterns to various registers but do it out of */
+	/* sync, then read back and verify values. */
+
+	for (i = 0 ; i < count ; i++) {
+		write_reg(info, TMC, testval[i]);
+		write_reg(info, IDL, testval[(i+1)%count]);
+		write_reg(info, SA0, testval[(i+2)%count]);
+		write_reg(info, SA1, testval[(i+3)%count]);
+
+		if ( (read_reg(info, TMC) != testval[i]) ||
+			  (read_reg(info, IDL) != testval[(i+1)%count]) ||
+			  (read_reg(info, SA0) != testval[(i+2)%count]) ||
+			  (read_reg(info, SA1) != testval[(i+3)%count]) )
+		{
+			rc = false;
+			break;
+		}
+	}
+
+	reset_port(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return rc;
+}
+
+static bool irq_test(SLMP_INFO *info)
+{
+	unsigned long timeout;
+	unsigned long flags;
+
+	unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
+
+	spin_lock_irqsave(&info->lock,flags);
+	reset_port(info);
+
+	/* assume failure */
+	info->init_error = DiagStatus_IrqFailure;
+	info->irq_occurred = false;
+
+	/* setup timer0 on SCA0 to interrupt */
+
+	/* IER2<7..4> = timer<3..0> interrupt enables (1=enabled) */
+	write_reg(info, IER2, (unsigned char)((info->port_num & 1) ? BIT6 : BIT4));
+
+	write_reg(info, (unsigned char)(timer + TEPR), 0);	/* timer expand prescale */
+	write_reg16(info, (unsigned char)(timer + TCONR), 1);	/* timer constant */
+
+
+	/* TMCS, Timer Control/Status Register
+	 *
+	 * 07      CMF, Compare match flag (read only) 1=match
+	 * 06      ECMI, CMF Interrupt Enable: 1=enabled
+	 * 05      Reserved, must be 0
+	 * 04      TME, Timer Enable
+	 * 03..00  Reserved, must be 0
+	 *
+	 * 0101 0000
+	 */
+	write_reg(info, (unsigned char)(timer + TMCS), 0x50);
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	timeout=100;
+	while( timeout-- && !info->irq_occurred ) {
+		msleep_interruptible(10);
+	}
+
+	spin_lock_irqsave(&info->lock,flags);
+	reset_port(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	return info->irq_occurred;
+}
+
+/* initialize individual SCA device (2 ports)
+ */
+static bool sca_init(SLMP_INFO *info)
+{
+	/* set wait controller to single mem partition (low), no wait states */
+	write_reg(info, PABR0, 0);	/* wait controller addr boundary 0 */
+	write_reg(info, PABR1, 0);	/* wait controller addr boundary 1 */
+	write_reg(info, WCRL, 0);	/* wait controller low range */
+	write_reg(info, WCRM, 0);	/* wait controller mid range */
+	write_reg(info, WCRH, 0);	/* wait controller high range */
+
+	/* DPCR, DMA Priority Control
+	 *
+	 * 07..05  Not used, must be 0
+	 * 04      BRC, bus release condition: 0=all transfers complete
+	 * 03      CCC, channel change condition: 0=every cycle
+	 * 02..00  PR<2..0>, priority 100=round robin
+	 *
+	 * 00000100 = 0x04
+	 */
+	write_reg(info, DPCR, dma_priority);
+
+	/* DMA Master Enable, BIT7: 1=enable all channels */
+	write_reg(info, DMER, 0x80);
+
+	/* enable all interrupt classes */
+	write_reg(info, IER0, 0xff);	/* TxRDY,RxRDY,TxINT,RxINT (ports 0-1) */
+	write_reg(info, IER1, 0xff);	/* DMIB,DMIA (channels 0-3) */
+	write_reg(info, IER2, 0xf0);	/* TIRQ (timers 0-3) */
+
+	/* ITCR, interrupt control register
+	 * 07      IPC, interrupt priority, 0=MSCI->DMA
+	 * 06..05  IAK<1..0>, Acknowledge cycle, 00=non-ack cycle
+	 * 04      VOS, Vector Output, 0=unmodified vector
+	 * 03..00  Reserved, must be 0
+	 */
+	write_reg(info, ITCR, 0);
+
+	return true;
+}
+
+/* initialize adapter hardware
+ */
+static bool init_adapter(SLMP_INFO *info)
+{
+	int i;
+
+	/* Set BIT30 of Local Control Reg 0x50 to reset SCA */
+	volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
+	u32 readval;
+
+	info->misc_ctrl_value |= BIT30;
+	*MiscCtrl = info->misc_ctrl_value;
+
+	/*
+	 * Force at least 170ns delay before clearing
+	 * reset bit. Each read from LCR takes at least
+	 * 30ns so 10 times for 300ns to be safe.
+	 */
+	for(i=0;i<10;i++)
+		readval = *MiscCtrl;
+
+	info->misc_ctrl_value &= ~BIT30;
+	*MiscCtrl = info->misc_ctrl_value;
+
+	/* init control reg (all DTRs off, all clksel=input) */
+	info->ctrlreg_value = 0xaa;
+	write_control_reg(info);
+
+	{
+		volatile u32 *LCR1BRDR = (u32 *)(info->lcr_base + 0x2c);
+		lcr1_brdr_value &= ~(BIT5 + BIT4 + BIT3);
+
+		switch(read_ahead_count)
+		{
+		case 16:
+			lcr1_brdr_value |= BIT5 + BIT4 + BIT3;
+			break;
+		case 8:
+			lcr1_brdr_value |= BIT5 + BIT4;
+			break;
+		case 4:
+			lcr1_brdr_value |= BIT5 + BIT3;
+			break;
+		case 0:
+			lcr1_brdr_value |= BIT5;
+			break;
+		}
+
+		*LCR1BRDR = lcr1_brdr_value;
+		*MiscCtrl = misc_ctrl_value;
+	}
+
+	sca_init(info->port_array[0]);
+	sca_init(info->port_array[2]);
+
+	return true;
+}
+
+/* Loopback an HDLC frame to test the hardware
+ * interrupt and DMA functions.
+ */
+static bool loopback_test(SLMP_INFO *info)
+{
+#define TESTFRAMESIZE 20
+
+	unsigned long timeout;
+	u16 count = TESTFRAMESIZE;
+	unsigned char buf[TESTFRAMESIZE];
+	bool rc = false;
+	unsigned long flags;
+
+	struct tty_struct *oldtty = info->port.tty;
+	u32 speed = info->params.clock_speed;
+
+	info->params.clock_speed = 3686400;
+	info->port.tty = NULL;
+
+	/* assume failure */
+	info->init_error = DiagStatus_DmaFailure;
+
+	/* build and send transmit frame */
+	for (count = 0; count < TESTFRAMESIZE;++count)
+		buf[count] = (unsigned char)count;
+
+	memset(info->tmp_rx_buf,0,TESTFRAMESIZE);
+
+	/* program hardware for HDLC and enabled receiver */
+	spin_lock_irqsave(&info->lock,flags);
+	hdlc_mode(info);
+	enable_loopback(info,1);
+       	rx_start(info);
+	info->tx_count = count;
+	tx_load_dma_buffer(info,buf,count);
+	tx_start(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	/* wait for receive complete */
+	/* Set a timeout for waiting for interrupt. */
+	for ( timeout = 100; timeout; --timeout ) {
+		msleep_interruptible(10);
+
+		if (rx_get_frame(info)) {
+			rc = true;
+			break;
+		}
+	}
+
+	/* verify received frame length and contents */
+	if (rc &&
+	    ( info->tmp_rx_buf_count != count ||
+	      memcmp(buf, info->tmp_rx_buf,count))) {
+		rc = false;
+	}
+
+	spin_lock_irqsave(&info->lock,flags);
+	reset_adapter(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	info->params.clock_speed = speed;
+	info->port.tty = oldtty;
+
+	return rc;
+}
+
+/* Perform diagnostics on hardware
+ */
+static int adapter_test( SLMP_INFO *info )
+{
+	unsigned long flags;
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):Testing device %s\n",
+			__FILE__,__LINE__,info->device_name );
+
+	spin_lock_irqsave(&info->lock,flags);
+	init_adapter(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	info->port_array[0]->port_count = 0;
+
+	if ( register_test(info->port_array[0]) &&
+		register_test(info->port_array[1])) {
+
+		info->port_array[0]->port_count = 2;
+
+		if ( register_test(info->port_array[2]) &&
+			register_test(info->port_array[3]) )
+			info->port_array[0]->port_count += 2;
+	}
+	else {
+		printk( "%s(%d):Register test failure for device %s Addr=%08lX\n",
+			__FILE__,__LINE__,info->device_name, (unsigned long)(info->phys_sca_base));
+		return -ENODEV;
+	}
+
+	if ( !irq_test(info->port_array[0]) ||
+		!irq_test(info->port_array[1]) ||
+		 (info->port_count == 4 && !irq_test(info->port_array[2])) ||
+		 (info->port_count == 4 && !irq_test(info->port_array[3]))) {
+		printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",
+			__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );
+		return -ENODEV;
+	}
+
+	if (!loopback_test(info->port_array[0]) ||
+		!loopback_test(info->port_array[1]) ||
+		 (info->port_count == 4 && !loopback_test(info->port_array[2])) ||
+		 (info->port_count == 4 && !loopback_test(info->port_array[3]))) {
+		printk( "%s(%d):DMA test failure for device %s\n",
+			__FILE__,__LINE__,info->device_name);
+		return -ENODEV;
+	}
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):device %s passed diagnostics\n",
+			__FILE__,__LINE__,info->device_name );
+
+	info->port_array[0]->init_error = 0;
+	info->port_array[1]->init_error = 0;
+	if ( info->port_count > 2 ) {
+		info->port_array[2]->init_error = 0;
+		info->port_array[3]->init_error = 0;
+	}
+
+	return 0;
+}
+
+/* Test the shared memory on a PCI adapter.
+ */
+static bool memory_test(SLMP_INFO *info)
+{
+	static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
+		0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
+	unsigned long count = ARRAY_SIZE(testval);
+	unsigned long i;
+	unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long);
+	unsigned long * addr = (unsigned long *)info->memory_base;
+
+	/* Test data lines with test pattern at one location. */
+
+	for ( i = 0 ; i < count ; i++ ) {
+		*addr = testval[i];
+		if ( *addr != testval[i] )
+			return false;
+	}
+
+	/* Test address lines with incrementing pattern over */
+	/* entire address range. */
+
+	for ( i = 0 ; i < limit ; i++ ) {
+		*addr = i * 4;
+		addr++;
+	}
+
+	addr = (unsigned long *)info->memory_base;
+
+	for ( i = 0 ; i < limit ; i++ ) {
+		if ( *addr != i * 4 )
+			return false;
+		addr++;
+	}
+
+	memset( info->memory_base, 0, SCA_MEM_SIZE );
+	return true;
+}
+
+/* Load data into PCI adapter shared memory.
+ *
+ * The PCI9050 releases control of the local bus
+ * after completing the current read or write operation.
+ *
+ * While the PCI9050 write FIFO not empty, the
+ * PCI9050 treats all of the writes as a single transaction
+ * and does not release the bus. This causes DMA latency problems
+ * at high speeds when copying large data blocks to the shared memory.
+ *
+ * This function breaks a write into multiple transations by
+ * interleaving a read which flushes the write FIFO and 'completes'
+ * the write transation. This allows any pending DMA request to gain control
+ * of the local bus in a timely fasion.
+ */
+static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count)
+{
+	/* A load interval of 16 allows for 4 32-bit writes at */
+	/* 136ns each for a maximum latency of 542ns on the local bus.*/
+
+	unsigned short interval = count / sca_pci_load_interval;
+	unsigned short i;
+
+	for ( i = 0 ; i < interval ; i++ )
+	{
+		memcpy(dest, src, sca_pci_load_interval);
+		read_status_reg(info);
+		dest += sca_pci_load_interval;
+		src += sca_pci_load_interval;
+	}
+
+	memcpy(dest, src, count % sca_pci_load_interval);
+}
+
+static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit)
+{
+	int i;
+	int linecount;
+	if (xmit)
+		printk("%s tx data:\n",info->device_name);
+	else
+		printk("%s rx data:\n",info->device_name);
+
+	while(count) {
+		if (count > 16)
+			linecount = 16;
+		else
+			linecount = count;
+
+		for(i=0;i<linecount;i++)
+			printk("%02X ",(unsigned char)data[i]);
+		for(;i<17;i++)
+			printk("   ");
+		for(i=0;i<linecount;i++) {
+			if (data[i]>=040 && data[i]<=0176)
+				printk("%c",data[i]);
+			else
+				printk(".");
+		}
+		printk("\n");
+
+		data  += linecount;
+		count -= linecount;
+	}
+}	/* end of trace_block() */
+
+/* called when HDLC frame times out
+ * update stats and do tx completion processing
+ */
+static void tx_timeout(unsigned long context)
+{
+	SLMP_INFO *info = (SLMP_INFO*)context;
+	unsigned long flags;
+
+	if ( debug_level >= DEBUG_LEVEL_INFO )
+		printk( "%s(%d):%s tx_timeout()\n",
+			__FILE__,__LINE__,info->device_name);
+	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
+		info->icount.txtimeout++;
+	}
+	spin_lock_irqsave(&info->lock,flags);
+	info->tx_active = false;
+	info->tx_count = info->tx_put = info->tx_get = 0;
+
+	spin_unlock_irqrestore(&info->lock,flags);
+
+#if SYNCLINK_GENERIC_HDLC
+	if (info->netcount)
+		hdlcdev_tx_done(info);
+	else
+#endif
+		bh_transmit(info);
+}
+
+/* called to periodically check the DSR/RI modem signal input status
+ */
+static void status_timeout(unsigned long context)
+{
+	u16 status = 0;
+	SLMP_INFO *info = (SLMP_INFO*)context;
+	unsigned long flags;
+	unsigned char delta;
+
+
+	spin_lock_irqsave(&info->lock,flags);
+	get_signals(info);
+	spin_unlock_irqrestore(&info->lock,flags);
+
+	/* check for DSR/RI state change */
+
+	delta = info->old_signals ^ info->serial_signals;
+	info->old_signals = info->serial_signals;
+
+	if (delta & SerialSignal_DSR)
+		status |= MISCSTATUS_DSR_LATCHED|(info->serial_signals&SerialSignal_DSR);
+
+	if (delta & SerialSignal_RI)
+		status |= MISCSTATUS_RI_LATCHED|(info->serial_signals&SerialSignal_RI);
+
+	if (delta & SerialSignal_DCD)
+		status |= MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD);
+
+	if (delta & SerialSignal_CTS)
+		status |= MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS);
+
+	if (status)
+		isr_io_pin(info,status);
+
+	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
+}
+
+
+/* Register Access Routines -
+ * All registers are memory mapped
+ */
+#define CALC_REGADDR() \
+	unsigned char * RegAddr = (unsigned char*)(info->sca_base + Addr); \
+	if (info->port_num > 1) \
+		RegAddr += 256;	    		/* port 0-1 SCA0, 2-3 SCA1 */ \
+	if ( info->port_num & 1) { \
+		if (Addr > 0x7f) \
+			RegAddr += 0x40;	/* DMA access */ \
+		else if (Addr > 0x1f && Addr < 0x60) \
+			RegAddr += 0x20;	/* MSCI access */ \
+	}
+
+
+static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr)
+{
+	CALC_REGADDR();
+	return *RegAddr;
+}
+static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value)
+{
+	CALC_REGADDR();
+	*RegAddr = Value;
+}
+
+static u16 read_reg16(SLMP_INFO * info, unsigned char Addr)
+{
+	CALC_REGADDR();
+	return *((u16 *)RegAddr);
+}
+
+static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value)
+{
+	CALC_REGADDR();
+	*((u16 *)RegAddr) = Value;
+}
+
+static unsigned char read_status_reg(SLMP_INFO * info)
+{
+	unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
+	return *RegAddr;
+}
+
+static void write_control_reg(SLMP_INFO * info)
+{
+	unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
+	*RegAddr = info->port_array[0]->ctrlreg_value;
+}
+
+
+static int __devinit synclinkmp_init_one (struct pci_dev *dev,
+					  const struct pci_device_id *ent)
+{
+	if (pci_enable_device(dev)) {
+		printk("error enabling pci device %p\n", dev);
+		return -EIO;
+	}
+	device_init( ++synclinkmp_adapter_count, dev );
+	return 0;
+}
+
+static void __devexit synclinkmp_remove_one (struct pci_dev *dev)
+{
+}
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index f64582b..7c58669 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -95,8 +95,10 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
 {
 	if (buf->valid == 0)
 		return;
-	if (audit_enabled == 0)
+	if (audit_enabled == 0) {
+		buf->valid = 0;
 		return;
+	}
 	tty_audit_log("tty", tsk, loginuid, sessionid, buf->major, buf->minor,
 		      buf->data, buf->valid);
 	buf->valid = 0;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index d8210ca..b945121 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -322,7 +322,7 @@ void tty_schedule_flip(struct tty_struct *tty)
 	if (tty->buf.tail != NULL)
 		tty->buf.tail->commit = tty->buf.tail->used;
 	spin_unlock_irqrestore(&tty->buf.lock, flags);
-	schedule_delayed_work(&tty->buf.work, 1);
+	schedule_work(&tty->buf.work);
 }
 EXPORT_SYMBOL(tty_schedule_flip);
 
@@ -402,7 +402,7 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
 static void flush_to_ldisc(struct work_struct *work)
 {
 	struct tty_struct *tty =
-		container_of(work, struct tty_struct, buf.work.work);
+		container_of(work, struct tty_struct, buf.work);
 	unsigned long 	flags;
 	struct tty_ldisc *disc;
 
@@ -443,7 +443,7 @@ static void flush_to_ldisc(struct work_struct *work)
 			if (test_bit(TTY_FLUSHPENDING, &tty->flags))
 				break;
 			if (!tty->receive_room || seen_tail) {
-				schedule_delayed_work(&tty->buf.work, 1);
+				schedule_work(&tty->buf.work);
 				break;
 			}
 			if (count > tty->receive_room)
@@ -481,7 +481,7 @@ static void flush_to_ldisc(struct work_struct *work)
  */
 void tty_flush_to_ldisc(struct tty_struct *tty)
 {
-	flush_delayed_work(&tty->buf.work);
+	flush_work(&tty->buf.work);
 }
 
 /**
@@ -506,9 +506,9 @@ void tty_flip_buffer_push(struct tty_struct *tty)
 	spin_unlock_irqrestore(&tty->buf.lock, flags);
 
 	if (tty->low_latency)
-		flush_to_ldisc(&tty->buf.work.work);
+		flush_to_ldisc(&tty->buf.work);
 	else
-		schedule_delayed_work(&tty->buf.work, 1);
+		schedule_work(&tty->buf.work);
 }
 EXPORT_SYMBOL(tty_flip_buffer_push);
 
@@ -529,6 +529,6 @@ void tty_buffer_init(struct tty_struct *tty)
 	tty->buf.tail = NULL;
 	tty->buf.free = NULL;
 	tty->buf.memory_used = 0;
-	INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc);
+	INIT_WORK(&tty->buf.work, flush_to_ldisc);
 }
 
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 0065da4..936a4ea 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -90,7 +90,6 @@
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/smp_lock.h>
 #include <linux/device.h>
 #include <linux/wait.h>
 #include <linux/bitops.h>
@@ -2465,12 +2464,12 @@ out:
  *	Locking: none (up to the driver)
  */
 
-static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
+static int tty_tiocmget(struct tty_struct *tty, int __user *p)
 {
 	int retval = -EINVAL;
 
 	if (tty->ops->tiocmget) {
-		retval = tty->ops->tiocmget(tty, file);
+		retval = tty->ops->tiocmget(tty);
 
 		if (retval >= 0)
 			retval = put_user(retval, p);
@@ -2481,7 +2480,6 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
 /**
  *	tty_tiocmset		-	set modem status
  *	@tty: tty device
- *	@file: user file pointer
  *	@cmd: command - clear bits, set bits or set all
  *	@p: pointer to desired bits
  *
@@ -2491,7 +2489,7 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
  *	Locking: none (up to the driver)
  */
 
-static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
+static int tty_tiocmset(struct tty_struct *tty, unsigned int cmd,
 	     unsigned __user *p)
 {
 	int retval;
@@ -2518,7 +2516,7 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
 	}
 	set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
 	clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
-	return tty->ops->tiocmset(tty, file, set, clear);
+	return tty->ops->tiocmset(tty, set, clear);
 }
 
 static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
@@ -2627,6 +2625,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return put_user(tty->ldisc->ops->num, (int __user *)p);
 	case TIOCSETD:
 		return tiocsetd(tty, p);
+	case TIOCVHANGUP:
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+		tty_vhangup(tty);
+		return 0;
 	case TIOCGDEV:
 	{
 		unsigned int ret = new_encode_dev(tty_devnum(real_tty));
@@ -2655,11 +2658,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		return send_break(tty, arg ? arg*100 : 250);
 
 	case TIOCMGET:
-		return tty_tiocmget(tty, file, p);
+		return tty_tiocmget(tty, p);
 	case TIOCMSET:
 	case TIOCMBIC:
 	case TIOCMBIS:
-		return tty_tiocmset(tty, file, cmd, p);
+		return tty_tiocmset(tty, cmd, p);
 	case TIOCGICOUNT:
 		retval = tty_tiocgicount(tty, p);
 		/* For the moment allow fall through to the old method */
@@ -2677,7 +2680,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		break;
 	}
 	if (tty->ops->ioctl) {
-		retval = (tty->ops->ioctl)(tty, file, cmd, arg);
+		retval = (tty->ops->ioctl)(tty, cmd, arg);
 		if (retval != -ENOIOCTLCMD)
 			return retval;
 	}
@@ -2705,7 +2708,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
 		return -EINVAL;
 
 	if (tty->ops->compat_ioctl) {
-		retval = (tty->ops->compat_ioctl)(tty, file, cmd, arg);
+		retval = (tty->ops->compat_ioctl)(tty, cmd, arg);
 		if (retval != -ENOIOCTLCMD)
 			return retval;
 	}
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 0c18899..1a1135d 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -486,7 +486,7 @@ int tty_termios_hw_change(struct ktermios *a, struct ktermios *b)
 EXPORT_SYMBOL(tty_termios_hw_change);
 
 /**
- *	change_termios		-	update termios values
+ *	tty_set_termios		-	update termios values
  *	@tty: tty to update
  *	@new_termios: desired new value
  *
@@ -497,7 +497,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
  *	Locking: termios_mutex
  */
 
-static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
+int tty_set_termios(struct tty_struct *tty, struct ktermios *new_termios)
 {
 	struct ktermios old_termios;
 	struct tty_ldisc *ld;
@@ -553,7 +553,9 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
 		tty_ldisc_deref(ld);
 	}
 	mutex_unlock(&tty->termios_mutex);
+	return 0;
 }
+EXPORT_SYMBOL_GPL(tty_set_termios);
 
 /**
  *	set_termios		-	set termios values for a tty
@@ -562,7 +564,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
  *	@opt: option information
  *
  *	Helper function to prepare termios data and run necessary other
- *	functions before using change_termios to do the actual changes.
+ *	functions before using tty_set_termios to do the actual changes.
  *
  *	Locking:
  *		Called functions take ldisc and termios_mutex locks
@@ -620,7 +622,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
 			return -EINTR;
 	}
 
-	change_termios(tty, &tmp_termios);
+	tty_set_termios(tty, &tmp_termios);
 
 	/* FIXME: Arguably if tmp_termios == tty->termios AND the
 	   actual requested termios was not tmp_termios then we may
@@ -797,7 +799,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
 						termios.c_ospeed);
 #endif
 	mutex_unlock(&tty->termios_mutex);
-	change_termios(tty, &termios);
+	tty_set_termios(tty, &termios);
 	return 0;
 }
 #endif
@@ -951,6 +953,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
 	int ret = 0;
 	struct ktermios kterm;
 
+	BUG_ON(file == NULL);
+
 	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver->subtype == PTY_TYPE_MASTER)
 		real_tty = tty->link;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 4214d58..e19e136 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -34,8 +34,6 @@
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 
-#include <linux/smp_lock.h>	/* For the moment */
-
 #include <linux/kmod.h>
 #include <linux/nsproxy.h>
 
@@ -531,7 +529,20 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 static int tty_ldisc_halt(struct tty_struct *tty)
 {
 	clear_bit(TTY_LDISC, &tty->flags);
-	return cancel_delayed_work_sync(&tty->buf.work);
+	return cancel_work_sync(&tty->buf.work);
+}
+
+/**
+ *	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_sync(&tty->hangup_work);
+	flush_work_sync(&tty->SAK_work);
+	flush_work_sync(&tty->buf.work);
 }
 
 /**
@@ -653,7 +664,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
 	mutex_unlock(&tty->ldisc_mutex);
 
-	flush_scheduled_work();
+	tty_ldisc_flush_works(tty);
 
 	retval = tty_ldisc_wait_idle(tty);
 
@@ -711,9 +722,9 @@ enable:
 	/* Restart the work queue in case no characters kick it off. Safe if
 	   already running */
 	if (work)
-		schedule_delayed_work(&tty->buf.work, 1);
+		schedule_work(&tty->buf.work);
 	if (o_work)
-		schedule_delayed_work(&o_tty->buf.work, 1);
+		schedule_work(&o_tty->buf.work);
 	mutex_unlock(&tty->ldisc_mutex);
 	tty_unlock();
 	return retval;
@@ -819,12 +830,12 @@ void tty_ldisc_hangup(struct tty_struct *tty)
 
 	/*
 	 * this is like tty_ldisc_halt, but we need to give up
-	 * the BTM before calling cancel_delayed_work_sync,
-	 * which may need to wait for another function taking the BTM
+	 * 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();
-	cancel_delayed_work_sync(&tty->buf.work);
+	cancel_work_sync(&tty->buf.work);
 	mutex_unlock(&tty->ldisc_mutex);
 
 	tty_lock();
@@ -905,7 +916,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 
 	tty_unlock();
 	tty_ldisc_halt(tty);
-	flush_scheduled_work();
+	tty_ldisc_flush_works(tty);
 	tty_lock();
 
 	mutex_lock(&tty->ldisc_mutex);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index e95d787..6dd3c68 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -654,7 +654,8 @@ static void k_spec(struct vc_data *vc, unsigned char value, char up_flag)
 	if (value >= ARRAY_SIZE(fn_handler))
 		return;
 	if ((kbd->kbdmode == VC_RAW ||
-	     kbd->kbdmode == VC_MEDIUMRAW) &&
+	     kbd->kbdmode == VC_MEDIUMRAW ||
+	     kbd->kbdmode == VC_OFF) &&
 	     value != KVAL(K_SAK))
 		return;		/* SAK is allowed even in raw mode */
 	fn_handler[value](vc);
@@ -1295,7 +1296,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)
 	if (rc == NOTIFY_STOP)
 		return;
 
-	if (raw_mode && type != KT_SPEC && type != KT_SHIFT)
+	if ((raw_mode || kbd->kbdmode == VC_OFF) && type != KT_SPEC && type != KT_SHIFT)
 		return;
 
 	(*k_handler[type])(vc, keysym & 0xff, !down);
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index c956ed6..adf0ad2 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -26,7 +26,6 @@
 #include <linux/selection.h>
 #include <linux/tiocl.h>
 #include <linux/console.h>
-#include <linux/smp_lock.h>
 
 /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */
 #define isspace(c)	((c) == ' ')
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c
index a672ed1..1564261 100644
--- a/drivers/tty/vt/vc_screen.c
+++ b/drivers/tty/vt/vc_screen.c
@@ -28,13 +28,11 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/init.h>
-#include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/kbd_kern.h>
 #include <linux/console.h>
 #include <linux/device.h>
-#include <linux/smp_lock.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
@@ -51,6 +49,8 @@
 #undef addr
 #define HEADER_SIZE	4
 
+#define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
+
 struct vcs_poll_data {
 	struct notifier_block notifier;
 	unsigned int cons_num;
@@ -131,21 +131,45 @@ vcs_poll_data_get(struct file *file)
 	return poll;
 }
 
+/*
+ * Returns VC for inode.
+ * Must be called with console_lock.
+ */
+static struct vc_data*
+vcs_vc(struct inode *inode, int *viewed)
+{
+	unsigned int currcons = iminor(inode) & 127;
+
+	WARN_CONSOLE_UNLOCKED();
+
+	if (currcons == 0) {
+		currcons = fg_console;
+		if (viewed)
+			*viewed = 1;
+	} else {
+		currcons--;
+		if (viewed)
+			*viewed = 0;
+	}
+	return vc_cons[currcons].d;
+}
+
+/*
+ * Returns size for VC carried by inode.
+ * Must be called with console_lock.
+ */
 static int
 vcs_size(struct inode *inode)
 {
 	int size;
 	int minor = iminor(inode);
-	int currcons = minor & 127;
 	struct vc_data *vc;
 
-	if (currcons == 0)
-		currcons = fg_console;
-	else
-		currcons--;
-	if (!vc_cons_allocated(currcons))
+	WARN_CONSOLE_UNLOCKED();
+
+	vc = vcs_vc(inode, NULL);
+	if (!vc)
 		return -ENXIO;
-	vc = vc_cons[currcons].d;
 
 	size = vc->vc_rows * vc->vc_cols;
 
@@ -158,11 +182,13 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 {
 	int size;
 
-	mutex_lock(&con_buf_mtx);
+	console_lock();
 	size = vcs_size(file->f_path.dentry->d_inode);
+	console_unlock();
+	if (size < 0)
+		return size;
 	switch (orig) {
 		default:
-			mutex_unlock(&con_buf_mtx);
 			return -EINVAL;
 		case 2:
 			offset += size;
@@ -173,11 +199,9 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 			break;
 	}
 	if (offset < 0 || offset > size) {
-		mutex_unlock(&con_buf_mtx);
 		return -EINVAL;
 	}
 	file->f_pos = offset;
-	mutex_unlock(&con_buf_mtx);
 	return file->f_pos;
 }
 
@@ -190,12 +214,15 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	struct vc_data *vc;
 	struct vcs_poll_data *poll;
 	long pos;
-	long viewed, attr, read;
-	int col, maxcol;
+	long attr, read;
+	int col, maxcol, viewed;
 	unsigned short *org = NULL;
 	ssize_t ret;
+	char *con_buf;
 
-	mutex_lock(&con_buf_mtx);
+	con_buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!con_buf)
+		return -ENOMEM;
 
 	pos = *ppos;
 
@@ -205,18 +232,10 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 	console_lock();
 
 	attr = (currcons & 128);
-	currcons = (currcons & 127);
-	if (currcons == 0) {
-		currcons = fg_console;
-		viewed = 1;
-	} else {
-		currcons--;
-		viewed = 0;
-	}
 	ret = -ENXIO;
-	if (!vc_cons_allocated(currcons))
+	vc = vcs_vc(inode, &viewed);
+	if (!vc)
 		goto unlock_out;
-	vc = vc_cons[currcons].d;
 
 	ret = -EINVAL;
 	if (pos < 0)
@@ -237,6 +256,12 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 		 * could sleep.
 		 */
 		size = vcs_size(inode);
+		if (size < 0) {
+			if (read)
+				break;
+			ret = size;
+			goto unlock_out;
+		}
 		if (pos >= size)
 			break;
 		if (count > size - pos)
@@ -355,7 +380,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 		ret = read;
 unlock_out:
 	console_unlock();
-	mutex_unlock(&con_buf_mtx);
+	free_page((unsigned long) con_buf);
 	return ret;
 }
 
@@ -366,13 +391,16 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 	unsigned int currcons = iminor(inode);
 	struct vc_data *vc;
 	long pos;
-	long viewed, attr, size, written;
+	long attr, size, written;
 	char *con_buf0;
-	int col, maxcol;
+	int col, maxcol, viewed;
 	u16 *org0 = NULL, *org = NULL;
 	size_t ret;
+	char *con_buf;
 
-	mutex_lock(&con_buf_mtx);
+	con_buf = (char *) __get_free_page(GFP_KERNEL);
+	if (!con_buf)
+		return -ENOMEM;
 
 	pos = *ppos;
 
@@ -382,19 +410,10 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 	console_lock();
 
 	attr = (currcons & 128);
-	currcons = (currcons & 127);
-
-	if (currcons == 0) {
-		currcons = fg_console;
-		viewed = 1;
-	} else {
-		currcons--;
-		viewed = 0;
-	}
 	ret = -ENXIO;
-	if (!vc_cons_allocated(currcons))
+	vc = vcs_vc(inode, &viewed);
+	if (!vc)
 		goto unlock_out;
-	vc = vc_cons[currcons].d;
 
 	size = vcs_size(inode);
 	ret = -EINVAL;
@@ -436,6 +455,12 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 		 * Return data written up to now on failure.
 		 */
 		size = vcs_size(inode);
+		if (size < 0) {
+			if (written)
+				break;
+			ret = size;
+			goto unlock_out;
+		}
 		if (pos >= size)
 			break;
 		if (this_round > size - pos)
@@ -543,9 +568,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 
 unlock_out:
 	console_unlock();
-
-	mutex_unlock(&con_buf_mtx);
-
+	free_page((unsigned long) con_buf);
 	return ret;
 }
 
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 147ede3..c83cdfb 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -89,7 +89,6 @@
 #include <linux/mutex.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
-#include <linux/smp_lock.h>
 #include <linux/tiocl.h>
 #include <linux/kbd_kern.h>
 #include <linux/consolemap.h>
@@ -2068,18 +2067,6 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 	}
 }
 
-/* This is a temporary buffer used to prepare a tty console write
- * so that we can easily avoid touching user space while holding the
- * console spinlock.  It is allocated in con_init and is shared by
- * this code and the vc_screen read/write tty calls.
- *
- * We have to allocate this statically in the kernel data section
- * since console_init (and thus con_init) are called before any
- * kernel memory allocation is available.
- */
-char con_buf[CON_BUF_SIZE];
-DEFINE_MUTEX(con_buf_mtx);
-
 /* is_double_width() is based on the wcwidth() implementation by
  * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
  * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
@@ -2157,10 +2144,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
 
 	currcons = vc->vc_num;
 	if (!vc_cons_allocated(currcons)) {
-	    /* could this happen? */
-		printk_once("con_write: tty %d not allocated\n", currcons+1);
-	    console_unlock();
-	    return 0;
+		/* could this happen? */
+		pr_warn_once("con_write: tty %d not allocated\n", currcons+1);
+		console_unlock();
+		return 0;
 	}
 
 	himask = vc->vc_hi_font_mask;
@@ -2940,7 +2927,7 @@ static int __init con_init(void)
 	gotoxy(vc, vc->vc_x, vc->vc_y);
 	csi_J(vc, 0);
 	update_screen(vc);
-	printk("Console: %s %s %dx%d",
+	pr_info("Console: %s %s %dx%d",
 		vc->vc_can_do_color ? "colour" : "mono",
 		display_desc, vc->vc_cols, vc->vc_rows);
 	printable = 1;
@@ -3103,7 +3090,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
 			clear_buffer_attributes(vc);
 	}
 
-	printk("Console: switching ");
+	pr_info("Console: switching ");
 	if (!deflt)
 		printk("consoles %d-%d ", first+1, last+1);
 	if (j >= 0) {
@@ -3809,7 +3796,8 @@ void do_unblank_screen(int leaving_gfx)
 		return;
 	if (!vc_cons_allocated(fg_console)) {
 		/* impossible */
-		printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
+		pr_warning("unblank_screen: tty %d not allocated ??\n",
+			   fg_console+1);
 		return;
 	}
 	vc = vc_cons[fg_console].d;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 1235ebd..937d172 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -27,7 +27,6 @@
 #include <linux/console.h>
 #include <linux/consolemap.h>
 #include <linux/signal.h>
-#include <linux/smp_lock.h>
 #include <linux/timex.h>
 
 #include <asm/io.h>
@@ -495,7 +494,7 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
  * We handle the console-specific ioctl's here.  We allow the
  * capability to modify any console, not just the fg_console. 
  */
-int vt_ioctl(struct tty_struct *tty, struct file * file,
+int vt_ioctl(struct tty_struct *tty,
 	     unsigned int cmd, unsigned long arg)
 {
 	struct vc_data *vc = tty->driver_data;
@@ -688,6 +687,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 			kbd->kbdmode = VC_UNICODE;
 			compute_shiftstate();
 			break;
+		  case K_OFF:
+			kbd->kbdmode = VC_OFF;
+			break;
 		  default:
 			ret = -EINVAL;
 			goto out;
@@ -1007,8 +1009,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
 			if (ret)
 				break;
 			/* Commence switch and lock */
-			set_console(arg);
+			set_console(vsa.console);
 		}
+		break;
 	}
 
 	/*
@@ -1491,7 +1494,7 @@ compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
 	return 0;
 }
 
-long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
+long vt_compat_ioctl(struct tty_struct *tty,
 	     unsigned int cmd, unsigned long arg)
 {
 	struct vc_data *vc = tty->driver_data;
@@ -1577,7 +1580,7 @@ out:
 
 fallback:
 	tty_unlock();
-	return vt_ioctl(tty, file, cmd, arg);
+	return vt_ioctl(tty, cmd, arg);
 }
 
 
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index bb44079..6f3ea9b 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -94,4 +94,21 @@ config UIO_NETX
 	  To compile this driver as a module, choose M here; the module
 	  will be called uio_netx.
 
+config UIO_PRUSS
+	tristate "Texas Instruments PRUSS driver"
+	depends on ARCH_DAVINCI_DA850
+	help
+	  PRUSS driver for OMAPL138/DA850/AM18XX devices
+	  PRUSS driver requires user space components, examples and user space
+	  driver is available from below SVN repo - you may use anonymous login
+
+	  https://gforge.ti.com/gf/project/pru_sw/
+
+	  More info on API is available at below wiki
+
+	  http://processors.wiki.ti.com/index.php/PRU_Linux_Application_Loader
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called uio_pruss.
+
 endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 18fd818..d4dd9a5 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_UIO_AEC)	+= uio_aec.o
 obj-$(CONFIG_UIO_SERCOS3)	+= uio_sercos3.o
 obj-$(CONFIG_UIO_PCI_GENERIC)	+= uio_pci_generic.o
 obj-$(CONFIG_UIO_NETX)	+= uio_netx.o
+obj-$(CONFIG_UIO_PRUSS)         += uio_pruss.o
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
new file mode 100644
index 0000000..daf6e77
--- /dev/null
+++ b/drivers/uio/uio_pruss.c
@@ -0,0 +1,247 @@
+/*
+ * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
+ *
+ * This driver exports PRUSS host event out interrupts and PRUSS, L3 RAM,
+ * and DDR RAM to user space for applications interacting with PRUSS firmware
+ *
+ * Copyright (C) 2010-11 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 version 2.
+ *
+ * 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.
+ */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/uio_driver.h>
+#include <linux/platform_data/uio_pruss.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <mach/sram.h>
+
+#define DRV_NAME "pruss_uio"
+#define DRV_VERSION "1.0"
+
+static int sram_pool_sz = SZ_16K;
+module_param(sram_pool_sz, int, 0);
+MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate ");
+
+static int extram_pool_sz = SZ_256K;
+module_param(extram_pool_sz, int, 0);
+MODULE_PARM_DESC(extram_pool_sz, "external ram pool size to allocate");
+
+/*
+ * Host event IRQ numbers from PRUSS - PRUSS can generate upto 8 interrupt
+ * events to AINTC of ARM host processor - which can be used for IPC b/w PRUSS
+ * firmware and user space application, async notification from PRU firmware
+ * to user space application
+ * 3	PRU_EVTOUT0
+ * 4	PRU_EVTOUT1
+ * 5	PRU_EVTOUT2
+ * 6	PRU_EVTOUT3
+ * 7	PRU_EVTOUT4
+ * 8	PRU_EVTOUT5
+ * 9	PRU_EVTOUT6
+ * 10	PRU_EVTOUT7
+*/
+#define MAX_PRUSS_EVT	8
+
+#define PINTC_HIDISR	0x0038
+#define PINTC_HIPIR	0x0900
+#define HIPIR_NOPEND	0x80000000
+#define PINTC_HIER	0x1500
+
+struct uio_pruss_dev {
+	struct uio_info *info;
+	struct clk *pruss_clk;
+	dma_addr_t sram_paddr;
+	dma_addr_t ddr_paddr;
+	void __iomem *prussio_vaddr;
+	void *sram_vaddr;
+	void *ddr_vaddr;
+	unsigned int hostirq_start;
+	unsigned int pintc_base;
+};
+
+static irqreturn_t pruss_handler(int irq, struct uio_info *info)
+{
+	struct uio_pruss_dev *gdev = info->priv;
+	int intr_bit = (irq - gdev->hostirq_start + 2);
+	int val, intr_mask = (1 << intr_bit);
+	void __iomem *base = gdev->prussio_vaddr + gdev->pintc_base;
+	void __iomem *intren_reg = base + PINTC_HIER;
+	void __iomem *intrdis_reg = base + PINTC_HIDISR;
+	void __iomem *intrstat_reg = base + PINTC_HIPIR + (intr_bit << 2);
+
+	val = ioread32(intren_reg);
+	/* Is interrupt enabled and active ? */
+	if (!(val & intr_mask) && (ioread32(intrstat_reg) & HIPIR_NOPEND))
+		return IRQ_NONE;
+	/* Disable interrupt */
+	iowrite32(intr_bit, intrdis_reg);
+	return IRQ_HANDLED;
+}
+
+static void pruss_cleanup(struct platform_device *dev,
+			struct uio_pruss_dev *gdev)
+{
+	int cnt;
+	struct uio_info *p = gdev->info;
+
+	for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+		uio_unregister_device(p);
+		kfree(p->name);
+	}
+	iounmap(gdev->prussio_vaddr);
+	if (gdev->ddr_vaddr) {
+		dma_free_coherent(&dev->dev, extram_pool_sz, gdev->ddr_vaddr,
+			gdev->ddr_paddr);
+	}
+	if (gdev->sram_vaddr)
+		sram_free(gdev->sram_vaddr, sram_pool_sz);
+	kfree(gdev->info);
+	clk_put(gdev->pruss_clk);
+	kfree(gdev);
+}
+
+static int __devinit pruss_probe(struct platform_device *dev)
+{
+	struct uio_info *p;
+	struct uio_pruss_dev *gdev;
+	struct resource *regs_prussio;
+	int ret = -ENODEV, cnt = 0, len;
+	struct uio_pruss_pdata *pdata = dev->dev.platform_data;
+
+	gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
+	if (!gdev)
+		return -ENOMEM;
+
+	gdev->info = kzalloc(sizeof(*p) * MAX_PRUSS_EVT, GFP_KERNEL);
+	if (!gdev->info) {
+		kfree(gdev);
+		return -ENOMEM;
+	}
+	/* Power on PRU in case its not done as part of boot-loader */
+	gdev->pruss_clk = clk_get(&dev->dev, "pruss");
+	if (IS_ERR(gdev->pruss_clk)) {
+		dev_err(&dev->dev, "Failed to get clock\n");
+		kfree(gdev->info);
+		kfree(gdev);
+		ret = PTR_ERR(gdev->pruss_clk);
+		return ret;
+	} else {
+		clk_enable(gdev->pruss_clk);
+	}
+
+	regs_prussio = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!regs_prussio) {
+		dev_err(&dev->dev, "No PRUSS I/O resource specified\n");
+		goto out_free;
+	}
+
+	if (!regs_prussio->start) {
+		dev_err(&dev->dev, "Invalid memory resource\n");
+		goto out_free;
+	}
+
+	gdev->sram_vaddr = sram_alloc(sram_pool_sz, &(gdev->sram_paddr));
+	if (!gdev->sram_vaddr) {
+		dev_err(&dev->dev, "Could not allocate SRAM pool\n");
+		goto out_free;
+	}
+
+	gdev->ddr_vaddr = dma_alloc_coherent(&dev->dev, extram_pool_sz,
+				&(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA);
+	if (!gdev->ddr_vaddr) {
+		dev_err(&dev->dev, "Could not allocate external memory\n");
+		goto out_free;
+	}
+
+	len = resource_size(regs_prussio);
+	gdev->prussio_vaddr = ioremap(regs_prussio->start, len);
+	if (!gdev->prussio_vaddr) {
+		dev_err(&dev->dev, "Can't remap PRUSS I/O  address range\n");
+		goto out_free;
+	}
+
+	gdev->pintc_base = pdata->pintc_base;
+	gdev->hostirq_start = platform_get_irq(dev, 0);
+
+	for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+		p->mem[0].addr = regs_prussio->start;
+		p->mem[0].size = resource_size(regs_prussio);
+		p->mem[0].memtype = UIO_MEM_PHYS;
+
+		p->mem[1].addr = gdev->sram_paddr;
+		p->mem[1].size = sram_pool_sz;
+		p->mem[1].memtype = UIO_MEM_PHYS;
+
+		p->mem[2].addr = gdev->ddr_paddr;
+		p->mem[2].size = extram_pool_sz;
+		p->mem[2].memtype = UIO_MEM_PHYS;
+
+		p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", cnt);
+		p->version = DRV_VERSION;
+
+		/* Register PRUSS IRQ lines */
+		p->irq = gdev->hostirq_start + cnt;
+		p->handler = pruss_handler;
+		p->priv = gdev;
+
+		ret = uio_register_device(&dev->dev, p);
+		if (ret < 0)
+			goto out_free;
+	}
+
+	platform_set_drvdata(dev, gdev);
+	return 0;
+
+out_free:
+	pruss_cleanup(dev, gdev);
+	return ret;
+}
+
+static int __devexit pruss_remove(struct platform_device *dev)
+{
+	struct uio_pruss_dev *gdev = platform_get_drvdata(dev);
+
+	pruss_cleanup(dev, gdev);
+	platform_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver pruss_driver = {
+	.probe = pruss_probe,
+	.remove = __devexit_p(pruss_remove),
+	.driver = {
+		   .name = DRV_NAME,
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static int __init pruss_init_module(void)
+{
+	return platform_driver_register(&pruss_driver);
+}
+
+module_init(pruss_init_module);
+
+static void __exit pruss_exit_module(void)
+{
+	platform_driver_unregister(&pruss_driver);
+}
+
+module_exit(pruss_exit_module);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR("Amit Chatterjee <amit.chatterjee@ti.com>");
+MODULE_AUTHOR("Pratheesh Gangadhar <pratheesh@ti.com>");
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index fceea5e..41b6e51 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -31,7 +31,6 @@ config USB_ARCH_HAS_OHCI
 	# ARM:
 	default y if SA1111
 	default y if ARCH_OMAP
-	default y if ARCH_LH7A404
 	default y if ARCH_S3C2410
 	default y if PXA27x
 	default y if PXA3xx
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index 99ac70e..b268e9f 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -168,7 +168,6 @@ struct uea_softc {
 	union cmv_dsc cmv_dsc;
 
 	struct work_struct task;
-	struct workqueue_struct *work_q;
 	u16 pageno;
 	u16 ovl;
 
@@ -1879,7 +1878,7 @@ static int uea_start_reset(struct uea_softc *sc)
 	/* start loading DSP */
 	sc->pageno = 0;
 	sc->ovl = 0;
-	queue_work(sc->work_q, &sc->task);
+	schedule_work(&sc->task);
 
 	/* wait for modem ready CMV */
 	ret = wait_cmv_ack(sc);
@@ -2091,14 +2090,14 @@ static void uea_schedule_load_page_e1(struct uea_softc *sc,
 {
 	sc->pageno = intr->e1_bSwapPageNo;
 	sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4;
-	queue_work(sc->work_q, &sc->task);
+	schedule_work(&sc->task);
 }
 
 static void uea_schedule_load_page_e4(struct uea_softc *sc,
 						struct intr_pkt *intr)
 {
 	sc->pageno = intr->e4_bSwapPageNo;
-	queue_work(sc->work_q, &sc->task);
+	schedule_work(&sc->task);
 }
 
 /*
@@ -2170,13 +2169,6 @@ static int uea_boot(struct uea_softc *sc)
 
 	init_waitqueue_head(&sc->sync_q);
 
-	sc->work_q = create_workqueue("ueagle-dsp");
-	if (!sc->work_q) {
-		uea_err(INS_TO_USBDEV(sc), "cannot allocate workqueue\n");
-		uea_leaves(INS_TO_USBDEV(sc));
-		return -ENOMEM;
-	}
-
 	if (UEA_CHIP_VERSION(sc) == ADI930)
 		load_XILINX_firmware(sc);
 
@@ -2225,7 +2217,6 @@ err1:
 	sc->urb_int = NULL;
 	kfree(intr);
 err0:
-	destroy_workqueue(sc->work_q);
 	uea_leaves(INS_TO_USBDEV(sc));
 	return -ENOMEM;
 }
@@ -2246,8 +2237,8 @@ static void uea_stop(struct uea_softc *sc)
 	kfree(sc->urb_int->transfer_buffer);
 	usb_free_urb(sc->urb_int);
 
-	/* stop any pending boot process, when no one can schedule work */
-	destroy_workqueue(sc->work_q);
+	/* flush the work item, when no one can schedule it */
+	flush_work_sync(&sc->task);
 
 	if (sc->dsp_firm)
 		release_firmware(sc->dsp_firm);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 4ab49d4..f492a7f 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -776,7 +776,7 @@ static int acm_tty_break_ctl(struct tty_struct *tty, int state)
 	return retval;
 }
 
-static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
+static int acm_tty_tiocmget(struct tty_struct *tty)
 {
 	struct acm *acm = tty->driver_data;
 
@@ -791,7 +791,7 @@ static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
 	       TIOCM_CTS;
 }
 
-static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+static int acm_tty_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct acm *acm = tty->driver_data;
@@ -813,7 +813,7 @@ static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file,
 	return acm_set_control(acm, acm->ctrlout = newctrl);
 }
 
-static int acm_tty_ioctl(struct tty_struct *tty, struct file *file,
+static int acm_tty_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct acm *acm = tty->driver_data;
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 2c69654..b0585e6 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -10,7 +10,7 @@
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/mm.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
 #include <linux/usb.h>
@@ -22,7 +22,7 @@
  */
 
 /* FIXME tune these based on pool statistics ... */
-static const size_t	pool_max [HCD_BUFFER_POOLS] = {
+static const size_t	pool_max[HCD_BUFFER_POOLS] = {
 	/* platforms without dma-friendly caches might need to
 	 * prevent cacheline sharing...
 	 */
@@ -51,7 +51,7 @@ static const size_t	pool_max [HCD_BUFFER_POOLS] = {
 int hcd_buffer_create(struct usb_hcd *hcd)
 {
 	char		name[16];
-	int 		i, size;
+	int		i, size;
 
 	if (!hcd->self.controller->dma_mask &&
 	    !(hcd->driver->flags & HCD_LOCAL_MEM))
@@ -64,7 +64,7 @@ int hcd_buffer_create(struct usb_hcd *hcd)
 		snprintf(name, sizeof name, "buffer-%d", size);
 		hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
 				size, size, 0);
-		if (!hcd->pool [i]) {
+		if (!hcd->pool[i]) {
 			hcd_buffer_destroy(hcd);
 			return -ENOMEM;
 		}
@@ -99,14 +99,14 @@ void hcd_buffer_destroy(struct usb_hcd *hcd)
  */
 
 void *hcd_buffer_alloc(
-	struct usb_bus 	*bus,
+	struct usb_bus		*bus,
 	size_t			size,
 	gfp_t			mem_flags,
 	dma_addr_t		*dma
 )
 {
 	struct usb_hcd		*hcd = bus_to_hcd(bus);
-	int 			i;
+	int			i;
 
 	/* some USB hosts just use PIO */
 	if (!bus->controller->dma_mask &&
@@ -116,21 +116,21 @@ void *hcd_buffer_alloc(
 	}
 
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
-		if (size <= pool_max [i])
-			return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
+		if (size <= pool_max[i])
+			return dma_pool_alloc(hcd->pool[i], mem_flags, dma);
 	}
 	return dma_alloc_coherent(hcd->self.controller, size, dma, mem_flags);
 }
 
 void hcd_buffer_free(
-	struct usb_bus 	*bus,
+	struct usb_bus		*bus,
 	size_t			size,
-	void 			*addr,
+	void			*addr,
 	dma_addr_t		dma
 )
 {
 	struct usb_hcd		*hcd = bus_to_hcd(bus);
-	int 			i;
+	int			i;
 
 	if (!addr)
 		return;
@@ -142,8 +142,8 @@ void hcd_buffer_free(
 	}
 
 	for (i = 0; i < HCD_BUFFER_POOLS; i++) {
-		if (size <= pool_max [i]) {
-			dma_pool_free(hcd->pool [i], addr, dma);
+		if (size <= pool_max[i]) {
+			dma_pool_free(hcd->pool[i], addr, dma);
 			return;
 		}
 	}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index fca6172..e35a176 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1646,7 +1646,7 @@ static int autosuspend_check(struct usb_device *udev)
 	return 0;
 }
 
-static int usb_runtime_suspend(struct device *dev)
+int usb_runtime_suspend(struct device *dev)
 {
 	struct usb_device	*udev = to_usb_device(dev);
 	int			status;
@@ -1659,10 +1659,15 @@ static int usb_runtime_suspend(struct device *dev)
 		return -EAGAIN;
 
 	status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
+	/* The PM core reacts badly unless the return code is 0,
+	 * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.
+	 */
+	if (status != 0)
+		return -EBUSY;
 	return status;
 }
 
-static int usb_runtime_resume(struct device *dev)
+int usb_runtime_resume(struct device *dev)
 {
 	struct usb_device	*udev = to_usb_device(dev);
 	int			status;
@@ -1674,7 +1679,7 @@ static int usb_runtime_resume(struct device *dev)
 	return status;
 }
 
-static int usb_runtime_idle(struct device *dev)
+int usb_runtime_idle(struct device *dev)
 {
 	struct usb_device	*udev = to_usb_device(dev);
 
@@ -1686,19 +1691,10 @@ static int usb_runtime_idle(struct device *dev)
 	return 0;
 }
 
-static const struct dev_pm_ops usb_bus_pm_ops = {
-	.runtime_suspend =	usb_runtime_suspend,
-	.runtime_resume =	usb_runtime_resume,
-	.runtime_idle =		usb_runtime_idle,
-};
-
 #endif /* CONFIG_USB_SUSPEND */
 
 struct bus_type usb_bus_type = {
 	.name =		"usb",
 	.match =	usb_device_match,
 	.uevent =	usb_uevent,
-#ifdef CONFIG_USB_SUSPEND
-	.pm =		&usb_bus_pm_ops,
-#endif
 };
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index f71e8e3..ce22f4a 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -192,13 +192,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
 			pci_name(dev));
 		retval = -ENODEV;
-		goto err1;
+		goto disable_pci;
 	}
 
 	hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
 	if (!hcd) {
 		retval = -ENOMEM;
-		goto err1;
+		goto disable_pci;
 	}
 
 	if (driver->flags & HCD_MEMORY) {
@@ -209,13 +209,13 @@ 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 err2;
+			goto clear_companion;
 		}
 		hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
 		if (hcd->regs == NULL) {
 			dev_dbg(&dev->dev, "error mapping memory\n");
 			retval = -EFAULT;
-			goto err3;
+			goto release_mem_region;
 		}
 
 	} else {
@@ -236,7 +236,7 @@ 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 err2;
+			goto clear_companion;
 		}
 	}
 
@@ -244,24 +244,24 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
 	if (retval != 0)
-		goto err4;
+		goto unmap_registers;
 	set_hs_companion(dev, hcd);
 
 	if (pci_dev_run_wake(dev))
 		pm_runtime_put_noidle(&dev->dev);
 	return retval;
 
- err4:
+unmap_registers:
 	if (driver->flags & HCD_MEMORY) {
 		iounmap(hcd->regs);
- err3:
+release_mem_region:
 		release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 	} else
 		release_region(hcd->rsrc_start, hcd->rsrc_len);
- err2:
+clear_companion:
 	clear_hs_companion(dev, hcd);
 	usb_put_hcd(hcd);
- err1:
+disable_pci:
 	pci_disable_device(dev);
 	dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
 	return retval;
@@ -335,7 +335,7 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
 
-#ifdef	CONFIG_PM_OPS
+#ifdef	CONFIG_PM
 
 #ifdef	CONFIG_PPC_PMAC
 static void powermac_set_asic(struct pci_dev *pci_dev, int enable)
@@ -363,11 +363,17 @@ static int check_root_hub_suspended(struct device *dev)
 	struct pci_dev		*pci_dev = to_pci_dev(dev);
 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 
-	if (!(hcd->state == HC_STATE_SUSPENDED ||
-			hcd->state == HC_STATE_HALT)) {
+	if (HCD_RH_RUNNING(hcd)) {
 		dev_warn(dev, "Root hub is not suspended\n");
 		return -EBUSY;
 	}
+	if (hcd->shared_hcd) {
+		hcd = hcd->shared_hcd;
+		if (HCD_RH_RUNNING(hcd)) {
+			dev_warn(dev, "Secondary root hub is not suspended\n");
+			return -EBUSY;
+		}
+	}
 	return 0;
 }
 
@@ -386,17 +392,22 @@ static int suspend_common(struct device *dev, bool do_wakeup)
 	if (retval)
 		return retval;
 
-	if (hcd->driver->pci_suspend) {
+	if (hcd->driver->pci_suspend && !HCD_DEAD(hcd)) {
 		/* Optimization: Don't suspend if a root-hub wakeup is
 		 * pending and it would cause the HCD to wake up anyway.
 		 */
 		if (do_wakeup && HCD_WAKEUP_PENDING(hcd))
 			return -EBUSY;
+		if (do_wakeup && hcd->shared_hcd &&
+				HCD_WAKEUP_PENDING(hcd->shared_hcd))
+			return -EBUSY;
 		retval = hcd->driver->pci_suspend(hcd, do_wakeup);
 		suspend_report_result(hcd->driver->pci_suspend, retval);
 
 		/* Check again in case wakeup raced with pci_suspend */
-		if (retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) {
+		if ((retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) ||
+				(retval == 0 && do_wakeup && hcd->shared_hcd &&
+				 HCD_WAKEUP_PENDING(hcd->shared_hcd))) {
 			if (hcd->driver->pci_resume)
 				hcd->driver->pci_resume(hcd, false);
 			retval = -EBUSY;
@@ -427,7 +438,9 @@ static int resume_common(struct device *dev, int event)
 	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);
 	int			retval;
 
-	if (hcd->state != HC_STATE_SUSPENDED) {
+	if (HCD_RH_RUNNING(hcd) ||
+			(hcd->shared_hcd &&
+			 HCD_RH_RUNNING(hcd->shared_hcd))) {
 		dev_dbg(dev, "can't resume, not suspended!\n");
 		return 0;
 	}
@@ -441,8 +454,10 @@ static int resume_common(struct device *dev, int event)
 	pci_set_master(pci_dev);
 
 	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+	if (hcd->shared_hcd)
+		clear_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
 
-	if (hcd->driver->pci_resume) {
+	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
 		if (event != PM_EVENT_AUTO_RESUME)
 			wait_for_companions(pci_dev, hcd);
 
@@ -450,6 +465,8 @@ static int resume_common(struct device *dev, int event)
 				event == PM_EVENT_RESTORE);
 		if (retval) {
 			dev_err(dev, "PCI post-resume error %d!\n", retval);
+			if (hcd->shared_hcd)
+				usb_hc_died(hcd->shared_hcd);
 			usb_hc_died(hcd);
 		}
 	}
@@ -475,10 +492,11 @@ static int hcd_pci_suspend_noirq(struct device *dev)
 
 	pci_save_state(pci_dev);
 
-	/* If the root hub is HALTed rather than SUSPENDed,
-	 * disallow remote wakeup.
+	/* If the root hub is dead rather than suspended, disallow remote
+	 * wakeup.  usb_hc_died() should ensure that both hosts are marked as
+	 * dying, so we only need to check the primary roothub.
 	 */
-	if (hcd->state == HC_STATE_HALT)
+	if (HCD_DEAD(hcd))
 		device_set_wakeup_enable(dev, 0);
 	dev_dbg(dev, "wakeup: %d\n", device_may_wakeup(dev));
 
@@ -580,4 +598,4 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = {
 };
 EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops);
 
-#endif	/* CONFIG_PM_OPS */
+#endif	/* CONFIG_PM */
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e935f71..02b4dbf 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -297,7 +297,7 @@ static const u8 ss_rh_config_descriptor[] = {
 	/* one configuration */
 	0x09,       /*  __u8  bLength; */
 	0x02,       /*  __u8  bDescriptorType; Configuration */
-	0x19, 0x00, /*  __le16 wTotalLength; FIXME */
+	0x1f, 0x00, /*  __le16 wTotalLength; */
 	0x01,       /*  __u8  bNumInterfaces; (1) */
 	0x01,       /*  __u8  bConfigurationValue; */
 	0x00,       /*  __u8  iConfiguration; */
@@ -327,11 +327,14 @@ static const u8 ss_rh_config_descriptor[] = {
 		    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
 		     * see hub.c:hub_configure() for details. */
 	(USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
-	0x0c        /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
-	/*
-	 * All 3.0 hubs should have an endpoint companion descriptor,
-	 * but we're ignoring that for now.  FIXME?
-	 */
+	0x0c,       /*  __u8  ep_bInterval; (256ms -- usb 2.0 spec) */
+
+	/* one SuperSpeed endpoint companion descriptor */
+	0x06,        /* __u8 ss_bLength */
+	0x30,        /* __u8 ss_bDescriptorType; SuperSpeed EP Companion */
+	0x00,        /* __u8 ss_bMaxBurst; allows 1 TX between ACKs */
+	0x00,        /* __u8 ss_bmAttributes; 1 packet per service interval */
+	0x02, 0x00   /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
 };
 
 /*-------------------------------------------------------------------------*/
@@ -504,7 +507,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 	case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
 		switch (wValue & 0xff00) {
 		case USB_DT_DEVICE << 8:
-			switch (hcd->driver->flags & HCD_MASK) {
+			switch (hcd->speed) {
 			case HCD_USB3:
 				bufp = usb3_rh_dev_descriptor;
 				break;
@@ -522,7 +525,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
 				patch_protocol = 1;
 			break;
 		case USB_DT_CONFIG << 8:
-			switch (hcd->driver->flags & HCD_MASK) {
+			switch (hcd->speed) {
 			case HCD_USB3:
 				bufp = ss_rh_config_descriptor;
 				len = sizeof ss_rh_config_descriptor;
@@ -983,7 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
 		spin_unlock_irq (&hcd_root_hub_lock);
 
 		/* Did the HC die before the root hub was registered? */
-		if (hcd->state == HC_STATE_HALT)
+		if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
 			usb_hc_died (hcd);	/* This time clean up */
 	}
 
@@ -1089,13 +1092,10 @@ int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb)
 	 * Check the host controller's state and add the URB to the
 	 * endpoint's queue.
 	 */
-	switch (hcd->state) {
-	case HC_STATE_RUNNING:
-	case HC_STATE_RESUMING:
+	if (HCD_RH_RUNNING(hcd)) {
 		urb->unlinked = 0;
 		list_add_tail(&urb->urb_list, &urb->ep->urb_list);
-		break;
-	default:
+	} else {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
@@ -1153,6 +1153,8 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
 		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "
 			"Controller is probably using the wrong IRQ.\n");
 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+		if (hcd->shared_hcd)
+			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
 	}
 
 	return 0;
@@ -1262,7 +1264,7 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
 	*dma_handle = 0;
 }
 
-void unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
+void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
 	if (urb->transfer_flags & URB_SETUP_MAP_SINGLE)
 		dma_unmap_single(hcd->self.controller,
@@ -1279,13 +1281,21 @@ void unmap_urb_setup_for_dma(struct usb_hcd *hcd, struct urb *urb)
 	/* Make it safe to call this routine more than once */
 	urb->transfer_flags &= ~(URB_SETUP_MAP_SINGLE | URB_SETUP_MAP_LOCAL);
 }
-EXPORT_SYMBOL_GPL(unmap_urb_setup_for_dma);
+EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_setup_for_dma);
 
-void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	if (hcd->driver->unmap_urb_for_dma)
+		hcd->driver->unmap_urb_for_dma(hcd, urb);
+	else
+		usb_hcd_unmap_urb_for_dma(hcd, urb);
+}
+
+void usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 {
 	enum dma_data_direction dir;
 
-	unmap_urb_setup_for_dma(hcd, urb);
+	usb_hcd_unmap_urb_setup_for_dma(hcd, urb);
 
 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 	if (urb->transfer_flags & URB_DMA_MAP_SG)
@@ -1314,11 +1324,20 @@ void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 	urb->transfer_flags &= ~(URB_DMA_MAP_SG | URB_DMA_MAP_PAGE |
 			URB_DMA_MAP_SINGLE | URB_MAP_LOCAL);
 }
-EXPORT_SYMBOL_GPL(unmap_urb_for_dma);
+EXPORT_SYMBOL_GPL(usb_hcd_unmap_urb_for_dma);
 
 static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 			   gfp_t mem_flags)
 {
+	if (hcd->driver->map_urb_for_dma)
+		return hcd->driver->map_urb_for_dma(hcd, urb, mem_flags);
+	else
+		return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+}
+
+int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+			    gfp_t mem_flags)
+{
 	enum dma_data_direction dir;
 	int ret = 0;
 
@@ -1410,10 +1429,11 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 		}
 		if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
 				URB_SETUP_MAP_LOCAL)))
-			unmap_urb_for_dma(hcd, urb);
+			usb_hcd_unmap_urb_for_dma(hcd, urb);
 	}
 	return ret;
 }
+EXPORT_SYMBOL_GPL(usb_hcd_map_urb_for_dma);
 
 /*-------------------------------------------------------------------------*/
 
@@ -1913,7 +1933,7 @@ int usb_hcd_get_frame_number (struct usb_device *udev)
 {
 	struct usb_hcd	*hcd = bus_to_hcd(udev->bus);
 
-	if (!HC_IS_RUNNING (hcd->state))
+	if (!HCD_RH_RUNNING(hcd))
 		return -ESHUTDOWN;
 	return hcd->driver->get_frame_number (hcd);
 }
@@ -1930,9 +1950,15 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
 
 	dev_dbg(&rhdev->dev, "bus %s%s\n",
 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "suspend");
+	if (HCD_DEAD(hcd)) {
+		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "suspend");
+		return 0;
+	}
+
 	if (!hcd->driver->bus_suspend) {
 		status = -ENOENT;
 	} else {
+		clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
 		hcd->state = HC_STATE_QUIESCING;
 		status = hcd->driver->bus_suspend(hcd);
 	}
@@ -1940,7 +1966,12 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
 		usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
 		hcd->state = HC_STATE_SUSPENDED;
 	} else {
-		hcd->state = old_state;
+		spin_lock_irq(&hcd_root_hub_lock);
+		if (!HCD_DEAD(hcd)) {
+			set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+			hcd->state = old_state;
+		}
+		spin_unlock_irq(&hcd_root_hub_lock);
 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
 				"suspend", status);
 	}
@@ -1955,9 +1986,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 
 	dev_dbg(&rhdev->dev, "usb %s%s\n",
 			(msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume");
+	if (HCD_DEAD(hcd)) {
+		dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume");
+		return 0;
+	}
 	if (!hcd->driver->bus_resume)
 		return -ENOENT;
-	if (hcd->state == HC_STATE_RUNNING)
+	if (HCD_RH_RUNNING(hcd))
 		return 0;
 
 	hcd->state = HC_STATE_RESUMING;
@@ -1966,10 +2001,15 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 	if (status == 0) {
 		/* TRSMRCY = 10 msec */
 		msleep(10);
-		usb_set_device_state(rhdev, rhdev->actconfig
-				? USB_STATE_CONFIGURED
-				: USB_STATE_ADDRESS);
-		hcd->state = HC_STATE_RUNNING;
+		spin_lock_irq(&hcd_root_hub_lock);
+		if (!HCD_DEAD(hcd)) {
+			usb_set_device_state(rhdev, rhdev->actconfig
+					? USB_STATE_CONFIGURED
+					: USB_STATE_ADDRESS);
+			set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+			hcd->state = HC_STATE_RUNNING;
+		}
+		spin_unlock_irq(&hcd_root_hub_lock);
 	} else {
 		hcd->state = old_state;
 		dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
@@ -2080,12 +2120,14 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 	 */
 	local_irq_save(flags);
 
-	if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) {
+	if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
 		rc = IRQ_NONE;
 	} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
 		rc = IRQ_NONE;
 	} else {
 		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+		if (hcd->shared_hcd)
+			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
 
 		if (unlikely(hcd->state == HC_STATE_HALT))
 			usb_hc_died(hcd);
@@ -2105,7 +2147,9 @@ EXPORT_SYMBOL_GPL(usb_hcd_irq);
  *
  * This is called by bus glue to report a USB host controller that died
  * while operations may still have been pending.  It's called automatically
- * by the PCI glue, so only glue for non-PCI busses should need to call it. 
+ * by the PCI glue, so only glue for non-PCI busses should need to call it.
+ *
+ * Only call this function with the primary HCD.
  */
 void usb_hc_died (struct usb_hcd *hcd)
 {
@@ -2114,6 +2158,8 @@ void usb_hc_died (struct usb_hcd *hcd)
 	dev_err (hcd->self.controller, "HC died; cleaning up\n");
 
 	spin_lock_irqsave (&hcd_root_hub_lock, flags);
+	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+	set_bit(HCD_FLAG_DEAD, &hcd->flags);
 	if (hcd->rh_registered) {
 		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 
@@ -2122,17 +2168,31 @@ void usb_hc_died (struct usb_hcd *hcd)
 				USB_STATE_NOTATTACHED);
 		usb_kick_khubd (hcd->self.root_hub);
 	}
+	if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
+		hcd = hcd->shared_hcd;
+		if (hcd->rh_registered) {
+			clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+
+			/* make khubd clean up old urbs and devices */
+			usb_set_device_state(hcd->self.root_hub,
+					USB_STATE_NOTATTACHED);
+			usb_kick_khubd(hcd->self.root_hub);
+		}
+	}
 	spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
+	/* Make sure that the other roothub is also deallocated. */
 }
 EXPORT_SYMBOL_GPL (usb_hc_died);
 
 /*-------------------------------------------------------------------------*/
 
 /**
- * usb_create_hcd - create and initialize an HCD structure
+ * usb_create_shared_hcd - create and initialize an HCD structure
  * @driver: HC driver that will use this hcd
  * @dev: device for this HC, stored in hcd->self.controller
  * @bus_name: value to store in hcd->self.bus_name
+ * @primary_hcd: a pointer to the usb_hcd structure that is sharing the
+ *              PCI device.  Only allocate certain resources for the primary HCD
  * Context: !in_interrupt()
  *
  * Allocate a struct usb_hcd, with extra space at the end for the
@@ -2141,8 +2201,9 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
  *
  * If memory is unavailable, returns NULL.
  */
-struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
-		struct device *dev, const char *bus_name)
+struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
+		struct device *dev, const char *bus_name,
+		struct usb_hcd *primary_hcd)
 {
 	struct usb_hcd *hcd;
 
@@ -2151,7 +2212,24 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 		dev_dbg (dev, "hcd alloc failed\n");
 		return NULL;
 	}
-	dev_set_drvdata(dev, hcd);
+	if (primary_hcd == NULL) {
+		hcd->bandwidth_mutex = kmalloc(sizeof(*hcd->bandwidth_mutex),
+				GFP_KERNEL);
+		if (!hcd->bandwidth_mutex) {
+			kfree(hcd);
+			dev_dbg(dev, "hcd bandwidth mutex alloc failed\n");
+			return NULL;
+		}
+		mutex_init(hcd->bandwidth_mutex);
+		dev_set_drvdata(dev, hcd);
+	} else {
+		hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;
+		hcd->primary_hcd = primary_hcd;
+		primary_hcd->primary_hcd = primary_hcd;
+		hcd->shared_hcd = primary_hcd;
+		primary_hcd->shared_hcd = hcd;
+	}
+
 	kref_init(&hcd->kref);
 
 	usb_bus_init(&hcd->self);
@@ -2165,19 +2243,53 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 #ifdef CONFIG_USB_SUSPEND
 	INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
-	mutex_init(&hcd->bandwidth_mutex);
 
 	hcd->driver = driver;
+	hcd->speed = driver->flags & HCD_MASK;
 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
 			"USB Host Controller";
 	return hcd;
 }
+EXPORT_SYMBOL_GPL(usb_create_shared_hcd);
+
+/**
+ * usb_create_hcd - create and initialize an HCD structure
+ * @driver: HC driver that will use this hcd
+ * @dev: device for this HC, stored in hcd->self.controller
+ * @bus_name: value to store in hcd->self.bus_name
+ * Context: !in_interrupt()
+ *
+ * Allocate a struct usb_hcd, with extra space at the end for the
+ * HC driver's private data.  Initialize the generic members of the
+ * hcd structure.
+ *
+ * If memory is unavailable, returns NULL.
+ */
+struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
+		struct device *dev, const char *bus_name)
+{
+	return usb_create_shared_hcd(driver, dev, bus_name, NULL);
+}
 EXPORT_SYMBOL_GPL(usb_create_hcd);
 
+/*
+ * Roothubs that share one PCI device must also share the bandwidth mutex.
+ * Don't deallocate the bandwidth_mutex until the last shared usb_hcd is
+ * deallocated.
+ *
+ * Make sure to only deallocate the bandwidth_mutex when the primary HCD is
+ * freed.  When hcd_release() is called for the non-primary HCD, set the
+ * primary_hcd's shared_hcd pointer to null (since the non-primary HCD will be
+ * freed shortly).
+ */
 static void hcd_release (struct kref *kref)
 {
 	struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
 
+	if (usb_hcd_is_primary_hcd(hcd))
+		kfree(hcd->bandwidth_mutex);
+	else
+		hcd->shared_hcd->shared_hcd = NULL;
 	kfree(hcd);
 }
 
@@ -2196,6 +2308,54 @@ void usb_put_hcd (struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_put_hcd);
 
+int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)
+{
+	if (!hcd->primary_hcd)
+		return 1;
+	return hcd == hcd->primary_hcd;
+}
+EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd);
+
+static int usb_hcd_request_irqs(struct usb_hcd *hcd,
+		unsigned int irqnum, unsigned long irqflags)
+{
+	int retval;
+
+	if (hcd->driver->irq) {
+
+		/* IRQF_DISABLED doesn't work as advertised when used together
+		 * with IRQF_SHARED. As usb_hcd_irq() will always disable
+		 * interrupts we can remove it here.
+		 */
+		if (irqflags & IRQF_SHARED)
+			irqflags &= ~IRQF_DISABLED;
+
+		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+				hcd->driver->description, hcd->self.busnum);
+		retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
+				hcd->irq_descr, hcd);
+		if (retval != 0) {
+			dev_err(hcd->self.controller,
+					"request interrupt %d failed\n",
+					irqnum);
+			return retval;
+		}
+		hcd->irq = irqnum;
+		dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
+				(hcd->driver->flags & HCD_MEMORY) ?
+					"io mem" : "io base",
+					(unsigned long long)hcd->rsrc_start);
+	} else {
+		hcd->irq = -1;
+		if (hcd->rsrc_start)
+			dev_info(hcd->self.controller, "%s 0x%08llx\n",
+					(hcd->driver->flags & HCD_MEMORY) ?
+					"io mem" : "io base",
+					(unsigned long long)hcd->rsrc_start);
+	}
+	return 0;
+}
+
 /**
  * usb_add_hcd - finish generic HCD structure initialization and register
  * @hcd: the usb_hcd structure to initialize
@@ -2236,7 +2396,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	}
 	hcd->self.root_hub = rhdev;
 
-	switch (hcd->driver->flags & HCD_MASK) {
+	switch (hcd->speed) {
 	case HCD_USB11:
 		rhdev->speed = USB_SPEED_FULL;
 		break;
@@ -2256,6 +2416,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	 */
 	device_init_wakeup(&rhdev->dev, 1);
 
+	/* HCD_FLAG_RH_RUNNING doesn't matter until the root hub is
+	 * registered.  But since the controller can die at any time,
+	 * let's initialize the flag before touching the hardware.
+	 */
+	set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
+
 	/* "reset" is misnamed; its role is now one-time init. the controller
 	 * should already have been reset (and boot firmware kicked off etc).
 	 */
@@ -2271,38 +2437,15 @@ int usb_add_hcd(struct usb_hcd *hcd,
 		dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
 
 	/* enable irqs just before we start the controller */
-	if (hcd->driver->irq) {
-
-		/* IRQF_DISABLED doesn't work as advertised when used together
-		 * with IRQF_SHARED. As usb_hcd_irq() will always disable
-		 * interrupts we can remove it here.
-		 */
-		if (irqflags & IRQF_SHARED)
-			irqflags &= ~IRQF_DISABLED;
-
-		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
-				hcd->driver->description, hcd->self.busnum);
-		if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
-				hcd->irq_descr, hcd)) != 0) {
-			dev_err(hcd->self.controller,
-					"request interrupt %d failed\n", irqnum);
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
+		if (retval)
 			goto err_request_irq;
-		}
-		hcd->irq = irqnum;
-		dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
-				(hcd->driver->flags & HCD_MEMORY) ?
-					"io mem" : "io base",
-					(unsigned long long)hcd->rsrc_start);
-	} else {
-		hcd->irq = -1;
-		if (hcd->rsrc_start)
-			dev_info(hcd->self.controller, "%s 0x%08llx\n",
-					(hcd->driver->flags & HCD_MEMORY) ?
-					"io mem" : "io base",
-					(unsigned long long)hcd->rsrc_start);
 	}
 
-	if ((retval = hcd->driver->start(hcd)) < 0) {
+	hcd->state = HC_STATE_RUNNING;
+	retval = hcd->driver->start(hcd);
+	if (retval < 0) {
 		dev_err(hcd->self.controller, "startup error %d\n", retval);
 		goto err_hcd_driver_start;
 	}
@@ -2323,6 +2466,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
 	return retval;
 
 error_create_attr_group:
+	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
 	if (HC_IS_RUNNING(hcd->state))
 		hcd->state = HC_STATE_QUIESCING;
 	spin_lock_irq(&hcd_root_hub_lock);
@@ -2344,7 +2488,7 @@ err_register_root_hub:
 	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	del_timer_sync(&hcd->rh_timer);
 err_hcd_driver_start:
-	if (hcd->irq >= 0)
+	if (usb_hcd_is_primary_hcd(hcd) && hcd->irq >= 0)
 		free_irq(irqnum, hcd);
 err_request_irq:
 err_hcd_driver_setup:
@@ -2375,6 +2519,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 	usb_get_dev(rhdev);
 	sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group);
 
+	clear_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
 	if (HC_IS_RUNNING (hcd->state))
 		hcd->state = HC_STATE_QUIESCING;
 
@@ -2407,8 +2552,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	del_timer_sync(&hcd->rh_timer);
 
-	if (hcd->irq >= 0)
-		free_irq(hcd->irq, hcd);
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		if (hcd->irq >= 0)
+			free_irq(hcd->irq, hcd);
+	}
 
 	usb_put_dev(hcd->self.root_hub);
 	usb_deregister_bus(&hcd->self);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0f299b7..564eaa5 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -82,6 +82,10 @@ struct usb_hub {
 	void			**port_owners;
 };
 
+static inline int hub_is_superspeed(struct usb_device *hdev)
+{
+	return (hdev->descriptor.bDeviceProtocol == 3);
+}
 
 /* Protect struct usb_device->state and ->children members
  * Note: Both are also protected by ->dev.sem, except that ->state can
@@ -151,14 +155,14 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
 
 static int usb_reset_and_verify_device(struct usb_device *udev);
 
-static inline char *portspeed(int portstatus)
+static inline char *portspeed(struct usb_hub *hub, int portstatus)
 {
+	if (hub_is_superspeed(hub->hdev))
+		return "5.0 Gb/s";
 	if (portstatus & USB_PORT_STAT_HIGH_SPEED)
     		return "480 Mb/s";
 	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
 		return "1.5 Mb/s";
-	else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
-		return "5.0 Gb/s";
 	else
 		return "12 Mb/s";
 }
@@ -172,14 +176,23 @@ static struct usb_hub *hdev_to_hub(struct usb_device *hdev)
 }
 
 /* USB 2.0 spec Section 11.24.4.5 */
-static int get_hub_descriptor(struct usb_device *hdev, void *data, int size)
+static int get_hub_descriptor(struct usb_device *hdev, void *data)
 {
-	int i, ret;
+	int i, ret, size;
+	unsigned dtype;
+
+	if (hub_is_superspeed(hdev)) {
+		dtype = USB_DT_SS_HUB;
+		size = USB_DT_SS_HUB_SIZE;
+	} else {
+		dtype = USB_DT_HUB;
+		size = sizeof(struct usb_hub_descriptor);
+	}
 
 	for (i = 0; i < 3; i++) {
 		ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
-			USB_DT_HUB << 8, 0, data, size,
+			dtype << 8, 0, data, size,
 			USB_CTRL_GET_TIMEOUT);
 		if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
 			return ret;
@@ -365,6 +378,16 @@ static int hub_port_status(struct usb_hub *hub, int port1,
 	} else {
 		*status = le16_to_cpu(hub->status->port.wPortStatus);
 		*change = le16_to_cpu(hub->status->port.wPortChange);
+
+		if ((hub->hdev->parent != NULL) &&
+				hub_is_superspeed(hub->hdev)) {
+			/* Translate the USB 3 port status */
+			u16 tmp = *status & USB_SS_PORT_STAT_MASK;
+			if (*status & USB_SS_PORT_STAT_POWER)
+				tmp |= USB_PORT_STAT_POWER;
+			*status = tmp;
+		}
+
 		ret = 0;
 	}
 	mutex_unlock(&hub->status_mutex);
@@ -607,7 +630,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 	if (hdev->children[port1-1] && set_state)
 		usb_set_device_state(hdev->children[port1-1],
 				USB_STATE_NOTATTACHED);
-	if (!hub->error)
+	if (!hub->error && !hub_is_superspeed(hub->hdev))
 		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
 	if (ret)
 		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
@@ -616,7 +639,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 }
 
 /*
- * Disable a port and mark a logical connnect-change event, so that some
+ * Disable a port and mark a logical connect-change event, so that some
  * time later khubd will disconnect() any existing usb_device on the port
  * and will re-enumerate if there actually is a device attached.
  */
@@ -769,12 +792,8 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 			 * USB3 protocol ports will automatically transition
 			 * to Enabled state when detect an USB3.0 device attach.
 			 * Do not disable USB3 protocol ports.
-			 * FIXME: USB3 root hub and external hubs are treated
-			 * differently here.
 			 */
-			if (hdev->descriptor.bDeviceProtocol != 3 ||
-			    (!hdev->parent &&
-			     !(portstatus & USB_PORT_STAT_SUPER_SPEED))) {
+			if (!hub_is_superspeed(hdev)) {
 				clear_port_feature(hdev, port1,
 						   USB_PORT_FEAT_ENABLE);
 				portstatus &= ~USB_PORT_STAT_ENABLE;
@@ -795,6 +814,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_ENABLE);
 		}
+		if (portchange & USB_PORT_STAT_C_LINK_STATE) {
+			need_debounce_delay = true;
+			clear_port_feature(hub->hdev, port1,
+					USB_PORT_FEAT_C_PORT_LINK_STATE);
+		}
 
 		/* We can forget about a "removed" device when there's a
 		 * physical disconnect or the connect status changes.
@@ -964,12 +988,23 @@ static int hub_configure(struct usb_hub *hub,
 		goto fail;
 	}
 
+	if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) {
+		ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+				HUB_SET_DEPTH, USB_RT_HUB,
+				hdev->level - 1, 0, NULL, 0,
+				USB_CTRL_SET_TIMEOUT);
+
+		if (ret < 0) {
+			message = "can't set hub depth";
+			goto fail;
+		}
+	}
+
 	/* Request the entire hub descriptor.
 	 * hub->descriptor can handle USB_MAXCHILDREN ports,
 	 * but the hub can/will return fewer bytes here.
 	 */
-	ret = get_hub_descriptor(hdev, hub->descriptor,
-			sizeof(*hub->descriptor));
+	ret = get_hub_descriptor(hdev, hub->descriptor);
 	if (ret < 0) {
 		message = "can't read hub descriptor";
 		goto fail;
@@ -991,12 +1026,14 @@ static int hub_configure(struct usb_hub *hub,
 
 	wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
 
-	if (wHubCharacteristics & HUB_CHAR_COMPOUND) {
+	/* FIXME for USB 3.0, skip for now */
+	if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&
+			!(hub_is_superspeed(hdev))) {
 		int	i;
 		char	portstr [USB_MAXCHILDREN + 1];
 
 		for (i = 0; i < hdev->maxchild; i++)
-			portstr[i] = hub->descriptor->DeviceRemovable
+			portstr[i] = hub->descriptor->u.hs.DeviceRemovable
 				    [((i + 1) / 8)] & (1 << ((i + 1) % 8))
 				? 'F' : 'R';
 		portstr[hdev->maxchild] = 0;
@@ -1253,8 +1290,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
 
-	/* Hubs have proper suspend/resume support */
-	usb_enable_autosuspend(hdev);
+	/* Hubs have proper suspend/resume support.  USB 3.0 device suspend is
+	 * different from USB 2.0/1.1 device suspend, and unfortunately we
+	 * don't support it yet.  So leave autosuspend disabled for USB 3.0
+	 * external hubs for now.  Enable autosuspend for USB 3.0 roothubs,
+	 * since that isn't a "real" hub.
+	 */
+	if (!hub_is_superspeed(hdev) || !hdev->parent)
+		usb_enable_autosuspend(hdev);
 
 	if (hdev->level == MAX_TOPO_LEVEL) {
 		dev_err(&intf->dev,
@@ -1465,6 +1508,7 @@ void usb_set_device_state(struct usb_device *udev,
 		enum usb_device_state new_state)
 {
 	unsigned long flags;
+	int wakeup = -1;
 
 	spin_lock_irqsave(&device_state_lock, flags);
 	if (udev->state == USB_STATE_NOTATTACHED)
@@ -1479,11 +1523,10 @@ void usb_set_device_state(struct usb_device *udev,
 					|| new_state == USB_STATE_SUSPENDED)
 				;	/* No change to wakeup settings */
 			else if (new_state == USB_STATE_CONFIGURED)
-				device_set_wakeup_capable(&udev->dev,
-					(udev->actconfig->desc.bmAttributes
-					 & USB_CONFIG_ATT_WAKEUP));
+				wakeup = udev->actconfig->desc.bmAttributes
+					 & USB_CONFIG_ATT_WAKEUP;
 			else
-				device_set_wakeup_capable(&udev->dev, 0);
+				wakeup = 0;
 		}
 		if (udev->state == USB_STATE_SUSPENDED &&
 			new_state != USB_STATE_SUSPENDED)
@@ -1495,10 +1538,19 @@ void usb_set_device_state(struct usb_device *udev,
 	} else
 		recursively_mark_NOTATTACHED(udev);
 	spin_unlock_irqrestore(&device_state_lock, flags);
+	if (wakeup >= 0)
+		device_set_wakeup_capable(&udev->dev, wakeup);
 }
 EXPORT_SYMBOL_GPL(usb_set_device_state);
 
 /*
+ * Choose a device number.
+ *
+ * Device numbers are used as filenames in usbfs.  On USB-1.1 and
+ * USB-2.0 buses they are also used as device addresses, however on
+ * USB-3.0 buses the address is assigned by the controller hardware
+ * and it usually is not the same as the device number.
+ *
  * WUSB devices are simple: they have no hubs behind, so the mapping
  * device <-> virtual port number becomes 1:1. Why? to simplify the
  * life of the device connection logic in
@@ -1520,7 +1572,7 @@ EXPORT_SYMBOL_GPL(usb_set_device_state);
  * the HCD must setup data structures before issuing a set address
  * command to the hardware.
  */
-static void choose_address(struct usb_device *udev)
+static void choose_devnum(struct usb_device *udev)
 {
 	int		devnum;
 	struct usb_bus	*bus = udev->bus;
@@ -1545,7 +1597,7 @@ static void choose_address(struct usb_device *udev)
 	}
 }
 
-static void release_address(struct usb_device *udev)
+static void release_devnum(struct usb_device *udev)
 {
 	if (udev->devnum > 0) {
 		clear_bit(udev->devnum, udev->bus->devmap.devicemap);
@@ -1553,7 +1605,7 @@ static void release_address(struct usb_device *udev)
 	}
 }
 
-static void update_address(struct usb_device *udev, int devnum)
+static void update_devnum(struct usb_device *udev, int devnum)
 {
 	/* The address for a WUSB device is managed by wusbcore. */
 	if (!udev->wusb)
@@ -1600,7 +1652,8 @@ void usb_disconnect(struct usb_device **pdev)
 	 * this quiesces everyting except pending urbs.
 	 */
 	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
-	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);
+	dev_info(&udev->dev, "USB disconnect, device number %d\n",
+			udev->devnum);
 
 	usb_lock_device(udev);
 
@@ -1630,7 +1683,7 @@ void usb_disconnect(struct usb_device **pdev)
 	/* Free the device number and delete the parent's children[]
 	 * (or root_hub) pointer.
 	 */
-	release_address(udev);
+	release_devnum(udev);
 
 	/* Avoid races with recursively_mark_NOTATTACHED() */
 	spin_lock_irq(&device_state_lock);
@@ -2015,7 +2068,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
 		    (portstatus & USB_PORT_STAT_ENABLE)) {
 			if (hub_is_wusb(hub))
 				udev->speed = USB_SPEED_WIRELESS;
-			else if (portstatus & USB_PORT_STAT_SUPER_SPEED)
+			else if (hub_is_superspeed(hub->hdev))
 				udev->speed = USB_SPEED_SUPER;
 			else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
 				udev->speed = USB_SPEED_HIGH;
@@ -2071,7 +2124,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
 		case 0:
 			/* TRSTRCY = 10 ms; plus some extra */
 			msleep(10 + 40);
-			update_address(udev, 0);
+			update_devnum(udev, 0);
 			if (hcd->driver->reset_device) {
 				status = hcd->driver->reset_device(hcd, udev);
 				if (status < 0) {
@@ -2634,7 +2687,7 @@ static int hub_set_address(struct usb_device *udev, int devnum)
 				USB_REQ_SET_ADDRESS, 0, devnum, 0,
 				NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval == 0) {
-		update_address(udev, devnum);
+		update_devnum(udev, devnum);
 		/* Device now using proper address. */
 		usb_set_device_state(udev, USB_STATE_ADDRESS);
 		usb_ep0_reinit(udev);
@@ -2739,9 +2792,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 	}
 	if (udev->speed != USB_SPEED_SUPER)
 		dev_info(&udev->dev,
-				"%s %s speed %sUSB device using %s and address %d\n",
+				"%s %s speed %sUSB device number %d using %s\n",
 				(udev->config) ? "reset" : "new", speed, type,
-				udev->bus->controller->driver->name, devnum);
+				devnum, udev->bus->controller->driver->name);
 
 	/* Set up TT records, if needed  */
 	if (hdev->tt) {
@@ -2771,10 +2824,6 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 	 * value.
 	 */
 	for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
-		/*
-		 * An xHCI controller cannot send any packets to a device until
-		 * a set address command successfully completes.
-		 */
 		if (USE_NEW_SCHEME(retry_counter) && !(hcd->driver->flags & HCD_USB3)) {
 			struct usb_device_descriptor *buf;
 			int r = 0;
@@ -2857,9 +2906,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 			if (udev->speed == USB_SPEED_SUPER) {
 				devnum = udev->devnum;
 				dev_info(&udev->dev,
-						"%s SuperSpeed USB device using %s and address %d\n",
+						"%s SuperSpeed USB device number %d using %s\n",
 						(udev->config) ? "reset" : "new",
-						udev->bus->controller->driver->name, devnum);
+						devnum, udev->bus->controller->driver->name);
 			}
 
 			/* cope with hardware quirkiness:
@@ -2922,7 +2971,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 fail:
 	if (retval) {
 		hub_port_disable(hub, port1, 0);
-		update_address(udev, devnum);	/* for disconnect processing */
+		update_devnum(udev, devnum);	/* for disconnect processing */
 	}
 	mutex_unlock(&usb_address0_mutex);
 	return retval;
@@ -3013,7 +3062,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 
 	dev_dbg (hub_dev,
 		"port %d, status %04x, change %04x, %s\n",
-		port1, portstatus, portchange, portspeed (portstatus));
+		port1, portstatus, portchange, portspeed(hub, portstatus));
 
 	if (hub->has_indicators) {
 		set_port_led(hub, port1, HUB_LED_AUTO);
@@ -3114,32 +3163,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
 		udev->level = hdev->level + 1;
 		udev->wusb = hub_is_wusb(hub);
 
-		/*
-		 * USB 3.0 devices are reset automatically before the connect
-		 * port status change appears, and the root hub port status
-		 * shows the correct speed.  We also get port change
-		 * notifications for USB 3.0 devices from the USB 3.0 portion of
-		 * an external USB 3.0 hub, but this isn't handled correctly yet
-		 * FIXME.
-		 */
-
-		if (!(hcd->driver->flags & HCD_USB3))
-			udev->speed = USB_SPEED_UNKNOWN;
-		else if ((hdev->parent == NULL) &&
-				(portstatus & USB_PORT_STAT_SUPER_SPEED))
+		/* Only USB 3.0 devices are connected to SuperSpeed hubs. */
+		if (hub_is_superspeed(hub->hdev))
 			udev->speed = USB_SPEED_SUPER;
 		else
 			udev->speed = USB_SPEED_UNKNOWN;
 
-		/*
-		 * Set the address.
-		 * Note xHCI needs to issue an address device command later
-		 * in the hub_port_init sequence for SS/HS/FS/LS devices,
-		 * and xHC will assign an address to the device. But use
-		 * kernel assigned address here, to avoid any address conflict
-		 * issue.
-		 */
-		choose_address(udev);
+		choose_devnum(udev);
 		if (udev->devnum <= 0) {
 			status = -ENOTCONN;	/* Don't retry */
 			goto loop;
@@ -3231,7 +3261,7 @@ loop_disable:
 		hub_port_disable(hub, port1, 1);
 loop:
 		usb_ep0_reinit(udev);
-		release_address(udev);
+		release_devnum(udev);
 		hub_free_dev(udev);
 		usb_put_dev(udev);
 		if ((status == -ENOTCONN) || (status == -ENOTSUPP))
@@ -3408,12 +3438,19 @@ static void hub_events(void)
 			}
 			
 			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
-				dev_err (hub_dev,
-					"over-current change on port %d\n",
-					i);
+				u16 status = 0;
+				u16 unused;
+
+				dev_dbg(hub_dev, "over-current change on port "
+					"%d\n", i);
 				clear_port_feature(hdev, i,
 					USB_PORT_FEAT_C_OVER_CURRENT);
+				msleep(100);	/* Cool down */
 				hub_power_on(hub, true);
+				hub_port_status(hub, i, &status, &unused);
+				if (status & USB_PORT_STAT_OVERCURRENT)
+					dev_err(hub_dev, "over-current "
+						"condition on port %d\n", i);
 			}
 
 			if (portchange & USB_PORT_STAT_C_RESET) {
@@ -3423,6 +3460,25 @@ static void hub_events(void)
 				clear_port_feature(hdev, i,
 					USB_PORT_FEAT_C_RESET);
 			}
+			if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
+					hub_is_superspeed(hub->hdev)) {
+				dev_dbg(hub_dev,
+					"warm reset change on port %d\n",
+					i);
+				clear_port_feature(hdev, i,
+					USB_PORT_FEAT_C_BH_PORT_RESET);
+			}
+			if (portchange & USB_PORT_STAT_C_LINK_STATE) {
+				clear_port_feature(hub->hdev, i,
+						USB_PORT_FEAT_C_PORT_LINK_STATE);
+			}
+			if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) {
+				dev_warn(hub_dev,
+					"config error on port %d\n",
+					i);
+				clear_port_feature(hub->hdev, i,
+						USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
+			}
 
 			if (connect_change)
 				hub_port_connect_change(hub, i,
@@ -3445,10 +3501,17 @@ static void hub_events(void)
 					hub->limited_power = 0;
 			}
 			if (hubchange & HUB_CHANGE_OVERCURRENT) {
-				dev_dbg (hub_dev, "overcurrent change\n");
-				msleep(500);	/* Cool down */
+				u16 status = 0;
+				u16 unused;
+
+				dev_dbg(hub_dev, "over-current change\n");
 				clear_hub_feature(hdev, C_HUB_OVER_CURRENT);
+				msleep(500);	/* Cool down */
                         	hub_power_on(hub, true);
+				hub_hub_status(hub, &status, &unused);
+				if (status & HUB_STATUS_OVERCURRENT)
+					dev_err(hub_dev, "over-current "
+						"condition\n");
 			}
 		}
 
@@ -3697,13 +3760,13 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
 	if (!udev->actconfig)
 		goto done;
 
-	mutex_lock(&hcd->bandwidth_mutex);
+	mutex_lock(hcd->bandwidth_mutex);
 	ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL);
 	if (ret < 0) {
 		dev_warn(&udev->dev,
 				"Busted HC?  Not enough HCD resources for "
 				"old configuration.\n");
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		goto re_enumerate;
 	}
 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
@@ -3714,10 +3777,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
 		dev_err(&udev->dev,
 			"can't restore configuration #%d (error=%d)\n",
 			udev->actconfig->desc.bConfigurationValue, ret);
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		goto re_enumerate;
   	}
-	mutex_unlock(&hcd->bandwidth_mutex);
+	mutex_unlock(hcd->bandwidth_mutex);
 	usb_set_device_state(udev, USB_STATE_CONFIGURED);
 
 	/* Put interfaces back into the same altsettings as before.
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 8324874..5701e85 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1284,12 +1284,12 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 	/* Make sure we have enough bandwidth for this alternate interface.
 	 * Remove the current alt setting and add the new alt setting.
 	 */
-	mutex_lock(&hcd->bandwidth_mutex);
+	mutex_lock(hcd->bandwidth_mutex);
 	ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
 	if (ret < 0) {
 		dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",
 				alternate);
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		return ret;
 	}
 
@@ -1311,10 +1311,10 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 	} else if (ret < 0) {
 		/* Re-instate the old alt setting */
 		usb_hcd_alloc_bandwidth(dev, NULL, alt, iface->cur_altsetting);
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		return ret;
 	}
-	mutex_unlock(&hcd->bandwidth_mutex);
+	mutex_unlock(hcd->bandwidth_mutex);
 
 	/* FIXME drivers shouldn't need to replicate/bugfix the logic here
 	 * when they implement async or easily-killable versions of this or
@@ -1413,7 +1413,7 @@ int usb_reset_configuration(struct usb_device *dev)
 
 	config = dev->actconfig;
 	retval = 0;
-	mutex_lock(&hcd->bandwidth_mutex);
+	mutex_lock(hcd->bandwidth_mutex);
 	/* Make sure we have enough bandwidth for each alternate setting 0 */
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
 		struct usb_interface *intf = config->interface[i];
@@ -1442,7 +1442,7 @@ reset_old_alts:
 				usb_hcd_alloc_bandwidth(dev, NULL,
 						alt, intf->cur_altsetting);
 		}
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		return retval;
 	}
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -1451,7 +1451,7 @@ reset_old_alts:
 			NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval < 0)
 		goto reset_old_alts;
-	mutex_unlock(&hcd->bandwidth_mutex);
+	mutex_unlock(hcd->bandwidth_mutex);
 
 	/* re-init hc/hcd interface/endpoint state */
 	for (i = 0; i < config->desc.bNumInterfaces; i++) {
@@ -1739,10 +1739,10 @@ free_interfaces:
 	 * host controller will not allow submissions to dropped endpoints.  If
 	 * this call fails, the device state is unchanged.
 	 */
-	mutex_lock(&hcd->bandwidth_mutex);
+	mutex_lock(hcd->bandwidth_mutex);
 	ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
 	if (ret < 0) {
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		usb_autosuspend_device(dev);
 		goto free_interfaces;
 	}
@@ -1761,11 +1761,11 @@ free_interfaces:
 	if (!cp) {
 		usb_set_device_state(dev, USB_STATE_ADDRESS);
 		usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
-		mutex_unlock(&hcd->bandwidth_mutex);
+		mutex_unlock(hcd->bandwidth_mutex);
 		usb_autosuspend_device(dev);
 		goto free_interfaces;
 	}
-	mutex_unlock(&hcd->bandwidth_mutex);
+	mutex_unlock(hcd->bandwidth_mutex);
 	usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
 	/* Initialize the new interface structures and the
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index c14fc08..ae334b0 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -366,7 +366,16 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 	if (xfertype == USB_ENDPOINT_XFER_ISOC) {
 		int	n, len;
 
-		/* FIXME SuperSpeed isoc endpoints have up to 16 bursts */
+		/* SuperSpeed isoc endpoints have up to 16 bursts of up to
+		 * 3 packets each
+		 */
+		if (dev->speed == USB_SPEED_SUPER) {
+			int     burst = 1 + ep->ss_ep_comp.bMaxBurst;
+			int     mult = USB_SS_MULT(ep->ss_ep_comp.bmAttributes);
+			max *= burst;
+			max *= mult;
+		}
+
 		/* "high bandwidth" mode, 1-3 packets/uframe? */
 		if (dev->speed == USB_SPEED_HIGH) {
 			int	mult = 1 + ((max >> 11) & 0x03);
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 079cb57..d9d4b16 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -315,6 +315,11 @@ 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
+	.runtime_suspend =	usb_runtime_suspend,
+	.runtime_resume =	usb_runtime_resume,
+	.runtime_idle =		usb_runtime_idle,
+#endif
 };
 
 #endif	/* CONFIG_PM */
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index b975450..d450b74 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -77,6 +77,9 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 extern void usb_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
 extern int usb_remote_wakeup(struct usb_device *dev);
+extern int usb_runtime_suspend(struct device *dev);
+extern int usb_runtime_resume(struct device *dev);
+extern int usb_runtime_idle(struct device *dev);
 
 #else
 
@@ -122,6 +125,19 @@ static inline int is_usb_device_driver(struct device_driver *drv)
 			for_devices;
 }
 
+/* translate USB error codes to codes user space understands */
+static inline int usb_translate_errors(int error_code)
+{
+	switch (error_code) {
+	case 0:
+	case -ENOMEM:
+	case -ENODEV:
+		return error_code;
+	default:
+		return -EIO;
+	}
+}
+
 
 /* for labeling diagnostics */
 extern const char *usbcore_name;
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c
index 94ecdbc..0bc06e2 100644
--- a/drivers/usb/early/ehci-dbgp.c
+++ b/drivers/usb/early/ehci-dbgp.c
@@ -601,7 +601,7 @@ try_again:
 		dbgp_printk("dbgp_bulk_write failed: %d\n", ret);
 		goto err;
 	}
-	dbgp_printk("small write doned\n");
+	dbgp_printk("small write done\n");
 	dbgp_not_safe = 0;
 
 	return 0;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d500996..bc5123c 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -176,15 +176,15 @@ config USB_FSL_USB2
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
-config USB_GADGET_LH7A40X
-	boolean "LH7A40X"
-	depends on ARCH_LH7A40X
+config USB_GADGET_FUSB300
+	boolean "Faraday FUSB300 USB Peripheral Controller"
+	select USB_GADGET_DUALSPEED
 	help
-	   This driver provides USB Device Controller driver for LH7A40x
+	   Faraday usb device controller FUSB300 driver
 
-config USB_LH7A40X
+config USB_FUSB300
 	tristate
-	depends on USB_GADGET_LH7A40X
+	depends on USB_GADGET_FUSB300
 	default USB_GADGET
 	select USB_GADGET_SELECTED
 
@@ -540,7 +540,7 @@ config USB_GADGET_CI13XXX_MSM
 	boolean "MIPS USB CI13xxx for MSM"
 	depends on ARCH_MSM
 	select USB_GADGET_DUALSPEED
-	select USB_MSM_OTG_72K
+	select USB_MSM_OTG
 	help
 	  MSM SoC has chipidea USB controller.  This driver uses
 	  ci13xxx_udc core.
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 55f5e8a..1ea15ee 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_USB_PXA27X)	+= pxa27x_udc.o
 obj-$(CONFIG_USB_IMX)		+= imx_udc.o
 obj-$(CONFIG_USB_GOKU)		+= goku_udc.o
 obj-$(CONFIG_USB_OMAP)		+= omap_udc.o
-obj-$(CONFIG_USB_LH7A40X)	+= lh7a40x_udc.o
 obj-$(CONFIG_USB_S3C2410)	+= s3c2410_udc.o
 obj-$(CONFIG_USB_AT91)		+= at91_udc.o
 obj-$(CONFIG_USB_ATMEL_USBA)	+= atmel_usba_udc.o
@@ -28,6 +27,7 @@ obj-$(CONFIG_USB_EG20T)		+= pch_udc.o
 obj-$(CONFIG_USB_PXA_U2O)	+= mv_udc.o
 mv_udc-y			:= mv_udc_core.o mv_udc_phy.o
 obj-$(CONFIG_USB_CI13XXX_MSM)	+= ci13xxx_msm.o
+obj-$(CONFIG_USB_FUSB300)	+= fusb300_udc.o
 
 #
 # USB gadget drivers
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index bdec36a..bb8ddf0 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1798,8 +1798,10 @@ static int __init at91udc_probe(struct platform_device *pdev)
 	}
 
 	retval = device_register(&udc->gadget.dev);
-	if (retval < 0)
+	if (retval < 0) {
+		put_device(&udc->gadget.dev);
 		goto fail0b;
+	}
 
 	/* don't do anything until we have both gadget driver and VBUS */
 	clk_enable(udc->iclk);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index a1c67ae..e09178b 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -435,20 +435,6 @@ static int hw_ep_get_halt(int num, int dir)
 }
 
 /**
- * hw_ep_is_primed: test if endpoint is primed (execute without interruption)
- * @num:   endpoint number
- * @dir:   endpoint direction
- *
- * This function returns true if endpoint primed
- */
-static int hw_ep_is_primed(int num, int dir)
-{
-	u32 reg = hw_cread(CAP_ENDPTPRIME, ~0) | hw_cread(CAP_ENDPTSTAT, ~0);
-
-	return test_bit(hw_ep_bit(num, dir), (void *)&reg);
-}
-
-/**
  * hw_test_and_clear_setup_status: test & clear setup status (execute without
  *                                 interruption)
  * @n: bit number (endpoint)
@@ -472,10 +458,6 @@ static int hw_ep_prime(int num, int dir, int is_ctrl)
 {
 	int n = hw_ep_bit(num, dir);
 
-	/* the caller should flush first */
-	if (hw_ep_is_primed(num, dir))
-		return -EBUSY;
-
 	if (is_ctrl && dir == RX && hw_cread(CAP_ENDPTSETUPSTAT, BIT(num)))
 		return -EAGAIN;
 
@@ -1434,6 +1416,8 @@ static inline u8 _usb_addr(struct ci13xxx_ep *ep)
 static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 {
 	unsigned i;
+	int ret = 0;
+	unsigned length = mReq->req.length;
 
 	trace("%p, %p", mEp, mReq);
 
@@ -1441,53 +1425,91 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 	if (mReq->req.status == -EALREADY)
 		return -EALREADY;
 
-	if (hw_ep_is_primed(mEp->num, mEp->dir))
-		return -EBUSY;
-
 	mReq->req.status = -EALREADY;
-
-	if (mReq->req.length && !mReq->req.dma) {
+	if (length && !mReq->req.dma) {
 		mReq->req.dma = \
 			dma_map_single(mEp->device, mReq->req.buf,
-				       mReq->req.length, mEp->dir ?
-				       DMA_TO_DEVICE : DMA_FROM_DEVICE);
+				       length, mEp->dir ? DMA_TO_DEVICE :
+				       DMA_FROM_DEVICE);
 		if (mReq->req.dma == 0)
 			return -ENOMEM;
 
 		mReq->map = 1;
 	}
 
+	if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) {
+		mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC,
+					   &mReq->zdma);
+		if (mReq->zptr == NULL) {
+			if (mReq->map) {
+				dma_unmap_single(mEp->device, mReq->req.dma,
+					length, mEp->dir ? DMA_TO_DEVICE :
+					DMA_FROM_DEVICE);
+				mReq->req.dma = 0;
+				mReq->map     = 0;
+			}
+			return -ENOMEM;
+		}
+		memset(mReq->zptr, 0, sizeof(*mReq->zptr));
+		mReq->zptr->next    = TD_TERMINATE;
+		mReq->zptr->token   = TD_STATUS_ACTIVE;
+		if (!mReq->req.no_interrupt)
+			mReq->zptr->token   |= TD_IOC;
+	}
 	/*
 	 * TD configuration
 	 * TODO - handle requests which spawns into several TDs
 	 */
 	memset(mReq->ptr, 0, sizeof(*mReq->ptr));
-	mReq->ptr->next    |= TD_TERMINATE;
-	mReq->ptr->token    = mReq->req.length << ffs_nr(TD_TOTAL_BYTES);
+	mReq->ptr->token    = length << ffs_nr(TD_TOTAL_BYTES);
 	mReq->ptr->token   &= TD_TOTAL_BYTES;
-	mReq->ptr->token   |= TD_IOC;
 	mReq->ptr->token   |= TD_STATUS_ACTIVE;
+	if (mReq->zptr) {
+		mReq->ptr->next    = mReq->zdma;
+	} else {
+		mReq->ptr->next    = TD_TERMINATE;
+		if (!mReq->req.no_interrupt)
+			mReq->ptr->token  |= TD_IOC;
+	}
 	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;
 
-	/*
-	 *  QH configuration
-	 *  At this point it's guaranteed exclusive access to qhead
-	 *  (endpt is not primed) so it's no need to use tripwire
-	 */
+	if (!list_empty(&mEp->qh.queue)) {
+		struct ci13xxx_req *mReqPrev;
+		int n = hw_ep_bit(mEp->num, mEp->dir);
+		int tmp_stat;
+
+		mReqPrev = list_entry(mEp->qh.queue.prev,
+				struct ci13xxx_req, queue);
+		if (mReqPrev->zptr)
+			mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
+		else
+			mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
+		wmb();
+		if (hw_cread(CAP_ENDPTPRIME, BIT(n)))
+			goto done;
+		do {
+			hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
+			tmp_stat = hw_cread(CAP_ENDPTSTAT, BIT(n));
+		} while (!hw_cread(CAP_USBCMD, USBCMD_ATDTW));
+		hw_cwrite(CAP_USBCMD, USBCMD_ATDTW, 0);
+		if (tmp_stat)
+			goto done;
+	}
+
+	/*  QH configuration */
 	mEp->qh.ptr->td.next   = mReq->dma;    /* TERMINATE = 0 */
 	mEp->qh.ptr->td.token &= ~TD_STATUS;   /* clear status */
-	if (mReq->req.zero == 0)
-		mEp->qh.ptr->cap |=  QH_ZLT;
-	else
-		mEp->qh.ptr->cap &= ~QH_ZLT;
+	mEp->qh.ptr->cap |=  QH_ZLT;
 
 	wmb();   /* synchronize before ep prime */
 
-	return hw_ep_prime(mEp->num, mEp->dir,
+	ret = hw_ep_prime(mEp->num, mEp->dir,
 			   mEp->type == USB_ENDPOINT_XFER_CONTROL);
+done:
+	return ret;
 }
 
 /**
@@ -1504,8 +1526,15 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 	if (mReq->req.status != -EALREADY)
 		return -EINVAL;
 
-	if (hw_ep_is_primed(mEp->num, mEp->dir))
-		hw_ep_flush(mEp->num, mEp->dir);
+	if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
+		return -EBUSY;
+
+	if (mReq->zptr) {
+		if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
+			return -EBUSY;
+		dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+		mReq->zptr = NULL;
+	}
 
 	mReq->req.status = 0;
 
@@ -1517,9 +1546,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 	}
 
 	mReq->req.status = mReq->ptr->token & TD_STATUS;
-	if      ((TD_STATUS_ACTIVE & mReq->req.status) != 0)
-		mReq->req.status = -ECONNRESET;
-	else if ((TD_STATUS_HALTED & mReq->req.status) != 0)
+	if ((TD_STATUS_HALTED & mReq->req.status) != 0)
 		mReq->req.status = -1;
 	else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
 		mReq->req.status = -1;
@@ -1581,12 +1608,19 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
 {
 	struct usb_ep *ep;
 	struct ci13xxx    *udc = container_of(gadget, struct ci13xxx, gadget);
+	unsigned long flags;
 
 	trace("%p", gadget);
 
 	if (gadget == NULL)
 		return -EINVAL;
 
+	spin_lock_irqsave(udc->lock, flags);
+	udc->gadget.speed = USB_SPEED_UNKNOWN;
+	udc->remote_wakeup = 0;
+	udc->suspended = 0;
+	spin_unlock_irqrestore(udc->lock, flags);
+
 	/* flush all endpoints */
 	gadget_for_each_ep(ep, gadget) {
 		usb_ep_fifo_flush(ep);
@@ -1720,7 +1754,8 @@ __acquires(mEp->lock)
 	}
 
 	if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
-		/* TODO: D1 - Remote Wakeup; D0 - Self Powered */
+		/* Assume that device is bus powered for now. */
+		*((u16 *)req->buf) = _udc->remote_wakeup << 1;
 		retval = 0;
 	} else if ((setup->bRequestType & USB_RECIP_MASK) \
 		   == USB_RECIP_ENDPOINT) {
@@ -1749,6 +1784,28 @@ __acquires(mEp->lock)
 }
 
 /**
+ * isr_setup_status_complete: setup_status request complete function
+ * @ep:  endpoint
+ * @req: request handled
+ *
+ * Caller must release lock. Put the port in test mode if test mode
+ * feature is selected.
+ */
+static void
+isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct ci13xxx *udc = req->context;
+	unsigned long flags;
+
+	trace("%p, %p", ep, req);
+
+	spin_lock_irqsave(udc->lock, flags);
+	if (udc->test_mode)
+		hw_port_test_set(udc->test_mode);
+	spin_unlock_irqrestore(udc->lock, flags);
+}
+
+/**
  * isr_setup_status_phase: queues the status phase of a setup transation
  * @udc: udc struct
  *
@@ -1764,6 +1821,8 @@ __acquires(mEp->lock)
 	trace("%p", udc);
 
 	mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
+	udc->status->context = udc;
+	udc->status->complete = isr_setup_status_complete;
 
 	spin_unlock(mEp->lock);
 	retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
@@ -1783,7 +1842,7 @@ static int isr_tr_complete_low(struct ci13xxx_ep *mEp)
 __releases(mEp->lock)
 __acquires(mEp->lock)
 {
-	struct ci13xxx_req *mReq;
+	struct ci13xxx_req *mReq, *mReqTemp;
 	int retval;
 
 	trace("%p", mEp);
@@ -1791,34 +1850,25 @@ __acquires(mEp->lock)
 	if (list_empty(&mEp->qh.queue))
 		return -EINVAL;
 
-	/* pop oldest request */
-	mReq = list_entry(mEp->qh.queue.next,
-			  struct ci13xxx_req, queue);
-	list_del_init(&mReq->queue);
-
-	retval = _hardware_dequeue(mEp, mReq);
-	if (retval < 0) {
-		dbg_event(_usb_addr(mEp), "DONE", retval);
-		goto done;
-	}
-
-	dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
-
-	if (!list_empty(&mEp->qh.queue)) {
-		struct ci13xxx_req* mReqEnq;
-
-		mReqEnq = list_entry(mEp->qh.queue.next,
-				  struct ci13xxx_req, queue);
-		_hardware_enqueue(mEp, mReqEnq);
+	list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
+			queue) {
+		retval = _hardware_dequeue(mEp, mReq);
+		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);
+			mReq->req.complete(&mEp->ep, &mReq->req);
+			spin_lock(mEp->lock);
+		}
 	}
 
-	if (mReq->req.complete != NULL) {
-		spin_unlock(mEp->lock);
-		mReq->req.complete(&mEp->ep, &mReq->req);
-		spin_lock(mEp->lock);
-	}
+	if (retval == EBUSY)
+		retval = 0;
+	if (retval < 0)
+		dbg_event(_usb_addr(mEp), "DONE", retval);
 
- done:
 	return retval;
 }
 
@@ -1833,6 +1883,7 @@ __releases(udc->lock)
 __acquires(udc->lock)
 {
 	unsigned i;
+	u8 tmode = 0;
 
 	trace("%p", udc);
 
@@ -1895,22 +1946,32 @@ __acquires(udc->lock)
 
 		switch (req.bRequest) {
 		case USB_REQ_CLEAR_FEATURE:
-			if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
-			    le16_to_cpu(req.wValue) != USB_ENDPOINT_HALT)
-				goto delegate;
-			if (req.wLength != 0)
-				break;
-			num  = le16_to_cpu(req.wIndex);
-			num &= USB_ENDPOINT_NUMBER_MASK;
-			if (!udc->ci13xxx_ep[num].wedge) {
-				spin_unlock(udc->lock);
-				err = usb_ep_clear_halt(
-					&udc->ci13xxx_ep[num].ep);
-				spin_lock(udc->lock);
-				if (err)
+			if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
+					le16_to_cpu(req.wValue) ==
+					USB_ENDPOINT_HALT) {
+				if (req.wLength != 0)
 					break;
+				num  = le16_to_cpu(req.wIndex);
+				num &= USB_ENDPOINT_NUMBER_MASK;
+				if (!udc->ci13xxx_ep[num].wedge) {
+					spin_unlock(udc->lock);
+					err = usb_ep_clear_halt(
+						&udc->ci13xxx_ep[num].ep);
+					spin_lock(udc->lock);
+					if (err)
+						break;
+				}
+				err = isr_setup_status_phase(udc);
+			} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
+					le16_to_cpu(req.wValue) ==
+					USB_DEVICE_REMOTE_WAKEUP) {
+				if (req.wLength != 0)
+					break;
+				udc->remote_wakeup = 0;
+				err = isr_setup_status_phase(udc);
+			} else {
+				goto delegate;
 			}
-			err = isr_setup_status_phase(udc);
 			break;
 		case USB_REQ_GET_STATUS:
 			if (type != (USB_DIR_IN|USB_RECIP_DEVICE)   &&
@@ -1934,20 +1995,48 @@ __acquires(udc->lock)
 			err = isr_setup_status_phase(udc);
 			break;
 		case USB_REQ_SET_FEATURE:
-			if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
-			    le16_to_cpu(req.wValue) != USB_ENDPOINT_HALT)
-				goto delegate;
-			if (req.wLength != 0)
-				break;
-			num  = le16_to_cpu(req.wIndex);
-			num &= USB_ENDPOINT_NUMBER_MASK;
+			if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
+					le16_to_cpu(req.wValue) ==
+					USB_ENDPOINT_HALT) {
+				if (req.wLength != 0)
+					break;
+				num  = le16_to_cpu(req.wIndex);
+				num &= USB_ENDPOINT_NUMBER_MASK;
 
-			spin_unlock(udc->lock);
-			err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
-			spin_lock(udc->lock);
-			if (err)
-				break;
-			err = isr_setup_status_phase(udc);
+				spin_unlock(udc->lock);
+				err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
+				spin_lock(udc->lock);
+				if (!err)
+					isr_setup_status_phase(udc);
+			} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
+				if (req.wLength != 0)
+					break;
+				switch (le16_to_cpu(req.wValue)) {
+				case USB_DEVICE_REMOTE_WAKEUP:
+					udc->remote_wakeup = 1;
+					err = isr_setup_status_phase(udc);
+					break;
+				case USB_DEVICE_TEST_MODE:
+					tmode = le16_to_cpu(req.wIndex) >> 8;
+					switch (tmode) {
+					case TEST_J:
+					case TEST_K:
+					case TEST_SE0_NAK:
+					case TEST_PACKET:
+					case TEST_FORCE_EN:
+						udc->test_mode = tmode;
+						err = isr_setup_status_phase(
+								udc);
+						break;
+					default:
+						break;
+					}
+				default:
+					goto delegate;
+				}
+			} else {
+				goto delegate;
+			}
 			break;
 		default:
 delegate:
@@ -2178,15 +2267,15 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
 	/* push request */
 	mReq->req.status = -EINPROGRESS;
 	mReq->req.actual = 0;
-	list_add_tail(&mReq->queue, &mEp->qh.queue);
 
-	if (list_is_singular(&mEp->qh.queue))
-		retval = _hardware_enqueue(mEp, mReq);
+	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:
 	spin_unlock_irqrestore(mEp->lock, flags);
@@ -2206,19 +2295,25 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 
 	trace("%p, %p", ep, req);
 
-	if (ep == NULL || req == NULL || mEp->desc == NULL ||
-	    list_empty(&mReq->queue)  || list_empty(&mEp->qh.queue))
+	if (ep == NULL || req == NULL || mReq->req.status != -EALREADY ||
+		mEp->desc == NULL || list_empty(&mReq->queue) ||
+		list_empty(&mEp->qh.queue))
 		return -EINVAL;
 
 	spin_lock_irqsave(mEp->lock, flags);
 
 	dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
 
-	if (mReq->req.status == -EALREADY)
-		_hardware_dequeue(mEp, mReq);
+	hw_ep_flush(mEp->num, mEp->dir);
 
 	/* pop request */
 	list_del_init(&mReq->queue);
+	if (mReq->map) {
+		dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
+				 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+		mReq->req.dma = 0;
+		mReq->map     = 0;
+	}
 	req->status = -ECONNRESET;
 
 	if (mReq->req.complete != NULL) {
@@ -2377,6 +2472,31 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
 	return 0;
 }
 
+static int ci13xxx_wakeup(struct usb_gadget *_gadget)
+{
+	struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
+	unsigned long flags;
+	int ret = 0;
+
+	trace();
+
+	spin_lock_irqsave(udc->lock, flags);
+	if (!udc->remote_wakeup) {
+		ret = -EOPNOTSUPP;
+		dbg_trace("remote wakeup feature is not enabled\n");
+		goto out;
+	}
+	if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
+		ret = -EINVAL;
+		dbg_trace("port is not suspended\n");
+		goto out;
+	}
+	hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
+out:
+	spin_unlock_irqrestore(udc->lock, flags);
+	return ret;
+}
+
 /**
  * Device operations part of the API to the USB controller hardware,
  * which don't involve endpoints (or i/o)
@@ -2384,6 +2504,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
  */
 static const struct usb_gadget_ops usb_gadget_ops = {
 	.vbus_session	= ci13xxx_vbus_session,
+	.wakeup		= ci13xxx_wakeup,
 };
 
 /**
@@ -2626,6 +2747,12 @@ static irqreturn_t udc_irq(void)
 			isr_statistics.pci++;
 			udc->gadget.speed = hw_port_is_high_speed() ?
 				USB_SPEED_HIGH : USB_SPEED_FULL;
+			if (udc->suspended) {
+				spin_unlock(udc->lock);
+				udc->driver->resume(&udc->gadget);
+				spin_lock(udc->lock);
+				udc->suspended = 0;
+			}
 		}
 		if (USBi_UEI & intr)
 			isr_statistics.uei++;
@@ -2633,8 +2760,15 @@ static irqreturn_t udc_irq(void)
 			isr_statistics.ui++;
 			isr_tr_complete_handler(udc);
 		}
-		if (USBi_SLI & intr)
+		if (USBi_SLI & intr) {
+			if (udc->gadget.speed != USB_SPEED_UNKNOWN) {
+				udc->suspended = 1;
+				spin_unlock(udc->lock);
+				udc->driver->suspend(&udc->gadget);
+				spin_lock(udc->lock);
+			}
 			isr_statistics.sli++;
+		}
 		retval = IRQ_HANDLED;
 	} else {
 		isr_statistics.none++;
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index a2492b6..2370777 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -33,6 +33,7 @@ struct ci13xxx_td {
 	/* 0 */
 	u32 next;
 #define TD_TERMINATE          BIT(0)
+#define TD_ADDR_MASK          (0xFFFFFFEUL << 5)
 	/* 1 */
 	u32 token;
 #define TD_STATUS             (0x00FFUL <<  0)
@@ -74,6 +75,8 @@ struct ci13xxx_req {
 	struct list_head     queue;
 	struct ci13xxx_td   *ptr;
 	dma_addr_t           dma;
+	struct ci13xxx_td   *zptr;
+	dma_addr_t           zdma;
 };
 
 /* Extension of usb_ep */
@@ -125,6 +128,10 @@ struct ci13xxx {
 	u32                        ep0_dir;    /* ep0 direction */
 #define ep0out ci13xxx_ep[0]
 #define ep0in  ci13xxx_ep[16]
+	u8                         remote_wakeup; /* Is remote wakeup feature
+							enabled by the host? */
+	u8                         suspended;  /* suspended by the host */
+	u8                         test_mode;  /* the selected test mode */
 
 	struct usb_gadget_driver  *driver;     /* 3rd party gadget driver */
 	struct ci13xxx_udc_driver *udc_driver; /* device controller driver */
@@ -152,6 +159,7 @@ struct ci13xxx {
 #define USBCMD_RS             BIT(0)
 #define USBCMD_RST            BIT(1)
 #define USBCMD_SUTW           BIT(13)
+#define USBCMD_ATDTW          BIT(14)
 
 /* USBSTS & USBINTR */
 #define USBi_UI               BIT(0)
@@ -165,6 +173,7 @@ struct ci13xxx {
 #define DEVICEADDR_USBADR     (0x7FUL << 25)
 
 /* PORTSC */
+#define PORTSC_FPR            BIT(6)
 #define PORTSC_SUSP           BIT(7)
 #define PORTSC_HSP            BIT(9)
 #define PORTSC_PTC            (0x0FUL << 16)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 1ba4bef..c2251c4 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -813,7 +813,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 	 */
 	req->zero = 0;
 	req->complete = composite_setup_complete;
-	req->length = USB_BUFSIZ;
+	req->length = 0;
 	gadget->ep0->driver_data = cdev;
 
 	switch (ctrl->bRequest) {
@@ -887,7 +887,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
 			goto unknown;
-		if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
 			break;
 		f = cdev->config->interface[intf];
 		if (!f)
@@ -899,7 +899,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 	case USB_REQ_GET_INTERFACE:
 		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
 			goto unknown;
-		if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
 			break;
 		f = cdev->config->interface[intf];
 		if (!f)
@@ -928,7 +928,7 @@ unknown:
 		 */
 		switch (ctrl->bRequestType & USB_RECIP_MASK) {
 		case USB_RECIP_INTERFACE:
-			if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)
+			if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
 				break;
 			f = cdev->config->interface[intf];
 			break;
@@ -1258,16 +1258,16 @@ static struct usb_gadget_driver composite_driver = {
  * while it was binding.  That would usually be done in order to wait for
  * some userspace participation.
  */
-extern int usb_composite_probe(struct usb_composite_driver *driver,
+int usb_composite_probe(struct usb_composite_driver *driver,
 			       int (*bind)(struct usb_composite_dev *cdev))
 {
 	if (!driver || !driver->dev || !bind || composite)
 		return -EINVAL;
 
-	if (!driver->iProduct)
-		driver->iProduct = driver->name;
 	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;
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 13b9f47..3214ca3 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -1593,8 +1593,8 @@ hub_descriptor (struct usb_hub_descriptor *desc)
 	desc->bDescLength = 9;
 	desc->wHubCharacteristics = cpu_to_le16(0x0001);
 	desc->bNbrPorts = 1;
-	desc->bitmap [0] = 0xff;
-	desc->bitmap [1] = 0xff;
+	desc->u.hs.DeviceRemovable[0] = 0xff;
+	desc->u.hs.DeviceRemovable[1] = 0xff;
 }
 
 static int dummy_hub_control (
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 8a83248..9b7360f 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -128,6 +128,13 @@ ep_matches (
 		}
 	}
 
+	/*
+	 * 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.
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 1499f9e..19fffcc 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -368,6 +368,14 @@ static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len)
 	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);
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index 77b1eb5..43a49ec 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -88,15 +88,18 @@ eenahb:
 void fsl_udc_clk_finalize(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-#if defined(CONFIG_ARCH_MX35)
-	unsigned int v;
-
-	/* workaround ENGcm09152 for i.MX35 */
-	if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
-		v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-				USBPHYCTRL_OTGBASE_OFFSET));
-		writel(v | USBPHYCTRL_EVDO, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-				USBPHYCTRL_OTGBASE_OFFSET));
+#if defined(CONFIG_SOC_IMX35)
+	if (cpu_is_mx35()) {
+		unsigned int v;
+
+		/* workaround ENGcm09152 for i.MX35 */
+		if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+			v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
+					USBPHYCTRL_OTGBASE_OFFSET));
+			writel(v | USBPHYCTRL_EVDO,
+				MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
+					USBPHYCTRL_OTGBASE_OFFSET));
+		}
 	}
 #endif
 
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c
index 792d5ef..aee7e3c 100644
--- a/drivers/usb/gadget/fsl_qe_udc.c
+++ b/drivers/usb/gadget/fsl_qe_udc.c
@@ -2523,8 +2523,7 @@ static void qe_udc_release(struct device *dev)
 }
 
 /* Driver probe functions */
-static int __devinit qe_udc_probe(struct platform_device *ofdev,
-			const struct of_device_id *match)
+static int __devinit qe_udc_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct qe_ep *ep;
@@ -2532,6 +2531,9 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev,
 	unsigned int i;
 	const void *prop;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+
 	prop = of_get_property(np, "mode", NULL);
 	if (!prop || strcmp(prop, "peripheral"))
 		return -ENODEV;
@@ -2543,7 +2545,7 @@ static int __devinit qe_udc_probe(struct platform_device *ofdev,
 		return -ENOMEM;
 	}
 
-	udc_controller->soc_type = (unsigned long)match->data;
+	udc_controller->soc_type = (unsigned long)ofdev->dev.of_match->data;
 	udc_controller->usb_regs = of_iomap(np, 0);
 	if (!udc_controller->usb_regs) {
 		ret = -ENOMEM;
@@ -2768,7 +2770,7 @@ static const struct of_device_id qe_udc_match[] __devinitconst = {
 
 MODULE_DEVICE_TABLE(of, qe_udc_match);
 
-static struct of_platform_driver udc_driver = {
+static struct platform_driver udc_driver = {
 	.driver = {
 		.name = (char *)driver_name,
 		.owner = THIS_MODULE,
@@ -2786,12 +2788,12 @@ static int __init qe_udc_init(void)
 {
 	printk(KERN_INFO "%s: %s, %s\n", driver_name, driver_desc,
 			DRIVER_VERSION);
-	return of_register_platform_driver(&udc_driver);
+	return platform_driver_register(&udc_driver);
 }
 
 static void __exit qe_udc_exit(void)
 {
-	of_unregister_platform_driver(&udc_driver);
+	platform_driver_unregister(&udc_driver);
 }
 
 module_init(qe_udc_init);
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 4c55eda..912cb8e 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -766,7 +766,6 @@ 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 is_iso = 0;
 
 	/* catch various bogus parameters */
 	if (!_req || !req->req.complete || !req->req.buf
@@ -781,7 +780,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 	if (ep->desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) {
 		if (req->req.length > ep->ep.maxpacket)
 			return -EMSGSIZE;
-		is_iso = 1;
 	}
 
 	udc = ep->udc;
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
new file mode 100644
index 0000000..763d462
--- /dev/null
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -0,0 +1,1744 @@
+/*
+ * Fusb300 UDC (USB gadget)
+ *
+ * Copyright (C) 2010 Faraday Technology Corp.
+ *
+ * Author : Yuan-hsin Chen <yhchen@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "fusb300_udc.h"
+
+MODULE_DESCRIPTION("FUSB300  USB gadget driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yuan Hsin Chen <yhchen@faraday-tech.com>");
+MODULE_ALIAS("platform:fusb300_udc");
+
+#define DRIVER_VERSION	"20 October 2010"
+
+static const char udc_name[] = "fusb300_udc";
+static const char * const fusb300_ep_name[] = {
+	"ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7", "ep8", "ep9",
+	"ep10", "ep11", "ep12", "ep13", "ep14", "ep15"
+};
+
+static void done(struct fusb300_ep *ep, struct fusb300_request *req,
+		 int status);
+
+static void fusb300_enable_bit(struct fusb300 *fusb300, u32 offset,
+			       u32 value)
+{
+	u32 reg = ioread32(fusb300->reg + offset);
+
+	reg |= value;
+	iowrite32(reg, fusb300->reg + offset);
+}
+
+static void fusb300_disable_bit(struct fusb300 *fusb300, u32 offset,
+				u32 value)
+{
+	u32 reg = ioread32(fusb300->reg + offset);
+
+	reg &= ~value;
+	iowrite32(reg, fusb300->reg + offset);
+}
+
+
+static void fusb300_ep_setting(struct fusb300_ep *ep,
+			       struct fusb300_ep_info info)
+{
+	ep->epnum = info.epnum;
+	ep->type = info.type;
+}
+
+static int fusb300_ep_release(struct fusb300_ep *ep)
+{
+	if (!ep->epnum)
+		return 0;
+	ep->epnum = 0;
+	ep->stall = 0;
+	ep->wedged = 0;
+	return 0;
+}
+
+static void fusb300_set_fifo_entry(struct fusb300 *fusb300,
+				   u32 ep)
+{
+	u32 val = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+
+	val &= ~FUSB300_EPSET1_FIFOENTRY_MSK;
+	val |= FUSB300_EPSET1_FIFOENTRY(FUSB300_FIFO_ENTRY_NUM);
+	iowrite32(val, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+}
+
+static void fusb300_set_start_entry(struct fusb300 *fusb300,
+				    u8 ep)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+	u32 start_entry = fusb300->fifo_entry_num * FUSB300_FIFO_ENTRY_NUM;
+
+	reg &= ~FUSB300_EPSET1_START_ENTRY_MSK	;
+	reg |= FUSB300_EPSET1_START_ENTRY(start_entry);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+	if (fusb300->fifo_entry_num == FUSB300_MAX_FIFO_ENTRY) {
+		fusb300->fifo_entry_num = 0;
+		fusb300->addrofs = 0;
+		pr_err("fifo entry is over the maximum number!\n");
+	} else
+		fusb300->fifo_entry_num++;
+}
+
+/* set fusb300_set_start_entry first before fusb300_set_epaddrofs */
+static void fusb300_set_epaddrofs(struct fusb300 *fusb300,
+				  struct fusb300_ep_info info)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+
+	reg &= ~FUSB300_EPSET2_ADDROFS_MSK;
+	reg |= FUSB300_EPSET2_ADDROFS(fusb300->addrofs);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+	fusb300->addrofs += (info.maxpacket + 7) / 8 * FUSB300_FIFO_ENTRY_NUM;
+}
+
+static void ep_fifo_setting(struct fusb300 *fusb300,
+			    struct fusb300_ep_info info)
+{
+	fusb300_set_fifo_entry(fusb300, info.epnum);
+	fusb300_set_start_entry(fusb300, info.epnum);
+	fusb300_set_epaddrofs(fusb300, info);
+}
+
+static void fusb300_set_eptype(struct fusb300 *fusb300,
+			       struct fusb300_ep_info info)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+
+	reg &= ~FUSB300_EPSET1_TYPE_MSK;
+	reg |= FUSB300_EPSET1_TYPE(info.type);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void fusb300_set_epdir(struct fusb300 *fusb300,
+			      struct fusb300_ep_info info)
+{
+	u32 reg;
+
+	if (!info.dir_in)
+		return;
+	reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+	reg &= ~FUSB300_EPSET1_DIR_MSK;
+	reg |= FUSB300_EPSET1_DIRIN;
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void fusb300_set_ep_active(struct fusb300 *fusb300,
+			  u8 ep)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+
+	reg |= FUSB300_EPSET1_ACTEN;
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(ep));
+}
+
+static void fusb300_set_epmps(struct fusb300 *fusb300,
+			      struct fusb300_ep_info info)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+
+	reg &= ~FUSB300_EPSET2_MPS_MSK;
+	reg |= FUSB300_EPSET2_MPS(info.maxpacket);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET2(info.epnum));
+}
+
+static void fusb300_set_interval(struct fusb300 *fusb300,
+				 struct fusb300_ep_info info)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+
+	reg &= ~FUSB300_EPSET1_INTERVAL(0x7);
+	reg |= FUSB300_EPSET1_INTERVAL(info.interval);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void fusb300_set_bwnum(struct fusb300 *fusb300,
+			      struct fusb300_ep_info info)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+
+	reg &= ~FUSB300_EPSET1_BWNUM(0x3);
+	reg |= FUSB300_EPSET1_BWNUM(info.bw_num);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET1(info.epnum));
+}
+
+static void set_ep_reg(struct fusb300 *fusb300,
+		      struct fusb300_ep_info info)
+{
+	fusb300_set_eptype(fusb300, info);
+	fusb300_set_epdir(fusb300, info);
+	fusb300_set_epmps(fusb300, info);
+
+	if (info.interval)
+		fusb300_set_interval(fusb300, info);
+
+	if (info.bw_num)
+		fusb300_set_bwnum(fusb300, info);
+
+	fusb300_set_ep_active(fusb300, info.epnum);
+}
+
+static int config_ep(struct fusb300_ep *ep,
+		     const struct usb_endpoint_descriptor *desc)
+{
+	struct fusb300 *fusb300 = ep->fusb300;
+	struct fusb300_ep_info info;
+
+	ep->desc = desc;
+
+	info.interval = 0;
+	info.addrofs = 0;
+	info.bw_num = 0;
+
+	info.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+	info.dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0;
+	info.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
+	info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+
+	if ((info.type == USB_ENDPOINT_XFER_INT) ||
+	   (info.type == USB_ENDPOINT_XFER_ISOC)) {
+		info.interval = desc->bInterval;
+		if (info.type == USB_ENDPOINT_XFER_ISOC)
+			info.bw_num = ((desc->wMaxPacketSize & 0x1800) >> 11);
+	}
+
+	ep_fifo_setting(fusb300, info);
+
+	set_ep_reg(fusb300, info);
+
+	fusb300_ep_setting(ep, info);
+
+	fusb300->ep[info.epnum] = ep;
+
+	return 0;
+}
+
+static int fusb300_enable(struct usb_ep *_ep,
+			  const struct usb_endpoint_descriptor *desc)
+{
+	struct fusb300_ep *ep;
+
+	ep = container_of(_ep, struct fusb300_ep, ep);
+
+	if (ep->fusb300->reenum) {
+		ep->fusb300->fifo_entry_num = 0;
+		ep->fusb300->addrofs = 0;
+		ep->fusb300->reenum = 0;
+	}
+
+	return config_ep(ep, desc);
+}
+
+static int fusb300_disable(struct usb_ep *_ep)
+{
+	struct fusb300_ep *ep;
+	struct fusb300_request *req;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct fusb300_ep, ep);
+
+	BUG_ON(!ep);
+
+	while (!list_empty(&ep->queue)) {
+		req = list_entry(ep->queue.next, struct fusb300_request, queue);
+		spin_lock_irqsave(&ep->fusb300->lock, flags);
+		done(ep, req, -ECONNRESET);
+		spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+	}
+
+	return fusb300_ep_release(ep);
+}
+
+static struct usb_request *fusb300_alloc_request(struct usb_ep *_ep,
+						gfp_t gfp_flags)
+{
+	struct fusb300_request *req;
+
+	req = kzalloc(sizeof(struct fusb300_request), gfp_flags);
+	if (!req)
+		return NULL;
+	INIT_LIST_HEAD(&req->queue);
+
+	return &req->req;
+}
+
+static void fusb300_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct fusb300_request *req;
+
+	req = container_of(_req, struct fusb300_request, req);
+	kfree(req);
+}
+
+static int enable_fifo_int(struct fusb300_ep *ep)
+{
+	struct fusb300 *fusb300 = ep->fusb300;
+
+	if (ep->epnum) {
+		fusb300_enable_bit(fusb300, FUSB300_OFFSET_IGER0,
+			FUSB300_IGER0_EEPn_FIFO_INT(ep->epnum));
+	} else {
+		pr_err("can't enable_fifo_int ep0\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int disable_fifo_int(struct fusb300_ep *ep)
+{
+	struct fusb300 *fusb300 = ep->fusb300;
+
+	if (ep->epnum) {
+		fusb300_disable_bit(fusb300, FUSB300_OFFSET_IGER0,
+			FUSB300_IGER0_EEPn_FIFO_INT(ep->epnum));
+	} else {
+		pr_err("can't disable_fifo_int ep0\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void fusb300_set_cxlen(struct fusb300 *fusb300, u32 length)
+{
+	u32 reg;
+
+	reg = ioread32(fusb300->reg + FUSB300_OFFSET_CSR);
+	reg &= ~FUSB300_CSR_LEN_MSK;
+	reg |= FUSB300_CSR_LEN(length);
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_CSR);
+}
+
+/* write data to cx fifo */
+static void fusb300_wrcxf(struct fusb300_ep *ep,
+		   struct fusb300_request *req)
+{
+	int i = 0;
+	u8 *tmp;
+	u32 data;
+	struct fusb300 *fusb300 = ep->fusb300;
+	u32 length = req->req.length - req->req.actual;
+
+	tmp = req->req.buf + req->req.actual;
+
+	if (length > SS_CTL_MAX_PACKET_SIZE) {
+		fusb300_set_cxlen(fusb300, SS_CTL_MAX_PACKET_SIZE);
+		for (i = (SS_CTL_MAX_PACKET_SIZE >> 2); i > 0; i--) {
+			data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16 |
+				*(tmp + 3) << 24;
+			iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+			tmp += 4;
+		}
+		req->req.actual += SS_CTL_MAX_PACKET_SIZE;
+	} else { /* length is less than max packet size */
+		fusb300_set_cxlen(fusb300, length);
+		for (i = length >> 2; i > 0; i--) {
+			data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16 |
+				*(tmp + 3) << 24;
+			printk(KERN_DEBUG "    0x%x\n", data);
+			iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+			tmp = tmp + 4;
+		}
+		switch (length % 4) {
+		case 1:
+			data = *tmp;
+			printk(KERN_DEBUG "    0x%x\n", data);
+			iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+			break;
+		case 2:
+			data = *tmp | *(tmp + 1) << 8;
+			printk(KERN_DEBUG "    0x%x\n", data);
+			iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+			break;
+		case 3:
+			data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
+			printk(KERN_DEBUG "    0x%x\n", data);
+			iowrite32(data, fusb300->reg + FUSB300_OFFSET_CXPORT);
+			break;
+		default:
+			break;
+		}
+		req->req.actual += length;
+	}
+}
+
+static void fusb300_set_epnstall(struct fusb300 *fusb300, u8 ep)
+{
+	fusb300_enable_bit(fusb300, FUSB300_OFFSET_EPSET0(ep),
+		FUSB300_EPSET0_STL);
+}
+
+static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
+
+	if (reg & FUSB300_EPSET0_STL) {
+		printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
+		reg &= ~FUSB300_EPSET0_STL;
+		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
+	}
+}
+
+static void ep0_queue(struct fusb300_ep *ep, struct fusb300_request *req)
+{
+	if (ep->fusb300->ep0_dir) { /* if IN */
+		if (req->req.length) {
+			fusb300_wrcxf(ep, req);
+		} else
+			printk(KERN_DEBUG "%s : req->req.length = 0x%x\n",
+				__func__, req->req.length);
+		if ((req->req.length == req->req.actual) ||
+		    (req->req.actual < ep->ep.maxpacket))
+			done(ep, req, 0);
+	} else { /* OUT */
+		if (!req->req.length)
+			done(ep, req, 0);
+		else
+			fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER1,
+				FUSB300_IGER1_CX_OUT_INT);
+	}
+}
+
+static int fusb300_queue(struct usb_ep *_ep, struct usb_request *_req,
+			 gfp_t gfp_flags)
+{
+	struct fusb300_ep *ep;
+	struct fusb300_request *req;
+	unsigned long flags;
+	int request  = 0;
+
+	ep = container_of(_ep, struct fusb300_ep, ep);
+	req = container_of(_req, struct fusb300_request, req);
+
+	if (ep->fusb300->gadget.speed == USB_SPEED_UNKNOWN)
+		return -ESHUTDOWN;
+
+	spin_lock_irqsave(&ep->fusb300->lock, flags);
+
+	if (list_empty(&ep->queue))
+		request = 1;
+
+	list_add_tail(&req->queue, &ep->queue);
+
+	req->req.actual = 0;
+	req->req.status = -EINPROGRESS;
+
+	if (ep->desc == NULL) /* ep0 */
+		ep0_queue(ep, req);
+	else if (request && !ep->stall)
+		enable_fifo_int(ep);
+
+	spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+
+	return 0;
+}
+
+static int fusb300_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+	struct fusb300_ep *ep;
+	struct fusb300_request *req;
+	unsigned long flags;
+
+	ep = container_of(_ep, struct fusb300_ep, ep);
+	req = container_of(_req, struct fusb300_request, req);
+
+	spin_lock_irqsave(&ep->fusb300->lock, flags);
+	if (!list_empty(&ep->queue))
+		done(ep, req, -ECONNRESET);
+	spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+
+	return 0;
+}
+
+static int fusb300_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedge)
+{
+	struct fusb300_ep *ep;
+	struct fusb300 *fusb300;
+	unsigned long flags;
+	int ret = 0;
+
+	ep = container_of(_ep, struct fusb300_ep, ep);
+
+	fusb300 = ep->fusb300;
+
+	spin_lock_irqsave(&ep->fusb300->lock, flags);
+
+	if (!list_empty(&ep->queue)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	if (value) {
+		fusb300_set_epnstall(fusb300, ep->epnum);
+		ep->stall = 1;
+		if (wedge)
+			ep->wedged = 1;
+	} else {
+		fusb300_clear_epnstall(fusb300, ep->epnum);
+		ep->stall = 0;
+		ep->wedged = 0;
+	}
+
+out:
+	spin_unlock_irqrestore(&ep->fusb300->lock, flags);
+	return ret;
+}
+
+static int fusb300_set_halt(struct usb_ep *_ep, int value)
+{
+	return fusb300_set_halt_and_wedge(_ep, value, 0);
+}
+
+static int fusb300_set_wedge(struct usb_ep *_ep)
+{
+	return fusb300_set_halt_and_wedge(_ep, 1, 1);
+}
+
+static void fusb300_fifo_flush(struct usb_ep *_ep)
+{
+}
+
+static struct usb_ep_ops fusb300_ep_ops = {
+	.enable		= fusb300_enable,
+	.disable	= fusb300_disable,
+
+	.alloc_request	= fusb300_alloc_request,
+	.free_request	= fusb300_free_request,
+
+	.queue		= fusb300_queue,
+	.dequeue	= fusb300_dequeue,
+
+	.set_halt	= fusb300_set_halt,
+	.fifo_flush	= fusb300_fifo_flush,
+	.set_wedge	= fusb300_set_wedge,
+};
+
+/*****************************************************************************/
+static void fusb300_clear_int(struct fusb300 *fusb300, u32 offset,
+		       u32 value)
+{
+	iowrite32(value, fusb300->reg + offset);
+}
+
+static void fusb300_reset(void)
+{
+}
+
+static void fusb300_set_cxstall(struct fusb300 *fusb300)
+{
+	fusb300_enable_bit(fusb300, FUSB300_OFFSET_CSR,
+			   FUSB300_CSR_STL);
+}
+
+static void fusb300_set_cxdone(struct fusb300 *fusb300)
+{
+	fusb300_enable_bit(fusb300, FUSB300_OFFSET_CSR,
+			   FUSB300_CSR_DONE);
+}
+
+/* read data from cx fifo */
+void fusb300_rdcxf(struct fusb300 *fusb300,
+		   u8 *buffer, u32 length)
+{
+	int i = 0;
+	u8 *tmp;
+	u32 data;
+
+	tmp = buffer;
+
+	for (i = (length >> 2); i > 0; i--) {
+		data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+		printk(KERN_DEBUG "    0x%x\n", data);
+		*tmp = data & 0xFF;
+		*(tmp + 1) = (data >> 8) & 0xFF;
+		*(tmp + 2) = (data >> 16) & 0xFF;
+		*(tmp + 3) = (data >> 24) & 0xFF;
+		tmp = tmp + 4;
+	}
+
+	switch (length % 4) {
+	case 1:
+		data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+		printk(KERN_DEBUG "    0x%x\n", data);
+		*tmp = data & 0xFF;
+		break;
+	case 2:
+		data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+		printk(KERN_DEBUG "    0x%x\n", data);
+		*tmp = data & 0xFF;
+		*(tmp + 1) = (data >> 8) & 0xFF;
+		break;
+	case 3:
+		data = ioread32(fusb300->reg + FUSB300_OFFSET_CXPORT);
+		printk(KERN_DEBUG "    0x%x\n", data);
+		*tmp = data & 0xFF;
+		*(tmp + 1) = (data >> 8) & 0xFF;
+		*(tmp + 2) = (data >> 16) & 0xFF;
+		break;
+	default:
+		break;
+	}
+}
+
+#if 0
+static void fusb300_dbg_fifo(struct fusb300_ep *ep,
+				u8 entry, u16 length)
+{
+	u32 reg;
+	u32 i = 0;
+	u32 j = 0;
+
+	reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_GTM);
+	reg &= ~(FUSB300_GTM_TST_EP_ENTRY(0xF) |
+		FUSB300_GTM_TST_EP_NUM(0xF) | FUSB300_GTM_TST_FIFO_DEG);
+	reg |= (FUSB300_GTM_TST_EP_ENTRY(entry) |
+		FUSB300_GTM_TST_EP_NUM(ep->epnum) | FUSB300_GTM_TST_FIFO_DEG);
+	iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_GTM);
+
+	for (i = 0; i < (length >> 2); i++) {
+		if (i * 4 == 1024)
+			break;
+		reg = ioread32(ep->fusb300->reg +
+			FUSB300_OFFSET_BUFDBG_START + i * 4);
+		printk(KERN_DEBUG"  0x%-8x", reg);
+		j++;
+		if ((j % 4)  == 0)
+			printk(KERN_DEBUG "\n");
+	}
+
+	if (length % 4) {
+		reg = ioread32(ep->fusb300->reg +
+			FUSB300_OFFSET_BUFDBG_START + i * 4);
+		printk(KERN_DEBUG "  0x%x\n", reg);
+	}
+
+	if ((j % 4)  != 0)
+		printk(KERN_DEBUG "\n");
+
+	fusb300_disable_bit(ep->fusb300, FUSB300_OFFSET_GTM,
+		FUSB300_GTM_TST_FIFO_DEG);
+}
+
+static void fusb300_cmp_dbg_fifo(struct fusb300_ep *ep,
+				u8 entry, u16 length, u8 *golden)
+{
+	u32 reg;
+	u32 i = 0;
+	u32 golden_value;
+	u8 *tmp;
+
+	tmp = golden;
+
+	printk(KERN_DEBUG "fusb300_cmp_dbg_fifo (entry %d) : start\n", entry);
+
+	reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_GTM);
+	reg &= ~(FUSB300_GTM_TST_EP_ENTRY(0xF) |
+		FUSB300_GTM_TST_EP_NUM(0xF) | FUSB300_GTM_TST_FIFO_DEG);
+	reg |= (FUSB300_GTM_TST_EP_ENTRY(entry) |
+		FUSB300_GTM_TST_EP_NUM(ep->epnum) | FUSB300_GTM_TST_FIFO_DEG);
+	iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_GTM);
+
+	for (i = 0; i < (length >> 2); i++) {
+		if (i * 4 == 1024)
+			break;
+		golden_value = *tmp | *(tmp + 1) << 8 |
+				*(tmp + 2) << 16 | *(tmp + 3) << 24;
+
+		reg = ioread32(ep->fusb300->reg +
+			FUSB300_OFFSET_BUFDBG_START + i*4);
+
+		if (reg != golden_value) {
+			printk(KERN_DEBUG "0x%x  :  ", (u32)(ep->fusb300->reg +
+				FUSB300_OFFSET_BUFDBG_START + i*4));
+			printk(KERN_DEBUG "    golden = 0x%x, reg = 0x%x\n",
+				golden_value, reg);
+		}
+		tmp += 4;
+	}
+
+	switch (length % 4) {
+	case 1:
+		golden_value = *tmp;
+	case 2:
+		golden_value = *tmp | *(tmp + 1) << 8;
+	case 3:
+		golden_value = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
+	default:
+		break;
+
+	reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_BUFDBG_START + i*4);
+	if (reg != golden_value) {
+		printk(KERN_DEBUG "0x%x:", (u32)(ep->fusb300->reg +
+			FUSB300_OFFSET_BUFDBG_START + i*4));
+		printk(KERN_DEBUG "  golden = 0x%x, reg = 0x%x\n",
+			golden_value, reg);
+	}
+	}
+
+	printk(KERN_DEBUG "fusb300_cmp_dbg_fifo : end\n");
+	fusb300_disable_bit(ep->fusb300, FUSB300_OFFSET_GTM,
+		FUSB300_GTM_TST_FIFO_DEG);
+}
+#endif
+
+static void fusb300_rdfifo(struct fusb300_ep *ep,
+			  struct fusb300_request *req,
+			  u32 length)
+{
+	int i = 0;
+	u8 *tmp;
+	u32 data, reg;
+	struct fusb300 *fusb300 = ep->fusb300;
+
+	tmp = req->req.buf + req->req.actual;
+	req->req.actual += length;
+
+	if (req->req.actual > req->req.length)
+		printk(KERN_DEBUG "req->req.actual > req->req.length\n");
+
+	for (i = (length >> 2); i > 0; i--) {
+		data = ioread32(fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		*tmp = data & 0xFF;
+		*(tmp + 1) = (data >> 8) & 0xFF;
+		*(tmp + 2) = (data >> 16) & 0xFF;
+		*(tmp + 3) = (data >> 24) & 0xFF;
+		tmp = tmp + 4;
+	}
+
+	switch (length % 4) {
+	case 1:
+		data = ioread32(fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		*tmp = data & 0xFF;
+		break;
+	case 2:
+		data = ioread32(fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		*tmp = data & 0xFF;
+		*(tmp + 1) = (data >> 8) & 0xFF;
+		break;
+	case 3:
+		data = ioread32(fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		*tmp = data & 0xFF;
+		*(tmp + 1) = (data >> 8) & 0xFF;
+		*(tmp + 2) = (data >> 16) & 0xFF;
+		break;
+	default:
+		break;
+	}
+
+	do {
+		reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
+		reg &= FUSB300_IGR1_SYNF0_EMPTY_INT;
+		if (i)
+			printk(KERN_INFO "sync fifo is not empty!\n");
+		i++;
+	} while (!reg);
+}
+
+/* write data to fifo */
+static void fusb300_wrfifo(struct fusb300_ep *ep,
+			   struct fusb300_request *req)
+{
+	int i = 0;
+	u8 *tmp;
+	u32 data, reg;
+	struct fusb300 *fusb300 = ep->fusb300;
+
+	tmp = req->req.buf;
+	req->req.actual = req->req.length;
+
+	for (i = (req->req.length >> 2); i > 0; i--) {
+		data = *tmp | *(tmp + 1) << 8 |
+			*(tmp + 2) << 16 | *(tmp + 3) << 24;
+
+		iowrite32(data, fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		tmp += 4;
+	}
+
+	switch (req->req.length % 4) {
+	case 1:
+		data = *tmp;
+		iowrite32(data, fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		break;
+	case 2:
+		data = *tmp | *(tmp + 1) << 8;
+		iowrite32(data, fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		break;
+	case 3:
+		data = *tmp | *(tmp + 1) << 8 | *(tmp + 2) << 16;
+		iowrite32(data, fusb300->reg +
+			FUSB300_OFFSET_EPPORT(ep->epnum));
+		break;
+	default:
+		break;
+	}
+
+	do {
+		reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
+		reg &= FUSB300_IGR1_SYNF0_EMPTY_INT;
+		if (i)
+			printk(KERN_INFO"sync fifo is not empty!\n");
+		i++;
+	} while (!reg);
+}
+
+static u8 fusb300_get_epnstall(struct fusb300 *fusb300, u8 ep)
+{
+	u8 value;
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
+
+	value = reg & FUSB300_EPSET0_STL;
+
+	return value;
+}
+
+static u8 fusb300_get_cxstall(struct fusb300 *fusb300)
+{
+	u8 value;
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_CSR);
+
+	value = (reg & FUSB300_CSR_STL) >> 1;
+
+	return value;
+}
+
+static void request_error(struct fusb300 *fusb300)
+{
+	fusb300_set_cxstall(fusb300);
+	printk(KERN_DEBUG "request error!!\n");
+}
+
+static void get_status(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+__releases(fusb300->lock)
+__acquires(fusb300->lock)
+{
+	u8 ep;
+	u16 status = 0;
+	u16 w_index = ctrl->wIndex;
+
+	switch (ctrl->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_DEVICE:
+		status = 1 << USB_DEVICE_SELF_POWERED;
+		break;
+	case USB_RECIP_INTERFACE:
+		status = 0;
+		break;
+	case USB_RECIP_ENDPOINT:
+		ep = w_index & USB_ENDPOINT_NUMBER_MASK;
+		if (ep) {
+			if (fusb300_get_epnstall(fusb300, ep))
+				status = 1 << USB_ENDPOINT_HALT;
+		} else {
+			if (fusb300_get_cxstall(fusb300))
+				status = 0;
+		}
+		break;
+
+	default:
+		request_error(fusb300);
+		return;		/* exit */
+	}
+
+	fusb300->ep0_data = cpu_to_le16(status);
+	fusb300->ep0_req->buf = &fusb300->ep0_data;
+	fusb300->ep0_req->length = 2;
+
+	spin_unlock(&fusb300->lock);
+	fusb300_queue(fusb300->gadget.ep0, fusb300->ep0_req, GFP_KERNEL);
+	spin_lock(&fusb300->lock);
+}
+
+static void set_feature(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+	u8 ep;
+
+	switch (ctrl->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_DEVICE:
+		fusb300_set_cxdone(fusb300);
+		break;
+	case USB_RECIP_INTERFACE:
+		fusb300_set_cxdone(fusb300);
+		break;
+	case USB_RECIP_ENDPOINT: {
+		u16 w_index = le16_to_cpu(ctrl->wIndex);
+
+		ep = w_index & USB_ENDPOINT_NUMBER_MASK;
+		if (ep)
+			fusb300_set_epnstall(fusb300, ep);
+		else
+			fusb300_set_cxstall(fusb300);
+		fusb300_set_cxdone(fusb300);
+		}
+		break;
+	default:
+		request_error(fusb300);
+		break;
+	}
+}
+
+static void fusb300_clear_seqnum(struct fusb300 *fusb300, u8 ep)
+{
+	fusb300_enable_bit(fusb300, FUSB300_OFFSET_EPSET0(ep),
+			    FUSB300_EPSET0_CLRSEQNUM);
+}
+
+static void clear_feature(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+	struct fusb300_ep *ep =
+		fusb300->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK];
+
+	switch (ctrl->bRequestType & USB_RECIP_MASK) {
+	case USB_RECIP_DEVICE:
+		fusb300_set_cxdone(fusb300);
+		break;
+	case USB_RECIP_INTERFACE:
+		fusb300_set_cxdone(fusb300);
+		break;
+	case USB_RECIP_ENDPOINT:
+		if (ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK) {
+			if (ep->wedged) {
+				fusb300_set_cxdone(fusb300);
+				break;
+			}
+			if (ep->stall) {
+				ep->stall = 0;
+				fusb300_clear_seqnum(fusb300, ep->epnum);
+				fusb300_clear_epnstall(fusb300, ep->epnum);
+				if (!list_empty(&ep->queue))
+					enable_fifo_int(ep);
+			}
+		}
+		fusb300_set_cxdone(fusb300);
+		break;
+	default:
+		request_error(fusb300);
+		break;
+	}
+}
+
+static void fusb300_set_dev_addr(struct fusb300 *fusb300, u16 addr)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_DAR);
+
+	reg &= ~FUSB300_DAR_DRVADDR_MSK;
+	reg |= FUSB300_DAR_DRVADDR(addr);
+
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_DAR);
+}
+
+static void set_address(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+	if (ctrl->wValue >= 0x0100)
+		request_error(fusb300);
+	else {
+		fusb300_set_dev_addr(fusb300, ctrl->wValue);
+		fusb300_set_cxdone(fusb300);
+	}
+}
+
+#define UVC_COPY_DESCRIPTORS(mem, src) \
+	do { \
+		const struct usb_descriptor_header * const *__src; \
+		for (__src = src; *__src; ++__src) { \
+			memcpy(mem, *__src, (*__src)->bLength); \
+			mem += (*__src)->bLength; \
+		} \
+	} while (0)
+
+static void fusb300_ep0_complete(struct usb_ep *ep,
+				struct usb_request *req)
+{
+}
+
+static int setup_packet(struct fusb300 *fusb300, struct usb_ctrlrequest *ctrl)
+{
+	u8 *p = (u8 *)ctrl;
+	u8 ret = 0;
+	u8 i = 0;
+
+	fusb300_rdcxf(fusb300, p, 8);
+	fusb300->ep0_dir = ctrl->bRequestType & USB_DIR_IN;
+	fusb300->ep0_length = ctrl->wLength;
+
+	/* check request */
+	if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+		switch (ctrl->bRequest) {
+		case USB_REQ_GET_STATUS:
+			get_status(fusb300, ctrl);
+			break;
+		case USB_REQ_CLEAR_FEATURE:
+			clear_feature(fusb300, ctrl);
+			break;
+		case USB_REQ_SET_FEATURE:
+			set_feature(fusb300, ctrl);
+			break;
+		case USB_REQ_SET_ADDRESS:
+			set_address(fusb300, ctrl);
+			break;
+		case USB_REQ_SET_CONFIGURATION:
+			fusb300_enable_bit(fusb300, FUSB300_OFFSET_DAR,
+					   FUSB300_DAR_SETCONFG);
+			/* clear sequence number */
+			for (i = 1; i <= FUSB300_MAX_NUM_EP; i++)
+				fusb300_clear_seqnum(fusb300, i);
+			fusb300->reenum = 1;
+			ret = 1;
+			break;
+		default:
+			ret = 1;
+			break;
+		}
+	} else
+		ret = 1;
+
+	return ret;
+}
+
+static void fusb300_set_ep_bycnt(struct fusb300_ep *ep, u32 bycnt)
+{
+	struct fusb300 *fusb300 = ep->fusb300;
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
+
+	reg &= ~FUSB300_FFR_BYCNT;
+	reg |= bycnt & FUSB300_FFR_BYCNT;
+
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
+}
+
+static void done(struct fusb300_ep *ep, struct fusb300_request *req,
+		 int status)
+{
+	list_del_init(&req->queue);
+
+	/* don't modify queue heads during completion callback */
+	if (ep->fusb300->gadget.speed == USB_SPEED_UNKNOWN)
+		req->req.status = -ESHUTDOWN;
+	else
+		req->req.status = status;
+
+	spin_unlock(&ep->fusb300->lock);
+	req->req.complete(&ep->ep, &req->req);
+	spin_lock(&ep->fusb300->lock);
+
+	if (ep->epnum) {
+		disable_fifo_int(ep);
+		if (!list_empty(&ep->queue))
+			enable_fifo_int(ep);
+	} else
+		fusb300_set_cxdone(ep->fusb300);
+}
+
+void fusb300_fill_idma_prdtbl(struct fusb300_ep *ep,
+			struct fusb300_request *req)
+{
+	u32 value;
+	u32 reg;
+
+	/* wait SW owner */
+	do {
+		reg = ioread32(ep->fusb300->reg +
+			FUSB300_OFFSET_EPPRD_W0(ep->epnum));
+		reg &= FUSB300_EPPRD0_H;
+	} while (reg);
+
+	iowrite32((u32) req->req.buf, ep->fusb300->reg +
+		FUSB300_OFFSET_EPPRD_W1(ep->epnum));
+
+	value = FUSB300_EPPRD0_BTC(req->req.length) | FUSB300_EPPRD0_H |
+		FUSB300_EPPRD0_F | FUSB300_EPPRD0_L | FUSB300_EPPRD0_I;
+	iowrite32(value, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W0(ep->epnum));
+
+	iowrite32(0x0, ep->fusb300->reg + FUSB300_OFFSET_EPPRD_W2(ep->epnum));
+
+	fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_EPPRDRDY,
+		FUSB300_EPPRDR_EP_PRD_RDY(ep->epnum));
+}
+
+static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
+{
+	u32 reg;
+
+	do {
+		reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGR1);
+		if ((reg & FUSB300_IGR1_VBUS_CHG_INT) ||
+		    (reg & FUSB300_IGR1_WARM_RST_INT) ||
+		    (reg & FUSB300_IGR1_HOT_RST_INT) ||
+		    (reg & FUSB300_IGR1_USBRST_INT)
+		)
+			goto IDMA_RESET;
+		reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGR0);
+		reg &= FUSB300_IGR0_EPn_PRD_INT(ep->epnum);
+	} while (!reg);
+
+	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
+		FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
+IDMA_RESET:
+	fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
+		FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
+}
+
+static void  fusb300_set_idma(struct fusb300_ep *ep,
+			struct fusb300_request *req)
+{
+	dma_addr_t d;
+	u8 *tmp = NULL;
+
+	d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
+
+	if (dma_mapping_error(NULL, d)) {
+		kfree(req->req.buf);
+		printk(KERN_DEBUG "dma_mapping_error\n");
+	}
+
+	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));
+
+	tmp = req->req.buf;
+	req->req.buf = (u8 *)d;
+
+	fusb300_fill_idma_prdtbl(ep, req);
+	/* check idma is done */
+	fusb300_wait_idma_finished(ep);
+
+	req->req.buf = tmp;
+
+	if (d)
+		dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
+}
+
+static void in_ep_fifo_handler(struct fusb300_ep *ep)
+{
+	struct fusb300_request *req = list_entry(ep->queue.next,
+					struct fusb300_request, queue);
+
+	if (req->req.length) {
+#if 0
+		fusb300_set_ep_bycnt(ep, req->req.length);
+		fusb300_wrfifo(ep, req);
+#else
+		fusb300_set_idma(ep, req);
+#endif
+	}
+	done(ep, req, 0);
+}
+
+static void out_ep_fifo_handler(struct fusb300_ep *ep)
+{
+	struct fusb300 *fusb300 = ep->fusb300;
+	struct fusb300_request *req = list_entry(ep->queue.next,
+						 struct fusb300_request, queue);
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_EPFFR(ep->epnum));
+	u32 length = reg & FUSB300_FFR_BYCNT;
+
+	fusb300_rdfifo(ep, req, length);
+
+	/* finish out transfer */
+	if ((req->req.length == req->req.actual) || (length < ep->ep.maxpacket))
+		done(ep, req, 0);
+}
+
+static void check_device_mode(struct fusb300 *fusb300)
+{
+	u32 reg = ioread32(fusb300->reg + FUSB300_OFFSET_GCR);
+
+	switch (reg & FUSB300_GCR_DEVEN_MSK) {
+	case FUSB300_GCR_DEVEN_SS:
+		fusb300->gadget.speed = USB_SPEED_SUPER;
+		break;
+	case FUSB300_GCR_DEVEN_HS:
+		fusb300->gadget.speed = USB_SPEED_HIGH;
+		break;
+	case FUSB300_GCR_DEVEN_FS:
+		fusb300->gadget.speed = USB_SPEED_FULL;
+		break;
+	default:
+		fusb300->gadget.speed = USB_SPEED_UNKNOWN;
+		break;
+	}
+	printk(KERN_INFO "dev_mode = %d\n", (reg & FUSB300_GCR_DEVEN_MSK));
+}
+
+
+static void fusb300_ep0out(struct fusb300 *fusb300)
+{
+	struct fusb300_ep *ep = fusb300->ep[0];
+	u32 reg;
+
+	if (!list_empty(&ep->queue)) {
+		struct fusb300_request *req;
+
+		req = list_first_entry(&ep->queue,
+			struct fusb300_request, queue);
+		if (req->req.length)
+			fusb300_rdcxf(ep->fusb300, req->req.buf,
+				req->req.length);
+		done(ep, req, 0);
+		reg = ioread32(fusb300->reg + FUSB300_OFFSET_IGER1);
+		reg &= ~FUSB300_IGER1_CX_OUT_INT;
+		iowrite32(reg, fusb300->reg + FUSB300_OFFSET_IGER1);
+	} else
+		pr_err("%s : empty queue\n", __func__);
+}
+
+static void fusb300_ep0in(struct fusb300 *fusb300)
+{
+	struct fusb300_request *req;
+	struct fusb300_ep *ep = fusb300->ep[0];
+
+	if ((!list_empty(&ep->queue)) && (fusb300->ep0_dir)) {
+		req = list_entry(ep->queue.next,
+				struct fusb300_request, queue);
+		if (req->req.length)
+			fusb300_wrcxf(ep, req);
+		if ((req->req.length - req->req.actual) < ep->ep.maxpacket)
+			done(ep, req, 0);
+	} else
+		fusb300_set_cxdone(fusb300);
+}
+
+static void fusb300_grp2_handler(void)
+{
+}
+
+static void fusb300_grp3_handler(void)
+{
+}
+
+static void fusb300_grp4_handler(void)
+{
+}
+
+static void fusb300_grp5_handler(void)
+{
+}
+
+static irqreturn_t fusb300_irq(int irq, void *_fusb300)
+{
+	struct fusb300 *fusb300 = _fusb300;
+	u32 int_grp1 = ioread32(fusb300->reg + FUSB300_OFFSET_IGR1);
+	u32 int_grp1_en = ioread32(fusb300->reg + FUSB300_OFFSET_IGER1);
+	u32 int_grp0 = ioread32(fusb300->reg + FUSB300_OFFSET_IGR0);
+	u32 int_grp0_en = ioread32(fusb300->reg + FUSB300_OFFSET_IGER0);
+	struct usb_ctrlrequest ctrl;
+	u8 in;
+	u32 reg;
+	int i;
+
+	spin_lock(&fusb300->lock);
+
+	int_grp1 &= int_grp1_en;
+	int_grp0 &= int_grp0_en;
+
+	if (int_grp1 & FUSB300_IGR1_WARM_RST_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_WARM_RST_INT);
+		printk(KERN_INFO"fusb300_warmreset\n");
+		fusb300_reset();
+	}
+
+	if (int_grp1 & FUSB300_IGR1_HOT_RST_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_HOT_RST_INT);
+		printk(KERN_INFO"fusb300_hotreset\n");
+		fusb300_reset();
+	}
+
+	if (int_grp1 & FUSB300_IGR1_USBRST_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_USBRST_INT);
+		fusb300_reset();
+	}
+	/* COMABT_INT has a highest priority */
+
+	if (int_grp1 & FUSB300_IGR1_CX_COMABT_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_CX_COMABT_INT);
+		printk(KERN_INFO"fusb300_ep0abt\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_VBUS_CHG_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_VBUS_CHG_INT);
+		printk(KERN_INFO"fusb300_vbus_change\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U3_EXIT_FAIL_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U3_EXIT_FAIL_INT);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U2_EXIT_FAIL_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U2_EXIT_FAIL_INT);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U1_EXIT_FAIL_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U1_EXIT_FAIL_INT);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U2_ENTRY_FAIL_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U2_ENTRY_FAIL_INT);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U1_ENTRY_FAIL_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U1_ENTRY_FAIL_INT);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U3_EXIT_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U3_EXIT_INT);
+		printk(KERN_INFO "FUSB300_IGR1_U3_EXIT_INT\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U2_EXIT_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U2_EXIT_INT);
+		printk(KERN_INFO "FUSB300_IGR1_U2_EXIT_INT\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U1_EXIT_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U1_EXIT_INT);
+		printk(KERN_INFO "FUSB300_IGR1_U1_EXIT_INT\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U3_ENTRY_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U3_ENTRY_INT);
+		printk(KERN_INFO "FUSB300_IGR1_U3_ENTRY_INT\n");
+		fusb300_enable_bit(fusb300, FUSB300_OFFSET_SSCR1,
+				   FUSB300_SSCR1_GO_U3_DONE);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U2_ENTRY_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U2_ENTRY_INT);
+		printk(KERN_INFO "FUSB300_IGR1_U2_ENTRY_INT\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_U1_ENTRY_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_U1_ENTRY_INT);
+		printk(KERN_INFO "FUSB300_IGR1_U1_ENTRY_INT\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_RESM_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_RESM_INT);
+		printk(KERN_INFO "fusb300_resume\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_SUSP_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_SUSP_INT);
+		printk(KERN_INFO "fusb300_suspend\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_HS_LPM_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_HS_LPM_INT);
+		printk(KERN_INFO "fusb300_HS_LPM_INT\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_DEV_MODE_CHG_INT) {
+		fusb300_clear_int(fusb300, FUSB300_OFFSET_IGR1,
+				  FUSB300_IGR1_DEV_MODE_CHG_INT);
+		check_device_mode(fusb300);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_CX_COMFAIL_INT) {
+		fusb300_set_cxstall(fusb300);
+		printk(KERN_INFO "fusb300_ep0fail\n");
+	}
+
+	if (int_grp1 & FUSB300_IGR1_CX_SETUP_INT) {
+		printk(KERN_INFO "fusb300_ep0setup\n");
+		if (setup_packet(fusb300, &ctrl)) {
+			spin_unlock(&fusb300->lock);
+			if (fusb300->driver->setup(&fusb300->gadget, &ctrl) < 0)
+				fusb300_set_cxstall(fusb300);
+			spin_lock(&fusb300->lock);
+		}
+	}
+
+	if (int_grp1 & FUSB300_IGR1_CX_CMDEND_INT)
+		printk(KERN_INFO "fusb300_cmdend\n");
+
+
+	if (int_grp1 & FUSB300_IGR1_CX_OUT_INT) {
+		printk(KERN_INFO "fusb300_cxout\n");
+		fusb300_ep0out(fusb300);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_CX_IN_INT) {
+		printk(KERN_INFO "fusb300_cxin\n");
+		fusb300_ep0in(fusb300);
+	}
+
+	if (int_grp1 & FUSB300_IGR1_INTGRP5)
+		fusb300_grp5_handler();
+
+	if (int_grp1 & FUSB300_IGR1_INTGRP4)
+		fusb300_grp4_handler();
+
+	if (int_grp1 & FUSB300_IGR1_INTGRP3)
+		fusb300_grp3_handler();
+
+	if (int_grp1 & FUSB300_IGR1_INTGRP2)
+		fusb300_grp2_handler();
+
+	if (int_grp0) {
+		for (i = 1; i < FUSB300_MAX_NUM_EP; i++) {
+			if (int_grp0 & FUSB300_IGR0_EPn_FIFO_INT(i)) {
+				reg = ioread32(fusb300->reg +
+					FUSB300_OFFSET_EPSET1(i));
+				in = (reg & FUSB300_EPSET1_DIRIN) ? 1 : 0;
+				if (in)
+					in_ep_fifo_handler(fusb300->ep[i]);
+				else
+					out_ep_fifo_handler(fusb300->ep[i]);
+			}
+		}
+	}
+
+	spin_unlock(&fusb300->lock);
+
+	return IRQ_HANDLED;
+}
+
+static void fusb300_set_u2_timeout(struct fusb300 *fusb300,
+				   u32 time)
+{
+	u32 reg;
+
+	reg = ioread32(fusb300->reg + FUSB300_OFFSET_TT);
+	reg &= ~0xff;
+	reg |= FUSB300_SSCR2_U2TIMEOUT(time);
+
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_TT);
+}
+
+static void fusb300_set_u1_timeout(struct fusb300 *fusb300,
+				   u32 time)
+{
+	u32 reg;
+
+	reg = ioread32(fusb300->reg + FUSB300_OFFSET_TT);
+	reg &= ~(0xff << 8);
+	reg |= FUSB300_SSCR2_U1TIMEOUT(time);
+
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_TT);
+}
+
+static void init_controller(struct fusb300 *fusb300)
+{
+	u32 reg;
+	u32 mask = 0;
+	u32 val = 0;
+
+	/* split on */
+	mask = val = FUSB300_AHBBCR_S0_SPLIT_ON | FUSB300_AHBBCR_S1_SPLIT_ON;
+	reg = ioread32(fusb300->reg + FUSB300_OFFSET_AHBCR);
+	reg &= ~mask;
+	reg |= val;
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_AHBCR);
+
+	/* enable high-speed LPM */
+	mask = val = FUSB300_HSCR_HS_LPM_PERMIT;
+	reg = ioread32(fusb300->reg + FUSB300_OFFSET_HSCR);
+	reg &= ~mask;
+	reg |= val;
+	iowrite32(reg, fusb300->reg + FUSB300_OFFSET_HSCR);
+
+	/*set u1 u2 timmer*/
+	fusb300_set_u2_timeout(fusb300, 0xff);
+	fusb300_set_u1_timeout(fusb300, 0xff);
+
+	/* enable all grp1 interrupt */
+	iowrite32(0xcfffff9f, fusb300->reg + FUSB300_OFFSET_IGER1);
+}
+/*------------------------------------------------------------------------*/
+static struct fusb300 *the_controller;
+
+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
+		int (*bind)(struct usb_gadget *))
+{
+	struct fusb300 *fusb300 = the_controller;
+	int retval;
+
+	if (!driver
+			|| driver->speed < USB_SPEED_FULL
+			|| !bind
+			|| !driver->setup)
+		return -EINVAL;
+
+	if (!fusb300)
+		return -ENODEV;
+
+	if (fusb300->driver)
+		return -EBUSY;
+
+	/* hook up the driver */
+	driver->driver.bus = NULL;
+	fusb300->driver = driver;
+	fusb300->gadget.dev.driver = &driver->driver;
+
+	retval = device_add(&fusb300->gadget.dev);
+	if (retval) {
+		pr_err("device_add error (%d)\n", retval);
+		goto error;
+	}
+
+	retval = bind(&fusb300->gadget);
+	if (retval) {
+		pr_err("bind to driver error (%d)\n", retval);
+		device_del(&fusb300->gadget.dev);
+		goto error;
+	}
+
+	return 0;
+
+error:
+	fusb300->driver = NULL;
+	fusb300->gadget.dev.driver = NULL;
+
+	return retval;
+}
+EXPORT_SYMBOL(usb_gadget_probe_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	struct fusb300 *fusb300 = the_controller;
+
+	if (driver != fusb300->driver || !driver->unbind)
+		return -EINVAL;
+
+	driver->unbind(&fusb300->gadget);
+	fusb300->gadget.dev.driver = NULL;
+
+	init_controller(fusb300);
+	device_del(&fusb300->gadget.dev);
+	fusb300->driver = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+/*--------------------------------------------------------------------------*/
+
+static int fusb300_udc_pullup(struct usb_gadget *_gadget, int is_active)
+{
+	return 0;
+}
+
+static struct usb_gadget_ops fusb300_gadget_ops = {
+	.pullup		= fusb300_udc_pullup,
+};
+
+static int __exit fusb300_remove(struct platform_device *pdev)
+{
+	struct fusb300 *fusb300 = dev_get_drvdata(&pdev->dev);
+
+	iounmap(fusb300->reg);
+	free_irq(platform_get_irq(pdev, 0), fusb300);
+
+	fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
+	kfree(fusb300);
+
+	return 0;
+}
+
+static int __init fusb300_probe(struct platform_device *pdev)
+{
+	struct resource *res, *ires, *ires1;
+	void __iomem *reg = NULL;
+	struct fusb300 *fusb300 = NULL;
+	struct fusb300_ep *_ep[FUSB300_MAX_NUM_EP];
+	int ret = 0;
+	int i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV;
+		pr_err("platform_get_resource error.\n");
+		goto clean_up;
+	}
+
+	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!ires) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev,
+			"platform_get_resource IORESOURCE_IRQ error.\n");
+		goto clean_up;
+	}
+
+	ires1 = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+	if (!ires1) {
+		ret = -ENODEV;
+		dev_err(&pdev->dev,
+			"platform_get_resource IORESOURCE_IRQ 1 error.\n");
+		goto clean_up;
+	}
+
+	reg = ioremap(res->start, resource_size(res));
+	if (reg == NULL) {
+		ret = -ENOMEM;
+		pr_err("ioremap error.\n");
+		goto clean_up;
+	}
+
+	/* initialize udc */
+	fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
+	if (fusb300 == NULL) {
+		pr_err("kzalloc error\n");
+		goto clean_up;
+	}
+
+	for (i = 0; i < FUSB300_MAX_NUM_EP; i++) {
+		_ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL);
+		if (_ep[i] == NULL) {
+			pr_err("_ep kzalloc error\n");
+			goto clean_up;
+		}
+		fusb300->ep[i] = _ep[i];
+	}
+
+	spin_lock_init(&fusb300->lock);
+
+	dev_set_drvdata(&pdev->dev, fusb300);
+
+	fusb300->gadget.ops = &fusb300_gadget_ops;
+
+	device_initialize(&fusb300->gadget.dev);
+
+	dev_set_name(&fusb300->gadget.dev, "gadget");
+
+	fusb300->gadget.is_dualspeed = 1;
+	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;
+
+	ret = request_irq(ires->start, fusb300_irq, IRQF_DISABLED | IRQF_SHARED,
+			  udc_name, fusb300);
+	if (ret < 0) {
+		pr_err("request_irq error (%d)\n", ret);
+		goto clean_up;
+	}
+
+	ret = request_irq(ires1->start, fusb300_irq,
+			IRQF_DISABLED | IRQF_SHARED, udc_name, fusb300);
+	if (ret < 0) {
+		pr_err("request_irq1 error (%d)\n", ret);
+		goto clean_up;
+	}
+
+	INIT_LIST_HEAD(&fusb300->gadget.ep_list);
+
+	for (i = 0; i < FUSB300_MAX_NUM_EP ; i++) {
+		struct fusb300_ep *ep = fusb300->ep[i];
+
+		if (i != 0) {
+			INIT_LIST_HEAD(&fusb300->ep[i]->ep.ep_list);
+			list_add_tail(&fusb300->ep[i]->ep.ep_list,
+				     &fusb300->gadget.ep_list);
+		}
+		ep->fusb300 = fusb300;
+		INIT_LIST_HEAD(&ep->queue);
+		ep->ep.name = fusb300_ep_name[i];
+		ep->ep.ops = &fusb300_ep_ops;
+		ep->ep.maxpacket = HS_BULK_MAX_PACKET_SIZE;
+	}
+	fusb300->ep[0]->ep.maxpacket = HS_CTL_MAX_PACKET_SIZE;
+	fusb300->ep[0]->epnum = 0;
+	fusb300->gadget.ep0 = &fusb300->ep[0]->ep;
+	INIT_LIST_HEAD(&fusb300->gadget.ep0->ep_list);
+
+	the_controller = fusb300;
+
+	fusb300->ep0_req = fusb300_alloc_request(&fusb300->ep[0]->ep,
+				GFP_KERNEL);
+	if (fusb300->ep0_req == NULL)
+		goto clean_up3;
+
+	init_controller(fusb300);
+	dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
+
+	return 0;
+
+clean_up3:
+	free_irq(ires->start, fusb300);
+
+clean_up:
+	if (fusb300) {
+		if (fusb300->ep0_req)
+			fusb300_free_request(&fusb300->ep[0]->ep,
+				fusb300->ep0_req);
+		kfree(fusb300);
+	}
+	if (reg)
+		iounmap(reg);
+
+	return ret;
+}
+
+static struct platform_driver fusb300_driver = {
+	.remove =	__exit_p(fusb300_remove),
+	.driver		= {
+		.name =	(char *) udc_name,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init fusb300_udc_init(void)
+{
+	return platform_driver_probe(&fusb300_driver, fusb300_probe);
+}
+
+module_init(fusb300_udc_init);
+
+static void __exit fusb300_udc_cleanup(void)
+{
+	platform_driver_unregister(&fusb300_driver);
+}
+module_exit(fusb300_udc_cleanup);
diff --git a/drivers/usb/gadget/fusb300_udc.h b/drivers/usb/gadget/fusb300_udc.h
new file mode 100644
index 0000000..f51aa2e
--- /dev/null
+++ b/drivers/usb/gadget/fusb300_udc.h
@@ -0,0 +1,687 @@
+/*
+ * Fusb300 UDC (USB gadget)
+ *
+ * Copyright (C) 2010 Faraday Technology Corp.
+ *
+ * Author : Yuan-hsin Chen <yhchen@faraday-tech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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 __FUSB300_UDC_H__
+#define __FUSB300_UDC_H_
+
+#include <linux/kernel.h>
+
+#define FUSB300_OFFSET_GCR		0x00
+#define FUSB300_OFFSET_GTM		0x04
+#define FUSB300_OFFSET_DAR		0x08
+#define FUSB300_OFFSET_CSR		0x0C
+#define FUSB300_OFFSET_CXPORT		0x10
+#define FUSB300_OFFSET_EPSET0(n)	(0x20 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPSET1(n)	(0x24 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPSET2(n)	(0x28 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPFFR(n)		(0x2c + (n - 1) * 0x30)
+#define FUSB300_OFFSET_EPSTRID(n)	(0x40 + (n - 1) * 0x30)
+#define FUSB300_OFFSET_HSPTM		0x300
+#define FUSB300_OFFSET_HSCR		0x304
+#define FUSB300_OFFSET_SSCR0		0x308
+#define FUSB300_OFFSET_SSCR1		0x30C
+#define FUSB300_OFFSET_TT		0x310
+#define FUSB300_OFFSET_DEVNOTF		0x314
+#define FUSB300_OFFSET_DNC1		0x318
+#define FUSB300_OFFSET_CS		0x31C
+#define FUSB300_OFFSET_SOF		0x324
+#define FUSB300_OFFSET_EFCS		0x328
+#define FUSB300_OFFSET_IGR0		0x400
+#define FUSB300_OFFSET_IGR1		0x404
+#define FUSB300_OFFSET_IGR2		0x408
+#define FUSB300_OFFSET_IGR3		0x40C
+#define FUSB300_OFFSET_IGR4		0x410
+#define FUSB300_OFFSET_IGR5		0x414
+#define FUSB300_OFFSET_IGER0		0x420
+#define FUSB300_OFFSET_IGER1		0x424
+#define FUSB300_OFFSET_IGER2		0x428
+#define FUSB300_OFFSET_IGER3		0x42C
+#define FUSB300_OFFSET_IGER4		0x430
+#define FUSB300_OFFSET_IGER5		0x434
+#define FUSB300_OFFSET_DMAHMER		0x500
+#define FUSB300_OFFSET_EPPRDRDY		0x504
+#define FUSB300_OFFSET_DMAEPMR		0x508
+#define FUSB300_OFFSET_DMAENR		0x50C
+#define FUSB300_OFFSET_DMAAPR		0x510
+#define FUSB300_OFFSET_AHBCR		0x514
+#define FUSB300_OFFSET_EPPRD_W0(n)	(0x520 + (n - 1) * 0x10)
+#define FUSB300_OFFSET_EPPRD_W1(n)	(0x524 + (n - 1) * 0x10)
+#define FUSB300_OFFSET_EPPRD_W2(n)	(0x528 + (n - 1) * 0x10)
+#define FUSB300_OFFSET_EPRD_PTR(n)	(0x52C + (n - 1) * 0x10)
+#define FUSB300_OFFSET_BUFDBG_START	0x800
+#define FUSB300_OFFSET_BUFDBG_END	0xBFC
+#define FUSB300_OFFSET_EPPORT(n)	(0x1010 + (n - 1) * 0x10)
+
+/*
+ * *	Global Control Register (offset = 000H)
+ * */
+#define FUSB300_GCR_SF_RST		(1 << 8)
+#define FUSB300_GCR_VBUS_STATUS		(1 << 7)
+#define FUSB300_GCR_FORCE_HS_SUSP	(1 << 6)
+#define FUSB300_GCR_SYNC_FIFO1_CLR	(1 << 5)
+#define FUSB300_GCR_SYNC_FIFO0_CLR	(1 << 4)
+#define FUSB300_GCR_FIFOCLR		(1 << 3)
+#define FUSB300_GCR_GLINTEN		(1 << 2)
+#define FUSB300_GCR_DEVEN_FS		0x3
+#define FUSB300_GCR_DEVEN_HS		0x2
+#define FUSB300_GCR_DEVEN_SS		0x1
+#define FUSB300_GCR_DEVDIS		0x0
+#define FUSB300_GCR_DEVEN_MSK		0x3
+
+
+/*
+ * *Global Test Mode (offset = 004H)
+ * */
+#define FUSB300_GTM_TST_DIS_SOFGEN	(1 << 16)
+#define FUSB300_GTM_TST_CUR_EP_ENTRY(n)	((n & 0xF) << 12)
+#define FUSB300_GTM_TST_EP_ENTRY(n)	((n & 0xF) << 8)
+#define FUSB300_GTM_TST_EP_NUM(n)	((n & 0xF) << 4)
+#define FUSB300_GTM_TST_FIFO_DEG	(1 << 1)
+#define FUSB300_GTM_TSTMODE		(1 << 0)
+
+/*
+ * * Device Address Register (offset = 008H)
+ * */
+#define FUSB300_DAR_SETCONFG	(1 << 7)
+#define FUSB300_DAR_DRVADDR(x)	(x & 0x7F)
+#define FUSB300_DAR_DRVADDR_MSK	0x7F
+
+/*
+ * *Control Transfer Configuration and Status Register
+ * (CX_Config_Status, offset = 00CH)
+ * */
+#define FUSB300_CSR_LEN(x)	((x & 0xFFFF) << 8)
+#define FUSB300_CSR_LEN_MSK	(0xFFFF << 8)
+#define FUSB300_CSR_EMP		(1 << 4)
+#define FUSB300_CSR_FUL		(1 << 3)
+#define FUSB300_CSR_CLR		(1 << 2)
+#define FUSB300_CSR_STL		(1 << 1)
+#define FUSB300_CSR_DONE	(1 << 0)
+
+/*
+ * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
+ * */
+#define FUSB300_EPSET0_CLRSEQNUM	(1 << 2)
+#define FUSB300_EPSET0_EPn_TX0BYTE	(1 << 1)
+#define FUSB300_EPSET0_STL		(1 << 0)
+
+/*
+ * * EPn Setting 1 (EPn_SET1, offset = 024H+(n-1)*30H, n=1~15)
+ * */
+#define FUSB300_EPSET1_START_ENTRY(x)	((x & 0xFF) << 24)
+#define FUSB300_EPSET1_START_ENTRY_MSK	(0xFF << 24)
+#define FUSB300_EPSET1_FIFOENTRY(x)	((x & 0x1F) << 12)
+#define FUSB300_EPSET1_FIFOENTRY_MSK	(0x1f << 12)
+#define FUSB300_EPSET1_INTERVAL(x)	((x & 0x7) << 6)
+#define FUSB300_EPSET1_BWNUM(x)		((x & 0x3) << 4)
+#define FUSB300_EPSET1_TYPEISO		(1 << 2)
+#define FUSB300_EPSET1_TYPEBLK		(2 << 2)
+#define FUSB300_EPSET1_TYPEINT		(3 << 2)
+#define FUSB300_EPSET1_TYPE(x)		((x & 0x3) << 2)
+#define FUSB300_EPSET1_TYPE_MSK		(0x3 << 2)
+#define FUSB300_EPSET1_DIROUT		(0 << 1)
+#define FUSB300_EPSET1_DIRIN		(1 << 1)
+#define FUSB300_EPSET1_DIR(x)		((x & 0x1) << 1)
+#define FUSB300_EPSET1_DIRIN		(1 << 1)
+#define FUSB300_EPSET1_DIR_MSK		((0x1) << 1)
+#define FUSB300_EPSET1_ACTDIS		0
+#define FUSB300_EPSET1_ACTEN		1
+
+/*
+ * *EPn Setting 2 (EPn_SET2, offset = 028H+(n-1)*30H, n=1~15)
+ * */
+#define FUSB300_EPSET2_ADDROFS(x)	((x & 0x7FFF) << 16)
+#define FUSB300_EPSET2_ADDROFS_MSK	(0x7fff << 16)
+#define FUSB300_EPSET2_MPS(x)		(x & 0x7FF)
+#define FUSB300_EPSET2_MPS_MSK		0x7FF
+
+/*
+ * * EPn FIFO Register (offset = 2cH+(n-1)*30H)
+ * */
+#define FUSB300_FFR_RST		(1 << 31)
+#define FUSB300_FF_FUL		(1 << 30)
+#define FUSB300_FF_EMPTY	(1 << 29)
+#define FUSB300_FFR_BYCNT	0x1FFFF
+
+/*
+ * *EPn Stream ID (EPn_STR_ID, offset = 040H+(n-1)*30H, n=1~15)
+ * */
+#define FUSB300_STRID_STREN	(1 << 16)
+#define FUSB300_STRID_STRID(x)	(x & 0xFFFF)
+
+/*
+ * *HS PHY Test Mode (offset = 300H)
+ * */
+#define FUSB300_HSPTM_TSTPKDONE		(1 << 4)
+#define FUSB300_HSPTM_TSTPKT		(1 << 3)
+#define FUSB300_HSPTM_TSTSET0NAK	(1 << 2)
+#define FUSB300_HSPTM_TSTKSTA		(1 << 1)
+#define FUSB300_HSPTM_TSTJSTA		(1 << 0)
+
+/*
+ * *HS Control Register (offset = 304H)
+ * */
+#define FUSB300_HSCR_HS_LPM_PERMIT	(1 << 8)
+#define FUSB300_HSCR_HS_LPM_RMWKUP	(1 << 7)
+#define FUSB300_HSCR_CAP_LPM_RMWKUP	(1 << 6)
+#define FUSB300_HSCR_HS_GOSUSP		(1 << 5)
+#define FUSB300_HSCR_HS_GORMWKU		(1 << 4)
+#define FUSB300_HSCR_CAP_RMWKUP		(1 << 3)
+#define FUSB300_HSCR_IDLECNT_0MS	0
+#define FUSB300_HSCR_IDLECNT_1MS	1
+#define FUSB300_HSCR_IDLECNT_2MS	2
+#define FUSB300_HSCR_IDLECNT_3MS	3
+#define FUSB300_HSCR_IDLECNT_4MS	4
+#define FUSB300_HSCR_IDLECNT_5MS	5
+#define FUSB300_HSCR_IDLECNT_6MS	6
+#define FUSB300_HSCR_IDLECNT_7MS	7
+
+/*
+ * * SS Controller Register 0 (offset = 308H)
+ * */
+#define FUSB300_SSCR0_MAX_INTERVAL(x)	((x & 0x7) << 4)
+#define FUSB300_SSCR0_U2_FUN_EN		(1 << 1)
+#define FUSB300_SSCR0_U1_FUN_EN		(1 << 0)
+
+/*
+ * * SS Controller Register 1 (offset = 30CH)
+ * */
+#define FUSB300_SSCR1_GO_U3_DONE	(1 << 8)
+#define FUSB300_SSCR1_TXDEEMPH_LEVEL	(1 << 7)
+#define FUSB300_SSCR1_DIS_SCRMB		(1 << 6)
+#define FUSB300_SSCR1_FORCE_RECOVERY	(1 << 5)
+#define FUSB300_SSCR1_U3_WAKEUP_EN	(1 << 4)
+#define FUSB300_SSCR1_U2_EXIT_EN	(1 << 3)
+#define FUSB300_SSCR1_U1_EXIT_EN	(1 << 2)
+#define FUSB300_SSCR1_U2_ENTRY_EN	(1 << 1)
+#define FUSB300_SSCR1_U1_ENTRY_EN	(1 << 0)
+
+/*
+ * *SS Controller Register 2  (offset = 310H)
+ * */
+#define FUSB300_SSCR2_SS_TX_SWING		(1 << 25)
+#define FUSB300_SSCR2_FORCE_LINKPM_ACCEPT	(1 << 24)
+#define FUSB300_SSCR2_U2_INACT_TIMEOUT(x)	((x & 0xFF) << 16)
+#define FUSB300_SSCR2_U1TIMEOUT(x)		((x & 0xFF) << 8)
+#define FUSB300_SSCR2_U2TIMEOUT(x)		(x & 0xFF)
+
+/*
+ * *SS Device Notification Control (DEV_NOTF, offset = 314H)
+ * */
+#define FUSB300_DEVNOTF_CONTEXT0(x)		((x & 0xFFFFFF) << 8)
+#define FUSB300_DEVNOTF_TYPE_DIS		0
+#define FUSB300_DEVNOTF_TYPE_FUNCWAKE		1
+#define FUSB300_DEVNOTF_TYPE_LTM		2
+#define FUSB300_DEVNOTF_TYPE_BUSINT_ADJMSG	3
+
+/*
+ * *BFM Arbiter Priority Register (BFM_ARB offset = 31CH)
+ * */
+#define FUSB300_BFMARB_ARB_M1	(1 << 3)
+#define FUSB300_BFMARB_ARB_M0	(1 << 2)
+#define FUSB300_BFMARB_ARB_S1	(1 << 1)
+#define FUSB300_BFMARB_ARB_S0	1
+
+/*
+ * *Vendor Specific IO Control Register (offset = 320H)
+ * */
+#define FUSB300_VSIC_VCTLOAD_N	(1 << 8)
+#define FUSB300_VSIC_VCTL(x)	(x & 0x3F)
+
+/*
+ * *SOF Mask Timer (offset = 324H)
+ * */
+#define FUSB300_SOF_MASK_TIMER_HS	0x044c
+#define FUSB300_SOF_MASK_TIMER_FS	0x2710
+
+/*
+ * *Error Flag and Control Status (offset = 328H)
+ * */
+#define FUSB300_EFCS_PM_STATE_U3	3
+#define FUSB300_EFCS_PM_STATE_U2	2
+#define FUSB300_EFCS_PM_STATE_U1	1
+#define FUSB300_EFCS_PM_STATE_U0	0
+
+/*
+ * *Interrupt Group 0 Register (offset = 400H)
+ * */
+#define FUSB300_IGR0_EP15_PRD_INT	(1 << 31)
+#define FUSB300_IGR0_EP14_PRD_INT	(1 << 30)
+#define FUSB300_IGR0_EP13_PRD_INT	(1 << 29)
+#define FUSB300_IGR0_EP12_PRD_INT	(1 << 28)
+#define FUSB300_IGR0_EP11_PRD_INT	(1 << 27)
+#define FUSB300_IGR0_EP10_PRD_INT	(1 << 26)
+#define FUSB300_IGR0_EP9_PRD_INT	(1 << 25)
+#define FUSB300_IGR0_EP8_PRD_INT	(1 << 24)
+#define FUSB300_IGR0_EP7_PRD_INT	(1 << 23)
+#define FUSB300_IGR0_EP6_PRD_INT	(1 << 22)
+#define FUSB300_IGR0_EP5_PRD_INT	(1 << 21)
+#define FUSB300_IGR0_EP4_PRD_INT	(1 << 20)
+#define FUSB300_IGR0_EP3_PRD_INT	(1 << 19)
+#define FUSB300_IGR0_EP2_PRD_INT	(1 << 18)
+#define FUSB300_IGR0_EP1_PRD_INT	(1 << 17)
+#define FUSB300_IGR0_EPn_PRD_INT(n)	(1 << (n + 16))
+
+#define FUSB300_IGR0_EP15_FIFO_INT	(1 << 15)
+#define FUSB300_IGR0_EP14_FIFO_INT	(1 << 14)
+#define FUSB300_IGR0_EP13_FIFO_INT	(1 << 13)
+#define FUSB300_IGR0_EP12_FIFO_INT	(1 << 12)
+#define FUSB300_IGR0_EP11_FIFO_INT	(1 << 11)
+#define FUSB300_IGR0_EP10_FIFO_INT	(1 << 10)
+#define FUSB300_IGR0_EP9_FIFO_INT	(1 << 9)
+#define FUSB300_IGR0_EP8_FIFO_INT	(1 << 8)
+#define FUSB300_IGR0_EP7_FIFO_INT	(1 << 7)
+#define FUSB300_IGR0_EP6_FIFO_INT	(1 << 6)
+#define FUSB300_IGR0_EP5_FIFO_INT	(1 << 5)
+#define FUSB300_IGR0_EP4_FIFO_INT	(1 << 4)
+#define FUSB300_IGR0_EP3_FIFO_INT	(1 << 3)
+#define FUSB300_IGR0_EP2_FIFO_INT	(1 << 2)
+#define FUSB300_IGR0_EP1_FIFO_INT	(1 << 1)
+#define FUSB300_IGR0_EPn_FIFO_INT(n)	(1 << n)
+
+/*
+ * *Interrupt Group 1 Register (offset = 404H)
+ * */
+#define FUSB300_IGR1_INTGRP5		(1 << 31)
+#define FUSB300_IGR1_VBUS_CHG_INT	(1 << 30)
+#define FUSB300_IGR1_SYNF1_EMPTY_INT	(1 << 29)
+#define FUSB300_IGR1_SYNF0_EMPTY_INT	(1 << 28)
+#define FUSB300_IGR1_U3_EXIT_FAIL_INT	(1 << 27)
+#define FUSB300_IGR1_U2_EXIT_FAIL_INT	(1 << 26)
+#define FUSB300_IGR1_U1_EXIT_FAIL_INT	(1 << 25)
+#define FUSB300_IGR1_U2_ENTRY_FAIL_INT	(1 << 24)
+#define FUSB300_IGR1_U1_ENTRY_FAIL_INT	(1 << 23)
+#define FUSB300_IGR1_U3_EXIT_INT	(1 << 22)
+#define FUSB300_IGR1_U2_EXIT_INT	(1 << 21)
+#define FUSB300_IGR1_U1_EXIT_INT	(1 << 20)
+#define FUSB300_IGR1_U3_ENTRY_INT	(1 << 19)
+#define FUSB300_IGR1_U2_ENTRY_INT	(1 << 18)
+#define FUSB300_IGR1_U1_ENTRY_INT	(1 << 17)
+#define FUSB300_IGR1_HOT_RST_INT	(1 << 16)
+#define FUSB300_IGR1_WARM_RST_INT	(1 << 15)
+#define FUSB300_IGR1_RESM_INT		(1 << 14)
+#define FUSB300_IGR1_SUSP_INT		(1 << 13)
+#define FUSB300_IGR1_HS_LPM_INT		(1 << 12)
+#define FUSB300_IGR1_USBRST_INT		(1 << 11)
+#define FUSB300_IGR1_DEV_MODE_CHG_INT	(1 << 9)
+#define FUSB300_IGR1_CX_COMABT_INT	(1 << 8)
+#define FUSB300_IGR1_CX_COMFAIL_INT	(1 << 7)
+#define FUSB300_IGR1_CX_CMDEND_INT	(1 << 6)
+#define FUSB300_IGR1_CX_OUT_INT		(1 << 5)
+#define FUSB300_IGR1_CX_IN_INT		(1 << 4)
+#define FUSB300_IGR1_CX_SETUP_INT	(1 << 3)
+#define FUSB300_IGR1_INTGRP4		(1 << 2)
+#define FUSB300_IGR1_INTGRP3		(1 << 1)
+#define FUSB300_IGR1_INTGRP2		(1 << 0)
+
+/*
+ * *Interrupt Group 2 Register (offset = 408H)
+ * */
+#define FUSB300_IGR2_EP6_STR_ACCEPT_INT		(1 << 29)
+#define FUSB300_IGR2_EP6_STR_RESUME_INT		(1 << 28)
+#define FUSB300_IGR2_EP6_STR_REQ_INT		(1 << 27)
+#define FUSB300_IGR2_EP6_STR_NOTRDY_INT		(1 << 26)
+#define FUSB300_IGR2_EP6_STR_PRIME_INT		(1 << 25)
+#define FUSB300_IGR2_EP5_STR_ACCEPT_INT		(1 << 24)
+#define FUSB300_IGR2_EP5_STR_RESUME_INT		(1 << 23)
+#define FUSB300_IGR2_EP5_STR_REQ_INT		(1 << 22)
+#define FUSB300_IGR2_EP5_STR_NOTRDY_INT		(1 << 21)
+#define FUSB300_IGR2_EP5_STR_PRIME_INT		(1 << 20)
+#define FUSB300_IGR2_EP4_STR_ACCEPT_INT		(1 << 19)
+#define FUSB300_IGR2_EP4_STR_RESUME_INT		(1 << 18)
+#define FUSB300_IGR2_EP4_STR_REQ_INT		(1 << 17)
+#define FUSB300_IGR2_EP4_STR_NOTRDY_INT		(1 << 16)
+#define FUSB300_IGR2_EP4_STR_PRIME_INT		(1 << 15)
+#define FUSB300_IGR2_EP3_STR_ACCEPT_INT		(1 << 14)
+#define FUSB300_IGR2_EP3_STR_RESUME_INT		(1 << 13)
+#define FUSB300_IGR2_EP3_STR_REQ_INT		(1 << 12)
+#define FUSB300_IGR2_EP3_STR_NOTRDY_INT		(1 << 11)
+#define FUSB300_IGR2_EP3_STR_PRIME_INT		(1 << 10)
+#define FUSB300_IGR2_EP2_STR_ACCEPT_INT		(1 << 9)
+#define FUSB300_IGR2_EP2_STR_RESUME_INT		(1 << 8)
+#define FUSB300_IGR2_EP2_STR_REQ_INT		(1 << 7)
+#define FUSB300_IGR2_EP2_STR_NOTRDY_INT		(1 << 6)
+#define FUSB300_IGR2_EP2_STR_PRIME_INT		(1 << 5)
+#define FUSB300_IGR2_EP1_STR_ACCEPT_INT		(1 << 4)
+#define FUSB300_IGR2_EP1_STR_RESUME_INT		(1 << 3)
+#define FUSB300_IGR2_EP1_STR_REQ_INT		(1 << 2)
+#define FUSB300_IGR2_EP1_STR_NOTRDY_INT		(1 << 1)
+#define FUSB300_IGR2_EP1_STR_PRIME_INT		(1 << 0)
+
+#define FUSB300_IGR2_EP_STR_ACCEPT_INT(n)	(1 << (5 * n - 1))
+#define FUSB300_IGR2_EP_STR_RESUME_INT(n)	(1 << (5 * n - 2))
+#define FUSB300_IGR2_EP_STR_REQ_INT(n)		(1 << (5 * n - 3))
+#define FUSB300_IGR2_EP_STR_NOTRDY_INT(n)	(1 << (5 * n - 4))
+#define FUSB300_IGR2_EP_STR_PRIME_INT(n)	(1 << (5 * n - 5))
+
+/*
+ * *Interrupt Group 3 Register (offset = 40CH)
+ * */
+#define FUSB300_IGR3_EP12_STR_ACCEPT_INT	(1 << 29)
+#define FUSB300_IGR3_EP12_STR_RESUME_INT	(1 << 28)
+#define FUSB300_IGR3_EP12_STR_REQ_INT		(1 << 27)
+#define FUSB300_IGR3_EP12_STR_NOTRDY_INT	(1 << 26)
+#define FUSB300_IGR3_EP12_STR_PRIME_INT		(1 << 25)
+#define FUSB300_IGR3_EP11_STR_ACCEPT_INT	(1 << 24)
+#define FUSB300_IGR3_EP11_STR_RESUME_INT	(1 << 23)
+#define FUSB300_IGR3_EP11_STR_REQ_INT		(1 << 22)
+#define FUSB300_IGR3_EP11_STR_NOTRDY_INT	(1 << 21)
+#define FUSB300_IGR3_EP11_STR_PRIME_INT		(1 << 20)
+#define FUSB300_IGR3_EP10_STR_ACCEPT_INT	(1 << 19)
+#define FUSB300_IGR3_EP10_STR_RESUME_INT	(1 << 18)
+#define FUSB300_IGR3_EP10_STR_REQ_INT		(1 << 17)
+#define FUSB300_IGR3_EP10_STR_NOTRDY_INT	(1 << 16)
+#define FUSB300_IGR3_EP10_STR_PRIME_INT		(1 << 15)
+#define FUSB300_IGR3_EP9_STR_ACCEPT_INT		(1 << 14)
+#define FUSB300_IGR3_EP9_STR_RESUME_INT		(1 << 13)
+#define FUSB300_IGR3_EP9_STR_REQ_INT		(1 << 12)
+#define FUSB300_IGR3_EP9_STR_NOTRDY_INT		(1 << 11)
+#define FUSB300_IGR3_EP9_STR_PRIME_INT		(1 << 10)
+#define FUSB300_IGR3_EP8_STR_ACCEPT_INT		(1 << 9)
+#define FUSB300_IGR3_EP8_STR_RESUME_INT		(1 << 8)
+#define FUSB300_IGR3_EP8_STR_REQ_INT		(1 << 7)
+#define FUSB300_IGR3_EP8_STR_NOTRDY_INT		(1 << 6)
+#define FUSB300_IGR3_EP8_STR_PRIME_INT		(1 << 5)
+#define FUSB300_IGR3_EP7_STR_ACCEPT_INT		(1 << 4)
+#define FUSB300_IGR3_EP7_STR_RESUME_INT		(1 << 3)
+#define FUSB300_IGR3_EP7_STR_REQ_INT		(1 << 2)
+#define FUSB300_IGR3_EP7_STR_NOTRDY_INT		(1 << 1)
+#define FUSB300_IGR3_EP7_STR_PRIME_INT		(1 << 0)
+
+#define FUSB300_IGR3_EP_STR_ACCEPT_INT(n)	(1 << (5 * (n - 6) - 1))
+#define FUSB300_IGR3_EP_STR_RESUME_INT(n)	(1 << (5 * (n - 6) - 2))
+#define FUSB300_IGR3_EP_STR_REQ_INT(n)		(1 << (5 * (n - 6) - 3))
+#define FUSB300_IGR3_EP_STR_NOTRDY_INT(n)	(1 << (5 * (n - 6) - 4))
+#define FUSB300_IGR3_EP_STR_PRIME_INT(n)	(1 << (5 * (n - 6) - 5))
+
+/*
+ * *Interrupt Group 4 Register (offset = 410H)
+ * */
+#define FUSB300_IGR4_EP15_RX0_INT		(1 << 31)
+#define FUSB300_IGR4_EP14_RX0_INT		(1 << 30)
+#define FUSB300_IGR4_EP13_RX0_INT		(1 << 29)
+#define FUSB300_IGR4_EP12_RX0_INT		(1 << 28)
+#define FUSB300_IGR4_EP11_RX0_INT		(1 << 27)
+#define FUSB300_IGR4_EP10_RX0_INT		(1 << 26)
+#define FUSB300_IGR4_EP9_RX0_INT		(1 << 25)
+#define FUSB300_IGR4_EP8_RX0_INT		(1 << 24)
+#define FUSB300_IGR4_EP7_RX0_INT		(1 << 23)
+#define FUSB300_IGR4_EP6_RX0_INT		(1 << 22)
+#define FUSB300_IGR4_EP5_RX0_INT		(1 << 21)
+#define FUSB300_IGR4_EP4_RX0_INT		(1 << 20)
+#define FUSB300_IGR4_EP3_RX0_INT		(1 << 19)
+#define FUSB300_IGR4_EP2_RX0_INT		(1 << 18)
+#define FUSB300_IGR4_EP1_RX0_INT		(1 << 17)
+#define FUSB300_IGR4_EP_RX0_INT(x)		(1 << (x + 16))
+#define FUSB300_IGR4_EP15_STR_ACCEPT_INT	(1 << 14)
+#define FUSB300_IGR4_EP15_STR_RESUME_INT	(1 << 13)
+#define FUSB300_IGR4_EP15_STR_REQ_INT		(1 << 12)
+#define FUSB300_IGR4_EP15_STR_NOTRDY_INT	(1 << 11)
+#define FUSB300_IGR4_EP15_STR_PRIME_INT		(1 << 10)
+#define FUSB300_IGR4_EP14_STR_ACCEPT_INT	(1 << 9)
+#define FUSB300_IGR4_EP14_STR_RESUME_INT	(1 << 8)
+#define FUSB300_IGR4_EP14_STR_REQ_INT		(1 << 7)
+#define FUSB300_IGR4_EP14_STR_NOTRDY_INT	(1 << 6)
+#define FUSB300_IGR4_EP14_STR_PRIME_INT		(1 << 5)
+#define FUSB300_IGR4_EP13_STR_ACCEPT_INT	(1 << 4)
+#define FUSB300_IGR4_EP13_STR_RESUME_INT	(1 << 3)
+#define FUSB300_IGR4_EP13_STR_REQ_INT		(1 << 2)
+#define FUSB300_IGR4_EP13_STR_NOTRDY_INT	(1 << 1)
+#define FUSB300_IGR4_EP13_STR_PRIME_INT		(1 << 0)
+
+#define FUSB300_IGR4_EP_STR_ACCEPT_INT(n)	(1 << (5 * (n - 12) - 1))
+#define FUSB300_IGR4_EP_STR_RESUME_INT(n)	(1 << (5 * (n - 12) - 2))
+#define FUSB300_IGR4_EP_STR_REQ_INT(n)		(1 << (5 * (n - 12) - 3))
+#define FUSB300_IGR4_EP_STR_NOTRDY_INT(n)	(1 << (5 * (n - 12) - 4))
+#define FUSB300_IGR4_EP_STR_PRIME_INT(n)	(1 << (5 * (n - 12) - 5))
+
+/*
+ * *Interrupt Group 5 Register (offset = 414H)
+ * */
+#define FUSB300_IGR5_EP_STL_INT(n)	(1 << n)
+
+/*
+ * *Interrupt Enable Group 0 Register (offset = 420H)
+ * */
+#define FUSB300_IGER0_EEP15_PRD_INT	(1 << 31)
+#define FUSB300_IGER0_EEP14_PRD_INT	(1 << 30)
+#define FUSB300_IGER0_EEP13_PRD_INT	(1 << 29)
+#define FUSB300_IGER0_EEP12_PRD_INT	(1 << 28)
+#define FUSB300_IGER0_EEP11_PRD_INT	(1 << 27)
+#define FUSB300_IGER0_EEP10_PRD_INT	(1 << 26)
+#define FUSB300_IGER0_EEP9_PRD_INT	(1 << 25)
+#define FUSB300_IGER0_EP8_PRD_INT	(1 << 24)
+#define FUSB300_IGER0_EEP7_PRD_INT	(1 << 23)
+#define FUSB300_IGER0_EEP6_PRD_INT	(1 << 22)
+#define FUSB300_IGER0_EEP5_PRD_INT	(1 << 21)
+#define FUSB300_IGER0_EEP4_PRD_INT	(1 << 20)
+#define FUSB300_IGER0_EEP3_PRD_INT	(1 << 19)
+#define FUSB300_IGER0_EEP2_PRD_INT	(1 << 18)
+#define FUSB300_IGER0_EEP1_PRD_INT	(1 << 17)
+#define FUSB300_IGER0_EEPn_PRD_INT(n)	(1 << (n + 16))
+
+#define FUSB300_IGER0_EEP15_FIFO_INT	(1 << 15)
+#define FUSB300_IGER0_EEP14_FIFO_INT	(1 << 14)
+#define FUSB300_IGER0_EEP13_FIFO_INT	(1 << 13)
+#define FUSB300_IGER0_EEP12_FIFO_INT	(1 << 12)
+#define FUSB300_IGER0_EEP11_FIFO_INT	(1 << 11)
+#define FUSB300_IGER0_EEP10_FIFO_INT	(1 << 10)
+#define FUSB300_IGER0_EEP9_FIFO_INT	(1 << 9)
+#define FUSB300_IGER0_EEP8_FIFO_INT	(1 << 8)
+#define FUSB300_IGER0_EEP7_FIFO_INT	(1 << 7)
+#define FUSB300_IGER0_EEP6_FIFO_INT	(1 << 6)
+#define FUSB300_IGER0_EEP5_FIFO_INT	(1 << 5)
+#define FUSB300_IGER0_EEP4_FIFO_INT	(1 << 4)
+#define FUSB300_IGER0_EEP3_FIFO_INT	(1 << 3)
+#define FUSB300_IGER0_EEP2_FIFO_INT	(1 << 2)
+#define FUSB300_IGER0_EEP1_FIFO_INT	(1 << 1)
+#define FUSB300_IGER0_EEPn_FIFO_INT(n)	(1 << n)
+
+/*
+ * *Interrupt Enable Group 1 Register (offset = 424H)
+ * */
+#define FUSB300_IGER1_EINT_GRP5		(1 << 31)
+#define FUSB300_IGER1_VBUS_CHG_INT	(1 << 30)
+#define FUSB300_IGER1_SYNF1_EMPTY_INT	(1 << 29)
+#define FUSB300_IGER1_SYNF0_EMPTY_INT	(1 << 28)
+#define FUSB300_IGER1_U3_EXIT_FAIL_INT	(1 << 27)
+#define FUSB300_IGER1_U2_EXIT_FAIL_INT	(1 << 26)
+#define FUSB300_IGER1_U1_EXIT_FAIL_INT	(1 << 25)
+#define FUSB300_IGER1_U2_ENTRY_FAIL_INT	(1 << 24)
+#define FUSB300_IGER1_U1_ENTRY_FAIL_INT	(1 << 23)
+#define FUSB300_IGER1_U3_EXIT_INT	(1 << 22)
+#define FUSB300_IGER1_U2_EXIT_INT	(1 << 21)
+#define FUSB300_IGER1_U1_EXIT_INT	(1 << 20)
+#define FUSB300_IGER1_U3_ENTRY_INT	(1 << 19)
+#define FUSB300_IGER1_U2_ENTRY_INT	(1 << 18)
+#define FUSB300_IGER1_U1_ENTRY_INT	(1 << 17)
+#define FUSB300_IGER1_HOT_RST_INT	(1 << 16)
+#define FUSB300_IGER1_WARM_RST_INT	(1 << 15)
+#define FUSB300_IGER1_RESM_INT		(1 << 14)
+#define FUSB300_IGER1_SUSP_INT		(1 << 13)
+#define FUSB300_IGER1_LPM_INT		(1 << 12)
+#define FUSB300_IGER1_HS_RST_INT	(1 << 11)
+#define FUSB300_IGER1_EDEV_MODE_CHG_INT	(1 << 9)
+#define FUSB300_IGER1_CX_COMABT_INT	(1 << 8)
+#define FUSB300_IGER1_CX_COMFAIL_INT	(1 << 7)
+#define FUSB300_IGER1_CX_CMDEND_INT	(1 << 6)
+#define FUSB300_IGER1_CX_OUT_INT	(1 << 5)
+#define FUSB300_IGER1_CX_IN_INT		(1 << 4)
+#define FUSB300_IGER1_CX_SETUP_INT	(1 << 3)
+#define FUSB300_IGER1_INTGRP4		(1 << 2)
+#define FUSB300_IGER1_INTGRP3		(1 << 1)
+#define FUSB300_IGER1_INTGRP2		(1 << 0)
+
+/*
+ * *Interrupt Enable Group 2 Register (offset = 428H)
+ * */
+#define FUSB300_IGER2_EEP_STR_ACCEPT_INT(n)	(1 << (5 * n - 1))
+#define FUSB300_IGER2_EEP_STR_RESUME_INT(n)	(1 << (5 * n - 2))
+#define FUSB300_IGER2_EEP_STR_REQ_INT(n)	(1 << (5 * n - 3))
+#define FUSB300_IGER2_EEP_STR_NOTRDY_INT(n)	(1 << (5 * n - 4))
+#define FUSB300_IGER2_EEP_STR_PRIME_INT(n)	(1 << (5 * n - 5))
+
+/*
+ * *Interrupt Enable Group 3 Register (offset = 42CH)
+ * */
+
+#define FUSB300_IGER3_EEP_STR_ACCEPT_INT(n)	(1 << (5 * (n - 6) - 1))
+#define FUSB300_IGER3_EEP_STR_RESUME_INT(n)	(1 << (5 * (n - 6) - 2))
+#define FUSB300_IGER3_EEP_STR_REQ_INT(n)	(1 << (5 * (n - 6) - 3))
+#define FUSB300_IGER3_EEP_STR_NOTRDY_INT(n)	(1 << (5 * (n - 6) - 4))
+#define FUSB300_IGER3_EEP_STR_PRIME_INT(n)	(1 << (5 * (n - 6) - 5))
+
+/*
+ * *Interrupt Enable Group 4 Register (offset = 430H)
+ * */
+
+#define FUSB300_IGER4_EEP_RX0_INT(n)		(1 << (n + 16))
+#define FUSB300_IGER4_EEP_STR_ACCEPT_INT(n)	(1 << (5 * (n - 6) - 1))
+#define FUSB300_IGER4_EEP_STR_RESUME_INT(n)	(1 << (5 * (n - 6) - 2))
+#define FUSB300_IGER4_EEP_STR_REQ_INT(n)	(1 << (5 * (n - 6) - 3))
+#define FUSB300_IGER4_EEP_STR_NOTRDY_INT(n)	(1 << (5 * (n - 6) - 4))
+#define FUSB300_IGER4_EEP_STR_PRIME_INT(n)	(1 << (5 * (n - 6) - 5))
+
+/* EP PRD Ready (EP_PRD_RDY, offset = 504H) */
+
+#define FUSB300_EPPRDR_EP15_PRD_RDY		(1 << 15)
+#define FUSB300_EPPRDR_EP14_PRD_RDY		(1 << 14)
+#define FUSB300_EPPRDR_EP13_PRD_RDY		(1 << 13)
+#define FUSB300_EPPRDR_EP12_PRD_RDY		(1 << 12)
+#define FUSB300_EPPRDR_EP11_PRD_RDY		(1 << 11)
+#define FUSB300_EPPRDR_EP10_PRD_RDY		(1 << 10)
+#define FUSB300_EPPRDR_EP9_PRD_RDY		(1 << 9)
+#define FUSB300_EPPRDR_EP8_PRD_RDY		(1 << 8)
+#define FUSB300_EPPRDR_EP7_PRD_RDY		(1 << 7)
+#define FUSB300_EPPRDR_EP6_PRD_RDY		(1 << 6)
+#define FUSB300_EPPRDR_EP5_PRD_RDY		(1 << 5)
+#define FUSB300_EPPRDR_EP4_PRD_RDY		(1 << 4)
+#define FUSB300_EPPRDR_EP3_PRD_RDY		(1 << 3)
+#define FUSB300_EPPRDR_EP2_PRD_RDY		(1 << 2)
+#define FUSB300_EPPRDR_EP1_PRD_RDY		(1 << 1)
+#define FUSB300_EPPRDR_EP_PRD_RDY(n)		(1 << n)
+
+/* AHB Bus Control Register (offset = 514H) */
+#define FUSB300_AHBBCR_S1_SPLIT_ON		(1 << 17)
+#define FUSB300_AHBBCR_S0_SPLIT_ON		(1 << 16)
+#define FUSB300_AHBBCR_S1_1entry		(0 << 12)
+#define FUSB300_AHBBCR_S1_4entry		(3 << 12)
+#define FUSB300_AHBBCR_S1_8entry		(5 << 12)
+#define FUSB300_AHBBCR_S1_16entry		(7 << 12)
+#define FUSB300_AHBBCR_S0_1entry		(0 << 8)
+#define FUSB300_AHBBCR_S0_4entry		(3 << 8)
+#define FUSB300_AHBBCR_S0_8entry		(5 << 8)
+#define FUSB300_AHBBCR_S0_16entry		(7 << 8)
+#define FUSB300_AHBBCR_M1_BURST_SINGLE		(0 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR		(1 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR4		(3 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR8		(5 << 4)
+#define FUSB300_AHBBCR_M1_BURST_INCR16		(7 << 4)
+#define FUSB300_AHBBCR_M0_BURST_SINGLE		0
+#define FUSB300_AHBBCR_M0_BURST_INCR		1
+#define FUSB300_AHBBCR_M0_BURST_INCR4		3
+#define FUSB300_AHBBCR_M0_BURST_INCR8		5
+#define FUSB300_AHBBCR_M0_BURST_INCR16		7
+#define FUSB300_IGER5_EEP_STL_INT(n)		(1 << n)
+
+/* WORD 0 Data Structure of PRD Table */
+#define FUSB300_EPPRD0_M			(1 << 30)
+#define FUSB300_EPPRD0_O			(1 << 29)
+/* The finished prd */
+#define FUSB300_EPPRD0_F			(1 << 28)
+#define FUSB300_EPPRD0_I			(1 << 27)
+#define FUSB300_EPPRD0_A			(1 << 26)
+/* To decide HW point to first prd at next time */
+#define FUSB300_EPPRD0_L			(1 << 25)
+#define FUSB300_EPPRD0_H			(1 << 24)
+#define FUSB300_EPPRD0_BTC(n)			(n & 0xFFFFFF)
+
+/*----------------------------------------------------------------------*/
+#define FUSB300_MAX_NUM_EP		16
+
+#define FUSB300_FIFO_ENTRY_NUM		8
+#define FUSB300_MAX_FIFO_ENTRY		8
+
+#define SS_CTL_MAX_PACKET_SIZE		0x200
+#define SS_BULK_MAX_PACKET_SIZE		0x400
+#define SS_INT_MAX_PACKET_SIZE		0x400
+#define SS_ISO_MAX_PACKET_SIZE		0x400
+
+#define HS_BULK_MAX_PACKET_SIZE		0x200
+#define HS_CTL_MAX_PACKET_SIZE		0x40
+#define HS_INT_MAX_PACKET_SIZE		0x400
+#define HS_ISO_MAX_PACKET_SIZE		0x400
+
+struct fusb300_ep_info {
+	u8	epnum;
+	u8	type;
+	u8	interval;
+	u8	dir_in;
+	u16	maxpacket;
+	u16	addrofs;
+	u16	bw_num;
+};
+
+struct fusb300_request {
+
+	struct usb_request	req;
+	struct list_head	queue;
+};
+
+
+struct fusb300_ep {
+	struct usb_ep		ep;
+	struct fusb300		*fusb300;
+
+	struct list_head	queue;
+	unsigned		stall:1;
+	unsigned		wedged:1;
+	unsigned		use_dma:1;
+
+	unsigned char		epnum;
+	unsigned char		type;
+	const struct usb_endpoint_descriptor	*desc;
+};
+
+struct fusb300 {
+	spinlock_t		lock;
+	void __iomem		*reg;
+
+	unsigned long		irq_trigger;
+
+	struct usb_gadget		gadget;
+	struct usb_gadget_driver	*driver;
+
+	struct fusb300_ep	*ep[FUSB300_MAX_NUM_EP];
+
+	struct usb_request	*ep0_req;	/* for internal request */
+	__le16			ep0_data;
+	u32			ep0_length;	/* for internal request */
+	u8			ep0_dir;	/* 0/0x80  out/in */
+
+	u8			fifo_entry_num;	/* next start fifo entry */
+	u32			addrofs;	/* next fifo address offset */
+	u8			reenum;		/* if re-enumeration */
+};
+
+#endif
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
index 5c2720d..e896f63 100644
--- a/drivers/usb/gadget/gadget_chips.h
+++ b/drivers/usb/gadget/gadget_chips.h
@@ -45,12 +45,6 @@
 #define	gadget_is_goku(g)	0
 #endif
 
-#ifdef CONFIG_USB_GADGET_LH7A40X
-#define	gadget_is_lh7a40x(g)	!strcmp("lh7a40x_udc", (g)->name)
-#else
-#define	gadget_is_lh7a40x(g)	0
-#endif
-
 #ifdef CONFIG_USB_GADGET_OMAP
 #define	gadget_is_omap(g)	!strcmp("omap_udc", (g)->name)
 #else
@@ -181,8 +175,6 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
 		return 0x06;
 	else if (gadget_is_omap(gadget))
 		return 0x08;
-	else if (gadget_is_lh7a40x(gadget))
-		return 0x09;
 	else if (gadget_is_pxa27x(gadget))
 		return 0x11;
 	else if (gadget_is_s3c2410(gadget))
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c
deleted file mode 100644
index 6b58bd8..0000000
--- a/drivers/usb/gadget/lh7a40x_udc.c
+++ /dev/null
@@ -1,2152 +0,0 @@
-/*
- * linux/drivers/usb/gadget/lh7a40x_udc.c
- * Sharp LH7A40x on-chip full speed USB device controllers
- *
- * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
- * Copyright (C) 2004 Bo Henriksen, Nordic ID
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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/platform_device.h>
-#include <linux/slab.h>
-
-#include "lh7a40x_udc.h"
-
-//#define DEBUG printk
-//#define DEBUG_EP0 printk
-//#define DEBUG_SETUP printk
-
-#ifndef DEBUG_EP0
-# define DEBUG_EP0(fmt,args...)
-#endif
-#ifndef DEBUG_SETUP
-# define DEBUG_SETUP(fmt,args...)
-#endif
-#ifndef DEBUG
-# define NO_STATES
-# define DEBUG(fmt,args...)
-#endif
-
-#define	DRIVER_DESC			"LH7A40x USB Device Controller"
-#define	DRIVER_VERSION		__DATE__
-
-#ifndef _BIT			/* FIXME - what happended to _BIT in 2.6.7bk18? */
-#define _BIT(x) (1<<(x))
-#endif
-
-struct lh7a40x_udc *the_controller;
-
-static const char driver_name[] = "lh7a40x_udc";
-static const char driver_desc[] = DRIVER_DESC;
-static const char ep0name[] = "ep0-control";
-
-/*
-  Local definintions.
-*/
-
-#ifndef NO_STATES
-static char *state_names[] = {
-	"WAIT_FOR_SETUP",
-	"DATA_STATE_XMIT",
-	"DATA_STATE_NEED_ZLP",
-	"WAIT_FOR_OUT_STATUS",
-	"DATA_STATE_RECV"
-};
-#endif
-
-/*
-  Local declarations.
-*/
-static int lh7a40x_ep_enable(struct usb_ep *ep,
-			     const struct usb_endpoint_descriptor *);
-static int lh7a40x_ep_disable(struct usb_ep *ep);
-static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t);
-static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *);
-static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
-static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
-static int lh7a40x_set_halt(struct usb_ep *ep, int);
-static int lh7a40x_fifo_status(struct usb_ep *ep);
-static void lh7a40x_fifo_flush(struct usb_ep *ep);
-static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
-static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);
-
-static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req,
-		 int status);
-static void pio_irq_enable(int bEndpointAddress);
-static void pio_irq_disable(int bEndpointAddress);
-static void stop_activity(struct lh7a40x_udc *dev,
-			  struct usb_gadget_driver *driver);
-static void flush(struct lh7a40x_ep *ep);
-static void udc_enable(struct lh7a40x_udc *dev);
-static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address);
-
-static struct usb_ep_ops lh7a40x_ep_ops = {
-	.enable = lh7a40x_ep_enable,
-	.disable = lh7a40x_ep_disable,
-
-	.alloc_request = lh7a40x_alloc_request,
-	.free_request = lh7a40x_free_request,
-
-	.queue = lh7a40x_queue,
-	.dequeue = lh7a40x_dequeue,
-
-	.set_halt = lh7a40x_set_halt,
-	.fifo_status = lh7a40x_fifo_status,
-	.fifo_flush = lh7a40x_fifo_flush,
-};
-
-/* Inline code */
-
-static __inline__ int write_packet(struct lh7a40x_ep *ep,
-				   struct lh7a40x_request *req, int max)
-{
-	u8 *buf;
-	int length, count;
-	volatile u32 *fifo = (volatile u32 *)ep->fifo;
-
-	buf = req->req.buf + req->req.actual;
-	prefetch(buf);
-
-	length = req->req.length - req->req.actual;
-	length = min(length, max);
-	req->req.actual += length;
-
-	DEBUG("Write %d (max %d), fifo %p\n", length, max, fifo);
-
-	count = length;
-	while (count--) {
-		*fifo = *buf++;
-	}
-
-	return length;
-}
-
-static __inline__ void usb_set_index(u32 ep)
-{
-	*(volatile u32 *)io_p2v(USB_INDEX) = ep;
-}
-
-static __inline__ u32 usb_read(u32 port)
-{
-	return *(volatile u32 *)io_p2v(port);
-}
-
-static __inline__ void usb_write(u32 val, u32 port)
-{
-	*(volatile u32 *)io_p2v(port) = val;
-}
-
-static __inline__ void usb_set(u32 val, u32 port)
-{
-	volatile u32 *ioport = (volatile u32 *)io_p2v(port);
-	u32 after = (*ioport) | val;
-	*ioport = after;
-}
-
-static __inline__ void usb_clear(u32 val, u32 port)
-{
-	volatile u32 *ioport = (volatile u32 *)io_p2v(port);
-	u32 after = (*ioport) & ~val;
-	*ioport = after;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define GPIO_PORTC_DR 	(0x80000E08)
-#define GPIO_PORTC_DDR 	(0x80000E18)
-#define GPIO_PORTC_PDR 	(0x80000E70)
-
-/* get port C pin data register */
-#define get_portc_pdr(bit) 		((usb_read(GPIO_PORTC_PDR) & _BIT(bit)) != 0)
-/* get port C data direction register */
-#define get_portc_ddr(bit) 		((usb_read(GPIO_PORTC_DDR) & _BIT(bit)) != 0)
-/* set port C data register */
-#define set_portc_dr(bit, val) 	(val ? usb_set(_BIT(bit), GPIO_PORTC_DR) : usb_clear(_BIT(bit), GPIO_PORTC_DR))
-/* set port C data direction register */
-#define set_portc_ddr(bit, val) (val ? usb_set(_BIT(bit), GPIO_PORTC_DDR) : usb_clear(_BIT(bit), GPIO_PORTC_DDR))
-
-/*
- * LPD7A404 GPIO's:
- * Port C bit 1 = USB Port 1 Power Enable
- * Port C bit 2 = USB Port 1 Data Carrier Detect
- */
-#define is_usb_connected() 		get_portc_pdr(2)
-
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-
-static const char proc_node_name[] = "driver/udc";
-
-static int
-udc_proc_read(char *page, char **start, off_t off, int count,
-	      int *eof, void *_dev)
-{
-	char *buf = page;
-	struct lh7a40x_udc *dev = _dev;
-	char *next = buf;
-	unsigned size = count;
-	unsigned long flags;
-	int t;
-
-	if (off != 0)
-		return 0;
-
-	local_irq_save(flags);
-
-	/* basic device status */
-	t = scnprintf(next, size,
-		      DRIVER_DESC "\n"
-		      "%s version: %s\n"
-		      "Gadget driver: %s\n"
-		      "Host: %s\n\n",
-		      driver_name, DRIVER_VERSION,
-		      dev->driver ? dev->driver->driver.name : "(none)",
-		      is_usb_connected()? "full speed" : "disconnected");
-	size -= t;
-	next += t;
-
-	t = scnprintf(next, size,
-		      "GPIO:\n"
-		      " Port C bit 1: %d, dir %d\n"
-		      " Port C bit 2: %d, dir %d\n\n",
-		      get_portc_pdr(1), get_portc_ddr(1),
-		      get_portc_pdr(2), get_portc_ddr(2)
-	    );
-	size -= t;
-	next += t;
-
-	t = scnprintf(next, size,
-		      "DCP pullup: %d\n\n",
-		      (usb_read(USB_PM) & PM_USB_DCP) != 0);
-	size -= t;
-	next += t;
-
-	local_irq_restore(flags);
-	*eof = 1;
-	return count - size;
-}
-
-#define create_proc_files() 	create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
-#define remove_proc_files() 	remove_proc_entry(proc_node_name, NULL)
-
-#else	/* !CONFIG_USB_GADGET_DEBUG_FILES */
-
-#define create_proc_files() do {} while (0)
-#define remove_proc_files() do {} while (0)
-
-#endif	/* CONFIG_USB_GADGET_DEBUG_FILES */
-
-/*
- * 	udc_disable - disable USB device controller
- */
-static void udc_disable(struct lh7a40x_udc *dev)
-{
-	DEBUG("%s, %p\n", __func__, dev);
-
-	udc_set_address(dev, 0);
-
-	/* Disable interrupts */
-	usb_write(0, USB_IN_INT_EN);
-	usb_write(0, USB_OUT_INT_EN);
-	usb_write(0, USB_INT_EN);
-
-	/* Disable the USB */
-	usb_write(0, USB_PM);
-
-#ifdef CONFIG_ARCH_LH7A404
-	/* Disable USB power */
-	set_portc_dr(1, 0);
-#endif
-
-	/* if hardware supports it, disconnect from usb */
-	/* make_usb_disappear(); */
-
-	dev->ep0state = WAIT_FOR_SETUP;
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-	dev->usb_address = 0;
-}
-
-/*
- * 	udc_reinit - initialize software state
- */
-static void udc_reinit(struct lh7a40x_udc *dev)
-{
-	u32 i;
-
-	DEBUG("%s, %p\n", __func__, dev);
-
-	/* device/ep0 records init */
-	INIT_LIST_HEAD(&dev->gadget.ep_list);
-	INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
-	dev->ep0state = WAIT_FOR_SETUP;
-
-	/* basic endpoint records init */
-	for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
-		struct lh7a40x_ep *ep = &dev->ep[i];
-
-		if (i != 0)
-			list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
-
-		ep->desc = 0;
-		ep->stopped = 0;
-		INIT_LIST_HEAD(&ep->queue);
-		ep->pio_irqs = 0;
-	}
-
-	/* the rest was statically initialized, and is read-only */
-}
-
-#define BYTES2MAXP(x)	(x / 8)
-#define MAXP2BYTES(x)	(x * 8)
-
-/* until it's enabled, this UDC should be completely invisible
- * to any USB host.
- */
-static void udc_enable(struct lh7a40x_udc *dev)
-{
-	int ep;
-
-	DEBUG("%s, %p\n", __func__, dev);
-
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-
-#ifdef CONFIG_ARCH_LH7A404
-	/* Set Port C bit 1 & 2 as output */
-	set_portc_ddr(1, 1);
-	set_portc_ddr(2, 1);
-
-	/* Enable USB power */
-	set_portc_dr(1, 0);
-#endif
-
-	/*
-	 * C.f Chapter 18.1.3.1 Initializing the USB
-	 */
-
-	/* Disable the USB */
-	usb_clear(PM_USB_ENABLE, USB_PM);
-
-	/* Reset APB & I/O sides of the USB */
-	usb_set(USB_RESET_APB | USB_RESET_IO, USB_RESET);
-	mdelay(5);
-	usb_clear(USB_RESET_APB | USB_RESET_IO, USB_RESET);
-
-	/* Set MAXP values for each */
-	for (ep = 0; ep < UDC_MAX_ENDPOINTS; ep++) {
-		struct lh7a40x_ep *ep_reg = &dev->ep[ep];
-		u32 csr;
-
-		usb_set_index(ep);
-
-		switch (ep_reg->ep_type) {
-		case ep_bulk_in:
-		case ep_interrupt:
-			usb_clear(USB_IN_CSR2_USB_DMA_EN | USB_IN_CSR2_AUTO_SET,
-				  ep_reg->csr2);
-			/* Fall through */
-		case ep_control:
-			usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
-				  USB_IN_MAXP);
-			break;
-		case ep_bulk_out:
-			usb_clear(USB_OUT_CSR2_USB_DMA_EN |
-				  USB_OUT_CSR2_AUTO_CLR, ep_reg->csr2);
-			usb_write(BYTES2MAXP(ep_maxpacket(ep_reg)),
-				  USB_OUT_MAXP);
-			break;
-		}
-
-		/* Read & Write CSR1, just in case */
-		csr = usb_read(ep_reg->csr1);
-		usb_write(csr, ep_reg->csr1);
-
-		flush(ep_reg);
-	}
-
-	/* Disable interrupts */
-	usb_write(0, USB_IN_INT_EN);
-	usb_write(0, USB_OUT_INT_EN);
-	usb_write(0, USB_INT_EN);
-
-	/* Enable interrupts */
-	usb_set(USB_IN_INT_EP0, USB_IN_INT_EN);
-	usb_set(USB_INT_RESET_INT | USB_INT_RESUME_INT, USB_INT_EN);
-	/* Dont enable rest of the interrupts */
-	/* usb_set(USB_IN_INT_EP3 | USB_IN_INT_EP1 | USB_IN_INT_EP0, USB_IN_INT_EN);
-	   usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN); */
-
-	/* Enable SUSPEND */
-	usb_set(PM_ENABLE_SUSPEND, USB_PM);
-
-	/* Enable the USB */
-	usb_set(PM_USB_ENABLE, USB_PM);
-
-#ifdef CONFIG_ARCH_LH7A404
-	/* NOTE: DOES NOT WORK! */
-	/* Let host detect UDC:
-	 * Software must write a 0 to the PMR:DCP_CTRL bit to turn this
-	 * transistor on and pull the USBDP pin HIGH.
-	 */
-	/* usb_clear(PM_USB_DCP, USB_PM);
-	   usb_set(PM_USB_DCP, USB_PM); */
-#endif
-}
-
-/*
-  Register entry point for the peripheral controller driver.
-*/
-int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
-		int (*bind)(struct usb_gadget *))
-{
-	struct lh7a40x_udc *dev = the_controller;
-	int retval;
-
-	DEBUG("%s: %s\n", __func__, driver->driver.name);
-
-	if (!driver
-			|| driver->speed != USB_SPEED_FULL
-			|| !bind
-			|| !driver->disconnect
-			|| !driver->setup)
-		return -EINVAL;
-	if (!dev)
-		return -ENODEV;
-	if (dev->driver)
-		return -EBUSY;
-
-	/* first hook up the driver ... */
-	dev->driver = driver;
-	dev->gadget.dev.driver = &driver->driver;
-
-	device_add(&dev->gadget.dev);
-	retval = bind(&dev->gadget);
-	if (retval) {
-		printk(KERN_WARNING "%s: bind to driver %s --> error %d\n",
-		       dev->gadget.name, driver->driver.name, retval);
-		device_del(&dev->gadget.dev);
-
-		dev->driver = 0;
-		dev->gadget.dev.driver = 0;
-		return retval;
-	}
-
-	/* ... then enable host detection and ep0; and we're ready
-	 * for set_configuration as well as eventual disconnect.
-	 * NOTE:  this shouldn't power up until later.
-	 */
-	printk(KERN_WARNING "%s: registered gadget driver '%s'\n",
-	       dev->gadget.name, driver->driver.name);
-
-	udc_enable(dev);
-
-	return 0;
-}
-EXPORT_SYMBOL(usb_gadget_probe_driver);
-
-/*
-  Unregister entry point for the peripheral controller driver.
-*/
-int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
-{
-	struct lh7a40x_udc *dev = the_controller;
-	unsigned long flags;
-
-	if (!dev)
-		return -ENODEV;
-	if (!driver || driver != dev->driver || !driver->unbind)
-		return -EINVAL;
-
-	spin_lock_irqsave(&dev->lock, flags);
-	dev->driver = 0;
-	stop_activity(dev, driver);
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	driver->unbind(&dev->gadget);
-	dev->gadget.dev.driver = NULL;
-	device_del(&dev->gadget.dev);
-
-	udc_disable(dev);
-
-	DEBUG("unregistered gadget driver '%s'\n", driver->driver.name);
-	return 0;
-}
-
-EXPORT_SYMBOL(usb_gadget_unregister_driver);
-
-/*-------------------------------------------------------------------------*/
-
-/** Write request to FIFO (max write == maxp size)
- *  Return:  0 = still running, 1 = completed, negative = errno
- *  NOTE: INDEX register must be set for EP
- */
-static int write_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
-{
-	u32 max;
-	u32 csr;
-
-	max = le16_to_cpu(ep->desc->wMaxPacketSize);
-
-	csr = usb_read(ep->csr1);
-	DEBUG("CSR: %x %d\n", csr, csr & USB_IN_CSR1_FIFO_NOT_EMPTY);
-
-	if (!(csr & USB_IN_CSR1_FIFO_NOT_EMPTY)) {
-		unsigned count;
-		int is_last, is_short;
-
-		count = write_packet(ep, req, max);
-		usb_set(USB_IN_CSR1_IN_PKT_RDY, ep->csr1);
-
-		/* last packet is usually short (or a zlp) */
-		if (unlikely(count != max))
-			is_last = is_short = 1;
-		else {
-			if (likely(req->req.length != req->req.actual)
-			    || req->req.zero)
-				is_last = 0;
-			else
-				is_last = 1;
-			/* interrupt/iso maxpacket may not fill the fifo */
-			is_short = unlikely(max < ep_maxpacket(ep));
-		}
-
-		DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __func__,
-		      ep->ep.name, count,
-		      is_last ? "/L" : "", is_short ? "/S" : "",
-		      req->req.length - req->req.actual, req);
-
-		/* requests complete when all IN data is in the FIFO */
-		if (is_last) {
-			done(ep, req, 0);
-			if (list_empty(&ep->queue)) {
-				pio_irq_disable(ep_index(ep));
-			}
-			return 1;
-		}
-	} else {
-		DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep));
-	}
-
-	return 0;
-}
-
-/** Read to request from FIFO (max read == bytes in fifo)
- *  Return:  0 = still running, 1 = completed, negative = errno
- *  NOTE: INDEX register must be set for EP
- */
-static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
-{
-	u32 csr;
-	u8 *buf;
-	unsigned bufferspace, count, is_short;
-	volatile u32 *fifo = (volatile u32 *)ep->fifo;
-
-	/* make sure there's a packet in the FIFO. */
-	csr = usb_read(ep->csr1);
-	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY)) {
-		DEBUG("%s: Packet NOT ready!\n", __func__);
-		return -EINVAL;
-	}
-
-	buf = req->req.buf + req->req.actual;
-	prefetchw(buf);
-	bufferspace = req->req.length - req->req.actual;
-
-	/* read all bytes from this packet */
-	count = usb_read(USB_OUT_FIFO_WC1);
-	req->req.actual += min(count, bufferspace);
-
-	is_short = (count < ep->ep.maxpacket);
-	DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n",
-	      ep->ep.name, csr, count,
-	      is_short ? "/S" : "", req, req->req.actual, req->req.length);
-
-	while (likely(count-- != 0)) {
-		u8 byte = (u8) (*fifo & 0xff);
-
-		if (unlikely(bufferspace == 0)) {
-			/* this happens when the driver's buffer
-			 * is smaller than what the host sent.
-			 * discard the extra data.
-			 */
-			if (req->req.status != -EOVERFLOW)
-				printk(KERN_WARNING "%s overflow %d\n",
-				       ep->ep.name, count);
-			req->req.status = -EOVERFLOW;
-		} else {
-			*buf++ = byte;
-			bufferspace--;
-		}
-	}
-
-	usb_clear(USB_OUT_CSR1_OUT_PKT_RDY, ep->csr1);
-
-	/* completion */
-	if (is_short || req->req.actual == req->req.length) {
-		done(ep, req, 0);
-		usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
-
-		if (list_empty(&ep->queue))
-			pio_irq_disable(ep_index(ep));
-		return 1;
-	}
-
-	/* finished that packet.  the next one may be waiting... */
-	return 0;
-}
-
-/*
- *	done - retire a request; caller blocked irqs
- *  INDEX register is preserved to keep same
- */
-static void done(struct lh7a40x_ep *ep, struct lh7a40x_request *req, int status)
-{
-	unsigned int stopped = ep->stopped;
-	u32 index;
-
-	DEBUG("%s, %p\n", __func__, ep);
-	list_del_init(&req->queue);
-
-	if (likely(req->req.status == -EINPROGRESS))
-		req->req.status = status;
-	else
-		status = req->req.status;
-
-	if (status && status != -ESHUTDOWN)
-		DEBUG("complete %s req %p stat %d len %u/%u\n",
-		      ep->ep.name, &req->req, status,
-		      req->req.actual, req->req.length);
-
-	/* don't modify queue heads during completion callback */
-	ep->stopped = 1;
-	/* Read current index (completion may modify it) */
-	index = usb_read(USB_INDEX);
-
-	spin_unlock(&ep->dev->lock);
-	req->req.complete(&ep->ep, &req->req);
-	spin_lock(&ep->dev->lock);
-
-	/* Restore index */
-	usb_set_index(index);
-	ep->stopped = stopped;
-}
-
-/** Enable EP interrupt */
-static void pio_irq_enable(int ep)
-{
-	DEBUG("%s: %d\n", __func__, ep);
-
-	switch (ep) {
-	case 1:
-		usb_set(USB_IN_INT_EP1, USB_IN_INT_EN);
-		break;
-	case 2:
-		usb_set(USB_OUT_INT_EP2, USB_OUT_INT_EN);
-		break;
-	case 3:
-		usb_set(USB_IN_INT_EP3, USB_IN_INT_EN);
-		break;
-	default:
-		DEBUG("Unknown endpoint: %d\n", ep);
-		break;
-	}
-}
-
-/** Disable EP interrupt */
-static void pio_irq_disable(int ep)
-{
-	DEBUG("%s: %d\n", __func__, ep);
-
-	switch (ep) {
-	case 1:
-		usb_clear(USB_IN_INT_EP1, USB_IN_INT_EN);
-		break;
-	case 2:
-		usb_clear(USB_OUT_INT_EP2, USB_OUT_INT_EN);
-		break;
-	case 3:
-		usb_clear(USB_IN_INT_EP3, USB_IN_INT_EN);
-		break;
-	default:
-		DEBUG("Unknown endpoint: %d\n", ep);
-		break;
-	}
-}
-
-/*
- * 	nuke - dequeue ALL requests
- */
-void nuke(struct lh7a40x_ep *ep, int status)
-{
-	struct lh7a40x_request *req;
-
-	DEBUG("%s, %p\n", __func__, ep);
-
-	/* Flush FIFO */
-	flush(ep);
-
-	/* called with irqs blocked */
-	while (!list_empty(&ep->queue)) {
-		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
-		done(ep, req, status);
-	}
-
-	/* Disable IRQ if EP is enabled (has descriptor) */
-	if (ep->desc)
-		pio_irq_disable(ep_index(ep));
-}
-
-/*
-void nuke_all(struct lh7a40x_udc *dev)
-{
-	int n;
-	for(n=0; n<UDC_MAX_ENDPOINTS; n++) {
-		struct lh7a40x_ep *ep = &dev->ep[n];
-		usb_set_index(n);
-		nuke(ep, 0);
-	}
-}*/
-
-/*
-static void flush_all(struct lh7a40x_udc *dev)
-{
-	int n;
-    for (n = 0; n < UDC_MAX_ENDPOINTS; n++)
-    {
-		struct lh7a40x_ep *ep = &dev->ep[n];
-		flush(ep);
-    }
-}
-*/
-
-/** Flush EP
- * NOTE: INDEX register must be set before this call
- */
-static void flush(struct lh7a40x_ep *ep)
-{
-	DEBUG("%s, %p\n", __func__, ep);
-
-	switch (ep->ep_type) {
-	case ep_control:
-		/* check, by implication c.f. 15.1.2.11 */
-		break;
-
-	case ep_bulk_in:
-	case ep_interrupt:
-		/* if(csr & USB_IN_CSR1_IN_PKT_RDY) */
-		usb_set(USB_IN_CSR1_FIFO_FLUSH, ep->csr1);
-		break;
-
-	case ep_bulk_out:
-		/* if(csr & USB_OUT_CSR1_OUT_PKT_RDY) */
-		usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1);
-		break;
-	}
-}
-
-/**
- * lh7a40x_in_epn - handle IN interrupt
- */
-static void lh7a40x_in_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
-{
-	u32 csr;
-	struct lh7a40x_ep *ep = &dev->ep[ep_idx];
-	struct lh7a40x_request *req;
-
-	usb_set_index(ep_idx);
-
-	csr = usb_read(ep->csr1);
-	DEBUG("%s: %d, csr %x\n", __func__, ep_idx, csr);
-
-	if (csr & USB_IN_CSR1_SENT_STALL) {
-		DEBUG("USB_IN_CSR1_SENT_STALL\n");
-		usb_set(USB_IN_CSR1_SENT_STALL /*|USB_IN_CSR1_SEND_STALL */ ,
-			ep->csr1);
-		return;
-	}
-
-	if (!ep->desc) {
-		DEBUG("%s: NO EP DESC\n", __func__);
-		return;
-	}
-
-	if (list_empty(&ep->queue))
-		req = 0;
-	else
-		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
-
-	DEBUG("req: %p\n", req);
-
-	if (!req)
-		return;
-
-	write_fifo(ep, req);
-}
-
-/* ********************************************************************************************* */
-/* Bulk OUT (recv)
- */
-
-static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr)
-{
-	struct lh7a40x_ep *ep = &dev->ep[ep_idx];
-	struct lh7a40x_request *req;
-
-	DEBUG("%s: %d\n", __func__, ep_idx);
-
-	usb_set_index(ep_idx);
-
-	if (ep->desc) {
-		u32 csr;
-		csr = usb_read(ep->csr1);
-
-		while ((csr =
-			usb_read(ep->
-				 csr1)) & (USB_OUT_CSR1_OUT_PKT_RDY |
-					   USB_OUT_CSR1_SENT_STALL)) {
-			DEBUG("%s: %x\n", __func__, csr);
-
-			if (csr & USB_OUT_CSR1_SENT_STALL) {
-				DEBUG("%s: stall sent, flush fifo\n",
-				      __func__);
-				/* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
-				flush(ep);
-			} else if (csr & USB_OUT_CSR1_OUT_PKT_RDY) {
-				if (list_empty(&ep->queue))
-					req = 0;
-				else
-					req =
-					    list_entry(ep->queue.next,
-						       struct lh7a40x_request,
-						       queue);
-
-				if (!req) {
-					printk(KERN_WARNING
-					       "%s: NULL REQ %d\n",
-					       __func__, ep_idx);
-					flush(ep);
-					break;
-				} else {
-					read_fifo(ep, req);
-				}
-			}
-
-		}
-
-	} else {
-		/* Throw packet away.. */
-		printk(KERN_WARNING "%s: No descriptor?!?\n", __func__);
-		flush(ep);
-	}
-}
-
-static void stop_activity(struct lh7a40x_udc *dev,
-			  struct usb_gadget_driver *driver)
-{
-	int i;
-
-	/* don't disconnect drivers more than once */
-	if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-		driver = 0;
-	dev->gadget.speed = USB_SPEED_UNKNOWN;
-
-	/* prevent new request submissions, kill any outstanding requests  */
-	for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
-		struct lh7a40x_ep *ep = &dev->ep[i];
-		ep->stopped = 1;
-
-		usb_set_index(i);
-		nuke(ep, -ESHUTDOWN);
-	}
-
-	/* report disconnect; the driver is already quiesced */
-	if (driver) {
-		spin_unlock(&dev->lock);
-		driver->disconnect(&dev->gadget);
-		spin_lock(&dev->lock);
-	}
-
-	/* re-init driver-visible data structures */
-	udc_reinit(dev);
-}
-
-/** Handle USB RESET interrupt
- */
-static void lh7a40x_reset_intr(struct lh7a40x_udc *dev)
-{
-#if 0				/* def CONFIG_ARCH_LH7A404 */
-	/* Does not work always... */
-
-	DEBUG("%s: %d\n", __func__, dev->usb_address);
-
-	if (!dev->usb_address) {
-		/*usb_set(USB_RESET_IO, USB_RESET);
-		   mdelay(5);
-		   usb_clear(USB_RESET_IO, USB_RESET); */
-		return;
-	}
-	/* Put the USB controller into reset. */
-	usb_set(USB_RESET_IO, USB_RESET);
-
-	/* Set Device ID to 0 */
-	udc_set_address(dev, 0);
-
-	/* Let PLL2 settle down */
-	mdelay(5);
-
-	/* Release the USB controller from reset */
-	usb_clear(USB_RESET_IO, USB_RESET);
-
-	/* Re-enable UDC */
-	udc_enable(dev);
-
-#endif
-	dev->gadget.speed = USB_SPEED_FULL;
-}
-
-/*
- *	lh7a40x usb client interrupt handler.
- */
-static irqreturn_t lh7a40x_udc_irq(int irq, void *_dev)
-{
-	struct lh7a40x_udc *dev = _dev;
-
-	DEBUG("\n\n");
-
-	spin_lock(&dev->lock);
-
-	for (;;) {
-		u32 intr_in = usb_read(USB_IN_INT);
-		u32 intr_out = usb_read(USB_OUT_INT);
-		u32 intr_int = usb_read(USB_INT);
-
-		/* Test also against enable bits.. (lh7a40x errata).. Sigh.. */
-		u32 in_en = usb_read(USB_IN_INT_EN);
-		u32 out_en = usb_read(USB_OUT_INT_EN);
-
-		if (!intr_out && !intr_in && !intr_int)
-			break;
-
-		DEBUG("%s (on state %s)\n", __func__,
-		      state_names[dev->ep0state]);
-		DEBUG("intr_out = %x\n", intr_out);
-		DEBUG("intr_in  = %x\n", intr_in);
-		DEBUG("intr_int = %x\n", intr_int);
-
-		if (intr_in) {
-			usb_write(intr_in, USB_IN_INT);
-
-			if ((intr_in & USB_IN_INT_EP1)
-			    && (in_en & USB_IN_INT_EP1)) {
-				DEBUG("USB_IN_INT_EP1\n");
-				lh7a40x_in_epn(dev, 1, intr_in);
-			}
-			if ((intr_in & USB_IN_INT_EP3)
-			    && (in_en & USB_IN_INT_EP3)) {
-				DEBUG("USB_IN_INT_EP3\n");
-				lh7a40x_in_epn(dev, 3, intr_in);
-			}
-			if (intr_in & USB_IN_INT_EP0) {
-				DEBUG("USB_IN_INT_EP0 (control)\n");
-				lh7a40x_handle_ep0(dev, intr_in);
-			}
-		}
-
-		if (intr_out) {
-			usb_write(intr_out, USB_OUT_INT);
-
-			if ((intr_out & USB_OUT_INT_EP2)
-			    && (out_en & USB_OUT_INT_EP2)) {
-				DEBUG("USB_OUT_INT_EP2\n");
-				lh7a40x_out_epn(dev, 2, intr_out);
-			}
-		}
-
-		if (intr_int) {
-			usb_write(intr_int, USB_INT);
-
-			if (intr_int & USB_INT_RESET_INT) {
-				lh7a40x_reset_intr(dev);
-			}
-
-			if (intr_int & USB_INT_RESUME_INT) {
-				DEBUG("USB resume\n");
-
-				if (dev->gadget.speed != USB_SPEED_UNKNOWN
-				    && dev->driver
-				    && dev->driver->resume
-				    && is_usb_connected()) {
-					dev->driver->resume(&dev->gadget);
-				}
-			}
-
-			if (intr_int & USB_INT_SUSPEND_INT) {
-				DEBUG("USB suspend%s\n",
-				      is_usb_connected()? "" : "+disconnect");
-				if (!is_usb_connected()) {
-					stop_activity(dev, dev->driver);
-				} else if (dev->gadget.speed !=
-					   USB_SPEED_UNKNOWN && dev->driver
-					   && dev->driver->suspend) {
-					dev->driver->suspend(&dev->gadget);
-				}
-			}
-
-		}
-	}
-
-	spin_unlock(&dev->lock);
-
-	return IRQ_HANDLED;
-}
-
-static int lh7a40x_ep_enable(struct usb_ep *_ep,
-			     const struct usb_endpoint_descriptor *desc)
-{
-	struct lh7a40x_ep *ep;
-	struct lh7a40x_udc *dev;
-	unsigned long flags;
-
-	DEBUG("%s, %p\n", __func__, _ep);
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (!_ep || !desc || ep->desc || _ep->name == ep0name
-	    || desc->bDescriptorType != USB_DT_ENDPOINT
-	    || ep->bEndpointAddress != desc->bEndpointAddress
-	    || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
-		DEBUG("%s, bad ep or descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	/* xfer types must match, except that interrupt ~= bulk */
-	if (ep->bmAttributes != desc->bmAttributes
-	    && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
-	    && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
-		DEBUG("%s, %s type mismatch\n", __func__, _ep->name);
-		return -EINVAL;
-	}
-
-	/* hardware _could_ do smaller, but driver doesn't */
-	if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
-	     && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(ep))
-	    || !desc->wMaxPacketSize) {
-		DEBUG("%s, bad %s maxpacket\n", __func__, _ep->name);
-		return -ERANGE;
-	}
-
-	dev = ep->dev;
-	if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
-		DEBUG("%s, bogus device state\n", __func__);
-		return -ESHUTDOWN;
-	}
-
-	spin_lock_irqsave(&ep->dev->lock, flags);
-
-	ep->stopped = 0;
-	ep->desc = desc;
-	ep->pio_irqs = 0;
-	ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
-
-	spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-	/* Reset halt state (does flush) */
-	lh7a40x_set_halt(_ep, 0);
-
-	DEBUG("%s: enabled %s\n", __func__, _ep->name);
-	return 0;
-}
-
-/** Disable EP
- *  NOTE: Sets INDEX register
- */
-static int lh7a40x_ep_disable(struct usb_ep *_ep)
-{
-	struct lh7a40x_ep *ep;
-	unsigned long flags;
-
-	DEBUG("%s, %p\n", __func__, _ep);
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (!_ep || !ep->desc) {
-		DEBUG("%s, %s not enabled\n", __func__,
-		      _ep ? ep->ep.name : NULL);
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&ep->dev->lock, flags);
-
-	usb_set_index(ep_index(ep));
-
-	/* Nuke all pending requests (does flush) */
-	nuke(ep, -ESHUTDOWN);
-
-	/* Disable ep IRQ */
-	pio_irq_disable(ep_index(ep));
-
-	ep->desc = 0;
-	ep->stopped = 1;
-
-	spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-	DEBUG("%s: disabled %s\n", __func__, _ep->name);
-	return 0;
-}
-
-static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep,
-						 gfp_t gfp_flags)
-{
-	struct lh7a40x_request *req;
-
-	DEBUG("%s, %p\n", __func__, ep);
-
-	req = kzalloc(sizeof(*req), gfp_flags);
-	if (!req)
-		return 0;
-
-	INIT_LIST_HEAD(&req->queue);
-
-	return &req->req;
-}
-
-static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req)
-{
-	struct lh7a40x_request *req;
-
-	DEBUG("%s, %p\n", __func__, ep);
-
-	req = container_of(_req, struct lh7a40x_request, req);
-	WARN_ON(!list_empty(&req->queue));
-	kfree(req);
-}
-
-/** Queue one request
- *  Kickstart transfer if needed
- *  NOTE: Sets INDEX register
- */
-static int lh7a40x_queue(struct usb_ep *_ep, struct usb_request *_req,
-			 gfp_t gfp_flags)
-{
-	struct lh7a40x_request *req;
-	struct lh7a40x_ep *ep;
-	struct lh7a40x_udc *dev;
-	unsigned long flags;
-
-	DEBUG("\n\n\n%s, %p\n", __func__, _ep);
-
-	req = container_of(_req, struct lh7a40x_request, req);
-	if (unlikely
-	    (!_req || !_req->complete || !_req->buf
-	     || !list_empty(&req->queue))) {
-		DEBUG("%s, bad params\n", __func__);
-		return -EINVAL;
-	}
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-		DEBUG("%s, bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	dev = ep->dev;
-	if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
-		DEBUG("%s, bogus device state %p\n", __func__, dev->driver);
-		return -ESHUTDOWN;
-	}
-
-	DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length,
-	      _req->buf);
-
-	spin_lock_irqsave(&dev->lock, flags);
-
-	_req->status = -EINPROGRESS;
-	_req->actual = 0;
-
-	/* kickstart this i/o queue? */
-	DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue),
-	      ep->stopped);
-	if (list_empty(&ep->queue) && likely(!ep->stopped)) {
-		u32 csr;
-
-		if (unlikely(ep_index(ep) == 0)) {
-			/* EP0 */
-			list_add_tail(&req->queue, &ep->queue);
-			lh7a40x_ep0_kick(dev, ep);
-			req = 0;
-		} else if (ep_is_in(ep)) {
-			/* EP1 & EP3 */
-			usb_set_index(ep_index(ep));
-			csr = usb_read(ep->csr1);
-			pio_irq_enable(ep_index(ep));
-			if ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY) == 0) {
-				if (write_fifo(ep, req) == 1)
-					req = 0;
-			}
-		} else {
-			/* EP2 */
-			usb_set_index(ep_index(ep));
-			csr = usb_read(ep->csr1);
-			pio_irq_enable(ep_index(ep));
-			if (!(csr & USB_OUT_CSR1_FIFO_FULL)) {
-				if (read_fifo(ep, req) == 1)
-					req = 0;
-			}
-		}
-	}
-
-	/* pio or dma irq handler advances the queue. */
-	if (likely(req != 0))
-		list_add_tail(&req->queue, &ep->queue);
-
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	return 0;
-}
-
-/* dequeue JUST ONE request */
-static int lh7a40x_dequeue(struct usb_ep *_ep, struct usb_request *_req)
-{
-	struct lh7a40x_ep *ep;
-	struct lh7a40x_request *req;
-	unsigned long flags;
-
-	DEBUG("%s, %p\n", __func__, _ep);
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (!_ep || ep->ep.name == ep0name)
-		return -EINVAL;
-
-	spin_lock_irqsave(&ep->dev->lock, flags);
-
-	/* make sure it's actually queued on this endpoint */
-	list_for_each_entry(req, &ep->queue, queue) {
-		if (&req->req == _req)
-			break;
-	}
-	if (&req->req != _req) {
-		spin_unlock_irqrestore(&ep->dev->lock, flags);
-		return -EINVAL;
-	}
-
-	done(ep, req, -ECONNRESET);
-
-	spin_unlock_irqrestore(&ep->dev->lock, flags);
-	return 0;
-}
-
-/** Halt specific EP
- *  Return 0 if success
- *  NOTE: Sets INDEX register to EP !
- */
-static int lh7a40x_set_halt(struct usb_ep *_ep, int value)
-{
-	struct lh7a40x_ep *ep;
-	unsigned long flags;
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-		DEBUG("%s, bad ep\n", __func__);
-		return -EINVAL;
-	}
-
-	usb_set_index(ep_index(ep));
-
-	DEBUG("%s, ep %d, val %d\n", __func__, ep_index(ep), value);
-
-	spin_lock_irqsave(&ep->dev->lock, flags);
-
-	if (ep_index(ep) == 0) {
-		/* EP0 */
-		usb_set(EP0_SEND_STALL, ep->csr1);
-	} else if (ep_is_in(ep)) {
-		u32 csr = usb_read(ep->csr1);
-		if (value && ((csr & USB_IN_CSR1_FIFO_NOT_EMPTY)
-			      || !list_empty(&ep->queue))) {
-			/*
-			 * Attempts to halt IN endpoints will fail (returning -EAGAIN)
-			 * if any transfer requests are still queued, or if the controller
-			 * FIFO still holds bytes that the host hasn't collected.
-			 */
-			spin_unlock_irqrestore(&ep->dev->lock, flags);
-			DEBUG
-			    ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n",
-			     (csr & USB_IN_CSR1_FIFO_NOT_EMPTY),
-			     !list_empty(&ep->queue));
-			return -EAGAIN;
-		}
-		flush(ep);
-		if (value)
-			usb_set(USB_IN_CSR1_SEND_STALL, ep->csr1);
-		else {
-			usb_clear(USB_IN_CSR1_SEND_STALL, ep->csr1);
-			usb_set(USB_IN_CSR1_CLR_DATA_TOGGLE, ep->csr1);
-		}
-
-	} else {
-
-		flush(ep);
-		if (value)
-			usb_set(USB_OUT_CSR1_SEND_STALL, ep->csr1);
-		else {
-			usb_clear(USB_OUT_CSR1_SEND_STALL, ep->csr1);
-			usb_set(USB_OUT_CSR1_CLR_DATA_REG, ep->csr1);
-		}
-	}
-
-	if (value) {
-		ep->stopped = 1;
-	} else {
-		ep->stopped = 0;
-	}
-
-	spin_unlock_irqrestore(&ep->dev->lock, flags);
-
-	DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS");
-
-	return 0;
-}
-
-/** Return bytes in EP FIFO
- *  NOTE: Sets INDEX register to EP
- */
-static int lh7a40x_fifo_status(struct usb_ep *_ep)
-{
-	u32 csr;
-	int count = 0;
-	struct lh7a40x_ep *ep;
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (!_ep) {
-		DEBUG("%s, bad ep\n", __func__);
-		return -ENODEV;
-	}
-
-	DEBUG("%s, %d\n", __func__, ep_index(ep));
-
-	/* LPD can't report unclaimed bytes from IN fifos */
-	if (ep_is_in(ep))
-		return -EOPNOTSUPP;
-
-	usb_set_index(ep_index(ep));
-
-	csr = usb_read(ep->csr1);
-	if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN ||
-	    csr & USB_OUT_CSR1_OUT_PKT_RDY) {
-		count = usb_read(USB_OUT_FIFO_WC1);
-	}
-
-	return count;
-}
-
-/** Flush EP FIFO
- *  NOTE: Sets INDEX register to EP
- */
-static void lh7a40x_fifo_flush(struct usb_ep *_ep)
-{
-	struct lh7a40x_ep *ep;
-
-	ep = container_of(_ep, struct lh7a40x_ep, ep);
-	if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
-		DEBUG("%s, bad ep\n", __func__);
-		return;
-	}
-
-	usb_set_index(ep_index(ep));
-	flush(ep);
-}
-
-/****************************************************************/
-/* End Point 0 related functions                                */
-/****************************************************************/
-
-/* return:  0 = still running, 1 = completed, negative = errno */
-static int write_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
-{
-	u32 max;
-	unsigned count;
-	int is_last;
-
-	max = ep_maxpacket(ep);
-
-	DEBUG_EP0("%s\n", __func__);
-
-	count = write_packet(ep, req, max);
-
-	/* last packet is usually short (or a zlp) */
-	if (unlikely(count != max))
-		is_last = 1;
-	else {
-		if (likely(req->req.length != req->req.actual) || req->req.zero)
-			is_last = 0;
-		else
-			is_last = 1;
-	}
-
-	DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __func__,
-		  ep->ep.name, count,
-		  is_last ? "/L" : "", req->req.length - req->req.actual, req);
-
-	/* requests complete when all IN data is in the FIFO */
-	if (is_last) {
-		done(ep, req, 0);
-		return 1;
-	}
-
-	return 0;
-}
-
-static __inline__ int lh7a40x_fifo_read(struct lh7a40x_ep *ep,
-					unsigned char *cp, int max)
-{
-	int bytes;
-	int count = usb_read(USB_OUT_FIFO_WC1);
-	volatile u32 *fifo = (volatile u32 *)ep->fifo;
-
-	if (count > max)
-		count = max;
-	bytes = count;
-	while (count--)
-		*cp++ = *fifo & 0xFF;
-	return bytes;
-}
-
-static __inline__ void lh7a40x_fifo_write(struct lh7a40x_ep *ep,
-					  unsigned char *cp, int count)
-{
-	volatile u32 *fifo = (volatile u32 *)ep->fifo;
-	DEBUG_EP0("fifo_write: %d %d\n", ep_index(ep), count);
-	while (count--)
-		*fifo = *cp++;
-}
-
-static int read_fifo_ep0(struct lh7a40x_ep *ep, struct lh7a40x_request *req)
-{
-	u32 csr;
-	u8 *buf;
-	unsigned bufferspace, count, is_short;
-	volatile u32 *fifo = (volatile u32 *)ep->fifo;
-
-	DEBUG_EP0("%s\n", __func__);
-
-	csr = usb_read(USB_EP0_CSR);
-	if (!(csr & USB_OUT_CSR1_OUT_PKT_RDY))
-		return 0;
-
-	buf = req->req.buf + req->req.actual;
-	prefetchw(buf);
-	bufferspace = req->req.length - req->req.actual;
-
-	/* read all bytes from this packet */
-	if (likely(csr & EP0_OUT_PKT_RDY)) {
-		count = usb_read(USB_OUT_FIFO_WC1);
-		req->req.actual += min(count, bufferspace);
-	} else			/* zlp */
-		count = 0;
-
-	is_short = (count < ep->ep.maxpacket);
-	DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n",
-		  ep->ep.name, csr, count,
-		  is_short ? "/S" : "", req, req->req.actual, req->req.length);
-
-	while (likely(count-- != 0)) {
-		u8 byte = (u8) (*fifo & 0xff);
-
-		if (unlikely(bufferspace == 0)) {
-			/* this happens when the driver's buffer
-			 * is smaller than what the host sent.
-			 * discard the extra data.
-			 */
-			if (req->req.status != -EOVERFLOW)
-				DEBUG_EP0("%s overflow %d\n", ep->ep.name,
-					  count);
-			req->req.status = -EOVERFLOW;
-		} else {
-			*buf++ = byte;
-			bufferspace--;
-		}
-	}
-
-	/* completion */
-	if (is_short || req->req.actual == req->req.length) {
-		done(ep, req, 0);
-		return 1;
-	}
-
-	/* finished that packet.  the next one may be waiting... */
-	return 0;
-}
-
-/**
- * udc_set_address - set the USB address for this device
- * @address:
- *
- * Called from control endpoint function after it decodes a set address setup packet.
- */
-static void udc_set_address(struct lh7a40x_udc *dev, unsigned char address)
-{
-	DEBUG_EP0("%s: %d\n", __func__, address);
-	/* c.f. 15.1.2.2 Table 15-4 address will be used after DATA_END is set */
-	dev->usb_address = address;
-	usb_set((address & USB_FA_FUNCTION_ADDR), USB_FA);
-	usb_set(USB_FA_ADDR_UPDATE | (address & USB_FA_FUNCTION_ADDR), USB_FA);
-	/* usb_read(USB_FA); */
-}
-
-/*
- * DATA_STATE_RECV (OUT_PKT_RDY)
- *      - if error
- *              set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits
- *      - else
- *              set EP0_CLR_OUT bit
- 				if last set EP0_DATA_END bit
- */
-static void lh7a40x_ep0_out(struct lh7a40x_udc *dev, u32 csr)
-{
-	struct lh7a40x_request *req;
-	struct lh7a40x_ep *ep = &dev->ep[0];
-	int ret;
-
-	DEBUG_EP0("%s: %x\n", __func__, csr);
-
-	if (list_empty(&ep->queue))
-		req = 0;
-	else
-		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
-
-	if (req) {
-
-		if (req->req.length == 0) {
-			DEBUG_EP0("ZERO LENGTH OUT!\n");
-			usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
-			dev->ep0state = WAIT_FOR_SETUP;
-			return;
-		}
-		ret = read_fifo_ep0(ep, req);
-		if (ret) {
-			/* Done! */
-			DEBUG_EP0("%s: finished, waiting for status\n",
-				  __func__);
-
-			usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
-			dev->ep0state = WAIT_FOR_SETUP;
-		} else {
-			/* Not done yet.. */
-			DEBUG_EP0("%s: not finished\n", __func__);
-			usb_set(EP0_CLR_OUT, USB_EP0_CSR);
-		}
-	} else {
-		DEBUG_EP0("NO REQ??!\n");
-	}
-}
-
-/*
- * DATA_STATE_XMIT
- */
-static int lh7a40x_ep0_in(struct lh7a40x_udc *dev, u32 csr)
-{
-	struct lh7a40x_request *req;
-	struct lh7a40x_ep *ep = &dev->ep[0];
-	int ret, need_zlp = 0;
-
-	DEBUG_EP0("%s: %x\n", __func__, csr);
-
-	if (list_empty(&ep->queue))
-		req = 0;
-	else
-		req = list_entry(ep->queue.next, struct lh7a40x_request, queue);
-
-	if (!req) {
-		DEBUG_EP0("%s: NULL REQ\n", __func__);
-		return 0;
-	}
-
-	if (req->req.length == 0) {
-
-		usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
-		dev->ep0state = WAIT_FOR_SETUP;
-		return 1;
-	}
-
-	if (req->req.length - req->req.actual == EP0_PACKETSIZE) {
-		/* Next write will end with the packet size, */
-		/* so we need Zero-length-packet */
-		need_zlp = 1;
-	}
-
-	ret = write_fifo_ep0(ep, req);
-
-	if (ret == 1 && !need_zlp) {
-		/* Last packet */
-		DEBUG_EP0("%s: finished, waiting for status\n", __func__);
-
-		usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
-		dev->ep0state = WAIT_FOR_SETUP;
-	} else {
-		DEBUG_EP0("%s: not finished\n", __func__);
-		usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
-	}
-
-	if (need_zlp) {
-		DEBUG_EP0("%s: Need ZLP!\n", __func__);
-		usb_set(EP0_IN_PKT_RDY, USB_EP0_CSR);
-		dev->ep0state = DATA_STATE_NEED_ZLP;
-	}
-
-	return 1;
-}
-
-static int lh7a40x_handle_get_status(struct lh7a40x_udc *dev,
-				     struct usb_ctrlrequest *ctrl)
-{
-	struct lh7a40x_ep *ep0 = &dev->ep[0];
-	struct lh7a40x_ep *qep;
-	int reqtype = (ctrl->bRequestType & USB_RECIP_MASK);
-	u16 val = 0;
-
-	if (reqtype == USB_RECIP_INTERFACE) {
-		/* This is not supported.
-		 * And according to the USB spec, this one does nothing..
-		 * Just return 0
-		 */
-		DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n");
-	} else if (reqtype == USB_RECIP_DEVICE) {
-		DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n");
-		val |= (1 << 0);	/* Self powered */
-		/*val |= (1<<1); *//* Remote wakeup */
-	} else if (reqtype == USB_RECIP_ENDPOINT) {
-		int ep_num = (ctrl->wIndex & ~USB_DIR_IN);
-
-		DEBUG_SETUP
-		    ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n",
-		     ep_num, ctrl->wLength);
-
-		if (ctrl->wLength > 2 || ep_num > 3)
-			return -EOPNOTSUPP;
-
-		qep = &dev->ep[ep_num];
-		if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0)
-		    && ep_index(qep) != 0) {
-			return -EOPNOTSUPP;
-		}
-
-		usb_set_index(ep_index(qep));
-
-		/* Return status on next IN token */
-		switch (qep->ep_type) {
-		case ep_control:
-			val =
-			    (usb_read(qep->csr1) & EP0_SEND_STALL) ==
-			    EP0_SEND_STALL;
-			break;
-		case ep_bulk_in:
-		case ep_interrupt:
-			val =
-			    (usb_read(qep->csr1) & USB_IN_CSR1_SEND_STALL) ==
-			    USB_IN_CSR1_SEND_STALL;
-			break;
-		case ep_bulk_out:
-			val =
-			    (usb_read(qep->csr1) & USB_OUT_CSR1_SEND_STALL) ==
-			    USB_OUT_CSR1_SEND_STALL;
-			break;
-		}
-
-		/* Back to EP0 index */
-		usb_set_index(0);
-
-		DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num,
-			    ctrl->wIndex, val);
-	} else {
-		DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype);
-		return -EOPNOTSUPP;
-	}
-
-	/* Clear "out packet ready" */
-	usb_set((EP0_CLR_OUT), USB_EP0_CSR);
-	/* Put status to FIFO */
-	lh7a40x_fifo_write(ep0, (u8 *) & val, sizeof(val));
-	/* Issue "In packet ready" */
-	usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
-
-	return 0;
-}
-
-/*
- * WAIT_FOR_SETUP (OUT_PKT_RDY)
- *      - read data packet from EP0 FIFO
- *      - decode command
- *      - if error
- *              set EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL bits
- *      - else
- *              set EP0_CLR_OUT | EP0_DATA_END bits
- */
-static void lh7a40x_ep0_setup(struct lh7a40x_udc *dev, u32 csr)
-{
-	struct lh7a40x_ep *ep = &dev->ep[0];
-	struct usb_ctrlrequest ctrl;
-	int i, bytes, is_in;
-
-	DEBUG_SETUP("%s: %x\n", __func__, csr);
-
-	/* Nuke all previous transfers */
-	nuke(ep, -EPROTO);
-
-	/* read control req from fifo (8 bytes) */
-	bytes = lh7a40x_fifo_read(ep, (unsigned char *)&ctrl, 8);
-
-	DEBUG_SETUP("Read CTRL REQ %d bytes\n", bytes);
-	DEBUG_SETUP("CTRL.bRequestType = %d (is_in %d)\n", ctrl.bRequestType,
-		    ctrl.bRequestType == USB_DIR_IN);
-	DEBUG_SETUP("CTRL.bRequest = %d\n", ctrl.bRequest);
-	DEBUG_SETUP("CTRL.wLength = %d\n", ctrl.wLength);
-	DEBUG_SETUP("CTRL.wValue = %d (%d)\n", ctrl.wValue, ctrl.wValue >> 8);
-	DEBUG_SETUP("CTRL.wIndex = %d\n", ctrl.wIndex);
-
-	/* Set direction of EP0 */
-	if (likely(ctrl.bRequestType & USB_DIR_IN)) {
-		ep->bEndpointAddress |= USB_DIR_IN;
-		is_in = 1;
-	} else {
-		ep->bEndpointAddress &= ~USB_DIR_IN;
-		is_in = 0;
-	}
-
-	dev->req_pending = 1;
-
-	/* Handle some SETUP packets ourselves */
-	switch (ctrl.bRequest) {
-	case USB_REQ_SET_ADDRESS:
-		if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
-			break;
-
-		DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue);
-		udc_set_address(dev, ctrl.wValue);
-		usb_set((EP0_CLR_OUT | EP0_DATA_END), USB_EP0_CSR);
-		return;
-
-	case USB_REQ_GET_STATUS:{
-			if (lh7a40x_handle_get_status(dev, &ctrl) == 0)
-				return;
-
-	case USB_REQ_CLEAR_FEATURE:
-	case USB_REQ_SET_FEATURE:
-			if (ctrl.bRequestType == USB_RECIP_ENDPOINT) {
-				struct lh7a40x_ep *qep;
-				int ep_num = (ctrl.wIndex & 0x0f);
-
-				/* Support only HALT feature */
-				if (ctrl.wValue != 0 || ctrl.wLength != 0
-				    || ep_num > 3 || ep_num < 1)
-					break;
-
-				qep = &dev->ep[ep_num];
-				spin_unlock(&dev->lock);
-				if (ctrl.bRequest == USB_REQ_SET_FEATURE) {
-					DEBUG_SETUP("SET_FEATURE (%d)\n",
-						    ep_num);
-					lh7a40x_set_halt(&qep->ep, 1);
-				} else {
-					DEBUG_SETUP("CLR_FEATURE (%d)\n",
-						    ep_num);
-					lh7a40x_set_halt(&qep->ep, 0);
-				}
-				spin_lock(&dev->lock);
-				usb_set_index(0);
-
-				/* Reply with a ZLP on next IN token */
-				usb_set((EP0_CLR_OUT | EP0_DATA_END),
-					USB_EP0_CSR);
-				return;
-			}
-			break;
-		}
-
-	default:
-		break;
-	}
-
-	if (likely(dev->driver)) {
-		/* device-2-host (IN) or no data setup command, process immediately */
-		spin_unlock(&dev->lock);
-		i = dev->driver->setup(&dev->gadget, &ctrl);
-		spin_lock(&dev->lock);
-
-		if (i < 0) {
-			/* setup processing failed, force stall */
-			DEBUG_SETUP
-			    ("  --> ERROR: gadget setup FAILED (stalling), setup returned %d\n",
-			     i);
-			usb_set_index(0);
-			usb_set((EP0_CLR_OUT | EP0_DATA_END | EP0_SEND_STALL),
-				USB_EP0_CSR);
-
-			/* ep->stopped = 1; */
-			dev->ep0state = WAIT_FOR_SETUP;
-		}
-	}
-}
-
-/*
- * DATA_STATE_NEED_ZLP
- */
-static void lh7a40x_ep0_in_zlp(struct lh7a40x_udc *dev, u32 csr)
-{
-	DEBUG_EP0("%s: %x\n", __func__, csr);
-
-	/* c.f. Table 15-14 */
-	usb_set((EP0_IN_PKT_RDY | EP0_DATA_END), USB_EP0_CSR);
-	dev->ep0state = WAIT_FOR_SETUP;
-}
-
-/*
- * handle ep0 interrupt
- */
-static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr)
-{
-	struct lh7a40x_ep *ep = &dev->ep[0];
-	u32 csr;
-
-	/* Set index 0 */
-	usb_set_index(0);
- 	csr = usb_read(USB_EP0_CSR);
-
-	DEBUG_EP0("%s: csr = %x\n", __func__, csr);
-
-	/*
-	 * For overview of what we should be doing see c.f. Chapter 18.1.2.4
-	 * We will follow that outline here modified by our own global state
-	 * indication which provides hints as to what we think should be
-	 * happening..
-	 */
-
-	/*
-	 * if SENT_STALL is set
-	 *      - clear the SENT_STALL bit
-	 */
-	if (csr & EP0_SENT_STALL) {
-		DEBUG_EP0("%s: EP0_SENT_STALL is set: %x\n", __func__, csr);
-		usb_clear((EP0_SENT_STALL | EP0_SEND_STALL), USB_EP0_CSR);
-		nuke(ep, -ECONNABORTED);
-		dev->ep0state = WAIT_FOR_SETUP;
-		return;
-	}
-
-	/*
-	 * if a transfer is in progress && IN_PKT_RDY and OUT_PKT_RDY are clear
-	 *      - fill EP0 FIFO
-	 *      - if last packet
-	 *      -       set IN_PKT_RDY | DATA_END
-	 *      - else
-	 *              set IN_PKT_RDY
-	 */
-	if (!(csr & (EP0_IN_PKT_RDY | EP0_OUT_PKT_RDY))) {
-		DEBUG_EP0("%s: IN_PKT_RDY and OUT_PKT_RDY are clear\n",
-			  __func__);
-
-		switch (dev->ep0state) {
-		case DATA_STATE_XMIT:
-			DEBUG_EP0("continue with DATA_STATE_XMIT\n");
-			lh7a40x_ep0_in(dev, csr);
-			return;
-		case DATA_STATE_NEED_ZLP:
-			DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n");
-			lh7a40x_ep0_in_zlp(dev, csr);
-			return;
-		default:
-			/* Stall? */
-			DEBUG_EP0("Odd state!! state = %s\n",
-				  state_names[dev->ep0state]);
-			dev->ep0state = WAIT_FOR_SETUP;
-			/* nuke(ep, 0); */
-			/* usb_set(EP0_SEND_STALL, ep->csr1); */
-			break;
-		}
-	}
-
-	/*
-	 * if SETUP_END is set
-	 *      - abort the last transfer
-	 *      - set SERVICED_SETUP_END_BIT
-	 */
-	if (csr & EP0_SETUP_END) {
-		DEBUG_EP0("%s: EP0_SETUP_END is set: %x\n", __func__, csr);
-
-		usb_set(EP0_CLR_SETUP_END, USB_EP0_CSR);
-
-		nuke(ep, 0);
-		dev->ep0state = WAIT_FOR_SETUP;
-	}
-
-	/*
-	 * if EP0_OUT_PKT_RDY is set
-	 *      - read data packet from EP0 FIFO
-	 *      - decode command
-	 *      - if error
-	 *              set SERVICED_OUT_PKT_RDY | DATA_END bits | SEND_STALL
-	 *      - else
-	 *              set SERVICED_OUT_PKT_RDY | DATA_END bits
-	 */
-	if (csr & EP0_OUT_PKT_RDY) {
-
-		DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __func__,
-			  csr);
-
-		switch (dev->ep0state) {
-		case WAIT_FOR_SETUP:
-			DEBUG_EP0("WAIT_FOR_SETUP\n");
-			lh7a40x_ep0_setup(dev, csr);
-			break;
-
-		case DATA_STATE_RECV:
-			DEBUG_EP0("DATA_STATE_RECV\n");
-			lh7a40x_ep0_out(dev, csr);
-			break;
-
-		default:
-			/* send stall? */
-			DEBUG_EP0("strange state!! 2. send stall? state = %d\n",
-				  dev->ep0state);
-			break;
-		}
-	}
-}
-
-static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep)
-{
-	u32 csr;
-
-	usb_set_index(0);
-	csr = usb_read(USB_EP0_CSR);
-
-	DEBUG_EP0("%s: %x\n", __func__, csr);
-
-	/* Clear "out packet ready" */
-	usb_set(EP0_CLR_OUT, USB_EP0_CSR);
-
-	if (ep_is_in(ep)) {
-		dev->ep0state = DATA_STATE_XMIT;
-		lh7a40x_ep0_in(dev, csr);
-	} else {
-		dev->ep0state = DATA_STATE_RECV;
-		lh7a40x_ep0_out(dev, csr);
-	}
-}
-
-/* ---------------------------------------------------------------------------
- * 	device-scoped parts of the api to the usb controller hardware
- * ---------------------------------------------------------------------------
- */
-
-static int lh7a40x_udc_get_frame(struct usb_gadget *_gadget)
-{
-	u32 frame1 = usb_read(USB_FRM_NUM1);	/* Least significant 8 bits */
-	u32 frame2 = usb_read(USB_FRM_NUM2);	/* Most significant 3 bits */
-	DEBUG("%s, %p\n", __func__, _gadget);
-	return ((frame2 & 0x07) << 8) | (frame1 & 0xff);
-}
-
-static int lh7a40x_udc_wakeup(struct usb_gadget *_gadget)
-{
-	/* host may not have enabled remote wakeup */
-	/*if ((UDCCS0 & UDCCS0_DRWF) == 0)
-	   return -EHOSTUNREACH;
-	   udc_set_mask_UDCCR(UDCCR_RSM); */
-	return -ENOTSUPP;
-}
-
-static const struct usb_gadget_ops lh7a40x_udc_ops = {
-	.get_frame = lh7a40x_udc_get_frame,
-	.wakeup = lh7a40x_udc_wakeup,
-	/* current versions must always be self-powered */
-};
-
-static void nop_release(struct device *dev)
-{
-	DEBUG("%s %s\n", __func__, dev_name(dev));
-}
-
-static struct lh7a40x_udc memory = {
-	.usb_address = 0,
-
-	.gadget = {
-		   .ops = &lh7a40x_udc_ops,
-		   .ep0 = &memory.ep[0].ep,
-		   .name = driver_name,
-		   .dev = {
-			   .init_name = "gadget",
-			   .release = nop_release,
-			   },
-		   },
-
-	/* control endpoint */
-	.ep[0] = {
-		  .ep = {
-			 .name = ep0name,
-			 .ops = &lh7a40x_ep_ops,
-			 .maxpacket = EP0_PACKETSIZE,
-			 },
-		  .dev = &memory,
-
-		  .bEndpointAddress = 0,
-		  .bmAttributes = 0,
-
-		  .ep_type = ep_control,
-		  .fifo = io_p2v(USB_EP0_FIFO),
-		  .csr1 = USB_EP0_CSR,
-		  .csr2 = USB_EP0_CSR,
-		  },
-
-	/* first group of endpoints */
-	.ep[1] = {
-		  .ep = {
-			 .name = "ep1in-bulk",
-			 .ops = &lh7a40x_ep_ops,
-			 .maxpacket = 64,
-			 },
-		  .dev = &memory,
-
-		  .bEndpointAddress = USB_DIR_IN | 1,
-		  .bmAttributes = USB_ENDPOINT_XFER_BULK,
-
-		  .ep_type = ep_bulk_in,
-		  .fifo = io_p2v(USB_EP1_FIFO),
-		  .csr1 = USB_IN_CSR1,
-		  .csr2 = USB_IN_CSR2,
-		  },
-
-	.ep[2] = {
-		  .ep = {
-			 .name = "ep2out-bulk",
-			 .ops = &lh7a40x_ep_ops,
-			 .maxpacket = 64,
-			 },
-		  .dev = &memory,
-
-		  .bEndpointAddress = 2,
-		  .bmAttributes = USB_ENDPOINT_XFER_BULK,
-
-		  .ep_type = ep_bulk_out,
-		  .fifo = io_p2v(USB_EP2_FIFO),
-		  .csr1 = USB_OUT_CSR1,
-		  .csr2 = USB_OUT_CSR2,
-		  },
-
-	.ep[3] = {
-		  .ep = {
-			 .name = "ep3in-int",
-			 .ops = &lh7a40x_ep_ops,
-			 .maxpacket = 64,
-			 },
-		  .dev = &memory,
-
-		  .bEndpointAddress = USB_DIR_IN | 3,
-		  .bmAttributes = USB_ENDPOINT_XFER_INT,
-
-		  .ep_type = ep_interrupt,
-		  .fifo = io_p2v(USB_EP3_FIFO),
-		  .csr1 = USB_IN_CSR1,
-		  .csr2 = USB_IN_CSR2,
-		  },
-};
-
-/*
- * 	probe - binds to the platform device
- */
-static int lh7a40x_udc_probe(struct platform_device *pdev)
-{
-	struct lh7a40x_udc *dev = &memory;
-	int retval;
-
-	DEBUG("%s: %p\n", __func__, pdev);
-
-	spin_lock_init(&dev->lock);
-	dev->dev = &pdev->dev;
-
-	device_initialize(&dev->gadget.dev);
-	dev->gadget.dev.parent = &pdev->dev;
-
-	the_controller = dev;
-	platform_set_drvdata(pdev, dev);
-
-	udc_disable(dev);
-	udc_reinit(dev);
-
-	/* irq setup after old hardware state is cleaned up */
-	retval =
-	    request_irq(IRQ_USBINTR, lh7a40x_udc_irq, IRQF_DISABLED, driver_name,
-			dev);
-	if (retval != 0) {
-		DEBUG(KERN_ERR "%s: can't get irq %i, err %d\n", driver_name,
-		      IRQ_USBINTR, retval);
-		return -EBUSY;
-	}
-
-	create_proc_files();
-
-	return retval;
-}
-
-static int lh7a40x_udc_remove(struct platform_device *pdev)
-{
-	struct lh7a40x_udc *dev = platform_get_drvdata(pdev);
-
-	DEBUG("%s: %p\n", __func__, pdev);
-
-	if (dev->driver)
-		return -EBUSY;
-
-	udc_disable(dev);
-	remove_proc_files();
-
-	free_irq(IRQ_USBINTR, dev);
-
-	platform_set_drvdata(pdev, 0);
-
-	the_controller = 0;
-
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static struct platform_driver udc_driver = {
-	.probe = lh7a40x_udc_probe,
-	.remove = lh7a40x_udc_remove,
-	    /* FIXME power management support */
-	    /* .suspend = ... disable UDC */
-	    /* .resume = ... re-enable UDC */
-	.driver	= {
-		.name = (char *)driver_name,
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init udc_init(void)
-{
-	DEBUG("%s: %s version %s\n", __func__, driver_name, DRIVER_VERSION);
-	return platform_driver_register(&udc_driver);
-}
-
-static void __exit udc_exit(void)
-{
-	platform_driver_unregister(&udc_driver);
-}
-
-module_init(udc_init);
-module_exit(udc_exit);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Mikko Lahteenmaki, Bo Henriksen");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:lh7a40x_udc");
diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h
deleted file mode 100644
index ca86120..0000000
--- a/drivers/usb/gadget/lh7a40x_udc.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * linux/drivers/usb/gadget/lh7a40x_udc.h
- * Sharp LH7A40x on-chip full speed USB device controllers
- *
- * Copyright (C) 2004 Mikko Lahteenmaki, Nordic ID
- * Copyright (C) 2004 Bo Henriksen, Nordic ID
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You 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 __LH7A40X_H_
-#define __LH7A40X_H_
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/timer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/byteorder.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <mach/hardware.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-
-/*
- * Memory map
- */
-
-#define USB_FA					0x80000200	// function address register
-#define USB_PM					0x80000204	// power management register
-
-#define USB_IN_INT				0x80000208	// IN interrupt register bank (EP0-EP3)
-#define USB_OUT_INT				0x80000210	// OUT interrupt register bank (EP2)
-#define USB_INT					0x80000218	// interrupt register bank
-
-#define USB_IN_INT_EN			0x8000021C	// IN interrupt enable register bank
-#define USB_OUT_INT_EN			0x80000224	// OUT interrupt enable register bank
-#define USB_INT_EN				0x8000022C	// USB interrupt enable register bank
-
-#define USB_FRM_NUM1			0x80000230	// Frame number1 register
-#define USB_FRM_NUM2			0x80000234	// Frame number2 register
-#define USB_INDEX				0x80000238	// index register
-
-#define USB_IN_MAXP				0x80000240	// IN MAXP register
-#define USB_IN_CSR1				0x80000244	// IN CSR1 register/EP0 CSR register
-#define USB_EP0_CSR				0x80000244	// IN CSR1 register/EP0 CSR register
-#define USB_IN_CSR2				0x80000248	// IN CSR2 register
-#define USB_OUT_MAXP			0x8000024C	// OUT MAXP register
-
-#define USB_OUT_CSR1			0x80000250	// OUT CSR1 register
-#define USB_OUT_CSR2			0x80000254	// OUT CSR2 register
-#define USB_OUT_FIFO_WC1		0x80000258	// OUT FIFO write count1 register
-#define USB_OUT_FIFO_WC2		0x8000025C	// OUT FIFO write count2 register
-
-#define USB_RESET				0x8000044C	// USB reset register
-
-#define	USB_EP0_FIFO			0x80000280
-#define	USB_EP1_FIFO			0x80000284
-#define	USB_EP2_FIFO			0x80000288
-#define	USB_EP3_FIFO			0x8000028c
-
-/*
- * USB reset register
- */
-#define USB_RESET_APB			(1<<1)	//resets USB APB control side WRITE
-#define USB_RESET_IO			(1<<0)	//resets USB IO side WRITE
-
-/*
- * USB function address register
- */
-#define USB_FA_ADDR_UPDATE		(1<<7)
-#define USB_FA_FUNCTION_ADDR	(0x7F)
-
-/*
- * Power Management register
- */
-#define PM_USB_DCP				(1<<5)
-#define PM_USB_ENABLE			(1<<4)
-#define PM_USB_RESET			(1<<3)
-#define PM_UC_RESUME			(1<<2)
-#define PM_SUSPEND_MODE			(1<<1)
-#define PM_ENABLE_SUSPEND		(1<<0)
-
-/*
- * IN interrupt register
- */
-#define USB_IN_INT_EP3				(1<<3)
-#define USB_IN_INT_EP1				(1<<1)
-#define USB_IN_INT_EP0				(1<<0)
-
-/*
- * OUT interrupt register
- */
-#define USB_OUT_INT_EP2				(1<<2)
-
-/*
- * USB interrupt register
- */
-#define USB_INT_RESET_INT			(1<<2)
-#define USB_INT_RESUME_INT			(1<<1)
-#define USB_INT_SUSPEND_INT			(1<<0)
-
-/*
- * USB interrupt enable register
- */
-#define USB_INT_EN_USB_RESET_INTER		(1<<2)
-#define USB_INT_EN_RESUME_INTER			(1<<1)
-#define USB_INT_EN_SUSPEND_INTER		(1<<0)
-
-/*
- * INCSR1 register
- */
-#define USB_IN_CSR1_CLR_DATA_TOGGLE		(1<<6)
-#define USB_IN_CSR1_SENT_STALL			(1<<5)
-#define USB_IN_CSR1_SEND_STALL			(1<<4)
-#define USB_IN_CSR1_FIFO_FLUSH			(1<<3)
-#define USB_IN_CSR1_FIFO_NOT_EMPTY		(1<<1)
-#define USB_IN_CSR1_IN_PKT_RDY			(1<<0)
-
-/*
- * INCSR2 register
- */
-#define USB_IN_CSR2_AUTO_SET			(1<<7)
-#define USB_IN_CSR2_USB_DMA_EN			(1<<4)
-
-/*
- * OUT CSR1 register
- */
-#define USB_OUT_CSR1_CLR_DATA_REG		(1<<7)
-#define USB_OUT_CSR1_SENT_STALL			(1<<6)
-#define USB_OUT_CSR1_SEND_STALL			(1<<5)
-#define USB_OUT_CSR1_FIFO_FLUSH			(1<<4)
-#define USB_OUT_CSR1_FIFO_FULL			(1<<1)
-#define USB_OUT_CSR1_OUT_PKT_RDY		(1<<0)
-
-/*
- * OUT CSR2 register
- */
-#define USB_OUT_CSR2_AUTO_CLR			(1<<7)
-#define USB_OUT_CSR2_USB_DMA_EN			(1<<4)
-
-/*
- * EP0 CSR
- */
-#define EP0_CLR_SETUP_END		(1<<7)	/* Clear "Setup Ends" Bit (w) */
-#define EP0_CLR_OUT				(1<<6)	/* Clear "Out packet ready" Bit (w) */
-#define EP0_SEND_STALL			(1<<5)	/* Send STALL Handshake (rw) */
-#define EP0_SETUP_END			(1<<4)	/* Setup Ends (r) */
-
-#define EP0_DATA_END			(1<<3)	/* Data end (rw) */
-#define EP0_SENT_STALL			(1<<2)	/* Sent Stall Handshake (r) */
-#define EP0_IN_PKT_RDY			(1<<1)	/* In packet ready (rw) */
-#define EP0_OUT_PKT_RDY			(1<<0)	/* Out packet ready (r) */
-
-/* general CSR */
-#define OUT_PKT_RDY		(1<<0)
-#define IN_PKT_RDY		(1<<0)
-
-/*
- * IN/OUT MAXP register
- */
-#define USB_OUT_MAXP_MAXP			(0xF)
-#define USB_IN_MAXP_MAXP			(0xF)
-
-// Max packet size
-//#define EP0_PACKETSIZE        0x10
-#define EP0_PACKETSIZE  	0x8
-#define EP0_MAXPACKETSIZE  	0x10
-
-#define UDC_MAX_ENDPOINTS       4
-
-#define WAIT_FOR_SETUP          0
-#define DATA_STATE_XMIT         1
-#define DATA_STATE_NEED_ZLP     2
-#define WAIT_FOR_OUT_STATUS     3
-#define DATA_STATE_RECV         4
-
-/* ********************************************************************************************* */
-/* IO
- */
-
-typedef enum ep_type {
-	ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
-} ep_type_t;
-
-struct lh7a40x_ep {
-	struct usb_ep ep;
-	struct lh7a40x_udc *dev;
-
-	const struct usb_endpoint_descriptor *desc;
-	struct list_head queue;
-	unsigned long pio_irqs;
-
-	u8 stopped;
-	u8 bEndpointAddress;
-	u8 bmAttributes;
-
-	ep_type_t ep_type;
-	u32 fifo;
-	u32 csr1;
-	u32 csr2;
-};
-
-struct lh7a40x_request {
-	struct usb_request req;
-	struct list_head queue;
-};
-
-struct lh7a40x_udc {
-	struct usb_gadget gadget;
-	struct usb_gadget_driver *driver;
-	struct device *dev;
-	spinlock_t lock;
-
-	int ep0state;
-	struct lh7a40x_ep ep[UDC_MAX_ENDPOINTS];
-
-	unsigned char usb_address;
-
-	unsigned req_pending:1, req_std:1, req_config:1;
-};
-
-extern struct lh7a40x_udc *the_controller;
-
-#define ep_is_in(EP) 		(((EP)->bEndpointAddress&USB_DIR_IN)==USB_DIR_IN)
-#define ep_index(EP) 		((EP)->bEndpointAddress&0xF)
-#define ep_maxpacket(EP) 	((EP)->ep.maxpacket)
-
-#endif
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 51b19f3..084aa08 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -258,7 +258,7 @@ static int pipe_buffer_setting(struct m66592 *m66592,
 		break;
 	case M66592_BULK:
 		/* isochronous pipes may be used as bulk pipes */
-		if (info->pipe > M66592_BASE_PIPENUM_BULK)
+		if (info->pipe >= M66592_BASE_PIPENUM_BULK)
 			bufnum = info->pipe - M66592_BASE_PIPENUM_BULK;
 		else
 			bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC;
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index b120dbb..3e4b35e 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -367,7 +367,6 @@ struct pch_udc_dev {
 static const char	ep0_string[] = "ep0in";
 static DEFINE_SPINLOCK(udc_stall_spinlock);	/* stall spin lock */
 struct pch_udc_dev *pch_udc;		/* pointer to device object */
-
 static int speed_fs;
 module_param_named(speed_fs, speed_fs, bool, S_IRUGO);
 MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
@@ -383,6 +382,8 @@ MODULE_PARM_DESC(speed_fs, "true for Full speed operation");
  * @dma_mapped:		DMA memory mapped for request
  * @dma_done:		DMA completed for request
  * @chain_len:		chain length
+ * @buf:		Buffer memory for align adjustment
+ * @dma:		DMA memory for align adjustment
  */
 struct pch_udc_request {
 	struct usb_request		req;
@@ -394,6 +395,8 @@ struct pch_udc_request {
 					dma_mapped:1,
 					dma_done:1;
 	unsigned			chain_len;
+	void				*buf;
+	dma_addr_t			dma;
 };
 
 static inline u32 pch_udc_readl(struct pch_udc_dev *dev, unsigned long reg)
@@ -615,7 +618,7 @@ static inline void pch_udc_ep_set_trfr_type(struct pch_udc_ep *ep,
 /**
  * pch_udc_ep_set_bufsz() - Set the maximum packet size for the endpoint
  * @ep:		Reference to structure of type pch_udc_ep_regs
- * @buf_size:	The buffer size
+ * @buf_size:	The buffer word size
  */
 static void pch_udc_ep_set_bufsz(struct pch_udc_ep *ep,
 						 u32 buf_size, u32 ep_in)
@@ -635,7 +638,7 @@ static void pch_udc_ep_set_bufsz(struct pch_udc_ep *ep,
 /**
  * pch_udc_ep_set_maxpkt() - Set the Max packet size for the endpoint
  * @ep:		Reference to structure of type pch_udc_ep_regs
- * @pkt_size:	The packet size
+ * @pkt_size:	The packet byte size
  */
 static void pch_udc_ep_set_maxpkt(struct pch_udc_ep *ep, u32 pkt_size)
 {
@@ -920,25 +923,10 @@ static void pch_udc_ep_clear_nak(struct pch_udc_ep *ep)
  */
 static void pch_udc_ep_fifo_flush(struct pch_udc_ep *ep, int dir)
 {
-	unsigned int loopcnt = 0;
-	struct pch_udc_dev *dev = ep->dev;
-
 	if (dir) {	/* IN ep */
 		pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_F);
 		return;
 	}
-
-	if (pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP)
-		return;
-	pch_udc_ep_bit_set(ep, UDC_EPCTL_ADDR, UDC_EPCTL_MRXFLUSH);
-	/* Wait for RxFIFO Empty */
-	loopcnt = 10000;
-	while (!(pch_udc_read_ep_status(ep) & UDC_EPSTS_MRXFIFO_EMP) &&
-		--loopcnt)
-		udelay(5);
-	if (!loopcnt)
-		dev_err(&dev->pdev->dev, "RxFIFO not Empty\n");
-	pch_udc_ep_bit_clr(ep, UDC_EPCTL_ADDR, UDC_EPCTL_MRXFLUSH);
 }
 
 /**
@@ -1220,14 +1208,31 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
 
 	dev = ep->dev;
 	if (req->dma_mapped) {
-		if (ep->in)
-			dma_unmap_single(&dev->pdev->dev, req->req.dma,
-					 req->req.length, DMA_TO_DEVICE);
-		else
-			dma_unmap_single(&dev->pdev->dev, req->req.dma,
-					 req->req.length, DMA_FROM_DEVICE);
+		if (req->dma == DMA_ADDR_INVALID) {
+			if (ep->in)
+				dma_unmap_single(&dev->pdev->dev, req->req.dma,
+						 req->req.length,
+						 DMA_TO_DEVICE);
+			else
+				dma_unmap_single(&dev->pdev->dev, req->req.dma,
+						 req->req.length,
+						 DMA_FROM_DEVICE);
+			req->req.dma = DMA_ADDR_INVALID;
+		} else {
+			if (ep->in)
+				dma_unmap_single(&dev->pdev->dev, req->dma,
+						 req->req.length,
+						 DMA_TO_DEVICE);
+			else {
+				dma_unmap_single(&dev->pdev->dev, req->dma,
+						 req->req.length,
+						 DMA_FROM_DEVICE);
+				memcpy(req->req.buf, req->buf, req->req.length);
+			}
+			kfree(req->buf);
+			req->dma = DMA_ADDR_INVALID;
+		}
 		req->dma_mapped = 0;
-		req->req.dma = DMA_ADDR_INVALID;
 	}
 	ep->halted = 1;
 	spin_unlock(&dev->lock);
@@ -1268,12 +1273,18 @@ static void pch_udc_free_dma_chain(struct pch_udc_dev *dev,
 	struct pch_udc_data_dma_desc *td = req->td_data;
 	unsigned i = req->chain_len;
 
+	dma_addr_t addr2;
+	dma_addr_t addr = (dma_addr_t)td->next;
+	td->next = 0x00;
 	for (; i > 1; --i) {
-		dma_addr_t addr = (dma_addr_t)td->next;
 		/* do not free first desc., will be done by free for request */
 		td = phys_to_virt(addr);
+		addr2 = (dma_addr_t)td->next;
 		pci_pool_free(dev->data_requests, td, addr);
+		td->next = 0x00;
+		addr = addr2;
 	}
+	req->chain_len = 1;
 }
 
 /**
@@ -1301,23 +1312,23 @@ static int pch_udc_create_dma_chain(struct pch_udc_ep *ep,
 	if (req->chain_len > 1)
 		pch_udc_free_dma_chain(ep->dev, req);
 
-	for (; ; bytes -= buf_len, ++len) {
-		if (ep->in)
-			td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes);
-		else
-			td->status = PCH_UDC_BS_HST_BSY;
+	if (req->dma == DMA_ADDR_INVALID)
+		td->dataptr = req->req.dma;
+	else
+		td->dataptr = req->dma;
 
+	td->status = PCH_UDC_BS_HST_BSY;
+	for (; ; bytes -= buf_len, ++len) {
+		td->status = PCH_UDC_BS_HST_BSY | min(buf_len, bytes);
 		if (bytes <= buf_len)
 			break;
-
 		last = td;
 		td = pci_pool_alloc(ep->dev->data_requests, gfp_flags,
 				    &dma_addr);
 		if (!td)
 			goto nomem;
-
 		i += buf_len;
-		td->dataptr = req->req.dma + i;
+		td->dataptr = req->td_data->dataptr + i;
 		last->next = dma_addr;
 	}
 
@@ -1352,28 +1363,15 @@ static int prepare_dma(struct pch_udc_ep *ep, struct pch_udc_request *req,
 {
 	int	retval;
 
-	req->td_data->dataptr = req->req.dma;
-	req->td_data->status |= PCH_UDC_DMA_LAST;
 	/* Allocate and create a DMA chain */
 	retval = pch_udc_create_dma_chain(ep, req, ep->ep.maxpacket, gfp);
 	if (retval) {
-		pr_err("%s: could not create DMA chain: %d\n",
-		       __func__, retval);
+		pr_err("%s: could not create DMA chain:%d\n", __func__, retval);
 		return retval;
 	}
-	if (!ep->in)
-		return 0;
-	if (req->req.length <= ep->ep.maxpacket)
-		req->td_data->status = PCH_UDC_DMA_LAST | PCH_UDC_BS_HST_BSY |
-				       req->req.length;
-	/* if bytes < max packet then tx bytes must
-	 * be written in packet per buffer mode
-	 */
-	if ((req->req.length < ep->ep.maxpacket) || !ep->num)
+	if (ep->in)
 		req->td_data->status = (req->td_data->status &
-					~PCH_UDC_RXTX_BYTES) | req->req.length;
-	req->td_data->status = (req->td_data->status &
-				~PCH_UDC_BUFF_STS) | PCH_UDC_BS_HST_BSY;
+				~PCH_UDC_BUFF_STS) | PCH_UDC_BS_HST_RDY;
 	return 0;
 }
 
@@ -1529,6 +1527,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep,
 	if (!req)
 		return NULL;
 	req->req.dma = DMA_ADDR_INVALID;
+	req->dma = DMA_ADDR_INVALID;
 	INIT_LIST_HEAD(&req->queue);
 	if (!ep->dev->dma_addr)
 		return &req->req;
@@ -1613,16 +1612,33 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
 	/* map the buffer for dma */
 	if (usbreq->length &&
 	    ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
-		if (ep->in)
-			usbreq->dma = dma_map_single(&dev->pdev->dev,
-						     usbreq->buf,
-						     usbreq->length,
-						     DMA_TO_DEVICE);
-		else
-			usbreq->dma = dma_map_single(&dev->pdev->dev,
-						     usbreq->buf,
-						     usbreq->length,
-						     DMA_FROM_DEVICE);
+		if (!((unsigned long)(usbreq->buf) & 0x03)) {
+			if (ep->in)
+				usbreq->dma = dma_map_single(&dev->pdev->dev,
+							     usbreq->buf,
+							     usbreq->length,
+							     DMA_TO_DEVICE);
+			else
+				usbreq->dma = dma_map_single(&dev->pdev->dev,
+							     usbreq->buf,
+							     usbreq->length,
+							     DMA_FROM_DEVICE);
+		} else {
+			req->buf = kzalloc(usbreq->length, GFP_ATOMIC);
+			if (!req->buf)
+				return -ENOMEM;
+			if (ep->in) {
+				memcpy(req->buf, usbreq->buf, usbreq->length);
+				req->dma = dma_map_single(&dev->pdev->dev,
+							  req->buf,
+							  usbreq->length,
+							  DMA_TO_DEVICE);
+			} else
+				req->dma = dma_map_single(&dev->pdev->dev,
+							  req->buf,
+							  usbreq->length,
+							  DMA_FROM_DEVICE);
+		}
 		req->dma_mapped = 1;
 	}
 	if (usbreq->length > 0) {
@@ -1920,32 +1936,46 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep)
 	struct pch_udc_request *req;
 	struct pch_udc_dev *dev = ep->dev;
 	unsigned int count;
+	struct pch_udc_data_dma_desc *td;
+	dma_addr_t addr;
 
 	if (list_empty(&ep->queue))
 		return;
-
 	/* next request */
 	req = list_entry(ep->queue.next, struct pch_udc_request, queue);
-	if ((req->td_data_last->status & PCH_UDC_BUFF_STS) !=
-	    PCH_UDC_BS_DMA_DONE)
-		return;
 	pch_udc_clear_dma(ep->dev, DMA_DIR_RX);
 	pch_udc_ep_set_ddptr(ep, 0);
-	if ((req->td_data_last->status & PCH_UDC_RXTX_STS) !=
-	    PCH_UDC_RTS_SUCC) {
-		dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) "
-			"epstatus=0x%08x\n",
-			(req->td_data_last->status & PCH_UDC_RXTX_STS),
-			(int)(ep->epsts));
-		return;
-	}
-	count = req->td_data_last->status & PCH_UDC_RXTX_BYTES;
+	if ((req->td_data_last->status & PCH_UDC_BUFF_STS) ==
+	    PCH_UDC_BS_DMA_DONE)
+		td = req->td_data_last;
+	else
+		td = req->td_data;
 
+	while (1) {
+		if ((td->status & PCH_UDC_RXTX_STS) != PCH_UDC_RTS_SUCC) {
+			dev_err(&dev->pdev->dev, "Invalid RXTX status=0x%08x "
+				"epstatus=0x%08x\n",
+				(req->td_data->status & PCH_UDC_RXTX_STS),
+				(int)(ep->epsts));
+			return;
+		}
+		if ((td->status & PCH_UDC_BUFF_STS) == PCH_UDC_BS_DMA_DONE)
+			if (td->status | PCH_UDC_DMA_LAST) {
+				count = td->status & PCH_UDC_RXTX_BYTES;
+				break;
+			}
+		if (td == req->td_data_last) {
+			dev_err(&dev->pdev->dev, "Not complete RX descriptor");
+			return;
+		}
+		addr = (dma_addr_t)td->next;
+		td = phys_to_virt(addr);
+	}
 	/* on 64k packets the RXBYTES field is zero */
 	if (!count && (req->req.length == UDC_DMA_MAXPACKET))
 		count = UDC_DMA_MAXPACKET;
 	req->td_data->status |= PCH_UDC_DMA_LAST;
-	req->td_data_last->status |= PCH_UDC_BS_HST_BSY;
+	td->status |= PCH_UDC_BS_HST_BSY;
 
 	req->dma_going = 0;
 	req->req.actual = count;
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index c244895..6d8b040 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -902,7 +902,7 @@ static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
 	int pwr_reg;
 	int ep0csr;
 	int i;
-	u32 idx;
+	u32 idx, idx2;
 	unsigned long flags;
 
 	spin_lock_irqsave(&dev->lock, flags);
@@ -1017,6 +1017,20 @@ static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
 		}
 	}
 
+	/* what else causes this interrupt? a receive! who is it? */
+	if (!usb_status && !usbd_status && !pwr_reg && !ep0csr) {
+		for (i = 1; i < S3C2410_ENDPOINTS; i++) {
+			idx2 = udc_read(S3C2410_UDC_INDEX_REG);
+			udc_write(i, S3C2410_UDC_INDEX_REG);
+
+			if (udc_read(S3C2410_UDC_OUT_CSR1_REG) & 0x1)
+				s3c2410_udc_handle_ep(&dev->ep[i]);
+
+			/* restore index */
+			udc_write(idx2, S3C2410_UDC_INDEX_REG);
+		}
+	}
+
 	dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
 
 	/* Restore old index */
@@ -1467,7 +1481,9 @@ static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on)
 {
 	dprintk(DEBUG_NORMAL, "%s()\n", __func__);
 
-	if (udc_info && udc_info->udc_command) {
+	if (udc_info && (udc_info->udc_command ||
+		gpio_is_valid(udc_info->pullup_pin))) {
+
 		if (is_on)
 			s3c2410_udc_enable(udc);
 		else {
@@ -1544,6 +1560,32 @@ static const struct usb_gadget_ops s3c2410_ops = {
 	.vbus_draw		= s3c2410_vbus_draw,
 };
 
+static void s3c2410_udc_command(enum s3c2410_udc_cmd_e cmd)
+{
+	if (!udc_info)
+		return;
+
+	if (udc_info->udc_command) {
+		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+	} else if (gpio_is_valid(udc_info->pullup_pin)) {
+		int value;
+
+		switch (cmd) {
+		case S3C2410_UDC_P_ENABLE:
+			value = 1;
+			break;
+		case S3C2410_UDC_P_DISABLE:
+			value = 0;
+			break;
+		default:
+			return;
+		}
+		value ^= udc_info->pullup_pin_inverted;
+
+		gpio_set_value(udc_info->pullup_pin, value);
+	}
+}
+
 /*------------------------- gadget driver handling---------------------------*/
 /*
  * s3c2410_udc_disable
@@ -1565,8 +1607,7 @@ static void s3c2410_udc_disable(struct s3c2410_udc *dev)
 	udc_write(0x1F, S3C2410_UDC_EP_INT_REG);
 
 	/* Good bye, cruel world */
-	if (udc_info && udc_info->udc_command)
-		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+	s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
 
 	/* Set speed to unknown */
 	dev->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1627,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
 	udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG);
 
 	/* time to say "hello, world" */
-	if (udc_info && udc_info->udc_command)
-		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
 }
 
 /*
@@ -1903,6 +1943,17 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 		udc->vbus = 1;
 	}
 
+	if (udc_info && !udc_info->udc_command &&
+		gpio_is_valid(udc_info->pullup_pin)) {
+
+		retval = gpio_request_one(udc_info->pullup_pin,
+				udc_info->vbus_pin_inverted ?
+				GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW,
+				"udc pullup");
+		if (retval)
+			goto err_vbus_irq;
+	}
+
 	if (s3c2410_udc_debugfs_root) {
 		udc->regs_info = debugfs_create_file("registers", S_IRUGO,
 				s3c2410_udc_debugfs_root,
@@ -1915,6 +1966,9 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
 
 	return 0;
 
+err_vbus_irq:
+	if (udc_info && udc_info->vbus_pin > 0)
+		free_irq(gpio_to_irq(udc_info->vbus_pin), udc);
 err_gpio_claim:
 	if (udc_info && udc_info->vbus_pin > 0)
 		gpio_free(udc_info->vbus_pin);
@@ -1942,6 +1996,10 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 
 	debugfs_remove(udc->regs_info);
 
+	if (udc_info && !udc_info->udc_command &&
+		gpio_is_valid(udc_info->pullup_pin))
+		gpio_free(udc_info->pullup_pin);
+
 	if (udc_info && udc_info->vbus_pin > 0) {
 		irq = gpio_to_irq(udc_info->vbus_pin);
 		free_irq(irq, udc);
@@ -1973,16 +2031,14 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message)
 {
-	if (udc_info && udc_info->udc_command)
-		udc_info->udc_command(S3C2410_UDC_P_DISABLE);
+	s3c2410_udc_command(S3C2410_UDC_P_DISABLE);
 
 	return 0;
 }
 
 static int s3c2410_udc_resume(struct platform_device *pdev)
 {
-	if (udc_info && udc_info->udc_command)
-		udc_info->udc_command(S3C2410_UDC_P_ENABLE);
+	s3c2410_udc_command(S3C2410_UDC_P_ENABLE);
 
 	return 0;
 }
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index 1eda968..2ac1d21 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -241,7 +241,7 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
 	size -= size % out->maxpacket;
 
 	if (dev->port_usb->is_fixed)
-		size = max(size, dev->port_usb->fixed_out_len);
+		size = max_t(size_t, size, dev->port_usb->fixed_out_len);
 
 	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
 	if (skb == NULL) {
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 0e6afa2..9483acd 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -91,17 +91,28 @@ config USB_EHCI_TT_NEWSCHED
 
 	  If unsure, say Y.
 
+config USB_EHCI_HCD_PMC_MSP
+	tristate "EHCI support for on-chip PMC MSP71xx USB controller"
+	depends on USB_EHCI_HCD && MSP_HAS_USB
+	default n
+	select USB_EHCI_BIG_ENDIAN_DESC
+	select USB_EHCI_BIG_ENDIAN_MMIO
+	---help---
+		Enables support for the onchip USB controller on the PMC_MSP7100 Family SoC's.
+		If unsure, say N.
+
 config USB_EHCI_BIG_ENDIAN_MMIO
 	bool
 	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
 				    ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
-				    PPC_MPC512x || CPU_CAVIUM_OCTEON)
+				    PPC_MPC512x || CPU_CAVIUM_OCTEON || \
+				    PMC_MSP)
 	default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
 	bool
 	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
-				    PPC_MPC512x)
+				    PPC_MPC512x || PMC_MSP)
 	default y
 
 config XPS_USB_HCD_XILINX
@@ -145,7 +156,7 @@ config USB_EHCI_MSM
 	bool "Support for MSM on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && ARCH_MSM
 	select USB_EHCI_ROOT_HUB_TT
-	select USB_MSM_OTG_72K
+	select USB_MSM_OTG
 	---help---
 	  Enables support for the USB Host controller present on the
 	  Qualcomm chipsets. Root Hub has inbuilt TT.
@@ -154,6 +165,14 @@ config USB_EHCI_MSM
 	  This driver is not supported on boards like trout which
 	  has an external PHY.
 
+config USB_EHCI_TEGRA
+       boolean "NVIDIA Tegra HCD support"
+       depends on USB_EHCI_HCD && ARCH_TEGRA
+       select USB_EHCI_ROOT_HUB_TT
+       help
+         This driver enables support for the internal USB Host Controllers
+         found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
+
 config USB_EHCI_HCD_PPC_OF
 	bool "EHCI support for PPC USB controller on OF platform bus"
 	depends on USB_EHCI_HCD && PPC_OF
@@ -162,6 +181,13 @@ config USB_EHCI_HCD_PPC_OF
 	  Enables support for the USB controller present on the PowerPC
 	  OpenFirmware platform bus.
 
+config USB_EHCI_SH
+	bool "EHCI support for SuperH USB controller"
+	depends on USB_EHCI_HCD && SUPERH
+	---help---
+	  Enables support for the on-chip EHCI controller on the SuperH.
+	  If you use the PCI EHCI controller, this option is not necessary.
+
 config USB_W90X900_EHCI
 	bool "W90X900(W90P910) EHCI support"
 	depends on USB_EHCI_HCD && ARCH_W90X900
@@ -315,6 +341,13 @@ config USB_OHCI_HCD_SSB
 
 	  If unsure, say N.
 
+config USB_OHCI_SH
+	bool "OHCI support for SuperH USB controller"
+	depends on USB_OHCI_HCD && SUPERH
+	---help---
+	  Enables support for the on-chip OHCI controller on the SuperH.
+	  If you use the PCI OHCI controller, this option is not necessary.
+
 config USB_CNS3XXX_OHCI
 	bool "Cavium CNS3XXX OHCI Module"
 	depends on USB_OHCI_HCD && ARCH_CNS3XXX
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index d6a69d5..b2ed55c 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -115,7 +115,7 @@ static const struct hc_driver ehci_atmel_hc_driver = {
 	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
 };
 
-static int __init ehci_atmel_drv_probe(struct platform_device *pdev)
+static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd;
 	const struct hc_driver *driver = &ehci_atmel_hc_driver;
@@ -207,7 +207,7 @@ fail_create_hcd:
 	return retval;
 }
 
-static int __exit ehci_atmel_drv_remove(struct platform_device *pdev)
+static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev)
 {
 	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
@@ -227,7 +227,7 @@ static int __exit ehci_atmel_drv_remove(struct platform_device *pdev)
 
 static struct platform_driver ehci_atmel_driver = {
 	.probe		= ehci_atmel_drv_probe,
-	.remove		= __exit_p(ehci_atmel_drv_remove),
+	.remove		= __devexit_p(ehci_atmel_drv_remove),
 	.shutdown	= usb_hcd_platform_shutdown,
 	.driver.name	= "atmel-ehci",
 };
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 3be238a..693c29b 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -28,11 +28,9 @@
 	dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
 
 #ifdef VERBOSE_DEBUG
-#	define vdbg dbg
 #	define ehci_vdbg ehci_dbg
 #else
-#	define vdbg(fmt,args...) do { } while (0)
-#	define ehci_vdbg(ehci, fmt, args...) do { } while (0)
+	static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {}
 #endif
 
 #ifdef	DEBUG
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 74dcf49..78561d1 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -114,13 +114,11 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n");
 
 #define	INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
-/* for ASPM quirk of ISOC on AMD SB800 */
-static struct pci_dev *amd_nb_dev;
-
 /*-------------------------------------------------------------------------*/
 
 #include "ehci.h"
 #include "ehci-dbg.c"
+#include "pci-quirks.h"
 
 /*-------------------------------------------------------------------------*/
 
@@ -532,10 +530,8 @@ static void ehci_stop (struct usb_hcd *hcd)
 	spin_unlock_irq (&ehci->lock);
 	ehci_mem_cleanup (ehci);
 
-	if (amd_nb_dev) {
-		pci_dev_put(amd_nb_dev);
-		amd_nb_dev = NULL;
-	}
+	if (ehci->amd_pll_fix == 1)
+		usb_amd_dev_put();
 
 #ifdef	EHCI_STATS
 	ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
@@ -679,7 +675,12 @@ static int ehci_run (struct usb_hcd *hcd)
 	hcd->uses_new_polling = 1;
 
 	/* EHCI spec section 4.1 */
-	if ((retval = ehci_reset(ehci)) != 0) {
+	/*
+	 * TDI driver does the ehci_reset in their reset callback.
+	 * Don't reset here, because configuration settings will
+	 * vanish.
+	 */
+	if (!ehci_is_TDI(ehci) && (retval = ehci_reset(ehci)) != 0) {
 		ehci_mem_cleanup(ehci);
 		return retval;
 	}
@@ -1179,7 +1180,7 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_mxc_driver
 #endif
 
-#ifdef CONFIG_CPU_SUBTYPE_SH7786
+#ifdef CONFIG_USB_EHCI_SH
 #include "ehci-sh.c"
 #define PLATFORM_DRIVER		ehci_hcd_sh_driver
 #endif
@@ -1254,6 +1255,16 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ehci_msm_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_HCD_PMC_MSP
+#include "ehci-pmcmsp.c"
+#define	PLATFORM_DRIVER		ehci_hcd_msp_driver
+#endif
+
+#ifdef CONFIG_USB_EHCI_TEGRA
+#include "ehci-tegra.c"
+#define PLATFORM_DRIVER		tegra_ehci_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
@@ -1306,24 +1317,24 @@ static int __init ehci_hcd_init(void)
 #endif
 
 #ifdef OF_PLATFORM_DRIVER
-	retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+	retval = platform_driver_register(&OF_PLATFORM_DRIVER);
 	if (retval < 0)
 		goto clean3;
 #endif
 
 #ifdef XILINX_OF_PLATFORM_DRIVER
-	retval = of_register_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+	retval = platform_driver_register(&XILINX_OF_PLATFORM_DRIVER);
 	if (retval < 0)
 		goto clean4;
 #endif
 	return retval;
 
 #ifdef XILINX_OF_PLATFORM_DRIVER
-	/* of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER); */
+	/* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */
 clean4:
 #endif
 #ifdef OF_PLATFORM_DRIVER
-	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+	platform_driver_unregister(&OF_PLATFORM_DRIVER);
 clean3:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
@@ -1351,10 +1362,10 @@ module_init(ehci_hcd_init);
 static void __exit ehci_hcd_cleanup(void)
 {
 #ifdef XILINX_OF_PLATFORM_DRIVER
-	of_unregister_platform_driver(&XILINX_OF_PLATFORM_DRIVER);
+	platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER);
 #endif
 #ifdef OF_PLATFORM_DRIVER
-	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+	platform_driver_unregister(&OF_PLATFORM_DRIVER);
 #endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 8a515f0..d05ea03 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -106,6 +106,27 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
 	ehci->owned_ports = 0;
 }
 
+static int ehci_port_change(struct ehci_hcd *ehci)
+{
+	int i = HCS_N_PORTS(ehci->hcs_params);
+
+	/* First check if the controller indicates a change event */
+
+	if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)
+		return 1;
+
+	/*
+	 * Not all controllers appear to update this while going from D3 to D0,
+	 * so check the individual port status registers as well
+	 */
+
+	while (i--)
+		if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC)
+			return 1;
+
+	return 0;
+}
+
 static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 		bool suspending, bool do_wakeup)
 {
@@ -173,7 +194,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
 	}
 
 	/* Does the root hub have a port wakeup pending? */
-	if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
+	if (!suspending && ehci_port_change(ehci))
 		usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
 
 	spin_unlock_irqrestore(&ehci->lock, flags);
@@ -538,14 +559,15 @@ static ssize_t store_companion(struct device *dev,
 }
 static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
 
-static inline void create_companion_file(struct ehci_hcd *ehci)
+static inline int create_companion_file(struct ehci_hcd *ehci)
 {
-	int	i;
+	int	i = 0;
 
 	/* with integrated TT there is no companion! */
 	if (!ehci_is_TDI(ehci))
 		i = device_create_file(ehci_to_hcd(ehci)->self.controller,
 				       &dev_attr_companion);
+	return i;
 }
 
 static inline void remove_companion_file(struct ehci_hcd *ehci)
@@ -695,8 +717,8 @@ ehci_hub_descriptor (
 	desc->bDescLength = 7 + 2 * temp;
 
 	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset (&desc->bitmap [0], 0, temp);
-	memset (&desc->bitmap [temp], 0xff, temp);
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
 
 	temp = 0x0008;			/* per-port overcurrent reporting */
 	if (HCS_PPC (ehci->hcs_params))
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
index b4d4d63..2111627 100644
--- a/drivers/usb/host/ehci-lpm.c
+++ b/drivers/usb/host/ehci-lpm.c
@@ -17,7 +17,8 @@
 */
 
 /* this file is part of ehci-hcd.c */
-static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
+static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
+	int dev_addr, int port_num)
 {
 	u32 __iomem portsc;
 
@@ -37,7 +38,7 @@ static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num)
  * this function is used to check if the device support LPM
  * if yes, mark the PORTSC register with PORT_LPM bit
  */
-static int ehci_lpm_check(struct ehci_hcd *ehci, int port)
+static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
 {
 	u32 __iomem	*portsc ;
 	u32 val32;
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 413f4de..9ce1b0b 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -1,6 +1,6 @@
 /* ehci-msm.c - HSUSB Host Controller Driver Implementation
  *
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  *
  * Partly derived from ehci-fsl.c and ehci-hcd.c
  * Copyright (c) 2000-2004 by David Brownell
@@ -34,92 +34,6 @@
 
 static struct otg_transceiver *otg;
 
-/*
- * ehci_run defined in drivers/usb/host/ehci-hcd.c reset the controller and
- * the configuration settings in ehci_msm_reset vanish after controller is
- * reset. Resetting the controler in ehci_run seems to be un-necessary
- * provided HCD reset the controller before calling ehci_run. Most of the HCD
- * do but some are not. So this function is same as ehci_run but we don't
- * reset the controller here.
- */
-static int ehci_msm_run(struct usb_hcd *hcd)
-{
-	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
-	u32			temp;
-	u32			hcc_params;
-
-	hcd->uses_new_polling = 1;
-
-	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
-	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
-
-	/*
-	 * hcc_params controls whether ehci->regs->segment must (!!!)
-	 * be used; it constrains QH/ITD/SITD and QTD locations.
-	 * pci_pool consistent memory always uses segment zero.
-	 * streaming mappings for I/O buffers, like pci_map_single(),
-	 * can return segments above 4GB, if the device allows.
-	 *
-	 * NOTE:  the dma mask is visible through dma_supported(), so
-	 * drivers can pass this info along ... like NETIF_F_HIGHDMA,
-	 * Scsi_Host.highmem_io, and so forth.  It's readonly to all
-	 * host side drivers though.
-	 */
-	hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
-	if (HCC_64BIT_ADDR(hcc_params))
-		ehci_writel(ehci, 0, &ehci->regs->segment);
-
-	/*
-	 * Philips, Intel, and maybe others need CMD_RUN before the
-	 * root hub will detect new devices (why?); NEC doesn't
-	 */
-	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
-	ehci->command |= CMD_RUN;
-	ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	dbg_cmd(ehci, "init", ehci->command);
-
-	/*
-	 * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
-	 * are explicitly handed to companion controller(s), so no TT is
-	 * involved with the root hub.  (Except where one is integrated,
-	 * and there's no companion controller unless maybe for USB OTG.)
-	 *
-	 * Turning on the CF flag will transfer ownership of all ports
-	 * from the companions to the EHCI controller.  If any of the
-	 * companions are in the middle of a port reset at the time, it
-	 * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
-	 * guarantees that no resets are in progress.  After we set CF,
-	 * a short delay lets the hardware catch up; new resets shouldn't
-	 * be started before the port switching actions could complete.
-	 */
-	down_write(&ehci_cf_port_reset_rwsem);
-	hcd->state = HC_STATE_RUNNING;
-	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
-	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */
-	usleep_range(5000, 5500);
-	up_write(&ehci_cf_port_reset_rwsem);
-	ehci->last_periodic_enable = ktime_get_real();
-
-	temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
-	ehci_info(ehci,
-		"USB %x.%x started, EHCI %x.%02x%s\n",
-		((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
-		temp >> 8, temp & 0xff,
-		ignore_oc ? ", overcurrent ignored" : "");
-
-	ehci_writel(ehci, INTR_MASK,
-		    &ehci->regs->intr_enable); /* Turn On Interrupts */
-
-	/* GRR this is run-once init(), being done every time the HC starts.
-	 * So long as they're part of class devices, we can't do it init()
-	 * since the class device isn't created that early.
-	 */
-	create_debug_files(ehci);
-	create_companion_file(ehci);
-
-	return 0;
-}
-
 static int ehci_msm_reset(struct usb_hcd *hcd)
 {
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
@@ -128,6 +42,8 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	ehci->caps = USB_CAPLENGTH;
 	ehci->regs = USB_CAPLENGTH +
 		HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
 
 	/* cache the data to minimize the chip reads*/
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
@@ -135,6 +51,10 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
 	hcd->has_tt = 1;
 	ehci->sbrn = HCD_USB2;
 
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
 	/* data structure init */
 	retval = ehci_init(hcd);
 	if (retval)
@@ -167,7 +87,7 @@ static struct hc_driver msm_hc_driver = {
 	.flags			= HCD_USB2 | HCD_MEMORY,
 
 	.reset			= ehci_msm_reset,
-	.start			= ehci_msm_run,
+	.start			= ehci_run,
 
 	.stop			= ehci_stop,
 	.shutdown		= ehci_shutdown,
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index c8e360d..25c8c10 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -203,11 +203,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
 		mdelay(10);
 	}
 
-	/* setup specific usb hw */
-	ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
-	if (ret < 0)
-		goto err_init;
-
 	ehci = hcd_to_ehci(hcd);
 
 	/* EHCI registers start at offset 0x100 */
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index f784ceb..7e41a95 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -4,9 +4,10 @@
  * Bus Glue for the EHCI controllers in OMAP3/4
  * Tested on several OMAP3 boards, and OMAP4 Pandaboard
  *
- * Copyright (C) 2007-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
  *	Author: Vikram Pandita <vikram.pandita@ti.com>
  *	Author: Anand Gadiyar <gadiyar@ti.com>
+ *	Author: Keshava Munegowda <keshava_mgowda@ti.com>
  *
  * Copyright (C) 2009 Nokia Corporation
  *	Contact: Felipe Balbi <felipe.balbi@nokia.com>
@@ -27,116 +28,19 @@
  * 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 Nov 21, 2010):
+ * TODO (last updated Feb 27, 2010):
  *	- add kernel-doc
  *	- enable AUTOIDLE
  *	- add suspend/resume
- *	- move workarounds to board-files
- *	- factor out code common to OHCI
  *	- add HSIC and TLL support
  *	- convert to use hwmod and runtime PM
  */
 
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
 #include <plat/usb.h>
 
-/*
- * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
- *	Use ehci_omap_readl()/ehci_omap_writel() functions
- */
-
-/* TLL Register Set */
-#define	OMAP_USBTLL_REVISION				(0x00)
-#define	OMAP_USBTLL_SYSCONFIG				(0x10)
-#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_USBTLL_SYSSTATUS				(0x14)
-#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
-
-#define	OMAP_USBTLL_IRQSTATUS				(0x18)
-#define	OMAP_USBTLL_IRQENABLE				(0x1C)
-
-#define	OMAP_TLL_SHARED_CONF				(0x30)
-#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
-#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
-#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
-#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
-#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
-
-#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
-#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
-#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
-#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
-#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
-#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
-
-#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
-#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
-#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
-#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
-#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
-
-#define OMAP_TLL_CHANNEL_COUNT				3
-#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
-#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
-#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
-
-/* UHH Register Set */
-#define	OMAP_UHH_REVISION				(0x00)
-#define	OMAP_UHH_SYSCONFIG				(0x10)
-#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
-#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_UHH_SYSSTATUS				(0x14)
-#define	OMAP_UHH_HOSTCONFIG				(0x40)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
-#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
-#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
-#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
-#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
-#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
-#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
-#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
-
-/* OMAP4-specific defines */
-#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR		(3 << 2)
-#define OMAP4_UHH_SYSCONFIG_NOIDLE			(1 << 2)
-
-#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR		(3 << 4)
-#define OMAP4_UHH_SYSCONFIG_NOSTDBY			(1 << 4)
-#define OMAP4_UHH_SYSCONFIG_SOFTRESET			(1 << 0)
-
-#define OMAP4_P1_MODE_CLEAR				(3 << 16)
-#define OMAP4_P1_MODE_TLL				(1 << 16)
-#define OMAP4_P1_MODE_HSIC				(3 << 16)
-#define OMAP4_P2_MODE_CLEAR				(3 << 18)
-#define OMAP4_P2_MODE_TLL				(1 << 18)
-#define OMAP4_P2_MODE_HSIC				(3 << 18)
-
-#define OMAP_REV2_TLL_CHANNEL_COUNT			2
-
-#define	OMAP_UHH_DEBUG_CSR				(0x44)
-
 /* EHCI Register Set */
 #define EHCI_INSNREG04					(0xA0)
 #define EHCI_INSNREG04_DISABLE_UNSUSPEND		(1 << 5)
@@ -148,137 +52,24 @@
 #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
 #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
 
-/* Values of UHH_REVISION - Note: these are not given in the TRM */
-#define OMAP_EHCI_REV1	0x00000010	/* OMAP3 */
-#define OMAP_EHCI_REV2	0x50700100	/* OMAP4 */
-
-#define is_omap_ehci_rev1(x)	(x->omap_ehci_rev == OMAP_EHCI_REV1)
-#define is_omap_ehci_rev2(x)	(x->omap_ehci_rev == OMAP_EHCI_REV2)
+/*-------------------------------------------------------------------------*/
 
-#define is_ehci_phy_mode(x)	(x == EHCI_HCD_OMAP_MODE_PHY)
-#define is_ehci_tll_mode(x)	(x == EHCI_HCD_OMAP_MODE_TLL)
-#define is_ehci_hsic_mode(x)	(x == EHCI_HCD_OMAP_MODE_HSIC)
+static const struct hc_driver ehci_omap_hc_driver;
 
-/*-------------------------------------------------------------------------*/
 
-static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val)
+static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
 {
 	__raw_writel(val, base + reg);
 }
 
-static inline u32 ehci_omap_readl(void __iomem *base, u32 reg)
+static inline u32 ehci_read(void __iomem *base, u32 reg)
 {
 	return __raw_readl(base + reg);
 }
 
-static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val)
-{
-	__raw_writeb(val, base + reg);
-}
-
-static inline u8 ehci_omap_readb(void __iomem *base, u8 reg)
-{
-	return __raw_readb(base + reg);
-}
-
-/*-------------------------------------------------------------------------*/
-
-struct ehci_hcd_omap {
-	struct ehci_hcd		*ehci;
-	struct device		*dev;
-
-	struct clk		*usbhost_ick;
-	struct clk		*usbhost_hs_fck;
-	struct clk		*usbhost_fs_fck;
-	struct clk		*usbtll_fck;
-	struct clk		*usbtll_ick;
-	struct clk		*xclk60mhsp1_ck;
-	struct clk		*xclk60mhsp2_ck;
-	struct clk		*utmi_p1_fck;
-	struct clk		*utmi_p2_fck;
-
-	/* FIXME the following two workarounds are
-	 * board specific not silicon-specific so these
-	 * should be moved to board-file instead.
-	 *
-	 * Maybe someone from TI will know better which
-	 * board is affected and needs the workarounds
-	 * to be applied
-	 */
-
-	/* gpio for resetting phy */
-	int			reset_gpio_port[OMAP3_HS_USB_PORTS];
-
-	/* phy reset workaround */
-	int			phy_reset;
-
-	/* IP revision */
-	u32			omap_ehci_rev;
-
-	/* desired phy_mode: TLL, PHY */
-	enum ehci_hcd_omap_mode	port_mode[OMAP3_HS_USB_PORTS];
-
-	void __iomem		*uhh_base;
-	void __iomem		*tll_base;
-	void __iomem		*ehci_base;
-
-	/* Regulators for USB PHYs.
-	 * Each PHY can have a separate regulator.
-	 */
-	struct regulator        *regulator[OMAP3_HS_USB_PORTS];
-};
-
-/*-------------------------------------------------------------------------*/
-
-static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask,
-				u8 tll_channel_count)
-{
-	unsigned reg;
-	int i;
-
-	/* Program the 3 TLL channels upfront */
-	for (i = 0; i < tll_channel_count; i++) {
-		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
-
-		/* Disable AutoIdle, BitStuffing and use SDR Mode */
-		reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
-				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
-				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
-		ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
-	}
-
-	/* Program Common TLL register */
-	reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF);
-	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
-			| OMAP_TLL_SHARED_CONF_USB_DIVRATION
-			| OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN);
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
-
-	ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
-
-	/* Enable channels now */
-	for (i = 0; i < tll_channel_count; i++) {
-		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
-
-		/* Enable only the reg that is needed */
-		if (!(tll_channel_mask & 1<<i))
-			continue;
-
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
-		ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
-
-		ehci_omap_writeb(omap->tll_base,
-				OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
-		dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n",
-				i+1, ehci_omap_readb(omap->tll_base,
-				OMAP_TLL_ULPI_SCRATCH_REGISTER(i)));
-	}
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
+static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
 {
+	struct usb_hcd	*hcd = dev_get_drvdata(&pdev->dev);
 	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 	unsigned reg = 0;
 
@@ -292,266 +83,87 @@ static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
 		/* start ULPI access*/
 		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
 
-	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg);
+	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
 
 	/* Wait for ULPI access completion */
-	while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI)
+	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
 			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
 		cpu_relax();
 
 		if (time_after(jiffies, timeout)) {
-			dev_dbg(omap->dev, "phy reset operation timed out\n");
+			dev_dbg(&pdev->dev, "phy reset operation timed out\n");
 			break;
 		}
 	}
 }
 
-/* omap_start_ehc
- *	- Start the TI USBHOST controller
- */
-static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-	u8 tll_ch_mask = 0;
-	unsigned reg = 0;
-	int ret = 0;
-
-	dev_dbg(omap->dev, "starting TI EHCI USB Controller\n");
 
-	/* Enable Clocks for USBHOST */
-	omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick");
-	if (IS_ERR(omap->usbhost_ick)) {
-		ret =  PTR_ERR(omap->usbhost_ick);
-		goto err_host_ick;
-	}
-	clk_enable(omap->usbhost_ick);
-
-	omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck");
-	if (IS_ERR(omap->usbhost_hs_fck)) {
-		ret = PTR_ERR(omap->usbhost_hs_fck);
-		goto err_host_120m_fck;
-	}
-	clk_enable(omap->usbhost_hs_fck);
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
 
-	omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck");
-	if (IS_ERR(omap->usbhost_fs_fck)) {
-		ret = PTR_ERR(omap->usbhost_fs_fck);
-		goto err_host_48m_fck;
-	}
-	clk_enable(omap->usbhost_fs_fck);
-
-	if (omap->phy_reset) {
-		/* Refer: ISSUE1 */
-		if (gpio_is_valid(omap->reset_gpio_port[0])) {
-			gpio_request(omap->reset_gpio_port[0],
-						"USB1 PHY reset");
-			gpio_direction_output(omap->reset_gpio_port[0], 0);
-		}
+/**
+ * ehci_hcd_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ */
+static int ehci_hcd_omap_probe(struct platform_device *pdev)
+{
+	struct device				*dev = &pdev->dev;
+	struct ehci_hcd_omap_platform_data	*pdata = dev->platform_data;
+	struct resource				*res;
+	struct usb_hcd				*hcd;
+	void __iomem				*regs;
+	struct ehci_hcd				*omap_ehci;
+	int					ret = -ENODEV;
+	int					irq;
 
-		if (gpio_is_valid(omap->reset_gpio_port[1])) {
-			gpio_request(omap->reset_gpio_port[1],
-						"USB2 PHY reset");
-			gpio_direction_output(omap->reset_gpio_port[1], 0);
-		}
+	if (usb_disabled())
+		return -ENODEV;
 
-		/* Hold the PHY in RESET for enough time till DIR is high */
-		udelay(10);
+	if (!dev->parent) {
+		dev_err(dev, "Missing parent device\n");
+		return -ENODEV;
 	}
 
-	/* Configure TLL for 60Mhz clk for ULPI */
-	omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
-	if (IS_ERR(omap->usbtll_fck)) {
-		ret = PTR_ERR(omap->usbtll_fck);
-		goto err_tll_fck;
+	irq = platform_get_irq_byname(pdev, "ehci-irq");
+	if (irq < 0) {
+		dev_err(dev, "EHCI irq failed\n");
+		return -ENODEV;
 	}
-	clk_enable(omap->usbtll_fck);
 
-	omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick");
-	if (IS_ERR(omap->usbtll_ick)) {
-		ret = PTR_ERR(omap->usbtll_ick);
-		goto err_tll_ick;
+	res =  platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "ehci");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		return -ENODEV;
 	}
-	clk_enable(omap->usbtll_ick);
-
-	omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base,
-						OMAP_UHH_REVISION);
-	dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n",
-					omap->omap_ehci_rev);
 
-	/*
-	 * Enable per-port clocks as needed (newer controllers only).
-	 * - External ULPI clock for PHY mode
-	 * - Internal clocks for TLL and HSIC modes (TODO)
-	 */
-	if (is_omap_ehci_rev2(omap)) {
-		switch (omap->port_mode[0]) {
-		case EHCI_HCD_OMAP_MODE_PHY:
-			omap->xclk60mhsp1_ck = clk_get(omap->dev,
-							"xclk60mhsp1_ck");
-			if (IS_ERR(omap->xclk60mhsp1_ck)) {
-				ret = PTR_ERR(omap->xclk60mhsp1_ck);
-				dev_err(omap->dev,
-					"Unable to get Port1 ULPI clock\n");
-			}
-
-			omap->utmi_p1_fck = clk_get(omap->dev,
-							"utmi_p1_gfclk");
-			if (IS_ERR(omap->utmi_p1_fck)) {
-				ret = PTR_ERR(omap->utmi_p1_fck);
-				dev_err(omap->dev,
-					"Unable to get utmi_p1_fck\n");
-			}
-
-			ret = clk_set_parent(omap->utmi_p1_fck,
-						omap->xclk60mhsp1_ck);
-			if (ret != 0) {
-				dev_err(omap->dev,
-					"Unable to set P1 f-clock\n");
-			}
-			break;
-		case EHCI_HCD_OMAP_MODE_TLL:
-			/* TODO */
-		default:
-			break;
-		}
-		switch (omap->port_mode[1]) {
-		case EHCI_HCD_OMAP_MODE_PHY:
-			omap->xclk60mhsp2_ck = clk_get(omap->dev,
-							"xclk60mhsp2_ck");
-			if (IS_ERR(omap->xclk60mhsp2_ck)) {
-				ret = PTR_ERR(omap->xclk60mhsp2_ck);
-				dev_err(omap->dev,
-					"Unable to get Port2 ULPI clock\n");
-			}
-
-			omap->utmi_p2_fck = clk_get(omap->dev,
-							"utmi_p2_gfclk");
-			if (IS_ERR(omap->utmi_p2_fck)) {
-				ret = PTR_ERR(omap->utmi_p2_fck);
-				dev_err(omap->dev,
-					"Unable to get utmi_p2_fck\n");
-			}
-
-			ret = clk_set_parent(omap->utmi_p2_fck,
-						omap->xclk60mhsp2_ck);
-			if (ret != 0) {
-				dev_err(omap->dev,
-					"Unable to set P2 f-clock\n");
-			}
-			break;
-		case EHCI_HCD_OMAP_MODE_TLL:
-			/* TODO */
-		default:
-			break;
-		}
+	regs = ioremap(res->start, resource_size(res));
+	if (!regs) {
+		dev_err(dev, "UHH EHCI ioremap failed\n");
+		return -ENOMEM;
 	}
 
-
-	/* perform TLL soft reset, and wait until reset is complete */
-	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
-
-	/* Wait for TLL reset to complete */
-	while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			dev_dbg(omap->dev, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_sys_status;
-		}
+	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_dbg(omap->dev, "TLL RESET DONE\n");
-
-	/* (1<<3) = no idle mode only for initial debugging */
-	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
-			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
-			OMAP_USBTLL_SYSCONFIG_CACTIVITY);
-
-
-	/* Put UHH in NoIdle/NoStandby mode */
-	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
-	if (is_omap_ehci_rev1(omap)) {
-		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
-				| OMAP_UHH_SYSCONFIG_SIDLEMODE
-				| OMAP_UHH_SYSCONFIG_CACTIVITY
-				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
-		reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
-
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = regs;
 
-	} else if (is_omap_ehci_rev2(omap)) {
-		reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
-		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
-		reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
-		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
-	}
-	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
-
-	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
-
-	/* setup ULPI bypass and burst configurations */
-	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
-	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
-
-	if (is_omap_ehci_rev1(omap)) {
-		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-			reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-			reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
-			reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
-
-		/* Bypass the TLL module for PHY mode operation */
-		if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
-			dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
-			if (is_ehci_phy_mode(omap->port_mode[0]) ||
-				is_ehci_phy_mode(omap->port_mode[1]) ||
-					is_ehci_phy_mode(omap->port_mode[2]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-			else
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-		} else {
-			dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
-			if (is_ehci_phy_mode(omap->port_mode[0]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-			else if (is_ehci_tll_mode(omap->port_mode[0]))
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-
-			if (is_ehci_phy_mode(omap->port_mode[1]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-			else if (is_ehci_tll_mode(omap->port_mode[1]))
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-
-			if (is_ehci_phy_mode(omap->port_mode[2]))
-				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-			else if (is_ehci_tll_mode(omap->port_mode[2]))
-				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-		}
-	} else if (is_omap_ehci_rev2(omap)) {
-		/* Clear port mode fields for PHY mode*/
-		reg &= ~OMAP4_P1_MODE_CLEAR;
-		reg &= ~OMAP4_P2_MODE_CLEAR;
-
-		if (is_ehci_tll_mode(omap->port_mode[0]))
-			reg |= OMAP4_P1_MODE_TLL;
-		else if (is_ehci_hsic_mode(omap->port_mode[0]))
-			reg |= OMAP4_P1_MODE_HSIC;
-
-		if (is_ehci_tll_mode(omap->port_mode[1]))
-			reg |= OMAP4_P2_MODE_TLL;
-		else if (is_ehci_hsic_mode(omap->port_mode[1]))
-			reg |= OMAP4_P2_MODE_HSIC;
+	ret = omap_usbhs_enable(dev);
+	if (ret) {
+		dev_err(dev, "failed to start usbhs with err %d\n", ret);
+		goto err_enable;
 	}
 
-	ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
-	dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
-
-
 	/*
 	 * An undocumented "feature" in the OMAP3 EHCI controller,
 	 * causes suspended ports to be taken out of suspend when
@@ -561,363 +173,50 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 	 * to suspend. Writing 1 to this undocumented register bit
 	 * disables this feature and restores normal behavior.
 	 */
-	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04,
+	ehci_write(regs, EHCI_INSNREG04,
 				EHCI_INSNREG04_DISABLE_UNSUSPEND);
 
-	if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
-		(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
-			(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
-
-		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
-			tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK;
-		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
-			tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK;
-		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
-			tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;
-
-		/* Enable UTMI mode for required TLL channels */
-		omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT);
-	}
-
-	if (omap->phy_reset) {
-		/* Refer ISSUE1:
-		 * Hold the PHY in RESET for enough time till
-		 * PHY is settled and ready
-		 */
-		udelay(10);
-
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_set_value(omap->reset_gpio_port[0], 1);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_set_value(omap->reset_gpio_port[1], 1);
-	}
-
 	/* Soft reset the PHY using PHY reset command over ULPI */
-	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
-		omap_ehci_soft_phy_reset(omap, 0);
-	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
-		omap_ehci_soft_phy_reset(omap, 1);
-
-	return 0;
-
-err_sys_status:
-	clk_disable(omap->utmi_p2_fck);
-	clk_put(omap->utmi_p2_fck);
-	clk_disable(omap->xclk60mhsp2_ck);
-	clk_put(omap->xclk60mhsp2_ck);
-	clk_disable(omap->utmi_p1_fck);
-	clk_put(omap->utmi_p1_fck);
-	clk_disable(omap->xclk60mhsp1_ck);
-	clk_put(omap->xclk60mhsp1_ck);
-	clk_disable(omap->usbtll_ick);
-	clk_put(omap->usbtll_ick);
-
-err_tll_ick:
-	clk_disable(omap->usbtll_fck);
-	clk_put(omap->usbtll_fck);
-
-err_tll_fck:
-	clk_disable(omap->usbhost_fs_fck);
-	clk_put(omap->usbhost_fs_fck);
-
-	if (omap->phy_reset) {
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_free(omap->reset_gpio_port[0]);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_free(omap->reset_gpio_port[1]);
-	}
-
-err_host_48m_fck:
-	clk_disable(omap->usbhost_hs_fck);
-	clk_put(omap->usbhost_hs_fck);
+	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
+		omap_ehci_soft_phy_reset(pdev, 0);
+	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
+		omap_ehci_soft_phy_reset(pdev, 1);
 
-err_host_120m_fck:
-	clk_disable(omap->usbhost_ick);
-	clk_put(omap->usbhost_ick);
-
-err_host_ick:
-	return ret;
-}
-
-static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-
-	dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n");
-
-	/* Reset OMAP modules for insmod/rmmod to work */
-	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
-			is_omap_ehci_rev2(omap) ?
-			OMAP4_UHH_SYSCONFIG_SOFTRESET :
-			OMAP_UHH_SYSCONFIG_SOFTRESET);
-	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 1))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 2))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
-
-	while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	if (omap->usbtll_fck != NULL) {
-		clk_disable(omap->usbtll_fck);
-		clk_put(omap->usbtll_fck);
-		omap->usbtll_fck = NULL;
-	}
-
-	if (omap->usbhost_ick != NULL) {
-		clk_disable(omap->usbhost_ick);
-		clk_put(omap->usbhost_ick);
-		omap->usbhost_ick = NULL;
-	}
-
-	if (omap->usbhost_fs_fck != NULL) {
-		clk_disable(omap->usbhost_fs_fck);
-		clk_put(omap->usbhost_fs_fck);
-		omap->usbhost_fs_fck = NULL;
-	}
-
-	if (omap->usbhost_hs_fck != NULL) {
-		clk_disable(omap->usbhost_hs_fck);
-		clk_put(omap->usbhost_hs_fck);
-		omap->usbhost_hs_fck = NULL;
-	}
-
-	if (omap->usbtll_ick != NULL) {
-		clk_disable(omap->usbtll_ick);
-		clk_put(omap->usbtll_ick);
-		omap->usbtll_ick = NULL;
-	}
-
-	if (is_omap_ehci_rev2(omap)) {
-		if (omap->xclk60mhsp1_ck != NULL) {
-			clk_disable(omap->xclk60mhsp1_ck);
-			clk_put(omap->xclk60mhsp1_ck);
-			omap->xclk60mhsp1_ck = NULL;
-		}
-
-		if (omap->utmi_p1_fck != NULL) {
-			clk_disable(omap->utmi_p1_fck);
-			clk_put(omap->utmi_p1_fck);
-			omap->utmi_p1_fck = NULL;
-		}
-
-		if (omap->xclk60mhsp2_ck != NULL) {
-			clk_disable(omap->xclk60mhsp2_ck);
-			clk_put(omap->xclk60mhsp2_ck);
-			omap->xclk60mhsp2_ck = NULL;
-		}
-
-		if (omap->utmi_p2_fck != NULL) {
-			clk_disable(omap->utmi_p2_fck);
-			clk_put(omap->utmi_p2_fck);
-			omap->utmi_p2_fck = NULL;
-		}
-	}
-
-	if (omap->phy_reset) {
-		if (gpio_is_valid(omap->reset_gpio_port[0]))
-			gpio_free(omap->reset_gpio_port[0]);
-
-		if (gpio_is_valid(omap->reset_gpio_port[1]))
-			gpio_free(omap->reset_gpio_port[1]);
-	}
-
-	dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ehci_omap_hc_driver;
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-/**
- * ehci_hcd_omap_probe - initialize TI-based HCDs
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- */
-static int ehci_hcd_omap_probe(struct platform_device *pdev)
-{
-	struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
-	struct ehci_hcd_omap *omap;
-	struct resource *res;
-	struct usb_hcd *hcd;
-
-	int irq = platform_get_irq(pdev, 0);
-	int ret = -ENODEV;
-	int i;
-	char supply[7];
-
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "missing platform_data\n");
-		goto err_pdata;
-	}
-
-	if (usb_disabled())
-		goto err_disabled;
-
-	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
-	if (!omap) {
-		ret = -ENOMEM;
-		goto err_disabled;
-	}
-
-	hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev,
-			dev_name(&pdev->dev));
-	if (!hcd) {
-		dev_err(&pdev->dev, "failed to create hcd with err %d\n", ret);
-		ret = -ENOMEM;
-		goto err_create_hcd;
-	}
-
-	platform_set_drvdata(pdev, omap);
-	omap->dev		= &pdev->dev;
-	omap->phy_reset		= pdata->phy_reset;
-	omap->reset_gpio_port[0]	= pdata->reset_gpio_port[0];
-	omap->reset_gpio_port[1]	= pdata->reset_gpio_port[1];
-	omap->reset_gpio_port[2]	= pdata->reset_gpio_port[2];
-	omap->port_mode[0]		= pdata->port_mode[0];
-	omap->port_mode[1]		= pdata->port_mode[1];
-	omap->port_mode[2]		= pdata->port_mode[2];
-	omap->ehci		= hcd_to_ehci(hcd);
-	omap->ehci->sbrn	= 0x20;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	hcd->rsrc_start = res->start;
-	hcd->rsrc_len = resource_size(res);
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&pdev->dev, "EHCI ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
+	omap_ehci = hcd_to_ehci(hcd);
+	omap_ehci->sbrn = 0x20;
 
 	/* we know this is the memory we want, no need to ioremap again */
-	omap->ehci->caps = hcd->regs;
-	omap->ehci_base = hcd->regs;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	omap->uhh_base = ioremap(res->start, resource_size(res));
-	if (!omap->uhh_base) {
-		dev_err(&pdev->dev, "UHH ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_uhh_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	omap->tll_base = ioremap(res->start, resource_size(res));
-	if (!omap->tll_base) {
-		dev_err(&pdev->dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_tll_ioremap;
-	}
-
-	/* get ehci regulator and enable */
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) {
-			omap->regulator[i] = NULL;
-			continue;
-		}
-		snprintf(supply, sizeof(supply), "hsusb%d", i);
-		omap->regulator[i] = regulator_get(omap->dev, supply);
-		if (IS_ERR(omap->regulator[i])) {
-			omap->regulator[i] = NULL;
-			dev_dbg(&pdev->dev,
-			"failed to get ehci port%d regulator\n", i);
-		} else {
-			regulator_enable(omap->regulator[i]);
-		}
-	}
-
-	ret = omap_start_ehc(omap, hcd);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to start ehci with err %d\n", ret);
-		goto err_start;
-	}
+	omap_ehci->caps = hcd->regs;
+	omap_ehci->regs = hcd->regs
+			+ HC_LENGTH(readl(&omap_ehci->caps->hc_capbase));
 
-	omap->ehci->regs = hcd->regs
-		+ HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
-
-	dbg_hcs_params(omap->ehci, "reset");
-	dbg_hcc_params(omap->ehci, "reset");
+	dbg_hcs_params(omap_ehci, "reset");
+	dbg_hcc_params(omap_ehci, "reset");
 
 	/* cache this readonly data; minimize chip reads */
-	omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
+	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
 
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (ret) {
-		dev_err(&pdev->dev, "failed to add hcd with err %d\n", ret);
+		dev_err(dev, "failed to add hcd with err %d\n", ret);
 		goto err_add_hcd;
 	}
 
 	/* root ports should always stay powered */
-	ehci_port_power(omap->ehci, 1);
+	ehci_port_power(omap_ehci, 1);
 
 	return 0;
 
 err_add_hcd:
-	omap_stop_ehc(omap, hcd);
+	omap_usbhs_disable(dev);
 
-err_start:
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (omap->regulator[i]) {
-			regulator_disable(omap->regulator[i]);
-			regulator_put(omap->regulator[i]);
-		}
-	}
-	iounmap(omap->tll_base);
-
-err_tll_ioremap:
-	iounmap(omap->uhh_base);
-
-err_uhh_ioremap:
-	iounmap(hcd->regs);
-
-err_ioremap:
+err_enable:
 	usb_put_hcd(hcd);
 
-err_create_hcd:
-	kfree(omap);
-err_disabled:
-err_pdata:
+err_io:
 	return ret;
 }
 
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
 
 /**
  * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs
@@ -929,31 +228,18 @@ err_pdata:
  */
 static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
-	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
-	int i;
+	struct device *dev	= &pdev->dev;
+	struct usb_hcd *hcd	= dev_get_drvdata(dev);
 
 	usb_remove_hcd(hcd);
-	omap_stop_ehc(omap, hcd);
-	iounmap(hcd->regs);
-	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-		if (omap->regulator[i]) {
-			regulator_disable(omap->regulator[i]);
-			regulator_put(omap->regulator[i]);
-		}
-	}
-	iounmap(omap->tll_base);
-	iounmap(omap->uhh_base);
+	omap_usbhs_disable(dev);
 	usb_put_hcd(hcd);
-	kfree(omap);
-
 	return 0;
 }
 
 static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
 {
-	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
+	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 0f87dc7..281e094 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -105,7 +105,8 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
 	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 	int retval;
 
-	ehci_reset(ehci);
+	hcd->has_tt = 1;
+
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -117,7 +118,7 @@ static int ehci_orion_setup(struct usb_hcd *hcd)
 	if (retval)
 		return retval;
 
-	hcd->has_tt = 1;
+	ehci_reset(ehci);
 
 	ehci_port_power(ehci, 0);
 
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 07bb982..d5eaea7 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -44,42 +44,6 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
 	return 0;
 }
 
-static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci)
-{
-	struct pci_dev *amd_smbus_dev;
-	u8 rev = 0;
-
-	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
-	if (amd_smbus_dev) {
-		pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
-		if (rev < 0x40) {
-			pci_dev_put(amd_smbus_dev);
-			amd_smbus_dev = NULL;
-			return 0;
-		}
-	} else {
-		amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL);
-		if (!amd_smbus_dev)
-			return 0;
-		pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
-		if (rev < 0x11 || rev > 0x18) {
-			pci_dev_put(amd_smbus_dev);
-			amd_smbus_dev = NULL;
-			return 0;
-		}
-	}
-
-	if (!amd_nb_dev)
-		amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
-
-	ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n");
-
-	pci_dev_put(amd_smbus_dev);
-	amd_smbus_dev = NULL;
-
-	return 1;
-}
-
 /* called during probe() after chip reset completes */
 static int ehci_pci_setup(struct usb_hcd *hcd)
 {
@@ -138,9 +102,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
-	if (ehci_quirk_amd_hudson(ehci))
-		ehci->amd_l1_fix = 1;
-
 	retval = ehci_halt(ehci);
 	if (retval)
 		return retval;
@@ -191,6 +152,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 		break;
 	case PCI_VENDOR_ID_AMD:
+		/* AMD PLL quirk */
+		if (usb_amd_find_chipset_info())
+			ehci->amd_pll_fix = 1;
 		/* AMD8111 EHCI doesn't work, according to AMD errata */
 		if (pdev->device == 0x7463) {
 			ehci_info(ehci, "ignoring AMD8111 (errata)\n");
@@ -236,6 +200,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 		}
 		break;
 	case PCI_VENDOR_ID_ATI:
+		/* AMD PLL quirk */
+		if (usb_amd_find_chipset_info())
+			ehci->amd_pll_fix = 1;
 		/* SB600 and old version of SB700 have a bug in EHCI controller,
 		 * which causes usb devices lose response in some cases.
 		 */
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c
new file mode 100644
index 0000000..a216864
--- /dev/null
+++ b/drivers/usb/host/ehci-pmcmsp.c
@@ -0,0 +1,383 @@
+/*
+ * PMC MSP EHCI (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 2006-2010 PMC-Sierra 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.
+ *
+ */
+
+/* includes */
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/usb.h>
+#include <msp_usb.h>
+
+/* stream disable*/
+#define USB_CTRL_MODE_STREAM_DISABLE	0x10
+
+/* threshold */
+#define USB_CTRL_FIFO_THRESH		0x00300000
+
+/* register offset for usb_mode */
+#define USB_EHCI_REG_USB_MODE		0x68
+
+/* register offset for usb fifo */
+#define USB_EHCI_REG_USB_FIFO		0x24
+
+/* register offset for usb status */
+#define USB_EHCI_REG_USB_STATUS		0x44
+
+/* serial/parallel transceiver */
+#define USB_EHCI_REG_BIT_STAT_STS	(1<<29)
+
+/* TWI USB0 host device pin */
+#define MSP_PIN_USB0_HOST_DEV		49
+
+/* TWI USB1 host device pin */
+#define MSP_PIN_USB1_HOST_DEV		50
+
+
+static void usb_hcd_tdi_set_mode(struct ehci_hcd *ehci)
+{
+	u8 *base;
+	u8 *statreg;
+	u8 *fiforeg;
+	u32 val;
+	struct ehci_regs *reg_base = ehci->regs;
+
+	/* get register base */
+	base = (u8 *)reg_base + USB_EHCI_REG_USB_MODE;
+	statreg = (u8 *)reg_base + USB_EHCI_REG_USB_STATUS;
+	fiforeg = (u8 *)reg_base + USB_EHCI_REG_USB_FIFO;
+
+	/* Disable controller mode stream */
+	val = ehci_readl(ehci, (u32 *)base);
+	ehci_writel(ehci, (val | USB_CTRL_MODE_STREAM_DISABLE),
+			(u32 *)base);
+
+	/* clear STS to select parallel transceiver interface */
+	val = ehci_readl(ehci, (u32 *)statreg);
+	val = val & ~USB_EHCI_REG_BIT_STAT_STS;
+	ehci_writel(ehci, val, (u32 *)statreg);
+
+	/* write to set the proper fifo threshold */
+	ehci_writel(ehci, USB_CTRL_FIFO_THRESH, (u32 *)fiforeg);
+
+	/* set TWI GPIO USB_HOST_DEV pin high */
+	gpio_direction_output(MSP_PIN_USB0_HOST_DEV, 1);
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	gpio_direction_output(MSP_PIN_USB1_HOST_DEV, 1);
+#endif
+}
+
+/* called during probe() after chip reset completes */
+static int ehci_msp_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
+	int			retval;
+	ehci->big_endian_mmio = 1;
+	ehci->big_endian_desc = 1;
+
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs +
+			HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+	hcd->has_tt = 1;
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	ehci_reset(ehci);
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	usb_hcd_tdi_set_mode(ehci);
+	ehci_port_power(ehci, 0);
+
+	return retval;
+}
+
+
+/* configure so an HC device and id are always provided
+ * always called with process context; sleeping is OK
+ */
+
+static int usb_hcd_msp_map_regs(struct mspusb_device *dev)
+{
+	struct resource *res;
+	struct platform_device *pdev = &dev->dev;
+	u32 res_len;
+	int retval;
+
+	/* MAB register space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res == NULL)
+		return -ENOMEM;
+	res_len = res->end - res->start + 1;
+	if (!request_mem_region(res->start, res_len, "mab regs"))
+		return -EBUSY;
+
+	dev->mab_regs = ioremap_nocache(res->start, res_len);
+	if (dev->mab_regs == NULL) {
+		retval = -ENOMEM;
+		goto err1;
+	}
+
+	/* MSP USB register space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (res == NULL) {
+		retval = -ENOMEM;
+		goto err2;
+	}
+	res_len = res->end - res->start + 1;
+	if (!request_mem_region(res->start, res_len, "usbid regs")) {
+		retval = -EBUSY;
+		goto err2;
+	}
+	dev->usbid_regs = ioremap_nocache(res->start, res_len);
+	if (dev->usbid_regs == NULL) {
+		retval = -ENOMEM;
+		goto err3;
+	}
+
+	return 0;
+err3:
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	res_len = res->end - res->start + 1;
+	release_mem_region(res->start, res_len);
+err2:
+	iounmap(dev->mab_regs);
+err1:
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	res_len = res->end - res->start + 1;
+	release_mem_region(res->start, res_len);
+	dev_err(&pdev->dev, "Failed to map non-EHCI regs.\n");
+	return retval;
+}
+
+/**
+ * usb_hcd_msp_probe - initialize PMC MSP-based HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ */
+int usb_hcd_msp_probe(const struct hc_driver *driver,
+			  struct platform_device *dev)
+{
+	int retval;
+	struct usb_hcd *hcd;
+	struct resource *res;
+	struct ehci_hcd		*ehci ;
+
+	hcd = usb_create_hcd(driver, &dev->dev, "pmcmsp");
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		pr_debug("No IOMEM resource info for %s.\n", dev->name);
+		retval = -ENOMEM;
+		goto err1;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, dev->name)) {
+		retval = -EBUSY;
+		goto err1;
+	}
+	hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	res = platform_get_resource(dev, IORESOURCE_IRQ, 0);
+	if (res == NULL) {
+		dev_err(&dev->dev, "No IRQ resource info for %s.\n", dev->name);
+		retval = -ENOMEM;
+		goto err3;
+	}
+
+	/* Map non-EHCI register spaces */
+	retval = usb_hcd_msp_map_regs(to_mspusb_device(dev));
+	if (retval != 0)
+		goto err3;
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->big_endian_mmio = 1;
+	ehci->big_endian_desc = 1;
+
+
+	retval = usb_add_hcd(hcd, res->start, IRQF_SHARED);
+	if (retval == 0)
+		return 0;
+
+	usb_remove_hcd(hcd);
+err3:
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+
+	return retval;
+}
+
+
+
+/**
+ * usb_hcd_msp_remove - shutdown processing for PMC MSP-based HCDs
+ * @dev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_msp_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ * may be called without controller electrically present
+ * may be called with controller, bus, and devices active
+ */
+void usb_hcd_msp_remove(struct usb_hcd *hcd, struct platform_device *dev)
+{
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+}
+
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+/*
+ * Wrapper around the main ehci_irq.  Since both USB host controllers are
+ * sharing the same IRQ, need to first determine whether we're the intended
+ * recipient of this interrupt.
+ */
+static irqreturn_t ehci_msp_irq(struct usb_hcd *hcd)
+{
+	u32 int_src;
+	struct device *dev = hcd->self.controller;
+	struct platform_device *pdev;
+	struct mspusb_device *mdev;
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	/* need to reverse-map a couple of containers to get our device */
+	pdev = to_platform_device(dev);
+	mdev = to_mspusb_device(pdev);
+
+	/* Check to see if this interrupt is for this host controller */
+	int_src = ehci_readl(ehci, &mdev->mab_regs->int_stat);
+	if (int_src & (1 << pdev->id))
+		return ehci_irq(hcd);
+
+	/* Not for this device */
+	return IRQ_NONE;
+}
+#endif /* DUAL_USB */
+
+static const struct hc_driver ehci_msp_hc_driver = {
+	.description =		hcd_name,
+	.product_desc =		"PMC MSP EHCI",
+	.hcd_priv_size =	sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	.irq =			ehci_msp_irq,
+#else
+	.irq =			ehci_irq,
+#endif
+	.flags =		HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset =		ehci_msp_setup,
+	.start =		ehci_run,
+	.shutdown		= ehci_shutdown,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+
+	/*
+	 * 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 int ehci_hcd_msp_drv_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	pr_debug("In ehci_hcd_msp_drv_probe");
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	gpio_request(MSP_PIN_USB0_HOST_DEV, "USB0_HOST_DEV_GPIO");
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	gpio_request(MSP_PIN_USB1_HOST_DEV, "USB1_HOST_DEV_GPIO");
+#endif
+
+	ret = usb_hcd_msp_probe(&ehci_msp_hc_driver, pdev);
+
+	return ret;
+}
+
+static int ehci_hcd_msp_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_hcd_msp_remove(hcd, pdev);
+
+	/* free TWI GPIO USB_HOST_DEV pin */
+	gpio_free(MSP_PIN_USB0_HOST_DEV);
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+	gpio_free(MSP_PIN_USB1_HOST_DEV);
+#endif
+
+	return 0;
+}
+
+MODULE_ALIAS("pmcmsp-ehci");
+
+static struct platform_driver ehci_hcd_msp_driver = {
+	.probe		= ehci_hcd_msp_drv_probe,
+	.remove		= ehci_hcd_msp_drv_remove,
+	.driver		= {
+		.name	= "pmcmsp-ehci",
+		.owner	= THIS_MODULE,
+	},
+};
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index ba52be4..1f09f25 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -105,8 +105,7 @@ ppc44x_enable_bmt(struct device_node *dn)
 }
 
 
-static int __devinit
-ehci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
@@ -255,14 +254,12 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op)
 }
 
 
-static int ehci_hcd_ppc_of_shutdown(struct platform_device *op)
+static void ehci_hcd_ppc_of_shutdown(struct platform_device *op)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
-
-	return 0;
 }
 
 
@@ -275,7 +272,7 @@ static const struct of_device_id ehci_hcd_ppc_of_match[] = {
 MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
 
 
-static struct of_platform_driver ehci_hcd_ppc_of_driver = {
+static struct platform_driver ehci_hcd_ppc_of_driver = {
 	.probe		= ehci_hcd_ppc_of_probe,
 	.remove		= ehci_hcd_ppc_of_remove,
 	.shutdown	= ehci_hcd_ppc_of_shutdown,
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 233c288..fe99895 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -1107,22 +1107,24 @@ submit_async (
 	struct list_head	*qtd_list,
 	gfp_t			mem_flags
 ) {
-	struct ehci_qtd		*qtd;
 	int			epnum;
 	unsigned long		flags;
 	struct ehci_qh		*qh = NULL;
 	int			rc;
 
-	qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
 	epnum = urb->ep->desc.bEndpointAddress;
 
 #ifdef EHCI_URB_TRACE
-	ehci_dbg (ehci,
-		"%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-		__func__, urb->dev->devpath, urb,
-		epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
-		urb->transfer_buffer_length,
-		qtd, urb->ep->hcpriv);
+	{
+		struct ehci_qtd *qtd;
+		qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list);
+		ehci_dbg(ehci,
+			 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+			 __func__, urb->dev->devpath, urb,
+			 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
+			 urb->transfer_buffer_length,
+			 qtd, urb->ep->hcpriv);
+	}
 #endif
 
 	spin_lock_irqsave (&ehci->lock, flags);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index aa46f57..1543c83 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1048,8 +1048,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
 	 * not like a QH -- no persistent state (toggle, halt)
 	 */
 	if (stream->refcount == 1) {
-		int		is_in;
-
 		// BUG_ON (!list_empty(&stream->td_list));
 
 		while (!list_empty (&stream->free_list)) {
@@ -1076,7 +1074,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
 			}
 		}
 
-		is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
 		stream->bEndpointAddress &= 0x0f;
 		if (stream->ep)
 			stream->ep->hcpriv = NULL;
@@ -1590,63 +1587,6 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd)
 	*hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD);
 }
 
-#define AB_REG_BAR_LOW 0xe0
-#define AB_REG_BAR_HIGH 0xe1
-#define AB_INDX(addr) ((addr) + 0x00)
-#define AB_DATA(addr) ((addr) + 0x04)
-#define NB_PCIE_INDX_ADDR 0xe0
-#define NB_PCIE_INDX_DATA 0xe4
-#define NB_PIF0_PWRDOWN_0 0x01100012
-#define NB_PIF0_PWRDOWN_1 0x01100013
-
-static void ehci_quirk_amd_L1(struct ehci_hcd *ehci, int disable)
-{
-	u32 addr, addr_low, addr_high, val;
-
-	outb_p(AB_REG_BAR_LOW, 0xcd6);
-	addr_low = inb_p(0xcd7);
-	outb_p(AB_REG_BAR_HIGH, 0xcd6);
-	addr_high = inb_p(0xcd7);
-	addr = addr_high << 8 | addr_low;
-	outl_p(0x30, AB_INDX(addr));
-	outl_p(0x40, AB_DATA(addr));
-	outl_p(0x34, AB_INDX(addr));
-	val = inl_p(AB_DATA(addr));
-
-	if (disable) {
-		val &= ~0x8;
-		val |= (1 << 4) | (1 << 9);
-	} else {
-		val |= 0x8;
-		val &= ~((1 << 4) | (1 << 9));
-	}
-	outl_p(val, AB_DATA(addr));
-
-	if (amd_nb_dev) {
-		addr = NB_PIF0_PWRDOWN_0;
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
-		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
-		if (disable)
-			val &= ~(0x3f << 7);
-		else
-			val |= 0x3f << 7;
-
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
-
-		addr = NB_PIF0_PWRDOWN_1;
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_ADDR, addr);
-		pci_read_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, &val);
-		if (disable)
-			val &= ~(0x3f << 7);
-		else
-			val |= 0x3f << 7;
-
-		pci_write_config_dword(amd_nb_dev, NB_PCIE_INDX_DATA, val);
-	}
-
-	return;
-}
-
 /* fit urb's itds into the selected schedule slot; activate as needed */
 static int
 itd_link_urb (
@@ -1675,8 +1615,8 @@ itd_link_urb (
 	}
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 1);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_disable();
 	}
 
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -1804,8 +1744,8 @@ itd_complete (
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 0);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_enable();
 	}
 
 	if (unlikely(list_is_singular(&stream->td_list))) {
@@ -2095,8 +2035,8 @@ sitd_link_urb (
 	}
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 1);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_disable();
 	}
 
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
@@ -2200,8 +2140,8 @@ sitd_complete (
 	ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
 
 	if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) {
-		if (ehci->amd_l1_fix == 1)
-			ehci_quirk_amd_L1(ehci, 0);
+		if (ehci->amd_pll_fix == 1)
+			usb_amd_quirk_pll_enable();
 	}
 
 	if (list_is_singular(&stream->td_list)) {
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
new file mode 100644
index 0000000..a516af2
--- /dev/null
+++ b/drivers/usb/host/ehci-tegra.c
@@ -0,0 +1,715 @@
+/*
+ * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2009 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * 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/platform_device.h>
+#include <linux/platform_data/tegra_usb.h>
+#include <linux/irq.h>
+#include <linux/usb/otg.h>
+#include <mach/usb_phy.h>
+
+#define TEGRA_USB_DMA_ALIGN 32
+
+struct tegra_ehci_hcd {
+	struct ehci_hcd *ehci;
+	struct tegra_usb_phy *phy;
+	struct clk *clk;
+	struct clk *emc_clk;
+	struct otg_transceiver *transceiver;
+	int host_resumed;
+	int bus_suspended;
+	int port_resuming;
+	int power_down_on_bus_suspend;
+	enum tegra_usb_phy_port_speed port_speed;
+};
+
+static void tegra_ehci_power_up(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	clk_enable(tegra->emc_clk);
+	clk_enable(tegra->clk);
+	tegra_usb_phy_power_on(tegra->phy);
+	tegra->host_resumed = 1;
+}
+
+static void tegra_ehci_power_down(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	tegra->host_resumed = 0;
+	tegra_usb_phy_power_off(tegra->phy);
+	clk_disable(tegra->clk);
+	clk_disable(tegra->emc_clk);
+}
+
+static int tegra_ehci_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength
+)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	u32 __iomem	*status_reg;
+	u32		temp;
+	unsigned long	flags;
+	int		retval = 0;
+
+	status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
+
+	spin_lock_irqsave(&ehci->lock, flags);
+
+	/*
+	 * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits
+	 * that are write on clear, by writing back the register read value, so
+	 * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits
+	 */
+	if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) {
+		temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS;
+		ehci_writel(ehci, temp & ~PORT_PE, status_reg);
+		goto done;
+	}
+
+	else if (typeReq == GetPortStatus) {
+		temp = ehci_readl(ehci, status_reg);
+		if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
+			/* Resume completed, re-enable disconnect detection */
+			tegra->port_resuming = 0;
+			tegra_usb_phy_postresume(tegra->phy);
+		}
+	}
+
+	else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
+		temp = ehci_readl(ehci, status_reg);
+		if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
+			retval = -EPIPE;
+			goto done;
+		}
+
+		temp &= ~PORT_WKCONN_E;
+		temp |= PORT_WKDISC_E | PORT_WKOC_E;
+		ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
+
+		/*
+		 * If a transaction is in progress, there may be a delay in
+		 * suspending the port. Poll until the port is suspended.
+		 */
+		if (handshake(ehci, status_reg, PORT_SUSPEND,
+						PORT_SUSPEND, 5000))
+			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
+
+		set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
+		goto done;
+	}
+
+	/*
+	 * Tegra host controller will time the resume operation to clear the bit
+	 * when the port control state switches to HS or FS Idle. This behavior
+	 * is different from EHCI where the host controller driver is required
+	 * to set this bit to a zero after the resume duration is timed in the
+	 * driver.
+	 */
+	else if (typeReq == ClearPortFeature &&
+					wValue == USB_PORT_FEAT_SUSPEND) {
+		temp = ehci_readl(ehci, status_reg);
+		if ((temp & PORT_RESET) || !(temp & PORT_PE)) {
+			retval = -EPIPE;
+			goto done;
+		}
+
+		if (!(temp & PORT_SUSPEND))
+			goto done;
+
+		/* Disable disconnect detection during port resume */
+		tegra_usb_phy_preresume(tegra->phy);
+
+		ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
+
+		temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
+		/* start resume signalling */
+		ehci_writel(ehci, temp | PORT_RESUME, status_reg);
+
+		spin_unlock_irqrestore(&ehci->lock, flags);
+		msleep(20);
+		spin_lock_irqsave(&ehci->lock, flags);
+
+		/* Poll until the controller clears RESUME and SUSPEND */
+		if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
+			pr_err("%s: timeout waiting for RESUME\n", __func__);
+		if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
+			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
+
+		ehci->reset_done[wIndex-1] = 0;
+
+		tegra->port_resuming = 1;
+		goto done;
+	}
+
+	spin_unlock_irqrestore(&ehci->lock, flags);
+
+	/* Handle the hub control events here */
+	return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+done:
+	spin_unlock_irqrestore(&ehci->lock, flags);
+	return retval;
+}
+
+static void tegra_ehci_restart(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	ehci_reset(ehci);
+
+	/* setup the frame list and Async q heads */
+	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
+	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);
+	/* setup the command register and set the controller in RUN mode */
+	ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
+	ehci->command |= CMD_RUN;
+	ehci_writel(ehci, ehci->command, &ehci->regs->command);
+
+	down_write(&ehci_cf_port_reset_rwsem);
+	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+	/* flush posted writes */
+	ehci_readl(ehci, &ehci->regs->command);
+	up_write(&ehci_cf_port_reset_rwsem);
+}
+
+static int tegra_usb_suspend(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	struct ehci_regs __iomem *hw = tegra->ehci->regs;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tegra->ehci->lock, flags);
+
+	tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
+	ehci_halt(tegra->ehci);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+	spin_unlock_irqrestore(&tegra->ehci->lock, flags);
+
+	tegra_ehci_power_down(hcd);
+	return 0;
+}
+
+static int tegra_usb_resume(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	struct ehci_regs __iomem *hw = ehci->regs;
+	unsigned long val;
+
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	tegra_ehci_power_up(hcd);
+
+	if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
+		/* Wait for the phy to detect new devices
+		 * before we restart the controller */
+		msleep(10);
+		goto restart;
+	}
+
+	/* Force the phy to keep data lines in suspend state */
+	tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
+
+	/* Enable host mode */
+	tdi_reset(ehci);
+
+	/* Enable Port Power */
+	val = readl(&hw->port_status[0]);
+	val |= PORT_POWER;
+	writel(val, &hw->port_status[0]);
+	udelay(10);
+
+	/* Check if the phy resume from LP0. When the phy resume from LP0
+	 * USB register will be reset. */
+	if (!readl(&hw->async_next)) {
+		/* Program the field PTC based on the saved speed mode */
+		val = readl(&hw->port_status[0]);
+		val &= ~PORT_TEST(~0);
+		if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
+			val |= PORT_TEST_FORCE;
+		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
+			val |= PORT_TEST(6);
+		else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+			val |= PORT_TEST(7);
+		writel(val, &hw->port_status[0]);
+		udelay(10);
+
+		/* Disable test mode by setting PTC field to NORMAL_OP */
+		val = readl(&hw->port_status[0]);
+		val &= ~PORT_TEST(~0);
+		writel(val, &hw->port_status[0]);
+		udelay(10);
+	}
+
+	/* Poll until CCS is enabled */
+	if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
+						 PORT_CONNECT, 2000)) {
+		pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
+		goto restart;
+	}
+
+	/* Poll until PE is enabled */
+	if (handshake(ehci, &hw->port_status[0], PORT_PE,
+						 PORT_PE, 2000)) {
+		pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
+		goto restart;
+	}
+
+	/* Clear the PCI status, to avoid an interrupt taken upon resume */
+	val = readl(&hw->status);
+	val |= STS_PCD;
+	writel(val, &hw->status);
+
+	/* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+	val = readl(&hw->port_status[0]);
+	if ((val & PORT_POWER) && (val & PORT_PE)) {
+		val |= PORT_SUSPEND;
+		writel(val, &hw->port_status[0]);
+
+		/* Wait until port suspend completes */
+		if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
+							 PORT_SUSPEND, 1000)) {
+			pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+								__func__);
+			goto restart;
+		}
+	}
+
+	tegra_ehci_phy_restore_end(tegra->phy);
+	return 0;
+
+restart:
+	if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
+		tegra_ehci_phy_restore_end(tegra->phy);
+
+	tegra_ehci_restart(hcd);
+	return 0;
+}
+
+static void tegra_ehci_shutdown(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	/* ehci_shutdown touches the USB controller registers, make sure
+	 * controller has clocks to it */
+	if (!tegra->host_resumed)
+		tegra_ehci_power_up(hcd);
+
+	ehci_shutdown(hcd);
+}
+
+static int tegra_ehci_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	/* EHCI registers start at offset 0x100 */
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+		HC_LENGTH(readl(&ehci->caps->hc_capbase));
+
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+	/* switch to host mode */
+	hcd->has_tt = 1;
+	ehci_reset(ehci);
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	ehci->sbrn = 0x20;
+
+	ehci_port_power(ehci, 1);
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+	int error_status = 0;
+
+	error_status = ehci_bus_suspend(hcd);
+	if (!error_status && tegra->power_down_on_bus_suspend) {
+		tegra_usb_suspend(hcd);
+		tegra->bus_suspended = 1;
+	}
+
+	return error_status;
+}
+
+static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
+{
+	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
+
+	if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
+		tegra_usb_resume(hcd);
+		tegra->bus_suspended = 0;
+	}
+
+	tegra_usb_phy_preresume(tegra->phy);
+	tegra->port_resuming = 1;
+	return ehci_bus_resume(hcd);
+}
+#endif
+
+struct temp_buffer {
+	void *kmalloc_ptr;
+	void *old_xfer_buffer;
+	u8 data[0];
+};
+
+static void free_temp_buffer(struct urb *urb)
+{
+	enum dma_data_direction dir;
+	struct 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 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 alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
+{
+	enum dma_data_direction dir;
+	struct temp_buffer *temp, *kmalloc_ptr;
+	size_t kmalloc_size;
+
+	if (urb->num_sgs || urb->sg ||
+	    urb->transfer_buffer_length == 0 ||
+	    !((uintptr_t)urb->transfer_buffer & (TEGRA_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 temp_buffer) + TEGRA_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 + 1, TEGRA_USB_DMA_ALIGN) - 1;
+
+	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 tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+				      gfp_t mem_flags)
+{
+	int ret;
+
+	ret = alloc_temp_buffer(urb, mem_flags);
+	if (ret)
+		return ret;
+
+	ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+	if (ret)
+		free_temp_buffer(urb);
+
+	return ret;
+}
+
+static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+	usb_hcd_unmap_urb_for_dma(hcd, urb);
+	free_temp_buffer(urb);
+}
+
+static const struct hc_driver tegra_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "Tegra EHCI Host Controller",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	.flags			= HCD_USB2 | HCD_MEMORY,
+
+	.reset			= tegra_ehci_setup,
+	.irq			= ehci_irq,
+
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= tegra_ehci_shutdown,
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.map_urb_for_dma	= tegra_ehci_map_urb_for_dma,
+	.unmap_urb_for_dma	= tegra_ehci_unmap_urb_for_dma,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+	.get_frame_number	= ehci_get_frame,
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= tegra_ehci_hub_control,
+	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+#ifdef CONFIG_PM
+	.bus_suspend		= tegra_ehci_bus_suspend,
+	.bus_resume		= tegra_ehci_bus_resume,
+#endif
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+};
+
+static int tegra_ehci_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct usb_hcd *hcd;
+	struct tegra_ehci_hcd *tegra;
+	struct tegra_ehci_platform_data *pdata;
+	int err = 0;
+	int irq;
+	int instance = pdev->id;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "Platform data missing\n");
+		return -EINVAL;
+	}
+
+	tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+
+	hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev,
+					dev_name(&pdev->dev));
+	if (!hcd) {
+		dev_err(&pdev->dev, "Unable to create HCD\n");
+		err = -ENOMEM;
+		goto fail_hcd;
+	}
+
+	platform_set_drvdata(pdev, tegra);
+
+	tegra->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(tegra->clk)) {
+		dev_err(&pdev->dev, "Can't get ehci clock\n");
+		err = PTR_ERR(tegra->clk);
+		goto fail_clk;
+	}
+
+	err = clk_enable(tegra->clk);
+	if (err)
+		goto fail_clken;
+
+	tegra->emc_clk = clk_get(&pdev->dev, "emc");
+	if (IS_ERR(tegra->emc_clk)) {
+		dev_err(&pdev->dev, "Can't get emc clock\n");
+		err = PTR_ERR(tegra->emc_clk);
+		goto fail_emc_clk;
+	}
+
+	clk_enable(tegra->emc_clk);
+	clk_set_rate(tegra->emc_clk, 400000000);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get I/O memory\n");
+		err = -ENXIO;
+		goto fail_io;
+	}
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+	hcd->regs = ioremap(res->start, resource_size(res));
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "Failed to remap I/O memory\n");
+		err = -ENOMEM;
+		goto fail_io;
+	}
+
+	tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config,
+						TEGRA_USB_PHY_MODE_HOST);
+	if (IS_ERR(tegra->phy)) {
+		dev_err(&pdev->dev, "Failed to open USB phy\n");
+		err = -ENXIO;
+		goto fail_phy;
+	}
+
+	err = tegra_usb_phy_power_on(tegra->phy);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to power on the phy\n");
+		goto fail;
+	}
+
+	tegra->host_resumed = 1;
+	tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
+	tegra->ehci = hcd_to_ehci(hcd);
+
+	irq = platform_get_irq(pdev, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "Failed to get IRQ\n");
+		err = -ENODEV;
+		goto fail;
+	}
+	set_irq_flags(irq, IRQF_VALID);
+
+#ifdef CONFIG_USB_OTG_UTILS
+	if (pdata->operating_mode == TEGRA_USB_OTG) {
+		tegra->transceiver = otg_get_transceiver();
+		if (tegra->transceiver)
+			otg_set_host(tegra->transceiver, &hcd->self);
+	}
+#endif
+
+	err = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to add USB HCD\n");
+		goto fail;
+	}
+
+	return err;
+
+fail:
+#ifdef CONFIG_USB_OTG_UTILS
+	if (tegra->transceiver) {
+		otg_set_host(tegra->transceiver, NULL);
+		otg_put_transceiver(tegra->transceiver);
+	}
+#endif
+	tegra_usb_phy_close(tegra->phy);
+fail_phy:
+	iounmap(hcd->regs);
+fail_io:
+	clk_disable(tegra->emc_clk);
+	clk_put(tegra->emc_clk);
+fail_emc_clk:
+	clk_disable(tegra->clk);
+fail_clken:
+	clk_put(tegra->clk);
+fail_clk:
+	usb_put_hcd(hcd);
+fail_hcd:
+	kfree(tegra);
+	return err;
+}
+
+#ifdef CONFIG_PM
+static int tegra_ehci_resume(struct platform_device *pdev)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (tegra->bus_suspended)
+		return 0;
+
+	return tegra_usb_resume(hcd);
+}
+
+static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (tegra->bus_suspended)
+		return 0;
+
+	if (time_before(jiffies, tegra->ehci->next_statechange))
+		msleep(10);
+
+	return tegra_usb_suspend(hcd);
+}
+#endif
+
+static int tegra_ehci_remove(struct platform_device *pdev)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (tegra == NULL || hcd == NULL)
+		return -EINVAL;
+
+#ifdef CONFIG_USB_OTG_UTILS
+	if (tegra->transceiver) {
+		otg_set_host(tegra->transceiver, NULL);
+		otg_put_transceiver(tegra->transceiver);
+	}
+#endif
+
+	usb_remove_hcd(hcd);
+	usb_put_hcd(hcd);
+
+	tegra_usb_phy_close(tegra->phy);
+	iounmap(hcd->regs);
+
+	clk_disable(tegra->clk);
+	clk_put(tegra->clk);
+
+	clk_disable(tegra->emc_clk);
+	clk_put(tegra->emc_clk);
+
+	kfree(tegra);
+	return 0;
+}
+
+static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
+{
+	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+
+	if (hcd->driver->shutdown)
+		hcd->driver->shutdown(hcd);
+}
+
+static struct platform_driver tegra_ehci_driver = {
+	.probe		= tegra_ehci_probe,
+	.remove		= tegra_ehci_remove,
+#ifdef CONFIG_PM
+	.suspend	= tegra_ehci_suspend,
+	.resume		= tegra_ehci_resume,
+#endif
+	.shutdown	= tegra_ehci_hcd_shutdown,
+	.driver		= {
+		.name	= "tegra-ehci",
+	}
+};
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index a6f21b8..effc58d 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -143,15 +143,13 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = {
 /**
  * ehci_hcd_xilinx_of_probe - Probe method for the USB host controller
  * @op:		pointer to the platform_device bound to the host controller
- * @match:	pointer to of_device_id structure, not used
  *
  * This function requests resources and sets up appropriate properties for the
  * host controller. Because the Xilinx USB host controller can be configured
  * as HS only or HS/FS only, it checks the configuration in the device tree
  * entry, and sets an appropriate value for hcd->has_tt.
  */
-static int __devinit
-ehci_hcd_xilinx_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
@@ -289,7 +287,7 @@ static const struct of_device_id ehci_hcd_xilinx_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
 
-static struct of_platform_driver ehci_hcd_xilinx_of_driver = {
+static struct platform_driver ehci_hcd_xilinx_of_driver = {
 	.probe		= ehci_hcd_xilinx_of_probe,
 	.remove		= ehci_hcd_xilinx_of_remove,
 	.shutdown	= ehci_hcd_xilinx_of_shutdown,
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 799ac16..f86d3fa 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -131,7 +131,7 @@ struct ehci_hcd {			/* one per controller */
 	unsigned		has_amcc_usb23:1;
 	unsigned		need_io_watchdog:1;
 	unsigned		broken_periodic:1;
-	unsigned		amd_l1_fix:1;
+	unsigned		amd_pll_fix:1;
 	unsigned		fs_i_thresh:1;	/* Intel iso scheduling */
 	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/
 
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 12fd184..b84ff7e 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -561,8 +561,7 @@ static const struct hc_driver fhci_driver = {
 	.hub_control = fhci_hub_control,
 };
 
-static int __devinit of_fhci_probe(struct platform_device *ofdev,
-				   const struct of_device_id *ofid)
+static int __devinit of_fhci_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *node = dev->of_node;
@@ -812,7 +811,7 @@ static const struct of_device_id of_fhci_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_fhci_match);
 
-static struct of_platform_driver of_fhci_driver = {
+static struct platform_driver of_fhci_driver = {
 	.driver = {
 		.name = "fsl,usb-fhci",
 		.owner = THIS_MODULE,
@@ -824,13 +823,13 @@ static struct of_platform_driver of_fhci_driver = {
 
 static int __init fhci_module_init(void)
 {
-	return of_register_platform_driver(&of_fhci_driver);
+	return platform_driver_register(&of_fhci_driver);
 }
 module_init(fhci_module_init);
 
 static void __exit fhci_module_exit(void)
 {
-	of_unregister_platform_driver(&of_fhci_driver);
+	platform_driver_unregister(&of_fhci_driver);
 }
 module_exit(fhci_module_exit);
 
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index f90d003..2562e92 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -927,7 +927,8 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
 		if (state == US_CTRL_SETUP) {
 			dir = TD_DIR_SETUP;
 			if (unsuitable_for_dma(urb->setup_dma))
-				unmap_urb_setup_for_dma(imx21->hcd, urb);
+				usb_hcd_unmap_urb_setup_for_dma(imx21->hcd,
+					urb);
 			etd->dma_handle = urb->setup_dma;
 			etd->cpu_buffer = urb->setup_packet;
 			bufround = 0;
@@ -943,7 +944,7 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb)
 		dir = usb_pipeout(pipe) ? TD_DIR_OUT : TD_DIR_IN;
 		bufround = (dir == TD_DIR_IN) ? 1 : 0;
 		if (unsuitable_for_dma(urb->transfer_dma))
-			unmap_urb_for_dma(imx21->hcd, urb);
+			usb_hcd_unmap_urb_for_dma(imx21->hcd, urb);
 
 		etd->dma_handle = urb->transfer_dma;
 		etd->cpu_buffer = urb->transfer_buffer;
@@ -1471,8 +1472,8 @@ static int get_hub_descriptor(struct usb_hcd *hcd,
 		0x0010 |	/* No over current protection */
 		0);
 
-	desc->bitmap[0] = 1 << 1;
-	desc->bitmap[1] = ~0;
+	desc->u.hs.DeviceRemovable[0] = 1 << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 	return 0;
 }
 
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index 0da7fc0..c0e22f2 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -951,9 +951,9 @@ static void isp116x_hub_descriptor(struct isp116x *isp116x,
 	/* Power switching, device type, overcurrent. */
 	desc->wHubCharacteristics = cpu_to_le16((u16) ((reg >> 8) & 0x1f));
 	desc->bPwrOn2PwrGood = (u8) ((reg >> 24) & 0xff);
-	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = 0;
-	desc->bitmap[1] = ~0;
+	/* ports removable, and legacy PortPwrCtrlMask */
+	desc->u.hs.DeviceRemovable[0] = 0;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 }
 
 /* Perform reset of a given port.
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 43a39eb..662cd00 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -226,7 +226,6 @@ static int claim_ptd_buffers(struct isp1362_ep_queue *epq,
 
 static inline void release_ptd_buffers(struct isp1362_ep_queue *epq, struct isp1362_ep *ep)
 {
-	int index = ep->ptd_index;
 	int last = ep->ptd_index + ep->num_ptds;
 
 	if (last > epq->buf_count)
@@ -236,10 +235,8 @@ static inline void release_ptd_buffers(struct isp1362_ep_queue *epq, struct isp1
 		    epq->buf_map, epq->skip_map);
 	BUG_ON(last > epq->buf_count);
 
-	for (; index < last; index++) {
-		__clear_bit(index, &epq->buf_map);
-		__set_bit(index, &epq->skip_map);
-	}
+	bitmap_clear(&epq->buf_map, ep->ptd_index, ep->num_ptds);
+	bitmap_set(&epq->skip_map, ep->ptd_index, ep->num_ptds);
 	epq->buf_avail += ep->num_ptds;
 	epq->ptd_count--;
 
@@ -1555,9 +1552,9 @@ static void isp1362_hub_descriptor(struct isp1362_hcd *isp1362_hcd,
 	desc->wHubCharacteristics = cpu_to_le16((reg >> 8) & 0x1f);
 	DBG(0, "%s: hubcharacteristics = %02x\n", __func__, cpu_to_le16((reg >> 8) & 0x1f));
 	desc->bPwrOn2PwrGood = (reg >> 24) & 0xff;
-	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
-	desc->bitmap[1] = ~0;
+	/* ports removable, and legacy PortPwrCtrlMask */
+	desc->u.hs.DeviceRemovable[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 
 	DBG(3, "%s: exit\n", __func__);
 }
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c
index bdba8c5..f50e84a 100644
--- a/drivers/usb/host/isp1760-hcd.c
+++ b/drivers/usb/host/isp1760-hcd.c
@@ -33,6 +33,7 @@ struct isp1760_hcd {
 	struct inter_packet_info atl_ints[32];
 	struct inter_packet_info int_ints[32];
 	struct memory_chunk memory_pool[BLOCKS];
+	u32 atl_queued;
 
 	/* periodic schedule support */
 #define	DEFAULT_I_TDPS		1024
@@ -47,10 +48,6 @@ static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd)
 {
 	return (struct isp1760_hcd *) (hcd->hcd_priv);
 }
-static inline struct usb_hcd *priv_to_hcd(struct isp1760_hcd *priv)
-{
-	return container_of((void *) priv, struct usb_hcd, hcd_priv);
-}
 
 /* Section 2.2 Host Controller Capability Registers */
 #define HC_LENGTH(p)		(((p)>>00)&0x00ff)	/* bits 7:0 */
@@ -80,11 +77,10 @@ static inline struct usb_hcd *priv_to_hcd(struct isp1760_hcd *priv)
 #define PORT_RWC_BITS   (PORT_CSC)
 
 struct isp1760_qtd {
-	struct isp1760_qtd *hw_next;
 	u8 packet_type;
-	u8 toggle;
-
 	void *data_buffer;
+	u32 payload_addr;
+
 	/* the rest is HCD-private */
 	struct list_head qtd_list;
 	struct urb *urb;
@@ -92,205 +88,267 @@ struct isp1760_qtd {
 
 	/* isp special*/
 	u32 status;
-#define URB_COMPLETE_NOTIFY	(1 << 0)
 #define URB_ENQUEUED		(1 << 1)
-#define URB_TYPE_ATL		(1 << 2)
-#define URB_TYPE_INT		(1 << 3)
 };
 
 struct isp1760_qh {
 	/* first part defined by EHCI spec */
 	struct list_head qtd_list;
-	struct isp1760_hcd *priv;
-
-	/* periodic schedule info */
-	unsigned short period;		/* polling interval */
-	struct usb_device *dev;
 
 	u32 toggle;
 	u32 ping;
 };
 
-#define ehci_port_speed(priv, portsc) USB_PORT_STAT_HIGH_SPEED
-
-static unsigned int isp1760_readl(__u32 __iomem *regs)
+/*
+ * Access functions for isp176x registers (addresses 0..0x03FF).
+ */
+static u32 reg_read32(void __iomem *base, u32 reg)
 {
-	return readl(regs);
+	return readl(base + reg);
 }
 
-static void isp1760_writel(const unsigned int val, __u32 __iomem *regs)
+static void reg_write32(void __iomem *base, u32 reg, u32 val)
 {
-	writel(val, regs);
+	writel(val, base + reg);
 }
 
 /*
- * The next two copy via MMIO data to/from the device. memcpy_{to|from}io()
+ * Access functions for isp176x memory (offset >= 0x0400).
+ *
+ * bank_reads8() reads memory locations prefetched by an earlier write to
+ * HC_MEMORY_REG (see isp176x datasheet). Unless you want to do fancy multi-
+ * bank optimizations, you should use the more generic mem_reads8() below.
+ *
+ * For access to ptd memory, use the specialized ptd_read() and ptd_write()
+ * below.
+ *
+ * These functions copy via MMIO data to/from the device. memcpy_{to|from}io()
  * doesn't quite work because some people have to enforce 32-bit access
  */
-static void priv_read_copy(struct isp1760_hcd *priv, u32 *src,
-		__u32 __iomem *dst, u32 len)
+static void bank_reads8(void __iomem *src_base, u32 src_offset, u32 bank_addr,
+							__u32 *dst, u32 bytes)
 {
+	__u32 __iomem *src;
 	u32 val;
-	u8 *buff8;
+	__u8 *src_byteptr;
+	__u8 *dst_byteptr;
 
-	if (!src) {
-		printk(KERN_ERR "ERROR: buffer: %p len: %d\n", src, len);
-		return;
-	}
+	src = src_base + (bank_addr | src_offset);
 
-	while (len >= 4) {
-		*src = __raw_readl(dst);
-		len -= 4;
-		src++;
-		dst++;
+	if (src_offset < PAYLOAD_OFFSET) {
+		while (bytes >= 4) {
+			*dst = le32_to_cpu(__raw_readl(src));
+			bytes -= 4;
+			src++;
+			dst++;
+		}
+	} else {
+		while (bytes >= 4) {
+			*dst = __raw_readl(src);
+			bytes -= 4;
+			src++;
+			dst++;
+		}
 	}
 
-	if (!len)
+	if (!bytes)
 		return;
 
 	/* in case we have 3, 2 or 1 by left. The dst buffer may not be fully
 	 * allocated.
 	 */
-	val = isp1760_readl(dst);
-
-	buff8 = (u8 *)src;
-	while (len) {
-
-		*buff8 = val;
-		val >>= 8;
-		len--;
-		buff8++;
+	if (src_offset < PAYLOAD_OFFSET)
+		val = le32_to_cpu(__raw_readl(src));
+	else
+		val = __raw_readl(src);
+
+	dst_byteptr = (void *) dst;
+	src_byteptr = (void *) &val;
+	while (bytes > 0) {
+		*dst_byteptr = *src_byteptr;
+		dst_byteptr++;
+		src_byteptr++;
+		bytes--;
 	}
 }
 
-static void priv_write_copy(const struct isp1760_hcd *priv, const u32 *src,
-		__u32 __iomem *dst, u32 len)
+static void mem_reads8(void __iomem *src_base, u32 src_offset, void *dst,
+								u32 bytes)
 {
-	while (len >= 4) {
-		__raw_writel(*src, dst);
-		len -= 4;
-		src++;
-		dst++;
+	reg_write32(src_base, HC_MEMORY_REG, src_offset + ISP_BANK(0));
+	ndelay(90);
+	bank_reads8(src_base, src_offset, ISP_BANK(0), dst, bytes);
+}
+
+static void mem_writes8(void __iomem *dst_base, u32 dst_offset,
+						__u32 const *src, u32 bytes)
+{
+	__u32 __iomem *dst;
+
+	dst = dst_base + dst_offset;
+
+	if (dst_offset < PAYLOAD_OFFSET) {
+		while (bytes >= 4) {
+			__raw_writel(cpu_to_le32(*src), dst);
+			bytes -= 4;
+			src++;
+			dst++;
+		}
+	} else {
+		while (bytes >= 4) {
+			__raw_writel(*src, dst);
+			bytes -= 4;
+			src++;
+			dst++;
+		}
 	}
 
-	if (!len)
+	if (!bytes)
 		return;
-	/* in case we have 3, 2 or 1 by left. The buffer is allocated and the
-	 * extra bytes should not be read by the HW
+	/* in case we have 3, 2 or 1 bytes left. The buffer is allocated and the
+	 * extra bytes should not be read by the HW.
 	 */
 
-	__raw_writel(*src, dst);
+	if (dst_offset < PAYLOAD_OFFSET)
+		__raw_writel(cpu_to_le32(*src), dst);
+	else
+		__raw_writel(*src, dst);
+}
+
+/*
+ * Read and write ptds. 'ptd_offset' should be one of ISO_PTD_OFFSET,
+ * INT_PTD_OFFSET, and ATL_PTD_OFFSET. 'slot' should be less than 32.
+ */
+static void ptd_read(void __iomem *base, u32 ptd_offset, u32 slot,
+								struct ptd *ptd)
+{
+	reg_write32(base, HC_MEMORY_REG,
+				ISP_BANK(0) + ptd_offset + slot*sizeof(*ptd));
+	ndelay(90);
+	bank_reads8(base, ptd_offset + slot*sizeof(*ptd), ISP_BANK(0),
+						(void *) ptd, sizeof(*ptd));
+}
+
+static void ptd_write(void __iomem *base, u32 ptd_offset, u32 slot,
+								struct ptd *ptd)
+{
+	mem_writes8(base, ptd_offset + slot*sizeof(*ptd) + sizeof(ptd->dw0),
+						&ptd->dw1, 7*sizeof(ptd->dw1));
+	/* Make sure dw0 gets written last (after other dw's and after payload)
+	   since it contains the enable bit */
+	wmb();
+	mem_writes8(base, ptd_offset + slot*sizeof(*ptd), &ptd->dw0,
+							sizeof(ptd->dw0));
 }
 
+
 /* memory management of the 60kb on the chip from 0x1000 to 0xffff */
 static void init_memory(struct isp1760_hcd *priv)
 {
-	int i;
-	u32 payload;
+	int i, curr;
+	u32 payload_addr;
 
-	payload = 0x1000;
+	payload_addr = PAYLOAD_OFFSET;
 	for (i = 0; i < BLOCK_1_NUM; i++) {
-		priv->memory_pool[i].start = payload;
+		priv->memory_pool[i].start = payload_addr;
 		priv->memory_pool[i].size = BLOCK_1_SIZE;
 		priv->memory_pool[i].free = 1;
-		payload += priv->memory_pool[i].size;
+		payload_addr += priv->memory_pool[i].size;
 	}
 
-
-	for (i = BLOCK_1_NUM; i < BLOCK_1_NUM + BLOCK_2_NUM; i++) {
-		priv->memory_pool[i].start = payload;
-		priv->memory_pool[i].size = BLOCK_2_SIZE;
-		priv->memory_pool[i].free = 1;
-		payload += priv->memory_pool[i].size;
+	curr = i;
+	for (i = 0; i < BLOCK_2_NUM; i++) {
+		priv->memory_pool[curr + i].start = payload_addr;
+		priv->memory_pool[curr + i].size = BLOCK_2_SIZE;
+		priv->memory_pool[curr + i].free = 1;
+		payload_addr += priv->memory_pool[curr + i].size;
 	}
 
-
-	for (i = BLOCK_1_NUM + BLOCK_2_NUM; i < BLOCKS; i++) {
-		priv->memory_pool[i].start = payload;
-		priv->memory_pool[i].size = BLOCK_3_SIZE;
-		priv->memory_pool[i].free = 1;
-		payload += priv->memory_pool[i].size;
+	curr = i;
+	for (i = 0; i < BLOCK_3_NUM; i++) {
+		priv->memory_pool[curr + i].start = payload_addr;
+		priv->memory_pool[curr + i].size = BLOCK_3_SIZE;
+		priv->memory_pool[curr + i].free = 1;
+		payload_addr += priv->memory_pool[curr + i].size;
 	}
 
-	BUG_ON(payload - priv->memory_pool[i - 1].size > PAYLOAD_SIZE);
+	BUG_ON(payload_addr - priv->memory_pool[0].start > PAYLOAD_AREA_SIZE);
 }
 
-static u32 alloc_mem(struct isp1760_hcd *priv, u32 size)
+static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int i;
 
-	if (!size)
-		return ISP1760_NULL_POINTER;
+	BUG_ON(qtd->payload_addr);
+
+	if (!qtd->length)
+		return;
 
 	for (i = 0; i < BLOCKS; i++) {
-		if (priv->memory_pool[i].size >= size &&
+		if (priv->memory_pool[i].size >= qtd->length &&
 				priv->memory_pool[i].free) {
-
 			priv->memory_pool[i].free = 0;
-			return priv->memory_pool[i].start;
+			qtd->payload_addr = priv->memory_pool[i].start;
+			return;
 		}
 	}
 
-	printk(KERN_ERR "ISP1760 MEM: can not allocate %d bytes of memory\n",
-			size);
-	printk(KERN_ERR "Current memory map:\n");
+	dev_err(hcd->self.controller,
+				"%s: Can not allocate %lu bytes of memory\n"
+				"Current memory map:\n",
+				__func__, qtd->length);
 	for (i = 0; i < BLOCKS; i++) {
-		printk(KERN_ERR "Pool %2d size %4d status: %d\n",
+		dev_err(hcd->self.controller, "Pool %2d size %4d status: %d\n",
 				i, priv->memory_pool[i].size,
 				priv->memory_pool[i].free);
 	}
 	/* XXX maybe -ENOMEM could be possible */
 	BUG();
-	return 0;
+	return;
 }
 
-static void free_mem(struct isp1760_hcd *priv, u32 mem)
+static void free_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int i;
 
-	if (mem == ISP1760_NULL_POINTER)
+	if (!qtd->payload_addr)
 		return;
 
 	for (i = 0; i < BLOCKS; i++) {
-		if (priv->memory_pool[i].start == mem) {
-
+		if (priv->memory_pool[i].start == qtd->payload_addr) {
 			BUG_ON(priv->memory_pool[i].free);
-
 			priv->memory_pool[i].free = 1;
-			return ;
+			qtd->payload_addr = 0;
+			return;
 		}
 	}
 
-	printk(KERN_ERR "Trying to free not-here-allocated memory :%08x\n",
-			mem);
+	dev_err(hcd->self.controller, "%s: Invalid pointer: %08x\n",
+						__func__, qtd->payload_addr);
 	BUG();
 }
 
 static void isp1760_init_regs(struct usb_hcd *hcd)
 {
-	isp1760_writel(0, hcd->regs + HC_BUFFER_STATUS_REG);
-	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ATL_PTD_SKIPMAP_REG);
-	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_INT_PTD_SKIPMAP_REG);
-	isp1760_writel(NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ISO_PTD_SKIPMAP_REG);
-
-	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ATL_PTD_DONEMAP_REG);
-	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_INT_PTD_DONEMAP_REG);
-	isp1760_writel(~NO_TRANSFER_ACTIVE, hcd->regs +
-			HC_ISO_PTD_DONEMAP_REG);
+	reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0);
+	reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE);
+
+	reg_write32(hcd->regs, HC_ATL_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_INT_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE);
+	reg_write32(hcd->regs, HC_ISO_PTD_DONEMAP_REG, ~NO_TRANSFER_ACTIVE);
 }
 
-static int handshake(struct isp1760_hcd *priv, void __iomem *ptr,
+static int handshake(struct usb_hcd *hcd, u32 reg,
 		      u32 mask, u32 done, int usec)
 {
 	u32 result;
 
 	do {
-		result = isp1760_readl(ptr);
+		result = reg_read32(hcd->regs, reg);
 		if (result == ~0)
 			return -ENODEV;
 		result &= mask;
@@ -303,17 +361,18 @@ static int handshake(struct isp1760_hcd *priv, void __iomem *ptr,
 }
 
 /* reset a non-running (STS_HALT == 1) controller */
-static int ehci_reset(struct isp1760_hcd *priv)
+static int ehci_reset(struct usb_hcd *hcd)
 {
 	int retval;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
-	u32 command = isp1760_readl(hcd->regs + HC_USBCMD);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
+	u32 command = reg_read32(hcd->regs, HC_USBCMD);
 
 	command |= CMD_RESET;
-	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	reg_write32(hcd->regs, HC_USBCMD, command);
 	hcd->state = HC_STATE_HALT;
 	priv->next_statechange = jiffies;
-	retval = handshake(priv, hcd->regs + HC_USBCMD,
+	retval = handshake(hcd, HC_USBCMD,
 			    CMD_RESET, 0, 250 * 1000);
 	return retval;
 }
@@ -324,8 +383,7 @@ static void qh_destroy(struct isp1760_qh *qh)
 	kmem_cache_free(qh_cachep, qh);
 }
 
-static struct isp1760_qh *isp1760_qh_alloc(struct isp1760_hcd *priv,
-		gfp_t flags)
+static struct isp1760_qh *isp1760_qh_alloc(gfp_t flags)
 {
 	struct isp1760_qh *qh;
 
@@ -334,7 +392,6 @@ static struct isp1760_qh *isp1760_qh_alloc(struct isp1760_hcd *priv,
 		return qh;
 
 	INIT_LIST_HEAD(&qh->qtd_list);
-	qh->priv = priv;
 	return qh;
 }
 
@@ -361,7 +418,7 @@ static int priv_init(struct usb_hcd *hcd)
 	priv->periodic_size = DEFAULT_I_TDPS;
 
 	/* controllers may cache some of the periodic schedule ... */
-	hcc_params = isp1760_readl(hcd->regs + HC_HCCPARAMS);
+	hcc_params = reg_read32(hcd->regs, HC_HCCPARAMS);
 	/* full frame cache */
 	if (HCC_ISOC_CACHE(hcc_params))
 		priv->i_thresh = 8;
@@ -398,15 +455,15 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	 * Write it twice to ensure correct upper bits if switching
 	 * to 16-bit mode.
 	 */
-	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
 
-	isp1760_writel(0xdeadbabe, hcd->regs + HC_SCRATCH_REG);
+	reg_write32(hcd->regs, HC_SCRATCH_REG, 0xdeadbabe);
 	/* Change bus pattern */
-	scratch = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
-	scratch = isp1760_readl(hcd->regs + HC_SCRATCH_REG);
+	scratch = reg_read32(hcd->regs, HC_CHIP_ID_REG);
+	scratch = reg_read32(hcd->regs, HC_SCRATCH_REG);
 	if (scratch != 0xdeadbabe) {
-		printk(KERN_ERR "ISP1760: Scratch test failed.\n");
+		dev_err(hcd->self.controller, "Scratch test failed.\n");
 		return -ENODEV;
 	}
 
@@ -414,30 +471,30 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	isp1760_init_regs(hcd);
 
 	/* reset */
-	isp1760_writel(SW_RESET_RESET_ALL, hcd->regs + HC_RESET_REG);
+	reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_ALL);
 	mdelay(100);
 
-	isp1760_writel(SW_RESET_RESET_HC, hcd->regs + HC_RESET_REG);
+	reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_HC);
 	mdelay(100);
 
-	result = ehci_reset(priv);
+	result = ehci_reset(hcd);
 	if (result)
 		return result;
 
 	/* Step 11 passed */
 
-	isp1760_info(priv, "bus width: %d, oc: %s\n",
+	dev_info(hcd->self.controller, "bus width: %d, oc: %s\n",
 			   (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ?
 			   16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ?
 			   "analog" : "digital");
 
 	/* ATL reset */
-	isp1760_writel(hwmode | ALL_ATX_RESET, hcd->regs + HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET);
 	mdelay(10);
-	isp1760_writel(hwmode, hcd->regs + HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode);
 
-	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_REG);
-	isp1760_writel(INTERRUPT_ENABLE_MASK, hcd->regs + HC_INTERRUPT_ENABLE);
+	reg_write32(hcd->regs, HC_INTERRUPT_REG, INTERRUPT_ENABLE_MASK);
+	reg_write32(hcd->regs, HC_INTERRUPT_ENABLE, INTERRUPT_ENABLE_MASK);
 
 	/*
 	 * PORT 1 Control register of the ISP1760 is the OTG control
@@ -445,11 +502,10 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 	 * support in this driver, we use port 1 as a "normal" USB host port on
 	 * both chips.
 	 */
-	isp1760_writel(PORT1_POWER | PORT1_INIT2,
-		       hcd->regs + HC_PORT1_CTRL);
+	reg_write32(hcd->regs, HC_PORT1_CTRL, PORT1_POWER | PORT1_INIT2);
 	mdelay(10);
 
-	priv->hcs_params = isp1760_readl(hcd->regs + HC_HCSPARAMS);
+	priv->hcs_params = reg_read32(hcd->regs, HC_HCSPARAMS);
 
 	return priv_init(hcd);
 }
@@ -457,25 +513,24 @@ static int isp1760_hc_setup(struct usb_hcd *hcd)
 static void isp1760_init_maps(struct usb_hcd *hcd)
 {
 	/*set last maps, for iso its only 1, else 32 tds bitmap*/
-	isp1760_writel(0x80000000, hcd->regs + HC_ATL_PTD_LASTPTD_REG);
-	isp1760_writel(0x80000000, hcd->regs + HC_INT_PTD_LASTPTD_REG);
-	isp1760_writel(0x00000001, hcd->regs + HC_ISO_PTD_LASTPTD_REG);
+	reg_write32(hcd->regs, HC_ATL_PTD_LASTPTD_REG, 0x80000000);
+	reg_write32(hcd->regs, HC_INT_PTD_LASTPTD_REG, 0x80000000);
+	reg_write32(hcd->regs, HC_ISO_PTD_LASTPTD_REG, 0x00000001);
 }
 
 static void isp1760_enable_interrupts(struct usb_hcd *hcd)
 {
-	isp1760_writel(0, hcd->regs + HC_ATL_IRQ_MASK_AND_REG);
-	isp1760_writel(0, hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
-	isp1760_writel(0, hcd->regs + HC_INT_IRQ_MASK_AND_REG);
-	isp1760_writel(0, hcd->regs + HC_INT_IRQ_MASK_OR_REG);
-	isp1760_writel(0, hcd->regs + HC_ISO_IRQ_MASK_AND_REG);
-	isp1760_writel(0xffffffff, hcd->regs + HC_ISO_IRQ_MASK_OR_REG);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_AND_REG, 0);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, 0);
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_AND_REG, 0);
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, 0);
+	reg_write32(hcd->regs, HC_ISO_IRQ_MASK_AND_REG, 0);
+	reg_write32(hcd->regs, HC_ISO_IRQ_MASK_OR_REG, 0xffffffff);
 	/* step 23 passed */
 }
 
 static int isp1760_run(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int retval;
 	u32 temp;
 	u32 command;
@@ -485,15 +540,15 @@ static int isp1760_run(struct usb_hcd *hcd)
 
 	hcd->state = HC_STATE_RUNNING;
 	isp1760_enable_interrupts(hcd);
-	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(temp | HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
+	temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp | HW_GLOBAL_INTR_EN);
 
-	command = isp1760_readl(hcd->regs + HC_USBCMD);
+	command = reg_read32(hcd->regs, HC_USBCMD);
 	command &= ~(CMD_LRESET|CMD_RESET);
 	command |= CMD_RUN;
-	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	reg_write32(hcd->regs, HC_USBCMD, command);
 
-	retval = handshake(priv, hcd->regs + HC_USBCMD,	CMD_RUN, CMD_RUN,
+	retval = handshake(hcd, HC_USBCMD, CMD_RUN, CMD_RUN,
 			250 * 1000);
 	if (retval)
 		return retval;
@@ -504,17 +559,16 @@ static int isp1760_run(struct usb_hcd *hcd)
 	 * the semaphore while doing so.
 	 */
 	down_write(&ehci_cf_port_reset_rwsem);
-	isp1760_writel(FLAG_CF, hcd->regs + HC_CONFIGFLAG);
+	reg_write32(hcd->regs, HC_CONFIGFLAG, FLAG_CF);
 
-	retval = handshake(priv, hcd->regs + HC_CONFIGFLAG, FLAG_CF, FLAG_CF,
-			250 * 1000);
+	retval = handshake(hcd, HC_CONFIGFLAG, FLAG_CF, FLAG_CF, 250 * 1000);
 	up_write(&ehci_cf_port_reset_rwsem);
 	if (retval)
 		return retval;
 
-	chipid = isp1760_readl(hcd->regs + HC_CHIP_ID_REG);
-	isp1760_info(priv, "USB ISP %04x HW rev. %d started\n",	chipid & 0xffff,
-			chipid >> 16);
+	chipid = reg_read32(hcd->regs, HC_CHIP_ID_REG);
+	dev_info(hcd->self.controller, "USB ISP %04x HW rev. %d started\n",
+					chipid & 0xffff, chipid >> 16);
 
 	/* PTD Register Init Part 2, Step 28 */
 	/* enable INTs */
@@ -532,160 +586,156 @@ static u32 base_to_chip(u32 base)
 	return ((base - 0x400) >> 3);
 }
 
-static void transform_into_atl(struct isp1760_hcd *priv, struct isp1760_qh *qh,
-			struct isp1760_qtd *qtd, struct urb *urb,
-			u32 payload, struct ptd *ptd)
+static int last_qtd_of_urb(struct isp1760_qtd *qtd, struct isp1760_qh *qh)
+{
+	struct urb *urb;
+
+	if (list_is_last(&qtd->qtd_list, &qh->qtd_list))
+		return 1;
+
+	urb = qtd->urb;
+	qtd = list_entry(qtd->qtd_list.next, typeof(*qtd), qtd_list);
+	return (qtd->urb != urb);
+}
+
+static void transform_into_atl(struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct ptd *ptd)
 {
-	u32 dw0;
-	u32 dw1;
-	u32 dw2;
-	u32 dw3;
 	u32 maxpacket;
 	u32 multi;
 	u32 pid_code;
 	u32 rl = RL_COUNTER;
 	u32 nak = NAK_COUNTER;
 
+	memset(ptd, 0, sizeof(*ptd));
+
 	/* according to 3.6.2, max packet len can not be > 0x400 */
-	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	maxpacket = usb_maxpacket(qtd->urb->dev, qtd->urb->pipe,
+						usb_pipeout(qtd->urb->pipe));
 	multi =  1 + ((maxpacket >> 11) & 0x3);
 	maxpacket &= 0x7ff;
 
 	/* DW0 */
-	dw0 = PTD_VALID;
-	dw0 |= PTD_LENGTH(qtd->length);
-	dw0 |= PTD_MAXPACKET(maxpacket);
-	dw0 |= PTD_ENDPOINT(usb_pipeendpoint(urb->pipe));
-	dw1 = usb_pipeendpoint(urb->pipe) >> 1;
+	ptd->dw0 = PTD_VALID;
+	ptd->dw0 |= PTD_LENGTH(qtd->length);
+	ptd->dw0 |= PTD_MAXPACKET(maxpacket);
+	ptd->dw0 |= PTD_ENDPOINT(usb_pipeendpoint(qtd->urb->pipe));
 
 	/* DW1 */
-	dw1 |= PTD_DEVICE_ADDR(usb_pipedevice(urb->pipe));
+	ptd->dw1 = usb_pipeendpoint(qtd->urb->pipe) >> 1;
+	ptd->dw1 |= PTD_DEVICE_ADDR(usb_pipedevice(qtd->urb->pipe));
 
 	pid_code = qtd->packet_type;
-	dw1 |= PTD_PID_TOKEN(pid_code);
+	ptd->dw1 |= PTD_PID_TOKEN(pid_code);
 
-	if (usb_pipebulk(urb->pipe))
-		dw1 |= PTD_TRANS_BULK;
-	else if  (usb_pipeint(urb->pipe))
-		dw1 |= PTD_TRANS_INT;
+	if (usb_pipebulk(qtd->urb->pipe))
+		ptd->dw1 |= PTD_TRANS_BULK;
+	else if  (usb_pipeint(qtd->urb->pipe))
+		ptd->dw1 |= PTD_TRANS_INT;
 
-	if (urb->dev->speed != USB_SPEED_HIGH) {
+	if (qtd->urb->dev->speed != USB_SPEED_HIGH) {
 		/* split transaction */
 
-		dw1 |= PTD_TRANS_SPLIT;
-		if (urb->dev->speed == USB_SPEED_LOW)
-			dw1 |= PTD_SE_USB_LOSPEED;
+		ptd->dw1 |= PTD_TRANS_SPLIT;
+		if (qtd->urb->dev->speed == USB_SPEED_LOW)
+			ptd->dw1 |= PTD_SE_USB_LOSPEED;
 
-		dw1 |= PTD_PORT_NUM(urb->dev->ttport);
-		dw1 |= PTD_HUB_NUM(urb->dev->tt->hub->devnum);
+		ptd->dw1 |= PTD_PORT_NUM(qtd->urb->dev->ttport);
+		ptd->dw1 |= PTD_HUB_NUM(qtd->urb->dev->tt->hub->devnum);
 
 		/* SE bit for Split INT transfers */
-		if (usb_pipeint(urb->pipe) &&
-				(urb->dev->speed == USB_SPEED_LOW))
-			dw1 |= 2 << 16;
+		if (usb_pipeint(qtd->urb->pipe) &&
+				(qtd->urb->dev->speed == USB_SPEED_LOW))
+			ptd->dw1 |= 2 << 16;
 
-		dw3 = 0;
+		ptd->dw3 = 0;
 		rl = 0;
 		nak = 0;
 	} else {
-		dw0 |= PTD_MULTI(multi);
-		if (usb_pipecontrol(urb->pipe) || usb_pipebulk(urb->pipe))
-			dw3 = qh->ping;
+		ptd->dw0 |= PTD_MULTI(multi);
+		if (usb_pipecontrol(qtd->urb->pipe) ||
+						usb_pipebulk(qtd->urb->pipe))
+			ptd->dw3 = qh->ping;
 		else
-			dw3 = 0;
+			ptd->dw3 = 0;
 	}
 	/* DW2 */
-	dw2 = 0;
-	dw2 |= PTD_DATA_START_ADDR(base_to_chip(payload));
-	dw2 |= PTD_RL_CNT(rl);
-	dw3 |= PTD_NAC_CNT(nak);
+	ptd->dw2 = 0;
+	ptd->dw2 |= PTD_DATA_START_ADDR(base_to_chip(qtd->payload_addr));
+	ptd->dw2 |= PTD_RL_CNT(rl);
+	ptd->dw3 |= PTD_NAC_CNT(nak);
 
 	/* DW3 */
-	if (usb_pipecontrol(urb->pipe))
-		dw3 |= PTD_DATA_TOGGLE(qtd->toggle);
-	else
-		dw3 |= qh->toggle;
-
+	ptd->dw3 |= qh->toggle;
+	if (usb_pipecontrol(qtd->urb->pipe)) {
+		if (qtd->data_buffer == qtd->urb->setup_packet)
+			ptd->dw3 &= ~PTD_DATA_TOGGLE(1);
+		else if (last_qtd_of_urb(qtd, qh))
+			ptd->dw3 |= PTD_DATA_TOGGLE(1);
+	}
 
-	dw3 |= PTD_ACTIVE;
+	ptd->dw3 |= PTD_ACTIVE;
 	/* Cerr */
-	dw3 |= PTD_CERR(ERR_COUNTER);
-
-	memset(ptd, 0, sizeof(*ptd));
-
-	ptd->dw0 = cpu_to_le32(dw0);
-	ptd->dw1 = cpu_to_le32(dw1);
-	ptd->dw2 = cpu_to_le32(dw2);
-	ptd->dw3 = cpu_to_le32(dw3);
+	ptd->dw3 |= PTD_CERR(ERR_COUNTER);
 }
 
-static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
-			struct isp1760_qtd *qtd, struct urb *urb,
-			u32 payload, struct ptd *ptd)
+static void transform_add_int(struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct ptd *ptd)
 {
-	u32 maxpacket;
-	u32 multi;
-	u32 numberofusofs;
-	u32 i;
-	u32 usofmask, usof;
+	u32 usof;
 	u32 period;
 
-	maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	multi =  1 + ((maxpacket >> 11) & 0x3);
-	maxpacket &= 0x7ff;
-	/* length of the data per uframe */
-	maxpacket = multi * maxpacket;
-
-	numberofusofs = urb->transfer_buffer_length / maxpacket;
-	if (urb->transfer_buffer_length % maxpacket)
-		numberofusofs += 1;
-
-	usofmask = 1;
-	usof = 0;
-	for (i = 0; i < numberofusofs; i++) {
-		usof |= usofmask;
-		usofmask <<= 1;
-	}
-
-	if (urb->dev->speed != USB_SPEED_HIGH) {
-		/* split */
-		ptd->dw5 = cpu_to_le32(0x1c);
+	/*
+	 * Most of this is guessing. ISP1761 datasheet is quite unclear, and
+	 * the algorithm from the original Philips driver code, which was
+	 * pretty much used in this driver before as well, is quite horrendous
+	 * and, i believe, incorrect. The code below follows the datasheet and
+	 * USB2.0 spec as far as I can tell, and plug/unplug seems to be much
+	 * more reliable this way (fingers crossed...).
+	 */
 
-		if (qh->period >= 32)
-			period = qh->period / 2;
+	if (qtd->urb->dev->speed == USB_SPEED_HIGH) {
+		/* urb->interval is in units of microframes (1/8 ms) */
+		period = qtd->urb->interval >> 3;
+
+		if (qtd->urb->interval > 4)
+			usof = 0x01; /* One bit set =>
+						interval 1 ms * uFrame-match */
+		else if (qtd->urb->interval > 2)
+			usof = 0x22; /* Two bits set => interval 1/2 ms */
+		else if (qtd->urb->interval > 1)
+			usof = 0x55; /* Four bits set => interval 1/4 ms */
 		else
-			period = qh->period;
-
+			usof = 0xff; /* All bits set => interval 1/8 ms */
 	} else {
+		/* urb->interval is in units of frames (1 ms) */
+		period = qtd->urb->interval;
+		usof = 0x0f;		/* Execute Start Split on any of the
+					   four first uFrames */
 
-		if (qh->period >= 8)
-			period = qh->period/8;
-		else
-			period = qh->period;
-
-		if (period >= 32)
-			period  = 16;
-
-		if (qh->period >= 8) {
-			/* millisecond period */
-			period = (period << 3);
-		} else {
-			/* usof based tranmsfers */
-			/* minimum 4 usofs */
-			usof = 0x11;
-		}
+		/*
+		 * First 8 bits in dw5 is uSCS and "specifies which uSOF the
+		 * complete split needs to be sent. Valid only for IN." Also,
+		 * "All bits can be set to one for every transfer." (p 82,
+		 * ISP1761 data sheet.) 0x1c is from Philips driver. Where did
+		 * that number come from? 0xff seems to work fine...
+		 */
+		/* ptd->dw5 = 0x1c; */
+		ptd->dw5 = 0xff; /* Execute Complete Split on any uFrame */
 	}
 
-	ptd->dw2 |= cpu_to_le32(period);
-	ptd->dw4 = cpu_to_le32(usof);
+	period = period >> 1;/* Ensure equal or shorter period than requested */
+	period &= 0xf8; /* Mask off too large values and lowest unused 3 bits */
+
+	ptd->dw2 |= period;
+	ptd->dw4 = usof;
 }
 
-static void transform_into_int(struct isp1760_hcd *priv, struct isp1760_qh *qh,
-			struct isp1760_qtd *qtd, struct urb *urb,
-			u32 payload, struct ptd *ptd)
+static void transform_into_int(struct isp1760_qh *qh,
+			struct isp1760_qtd *qtd, struct ptd *ptd)
 {
-	transform_into_atl(priv, qh, qtd, urb, payload, ptd);
-	transform_add_int(priv, qh, qtd, urb,  payload, ptd);
+	transform_into_atl(qh, qtd, ptd);
+	transform_add_int(qh, qtd, ptd);
 }
 
 static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
@@ -695,10 +745,9 @@ static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
 
 	qtd->data_buffer = databuffer;
 	qtd->packet_type = GET_QTD_TOKEN_TYPE(token);
-	qtd->toggle = GET_DATA_TOGGLE(token);
 
-	if (len > HC_ATL_PL_SIZE)
-		count = HC_ATL_PL_SIZE;
+	if (len > MAX_PAYLOAD_SIZE)
+		count = MAX_PAYLOAD_SIZE;
 	else
 		count = len;
 
@@ -706,29 +755,27 @@ static int qtd_fill(struct isp1760_qtd *qtd, void *databuffer, size_t len,
 	return count;
 }
 
-static int check_error(struct ptd *ptd)
+static int check_error(struct usb_hcd *hcd, struct ptd *ptd)
 {
 	int error = 0;
-	u32 dw3;
 
-	dw3 = le32_to_cpu(ptd->dw3);
-	if (dw3 & DW3_HALT_BIT) {
+	if (ptd->dw3 & DW3_HALT_BIT) {
 		error = -EPIPE;
 
-		if (dw3 & DW3_ERROR_BIT)
+		if (ptd->dw3 & DW3_ERROR_BIT)
 			pr_err("error bit is set in DW3\n");
 	}
 
-	if (dw3 & DW3_QTD_ACTIVE) {
-		printk(KERN_ERR "transfer active bit is set DW3\n");
-		printk(KERN_ERR "nak counter: %d, rl: %d\n", (dw3 >> 19) & 0xf,
-				(le32_to_cpu(ptd->dw2) >> 25) & 0xf);
+	if (ptd->dw3 & DW3_QTD_ACTIVE) {
+		dev_err(hcd->self.controller, "Transfer active bit is set DW3\n"
+			"nak counter: %d, rl: %d\n",
+			(ptd->dw3 >> 19) & 0xf, (ptd->dw2 >> 25) & 0xf);
 	}
 
 	return error;
 }
 
-static void check_int_err_status(u32 dw4)
+static void check_int_err_status(struct usb_hcd *hcd, u32 dw4)
 {
 	u32 i;
 
@@ -737,79 +784,67 @@ static void check_int_err_status(u32 dw4)
 	for (i = 0; i < 8; i++) {
 		switch (dw4 & 0x7) {
 		case INT_UNDERRUN:
-			printk(KERN_ERR "ERROR: under run , %d\n", i);
+			dev_err(hcd->self.controller, "Underrun (%d)\n", i);
 			break;
 
 		case INT_EXACT:
-			printk(KERN_ERR "ERROR: transaction error, %d\n", i);
+			dev_err(hcd->self.controller,
+						"Transaction error (%d)\n", i);
 			break;
 
 		case INT_BABBLE:
-			printk(KERN_ERR "ERROR: babble error, %d\n", i);
+			dev_err(hcd->self.controller, "Babble error (%d)\n", i);
 			break;
 		}
 		dw4 >>= 3;
 	}
 }
 
-static void enqueue_one_qtd(struct isp1760_qtd *qtd, struct isp1760_hcd *priv,
-		u32 payload)
+static void enqueue_one_qtd(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
 {
-	u32 token;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
-
-	token = qtd->packet_type;
-
-	if (qtd->length && (qtd->length <= HC_ATL_PL_SIZE)) {
-		switch (token) {
+	if (qtd->length && (qtd->length <= MAX_PAYLOAD_SIZE)) {
+		switch (qtd->packet_type) {
 		case IN_PID:
 			break;
 		case OUT_PID:
 		case SETUP_PID:
-			priv_write_copy(priv, qtd->data_buffer,
-					hcd->regs + payload,
-					qtd->length);
+			mem_writes8(hcd->regs, qtd->payload_addr,
+						qtd->data_buffer, qtd->length);
 		}
 	}
 }
 
-static void enqueue_one_atl_qtd(u32 atl_regs, u32 payload,
-		struct isp1760_hcd *priv, struct isp1760_qh *qh,
-		struct urb *urb, u32 slot, struct isp1760_qtd *qtd)
+static void enqueue_one_atl_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh,
+					u32 slot, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct ptd ptd;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
 
-	transform_into_atl(priv, qh, qtd, urb, payload, &ptd);
-	priv_write_copy(priv, (u32 *)&ptd, hcd->regs + atl_regs, sizeof(ptd));
-	enqueue_one_qtd(qtd, priv, payload);
+	alloc_mem(hcd, qtd);
+	transform_into_atl(qh, qtd, &ptd);
+	ptd_write(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+	enqueue_one_qtd(hcd, qtd);
 
-	priv->atl_ints[slot].urb = urb;
 	priv->atl_ints[slot].qh = qh;
 	priv->atl_ints[slot].qtd = qtd;
-	priv->atl_ints[slot].data_buffer = qtd->data_buffer;
-	priv->atl_ints[slot].payload = payload;
-	qtd->status |= URB_ENQUEUED | URB_TYPE_ATL;
+	qtd->status |= URB_ENQUEUED;
 	qtd->status |= slot << 16;
 }
 
-static void enqueue_one_int_qtd(u32 int_regs, u32 payload,
-		struct isp1760_hcd *priv, struct isp1760_qh *qh,
-		struct urb *urb, u32 slot,  struct isp1760_qtd *qtd)
+static void enqueue_one_int_qtd(struct usb_hcd *hcd, struct isp1760_qh *qh,
+					u32 slot, struct isp1760_qtd *qtd)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct ptd ptd;
-	struct usb_hcd *hcd = priv_to_hcd(priv);
 
-	transform_into_int(priv, qh, qtd, urb, payload, &ptd);
-	priv_write_copy(priv, (u32 *)&ptd, hcd->regs + int_regs, sizeof(ptd));
-	enqueue_one_qtd(qtd, priv, payload);
+	alloc_mem(hcd, qtd);
+	transform_into_int(qh, qtd, &ptd);
+	ptd_write(hcd->regs, INT_PTD_OFFSET, slot, &ptd);
+	enqueue_one_qtd(hcd, qtd);
 
-	priv->int_ints[slot].urb = urb;
 	priv->int_ints[slot].qh = qh;
 	priv->int_ints[slot].qtd = qtd;
-	priv->int_ints[slot].data_buffer = qtd->data_buffer;
-	priv->int_ints[slot].payload = payload;
-	qtd->status |= URB_ENQUEUED | URB_TYPE_INT;
+	qtd->status |= URB_ENQUEUED;
 	qtd->status |= slot << 16;
 }
 
@@ -818,9 +853,7 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 skip_map, or_map;
-	u32 queue_entry;
 	u32 slot;
-	u32 atl_regs, payload;
 	u32 buffstatus;
 
 	/*
@@ -831,38 +864,35 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 	 */
 	mmiowb();
 	ndelay(195);
-	skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
 
 	BUG_ON(!skip_map);
 	slot = __ffs(skip_map);
-	queue_entry = 1 << slot;
-
-	atl_regs = ATL_REGS_OFFSET + slot * sizeof(struct ptd);
 
-	payload = alloc_mem(priv, qtd->length);
+	enqueue_one_atl_qtd(hcd, qh, slot, qtd);
 
-	enqueue_one_atl_qtd(atl_regs, payload, priv, qh, qtd->urb, slot, qtd);
+	or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG);
+	or_map |= (1 << slot);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map);
 
-	or_map = isp1760_readl(hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
-	or_map |= queue_entry;
-	isp1760_writel(or_map, hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	skip_map &= ~(1 << slot);
+	reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
 
-	skip_map &= ~queue_entry;
-	isp1760_writel(skip_map, hcd->regs + HC_ATL_PTD_SKIPMAP_REG);
+	priv->atl_queued++;
+	if (priv->atl_queued == 2)
+		reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
+				INTERRUPT_ENABLE_SOT_MASK);
 
-	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
+	buffstatus = reg_read32(hcd->regs, HC_BUFFER_STATUS_REG);
 	buffstatus |= ATL_BUFFER;
-	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
+	reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, buffstatus);
 }
 
 static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 				  struct isp1760_qtd *qtd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 skip_map, or_map;
-	u32 queue_entry;
 	u32 slot;
-	u32 int_regs, payload;
 	u32 buffstatus;
 
 	/*
@@ -873,37 +903,34 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh,
 	 */
 	mmiowb();
 	ndelay(195);
-	skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
 
 	BUG_ON(!skip_map);
 	slot = __ffs(skip_map);
-	queue_entry = 1 << slot;
-
-	int_regs = INT_REGS_OFFSET + slot * sizeof(struct ptd);
 
-	payload = alloc_mem(priv, qtd->length);
+	enqueue_one_int_qtd(hcd, qh, slot, qtd);
 
-	enqueue_one_int_qtd(int_regs, payload, priv, qh, qtd->urb, slot, qtd);
+	or_map = reg_read32(hcd->regs, HC_INT_IRQ_MASK_OR_REG);
+	or_map |= (1 << slot);
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, or_map);
 
-	or_map = isp1760_readl(hcd->regs + HC_INT_IRQ_MASK_OR_REG);
-	or_map |= queue_entry;
-	isp1760_writel(or_map, hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	skip_map &= ~(1 << slot);
+	reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
 
-	skip_map &= ~queue_entry;
-	isp1760_writel(skip_map, hcd->regs + HC_INT_PTD_SKIPMAP_REG);
-
-	buffstatus = isp1760_readl(hcd->regs + HC_BUFFER_STATUS_REG);
+	buffstatus = reg_read32(hcd->regs, HC_BUFFER_STATUS_REG);
 	buffstatus |= INT_BUFFER;
-	isp1760_writel(buffstatus, hcd->regs + HC_BUFFER_STATUS_REG);
+	reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, buffstatus);
 }
 
-static void isp1760_urb_done(struct isp1760_hcd *priv, struct urb *urb, int status)
+static void isp1760_urb_done(struct usb_hcd *hcd, struct urb *urb)
 __releases(priv->lock)
 __acquires(priv->lock)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
+
 	if (!urb->unlinked) {
-		if (status == -EINPROGRESS)
-			status = 0;
+		if (urb->status == -EINPROGRESS)
+			urb->status = 0;
 	}
 
 	if (usb_pipein(urb->pipe) && usb_pipetype(urb->pipe) != PIPE_CONTROL) {
@@ -915,22 +942,28 @@ __acquires(priv->lock)
 	}
 
 	/* complete() can reenter this HCD */
-	usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
+	usb_hcd_unlink_urb_from_ep(hcd, urb);
 	spin_unlock(&priv->lock);
-	usb_hcd_giveback_urb(priv_to_hcd(priv), urb, status);
+	usb_hcd_giveback_urb(hcd, urb, urb->status);
 	spin_lock(&priv->lock);
 }
 
 static void isp1760_qtd_free(struct isp1760_qtd *qtd)
 {
+	BUG_ON(qtd->payload_addr);
 	kmem_cache_free(qtd_cachep, qtd);
 }
 
-static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd)
+static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd,
+							struct isp1760_qh *qh)
 {
 	struct isp1760_qtd *tmp_qtd;
 
-	tmp_qtd = qtd->hw_next;
+	if (list_is_last(&qtd->qtd_list, &qh->qtd_list))
+		tmp_qtd = NULL;
+	else
+		tmp_qtd = list_entry(qtd->qtd_list.next, struct isp1760_qtd,
+								qtd_list);
 	list_del(&qtd->qtd_list);
 	isp1760_qtd_free(qtd);
 	return tmp_qtd;
@@ -941,32 +974,26 @@ static struct isp1760_qtd *clean_this_qtd(struct isp1760_qtd *qtd)
  * isn't the last one than remove also his successor(s).
  * Returns the QTD which is part of an new URB and should be enqueued.
  */
-static struct isp1760_qtd *clean_up_qtdlist(struct isp1760_qtd *qtd)
+static struct isp1760_qtd *clean_up_qtdlist(struct isp1760_qtd *qtd,
+							struct isp1760_qh *qh)
 {
-	struct isp1760_qtd *tmp_qtd;
-	int last_one;
+	struct urb *urb;
 
+	urb = qtd->urb;
 	do {
-		tmp_qtd = qtd->hw_next;
-		last_one = qtd->status & URB_COMPLETE_NOTIFY;
-		list_del(&qtd->qtd_list);
-		isp1760_qtd_free(qtd);
-		qtd = tmp_qtd;
-	} while (!last_one && qtd);
+		qtd = clean_this_qtd(qtd, qh);
+	} while (qtd && (qtd->urb == urb));
 
 	return qtd;
 }
 
-static void do_atl_int(struct usb_hcd *usb_hcd)
+static void do_atl_int(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 done_map, skip_map;
 	struct ptd ptd;
-	struct urb *urb = NULL;
-	u32 atl_regs_base;
-	u32 atl_regs;
-	u32 queue_entry;
-	u32 payload;
+	struct urb *urb;
+	u32 slot;
 	u32 length;
 	u32 or_map;
 	u32 status = -EINVAL;
@@ -976,62 +1003,36 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 	u32 rl;
 	u32 nakcount;
 
-	done_map = isp1760_readl(usb_hcd->regs +
-			HC_ATL_PTD_DONEMAP_REG);
-	skip_map = isp1760_readl(usb_hcd->regs +
-			HC_ATL_PTD_SKIPMAP_REG);
+	done_map = reg_read32(hcd->regs, HC_ATL_PTD_DONEMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
 
-	or_map = isp1760_readl(usb_hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG);
 	or_map &= ~done_map;
-	isp1760_writel(or_map, usb_hcd->regs + HC_ATL_IRQ_MASK_OR_REG);
+	reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map);
 
-	atl_regs_base = ATL_REGS_OFFSET;
 	while (done_map) {
-		u32 dw1;
-		u32 dw2;
-		u32 dw3;
-
 		status = 0;
+		priv->atl_queued--;
 
-		queue_entry = __ffs(done_map);
-		done_map &= ~(1 << queue_entry);
-		skip_map |= 1 << queue_entry;
-
-		atl_regs = atl_regs_base + queue_entry * sizeof(struct ptd);
+		slot = __ffs(done_map);
+		done_map &= ~(1 << slot);
+		skip_map |= (1 << slot);
 
-		urb = priv->atl_ints[queue_entry].urb;
-		qtd = priv->atl_ints[queue_entry].qtd;
-		qh = priv->atl_ints[queue_entry].qh;
-		payload = priv->atl_ints[queue_entry].payload;
+		qtd = priv->atl_ints[slot].qtd;
+		qh = priv->atl_ints[slot].qh;
 
 		if (!qh) {
-			printk(KERN_ERR "qh is 0\n");
+			dev_err(hcd->self.controller, "qh is 0\n");
 			continue;
 		}
-		isp1760_writel(atl_regs + ISP_BANK(0), usb_hcd->regs +
-				HC_MEMORY_REG);
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
-		/*
-		 * write bank1 address twice to ensure the 90ns delay (time
-		 * between BANK0 write and the priv_read_copy() call is at
-		 * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns)
-		 */
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
+		ptd_read(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
 
-		priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs +
-				ISP_BANK(0), sizeof(ptd));
-
-		dw1 = le32_to_cpu(ptd.dw1);
-		dw2 = le32_to_cpu(ptd.dw2);
-		dw3 = le32_to_cpu(ptd.dw3);
-		rl = (dw2 >> 25) & 0x0f;
-		nakcount = (dw3 >> 19) & 0xf;
+		rl = (ptd.dw2 >> 25) & 0x0f;
+		nakcount = (ptd.dw3 >> 19) & 0xf;
 
 		/* Transfer Error, *but* active and no HALT -> reload */
-		if ((dw3 & DW3_ERROR_BIT) && (dw3 & DW3_QTD_ACTIVE) &&
-				!(dw3 & DW3_HALT_BIT)) {
+		if ((ptd.dw3 & DW3_ERROR_BIT) && (ptd.dw3 & DW3_QTD_ACTIVE) &&
+				!(ptd.dw3 & DW3_HALT_BIT)) {
 
 			/* according to ppriv code, we have to
 			 * reload this one if trasfered bytes != requested bytes
@@ -1040,13 +1041,14 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 			 * triggered so far.
 			 */
 
-			length = PTD_XFERRED_LENGTH(dw3);
-			printk(KERN_ERR "Should reload now.... transfered %d "
+			length = PTD_XFERRED_LENGTH(ptd.dw3);
+			dev_err(hcd->self.controller,
+					"Should reload now... transferred %d "
 					"of %zu\n", length, qtd->length);
 			BUG();
 		}
 
-		if (!nakcount && (dw3 & DW3_QTD_ACTIVE)) {
+		if (!nakcount && (ptd.dw3 & DW3_QTD_ACTIVE)) {
 			u32 buffstatus;
 
 			/*
@@ -1054,52 +1056,45 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 			 * device is not able to send data fast enough.
 			 * This happens mostly on slower hardware.
 			 */
-			printk(KERN_NOTICE "Reloading ptd %p/%p... qh %p read: "
-					"%d of %zu done: %08x cur: %08x\n", qtd,
-					urb, qh, PTD_XFERRED_LENGTH(dw3),
-					qtd->length, done_map,
-					(1 << queue_entry));
 
 			/* RL counter = ERR counter */
-			dw3 &= ~(0xf << 19);
-			dw3 |= rl << 19;
-			dw3 &= ~(3 << (55 - 32));
-			dw3 |= ERR_COUNTER << (55 - 32);
+			ptd.dw3 &= ~(0xf << 19);
+			ptd.dw3 |= rl << 19;
+			ptd.dw3 &= ~(3 << (55 - 32));
+			ptd.dw3 |= ERR_COUNTER << (55 - 32);
 
 			/*
 			 * It is not needed to write skip map back because it
 			 * is unchanged. Just make sure that this entry is
 			 * unskipped once it gets written to the HW.
 			 */
-			skip_map &= ~(1 << queue_entry);
-			or_map = isp1760_readl(usb_hcd->regs +
-					HC_ATL_IRQ_MASK_OR_REG);
-			or_map |= 1 << queue_entry;
-			isp1760_writel(or_map, usb_hcd->regs +
-					HC_ATL_IRQ_MASK_OR_REG);
-
-			ptd.dw3 = cpu_to_le32(dw3);
-			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
-					atl_regs, sizeof(ptd));
-
-			ptd.dw0 |= cpu_to_le32(PTD_VALID);
-			priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs +
-					atl_regs, sizeof(ptd));
-
-			buffstatus = isp1760_readl(usb_hcd->regs +
-					HC_BUFFER_STATUS_REG);
+			skip_map &= ~(1 << slot);
+			or_map = reg_read32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG);
+			or_map |= 1 << slot;
+			reg_write32(hcd->regs, HC_ATL_IRQ_MASK_OR_REG, or_map);
+
+			ptd.dw0 |= PTD_VALID;
+			ptd_write(hcd->regs, ATL_PTD_OFFSET, slot, &ptd);
+
+			priv->atl_queued++;
+			if (priv->atl_queued == 2)
+				reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
+						INTERRUPT_ENABLE_SOT_MASK);
+
+			buffstatus = reg_read32(hcd->regs,
+							HC_BUFFER_STATUS_REG);
 			buffstatus |= ATL_BUFFER;
-			isp1760_writel(buffstatus, usb_hcd->regs +
-					HC_BUFFER_STATUS_REG);
+			reg_write32(hcd->regs, HC_BUFFER_STATUS_REG,
+								buffstatus);
 			continue;
 		}
 
-		error = check_error(&ptd);
+		error = check_error(hcd, &ptd);
 		if (error) {
 			status = error;
-			priv->atl_ints[queue_entry].qh->toggle = 0;
-			priv->atl_ints[queue_entry].qh->ping = 0;
-			urb->status = -EPIPE;
+			priv->atl_ints[slot].qh->toggle = 0;
+			priv->atl_ints[slot].qh->ping = 0;
+			qtd->urb->status = -EPIPE;
 
 #if 0
 			printk(KERN_ERR "Error in %s().\n", __func__);
@@ -1110,154 +1105,123 @@ static void do_atl_int(struct usb_hcd *usb_hcd)
 					ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7);
 #endif
 		} else {
-			if (usb_pipetype(urb->pipe) == PIPE_BULK) {
-				priv->atl_ints[queue_entry].qh->toggle = dw3 &
-					(1 << 25);
-				priv->atl_ints[queue_entry].qh->ping = dw3 &
-					(1 << 26);
-			}
+			priv->atl_ints[slot].qh->toggle = ptd.dw3 & (1 << 25);
+			priv->atl_ints[slot].qh->ping = ptd.dw3 & (1 << 26);
 		}
 
-		length = PTD_XFERRED_LENGTH(dw3);
+		length = PTD_XFERRED_LENGTH(ptd.dw3);
 		if (length) {
-			switch (DW1_GET_PID(dw1)) {
+			switch (DW1_GET_PID(ptd.dw1)) {
 			case IN_PID:
-				priv_read_copy(priv,
-					priv->atl_ints[queue_entry].data_buffer,
-					usb_hcd->regs + payload + ISP_BANK(1),
-					length);
+				mem_reads8(hcd->regs, qtd->payload_addr,
+						qtd->data_buffer, length);
 
 			case OUT_PID:
 
-				urb->actual_length += length;
+				qtd->urb->actual_length += length;
 
 			case SETUP_PID:
 				break;
 			}
 		}
 
-		priv->atl_ints[queue_entry].data_buffer = NULL;
-		priv->atl_ints[queue_entry].urb = NULL;
-		priv->atl_ints[queue_entry].qtd = NULL;
-		priv->atl_ints[queue_entry].qh = NULL;
+		priv->atl_ints[slot].qtd = NULL;
+		priv->atl_ints[slot].qh = NULL;
 
-		free_mem(priv, payload);
+		free_mem(hcd, qtd);
 
-		isp1760_writel(skip_map, usb_hcd->regs +
-				HC_ATL_PTD_SKIPMAP_REG);
+		reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, skip_map);
 
-		if (urb->status == -EPIPE) {
+		if (qtd->urb->status == -EPIPE) {
 			/* HALT was received */
 
-			qtd = clean_up_qtdlist(qtd);
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
-		} else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) {
+		} else if (usb_pipebulk(qtd->urb->pipe) &&
+						(length < qtd->length)) {
 			/* short BULK received */
 
-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				urb->status = -EREMOTEIO;
-				isp1760_dbg(priv, "short bulk, %d instead %zu "
-					"with URB_SHORT_NOT_OK flag.\n",
-					length, qtd->length);
+			if (qtd->urb->transfer_flags & URB_SHORT_NOT_OK) {
+				qtd->urb->status = -EREMOTEIO;
+				dev_dbg(hcd->self.controller,
+						"short bulk, %d instead %zu "
+						"with URB_SHORT_NOT_OK flag.\n",
+						length, qtd->length);
 			}
 
-			if (urb->status == -EINPROGRESS)
-				urb->status = 0;
-
-			qtd = clean_up_qtdlist(qtd);
+			if (qtd->urb->status == -EINPROGRESS)
+				qtd->urb->status = 0;
 
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
-		} else if (qtd->status & URB_COMPLETE_NOTIFY) {
+		} else if (last_qtd_of_urb(qtd, qh)) {
 			/* that was the last qtd of that URB */
 
-			if (urb->status == -EINPROGRESS)
-				urb->status = 0;
+			if (qtd->urb->status == -EINPROGRESS)
+				qtd->urb->status = 0;
 
-			qtd = clean_this_qtd(qtd);
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
 		} else {
 			/* next QTD of this URB */
 
-			qtd = clean_this_qtd(qtd);
+			qtd = clean_this_qtd(qtd, qh);
 			BUG_ON(!qtd);
 		}
 
 		if (qtd)
-			enqueue_an_ATL_packet(usb_hcd, qh, qtd);
+			enqueue_an_ATL_packet(hcd, qh, qtd);
 
-		skip_map = isp1760_readl(usb_hcd->regs +
-				HC_ATL_PTD_SKIPMAP_REG);
+		skip_map = reg_read32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG);
 	}
+	if (priv->atl_queued <= 1)
+		reg_write32(hcd->regs, HC_INTERRUPT_ENABLE,
+							INTERRUPT_ENABLE_MASK);
 }
 
-static void do_intl_int(struct usb_hcd *usb_hcd)
+static void do_intl_int(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 done_map, skip_map;
 	struct ptd ptd;
-	struct urb *urb = NULL;
-	u32 int_regs;
-	u32 int_regs_base;
-	u32 payload;
+	struct urb *urb;
 	u32 length;
 	u32 or_map;
 	int error;
-	u32 queue_entry;
+	u32 slot;
 	struct isp1760_qtd *qtd;
 	struct isp1760_qh *qh;
 
-	done_map = isp1760_readl(usb_hcd->regs +
-			HC_INT_PTD_DONEMAP_REG);
-	skip_map = isp1760_readl(usb_hcd->regs +
-			HC_INT_PTD_SKIPMAP_REG);
+	done_map = reg_read32(hcd->regs, HC_INT_PTD_DONEMAP_REG);
+	skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
 
-	or_map = isp1760_readl(usb_hcd->regs + HC_INT_IRQ_MASK_OR_REG);
+	or_map = reg_read32(hcd->regs, HC_INT_IRQ_MASK_OR_REG);
 	or_map &= ~done_map;
-	isp1760_writel(or_map, usb_hcd->regs + HC_INT_IRQ_MASK_OR_REG);
-
-	int_regs_base = INT_REGS_OFFSET;
+	reg_write32(hcd->regs, HC_INT_IRQ_MASK_OR_REG, or_map);
 
 	while (done_map) {
-		u32 dw1;
-		u32 dw3;
+		slot = __ffs(done_map);
+		done_map &= ~(1 << slot);
+		skip_map |= (1 << slot);
 
-		queue_entry = __ffs(done_map);
-		done_map &= ~(1 << queue_entry);
-		skip_map |= 1 << queue_entry;
-
-		int_regs = int_regs_base + queue_entry * sizeof(struct ptd);
-		urb = priv->int_ints[queue_entry].urb;
-		qtd = priv->int_ints[queue_entry].qtd;
-		qh = priv->int_ints[queue_entry].qh;
-		payload = priv->int_ints[queue_entry].payload;
+		qtd = priv->int_ints[slot].qtd;
+		qh = priv->int_ints[slot].qh;
 
 		if (!qh) {
-			printk(KERN_ERR "(INT) qh is 0\n");
+			dev_err(hcd->self.controller, "(INT) qh is 0\n");
 			continue;
 		}
 
-		isp1760_writel(int_regs + ISP_BANK(0), usb_hcd->regs +
-				HC_MEMORY_REG);
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
-		/*
-		 * write bank1 address twice to ensure the 90ns delay (time
-		 * between BANK0 write and the priv_read_copy() call is at
-		 * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns)
-		 */
-		isp1760_writel(payload  + ISP_BANK(1), usb_hcd->regs +
-				HC_MEMORY_REG);
+		ptd_read(hcd->regs, INT_PTD_OFFSET, slot, &ptd);
+		check_int_err_status(hcd, ptd.dw4);
 
-		priv_read_copy(priv, (u32 *)&ptd, usb_hcd->regs + int_regs +
-				ISP_BANK(0), sizeof(ptd));
-		dw1 = le32_to_cpu(ptd.dw1);
-		dw3 = le32_to_cpu(ptd.dw3);
-		check_int_err_status(le32_to_cpu(ptd.dw4));
-
-		error = check_error(&ptd);
+		error = check_error(hcd, &ptd);
 		if (error) {
 #if 0
 			printk(KERN_ERR "Error in %s().\n", __func__);
@@ -1267,83 +1231,77 @@ static void do_intl_int(struct usb_hcd *usb_hcd)
 					ptd.dw0, ptd.dw1, ptd.dw2, ptd.dw3,
 					ptd.dw4, ptd.dw5, ptd.dw6, ptd.dw7);
 #endif
-			urb->status = -EPIPE;
-			priv->int_ints[queue_entry].qh->toggle = 0;
-			priv->int_ints[queue_entry].qh->ping = 0;
+			qtd->urb->status = -EPIPE;
+			priv->int_ints[slot].qh->toggle = 0;
+			priv->int_ints[slot].qh->ping = 0;
 
 		} else {
-			priv->int_ints[queue_entry].qh->toggle =
-				dw3 & (1 << 25);
-			priv->int_ints[queue_entry].qh->ping = dw3 & (1 << 26);
+			priv->int_ints[slot].qh->toggle = ptd.dw3 & (1 << 25);
+			priv->int_ints[slot].qh->ping = ptd.dw3 & (1 << 26);
 		}
 
-		if (urb->dev->speed != USB_SPEED_HIGH)
-			length = PTD_XFERRED_LENGTH_LO(dw3);
+		if (qtd->urb->dev->speed != USB_SPEED_HIGH)
+			length = PTD_XFERRED_LENGTH_LO(ptd.dw3);
 		else
-			length = PTD_XFERRED_LENGTH(dw3);
+			length = PTD_XFERRED_LENGTH(ptd.dw3);
 
 		if (length) {
-			switch (DW1_GET_PID(dw1)) {
+			switch (DW1_GET_PID(ptd.dw1)) {
 			case IN_PID:
-				priv_read_copy(priv,
-					priv->int_ints[queue_entry].data_buffer,
-					usb_hcd->regs + payload + ISP_BANK(1),
-					length);
+				mem_reads8(hcd->regs, qtd->payload_addr,
+						qtd->data_buffer, length);
 			case OUT_PID:
 
-				urb->actual_length += length;
+				qtd->urb->actual_length += length;
 
 			case SETUP_PID:
 				break;
 			}
 		}
 
-		priv->int_ints[queue_entry].data_buffer = NULL;
-		priv->int_ints[queue_entry].urb = NULL;
-		priv->int_ints[queue_entry].qtd = NULL;
-		priv->int_ints[queue_entry].qh = NULL;
+		priv->int_ints[slot].qtd = NULL;
+		priv->int_ints[slot].qh = NULL;
 
-		isp1760_writel(skip_map, usb_hcd->regs +
-				HC_INT_PTD_SKIPMAP_REG);
-		free_mem(priv, payload);
+		reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, skip_map);
+		free_mem(hcd, qtd);
 
-		if (urb->status == -EPIPE) {
+		if (qtd->urb->status == -EPIPE) {
 			/* HALT received */
 
-			 qtd = clean_up_qtdlist(qtd);
-			 isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
-		} else if (qtd->status & URB_COMPLETE_NOTIFY) {
+		} else if (last_qtd_of_urb(qtd, qh)) {
 
-			if (urb->status == -EINPROGRESS)
-				urb->status = 0;
+			if (qtd->urb->status == -EINPROGRESS)
+				qtd->urb->status = 0;
 
-			qtd = clean_this_qtd(qtd);
-			isp1760_urb_done(priv, urb, urb->status);
+			urb = qtd->urb;
+			qtd = clean_up_qtdlist(qtd, qh);
+			isp1760_urb_done(hcd, urb);
 
 		} else {
 			/* next QTD of this URB */
 
-			qtd = clean_this_qtd(qtd);
+			qtd = clean_this_qtd(qtd, qh);
 			BUG_ON(!qtd);
 		}
 
 		if (qtd)
-			enqueue_an_INT_packet(usb_hcd, qh, qtd);
+			enqueue_an_INT_packet(hcd, qh, qtd);
 
-		skip_map = isp1760_readl(usb_hcd->regs +
-				HC_INT_PTD_SKIPMAP_REG);
+		skip_map = reg_read32(hcd->regs, HC_INT_PTD_SKIPMAP_REG);
 	}
 }
 
-#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
-static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
+static struct isp1760_qh *qh_make(struct usb_hcd *hcd, struct urb *urb,
 		gfp_t flags)
 {
 	struct isp1760_qh *qh;
 	int is_input, type;
 
-	qh = isp1760_qh_alloc(priv, flags);
+	qh = isp1760_qh_alloc(flags);
 	if (!qh)
 		return qh;
 
@@ -1353,29 +1311,6 @@ static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
 	is_input = usb_pipein(urb->pipe);
 	type = usb_pipetype(urb->pipe);
 
-	if (type == PIPE_INTERRUPT) {
-
-		if (urb->dev->speed == USB_SPEED_HIGH) {
-
-			qh->period = urb->interval >> 3;
-			if (qh->period == 0 && urb->interval != 1) {
-				/* NOTE interval 2 or 4 uframes could work.
-				 * But interval 1 scheduling is simpler, and
-				 * includes high bandwidth.
-				 */
-				printk(KERN_ERR "intr period %d uframes, NYET!",
-						urb->interval);
-				qh_destroy(qh);
-				return NULL;
-			}
-		} else {
-			qh->period = urb->interval;
-		}
-	}
-
-	/* support for tt scheduling, and access to toggles */
-	qh->dev = urb->dev;
-
 	if (!usb_pipecontrol(urb->pipe))
 		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), !is_input,
 				1);
@@ -1388,43 +1323,27 @@ static struct isp1760_qh *qh_make(struct isp1760_hcd *priv, struct urb *urb,
  * Returns null if it can't allocate a QH it needs to.
  * If the QH has TDs (urbs) already, that's great.
  */
-static struct isp1760_qh *qh_append_tds(struct isp1760_hcd *priv,
+static struct isp1760_qh *qh_append_tds(struct usb_hcd *hcd,
 		struct urb *urb, struct list_head *qtd_list, int epnum,
 		void **ptr)
 {
 	struct isp1760_qh *qh;
-	struct isp1760_qtd *qtd;
-	struct isp1760_qtd *prev_qtd;
 
 	qh = (struct isp1760_qh *)*ptr;
 	if (!qh) {
 		/* can't sleep here, we have priv->lock... */
-		qh = qh_make(priv, urb, GFP_ATOMIC);
+		qh = qh_make(hcd, urb, GFP_ATOMIC);
 		if (!qh)
 			return qh;
 		*ptr = qh;
 	}
 
-	qtd = list_entry(qtd_list->next, struct isp1760_qtd,
-			qtd_list);
-	if (!list_empty(&qh->qtd_list))
-		prev_qtd = list_entry(qh->qtd_list.prev,
-				struct isp1760_qtd, qtd_list);
-	else
-		prev_qtd = NULL;
-
 	list_splice(qtd_list, qh->qtd_list.prev);
-	if (prev_qtd) {
-		BUG_ON(prev_qtd->hw_next);
-		prev_qtd->hw_next = qtd;
-	}
 
-	urb->hcpriv = qh;
 	return qh;
 }
 
-static void qtd_list_free(struct isp1760_hcd *priv, struct urb *urb,
-		struct list_head *qtd_list)
+static void qtd_list_free(struct urb *urb, struct list_head *qtd_list)
 {
 	struct list_head *entry, *temp;
 
@@ -1437,9 +1356,10 @@ static void qtd_list_free(struct isp1760_hcd *priv, struct urb *urb,
 	}
 }
 
-static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
+static int isp1760_prepare_enqueue(struct usb_hcd *hcd, struct urb *urb,
 		struct list_head *qtd_list, gfp_t mem_flags, packet_enqueue *p)
 {
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct isp1760_qtd         *qtd;
 	int                     epnum;
 	unsigned long           flags;
@@ -1451,11 +1371,11 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
 	epnum = urb->ep->desc.bEndpointAddress;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) {
+	if (!HCD_HW_ACCESSIBLE(hcd)) {
 		rc = -ESHUTDOWN;
 		goto done;
 	}
-	rc = usb_hcd_link_urb_to_ep(priv_to_hcd(priv), urb);
+	rc = usb_hcd_link_urb_to_ep(hcd, urb);
 	if (rc)
 		goto done;
 
@@ -1465,25 +1385,24 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb,
 	else
 		qh_busy = 0;
 
-	qh = qh_append_tds(priv, urb, qtd_list, epnum, &urb->ep->hcpriv);
+	qh = qh_append_tds(hcd, urb, qtd_list, epnum, &urb->ep->hcpriv);
 	if (!qh) {
-		usb_hcd_unlink_urb_from_ep(priv_to_hcd(priv), urb);
+		usb_hcd_unlink_urb_from_ep(hcd, urb);
 		rc = -ENOMEM;
 		goto done;
 	}
 
 	if (!qh_busy)
-		p(priv_to_hcd(priv), qh, qtd);
+		p(hcd, qh, qtd);
 
 done:
 	spin_unlock_irqrestore(&priv->lock, flags);
 	if (!qh)
-		qtd_list_free(priv, urb, qtd_list);
+		qtd_list_free(urb, qtd_list);
 	return rc;
 }
 
-static struct isp1760_qtd *isp1760_qtd_alloc(struct isp1760_hcd *priv,
-		gfp_t flags)
+static struct isp1760_qtd *isp1760_qtd_alloc(gfp_t flags)
 {
 	struct isp1760_qtd *qtd;
 
@@ -1497,10 +1416,11 @@ static struct isp1760_qtd *isp1760_qtd_alloc(struct isp1760_hcd *priv,
 /*
  * create a list of filled qtds for this URB; won't link into qh.
  */
-static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
+#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
+static struct list_head *qh_urb_transaction(struct usb_hcd *hcd,
 		struct urb *urb, struct list_head *head, gfp_t flags)
 {
-	struct isp1760_qtd *qtd, *qtd_prev;
+	struct isp1760_qtd *qtd;
 	void *buf;
 	int len, maxpacket;
 	int is_input;
@@ -1509,7 +1429,7 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 	/*
 	 * URBs map to sequences of QTDs:  one logical transaction
 	 */
-	qtd = isp1760_qtd_alloc(priv, flags);
+	qtd = isp1760_qtd_alloc(flags);
 	if (!qtd)
 		return NULL;
 
@@ -1529,13 +1449,10 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 				token | SETUP_PID);
 
 		/* ... and always at least one more pid */
-		token ^= DATA_TOGGLE;
-		qtd_prev = qtd;
-		qtd = isp1760_qtd_alloc(priv, flags);
+		qtd = isp1760_qtd_alloc(flags);
 		if (!qtd)
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = qtd;
 		list_add_tail(&qtd->qtd_list, head);
 
 		/* for zero length DATA stages, STATUS is always IN */
@@ -1565,7 +1482,7 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 
 		if (!buf && len) {
 			/* XXX This looks like usb storage / SCSI bug */
-			printk(KERN_ERR "buf is null, dma is %08lx len is %d\n",
+			dev_err(hcd->self.controller, "buf is null, dma is %08lx len is %d\n",
 					(long unsigned)urb->transfer_dma, len);
 			WARN_ON(1);
 		}
@@ -1574,19 +1491,13 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 		len -= this_qtd_len;
 		buf += this_qtd_len;
 
-		/* qh makes control packets use qtd toggle; maybe switch it */
-		if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
-			token ^= DATA_TOGGLE;
-
 		if (len <= 0)
 			break;
 
-		qtd_prev = qtd;
-		qtd = isp1760_qtd_alloc(priv, flags);
+		qtd = isp1760_qtd_alloc(flags);
 		if (!qtd)
 			goto cleanup;
 		qtd->urb = urb;
-		qtd_prev->hw_next = qtd;
 		list_add_tail(&qtd->qtd_list, head);
 	}
 
@@ -1601,20 +1512,16 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 			one_more = 1;
 			/* "in" <--> "out"  */
 			token ^= IN_PID;
-			/* force DATA1 */
-			token |= DATA_TOGGLE;
 		} else if (usb_pipebulk(urb->pipe)
 				&& (urb->transfer_flags & URB_ZERO_PACKET)
 				&& !(urb->transfer_buffer_length % maxpacket)) {
 			one_more = 1;
 		}
 		if (one_more) {
-			qtd_prev = qtd;
-			qtd = isp1760_qtd_alloc(priv, flags);
+			qtd = isp1760_qtd_alloc(flags);
 			if (!qtd)
 				goto cleanup;
 			qtd->urb = urb;
-			qtd_prev->hw_next = qtd;
 			list_add_tail(&qtd->qtd_list, head);
 
 			/* never any data in such packets */
@@ -1622,18 +1529,17 @@ static struct list_head *qh_urb_transaction(struct isp1760_hcd *priv,
 		}
 	}
 
-	qtd->status = URB_COMPLETE_NOTIFY;
+	qtd->status = 0;
 	return head;
 
 cleanup:
-	qtd_list_free(priv, urb, head);
+	qtd_list_free(urb, head);
 	return NULL;
 }
 
 static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 		gfp_t mem_flags)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct list_head qtd_list;
 	packet_enqueue *pe;
 
@@ -1642,29 +1548,27 @@ static int isp1760_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
 	case PIPE_BULK:
-
-		if (!qh_urb_transaction(priv, urb, &qtd_list, mem_flags))
+		if (!qh_urb_transaction(hcd, urb, &qtd_list, mem_flags))
 			return -ENOMEM;
 		pe =  enqueue_an_ATL_packet;
 		break;
 
 	case PIPE_INTERRUPT:
-		if (!qh_urb_transaction(priv, urb, &qtd_list, mem_flags))
+		if (!qh_urb_transaction(hcd, urb, &qtd_list, mem_flags))
 			return -ENOMEM;
 		pe = enqueue_an_INT_packet;
 		break;
 
 	case PIPE_ISOCHRONOUS:
-		printk(KERN_ERR "PIPE_ISOCHRONOUS ain't supported\n");
+		dev_err(hcd->self.controller, "PIPE_ISOCHRONOUS ain't supported\n");
 	default:
 		return -EPIPE;
 	}
 
-	return isp1760_prepare_enqueue(priv, urb, &qtd_list, mem_flags, pe);
+	return isp1760_prepare_enqueue(hcd, urb, &qtd_list, mem_flags, pe);
 }
 
-static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
-		int status)
+static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct inter_packet_info *ints;
@@ -1681,7 +1585,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
 	case PIPE_INTERRUPT:
 		ints = priv->int_ints;
-		reg_base = INT_REGS_OFFSET;
+		reg_base = INT_PTD_OFFSET;
 		or_reg = HC_INT_IRQ_MASK_OR_REG;
 		skip_reg = HC_INT_PTD_SKIPMAP_REG;
 		pe = enqueue_an_INT_packet;
@@ -1689,7 +1593,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 
 	default:
 		ints = priv->atl_ints;
-		reg_base = ATL_REGS_OFFSET;
+		reg_base = ATL_PTD_OFFSET;
 		or_reg = HC_ATL_IRQ_MASK_OR_REG;
 		skip_reg = HC_ATL_PTD_SKIPMAP_REG;
 		pe =  enqueue_an_ATL_packet;
@@ -1700,81 +1604,84 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb,
 	spin_lock_irqsave(&priv->lock, flags);
 
 	for (i = 0; i < 32; i++) {
-		if (ints->urb == urb) {
+		if (!ints[i].qh)
+			continue;
+		BUG_ON(!ints[i].qtd);
+
+		if (ints[i].qtd->urb == urb) {
 			u32 skip_map;
 			u32 or_map;
 			struct isp1760_qtd *qtd;
-			struct isp1760_qh *qh = ints->qh;
+			struct isp1760_qh *qh;
 
-			skip_map = isp1760_readl(hcd->regs + skip_reg);
+			skip_map = reg_read32(hcd->regs, skip_reg);
 			skip_map |= 1 << i;
-			isp1760_writel(skip_map, hcd->regs + skip_reg);
+			reg_write32(hcd->regs, skip_reg, skip_map);
 
-			or_map = isp1760_readl(hcd->regs + or_reg);
+			or_map = reg_read32(hcd->regs, or_reg);
 			or_map &= ~(1 << i);
-			isp1760_writel(or_map, hcd->regs + or_reg);
+			reg_write32(hcd->regs, or_reg, or_map);
+
+			ptd_write(hcd->regs, reg_base, i, &ptd);
 
-			priv_write_copy(priv, (u32 *)&ptd, hcd->regs + reg_base
-					+ i * sizeof(ptd), sizeof(ptd));
-			qtd = ints->qtd;
-			qtd = clean_up_qtdlist(qtd);
+			qtd = ints[i].qtd;
+			qh = ints[i].qh;
 
-			free_mem(priv, ints->payload);
+			free_mem(hcd, qtd);
+			qtd = clean_up_qtdlist(qtd, qh);
 
-			ints->urb = NULL;
-			ints->qh = NULL;
-			ints->qtd = NULL;
-			ints->data_buffer = NULL;
-			ints->payload = 0;
+			ints[i].qh = NULL;
+			ints[i].qtd = NULL;
 
-			isp1760_urb_done(priv, urb, status);
+			isp1760_urb_done(hcd, urb);
 			if (qtd)
 				pe(hcd, qh, qtd);
 			break;
 
-		} else if (ints->qtd) {
-			struct isp1760_qtd *qtd, *prev_qtd = ints->qtd;
+		} else {
+			struct isp1760_qtd *qtd;
 
-			for (qtd = ints->qtd->hw_next; qtd; qtd = qtd->hw_next) {
+			list_for_each_entry(qtd, &ints[i].qtd->qtd_list,
+								qtd_list) {
 				if (qtd->urb == urb) {
-					prev_qtd->hw_next = clean_up_qtdlist(qtd);
-					isp1760_urb_done(priv, urb, status);
+					clean_up_qtdlist(qtd, ints[i].qh);
+					isp1760_urb_done(hcd, urb);
+					qtd = NULL;
 					break;
 				}
-				prev_qtd = qtd;
 			}
-			/* we found the urb before the end of the list */
-			if (qtd)
+
+			/* We found the urb before the last slot */
+			if (!qtd)
 				break;
 		}
-		ints++;
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 	return 0;
 }
 
-static irqreturn_t isp1760_irq(struct usb_hcd *usb_hcd)
+static irqreturn_t isp1760_irq(struct usb_hcd *hcd)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 imask;
 	irqreturn_t irqret = IRQ_NONE;
 
 	spin_lock(&priv->lock);
 
-	if (!(usb_hcd->state & HC_STATE_RUNNING))
+	if (!(hcd->state & HC_STATE_RUNNING))
 		goto leave;
 
-	imask = isp1760_readl(usb_hcd->regs + HC_INTERRUPT_REG);
+	imask = reg_read32(hcd->regs, HC_INTERRUPT_REG);
 	if (unlikely(!imask))
 		goto leave;
 
-	isp1760_writel(imask, usb_hcd->regs + HC_INTERRUPT_REG);
-	if (imask & HC_ATL_INT)
-		do_atl_int(usb_hcd);
+	reg_write32(hcd->regs, HC_INTERRUPT_REG, imask);
+	if (imask & (HC_ATL_INT | HC_SOT_INT))
+		do_atl_int(hcd);
 
 	if (imask & HC_INTL_INT)
-		do_intl_int(usb_hcd);
+		do_intl_int(hcd);
 
 	irqret = IRQ_HANDLED;
 leave:
@@ -1799,12 +1706,12 @@ static int isp1760_hub_status_data(struct usb_hcd *hcd, char *buf)
 	mask = PORT_CSC;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	temp = isp1760_readl(hcd->regs + HC_PORTSC1);
+	temp = reg_read32(hcd->regs, HC_PORTSC1);
 
 	if (temp & PORT_OWNER) {
 		if (temp & PORT_CSC) {
 			temp &= ~PORT_CSC;
-			isp1760_writel(temp, hcd->regs + HC_PORTSC1);
+			reg_write32(hcd->regs, HC_PORTSC1, temp);
 			goto done;
 		}
 	}
@@ -1844,9 +1751,9 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
 	temp = 1 + (ports / 8);
 	desc->bDescLength = 7 + 2 * temp;
 
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset(&desc->bitmap[0], 0, temp);
-	memset(&desc->bitmap[temp], 0xff, temp);
+	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
 
 	/* per-port overcurrent reporting */
 	temp = 0x0008;
@@ -1861,8 +1768,8 @@ static void isp1760_hub_descriptor(struct isp1760_hcd *priv,
 
 #define	PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
-static int check_reset_complete(struct isp1760_hcd *priv, int index,
-		u32 __iomem *status_reg, int port_status)
+static int check_reset_complete(struct usb_hcd *hcd, int index,
+		int port_status)
 {
 	if (!(port_status & PORT_CONNECT))
 		return port_status;
@@ -1870,15 +1777,17 @@ static int check_reset_complete(struct isp1760_hcd *priv, int index,
 	/* if reset finished and it's still not enabled -- handoff */
 	if (!(port_status & PORT_PE)) {
 
-		printk(KERN_ERR "port %d full speed --> companion\n",
-			index + 1);
+		dev_err(hcd->self.controller,
+					"port %d full speed --> companion\n",
+					index + 1);
 
 		port_status |= PORT_OWNER;
 		port_status &= ~PORT_RWC_BITS;
-		isp1760_writel(port_status, status_reg);
+		reg_write32(hcd->regs, HC_PORTSC1, port_status);
 
 	} else
-		printk(KERN_ERR "port %d high speed\n", index + 1);
+		dev_err(hcd->self.controller, "port %d high speed\n",
+								index + 1);
 
 	return port_status;
 }
@@ -1888,7 +1797,6 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 {
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	int ports = HCS_N_PORTS(priv->hcs_params);
-	u32 __iomem *status_reg = hcd->regs + HC_PORTSC1;
 	u32 temp, status;
 	unsigned long flags;
 	int retval = 0;
@@ -1917,7 +1825,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		temp = isp1760_readl(status_reg);
+		temp = reg_read32(hcd->regs, HC_PORTSC1);
 
 		/*
 		 * Even if OWNER is set, so the port is owned by the
@@ -1928,7 +1836,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
-			isp1760_writel(temp & ~PORT_PE, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_PE);
 			break;
 		case USB_PORT_FEAT_C_ENABLE:
 			/* XXX error? */
@@ -1942,8 +1850,8 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 					goto error;
 				/* resume signaling for 20 msec */
 				temp &= ~(PORT_RWC_BITS);
-				isp1760_writel(temp | PORT_RESUME,
-						status_reg);
+				reg_write32(hcd->regs, HC_PORTSC1,
+							temp | PORT_RESUME);
 				priv->reset_done = jiffies +
 					msecs_to_jiffies(20);
 			}
@@ -1953,11 +1861,11 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (HCS_PPC(priv->hcs_params))
-				isp1760_writel(temp & ~PORT_POWER, status_reg);
+				reg_write32(hcd->regs, HC_PORTSC1,
+							temp & ~PORT_POWER);
 			break;
 		case USB_PORT_FEAT_C_CONNECTION:
-			isp1760_writel(temp | PORT_CSC,
-					status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_CSC);
 			break;
 		case USB_PORT_FEAT_C_OVER_CURRENT:
 			/* XXX error ?*/
@@ -1968,7 +1876,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		default:
 			goto error;
 		}
-		isp1760_readl(hcd->regs + HC_USBCMD);
+		reg_read32(hcd->regs, HC_USBCMD);
 		break;
 	case GetHubDescriptor:
 		isp1760_hub_descriptor(priv, (struct usb_hub_descriptor *)
@@ -1983,7 +1891,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 			goto error;
 		wIndex--;
 		status = 0;
-		temp = isp1760_readl(status_reg);
+		temp = reg_read32(hcd->regs, HC_PORTSC1);
 
 		/* wPortChange bits */
 		if (temp & PORT_CSC)
@@ -1992,7 +1900,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 
 		/* whoever resumes must GetPortStatus to complete it!! */
 		if (temp & PORT_RESUME) {
-			printk(KERN_ERR "Port resume should be skipped.\n");
+			dev_err(hcd->self.controller, "Port resume should be skipped.\n");
 
 			/* Remote Wakeup received? */
 			if (!priv->reset_done) {
@@ -2000,8 +1908,7 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 				priv->reset_done = jiffies
 						+ msecs_to_jiffies(20);
 				/* check the port again */
-				mod_timer(&priv_to_hcd(priv)->rh_timer,
-						priv->reset_done);
+				mod_timer(&hcd->rh_timer, priv->reset_done);
 			}
 
 			/* resume completed? */
@@ -2011,14 +1918,13 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 				priv->reset_done = 0;
 
 				/* stop resume signaling */
-				temp = isp1760_readl(status_reg);
-				isp1760_writel(
-					temp & ~(PORT_RWC_BITS | PORT_RESUME),
-					status_reg);
-				retval = handshake(priv, status_reg,
+				temp = reg_read32(hcd->regs, HC_PORTSC1);
+				reg_write32(hcd->regs, HC_PORTSC1,
+					temp & ~(PORT_RWC_BITS | PORT_RESUME));
+				retval = handshake(hcd, HC_PORTSC1,
 					   PORT_RESUME, 0, 2000 /* 2msec */);
 				if (retval != 0) {
-					isp1760_err(priv,
+					dev_err(hcd->self.controller,
 						"port %d resume error %d\n",
 						wIndex + 1, retval);
 					goto error;
@@ -2035,22 +1941,21 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 			priv->reset_done = 0;
 
 			/* force reset to complete */
-			isp1760_writel(temp & ~PORT_RESET,
-					status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp & ~PORT_RESET);
 			/* REVISIT:  some hardware needs 550+ usec to clear
 			 * this bit; seems too long to spin routinely...
 			 */
-			retval = handshake(priv, status_reg,
+			retval = handshake(hcd, HC_PORTSC1,
 					PORT_RESET, 0, 750);
 			if (retval != 0) {
-				isp1760_err(priv, "port %d reset error %d\n",
+				dev_err(hcd->self.controller, "port %d reset error %d\n",
 						wIndex + 1, retval);
 				goto error;
 			}
 
 			/* see what we found out */
-			temp = check_reset_complete(priv, wIndex, status_reg,
-					isp1760_readl(status_reg));
+			temp = check_reset_complete(hcd, wIndex,
+					reg_read32(hcd->regs, HC_PORTSC1));
 		}
 		/*
 		 * Even if OWNER is set, there's no harm letting khubd
@@ -2059,12 +1964,12 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		 */
 
 		if (temp & PORT_OWNER)
-			printk(KERN_ERR "Warning: PORT_OWNER is set\n");
+			dev_err(hcd->self.controller, "PORT_OWNER is set\n");
 
 		if (temp & PORT_CONNECT) {
 			status |= USB_PORT_STAT_CONNECTION;
 			/* status may be from integrated TT */
-			status |= ehci_port_speed(priv, temp);
+			status |= USB_PORT_STAT_HIGH_SPEED;
 		}
 		if (temp & PORT_PE)
 			status |= USB_PORT_STAT_ENABLE;
@@ -2093,14 +1998,14 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		temp = isp1760_readl(status_reg);
+		temp = reg_read32(hcd->regs, HC_PORTSC1);
 		if (temp & PORT_OWNER)
 			break;
 
 /*		temp &= ~PORT_RWC_BITS; */
 		switch (wValue) {
 		case USB_PORT_FEAT_ENABLE:
-			isp1760_writel(temp | PORT_PE, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_PE);
 			break;
 
 		case USB_PORT_FEAT_SUSPEND:
@@ -2108,12 +2013,12 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 					|| (temp & PORT_RESET) != 0)
 				goto error;
 
-			isp1760_writel(temp | PORT_SUSPEND, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp | PORT_SUSPEND);
 			break;
 		case USB_PORT_FEAT_POWER:
 			if (HCS_PPC(priv->hcs_params))
-				isp1760_writel(temp | PORT_POWER,
-						status_reg);
+				reg_write32(hcd->regs, HC_PORTSC1,
+							temp | PORT_POWER);
 			break;
 		case USB_PORT_FEAT_RESET:
 			if (temp & PORT_RESUME)
@@ -2136,12 +2041,12 @@ static int isp1760_hub_control(struct usb_hcd *hcd, u16 typeReq,
 				priv->reset_done = jiffies +
 					msecs_to_jiffies(50);
 			}
-			isp1760_writel(temp, status_reg);
+			reg_write32(hcd->regs, HC_PORTSC1, temp);
 			break;
 		default:
 			goto error;
 		}
-		isp1760_readl(hcd->regs + HC_USBCMD);
+		reg_read32(hcd->regs, HC_USBCMD);
 		break;
 
 	default:
@@ -2153,10 +2058,10 @@ error:
 	return retval;
 }
 
-static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd,
+static void isp1760_endpoint_disable(struct usb_hcd *hcd,
 		struct usb_host_endpoint *ep)
 {
-	struct isp1760_hcd *priv = hcd_to_priv(usb_hcd);
+	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	struct isp1760_qh *qh;
 	struct isp1760_qtd *qtd;
 	unsigned long flags;
@@ -2176,16 +2081,16 @@ static void isp1760_endpoint_disable(struct usb_hcd *usb_hcd,
 				qtd_list);
 
 		if (qtd->status & URB_ENQUEUED) {
-
 			spin_unlock_irqrestore(&priv->lock, flags);
-			isp1760_urb_dequeue(usb_hcd, qtd->urb, -ECONNRESET);
+			isp1760_urb_dequeue(hcd, qtd->urb, -ECONNRESET);
 			spin_lock_irqsave(&priv->lock, flags);
 		} else {
 			struct urb *urb;
 
 			urb = qtd->urb;
-			clean_up_qtdlist(qtd);
-			isp1760_urb_done(priv, urb, -ECONNRESET);
+			clean_up_qtdlist(qtd, qh);
+			urb->status = -ECONNRESET;
+			isp1760_urb_done(hcd, urb);
 		}
 	} while (1);
 
@@ -2203,7 +2108,7 @@ static int isp1760_get_frame(struct usb_hcd *hcd)
 	struct isp1760_hcd *priv = hcd_to_priv(hcd);
 	u32 fr;
 
-	fr = isp1760_readl(hcd->regs + HC_FRINDEX);
+	fr = reg_read32(hcd->regs, HC_FRINDEX);
 	return (fr >> 3) % priv->periodic_size;
 }
 
@@ -2217,13 +2122,13 @@ static void isp1760_stop(struct usb_hcd *hcd)
 	mdelay(20);
 
 	spin_lock_irq(&priv->lock);
-	ehci_reset(priv);
+	ehci_reset(hcd);
 	/* Disable IRQ */
-	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
+	temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN);
 	spin_unlock_irq(&priv->lock);
 
-	isp1760_writel(0, hcd->regs + HC_CONFIGFLAG);
+	reg_write32(hcd->regs, HC_CONFIGFLAG, 0);
 }
 
 static void isp1760_shutdown(struct usb_hcd *hcd)
@@ -2231,12 +2136,12 @@ static void isp1760_shutdown(struct usb_hcd *hcd)
 	u32 command, temp;
 
 	isp1760_stop(hcd);
-	temp = isp1760_readl(hcd->regs + HC_HW_MODE_CTRL);
-	isp1760_writel(temp &= ~HW_GLOBAL_INTR_EN, hcd->regs + HC_HW_MODE_CTRL);
+	temp = reg_read32(hcd->regs, HC_HW_MODE_CTRL);
+	reg_write32(hcd->regs, HC_HW_MODE_CTRL, temp &= ~HW_GLOBAL_INTR_EN);
 
-	command = isp1760_readl(hcd->regs + HC_USBCMD);
+	command = reg_read32(hcd->regs, HC_USBCMD);
 	command &= ~CMD_RUN;
-	isp1760_writel(command, hcd->regs + HC_USBCMD);
+	reg_write32(hcd->regs, HC_USBCMD, command);
 }
 
 static const struct hc_driver isp1760_hc_driver = {
diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h
index 6931ef5..8705076 100644
--- a/drivers/usb/host/isp1760-hcd.h
+++ b/drivers/usb/host/isp1760-hcd.h
@@ -69,6 +69,7 @@ void deinit_kmem_cache(void);
 
 #define HC_INTERRUPT_ENABLE	0x314
 #define INTERRUPT_ENABLE_MASK	(HC_INTL_INT | HC_ATL_INT | HC_EOT_INT)
+#define INTERRUPT_ENABLE_SOT_MASK	(HC_INTL_INT | HC_SOT_INT | HC_EOT_INT)
 
 #define HC_ISO_INT		(1 << 9)
 #define HC_ATL_INT		(1 << 8)
@@ -83,37 +84,29 @@ void deinit_kmem_cache(void);
 #define HC_INT_IRQ_MASK_AND_REG	0x328
 #define HC_ATL_IRQ_MASK_AND_REG	0x32C
 
-/* Register sets */
-#define HC_BEGIN_OF_ATL		0x0c00
-#define HC_BEGIN_OF_INT		0x0800
-#define HC_BEGIN_OF_ISO		0x0400
-#define HC_BEGIN_OF_PAYLOAD	0x1000
-
 /* urb state*/
 #define DELETE_URB		(0x0008)
 #define NO_TRANSFER_ACTIVE	(0xffffffff)
 
-#define ATL_REGS_OFFSET		(0xc00)
-#define INT_REGS_OFFSET		(0x800)
-
-/* Philips Transfer Descriptor (PTD) */
+/* Philips Proprietary Transfer Descriptor (PTD) */
+typedef __u32 __bitwise __dw;
 struct ptd {
-	__le32 dw0;
-	__le32 dw1;
-	__le32 dw2;
-	__le32 dw3;
-	__le32 dw4;
-	__le32 dw5;
-	__le32 dw6;
-	__le32 dw7;
+	__dw dw0;
+	__dw dw1;
+	__dw dw2;
+	__dw dw3;
+	__dw dw4;
+	__dw dw5;
+	__dw dw6;
+	__dw dw7;
 };
+#define PTD_OFFSET		0x0400
+#define ISO_PTD_OFFSET		0x0400
+#define INT_PTD_OFFSET		0x0800
+#define ATL_PTD_OFFSET		0x0c00
+#define PAYLOAD_OFFSET		0x1000
 
 struct inter_packet_info {
-	void *data_buffer;
-	u32 payload;
-#define PTD_FIRE_NEXT		(1 << 0)
-#define PTD_URB_FINISHED	(1 << 1)
-	struct urb *urb;
 	struct isp1760_qh *qh;
 	struct isp1760_qtd *qtd;
 };
@@ -122,15 +115,6 @@ struct inter_packet_info {
 typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh,
 		struct isp1760_qtd *qtd);
 
-#define isp1760_dbg(priv, fmt, args...) \
-	dev_dbg(priv_to_hcd(priv)->self.controller, fmt, ##args)
-
-#define isp1760_info(priv, fmt, args...) \
-	dev_info(priv_to_hcd(priv)->self.controller, fmt, ##args)
-
-#define isp1760_err(priv, fmt, args...) \
-	dev_err(priv_to_hcd(priv)->self.controller, fmt, ##args)
-
 /*
  * Device flags that can vary from board to board.  All of these
  * indicate the most "atypical" case, so that a devflags of 0 is
@@ -167,10 +151,8 @@ struct memory_chunk {
 #define BLOCK_2_SIZE 1024
 #define BLOCK_3_SIZE 8192
 #define BLOCKS (BLOCK_1_NUM + BLOCK_2_NUM + BLOCK_3_NUM)
-#define PAYLOAD_SIZE 0xf000
-
-/* I saw if some reloads if the pointer was negative */
-#define ISP1760_NULL_POINTER	(0x400)
+#define MAX_PAYLOAD_SIZE BLOCK_3_SIZE
+#define PAYLOAD_AREA_SIZE 0xf000
 
 /* ATL */
 /* DW0 */
@@ -224,6 +206,4 @@ struct memory_chunk {
 #define NAK_COUNTER	(0)
 #define ERR_COUNTER	(2)
 
-#define HC_ATL_PL_SIZE	(8192)
-
 #endif
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c
index 3b28dbf..7ee3005 100644
--- a/drivers/usb/host/isp1760-if.c
+++ b/drivers/usb/host/isp1760-if.c
@@ -27,8 +27,7 @@
 #endif
 
 #ifdef CONFIG_PPC_OF
-static int of_isp1760_probe(struct platform_device *dev,
-		const struct of_device_id *match)
+static int of_isp1760_probe(struct platform_device *dev)
 {
 	struct usb_hcd *hcd;
 	struct device_node *dp = dev->dev.of_node;
@@ -119,7 +118,7 @@ static const struct of_device_id of_isp1760_match[] = {
 };
 MODULE_DEVICE_TABLE(of, of_isp1760_match);
 
-static struct of_platform_driver isp1760_of_driver = {
+static struct platform_driver isp1760_of_driver = {
 	.driver = {
 		.name = "nxp-isp1760",
 		.owner = THIS_MODULE,
@@ -398,7 +397,7 @@ static int __init isp1760_init(void)
 	if (!ret)
 		any_ret = 0;
 #ifdef CONFIG_PPC_OF
-	ret = of_register_platform_driver(&isp1760_of_driver);
+	ret = platform_driver_register(&isp1760_of_driver);
 	if (!ret)
 		any_ret = 0;
 #endif
@@ -418,7 +417,7 @@ static void __exit isp1760_exit(void)
 {
 	platform_driver_unregister(&isp1760_plat_driver);
 #ifdef CONFIG_PPC_OF
-	of_unregister_platform_driver(&isp1760_of_driver);
+	platform_driver_unregister(&isp1760_of_driver);
 #endif
 #ifdef CONFIG_PCI
 	pci_unregister_driver(&isp1761_pci_driver);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 759a12f..e728863 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -75,6 +75,7 @@ static const char	hcd_name [] = "ohci_hcd";
 #define	STATECHANGE_DELAY	msecs_to_jiffies(300)
 
 #include "ohci.h"
+#include "pci-quirks.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
@@ -85,18 +86,8 @@ static int ohci_restart (struct ohci_hcd *ohci);
 #endif
 
 #ifdef CONFIG_PCI
-static void quirk_amd_pll(int state);
-static void amd_iso_dev_put(void);
 static void sb800_prefetch(struct ohci_hcd *ohci, int on);
 #else
-static inline void quirk_amd_pll(int state)
-{
-	return;
-}
-static inline void amd_iso_dev_put(void)
-{
-	return;
-}
 static inline void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
 	return;
@@ -912,7 +903,7 @@ static void ohci_stop (struct usb_hcd *hcd)
 	if (quirk_zfmicro(ohci))
 		del_timer(&ohci->unlink_watchdog);
 	if (quirk_amdiso(ohci))
-		amd_iso_dev_put();
+		usb_amd_dev_put();
 
 	remove_debug_files (ohci);
 	ohci_mem_cleanup (ohci);
@@ -1023,11 +1014,6 @@ MODULE_LICENSE ("GPL");
 #define OMAP3_PLATFORM_DRIVER	ohci_hcd_omap3_driver
 #endif
 
-#ifdef CONFIG_ARCH_LH7A404
-#include "ohci-lh7a404.c"
-#define PLATFORM_DRIVER		ohci_hcd_lh7a404_driver
-#endif
-
 #if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
 #include "ohci-pxa27x.c"
 #define PLATFORM_DRIVER		ohci_hcd_pxa27x_driver
@@ -1068,10 +1054,7 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER		ohci_hcd_da8xx_driver
 #endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7721) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
+#ifdef CONFIG_USB_OHCI_SH
 #include "ohci-sh.c"
 #define PLATFORM_DRIVER		ohci_hcd_sh_driver
 #endif
@@ -1180,7 +1163,7 @@ static int __init ohci_hcd_mod_init(void)
 #endif
 
 #ifdef OF_PLATFORM_DRIVER
-	retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+	retval = platform_driver_register(&OF_PLATFORM_DRIVER);
 	if (retval < 0)
 		goto error_of_platform;
 #endif
@@ -1239,7 +1222,7 @@ static int __init ohci_hcd_mod_init(void)
  error_sa1111:
 #endif
 #ifdef OF_PLATFORM_DRIVER
-	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+	platform_driver_unregister(&OF_PLATFORM_DRIVER);
  error_of_platform:
 #endif
 #ifdef PLATFORM_DRIVER
@@ -1287,7 +1270,7 @@ static void __exit ohci_hcd_mod_exit(void)
 	sa1111_driver_unregister(&SA1111_DRIVER);
 #endif
 #ifdef OF_PLATFORM_DRIVER
-	of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+	platform_driver_unregister(&OF_PLATFORM_DRIVER);
 #endif
 #ifdef PLATFORM_DRIVER
 	platform_driver_unregister(&PLATFORM_DRIVER);
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index cddcda9..9154615 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -580,15 +580,16 @@ ohci_hub_descriptor (
 	    temp |= 0x0008;
 	desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ohci, temp);
 
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
 	rh = roothub_b (ohci);
-	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
-	desc->bitmap [0] = rh & RH_B_DR;
+	memset(desc->u.hs.DeviceRemovable, 0xff,
+			sizeof(desc->u.hs.DeviceRemovable));
+	desc->u.hs.DeviceRemovable[0] = rh & RH_B_DR;
 	if (ohci->num_ports > 7) {
-		desc->bitmap [1] = (rh & RH_B_DR) >> 8;
-		desc->bitmap [2] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = (rh & RH_B_DR) >> 8;
+		desc->u.hs.DeviceRemovable[2] = 0xff;
 	} else
-		desc->bitmap [1] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = 0xff;
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
deleted file mode 100644
index 18d39f0..0000000
--- a/drivers/usb/host/ohci-lh7a404.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * OHCI HCD (Host Controller Driver) for USB.
- *
- * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
- * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
- * (C) Copyright 2002 Hewlett-Packard Company
- *
- * Bus Glue for Sharp LH7A404
- *
- * Written by Christopher Hoover <ch@hpl.hp.com>
- * Based on fragments of previous driver by Russell King et al.
- *
- * Modified for LH7A404 from ohci-sa1111.c
- *  by Durgesh Pattamatta <pattamattad@sharpsec.com>
- *
- * This file is licenced under the GPL.
- */
-
-#include <linux/platform_device.h>
-#include <linux/signal.h>
-
-#include <mach/hardware.h>
-
-
-extern int usb_disabled(void);
-
-/*-------------------------------------------------------------------------*/
-
-static void lh7a404_start_hc(struct platform_device *dev)
-{
-	printk(KERN_DEBUG "%s: starting LH7A404 OHCI USB Controller\n",
-	       __FILE__);
-
-	/*
-	 * Now, carefully enable the USB clock, and take
-	 * the USB host controller out of reset.
-	 */
-	CSC_PWRCNT |= CSC_PWRCNT_USBH_EN; /* Enable clock */
-	udelay(1000);
-	USBH_CMDSTATUS = OHCI_HCR;
-
-	printk(KERN_DEBUG "%s: Clock to USB host has been enabled \n", __FILE__);
-}
-
-static void lh7a404_stop_hc(struct platform_device *dev)
-{
-	printk(KERN_DEBUG "%s: stopping LH7A404 OHCI USB Controller\n",
-	       __FILE__);
-
-	CSC_PWRCNT &= ~CSC_PWRCNT_USBH_EN; /* Disable clock */
-}
-
-
-/*-------------------------------------------------------------------------*/
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
-/**
- * usb_hcd_lh7a404_probe - initialize LH7A404-based HCDs
- * Context: !in_interrupt()
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- *
- */
-int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
-			  struct platform_device *dev)
-{
-	int retval;
-	struct usb_hcd *hcd;
-
-	if (dev->resource[1].flags != IORESOURCE_IRQ) {
-		pr_debug("resource[1] is not IORESOURCE_IRQ");
-		return -ENOMEM;
-	}
-
-	hcd = usb_create_hcd(driver, &dev->dev, "lh7a404");
-	if (!hcd)
-		return -ENOMEM;
-	hcd->rsrc_start = dev->resource[0].start;
-	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
-
-	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
-		pr_debug("request_mem_region failed");
-		retval = -EBUSY;
-		goto err1;
-	}
-
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		pr_debug("ioremap failed");
-		retval = -ENOMEM;
-		goto err2;
-	}
-
-	lh7a404_start_hc(dev);
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
-	if (retval == 0)
-		return retval;
-
-	lh7a404_stop_hc(dev);
-	iounmap(hcd->regs);
- err2:
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
- err1:
-	usb_put_hcd(hcd);
-	return retval;
-}
-
-
-/* may be called without controller electrically present */
-/* may be called with controller, bus, and devices active */
-
-/**
- * usb_hcd_lh7a404_remove - shutdown processing for LH7A404-based HCDs
- * @dev: USB Host Controller being removed
- * Context: !in_interrupt()
- *
- * Reverses the effect of usb_hcd_lh7a404_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- *
- */
-void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev)
-{
-	usb_remove_hcd(hcd);
-	lh7a404_stop_hc(dev);
-	iounmap(hcd->regs);
-	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-	usb_put_hcd(hcd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int __devinit
-ohci_lh7a404_start (struct usb_hcd *hcd)
-{
-	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
-	int		ret;
-
-	ohci_dbg (ohci, "ohci_lh7a404_start, ohci:%p", ohci);
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
-	if ((ret = ohci_run (ohci)) < 0) {
-		err ("can't start %s", hcd->self.bus_name);
-		ohci_stop (hcd);
-		return ret;
-	}
-	return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static const struct hc_driver ohci_lh7a404_hc_driver = {
-	.description =		hcd_name,
-	.product_desc =		"LH7A404 OHCI",
-	.hcd_priv_size =	sizeof(struct ohci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq =			ohci_irq,
-	.flags =		HCD_USB11 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.start =		ohci_lh7a404_start,
-	.stop =			ohci_stop,
-	.shutdown =		ohci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue =		ohci_urb_enqueue,
-	.urb_dequeue =		ohci_urb_dequeue,
-	.endpoint_disable =	ohci_endpoint_disable,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number =	ohci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data =	ohci_hub_status_data,
-	.hub_control =		ohci_hub_control,
-#ifdef	CONFIG_PM
-	.bus_suspend =		ohci_bus_suspend,
-	.bus_resume =		ohci_bus_resume,
-#endif
-	.start_port_reset =	ohci_start_port_reset,
-};
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_lh7a404_drv_probe(struct platform_device *pdev)
-{
-	int ret;
-
-	pr_debug ("In ohci_hcd_lh7a404_drv_probe");
-
-	if (usb_disabled())
-		return -ENODEV;
-
-	ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, pdev);
-	return ret;
-}
-
-static int ohci_hcd_lh7a404_drv_remove(struct platform_device *pdev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-	usb_hcd_lh7a404_remove(hcd, pdev);
-	return 0;
-}
-	/*TBD*/
-/*static int ohci_hcd_lh7a404_drv_suspend(struct platform_device *dev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(dev);
-
-	return 0;
-}
-static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev)
-{
-	struct usb_hcd *hcd = platform_get_drvdata(dev);
-
-
-	return 0;
-}
-*/
-
-static struct platform_driver ohci_hcd_lh7a404_driver = {
-	.probe		= ohci_hcd_lh7a404_drv_probe,
-	.remove		= ohci_hcd_lh7a404_drv_remove,
-	.shutdown	= usb_hcd_platform_shutdown,
-	/*.suspend	= ohci_hcd_lh7a404_drv_suspend, */
-	/*.resume	= ohci_hcd_lh7a404_drv_resume, */
-	.driver		= {
-		.name	= "lh7a404-ohci",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS("platform:lh7a404-ohci");
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index a37d599..6048f2f 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
  * Author: Vikram Pandita <vikram.pandita@ti.com>
  * Author: Anand Gadiyar <gadiyar@ti.com>
+ * Author: Keshava Munegowda <keshava_mgowda@ti.com>
  *
  * Based on ehci-omap.c and some other ohci glue layers
  *
@@ -24,150 +25,15 @@
  * 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 Mar 10th, 2010):
+ * TODO (last updated Feb 27, 2011):
  *	- add kernel-doc
- *	- Factor out code common to EHCI to a separate file
- *	- Make EHCI and OHCI coexist together
- *	  - needs newer silicon versions to actually work
- *	  - the last one to be loaded currently steps on the other's toes
- *	- Add hooks for configuring transceivers, etc. at init/exit
- *	- Add aggressive clock-management code
  */
 
 #include <linux/platform_device.h>
-#include <linux/clk.h>
-
 #include <plat/usb.h>
 
-/*
- * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
- *	Use ohci_omap_readl()/ohci_omap_writel() functions
- */
-
-/* TLL Register Set */
-#define	OMAP_USBTLL_REVISION				(0x00)
-#define	OMAP_USBTLL_SYSCONFIG				(0x10)
-#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_USBTLL_SYSSTATUS				(0x14)
-#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
-
-#define	OMAP_USBTLL_IRQSTATUS				(0x18)
-#define	OMAP_USBTLL_IRQENABLE				(0x1C)
-
-#define	OMAP_TLL_SHARED_CONF				(0x30)
-#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
-#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
-#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
-#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
-#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
-
-#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
-#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
-#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
-#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
-#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
-#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
-#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
-#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
-
-#define OMAP_TLL_CHANNEL_COUNT				3
-
-/* UHH Register Set */
-#define	OMAP_UHH_REVISION				(0x00)
-#define	OMAP_UHH_SYSCONFIG				(0x10)
-#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
-#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
-#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
-#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
-#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
-#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
-
-#define	OMAP_UHH_SYSSTATUS				(0x14)
-#define OMAP_UHH_SYSSTATUS_UHHRESETDONE			(1 << 0)
-#define OMAP_UHH_SYSSTATUS_OHCIRESETDONE		(1 << 1)
-#define OMAP_UHH_SYSSTATUS_EHCIRESETDONE		(1 << 2)
-#define	OMAP_UHH_HOSTCONFIG				(0x40)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
-#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
-#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
-#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
-#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
-#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
-#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
-#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
-#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
-
-#define	OMAP_UHH_DEBUG_CSR				(0x44)
-
 /*-------------------------------------------------------------------------*/
 
-static inline void ohci_omap_writel(void __iomem *base, u32 reg, u32 val)
-{
-	__raw_writel(val, base + reg);
-}
-
-static inline u32 ohci_omap_readl(void __iomem *base, u32 reg)
-{
-	return __raw_readl(base + reg);
-}
-
-static inline void ohci_omap_writeb(void __iomem *base, u8 reg, u8 val)
-{
-	__raw_writeb(val, base + reg);
-}
-
-static inline u8 ohci_omap_readb(void __iomem *base, u8 reg)
-{
-	return __raw_readb(base + reg);
-}
-
-/*-------------------------------------------------------------------------*/
-
-struct ohci_hcd_omap3 {
-	struct ohci_hcd		*ohci;
-	struct device		*dev;
-
-	struct clk		*usbhost_ick;
-	struct clk		*usbhost2_120m_fck;
-	struct clk		*usbhost1_48m_fck;
-	struct clk		*usbtll_fck;
-	struct clk		*usbtll_ick;
-
-	/* port_mode: TLL/PHY, 2/3/4/6-PIN, DP-DM/DAT-SE0 */
-	enum ohci_omap3_port_mode	port_mode[OMAP3_HS_USB_PORTS];
-	void __iomem		*uhh_base;
-	void __iomem		*tll_base;
-	void __iomem		*ohci_base;
-
-	unsigned		es2_compatibility:1;
-};
-
-/*-------------------------------------------------------------------------*/
-
-static void ohci_omap3_clock_power(struct ohci_hcd_omap3 *omap, int on)
-{
-	if (on) {
-		clk_enable(omap->usbtll_ick);
-		clk_enable(omap->usbtll_fck);
-		clk_enable(omap->usbhost_ick);
-		clk_enable(omap->usbhost1_48m_fck);
-		clk_enable(omap->usbhost2_120m_fck);
-	} else {
-		clk_disable(omap->usbhost2_120m_fck);
-		clk_disable(omap->usbhost1_48m_fck);
-		clk_disable(omap->usbhost_ick);
-		clk_disable(omap->usbtll_fck);
-		clk_disable(omap->usbtll_ick);
-	}
-}
-
 static int ohci_omap3_init(struct usb_hcd *hcd)
 {
 	dev_dbg(hcd->self.controller, "starting OHCI controller\n");
@@ -175,7 +41,6 @@ static int ohci_omap3_init(struct usb_hcd *hcd)
 	return ohci_init(hcd_to_ohci(hcd));
 }
 
-
 /*-------------------------------------------------------------------------*/
 
 static int ohci_omap3_start(struct usb_hcd *hcd)
@@ -202,325 +67,6 @@ static int ohci_omap3_start(struct usb_hcd *hcd)
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * convert the port-mode enum to a value we can use in the FSLSMODE
- * field of USBTLL_CHANNEL_CONF
- */
-static unsigned ohci_omap3_fslsmode(enum ohci_omap3_port_mode mode)
-{
-	switch (mode) {
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-		return 0x0;
-
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-		return 0x1;
-
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-		return 0x2;
-
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-		return 0x3;
-
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-		return 0x4;
-
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		return 0x5;
-
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		return 0x6;
-
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		return 0x7;
-
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-		return 0xA;
-
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		return 0xB;
-	default:
-		pr_warning("Invalid port mode, using default\n");
-		return 0x0;
-	}
-}
-
-static void ohci_omap3_tll_config(struct ohci_hcd_omap3 *omap)
-{
-	u32 reg;
-	int i;
-
-	/* Program TLL SHARED CONF */
-	reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF);
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
-	reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
-	reg |= OMAP_TLL_SHARED_CONF_USB_DIVRATION;
-	reg |= OMAP_TLL_SHARED_CONF_FCLK_IS_ON;
-	ohci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
-
-	/* Program each TLL channel */
-	/*
-	 * REVISIT: Only the 3-pin and 4-pin PHY modes have
-	 * actually been tested.
-	 */
-	for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) {
-
-		/* Enable only those channels that are actually used */
-		if (omap->port_mode[i] == OMAP_OHCI_PORT_MODE_UNUSED)
-			continue;
-
-		reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
-		reg |= ohci_omap3_fslsmode(omap->port_mode[i])
-				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
-		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
-		ohci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
-	}
-}
-
-/* omap3_start_ohci
- *	- Start the TI USBHOST controller
- */
-static int omap3_start_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-	u32 reg = 0;
-	int ret = 0;
-
-	dev_dbg(omap->dev, "starting TI OHCI USB Controller\n");
-
-	/* Get all the clock handles we need */
-	omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick");
-	if (IS_ERR(omap->usbhost_ick)) {
-		dev_err(omap->dev, "could not get usbhost_ick\n");
-		ret =  PTR_ERR(omap->usbhost_ick);
-		goto err_host_ick;
-	}
-
-	omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck");
-	if (IS_ERR(omap->usbhost2_120m_fck)) {
-		dev_err(omap->dev, "could not get usbhost_120m_fck\n");
-		ret = PTR_ERR(omap->usbhost2_120m_fck);
-		goto err_host_120m_fck;
-	}
-
-	omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck");
-	if (IS_ERR(omap->usbhost1_48m_fck)) {
-		dev_err(omap->dev, "could not get usbhost_48m_fck\n");
-		ret = PTR_ERR(omap->usbhost1_48m_fck);
-		goto err_host_48m_fck;
-	}
-
-	omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
-	if (IS_ERR(omap->usbtll_fck)) {
-		dev_err(omap->dev, "could not get usbtll_fck\n");
-		ret = PTR_ERR(omap->usbtll_fck);
-		goto err_tll_fck;
-	}
-
-	omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick");
-	if (IS_ERR(omap->usbtll_ick)) {
-		dev_err(omap->dev, "could not get usbtll_ick\n");
-		ret = PTR_ERR(omap->usbtll_ick);
-		goto err_tll_ick;
-	}
-
-	/* Now enable all the clocks in the correct order */
-	ohci_omap3_clock_power(omap, 1);
-
-	/* perform TLL soft reset, and wait until reset is complete */
-	ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
-
-	/* Wait for TLL reset to complete */
-	while (!(ohci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			dev_dbg(omap->dev, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_sys_status;
-		}
-	}
-
-	dev_dbg(omap->dev, "TLL reset done\n");
-
-	/* (1<<3) = no idle mode only for initial debugging */
-	ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
-			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
-			OMAP_USBTLL_SYSCONFIG_CACTIVITY);
-
-
-	/* Put UHH in NoIdle/NoStandby mode */
-	reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
-	reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
-			| OMAP_UHH_SYSCONFIG_SIDLEMODE
-			| OMAP_UHH_SYSCONFIG_CACTIVITY
-			| OMAP_UHH_SYSCONFIG_MIDLEMODE);
-	reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
-	reg &= ~OMAP_UHH_SYSCONFIG_SOFTRESET;
-
-	ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
-
-	reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
-
-	/* setup ULPI bypass and burst configurations */
-	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
-			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
-	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
-
-	/*
-	 * REVISIT: Pi_CONNECT_STATUS controls MStandby
-	 * assertion and Swakeup generation - let us not
-	 * worry about this for now. OMAP HWMOD framework
-	 * might take care of this later. If not, we can
-	 * update these registers when adding aggressive
-	 * clock management code.
-	 *
-	 * For now, turn off all the Pi_CONNECT_STATUS bits
-	 *
-	if (omap->port_mode[0] == OMAP_OHCI_PORT_MODE_UNUSED)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-	if (omap->port_mode[1] == OMAP_OHCI_PORT_MODE_UNUSED)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-	if (omap->port_mode[2] == OMAP_OHCI_PORT_MODE_UNUSED)
-		reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
-	 */
-	reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
-	reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
-	reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
-
-	 if (omap->es2_compatibility) {
-		/*
-		 * All OHCI modes need to go through the TLL,
-		 * unlike in the EHCI case. So use UTMI mode
-		 * for all ports for OHCI, on ES2.x silicon
-		 */
-		dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
-		reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
-	} else {
-		dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
-		if (omap->port_mode[0] == OMAP_OHCI_PORT_MODE_UNUSED)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
-
-		if (omap->port_mode[1] == OMAP_OHCI_PORT_MODE_UNUSED)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
-
-		if (omap->port_mode[2] == OMAP_OHCI_PORT_MODE_UNUSED)
-			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-		else
-			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
-
-	}
-	ohci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
-	dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
-
-	ohci_omap3_tll_config(omap);
-
-	return 0;
-
-err_sys_status:
-	ohci_omap3_clock_power(omap, 0);
-	clk_put(omap->usbtll_ick);
-
-err_tll_ick:
-	clk_put(omap->usbtll_fck);
-
-err_tll_fck:
-	clk_put(omap->usbhost1_48m_fck);
-
-err_host_48m_fck:
-	clk_put(omap->usbhost2_120m_fck);
-
-err_host_120m_fck:
-	clk_put(omap->usbhost_ick);
-
-err_host_ick:
-	return ret;
-}
-
-static void omap3_stop_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-
-	dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n");
-
-	/* Reset USBHOST for insmod/rmmod to work */
-	ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
-			OMAP_UHH_SYSCONFIG_SOFTRESET);
-	while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& OMAP_UHH_SYSSTATUS_UHHRESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& OMAP_UHH_SYSSTATUS_OHCIRESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& OMAP_UHH_SYSSTATUS_EHCIRESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
-
-	while (!(ohci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout))
-			dev_dbg(omap->dev, "operation timed out\n");
-	}
-
-	ohci_omap3_clock_power(omap, 0);
-
-	if (omap->usbtll_fck != NULL) {
-		clk_put(omap->usbtll_fck);
-		omap->usbtll_fck = NULL;
-	}
-
-	if (omap->usbhost_ick != NULL) {
-		clk_put(omap->usbhost_ick);
-		omap->usbhost_ick = NULL;
-	}
-
-	if (omap->usbhost1_48m_fck != NULL) {
-		clk_put(omap->usbhost1_48m_fck);
-		omap->usbhost1_48m_fck = NULL;
-	}
-
-	if (omap->usbhost2_120m_fck != NULL) {
-		clk_put(omap->usbhost2_120m_fck);
-		omap->usbhost2_120m_fck = NULL;
-	}
-
-	if (omap->usbtll_ick != NULL) {
-		clk_put(omap->usbtll_ick);
-		omap->usbtll_ick = NULL;
-	}
-
-	dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
-}
-
-/*-------------------------------------------------------------------------*/
-
 static const struct hc_driver ohci_omap3_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"OMAP3 OHCI Host Controller",
@@ -580,107 +126,77 @@ static const struct hc_driver ohci_omap3_hc_driver = {
  */
 static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
 {
-	struct ohci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
-	struct ohci_hcd_omap3 *omap;
-	struct resource *res;
-	struct usb_hcd *hcd;
-	int ret = -ENODEV;
-	int irq;
+	struct device		*dev = &pdev->dev;
+	struct usb_hcd		*hcd = NULL;
+	void __iomem		*regs = NULL;
+	struct resource		*res;
+	int			ret = -ENODEV;
+	int			irq;
 
 	if (usb_disabled())
-		goto err_disabled;
+		goto err_end;
 
-	if (!pdata) {
-		dev_dbg(&pdev->dev, "missing platform_data\n");
-		goto err_pdata;
+	if (!dev->parent) {
+		dev_err(dev, "Missing parent device\n");
+		return -ENODEV;
 	}
 
-	irq = platform_get_irq(pdev, 0);
+	irq = platform_get_irq_byname(pdev, "ohci-irq");
+	if (irq < 0) {
+		dev_err(dev, "OHCI irq failed\n");
+		return -ENODEV;
+	}
 
-	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
-	if (!omap) {
-		ret = -ENOMEM;
-		goto err_disabled;
+	res = platform_get_resource_byname(pdev,
+				IORESOURCE_MEM, "ohci");
+	if (!ret) {
+		dev_err(dev, "UHH OHCI get resource failed\n");
+		return -ENOMEM;
 	}
 
-	hcd = usb_create_hcd(&ohci_omap3_hc_driver, &pdev->dev,
-			dev_name(&pdev->dev));
-	if (!hcd) {
-		ret = -ENOMEM;
-		goto err_create_hcd;
+	regs = ioremap(res->start, resource_size(res));
+	if (!regs) {
+		dev_err(dev, "UHH OHCI ioremap failed\n");
+		return -ENOMEM;
 	}
 
-	platform_set_drvdata(pdev, omap);
-	omap->dev		= &pdev->dev;
-	omap->port_mode[0]	= pdata->port_mode[0];
-	omap->port_mode[1]	= pdata->port_mode[1];
-	omap->port_mode[2]	= pdata->port_mode[2];
-	omap->es2_compatibility	= pdata->es2_compatibility;
-	omap->ohci		= hcd_to_ohci(hcd);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
+			dev_name(dev));
+	if (!hcd) {
+		dev_err(dev, "usb_create_hcd failed\n");
+		goto err_io;
+	}
 
 	hcd->rsrc_start = res->start;
 	hcd->rsrc_len = resource_size(res);
+	hcd->regs =  regs;
 
-	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
-	if (!hcd->regs) {
-		dev_err(&pdev->dev, "OHCI ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	omap->uhh_base = ioremap(res->start, resource_size(res));
-	if (!omap->uhh_base) {
-		dev_err(&pdev->dev, "UHH ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_uhh_ioremap;
-	}
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	omap->tll_base = ioremap(res->start, resource_size(res));
-	if (!omap->tll_base) {
-		dev_err(&pdev->dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_tll_ioremap;
-	}
-
-	ret = omap3_start_ohci(omap, hcd);
+	ret = omap_usbhs_enable(dev);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to start ohci\n");
-		goto err_start;
+		dev_dbg(dev, "failed to start ohci\n");
+		goto err_end;
 	}
 
-	ohci_hcd_init(omap->ohci);
+	ohci_hcd_init(hcd_to_ohci(hcd));
 
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
+		dev_dbg(dev, "failed to add hcd with err %d\n", ret);
 		goto err_add_hcd;
 	}
 
 	return 0;
 
 err_add_hcd:
-	omap3_stop_ohci(omap, hcd);
-
-err_start:
-	iounmap(omap->tll_base);
-
-err_tll_ioremap:
-	iounmap(omap->uhh_base);
-
-err_uhh_ioremap:
-	iounmap(hcd->regs);
+	omap_usbhs_disable(dev);
 
-err_ioremap:
+err_end:
 	usb_put_hcd(hcd);
 
-err_create_hcd:
-	kfree(omap);
-err_pdata:
-err_disabled:
+err_io:
+	iounmap(regs);
+
 	return ret;
 }
 
@@ -699,24 +215,20 @@ err_disabled:
  */
 static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
 {
-	struct ohci_hcd_omap3 *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ohci_to_hcd(omap->ohci);
+	struct device *dev	= &pdev->dev;
+	struct usb_hcd *hcd	= dev_get_drvdata(dev);
 
-	usb_remove_hcd(hcd);
-	omap3_stop_ohci(omap, hcd);
 	iounmap(hcd->regs);
-	iounmap(omap->tll_base);
-	iounmap(omap->uhh_base);
+	usb_remove_hcd(hcd);
+	omap_usbhs_disable(dev);
 	usb_put_hcd(hcd);
-	kfree(omap);
 
 	return 0;
 }
 
 static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
 {
-	struct ohci_hcd_omap3 *omap = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = ohci_to_hcd(omap->ohci);
+	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 36ee9a6..d84d6f0 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -22,24 +22,6 @@
 #include <linux/io.h>
 
 
-/* constants used to work around PM-related transfer
- * glitches in some AMD 700 series southbridges
- */
-#define AB_REG_BAR	0xf0
-#define AB_INDX(addr)	((addr) + 0x00)
-#define AB_DATA(addr)	((addr) + 0x04)
-#define AX_INDXC	0X30
-#define AX_DATAC	0x34
-
-#define NB_PCIE_INDX_ADDR	0xe0
-#define NB_PCIE_INDX_DATA	0xe4
-#define PCIE_P_CNTL		0x10040
-#define BIF_NB			0x10002
-
-static struct pci_dev *amd_smbus_dev;
-static struct pci_dev *amd_hb_dev;
-static int amd_ohci_iso_count;
-
 /*-------------------------------------------------------------------------*/
 
 static int broken_suspend(struct usb_hcd *hcd)
@@ -168,15 +150,18 @@ static int ohci_quirk_nec(struct usb_hcd *hcd)
 static int ohci_quirk_amd700(struct usb_hcd *hcd)
 {
 	struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-	u8 rev = 0;
+	struct pci_dev *amd_smbus_dev;
+	u8 rev;
 
-	if (!amd_smbus_dev)
-		amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
-				PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
+	if (usb_amd_find_chipset_info())
+		ohci->flags |= OHCI_QUIRK_AMD_PLL;
+
+	amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI,
+			PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL);
 	if (!amd_smbus_dev)
 		return 0;
 
-	pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev);
+	rev = amd_smbus_dev->revision;
 
 	/* SB800 needs pre-fetch fix */
 	if ((rev >= 0x40) && (rev <= 0x4f)) {
@@ -184,19 +169,8 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
 		ohci_dbg(ohci, "enabled AMD prefetch quirk\n");
 	}
 
-	if ((rev > 0x3b) || (rev < 0x30)) {
-		pci_dev_put(amd_smbus_dev);
-		amd_smbus_dev = NULL;
-		return 0;
-	}
-
-	amd_ohci_iso_count++;
-
-	if (!amd_hb_dev)
-		amd_hb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9600, NULL);
-
-	ohci->flags |= OHCI_QUIRK_AMD_ISO;
-	ohci_dbg(ohci, "enabled AMD ISO transfers quirk\n");
+	pci_dev_put(amd_smbus_dev);
+	amd_smbus_dev = NULL;
 
 	return 0;
 }
@@ -215,74 +189,6 @@ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
 	return 0;
 }
 
-/*
- * The hardware normally enables the A-link power management feature, which
- * lets the system lower the power consumption in idle states.
- *
- * Assume the system is configured to have USB 1.1 ISO transfers going
- * to or from a USB device.  Without this quirk, that stream may stutter
- * or have breaks occasionally.  For transfers going to speakers, this
- * makes a very audible mess...
- *
- * That audio playback corruption is due to the audio stream getting
- * interrupted occasionally when the link goes in lower power state
- * This USB quirk prevents the link going into that lower power state
- * during audio playback or other ISO operations.
- */
-static void quirk_amd_pll(int on)
-{
-	u32 addr;
-	u32 val;
-	u32 bit = (on > 0) ? 1 : 0;
-
-	pci_read_config_dword(amd_smbus_dev, AB_REG_BAR, &addr);
-
-	/* BIT names/meanings are NDA-protected, sorry ... */
-
-	outl(AX_INDXC, AB_INDX(addr));
-	outl(0x40, AB_DATA(addr));
-	outl(AX_DATAC, AB_INDX(addr));
-	val = inl(AB_DATA(addr));
-	val &= ~((1 << 3) | (1 << 4) | (1 << 9));
-	val |= (bit << 3) | ((!bit) << 4) | ((!bit) << 9);
-	outl(val, AB_DATA(addr));
-
-	if (amd_hb_dev) {
-		addr = PCIE_P_CNTL;
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
-
-		pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
-		val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
-		val |= bit | (bit << 3) | (bit << 12);
-		val |= ((!bit) << 4) | ((!bit) << 9);
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
-
-		addr = BIF_NB;
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_ADDR, addr);
-
-		pci_read_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, &val);
-		val &= ~(1 << 8);
-		val |= bit << 8;
-		pci_write_config_dword(amd_hb_dev, NB_PCIE_INDX_DATA, val);
-	}
-}
-
-static void amd_iso_dev_put(void)
-{
-	amd_ohci_iso_count--;
-	if (amd_ohci_iso_count == 0) {
-		if (amd_smbus_dev) {
-			pci_dev_put(amd_smbus_dev);
-			amd_smbus_dev = NULL;
-		}
-		if (amd_hb_dev) {
-			pci_dev_put(amd_hb_dev);
-			amd_hb_dev = NULL;
-		}
-	}
-
-}
-
 static void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
 	struct pci_dev *pdev;
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index b2c2dbf..1ca1821 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -80,8 +80,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = {
 };
 
 
-static int __devinit
-ohci_hcd_ppc_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct usb_hcd *hcd;
@@ -201,14 +200,12 @@ static int ohci_hcd_ppc_of_remove(struct platform_device *op)
 	return 0;
 }
 
-static int ohci_hcd_ppc_of_shutdown(struct platform_device *op)
+static void ohci_hcd_ppc_of_shutdown(struct platform_device *op)
 {
 	struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
 
         if (hcd->driver->shutdown)
                 hcd->driver->shutdown(hcd);
-
-	return 0;
 }
 
 
@@ -243,7 +240,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
 #endif
 
 
-static struct of_platform_driver ohci_hcd_ppc_of_driver = {
+static struct platform_driver ohci_hcd_ppc_of_driver = {
 	.probe		= ohci_hcd_ppc_of_probe,
 	.remove		= ohci_hcd_ppc_of_remove,
 	.shutdown 	= ohci_hcd_ppc_of_shutdown,
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 83094d0..dd24fc1 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -52,7 +52,7 @@ __acquires(ohci->lock)
 		ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
 		if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
 			if (quirk_amdiso(ohci))
-				quirk_amd_pll(1);
+				usb_amd_quirk_pll_enable();
 			if (quirk_amdprefetch(ohci))
 				sb800_prefetch(ohci, 0);
 		}
@@ -686,7 +686,7 @@ static void td_submit_urb (
 		}
 		if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0) {
 			if (quirk_amdiso(ohci))
-				quirk_amd_pll(0);
+				usb_amd_quirk_pll_disable();
 			if (quirk_amdprefetch(ohci))
 				sb800_prefetch(ohci, 1);
 		}
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 51facb9..35e5fd6 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -401,7 +401,7 @@ struct ohci_hcd {
 #define	OHCI_QUIRK_NEC		0x40			/* lost interrupts */
 #define	OHCI_QUIRK_FRAME_NO	0x80			/* no big endian frame_no shift */
 #define	OHCI_QUIRK_HUB_POWER	0x100			/* distrust firmware power/oc setup */
-#define	OHCI_QUIRK_AMD_ISO	0x200			/* ISO transfers*/
+#define	OHCI_QUIRK_AMD_PLL	0x200			/* AMD PLL quirk*/
 #define	OHCI_QUIRK_AMD_PREFETCH	0x400			/* pre-fetch for ISO transfer */
 #define	OHCI_QUIRK_SHUTDOWN	0x800			/* nVidia power bug */
 	// there are also chip quirks/bugs in init logic
@@ -433,7 +433,7 @@ static inline int quirk_zfmicro(struct ohci_hcd *ohci)
 }
 static inline int quirk_amdiso(struct ohci_hcd *ohci)
 {
-	return ohci->flags & OHCI_QUIRK_AMD_ISO;
+	return ohci->flags & OHCI_QUIRK_AMD_PLL;
 }
 static inline int quirk_amdprefetch(struct ohci_hcd *ohci)
 {
@@ -575,18 +575,8 @@ static inline void _ohci_writel (const struct ohci_hcd *ohci,
 #endif
 }
 
-#ifdef CONFIG_ARCH_LH7A404
-/* Marc Singer: at the time this code was written, the LH7A404
- * had a problem reading the USB host registers.  This
- * implementation of the ohci_readl function performs the read
- * twice as a work-around.
- */
-#define ohci_readl(o,r)		(_ohci_readl(o,r),_ohci_readl(o,r))
-#define ohci_writel(o,v,r)	_ohci_writel(o,v,r)
-#else
 #define ohci_readl(o,r)		_ohci_readl(o,r)
 #define ohci_writel(o,v,r)	_ohci_writel(o,v,r)
-#endif
 
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index e0cb12b..38193f4 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -451,9 +451,9 @@ static void ehci_hub_descriptor(struct oxu_hcd *oxu,
 	temp = 1 + (ports / 8);
 	desc->bDescLength = 7 + 2 * temp;
 
-	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset(&desc->bitmap[0], 0, temp);
-	memset(&desc->bitmap[temp], 0xff, temp);
+	/* ports removable, and usb 1.0 legacy PortPwrCtrlMask */
+	memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
 
 	temp = 0x0008;			/* per-port overcurrent reporting */
 	if (HCS_PPC(oxu->hcs_params))
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 4c502c8..1d586d4 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -52,6 +52,264 @@
 #define EHCI_USBLEGCTLSTS	4		/* legacy control/status */
 #define EHCI_USBLEGCTLSTS_SOOE	(1 << 13)	/* SMI on ownership change */
 
+/* AMD quirk use */
+#define	AB_REG_BAR_LOW		0xe0
+#define	AB_REG_BAR_HIGH		0xe1
+#define	AB_REG_BAR_SB700	0xf0
+#define	AB_INDX(addr)		((addr) + 0x00)
+#define	AB_DATA(addr)		((addr) + 0x04)
+#define	AX_INDXC		0x30
+#define	AX_DATAC		0x34
+
+#define	NB_PCIE_INDX_ADDR	0xe0
+#define	NB_PCIE_INDX_DATA	0xe4
+#define	PCIE_P_CNTL		0x10040
+#define	BIF_NB			0x10002
+#define	NB_PIF0_PWRDOWN_0	0x01100012
+#define	NB_PIF0_PWRDOWN_1	0x01100013
+
+static struct amd_chipset_info {
+	struct pci_dev	*nb_dev;
+	struct pci_dev	*smbus_dev;
+	int nb_type;
+	int sb_type;
+	int isoc_reqs;
+	int probe_count;
+	int probe_result;
+} amd_chipset;
+
+static DEFINE_SPINLOCK(amd_lock);
+
+int usb_amd_find_chipset_info(void)
+{
+	u8 rev = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_lock, flags);
+
+	amd_chipset.probe_count++;
+	/* probe only once */
+	if (amd_chipset.probe_count > 1) {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return amd_chipset.probe_result;
+	}
+
+	amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
+	if (amd_chipset.smbus_dev) {
+		rev = amd_chipset.smbus_dev->revision;
+		if (rev >= 0x40)
+			amd_chipset.sb_type = 1;
+		else if (rev >= 0x30 && rev <= 0x3b)
+			amd_chipset.sb_type = 3;
+	} else {
+		amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+							0x780b, NULL);
+		if (!amd_chipset.smbus_dev) {
+			spin_unlock_irqrestore(&amd_lock, flags);
+			return 0;
+		}
+		rev = amd_chipset.smbus_dev->revision;
+		if (rev >= 0x11 && rev <= 0x18)
+			amd_chipset.sb_type = 2;
+	}
+
+	if (amd_chipset.sb_type == 0) {
+		if (amd_chipset.smbus_dev) {
+			pci_dev_put(amd_chipset.smbus_dev);
+			amd_chipset.smbus_dev = NULL;
+		}
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return 0;
+	}
+
+	amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL);
+	if (amd_chipset.nb_dev) {
+		amd_chipset.nb_type = 1;
+	} else {
+		amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+							0x1510, NULL);
+		if (amd_chipset.nb_dev) {
+			amd_chipset.nb_type = 2;
+		} else  {
+			amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+								0x9600, NULL);
+			if (amd_chipset.nb_dev)
+				amd_chipset.nb_type = 3;
+		}
+	}
+
+	amd_chipset.probe_result = 1;
+	printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
+
+	spin_unlock_irqrestore(&amd_lock, flags);
+	return amd_chipset.probe_result;
+}
+EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
+
+/*
+ * The hardware normally enables the A-link power management feature, which
+ * lets the system lower the power consumption in idle states.
+ *
+ * This USB quirk prevents the link going into that lower power state
+ * during isochronous transfers.
+ *
+ * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of
+ * some AMD platforms may stutter or have breaks occasionally.
+ */
+static void usb_amd_quirk_pll(int disable)
+{
+	u32 addr, addr_low, addr_high, val;
+	u32 bit = disable ? 0 : 1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_lock, flags);
+
+	if (disable) {
+		amd_chipset.isoc_reqs++;
+		if (amd_chipset.isoc_reqs > 1) {
+			spin_unlock_irqrestore(&amd_lock, flags);
+			return;
+		}
+	} else {
+		amd_chipset.isoc_reqs--;
+		if (amd_chipset.isoc_reqs > 0) {
+			spin_unlock_irqrestore(&amd_lock, flags);
+			return;
+		}
+	}
+
+	if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) {
+		outb_p(AB_REG_BAR_LOW, 0xcd6);
+		addr_low = inb_p(0xcd7);
+		outb_p(AB_REG_BAR_HIGH, 0xcd6);
+		addr_high = inb_p(0xcd7);
+		addr = addr_high << 8 | addr_low;
+
+		outl_p(0x30, AB_INDX(addr));
+		outl_p(0x40, AB_DATA(addr));
+		outl_p(0x34, AB_INDX(addr));
+		val = inl_p(AB_DATA(addr));
+	} else if (amd_chipset.sb_type == 3) {
+		pci_read_config_dword(amd_chipset.smbus_dev,
+					AB_REG_BAR_SB700, &addr);
+		outl(AX_INDXC, AB_INDX(addr));
+		outl(0x40, AB_DATA(addr));
+		outl(AX_DATAC, AB_INDX(addr));
+		val = inl(AB_DATA(addr));
+	} else {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return;
+	}
+
+	if (disable) {
+		val &= ~0x08;
+		val |= (1 << 4) | (1 << 9);
+	} else {
+		val |= 0x08;
+		val &= ~((1 << 4) | (1 << 9));
+	}
+	outl_p(val, AB_DATA(addr));
+
+	if (!amd_chipset.nb_dev) {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return;
+	}
+
+	if (amd_chipset.nb_type == 1 || amd_chipset.nb_type == 3) {
+		addr = PCIE_P_CNTL;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+
+		val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12));
+		val |= bit | (bit << 3) | (bit << 12);
+		val |= ((!bit) << 4) | ((!bit) << 9);
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+
+		addr = BIF_NB;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+		val &= ~(1 << 8);
+		val |= bit << 8;
+
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+	} else if (amd_chipset.nb_type == 2) {
+		addr = NB_PIF0_PWRDOWN_0;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+
+		addr = NB_PIF0_PWRDOWN_1;
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_ADDR, addr);
+		pci_read_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, &val);
+		if (disable)
+			val &= ~(0x3f << 7);
+		else
+			val |= 0x3f << 7;
+
+		pci_write_config_dword(amd_chipset.nb_dev,
+					NB_PCIE_INDX_DATA, val);
+	}
+
+	spin_unlock_irqrestore(&amd_lock, flags);
+	return;
+}
+
+void usb_amd_quirk_pll_disable(void)
+{
+	usb_amd_quirk_pll(1);
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable);
+
+void usb_amd_quirk_pll_enable(void)
+{
+	usb_amd_quirk_pll(0);
+}
+EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable);
+
+void usb_amd_dev_put(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&amd_lock, flags);
+
+	amd_chipset.probe_count--;
+	if (amd_chipset.probe_count > 0) {
+		spin_unlock_irqrestore(&amd_lock, flags);
+		return;
+	}
+
+	if (amd_chipset.nb_dev) {
+		pci_dev_put(amd_chipset.nb_dev);
+		amd_chipset.nb_dev = NULL;
+	}
+	if (amd_chipset.smbus_dev) {
+		pci_dev_put(amd_chipset.smbus_dev);
+		amd_chipset.smbus_dev = NULL;
+	}
+	amd_chipset.nb_type = 0;
+	amd_chipset.sb_type = 0;
+	amd_chipset.isoc_reqs = 0;
+	amd_chipset.probe_result = 0;
+
+	spin_unlock_irqrestore(&amd_lock, flags);
+}
+EXPORT_SYMBOL_GPL(usb_amd_dev_put);
 
 /*
  * Make sure the controller is completely inactive, unable to
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h
index 1564edf..6ae9f78 100644
--- a/drivers/usb/host/pci-quirks.h
+++ b/drivers/usb/host/pci-quirks.h
@@ -1,7 +1,17 @@
 #ifndef __LINUX_USB_PCI_QUIRKS_H
 #define __LINUX_USB_PCI_QUIRKS_H
 
+#ifdef CONFIG_PCI
 void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
 int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
+int usb_amd_find_chipset_info(void);
+void usb_amd_dev_put(void);
+void usb_amd_quirk_pll_disable(void);
+void usb_amd_quirk_pll_enable(void);
+#else
+static inline void usb_amd_quirk_pll_disable(void) {}
+static inline void usb_amd_quirk_pll_enable(void) {}
+static inline void usb_amd_dev_put(void) {}
+#endif  /* CONFIG_PCI */
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 3076b1c..db6f8b9 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -2150,8 +2150,9 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
 	desc->bDescLength = 9;
 	desc->bPwrOn2PwrGood = 0;
 	desc->wHubCharacteristics = cpu_to_le16(0x0011);
-	desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1;
-	desc->bitmap[1] = ~0;
+	desc->u.hs.DeviceRemovable[0] =
+		((1 << r8a66597->max_root_hub) - 1) << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 }
 
 static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 2e9602a..18b7099 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1111,9 +1111,9 @@ sl811h_hub_descriptor (
 
 	desc->wHubCharacteristics = cpu_to_le16(temp);
 
-	/* two bitmaps:  ports removable, and legacy PortPwrCtrlMask */
-	desc->bitmap[0] = 0 << 1;
-	desc->bitmap[1] = ~0;
+	/* ports removable, and legacy PortPwrCtrlMask */
+	desc->u.hs.DeviceRemovable[0] = 0 << 1;
+	desc->u.hs.DeviceRemovable[1] = ~0;
 }
 
 static void
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index fab7649..b478593 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2604,13 +2604,14 @@ static int u132_roothub_descriptor(struct u132 *u132,
 	retval = u132_read_pcimem(u132, roothub.b, &rh_b);
 	if (retval)
 		return retval;
-	memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
-	desc->bitmap[0] = rh_b & RH_B_DR;
+	memset(desc->u.hs.DeviceRemovable, 0xff,
+			sizeof(desc->u.hs.DeviceRemovable));
+	desc->u.hs.DeviceRemovable[0] = rh_b & RH_B_DR;
 	if (u132->num_ports > 7) {
-		desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
-		desc->bitmap[2] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = (rh_b & RH_B_DR) >> 8;
+		desc->u.hs.DeviceRemovable[2] = 0xff;
 	} else
-		desc->bitmap[1] = 0xff;
+		desc->u.hs.DeviceRemovable[1] = 0xff;
 	return 0;
 }
 
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index cee8678..4f65b14 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -471,7 +471,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd)
 
 /*
  * Store the current frame number in uhci->frame_number if the controller
- * is runnning.  Expand from 11 bits (of which we use only 10) to a
+ * is running.  Expand from 11 bits (of which we use only 10) to a
  * full-sized integer.
  *
  * Like many other parts of the driver, this code relies on being polled
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index 78c4eda..ce5c9e5 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -19,8 +19,8 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* Up to 16 microframes to halt an HC - one microframe is 125 microsectonds */
-#define XHCI_MAX_HALT_USEC	(16*125)
+/* Up to 16 ms to halt an HC */
+#define XHCI_MAX_HALT_USEC	(16*1000)
 /* HC not running - set to 1 when run/stop bit is cleared. */
 #define XHCI_STS_HALT		(1<<0)
 
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 5d963e3..a78f2eb 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -28,27 +28,15 @@
 #define	PORT_RWC_BITS	(PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
 			 PORT_RC | PORT_PLC | PORT_PE)
 
-static void xhci_hub_descriptor(struct xhci_hcd *xhci,
-		struct usb_hub_descriptor *desc)
+static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc, int ports)
 {
-	int ports;
 	u16 temp;
 
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
-
-	/* USB 3.0 hubs have a different descriptor, but we fake this for now */
-	desc->bDescriptorType = 0x29;
 	desc->bPwrOn2PwrGood = 10;	/* xhci section 5.4.9 says 20ms max */
 	desc->bHubContrCurrent = 0;
 
 	desc->bNbrPorts = ports;
-	temp = 1 + (ports / 8);
-	desc->bDescLength = 7 + 2 * temp;
-
-	/* Why does core/hcd.h define bitmap?  It's just confusing. */
-	memset(&desc->DeviceRemovable[0], 0, temp);
-	memset(&desc->DeviceRemovable[temp], 0xff, temp);
-
 	/* Ugh, these should be #defines, FIXME */
 	/* Using table 11-13 in USB 2.0 spec. */
 	temp = 0;
@@ -65,14 +53,108 @@ static void xhci_hub_descriptor(struct xhci_hcd *xhci,
 	desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp);
 }
 
+/* Fill in the USB 2.0 roothub descriptor */
+static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc)
+{
+	int ports;
+	u16 temp;
+	__u8 port_removable[(USB_MAXCHILDREN + 1 + 7) / 8];
+	u32 portsc;
+	unsigned int i;
+
+	ports = xhci->num_usb2_ports;
+
+	xhci_common_hub_descriptor(xhci, desc, ports);
+	desc->bDescriptorType = 0x29;
+	temp = 1 + (ports / 8);
+	desc->bDescLength = 7 + 2 * temp;
+
+	/* The Device Removable bits are reported on a byte granularity.
+	 * If the port doesn't exist within that byte, the bit is set to 0.
+	 */
+	memset(port_removable, 0, sizeof(port_removable));
+	for (i = 0; i < ports; i++) {
+		portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+		/* If a device is removable, PORTSC reports a 0, same as in the
+		 * hub descriptor DeviceRemovable bits.
+		 */
+		if (portsc & PORT_DEV_REMOVE)
+			/* This math is hairy because bit 0 of DeviceRemovable
+			 * is reserved, and bit 1 is for port 1, etc.
+			 */
+			port_removable[(i + 1) / 8] |= 1 << ((i + 1) % 8);
+	}
+
+	/* ch11.h defines a hub descriptor that has room for USB_MAXCHILDREN
+	 * ports on it.  The USB 2.0 specification says that there are two
+	 * variable length fields at the end of the hub descriptor:
+	 * DeviceRemovable and PortPwrCtrlMask.  But since we can have less than
+	 * USB_MAXCHILDREN ports, we may need to use the DeviceRemovable array
+	 * to set PortPwrCtrlMask bits.  PortPwrCtrlMask must always be set to
+	 * 0xFF, so we initialize the both arrays (DeviceRemovable and
+	 * PortPwrCtrlMask) to 0xFF.  Then we set the DeviceRemovable for each
+	 * set of ports that actually exist.
+	 */
+	memset(desc->u.hs.DeviceRemovable, 0xff,
+			sizeof(desc->u.hs.DeviceRemovable));
+	memset(desc->u.hs.PortPwrCtrlMask, 0xff,
+			sizeof(desc->u.hs.PortPwrCtrlMask));
+
+	for (i = 0; i < (ports + 1 + 7) / 8; i++)
+		memset(&desc->u.hs.DeviceRemovable[i], port_removable[i],
+				sizeof(__u8));
+}
+
+/* Fill in the USB 3.0 roothub descriptor */
+static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc)
+{
+	int ports;
+	u16 port_removable;
+	u32 portsc;
+	unsigned int i;
+
+	ports = xhci->num_usb3_ports;
+	xhci_common_hub_descriptor(xhci, desc, ports);
+	desc->bDescriptorType = 0x2a;
+	desc->bDescLength = 12;
+
+	/* header decode latency should be zero for roothubs,
+	 * see section 4.23.5.2.
+	 */
+	desc->u.ss.bHubHdrDecLat = 0;
+	desc->u.ss.wHubDelay = 0;
+
+	port_removable = 0;
+	/* bit 0 is reserved, bit 1 is for port 1, etc. */
+	for (i = 0; i < ports; i++) {
+		portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+		if (portsc & PORT_DEV_REMOVE)
+			port_removable |= 1 << (i + 1);
+	}
+	memset(&desc->u.ss.DeviceRemovable,
+			(__force __u16) cpu_to_le16(port_removable),
+			sizeof(__u16));
+}
+
+static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		struct usb_hub_descriptor *desc)
+{
+
+	if (hcd->speed == HCD_USB3)
+		xhci_usb3_hub_descriptor(hcd, xhci, desc);
+	else
+		xhci_usb2_hub_descriptor(hcd, xhci, desc);
+
+}
+
 static unsigned int xhci_port_speed(unsigned int port_status)
 {
 	if (DEV_LOWSPEED(port_status))
 		return USB_PORT_STAT_LOW_SPEED;
 	if (DEV_HIGHSPEED(port_status))
 		return USB_PORT_STAT_HIGH_SPEED;
-	if (DEV_SUPERSPEED(port_status))
-		return USB_PORT_STAT_SUPER_SPEED;
 	/*
 	 * FIXME: Yes, we should check for full speed, but the core uses that as
 	 * a default in portspeed() in usb/core/hub.c (which is the only place
@@ -135,17 +217,22 @@ u32 xhci_port_state_to_neutral(u32 state)
 
 /*
  * find slot id based on port number.
+ * @port: The one-based port number from one of the two split roothubs.
  */
-int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port)
+int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		u16 port)
 {
 	int slot_id;
 	int i;
+	enum usb_device_speed speed;
 
 	slot_id = 0;
 	for (i = 0; i < MAX_HC_SLOTS; i++) {
 		if (!xhci->devs[i])
 			continue;
-		if (xhci->devs[i]->port == port) {
+		speed = xhci->devs[i]->udev->speed;
+		if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3))
+				&& xhci->devs[i]->port == port) {
 			slot_id = i;
 			break;
 		}
@@ -226,11 +313,11 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
 	return;
 }
 
-static void xhci_disable_port(struct xhci_hcd *xhci, u16 wIndex,
-		u32 __iomem *addr, u32 port_status)
+static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		u16 wIndex, u32 __iomem *addr, u32 port_status)
 {
 	/* Don't allow the USB core to disable SuperSpeed ports. */
-	if (xhci->port_array[wIndex] == 0x03) {
+	if (hcd->speed == HCD_USB3) {
 		xhci_dbg(xhci, "Ignoring request to disable "
 				"SuperSpeed port.\n");
 		return;
@@ -289,10 +376,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 	unsigned long flags;
 	u32 temp, temp1, status;
 	int retval = 0;
-	u32 __iomem *addr;
+	u32 __iomem **port_array;
 	int slot_id;
-
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	struct xhci_bus_state *bus_state;
+
+	if (hcd->speed == HCD_USB3) {
+		ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+	} else {
+		ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
 	spin_lock_irqsave(&xhci->lock, flags);
 	switch (typeReq) {
@@ -301,17 +396,35 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		memset(buf, 0, 4);
 		break;
 	case GetHubDescriptor:
-		xhci_hub_descriptor(xhci, (struct usb_hub_descriptor *) buf);
+		/* Check to make sure userspace is asking for the USB 3.0 hub
+		 * descriptor for the USB 3.0 roothub.  If not, we stall the
+		 * endpoint, like external hubs do.
+		 */
+		if (hcd->speed == HCD_USB3 &&
+				(wLength < USB_DT_SS_HUB_SIZE ||
+				 wValue != (USB_DT_SS_HUB << 8))) {
+			xhci_dbg(xhci, "Wrong hub descriptor type for "
+					"USB 3.0 roothub.\n");
+			goto error;
+		}
+		xhci_hub_descriptor(hcd, xhci,
+				(struct usb_hub_descriptor *) buf);
 		break;
 	case GetPortStatus:
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
 		status = 0;
-		addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(wIndex & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[wIndex]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
 		xhci_dbg(xhci, "get port status, actual port %d status  = 0x%x\n", wIndex, temp);
 
+		/* FIXME - should we return a port status value like the USB
+		 * 3.0 external hubs do?
+		 */
 		/* wPortChange bits */
 		if (temp & PORT_CSC)
 			status |= USB_PORT_STAT_C_CONNECTION << 16;
@@ -330,38 +443,33 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			if ((temp & PORT_RESET) || !(temp & PORT_PE))
 				goto error;
 			if (!DEV_SUPERSPEED(temp) && time_after_eq(jiffies,
-						xhci->resume_done[wIndex])) {
+						bus_state->resume_done[wIndex])) {
 				xhci_dbg(xhci, "Resume USB2 port %d\n",
 					wIndex + 1);
-				xhci->resume_done[wIndex] = 0;
+				bus_state->resume_done[wIndex] = 0;
 				temp1 = xhci_port_state_to_neutral(temp);
 				temp1 &= ~PORT_PLS_MASK;
 				temp1 |= PORT_LINK_STROBE | XDEV_U0;
-				xhci_writel(xhci, temp1, addr);
+				xhci_writel(xhci, temp1, port_array[wIndex]);
 
 				xhci_dbg(xhci, "set port %d resume\n",
 					wIndex + 1);
-				slot_id = xhci_find_slot_id_by_port(xhci,
+				slot_id = xhci_find_slot_id_by_port(hcd, xhci,
 								 wIndex + 1);
 				if (!slot_id) {
 					xhci_dbg(xhci, "slot_id is zero\n");
 					goto error;
 				}
 				xhci_ring_device(xhci, slot_id);
-				xhci->port_c_suspend[wIndex >> 5] |=
-						1 << (wIndex & 31);
-				xhci->suspended_ports[wIndex >> 5] &=
-						~(1 << (wIndex & 31));
+				bus_state->port_c_suspend |= 1 << wIndex;
+				bus_state->suspended_ports &= ~(1 << wIndex);
 			}
 		}
 		if ((temp & PORT_PLS_MASK) == XDEV_U0
 			&& (temp & PORT_POWER)
-			&& (xhci->suspended_ports[wIndex >> 5] &
-			    (1 << (wIndex & 31)))) {
-			xhci->suspended_ports[wIndex >> 5] &=
-					~(1 << (wIndex & 31));
-			xhci->port_c_suspend[wIndex >> 5] |=
-					1 << (wIndex & 31);
+			&& (bus_state->suspended_ports & (1 << wIndex))) {
+			bus_state->suspended_ports &= ~(1 << wIndex);
+			bus_state->port_c_suspend |= 1 << wIndex;
 		}
 		if (temp & PORT_CONNECT) {
 			status |= USB_PORT_STAT_CONNECTION;
@@ -375,7 +483,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			status |= USB_PORT_STAT_RESET;
 		if (temp & PORT_POWER)
 			status |= USB_PORT_STAT_POWER;
-		if (xhci->port_c_suspend[wIndex >> 5] & (1 << (wIndex & 31)))
+		if (bus_state->port_c_suspend & (1 << wIndex))
 			status |= 1 << USB_PORT_FEAT_C_SUSPEND;
 		xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
 		put_unaligned(cpu_to_le32(status), (__le32 *) buf);
@@ -385,12 +493,16 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS*(wIndex & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[wIndex]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
 		temp = xhci_port_state_to_neutral(temp);
+		/* FIXME: What new port features do we need to support? */
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			/* In spec software should not attempt to suspend
 			 * a port unless the port reports that it is in the
 			 * enabled (PED = â1â,PLS < â3â) state.
@@ -402,7 +514,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 				goto error;
 			}
 
-			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					wIndex + 1);
 			if (!slot_id) {
 				xhci_warn(xhci, "slot_id is zero\n");
 				goto error;
@@ -415,15 +528,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			temp = xhci_port_state_to_neutral(temp);
 			temp &= ~PORT_PLS_MASK;
 			temp |= PORT_LINK_STROBE | XDEV_U3;
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[wIndex]);
 
 			spin_unlock_irqrestore(&xhci->lock, flags);
 			msleep(10); /* wait device to enter */
 			spin_lock_irqsave(&xhci->lock, flags);
 
-			temp = xhci_readl(xhci, addr);
-			xhci->suspended_ports[wIndex >> 5] |=
-					1 << (wIndex & (31));
+			temp = xhci_readl(xhci, port_array[wIndex]);
+			bus_state->suspended_ports |= 1 << wIndex;
 			break;
 		case USB_PORT_FEAT_POWER:
 			/*
@@ -432,34 +544,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			 * However, khubd will ignore the roothub events until
 			 * the roothub is registered.
 			 */
-			xhci_writel(xhci, temp | PORT_POWER, addr);
+			xhci_writel(xhci, temp | PORT_POWER,
+					port_array[wIndex]);
 
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);
 			break;
 		case USB_PORT_FEAT_RESET:
 			temp = (temp | PORT_RESET);
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[wIndex]);
 
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "set port reset, actual port %d status  = 0x%x\n", wIndex, temp);
 			break;
 		default:
 			goto error;
 		}
-		temp = xhci_readl(xhci, addr); /* unblock any posted writes */
+		/* unblock any posted writes */
+		temp = xhci_readl(xhci, port_array[wIndex]);
 		break;
 	case ClearPortFeature:
 		if (!wIndex || wIndex > ports)
 			goto error;
 		wIndex--;
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS*(wIndex & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[wIndex]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
+		/* FIXME: What new port features do we need to support? */
 		temp = xhci_port_state_to_neutral(temp);
 		switch (wValue) {
 		case USB_PORT_FEAT_SUSPEND:
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[wIndex]);
 			xhci_dbg(xhci, "clear USB_PORT_FEAT_SUSPEND\n");
 			xhci_dbg(xhci, "PORTSC %04x\n", temp);
 			if (temp & PORT_RESET)
@@ -471,30 +588,34 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 					temp = xhci_port_state_to_neutral(temp);
 					temp &= ~PORT_PLS_MASK;
 					temp |= PORT_LINK_STROBE | XDEV_U0;
-					xhci_writel(xhci, temp, addr);
-					xhci_readl(xhci, addr);
+					xhci_writel(xhci, temp,
+							port_array[wIndex]);
+					xhci_readl(xhci, port_array[wIndex]);
 				} else {
 					temp = xhci_port_state_to_neutral(temp);
 					temp &= ~PORT_PLS_MASK;
 					temp |= PORT_LINK_STROBE | XDEV_RESUME;
-					xhci_writel(xhci, temp, addr);
+					xhci_writel(xhci, temp,
+							port_array[wIndex]);
 
 					spin_unlock_irqrestore(&xhci->lock,
 							       flags);
 					msleep(20);
 					spin_lock_irqsave(&xhci->lock, flags);
 
-					temp = xhci_readl(xhci, addr);
+					temp = xhci_readl(xhci,
+							port_array[wIndex]);
 					temp = xhci_port_state_to_neutral(temp);
 					temp &= ~PORT_PLS_MASK;
 					temp |= PORT_LINK_STROBE | XDEV_U0;
-					xhci_writel(xhci, temp, addr);
+					xhci_writel(xhci, temp,
+							port_array[wIndex]);
 				}
-				xhci->port_c_suspend[wIndex >> 5] |=
-						1 << (wIndex & 31);
+				bus_state->port_c_suspend |= 1 << wIndex;
 			}
 
-			slot_id = xhci_find_slot_id_by_port(xhci, wIndex + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					wIndex + 1);
 			if (!slot_id) {
 				xhci_dbg(xhci, "slot_id is zero\n");
 				goto error;
@@ -502,17 +623,17 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
 			xhci_ring_device(xhci, slot_id);
 			break;
 		case USB_PORT_FEAT_C_SUSPEND:
-			xhci->port_c_suspend[wIndex >> 5] &=
-					~(1 << (wIndex & 31));
+			bus_state->port_c_suspend &= ~(1 << wIndex);
 		case USB_PORT_FEAT_C_RESET:
 		case USB_PORT_FEAT_C_CONNECTION:
 		case USB_PORT_FEAT_C_OVER_CURRENT:
 		case USB_PORT_FEAT_C_ENABLE:
 			xhci_clear_port_change_bit(xhci, wValue, wIndex,
-					addr, temp);
+					port_array[wIndex], temp);
 			break;
 		case USB_PORT_FEAT_ENABLE:
-			xhci_disable_port(xhci, wIndex, addr, temp);
+			xhci_disable_port(hcd, xhci, wIndex,
+					port_array[wIndex], temp);
 			break;
 		default:
 			goto error;
@@ -543,9 +664,17 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 	int i, retval;
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int ports;
-	u32 __iomem *addr;
-
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	u32 __iomem **port_array;
+	struct xhci_bus_state *bus_state;
+
+	if (hcd->speed == HCD_USB3) {
+		ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+	} else {
+		ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
 	/* Initial status is no changes */
 	retval = (ports + 8) / 8;
@@ -557,13 +686,15 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 	spin_lock_irqsave(&xhci->lock, flags);
 	/* For each port, did anything change?  If so, set that bit in buf. */
 	for (i = 0; i < ports; i++) {
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS*i;
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[i]);
+		if (temp == 0xffffffff) {
+			retval = -ENODEV;
+			break;
+		}
 		if ((temp & mask) != 0 ||
-			(xhci->port_c_suspend[i >> 5] &	1 << (i & 31)) ||
-			(xhci->resume_done[i] && time_after_eq(
-			    jiffies, xhci->resume_done[i]))) {
+			(bus_state->port_c_suspend & 1 << i) ||
+			(bus_state->resume_done[i] && time_after_eq(
+			    jiffies, bus_state->resume_done[i]))) {
 			buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
 			status = 1;
 		}
@@ -577,42 +708,51 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
 int xhci_bus_suspend(struct usb_hcd *hcd)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	int port;
+	int max_ports, port_index;
+	u32 __iomem **port_array;
+	struct xhci_bus_state *bus_state;
 	unsigned long flags;
 
-	xhci_dbg(xhci, "suspend root hub\n");
+	if (hcd->speed == HCD_USB3) {
+		max_ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+		xhci_dbg(xhci, "suspend USB 3.0 root hub\n");
+	} else {
+		max_ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+		xhci_dbg(xhci, "suspend USB 2.0 root hub\n");
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
 	spin_lock_irqsave(&xhci->lock, flags);
 
 	if (hcd->self.root_hub->do_remote_wakeup) {
-		port = HCS_MAX_PORTS(xhci->hcs_params1);
-		while (port--) {
-			if (xhci->resume_done[port] != 0) {
+		port_index = max_ports;
+		while (port_index--) {
+			if (bus_state->resume_done[port_index] != 0) {
 				spin_unlock_irqrestore(&xhci->lock, flags);
 				xhci_dbg(xhci, "suspend failed because "
 						"port %d is resuming\n",
-						port + 1);
+						port_index + 1);
 				return -EBUSY;
 			}
 		}
 	}
 
-	port = HCS_MAX_PORTS(xhci->hcs_params1);
-	xhci->bus_suspended = 0;
-	while (port--) {
+	port_index = max_ports;
+	bus_state->bus_suspended = 0;
+	while (port_index--) {
 		/* suspend the port if the port is not suspended */
-		u32 __iomem *addr;
 		u32 t1, t2;
 		int slot_id;
 
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS * (port & 0xff);
-		t1 = xhci_readl(xhci, addr);
+		t1 = xhci_readl(xhci, port_array[port_index]);
 		t2 = xhci_port_state_to_neutral(t1);
 
 		if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
-			xhci_dbg(xhci, "port %d not suspended\n", port);
-			slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
+			xhci_dbg(xhci, "port %d not suspended\n", port_index);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					port_index + 1);
 			if (slot_id) {
 				spin_unlock_irqrestore(&xhci->lock, flags);
 				xhci_stop_device(xhci, slot_id, 1);
@@ -620,7 +760,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 			}
 			t2 &= ~PORT_PLS_MASK;
 			t2 |= PORT_LINK_STROBE | XDEV_U3;
-			set_bit(port, &xhci->bus_suspended);
+			set_bit(port_index, &bus_state->bus_suspended);
 		}
 		if (hcd->self.root_hub->do_remote_wakeup) {
 			if (t1 & PORT_CONNECT) {
@@ -635,22 +775,24 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 
 		t1 = xhci_port_state_to_neutral(t1);
 		if (t1 != t2)
-			xhci_writel(xhci, t2, addr);
+			xhci_writel(xhci, t2, port_array[port_index]);
 
 		if (DEV_HIGHSPEED(t1)) {
 			/* enable remote wake up for USB 2.0 */
 			u32 __iomem *addr;
 			u32 tmp;
 
-			addr = &xhci->op_regs->port_power_base +
-				NUM_PORT_REGS * (port & 0xff);
+			/* Add one to the port status register address to get
+			 * the port power control register address.
+			 */
+			addr = port_array[port_index] + 1;
 			tmp = xhci_readl(xhci, addr);
 			tmp |= PORT_RWE;
 			xhci_writel(xhci, tmp, addr);
 		}
 	}
 	hcd->state = HC_STATE_SUSPENDED;
-	xhci->next_statechange = jiffies + msecs_to_jiffies(10);
+	bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return 0;
 }
@@ -658,13 +800,24 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
 int xhci_bus_resume(struct usb_hcd *hcd)
 {
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
-	int port;
+	int max_ports, port_index;
+	u32 __iomem **port_array;
+	struct xhci_bus_state *bus_state;
 	u32 temp;
 	unsigned long flags;
 
-	xhci_dbg(xhci, "resume root hub\n");
+	if (hcd->speed == HCD_USB3) {
+		max_ports = xhci->num_usb3_ports;
+		port_array = xhci->usb3_ports;
+		xhci_dbg(xhci, "resume USB 3.0 root hub\n");
+	} else {
+		max_ports = xhci->num_usb2_ports;
+		port_array = xhci->usb2_ports;
+		xhci_dbg(xhci, "resume USB 2.0 root hub\n");
+	}
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
 
-	if (time_before(jiffies, xhci->next_statechange))
+	if (time_before(jiffies, bus_state->next_statechange))
 		msleep(5);
 
 	spin_lock_irqsave(&xhci->lock, flags);
@@ -678,57 +831,57 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 	temp &= ~CMD_EIE;
 	xhci_writel(xhci, temp, &xhci->op_regs->command);
 
-	port = HCS_MAX_PORTS(xhci->hcs_params1);
-	while (port--) {
+	port_index = max_ports;
+	while (port_index--) {
 		/* Check whether need resume ports. If needed
 		   resume port and disable remote wakeup */
-		u32 __iomem *addr;
 		u32 temp;
 		int slot_id;
 
-		addr = &xhci->op_regs->port_status_base +
-			NUM_PORT_REGS * (port & 0xff);
-		temp = xhci_readl(xhci, addr);
+		temp = xhci_readl(xhci, port_array[port_index]);
 		if (DEV_SUPERSPEED(temp))
 			temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
 		else
 			temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
-		if (test_bit(port, &xhci->bus_suspended) &&
+		if (test_bit(port_index, &bus_state->bus_suspended) &&
 		    (temp & PORT_PLS_MASK)) {
 			if (DEV_SUPERSPEED(temp)) {
 				temp = xhci_port_state_to_neutral(temp);
 				temp &= ~PORT_PLS_MASK;
 				temp |= PORT_LINK_STROBE | XDEV_U0;
-				xhci_writel(xhci, temp, addr);
+				xhci_writel(xhci, temp, port_array[port_index]);
 			} else {
 				temp = xhci_port_state_to_neutral(temp);
 				temp &= ~PORT_PLS_MASK;
 				temp |= PORT_LINK_STROBE | XDEV_RESUME;
-				xhci_writel(xhci, temp, addr);
+				xhci_writel(xhci, temp, port_array[port_index]);
 
 				spin_unlock_irqrestore(&xhci->lock, flags);
 				msleep(20);
 				spin_lock_irqsave(&xhci->lock, flags);
 
-				temp = xhci_readl(xhci, addr);
+				temp = xhci_readl(xhci, port_array[port_index]);
 				temp = xhci_port_state_to_neutral(temp);
 				temp &= ~PORT_PLS_MASK;
 				temp |= PORT_LINK_STROBE | XDEV_U0;
-				xhci_writel(xhci, temp, addr);
+				xhci_writel(xhci, temp, port_array[port_index]);
 			}
-			slot_id = xhci_find_slot_id_by_port(xhci, port + 1);
+			slot_id = xhci_find_slot_id_by_port(hcd,
+					xhci, port_index + 1);
 			if (slot_id)
 				xhci_ring_device(xhci, slot_id);
 		} else
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[port_index]);
 
 		if (DEV_HIGHSPEED(temp)) {
 			/* disable remote wake up for USB 2.0 */
 			u32 __iomem *addr;
 			u32 tmp;
 
-			addr = &xhci->op_regs->port_power_base +
-				NUM_PORT_REGS * (port & 0xff);
+			/* Add one to the port status register address to get
+			 * the port power control register address.
+			 */
+			addr = port_array[port_index] + 1;
 			tmp = xhci_readl(xhci, addr);
 			tmp &= ~PORT_RWE;
 			xhci_writel(xhci, tmp, addr);
@@ -737,8 +890,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 
 	(void) xhci_readl(xhci, &xhci->op_regs->command);
 
-	xhci->next_statechange = jiffies + msecs_to_jiffies(5);
-	hcd->state = HC_STATE_RUNNING;
+	bus_state->next_statechange = jiffies + msecs_to_jiffies(5);
 	/* re-enable irqs */
 	temp = xhci_readl(xhci, &xhci->op_regs->command);
 	temp |= CMD_EIE;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index a953439..a003e79 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -814,14 +814,64 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
 	ep0_ctx->deq |= ep_ring->cycle_state;
 }
 
+/*
+ * The xHCI roothub may have ports of differing speeds in any order in the port
+ * status registers.  xhci->port_array provides an array of the port speed for
+ * each offset into the port status registers.
+ *
+ * The xHCI hardware wants to know the roothub port number that the USB device
+ * is attached to (or the roothub port its ancestor hub is attached to).  All we
+ * know is the index of that port under either the USB 2.0 or the USB 3.0
+ * roothub, but that doesn't give us the real index into the HW port status
+ * registers.  Scan through the xHCI roothub port array, looking for the Nth
+ * entry of the correct port speed.  Return the port number of that entry.
+ */
+static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
+		struct usb_device *udev)
+{
+	struct usb_device *top_dev;
+	unsigned int num_similar_speed_ports;
+	unsigned int faked_port_num;
+	int i;
+
+	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
+			top_dev = top_dev->parent)
+		/* Found device below root hub */;
+	faked_port_num = top_dev->portnum;
+	for (i = 0, num_similar_speed_ports = 0;
+			i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
+		u8 port_speed = xhci->port_array[i];
+
+		/*
+		 * Skip ports that don't have known speeds, or have duplicate
+		 * Extended Capabilities port speed entries.
+		 */
+		if (port_speed == 0 || port_speed == -1)
+			continue;
+
+		/*
+		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and
+		 * 1.1 ports are under the USB 2.0 hub.  If the port speed
+		 * matches the device speed, it's a similar speed port.
+		 */
+		if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER))
+			num_similar_speed_ports++;
+		if (num_similar_speed_ports == faked_port_num)
+			/* Roothub ports are numbered from 1 to N */
+			return i+1;
+	}
+	return 0;
+}
+
 /* Setup an xHCI virtual device for a Set Address command */
 int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev)
 {
 	struct xhci_virt_device *dev;
 	struct xhci_ep_ctx	*ep0_ctx;
-	struct usb_device	*top_dev;
 	struct xhci_slot_ctx    *slot_ctx;
 	struct xhci_input_control_ctx *ctrl_ctx;
+	u32			port_num;
+	struct usb_device *top_dev;
 
 	dev = xhci->devs[udev->slot_id];
 	/* Slot ID 0 is reserved */
@@ -863,16 +913,20 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
 		BUG();
 	}
 	/* Find the root hub port this device is under */
+	port_num = xhci_find_real_port_number(xhci, udev);
+	if (!port_num)
+		return -EINVAL;
+	slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(port_num);
+	/* Set the port number in the virtual_device to the faked port number */
 	for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
 			top_dev = top_dev->parent)
 		/* Found device below root hub */;
-	slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(top_dev->portnum);
 	dev->port = top_dev->portnum;
-	xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum);
+	xhci_dbg(xhci, "Set root hub portnum to %d\n", port_num);
+	xhci_dbg(xhci, "Set fake root hub portnum to %d\n", dev->port);
 
-	/* Is this a LS/FS device under a HS hub? */
-	if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) &&
-			udev->tt) {
+	/* Is this a LS/FS device under an external HS hub? */
+	if (udev->tt && udev->tt->hub->parent) {
 		slot_ctx->tt_info = udev->tt->hub->slot_id;
 		slot_ctx->tt_info |= udev->ttport << 8;
 		if (udev->tt->multi)
@@ -1452,7 +1506,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
 	xhci->page_size = 0;
 	xhci->page_shift = 0;
-	xhci->bus_suspended = 0;
+	xhci->bus_state[0].bus_suspended = 0;
+	xhci->bus_state[1].bus_suspended = 0;
 }
 
 static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@@ -1748,6 +1803,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 	}
 	xhci_dbg(xhci, "Found %u USB 2.0 ports and %u USB 3.0 ports.\n",
 			xhci->num_usb2_ports, xhci->num_usb3_ports);
+
+	/* Place limits on the number of roothub ports so that the hub
+	 * descriptors aren't longer than the USB core will allocate.
+	 */
+	if (xhci->num_usb3_ports > 15) {
+		xhci_dbg(xhci, "Limiting USB 3.0 roothub ports to 15.\n");
+		xhci->num_usb3_ports = 15;
+	}
+	if (xhci->num_usb2_ports > USB_MAXCHILDREN) {
+		xhci_dbg(xhci, "Limiting USB 2.0 roothub ports to %u.\n",
+				USB_MAXCHILDREN);
+		xhci->num_usb2_ports = USB_MAXCHILDREN;
+	}
+
 	/*
 	 * Note we could have all USB 3.0 ports, or all USB 2.0 ports.
 	 * Not sure how the USB core will handle a hub with no ports...
@@ -1772,6 +1841,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 					"addr = %p\n", i,
 					xhci->usb2_ports[port_index]);
 			port_index++;
+			if (port_index == xhci->num_usb2_ports)
+				break;
 		}
 	}
 	if (xhci->num_usb3_ports) {
@@ -1790,6 +1861,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
 						"addr = %p\n", i,
 						xhci->usb3_ports[port_index]);
 				port_index++;
+				if (port_index == xhci->num_usb3_ports)
+					break;
 			}
 	}
 	return 0;
@@ -1971,8 +2044,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 	init_completion(&xhci->addr_dev);
 	for (i = 0; i < MAX_HC_SLOTS; ++i)
 		xhci->devs[i] = NULL;
-	for (i = 0; i < MAX_HC_PORTS; ++i)
-		xhci->resume_done[i] = 0;
+	for (i = 0; i < USB_MAXCHILDREN; ++i) {
+		xhci->bus_state[0].resume_done[i] = 0;
+		xhci->bus_state[1].resume_done[i] = 0;
+	}
 
 	if (scratchpad_alloc(xhci, flags))
 		goto fail;
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index bb668a8..ceea9f3 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -50,13 +50,45 @@ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
 /* called during probe() after chip reset completes */
 static int xhci_pci_setup(struct usb_hcd *hcd)
 {
-	struct xhci_hcd		*xhci = hcd_to_xhci(hcd);
+	struct xhci_hcd		*xhci;
 	struct pci_dev		*pdev = to_pci_dev(hcd->self.controller);
 	int			retval;
 	u32			temp;
 
 	hcd->self.sg_tablesize = TRBS_PER_SEGMENT - 2;
 
+	if (usb_hcd_is_primary_hcd(hcd)) {
+		xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);
+		if (!xhci)
+			return -ENOMEM;
+		*((struct xhci_hcd **) hcd->hcd_priv) = xhci;
+		xhci->main_hcd = hcd;
+		/* Mark the first roothub as being USB 2.0.
+		 * The xHCI driver will register the USB 3.0 roothub.
+		 */
+		hcd->speed = HCD_USB2;
+		hcd->self.root_hub->speed = USB_SPEED_HIGH;
+		/*
+		 * USB 2.0 roothub under xHCI has an integrated TT,
+		 * (rate matching hub) as opposed to having an OHCI/UHCI
+		 * companion controller.
+		 */
+		hcd->has_tt = 1;
+	} else {
+		/* xHCI private pointer was set in xhci_pci_probe for the second
+		 * registered roothub.
+		 */
+		xhci = hcd_to_xhci(hcd);
+		temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
+		if (HCC_64BIT_ADDR(temp)) {
+			xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+		} else {
+			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+		}
+		return 0;
+	}
+
 	xhci->cap_regs = hcd->regs;
 	xhci->op_regs = hcd->regs +
 		HC_LENGTH(xhci_readl(xhci, &xhci->cap_regs->hc_capbase));
@@ -85,13 +117,13 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
 	/* Make sure the HC is halted. */
 	retval = xhci_halt(xhci);
 	if (retval)
-		return retval;
+		goto error;
 
 	xhci_dbg(xhci, "Resetting HCD\n");
 	/* Reset the internal HC memory state and registers. */
 	retval = xhci_reset(xhci);
 	if (retval)
-		return retval;
+		goto error;
 	xhci_dbg(xhci, "Reset complete\n");
 
 	temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
@@ -106,14 +138,85 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
 	/* Initialize HCD and host controller data structures. */
 	retval = xhci_init(hcd);
 	if (retval)
-		return retval;
+		goto error;
 	xhci_dbg(xhci, "Called HCD init\n");
 
 	pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
 	xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
 
 	/* Find any debug ports */
-	return xhci_pci_reinit(xhci, pdev);
+	retval = xhci_pci_reinit(xhci, pdev);
+	if (!retval)
+		return retval;
+
+error:
+	kfree(xhci);
+	return retval;
+}
+
+/*
+ * We need to register our own PCI probe function (instead of the USB core's
+ * function) in order to create a second roothub under xHCI.
+ */
+static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	int retval;
+	struct xhci_hcd *xhci;
+	struct hc_driver *driver;
+	struct usb_hcd *hcd;
+
+	driver = (struct hc_driver *)id->driver_data;
+	/* Register the USB 2.0 roothub.
+	 * FIXME: USB core must know to register the USB 2.0 roothub first.
+	 * This is sort of silly, because we could just set the HCD driver flags
+	 * to say USB 2.0, but I'm not sure what the implications would be in
+	 * the other parts of the HCD code.
+	 */
+	retval = usb_hcd_pci_probe(dev, id);
+
+	if (retval)
+		return retval;
+
+	/* USB 2.0 roothub is stored in the PCI device now. */
+	hcd = dev_get_drvdata(&dev->dev);
+	xhci = hcd_to_xhci(hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(driver, &dev->dev,
+				pci_name(dev), hcd);
+	if (!xhci->shared_hcd) {
+		retval = -ENOMEM;
+		goto dealloc_usb2_hcd;
+	}
+
+	/* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset)
+	 * is called by usb_add_hcd().
+	 */
+	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
+
+	retval = usb_add_hcd(xhci->shared_hcd, dev->irq,
+			IRQF_DISABLED | IRQF_SHARED);
+	if (retval)
+		goto put_usb3_hcd;
+	/* Roothub already marked as USB 3.0 speed */
+	return 0;
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+dealloc_usb2_hcd:
+	usb_hcd_pci_remove(dev);
+	return retval;
+}
+
+static void xhci_pci_remove(struct pci_dev *dev)
+{
+	struct xhci_hcd *xhci;
+
+	xhci = hcd_to_xhci(pci_get_drvdata(dev));
+	if (xhci->shared_hcd) {
+		usb_remove_hcd(xhci->shared_hcd);
+		usb_put_hcd(xhci->shared_hcd);
+	}
+	usb_hcd_pci_remove(dev);
+	kfree(xhci);
 }
 
 #ifdef CONFIG_PM
@@ -122,7 +225,8 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int	retval = 0;
 
-	if (hcd->state != HC_STATE_SUSPENDED)
+	if (hcd->state != HC_STATE_SUSPENDED ||
+			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
 		return -EINVAL;
 
 	retval = xhci_suspend(xhci);
@@ -143,13 +247,13 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 static const struct hc_driver xhci_pci_hc_driver = {
 	.description =		hcd_name,
 	.product_desc =		"xHCI Host Controller",
-	.hcd_priv_size =	sizeof(struct xhci_hcd),
+	.hcd_priv_size =	sizeof(struct xhci_hcd *),
 
 	/*
 	 * generic hardware linkage
 	 */
 	.irq =			xhci_irq,
-	.flags =		HCD_MEMORY | HCD_USB3,
+	.flags =		HCD_MEMORY | HCD_USB3 | HCD_SHARED,
 
 	/*
 	 * basic lifecycle operations
@@ -210,8 +314,8 @@ static struct pci_driver xhci_pci_driver = {
 	.name =		(char *) hcd_name,
 	.id_table =	pci_ids,
 
-	.probe =	usb_hcd_pci_probe,
-	.remove =	usb_hcd_pci_remove,
+	.probe =	xhci_pci_probe,
+	.remove =	xhci_pci_remove,
 	/* suspend and resume implemented later */
 
 	.shutdown = 	usb_hcd_pci_shutdown,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3289bf4..cfc1ad9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -380,10 +380,8 @@ static struct xhci_segment *find_trb_seg(
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
 		generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-		if ((generic_trb->field[3] & TRB_TYPE_BITMASK) ==
-				TRB_TYPE(TRB_LINK) &&
-				(generic_trb->field[3] & LINK_TOGGLE))
-			*cycle_state = ~(*cycle_state) & 0x1;
+		if (generic_trb->field[3] & LINK_TOGGLE)
+			*cycle_state ^= 0x1;
 		cur_seg = cur_seg->next;
 		if (cur_seg == start_seg)
 			/* Looped over the entire list.  Oops! */
@@ -497,18 +495,29 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	trb = &state->new_deq_ptr->generic;
 	if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) &&
 				(trb->field[3] & LINK_TOGGLE))
-		state->new_cycle_state = ~(state->new_cycle_state) & 0x1;
+		state->new_cycle_state ^= 0x1;
 	next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
 
+	/*
+	 * If there is only one segment in a ring, find_trb_seg()'s while loop
+	 * will not run, and it will return before it has a chance to see if it
+	 * needs to toggle the cycle bit.  It can't tell if the stalled transfer
+	 * ended just before the link TRB on a one-segment ring, or if the TD
+	 * wrapped around the top of the ring, because it doesn't have the TD in
+	 * question.  Look for the one-segment case where stalled TRB's address
+	 * is greater than the new dequeue pointer address.
+	 */
+	if (ep_ring->first_seg == ep_ring->first_seg->next &&
+			state->new_deq_ptr < dev->eps[ep_index].stopped_trb)
+		state->new_cycle_state ^= 0x1;
+	xhci_dbg(xhci, "Cycle state = 0x%x\n", state->new_cycle_state);
+
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg(xhci, "New dequeue segment = %p (virtual)\n",
 			state->new_deq_seg);
 	addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
 	xhci_dbg(xhci, "New dequeue pointer = 0x%llx (DMA)\n",
 			(unsigned long long) addr);
-	xhci_dbg(xhci, "Setting dequeue pointer in internal ring state.\n");
-	ep_ring->dequeue = state->new_deq_ptr;
-	ep_ring->deq_seg = state->new_deq_seg;
 }
 
 static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
@@ -599,13 +608,14 @@ static inline void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci,
 static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
 		struct xhci_td *cur_td, int status, char *adjective)
 {
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct usb_hcd *hcd;
 	struct urb	*urb;
 	struct urb_priv	*urb_priv;
 
 	urb = cur_td->urb;
 	urb_priv = urb->hcpriv;
 	urb_priv->td_cnt++;
+	hcd = bus_to_hcd(urb->dev->bus);
 
 	/* Only giveback urb when this is the last td in urb */
 	if (urb_priv->td_cnt == urb_priv->length) {
@@ -824,8 +834,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
 	if (ret < 0) {
 		/* This is bad; the host is not responding to commands and it's
 		 * not allowing itself to be halted.  At least interrupts are
-		 * disabled, so we can set HC_STATE_HALT and notify the
-		 * USB core.  But if we call usb_hc_died(), it will attempt to
+		 * disabled. If we call usb_hc_died(), it will attempt to
 		 * disconnect all device drivers under this host.  Those
 		 * disconnect() methods will wait for all URBs to be unlinked,
 		 * so we must complete them.
@@ -870,9 +879,8 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
 		}
 	}
 	spin_unlock(&xhci->lock);
-	xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 	xhci_dbg(xhci, "Calling usb_hc_died()\n");
-	usb_hc_died(xhci_to_hcd(xhci));
+	usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
 	xhci_dbg(xhci, "xHCI host controller is dead.\n");
 }
 
@@ -951,9 +959,26 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
 	} else {
 		xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
 				ep_ctx->deq);
+		if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg,
+					dev->eps[ep_index].queued_deq_ptr) ==
+				(ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) {
+			/* Update the ring's dequeue segment and dequeue pointer
+			 * to reflect the new position.
+			 */
+			ep_ring->deq_seg = dev->eps[ep_index].queued_deq_seg;
+			ep_ring->dequeue = dev->eps[ep_index].queued_deq_ptr;
+		} else {
+			xhci_warn(xhci, "Mismatch between completed Set TR Deq "
+					"Ptr command & xHCI internal state.\n");
+			xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
+					dev->eps[ep_index].queued_deq_seg,
+					dev->eps[ep_index].queued_deq_ptr);
+		}
 	}
 
 	dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
+	dev->eps[ep_index].queued_deq_seg = NULL;
+	dev->eps[ep_index].queued_deq_ptr = NULL;
 	/* Restart any rings with pending URBs */
 	ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
@@ -1118,7 +1143,6 @@ bandwidth_change:
 		handle_set_deq_completion(xhci, event, xhci->cmd_ring->dequeue);
 		break;
 	case TRB_TYPE(TRB_CMD_NOOP):
-		++xhci->noops_handled;
 		break;
 	case TRB_TYPE(TRB_RESET_EP):
 		handle_reset_ep_completion(xhci, event, xhci->cmd_ring->dequeue);
@@ -1162,15 +1186,55 @@ static void handle_vendor_event(struct xhci_hcd *xhci,
 		handle_cmd_completion(xhci, &event->event_cmd);
 }
 
+/* @port_id: the one-based port ID from the hardware (indexed from array of all
+ * port registers -- USB 3.0 and USB 2.0).
+ *
+ * Returns a zero-based port number, which is suitable for indexing into each of
+ * the split roothubs' port arrays and bus state arrays.
+ */
+static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
+		struct xhci_hcd *xhci, u32 port_id)
+{
+	unsigned int i;
+	unsigned int num_similar_speed_ports = 0;
+
+	/* port_id from the hardware is 1-based, but port_array[], usb3_ports[],
+	 * and usb2_ports are 0-based indexes.  Count the number of similar
+	 * speed ports, up to 1 port before this port.
+	 */
+	for (i = 0; i < (port_id - 1); i++) {
+		u8 port_speed = xhci->port_array[i];
+
+		/*
+		 * Skip ports that don't have known speeds, or have duplicate
+		 * Extended Capabilities port speed entries.
+		 */
+		if (port_speed == 0 || port_speed == -1)
+			continue;
+
+		/*
+		 * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and
+		 * 1.1 ports are under the USB 2.0 hub.  If the port speed
+		 * matches the device speed, it's a similar speed port.
+		 */
+		if ((port_speed == 0x03) == (hcd->speed == HCD_USB3))
+			num_similar_speed_ports++;
+	}
+	return num_similar_speed_ports;
+}
+
 static void handle_port_status(struct xhci_hcd *xhci,
 		union xhci_trb *event)
 {
-	struct usb_hcd *hcd = xhci_to_hcd(xhci);
+	struct usb_hcd *hcd;
 	u32 port_id;
 	u32 temp, temp1;
-	u32 __iomem *addr;
-	int ports;
+	int max_ports;
 	int slot_id;
+	unsigned int faked_port_index;
+	u8 major_revision;
+	struct xhci_bus_state *bus_state;
+	u32 __iomem **port_array;
 
 	/* Port status change events always have a successful completion code */
 	if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
@@ -1180,14 +1244,50 @@ static void handle_port_status(struct xhci_hcd *xhci,
 	port_id = GET_PORT_ID(event->generic.field[0]);
 	xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
 
-	ports = HCS_MAX_PORTS(xhci->hcs_params1);
-	if ((port_id <= 0) || (port_id > ports)) {
+	max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
+	if ((port_id <= 0) || (port_id > max_ports)) {
 		xhci_warn(xhci, "Invalid port id %d\n", port_id);
 		goto cleanup;
 	}
 
-	addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1);
-	temp = xhci_readl(xhci, addr);
+	/* Figure out which usb_hcd this port is attached to:
+	 * is it a USB 3.0 port or a USB 2.0/1.1 port?
+	 */
+	major_revision = xhci->port_array[port_id - 1];
+	if (major_revision == 0) {
+		xhci_warn(xhci, "Event for port %u not in "
+				"Extended Capabilities, ignoring.\n",
+				port_id);
+		goto cleanup;
+	}
+	if (major_revision == (u8) -1) {
+		xhci_warn(xhci, "Event for port %u duplicated in"
+				"Extended Capabilities, ignoring.\n",
+				port_id);
+		goto cleanup;
+	}
+
+	/*
+	 * Hardware port IDs reported by a Port Status Change Event include USB
+	 * 3.0 and USB 2.0 ports.  We want to check if the port has reported a
+	 * resume event, but we first need to translate the hardware port ID
+	 * into the index into the ports on the correct split roothub, and the
+	 * correct bus_state structure.
+	 */
+	/* Find the right roothub. */
+	hcd = xhci_to_hcd(xhci);
+	if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
+		hcd = xhci->shared_hcd;
+	bus_state = &xhci->bus_state[hcd_index(hcd)];
+	if (hcd->speed == HCD_USB3)
+		port_array = xhci->usb3_ports;
+	else
+		port_array = xhci->usb2_ports;
+	/* Find the faked port hub number */
+	faked_port_index = find_faked_portnum_from_hw_portnum(hcd, xhci,
+			port_id);
+
+	temp = xhci_readl(xhci, port_array[faked_port_index]);
 	if (hcd->state == HC_STATE_SUSPENDED) {
 		xhci_dbg(xhci, "resume root hub\n");
 		usb_hcd_resume_root_hub(hcd);
@@ -1207,8 +1307,9 @@ static void handle_port_status(struct xhci_hcd *xhci,
 			temp = xhci_port_state_to_neutral(temp);
 			temp &= ~PORT_PLS_MASK;
 			temp |= PORT_LINK_STROBE | XDEV_U0;
-			xhci_writel(xhci, temp, addr);
-			slot_id = xhci_find_slot_id_by_port(xhci, port_id);
+			xhci_writel(xhci, temp, port_array[faked_port_index]);
+			slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+					faked_port_index);
 			if (!slot_id) {
 				xhci_dbg(xhci, "slot_id is zero\n");
 				goto cleanup;
@@ -1216,16 +1317,16 @@ static void handle_port_status(struct xhci_hcd *xhci,
 			xhci_ring_device(xhci, slot_id);
 			xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
 			/* Clear PORT_PLC */
-			temp = xhci_readl(xhci, addr);
+			temp = xhci_readl(xhci, port_array[faked_port_index]);
 			temp = xhci_port_state_to_neutral(temp);
 			temp |= PORT_PLC;
-			xhci_writel(xhci, temp, addr);
+			xhci_writel(xhci, temp, port_array[faked_port_index]);
 		} else {
 			xhci_dbg(xhci, "resume HS port %d\n", port_id);
-			xhci->resume_done[port_id - 1] = jiffies +
+			bus_state->resume_done[faked_port_index] = jiffies +
 				msecs_to_jiffies(20);
 			mod_timer(&hcd->rh_timer,
-				  xhci->resume_done[port_id - 1]);
+				  bus_state->resume_done[faked_port_index]);
 			/* Do the rest in GetPortStatus */
 		}
 	}
@@ -1236,7 +1337,7 @@ cleanup:
 
 	spin_unlock(&xhci->lock);
 	/* Pass this up to the core */
-	usb_hcd_poll_rh_status(xhci_to_hcd(xhci));
+	usb_hcd_poll_rh_status(hcd);
 	spin_lock(&xhci->lock);
 }
 
@@ -1990,12 +2091,12 @@ cleanup:
 					trb_comp_code != COMP_BABBLE))
 				xhci_urb_free_priv(xhci, urb_priv);
 
-			usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb);
+			usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
 			xhci_dbg(xhci, "Giveback URB %p, len = %d, "
 					"status = %d\n",
 					urb, urb->actual_length, status);
 			spin_unlock(&xhci->lock);
-			usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status);
+			usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
 			spin_lock(&xhci->lock);
 		}
 
@@ -2119,7 +2220,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
 		xhci_warn(xhci, "WARNING: Host System Error\n");
 		xhci_halt(xhci);
 hw_died:
-		xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 		spin_unlock(&xhci->lock);
 		return -ESHUTDOWN;
 	}
@@ -2187,8 +2287,12 @@ hw_died:
 irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)
 {
 	irqreturn_t ret;
+	struct xhci_hcd *xhci;
 
+	xhci = hcd_to_xhci(hcd);
 	set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+	if (xhci->shared_hcd)
+		set_bit(HCD_FLAG_SAW_IRQ, &xhci->shared_hcd->flags);
 
 	ret = xhci_irq(hcd);
 
@@ -2332,7 +2436,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
 	INIT_LIST_HEAD(&td->cancelled_td_list);
 
 	if (td_index == 0) {
-		ret = usb_hcd_link_urb_to_ep(xhci_to_hcd(xhci), urb);
+		ret = usb_hcd_link_urb_to_ep(bus_to_hcd(urb->dev->bus), urb);
 		if (unlikely(ret)) {
 			xhci_urb_free_priv(xhci, urb_priv);
 			urb->hcpriv = NULL;
@@ -3131,24 +3235,6 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
 	return 0;
 }
 
-/* Queue a no-op command on the command ring */
-static int queue_cmd_noop(struct xhci_hcd *xhci)
-{
-	return queue_command(xhci, 0, 0, 0, TRB_TYPE(TRB_CMD_NOOP), false);
-}
-
-/*
- * Place a no-op command on the command ring to test the command and
- * event ring.
- */
-void *xhci_setup_one_noop(struct xhci_hcd *xhci)
-{
-	if (queue_cmd_noop(xhci) < 0)
-		return NULL;
-	xhci->noops_submitted++;
-	return xhci_ring_cmd_db;
-}
-
 /* Queue a slot enable or disable request on the command ring */
 int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id)
 {
@@ -3229,6 +3315,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
 	u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
 	u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
 	u32 type = TRB_TYPE(TRB_SET_DEQ);
+	struct xhci_virt_ep *ep;
 
 	addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
 	if (addr == 0) {
@@ -3237,6 +3324,14 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id,
 				deq_seg, deq_ptr);
 		return 0;
 	}
+	ep = &xhci->devs[slot_id]->eps[ep_index];
+	if ((ep->ep_state & SET_DEQ_PENDING)) {
+		xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
+		xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n");
+		return 0;
+	}
+	ep->queued_deq_seg = deq_seg;
+	ep->queued_deq_ptr = deq_ptr;
 	return queue_command(xhci, lower_32_bits(addr) | cycle_state,
 			upper_32_bits(addr), trb_stream_id,
 			trb_slot_id | trb_ep_index | type, false);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2083fc2..9a3645f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -93,17 +93,20 @@ void xhci_quiesce(struct xhci_hcd *xhci)
  *
  * Disable any IRQs and clear the run/stop bit.
  * HC will complete any current and actively pipelined transactions, and
- * should halt within 16 microframes of the run/stop bit being cleared.
+ * should halt within 16 ms of the run/stop bit being cleared.
  * Read HC Halted bit in the status register to see when the HC is finished.
- * XXX: shouldn't we set HC_STATE_HALT here somewhere?
  */
 int xhci_halt(struct xhci_hcd *xhci)
 {
+	int ret;
 	xhci_dbg(xhci, "// Halt the HC\n");
 	xhci_quiesce(xhci);
 
-	return handshake(xhci, &xhci->op_regs->status,
+	ret = handshake(xhci, &xhci->op_regs->status,
 			STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
+	if (!ret)
+		xhci->xhc_state |= XHCI_STATE_HALTED;
+	return ret;
 }
 
 /*
@@ -130,11 +133,13 @@ static int xhci_start(struct xhci_hcd *xhci)
 		xhci_err(xhci, "Host took too long to start, "
 				"waited %u microseconds.\n",
 				XHCI_MAX_HALT_USEC);
+	if (!ret)
+		xhci->xhc_state &= ~XHCI_STATE_HALTED;
 	return ret;
 }
 
 /*
- * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
+ * Reset a halted HC.
  *
  * This resets pipelines, timers, counters, state machines, etc.
  * Transactions will be terminated immediately, and operational registers
@@ -156,8 +161,6 @@ int xhci_reset(struct xhci_hcd *xhci)
 	command = xhci_readl(xhci, &xhci->op_regs->command);
 	command |= CMD_RESET;
 	xhci_writel(xhci, command, &xhci->op_regs->command);
-	/* XXX: Why does EHCI set this here?  Shouldn't other code do this? */
-	xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 
 	ret = handshake(xhci, &xhci->op_regs->command,
 			CMD_RESET, 0, 250 * 1000);
@@ -350,7 +353,6 @@ static void xhci_event_ring_work(unsigned long arg)
 
 	temp = xhci_readl(xhci, &xhci->ir_set->irq_pending);
 	xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp);
-	xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled);
 	xhci_dbg(xhci, "HC error bitmask = 0x%x\n", xhci->error_bitmask);
 	xhci->error_bitmask = 0;
 	xhci_dbg(xhci, "Event ring:\n");
@@ -370,10 +372,6 @@ static void xhci_event_ring_work(unsigned long arg)
 			xhci_dbg_ep_rings(xhci, i, j, &xhci->devs[i]->eps[j]);
 		}
 	}
-
-	if (xhci->noops_submitted != NUM_TEST_NOOPS)
-		if (xhci_setup_one_noop(xhci))
-			xhci_ring_cmd_db(xhci);
 	spin_unlock_irqrestore(&xhci->lock, flags);
 
 	if (!xhci->zombie)
@@ -383,6 +381,21 @@ static void xhci_event_ring_work(unsigned long arg)
 }
 #endif
 
+static int xhci_run_finished(struct xhci_hcd *xhci)
+{
+	if (xhci_start(xhci)) {
+		xhci_halt(xhci);
+		return -ENODEV;
+	}
+	xhci->shared_hcd->state = HC_STATE_RUNNING;
+
+	if (xhci->quirks & XHCI_NEC_HOST)
+		xhci_ring_cmd_db(xhci);
+
+	xhci_dbg(xhci, "Finished xhci_run for USB3 roothub\n");
+	return 0;
+}
+
 /*
  * Start the HC after it was halted.
  *
@@ -402,9 +415,14 @@ int xhci_run(struct usb_hcd *hcd)
 	u32 ret;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 	struct pci_dev  *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller);
-	void (*doorbell)(struct xhci_hcd *) = NULL;
+
+	/* Start the xHCI host controller running only after the USB 2.0 roothub
+	 * is setup.
+	 */
 
 	hcd->uses_new_polling = 1;
+	if (!usb_hcd_is_primary_hcd(hcd))
+		return xhci_run_finished(xhci);
 
 	xhci_dbg(xhci, "xhci_run\n");
 	/* unregister the legacy interrupt */
@@ -461,7 +479,6 @@ int xhci_run(struct usb_hcd *hcd)
 	xhci_writel(xhci, temp, &xhci->ir_set->irq_control);
 
 	/* Set the HCD state before we enable the irqs */
-	hcd->state = HC_STATE_RUNNING;
 	temp = xhci_readl(xhci, &xhci->op_regs->command);
 	temp |= (CMD_EIE);
 	xhci_dbg(xhci, "// Enable interrupts, cmd = 0x%x.\n",
@@ -475,24 +492,27 @@ int xhci_run(struct usb_hcd *hcd)
 			&xhci->ir_set->irq_pending);
 	xhci_print_ir_set(xhci, 0);
 
-	if (NUM_TEST_NOOPS > 0)
-		doorbell = xhci_setup_one_noop(xhci);
 	if (xhci->quirks & XHCI_NEC_HOST)
 		xhci_queue_vendor_command(xhci, 0, 0, 0,
 				TRB_TYPE(TRB_NEC_GET_FW));
 
-	if (xhci_start(xhci)) {
-		xhci_halt(xhci);
-		return -ENODEV;
-	}
+	xhci_dbg(xhci, "Finished xhci_run for USB2 roothub\n");
+	return 0;
+}
 
-	if (doorbell)
-		(*doorbell)(xhci);
-	if (xhci->quirks & XHCI_NEC_HOST)
-		xhci_ring_cmd_db(xhci);
+static void xhci_only_stop_hcd(struct usb_hcd *hcd)
+{
+	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-	xhci_dbg(xhci, "Finished xhci_run\n");
-	return 0;
+	spin_lock_irq(&xhci->lock);
+	xhci_halt(xhci);
+
+	/* The shared_hcd is going to be deallocated shortly (the USB core only
+	 * calls this function when allocation fails in usb_add_hcd(), or
+	 * usb_remove_hcd() is called).  So we need to unset xHCI's pointer.
+	 */
+	xhci->shared_hcd = NULL;
+	spin_unlock_irq(&xhci->lock);
 }
 
 /*
@@ -509,7 +529,15 @@ void xhci_stop(struct usb_hcd *hcd)
 	u32 temp;
 	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
+	if (!usb_hcd_is_primary_hcd(hcd)) {
+		xhci_only_stop_hcd(xhci->shared_hcd);
+		return;
+	}
+
 	spin_lock_irq(&xhci->lock);
+	/* Make sure the xHC is halted for a USB3 roothub
+	 * (xhci_stop() could be called as part of failed init).
+	 */
 	xhci_halt(xhci);
 	xhci_reset(xhci);
 	spin_unlock_irq(&xhci->lock);
@@ -542,6 +570,8 @@ void xhci_stop(struct usb_hcd *hcd)
  * This is called when the machine is rebooting or halting.  We assume that the
  * machine will be powered off, and the HC's internal state will be reset.
  * Don't bother to free memory.
+ *
+ * This will only ever be called with the main usb_hcd (the USB3 roothub).
  */
 void xhci_shutdown(struct usb_hcd *hcd)
 {
@@ -657,6 +687,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
 
 	spin_lock_irq(&xhci->lock);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
 	/* step 1: stop endpoint */
 	/* skipped assuming that port suspend has done */
 
@@ -706,10 +737,15 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
 	u32			command, temp = 0;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
-	int	old_state, retval;
+	struct usb_hcd		*secondary_hcd;
+	int			retval;
 
-	old_state = hcd->state;
-	if (time_before(jiffies, xhci->next_statechange))
+	/* Wait a bit if either of the roothubs need to settle from the
+	 * transistion into bus suspend.
+	 */
+	if (time_before(jiffies, xhci->bus_state[0].next_statechange) ||
+			time_before(jiffies,
+				xhci->bus_state[1].next_statechange))
 		msleep(100);
 
 	spin_lock_irq(&xhci->lock);
@@ -762,16 +798,34 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 		xhci_dbg(xhci, "xhci_stop completed - status = %x\n",
 			    xhci_readl(xhci, &xhci->op_regs->status));
 
-		xhci_dbg(xhci, "Initialize the HCD\n");
-		retval = xhci_init(hcd);
+		/* USB core calls the PCI reinit and start functions twice:
+		 * first with the primary HCD, and then with the secondary HCD.
+		 * If we don't do the same, the host will never be started.
+		 */
+		if (!usb_hcd_is_primary_hcd(hcd))
+			secondary_hcd = hcd;
+		else
+			secondary_hcd = xhci->shared_hcd;
+
+		xhci_dbg(xhci, "Initialize the xhci_hcd\n");
+		retval = xhci_init(hcd->primary_hcd);
 		if (retval)
 			return retval;
+		xhci_dbg(xhci, "Start the primary HCD\n");
+		retval = xhci_run(hcd->primary_hcd);
+		if (retval)
+			goto failed_restart;
 
-		xhci_dbg(xhci, "Start the HCD\n");
-		retval = xhci_run(hcd);
-		if (!retval)
+		xhci_dbg(xhci, "Start the secondary HCD\n");
+		retval = xhci_run(secondary_hcd);
+		if (!retval) {
 			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+			set_bit(HCD_FLAG_HW_ACCESSIBLE,
+					&xhci->shared_hcd->flags);
+		}
+failed_restart:
 		hcd->state = HC_STATE_SUSPENDED;
+		xhci->shared_hcd->state = HC_STATE_SUSPENDED;
 		return retval;
 	}
 
@@ -792,10 +846,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 	 */
 
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	if (!hibernated)
-		hcd->state = old_state;
-	else
-		hcd->state = HC_STATE_SUSPENDED;
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
 
 	spin_unlock_irq(&xhci->lock);
 	return 0;
@@ -1167,13 +1218,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 	if (ret || !urb->hcpriv)
 		goto done;
 	temp = xhci_readl(xhci, &xhci->op_regs->status);
-	if (temp == 0xffffffff) {
+	if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
 		xhci_dbg(xhci, "HW died, freeing TD.\n");
 		urb_priv = urb->hcpriv;
 
 		usb_hcd_unlink_urb_from_ep(hcd, urb);
 		spin_unlock_irqrestore(&xhci->lock, flags);
-		usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN);
+		usb_hcd_giveback_urb(hcd, urb, -ESHUTDOWN);
 		xhci_urb_free_priv(xhci, urb_priv);
 		return ret;
 	}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 7f127df..711de25 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -644,6 +644,9 @@ struct xhci_ep_ctx {
 #define AVG_TRB_LENGTH_FOR_EP(p)	((p) & 0xffff)
 #define MAX_ESIT_PAYLOAD_FOR_EP(p)	(((p) & 0xffff) << 16)
 
+/* deq bitmasks */
+#define EP_CTX_CYCLE_MASK		(1 << 0)
+
 
 /**
  * struct xhci_input_control_context
@@ -746,6 +749,12 @@ struct xhci_virt_ep {
 	struct timer_list	stop_cmd_timer;
 	int			stop_cmds_pending;
 	struct xhci_hcd		*xhci;
+	/* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue
+	 * command.  We'll need to update the ring's dequeue segment and dequeue
+	 * pointer after the command completes.
+	 */
+	struct xhci_segment	*queued_deq_seg;
+	union xhci_trb		*queued_deq_ptr;
 	/*
 	 * Sometimes the xHC can not process isochronous endpoint ring quickly
 	 * enough, and it will miss some isoc tds on the ring and generate
@@ -1161,8 +1170,29 @@ struct s3_save {
 	u64	erst_dequeue;
 };
 
+struct xhci_bus_state {
+	unsigned long		bus_suspended;
+	unsigned long		next_statechange;
+
+	/* Port suspend arrays are indexed by the portnum of the fake roothub */
+	/* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */
+	u32			port_c_suspend;
+	u32			suspended_ports;
+	unsigned long		resume_done[USB_MAXCHILDREN];
+};
+
+static inline unsigned int hcd_index(struct usb_hcd *hcd)
+{
+	if (hcd->speed == HCD_USB3)
+		return 0;
+	else
+		return 1;
+}
+
 /* There is one ehci_hci structure per controller */
 struct xhci_hcd {
+	struct usb_hcd *main_hcd;
+	struct usb_hcd *shared_hcd;
 	/* glue to PCI and HCD framework */
 	struct xhci_cap_regs __iomem *cap_regs;
 	struct xhci_op_regs __iomem *op_regs;
@@ -1224,9 +1254,6 @@ struct xhci_hcd {
 	/* Host controller watchdog timer structures */
 	unsigned int		xhc_state;
 
-	unsigned long		bus_suspended;
-	unsigned long		next_statechange;
-
 	u32			command;
 	struct s3_save		s3;
 /* Host controller is dying - not responding to commands. "I'm not dead yet!"
@@ -1242,18 +1269,15 @@ struct xhci_hcd {
  * There are no reports of xHCI host controllers that display this issue.
  */
 #define XHCI_STATE_DYING	(1 << 0)
+#define XHCI_STATE_HALTED	(1 << 1)
 	/* Statistics */
-	int			noops_submitted;
-	int			noops_handled;
 	int			error_bitmask;
 	unsigned int		quirks;
 #define	XHCI_LINK_TRB_QUIRK	(1 << 0)
 #define XHCI_RESET_EP_QUIRK	(1 << 1)
 #define XHCI_NEC_HOST		(1 << 2)
-	u32			port_c_suspend[8];	/* port suspend change*/
-	u32			suspended_ports[8];	/* which ports are
-							   suspended */
-	unsigned long		resume_done[MAX_HC_PORTS];
+	/* There are two roothubs to keep track of bus suspend info for */
+	struct xhci_bus_state   bus_state[2];
 	/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
 	u8			*port_array;
 	/* Array of pointers to USB 3.0 PORTSC registers */
@@ -1264,18 +1288,15 @@ struct xhci_hcd {
 	unsigned int		num_usb2_ports;
 };
 
-/* For testing purposes */
-#define NUM_TEST_NOOPS	0
-
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
 static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd)
 {
-	return (struct xhci_hcd *) (hcd->hcd_priv);
+	return *((struct xhci_hcd **) (hcd->hcd_priv));
 }
 
 static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
 {
-	return container_of((void *) xhci, struct usb_hcd, hcd_priv);
+	return xhci->main_hcd;
 }
 
 #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING
@@ -1471,7 +1492,6 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
 		dma_addr_t suspect_dma);
 int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);
-void *xhci_setup_one_noop(struct xhci_hcd *xhci);
 int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id);
 int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr,
 		u32 slot_id);
@@ -1525,7 +1545,8 @@ int xhci_bus_resume(struct usb_hcd *hcd);
 #endif	/* CONFIG_PM */
 
 u32 xhci_port_state_to_neutral(u32 state);
-int xhci_find_slot_id_by_port(struct xhci_hcd *xhci, u16 port);
+int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
+		u16 port);
 void xhci_ring_device(struct xhci_hcd *xhci, int slot_id);
 
 /* xHCI contexts */
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
index 1fa6ce3..68ab460 100644
--- a/drivers/usb/misc/appledisplay.c
+++ b/drivers/usb/misc/appledisplay.c
@@ -282,6 +282,7 @@ static int appledisplay_probe(struct usb_interface *iface,
 	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
 		atomic_inc_return(&count_displays) - 1);
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	pdata->bd = backlight_device_register(bl_name, NULL, pdata,
 					      &appledisplay_bl_data, &props);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index a35b427..388cc12 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -83,6 +83,8 @@ static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test)
 #define WARNING(tdev, fmt, args...) \
 	dev_warn(&(tdev)->intf->dev , fmt , ## args)
 
+#define GUARD_BYTE	0xA5
+
 /*-------------------------------------------------------------------------*/
 
 static int
@@ -186,11 +188,12 @@ static void simple_callback(struct urb *urb)
 	complete(urb->context);
 }
 
-static struct urb *simple_alloc_urb(
+static struct urb *usbtest_alloc_urb(
 	struct usb_device	*udev,
 	int			pipe,
-	unsigned long		bytes
-)
+	unsigned long		bytes,
+	unsigned		transfer_flags,
+	unsigned		offset)
 {
 	struct urb		*urb;
 
@@ -201,19 +204,46 @@ static struct urb *simple_alloc_urb(
 	urb->interval = (udev->speed == USB_SPEED_HIGH)
 			? (INTERRUPT_RATE << 3)
 			: INTERRUPT_RATE;
-	urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+	urb->transfer_flags = transfer_flags;
 	if (usb_pipein(pipe))
 		urb->transfer_flags |= URB_SHORT_NOT_OK;
-	urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL,
-			&urb->transfer_dma);
+
+	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+		urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset,
+			GFP_KERNEL, &urb->transfer_dma);
+	else
+		urb->transfer_buffer = kmalloc(bytes + offset, GFP_KERNEL);
+
 	if (!urb->transfer_buffer) {
 		usb_free_urb(urb);
-		urb = NULL;
-	} else
-		memset(urb->transfer_buffer, 0, bytes);
+		return NULL;
+	}
+
+	/* To test unaligned transfers add an offset and fill the
+		unused memory with a guard value */
+	if (offset) {
+		memset(urb->transfer_buffer, GUARD_BYTE, offset);
+		urb->transfer_buffer += offset;
+		if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+			urb->transfer_dma += offset;
+	}
+
+	/* For inbound transfers use guard byte so that test fails if
+		data not correctly copied */
+	memset(urb->transfer_buffer,
+			usb_pipein(urb->pipe) ? GUARD_BYTE : 0,
+			bytes);
 	return urb;
 }
 
+static struct urb *simple_alloc_urb(
+	struct usb_device	*udev,
+	int			pipe,
+	unsigned long		bytes)
+{
+	return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0);
+}
+
 static unsigned pattern;
 static unsigned mod_pattern;
 module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR);
@@ -238,13 +268,38 @@ static inline void simple_fill_buf(struct urb *urb)
 	}
 }
 
-static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
+static inline unsigned buffer_offset(void *buf)
+{
+	return (unsigned)buf & (ARCH_KMALLOC_MINALIGN - 1);
+}
+
+static int check_guard_bytes(struct usbtest_dev *tdev, struct urb *urb)
+{
+	u8 *buf = urb->transfer_buffer;
+	u8 *guard = buf - buffer_offset(buf);
+	unsigned i;
+
+	for (i = 0; guard < buf; i++, guard++) {
+		if (*guard != GUARD_BYTE) {
+			ERROR(tdev, "guard byte[%d] %d (not %d)\n",
+				i, *guard, GUARD_BYTE);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
 {
 	unsigned	i;
 	u8		expected;
 	u8		*buf = urb->transfer_buffer;
 	unsigned	len = urb->actual_length;
 
+	int ret = check_guard_bytes(tdev, urb);
+	if (ret)
+		return ret;
+
 	for (i = 0; i < len; i++, buf++) {
 		switch (pattern) {
 		/* all-zeroes has no synchronization issues */
@@ -274,8 +329,16 @@ static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
 
 static void simple_free_urb(struct urb *urb)
 {
-	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
-			  urb->transfer_buffer, urb->transfer_dma);
+	unsigned offset = buffer_offset(urb->transfer_buffer);
+
+	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+		usb_free_coherent(
+			urb->dev,
+			urb->transfer_buffer_length + offset,
+			urb->transfer_buffer - offset,
+			urb->transfer_dma - offset);
+	else
+		kfree(urb->transfer_buffer - offset);
 	usb_free_urb(urb);
 }
 
@@ -1256,7 +1319,7 @@ done:
  * try whatever we're told to try.
  */
 static int ctrl_out(struct usbtest_dev *dev,
-		unsigned count, unsigned length, unsigned vary)
+		unsigned count, unsigned length, unsigned vary, unsigned offset)
 {
 	unsigned		i, j, len;
 	int			retval;
@@ -1267,10 +1330,11 @@ static int ctrl_out(struct usbtest_dev *dev,
 	if (length < 1 || length > 0xffff || vary >= length)
 		return -EINVAL;
 
-	buf = kmalloc(length, GFP_KERNEL);
+	buf = kmalloc(length + offset, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
 
+	buf += offset;
 	udev = testdev_to_usbdev(dev);
 	len = length;
 	retval = 0;
@@ -1337,7 +1401,7 @@ static int ctrl_out(struct usbtest_dev *dev,
 		ERROR(dev, "ctrl_out %s failed, code %d, count %d\n",
 			what, retval, i);
 
-	kfree(buf);
+	kfree(buf - offset);
 	return retval;
 }
 
@@ -1373,6 +1437,8 @@ static void iso_callback(struct urb *urb)
 		ctx->errors += urb->number_of_packets;
 	else if (urb->actual_length != urb->transfer_buffer_length)
 		ctx->errors++;
+	else if (check_guard_bytes(ctx->dev, urb) != 0)
+		ctx->errors++;
 
 	if (urb->status == 0 && ctx->count > (ctx->pending - 1)
 			&& !ctx->submit_error) {
@@ -1408,7 +1474,8 @@ static struct urb *iso_alloc_urb(
 	struct usb_device	*udev,
 	int			pipe,
 	struct usb_endpoint_descriptor	*desc,
-	long			bytes
+	long			bytes,
+	unsigned offset
 )
 {
 	struct urb		*urb;
@@ -1428,13 +1495,24 @@ static struct urb *iso_alloc_urb(
 
 	urb->number_of_packets = packets;
 	urb->transfer_buffer_length = bytes;
-	urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL,
-			&urb->transfer_dma);
+	urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset,
+							GFP_KERNEL,
+							&urb->transfer_dma);
 	if (!urb->transfer_buffer) {
 		usb_free_urb(urb);
 		return NULL;
 	}
-	memset(urb->transfer_buffer, 0, bytes);
+	if (offset) {
+		memset(urb->transfer_buffer, GUARD_BYTE, offset);
+		urb->transfer_buffer += offset;
+		urb->transfer_dma += offset;
+	}
+	/* For inbound transfers use guard byte so that test fails if
+		data not correctly copied */
+	memset(urb->transfer_buffer,
+			usb_pipein(urb->pipe) ? GUARD_BYTE : 0,
+			bytes);
+
 	for (i = 0; i < packets; i++) {
 		/* here, only the last packet will be short */
 		urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp);
@@ -1452,7 +1530,7 @@ static struct urb *iso_alloc_urb(
 
 static int
 test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
-		int pipe, struct usb_endpoint_descriptor *desc)
+		int pipe, struct usb_endpoint_descriptor *desc, unsigned offset)
 {
 	struct iso_context	context;
 	struct usb_device	*udev;
@@ -1480,7 +1558,7 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
 
 	for (i = 0; i < param->sglen; i++) {
 		urbs[i] = iso_alloc_urb(udev, pipe, desc,
-				param->length);
+					param->length, offset);
 		if (!urbs[i]) {
 			status = -ENOMEM;
 			goto fail;
@@ -1542,6 +1620,26 @@ fail:
 	return status;
 }
 
+static int test_unaligned_bulk(
+	struct usbtest_dev *tdev,
+	int pipe,
+	unsigned length,
+	int iterations,
+	unsigned transfer_flags,
+	const char *label)
+{
+	int retval;
+	struct urb *urb = usbtest_alloc_urb(
+		testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1);
+
+	if (!urb)
+		return -ENOMEM;
+
+	retval = simple_io(tdev, urb, iterations, 0, 0, label);
+	simple_free_urb(urb);
+	return retval;
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* We only have this one interface to user space, through usbfs.
@@ -1843,7 +1941,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 				realworld ? 1 : 0, param->length,
 				param->vary);
 		retval = ctrl_out(dev, param->iterations,
-				param->length, param->vary);
+				param->length, param->vary, 0);
 		break;
 
 	/* iso write tests */
@@ -1856,7 +1954,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 				param->sglen, param->length);
 		/* FIRMWARE:  iso sink */
 		retval = test_iso_queue(dev, param,
-				dev->out_iso_pipe, dev->iso_out);
+				dev->out_iso_pipe, dev->iso_out, 0);
 		break;
 
 	/* iso read tests */
@@ -1869,13 +1967,103 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
 				param->sglen, param->length);
 		/* FIRMWARE:  iso source */
 		retval = test_iso_queue(dev, param,
-				dev->in_iso_pipe, dev->iso_in);
+				dev->in_iso_pipe, dev->iso_in, 0);
 		break;
 
 	/* FIXME unlink from queue (ring with N urbs) */
 
 	/* FIXME scatterlist cancel (needs helper thread) */
 
+	/* Tests for bulk I/O using DMA mapping by core and odd address */
+	case 17:
+		if (dev->out_pipe == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 17:  write odd addr %d bytes %u times core map\n",
+			param->length, param->iterations);
+
+		retval = test_unaligned_bulk(
+				dev, dev->out_pipe,
+				param->length, param->iterations,
+				0, "test17");
+		break;
+
+	case 18:
+		if (dev->in_pipe == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 18:  read odd addr %d bytes %u times core map\n",
+			param->length, param->iterations);
+
+		retval = test_unaligned_bulk(
+				dev, dev->in_pipe,
+				param->length, param->iterations,
+				0, "test18");
+		break;
+
+	/* Tests for bulk I/O using premapped coherent buffer and odd address */
+	case 19:
+		if (dev->out_pipe == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 19:  write odd addr %d bytes %u times premapped\n",
+			param->length, param->iterations);
+
+		retval = test_unaligned_bulk(
+				dev, dev->out_pipe,
+				param->length, param->iterations,
+				URB_NO_TRANSFER_DMA_MAP, "test19");
+		break;
+
+	case 20:
+		if (dev->in_pipe == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 20:  read odd addr %d bytes %u times premapped\n",
+			param->length, param->iterations);
+
+		retval = test_unaligned_bulk(
+				dev, dev->in_pipe,
+				param->length, param->iterations,
+				URB_NO_TRANSFER_DMA_MAP, "test20");
+		break;
+
+	/* control write tests with unaligned buffer */
+	case 21:
+		if (!dev->info->ctrl_out)
+			break;
+		dev_info(&intf->dev,
+				"TEST 21:  %d ep0out odd addr, %d..%d vary %d\n",
+				param->iterations,
+				realworld ? 1 : 0, param->length,
+				param->vary);
+		retval = ctrl_out(dev, param->iterations,
+				param->length, param->vary, 1);
+		break;
+
+	/* unaligned iso tests */
+	case 22:
+		if (dev->out_iso_pipe == 0 || param->sglen == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 22:  write %d iso odd, %d entries of %d bytes\n",
+				param->iterations,
+				param->sglen, param->length);
+		retval = test_iso_queue(dev, param,
+				dev->out_iso_pipe, dev->iso_out, 1);
+		break;
+
+	case 23:
+		if (dev->in_iso_pipe == 0 || param->sglen == 0)
+			break;
+		dev_info(&intf->dev,
+			"TEST 23:  read %d iso odd, %d entries of %d bytes\n",
+				param->iterations,
+				param->sglen, param->length);
+		retval = test_iso_queue(dev, param,
+				dev->in_iso_pipe, dev->iso_in, 1);
+		break;
+
 	}
 	do_gettimeofday(&param->duration);
 	param->duration.tv_sec -= start.tv_sec;
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index a545d65..c302e19 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -236,6 +236,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
 			fp++;
 			dp++;
 		}
+		/* Wasteful, but simple to understand: ISO 'C' is sparse. */
+		if (ev_type == 'C')
+			ep->length = urb->transfer_buffer_length;
 	}
 
 	ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index c292d5c..630ae7f 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1530,7 +1530,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) || \
+#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
 	defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \
 	defined(CONFIG_ARCH_U5500)
 
@@ -1950,31 +1950,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 		goto fail0;
 	}
 
-	switch (plat->mode) {
-	case MUSB_HOST:
-#ifdef CONFIG_USB_MUSB_HDRC_HCD
-		break;
-#else
-		goto bad_config;
-#endif
-	case MUSB_PERIPHERAL:
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
-		break;
-#else
-		goto bad_config;
-#endif
-	case MUSB_OTG:
-#ifdef CONFIG_USB_MUSB_OTG
-		break;
-#else
-bad_config:
-#endif
-	default:
-		dev_err(dev, "incompatible Kconfig role setting\n");
-		status = -EINVAL;
-		goto fail0;
-	}
-
 	/* allocate */
 	musb = allocate_instance(dev, plat->config, ctrl);
 	if (!musb) {
@@ -1982,6 +1957,10 @@ bad_config:
 		goto fail0;
 	}
 
+	pm_runtime_use_autosuspend(musb->controller);
+	pm_runtime_set_autosuspend_delay(musb->controller, 200);
+	pm_runtime_enable(musb->controller);
+
 	spin_lock_init(&musb->lock);
 	musb->board_mode = plat->mode;
 	musb->board_set_power = plat->set_power;
@@ -2117,6 +2096,8 @@ bad_config:
 	if (status < 0)
 		goto fail3;
 
+	pm_runtime_put(musb->controller);
+
 	status = musb_init_debugfs(musb);
 	if (status < 0)
 		goto fail4;
@@ -2216,9 +2197,11 @@ static int __exit musb_remove(struct platform_device *pdev)
 	 *  - Peripheral mode: peripheral is deactivated (or never-activated)
 	 *  - OTG mode: both roles are deactivated (or never-activated)
 	 */
+	pm_runtime_get_sync(musb->controller);
 	musb_exit_debugfs(musb);
 	musb_shutdown(pdev);
 
+	pm_runtime_put(musb->controller);
 	musb_free(musb);
 	iounmap(ctrl_base);
 	device_init_wakeup(&pdev->dev, 0);
@@ -2404,9 +2387,41 @@ static int musb_resume_noirq(struct device *dev)
 	return 0;
 }
 
+static int musb_runtime_suspend(struct device *dev)
+{
+	struct musb	*musb = dev_to_musb(dev);
+
+	musb_save_context(musb);
+
+	return 0;
+}
+
+static int musb_runtime_resume(struct device *dev)
+{
+	struct musb	*musb = dev_to_musb(dev);
+	static int	first = 1;
+
+	/*
+	 * When pm_runtime_get_sync called for the first time in driver
+	 * init,  some of the structure is still not initialized which is
+	 * used in restore function. But clock needs to be
+	 * enabled before any register access, so
+	 * pm_runtime_get_sync has to be called.
+	 * Also context restore without save does not make
+	 * any sense
+	 */
+	if (!first)
+		musb_restore_context(musb);
+	first = 0;
+
+	return 0;
+}
+
 static const struct dev_pm_ops musb_dev_pm_ops = {
 	.suspend	= musb_suspend,
 	.resume_noirq	= musb_resume_noirq,
+	.runtime_suspend = musb_runtime_suspend,
+	.runtime_resume = musb_runtime_resume,
 };
 
 #define MUSB_DEV_PM_OPS (&musb_dev_pm_ops)
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index e6400be..4bd9e21 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -212,8 +212,8 @@ enum musb_g_ep0_state {
  * directly with the "flat" model, or after setting up an index register.
  */
 
-#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \
-		|| defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_BLACKFIN) \
+#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_SOC_OMAP2430) \
+		|| defined(CONFIG_SOC_OMAP3430) || defined(CONFIG_BLACKFIN) \
 		|| defined(CONFIG_ARCH_OMAP4)
 /* REVISIT indexed access seemed to
  * misbehave (on DaVinci) for at least peripheral IN ...
@@ -328,7 +328,7 @@ struct musb_hw_ep {
 #endif
 };
 
-static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep)
+static inline struct musb_request *next_in_request(struct musb_hw_ep *hw_ep)
 {
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	return next_request(&hw_ep->ep_in);
@@ -337,7 +337,7 @@ static inline struct usb_request *next_in_request(struct musb_hw_ep *hw_ep)
 #endif
 }
 
-static inline struct usb_request *next_out_request(struct musb_hw_ep *hw_ep)
+static inline struct musb_request *next_out_request(struct musb_hw_ep *hw_ep)
 {
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 	return next_request(&hw_ep->ep_out);
@@ -358,10 +358,6 @@ struct musb_csr_regs {
 
 struct musb_context_registers {
 
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-    defined(CONFIG_ARCH_OMAP4)
-	u32 otg_sysconfig, otg_forcestandby;
-#endif
 	u8 power;
 	u16 intrtxe, intrrxe;
 	u8 intrusbe;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 2fe3046..5c7b321 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -189,7 +189,7 @@ __acquires(ep->musb->lock)
 
 	req = to_musb_request(request);
 
-	list_del(&request->list);
+	list_del(&req->list);
 	if (req->request.status == -EINPROGRESS)
 		req->request.status = status;
 	musb = req->musb;
@@ -251,9 +251,8 @@ static void nuke(struct musb_ep *ep, const int status)
 		ep->dma = NULL;
 	}
 
-	while (!list_empty(&(ep->req_list))) {
-		req = container_of(ep->req_list.next, struct musb_request,
-				request.list);
+	while (!list_empty(&ep->req_list)) {
+		req = list_first_entry(&ep->req_list, struct musb_request, list);
 		musb_g_giveback(ep, &req->request, status);
 	}
 }
@@ -485,6 +484,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
 void musb_g_tx(struct musb *musb, u8 epnum)
 {
 	u16			csr;
+	struct musb_request	*req;
 	struct usb_request	*request;
 	u8 __iomem		*mbase = musb->mregs;
 	struct musb_ep		*musb_ep = &musb->endpoints[epnum].ep_in;
@@ -492,7 +492,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 	struct dma_channel	*dma;
 
 	musb_ep_select(mbase, epnum);
-	request = next_request(musb_ep);
+	req = next_request(musb_ep);
+	request = &req->request;
 
 	csr = musb_readw(epio, MUSB_TXCSR);
 	DBG(4, "<== %s, txcsr %04x\n", musb_ep->end_point.name, csr);
@@ -571,15 +572,15 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 
 		if (request->actual == request->length) {
 			musb_g_giveback(musb_ep, request, 0);
-			request = musb_ep->desc ? next_request(musb_ep) : NULL;
-			if (!request) {
+			req = musb_ep->desc ? next_request(musb_ep) : NULL;
+			if (!req) {
 				DBG(4, "%s idle now\n",
 					musb_ep->end_point.name);
 				return;
 			}
 		}
 
-		txstate(musb, to_musb_request(request));
+		txstate(musb, req);
 	}
 }
 
@@ -821,6 +822,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 void musb_g_rx(struct musb *musb, u8 epnum)
 {
 	u16			csr;
+	struct musb_request	*req;
 	struct usb_request	*request;
 	void __iomem		*mbase = musb->mregs;
 	struct musb_ep		*musb_ep;
@@ -835,10 +837,12 @@ void musb_g_rx(struct musb *musb, u8 epnum)
 
 	musb_ep_select(mbase, epnum);
 
-	request = next_request(musb_ep);
-	if (!request)
+	req = next_request(musb_ep);
+	if (!req)
 		return;
 
+	request = &req->request;
+
 	csr = musb_readw(epio, MUSB_RXCSR);
 	dma = is_dma_capable() ? musb_ep->dma : NULL;
 
@@ -914,15 +918,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
 #endif
 		musb_g_giveback(musb_ep, request, 0);
 
-		request = next_request(musb_ep);
-		if (!request)
+		req = next_request(musb_ep);
+		if (!req)
 			return;
 	}
 #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
 exit:
 #endif
 	/* Analyze request */
-	rxstate(musb, to_musb_request(request));
+	rxstate(musb, req);
 }
 
 /* ------------------------------------------------------------ */
@@ -974,7 +978,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			ok = musb->hb_iso_rx;
 
 		if (!ok) {
-			DBG(4, "%s: not support ISO high bandwidth\n", __func__);
+			DBG(4, "no support for high bandwidth ISO\n");
 			goto fail;
 		}
 		musb_ep->hb_mult = (tmp >> 11) & 3;
@@ -998,7 +1002,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			goto fail;
 
 		if (tmp > hw_ep->max_packet_sz_tx) {
-			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
+			DBG(4, "packet size beyond hardware FIFO size\n");
 			goto fail;
 		}
 
@@ -1038,7 +1042,7 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			goto fail;
 
 		if (tmp > hw_ep->max_packet_sz_rx) {
-			DBG(4, "%s: packet size beyond hw fifo size\n", __func__);
+			DBG(4, "packet size beyond hardware FIFO size\n");
 			goto fail;
 		}
 
@@ -1171,7 +1175,6 @@ struct usb_request *musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
 		return NULL;
 	}
 
-	INIT_LIST_HEAD(&request->request.list);
 	request->request.dma = DMA_ADDR_INVALID;
 	request->epnum = musb_ep->current_epnum;
 	request->ep = musb_ep;
@@ -1257,10 +1260,10 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
 	}
 
 	/* add request to the list */
-	list_add_tail(&(request->request.list), &(musb_ep->req_list));
+	list_add_tail(&request->list, &musb_ep->req_list);
 
 	/* it this is the head of the queue, start i/o ... */
-	if (!musb_ep->busy && &request->request.list == musb_ep->req_list.next)
+	if (!musb_ep->busy && &request->list == musb_ep->req_list.next)
 		musb_ep_restart(musb, request);
 
 cleanup:
@@ -1271,7 +1274,8 @@ cleanup:
 static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
 {
 	struct musb_ep		*musb_ep = to_musb_ep(ep);
-	struct usb_request	*r;
+	struct musb_request	*req = to_musb_request(request);
+	struct musb_request	*r;
 	unsigned long		flags;
 	int			status = 0;
 	struct musb		*musb = musb_ep->musb;
@@ -1282,10 +1286,10 @@ static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
 	spin_lock_irqsave(&musb->lock, flags);
 
 	list_for_each_entry(r, &musb_ep->req_list, list) {
-		if (r == request)
+		if (r == req)
 			break;
 	}
-	if (r != request) {
+	if (r != req) {
 		DBG(3, "request %p not queued to %s\n", request, ep->name);
 		status = -EINVAL;
 		goto done;
@@ -1349,7 +1353,7 @@ static int musb_gadget_set_halt(struct usb_ep *ep, int value)
 
 	musb_ep_select(mbase, epnum);
 
-	request = to_musb_request(next_request(musb_ep));
+	request = next_request(musb_ep);
 	if (value) {
 		if (request) {
 			DBG(3, "request in progress, cannot halt %s\n",
@@ -1801,90 +1805,105 @@ void musb_gadget_cleanup(struct musb *musb)
 int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
 		int (*bind)(struct usb_gadget *))
 {
-	int retval;
-	unsigned long flags;
-	struct musb *musb = the_gadget;
+	struct musb		*musb = the_gadget;
+	unsigned long		flags;
+	int			retval = -EINVAL;
 
 	if (!driver
 			|| driver->speed != USB_SPEED_HIGH
 			|| !bind || !driver->setup)
-		return -EINVAL;
+		goto err0;
 
 	/* driver must be initialized to support peripheral mode */
 	if (!musb) {
-		DBG(1, "%s, no dev??\n", __func__);
-		return -ENODEV;
+		DBG(1, "no dev??\n");
+		retval = -ENODEV;
+		goto err0;
 	}
 
+	pm_runtime_get_sync(musb->controller);
+
 	DBG(3, "registering driver %s\n", driver->function);
-	spin_lock_irqsave(&musb->lock, flags);
 
 	if (musb->gadget_driver) {
 		DBG(1, "%s is already bound to %s\n",
 				musb_driver_name,
 				musb->gadget_driver->driver.name);
 		retval = -EBUSY;
-	} else {
-		musb->gadget_driver = driver;
-		musb->g.dev.driver = &driver->driver;
-		driver->driver.bus = NULL;
-		musb->softconnect = 1;
-		retval = 0;
+		goto err0;
 	}
 
+	spin_lock_irqsave(&musb->lock, flags);
+	musb->gadget_driver = driver;
+	musb->g.dev.driver = &driver->driver;
+	driver->driver.bus = NULL;
+	musb->softconnect = 1;
 	spin_unlock_irqrestore(&musb->lock, flags);
 
-	if (retval == 0) {
-		retval = bind(&musb->g);
-		if (retval != 0) {
-			DBG(3, "bind to driver %s failed --> %d\n",
-					driver->driver.name, retval);
-			musb->gadget_driver = NULL;
-			musb->g.dev.driver = NULL;
-		}
+	retval = bind(&musb->g);
+	if (retval) {
+		DBG(3, "bind to driver %s failed --> %d\n",
+				driver->driver.name, retval);
+		goto err1;
+	}
 
-		spin_lock_irqsave(&musb->lock, flags);
+	spin_lock_irqsave(&musb->lock, flags);
 
-		otg_set_peripheral(musb->xceiv, &musb->g);
-		musb->xceiv->state = OTG_STATE_B_IDLE;
-		musb->is_active = 1;
+	otg_set_peripheral(musb->xceiv, &musb->g);
+	musb->xceiv->state = OTG_STATE_B_IDLE;
+	musb->is_active = 1;
 
-		/* FIXME this ignores the softconnect flag.  Drivers are
-		 * allowed hold the peripheral inactive until for example
-		 * userspace hooks up printer hardware or DSP codecs, so
-		 * hosts only see fully functional devices.
-		 */
+	/*
+	 * FIXME this ignores the softconnect flag.  Drivers are
+	 * allowed hold the peripheral inactive until for example
+	 * userspace hooks up printer hardware or DSP codecs, so
+	 * hosts only see fully functional devices.
+	 */
 
-		if (!is_otg_enabled(musb))
-			musb_start(musb);
+	if (!is_otg_enabled(musb))
+		musb_start(musb);
 
-		otg_set_peripheral(musb->xceiv, &musb->g);
+	otg_set_peripheral(musb->xceiv, &musb->g);
 
-		spin_unlock_irqrestore(&musb->lock, flags);
+	spin_unlock_irqrestore(&musb->lock, flags);
 
-		if (is_otg_enabled(musb)) {
-			struct usb_hcd	*hcd = musb_to_hcd(musb);
+	if (is_otg_enabled(musb)) {
+		struct usb_hcd	*hcd = musb_to_hcd(musb);
 
-			DBG(3, "OTG startup...\n");
+		DBG(3, "OTG startup...\n");
 
-			/* REVISIT:  funcall to other code, which also
-			 * handles power budgeting ... this way also
-			 * ensures HdrcStart is indirectly called.
-			 */
-			retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
-			if (retval < 0) {
-				DBG(1, "add_hcd failed, %d\n", retval);
-				spin_lock_irqsave(&musb->lock, flags);
-				otg_set_peripheral(musb->xceiv, NULL);
-				musb->gadget_driver = NULL;
-				musb->g.dev.driver = NULL;
-				spin_unlock_irqrestore(&musb->lock, flags);
-			} else {
-				hcd->self.uses_pio_for_control = 1;
-			}
+		/* REVISIT:  funcall to other code, which also
+		 * handles power budgeting ... this way also
+		 * ensures HdrcStart is indirectly called.
+		 */
+		retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
+		if (retval < 0) {
+			DBG(1, "add_hcd failed, %d\n", retval);
+			goto err2;
+
+			if ((musb->xceiv->last_event == USB_EVENT_ID)
+						&& musb->xceiv->set_vbus)
+				otg_set_vbus(musb->xceiv, 1);
 		}
+
+		hcd->self.uses_pio_for_control = 1;
+
+		if (musb->xceiv->last_event == USB_EVENT_NONE)
+			pm_runtime_put(musb->controller);
+
 	}
 
+	return 0;
+
+err2:
+	if (!is_otg_enabled(musb))
+		musb_stop(musb);
+
+err1:
+	musb->gadget_driver = NULL;
+	musb->g.dev.driver = NULL;
+
+err0:
 	return retval;
 }
 EXPORT_SYMBOL(usb_gadget_probe_driver);
@@ -1939,14 +1958,20 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
  */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 {
-	unsigned long	flags;
-	int		retval = 0;
 	struct musb	*musb = the_gadget;
+	unsigned long	flags;
 
 	if (!driver || !driver->unbind || !musb)
 		return -EINVAL;
 
-	/* REVISIT always use otg_set_peripheral() here too;
+	if (!musb->gadget_driver)
+		return -EINVAL;
+
+	if (musb->xceiv->last_event == USB_EVENT_NONE)
+		pm_runtime_get_sync(musb->controller);
+
+	/*
+	 * REVISIT always use otg_set_peripheral() here too;
 	 * this needs to shut down the OTG engine.
 	 */
 
@@ -1956,29 +1981,26 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 	musb_hnp_stop(musb);
 #endif
 
-	if (musb->gadget_driver == driver) {
+	(void) musb_gadget_vbus_draw(&musb->g, 0);
 
-		(void) musb_gadget_vbus_draw(&musb->g, 0);
+	musb->xceiv->state = OTG_STATE_UNDEFINED;
+	stop_activity(musb, driver);
+	otg_set_peripheral(musb->xceiv, NULL);
 
-		musb->xceiv->state = OTG_STATE_UNDEFINED;
-		stop_activity(musb, driver);
-		otg_set_peripheral(musb->xceiv, NULL);
+	DBG(3, "unregistering driver %s\n", driver->function);
 
-		DBG(3, "unregistering driver %s\n", driver->function);
-		spin_unlock_irqrestore(&musb->lock, flags);
-		driver->unbind(&musb->g);
-		spin_lock_irqsave(&musb->lock, flags);
+	spin_unlock_irqrestore(&musb->lock, flags);
+	driver->unbind(&musb->g);
+	spin_lock_irqsave(&musb->lock, flags);
 
-		musb->gadget_driver = NULL;
-		musb->g.dev.driver = NULL;
+	musb->gadget_driver = NULL;
+	musb->g.dev.driver = NULL;
 
-		musb->is_active = 0;
-		musb_platform_try_idle(musb, 0);
-	} else
-		retval = -EINVAL;
+	musb->is_active = 0;
+	musb_platform_try_idle(musb, 0);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
-	if (is_otg_enabled(musb) && retval == 0) {
+	if (is_otg_enabled(musb)) {
 		usb_remove_hcd(musb_to_hcd(musb));
 		/* FIXME we need to be able to register another
 		 * gadget driver here and have everything work;
@@ -1986,7 +2008,12 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
 		 */
 	}
 
-	return retval;
+	if (!is_otg_enabled(musb))
+		musb_stop(musb);
+
+	pm_runtime_put(musb->controller);
+
+	return 0;
 }
 EXPORT_SYMBOL(usb_gadget_unregister_driver);
 
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h
index a55354f..66b7c5e 100644
--- a/drivers/usb/musb/musb_gadget.h
+++ b/drivers/usb/musb/musb_gadget.h
@@ -35,6 +35,8 @@
 #ifndef __MUSB_GADGET_H
 #define __MUSB_GADGET_H
 
+#include <linux/list.h>
+
 enum buffer_map_state {
 	UN_MAPPED = 0,
 	PRE_MAPPED,
@@ -43,6 +45,7 @@ enum buffer_map_state {
 
 struct musb_request {
 	struct usb_request	request;
+	struct list_head	list;
 	struct musb_ep		*ep;
 	struct musb		*musb;
 	u8 tx;			/* endpoint direction */
@@ -94,13 +97,13 @@ static inline struct musb_ep *to_musb_ep(struct usb_ep *ep)
 	return ep ? container_of(ep, struct musb_ep, end_point) : NULL;
 }
 
-static inline struct usb_request *next_request(struct musb_ep *ep)
+static inline struct musb_request *next_request(struct musb_ep *ep)
 {
 	struct list_head	*queue = &ep->req_list;
 
 	if (list_empty(queue))
 		return NULL;
-	return container_of(queue->next, struct usb_request, list);
+	return container_of(queue->next, struct musb_request, list);
 }
 
 extern void musb_g_tx(struct musb *musb, u8 epnum);
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 6dd03f4..75a542e 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -304,8 +304,7 @@ __acquires(musb->lock)
 				}
 
 				/* Maybe start the first request in the queue */
-				request = to_musb_request(
-						next_request(musb_ep));
+				request = next_request(musb_ep);
 				if (!musb_ep->busy && request) {
 					DBG(3, "restarting the request\n");
 					musb_ep_restart(musb, request);
@@ -491,10 +490,12 @@ stall:
 static void ep0_rxstate(struct musb *musb)
 {
 	void __iomem		*regs = musb->control_ep->regs;
+	struct musb_request	*request;
 	struct usb_request	*req;
 	u16			count, csr;
 
-	req = next_ep0_request(musb);
+	request = next_ep0_request(musb);
+	req = &request->request;
 
 	/* read packet and ack; or stall because of gadget driver bug:
 	 * should have provided the rx buffer before setup() returned.
@@ -544,17 +545,20 @@ static void ep0_rxstate(struct musb *musb)
 static void ep0_txstate(struct musb *musb)
 {
 	void __iomem		*regs = musb->control_ep->regs;
-	struct usb_request	*request = next_ep0_request(musb);
+	struct musb_request	*req = next_ep0_request(musb);
+	struct usb_request	*request;
 	u16			csr = MUSB_CSR0_TXPKTRDY;
 	u8			*fifo_src;
 	u8			fifo_count;
 
-	if (!request) {
+	if (!req) {
 		/* WARN_ON(1); */
 		DBG(2, "odd; csr0 %04x\n", musb_readw(regs, MUSB_CSR0));
 		return;
 	}
 
+	request = &req->request;
+
 	/* load the data */
 	fifo_src = (u8 *) request->buf + request->actual;
 	fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
@@ -598,7 +602,7 @@ static void ep0_txstate(struct musb *musb)
 static void
 musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
 {
-	struct usb_request	*r;
+	struct musb_request	*r;
 	void __iomem		*regs = musb->control_ep->regs;
 
 	musb_read_fifo(&musb->endpoints[0], sizeof *req, (u8 *)req);
@@ -616,7 +620,7 @@ musb_read_setup(struct musb *musb, struct usb_ctrlrequest *req)
 	/* clean up any leftover transfers */
 	r = next_ep0_request(musb);
 	if (r)
-		musb_g_ep0_giveback(musb, r);
+		musb_g_ep0_giveback(musb, &r->request);
 
 	/* For zero-data requests we want to delay the STATUS stage to
 	 * avoid SETUPEND errors.  If we read data (OUT), delay accepting
@@ -758,11 +762,11 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb)
 	case MUSB_EP0_STAGE_STATUSOUT:
 		/* end of sequence #1: write to host (TX state) */
 		{
-			struct usb_request	*req;
+			struct musb_request	*req;
 
 			req = next_ep0_request(musb);
 			if (req)
-				musb_g_ep0_giveback(musb, req);
+				musb_g_ep0_giveback(musb, &req->request);
 		}
 
 		/*
@@ -961,7 +965,7 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags)
 	}
 
 	/* add request to the list */
-	list_add_tail(&(req->request.list), &(ep->req_list));
+	list_add_tail(&req->list, &ep->req_list);
 
 	DBG(3, "queue to %s (%s), length=%d\n",
 			ep->name, ep->is_in ? "IN/TX" : "OUT/RX",
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 0f523d7..5eef4a8 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -1335,7 +1335,7 @@ void musb_host_tx(struct musb *musb, u8 epnum)
 	if (length > qh->maxpacket)
 		length = qh->maxpacket;
 	/* Unmap the buffer so that CPU can use it */
-	unmap_urb_for_dma(musb_to_hcd(musb), urb);
+	usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb);
 	musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset);
 	qh->segsize = length;
 
@@ -1757,7 +1757,7 @@ void musb_host_rx(struct musb *musb, u8 epnum)
 
 		if (!dma) {
 			/* Unmap the buffer so that CPU can use it */
-			unmap_urb_for_dma(musb_to_hcd(musb), urb);
+			usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb);
 			done = musb_host_packet_rx(musb, urb,
 					epnum, iso_err);
 			DBG(6, "read %spacket\n", done ? "last " : "");
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index b46d187..489104a 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -305,8 +305,8 @@ int musb_hub_control(
 		desc->bHubContrCurrent = 0;
 
 		/* workaround bogus struct definition */
-		desc->DeviceRemovable[0] = 0x02;	/* port 1 */
-		desc->DeviceRemovable[1] = 0xff;
+		desc->u.hs.DeviceRemovable[0] = 0x02;	/* port 1 */
+		desc->u.hs.DeviceRemovable[1] = 0xff;
 		}
 		break;
 	case GetHubStatus:
diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h
index 21056c9..320fd4a 100644
--- a/drivers/usb/musb/musbhsdma.h
+++ b/drivers/usb/musb/musbhsdma.h
@@ -31,7 +31,7 @@
  *
  */
 
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
 #include "omap2430.h"
 #endif
 
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index bc8badd..25cb8b0 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -33,6 +33,8 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
 
 #include "musb_core.h"
 #include "omap2430.h"
@@ -40,7 +42,6 @@
 struct omap2430_glue {
 	struct device		*dev;
 	struct platform_device	*musb;
-	struct clk		*clk;
 };
 #define glue_to_musb(g)		platform_get_drvdata(g->musb)
 
@@ -216,20 +217,12 @@ static inline void omap2430_low_level_exit(struct musb *musb)
 	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 	l |= ENABLEFORCE;	/* enable MSTANDBY */
 	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
-
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l |= ENABLEWAKEUP;	/* enable wakeup */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
 }
 
 static inline void omap2430_low_level_init(struct musb *musb)
 {
 	u32 l;
 
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l &= ~ENABLEWAKEUP;	/* disable wakeup */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
-
 	l = musb_readl(musb->mregs, OTG_FORCESTDBY);
 	l &= ~ENABLEFORCE;	/* disable MSTANDBY */
 	musb_writel(musb->mregs, OTG_FORCESTDBY, l);
@@ -251,31 +244,39 @@ static int musb_otg_notifications(struct notifier_block *nb,
 		if (is_otg_enabled(musb)) {
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
 			if (musb->gadget_driver) {
+				pm_runtime_get_sync(musb->controller);
 				otg_init(musb->xceiv);
-
-				if (data->interface_type ==
-						MUSB_INTERFACE_UTMI)
-					omap2430_musb_set_vbus(musb, 1);
-
+				omap2430_musb_set_vbus(musb, 1);
 			}
 #endif
 		} else {
+			pm_runtime_get_sync(musb->controller);
 			otg_init(musb->xceiv);
-			if (data->interface_type ==
-					MUSB_INTERFACE_UTMI)
-				omap2430_musb_set_vbus(musb, 1);
+			omap2430_musb_set_vbus(musb, 1);
 		}
 		break;
 
 	case USB_EVENT_VBUS:
 		DBG(4, "VBUS Connect\n");
 
+		if (musb->gadget_driver)
+			pm_runtime_get_sync(musb->controller);
+
 		otg_init(musb->xceiv);
 		break;
 
 	case USB_EVENT_NONE:
 		DBG(4, "VBUS Disconnect\n");
 
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
+		if (is_otg_enabled(musb))
+			if (musb->gadget_driver)
+#endif
+			{
+				pm_runtime_mark_last_busy(musb->controller);
+				pm_runtime_put_autosuspend(musb->controller);
+			}
+
 		if (data->interface_type == MUSB_INTERFACE_UTMI) {
 			if (musb->xceiv->set_vbus)
 				otg_set_vbus(musb->xceiv, 0);
@@ -307,22 +308,11 @@ static int omap2430_musb_init(struct musb *musb)
 		return -ENODEV;
 	}
 
-	omap2430_low_level_init(musb);
-
-	l = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	l &= ~ENABLEWAKEUP;	/* disable wakeup */
-	l &= ~NOSTDBY;		/* remove possible nostdby */
-	l |= SMARTSTDBY;	/* enable smart standby */
-	l &= ~AUTOIDLE;		/* disable auto idle */
-	l &= ~NOIDLE;		/* remove possible noidle */
-	l |= SMARTIDLE;		/* enable smart idle */
-	/*
-	 * MUSB AUTOIDLE don't work in 3430.
-	 * Workaround by Richard Woodruff/TI
-	 */
-	if (!cpu_is_omap3430())
-		l |= AUTOIDLE;		/* enable auto idle */
-	musb_writel(musb->mregs, OTG_SYSCONFIG, l);
+	status = pm_runtime_get_sync(dev);
+	if (status < 0) {
+		dev_err(dev, "pm_runtime_get_sync FAILED");
+		goto err1;
+	}
 
 	l = musb_readl(musb->mregs, OTG_INTERFSEL);
 
@@ -350,14 +340,58 @@ static int omap2430_musb_init(struct musb *musb)
 	if (status)
 		DBG(1, "notification register failed\n");
 
-	/* check whether cable is already connected */
-	if (musb->xceiv->state ==OTG_STATE_B_IDLE)
-		musb_otg_notifications(&musb->nb, 1,
-					musb->xceiv->gadget);
-
 	setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
 
 	return 0;
+
+err1:
+	pm_runtime_disable(dev);
+	return status;
+}
+
+static void omap2430_musb_enable(struct musb *musb)
+{
+	u8		devctl;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	struct device *dev = musb->controller;
+	struct musb_hdrc_platform_data *pdata = dev->platform_data;
+	struct omap_musb_board_data *data = pdata->board_data;
+
+	switch (musb->xceiv->last_event) {
+
+	case USB_EVENT_ID:
+		otg_init(musb->xceiv);
+		if (data->interface_type == MUSB_INTERFACE_UTMI) {
+			devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+			/* start the session */
+			devctl |= MUSB_DEVCTL_SESSION;
+			musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+			while (musb_readb(musb->mregs, MUSB_DEVCTL) &
+						MUSB_DEVCTL_BDEVICE) {
+				cpu_relax();
+
+				if (time_after(jiffies, timeout)) {
+					dev_err(musb->controller,
+					"configured as A device timeout");
+					break;
+				}
+			}
+		}
+		break;
+
+	case USB_EVENT_VBUS:
+		otg_init(musb->xceiv);
+		break;
+
+	default:
+		break;
+	}
+}
+
+static void omap2430_musb_disable(struct musb *musb)
+{
+	if (musb->xceiv->last_event)
+		otg_shutdown(musb->xceiv);
 }
 
 static int omap2430_musb_exit(struct musb *musb)
@@ -378,6 +412,9 @@ static const struct musb_platform_ops omap2430_ops = {
 	.try_idle	= omap2430_musb_try_idle,
 
 	.set_vbus	= omap2430_musb_set_vbus,
+
+	.enable		= omap2430_musb_enable,
+	.disable	= omap2430_musb_disable,
 };
 
 static u64 omap2430_dmamask = DMA_BIT_MASK(32);
@@ -387,8 +424,6 @@ static int __init omap2430_probe(struct platform_device *pdev)
 	struct musb_hdrc_platform_data	*pdata = pdev->dev.platform_data;
 	struct platform_device		*musb;
 	struct omap2430_glue		*glue;
-	struct clk			*clk;
-
 	int				ret = -ENOMEM;
 
 	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
@@ -403,26 +438,12 @@ static int __init omap2430_probe(struct platform_device *pdev)
 		goto err1;
 	}
 
-	clk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "failed to get clock\n");
-		ret = PTR_ERR(clk);
-		goto err2;
-	}
-
-	ret = clk_enable(clk);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto err3;
-	}
-
 	musb->dev.parent		= &pdev->dev;
 	musb->dev.dma_mask		= &omap2430_dmamask;
 	musb->dev.coherent_dma_mask	= omap2430_dmamask;
 
 	glue->dev			= &pdev->dev;
 	glue->musb			= musb;
-	glue->clk			= clk;
 
 	pdata->platform_ops		= &omap2430_ops;
 
@@ -432,28 +453,24 @@ static int __init omap2430_probe(struct platform_device *pdev)
 			pdev->num_resources);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add resources\n");
-		goto err4;
+		goto err2;
 	}
 
 	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
 	if (ret) {
 		dev_err(&pdev->dev, "failed to add platform_data\n");
-		goto err4;
+		goto err2;
 	}
 
 	ret = platform_device_add(musb);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register musb device\n");
-		goto err4;
+		goto err2;
 	}
 
-	return 0;
-
-err4:
-	clk_disable(clk);
+	pm_runtime_enable(&pdev->dev);
 
-err3:
-	clk_put(clk);
+	return 0;
 
 err2:
 	platform_device_put(musb);
@@ -471,61 +488,40 @@ static int __exit omap2430_remove(struct platform_device *pdev)
 
 	platform_device_del(glue->musb);
 	platform_device_put(glue->musb);
-	clk_disable(glue->clk);
-	clk_put(glue->clk);
+	pm_runtime_put(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
 	kfree(glue);
 
 	return 0;
 }
 
 #ifdef CONFIG_PM
-static void omap2430_save_context(struct musb *musb)
-{
-	musb->context.otg_sysconfig = musb_readl(musb->mregs, OTG_SYSCONFIG);
-	musb->context.otg_forcestandby = musb_readl(musb->mregs, OTG_FORCESTDBY);
-}
 
-static void omap2430_restore_context(struct musb *musb)
-{
-	musb_writel(musb->mregs, OTG_SYSCONFIG, musb->context.otg_sysconfig);
-	musb_writel(musb->mregs, OTG_FORCESTDBY, musb->context.otg_forcestandby);
-}
-
-static int omap2430_suspend(struct device *dev)
+static int omap2430_runtime_suspend(struct device *dev)
 {
 	struct omap2430_glue		*glue = dev_get_drvdata(dev);
 	struct musb			*musb = glue_to_musb(glue);
 
 	omap2430_low_level_exit(musb);
 	otg_set_suspend(musb->xceiv, 1);
-	omap2430_save_context(musb);
-	clk_disable(glue->clk);
 
 	return 0;
 }
 
-static int omap2430_resume(struct device *dev)
+static int omap2430_runtime_resume(struct device *dev)
 {
 	struct omap2430_glue		*glue = dev_get_drvdata(dev);
 	struct musb			*musb = glue_to_musb(glue);
-	int				ret;
-
-	ret = clk_enable(glue->clk);
-	if (ret) {
-		dev_err(dev, "faled to enable clock\n");
-		return ret;
-	}
 
 	omap2430_low_level_init(musb);
-	omap2430_restore_context(musb);
 	otg_set_suspend(musb->xceiv, 0);
 
 	return 0;
 }
 
 static struct dev_pm_ops omap2430_pm_ops = {
-	.suspend	= omap2430_suspend,
-	.resume		= omap2430_resume,
+	.runtime_suspend = omap2430_runtime_suspend,
+	.runtime_resume = omap2430_runtime_resume,
 };
 
 #define DEV_PM_OPS	(&omap2430_pm_ops)
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index c061a88..99cb541 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -680,7 +680,7 @@ dma_controller_create(struct musb *musb, void __iomem *base)
 
 	tusb_dma = kzalloc(sizeof(struct tusb_omap_dma), GFP_KERNEL);
 	if (!tusb_dma)
-		goto cleanup;
+		goto out;
 
 	tusb_dma->musb = musb;
 	tusb_dma->tbase = musb->ctrl_base;
@@ -721,6 +721,6 @@ dma_controller_create(struct musb *musb, void __iomem *base)
 
 cleanup:
 	dma_controller_destroy(&tusb_dma->controller);
-
+out:
 	return NULL;
 }
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 9ffc823..daf3e5f 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -49,6 +49,13 @@ config USB_ULPI
 	  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
@@ -93,7 +100,7 @@ config USB_LANGWELL_OTG
 	  To compile this driver as a module, choose M here: the
 	  module will be called langwell_otg.
 
-config USB_MSM_OTG_72K
+config USB_MSM_OTG
 	tristate "OTG support for Qualcomm on-chip USB controller"
 	depends on (USB || USB_GADGET) && ARCH_MSM
 	select USB_OTG_UTILS
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index a520e71..e22d917 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_TWL6030_USB)	+= twl6030-usb.o
 obj-$(CONFIG_USB_LANGWELL_OTG)	+= langwell_otg.o
 obj-$(CONFIG_NOP_USB_XCEIV)	+= nop-usb-xceiv.o
 obj-$(CONFIG_USB_ULPI)		+= ulpi.o
-obj-$(CONFIG_USB_MSM_OTG_72K)	+= msm72k_otg.o
+obj-$(CONFIG_USB_ULPI_VIEWPORT)	+= ulpi_viewport.o
+obj-$(CONFIG_USB_MSM_OTG)	+= msm_otg.o
 obj-$(CONFIG_AB8500_USB)	+= ab8500-usb.o
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index d14736b..07ccea9 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -212,7 +212,7 @@ static int ab8500_usb_link_status_update(struct ab8500_usb *ab)
 		break;
 	}
 
-	blocking_notifier_call_chain(&ab->otg.notifier, event, v);
+	atomic_notifier_call_chain(&ab->otg.notifier, event, v);
 
 	return 0;
 }
@@ -281,7 +281,7 @@ static int ab8500_usb_set_power(struct otg_transceiver *otg, unsigned mA)
 	ab->vbus_draw = mA;
 
 	if (mA)
-		blocking_notifier_call_chain(&ab->otg.notifier,
+		atomic_notifier_call_chain(&ab->otg.notifier,
 				USB_EVENT_ENUMERATED, ab->otg.gadget);
 	return 0;
 }
@@ -500,7 +500,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, ab);
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&ab->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&ab->otg.notifier);
 
 	/* v1: Wait for link status to become stable.
 	 * all: Updates form set_host and set_peripheral as they are atomic.
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index e00fa1b..8c6fdef 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1510,7 +1510,7 @@ isp1301_start_hnp(struct otg_transceiver *dev)
 
 /*-------------------------------------------------------------------------*/
 
-static int __init
+static int __devinit
 isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 {
 	int			status;
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
index 9fea482..7f9b8cd 100644
--- a/drivers/usb/otg/langwell_otg.c
+++ b/drivers/usb/otg/langwell_otg.c
@@ -174,50 +174,24 @@ static int langwell_otg_set_power(struct otg_transceiver *otg,
 	return 0;
 }
 
-/* A-device drives vbus, controlled through PMIC CHRGCNTL register*/
+/* A-device drives vbus, controlled through IPC commands */
 static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
 {
 	struct langwell_otg		*lnw = the_transceiver;
-	u8 r;
+	u8				sub_id;
 
 	dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off");
 
-	/* FIXME: surely we should cache this on the first read. If not use
-	   readv to avoid two transactions */
-	if (intel_scu_ipc_ioread8(0x00, &r) < 0) {
-		dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2");
-		return -EBUSY;
-	}
-	if ((r & 0x03) != 0x02) {
-		dev_dbg(lnw->dev, "not NEC PMIC attached\n");
-		return -EBUSY;
-	}
-
-	if (intel_scu_ipc_ioread8(0x20, &r) < 0) {
-		dev_dbg(lnw->dev, "Failed to read PMIC register 0xD2");
-		return -EBUSY;
-	}
-
-	if ((r & 0x20) == 0) {
-		dev_dbg(lnw->dev, "no battery attached\n");
-		return -EBUSY;
-	}
+	if (enabled)
+		sub_id = 0x8; /* Turn on the VBus */
+	else
+		sub_id = 0x9; /* Turn off the VBus */
 
-	/* Workaround for battery attachment issue */
-	if (r == 0x34) {
-		dev_dbg(lnw->dev, "no battery attached on SH\n");
+	if (intel_scu_ipc_simple_command(0xef, sub_id)) {
+		dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n");
 		return -EBUSY;
 	}
 
-	dev_dbg(lnw->dev, "battery attached. 2 reg = %x\n", r);
-
-	/* workaround: FW detect writing 0x20/0xc0 to d4 event.
-	 * this is only for NEC PMIC.
-	 */
-
-	if (intel_scu_ipc_iowrite8(0xD4, enabled ? 0x20 : 0xC0))
-		dev_dbg(lnw->dev, "Failed to write PMIC.\n");
-
 	dev_dbg(lnw->dev, "%s --->\n", __func__);
 
 	return 0;
@@ -394,14 +368,14 @@ static void langwell_otg_phy_low_power(int on)
 	dev_dbg(lnw->dev, "%s <--- done\n", __func__);
 }
 
-/* After drv vbus, add 2 ms delay to set PHCD */
+/* After drv vbus, add 5 ms delay to set PHCD */
 static void langwell_otg_phy_low_power_wait(int on)
 {
 	struct langwell_otg	*lnw = the_transceiver;
 
-	dev_dbg(lnw->dev, "add 2ms delay before programing PHCD\n");
+	dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n");
 
-	mdelay(2);
+	mdelay(5);
 	langwell_otg_phy_low_power(on);
 }
 
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
deleted file mode 100644
index 1cd52ed..0000000
--- a/drivers/usb/otg/msm72k_otg.c
+++ /dev/null
@@ -1,1125 +0,0 @@
-/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- */
-
-#include <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 <mach/clk.h>
-
-#define MSM_USB_BASE	(motg->regs)
-#define DRIVER_NAME	"msm_otg"
-
-#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
-static int ulpi_read(struct otg_transceiver *otg, u32 reg)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-	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(otg->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 otg_transceiver *otg, u32 val, u32 reg)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-	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(otg->dev, "ulpi_write: timeout\n");
-		return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-static struct otg_io_access_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->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
-				seq[0], seq[1]);
-		ulpi_write(&motg->otg, 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->otg.dev, "usb hs_clk assert failed\n");
-	} else {
-		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
-		if (ret)
-			dev_err(motg->otg.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->otg.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->otg.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->otg, 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->otg, ULPI_DEBUG);
-		if (ret != -ETIMEDOUT)
-			break;
-		ret = msm_otg_phy_clk_reset(motg);
-		if (ret)
-			return ret;
-	}
-	if (!retries)
-		return -ETIMEDOUT;
-
-	dev_info(motg->otg.dev, "phy_reset: success\n");
-	return 0;
-}
-
-#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
-static int msm_otg_reset(struct otg_transceiver *otg)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-	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(otg->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(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
-		ulpi_write(otg, ulpi_val, ULPI_USB_INT_EN_FALL);
-	}
-
-	return 0;
-}
-
-#define PHY_SUSPEND_TIMEOUT_USEC	(500 * 1000)
-static int msm_otg_suspend(struct msm_otg *motg)
-{
-	struct otg_transceiver *otg = &motg->otg;
-	struct usb_bus *bus = 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);
-	/*
-	 * 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).
-	 */
-	ulpi_read(otg, 0x14);
-
-	/*
-	 * 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.
-	 */
-	if (pdata->otg_control == OTG_PHY_CONTROL)
-		ulpi_write(otg, 0x01, 0x30);
-
-	/*
-	 * PLL is not turned off when PHY enters into low power mode (LPM).
-	 * Disable PLL for maximum power savings.
-	 */
-	ulpi_write(otg, 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(otg->dev, "Unable to suspend PHY\n");
-		msm_otg_reset(otg);
-		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);
-
-	clk_disable(motg->pclk);
-	clk_disable(motg->clk);
-	if (motg->core_clk)
-		clk_disable(motg->core_clk);
-
-	if (device_may_wakeup(otg->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(otg->dev, "USB in low power mode\n");
-
-	return 0;
-}
-
-#define PHY_RESUME_TIMEOUT_USEC	(100 * 1000)
-static int msm_otg_resume(struct msm_otg *motg)
-{
-	struct otg_transceiver *otg = &motg->otg;
-	struct usb_bus *bus = otg->host;
-	int cnt = 0;
-	unsigned temp;
-
-	if (!atomic_read(&motg->in_lpm))
-		return 0;
-
-	clk_enable(motg->pclk);
-	clk_enable(motg->clk);
-	if (motg->core_clk)
-		clk_enable(motg->core_clk);
-
-	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(otg->dev, "Unable to resume USB."
-				"Re-plugin the cable\n");
-		msm_otg_reset(otg);
-	}
-
-skip_phy_resume:
-	if (device_may_wakeup(otg->dev))
-		disable_irq_wake(motg->irq);
-	if (bus)
-		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
-
-	if (motg->async_int) {
-		motg->async_int = 0;
-		pm_runtime_put(otg->dev);
-		enable_irq(motg->irq);
-	}
-
-	atomic_set(&motg->in_lpm, 0);
-
-	dev_info(otg->dev, "USB exited from low power mode\n");
-
-	return 0;
-}
-
-static void msm_otg_start_host(struct otg_transceiver *otg, int on)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-	struct msm_otg_platform_data *pdata = motg->pdata;
-	struct usb_hcd *hcd;
-
-	if (!otg->host)
-		return;
-
-	hcd = bus_to_hcd(otg->host);
-
-	if (on) {
-		dev_dbg(otg->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(otg->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 otg_transceiver *otg, struct usb_bus *host)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-	struct usb_hcd *hcd;
-
-	/*
-	 * Fail host registration if this board can support
-	 * only peripheral configuration.
-	 */
-	if (motg->pdata->mode == USB_PERIPHERAL) {
-		dev_info(otg->dev, "Host mode is not supported\n");
-		return -ENODEV;
-	}
-
-	if (!host) {
-		if (otg->state == OTG_STATE_A_HOST) {
-			pm_runtime_get_sync(otg->dev);
-			msm_otg_start_host(otg, 0);
-			otg->host = NULL;
-			otg->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->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->dev);
-		schedule_work(&motg->sm_work);
-	}
-
-	return 0;
-}
-
-static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-	struct msm_otg_platform_data *pdata = motg->pdata;
-
-	if (!otg->gadget)
-		return;
-
-	if (on) {
-		dev_dbg(otg->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(otg->gadget);
-	} else {
-		dev_dbg(otg->dev, "gadget off\n");
-		usb_gadget_vbus_disconnect(otg->gadget);
-		if (pdata->setup_gpio)
-			pdata->setup_gpio(OTG_STATE_UNDEFINED);
-	}
-
-}
-
-static int msm_otg_set_peripheral(struct otg_transceiver *otg,
-			struct usb_gadget *gadget)
-{
-	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
-
-	/*
-	 * Fail peripheral registration if this board can support
-	 * only host configuration.
-	 */
-	if (motg->pdata->mode == USB_HOST) {
-		dev_info(otg->dev, "Peripheral mode is not supported\n");
-		return -ENODEV;
-	}
-
-	if (!gadget) {
-		if (otg->state == OTG_STATE_B_PERIPHERAL) {
-			pm_runtime_get_sync(otg->dev);
-			msm_otg_start_peripheral(otg, 0);
-			otg->gadget = NULL;
-			otg->state = OTG_STATE_UNDEFINED;
-			schedule_work(&motg->sm_work);
-		} else {
-			otg->gadget = NULL;
-		}
-
-		return 0;
-	}
-	otg->gadget = gadget;
-	dev_dbg(otg->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->dev);
-		schedule_work(&motg->sm_work);
-	}
-
-	return 0;
-}
-
-/*
- * 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 otg_transceiver *otg = &motg->otg;
-
-	switch (otg->state) {
-	case OTG_STATE_UNDEFINED:
-		dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
-		msm_otg_reset(otg);
-		msm_otg_init_sm(motg);
-		otg->state = OTG_STATE_B_IDLE;
-		/* FALL THROUGH */
-	case OTG_STATE_B_IDLE:
-		dev_dbg(otg->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, 1);
-			otg->state = OTG_STATE_A_HOST;
-		} else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
-			msm_otg_start_peripheral(otg, 1);
-			otg->state = OTG_STATE_B_PERIPHERAL;
-		}
-		pm_runtime_put_sync(otg->dev);
-		break;
-	case OTG_STATE_B_PERIPHERAL:
-		dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
-		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
-				!test_bit(ID, &motg->inputs)) {
-			msm_otg_start_peripheral(otg, 0);
-			otg->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg);
-			schedule_work(w);
-		}
-		break;
-	case OTG_STATE_A_HOST:
-		dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
-		if (test_bit(ID, &motg->inputs)) {
-			msm_otg_start_host(otg, 0);
-			otg->state = OTG_STATE_B_IDLE;
-			msm_otg_reset(otg);
-			schedule_work(w);
-		}
-		break;
-	default:
-		break;
-	}
-}
-
-static irqreturn_t msm_otg_irq(int irq, void *data)
-{
-	struct msm_otg *motg = data;
-	struct otg_transceiver *otg = &motg->otg;
-	u32 otgsc = 0;
-
-	if (atomic_read(&motg->in_lpm)) {
-		disable_irq_nosync(irq);
-		motg->async_int = 1;
-		pm_runtime_get(otg->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(otg->dev, "ID set/clear\n");
-		pm_runtime_get_noresume(otg->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(otg->dev, "BSV set/clear\n");
-		pm_runtime_get_noresume(otg->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 otg_transceiver *otg = &motg->otg;
-
-	switch (otg->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 msm_otg *motg = file->private_data;
-	char buf[16];
-	struct otg_transceiver *otg = &motg->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->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->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->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->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 otg_transceiver *otg;
-
-	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->pdata = pdev->dev.platform_data;
-	otg = &motg->otg;
-	otg->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;
-	}
-
-	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_clk;
-	}
-
-	/*
-	 * 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);
-	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);
-	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;
-	}
-
-	otg->init = msm_otg_reset;
-	otg->set_host = msm_otg_set_host;
-	otg->set_peripheral = msm_otg_set_peripheral;
-
-	otg->io_ops = &msm_otg_io_ops;
-
-	ret = otg_set_transceiver(&motg->otg);
-	if (ret) {
-		dev_err(&pdev->dev, "otg_set_transceiver 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);
-free_regs:
-	iounmap(motg->regs);
-put_core_clk:
-	if (motg->core_clk)
-		clk_put(motg->core_clk);
-	clk_put(motg->pclk);
-put_clk:
-	clk_put(motg->clk);
-put_phy_reset_clk:
-	clk_put(motg->phy_reset_clk);
-free_motg:
-	kfree(motg);
-	return ret;
-}
-
-static int __devexit msm_otg_remove(struct platform_device *pdev)
-{
-	struct msm_otg *motg = platform_get_drvdata(pdev);
-	struct otg_transceiver *otg = &motg->otg;
-	int cnt = 0;
-
-	if (otg->host || otg->gadget)
-		return -EBUSY;
-
-	msm_otg_debugfs_cleanup();
-	cancel_work_sync(&motg->sm_work);
-
-	msm_otg_resume(motg);
-
-	device_init_wakeup(&pdev->dev, 0);
-	pm_runtime_disable(&pdev->dev);
-
-	otg_set_transceiver(NULL);
-	free_irq(motg->irq, motg);
-
-	/*
-	 * Put PHY in low power mode.
-	 */
-	ulpi_read(otg, 0x14);
-	ulpi_write(otg, 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(otg->dev, "Unable to suspend PHY\n");
-
-	clk_disable(motg->pclk);
-	clk_disable(motg->clk);
-	if (motg->core_clk)
-		clk_disable(motg->core_clk);
-
-	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);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_RUNTIME
-static int msm_otg_runtime_idle(struct device *dev)
-{
-	struct msm_otg *motg = dev_get_drvdata(dev);
-	struct otg_transceiver *otg = &motg->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->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);
-}
-#else
-#define msm_otg_runtime_idle	NULL
-#define msm_otg_runtime_suspend	NULL
-#define msm_otg_runtime_resume	NULL
-#endif
-
-#ifdef CONFIG_PM
-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;
-}
-#else
-#define msm_otg_pm_suspend	NULL
-#define msm_otg_pm_resume	NULL
-#endif
-
-static const struct dev_pm_ops msm_otg_dev_pm_ops = {
-	.runtime_suspend = msm_otg_runtime_suspend,
-	.runtime_resume  = msm_otg_runtime_resume,
-	.runtime_idle    = msm_otg_runtime_idle,
-	.suspend         = msm_otg_pm_suspend,
-	.resume          = msm_otg_pm_resume,
-};
-
-static struct platform_driver msm_otg_driver = {
-	.remove = __devexit_p(msm_otg_remove),
-	.driver = {
-		.name = DRIVER_NAME,
-		.owner = THIS_MODULE,
-		.pm = &msm_otg_dev_pm_ops,
-	},
-};
-
-static int __init msm_otg_init(void)
-{
-	return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
-}
-
-static void __exit msm_otg_exit(void)
-{
-	platform_driver_unregister(&msm_otg_driver);
-}
-
-module_init(msm_otg_init);
-module_exit(msm_otg_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MSM USB transceiver driver");
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
new file mode 100644
index 0000000..2965986
--- /dev/null
+++ b/drivers/usb/otg/msm_otg.c
@@ -0,0 +1,1124 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <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 <mach/clk.h>
+
+#define MSM_USB_BASE	(motg->regs)
+#define DRIVER_NAME	"msm_otg"
+
+#define ULPI_IO_TIMEOUT_USEC	(10 * 1000)
+static int ulpi_read(struct otg_transceiver *otg, u32 reg)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	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(otg->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 otg_transceiver *otg, u32 val, u32 reg)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	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(otg->dev, "ulpi_write: timeout\n");
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static struct otg_io_access_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->otg.dev, "ulpi: write 0x%02x to 0x%02x\n",
+				seq[0], seq[1]);
+		ulpi_write(&motg->otg, 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->otg.dev, "usb hs_clk assert failed\n");
+	} else {
+		ret = clk_reset(motg->clk, CLK_RESET_DEASSERT);
+		if (ret)
+			dev_err(motg->otg.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->otg.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->otg.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->otg, 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->otg, ULPI_DEBUG);
+		if (ret != -ETIMEDOUT)
+			break;
+		ret = msm_otg_phy_clk_reset(motg);
+		if (ret)
+			return ret;
+	}
+	if (!retries)
+		return -ETIMEDOUT;
+
+	dev_info(motg->otg.dev, "phy_reset: success\n");
+	return 0;
+}
+
+#define LINK_RESET_TIMEOUT_USEC		(250 * 1000)
+static int msm_otg_reset(struct otg_transceiver *otg)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	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(otg->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(otg, ulpi_val, ULPI_USB_INT_EN_RISE);
+		ulpi_write(otg, 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 otg_transceiver *otg = &motg->otg;
+	struct usb_bus *bus = 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);
+	/*
+	 * 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).
+	 */
+	ulpi_read(otg, 0x14);
+
+	/*
+	 * 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.
+	 */
+	if (pdata->otg_control == OTG_PHY_CONTROL)
+		ulpi_write(otg, 0x01, 0x30);
+
+	/*
+	 * PLL is not turned off when PHY enters into low power mode (LPM).
+	 * Disable PLL for maximum power savings.
+	 */
+	ulpi_write(otg, 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(otg->dev, "Unable to suspend PHY\n");
+		msm_otg_reset(otg);
+		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);
+
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+	if (motg->core_clk)
+		clk_disable(motg->core_clk);
+
+	if (device_may_wakeup(otg->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(otg->dev, "USB in low power mode\n");
+
+	return 0;
+}
+
+static int msm_otg_resume(struct msm_otg *motg)
+{
+	struct otg_transceiver *otg = &motg->otg;
+	struct usb_bus *bus = otg->host;
+	int cnt = 0;
+	unsigned temp;
+
+	if (!atomic_read(&motg->in_lpm))
+		return 0;
+
+	clk_enable(motg->pclk);
+	clk_enable(motg->clk);
+	if (motg->core_clk)
+		clk_enable(motg->core_clk);
+
+	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(otg->dev, "Unable to resume USB."
+				"Re-plugin the cable\n");
+		msm_otg_reset(otg);
+	}
+
+skip_phy_resume:
+	if (device_may_wakeup(otg->dev))
+		disable_irq_wake(motg->irq);
+	if (bus)
+		set_bit(HCD_FLAG_HW_ACCESSIBLE, &(bus_to_hcd(bus))->flags);
+
+	if (motg->async_int) {
+		motg->async_int = 0;
+		pm_runtime_put(otg->dev);
+		enable_irq(motg->irq);
+	}
+
+	atomic_set(&motg->in_lpm, 0);
+
+	dev_info(otg->dev, "USB exited from low power mode\n");
+
+	return 0;
+}
+#endif
+
+static void msm_otg_start_host(struct otg_transceiver *otg, int on)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+	struct usb_hcd *hcd;
+
+	if (!otg->host)
+		return;
+
+	hcd = bus_to_hcd(otg->host);
+
+	if (on) {
+		dev_dbg(otg->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(otg->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 otg_transceiver *otg, struct usb_bus *host)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct usb_hcd *hcd;
+
+	/*
+	 * Fail host registration if this board can support
+	 * only peripheral configuration.
+	 */
+	if (motg->pdata->mode == USB_PERIPHERAL) {
+		dev_info(otg->dev, "Host mode is not supported\n");
+		return -ENODEV;
+	}
+
+	if (!host) {
+		if (otg->state == OTG_STATE_A_HOST) {
+			pm_runtime_get_sync(otg->dev);
+			msm_otg_start_host(otg, 0);
+			otg->host = NULL;
+			otg->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->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->dev);
+		schedule_work(&motg->sm_work);
+	}
+
+	return 0;
+}
+
+static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+	struct msm_otg_platform_data *pdata = motg->pdata;
+
+	if (!otg->gadget)
+		return;
+
+	if (on) {
+		dev_dbg(otg->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(otg->gadget);
+	} else {
+		dev_dbg(otg->dev, "gadget off\n");
+		usb_gadget_vbus_disconnect(otg->gadget);
+		if (pdata->setup_gpio)
+			pdata->setup_gpio(OTG_STATE_UNDEFINED);
+	}
+
+}
+
+static int msm_otg_set_peripheral(struct otg_transceiver *otg,
+			struct usb_gadget *gadget)
+{
+	struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
+
+	/*
+	 * Fail peripheral registration if this board can support
+	 * only host configuration.
+	 */
+	if (motg->pdata->mode == USB_HOST) {
+		dev_info(otg->dev, "Peripheral mode is not supported\n");
+		return -ENODEV;
+	}
+
+	if (!gadget) {
+		if (otg->state == OTG_STATE_B_PERIPHERAL) {
+			pm_runtime_get_sync(otg->dev);
+			msm_otg_start_peripheral(otg, 0);
+			otg->gadget = NULL;
+			otg->state = OTG_STATE_UNDEFINED;
+			schedule_work(&motg->sm_work);
+		} else {
+			otg->gadget = NULL;
+		}
+
+		return 0;
+	}
+	otg->gadget = gadget;
+	dev_dbg(otg->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->dev);
+		schedule_work(&motg->sm_work);
+	}
+
+	return 0;
+}
+
+/*
+ * 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 otg_transceiver *otg = &motg->otg;
+
+	switch (otg->state) {
+	case OTG_STATE_UNDEFINED:
+		dev_dbg(otg->dev, "OTG_STATE_UNDEFINED state\n");
+		msm_otg_reset(otg);
+		msm_otg_init_sm(motg);
+		otg->state = OTG_STATE_B_IDLE;
+		/* FALL THROUGH */
+	case OTG_STATE_B_IDLE:
+		dev_dbg(otg->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, 1);
+			otg->state = OTG_STATE_A_HOST;
+		} else if (test_bit(B_SESS_VLD, &motg->inputs) && otg->gadget) {
+			msm_otg_start_peripheral(otg, 1);
+			otg->state = OTG_STATE_B_PERIPHERAL;
+		}
+		pm_runtime_put_sync(otg->dev);
+		break;
+	case OTG_STATE_B_PERIPHERAL:
+		dev_dbg(otg->dev, "OTG_STATE_B_PERIPHERAL state\n");
+		if (!test_bit(B_SESS_VLD, &motg->inputs) ||
+				!test_bit(ID, &motg->inputs)) {
+			msm_otg_start_peripheral(otg, 0);
+			otg->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg);
+			schedule_work(w);
+		}
+		break;
+	case OTG_STATE_A_HOST:
+		dev_dbg(otg->dev, "OTG_STATE_A_HOST state\n");
+		if (test_bit(ID, &motg->inputs)) {
+			msm_otg_start_host(otg, 0);
+			otg->state = OTG_STATE_B_IDLE;
+			msm_otg_reset(otg);
+			schedule_work(w);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static irqreturn_t msm_otg_irq(int irq, void *data)
+{
+	struct msm_otg *motg = data;
+	struct otg_transceiver *otg = &motg->otg;
+	u32 otgsc = 0;
+
+	if (atomic_read(&motg->in_lpm)) {
+		disable_irq_nosync(irq);
+		motg->async_int = 1;
+		pm_runtime_get(otg->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(otg->dev, "ID set/clear\n");
+		pm_runtime_get_noresume(otg->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(otg->dev, "BSV set/clear\n");
+		pm_runtime_get_noresume(otg->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 otg_transceiver *otg = &motg->otg;
+
+	switch (otg->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 otg_transceiver *otg = &motg->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->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->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->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->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 otg_transceiver *otg;
+
+	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->pdata = pdev->dev.platform_data;
+	otg = &motg->otg;
+	otg->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;
+	}
+
+	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_clk;
+	}
+
+	/*
+	 * 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);
+	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);
+	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;
+	}
+
+	otg->init = msm_otg_reset;
+	otg->set_host = msm_otg_set_host;
+	otg->set_peripheral = msm_otg_set_peripheral;
+
+	otg->io_ops = &msm_otg_io_ops;
+
+	ret = otg_set_transceiver(&motg->otg);
+	if (ret) {
+		dev_err(&pdev->dev, "otg_set_transceiver 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);
+free_regs:
+	iounmap(motg->regs);
+put_core_clk:
+	if (motg->core_clk)
+		clk_put(motg->core_clk);
+	clk_put(motg->pclk);
+put_clk:
+	clk_put(motg->clk);
+put_phy_reset_clk:
+	clk_put(motg->phy_reset_clk);
+free_motg:
+	kfree(motg);
+	return ret;
+}
+
+static int __devexit msm_otg_remove(struct platform_device *pdev)
+{
+	struct msm_otg *motg = platform_get_drvdata(pdev);
+	struct otg_transceiver *otg = &motg->otg;
+	int cnt = 0;
+
+	if (otg->host || otg->gadget)
+		return -EBUSY;
+
+	msm_otg_debugfs_cleanup();
+	cancel_work_sync(&motg->sm_work);
+
+	pm_runtime_resume(&pdev->dev);
+
+	device_init_wakeup(&pdev->dev, 0);
+	pm_runtime_disable(&pdev->dev);
+
+	otg_set_transceiver(NULL);
+	free_irq(motg->irq, motg);
+
+	/*
+	 * Put PHY in low power mode.
+	 */
+	ulpi_read(otg, 0x14);
+	ulpi_write(otg, 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(otg->dev, "Unable to suspend PHY\n");
+
+	clk_disable(motg->pclk);
+	clk_disable(motg->clk);
+	if (motg->core_clk)
+		clk_disable(motg->core_clk);
+
+	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);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int msm_otg_runtime_idle(struct device *dev)
+{
+	struct msm_otg *motg = dev_get_drvdata(dev);
+	struct otg_transceiver *otg = &motg->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->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 = __devexit_p(msm_otg_remove),
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm = &msm_otg_dev_pm_ops,
+#endif
+	},
+};
+
+static int __init msm_otg_init(void)
+{
+	return platform_driver_probe(&msm_otg_driver, msm_otg_probe);
+}
+
+static void __exit msm_otg_exit(void)
+{
+	platform_driver_unregister(&msm_otg_driver);
+}
+
+module_init(msm_otg_init);
+module_exit(msm_otg_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM USB transceiver driver");
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index 8acf165..c1e3600 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -132,7 +132,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, nop);
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&nop->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&nop->otg.notifier);
 
 	return 0;
 exit:
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 6ca505f..e01b073 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -275,6 +275,8 @@ static enum usb_xceiv_events twl4030_usb_linkstat(struct twl4030_usb *twl)
 	dev_dbg(twl->dev, "HW_CONDITIONS 0x%02x/%d; link %d\n",
 			status, status, linkstat);
 
+	twl->otg.last_event = linkstat;
+
 	/* REVISIT this assumes host and peripheral controllers
 	 * are registered, and that both are active...
 	 */
@@ -512,7 +514,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 		else
 			twl4030_phy_resume(twl);
 
-		blocking_notifier_call_chain(&twl->otg.notifier, status,
+		atomic_notifier_call_chain(&twl->otg.notifier, status,
 				twl->otg.gadget);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -534,7 +536,7 @@ static void twl4030_usb_phy_init(struct twl4030_usb *twl)
 			twl->asleep = 0;
 		}
 
-		blocking_notifier_call_chain(&twl->otg.notifier, status,
+		atomic_notifier_call_chain(&twl->otg.notifier, status,
 				twl->otg.gadget);
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -623,7 +625,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
 
 	/* Our job is to use irqs and status from the power module
 	 * to keep the transceiver disabled when nothing's connected.
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index 28f7701..8a91b4b 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -149,7 +149,6 @@ static int twl6030_set_phy_clk(struct otg_transceiver *x, int on)
 
 static int twl6030_phy_init(struct otg_transceiver *x)
 {
-	u8 hw_state;
 	struct twl6030_usb *twl;
 	struct device *dev;
 	struct twl4030_usb_data *pdata;
@@ -158,11 +157,7 @@ static int twl6030_phy_init(struct otg_transceiver *x)
 	dev  = twl->dev;
 	pdata = dev->platform_data;
 
-	regulator_enable(twl->usb3v3);
-
-	hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
-
-	if (hw_state & STS_USB_ID)
+	if (twl->linkstat == USB_EVENT_ID)
 		pdata->phy_power(twl->dev, 1, 1);
 	else
 		pdata->phy_power(twl->dev, 0, 1);
@@ -180,7 +175,17 @@ static void twl6030_phy_shutdown(struct otg_transceiver *x)
 	dev  = twl->dev;
 	pdata = dev->platform_data;
 	pdata->phy_power(twl->dev, 0, 0);
-	regulator_disable(twl->usb3v3);
+}
+
+static int twl6030_phy_suspend(struct otg_transceiver *x, int suspend)
+{
+	struct twl6030_usb *twl = xceiv_to_twl(x);
+	struct device *dev = twl->dev;
+	struct twl4030_usb_data *pdata = dev->platform_data;
+
+	pdata->phy_suspend(dev, suspend);
+
+	return 0;
 }
 
 static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
@@ -199,16 +204,6 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl)
 	if (IS_ERR(twl->usb3v3))
 		return -ENODEV;
 
-	regulator_enable(twl->usb3v3);
-
-	/* Program the VUSB_CFG_TRANS for ACTIVE state. */
-	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0x3F,
-						VUSB_CFG_TRANS);
-
-	/* Program the VUSB_CFG_STATE register to ON on all groups. */
-	twl6030_writeb(twl, TWL_MODULE_PM_RECEIVER, 0xE1,
-						VUSB_CFG_STATE);
-
 	/* Program the USB_VBUS_CTRL_SET and set VBUS_ACT_COMP bit */
 	twl6030_writeb(twl, TWL_MODULE_USB, 0x4, USB_VBUS_CTRL_SET);
 
@@ -261,16 +256,25 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
 						CONTROLLER_STAT1);
 	if (!(hw_state & STS_USB_ID)) {
 		if (vbus_state & VBUS_DET) {
+			regulator_enable(twl->usb3v3);
+			twl->asleep = 1;
 			status = USB_EVENT_VBUS;
 			twl->otg.default_a = false;
 			twl->otg.state = OTG_STATE_B_IDLE;
+			twl->linkstat = status;
+			twl->otg.last_event = status;
+			atomic_notifier_call_chain(&twl->otg.notifier,
+						status, twl->otg.gadget);
 		} else {
 			status = USB_EVENT_NONE;
-		}
-		if (status >= 0) {
 			twl->linkstat = status;
-			blocking_notifier_call_chain(&twl->otg.notifier,
+			twl->otg.last_event = status;
+			atomic_notifier_call_chain(&twl->otg.notifier,
 						status, twl->otg.gadget);
+			if (twl->asleep) {
+				regulator_disable(twl->usb3v3);
+				twl->asleep = 0;
+			}
 		}
 	}
 	sysfs_notify(&twl->dev->kobj, NULL, "vbus");
@@ -288,13 +292,17 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 
 	if (hw_state & STS_USB_ID) {
 
+		regulator_enable(twl->usb3v3);
+		twl->asleep = 1;
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR, 0x1);
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_SET,
 								0x10);
 		status = USB_EVENT_ID;
 		twl->otg.default_a = true;
 		twl->otg.state = OTG_STATE_A_IDLE;
-		blocking_notifier_call_chain(&twl->otg.notifier, status,
+		twl->linkstat = status;
+		twl->otg.last_event = status;
+		atomic_notifier_call_chain(&twl->otg.notifier, status,
 							twl->otg.gadget);
 	} else  {
 		twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_EN_HI_CLR,
@@ -303,7 +311,6 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
 								0x1);
 	}
 	twl6030_writeb(twl, TWL_MODULE_USB, USB_ID_INT_LATCH_CLR, status);
-	twl->linkstat = status;
 
 	return IRQ_HANDLED;
 }
@@ -395,6 +402,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	twl->otg.set_vbus	= twl6030_set_vbus;
 	twl->otg.init		= twl6030_phy_init;
 	twl->otg.shutdown	= twl6030_phy_shutdown;
+	twl->otg.set_suspend	= twl6030_phy_suspend;
 
 	/* init spinlock for workqueue */
 	spin_lock_init(&twl->lock);
@@ -411,7 +419,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 	if (device_create_file(&pdev->dev, &dev_attr_vbus))
 		dev_warn(&pdev->dev, "could not create sysfs file\n");
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
+	ATOMIC_INIT_NOTIFIER_HEAD(&twl->otg.notifier);
 
 	twl->irq_enabled = true;
 	status = request_threaded_irq(twl->irq1, NULL, twl6030_usbotg_irq,
@@ -437,7 +445,9 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
 		return status;
 	}
 
+	twl->asleep = 0;
 	pdata->phy_init(dev);
+	twl6030_phy_suspend(&twl->otg, 0);
 	twl6030_enable_irq(&twl->otg);
 	dev_info(&pdev->dev, "Initialized TWL6030 USB module\n");
 
diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c
new file mode 100644
index 0000000..e9a37f9
--- /dev/null
+++ b/drivers/usb/otg/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 otg_transceiver *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 otg_transceiver *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 otg_io_access_ops ulpi_viewport_access_ops = {
+	.read	= ulpi_viewport_read,
+	.write	= ulpi_viewport_write,
+};
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c
index 8f1d4fb..5cdb9d9 100644
--- a/drivers/usb/serial/ark3116.c
+++ b/drivers/usb/serial/ark3116.c
@@ -431,7 +431,7 @@ static int ark3116_get_icount(struct tty_struct *tty,
 	return 0;
 }
 
-static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
+static int ark3116_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -485,7 +485,7 @@ static int ark3116_ioctl(struct tty_struct *tty, struct file *file,
 	return -ENOIOCTLCMD;
 }
 
-static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
+static int ark3116_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ark3116_private *priv = usb_get_serial_port_data(port);
@@ -511,7 +511,7 @@ static int ark3116_tiocmget(struct tty_struct *tty, struct file *file)
 		(ctrl   & UART_MCR_OUT2 ? TIOCM_OUT2 : 0);
 }
 
-static int ark3116_tiocmset(struct tty_struct *tty, struct file *file,
+static int ark3116_tiocmset(struct tty_struct *tty,
 			unsigned set, unsigned clr)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 36df352..d6921fa 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -100,8 +100,8 @@ static void belkin_sa_process_read_urb(struct urb *urb);
 static void belkin_sa_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios * old);
 static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state);
-static int  belkin_sa_tiocmget(struct tty_struct *tty, struct file *file);
-static int  belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+static int  belkin_sa_tiocmget(struct tty_struct *tty);
+static int  belkin_sa_tiocmset(struct tty_struct *tty,
 					unsigned int set, unsigned int clear);
 
 
@@ -497,7 +497,7 @@ static void belkin_sa_break_ctl(struct tty_struct *tty, int break_state)
 		dev_err(&port->dev, "Set break_ctl %d\n", break_state);
 }
 
-static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
+static int belkin_sa_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct belkin_sa_private *priv = usb_get_serial_port_data(port);
@@ -513,7 +513,7 @@ static int belkin_sa_tiocmget(struct tty_struct *tty, struct file *file)
 	return control_state;
 }
 
-static int belkin_sa_tiocmset(struct tty_struct *tty, struct file *file,
+static int belkin_sa_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 7b8815d..6ae1c06 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -75,6 +75,7 @@ static int debug;
 static const struct usb_device_id id_table[] = {
 	{ USB_DEVICE(0x4348, 0x5523) },
 	{ USB_DEVICE(0x1a86, 0x7523) },
+	{ USB_DEVICE(0x1a86, 0x5523) },
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
@@ -431,7 +432,7 @@ out:
 	kfree(break_reg);
 }
 
-static int ch341_tiocmset(struct tty_struct *tty, struct file *file,
+static int ch341_tiocmset(struct tty_struct *tty,
 			  unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -552,8 +553,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	return 0;
 }
 
-/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/
-static int ch341_ioctl(struct tty_struct *tty, struct file *file,
+static int ch341_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -572,7 +572,7 @@ static int ch341_ioctl(struct tty_struct *tty, struct file *file,
 	return -ENOIOCTLCMD;
 }
 
-static int ch341_tiocmget(struct tty_struct *tty, struct file *file)
+static int ch341_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ch341_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 735ea03..4df3e0c 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -41,10 +41,9 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
 	unsigned int *cflagp, unsigned int *baudp);
 static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
 							struct ktermios*);
-static int cp210x_tiocmget(struct tty_struct *, struct file *);
-static int cp210x_tiocmset(struct tty_struct *, struct file *,
-		unsigned int, unsigned int);
-static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *,
+static int cp210x_tiocmget(struct tty_struct *);
+static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int);
+static int cp210x_tiocmset_port(struct usb_serial_port *port,
 		unsigned int, unsigned int);
 static void cp210x_break_ctl(struct tty_struct *, int);
 static int cp210x_startup(struct usb_serial *);
@@ -698,14 +697,14 @@ static void cp210x_set_termios(struct tty_struct *tty,
 
 }
 
-static int cp210x_tiocmset (struct tty_struct *tty, struct file *file,
+static int cp210x_tiocmset (struct tty_struct *tty,
 		unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
-	return cp210x_tiocmset_port(port, file, set, clear);
+	return cp210x_tiocmset_port(port, set, clear);
 }
 
-static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
+static int cp210x_tiocmset_port(struct usb_serial_port *port,
 		unsigned int set, unsigned int clear)
 {
 	unsigned int control = 0;
@@ -737,12 +736,12 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file,
 static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
 {
 	if (on)
-		cp210x_tiocmset_port(p, NULL,  TIOCM_DTR|TIOCM_RTS, 0);
+		cp210x_tiocmset_port(p, TIOCM_DTR|TIOCM_RTS, 0);
 	else
-		cp210x_tiocmset_port(p, NULL,  0, TIOCM_DTR|TIOCM_RTS);
+		cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
 }
 
-static int cp210x_tiocmget (struct tty_struct *tty, struct file *file)
+static int cp210x_tiocmget (struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	unsigned int control;
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 2edf238..987e9bf 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -169,12 +169,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, struct file *file,
+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, struct file *file);
-static int  cypress_tiocmset(struct tty_struct *tty, struct file *file,
+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_chars_in_buffer(struct tty_struct *tty);
 static void cypress_throttle(struct tty_struct *tty);
@@ -864,7 +864,7 @@ static int cypress_write_room(struct tty_struct *tty)
 }
 
 
-static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
+static int cypress_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct cypress_private *priv = usb_get_serial_port_data(port);
@@ -892,7 +892,7 @@ static int cypress_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 
-static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
+static int cypress_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -917,7 +917,7 @@ static int cypress_tiocmset(struct tty_struct *tty, struct file *file,
 }
 
 
-static int cypress_ioctl(struct tty_struct *tty, struct file *file,
+static int cypress_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 666e5a6..86fbba6 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -445,11 +445,11 @@ static void digi_rx_unthrottle(struct tty_struct *tty);
 static void digi_set_termios(struct tty_struct *tty,
 		struct usb_serial_port *port, struct ktermios *old_termios);
 static void digi_break_ctl(struct tty_struct *tty, int break_state);
-static int digi_tiocmget(struct tty_struct *tty, struct file *file);
-static int digi_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear);
+static int digi_tiocmget(struct tty_struct *tty);
+static int digi_tiocmset(struct tty_struct *tty, unsigned int set,
+		unsigned int clear);
 static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,
-	const unsigned char *buf, int count);
+		const unsigned char *buf, int count);
 static void digi_write_bulk_callback(struct urb *urb);
 static int digi_write_room(struct tty_struct *tty);
 static int digi_chars_in_buffer(struct tty_struct *tty);
@@ -1118,7 +1118,7 @@ static void digi_break_ctl(struct tty_struct *tty, int break_state)
 }
 
 
-static int digi_tiocmget(struct tty_struct *tty, struct file *file)
+static int digi_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
@@ -1134,8 +1134,8 @@ static int digi_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 
-static int digi_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear)
+static int digi_tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct digi_port *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index f349a36..65967b3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -722,6 +722,8 @@ static struct usb_device_id id_table_combined [] = {
 	{ USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) },
 	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+	{ USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID),
+		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID),
@@ -864,10 +866,10 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
 						void *dest, size_t size);
 static void ftdi_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
-static int  ftdi_tiocmget(struct tty_struct *tty, struct file *file);
-static int  ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+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_ioctl(struct tty_struct *tty, struct file *file,
+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);
 
@@ -973,7 +975,7 @@ static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base)
 	int divisor3;
 
 	/* hi-speed baud rate is 10-bit sampling instead of 16-bit */
-	divisor3 = (base / 10 / baud) * 8;
+	divisor3 = base * 8 / (baud * 10);
 
 	divisor = divisor3 >> 3;
 	divisor |= (__u32)divfrac[divisor3 & 0x7] << 14;
@@ -2176,7 +2178,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
 	}
 }
 
-static int ftdi_tiocmget(struct tty_struct *tty, struct file *file)
+static int ftdi_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -2229,7 +2231,7 @@ out:
 	return ret;
 }
 
-static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
+static int ftdi_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -2237,7 +2239,7 @@ static int ftdi_tiocmset(struct tty_struct *tty, struct file *file,
 	return update_mctrl(port, set, clear);
 }
 
-static int ftdi_ioctl(struct tty_struct *tty, struct file *file,
+static int ftdi_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 117e8e6..c543e55 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -730,6 +730,7 @@
 /* Olimex */
 #define OLIMEX_VID			0x15BA
 #define OLIMEX_ARM_USB_OCD_PID		0x0003
+#define OLIMEX_ARM_USB_OCD_H_PID	0x002b
 
 /*
  * Telldus Technologies
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 3b246d9..f1aedfa 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -216,11 +216,11 @@ static void edge_unthrottle(struct tty_struct *tty);
 static void edge_set_termios(struct tty_struct *tty,
 					struct usb_serial_port *port,
 					struct ktermios *old_termios);
-static int  edge_ioctl(struct tty_struct *tty, struct file *file,
+static int  edge_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg);
 static void edge_break(struct tty_struct *tty, int break_state);
-static int  edge_tiocmget(struct tty_struct *tty, struct file *file);
-static int  edge_tiocmset(struct tty_struct *tty, struct file *file,
+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);
@@ -1568,7 +1568,7 @@ static int get_lsr_info(struct edgeport_port *edge_port,
 	return 0;
 }
 
-static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+static int edge_tiocmset(struct tty_struct *tty,
 					unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -1599,7 +1599,7 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file,
 	return 0;
 }
 
-static int edge_tiocmget(struct tty_struct *tty, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
@@ -1679,7 +1679,7 @@ static int get_serial_info(struct edgeport_port *edge_port,
  * SerialIoctl
  *	this function handles any ioctl calls to the driver
  *****************************************************************************/
-static int edge_ioctl(struct tty_struct *tty, struct file *file,
+static int edge_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -2343,7 +2343,6 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
 				usb_get_serial_data(edge_port->port->serial);
 	int status = 0;
 	struct urb *urb;
-	int timeout;
 
 	usb_serial_debug_data(debug, &edge_port->port->dev,
 						__func__, length, buffer);
@@ -2376,8 +2375,6 @@ static int write_cmd_usb(struct edgeport_port *edge_port,
 		return status;
 	}
 
-	/* wait for command to finish */
-	timeout = COMMAND_TIMEOUT;
 #if 0
 	wait_event(&edge_port->wait_command, !edge_port->commandPending);
 
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 22506b0..d843491 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2444,7 +2444,7 @@ static void edge_set_termios(struct tty_struct *tty,
 	change_port_settings(tty, edge_port, old_termios);
 }
 
-static int edge_tiocmset(struct tty_struct *tty, struct file *file,
+static int edge_tiocmset(struct tty_struct *tty,
 					unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -2477,7 +2477,7 @@ static int edge_tiocmset(struct tty_struct *tty, struct file *file,
 	return 0;
 }
 
-static int edge_tiocmget(struct tty_struct *tty, struct file *file)
+static int edge_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
@@ -2552,7 +2552,7 @@ static int get_serial_info(struct edgeport_port *edge_port,
 	return 0;
 }
 
-static int edge_ioctl(struct tty_struct *tty, struct file *file,
+static int edge_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 99b97c0..6aca631 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -150,7 +150,7 @@ static void iuu_release(struct usb_serial *serial)
 	}
 }
 
-static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
+static int iuu_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -179,7 +179,7 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file,
  * When no card , the reader respond with TIOCM_CD
  * This is known as CD autodetect mechanism
  */
-static int iuu_tiocmget(struct tty_struct *tty, struct file *file)
+static int iuu_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct iuu_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 0791778..a442352 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -301,7 +301,7 @@ static void keyspan_set_termios(struct tty_struct *tty,
 	keyspan_send_setup(port, 0);
 }
 
-static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
+static int keyspan_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
@@ -317,7 +317,7 @@ static int keyspan_tiocmget(struct tty_struct *tty, struct file *file)
 	return value;
 }
 
-static int keyspan_tiocmset(struct tty_struct *tty, struct file *file,
+static int keyspan_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -2121,16 +2121,16 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
 	/* Work out which port within the device is being setup */
 	device_port = port->number - port->serial->minor;
 
-	dbg("%s - endpoint %d port %d (%d)",
-			__func__, usb_pipeendpoint(this_urb->pipe),
-			port->number, device_port);
-
-		/* Make sure we have an urb then send the message */
+	/* Make sure we have an urb then send the message */
 	if (this_urb == NULL) {
 		dbg("%s - oops no urb for port %d.", __func__, port->number);
 		return -1;
 	}
 
+	dbg("%s - endpoint %d port %d (%d)",
+			__func__, usb_pipeendpoint(this_urb->pipe),
+			port->number, device_port);
+
 	/* Save reset port val for resend.
 	   Don't overwrite resend for open/close condition. */
 	if ((reset_port + 1) > p_priv->resend_cont)
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h
index ce134dc..13fa1d1 100644
--- a/drivers/usb/serial/keyspan.h
+++ b/drivers/usb/serial/keyspan.h
@@ -58,10 +58,9 @@ static void keyspan_set_termios		(struct tty_struct *tty,
 					 struct ktermios *old);
 static void keyspan_break_ctl		(struct tty_struct *tty,
 					 int break_state);
-static int  keyspan_tiocmget		(struct tty_struct *tty,
-					 struct file *file);
+static int  keyspan_tiocmget		(struct tty_struct *tty);
 static int  keyspan_tiocmset		(struct tty_struct *tty,
-					 struct file *file, unsigned int set,
+					 unsigned int set,
 					 unsigned int clear);
 static int  keyspan_fake_startup	(struct usb_serial *serial);
 
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 554a869..d5c0c6a 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -173,7 +173,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work)
 		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);
-	tty_wakeup(tty);
+	if (tty)
+		tty_wakeup(tty);
 	tty_kref_put(tty);
 }
 
@@ -206,7 +207,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work)
 static void keyspan_pda_rx_interrupt(struct urb *urb)
 {
 	struct usb_serial_port *port = urb->context;
-	struct tty_struct *tty = tty_port_tty_get(&port->port);
+	struct tty_struct *tty;
 	unsigned char *data = urb->transfer_buffer;
 	int retval;
 	int status = urb->status;
@@ -223,7 +224,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
 		/* this urb is terminated, clean up */
 		dbg("%s - urb shutting down with status: %d",
 		    __func__, status);
-		goto out;
+		return;
 	default:
 		dbg("%s - nonzero urb status received: %d",
 		    __func__, status);
@@ -233,12 +234,14 @@ static void keyspan_pda_rx_interrupt(struct urb *urb)
 	/* see if the message is data or a status interrupt */
 	switch (data[0]) {
 	case 0:
-		/* rest of message is rx data */
-		if (urb->actual_length) {
+		tty = tty_port_tty_get(&port->port);
+		 /* rest of message is rx data */
+		if (tty && urb->actual_length) {
 			tty_insert_flip_string(tty, data + 1,
 						urb->actual_length - 1);
 			tty_flip_buffer_push(tty);
 		}
+		tty_kref_put(tty);
 		break;
 	case 1:
 		/* status interrupt */
@@ -265,8 +268,6 @@ exit:
 		dev_err(&port->dev,
 			"%s - usb_submit_urb failed with result %d",
 			__func__, retval);
-out:
-	tty_kref_put(tty);		     
 }
 
 
@@ -457,7 +458,7 @@ static int keyspan_pda_set_modem_info(struct usb_serial *serial,
 	return rc;
 }
 
-static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
+static int keyspan_pda_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct usb_serial *serial = port->serial;
@@ -478,7 +479,7 @@ static int keyspan_pda_tiocmget(struct tty_struct *tty, struct file *file)
 	return value;
 }
 
-static int keyspan_pda_tiocmset(struct tty_struct *tty, struct file *file,
+static int keyspan_pda_tiocmset(struct tty_struct *tty,
 				unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index e8a65ce..19373cb 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -68,8 +68,8 @@ static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void klsi_105_close(struct usb_serial_port *port);
 static void klsi_105_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
-static int  klsi_105_tiocmget(struct tty_struct *tty, struct file *file);
-static int  klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+static int  klsi_105_tiocmget(struct tty_struct *tty);
+static int  klsi_105_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
 static void klsi_105_process_read_urb(struct urb *urb);
 static int klsi_105_prepare_write_buffer(struct usb_serial_port *port,
@@ -637,7 +637,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
 }
 #endif
 
-static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
+static int klsi_105_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct klsi_105_private *priv = usb_get_serial_port_data(port);
@@ -661,7 +661,7 @@ static int klsi_105_tiocmget(struct tty_struct *tty, struct file *file)
 	return (int)line_state;
 }
 
-static int klsi_105_tiocmset(struct tty_struct *tty, struct file *file,
+static int klsi_105_tiocmset(struct tty_struct *tty,
 			     unsigned int set, unsigned int clear)
 {
 	int retval = -EINVAL;
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index bd5bd85..ddd1463 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -75,10 +75,10 @@ static void kobil_close(struct usb_serial_port *port);
 static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
 			 const unsigned char *buf, int count);
 static int  kobil_write_room(struct tty_struct *tty);
-static int  kobil_ioctl(struct tty_struct *tty, struct file *file,
+static int  kobil_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg);
-static int  kobil_tiocmget(struct tty_struct *tty, struct file *file);
-static int  kobil_tiocmset(struct tty_struct *tty, struct file *file,
+static int  kobil_tiocmget(struct tty_struct *tty);
+static int  kobil_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear);
 static void kobil_read_int_callback(struct urb *urb);
 static void kobil_write_callback(struct urb *purb);
@@ -372,7 +372,7 @@ static void kobil_read_int_callback(struct urb *urb)
 	}
 
 	tty = tty_port_tty_get(&port->port);
-	if (urb->actual_length) {
+	if (tty && urb->actual_length) {
 
 		/* BEGIN DEBUG */
 		/*
@@ -504,7 +504,7 @@ static int kobil_write_room(struct tty_struct *tty)
 }
 
 
-static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
+static int kobil_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct kobil_private *priv;
@@ -544,7 +544,7 @@ static int kobil_tiocmget(struct tty_struct *tty, struct file *file)
 	return result;
 }
 
-static int kobil_tiocmset(struct tty_struct *tty, struct file *file,
+static int kobil_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -668,7 +668,7 @@ static void kobil_set_termios(struct tty_struct *tty,
 		);
 }
 
-static int kobil_ioctl(struct tty_struct *tty, struct file *file,
+static int kobil_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 2849f8c..d2c0196 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -78,6 +78,8 @@
 #include <asm/unaligned.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial.h>
+#include <linux/ioctl.h>
 #include "mct_u232.h"
 
 /*
@@ -101,9 +103,13 @@ static void mct_u232_read_int_callback(struct urb *urb);
 static void mct_u232_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
 static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
-static int  mct_u232_tiocmget(struct tty_struct *tty, struct file *file);
-static int  mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+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, struct file *file,
+			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);
 
@@ -150,9 +156,10 @@ static struct usb_serial_driver mct_u232_device = {
 	.tiocmset =	     mct_u232_tiocmset,
 	.attach =	     mct_u232_startup,
 	.release =	     mct_u232_release,
+	.ioctl =             mct_u232_ioctl,
+	.get_icount =        mct_u232_get_icount,
 };
 
-
 struct mct_u232_private {
 	spinlock_t lock;
 	unsigned int	     control_state; /* Modem Line Setting (TIOCM) */
@@ -160,6 +167,9 @@ 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;
+	wait_queue_head_t    msr_wait;	/* for handling sleeping while waiting
+						for msr change to happen */
 };
 
 #define THROTTLED		0x01
@@ -386,6 +396,20 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial,
 	return rc;
 } /* mct_u232_get_modem_stat */
 
+static void mct_u232_msr_to_icount(struct async_icount *icount,
+						unsigned char msr)
+{
+	/* Translate Control Line states */
+	if (msr & MCT_U232_MSR_DDSR)
+		icount->dsr++;
+	if (msr & MCT_U232_MSR_DCTS)
+		icount->cts++;
+	if (msr & MCT_U232_MSR_DRI)
+		icount->rng++;
+	if (msr & MCT_U232_MSR_DCD)
+		icount->dcd++;
+} /* mct_u232_msr_to_icount */
+
 static void mct_u232_msr_to_state(unsigned int *control_state,
 						unsigned char msr)
 {
@@ -422,6 +446,7 @@ static int mct_u232_startup(struct usb_serial *serial)
 	if (!priv)
 		return -ENOMEM;
 	spin_lock_init(&priv->lock);
+	init_waitqueue_head(&priv->msr_wait);
 	usb_set_serial_port_data(serial->port[0], priv);
 
 	init_waitqueue_head(&serial->port[0]->write_wait);
@@ -621,6 +646,8 @@ static void mct_u232_read_int_callback(struct urb *urb)
 	/* Record Control Line states */
 	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);
 
+	mct_u232_msr_to_icount(&priv->icount, priv->last_msr);
+
 #if 0
 	/* Not yet handled. See belkin_sa.c for further information */
 	/* Now to report any errors */
@@ -647,6 +674,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
 		tty_kref_put(tty);
 	}
 #endif
+	wake_up_interruptible(&priv->msr_wait);
 	spin_unlock_irqrestore(&priv->lock, flags);
 exit:
 	retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -762,7 +790,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state)
 } /* mct_u232_break_ctl */
 
 
-static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
+static int mct_u232_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct mct_u232_private *priv = usb_get_serial_port_data(port);
@@ -778,7 +806,7 @@ static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file)
 	return control_state;
 }
 
-static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file,
+static int mct_u232_tiocmset(struct tty_struct *tty,
 			      unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -826,7 +854,6 @@ static void mct_u232_throttle(struct tty_struct *tty)
 	}
 }
 
-
 static void mct_u232_unthrottle(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -847,6 +874,82 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
 	}
 }
 
+static int  mct_u232_ioctl(struct tty_struct *tty, struct file *file,
+			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;
+
+	dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd);
+
+	switch (cmd) {
+
+	case TIOCMIWAIT:
+
+		dbg("%s (%d) TIOCMIWAIT", __func__,  port->number);
+
+		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(&mct_u232_port->msr_wait,
+					&wait, TASK_INTERRUPTIBLE);
+			schedule();
+			finish_wait(&mct_u232_port->msr_wait, &wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			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);
+
+	dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d",
+		__func__,  port->number, icount->rx, icount->tx);
+	return 0;
+}
+
 static int __init mct_u232_init(void)
 {
 	int retval;
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 7d3bc9a..40abedb 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -1833,7 +1833,7 @@ static int get_lsr_info(struct tty_struct *tty,
 	return 0;
 }
 
-static int mos7720_tiocmget(struct tty_struct *tty, struct file *file)
+static int mos7720_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
@@ -1858,14 +1858,14 @@ static int mos7720_tiocmget(struct tty_struct *tty, struct file *file)
 	return result;
 }
 
-static int mos7720_tiocmset(struct tty_struct *tty, struct file *file,
+static int mos7720_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7720_port = usb_get_serial_port_data(port);
 	unsigned int mcr ;
 	dbg("%s - port %d", __func__, port->number);
-	dbg("he was at tiocmget");
+	dbg("he was at tiocmset");
 
 	mcr = mos7720_port->shadowMCR;
 
@@ -1987,7 +1987,7 @@ static int get_serial_info(struct moschip_port *mos7720_port,
 	return 0;
 }
 
-static int mos7720_ioctl(struct tty_struct *tty, struct file *file,
+static int mos7720_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -2052,7 +2052,7 @@ static int mos7720_startup(struct usb_serial *serial)
 	struct usb_device *dev;
 	int i;
 	char data;
-	u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
+	u16 product;
 	int ret_val;
 
 	dbg("%s: Entering ..........", __func__);
@@ -2062,6 +2062,7 @@ static int mos7720_startup(struct usb_serial *serial)
 		return -ENODEV;
 	}
 
+	product = le16_to_cpu(serial->dev->descriptor.idProduct);
 	dev = serial->dev;
 
 	/*
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 5627993..7b50aa1 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -1644,7 +1644,7 @@ static void mos7840_unthrottle(struct tty_struct *tty)
 	}
 }
 
-static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
+static int mos7840_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct moschip_port *mos7840_port;
@@ -1674,7 +1674,7 @@ static int mos7840_tiocmget(struct tty_struct *tty, struct file *file)
 	return result;
 }
 
-static int mos7840_tiocmset(struct tty_struct *tty, struct file *file,
+static int mos7840_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -2235,7 +2235,7 @@ static int mos7840_get_icount(struct tty_struct *tty,
  *	this function handles any ioctl calls to the driver
  *****************************************************************************/
 
-static int mos7840_ioctl(struct tty_struct *tty, struct file *file,
+static int mos7840_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c
index eda1f92..201f609 100644
--- a/drivers/usb/serial/opticon.c
+++ b/drivers/usb/serial/opticon.c
@@ -1,6 +1,7 @@
 /*
  * Opticon USB barcode to serial driver
  *
+ * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com>
  * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de>
  * Copyright (C) 2008 - 2009 Novell Inc.
  *
@@ -21,6 +22,16 @@
 #include <linux/usb/serial.h>
 #include <linux/uaccess.h>
 
+#define CONTROL_RTS			0x02
+#define RESEND_CTS_STATE	0x03
+
+/* max number of write urbs in flight */
+#define URB_UPPER_LIMIT	8
+
+/* This driver works for the Opticon 1D barcode reader
+ * an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */
+#define DRIVER_DESC	"Opticon USB barcode to serial driver (1D)"
+
 static int debug;
 
 static const struct usb_device_id id_table[] = {
@@ -42,13 +53,13 @@ struct opticon_private {
 	bool throttled;
 	bool actually_throttled;
 	bool rts;
+	bool cts;
 	int outstanding_urbs;
 };
 
-/* max number of write urbs in flight */
-#define URB_UPPER_LIMIT	4
 
-static void opticon_bulk_callback(struct urb *urb)
+
+static void opticon_read_bulk_callback(struct urb *urb)
 {
 	struct opticon_private *priv = urb->context;
 	unsigned char *data = urb->transfer_buffer;
@@ -57,6 +68,7 @@ static void opticon_bulk_callback(struct urb *urb)
 	struct tty_struct *tty;
 	int result;
 	int data_length;
+	unsigned long flags;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -87,10 +99,10 @@ static void opticon_bulk_callback(struct urb *urb)
 		 * Data from the device comes with a 2 byte header:
 		 *
 		 * <0x00><0x00>data...
-		 * 	This is real data to be sent to the tty layer
+		 *	This is real data to be sent to the tty layer
 		 * <0x00><0x01)level
-		 * 	This is a RTS level change, the third byte is the RTS
-		 * 	value (0 for low, 1 for high).
+		 *	This is a CTS level change, the third byte is the CTS
+		 *	value (0 for low, 1 for high).
 		 */
 		if ((data[0] == 0x00) && (data[1] == 0x00)) {
 			/* real data, send it to the tty layer */
@@ -103,10 +115,13 @@ static void opticon_bulk_callback(struct urb *urb)
 			}
 		} else {
 			if ((data[0] == 0x00) && (data[1] == 0x01)) {
+				spin_lock_irqsave(&priv->lock, flags);
+				/* CTS status infomation package */
 				if (data[2] == 0x00)
-					priv->rts = false;
+					priv->cts = false;
 				else
-					priv->rts = true;
+					priv->cts = true;
+				spin_unlock_irqrestore(&priv->lock, flags);
 			} else {
 				dev_dbg(&priv->udev->dev,
 					"Unknown data packet received from the device:"
@@ -129,7 +144,7 @@ exit:
 				  usb_rcvbulkpipe(priv->udev,
 						  priv->bulk_address),
 				  priv->bulk_in_buffer, priv->buffer_size,
-				  opticon_bulk_callback, priv);
+				  opticon_read_bulk_callback, priv);
 		result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC);
 		if (result)
 			dev_err(&port->dev,
@@ -140,6 +155,24 @@ exit:
 	spin_unlock(&priv->lock);
 }
 
+static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
+				u8 val)
+{
+	struct usb_serial *serial = port->serial;
+	int retval;
+	u8 buffer[2];
+
+	buffer[0] = val;
+	/* Send the message to the vendor control endpoint
+	 * of the connected device */
+	retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+				requesttype,
+				USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+				0, 0, buffer, 1, 0);
+
+	return retval;
+}
+
 static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
 	struct opticon_private *priv = usb_get_serial_data(port->serial);
@@ -152,19 +185,30 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
 	priv->throttled = false;
 	priv->actually_throttled = false;
 	priv->port = port;
+	priv->rts = false;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	/* Start reading from the device */
+	/* Clear RTS line */
+	send_control_msg(port, CONTROL_RTS, 0);
+
+	/* Setup the read URB and start reading from the device */
 	usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
 			  usb_rcvbulkpipe(priv->udev,
 					  priv->bulk_address),
 			  priv->bulk_in_buffer, priv->buffer_size,
-			  opticon_bulk_callback, priv);
+			  opticon_read_bulk_callback, priv);
+
+	/* clear the halt status of the enpoint */
+	usb_clear_halt(priv->udev, priv->bulk_read_urb->pipe);
+
 	result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL);
 	if (result)
 		dev_err(&port->dev,
 			"%s - failed resubmitting read urb, error %d\n",
 			__func__, result);
+	/* Request CTS line state, sometimes during opening the current
+	 * CTS state can be missed. */
+	send_control_msg(port, RESEND_CTS_STATE, 1);
 	return result;
 }
 
@@ -178,7 +222,7 @@ static void opticon_close(struct usb_serial_port *port)
 	usb_kill_urb(priv->bulk_read_urb);
 }
 
-static void opticon_write_bulk_callback(struct urb *urb)
+static void opticon_write_control_callback(struct urb *urb)
 {
 	struct opticon_private *priv = urb->context;
 	int status = urb->status;
@@ -210,6 +254,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 	unsigned char *buffer;
 	unsigned long flags;
 	int status;
+	struct usb_ctrlrequest *dr;
 
 	dbg("%s - port %d", __func__, port->number);
 
@@ -226,6 +271,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 	if (!buffer) {
 		dev_err(&port->dev, "out of memory\n");
 		count = -ENOMEM;
+
 		goto error_no_buffer;
 	}
 
@@ -240,35 +286,28 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 
 	usb_serial_debug_data(debug, &port->dev, __func__, count, buffer);
 
-	if (port->bulk_out_endpointAddress) {
-		usb_fill_bulk_urb(urb, serial->dev,
-				  usb_sndbulkpipe(serial->dev,
-						  port->bulk_out_endpointAddress),
-				  buffer, count, opticon_write_bulk_callback, priv);
-	} else {
-		struct usb_ctrlrequest *dr;
-
-		dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
-		if (!dr)
-			return -ENOMEM;
-
-		dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
-		dr->bRequest = 0x01;
-		dr->wValue = 0;
-		dr->wIndex = 0;
-		dr->wLength = cpu_to_le16(count);
-
-		usb_fill_control_urb(urb, serial->dev,
-			usb_sndctrlpipe(serial->dev, 0),
-			(unsigned char *)dr, buffer, count,
-			opticon_write_bulk_callback, priv);
-	}
+	/* The conncected devices do not have a bulk write endpoint,
+	 * to transmit data to de barcode device the control endpoint is used */
+	dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO);
+	if (!dr)
+		return -ENOMEM;
+
+	dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
+	dr->bRequest = 0x01;
+	dr->wValue = 0;
+	dr->wIndex = 0;
+	dr->wLength = cpu_to_le16(count);
+
+	usb_fill_control_urb(urb, serial->dev,
+		usb_sndctrlpipe(serial->dev, 0),
+		(unsigned char *)dr, buffer, count,
+		opticon_write_control_callback, priv);
 
 	/* send it down the pipe */
 	status = usb_submit_urb(urb, GFP_ATOMIC);
 	if (status) {
 		dev_err(&port->dev,
-		   "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+		"%s - usb_submit_urb(write endpoint) failed status = %d\n",
 							__func__, status);
 		count = status;
 		goto error;
@@ -352,7 +391,7 @@ static void opticon_unthrottle(struct tty_struct *tty)
 	}
 }
 
-static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
+static int opticon_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct opticon_private *priv = usb_get_serial_data(port->serial);
@@ -360,16 +399,49 @@ static int opticon_tiocmget(struct tty_struct *tty, struct file *file)
 	int result = 0;
 
 	dbg("%s - port %d", __func__, port->number);
+	if (!usb_get_intfdata(port->serial->interface))
+		return -ENODEV;
 
 	spin_lock_irqsave(&priv->lock, flags);
 	if (priv->rts)
-		result = TIOCM_RTS;
+		result |= TIOCM_RTS;
+	if (priv->cts)
+		result |= TIOCM_CTS;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	dbg("%s - %x", __func__, result);
 	return result;
 }
 
+static int opticon_tiocmset(struct tty_struct *tty, struct file *file,
+			   unsigned int set, unsigned int clear)
+{
+	struct usb_serial_port *port = tty->driver_data;
+	struct opticon_private *priv = usb_get_serial_data(port->serial);
+	unsigned long flags;
+	bool rts;
+	bool changed = false;
+
+	if (!usb_get_intfdata(port->serial->interface))
+		return -ENODEV;
+	/* We only support RTS so we only handle that */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rts = priv->rts;
+	if (set & TIOCM_RTS)
+		priv->rts = true;
+	if (clear & TIOCM_RTS)
+		priv->rts = false;
+	changed = rts ^ priv->rts;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!changed)
+		return 0;
+
+	/* Send the new RTS state to the connected device */
+	return send_control_msg(port, CONTROL_RTS, !rts);
+}
+
 static int get_serial_info(struct opticon_private *priv,
 			   struct serial_struct __user *serial)
 {
@@ -396,7 +468,7 @@ static int get_serial_info(struct opticon_private *priv,
 	return 0;
 }
 
-static int opticon_ioctl(struct tty_struct *tty, struct file *file,
+static int opticon_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -431,6 +503,7 @@ static int opticon_startup(struct usb_serial *serial)
 	priv->serial = serial;
 	priv->port = serial->port[0];
 	priv->udev = serial->dev;
+	priv->outstanding_urbs = 0;	/* Init the outstanding urbs */
 
 	/* find our bulk endpoint */
 	intf = serial->interface->altsetting;
@@ -456,13 +529,6 @@ static int opticon_startup(struct usb_serial *serial)
 
 		priv->bulk_address = endpoint->bEndpointAddress;
 
-		/* set up our bulk urb */
-		usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev,
-				  usb_rcvbulkpipe(priv->udev,
-						  endpoint->bEndpointAddress),
-				  priv->bulk_in_buffer, priv->buffer_size,
-				  opticon_bulk_callback, priv);
-
 		bulk_in_found = true;
 		break;
 		}
@@ -558,6 +624,7 @@ static struct usb_serial_driver opticon_device = {
 	.unthrottle =		opticon_unthrottle,
 	.ioctl =		opticon_ioctl,
 	.tiocmget =		opticon_tiocmget,
+	.tiocmset =		opticon_tiocmset,
 };
 
 static int __init opticon_init(void)
@@ -581,6 +648,7 @@ static void __exit opticon_exit(void)
 
 module_init(opticon_init);
 module_exit(opticon_exit);
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 module_param(debug, bool, S_IRUGO | S_IWUSR);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5f46838..75c7f45 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -652,7 +652,8 @@ static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff,
+	  0xff, 0xff), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) },
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c
index 7361320..4c29e6c 100644
--- a/drivers/usb/serial/oti6858.c
+++ b/drivers/usb/serial/oti6858.c
@@ -135,7 +135,7 @@ 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, struct file *file,
+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);
@@ -144,8 +144,8 @@ static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
 			const unsigned char *buf, int count);
 static int oti6858_write_room(struct tty_struct *tty);
 static int oti6858_chars_in_buffer(struct tty_struct *tty);
-static int oti6858_tiocmget(struct tty_struct *tty, struct file *file);
-static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
+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_startup(struct usb_serial *serial);
 static void oti6858_release(struct usb_serial *serial);
@@ -624,7 +624,7 @@ static void oti6858_close(struct usb_serial_port *port)
 	usb_kill_urb(port->interrupt_in_urb);
 }
 
-static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
+static int oti6858_tiocmset(struct tty_struct *tty,
 				unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -657,7 +657,7 @@ static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
 	return 0;
 }
 
-static int oti6858_tiocmget(struct tty_struct *tty, struct file *file)
+static int oti6858_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct oti6858_private *priv = usb_get_serial_port_data(port);
@@ -728,7 +728,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	return 0;
 }
 
-static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
+static int oti6858_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 08c9181..30461fc 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -505,7 +505,7 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 	return 0;
 }
 
-static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
+static int pl2303_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -531,7 +531,7 @@ static int pl2303_tiocmset(struct tty_struct *tty, struct file *file,
 	return set_control_lines(port->serial->dev, control);
 }
 
-static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
+static int pl2303_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -606,7 +606,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 	return 0;
 }
 
-static int pl2303_ioctl(struct tty_struct *tty, struct file *file,
+static int pl2303_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	struct serial_struct ser;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 0457813..d5d136a 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -376,7 +376,10 @@ static int sierra_send_setup(struct usb_serial_port *port)
 	if (!do_send)
 		return 0;
 
-	usb_autopm_get_interface(serial->interface);
+	retval = usb_autopm_get_interface(serial->interface);
+	if (retval < 0)
+		return retval;
+
 	retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 		0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
 	usb_autopm_put_interface(serial->interface);
@@ -392,7 +395,7 @@ static void sierra_set_termios(struct tty_struct *tty,
 	sierra_send_setup(port);
 }
 
-static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
+static int sierra_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	unsigned int value;
@@ -411,7 +414,7 @@ static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
 	return value;
 }
 
-static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
+static int sierra_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -811,8 +814,12 @@ static void sierra_close(struct usb_serial_port *port)
 		mutex_lock(&serial->disc_mutex);
 		if (!serial->disconnected) {
 			serial->interface->needs_remote_wakeup = 0;
-			usb_autopm_get_interface(serial->interface);
-			sierra_send_setup(port);
+			/* 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);
@@ -865,7 +872,8 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
 		/* get rid of everything as in close */
 		sierra_close(port);
 		/* restore balance for autopm */
-		usb_autopm_put_interface(serial->interface);
+		if (!serial->disconnected)
+			usb_autopm_put_interface(serial->interface);
 		return err;
 	}
 	sierra_send_setup(port);
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index cbfb70b..180ea6c 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -576,7 +576,7 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
 	return 0;
 }
 
-static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
+static int spcp8x5_ioctl(struct tty_struct *tty,
 			 unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -595,7 +595,7 @@ static int spcp8x5_ioctl(struct tty_struct *tty, struct file *file,
 	return -ENOIOCTLCMD;
 }
 
-static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
+static int spcp8x5_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -618,7 +618,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty, struct file *file,
 	return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
 }
 
-static int spcp8x5_tiocmget(struct tty_struct *tty, struct file *file)
+static int spcp8x5_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct spcp8x5_private *priv = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 8359ec7..87362e4 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -439,7 +439,7 @@ static int ssu100_get_icount(struct tty_struct *tty,
 
 
 
-static int ssu100_ioctl(struct tty_struct *tty, struct file *file,
+static int ssu100_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -484,7 +484,7 @@ static int ssu100_attach(struct usb_serial *serial)
 	return ssu100_initdevice(serial->dev);
 }
 
-static int ssu100_tiocmget(struct tty_struct *tty, struct file *file)
+static int ssu100_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct usb_device *dev = port->serial->dev;
@@ -517,7 +517,7 @@ mget_out:
 	return r;
 }
 
-static int ssu100_tiocmset(struct tty_struct *tty, struct file *file,
+static int ssu100_tiocmset(struct tty_struct *tty,
 			   unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index a910004..c6d92a5 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -106,14 +106,14 @@ static int ti_write_room(struct tty_struct *tty);
 static int ti_chars_in_buffer(struct tty_struct *tty);
 static void ti_throttle(struct tty_struct *tty);
 static void ti_unthrottle(struct tty_struct *tty);
-static int ti_ioctl(struct tty_struct *tty, struct file *file,
+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, struct file *file);
-static int ti_tiocmset(struct tty_struct *tty, struct file *file,
+static int ti_tiocmget(struct tty_struct *tty);
+static int ti_tiocmset(struct tty_struct *tty,
 		unsigned int set, unsigned int clear);
 static void ti_break(struct tty_struct *tty, int break_state);
 static void ti_interrupt_callback(struct urb *urb);
@@ -818,7 +818,7 @@ static int ti_get_icount(struct tty_struct *tty,
 	return 0;
 }
 
-static int ti_ioctl(struct tty_struct *tty, struct file *file,
+static int ti_ioctl(struct tty_struct *tty,
 	unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -1000,7 +1000,7 @@ static void ti_set_termios(struct tty_struct *tty,
 }
 
 
-static int ti_tiocmget(struct tty_struct *tty, struct file *file)
+static int ti_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
@@ -1033,8 +1033,8 @@ static int ti_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 
-static int ti_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear)
+static int ti_tiocmset(struct tty_struct *tty,
+				unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct ti_port *tport = usb_get_serial_port_data(port);
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 546a521..1c03130 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -406,7 +406,7 @@ static void serial_unthrottle(struct tty_struct *tty)
 		port->serial->type->unthrottle(tty);
 }
 
-static int serial_ioctl(struct tty_struct *tty, struct file *file,
+static int serial_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -417,7 +417,7 @@ static int serial_ioctl(struct tty_struct *tty, struct file *file,
 	/* 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, file, cmd, arg);
+		retval = port->serial->type->ioctl(tty, cmd, arg);
 	} else
 		retval = -ENOIOCTLCMD;
 	return retval;
@@ -496,18 +496,18 @@ static const struct file_operations serial_proc_fops = {
 	.release	= single_release,
 };
 
-static int serial_tiocmget(struct tty_struct *tty, struct file *file)
+static int serial_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 
 	dbg("%s - port %d", __func__, port->number);
 
 	if (port->serial->type->tiocmget)
-		return port->serial->type->tiocmget(tty, file);
+		return port->serial->type->tiocmget(tty);
 	return -EINVAL;
 }
 
-static int serial_tiocmset(struct tty_struct *tty, struct file *file,
+static int serial_tiocmset(struct tty_struct *tty,
 			    unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -515,7 +515,7 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file,
 	dbg("%s - port %d", __func__, port->number);
 
 	if (port->serial->type->tiocmset)
-		return port->serial->type->tiocmset(tty, file, set, clear);
+		return port->serial->type->tiocmset(tty, set, clear);
 	return -EINVAL;
 }
 
@@ -911,9 +911,8 @@ int usb_serial_probe(struct usb_interface *interface,
 			dev_err(&interface->dev, "No free urbs available\n");
 			goto probe_error;
 		}
-		buffer_size = serial->type->bulk_in_size;
-		if (!buffer_size)
-			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+		buffer_size = max_t(int, serial->type->bulk_in_size,
+				le16_to_cpu(endpoint->wMaxPacketSize));
 		port->bulk_in_size = buffer_size;
 		port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
 		port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h
index 3ab77c5..c47b6ec 100644
--- a/drivers/usb/serial/usb-wwan.h
+++ b/drivers/usb/serial/usb-wwan.h
@@ -15,10 +15,10 @@ extern int usb_wwan_write_room(struct tty_struct *tty);
 extern void usb_wwan_set_termios(struct tty_struct *tty,
 				 struct usb_serial_port *port,
 				 struct ktermios *old);
-extern int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file);
-extern int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
+extern int usb_wwan_tiocmget(struct tty_struct *tty);
+extern int usb_wwan_tiocmset(struct tty_struct *tty,
 			     unsigned int set, unsigned int clear);
-extern int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
+extern int usb_wwan_ioctl(struct tty_struct *tty,
 			  unsigned int cmd, unsigned long arg);
 extern int usb_wwan_send_setup(struct usb_serial_port *port);
 extern int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 9c014e2..a65ddd5 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -79,7 +79,7 @@ void usb_wwan_set_termios(struct tty_struct *tty,
 }
 EXPORT_SYMBOL(usb_wwan_set_termios);
 
-int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file)
+int usb_wwan_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	unsigned int value;
@@ -98,7 +98,7 @@ int usb_wwan_tiocmget(struct tty_struct *tty, struct file *file)
 }
 EXPORT_SYMBOL(usb_wwan_tiocmget);
 
-int usb_wwan_tiocmset(struct tty_struct *tty, struct file *file,
+int usb_wwan_tiocmset(struct tty_struct *tty,
 		      unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -178,7 +178,7 @@ static int set_serial_info(struct usb_serial_port *port,
 	return retval;
 }
 
-int usb_wwan_ioctl(struct tty_struct *tty, struct file *file,
+int usb_wwan_ioctl(struct tty_struct *tty,
 		   unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -261,7 +261,8 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port,
 				intfdata->in_flight--;
 				spin_unlock_irqrestore(&intfdata->susp_lock,
 						       flags);
-				continue;
+				usb_autopm_put_interface_async(port->serial->interface);
+				break;
 			}
 		}
 
@@ -308,11 +309,16 @@ static void usb_wwan_indat_callback(struct urb *urb)
 		/* Resubmit urb so we continue receiving */
 		if (status != -ESHUTDOWN) {
 			err = usb_submit_urb(urb, GFP_ATOMIC);
-			if (err && err != -EPERM)
-				printk(KERN_ERR "%s: resubmit read urb failed. "
-				       "(%d)", __func__, err);
-			else
+			if (err) {
+				if (err != -EPERM) {
+					printk(KERN_ERR "%s: resubmit read urb failed. "
+						"(%d)", __func__, err);
+					/* busy also in error unless we are killed */
+					usb_mark_last_busy(port->serial->dev);
+				}
+			} else {
 				usb_mark_last_busy(port->serial->dev);
+			}
 		}
 
 	}
@@ -421,6 +427,7 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port)
 	spin_lock_irq(&intfdata->susp_lock);
 	portdata->opened = 1;
 	spin_unlock_irq(&intfdata->susp_lock);
+	/* this balances a get in the generic USB serial code */
 	usb_autopm_put_interface(serial->interface);
 
 	return 0;
@@ -447,7 +454,8 @@ void usb_wwan_close(struct usb_serial_port *port)
 			usb_kill_urb(portdata->in_urbs[i]);
 		for (i = 0; i < N_OUT_URB; i++)
 			usb_kill_urb(portdata->out_urbs[i]);
-		usb_autopm_get_interface(serial->interface);
+		/* balancing - important as an error cannot be handled*/
+		usb_autopm_get_interface_no_resume(serial->interface);
 		serial->interface->needs_remote_wakeup = 0;
 	}
 }
@@ -661,6 +669,18 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message)
 }
 EXPORT_SYMBOL(usb_wwan_suspend);
 
+static void unbusy_queued_urb(struct urb *urb, struct usb_wwan_port_private *portdata)
+{
+	int i;
+
+	for (i = 0; i < N_OUT_URB; i++) {
+		if (urb == portdata->out_urbs[i]) {
+			clear_bit(i, &portdata->out_busy);
+			break;
+		}
+	}
+}
+
 static void play_delayed(struct usb_serial_port *port)
 {
 	struct usb_wwan_intf_private *data;
@@ -672,8 +692,17 @@ static void play_delayed(struct usb_serial_port *port)
 	data = port->serial->private;
 	while ((urb = usb_get_from_anchor(&portdata->delayed))) {
 		err = usb_submit_urb(urb, GFP_ATOMIC);
-		if (!err)
+		if (!err) {
 			data->in_flight++;
+		} else {
+			/* we have to throw away the rest */
+			do {
+				unbusy_queued_urb(urb, portdata);
+				//extremely dirty
+				atomic_dec(&port->serial->interface->dev.power.usage_count);
+			} while ((urb = usb_get_from_anchor(&portdata->delayed)));
+			break;
+		}
 	}
 }
 
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 3f9ac88..5b073bc 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -152,12 +152,12 @@ static int  whiteheat_write(struct tty_struct *tty,
 			struct usb_serial_port *port,
 			const unsigned char *buf, int count);
 static int  whiteheat_write_room(struct tty_struct *tty);
-static int  whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+static int  whiteheat_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg);
 static void whiteheat_set_termios(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
-static int  whiteheat_tiocmget(struct tty_struct *tty, struct file *file);
-static int  whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+static int  whiteheat_tiocmget(struct tty_struct *tty);
+static int  whiteheat_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
 static void whiteheat_break_ctl(struct tty_struct *tty, int break_state);
 static int  whiteheat_chars_in_buffer(struct tty_struct *tty);
@@ -833,7 +833,7 @@ static int whiteheat_write_room(struct tty_struct *tty)
 	return (room);
 }
 
-static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
+static int whiteheat_tiocmget(struct tty_struct *tty)
 {
 	struct usb_serial_port *port = tty->driver_data;
 	struct whiteheat_private *info = usb_get_serial_port_data(port);
@@ -850,7 +850,7 @@ static int whiteheat_tiocmget(struct tty_struct *tty, struct file *file)
 	return modem_signals;
 }
 
-static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
+static int whiteheat_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear)
 {
 	struct usb_serial_port *port = tty->driver_data;
@@ -874,7 +874,7 @@ static int whiteheat_tiocmset(struct tty_struct *tty, struct file *file,
 }
 
 
-static int whiteheat_ioctl(struct tty_struct *tty, struct file *file,
+static int whiteheat_ioctl(struct tty_struct *tty,
 					unsigned int cmd, unsigned long arg)
 {
 	struct usb_serial_port *port = tty->driver_data;
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 49a489e..9798725 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -31,6 +31,16 @@ config USB_STORAGE_DEBUG
 	  Say Y here in order to have the USB Mass Storage code generate
 	  verbose debugging messages.
 
+config USB_STORAGE_REALTEK
+	tristate "Realtek Card Reader support"
+	depends on USB_STORAGE
+	help
+	  Say Y here to include additional code to support the power-saving function
+	  for Realtek RTS51xx USB card readers.
+
+	  If this driver is compiled as a module, it will be named ums-realtek.
+
+
 config USB_STORAGE_DATAFAB
 	tristate "Datafab Compact Flash Reader support"
 	depends on USB_STORAGE
@@ -172,6 +182,21 @@ config USB_STORAGE_CYPRESS_ATACB
 
 	  If this driver is compiled as a module, it will be named ums-cypress.
 
+config USB_STORAGE_ENE_UB6250
+	tristate "USB ENE card reader support"
+	depends on USB && SCSI
+	depends on USB_STORAGE
+	---help---
+	  Say Y here if you wish to control a ENE SD Card reader.
+	  To use SM/MS card, please build driver/staging/keucr/keucr.ko
+
+	  This option depends on 'SCSI' support being enabled, but you
+	  probably also need 'SCSI device support: SCSI disk support'
+	  (BLK_DEV_SD) for most USB storage devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ums-eneub6250.
+
 config USB_UAS
 	tristate "USB Attached SCSI"
 	depends on USB && SCSI
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index fcf14cd..82e6416 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -25,11 +25,13 @@ endif
 obj-$(CONFIG_USB_STORAGE_ALAUDA)	+= ums-alauda.o
 obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o
 obj-$(CONFIG_USB_STORAGE_DATAFAB)	+= ums-datafab.o
+obj-$(CONFIG_USB_STORAGE_ENE_UB6250)	+= ums-eneub6250.o
 obj-$(CONFIG_USB_STORAGE_FREECOM)	+= ums-freecom.o
 obj-$(CONFIG_USB_STORAGE_ISD200)	+= ums-isd200.o
 obj-$(CONFIG_USB_STORAGE_JUMPSHOT)	+= ums-jumpshot.o
 obj-$(CONFIG_USB_STORAGE_KARMA)		+= ums-karma.o
 obj-$(CONFIG_USB_STORAGE_ONETOUCH)	+= ums-onetouch.o
+obj-$(CONFIG_USB_STORAGE_REALTEK)	+= ums-realtek.o
 obj-$(CONFIG_USB_STORAGE_SDDR09)	+= ums-sddr09.o
 obj-$(CONFIG_USB_STORAGE_SDDR55)	+= ums-sddr55.o
 obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
@@ -37,11 +39,13 @@ obj-$(CONFIG_USB_STORAGE_USBAT)		+= ums-usbat.o
 ums-alauda-y		:= alauda.o
 ums-cypress-y		:= cypress_atacb.o
 ums-datafab-y		:= datafab.o
+ums-eneub6250-y		:= ene_ub6250.o
 ums-freecom-y		:= freecom.o
 ums-isd200-y		:= isd200.o
 ums-jumpshot-y		:= jumpshot.o
 ums-karma-y		:= karma.o
 ums-onetouch-y		:= onetouch.o
+ums-realtek-y		:= realtek_cr.o
 ums-sddr09-y		:= sddr09.o
 ums-sddr55-y		:= sddr55.o
 ums-usbat-y		:= shuttle_usbat.o
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
new file mode 100644
index 0000000..08e0374
--- /dev/null
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -0,0 +1,803 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+#include <linux/firmware.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+
+MODULE_DESCRIPTION("Driver for ENE UB6250 reader");
+MODULE_LICENSE("GPL");
+
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+	.driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+struct usb_device_id ene_ub6250_usb_ids[] = {
+#	include "unusual_ene_ub6250.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ene_ub6250_usb_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev ene_ub6250_unusual_dev_list[] = {
+#	include "unusual_ene_ub6250.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+
+
+/* ENE bin code len */
+#define ENE_BIN_CODE_LEN    0x800
+/* EnE HW Register */
+#define REG_CARD_STATUS     0xFF83
+#define REG_HW_TRAP1        0xFF89
+
+/* SRB Status */
+#define SS_SUCCESS                  0x00      /* No Sense */
+#define SS_NOT_READY                0x02
+#define SS_MEDIUM_ERR               0x03
+#define SS_HW_ERR                   0x04
+#define SS_ILLEGAL_REQUEST          0x05
+#define SS_UNIT_ATTENTION           0x06
+
+/* ENE Load FW Pattern */
+#define SD_INIT1_PATTERN   1
+#define SD_INIT2_PATTERN   2
+#define SD_RW_PATTERN      3
+#define MS_INIT_PATTERN    4
+#define MSP_RW_PATTERN     5
+#define MS_RW_PATTERN      6
+#define SM_INIT_PATTERN    7
+#define SM_RW_PATTERN      8
+
+#define FDIR_WRITE         0
+#define FDIR_READ          1
+
+
+struct SD_STATUS {
+	u8    Insert:1;
+	u8    Ready:1;
+	u8    MediaChange:1;
+	u8    IsMMC:1;
+	u8    HiCapacity:1;
+	u8    HiSpeed:1;
+	u8    WtP:1;
+	u8    Reserved:1;
+};
+
+struct MS_STATUS {
+	u8    Insert:1;
+	u8    Ready:1;
+	u8    MediaChange:1;
+	u8    IsMSPro:1;
+	u8    IsMSPHG:1;
+	u8    Reserved1:1;
+	u8    WtP:1;
+	u8    Reserved2:1;
+};
+
+struct SM_STATUS {
+	u8    Insert:1;
+	u8    Ready:1;
+	u8    MediaChange:1;
+	u8    Reserved:3;
+	u8    WtP:1;
+	u8    IsMS:1;
+};
+
+
+/* SD Block Length */
+/* 2^9 = 512 Bytes, The HW maximum read/write data length */
+#define SD_BLOCK_LEN  9
+
+struct ene_ub6250_info {
+	/* for 6250 code */
+	struct SD_STATUS	SD_Status;
+	struct MS_STATUS	MS_Status;
+	struct SM_STATUS	SM_Status;
+
+	/* ----- SD Control Data ---------------- */
+	/*SD_REGISTER SD_Regs; */
+	u16		SD_Block_Mult;
+	u8		SD_READ_BL_LEN;
+	u16		SD_C_SIZE;
+	u8		SD_C_SIZE_MULT;
+
+	/* SD/MMC New spec. */
+	u8		SD_SPEC_VER;
+	u8		SD_CSD_VER;
+	u8		SD20_HIGH_CAPACITY;
+	u32		HC_C_SIZE;
+	u8		MMC_SPEC_VER;
+	u8		MMC_BusWidth;
+	u8		MMC_HIGH_CAPACITY;
+
+	/*----- MS Control Data ---------------- */
+	bool		MS_SWWP;
+	u32		MSP_TotalBlock;
+	/*MS_LibControl       MS_Lib;*/
+	bool		MS_IsRWPage;
+	u16		MS_Model;
+
+	/*----- SM Control Data ---------------- */
+	u8		SM_DeviceID;
+	u8		SM_CardID;
+
+	unsigned char	*testbuf;
+	u8		BIN_FLAG;
+	u32		bl_num;
+	int		SrbStatus;
+
+	/*------Power Managerment ---------------*/
+	bool		Power_IsResum;
+};
+
+static int ene_sd_init(struct us_data *us);
+static int ene_load_bincode(struct us_data *us, unsigned char flag);
+
+static void ene_ub6250_info_destructor(void *extra)
+{
+	if (!extra)
+		return;
+}
+
+static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+
+	int result;
+	unsigned int residue;
+	unsigned int cswlen = 0, partial = 0;
+	unsigned int transfer_length = bcb->DataTransferLength;
+
+	/* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */
+	/* send cmd to out endpoint */
+	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+					    bcb, US_BULK_CB_WRAP_LEN, NULL);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("send cmd to out endpoint fail ---\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (buf) {
+		unsigned int pipe = fDir;
+
+		if (fDir  == FDIR_READ)
+			pipe = us->recv_bulk_pipe;
+		else
+			pipe = us->send_bulk_pipe;
+
+		/* Bulk */
+		if (use_sg) {
+			result = usb_stor_bulk_srb(us, pipe, us->srb);
+		} else {
+			result = usb_stor_bulk_transfer_sg(us, pipe, buf,
+						transfer_length, 0, &partial);
+		}
+		if (result != USB_STOR_XFER_GOOD) {
+			US_DEBUGP("data transfer fail ---\n");
+			return USB_STOR_TRANSPORT_ERROR;
+		}
+	}
+
+	/* Get CSW for device status */
+	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
+					    US_BULK_CS_WRAP_LEN, &cswlen);
+
+	if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
+		US_DEBUGP("Received 0-length CSW; retrying...\n");
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+					    bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+	}
+
+	if (result == USB_STOR_XFER_STALLED) {
+		/* get the status again */
+		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
+		result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+						bcs, US_BULK_CS_WRAP_LEN, NULL);
+	}
+
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	/* check bulk status */
+	residue = le32_to_cpu(bcs->Residue);
+
+	/* try to compute the actual residue, based on how much data
+	 * was really transferred and what the device tells us */
+	if (residue && !(us->fflags & US_FL_IGNORE_RESIDUE)) {
+		residue = min(residue, transfer_length);
+		if (us->srb != NULL)
+			scsi_set_resid(us->srb, max(scsi_get_resid(us->srb),
+								(int)residue));
+	}
+
+	if (bcs->Status != US_BULK_STAT_OK)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_test_unit_ready(struct us_data *us, struct scsi_cmnd *srb)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (info->SD_Status.Insert && info->SD_Status.Ready)
+		return USB_STOR_TRANSPORT_GOOD;
+	else {
+		ene_sd_init(us);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_inquiry(struct us_data *us, struct scsi_cmnd *srb)
+{
+	unsigned char data_ptr[36] = {
+		0x00, 0x80, 0x02, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x55,
+		0x53, 0x42, 0x32, 0x2E, 0x30, 0x20, 0x20, 0x43, 0x61,
+		0x72, 0x64, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20,
+		0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x30, 0x30 };
+
+	usb_stor_set_xfer_buf(data_ptr, 36, srb);
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_mode_sense(struct us_data *us, struct scsi_cmnd *srb)
+{
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+	unsigned char mediaNoWP[12] = {
+		0x0b, 0x00, 0x00, 0x08, 0x00, 0x00,
+		0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+	unsigned char mediaWP[12]   = {
+		0x0b, 0x00, 0x80, 0x08, 0x00, 0x00,
+		0x71, 0xc0, 0x00, 0x00, 0x02, 0x00 };
+
+	if (info->SD_Status.WtP)
+		usb_stor_set_xfer_buf(mediaWP, 12, srb);
+	else
+		usb_stor_set_xfer_buf(mediaNoWP, 12, srb);
+
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
+{
+	u32   bl_num;
+	u16    bl_len;
+	unsigned int offset = 0;
+	unsigned char    buf[8];
+	struct scatterlist *sg = NULL;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	US_DEBUGP("sd_scsi_read_capacity\n");
+	if (info->SD_Status.HiCapacity) {
+		bl_len = 0x200;
+		if (info->SD_Status.IsMMC)
+			bl_num = info->HC_C_SIZE-1;
+		else
+			bl_num = (info->HC_C_SIZE + 1) * 1024 - 1;
+	} else {
+		bl_len = 1<<(info->SD_READ_BL_LEN);
+		bl_num = info->SD_Block_Mult * (info->SD_C_SIZE + 1)
+				* (1 << (info->SD_C_SIZE_MULT + 2)) - 1;
+	}
+	info->bl_num = bl_num;
+	US_DEBUGP("bl_len = %x\n", bl_len);
+	US_DEBUGP("bl_num = %x\n", bl_num);
+
+	/*srb->request_bufflen = 8; */
+	buf[0] = (bl_num >> 24) & 0xff;
+	buf[1] = (bl_num >> 16) & 0xff;
+	buf[2] = (bl_num >> 8) & 0xff;
+	buf[3] = (bl_num >> 0) & 0xff;
+	buf[4] = (bl_len >> 24) & 0xff;
+	buf[5] = (bl_len >> 16) & 0xff;
+	buf[6] = (bl_len >> 8) & 0xff;
+	buf[7] = (bl_len >> 0) & 0xff;
+
+	usb_stor_access_xfer_buf(buf, 8, srb, &sg, &offset, TO_XFER_BUF);
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int result;
+	unsigned char *cdb = srb->cmnd;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) |
+		 ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff);
+	u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+	u32 bnByte = bn * 0x200;
+	u32 blenByte = blen * 0x200;
+
+	if (bn > info->bl_num)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	result = ene_load_bincode(us, SD_RW_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Load SD RW pattern Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (info->SD_Status.HiCapacity)
+		bnByte = bn;
+
+	/* set up the command wrapper */
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = blenByte;
+	bcb->Flags  = 0x80;
+	bcb->CDB[0] = 0xF1;
+	bcb->CDB[5] = (unsigned char)(bnByte);
+	bcb->CDB[4] = (unsigned char)(bnByte>>8);
+	bcb->CDB[3] = (unsigned char)(bnByte>>16);
+	bcb->CDB[2] = (unsigned char)(bnByte>>24);
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, scsi_sglist(srb), 1);
+	return result;
+}
+
+static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int result;
+	unsigned char *cdb = srb->cmnd;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	u32 bn = ((cdb[2] << 24) & 0xff000000) | ((cdb[3] << 16) & 0x00ff0000) |
+		 ((cdb[4] << 8) & 0x0000ff00) | ((cdb[5] << 0) & 0x000000ff);
+	u16 blen = ((cdb[7] << 8) & 0xff00) | ((cdb[8] << 0) & 0x00ff);
+	u32 bnByte = bn * 0x200;
+	u32 blenByte = blen * 0x200;
+
+	if (bn > info->bl_num)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	result = ene_load_bincode(us, SD_RW_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Load SD RW pattern Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (info->SD_Status.HiCapacity)
+		bnByte = bn;
+
+	/* set up the command wrapper */
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = blenByte;
+	bcb->Flags  = 0x00;
+	bcb->CDB[0] = 0xF0;
+	bcb->CDB[5] = (unsigned char)(bnByte);
+	bcb->CDB[4] = (unsigned char)(bnByte>>8);
+	bcb->CDB[3] = (unsigned char)(bnByte>>16);
+	bcb->CDB[2] = (unsigned char)(bnByte>>24);
+
+	result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
+	return result;
+}
+
+static int ene_get_card_type(struct us_data *us, u16 index, void *buf)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	int result;
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength	= 0x01;
+	bcb->Flags			= 0x80;
+	bcb->CDB[0]			= 0xED;
+	bcb->CDB[2]			= (unsigned char)(index>>8);
+	bcb->CDB[3]			= (unsigned char)index;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, buf, 0);
+	return result;
+}
+
+static int ene_get_card_status(struct us_data *us, u8 *buf)
+{
+	u16 tmpreg;
+	u32 reg4b;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	/*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/
+	reg4b = *(u32 *)&buf[0x18];
+	info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f);
+
+	tmpreg = (u16) reg4b;
+	reg4b = *(u32 *)(&buf[0x14]);
+	if (info->SD_Status.HiCapacity && !info->SD_Status.IsMMC)
+		info->HC_C_SIZE = (reg4b >> 8) & 0x3fffff;
+
+	info->SD_C_SIZE = ((tmpreg & 0x03) << 10) | (u16)(reg4b >> 22);
+	info->SD_C_SIZE_MULT = (u8)(reg4b >> 7)  & 0x07;
+	if (info->SD_Status.HiCapacity && info->SD_Status.IsMMC)
+		info->HC_C_SIZE = *(u32 *)(&buf[0x100]);
+
+	if (info->SD_READ_BL_LEN > SD_BLOCK_LEN) {
+		info->SD_Block_Mult = 1 << (info->SD_READ_BL_LEN-SD_BLOCK_LEN);
+		info->SD_READ_BL_LEN = SD_BLOCK_LEN;
+	} else {
+		info->SD_Block_Mult = 1;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+static int ene_load_bincode(struct us_data *us, unsigned char flag)
+{
+	int err;
+	char *fw_name = NULL;
+	unsigned char *buf = NULL;
+	const struct firmware *sd_fw = NULL;
+	int result = USB_STOR_TRANSPORT_ERROR;
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	if (info->BIN_FLAG == flag)
+		return USB_STOR_TRANSPORT_GOOD;
+
+	switch (flag) {
+	/* For SD */
+	case SD_INIT1_PATTERN:
+		US_DEBUGP("SD_INIT1_PATTERN\n");
+		fw_name = "ene-ub6250/sd_init1.bin";
+		break;
+	case SD_INIT2_PATTERN:
+		US_DEBUGP("SD_INIT2_PATTERN\n");
+		fw_name = "ene-ub6250/sd_init2.bin";
+		break;
+	case SD_RW_PATTERN:
+		US_DEBUGP("SD_RDWR_PATTERN\n");
+		fw_name = "ene-ub6250/sd_rdwr.bin";
+		break;
+	default:
+		US_DEBUGP("----------- Unknown PATTERN ----------\n");
+		goto nofw;
+	}
+
+	err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);
+	if (err) {
+		US_DEBUGP("load firmware %s failed\n", fw_name);
+		goto nofw;
+	}
+	buf = kmalloc(sd_fw->size, GFP_KERNEL);
+	if (buf == NULL) {
+		US_DEBUGP("Malloc memory for fireware failed!\n");
+		goto nofw;
+	}
+	memcpy(buf, sd_fw->data, sd_fw->size);
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = sd_fw->size;
+	bcb->Flags = 0x00;
+	bcb->CDB[0] = 0xEF;
+
+	result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
+	info->BIN_FLAG = flag;
+	kfree(buf);
+
+nofw:
+	if (sd_fw != NULL) {
+		release_firmware(sd_fw);
+		sd_fw = NULL;
+	}
+
+	return result;
+}
+
+static int ene_sd_init(struct us_data *us)
+{
+	int result;
+	u8  buf[0x200];
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
+
+	US_DEBUGP("transport --- ENE_SDInit\n");
+	/* SD Init Part-1 */
+	result = ene_load_bincode(us, SD_INIT1_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Load SD Init Code Part-1 Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->Flags = 0x80;
+	bcb->CDB[0] = 0xF2;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Exection SD Init Code Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* SD Init Part-2 */
+	result = ene_load_bincode(us, SD_INIT2_PATTERN);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Load SD Init Code Part-2 Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	memset(bcb, 0, sizeof(struct bulk_cb_wrap));
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = 0x200;
+	bcb->Flags              = 0x80;
+	bcb->CDB[0]             = 0xF1;
+
+	result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
+	if (result != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("Exection SD Init Code Fail !!\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	info->SD_Status =  *(struct SD_STATUS *)&buf[0];
+	if (info->SD_Status.Insert && info->SD_Status.Ready) {
+		ene_get_card_status(us, (unsigned char *)&buf);
+		US_DEBUGP("Insert     = %x\n", info->SD_Status.Insert);
+		US_DEBUGP("Ready      = %x\n", info->SD_Status.Ready);
+		US_DEBUGP("IsMMC      = %x\n", info->SD_Status.IsMMC);
+		US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity);
+		US_DEBUGP("HiSpeed    = %x\n", info->SD_Status.HiSpeed);
+		US_DEBUGP("WtP        = %x\n", info->SD_Status.WtP);
+	} else {
+		US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+
+static int ene_init(struct us_data *us)
+{
+	int result;
+	u8  misc_reg03 = 0;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	if (misc_reg03 & 0x01) {
+		if (!info->SD_Status.Ready) {
+			result = ene_sd_init(us);
+			if (result != USB_STOR_XFER_GOOD)
+				return USB_STOR_TRANSPORT_ERROR;
+		}
+	}
+
+	return result;
+}
+
+/*----- sd_scsi_irp() ---------*/
+static int sd_scsi_irp(struct us_data *us, struct scsi_cmnd *srb)
+{
+	int    result;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)us->extra;
+
+	info->SrbStatus = SS_SUCCESS;
+	switch (srb->cmnd[0]) {
+	case TEST_UNIT_READY:
+		result = sd_scsi_test_unit_ready(us, srb);
+		break; /* 0x00 */
+	case INQUIRY:
+		result = sd_scsi_inquiry(us, srb);
+		break; /* 0x12 */
+	case MODE_SENSE:
+		result = sd_scsi_mode_sense(us, srb);
+		break; /* 0x1A */
+	/*
+	case START_STOP:
+		result = SD_SCSI_Start_Stop(us, srb);
+		break; //0x1B
+	*/
+	case READ_CAPACITY:
+		result = sd_scsi_read_capacity(us, srb);
+		break; /* 0x25 */
+	case READ_10:
+		result = sd_scsi_read(us, srb);
+		break; /* 0x28 */
+	case WRITE_10:
+		result = sd_scsi_write(us, srb);
+		break; /* 0x2A */
+	default:
+		info->SrbStatus = SS_ILLEGAL_REQUEST;
+		result = USB_STOR_TRANSPORT_FAILED;
+		break;
+	}
+	return result;
+}
+
+static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	int result = 0;
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+	/*US_DEBUG(usb_stor_show_command(srb)); */
+	scsi_set_resid(srb, 0);
+	if (unlikely(!info->SD_Status.Ready))
+		result = ene_init(us);
+	else
+		result = sd_scsi_irp(us, srb);
+
+	return 0;
+}
+
+
+static int ene_ub6250_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	int result;
+	u8  misc_reg03 = 0;
+	struct us_data *us;
+
+	result = usb_stor_probe1(&us, intf, id,
+		   (id - ene_ub6250_usb_ids) + ene_ub6250_unusual_dev_list);
+	if (result)
+		return result;
+
+	/* FIXME: where should the code alloc extra buf ? */
+	if (!us->extra) {
+		us->extra = kzalloc(sizeof(struct ene_ub6250_info), GFP_KERNEL);
+		if (!us->extra)
+			return -ENOMEM;
+		us->extra_destructor = ene_ub6250_info_destructor;
+	}
+
+	us->transport_name = "ene_ub6250";
+	us->transport = ene_transport;
+	us->max_lun = 0;
+
+	result = usb_stor_probe2(us);
+	if (result)
+		return result;
+
+	/* probe card type */
+	result = ene_get_card_type(us, REG_CARD_STATUS, &misc_reg03);
+	if (result != USB_STOR_XFER_GOOD) {
+		usb_stor_disconnect(intf);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (!(misc_reg03 & 0x01)) {
+		result = -ENODEV;
+		printk(KERN_NOTICE "ums_eneub6250: The driver only supports SD\
+		card. To use SM/MS card, please build driver/stagging/keucr\n");
+		usb_stor_disconnect(intf);
+	}
+
+	return result;
+}
+
+
+#ifdef CONFIG_PM
+
+static int ene_ub6250_resume(struct usb_interface *iface)
+{
+	u8 tmp = 0;
+	struct us_data *us = usb_get_intfdata(iface);
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+
+	mutex_lock(&us->dev_mutex);
+
+	US_DEBUGP("%s\n", __func__);
+	if (us->suspend_resume_hook)
+		(us->suspend_resume_hook)(us, US_RESUME);
+
+	mutex_unlock(&us->dev_mutex);
+
+	info->Power_IsResum = true;
+	/*info->SD_Status.Ready = 0; */
+	info->SD_Status = *(struct SD_STATUS *)&tmp;
+	info->MS_Status = *(struct MS_STATUS *)&tmp;
+	info->SM_Status = *(struct SM_STATUS *)&tmp;
+
+	return 0;
+}
+
+static int ene_ub6250_reset_resume(struct usb_interface *iface)
+{
+	u8 tmp = 0;
+	struct us_data *us = usb_get_intfdata(iface);
+	struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
+	US_DEBUGP("%s\n", __func__);
+	/* Report the reset to the SCSI core */
+	usb_stor_reset_resume(iface);
+
+	/* FIXME: Notify the subdrivers that they need to reinitialize
+	 * the device */
+	info->Power_IsResum = true;
+	/*info->SD_Status.Ready = 0; */
+	info->SD_Status = *(struct SD_STATUS *)&tmp;
+	info->MS_Status = *(struct MS_STATUS *)&tmp;
+	info->SM_Status = *(struct SM_STATUS *)&tmp;
+
+	return 0;
+}
+
+#else
+
+#define ene_ub6250_resume		NULL
+#define ene_ub6250_reset_resume		NULL
+
+#endif
+
+static struct usb_driver ene_ub6250_driver = {
+	.name =		"ums_eneub6250",
+	.probe =	ene_ub6250_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	ene_ub6250_resume,
+	.reset_resume =	ene_ub6250_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	ene_ub6250_usb_ids,
+	.soft_unbind =	1,
+};
+
+static int __init ene_ub6250_init(void)
+{
+	return usb_register(&ene_ub6250_driver);
+}
+
+static void __exit ene_ub6250_exit(void)
+{
+	usb_deregister(&ene_ub6250_driver);
+}
+
+module_init(ene_ub6250_init);
+module_exit(ene_ub6250_exit);
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
new file mode 100644
index 0000000..d509a4a
--- /dev/null
+++ b/drivers/usb/storage/realtek_cr.c
@@ -0,0 +1,675 @@
+/* Driver for Realtek RTS51xx USB card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#include <linux/module.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <linux/cdrom.h>
+
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/usb_usual.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "protocol.h"
+#include "debug.h"
+
+MODULE_DESCRIPTION("Driver for Realtek USB Card Reader");
+MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.03");
+
+static int auto_delink_en = 1;
+module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
+
+struct rts51x_status {
+	u16 vid;
+	u16 pid;
+	u8 cur_lun;
+	u8 card_type;
+	u8 total_lun;
+	u16 fw_ver;
+	u8 phy_exist;
+	u8 multi_flag;
+	u8 multi_card;
+	u8 log_exist;
+	union {
+		u8 detailed_type1;
+		u8 detailed_type2;
+	} detailed_type;
+	u8 function[2];
+};
+
+struct rts51x_chip {
+	u16			vendor_id;
+	u16			product_id;
+	char			max_lun;
+
+	struct rts51x_status	*status;
+	int			status_len;
+
+	u32			flag;
+};
+
+/* flag definition */
+#define FLIDX_AUTO_DELINK		0x01
+
+#define SCSI_LUN(srb)			((srb)->device->lun)
+
+/* Bit Operation */
+#define SET_BIT(data, idx)		((data) |= 1 << (idx))
+#define CLR_BIT(data, idx)		((data) &= ~(1 << (idx)))
+#define CHK_BIT(data, idx)		((data) & (1 << (idx)))
+
+#define SET_AUTO_DELINK(chip)		((chip)->flag |= FLIDX_AUTO_DELINK)
+#define CLR_AUTO_DELINK(chip)		((chip)->flag &= ~FLIDX_AUTO_DELINK)
+#define CHK_AUTO_DELINK(chip)		((chip)->flag & FLIDX_AUTO_DELINK)
+
+#define RTS51X_GET_VID(chip)		((chip)->vendor_id)
+#define RTS51X_GET_PID(chip)		((chip)->product_id)
+
+#define FW_VERSION(chip)		((chip)->status[0].fw_ver)
+#define STATUS_LEN(chip)		((chip)->status_len)
+
+/* Check card reader function */
+#define SUPPORT_DETAILED_TYPE1(chip)	\
+		CHK_BIT((chip)->status[0].function[0], 1)
+#define SUPPORT_OT(chip)		\
+		CHK_BIT((chip)->status[0].function[0], 2)
+#define SUPPORT_OC(chip)		\
+		CHK_BIT((chip)->status[0].function[0], 3)
+#define SUPPORT_AUTO_DELINK(chip)	\
+		CHK_BIT((chip)->status[0].function[0], 4)
+#define SUPPORT_SDIO(chip)		\
+		CHK_BIT((chip)->status[0].function[1], 0)
+#define SUPPORT_DETAILED_TYPE2(chip)	\
+		CHK_BIT((chip)->status[0].function[1], 1)
+
+#define CHECK_PID(chip, pid)		(RTS51X_GET_PID(chip) == (pid))
+#define CHECK_FW_VER(chip, fw_ver)	(FW_VERSION(chip) == (fw_ver))
+#define CHECK_ID(chip, pid, fw_ver)	\
+		(CHECK_PID((chip), (pid)) && CHECK_FW_VER((chip), (fw_ver)))
+
+#define wait_timeout_x(task_state, msecs)	\
+do {						\
+	set_current_state((task_state));	\
+	schedule_timeout((msecs) * HZ / 1000);	\
+} while (0)
+
+#define wait_timeout(msecs)		\
+		wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
+
+static int init_realtek_cr(struct us_data *us);
+
+/*
+ * The table of devices
+ */
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+		    vendorName, productName, useProtocol, useTransport, \
+		    initFunction, flags) \
+{\
+	USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+	.driver_info = (flags)|(USB_US_TYPE_STOR<<24)\
+}
+
+static const struct usb_device_id realtek_cr_ids[] = {
+#	include "unusual_realtek.h"
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, realtek_cr_ids);
+
+#undef UNUSUAL_DEV
+
+/*
+ * The flags table
+ */
+#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
+		    vendor_name, product_name, use_protocol, use_transport, \
+		    init_function, Flags) \
+{ \
+	.vendorName = vendor_name,	\
+	.productName = product_name,	\
+	.useProtocol = use_protocol,	\
+	.useTransport = use_transport,	\
+	.initFunction = init_function,	\
+}
+
+static struct us_unusual_dev realtek_cr_unusual_dev_list[] = {
+#	include "unusual_realtek.h"
+	{ }		/* Terminating entry */
+};
+
+#undef UNUSUAL_DEV
+
+static int rts51x_bulk_transport(struct us_data *us, u8 lun,
+				 u8 *cmd, int cmd_len, u8 *buf, int buf_len,
+				 enum dma_data_direction dir, int *act_len)
+{
+	struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+	struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
+	int result;
+	unsigned int residue;
+	unsigned int cswlen;
+	unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+
+	/* set up the command wrapper */
+	bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+	bcb->DataTransferLength = cpu_to_le32(buf_len);
+	bcb->Flags = (dir == DMA_FROM_DEVICE) ? 1 << 7 : 0;
+	bcb->Tag = ++us->tag;
+	bcb->Lun = lun;
+	bcb->Length = cmd_len;
+
+	/* copy the command payload */
+	memset(bcb->CDB, 0, sizeof(bcb->CDB));
+	memcpy(bcb->CDB, cmd, bcb->Length);
+
+	/* send it to out endpoint */
+	result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+				bcb, cbwlen, NULL);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	/* DATA STAGE */
+	/* send/receive data payload, if there is any */
+
+	if (buf && buf_len) {
+		unsigned int pipe = (dir == DMA_FROM_DEVICE) ?
+				us->recv_bulk_pipe : us->send_bulk_pipe;
+		result = usb_stor_bulk_transfer_buf(us, pipe,
+				buf, buf_len, NULL);
+		if (result == USB_STOR_XFER_ERROR)
+			return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* get CSW for device status */
+	result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+				bcs, US_BULK_CS_WRAP_LEN, &cswlen);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	/* check bulk status */
+	if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
+		US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
+			  le32_to_cpu(bcs->Signature),
+			  US_BULK_CS_SIGN);
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	residue = bcs->Residue;
+	if (bcs->Tag != us->tag)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	/* try to compute the actual residue, based on how much data
+	 * was really transferred and what the device tells us */
+	if (residue)
+		residue = residue < buf_len ? residue : buf_len;
+
+	if (act_len)
+		*act_len = buf_len - residue;
+
+	/* based on the status code, we report good or bad */
+	switch (bcs->Status) {
+	case US_BULK_STAT_OK:
+		/* command good -- note that data could be short */
+		return USB_STOR_TRANSPORT_GOOD;
+
+	case US_BULK_STAT_FAIL:
+		/* command failed */
+		return USB_STOR_TRANSPORT_FAILED;
+
+	case US_BULK_STAT_PHASE:
+		/* phase error -- note that a transport reset will be
+			* invoked by the invoke_transport() function
+			*/
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	/* we should never get here, but if we do, we're in trouble */
+	return USB_STOR_TRANSPORT_ERROR;
+}
+
+/* Determine what the maximum LUN supported is */
+static int rts51x_get_max_lun(struct us_data *us)
+{
+	int result;
+
+	/* issue the command */
+	us->iobuf[0] = 0;
+	result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
+				 US_BULK_GET_MAX_LUN,
+				 USB_DIR_IN | USB_TYPE_CLASS |
+				 USB_RECIP_INTERFACE,
+				 0, us->ifnum, us->iobuf, 1, 10*HZ);
+
+	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
+		  result, us->iobuf[0]);
+
+	/* if we have a successful request, return the result */
+	if (result > 0)
+		return us->iobuf[0];
+
+	return 0;
+}
+
+static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
+{
+	int retval;
+	u8 cmnd[12] = {0};
+
+	US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
+
+	cmnd[0] = 0xF0;
+	cmnd[1] = 0x0D;
+	cmnd[2] = (u8)(addr >> 8);
+	cmnd[3] = (u8)addr;
+	cmnd[4] = (u8)(len >> 8);
+	cmnd[5] = (u8)len;
+
+	retval = rts51x_bulk_transport(us, 0, cmnd, 12,
+				       data, len, DMA_FROM_DEVICE, NULL);
+	if (retval != USB_STOR_TRANSPORT_GOOD)
+		return -EIO;
+
+	return 0;
+}
+
+static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
+{
+	int retval;
+	u8 cmnd[12] = {0};
+
+	US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
+
+	cmnd[0] = 0xF0;
+	cmnd[1] = 0x0E;
+	cmnd[2] = (u8)(addr >> 8);
+	cmnd[3] = (u8)addr;
+	cmnd[4] = (u8)(len >> 8);
+	cmnd[5] = (u8)len;
+
+	retval = rts51x_bulk_transport(us, 0, cmnd, 12,
+				       data, len, DMA_TO_DEVICE, NULL);
+	if (retval != USB_STOR_TRANSPORT_GOOD)
+		return -EIO;
+
+	return 0;
+}
+
+static int rts51x_read_status(struct us_data *us,
+			      u8 lun, u8 *status, int len, int *actlen)
+{
+	int retval;
+	u8 cmnd[12] = {0};
+
+	US_DEBUGP("%s, lun = %d\n", __func__, lun);
+
+	cmnd[0] = 0xF0;
+	cmnd[1] = 0x09;
+
+	retval = rts51x_bulk_transport(us, lun, cmnd, 12,
+				       status, len, DMA_FROM_DEVICE, actlen);
+	if (retval != USB_STOR_TRANSPORT_GOOD)
+		return -EIO;
+
+	return 0;
+}
+
+static int rts51x_check_status(struct us_data *us, u8 lun)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+	int retval;
+	u8 buf[16];
+
+	retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len));
+	if (retval < 0)
+		return -EIO;
+
+	US_DEBUGP("chip->status_len = %d\n", chip->status_len);
+
+	chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1];
+	chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3];
+	chip->status[lun].cur_lun = buf[4];
+	chip->status[lun].card_type = buf[5];
+	chip->status[lun].total_lun = buf[6];
+	chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8];
+	chip->status[lun].phy_exist = buf[9];
+	chip->status[lun].multi_flag = buf[10];
+	chip->status[lun].multi_card = buf[11];
+	chip->status[lun].log_exist = buf[12];
+	if (chip->status_len == 16) {
+		chip->status[lun].detailed_type.detailed_type1 = buf[13];
+		chip->status[lun].function[0] = buf[14];
+		chip->status[lun].function[1] = buf[15];
+	}
+
+	return 0;
+}
+
+static int enable_oscillator(struct us_data *us)
+{
+	int retval;
+	u8 value;
+
+	retval = rts51x_read_mem(us, 0xFE77, &value, 1);
+	if (retval < 0)
+		return -EIO;
+
+	value |= 0x04;
+	retval = rts51x_write_mem(us, 0xFE77, &value, 1);
+	if (retval < 0)
+		return -EIO;
+
+	retval = rts51x_read_mem(us, 0xFE77, &value, 1);
+	if (retval < 0)
+		return -EIO;
+
+	if (!(value & 0x04))
+		return -EIO;
+
+	return 0;
+}
+
+static int do_config_autodelink(struct us_data *us, int enable, int force)
+{
+	int retval;
+	u8 value;
+
+	retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+	if (retval < 0)
+		return -EIO;
+
+	if (enable) {
+		if (force)
+			value |= 0x03;
+		else
+			value |= 0x01;
+	} else {
+		value &= ~0x03;
+	}
+
+	US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value);
+
+	retval = rts51x_write_mem(us, 0xFE47, &value, 1);
+	if (retval < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static int config_autodelink_after_power_on(struct us_data *us)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+	int retval;
+	u8 value;
+
+	if (!CHK_AUTO_DELINK(chip))
+		return 0;
+
+	retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+	if (retval < 0)
+		return -EIO;
+
+	if (auto_delink_en) {
+		CLR_BIT(value, 0);
+		CLR_BIT(value, 1);
+		SET_BIT(value, 2);
+
+		if (CHECK_ID(chip, 0x0138, 0x3882))
+			CLR_BIT(value, 2);
+
+		SET_BIT(value, 7);
+
+		retval = rts51x_write_mem(us, 0xFE47, &value, 1);
+		if (retval < 0)
+			return -EIO;
+
+		retval = enable_oscillator(us);
+		if (retval == 0)
+			(void)do_config_autodelink(us, 1, 0);
+	} else {
+		/* Autodelink controlled by firmware */
+
+		SET_BIT(value, 2);
+
+		if (CHECK_ID(chip, 0x0138, 0x3882))
+			CLR_BIT(value, 2);
+
+		if (CHECK_ID(chip, 0x0159, 0x5889) ||
+				CHECK_ID(chip, 0x0138, 0x3880)) {
+			CLR_BIT(value, 0);
+			CLR_BIT(value, 7);
+		}
+
+		retval = rts51x_write_mem(us, 0xFE47, &value, 1);
+		if (retval < 0)
+			return -EIO;
+
+		if (CHECK_ID(chip, 0x0159, 0x5888)) {
+			value = 0xFF;
+			retval = rts51x_write_mem(us, 0xFE79, &value, 1);
+			if (retval < 0)
+				return -EIO;
+
+			value = 0x01;
+			retval = rts51x_write_mem(us, 0x48, &value, 1);
+			if (retval < 0)
+				return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static int config_autodelink_before_power_down(struct us_data *us)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra);
+	int retval;
+	u8 value;
+
+	if (!CHK_AUTO_DELINK(chip))
+		return 0;
+
+	if (auto_delink_en) {
+		retval = rts51x_read_mem(us, 0xFE77, &value, 1);
+		if (retval < 0)
+			return -EIO;
+
+		SET_BIT(value, 2);
+		retval = rts51x_write_mem(us, 0xFE77, &value, 1);
+		if (retval < 0)
+			return -EIO;
+
+		if (CHECK_ID(chip, 0x0159, 0x5888)) {
+			value = 0x01;
+			retval = rts51x_write_mem(us, 0x48, &value, 1);
+			if (retval < 0)
+				return -EIO;
+		}
+
+		retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+		if (retval < 0)
+			return -EIO;
+
+		SET_BIT(value, 0);
+		if (CHECK_ID(chip, 0x0138, 0x3882))
+			SET_BIT(value, 2);
+		retval = rts51x_write_mem(us, 0xFE77, &value, 1);
+		if (retval < 0)
+			return -EIO;
+	} else {
+		if (CHECK_ID(chip, 0x0159, 0x5889) ||
+				CHECK_ID(chip, 0x0138, 0x3880) ||
+				CHECK_ID(chip, 0x0138, 0x3882)) {
+			retval = rts51x_read_mem(us, 0xFE47, &value, 1);
+			if (retval < 0)
+				return -EIO;
+
+			if (CHECK_ID(chip, 0x0159, 0x5889) ||
+					CHECK_ID(chip, 0x0138, 0x3880)) {
+				SET_BIT(value, 0);
+				SET_BIT(value, 7);
+			}
+
+			if (CHECK_ID(chip, 0x0138, 0x3882))
+				SET_BIT(value, 2);
+
+			retval = rts51x_write_mem(us, 0xFE47, &value, 1);
+			if (retval < 0)
+				return -EIO;
+		}
+
+		if (CHECK_ID(chip, 0x0159, 0x5888)) {
+			value = 0x01;
+			retval = rts51x_write_mem(us, 0x48, &value, 1);
+			if (retval < 0)
+				return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+static void realtek_cr_destructor(void *extra)
+{
+	struct rts51x_chip *chip = (struct rts51x_chip *)extra;
+
+	if (!chip)
+		return;
+
+	kfree(chip->status);
+}
+
+#ifdef CONFIG_PM
+static void realtek_pm_hook(struct us_data *us, int pm_state)
+{
+	if (pm_state == US_SUSPEND)
+		(void)config_autodelink_before_power_down(us);
+}
+#endif
+
+static int init_realtek_cr(struct us_data *us)
+{
+	struct rts51x_chip *chip;
+	int size, i, retval;
+
+	chip = kzalloc(sizeof(struct rts51x_chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	us->extra = chip;
+	us->extra_destructor = realtek_cr_destructor;
+#ifdef CONFIG_PM
+	us->suspend_resume_hook = realtek_pm_hook;
+#endif
+
+	us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
+
+	US_DEBUGP("chip->max_lun = %d\n", chip->max_lun);
+
+	size = (chip->max_lun + 1) * sizeof(struct rts51x_status);
+	chip->status = kzalloc(size, GFP_KERNEL);
+	if (!chip->status)
+		goto INIT_FAIL;
+
+	for (i = 0; i <= (int)(chip->max_lun); i++) {
+		retval = rts51x_check_status(us, (u8)i);
+		if (retval < 0)
+			goto INIT_FAIL;
+	}
+
+	if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) ||
+			CHECK_FW_VER(chip, 0x5901))
+		SET_AUTO_DELINK(chip);
+	if (STATUS_LEN(chip) == 16) {
+		if (SUPPORT_AUTO_DELINK(chip))
+			SET_AUTO_DELINK(chip);
+	}
+
+	US_DEBUGP("chip->flag = 0x%x\n", chip->flag);
+
+	(void)config_autodelink_after_power_on(us);
+
+	return 0;
+
+INIT_FAIL:
+	if (us->extra) {
+		kfree(chip->status);
+		kfree(us->extra);
+		us->extra = NULL;
+	}
+
+	return -EIO;
+}
+
+static int realtek_cr_probe(struct usb_interface *intf,
+			 const struct usb_device_id *id)
+{
+	struct us_data *us;
+	int result;
+
+	US_DEBUGP("Probe Realtek Card Reader!\n");
+
+	result = usb_stor_probe1(&us, intf, id,
+			(id - realtek_cr_ids) + realtek_cr_unusual_dev_list);
+	if (result)
+		return result;
+
+	result = usb_stor_probe2(us);
+	return result;
+}
+
+static struct usb_driver realtek_cr_driver = {
+	.name =		"ums-realtek",
+	.probe =	realtek_cr_probe,
+	.disconnect =	usb_stor_disconnect,
+	.suspend =	usb_stor_suspend,
+	.resume =	usb_stor_resume,
+	.reset_resume =	usb_stor_reset_resume,
+	.pre_reset =	usb_stor_pre_reset,
+	.post_reset =	usb_stor_post_reset,
+	.id_table =	realtek_cr_ids,
+	.soft_unbind =	1,
+};
+
+static int __init realtek_cr_init(void)
+{
+	return usb_register(&realtek_cr_driver);
+}
+
+static void __exit realtek_cr_exit(void)
+{
+	usb_deregister(&realtek_cr_driver);
+}
+
+module_init(realtek_cr_init);
+module_exit(realtek_cr_exit);
diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c
index ceba512..1deca07 100644
--- a/drivers/usb/storage/sierra_ms.c
+++ b/drivers/usb/storage/sierra_ms.c
@@ -126,13 +126,11 @@ static DEVICE_ATTR(truinst, S_IRUGO, show_truinst, NULL);
 int sierra_ms_init(struct us_data *us)
 {
 	int result, retries;
-	signed long delay_t;
 	struct swoc_info *swocInfo;
 	struct usb_device *udev;
 	struct Scsi_Host *sh;
 	struct scsi_device *sd;
 
-	delay_t = 2;
 	retries = 3;
 	result = 0;
 	udev = us->pusb_dev;
diff --git a/drivers/usb/storage/unusual_ene_ub6250.h b/drivers/usb/storage/unusual_ene_ub6250.h
new file mode 100644
index 0000000..5667f5d
--- /dev/null
+++ b/drivers/usb/storage/unusual_ene_ub6250.h
@@ -0,0 +1,26 @@
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#if defined(CONFIG_USB_STORAGE_ENE_UB6250) || \
+		defined(CONFIG_USB_STORAGE_ENE_UB6250_MODULE)
+
+UNUSUAL_DEV(0x0cf2, 0x6250, 0x0000, 0x9999,
+		"ENE",
+		"ENE UB6250 reader",
+		USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0),
+
+#endif /* defined(CONFIG_USB_STORAGE_ENE_UB6250) || ... */
diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h
new file mode 100644
index 0000000..3236e03
--- /dev/null
+++ b/drivers/usb/storage/unusual_realtek.h
@@ -0,0 +1,41 @@
+/* Driver for Realtek RTS51xx USB card reader
+ *
+ * Copyright(c) 2009 Realtek Semiconductor Corp. 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, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * 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/>.
+ *
+ * Author:
+ *   wwang (wei_wang@realsil.com.cn)
+ *   No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China
+ */
+
+#if defined(CONFIG_USB_STORAGE_REALTEK) || \
+		defined(CONFIG_USB_STORAGE_REALTEK_MODULE)
+
+UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
+		"Realtek",
+		"USB Card Reader",
+		USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
+
+UNUSUAL_DEV(0x0bda, 0x0158, 0x0000, 0x9999,
+		"Realtek",
+		"USB Card Reader",
+		USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
+
+UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999,
+		"Realtek",
+		"USB Card Reader",
+		USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
+
+#endif  /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c
index 468bde7..b969279 100644
--- a/drivers/usb/storage/usual-tables.c
+++ b/drivers/usb/storage/usual-tables.c
@@ -80,11 +80,13 @@ static struct ignore_entry ignore_ids[] = {
 #	include "unusual_alauda.h"
 #	include "unusual_cypress.h"
 #	include "unusual_datafab.h"
+#	include "unusual_ene_ub6250.h"
 #	include "unusual_freecom.h"
 #	include "unusual_isd200.h"
 #	include "unusual_jumpshot.h"
 #	include "unusual_karma.h"
 #	include "unusual_onetouch.h"
+#	include "unusual_realtek.h"
 #	include "unusual_sddr09.h"
 #	include "unusual_sddr55.h"
 #	include "unusual_usbat.h"
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c
index a68ad7a..c175b73 100644
--- a/drivers/usb/wusbcore/rh.c
+++ b/drivers/usb/wusbcore/rh.c
@@ -156,7 +156,7 @@ int wusbhc_rh_status_data(struct usb_hcd *usb_hcd, char *_buf)
 EXPORT_SYMBOL_GPL(wusbhc_rh_status_data);
 
 /*
- * Return the hub's desciptor
+ * Return the hub's descriptor
  *
  * NOTE: almost cut and paste from ehci-hub.c
  *
@@ -184,8 +184,8 @@ static int wusbhc_rh_get_hub_descr(struct wusbhc *wusbhc, u16 wValue,
 	descr->bPwrOn2PwrGood = 0;
 	descr->bHubContrCurrent = 0;
 	/* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-	memset(&descr->bitmap[0], 0, temp);
-	memset(&descr->bitmap[temp], 0xff, temp);
+	memset(&descr->u.hs.DeviceRemovable[0], 0, temp);
+	memset(&descr->u.hs.DeviceRemovable[temp], 0xff, temp);
 	return 0;
 }
 
diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c
index 2054d4e..0faca16 100644
--- a/drivers/usb/wusbcore/wusbhc.c
+++ b/drivers/usb/wusbcore/wusbhc.c
@@ -320,7 +320,7 @@ u8 wusb_cluster_id_get(void)
 	u8 id;
 	spin_lock(&wusb_cluster_ids_lock);
 	id = find_first_zero_bit(wusb_cluster_id_table, CLUSTER_IDS);
-	if (id > CLUSTER_IDS) {
+	if (id >= CLUSTER_IDS) {
 		id = 0;
 		goto out;
 	}
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h
index 3d94c42..6bd426b 100644
--- a/drivers/usb/wusbcore/wusbhc.h
+++ b/drivers/usb/wusbcore/wusbhc.h
@@ -132,7 +132,7 @@ static inline void wusb_dev_put(struct wusb_dev *wusb_dev)
 }
 
 /**
- * Wireless USB Host Controlller root hub "fake" ports
+ * Wireless USB Host Controller root hub "fake" ports
  * (state and device information)
  *
  * Wireless USB is wireless, so there are no ports; but we
diff --git a/drivers/uwb/scan.c b/drivers/uwb/scan.c
index 76a1a1e..367aa12 100644
--- a/drivers/uwb/scan.c
+++ b/drivers/uwb/scan.c
@@ -42,7 +42,7 @@
 /**
  * Start/stop scanning in a radio controller
  *
- * @rc:      UWB Radio Controlller
+ * @rc:      UWB Radio Controller
  * @channel: Channel to scan; encodings in WUSB1.0[Table 5.12]
  * @type:    Type of scanning to do.
  * @bpst_offset: value at which to start scanning (if type ==
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index f616cef..2f7c76a 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -60,6 +60,7 @@ static int move_iovec_hdr(struct iovec *from, struct iovec *to,
 {
 	int seg = 0;
 	size_t size;
+
 	while (len && seg < iov_count) {
 		size = min(from->iov_len, len);
 		to->iov_base = from->iov_base;
@@ -79,6 +80,7 @@ static void copy_iovec_hdr(const struct iovec *from, struct iovec *to,
 {
 	int seg = 0;
 	size_t size;
+
 	while (len && seg < iovcount) {
 		size = min(from->iov_len, len);
 		to->iov_base = from->iov_base;
@@ -211,12 +213,13 @@ static int peek_head_len(struct sock *sk)
 {
 	struct sk_buff *head;
 	int len = 0;
+	unsigned long flags;
 
-	lock_sock(sk);
+	spin_lock_irqsave(&sk->sk_receive_queue.lock, flags);
 	head = skb_peek(&sk->sk_receive_queue);
-	if (head)
+	if (likely(head))
 		len = head->len;
-	release_sock(sk);
+	spin_unlock_irqrestore(&sk->sk_receive_queue.lock, flags);
 	return len;
 }
 
@@ -227,6 +230,7 @@ static int peek_head_len(struct sock *sk)
  * @iovcount	- returned count of io vectors we fill
  * @log		- vhost log
  * @log_num	- log offset
+ * @quota       - headcount quota, 1 for big buffer
  *	returns number of buffer heads allocated, negative on error
  */
 static int get_rx_bufs(struct vhost_virtqueue *vq,
@@ -234,7 +238,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
 		       int datalen,
 		       unsigned *iovcount,
 		       struct vhost_log *log,
-		       unsigned *log_num)
+		       unsigned *log_num,
+		       unsigned int quota)
 {
 	unsigned int out, in;
 	int seg = 0;
@@ -242,7 +247,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
 	unsigned d;
 	int r, nlogs = 0;
 
-	while (datalen > 0) {
+	while (datalen > 0 && headcount < quota) {
 		if (unlikely(seg >= UIO_MAXIOV)) {
 			r = -ENOBUFS;
 			goto err;
@@ -282,117 +287,7 @@ err:
 
 /* Expects to be always run from workqueue - which acts as
  * read-size critical section for our kind of RCU. */
-static void handle_rx_big(struct vhost_net *net)
-{
-	struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
-	unsigned out, in, log, s;
-	int head;
-	struct vhost_log *vq_log;
-	struct msghdr msg = {
-		.msg_name = NULL,
-		.msg_namelen = 0,
-		.msg_control = NULL, /* FIXME: get and handle RX aux data. */
-		.msg_controllen = 0,
-		.msg_iov = vq->iov,
-		.msg_flags = MSG_DONTWAIT,
-	};
-
-	struct virtio_net_hdr hdr = {
-		.flags = 0,
-		.gso_type = VIRTIO_NET_HDR_GSO_NONE
-	};
-
-	size_t len, total_len = 0;
-	int err;
-	size_t hdr_size;
-	/* TODO: check that we are running from vhost_worker? */
-	struct socket *sock = rcu_dereference_check(vq->private_data, 1);
-	if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
-		return;
-
-	mutex_lock(&vq->mutex);
-	vhost_disable_notify(vq);
-	hdr_size = vq->vhost_hlen;
-
-	vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
-		vq->log : NULL;
-
-	for (;;) {
-		head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
-					 ARRAY_SIZE(vq->iov),
-					 &out, &in,
-					 vq_log, &log);
-		/* On error, stop handling until the next kick. */
-		if (unlikely(head < 0))
-			break;
-		/* OK, now we need to know about added descriptors. */
-		if (head == vq->num) {
-			if (unlikely(vhost_enable_notify(vq))) {
-				/* They have slipped one in as we were
-				 * doing that: check again. */
-				vhost_disable_notify(vq);
-				continue;
-			}
-			/* Nothing new?  Wait for eventfd to tell us
-			 * they refilled. */
-			break;
-		}
-		/* We don't need to be notified again. */
-		if (out) {
-			vq_err(vq, "Unexpected descriptor format for RX: "
-			       "out %d, int %d\n",
-			       out, in);
-			break;
-		}
-		/* Skip header. TODO: support TSO/mergeable rx buffers. */
-		s = move_iovec_hdr(vq->iov, vq->hdr, hdr_size, in);
-		msg.msg_iovlen = in;
-		len = iov_length(vq->iov, in);
-		/* Sanity check */
-		if (!len) {
-			vq_err(vq, "Unexpected header len for RX: "
-			       "%zd expected %zd\n",
-			       iov_length(vq->hdr, s), hdr_size);
-			break;
-		}
-		err = sock->ops->recvmsg(NULL, sock, &msg,
-					 len, MSG_DONTWAIT | MSG_TRUNC);
-		/* TODO: Check specific error and bomb out unless EAGAIN? */
-		if (err < 0) {
-			vhost_discard_vq_desc(vq, 1);
-			break;
-		}
-		/* TODO: Should check and handle checksum. */
-		if (err > len) {
-			pr_debug("Discarded truncated rx packet: "
-				 " len %d > %zd\n", err, len);
-			vhost_discard_vq_desc(vq, 1);
-			continue;
-		}
-		len = err;
-		err = memcpy_toiovec(vq->hdr, (unsigned char *)&hdr, hdr_size);
-		if (err) {
-			vq_err(vq, "Unable to write vnet_hdr at addr %p: %d\n",
-			       vq->iov->iov_base, err);
-			break;
-		}
-		len += hdr_size;
-		vhost_add_used_and_signal(&net->dev, vq, head, len);
-		if (unlikely(vq_log))
-			vhost_log_write(vq, vq_log, log, len);
-		total_len += len;
-		if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
-			vhost_poll_queue(&vq->poll);
-			break;
-		}
-	}
-
-	mutex_unlock(&vq->mutex);
-}
-
-/* Expects to be always run from workqueue - which acts as
- * read-size critical section for our kind of RCU. */
-static void handle_rx_mergeable(struct vhost_net *net)
+static void handle_rx(struct vhost_net *net)
 {
 	struct vhost_virtqueue *vq = &net->dev.vqs[VHOST_NET_VQ_RX];
 	unsigned uninitialized_var(in), log;
@@ -405,19 +300,18 @@ static void handle_rx_mergeable(struct vhost_net *net)
 		.msg_iov = vq->iov,
 		.msg_flags = MSG_DONTWAIT,
 	};
-
 	struct virtio_net_hdr_mrg_rxbuf hdr = {
 		.hdr.flags = 0,
 		.hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
 	};
-
 	size_t total_len = 0;
-	int err, headcount;
+	int err, headcount, mergeable;
 	size_t vhost_hlen, sock_hlen;
 	size_t vhost_len, sock_len;
 	/* TODO: check that we are running from vhost_worker? */
 	struct socket *sock = rcu_dereference_check(vq->private_data, 1);
-	if (!sock || skb_queue_empty(&sock->sk->sk_receive_queue))
+
+	if (!sock)
 		return;
 
 	mutex_lock(&vq->mutex);
@@ -427,12 +321,14 @@ static void handle_rx_mergeable(struct vhost_net *net)
 
 	vq_log = unlikely(vhost_has_feature(&net->dev, VHOST_F_LOG_ALL)) ?
 		vq->log : NULL;
+	mergeable = vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF);
 
 	while ((sock_len = peek_head_len(sock->sk))) {
 		sock_len += sock_hlen;
 		vhost_len = sock_len + vhost_hlen;
 		headcount = get_rx_bufs(vq, vq->heads, vhost_len,
-					&in, vq_log, &log);
+					&in, vq_log, &log,
+					likely(mergeable) ? UIO_MAXIOV : 1);
 		/* On error, stop handling until the next kick. */
 		if (unlikely(headcount < 0))
 			break;
@@ -476,7 +372,7 @@ static void handle_rx_mergeable(struct vhost_net *net)
 			break;
 		}
 		/* TODO: Should check and handle checksum. */
-		if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF) &&
+		if (likely(mergeable) &&
 		    memcpy_toiovecend(vq->hdr, (unsigned char *)&headcount,
 				      offsetof(typeof(hdr), num_buffers),
 				      sizeof hdr.num_buffers)) {
@@ -498,14 +394,6 @@ static void handle_rx_mergeable(struct vhost_net *net)
 	mutex_unlock(&vq->mutex);
 }
 
-static void handle_rx(struct vhost_net *net)
-{
-	if (vhost_has_feature(&net->dev, VIRTIO_NET_F_MRG_RXBUF))
-		handle_rx_mergeable(net);
-	else
-		handle_rx_big(net);
-}
-
 static void handle_tx_kick(struct vhost_work *work)
 {
 	struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue,
@@ -654,6 +542,7 @@ static struct socket *get_raw_socket(int fd)
 	} uaddr;
 	int uaddr_len = sizeof uaddr, r;
 	struct socket *sock = sockfd_lookup(fd, &r);
+
 	if (!sock)
 		return ERR_PTR(-ENOTSOCK);
 
@@ -682,6 +571,7 @@ static struct socket *get_tap_socket(int fd)
 {
 	struct file *file = fget(fd);
 	struct socket *sock;
+
 	if (!file)
 		return ERR_PTR(-EBADF);
 	sock = tun_get_socket(file);
@@ -696,6 +586,7 @@ static struct socket *get_tap_socket(int fd)
 static struct socket *get_socket(int fd)
 {
 	struct socket *sock;
+
 	/* special case to disable backend */
 	if (fd == -1)
 		return NULL;
@@ -741,9 +632,9 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
 	oldsock = rcu_dereference_protected(vq->private_data,
 					    lockdep_is_held(&vq->mutex));
 	if (sock != oldsock) {
-                vhost_net_disable_vq(n, vq);
-                rcu_assign_pointer(vq->private_data, sock);
-                vhost_net_enable_vq(n, vq);
+		vhost_net_disable_vq(n, vq);
+		rcu_assign_pointer(vq->private_data, sock);
+		vhost_net_enable_vq(n, vq);
 	}
 
 	mutex_unlock(&vq->mutex);
@@ -768,6 +659,7 @@ static long vhost_net_reset_owner(struct vhost_net *n)
 	struct socket *tx_sock = NULL;
 	struct socket *rx_sock = NULL;
 	long err;
+
 	mutex_lock(&n->dev.mutex);
 	err = vhost_dev_check_owner(&n->dev);
 	if (err)
@@ -829,6 +721,7 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
 	struct vhost_vring_file backend;
 	u64 features;
 	int r;
+
 	switch (ioctl) {
 	case VHOST_NET_SET_BACKEND:
 		if (copy_from_user(&backend, argp, sizeof backend))
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index ade0568..2ab2912 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -41,8 +41,8 @@ static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
 			    poll_table *pt)
 {
 	struct vhost_poll *poll;
-	poll = container_of(pt, struct vhost_poll, table);
 
+	poll = container_of(pt, struct vhost_poll, table);
 	poll->wqh = wqh;
 	add_wait_queue(wqh, &poll->wait);
 }
@@ -85,6 +85,7 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
 void vhost_poll_start(struct vhost_poll *poll, struct file *file)
 {
 	unsigned long mask;
+
 	mask = file->f_op->poll(file, &poll->table);
 	if (mask)
 		vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask);
@@ -101,6 +102,7 @@ static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work,
 				unsigned seq)
 {
 	int left;
+
 	spin_lock_irq(&dev->work_lock);
 	left = seq - work->done_seq;
 	spin_unlock_irq(&dev->work_lock);
@@ -222,6 +224,7 @@ static int vhost_worker(void *data)
 static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
 {
 	int i;
+
 	for (i = 0; i < dev->nvqs; ++i) {
 		dev->vqs[i].indirect = kmalloc(sizeof *dev->vqs[i].indirect *
 					       UIO_MAXIOV, GFP_KERNEL);
@@ -235,6 +238,7 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
 			goto err_nomem;
 	}
 	return 0;
+
 err_nomem:
 	for (; i >= 0; --i) {
 		kfree(dev->vqs[i].indirect);
@@ -247,6 +251,7 @@ err_nomem:
 static void vhost_dev_free_iovecs(struct vhost_dev *dev)
 {
 	int i;
+
 	for (i = 0; i < dev->nvqs; ++i) {
 		kfree(dev->vqs[i].indirect);
 		dev->vqs[i].indirect = NULL;
@@ -296,26 +301,28 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
 }
 
 struct vhost_attach_cgroups_struct {
-        struct vhost_work work;
-        struct task_struct *owner;
-        int ret;
+	struct vhost_work work;
+	struct task_struct *owner;
+	int ret;
 };
 
 static void vhost_attach_cgroups_work(struct vhost_work *work)
 {
-        struct vhost_attach_cgroups_struct *s;
-        s = container_of(work, struct vhost_attach_cgroups_struct, work);
-        s->ret = cgroup_attach_task_all(s->owner, current);
+	struct vhost_attach_cgroups_struct *s;
+
+	s = container_of(work, struct vhost_attach_cgroups_struct, work);
+	s->ret = cgroup_attach_task_all(s->owner, current);
 }
 
 static int vhost_attach_cgroups(struct vhost_dev *dev)
 {
-        struct vhost_attach_cgroups_struct attach;
-        attach.owner = current;
-        vhost_work_init(&attach.work, vhost_attach_cgroups_work);
-        vhost_work_queue(dev, &attach.work);
-        vhost_work_flush(dev, &attach.work);
-        return attach.ret;
+	struct vhost_attach_cgroups_struct attach;
+
+	attach.owner = current;
+	vhost_work_init(&attach.work, vhost_attach_cgroups_work);
+	vhost_work_queue(dev, &attach.work);
+	vhost_work_flush(dev, &attach.work);
+	return attach.ret;
 }
 
 /* Caller should have device mutex */
@@ -323,11 +330,13 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
 {
 	struct task_struct *worker;
 	int err;
+
 	/* Is there an owner already? */
 	if (dev->mm) {
 		err = -EBUSY;
 		goto err_mm;
 	}
+
 	/* No owner, become one */
 	dev->mm = get_task_mm(current);
 	worker = kthread_create(vhost_worker, dev, "vhost-%d", current->pid);
@@ -380,6 +389,7 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
 void vhost_dev_cleanup(struct vhost_dev *dev)
 {
 	int i;
+
 	for (i = 0; i < dev->nvqs; ++i) {
 		if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
 			vhost_poll_stop(&dev->vqs[i].poll);
@@ -421,6 +431,7 @@ void vhost_dev_cleanup(struct vhost_dev *dev)
 static int log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
 {
 	u64 a = addr / VHOST_PAGE_SIZE / 8;
+
 	/* Make sure 64 bit math will not overflow. */
 	if (a > ULONG_MAX - (unsigned long)log_base ||
 	    a + (unsigned long)log_base > ULONG_MAX)
@@ -461,6 +472,7 @@ static int memory_access_ok(struct vhost_dev *d, struct vhost_memory *mem,
 			    int log_all)
 {
 	int i;
+
 	for (i = 0; i < d->nvqs; ++i) {
 		int ok;
 		mutex_lock(&d->vqs[i].mutex);
@@ -527,6 +539,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
 {
 	struct vhost_memory mem, *newmem, *oldmem;
 	unsigned long size = offsetof(struct vhost_memory, regions);
+
 	if (copy_from_user(&mem, m, size))
 		return -EFAULT;
 	if (mem.padding)
@@ -544,7 +557,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
 		return -EFAULT;
 	}
 
-	if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) {
+	if (!memory_access_ok(d, newmem,
+			      vhost_has_feature(d, VHOST_F_LOG_ALL))) {
 		kfree(newmem);
 		return -EFAULT;
 	}
@@ -560,6 +574,7 @@ static int init_used(struct vhost_virtqueue *vq,
 		     struct vring_used __user *used)
 {
 	int r = put_user(vq->used_flags, &used->flags);
+
 	if (r)
 		return r;
 	return get_user(vq->last_used_idx, &used->idx);
@@ -849,6 +864,7 @@ static const struct vhost_memory_region *find_region(struct vhost_memory *mem,
 {
 	struct vhost_memory_region *reg;
 	int i;
+
 	/* linear search is not brilliant, but we really have on the order of 6
 	 * regions in practice */
 	for (i = 0; i < mem->nregions; ++i) {
@@ -871,6 +887,7 @@ static int set_bit_to_user(int nr, void __user *addr)
 	void *base;
 	int bit = nr + (log % PAGE_SIZE) * 8;
 	int r;
+
 	r = get_user_pages_fast(log, 1, 1, &page);
 	if (r < 0)
 		return r;
@@ -888,6 +905,7 @@ static int log_write(void __user *log_base,
 {
 	u64 write_page = write_address / VHOST_PAGE_SIZE;
 	int r;
+
 	if (!write_length)
 		return 0;
 	write_length += write_address % VHOST_PAGE_SIZE;
@@ -1037,8 +1055,8 @@ static int get_indirect(struct vhost_dev *dev, struct vhost_virtqueue *vq,
 			       i, count);
 			return -EINVAL;
 		}
-		if (unlikely(memcpy_fromiovec((unsigned char *)&desc, vq->indirect,
-					      sizeof desc))) {
+		if (unlikely(memcpy_fromiovec((unsigned char *)&desc,
+					      vq->indirect, sizeof desc))) {
 			vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n",
 			       i, (size_t)indirect->addr + i * sizeof desc);
 			return -EINVAL;
@@ -1153,7 +1171,7 @@ int vhost_get_vq_desc(struct vhost_dev *dev, struct vhost_virtqueue *vq,
 			       i, vq->num, head);
 			return -EINVAL;
 		}
-		ret = copy_from_user(&desc, vq->desc + i, sizeof desc);
+		ret = __copy_from_user(&desc, vq->desc + i, sizeof desc);
 		if (unlikely(ret)) {
 			vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
 			       i, vq->desc + i);
@@ -1317,6 +1335,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
 void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq)
 {
 	__u16 flags;
+
 	/* Flush out used index updates. This is paired
 	 * with the barrier that the Guest executes when enabling
 	 * interrupts. */
@@ -1361,6 +1380,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq)
 {
 	u16 avail_idx;
 	int r;
+
 	if (!(vq->used_flags & VRING_USED_F_NO_NOTIFY))
 		return false;
 	vq->used_flags &= ~VRING_USED_F_NO_NOTIFY;
@@ -1387,6 +1407,7 @@ bool vhost_enable_notify(struct vhost_virtqueue *vq)
 void vhost_disable_notify(struct vhost_virtqueue *vq)
 {
 	int r;
+
 	if (vq->used_flags & VRING_USED_F_NO_NOTIFY)
 		return;
 	vq->used_flags |= VRING_USED_F_NO_NOTIFY;
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6bafb51b..e6a8d8c 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -322,69 +322,6 @@ config FB_ARMCLCD
 	  here and read <file:Documentation/kbuild/modules.txt>.  The module
 	  will be called amba-clcd.
 
-choice
-
-	depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X)
-	prompt "LCD Panel"
-	default FB_ARMCLCD_SHARP_LQ035Q7DB02
-
-config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
-	bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC"
-	help
-	  This is an implementation of the Sharp LQ035Q7DB02, a 3.5"
-	  color QVGA, HRTFT panel.  The LogicPD device includes
-	  an integrated HRTFT controller IC.
-	  The native resolution is 240x320.
-
-config FB_ARMCLCD_SHARP_LQ057Q3DC02
-	bool "LogicPD LCD 5.7\" QVGA"
-	help
-	  This is an implementation of the Sharp LQ057Q3DC02, a 5.7"
-	  color QVGA, TFT panel.  The LogicPD device includes an
-	  The native resolution is 320x240.
-
-config FB_ARMCLCD_SHARP_LQ64D343
-	bool "LogicPD LCD 6.4\" VGA"
-	help
-	  This is an implementation of the Sharp LQ64D343, a 6.4"
-	  color VGA, TFT panel.  The LogicPD device includes an
-	  The native resolution is 640x480.
-
-config FB_ARMCLCD_SHARP_LQ10D368
-	bool "LogicPD LCD 10.4\" VGA"
-	help
-	  This is an implementation of the Sharp LQ10D368, a 10.4"
-	  color VGA, TFT panel.  The LogicPD device includes an
-	  The native resolution is 640x480.
-
-
-config FB_ARMCLCD_SHARP_LQ121S1DG41
-	bool "LogicPD LCD 12.1\" SVGA"
-	help
-	  This is an implementation of the Sharp LQ121S1DG41, a 12.1"
-	  color SVGA, TFT panel.  The LogicPD device includes an
-	  The native resolution is 800x600.
-
-	  This panel requires a clock rate may be an integer fraction
-	  of the base LCDCLK frequency.  The driver will select the
-	  highest frequency available that is lower than the maximum
-	  allowed.  The panel may flicker if the clock rate is
-	  slower than the recommended minimum.
-
-config FB_ARMCLCD_AUO_A070VW01_WIDE
-	bool "AU Optronics A070VW01 LCD 7.0\" WIDE"
-	help
-	  This is an implementation of the AU Optronics, a 7.0"
-	  WIDE Color.  The native resolution is 234x480.
-
-config FB_ARMCLCD_HITACHI
-	bool "Hitachi Wide Screen 800x480"
-	help
-	  This is an implementation of the Hitachi 800x480.
-
-endchoice
-
-
 config FB_ACORN
 	bool "Acorn VIDC support"
 	depends on (FB = y) && ARM && ARCH_ACORN
@@ -439,6 +376,24 @@ config FB_CYBER2000
 	  Say Y if you have a NetWinder or a graphics card containing this
 	  device, otherwise say N.
 
+config FB_CYBER2000_DDC
+	bool "DDC for CyberPro support"
+	depends on FB_CYBER2000
+	select FB_DDC
+	default y
+	help
+	  Say Y here if you want DDC support for your CyberPro graphics
+	  card. This is only I2C bus support, driver does not use EDID.
+
+config FB_CYBER2000_I2C
+	bool "CyberPro 2000/2010/5000 I2C support"
+	depends on FB_CYBER2000 && I2C && ARCH_NETWINDER
+	select I2C_ALGOBIT
+	help
+	  Enable support for the I2C video decoder interface on the
+	  Integraphics CyberPro 20x0 and 5000 VGA chips.  This is used
+	  on the Netwinder machines for the SAA7111 video capture.
+
 config FB_APOLLO
 	bool
 	depends on (FB = y) && APOLLO
@@ -2005,6 +1960,7 @@ config FB_SH_MOBILE_LCDC
 	select FB_SYS_IMAGEBLIT
 	select FB_SYS_FOPS
 	select FB_DEFERRED_IO
+	select FB_BACKLIGHT
 	select SH_MIPI_DSI if SH_LCD_MIPI_DSI
 	---help---
 	  Frame buffer driver for the on-chip SH-Mobile LCD controller.
@@ -2365,6 +2321,26 @@ config FB_JZ4740
 	help
 	  Framebuffer support for the JZ4740 SoC.
 
+config FB_MXS
+	tristate "MXS LCD framebuffer support"
+	depends on FB && ARCH_MXS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  Framebuffer support for the MXS SoC.
+
+config FB_PUV3_UNIGFX
+	tristate "PKUnity v3 Unigfx framebuffer support"
+	depends on FB && UNICORE32 && ARCH_PUV3
+	select FB_SYS_FILLRECT
+	select FB_SYS_COPYAREA
+	select FB_SYS_IMAGEBLIT
+	select FB_SYS_FOPS
+	help
+	  Choose this option if you want to use the Unigfx device as a
+	  framebuffer device. Without the support of PCI & AGP.
+
 source "drivers/video/omap/Kconfig"
 source "drivers/video/omap2/Kconfig"
 
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 8c8fabd..2ea44b6 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -139,6 +139,7 @@ obj-$(CONFIG_FB_MB862XX)	  += mb862xx/
 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
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_UVESA)            += uvesafb.o
@@ -153,6 +154,7 @@ obj-$(CONFIG_FB_BFIN_T350MCQB)	  += bfin-t350mcqb-fb.o
 obj-$(CONFIG_FB_BFIN_7393)        += bfin_adv7393fb.o
 obj-$(CONFIG_FB_MX3)		  += mx3fb.o
 obj-$(CONFIG_FB_DA8XX)		  += da8xx-fb.o
+obj-$(CONFIG_FB_MXS)		  += mxsfb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index 1c2c683..013c8ce 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -461,7 +461,7 @@ static int clcdfb_register(struct clcd_fb *fb)
 	return ret;
 }
 
-static int clcdfb_probe(struct amba_device *dev, struct amba_id *id)
+static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct clcd_board *board = dev->dev.platform_data;
 	struct clcd_fb *fb;
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index bac16345..4b4e8da 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -127,6 +127,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo)
 		return;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bl = backlight_device_register("backlight", &sinfo->pdev->dev, sinfo,
 				       &atmel_lcdc_bl_ops, &props);
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index 4cb6a57..b0b2ac3 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -1818,6 +1818,7 @@ static void aty128_bl_init(struct aty128fb_par *par)
 	snprintf(name, sizeof(name), "aty128bl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &aty128_bl_data,
 				       &props);
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 94e293f..d437b3d 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -2241,6 +2241,7 @@ static void aty_bl_init(struct atyfb_par *par)
 	snprintf(name, sizeof(name), "atybl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &aty_bl_data,
 				       &props);
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
index 9b811dd..db572df 100644
--- a/drivers/video/aty/radeon_backlight.c
+++ b/drivers/video/aty/radeon_backlight.c
@@ -158,6 +158,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo)
 	snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, rinfo->info->dev, pdata,
 				       &radeon_bl_data, &props);
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
index b224396..e59623a 100644
--- a/drivers/video/backlight/88pm860x_bl.c
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -227,6 +227,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = MAX_BRIGHTNESS;
 	bl = backlight_device_register(name, &pdev->dev, data,
 					&pm860x_backlight_ops, &props);
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index e54a337..0c9373b 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -109,6 +109,14 @@ config LCD_S6E63M0
 	  If you have an S6E63M0 LCD Panel, say Y to enable its
 	  LCD control driver.
 
+config LCD_LD9040
+	tristate "LD9040 AMOLED LCD Driver"
+	depends on SPI && BACKLIGHT_CLASS_DEVICE
+	default n
+	help
+	  If you have an LD9040 Panel, say Y to enable its
+	  control driver.
+
 endif # LCD_CLASS_DEVICE
 
 #
@@ -236,12 +244,12 @@ config BACKLIGHT_MAX8925
 	  If you have a LCD backlight connected to the WLED output of MAX8925
 	  WLED output, say Y here to enable this driver.
 
-config BACKLIGHT_MBP_NVIDIA
-       tristate "MacBook Pro Nvidia Backlight Driver"
-       depends on X86
+config BACKLIGHT_APPLE
+       tristate "Apple Backlight Driver"
+       depends on X86 && ACPI
        help
-         If you have an Apple Macbook Pro with Nvidia graphics hardware say Y
-	 to enable a driver for its backlight
+         If you have an Intel-based Apple say Y to enable a driver for its
+	 backlight.
 
 config BACKLIGHT_TOSA
 	tristate "Sharp SL-6000 Backlight Driver"
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 44c0f81..b9ca849 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_LCD_VGG2432A4)	   += vgg2432a4.o
 obj-$(CONFIG_LCD_TDO24M)	   += tdo24m.o
 obj-$(CONFIG_LCD_TOSA)		   += tosa_lcd.o
 obj-$(CONFIG_LCD_S6E63M0)	+= s6e63m0.o
+obj-$(CONFIG_LCD_LD9040)	+= ld9040.o
 
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM)    += atmel-pwm-bl.o
@@ -26,7 +27,7 @@ obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)	+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_DA903X)	+= da903x_bl.o
 obj-$(CONFIG_BACKLIGHT_MAX8925)	+= max8925_bl.o
-obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
+obj-$(CONFIG_BACKLIGHT_APPLE)	+= apple_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)	+= tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_SAHARA)	+= kb3886_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)	+= wm831x_bl.o
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index 9f436e0..af31197 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -303,6 +303,7 @@ static int __devinit adp5520_bl_probe(struct platform_device *pdev)
 	mutex_init(&data->lock);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = ADP5020_MAX_BRIGHTNESS;
 	bl = backlight_device_register(pdev->name, data->master, data,
 				       &adp5520_bl_ops, &props);
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index 734c650..d2a96a4 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -709,6 +709,7 @@ static int __devinit adp8860_probe(struct i2c_client *client,
 	i2c_set_clientdata(client, data);
 
 	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = ADP8860_MAX_BRIGHTNESS;
 
 	mutex_init(&data->lock);
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c
index fe9af12..c861c41 100644
--- a/drivers/video/backlight/adx_bl.c
+++ b/drivers/video/backlight/adx_bl.c
@@ -104,6 +104,7 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev,
 					  bl, &adx_backlight_ops, &props);
diff --git a/drivers/video/backlight/apple_bl.c b/drivers/video/backlight/apple_bl.c
new file mode 100644
index 0000000..be98d15
--- /dev/null
+++ b/drivers/video/backlight/apple_bl.c
@@ -0,0 +1,241 @@
+/*
+ *  Backlight Driver for Intel-based Apples
+ *
+ *  Copyright (c) Red Hat <mjg@redhat.com>
+ *  Based on code from Pommed:
+ *  Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
+ *  Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
+ *  Copyright (C) 2007 Julien BLACHE <jb@jblache.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 driver triggers SMIs which cause the firmware to change the
+ *  backlight brightness. This is icky in many ways, but it's impractical to
+ *  get at the firmware code in order to figure out what it's actually doing.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/acpi.h>
+
+static struct backlight_device *apple_backlight_device;
+
+struct hw_data {
+	/* I/O resource to allocate. */
+	unsigned long iostart;
+	unsigned long iolen;
+	/* Backlight operations structure. */
+	const struct backlight_ops backlight_ops;
+	void (*set_brightness)(int);
+};
+
+static const struct hw_data *hw_data;
+
+#define DRIVER "apple_backlight: "
+
+/* Module parameters. */
+static int debug;
+module_param_named(debug, debug, int, 0644);
+MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
+
+/*
+ * Implementation for machines with Intel chipset.
+ */
+static void intel_chipset_set_brightness(int intensity)
+{
+	outb(0x04 | (intensity << 4), 0xb3);
+	outb(0xbf, 0xb2);
+}
+
+static int intel_chipset_send_intensity(struct backlight_device *bd)
+{
+	int intensity = bd->props.brightness;
+
+	if (debug)
+		printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
+		       intensity);
+
+	intel_chipset_set_brightness(intensity);
+	return 0;
+}
+
+static int intel_chipset_get_intensity(struct backlight_device *bd)
+{
+	int intensity;
+
+	outb(0x03, 0xb3);
+	outb(0xbf, 0xb2);
+	intensity = inb(0xb3) >> 4;
+
+	if (debug)
+		printk(KERN_DEBUG DRIVER "read brightness of %d\n",
+		       intensity);
+
+	return intensity;
+}
+
+static const struct hw_data intel_chipset_data = {
+	.iostart = 0xb2,
+	.iolen = 2,
+	.backlight_ops	= {
+		.options	= BL_CORE_SUSPENDRESUME,
+		.get_brightness	= intel_chipset_get_intensity,
+		.update_status	= intel_chipset_send_intensity,
+	},
+	.set_brightness = intel_chipset_set_brightness,
+};
+
+/*
+ * Implementation for machines with Nvidia chipset.
+ */
+static void nvidia_chipset_set_brightness(int intensity)
+{
+	outb(0x04 | (intensity << 4), 0x52f);
+	outb(0xbf, 0x52e);
+}
+
+static int nvidia_chipset_send_intensity(struct backlight_device *bd)
+{
+	int intensity = bd->props.brightness;
+
+	if (debug)
+		printk(KERN_DEBUG DRIVER "setting brightness to %d\n",
+		       intensity);
+
+	nvidia_chipset_set_brightness(intensity);
+	return 0;
+}
+
+static int nvidia_chipset_get_intensity(struct backlight_device *bd)
+{
+	int intensity;
+
+	outb(0x03, 0x52f);
+	outb(0xbf, 0x52e);
+	intensity = inb(0x52f) >> 4;
+
+	if (debug)
+		printk(KERN_DEBUG DRIVER "read brightness of %d\n",
+		       intensity);
+
+	return intensity;
+}
+
+static const struct hw_data nvidia_chipset_data = {
+	.iostart = 0x52e,
+	.iolen = 2,
+	.backlight_ops		= {
+		.options	= BL_CORE_SUSPENDRESUME,
+		.get_brightness	= nvidia_chipset_get_intensity,
+		.update_status	= nvidia_chipset_send_intensity
+	},
+	.set_brightness = nvidia_chipset_set_brightness,
+};
+
+static int __devinit apple_bl_add(struct acpi_device *dev)
+{
+	struct backlight_properties props;
+	struct pci_dev *host;
+	int intensity;
+
+	host = pci_get_bus_and_slot(0, 0);
+
+	if (!host) {
+		printk(KERN_ERR DRIVER "unable to find PCI host\n");
+		return -ENODEV;
+	}
+
+	if (host->vendor == PCI_VENDOR_ID_INTEL)
+		hw_data = &intel_chipset_data;
+	else if (host->vendor == PCI_VENDOR_ID_NVIDIA)
+		hw_data = &nvidia_chipset_data;
+
+	pci_dev_put(host);
+
+	if (!hw_data) {
+		printk(KERN_ERR DRIVER "unknown hardware\n");
+		return -ENODEV;
+	}
+
+	/* Check that the hardware responds - this may not work under EFI */
+
+	intensity = hw_data->backlight_ops.get_brightness(NULL);
+
+	if (!intensity) {
+		hw_data->set_brightness(1);
+		if (!hw_data->backlight_ops.get_brightness(NULL))
+			return -ENODEV;
+
+		hw_data->set_brightness(0);
+	}
+
+	if (!request_region(hw_data->iostart, hw_data->iolen,
+			    "Apple backlight"))
+		return -ENXIO;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
+	props.max_brightness = 15;
+	apple_backlight_device = backlight_device_register("apple_backlight",
+				  NULL, NULL, &hw_data->backlight_ops, &props);
+
+	if (IS_ERR(apple_backlight_device)) {
+		release_region(hw_data->iostart, hw_data->iolen);
+		return PTR_ERR(apple_backlight_device);
+	}
+
+	apple_backlight_device->props.brightness =
+		hw_data->backlight_ops.get_brightness(apple_backlight_device);
+	backlight_update_status(apple_backlight_device);
+
+	return 0;
+}
+
+static int __devexit apple_bl_remove(struct acpi_device *dev, int type)
+{
+	backlight_device_unregister(apple_backlight_device);
+
+	release_region(hw_data->iostart, hw_data->iolen);
+	hw_data = NULL;
+	return 0;
+}
+
+static const struct acpi_device_id apple_bl_ids[] = {
+	{"APP0002", 0},
+	{"", 0},
+};
+
+static struct acpi_driver apple_bl_driver = {
+	.name = "Apple backlight",
+	.ids = apple_bl_ids,
+	.ops = {
+		.add = apple_bl_add,
+		.remove = apple_bl_remove,
+	},
+};
+
+static int __init apple_bl_init(void)
+{
+	return acpi_bus_register_driver(&apple_bl_driver);
+}
+
+static void __exit apple_bl_exit(void)
+{
+	acpi_bus_unregister_driver(&apple_bl_driver);
+}
+
+module_init(apple_bl_init);
+module_exit(apple_bl_exit);
+
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_DESCRIPTION("Apple Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(acpi, apple_bl_ids);
+MODULE_ALIAS("mbp_nvidia_bl");
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c
index e6a66da..0443a4f 100644
--- a/drivers/video/backlight/atmel-pwm-bl.c
+++ b/drivers/video/backlight/atmel-pwm-bl.c
@@ -168,6 +168,7 @@ static int atmel_pwm_bl_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = pdata->pwm_duty_max - pdata->pwm_duty_min;
 	bldev = backlight_device_register("atmel-pwm-bl", &pdev->dev, pwmbl,
 					  &atmel_pwm_bl_ops, &props);
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index 0870329..80d292f 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -19,6 +19,12 @@
 #include <asm/backlight.h>
 #endif
 
+static const char const *backlight_types[] = {
+	[BACKLIGHT_RAW] = "raw",
+	[BACKLIGHT_PLATFORM] = "platform",
+	[BACKLIGHT_FIRMWARE] = "firmware",
+};
+
 #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \
 			   defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE))
 /* This callback gets called when something important happens inside a
@@ -169,6 +175,14 @@ static ssize_t backlight_store_brightness(struct device *dev,
 	return rc;
 }
 
+static ssize_t backlight_show_type(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct backlight_device *bd = to_backlight_device(dev);
+
+	return sprintf(buf, "%s\n", backlight_types[bd->props.type]);
+}
+
 static ssize_t backlight_show_max_brightness(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -234,6 +248,7 @@ static struct device_attribute bl_device_attributes[] = {
 	__ATTR(actual_brightness, 0444, backlight_show_actual_brightness,
 		     NULL),
 	__ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),
+	__ATTR(type, 0444, backlight_show_type, NULL),
 	__ATTR_NULL,
 };
 
@@ -292,9 +307,16 @@ struct backlight_device *backlight_device_register(const char *name,
 	dev_set_drvdata(&new_bd->dev, devdata);
 
 	/* Set default properties */
-	if (props)
+	if (props) {
 		memcpy(&new_bd->props, props,
 		       sizeof(struct backlight_properties));
+		if (props->type <= 0 || props->type >= BACKLIGHT_TYPE_MAX) {
+			WARN(1, "%s: invalid backlight type", name);
+			new_bd->props.type = BACKLIGHT_RAW;
+		}
+	} else {
+		new_bd->props.type = BACKLIGHT_RAW;
+	}
 
 	rc = device_register(&new_bd->dev);
 	if (rc) {
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c
index 1e71c35..af60983 100644
--- a/drivers/video/backlight/corgi_lcd.c
+++ b/drivers/video/backlight/corgi_lcd.c
@@ -562,6 +562,7 @@ static int __devinit corgi_lcd_probe(struct spi_device *spi)
 	lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = pdata->max_intensity;
 	lcd->bl_dev = backlight_device_register("corgi_bl", &spi->dev, lcd,
 						&corgi_bl_ops, &props);
diff --git a/drivers/video/backlight/cr_bllcd.c b/drivers/video/backlight/cr_bllcd.c
index 397d15e..6c8c540 100644
--- a/drivers/video/backlight/cr_bllcd.c
+++ b/drivers/video/backlight/cr_bllcd.c
@@ -193,6 +193,7 @@ static int cr_backlight_probe(struct platform_device *pdev)
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	bdp = backlight_device_register("cr-backlight", &pdev->dev, NULL,
 					&cr_backlight_ops, &props);
 	if (IS_ERR(bdp)) {
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c
index 87659ed..62043f1 100644
--- a/drivers/video/backlight/da903x_bl.c
+++ b/drivers/video/backlight/da903x_bl.c
@@ -136,6 +136,7 @@ static int da903x_backlight_probe(struct platform_device *pdev)
 		da903x_write(data->da903x_dev, DA9034_WLED_CONTROL2,
 				DA9034_WLED_ISET(pdata->output_current));
 
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = max_brightness;
 	bl = backlight_device_register(pdev->name, data->da903x_dev, data,
 				       &da903x_backlight_ops, &props);
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c
index b0cc491..9f1e389 100644
--- a/drivers/video/backlight/ep93xx_bl.c
+++ b/drivers/video/backlight/ep93xx_bl.c
@@ -87,6 +87,7 @@ static int __init ep93xxbl_probe(struct platform_device *dev)
 	ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = EP93XX_MAX_BRIGHT;
 	bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl,
 				       &ep93xxbl_ops, &props);
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 312ca61..8c6befd 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -91,6 +91,7 @@ static int genericbl_probe(struct platform_device *pdev)
 		name = machinfo->name;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = machinfo->max_intensity;
 	bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops,
 				       &props);
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index 267d23f..38aa002 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -109,6 +109,7 @@ static int __devinit hp680bl_probe(struct platform_device *pdev)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = HP680_MAX_INTENSITY;
 	bd = backlight_device_register("hp680-bl", &pdev->dev, NULL,
 				       &hp680bl_ops, &props);
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c
index 2f177b3..de65d80 100644
--- a/drivers/video/backlight/jornada720_bl.c
+++ b/drivers/video/backlight/jornada720_bl.c
@@ -106,6 +106,7 @@ static int jornada_bl_probe(struct platform_device *pdev)
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = BL_MAX_BRIGHT;
 	bd = backlight_device_register(S1D_DEVICENAME, &pdev->dev, NULL,
 				       &jornada_bl_ops, &props);
@@ -146,12 +147,12 @@ static struct platform_driver jornada_bl_driver = {
 	},
 };
 
-int __init jornada_bl_init(void)
+static int __init jornada_bl_init(void)
 {
 	return platform_driver_register(&jornada_bl_driver);
 }
 
-void __exit jornada_bl_exit(void)
+static void __exit jornada_bl_exit(void)
 {
 	platform_driver_unregister(&jornada_bl_driver);
 }
diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c
index cbbb167..d2ff658 100644
--- a/drivers/video/backlight/jornada720_lcd.c
+++ b/drivers/video/backlight/jornada720_lcd.c
@@ -135,12 +135,12 @@ static struct platform_driver jornada_lcd_driver = {
 	},
 };
 
-int __init jornada_lcd_init(void)
+static int __init jornada_lcd_init(void)
 {
 	return platform_driver_register(&jornada_lcd_driver);
 }
 
-void __exit jornada_lcd_exit(void)
+static void __exit jornada_lcd_exit(void)
 {
 	platform_driver_unregister(&jornada_lcd_driver);
 }
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c
index f439a86..72dd555 100644
--- a/drivers/video/backlight/kb3886_bl.c
+++ b/drivers/video/backlight/kb3886_bl.c
@@ -149,6 +149,7 @@ static int kb3886bl_probe(struct platform_device *pdev)
 		machinfo->limit_mask = -1;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = machinfo->max_intensity;
 	kb3886_backlight_device = backlight_device_register("kb3886-bl",
 							    &pdev->dev, NULL,
diff --git a/drivers/video/backlight/ld9040.c b/drivers/video/backlight/ld9040.c
new file mode 100644
index 0000000..7281b25
--- /dev/null
+++ b/drivers/video/backlight/ld9040.c
@@ -0,0 +1,819 @@
+/*
+ * ld9040 AMOLED LCD panel driver.
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ * Author: Donghwa Lee  <dh09.lee@samsung.com>
+ * Derived from drivers/video/backlight/s6e63m0.c
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/wait.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/lcd.h>
+#include <linux/backlight.h>
+
+#include "ld9040_gamma.h"
+
+#define SLEEPMSEC		0x1000
+#define ENDDEF			0x2000
+#define	DEFMASK			0xFF00
+#define COMMAND_ONLY		0xFE
+#define DATA_ONLY		0xFF
+
+#define MIN_BRIGHTNESS		0
+#define MAX_BRIGHTNESS		24
+#define power_is_on(pwr)	((pwr) <= FB_BLANK_NORMAL)
+
+struct ld9040 {
+	struct device			*dev;
+	struct spi_device		*spi;
+	unsigned int			power;
+	unsigned int			current_brightness;
+
+	struct lcd_device		*ld;
+	struct backlight_device		*bd;
+	struct lcd_platform_data	*lcd_pd;
+};
+
+static const unsigned short seq_swreset[] = {
+	0x01, COMMAND_ONLY,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_user_setting[] = {
+	0xF0, 0x5A,
+
+	DATA_ONLY, 0x5A,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_elvss_on[] = {
+	0xB1, 0x0D,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x16,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_gtcon[] = {
+	0xF7, 0x09,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_panel_condition[] = {
+	0xF8, 0x05,
+
+	DATA_ONLY, 0x65,
+	DATA_ONLY, 0x96,
+	DATA_ONLY, 0x71,
+	DATA_ONLY, 0x7D,
+	DATA_ONLY, 0x19,
+	DATA_ONLY, 0x3B,
+	DATA_ONLY, 0x0D,
+	DATA_ONLY, 0x19,
+	DATA_ONLY, 0x7E,
+	DATA_ONLY, 0x0D,
+	DATA_ONLY, 0xE2,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x7E,
+	DATA_ONLY, 0x7D,
+	DATA_ONLY, 0x07,
+	DATA_ONLY, 0x07,
+	DATA_ONLY, 0x20,
+	DATA_ONLY, 0x20,
+	DATA_ONLY, 0x20,
+	DATA_ONLY, 0x02,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_gamma_set1[] = {
+	0xF9, 0x00,
+
+	DATA_ONLY, 0xA7,
+	DATA_ONLY, 0xB4,
+	DATA_ONLY, 0xAE,
+	DATA_ONLY, 0xBF,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x91,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0xB2,
+	DATA_ONLY, 0xB4,
+	DATA_ONLY, 0xAA,
+	DATA_ONLY, 0xBB,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0xAC,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0xB3,
+	DATA_ONLY, 0xB1,
+	DATA_ONLY, 0xAA,
+	DATA_ONLY, 0xBC,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0xB3,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_gamma_ctrl[] = {
+	0xFB, 0x02,
+
+	DATA_ONLY, 0x5A,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_gamma_start[] = {
+	0xF9, COMMAND_ONLY,
+
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_apon[] = {
+	0xF3, 0x00,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x0A,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_display_ctrl[] = {
+	0xF2, 0x02,
+
+	DATA_ONLY, 0x08,
+	DATA_ONLY, 0x08,
+	DATA_ONLY, 0x10,
+	DATA_ONLY, 0x10,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_manual_pwr[] = {
+	0xB0, 0x04,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_pwr_ctrl[] = {
+	0xF4, 0x0A,
+
+	DATA_ONLY, 0x87,
+	DATA_ONLY, 0x25,
+	DATA_ONLY, 0x6A,
+	DATA_ONLY, 0x44,
+	DATA_ONLY, 0x02,
+	DATA_ONLY, 0x88,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_sleep_out[] = {
+	0x11, COMMAND_ONLY,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_sleep_in[] = {
+	0x10, COMMAND_ONLY,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_display_on[] = {
+	0x29, COMMAND_ONLY,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_display_off[] = {
+	0x28, COMMAND_ONLY,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vci1_1st_en[] = {
+	0xF3, 0x10,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vl1_en[] = {
+	0xF3, 0x11,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vl2_en[] = {
+	0xF3, 0x13,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vci1_2nd_en[] = {
+	0xF3, 0x33,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vl3_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vreg1_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0x01,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vgh_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0x11,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vgl_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0x31,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x02,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vmos_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xB1,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vint_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xF1,
+	/* DATA_ONLY, 0x71,	VMOS/VBL/VBH not used */
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vbh_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xF9,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_vbl_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xFD,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_gam_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xFF,
+	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_sd_amp_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xFF,
+	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
+	DATA_ONLY, 0x80,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_gls_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xFF,
+	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
+	DATA_ONLY, 0x81,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_els_en[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xFF,
+	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
+	DATA_ONLY, 0x83,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
+	ENDDEF, 0x00
+};
+
+static const unsigned short seq_el_on[] = {
+	0xF3, 0x37,
+
+	DATA_ONLY, 0xFF,
+	/* DATA_ONLY, 0x73,	VMOS/VBL/VBH not used */
+	DATA_ONLY, 0x87,
+	DATA_ONLY, 0x00,
+	DATA_ONLY, 0x03,
+	/* DATA_ONLY, 0x02,	VMOS/VBL/VBH not used */
+	ENDDEF, 0x00
+};
+
+static int ld9040_spi_write_byte(struct ld9040 *lcd, int addr, int data)
+{
+	u16 buf[1];
+	struct spi_message msg;
+
+	struct spi_transfer xfer = {
+		.len		= 2,
+		.tx_buf		= buf,
+	};
+
+	buf[0] = (addr << 8) | data;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	return spi_sync(lcd->spi, &msg);
+}
+
+static int ld9040_spi_write(struct ld9040 *lcd, unsigned char address,
+	unsigned char command)
+{
+	int ret = 0;
+
+	if (address != DATA_ONLY)
+		ret = ld9040_spi_write_byte(lcd, 0x0, address);
+	if (command != COMMAND_ONLY)
+		ret = ld9040_spi_write_byte(lcd, 0x1, command);
+
+	return ret;
+}
+
+static int ld9040_panel_send_sequence(struct ld9040 *lcd,
+	const unsigned short *wbuf)
+{
+	int ret = 0, i = 0;
+
+	while ((wbuf[i] & DEFMASK) != ENDDEF) {
+		if ((wbuf[i] & DEFMASK) != SLEEPMSEC) {
+			ret = ld9040_spi_write(lcd, wbuf[i], wbuf[i+1]);
+			if (ret)
+				break;
+		} else
+			udelay(wbuf[i+1]*1000);
+		i += 2;
+	}
+
+	return ret;
+}
+
+static int _ld9040_gamma_ctl(struct ld9040 *lcd, const unsigned int *gamma)
+{
+	unsigned int i = 0;
+	int ret = 0;
+
+	/* start gamma table updating. */
+	ret = ld9040_panel_send_sequence(lcd, seq_gamma_start);
+	if (ret) {
+		dev_err(lcd->dev, "failed to disable gamma table updating.\n");
+		goto gamma_err;
+	}
+
+	for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) {
+		ret = ld9040_spi_write(lcd, DATA_ONLY, gamma[i]);
+		if (ret) {
+			dev_err(lcd->dev, "failed to set gamma table.\n");
+			goto gamma_err;
+		}
+	}
+
+	/* update gamma table. */
+	ret = ld9040_panel_send_sequence(lcd, seq_gamma_ctrl);
+	if (ret)
+		dev_err(lcd->dev, "failed to update gamma table.\n");
+
+gamma_err:
+	return ret;
+}
+
+static int ld9040_gamma_ctl(struct ld9040 *lcd, int gamma)
+{
+	int ret = 0;
+
+	ret = _ld9040_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]);
+
+	return ret;
+}
+
+
+static int ld9040_ldi_init(struct ld9040 *lcd)
+{
+	int ret, i;
+	static const unsigned short *init_seq[] = {
+		seq_user_setting,
+		seq_panel_condition,
+		seq_display_ctrl,
+		seq_manual_pwr,
+		seq_elvss_on,
+		seq_gtcon,
+		seq_gamma_set1,
+		seq_gamma_ctrl,
+		seq_sleep_out,
+	};
+
+	for (i = 0; i < ARRAY_SIZE(init_seq); i++) {
+		ret = ld9040_panel_send_sequence(lcd, init_seq[i]);
+		/* workaround: minimum delay time for transferring CMD */
+		udelay(300);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int ld9040_ldi_enable(struct ld9040 *lcd)
+{
+	int ret = 0;
+
+	ret = ld9040_panel_send_sequence(lcd, seq_display_on);
+
+	return ret;
+}
+
+static int ld9040_ldi_disable(struct ld9040 *lcd)
+{
+	int ret;
+
+	ret = ld9040_panel_send_sequence(lcd, seq_display_off);
+	ret = ld9040_panel_send_sequence(lcd, seq_sleep_in);
+
+	return ret;
+}
+
+static int ld9040_power_on(struct ld9040 *lcd)
+{
+	int ret = 0;
+	struct lcd_platform_data *pd = NULL;
+	pd = lcd->lcd_pd;
+	if (!pd) {
+		dev_err(lcd->dev, "platform data is NULL.\n");
+		return -EFAULT;
+	}
+
+	if (!pd->power_on) {
+		dev_err(lcd->dev, "power_on is NULL.\n");
+		return -EFAULT;
+	} else {
+		pd->power_on(lcd->ld, 1);
+		mdelay(pd->power_on_delay);
+	}
+
+	if (!pd->reset) {
+		dev_err(lcd->dev, "reset is NULL.\n");
+		return -EFAULT;
+	} else {
+		pd->reset(lcd->ld);
+		mdelay(pd->reset_delay);
+	}
+
+	ret = ld9040_ldi_init(lcd);
+	if (ret) {
+		dev_err(lcd->dev, "failed to initialize ldi.\n");
+		return ret;
+	}
+
+	ret = ld9040_ldi_enable(lcd);
+	if (ret) {
+		dev_err(lcd->dev, "failed to enable ldi.\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ld9040_power_off(struct ld9040 *lcd)
+{
+	int ret = 0;
+	struct lcd_platform_data *pd = NULL;
+
+	pd = lcd->lcd_pd;
+	if (!pd) {
+		dev_err(lcd->dev, "platform data is NULL.\n");
+		return -EFAULT;
+	}
+
+	ret = ld9040_ldi_disable(lcd);
+	if (ret) {
+		dev_err(lcd->dev, "lcd setting failed.\n");
+		return -EIO;
+	}
+
+	mdelay(pd->power_off_delay);
+
+	if (!pd->power_on) {
+		dev_err(lcd->dev, "power_on is NULL.\n");
+		return -EFAULT;
+	} else
+		pd->power_on(lcd->ld, 0);
+
+	return 0;
+}
+
+static int ld9040_power(struct ld9040 *lcd, int power)
+{
+	int ret = 0;
+
+	if (power_is_on(power) && !power_is_on(lcd->power))
+		ret = ld9040_power_on(lcd);
+	else if (!power_is_on(power) && power_is_on(lcd->power))
+		ret = ld9040_power_off(lcd);
+
+	if (!ret)
+		lcd->power = power;
+
+	return ret;
+}
+
+static int ld9040_set_power(struct lcd_device *ld, int power)
+{
+	struct ld9040 *lcd = lcd_get_data(ld);
+
+	if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN &&
+		power != FB_BLANK_NORMAL) {
+		dev_err(lcd->dev, "power value should be 0, 1 or 4.\n");
+		return -EINVAL;
+	}
+
+	return ld9040_power(lcd, power);
+}
+
+static int ld9040_get_power(struct lcd_device *ld)
+{
+	struct ld9040 *lcd = lcd_get_data(ld);
+
+	return lcd->power;
+}
+
+static int ld9040_get_brightness(struct backlight_device *bd)
+{
+	return bd->props.brightness;
+}
+
+static int ld9040_set_brightness(struct backlight_device *bd)
+{
+	int ret = 0, brightness = bd->props.brightness;
+	struct ld9040 *lcd = bl_get_data(bd);
+
+	if (brightness < MIN_BRIGHTNESS ||
+		brightness > bd->props.max_brightness) {
+		dev_err(&bd->dev, "lcd brightness should be %d to %d.\n",
+			MIN_BRIGHTNESS, MAX_BRIGHTNESS);
+		return -EINVAL;
+	}
+
+	ret = ld9040_gamma_ctl(lcd, bd->props.brightness);
+	if (ret) {
+		dev_err(&bd->dev, "lcd brightness setting failed.\n");
+		return -EIO;
+	}
+
+	return ret;
+}
+
+static struct lcd_ops ld9040_lcd_ops = {
+	.set_power = ld9040_set_power,
+	.get_power = ld9040_get_power,
+};
+
+static const struct backlight_ops ld9040_backlight_ops  = {
+	.get_brightness = ld9040_get_brightness,
+	.update_status = ld9040_set_brightness,
+};
+
+
+static int ld9040_probe(struct spi_device *spi)
+{
+	int ret = 0;
+	struct ld9040 *lcd = NULL;
+	struct lcd_device *ld = NULL;
+	struct backlight_device *bd = NULL;
+
+	lcd = kzalloc(sizeof(struct ld9040), GFP_KERNEL);
+	if (!lcd)
+		return -ENOMEM;
+
+	/* ld9040 lcd panel uses 3-wire 9bits SPI Mode. */
+	spi->bits_per_word = 9;
+
+	ret = spi_setup(spi);
+	if (ret < 0) {
+		dev_err(&spi->dev, "spi setup failed.\n");
+		goto out_free_lcd;
+	}
+
+	lcd->spi = spi;
+	lcd->dev = &spi->dev;
+
+	lcd->lcd_pd = spi->dev.platform_data;
+	if (!lcd->lcd_pd) {
+		dev_err(&spi->dev, "platform data is NULL.\n");
+		goto out_free_lcd;
+	}
+
+	ld = lcd_device_register("ld9040", &spi->dev, lcd, &ld9040_lcd_ops);
+	if (IS_ERR(ld)) {
+		ret = PTR_ERR(ld);
+		goto out_free_lcd;
+	}
+
+	lcd->ld = ld;
+
+	bd = backlight_device_register("ld9040-bl", &spi->dev,
+		lcd, &ld9040_backlight_ops, NULL);
+	if (IS_ERR(ld)) {
+		ret = PTR_ERR(ld);
+		goto out_free_lcd;
+	}
+
+	bd->props.max_brightness = MAX_BRIGHTNESS;
+	bd->props.brightness = MAX_BRIGHTNESS;
+	lcd->bd = bd;
+
+	/*
+	 * if lcd panel was on from bootloader like u-boot then
+	 * do not lcd on.
+	 */
+	if (!lcd->lcd_pd->lcd_enabled) {
+		/*
+		 * if lcd panel was off from bootloader then
+		 * current lcd status is powerdown and then
+		 * it enables lcd panel.
+		 */
+		lcd->power = FB_BLANK_POWERDOWN;
+
+		ld9040_power(lcd, FB_BLANK_UNBLANK);
+	} else
+		lcd->power = FB_BLANK_UNBLANK;
+
+	dev_set_drvdata(&spi->dev, lcd);
+
+	dev_info(&spi->dev, "ld9040 panel driver has been probed.\n");
+	return 0;
+
+out_free_lcd:
+	kfree(lcd);
+	return ret;
+}
+
+static int __devexit ld9040_remove(struct spi_device *spi)
+{
+	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
+
+	ld9040_power(lcd, FB_BLANK_POWERDOWN);
+	lcd_device_unregister(lcd->ld);
+	kfree(lcd);
+
+	return 0;
+}
+
+#if defined(CONFIG_PM)
+static int ld9040_suspend(struct spi_device *spi, pm_message_t mesg)
+{
+	int ret = 0;
+	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
+
+	dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power);
+
+	/*
+	 * when lcd panel is suspend, lcd panel becomes off
+	 * regardless of status.
+	 */
+	ret = ld9040_power(lcd, FB_BLANK_POWERDOWN);
+
+	return ret;
+}
+
+static int ld9040_resume(struct spi_device *spi)
+{
+	int ret = 0;
+	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
+
+	lcd->power = FB_BLANK_POWERDOWN;
+
+	ret = ld9040_power(lcd, FB_BLANK_UNBLANK);
+
+	return ret;
+}
+#else
+#define ld9040_suspend		NULL
+#define ld9040_resume		NULL
+#endif
+
+/* Power down all displays on reboot, poweroff or halt. */
+static void ld9040_shutdown(struct spi_device *spi)
+{
+	struct ld9040 *lcd = dev_get_drvdata(&spi->dev);
+
+	ld9040_power(lcd, FB_BLANK_POWERDOWN);
+}
+
+static struct spi_driver ld9040_driver = {
+	.driver = {
+		.name	= "ld9040",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ld9040_probe,
+	.remove		= __devexit_p(ld9040_remove),
+	.shutdown	= ld9040_shutdown,
+	.suspend	= ld9040_suspend,
+	.resume		= ld9040_resume,
+};
+
+static int __init ld9040_init(void)
+{
+	return spi_register_driver(&ld9040_driver);
+}
+
+static void __exit ld9040_exit(void)
+{
+	spi_unregister_driver(&ld9040_driver);
+}
+
+module_init(ld9040_init);
+module_exit(ld9040_exit);
+
+MODULE_AUTHOR("Donghwa Lee <dh09.lee@samsung.com>");
+MODULE_DESCRIPTION("ld9040 LCD Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/ld9040_gamma.h b/drivers/video/backlight/ld9040_gamma.h
new file mode 100644
index 0000000..038d9c8
--- /dev/null
+++ b/drivers/video/backlight/ld9040_gamma.h
@@ -0,0 +1,200 @@
+/*
+ * Gamma level definitions.
+ *
+ * Copyright (c) 2011 Samsung Electronics
+ * InKi Dae <inki.dae@samsung.com>
+ * Donghwa Lee <dh09.lee@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 _LD9040_BRIGHTNESS_H
+#define _LD9040_BRIGHTNESS_H
+
+#define MAX_GAMMA_LEVEL		25
+#define GAMMA_TABLE_COUNT	21
+
+/* gamma value: 2.2 */
+static const unsigned int ld9040_22_300[] = {
+	0x00, 0xa7, 0xb4, 0xae, 0xbf, 0x00, 0x91,
+	0x00, 0xb2, 0xb4, 0xaa, 0xbb, 0x00, 0xac,
+	0x00, 0xb3, 0xb1, 0xaa, 0xbc, 0x00, 0xb3
+};
+
+static const unsigned int ld9040_22_290[] = {
+	0x00, 0xa9, 0xb7, 0xae, 0xbd, 0x00, 0x89,
+	0x00, 0xb7, 0xb6, 0xa8, 0xba, 0x00, 0xa4,
+	0x00, 0xb1, 0xb4, 0xaa, 0xbb, 0x00, 0xaa
+};
+
+static const unsigned int ld9040_22_280[] = {
+	0x00, 0xa9, 0xb6, 0xad, 0xbf, 0x00, 0x86,
+	0x00, 0xb8, 0xb5, 0xa8, 0xbc, 0x00, 0xa0,
+	0x00, 0xb3, 0xb3, 0xa9, 0xbc, 0x00, 0xa7
+};
+
+static const unsigned int ld9040_22_270[] = {
+	0x00, 0xa8, 0xb8, 0xae, 0xbe, 0x00, 0x84,
+	0x00, 0xb9, 0xb7, 0xa8, 0xbc, 0x00, 0x9d,
+	0x00, 0xb2, 0xb5, 0xaa, 0xbc, 0x00, 0xa4
+
+};
+static const unsigned int ld9040_22_260[] = {
+	0x00, 0xa4, 0xb8, 0xb0, 0xbf, 0x00, 0x80,
+	0x00, 0xb8, 0xb6, 0xaa, 0xbc, 0x00, 0x9a,
+	0x00, 0xb0, 0xb5, 0xab, 0xbd, 0x00, 0xa0
+};
+
+static const unsigned int ld9040_22_250[] = {
+	0x00, 0xa4, 0xb9, 0xaf, 0xc1, 0x00, 0x7d,
+	0x00, 0xb9, 0xb6, 0xaa, 0xbb, 0x00, 0x97,
+	0x00, 0xb1, 0xb5, 0xaa, 0xbf, 0x00, 0x9d
+};
+
+static const unsigned int ld9040_22_240[] = {
+	0x00, 0xa2, 0xb9, 0xaf, 0xc2, 0x00, 0x7a,
+	0x00, 0xb9, 0xb7, 0xaa, 0xbd, 0x00, 0x94,
+	0x00, 0xb0, 0xb5, 0xab, 0xbf, 0x00, 0x9a
+};
+
+static const unsigned int ld9040_22_230[] = {
+	0x00, 0xa0, 0xb9, 0xaf, 0xc3, 0x00, 0x77,
+	0x00, 0xb9, 0xb7, 0xab, 0xbe, 0x00, 0x90,
+	0x00, 0xb0, 0xb6, 0xab, 0xbf, 0x00, 0x97
+};
+
+static const unsigned int ld9040_22_220[] = {
+	0x00, 0x9e, 0xba, 0xb0, 0xc2, 0x00, 0x75,
+	0x00, 0xb9, 0xb8, 0xab, 0xbe, 0x00, 0x8e,
+	0x00, 0xb0, 0xb6, 0xac, 0xbf, 0x00, 0x94
+};
+
+static const unsigned int ld9040_22_210[] = {
+	0x00, 0x9c, 0xb9, 0xb0, 0xc4, 0x00, 0x72,
+	0x00, 0xb8, 0xb8, 0xac, 0xbf, 0x00, 0x8a,
+	0x00, 0xb0, 0xb6, 0xac, 0xc0, 0x00, 0x91
+};
+
+static const unsigned int ld9040_22_200[] = {
+	0x00, 0x9a, 0xba, 0xb1, 0xc4, 0x00, 0x6f,
+	0x00, 0xb8, 0xb8, 0xad, 0xc0, 0x00, 0x86,
+	0x00, 0xb0, 0xb7, 0xad, 0xc0, 0x00, 0x8d
+};
+
+static const unsigned int ld9040_22_190[] = {
+	0x00, 0x97, 0xba, 0xb2, 0xc5, 0x00, 0x6c,
+	0x00, 0xb8, 0xb8, 0xae, 0xc1, 0x00, 0x82,
+	0x00, 0xb0, 0xb6, 0xae, 0xc2, 0x00, 0x89
+};
+
+static const unsigned int ld9040_22_180[] = {
+	0x00, 0x93, 0xba, 0xb3, 0xc5, 0x00, 0x69,
+	0x00, 0xb8, 0xb9, 0xae, 0xc1, 0x00, 0x7f,
+	0x00, 0xb0, 0xb6, 0xae, 0xc3, 0x00, 0x85
+};
+
+static const unsigned int ld9040_22_170[] = {
+	0x00, 0x8b, 0xb9, 0xb3, 0xc7, 0x00, 0x65,
+	0x00, 0xb7, 0xb8, 0xaf, 0xc3, 0x00, 0x7a,
+	0x00, 0x80, 0xb6, 0xae, 0xc4, 0x00, 0x81
+};
+
+static const unsigned int ld9040_22_160[] = {
+	0x00, 0x89, 0xba, 0xb3, 0xc8, 0x00, 0x62,
+	0x00, 0xb6, 0xba, 0xaf, 0xc3, 0x00, 0x76,
+	0x00, 0xaf, 0xb7, 0xae, 0xc4, 0x00, 0x7e
+};
+
+static const unsigned int ld9040_22_150[] = {
+	0x00, 0x82, 0xba, 0xb4, 0xc7, 0x00, 0x5f,
+	0x00, 0xb5, 0xba, 0xb0, 0xc3, 0x00, 0x72,
+	0x00, 0xae, 0xb8, 0xb0, 0xc3, 0x00, 0x7a
+};
+
+static const unsigned int ld9040_22_140[] = {
+	0x00, 0x7b, 0xbb, 0xb4, 0xc8, 0x00, 0x5b,
+	0x00, 0xb5, 0xba, 0xb1, 0xc4, 0x00, 0x6e,
+	0x00, 0xae, 0xb9, 0xb0, 0xc5, 0x00, 0x75
+};
+
+static const unsigned int ld9040_22_130[] = {
+	0x00, 0x71, 0xbb, 0xb5, 0xc8, 0x00, 0x57,
+	0x00, 0xb5, 0xbb, 0xb0, 0xc5, 0x00, 0x6a,
+	0x00, 0xae, 0xb9, 0xb1, 0xc6, 0x00, 0x70
+};
+
+static const unsigned int ld9040_22_120[] = {
+	0x00, 0x47, 0xba, 0xb6, 0xca, 0x00, 0x53,
+	0x00, 0xb5, 0xbb, 0xb3, 0xc6, 0x00, 0x65,
+	0x00, 0xae, 0xb8, 0xb3, 0xc7, 0x00, 0x6c
+};
+
+static const unsigned int ld9040_22_110[] = {
+	0x00, 0x13, 0xbb, 0xb7, 0xca, 0x00, 0x4f,
+	0x00, 0xb4, 0xbb, 0xb3, 0xc7, 0x00, 0x60,
+	0x00, 0xad, 0xb8, 0xb4, 0xc7, 0x00, 0x67
+};
+
+static const unsigned int ld9040_22_100[] = {
+	0x00, 0x13, 0xba, 0xb8, 0xcb, 0x00, 0x4b,
+	0x00, 0xb3, 0xbc, 0xb4, 0xc7, 0x00, 0x5c,
+	0x00, 0xac, 0xb8, 0xb4, 0xc8, 0x00, 0x62
+};
+
+static const unsigned int ld9040_22_90[] = {
+	0x00, 0x13, 0xb9, 0xb8, 0xcd, 0x00, 0x46,
+	0x00, 0xb1, 0xbc, 0xb5, 0xc8, 0x00, 0x56,
+	0x00, 0xaa, 0xb8, 0xb4, 0xc9, 0x00, 0x5d
+};
+
+static const unsigned int ld9040_22_80[] = {
+	0x00, 0x13, 0xba, 0xb9, 0xcd, 0x00, 0x41,
+	0x00, 0xb0, 0xbe, 0xb5, 0xc9, 0x00, 0x51,
+	0x00, 0xa9, 0xb9, 0xb5, 0xca, 0x00, 0x57
+};
+
+static const unsigned int ld9040_22_70[] = {
+	0x00, 0x13, 0xb9, 0xb9, 0xd0, 0x00, 0x3c,
+	0x00, 0xaf, 0xbf, 0xb6, 0xcb, 0x00, 0x4b,
+	0x00, 0xa8, 0xb9, 0xb5, 0xcc, 0x00, 0x52
+};
+
+static const unsigned int ld9040_22_50[] = {
+	0x00, 0x13, 0xb2, 0xba, 0xd2, 0x00, 0x30,
+	0x00, 0xaf, 0xc0, 0xb8, 0xcd, 0x00, 0x3d,
+	0x00, 0xa8, 0xb8, 0xb7, 0xcd, 0x00, 0x44
+};
+
+struct ld9040_gamma {
+	unsigned int *gamma_22_table[MAX_GAMMA_LEVEL];
+} gamma_table = {
+	.gamma_22_table[0] = (unsigned int *)&ld9040_22_50,
+	.gamma_22_table[1] = (unsigned int *)&ld9040_22_70,
+	.gamma_22_table[2] = (unsigned int *)&ld9040_22_80,
+	.gamma_22_table[3] = (unsigned int *)&ld9040_22_90,
+	.gamma_22_table[4] = (unsigned int *)&ld9040_22_100,
+	.gamma_22_table[5] = (unsigned int *)&ld9040_22_110,
+	.gamma_22_table[6] = (unsigned int *)&ld9040_22_120,
+	.gamma_22_table[7] = (unsigned int *)&ld9040_22_130,
+	.gamma_22_table[8] = (unsigned int *)&ld9040_22_140,
+	.gamma_22_table[9] = (unsigned int *)&ld9040_22_150,
+	.gamma_22_table[10] = (unsigned int *)&ld9040_22_160,
+	.gamma_22_table[11] = (unsigned int *)&ld9040_22_170,
+	.gamma_22_table[12] = (unsigned int *)&ld9040_22_180,
+	.gamma_22_table[13] = (unsigned int *)&ld9040_22_190,
+	.gamma_22_table[14] = (unsigned int *)&ld9040_22_200,
+	.gamma_22_table[15] = (unsigned int *)&ld9040_22_210,
+	.gamma_22_table[16] = (unsigned int *)&ld9040_22_220,
+	.gamma_22_table[17] = (unsigned int *)&ld9040_22_230,
+	.gamma_22_table[18] = (unsigned int *)&ld9040_22_240,
+	.gamma_22_table[19] = (unsigned int *)&ld9040_22_250,
+	.gamma_22_table[20] = (unsigned int *)&ld9040_22_260,
+	.gamma_22_table[21] = (unsigned int *)&ld9040_22_270,
+	.gamma_22_table[22] = (unsigned int *)&ld9040_22_280,
+	.gamma_22_table[23] = (unsigned int *)&ld9040_22_290,
+	.gamma_22_table[24] = (unsigned int *)&ld9040_22_300,
+};
+
+#endif
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index d2f5901..bbca312 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -184,6 +184,7 @@ static int locomolcd_probe(struct locomo_dev *ldev)
 	local_irq_restore(flags);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 4;
 	locomolcd_bl_device = backlight_device_register("locomo-bl",
 							&ldev->dev, NULL,
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index 209acc1..07e8e27 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -136,6 +136,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev)
 	data->current_brightness = 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = MAX_BRIGHTNESS;
 	bl = backlight_device_register(name, &pdev->dev, data,
 					&max8925_backlight_ops, &props);
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c
deleted file mode 100644
index 1485f73..0000000
--- a/drivers/video/backlight/mbp_nvidia_bl.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- *  Backlight Driver for Nvidia 8600 in Macbook Pro
- *
- *  Copyright (c) Red Hat <mjg@redhat.com>
- *  Based on code from Pommed:
- *  Copyright (C) 2006 Nicolas Boichat <nicolas @boichat.ch>
- *  Copyright (C) 2006 Felipe Alfaro Solana <felipe_alfaro @linuxmail.org>
- *  Copyright (C) 2007 Julien BLACHE <jb@jblache.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 driver triggers SMIs which cause the firmware to change the
- *  backlight brightness. This is icky in many ways, but it's impractical to
- *  get at the firmware code in order to figure out what it's actually doing.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/backlight.h>
-#include <linux/err.h>
-#include <linux/dmi.h>
-#include <linux/io.h>
-
-static struct backlight_device *mbp_backlight_device;
-
-/* Structure to be passed to the DMI_MATCH function. */
-struct dmi_match_data {
-	/* I/O resource to allocate. */
-	unsigned long iostart;
-	unsigned long iolen;
-	/* Backlight operations structure. */
-	const struct backlight_ops backlight_ops;
-};
-
-/* Module parameters. */
-static int debug;
-module_param_named(debug, debug, int, 0644);
-MODULE_PARM_DESC(debug, "Set to one to enable debugging messages.");
-
-/*
- * Implementation for MacBooks with Intel chipset.
- */
-static int intel_chipset_send_intensity(struct backlight_device *bd)
-{
-	int intensity = bd->props.brightness;
-
-	if (debug)
-		printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n",
-		       intensity);
-
-	outb(0x04 | (intensity << 4), 0xb3);
-	outb(0xbf, 0xb2);
-	return 0;
-}
-
-static int intel_chipset_get_intensity(struct backlight_device *bd)
-{
-	int intensity;
-
-	outb(0x03, 0xb3);
-	outb(0xbf, 0xb2);
-	intensity = inb(0xb3) >> 4;
-
-	if (debug)
-		printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n",
-		       intensity);
-
-	return intensity;
-}
-
-static const struct dmi_match_data intel_chipset_data = {
-	.iostart = 0xb2,
-	.iolen = 2,
-	.backlight_ops	= {
-		.options	= BL_CORE_SUSPENDRESUME,
-		.get_brightness	= intel_chipset_get_intensity,
-		.update_status	= intel_chipset_send_intensity,
-	}
-};
-
-/*
- * Implementation for MacBooks with Nvidia chipset.
- */
-static int nvidia_chipset_send_intensity(struct backlight_device *bd)
-{
-	int intensity = bd->props.brightness;
-
-	if (debug)
-		printk(KERN_DEBUG "mbp_nvidia_bl: setting brightness to %d\n",
-		       intensity);
-
-	outb(0x04 | (intensity << 4), 0x52f);
-	outb(0xbf, 0x52e);
-	return 0;
-}
-
-static int nvidia_chipset_get_intensity(struct backlight_device *bd)
-{
-	int intensity;
-
-	outb(0x03, 0x52f);
-	outb(0xbf, 0x52e);
-	intensity = inb(0x52f) >> 4;
-
-	if (debug)
-		printk(KERN_DEBUG "mbp_nvidia_bl: read brightness of %d\n",
-		       intensity);
-
-	return intensity;
-}
-
-static const struct dmi_match_data nvidia_chipset_data = {
-	.iostart = 0x52e,
-	.iolen = 2,
-	.backlight_ops		= {
-		.options	= BL_CORE_SUSPENDRESUME,
-		.get_brightness	= nvidia_chipset_get_intensity,
-		.update_status	= nvidia_chipset_send_intensity
-	}
-};
-
-/*
- * DMI matching.
- */
-static /* const */ struct dmi_match_data *driver_data;
-
-static int mbp_dmi_match(const struct dmi_system_id *id)
-{
-	driver_data = id->driver_data;
-
-	printk(KERN_INFO "mbp_nvidia_bl: %s detected\n", id->ident);
-	return 1;
-}
-
-static const struct dmi_system_id __initdata mbp_device_table[] = {
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 1,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 2,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 3,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook3,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 4,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 4,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook4,2"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 1,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 1,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 2,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 2,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 3,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 3,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,2"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 4,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookAir 1,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir1,1"),
-		},
-		.driver_data	= (void *)&intel_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 5,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,1"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 5,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5,2"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBook 6,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookAir 2,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir2,1"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 5,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,1"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 5,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,2"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 5,3",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 5,4",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookPro 5,5",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,5"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookAir 3,1",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,1"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{
-		.callback	= mbp_dmi_match,
-		.ident		= "MacBookAir 3,2",
-		.matches	= {
-			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
-			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir3,2"),
-		},
-		.driver_data	= (void *)&nvidia_chipset_data,
-	},
-	{ }
-};
-
-static int __init mbp_init(void)
-{
-	struct backlight_properties props;
-	if (!dmi_check_system(mbp_device_table))
-		return -ENODEV;
-
-	if (!request_region(driver_data->iostart, driver_data->iolen, 
-						"Macbook Pro backlight"))
-		return -ENXIO;
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = 15;
-	mbp_backlight_device = backlight_device_register("mbp_backlight", NULL,
-							 NULL,
-							 &driver_data->backlight_ops,
-							 &props);
-	if (IS_ERR(mbp_backlight_device)) {
-		release_region(driver_data->iostart, driver_data->iolen);
-		return PTR_ERR(mbp_backlight_device);
-	}
-
-	mbp_backlight_device->props.brightness =
-		driver_data->backlight_ops.get_brightness(mbp_backlight_device);
-	backlight_update_status(mbp_backlight_device);
-
-	return 0;
-}
-
-static void __exit mbp_exit(void)
-{
-	backlight_device_unregister(mbp_backlight_device);
-
-	release_region(driver_data->iostart, driver_data->iolen);
-}
-
-module_init(mbp_init);
-module_exit(mbp_exit);
-
-MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
-MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(dmi, mbp_device_table);
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c
index d3bc562..08d26a7 100644
--- a/drivers/video/backlight/omap1_bl.c
+++ b/drivers/video/backlight/omap1_bl.c
@@ -146,6 +146,7 @@ static int omapbl_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = OMAPBL_MAX_INTENSITY;
 	dev = backlight_device_register("omap-bl", &pdev->dev, bl, &omapbl_ops,
 					&props);
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c
index 3c424f7..ef5628d 100644
--- a/drivers/video/backlight/pcf50633-backlight.c
+++ b/drivers/video/backlight/pcf50633-backlight.c
@@ -112,6 +112,7 @@ static int __devinit pcf50633_bl_probe(struct platform_device *pdev)
 	if (!pcf_bl)
 		return -ENOMEM;
 
+	bl_props.type = BACKLIGHT_RAW;
 	bl_props.max_brightness = 0x3f;
 	bl_props.power = FB_BLANK_UNBLANK;
 
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c
index 809278c..6af183d 100644
--- a/drivers/video/backlight/progear_bl.c
+++ b/drivers/video/backlight/progear_bl.c
@@ -84,6 +84,7 @@ static int progearbl_probe(struct platform_device *pdev)
 	pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN;
 	progear_backlight_device = backlight_device_register("progear-bl",
 							     &pdev->dev, NULL,
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 21866ec..b8f38ec 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -28,6 +28,7 @@ struct pwm_bl_data {
 	unsigned int		lth_brightness;
 	int			(*notify)(struct device *,
 					  int brightness);
+	int			(*check_fb)(struct device *, struct fb_info *);
 };
 
 static int pwm_backlight_update_status(struct backlight_device *bl)
@@ -62,9 +63,18 @@ static int pwm_backlight_get_brightness(struct backlight_device *bl)
 	return bl->props.brightness;
 }
 
+static int pwm_backlight_check_fb(struct backlight_device *bl,
+				  struct fb_info *info)
+{
+	struct pwm_bl_data *pb = dev_get_drvdata(&bl->dev);
+
+	return !pb->check_fb || pb->check_fb(pb->dev, info);
+}
+
 static const struct backlight_ops pwm_backlight_ops = {
 	.update_status	= pwm_backlight_update_status,
 	.get_brightness	= pwm_backlight_get_brightness,
+	.check_fb	= pwm_backlight_check_fb,
 };
 
 static int pwm_backlight_probe(struct platform_device *pdev)
@@ -95,6 +105,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 
 	pb->period = data->pwm_period_ns;
 	pb->notify = data->notify;
+	pb->check_fb = data->check_fb;
 	pb->lth_brightness = data->lth_brightness *
 		(data->pwm_period_ns / data->max_brightness);
 	pb->dev = &pdev->dev;
@@ -108,6 +119,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 		dev_dbg(&pdev->dev, "got pwm for backlight\n");
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = data->max_brightness;
 	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
 				       &pwm_backlight_ops, &props);
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c
index 5927db0..322040f 100644
--- a/drivers/video/backlight/s6e63m0.c
+++ b/drivers/video/backlight/s6e63m0.c
@@ -778,6 +778,7 @@ static int __devinit s6e63m0_probe(struct spi_device *spi)
 
 	bd->props.max_brightness = MAX_BRIGHTNESS;
 	bd->props.brightness = MAX_BRIGHTNESS;
+	bd->props.type = BACKLIGHT_RAW;
 	lcd->bd = bd;
 
 	/*
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c
index 2a04b38..425a736 100644
--- a/drivers/video/backlight/tosa_bl.c
+++ b/drivers/video/backlight/tosa_bl.c
@@ -102,6 +102,7 @@ static int __devinit tosa_bl_probe(struct i2c_client *client,
 	data->i2c = client;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 512 - 1;
 	data->bl = backlight_device_register("tosa-bl", &client->dev, data,
 					     &bl_ops, &props);
diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c
index 08fd87f..d4c6eb2 100644
--- a/drivers/video/backlight/wm831x_bl.c
+++ b/drivers/video/backlight/wm831x_bl.c
@@ -193,6 +193,7 @@ static int wm831x_backlight_probe(struct platform_device *pdev)
 	data->current_brightness = 0;
 	data->isink_reg = isink_reg;
 
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = max_isel;
 	bl = backlight_device_register("wm831x", &pdev->dev, data,
 				       &wm831x_backlight_ops, &props);
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
index e7d0f52..2464b91 100644
--- a/drivers/video/bf54x-lq043fb.c
+++ b/drivers/video/bf54x-lq043fb.c
@@ -649,6 +649,7 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev)
 	}
 #ifndef NO_BL_SUPPORT
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 255;
 	bl_dev = backlight_device_register("bf54x-bl", NULL, NULL,
 					   &bfin_lq043fb_bl_ops, &props);
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c
index 3cf7767..d8de29f 100644
--- a/drivers/video/bfin-t350mcqb-fb.c
+++ b/drivers/video/bfin-t350mcqb-fb.c
@@ -545,6 +545,7 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev)
 	}
 #ifndef NO_BL_SUPPORT
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 255;
 	bl_dev = backlight_device_register("bf52x-bl", NULL, NULL,
 					   &bfin_lq043fb_bl_ops, &props);
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c
index 4dc1346..7ba74cd 100644
--- a/drivers/video/bw2.c
+++ b/drivers/video/bw2.c
@@ -273,7 +273,7 @@ static int __devinit bw2_do_default_mode(struct bw2_par *par,
 	return 0;
 }
 
-static int __devinit bw2_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bw2_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -375,7 +375,7 @@ static const struct of_device_id bw2_match[] = {
 };
 MODULE_DEVICE_TABLE(of, bw2_match);
 
-static struct of_platform_driver bw2_driver = {
+static struct platform_driver bw2_driver = {
 	.driver = {
 		.name = "bw2",
 		.owner = THIS_MODULE,
@@ -390,12 +390,12 @@ static int __init bw2_init(void)
 	if (fb_get_options("bw2fb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&bw2_driver);
+	return platform_driver_register(&bw2_driver);
 }
 
 static void __exit bw2_exit(void)
 {
-	of_unregister_platform_driver(&bw2_driver);
+	platform_driver_unregister(&bw2_driver);
 }
 
 module_init(bw2_init);
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c
index 2424953..e2c85b0 100644
--- a/drivers/video/cg14.c
+++ b/drivers/video/cg14.c
@@ -463,7 +463,7 @@ static void cg14_unmap_regs(struct platform_device *op, struct fb_info *info,
 			   info->screen_base, info->fix.smem_len);
 }
 
-static int __devinit cg14_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit cg14_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -595,7 +595,7 @@ static const struct of_device_id cg14_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cg14_match);
 
-static struct of_platform_driver cg14_driver = {
+static struct platform_driver cg14_driver = {
 	.driver = {
 		.name = "cg14",
 		.owner = THIS_MODULE,
@@ -610,12 +610,12 @@ static int __init cg14_init(void)
 	if (fb_get_options("cg14fb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&cg14_driver);
+	return platform_driver_register(&cg14_driver);
 }
 
 static void __exit cg14_exit(void)
 {
-	of_unregister_platform_driver(&cg14_driver);
+	platform_driver_unregister(&cg14_driver);
 }
 
 module_init(cg14_init);
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c
index 09c0c3c..f927a7b 100644
--- a/drivers/video/cg3.c
+++ b/drivers/video/cg3.c
@@ -346,8 +346,7 @@ static int __devinit cg3_do_default_mode(struct cg3_par *par)
 	return 0;
 }
 
-static int __devinit cg3_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit cg3_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -462,7 +461,7 @@ static const struct of_device_id cg3_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cg3_match);
 
-static struct of_platform_driver cg3_driver = {
+static struct platform_driver cg3_driver = {
 	.driver = {
 		.name = "cg3",
 		.owner = THIS_MODULE,
@@ -477,12 +476,12 @@ static int __init cg3_init(void)
 	if (fb_get_options("cg3fb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&cg3_driver);
+	return platform_driver_register(&cg3_driver);
 }
 
 static void __exit cg3_exit(void)
 {
-	of_unregister_platform_driver(&cg3_driver);
+	platform_driver_unregister(&cg3_driver);
 }
 
 module_init(cg3_init);
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c
index 2b5a970..4ffad90 100644
--- a/drivers/video/cg6.c
+++ b/drivers/video/cg6.c
@@ -737,8 +737,7 @@ static void cg6_unmap_regs(struct platform_device *op, struct fb_info *info,
 			   info->fix.smem_len);
 }
 
-static int __devinit cg6_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit cg6_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -855,7 +854,7 @@ static const struct of_device_id cg6_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cg6_match);
 
-static struct of_platform_driver cg6_driver = {
+static struct platform_driver cg6_driver = {
 	.driver = {
 		.name = "cg6",
 		.owner = THIS_MODULE,
@@ -870,12 +869,12 @@ static int __init cg6_init(void)
 	if (fb_get_options("cg6fb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&cg6_driver);
+	return platform_driver_register(&cg6_driver);
 }
 
 static void __exit cg6_exit(void)
 {
-	of_unregister_platform_driver(&cg6_driver);
+	platform_driver_unregister(&cg6_driver);
 }
 
 module_init(cg6_init);
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index 0c1afd1..8503807 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -47,6 +47,8 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -61,10 +63,10 @@ struct cfb_info {
 	struct fb_info		fb;
 	struct display_switch	*dispsw;
 	struct display		*display;
-	struct pci_dev		*dev;
 	unsigned char		__iomem *region;
 	unsigned char		__iomem *regs;
 	u_int			id;
+	u_int			irq;
 	int			func_use_count;
 	u_long			ref_ps;
 
@@ -88,6 +90,19 @@ struct cfb_info {
 	u_char			ramdac_powerdown;
 
 	u32			pseudo_palette[16];
+
+	spinlock_t		reg_b0_lock;
+
+#ifdef CONFIG_FB_CYBER2000_DDC
+	bool			ddc_registered;
+	struct i2c_adapter	ddc_adapter;
+	struct i2c_algo_bit_data	ddc_algo;
+#endif
+
+#ifdef CONFIG_FB_CYBER2000_I2C
+	struct i2c_adapter	i2c_adapter;
+	struct i2c_algo_bit_data i2c_algo;
+#endif
 };
 
 static char *default_font = "Acorn8x8";
@@ -494,6 +509,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
 	cyber2000_attrw(0x14, 0x00, cfb);
 
 	/* PLL registers */
+	spin_lock(&cfb->reg_b0_lock);
 	cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
 	cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
 	cyber2000_grphw(EXT_MCLK_MULT, cfb->mclk_mult, cfb);
@@ -501,6 +517,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
 	cyber2000_grphw(0x90, 0x01, cfb);
 	cyber2000_grphw(0xb9, 0x80, cfb);
 	cyber2000_grphw(0xb9, 0x00, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
 
 	cfb->ramdac_ctrl = hw->ramdac;
 	cyber2000fb_write_ramdac_ctrl(cfb);
@@ -681,9 +698,9 @@ cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb,
 	 *    pll_ps_calc = best_div1 / (ref_ps * best_mult)
 	 */
 	best_diff = 0x7fffffff;
-	best_mult = 32;
-	best_div1 = 255;
-	for (t_div1 = 32; t_div1 > 1; t_div1 -= 1) {
+	best_mult = 2;
+	best_div1 = 32;
+	for (t_div1 = 2; t_div1 < 32; t_div1 += 1) {
 		u_int rr, t_mult, t_pll_ps;
 		int diff;
 
@@ -1105,24 +1122,22 @@ void cyber2000fb_disable_extregs(struct cfb_info *cfb)
 }
 EXPORT_SYMBOL(cyber2000fb_disable_extregs);
 
-void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var)
-{
-	memcpy(var, &cfb->fb.var, sizeof(struct fb_var_screeninfo));
-}
-EXPORT_SYMBOL(cyber2000fb_get_fb_var);
-
 /*
  * Attach a capture/tv driver to the core CyberX0X0 driver.
  */
 int cyber2000fb_attach(struct cyberpro_info *info, int idx)
 {
 	if (int_cfb_info != NULL) {
-		info->dev	      = int_cfb_info->dev;
+		info->dev	      = int_cfb_info->fb.device;
+#ifdef CONFIG_FB_CYBER2000_I2C
+		info->i2c	      = &int_cfb_info->i2c_adapter;
+#else
+		info->i2c	      = NULL;
+#endif
 		info->regs	      = int_cfb_info->regs;
+		info->irq             = int_cfb_info->irq;
 		info->fb	      = int_cfb_info->fb.screen_base;
 		info->fb_size	      = int_cfb_info->fb.fix.smem_len;
-		info->enable_extregs  = cyber2000fb_enable_extregs;
-		info->disable_extregs = cyber2000fb_disable_extregs;
 		info->info	      = int_cfb_info;
 
 		strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
@@ -1141,6 +1156,183 @@ void cyber2000fb_detach(int idx)
 }
 EXPORT_SYMBOL(cyber2000fb_detach);
 
+#ifdef CONFIG_FB_CYBER2000_DDC
+
+#define DDC_REG		0xb0
+#define DDC_SCL_OUT	(1 << 0)
+#define DDC_SDA_OUT	(1 << 4)
+#define DDC_SCL_IN	(1 << 2)
+#define DDC_SDA_IN	(1 << 6)
+
+static void cyber2000fb_enable_ddc(struct cfb_info *cfb)
+{
+	spin_lock(&cfb->reg_b0_lock);
+	cyber2000fb_writew(0x1bf, 0x3ce, cfb);
+}
+
+static void cyber2000fb_disable_ddc(struct cfb_info *cfb)
+{
+	cyber2000fb_writew(0x0bf, 0x3ce, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+}
+
+
+static void cyber2000fb_ddc_setscl(void *data, int val)
+{
+	struct cfb_info *cfb = data;
+	unsigned char reg;
+
+	cyber2000fb_enable_ddc(cfb);
+	reg = cyber2000_grphr(DDC_REG, cfb);
+	if (!val)	/* bit is inverted */
+		reg |= DDC_SCL_OUT;
+	else
+		reg &= ~DDC_SCL_OUT;
+	cyber2000_grphw(DDC_REG, reg, cfb);
+	cyber2000fb_disable_ddc(cfb);
+}
+
+static void cyber2000fb_ddc_setsda(void *data, int val)
+{
+	struct cfb_info *cfb = data;
+	unsigned char reg;
+
+	cyber2000fb_enable_ddc(cfb);
+	reg = cyber2000_grphr(DDC_REG, cfb);
+	if (!val)	/* bit is inverted */
+		reg |= DDC_SDA_OUT;
+	else
+		reg &= ~DDC_SDA_OUT;
+	cyber2000_grphw(DDC_REG, reg, cfb);
+	cyber2000fb_disable_ddc(cfb);
+}
+
+static int cyber2000fb_ddc_getscl(void *data)
+{
+	struct cfb_info *cfb = data;
+	int retval;
+
+	cyber2000fb_enable_ddc(cfb);
+	retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SCL_IN);
+	cyber2000fb_disable_ddc(cfb);
+
+	return retval;
+}
+
+static int cyber2000fb_ddc_getsda(void *data)
+{
+	struct cfb_info *cfb = data;
+	int retval;
+
+	cyber2000fb_enable_ddc(cfb);
+	retval = !!(cyber2000_grphr(DDC_REG, cfb) & DDC_SDA_IN);
+	cyber2000fb_disable_ddc(cfb);
+
+	return retval;
+}
+
+static int __devinit cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
+{
+	strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
+		sizeof(cfb->ddc_adapter.name));
+	cfb->ddc_adapter.owner		= THIS_MODULE;
+	cfb->ddc_adapter.class		= I2C_CLASS_DDC;
+	cfb->ddc_adapter.algo_data	= &cfb->ddc_algo;
+	cfb->ddc_adapter.dev.parent	= cfb->fb.device;
+	cfb->ddc_algo.setsda		= cyber2000fb_ddc_setsda;
+	cfb->ddc_algo.setscl		= cyber2000fb_ddc_setscl;
+	cfb->ddc_algo.getsda		= cyber2000fb_ddc_getsda;
+	cfb->ddc_algo.getscl		= cyber2000fb_ddc_getscl;
+	cfb->ddc_algo.udelay		= 10;
+	cfb->ddc_algo.timeout		= 20;
+	cfb->ddc_algo.data		= cfb;
+
+	i2c_set_adapdata(&cfb->ddc_adapter, cfb);
+
+	return i2c_bit_add_bus(&cfb->ddc_adapter);
+}
+#endif /* CONFIG_FB_CYBER2000_DDC */
+
+#ifdef CONFIG_FB_CYBER2000_I2C
+static void cyber2000fb_i2c_setsda(void *data, int state)
+{
+	struct cfb_info *cfb = data;
+	unsigned int latch2;
+
+	spin_lock(&cfb->reg_b0_lock);
+	latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
+	latch2 &= EXT_LATCH2_I2C_CLKEN;
+	if (state)
+		latch2 |= EXT_LATCH2_I2C_DATEN;
+	cyber2000_grphw(EXT_LATCH2, latch2, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+}
+
+static void cyber2000fb_i2c_setscl(void *data, int state)
+{
+	struct cfb_info *cfb = data;
+	unsigned int latch2;
+
+	spin_lock(&cfb->reg_b0_lock);
+	latch2 = cyber2000_grphr(EXT_LATCH2, cfb);
+	latch2 &= EXT_LATCH2_I2C_DATEN;
+	if (state)
+		latch2 |= EXT_LATCH2_I2C_CLKEN;
+	cyber2000_grphw(EXT_LATCH2, latch2, cfb);
+	spin_unlock(&cfb->reg_b0_lock);
+}
+
+static int cyber2000fb_i2c_getsda(void *data)
+{
+	struct cfb_info *cfb = data;
+	int ret;
+
+	spin_lock(&cfb->reg_b0_lock);
+	ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_DAT);
+	spin_unlock(&cfb->reg_b0_lock);
+
+	return ret;
+}
+
+static int cyber2000fb_i2c_getscl(void *data)
+{
+	struct cfb_info *cfb = data;
+	int ret;
+
+	spin_lock(&cfb->reg_b0_lock);
+	ret = !!(cyber2000_grphr(EXT_LATCH2, cfb) & EXT_LATCH2_I2C_CLK);
+	spin_unlock(&cfb->reg_b0_lock);
+
+	return ret;
+}
+
+static int __devinit cyber2000fb_i2c_register(struct cfb_info *cfb)
+{
+	strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
+		sizeof(cfb->i2c_adapter.name));
+	cfb->i2c_adapter.owner = THIS_MODULE;
+	cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
+	cfb->i2c_adapter.dev.parent = cfb->fb.device;
+	cfb->i2c_algo.setsda = cyber2000fb_i2c_setsda;
+	cfb->i2c_algo.setscl = cyber2000fb_i2c_setscl;
+	cfb->i2c_algo.getsda = cyber2000fb_i2c_getsda;
+	cfb->i2c_algo.getscl = cyber2000fb_i2c_getscl;
+	cfb->i2c_algo.udelay = 5;
+	cfb->i2c_algo.timeout = msecs_to_jiffies(100);
+	cfb->i2c_algo.data = cfb;
+
+	return i2c_bit_add_bus(&cfb->i2c_adapter);
+}
+
+static void cyber2000fb_i2c_unregister(struct cfb_info *cfb)
+{
+	i2c_del_adapter(&cfb->i2c_adapter);
+}
+#else
+#define cyber2000fb_i2c_register(cfb)	(0)
+#define cyber2000fb_i2c_unregister(cfb)	do { } while (0)
+#endif
+
 /*
  * These parameters give
  * 640x480, hsync 31.5kHz, vsync 60Hz
@@ -1275,6 +1467,8 @@ static struct cfb_info __devinit *cyberpro_alloc_fb_info(unsigned int id,
 	cfb->fb.flags		= FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
 	cfb->fb.pseudo_palette	= cfb->pseudo_palette;
 
+	spin_lock_init(&cfb->reg_b0_lock);
+
 	fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0);
 
 	return cfb;
@@ -1369,6 +1563,11 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
 	cfb->fb.fix.mmio_len   = MMIO_SIZE;
 	cfb->fb.screen_base    = cfb->region;
 
+#ifdef CONFIG_FB_CYBER2000_DDC
+	if (cyber2000fb_setup_ddc_bus(cfb) == 0)
+		cfb->ddc_registered = true;
+#endif
+
 	err = -EINVAL;
 	if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
 			  &cyber2000fb_default_mode, 8)) {
@@ -1401,14 +1600,32 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
 		cfb->fb.var.xres, cfb->fb.var.yres,
 		h_sync / 1000, h_sync % 1000, v_sync);
 
-	if (cfb->dev)
-		cfb->fb.device = &cfb->dev->dev;
+	err = cyber2000fb_i2c_register(cfb);
+	if (err)
+		goto failed;
+
 	err = register_framebuffer(&cfb->fb);
+	if (err)
+		cyber2000fb_i2c_unregister(cfb);
 
 failed:
+#ifdef CONFIG_FB_CYBER2000_DDC
+	if (err && cfb->ddc_registered)
+		i2c_del_adapter(&cfb->ddc_adapter);
+#endif
 	return err;
 }
 
+static void __devexit cyberpro_common_remove(struct cfb_info *cfb)
+{
+	unregister_framebuffer(&cfb->fb);
+#ifdef CONFIG_FB_CYBER2000_DDC
+	if (cfb->ddc_registered)
+		i2c_del_adapter(&cfb->ddc_adapter);
+#endif
+	cyber2000fb_i2c_unregister(cfb);
+}
+
 static void cyberpro_common_resume(struct cfb_info *cfb)
 {
 	cyberpro_init_hw(cfb);
@@ -1442,12 +1659,13 @@ static int __devinit cyberpro_vl_probe(void)
 	if (!cfb)
 		goto failed_release;
 
-	cfb->dev = NULL;
+	cfb->irq = -1;
 	cfb->region = ioremap(FB_START, FB_SIZE);
 	if (!cfb->region)
 		goto failed_ioremap;
 
 	cfb->regs = cfb->region + MMIO_OFFSET;
+	cfb->fb.device = NULL;
 	cfb->fb.fix.mmio_start = FB_START + MMIO_OFFSET;
 	cfb->fb.fix.smem_start = FB_START;
 
@@ -1585,12 +1803,13 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (err)
 		goto failed_regions;
 
-	cfb->dev = dev;
+	cfb->irq = dev->irq;
 	cfb->region = pci_ioremap_bar(dev, 0);
 	if (!cfb->region)
 		goto failed_ioremap;
 
 	cfb->regs = cfb->region + MMIO_OFFSET;
+	cfb->fb.device = &dev->dev;
 	cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
 	cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
 
@@ -1648,15 +1867,7 @@ static void __devexit cyberpro_pci_remove(struct pci_dev *dev)
 	struct cfb_info *cfb = pci_get_drvdata(dev);
 
 	if (cfb) {
-		/*
-		 * If unregister_framebuffer fails, then
-		 * we will be leaving hooks that could cause
-		 * oopsen laying around.
-		 */
-		if (unregister_framebuffer(&cfb->fb))
-			printk(KERN_WARNING "%s: danger Will Robinson, "
-				"danger danger!  Oopsen imminent!\n",
-				cfb->fb.fix.id);
+		cyberpro_common_remove(cfb);
 		iounmap(cfb->region);
 		cyberpro_free_fb_info(cfb);
 
diff --git a/drivers/video/cyber2000fb.h b/drivers/video/cyber2000fb.h
index de4fc43..bad6910 100644
--- a/drivers/video/cyber2000fb.h
+++ b/drivers/video/cyber2000fb.h
@@ -464,12 +464,14 @@ static void debug_printf(char *fmt, ...)
 struct cfb_info;
 
 struct cyberpro_info {
-	struct pci_dev	*dev;
+	struct device	*dev;
+	struct i2c_adapter *i2c;
 	unsigned char	__iomem *regs;
 	char		__iomem *fb;
 	char		dev_name[32];
 	unsigned int	fb_size;
 	unsigned int	chip_id;
+	unsigned int	irq;
 
 	/*
 	 * The following is a pointer to be passed into the
@@ -478,15 +480,6 @@ struct cyberpro_info {
 	 * is within this structure.
 	 */
 	struct cfb_info *info;
-
-	/*
-	 * Use these to enable the BM or TV registers.  In an SMP
-	 * environment, these two function pointers should only be
-	 * called from the module_init() or module_exit()
-	 * functions.
-	 */
-	void (*enable_extregs)(struct cfb_info *);
-	void (*disable_extregs)(struct cfb_info *);
 };
 
 #define ID_IGA_1682		0
@@ -494,8 +487,6 @@ struct cyberpro_info {
 #define ID_CYBERPRO_2010	2
 #define ID_CYBERPRO_5000	3
 
-struct fb_var_screeninfo;
-
 /*
  * Note! Writing to the Cyber20x0 registers from an interrupt
  * routine is definitely a bad idea atm.
@@ -504,4 +495,3 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx);
 void cyber2000fb_detach(int idx);
 void cyber2000fb_enable_extregs(struct cfb_info *cfb);
 void cyber2000fb_disable_extregs(struct cfb_info *cfb);
-void cyber2000fb_get_fb_var(struct cfb_info *cfb, struct fb_var_screeninfo *var);
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
new file mode 100644
index 0000000..dbd2dc4
--- /dev/null
+++ b/drivers/video/fb-puv3.c
@@ -0,0 +1,846 @@
+/*
+ * Frame Buffer Driver for PKUnity-v3 Unigfx
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+
+/* Platform_data reserved for unifb registers. */
+#define UNIFB_REGS_NUM		10
+/* RAM reserved for the frame buffer. */
+#define UNIFB_MEMSIZE		(SZ_4M)		/* 4 MB for 1024*768*32b */
+
+/*
+ * cause UNIGFX don not have EDID
+ * all the modes are organized as follow
+ */
+static const struct fb_videomode unifb_modes[] = {
+	/* 0 640x480-60 VESA */
+	{ "640x480@60",  60,  640, 480,  25175000,  48, 16, 34, 10,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 1 640x480-75 VESA */
+	{ "640x480@75",  75,  640, 480,  31500000, 120, 16, 18,  1,  64, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 2 800x600-60 VESA */
+	{ "800x600@60",  60,  800, 600,  40000000,  88, 40, 26,  1, 128, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 3 800x600-75 VESA */
+	{ "800x600@75",  75,  800, 600,  49500000, 160, 16, 23,  1,  80, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 4 1024x768-60 VESA */
+	{ "1024x768@60", 60, 1024, 768,  65000000, 160, 24, 34,  3, 136, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 5 1024x768-75 VESA */
+	{ "1024x768@75", 75, 1024, 768,  78750000, 176, 16, 30,  1,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 6 1280x960-60 VESA */
+	{ "1280x960@60", 60, 1280, 960, 108000000, 312, 96, 38,  1, 112, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 7 1440x900-60 VESA */
+	{ "1440x900@60", 60, 1440, 900, 106500000, 232, 80, 30,  3, 152, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 8 FIXME 9 1024x600-60 VESA UNTESTED */
+	{ "1024x600@60", 60, 1024, 600,  50650000, 160, 24, 26,  1, 136, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 9 FIXME 10 1024x600-75 VESA UNTESTED */
+	{ "1024x600@75", 75, 1024, 600,  61500000, 176, 16, 23,  1,  96, 1,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+	/* 10 FIXME 11 1366x768-60 VESA UNTESTED */
+	{ "1366x768@60", 60, 1366, 768,  85500000, 256, 58, 18,  1,  112, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA },
+};
+
+static struct fb_var_screeninfo unifb_default = {
+	.xres =		640,
+	.yres =		480,
+	.xres_virtual =	640,
+	.yres_virtual =	480,
+	.bits_per_pixel = 16,
+	.red =		{ 11, 5, 0 },
+	.green =	{ 5,  6, 0 },
+	.blue =		{ 0,  5, 0 },
+	.activate =	FB_ACTIVATE_NOW,
+	.height =	-1,
+	.width =	-1,
+	.pixclock =	25175000,
+	.left_margin =	48,
+	.right_margin =	16,
+	.upper_margin =	33,
+	.lower_margin =	10,
+	.hsync_len =	96,
+	.vsync_len =	2,
+	.vmode =	FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo unifb_fix = {
+	.id =		"UNIGFX FB",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_TRUECOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	1,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static void unifb_sync(struct fb_info *info)
+{
+	/* TODO: may, this can be replaced by interrupt */
+	int cnt;
+
+	for (cnt = 0; cnt < 0x10000000; cnt++) {
+		if (readl(UGE_COMMAND) & 0x1000000)
+			return;
+	}
+
+	if (cnt > 0x8000000)
+		dev_warn(info->device, "Warning: UniGFX GE time out ...\n");
+}
+
+static void unifb_prim_fillrect(struct fb_info *info,
+				const struct fb_fillrect *region)
+{
+	int awidth = region->width;
+	int aheight = region->height;
+	int m_iBpp = info->var.bits_per_pixel;
+	int screen_width = info->var.xres;
+	int src_sel = 1;	/* from fg_color */
+	int pat_sel = 1;
+	int src_x0 = 0;
+	int dst_x0 = region->dx;
+	int src_y0 = 0;
+	int dst_y0 = region->dy;
+	int rop_alpha_sel = 0;
+	int rop_alpha_code = 0xCC;
+	int x_dir = 1;
+	int y_dir = 1;
+	int alpha_r = 0;
+	int alpha_sel = 0;
+	int dst_pitch = screen_width * (m_iBpp / 8);
+	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+	int src_pitch = screen_width * (m_iBpp / 8);
+	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+	unsigned int command = 0;
+	int clip_region = 0;
+	int clip_en = 0;
+	int tp_en = 0;
+	int fg_color = 0;
+	int bottom = info->var.yres - 1;
+	int right = info->var.xres - 1;
+	int top = 0;
+
+	bottom = (bottom << 16) | right;
+	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16)
+		| (x_dir << 20) | (y_dir << 21) | (command << 24)
+		| (clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+	src_pitch = (dst_pitch << 16) | src_pitch;
+	awidth = awidth | (aheight << 16);
+	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff)
+		| (alpha_sel << 16);
+	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+	fg_color = region->color;
+
+	unifb_sync(info);
+
+	writel(((u32 *)(info->pseudo_palette))[fg_color], UGE_FCOLOR);
+	writel(0, UGE_BCOLOR);
+	writel(src_pitch, UGE_PITCH);
+	writel(src_offset, UGE_SRCSTART);
+	writel(dst_offset, UGE_DSTSTART);
+	writel(awidth, UGE_WIDHEIGHT);
+	writel(top, UGE_CLIP0);
+	writel(bottom, UGE_CLIP1);
+	writel(alpha_r, UGE_ROPALPHA);
+	writel(src_x0, UGE_SRCXY);
+	writel(dst_x0, UGE_DSTXY);
+	writel(command, UGE_COMMAND);
+}
+
+static void unifb_fillrect(struct fb_info *info,
+		const struct fb_fillrect *region)
+{
+	struct fb_fillrect modded;
+	int vxres, vyres;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		sys_fillrect(info, region);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	memcpy(&modded, region, sizeof(struct fb_fillrect));
+
+	if (!modded.width || !modded.height ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	unifb_prim_fillrect(info, &modded);
+}
+
+static void unifb_prim_copyarea(struct fb_info *info,
+				const struct fb_copyarea *area)
+{
+	int awidth = area->width;
+	int aheight = area->height;
+	int m_iBpp = info->var.bits_per_pixel;
+	int screen_width = info->var.xres;
+	int src_sel = 2;	/* from mem */
+	int pat_sel = 0;
+	int src_x0 = area->sx;
+	int dst_x0 = area->dx;
+	int src_y0 = area->sy;
+	int dst_y0 = area->dy;
+
+	int rop_alpha_sel = 0;
+	int rop_alpha_code = 0xCC;
+	int x_dir = 1;
+	int y_dir = 1;
+
+	int alpha_r = 0;
+	int alpha_sel = 0;
+	int dst_pitch = screen_width * (m_iBpp / 8);
+	int dst_offset = dst_y0 * dst_pitch + dst_x0 * (m_iBpp / 8);
+	int src_pitch = screen_width * (m_iBpp / 8);
+	int src_offset = src_y0 * src_pitch + src_x0 * (m_iBpp / 8);
+	unsigned int command = 0;
+	int clip_region = 0;
+	int clip_en = 1;
+	int tp_en = 0;
+	int top = 0;
+	int bottom = info->var.yres;
+	int right = info->var.xres;
+	int fg_color = 0;
+	int bg_color = 0;
+
+	if (src_x0 < 0)
+		src_x0 = 0;
+	if (src_y0 < 0)
+		src_y0 = 0;
+
+	if (src_y0 - dst_y0 > 0) {
+		y_dir = 1;
+	} else {
+		y_dir = 0;
+		src_offset = (src_y0 + aheight) * src_pitch +
+				src_x0 * (m_iBpp / 8);
+		dst_offset = (dst_y0 + aheight) * dst_pitch +
+				dst_x0 * (m_iBpp / 8);
+		src_y0 += aheight;
+		dst_y0 += aheight;
+	}
+
+	command = (rop_alpha_sel << 26) | (pat_sel << 18) | (src_sel << 16) |
+		(x_dir << 20) | (y_dir << 21) | (command << 24) |
+		(clip_region << 23) | (clip_en << 22) | (tp_en << 27);
+	src_pitch = (dst_pitch << 16) | src_pitch;
+	awidth = awidth | (aheight << 16);
+	alpha_r = ((rop_alpha_code & 0xff) << 8) | (alpha_r & 0xff) |
+		(alpha_sel << 16);
+	src_x0 = (src_x0 & 0x1fff) | ((src_y0 & 0x1fff) << 16);
+	dst_x0 = (dst_x0 & 0x1fff) | ((dst_y0 & 0x1fff) << 16);
+	bottom = (bottom << 16) | right;
+
+	unifb_sync(info);
+
+	writel(src_pitch, UGE_PITCH);
+	writel(src_offset, UGE_SRCSTART);
+	writel(dst_offset, UGE_DSTSTART);
+	writel(awidth, UGE_WIDHEIGHT);
+	writel(top, UGE_CLIP0);
+	writel(bottom, UGE_CLIP1);
+	writel(bg_color, UGE_BCOLOR);
+	writel(fg_color, UGE_FCOLOR);
+	writel(alpha_r, UGE_ROPALPHA);
+	writel(src_x0, UGE_SRCXY);
+	writel(dst_x0, UGE_DSTXY);
+	writel(command, UGE_COMMAND);
+}
+
+static void unifb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct fb_copyarea modded;
+	u32 vxres, vyres;
+	modded.sx = area->sx;
+	modded.sy = area->sy;
+	modded.dx = area->dx;
+	modded.dy = area->dy;
+	modded.width = area->width;
+	modded.height = area->height;
+
+	if (info->flags & FBINFO_HWACCEL_DISABLED) {
+		sys_copyarea(info, area);
+		return;
+	}
+
+	vxres = info->var.xres_virtual;
+	vyres = info->var.yres_virtual;
+
+	if (!modded.width || !modded.height ||
+	    modded.sx >= vxres || modded.sy >= vyres ||
+	    modded.dx >= vxres || modded.dy >= vyres)
+		return;
+
+	if (modded.sx + modded.width > vxres)
+		modded.width = vxres - modded.sx;
+	if (modded.dx + modded.width > vxres)
+		modded.width = vxres - modded.dx;
+	if (modded.sy + modded.height > vyres)
+		modded.height = vyres - modded.sy;
+	if (modded.dy + modded.height > vyres)
+		modded.height = vyres - modded.dy;
+
+	unifb_prim_copyarea(info, &modded);
+}
+
+static void unifb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	sys_imageblit(info, image);
+}
+
+static u_long get_line_length(int xres_virtual, int bpp)
+{
+	u_long length;
+
+	length = xres_virtual * bpp;
+	length = (length + 31) & ~31;
+	length >>= 3;
+	return length;
+}
+
+/*
+ *  Setting the video mode has been split into two parts.
+ *  First part, xxxfb_check_var, must not write anything
+ *  to hardware, it should only verify and adjust var.
+ *  This means it doesn't alter par but it does use hardware
+ *  data from it to check this var.
+ */
+static int unifb_check_var(struct fb_var_screeninfo *var,
+			 struct fb_info *info)
+{
+	u_long line_length;
+
+	/*
+	 *  FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!
+	 *  as FB_VMODE_SMOOTH_XPAN is only used internally
+	 */
+
+	if (var->vmode & FB_VMODE_CONUPDATE) {
+		var->vmode |= FB_VMODE_YWRAP;
+		var->xoffset = info->var.xoffset;
+		var->yoffset = info->var.yoffset;
+	}
+
+	/*
+	 *  Some very basic checks
+	 */
+	if (!var->xres)
+		var->xres = 1;
+	if (!var->yres)
+		var->yres = 1;
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+	if (var->bits_per_pixel <= 1)
+		var->bits_per_pixel = 1;
+	else if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else if (var->bits_per_pixel <= 24)
+		var->bits_per_pixel = 24;
+	else if (var->bits_per_pixel <= 32)
+		var->bits_per_pixel = 32;
+	else
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xoffset + var->xres)
+		var->xres_virtual = var->xoffset + var->xres;
+	if (var->yres_virtual < var->yoffset + var->yres)
+		var->yres_virtual = var->yoffset + var->yres;
+
+	/*
+	 *  Memory limit
+	 */
+	line_length =
+	    get_line_length(var->xres_virtual, var->bits_per_pixel);
+	if (line_length * var->yres_virtual > UNIFB_MEMSIZE)
+		return -ENOMEM;
+
+	/*
+	 * Now that we checked it we alter var. The reason being is that the
+	 * video mode passed in might not work but slight changes to it might
+	 * make it work. This way we let the user know what is acceptable.
+	 */
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:		/* RGBA 5551 */
+		if (var->transp.length) {
+			var->red.offset = 0;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 10;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {	/* RGB 565 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:		/* RGB 888 */
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:		/* RGBA 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		break;
+	}
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	return 0;
+}
+
+/*
+ * This routine actually sets the video mode. It's in here where we
+ * the hardware state info->par and fix which can be affected by the
+ * change in par. For this driver it doesn't do much.
+ */
+static int unifb_set_par(struct fb_info *info)
+{
+	int hTotal, vTotal, hSyncStart, hSyncEnd, vSyncStart, vSyncEnd;
+	int format;
+
+#ifdef CONFIG_PUV3_PM
+	struct clk *clk_vga;
+	u32 pixclk = 0;
+	int i;
+
+	for (i = 0; i <= 10; i++) {
+		if    (info->var.xres         == unifb_modes[i].xres
+		    && info->var.yres         == unifb_modes[i].yres
+		    && info->var.upper_margin == unifb_modes[i].upper_margin
+		    && info->var.lower_margin == unifb_modes[i].lower_margin
+		    && info->var.left_margin  == unifb_modes[i].left_margin
+		    && info->var.right_margin == unifb_modes[i].right_margin
+		    && info->var.hsync_len    == unifb_modes[i].hsync_len
+		    && info->var.vsync_len    == unifb_modes[i].vsync_len) {
+			pixclk = unifb_modes[i].pixclock;
+			break;
+		}
+	}
+
+	/* set clock rate */
+	clk_vga = clk_get(info->device, "VGA_CLK");
+	if (clk_vga == ERR_PTR(-ENOENT))
+		return -ENOENT;
+
+	if (pixclk != 0) {
+		if (clk_set_rate(clk_vga, pixclk)) { /* set clock failed */
+			info->fix = unifb_fix;
+			info->var = unifb_default;
+			if (clk_set_rate(clk_vga, unifb_default.pixclock))
+				return -EINVAL;
+		}
+	}
+#endif
+
+	info->fix.line_length = get_line_length(info->var.xres_virtual,
+						info->var.bits_per_pixel);
+
+	hSyncStart = info->var.xres + info->var.right_margin;
+	hSyncEnd = hSyncStart + info->var.hsync_len;
+	hTotal = hSyncEnd + info->var.left_margin;
+
+	vSyncStart = info->var.yres + info->var.lower_margin;
+	vSyncEnd = vSyncStart + info->var.vsync_len;
+	vTotal = vSyncEnd + info->var.upper_margin;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		format = UDE_CFG_DST8;
+		break;
+	case 16:
+		format = UDE_CFG_DST16;
+		break;
+	case 24:
+		format = UDE_CFG_DST24;
+		break;
+	case 32:
+		format = UDE_CFG_DST32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA);
+	writel(info->var.yres, UDE_LS);
+	writel(get_line_length(info->var.xres,
+			info->var.bits_per_pixel) >> 3, UDE_PS);
+			/* >> 3 for hardware required. */
+	writel((hTotal << 16) | (info->var.xres), UDE_HAT);
+	writel(((hTotal - 1) << 16) | (info->var.xres - 1), UDE_HBT);
+	writel(((hSyncEnd - 1) << 16) | (hSyncStart - 1), UDE_HST);
+	writel((vTotal << 16) | (info->var.yres), UDE_VAT);
+	writel(((vTotal - 1) << 16) | (info->var.yres - 1), UDE_VBT);
+	writel(((vSyncEnd - 1) << 16) | (vSyncStart - 1), UDE_VST);
+	writel(UDE_CFG_GDEN_ENABLE | UDE_CFG_TIMEUP_ENABLE
+			| format | 0xC0000001, UDE_CFG);
+
+	return 0;
+}
+
+/*
+ *  Set a single color register. The values supplied are already
+ *  rounded down to the hardware's capabilities (according to the
+ *  entries in the var structure). Return != 0 for invalid regno.
+ */
+static int unifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			 u_int transp, struct fb_info *info)
+{
+	if (regno >= 256)	/* no. of hw registers */
+		return 1;
+
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+#define CNVT_TOHW(val, width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		red = CNVT_TOHW(red, info->var.red.length);
+		green = CNVT_TOHW(green, info->var.green.length);
+		blue = CNVT_TOHW(blue, info->var.blue.length);
+		transp = CNVT_TOHW(transp, info->var.transp.length);
+		break;
+	case FB_VISUAL_DIRECTCOLOR:
+		red = CNVT_TOHW(red, 8);	/* expect 8 bit DAC */
+		green = CNVT_TOHW(green, 8);
+		blue = CNVT_TOHW(blue, 8);
+		/* hey, there is bug in transp handling... */
+		transp = CNVT_TOHW(transp, 8);
+		break;
+	}
+#undef CNVT_TOHW
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return 1;
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset) |
+		    (transp << info->var.transp.offset);
+		switch (info->var.bits_per_pixel) {
+		case 8:
+			break;
+		case 16:
+		case 24:
+		case 32:
+			((u32 *) (info->pseudo_palette))[regno] = v;
+			break;
+		default:
+			return 1;
+		}
+		return 0;
+	}
+	return 0;
+}
+
+/*
+ *  Pan or Wrap the Display
+ *
+ *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int unifb_pan_display(struct fb_var_screeninfo *var,
+			   struct fb_info *info)
+{
+	if (var->vmode & FB_VMODE_YWRAP) {
+		if (var->yoffset < 0
+		    || var->yoffset >= info->var.yres_virtual
+		    || var->xoffset)
+			return -EINVAL;
+	} else {
+		if (var->xoffset + var->xres > info->var.xres_virtual ||
+		    var->yoffset + var->yres > info->var.yres_virtual)
+			return -EINVAL;
+	}
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+	return 0;
+}
+
+int unifb_mmap(struct fb_info *info,
+		    struct vm_area_struct *vma)
+{
+	unsigned long size = vma->vm_end - vma->vm_start;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long pos = info->fix.smem_start + offset;
+
+	if (offset + size > info->fix.smem_len)
+		return -EINVAL;
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
+				vma->vm_page_prot))
+		return -EAGAIN;
+
+	vma->vm_flags |= VM_RESERVED;	/* avoid to swap out this VMA */
+	return 0;
+
+}
+
+static struct fb_ops unifb_ops = {
+	.fb_read        = fb_sys_read,
+	.fb_write       = fb_sys_write,
+	.fb_check_var	= unifb_check_var,
+	.fb_set_par	= unifb_set_par,
+	.fb_setcolreg	= unifb_setcolreg,
+	.fb_pan_display	= unifb_pan_display,
+	.fb_fillrect	= unifb_fillrect,
+	.fb_copyarea	= unifb_copyarea,
+	.fb_imageblit   = unifb_imageblit,
+	.fb_mmap	= unifb_mmap,
+};
+
+/*
+ *  Initialisation
+ */
+static int unifb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	u32 unifb_regs[UNIFB_REGS_NUM];
+	int retval = -ENOMEM;
+	struct resource *iomem, *mapmem;
+
+	info = framebuffer_alloc(sizeof(u32)*256, &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE;
+	info->fbops = &unifb_ops;
+
+	retval = fb_find_mode(&info->var, info, NULL,
+			      unifb_modes, 10, &unifb_modes[0], 16);
+
+	if (!retval || (retval == 4))
+		info->var = unifb_default;
+
+	iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	unifb_fix.mmio_start = iomem->start;
+
+	mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1);
+	unifb_fix.smem_start = mapmem->start;
+	unifb_fix.smem_len = UNIFB_MEMSIZE;
+
+	info->fix = unifb_fix;
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_FLAG_DEFAULT;
+#ifdef FB_ACCEL_PUV3_UNIGFX
+	info->fix.accel = FB_ACCEL_PUV3_UNIGFX;
+#endif
+
+	retval = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (retval < 0)
+		goto err1;
+
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err2;
+	platform_set_drvdata(dev, info);
+	platform_device_add_data(dev, unifb_regs, sizeof(u32) * UNIFB_REGS_NUM);
+
+	printk(KERN_INFO
+	       "fb%d: Virtual frame buffer device, using %dM of video memory\n",
+	       info->node, UNIFB_MEMSIZE >> 20);
+	return 0;
+err2:
+	fb_dealloc_cmap(&info->cmap);
+err1:
+	framebuffer_release(info);
+err:
+	return retval;
+}
+
+static int unifb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int unifb_resume(struct platform_device *dev)
+{
+	int rc = 0;
+	u32 *unifb_regs = dev->dev.platform_data;
+
+	if (dev->dev.power.power_state.event == PM_EVENT_ON)
+		return 0;
+
+	console_lock();
+
+	if (dev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+		writel(unifb_regs[0], UDE_FSA);
+		writel(unifb_regs[1], UDE_LS);
+		writel(unifb_regs[2], UDE_PS);
+		writel(unifb_regs[3], UDE_HAT);
+		writel(unifb_regs[4], UDE_HBT);
+		writel(unifb_regs[5], UDE_HST);
+		writel(unifb_regs[6], UDE_VAT);
+		writel(unifb_regs[7], UDE_VBT);
+		writel(unifb_regs[8], UDE_VST);
+		writel(unifb_regs[9], UDE_CFG);
+	}
+	dev->dev.power.power_state = PMSG_ON;
+
+	console_unlock();
+
+	return rc;
+}
+
+static int unifb_suspend(struct platform_device *dev, pm_message_t mesg)
+{
+	u32 *unifb_regs = dev->dev.platform_data;
+
+	unifb_regs[0] = readl(UDE_FSA);
+	unifb_regs[1] = readl(UDE_LS);
+	unifb_regs[2] = readl(UDE_PS);
+	unifb_regs[3] = readl(UDE_HAT);
+	unifb_regs[4] = readl(UDE_HBT);
+	unifb_regs[5] = readl(UDE_HST);
+	unifb_regs[6] = readl(UDE_VAT);
+	unifb_regs[7] = readl(UDE_VBT);
+	unifb_regs[8] = readl(UDE_VST);
+	unifb_regs[9] = readl(UDE_CFG);
+
+	if (mesg.event == dev->dev.power.power_state.event)
+		return 0;
+
+	switch (mesg.event) {
+	case PM_EVENT_FREEZE:		/* about to take snapshot */
+	case PM_EVENT_PRETHAW:		/* before restoring snapshot */
+		goto done;
+	}
+
+	console_lock();
+
+	/* do nothing... */
+
+	console_unlock();
+
+done:
+	dev->dev.power.power_state = mesg;
+
+	return 0;
+}
+#else
+#define	unifb_resume	NULL
+#define unifb_suspend	NULL
+#endif
+
+static struct platform_driver unifb_driver = {
+	.probe	 = unifb_probe,
+	.remove  = unifb_remove,
+	.resume  = unifb_resume,
+	.suspend = unifb_suspend,
+	.driver  = {
+		.name	= "PKUnity-v3-UNIGFX",
+	},
+};
+
+static int __init unifb_init(void)
+{
+#ifndef MODULE
+	if (fb_get_options("unifb", NULL))
+		return -ENODEV;
+#endif
+
+	return platform_driver_register(&unifb_driver);
+}
+
+module_init(unifb_init);
+
+static void __exit unifb_exit(void)
+{
+	platform_driver_unregister(&unifb_driver);
+}
+
+module_exit(unifb_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c
index 6739b2a..910c5e6 100644
--- a/drivers/video/ffb.c
+++ b/drivers/video/ffb.c
@@ -893,8 +893,7 @@ static void ffb_init_fix(struct fb_info *info)
 	info->fix.accel = FB_ACCEL_SUN_CREATOR;
 }
 
-static int __devinit ffb_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit ffb_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct ffb_fbc __iomem *fbc;
@@ -1052,7 +1051,7 @@ static const struct of_device_id ffb_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ffb_match);
 
-static struct of_platform_driver ffb_driver = {
+static struct platform_driver ffb_driver = {
 	.driver = {
 		.name = "ffb",
 		.owner = THIS_MODULE,
@@ -1067,12 +1066,12 @@ static int __init ffb_init(void)
 	if (fb_get_options("ffb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&ffb_driver);
+	return platform_driver_register(&ffb_driver);
 }
 
 static void __exit ffb_exit(void)
 {
-	of_unregister_platform_driver(&ffb_driver);
+	platform_driver_unregister(&ffb_driver);
 }
 
 module_init(ffb_init);
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 8bbbf08..9048f87 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -1487,8 +1487,7 @@ static ssize_t show_monitor(struct device *device,
 	return diu_ops.show_monitor_port(machine_data->monitor_port, buf);
 }
 
-static int __devinit fsl_diu_probe(struct platform_device *ofdev,
-	const struct of_device_id *match)
+static int __devinit fsl_diu_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct mfb_info *mfbi;
@@ -1735,7 +1734,7 @@ static struct of_device_id fsl_diu_match[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_diu_match);
 
-static struct of_platform_driver fsl_diu_driver = {
+static struct platform_driver fsl_diu_driver = {
 	.driver = {
 		.name = "fsl_diu",
 		.owner = THIS_MODULE,
@@ -1797,7 +1796,7 @@ static int __init fsl_diu_init(void)
 	if (!coherence_data)
 		return -ENOMEM;
 #endif
-	ret = of_register_platform_driver(&fsl_diu_driver);
+	ret = platform_driver_register(&fsl_diu_driver);
 	if (ret) {
 		printk(KERN_ERR
 			"fsl-diu: failed to register platform driver\n");
@@ -1811,7 +1810,7 @@ static int __init fsl_diu_init(void)
 
 static void __exit fsl_diu_exit(void)
 {
-	of_unregister_platform_driver(&fsl_diu_driver);
+	platform_driver_unregister(&fsl_diu_driver);
 #if defined(CONFIG_NOT_COHERENT_CACHE)
 	vfree(coherence_data);
 #endif
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 69bd4a5..ef72cb4 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -499,6 +499,7 @@ static void imxfb_init_backlight(struct imxfb_info *fbi)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = 0xff;
+	props.type = BACKLIGHT_RAW;
 	writel(fbi->pwmr, fbi->regs + LCDC_PWMR);
 
 	bl = backlight_device_register("imxfb-bl", &fbi->pdev->dev, fbi,
diff --git a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile
index 6c782d3..f7d631e 100644
--- a/drivers/video/intelfb/Makefile
+++ b/drivers/video/intelfb/Makefile
@@ -4,7 +4,4 @@ intelfb-y := intelfbdrv.o intelfbhw.o
 intelfb-$(CONFIG_FB_INTEL_I2C) += intelfb_i2c.o
 intelfb-objs := $(intelfb-y)
 
-ifdef CONFIG_FB_INTEL_DEBUG
-#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
-EXTRA_CFLAGS += -DDEBUG -DREGDUMP
-endif
+ccflags-$(CONFIG_FB_INTEL_DEBUG) := -DDEBUG -DREGDUMP
diff --git a/drivers/video/leo.c b/drivers/video/leo.c
index b599e5e..9e946e2 100644
--- a/drivers/video/leo.c
+++ b/drivers/video/leo.c
@@ -547,8 +547,7 @@ static void leo_unmap_regs(struct platform_device *op, struct fb_info *info,
 		of_iounmap(&op->resource[0], info->screen_base, 0x800000);
 }
 
-static int __devinit leo_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit leo_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -662,7 +661,7 @@ static const struct of_device_id leo_match[] = {
 };
 MODULE_DEVICE_TABLE(of, leo_match);
 
-static struct of_platform_driver leo_driver = {
+static struct platform_driver leo_driver = {
 	.driver = {
 		.name = "leo",
 		.owner = THIS_MODULE,
@@ -677,12 +676,12 @@ static int __init leo_init(void)
 	if (fb_get_options("leofb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&leo_driver);
+	return platform_driver_register(&leo_driver);
 }
 
 static void __exit leo_exit(void)
 {
-	of_unregister_platform_driver(&leo_driver);
+	platform_driver_unregister(&leo_driver);
 }
 
 module_init(leo_init);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index a082deb..a74439a 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -1461,13 +1461,6 @@ static struct board {
 		MGA_G100,
 		&vbG100,
 		"MGA-G100 (AGP)"},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200EV_PCI,	0xFF,
-		0,			0,
-		DEVF_G200,
-		230000,
-		MGA_G200,
-		&vbG200,
-		"MGA-G200eV (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,	0xFF,
 		0,			0,
 		DEVF_G200,
@@ -2119,8 +2112,6 @@ static struct pci_device_id matroxfb_devices[] = {
 		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,
 		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
-	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200EV_PCI,
-		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,
 		PCI_ANY_ID,	PCI_ANY_ID,	0, 0, 0},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c
index b1c4374..c76e663 100644
--- a/drivers/video/mb862xx/mb862xxfb.c
+++ b/drivers/video/mb862xx/mb862xxfb.c
@@ -550,8 +550,7 @@ static int mb862xx_gdc_init(struct mb862xxfb_par *par)
 	return 0;
 }
 
-static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev,
-					       const struct of_device_id *id)
+static int __devinit of_platform_mb862xx_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct device *dev = &ofdev->dev;
@@ -717,7 +716,7 @@ static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = {
 	{ /* end */ }
 };
 
-static struct of_platform_driver of_platform_mb862xxfb_driver = {
+static struct platform_driver of_platform_mb862xxfb_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -1038,7 +1037,7 @@ static int __devinit mb862xxfb_init(void)
 	int ret = -ENODEV;
 
 #if defined(CONFIG_FB_MB862XX_LIME)
-	ret = of_register_platform_driver(&of_platform_mb862xxfb_driver);
+	ret = platform_driver_register(&of_platform_mb862xxfb_driver);
 #endif
 #if defined(CONFIG_FB_MB862XX_PCI_GDC)
 	ret = pci_register_driver(&mb862xxfb_pci_driver);
@@ -1049,7 +1048,7 @@ static int __devinit mb862xxfb_init(void)
 static void __exit mb862xxfb_exit(void)
 {
 #if defined(CONFIG_FB_MB862XX_LIME)
-	of_unregister_platform_driver(&of_platform_mb862xxfb_driver);
+	platform_driver_unregister(&of_platform_mb862xxfb_driver);
 #endif
 #if defined(CONFIG_FB_MB862XX_PCI_GDC)
 	pci_unregister_driver(&mb862xxfb_pci_driver);
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index 4e3deb4..d804774 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -449,6 +449,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 #define PPP_CFG_MDP_XRGB_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
 #define PPP_CFG_MDP_RGBA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
 #define PPP_CFG_MDP_BGRA_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
+#define PPP_CFG_MDP_RGBX_8888(dir) PPP_CFG_MDP_ARGB_8888(dir)
 
 #define PPP_CFG_MDP_Y_CBCR_H2V2(dir)   (PPP_##dir##_C2R_8BIT | \
 					PPP_##dir##_C0G_8BIT | \
@@ -488,12 +489,14 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 	MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8)
 #define PPP_PACK_PATTERN_MDP_RGB_888 PPP_PACK_PATTERN_MDP_RGB_565
 #define PPP_PACK_PATTERN_MDP_XRGB_8888 \
-	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
+	MDP_GET_PACK_PATTERN(CLR_B, CLR_G, CLR_R, CLR_ALPHA, 8)
 #define PPP_PACK_PATTERN_MDP_ARGB_8888 PPP_PACK_PATTERN_MDP_XRGB_8888
 #define PPP_PACK_PATTERN_MDP_RGBA_8888 \
 	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
 #define PPP_PACK_PATTERN_MDP_BGRA_8888 \
 	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B, 8)
+#define PPP_PACK_PATTERN_MDP_RGBX_8888 \
+	MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R, 8)
 #define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1 \
 	MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8)
 #define PPP_PACK_PATTERN_MDP_Y_CBCR_H2V2 PPP_PACK_PATTERN_MDP_Y_CBCR_H2V1
@@ -509,6 +512,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 #define PPP_CHROMA_SAMP_MDP_ARGB_8888(dir) PPP_OP_##dir##_CHROMA_RGB
 #define PPP_CHROMA_SAMP_MDP_RGBA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
 #define PPP_CHROMA_SAMP_MDP_BGRA_8888(dir) PPP_OP_##dir##_CHROMA_RGB
+#define PPP_CHROMA_SAMP_MDP_RGBX_8888(dir) PPP_OP_##dir##_CHROMA_RGB
 #define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
 #define PPP_CHROMA_SAMP_MDP_Y_CBCR_H2V2(dir) PPP_OP_##dir##_CHROMA_420
 #define PPP_CHROMA_SAMP_MDP_Y_CRCB_H2V1(dir) PPP_OP_##dir##_CHROMA_H2V1
@@ -523,6 +527,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 	[MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888,\
 	[MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888,\
 	[MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888,\
+	[MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888,\
 	[MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1,\
 	[MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2,\
 	[MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1,\
@@ -536,6 +541,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 	[MDP_ARGB_8888] = PPP_##name##_MDP_ARGB_8888(dir),\
 	[MDP_RGBA_8888] = PPP_##name##_MDP_RGBA_8888(dir),\
 	[MDP_BGRA_8888] = PPP_##name##_MDP_BGRA_8888(dir),\
+	[MDP_RGBX_8888] = PPP_##name##_MDP_RGBX_8888(dir),\
 	[MDP_Y_CBCR_H2V1] = PPP_##name##_MDP_Y_CBCR_H2V1(dir),\
 	[MDP_Y_CBCR_H2V2] = PPP_##name##_MDP_Y_CBCR_H2V2(dir),\
 	[MDP_Y_CRCB_H2V1] = PPP_##name##_MDP_Y_CRCB_H2V1(dir),\
@@ -547,7 +553,8 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		       (img == MDP_YCRYCB_H2V1))
 #define IS_RGB(img) ((img == MDP_RGB_565) | (img == MDP_RGB_888) | \
 		     (img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
-		     (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888))
+		     (img == MDP_XRGB_8888) | (img == MDP_BGRA_8888) | \
+		     (img == MDP_RGBX_8888))
 #define HAS_ALPHA(img) ((img == MDP_ARGB_8888) | (img == MDP_RGBA_8888) | \
 			(img == MDP_BGRA_8888))
 
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 4ff001f..2b6564e 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -69,6 +69,7 @@ static uint32_t bytes_per_pixel[] = {
 	[MDP_ARGB_8888] = 4,
 	[MDP_RGBA_8888] = 4,
 	[MDP_BGRA_8888] = 4,
+	[MDP_RGBX_8888] = 4,
 	[MDP_Y_CBCR_H2V1] = 1,
 	[MDP_Y_CBCR_H2V2] = 1,
 	[MDP_Y_CRCB_H2V1] = 1,
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index debe593..ec35130 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -81,7 +81,6 @@ struct msmfb_info {
 	spinlock_t update_lock;
 	struct mutex panel_init_lock;
 	wait_queue_head_t frame_wq;
-	struct workqueue_struct *resume_workqueue;
 	struct work_struct resume_work;
 	struct msmfb_callback dma_callback;
 	struct msmfb_callback vsync_callback;
@@ -111,7 +110,7 @@ static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
 	if (msmfb->sleeping == UPDATING &&
 	    msmfb->frame_done == msmfb->update_frame) {
 		DLOG(SUSPEND_RESUME, "full update completed\n");
-		queue_work(msmfb->resume_workqueue, &msmfb->resume_work);
+		schedule_work(&msmfb->resume_work);
 	}
 	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
 	wake_up(&msmfb->frame_wq);
@@ -220,8 +219,8 @@ restart:
 
 	sleeping = msmfb->sleeping;
 	/* on a full update, if the last frame has not completed, wait for it */
-	if (pan_display && (msmfb->frame_requested != msmfb->frame_done ||
-			    sleeping == UPDATING)) {
+	if ((pan_display && msmfb->frame_requested != msmfb->frame_done) ||
+			    sleeping == UPDATING) {
 		int ret;
 		spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
 		ret = wait_event_interruptible_timeout(msmfb->frame_wq,
@@ -470,6 +469,18 @@ static void setup_fb_info(struct msmfb_info *msmfb)
 	fb_info->var.yoffset = 0;
 
 	if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
+		/*
+		 * Set the param in the fixed screen, so userspace can't
+		 * change it. This will be used to check for the
+		 * capability.
+		 */
+		fb_info->fix.reserved[0] = 0x5444;
+		fb_info->fix.reserved[1] = 0x5055;
+
+		/*
+		 * This preloads the value so that if userspace doesn't
+		 * change it, it will be a full update
+		 */
 		fb_info->var.reserved[0] = 0x54445055;
 		fb_info->var.reserved[1] = 0;
 		fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
@@ -559,12 +570,6 @@ static int msmfb_probe(struct platform_device *pdev)
 	spin_lock_init(&msmfb->update_lock);
 	mutex_init(&msmfb->panel_init_lock);
 	init_waitqueue_head(&msmfb->frame_wq);
-	msmfb->resume_workqueue = create_workqueue("panel_on");
-	if (msmfb->resume_workqueue == NULL) {
-		printk(KERN_ERR "failed to create panel_on workqueue\n");
-		ret = -ENOMEM;
-		goto error_create_workqueue;
-	}
 	INIT_WORK(&msmfb->resume_work, power_on_panel);
 	msmfb->black = kzalloc(msmfb->fb->var.bits_per_pixel*msmfb->xres,
 			       GFP_KERNEL);
@@ -589,8 +594,6 @@ static int msmfb_probe(struct platform_device *pdev)
 	return 0;
 
 error_register_framebuffer:
-	destroy_workqueue(msmfb->resume_workqueue);
-error_create_workqueue:
 	iounmap(fb->screen_base);
 error_setup_fbmem:
 	framebuffer_release(msmfb->fb);
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
new file mode 100644
index 0000000..7d02848
--- /dev/null
+++ b/drivers/video/mxsfb.c
@@ -0,0 +1,919 @@
+/*
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix
+ *
+ * This code is based on:
+ * Author: Vitaly Wool <vital@embeddedalley.com>
+ *
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Embedded Alley Solutions, 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.
+ */
+
+#define DRIVER_NAME "mxsfb"
+
+/**
+ * @file
+ * @brief LCDIF driver for i.MX23 and i.MX28
+ *
+ * The LCDIF support four modes of operation
+ * - MPU interface (to drive smart displays) -> not supported yet
+ * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet
+ * - Dotclock interface (to drive LC displays with RGB data and sync signals)
+ * - DVI (to drive ITU-R BT656)  -> not supported yet
+ *
+ * This driver depends on a correct setup of the pins used for this purpose
+ * (platform specific).
+ *
+ * For the developer: Don't forget to set the data bus width to the display
+ * in the imx_fb_videomode structure. You will else end up with ugly colours.
+ * If you fight against jitter you can vary the clock delay. This is a feature
+ * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give
+ * the required value in the imx_fb_videomode structure.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <mach/mxsfb.h>
+
+#define REG_SET	4
+#define REG_CLR	8
+
+#define LCDC_CTRL			0x00
+#define LCDC_CTRL1			0x10
+#define LCDC_V4_CTRL2			0x20
+#define LCDC_V3_TRANSFER_COUNT		0x20
+#define LCDC_V4_TRANSFER_COUNT		0x30
+#define LCDC_V4_CUR_BUF			0x40
+#define LCDC_V4_NEXT_BUF		0x50
+#define LCDC_V3_CUR_BUF			0x30
+#define LCDC_V3_NEXT_BUF		0x40
+#define LCDC_TIMING			0x60
+#define LCDC_VDCTRL0			0x70
+#define LCDC_VDCTRL1			0x80
+#define LCDC_VDCTRL2			0x90
+#define LCDC_VDCTRL3			0xa0
+#define LCDC_VDCTRL4			0xb0
+#define LCDC_DVICTRL0			0xc0
+#define LCDC_DVICTRL1			0xd0
+#define LCDC_DVICTRL2			0xe0
+#define LCDC_DVICTRL3			0xf0
+#define LCDC_DVICTRL4			0x100
+#define LCDC_V4_DATA			0x180
+#define LCDC_V3_DATA			0x1b0
+#define LCDC_V4_DEBUG0			0x1d0
+#define LCDC_V3_DEBUG0			0x1f0
+
+#define CTRL_SFTRST			(1 << 31)
+#define CTRL_CLKGATE			(1 << 30)
+#define CTRL_BYPASS_COUNT		(1 << 19)
+#define CTRL_VSYNC_MODE			(1 << 18)
+#define CTRL_DOTCLK_MODE		(1 << 17)
+#define CTRL_DATA_SELECT		(1 << 16)
+#define CTRL_SET_BUS_WIDTH(x)		(((x) & 0x3) << 10)
+#define CTRL_GET_BUS_WIDTH(x)		(((x) >> 10) & 0x3)
+#define CTRL_SET_WORD_LENGTH(x)		(((x) & 0x3) << 8)
+#define CTRL_GET_WORD_LENGTH(x)		(((x) >> 8) & 0x3)
+#define CTRL_MASTER			(1 << 5)
+#define CTRL_DF16			(1 << 3)
+#define CTRL_DF18			(1 << 2)
+#define CTRL_DF24			(1 << 1)
+#define CTRL_RUN			(1 << 0)
+
+#define CTRL1_FIFO_CLEAR		(1 << 21)
+#define CTRL1_SET_BYTE_PACKAGING(x)	(((x) & 0xf) << 16)
+#define CTRL1_GET_BYTE_PACKAGING(x)	(((x) >> 16) & 0xf)
+
+#define TRANSFER_COUNT_SET_VCOUNT(x)	(((x) & 0xffff) << 16)
+#define TRANSFER_COUNT_GET_VCOUNT(x)	(((x) >> 16) & 0xffff)
+#define TRANSFER_COUNT_SET_HCOUNT(x)	((x) & 0xffff)
+#define TRANSFER_COUNT_GET_HCOUNT(x)	((x) & 0xffff)
+
+
+#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_ENABLE_ACT_HIGH		(1 << 24)
+#define VDCTRL0_VSYNC_PERIOD_UNIT	(1 << 21)
+#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT	(1 << 20)
+#define VDCTRL0_HALF_LINE		(1 << 19)
+#define VDCTRL0_HALF_LINE_MODE		(1 << 18)
+#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff)
+
+#define VDCTRL2_SET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
+#define VDCTRL2_GET_HSYNC_PERIOD(x)	((x) & 0x3ffff)
+
+#define VDCTRL3_MUX_SYNC_SIGNALS	(1 << 29)
+#define VDCTRL3_VSYNC_ONLY		(1 << 28)
+#define SET_HOR_WAIT_CNT(x)		(((x) & 0xfff) << 16)
+#define GET_HOR_WAIT_CNT(x)		(((x) >> 16) & 0xfff)
+#define SET_VERT_WAIT_CNT(x)		((x) & 0xffff)
+#define GET_VERT_WAIT_CNT(x)		((x) & 0xffff)
+
+#define VDCTRL4_SET_DOTCLK_DLY(x)	(((x) & 0x7) << 29) /* v4 only */
+#define VDCTRL4_GET_DOTCLK_DLY(x)	(((x) >> 29) & 0x7) /* v4 only */
+#define VDCTRL4_SYNC_SIGNALS_ON		(1 << 18)
+#define SET_DOTCLK_H_VALID_DATA_CNT(x)	((x) & 0x3ffff)
+
+#define DEBUG0_HSYNC			(1 < 26)
+#define DEBUG0_VSYNC			(1 < 25)
+
+#define MIN_XRES			120
+#define MIN_YRES			120
+
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define TRANSP 3
+
+enum mxsfb_devtype {
+	MXSFB_V3,
+	MXSFB_V4,
+};
+
+/* CPU dependent register offsets */
+struct mxsfb_devdata {
+	unsigned transfer_count;
+	unsigned cur_buf;
+	unsigned next_buf;
+	unsigned debug0;
+	unsigned hs_wdth_mask;
+	unsigned hs_wdth_shift;
+	unsigned ipversion;
+};
+
+struct mxsfb_info {
+	struct fb_info fb_info;
+	struct platform_device *pdev;
+	struct clk *clk;
+	void __iomem *base;	/* registers */
+	unsigned allocated_size;
+	int enabled;
+	unsigned ld_intf_width;
+	unsigned dotclk_delay;
+	const struct mxsfb_devdata *devdata;
+	int mapped;
+};
+
+#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
+#define mxsfb_is_v4(host) (host->devdata->ipversion == 4)
+
+static const struct mxsfb_devdata mxsfb_devdata[] = {
+	[MXSFB_V3] = {
+		.transfer_count = LCDC_V3_TRANSFER_COUNT,
+		.cur_buf = LCDC_V3_CUR_BUF,
+		.next_buf = LCDC_V3_NEXT_BUF,
+		.debug0 = LCDC_V3_DEBUG0,
+		.hs_wdth_mask = 0xff,
+		.hs_wdth_shift = 24,
+		.ipversion = 3,
+	},
+	[MXSFB_V4] = {
+		.transfer_count = LCDC_V4_TRANSFER_COUNT,
+		.cur_buf = LCDC_V4_CUR_BUF,
+		.next_buf = LCDC_V4_NEXT_BUF,
+		.debug0 = LCDC_V4_DEBUG0,
+		.hs_wdth_mask = 0x3fff,
+		.hs_wdth_shift = 18,
+		.ipversion = 4,
+	},
+};
+
+#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info))
+
+/* mask and shift depends on architecture */
+static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
+{
+	return (val & host->devdata->hs_wdth_mask) <<
+		host->devdata->hs_wdth_shift;
+}
+
+static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val)
+{
+	return (val >> host->devdata->hs_wdth_shift) &
+		host->devdata->hs_wdth_mask;
+}
+
+static const struct fb_bitfield def_rgb565[] = {
+	[RED] = {
+		.offset = 11,
+		.length = 5,
+	},
+	[GREEN] = {
+		.offset = 5,
+		.length = 6,
+	},
+	[BLUE] = {
+		.offset = 0,
+		.length = 5,
+	},
+	[TRANSP] = {	/* no support for transparency */
+		.length = 0,
+	}
+};
+
+static const struct fb_bitfield def_rgb666[] = {
+	[RED] = {
+		.offset = 16,
+		.length = 6,
+	},
+	[GREEN] = {
+		.offset = 8,
+		.length = 6,
+	},
+	[BLUE] = {
+		.offset = 0,
+		.length = 6,
+	},
+	[TRANSP] = {	/* no support for transparency */
+		.length = 0,
+	}
+};
+
+static const struct fb_bitfield def_rgb888[] = {
+	[RED] = {
+		.offset = 16,
+		.length = 8,
+	},
+	[GREEN] = {
+		.offset = 8,
+		.length = 8,
+	},
+	[BLUE] = {
+		.offset = 0,
+		.length = 8,
+	},
+	[TRANSP] = {	/* no support for transparency */
+		.length = 0,
+	}
+};
+
+static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int mxsfb_check_var(struct fb_var_screeninfo *var,
+		struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	const struct fb_bitfield *rgb = NULL;
+
+	if (var->xres < MIN_XRES)
+		var->xres = MIN_XRES;
+	if (var->yres < MIN_YRES)
+		var->yres = MIN_YRES;
+
+	var->xres_virtual = var->xres;
+
+	var->yres_virtual = var->yres;
+
+	switch (var->bits_per_pixel) {
+	case 16:
+		/* always expect RGB 565 */
+		rgb = def_rgb565;
+		break;
+	case 32:
+		switch (host->ld_intf_width) {
+		case STMLCDIF_8BIT:
+			pr_debug("Unsupported LCD bus width mapping\n");
+			break;
+		case STMLCDIF_16BIT:
+		case STMLCDIF_18BIT:
+			/* 24 bit to 18 bit mapping */
+			rgb = def_rgb666;
+			break;
+		case STMLCDIF_24BIT:
+			/* real 24 bit */
+			rgb = def_rgb888;
+			break;
+		}
+		break;
+	default:
+		pr_debug("Unsupported colour depth: %u\n", var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	/*
+	 * Copy the RGB parameters for this display
+	 * from the machine specific parameters.
+	 */
+	var->red    = rgb[RED];
+	var->green  = rgb[GREEN];
+	var->blue   = rgb[BLUE];
+	var->transp = rgb[TRANSP];
+
+	return 0;
+}
+
+static void mxsfb_enable_controller(struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	u32 reg;
+
+	dev_dbg(&host->pdev->dev, "%s\n", __func__);
+
+	clk_enable(host->clk);
+	clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U);
+
+	/* if it was disabled, re-enable the mode again */
+	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET);
+
+	/* enable the SYNC signals first, then the DMA engine */
+	reg = readl(host->base + LCDC_VDCTRL4);
+	reg |= VDCTRL4_SYNC_SIGNALS_ON;
+	writel(reg, host->base + LCDC_VDCTRL4);
+
+	writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET);
+
+	host->enabled = 1;
+}
+
+static void mxsfb_disable_controller(struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	unsigned loop;
+	u32 reg;
+
+	dev_dbg(&host->pdev->dev, "%s\n", __func__);
+
+	/*
+	 * Even if we disable the controller here, it will still continue
+	 * until its FIFOs are running out of data
+	 */
+	writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR);
+
+	loop = 1000;
+	while (loop) {
+		reg = readl(host->base + LCDC_CTRL);
+		if (!(reg & CTRL_RUN))
+			break;
+		loop--;
+	}
+
+	writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR);
+
+	clk_disable(host->clk);
+
+	host->enabled = 0;
+}
+
+static int mxsfb_set_par(struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	u32 ctrl, vdctrl0, vdctrl4;
+	int line_size, fb_size;
+	int reenable = 0;
+
+	line_size =  fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3);
+	fb_size = fb_info->var.yres_virtual * line_size;
+
+	if (fb_size > fb_info->fix.smem_len)
+		return -ENOMEM;
+
+	fb_info->fix.line_length = line_size;
+
+	/*
+	 * It seems, you can't re-program the controller if it is still running.
+	 * This may lead into shifted pictures (FIFO issue?).
+	 * So, first stop the controller and drain its FIFOs
+	 */
+	if (host->enabled) {
+		reenable = 1;
+		mxsfb_disable_controller(fb_info);
+	}
+
+	/* clear the FIFOs */
+	writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET);
+
+	ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER |
+		CTRL_SET_BUS_WIDTH(host->ld_intf_width);;
+
+	switch (fb_info->var.bits_per_pixel) {
+	case 16:
+		dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n");
+		ctrl |= CTRL_SET_WORD_LENGTH(0);
+		writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1);
+		break;
+	case 32:
+		dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n");
+		ctrl |= CTRL_SET_WORD_LENGTH(3);
+		switch (host->ld_intf_width) {
+		case STMLCDIF_8BIT:
+			dev_dbg(&host->pdev->dev,
+					"Unsupported LCD bus width mapping\n");
+			return -EINVAL;
+		case STMLCDIF_16BIT:
+		case STMLCDIF_18BIT:
+			/* 24 bit to 18 bit mapping */
+			ctrl |= CTRL_DF24; /* ignore the upper 2 bits in
+					    *  each colour component
+					    */
+			break;
+		case STMLCDIF_24BIT:
+			/* real 24 bit */
+			break;
+		}
+		/* do not use packed pixels = one pixel per word instead */
+		writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1);
+		break;
+	default:
+		dev_dbg(&host->pdev->dev, "Unhandled color depth of %u\n",
+				fb_info->var.bits_per_pixel);
+		return -EINVAL;
+	}
+
+	writel(ctrl, host->base + LCDC_CTRL);
+
+	writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) |
+			TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres),
+			host->base + host->devdata->transfer_count);
+
+	vdctrl0 = VDCTRL0_ENABLE_PRESENT |	/* always in DOTCLOCK mode */
+		VDCTRL0_VSYNC_PERIOD_UNIT |
+		VDCTRL0_VSYNC_PULSE_WIDTH_UNIT |
+		VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len);
+	if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
+	if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
+	if (fb_info->var.sync & FB_SYNC_DATA_ENABLE_HIGH_ACT)
+		vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
+	if (fb_info->var.sync & FB_SYNC_DOTCLK_FAILING_ACT)
+		vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING;
+
+	writel(vdctrl0, host->base + LCDC_VDCTRL0);
+
+	/* frame length in lines */
+	writel(fb_info->var.upper_margin + fb_info->var.vsync_len +
+		fb_info->var.lower_margin + fb_info->var.yres,
+		host->base + LCDC_VDCTRL1);
+
+	/* line length in units of clocks or pixels */
+	writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) |
+		VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin +
+		fb_info->var.hsync_len + fb_info->var.right_margin +
+		fb_info->var.xres),
+		host->base + LCDC_VDCTRL2);
+
+	writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin +
+		fb_info->var.hsync_len) |
+		SET_VERT_WAIT_CNT(fb_info->var.upper_margin +
+			fb_info->var.vsync_len),
+		host->base + LCDC_VDCTRL3);
+
+	vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres);
+	if (mxsfb_is_v4(host))
+		vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay);
+	writel(vdctrl4, host->base + LCDC_VDCTRL4);
+
+	writel(fb_info->fix.smem_start +
+			fb_info->fix.line_length * fb_info->var.yoffset,
+			host->base + host->devdata->next_buf);
+
+	if (reenable)
+		mxsfb_enable_controller(fb_info);
+
+	return 0;
+}
+
+static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		u_int transp, struct fb_info *fb_info)
+{
+	unsigned int val;
+	int ret = -EINVAL;
+
+	/*
+	 * If greyscale is true, then we convert the RGB value
+	 * to greyscale no matter what visual we are using.
+	 */
+	if (fb_info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green +
+					7471 * blue) >> 16;
+
+	switch (fb_info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		/*
+		 * 12 or 16-bit True Colour.  We encode the RGB value
+		 * according to the RGB bitfield information.
+		 */
+		if (regno < 16) {
+			u32 *pal = fb_info->pseudo_palette;
+
+			val  = chan_to_field(red, &fb_info->var.red);
+			val |= chan_to_field(green, &fb_info->var.green);
+			val |= chan_to_field(blue, &fb_info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		break;
+	}
+
+	return ret;
+}
+
+static int mxsfb_blank(int blank, struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+
+	switch (blank) {
+	case FB_BLANK_POWERDOWN:
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_NORMAL:
+		if (host->enabled)
+			mxsfb_disable_controller(fb_info);
+		break;
+
+	case FB_BLANK_UNBLANK:
+		if (!host->enabled)
+			mxsfb_enable_controller(fb_info);
+		break;
+	}
+	return 0;
+}
+
+static int mxsfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *fb_info)
+{
+	struct mxsfb_info *host = to_imxfb_host(fb_info);
+	unsigned offset;
+
+	if (var->xoffset != 0)
+		return -EINVAL;
+
+	offset = fb_info->fix.line_length * var->yoffset;
+
+	/* update on next VSYNC */
+	writel(fb_info->fix.smem_start + offset,
+			host->base + host->devdata->next_buf);
+
+	return 0;
+}
+
+static struct fb_ops mxsfb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = mxsfb_check_var,
+	.fb_set_par = mxsfb_set_par,
+	.fb_setcolreg = mxsfb_setcolreg,
+	.fb_blank = mxsfb_blank,
+	.fb_pan_display = mxsfb_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+};
+
+static int __devinit mxsfb_restore_mode(struct mxsfb_info *host)
+{
+	struct fb_info *fb_info = &host->fb_info;
+	unsigned line_count;
+	unsigned period;
+	unsigned long pa, fbsize;
+	int bits_per_pixel, ofs;
+	u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl;
+	struct fb_videomode vmode;
+
+	/* Only restore the mode when the controller is running */
+	ctrl = readl(host->base + LCDC_CTRL);
+	if (!(ctrl & CTRL_RUN))
+		return -EINVAL;
+
+	vdctrl0 = readl(host->base + LCDC_VDCTRL0);
+	vdctrl2 = readl(host->base + LCDC_VDCTRL2);
+	vdctrl3 = readl(host->base + LCDC_VDCTRL3);
+	vdctrl4 = readl(host->base + LCDC_VDCTRL4);
+
+	transfer_count = readl(host->base + host->devdata->transfer_count);
+
+	vmode.xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count);
+	vmode.yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count);
+
+	switch (CTRL_GET_WORD_LENGTH(ctrl)) {
+	case 0:
+		bits_per_pixel = 16;
+		break;
+	case 3:
+		bits_per_pixel = 32;
+	case 1:
+	default:
+		return -EINVAL;
+	}
+
+	fb_info->var.bits_per_pixel = bits_per_pixel;
+
+	vmode.pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U);
+	vmode.hsync_len = get_hsync_pulse_width(host, vdctrl2);
+	vmode.left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode.hsync_len;
+	vmode.right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - vmode.hsync_len -
+		vmode.left_margin - vmode.xres;
+	vmode.vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0);
+	period = readl(host->base + LCDC_VDCTRL1);
+	vmode.upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode.vsync_len;
+	vmode.lower_margin = period - vmode.vsync_len - vmode.upper_margin - vmode.yres;
+
+	vmode.vmode = FB_VMODE_NONINTERLACED;
+
+	vmode.sync = 0;
+	if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH)
+		vmode.sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH)
+		vmode.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+	pr_debug("Reconstructed video mode:\n");
+	pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n",
+			vmode.xres, vmode.yres,
+			vmode.hsync_len, vmode.left_margin, vmode.right_margin,
+			vmode.vsync_len, vmode.upper_margin, vmode.lower_margin);
+	pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode.pixclock));
+
+	fb_add_videomode(&vmode, &fb_info->modelist);
+
+	host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl);
+	host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4);
+
+	fb_info->fix.line_length = vmode.xres * (bits_per_pixel >> 3);
+
+	pa = readl(host->base + host->devdata->cur_buf);
+	fbsize = fb_info->fix.line_length * vmode.yres;
+	if (pa < fb_info->fix.smem_start)
+		return -EINVAL;
+	if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len)
+		return -EINVAL;
+	ofs = pa - fb_info->fix.smem_start;
+	if (ofs) {
+		memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize);
+		writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
+	}
+
+	line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
+	fb_info->fix.ypanstep = 1;
+
+	clk_enable(host->clk);
+	host->enabled = 1;
+
+	return 0;
+}
+
+static int __devinit 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;
+
+	fb_info->fbops = &mxsfb_ops;
+	fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST;
+	strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id));
+	fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
+	fb_info->fix.ypanstep = 1;
+	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;
+	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;
+
+		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_info->fix.smem_start = fb_phys;
+	fb_info->screen_base = fb_virt;
+	fb_info->screen_size = fb_info->fix.smem_len = fb_size;
+
+	if (mxsfb_restore_mode(host))
+		memset(fb_virt, 0, fb_size);
+
+	return 0;
+}
+
+static void __devexit 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);
+	}
+}
+
+static int __devinit mxsfb_probe(struct platform_device *pdev)
+{
+	struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *res;
+	struct mxsfb_info *host;
+	struct fb_info *fb_info;
+	struct fb_modelist *modelist;
+	int i, ret;
+
+	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;
+	}
+
+	host = to_imxfb_host(fb_info);
+
+	host->base = ioremap(res->start, resource_size(res));
+	if (!host->base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto error_ioremap;
+	}
+
+	host->pdev = pdev;
+	platform_set_drvdata(pdev, host);
+
+	host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];
+
+	host->clk = clk_get(&host->pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto error_getclock;
+	}
+
+	fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+	if (!fb_info->pseudo_palette) {
+		ret = -ENOMEM;
+		goto error_pseudo_pallette;
+	}
+
+	INIT_LIST_HEAD(&fb_info->modelist);
+
+	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);
+
+	modelist = list_first_entry(&fb_info->modelist,
+			struct fb_modelist, list);
+	fb_videomode_to_var(&fb_info->var, &modelist->mode);
+
+	/* init the color fields */
+	mxsfb_check_var(&fb_info->var, fb_info);
+
+	platform_set_drvdata(pdev, fb_info);
+
+	ret = register_framebuffer(fb_info);
+	if (ret != 0) {
+		dev_err(&pdev->dev,"Failed to register framebuffer\n");
+		goto error_register;
+	}
+
+	if (!host->enabled) {
+		writel(0, host->base + LCDC_CTRL);
+		mxsfb_set_par(fb_info);
+		mxsfb_enable_controller(fb_info);
+	}
+
+	dev_info(&pdev->dev, "initialized\n");
+
+	return 0;
+
+error_register:
+	if (host->enabled)
+		clk_disable(host->clk);
+	fb_destroy_modelist(&fb_info->modelist);
+error_init_fb:
+	kfree(fb_info->pseudo_palette);
+error_pseudo_pallette:
+	clk_put(host->clk);
+error_getclock:
+	iounmap(host->base);
+error_ioremap:
+	framebuffer_release(fb_info);
+error_alloc_info:
+	release_mem_region(res->start, resource_size(res));
+
+	return ret;
+}
+
+static int __devexit 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);
+
+	return 0;
+}
+
+static struct platform_device_id mxsfb_devtype[] = {
+	{
+		.name = "imx23-fb",
+		.driver_data = MXSFB_V3,
+	}, {
+		.name = "imx28-fb",
+		.driver_data = MXSFB_V4,
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
+
+static struct platform_driver mxsfb_driver = {
+	.probe = mxsfb_probe,
+	.remove = __devexit_p(mxsfb_remove),
+	.id_table = mxsfb_devtype,
+	.driver = {
+		   .name = DRIVER_NAME,
+	},
+};
+
+static int __init mxsfb_init(void)
+{
+	return platform_driver_register(&mxsfb_driver);
+}
+
+static void __exit mxsfb_exit(void)
+{
+	platform_driver_unregister(&mxsfb_driver);
+}
+
+module_init(mxsfb_init);
+module_exit(mxsfb_exit);
+
+MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
index 6aac6d1..8471008 100644
--- a/drivers/video/nvidia/nv_backlight.c
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -111,6 +111,7 @@ void nvidia_bl_init(struct nvidia_par *par)
 	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &nvidia_bl_ops,
 				       &props);
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index e773106..7e04c92 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -534,6 +534,7 @@ static int acx_panel_probe(struct omap_dss_device *dssdev)
 
 	props.fb_blank = FB_BLANK_UNBLANK;
 	props.power = FB_BLANK_UNBLANK;
+	props.type = BACKLIGHT_RAW;
 
 	bldev = backlight_device_register("acx565akm", &md->spi->dev,
 			md, &acx565akm_bl_ops, &props);
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
index 9a138f6..d2b35d2 100644
--- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
+++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
@@ -99,6 +99,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = dssdev->max_backlight_level;
+	props.type = BACKLIGHT_RAW;
 
 	bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev,
 			&sharp_ls_bl_ops, &props);
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 61026f9..c74e8b7 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -729,6 +729,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
 		props.max_brightness = 255;
 	else
 		props.max_brightness = 127;
+
+	props.type = BACKLIGHT_RAW;
 	bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
 					  &taal_bl_ops, &props);
 	if (IS_ERR(bldev)) {
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c
index b6c3fc2..d57cc58 100644
--- a/drivers/video/p9100.c
+++ b/drivers/video/p9100.c
@@ -249,7 +249,7 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
 	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
 }
 
-static int __devinit p9100_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit p9100_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -352,7 +352,7 @@ static const struct of_device_id p9100_match[] = {
 };
 MODULE_DEVICE_TABLE(of, p9100_match);
 
-static struct of_platform_driver p9100_driver = {
+static struct platform_driver p9100_driver = {
 	.driver = {
 		.name = "p9100",
 		.owner = THIS_MODULE,
@@ -367,12 +367,12 @@ static int __init p9100_init(void)
 	if (fb_get_options("p9100fb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&p9100_driver);
+	return platform_driver_register(&p9100_driver);
 }
 
 static void __exit p9100_exit(void)
 {
-	of_unregister_platform_driver(&p9100_driver);
+	platform_driver_unregister(&p9100_driver);
 }
 
 module_init(p9100_init);
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index a50e197..ef532d9 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -533,8 +533,7 @@ static int __init platinumfb_setup(char *options)
 #define invalidate_cache(addr)
 #endif
 
-static int __devinit platinumfb_probe(struct platform_device* odev,
-				      const struct of_device_id *match)
+static int __devinit platinumfb_probe(struct platform_device* odev)
 {
 	struct device_node	*dp = odev->dev.of_node;
 	struct fb_info		*info;
@@ -677,7 +676,7 @@ static struct of_device_id platinumfb_match[] =
 	{},
 };
 
-static struct of_platform_driver platinum_driver = 
+static struct platform_driver platinum_driver = 
 {
 	.driver = {
 		.name = "platinumfb",
@@ -697,14 +696,14 @@ static int __init platinumfb_init(void)
 		return -ENODEV;
 	platinumfb_setup(option);
 #endif
-	of_register_platform_driver(&platinum_driver);
+	platform_driver_register(&platinum_driver);
 
 	return 0;
 }
 
 static void __exit platinumfb_exit(void)
 {
-	of_unregister_platform_driver(&platinum_driver);
+	platform_driver_unregister(&platinum_driver);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index da38818..d8ab7be 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -355,6 +355,7 @@ static void riva_bl_init(struct riva_par *par)
 	snprintf(name, sizeof(name), "rivabl%d", info->node);
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, info->dev, par, &riva_bl_ops,
 				       &props);
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index bf12e53..bf2629f 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -21,6 +21,8 @@
 #include <linux/ioctl.h>
 #include <linux/slab.h>
 #include <linux/console.h>
+#include <linux/backlight.h>
+#include <linux/gpio.h>
 #include <video/sh_mobile_lcdc.h>
 #include <asm/atomic.h>
 
@@ -67,6 +69,7 @@ static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
 	[LDSM1R] = 0x428,
 	[LDSM2R] = 0x42c,
 	[LDSA1R] = 0x430,
+	[LDSA2R] = 0x434,
 	[LDMLSR] = 0x438,
 	[LDHCNR] = 0x448,
 	[LDHSYNR] = 0x44c,
@@ -151,6 +154,7 @@ static bool banked(int reg_nr)
 	case LDDFR:
 	case LDSM1R:
 	case LDSA1R:
+	case LDSA2R:
 	case LDMLSR:
 	case LDHCNR:
 	case LDHSYNR:
@@ -463,6 +467,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	struct sh_mobile_lcdc_board_cfg	*board_cfg;
 	unsigned long tmp;
 	int bpp = 0;
+	unsigned long ldddsr;
 	int k, m;
 	int ret = 0;
 
@@ -541,16 +546,21 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 	}
 
 	/* word and long word swap */
-	switch (bpp) {
-	case 16:
-		lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 6);
-		break;
-	case 24:
-		lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 7);
-		break;
-	case 32:
-		lcdc_write(priv, _LDDDSR, lcdc_read(priv, _LDDDSR) | 4);
-		break;
+	ldddsr = lcdc_read(priv, _LDDDSR);
+	if  (priv->ch[0].info->var.nonstd)
+		lcdc_write(priv, _LDDDSR, ldddsr | 7);
+	else {
+		switch (bpp) {
+		case 16:
+			lcdc_write(priv, _LDDDSR, ldddsr | 6);
+			break;
+		case 24:
+			lcdc_write(priv, _LDDDSR, ldddsr | 7);
+			break;
+		case 32:
+			lcdc_write(priv, _LDDDSR, ldddsr | 4);
+			break;
+		}
 	}
 
 	for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
@@ -561,21 +571,40 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 
 		/* set bpp format in PKF[4:0] */
 		tmp = lcdc_read_chan(ch, LDDFR);
-		tmp &= ~0x0001001f;
-		switch (ch->info->var.bits_per_pixel) {
-		case 16:
-			tmp |= 0x03;
-			break;
-		case 24:
-			tmp |= 0x0b;
-			break;
-		case 32:
-			break;
+		tmp &= ~0x0003031f;
+		if (ch->info->var.nonstd) {
+			tmp |= (ch->info->var.nonstd << 16);
+			switch (ch->info->var.bits_per_pixel) {
+			case 12:
+				break;
+			case 16:
+				tmp |= (0x1 << 8);
+				break;
+			case 24:
+				tmp |= (0x2 << 8);
+				break;
+			}
+		} else {
+			switch (ch->info->var.bits_per_pixel) {
+			case 16:
+				tmp |= 0x03;
+				break;
+			case 24:
+				tmp |= 0x0b;
+				break;
+			case 32:
+				break;
+			}
 		}
 		lcdc_write_chan(ch, LDDFR, tmp);
 
 		/* point out our frame buffer */
 		lcdc_write_chan(ch, LDSA1R, ch->info->fix.smem_start);
+		if (ch->info->var.nonstd)
+			lcdc_write_chan(ch, LDSA2R,
+				ch->info->fix.smem_start +
+				ch->info->var.xres *
+				ch->info->var.yres_virtual);
 
 		/* set line size */
 		lcdc_write_chan(ch, LDMLSR, ch->info->fix.line_length);
@@ -618,6 +647,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
 			board_cfg->display_on(board_cfg->board_data, ch->info);
 			module_put(board_cfg->owner);
 		}
+
+		if (ch->bl) {
+			ch->bl->props.power = FB_BLANK_UNBLANK;
+			backlight_update_status(ch->bl);
+		}
 	}
 
 	return 0;
@@ -648,6 +682,11 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
 			sh_mobile_lcdc_clk_on(priv);
 		}
 
+		if (ch->bl) {
+			ch->bl->props.power = FB_BLANK_POWERDOWN;
+			backlight_update_status(ch->bl);
+		}
+
 		board_cfg = &ch->cfg.board_cfg;
 		if (try_module_get(board_cfg->owner) && board_cfg->display_off) {
 			board_cfg->display_off(board_cfg->board_data);
@@ -804,9 +843,15 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 	struct sh_mobile_lcdc_priv *priv = ch->lcdc;
 	unsigned long ldrcntr;
 	unsigned long new_pan_offset;
+	unsigned long base_addr_y, base_addr_c;
+	unsigned long c_offset;
 
-	new_pan_offset = (var->yoffset * info->fix.line_length) +
-		(var->xoffset * (info->var.bits_per_pixel / 8));
+	if (!var->nonstd)
+		new_pan_offset = (var->yoffset * info->fix.line_length) +
+			(var->xoffset * (info->var.bits_per_pixel / 8));
+	else
+		new_pan_offset = (var->yoffset * info->fix.line_length) +
+			(var->xoffset);
 
 	if (new_pan_offset == ch->pan_offset)
 		return 0;	/* No change, do nothing */
@@ -814,7 +859,26 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
 	ldrcntr = lcdc_read(priv, _LDRCNTR);
 
 	/* Set the source address for the next refresh */
-	lcdc_write_chan_mirror(ch, LDSA1R, ch->dma_handle + new_pan_offset);
+	base_addr_y = ch->dma_handle + new_pan_offset;
+	if (var->nonstd) {
+		/* Set y offset */
+		c_offset = (var->yoffset *
+			info->fix.line_length *
+			(info->var.bits_per_pixel - 8)) / 8;
+		base_addr_c = ch->dma_handle + var->xres * var->yres_virtual +
+			c_offset;
+		/* Set x offset */
+		if (info->var.bits_per_pixel == 24)
+			base_addr_c += 2 * var->xoffset;
+		else
+			base_addr_c += var->xoffset;
+	} else
+		base_addr_c = 0;
+
+	lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
+	if (base_addr_c)
+		lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
+
 	if (lcdc_chan_is_sublcd(ch))
 		lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS);
 	else
@@ -885,7 +949,10 @@ static void sh_mobile_fb_reconfig(struct fb_info *info)
 		/* Couldn't reconfigure, hopefully, can continue as before */
 		return;
 
-	info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
+	if (info->var.nonstd)
+		info->fix.line_length = mode1.xres;
+	else
+		info->fix.line_length = mode1.xres * (ch->cfg.bpp / 8);
 
 	/*
 	 * fb_set_var() calls the notifier change internally, only if
@@ -980,8 +1047,80 @@ static struct fb_ops sh_mobile_lcdc_ops = {
 	.fb_check_var	= sh_mobile_check_var,
 };
 
-static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp)
+static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev)
+{
+	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
+	struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
+	int brightness = bdev->props.brightness;
+
+	if (bdev->props.power != FB_BLANK_UNBLANK ||
+	    bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	return cfg->set_brightness(cfg->board_data, brightness);
+}
+
+static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev)
+{
+	struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev);
+	struct sh_mobile_lcdc_board_cfg *cfg = &ch->cfg.board_cfg;
+
+	return cfg->get_brightness(cfg->board_data);
+}
+
+static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev,
+				   struct fb_info *info)
+{
+	return (info->bl_dev == bdev);
+}
+
+static struct backlight_ops sh_mobile_lcdc_bl_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= sh_mobile_lcdc_update_bl,
+	.get_brightness	= sh_mobile_lcdc_get_brightness,
+	.check_fb	= sh_mobile_lcdc_check_fb,
+};
+
+static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
+					       struct sh_mobile_lcdc_chan *ch)
+{
+	struct backlight_device *bl;
+
+	bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch,
+				       &sh_mobile_lcdc_bl_ops, NULL);
+	if (!bl) {
+		dev_err(parent, "unable to register backlight device\n");
+		return NULL;
+	}
+
+	bl->props.max_brightness = ch->cfg.bl_info.max_brightness;
+	bl->props.brightness = bl->props.max_brightness;
+	backlight_update_status(bl);
+
+	return bl;
+}
+
+static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
+{
+	backlight_device_unregister(bdev);
+}
+
+static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp,
+				   int nonstd)
 {
+	if (nonstd) {
+		switch (bpp) {
+		case 12:
+		case 16:
+		case 24:
+			var->bits_per_pixel = bpp;
+			var->nonstd = nonstd;
+			return 0;
+		default:
+			return -EINVAL;
+		}
+	}
+
 	switch (bpp) {
 	case 16: /* PKF[4:0] = 00011 - RGB 565 */
 		var->red.offset = 11;
@@ -1198,6 +1337,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		init_completion(&ch->vsync_completion);
 		ch->pan_offset = 0;
 
+		/* probe the backlight is there is one defined */
+		if (ch->cfg.bl_info.max_brightness)
+			ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
+
 		switch (pdata->ch[i].chan) {
 		case LCDC_CHAN_MAINLCD:
 			ch->enabled = 1 << 1;
@@ -1260,6 +1403,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		     k < cfg->num_cfg && lcd_cfg;
 		     k++, lcd_cfg++) {
 			unsigned long size = lcd_cfg->yres * lcd_cfg->xres;
+			/* NV12 buffers must have even number of lines */
+			if ((cfg->nonstd) && cfg->bpp == 12 &&
+					(lcd_cfg->yres & 0x1)) {
+				dev_err(&pdev->dev, "yres must be multiple of 2"
+						" for YCbCr420 mode.\n");
+				error = -EINVAL;
+				goto err1;
+			}
 
 			if (size > max_size) {
 				max_cfg = lcd_cfg;
@@ -1274,7 +1425,11 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 				max_cfg->xres, max_cfg->yres);
 
 		info->fix = sh_mobile_lcdc_fix;
-		info->fix.smem_len = max_size * (cfg->bpp / 8) * 2;
+		info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
+
+		 /* Only pan in 2 line steps for NV12 */
+		if (cfg->nonstd && cfg->bpp == 12)
+			info->fix.ypanstep = 2;
 
 		if (!mode) {
 			mode = &default_720p;
@@ -1292,7 +1447,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		var->yres_virtual = var->yres * 2;
 		var->activate = FB_ACTIVATE_NOW;
 
-		error = sh_mobile_lcdc_set_bpp(var, cfg->bpp);
+		error = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd);
 		if (error)
 			break;
 
@@ -1316,7 +1471,11 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 		}
 
 		info->fix.smem_start = ch->dma_handle;
-		info->fix.line_length = var->xres * (cfg->bpp / 8);
+		if (var->nonstd)
+			info->fix.line_length = var->xres;
+		else
+			info->fix.line_length = var->xres * (cfg->bpp / 8);
+
 		info->screen_base = buf;
 		info->device = &pdev->dev;
 		ch->display_var = *var;
@@ -1345,6 +1504,8 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
 			}
 		}
 
+		info->bl_dev = ch->bl;
+
 		error = register_framebuffer(info);
 		if (error < 0)
 			goto err1;
@@ -1404,6 +1565,11 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
 		framebuffer_release(info);
 	}
 
+	for (i = 0; i < ARRAY_SIZE(priv->ch); i++) {
+		if (priv->ch[i].bl)
+			sh_mobile_lcdc_bl_remove(priv->ch[i].bl);
+	}
+
 	if (priv->dot_clk)
 		clk_put(priv->dot_clk);
 
diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h
index 9ecee2f..4635eed 100644
--- a/drivers/video/sh_mobile_lcdcfb.h
+++ b/drivers/video/sh_mobile_lcdcfb.h
@@ -8,7 +8,7 @@
 
 /* per-channel registers */
 enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
-       LDSM2R, LDSA1R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
+       LDSM2R, LDSA1R, LDSA2R, LDMLSR, LDHCNR, LDHSYNR, LDVLNR, LDVSYNR, LDPMR,
        LDHAJR,
        NR_CH_REGS };
 
@@ -16,6 +16,7 @@ enum { LDDCKPAT1R, LDDCKPAT2R, LDMT1R, LDMT2R, LDMT3R, LDDFR, LDSM1R,
 
 struct sh_mobile_lcdc_priv;
 struct fb_info;
+struct backlight_device;
 
 struct sh_mobile_lcdc_chan {
 	struct sh_mobile_lcdc_priv *lcdc;
@@ -26,6 +27,7 @@ struct sh_mobile_lcdc_chan {
 	u32 pseudo_palette[PALETTE_NR];
 	unsigned long saved_ch_regs[NR_CH_REGS];
 	struct fb_info *info;
+	struct backlight_device *bl;
 	dma_addr_t dma_handle;
 	struct fb_deferred_io defio;
 	struct scatterlist *sglist;
diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c
index 5dbe06a..b7f27ac 100644
--- a/drivers/video/sunxvr1000.c
+++ b/drivers/video/sunxvr1000.c
@@ -111,8 +111,7 @@ static int __devinit gfb_set_fbinfo(struct gfb_info *gp)
         return 0;
 }
 
-static int __devinit gfb_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit gfb_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -198,7 +197,7 @@ static const struct of_device_id gfb_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ffb_match);
 
-static struct of_platform_driver gfb_driver = {
+static struct platform_driver gfb_driver = {
 	.probe		= gfb_probe,
 	.remove		= __devexit_p(gfb_remove),
 	.driver = {
@@ -213,12 +212,12 @@ static int __init gfb_init(void)
 	if (fb_get_options("gfb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&gfb_driver);
+	return platform_driver_register(&gfb_driver);
 }
 
 static void __exit gfb_exit(void)
 {
-	of_unregister_platform_driver(&gfb_driver);
+	platform_driver_unregister(&gfb_driver);
 }
 
 module_init(gfb_init);
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c
index 77ad279..855b719 100644
--- a/drivers/video/tcx.c
+++ b/drivers/video/tcx.c
@@ -362,8 +362,7 @@ static void tcx_unmap_regs(struct platform_device *op, struct fb_info *info,
 			   info->screen_base, info->fix.smem_len);
 }
 
-static int __devinit tcx_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit tcx_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct fb_info *info;
@@ -511,7 +510,7 @@ static const struct of_device_id tcx_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tcx_match);
 
-static struct of_platform_driver tcx_driver = {
+static struct platform_driver tcx_driver = {
 	.driver = {
 		.name = "tcx",
 		.owner = THIS_MODULE,
@@ -526,12 +525,12 @@ static int __init tcx_init(void)
 	if (fb_get_options("tcxfb", NULL))
 		return -ENODEV;
 
-	return of_register_platform_driver(&tcx_driver);
+	return platform_driver_register(&tcx_driver);
 }
 
 static void __exit tcx_exit(void)
 {
-	of_unregister_platform_driver(&tcx_driver);
+	platform_driver_unregister(&tcx_driver);
 }
 
 module_init(tcx_init);
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 52ec095..5180a21 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -73,7 +73,7 @@ static void uvesafb_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *ns
 	struct uvesafb_task *utask;
 	struct uvesafb_ktask *task;
 
-	if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+	if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
 		return;
 
 	if (msg->seq >= UVESAFB_TASKS_MAX)
diff --git a/drivers/video/via/chip.h b/drivers/video/via/chip.h
index 48f1342..781f3aa 100644
--- a/drivers/video/via/chip.h
+++ b/drivers/video/via/chip.h
@@ -110,16 +110,13 @@
 struct tmds_chip_information {
 	int tmds_chip_name;
 	int tmds_chip_slave_addr;
-	int data_mode;
 	int output_interface;
 	int i2c_port;
-	int device_type;
 };
 
 struct lvds_chip_information {
 	int lvds_chip_name;
 	int lvds_chip_slave_addr;
-	int data_mode;
 	int output_interface;
 	int i2c_port;
 };
@@ -142,9 +139,6 @@ struct chip_information {
 
 struct crt_setting_information {
 	int iga_path;
-	int h_active;
-	int v_active;
-	int bpp;
 	int refresh_rate;
 };
 
@@ -162,8 +156,6 @@ struct lvds_setting_information {
 	int h_active;
 	int v_active;
 	int bpp;
-	int refresh_rate;
-	int lcd_panel_id;
 	int lcd_panel_hres;
 	int lcd_panel_vres;
 	int display_method;
@@ -188,7 +180,6 @@ struct GFX_DPA_SETTING {
 };
 
 struct VT1636_DPA_SETTING {
-	int PanelSizeID;
 	u8 CLK_SEL_ST1;
 	u8 CLK_SEL_ST2;
 };
diff --git a/drivers/video/via/dvi.c b/drivers/video/via/dvi.c
index 84e21b3..41ca198 100644
--- a/drivers/video/via/dvi.c
+++ b/drivers/video/via/dvi.c
@@ -195,7 +195,9 @@ void viafb_dvi_set_mode(struct VideoModeTable *mode, int mode_bpp,
 	struct crt_mode_table *pDviTiming;
 	unsigned long desirePixelClock, maxPixelClock;
 	pDviTiming = mode->crtc;
-	desirePixelClock = pDviTiming->clk / 1000000;
+	desirePixelClock = pDviTiming->refresh_rate
+		* pDviTiming->crtc.hor_total * pDviTiming->crtc.ver_total
+		/ 1000000;
 	maxPixelClock = (unsigned long)viaparinfo->
 		tmds_setting_info->max_pixel_clock;
 
diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 36d73f9..5728fd7 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -22,342 +22,290 @@
 #include <linux/via-core.h>
 #include "global.h"
 
-static struct pll_map pll_value[] = {
-	{25175000,
-		{99, 7, 3},
-		{85, 3, 4},	/* ignoring bit difference: 0x00008000 */
-		{141, 5, 4},
-		{141, 5, 4} },
-	{29581000,
-		{33, 4, 2},
-		{66, 2, 4},	/* ignoring bit difference: 0x00808000 */
-		{166, 5, 4},	/* ignoring bit difference: 0x00008000 */
-		{165, 5, 4} },
-	{26880000,
-		{15, 4, 1},
-		{30, 2, 3},	/* ignoring bit difference: 0x00808000 */
-		{150, 5, 4},
-		{150, 5, 4} },
-	{31500000,
-		{53, 3, 3},	/* ignoring bit difference: 0x00008000 */
-		{141, 4, 4},	/* ignoring bit difference: 0x00008000 */
-		{176, 5, 4},
-		{176, 5, 4} },
-	{31728000,
-		{31, 7, 1},
-		{177, 5, 4},	/* ignoring bit difference: 0x00008000 */
-		{177, 5, 4},
-		{142, 4, 4} },
-	{32688000,
-		{73, 4, 3},
-		{146, 4, 4},	/* ignoring bit difference: 0x00008000 */
-		{183, 5, 4},
-		{146, 4, 4} },
-	{36000000,
-		{101, 5, 3},	/* ignoring bit difference: 0x00008000 */
-		{161, 4, 4},	/* ignoring bit difference: 0x00008000 */
-		{202, 5, 4},
-		{161, 4, 4} },
-	{40000000,
-		{89, 4, 3},
-		{89, 4, 3},	/* ignoring bit difference: 0x00008000 */
-		{112, 5, 3},
-		{112, 5, 3} },
-	{41291000,
-		{23, 4, 1},
-		{69, 3, 3},	/* ignoring bit difference: 0x00008000 */
-		{115, 5, 3},
-		{115, 5, 3} },
-	{43163000,
-		{121, 5, 3},
-		{121, 5, 3},	/* ignoring bit difference: 0x00008000 */
-		{121, 5, 3},
-		{121, 5, 3} },
-	{45250000,
-		{127, 5, 3},
-		{127, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{127, 5, 3},
-		{127, 5, 3} },
-	{46000000,
-		{90, 7, 2},
-		{103, 4, 3},	/* ignoring bit difference: 0x00008000 */
-		{129, 5, 3},
-		{103, 4, 3} },
-	{46996000,
-		{105, 4, 3},	/* ignoring bit difference: 0x00008000 */
-		{131, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{131, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{105, 4, 3} },
-	{48000000,
-		{67, 20, 0},
-		{134, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{134, 5, 3},
-		{134, 5, 3} },
-	{48875000,
-		{99, 29, 0},
-		{82, 3, 3},	/* ignoring bit difference: 0x00808000 */
-		{82, 3, 3},	/* ignoring bit difference: 0x00808000 */
-		{137, 5, 3} },
-	{49500000,
-		{83, 6, 2},
-		{83, 3, 3},	/* ignoring bit difference: 0x00008000 */
-		{138, 5, 3},
-		{83, 3, 3} },
-	{52406000,
-		{117, 4, 3},
-		{117, 4, 3},	/* ignoring bit difference: 0x00008000 */
-		{117, 4, 3},
-		{88, 3, 3} },
-	{52977000,
-		{37, 5, 1},
-		{148, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{148, 5, 3},
-		{148, 5, 3} },
-	{56250000,
-		{55, 7, 1},	/* ignoring bit difference: 0x00008000 */
-		{126, 4, 3},	/* ignoring bit difference: 0x00008000 */
-		{157, 5, 3},
-		{157, 5, 3} },
-	{57275000,
-		{0, 0, 0},
-		{2, 2, 0},
-		{2, 2, 0},
-		{157, 5, 3} },	/* ignoring bit difference: 0x00808000 */
-	{60466000,
-		{76, 9, 1},
-		{169, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{169, 5, 3},	/* FIXED: old = {72, 2, 3} */
-		{169, 5, 3} },
-	{61500000,
-		{86, 20, 0},
-		{172, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{172, 5, 3},
-		{172, 5, 3} },
-	{65000000,
-		{109, 6, 2},	/* ignoring bit difference: 0x00008000 */
-		{109, 3, 3},	/* ignoring bit difference: 0x00008000 */
-		{109, 3, 3},
-		{109, 3, 3} },
-	{65178000,
-		{91, 5, 2},
-		{182, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{109, 3, 3},
-		{182, 5, 3} },
-	{66750000,
-		{75, 4, 2},
-		{150, 4, 3},	/* ignoring bit difference: 0x00808000 */
-		{150, 4, 3},
-		{112, 3, 3} },
-	{68179000,
-		{19, 4, 0},
-		{114, 3, 3},	/* ignoring bit difference: 0x00008000 */
-		{190, 5, 3},
-		{191, 5, 3} },
-	{69924000,
-		{83, 17, 0},
-		{195, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{195, 5, 3},
-		{195, 5, 3} },
-	{70159000,
-		{98, 20, 0},
-		{196, 5, 3},	/* ignoring bit difference: 0x00808000 */
-		{196, 5, 3},
-		{195, 5, 3} },
-	{72000000,
-		{121, 24, 0},
-		{161, 4, 3},	/* ignoring bit difference: 0x00808000 */
-		{161, 4, 3},
-		{161, 4, 3} },
-	{78750000,
-		{33, 3, 1},
-		{66, 3, 2},	/* ignoring bit difference: 0x00008000 */
-		{110, 5, 2},
-		{110, 5, 2} },
-	{80136000,
-		{28, 5, 0},
-		{68, 3, 2},	/* ignoring bit difference: 0x00008000 */
-		{112, 5, 2},
-		{112, 5, 2} },
-	{83375000,
-		{93, 2, 3},
-		{93, 4, 2},	/* ignoring bit difference: 0x00800000 */
-		{93, 4, 2},	/* ignoring bit difference: 0x00800000 */
-		{117, 5, 2} },
-	{83950000,
-		{41, 7, 0},
-		{117, 5, 2},	/* ignoring bit difference: 0x00008000 */
-		{117, 5, 2},
-		{117, 5, 2} },
-	{84750000,
-		{118, 5, 2},
-		{118, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{118, 5, 2},
-		{118, 5, 2} },
-	{85860000,
-		{84, 7, 1},
-		{120, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{120, 5, 2},
-		{118, 5, 2} },
-	{88750000,
-		{31, 5, 0},
-		{124, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{174, 7, 2},	/* ignoring bit difference: 0x00808000 */
-		{124, 5, 2} },
-	{94500000,
-		{33, 5, 0},
-		{132, 5, 2},	/* ignoring bit difference: 0x00008000 */
-		{132, 5, 2},
-		{132, 5, 2} },
-	{97750000,
-		{82, 6, 1},
-		{137, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{137, 5, 2},
-		{137, 5, 2} },
-	{101000000,
-		{127, 9, 1},
-		{141, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{141, 5, 2},
-		{141, 5, 2} },
-	{106500000,
-		{119, 4, 2},
-		{119, 4, 2},	/* ignoring bit difference: 0x00808000 */
-		{119, 4, 2},
-		{149, 5, 2} },
-	{108000000,
-		{121, 4, 2},
-		{121, 4, 2},	/* ignoring bit difference: 0x00808000 */
-		{151, 5, 2},
-		{151, 5, 2} },
-	{113309000,
-		{95, 12, 0},
-		{95, 3, 2},	/* ignoring bit difference: 0x00808000 */
-		{95, 3, 2},
-		{159, 5, 2} },
-	{118840000,
-		{83, 5, 1},
-		{166, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{166, 5, 2},
-		{166, 5, 2} },
-	{119000000,
-		{108, 13, 0},
-		{133, 4, 2},	/* ignoring bit difference: 0x00808000 */
-		{133, 4, 2},
-		{167, 5, 2} },
-	{121750000,
-		{85, 5, 1},
-		{170, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{68, 2, 2},
-		{0, 0, 0} },
-	{125104000,
-		{53, 6, 0},	/* ignoring bit difference: 0x00008000 */
-		{106, 3, 2},	/* ignoring bit difference: 0x00008000 */
-		{175, 5, 2},
-		{0, 0, 0} },
-	{135000000,
-		{94, 5, 1},
-		{28, 3, 0},	/* ignoring bit difference: 0x00804000 */
-		{151, 4, 2},
-		{189, 5, 2} },
-	{136700000,
-		{115, 12, 0},
-		{191, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{191, 5, 2},
-		{191, 5, 2} },
-	{138400000,
-		{87, 9, 0},
-		{116, 3, 2},	/* ignoring bit difference: 0x00808000 */
-		{116, 3, 2},
-		{194, 5, 2} },
-	{146760000,
-		{103, 5, 1},
-		{206, 5, 2},	/* ignoring bit difference: 0x00808000 */
-		{206, 5, 2},
-		{206, 5, 2} },
-	{153920000,
-		{86, 8, 0},
-		{86, 4, 1},	/* ignoring bit difference: 0x00808000 */
-		{86, 4, 1},
-		{86, 4, 1} },	/* FIXED: old = {84, 2, 1} */
-	{156000000,
-		{109, 5, 1},
-		{109, 5, 1},	/* ignoring bit difference: 0x00808000 */
-		{109, 5, 1},
-		{108, 5, 1} },
-	{157500000,
-		{55, 5, 0},	/* ignoring bit difference: 0x00008000 */
-		{22, 2, 0},	/* ignoring bit difference: 0x00802000 */
-		{110, 5, 1},
-		{110, 5, 1} },
-	{162000000,
-		{113, 5, 1},
-		{113, 5, 1},	/* ignoring bit difference: 0x00808000 */
-		{113, 5, 1},
-		{113, 5, 1} },
-	{187000000,
-		{118, 9, 0},
-		{131, 5, 1},	/* ignoring bit difference: 0x00808000 */
-		{131, 5, 1},
-		{131, 5, 1} },
-	{193295000,
-		{108, 8, 0},
-		{81, 3, 1},	/* ignoring bit difference: 0x00808000 */
-		{135, 5, 1},
-		{135, 5, 1} },
-	{202500000,
-		{99, 7, 0},
-		{85, 3, 1},	/* ignoring bit difference: 0x00808000 */
-		{142, 5, 1},
-		{142, 5, 1} },
-	{204000000,
-		{100, 7, 0},
-		{143, 5, 1},	/* ignoring bit difference: 0x00808000 */
-		{143, 5, 1},
-		{143, 5, 1} },
-	{218500000,
-		{92, 6, 0},
-		{153, 5, 1},	/* ignoring bit difference: 0x00808000 */
-		{153, 5, 1},
-		{153, 5, 1} },
-	{234000000,
-		{98, 6, 0},
-		{98, 3, 1},	/* ignoring bit difference: 0x00008000 */
-		{98, 3, 1},
-		{164, 5, 1} },
-	{267250000,
-		{112, 6, 0},
-		{112, 3, 1},	/* ignoring bit difference: 0x00808000 */
-		{187, 5, 1},
-		{187, 5, 1} },
-	{297500000,
-		{102, 5, 0},	/* ignoring bit difference: 0x00008000 */
-		{166, 4, 1},	/* ignoring bit difference: 0x00008000 */
-		{208, 5, 1},
-		{208, 5, 1} },
-	{74481000,
-		{26, 5, 0},
-		{125, 3, 3},	/* ignoring bit difference: 0x00808000 */
-		{208, 5, 3},
-		{209, 5, 3} },
-	{172798000,
-		{121, 5, 1},
-		{121, 5, 1},	/* ignoring bit difference: 0x00808000 */
-		{121, 5, 1},
-		{121, 5, 1} },
-	{122614000,
-		{60, 7, 0},
-		{137, 4, 2},	/* ignoring bit difference: 0x00808000 */
-		{137, 4, 2},
-		{172, 5, 2} },
-	{74270000,
-		{83, 8, 1},
-		{208, 5, 3},
-		{208, 5, 3},
-		{0, 0, 0} },
-	{148500000,
-		{83, 8, 0},
-		{208, 5, 2},
-		{166, 4, 2},
-		{208, 5, 2} }
+static struct pll_config cle266_pll_config[] = {
+	{19, 4, 0},
+	{26, 5, 0},
+	{28, 5, 0},
+	{31, 5, 0},
+	{33, 5, 0},
+	{55, 5, 0},
+	{102, 5, 0},
+	{53, 6, 0},
+	{92, 6, 0},
+	{98, 6, 0},
+	{112, 6, 0},
+	{41, 7, 0},
+	{60, 7, 0},
+	{99, 7, 0},
+	{100, 7, 0},
+	{83, 8, 0},
+	{86, 8, 0},
+	{108, 8, 0},
+	{87, 9, 0},
+	{118, 9, 0},
+	{95, 12, 0},
+	{115, 12, 0},
+	{108, 13, 0},
+	{83, 17, 0},
+	{67, 20, 0},
+	{86, 20, 0},
+	{98, 20, 0},
+	{121, 24, 0},
+	{99, 29, 0},
+	{33, 3, 1},
+	{15, 4, 1},
+	{23, 4, 1},
+	{37, 5, 1},
+	{83, 5, 1},
+	{85, 5, 1},
+	{94, 5, 1},
+	{103, 5, 1},
+	{109, 5, 1},
+	{113, 5, 1},
+	{121, 5, 1},
+	{82, 6, 1},
+	{31, 7, 1},
+	{55, 7, 1},
+	{84, 7, 1},
+	{83, 8, 1},
+	{76, 9, 1},
+	{127, 9, 1},
+	{33, 4, 2},
+	{75, 4, 2},
+	{119, 4, 2},
+	{121, 4, 2},
+	{91, 5, 2},
+	{118, 5, 2},
+	{83, 6, 2},
+	{109, 6, 2},
+	{90, 7, 2},
+	{93, 2, 3},
+	{53, 3, 3},
+	{73, 4, 3},
+	{89, 4, 3},
+	{105, 4, 3},
+	{117, 4, 3},
+	{101, 5, 3},
+	{121, 5, 3},
+	{127, 5, 3},
+	{99, 7, 3}
+};
+
+static struct pll_config k800_pll_config[] = {
+	{22, 2, 0},
+	{28, 3, 0},
+	{81, 3, 1},
+	{85, 3, 1},
+	{98, 3, 1},
+	{112, 3, 1},
+	{86, 4, 1},
+	{166, 4, 1},
+	{109, 5, 1},
+	{113, 5, 1},
+	{121, 5, 1},
+	{131, 5, 1},
+	{143, 5, 1},
+	{153, 5, 1},
+	{66, 3, 2},
+	{68, 3, 2},
+	{95, 3, 2},
+	{106, 3, 2},
+	{116, 3, 2},
+	{93, 4, 2},
+	{119, 4, 2},
+	{121, 4, 2},
+	{133, 4, 2},
+	{137, 4, 2},
+	{117, 5, 2},
+	{118, 5, 2},
+	{120, 5, 2},
+	{124, 5, 2},
+	{132, 5, 2},
+	{137, 5, 2},
+	{141, 5, 2},
+	{166, 5, 2},
+	{170, 5, 2},
+	{191, 5, 2},
+	{206, 5, 2},
+	{208, 5, 2},
+	{30, 2, 3},
+	{69, 3, 3},
+	{82, 3, 3},
+	{83, 3, 3},
+	{109, 3, 3},
+	{114, 3, 3},
+	{125, 3, 3},
+	{89, 4, 3},
+	{103, 4, 3},
+	{117, 4, 3},
+	{126, 4, 3},
+	{150, 4, 3},
+	{161, 4, 3},
+	{121, 5, 3},
+	{127, 5, 3},
+	{131, 5, 3},
+	{134, 5, 3},
+	{148, 5, 3},
+	{169, 5, 3},
+	{172, 5, 3},
+	{182, 5, 3},
+	{195, 5, 3},
+	{196, 5, 3},
+	{208, 5, 3},
+	{66, 2, 4},
+	{85, 3, 4},
+	{141, 4, 4},
+	{146, 4, 4},
+	{161, 4, 4},
+	{177, 5, 4}
+};
+
+static struct pll_config cx700_pll_config[] = {
+	{98, 3, 1},
+	{86, 4, 1},
+	{109, 5, 1},
+	{110, 5, 1},
+	{113, 5, 1},
+	{121, 5, 1},
+	{131, 5, 1},
+	{135, 5, 1},
+	{142, 5, 1},
+	{143, 5, 1},
+	{153, 5, 1},
+	{187, 5, 1},
+	{208, 5, 1},
+	{68, 2, 2},
+	{95, 3, 2},
+	{116, 3, 2},
+	{93, 4, 2},
+	{119, 4, 2},
+	{133, 4, 2},
+	{137, 4, 2},
+	{151, 4, 2},
+	{166, 4, 2},
+	{110, 5, 2},
+	{112, 5, 2},
+	{117, 5, 2},
+	{118, 5, 2},
+	{120, 5, 2},
+	{132, 5, 2},
+	{137, 5, 2},
+	{141, 5, 2},
+	{151, 5, 2},
+	{166, 5, 2},
+	{175, 5, 2},
+	{191, 5, 2},
+	{206, 5, 2},
+	{174, 7, 2},
+	{82, 3, 3},
+	{109, 3, 3},
+	{117, 4, 3},
+	{150, 4, 3},
+	{161, 4, 3},
+	{112, 5, 3},
+	{115, 5, 3},
+	{121, 5, 3},
+	{127, 5, 3},
+	{129, 5, 3},
+	{131, 5, 3},
+	{134, 5, 3},
+	{138, 5, 3},
+	{148, 5, 3},
+	{157, 5, 3},
+	{169, 5, 3},
+	{172, 5, 3},
+	{190, 5, 3},
+	{195, 5, 3},
+	{196, 5, 3},
+	{208, 5, 3},
+	{141, 5, 4},
+	{150, 5, 4},
+	{166, 5, 4},
+	{176, 5, 4},
+	{177, 5, 4},
+	{183, 5, 4},
+	{202, 5, 4}
+};
+
+static struct pll_config vx855_pll_config[] = {
+	{86, 4, 1},
+	{108, 5, 1},
+	{110, 5, 1},
+	{113, 5, 1},
+	{121, 5, 1},
+	{131, 5, 1},
+	{135, 5, 1},
+	{142, 5, 1},
+	{143, 5, 1},
+	{153, 5, 1},
+	{164, 5, 1},
+	{187, 5, 1},
+	{208, 5, 1},
+	{110, 5, 2},
+	{112, 5, 2},
+	{117, 5, 2},
+	{118, 5, 2},
+	{124, 5, 2},
+	{132, 5, 2},
+	{137, 5, 2},
+	{141, 5, 2},
+	{149, 5, 2},
+	{151, 5, 2},
+	{159, 5, 2},
+	{166, 5, 2},
+	{167, 5, 2},
+	{172, 5, 2},
+	{189, 5, 2},
+	{191, 5, 2},
+	{194, 5, 2},
+	{206, 5, 2},
+	{208, 5, 2},
+	{83, 3, 3},
+	{88, 3, 3},
+	{109, 3, 3},
+	{112, 3, 3},
+	{103, 4, 3},
+	{105, 4, 3},
+	{161, 4, 3},
+	{112, 5, 3},
+	{115, 5, 3},
+	{121, 5, 3},
+	{127, 5, 3},
+	{134, 5, 3},
+	{137, 5, 3},
+	{148, 5, 3},
+	{157, 5, 3},
+	{169, 5, 3},
+	{172, 5, 3},
+	{182, 5, 3},
+	{191, 5, 3},
+	{195, 5, 3},
+	{209, 5, 3},
+	{142, 4, 4},
+	{146, 4, 4},
+	{161, 4, 4},
+	{141, 5, 4},
+	{150, 5, 4},
+	{165, 5, 4},
+	{176, 5, 4}
+};
+
+/* according to VIA Technologies these values are based on experiment */
+static struct io_reg scaling_parameters[] = {
+	{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1 */
+	{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2 */
+	{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3 */
+	{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4 */
+	{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5 */
+	{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6 */
+	{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7 */
+	{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8 */
+	{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9 */
+	{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10 */
+	{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11 */
+	{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12 */
+	{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13 */
+	{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14 */
 };
 
 static struct fifo_depth_select display_fifo_depth_reg = {
@@ -751,7 +699,7 @@ void viafb_unlock_crt(void)
 	viafb_write_reg_mask(CR47, VIACR, 0, BIT0);
 }
 
-void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
+static void write_dac_reg(u8 index, u8 r, u8 g, u8 b)
 {
 	outb(index, LUT_INDEX_WRITE);
 	outb(r, LUT_DATA);
@@ -1674,43 +1622,63 @@ static u32 vx855_encode_pll(struct pll_config pll)
 		| pll.multiplier;
 }
 
-u32 viafb_get_clk_value(int clk)
+static inline u32 get_pll_internal_frequency(u32 ref_freq,
+	struct pll_config pll)
 {
-	u32 value = 0;
-	int i = 0;
+	return ref_freq / pll.divisor * pll.multiplier;
+}
 
-	while (i < NUM_TOTAL_PLL_TABLE && clk != pll_value[i].clk)
-		i++;
+static inline u32 get_pll_output_frequency(u32 ref_freq, struct pll_config pll)
+{
+	return get_pll_internal_frequency(ref_freq, pll)>>pll.rshift;
+}
 
-	if (i == NUM_TOTAL_PLL_TABLE) {
-		printk(KERN_WARNING "viafb_get_clk_value: PLL lookup failed!");
-	} else {
-		switch (viaparinfo->chip_info->gfx_chip_name) {
-		case UNICHROME_CLE266:
-		case UNICHROME_K400:
-			value = cle266_encode_pll(pll_value[i].cle266_pll);
-			break;
+static struct pll_config get_pll_config(struct pll_config *config, int size,
+	int clk)
+{
+	struct pll_config best = config[0];
+	const u32 f0 = 14318180; /* X1 frequency */
+	int i;
 
-		case UNICHROME_K800:
-		case UNICHROME_PM800:
-		case UNICHROME_CN700:
-			value = k800_encode_pll(pll_value[i].k800_pll);
-			break;
+	for (i = 1; i < size; i++) {
+		if (abs(get_pll_output_frequency(f0, config[i]) - clk)
+			< abs(get_pll_output_frequency(f0, best) - clk))
+			best = config[i];
+	}
 
-		case UNICHROME_CX700:
-		case UNICHROME_CN750:
-		case UNICHROME_K8M890:
-		case UNICHROME_P4M890:
-		case UNICHROME_P4M900:
-		case UNICHROME_VX800:
-			value = k800_encode_pll(pll_value[i].cx700_pll);
-			break;
+	return best;
+}
 
-		case UNICHROME_VX855:
-		case UNICHROME_VX900:
-			value = vx855_encode_pll(pll_value[i].vx855_pll);
-			break;
-		}
+u32 viafb_get_clk_value(int clk)
+{
+	u32 value = 0;
+
+	switch (viaparinfo->chip_info->gfx_chip_name) {
+	case UNICHROME_CLE266:
+	case UNICHROME_K400:
+		value = cle266_encode_pll(get_pll_config(cle266_pll_config,
+			ARRAY_SIZE(cle266_pll_config), clk));
+		break;
+	case UNICHROME_K800:
+	case UNICHROME_PM800:
+	case UNICHROME_CN700:
+		value = k800_encode_pll(get_pll_config(k800_pll_config,
+			ARRAY_SIZE(k800_pll_config), clk));
+		break;
+	case UNICHROME_CX700:
+	case UNICHROME_CN750:
+	case UNICHROME_K8M890:
+	case UNICHROME_P4M890:
+	case UNICHROME_P4M900:
+	case UNICHROME_VX800:
+		value = k800_encode_pll(get_pll_config(cx700_pll_config,
+			ARRAY_SIZE(cx700_pll_config), clk));
+		break;
+	case UNICHROME_VX855:
+	case UNICHROME_VX900:
+		value = vx855_encode_pll(get_pll_config(vx855_pll_config,
+			ARRAY_SIZE(vx855_pll_config), clk));
+		break;
 	}
 
 	return value;
@@ -2034,7 +2002,7 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 	int i;
 	int index = 0;
 	int h_addr, v_addr;
-	u32 pll_D_N;
+	u32 pll_D_N, clock;
 
 	for (i = 0; i < video_mode->mode_array; i++) {
 		index = i;
@@ -2087,7 +2055,9 @@ void viafb_fill_crtc_timing(struct crt_mode_table *crt_table,
 	    && (viaparinfo->chip_info->gfx_chip_name != UNICHROME_K400))
 		viafb_load_FIFO_reg(set_iga, h_addr, v_addr);
 
-	pll_D_N = viafb_get_clk_value(crt_table[index].clk);
+	clock = crt_reg.hor_total * crt_reg.ver_total
+		* crt_table[index].refresh_rate;
+	pll_D_N = viafb_get_clk_value(clock);
 	DEBUG_MSG(KERN_INFO "PLL=%x", pll_D_N);
 	viafb_set_vclock(pll_D_N, set_iga);
 
@@ -2117,9 +2087,6 @@ void viafb_update_device_setting(int hres, int vres,
 	int bpp, int vmode_refresh, int flag)
 {
 	if (flag == 0) {
-		viaparinfo->crt_setting_info->h_active = hres;
-		viaparinfo->crt_setting_info->v_active = vres;
-		viaparinfo->crt_setting_info->bpp = bpp;
 		viaparinfo->crt_setting_info->refresh_rate =
 			vmode_refresh;
 
@@ -2129,13 +2096,9 @@ void viafb_update_device_setting(int hres, int vres,
 		viaparinfo->lvds_setting_info->h_active = hres;
 		viaparinfo->lvds_setting_info->v_active = vres;
 		viaparinfo->lvds_setting_info->bpp = bpp;
-		viaparinfo->lvds_setting_info->refresh_rate =
-			vmode_refresh;
 		viaparinfo->lvds_setting_info2->h_active = hres;
 		viaparinfo->lvds_setting_info2->v_active = vres;
 		viaparinfo->lvds_setting_info2->bpp = bpp;
-		viaparinfo->lvds_setting_info2->refresh_rate =
-			vmode_refresh;
 	} else {
 
 		if (viaparinfo->tmds_setting_info->iga_path == IGA2) {
@@ -2147,15 +2110,11 @@ void viafb_update_device_setting(int hres, int vres,
 			viaparinfo->lvds_setting_info->h_active = hres;
 			viaparinfo->lvds_setting_info->v_active = vres;
 			viaparinfo->lvds_setting_info->bpp = bpp;
-			viaparinfo->lvds_setting_info->refresh_rate =
-				vmode_refresh;
 		}
 		if (IGA2 == viaparinfo->lvds_setting_info2->iga_path) {
 			viaparinfo->lvds_setting_info2->h_active = hres;
 			viaparinfo->lvds_setting_info2->v_active = vres;
 			viaparinfo->lvds_setting_info2->bpp = bpp;
-			viaparinfo->lvds_setting_info2->refresh_rate =
-				vmode_refresh;
 		}
 	}
 }
@@ -2430,6 +2389,7 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 		break;
 	}
 
+	viafb_write_regx(scaling_parameters, ARRAY_SIZE(scaling_parameters));
 	device_off();
 	via_set_state(devices, VIA_STATE_OFF);
 
@@ -2608,35 +2568,43 @@ int viafb_setmode(struct VideoModeTable *vmode_tbl, int video_bpp,
 int viafb_get_pixclock(int hres, int vres, int vmode_refresh)
 {
 	int i;
+	struct crt_mode_table *best;
+	struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
+
+	if (!vmode)
+		return RES_640X480_60HZ_PIXCLOCK;
 
-	for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
-		if ((hres == res_map_refresh_tbl[i].hres)
-		    && (vres == res_map_refresh_tbl[i].vres)
-		    && (vmode_refresh == res_map_refresh_tbl[i].vmode_refresh))
-			return res_map_refresh_tbl[i].pixclock;
+	best = &vmode->crtc[0];
+	for (i = 1; i < vmode->mode_array; i++) {
+		if (abs(vmode->crtc[i].refresh_rate - vmode_refresh)
+			< abs(best->refresh_rate - vmode_refresh))
+			best = &vmode->crtc[i];
 	}
-	return RES_640X480_60HZ_PIXCLOCK;
 
+	return 1000000000 / (best->crtc.hor_total * best->crtc.ver_total)
+		* 1000 / best->refresh_rate;
 }
 
 int viafb_get_refresh(int hres, int vres, u32 long_refresh)
 {
-#define REFRESH_TOLERANCE 3
-	int i, nearest = -1, diff = REFRESH_TOLERANCE;
-	for (i = 0; i < NUM_TOTAL_RES_MAP_REFRESH; i++) {
-		if ((hres == res_map_refresh_tbl[i].hres)
-		    && (vres == res_map_refresh_tbl[i].vres)
-		    && (diff > (abs(long_refresh -
-		    res_map_refresh_tbl[i].vmode_refresh)))) {
-			diff = abs(long_refresh - res_map_refresh_tbl[i].
-				vmode_refresh);
-			nearest = i;
-		}
+	int i;
+	struct crt_mode_table *best;
+	struct VideoModeTable *vmode = viafb_get_mode(hres, vres);
+
+	if (!vmode)
+		return 60;
+
+	best = &vmode->crtc[0];
+	for (i = 1; i < vmode->mode_array; i++) {
+		if (abs(vmode->crtc[i].refresh_rate - long_refresh)
+			< abs(best->refresh_rate - long_refresh))
+			best = &vmode->crtc[i];
 	}
-#undef REFRESH_TOLERANCE
-	if (nearest > 0)
-		return res_map_refresh_tbl[nearest].vmode_refresh;
-	return 60;
+
+	if (abs(best->refresh_rate - long_refresh) > 3)
+		return 60;
+
+	return best->refresh_rate;
 }
 
 static void device_off(void)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 668d534..7295263 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -893,8 +893,6 @@ struct iga2_crtc_timing {
 /* VT3410 chipset*/
 #define VX900_FUNCTION3     0x3410
 
-#define NUM_TOTAL_PLL_TABLE ARRAY_SIZE(pll_value)
-
 struct IODATA {
 	u8 Index;
 	u8 Mask;
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 3425c39..64bc7e7 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -26,10 +26,12 @@
 
 /* CLE266 Software Power Sequence */
 /* {Mask}, {Data}, {Delay} */
-int PowerSequenceOn[3][3] = { {0x10, 0x08, 0x06}, {0x10, 0x08, 0x06},
-	{0x19, 0x1FE, 0x01} };
-int PowerSequenceOff[3][3] = { {0x06, 0x08, 0x10}, {0x00, 0x00, 0x00},
-	{0xD2, 0x19, 0x01} };
+static const int PowerSequenceOn[3][3] = {
+	{0x10, 0x08, 0x06}, {0x10, 0x08, 0x06},	{0x19, 0x1FE, 0x01}
+};
+static const int PowerSequenceOff[3][3] = {
+	{0x06, 0x08, 0x10}, {0x00, 0x00, 0x00},	{0xD2, 0x19, 0x01}
+};
 
 static struct _lcd_scaling_factor lcd_scaling_factor = {
 	/* LCD Horizontal Scaling Factor Register */
@@ -95,8 +97,6 @@ void __devinit viafb_init_lcd_size(void)
 	DEBUG_MSG(KERN_INFO "viafb_init_lcd_size()\n");
 
 	fp_id_to_vindex(viafb_lcd_panel_id);
-	viaparinfo->lvds_setting_info2->lcd_panel_id =
-		viaparinfo->lvds_setting_info->lcd_panel_id;
 	viaparinfo->lvds_setting_info2->lcd_panel_hres =
 		viaparinfo->lvds_setting_info->lcd_panel_hres;
 	viaparinfo->lvds_setting_info2->lcd_panel_vres =
@@ -203,176 +203,132 @@ static void __devinit fp_id_to_vindex(int panel_id)
 	case 0x0:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 640;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID0_640X480;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x1:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID1_800X600;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x2:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x3:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x4:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID4_1280X1024;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x5:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID5_1400X1050;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x6:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID6_1600X1200;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x8:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 480;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_IDA_800X480;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x9:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0xA:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0xB:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID2_1024X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0xC:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0xD:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 1024;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID4_1280X1024;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0xE:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1400;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 1050;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID5_1400X1050;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0xF:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1600;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 1200;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID6_1600X1200;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0x10:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1366;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID7_1366X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0x11:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1024;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID8_1024X600;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x12:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x13:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 800;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID9_1280X800;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
 	case 0x14:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1360;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_IDB_1360X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0x15:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1280;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 768;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID3_1280X768;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 1;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	case 0x16:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 480;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 640;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_IDC_480X640;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 		break;
@@ -380,16 +336,12 @@ static void __devinit fp_id_to_vindex(int panel_id)
 		/* OLPC XO-1.5 panel */
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 1200;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 900;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_IDD_1200X900;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 0;
 		break;
 	default:
 		viaparinfo->lvds_setting_info->lcd_panel_hres = 800;
 		viaparinfo->lvds_setting_info->lcd_panel_vres = 600;
-		viaparinfo->lvds_setting_info->lcd_panel_id =
-			LCD_PANEL_ID1_800X600;
 		viaparinfo->lvds_setting_info->device_lcd_dualedge = 0;
 		viaparinfo->lvds_setting_info->LCDDithering = 1;
 	}
@@ -610,7 +562,7 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
 	int set_vres = plvds_setting_info->v_active;
 	int panel_hres = plvds_setting_info->lcd_panel_hres;
 	int panel_vres = plvds_setting_info->lcd_panel_vres;
-	u32 pll_D_N;
+	u32 pll_D_N, clock;
 	struct display_timing mode_crt_reg, panel_crt_reg;
 	struct crt_mode_table *panel_crt_table = NULL;
 	struct VideoModeTable *vmode_tbl = viafb_get_mode(panel_hres,
@@ -625,7 +577,9 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
 	DEBUG_MSG(KERN_INFO "bellow viafb_lcd_set_mode!!\n");
 	if (VT1636_LVDS == plvds_chip_info->lvds_chip_name)
 		viafb_init_lvds_vt1636(plvds_setting_info, plvds_chip_info);
-	plvds_setting_info->vclk = panel_crt_table->clk;
+	clock = panel_crt_reg.hor_total * panel_crt_reg.ver_total
+		* panel_crt_table->refresh_rate;
+	plvds_setting_info->vclk = clock;
 	if (set_iga == IGA1) {
 		/* IGA1 doesn't have LCD scaling, so set it as centering. */
 		viafb_load_crtc_timing(lcd_centering_timging
@@ -660,7 +614,7 @@ void viafb_lcd_set_mode(struct crt_mode_table *mode_crt_table,
 
 	fill_lcd_format();
 
-	pll_D_N = viafb_get_clk_value(panel_crt_table[0].clk);
+	pll_D_N = viafb_get_clk_value(clock);
 	DEBUG_MSG(KERN_INFO "PLL=0x%x", pll_D_N);
 	viafb_set_vclock(pll_D_N, set_iga);
 	lcd_patch_skew(plvds_setting_info, plvds_chip_info);
@@ -1064,34 +1018,33 @@ static struct display_timing lcd_centering_timging(struct display_timing
 
 bool viafb_lcd_get_mobile_state(bool *mobile)
 {
-	unsigned char *romptr, *tableptr;
+	unsigned char __iomem *romptr, *tableptr, *biosptr;
 	u8 core_base;
-	unsigned char *biosptr;
 	/* Rom address */
-	u32 romaddr = 0x000C0000;
-	u16 start_pattern = 0;
+	const u32 romaddr = 0x000C0000;
+	u16 start_pattern;
 
 	biosptr = ioremap(romaddr, 0x10000);
+	start_pattern = readw(biosptr);
 
-	memcpy(&start_pattern, biosptr, 2);
 	/* Compare pattern */
 	if (start_pattern == 0xAA55) {
 		/* Get the start of Table */
 		/* 0x1B means BIOS offset position */
 		romptr = biosptr + 0x1B;
-		tableptr = biosptr + *((u16 *) romptr);
+		tableptr = biosptr + readw(romptr);
 
 		/* Get the start of biosver structure */
 		/* 18 means BIOS version position. */
 		romptr = tableptr + 18;
-		romptr = biosptr + *((u16 *) romptr);
+		romptr = biosptr + readw(romptr);
 
 		/* The offset should be 44, but the
 		   actual image is less three char. */
 		/* pRom += 44; */
 		romptr += 41;
 
-		core_base = *romptr++;
+		core_base = readb(romptr);
 
 		if (core_base & 0x8)
 			*mobile = false;
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 2cbe103..4b7831f 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -627,77 +627,6 @@
 #define M2048x1536_R60_HSP      NEGATIVE
 #define M2048x1536_R60_VSP      POSITIVE
 
-/* define PLL index: */
-#define CLK_25_175M     25175000
-#define CLK_26_880M     26880000
-#define CLK_29_581M     29581000
-#define CLK_31_500M     31500000
-#define CLK_31_728M     31728000
-#define CLK_32_668M     32688000
-#define CLK_36_000M     36000000
-#define CLK_40_000M     40000000
-#define CLK_41_291M     41291000
-#define CLK_43_163M     43163000
-#define CLK_45_250M     45250000	/* 45.46MHz */
-#define CLK_46_000M     46000000
-#define CLK_46_996M     46996000
-#define CLK_48_000M     48000000
-#define CLK_48_875M     48875000
-#define CLK_49_500M     49500000
-#define CLK_52_406M     52406000
-#define CLK_52_977M     52977000
-#define CLK_56_250M     56250000
-#define CLK_57_275M     57275000
-#define CLK_60_466M     60466000
-#define CLK_61_500M     61500000
-#define CLK_65_000M     65000000
-#define CLK_65_178M     65178000
-#define CLK_66_750M     66750000	/* 67.116MHz */
-#define CLK_68_179M     68179000
-#define CLK_69_924M     69924000
-#define CLK_70_159M     70159000
-#define CLK_72_000M     72000000
-#define CLK_74_270M     74270000
-#define CLK_78_750M     78750000
-#define CLK_80_136M     80136000
-#define CLK_83_375M     83375000
-#define CLK_83_950M     83950000
-#define CLK_84_750M     84750000	/* 84.537Mhz */
-#define CLK_85_860M     85860000
-#define CLK_88_750M     88750000
-#define CLK_94_500M     94500000
-#define CLK_97_750M     97750000
-#define CLK_101_000M    101000000
-#define CLK_106_500M    106500000
-#define CLK_108_000M    108000000
-#define CLK_113_309M    113309000
-#define CLK_118_840M    118840000
-#define CLK_119_000M    119000000
-#define CLK_121_750M    121750000	/* 121.704MHz */
-#define CLK_125_104M    125104000
-#define CLK_135_000M    135000000
-#define CLK_136_700M    136700000
-#define CLK_138_400M    138400000
-#define CLK_146_760M    146760000
-#define CLK_148_500M    148500000
-
-#define CLK_153_920M    153920000
-#define CLK_156_000M    156000000
-#define CLK_157_500M    157500000
-#define CLK_162_000M    162000000
-#define CLK_187_000M    187000000
-#define CLK_193_295M    193295000
-#define CLK_202_500M    202500000
-#define CLK_204_000M    204000000
-#define CLK_218_500M    218500000
-#define CLK_234_000M    234000000
-#define CLK_267_250M    267250000
-#define CLK_297_500M    297500000
-#define CLK_74_481M     74481000
-#define CLK_172_798M    172798000
-#define CLK_122_614M    122614000
-
-
 /* Definition CRTC Timing Index */
 #define H_TOTAL_INDEX               0
 #define H_ADDR_INDEX                1
@@ -722,76 +651,7 @@
 
 /* Definition Video Mode Pixel Clock (picoseconds)
 */
-#define RES_480X640_60HZ_PIXCLOCK    39722
 #define RES_640X480_60HZ_PIXCLOCK    39722
-#define RES_640X480_75HZ_PIXCLOCK    31747
-#define RES_640X480_85HZ_PIXCLOCK    27777
-#define RES_640X480_100HZ_PIXCLOCK   23168
-#define RES_640X480_120HZ_PIXCLOCK   19081
-#define RES_720X480_60HZ_PIXCLOCK    37020
-#define RES_720X576_60HZ_PIXCLOCK    30611
-#define RES_800X600_60HZ_PIXCLOCK    25000
-#define RES_800X600_75HZ_PIXCLOCK    20203
-#define RES_800X600_85HZ_PIXCLOCK    17777
-#define RES_800X600_100HZ_PIXCLOCK   14667
-#define RES_800X600_120HZ_PIXCLOCK   11912
-#define RES_800X480_60HZ_PIXCLOCK    33805
-#define RES_848X480_60HZ_PIXCLOCK    31756
-#define RES_856X480_60HZ_PIXCLOCK    31518
-#define RES_1024X512_60HZ_PIXCLOCK   24218
-#define RES_1024X600_60HZ_PIXCLOCK   20460
-#define RES_1024X768_60HZ_PIXCLOCK   15385
-#define RES_1024X768_75HZ_PIXCLOCK   12699
-#define RES_1024X768_85HZ_PIXCLOCK   10582
-#define RES_1024X768_100HZ_PIXCLOCK  8825
-#define RES_1152X864_75HZ_PIXCLOCK   9259
-#define RES_1280X768_60HZ_PIXCLOCK   12480
-#define RES_1280X800_60HZ_PIXCLOCK   11994
-#define RES_1280X960_60HZ_PIXCLOCK   9259
-#define RES_1280X1024_60HZ_PIXCLOCK  9260
-#define RES_1280X1024_75HZ_PIXCLOCK  7408
-#define RES_1280X768_85HZ_PIXCLOCK   6349
-#define RES_1440X1050_60HZ_PIXCLOCK  7993
-#define RES_1600X1200_60HZ_PIXCLOCK  6172
-#define RES_1600X1200_75HZ_PIXCLOCK  4938
-#define RES_1280X720_60HZ_PIXCLOCK   13426
-#define RES_1200X900_60HZ_PIXCLOCK   17459
-#define RES_1920X1080_60HZ_PIXCLOCK  5787
-#define RES_1400X1050_60HZ_PIXCLOCK  8214
-#define RES_1400X1050_75HZ_PIXCLOCK  6410
-#define RES_1368X768_60HZ_PIXCLOCK   11647
-#define RES_960X600_60HZ_PIXCLOCK      22099
-#define RES_1000X600_60HZ_PIXCLOCK    20834
-#define RES_1024X576_60HZ_PIXCLOCK    21278
-#define RES_1088X612_60HZ_PIXCLOCK    18877
-#define RES_1152X720_60HZ_PIXCLOCK    14981
-#define RES_1200X720_60HZ_PIXCLOCK    14253
-#define RES_1280X600_60HZ_PIXCLOCK    16260
-#define RES_1280X720_50HZ_PIXCLOCK    16538
-#define RES_1280X768_50HZ_PIXCLOCK    15342
-#define RES_1366X768_50HZ_PIXCLOCK    14301
-#define RES_1366X768_60HZ_PIXCLOCK    11646
-#define RES_1360X768_60HZ_PIXCLOCK    11799
-#define RES_1440X900_60HZ_PIXCLOCK    9390
-#define RES_1440X900_75HZ_PIXCLOCK    7315
-#define RES_1600X900_60HZ_PIXCLOCK    8415
-#define RES_1600X1024_60HZ_PIXCLOCK   7315
-#define RES_1680X1050_60HZ_PIXCLOCK   6814
-#define RES_1680X1050_75HZ_PIXCLOCK   5348
-#define RES_1792X1344_60HZ_PIXCLOCK   4902
-#define RES_1856X1392_60HZ_PIXCLOCK   4577
-#define RES_1920X1200_60HZ_PIXCLOCK   5173
-#define RES_1920X1440_60HZ_PIXCLOCK   4274
-#define RES_1920X1440_75HZ_PIXCLOCK   3367
-#define RES_2048X1536_60HZ_PIXCLOCK   3742
-
-#define RES_1360X768_RB_60HZ_PIXCLOCK 13889
-#define RES_1400X1050_RB_60HZ_PIXCLOCK 9901
-#define RES_1440X900_RB_60HZ_PIXCLOCK   11268
-#define RES_1600X900_RB_60HZ_PIXCLOCK   10230
-#define RES_1680X1050_RB_60HZ_PIXCLOCK 8403
-#define RES_1920X1080_RB_60HZ_PIXCLOCK 7225
-#define RES_1920X1200_RB_60HZ_PIXCLOCK 6497
 
 /* LCD display method
 */
@@ -822,7 +682,6 @@ struct display_timing {
 
 struct crt_mode_table {
 	int refresh_rate;
-	unsigned long clk;
 	int h_sync_polarity;
 	int v_sync_polarity;
 	struct display_timing crtc;
diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/via/tblDPASetting.c
index 0c4c8cc..73bb554 100644
--- a/drivers/video/via/tblDPASetting.c
+++ b/drivers/video/via/tblDPASetting.c
@@ -20,17 +20,6 @@
  */
 
 #include "global.h"
-/* For VT3324: */
-struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[] = {
-	/* Panel ID,       CLK_SEL_ST1[09],    CLK_SEL_ST2[08] */
-	{LCD_PANEL_ID0_640X480, 0x00, 0x00},	/* For 640x480   */
-	{LCD_PANEL_ID1_800X600, 0x00, 0x00},	/* For 800x600   */
-	{LCD_PANEL_ID2_1024X768, 0x00, 0x00},	/* For 1024x768  */
-	{LCD_PANEL_ID3_1280X768, 0x00, 0x00},	/* For 1280x768  */
-	{LCD_PANEL_ID4_1280X1024, 0x00, 0x00},	/* For 1280x1024 */
-	{LCD_PANEL_ID5_1400X1050, 0x00, 0x00},	/* For 1400x1050 */
-	{LCD_PANEL_ID6_1600X1200, 0x0B, 0x03}	/* For 1600x1200 */
-};
 
 struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
 /*  ClkRange, DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
@@ -57,18 +46,6 @@ struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[] = {
 	 0x00},
 };
 
-/* For VT3327: */
-struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[] = {
-	/* Panel ID,       CLK_SEL_ST1[09],    CLK_SEL_ST2[08] */
-	{LCD_PANEL_ID0_640X480, 0x00, 0x00},	/* For 640x480   */
-	{LCD_PANEL_ID1_800X600, 0x00, 0x00},	/* For 800x600   */
-	{LCD_PANEL_ID2_1024X768, 0x00, 0x00},	/* For 1024x768  */
-	{LCD_PANEL_ID3_1280X768, 0x00, 0x00},	/* For 1280x768  */
-	{LCD_PANEL_ID4_1280X1024, 0x00, 0x00},	/* For 1280x1024 */
-	{LCD_PANEL_ID5_1400X1050, 0x00, 0x00},	/* For 1400x1050 */
-	{LCD_PANEL_ID6_1600X1200, 0x00, 0x00}	/* For 1600x1200 */
-};
-
 struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[] = {
 /*  ClkRange,DVP0, DVP0DataDriving,  DVP0ClockDriving, DVP1,
 					DVP1Driving, DFPHigh,   DFPLow */
diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/via/tblDPASetting.h
index b065a83..6db6151 100644
--- a/drivers/video/via/tblDPASetting.h
+++ b/drivers/video/via/tblDPASetting.h
@@ -38,9 +38,7 @@ enum DPA_RANGE {
 	DPA_CLK_RANGE_150M
 };
 
-extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3324[7];
 extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3324[6];
-extern struct VT1636_DPA_SETTING VT1636_DPA_SETTING_TBL_VT3327[7];
 extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3327[];
 extern struct GFX_DPA_SETTING GFX_DPA_SETTING_TBL_VT3364[6];
 
diff --git a/drivers/video/via/via_i2c.c b/drivers/video/via/via_i2c.c
index 3844b55..78f1405 100644
--- a/drivers/video/via/via_i2c.c
+++ b/drivers/video/via/via_i2c.c
@@ -32,7 +32,7 @@
  */
 #define VIAFB_NUM_I2C		5
 static struct via_i2c_stuff via_i2c_par[VIAFB_NUM_I2C];
-struct viafb_dev *i2c_vdev;  /* Passed in from core */
+static struct viafb_dev *i2c_vdev;  /* Passed in from core */
 
 static void via_i2c_setscl(void *data, int state)
 {
@@ -209,7 +209,6 @@ static int create_i2c_bus(struct i2c_adapter *adapter,
 	sprintf(adapter->name, "viafb i2c io_port idx 0x%02x",
 		adap_cfg->ioport_index);
 	adapter->owner = THIS_MODULE;
-	adapter->id = 0x01FFFF;
 	adapter->class = I2C_CLASS_DDC;
 	adapter->algo_data = algo;
 	if (pdev)
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c
index 4e66349..f555b89 100644
--- a/drivers/video/via/viafbdev.c
+++ b/drivers/video/via/viafbdev.c
@@ -43,11 +43,11 @@ static int viafb_second_size;
 static int viafb_accel = 1;
 
 /* Added for specifying active devices.*/
-char *viafb_active_dev;
+static char *viafb_active_dev;
 
 /*Added for specify lcd output port*/
-char *viafb_lcd_port = "";
-char *viafb_dvi_port = "";
+static char *viafb_lcd_port = "";
+static char *viafb_dvi_port = "";
 
 static void retrieve_device_setting(struct viafb_ioctl_setting
 	*setting_info);
diff --git a/drivers/video/via/viafbdev.h b/drivers/video/via/viafbdev.h
index d66f963..137996d 100644
--- a/drivers/video/via/viafbdev.h
+++ b/drivers/video/via/viafbdev.h
@@ -94,9 +94,6 @@ extern int viafb_LCD_ON;
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
 
-extern int strict_strtoul(const char *cp, unsigned int base,
-	unsigned long *res);
-
 u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information
 	*plvds_setting_info, struct lvds_chip_information
 	*plvds_chip_info, u8 index);
diff --git a/drivers/video/via/viamode.c b/drivers/video/via/viamode.c
index 2dbad3c..8c5bc41 100644
--- a/drivers/video/via/viamode.c
+++ b/drivers/video/via/viamode.c
@@ -21,72 +21,6 @@
 
 #include <linux/via-core.h>
 #include "global.h"
-struct res_map_refresh res_map_refresh_tbl[] = {
-/*hres, vres, vclock, vmode_refresh*/
-	{480, 640, RES_480X640_60HZ_PIXCLOCK, 60},
-	{640, 480, RES_640X480_60HZ_PIXCLOCK, 60},
-	{640, 480, RES_640X480_75HZ_PIXCLOCK, 75},
-	{640, 480, RES_640X480_85HZ_PIXCLOCK, 85},
-	{640, 480, RES_640X480_100HZ_PIXCLOCK, 100},
-	{640, 480, RES_640X480_120HZ_PIXCLOCK, 120},
-	{720, 480, RES_720X480_60HZ_PIXCLOCK, 60},
-	{720, 576, RES_720X576_60HZ_PIXCLOCK, 60},
-	{800, 480, RES_800X480_60HZ_PIXCLOCK, 60},
-	{800, 600, RES_800X600_60HZ_PIXCLOCK, 60},
-	{800, 600, RES_800X600_75HZ_PIXCLOCK, 75},
-	{800, 600, RES_800X600_85HZ_PIXCLOCK, 85},
-	{800, 600, RES_800X600_100HZ_PIXCLOCK, 100},
-	{800, 600, RES_800X600_120HZ_PIXCLOCK, 120},
-	{848, 480, RES_848X480_60HZ_PIXCLOCK, 60},
-	{856, 480, RES_856X480_60HZ_PIXCLOCK, 60},
-	{1024, 512, RES_1024X512_60HZ_PIXCLOCK, 60},
-	{1024, 600, RES_1024X600_60HZ_PIXCLOCK, 60},
-	{1024, 768, RES_1024X768_60HZ_PIXCLOCK, 60},
-	{1024, 768, RES_1024X768_75HZ_PIXCLOCK, 75},
-	{1024, 768, RES_1024X768_85HZ_PIXCLOCK, 85},
-	{1024, 768, RES_1024X768_100HZ_PIXCLOCK, 100},
-/*  {1152,864, RES_1152X864_70HZ_PIXCLOCK,  70},*/
-	{1152, 864, RES_1152X864_75HZ_PIXCLOCK, 75},
-	{1280, 768, RES_1280X768_60HZ_PIXCLOCK, 60},
-	{1280, 800, RES_1280X800_60HZ_PIXCLOCK, 60},
-	{1280, 960, RES_1280X960_60HZ_PIXCLOCK, 60},
-	{1280, 1024, RES_1280X1024_60HZ_PIXCLOCK, 60},
-	{1280, 1024, RES_1280X1024_75HZ_PIXCLOCK, 75},
-	{1280, 1024, RES_1280X768_85HZ_PIXCLOCK, 85},
-	{1440, 1050, RES_1440X1050_60HZ_PIXCLOCK, 60},
-	{1600, 1200, RES_1600X1200_60HZ_PIXCLOCK, 60},
-	{1600, 1200, RES_1600X1200_75HZ_PIXCLOCK, 75},
-	{1280, 720, RES_1280X720_60HZ_PIXCLOCK, 60},
-	{1920, 1080, RES_1920X1080_60HZ_PIXCLOCK, 60},
-	{1400, 1050, RES_1400X1050_60HZ_PIXCLOCK, 60},
-	{1400, 1050, RES_1400X1050_75HZ_PIXCLOCK, 75},
-	{1368, 768, RES_1368X768_60HZ_PIXCLOCK, 60},
-	{960, 600, RES_960X600_60HZ_PIXCLOCK, 60},
-	{1000, 600, RES_1000X600_60HZ_PIXCLOCK, 60},
-	{1024, 576, RES_1024X576_60HZ_PIXCLOCK, 60},
-	{1088, 612, RES_1088X612_60HZ_PIXCLOCK, 60},
-	{1152, 720, RES_1152X720_60HZ_PIXCLOCK, 60},
-	{1200, 720, RES_1200X720_60HZ_PIXCLOCK, 60},
-	{1200, 900, RES_1200X900_60HZ_PIXCLOCK, 60},
-	{1280, 600, RES_1280X600_60HZ_PIXCLOCK, 60},
-	{1280, 720, RES_1280X720_50HZ_PIXCLOCK, 50},
-	{1280, 768, RES_1280X768_50HZ_PIXCLOCK, 50},
-	{1360, 768, RES_1360X768_60HZ_PIXCLOCK, 60},
-	{1366, 768, RES_1366X768_50HZ_PIXCLOCK, 50},
-	{1366, 768, RES_1366X768_60HZ_PIXCLOCK, 60},
-	{1440, 900, RES_1440X900_60HZ_PIXCLOCK, 60},
-	{1440, 900, RES_1440X900_75HZ_PIXCLOCK, 75},
-	{1600, 900, RES_1600X900_60HZ_PIXCLOCK, 60},
-	{1600, 1024, RES_1600X1024_60HZ_PIXCLOCK, 60},
-	{1680, 1050, RES_1680X1050_60HZ_PIXCLOCK, 60},
-	{1680, 1050, RES_1680X1050_75HZ_PIXCLOCK, 75},
-	{1792, 1344, RES_1792X1344_60HZ_PIXCLOCK, 60},
-	{1856, 1392, RES_1856X1392_60HZ_PIXCLOCK, 60},
-	{1920, 1200, RES_1920X1200_60HZ_PIXCLOCK, 60},
-	{1920, 1440, RES_1920X1440_60HZ_PIXCLOCK, 60},
-	{1920, 1440, RES_1920X1440_75HZ_PIXCLOCK, 75},
-	{2048, 1536, RES_2048X1536_60HZ_PIXCLOCK, 60}
-};
 
 struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
 {VIASR, SR15, 0x02, 0x02},
@@ -108,20 +42,6 @@ struct io_reg CN400_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
 {VIACR, CR6A, 0xFF, 0x40},
 {VIACR, CR6B, 0xFF, 0x00},
 {VIACR, CR6C, 0xFF, 0x00},
-{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1             */
-{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2             */
-{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3             */
-{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4             */
-{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5             */
-{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6             */
-{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7             */
-{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8             */
-{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9             */
-{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10            */
-{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11            */
-{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12            */
-{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13            */
-{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14            */
 {VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                      */
 {VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0                */
 {VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1                */
@@ -172,20 +92,6 @@ struct io_reg CN700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
 {VIACR, CR78, 0xFF, 0x00},	/* LCD scaling Factor */
 {VIACR, CR79, 0xFF, 0x00},	/* LCD scaling Factor */
 {VIACR, CR9F, 0x03, 0x00},	/* LCD scaling Factor */
-{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1 */
-{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2 */
-{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3 */
-{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4 */
-{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5 */
-{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6 */
-{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7 */
-{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8 */
-{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9 */
-{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10 */
-{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11 */
-{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12 */
-{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13 */
-{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14 */
 {VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type */
 {VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0 */
 {VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1 */
@@ -229,20 +135,6 @@ struct io_reg KM400_ModeXregs[] = {
 	{VIACR, CR36, 0xFF, 0x01},	/* Power Mangement 3                  */
 	{VIACR, CR68, 0xFF, 0x67},	/* Default FIFO For IGA2              */
 	{VIACR, CR6A, 0x20, 0x20},	/* Extended FIFO On                   */
-	{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1            */
-	{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2            */
-	{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3            */
-	{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4            */
-	{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5            */
-	{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6            */
-	{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7            */
-	{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8            */
-	{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9            */
-	{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10           */
-	{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11           */
-	{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12           */
-	{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13           */
-	{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14           */
 	{VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                     */
 	{VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0               */
 	{VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1               */
@@ -283,20 +175,6 @@ struct io_reg CX700_ModeXregs[] = { {VIASR, SR10, 0xFF, 0x01},
 {VIACR, CR6A, 0xFF, 0x40},
 {VIACR, CR6B, 0xFF, 0x00},
 {VIACR, CR6C, 0xFF, 0x00},
-{VIACR, CR7A, 0xFF, 0x01},	/* LCD Scaling Parameter 1             */
-{VIACR, CR7B, 0xFF, 0x02},	/* LCD Scaling Parameter 2             */
-{VIACR, CR7C, 0xFF, 0x03},	/* LCD Scaling Parameter 3             */
-{VIACR, CR7D, 0xFF, 0x04},	/* LCD Scaling Parameter 4             */
-{VIACR, CR7E, 0xFF, 0x07},	/* LCD Scaling Parameter 5             */
-{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Scaling Parameter 6             */
-{VIACR, CR80, 0xFF, 0x0D},	/* LCD Scaling Parameter 7             */
-{VIACR, CR81, 0xFF, 0x13},	/* LCD Scaling Parameter 8             */
-{VIACR, CR82, 0xFF, 0x16},	/* LCD Scaling Parameter 9             */
-{VIACR, CR83, 0xFF, 0x19},	/* LCD Scaling Parameter 10            */
-{VIACR, CR84, 0xFF, 0x1C},	/* LCD Scaling Parameter 11            */
-{VIACR, CR85, 0xFF, 0x1D},	/* LCD Scaling Parameter 12            */
-{VIACR, CR86, 0xFF, 0x1E},	/* LCD Scaling Parameter 13            */
-{VIACR, CR87, 0xFF, 0x1F},	/* LCD Scaling Parameter 14            */
 {VIACR, CR88, 0xFF, 0x40},	/* LCD Panel Type                      */
 {VIACR, CR89, 0xFF, 0x00},	/* LCD Timing Control 0                */
 {VIACR, CR8A, 0xFF, 0x88},	/* LCD Timing Control 1                */
@@ -342,20 +220,6 @@ struct io_reg VX855_ModeXregs[] = {
 {VIACR, CR6A, 0xFD, 0x60},
 {VIACR, CR6B, 0xFF, 0x00},
 {VIACR, CR6C, 0xFF, 0x00},
-{VIACR, CR7A, 0xFF, 0x01},          /* LCD Scaling Parameter 1             */
-{VIACR, CR7B, 0xFF, 0x02},          /* LCD Scaling Parameter 2             */
-{VIACR, CR7C, 0xFF, 0x03},          /* LCD Scaling Parameter 3             */
-{VIACR, CR7D, 0xFF, 0x04},          /* LCD Scaling Parameter 4             */
-{VIACR, CR7E, 0xFF, 0x07},          /* LCD Scaling Parameter 5             */
-{VIACR, CR7F, 0xFF, 0x0A},          /* LCD Scaling Parameter 6             */
-{VIACR, CR80, 0xFF, 0x0D},          /* LCD Scaling Parameter 7             */
-{VIACR, CR81, 0xFF, 0x13},          /* LCD Scaling Parameter 8             */
-{VIACR, CR82, 0xFF, 0x16},          /* LCD Scaling Parameter 9             */
-{VIACR, CR83, 0xFF, 0x19},          /* LCD Scaling Parameter 10            */
-{VIACR, CR84, 0xFF, 0x1C},          /* LCD Scaling Parameter 11            */
-{VIACR, CR85, 0xFF, 0x1D},          /* LCD Scaling Parameter 12            */
-{VIACR, CR86, 0xFF, 0x1E},          /* LCD Scaling Parameter 13            */
-{VIACR, CR87, 0xFF, 0x1F},          /* LCD Scaling Parameter 14            */
 {VIACR, CR88, 0xFF, 0x40},          /* LCD Panel Type                      */
 {VIACR, CR89, 0xFF, 0x00},          /* LCD Timing Control 0                */
 {VIACR, CR8A, 0xFF, 0x88},          /* LCD Timing Control 1                */
@@ -390,21 +254,6 @@ struct io_reg CLE266_ModeXregs[] = { {VIASR, SR1E, 0xF0, 0x00},
 {VIAGR, GR20, 0xFF, 0x00},
 {VIAGR, GR21, 0xFF, 0x00},
 {VIAGR, GR22, 0xFF, 0x00},
-	/* LCD Parameters */
-{VIACR, CR7A, 0xFF, 0x01},	/* LCD Parameter 1 */
-{VIACR, CR7B, 0xFF, 0x02},	/* LCD Parameter 2 */
-{VIACR, CR7C, 0xFF, 0x03},	/* LCD Parameter 3 */
-{VIACR, CR7D, 0xFF, 0x04},	/* LCD Parameter 4 */
-{VIACR, CR7E, 0xFF, 0x07},	/* LCD Parameter 5 */
-{VIACR, CR7F, 0xFF, 0x0A},	/* LCD Parameter 6 */
-{VIACR, CR80, 0xFF, 0x0D},	/* LCD Parameter 7 */
-{VIACR, CR81, 0xFF, 0x13},	/* LCD Parameter 8 */
-{VIACR, CR82, 0xFF, 0x16},	/* LCD Parameter 9 */
-{VIACR, CR83, 0xFF, 0x19},	/* LCD Parameter 10 */
-{VIACR, CR84, 0xFF, 0x1C},	/* LCD Parameter 11 */
-{VIACR, CR85, 0xFF, 0x1D},	/* LCD Parameter 12 */
-{VIACR, CR86, 0xFF, 0x1E},	/* LCD Parameter 13 */
-{VIACR, CR87, 0xFF, 0x1F},	/* LCD Parameter 14 */
 
 };
 
@@ -443,328 +292,321 @@ struct VPITTable VPIT = {
 /********************/
 
 /* 480x640 */
-struct crt_mode_table CRTM480x640[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM480x640[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_25_175M, M480X640_R60_HSP, M480X640_R60_VSP,
+	{REFRESH_60, M480X640_R60_HSP, M480X640_R60_VSP,
 	 {624, 480, 480, 144, 504, 48, 663, 640, 640, 23, 641, 3} }	/* GTF*/
 };
 
 /* 640x480*/
-struct crt_mode_table CRTM640x480[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM640x480[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_25_175M, M640X480_R60_HSP, M640X480_R60_VSP,
+	{REFRESH_60, M640X480_R60_HSP, M640X480_R60_VSP,
 	 {800, 640, 648, 144, 656, 96, 525, 480, 480, 45, 490, 2} },
-	{REFRESH_75, CLK_31_500M, M640X480_R75_HSP, M640X480_R75_VSP,
+	{REFRESH_75, M640X480_R75_HSP, M640X480_R75_VSP,
 	 {840, 640, 640, 200, 656, 64, 500, 480, 480, 20, 481, 3} },
-	{REFRESH_85, CLK_36_000M, M640X480_R85_HSP, M640X480_R85_VSP,
+	{REFRESH_85, M640X480_R85_HSP, M640X480_R85_VSP,
 	 {832, 640, 640, 192, 696, 56, 509, 480, 480, 29, 481, 3} },
-	{REFRESH_100, CLK_43_163M, M640X480_R100_HSP, M640X480_R100_VSP,
+	{REFRESH_100, M640X480_R100_HSP, M640X480_R100_VSP,
 	 {848, 640, 640, 208, 680, 64, 509, 480, 480, 29, 481, 3} }, /*GTF*/
-	    {REFRESH_120, CLK_52_406M, M640X480_R120_HSP,
-	     M640X480_R120_VSP,
-	     {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481,
-	      3} } /*GTF*/
+	{REFRESH_120, M640X480_R120_HSP, M640X480_R120_VSP,
+	 {848, 640, 640, 208, 680, 64, 515, 480, 480, 35, 481, 3} } /*GTF*/
 };
 
 /*720x480 (GTF)*/
-struct crt_mode_table CRTM720x480[] = {
-	/*r_rate,vclk,hsp,vsp      */
+static struct crt_mode_table CRTM720x480[] = {
+	/*r_rate,hsp,vsp      */
 	/*HT, HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_26_880M, M720X480_R60_HSP, M720X480_R60_VSP,
+	{REFRESH_60, M720X480_R60_HSP, M720X480_R60_VSP,
 	 {896, 720, 720, 176, 736, 72, 497, 480, 480, 17, 481, 3} }
 
 };
 
 /*720x576 (GTF)*/
-struct crt_mode_table CRTM720x576[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM720x576[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_32_668M, M720X576_R60_HSP, M720X576_R60_VSP,
+	{REFRESH_60, M720X576_R60_HSP, M720X576_R60_VSP,
 	 {912, 720, 720, 192, 744, 72, 597, 576, 576, 21, 577, 3} }
 };
 
 /* 800x480 (CVT) */
-struct crt_mode_table CRTM800x480[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM800x480[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_29_581M, M800X480_R60_HSP, M800X480_R60_VSP,
+	{REFRESH_60, M800X480_R60_HSP, M800X480_R60_VSP,
 	 {992, 800, 800, 192, 824, 72, 500, 480, 480, 20, 483, 7} }
 };
 
 /* 800x600*/
-struct crt_mode_table CRTM800x600[] = {
-	/*r_rate,vclk,hsp,vsp     */
+static struct crt_mode_table CRTM800x600[] = {
+	/*r_rate,hsp,vsp     */
 	/*HT,   HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_40_000M, M800X600_R60_HSP, M800X600_R60_VSP,
+	{REFRESH_60, M800X600_R60_HSP, M800X600_R60_VSP,
 	 {1056, 800, 800, 256, 840, 128, 628, 600, 600, 28, 601, 4} },
-	{REFRESH_75, CLK_49_500M, M800X600_R75_HSP, M800X600_R75_VSP,
+	{REFRESH_75, M800X600_R75_HSP, M800X600_R75_VSP,
 	 {1056, 800, 800, 256, 816, 80, 625, 600, 600, 25, 601, 3} },
-	{REFRESH_85, CLK_56_250M, M800X600_R85_HSP, M800X600_R85_VSP,
+	{REFRESH_85, M800X600_R85_HSP, M800X600_R85_VSP,
 	 {1048, 800, 800, 248, 832, 64, 631, 600, 600, 31, 601, 3} },
-	{REFRESH_100, CLK_68_179M, M800X600_R100_HSP, M800X600_R100_VSP,
+	{REFRESH_100, M800X600_R100_HSP, M800X600_R100_VSP,
 	 {1072, 800, 800, 272, 848, 88, 636, 600, 600, 36, 601, 3} },
-	{REFRESH_120, CLK_83_950M, M800X600_R120_HSP,
-		  M800X600_R120_VSP,
-		  {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601,
-		   3} }
+	{REFRESH_120, M800X600_R120_HSP, M800X600_R120_VSP,
+	 {1088, 800, 800, 288, 856, 88, 643, 600, 600, 43, 601, 3} }
 };
 
 /* 848x480 (CVT) */
-struct crt_mode_table CRTM848x480[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM848x480[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_31_500M, M848X480_R60_HSP, M848X480_R60_VSP,
+	{REFRESH_60, M848X480_R60_HSP, M848X480_R60_VSP,
 	 {1056, 848, 848, 208, 872, 80, 500, 480, 480, 20, 483, 5} }
 };
 
 /*856x480 (GTF) convert to 852x480*/
-struct crt_mode_table CRTM852x480[] = {
-	/*r_rate,vclk,hsp,vsp     */
+static struct crt_mode_table CRTM852x480[] = {
+	/*r_rate,hsp,vsp     */
 	/*HT,   HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_31_728M, M852X480_R60_HSP, M852X480_R60_VSP,
+	{REFRESH_60, M852X480_R60_HSP, M852X480_R60_VSP,
 	{1064, 856, 856, 208, 872, 88, 497, 480, 480, 17, 481, 3} }
 };
 
 /*1024x512 (GTF)*/
-struct crt_mode_table CRTM1024x512[] = {
-	/*r_rate,vclk,hsp,vsp     */
+static struct crt_mode_table CRTM1024x512[] = {
+	/*r_rate,hsp,vsp     */
 	/*HT,   HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_41_291M, M1024X512_R60_HSP, M1024X512_R60_VSP,
+	{REFRESH_60, M1024X512_R60_HSP, M1024X512_R60_VSP,
 	 {1296, 1024, 1024, 272, 1056, 104, 531, 512, 512, 19, 513, 3} }
 
 };
 
 /* 1024x600*/
-struct crt_mode_table CRTM1024x600[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1024x600[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_48_875M, M1024X600_R60_HSP, M1024X600_R60_VSP,
+	{REFRESH_60, M1024X600_R60_HSP, M1024X600_R60_VSP,
 	 {1312, 1024, 1024, 288, 1064, 104, 622, 600, 600, 22, 601, 3} },
 };
 
 /* 1024x768*/
-struct crt_mode_table CRTM1024x768[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1024x768[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_65_000M, M1024X768_R60_HSP, M1024X768_R60_VSP,
+	{REFRESH_60, M1024X768_R60_HSP, M1024X768_R60_VSP,
 	{1344, 1024, 1024, 320, 1048, 136, 806, 768, 768, 38, 771, 6} },
-	{REFRESH_75, CLK_78_750M, M1024X768_R75_HSP, M1024X768_R75_VSP,
+	{REFRESH_75, M1024X768_R75_HSP, M1024X768_R75_VSP,
 	{1312, 1024, 1024, 288, 1040, 96, 800, 768, 768, 32, 769, 3} },
-	{REFRESH_85, CLK_94_500M, M1024X768_R85_HSP, M1024X768_R85_VSP,
+	{REFRESH_85, M1024X768_R85_HSP, M1024X768_R85_VSP,
 	{1376, 1024, 1024, 352, 1072, 96, 808, 768, 768, 40, 769, 3} },
-	{REFRESH_100, CLK_113_309M, M1024X768_R100_HSP, M1024X768_R100_VSP,
+	{REFRESH_100, M1024X768_R100_HSP, M1024X768_R100_VSP,
 	{1392, 1024, 1024, 368, 1096, 112, 814, 768, 768, 46, 769, 3} }
 };
 
 /* 1152x864*/
-struct crt_mode_table CRTM1152x864[] = {
-	/*r_rate,vclk,hsp,vsp      */
+static struct crt_mode_table CRTM1152x864[] = {
+	/*r_rate,hsp,vsp      */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_75, CLK_108_000M, M1152X864_R75_HSP, M1152X864_R75_VSP,
+	{REFRESH_75, M1152X864_R75_HSP, M1152X864_R75_VSP,
 	 {1600, 1152, 1152, 448, 1216, 128, 900, 864, 864, 36, 865, 3} }
 
 };
 
 /* 1280x720 (HDMI 720P)*/
-struct crt_mode_table CRTM1280x720[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1280x720[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE      */
-	{REFRESH_60, CLK_74_481M, M1280X720_R60_HSP, M1280X720_R60_VSP,
+	{REFRESH_60, M1280X720_R60_HSP, M1280X720_R60_VSP,
 	 {1648, 1280, 1280, 368, 1392, 40, 750, 720, 720, 30, 725, 5} },
-	{REFRESH_50, CLK_60_466M, M1280X720_R50_HSP, M1280X720_R50_VSP,
+	{REFRESH_50, M1280X720_R50_HSP, M1280X720_R50_VSP,
 	 {1632, 1280, 1280, 352, 1328, 128, 741, 720, 720, 21, 721, 3} }
 };
 
 /*1280x768 (GTF)*/
-struct crt_mode_table CRTM1280x768[] = {
-	/*r_rate,vclk,hsp,vsp     */
+static struct crt_mode_table CRTM1280x768[] = {
+	/*r_rate,hsp,vsp     */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_80_136M, M1280X768_R60_HSP, M1280X768_R60_VSP,
+	{REFRESH_60, M1280X768_R60_HSP, M1280X768_R60_VSP,
 	 {1680, 1280, 1280, 400, 1344, 136, 795, 768, 768, 27, 769, 3} },
-	{REFRESH_50, CLK_65_178M, M1280X768_R50_HSP, M1280X768_R50_VSP,
+	{REFRESH_50, M1280X768_R50_HSP, M1280X768_R50_VSP,
 	 {1648, 1280, 1280, 368, 1336, 128, 791, 768, 768, 23, 769, 3} }
 };
 
 /* 1280x800 (CVT) */
-struct crt_mode_table CRTM1280x800[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1280x800[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_83_375M, M1280X800_R60_HSP, M1280X800_R60_VSP,
+	{REFRESH_60, M1280X800_R60_HSP, M1280X800_R60_VSP,
 	 {1680, 1280, 1280, 400, 1352, 128, 831, 800, 800, 31, 803, 6} }
 };
 
 /*1280x960*/
-struct crt_mode_table CRTM1280x960[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1280x960[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_108_000M, M1280X960_R60_HSP, M1280X960_R60_VSP,
+	{REFRESH_60, M1280X960_R60_HSP, M1280X960_R60_VSP,
 	 {1800, 1280, 1280, 520, 1376, 112, 1000, 960, 960, 40, 961, 3} }
 };
 
 /* 1280x1024*/
-struct crt_mode_table CRTM1280x1024[] = {
-	/*r_rate,vclk,,hsp,vsp */
+static struct crt_mode_table CRTM1280x1024[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_108_000M, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
+	{REFRESH_60, M1280X1024_R60_HSP, M1280X1024_R60_VSP,
 	 {1688, 1280, 1280, 408, 1328, 112, 1066, 1024, 1024, 42, 1025,
 	  3} },
-	{REFRESH_75, CLK_135_000M, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
+	{REFRESH_75, M1280X1024_R75_HSP, M1280X1024_R75_VSP,
 	 {1688, 1280, 1280, 408, 1296, 144, 1066, 1024, 1024, 42, 1025,
 	  3} },
-	{REFRESH_85, CLK_157_500M, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
+	{REFRESH_85, M1280X1024_R85_HSP, M1280X1024_R85_VSP,
 	 {1728, 1280, 1280, 448, 1344, 160, 1072, 1024, 1024, 48, 1025, 3} }
 };
 
 /* 1368x768 (GTF) */
-struct crt_mode_table CRTM1368x768[] = {
-	/* r_rate,  vclk, hsp, vsp */
+static struct crt_mode_table CRTM1368x768[] = {
+	/* r_rate,  hsp, vsp */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
+	{REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
 	 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} }
 };
 
 /*1440x1050 (GTF)*/
-struct crt_mode_table CRTM1440x1050[] = {
-	/*r_rate,vclk,hsp,vsp      */
+static struct crt_mode_table CRTM1440x1050[] = {
+	/*r_rate,hsp,vsp      */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_125_104M, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
+	{REFRESH_60, M1440X1050_R60_HSP, M1440X1050_R60_VSP,
 	 {1936, 1440, 1440, 496, 1536, 152, 1077, 1040, 1040, 37, 1041, 3} }
 };
 
 /* 1600x1200*/
-struct crt_mode_table CRTM1600x1200[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1600x1200[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_162_000M, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
+	{REFRESH_60, M1600X1200_R60_HSP, M1600X1200_R60_VSP,
 	 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201,
 	  3} },
-	{REFRESH_75, CLK_202_500M, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
+	{REFRESH_75, M1600X1200_R75_HSP, M1600X1200_R75_VSP,
 	 {2160, 1600, 1600, 560, 1664, 192, 1250, 1200, 1200, 50, 1201, 3} }
 
 };
 
 /* 1680x1050 (CVT) */
-struct crt_mode_table CRTM1680x1050[] = {
-	/* r_rate,          vclk,              hsp,             vsp  */
+static struct crt_mode_table CRTM1680x1050[] = {
+	/* r_rate,              hsp,             vsp  */
 	/* HT,  HA,  HBS, HBE, HSS, HSE,    VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_146_760M, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
+	{REFRESH_60, M1680x1050_R60_HSP, M1680x1050_R60_VSP,
 	 {2240, 1680, 1680, 560, 1784, 176, 1089, 1050, 1050, 39, 1053,
 	  6} },
-	{REFRESH_75, CLK_187_000M, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
+	{REFRESH_75, M1680x1050_R75_HSP, M1680x1050_R75_VSP,
 	 {2272, 1680, 1680, 592, 1800, 176, 1099, 1050, 1050, 49, 1053, 6} }
 };
 
 /* 1680x1050 (CVT Reduce Blanking) */
-struct crt_mode_table CRTM1680x1050_RB[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1680x1050_RB[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE,    VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_119_000M, M1680x1050_RB_R60_HSP,
-	 M1680x1050_RB_R60_VSP,
+	{REFRESH_60, M1680x1050_RB_R60_HSP, M1680x1050_RB_R60_VSP,
 	 {1840, 1680, 1680, 160, 1728, 32, 1080, 1050, 1050, 30, 1053, 6} }
 };
 
 /* 1920x1080 (CVT)*/
-struct crt_mode_table CRTM1920x1080[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1920x1080[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_172_798M, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
+	{REFRESH_60, M1920X1080_R60_HSP, M1920X1080_R60_VSP,
 	 {2576, 1920, 1920, 656, 2048, 200, 1120, 1080, 1080, 40, 1083, 5} }
 };
 
 /* 1920x1080 (CVT with Reduce Blanking) */
-struct crt_mode_table CRTM1920x1080_RB[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1920x1080_RB[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_138_400M, M1920X1080_RB_R60_HSP,
-	 M1920X1080_RB_R60_VSP,
+	{REFRESH_60, M1920X1080_RB_R60_HSP, M1920X1080_RB_R60_VSP,
 	 {2080, 1920, 1920, 160, 1968, 32, 1111, 1080, 1080, 31, 1083, 5} }
 };
 
 /* 1920x1440*/
-struct crt_mode_table CRTM1920x1440[] = {
-	/*r_rate,vclk,hsp,vsp */
+static struct crt_mode_table CRTM1920x1440[] = {
+	/*r_rate,hsp,vsp */
 	/*HT,  HA,   HBS,  HBE, HSS,  HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_234_000M, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
+	{REFRESH_60, M1920X1440_R60_HSP, M1920X1440_R60_VSP,
 	 {2600, 1920, 1920, 680, 2048, 208, 1500, 1440, 1440, 60, 1441,
 	  3} },
-	{REFRESH_75, CLK_297_500M, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
+	{REFRESH_75, M1920X1440_R75_HSP, M1920X1440_R75_VSP,
 	 {2640, 1920, 1920, 720, 2064, 224, 1500, 1440, 1440, 60, 1441, 3} }
 };
 
 /* 1400x1050 (CVT) */
-struct crt_mode_table CRTM1400x1050[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1400x1050[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_121_750M, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
+	{REFRESH_60, M1400X1050_R60_HSP, M1400X1050_R60_VSP,
 	 {1864, 1400, 1400, 464, 1488, 144, 1089, 1050, 1050, 39, 1053,
 	  4} },
-	{REFRESH_75, CLK_156_000M, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
+	{REFRESH_75, M1400X1050_R75_HSP, M1400X1050_R75_VSP,
 	 {1896, 1400, 1400, 496, 1504, 144, 1099, 1050, 1050, 49, 1053, 4} }
 };
 
 /* 1400x1050 (CVT Reduce Blanking) */
-struct crt_mode_table CRTM1400x1050_RB[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1400x1050_RB[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_101_000M, M1400X1050_RB_R60_HSP,
-	 M1400X1050_RB_R60_VSP,
+	{REFRESH_60, M1400X1050_RB_R60_HSP, M1400X1050_RB_R60_VSP,
 	 {1560, 1400, 1400, 160, 1448, 32, 1080, 1050, 1050, 30, 1053, 4} }
 };
 
 /* 960x600 (CVT) */
-struct crt_mode_table CRTM960x600[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM960x600[] = {
+	/* r_rate,          hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_45_250M, M960X600_R60_HSP, M960X600_R60_VSP,
+	{REFRESH_60, M960X600_R60_HSP, M960X600_R60_VSP,
 	 {1216, 960, 960, 256, 992, 96, 624, 600, 600, 24, 603, 6} }
 };
 
 /* 1000x600 (GTF) */
-struct crt_mode_table CRTM1000x600[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1000x600[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_48_000M, M1000X600_R60_HSP, M1000X600_R60_VSP,
+	{REFRESH_60, M1000X600_R60_HSP, M1000X600_R60_VSP,
 	 {1288, 1000, 1000, 288, 1040, 104, 622, 600, 600, 22, 601, 3} }
 };
 
 /* 1024x576 (GTF) */
-struct crt_mode_table CRTM1024x576[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1024x576[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_46_996M, M1024X576_R60_HSP, M1024X576_R60_VSP,
+	{REFRESH_60, M1024X576_R60_HSP, M1024X576_R60_VSP,
 	 {1312, 1024, 1024, 288, 1064, 104, 597, 576, 576, 21, 577, 3} }
 };
 
 /* 1088x612 (CVT) */
-struct crt_mode_table CRTM1088x612[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1088x612[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_52_977M, M1088X612_R60_HSP, M1088X612_R60_VSP,
+	{REFRESH_60, M1088X612_R60_HSP, M1088X612_R60_VSP,
 	 {1392, 1088, 1088, 304, 1136, 104, 636, 612, 612, 24, 615, 5} }
 };
 
 /* 1152x720 (CVT) */
-struct crt_mode_table CRTM1152x720[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1152x720[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_66_750M, M1152X720_R60_HSP, M1152X720_R60_VSP,
+	{REFRESH_60, M1152X720_R60_HSP, M1152X720_R60_VSP,
 	 {1488, 1152, 1152, 336, 1208, 112, 748, 720, 720, 28, 723, 6} }
 };
 
 /* 1200x720 (GTF) */
-struct crt_mode_table CRTM1200x720[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1200x720[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_70_159M, M1200X720_R60_HSP, M1200X720_R60_VSP,
+	{REFRESH_60, M1200X720_R60_HSP, M1200X720_R60_VSP,
 	 {1568, 1200, 1200, 368, 1256, 128, 746, 720, 720, 26, 721, 3} }
 };
 
 /* 1200x900 (DCON) */
-struct crt_mode_table DCON1200x900[] = {
-	/* r_rate,          vclk,               hsp,               vsp   */
-	{REFRESH_60, CLK_57_275M, M1200X900_R60_HSP, M1200X900_R60_VSP,
+static struct crt_mode_table DCON1200x900[] = {
+	/* r_rate,               hsp,               vsp   */
+	{REFRESH_60, M1200X900_R60_HSP, M1200X900_R60_VSP,
 	/* The correct htotal is 1240, but this doesn't raster on VX855. */
 	/* Via suggested changing to a multiple of 16, hence 1264.       */
 	/*  HT,   HA,  HBS, HBE,  HSS, HSE,  VT,  VA, VBS, VBE, VSS, VSE */
@@ -772,126 +614,122 @@ struct crt_mode_table DCON1200x900[] = {
 };
 
 /* 1280x600 (GTF) */
-struct crt_mode_table CRTM1280x600[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1280x600[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE, VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_61_500M, M1280x600_R60_HSP, M1280x600_R60_VSP,
+	{REFRESH_60, M1280x600_R60_HSP, M1280x600_R60_VSP,
 	 {1648, 1280, 1280, 368, 1336, 128, 622, 600, 600, 22, 601, 3} }
 };
 
 /* 1360x768 (CVT) */
-struct crt_mode_table CRTM1360x768[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1360x768[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_84_750M, M1360X768_R60_HSP, M1360X768_R60_VSP,
+	{REFRESH_60, M1360X768_R60_HSP, M1360X768_R60_VSP,
 	 {1776, 1360, 1360, 416, 1432, 136, 798, 768, 768, 30, 771, 5} }
 };
 
 /* 1360x768 (CVT Reduce Blanking) */
-struct crt_mode_table CRTM1360x768_RB[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1360x768_RB[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_72_000M, M1360X768_RB_R60_HSP,
-	 M1360X768_RB_R60_VSP,
+	{REFRESH_60, M1360X768_RB_R60_HSP, M1360X768_RB_R60_VSP,
 	 {1520, 1360, 1360, 160, 1408, 32, 790, 768, 768, 22, 771, 5} }
 };
 
 /* 1366x768 (GTF) */
-struct crt_mode_table CRTM1366x768[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1366x768[] = {
+	/* r_rate,          hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_85_860M, M1368X768_R60_HSP, M1368X768_R60_VSP,
+	{REFRESH_60, M1368X768_R60_HSP, M1368X768_R60_VSP,
 	 {1800, 1368, 1368, 432, 1440, 144, 795, 768, 768, 27, 769, 3} },
-	{REFRESH_50, CLK_69_924M, M1368X768_R50_HSP, M1368X768_R50_VSP,
+	{REFRESH_50, M1368X768_R50_HSP, M1368X768_R50_VSP,
 	 {1768, 1368, 1368, 400, 1424, 144, 791, 768, 768, 23, 769, 3} }
 };
 
 /* 1440x900 (CVT) */
-struct crt_mode_table CRTM1440x900[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1440x900[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_106_500M, M1440X900_R60_HSP, M1440X900_R60_VSP,
+	{REFRESH_60, M1440X900_R60_HSP, M1440X900_R60_VSP,
 	 {1904, 1440, 1440, 464, 1520, 152, 934, 900, 900, 34, 903, 6} },
-	{REFRESH_75, CLK_136_700M, M1440X900_R75_HSP, M1440X900_R75_VSP,
+	{REFRESH_75, M1440X900_R75_HSP, M1440X900_R75_VSP,
 	 {1936, 1440, 1440, 496, 1536, 152, 942, 900, 900, 42, 903, 6} }
 };
 
 /* 1440x900 (CVT Reduce Blanking) */
-struct crt_mode_table CRTM1440x900_RB[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1440x900_RB[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_88_750M, M1440X900_RB_R60_HSP,
-	 M1440X900_RB_R60_VSP,
+	{REFRESH_60, M1440X900_RB_R60_HSP, M1440X900_RB_R60_VSP,
 	 {1600, 1440, 1440, 160, 1488, 32, 926, 900, 900, 26, 903, 6} }
 };
 
 /* 1600x900 (CVT) */
-struct crt_mode_table CRTM1600x900[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1600x900[] = {
+	/* r_rate,          hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_118_840M, M1600X900_R60_HSP, M1600X900_R60_VSP,
+	{REFRESH_60, M1600X900_R60_HSP, M1600X900_R60_VSP,
 	 {2112, 1600, 1600, 512, 1688, 168, 934, 900, 900, 34, 903, 5} }
 };
 
 /* 1600x900 (CVT Reduce Blanking) */
-struct crt_mode_table CRTM1600x900_RB[] = {
-	/* r_rate,        vclk,           hsp,        vsp   */
+static struct crt_mode_table CRTM1600x900_RB[] = {
+	/* r_rate,           hsp,        vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_97_750M, M1600X900_RB_R60_HSP,
-	 M1600X900_RB_R60_VSP,
+	{REFRESH_60, M1600X900_RB_R60_HSP, M1600X900_RB_R60_VSP,
 	 {1760, 1600, 1600, 160, 1648, 32, 926, 900, 900, 26, 903, 5} }
 };
 
 /* 1600x1024 (GTF) */
-struct crt_mode_table CRTM1600x1024[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1600x1024[] = {
+	/* r_rate,          hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_136_700M, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
+	{REFRESH_60, M1600X1024_R60_HSP, M1600X1024_R60_VSP,
 	 {2144, 1600, 1600, 544, 1704, 168, 1060, 1024, 1024, 36, 1025, 3} }
 };
 
 /* 1792x1344 (DMT) */
-struct crt_mode_table CRTM1792x1344[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1792x1344[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_204_000M, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
+	{REFRESH_60, M1792x1344_R60_HSP, M1792x1344_R60_VSP,
 	 {2448, 1792, 1792, 656, 1920, 200, 1394, 1344, 1344, 50, 1345, 3} }
 };
 
 /* 1856x1392 (DMT) */
-struct crt_mode_table CRTM1856x1392[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1856x1392[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_218_500M, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
+	{REFRESH_60, M1856x1392_R60_HSP, M1856x1392_R60_VSP,
 	 {2528, 1856, 1856, 672, 1952, 224, 1439, 1392, 1392, 47, 1393, 3} }
 };
 
 /* 1920x1200 (CVT) */
-struct crt_mode_table CRTM1920x1200[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1920x1200[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_193_295M, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
+	{REFRESH_60, M1920X1200_R60_HSP, M1920X1200_R60_VSP,
 	 {2592, 1920, 1920, 672, 2056, 200, 1245, 1200, 1200, 45, 1203, 6} }
 };
 
 /* 1920x1200 (CVT with Reduce Blanking) */
-struct crt_mode_table CRTM1920x1200_RB[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM1920x1200_RB[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE, HSS, HSE, VT,  VA,  VBS, VBE, VSS, VSE */
-	{REFRESH_60, CLK_153_920M, M1920X1200_RB_R60_HSP,
-	 M1920X1200_RB_R60_VSP,
+	{REFRESH_60, M1920X1200_RB_R60_HSP, M1920X1200_RB_R60_VSP,
 	 {2080, 1920, 1920, 160, 1968, 32, 1235, 1200, 1200, 35, 1203, 6} }
 };
 
 /* 2048x1536 (CVT) */
-struct crt_mode_table CRTM2048x1536[] = {
-	/* r_rate,          vclk,              hsp,             vsp   */
+static struct crt_mode_table CRTM2048x1536[] = {
+	/* r_rate,              hsp,             vsp   */
 	/* HT,  HA,  HBS, HBE,  HSS, HSE,   VT,  VA,  VBS, VBE,  VSS, VSE */
-	{REFRESH_60, CLK_267_250M, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
+	{REFRESH_60, M2048x1536_R60_HSP, M2048x1536_R60_VSP,
 	 {2800, 2048, 2048, 752, 2200, 224, 1592, 1536, 1536, 56, 1539, 4} }
 };
 
-struct VideoModeTable viafb_modes[] = {
+static struct VideoModeTable viafb_modes[] = {
 	/* Display : 480x640 (GTF) */
 	{CRTM480x640, ARRAY_SIZE(CRTM480x640)},
 
@@ -1016,7 +854,7 @@ struct VideoModeTable viafb_modes[] = {
 	{CRTM1400x1050, ARRAY_SIZE(CRTM1400x1050)}
 };
 
-struct VideoModeTable viafb_rb_modes[] = {
+static struct VideoModeTable viafb_rb_modes[] = {
 	/* Display : 1360x768 (CVT Reduce Blanking) */
 	{CRTM1360x768_RB, ARRAY_SIZE(CRTM1360x768_RB)},
 
@@ -1040,14 +878,12 @@ struct VideoModeTable viafb_rb_modes[] = {
 };
 
 struct crt_mode_table CEAM1280x720[] = {
-	{REFRESH_60, CLK_74_270M, M1280X720_CEA_R60_HSP,
-	 M1280X720_CEA_R60_VSP,
+	{REFRESH_60, M1280X720_CEA_R60_HSP, M1280X720_CEA_R60_VSP,
 	 /* HT,    HA,   HBS,  HBE,  HSS, HSE,  VT,   VA,  VBS, VBE, VSS, VSE */
 	 {1650, 1280, 1280, 370, 1390, 40, 750, 720, 720, 30, 725, 5} }
 };
 struct crt_mode_table CEAM1920x1080[] = {
-	{REFRESH_60, CLK_148_500M, M1920X1080_CEA_R60_HSP,
-	 M1920X1080_CEA_R60_VSP,
+	{REFRESH_60, M1920X1080_CEA_R60_HSP, M1920X1080_CEA_R60_VSP,
 	 /* HT,    HA,   HBS,  HBE,  HSS, HSE,  VT,  VA, VBS, VBE,  VSS, VSE */
 	 {2200, 1920, 1920, 300, 2008, 44, 1125, 1080, 1080, 45, 1084, 5} }
 };
@@ -1057,7 +893,6 @@ struct VideoModeTable CEA_HDMI_Modes[] = {
 	{CEAM1920x1080, ARRAY_SIZE(CEAM1920x1080)}
 };
 
-int NUM_TOTAL_RES_MAP_REFRESH = ARRAY_SIZE(res_map_refresh_tbl);
 int NUM_TOTAL_CEA_MODES = ARRAY_SIZE(CEA_HDMI_Modes);
 int NUM_TOTAL_CN400_ModeXregs = ARRAY_SIZE(CN400_ModeXregs);
 int NUM_TOTAL_CN700_ModeXregs = ARRAY_SIZE(CN700_ModeXregs);
diff --git a/drivers/video/via/viamode.h b/drivers/video/via/viamode.h
index 5b1ced8..8a67ea1 100644
--- a/drivers/video/via/viamode.h
+++ b/drivers/video/via/viamode.h
@@ -41,14 +41,6 @@ struct patch_table {
 	struct io_reg *io_reg_table;
 };
 
-struct res_map_refresh {
-	int hres;
-	int vres;
-	int pixclock;
-	int vmode_refresh;
-};
-
-extern int NUM_TOTAL_RES_MAP_REFRESH;
 extern int NUM_TOTAL_CEA_MODES;
 extern int NUM_TOTAL_CN400_ModeXregs;
 extern int NUM_TOTAL_CN700_ModeXregs;
@@ -66,7 +58,6 @@ extern struct crt_mode_table CEAM1280x720[];
 extern struct crt_mode_table CEAM1920x1080[];
 extern struct VideoModeTable CEA_HDMI_Modes[];
 
-extern struct res_map_refresh res_map_refresh_tbl[];
 extern struct io_reg CN400_ModeXregs[];
 extern struct io_reg CN700_ModeXregs[];
 extern struct io_reg KM400_ModeXregs[];
diff --git a/drivers/video/via/vt1636.c b/drivers/video/via/vt1636.c
index 60e4192..ee2903b 100644
--- a/drivers/video/via/vt1636.c
+++ b/drivers/video/via/vt1636.c
@@ -167,22 +167,6 @@ static int get_clk_range_index(u32 Clk)
 		return DPA_CLK_RANGE_150M;
 }
 
-static int get_lvds_dpa_setting_index(int panel_size_id,
-			     struct VT1636_DPA_SETTING *p_vt1636_dpasetting_tbl,
-			       int tbl_size)
-{
-	int i;
-
-	for (i = 0; i < tbl_size; i++) {
-		if (panel_size_id == p_vt1636_dpasetting_tbl->PanelSizeID)
-			return i;
-
-		p_vt1636_dpasetting_tbl++;
-	}
-
-	return 0;
-}
-
 static void set_dpa_vt1636(struct lvds_setting_information
 	*plvds_setting_info, struct lvds_chip_information *plvds_chip_info,
 		    struct VT1636_DPA_SETTING *p_vt1636_dpa_setting)
@@ -206,7 +190,9 @@ void viafb_vt1636_patch_skew_on_vt3324(
 	struct lvds_setting_information *plvds_setting_info,
 	struct lvds_chip_information *plvds_chip_info)
 {
-	int index, size;
+	struct VT1636_DPA_SETTING dpa = {0x00, 0x00}, dpa_16x12 = {0x0B, 0x03},
+		*pdpa;
+	int index;
 
 	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3324.\n");
 
@@ -216,19 +202,21 @@ void viafb_vt1636_patch_skew_on_vt3324(
 		    &GFX_DPA_SETTING_TBL_VT3324[index]);
 
 	/* LVDS Transmitter DPA settings: */
-	size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3324);
-	index =
-	    get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
-				       VT1636_DPA_SETTING_TBL_VT3324, size);
-	set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
-		       &VT1636_DPA_SETTING_TBL_VT3324[index]);
+	if (plvds_setting_info->lcd_panel_hres == 1600 &&
+		plvds_setting_info->lcd_panel_vres == 1200)
+		pdpa = &dpa_16x12;
+	else
+		pdpa = &dpa;
+
+	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, pdpa);
 }
 
 void viafb_vt1636_patch_skew_on_vt3327(
 	struct lvds_setting_information *plvds_setting_info,
 	struct lvds_chip_information *plvds_chip_info)
 {
-	int index, size;
+	struct VT1636_DPA_SETTING dpa = {0x00, 0x00};
+	int index;
 
 	DEBUG_MSG(KERN_INFO "viafb_vt1636_patch_skew_on_vt3327.\n");
 
@@ -238,12 +226,7 @@ void viafb_vt1636_patch_skew_on_vt3327(
 		    &GFX_DPA_SETTING_TBL_VT3327[index]);
 
 	/* LVDS Transmitter DPA settings: */
-	size = ARRAY_SIZE(VT1636_DPA_SETTING_TBL_VT3327);
-	index =
-	    get_lvds_dpa_setting_index(plvds_setting_info->lcd_panel_id,
-				       VT1636_DPA_SETTING_TBL_VT3327, size);
-	set_dpa_vt1636(plvds_setting_info, plvds_chip_info,
-		       &VT1636_DPA_SETTING_TBL_VT3327[index]);
+	set_dpa_vt1636(plvds_setting_info, plvds_chip_info, &dpa);
 }
 
 void viafb_vt1636_patch_skew_on_vt3364(
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index 68bd234..77dea01 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -404,8 +404,7 @@ static int xilinxfb_release(struct device *dev)
  * OF bus binding
  */
 
-static int __devinit
-xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit xilinxfb_of_probe(struct platform_device *op)
 {
 	const u32 *prop;
 	u32 *p;
@@ -418,8 +417,6 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
 	/* Copy with the default pdata (not a ptr reference!) */
 	pdata = xilinx_fb_default_pdata;
 
-	dev_dbg(&op->dev, "xilinxfb_of_probe(%p, %p)\n", op, match);
-
 	/* Allocate the driver data region */
 	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata) {
@@ -505,7 +502,7 @@ static struct of_device_id xilinxfb_of_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, xilinxfb_of_match);
 
-static struct of_platform_driver xilinxfb_of_driver = {
+static struct platform_driver xilinxfb_of_driver = {
 	.probe = xilinxfb_of_probe,
 	.remove = __devexit_p(xilinxfb_of_remove),
 	.driver = {
@@ -523,13 +520,13 @@ static struct of_platform_driver xilinxfb_of_driver = {
 static int __init
 xilinxfb_init(void)
 {
-	return of_register_platform_driver(&xilinxfb_of_driver);
+	return platform_driver_register(&xilinxfb_of_driver);
 }
 
 static void __exit
 xilinxfb_cleanup(void)
 {
-	of_unregister_platform_driver(&xilinxfb_of_driver);
+	platform_driver_unregister(&xilinxfb_of_driver);
 }
 
 module_init(xilinxfb_init);
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 80b3b12..7c608c5 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -60,7 +60,7 @@ config W1_MASTER_GPIO
 
 config HDQ_MASTER_OMAP
 	tristate "OMAP HDQ driver"
-	depends on ARCH_OMAP2430 || ARCH_OMAP3
+	depends on SOC_OMAP2430 || ARCH_OMAP3
 	help
 	  Say Y here if you want support for the 1-wire or HDQ Interface
 	  on an OMAP processor.
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 31649b7..b69d714 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -533,6 +533,16 @@ config I6300ESB_WDT
 	  To compile this driver as a module, choose M here: the
 	  module will be called i6300esb.
 
+config INTEL_SCU_WATCHDOG
+	bool "Intel SCU Watchdog for Mobile Platforms"
+	depends on WATCHDOG
+	depends on INTEL_SCU_IPC
+	---help---
+	  Hardware driver for the watchdog time built into the Intel SCU
+	  for Intel Mobile Platforms.
+
+	  To compile this driver as a module, choose M here.
+
 config ITCO_WDT
 	tristate "Intel TCO Timer/Watchdog"
 	depends on (X86 || IA64) && PCI
@@ -580,7 +590,7 @@ config IT87_WDT
 	depends on X86 && EXPERIMENTAL
 	---help---
 	  This is the driver for the hardware watchdog on the ITE IT8702,
-	  IT8712, IT8716, IT8718, IT8720, IT8726, IT8712 Super I/O chips.
+	  IT8712, IT8716, IT8718, IT8720, IT8721, IT8726 Super I/O chips.
 	  This watchdog simply watches your kernel to make sure it doesn't
 	  freeze, and if it does, it reboots your computer after a certain
 	  amount of time.
@@ -589,18 +599,20 @@ config IT87_WDT
 	  be called it87_wdt.
 
 config HP_WATCHDOG
-	tristate "HP Proliant iLO2+ Hardware Watchdog Timer"
+	tristate "HP ProLiant iLO2+ Hardware Watchdog Timer"
 	depends on X86
+	default m
 	help
 	  A software monitoring watchdog and NMI sourcing driver. This driver
 	  will detect lockups and provide a stack trace. This is a driver that
-	  will only load on a HP ProLiant system with a minimum of iLO2 support.
+	  will only load on an HP ProLiant system with a minimum of iLO2 support.
 	  To compile this driver as a module, choose M here: the module will be
 	  called hpwdt.
 
 config HPWDT_NMI_DECODING
 	bool "NMI decoding support for the HP ProLiant iLO2+ Hardware Watchdog Timer"
 	depends on HP_WATCHDOG
+	default y
 	help
 	  When an NMI occurs this feature will make the necessary BIOS calls to
 	  log the cause of the NMI.
@@ -903,6 +915,12 @@ config INDYDOG
 	  timer expired and no process has written to /dev/watchdog during
 	  that time.
 
+config JZ4740_WDT
+	tristate "Ingenic jz4740 SoC hardware watchdog"
+	depends on MACH_JZ4740
+	help
+	  Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs.
+
 config WDT_MTX1
 	tristate "MTX-1 Hardware Watchdog"
 	depends on MIPS_MTX1
@@ -1083,14 +1101,6 @@ config SH_WDT
 	  To compile this driver as a module, choose M here: the
 	  module will be called shwdt.
 
-config SH_WDT_MMAP
-	bool "Allow mmap of SH WDT"
-	default n
-	depends on SH_WDT
-	help
-	  If you say Y here, user applications will be able to mmap the
-	  WDT/CPG registers.
-
 # SPARC Architecture
 
 # SPARC64 Architecture
@@ -1119,6 +1129,16 @@ config WATCHDOG_RIO
 
 # XTENSA Architecture
 
+# Xen Architecture
+
+config XEN_WDT
+	tristate "Xen Watchdog support"
+	depends on XEN
+	help
+	  Say Y here to support the hypervisor watchdog capability provided
+	  by Xen 4.0 and newer.  The watchdog timeout period is normally one
+	  minute but can be changed with a boot-time parameter.
+
 #
 # ISA-based Watchdog Cards
 #
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 20e44c4..d520bf9 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -102,6 +102,7 @@ obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
 obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
 obj-$(CONFIG_MACHZ_WDT) += machzwd.o
 obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o
+obj-$(CONFIG_INTEL_SCU_WATCHDOG) += intel_scu_watchdog.o
 
 # M32R Architecture
 
@@ -114,6 +115,7 @@ obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
 obj-$(CONFIG_BCM63XX_WDT) += bcm63xx_wdt.o
 obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o
 obj-$(CONFIG_INDYDOG) += indydog.o
+obj-$(CONFIG_JZ4740_WDT) += jz4740_wdt.o
 obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o
 obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o
 obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
@@ -148,6 +150,9 @@ obj-$(CONFIG_WATCHDOG_CP1XXX)		+= cpwd.o
 
 # XTENSA Architecture
 
+# Xen
+obj-$(CONFIG_XEN_WDT) += xen_wdt.o
+
 # Architecture Independant
 obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
 obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index fa4d360..f16dcbd 100644
--- a/drivers/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -301,7 +301,7 @@ static int ali_notify_sys(struct notifier_block *this,
  *	want to register another driver on the same PCI id.
  */
 
-static struct pci_device_id ali_pci_tbl[] __used = {
+static DEFINE_PCI_DEVICE_TABLE(ali_pci_tbl) __used = {
 	{ PCI_VENDOR_ID_AL, 0x1533, PCI_ANY_ID, PCI_ANY_ID,},
 	{ PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
 	{ 0, },
@@ -362,12 +362,12 @@ static int __init ali_find_watchdog(void)
  */
 
 static const struct file_operations ali_fops = {
-	.owner 		=	THIS_MODULE,
-	.llseek 	=	no_llseek,
+	.owner		=	THIS_MODULE,
+	.llseek		=	no_llseek,
 	.write		=	ali_write,
 	.unlocked_ioctl =	ali_ioctl,
-	.open 		=	ali_open,
-	.release 	=	ali_release,
+	.open		=	ali_open,
+	.release	=	ali_release,
 };
 
 static struct miscdevice ali_miscdev = {
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index 4b7a2b4..46f4b85 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -430,7 +430,7 @@ err_out:
 module_init(alim7101_wdt_init);
 module_exit(alim7101_wdt_unload);
 
-static struct pci_device_id alim7101_pci_tbl[] __devinitdata __used = {
+static DEFINE_PCI_DEVICE_TABLE(alim7101_pci_tbl) __used = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 	{ }
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index 5f24552..bd44417 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -150,8 +150,8 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
 }
 
 static const struct watchdog_info bcm47xx_wdt_info = {
-	.identity 	= DRV_NAME,
-	.options 	= WDIOF_SETTIMEOUT |
+	.identity	= DRV_NAME,
+	.options	= WDIOF_SETTIMEOUT |
 				WDIOF_KEEPALIVEPING |
 				WDIOF_MAGICCLOSE,
 };
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 9042a95..b9fa9b7 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -63,7 +63,7 @@ static DEFINE_SPINLOCK(bfin_wdt_spinlock);
 /**
  *	bfin_wdt_keepalive - Keep the Userspace Watchdog Alive
  *
- * 	The Userspace watchdog got a KeepAlive: schedule the next timeout.
+ *	The Userspace watchdog got a KeepAlive: schedule the next timeout.
  */
 static int bfin_wdt_keepalive(void)
 {
@@ -337,7 +337,7 @@ static int bfin_wdt_resume(struct platform_device *pdev)
 static const struct file_operations bfin_wdt_fops = {
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
-	.write    	= bfin_wdt_write,
+	.write		= bfin_wdt_write,
 	.unlocked_ioctl	= bfin_wdt_ioctl,
 	.open		= bfin_wdt_open,
 	.release	= bfin_wdt_release,
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index 7e7ec9c..337265b 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -4,7 +4,7 @@
  * Author: Matthew McClintock
  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
  *
- * Copyright 2005, 2008, 2010 Freescale Semiconductor Inc.
+ * Copyright 2005, 2008, 2010-2011 Freescale Semiconductor Inc.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -221,9 +221,8 @@ static int booke_wdt_open(struct inode *inode, struct file *file)
 	if (booke_wdt_enabled == 0) {
 		booke_wdt_enabled = 1;
 		on_each_cpu(__booke_wdt_enable, NULL, 0);
-		printk(KERN_INFO
-		      "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
-				booke_wdt_period);
+		pr_debug("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
+			period_to_sec(booke_wdt_period));
 	}
 	spin_unlock(&booke_wdt_lock);
 
@@ -240,6 +239,7 @@ static int booke_wdt_release(struct inode *inode, struct file *file)
 	 */
 	on_each_cpu(__booke_wdt_disable, NULL, 0);
 	booke_wdt_enabled = 0;
+	pr_debug("booke_wdt: watchdog disabled\n");
 #endif
 
 	clear_bit(0, &wdt_is_active);
@@ -271,21 +271,20 @@ static int __init booke_wdt_init(void)
 {
 	int ret = 0;
 
-	printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n");
+	pr_info("booke_wdt: powerpc book-e watchdog driver loaded\n");
 	ident.firmware_version = cur_cpu_spec->pvr_value;
 
 	ret = misc_register(&booke_wdt_miscdev);
 	if (ret) {
-		printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n",
-				WATCHDOG_MINOR, ret);
+		pr_err("booke_wdt: cannot register device (minor=%u, ret=%i)\n",
+		       WATCHDOG_MINOR, ret);
 		return ret;
 	}
 
 	spin_lock(&booke_wdt_lock);
 	if (booke_wdt_enabled == 1) {
-		printk(KERN_INFO
-		      "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n",
-				booke_wdt_period);
+		pr_info("booke_wdt: watchdog enabled (timeout = %llu sec)\n",
+			period_to_sec(booke_wdt_period));
 		on_each_cpu(__booke_wdt_enable, NULL, 0);
 	}
 	spin_unlock(&booke_wdt_lock);
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 3de4ba0..1e013e8 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -5,10 +5,10 @@
  * interface and Solaris-compatible ioctls as best it is
  * able.
  *
- * NOTE: 	CP1400 systems appear to have a defective intr_mask
- * 			register on the PLD, preventing the disabling of
- * 			timer interrupts.  We use a timer to periodically
- * 			reset 'stopped' watchdogs on affected platforms.
+ * NOTE:	CP1400 systems appear to have a defective intr_mask
+ *			register on the PLD, preventing the disabling of
+ *			timer interrupts.  We use a timer to periodically
+ *			reset 'stopped' watchdogs on affected platforms.
  *
  * Copyright (c) 2000 Eric Brower (ebrower@usa.net)
  * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
@@ -107,13 +107,13 @@ static struct cpwd *cpwd_device;
  * -------------------
  * |-  counter val  -|
  * -------------------
- * dcntr - 	Current 16-bit downcounter value.
- * 			When downcounter reaches '0' watchdog expires.
- * 			Reading this register resets downcounter with
- * 			'limit' value.
- * limit - 	16-bit countdown value in 1/10th second increments.
- * 			Writing this register begins countdown with input value.
- * 			Reading from this register does not affect counter.
+ * dcntr -	Current 16-bit downcounter value.
+ *			When downcounter reaches '0' watchdog expires.
+ *			Reading this register resets downcounter with
+ *			'limit' value.
+ * limit -	16-bit countdown value in 1/10th second increments.
+ *			Writing this register begins countdown with input value.
+ *			Reading from this register does not affect counter.
  * NOTES:	After watchdog reset, dcntr and limit contain '1'
  *
  * status register (byte access):
@@ -123,7 +123,7 @@ static struct cpwd *cpwd_device;
  * |-   UNUSED  -| EXP | RUN |
  * ---------------------------
  * status-	Bit 0 - Watchdog is running
- * 			Bit 1 - Watchdog has expired
+ *			Bit 1 - Watchdog has expired
  *
  *** PLD register block definition (struct wd_pld_regblk)
  *
@@ -197,7 +197,7 @@ static u8 cpwd_readb(void __iomem *addr)
  * Because of the CP1400 defect this should only be
  * called during initialzation or by wd_[start|stop]timer()
  *
- * index 	- sub-device index, or -1 for 'all'
+ * index	- sub-device index, or -1 for 'all'
  * enable	- non-zero to enable interrupts, zero to disable
  */
 static void cpwd_toggleintr(struct cpwd *p, int index, int enable)
@@ -317,13 +317,13 @@ static int cpwd_getstatus(struct cpwd *p, int index)
 		} else {
 			/* Fudge WD_EXPIRED status for defective CP1400--
 			 * IF timer is running
-			 * 	AND brokenstop is set
-			 * 	AND an interrupt has been serviced
+			 *	AND brokenstop is set
+			 *	AND an interrupt has been serviced
 			 * we are WD_EXPIRED.
 			 *
 			 * IF timer is running
-			 * 	AND brokenstop is set
-			 * 	AND no interrupt has been serviced
+			 *	AND brokenstop is set
+			 *	AND no interrupt has been serviced
 			 * we are WD_FREERUN.
 			 */
 			if (p->broken &&
@@ -528,8 +528,7 @@ static const struct file_operations cpwd_fops = {
 	.llseek =		no_llseek,
 };
 
-static int __devinit cpwd_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit cpwd_probe(struct platform_device *op)
 {
 	struct device_node *options;
 	const char *str_prop;
@@ -614,7 +613,7 @@ static int __devinit cpwd_probe(struct platform_device *op,
 
 	if (p->broken) {
 		init_timer(&cpwd_timer);
-		cpwd_timer.function 	= cpwd_brokentimer;
+		cpwd_timer.function	= cpwd_brokentimer;
 		cpwd_timer.data		= (unsigned long) p;
 		cpwd_timer.expires	= WD_BTIMEOUT;
 
@@ -678,7 +677,7 @@ static const struct of_device_id cpwd_match[] = {
 };
 MODULE_DEVICE_TABLE(of, cpwd_match);
 
-static struct of_platform_driver cpwd_driver = {
+static struct platform_driver cpwd_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -690,12 +689,12 @@ static struct of_platform_driver cpwd_driver = {
 
 static int __init cpwd_init(void)
 {
-	return of_register_platform_driver(&cpwd_driver);
+	return platform_driver_register(&cpwd_driver);
 }
 
 static void __exit cpwd_exit(void)
 {
-	of_unregister_platform_driver(&cpwd_driver);
+	platform_driver_unregister(&cpwd_driver);
 }
 
 module_init(cpwd_init);
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
index 3f3dc09..f1d1da6 100644
--- a/drivers/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
@@ -201,7 +201,7 @@ static void eurwdt_ping(void)
 static ssize_t eurwdt_write(struct file *file, const char __user *buf,
 size_t count, loff_t *ppos)
 {
-	if (count) 	{
+	if (count) {
 		if (!nowayout) {
 			size_t i;
 
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index f6bd6f1..29a7cd4 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -261,8 +261,7 @@ static struct miscdevice gef_wdt_miscdev = {
 };
 
 
-static int __devinit gef_wdt_probe(struct platform_device *dev,
-	const struct of_device_id *match)
+static int __devinit gef_wdt_probe(struct platform_device *dev)
 {
 	int timeout = 10;
 	u32 freq;
@@ -303,7 +302,7 @@ static const struct of_device_id gef_wdt_ids[] = {
 	{},
 };
 
-static struct of_platform_driver gef_wdt_driver = {
+static struct platform_driver gef_wdt_driver = {
 	.driver = {
 		.name = "gef_wdt",
 		.owner = THIS_MODULE,
@@ -315,12 +314,12 @@ static struct of_platform_driver gef_wdt_driver = {
 static int __init gef_wdt_init(void)
 {
 	printk(KERN_INFO "GE watchdog driver\n");
-	return of_register_platform_driver(&gef_wdt_driver);
+	return platform_driver_register(&gef_wdt_driver);
 }
 
 static void __exit gef_wdt_exit(void)
 {
-	of_unregister_platform_driver(&gef_wdt_driver);
+	platform_driver_unregister(&gef_wdt_driver);
 }
 
 module_init(gef_wdt_init);
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 204a560..8cb2685 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -52,7 +52,7 @@ static void __iomem *pci_mem_addr;		/* the PCI-memory address */
 static unsigned long __iomem *hpwdt_timer_reg;
 static unsigned long __iomem *hpwdt_timer_con;
 
-static struct pci_device_id hpwdt_devices[] = {
+static DEFINE_PCI_DEVICE_TABLE(hpwdt_devices) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xB203) },	/* iLO2 */
 	{ PCI_DEVICE(PCI_VENDOR_ID_HP, 0x3306) },	/* iLO3 */
 	{0},			/* terminate list */
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index bb9750a..db45091 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -334,7 +334,7 @@ static struct miscdevice esb_miscdev = {
 /*
  * Data for PCI driver interface
  */
-static struct pci_device_id esb_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(esb_pci_tbl) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
 	{ 0, },                 /* End of list */
 };
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 2c6c2b4..35a0d12 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -247,7 +247,7 @@ static struct {
 	{NULL, 0}
 };
 
-#define ITCO_PCI_DEVICE(dev, data) 	\
+#define ITCO_PCI_DEVICE(dev, data) \
 	.vendor = PCI_VENDOR_ID_INTEL,	\
 	.device = dev,			\
 	.subvendor = PCI_ANY_ID,	\
@@ -262,7 +262,7 @@ static struct {
  * pci_driver, because the I/O Controller Hub has also other
  * functions that probably will be registered by other drivers.
  */
-static struct pci_device_id iTCO_wdt_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0,	TCO_ICH)},
 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0,	TCO_ICH0)},
 	{ ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0,	TCO_ICH2)},
diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c
new file mode 100644
index 0000000..919bdd1
--- /dev/null
+++ b/drivers/watchdog/intel_scu_watchdog.c
@@ -0,0 +1,572 @@
+/*
+ *      Intel_SCU 0.2:  An Intel SCU IOH Based Watchdog Device
+ *			for Intel part #(s):
+ *				- AF82MP20 PCH
+ *
+ *      Copyright (C) 2009-2010 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., 59 Temple Place - Suite 330,
+ *      Boston, MA  02111-1307, USA.
+ *      The full GNU General Public License is included in this
+ *      distribution in the file called COPYING.
+ *
+ */
+
+#include <linux/compiler.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/fs.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sfi.h>
+#include <linux/types.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/intel_scu_ipc.h>
+#include <asm/apb_timer.h>
+#include <asm/mrst.h>
+
+#include "intel_scu_watchdog.h"
+
+/* Bounds number of times we will retry loading time count */
+/* This retry is a work around for a silicon bug.	   */
+#define MAX_RETRY 16
+
+#define IPC_SET_WATCHDOG_TIMER	0xF8
+
+static int timer_margin = DEFAULT_SOFT_TO_HARD_MARGIN;
+module_param(timer_margin, int, 0);
+MODULE_PARM_DESC(timer_margin,
+		"Watchdog timer margin"
+		"Time between interrupt and resetting the system"
+		"The range is from 1 to 160"
+		"This is the time for all keep alives to arrive");
+
+static int timer_set = DEFAULT_TIME;
+module_param(timer_set, int, 0);
+MODULE_PARM_DESC(timer_set,
+		"Default Watchdog timer setting"
+		"Complete cycle time"
+		"The range is from 1 to 170"
+		"This is the time for all keep alives to arrive");
+
+/* After watchdog device is closed, check force_boot. If:
+ * force_boot == 0, then force boot on next watchdog interrupt after close,
+ * force_boot == 1, then force boot immediately when device is closed.
+ */
+static int force_boot;
+module_param(force_boot, int, 0);
+MODULE_PARM_DESC(force_boot,
+		"A value of 1 means that the driver will reboot"
+		"the system immediately if the /dev/watchdog device is closed"
+		"A value of 0 means that when /dev/watchdog device is closed"
+		"the watchdog timer will be refreshed for one more interval"
+		"of length: timer_set. At the end of this interval, the"
+		"watchdog timer will reset the system."
+		);
+
+/* there is only one device in the system now; this can be made into
+ * an array in the future if we have more than one device */
+
+static struct intel_scu_watchdog_dev watchdog_device;
+
+/* Forces restart, if force_reboot is set */
+static void watchdog_fire(void)
+{
+	if (force_boot) {
+		printk(KERN_CRIT PFX "Initiating system reboot.\n");
+		emergency_restart();
+		printk(KERN_CRIT PFX "Reboot didn't ?????\n");
+	}
+
+	else {
+		printk(KERN_CRIT PFX "Immediate Reboot Disabled\n");
+		printk(KERN_CRIT PFX
+			"System will reset when watchdog timer times out!\n");
+	}
+}
+
+static int check_timer_margin(int new_margin)
+{
+	if ((new_margin < MIN_TIME_CYCLE) ||
+	    (new_margin > MAX_TIME - timer_set)) {
+		pr_debug("Watchdog timer: value of new_margin %d is out of the range %d to %d\n",
+			  new_margin, MIN_TIME_CYCLE, MAX_TIME - timer_set);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * IPC operations
+ */
+static int watchdog_set_ipc(int soft_threshold, int threshold)
+{
+	u32	*ipc_wbuf;
+	u8	 cbuf[16] = { '\0' };
+	int	 ipc_ret = 0;
+
+	ipc_wbuf = (u32 *)&cbuf;
+	ipc_wbuf[0] = soft_threshold;
+	ipc_wbuf[1] = threshold;
+
+	ipc_ret = intel_scu_ipc_command(
+			IPC_SET_WATCHDOG_TIMER,
+			0,
+			ipc_wbuf,
+			2,
+			NULL,
+			0);
+
+	if (ipc_ret != 0)
+		pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret);
+
+	return ipc_ret;
+};
+
+/*
+ *      Intel_SCU operations
+ */
+
+/* timer interrupt handler */
+static irqreturn_t watchdog_timer_interrupt(int irq, void *dev_id)
+{
+	int int_status;
+	int_status = ioread32(watchdog_device.timer_interrupt_status_addr);
+
+	pr_debug("Watchdog timer: irq, int_status: %x\n", int_status);
+
+	if (int_status != 0)
+		return IRQ_NONE;
+
+	/* has the timer been started? If not, then this is spurious */
+	if (watchdog_device.timer_started == 0) {
+		pr_debug("Watchdog timer: spurious interrupt received\n");
+		return IRQ_HANDLED;
+	}
+
+	/* temporarily disable the timer */
+	iowrite32(0x00000002, watchdog_device.timer_control_addr);
+
+	/* set the timer to the threshold */
+	iowrite32(watchdog_device.threshold,
+		  watchdog_device.timer_load_count_addr);
+
+	/* allow the timer to run */
+	iowrite32(0x00000003, watchdog_device.timer_control_addr);
+
+	return IRQ_HANDLED;
+}
+
+static int intel_scu_keepalive(void)
+{
+
+	/* read eoi register - clears interrupt */
+	ioread32(watchdog_device.timer_clear_interrupt_addr);
+
+	/* temporarily disable the timer */
+	iowrite32(0x00000002, watchdog_device.timer_control_addr);
+
+	/* set the timer to the soft_threshold */
+	iowrite32(watchdog_device.soft_threshold,
+		  watchdog_device.timer_load_count_addr);
+
+	/* allow the timer to run */
+	iowrite32(0x00000003, watchdog_device.timer_control_addr);
+
+	return 0;
+}
+
+static int intel_scu_stop(void)
+{
+	iowrite32(0, watchdog_device.timer_control_addr);
+	return 0;
+}
+
+static int intel_scu_set_heartbeat(u32 t)
+{
+	int			 ipc_ret;
+	int			 retry_count;
+	u32			 soft_value;
+	u32			 hw_pre_value;
+	u32			 hw_value;
+
+	watchdog_device.timer_set = t;
+	watchdog_device.threshold =
+		timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
+	watchdog_device.soft_threshold =
+		(watchdog_device.timer_set - timer_margin)
+		* watchdog_device.timer_tbl_ptr->freq_hz;
+
+	pr_debug("Watchdog timer: set_heartbeat: timer freq is %d\n",
+		watchdog_device.timer_tbl_ptr->freq_hz);
+	pr_debug("Watchdog timer: set_heartbeat: timer_set is %x (hex)\n",
+		watchdog_device.timer_set);
+	pr_debug("Watchdog timer: set_hearbeat: timer_margin is %x (hex)\n",
+		timer_margin);
+	pr_debug("Watchdog timer: set_heartbeat: threshold is %x (hex)\n",
+		watchdog_device.threshold);
+	pr_debug("Watchdog timer: set_heartbeat: soft_threshold is %x (hex)\n",
+		watchdog_device.soft_threshold);
+
+	/* Adjust thresholds by FREQ_ADJUSTMENT factor, to make the */
+	/* watchdog timing come out right. */
+	watchdog_device.threshold =
+		watchdog_device.threshold / FREQ_ADJUSTMENT;
+	watchdog_device.soft_threshold =
+		watchdog_device.soft_threshold / FREQ_ADJUSTMENT;
+
+	/* temporarily disable the timer */
+	iowrite32(0x00000002, watchdog_device.timer_control_addr);
+
+	/* send the threshold and soft_threshold via IPC to the processor */
+	ipc_ret = watchdog_set_ipc(watchdog_device.soft_threshold,
+				   watchdog_device.threshold);
+
+	if (ipc_ret != 0) {
+		/* Make sure the watchdog timer is stopped */
+		intel_scu_stop();
+		return ipc_ret;
+	}
+
+	/* Soft Threshold set loop. Early versions of silicon did */
+	/* not always set this count correctly.  This loop checks */
+	/* the value and retries if it was not set correctly.     */
+
+	retry_count = 0;
+	soft_value = watchdog_device.soft_threshold & 0xFFFF0000;
+	do {
+
+		/* Make sure timer is stopped */
+		intel_scu_stop();
+
+		if (MAX_RETRY < retry_count++) {
+			/* Unable to set timer value */
+			pr_err("Watchdog timer: Unable to set timer\n");
+			return -ENODEV;
+		}
+
+		/* set the timer to the soft threshold */
+		iowrite32(watchdog_device.soft_threshold,
+			watchdog_device.timer_load_count_addr);
+
+		/* read count value before starting timer */
+		hw_pre_value = ioread32(watchdog_device.timer_load_count_addr);
+		hw_pre_value = hw_pre_value & 0xFFFF0000;
+
+		/* Start the timer */
+		iowrite32(0x00000003, watchdog_device.timer_control_addr);
+
+		/* read the value the time loaded into its count reg */
+		hw_value = ioread32(watchdog_device.timer_load_count_addr);
+		hw_value = hw_value & 0xFFFF0000;
+
+
+	} while (soft_value != hw_value);
+
+	watchdog_device.timer_started = 1;
+
+	return 0;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int intel_scu_open(struct inode *inode, struct file *file)
+{
+
+	/* Set flag to indicate that watchdog device is open */
+	if (test_and_set_bit(0, &watchdog_device.driver_open))
+		return -EBUSY;
+
+	/* Check for reopen of driver. Reopens are not allowed */
+	if (watchdog_device.driver_closed)
+		return -EPERM;
+
+	return nonseekable_open(inode, file);
+}
+
+static int intel_scu_release(struct inode *inode, struct file *file)
+{
+	/*
+	 * This watchdog should not be closed, after the timer
+	 * is started with the WDIPC_SETTIMEOUT ioctl
+	 * If force_boot is set watchdog_fire() will cause an
+	 * immediate reset. If force_boot is not set, the watchdog
+	 * timer is refreshed for one more interval. At the end
+	 * of that interval, the watchdog timer will reset the system.
+	 */
+
+	if (!test_and_clear_bit(0, &watchdog_device.driver_open)) {
+		pr_debug("Watchdog timer: intel_scu_release, without open\n");
+		return -ENOTTY;
+	}
+
+	if (!watchdog_device.timer_started) {
+		/* Just close, since timer has not been started */
+		pr_debug("Watchdog timer: closed, without starting timer\n");
+		return 0;
+	}
+
+	printk(KERN_CRIT PFX
+	       "Unexpected close of /dev/watchdog!\n");
+
+	/* Since the timer was started, prevent future reopens */
+	watchdog_device.driver_closed = 1;
+
+	/* Refresh the timer for one more interval */
+	intel_scu_keepalive();
+
+	/* Reboot system (if force_boot is set) */
+	watchdog_fire();
+
+	/* We should only reach this point if force_boot is not set */
+	return 0;
+}
+
+static ssize_t intel_scu_write(struct file *file,
+			      char const *data,
+			      size_t len,
+			      loff_t *ppos)
+{
+
+	if (watchdog_device.timer_started)
+		/* Watchdog already started, keep it alive */
+		intel_scu_keepalive();
+	else
+		/* Start watchdog with timer value set by init */
+		intel_scu_set_heartbeat(watchdog_device.timer_set);
+
+	return len;
+}
+
+static long intel_scu_ioctl(struct file *file,
+			   unsigned int cmd,
+			   unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	u32 __user *p = argp;
+	u32 new_margin;
+
+
+	static const struct watchdog_info ident = {
+		.options =          WDIOF_SETTIMEOUT
+				    | WDIOF_KEEPALIVEPING,
+		.firmware_version = 0,  /* @todo Get from SCU via
+						 ipc_get_scu_fw_version()? */
+		.identity =         "Intel_SCU IOH Watchdog"  /* len < 32 */
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		return copy_to_user(argp,
+				    &ident,
+				    sizeof(ident)) ? -EFAULT : 0;
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, p);
+	case WDIOC_KEEPALIVE:
+		intel_scu_keepalive();
+
+		return 0;
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_margin, p))
+			return -EFAULT;
+
+		if (check_timer_margin(new_margin))
+			return -EINVAL;
+
+		if (intel_scu_set_heartbeat(new_margin))
+			return -EINVAL;
+		return 0;
+	case WDIOC_GETTIMEOUT:
+		return put_user(watchdog_device.soft_threshold, p);
+
+	default:
+		return -ENOTTY;
+	}
+}
+
+/*
+ *      Notifier for system down
+ */
+static int intel_scu_notify_sys(struct notifier_block *this,
+			       unsigned long code,
+			       void *another_unused)
+{
+	if (code == SYS_DOWN || code == SYS_HALT)
+		/* Turn off the watchdog timer. */
+		intel_scu_stop();
+	return NOTIFY_DONE;
+}
+
+/*
+ *      Kernel Interfaces
+ */
+static const struct file_operations intel_scu_fops = {
+	.owner          = THIS_MODULE,
+	.llseek         = no_llseek,
+	.write          = intel_scu_write,
+	.unlocked_ioctl = intel_scu_ioctl,
+	.open           = intel_scu_open,
+	.release        = intel_scu_release,
+};
+
+static int __init intel_scu_watchdog_init(void)
+{
+	int ret;
+	u32 __iomem *tmp_addr;
+
+	/*
+	 * We don't really need to check this as the SFI timer get will fail
+	 * but if we do so we can exit with a clearer reason and no noise.
+	 *
+	 * If it isn't an intel MID device then it doesn't have this watchdog
+	 */
+	if (!mrst_identify_cpu())
+		return -ENODEV;
+
+	/* Check boot parameters to verify that their initial values */
+	/* are in range. */
+	/* Check value of timer_set boot parameter */
+	if ((timer_set < MIN_TIME_CYCLE) ||
+	    (timer_set > MAX_TIME - MIN_TIME_CYCLE)) {
+		pr_err("Watchdog timer: value of timer_set %x (hex) "
+		  "is out of range from %x to %x (hex)\n",
+		  timer_set, MIN_TIME_CYCLE, MAX_TIME - MIN_TIME_CYCLE);
+		return -EINVAL;
+	}
+
+	/* Check value of timer_margin boot parameter */
+	if (check_timer_margin(timer_margin))
+		return -EINVAL;
+
+	watchdog_device.timer_tbl_ptr = sfi_get_mtmr(sfi_mtimer_num-1);
+
+	if (watchdog_device.timer_tbl_ptr == NULL) {
+		pr_debug("Watchdog timer - Intel SCU watchdog: timer is not available\n");
+		return -ENODEV;
+	}
+	/* make sure the timer exists */
+	if (watchdog_device.timer_tbl_ptr->phys_addr == 0) {
+		pr_debug("Watchdog timer - Intel SCU watchdog - timer %d does not have valid physical memory\n",
+								sfi_mtimer_num);
+		return -ENODEV;
+	}
+
+	if (watchdog_device.timer_tbl_ptr->irq == 0) {
+		pr_debug("Watchdog timer: timer %d invalid irq\n",
+							sfi_mtimer_num);
+		return -ENODEV;
+	}
+
+	tmp_addr = ioremap_nocache(watchdog_device.timer_tbl_ptr->phys_addr,
+			20);
+
+	if (tmp_addr == NULL) {
+		pr_debug("Watchdog timer: timer unable to ioremap\n");
+		return -ENOMEM;
+	}
+
+	watchdog_device.timer_load_count_addr = tmp_addr++;
+	watchdog_device.timer_current_value_addr = tmp_addr++;
+	watchdog_device.timer_control_addr = tmp_addr++;
+	watchdog_device.timer_clear_interrupt_addr = tmp_addr++;
+	watchdog_device.timer_interrupt_status_addr = tmp_addr++;
+
+	/* Set the default time values in device structure */
+
+	watchdog_device.timer_set = timer_set;
+	watchdog_device.threshold =
+		timer_margin * watchdog_device.timer_tbl_ptr->freq_hz;
+	watchdog_device.soft_threshold =
+		(watchdog_device.timer_set - timer_margin)
+		* watchdog_device.timer_tbl_ptr->freq_hz;
+
+
+	watchdog_device.intel_scu_notifier.notifier_call =
+		intel_scu_notify_sys;
+
+	ret = register_reboot_notifier(&watchdog_device.intel_scu_notifier);
+	if (ret) {
+		pr_err("Watchdog timer: cannot register notifier %d)\n", ret);
+		goto register_reboot_error;
+	}
+
+	watchdog_device.miscdev.minor = WATCHDOG_MINOR;
+	watchdog_device.miscdev.name = "watchdog";
+	watchdog_device.miscdev.fops = &intel_scu_fops;
+
+	ret = misc_register(&watchdog_device.miscdev);
+	if (ret) {
+		pr_err("Watchdog timer: cannot register miscdev %d err =%d\n",
+							WATCHDOG_MINOR, ret);
+		goto misc_register_error;
+	}
+
+	ret = request_irq((unsigned int)watchdog_device.timer_tbl_ptr->irq,
+		watchdog_timer_interrupt,
+		IRQF_SHARED, "watchdog",
+		&watchdog_device.timer_load_count_addr);
+	if (ret) {
+		pr_err("Watchdog timer: error requesting irq %d\n", ret);
+		goto request_irq_error;
+	}
+	/* Make sure timer is disabled before returning */
+	intel_scu_stop();
+	return 0;
+
+/* error cleanup */
+
+request_irq_error:
+	misc_deregister(&watchdog_device.miscdev);
+misc_register_error:
+	unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
+register_reboot_error:
+	intel_scu_stop();
+	iounmap(watchdog_device.timer_load_count_addr);
+	return ret;
+}
+
+static void __exit intel_scu_watchdog_exit(void)
+{
+
+	misc_deregister(&watchdog_device.miscdev);
+	unregister_reboot_notifier(&watchdog_device.intel_scu_notifier);
+	/* disable the timer */
+	iowrite32(0x00000002, watchdog_device.timer_control_addr);
+	iounmap(watchdog_device.timer_load_count_addr);
+}
+
+late_initcall(intel_scu_watchdog_init);
+module_exit(intel_scu_watchdog_exit);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Intel SCU Watchdog Device Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_VERSION(WDT_VER);
diff --git a/drivers/watchdog/intel_scu_watchdog.h b/drivers/watchdog/intel_scu_watchdog.h
new file mode 100644
index 0000000..d2b074a
--- /dev/null
+++ b/drivers/watchdog/intel_scu_watchdog.h
@@ -0,0 +1,66 @@
+/*
+ *      Intel_SCU 0.2:  An Intel SCU IOH Based Watchdog Device
+ *			for Intel part #(s):
+ *				- AF82MP20 PCH
+ *
+ *      Copyright (C) 2009-2010 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., 59 Temple Place - Suite 330,
+ *      Boston, MA  02111-1307, USA.
+ *      The full GNU General Public License is included in this
+ *      distribution in the file called COPYING.
+ *
+ */
+
+#ifndef __INTEL_SCU_WATCHDOG_H
+#define __INTEL_SCU_WATCHDOG_H
+
+#define PFX "Intel_SCU: "
+#define WDT_VER "0.3"
+
+/* minimum time between interrupts */
+#define MIN_TIME_CYCLE 1
+
+/* Time from warning to reboot is 2 seconds */
+#define DEFAULT_SOFT_TO_HARD_MARGIN 2
+
+#define MAX_TIME 170
+
+#define DEFAULT_TIME 5
+
+#define MAX_SOFT_TO_HARD_MARGIN (MAX_TIME-MIN_TIME_CYCLE)
+
+/* Ajustment to clock tick frequency to make timing come out right */
+#define FREQ_ADJUSTMENT 8
+
+struct intel_scu_watchdog_dev {
+	ulong driver_open;
+	ulong driver_closed;
+	u32 timer_started;
+	u32 timer_set;
+	u32 threshold;
+	u32 soft_threshold;
+	u32 __iomem *timer_load_count_addr;
+	u32 __iomem *timer_current_value_addr;
+	u32 __iomem *timer_control_addr;
+	u32 __iomem *timer_clear_interrupt_addr;
+	u32 __iomem *timer_interrupt_status_addr;
+	struct sfi_timer_table_entry *timer_tbl_ptr;
+	struct notifier_block intel_scu_notifier;
+	struct miscdevice miscdev;
+};
+
+extern int sfi_mtimer_num;
+
+/* extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint); */
+#endif /* __INTEL_SCU_WATCHDOG_H */
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index b32c6c0..6143f52 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -69,7 +69,7 @@ static unsigned short address;
 #define IT8712F_DEVID	0x8712
 
 #define LDN_GPIO	0x07	/* GPIO and Watch Dog Timer */
-#define LDN_GAME 	0x09	/* Game Port */
+#define LDN_GAME	0x09	/* Game Port */
 
 #define WDT_CONTROL	0x71	/* WDT Register: Control */
 #define WDT_CONFIG	0x72	/* WDT Register: Configuration */
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index dad2924..b1bc72f 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -12,7 +12,7 @@
  *		    http://www.ite.com.tw/
  *
  *	Support of the watchdog timers, which are available on
- *	IT8702, IT8712, IT8716, IT8718, IT8720 and IT8726.
+ *	IT8702, IT8712, IT8716, IT8718, IT8720, IT8721 and IT8726.
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -45,7 +45,7 @@
 
 #include <asm/system.h>
 
-#define WATCHDOG_VERSION	"1.13"
+#define WATCHDOG_VERSION	"1.14"
 #define WATCHDOG_NAME		"IT87 WDT"
 #define PFX			WATCHDOG_NAME ": "
 #define DRIVER_VERSION		WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
@@ -54,7 +54,7 @@
 /* Defaults for Module Parameter */
 #define DEFAULT_NOGAMEPORT	0
 #define DEFAULT_EXCLUSIVE	1
-#define DEFAULT_TIMEOUT 	60
+#define DEFAULT_TIMEOUT		60
 #define DEFAULT_TESTMODE	0
 #define DEFAULT_NOWAYOUT	WATCHDOG_NOWAYOUT
 
@@ -70,9 +70,9 @@
 /* Configuration Registers and Functions */
 #define LDNREG		0x07
 #define CHIPID		0x20
-#define CHIPREV 	0x22
+#define CHIPREV		0x22
 #define ACTREG		0x30
-#define BASEREG 	0x60
+#define BASEREG		0x60
 
 /* Chip Id numbers */
 #define NO_DEV_ID	0xffff
@@ -82,10 +82,11 @@
 #define IT8716_ID	0x8716
 #define IT8718_ID	0x8718
 #define IT8720_ID	0x8720
+#define IT8721_ID	0x8721
 #define IT8726_ID	0x8726	/* the data sheet suggest wrongly 0x8716 */
 
 /* GPIO Configuration Registers LDN=0x07 */
-#define WDTCTRL 	0x71
+#define WDTCTRL		0x71
 #define WDTCFG		0x72
 #define WDTVALLSB	0x73
 #define WDTVALMSB	0x74
@@ -94,7 +95,7 @@
 #define WDT_CIRINT	0x80
 #define WDT_MOUSEINT	0x40
 #define WDT_KYBINT	0x20
-#define WDT_GAMEPORT	0x10 /* not in it8718, it8720 */
+#define WDT_GAMEPORT	0x10 /* not in it8718, it8720, it8721 */
 #define WDT_FORCE	0x02
 #define WDT_ZERO	0x01
 
@@ -102,11 +103,11 @@
 #define WDT_TOV1	0x80
 #define WDT_KRST	0x40
 #define WDT_TOVE	0x20
-#define WDT_PWROK	0x10
+#define WDT_PWROK	0x10 /* not in it8721 */
 #define WDT_INT_MASK	0x0f
 
 /* CIR Configuration Register LDN=0x0a */
-#define CIR_ILS 	0x70
+#define CIR_ILS		0x70
 
 /* The default Base address is not always available, we use this */
 #define CIR_BASE	0x0208
@@ -134,7 +135,7 @@
 #define WDTS_USE_GP	4
 #define WDTS_EXPECTED	5
 
-static	unsigned int base, gpact, ciract, max_units;
+static	unsigned int base, gpact, ciract, max_units, chip_type;
 static	unsigned long wdt_status;
 static	DEFINE_SPINLOCK(spinlock);
 
@@ -215,7 +216,7 @@ static inline void superio_outw(int val, int reg)
 /* Internal function, should be called after superio_select(GPIO) */
 static void wdt_update_timeout(void)
 {
-	unsigned char cfg = WDT_KRST | WDT_PWROK;
+	unsigned char cfg = WDT_KRST;
 	int tm = timeout;
 
 	if (testmode)
@@ -226,6 +227,9 @@ static void wdt_update_timeout(void)
 	else
 		tm /= 60;
 
+	if (chip_type != IT8721_ID)
+		cfg |= WDT_PWROK;
+
 	superio_outb(cfg, WDTCFG);
 	superio_outb(tm, WDTVALLSB);
 	if (max_units > 255)
@@ -555,7 +559,6 @@ static int __init it87_wdt_init(void)
 {
 	int rc = 0;
 	int try_gameport = !nogameport;
-	u16 chip_type;
 	u8  chip_rev;
 	unsigned long flags;
 
@@ -581,6 +584,7 @@ static int __init it87_wdt_init(void)
 		break;
 	case IT8718_ID:
 	case IT8720_ID:
+	case IT8721_ID:
 		max_units = 65535;
 		try_gameport = 0;
 		break;
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
new file mode 100644
index 0000000..684ba01
--- /dev/null
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -0,0 +1,322 @@
+/*
+ *  Copyright (C) 2010, Paul Cercueil <paul@crapouillou.net>
+ *  JZ4740 Watchdog 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.
+ *
+ *  You 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/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+
+#include <asm/mach-jz4740/timer.h>
+
+#define JZ_REG_WDT_TIMER_DATA     0x0
+#define JZ_REG_WDT_COUNTER_ENABLE 0x4
+#define JZ_REG_WDT_TIMER_COUNTER  0x8
+#define JZ_REG_WDT_TIMER_CONTROL  0xC
+
+#define JZ_WDT_CLOCK_PCLK 0x1
+#define JZ_WDT_CLOCK_RTC  0x2
+#define JZ_WDT_CLOCK_EXT  0x4
+
+#define WDT_IN_USE        0
+#define WDT_OK_TO_CLOSE   1
+
+#define JZ_WDT_CLOCK_DIV_SHIFT   3
+
+#define JZ_WDT_CLOCK_DIV_1    (0 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_4    (1 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_16   (2 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_64   (3 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_256  (4 << JZ_WDT_CLOCK_DIV_SHIFT)
+#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT)
+
+#define DEFAULT_HEARTBEAT 5
+#define MAX_HEARTBEAT     2048
+
+static struct {
+	void __iomem *base;
+	struct resource	*mem;
+	struct clk *rtc_clk;
+	unsigned long status;
+} jz4740_wdt;
+
+static int heartbeat = DEFAULT_HEARTBEAT;
+
+
+static void jz4740_wdt_service(void)
+{
+	writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
+}
+
+static void jz4740_wdt_set_heartbeat(int new_heartbeat)
+{
+	unsigned int rtc_clk_rate;
+	unsigned int timeout_value;
+	unsigned short clock_div = JZ_WDT_CLOCK_DIV_1;
+
+	heartbeat = new_heartbeat;
+
+	rtc_clk_rate = clk_get_rate(jz4740_wdt.rtc_clk);
+
+	timeout_value = rtc_clk_rate * heartbeat;
+	while (timeout_value > 0xffff) {
+		if (clock_div == JZ_WDT_CLOCK_DIV_1024) {
+			/* Requested timeout too high;
+			* use highest possible value. */
+			timeout_value = 0xffff;
+			break;
+		}
+		timeout_value >>= 2;
+		clock_div += (1 << JZ_WDT_CLOCK_DIV_SHIFT);
+	}
+
+	writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
+	writew(clock_div, jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
+
+	writew((u16)timeout_value, jz4740_wdt.base + JZ_REG_WDT_TIMER_DATA);
+	writew(0x0, jz4740_wdt.base + JZ_REG_WDT_TIMER_COUNTER);
+	writew(clock_div | JZ_WDT_CLOCK_RTC,
+		jz4740_wdt.base + JZ_REG_WDT_TIMER_CONTROL);
+
+	writeb(0x1, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
+}
+
+static void jz4740_wdt_enable(void)
+{
+	jz4740_timer_enable_watchdog();
+	jz4740_wdt_set_heartbeat(heartbeat);
+}
+
+static void jz4740_wdt_disable(void)
+{
+	jz4740_timer_disable_watchdog();
+	writeb(0x0, jz4740_wdt.base + JZ_REG_WDT_COUNTER_ENABLE);
+}
+
+static int jz4740_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(WDT_IN_USE, &jz4740_wdt.status))
+		return -EBUSY;
+
+	jz4740_wdt_enable();
+
+	return nonseekable_open(inode, file);
+}
+
+static ssize_t jz4740_wdt_write(struct file *file, const char *data,
+		size_t len, loff_t *ppos)
+{
+	if (len) {
+		size_t i;
+
+		clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
+		for (i = 0; i != len; i++) {
+			char c;
+
+			if (get_user(c, data + i))
+				return -EFAULT;
+
+			if (c == 'V')
+				set_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status);
+		}
+		jz4740_wdt_service();
+	}
+
+	return len;
+}
+
+static const struct watchdog_info ident = {
+	.options = WDIOF_KEEPALIVEPING,
+	.identity = "jz4740 Watchdog",
+};
+
+static long jz4740_wdt_ioctl(struct file *file,
+					unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOTTY;
+	int heartbeat_seconds;
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		ret = copy_to_user((struct watchdog_info *)arg, &ident,
+				sizeof(ident)) ? -EFAULT : 0;
+		break;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		ret = put_user(0, (int *)arg);
+		break;
+
+	case WDIOC_KEEPALIVE:
+		jz4740_wdt_service();
+		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(heartbeat_seconds, (int __user *)arg))
+			return -EFAULT;
+
+		jz4740_wdt_set_heartbeat(heartbeat_seconds);
+		return 0;
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(heartbeat, (int *)arg);
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int jz4740_wdt_release(struct inode *inode, struct file *file)
+{
+	jz4740_wdt_service();
+
+	if (test_and_clear_bit(WDT_OK_TO_CLOSE, &jz4740_wdt.status))
+		jz4740_wdt_disable();
+
+	clear_bit(WDT_IN_USE, &jz4740_wdt.status);
+	return 0;
+}
+
+static const struct file_operations jz4740_wdt_fops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.write = jz4740_wdt_write,
+	.unlocked_ioctl = jz4740_wdt_ioctl,
+	.open = jz4740_wdt_open,
+	.release = jz4740_wdt_release,
+};
+
+static struct miscdevice jz4740_wdt_miscdev = {
+	.minor = WATCHDOG_MINOR,
+	.name = "watchdog",
+	.fops = &jz4740_wdt_fops,
+};
+
+static int __devinit jz4740_wdt_probe(struct platform_device *pdev)
+{
+	int ret = 0, size;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(dev, "failed to get memory region resource\n");
+		return -ENXIO;
+	}
+
+	size = resource_size(res);
+	jz4740_wdt.mem = request_mem_region(res->start, size, pdev->name);
+	if (jz4740_wdt.mem == NULL) {
+		dev_err(dev, "failed to get memory region\n");
+		return -EBUSY;
+	}
+
+	jz4740_wdt.base = ioremap_nocache(res->start, size);
+	if (jz4740_wdt.base == NULL) {
+		dev_err(dev, "failed to map memory region\n");
+		ret = -EBUSY;
+		goto err_release_region;
+	}
+
+	jz4740_wdt.rtc_clk = clk_get(NULL, "rtc");
+	if (IS_ERR(jz4740_wdt.rtc_clk)) {
+		dev_err(dev, "cannot find RTC clock\n");
+		ret = PTR_ERR(jz4740_wdt.rtc_clk);
+		goto err_iounmap;
+	}
+
+	ret = misc_register(&jz4740_wdt_miscdev);
+	if (ret < 0) {
+		dev_err(dev, "cannot register misc device\n");
+		goto err_disable_clk;
+	}
+
+	return 0;
+
+err_disable_clk:
+	clk_put(jz4740_wdt.rtc_clk);
+err_iounmap:
+	iounmap(jz4740_wdt.base);
+err_release_region:
+	release_mem_region(jz4740_wdt.mem->start,
+			resource_size(jz4740_wdt.mem));
+	return ret;
+}
+
+
+static int __devexit jz4740_wdt_remove(struct platform_device *pdev)
+{
+	jz4740_wdt_disable();
+	misc_deregister(&jz4740_wdt_miscdev);
+	clk_put(jz4740_wdt.rtc_clk);
+
+	iounmap(jz4740_wdt.base);
+	jz4740_wdt.base = NULL;
+
+	release_mem_region(jz4740_wdt.mem->start,
+				resource_size(jz4740_wdt.mem));
+	jz4740_wdt.mem = NULL;
+
+	return 0;
+}
+
+
+static struct platform_driver jz4740_wdt_driver = {
+	.probe = jz4740_wdt_probe,
+	.remove = __devexit_p(jz4740_wdt_remove),
+	.driver = {
+		.name = "jz4740-wdt",
+		.owner	= THIS_MODULE,
+	},
+};
+
+
+static int __init jz4740_wdt_init(void)
+{
+	return platform_driver_register(&jz4740_wdt_driver);
+}
+module_init(jz4740_wdt_init);
+
+static void __exit jz4740_wdt_exit(void)
+{
+	platform_driver_unregister(&jz4740_wdt_driver);
+}
+module_exit(jz4740_wdt_exit);
+
+MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
+MODULE_DESCRIPTION("jz4740 Watchdog Driver");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat,
+		"Watchdog heartbeat period in seconds from 1 to "
+		__MODULE_STRING(MAX_HEARTBEAT) ", default "
+		__MODULE_STRING(DEFAULT_HEARTBEAT));
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform:jz4740-wdt");
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 9280350..1332b83 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -54,7 +54,7 @@
 
 /* indexes */			/* size */
 #define ZFL_VERSION	0x02	/* 16   */
-#define CONTROL 	0x10	/* 16   */
+#define CONTROL		0x10	/* 16   */
 #define STATUS		0x12	/* 8    */
 #define COUNTER_1	0x0C	/* 16   */
 #define COUNTER_2	0x0E	/* 8    */
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
index 3053ff0..7a82ce5 100644
--- a/drivers/watchdog/max63xx_wdt.c
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -41,7 +41,7 @@ static int nowayout  = WATCHDOG_NOWAYOUT;
  * to ping the watchdog.
  */
 #define MAX6369_WDSET	(7 << 0)
-#define MAX6369_WDI   	(1 << 3)
+#define MAX6369_WDI	(1 << 3)
 
 static DEFINE_SPINLOCK(io_lock);
 
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 8fa213c..6709d72 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -2,9 +2,9 @@
  * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface
  *
  * Authors: Dave Updegraff <dave@cray.org>
- * 	    Kumar Gala <galak@kernel.crashing.org>
- * 		Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
- * 				..and from sc520_wdt
+ *	    Kumar Gala <galak@kernel.crashing.org>
+ *		Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org>
+ *				..and from sc520_wdt
  * Copyright (c) 2008  MontaVista Software, Inc.
  *                     Anton Vorontsov <avorontsov@ru.mvista.com>
  *
@@ -185,15 +185,18 @@ static struct miscdevice mpc8xxx_wdt_miscdev = {
 	.fops	= &mpc8xxx_wdt_fops,
 };
 
-static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev,
-				       const struct of_device_id *match)
+static int __devinit mpc8xxx_wdt_probe(struct platform_device *ofdev)
 {
 	int ret;
 	struct device_node *np = ofdev->dev.of_node;
-	struct mpc8xxx_wdt_type *wdt_type = match->data;
+	struct mpc8xxx_wdt_type *wdt_type;
 	u32 freq = fsl_get_sys_freq();
 	bool enabled;
 
+	if (!ofdev->dev.of_match)
+		return -EINVAL;
+	wdt_type = match->data;
+
 	if (!freq || freq == -1)
 		return -EINVAL;
 
@@ -272,7 +275,7 @@ static const struct of_device_id mpc8xxx_wdt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match);
 
-static struct of_platform_driver mpc8xxx_wdt_driver = {
+static struct platform_driver mpc8xxx_wdt_driver = {
 	.probe		= mpc8xxx_wdt_probe,
 	.remove		= __devexit_p(mpc8xxx_wdt_remove),
 	.driver = {
@@ -308,13 +311,13 @@ module_init(mpc8xxx_wdt_init_late);
 
 static int __init mpc8xxx_wdt_init(void)
 {
-	return of_register_platform_driver(&mpc8xxx_wdt_driver);
+	return platform_driver_register(&mpc8xxx_wdt_driver);
 }
 arch_initcall(mpc8xxx_wdt_init);
 
 static void __exit mpc8xxx_wdt_exit(void)
 {
-	of_unregister_platform_driver(&mpc8xxx_wdt_driver);
+	platform_driver_unregister(&mpc8xxx_wdt_driver);
 }
 module_exit(mpc8xxx_wdt_exit);
 
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index b8ec7ac..2b4af22 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -172,7 +172,7 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file)
 
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we set nowayout
+	 *	Lock it in if it's a module and we set nowayout
 	 */
 	if (wdt->expect_close == 42)
 		mpcore_wdt_stop(wdt);
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index 08e8a6a..5ec5ac1 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -190,19 +190,19 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf,
 }
 
 static const struct file_operations mtx1_wdt_fops = {
-	.owner 		= THIS_MODULE,
+	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.unlocked_ioctl	= mtx1_wdt_ioctl,
-	.open 		= mtx1_wdt_open,
-	.write 		= mtx1_wdt_write,
-	.release 	= mtx1_wdt_release,
+	.open		= mtx1_wdt_open,
+	.write		= mtx1_wdt_write,
+	.release	= mtx1_wdt_release,
 };
 
 
 static struct miscdevice mtx1_wdt_misc = {
-	.minor 	= WATCHDOG_MINOR,
-	.name 	= "watchdog",
-	.fops 	= &mtx1_wdt_fops,
+	.minor	= WATCHDOG_MINOR,
+	.name	= "watchdog",
+	.fops	= &mtx1_wdt_fops,
 };
 
 
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
index 1a50aa7..267377a 100644
--- a/drivers/watchdog/nv_tco.c
+++ b/drivers/watchdog/nv_tco.c
@@ -289,7 +289,7 @@ static struct miscdevice nv_tco_miscdev = {
  * register a pci_driver, because someone else might one day
  * want to register another driver on the same PCI id.
  */
-static struct pci_device_id tco_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(tco_pci_tbl) = {
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS,
 	  PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS,
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 3dd4971..2b4acb8 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -124,6 +124,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
 	u32 pre_margin = GET_WLDR_VAL(timer_margin);
 	void __iomem *base = wdev->base;
 
+	pm_runtime_get_sync(wdev->dev);
+
 	/* just count up at 32 KHz */
 	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
 		cpu_relax();
@@ -131,6 +133,8 @@ static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev)
 	__raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR);
 	while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04)
 		cpu_relax();
+
+	pm_runtime_put_sync(wdev->dev);
 }
 
 /*
@@ -160,6 +164,8 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
 	omap_wdt_ping(wdev); /* trigger loading of new timeout value */
 	omap_wdt_enable(wdev);
 
+	pm_runtime_put_sync(wdev->dev);
+
 	return nonseekable_open(inode, file);
 }
 
@@ -171,6 +177,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
 	 *      Shut off the timer unless NOWAYOUT is defined.
 	 */
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
+	pm_runtime_get_sync(wdev->dev);
 
 	omap_wdt_disable(wdev);
 
@@ -190,9 +197,11 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data,
 
 	/* Refresh LOAD_TIME. */
 	if (len) {
+		pm_runtime_get_sync(wdev->dev);
 		spin_lock(&wdt_lock);
 		omap_wdt_ping(wdev);
 		spin_unlock(&wdt_lock);
+		pm_runtime_put_sync(wdev->dev);
 	}
 	return len;
 }
@@ -224,15 +233,18 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 			return put_user(omap_prcm_get_reset_sources(),
 					(int __user *)arg);
 	case WDIOC_KEEPALIVE:
+		pm_runtime_get_sync(wdev->dev);
 		spin_lock(&wdt_lock);
 		omap_wdt_ping(wdev);
 		spin_unlock(&wdt_lock);
+		pm_runtime_put_sync(wdev->dev);
 		return 0;
 	case WDIOC_SETTIMEOUT:
 		if (get_user(new_margin, (int __user *)arg))
 			return -EFAULT;
 		omap_wdt_adjust_timeout(new_margin);
 
+		pm_runtime_get_sync(wdev->dev);
 		spin_lock(&wdt_lock);
 		omap_wdt_disable(wdev);
 		omap_wdt_set_timeout(wdev);
@@ -240,6 +252,7 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd,
 
 		omap_wdt_ping(wdev);
 		spin_unlock(&wdt_lock);
+		pm_runtime_put_sync(wdev->dev);
 		/* Fall */
 	case WDIOC_GETTIMEOUT:
 		return put_user(timer_margin, (int __user *)arg);
@@ -345,8 +358,11 @@ static void omap_wdt_shutdown(struct platform_device *pdev)
 {
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 
-	if (wdev->omap_wdt_users)
+	if (wdev->omap_wdt_users) {
+		pm_runtime_get_sync(wdev->dev);
 		omap_wdt_disable(wdev);
+		pm_runtime_put_sync(wdev->dev);
+	}
 }
 
 static int __devexit omap_wdt_remove(struct platform_device *pdev)
@@ -381,8 +397,11 @@ static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
 {
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 
-	if (wdev->omap_wdt_users)
+	if (wdev->omap_wdt_users) {
+		pm_runtime_get_sync(wdev->dev);
 		omap_wdt_disable(wdev);
+		pm_runtime_put_sync(wdev->dev);
+	}
 
 	return 0;
 }
@@ -392,8 +411,10 @@ static int omap_wdt_resume(struct platform_device *pdev)
 	struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
 
 	if (wdev->omap_wdt_users) {
+		pm_runtime_get_sync(wdev->dev);
 		omap_wdt_enable(wdev);
 		omap_wdt_ping(wdev);
+		pm_runtime_put_sync(wdev->dev);
 	}
 
 	return 0;
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h
index fc02ec6..09b774c 100644
--- a/drivers/watchdog/omap_wdt.h
+++ b/drivers/watchdog/omap_wdt.h
@@ -44,7 +44,7 @@
  * months before firing.  These limits work without scaling,
  * with the 60 second default assumed by most tools and docs.
  */
-#define TIMER_MARGIN_MAX    	(24 * 60 * 60)	/* 1 day */
+#define TIMER_MARGIN_MAX	(24 * 60 * 60)	/* 1 day */
 #define TIMER_MARGIN_DEFAULT	60	/* 60 secs */
 #define TIMER_MARGIN_MIN	1
 
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 3a56bc3..139d773 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -514,7 +514,7 @@ static struct miscdevice pc87413_miscdev = {
 /* -- Module init functions -------------------------------------*/
 
 /**
- * 	pc87413_init: module's "constructor"
+ *	pc87413_init: module's "constructor"
  *
  *	Set up the WDT watchdog board. All we have to do is grab the
  *	resources we require and bitch if anyone beat us to them.
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index 64374d6..b8d14f8 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -817,7 +817,7 @@ static void __devexit pcipcwd_card_exit(struct pci_dev *pdev)
 	cards_found--;
 }
 
-static struct pci_device_id pcipcwd_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(pcipcwd_pci_tbl) = {
 	{ PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD,
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{ 0 },			/* End of list */
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index bf5b97c..c7cf4cb 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -4,7 +4,7 @@
  * Watchdog driver for PNX4008 board
  *
  * Authors: Dmitry Chigirev <source@mvista.com>,
- * 	    Vitaly Wool <vitalywool@gmail.com>
+ *	    Vitaly Wool <vitalywool@gmail.com>
  * Based on sa1100 driver,
  * Copyright (C) 2000 Oleg Drokin <green@crimea.edu>
  *
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index 3faee1a..109b533 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -172,8 +172,7 @@ static struct miscdevice riowd_miscdev = {
 	.fops	= &riowd_fops
 };
 
-static int __devinit riowd_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit riowd_probe(struct platform_device *op)
 {
 	struct riowd *p;
 	int err = -EINVAL;
@@ -238,7 +237,7 @@ static const struct of_device_id riowd_match[] = {
 };
 MODULE_DEVICE_TABLE(of, riowd_match);
 
-static struct of_platform_driver riowd_driver = {
+static struct platform_driver riowd_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -250,12 +249,12 @@ static struct of_platform_driver riowd_driver = {
 
 static int __init riowd_init(void)
 {
-	return of_register_platform_driver(&riowd_driver);
+	return platform_driver_register(&riowd_driver);
 }
 
 static void __exit riowd_exit(void)
 {
-	of_unregister_platform_driver(&riowd_driver);
+	platform_driver_unregister(&riowd_driver);
 }
 
 module_init(riowd_init);
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index ae53662..25b39bf 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -224,7 +224,7 @@ static int s3c2410wdt_release(struct inode *inode, struct file *file)
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we set nowayout
+	 *	Lock it in if it's a module and we set nowayout
 	 */
 
 	if (expect_close == 42)
diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c
index 68e2e2d..514ec23 100644
--- a/drivers/watchdog/sbc8360.c
+++ b/drivers/watchdog/sbc8360.c
@@ -114,7 +114,7 @@ static char expect_close;
  *	C |	6.5s	65s	650s	1300s
  *	D |	7s	70s	700s	1400s
  *	E |	7.5s	75s	750s	1500s
- *	F |	8s	80s 	800s 	1600s
+ *	F |	8s	80s	800s	1600s
  *
  * Another way to say the same things is:
  *  For N=1, Timeout = (M+1) * 0.5s
diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c
index 28f1214..3066a51 100644
--- a/drivers/watchdog/sbc_epx_c3.c
+++ b/drivers/watchdog/sbc_epx_c3.c
@@ -220,7 +220,7 @@ module_exit(watchdog_exit);
 MODULE_AUTHOR("Calin A. Culianu <calin@ajvar.org>");
 MODULE_DESCRIPTION("Hardware Watchdog Device for Winsystems EPX-C3 SBC.  "
 	"Note that there is no way to probe for this device -- "
-	"so only use it if you are *sure* you are runnning on this specific "
+	"so only use it if you are *sure* you are running on this specific "
 	"SBC system from Winsystems!  It writes to IO ports 0x1ee and 0x1ef!");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c
index 7990625..d5d3994 100644
--- a/drivers/watchdog/sbc_fitpc2_wdt.c
+++ b/drivers/watchdog/sbc_fitpc2_wdt.c
@@ -41,7 +41,7 @@ static DEFINE_MUTEX(wdt_lock);
 #define IFACE_ON_COMMAND	1
 #define REBOOT_COMMAND		2
 
-#define WATCHDOG_NAME 		"SBC-FITPC2 Watchdog"
+#define WATCHDOG_NAME		"SBC-FITPC2 Watchdog"
 
 static void wdt_send_data(unsigned char command, unsigned char data)
 {
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 6fc7406..4e3e7eb 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -1,9 +1,9 @@
 /*
- * drivers/char/watchdog/shwdt.c
+ * drivers/watchdog/shwdt.c
  *
  * Watchdog driver for integrated watchdog in the SuperH processors.
  *
- * Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (C) 2001 - 2010  Paul Mundt <lethal@linux-sh.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
@@ -19,6 +19,7 @@
  */
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/miscdevice.h>
@@ -28,11 +29,12 @@
 #include <linux/ioport.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/slab.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <asm/watchdog.h>
 
-#define PFX "shwdt: "
+#define DRV_NAME "sh-wdt"
 
 /*
  * Default clock division ratio is 5.25 msecs. For an additional table of
@@ -62,37 +64,36 @@
  * misses its deadline, the kernel timer will allow the WDT to overflow.
  */
 static int clock_division_ratio = WTCSR_CKS_4096;
-
 #define next_ping_period(cks)	msecs_to_jiffies(cks - 4)
 
-static void sh_wdt_ping(unsigned long data);
-
-static unsigned long shwdt_is_open;
 static const struct watchdog_info sh_wdt_info;
-static char shwdt_expect_close;
-static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
-static unsigned long next_heartbeat;
+static struct platform_device *sh_wdt_dev;
 static DEFINE_SPINLOCK(shwdt_lock);
 
 #define WATCHDOG_HEARTBEAT 30			/* 30 sec default heartbeat */
 static int heartbeat = WATCHDOG_HEARTBEAT;	/* in seconds */
-
 static int nowayout = WATCHDOG_NOWAYOUT;
+static unsigned long next_heartbeat;
 
-/**
- * 	sh_wdt_start - Start the Watchdog
- *
- * 	Starts the watchdog.
- */
-static void sh_wdt_start(void)
+struct sh_wdt {
+	void __iomem		*base;
+	struct device		*dev;
+
+	struct timer_list	timer;
+
+	unsigned long		enabled;
+	char			expect_close;
+};
+
+static void sh_wdt_start(struct sh_wdt *wdt)
 {
-	__u8 csr;
 	unsigned long flags;
+	u8 csr;
 
 	spin_lock_irqsave(&shwdt_lock, flags);
 
 	next_heartbeat = jiffies + (heartbeat * HZ);
-	mod_timer(&timer, next_ping_period(clock_division_ratio));
+	mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
 
 	csr = sh_wdt_read_csr();
 	csr |= WTCSR_WT | clock_division_ratio;
@@ -114,15 +115,6 @@ static void sh_wdt_start(void)
 	sh_wdt_write_csr(csr);
 
 #ifdef CONFIG_CPU_SH2
-	/*
-	 * Whoever came up with the RSTCSR semantics must've been smoking
-	 * some of the good stuff, since in addition to the WTCSR/WTCNT write
-	 * brain-damage, it's managed to fuck things up one step further..
-	 *
-	 * If we need to clear the WOVF bit, the upper byte has to be 0xa5..
-	 * but if we want to touch RSTE or RSTS, the upper byte has to be
-	 * 0x5a..
-	 */
 	csr = sh_wdt_read_rstcsr();
 	csr &= ~RSTCSR_RSTS;
 	sh_wdt_write_rstcsr(csr);
@@ -130,30 +122,23 @@ static void sh_wdt_start(void)
 	spin_unlock_irqrestore(&shwdt_lock, flags);
 }
 
-/**
- * 	sh_wdt_stop - Stop the Watchdog
- * 	Stops the watchdog.
- */
-static void sh_wdt_stop(void)
+static void sh_wdt_stop(struct sh_wdt *wdt)
 {
-	__u8 csr;
 	unsigned long flags;
+	u8 csr;
 
 	spin_lock_irqsave(&shwdt_lock, flags);
 
-	del_timer(&timer);
+	del_timer(&wdt->timer);
 
 	csr = sh_wdt_read_csr();
 	csr &= ~WTCSR_TME;
 	sh_wdt_write_csr(csr);
+
 	spin_unlock_irqrestore(&shwdt_lock, flags);
 }
 
-/**
- * 	sh_wdt_keepalive - Keep the Userspace Watchdog Alive
- * 	The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
- */
-static inline void sh_wdt_keepalive(void)
+static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
 {
 	unsigned long flags;
 
@@ -162,10 +147,6 @@ static inline void sh_wdt_keepalive(void)
 	spin_unlock_irqrestore(&shwdt_lock, flags);
 }
 
-/**
- * 	sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
- * 	Set the Userspace Watchdog heartbeat
- */
 static int sh_wdt_set_heartbeat(int t)
 {
 	unsigned long flags;
@@ -179,19 +160,14 @@ static int sh_wdt_set_heartbeat(int t)
 	return 0;
 }
 
-/**
- * 	sh_wdt_ping - Ping the Watchdog
- *	@data: Unused
- *
- * 	Clears overflow bit, resets timer counter.
- */
 static void sh_wdt_ping(unsigned long data)
 {
+	struct sh_wdt *wdt = (struct sh_wdt *)data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&shwdt_lock, flags);
 	if (time_before(jiffies, next_heartbeat)) {
-		__u8 csr;
+		u8 csr;
 
 		csr = sh_wdt_read_csr();
 		csr &= ~WTCSR_IOVF;
@@ -199,148 +175,76 @@ static void sh_wdt_ping(unsigned long data)
 
 		sh_wdt_write_cnt(0);
 
-		mod_timer(&timer, next_ping_period(clock_division_ratio));
+		mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
 	} else
-		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
-		       "the watchdog\n");
+		dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
+		         "the watchdog\n");
 	spin_unlock_irqrestore(&shwdt_lock, flags);
 }
 
-/**
- * 	sh_wdt_open - Open the Device
- * 	@inode: inode of device
- * 	@file: file handle of device
- *
- * 	Watchdog device is opened and started.
- */
 static int sh_wdt_open(struct inode *inode, struct file *file)
 {
-	if (test_and_set_bit(0, &shwdt_is_open))
+	struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
+
+	if (test_and_set_bit(0, &wdt->enabled))
 		return -EBUSY;
 	if (nowayout)
 		__module_get(THIS_MODULE);
 
-	sh_wdt_start();
+	file->private_data = wdt;
+
+	sh_wdt_start(wdt);
 
 	return nonseekable_open(inode, file);
 }
 
-/**
- * 	sh_wdt_close - Close the Device
- * 	@inode: inode of device
- * 	@file: file handle of device
- *
- * 	Watchdog device is closed and stopped.
- */
 static int sh_wdt_close(struct inode *inode, struct file *file)
 {
-	if (shwdt_expect_close == 42) {
-		sh_wdt_stop();
+	struct sh_wdt *wdt = file->private_data;
+
+	if (wdt->expect_close == 42) {
+		sh_wdt_stop(wdt);
 	} else {
-		printk(KERN_CRIT PFX "Unexpected close, not "
-		       "stopping watchdog!\n");
-		sh_wdt_keepalive();
+		dev_crit(wdt->dev, "Unexpected close, not "
+		         "stopping watchdog!\n");
+		sh_wdt_keepalive(wdt);
 	}
 
-	clear_bit(0, &shwdt_is_open);
-	shwdt_expect_close = 0;
+	clear_bit(0, &wdt->enabled);
+	wdt->expect_close = 0;
 
 	return 0;
 }
 
-/**
- * 	sh_wdt_write - Write to Device
- * 	@file: file handle of device
- * 	@buf: buffer to write
- * 	@count: length of buffer
- * 	@ppos: offset
- *
- * 	Pings the watchdog on write.
- */
 static ssize_t sh_wdt_write(struct file *file, const char *buf,
 			    size_t count, loff_t *ppos)
 {
+	struct sh_wdt *wdt = file->private_data;
+
 	if (count) {
 		if (!nowayout) {
 			size_t i;
 
-			shwdt_expect_close = 0;
+			wdt->expect_close = 0;
 
 			for (i = 0; i != count; i++) {
 				char c;
 				if (get_user(c, buf + i))
 					return -EFAULT;
 				if (c == 'V')
-					shwdt_expect_close = 42;
+					wdt->expect_close = 42;
 			}
 		}
-		sh_wdt_keepalive();
+		sh_wdt_keepalive(wdt);
 	}
 
 	return count;
 }
 
-/**
- * 	sh_wdt_mmap - map WDT/CPG registers into userspace
- * 	@file: file structure for the device
- * 	@vma: VMA to map the registers into
- *
- * 	A simple mmap() implementation for the corner cases where the counter
- * 	needs to be mapped in userspace directly. Due to the relatively small
- * 	size of the area, neighbouring registers not necessarily tied to the
- * 	CPG will also be accessible through the register page, so this remains
- * 	configurable for users that really know what they're doing.
- *
- *	Additionaly, the register page maps in the CPG register base relative
- *	to the nearest page-aligned boundary, which requires that userspace do
- *	the appropriate CPU subtype math for calculating the page offset for
- *	the counter value.
- */
-static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	int ret = -ENOSYS;
-
-#ifdef CONFIG_SH_WDT_MMAP
-	unsigned long addr;
-
-	/* Only support the simple cases where we map in a register page. */
-	if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
-		return -EINVAL;
-
-	/*
-	 * Pick WTCNT as the start, it's usually the first register after the
-	 * FRQCR, and neither one are generally page-aligned out of the box.
-	 */
-	addr = WTCNT & ~(PAGE_SIZE - 1);
-
-	vma->vm_flags |= VM_IO;
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-	if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
-			       PAGE_SIZE, vma->vm_page_prot)) {
-		printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
-		       __func__);
-		return -EAGAIN;
-	}
-
-	ret = 0;
-#endif
-
-	return ret;
-}
-
-/**
- * 	sh_wdt_ioctl - Query Device
- * 	@file: file handle of device
- * 	@cmd: watchdog command
- * 	@arg: argument
- *
- * 	Query basic information from the device or ping it, as outlined by the
- * 	watchdog API.
- */
 static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
 							unsigned long arg)
 {
+	struct sh_wdt *wdt = file->private_data;
 	int new_heartbeat;
 	int options, retval = -EINVAL;
 
@@ -356,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
 			return -EFAULT;
 
 		if (options & WDIOS_DISABLECARD) {
-			sh_wdt_stop();
+			sh_wdt_stop(wdt);
 			retval = 0;
 		}
 
 		if (options & WDIOS_ENABLECARD) {
-			sh_wdt_start();
+			sh_wdt_start(wdt);
 			retval = 0;
 		}
 
 		return retval;
 	case WDIOC_KEEPALIVE:
-		sh_wdt_keepalive();
+		sh_wdt_keepalive(wdt);
 		return 0;
 	case WDIOC_SETTIMEOUT:
 		if (get_user(new_heartbeat, (int *)arg))
@@ -376,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
 		if (sh_wdt_set_heartbeat(new_heartbeat))
 			return -EINVAL;
 
-		sh_wdt_keepalive();
+		sh_wdt_keepalive(wdt);
 		/* Fall */
 	case WDIOC_GETTIMEOUT:
 		return put_user(heartbeat, (int *)arg);
@@ -386,20 +290,13 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
 	return 0;
 }
 
-/**
- * 	sh_wdt_notify_sys - Notifier Handler
- * 	@this: notifier block
- * 	@code: notifier event
- * 	@unused: unused
- *
- * 	Handles specific events, such as turning off the watchdog during a
- * 	shutdown event.
- */
 static int sh_wdt_notify_sys(struct notifier_block *this,
 			     unsigned long code, void *unused)
 {
+	struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
+
 	if (code == SYS_DOWN || code == SYS_HALT)
-		sh_wdt_stop();
+		sh_wdt_stop(wdt);
 
 	return NOTIFY_DONE;
 }
@@ -411,7 +308,6 @@ static const struct file_operations sh_wdt_fops = {
 	.unlocked_ioctl	= sh_wdt_ioctl,
 	.open		= sh_wdt_open,
 	.release	= sh_wdt_close,
-	.mmap		= sh_wdt_mmap,
 };
 
 static const struct watchdog_info sh_wdt_info = {
@@ -431,66 +327,148 @@ static struct miscdevice sh_wdt_miscdev = {
 	.fops		= &sh_wdt_fops,
 };
 
-/**
- * 	sh_wdt_init - Initialize module
- * 	Registers the device and notifier handler. Actual device
- * 	initialization is handled by sh_wdt_open().
- */
-static int __init sh_wdt_init(void)
+static int __devinit sh_wdt_probe(struct platform_device *pdev)
 {
+	struct sh_wdt *wdt;
+	struct resource *res;
 	int rc;
 
-	if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) {
-		clock_division_ratio = WTCSR_CKS_4096;
-		printk(KERN_INFO PFX
-		  "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
-				clock_division_ratio);
+	/*
+	 * As this driver only covers the global watchdog case, reject
+	 * any attempts to register per-CPU watchdogs.
+	 */
+	if (pdev->id != -1)
+		return -EINVAL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(!res))
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start,
+				     resource_size(res), DRV_NAME))
+		return -EBUSY;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
+	if (unlikely(!wdt)) {
+		rc = -ENOMEM;
+		goto out_release;
 	}
 
-	rc = sh_wdt_set_heartbeat(heartbeat);
-	if (unlikely(rc)) {
-		heartbeat = WATCHDOG_HEARTBEAT;
-		printk(KERN_INFO PFX
-			"heartbeat value must be 1<=x<=3600, using %d\n",
-								heartbeat);
+	wdt->dev = &pdev->dev;
+
+	wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (unlikely(!wdt->base)) {
+		rc = -ENXIO;
+		goto out_err;
 	}
 
 	rc = register_reboot_notifier(&sh_wdt_notifier);
 	if (unlikely(rc)) {
-		printk(KERN_ERR PFX
+		dev_err(&pdev->dev,
 			"Can't register reboot notifier (err=%d)\n", rc);
-		return rc;
+		goto out_unmap;
 	}
 
+	sh_wdt_miscdev.parent = wdt->dev;
+
 	rc = misc_register(&sh_wdt_miscdev);
 	if (unlikely(rc)) {
-		printk(KERN_ERR PFX
+		dev_err(&pdev->dev,
 			"Can't register miscdev on minor=%d (err=%d)\n",
 						sh_wdt_miscdev.minor, rc);
-		unregister_reboot_notifier(&sh_wdt_notifier);
-		return rc;
+		goto out_unreg;
 	}
 
-	printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
-		heartbeat, nowayout);
+	init_timer(&wdt->timer);
+	wdt->timer.function	= sh_wdt_ping;
+	wdt->timer.data		= (unsigned long)wdt;
+	wdt->timer.expires	= next_ping_period(clock_division_ratio);
+
+	platform_set_drvdata(pdev, wdt);
+	sh_wdt_dev = pdev;
+
+	dev_info(&pdev->dev, "initialized.\n");
 
 	return 0;
+
+out_unreg:
+	unregister_reboot_notifier(&sh_wdt_notifier);
+out_unmap:
+	devm_iounmap(&pdev->dev, wdt->base);
+out_err:
+	devm_kfree(&pdev->dev, wdt);
+out_release:
+	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
+
+	return rc;
 }
 
-/**
- * 	sh_wdt_exit - Deinitialize module
- * 	Unregisters the device and notifier handler. Actual device
- * 	deinitialization is handled by sh_wdt_close().
- */
-static void __exit sh_wdt_exit(void)
+static int __devexit sh_wdt_remove(struct platform_device *pdev)
 {
+	struct sh_wdt *wdt = platform_get_drvdata(pdev);
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	platform_set_drvdata(pdev, NULL);
+
 	misc_deregister(&sh_wdt_miscdev);
+
+	sh_wdt_dev = NULL;
+
 	unregister_reboot_notifier(&sh_wdt_notifier);
+	devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
+	devm_iounmap(&pdev->dev, wdt->base);
+	devm_kfree(&pdev->dev, wdt);
+
+	return 0;
 }
 
+static struct platform_driver sh_wdt_driver = {
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+
+	.probe	= sh_wdt_probe,
+	.remove	= __devexit_p(sh_wdt_remove),
+};
+
+static int __init sh_wdt_init(void)
+{
+	int rc;
+
+	if (unlikely(clock_division_ratio < 0x5 ||
+		     clock_division_ratio > 0x7)) {
+		clock_division_ratio = WTCSR_CKS_4096;
+
+		pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n",
+			 DRV_NAME, clock_division_ratio);
+	}
+
+	rc = sh_wdt_set_heartbeat(heartbeat);
+	if (unlikely(rc)) {
+		heartbeat = WATCHDOG_HEARTBEAT;
+
+		pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
+			DRV_NAME, heartbeat);
+	}
+
+	pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
+		DRV_NAME, heartbeat, nowayout);
+
+	return platform_driver_register(&sh_wdt_driver);
+}
+
+static void __exit sh_wdt_exit(void)
+{
+	platform_driver_unregister(&sh_wdt_driver);
+}
+module_init(sh_wdt_init);
+module_exit(sh_wdt_exit);
+
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("SuperH watchdog driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 module_param(clock_division_ratio, int, 0);
@@ -507,6 +485,3 @@ module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout,
 	"Watchdog cannot be stopped once started (default="
 				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-module_init(sh_wdt_init);
-module_exit(sh_wdt_exit);
diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c
index 8a1f0bc..df88cfa 100644
--- a/drivers/watchdog/smsc37b787_wdt.c
+++ b/drivers/watchdog/smsc37b787_wdt.c
@@ -434,11 +434,11 @@ static long wb_smsc_wdt_ioctl(struct file *file,
 	} uarg;
 
 	static const struct watchdog_info ident = {
-		.options = 		WDIOF_KEEPALIVEPING |
+		.options =		WDIOF_KEEPALIVEPING |
 					WDIOF_SETTIMEOUT |
 					WDIOF_MAGICCLOSE,
 		.firmware_version =	0,
-		.identity = 		"SMsC 37B787 Watchdog",
+		.identity =		"SMsC 37B787 Watchdog",
 	};
 
 	uarg.i = (int __user *)arg;
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index 833f49f..100b114 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -151,7 +151,7 @@ static int softdog_release(struct inode *inode, struct file *file)
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we set nowayout
+	 *	Lock it in if it's a module and we set nowayout
 	 */
 	if (expect_close == 42) {
 		softdog_stop();
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
index 8083728..1bc4938 100644
--- a/drivers/watchdog/sp5100_tco.c
+++ b/drivers/watchdog/sp5100_tco.c
@@ -259,7 +259,7 @@ static struct miscdevice sp5100_tco_miscdev = {
  * register a pci_driver, because someone else might
  * want to register another driver on the same PCI id.
  */
-static struct pci_device_id sp5100_tco_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(sp5100_tco_pci_tbl) = {
 	{ PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, PCI_ANY_ID,
 	  PCI_ANY_ID, },
 	{ 0, },			/* End of list */
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 9127eda..0a0efe7 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -278,7 +278,7 @@ static struct miscdevice sp805_wdt_miscdev = {
 };
 
 static int __devinit
-sp805_wdt_probe(struct amba_device *adev, struct amba_id *id)
+sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret = 0;
 
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 18cdeb4..5a90a4a 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -68,7 +68,7 @@ struct platform_device *ts72xx_wdt_pdev;
  * to control register):
  *	value	description
  *	-------------------------
- * 	0x00	watchdog disabled
+ *	0x00	watchdog disabled
  *	0x01	250ms
  *	0x02	500ms
  *	0x03	1s
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c
index df2a64d..be9c4d8 100644
--- a/drivers/watchdog/w83697ug_wdt.c
+++ b/drivers/watchdog/w83697ug_wdt.c
@@ -87,10 +87,10 @@ static int w83697ug_select_wd_register(void)
 	outb_p(0x87, WDT_EFER); /* Enter extended function mode */
 	outb_p(0x87, WDT_EFER); /* Again according to manual */
 
-	outb(0x20, WDT_EFER); 	/* check chip version	*/
+	outb(0x20, WDT_EFER);	/* check chip version	*/
 	version = inb(WDT_EFDR);
 
-	if (version == 0x68) {	/* W83697UG 		*/
+	if (version == 0x68) {	/* W83697UG		*/
 		printk(KERN_INFO PFX "Watchdog chip version 0x%02x = "
 			"W83697UG/UF found at 0x%04x\n", version, wdt_io);
 
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 552a438..bb03e15 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -581,7 +581,7 @@ static void __exit wdt_exit(void)
 }
 
 /**
- * 	wdt_init:
+ *	wdt_init:
  *
  *	Set up the WDT watchdog board. All we have to do is grab the
  *	resources we require and bitch if anyone beat us to them.
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c
index 5c2521f..a2f01c9 100644
--- a/drivers/watchdog/wdt977.c
+++ b/drivers/watchdog/wdt977.c
@@ -281,7 +281,7 @@ static int wdt977_release(struct inode *inode, struct file *file)
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we set nowayout
+	 *	Lock it in if it's a module and we set nowayout
 	 */
 	if (expect_close == 42) {
 		wdt977_stop();
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index 6130c88..172dad6 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -31,7 +31,7 @@
  *		Jeff Garzik	:	PCI cleanups
  *		Tigran Aivazian	:	Restructured wdtpci_init_one() to handle
  *					failures
- *		Joel Becker 	:	Added WDIOC_GET/SETTIMEOUT
+ *		Joel Becker	:	Added WDIOC_GET/SETTIMEOUT
  *		Zwane Mwaikambo	:	Magic char closing, locking changes,
  *					cleanups
  *		Matt Domsch	:	nowayout module option
@@ -727,7 +727,7 @@ static void __devexit wdtpci_remove_one(struct pci_dev *pdev)
 }
 
 
-static struct pci_device_id wdtpci_pci_tbl[] = {
+static DEFINE_PCI_DEVICE_TABLE(wdtpci_pci_tbl) = {
 	{
 		.vendor	   = PCI_VENDOR_ID_ACCESSIO,
 		.device	   = PCI_DEVICE_ID_ACCESSIO_WDG_CSM,
@@ -764,7 +764,7 @@ static void __exit wdtpci_cleanup(void)
 
 
 /**
- * 	wdtpci_init:
+ *	wdtpci_init:
  *
  *	Set up the WDT watchdog board. All we have to do is grab the
  *	resources we require and bitch if anyone beat us to them.
diff --git a/drivers/watchdog/xen_wdt.c b/drivers/watchdog/xen_wdt.c
new file mode 100644
index 0000000..49bd9d3
--- /dev/null
+++ b/drivers/watchdog/xen_wdt.c
@@ -0,0 +1,359 @@
+/*
+ *	Xen Watchdog Driver
+ *
+ *	(c) Copyright 2010 Novell, 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.
+ */
+
+#define DRV_NAME	"wdt"
+#define DRV_VERSION	"0.01"
+#define PFX		DRV_NAME ": "
+
+#include <linux/bug.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/hrtimer.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+#include <xen/xen.h>
+#include <asm/xen/hypercall.h>
+#include <xen/interface/sched.h>
+
+static struct platform_device *platform_device;
+static DEFINE_SPINLOCK(wdt_lock);
+static struct sched_watchdog wdt;
+static __kernel_time_t wdt_expires;
+static bool is_active, expect_release;
+
+#define WATCHDOG_TIMEOUT 60 /* in seconds */
+static unsigned int timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, uint, S_IRUGO);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds "
+	"(default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, S_IRUGO);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started "
+	"(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static inline __kernel_time_t set_timeout(void)
+{
+	wdt.timeout = timeout;
+	return ktime_to_timespec(ktime_get()).tv_sec + timeout;
+}
+
+static int xen_wdt_start(void)
+{
+	__kernel_time_t expires;
+	int err;
+
+	spin_lock(&wdt_lock);
+
+	expires = set_timeout();
+	if (!wdt.id)
+		err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt);
+	else
+		err = -EBUSY;
+	if (err > 0) {
+		wdt.id = err;
+		wdt_expires = expires;
+		err = 0;
+	} else
+		BUG_ON(!err);
+
+	spin_unlock(&wdt_lock);
+
+	return err;
+}
+
+static int xen_wdt_stop(void)
+{
+	int err = 0;
+
+	spin_lock(&wdt_lock);
+
+	wdt.timeout = 0;
+	if (wdt.id)
+		err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt);
+	if (!err)
+		wdt.id = 0;
+
+	spin_unlock(&wdt_lock);
+
+	return err;
+}
+
+static int xen_wdt_kick(void)
+{
+	__kernel_time_t expires;
+	int err;
+
+	spin_lock(&wdt_lock);
+
+	expires = set_timeout();
+	if (wdt.id)
+		err = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wdt);
+	else
+		err = -ENXIO;
+	if (!err)
+		wdt_expires = expires;
+
+	spin_unlock(&wdt_lock);
+
+	return err;
+}
+
+static int xen_wdt_open(struct inode *inode, struct file *file)
+{
+	int err;
+
+	/* /dev/watchdog can only be opened once */
+	if (xchg(&is_active, true))
+		return -EBUSY;
+
+	err = xen_wdt_start();
+	if (err == -EBUSY)
+		err = xen_wdt_kick();
+	return err ?: nonseekable_open(inode, file);
+}
+
+static int xen_wdt_release(struct inode *inode, struct file *file)
+{
+	if (expect_release)
+		xen_wdt_stop();
+	else {
+		printk(KERN_CRIT PFX
+		       "unexpected close, not stopping watchdog!\n");
+		xen_wdt_kick();
+	}
+	is_active = false;
+	expect_release = false;
+	return 0;
+}
+
+static ssize_t xen_wdt_write(struct file *file, const char __user *data,
+			     size_t len, loff_t *ppos)
+{
+	/* See if we got the magic character 'V' and reload the timer */
+	if (len) {
+		if (!nowayout) {
+			size_t i;
+
+			/* in case it was set long ago */
+			expect_release = false;
+
+			/* scan to see whether or not we got the magic
+			   character */
+			for (i = 0; i != len; i++) {
+				char c;
+				if (get_user(c, data + i))
+					return -EFAULT;
+				if (c == 'V')
+					expect_release = true;
+			}
+		}
+
+		/* someone wrote to us, we should reload the timer */
+		xen_wdt_kick();
+	}
+	return len;
+}
+
+static long xen_wdt_ioctl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	int new_options, retval = -EINVAL;
+	int new_timeout;
+	int __user *argp = (void __user *)arg;
+	static const struct watchdog_info ident = {
+		.options =		WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+		.firmware_version =	0,
+		.identity =		DRV_NAME,
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETSTATUS:
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, argp);
+
+	case WDIOC_SETOPTIONS:
+		if (get_user(new_options, argp))
+			return -EFAULT;
+
+		if (new_options & WDIOS_DISABLECARD)
+			retval = xen_wdt_stop();
+		if (new_options & WDIOS_ENABLECARD) {
+			retval = xen_wdt_start();
+			if (retval == -EBUSY)
+				retval = xen_wdt_kick();
+		}
+		return retval;
+
+	case WDIOC_KEEPALIVE:
+		xen_wdt_kick();
+		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(new_timeout, argp))
+			return -EFAULT;
+		if (!new_timeout)
+			return -EINVAL;
+		timeout = new_timeout;
+		xen_wdt_kick();
+		/* fall through */
+	case WDIOC_GETTIMEOUT:
+		return put_user(timeout, argp);
+
+	case WDIOC_GETTIMELEFT:
+		retval = wdt_expires - ktime_to_timespec(ktime_get()).tv_sec;
+		return put_user(retval, argp);
+	}
+
+	return -ENOTTY;
+}
+
+static const struct file_operations xen_wdt_fops = {
+	.owner =		THIS_MODULE,
+	.llseek =		no_llseek,
+	.write =		xen_wdt_write,
+	.unlocked_ioctl =	xen_wdt_ioctl,
+	.open =			xen_wdt_open,
+	.release =		xen_wdt_release,
+};
+
+static struct miscdevice xen_wdt_miscdev = {
+	.minor =	WATCHDOG_MINOR,
+	.name =		"watchdog",
+	.fops =		&xen_wdt_fops,
+};
+
+static int __devinit xen_wdt_probe(struct platform_device *dev)
+{
+	struct sched_watchdog wd = { .id = ~0 };
+	int ret = HYPERVISOR_sched_op(SCHEDOP_watchdog, &wd);
+
+	switch (ret) {
+	case -EINVAL:
+		if (!timeout) {
+			timeout = WATCHDOG_TIMEOUT;
+			printk(KERN_INFO PFX
+			       "timeout value invalid, using %d\n", timeout);
+		}
+
+		ret = misc_register(&xen_wdt_miscdev);
+		if (ret) {
+			printk(KERN_ERR PFX
+			       "cannot register miscdev on minor=%d (%d)\n",
+			       WATCHDOG_MINOR, ret);
+			break;
+		}
+
+		printk(KERN_INFO PFX
+		       "initialized (timeout=%ds, nowayout=%d)\n",
+		       timeout, nowayout);
+		break;
+
+	case -ENOSYS:
+		printk(KERN_INFO PFX "not supported\n");
+		ret = -ENODEV;
+		break;
+
+	default:
+		printk(KERN_INFO PFX "bogus return value %d\n", ret);
+		break;
+	}
+
+	return ret;
+}
+
+static int __devexit xen_wdt_remove(struct platform_device *dev)
+{
+	/* Stop the timer before we leave */
+	if (!nowayout)
+		xen_wdt_stop();
+
+	misc_deregister(&xen_wdt_miscdev);
+
+	return 0;
+}
+
+static void xen_wdt_shutdown(struct platform_device *dev)
+{
+	xen_wdt_stop();
+}
+
+static int xen_wdt_suspend(struct platform_device *dev, pm_message_t state)
+{
+	return xen_wdt_stop();
+}
+
+static int xen_wdt_resume(struct platform_device *dev)
+{
+	return xen_wdt_start();
+}
+
+static struct platform_driver xen_wdt_driver = {
+	.probe          = xen_wdt_probe,
+	.remove         = __devexit_p(xen_wdt_remove),
+	.shutdown       = xen_wdt_shutdown,
+	.suspend        = xen_wdt_suspend,
+	.resume         = xen_wdt_resume,
+	.driver         = {
+		.owner  = THIS_MODULE,
+		.name   = DRV_NAME,
+	},
+};
+
+static int __init xen_wdt_init_module(void)
+{
+	int err;
+
+	if (!xen_domain())
+		return -ENODEV;
+
+	printk(KERN_INFO PFX "Xen WatchDog Timer Driver v%s\n", DRV_VERSION);
+
+	err = platform_driver_register(&xen_wdt_driver);
+	if (err)
+		return err;
+
+	platform_device = platform_device_register_simple(DRV_NAME,
+								  -1, NULL, 0);
+	if (IS_ERR(platform_device)) {
+		err = PTR_ERR(platform_device);
+		platform_driver_unregister(&xen_wdt_driver);
+	}
+
+	return err;
+}
+
+static void __exit xen_wdt_cleanup_module(void)
+{
+	platform_device_unregister(platform_device);
+	platform_driver_unregister(&xen_wdt_driver);
+	printk(KERN_INFO PFX "module unloaded\n");
+}
+
+module_init(xen_wdt_init_module);
+module_exit(xen_wdt_cleanup_module);
+
+MODULE_AUTHOR("Jan Beulich <jbeulich@novell.com>");
+MODULE_DESCRIPTION("Xen WatchDog Timer Driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 07bec09..a59638b 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -76,10 +76,20 @@ config XEN_XENBUS_FRONTEND
 config XEN_GNTDEV
 	tristate "userspace grant access device driver"
 	depends on XEN
+	default m
 	select MMU_NOTIFIER
 	help
 	  Allows userspace processes to use grants.
 
+config XEN_GRANT_DEV_ALLOC
+	tristate "User-space grant reference allocator driver"
+	depends on XEN
+	default m
+	help
+	  Allows userspace processes to create pages with access granted
+	  to other domains. This can be used to implement frontend drivers
+	  or as part of an inter-domain shared memory channel.
+
 config XEN_PLATFORM_PCI
 	tristate "xen platform pci device driver"
 	depends on XEN_PVHVM && PCI
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 5088cc2..f420f1f 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -1,4 +1,4 @@
-obj-y	+= grant-table.o features.o events.o manage.o
+obj-y	+= grant-table.o features.o events.o manage.o balloon.o
 obj-y	+= xenbus/
 
 nostackp := $(call cc-option, -fno-stack-protector)
@@ -7,9 +7,10 @@ CFLAGS_features.o			:= $(nostackp)
 obj-$(CONFIG_BLOCK)		+= biomerge.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= cpu_hotplug.o
 obj-$(CONFIG_XEN_XENCOMM)	+= xencomm.o
-obj-$(CONFIG_XEN_BALLOON)	+= balloon.o
+obj-$(CONFIG_XEN_BALLOON)	+= xen-balloon.o
 obj-$(CONFIG_XEN_DEV_EVTCHN)	+= xen-evtchn.o
 obj-$(CONFIG_XEN_GNTDEV)	+= xen-gntdev.o
+obj-$(CONFIG_XEN_GRANT_DEV_ALLOC)	+= xen-gntalloc.o
 obj-$(CONFIG_XENFS)		+= xenfs/
 obj-$(CONFIG_XEN_SYS_HYPERVISOR)	+= sys-hypervisor.o
 obj-$(CONFIG_XEN_PLATFORM_PCI)	+= xen-platform-pci.o
@@ -18,5 +19,6 @@ obj-$(CONFIG_XEN_DOM0)		+= pci.o
 
 xen-evtchn-y			:= evtchn.o
 xen-gntdev-y				:= gntdev.o
+xen-gntalloc-y				:= gntalloc.o
 
 xen-platform-pci-y		:= platform-pci.o
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 43f9f02..043af8a 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -1,6 +1,4 @@
 /******************************************************************************
- * balloon.c
- *
  * Xen balloon driver - enables returning/claiming memory to/from Xen.
  *
  * Copyright (c) 2003, B Dragovic
@@ -33,7 +31,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
@@ -42,13 +39,11 @@
 #include <linux/highmem.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
-#include <linux/sysdev.h>
 #include <linux/gfp.h>
 
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
-#include <asm/uaccess.h>
 #include <asm/tlb.h>
 #include <asm/e820.h>
 
@@ -58,35 +53,29 @@
 #include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/memory.h>
-#include <xen/xenbus.h>
+#include <xen/balloon.h>
 #include <xen/features.h>
 #include <xen/page.h>
 
-#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
-
-#define BALLOON_CLASS_NAME "xen_memory"
+/*
+ * balloon_process() state:
+ *
+ * BP_DONE: done or nothing to do,
+ * BP_EAGAIN: error, go to sleep,
+ * BP_ECANCELED: error, balloon operation canceled.
+ */
 
-struct balloon_stats {
-	/* We aim for 'current allocation' == 'target allocation'. */
-	unsigned long current_pages;
-	unsigned long target_pages;
-	/*
-	 * Drivers may alter the memory reservation independently, but they
-	 * must inform the balloon driver so we avoid hitting the hard limit.
-	 */
-	unsigned long driver_pages;
-	/* Number of pages in high- and low-memory balloons. */
-	unsigned long balloon_low;
-	unsigned long balloon_high;
+enum bp_state {
+	BP_DONE,
+	BP_EAGAIN,
+	BP_ECANCELED
 };
 
-static DEFINE_MUTEX(balloon_mutex);
-
-static struct sys_device balloon_sysdev;
 
-static int register_balloon(struct sys_device *sysdev);
+static DEFINE_MUTEX(balloon_mutex);
 
-static struct balloon_stats balloon_stats;
+struct balloon_stats balloon_stats;
+EXPORT_SYMBOL_GPL(balloon_stats);
 
 /* We increase/decrease in batches which fit in a page */
 static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
@@ -104,8 +93,7 @@ static LIST_HEAD(ballooned_pages);
 
 /* Main work function, always executed in process context. */
 static void balloon_process(struct work_struct *work);
-static DECLARE_WORK(balloon_worker, balloon_process);
-static struct timer_list balloon_timer;
+static DECLARE_DELAYED_WORK(balloon_worker, balloon_process);
 
 /* When ballooning out (allocating memory to return to Xen) we don't really
    want the kernel to try too hard since that can trigger the oom killer. */
@@ -140,14 +128,17 @@ static void balloon_append(struct page *page)
 }
 
 /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */
-static struct page *balloon_retrieve(void)
+static struct page *balloon_retrieve(bool prefer_highmem)
 {
 	struct page *page;
 
 	if (list_empty(&ballooned_pages))
 		return NULL;
 
-	page = list_entry(ballooned_pages.next, struct page, lru);
+	if (prefer_highmem)
+		page = list_entry(ballooned_pages.prev, struct page, lru);
+	else
+		page = list_entry(ballooned_pages.next, struct page, lru);
 	list_del(&page->lru);
 
 	if (PageHighMem(page)) {
@@ -177,9 +168,29 @@ static struct page *balloon_next_page(struct page *page)
 	return list_entry(next, struct page, lru);
 }
 
-static void balloon_alarm(unsigned long unused)
+static enum bp_state update_schedule(enum bp_state state)
 {
-	schedule_work(&balloon_worker);
+	if (state == BP_DONE) {
+		balloon_stats.schedule_delay = 1;
+		balloon_stats.retry_count = 1;
+		return BP_DONE;
+	}
+
+	++balloon_stats.retry_count;
+
+	if (balloon_stats.max_retry_count != RETRY_UNLIMITED &&
+			balloon_stats.retry_count > balloon_stats.max_retry_count) {
+		balloon_stats.schedule_delay = 1;
+		balloon_stats.retry_count = 1;
+		return BP_ECANCELED;
+	}
+
+	balloon_stats.schedule_delay <<= 1;
+
+	if (balloon_stats.schedule_delay > balloon_stats.max_schedule_delay)
+		balloon_stats.schedule_delay = balloon_stats.max_schedule_delay;
+
+	return BP_EAGAIN;
 }
 
 static unsigned long current_target(void)
@@ -194,11 +205,11 @@ static unsigned long current_target(void)
 	return target;
 }
 
-static int increase_reservation(unsigned long nr_pages)
+static enum bp_state increase_reservation(unsigned long nr_pages)
 {
+	int rc;
 	unsigned long  pfn, i;
 	struct page   *page;
-	long           rc;
 	struct xen_memory_reservation reservation = {
 		.address_bits = 0,
 		.extent_order = 0,
@@ -210,7 +221,10 @@ static int increase_reservation(unsigned long nr_pages)
 
 	page = balloon_first_page();
 	for (i = 0; i < nr_pages; i++) {
-		BUG_ON(page == NULL);
+		if (!page) {
+			nr_pages = i;
+			break;
+		}
 		frame_list[i] = page_to_pfn(page);
 		page = balloon_next_page(page);
 	}
@@ -218,11 +232,11 @@ static int increase_reservation(unsigned long nr_pages)
 	set_xen_guest_handle(reservation.extent_start, frame_list);
 	reservation.nr_extents = nr_pages;
 	rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
-	if (rc < 0)
-		goto out;
+	if (rc <= 0)
+		return BP_EAGAIN;
 
 	for (i = 0; i < rc; i++) {
-		page = balloon_retrieve();
+		page = balloon_retrieve(false);
 		BUG_ON(page == NULL);
 
 		pfn = page_to_pfn(page);
@@ -232,7 +246,7 @@ static int increase_reservation(unsigned long nr_pages)
 		set_phys_to_machine(pfn, frame_list[i]);
 
 		/* Link back into the page tables if not highmem. */
-		if (pfn < max_low_pfn) {
+		if (!xen_hvm_domain() && pfn < max_low_pfn) {
 			int ret;
 			ret = HYPERVISOR_update_va_mapping(
 				(unsigned long)__va(pfn << PAGE_SHIFT),
@@ -249,15 +263,14 @@ static int increase_reservation(unsigned long nr_pages)
 
 	balloon_stats.current_pages += rc;
 
- out:
-	return rc < 0 ? rc : rc != nr_pages;
+	return BP_DONE;
 }
 
-static int decrease_reservation(unsigned long nr_pages)
+static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
 {
+	enum bp_state state = BP_DONE;
 	unsigned long  pfn, i;
 	struct page   *page;
-	int            need_sleep = 0;
 	int ret;
 	struct xen_memory_reservation reservation = {
 		.address_bits = 0,
@@ -269,9 +282,9 @@ static int decrease_reservation(unsigned long nr_pages)
 		nr_pages = ARRAY_SIZE(frame_list);
 
 	for (i = 0; i < nr_pages; i++) {
-		if ((page = alloc_page(GFP_BALLOON)) == NULL) {
+		if ((page = alloc_page(gfp)) == NULL) {
 			nr_pages = i;
-			need_sleep = 1;
+			state = BP_EAGAIN;
 			break;
 		}
 
@@ -280,7 +293,7 @@ static int decrease_reservation(unsigned long nr_pages)
 
 		scrub_page(page);
 
-		if (!PageHighMem(page)) {
+		if (!xen_hvm_domain() && !PageHighMem(page)) {
 			ret = HYPERVISOR_update_va_mapping(
 				(unsigned long)__va(pfn << PAGE_SHIFT),
 				__pte_ma(0), 0);
@@ -296,7 +309,7 @@ static int decrease_reservation(unsigned long nr_pages)
 	/* No more mappings: invalidate P2M and add to balloon. */
 	for (i = 0; i < nr_pages; i++) {
 		pfn = mfn_to_pfn(frame_list[i]);
-		set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+		__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 		balloon_append(pfn_to_page(pfn));
 	}
 
@@ -307,7 +320,7 @@ static int decrease_reservation(unsigned long nr_pages)
 
 	balloon_stats.current_pages -= nr_pages;
 
-	return need_sleep;
+	return state;
 }
 
 /*
@@ -318,99 +331,125 @@ static int decrease_reservation(unsigned long nr_pages)
  */
 static void balloon_process(struct work_struct *work)
 {
-	int need_sleep = 0;
+	enum bp_state state = BP_DONE;
 	long credit;
 
 	mutex_lock(&balloon_mutex);
 
 	do {
 		credit = current_target() - balloon_stats.current_pages;
+
 		if (credit > 0)
-			need_sleep = (increase_reservation(credit) != 0);
+			state = increase_reservation(credit);
+
 		if (credit < 0)
-			need_sleep = (decrease_reservation(-credit) != 0);
+			state = decrease_reservation(-credit, GFP_BALLOON);
+
+		state = update_schedule(state);
 
 #ifndef CONFIG_PREEMPT
 		if (need_resched())
 			schedule();
 #endif
-	} while ((credit != 0) && !need_sleep);
+	} while (credit && state == BP_DONE);
 
 	/* Schedule more work if there is some still to be done. */
-	if (current_target() != balloon_stats.current_pages)
-		mod_timer(&balloon_timer, jiffies + HZ);
+	if (state == BP_EAGAIN)
+		schedule_delayed_work(&balloon_worker, balloon_stats.schedule_delay * HZ);
 
 	mutex_unlock(&balloon_mutex);
 }
 
 /* Resets the Xen limit, sets new target, and kicks off processing. */
-static void balloon_set_new_target(unsigned long target)
+void balloon_set_new_target(unsigned long target)
 {
 	/* No need for lock. Not read-modify-write updates. */
 	balloon_stats.target_pages = target;
-	schedule_work(&balloon_worker);
+	schedule_delayed_work(&balloon_worker, 0);
 }
+EXPORT_SYMBOL_GPL(balloon_set_new_target);
 
-static struct xenbus_watch target_watch =
-{
-	.node = "memory/target"
-};
-
-/* React to a change in the target key */
-static void watch_target(struct xenbus_watch *watch,
-			 const char **vec, unsigned int len)
+/**
+ * alloc_xenballooned_pages - get pages that have been ballooned out
+ * @nr_pages: Number of pages to get
+ * @pages: pages returned
+ * @return 0 on success, error otherwise
+ */
+int alloc_xenballooned_pages(int nr_pages, struct page** pages)
 {
-	unsigned long long new_target;
-	int err;
-
-	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
-	if (err != 1) {
-		/* This is ok (for domain0 at least) - so just return */
-		return;
+	int pgno = 0;
+	struct page* page;
+	mutex_lock(&balloon_mutex);
+	while (pgno < nr_pages) {
+		page = balloon_retrieve(true);
+		if (page) {
+			pages[pgno++] = page;
+		} else {
+			enum bp_state st;
+			st = decrease_reservation(nr_pages - pgno, GFP_HIGHUSER);
+			if (st != BP_DONE)
+				goto out_undo;
+		}
 	}
-
-	/* The given memory/target value is in KiB, so it needs converting to
-	 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
-	 */
-	balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
+	mutex_unlock(&balloon_mutex);
+	return 0;
+ out_undo:
+	while (pgno)
+		balloon_append(pages[--pgno]);
+	/* Free the memory back to the kernel soon */
+	schedule_delayed_work(&balloon_worker, 0);
+	mutex_unlock(&balloon_mutex);
+	return -ENOMEM;
 }
+EXPORT_SYMBOL(alloc_xenballooned_pages);
 
-static int balloon_init_watcher(struct notifier_block *notifier,
-				unsigned long event,
-				void *data)
+/**
+ * free_xenballooned_pages - return pages retrieved with get_ballooned_pages
+ * @nr_pages: Number of pages
+ * @pages: pages to return
+ */
+void free_xenballooned_pages(int nr_pages, struct page** pages)
 {
-	int err;
+	int i;
 
-	err = register_xenbus_watch(&target_watch);
-	if (err)
-		printk(KERN_ERR "Failed to set balloon watcher\n");
+	mutex_lock(&balloon_mutex);
 
-	return NOTIFY_DONE;
-}
+	for (i = 0; i < nr_pages; i++) {
+		if (pages[i])
+			balloon_append(pages[i]);
+	}
+
+	/* The balloon may be too large now. Shrink it if needed. */
+	if (current_target() != balloon_stats.current_pages)
+		schedule_delayed_work(&balloon_worker, 0);
 
-static struct notifier_block xenstore_notifier;
+	mutex_unlock(&balloon_mutex);
+}
+EXPORT_SYMBOL(free_xenballooned_pages);
 
 static int __init balloon_init(void)
 {
-	unsigned long pfn, extra_pfn_end;
+ 	unsigned long pfn, nr_pages, extra_pfn_end;
 	struct page *page;
 
-	if (!xen_pv_domain())
+	if (!xen_domain())
 		return -ENODEV;
 
-	pr_info("xen_balloon: Initialising balloon driver.\n");
+	pr_info("xen/balloon: Initialising balloon driver.\n");
 
-	balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
+ 	if (xen_pv_domain())
+ 		nr_pages = xen_start_info->nr_pages;
+ 	else
+ 		nr_pages = max_pfn;
+ 	balloon_stats.current_pages = min(nr_pages, max_pfn);
 	balloon_stats.target_pages  = balloon_stats.current_pages;
 	balloon_stats.balloon_low   = 0;
 	balloon_stats.balloon_high  = 0;
-	balloon_stats.driver_pages  = 0UL;
-
-	init_timer(&balloon_timer);
-	balloon_timer.data = 0;
-	balloon_timer.function = balloon_alarm;
 
-	register_balloon(&balloon_sysdev);
+	balloon_stats.schedule_delay = 1;
+	balloon_stats.max_schedule_delay = 32;
+	balloon_stats.retry_count = 1;
+	balloon_stats.max_retry_count = RETRY_UNLIMITED;
 
 	/*
 	 * Initialise the balloon with excess memory space.  We need
@@ -432,153 +471,9 @@ static int __init balloon_init(void)
 		__balloon_append(page);
 	}
 
-	target_watch.callback = watch_target;
-	xenstore_notifier.notifier_call = balloon_init_watcher;
-
-	register_xenstore_notifier(&xenstore_notifier);
-
 	return 0;
 }
 
 subsys_initcall(balloon_init);
 
-static void balloon_exit(void)
-{
-    /* XXX - release balloon here */
-    return;
-}
-
-module_exit(balloon_exit);
-
-#define BALLOON_SHOW(name, format, args...)				\
-	static ssize_t show_##name(struct sys_device *dev,		\
-				   struct sysdev_attribute *attr,	\
-				   char *buf)				\
-	{								\
-		return sprintf(buf, format, ##args);			\
-	}								\
-	static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
-
-BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
-BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
-BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
-BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
-
-static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
-			      char *buf)
-{
-	return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
-}
-
-static ssize_t store_target_kb(struct sys_device *dev,
-			       struct sysdev_attribute *attr,
-			       const char *buf,
-			       size_t count)
-{
-	char *endchar;
-	unsigned long long target_bytes;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	target_bytes = simple_strtoull(buf, &endchar, 0) * 1024;
-
-	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
-
-	return count;
-}
-
-static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
-		   show_target_kb, store_target_kb);
-
-
-static ssize_t show_target(struct sys_device *dev, struct sysdev_attribute *attr,
-			      char *buf)
-{
-	return sprintf(buf, "%llu\n",
-		       (unsigned long long)balloon_stats.target_pages
-		       << PAGE_SHIFT);
-}
-
-static ssize_t store_target(struct sys_device *dev,
-			    struct sysdev_attribute *attr,
-			    const char *buf,
-			    size_t count)
-{
-	char *endchar;
-	unsigned long long target_bytes;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	target_bytes = memparse(buf, &endchar);
-
-	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
-
-	return count;
-}
-
-static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
-		   show_target, store_target);
-
-
-static struct sysdev_attribute *balloon_attrs[] = {
-	&attr_target_kb,
-	&attr_target,
-};
-
-static struct attribute *balloon_info_attrs[] = {
-	&attr_current_kb.attr,
-	&attr_low_kb.attr,
-	&attr_high_kb.attr,
-	&attr_driver_kb.attr,
-	NULL
-};
-
-static struct attribute_group balloon_info_group = {
-	.name = "info",
-	.attrs = balloon_info_attrs,
-};
-
-static struct sysdev_class balloon_sysdev_class = {
-	.name = BALLOON_CLASS_NAME,
-};
-
-static int register_balloon(struct sys_device *sysdev)
-{
-	int i, error;
-
-	error = sysdev_class_register(&balloon_sysdev_class);
-	if (error)
-		return error;
-
-	sysdev->id = 0;
-	sysdev->cls = &balloon_sysdev_class;
-
-	error = sysdev_register(sysdev);
-	if (error) {
-		sysdev_class_unregister(&balloon_sysdev_class);
-		return error;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
-		error = sysdev_create_file(sysdev, balloon_attrs[i]);
-		if (error)
-			goto fail;
-	}
-
-	error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
-	if (error)
-		goto fail;
-
-	return 0;
-
- fail:
-	while (--i >= 0)
-		sysdev_remove_file(sysdev, balloon_attrs[i]);
-	sysdev_unregister(sysdev);
-	sysdev_class_unregister(&balloon_sysdev_class);
-	return error;
-}
-
 MODULE_LICENSE("GPL");
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 7468147..02b5a9c 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -56,6 +56,8 @@
  */
 static DEFINE_SPINLOCK(irq_mapping_update_lock);
 
+static LIST_HEAD(xen_irq_list_head);
+
 /* IRQ <-> VIRQ mapping. */
 static DEFINE_PER_CPU(int [NR_VIRQS], virq_to_irq) = {[0 ... NR_VIRQS-1] = -1};
 
@@ -85,7 +87,9 @@ enum xen_irq_type {
  */
 struct irq_info
 {
+	struct list_head list;
 	enum xen_irq_type type;	/* type */
+	unsigned irq;
 	unsigned short evtchn;	/* event channel */
 	unsigned short cpu;	/* cpu bound */
 
@@ -103,23 +107,10 @@ struct irq_info
 #define PIRQ_NEEDS_EOI	(1 << 0)
 #define PIRQ_SHAREABLE	(1 << 1)
 
-static struct irq_info *irq_info;
-static int *pirq_to_irq;
-
 static int *evtchn_to_irq;
-struct cpu_evtchn_s {
-	unsigned long bits[NR_EVENT_CHANNELS/BITS_PER_LONG];
-};
-
-static __initdata struct cpu_evtchn_s init_evtchn_mask = {
-	.bits[0 ... (NR_EVENT_CHANNELS/BITS_PER_LONG)-1] = ~0ul,
-};
-static struct cpu_evtchn_s *cpu_evtchn_mask_p = &init_evtchn_mask;
 
-static inline unsigned long *cpu_evtchn_mask(int cpu)
-{
-	return cpu_evtchn_mask_p[cpu].bits;
-}
+static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
+		      cpu_evtchn_mask);
 
 /* Xen will never allocate port zero for any purpose. */
 #define VALID_EVTCHN(chn)	((chn) != 0)
@@ -128,46 +119,86 @@ static struct irq_chip xen_dynamic_chip;
 static struct irq_chip xen_percpu_chip;
 static struct irq_chip xen_pirq_chip;
 
-/* Constructor for packed IRQ information. */
-static struct irq_info mk_unbound_info(void)
+/* Get info for IRQ */
+static struct irq_info *info_for_irq(unsigned irq)
 {
-	return (struct irq_info) { .type = IRQT_UNBOUND };
+	return get_irq_data(irq);
 }
 
-static struct irq_info mk_evtchn_info(unsigned short evtchn)
+/* Constructors for packed IRQ information. */
+static void xen_irq_info_common_init(struct irq_info *info,
+				     unsigned irq,
+				     enum xen_irq_type type,
+				     unsigned short evtchn,
+				     unsigned short cpu)
 {
-	return (struct irq_info) { .type = IRQT_EVTCHN, .evtchn = evtchn,
-			.cpu = 0 };
+
+	BUG_ON(info->type != IRQT_UNBOUND && info->type != type);
+
+	info->type = type;
+	info->irq = irq;
+	info->evtchn = evtchn;
+	info->cpu = cpu;
+
+	evtchn_to_irq[evtchn] = irq;
 }
 
-static struct irq_info mk_ipi_info(unsigned short evtchn, enum ipi_vector ipi)
+static void xen_irq_info_evtchn_init(unsigned irq,
+				     unsigned short evtchn)
 {
-	return (struct irq_info) { .type = IRQT_IPI, .evtchn = evtchn,
-			.cpu = 0, .u.ipi = ipi };
+	struct irq_info *info = info_for_irq(irq);
+
+	xen_irq_info_common_init(info, irq, IRQT_EVTCHN, evtchn, 0);
 }
 
-static struct irq_info mk_virq_info(unsigned short evtchn, unsigned short virq)
+static void xen_irq_info_ipi_init(unsigned cpu,
+				  unsigned irq,
+				  unsigned short evtchn,
+				  enum ipi_vector ipi)
 {
-	return (struct irq_info) { .type = IRQT_VIRQ, .evtchn = evtchn,
-			.cpu = 0, .u.virq = virq };
+	struct irq_info *info = info_for_irq(irq);
+
+	xen_irq_info_common_init(info, irq, IRQT_IPI, evtchn, 0);
+
+	info->u.ipi = ipi;
+
+	per_cpu(ipi_to_irq, cpu)[ipi] = irq;
 }
 
-static struct irq_info mk_pirq_info(unsigned short evtchn, unsigned short pirq,
-				    unsigned short gsi, unsigned short vector)
+static void xen_irq_info_virq_init(unsigned cpu,
+				   unsigned irq,
+				   unsigned short evtchn,
+				   unsigned short virq)
 {
-	return (struct irq_info) { .type = IRQT_PIRQ, .evtchn = evtchn,
-			.cpu = 0,
-			.u.pirq = { .pirq = pirq, .gsi = gsi, .vector = vector } };
+	struct irq_info *info = info_for_irq(irq);
+
+	xen_irq_info_common_init(info, irq, IRQT_VIRQ, evtchn, 0);
+
+	info->u.virq = virq;
+
+	per_cpu(virq_to_irq, cpu)[virq] = irq;
 }
 
-/*
- * Accessors for packed IRQ information.
- */
-static struct irq_info *info_for_irq(unsigned irq)
+static void xen_irq_info_pirq_init(unsigned irq,
+				   unsigned short evtchn,
+				   unsigned short pirq,
+				   unsigned short gsi,
+				   unsigned short vector,
+				   unsigned char flags)
 {
-	return &irq_info[irq];
+	struct irq_info *info = info_for_irq(irq);
+
+	xen_irq_info_common_init(info, irq, IRQT_PIRQ, evtchn, 0);
+
+	info->u.pirq.pirq = pirq;
+	info->u.pirq.gsi = gsi;
+	info->u.pirq.vector = vector;
+	info->u.pirq.flags = flags;
 }
 
+/*
+ * Accessors for packed IRQ information.
+ */
 static unsigned int evtchn_from_irq(unsigned irq)
 {
 	if (unlikely(WARN(irq < 0 || irq >= nr_irqs, "Invalid irq %d!\n", irq)))
@@ -212,26 +243,6 @@ static unsigned pirq_from_irq(unsigned irq)
 	return info->u.pirq.pirq;
 }
 
-static unsigned gsi_from_irq(unsigned irq)
-{
-	struct irq_info *info = info_for_irq(irq);
-
-	BUG_ON(info == NULL);
-	BUG_ON(info->type != IRQT_PIRQ);
-
-	return info->u.pirq.gsi;
-}
-
-static unsigned vector_from_irq(unsigned irq)
-{
-	struct irq_info *info = info_for_irq(irq);
-
-	BUG_ON(info == NULL);
-	BUG_ON(info->type != IRQT_PIRQ);
-
-	return info->u.pirq.vector;
-}
-
 static enum xen_irq_type type_from_irq(unsigned irq)
 {
 	return info_for_irq(irq)->type;
@@ -267,7 +278,7 @@ static inline unsigned long active_evtchns(unsigned int cpu,
 					   unsigned int idx)
 {
 	return (sh->evtchn_pending[idx] &
-		cpu_evtchn_mask(cpu)[idx] &
+		per_cpu(cpu_evtchn_mask, cpu)[idx] &
 		~sh->evtchn_mask[idx]);
 }
 
@@ -277,31 +288,31 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
 
 	BUG_ON(irq == -1);
 #ifdef CONFIG_SMP
-	cpumask_copy(irq_to_desc(irq)->affinity, cpumask_of(cpu));
+	cpumask_copy(irq_to_desc(irq)->irq_data.affinity, cpumask_of(cpu));
 #endif
 
-	clear_bit(chn, cpu_evtchn_mask(cpu_from_irq(irq)));
-	set_bit(chn, cpu_evtchn_mask(cpu));
+	clear_bit(chn, per_cpu(cpu_evtchn_mask, cpu_from_irq(irq)));
+	set_bit(chn, per_cpu(cpu_evtchn_mask, cpu));
 
-	irq_info[irq].cpu = cpu;
+	info_for_irq(irq)->cpu = cpu;
 }
 
 static void init_evtchn_cpu_bindings(void)
 {
 	int i;
 #ifdef CONFIG_SMP
-	struct irq_desc *desc;
+	struct irq_info *info;
 
 	/* By default all event channels notify CPU#0. */
-	for_each_irq_desc(i, desc) {
-		cpumask_copy(desc->affinity, cpumask_of(0));
+	list_for_each_entry(info, &xen_irq_list_head, list) {
+		struct irq_desc *desc = irq_to_desc(info->irq);
+		cpumask_copy(desc->irq_data.affinity, cpumask_of(0));
 	}
 #endif
 
 	for_each_possible_cpu(i)
-		memset(cpu_evtchn_mask(i),
-		       (i == 0) ? ~0 : 0, sizeof(struct cpu_evtchn_s));
-
+		memset(per_cpu(cpu_evtchn_mask, i),
+		       (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i)));
 }
 
 static inline void clear_evtchn(int port)
@@ -376,81 +387,90 @@ static void unmask_evtchn(int port)
 	put_cpu();
 }
 
-static int get_nr_hw_irqs(void)
+static void xen_irq_init(unsigned irq)
 {
-	int ret = 1;
+	struct irq_info *info;
+	struct irq_desc *desc = irq_to_desc(irq);
 
-#ifdef CONFIG_X86_IO_APIC
-	ret = get_nr_irqs_gsi();
+#ifdef CONFIG_SMP
+	/* By default all event channels notify CPU#0. */
+	cpumask_copy(desc->irq_data.affinity, cpumask_of(0));
 #endif
 
-	return ret;
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (info == NULL)
+		panic("Unable to allocate metadata for IRQ%d\n", irq);
+
+	info->type = IRQT_UNBOUND;
+
+	set_irq_data(irq, info);
+
+	list_add_tail(&info->list, &xen_irq_list_head);
 }
 
-static int find_unbound_pirq(int type)
+static int __must_check xen_allocate_irq_dynamic(void)
 {
-	int rc, i;
-	struct physdev_get_free_pirq op_get_free_pirq;
-	op_get_free_pirq.type = type;
+	int first = 0;
+	int irq;
 
-	rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq);
-	if (!rc)
-		return op_get_free_pirq.pirq;
+#ifdef CONFIG_X86_IO_APIC
+	/*
+	 * For an HVM guest or domain 0 which see "real" (emulated or
+	 * actual repectively) GSIs we allocate dynamic IRQs
+	 * e.g. those corresponding to event channels or MSIs
+	 * etc. from the range above those "real" GSIs to avoid
+	 * collisions.
+	 */
+	if (xen_initial_domain() || xen_hvm_domain())
+		first = get_nr_irqs_gsi();
+#endif
 
-	for (i = 0; i < nr_irqs; i++) {
-		if (pirq_to_irq[i] < 0)
-			return i;
-	}
-	return -1;
+	irq = irq_alloc_desc_from(first, -1);
+
+	xen_irq_init(irq);
+
+	return irq;
 }
 
-static int find_unbound_irq(void)
+static int __must_check xen_allocate_irq_gsi(unsigned gsi)
 {
-	struct irq_data *data;
-	int irq, res;
-	int bottom = get_nr_hw_irqs();
-	int top = nr_irqs-1;
-
-	if (bottom == nr_irqs)
-		goto no_irqs;
+	int irq;
 
-	/* This loop starts from the top of IRQ space and goes down.
-	 * We need this b/c if we have a PCI device in a Xen PV guest
-	 * we do not have an IO-APIC (though the backend might have them)
-	 * mapped in. To not have a collision of physical IRQs with the Xen
-	 * event channels start at the top of the IRQ space for virtual IRQs.
+	/*
+	 * A PV guest has no concept of a GSI (since it has no ACPI
+	 * nor access to/knowledge of the physical APICs). Therefore
+	 * all IRQs are dynamically allocated from the entire IRQ
+	 * space.
 	 */
-	for (irq = top; irq > bottom; irq--) {
-		data = irq_get_irq_data(irq);
-		/* only 15->0 have init'd desc; handle irq > 16 */
-		if (!data)
-			break;
-		if (data->chip == &no_irq_chip)
-			break;
-		if (data->chip != &xen_dynamic_chip)
-			continue;
-		if (irq_info[irq].type == IRQT_UNBOUND)
-			return irq;
-	}
-
-	if (irq == bottom)
-		goto no_irqs;
+	if (xen_pv_domain() && !xen_initial_domain())
+		return xen_allocate_irq_dynamic();
 
-	res = irq_alloc_desc_at(irq, -1);
+	/* Legacy IRQ descriptors are already allocated by the arch. */
+	if (gsi < NR_IRQS_LEGACY)
+		irq = gsi;
+	else
+		irq = irq_alloc_desc_at(gsi, -1);
 
-	if (WARN_ON(res != irq))
-		return -1;
+	xen_irq_init(irq);
 
 	return irq;
-
-no_irqs:
-	panic("No available IRQ to bind to: increase nr_irqs!\n");
 }
 
-static bool identity_mapped_irq(unsigned irq)
+static void xen_free_irq(unsigned irq)
 {
-	/* identity map all the hardware irqs */
-	return irq < get_nr_hw_irqs();
+	struct irq_info *info = get_irq_data(irq);
+
+	list_del(&info->list);
+
+	set_irq_data(irq, NULL);
+
+	kfree(info);
+
+	/* Legacy IRQ descriptors are managed by the arch. */
+	if (irq < NR_IRQS_LEGACY)
+		return;
+
+	irq_free_desc(irq);
 }
 
 static void pirq_unmask_notify(int irq)
@@ -486,7 +506,7 @@ static bool probing_irq(int irq)
 	return desc && desc->action == NULL;
 }
 
-static unsigned int startup_pirq(unsigned int irq)
+static unsigned int __startup_pirq(unsigned int irq)
 {
 	struct evtchn_bind_pirq bind_pirq;
 	struct irq_info *info = info_for_irq(irq);
@@ -524,9 +544,15 @@ out:
 	return 0;
 }
 
-static void shutdown_pirq(unsigned int irq)
+static unsigned int startup_pirq(struct irq_data *data)
+{
+	return __startup_pirq(data->irq);
+}
+
+static void shutdown_pirq(struct irq_data *data)
 {
 	struct evtchn_close close;
+	unsigned int irq = data->irq;
 	struct irq_info *info = info_for_irq(irq);
 	int evtchn = evtchn_from_irq(irq);
 
@@ -546,20 +572,20 @@ static void shutdown_pirq(unsigned int irq)
 	info->evtchn = 0;
 }
 
-static void enable_pirq(unsigned int irq)
+static void enable_pirq(struct irq_data *data)
 {
-	startup_pirq(irq);
+	startup_pirq(data);
 }
 
-static void disable_pirq(unsigned int irq)
+static void disable_pirq(struct irq_data *data)
 {
 }
 
-static void ack_pirq(unsigned int irq)
+static void ack_pirq(struct irq_data *data)
 {
-	int evtchn = evtchn_from_irq(irq);
+	int evtchn = evtchn_from_irq(data->irq);
 
-	move_native_irq(irq);
+	move_native_irq(data->irq);
 
 	if (VALID_EVTCHN(evtchn)) {
 		mask_evtchn(evtchn);
@@ -567,70 +593,41 @@ static void ack_pirq(unsigned int irq)
 	}
 }
 
-static void end_pirq(unsigned int irq)
-{
-	int evtchn = evtchn_from_irq(irq);
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	if (WARN_ON(!desc))
-		return;
-
-	if ((desc->status & (IRQ_DISABLED|IRQ_PENDING)) ==
-	    (IRQ_DISABLED|IRQ_PENDING)) {
-		shutdown_pirq(irq);
-	} else if (VALID_EVTCHN(evtchn)) {
-		unmask_evtchn(evtchn);
-		pirq_unmask_notify(irq);
-	}
-}
-
 static int find_irq_by_gsi(unsigned gsi)
 {
-	int irq;
-
-	for (irq = 0; irq < nr_irqs; irq++) {
-		struct irq_info *info = info_for_irq(irq);
+	struct irq_info *info;
 
-		if (info == NULL || info->type != IRQT_PIRQ)
+	list_for_each_entry(info, &xen_irq_list_head, list) {
+		if (info->type != IRQT_PIRQ)
 			continue;
 
-		if (gsi_from_irq(irq) == gsi)
-			return irq;
+		if (info->u.pirq.gsi == gsi)
+			return info->irq;
 	}
 
 	return -1;
 }
 
-int xen_allocate_pirq(unsigned gsi, int shareable, char *name)
+int xen_allocate_pirq_gsi(unsigned gsi)
 {
-	return xen_map_pirq_gsi(gsi, gsi, shareable, name);
+	return gsi;
 }
 
-/* xen_map_pirq_gsi might allocate irqs from the top down, as a
- * consequence don't assume that the irq number returned has a low value
- * or can be used as a pirq number unless you know otherwise.
- *
- * One notable exception is when xen_map_pirq_gsi is called passing an
- * hardware gsi as argument, in that case the irq number returned
- * matches the gsi number passed as second argument.
+/*
+ * Do not make any assumptions regarding the relationship between the
+ * IRQ number returned here and the Xen pirq argument.
  *
  * Note: We don't assign an event channel until the irq actually started
  * up.  Return an existing irq if we've already got one for the gsi.
  */
-int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name)
+int xen_bind_pirq_gsi_to_irq(unsigned gsi,
+			     unsigned pirq, int shareable, char *name)
 {
-	int irq = 0;
+	int irq = -1;
 	struct physdev_irq irq_op;
 
 	spin_lock(&irq_mapping_update_lock);
 
-	if ((pirq > nr_irqs) || (gsi > nr_irqs)) {
-		printk(KERN_WARNING "xen_map_pirq_gsi: %s %s is incorrect!\n",
-			pirq > nr_irqs ? "pirq" :"",
-			gsi > nr_irqs ? "gsi" : "");
-		goto out;
-	}
-
 	irq = find_irq_by_gsi(gsi);
 	if (irq != -1) {
 		printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n",
@@ -638,14 +635,9 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name)
 		goto out;	/* XXX need refcount? */
 	}
 
-	/* If we are a PV guest, we don't have GSIs (no ACPI passed). Therefore
-	 * we are using the !xen_initial_domain() to drop in the function.*/
-	if (identity_mapped_irq(gsi) || (!xen_initial_domain() &&
-				xen_pv_domain())) {
-		irq = gsi;
-		irq_alloc_desc_at(irq, -1);
-	} else
-		irq = find_unbound_irq();
+	irq = xen_allocate_irq_gsi(gsi);
+	if (irq < 0)
+		goto out;
 
 	set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
 				      handle_level_irq, name);
@@ -658,14 +650,13 @@ int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name)
 	 * this in the priv domain. */
 	if (xen_initial_domain() &&
 	    HYPERVISOR_physdev_op(PHYSDEVOP_alloc_irq_vector, &irq_op)) {
-		irq_free_desc(irq);
+		xen_free_irq(irq);
 		irq = -ENOSPC;
 		goto out;
 	}
 
-	irq_info[irq] = mk_pirq_info(0, pirq, gsi, irq_op.vector);
-	irq_info[irq].u.pirq.flags |= shareable ? PIRQ_SHAREABLE : 0;
-	pirq_to_irq[pirq] = irq;
+	xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector,
+			       shareable ? PIRQ_SHAREABLE : 0);
 
 out:
 	spin_unlock(&irq_mapping_update_lock);
@@ -674,87 +665,45 @@ out:
 }
 
 #ifdef CONFIG_PCI_MSI
-#include <linux/msi.h>
-#include "../pci/msi.h"
-
-void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc)
+int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc)
 {
-	spin_lock(&irq_mapping_update_lock);
-
-	if (alloc & XEN_ALLOC_IRQ) {
-		*irq = find_unbound_irq();
-		if (*irq == -1)
-			goto out;
-	}
-
-	if (alloc & XEN_ALLOC_PIRQ) {
-		*pirq = find_unbound_pirq(MAP_PIRQ_TYPE_MSI);
-		if (*pirq == -1)
-			goto out;
-	}
+	int rc;
+	struct physdev_get_free_pirq op_get_free_pirq;
 
-	set_irq_chip_and_handler_name(*irq, &xen_pirq_chip,
-				      handle_level_irq, name);
+	op_get_free_pirq.type = MAP_PIRQ_TYPE_MSI;
+	rc = HYPERVISOR_physdev_op(PHYSDEVOP_get_free_pirq, &op_get_free_pirq);
 
-	irq_info[*irq] = mk_pirq_info(0, *pirq, 0, 0);
-	pirq_to_irq[*pirq] = *irq;
+	WARN_ONCE(rc == -ENOSYS,
+		  "hypervisor does not support the PHYSDEVOP_get_free_pirq interface\n");
 
-out:
-	spin_unlock(&irq_mapping_update_lock);
+	return rc ? -1 : op_get_free_pirq.pirq;
 }
 
-int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type)
+int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+			     int pirq, int vector, const char *name)
 {
-	int irq = -1;
-	struct physdev_map_pirq map_irq;
-	int rc;
-	int pos;
-	u32 table_offset, bir;
-
-	memset(&map_irq, 0, sizeof(map_irq));
-	map_irq.domid = DOMID_SELF;
-	map_irq.type = MAP_PIRQ_TYPE_MSI;
-	map_irq.index = -1;
-	map_irq.pirq = -1;
-	map_irq.bus = dev->bus->number;
-	map_irq.devfn = dev->devfn;
-
-	if (type == PCI_CAP_ID_MSIX) {
-		pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-
-		pci_read_config_dword(dev, msix_table_offset_reg(pos),
-					&table_offset);
-		bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-
-		map_irq.table_base = pci_resource_start(dev, bir);
-		map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
-	}
+	int irq, ret;
 
 	spin_lock(&irq_mapping_update_lock);
 
-	irq = find_unbound_irq();
-
+	irq = xen_allocate_irq_dynamic();
 	if (irq == -1)
 		goto out;
 
-	rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
-	if (rc) {
-		printk(KERN_WARNING "xen map irq failed %d\n", rc);
-
-		irq_free_desc(irq);
-
-		irq = -1;
-		goto out;
-	}
-	irq_info[irq] = mk_pirq_info(0, map_irq.pirq, 0, map_irq.index);
-
 	set_irq_chip_and_handler_name(irq, &xen_pirq_chip,
-			handle_level_irq,
-			(type == PCI_CAP_ID_MSIX) ? "msi-x":"msi");
+				      handle_level_irq, name);
 
+	xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, 0);
+	ret = irq_set_msi_desc(irq, msidesc);
+	if (ret < 0)
+		goto error_irq;
 out:
 	spin_unlock(&irq_mapping_update_lock);
 	return irq;
+error_irq:
+	spin_unlock(&irq_mapping_update_lock);
+	xen_free_irq(irq);
+	return -1;
 }
 #endif
 
@@ -779,30 +728,35 @@ int xen_destroy_irq(int irq)
 			printk(KERN_WARNING "unmap irq failed %d\n", rc);
 			goto out;
 		}
-		pirq_to_irq[info->u.pirq.pirq] = -1;
 	}
-	irq_info[irq] = mk_unbound_info();
 
-	irq_free_desc(irq);
+	xen_free_irq(irq);
 
 out:
 	spin_unlock(&irq_mapping_update_lock);
 	return rc;
 }
 
-int xen_vector_from_irq(unsigned irq)
+int xen_irq_from_pirq(unsigned pirq)
 {
-	return vector_from_irq(irq);
-}
+	int irq;
 
-int xen_gsi_from_irq(unsigned irq)
-{
-	return gsi_from_irq(irq);
-}
+	struct irq_info *info;
 
-int xen_irq_from_pirq(unsigned pirq)
-{
-	return pirq_to_irq[pirq];
+	spin_lock(&irq_mapping_update_lock);
+
+	list_for_each_entry(info, &xen_irq_list_head, list) {
+		if (info == NULL || info->type != IRQT_PIRQ)
+			continue;
+		irq = info->irq;
+		if (info->u.pirq.pirq == pirq)
+			goto out;
+	}
+	irq = -1;
+out:
+	spin_unlock(&irq_mapping_update_lock);
+
+	return irq;
 }
 
 int bind_evtchn_to_irq(unsigned int evtchn)
@@ -814,15 +768,17 @@ int bind_evtchn_to_irq(unsigned int evtchn)
 	irq = evtchn_to_irq[evtchn];
 
 	if (irq == -1) {
-		irq = find_unbound_irq();
+		irq = xen_allocate_irq_dynamic();
+		if (irq == -1)
+			goto out;
 
 		set_irq_chip_and_handler_name(irq, &xen_dynamic_chip,
 					      handle_fasteoi_irq, "event");
 
-		evtchn_to_irq[evtchn] = irq;
-		irq_info[irq] = mk_evtchn_info(evtchn);
+		xen_irq_info_evtchn_init(irq, evtchn);
 	}
 
+out:
 	spin_unlock(&irq_mapping_update_lock);
 
 	return irq;
@@ -839,7 +795,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
 	irq = per_cpu(ipi_to_irq, cpu)[ipi];
 
 	if (irq == -1) {
-		irq = find_unbound_irq();
+		irq = xen_allocate_irq_dynamic();
 		if (irq < 0)
 			goto out;
 
@@ -852,9 +808,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
 			BUG();
 		evtchn = bind_ipi.port;
 
-		evtchn_to_irq[evtchn] = irq;
-		irq_info[irq] = mk_ipi_info(evtchn, ipi);
-		per_cpu(ipi_to_irq, cpu)[ipi] = irq;
+		xen_irq_info_ipi_init(cpu, irq, evtchn, ipi);
 
 		bind_evtchn_to_cpu(evtchn, cpu);
 	}
@@ -864,6 +818,21 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
 	return irq;
 }
 
+static int bind_interdomain_evtchn_to_irq(unsigned int remote_domain,
+					  unsigned int remote_port)
+{
+	struct evtchn_bind_interdomain bind_interdomain;
+	int err;
+
+	bind_interdomain.remote_dom  = remote_domain;
+	bind_interdomain.remote_port = remote_port;
+
+	err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain,
+					  &bind_interdomain);
+
+	return err ? : bind_evtchn_to_irq(bind_interdomain.local_port);
+}
+
 
 int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 {
@@ -875,7 +844,9 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 	irq = per_cpu(virq_to_irq, cpu)[virq];
 
 	if (irq == -1) {
-		irq = find_unbound_irq();
+		irq = xen_allocate_irq_dynamic();
+		if (irq == -1)
+			goto out;
 
 		set_irq_chip_and_handler_name(irq, &xen_percpu_chip,
 					      handle_percpu_irq, "virq");
@@ -887,14 +858,12 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
 			BUG();
 		evtchn = bind_virq.port;
 
-		evtchn_to_irq[evtchn] = irq;
-		irq_info[irq] = mk_virq_info(evtchn, virq);
-
-		per_cpu(virq_to_irq, cpu)[virq] = irq;
+		xen_irq_info_virq_init(cpu, irq, evtchn, virq);
 
 		bind_evtchn_to_cpu(evtchn, cpu);
 	}
 
+out:
 	spin_unlock(&irq_mapping_update_lock);
 
 	return irq;
@@ -931,11 +900,9 @@ static void unbind_from_irq(unsigned int irq)
 		evtchn_to_irq[evtchn] = -1;
 	}
 
-	if (irq_info[irq].type != IRQT_UNBOUND) {
-		irq_info[irq] = mk_unbound_info();
+	BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND);
 
-		irq_free_desc(irq);
-	}
+	xen_free_irq(irq);
 
 	spin_unlock(&irq_mapping_update_lock);
 }
@@ -949,6 +916,8 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
 	int retval;
 
 	irq = bind_evtchn_to_irq(evtchn);
+	if (irq < 0)
+		return irq;
 	retval = request_irq(irq, handler, irqflags, devname, dev_id);
 	if (retval != 0) {
 		unbind_from_irq(irq);
@@ -959,6 +928,29 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
 }
 EXPORT_SYMBOL_GPL(bind_evtchn_to_irqhandler);
 
+int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
+					  unsigned int remote_port,
+					  irq_handler_t handler,
+					  unsigned long irqflags,
+					  const char *devname,
+					  void *dev_id)
+{
+	int irq, retval;
+
+	irq = bind_interdomain_evtchn_to_irq(remote_domain, remote_port);
+	if (irq < 0)
+		return irq;
+
+	retval = request_irq(irq, handler, irqflags, devname, dev_id);
+	if (retval != 0) {
+		unbind_from_irq(irq);
+		return retval;
+	}
+
+	return irq;
+}
+EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irqhandler);
+
 int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
 			    irq_handler_t handler,
 			    unsigned long irqflags, const char *devname, void *dev_id)
@@ -967,6 +959,8 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
 	int retval;
 
 	irq = bind_virq_to_irq(virq, cpu);
+	if (irq < 0)
+		return irq;
 	retval = request_irq(irq, handler, irqflags, devname, dev_id);
 	if (retval != 0) {
 		unbind_from_irq(irq);
@@ -990,7 +984,7 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
 	if (irq < 0)
 		return irq;
 
-	irqflags |= IRQF_NO_SUSPEND;
+	irqflags |= IRQF_NO_SUSPEND | IRQF_FORCE_RESUME;
 	retval = request_irq(irq, handler, irqflags, devname, dev_id);
 	if (retval != 0) {
 		unbind_from_irq(irq);
@@ -1018,7 +1012,7 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
 {
 	struct shared_info *sh = HYPERVISOR_shared_info;
 	int cpu = smp_processor_id();
-	unsigned long *cpu_evtchn = cpu_evtchn_mask(cpu);
+	unsigned long *cpu_evtchn = per_cpu(cpu_evtchn_mask, cpu);
 	int i;
 	unsigned long flags;
 	static DEFINE_SPINLOCK(debug_lock);
@@ -1096,6 +1090,13 @@ irqreturn_t xen_debug_interrupt(int irq, void *dev_id)
 }
 
 static DEFINE_PER_CPU(unsigned, xed_nesting_count);
+static DEFINE_PER_CPU(unsigned int, current_word_idx);
+static DEFINE_PER_CPU(unsigned int, current_bit_idx);
+
+/*
+ * Mask out the i least significant bits of w
+ */
+#define MASK_LSBS(w, i) (w & ((~0UL) << i))
 
 /*
  * Search the CPUs pending events bitmasks.  For each one found, map
@@ -1108,6 +1109,9 @@ static DEFINE_PER_CPU(unsigned, xed_nesting_count);
  */
 static void __xen_evtchn_do_upcall(void)
 {
+	int start_word_idx, start_bit_idx;
+	int word_idx, bit_idx;
+	int i;
 	int cpu = get_cpu();
 	struct shared_info *s = HYPERVISOR_shared_info;
 	struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
@@ -1126,17 +1130,57 @@ static void __xen_evtchn_do_upcall(void)
 		wmb();
 #endif
 		pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0);
-		while (pending_words != 0) {
+
+		start_word_idx = __this_cpu_read(current_word_idx);
+		start_bit_idx = __this_cpu_read(current_bit_idx);
+
+		word_idx = start_word_idx;
+
+		for (i = 0; pending_words != 0; i++) {
 			unsigned long pending_bits;
-			int word_idx = __ffs(pending_words);
-			pending_words &= ~(1UL << word_idx);
+			unsigned long words;
 
-			while ((pending_bits = active_evtchns(cpu, s, word_idx)) != 0) {
-				int bit_idx = __ffs(pending_bits);
-				int port = (word_idx * BITS_PER_LONG) + bit_idx;
-				int irq = evtchn_to_irq[port];
+			words = MASK_LSBS(pending_words, word_idx);
+
+			/*
+			 * If we masked out all events, wrap to beginning.
+			 */
+			if (words == 0) {
+				word_idx = 0;
+				bit_idx = 0;
+				continue;
+			}
+			word_idx = __ffs(words);
+
+			pending_bits = active_evtchns(cpu, s, word_idx);
+			bit_idx = 0; /* usually scan entire word from start */
+			if (word_idx == start_word_idx) {
+				/* We scan the starting word in two parts */
+				if (i == 0)
+					/* 1st time: start in the middle */
+					bit_idx = start_bit_idx;
+				else
+					/* 2nd time: mask bits done already */
+					bit_idx &= (1UL << start_bit_idx) - 1;
+			}
+
+			do {
+				unsigned long bits;
+				int port, irq;
 				struct irq_desc *desc;
 
+				bits = MASK_LSBS(pending_bits, bit_idx);
+
+				/* If we masked out all events, move on. */
+				if (bits == 0)
+					break;
+
+				bit_idx = __ffs(bits);
+
+				/* Process port. */
+				port = (word_idx * BITS_PER_LONG) + bit_idx;
+				irq = evtchn_to_irq[port];
+
 				mask_evtchn(port);
 				clear_evtchn(port);
 
@@ -1145,7 +1189,21 @@ static void __xen_evtchn_do_upcall(void)
 					if (desc)
 						generic_handle_irq_desc(irq, desc);
 				}
-			}
+
+				bit_idx = (bit_idx + 1) % BITS_PER_LONG;
+
+				/* Next caller starts at last processed + 1 */
+				__this_cpu_write(current_word_idx,
+						 bit_idx ? word_idx :
+						 (word_idx+1) % BITS_PER_LONG);
+				__this_cpu_write(current_bit_idx, bit_idx);
+			} while (bit_idx != 0);
+
+			/* Scan start_l1i twice; all others once. */
+			if ((word_idx != start_word_idx) || (i != 0))
+				pending_words &= ~(1UL << word_idx);
+
+			word_idx = (word_idx + 1) % BITS_PER_LONG;
 		}
 
 		BUG_ON(!irqs_disabled());
@@ -1195,8 +1253,7 @@ void rebind_evtchn_irq(int evtchn, int irq)
 	   so there should be a proper type */
 	BUG_ON(info->type == IRQT_UNBOUND);
 
-	evtchn_to_irq[evtchn] = irq;
-	irq_info[irq] = mk_evtchn_info(evtchn);
+	xen_irq_info_evtchn_init(irq, evtchn);
 
 	spin_unlock(&irq_mapping_update_lock);
 
@@ -1213,10 +1270,14 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 	struct evtchn_bind_vcpu bind_vcpu;
 	int evtchn = evtchn_from_irq(irq);
 
-	/* events delivered via platform PCI interrupts are always
-	 * routed to vcpu 0 */
-	if (!VALID_EVTCHN(evtchn) ||
-		(xen_hvm_domain() && !xen_have_vector_callback))
+	if (!VALID_EVTCHN(evtchn))
+		return -1;
+
+	/*
+	 * Events delivered via platform PCI interrupts are always
+	 * routed to vcpu 0 and hence cannot be rebound.
+	 */
+	if (xen_hvm_domain() && !xen_have_vector_callback)
 		return -1;
 
 	/* Send future instances of this interrupt to other vcpu. */
@@ -1234,11 +1295,12 @@ static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
 	return 0;
 }
 
-static int set_affinity_irq(unsigned irq, const struct cpumask *dest)
+static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest,
+			    bool force)
 {
 	unsigned tcpu = cpumask_first(dest);
 
-	return rebind_irq_to_cpu(irq, tcpu);
+	return rebind_irq_to_cpu(data->irq, tcpu);
 }
 
 int resend_irq_on_evtchn(unsigned int irq)
@@ -1257,35 +1319,35 @@ int resend_irq_on_evtchn(unsigned int irq)
 	return 1;
 }
 
-static void enable_dynirq(unsigned int irq)
+static void enable_dynirq(struct irq_data *data)
 {
-	int evtchn = evtchn_from_irq(irq);
+	int evtchn = evtchn_from_irq(data->irq);
 
 	if (VALID_EVTCHN(evtchn))
 		unmask_evtchn(evtchn);
 }
 
-static void disable_dynirq(unsigned int irq)
+static void disable_dynirq(struct irq_data *data)
 {
-	int evtchn = evtchn_from_irq(irq);
+	int evtchn = evtchn_from_irq(data->irq);
 
 	if (VALID_EVTCHN(evtchn))
 		mask_evtchn(evtchn);
 }
 
-static void ack_dynirq(unsigned int irq)
+static void ack_dynirq(struct irq_data *data)
 {
-	int evtchn = evtchn_from_irq(irq);
+	int evtchn = evtchn_from_irq(data->irq);
 
-	move_masked_irq(irq);
+	move_masked_irq(data->irq);
 
 	if (VALID_EVTCHN(evtchn))
 		unmask_evtchn(evtchn);
 }
 
-static int retrigger_dynirq(unsigned int irq)
+static int retrigger_dynirq(struct irq_data *data)
 {
-	int evtchn = evtchn_from_irq(irq);
+	int evtchn = evtchn_from_irq(data->irq);
 	struct shared_info *sh = HYPERVISOR_shared_info;
 	int ret = 0;
 
@@ -1302,19 +1364,22 @@ static int retrigger_dynirq(unsigned int irq)
 	return ret;
 }
 
-static void restore_cpu_pirqs(void)
+static void restore_pirqs(void)
 {
 	int pirq, rc, irq, gsi;
 	struct physdev_map_pirq map_irq;
+	struct irq_info *info;
 
-	for (pirq = 0; pirq < nr_irqs; pirq++) {
-		irq = pirq_to_irq[pirq];
-		if (irq == -1)
+	list_for_each_entry(info, &xen_irq_list_head, list) {
+		if (info->type != IRQT_PIRQ)
 			continue;
 
+		pirq = info->u.pirq.pirq;
+		gsi = info->u.pirq.gsi;
+		irq = info->irq;
+
 		/* save/restore of PT devices doesn't work, so at this point the
 		 * only devices present are GSI based emulated devices */
-		gsi = gsi_from_irq(irq);
 		if (!gsi)
 			continue;
 
@@ -1327,14 +1392,13 @@ static void restore_cpu_pirqs(void)
 		if (rc) {
 			printk(KERN_WARNING "xen map irq failed gsi=%d irq=%d pirq=%d rc=%d\n",
 					gsi, irq, pirq, rc);
-			irq_info[irq] = mk_unbound_info();
-			pirq_to_irq[pirq] = -1;
+			xen_free_irq(irq);
 			continue;
 		}
 
 		printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
 
-		startup_pirq(irq);
+		__startup_pirq(irq);
 	}
 }
 
@@ -1358,8 +1422,7 @@ static void restore_cpu_virqs(unsigned int cpu)
 		evtchn = bind_virq.port;
 
 		/* Record the new mapping. */
-		evtchn_to_irq[evtchn] = irq;
-		irq_info[irq] = mk_virq_info(evtchn, virq);
+		xen_irq_info_virq_init(cpu, irq, evtchn, virq);
 		bind_evtchn_to_cpu(evtchn, cpu);
 	}
 }
@@ -1383,8 +1446,7 @@ static void restore_cpu_ipis(unsigned int cpu)
 		evtchn = bind_ipi.port;
 
 		/* Record the new mapping. */
-		evtchn_to_irq[evtchn] = irq;
-		irq_info[irq] = mk_ipi_info(evtchn, ipi);
+		xen_irq_info_ipi_init(cpu, irq, evtchn, ipi);
 		bind_evtchn_to_cpu(evtchn, cpu);
 	}
 }
@@ -1444,8 +1506,8 @@ void xen_poll_irq(int irq)
 
 void xen_irq_resume(void)
 {
-	unsigned int cpu, irq, evtchn;
-	struct irq_desc *desc;
+	unsigned int cpu, evtchn;
+	struct irq_info *info;
 
 	init_evtchn_cpu_bindings();
 
@@ -1454,8 +1516,8 @@ void xen_irq_resume(void)
 		mask_evtchn(evtchn);
 
 	/* No IRQ <-> event-channel mappings. */
-	for (irq = 0; irq < nr_irqs; irq++)
-		irq_info[irq].evtchn = 0; /* zap event-channel binding */
+	list_for_each_entry(info, &xen_irq_list_head, list)
+		info->evtchn = 0; /* zap event-channel binding */
 
 	for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
 		evtchn_to_irq[evtchn] = -1;
@@ -1465,66 +1527,48 @@ void xen_irq_resume(void)
 		restore_cpu_ipis(cpu);
 	}
 
-	/*
-	 * Unmask any IRQF_NO_SUSPEND IRQs which are enabled. These
-	 * are not handled by the IRQ core.
-	 */
-	for_each_irq_desc(irq, desc) {
-		if (!desc->action || !(desc->action->flags & IRQF_NO_SUSPEND))
-			continue;
-		if (desc->status & IRQ_DISABLED)
-			continue;
-
-		evtchn = evtchn_from_irq(irq);
-		if (evtchn == -1)
-			continue;
-
-		unmask_evtchn(evtchn);
-	}
-
-	restore_cpu_pirqs();
+	restore_pirqs();
 }
 
 static struct irq_chip xen_dynamic_chip __read_mostly = {
-	.name		= "xen-dyn",
+	.name			= "xen-dyn",
 
-	.disable	= disable_dynirq,
-	.mask		= disable_dynirq,
-	.unmask		= enable_dynirq,
+	.irq_disable		= disable_dynirq,
+	.irq_mask		= disable_dynirq,
+	.irq_unmask		= enable_dynirq,
 
-	.eoi		= ack_dynirq,
-	.set_affinity	= set_affinity_irq,
-	.retrigger	= retrigger_dynirq,
+	.irq_eoi		= ack_dynirq,
+	.irq_set_affinity	= set_affinity_irq,
+	.irq_retrigger		= retrigger_dynirq,
 };
 
 static struct irq_chip xen_pirq_chip __read_mostly = {
-	.name		= "xen-pirq",
+	.name			= "xen-pirq",
 
-	.startup	= startup_pirq,
-	.shutdown	= shutdown_pirq,
+	.irq_startup		= startup_pirq,
+	.irq_shutdown		= shutdown_pirq,
 
-	.enable		= enable_pirq,
-	.unmask		= enable_pirq,
+	.irq_enable		= enable_pirq,
+	.irq_unmask		= enable_pirq,
 
-	.disable	= disable_pirq,
-	.mask		= disable_pirq,
+	.irq_disable		= disable_pirq,
+	.irq_mask		= disable_pirq,
 
-	.ack		= ack_pirq,
-	.end		= end_pirq,
+	.irq_ack		= ack_pirq,
 
-	.set_affinity	= set_affinity_irq,
+	.irq_set_affinity	= set_affinity_irq,
 
-	.retrigger	= retrigger_dynirq,
+	.irq_retrigger		= retrigger_dynirq,
 };
 
 static struct irq_chip xen_percpu_chip __read_mostly = {
-	.name		= "xen-percpu",
+	.name			= "xen-percpu",
 
-	.disable	= disable_dynirq,
-	.mask		= disable_dynirq,
-	.unmask		= enable_dynirq,
+	.irq_disable		= disable_dynirq,
+	.irq_mask		= disable_dynirq,
+	.irq_unmask		= enable_dynirq,
 
-	.ack		= ack_dynirq,
+	.irq_ack		= ack_dynirq,
 };
 
 int xen_set_callback_via(uint64_t via)
@@ -1569,17 +1613,6 @@ void __init xen_init_IRQ(void)
 {
 	int i;
 
-	cpu_evtchn_mask_p = kcalloc(nr_cpu_ids, sizeof(struct cpu_evtchn_s),
-				    GFP_KERNEL);
-	irq_info = kcalloc(nr_irqs, sizeof(*irq_info), GFP_KERNEL);
-
-	/* We are using nr_irqs as the maximum number of pirq available but
-	 * that number is actually chosen by Xen and we don't know exactly
-	 * what it is. Be careful choosing high pirq numbers. */
-	pirq_to_irq = kcalloc(nr_irqs, sizeof(*pirq_to_irq), GFP_KERNEL);
-	for (i = 0; i < nr_irqs; i++)
-		pirq_to_irq[i] = -1;
-
 	evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq),
 				    GFP_KERNEL);
 	for (i = 0; i < NR_EVENT_CHANNELS; i++)
diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
new file mode 100644
index 0000000..a7ffdfe
--- /dev/null
+++ b/drivers/xen/gntalloc.c
@@ -0,0 +1,545 @@
+/******************************************************************************
+ * gntalloc.c
+ *
+ * Device for creating grant references (in user-space) that may be shared
+ * with other domains.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ */
+
+/*
+ * This driver exists to allow userspace programs in Linux to allocate kernel
+ * memory that will later be shared with another domain.  Without this device,
+ * Linux userspace programs cannot create grant references.
+ *
+ * How this stuff works:
+ *   X -> granting a page to Y
+ *   Y -> mapping the grant from X
+ *
+ *   1. X uses the gntalloc device to allocate a page of kernel memory, P.
+ *   2. X creates an entry in the grant table that says domid(Y) can access P.
+ *      This is done without a hypercall unless the grant table needs expansion.
+ *   3. X gives the grant reference identifier, GREF, to Y.
+ *   4. Y maps the page, either directly into kernel memory for use in a backend
+ *      driver, or via a the gntdev device to map into the address space of an
+ *      application running in Y. This is the first point at which Xen does any
+ *      tracking of the page.
+ *   5. A program in X mmap()s a segment of the gntalloc device that corresponds
+ *      to the shared page, and can now communicate with Y over the shared page.
+ *
+ *
+ * NOTE TO USERSPACE LIBRARIES:
+ *   The grant allocation and mmap()ing are, naturally, two separate operations.
+ *   You set up the sharing by calling the create ioctl() and then the mmap().
+ *   Teardown requires munmap() and either close() or ioctl().
+ *
+ * WARNING: Since Xen does not allow a guest to forcibly end the use of a grant
+ * reference, this device can be used to consume kernel memory by leaving grant
+ * references mapped by another domain when an application exits. Therefore,
+ * there is a global limit on the number of pages that can be allocated. When
+ * all references to the page are unmapped, it will be freed during the next
+ * grant operation.
+ */
+
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/highmem.h>
+
+#include <xen/xen.h>
+#include <xen/page.h>
+#include <xen/grant_table.h>
+#include <xen/gntalloc.h>
+#include <xen/events.h>
+
+static int limit = 1024;
+module_param(limit, int, 0644);
+MODULE_PARM_DESC(limit, "Maximum number of grants that may be allocated by "
+		"the gntalloc device");
+
+static LIST_HEAD(gref_list);
+static DEFINE_SPINLOCK(gref_lock);
+static int gref_size;
+
+struct notify_info {
+	uint16_t pgoff:12;    /* Bits 0-11: Offset of the byte to clear */
+	uint16_t flags:2;     /* Bits 12-13: Unmap notification flags */
+	int event;            /* Port (event channel) to notify */
+};
+
+/* Metadata on a grant reference. */
+struct gntalloc_gref {
+	struct list_head next_gref;  /* list entry gref_list */
+	struct list_head next_file;  /* list entry file->list, if open */
+	struct page *page;	     /* The shared page */
+	uint64_t file_index;         /* File offset for mmap() */
+	unsigned int users;          /* Use count - when zero, waiting on Xen */
+	grant_ref_t gref_id;         /* The grant reference number */
+	struct notify_info notify;   /* Unmap notification */
+};
+
+struct gntalloc_file_private_data {
+	struct list_head list;
+	uint64_t index;
+};
+
+static void __del_gref(struct gntalloc_gref *gref);
+
+static void do_cleanup(void)
+{
+	struct gntalloc_gref *gref, *n;
+	list_for_each_entry_safe(gref, n, &gref_list, next_gref) {
+		if (!gref->users)
+			__del_gref(gref);
+	}
+}
+
+static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
+	uint32_t *gref_ids, struct gntalloc_file_private_data *priv)
+{
+	int i, rc, readonly;
+	LIST_HEAD(queue_gref);
+	LIST_HEAD(queue_file);
+	struct gntalloc_gref *gref;
+
+	readonly = !(op->flags & GNTALLOC_FLAG_WRITABLE);
+	rc = -ENOMEM;
+	for (i = 0; i < op->count; i++) {
+		gref = kzalloc(sizeof(*gref), GFP_KERNEL);
+		if (!gref)
+			goto undo;
+		list_add_tail(&gref->next_gref, &queue_gref);
+		list_add_tail(&gref->next_file, &queue_file);
+		gref->users = 1;
+		gref->file_index = op->index + i * PAGE_SIZE;
+		gref->page = alloc_page(GFP_KERNEL|__GFP_ZERO);
+		if (!gref->page)
+			goto undo;
+
+		/* Grant foreign access to the page. */
+		gref->gref_id = gnttab_grant_foreign_access(op->domid,
+			pfn_to_mfn(page_to_pfn(gref->page)), readonly);
+		if (gref->gref_id < 0) {
+			rc = gref->gref_id;
+			goto undo;
+		}
+		gref_ids[i] = gref->gref_id;
+	}
+
+	/* Add to gref lists. */
+	spin_lock(&gref_lock);
+	list_splice_tail(&queue_gref, &gref_list);
+	list_splice_tail(&queue_file, &priv->list);
+	spin_unlock(&gref_lock);
+
+	return 0;
+
+undo:
+	spin_lock(&gref_lock);
+	gref_size -= (op->count - i);
+
+	list_for_each_entry(gref, &queue_file, next_file) {
+		/* __del_gref does not remove from queue_file */
+		__del_gref(gref);
+	}
+
+	/* It's possible for the target domain to map the just-allocated grant
+	 * references by blindly guessing their IDs; if this is done, then
+	 * __del_gref will leave them in the queue_gref list. They need to be
+	 * added to the global list so that we can free them when they are no
+	 * longer referenced.
+	 */
+	if (unlikely(!list_empty(&queue_gref)))
+		list_splice_tail(&queue_gref, &gref_list);
+	spin_unlock(&gref_lock);
+	return rc;
+}
+
+static void __del_gref(struct gntalloc_gref *gref)
+{
+	if (gref->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
+		uint8_t *tmp = kmap(gref->page);
+		tmp[gref->notify.pgoff] = 0;
+		kunmap(gref->page);
+	}
+	if (gref->notify.flags & UNMAP_NOTIFY_SEND_EVENT)
+		notify_remote_via_evtchn(gref->notify.event);
+
+	gref->notify.flags = 0;
+
+	if (gref->gref_id > 0) {
+		if (gnttab_query_foreign_access(gref->gref_id))
+			return;
+
+		if (!gnttab_end_foreign_access_ref(gref->gref_id, 0))
+			return;
+	}
+
+	gref_size--;
+	list_del(&gref->next_gref);
+
+	if (gref->page)
+		__free_page(gref->page);
+
+	kfree(gref);
+}
+
+/* finds contiguous grant references in a file, returns the first */
+static struct gntalloc_gref *find_grefs(struct gntalloc_file_private_data *priv,
+		uint64_t index, uint32_t count)
+{
+	struct gntalloc_gref *rv = NULL, *gref;
+	list_for_each_entry(gref, &priv->list, next_file) {
+		if (gref->file_index == index && !rv)
+			rv = gref;
+		if (rv) {
+			if (gref->file_index != index)
+				return NULL;
+			index += PAGE_SIZE;
+			count--;
+			if (count == 0)
+				return rv;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * -------------------------------------
+ *  File operations.
+ * -------------------------------------
+ */
+static int gntalloc_open(struct inode *inode, struct file *filp)
+{
+	struct gntalloc_file_private_data *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		goto out_nomem;
+	INIT_LIST_HEAD(&priv->list);
+
+	filp->private_data = priv;
+
+	pr_debug("%s: priv %p\n", __func__, priv);
+
+	return 0;
+
+out_nomem:
+	return -ENOMEM;
+}
+
+static int gntalloc_release(struct inode *inode, struct file *filp)
+{
+	struct gntalloc_file_private_data *priv = filp->private_data;
+	struct gntalloc_gref *gref;
+
+	pr_debug("%s: priv %p\n", __func__, priv);
+
+	spin_lock(&gref_lock);
+	while (!list_empty(&priv->list)) {
+		gref = list_entry(priv->list.next,
+			struct gntalloc_gref, next_file);
+		list_del(&gref->next_file);
+		gref->users--;
+		if (gref->users == 0)
+			__del_gref(gref);
+	}
+	kfree(priv);
+	spin_unlock(&gref_lock);
+
+	return 0;
+}
+
+static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
+		struct ioctl_gntalloc_alloc_gref __user *arg)
+{
+	int rc = 0;
+	struct ioctl_gntalloc_alloc_gref op;
+	uint32_t *gref_ids;
+
+	pr_debug("%s: priv %p\n", __func__, priv);
+
+	if (copy_from_user(&op, arg, sizeof(op))) {
+		rc = -EFAULT;
+		goto out;
+	}
+
+	gref_ids = kzalloc(sizeof(gref_ids[0]) * op.count, GFP_TEMPORARY);
+	if (!gref_ids) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	spin_lock(&gref_lock);
+	/* Clean up pages that were at zero (local) users but were still mapped
+	 * by remote domains. Since those pages count towards the limit that we
+	 * are about to enforce, removing them here is a good idea.
+	 */
+	do_cleanup();
+	if (gref_size + op.count > limit) {
+		spin_unlock(&gref_lock);
+		rc = -ENOSPC;
+		goto out_free;
+	}
+	gref_size += op.count;
+	op.index = priv->index;
+	priv->index += op.count * PAGE_SIZE;
+	spin_unlock(&gref_lock);
+
+	rc = add_grefs(&op, gref_ids, priv);
+	if (rc < 0)
+		goto out_free;
+
+	/* Once we finish add_grefs, it is unsafe to touch the new reference,
+	 * since it is possible for a concurrent ioctl to remove it (by guessing
+	 * its index). If the userspace application doesn't provide valid memory
+	 * to write the IDs to, then it will need to close the file in order to
+	 * release - which it will do by segfaulting when it tries to access the
+	 * IDs to close them.
+	 */
+	if (copy_to_user(arg, &op, sizeof(op))) {
+		rc = -EFAULT;
+		goto out_free;
+	}
+	if (copy_to_user(arg->gref_ids, gref_ids,
+			sizeof(gref_ids[0]) * op.count)) {
+		rc = -EFAULT;
+		goto out_free;
+	}
+
+out_free:
+	kfree(gref_ids);
+out:
+	return rc;
+}
+
+static long gntalloc_ioctl_dealloc(struct gntalloc_file_private_data *priv,
+		void __user *arg)
+{
+	int i, rc = 0;
+	struct ioctl_gntalloc_dealloc_gref op;
+	struct gntalloc_gref *gref, *n;
+
+	pr_debug("%s: priv %p\n", __func__, priv);
+
+	if (copy_from_user(&op, arg, sizeof(op))) {
+		rc = -EFAULT;
+		goto dealloc_grant_out;
+	}
+
+	spin_lock(&gref_lock);
+	gref = find_grefs(priv, op.index, op.count);
+	if (gref) {
+		/* Remove from the file list only, and decrease reference count.
+		 * The later call to do_cleanup() will remove from gref_list and
+		 * free the memory if the pages aren't mapped anywhere.
+		 */
+		for (i = 0; i < op.count; i++) {
+			n = list_entry(gref->next_file.next,
+				struct gntalloc_gref, next_file);
+			list_del(&gref->next_file);
+			gref->users--;
+			gref = n;
+		}
+	} else {
+		rc = -EINVAL;
+	}
+
+	do_cleanup();
+
+	spin_unlock(&gref_lock);
+dealloc_grant_out:
+	return rc;
+}
+
+static long gntalloc_ioctl_unmap_notify(struct gntalloc_file_private_data *priv,
+		void __user *arg)
+{
+	struct ioctl_gntalloc_unmap_notify op;
+	struct gntalloc_gref *gref;
+	uint64_t index;
+	int pgoff;
+	int rc;
+
+	if (copy_from_user(&op, arg, sizeof(op)))
+		return -EFAULT;
+
+	index = op.index & ~(PAGE_SIZE - 1);
+	pgoff = op.index & (PAGE_SIZE - 1);
+
+	spin_lock(&gref_lock);
+
+	gref = find_grefs(priv, index, 1);
+	if (!gref) {
+		rc = -ENOENT;
+		goto unlock_out;
+	}
+
+	if (op.action & ~(UNMAP_NOTIFY_CLEAR_BYTE|UNMAP_NOTIFY_SEND_EVENT)) {
+		rc = -EINVAL;
+		goto unlock_out;
+	}
+
+	gref->notify.flags = op.action;
+	gref->notify.pgoff = pgoff;
+	gref->notify.event = op.event_channel_port;
+	rc = 0;
+ unlock_out:
+	spin_unlock(&gref_lock);
+	return rc;
+}
+
+static long gntalloc_ioctl(struct file *filp, unsigned int cmd,
+		unsigned long arg)
+{
+	struct gntalloc_file_private_data *priv = filp->private_data;
+
+	switch (cmd) {
+	case IOCTL_GNTALLOC_ALLOC_GREF:
+		return gntalloc_ioctl_alloc(priv, (void __user *)arg);
+
+	case IOCTL_GNTALLOC_DEALLOC_GREF:
+		return gntalloc_ioctl_dealloc(priv, (void __user *)arg);
+
+	case IOCTL_GNTALLOC_SET_UNMAP_NOTIFY:
+		return gntalloc_ioctl_unmap_notify(priv, (void __user *)arg);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static void gntalloc_vma_close(struct vm_area_struct *vma)
+{
+	struct gntalloc_gref *gref = vma->vm_private_data;
+	if (!gref)
+		return;
+
+	spin_lock(&gref_lock);
+	gref->users--;
+	if (gref->users == 0)
+		__del_gref(gref);
+	spin_unlock(&gref_lock);
+}
+
+static struct vm_operations_struct gntalloc_vmops = {
+	.close = gntalloc_vma_close,
+};
+
+static int gntalloc_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct gntalloc_file_private_data *priv = filp->private_data;
+	struct gntalloc_gref *gref;
+	int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	int rv, i;
+
+	pr_debug("%s: priv %p, page %lu+%d\n", __func__,
+		       priv, vma->vm_pgoff, count);
+
+	if (!(vma->vm_flags & VM_SHARED)) {
+		printk(KERN_ERR "%s: Mapping must be shared.\n", __func__);
+		return -EINVAL;
+	}
+
+	spin_lock(&gref_lock);
+	gref = find_grefs(priv, vma->vm_pgoff << PAGE_SHIFT, count);
+	if (gref == NULL) {
+		rv = -ENOENT;
+		pr_debug("%s: Could not find grant reference",
+				__func__);
+		goto out_unlock;
+	}
+
+	vma->vm_private_data = gref;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_flags |= VM_DONTCOPY;
+	vma->vm_flags |= VM_PFNMAP | VM_PFN_AT_MMAP;
+
+	vma->vm_ops = &gntalloc_vmops;
+
+	for (i = 0; i < count; i++) {
+		gref->users++;
+		rv = vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
+				gref->page);
+		if (rv)
+			goto out_unlock;
+
+		gref = list_entry(gref->next_file.next,
+				struct gntalloc_gref, next_file);
+	}
+	rv = 0;
+
+out_unlock:
+	spin_unlock(&gref_lock);
+	return rv;
+}
+
+static const struct file_operations gntalloc_fops = {
+	.owner = THIS_MODULE,
+	.open = gntalloc_open,
+	.release = gntalloc_release,
+	.unlocked_ioctl = gntalloc_ioctl,
+	.mmap = gntalloc_mmap
+};
+
+/*
+ * -------------------------------------
+ * Module creation/destruction.
+ * -------------------------------------
+ */
+static struct miscdevice gntalloc_miscdev = {
+	.minor	= MISC_DYNAMIC_MINOR,
+	.name	= "xen/gntalloc",
+	.fops	= &gntalloc_fops,
+};
+
+static int __init gntalloc_init(void)
+{
+	int err;
+
+	if (!xen_domain())
+		return -ENODEV;
+
+	err = misc_register(&gntalloc_miscdev);
+	if (err != 0) {
+		printk(KERN_ERR "Could not register misc gntalloc device\n");
+		return err;
+	}
+
+	pr_debug("Created grant allocation device at %d,%d\n",
+			MISC_MAJOR, gntalloc_miscdev.minor);
+
+	return 0;
+}
+
+static void __exit gntalloc_exit(void)
+{
+	misc_deregister(&gntalloc_miscdev);
+}
+
+module_init(gntalloc_init);
+module_exit(gntalloc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Carter Weatherly <carter.weatherly@jhuapl.edu>, "
+		"Daniel De Graaf <dgdegra@tycho.nsa.gov>");
+MODULE_DESCRIPTION("User-space grant reference allocator driver");
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 1e31cdc..017ce60 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -32,10 +32,13 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
+#include <linux/highmem.h>
 
 #include <xen/xen.h>
 #include <xen/grant_table.h>
+#include <xen/balloon.h>
 #include <xen/gntdev.h>
+#include <xen/events.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 #include <asm/xen/page.h>
@@ -45,35 +48,46 @@ MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, "
 	      "Gerd Hoffmann <kraxel@redhat.com>");
 MODULE_DESCRIPTION("User-space granted page access driver");
 
-static int limit = 1024;
+static int limit = 1024*1024;
 module_param(limit, int, 0644);
-MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped at "
-		"once by a gntdev instance");
+MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by "
+		"the gntdev device");
+
+static atomic_t pages_mapped = ATOMIC_INIT(0);
+
+static int use_ptemod;
 
 struct gntdev_priv {
 	struct list_head maps;
-	uint32_t used;
-	uint32_t limit;
 	/* lock protects maps from concurrent changes */
 	spinlock_t lock;
 	struct mm_struct *mm;
 	struct mmu_notifier mn;
 };
 
+struct unmap_notify {
+	int flags;
+	/* Address relative to the start of the grant_map */
+	int addr;
+	int event;
+};
+
 struct grant_map {
 	struct list_head next;
-	struct gntdev_priv *priv;
 	struct vm_area_struct *vma;
 	int index;
 	int count;
 	int flags;
-	int is_mapped;
+	atomic_t users;
+	struct unmap_notify notify;
 	struct ioctl_gntdev_grant_ref *grants;
 	struct gnttab_map_grant_ref   *map_ops;
 	struct gnttab_unmap_grant_ref *unmap_ops;
 	struct page **pages;
 };
 
+static int unmap_grant_pages(struct grant_map *map, int offset, int pages);
+
 /* ------------------------------------------------------------------ */
 
 static void gntdev_print_maps(struct gntdev_priv *priv,
@@ -82,9 +96,7 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
 #ifdef DEBUG
 	struct grant_map *map;
 
-	pr_debug("maps list (priv %p, usage %d/%d)\n",
-	       priv, priv->used, priv->limit);
-
+	pr_debug("%s: maps list (priv %p)\n", __func__, priv);
 	list_for_each_entry(map, &priv->maps, next)
 		pr_debug("  index %2d, count %2d %s\n",
 		       map->index, map->count,
@@ -111,27 +123,21 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 	    NULL == add->pages)
 		goto err;
 
+	if (alloc_xenballooned_pages(count, add->pages))
+		goto err;
+
 	for (i = 0; i < count; i++) {
-		add->pages[i] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
-		if (add->pages[i] == NULL)
-			goto err;
+		add->map_ops[i].handle = -1;
+		add->unmap_ops[i].handle = -1;
 	}
 
 	add->index = 0;
 	add->count = count;
-	add->priv  = priv;
-
-	if (add->count + priv->used > priv->limit)
-		goto err;
+	atomic_set(&add->users, 1);
 
 	return add;
 
 err:
-	if (add->pages)
-		for (i = 0; i < count; i++) {
-			if (add->pages[i])
-				__free_page(add->pages[i]);
-		}
 	kfree(add->pages);
 	kfree(add->grants);
 	kfree(add->map_ops);
@@ -154,7 +160,6 @@ static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add)
 	list_add_tail(&add->next, &priv->maps);
 
 done:
-	priv->used += add->count;
 	gntdev_print_maps(priv, "[new]", add->index);
 }
 
@@ -166,57 +171,33 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv,
 	list_for_each_entry(map, &priv->maps, next) {
 		if (map->index != index)
 			continue;
-		if (map->count != count)
+		if (count && map->count != count)
 			continue;
 		return map;
 	}
 	return NULL;
 }
 
-static struct grant_map *gntdev_find_map_vaddr(struct gntdev_priv *priv,
-					       unsigned long vaddr)
+static void gntdev_put_map(struct grant_map *map)
 {
-	struct grant_map *map;
-
-	list_for_each_entry(map, &priv->maps, next) {
-		if (!map->vma)
-			continue;
-		if (vaddr < map->vma->vm_start)
-			continue;
-		if (vaddr >= map->vma->vm_end)
-			continue;
-		return map;
-	}
-	return NULL;
-}
-
-static int gntdev_del_map(struct grant_map *map)
-{
-	int i;
+	if (!map)
+		return;
 
-	if (map->vma)
-		return -EBUSY;
-	for (i = 0; i < map->count; i++)
-		if (map->unmap_ops[i].handle)
-			return -EBUSY;
+	if (!atomic_dec_and_test(&map->users))
+		return;
 
-	map->priv->used -= map->count;
-	list_del(&map->next);
-	return 0;
-}
+	atomic_sub(map->count, &pages_mapped);
 
-static void gntdev_free_map(struct grant_map *map)
-{
-	int i;
+	if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) {
+		notify_remote_via_evtchn(map->notify.event);
+	}
 
-	if (!map)
-		return;
+	if (map->pages) {
+		if (!use_ptemod)
+			unmap_grant_pages(map, 0, map->count);
 
-	if (map->pages)
-		for (i = 0; i < map->count; i++) {
-			if (map->pages[i])
-				__free_page(map->pages[i]);
-		}
+		free_xenballooned_pages(map->count, map->pages);
+	}
 	kfree(map->pages);
 	kfree(map->grants);
 	kfree(map->map_ops);
@@ -231,18 +212,17 @@ static int find_grant_ptes(pte_t *pte, pgtable_t token,
 {
 	struct grant_map *map = data;
 	unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT;
+	int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte;
 	u64 pte_maddr;
 
 	BUG_ON(pgnr >= map->count);
 	pte_maddr = arbitrary_virt_to_machine(pte).maddr;
 
-	gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr,
-			  GNTMAP_contains_pte | map->flags,
+	gnttab_set_map_op(&map->map_ops[pgnr], pte_maddr, flags,
 			  map->grants[pgnr].ref,
 			  map->grants[pgnr].domid);
-	gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr,
-			    GNTMAP_contains_pte | map->flags,
-			    0 /* handle */);
+	gnttab_set_unmap_op(&map->unmap_ops[pgnr], pte_maddr, flags,
+			    -1 /* handle */);
 	return 0;
 }
 
@@ -250,6 +230,21 @@ static int map_grant_pages(struct grant_map *map)
 {
 	int i, err = 0;
 
+	if (!use_ptemod) {
+		/* Note: it could already be mapped */
+		if (map->map_ops[0].handle != -1)
+			return 0;
+		for (i = 0; i < map->count; i++) {
+			unsigned long addr = (unsigned long)
+				pfn_to_kaddr(page_to_pfn(map->pages[i]));
+			gnttab_set_map_op(&map->map_ops[i], addr, map->flags,
+				map->grants[i].ref,
+				map->grants[i].domid);
+			gnttab_set_unmap_op(&map->unmap_ops[i], addr,
+				map->flags, -1 /* handle */);
+		}
+	}
+
 	pr_debug("map %d+%d\n", map->index, map->count);
 	err = gnttab_map_refs(map->map_ops, map->pages, map->count);
 	if (err)
@@ -258,28 +253,81 @@ static int map_grant_pages(struct grant_map *map)
 	for (i = 0; i < map->count; i++) {
 		if (map->map_ops[i].status)
 			err = -EINVAL;
-		map->unmap_ops[i].handle = map->map_ops[i].handle;
+		else {
+			BUG_ON(map->map_ops[i].handle == -1);
+			map->unmap_ops[i].handle = map->map_ops[i].handle;
+			pr_debug("map handle=%d\n", map->map_ops[i].handle);
+		}
 	}
 	return err;
 }
 
-static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
+static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
 {
 	int i, err = 0;
 
-	pr_debug("map %d+%d [%d+%d]\n", map->index, map->count, offset, pages);
-	err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages, pages);
+	if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
+		int pgno = (map->notify.addr >> PAGE_SHIFT);
+		if (pgno >= offset && pgno < offset + pages && use_ptemod) {
+			void __user *tmp = (void __user *)
+				map->vma->vm_start + map->notify.addr;
+			err = copy_to_user(tmp, &err, 1);
+			if (err)
+				return err;
+			map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
+		} else if (pgno >= offset && pgno < offset + pages) {
+			uint8_t *tmp = kmap(map->pages[pgno]);
+			tmp[map->notify.addr & (PAGE_SIZE-1)] = 0;
+			kunmap(map->pages[pgno]);
+			map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
+		}
+	}
+
+	err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, pages);
 	if (err)
 		return err;
 
 	for (i = 0; i < pages; i++) {
 		if (map->unmap_ops[offset+i].status)
 			err = -EINVAL;
-		map->unmap_ops[offset+i].handle = 0;
+		pr_debug("unmap handle=%d st=%d\n",
+			map->unmap_ops[offset+i].handle,
+			map->unmap_ops[offset+i].status);
+		map->unmap_ops[offset+i].handle = -1;
 	}
 	return err;
 }
 
+static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
+{
+	int range, err = 0;
+
+	pr_debug("unmap %d+%d [%d+%d]\n", map->index, map->count, offset, pages);
+
+	/* It is possible the requested range will have a "hole" where we
+	 * already unmapped some of the grants. Only unmap valid ranges.
+	 */
+	while (pages && !err) {
+		while (pages && map->unmap_ops[offset].handle == -1) {
+			offset++;
+			pages--;
+		}
+		range = 0;
+		while (range < pages) {
+			if (map->unmap_ops[offset+range].handle == -1) {
+				range--;
+				break;
+			}
+			range++;
+		}
+		err = __unmap_grant_pages(map, offset, range);
+		offset += range;
+		pages -= range;
+	}
+
+	return err;
+}
+
 /* ------------------------------------------------------------------ */
 
 static void gntdev_vma_close(struct vm_area_struct *vma)
@@ -287,22 +335,13 @@ static void gntdev_vma_close(struct vm_area_struct *vma)
 	struct grant_map *map = vma->vm_private_data;
 
 	pr_debug("close %p\n", vma);
-	map->is_mapped = 0;
 	map->vma = NULL;
 	vma->vm_private_data = NULL;
-}
-
-static int gntdev_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	pr_debug("vaddr %p, pgoff %ld (shouldn't happen)\n",
-			vmf->virtual_address, vmf->pgoff);
-	vmf->flags = VM_FAULT_ERROR;
-	return 0;
+	gntdev_put_map(map);
 }
 
 static struct vm_operations_struct gntdev_vmops = {
 	.close = gntdev_vma_close,
-	.fault = gntdev_vma_fault,
 };
 
 /* ------------------------------------------------------------------ */
@@ -320,8 +359,6 @@ static void mn_invl_range_start(struct mmu_notifier *mn,
 	list_for_each_entry(map, &priv->maps, next) {
 		if (!map->vma)
 			continue;
-		if (!map->is_mapped)
-			continue;
 		if (map->vma->vm_start >= end)
 			continue;
 		if (map->vma->vm_end <= start)
@@ -386,16 +423,17 @@ static int gntdev_open(struct inode *inode, struct file *flip)
 
 	INIT_LIST_HEAD(&priv->maps);
 	spin_lock_init(&priv->lock);
-	priv->limit = limit;
 
-	priv->mm = get_task_mm(current);
-	if (!priv->mm) {
-		kfree(priv);
-		return -ENOMEM;
+	if (use_ptemod) {
+		priv->mm = get_task_mm(current);
+		if (!priv->mm) {
+			kfree(priv);
+			return -ENOMEM;
+		}
+		priv->mn.ops = &gntdev_mmu_ops;
+		ret = mmu_notifier_register(&priv->mn, priv->mm);
+		mmput(priv->mm);
 	}
-	priv->mn.ops = &gntdev_mmu_ops;
-	ret = mmu_notifier_register(&priv->mn, priv->mm);
-	mmput(priv->mm);
 
 	if (ret) {
 		kfree(priv);
@@ -412,21 +450,19 @@ static int gntdev_release(struct inode *inode, struct file *flip)
 {
 	struct gntdev_priv *priv = flip->private_data;
 	struct grant_map *map;
-	int err;
 
 	pr_debug("priv %p\n", priv);
 
 	spin_lock(&priv->lock);
 	while (!list_empty(&priv->maps)) {
 		map = list_entry(priv->maps.next, struct grant_map, next);
-		err = gntdev_del_map(map);
-		if (WARN_ON(err))
-			gntdev_free_map(map);
-
+		list_del(&map->next);
+		gntdev_put_map(map);
 	}
 	spin_unlock(&priv->lock);
 
-	mmu_notifier_unregister(&priv->mn, priv->mm);
+	if (use_ptemod)
+		mmu_notifier_unregister(&priv->mn, priv->mm);
 	kfree(priv);
 	return 0;
 }
@@ -443,16 +479,21 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
 	pr_debug("priv %p, add %d\n", priv, op.count);
 	if (unlikely(op.count <= 0))
 		return -EINVAL;
-	if (unlikely(op.count > priv->limit))
-		return -EINVAL;
 
 	err = -ENOMEM;
 	map = gntdev_alloc_map(priv, op.count);
 	if (!map)
 		return err;
+
+	if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) {
+		pr_debug("can't map: over limit\n");
+		gntdev_put_map(map);
+		return err;
+	}
+
 	if (copy_from_user(map->grants, &u->refs,
 			   sizeof(map->grants[0]) * op.count) != 0) {
-		gntdev_free_map(map);
+		gntdev_put_map(map);
 		return err;
 	}
 
@@ -461,13 +502,9 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
 	op.index = map->index << PAGE_SHIFT;
 	spin_unlock(&priv->lock);
 
-	if (copy_to_user(u, &op, sizeof(op)) != 0) {
-		spin_lock(&priv->lock);
-		gntdev_del_map(map);
-		spin_unlock(&priv->lock);
-		gntdev_free_map(map);
-		return err;
-	}
+	if (copy_to_user(u, &op, sizeof(op)) != 0)
+		return -EFAULT;
+
 	return 0;
 }
 
@@ -484,11 +521,12 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
 
 	spin_lock(&priv->lock);
 	map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
-	if (map)
-		err = gntdev_del_map(map);
+	if (map) {
+		list_del(&map->next);
+		gntdev_put_map(map);
+		err = 0;
+	}
 	spin_unlock(&priv->lock);
-	if (!err)
-		gntdev_free_map(map);
 	return err;
 }
 
@@ -496,43 +534,66 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv,
 					      struct ioctl_gntdev_get_offset_for_vaddr __user *u)
 {
 	struct ioctl_gntdev_get_offset_for_vaddr op;
+	struct vm_area_struct *vma;
 	struct grant_map *map;
 
 	if (copy_from_user(&op, u, sizeof(op)) != 0)
 		return -EFAULT;
 	pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr);
 
-	spin_lock(&priv->lock);
-	map = gntdev_find_map_vaddr(priv, op.vaddr);
-	if (map == NULL ||
-	    map->vma->vm_start != op.vaddr) {
-		spin_unlock(&priv->lock);
+	vma = find_vma(current->mm, op.vaddr);
+	if (!vma || vma->vm_ops != &gntdev_vmops)
 		return -EINVAL;
-	}
+
+	map = vma->vm_private_data;
+	if (!map)
+		return -EINVAL;
+
 	op.offset = map->index << PAGE_SHIFT;
 	op.count = map->count;
-	spin_unlock(&priv->lock);
 
 	if (copy_to_user(u, &op, sizeof(op)) != 0)
 		return -EFAULT;
 	return 0;
 }
 
-static long gntdev_ioctl_set_max_grants(struct gntdev_priv *priv,
-					struct ioctl_gntdev_set_max_grants __user *u)
+static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
 {
-	struct ioctl_gntdev_set_max_grants op;
+	struct ioctl_gntdev_unmap_notify op;
+	struct grant_map *map;
+	int rc;
 
-	if (copy_from_user(&op, u, sizeof(op)) != 0)
+	if (copy_from_user(&op, u, sizeof(op)))
 		return -EFAULT;
-	pr_debug("priv %p, limit %d\n", priv, op.count);
-	if (op.count > limit)
-		return -E2BIG;
+
+	if (op.action & ~(UNMAP_NOTIFY_CLEAR_BYTE|UNMAP_NOTIFY_SEND_EVENT))
+		return -EINVAL;
 
 	spin_lock(&priv->lock);
-	priv->limit = op.count;
+
+	list_for_each_entry(map, &priv->maps, next) {
+		uint64_t begin = map->index << PAGE_SHIFT;
+		uint64_t end = (map->index + map->count) << PAGE_SHIFT;
+		if (op.index >= begin && op.index < end)
+			goto found;
+	}
+	rc = -ENOENT;
+	goto unlock_out;
+
+ found:
+	if ((op.action & UNMAP_NOTIFY_CLEAR_BYTE) &&
+			(map->flags & GNTMAP_readonly)) {
+		rc = -EINVAL;
+		goto unlock_out;
+	}
+
+	map->notify.flags = op.action;
+	map->notify.addr = op.index - (map->index << PAGE_SHIFT);
+	map->notify.event = op.event_channel_port;
+	rc = 0;
+ unlock_out:
 	spin_unlock(&priv->lock);
-	return 0;
+	return rc;
 }
 
 static long gntdev_ioctl(struct file *flip,
@@ -551,8 +612,8 @@ static long gntdev_ioctl(struct file *flip,
 	case IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR:
 		return gntdev_ioctl_get_offset_for_vaddr(priv, ptr);
 
-	case IOCTL_GNTDEV_SET_MAX_GRANTS:
-		return gntdev_ioctl_set_max_grants(priv, ptr);
+	case IOCTL_GNTDEV_SET_UNMAP_NOTIFY:
+		return gntdev_ioctl_notify(priv, ptr);
 
 	default:
 		pr_debug("priv %p, unknown cmd %x\n", priv, cmd);
@@ -568,7 +629,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 	int index = vma->vm_pgoff;
 	int count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	struct grant_map *map;
-	int err = -EINVAL;
+	int i, err = -EINVAL;
 
 	if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
 		return -EINVAL;
@@ -580,47 +641,70 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
 	map = gntdev_find_map_index(priv, index, count);
 	if (!map)
 		goto unlock_out;
-	if (map->vma)
+	if (use_ptemod && map->vma)
 		goto unlock_out;
-	if (priv->mm != vma->vm_mm) {
+	if (use_ptemod && priv->mm != vma->vm_mm) {
 		printk(KERN_WARNING "Huh? Other mm?\n");
 		goto unlock_out;
 	}
 
+	atomic_inc(&map->users);
+
 	vma->vm_ops = &gntdev_vmops;
 
 	vma->vm_flags |= VM_RESERVED|VM_DONTCOPY|VM_DONTEXPAND|VM_PFNMAP;
 
 	vma->vm_private_data = map;
-	map->vma = vma;
 
-	map->flags = GNTMAP_host_map | GNTMAP_application_map;
-	if (!(vma->vm_flags & VM_WRITE))
-		map->flags |= GNTMAP_readonly;
+	if (use_ptemod)
+		map->vma = vma;
+
+	if (map->flags) {
+		if ((vma->vm_flags & VM_WRITE) &&
+				(map->flags & GNTMAP_readonly))
+			return -EINVAL;
+	} else {
+		map->flags = GNTMAP_host_map;
+		if (!(vma->vm_flags & VM_WRITE))
+			map->flags |= GNTMAP_readonly;
+	}
 
 	spin_unlock(&priv->lock);
 
-	err = apply_to_page_range(vma->vm_mm, vma->vm_start,
-				  vma->vm_end - vma->vm_start,
-				  find_grant_ptes, map);
-	if (err) {
-		printk(KERN_WARNING "find_grant_ptes() failure.\n");
-		return err;
+	if (use_ptemod) {
+		err = apply_to_page_range(vma->vm_mm, vma->vm_start,
+					  vma->vm_end - vma->vm_start,
+					  find_grant_ptes, map);
+		if (err) {
+			printk(KERN_WARNING "find_grant_ptes() failure.\n");
+			goto out_put_map;
+		}
 	}
 
 	err = map_grant_pages(map);
-	if (err) {
-		printk(KERN_WARNING "map_grant_pages() failure.\n");
-		return err;
-	}
+	if (err)
+		goto out_put_map;
 
-	map->is_mapped = 1;
+	if (!use_ptemod) {
+		for (i = 0; i < count; i++) {
+			err = vm_insert_page(vma, vma->vm_start + i*PAGE_SIZE,
+				map->pages[i]);
+			if (err)
+				goto out_put_map;
+		}
+	}
 
 	return 0;
 
 unlock_out:
 	spin_unlock(&priv->lock);
 	return err;
+
+out_put_map:
+	if (use_ptemod)
+		map->vma = NULL;
+	gntdev_put_map(map);
+	return err;
 }
 
 static const struct file_operations gntdev_fops = {
@@ -646,6 +730,8 @@ static int __init gntdev_init(void)
 	if (!xen_domain())
 		return -ENODEV;
 
+	use_ptemod = xen_pv_domain();
+
 	err = misc_register(&gntdev_miscdev);
 	if (err != 0) {
 		printk(KERN_ERR "Could not register gntdev device\n");
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 9ef54eb..3745a31 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -458,7 +458,14 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 	if (ret)
 		return ret;
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return ret;
+
 	for (i = 0; i < count; i++) {
+		/* Do not add to override if the map failed. */
+		if (map_ops[i].status)
+			continue;
+
 		/* m2p override only supported for GNTMAP_contains_pte mappings */
 		if (!(map_ops[i].flags & GNTMAP_contains_pte))
 			continue;
@@ -483,6 +490,9 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
 	if (ret)
 		return ret;
 
+	if (xen_feature(XENFEAT_auto_translated_physmap))
+		return ret;
+
 	for (i = 0; i < count; i++) {
 		ret = m2p_remove_override(pages[i]);
 		if (ret)
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 2417727..95143dd 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -34,68 +34,62 @@ enum shutdown_state {
 /* Ignore multiple shutdown requests. */
 static enum shutdown_state shutting_down = SHUTDOWN_INVALID;
 
-#ifdef CONFIG_PM_SLEEP
-static int xen_hvm_suspend(void *data)
-{
-	int err;
-	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
-	int *cancelled = data;
-
-	BUG_ON(!irqs_disabled());
-
-	err = sysdev_suspend(PMSG_SUSPEND);
-	if (err) {
-		printk(KERN_ERR "xen_hvm_suspend: sysdev_suspend failed: %d\n",
-		       err);
-		return err;
-	}
-
-	*cancelled = HYPERVISOR_sched_op(SCHEDOP_shutdown, &r);
+struct suspend_info {
+	int cancelled;
+	unsigned long arg; /* extra hypercall argument */
+	void (*pre)(void);
+	void (*post)(int cancelled);
+};
 
-	xen_hvm_post_suspend(*cancelled);
+static void xen_hvm_post_suspend(int cancelled)
+{
+	xen_arch_hvm_post_suspend(cancelled);
 	gnttab_resume();
+}
 
-	if (!*cancelled) {
-		xen_irq_resume();
-		xen_console_resume();
-		xen_timer_resume();
-	}
-
-	sysdev_resume();
+static void xen_pre_suspend(void)
+{
+	xen_mm_pin_all();
+	gnttab_suspend();
+	xen_arch_pre_suspend();
+}
 
-	return 0;
+static void xen_post_suspend(int cancelled)
+{
+	xen_arch_post_suspend(cancelled);
+	gnttab_resume();
+	xen_mm_unpin_all();
 }
 
+#ifdef CONFIG_HIBERNATION
 static int xen_suspend(void *data)
 {
+	struct suspend_info *si = data;
 	int err;
-	int *cancelled = data;
 
 	BUG_ON(!irqs_disabled());
 
-	err = sysdev_suspend(PMSG_SUSPEND);
+	err = sysdev_suspend(PMSG_FREEZE);
 	if (err) {
 		printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
 			err);
 		return err;
 	}
 
-	xen_mm_pin_all();
-	gnttab_suspend();
-	xen_pre_suspend();
+	if (si->pre)
+		si->pre();
 
 	/*
 	 * This hypercall returns 1 if suspend was cancelled
 	 * or the domain was merely checkpointed, and 0 if it
 	 * is resuming in a new domain.
 	 */
-	*cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+	si->cancelled = HYPERVISOR_suspend(si->arg);
 
-	xen_post_suspend(*cancelled);
-	gnttab_resume();
-	xen_mm_unpin_all();
+	if (si->post)
+		si->post(si->cancelled);
 
-	if (!*cancelled) {
+	if (!si->cancelled) {
 		xen_irq_resume();
 		xen_console_resume();
 		xen_timer_resume();
@@ -109,7 +103,7 @@ static int xen_suspend(void *data)
 static void do_suspend(void)
 {
 	int err;
-	int cancelled = 1;
+	struct suspend_info si;
 
 	shutting_down = SHUTDOWN_SUSPEND;
 
@@ -124,7 +118,7 @@ static void do_suspend(void)
 	}
 #endif
 
-	err = dpm_suspend_start(PMSG_SUSPEND);
+	err = dpm_suspend_start(PMSG_FREEZE);
 	if (err) {
 		printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
 		goto out_thaw;
@@ -133,32 +127,41 @@ static void do_suspend(void)
 	printk(KERN_DEBUG "suspending xenstore...\n");
 	xs_suspend();
 
-	err = dpm_suspend_noirq(PMSG_SUSPEND);
+	err = dpm_suspend_noirq(PMSG_FREEZE);
 	if (err) {
 		printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
 		goto out_resume;
 	}
 
-	if (xen_hvm_domain())
-		err = stop_machine(xen_hvm_suspend, &cancelled, cpumask_of(0));
-	else
-		err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));
+	si.cancelled = 1;
 
-	dpm_resume_noirq(PMSG_RESUME);
+	if (xen_hvm_domain()) {
+		si.arg = 0UL;
+		si.pre = NULL;
+		si.post = &xen_hvm_post_suspend;
+	} else {
+		si.arg = virt_to_mfn(xen_start_info);
+		si.pre = &xen_pre_suspend;
+		si.post = &xen_post_suspend;
+	}
+
+	err = stop_machine(xen_suspend, &si, cpumask_of(0));
+
+	dpm_resume_noirq(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
 
 	if (err) {
 		printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
-		cancelled = 1;
+		si.cancelled = 1;
 	}
 
 out_resume:
-	if (!cancelled) {
+	if (!si.cancelled) {
 		xen_arch_resume();
 		xs_resume();
 	} else
 		xs_suspend_cancel();
 
-	dpm_resume_end(PMSG_RESUME);
+	dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
 
 	/* Make sure timer events get retriggered on all CPUs */
 	clock_was_set();
@@ -170,7 +173,24 @@ out:
 #endif
 	shutting_down = SHUTDOWN_INVALID;
 }
-#endif	/* CONFIG_PM_SLEEP */
+#endif	/* CONFIG_HIBERNATION */
+
+struct shutdown_handler {
+	const char *command;
+	void (*cb)(void);
+};
+
+static void do_poweroff(void)
+{
+	shutting_down = SHUTDOWN_POWEROFF;
+	orderly_poweroff(false);
+}
+
+static void do_reboot(void)
+{
+	shutting_down = SHUTDOWN_POWEROFF; /* ? */
+	ctrl_alt_del();
+}
 
 static void shutdown_handler(struct xenbus_watch *watch,
 			     const char **vec, unsigned int len)
@@ -178,6 +198,16 @@ static void shutdown_handler(struct xenbus_watch *watch,
 	char *str;
 	struct xenbus_transaction xbt;
 	int err;
+	static struct shutdown_handler handlers[] = {
+		{ "poweroff",	do_poweroff },
+		{ "halt",	do_poweroff },
+		{ "reboot",	do_reboot   },
+#ifdef CONFIG_HIBERNATION
+		{ "suspend",	do_suspend  },
+#endif
+		{NULL, NULL},
+	};
+	static struct shutdown_handler *handler;
 
 	if (shutting_down != SHUTDOWN_INVALID)
 		return;
@@ -194,7 +224,14 @@ static void shutdown_handler(struct xenbus_watch *watch,
 		return;
 	}
 
-	xenbus_write(xbt, "control", "shutdown", "");
+	for (handler = &handlers[0]; handler->command; handler++) {
+		if (strcmp(str, handler->command) == 0)
+			break;
+	}
+
+	/* Only acknowledge commands which we are prepared to handle. */
+	if (handler->cb)
+		xenbus_write(xbt, "control", "shutdown", "");
 
 	err = xenbus_transaction_end(xbt, 0);
 	if (err == -EAGAIN) {
@@ -202,17 +239,8 @@ static void shutdown_handler(struct xenbus_watch *watch,
 		goto again;
 	}
 
-	if (strcmp(str, "poweroff") == 0 ||
-	    strcmp(str, "halt") == 0) {
-		shutting_down = SHUTDOWN_POWEROFF;
-		orderly_poweroff(false);
-	} else if (strcmp(str, "reboot") == 0) {
-		shutting_down = SHUTDOWN_POWEROFF; /* ? */
-		ctrl_alt_del();
-#ifdef CONFIG_PM_SLEEP
-	} else if (strcmp(str, "suspend") == 0) {
-		do_suspend();
-#endif
+	if (handler->cb) {
+		handler->cb();
 	} else {
 		printk(KERN_INFO "Ignoring shutdown request: %s\n", str);
 		shutting_down = SHUTDOWN_INVALID;
@@ -291,27 +319,18 @@ static int shutdown_event(struct notifier_block *notifier,
 	return NOTIFY_DONE;
 }
 
-static int __init __setup_shutdown_event(void)
-{
-	/* Delay initialization in the PV on HVM case */
-	if (xen_hvm_domain())
-		return 0;
-
-	if (!xen_pv_domain())
-		return -ENODEV;
-
-	return xen_setup_shutdown_event();
-}
-
 int xen_setup_shutdown_event(void)
 {
 	static struct notifier_block xenstore_notifier = {
 		.notifier_call = shutdown_event
 	};
+
+	if (!xen_domain())
+		return -ENODEV;
 	register_xenstore_notifier(&xenstore_notifier);
 
 	return 0;
 }
 EXPORT_SYMBOL_GPL(xen_setup_shutdown_event);
 
-subsys_initcall(__setup_shutdown_event);
+subsys_initcall(xen_setup_shutdown_event);
diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c
index afbe041..319dd0a 100644
--- a/drivers/xen/platform-pci.c
+++ b/drivers/xen/platform-pci.c
@@ -156,9 +156,6 @@ static int __devinit platform_pci_init(struct pci_dev *pdev,
 	if (ret)
 		goto out;
 	xenbus_probe(NULL);
-	ret = xen_setup_shutdown_event();
-	if (ret)
-		goto out;
 	return 0;
 
 out:
diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c
new file mode 100644
index 0000000..a4ff225
--- /dev/null
+++ b/drivers/xen/xen-balloon.c
@@ -0,0 +1,256 @@
+/******************************************************************************
+ * Xen balloon driver - enables returning/claiming memory to/from Xen.
+ *
+ * Copyright (c) 2003, B Dragovic
+ * Copyright (c) 2003-2004, M Williamson, K Fraser
+ * Copyright (c) 2005 Dan M. Smith, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sysdev.h>
+#include <linux/capability.h>
+
+#include <xen/xen.h>
+#include <xen/interface/xen.h>
+#include <xen/balloon.h>
+#include <xen/xenbus.h>
+#include <xen/features.h>
+#include <xen/page.h>
+
+#define PAGES2KB(_p) ((_p)<<(PAGE_SHIFT-10))
+
+#define BALLOON_CLASS_NAME "xen_memory"
+
+static struct sys_device balloon_sysdev;
+
+static int register_balloon(struct sys_device *sysdev);
+
+static struct xenbus_watch target_watch =
+{
+	.node = "memory/target"
+};
+
+/* React to a change in the target key */
+static void watch_target(struct xenbus_watch *watch,
+			 const char **vec, unsigned int len)
+{
+	unsigned long long new_target;
+	int err;
+
+	err = xenbus_scanf(XBT_NIL, "memory", "target", "%llu", &new_target);
+	if (err != 1) {
+		/* This is ok (for domain0 at least) - so just return */
+		return;
+	}
+
+	/* The given memory/target value is in KiB, so it needs converting to
+	 * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
+	 */
+	balloon_set_new_target(new_target >> (PAGE_SHIFT - 10));
+}
+
+static int balloon_init_watcher(struct notifier_block *notifier,
+				unsigned long event,
+				void *data)
+{
+	int err;
+
+	err = register_xenbus_watch(&target_watch);
+	if (err)
+		printk(KERN_ERR "Failed to set balloon watcher\n");
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block xenstore_notifier;
+
+static int __init balloon_init(void)
+{
+	if (!xen_domain())
+		return -ENODEV;
+
+	pr_info("xen-balloon: Initialising balloon driver.\n");
+
+	register_balloon(&balloon_sysdev);
+
+	target_watch.callback = watch_target;
+	xenstore_notifier.notifier_call = balloon_init_watcher;
+
+	register_xenstore_notifier(&xenstore_notifier);
+
+	return 0;
+}
+subsys_initcall(balloon_init);
+
+static void balloon_exit(void)
+{
+    /* XXX - release balloon here */
+    return;
+}
+
+module_exit(balloon_exit);
+
+#define BALLOON_SHOW(name, format, args...)				\
+	static ssize_t show_##name(struct sys_device *dev,		\
+				   struct sysdev_attribute *attr,	\
+				   char *buf)				\
+	{								\
+		return sprintf(buf, format, ##args);			\
+	}								\
+	static SYSDEV_ATTR(name, S_IRUGO, show_##name, NULL)
+
+BALLOON_SHOW(current_kb, "%lu\n", PAGES2KB(balloon_stats.current_pages));
+BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
+BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
+
+static SYSDEV_ULONG_ATTR(schedule_delay, 0444, balloon_stats.schedule_delay);
+static SYSDEV_ULONG_ATTR(max_schedule_delay, 0644, balloon_stats.max_schedule_delay);
+static SYSDEV_ULONG_ATTR(retry_count, 0444, balloon_stats.retry_count);
+static SYSDEV_ULONG_ATTR(max_retry_count, 0644, balloon_stats.max_retry_count);
+
+static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.target_pages));
+}
+
+static ssize_t store_target_kb(struct sys_device *dev,
+			       struct sysdev_attribute *attr,
+			       const char *buf,
+			       size_t count)
+{
+	char *endchar;
+	unsigned long long target_bytes;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	target_bytes = simple_strtoull(buf, &endchar, 0) * 1024;
+
+	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+
+	return count;
+}
+
+static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
+		   show_target_kb, store_target_kb);
+
+
+static ssize_t show_target(struct sys_device *dev, struct sysdev_attribute *attr,
+			      char *buf)
+{
+	return sprintf(buf, "%llu\n",
+		       (unsigned long long)balloon_stats.target_pages
+		       << PAGE_SHIFT);
+}
+
+static ssize_t store_target(struct sys_device *dev,
+			    struct sysdev_attribute *attr,
+			    const char *buf,
+			    size_t count)
+{
+	char *endchar;
+	unsigned long long target_bytes;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	target_bytes = memparse(buf, &endchar);
+
+	balloon_set_new_target(target_bytes >> PAGE_SHIFT);
+
+	return count;
+}
+
+static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
+		   show_target, store_target);
+
+
+static struct sysdev_attribute *balloon_attrs[] = {
+	&attr_target_kb,
+	&attr_target,
+	&attr_schedule_delay.attr,
+	&attr_max_schedule_delay.attr,
+	&attr_retry_count.attr,
+	&attr_max_retry_count.attr
+};
+
+static struct attribute *balloon_info_attrs[] = {
+	&attr_current_kb.attr,
+	&attr_low_kb.attr,
+	&attr_high_kb.attr,
+	NULL
+};
+
+static struct attribute_group balloon_info_group = {
+	.name = "info",
+	.attrs = balloon_info_attrs
+};
+
+static struct sysdev_class balloon_sysdev_class = {
+	.name = BALLOON_CLASS_NAME
+};
+
+static int register_balloon(struct sys_device *sysdev)
+{
+	int i, error;
+
+	error = sysdev_class_register(&balloon_sysdev_class);
+	if (error)
+		return error;
+
+	sysdev->id = 0;
+	sysdev->cls = &balloon_sysdev_class;
+
+	error = sysdev_register(sysdev);
+	if (error) {
+		sysdev_class_unregister(&balloon_sysdev_class);
+		return error;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(balloon_attrs); i++) {
+		error = sysdev_create_file(sysdev, balloon_attrs[i]);
+		if (error)
+			goto fail;
+	}
+
+	error = sysfs_create_group(&sysdev->kobj, &balloon_info_group);
+	if (error)
+		goto fail;
+
+	return 0;
+
+ fail:
+	while (--i >= 0)
+		sysdev_remove_file(sysdev, balloon_attrs[i]);
+	sysdev_unregister(sysdev);
+	sysdev_class_unregister(&balloon_sysdev_class);
+	return error;
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c
index baa65e7..7397695 100644
--- a/drivers/xen/xenbus/xenbus_probe.c
+++ b/drivers/xen/xenbus/xenbus_probe.c
@@ -577,7 +577,7 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus)
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_changed);
 
-int xenbus_dev_suspend(struct device *dev, pm_message_t state)
+int xenbus_dev_suspend(struct device *dev)
 {
 	int err = 0;
 	struct xenbus_driver *drv;
@@ -590,7 +590,7 @@ int xenbus_dev_suspend(struct device *dev, pm_message_t state)
 		return 0;
 	drv = to_xenbus_driver(dev->driver);
 	if (drv->suspend)
-		err = drv->suspend(xdev, state);
+		err = drv->suspend(xdev);
 	if (err)
 		printk(KERN_WARNING
 		       "xenbus: suspend %s failed: %i\n", dev_name(dev), err);
@@ -642,6 +642,14 @@ int xenbus_dev_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_resume);
 
+int xenbus_dev_cancel(struct device *dev)
+{
+	/* Do nothing */
+	DPRINTK("cancel");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xenbus_dev_cancel);
+
 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
 int xenstored_ready = 0;
 
diff --git a/drivers/xen/xenbus/xenbus_probe.h b/drivers/xen/xenbus/xenbus_probe.h
index 2466581..888b990 100644
--- a/drivers/xen/xenbus/xenbus_probe.h
+++ b/drivers/xen/xenbus/xenbus_probe.h
@@ -64,8 +64,9 @@ extern void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);
 
 extern void xenbus_dev_shutdown(struct device *_dev);
 
-extern int xenbus_dev_suspend(struct device *dev, pm_message_t state);
+extern int xenbus_dev_suspend(struct device *dev);
 extern int xenbus_dev_resume(struct device *dev);
+extern int xenbus_dev_cancel(struct device *dev);
 
 extern void xenbus_otherend_changed(struct xenbus_watch *watch,
 				    const char **vec, unsigned int len,
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index 5bcc2d6..b6a2690 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -85,6 +85,14 @@ static struct device_attribute xenbus_frontend_dev_attrs[] = {
 	__ATTR_NULL
 };
 
+static const struct dev_pm_ops xenbus_pm_ops = {
+	.suspend	= xenbus_dev_suspend,
+	.resume		= xenbus_dev_resume,
+	.freeze		= xenbus_dev_suspend,
+	.thaw		= xenbus_dev_cancel,
+	.restore	= xenbus_dev_resume,
+};
+
 static struct xen_bus_type xenbus_frontend = {
 	.root = "device",
 	.levels = 2,		/* device/type/<id> */
@@ -100,8 +108,7 @@ static struct xen_bus_type xenbus_frontend = {
 		.shutdown	= xenbus_dev_shutdown,
 		.dev_attrs	= xenbus_frontend_dev_attrs,
 
-		.suspend	= xenbus_dev_suspend,
-		.resume		= xenbus_dev_resume,
+		.pm		= &xenbus_pm_ops,
 	},
 };
 
diff --git a/firmware/Makefile b/firmware/Makefile
index 0a9d1e2..0384afa 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -35,7 +35,7 @@ fw-shipped-$(CONFIG_ATM_AMBASSADOR) += atmsar11.fw
 fw-shipped-$(CONFIG_BNX2X) += bnx2x/bnx2x-e1-6.2.5.0.fw \
 			      bnx2x/bnx2x-e1h-6.2.5.0.fw \
 			      bnx2x/bnx2x-e2-6.2.5.0.fw
-fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-6.2.1.fw \
+fw-shipped-$(CONFIG_BNX2) += bnx2/bnx2-mips-09-6.2.1a.fw \
 			     bnx2/bnx2-rv2p-09-6.0.17.fw \
 			     bnx2/bnx2-rv2p-09ax-6.0.17.fw \
 			     bnx2/bnx2-mips-06-6.2.1.fw \
diff --git a/firmware/WHENCE b/firmware/WHENCE
index 14aaee8..76404f9 100644
--- a/firmware/WHENCE
+++ b/firmware/WHENCE
@@ -701,7 +701,7 @@ Driver: BNX2 - Broadcom NetXtremeII
 
 File: bnx2/bnx2-mips-06-6.2.1.fw
 File: bnx2/bnx2-rv2p-06-6.0.15.fw
-File: bnx2/bnx2-mips-09-6.2.1.fw
+File: bnx2/bnx2-mips-09-6.2.1a.fw
 File: bnx2/bnx2-rv2p-09-6.0.17.fw
 File: bnx2/bnx2-rv2p-09ax-6.0.17.fw
 
diff --git a/firmware/bnx2/bnx2-mips-09-6.2.1.fw.ihex b/firmware/bnx2/bnx2-mips-09-6.2.1.fw.ihex
deleted file mode 100644
index 68279b5..0000000
--- a/firmware/bnx2/bnx2-mips-09-6.2.1.fw.ihex
+++ /dev/null
@@ -1,6526 +0,0 @@
-:10000000080001180800000000005594000000C816
-:1000100000000000000000000000000008005594EF
-:10002000000000380000565C080000A00800000036
-:100030000000574400005694080059200000008436
-:100040000000ADD808005744000001C00000AE5CBD
-:100050000800321008000000000092F80000B01CF8
-:10006000000000000000000000000000080092F8FE
-:100070000000033C00014314080004900800040041
-:10008000000012FC000146500000000000000000CB
-:1000900000000000080016FC000000040001594C9C
-:1000A000080000A80800000000003D280001595089
-:1000B00000000000000000000000000008003D28D3
-:0800C0000000003000019678F9
-:0800C8000A00004600000000E0
-:1000D000000000000000000D636F6D362E322E31DF
-:1000E0000000000006020102000000000000000302
-:1000F000000000C800000032000000030000000003
-:1001000000000000000000000000000000000000EF
-:1001100000000010000001360000EA600000000549
-:1001200000000000000000000000000000000008C7
-:1001300000000000000000000000000000000000BF
-:1001400000000000000000000000000000000000AF
-:10015000000000000000000000000000000000009F
-:10016000000000020000000000000000000000008D
-:10017000000000000000000000000000000000007F
-:10018000000000000000000000000010000000005F
-:10019000000000000000000000000000000000005F
-:1001A000000000000000000000000000000000004F
-:1001B000000000000000000000000000000000003F
-:1001C000000000000000000000000000000000002F
-:1001D000000000000000000000000000000000001F
-:1001E0000000000010000003000000000000000DEF
-:1001F0000000000D3C020800244256083C030800A1
-:1002000024635754AC4000000043202B1480FFFDB2
-:10021000244200043C1D080037BD9FFC03A0F021D0
-:100220003C100800261001183C1C0800279C5608AA
-:100230000E000256000000000000000D27BDFFB4B4
-:10024000AFA10000AFA20004AFA30008AFA4000C50
-:10025000AFA50010AFA60014AFA70018AFA8001CF0
-:10026000AFA90020AFAA0024AFAB0028AFAC002C90
-:10027000AFAD0030AFAE0034AFAF0038AFB8003C28
-:10028000AFB90040AFBC0044AFBF00480E001544FA
-:10029000000000008FBF00488FBC00448FB90040B1
-:1002A0008FB8003C8FAF00388FAE00348FAD003078
-:1002B0008FAC002C8FAB00288FAA00248FA90020C0
-:1002C0008FA8001C8FA700188FA600148FA5001000
-:1002D0008FA4000C8FA300088FA200048FA1000040
-:1002E00027BD004C3C1B60108F7A5030377B502864
-:1002F00003400008AF7A00008F82002427BDFFE092
-:10030000AFB00010AFBF0018AFB100148C42000CAA
-:100310003C1080008E110100104000348FBF001887
-:100320000E000D84000000008F85002024047FFF54
-:100330000091202BACB100008E030104960201084D
-:1003400000031C003042FFFF00621825ACA300042C
-:100350009202010A96030114304200FF3063FFFF4E
-:100360000002140000431025ACA200089603010C03
-:100370009602010E00031C003042FFFF00621825A8
-:10038000ACA3000C960301109602011200031C009E
-:100390003042FFFF00621825ACA300108E02011846
-:1003A000ACA200148E02011CACA20018148000083C
-:1003B0008F820024978200003C0420050044182509
-:1003C00024420001ACA3001C0A0000C6A782000062
-:1003D0003C0340189442001E00431025ACA2001CB0
-:1003E0000E000DB8240400018FBF00188FB1001457
-:1003F0008FB000100000102103E0000827BD00208E
-:100400003C0780008CE202B834E50100044100089A
-:10041000240300013C0208008C42006024420001D9
-:100420003C010800AC22006003E0000800601021DD
-:100430003C0208008C42005C8CA4002094A30016AF
-:100440008CA6000494A5000E24420001ACE40280B6
-:100450002463FFFC3C010800AC22005C3C0210005D
-:10046000A4E30284A4E5028600001821ACE6028819
-:10047000ACE202B803E000080060102127BDFFE0F5
-:100480003C028000AFB0001034420100AFBF001C3E
-:10049000AFB20018AFB100148C43000094450008BF
-:1004A0002462FE002C42038110400003000381C23D
-:1004B0000A00010226100004240201001462000553
-:1004C0003C1180003C02800890420004305000FF44
-:1004D0003C11800036320100964300143202000FB6
-:1004E00000021500004310253C0308008C63004403
-:1004F00030A40004AE220080246300013C01080007
-:10050000AC2300441080000730A200028FBF001C03
-:100510008FB200188FB100148FB000100A0000CE07
-:1005200027BD00201040002D0000182130A20080BF
-:1005300010400005362200708E44001C0E000C672F
-:10054000240500A0362200708C4400008F82000C2D
-:10055000008210232C43012C10600004AF82001095
-:10056000240300010A000145AF84000C8E42000400
-:100570003C036020AF84000CAC6200143C02080015
-:100580008C42005850400015000018218C62000475
-:10059000240301FE304203FF144300100000182121
-:1005A0002E020004104000032E0200080A00014041
-:1005B0000000802114400003000000000A000140F8
-:1005C0002610FFF90000000D2402000202021004B0
-:1005D0003C036000AC626914000018218FBF001C4E
-:1005E0008FB200188FB100148FB00010006010217E
-:1005F00003E0000827BD00203C0480008C8301003C
-:1006000024020100506200033C0280080000000D3B
-:100610003C02800890430004000010213063000F6A
-:1006200000031D0003E00008AC8300800004188074
-:100630002782FF9C00621821000410C00044102390
-:100640008C640000000210C03C030800246356E4E0
-:10065000004310213C038000AC64009003E00008DC
-:10066000AF8200243C0208008C42011410400019A3
-:100670003084400030A2007F000231C03C02020002
-:100680001080001400A218253C026020AC43001426
-:100690003C0408008C8456B83C0308008C630110AD
-:1006A0003C02800024050900AC4500200086202182
-:1006B000246300013C028008AC4400643C01080053
-:1006C000AC2301103C010800AC2456B803E000083C
-:1006D000000000003C02602003E00008AC4500146C
-:1006E00003E000080000102103E0000800001021D2
-:1006F00030A2000810400008240201003C0208005B
-:100700008C42010C244200013C010800AC22010C87
-:1007100003E0000800000000148200080000000050
-:100720003C0208008C4200FC244200013C0108000D
-:10073000AC2200FC0A0001A330A200203C02080009
-:100740008C420084244200013C010800AC22008459
-:1007500030A200201040000830A200103C02080027
-:100760008C420108244200013C010800AC2201082F
-:1007700003E0000800000000104000080000000036
-:100780003C0208008C420104244200013C010800A4
-:10079000AC22010403E00008000000003C02080055
-:1007A0008C420100244200013C010800AC220100FF
-:1007B00003E000080000000027BDFFE0AFB1001417
-:1007C0003C118000AFB20018AFBF001CAFB00010EA
-:1007D0003632010096500008320200041040000733
-:1007E000320300028FBF001C8FB200188FB10014BB
-:1007F0008FB000100A0000CE27BD00201060000B53
-:10080000020028218E2401000E00018A0000000051
-:100810003202008010400003240500A10E000C6786
-:100820008E44001C0A0001E3240200018E2301040F
-:100830008F82000810430006020028218E24010048
-:100840000E00018A000000008E220104AF82000821
-:10085000000010218FBF001C8FB200188FB1001450
-:100860008FB0001003E0000827BD00202C82000498
-:1008700014400002000018212483FFFD240200021E
-:10088000006210043C03600003E00008AC626914DD
-:1008900027BDFFE0AFBF001CAFB20018AFB100141E
-:1008A000AFB000103C048000948201083043700017
-:1008B000240220001062000A2862200154400052E5
-:1008C0008FBF001C24024000106200482402600018
-:1008D0001062004A8FBF001C0A0002518FB200183C
-:1008E00034820100904300098C5000189451000C90
-:1008F000240200091062001C0000902128620009F7
-:10090000144000218F8200242402000A5062001249
-:10091000323100FF2402000B1062000F00000000C3
-:100920002402000C146200188F8200243C0208008C
-:100930008C4256B824030900AC83002000501021DB
-:100940003C038008AC6200643C010800AC2256B84D
-:100950000A0002508FBF001C0E0001E900102602A1
-:100960000A0002308F8200240E0001E900102602E6
-:100970003C0380089462001A8C72000C3042FFFF26
-:10098000020280258F8200248C42000C5040001E01
-:100990008FBF001C0E000D84000000003C02800090
-:1009A00034420100944300088F82002400031C009D
-:1009B0009444001E8F82002000641825AC50000073
-:1009C00024040001AC510004AC520008AC40000CFF
-:1009D000AC400010AC400014AC4000180E000DB844
-:1009E000AC43001C0A0002508FBF001C0E000440E4
-:1009F000000000000A0002508FBF001C0E000C9F78
-:100A0000000000008FBF001C8FB200188FB10014CF
-:100A10008FB000100000102103E0000827BD002067
-:100A200027BDFFD8AFB400203C036010AFBF002447
-:100A3000AFB3001CAFB20018AFB10014AFB00010DC
-:100A40008C6450002402FF7F3C1408002694563822
-:100A5000008220243484380CAC6450003C028000B6
-:100A6000240300370E0014B0AC4300083C07080014
-:100A700024E70618028010212404001D2484FFFFAF
-:100A8000AC4700000481FFFD244200043C02080042
-:100A9000244207C83C010800AC2256403C02080032
-:100AA000244202303C030800246306203C04080072
-:100AB000248403B43C05080024A506F03C06080085
-:100AC00024C62C9C3C010800AC2256803C02080045
-:100AD000244205303C010800AC2756843C01080044
-:100AE000AC2656943C010800AC23569C3C010800FF
-:100AF000AC2456A03C010800AC2556A43C010800DB
-:100B0000AC2256A83C010800AC23563C3C0108002E
-:100B1000AC2456443C010800AC2056603C0108005F
-:100B2000AC2556643C010800AC2056703C0108001E
-:100B3000AC27567C3C010800AC2656903C010800CE
-:100B4000AC2356980E00056E00000000AF80000C2C
-:100B50003C0280008C5300008F8300043C0208009C
-:100B60008C420020106200213262000700008821C0
-:100B70002792FF9C3C100800261056E43C02080017
-:100B80008C42002024050001022518040043202483
-:100B90008F820004004310245044000C26310001D1
-:100BA00010800008AF9000248E4300003C028000BB
-:100BB000AC4300900E000D4BAE05000C0A0002C1C4
-:100BC00026310001AE00000C263100012E22000269
-:100BD000261000381440FFE9265200043C020800A9
-:100BE0008C420020AF820004326200071040FFD91F
-:100BF0003C028000326200011040002D326200028F
-:100C00003C0580008CA2010000002021ACA2002045
-:100C10008CA301042C42078110400008ACA300A85B
-:100C200094A2010824032000304270001443000302
-:100C30003C02800890420005304400FF0E0001593C
-:100C4000000000003C0280009042010B304300FF96
-:100C50002C62001E54400004000310800E00018628
-:100C60000A0002EC00000000005410218C42000039
-:100C70000040F80900000000104000043C02800021
-:100C80008C4301043C026020AC4300143C02080089
-:100C90008C4200343C0440003C03800024420001AC
-:100CA000AC6401383C010800AC220034326200021E
-:100CB00010400010326200043C1080008E0201409F
-:100CC000000020210E000159AE0200200E00038317
-:100CD000000000003C024000AE0201783C02080027
-:100CE0008C420038244200013C010800AC2200384C
-:100CF000326200041040FF973C0280003C108000EC
-:100D00008E020180000020210E000159AE02002059
-:100D10008E03018024020F00546200073C02800809
-:100D20008E0201883C0300E03042FFFF00431025A3
-:100D30000A000328AE020080344200809042000086
-:100D400024030050304200FF14430007000000005D
-:100D50000E000362000000001440000300000000C9
-:100D60000E000971000000003C0208008C42003CAB
-:100D70003C0440003C03800024420001AC6401B804
-:100D80003C010800AC22003C0A0002A33C028000A7
-:100D90003C02900034420001008220253C02800089
-:100DA000AC4400203C0380008C6200200440FFFE25
-:100DB0000000000003E00008000000003C0280008A
-:100DC000344300010083202503E00008AC440020E8
-:100DD00027BDFFE0AFB10014AFB000100080882144
-:100DE000AFBF00180E00033230B000FF8F83FF94B6
-:100DF000022020219062002502028025A07000259B
-:100E00008C7000183C0280000E00033D020280241A
-:100E10001600000B8FBF00183C0480008C8201F884
-:100E20000440FFFE348201C024030002AC510000E4
-:100E3000A04300043C021000AC8201F88FBF0018F0
-:100E40008FB100148FB0001003E0000827BD002010
-:100E500027BDFFE83C028000AFBF00103442018094
-:100E6000944300048C4400083063020010600005C5
-:100E7000000028210E00100C000000000A0003787A
-:100E8000240500013C02FF000480000700821824B2
-:100E90003C02040014620004240500018F82FF94C8
-:100EA00090420008240500018FBF001000A010210F
-:100EB00003E0000827BD00188F82FF982405000179
-:100EC000A040001A3C028000344201400A00034264
-:100ED0008C4400008F85FF9427BDFFE0AFBF001C4E
-:100EE000AFB20018AFB10014AFB0001090A2000074
-:100EF000304400FF38830020388200300003182B74
-:100F00000002102B0062182410600003240200501D
-:100F1000148200A88FBF001C90A20005304200017F
-:100F2000104000A48FBF001C3C02800034420140EE
-:100F3000904200082443FFFF2C6200051040009EF1
-:100F40008FB20018000310803C030800246355ACE6
-:100F5000004310218C420000004000080000000007
-:100F60003C028000345101400E0003328E24000008
-:100F70008F92FF948E2200048E50000C1602000205
-:100F800024020001AE42000C0E00033D8E2400003E
-:100F90008E220004145000068FBF001C8FB2001870
-:100FA0008FB100148FB000100A000F7827BD002009
-:100FB0008E42000C0A000419000000003C0480006E
-:100FC0003482014094A300108C4200043063FFFF80
-:100FD0001443001C0000000024020001A4A2001021
-:100FE0008C8202380441000F3C0380003C02003F29
-:100FF0003448F0003C0760003C06FFC08CE22BBC8C
-:1010000000461824004810240002130200031D8229
-:10101000106200583C0280008C8202380440FFF7C6
-:101020003C038000346201408C44000034620200C2
-:10103000AC4400003C021000AC6202380A00043BE1
-:101040008FBF001C94A200100A00041900000000C9
-:10105000240200201482000F3C0280003C03800028
-:1010600094A20012346301408C6300043042FFFFFD
-:10107000146200050000000024020001A4A2001276
-:101080000A0004028FBF001C94A200120A00041977
-:1010900000000000345101400E0003328E24000095
-:1010A0008F92FF948E230004964200123050FFFF6F
-:1010B0001603000224020001A64200120E00033DA6
-:1010C0008E2400008E220004160200068FBF001C32
-:1010D0008FB200188FB100148FB000100A00037C8B
-:1010E00027BD0020964200120A00041900000000EB
-:1010F0003C03800094A20014346301408C6300041C
-:101100003042FFFF14620008240200018FBF001C60
-:101110008FB200188FB100148FB00010A4A2001479
-:101120000A00146327BD002094A20014144000217B
-:101130008FBF001C0A000435000000003C03800043
-:1011400094A20016346301408C6300043042FFFF18
-:101150001462000D240200018FBF001C8FB2001822
-:101160008FB100148FB00010A4A200160A000B1457
-:1011700027BD00209442007824420004A4A200105D
-:101180000A00043B8FBF001C94A200162403000138
-:101190003042FFFF144300078FBF001C3C020800D1
-:1011A0008C420070244200013C010800AC22007017
-:1011B0008FBF001C8FB200188FB100148FB00010C9
-:1011C00003E0000827BD002027BDFFD8AFB20018FC
-:1011D0008F92FF94AFB10014AFBF0020AFB3001CDB
-:1011E000AFB000103C028000345101008C5001006F
-:1011F0009242000092230009304400FF2402001FA5
-:10120000106200AB28620020104000192402003850
-:101210002862000A1040000D2402000B286200081A
-:101220001040002E8F820024046001042862000216
-:101230001440002A8F820024240200061062002637
-:101240008FBF00200A00055F8FB3001C1062006092
-:101250002862000B144000FA8FBF00202402000E09
-:10126000106200788F8200240A00055F8FB3001C93
-:10127000106200D2286200391040000A2402008067
-:1012800024020036106200E528620037104000C3D7
-:1012900024020035106200D98FBF00200A00055FCC
-:1012A0008FB3001C1062002D2862008110400006E0
-:1012B000240200C824020039106200C98FBF002038
-:1012C0000A00055F8FB3001C106200A28FBF0020D0
-:1012D0000A00055F8FB3001C8F8200248C42000C33
-:1012E000104000D78FBF00200E000D8400000000CA
-:1012F0003C038000346301008C6200008F85002075
-:10130000946700089466000CACA200008C64000492
-:101310008F82002400063400ACA400049448001E10
-:101320008C62001800073C0000E83825ACA20008D9
-:101330008C62001C24040001ACA2000C9062000A24
-:1013400000C23025ACA60010ACA00014ACA0001860
-:10135000ACA7001C0A00051D8FBF00208F8200244F
-:101360008C42000C104000B68FBF00200E000D8490
-:10137000000000008F820024962400089625000CAF
-:101380009443001E000422029626000E8F82002045
-:10139000000426000083202500052C003C0300806B
-:1013A00000A6282500832025AC400000AC400004A6
-:1013B000AC400008AC40000CAC450010AC40001440
-:1013C000AC400018AC44001C0A00051C24040001B9
-:1013D0009622000C14400018000000009242000504
-:1013E0003042001014400014000000000E000332D0
-:1013F0000200202192420005020020213442001008
-:101400000E00033DA242000592420000240300208A
-:10141000304200FF10430089020020218FBF0020CE
-:101420008FB3001C8FB200188FB100148FB0001062
-:101430000A00107527BD00280000000D0A00055E97
-:101440008FBF00208C42000C1040007D8FBF002019
-:101450000E000D84000000008E2200048F84002006
-:101460009623000CAC8200003C0280089445002CBE
-:101470008F82002400031C0030A5FFFF9446001E4D
-:101480003C02400E0065182500C23025AC830004E4
-:10149000AC800008AC80000CAC800010AC80001464
-:1014A000AC800018AC86001C0A00051C2404000156
-:1014B0000E000332020020218F93FF9802002021AA
-:1014C0000E00033DA660000C020020210E00034226
-:1014D000240500018F8200248C42000C104000582B
-:1014E0008FBF00200E000D84000000009622000C2B
-:1014F0008F83002000021400AC700000AC62000476
-:10150000AC6000088E4400388F820024AC64000C6C
-:101510008E46003C9445001E3C02401FAC66001005
-:1015200000A228258E62000424040001AC6200148D
-:10153000AC600018AC65001C8FBF00208FB3001C8E
-:101540008FB200188FB100148FB000100A000DB8D0
-:1015500027BD0028240200201082003A8FB3001C0F
-:101560000E000F5E00000000104000358FBF00200D
-:101570003C0480008C8201F80440FFFE348201C0EC
-:1015800024030002AC500000A04300043C02100001
-:10159000AC8201F80A00055E8FBF00200200202106
-:1015A0008FBF00208FB3001C8FB200188FB10014C2
-:1015B0008FB000100A000EA727BD00289625000C4A
-:1015C000020020218FBF00208FB3001C8FB20018B3
-:1015D0008FB100148FB000100A000ECC27BD002878
-:1015E000020020218FB3001C8FB200188FB10014AD
-:1015F0008FB000100A000EF727BD00289225000DBD
-:10160000020020218FB3001C8FB200188FB100148C
-:101610008FB000100A000F4827BD002802002021CB
-:101620008FBF00208FB3001C8FB200188FB1001441
-:101630008FB000100A000F1F27BD00288FBF0020A9
-:101640008FB3001C8FB200188FB100148FB0001040
-:1016500003E0000827BD00283C0580008CA202782A
-:101660000440FFFE34A2024024030002AC44000008
-:10167000A04300043C02100003E00008ACA2027882
-:10168000A380001803E00008A38000193C03800039
-:101690008C6202780440FFFE8F82001CAC62024024
-:1016A00024020002A06202443C02100003E0000891
-:1016B000AC6202783C02600003E000088C425404F3
-:1016C0009083003024020005008040213063003FF9
-:1016D0000000482114620005000050219082004C57
-:1016E0009483004E304900FF306AFFFFAD00000CCC
-:1016F000AD000010AD000024950200148D05001C03
-:101700008D0400183042FFFF004910230002110031
-:10171000000237C3004038210086202300A2102B8E
-:101720000082202300A72823AD05001CAD0400186B
-:10173000A5090014A5090020A50A001603E0000869
-:10174000A50A002203E000080000000027BDFFD822
-:10175000AFB200183C128008AFB40020AFB3001C39
-:10176000AFB10014AFBF0024AFB00010365101007C
-:101770003C0260008C4254049222000C3C1408008D
-:10178000929400F7304300FF2402000110620032FF
-:101790000080982124020002146200353650008037
-:1017A0000E00143D000000009202004C2403FF8054
-:1017B0003C0480003042007F000211C024420240FD
-:1017C0000262102100431824AC8300949245000863
-:1017D0009204004C3042007F3C03800614850007D1
-:1017E000004380212402FFFFA22200112402FFFFF8
-:1017F000A62200120A0005D22402FFFF9602002052
-:10180000A222001196020022A62200128E020024BB
-:101810003C048008AE2200143485008090A2004C65
-:1018200034830100A06200108CA2003CAC6200185E
-:101830008C820068AC6200F48C820064AC6200F0C0
-:101840008C82006CAC6200F824020001A0A2006847
-:101850000A0005EE3C0480080E001456000000004B
-:1018600036420080A04000680A0005EE3C04800873
-:10187000A2000068A20000690A0006293C02800854
-:10188000348300808C62003834850100AC62006CC7
-:1018900024020001A062006990A200D59083000894
-:1018A000305100FF3072007F12320019001111C058
-:1018B00024420240026210212403FF8000431824C6
-:1018C0003C048000AC8300943042007F3C038006DF
-:1018D000004380218E02000C1040000D02002021E8
-:1018E0000E00057E0000000026220001305100FF9E
-:1018F0009203003C023410260002102B0002102339
-:101900003063007F022288240A0005F8A203003C0D
-:101910003C088008350401008C8200E03507008017
-:10192000ACE2003C8C8200E0AD02000090E5004C8F
-:10193000908600D590E3004C908400D52402FF806F
-:1019400000A228243063007F308400FF00A62825F1
-:101950000064182A1060000230A500FF38A500803E
-:10196000A0E5004CA10500093C0280089043000E50
-:10197000344400803C058000A043000A8C8300189A
-:101980003C027FFF3442FFFF00621824AC83001842
-:101990008CA201F80440FFFE00000000ACB301C0BF
-:1019A0008FBF00248FB400208FB3001C8FB20018AB
-:1019B0008FB100148FB0001024020002A0A201C455
-:1019C00027BD00283C02100003E00008ACA201F88B
-:1019D00090A2000024420001A0A200003C030800E5
-:1019E0008C6300F4304200FF144300020080302179
-:1019F000A0A0000090A200008F84001C000211C073
-:101A00002442024024830040008220212402FF80DF
-:101A1000008220243063007F3C02800A006218218B
-:101A20003C028000AC44002403E00008ACC300008A
-:101A300094820006908300058C85000C8C86001033
-:101A40008C8700188C88001C8C8400203C010800C6
-:101A5000A42256C63C010800A02356C53C0108003C
-:101A6000AC2556CC3C010800AC2656D03C01080001
-:101A7000AC2756D83C010800AC2856DC3C010800D5
-:101A8000AC2456E003E00008000000003C0280089F
-:101A9000344201008C4400343C038000346504006F
-:101AA000AC6400388C420038AF850028AC62003C42
-:101AB0003C020005AC6200300000000000000000A5
-:101AC00003E00008000000003C020006308400FF34
-:101AD000008220253C028000AC4400300000000061
-:101AE00000000000000000003C0380008C62000049
-:101AF000304200101040FFFD3462040003E0000893
-:101B0000AF82002894C200003C080800950800CA73
-:101B100030E7FFFF0080482101021021A4C200002D
-:101B200094C200003042FFFF00E2102B544000013D
-:101B3000A4C7000094A200003C0308008C6300CC02
-:101B400024420001A4A2000094A200003042FFFF42
-:101B5000144300073C0280080107102BA4A00000DA
-:101B60005440000101003821A4C700003C02800855
-:101B7000344601008CC3002894A200003C0480007D
-:101B80003042FFFE000210C000621021AC82003C17
-:101B90008C82003C006218231860000400000000E2
-:101BA0008CC200240A0006BA244200018CC2002420
-:101BB000AC8200383C020050344200103C038000EC
-:101BC000AC620030000000000000000000000000D7
-:101BD0008C620000304200201040FFFD0000000039
-:101BE00094A200003C04800030420001000210C0BA
-:101BF000004410218C430400AD2300008C420404F7
-:101C0000AD2200043C02002003E00008AC8200305A
-:101C100027BDFFE0AFB20018AFB10014AFB00010A5
-:101C2000AFBF001C94C2000000C080213C1208001D
-:101C3000965200C624420001A6020000960300004E
-:101C400094E2000000E03021144300058FB1003021
-:101C50000E00068F024038210A0006F10000000045
-:101C60008C8300048C82000424420040046100073D
-:101C7000AC8200048C8200040440000400000000D8
-:101C80008C82000024420001AC8200009602000019
-:101C90003042FFFF50520001A600000096220000D3
-:101CA00024420001A62200003C02800834420100C8
-:101CB000962300009442003C144300048FBF001C94
-:101CC00024020001A62200008FBF001C8FB2001862
-:101CD0008FB100148FB0001003E0000827BD002072
-:101CE00027BDFFE03C028008AFBF0018344201006E
-:101CF0008C4800343C03800034690400AC68003830
-:101D00008C42003830E700FFAF890028AC62003C0D
-:101D10003C020005AC620030000000000000000042
-:101D200000000000000000000000000000000000B3
-:101D30008C82000C8C82000C97830016AD22000070
-:101D40008C82001000604021AD2200048C820018BB
-:101D5000AD2200088C82001CAD22000C8CA2001465
-:101D6000AD2200108C820020AD220014908200056C
-:101D7000304200FF00021200AD2200188CA20018B1
-:101D8000AD22001C8CA2000CAD2200208CA2001001
-:101D9000AD2200248CA2001CAD2200288CA20020C1
-:101DA000AD22002C3402FFFFAD260030AD20003400
-:101DB000506200013408FFFFAD28003850E00011E8
-:101DC0003C0280083C048008348401009482005066
-:101DD0003042FFFFAD22003C9483004494850044D0
-:101DE000240200013063FFFF000318C200641821C1
-:101DF0009064006430A5000700A210040A00075C8C
-:101E00000044102534420100AD20003C94430044BE
-:101E1000944400443063FFFF000318C2006218219D
-:101E200030840007906500642402000100821004E1
-:101E30000002102700451024A0620064000000008A
-:101E400000000000000000003C0200063442004098
-:101E50003C038000AC620030000000000000000085
-:101E6000000000008C620000304200101040FFFDB6
-:101E70003C06800834C201503463040034C7014A70
-:101E800034C4013434C5014034C60144AFA200104B
-:101E90000E0006D2AF8300288FBF001803E00008B1
-:101EA00027BD00208F8300143C0608008CC600E884
-:101EB0008F82001C30633FFF000319800046102111
-:101EC000004310212403FF80004318243C068000B7
-:101ED000ACC300283042007F3C03800C004330211B
-:101EE00090C2000D30A500FF0000382134420010E0
-:101EF000A0C2000D8F8900143C028008344201000A
-:101F00009443004400091382304800032402000176
-:101F1000A4C3000E1102000B2902000210400005AC
-:101F2000240200021100000C240300010A0007A48F
-:101F30000000182111020006000000000A0007A49A
-:101F4000000018218CC2002C0A0007A424430001C1
-:101F50008CC20014244300018CC200180043102BD3
-:101F60005040000A240700012402002714A20003A5
-:101F70003C0380080A0007B1240700013463010014
-:101F80009462004C24420001A462004C00091382B8
-:101F9000304300032C620002104000090080282119
-:101FA000146000040000000094C200340A0007C15D
-:101FB0003046FFFF8CC600380A0007C10080282188
-:101FC000000030213C040800248456C00A000706A3
-:101FD0000000000027BDFF90AFB60068AFB50064F9
-:101FE000AFB40060AFB3005CAFB20058AFB1005403
-:101FF000AFBF006CAFB000508C9000000080B021EB
-:102000003C0208008C4200E8960400328F83001CDA
-:102010002414FF8030843FFF0062182100042180D7
-:1020200000641821007410243C13800000A090214B
-:1020300090A50000AE620028920400323C02800CA1
-:102040003063007F00628821308400C02402004099
-:10205000148200320000A8218E3500388E2200182C
-:102060001440000224020001AE2200189202003C3B
-:10207000304200201440000E8F83001C000511C068
-:102080002442024000621821306400783C02008043
-:102090000082202500741824AE630800AE64081086
-:1020A0008E2200188E03000800431021AE22001873
-:1020B0008E22002C8E230018244200010062182B6F
-:1020C0001060004300000000924200002442000122
-:1020D000A24200003C0308008C6300F4304200FF81
-:1020E00050430001A2400000924200008F84001C77
-:1020F000000211C024420240248300403063007F6C
-:10210000008220213C02800A0094202400621821D1
-:10211000AE6400240A0008D2AEC30000920300326D
-:102120002402FFC000431024304200FF1440000589
-:1021300024020001AE220018962200340A00084250
-:102140003055FFFF8E22001424420001AE220018F9
-:102150009202003000021600000216030441001C27
-:10216000000000009602003227A400100080282101
-:10217000A7A20016960200320000302124070001B9
-:102180003042FFFFAF8200140E000706AFA0001C14
-:10219000960200328F83001C3C0408008C8400E807
-:1021A00030423FFF000211800064182100621821B4
-:1021B00000741024AE62002C3063007F3C02800E5D
-:1021C000006218219062000D3042007FA062000D75
-:1021D0009222000D304200105040007892420000E0
-:1021E0003C028008344401009482004C8EC30000FD
-:1021F0003C130800967300C62442FFFFA482004CE3
-:10220000946200329623000E3054FFFF3070FFFFBF
-:102210003C0308008C6300D000701807A7A30038A7
-:102220009482003E3063FFFF3042FFFF14620007DC
-:10223000000000008C8200303C038000244200300B
-:10224000AC62003C0A00086A8C82002C9482004038
-:102250003042FFFF5462000927A400408C820038FE
-:102260003C03800024420030AC62003C8C8200348D
-:10227000AC6200380A0008793C03800027A50038CA
-:1022800027A60048026038210E00068FA7A000484C
-:102290008FA300403C02800024630030AC43003830
-:1022A0008FA30044AC43003C3C0380003C0200058B
-:1022B000AC6200303C028008344401009482004249
-:1022C000346304003042FFFF0202102B1440000769
-:1022D000AF8300289482004E9483004202021021B2
-:1022E000004310230A00088F3043FFFF9483004E01
-:1022F00094820042026318210050102300621823C8
-:102300003063FFFF3C028008344401009482003CAB
-:102310003042FFFF14430003000000000A00089F42
-:10232000240300019482003C3042FFFF0062102B26
-:10233000144000058F8200289482003C0062102324
-:102340003043FFFF8F820028AC550000AC400004F2
-:10235000AC540008AC43000C3C02000634420010B0
-:102360003C038000AC620030000000000000000070
-:10237000000000008C620000304200101040FFFDA1
-:102380003C04800834840100001018C20064182145
-:102390009065006432020007240600010046100424
-:1023A00000451025A0620064948300429622000E2E
-:1023B00050430001A386001892420000244200010D
-:1023C000A24200003C0308008C6300F4304200FF8E
-:1023D00050430001A2400000924200008F84001C84
-:1023E000000211C0244202402483004000822021C8
-:1023F0002402FF80008220243063007F3C02800A98
-:10240000006218213C028000AC440024AEC30000EE
-:102410008FBF006C8FB600688FB500648FB400600A
-:102420008FB3005C8FB200588FB100548FB0005052
-:1024300003E0000827BD007027BDFFD8AFB3001C24
-:10244000AFB20018AFB10014AFB00010AFBF0020A2
-:102450000080982100E0802130B1FFFF0E000D8444
-:1024600030D200FF0000000000000000000000006B
-:102470008F8200208F830024AC510000AC520004F6
-:10248000AC530008AC40000CAC400010AC40001451
-:10249000AC4000189463001E02038025AC50001C61
-:1024A0000000000000000000000000002404000103
-:1024B0008FBF00208FB3001C8FB200188FB10014A3
-:1024C0008FB000100A000DB827BD002830A5FFFF0F
-:1024D0000A0008DC30C600FF3C02800834430100DB
-:1024E0009462000E3C080800950800C63046FFFFC5
-:1024F00014C000043402FFFF946500EA0A000929B1
-:102500008F84001C10C20027000000009462004E5F
-:102510009464003C3045FFFF00A6102300A6182B52
-:102520003087FFFF106000043044FFFF00C5102318
-:1025300000E210233044FFFF0088102B1040000EF3
-:1025400000E810233C028008344401002403000109
-:1025500034420080A44300162402FFFFA482000E30
-:10256000948500EA8F84001C0000302130A5FFFF15
-:102570000A0009013C0760200044102A10400009AD
-:102580003C0280083443008094620016304200010F
-:10259000104000043C0280009442007E244200145B
-:1025A000A462001603E000080000000027BDFFE061
-:1025B0003C028008AFBF001CAFB0001834420100DD
-:1025C000944300429442004C104000193068FFFFD1
-:1025D0009383001824020001146200298FBF001C9D
-:1025E0003C06800834D00100000810C200501021C1
-:1025F000904200643103000734C70148304200FFB5
-:10260000006210073042000134C9014E34C4012C6D
-:1026100034C5013E1040001634C601420E0006D2F9
-:10262000AFA90010960200420A0009463048FFFF99
-:102630003C028008344401009483004494820042A8
-:102640001043000F8FBF001C94820044A4820042FC
-:1026500094820050A482004E8C820038AC820030FC
-:1026600094820040A482003E9482004AA4820048E2
-:102670008FBF001C8FB000180A00090427BD00207E
-:102680008FB0001803E0000827BD002027BDFFA081
-:10269000AFB1004C3C118000AFBF0058AFB3005445
-:1026A000AFB20050AFB000483626018890C2000398
-:1026B0003044007FA3A400108E32018090C200003D
-:1026C0003043007F240200031062003BAF92001CE5
-:1026D00028620004104000062402000424020002C4
-:1026E000106200098FBF00580A000B0F8FB300540F
-:1026F0001062004D240200051062014E8FBF005889
-:102700000A000B0F8FB30054000411C002421021C5
-:102710002404FF8024420240004410242643004049
-:10272000AE2200243063007F3C02800A0062182140
-:102730009062003CAFA3003C00441025A062003C26
-:102740008FA3003C9062003C304200401040016C7E
-:102750008FBF00583C108008A3800018361001007D
-:102760008E0200E08C63003427A4003C27A50010F3
-:10277000004310210E0007C3AE0200E093A2001038
-:102780003C038000A20200D58C6202780440FFFE68
-:102790008F82001CAC62024024020002A06202444C
-:1027A0003C021000AC6202780E0009390000000003
-:1027B0000A000B0E8FBF00583C05800890C3000133
-:1027C00090A2000B1443014E8FBF005834A4008028
-:1027D0008C8200189082004C90A200083C0260009D
-:1027E0008C4254048C8300183C027FFF3442FFFF6C
-:1027F000006218243C0208008C4200B4AC8300182C
-:102800003C038000244200013C010800AC2200B4DB
-:102810008C6201F80440FFFE8F82001CAC6201C094
-:102820000A000AD6240200023C10800890C300016E
-:102830009202000B144301328FBF005827A40018E6
-:1028400036050110240600033C0260008C4254044B
-:102850000E000E470000000027A40028360501F0F6
-:102860000E000E47240600038FA200283603010045
-:10287000AE0200648FA2002CAE0200688FA200306E
-:10288000AE02006C93A40018906300D52402FF8070
-:102890000082102400431025304900FF3084007F5F
-:1028A0003122007F0082102A544000013929008023
-:1028B000000411C0244202402403FF800242102180
-:1028C00000431024AE220094264200403042007F94
-:1028D0003C038006004340218FA3001C2402FFFF1D
-:1028E000AFA800403C130800927300F71062003359
-:1028F00093A2001995030014304400FF3063FFFFDA
-:102900000064182B106000100000000095040014F3
-:102910008D07001C8D0600183084FFFF0044202323
-:102920000004210000E438210000102100E4202BE5
-:1029300000C2302100C43021AD07001CAD060018D4
-:102940000A000A2F93A20019950400148D07001C99
-:102950008D0600183084FFFF008220230004210030
-:10296000000010210080182100C2302300E4202B39
-:1029700000C4302300E33823AD07001CAD06001867
-:1029800093A200198FA30040A462001497A2001A1A
-:10299000A46200168FA2001CAC6200108FA2001C63
-:1029A000AC62000C93A20019A462002097A2001A46
-:1029B000A46200228FA2001CAC6200243C048008A8
-:1029C000348300808C6200388FA20020012088218F
-:1029D000AC62003C8FA20020AC82000093A20018E1
-:1029E000A062004C93A20018A0820009A0600068B9
-:1029F00093A20018105100512407FF803229007F54
-:102A0000000911C024420240024210213046007FDA
-:102A10003C03800000471024AC6200943C02800616
-:102A200000C2302190C2003CAFA60040000020212F
-:102A300000471025A0C2003C8FA80040950200026C
-:102A4000950300148D07001C3042FFFF3063FFFF29
-:102A50008D060018004310230002110000E2382107
-:102A600000E2102B00C4302100C23021AD07001C51
-:102A7000AD06001895020002A5020014A50000167C
-:102A80008D020008AD0200108D020008AD02000C9E
-:102A900095020002A5020020A50000228D02000878
-:102AA000AD0200249102003C304200401040001A68
-:102AB000262200013C108008A3A90038A38000183A
-:102AC000361001008E0200E08D03003427A4004080
-:102AD00027A50038004310210E0007C3AE0200E016
-:102AE00093A200383C038000A20200D58C620278D9
-:102AF0000440FFFE8F82001CAC62024024020002F0
-:102B0000A06202443C021000AC6202780E00093957
-:102B100000000000262200013043007F14730004EF
-:102B2000004020212403FF8002231024004320269C
-:102B300093A200180A000A4B309100FF93A40018DA
-:102B40008FA3001C2402FFFF1062000A308900FFDF
-:102B500024820001248300013042007F14530005C9
-:102B6000306900FF2403FF800083102400431026F7
-:102B7000304900FF3C028008904200080120882173
-:102B8000305000FF123000193222007F000211C0C5
-:102B900002421021244202402403FF8000431824F3
-:102BA0003C048000AC8300943042007F3C038006EC
-:102BB000004310218C43000C004020211060000BCA
-:102BC000AFA200400E00057E000000002623000199
-:102BD0002405FF803062007F145300020225202468
-:102BE000008518260A000AAF307100FF3C048008F7
-:102BF000348400808C8300183C027FFF3442FFFF46
-:102C000000621824AC8300183C0380008C6201F839
-:102C10000440FFFE00000000AC7201C0240200026C
-:102C2000A06201C43C021000AC6201F80A000B0E65
-:102C30008FBF00583C04800890C300019082000BB5
-:102C40001443002F8FBF0058349000809202000878
-:102C500030420040104000200000000092020008B6
-:102C60000002160000021603044100050240202164
-:102C70000E000ECC240500930A000B0E8FBF0058E7
-:102C80009202000924030018304200FF1443000D93
-:102C900002402021240500390E000E64000030217E
-:102CA0000E0003328F84001C8F82FF9424030012D5
-:102CB000A04300090E00033D8F84001C0A000B0E88
-:102CC0008FBF0058240500360E000E64000030212E
-:102CD0000A000B0E8FBF00580E0003320240202165
-:102CE000920200058F84001C344200200E00033D38
-:102CF000A20200050E0010758F84001C8FBF0058C3
-:102D00008FB300548FB200508FB1004C8FB0004889
-:102D100003E0000827BD00603C0280083445010044
-:102D20003C0280008C42014094A3000E0000302140
-:102D300000402021AF82001C3063FFFF3402FFFF00
-:102D4000106200063C0760202402FFFFA4A2000ED0
-:102D500094A500EA0A00090130A5FFFF03E000087E
-:102D60000000000027BDFFC83C0280003C06800830
-:102D7000AFB5002CAFB1001CAFBF0030AFB400281E
-:102D8000AFB30024AFB20020AFB00018345101003F
-:102D900034C501008C4301008E2200148CA400E491
-:102DA0000000A821AF83001C0044102318400052EB
-:102DB000A38000188E22001400005021ACA200E471
-:102DC00090C3000890A200D53073007FA3A200102A
-:102DD0008CB200E08CB400E4304200FF1053003BA2
-:102DE00093A200108F83001C2407FF80000211C0F3
-:102DF0000062102124420240246300400047102456
-:102E00003063007F3C0980003C08800A006818217C
-:102E1000AD2200248C62003427A4001427A50010E2
-:102E2000024280210290102304400028AFA3001426
-:102E30009062003C00E21024304200FF1440001970
-:102E4000020090219062003C34420040A062003CAD
-:102E50008F86001C93A3001024C200403042007FE4
-:102E6000004828213C0208008C4200F42463000141
-:102E7000306400FF14820002A3A30010A3A000107E
-:102E800093A20010AFA50014000211C0244202401A
-:102E900000C2102100471024AD2200240A000B4577
-:102EA00093A200100E0007C3000000003C0280083F
-:102EB00034420100AC5000E093A30010240A00014A
-:102EC000A04300D50A000B4593A200102402000184
-:102ED000154200093C0380008C6202780440FFFE2A
-:102EE0008F82001CAC62024024020002A0620244F5
-:102EF0003C021000AC6202789222000B2403000214
-:102F0000304200FF144300720000000096220008C7
-:102F1000304300FF24020082146200402402008437
-:102F20003C028000344901008D22000C95230006EC
-:102F3000000216023063FFFF3045003F24020027E5
-:102F400010A2000FAF83001428A200281040000830
-:102F5000240200312402002110A2000924020025CD
-:102F600010A20007938200190A000BBD00000000A8
-:102F700010A20007938200190A000BBD0000000098
-:102F80000E000777012020210A000C3D0000000000
-:102F90003C0380008C6202780440FFFE8F82001C9C
-:102FA000AC62024024020002A06202443C02100013
-:102FB000AC6202780A000C3D000000009523000678
-:102FC000912400058D25000C8D2600108D270018FA
-:102FD0008D28001C8D290020244200013C0108009E
-:102FE000A42356C63C010800A02456C53C01080095
-:102FF000AC2556CC3C010800AC2656D03C0108005C
-:10300000AC2756D83C010800AC2856DC3C0108002F
-:10301000AC2956E00A000C3DA38200191462000A94
-:10302000240200813C02800834420100944500EAF9
-:10303000922600058F84001C30A5FFFF30C600FFDC
-:103040000A000BFE3C0760211462005C00000000D7
-:103050009222000A304300FF306200201040000737
-:10306000306200403C02800834420100944500EA8E
-:103070008F84001C0A000BFC24060040104000074F
-:10308000000316003C02800834420100944500EA27
-:103090008F84001C0A000BFC24060041000216036A
-:1030A000044100463C02800834420100944500EA95
-:1030B0008F84001C2406004230A5FFFF3C076019E6
-:1030C0000E000901000000000A000C3D0000000095
-:1030D0009222000B24040016304200FF1044000628
-:1030E0003C0680009222000B24030017304200FFB0
-:1030F000144300320000000034C5010090A2000B10
-:10310000304200FF1444000B000080218CA20020FC
-:103110008CA400202403FF800043102400021140EF
-:103120003084007F004410253C032000004310251C
-:10313000ACC2083094A2000800021400000214037C
-:10314000044200012410000194A2000830420080D3
-:103150005040001A0200A82194A20008304220002A
-:10316000504000160200A8218CA300183C021C2D20
-:10317000344219ED106200110200A8213C0208003F
-:103180008C4200D4104000053C0280082403000457
-:1031900034420100A04300FC3C028008344201009C
-:1031A000944500EA8F84001C2406000630A5FFFF2A
-:1031B0000E0009013C0760210200A8210E00093918
-:1031C000000000009222000A304200081040000473
-:1031D00002A010210E0013790000000002A01021AF
-:1031E0008FBF00308FB5002C8FB400288FB3002420
-:1031F0008FB200208FB1001C8FB0001803E00008D0
-:1032000027BD00382402FF80008220243C02900069
-:1032100034420007008220253C028000AC4400209C
-:103220003C0380008C6200200440FFFE0000000090
-:1032300003E00008000000003C0380002402FF803F
-:10324000008220243462000700822025AC64002024
-:103250008C6200200440FFFE0000000003E0000834
-:103260000000000027BDFFD8AFB3001CAFB10014B1
-:10327000AFB00010AFBF0020AFB200183C1180000B
-:103280003C0280088E32002034530100AE2400201E
-:10329000966300EA000514003C074000004738250B
-:1032A00000A08021000030210E0009013065FFFFE1
-:1032B000240200A1160200022402FFFFA2620009FC
-:1032C000AE3200208FBF00208FB3001C8FB20018D9
-:1032D0008FB100148FB0001003E0000827BD002854
-:1032E0003C0280082403000527BDFFE834420100AA
-:1032F000A04300FCAFBF00103C0280008C420100E4
-:10330000240500A1004020210E000C67AF82001CA4
-:103310003C0380008C6202780440FFFE8F82001C18
-:103320008FBF001027BD0018AC62024024020002CB
-:10333000A06202443C021000AC62027803E0000884
-:103340000000000027BDFFE83C068000AFBF001072
-:1033500034C7010094E20008304400FF3883008243
-:10336000388200842C6300012C4200010062182581
-:103370001060002D24020083938200195040003B0E
-:103380008FBF00103C020800904256CC8CC4010054
-:103390003C06080094C656C63045003F38A30032AC
-:1033A00038A2003F2C6300012C4200010062182566
-:1033B000AF84001CAF860014A380001914600007BE
-:1033C00000E020212402002014A2001200000000CE
-:1033D0003402FFFF14C2000F00000000240200208E
-:1033E00014A2000500E028218CE300142402FFFF52
-:1033F0005062000B8FBF00103C040800248456C0AC
-:10340000000030210E000706240700010A000CD638
-:103410008FBF00100E000777000000008FBF001064
-:103420000A00093927BD001814820004240200850F
-:103430008CC501040A000CE1000020211482000662
-:103440002482FF808CC50104240440008FBF00103B
-:103450000A00016727BD0018304200FF2C4200021D
-:1034600010400004240200228FBF00100A000B2726
-:1034700027BD0018148200048F8200248FBF001023
-:103480000A000C8627BD00188C42000C1040001E5C
-:1034900000E0282190E300092402001814620003D0
-:1034A000240200160A000CFC240300081462000722
-:1034B00024020017240300123C02800834420080DA
-:1034C000A04300090A000D0994A7000854620007F0
-:1034D00094A700088F82FF942404FFFE9043000508
-:1034E00000641824A043000594A7000890A6001BC0
-:1034F0008CA4000094A500068FBF001000073C00BC
-:103500000A0008DC27BD00188FBF001003E0000888
-:1035100027BD00188F8500243C04800094A2002A57
-:103520008CA30034000230C02402FFF000C210243B
-:1035300000621821AC83003C8CA200303C03800068
-:10354000AC8200383C02005034420010AC620030C3
-:103550000000000000000000000000008C6200007D
-:10356000304200201040FFFD30C20008104000062D
-:103570003C0280008C620408ACA200208C62040C27
-:103580000A000D34ACA200248C430400ACA300203C
-:103590008C420404ACA200243C0300203C028000C6
-:1035A000AC4300303C0480008C8200300043102487
-:1035B0001440FFFD8F8600243C020040AC820030A6
-:1035C00094C3002A94C2002894C4002C94C5002EF1
-:1035D00024630001004410213064FFFFA4C20028CE
-:1035E00014850002A4C3002AA4C0002A03E0000836
-:1035F000000000008F84002427BDFFE83C05800404
-:1036000024840010AFBF00100E000E472406000AED
-:103610008F840024948200129483002E3042000F85
-:10362000244200030043180424027FFF0043102BB0
-:1036300010400002AC8300000000000D0E000D13CE
-:10364000000000008F8300248FBF001027BD0018EA
-:10365000946200149463001A3042000F00021500B7
-:10366000006218253C02800003E00008AC4300A083
-:103670008F8300243C028004944400069462001A64
-:103680008C650000A4640016004410233042FFFF44
-:103690000045102B03E00008384200018F8400240D
-:1036A0003C0780049486001A8C85000094E2000692
-:1036B000A482001694E3000600C310233042FFFFEB
-:1036C0000045102B384200011440FFF8A483001677
-:1036D00003E00008000000008F8400243C02800406
-:1036E000944200069483001A8C850000A482001680
-:1036F000006210233042FFFF0045102B38420001CA
-:103700005040000D8F850024006030213C0780046C
-:1037100094E20006A482001694E3000600C310237E
-:103720003042FFFF0045102B384200011440FFF8E3
-:10373000A48300168F8500243C03800034620400BB
-:103740008CA40020AF820020AC6400388CA200243E
-:10375000AC62003C3C020005AC62003003E00008B3
-:10376000ACA000048F8400243C0300068C8200047B
-:1037700000021140004310253C038000AC62003081
-:103780000000000000000000000000008C6200004B
-:10379000304200101040FFFD34620400AC80000491
-:1037A00003E00008AF8200208F86002427BDFFE0E1
-:1037B000AFB10014AFB00010AFBF00188CC300044D
-:1037C0008CC500248F820020309000FF94C4001A22
-:1037D00024630001244200202484000124A7002047
-:1037E000ACC30004AF820020A4C4001AACC70024FC
-:1037F00004A100060000882104E2000594C2001A1A
-:103800008CC2002024420001ACC2002094C2001AE5
-:1038100094C300282E040001004310262C4200010E
-:10382000004410245040000594C2001A24020001F4
-:10383000ACC2000894C2001A94C300280010202BC8
-:10384000004310262C4200010044102514400007BC
-:10385000000000008CC20008144000042402001084
-:103860008CC300041462000F8F8500240E000DA786
-:10387000241100018F820024944300289442001AEE
-:1038800014430003000000000E000D1300000000B0
-:10389000160000048F8500240E000D840000000037
-:1038A0008F85002494A2001E94A4001C24420001D1
-:1038B0003043FFFF14640002A4A2001EA4A0001E57
-:1038C0001200000A3C02800494A2001494A3001A7F
-:1038D0003042000F00021500006218253C028000F3
-:1038E000AC4300A00A000E1EACA0000894420006E3
-:1038F00094A3001A8CA40000A4A200160062102356
-:103900003042FFFF0044102B384200011040000DF0
-:1039100002201021006030213C07800494E2000660
-:10392000A4A2001694E3000600C310233042FFFF58
-:103930000044102B384200011440FFF8A4A30016E5
-:10394000022010218FBF00188FB100148FB000101B
-:1039500003E0000827BD002003E00008000000008D
-:103960008F82002C3C03000600021140004310250A
-:103970003C038000AC62003000000000000000004A
-:10398000000000008C620000304200101040FFFD7B
-:1039900034620400AF82002803E00008AF80002CEE
-:1039A00003E000080000102103E000080000000010
-:1039B0003084FFFF30A5FFFF0000182110800007B2
-:1039C000000000003082000110400002000420428C
-:1039D000006518210A000E3D0005284003E000089C
-:1039E0000060102110C0000624C6FFFF8CA200005A
-:1039F00024A50004AC8200000A000E4724840004C1
-:103A000003E000080000000010A0000824A3FFFF4E
-:103A1000AC86000000000000000000002402FFFF50
-:103A20002463FFFF1462FFFA2484000403E000080B
-:103A3000000000003C0280083442008024030001A2
-:103A4000AC43000CA4430010A4430012A443001490
-:103A500003E00008A44300168F82002427BDFFD88E
-:103A6000AFB3001CAFB20018AFB10014AFB000107C
-:103A7000AFBF00208C47000C248200802409FF8007
-:103A80003C08800E3043007F008080213C0A80008B
-:103A9000004920240068182130B100FF30D200FF17
-:103AA00010E000290000982126020100AD44002CFE
-:103AB000004928243042007F004820219062000005
-:103AC00024030050304200FF1443000400000000B3
-:103AD000AD45002C948200EA3053FFFF0E000D84A8
-:103AE000000000008F8200248F83002000112C0032
-:103AF0009442001E001224003484000100A22825F4
-:103B00003C02400000A22825AC7000008FBF0020BE
-:103B1000AC6000048FB20018AC7300088FB10014C1
-:103B2000AC60000C8FB3001CAC6400108FB00010B0
-:103B3000AC60001424040001AC60001827BD00280C
-:103B40000A000DB8AC65001C8FBF00208FB3001CAD
-:103B50008FB200188FB100148FB0001003E000087E
-:103B600027BD00283C06800034C201009043000FAE
-:103B7000240200101062000E2865001110A000073A
-:103B800024020012240200082405003A10620006F4
-:103B90000000302103E0000800000000240500358B
-:103BA0001462FFFC000030210A000E6400000000D7
-:103BB0008CC200748F83FF9424420FA003E000089E
-:103BC000AC62000C27BDFFE8AFBF00100E0003423F
-:103BD000240500013C0480088FBF0010240200016E
-:103BE00034830080A462001227BD00182402000163
-:103BF00003E00008A080001A27BDFFE0AFB2001864
-:103C0000AFB10014AFB00010AFBF001C30B2FFFF67
-:103C10000E000332008088213C028008345000806E
-:103C20009202000924030004304200FF1443000CF8
-:103C30003C028008124000082402000A0E000E5BBD
-:103C400000000000920200052403FFFE0043102440
-:103C5000A202000524020012A20200093C02800810
-:103C600034420080022020210E00033DA0400027A6
-:103C700016400003022020210E000EBF00000000AD
-:103C800002202021324600FF8FBF001C8FB2001897
-:103C90008FB100148FB00010240500380A000E64A4
-:103CA00027BD002027BDFFE0AFBF001CAFB200184A
-:103CB000AFB10014AFB000100E00033200808021BD
-:103CC0000E000E5B000000003C02800834450080BE
-:103CD00090A2000924120018305100FF1232000394
-:103CE0000200202124020012A0A2000990A20005D7
-:103CF0002403FFFE004310240E00033DA0A2000594
-:103D00000200202124050020163200070000302187
-:103D10008FBF001C8FB200188FB100148FB000103D
-:103D20000A00034227BD00208FBF001C8FB200187D
-:103D30008FB100148FB00010240500390A000E6402
-:103D400027BD002027BDFFE83C028000AFB0001077
-:103D5000AFBF0014344201009442000C2405003629
-:103D60000080802114400012304600FF0E00033214
-:103D7000000000003C02800834420080240300124E
-:103D8000A043000990430005346300100E000E5B51
-:103D9000A04300050E00033D020020210200202167
-:103DA0000E000342240500200A000F3C0000000022
-:103DB0000E000E64000000000E00033202002021FD
-:103DC0003C0280089043001B2405FF9F0200202135
-:103DD000006518248FBF00148FB00010A043001B93
-:103DE0000A00033D27BD001827BDFFE0AFBF001844
-:103DF000AFB10014AFB0001030B100FF0E000332BD
-:103E0000008080213C02800824030012344200809C
-:103E10000E000E5BA04300090E00033D02002021AE
-:103E200002002021022030218FBF00188FB1001422
-:103E30008FB00010240500350A000E6427BD002055
-:103E40003C0480089083000E9082000A1443000B0B
-:103E5000000028218F82FF942403005024050001D4
-:103E600090420000304200FF1443000400000000B4
-:103E70009082000E24420001A082000E03E00008A0
-:103E800000A010213C0380008C6201F80440FFFE7A
-:103E900024020002AC6401C0A06201C43C02100014
-:103EA00003E00008AC6201F827BDFFE0AFB20018E4
-:103EB0003C128008AFB10014AFBF001CAFB00010BF
-:103EC00036510080922200092403000A304200FF8C
-:103ED0001443003E000000008E4300048E22003890
-:103EE000506200808FBF001C92220000240300500B
-:103EF000304200FF144300253C0280008C42014008
-:103F00008E4300043642010002202821AC43001CED
-:103F10009622005C8E2300383042FFFF00021040E2
-:103F200000621821AE23001C8E4300048E2400384A
-:103F30009622005C006418233042FFFF0003184300
-:103F4000000210400043102A10400006000000004C
-:103F50008E4200048E230038004310230A000FAA6B
-:103F6000000220439622005C3042FFFF0002204006
-:103F70003C0280083443010034420080ACA4002C91
-:103F8000A040002424020001A062000C0E000F5E7D
-:103F900000000000104000538FBF001C3C02800056
-:103FA0008C4401403C0380008C6201F80440FFFE19
-:103FB00024020002AC6401C0A06201C43C021000F3
-:103FC000AC6201F80A0010078FBF001C92220009A2
-:103FD00024030010304200FF144300043C02800020
-:103FE0008C4401400A000FEE0000282192220009B3
-:103FF00024030016304200FF14430006240200147C
-:10400000A22200093C0280008C4401400A001001F9
-:104010008FBF001C8E2200388E23003C00431023EB
-:10402000044100308FBF001C92220027244200016F
-:10403000A2220027922200272C42000414400016DE
-:104040003C1080009222000924030004304200FF4B
-:10405000144300093C0280008C4401408FBF001CC7
-:104060008FB200188FB100148FB000102405009398
-:104070000A000ECC27BD00208C440140240500938B
-:104080008FBF001C8FB200188FB100148FB00010CA
-:104090000A000F4827BD00208E0401400E000332A5
-:1040A000000000008E4200042442FFFFAE420004E4
-:1040B0008E22003C2442FFFFAE22003C0E00033D56
-:1040C0008E0401408E0401408FBF001C8FB2001887
-:1040D0008FB100148FB00010240500040A000342C1
-:1040E00027BD00208FB200188FB100148FB00010D0
-:1040F00003E0000827BD00203C0680008CC2018838
-:104100003C038008346500809063000E00021402B6
-:10411000304400FF306300FF1464000E3C0280084E
-:1041200090A20026304200FF104400098F82FF94C5
-:10413000A0A400262403005090420000304200FF5B
-:1041400014430006000000000A0005A18CC4018091
-:104150003C02800834420080A044002603E00008AE
-:104160000000000027BDFFE030E700FFAFB20018FD
-:10417000AFBF001CAFB10014AFB0001000809021A1
-:1041800014E0000630C600FF000000000000000D33
-:10419000000000000A001060240001163C038008A3
-:1041A0009062000E304200FF14460023346200800B
-:1041B00090420026304200FF1446001F000000001D
-:1041C0009062000F304200FF1446001B0000000008
-:1041D0009062000A304200FF144600038F90FF9463
-:1041E0000000000D8F90FF948F82FF983C1180009B
-:1041F000AE05003CAC450000A066000A0E0003328C
-:104200008E240100A20000240E00033D8E24010034
-:104210003C0380008C6201F80440FFFE240200028F
-:10422000AC7201C0A06201C43C021000AC6201F893
-:104230000A0010618FBF001C000000000000000D8C
-:10424000000000002400013F8FBF001C8FB2001847
-:104250008FB100148FB0001003E0000827BD0020CC
-:104260008F83FF943C0280008C44010034420100A3
-:104270008C65003C9046001B0A00102724070001B3
-:104280003C0280089043000E9042000A0043102632
-:10429000304200FF03E000080002102B27BDFFE0C2
-:1042A0003C028008AFB10014AFB00010AFBF0018DF
-:1042B0003450008092020005240300303042003068
-:1042C00014430085008088218F8200248C42000CDA
-:1042D000104000828FBF00180E000D840000000007
-:1042E0008F860020ACD100009202000892030009E2
-:1042F000304200FF00021200306300FF004310252F
-:10430000ACC200049202004D000216000002160327
-:1043100004410005000000003C0308008C630048D5
-:104320000A00109F3C1080089202000830420040B2
-:10433000144000030000182192020027304300FFC0
-:104340003C108008361100809222004D00031E00B0
-:10435000304200FF0002140000621825ACC30008C0
-:104360008E2400308F820024ACC4000C8E250034D3
-:104370009443001E3C02C00BACC50010006218251F
-:104380008E22003800002021ACC200148E22003C96
-:10439000ACC200180E000DB8ACC3001C8E020004A5
-:1043A0008F8400203C058000AC8200008E2200201B
-:1043B000AC8200048E22001CAC8200088E220058C1
-:1043C0008CA3007400431021AC82000C8E22002CC0
-:1043D000AC8200108E2200408E23004400021400A4
-:1043E00000431025AC8200149222004D240300806B
-:1043F000304200FF1443000400000000AC800018AD
-:104400000A0010E38F8200248E23000C2402000196
-:104410001062000E2402FFFF92220008304200408A
-:104420001440000A2402FFFF8E23000C8CA20074AB
-:10443000006218233C0208000062102414400002AD
-:10444000000028210060282100051043AC820018DC
-:104450008F820024000020219443001E3C02C00CE7
-:10446000006218258F8200200E000DB8AC43001C9E
-:104470003C038008346201008C4200008F850020DC
-:10448000346300808FBF0018ACA20000ACA0000411
-:104490008C6400488F8200248FB10014ACA4000803
-:1044A000ACA0000CACA00010906300059446001E68
-:1044B0003C02400D00031E0000C23025ACA30014D6
-:1044C0008FB00010ACA0001824040001ACA6001CA2
-:1044D0000A000DB827BD00208FBF00188FB100144F
-:1044E0008FB0001003E0000827BD00203C028000D0
-:1044F0009443007C3C02800834460100308400FF75
-:104500003065FFFF2402000524A34650A0C4000C20
-:104510005482000C3065FFFF90C2000D2C42000752
-:104520001040000724A30A0090C3000D24020014C9
-:104530000062100400A210210A00111F3045FFFF85
-:104540003065FFFF3C0280083442008003E0000831
-:10455000A44500143C03800834680080AD05003891
-:10456000346701008CE2001C308400FF00A210239D
-:104570001840000330C600FF24A2FFFCACE2001C80
-:1045800030820001504000083C0380088D02003C4E
-:1045900000A2102304410012240400058C620004D0
-:1045A00010A2000F3C0380088C62000414A2001EBD
-:1045B000000000003C0208008C4200D8304200207D
-:1045C000104000093C0280083462008090630008BB
-:1045D0009042004C144300043C0280082404000470
-:1045E0000A00110900000000344300803442010039
-:1045F000A040000C24020001A462001410C0000AB4
-:104600003C0280008C4401003C0380008C6201F875
-:104610000440FFFE24020002AC6401C0A06201C499
-:104620003C021000AC6201F803E00008000000004A
-:1046300027BDFFE800A61823AFBF00101860008058
-:10464000308800FF3C02800834470080A0E000244E
-:1046500034440100A0E000278C82001C00A210233B
-:1046600004400056000000008CE2003C94E3005C33
-:104670008CE4002C004530233063FFFF00C3182179
-:104680000083202B1080000400E018218CE2002C15
-:104690000A00117800A2102194E2005C3042FFFF72
-:1046A00000C2102100A21021AC62001C3C02800854
-:1046B000344400809482005C8C83001C3042FFFFF5
-:1046C0000002104000A210210043102B10400004F3
-:1046D000000000008C82001C0A00118B3C06800840
-:1046E0009482005C3042FFFF0002104000A21021C3
-:1046F0003C06800834C3010034C70080AC82001C33
-:10470000A060000CACE500388C62001C00A21023F5
-:104710001840000224A2FFFCAC62001C3102000120
-:10472000104000083C0380088CE2003C00A21023EB
-:1047300004410012240400058CC2000410A20010E1
-:104740008FBF00108C62000414A2004F8FBF0010B6
-:104750003C0208008C4200D8304200201040000A81
-:104760003C02800834620080906300089042004C54
-:10477000144300053C028008240400048FBF00108D
-:104780000A00110927BD001834430080344201009B
-:10479000A040000C24020001A46200143C0280002E
-:1047A0008C4401003C0380008C6201F80440FFFE51
-:1047B000240200020A0011D8000000008CE2001C54
-:1047C000004610230043102B54400001ACE5001CB0
-:1047D00094E2005C3042FFFF0062102B144000079F
-:1047E0002402000294E2005C8CE3001C3042FFFFD4
-:1047F00000621821ACE3001C24020002ACE5003882
-:104800000E000F5EA082000C1040001F8FBF001032
-:104810003C0280008C4401003C0380008C6201F863
-:104820000440FFFE24020002AC6401C0A06201C487
-:104830003C021000AC6201F80A0011F08FBF0010BA
-:1048400031020010104000108FBF00103C028008A1
-:10485000344500808CA3001C94A2005C00661823E1
-:104860003042FFFF006218213C023FFF3444FFFF4B
-:104870000083102B544000010080182100C3102138
-:10488000ACA2001C8FBF001003E0000827BD001879
-:1048900027BDFFE800C0402100A63023AFBF0010B5
-:1048A00018C00026308A00FF3C028008344900808E
-:1048B0008D24001C8D23002C008820230064182BDD
-:1048C0001060000F344701008CE2002000461021E8
-:1048D000ACE200208CE200200044102B1440000BBE
-:1048E0003C023FFF8CE2002000441023ACE2002099
-:1048F0009522005C3042FFFF0A0012100082202146
-:10490000ACE00020008620213C023FFF3443FFFF43
-:104910000064102B54400001006020213C028008FC
-:104920003442008000851821AC43001CA0400024C4
-:10493000A04000270A0012623C03800831420010A8
-:10494000104000433C0380083C06800834C40080CB
-:104950008C82003C004810235840003E34660080A2
-:104960009082002424420001A0820024908200242E
-:104970003C0308008C630024304200FF0043102BEE
-:10498000144000688FBF001034C201008C42001C2C
-:1049900000A2102318400063000000008CC3000434
-:1049A0009482005C006818233042FFFF0003184324
-:1049B000000210400043102A1040000500000000D3
-:1049C0008CC20004004810230A0012450002104364
-:1049D0009482005C3042FFFF000210403C068008D9
-:1049E000AC82002C34C5008094A2005C8CA4002C06
-:1049F00094A3005C3042FFFF00021040008220219F
-:104A00003063FFFF0083202101041021ACA2001CB1
-:104A10008CC2000434C60100ACC2001C2402000297
-:104A20000E000F5EA0C2000C1040003E8FBF0010B1
-:104A30003C0280008C4401003C0380008C6201F841
-:104A40000440FFFE240200020A001292000000004F
-:104A500034660080ACC50038346401008C82001CD0
-:104A600000A210231840000224A2FFFCAC82001C0C
-:104A7000314200015040000A3C0380088CC2003CD7
-:104A800000A2102304430014240400058C620004D7
-:104A900014A200033C0380080A00128424040005C9
-:104AA0008C62000414A2001F8FBF00103C0208009B
-:104AB0008C4200D8304200201040000A3C0280089E
-:104AC00034620080906300089042004C144300055B
-:104AD0003C028008240400048FBF00100A00110962
-:104AE00027BD00183443008034420100A040000C70
-:104AF00024020001A46200143C0280008C440100E6
-:104B00003C0380008C6201F80440FFFE2402000296
-:104B1000AC6401C0A06201C43C021000AC6201F8A8
-:104B20008FBF001003E0000827BD001827BDFFE875
-:104B30003C0A8008AFBF0010354900808D22003C40
-:104B400000C04021308400FF004610231840009D23
-:104B500030E700FF354701002402000100A63023A2
-:104B6000A0E0000CA0E0000DA522001418C0002455
-:104B7000308200108D23001C8D22002C0068182329
-:104B80000043102B1040000F000000008CE20020BA
-:104B900000461021ACE200208CE200200043102BE4
-:104BA0001440000B3C023FFF8CE200200043102326
-:104BB000ACE200209522005C3042FFFF0A0012C1E7
-:104BC00000621821ACE00020006618213C023FFF83
-:104BD0003446FFFF00C3102B5440000100C01821D1
-:104BE0003C0280083442008000651821AC43001C60
-:104BF000A0400024A04000270A00130F3C038008B7
-:104C0000104000403C0380088D22003C00481023E7
-:104C10005840003D34670080912200242442000166
-:104C2000A1220024912200243C0308008C6300246C
-:104C3000304200FF0043102B1440009A8FBF001039
-:104C40008CE2001C00A21023184000960000000017
-:104C50008D4300049522005C006818233042FFFF5A
-:104C600000031843000210400043102A10400005C2
-:104C7000012020218D420004004810230A0012F276
-:104C8000000210439522005C3042FFFF00021040FA
-:104C90003C068008AC82002C34C5008094A2005CE5
-:104CA0008CA4002C94A3005C3042FFFF0002104053
-:104CB000008220213063FFFF0083182101031021AF
-:104CC000ACA2001C8CC2000434C60100ACC2001CA3
-:104CD000240200020E000F5EA0C2000C1040007102
-:104CE0008FBF00103C0280008C4401003C03800018
-:104CF0008C6201F80440FFFE240200020A0013390E
-:104D00000000000034670080ACE500383466010024
-:104D10008CC2001C00A210231840000224A2FFFC39
-:104D2000ACC2001C30820001504000083C038008E7
-:104D30008CE2003C00A2102304430051240400052F
-:104D40008C62000410A2003E3C0380088C620004C8
-:104D500054A200548FBF00103C0208008C4200D8BF
-:104D600030420020104000063C028008346200807F
-:104D7000906300089042004C104300403C028008C1
-:104D80003443008034420100A040000C24020001A2
-:104D9000A46200143C0280008C4401003C038000AB
-:104DA0008C6201F80440FFFE24020002AC6401C0E2
-:104DB000A06201C43C021000AC6201F80A00137743
-:104DC0008FBF001024020005A120002714E2000A72
-:104DD0003C038008354301009062000D2C42000620
-:104DE000504000053C0380089062000D2442000101
-:104DF000A062000D3C03800834670080ACE50038F9
-:104E0000346601008CC2001C00A21023184000026E
-:104E100024A2FFFCACC2001C308200015040000AFA
-:104E20003C0380088CE2003C00A2102304410014E3
-:104E3000240400058C62000414A200033C038008D3
-:104E40000A00136E240400058C62000414A20015ED
-:104E50008FBF00103C0208008C4200D83042002076
-:104E60001040000A3C028008346200809063000811
-:104E70009042004C144300053C02800824040004C6
-:104E80008FBF00100A00110927BD001834430080AD
-:104E900034420100A040000C24020001A46200146E
-:104EA0008FBF001003E0000827BD00183C0B8008EE
-:104EB00027BDFFE83C028000AFBF00103442010074
-:104EC000356A00809044000A356901008C45001461
-:104ED0008D4800389123000C308400FF0105102319
-:104EE0001C4000B3306700FF2CE20006504000B1C8
-:104EF0008FBF00102402000100E2300430C2000322
-:104F00005440000800A8302330C2000C144000A117
-:104F100030C20030144000A38FBF00100A00143BC1
-:104F20000000000018C00024308200108D43001CD7
-:104F30008D42002C006818230043102B1040000FF6
-:104F4000000000008D22002000461021AD2200202C
-:104F50008D2200200043102B1440000B3C023FFF29
-:104F60008D22002000431023AD2200209542005CDA
-:104F70003042FFFF0A0013AF00621821AD2000206D
-:104F8000006618213C023FFF3446FFFF00C3102B90
-:104F90005440000100C018213C02800834420080C7
-:104FA00000651821AC43001CA0400024A04000274D
-:104FB0000A0013FD3C038008104000403C038008B9
-:104FC0008D42003C004810231840003D34670080AB
-:104FD0009142002424420001A14200249142002475
-:104FE0003C0308008C630024304200FF0043102B78
-:104FF000144000708FBF00108D22001C00A21023EF
-:105000001840006C000000008D6300049542005CB5
-:10501000006818233042FFFF0003184300021040CD
-:105020000043102A10400005014020218D62000439
-:10503000004810230A0013E0000210439542005C70
-:105040003042FFFF000210403C068008AC82002C7A
-:1050500034C5008094A2005C8CA4002C94A3005C56
-:105060003042FFFF00021040008220213063FFFF2A
-:105070000083182101031021ACA2001C8CC2000483
-:1050800034C60100ACC2001C240200020E000F5EF8
-:10509000A0C2000C104000478FBF00103C028000EF
-:1050A0008C4401003C0380008C6201F80440FFFE48
-:1050B000240200020A00142D000000003467008062
-:1050C000ACE50038346601008CC2001C00A210233D
-:1050D0001840000224A2FFFCACC2001C3082000178
-:1050E0005040000A3C0380088CE2003C00A21023E0
-:1050F00004430014240400058C62000414A200037D
-:105100003C0380080A00141F240400058C6200047C
-:1051100014A200288FBF00103C0208008C4200D867
-:10512000304200201040000A3C02800834620080B7
-:10513000906300089042004C144300053C02800834
-:10514000240400048FBF00100A00110927BD0018B5
-:105150003443008034420100A040000C24020001CE
-:10516000A46200143C0280008C4401003C038000D7
-:105170008C6201F80440FFFE24020002AC6401C00E
-:10518000A06201C43C021000AC6201F80A00143BAA
-:105190008FBF00108FBF0010010030210A00115A8C
-:1051A00027BD0018010030210A00129927BD001800
-:1051B0008FBF001003E0000827BD00183C038008E3
-:1051C0003464010024020003A082000C8C620004FD
-:1051D00003E00008AC82001C3C05800834A300807A
-:1051E0009062002734A501002406004324420001F8
-:1051F000A0620027906300273C0208008C42004810
-:10520000306300FF146200043C07602194A500EAAB
-:105210000A00090130A5FFFF03E0000800000000BC
-:1052200027BDFFE8AFBF00103C0280000E00144411
-:105230008C4401803C02800834430100A060000CD3
-:105240008C4200048FBF001027BD001803E0000847
-:10525000AC62001C27BDFFE03C028008AFBF001815
-:10526000AFB10014AFB000103445008034460100E7
-:105270003C0880008D09014090C3000C8CA4003CC8
-:105280008CA200381482003B306700FF9502007C3E
-:1052900090A30027146000093045FFFF2402000599
-:1052A00054E200083C04800890C2000D2442000132
-:1052B000A0C2000D0A00147F3C048008A0C0000DAD
-:1052C0003C048008348201009042000C2403000555
-:1052D000304200FF1443000A24A205DC348300801E
-:1052E000906200272C4200075040000524A20A00CB
-:1052F00090630027240200140062100400A2102111
-:105300003C108008361000803045FFFF012020212E
-:105310000E001444A60500149602005C8E030038AB
-:105320003C1180003042FFFF000210400062182153
-:10533000AE03001C0E0003328E24014092020025B1
-:1053400034420040A20200250E00033D8E2401409D
-:105350008E2401403C0380008C6201F80440FFFE73
-:1053600024020002AC6401C0A06201C43C0210002F
-:10537000AC6201F88FBF00188FB100148FB000101D
-:1053800003E0000827BD00203C0360103C02080039
-:1053900024420174AC62502C8C6250003C048000AA
-:1053A00034420080AC6250003C0208002442547C2D
-:1053B0003C010800AC2256003C020800244254384C
-:1053C0003C010800AC2256043C020002AC840008F8
-:1053D000AC82000C03E000082402000100A0302190
-:1053E0003C1C0800279C56083C0200023C050400B7
-:1053F00000852826008220260004102B2CA5000101
-:105400002C840001000210803C0308002463560035
-:105410000085202500431821108000030000102182
-:10542000AC6600002402000103E000080000000058
-:105430003C1C0800279C56083C0200023C05040066
-:1054400000852826008220260004102B2CA50001B0
-:105450002C840001000210803C03080024635600E5
-:105460000085202500431821108000050000102130
-:105470003C02080024425438AC62000024020001BF
-:1054800003E00008000000003C0200023C030400AE
-:1054900000821026008318262C4200012C63000194
-:1054A000004310251040000B000028213C1C080080
-:1054B000279C56083C0380008C62000824050001EC
-:1054C00000431025AC6200088C62000C00441025DB
-:1054D000AC62000C03E0000800A010213C1C080096
-:1054E000279C56083C0580008CA3000C0004202754
-:1054F000240200010064182403E00008ACA3000C9F
-:105500003C020002148200063C0560008CA208D018
-:105510002403FFFE0043102403E00008ACA208D0DF
-:105520003C02040014820005000000008CA208D098
-:105530002403FFFD00431024ACA208D003E00008C0
-:10554000000000003C02601A344200108C430080CE
-:1055500027BDFFF88C440084AFA3000093A3000094
-:10556000240200041462001AAFA4000493A20001F4
-:105570001040000797A300023062FFFC3C0380004C
-:10558000004310218C4200000A001536AFA200042F
-:105590003062FFFC3C03800000431021AC4400005B
-:1055A000A3A000003C0560008CA208D02403FFFEED
-:1055B0003C04601A00431024ACA208D08FA300045E
-:1055C0008FA2000034840010AC830084AC82008081
-:1055D00003E0000827BD000827BDFFE8AFBF0010AB
-:1055E0003C1C0800279C56083C0280008C43000CA1
-:1055F0008C420004004318243C0200021060001496
-:10560000006228243C0204003C04000210A00005B3
-:10561000006210243C0208008C4256000A00155B10
-:1056200000000000104000073C0404003C02080099
-:105630008C4256040040F809000000000A00156082
-:10564000000000000000000D3C1C0800279C5608CC
-:0C5650008FBF001003E0000827BD001809
-:04565C008008024080
-:1056600080080100800800808008000000000C8095
-:105670000000320008000E9808000EF408000F88A1
-:1056800008001028080010748008010080080080BD
-:04569000800800008E
-:0C5694000A0000280000000000000000D8
-:1056A0000000000D6370362E322E31000000000025
-:1056B00006020104000000000000000000000000DD
-:1056C000000000000000000038003C000000000066
-:1056D00000000000000000000000000000000020AA
-:1056E00000000000000000000000000000000000BA
-:1056F00000000000000000000000000000000000AA
-:10570000000000000000000021003800000000013F
-:105710000000002B000000000000000400030D400A
-:105720000000000000000000000000000000000079
-:105730000000000000000000100000030000000056
-:105740000000000D0000000D3C020800244259AC8E
-:105750003C03080024635BF4AC4000000043202BB2
-:105760001480FFFD244200043C1D080037BD9FFC4F
-:1057700003A0F0213C100800261000A03C1C0800EB
-:10578000279C59AC0E0002F6000000000000000D3E
-:1057900027BDFFB4AFA10000AFA20004AFA3000873
-:1057A000AFA4000CAFA50010AFA60014AFA700185F
-:1057B000AFA8001CAFA90020AFAA0024AFAB0028FF
-:1057C000AFAC002CAFAD0030AFAE0034AFAF00389F
-:1057D000AFB8003CAFB90040AFBC0044AFBF004819
-:1057E0000E000820000000008FBF00488FBC00445E
-:1057F0008FB900408FB8003C8FAF00388FAE0034B7
-:105800008FAD00308FAC002C8FAB00288FAA002406
-:105810008FA900208FA8001C8FA700188FA6001446
-:105820008FA500108FA4000C8FA300088FA2000486
-:105830008FA1000027BD004C3C1B60188F7A5030B0
-:10584000377B502803400008AF7A000000A01821E1
-:1058500000801021008028213C0460003C0760008B
-:105860002406000810600006348420788C42000072
-:10587000ACE220088C63000003E00008ACE3200CDD
-:105880000A000F8100000000240300403C02600079
-:1058900003E00008AC4320003C0760008F86000452
-:1058A0008CE520740086102100A2182B14600007DC
-:1058B000000028218F8AFDA024050001A1440013C7
-:1058C0008F89000401244021AF88000403E0000810
-:1058D00000A010218F84FDA08F8500049086001306
-:1058E00030C300FF00A31023AF82000403E00008D0
-:1058F000A08000138F84FDA027BDFFE8AFB000108B
-:10590000AFBF001490890011908700112402002875
-:10591000312800FF3906002830E300FF2485002CE1
-:105920002CD00001106200162484001C0E00006EB2
-:10593000000000008F8FFDA03C05600024020204DF
-:1059400095EE003E95ED003C000E5C0031ACFFFF93
-:10595000016C5025ACAA2010520000012402000462
-:10596000ACA22000000000000000000000000000C9
-:105970008FBF00148FB0001003E0000827BD00188F
-:105980000A0000A6000028218F85FDA027BDFFD8B2
-:10599000AFBF0020AFB3001CAFB20018AFB100140E
-:1059A000AFB000100080982190A4001124B0001C1A
-:1059B00024B1002C308300FF386200280E000090D4
-:1059C0002C5200010E00009800000000020020216F
-:1059D0001240000202202821000028210E00006E43
-:1059E000000000008F8DFDA03C0880003C05600099
-:1059F00095AC003E95AB003C02683025000C4C0095
-:105A0000316AFFFF012A3825ACA7201024020202C8
-:105A1000ACA6201452400001240200028FBF0020D7
-:105A20008FB3001C8FB200188FB100148FB000101C
-:105A300027BD002803E00008ACA2200027BDFFE03E
-:105A4000AFB20018AFB10014AFB00010AFBF001C70
-:105A50003C1160008E2320748F82000430D0FFFF41
-:105A600030F2FFFF1062000C2406008F0E00006E63
-:105A7000000000003C06801F0010440034C5FF00F9
-:105A80000112382524040002AE2720100000302126
-:105A9000AE252014AE2420008FBF001C8FB200184A
-:105AA0008FB100148FB0001000C0102103E0000877
-:105AB00027BD002027BDFFE0AFB0001030D0FFFFB2
-:105AC000AFBF0018AFB100140E00006E30F1FFFF41
-:105AD00000102400009180253C036000AC70201071
-:105AE0008FBF00188FB100148FB000102402000483
-:105AF000AC62200027BD002003E000080000102158
-:105B000027BDFFE03C046018AFBF0018AFB1001420
-:105B1000AFB000108C8850002403FF7F34028071E6
-:105B20000103382434E5380C241F00313C1980006F
-:105B3000AC8550003C11800AAC8253BCAF3F0008DA
-:105B40000E00054CAF9100400E00050A3C116000AC
-:105B50000E00007D000000008E3008083C0F570941
-:105B60002418FFF00218602435EEE00035EDF00057
-:105B7000018E5026018D58262D4600012D69000109
-:105B8000AF86004C0E000D09AF8900503C06601630
-:105B90008CC700003C0860148D0500A03C03FFFF8B
-:105BA00000E320243C02535300052FC2108200550D
-:105BB00034D07C00960201F2A780006C10400003F4
-:105BC000A780007C384B1E1EA78B006C960201F844
-:105BD000104000048F8D0050384C1E1EA78C007C96
-:105BE0008F8D005011A000058F83004C240E0020E3
-:105BF000A78E007CA78E006C8F83004C1060000580
-:105C00009785007C240F0020A78F007CA78F006C55
-:105C10009785007C2CB8008153000001240500808A
-:105C20009784006C2C91040152200001240404008C
-:105C30001060000B3C0260008FBF00188FB1001491
-:105C40008FB0001027BD0020A784006CA785007CC2
-:105C5000A380007EA780007403E00008A780009264
-:105C60008C4704382419103C30FFFFFF13F9000360
-:105C700030A8FFFF1100004624030050A380007EDF
-:105C80009386007E50C00024A785007CA780007CFE
-:105C90009798007CA780006CA7800074A780009272
-:105CA0003C010800AC3800800E00078700000000AF
-:105CB0003C0F60008DED0808240EFFF03C0B600ED9
-:105CC000260C0388356A00100000482100002821B6
-:105CD00001AE20243C105709AF8C0010AF8A004859
-:105CE000AF89001810900023AF8500148FBF0018F3
-:105CF0008FB100148FB0001027BD002003E0000812
-:105D0000AF80005400055080014648218D260004D4
-:105D10000A00014800D180219798007CA784006C7C
-:105D2000A7800074A78000923C010800AC38008076
-:105D30000E000787000000003C0F60008DED080892
-:105D4000240EFFF03C0B600E260C0388356A001011
-:105D5000000048210000282101AE20243C105709F2
-:105D6000AF8C0010AF8A0048AF8900181490FFDF95
-:105D7000AF85001424110001AF9100548FBF0018AB
-:105D80008FB100148FB0001003E0000827BD002081
-:105D90000A00017BA383007E3083FFFF8F880040D1
-:105DA0008F87003C000321403C0580003C020050EE
-:105DB000008248253C0660003C0A010034AC040027
-:105DC0008CCD08E001AA58241160000500000000F5
-:105DD0008CCF08E024E7000101EA7025ACCE08E092
-:105DE0008D19001001805821ACB900388D180014AD
-:105DF000ACB8003CACA9003000000000000000007E
-:105E00000000000000000000000000000000000092
-:105E100000000000000000003C0380008C640000D3
-:105E2000308200201040FFFD3C0F60008DED08E047
-:105E30003C0E010001AE18241460FFE100000000D8
-:105E4000AF87003C03E00008AF8B00588F8500400F
-:105E5000240BFFF03C06800094A7001A8CA90024B4
-:105E600030ECFFFF000C38C000EB5024012A402129
-:105E7000ACC8003C8CA400248CC3003C00831023DD
-:105E800018400033000000008CAD002025A2000166
-:105E90003C0F0050ACC2003835EE00103C068000CC
-:105EA000ACCE003000000000000000000000000048
-:105EB00000000000000000000000000000000000E2
-:105EC000000000003C0480008C9900003338002062
-:105ED0001300FFFD30E20008104000173C0980006D
-:105EE0008C880408ACA800108C83040CACA30014AC
-:105EF0003C1900203C188000AF19003094AE001807
-:105F000094AF001C01CF3021A4A6001894AD001A54
-:105F100025A70001A4A7001A94AB001A94AC001E98
-:105F2000118B00030000000003E0000800000000E7
-:105F300003E00008A4A0001A8D2A0400ACAA0010F7
-:105F40008D240404ACA400140A0002183C1900209B
-:105F50008CA200200A0002003C0F00500A0001EE53
-:105F60000000000027BDFFE8AFBF00100E000232A6
-:105F7000000000008F8900408FBF00103C038000AC
-:105F8000A520000A9528000A9527000427BD0018BF
-:105F90003105FFFF30E6000F0006150000A22025A6
-:105FA00003E00008AC6400803C0508008CA50020DC
-:105FB0008F83000C27BDFFE8AFB00010AFBF001407
-:105FC00010A300100000802124040001020430040A
-:105FD00000A6202400C3102450440006261000010F
-:105FE000001018802787FDA41480000A006718217C
-:105FF000261000012E0900025520FFF38F83000CAC
-:10600000AF85000C8FBF00148FB0001003E00008B4
-:1060100027BD00188C6800003C058000ACA8002457
-:106020000E000234261000013C0508008CA500205B
-:106030000A0002592E0900022405000100851804F7
-:106040003C0408008C84002027BDFFC8AFBF00348B
-:1060500000831024AFBE0030AFB7002CAFB60028CD
-:10606000AFB50024AFB40020AFB3001CAFB200182E
-:10607000AFB1001410400051AFB000108F84004049
-:10608000948700069488000A00E8302330D5FFFF8B
-:1060900012A0004B8FBF0034948B0018948C000A20
-:1060A000016C50233142FFFF02A2482B1520000251
-:1060B00002A02021004020212C8F000515E00002C5
-:1060C00000809821241300040E0001C102602021E9
-:1060D0008F87004002609021AF80004494F4000A52
-:1060E000026080211260004E3291FFFF3C1670006A
-:1060F0003C1440003C1E20003C1760008F99005863
-:106100008F380000031618241074004F0283F82BF8
-:1061100017E0003600000000107E00478F86004424
-:1061200014C0003A2403000102031023022320219B
-:106130003050FFFF1600FFF13091FFFF8F870040C6
-:106140003C1100203C108000AE11003094EB000A9E
-:106150003C178000024B5021A4EA000A94E9000A8F
-:1061600094E800043123FFFF3106000F00062D00E4
-:106170000065F025AEFE008094F3000A94F6001846
-:1061800012D30036001221408CFF00148CF4001052
-:1061900003E468210000C02101A4782B029870213B
-:1061A00001CF6021ACED0014ACEC001002B238233A
-:1061B00030F5FFFF16A0FFB88F8400408FBF00347A
-:1061C0008FBE00308FB7002C8FB600288FB500240B
-:1061D0008FB400208FB3001C8FB200188FB1001451
-:1061E0008FB0001003E0000827BD00381477FFCC03
-:1061F0008F8600440E000EE202002021004018218C
-:106200008F86004410C0FFC9020310230270702360
-:106210008F87004001C368210A0002E431B2FFFF0A
-:106220008F86004414C0FFC93C1100203C10800040
-:106230000A0002AEAE1100300E00046602002021FA
-:106240000A0002DB00401821020020210E0009395B
-:10625000022028210A0002DB004018210E0001EE76
-:10626000000000000A0002C702B2382327BDFFC8A1
-:10627000AFB7002CAFB60028AFB50024AFB40020F4
-:10628000AFB3001CAFB20018AFB10014AFB0001034
-:10629000AFBF00300E00011B241300013C047FFF40
-:1062A0003C0380083C0220003C010800AC20007048
-:1062B0003496FFFF34770080345200033C1512C03F
-:1062C000241400013C1080002411FF800E000245C0
-:1062D000000000008F8700488F8B00188F89001402
-:1062E0008CEA00EC8CE800E8014B302B01092823F4
-:1062F00000A6102314400006014B18231440000E82
-:106300003C05800002A3602B1180000B0000000000
-:106310003C0560008CEE00EC8CED00E88CA4180CC1
-:10632000AF8E001804800053AF8D00148F8F0010C3
-:10633000ADF400003C0580008CBF00003BF900017B
-:10634000333800011700FFE13C0380008C6201003C
-:1063500024060C0010460009000000008C680100B3
-:106360002D043080548000103C0480008C690100B2
-:106370002D2331811060000C3C0480008CAA0100A8
-:1063800011460004000020218CA6010024C5FF81D5
-:1063900030A400FF8E0B01000E000269AE0B00243A
-:1063A0000A00034F3C0480008C8D01002DAC3300AB
-:1063B00011800022000000003C0708008CE70098D4
-:1063C00024EE00013C010800AC2E00983C04800043
-:1063D0008C8201001440000300000000566000148D
-:1063E0003C0440008C9F01008C9801000000982123
-:1063F00003F1C82400193940330F007F00EF7025E6
-:1064000001D26825AC8D08308C8C01008C85010090
-:10641000258B0100017130240006514030A3007F1C
-:106420000143482501324025AC8808303C04400037
-:10643000AE0401380A00030E000000008C99010030
-:10644000240F0020AC99002092F80000330300FFD5
-:10645000106F000C241F0050547FFFDD3C048000AF
-:106460008C8401000E00154E000000000A00034F4E
-:106470003C04800000963824ACA7180C0A000327BF
-:106480008F8F00108C8501000E0008F72404008017
-:106490000A00034F3C04800000A4102B24030001D9
-:1064A00010400009000030210005284000A4102BF6
-:1064B00004A00003000318405440FFFC00052840DE
-:1064C0005060000A0004182B0085382B54E00004AB
-:1064D0000003184200C33025008520230003184222
-:1064E0001460FFF9000528420004182B03E000089F
-:1064F00000C310213084FFFF30C600FF3C0780003E
-:106500008CE201B80440FFFE00064C000124302557
-:106510003C08200000C820253C031000ACE00180AE
-:10652000ACE50184ACE4018803E00008ACE301B809
-:106530003C0660008CC5201C2402FFF03083020062
-:10654000308601001060000E00A2282434A500014E
-:106550003087300010E0000530830C0034A50004C3
-:106560003C04600003E00008AC85201C1060FFFDC7
-:106570003C04600034A5000803E00008AC85201C42
-:1065800054C0FFF334A500020A0003B03087300086
-:1065900027BDFFE8AFB00010AFBF00143C0760009C
-:1065A000240600021080001100A080218F83005873
-:1065B0000E0003A78C6400188F8200580000202171
-:1065C000240600018C45000C0E000398000000001A
-:1065D0001600000224020003000010218FBF0014E7
-:1065E0008FB0001003E0000827BD00188CE8201CC5
-:1065F0002409FFF001092824ACE5201C8F870058EE
-:106600000A0003CD8CE5000C3C02600E00804021A6
-:1066100034460100240900180000000000000000BA
-:10662000000000003C0A00503C0380003547020097
-:10663000AC68003834640400AC65003CAC670030E2
-:106640008C6C0000318B00201160FFFD2407FFFFE0
-:106650002403007F8C8D00002463FFFF248400044A
-:10666000ACCD00001467FFFB24C60004000000004E
-:10667000000000000000000024A402000085282B78
-:106680003C0300203C0E80002529FFFF010540212E
-:10669000ADC300301520FFE00080282103E0000892
-:1066A000000000008F82005827BDFFD8AFB3001C48
-:1066B000AFBF0020AFB20018AFB10014AFB00010F0
-:1066C00094460002008098218C5200182CC300814F
-:1066D0008C4800048C4700088C51000C8C49001039
-:1066E000106000078C4A00142CC4000414800013AE
-:1066F00030EB000730C5000310A0001000000000C0
-:106700002410008B02002021022028210E00039873
-:10671000240600031660000224020003000010217A
-:106720008FBF00208FB3001C8FB200188FB10014F0
-:106730008FB0001003E0000827BD00281560FFF1AE
-:106740002410008B3C0C80003C030020241F00011F
-:10675000AD830030AF9F0044000000000000000047
-:10676000000000002419FFF024D8000F031978243A
-:106770003C1000D0AD88003801F0702524CD000316
-:106780003C08600EAD87003C35850400AD8E0030BE
-:10679000000D38823504003C3C0380008C6B000007
-:1067A000316200201040FFFD0000000010E00008F2
-:1067B00024E3FFFF2407FFFF8CA800002463FFFFF2
-:1067C00024A50004AC8800001467FFFB24840004A7
-:1067D0003C05600EACA60038000000000000000080
-:1067E000000000008F8600543C0400203C0780001D
-:1067F000ACE4003054C000060120202102402021DA
-:106800000E0003A7000080210A00041D02002021C1
-:106810000E0003DD01402821024020210E0003A7C5
-:10682000000080210A00041D0200202127BDFFE096
-:10683000AFB200183092FFFFAFB10014AFBF001C21
-:10684000AFB000101640000D000088210A0004932C
-:106850000220102124050003508500278CE5000C40
-:106860000000000D262800013111FFFF24E2002066
-:106870000232802B12000019AF8200588F82004430
-:10688000144000168F8700583C0670003C0320001F
-:106890008CE5000000A62024148300108F84006083
-:1068A000000544023C09800000A980241480FFE90F
-:1068B000310600FF2CCA000B5140FFEB26280001D7
-:1068C000000668803C0E080025CE575801AE6021B6
-:1068D0008D8B0000016000080000000002201021E4
-:1068E0008FBF001C8FB200188FB100148FB0001042
-:1068F00003E0000827BD00200E0003982404008454
-:106900001600FFD88F8700580A000474AF8000601B
-:10691000020028210E0003BF240400018F870058C5
-:106920000A000474AF820060020028210E0003BF39
-:10693000000020210A0004A38F8700580E000404E1
-:10694000020020218F8700580A000474AF82006083
-:1069500030AFFFFF000F19C03C0480008C9001B8DD
-:106960000600FFFE3C1920043C181000AC83018097
-:10697000AC800184AC990188AC9801B80A00047518
-:106980002628000190E2000390E30002000020218D
-:106990000002FE0000033A0000FF2825240600083C
-:1069A0000E000398000000001600FFDC2402000324
-:1069B0008F870058000010210A000474AF82006025
-:1069C00090E8000200002021240600090A0004C308
-:1069D00000082E0090E4000C240900FF308500FF21
-:1069E00010A900150000302190F9000290F8000372
-:1069F000308F00FF94EB000400196E000018740043
-:106A0000000F62000186202501AE5025014B28258C
-:106A10003084FF8B0A0004C32406000A90E30002BE
-:106A200090FF0004000020210003360000DF28252D
-:106A30000A0004C32406000B0A0004D52406008BB8
-:106A4000000449C23127003F000443423C02800059
-:106A500000082040240316802CE60020AC43002CC4
-:106A600024EAFFE02482000114C0000330A900FFE3
-:106A700000801021314700FF000260803C0D800043
-:106A8000240A0001018D20213C0B000E00EA28049D
-:106A9000008B302111200005000538278CCE000026
-:106AA00001C5382503E00008ACC700008CD8000001
-:106AB0000307782403E00008ACCF000027BDFFE007
-:106AC000AFB10014AFB00010AFBF00183C076000BA
-:106AD0008CE408083402F0003C1160003083F000C0
-:106AE000240501C03C04800E000030211062000625
-:106AF000241000018CEA08083149F0003928E00030
-:106B00000008382B000780403C0D0200AE2D081411
-:106B1000240C16803C0B80008E2744000E000F8B47
-:106B2000AD6C002C120000043C02169124050001FB
-:106B3000120500103C023D2C345800E0AE384408E9
-:106B40003C1108008E31007C8FBF00183C066000AD
-:106B500000118540360F16808FB100148FB00010E1
-:106B60003C0E020027BD0020ACCF442003E000080B
-:106B7000ACCE08103C0218DA345800E0AE384408B5
-:106B80003C1108008E31007C8FBF00183C0660006D
-:106B900000118540360F16808FB100148FB00010A1
-:106BA0003C0E020027BD0020ACCF442003E00008CB
-:106BB000ACCE08100A0004EB240500010A0004EB27
-:106BC0000000282124020400A7820024A780001CC2
-:106BD000000020213C06080024C65A582405FFFF67
-:106BE00024890001000440803124FFFF01061821A0
-:106BF0002C87002014E0FFFAAC6500002404040098
-:106C0000A7840026A780001E000020213C06080063
-:106C100024C65AD82405FFFF248D0001000460809B
-:106C200031A4FFFF018658212C8A00201540FFFA6D
-:106C3000AD650000A7800028A7800020A780002263
-:106C4000000020213C06080024C65B582405FFFFF5
-:106C5000249900010004C0803324FFFF030678213B
-:106C60002C8E000415C0FFFAADE500003C05600065
-:106C70008CA73D002403E08F00E31024344601403C
-:106C800003E00008ACA63D002487007F000731C266
-:106C900024C5FFFF000518C2246400013082FFFFF5
-:106CA000000238C0A78400303C010800AC27003047
-:106CB000AF80002C0000282100002021000030219E
-:106CC0002489000100A728213124FFFF2CA81701E7
-:106CD000110000032C8300801460FFF924C600011A
-:106CE00000C02821AF86002C10C0001DA786002AF6
-:106CF00024CAFFFF000A11423C08080025085B581F
-:106D00001040000A00002021004030212407FFFF2E
-:106D1000248E00010004688031C4FFFF01A86021B7
-:106D20000086582B1560FFFAAD87000030A2001FC7
-:106D30005040000800043080240300010043C804D0
-:106D400000041080004878212738FFFF03E0000886
-:106D5000ADF8000000C820212405FFFFAC8500002D
-:106D600003E000080000000030A5FFFF30C6FFFF71
-:106D700030A8001F0080602130E700FF0005294295
-:106D80000000502110C0001D24090001240B000147
-:106D900025180001010B2004330800FF0126782686
-:106DA000390E00202DED00012DC2000101A2182591
-:106DB0001060000D014450250005C880032C4021BF
-:106DC0000100182110E0000F000A20278D040000A8
-:106DD000008A1825AD03000024AD00010000402109
-:106DE0000000502131A5FFFF252E000131C9FFFF12
-:106DF00000C9102B1040FFE72518000103E0000830
-:106E0000000000008D0A0000014440240A0005D162
-:106E1000AC68000027BDFFE830A5FFFF30C6FFFFCC
-:106E2000AFB00010AFBF001430E7FFFF00005021EB
-:106E30003410FFFF0000602124AF001F00C0482174
-:106E4000241800012419002005E0001601E010219B
-:106E50000002F943019F682A0009702B01AE40240B
-:106E600011000017000C18800064102110E00005CC
-:106E70008C4B000000F840040008382301675824B8
-:106E800000003821154000410000402155600016E7
-:106E90003169FFFF258B0001316CFFFF05E1FFEC3D
-:106EA00001E0102124A2003E0002F943019F682A5C
-:106EB0000009702B01AE40241500FFEB000C188078
-:106EC000154600053402FFFF020028210E0005B51B
-:106ED00000003821020010218FBF00148FB0001075
-:106EE00003E0000827BD00181520000301601821E9
-:106EF000000B1C0224080010306A00FF154000053A
-:106F0000306E000F250D000800031A0231A800FFA3
-:106F1000306E000F15C00005307F000325100004FF
-:106F200000031902320800FF307F000317E000055C
-:106F3000386900012502000200031882304800FF72
-:106F4000386900013123000110600004310300FFA3
-:106F5000250A0001314800FF310300FF000C6940A1
-:106F600001A34021240A000110CAFFD53110FFFF00
-:106F7000246E000131C800FF1119FFC638C9000195
-:106F80002D1F002053E0001C258B0001240D000163
-:106F90000A000648240E002051460017258B0001E8
-:106FA00025090001312800FF2D0900205120001281
-:106FB000258B000125430001010D5004014B1024D5
-:106FC000250900011440FFF4306AFFFF3127FFFF5D
-:106FD00010EE000C2582FFFF304CFFFF0000502117
-:106FE0003410FFFF312800FF2D0900205520FFF24B
-:106FF00025430001258B0001014648260A000602B0
-:10700000316CFFFF00003821000050210A000654B7
-:107010003410FFFF27BDFFD8AFB0001030F0FFFFE6
-:10702000AFB10014001039423211FFE000071080A8
-:10703000AFB3001C00B1282330D3FFFFAFB200185C
-:1070400030A5FFFF00809021026030210044202104
-:10705000AFBF00200E0005E03207001F022288218A
-:107060003403FFFF0240202102002821026030216A
-:1070700000003821104300093231FFFF02201021A7
-:107080008FBF00208FB3001C8FB200188FB1001487
-:107090008FB0001003E0000827BD00280E0005E0B7
-:1070A0000000000000408821022010218FBF002036
-:1070B0008FB3001C8FB200188FB100148FB0001076
-:1070C00003E0000827BD0028000424003C03600002
-:1070D000AC603D0810A00002348210063482101605
-:1070E00003E00008AC623D0427BDFFE0AFB0001034
-:1070F000309000FF2E020006AFBF001810400008BD
-:10710000AFB10014001030803C03080024635784A2
-:1071100000C328218CA400000080000800000000AB
-:10712000000020218FBF00188FB100148FB0001015
-:107130000080102103E0000827BD00209791002A5D
-:1071400016200051000020213C020800904200332C
-:107150000A0006BB00000000978D002615A0003134
-:10716000000020210A0006BB2402000897870024A3
-:1071700014E0001A00001821006020212402000100
-:107180001080FFE98FBF0018000429C2004530219C
-:1071900000A6582B1160FFE43C0880003C0720004B
-:1071A000000569C001A76025AD0C00203C038008E4
-:1071B0002402001F2442FFFFAC6000000441FFFDD9
-:1071C0002463000424A5000100A6702B15C0FFF560
-:1071D000000569C00A0006A58FBF00189787001C2C
-:1071E0003C04080024845A58240504000E0006605C
-:1071F00024060001978B002424440001308AFFFFFD
-:107200002569FFFF2D48040000402821150000409B
-:10721000A789002424AC3800000C19C00A0006B964
-:10722000A780001C9787001E3C04080024845AD8BD
-:10723000240504000E00066024060001979900262C
-:10724000244400013098FFFF272FFFFF2F0E04007A
-:107250000040882115C0002CA78F0026A780001EA3
-:107260003A020003262401003084FFFF0E00068D41
-:107270002C4500010011F8C027F00100001021C0CA
-:107280000A0006BB240200089785002E978700227B
-:107290003C04080024845B580E00066024060001AC
-:1072A0009787002A8F89002C2445000130A8FFFF12
-:1072B00024E3FFFF0109302B0040802114C0001897
-:1072C000A783002AA7800022978500300E000F7543
-:1072D00002002021244A05003144FFFF0E00068DE4
-:1072E000240500013C05080094A500320E000F752E
-:1072F00002002021244521003C0208009042003376
-:107300000A0006BB000521C00A0006F3A784001E80
-:1073100024AC3800000C19C00A0006B9A784001C70
-:107320000A00070DA7850022308400FF27BDFFE873
-:107330002C820006AFBF0014AFB000101040001543
-:1073400000A03821000440803C0308002463579CBF
-:10735000010328218CA40000008000080000000028
-:1073600024CC007F000751C2000C59C23170FFFFCE
-:107370002547C40030E5FFFF2784001C02003021B0
-:107380000E0005B52407000197860028020620217B
-:10739000A78400288FBF00148FB0001003E00008FE
-:1073A00027BD00183C0508008CA50030000779C2F5
-:1073B0000E00038125E4DF003045FFFF3C04080098
-:1073C00024845B58240600010E0005B52407000143
-:1073D000978E002A8FBF00148FB0001025CD0001BA
-:1073E00027BD001803E00008A78D002A0007C9C2C6
-:1073F0002738FF00001878C231F0FFFF3C04080076
-:1074000024845AD802002821240600010E0005B564
-:1074100024070001978D0026260E0100000E84002F
-:1074200025AC00013C0B6000A78C0026AD603D0838
-:1074300036040006000030213C0760008CE23D0469
-:10744000305F000617E0FFFD24C9000100061B00A5
-:10745000312600FF006440252CC50004ACE83D0443
-:1074600014A0FFF68FBF00148FB0001003E00008D7
-:1074700027BD0018000751C22549C8002406000195
-:10748000240700013C04080024845A580E0005B566
-:107490003125FFFF978700248FBF00148FB00010A5
-:1074A00024E6000127BD001803E00008A786002499
-:1074B0003C0660183C090800252900FCACC9502C8A
-:1074C0008CC850003C0580003C020002350700805B
-:1074D000ACC750003C04080024841FE03C030800B3
-:1074E00024631F98ACA50008ACA2000C3C01080066
-:1074F000AC2459A43C010800AC2359A803E00008BF
-:107500002402000100A030213C1C0800279C59AC3B
-:107510003C0C04003C0B0002008B3826008C4026FB
-:107520002CE200010007502B2D050001000A4880C5
-:107530003C030800246359A4004520250123182199
-:107540001080000300001021AC660000240200013E
-:1075500003E00008000000003C1C0800279C59AC18
-:107560003C0B04003C0A0002008A3026008B3826BF
-:107570002CC200010006482B2CE5000100094080C8
-:107580003C030800246359A4004520250103182169
-:1075900010800005000010213C0C0800258C1F986D
-:1075A000AC6C00002402000103E0000800000000B1
-:1075B0003C0900023C080400008830260089382677
-:1075C0002CC30001008028212CE400010083102539
-:1075D0001040000B000030213C1C0800279C59ACD7
-:1075E0003C0A80008D4E00082406000101CA68256F
-:1075F000AD4D00088D4C000C01855825AD4B000C9D
-:1076000003E0000800C010213C1C0800279C59AC76
-:107610003C0580008CA6000C0004202724020001F9
-:1076200000C4182403E00008ACA3000C3C020002D4
-:107630001082000B3C0560003C070400108700032B
-:107640000000000003E00008000000008CA908D042
-:10765000240AFFFD012A402403E00008ACA808D05A
-:107660008CA408D02406FFFE0086182403E000083E
-:10767000ACA308D03C05601A34A600108CC300806F
-:1076800027BDFFF88CC50084AFA3000093A40000C1
-:107690002402001010820003AFA5000403E00008DC
-:1076A00027BD000893A7000114E0001497AC000266
-:1076B00097B800023C0F8000330EFFFC01CF682119
-:1076C000ADA50000A3A000003C0660008CC708D058
-:1076D0002408FFFE3C04601A00E82824ACC508D04A
-:1076E0008FA300048FA200003499001027BD00086A
-:1076F000AF22008003E00008AF2300843C0B800031
-:10770000318AFFFC014B48218D2800000A00080C3B
-:10771000AFA8000427BDFFE8AFBF00103C1C080065
-:10772000279C59AC3C0580008CA4000C8CA2000462
-:107730003C0300020044282410A0000A00A31824DF
-:107740003C0604003C0400021460000900A610245A
-:107750001440000F3C0404000000000D3C1C080015
-:10776000279C59AC8FBF001003E0000827BD00180C
-:107770003C0208008C4259A40040F80900000000B7
-:107780003C1C0800279C59AC0A0008358FBF00102C
-:107790003C0208008C4259A80040F8090000000093
-:1077A0000A00083B000000003C0880008D0201B880
-:1077B0000440FFFE35090180AD2400003C031000A9
-:1077C00024040040AD250004A1240008A1260009DE
-:1077D000A527000A03E00008AD0301B83084FFFFCD
-:1077E0000080382130A5FFFF000020210A00084555
-:1077F000240600803087FFFF8CA400002406003898
-:107800000A000845000028218F8300788F860070C9
-:107810001066000B008040213C07080024E75B68ED
-:10782000000328C000A710218C440000246300013D
-:10783000108800053063000F5466FFFA000328C06B
-:1078400003E00008000010213C07080024E75B6CFF
-:1078500000A7302103E000088CC200003C03900028
-:1078600034620001008220253C038000AC640020CB
-:107870008C65002004A0FFFE0000000003E000086B
-:10788000000000003C0280003443000100832025FA
-:1078900003E00008AC44002027BDFFE0AFB10014B6
-:1078A0003091FFFFAFB00010AFBF001812200013DF
-:1078B00000A080218CA20000240400022406020003
-:1078C0001040000F004028210E0007250000000096
-:1078D00000001021AE000000022038218FBF0018E8
-:1078E0008FB100148FB0001000402021000028212B
-:1078F000000030210A00084527BD00208CA20000AE
-:10790000022038218FBF00188FB100148FB00010F3
-:107910000040202100002821000030210A000845F5
-:1079200027BD002000A010213087FFFF8CA5000498
-:107930008C4400000A000845240600068F83FD9C45
-:1079400027BDFFE8AFBF0014AFB00010906700087C
-:10795000008010210080282130E600400000202116
-:1079600010C000088C5000000E0000BD0200202155
-:10797000020020218FBF00148FB000100A000548BC
-:1079800027BD00180E0008A4000000000E0000BD76
-:1079900002002021020020218FBF00148FB00010B0
-:1079A0000A00054827BD001827BDFFE0AFB0001052
-:1079B0008F90FD9CAFBF001CAFB20018AFB1001498
-:1079C00092060001008088210E00087230D2000467
-:1079D00092040005001129C2A6050000348300406E
-:1079E000A20300050E00087C022020210E00054A9B
-:1079F0000220202124020001AE02000C02202821D6
-:107A0000A602001024040002A602001224060200AE
-:107A1000A60200140E000725A60200161640000F4D
-:107A20008FBF001C978C00743C0B08008D6B007896
-:107A30002588FFFF3109FFFF256A0001012A382B45
-:107A400010E00006A78800743C0F6006240E0016A4
-:107A500035ED0010ADAE00508FBF001C8FB2001886
-:107A60008FB100148FB0001003E0000827BD002084
-:107A700027BDFFE0AFB10014AFBF0018AFB00010DA
-:107A80001080000400A088212402008010820007DA
-:107A9000000000000000000D8FBF00188FB100141F
-:107AA0008FB0001003E0000827BD00200E00087210
-:107AB00000A020218F86FD9C0220202190C500057A
-:107AC0000E00087C30B000FF2403003E1603FFF1D7
-:107AD0003C0680008CC401780480FFFE34C801405D
-:107AE000240900073C071000AD11000002202021EE
-:107AF000A10900048FBF00188FB100148FB00010CF
-:107B0000ACC701780A0008C527BD002027BDFFE0EB
-:107B1000AFB00010AFBF0018AFB100143C10800030
-:107B20008E110020000000000E00054AAE04002067
-:107B3000AE1100208FBF00188FB100148FB000105D
-:107B400003E0000827BD00203084FFFF00803821BB
-:107B50002406003500A020210A0008450000282145
-:107B60003084FFFF008038212406003600A0202149
-:107B70000A0008450000282127BDFFD0AFB500242A
-:107B80003095FFFFAFB60028AFB40020AFBF002C88
-:107B9000AFB3001CAFB20018AFB10014AFB000100B
-:107BA00030B6FFFF12A000270000A0218F920058DE
-:107BB0008E4300003C0680002402004000033E0289
-:107BC00000032C0230E4007F006698241482001D1C
-:107BD00030A500FF8F8300682C68000A1100001098
-:107BE0008F8D0044000358803C0C0800258C57B84A
-:107BF000016C50218D4900000120000800000000A8
-:107C000002D4302130C5FFFF0E0008522404008446
-:107C1000166000028F920058AF8000688F8D00447C
-:107C20002659002026980001032090213314FFFFDD
-:107C300015A00004AF9900580295202B1480FFDC9A
-:107C400000000000028010218FBF002C8FB600289A
-:107C50008FB500248FB400208FB3001C8FB20018A2
-:107C60008FB100148FB0001003E0000827BD003072
-:107C70002407003414A70149000000009247000EB9
-:107C80008F9FFDA08F90FD9C24181600A3E700197C
-:107C90009242000D3C0880003C07800CA3E20018D3
-:107CA000964A00123C0D60003C117FFFA60A005C62
-:107CB000964400103623FFFF240200053099FFFF91
-:107CC000AE1900548E46001CAD1800288CEF000041
-:107CD0008DAE444801E6482601C93021AE06003881
-:107CE0008E05003824CB00013C0E7F00AE05003C21
-:107CF0008E0C003CAFEC0004AE0B00208E13002075
-:107D0000AE13001CA3E0001BAE03002CA3E2001284
-:107D10008E4A001424130050AE0A00348E0400343E
-:107D2000AFE400148E590018AE1900489258000CA8
-:107D3000A218004E920D000835AF0020A20F0008D7
-:107D40008E090018012E282434AC4000AE0C001817
-:107D5000920B0000317200FF1253027F2403FF8058
-:107D60003C04080024845BE80E0008AA0000000020
-:107D70003C1108008E315BE80E00087202202021C1
-:107D80002405000424080001A2050025022020216A
-:107D90000E00087CA20800053C0580008CB001782C
-:107DA0000600FFFE8F92005834AE0140240F0002FF
-:107DB0003C091000ADD10000A1CF0004ACA90178AE
-:107DC0000A000962AF8000682CAD003751A0FF9413
-:107DD0008F8D0044000580803C110800263157E05B
-:107DE000021178218DEE000001C0000800000000A3
-:107DF0002411000414B1008C3C0780003C080800EA
-:107E00008D085BE88F86FD9CACE800208E4500085D
-:107E10008F99FDA0240D0050ACC500308E4C000899
-:107E2000ACCC00508E4B000CACCB00348E43001019
-:107E3000ACC300388E4A0010ACCA00548E42001405
-:107E4000ACC2003C8E5F0018AF3F00048E50001C97
-:107E5000ACD0002090C40000309800FF130D024AFF
-:107E6000000000008CC400348CD00030009030231F
-:107E700004C000F12404008C126000EE2402000310
-:107E80000A000962AF8200682419000514B900666F
-:107E90003C0580003C0808008D085BE88F86FD9C4F
-:107EA000ACA800208E4C00048F8AFDA0240720007F
-:107EB000ACCC001C924B000824120008A14B001906
-:107EC0008F82005890430009A14300188F85005805
-:107ED00090BF000A33E400FF1092001028890009C7
-:107EE000152000BA240E0002240D0020108D000B76
-:107EF000340780002898002117000008240740005C
-:107F000024100040109000053C0700012419008057
-:107F1000109900023C070002240740008CC20018A0
-:107F20003C03FF00004350240147F825ACDF001854
-:107F300090B2000BA0D200278F8300589464000CED
-:107F4000108001FE000000009467000C3C1F8000C0
-:107F50002405FFBFA4C7005C9063000E2407000443
-:107F6000A0C300088F820058904A000FA0CA0009E1
-:107F70008F8900588D3200108FE400740244C823AA
-:107F8000ACD900588D300014ACD0002C95380018B6
-:107F9000330DFFFFACCD00409531001A322FFFFFAB
-:107FA000ACCF00448D2E001CACCE00489128000EB2
-:107FB000A0C8000890CC000801855824126001B6C2
-:107FC000A0CB00088F9200580A000962AF870068B2
-:107FD0002406000614A600143C0E80003C0F080086
-:107FE0008DEF5BE88F85FD98ADCF00208E4900189E
-:107FF0008F86FD9C8F8BFDA0ACA900008CC800383B
-:1080000024040005ACA800048CCC003C1260008164
-:10801000AD6C00000A000962AF84006824110007FB
-:1080200010B1004B240400063C05080024A55BE8C1
-:108030000E000881240400818F9200580013102B39
-:108040000A000962AF820068241F002314BFFFF6F4
-:108050003C0C80003C0508008CA55BE88F8BFDA0E4
-:10806000AD8500208F91FD9C8E4600042564002084
-:1080700026450014AE260028240600030E000F81BA
-:10808000257000308F87005802002021240600034D
-:108090000E000F8124E500083C04080024845BE8FE
-:1080A0000E0008AA0000000092230000240A0050DD
-:1080B000306200FF544AFFE18F9200580E000F6CAF
-:1080C000000000000A000A6A8F920058240800335A
-:1080D00014A800323C0380003C1108008E315BE89C
-:1080E0008F8FFDA0AC7100208E420008240D002867
-:1080F0008F89FD9CADE200308E4A000C24060009F9
-:10810000ADEA00348E5F0010ADFF00388E440014DD
-:10811000ADE400208E590018ADF900248E58001CE3
-:10812000ADF80028A1ED00118E4E00041260003160
-:10813000AD2E00288F9200580A000962AF860068B1
-:10814000240D002214ADFFB8000000002404000735
-:108150003C1008008E105BE83C188000AF10002037
-:108160005660FEAEAF8400683C04080024845BE8DF
-:108170000E0008AA241300508F84FD9C90920000EA
-:10818000325900FF1333014B000000008F9200585A
-:10819000000020210A000962AF8400683C05080045
-:1081A00024A55BE80E000858240400810A000A6A2E
-:1081B0008F92005802D498213265FFFF0E000852BA
-:1081C000240400840A0009628F920058108EFF5325
-:1081D000240704002887000310E00179241100041B
-:1081E000240F0001548FFF4D240740000A000A228B
-:1081F000240701003C05080024A55BE80E0008A444
-:10820000240400828F920058000030210A00096285
-:10821000AF8600683C04080024845BE88CC2003808
-:108220000E0008AA8CC3003C8F9200580A000AC0B6
-:1082300000002021240400823C05080024A55BE8FE
-:108240000E0008A4000000008F92005800001021CA
-:108250000A000962AF8200688E5000048F91FD9C75
-:108260003C078000ACF00020922C00050200282181
-:10827000318B0002156001562404008A8F92FDA004
-:108280002404008D9245001B30A6002014C001502C
-:1082900002002821922E00092408001231C900FF93
-:1082A0001128014B240400810E00087202002021D5
-:1082B0009258001B240F000402002021370D0042B9
-:1082C000A24D001B0E00087CA22F00253C0580005B
-:1082D0008CA401780480FFFE34B90140241F000201
-:1082E000AF300000A33F00048F9200583C101000F4
-:1082F000ACB001780A000A6B0013102B8E500004FA
-:108300008F91FD9C3C038000AC700020922A0005F8
-:108310000200282131420002144000172404008A80
-:10832000922C00092412000402002821318B00FF46
-:1083300011720011240400810E0008720200202135
-:108340008F89FDA0240800122405FFFE912F001B39
-:108350000200202135EE0020A12E001BA2280009DA
-:108360009226000500C538240E00087CA2270005CF
-:1083700002002821000020210E0009330000000027
-:108380000A000A6A8F9200588E4C00043C07800055
-:108390003C10080026105BE8ACEC00203C01080013
-:1083A000AC2C5BE8924B0003317100041220013BBE
-:1083B0008F84FD9C24020006A0820009924F001BBE
-:1083C000240EFFC031E9003F012E4025A08800089F
-:1083D0009245000330A6000114C0013200000000E5
-:1083E0008E420008AE0200083C0208008C425BF09E
-:1083F000104001318F90FDA0000219C28F8DFD9CAD
-:10840000A603000C8E4A000C24180001240400145A
-:10841000AE0A002C8E420010AE02001C965F0016C1
-:10842000A61F003C96590014A619003EADB8000CDA
-:10843000A5B80010A5B80012A5B80014A5B800167C
-:1084400012600144A2040011925100033232000272
-:108450002E5300018F920058266200080A0009621C
-:10846000AF8200688E4400043C1980003C068008FE
-:10847000AF2400208E45000890D80000240D005045
-:10848000331100FF122D009C2407008824060009E8
-:108490000E000845000000000A000A6A8F9200588A
-:1084A0008E5000043C0980003C118008AD30002053
-:1084B0009228000024050050310400FF10850110AF
-:1084C0002407008802002021000028210E00084512
-:1084D0002406000E922D00002418FF80020028219F
-:1084E00001B8802524040004240600300E0007256E
-:1084F000A23000000A000A6A8F9200588E500004D1
-:108500008F91FDA03C028000AC500020923F001BE8
-:1085100033F900101320006C240700810200202191
-:10852000000028212406001F0E000845000000005E
-:108530000A000A6A8F9200588E44001C0E00085DE3
-:1085400000000000104000E3004048218F880058E0
-:1085500024070089012020218D05001C240600012C
-:108560000E000845000000000A000A6A8F920058B9
-:10857000964900023C10080026105BE831280004F0
-:10858000110000973C0460008E4E001C3C0F8000E0
-:10859000ADEE00203C010800AC2E5BE896470002DF
-:1085A00030E40001148000E6000000008E42000468
-:1085B000AE0200083C1008008E105BF0120000ECC8
-:1085C0003C0F80008F92FD9C241000018E4E0018FD
-:1085D0008F8DFDA08F9FFD9801CF4825AE490018D3
-:1085E000A2400005AE50000C3C0808008D085BF06E
-:1085F0008F840058A6500010000839C2A6500012FF
-:10860000A6500014A6500016A5A7000C8C8C0008DC
-:108610008F8B00588F8A0058ADAC002C8D63000CF6
-:1086200024070002ADA3001C91460010A1A6001172
-:108630008F82005890450011A3E500088F990058DB
-:1086400093380012A258004E8F910058922F0013B9
-:10865000A1AF00128F920058964E0014A5AE003CB8
-:1086600096490016A5A9003E8E480018ADA8001432
-:108670005660FD6AAF8700683C05080024A55BE8EA
-:108680000E000881000020218F9200580000382140
-:108690000A000962AF8700683C05080024A55BE872
-:1086A0000E0008A4240400828F9200580A000A4D8C
-:1086B000000038210E000F6C000000008F9200585F
-:1086C0000A000AC0000020210E00087202002021CA
-:1086D0009223001B02002021346A00100E00087C47
-:1086E000A22A001B000038210200202100002821BE
-:1086F0000A000BA52406001F9242000C305F000107
-:1087000013E0000300000000964A000EA4CA002CEB
-:10871000924B000C316300025060000600003821CB
-:108720008E470014964C0012ACC7001CA4CC001A53
-:10873000000038210A000B7F240600093C050800D0
-:1087400024A55BE80E0008A42404008B8F92005837
-:108750000A000A4D0013382B3C0C08008D8C5BE896
-:1087600024DFFFFE25930100326B007F016790211B
-:1087700002638824AD110028AE4600E0AE4000E45C
-:108780000A0009B3AE5F001CACC000543C0D0800E9
-:108790008DAD5BE83C18800C37090100ACED00287A
-:1087A0008E510014AD3100E08E4F0014AD2F00E467
-:1087B0008E4E001025C7FFFE0A0009F4AD27001CED
-:1087C0005491FDD6240740000A000A222407100015
-:1087D0000E00092D000000000A000A6A8F9200585E
-:1087E0008C83442C3C12DEAD3651BEEF3C010800B8
-:1087F000AC205BE810710062000000003C196C6264
-:1088000037387970147800082404000297850074C2
-:108810009782006C2404009200A2F82B13E0001948
-:1088200002002821240400020E00069524050200FF
-:108830003C068000ACC200203C010800AC225BE892
-:108840001040000D8F8C0058240A002824040003D7
-:10885000918B0010316300FF546A00012404000171
-:108860000E0000810000000010400004240400837A
-:108870000A000BC28F920058240400833C050800B4
-:1088800024A55BE80E000881000000008F920058CC
-:108890000013382B0A000962AF8700680A000B49F1
-:1088A000240200128E4400080E00085D0000000043
-:1088B0000A000B55AE0200083C05080024A55BE841
-:1088C0000E000858240400878F9200580A000B728B
-:1088D0000013102B240400040E000695240500301C
-:1088E0001440002A004048218F8800582407008344
-:1088F000012020218D05001C0A000BB32406000175
-:108900008F8300788F8600701066FEEE000038219D
-:108910003C07080024E75B6C000320C00087282187
-:108920008CAE000011D0005D246F000131E3000F18
-:108930005466FFFA000320C00A000B8C00003821A7
-:108940008E4400040E00085D000000000A000BC801
-:10895000AE0200083C05080024A55BE80E0008A450
-:10896000240400828F9200580A000B72000010212C
-:108970003C05080024A55BE80A000C7C2404008761
-:108980008C83442C0A000C5B3C196C628F88005865
-:108990003C0780083C0C8000240B0050240A000196
-:1089A000AD820020A0EB0000A0EA000191030004CA
-:1089B000A0E3001891040005A0E400199106000648
-:1089C0003C04080024845B6CA0E6001A91020007B6
-:1089D0003C06080024C65B68A0E2001B9105000865
-:1089E000A0E5001C911F0009A0FF001D9119000ABD
-:1089F000A0F9001E9118000BA0F8001F9112000CA6
-:108A0000A0F200209111000DA0F100219110000EA4
-:108A1000A0F00022910F000FA0EF0023910E001094
-:108A2000A0EE0024910D0011A0ED0025950C00147E
-:108A3000A4EC0028950B00168F8A00708F920078A6
-:108A4000A4EB002A95030018000A10C02545000178
-:108A5000A4E3002C8D1F001C0044C0210046C82147
-:108A600030A5000FAF3F0000AF09000010B20006B4
-:108A7000AF850070000038218D05001C01202021E9
-:108A80000A000BB32406000124AD000131A7000F3A
-:108A9000AF8700780A000CF9000038213C06080076
-:108AA00024C65B680086902100003821ACA000003D
-:108AB0000A000B8CAE4000003C0482013C036000C5
-:108AC00034820E02AC603D68AF80009803E000087D
-:108AD000AC623D6C27BDFFE8AFB000103090FFFFE7
-:108AE000001018422C620041AFBF00141440000275
-:108AF00024040080240300403C010800AC300060E6
-:108B00003C010800AC2300640E000F7500602821B2
-:108B1000244802BF2409FF8001092824001039805D
-:108B2000001030408FBF00148FB0001000A720212C
-:108B300000861821AF8300803C010800AC25005856
-:108B40003C010800AC24005C03E0000827BD0018CD
-:108B5000308300FF30C6FFFF30E400FF3C08800098
-:108B60008D0201B80440FFFE000354000144382583
-:108B70003C09600000E920253C031000AD050180A0
-:108B8000AD060184AD04018803E00008AD0301B81F
-:108B90008F8500583C0A6012354800108CAC0004E8
-:108BA0003C0D600E35A60010318B00062D690001CA
-:108BB000AD0900C48CA70004ACC731808CA20008AA
-:108BC00094A40002ACC231848CA3001C0460000396
-:108BD000A784009003E00008000000008CAF00189C
-:108BE000ACCF31D08CAE001C03E00008ACCE31D449
-:108BF0008F8500588F87FF288F86FF308CAE00044A
-:108C00003C0F601235E80010ACEE00788CAD000827
-:108C1000ACED007C8CAC0010ACCC004C8CAB000CF0
-:108C2000ACCB004894CA00543C0208008C4200447B
-:108C300025490001A4C9005494C400543083FFFFA7
-:108C400010620017000000003C0208008C42004047
-:108C5000A4C200528CA30018ACE300308CA2001414
-:108C6000ACE2002C8CB90018ACF900388CB80014B8
-:108C700024050001ACF800348D0600BC50C5001975
-:108C80008D0200B48D0200B8A4E2004894E40048CC
-:108C9000A4E4004A94E800EA03E000083102FFFF80
-:108CA0003C0208008C420024A4C00054A4C200521C
-:108CB0008CA30018ACE300308CA20014ACE2002CB2
-:108CC0008CB90018ACF900388CB8001424050001E8
-:108CD000ACF800348D0600BC54C5FFEB8D0200B823
-:108CE0008D0200B4A4E2004894E40048A4E4004AE1
-:108CF00094E800EA03E000083102FFFF8F86005885
-:108D00003C0480008CC900088CC80008000929C0F8
-:108D1000000839C0AC87002090C30007306200040F
-:108D20001040003EAF85009490CB0007316A0008E8
-:108D30001140003D8F87FF2C8CCD000C8CCE001491
-:108D400001AE602B11800036000000008CC2000CC8
-:108D5000ACE200708CCB00188F85FF288F88FF3025
-:108D6000ACEB00748CCA00102402FFF8ACAA00D847
-:108D70008CC9000CAD0900608CC4001CACA400D0F0
-:108D800090E3007C0062C824A0F9007C90D8000722
-:108D9000330F000811E000040000000090ED007C9B
-:108DA00035AC0001A0EC007C90CF000731EE000153
-:108DB00011C000060000000090E3007C241800347D
-:108DC00034790002A0F9007CACB800DC90C2000746
-:108DD0003046000210C000040000000090E8007C53
-:108DE00035040004A0E4007C90ED007D3C0B600E97
-:108DF000356A001031AC003FA0EC007D8D4931D4C4
-:108E00003127000110E00002240E0001A0AE00098D
-:108E100094AF00EA03E0000831E2FFFF8F87FF2CE8
-:108E20000A000DAF8CC200140A000DB0ACE0007057
-:108E30008F8C005827BDFFD8AFB3001CAFB200180D
-:108E4000AFB00010AFBF0020AFB10014918F00157C
-:108E50003C13600E3673001031EB000FA38B009CA7
-:108E60008D8F00048D8B0008959F0012959900103E
-:108E70009584001A9598001E958E001C33EDFFFF17
-:108E8000332AFFFF3089FFFF3308FFFF31C7FFFFA1
-:108E90003C010800AC2D00243C010800AC29004432
-:108EA0003C010800AC2A0040AE683178AE67317CE6
-:108EB00091850015959100163C12601236520010F3
-:108EC00030A200FF3230FFFFAE623188AE5000B4F6
-:108ED00091830014959F0018240600010066C804C1
-:108EE00033F8FFFFAE5900B8AE5800BC918E0014A5
-:108EF000AF8F00843C08600631CD00FFAE4D00C04E
-:108F0000918A00159584000E3C07600A314900FFE4
-:108F1000AF8B00883084FFFFAE4900C835110010C8
-:108F20000E000D1034F004103C0208008C4200606A
-:108F30003C0308008C6300643C0608008CC60058A3
-:108F40003C0508008CA5005C8F8400808FBF00204A
-:108F5000AE23004CAE65319CAE030054AE4500DC40
-:108F6000AE6231A0AE6331A4AE663198AE22004845
-:108F70008FB3001CAE0200508FB10014AE4200E06F
-:108F8000AE4300E4AE4600D88FB000108FB2001898
-:108F90000A00057D27BD0028978500929783007CF5
-:108FA00027BDFFE8AFB0001000A3102BAFBF001427
-:108FB000240400058F900058104000552409000239
-:108FC0000E0006958F850080AF8200942404000374
-:108FD0001040004F240900023C0680000E00008172
-:108FE000ACC2002024070001240820001040004DDE
-:108FF00024040005978E00928F8AFF2C24090050CC
-:1090000025C50001A7850092A14900003C0D08007C
-:109010008DAD0064240380008F84FF28000D66005E
-:10902000AD4C0018A5400006954B000A8F85FF3017
-:109030002402FF8001633024A546000A915F000AE4
-:109040000000482103E2C825A159000AA0A0000899
-:10905000A140004CA08000D5961800029783009094
-:109060003C020004A49800EA960F00022418FFBFF7
-:1090700025EE2401A48E00BE8E0D0004ACAD00448C
-:109080008E0C0008ACAC0040A4A00050A4A000547A
-:109090008E0B000C240C0030AC8B00288E060010C8
-:1090A000AC860024A480003EA487004EA487005014
-:1090B000A483003CAD420074AC8800D8ACA800602A
-:1090C000A08700FC909F00D433F9007FA09900D4C2
-:1090D000909000D402187824A08F00D4914E007C88
-:1090E00035CD0001A14D007C938B009CAD480070F4
-:1090F000AC8C00DCA08B00D68F8800888F87008422
-:10910000AC8800C4AC8700C8A5400078A540007AB0
-:109110008FBF00148FB000100120102103E0000861
-:1091200027BD00188F8500940E0007258F860080CC
-:109130000A000E9F2409000227BDFFE0AFB0001017
-:109140008F900058AFB10014AFBF00188E09000413
-:109150000E00054A000921C08E0800048F84FF28F4
-:109160008F82FF30000839C03C068000ACC7002069
-:10917000948500EA904300131460001C30B1FFFF97
-:109180008F8CFF2C918B0008316A00401540000B3A
-:10919000000000008E0D0004022030218FBF001857
-:1091A0008FB100148FB00010240400220000382179
-:1091B000000D29C00A000D2F27BD00200E000098C9
-:1091C000000000008E0D0004022030218FBF001827
-:1091D0008FB100148FB00010240400220000382149
-:1091E000000D29C00A000D2F27BD00200E000090A1
-:1091F000000000008E0D0004022030218FBF0018F7
-:109200008FB100148FB00010240400220000382118
-:10921000000D29C00A000D2F27BD002027BDFFE04B
-:10922000AFB200183092FFFFAFB00010AFBF001C0C
-:10923000AFB100141240001E000080218F8600583C
-:109240008CC500002403000600053F02000514023F
-:1092500030E4000714830016304500FF2CA80006F8
-:1092600011000040000558803C0C0800258C58BCBB
-:10927000016C50218D490000012000080000000011
-:109280008F8E0098240D000111CD005024020002A1
-:10929000AF820098260900013130FFFF24C800206A
-:1092A0000212202B010030211480FFE5AF88005806
-:1092B000020010218FBF001C8FB200188FB1001464
-:1092C0008FB0001003E0000827BD00209387007EC8
-:1092D00054E00034000030210E000DE700000000D3
-:1092E0008F8600580A000EFF240200018F87009825
-:1092F0002405000210E50031240400130000282199
-:1093000000003021240700010E000D2F0000000096
-:109310000A000F008F8600588F83009824020002F5
-:109320001462FFF6240400120E000D9A00000000E3
-:109330008F85009400403021240400120E000D2F70
-:10934000000038210A000F008F8600588F83009894
-:109350002411000310710029241F0002107FFFCE8A
-:1093600026090001240400100000282100003021FB
-:109370000A000F1D240700018F91009824060002A7
-:109380001626FFF9240400100E000E410000000014
-:10939000144000238F9800588F8600580A000EFF53
-:1093A00024020003240400140E000D2F00002821C5
-:1093B0008F8600580A000EFF240200020E000EA93C
-:1093C000000000000A000F008F8600580E000D3FBD
-:1093D00000000000241900022404001400002821C9
-:1093E0000000302100003821AF9900980E000D2FA9
-:1093F000000000000A000F008F8600580E000D5775
-:10940000000000008F8500942419000200403021E4
-:1094100024040010000038210A000F56AF9900986C
-:109420000040382124040010970F0002000028217A
-:109430000E000D2F31E6FFFF8F8600580A000F0047
-:10944000AF9100988F84FF2C3C077FFF34E6FFFF2D
-:109450008C8500182402000100A61824AC83001893
-:1094600003E00008A08200053084FFFF30A5FFFF65
-:109470001080000700001821308200011040000217
-:1094800000042042006518211480FFFB00052840DD
-:1094900003E000080060102110C000070000000079
-:1094A0008CA2000024C6FFFF24A50004AC820000AB
-:1094B00014C0FFFB2484000403E000080000000047
-:1094C00010A0000824A3FFFFAC86000000000000ED
-:1094D000000000002402FFFF2463FFFF1462FFFA74
-:1094E0002484000403E0000800000000000411C010
-:1094F00003E000082442024027BDFFE8AFB000109F
-:1095000000808021AFBF00140E000F9600A0202124
-:1095100000504821240AFF808FBF00148FB0001034
-:10952000012A30243127007F3C08800A3C042100B6
-:1095300000E8102100C428253C03800027BD001846
-:10954000AC650024AF820038AC400000AC6500245C
-:1095500003E00008AC4000403C0D08008DAD005811
-:1095600000056180240AFF8001A45821016C482174
-:10957000012A30243127007F3C08800C3C04210064
-:1095800000E8102100C428253C038000AC650028B9
-:10959000AF82003403E00008AC40002430A5FFFF98
-:1095A0003C0680008CC201B80440FFFE3C086015F8
-:1095B00000A838253C031000ACC40180ACC0018475
-:1095C000ACC7018803E00008ACC301B83C0D08003B
-:1095D0008DAD005800056180240AFF8001A4582148
-:1095E000016C4021010A4824000931403107007F05
-:1095F00000C728253C04200000A418253C02800058
-:10960000AC43083003E00008AF80003427BDFFE81A
-:10961000AFB0001000808021AFBF00140E000F9685
-:1096200000A0202100504821240BFF80012B502452
-:10963000000A39403128007F3C0620008FBF00140B
-:109640008FB0001000E8282534C2000100A21825C0
-:109650003C04800027BD0018AC83083003E00008FC
-:10966000AF8000383C0580088CA700603C0680086D
-:109670000087102B144000112C8340008CA8006040
-:109680002D0340001060000F240340008CC90060CF
-:109690000089282B14A00002008018218CC30060D0
-:1096A00000035A42000B30803C0A0800254A59202A
-:1096B00000CA202103E000088C8200001460FFF340
-:1096C0002403400000035A42000B30803C0A08008B
-:1096D000254A592000CA202103E000088C8200009E
-:1096E0003C05800890A60008938400AB24C20001CA
-:1096F000304200FF3043007F1064000C0002382726
-:10970000A0A200083C0480008C85017804A0FFFE24
-:109710008F8A00A0240900023C081000AC8A014096
-:10972000A089014403E00008AC8801780A00101BFE
-:1097300030E2008027BDFFD8AFB200188F9200A49E
-:10974000AFBF0020AFB3001CAFB00010AFB100142A
-:109750008F9300348E5900283C1000803C0EFFEFA0
-:10976000AE7900008E580024A260000A35CDFFFFBC
-:10977000AE7800049251002C3C0BFF9F356AFFFF2E
-:10978000A271000C8E6F000C3C080040A271000B0F
-:1097900001F06025018D4824012A382400E8302595
-:1097A000AE66000C8E450004AE6000183C0400FF5D
-:1097B000AE6500148E43002C3482FFFFA6600008C3
-:1097C0000062F824AE7F00108E5900088F9000A030
-:1097D000964E0012AE7900208E51000C31D83FFF1A
-:1097E00000187980AE7100248E4D001401F06021C4
-:1097F00031CB0001AE6D00288E4A0018000C41C22A
-:10980000000B4B80AE6A002C8E46001C01093821EB
-:10981000A667001CAE660030964500028E4400200C
-:10982000A665001EAE64003492430033306200042B
-:1098300054400006924700003C0280083443010077
-:109840008C7F00D0AE7F0030924700008F860038BA
-:10985000A0C700309245003330A4000250800007BA
-:10986000925100018F880038240BFF80910A00304C
-:10987000014B4825A1090030925100018F9000381A
-:10988000240CFFBF2404FFDFA21100318F8D0038AC
-:109890003C1880083711008091AF003C31EE007F0A
-:1098A000A1AE003C8F890038912B003C016C502404
-:1098B000A12A003C8F9F00388E68001493E6003C7C
-:1098C0002D0700010007114000C4282400A218251C
-:1098D000A3E3003C8F87003896590012A4F90032A8
-:1098E0008E450004922E007C30B0000300107823D7
-:1098F00031ED000300AD102131CC000215800002D3
-:1099000024460034244600303C0280083443008062
-:10991000907F007C00BFC824333800041700000289
-:1099200024C2000400C010218F98003824190002BE
-:10993000ACE20034A3190000924F003F8F8E003834
-:109940003C0C8008358B0080A1CF00018F9100383E
-:10995000924D003F8E440004A62D0002956A005CE3
-:109960000E000FF43150FFFF00024B800209382532
-:109970003C08420000E82825AE2500048E4400384B
-:109980008F850038ACA400188E460034ACA6001CAD
-:10999000ACA0000CACA00010A4A00014A4A0001661
-:1099A000A4A00020A4A00022ACA000248E62001479
-:1099B00050400001240200018FBF00208FB3001C23
-:1099C0008FB200188FB100148FB00010ACA2000845
-:1099D0000A00101327BD002827BDFFC83C058008DA
-:1099E00034A40080AFBF0034AFBE0030AFB7002C4E
-:1099F000AFB60028AFB50024AFB40020AFB3001C51
-:109A0000AFB20018AFB10014AFB00010948300786B
-:109A10009482007A104300512405FFFF0080F0215A
-:109A20000A0011230080B821108B004D8FBF003435
-:109A30008F8600A03C1808008F18005C2411FF805E
-:109A40003C1680000306782101F18024AED0002C62
-:109A500096EE007A31EC007F3C0D800E31CB7FFF1B
-:109A6000018D5021000B4840012AA82196A4000036
-:109A70003C0808008D0800582405FF8030953FFF02
-:109A800001061821001539800067C8210325F82434
-:109A90003C02010003E290253338007F3C11800C2A
-:109AA000AED20028031190219250000D320F000415
-:109AB00011E0003702E0982196E3007A96E8007AF8
-:109AC00096E5007A2404800031077FFF24E300013B
-:109AD00030627FFF00A4F82403E2C825A6F9007ACB
-:109AE00096E6007A3C1408008E94006030D67FFF22
-:109AF00012D400C1000000008E5800188F8400A00E
-:109B000002A028212713FFFF0E000FCEAE53002C1A
-:109B100097D5007897D4007A12950010000028217C
-:109B20003C098008352401003C0A8008914800085F
-:109B3000908700D53114007F30E400FF0284302B81
-:109B400014C0FFB9268B0001938E00AB268C000158
-:109B5000008E682115ACFFB78F8600A08FBF003440
-:109B60008FBE00308FB7002C8FB600288FB5002431
-:109B70008FB400208FB3001C8FB200188FB1001477
-:109B80008FB0001000A0102103E0000827BD0038AE
-:109B900000C020210E000F99028028218E4B00105A
-:109BA0008E4C00308F84003824090002016C502351
-:109BB000AE4A0010A089000096E3005C8E4400309D
-:109BC0008F9100380E000FF43070FFFF00024380C9
-:109BD000020838253C02420000E22825AE25000498
-:109BE0008E5F00048F8A00388E590000240B000815
-:109BF000AD5F001CAD590018AD40000CAD40001029
-:109C00009246000A240400052408C00030D000FF5A
-:109C1000A550001496580008A55800169251000A45
-:109C20003C188008322F00FFA54F0020964E0008F8
-:109C300037110100A54E0022AD400024924D000BCB
-:109C400031AC00FFA54C0002A14B00018E49003051
-:109C50008F830038240BFFBFAC690008A06400307C
-:109C60008F9000382403FFDF9607003200E8282495
-:109C700000B51025A6020032921F003233F9003FD2
-:109C800037260040A20600328F8C0038AD800034A9
-:109C90008E2F00D0AD8F0038918E003C3C0F7FFF9F
-:109CA00031CD007FA18D003C8F84003835EEFFFF61
-:109CB000908A003C014B4824A089003C8F850038E5
-:109CC00090A8003C01033824A0A7003C8E42003439
-:109CD0008F9100383C038008AE2200408E59002C42
-:109CE0008E5F0030033F3023AE26004492300048A0
-:109CF0003218007FA23800488F8800388E4D00301F
-:109D00008D0C004801AE582401965024014B482583
-:109D1000AD0900489244000AA104004C964700088F
-:109D20008F850038A4A7004E8E5000308E4400303E
-:109D30000E0003818C65006092F9007C0002F940FE
-:109D4000004028210002110003E2302133360002D6
-:109D500012C00003020680210005B0800216802197
-:109D6000926D007C31B30004126000020005708027
-:109D7000020E80218E4B00308F8800382405800031
-:109D8000316A0003000A4823312400030204182129
-:109D9000AD03003496E4007A96F0007A96F1007AEA
-:109DA00032027FFF2447000130FF7FFF0225C824D5
-:109DB000033F3025A6E6007A96F8007A3C120800A8
-:109DC0008E520060330F7FFF11F200180000000078
-:109DD0008F8400A00E000FCE02A028218F8400A047
-:109DE0000E000FDE028028210E001013000000007C
-:109DF0000A00111F0000000096F1007A022480245E
-:109E0000A6F0007A92EF007A92EB007A31EE00FF32
-:109E1000000E69C2000D6027000C51C03169007F3F
-:109E2000012A20250A001119A2E4007A96E6007A98
-:109E300000C5C024A6F8007A92EF007A92F3007A67
-:109E400031F200FF001271C2000E6827000DB1C090
-:109E5000326C007F01962825A2E5007A0A0011D015
-:109E60008F8400A03C0380003084FFFF30A5FFFFFB
-:109E7000AC640018AC65001C03E000088C620014A0
-:109E800027BDFFA03C068008AFBF005CAFBE0058F6
-:109E9000AFB70054AFB60050AFB5004CAFB40048F8
-:109EA000AFB30044AFB20040AFB1003CAFB0003838
-:109EB00034C80100910500D590C700083084FFFF29
-:109EC00030A500FF30E2007F0045182AAFA4001043
-:109ED000A7A00018A7A0002610600055AFA000148E
-:109EE00090CA00083149007F00A9302324D3FFFF26
-:109EF0000013802B8FB400100014902B02128824C2
-:109F0000522000888FB300143C03800894790052DB
-:109F1000947E00508FB60010033EC0230018BC0092
-:109F2000001714030016FC0002C2A82A16A00002A3
-:109F3000001F2C030040282100133C0000072403CD
-:109F400000A4102A5440000100A020212885000907
-:109F500014A000020080A021241400083C0C8008FA
-:109F60008D860048001459808D88004C3C03800089
-:109F70003169FFFF3C0A0010012A202534710400DA
-:109F8000AC660038AF9100A4AC68003CAC64003013
-:109F900000000000000000000000000000000000C1
-:109FA00000000000000000000000000000000000B1
-:109FB0008C6E000031CD002011A0FFFD0014782A26
-:109FC00001F01024104000390000A8213C16800840
-:109FD00092D700083C1280008E44010032F6007FC8
-:109FE0000E000F9902C028218E3900108E44010006
-:109FF0000000902133373FFF0E000FB102E028210F
-:10A00000923800003302003F2C500008520000102C
-:10A0100000008821000210803C030800246358E4FB
-:10A020000043F8218FFE000003C00008000000007C
-:10A0300090CF0008938C00AB31EE007F00AE682318
-:10A04000018D58210A0012172573FFFF0000882197
-:10A050003C1E80008FC401000E000FCE02E02821BC
-:10A060008FC401000E000FDE02C028211220000F55
-:10A070000013802B8F8B00A426A400010004AC00E9
-:10A08000027298230015AC032578004002B4B02A70
-:10A090000013802B241700010300882102D0102414
-:10A0A000AF9800A41440FFC9AFB700143C07800864
-:10A0B00094E200508FAE00103C05800002A288217F
-:10A0C0003C060020A4F10050ACA6003094F40050EF
-:10A0D00094EF005201D51823306CFFFF11F4001EDD
-:10A0E000AFAC00108CEF004C001561808CF500487F
-:10A0F00001EC28210000202100AC582B02A4C02133
-:10A10000030BB021ACE5004CACF600488FB4001056
-:10A110000014902B021288241620FF7C3C03800838
-:10A120008FB300148FBF005C8FBE00583A620001ED
-:10A130008FB700548FB600508FB5004C8FB40048D5
-:10A140008FB300448FB200408FB1003C8FB0003815
-:10A1500003E0000827BD006094FE00548CF2004428
-:10A1600033C9FFFE0009C8C00259F821ACBF003C4A
-:10A170008CE800448CAD003C010D50231940003B9D
-:10A18000000000008CF7004026E20001ACA200387D
-:10A190003C05005034A700103C038000AC67003041
-:10A1A00000000000000000000000000000000000AF
-:10A1B000000000000000000000000000000000009F
-:10A1C0008C7800003316002012C0FFFD3C1180087F
-:10A1D000962200543C1580003C068008304E000159
-:10A1E000000E18C0007578218DEC04003C070800B3
-:10A1F0008CE700443C040020ACCC00488DF40404FF
-:10A20000240B0001ACD4004C10EB0260AEA4003073
-:10A21000963900523C0508008CA5004000B99021F9
-:10A22000A6320052963F005427ED0001A62D00549F
-:10A230009626005430C4FFFF5487FF2F8FB40010C0
-:10A2400030A5FFFF0E0011F4A62000543C070800C3
-:10A250008CE70024963E00520047B82303D74823DA
-:10A26000A62900520A0012198FB400108CE2004097
-:10A270000A0012BE00000000922400012407000121
-:10A280003085007F14A7001C97AD00268E2B00148C
-:10A29000240CC000316A3FFF01AC48243C06080092
-:10A2A0008CC60060012A402531043FFF0086882BC0
-:10A2B00012200011A7A800263C0508008CA5005814
-:10A2C0008F9100A0000439802402FF8000B1182182
-:10A2D0000067F82103E2F02433F8007F3C1280008D
-:10A2E0003C19800EAE5E002C0319702191D0000D38
-:10A2F000360F0004A1CF000D0E001028241200011B
-:10A30000241100013C1E80008FC401000E000FCEFE
-:10A3100002E028218FC401000E000FDE02C02821B8
-:10A320001620FF558F8B00A40A0012860013802B85
-:10A330008F8600A490C80001310400201080019194
-:10A34000241000013C048008348B0080916A007C5A
-:10A350008F9E0034AFA0002C314900011120000F66
-:10A36000AFB000288CCD00148C8E006001AE602B45
-:10A370001580000201A038218C8700603C188008FD
-:10A38000370300808C70007000F0782B15E000021D
-:10A3900000E020218C640070AFA4002C3C028008F7
-:10A3A000344500808CD200148CBF0070025FC82B33
-:10A3B00017200002024020218CA400708FA7002CDF
-:10A3C0000087182310600003AFA3003024050002AB
-:10A3D000AFA500288FA400280264882B162000BA9D
-:10A3E000000018218CD000388FCE000C3C0F00806C
-:10A3F000AFD000008CCD00343C0CFF9F01CF58251E
-:10A40000AFCD000490CA003F3586FFFF01662024CF
-:10A410003C0900203C08FFEFA3CA000B0089382547
-:10A420003511FFFF00F118243C0500088F8700A4B8
-:10A430000065C825AFD9000C8CE20014AFC000182D
-:10A440008FA60030AFC200148CF800188FB0002C1B
-:10A450003C1FFFFBAFD8001C8CEF000837F2FFFF5A
-:10A4600003326824AFCF00248CEC000C020670216C
-:10A47000AFCD000CA7C00038A7C0003AAFCE002C6B
-:10A48000AFCC0020AFC000288CEA00148FAB002CAA
-:10A49000014B48230126402311000011AFC80010D2
-:10A4A00090EB003D8FC900048FC80000000B5100E5
-:10A4B000012A28210000102100AA882B010218215E
-:10A4C0000071F821AFC50004AFDF000090F2003D3D
-:10A4D000A3D2000A8F9900A497380006A7D80008D5
-:10A4E0008F910038240800023C038008A228000055
-:10A4F0003465008094BF005C8FA4002C33F0FFFF14
-:10A500000E000FF48F9200380002CB808F8500A4DC
-:10A51000021978253C18420001F87025AE4E00045F
-:10A520008F8400388CAD0038AC8D00188CAC0034B2
-:10A53000AC8C001CAC80000CAC800010A48000141B
-:10A54000A4800016A4800020A4800022AC800024F7
-:10A5500090A6003F8FA7002CA486000250E0019235
-:10A56000240700018FA200305040000290A2003D5D
-:10A5700090A2003E244A0001A08A00018F84003886
-:10A580008FA9002CAC8900083C128008364D008051
-:10A5900091AC007C3186000214C000022407003414
-:10A5A000240700308F8500A43C198008373F0080C5
-:10A5B00090B0000093F9007C240E0004A0900030BD
-:10A5C0008F8F00A48FB8002C8F8D003891F200017E
-:10A5D0003304000301C46023A1B200318F8E003820
-:10A5E0008F8600A42402C00095CA003294C90012CC
-:10A5F0008FAB002C0142402431233FFF010388250B
-:10A60000A5D1003291D000323185000300EBF82152
-:10A610003218003F370F0040A1CF00328FA4002C2A
-:10A6200003E5382133280004108000028F850038AC
-:10A6300000E838213C0A8008ACA700343549010005
-:10A640008D2800D08FA3002C2419FFBFACA80038A0
-:10A6500090B1003C2C640001240FFFDF3227007F03
-:10A66000A0A7003C8F98003800049140931F003C45
-:10A6700003F98024A310003C8F8C0038918E003C9D
-:10A6800001CF682401B23025A186003C8F8900A447
-:10A690008F8800388D2B0020AD0B00408D220024C8
-:10A6A000AD0200448D2A0028AD0A00488D23002CFD
-:10A6B0000E001013AD03004C8FB1002824070002D8
-:10A6C000122700118FA300280003282B00058023E8
-:10A6D0000270982400608021006090210A00126FAF
-:10A6E0000010882B962900128F8400A00000902172
-:10A6F0003125FFFFA7A900180E000FC22411000189
-:10A700000A00131D3C1E80003C0B80003C12800898
-:10A710008D640100924900088F92FF340E000F995A
-:10A720003125007F8F9900388FA700288FA4003033
-:10A73000A3270000965F005C33F0FFFF0E000FF4CC
-:10A740008F91003800026B80020D80253C0842008A
-:10A750008F8D00A402085025AE2A00048DA5003874
-:10A760008F8A003800007821000F1100AD450018D5
-:10A770008DB800343C047FFF3488FFFFAD58001CC7
-:10A7800091A6003E8D4C001C8D4900180006190052
-:10A79000000677020183C821004E58250323882B29
-:10A7A000012B382100F1F821AD59001CAD5F0018D4
-:10A7B000AD40000CAD40001091B0003E8FA40030C1
-:10A7C00024090005A550001495A500042419C00013
-:10A7D00000884024A545001691B8003EA5580020E9
-:10A7E00095AF0004A54F0022AD40002491AE003F7C
-:10A7F000A54E000291A6003E91AC003D01861023BB
-:10A80000244B0001A14B00018F9100388FA3003031
-:10A810003C028008344B0100AE230008A22900301E
-:10A820008F8C00388F8700A4959F003294F000121F
-:10A830002407FFBF033FC02432053FFF03057825EF
-:10A84000A58F0032918E00322418FFDF31CD003FFA
-:10A8500035A60040A18600328F910038240DFFFFFD
-:10A86000240CFF80AE2000348D6A00D0AE2A003860
-:10A870009223003C3069007FA229003C8F90003871
-:10A880003C0380009219003C0327F824A21F003CDF
-:10A890008F8E003891C5003C00B87824A1CF003CD1
-:10A8A0008F8A00383C0E8008AD4D00408FA6002CEA
-:10A8B000AD46004491420048004C5825A14B004849
-:10A8C0008F9000388F9900A48E09004801238824B6
-:10A8D00002283825AE070048933F003EA21F004CD7
-:10A8E0008F9800A48F8F003897050004A5E5004ECF
-:10A8F0000E0003818DC500609246007C8FAC003055
-:10A9000000026940000291000040282130CB000283
-:10A9100001B21021156000AA018230213C0E80088E
-:10A9200035C20080904C007C31830004106000032D
-:10A930008FB900300005788000CF3021241F00043B
-:10A940008F910038332D000303ED8023320800037C
-:10A9500000C85021AE2A00343C188000A7C500383A
-:10A960003C0680088F04010090DE00080E000FDE18
-:10A9700033C5007F0E001013000000000A00140D04
-:10A980008FA300288F9800348CC90038241F00033F
-:10A99000A7000008AF0900008CC50034A300000A1E
-:10A9A0008F9900A4AF0500043C080080932D003F60
-:10A9B000A31F000C8F0A000C3C02FF9FA30D000B8D
-:10A9C0000148F0253451FFFF3C12FFEF8F9900A49E
-:10A9D00003D170243646FFFF01C61824AF03000CD4
-:10A9E0008F2C0014972900128F8400A0AF0C001048
-:10A9F0008F2F0014AF000018AF000020AF0F00141D
-:10AA0000AF0000248F270018312F3FFF000F59801F
-:10AA1000AF0700288F2500080164F821312D0001BF
-:10AA2000AF0500308F31000C8F920038001F51C2EB
-:10AA3000000D438001481021241E00023C068008BE
-:10AA4000A702001CA7000034AF11002CA25E00007A
-:10AA500034D20080964E005C8F9900383C0342004F
-:10AA600031CCFFFF01833825AF2700048F8B00A472
-:10AA7000240500012402C0008D640038240700343E
-:10AA8000AF2400188D690034AF29001CAF20000CE2
-:10AA9000AF200010A7200014A7200016A720002038
-:10AAA000A7200022AF200024A7300002A325000128
-:10AAB0008F8800388F9F00A4AD10000893ED000030
-:10AAC000A10D00308F8A00A48F98003891510001A9
-:10AAD000A31100318F8B0038957E003203C27024A1
-:10AAE00001CF6025A56C0032916300323064003FD5
-:10AAF000A16400329249007C3125000214A00002BA
-:10AB00008F840038240700303C198008AC8700345B
-:10AB1000373201008E5F00D0240AFFBF020090216F
-:10AB2000AC9F0038908D003C31A8007FA088003C8D
-:10AB30008F9E003893C2003C004A8824A3D1003C79
-:10AB40008F8300380010882B9066003C34CE0020A4
-:10AB5000A06E003C8F8400A48F9800388C8C00205D
-:10AB6000AF0C00408C8F0024AF0F00448C8700286E
-:10AB7000AF0700488C8B002CAF0B004C0E0010135D
-:10AB80003C1E80000A0012700000000094C80052B1
-:10AB90003C0A08008D4A002401488821A4D10052B3
-:10ABA0000A0012198FB40010A08700018F840038AA
-:10ABB000240B0001AC8B00080A0013BE3C12800875
-:10ABC000000520800A0014A200C4302127BDFFE048
-:10ABD0003C0D8008AFB20018AFB00010AFBF001C32
-:10ABE000AFB1001435B200808E4C001835A80100BA
-:10ABF000964B000695A70050910900FC000C5602E8
-:10AC0000016728233143007F312600FF240200031F
-:10AC1000AF8300A8AF8400A010C2001B30B0FFFFBC
-:10AC2000910600FC2412000530C200FF10520033D0
-:10AC300000000000160000098FBF001C8FB2001832
-:10AC40008FB100148FB00010240D0C003C0C80005C
-:10AC500027BD002003E00008AD8D00240E0011FB8D
-:10AC6000020020218FBF001C8FB200188FB100148A
-:10AC70008FB00010240D0C003C0C800027BD00207C
-:10AC800003E00008AD8D0024965800789651007AB4
-:10AC9000924E007D0238782631E8FFFF31C400C0B3
-:10ACA000148000092D11000116000037000000007B
-:10ACB0005620FFE28FBF001C0E0010D100000000E4
-:10ACC0000A00156A8FBF001C1620FFDA0000000082
-:10ACD0000E0010D1000000001440FFD88FBF001CF0
-:10ACE0001600002200000000925F007D33E2003F6A
-:10ACF000A242007D0A00156A8FBF001C950900EA78
-:10AD00008F86008000802821240400050E0007257E
-:10AD10003130FFFF978300923C0480002465FFFFE1
-:10AD2000A78500928C8A01B80540FFFE0000000054
-:10AD3000AC8001808FBF001CAC9001848FB20018E2
-:10AD40008FB100148FB000103C0760133C0B100053
-:10AD5000240D0C003C0C800027BD0020AC8701882E
-:10AD6000AC8B01B803E00008AD8D00240E0011FB90
-:10AD7000020020215040FFB18FBF001C925F007D78
-:10AD80000A00159733E2003F0E0011FB020020215C
-:10AD90001440FFAA8FBF001C122000070000000013
-:10ADA0009259007D3330003F36020040A242007DC0
-:10ADB0000A00156A8FBF001C0E0010D100000000B1
-:10ADC0005040FF9E8FBF001C9259007D3330003FE2
-:08ADD0000A0015C6360200401E
-:08ADD800000000000000001B58
-:10ADE0000000000F0000000A00000008000000063C
-:10ADF0000000000500000005000000040000000441
-:10AE00000000000300000003000000030000000336
-:10AE10000000000300000002000000020000000229
-:10AE2000000000020000000200000002000000021A
-:10AE3000000000020000000200000002000000020A
-:10AE400000000002000000020000000200000002FA
-:0CAE5000000000010000000100000001F3
-:04AE5C008008010069
-:10AE6000800800808008000000000C000000308096
-:10AE7000080011D00800127C08001294080012A8E3
-:10AE8000080012BC080011D0080011D0080012F010
-:10AE90000800132C080013400800138808001A8CBF
-:10AEA00008001A8C08001AC408001AC408001AD82E
-:10AEB00008001AA808001D0008001CCC08001D5836
-:10AEC00008001D5808001DE008001D108008024001
-:10AED000080027340800256C0800275C080027F4C8
-:10AEE0000800293C0800298808002AAC080029B479
-:10AEF00008002A38080025DC08002EDC08002EA4F3
-:10AF000008002588080025880800258808002B20CF
-:10AF100008002B20080025880800258808002DD06F
-:10AF2000080025880800258808002588080025884D
-:10AF300008002E0C080025880800258808002588B0
-:10AF4000080025880800258808002588080025882D
-:10AF5000080025880800258808002588080025881D
-:10AF6000080025880800258808002588080029A8E9
-:10AF7000080025880800258808002E680800258814
-:10AF800008002588080025880800258808002588ED
-:10AF900008002588080025880800258808002588DD
-:10AFA00008002588080025880800258808002588CD
-:10AFB00008002588080025880800258808002588BD
-:10AFC00008002CF4080025880800258808002C6853
-:10AFD00008002BC408003CE408003CB808003C848E
-:10AFE00008003C5808003C3808003BEC8008010091
-:10AFF00080080080800800008008008008004C6401
-:10B0000008004C9C08004BE408004C6408004C64A9
-:0CB01000080049B808004C6408005050CB
-:04B01C000A000C8496
-:10B0200000000000000000000000000D7278703683
-:10B030002E322E3100000000060201030000000045
-:10B0400000000001000000000000000000000000FF
-:10B0500000000000000000000000000000000000F0
-:10B0600000000000000000000000000000000000E0
-:10B0700000000000000000000000000000000000D0
-:10B0800000000000000000000000000000000000C0
-:10B0900000000000000000000000000000000000B0
-:10B0A00000000000000000000000000000000000A0
-:10B0B0000000000000000000000000000000000090
-:10B0C0000000000000000000000000000000000080
-:10B0D0000000000000000000000000000000000070
-:10B0E0000000000000000000000000000000000060
-:10B0F0000000000000000000000000000000000050
-:10B10000000000000000000000000000000000003F
-:10B11000000000000000000000000000000000002F
-:10B12000000000000000000000000000000000001F
-:10B13000000000000000000000000000000000000F
-:10B1400000000000000000000000000000000000FF
-:10B1500000000000000000000000000000000000EF
-:10B1600000000000000000000000000000000000DF
-:10B1700000000000000000000000000000000000CF
-:10B1800000000000000000000000000000000000BF
-:10B1900000000000000000000000000000000000AF
-:10B1A000000000000000000000000000000000009F
-:10B1B000000000000000000000000000000000008F
-:10B1C000000000000000000000000000000000007F
-:10B1D000000000000000000000000000000000006F
-:10B1E000000000000000000000000000000000005F
-:10B1F000000000000000000000000000000000004F
-:10B20000000000000000000000000000000000003E
-:10B21000000000000000000000000000000000002E
-:10B22000000000000000000000000000000000001E
-:10B23000000000000000000000000000000000000E
-:10B2400000000000000000000000000000000000FE
-:10B2500000000000000000000000000000000000EE
-:10B2600000000000000000000000000000000000DE
-:10B2700000000000000000000000000000000000CE
-:10B2800000000000000000000000000000000000BE
-:10B2900000000000000000000000000000000000AE
-:10B2A000000000000000000000000000000000009E
-:10B2B000000000000000000000000000000000008E
-:10B2C000000000000000000000000000000000007E
-:10B2D000000000000000000000000000000000006E
-:10B2E000000000000000000000000000000000005E
-:10B2F000000000000000000000000000000000004E
-:10B30000000000000000000000000000000000003D
-:10B31000000000000000000000000000000000002D
-:10B32000000000000000000000000000000000001D
-:10B33000000000000000000000000000000000000D
-:10B3400000000000000000000000000000000000FD
-:10B3500000000000000000000000000000000000ED
-:10B3600000000000000000000000000000000000DD
-:10B3700000000000000000000000000000000000CD
-:10B3800000000000000000000000000000000000BD
-:10B3900000000000000000000000000000000000AD
-:10B3A000000000000000000000000000000000009D
-:10B3B000000000000000000000000000000000008D
-:10B3C000000000000000000000000000000000007D
-:10B3D000000000000000000000000000000000006D
-:10B3E000000000000000000000000000000000005D
-:10B3F000000000000000000000000000000000004D
-:10B40000000000000000000000000000000000003C
-:10B41000000000000000000000000000000000002C
-:10B42000000000000000000000000000000000001C
-:10B43000000000000000000000000000000000000C
-:10B4400000000000000000000000000000000000FC
-:10B4500000000000000000000000000000000000EC
-:10B4600000000000000000000000000000000000DC
-:10B4700000000000000000000000000000000000CC
-:10B4800000000000000000000000000000000000BC
-:10B4900000000000000000000000000000000000AC
-:10B4A000000000000000000000000000000000009C
-:10B4B000000000000000000000000000000000008C
-:10B4C000000000000000000000000000000000007C
-:10B4D000000000000000000000000000000000006C
-:10B4E000000000000000000000000000000000005C
-:10B4F000000000000000000000000000000000004C
-:10B50000000000000000000000000000000000003B
-:10B51000000000000000000000000000000000002B
-:10B52000000000000000000000000000000000001B
-:10B53000000000000000000000000000000000000B
-:10B5400000000000000000000000000000000000FB
-:10B5500000000000000000000000000000000000EB
-:10B5600000000000000000000000000000000000DB
-:10B5700000000000000000000000000000000000CB
-:10B5800000000000000000000000000000000000BB
-:10B5900000000000000000000000000000000000AB
-:10B5A000000000000000000000000000000000009B
-:10B5B000000000000000000000000000000000008B
-:10B5C000000000000000000000000000000000007B
-:10B5D000000000000000000000000000000000006B
-:10B5E000000000000000000000000000000000005B
-:10B5F000000000000000000000000000000000004B
-:10B60000000000000000000000000000000000003A
-:10B61000000000000000000000000000000000002A
-:10B62000000000000000000000000000000000001A
-:10B63000000000000000000000000000000000000A
-:10B6400000000000000000000000000000000000FA
-:10B6500000000000000000000000000000000000EA
-:10B6600000000000000000000000000000000000DA
-:10B6700000000000000000000000000000000000CA
-:10B6800000000000000000000000000000000000BA
-:10B6900000000000000000000000000000000000AA
-:10B6A000000000000000000000000000000000009A
-:10B6B000000000000000000000000000000000008A
-:10B6C000000000000000000000000000000000007A
-:10B6D000000000000000000000000000000000006A
-:10B6E000000000000000000000000000000000005A
-:10B6F000000000000000000000000000000000004A
-:10B700000000000000000000000000000000000039
-:10B710000000000000000000000000000000000029
-:10B720000000000000000000000000000000000019
-:10B730000000000000000000000000000000000009
-:10B7400000000000000000000000000000000000F9
-:10B7500000000000000000000000000000000000E9
-:10B7600000000000000000000000000000000000D9
-:10B7700000000000000000000000000000000000C9
-:10B7800000000000000000000000000000000000B9
-:10B7900000000000000000000000000000000000A9
-:10B7A0000000000000000000000000000000000099
-:10B7B0000000000000000000000000000000000089
-:10B7C0000000000000000000000000000000000079
-:10B7D0000000000000000000000000000000000069
-:10B7E0000000000000000000000000000000000059
-:10B7F0000000000000000000000000000000000049
-:10B800000000000000000000000000000000000038
-:10B810000000000000000000000000000000000028
-:10B820000000000000000000000000000000000018
-:10B830000000000000000000000000000000000008
-:10B8400000000000000000000000000000000000F8
-:10B8500000000000000000000000000000000000E8
-:10B8600000000000000000000000000000000000D8
-:10B8700000000000000000000000000000000000C8
-:10B8800000000000000000000000000000000000B8
-:10B8900000000000000000000000000000000000A8
-:10B8A0000000000000000000000000000000000098
-:10B8B0000000000000000000000000000000000088
-:10B8C0000000000000000000000000000000000078
-:10B8D0000000000000000000000000000000000068
-:10B8E0000000000000000000000000000000000058
-:10B8F0000000000000000000000000000000000048
-:10B900000000000000000000000000000000000037
-:10B910000000000000000000000000000000000027
-:10B920000000000000000000000000000000000017
-:10B930000000000000000000000000000000000007
-:10B9400000000000000000000000000000000000F7
-:10B9500000000000000000000000000000000000E7
-:10B9600000000000000000000000000000000000D7
-:10B9700000000000000000000000000000000000C7
-:10B9800000000000000000000000000000000000B7
-:10B9900000000000000000000000000000000000A7
-:10B9A0000000000000000000000000000000000097
-:10B9B0000000000000000000000000000000000087
-:10B9C0000000000000000000000000000000000077
-:10B9D0000000000000000000000000000000000067
-:10B9E0000000000000000000000000000000000057
-:10B9F0000000000000000000000000000000000047
-:10BA00000000000000000000000000000000000036
-:10BA10000000000000000000000000000000000026
-:10BA20000000000000000000000000000000000016
-:10BA30000000000000000000000000000000000006
-:10BA400000000000000000000000000000000000F6
-:10BA500000000000000000000000000000000000E6
-:10BA600000000000000000000000000000000000D6
-:10BA700000000000000000000000000000000000C6
-:10BA800000000000000000000000000000000000B6
-:10BA900000000000000000000000000000000000A6
-:10BAA0000000000000000000000000000000000096
-:10BAB0000000000000000000000000000000000086
-:10BAC0000000000000000000000000000000000076
-:10BAD0000000000000000000000000000000000066
-:10BAE0000000000000000000000000000000000056
-:10BAF0000000000000000000000000000000000046
-:10BB00000000000000000000000000000000000035
-:10BB10000000000000000000000000000000000025
-:10BB20000000000000000000000000000000000015
-:10BB30000000000000000000000000000000000005
-:10BB400000000000000000000000000000000000F5
-:10BB500000000000000000000000000000000000E5
-:10BB600000000000000000000000000000000000D5
-:10BB700000000000000000000000000000000000C5
-:10BB800000000000000000000000000000000000B5
-:10BB900000000000000000000000000000000000A5
-:10BBA0000000000000000000000000000000000095
-:10BBB0000000000000000000000000000000000085
-:10BBC0000000000000000000000000000000000075
-:10BBD0000000000000000000000000000000000065
-:10BBE0000000000000000000000000000000000055
-:10BBF0000000000000000000000000000000000045
-:10BC00000000000000000000000000000000000034
-:10BC10000000000000000000000000000000000024
-:10BC20000000000000000000000000000000000014
-:10BC30000000000000000000000000000000000004
-:10BC400000000000000000000000000000000000F4
-:10BC500000000000000000000000000000000000E4
-:10BC600000000000000000000000000000000000D4
-:10BC700000000000000000000000000000000000C4
-:10BC800000000000000000000000000000000000B4
-:10BC900000000000000000000000000000000000A4
-:10BCA0000000000000000000000000000000000094
-:10BCB0000000000000000000000000000000000084
-:10BCC0000000000000000000000000000000000074
-:10BCD0000000000000000000000000000000000064
-:10BCE0000000000000000000000000000000000054
-:10BCF0000000000000000000000000000000000044
-:10BD00000000000000000000000000000000000033
-:10BD10000000000000000000000000000000000023
-:10BD20000000000000000000000000000000000013
-:10BD30000000000000000000000000000000000003
-:10BD400000000000000000000000000000000000F3
-:10BD500000000000000000000000000000000000E3
-:10BD600000000000000000000000000000000000D3
-:10BD700000000000000000000000000000000000C3
-:10BD800000000000000000000000000000000000B3
-:10BD900000000000000000000000000000000000A3
-:10BDA0000000000000000000000000000000000093
-:10BDB0000000000000000000000000000000000083
-:10BDC0000000000000000000000000000000000073
-:10BDD0000000000000000000000000000000000063
-:10BDE0000000000000000000000000000000000053
-:10BDF0000000000000000000000000000000000043
-:10BE00000000000000000000000000000000000032
-:10BE10000000000000000000000000000000000022
-:10BE20000000000000000000000000000000000012
-:10BE30000000000000000000000000000000000002
-:10BE400000000000000000000000000000000000F2
-:10BE500000000000000000000000000000000000E2
-:10BE600000000000000000000000000000000000D2
-:10BE700000000000000000000000000000000000C2
-:10BE800000000000000000000000000000000000B2
-:10BE900000000000000000000000000000000000A2
-:10BEA0000000000000000000000000000000000092
-:10BEB0000000000000000000000000000000000082
-:10BEC0000000000000000000000000000000000072
-:10BED0000000000000000000000000000000000062
-:10BEE0000000000000000000000000000000000052
-:10BEF0000000000000000000000000000000000042
-:10BF00000000000000000000000000000000000031
-:10BF10000000000000000000000000000000000021
-:10BF20000000000000000000000000000000000011
-:10BF30000000000000000000000000000000000001
-:10BF400000000000000000000000000000000000F1
-:10BF500000000000000000000000000000000000E1
-:10BF600000000000000000000000000000000000D1
-:10BF700000000000000000000000000000000000C1
-:10BF800000000000000000000000000000000000B1
-:10BF900000000000000000000000000000000000A1
-:10BFA0000000000000000000000000000000000091
-:10BFB0000000000000000000000000000000000081
-:10BFC0000000000000000000000000000000000071
-:10BFD0000000000000000000000000000000000061
-:10BFE0000000000000000000000000000000000051
-:10BFF0000000000000000000000000000000000041
-:10C000000000000000000000000000000000000030
-:10C010000000000000000000000000000000000020
-:10C020000000000000000000000000000000000010
-:10C030000000000000000000000000000000000000
-:10C0400000000000000000000000000000000000F0
-:10C0500000000000000000000000000000000000E0
-:10C0600000000000000000000000000000000000D0
-:10C0700000000000000000000000000000000000C0
-:10C0800000000000000000000000000000000000B0
-:10C0900000000000000000000000000000000000A0
-:10C0A0000000000000000000000000000000000090
-:10C0B0000000000000000000000000000000000080
-:10C0C0000000000000000000000000000000000070
-:10C0D0000000000000000000000000000000000060
-:10C0E0000000000000000000000000000000000050
-:10C0F0000000000000000000000000000000000040
-:10C10000000000000000000000000000000000002F
-:10C11000000000000000000000000000000000001F
-:10C12000000000000000000000000000000000000F
-:10C1300000000000000000000000000000000000FF
-:10C1400000000000000000000000000000000000EF
-:10C1500000000000000000000000000000000000DF
-:10C1600000000000000000000000000000000000CF
-:10C1700000000000000000000000000000000000BF
-:10C1800000000000000000000000000000000000AF
-:10C19000000000000000000000000000000000009F
-:10C1A000000000000000000000000000000000008F
-:10C1B000000000000000000000000000000000007F
-:10C1C000000000000000000000000000000000006F
-:10C1D000000000000000000000000000000000005F
-:10C1E000000000000000000000000000000000004F
-:10C1F000000000000000000000000000000000003F
-:10C20000000000000000000000000000000000002E
-:10C21000000000000000000000000000000000001E
-:10C22000000000000000000000000000000000000E
-:10C2300000000000000000000000000000000000FE
-:10C2400000000000000000000000000000000000EE
-:10C2500000000000000000000000000000000000DE
-:10C2600000000000000000000000000000000000CE
-:10C2700000000000000000000000000000000000BE
-:10C2800000000000000000000000000000000000AE
-:10C29000000000000000000000000000000000009E
-:10C2A000000000000000000000000000000000008E
-:10C2B000000000000000000000000000000000007E
-:10C2C000000000000000000000000000000000006E
-:10C2D000000000000000000000000000000000005E
-:10C2E000000000000000000000000000000000004E
-:10C2F000000000000000000000000000000000003E
-:10C30000000000000000000000000000000000002D
-:10C31000000000000000000000000000000000001D
-:10C32000000000000000000000000000000000000D
-:10C3300000000000000000000000000000000000FD
-:10C3400000000000000000000000000000000000ED
-:10C3500000000000000000000000000000000000DD
-:10C3600000000000000000000000000000000000CD
-:10C3700000000000000000000000000000000000BD
-:10C3800000000000000000000000000000000000AD
-:10C39000000000000000000000000000000000009D
-:10C3A000000000000000000000000000000000008D
-:10C3B000000000000000000000000000000000007D
-:10C3C000000000000000000000000000000000006D
-:10C3D000000000000000000000000000000000005D
-:10C3E000000000000000000000000000000000004D
-:10C3F000000000000000000000000000000000003D
-:10C40000000000000000000000000000000000002C
-:10C41000000000000000000000000000000000001C
-:10C42000000000000000000000000000000000000C
-:10C4300000000000000000000000000000000000FC
-:10C4400000000000000000000000000000000000EC
-:10C4500000000000000000000000000000000000DC
-:10C4600000000000000000000000000000000000CC
-:10C4700000000000000000000000000000000000BC
-:10C4800000000000000000000000000000000000AC
-:10C49000000000000000000000000000000000009C
-:10C4A000000000000000000000000000000000008C
-:10C4B000000000000000000000000000000000007C
-:10C4C000000000000000000000000000000000006C
-:10C4D000000000000000000000000000000000005C
-:10C4E000000000000000000000000000000000004C
-:10C4F000000000000000000000000000000000003C
-:10C50000000000000000000000000000000000002B
-:10C51000000000000000000000000000000000001B
-:10C52000000000000000000000000000000000000B
-:10C5300000000000000000000000000000000000FB
-:10C5400000000000000000000000000000000000EB
-:10C5500000000000000000000000000000000000DB
-:10C5600000000000000000000000000000000000CB
-:10C5700000000000000000000000000000000000BB
-:10C5800000000000000000000000000000000000AB
-:10C59000000000000000000000000000000000009B
-:10C5A000000000000000000000000000000000008B
-:10C5B000000000000000000000000000000000007B
-:10C5C000000000000000000000000000000000006B
-:10C5D000000000000000000000000000000000005B
-:10C5E000000000000000000000000000000000004B
-:10C5F000000000000000000000000000000000003B
-:10C60000000000000000000000000000000000002A
-:10C61000000000000000000000000000000000001A
-:10C62000000000000000000000000000000000000A
-:10C6300000000000000000000000000000000000FA
-:10C6400000000000000000000000000000000000EA
-:10C6500000000000000000000000000000000000DA
-:10C6600000000000000000000000000000000000CA
-:10C6700000000000000000000000000000000000BA
-:10C6800000000000000000000000000000000000AA
-:10C69000000000000000000000000000000000009A
-:10C6A000000000000000000000000000000000008A
-:10C6B000000000000000000000000000000000007A
-:10C6C000000000000000000000000000000000006A
-:10C6D000000000000000000000000000000000005A
-:10C6E000000000000000000000000000000000004A
-:10C6F000000000000000000000000000000000003A
-:10C700000000000000000000000000000000000029
-:10C710000000000000000000000000000000000019
-:10C720000000000000000000000000000000000009
-:10C7300000000000000000000000000000000000F9
-:10C7400000000000000000000000000000000000E9
-:10C7500000000000000000000000000000000000D9
-:10C7600000000000000000000000000000000000C9
-:10C7700000000000000000000000000000000000B9
-:10C7800000000000000000000000000000000000A9
-:10C790000000000000000000000000000000000099
-:10C7A0000000000000000000000000000000000089
-:10C7B0000000000000000000000000000000000079
-:10C7C0000000000000000000000000000000000069
-:10C7D0000000000000000000000000000000000059
-:10C7E0000000000000000000000000000000000049
-:10C7F0000000000000000000000000000000000039
-:10C800000000000000000000000000000000000028
-:10C810000000000000000000000000000000000018
-:10C820000000000000000000000000000000000008
-:10C8300000000000000000000000000000000000F8
-:10C8400000000000000000000000000000000000E8
-:10C8500000000000000000000000000000000000D8
-:10C8600000000000000000000000000000000000C8
-:10C8700000000000000000000000000000000000B8
-:10C8800000000000000000000000000000000000A8
-:10C890000000000000000000000000000000000098
-:10C8A0000000000000000000000000000000000088
-:10C8B0000000000000000000000000000000000078
-:10C8C0000000000000000000000000000000000068
-:10C8D0000000000000000000000000000000000058
-:10C8E0000000000000000000000000000000000048
-:10C8F0000000000000000000000000000000000038
-:10C900000000000000000000000000000000000027
-:10C910000000000000000000000000000000000017
-:10C920000000000000000000000000000000000007
-:10C9300000000000000000000000000000000000F7
-:10C9400000000000000000000000000000000000E7
-:10C9500000000000000000000000000000000000D7
-:10C9600000000000000000000000000000000000C7
-:10C9700000000000000000000000000000000000B7
-:10C9800000000000000000000000000000000000A7
-:10C990000000000000000000000000000000000097
-:10C9A0000000000000000000000000000000000087
-:10C9B0000000000000000000000000000000000077
-:10C9C0000000000000000000000000000000000067
-:10C9D0000000000000000000000000000000000057
-:10C9E0000000000000000000000000000000000047
-:10C9F0000000000000000000000000000000000037
-:10CA00000000000000000000000000000000000026
-:10CA10000000000000000000000000000000000016
-:10CA20000000000000000000000000000000000006
-:10CA300000000000000000000000000000000000F6
-:10CA400000000000000000000000000000000000E6
-:10CA500000000000000000000000000000000000D6
-:10CA600000000000000000000000000000000000C6
-:10CA700000000000000000000000000000000000B6
-:10CA800000000000000000000000000000000000A6
-:10CA90000000000000000000000000000000000096
-:10CAA0000000000000000000000000000000000086
-:10CAB0000000000000000000000000000000000076
-:10CAC0000000000000000000000000000000000066
-:10CAD0000000000000000000000000000000000056
-:10CAE0000000000000000000000000000000000046
-:10CAF0000000000000000000000000000000000036
-:10CB00000000000000000000000000000000000025
-:10CB10000000000000000000000000000000000015
-:10CB20000000000000000000000000000000000005
-:10CB300000000000000000000000000000000000F5
-:10CB400000000000000000000000000000000000E5
-:10CB500000000000000000000000000000000000D5
-:10CB600000000000000000000000000000000000C5
-:10CB700000000000000000000000000000000000B5
-:10CB800000000000000000000000000000000000A5
-:10CB90000000000000000000000000000000000095
-:10CBA0000000000000000000000000000000000085
-:10CBB0000000000000000000000000000000000075
-:10CBC0000000000000000000000000000000000065
-:10CBD0000000000000000000000000000000000055
-:10CBE0000000000000000000000000000000000045
-:10CBF0000000000000000000000000000000000035
-:10CC00000000000000000000000000000000000024
-:10CC10000000000000000000000000000000000014
-:10CC20000000000000000000000000000000000004
-:10CC300000000000000000000000000000000000F4
-:10CC400000000000000000000000000000000000E4
-:10CC500000000000000000000000000000000000D4
-:10CC600000000000000000000000000000000000C4
-:10CC700000000000000000000000000000000000B4
-:10CC800000000000000000000000000000000000A4
-:10CC90000000000000000000000000000000000094
-:10CCA0000000000000000000000000000000000084
-:10CCB0000000000000000000000000000000000074
-:10CCC0000000000000000000000000000000000064
-:10CCD0000000000000000000000000000000000054
-:10CCE0000000000000000000000000000000000044
-:10CCF0000000000000000000000000000000000034
-:10CD00000000000000000000000000000000000023
-:10CD10000000000000000000000000000000000013
-:10CD20000000000000000000000000000000000003
-:10CD300000000000000000000000000000000000F3
-:10CD400000000000000000000000000000000000E3
-:10CD500000000000000000000000000000000000D3
-:10CD600000000000000000000000000000000000C3
-:10CD700000000000000000000000000000000000B3
-:10CD800000000000000000000000000000000000A3
-:10CD90000000000000000000000000000000000093
-:10CDA0000000000000000000000000000000000083
-:10CDB0000000000000000000000000000000000073
-:10CDC0000000000000000000000000000000000063
-:10CDD0000000000000000000000000000000000053
-:10CDE0000000000000000000000000000000000043
-:10CDF0000000000000000000000000000000000033
-:10CE00000000000000000000000000000000000022
-:10CE10000000000000000000000000000000000012
-:10CE20000000000000000000000000000000000002
-:10CE300000000000000000000000000000000000F2
-:10CE400000000000000000000000000000000000E2
-:10CE500000000000000000000000000000000000D2
-:10CE600000000000000000000000000000000000C2
-:10CE700000000000000000000000000000000000B2
-:10CE800000000000000000000000000000000000A2
-:10CE90000000000000000000000000000000000092
-:10CEA0000000000000000000000000000000000082
-:10CEB0000000000000000000000000000000000072
-:10CEC0000000000000000000000000000000000062
-:10CED0000000000000000000000000000000000052
-:10CEE0000000000000000000000000000000000042
-:10CEF0000000000000000000000000000000000032
-:10CF00000000000000000000000000000000000021
-:10CF10000000000000000000000000000000000011
-:10CF20000000000000000000000000000000000001
-:10CF300000000000000000000000000000000000F1
-:10CF400000000000000000000000000000000000E1
-:10CF500000000000000000000000000000000000D1
-:10CF600000000000000000000000000000000000C1
-:10CF700000000000000000000000000000000000B1
-:10CF800000000000000000000000000000000000A1
-:10CF90000000000000000000000000000000000091
-:10CFA0000000000000000000000000000000000081
-:10CFB0000000000000000000000000000000000071
-:10CFC0000000000000000000000000000000000061
-:10CFD0000000000000000000000000000000000051
-:10CFE0000000000000000000000000000000000041
-:10CFF0000000000000000000000000000000000031
-:10D000000000000000000000000000000000000020
-:10D010000000000000000000000000000000000010
-:10D020000000000000000000000000000000000000
-:10D0300000000000000000000000000000000000F0
-:10D0400000000000000000000000000000000000E0
-:10D0500000000000000000000000000000000000D0
-:10D0600000000000000000000000000000000000C0
-:10D0700000000000000000000000000000000000B0
-:10D0800000000000000000000000000000000000A0
-:10D090000000000000000000000000000000000090
-:10D0A0000000000000000000000000000000000080
-:10D0B0000000000000000000000000000000000070
-:10D0C0000000000000000000000000000000000060
-:10D0D0000000000000000000000000000000000050
-:10D0E0000000000000000000000000000000000040
-:10D0F0000000000000000000000000000000000030
-:10D10000000000000000000000000000000000001F
-:10D11000000000000000000000000000000000000F
-:10D1200000000000000000000000000000000000FF
-:10D1300000000000000000000000000000000000EF
-:10D1400000000000000000000000000000000000DF
-:10D1500000000000000000000000000000000000CF
-:10D1600000000000000000000000000000000000BF
-:10D1700000000000000000000000000000000000AF
-:10D18000000000000000000000000000000000009F
-:10D19000000000000000000000000000000000008F
-:10D1A000000000000000000000000000000000007F
-:10D1B000000000000000000000000000000000006F
-:10D1C000000000000000000000000000000000005F
-:10D1D000000000000000000000000000000000004F
-:10D1E000000000000000000000000000000000003F
-:10D1F000000000000000000000000000000000002F
-:10D20000000000000000000000000000000000001E
-:10D21000000000000000000000000000000000000E
-:10D2200000000000000000000000000000000000FE
-:10D2300000000000000000000000000000000000EE
-:10D2400000000000000000000000000000000000DE
-:10D2500000000000000000000000000000000000CE
-:10D2600000000000000000000000000000000000BE
-:10D2700000000000000000000000000000000000AE
-:10D28000000000000000000000000000000000009E
-:10D29000000000000000000000000000000000008E
-:10D2A000000000000000000000000000000000007E
-:10D2B000000000000000000000000000000000006E
-:10D2C000000000000000000000000000000000005E
-:10D2D000000000000000000000000000000000004E
-:10D2E000000000000000000000000000000000003E
-:10D2F000000000000000000000000000000000002E
-:10D30000000000000000000000000000000000001D
-:10D31000000000000000000000000000000000000D
-:10D3200000000000000000000000000000000000FD
-:10D3300000000000000000000000000000000000ED
-:10D3400000000000000000000000000000000000DD
-:10D3500000000000000000000000000000000000CD
-:10D3600000000000000000000000000000000000BD
-:10D3700000000000000000000000000000000000AD
-:10D38000000000000000000000000000000000009D
-:10D39000000000000000000000000000000000008D
-:10D3A000000000000000000000000000000000007D
-:10D3B000000000000000000000000000000000006D
-:10D3C000000000000000000000000000000000005D
-:10D3D000000000000000000000000000000000004D
-:10D3E000000000000000000000000000000000003D
-:10D3F000000000000000000000000000000000002D
-:10D40000000000000000000000000000000000001C
-:10D41000000000000000000000000000000000000C
-:10D4200000000000000000000000000000000000FC
-:10D4300000000000000000000000000000000000EC
-:10D4400000000000000000000000000000000000DC
-:10D4500000000000000000000000000000000000CC
-:10D4600000000000000000000000000000000000BC
-:10D4700000000000000000000000000000000000AC
-:10D48000000000000000000000000000000000009C
-:10D49000000000000000000000000000000000008C
-:10D4A000000000000000000000000000000000007C
-:10D4B000000000000000000000000000000000006C
-:10D4C000000000000000000000000000000000005C
-:10D4D000000000000000000000000000000000004C
-:10D4E000000000000000000000000000000000003C
-:10D4F000000000000000000000000000000000002C
-:10D50000000000000000000000000000000000001B
-:10D51000000000000000000000000000000000000B
-:10D5200000000000000000000000000000000000FB
-:10D5300000000000000000000000000000000000EB
-:10D5400000000000000000000000000000000000DB
-:10D5500000000000000000000000000000000000CB
-:10D5600000000000000000000000000000000000BB
-:10D5700000000000000000000000000000000000AB
-:10D58000000000000000000000000000000000009B
-:10D59000000000000000000000000000000000008B
-:10D5A000000000000000000000000000000000007B
-:10D5B000000000000000000000000000000000006B
-:10D5C000000000000000000000000000000000005B
-:10D5D000000000000000000000000000000000004B
-:10D5E000000000000000000000000000000000003B
-:10D5F000000000000000000000000000000000002B
-:10D60000000000000000000000000000000000001A
-:10D61000000000000000000000000000000000000A
-:10D6200000000000000000000000000000000000FA
-:10D6300000000000000000000000000000000000EA
-:10D6400000000000000000000000000000000000DA
-:10D6500000000000000000000000000000000000CA
-:10D6600000000000000000000000000000000000BA
-:10D6700000000000000000000000000000000000AA
-:10D68000000000000000000000000000000000009A
-:10D69000000000000000000000000000000000008A
-:10D6A000000000000000000000000000000000007A
-:10D6B000000000000000000000000000000000006A
-:10D6C000000000000000000000000000000000005A
-:10D6D000000000000000000000000000000000004A
-:10D6E000000000000000000000000000000000003A
-:10D6F000000000000000000000000000000000002A
-:10D700000000000000000000000000000000000019
-:10D710000000000000000000000000000000000009
-:10D7200000000000000000000000000000000000F9
-:10D7300000000000000000000000000000000000E9
-:10D7400000000000000000000000000000000000D9
-:10D7500000000000000000000000000000000000C9
-:10D7600000000000000000000000000000000000B9
-:10D7700000000000000000000000000000000000A9
-:10D780000000000000000000000000000000000099
-:10D790000000000000000000000000000000000089
-:10D7A0000000000000000000000000000000000079
-:10D7B0000000000000000000000000000000000069
-:10D7C0000000000000000000000000000000000059
-:10D7D0000000000000000000000000000000000049
-:10D7E0000000000000000000000000000000000039
-:10D7F0000000000000000000000000000000000029
-:10D800000000000000000000000000000000000018
-:10D810000000000000000000000000000000000008
-:10D8200000000000000000000000000000000000F8
-:10D8300000000000000000000000000000000000E8
-:10D8400000000000000000000000000000000000D8
-:10D8500000000000000000000000000000000000C8
-:10D8600000000000000000000000000000000000B8
-:10D8700000000000000000000000000000000000A8
-:10D880000000000000000000000000000000000098
-:10D890000000000000000000000000000000000088
-:10D8A0000000000000000000000000000000000078
-:10D8B0000000000000000000000000000000000068
-:10D8C0000000000000000000000000000000000058
-:10D8D0000000000000000000000000000000000048
-:10D8E0000000000000000000000000000000000038
-:10D8F0000000000000000000000000000000000028
-:10D900000000000000000000000000000000000017
-:10D910000000000000000000000000000000000007
-:10D9200000000000000000000000000000000000F7
-:10D9300000000000000000000000000000000000E7
-:10D9400000000000000000000000000000000000D7
-:10D9500000000000000000000000000000000000C7
-:10D9600000000000000000000000000000000000B7
-:10D9700000000000000000000000000000000000A7
-:10D980000000000000000000000000000000000097
-:10D990000000000000000000000000000000000087
-:10D9A0000000000000000000000000000000000077
-:10D9B0000000000000000000000000000000000067
-:10D9C0000000000000000000000000000000000057
-:10D9D0000000000000000000000000000000000047
-:10D9E0000000000000000000000000000000000037
-:10D9F0000000000000000000000000000000000027
-:10DA00000000000000000000000000000000000016
-:10DA10000000000000000000000000000000000006
-:10DA200000000000000000000000000000000000F6
-:10DA300000000000000000000000000000000000E6
-:10DA400000000000000000000000000000000000D6
-:10DA500000000000000000000000000000000000C6
-:10DA600000000000000000000000000000000000B6
-:10DA700000000000000000000000000000000000A6
-:10DA80000000000000000000000000000000000096
-:10DA90000000000000000000000000000000000086
-:10DAA0000000000000000000000000000000000076
-:10DAB0000000000000000000000000000000000066
-:10DAC0000000000000000000000000000000000056
-:10DAD0000000000000000000000000000000000046
-:10DAE0000000000000000000000000000000000036
-:10DAF0000000000000000000000000000000000026
-:10DB00000000000000000000000000000000000015
-:10DB10000000000000000000000000000000000005
-:10DB200000000000000000000000000000000000F5
-:10DB300000000000000000000000000000000000E5
-:10DB400000000000000000000000000000000000D5
-:10DB500000000000000000000000000000000000C5
-:10DB600000000000000000000000000000000000B5
-:10DB700000000000000000000000000000000000A5
-:10DB80000000000000000000000000000000000095
-:10DB90000000000000000000000000000000000085
-:10DBA0000000000000000000000000000000000075
-:10DBB0000000000000000000000000000000000065
-:10DBC0000000000000000000000000000000000055
-:10DBD0000000000000000000000000000000000045
-:10DBE0000000000000000000000000000000000035
-:10DBF0000000000000000000000000000000000025
-:10DC00000000000000000000000000000000000014
-:10DC10000000000000000000000000000000000004
-:10DC200000000000000000000000000000000000F4
-:10DC300000000000000000000000000000000000E4
-:10DC400000000000000000000000000000000000D4
-:10DC500000000000000000000000000000000000C4
-:10DC600000000000000000000000000000000000B4
-:10DC700000000000000000000000000000000000A4
-:10DC80000000000000000000000000000000000094
-:10DC90000000000000000000000000000000000084
-:10DCA0000000000000000000000000000000000074
-:10DCB0000000000000000000000000000000000064
-:10DCC0000000000000000000000000000000000054
-:10DCD0000000000000000000000000000000000044
-:10DCE0000000000000000000000000000000000034
-:10DCF0000000000000000000000000000000000024
-:10DD00000000000000000000000000000000000013
-:10DD10000000000000000000000000000000000003
-:10DD200000000000000000000000000000000000F3
-:10DD300000000000000000000000000000000000E3
-:10DD400000000000000000000000000000000000D3
-:10DD500000000000000000000000000000000000C3
-:10DD600000000000000000000000000000000000B3
-:10DD700000000000000000000000000000000000A3
-:10DD80000000000000000000000000000000000093
-:10DD90000000000000000000000000000000000083
-:10DDA0000000000000000000000000000000000073
-:10DDB0000000000000000000000000000000000063
-:10DDC0000000000000000000000000000000000053
-:10DDD0000000000000000000000000000000000043
-:10DDE0000000000000000000000000000000000033
-:10DDF0000000000000000000000000000000000023
-:10DE00000000000000000000000000000000000012
-:10DE10000000000000000000000000000000000002
-:10DE200000000000000000000000000000000000F2
-:10DE300000000000000000000000000000000000E2
-:10DE400000000000000000000000000000000000D2
-:10DE500000000000000000000000000000000000C2
-:10DE600000000000000000000000000000000000B2
-:10DE700000000000000000000000000000000000A2
-:10DE80000000000000000000000000000000000092
-:10DE90000000000000000000000000000000000082
-:10DEA0000000000000000000000000000000000072
-:10DEB0000000000000000000000000000000000062
-:10DEC0000000000000000000000000000000000052
-:10DED0000000000000000000000000000000000042
-:10DEE0000000000000000000000000000000000032
-:10DEF0000000000000000000000000000000000022
-:10DF00000000000000000000000000000000000011
-:10DF10000000000000000000000000000000000001
-:10DF200000000000000000000000000000000000F1
-:10DF300000000000000000000000000000000000E1
-:10DF400000000000000000000000000000000000D1
-:10DF500000000000000000000000000000000000C1
-:10DF600000000000000000000000000000000000B1
-:10DF700000000000000000000000000000000000A1
-:10DF80000000000000000000000000000000000091
-:10DF90000000000000000000000000000000000081
-:10DFA0000000000000000000000000000000000071
-:10DFB0000000000000000000000000000000000061
-:10DFC0000000000000000000000000000000000051
-:10DFD0000000000000000000000000000000000041
-:10DFE0000000000000000000000000000000000031
-:10DFF0000000000000000000000000000000000021
-:10E000000000000000000000000000000000000010
-:10E010000000000000000000000000000000000000
-:10E0200000000000000000000000000000000000F0
-:10E0300000000000000000000000000000000000E0
-:10E0400000000000000000000000000000000000D0
-:10E0500000000000000000000000000000000000C0
-:10E0600000000000000000000000000000000000B0
-:10E0700000000000000000000000000000000000A0
-:10E080000000000000000000000000000000000090
-:10E090000000000000000000000000000000000080
-:10E0A0000000000000000000000000000000000070
-:10E0B0000000000000000000000000000000000060
-:10E0C0000000000000000000000000000000000050
-:10E0D0000000000000000000000000000000000040
-:10E0E0000000000000000000000000000000000030
-:10E0F0000000000000000000000000000000000020
-:10E10000000000000000000000000000000000000F
-:10E1100000000000000000000000000000000000FF
-:10E1200000000000000000000000000000000000EF
-:10E1300000000000000000000000000000000000DF
-:10E1400000000000000000000000000000000000CF
-:10E1500000000000000000000000000000000000BF
-:10E1600000000000000000000000000000000000AF
-:10E17000000000000000000000000000000000009F
-:10E18000000000000000000000000000000000008F
-:10E19000000000000000000000000000000000007F
-:10E1A000000000000000000000000000000000006F
-:10E1B000000000000000000000000000000000005F
-:10E1C000000000000000000000000000000000004F
-:10E1D000000000000000000000000000000000003F
-:10E1E000000000000000000000000000000000002F
-:10E1F000000000000000000000000000000000809F
-:10E20000000000000000000000000000000000000E
-:10E2100000000000000000000000000000000000FE
-:10E220000000000A000000000000000000000000E4
-:10E2300010000003000000000000000D0000000DB1
-:10E240003C020801244296603C0308012463989C28
-:10E25000AC4000000043202B1480FFFD244200044A
-:10E260003C1D080037BD9FFC03A0F0213C100800B6
-:10E27000261032103C1C0801279C96600E0012BE2E
-:10E28000000000000000000D3C02800030A5FFFFF0
-:10E2900030C600FF344301803C0880008D0901B87E
-:10E2A0000520FFFE00000000AC6400002404000212
-:10E2B000A4650008A066000AA064000BAC67001803
-:10E2C0003C03100003E00008AD0301B83C0560000A
-:10E2D0008CA24FF80440FFFE00000000ACA44FC029
-:10E2E0003C0310003C040200ACA44FC403E000084F
-:10E2F000ACA34FF89486000C00A050212488001491
-:10E3000000062B0200051080004448210109182B4B
-:10E310001060001100000000910300002C6400094F
-:10E320005080000991190001000360803C0D080134
-:10E3300025AD92F8018D58218D67000000E000089E
-:10E340000000000091190001011940210109302B42
-:10E3500054C0FFF29103000003E000080000102108
-:10E360000A000CCC25080001910F0001240E000AC0
-:10E3700015EE00400128C8232F38000A1700003D81
-:10E38000250D00028D580000250F0006370E0100F4
-:10E39000AD4E0000910C000291AB000191A400026F
-:10E3A00091A60003000C2E00000B3C0000A71025D6
-:10E3B00000041A000043C8250326C025AD580004F8
-:10E3C000910E000691ED000191E7000291E5000336
-:10E3D000000E5E00000D6400016C30250007220075
-:10E3E00000C41025004518252508000A0A000CCC99
-:10E3F000AD430008910F000125040002240800022B
-:10E4000055E80001012020210A000CCC00804021A9
-:10E41000910C0001240B0003158B00160000000076
-:10E420008D580000910E000225080003370D0008EA
-:10E43000A14E00100A000CCCAD4D00009119000156
-:10E44000240F0004172F000B0000000091070002AA
-:10E45000910400038D43000000072A0000A410254A
-:10E460003466000425080004AD42000C0A000CCC00
-:10E47000AD46000003E000082402000127BDFFE8CC
-:10E48000AFBF0014AFB000100E00167F00808021D7
-:10E490003C0480083485008090A600052403FFFE1C
-:10E4A0000200202100C310248FBF00148FB0001081
-:10E4B000A0A200050A00168927BD001827BDFFE8A5
-:10E4C000AFB00010AFBF00140E000FD40080802149
-:10E4D0003C06800834C5008090A40000240200504F
-:10E4E000308300FF106200073C09800002002021F9
-:10E4F0008FBF00148FB00010AD2001800A00108F74
-:10E5000027BD0018240801003C07800002002021DC
-:10E510008FBF00148FB00010ACE801800A00108F8C
-:10E5200027BD001827BDFF783C058008AFBE0080DE
-:10E53000AFB7007CAFB3006CAFB10064AFBF008475
-:10E54000AFB60078AFB50074AFB40070AFB200687A
-:10E55000AFB0006034A600803C0580008CB201287A
-:10E5600090C400098CA701043C020001309100FF17
-:10E5700000E218240000B8210000F021106000071C
-:10E58000000098213C0908008D2931F02413000176
-:10E59000252800013C010800AC2831F0ACA0008423
-:10E5A00090CC0005000C5827316A0001154000721C
-:10E5B000AFA0005090CD00002406002031A400FF41
-:10E5C00010860018240E0050108E009300000000EA
-:10E5D0003C1008008E1000DC260F00013C010800F2
-:10E5E000AC2F00DC0E0016F80000000000401821DF
-:10E5F0008FBF00848FBE00808FB7007C8FB60078FD
-:10E600008FB500748FB400708FB3006C8FB2006848
-:10E610008FB100648FB000600060102103E000083B
-:10E6200027BD00880000000D3C1F8000AFA0003017
-:10E6300097E501168FE201043C04002030B9FFFF8A
-:10E64000004438240007182B00033140AFA60030E7
-:10E650008FF5010437F80C003C1600400338802188
-:10E6600002B6A02434C40040128000479215000D69
-:10E6700032A800201500000234860080008030217E
-:10E6800014C0009FAFA600303C0D800835A6008066
-:10E6900090CC0008318B0040516000063C06800899
-:10E6A000240E0004122E00A8240F0012122F003294
-:10E6B0003C06800834C401003C0280009447011AE3
-:10E6C0009619000E909F00088E18000830E3FFFF97
-:10E6D00003F9B00432B40004AFB6005CAFA3005835
-:10E6E0008E1600041280002EAFB8005434C3008090
-:10E6F000906800083105004014A0002500000000CB
-:10E700008C70005002D090230640000500000000ED
-:10E710008C71003402D1A82306A201678EE20008A2
-:10E72000126000063C1280003C1508008EB531F4E2
-:10E7300026B600013C010800AC3631F4AE4000447E
-:10E74000240300018FBF00848FBE00808FB7007C40
-:10E750008FB600788FB500748FB400708FB3006CE3
-:10E760008FB200688FB100648FB00060006010212C
-:10E7700003E0000827BD00880E000D2800002021BE
-:10E780000A000D75004018210A000D9500C02021D7
-:10E790000E00174802C020211440FFE100000000D5
-:10E7A0003C0B8008356400808C8A003402CA482300
-:10E7B0000520001D000000003C1E08008FDE310017
-:10E7C00027D700013C010800AC3731001260000679
-:10E7D000024020213C1408008E9431F42690000160
-:10E7E0003C010800AC3031F40E00167F3C1E80085E
-:10E7F00037CD008091B700250240202136EE00047D
-:10E800000E001689A1AE00250E000CAC024020219E
-:10E810000A000DCA240300013C17080126F797607F
-:10E820000A000D843C1F80008C86003002C66023E5
-:10E830001980000C2419000C908F004F3C14080024
-:10E840008E94310032B500FC35ED0001268E0001BA
-:10E850003C010800AC2E3100A08D004FAFA0005845
-:10E860002419000CAFB900308C9800300316A02397
-:10E870001A80010B8FA300580074F82A17E0FFD309
-:10E88000000000001074002A8FA5005802D4B021A7
-:10E8900000B410233044FFFFAFA4005832A8000298
-:10E8A0001100002E32AB00103C15800836B00080FD
-:10E8B0009216000832D30040526000FB8EE200083E
-:10E8C0000E00167F02402021240A0018A20A000927
-:10E8D000921100052409FFFE024020210229902404
-:10E8E0000E001689A2120005240400390000282118
-:10E8F0000E001723240600180A000DCA2403000185
-:10E9000092FE000C3C0A800835490080001EBB00C6
-:10E910008D27003836F10081024020213225F08118
-:10E920000E000C9B30C600FF0A000DC10000000065
-:10E930003AA7000130E300011460FFA402D4B02123
-:10E940000A000E1D00000000024020210E00176585
-:10E95000020028210A000D75004018211160FF7087
-:10E960003C0F80083C0D800835EE00808DC40038D7
-:10E970008FA300548DA60004006660231D80FF68ED
-:10E98000000000000064C02307020001AFA400548F
-:10E990003C1F08008FFF31E433F9000113200015FC
-:10E9A0008FAC00583C07800094E3011A10600012FD
-:10E9B0003C0680080E002192024020213C03080101
-:10E9C00090639791306400021480014500000000BC
-:10E9D000306C0004118000078FAC0058306600FBDB
-:10E9E0003C010801A026979132B500FCAFA0005869
-:10E9F0008FAC00583C06800834D30080AFB40018B8
-:10EA0000AFB60010AFAC00143C088000950B01209D
-:10EA10008E6F0030966A005C8FA3005C8FBF003061
-:10EA20003169FFFF3144FFFF8FAE005401341021E4
-:10EA3000350540000064382B0045C82103E7C02598
-:10EA4000AFB90020AFAF0028AFB80030AFAF00249F
-:10EA5000AFA0002CAFAE0034926D000831B40008B6
-:10EA6000168000BB020020218EE200040040F8095D
-:10EA700027A400108FAF003031F300025660000170
-:10EA800032B500FE3C048008349F008093F90008F2
-:10EA900033380040530000138FA400248C850004F9
-:10EAA0008FA7005410A700D52404001432B0000131
-:10EAB0001200000C8FA400242414000C1234011A3C
-:10EAC0002A2D000D11A001022413000E240E000AAD
-:10EAD000522E0001241E00088FAF002425E40001FF
-:10EAE000AFA400248FAA00143C0B80083565008079
-:10EAF000008A48218CB10030ACA9003090A4004EAF
-:10EB00008CA700303408FFFC0088180400E3F821CB
-:10EB1000ACBF00348FA600308FB900548FB8005CB2
-:10EB200030C200081040000B033898218CAC002044
-:10EB3000119300D330C600FF92EE000C8FA7003473
-:10EB400002402021000E6B0035B400800E000C9BAB
-:10EB50003285F0803C028008345000808E0F0030F7
-:10EB600001F1302318C00097264800803C070800B8
-:10EB70008CE731E42404FF80010418243118007F5D
-:10EB80003C1F80003C19800430F10001AFE300908D
-:10EB900012200006031928213C0308019063979175
-:10EBA00030690008152000C6306A00F73C10800864
-:10EBB00036040080908C004F318B000115600042BC
-:10EBC000000000003C0608008CC6319830CE0010D2
-:10EBD00051C0004230F9000190AF006B55E0003F9A
-:10EBE00030F9000124180001A0B8006B3C1180002E
-:10EBF0009622007A24470064A48700123C0D800806
-:10EC000035A5008090B40008329000401600000442
-:10EC10003C03800832AE000115C0008B00000000EC
-:10EC2000346400808C86002010D3000A3463010015
-:10EC30008C67000002C7782319E000978FBF00544B
-:10EC4000AC93002024130001AC760000AFB3005059
-:10EC5000AC7F000417C0004E000000008FA90050D8
-:10EC60001520000B000000003C0308019063979101
-:10EC7000306A00011140002E8FAB0058306400FE56
-:10EC80003C010801A02497910A000D75000018218D
-:10EC90000E000CAC024020210A000F1300000000FF
-:10ECA0000A000E200000A0210040F80924040017EB
-:10ECB0000A000DCA240300010040F80924040016CC
-:10ECC0000A000DCA240300019094004F240DFFFE9A
-:10ECD000028D2824A085004F30F900011320000682
-:10ECE0003C0480083C03080190639791307F00103A
-:10ECF00017E00051306800EF34900080240A0001D2
-:10ED0000024020210E00167FA60A00129203002561
-:10ED100024090001AFA90050346200010240202103
-:10ED20000E001689A20200250A000EF93C0D80088B
-:10ED30001160FE83000018218FA5003030AC000464
-:10ED40001180FE2C8FBF00840A000DCB240300012C
-:10ED500027A500380E000CB6AFA000385440FF4382
-:10ED60008EE200048FB40038329001005200FF3F61
-:10ED70008EE200048FA3003C8E6E0058006E682364
-:10ED800005A3FF39AE6300580A000E948EE200041A
-:10ED90000E00167F024020213C038008346800806A
-:10EDA000024020210E001689A11E000903C0302157
-:10EDB000240400370E001723000028210A000F1139
-:10EDC0008FA900508FAB00185960FF8D3C0D800853
-:10EDD0000E00167F02402021920C00252405000120
-:10EDE000AFA5005035820004024020210E00168994
-:10EDF000A20200250A000EF93C0D800812240059D9
-:10EE00002A2300151060004D240900162408000C68
-:10EE10005628FF2732B000013C0A8008914C001BA5
-:10EE20002406FFBD241E000E01865824A14B001BA2
-:10EE30000A000EA532B000013C010801A0289791FC
-:10EE40000A000EF93C0D80088CB500308EFE0008DB
-:10EE50002404001826B6000103C0F809ACB600303F
-:10EE60003C030801906397913077000116E0FF8121
-:10EE7000306A00018FB200300A000D753243000481
-:10EE80003C1080009605011A50A0FF2B34C60010DC
-:10EE90000A000EC892EE000C8C6200001456FF6D42
-:10EEA000000000008C7800048FB9005403388823D8
-:10EEB0000621FF638FBF00540A000F0E0000000000
-:10EEC0003C010801A02A97910A000F3030F9000197
-:10EED0001633FF028FAF00240A000EB0241E00106C
-:10EEE0000E00167F024020213C0B80083568008010
-:10EEF00091090025240A0001AFAA0050353300040F
-:10EF0000024020210E001689A11300253C050801AE
-:10EF100090A5979130A200FD3C010801A022979195
-:10EF20000A000E6D004018212411000E53D1FEEA94
-:10EF3000241E00100A000EAF241E00165629FEDC07
-:10EF400032B000013C0A8008914C001B2406FFBD32
-:10EF5000241E001001865824A14B001B0A000EA598
-:10EF600032B000010A000EA4241E00123C038000EF
-:10EF70008C6201B80440FFFE24040800AC6401B8B0
-:10EF800003E000080000000030A5FFFF30C6FFFFCF
-:10EF90003C0780008CE201B80440FFFE34EA0180A7
-:10EFA000AD440000ACE400203C0480089483004899
-:10EFB0003068FFFF11000016AF88000824AB001274
-:10EFC000010B482B512000133C04800034EF01005A
-:10EFD00095EE00208F890000240D001A31CCFFFF30
-:10EFE00031274000A14D000B10E000362583FFFEC5
-:10EFF0000103C02B170000348F9900048F88000490
-:10F00000A5430014350700010A001003AF87000470
-:10F010003C04800024030003348201808F890000B7
-:10F020008F870004A043000B3C088000350C018052
-:10F03000A585000EA585001A8F85000C30EB800099
-:10F04000A5890010AD850028A58600081160000F75
-:10F050008F85001435190100972A00163158FFFCDE
-:10F06000270F000401E870218DCD400031A6FFFF7D
-:10F0700014C000072403BFFF3C02FFFF34487FFF9A
-:10F0800000E83824AF8700048F8500142403BFFFF5
-:10F090003C04800000E3582434830180A46B0026E4
-:10F0A000AC69002C10A0000300054C02A465001000
-:10F0B000A46900263C071000AC8701B803E00008F3
-:10F0C000000000008F990004240AFFFE032A382460
-:10F0D0000A001003AF87000427BDFFE88FA20028B5
-:10F0E00030A5FFFF30C6FFFFAFBF0010AF87000C99
-:10F0F000AF820014AF8000040E000FDBAF80000071
-:10F100008FBF001027BD001803E00008AF80001477
-:10F110003C06800034C4007034C701008C8A0000B3
-:10F1200090E500128F84000027BDFFF030A300FFA0
-:10F13000000318823082400010400037246500032D
-:10F140000005C8800326C0218F0E4000246F0004F4
-:10F15000000F6880AFAE000001A660218D8B4000DB
-:10F16000AFAB000494E900163128FFFC01063821FA
-:10F170008CE64000AFA600088FA9000800003021EF
-:10F18000000028213C07080024E701000A0010675E
-:10F19000240800089059000024A500012CAC000CA4
-:10F1A0000079C0210018788001E770218DCD000022
-:10F1B0001180000600CD302603A5102114A8FFF50C
-:10F1C00000051A005520FFF4905900003C0480000F
-:10F1D000348700703C0508008CA531048CE30000E6
-:10F1E0002CA2002010400009006A38230005488046
-:10F1F0003C0B0800256B3108012B402124AA00019B
-:10F20000AD0700003C010800AC2A310400C0102109
-:10F2100003E0000827BD0010308220001040000BE2
-:10F2200000055880016648218D24400024680004B0
-:10F2300000083880AFA4000000E618218C6540006B
-:10F24000AFA000080A001057AFA500040000000D91
-:10F250000A0010588FA9000827BDFFE03C07800076
-:10F2600034E60100AFBF001CAFB20018AFB100140C
-:10F27000AFB0001094C5000E8F87000030A4FFFFD0
-:10F280002483000430E2400010400010AF83002CC3
-:10F290003C09002000E940241100000D30EC800002
-:10F2A0008F8A0004240BBFFF00EB38243543100085
-:10F2B000AF87000030F220001640000B3C1900041C
-:10F2C000241FFFBF0A0010B7007F102430EC80001D
-:10F2D000158000423C0E002030F220001240FFF862
-:10F2E0008F8300043C19000400F9C0241300FFF5CB
-:10F2F000241FFFBF34620040AF82000430E20100EF
-:10F300001040001130F010008F83003010600006B4
-:10F310003C0F80003C05002000E52024148000C044
-:10F320003C0800043C0F800035EE010095CD001E26
-:10F3300095CC001C31AAFFFF000C5C00014B482556
-:10F34000AF89000C30F010001200000824110001F9
-:10F3500030F100201620008B3C18100000F890249B
-:10F36000164000823C040C002411000130E801002A
-:10F370001500000B3C0900018F85000430A94000F6
-:10F38000152000073C0900013C0C1F0100EC58242B
-:10F390003C0A1000116A01183C1080003C09000171
-:10F3A00000E9302410C000173C0B10003C18080086
-:10F3B0008F1800243307000214E0014024030001E9
-:10F3C0008FBF001C8FB200188FB100148FB00010D7
-:10F3D0000060102103E0000827BD002000EE682433
-:10F3E00011A0FFBE30F220008F8F00043C11FFFF00
-:10F3F00036307FFF00F0382435E380000A0010A685
-:10F40000AF87000000EB102450400065AF8000285B
-:10F410008F8C00303C0D0F0000ED18241580008803
-:10F42000AF83001030E8010011000086938F0010B8
-:10F430003C0A0200106A00833C1280003650010032
-:10F44000920500139789002E3626000230AF00FF88
-:10F4500025EE0004000E19C03C0480008C9801B811
-:10F460000700FFFE34880180AD0300003C198008CE
-:10F47000AC830020973100483225FFFF10A0015CCB
-:10F48000AF8500082523001200A3F82B53E0015993
-:10F490008F850004348D010095AC00202402001AF1
-:10F4A00030E44000318BFFFFA102000B108001927D
-:10F4B0002563FFFE00A3502B154001908F8F0004A1
-:10F4C000A50300148F88000435050001AF850004F2
-:10F4D0003C08800035190180A729000EA729001AD1
-:10F4E0008F89000C30B18000A7270010AF290028B9
-:10F4F000A72600081220000E3C04800035020100FF
-:10F50000944C0016318BFFFC256400040088182100
-:10F510008C7F400033E6FFFF14C000053C048000F0
-:10F520003C0AFFFF354D7FFF00AD2824AF85000466
-:10F53000240EBFFF00AE402434850180A4A800261D
-:10F54000ACA7002C3C071000AC8701B800001821C4
-:10F550008FBF001C8FB200188FB100148FB0001045
-:10F560000060102103E0000827BD00203C020BFFD3
-:10F5700000E41824345FFFFF03E3C82B5320FF7B14
-:10F58000241100013C0608008CC6002C24C5000193
-:10F590003C010800AC25002C0A0010D42411000501
-:10F5A0008F85002810A0002FAF80001090A30000CE
-:10F5B000146000792419000310A0002A30E601002D
-:10F5C00010C000CC8F860010241F000210DF00C97D
-:10F5D0008F8B000C3C0708008CE7003824E4FFFF09
-:10F5E00014E0000201641824000018213C0D0800FA
-:10F5F00025AD0038006D1021904C00048F85002C43
-:10F6000025830004000321C030A5FFFF3626000239
-:10F610000E000FDB000000000A00114D0000182151
-:10F6200000E8302414C0FF403C0F80000E00103D65
-:10F63000000000008F8700000A0010CAAF82000C93
-:10F64000938F00103C180801271896E0000F90C017
-:10F6500002588021AF9000288F85002814A0FFD386
-:10F66000AF8F00103C0480008C86400030C5010044
-:10F6700010A000BC322300043C0C08008D8C002438
-:10F6800024120004106000C23190000D3C04800080
-:10F690008C8D40003402FFFF11A201003231FFFBCC
-:10F6A0008C884000310A01005540000124110010EF
-:10F6B00030EE080011C000BE2419FFFB8F98002C0B
-:10F6C0002F0F03EF51E000010219802430E90100FF
-:10F6D00011200014320800018F87003014E000FB75
-:10F6E0008F8C000C3C05800034AB0100917F00132F
-:10F6F00033E300FF246A00042403FFFE0203802496
-:10F70000000A21C012000002023230253226FFFF1B
-:10F710000E000FDB9785002E1200FF290000182134
-:10F72000320800011100000D32180004240E0001FF
-:10F73000120E0002023230253226FFFF9785002E7E
-:10F740000E000FDB00002021240FFFFE020F80249B
-:10F750001200FF1B00001821321800045300FF188C
-:10F760002403000102323025241200045612000145
-:10F770003226FFFF9785002E0E000FDB24040100C8
-:10F780002419FFFB021988241220FF0D0000182104
-:10F790000A0010E9240300011079009C00003021C8
-:10F7A00090AD00012402000211A200BE30EA004028
-:10F7B00090B90001241800011338007F30E900409F
-:10F7C0008CA600049785002E00C020210E000FDBC0
-:10F7D0003626000200004021010018218FBF001CC6
-:10F7E0008FB200188FB100148FB00010006010218C
-:10F7F00003E0000827BD0020360F010095EE000C45
-:10F8000031CD020015A0FEE63C0900013C1880083D
-:10F81000971200489789002E362600023248FFFFD3
-:10F82000AF8800083C0380008C7101B80620FFFE01
-:10F83000346A0180AD4000001100008E3C0F800052
-:10F84000253F0012011FC82B1320008B240E00033C
-:10F85000346C0100958B00202402001A30E4400033
-:10F860003163FFFFA142000B108000A72463FFFE5D
-:10F870000103682B15A000A52408FFFE34A5000194
-:10F88000A5430014AF8500043C0480002412BFFF90
-:10F8900000B2802434850180A4A9000EA4A9001A16
-:10F8A000A4A60008A4B00026A4A700103C071000DE
-:10F8B000AC8701B80A00114D000018213C038000FC
-:10F8C00034640100949F000E3C1908008F3900D861
-:10F8D0002404008033E5FFFF273100013C010800CC
-:10F8E000AC3100D80E000FDB240600030A00114DD6
-:10F8F00000001821240A000210CA00598F85002C2C
-:10F900003C0308008C6300D0240E0001106E005EE2
-:10F910002CCF000C24D2FFFC2E5000041600002136
-:10F9200000002021241800021078001B2CD9000CA4
-:10F9300024DFFFF82FE900041520FF330000202109
-:10F9400030EB020051600004000621C054C00022C8
-:10F9500030A5FFFF000621C030A5FFFF0A00117D82
-:10F96000362600023C0908008D29002431300001B0
-:10F970005200FEF7000018219785002E362600025F
-:10F980000E000FDB000020210A00114D000018219D
-:10F990000A00119C241200021320FFE624DFFFF866
-:10F9A0000000202130A5FFFF0A00117D362600024D
-:10F9B0000A0011AC021980245120FF828CA6000499
-:10F9C0003C05080190A596E110A0FF7E24080001E7
-:10F9D0000A0011F0010018210E000FDB3226000191
-:10F9E0008F8600108F85002C0A00124F000621C060
-:10F9F0008F8500043C18800024120003371001801A
-:10FA0000A212000B0A00112E3C08800090A30001F6
-:10FA1000241100011071FF70240800012409000264
-:10FA20005069000430E60040240800010A0011F08B
-:10FA30000100182150C0FFFD240800013C0C80008B
-:10FA4000358B01009563001094A40002307FFFFF06
-:10FA5000509FFF62010018210A001284240800014F
-:10FA60002CA803EF1100FE56240300010A001239EE
-:10FA700000000000240E000335EA0180A14E000BB7
-:10FA80000A00121C3C04800011E0FFA2000621C005
-:10FA900030A5FFFF0A00117D362600020A0011A5DD
-:10FAA000241100201140FFC63C1280003650010096
-:10FAB000960F001094AE000231E80FFF15C8FFC08A
-:10FAC000000000000A0011E690B900013C060800A1
-:10FAD0008CC6003824C4FFFF14C00002018418241F
-:10FAE000000018213C0D080025AD0038006D1021E4
-:10FAF0000A0011B6904300048F8F0004240EFFFE0D
-:10FB00000A00112C01EE28242408FFFE0A00121A14
-:10FB100000A8282427BDFFC8AFB00010AFBF003435
-:10FB20003C10600CAFBE0030AFB7002CAFB6002861
-:10FB3000AFB50024AFB40020AFB3001CAFB20018C3
-:10FB4000AFB100148E0E5000240FFF7F3C068000E2
-:10FB500001CF682435AC380C240B0003AE0C5000E8
-:10FB6000ACCB00083C010800AC2000200E00184A75
-:10FB7000000000003C0A0010354980513C06601628
-:10FB8000AE09537C8CC700003C0860148D0500A0B2
-:10FB90003C03FFFF00E320243C02535300051FC237
-:10FBA0001482000634C57C000003A08002869821E0
-:10FBB0008E7200043C116000025128218CBF007C31
-:10FBC0008CA200783C1E600037C420203C05080150
-:10FBD00024A59328AF820018AF9F001C0E00170EBB
-:10FBE0002406000A3C190001273996E03C01080070
-:10FBF000AC3931DC0E002105AF8000148FD7080826
-:10FC00002418FFF03C15570902F8B02412D503243C
-:10FC100024040001AF8000303C148000369701803E
-:10FC20003C1E080127DE96E0369301008E9000000E
-:10FC30003205000310A0FFFD3207000110E000882C
-:10FC4000320600028E7100283C048000AE91002034
-:10FC50008E6500048E66000000A0382100C040219F
-:10FC60008C8301B80460FFFE3C0B0010240A0800DE
-:10FC700000AB4824AC8A01B8552000E2240ABFFF3B
-:10FC80009675000E3C1208008E52002030AC4000E9
-:10FC900032AFFFFF264E000125ED00043C010800B5
-:10FCA000AC2E0020118000EAAF8D002C3C18002003
-:10FCB00000B8B02412C000E730B980002408BFFFAC
-:10FCC00000A8382434C81000AF87000030E62000B8
-:10FCD00010C000EB2409FFBF3C03000400E328240C
-:10FCE00010A00002010910243502004030EA010092
-:10FCF00011400010AF8200048F8B003011600007AC
-:10FD00003C0D002000ED6024118000043C0F000435
-:10FD100000EF702411C00239000000009668001E38
-:10FD20009678001C3115FFFF0018B40002B690252C
-:10FD3000AF92000C30F910001320001324150001BD
-:10FD400030FF002017E0000A3C04100000E41024FB
-:10FD50001040000D3C0A0C003C090BFF00EA18247F
-:10FD60003525FFFF00A3302B10C0000830ED010047
-:10FD70003C0C08008D8C002C24150005258B0001FF
-:10FD80003C010800AC2B002C30ED010015A0000B4D
-:10FD90003C0500018F85000430AE400055C00007CF
-:10FDA0003C0500013C161F0100F690243C0F10009A
-:10FDB000124F01CE000000003C05000100E5302498
-:10FDC00010C000B13C0C10003C1F08008FFF002445
-:10FDD00033E90002152000732403000100601021A4
-:10FDE000104000083C0680003C188000370F0100DE
-:10FDF0008DEE00243C056020ACAE00140000000035
-:10FE00003C0680003C084000ACC8013800000000FF
-:10FE10005220001332060002262A0140262B0080C1
-:10FE2000240DFF80014D2024016D6024000C194039
-:10FE30003162007F0004A9403152007F3C1620004F
-:10FE400036C900020062F82502B2382500E988258B
-:10FE500003E9C825ACD90830ACD10830320600021D
-:10FE600010C0FF723C0F800035E501408CB80000E7
-:10FE700024100040ADF8002090AE000831C300709F
-:10FE8000107000D628680041510000082405006069
-:10FE9000241100201071000E3C0B40003C06800035
-:10FEA000ACCB01780A001304000000001465FFFBCE
-:10FEB0003C0B40000E002022000000003C0B4000E4
-:10FEC0003C068000ACCB01780A001304000000005F
-:10FED00090BF0009241900048CA7000033E900FF3B
-:10FEE000113901B22523FFFA2C72000612400016C8
-:10FEF0003C0680008CAB00048F86002494A2000A8C
-:10FF0000000B5602312500FF10C000053044FFFFF2
-:10FF10002D4C000815800002254A0004240A000325
-:10FF20002410000910B001F828AE000A11C001DC4D
-:10FF3000240F000A2404000810A40028000A41C06D
-:10FF4000010038213C0680008CC801B80500FFFE86
-:10FF500034D00180AE07000034C401409085000811
-:10FF6000240A00023C0B400030B900FF00198A004F
-:10FF70000229C025A6180008A20A000B948F000AC7
-:10FF80003C091000A60F00108C8E0004AE0E002459
-:10FF9000ACC901B83C068000ACCB01780A00130460
-:10FFA000000000003C0A8000354401009483000EEC
-:10FFB0003C0208008C4200D8240400803065FFFF1A
-:10FFC000245500013C010800AC3500D80E000FDBC1
-:10FFD000240600030A00137000001821000BC2025F
-:10FFE000330300FF240A0001146AFFD60100382100
-:10FFF0008F910020AF830024262B00010A0013CA32
-:020000040001F9
-:10000000AF8B002000CA2024AF85000010800008BC
-:10001000AF860004240C87FF00CC5824156000082C
-:100020003C0D006000AD302410C000050000000051
-:100030000E000D42000000000A00137100000000D5
-:100040000E001636000000000A00137100000000C8
-:1000500030B980005320FF1DAF8500003C02002016
-:1000600000A2F82453E0FF19AF8500003C07FFFF12
-:1000700034E47FFF00A438240A00132B34C8800026
-:100080000A0013340109102400EC58245160005A6E
-:10009000AF8000288F8D00303C0E0F0000EE18243A
-:1000A00015A00075AF83001030EF010011E0007360
-:1000B000939800103C120200107200703C06800001
-:1000C00034D90100932800139789002E36A6000228
-:1000D000311800FF27160004001619C03C048000E8
-:1000E0008C8501B804A0FFFE34880180AD030000B8
-:1000F0003C158008AC83002096BF004833E5FFFF25
-:1001000010A001EBAF8500082523001200A3102BDF
-:10011000504001E88F850004348D010095AC00202B
-:10012000240B001A30E44000318AFFFFA10B000BC2
-:10013000108001E92543FFFE00A3702B15C001E7E5
-:100140008F9600048F8F0004A503001435E500018D
-:10015000AF8500043C08800035150180A6A9000E7B
-:10016000A6A9001A8F89000C30BF8000A6A7001036
-:10017000AEA90028A6A6000813E0000F3C0F8000DF
-:10018000350C0100958B0016316AFFFC25440004F4
-:10019000008818218C6240003046FFFF14C0000721
-:1001A0002416BFFF3C0EFFFF35CD7FFF00AD282496
-:1001B000AF8500043C0F80002416BFFF00B69024DA
-:1001C00035E50180A4B20026ACA7002C3C07100046
-:1001D000ADE701B80A001370000018210E00168E5A
-:1001E000000000003C0B40003C068000ACCB0178D6
-:1001F0000A001304000000008F85002810A00025CD
-:10020000AF80001090A3000010600072241F000354
-:10021000107F00FF0000302190AD0001240C00028F
-:1002200011AC015930EE004090BF000124190001CB
-:1002300013F9000930E900408CA600049785002ED0
-:1002400000C020210E000FDB36A600020000402176
-:100250000A001370010018215120FFF88CA6000439
-:100260003C07080190E796E110E0FFF42408000144
-:100270000A00137001001821939800100018C8C0DC
-:10028000033E4021AF8800288F85002814A0FFDDA1
-:10029000AF9800103C0480008C86400030C50100FF
-:1002A00010A0008732AA00043C0B08008D6B0024CC
-:1002B00024160004154000033172000D24160002BC
-:1002C0003C0480008C8D4000340CFFFF11AC012CED
-:1002D00032B5FFFB8C8F400031EE010055C00001AC
-:1002E0002415001030F8080013000038241FFFFB0D
-:1002F0008F99002C2F2803EF51000001025F9024FA
-:1003000030E9010011200014325900018F870030BC
-:1003100014E001278F8B000C3C0480003486010020
-:1003200090C5001330A300FF24620004000221C026
-:100330002408FFFE024890241240000202B6302535
-:1003400032A6FFFF0E000FDB9785002E1240FEA3A2
-:1003500000001821325900011320000D324700041B
-:10036000241F0001125F000202B6302532A6FFFFF3
-:100370009785002E0E000FDB000020212409FFFED0
-:10038000024990241240FE950000182132470004D3
-:1003900050E0FE922403000102B63025241600042A
-:1003A0005656000132A6FFFF9785002E0E000FDB88
-:1003B000240401002402FFFB0242A82412A0FE87AD
-:1003C000000018210A001370240300010A0014B968
-:1003D000025F902410A0FFAF30E5010010A00017CD
-:1003E0008F8600102402000210C200148F84000CBB
-:1003F0003C0608008CC6003824C3FFFF14C000026E
-:1004000000831024000010213C0D080025AD0038A9
-:10041000004D6021918B00048F85002C256A00041B
-:10042000000A21C030A5FFFF36A600020E000FDB38
-:10043000000000000A00137000001821240E0002C2
-:1004400010CE0088241200013C0308008C6300D009
-:100450001072008D8F85002C24C8FFFC2D1800041D
-:100460001700006300002021241900021079005DAC
-:100470002CDF000C24C2FFF82C4900041520FFE9F2
-:100480000000202130E3020050600004000621C07B
-:1004900054C0000530A5FFFF000621C030A5FFFFB6
-:1004A0000A00150436A600020E000FDB32A600017A
-:1004B0008F8600108F85002C0A001520000621C0B1
-:1004C0003C0308008C630024307200015240FE435C
-:1004D000000018219785002E36A600020E000FDBC3
-:1004E000000020210A001370000018219668000CFB
-:1004F000311802005700FE313C0500013C1F800806
-:1005000097F900489789002E36A600023328FFFF8E
-:10051000AF8800083C0380008C7501B806A0FFFE80
-:100520003C04800034820180AC400000110000E7F0
-:1005300024180003252A0012010A182B106000E37A
-:1005400000000000966F00203C0E8000240D001A71
-:1005500031ECFFFF35CA018030EB4000A14D000BAC
-:10056000116000E12583FFFE0103902B164000DFA0
-:100570002416FFFE34A50001A5430014AF85000436
-:100580002419BFFF00B94024A6E9000EA6E9001A0D
-:10059000A6E60008A6E80026A6E700103C07100023
-:1005A000AE8701B80A001370000018213C048000D7
-:1005B0008C8901B80520FFFE349601802415001CAB
-:1005C000AEC70000A2D5000B3C071000AC8701B8F5
-:1005D0003C0B40003C068000ACCB01780A001304C1
-:1005E0000000000013E0FFA424C2FFF80000202157
-:1005F00030A5FFFF0A00150436A600020E00103DCC
-:10060000000000008F8700000A001346AF82000C34
-:1006100090A30001241500011075FF0D24080001AE
-:10062000240900021069000430E60040240800019B
-:100630000A0013700100182150C0FFFD24080001BA
-:100640003C0B8000356A01009543001094A4000221
-:100650003062FFFF5082FDE1010018210A0015857C
-:10066000240800018F85002C2CAF03EF11E0FDDB87
-:10067000240300013C0308008C6300D02412000115
-:100680001472FF7624C8FFFC2CD6000C12C0FF7237
-:10069000000621C030A5FFFF0A00150436A600029F
-:1006A00010AF005700043A022406000B14A6FE24E3
-:1006B000000A41C0316600FF0006FE00001F5E0315
-:1006C0000562007230C6007F000668C001BE382196
-:1006D000A0E00001A0E000003C1660008ED21820CF
-:1006E000240C000100CC100400021827000A41C0AD
-:1006F0000243A824A4E0000201003821AED518204E
-:100700000A0013CB3C06800014C000368F8D0020F9
-:10071000000A41C03C1F80003C058008AFE8002073
-:1007200094B9004013200002240500012405004173
-:100730003C0480008C8701B804E0FFFE3495018002
-:1007400024020003AEA80000A2A2000BA6A0000E87
-:10075000A6A0001AA6A00010AEA00028A6A500081A
-:1007600096A3002634720001A6B20026AEA0002C8B
-:100770003C161000AC9601B80A0013CA01003821DB
-:100780000A0014B22415002011C0FEB53C088000F8
-:10079000351801009716001094B2000232CF0FFFF7
-:1007A000164FFEAF000000000A00148490BF000145
-:1007B0003C0A08008D4A0038254CFFFF1540000216
-:1007C000016C1024000010213C1808002718003884
-:1007D0000058782191EE000425CD00040A0014C5CC
-:1007E000000D21C0000A41C025ACFFFF1580FDD4DB
-:1007F000AF8C0020010038210A0013CAAF8000240A
-:10080000240300FF10E3FDCE000A41C010C0001712
-:1008100000078600000720C0009E18212402000166
-:100820003C05080124A596E4009E7821000A41C0F9
-:100830000085C821000B8C02A0620000AF280000D8
-:10084000A1F100013C0E60008DC6182024180001A3
-:1008500000F8500400CA202501003821A5EB000251
-:10086000ADC418200A0013CB3C06800000104603DC
-:100870000502000D30E7007F11430006000720C08D
-:10088000009E18210A001601240200020A0015AB7E
-:10089000AF800020009E18210A00160124020003E8
-:1008A0000A0012FFAF8400300A001617AF8700203D
-:1008B0008F8500043C19800024080003373801802C
-:1008C000A308000B0A00144F3C088000A2F8000B9C
-:1008D0000A00155A2419BFFF8F9600042412FFFE48
-:1008E0000A00144D02D228242416FFFE0A001558CF
-:1008F00000B628243C038000346401008C8500008D
-:1009000030A2003E1440000800000000AC60004827
-:100910008C87000030E607C010C000050000000012
-:10092000AC60004CAC60005003E000082402000101
-:10093000AC600054AC6000408C880000310438008A
-:100940001080FFF9000000002402000103E000080D
-:10095000AC6000443C0380008C6201B80440FFFEA0
-:1009600034670180ACE4000024080001ACE000041E
-:10097000A4E5000824050002A0E8000A3464014050
-:10098000A0E5000B9483000A14C00008A4E3001043
-:10099000ACE000243C07800034E901803C041000F6
-:1009A000AD20002803E00008ACE401B88C86000408
-:1009B0003C041000ACE600243C07800034E90180D0
-:1009C000AD20002803E00008ACE401B83C0680003C
-:1009D0008CC201B80440FFFE34C701802409000224
-:1009E000ACE40000ACE40004A4E50008A0E9000ABF
-:1009F00034C50140A0E9000B94A8000A3C04100093
-:100A0000A4E80010ACE000248CA30004ACE30028B0
-:100A100003E00008ACC401B83C039000346200015C
-:100A2000008220253C038000AC6400208C650020FF
-:100A300004A0FFFE0000000003E00008000000002A
-:100A40003C028000344300010083202503E00008BD
-:100A5000AC44002027BDFFE03C098000AFBF001878
-:100A6000AFB10014AFB00010352801408D10000068
-:100A7000910400099107000891050008308400FFE7
-:100A800030E600FF00061A002C820081008330252A
-:100A90001040002A30A50080000460803C0D080151
-:100AA00025AD9350018D58218D6A0000014000084A
-:100AB000000000003C038000346201409445000ABD
-:100AC00014A0001E8F91FCC09227000530E60004A0
-:100AD00014C0001A000000000E00167F0200202142
-:100AE000922A000502002021354900040E001689D3
-:100AF000A229000592280005310400041480000298
-:100B0000000000000000000D922D0000240B0020CA
-:100B100031AC00FF158B00093C0580008CAE01B89C
-:100B200005C0FFFE34B10180AE3000003C0F100064
-:100B300024100005A230000BACAF01B80000000D7E
-:100B40008FBF00188FB100148FB0001003E00008B1
-:100B500027BD00200200202100C028218FBF0018DF
-:100B60008FB100148FB00010240600010A00164E49
-:100B700027BD00200000000D0200202100C0282118
-:100B80008FBF00188FB100148FB00010000030210B
-:100B90000A00164E27BD002014A0FFE80000000048
-:100BA000020020218FBF00188FB100148FB00010F9
-:100BB00000C028210A00166C27BD00203C078000D9
-:100BC0008CEE01B805C0FFFE34F00180241F000246
-:100BD000A21F000B34F80140A60600089719000A6E
-:100BE0003C0F1000A61900108F110004A61100126E
-:100BF000ACEF01B80A0016CA8FBF001827BDFFE886
-:100C0000AFBF00100E000FD4000000003C028000B7
-:100C10008FBF001000002021AC4001800A00108F1F
-:100C200027BD00183084FFFF30A5FFFF10800007AC
-:100C30000000182130820001104000020004204210
-:100C4000006518211480FFFB0005284003E0000820
-:100C50000060102110C00007000000008CA20000FE
-:100C600024C6FFFF24A50004AC82000014C0FFFBD3
-:100C70002484000403E000080000000010A0000825
-:100C800024A3FFFFAC86000000000000000000006D
-:100C90002402FFFF2463FFFF1462FFFA2484000490
-:100CA00003E00008000000003C03800027BDFFF8BF
-:100CB00034620180AFA20000308C00FF30AD00FF35
-:100CC00030CE00FF3C0B80008D6401B80480FFFE35
-:100CD000000000008FA900008D6801288FAA000085
-:100CE0008FA700008FA40000240500012402000249
-:100CF000A085000A8FA30000359940003C05100034
-:100D0000A062000B8FB800008FAC00008FA600001F
-:100D10008FAF000027BD0008AD280000AD400004E3
-:100D2000AD800024ACC00028A4F90008A70D001075
-:100D3000A5EE001203E00008AD6501B83C0680088E
-:100D400027BDFFE834C50080AFBF001090A70009A1
-:100D50002402001230E300FF1062000B00803021FB
-:100D60008CA8005000882023048000088FBF00104A
-:100D70008CAA0034240400390000282100CA48232A
-:100D800005200005240600128FBF00102402000178
-:100D900003E0000827BD00180E0017230000000024
-:100DA0008FBF00102402000103E0000827BD0018D7
-:100DB00027BDFFC8AFB20030AFB00028AFBF0034CE
-:100DC000AFB1002C00A0802190A5000D30A600102E
-:100DD00010C00010008090213C0280088C44000468
-:100DE0008E0300081064000C30A7000530A6000533
-:100DF00010C00093240400018FBF00348FB2003074
-:100E00008FB1002C8FB000280080102103E0000873
-:100E100027BD003830A7000510E0000F30AB0012EE
-:100E200010C00006240400013C0980088E08000858
-:100E30008D2500045105009C240400388FBF003428
-:100E40008FB200308FB1002C8FB0002800801021AD
-:100E500003E0000827BD0038240A0012156AFFE6E7
-:100E6000240400010200202127A500100E000CB66A
-:100E7000AFA000101440007C3C198008372400808B
-:100E800090980008331100081220000A8FA7001064
-:100E900030FF010013E000A48FA300148C860058DB
-:100EA00000661023044000043C0A8008AC8300580C
-:100EB0008FA700103C0A800835480080910900087F
-:100EC000312400081480000224080003000040219F
-:100ED0003C1F800893F1001193F9001237E600805F
-:100EE0008CCC0054333800FF03087821322D00FFEA
-:100EF000000F708001AE282100AC582B1160006FEC
-:100F00000000000094CA005C8CC900543144FFFF0B
-:100F1000012510230082182B1460006800000000D7
-:100F20008CCB00540165182330EC00041180006C58
-:100F3000000830808FA8001C0068102B1040006251
-:100F400030ED0004006610232C46008010C0000223
-:100F500000408821241100800E00167F02402021CD
-:100F60003C0D800835A6008024070001ACC7000CAA
-:100F700090C800080011484035A70100310C007FDF
-:100F8000A0CC00088E05000424AB0001ACCB0030DF
-:100F9000A4D1005C8CCA003C9602000E01422021C4
-:100FA000ACC400208CC3003C0069F821ACDF001CFD
-:100FB0008E190004ACF900008E180008ACF800048B
-:100FC0008FB10010322F000855E0004793A6002093
-:100FD000A0C0004E90D8004E2411FFDFA0F80008FA
-:100FE00090CF000801F17024A0CE00088E05000803
-:100FF0003C0B800835690080AD2500388D6A0014EF
-:101000008D2200302419005001422021AD240034EB
-:1010100091230000307F00FF13F90036264F0100B6
-:101020000E001689024020212404003800002821E7
-:101030000E0017232406000A0A0017882404000162
-:101040000E000D28000020218FBF00348FB2003029
-:101050008FB1002C8FB0002800402021008010218B
-:1010600003E0000827BD00388E0E00083C0F800802
-:1010700035F00080AE0E005402402021AE0000305A
-:101080000E00167F00000000920D00250240202176
-:1010900035AC00200E001689A20C00250E000CAC09
-:1010A00002402021240400382405008D0E0017235F
-:1010B000240600120A0017882404000194C5005C6D
-:1010C0000A0017C330A3FFFF2407021811A0FF9ED8
-:1010D00000E610238FAE001C0A0017CB01C61023B8
-:1010E0000A0017C82C620218A0E600080A0017F5CB
-:1010F0008E0500082406FF8001E6C0243C11800014
-:10110000AE3800288E0D000831E7007F3C0E800CC1
-:1011100000EE6021AD8D00E08E080008AF8C003C31
-:101120000A001801AD8800E4AC80005890850008E2
-:101130002403FFF700A33824A08700080A0017A69D
-:101140008FA700103C05080024A5616C3C04080032
-:10115000248470B83C020800244261742403000611
-:101160003C010801AC2597603C010801AC24976460
-:101170003C010801AC2297683C010801A023976C50
-:1011800003E000080000000003E000082402000162
-:101190003C028000308800FF344701803C0680001C
-:1011A0008CC301B80460FFFE000000008CC501285C
-:1011B0002418FF803C0D800A24AF010001F8702440
-:1011C00031EC007FACCE0024018D2021ACE5000085
-:1011D000948B00EA3509600024080002316AFFFFA1
-:1011E000ACEA000424020001A4E90008A0E8000B16
-:1011F000ACE000243C071000ACC701B8AF84003C51
-:1012000003E00008AF8500709388004C8F8900646C
-:101210008F82003C30C600FF0109382330E900FF0F
-:101220000122182130A500FF2468008810C00002A8
-:10123000012438210080382130E4000314800003A9
-:1012400030AA00031140000D312B000310A000094B
-:101250000000102190ED0000244E000131C200FF7B
-:101260000045602BA10D000024E700011580FFF967
-:101270002508000103E00008000000001560FFF3EE
-:101280000000000010A0FFFB000010218CF80000FF
-:1012900024590004332200FF0045782BAD180000CC
-:1012A00024E7000415E0FFF92508000403E0000826
-:1012B000000000009385004C9388005C8F870064D9
-:1012C000000432003103007F00E5102B30C47F00A2
-:1012D0001040000F006428258F84003C3C098000EA
-:1012E0008C8A00ECAD2A00A43C03800000A35825A2
-:1012F000AC6B00A08C6C00A00580FFFE000000001D
-:101300008C6D00ACAC8D00EC03E000088C6200A892
-:101310000A0018B38F84003C9388005D3C02800073
-:1013200000805021310300FEA383005D30ABFFFF3E
-:1013300030CC00FF30E7FFFF344801803C098000DB
-:101340008D2401B80480FFFE8F8D007024180016D4
-:10135000AD0D00008D2201248F8D003CAD020004F4
-:101360008D590020A5070008240201C4A119000A14
-:10137000A118000B952F01208D4E00088D47000409
-:10138000978300608D59002401CF302100C72821A8
-:1013900000A320232418FFFFA504000CA50B000EBA
-:1013A000A5020010A50C0012AD190018AD180024FC
-:1013B00095AF00E83C0B10002407FFF731EEFFFF6C
-:1013C000AD0E00288DAC0084AD0C002CAD2B01B807
-:1013D0008D46002000C7282403E00008AD4500200A
-:1013E0008F88003C0080582130E7FFFF910900D62C
-:1013F0003C02800030A5FFFF312400FF00041A00EA
-:101400000067502530C600FF344701803C0980004A
-:101410008D2C01B80580FFFE8F820070240F00170D
-:10142000ACE200008D390124ACF900048D78002075
-:10143000A4EA0008241901C4A0F8000AA0EF000BD8
-:10144000952301208D6E00088D6D00049784006047
-:1014500001C35021014D602101841023A4E2000C3E
-:10146000A4E5000EA4F90010A4E60012ACE00014FC
-:101470008D780024240DFFFFACF800188D0F007C40
-:10148000ACEF001C8D0E00783C0F1000ACEE00207D
-:10149000ACED0024950A00BE240DFFF73146FFFF96
-:1014A000ACE60028950C00809504008231837FFF14
-:1014B0000003CA003082FFFF0322C021ACF8002CD9
-:1014C000AD2F01B8950E00828D6A002000AE30214C
-:1014D000014D2824A506008203E00008AD65002028
-:1014E0003C028000344501803C0480008C8301B8BC
-:1014F0000460FFFE8F8A0048240600199549001CED
-:101500003128FFFF000839C0ACA70000A0A6000BDF
-:101510003C05100003E00008AC8501B88F8700503F
-:101520000080402130C400FF3C0680008CC201B81E
-:101530000440FFFE8F8900709383006C3499600033
-:10154000ACA90000A0A300058CE20010240F00024B
-:101550002403FFF7A4A20006A4B900088D180020F8
-:10156000A0B8000AA0AF000B8CEE0000ACAE0010DB
-:101570008CED0004ACAD00148CEC001CACAC002471
-:101580008CEB0020ACAB00288CEA002C3C07100050
-:10159000ACAA002C8D090024ACA90018ACC701B876
-:1015A0008D05002000A3202403E00008AD040020E6
-:1015B0008F86003C27BDFFE0AFB10014AFBF00181D
-:1015C000AFB0001090C300D430A500FF30620020FF
-:1015D00010400008008088218CCB00D02409FFDF58
-:1015E000256A0001ACCA00D090C800D40109382493
-:1015F000A0C700D414A000403C0C80008F84003CA5
-:10160000908700D42418FFBF2406FFEF30E3007F4B
-:10161000A08300D4979F00608F8200648F8D003C70
-:1016200003E2C823A7990060A5A000BC91AF00D435
-:1016300001F87024A1AE00D48F8C003CA18000D7AB
-:101640008F8A003CA5400082AD4000EC914500D45B
-:1016500000A65824A14B00D48F9000388F840064DA
-:10166000978600600204282110C0000FAF85003863
-:10167000A380005C3C0780008E2C000894ED0120C4
-:101680008E2B0004018D5021014B80210206202366
-:101690003086FFFF30C8000F3909000131310001E9
-:1016A00016200009A388005C9386004C8FBF0018A9
-:1016B0008FB100148FB0001027BD0020AF850068E7
-:1016C00003E00008AF86006400C870238FBF0018D5
-:1016D0009386004C8FB100148FB0001034EF0C00D3
-:1016E000010F282127BD0020ACEE0084AF850068E3
-:1016F00003E00008AF8600643590018002002821D5
-:101700000E001940240600828F84003C908600D48D
-:1017100030C5004050A0FFBAA380006C8F850050F8
-:101720003C0680008CCD01B805A0FFFE8F890070BB
-:101730002408608224070002AE090000A608000801
-:10174000A207000B8CA300083C0E1000AE03001093
-:101750008CA2000CAE0200148CBF0014AE1F001847
-:101760008CB90018AE1900248CB80024AE180028DB
-:101770008CAF0028AE0F002CACCE01B80A0019794E
-:10178000A380006C8F8A003C27BDFFE0AFB100143E
-:10179000AFB000108F880064AFBF0018938900407D
-:1017A000954200BC30D100FF0109182B0080802138
-:1017B00030AC00FF3047FFFF0000582114600003E9
-:1017C000310600FF01203021010958239783006072
-:1017D0000068202B148000270000000010680056CD
-:1017E000241900011199006334E708803165FFFF77
-:1017F0000E0018F1020020218F8300703C0780004A
-:1018000034E601803C0580008CAB01B80560FFFE2A
-:10181000240A00188F84003CACC30000A0CA000B4F
-:10182000948900BE3C081000A4C90010ACC0003070
-:10183000ACA801B89482008024430001A4830080F6
-:10184000949F00803C0608008CC6318833EC7FFFF3
-:101850001186005E000000000200202102202821E5
-:101860008FBF00188FB100148FB000100A001965E7
-:1018700027BD0020914400D42403FF8000838825E5
-:10188000A15100D4978400603088FFFF51000023ED
-:10189000938C00408F85003C2402EFFF008B78235F
-:1018A00094AE00BC0168502B31E900FF01C26824EE
-:1018B000A4AD00BC51400039010058213C1F8000FC
-:1018C00037E601008CD800043C19000103194024BC
-:1018D0005500000134E740008E0A00202403FFFB7E
-:1018E0002411000101432024AE0400201191002D99
-:1018F00034E7800002002021012030210E0018F181
-:101900003165FFFF978700608F890064A7800060C2
-:1019100001278023AF900064938C00408F8B003CA4
-:101920008FBF00188FB100148FB0001027BD0020AA
-:1019300003E00008A16C00D73C0D800035AA01002F
-:101940008D4800043C0900010109282454A000012D
-:1019500034E740008E0F00202418FFFB34E780009E
-:1019600001F8702424190001AE0E00201599FF9F84
-:1019700034E70880020020210E0018BF3165FFFF08
-:1019800002002021022028218FBF00188FB10014EF
-:101990008FB000100A00196527BD00200A001A2820
-:1019A0000000482102002021012030210E0018BF34
-:1019B0003165FFFF978700608F890064A780006012
-:1019C000012780230A001A3FAF900064948C0080A6
-:1019D000241F8000019F3024A4860080908B00800B
-:1019E000908F0080316700FF0007C9C20019C0272F
-:1019F000001871C031ED007F01AE2825A085008060
-:101A00000A001A10020020219385006C24030001B3
-:101A100027BDFFE800A330042CA20020AFB00010C7
-:101A2000AFBF001400C01821104000132410FFFEA7
-:101A30003C0708008CE7319000E610243C08800049
-:101A40003505018014400005240600848F89003C80
-:101A5000240A00042410FFFFA12A00FC0E001940F4
-:101A600000000000020010218FBF00148FB0001092
-:101A700003E0000827BD00183C0608008CC631941E
-:101A80000A001A8800C310248F87004827BDFFE092
-:101A9000AFB20018AFB10014AFB00010AFBF001C60
-:101AA00030D000FF90E6000D00A08821008090213A
-:101AB00030C5007FA0E5000D8F85003C8E23001807
-:101AC0008CA200D01062002E240A000E0E001A7B99
-:101AD000A38A006C2409FFFF104900222404FFFFA1
-:101AE00052000020000020218E2600003C0C001037
-:101AF00000CC5824156000393C0E000800CE682444
-:101B000055A0003F024020213C18000200D880244C
-:101B10001200001F3C0A00048F8700488CE200146A
-:101B20008CE300108CE500140043F82303E5C82B78
-:101B300013200005024020218E24002C8CF100107F
-:101B4000109100310240202124020012A382006C77
-:101B50000E001A7B2412FFFF105200022404FFFF24
-:101B6000000020218FBF001C8FB200188FB100141D
-:101B70008FB000100080102103E0000827BD002076
-:101B800090A800D4350400200A001AB1A0A400D403
-:101B900000CA48241520000B8F8B00488F8D004809
-:101BA0008DAC00101580000B024020218E2E002CE1
-:101BB00051C0FFEC00002021024020210A001ACC75
-:101BC000240200178D66001050C0FFE6000020219F
-:101BD000024020210A001ACC2402001102402021D8
-:101BE000240200150E001A7BA382006C240FFFFF55
-:101BF000104FFFDC2404FFFF0A001ABB8E260000F2
-:101C00000A001AF2240200143C08000400C8382418
-:101C100050E0FFD400002021024020210A001ACC0D
-:101C2000240200138F85003C27BDFFD8AFB3001CF2
-:101C3000AFB20018AFB10014AFB00010AFBF0020BA
-:101C400090A700D48F9000502412FFFF34E2004090
-:101C500092060000A0A200D48E03001000809821FC
-:101C60001072000630D1003F2408000D0E001A7BD0
-:101C7000A388006C105200252404FFFF8F8A003CCB
-:101C80008E0900188D4400D0112400070260202125
-:101C9000240C000E0E001A7BA38C006C240BFFFF9B
-:101CA000104B001A2404FFFF240400201224000417
-:101CB0008F8D003C91AF00D435EE0020A1AE00D452
-:101CC0008F85005810A00019000000001224004A5F
-:101CD0008F98003C8F92FCC0971000809651000AAC
-:101CE000523000488F9300443C1F08008FFF318C16
-:101CF00003E5C82B1720001E0260202100002821C8
-:101D00000E0019DA24060001000020218FBF0020F8
-:101D10008FB3001C8FB200188FB100148FB0001069
-:101D20000080102103E0000827BD00285224002A6B
-:101D30008E0500148F84003C948A008025490001A0
-:101D4000A4890080948800803C0208008C4231887D
-:101D500031077FFF10E2000E00000000026020212A
-:101D60000E001965240500010A001B3C000020211B
-:101D70002402002D0E001A7BA382006C2403FFFFB7
-:101D80001443FFE12404FFFF0A001B3D8FBF002026
-:101D900094990080241F800024050001033FC02483
-:101DA000A498008090920080908E0080325100FFB5
-:101DB000001181C200107827000F69C031CC007F6C
-:101DC000018D5825A08B00800E001965026020212E
-:101DD0000A001B3C000020212406FFFF54A6FFD66A
-:101DE0008F84003C026020210E001965240500014B
-:101DF0000A001B3C00002021026020210A001B5623
-:101E00002402000A2404FFFD0A001B3CAF93006477
-:101E10008F88003C27BDFFE8AFB00010AFBF0014B3
-:101E2000910A00D48F8700500080802135490040FE
-:101E30008CE60010A10900D43C0208008C4231B0AD
-:101E400030C53FFF00A2182B106000078F8500549B
-:101E5000240DFF8090AE000D01AE6024318B00FF99
-:101E6000156000080006C382020020212403000D33
-:101E70008FBF00148FB0001027BD00180A001A7B16
-:101E8000A383006C33060003240F000254CFFFF736
-:101E90000200202194A2001C8F85003C24190023FD
-:101EA000A4A200E88CE8000000081E02307F003F7A
-:101EB00013F900353C0A00838CE800188CA600D08A
-:101EC00011060008000000002405000E0E001A7B19
-:101ED000A385006C2407FFFF104700182404FFFFB0
-:101EE0008F85003C90A900D435240020A0A400D404
-:101EF0008F8C0048918E000D31CD007FA18D000D9B
-:101F00008F8300581060001C020020218F84005431
-:101F10008C9800100303782B11E0000D2419001891
-:101F200002002021A399006C0E001A7B2410FFFFF1
-:101F3000105000022404FFFF000020218FBF001476
-:101F40008FB000100080102103E0000827BD0018AA
-:101F50008C8600108F9F00480200202100C31023B0
-:101F6000AFE20010240500010E0019DA240600017A
-:101F70000A001BC8000020210E001965240500017D
-:101F80000A001BC800002021010A5824156AFFD945
-:101F90008F8C0048A0A600FC0A001BB5A386005E3B
-:101FA00030A500FF2406000124A9000100C9102B60
-:101FB0001040000C00004021240A000100A6182354
-:101FC000308B000124C60001006A3804000420425E
-:101FD0001160000200C9182B010740251460FFF8AA
-:101FE00000A6182303E000080100102127BDFFD838
-:101FF000AFB000188F900050AFB1001CAFBF0020F1
-:102000002403FFFF2411002FAFA30010920600004D
-:102010002405000826100001006620260E001BE1A2
-:10202000308400FF00021E003C021EDC34466F417B
-:102030000A001C090000102110A0000900801821CE
-:102040002445000130A2FFFF2C4500080461FFFA7F
-:10205000000320400086202614A0FFF900801821EC
-:102060000E001BE1240500208FA300102629FFFF8E
-:10207000313100FF00034202240700FF1627FFE270
-:102080000102182600035027AFAA0014AFAA0010BF
-:102090000000302127A8001027A7001400E67823AD
-:1020A00091ED000324CE000100C8602131C600FF7D
-:1020B0002CCB00041560FFF9A18D00008FA2001049
-:1020C0008FBF00208FB1001C8FB0001803E0000804
-:1020D00027BD002827BDFFD0AFB3001CAFB0001054
-:1020E000AFBF0028AFB50024AFB40020AFB20018D6
-:1020F000AFB100143C0C80008D880128240FFF80B4
-:102100003C06800A25100100250B0080020F682480
-:102110003205007F016F7024AD8E009000A628214B
-:10212000AD8D002490A600FC3169007F3C0A80043C
-:10213000012A1821A386005E9067007C0080982108
-:10214000AF83003430E20002AF880070AF85003CFE
-:1021500000A018211440000224040034240400309C
-:10216000A384004C8C7200DC30D100FF24040004F6
-:10217000AF92006412240004A380006C8E740004EB
-:102180001680001E3C0880009386005D30C7000169
-:1021900050E0000F8F8600648CA400848CA800841B
-:1021A0002413FF8000936024000C49403110007F0D
-:1021B000013078253C19200001F9682530DF00FE48
-:1021C0003C038000AC6D0830A39F005D8F860064E7
-:1021D0008FBF00288FB500248FB400208FB3001C60
-:1021E0008FB200188FB100148FB0001024020001CC
-:1021F00027BD003003E00008ACA600DC8E7F00089D
-:10220000950201208E67001003E2C8213326FFFFEC
-:1022100030D8000F33150001AF87003816A00058E2
-:10222000A398005C35090C000309382100D8182355
-:10223000AD030084AF8700688E6A00043148FFFF59
-:102240001100007EA78A006090AC00D42407FF80B4
-:1022500000EC302430CB00FF1560004B9786006007
-:10226000938E005E240D000230D5FFFF11CD02A237
-:102270000000A0218F85006402A5802B160000BC01
-:102280009388004C3C11800096240120310400FF0B
-:10229000148500888F8400688F98003833120003FB
-:1022A0005640008530A500FF8F900068310C00FF7C
-:1022B0002406003411860095AF900050920400046B
-:1022C000148001198F8E003CA38000408E0D000405
-:1022D0008DC800D83C0600FF34CCFFFF01AC302491
-:1022E0000106182B14600121AF8600588F87006407
-:1022F00097980060AF8700440307402310C000C7D1
-:10230000A78800608F91003430C300030003582376
-:10231000922A007C3171000302261021000A2082DB
-:10232000309200010012488000492821311FFFFF30
-:1023300003E5C82B132001208F88003C8F850038CF
-:102340008F8800681105025A3C0E3F018E0600007E
-:102350003C0C250000CE682411AC01638F84005032
-:1023600030E500FF0E00187B000030218F88003C14
-:102370008F8700648F8500380A001DE88F8600581B
-:102380000A001C87AF87006890AC00D400EC2024C2
-:10239000309000FF120000169386005D90B5008813
-:1023A00090B400D724A8008832A2003F2446FFE062
-:1023B0002CD10020A39400401220000CAF880050C4
-:1023C000240E000100CE2004308A00191540012B94
-:1023D0003C06800034D80002009858241560022E74
-:1023E0003092002016400234000000009386005D09
-:1023F00030CE000111C0000F978800608CA90084C6
-:102400008CAF00842410FF800130C82400191940CB
-:1024100031ED007F006D38253C1F200000FF902526
-:1024200030CB00FE3C188000AF120830A38B005D5B
-:10243000978800601500FF84000000008E63002074
-:10244000306C00041180FF519386005D2404FFFB73
-:10245000006430243C038000AE66002034660180B6
-:102460008C7301B80660FFFE8F8E0070346A010025
-:102470003C150001ACCE00008C620124240760856D
-:10248000ACC200048D54000402958824522000013F
-:1024900024076083241200023C1810003C0B8000CB
-:1024A000A4C70008A0D2000BAD7801B80A001C5CDC
-:1024B0009386005D30A500FF0E00187B2406000106
-:1024C0008F8800703C05800034A90900250201882E
-:1024D0009388004C304A0007304B00783C03408022
-:1024E0002407FF800163C825014980210047F824A3
-:1024F000310C00FF24060034ACBF0800AF90005040
-:10250000ACB908105586FF6E920400048F84003C1D
-:102510008E110030908E00D431CD001015A0001027
-:102520008F8300642C6F000515E000E400000000BC
-:10253000909800D42465FFFC331200101640000868
-:1025400030A400FF8F9F00688F99003813F90004B2
-:102550003887000130E20001144001C8000000008B
-:102560000E001BF4000000000A001E2900000000FD
-:102570008F84006830C500FF0E00187B2406000120
-:10258000938E004C240A003411CA00A08F85003CB1
-:102590008F860064978300603062FFFF00C288234B
-:1025A000AF910064A78000601280FF900280182124
-:1025B0002414FFFD5474FFA28E6300208E69000472
-:1025C0002403FFBF240BFFEF0135C823AE790004BD
-:1025D00090AF00D431ED007FA0AD00D48E66002016
-:1025E0008F98003CA780006034DF0002AE7F00209F
-:1025F000A70000BC931200D402434024A30800D4D7
-:102600008F95003CAEA000EC92AE00D401CB5024DC
-:10261000A2AA00D40A001D088F85003C8F910038C3
-:10262000AF80006402275821AF8B003800002021C2
-:102630002403FFFF108301B48F85003C8E0C001033
-:102640003C0D08008DAD31B09208000031843FFF91
-:10265000008D802B12000023310D003F3C19080033
-:102660008F3931A88F9F0070000479802408FF8083
-:10267000033F2021008FC8219385005D0328F824A3
-:102680003C0600803C0F800034D80001001F9140C0
-:102690003331007F8F86003C0251502535EE0940D2
-:1026A000332B0078333000073C0310003C02800CD1
-:1026B00001789025020E48210143C02502223821CD
-:1026C00034AE0001ADFF0804AF890054ADF2081428
-:1026D000AF870048ADFF0028ACD90084ADF80830C2
-:1026E000A38E005D9383005E2407000350670028DB
-:1026F00025A3FFE0240C0001146CFFAB8F85003C88
-:102700002411002311B10084000000002402000BFA
-:10271000026020210E001A7BA382006C0040A021E1
-:102720000A001D638F85003C02602021240B000CF1
-:102730000E001A7BA38B006C240AFFFF104AFFBC1B
-:102740002404FFFF8F8E003CA38000408E0D000408
-:102750008DC800D83C0600FF34CCFFFF01AC30240C
-:102760000106182B1060FEE1AF86005802602021A0
-:10277000241200190E001A7BA392006C240FFFFF95
-:10278000104FFFAB2404FFFF0A001CB48F860058D3
-:102790002C7400201280FFDE2402000B000328802E
-:1027A0003C1108012631955400B148218D2D0000BF
-:1027B00001A00008000000008F85003800A710214C
-:1027C00093850040AF82003802251821A383004082
-:1027D000951F00BC0226282137F91000A51900BC5E
-:1027E0005240FF92AF850064246A0004A38A00402F
-:1027F000950900BC24A40004AF8400643532200095
-:10280000A51200BC0A001D85000020218F860064EF
-:102810002CCB00051560FF60978300603072FFFFCE
-:1028200000D240232D18000513000003306400FF80
-:1028300024DFFFFC33E400FF8F8500688F860038BB
-:1028400010A60004388F000131ED000115A00138F9
-:10285000000000008F84003C908C00D4358700106D
-:10286000A08700D48F85003C8F860064978300602A
-:10287000ACA000EC0A001D603062FFFF8CAA00844F
-:102880008CB500843C0410000147102400028940EC
-:1028900032B4007F0234302500C460253C0880003B
-:1028A0002405000102602021240600010E0019DA2F
-:1028B000AD0C08300A001CF48F85003C8C8200ECC3
-:1028C0001222FE7E0260202124090005A389006CEB
-:1028D0000E001A7B2411FFFF1451FE782404FFFF21
-:1028E0000A001D862403FFFF8F8F00508F88003C55
-:1028F0008DF80000AD1800888DE70010AD07009836
-:102900008F8700640A001DE88F8600582407FFFFA8
-:1029100011870005000000000E001B7D02602021D1
-:102920000A001DC10040A0210E001B0202602021F0
-:102930000A001DC10040A0218F9000503C090800F2
-:102940008D2931B08E11001032323FFF0249682BC1
-:1029500011A0000C240AFF808F85005490AE000D5A
-:10296000014E1024304C00FF11800007026020212E
-:102970000011C38233030003240B0001106B010517
-:1029800000000000026020212418000D0E001A7BB8
-:10299000A398006C004020218F85003C0A001D6335
-:1029A0000080A0218F9000503C0A08008D4A31B071
-:1029B0008F8500548E0400100000A0218CB10014FB
-:1029C00030823FFF004A602B8CB200205180FFEE26
-:1029D0000260202190B8000D240BFF800178702444
-:1029E00031C300FF5060FFE80260202100044382F1
-:1029F0003106000314C0FFE40260202194BF001CD4
-:102A00008F99003C8E060028A73F00E88CAF00108D
-:102A1000022F202314C40139026020218F83005823
-:102A200000C36821022D382B14E001352402001860
-:102A30008F8A00488F820034024390218D4B001012
-:102A400001637023AD4E0010AD5200208C4C007419
-:102A50000192282B14A00156026020218F8400547B
-:102A60008E0800248C8600241106000702602021B5
-:102A70002419001C0E001A7BA399006C240FFFFF81
-:102A8000104FFFC52404FFFF8F8400488C8700246B
-:102A900024FF0001AC9F0024125101338F8D0034BC
-:102AA0008DB10074123201303C0B00808E0E00009C
-:102AB00001CB502415400075000000008E03001467
-:102AC0002411FFFF10710006026020212418001B52
-:102AD0000E001A7BA398006C1051FFAF2404FFFF77
-:102AE0008E0300003C0800010068302410C0001371
-:102AF0003C0400800064A024168000090200282104
-:102B0000026020212419001A0E001A7BA399006C80
-:102B1000240FFFFF104FFFA02404FFFF0200282115
-:102B2000026020210E001A9B240600012410FFFFE2
-:102B30001050FF992404FFFF241400018F9F0048C8
-:102B4000026020210280302197F100342405000129
-:102B500026270001A7E700340E0019DA0000000064
-:102B6000000020218F85003C0A001D630080A02109
-:102B70008F9000503C1408008E9431B08E070010E6
-:102B800030E83FFF0114302B10C000618F860054E5
-:102B9000241FFF8090C5000D03E52024309200FF24
-:102BA0005240005C026020218F8D005811A0000768
-:102BB00000078B828F85003C8F89FCC094AF00801A
-:102BC0009539000A132F00F68F870044322C00033A
-:102BD000158000630000000092020002104000D740
-:102BE000000000008E0A0024154000D80260202159
-:102BF0009204000324060002308800FF1506000539
-:102C0000308500FF8F940058528000F2026020212E
-:102C1000308500FF38AD00102DA400012CBF00014D
-:102C200003E43025020028210E001A9B02602021B7
-:102C30002410FFFF105000BE8F85003C8F8300588A
-:102C4000106000C4240500013C1908008F39318C44
-:102C50000323782B15E000B12409002D0260202108
-:102C6000000028210E0019DA240600018F85003C9F
-:102C7000000018210A001D630060A0210E0018A6A4
-:102C8000000000000A001E2900000000AC800020A7
-:102C90000A001EA98E0300140000282102602021D2
-:102CA0000E0019DA240600010A001CF48F85003C8E
-:102CB0000A001DE88F88003C8CB000848CB9008429
-:102CC0003C0310000207482400096940332F007FAD
-:102CD00001AFF82503E32825ACC5083091070001B2
-:102CE00024050001026020210E0019DA30E60001FF
-:102CF0000A001CF48F85003C938F004C2403FFFDD9
-:102D00000A001D65AF8F00640A001D652403FFFFE4
-:102D1000026020212410000D0E001A7BA390006C8D
-:102D2000004018218F85003C0A001D630060A0212F
-:102D30000E0018A600000000978300608F860064D4
-:102D40003070FFFF00D048232D3900051320FE12FC
-:102D50008F85003CACA200EC0A001D603062FFFFD2
-:102D600090C3000D307800085700FFA292040003C2
-:102D700002602021240200100E001A7BA382006C46
-:102D80002403FFFF5443FF9B920400030A001F43E8
-:102D90008F85003C90A8000D3106000810C00095FA
-:102DA0008F9400581680009E026020218E0F000C28
-:102DB0008CA4002055E40005026020218E1F00082D
-:102DC0008CB9002413F9003A02602021240200206B
-:102DD0000E001A7BA382006C2405FFFF1045FEEE57
-:102DE0002404FFFF8F8F0048240CFFF72403FF808B
-:102DF00091E9000D3C14800E3C0B8000012CC8248E
-:102E0000A1F9000D8F8F00343C0708008CE731AC2E
-:102E10008F8D007095E500788F99004800ED902126
-:102E200030BF7FFF001F20400244302130C8007FA8
-:102E300000C3C02401147021AD78002CA5D100007E
-:102E40008F2A002825420001AF2200288F29002C5C
-:102E50008E0C002C012C6821AF2D002C8E07002C2D
-:102E6000AF2700308E050014AF250034973F003A9D
-:102E700027E40001A724003A95F200783C100800EE
-:102E80008E1031B02643000130717FFF1230005C9C
-:102E9000006030218F83003402602021240500016E
-:102EA0000E001965A46600780A001ED200002021D9
-:102EB0008E0700142412FFFF10F200638F8C003C79
-:102EC0008E0900188D8D00D0152D005D0260202127
-:102ED0008E0A00248CA200281142005324020021F3
-:102EE0000E001A7BA382006C1452FFBE2404FFFF65
-:102EF0008F85003C0A001D630080A0212402001F72
-:102F00000E001A7BA382006C2409FFFF1049FEA269
-:102F10002404FFFF0A001E858F83005802602021D1
-:102F20000E001A7BA389006C1450FF518F85003C62
-:102F30002403FFFF0A001D630060A0218CCE002443
-:102F40008E0B0024116EFF2A026020210A001F57F9
-:102F50002402000F0E001965026020218F85003CBD
-:102F60000A001F16000018218E0900003C05008091
-:102F7000012590241640FF452402001A02602021FA
-:102F80000E001A7BA382006C240CFFFF144CFECBB6
-:102F90002404FFFF8F85003C0A001D630080A021F0
-:102FA0002403FFFD0060A0210A001D63AF870064B9
-:102FB0002418001D0E001A7BA398006C2403FFFF49
-:102FC0001443FEA62404FFFF8F85003C0A001D6306
-:102FD0000080A0212412002C0E001A7BA392006C0A
-:102FE0002403FFFF1043FF508F85003C0A001EFDA5
-:102FF00092040003026020210A001F6D24020024B5
-:10300000240B8000006B702431CAFFFF000A13C23A
-:10301000305100FF001180270A001F9E001033C0AE
-:103020000A001F6D240200278E0600288CAE002C9B
-:1030300010CE0008026020210A001FB12402001FE8
-:103040000A001FB12402000E026020210A001FB1F5
-:10305000240200258E04002C1080000D8F83003484
-:103060008C7800740304582B5560000C02602021FA
-:103070008CA800140086A0210114302B10C0FF5A28
-:103080008F8F0048026020210A001FB12402002215
-:10309000026020210A001FB1240200230A001FB190
-:1030A0002402002627BDFFD8AFB3001CAFB1001427
-:1030B000AFBF0020AFB20018AFB000103C028000DC
-:1030C0008C5201408C4B01483C048000000B8C0268
-:1030D000322300FF317300FF8C8501B804A0FFFE8E
-:1030E00034900180AE1200008C8701442464FFF00C
-:1030F000240600022C830013AE070004A61100086A
-:10310000A206000BAE1300241060004F8FBF0020FA
-:10311000000448803C0A0801254A95D4012A402130
-:103120008D04000000800008000000003C0308003F
-:103130008C6331A831693FFF0009998000728021BA
-:10314000021370212405FF80264D0100264C0080CB
-:103150003C02800031B1007F3198007F31CA007F8E
-:103160003C1F800A3C1980043C0F800C01C52024C0
-:1031700001A5302401853824014F1821AC460024D4
-:10318000023F402103194821AC470090AC4400287D
-:10319000AF830048AF88003CAF8900340E0019317E
-:1031A000016080213C0380008C6B01B80560FFFE4C
-:1031B0008F8700488F86003C3465018090E8000DC1
-:1031C000ACB20000A4B000060008260000041603FC
-:1031D00000029027001227C21080008124C20088BC
-:1031E000241F6082A4BF0008A0A0000524020002E2
-:1031F000A0A2000B8F8B0034000424003C082700A1
-:1032000000889025ACB20010ACA00014ACA0002443
-:10321000ACA00028ACA0002C8D6900382413FF80DE
-:10322000ACA9001890E3000D02638024320500FF72
-:1032300010A000058FBF002090ED000D31AC007F85
-:10324000A0EC000D8FBF00208FB3001C8FB20018C0
-:103250008FB100148FB000103C0A10003C0E8000AB
-:1032600027BD002803E00008ADCA01B8265F0100B1
-:103270002405FF8033F8007F3C06800003E57824B6
-:103280003C19800A03192021ACCF0024908E00D471
-:1032900000AE682431AC00FF11800024AF84003CF4
-:1032A000248E008895CD00123C0C08008D8C31A82E
-:1032B00031AB3FFF01924821000B5180012A402190
-:1032C00001052024ACC400283107007F3C06800C97
-:1032D00000E620219083000D00A31024304500FF5C
-:1032E00010A0FFD8AF8400489098000D330F001055
-:1032F00015E0FFD58FBF00200E001931000000003F
-:103300003C0380008C7901B80720FFFE000000001C
-:10331000AE1200008C7F0144AE1F0004A61100080D
-:1033200024110002A211000BAE1300243C1308016B
-:1033300092739790327000015200FFC38FBF00203C
-:103340000E00216E024020210A00208B8FBF00203A
-:103350003C1260008E452C083C03F0033462FFFFF2
-:1033600000A2F824AE5F2C088E582C083C1901C02E
-:1033700003199825AE532C080A00208B8FBF00201C
-:10338000264D010031AF007F3C10800A240EFF80E3
-:1033900001F0282101AE60243C0B8000AD6C0024BC
-:1033A0001660FFA8AF85003C24110003A0B100FC0B
-:1033B0000A00208B8FBF002026480100310A007FC1
-:1033C0003C0B800A2409FF80014B30210109202495
-:1033D0003C078000ACE400240A00208AAF86003C51
-:1033E000944E0012320C3FFF31CD3FFF15ACFF7DF4
-:1033F000241F608290D900D42418FF8003197824F8
-:1034000031EA00FF1140FF770000000024070004AC
-:10341000A0C700FC8F870048241160842406000D9B
-:10342000A4B10008A0A600050A002075240200022D
-:103430003C0400012484977C24030014240200FE31
-:103440003C010800AC2431EC3C010800AC2331E81D
-:103450003C010801A42297983C0408012484979811
-:103460000000182100643021A0C30004246300017F
-:103470002C6500FF54A0FFFC006430213C070800CD
-:1034800024E7010003E00008AF87007C00A058217A
-:10349000008048210000102114A0001200005021DB
-:1034A0000A00216A000000003C010801A42097984E
-:1034B0003C05080194A597988F82007C3C0C08017C
-:1034C000258C979800E2182100AC2021014B302B6D
-:1034D000A089000400001021A460000810C0003979
-:1034E000010048218F86007C0009384000E9402116
-:1034F0000008388000E6282190A8000B90B9000A47
-:103500000008204000881021000218800066C021B9
-:10351000A319000A8F85007C00E5782191EE000A4E
-:1035200091E6000B000E684001AE6021000C208087
-:1035300000851021A046000B3C0308019063979280
-:10354000106000222462FFFF8F83003C3C010801D1
-:10355000A0229792906C00FF1180000400000000F0
-:10356000906E00FF25CDFFFFA06D00FF3C19080104
-:1035700097399798272300013078FFFF2F0F00FF1E
-:1035800011E0FFC9254A00013C010801A4239798D6
-:103590003C05080194A597988F82007C3C0C08019B
-:1035A000258C979800E2182100AC2021014B302B8C
-:1035B000A089000400001021A460000814C0FFC905
-:1035C0000100482103E000080000000003E00008BB
-:1035D0002402000227BDFFE0248501002407FF80AC
-:1035E000AFB00010AFBF0018AFB1001400A718248F
-:1035F0003C10800030A4007F3C06800A0086282111
-:103600008E110024AE03002490A200FF1440000895
-:10361000AF85003CA0A000098FBF0018AE110024A8
-:103620008FB100148FB0001003E0000827BD002008
-:1036300090A900FD90A800FF312400FF0E00211C7E
-:10364000310500FF8F85003C8FBF0018A0A0000946
-:10365000AE1100248FB100148FB0001003E00008F9
-:1036600027BD002027BDFFD0AFB20020AFB1001CA6
-:10367000AFB00018AFBF002CAFB40028AFB3002428
-:103680003C0980009533011635320C00952F011A44
-:103690003271FFFF023280218E08000431EEFFFFFD
-:1036A000248B0100010E6821240CFF8025A5FFFF5B
-:1036B000016C50243166007F3C07800AAD2A00244B
-:1036C00000C73021AF850078AF8800743C01080145
-:1036D000A020979190C300090200D021008098217A
-:1036E000306300FF2862000510400048AF86003CB0
-:1036F000286400021480008E24140001240D0005AB
-:103700003C010801A02D977590CC00FD3C010801FB
-:10371000A02097763C010801A020977790CB000A63
-:10372000240AFF80318500FF014B4824312700FF28
-:1037300010E0000C000058213C1280083651008037
-:103740008E2F00308CD0005C01F0702305C0018EFC
-:103750008F87007490D4000A3284007FA0C4000ACE
-:103760008F86003C3C118008363000808E0F003080
-:103770008F87007400EF702319C000EE0000000076
-:1037800090D4000924120002328400FF10920247F4
-:10379000000000008CC2005800E2F82327F9FFFF68
-:1037A0001B2001300000000090C50009240800041F
-:1037B00030A300FF10680057240A00013C010801F3
-:1037C000A02A977590C900FF252700013C01080138
-:1037D000A02797743C0308019063977524060005A1
-:1037E0001066006A2C780005130000C400009021C8
-:1037F0000003F8803C0408012484962003E4C821D7
-:103800008F25000000A0000800000000241800FF21
-:103810001078005C0000000090CC000A90CA0009FB
-:103820003C080801910897913187008000EA4825FB
-:103830003C010801A029977C90C500FD3C140801BB
-:1038400092949792311100013C010801A025977DC7
-:1038500090DF00FE3C010801A03F977E90D200FF60
-:103860003C010801A032977F8CD900543C0108012B
-:10387000AC3997808CD000583C010801AC3097845B
-:103880008CC3005C3C010801AC34978C3C010801FE
-:10389000AC239788162000088FBF002C8FB4002817
-:1038A0008FB300248FB200208FB1001C8FB000189E
-:1038B00003E0000827BD00303C1180009624010E73
-:1038C0000E000FD43094FFFF3C0B08018D6B9794D2
-:1038D0000260382102802821AE2B01803C130801B0
-:1038E0008E73977401602021240600830E00102F30
-:1038F000AFB300108FBF002C8FB400288FB300240B
-:103900008FB200208FB1001C8FB0001803E00008B8
-:1039100027BD00303C1808008F1831FC270F00012C
-:103920003C010800AC2F31FC0A0021FF0000000020
-:103930001474FFB900000000A0C000FF3C0508009F
-:103940008CA531E43C0308008C6331E03C020800A4
-:103950008C4232048F99003C34A80001241F0002DD
-:103960003C010801AC2397943C010801A0289790E2
-:103970003C010801A0229793A33F00090A0021B847
-:103980008F86003C0E00216E000000000A0021FF1F
-:103990008F86003C3C1F080193FF97742419000197
-:1039A00013F902298F8700743C1008019210977850
-:1039B0003C06080190C6977610C000050200A021C1
-:1039C0003C04080190849779109001E48F87007C73
-:1039D000001088408F9F007C023048210009C88079
-:1039E000033F702195D80008270F0001A5CF0008DC
-:1039F0003C040801908497793C05080190A59776CE
-:103A00000E00211C000000008F87007C0230202166
-:103A10000004308000C720218C8500048F8200784C
-:103A200000A2402305020006AC8200048C8A00003C
-:103A30008F830074014310235C400001AC830000BD
-:103A40008F86003C90CB00FF2D6C00025580002D2E
-:103A5000241400010230F821001F408001072821B2
-:103A600090B9000B8CAE00040019C04003197821F6
-:103A7000000F1880006710218C4D000001AE8823D4
-:103A80002630FFFF5E00001F241400018C44000458
-:103A90008CAA0000008A482319200019240E000473
-:103AA0003C010801A02E977590AD000B8CAB000473
-:103AB000000D8840022D8021001010800047102149
-:103AC0008C440004016460230582020094430008D2
-:103AD00090DF00FE90B9000B33E500FF54B90004FD
-:103AE0000107A021A0D400FE8F87007C0107A02140
-:103AF0009284000B0E00211C240500018F86003CDF
-:103B000024140001125400962E50000116000042A9
-:103B10003C08FFFF241900021659FF3F0000000077
-:103B2000A0C000FF8F86003CA0D200090A0021FF40
-:103B30008F86003C90C700092404000230E300FF98
-:103B40001064016F24090004106901528F88007805
-:103B50008CCE0054010E682325B1000106200175AA
-:103B6000241800043C010801A03897753C010801A5
-:103B7000A020977490D400FD90D200FF2E4F000239
-:103B800015E0FF14328400FF000438408F89007C68
-:103B900090DF00FF00E41021000220800089C8218E
-:103BA0002FE500029324000B14A0FF0A2407000253
-:103BB0000004184000648021001058800169282109
-:103BC0008CAC0004010C50230540FF0200000000F3
-:103BD0003C0308019063977614600005246F000190
-:103BE0003C010801A02497793C010801A0279777A0
-:103BF0003C010801A02F977690CE00FF24E700013A
-:103C000031CD00FF01A7882B1220FFE990A4000B03
-:103C10000A0021EE000000003C0508018CA5977405
-:103C20003C12000400A8F82413F200062402000548
-:103C30003C09080191299775152000022402000310
-:103C4000240200053C010801A022979190C700FFC3
-:103C500014E0012024020002A0C200090A0021FF92
-:103C60008F86003C90CC00FF1180FEDA240A000110
-:103C70008F8C00788F89007C240F000301806821DD
-:103C80001160001E240E0002000540400105A02125
-:103C900000142080008990218E510004019180231E
-:103CA0000600FECC000000003C020801904297761E
-:103CB00014400005245800013C010801A02A977710
-:103CC0003C010801A02597793C010801A0389776AE
-:103CD00090DF00FF010510210002C88033E500FFDE
-:103CE000254A00010329202100AA402B1500FEB916
-:103CF0009085000B1560FFE5000540400005404041
-:103D000001051821000310803C010801A02A9774C6
-:103D10003C010801A0259778004918218C64000413
-:103D200000E4F82327F9FFFF1F20FFE9000000004F
-:103D30008C63000000E358230560013A01A3882347
-:103D400010E301170184C0231B00FEA20000000045
-:103D50003C010801A02E97750A00232D240B0001B9
-:103D6000240E0004A0CE00093C0D08008DAD31F8F2
-:103D70008F86003C25A200013C010800AC2231F8EE
-:103D80000A0021FF000000008CD9005C00F9C0236C
-:103D90001F00FE7B000000008CDF005C10FFFF6551
-:103DA0008F8400788CC3005C0083402325020001CF
-:103DB0001C40FF60000000008CC9005C24870001EB
-:103DC00000E9282B10A0FE943C0D80008DAB01046F
-:103DD0003C0C0001016C50241140FE8F24020010A5
-:103DE0003C010801A02297910A0021FF0000000079
-:103DF0008F9100788F86003C26220001ACC2005CC7
-:103E00000A0022BA241400018F87003C2404FF809A
-:103E10000000882190E9000A2414000101243025C3
-:103E2000A0E6000A3C05080190A597763C0408012D
-:103E3000908497790E00211C000000008F86003CC2
-:103E40008F85007C90C800FD310700FF00074040CF
-:103E50000107F821001FC0800305C8219323000B30
-:103E6000A0C300FD8F85007C8F86003C0305602188
-:103E7000918F000B000F704001CF6821000D8080F2
-:103E8000020510218C4B0000ACCB00548D84000443
-:103E90008F830078006450231940000224820001BF
-:103EA0002462000101074821ACC2005C0009308097
-:103EB00000C5402100E02021240500010E00211C46
-:103EC0009110000B8F86003C90C500FF10A0FF0CE6
-:103ED000001070408F85007C01D06821000D10809B
-:103EE000004558218D6400008F8C00780184502398
-:103EF0002547000104E0FF02263100013C030801D0
-:103F0000906397762E2F0002247800013C0108016F
-:103F1000A03897763C010801A034977711E0FEF8AD
-:103F2000020038210A00238D000740408F84003CA6
-:103F30008F8300788C85005800A340230502FE9AE9
-:103F4000AC8300580A002263000000003C0708010F
-:103F500090E79792240200FF10E200BE8F86003C9B
-:103F60003C1108019631979A3C0308012463979805
-:103F7000262500013230FFFF30ABFFFF0203602136
-:103F80002D6A00FF1540008D918700043C01080157
-:103F9000A420979A8F88003C0007484001272821D9
-:103FA000911800FF0005308024050001271400014E
-:103FB000A11400FF3C120801925297928F88007C56
-:103FC0008F8E0074264F000100C820213C0108019B
-:103FD000A02F9792AC8E00008F8D0078A4850008EA
-:103FE000AC8D00043C030801906397741460007763
-:103FF000000090213C010801A0259774A087000BC8
-:104000008F8C007C00CC5021A147000A8F82003C9D
-:10401000A04700FD8F84003CA08700FE8F86003CF7
-:104020008F9F0074ACDF00548F990078ACD9005892
-:104030008F8D007C0127C02100185880016DA021C0
-:10404000928F000A000F704001CF18210003888072
-:10405000022D8021A207000B8F86007C0166602163
-:10406000918A000B000A1040004A20210004288099
-:1040700000A64021A107000A3C07800834E900801F
-:104080008D2200308F86003CACC2005C0A0022BA50
-:104090002414000190CA00FF1540FEAD8F880078FF
-:1040A000A0C400090A0021FF8F86003CA0C000FDCB
-:1040B0008F98003C24060001A30000FE3C0108018B
-:1040C000A02697753C010801A02097740A0021EEF4
-:1040D0000000000090CB00FF3C04080190849793FF
-:1040E000316C00FF0184502B1540000F24020003A7
-:1040F00024020004A0C200090A0021FF8F86003CB0
-:1041000090C3000A2410FF8002035824316C00FF82
-:104110001180FDC1000000003C010801A02097753E
-:104120000A0021EE00000000A0C200090A0021FFE1
-:104130008F86003C90D4000A2412FF800254482449
-:10414000312800FF1500FFF4240200083C0108019B
-:10415000A02297910A0021FF000000000010884073
-:104160008F8B0074023018210003688001A7202182
-:10417000AC8B00008F8A0078240C0001A48C00080E
-:10418000AC8A00043C05080190A597762402000142
-:1041900010A2FE1E24A5FFFF0A0022799084000BC6
-:1041A0000184A0231A80FD8B000000003C0108015F
-:1041B000A02E97750A00232D240B00013C01080155
-:1041C000A425979A0A0023DF8F88003C240B000166
-:1041D000106B00228F98003C8F85003C90BF00FF41
-:1041E00033F900FF1079002B000000003C1F08018C
-:1041F00093FF9778001FC840033FC0210018A0809C
-:104200000288782191EE000AA08E000A8F8D007C32
-:104210003C0308019063977800CD88210A002405AB
-:10422000A223000B263000010600003101A49023D8
-:104230000640002B240200033C010801A02F9775C3
-:104240000A00232D240B00018F89003C0A00226301
-:10425000AD2700540A0022B924120001931400FD76
-:10426000A094000B8F88003C8F8F007C910E00FE85
-:1042700000CF6821A1AE000A8F91003CA22700FD6B
-:104280008F8300748F90003CAE0300540A00240614
-:104290008F8D007C90B000FEA090000A8F8B003CB8
-:1042A0008F8C007C916A00FD00CC1021A04A000B8D
-:1042B0008F84003CA08700FE8F8600788F85003CAD
-:1042C000ACA600580A0024068F8D007C94B8000824
-:1042D000ACA40004030378210A0022ADA4AF0008B7
-:1042E0003C010801A02297750A0021EE00000000A1
-:1042F00090CF0009240D000431EE00FF11CDFD85A3
-:10430000240200013C010801A02297750A0021EE59
-:0443100000000000A9
-:0C43140008003344080033440800342043
-:10432000080033F4080033D8080033280800332885
-:10433000080033280800334C800801008008008002
-:10434000800800005F865437E4AC62CC50103A45D8
-:1043500036621985BF14C0E81BC27A1E84F4B556B4
-:10436000094EA6FE7DDA01E7C04D748108005B3876
-:1043700008005B7C08005B2008005B2008005B20D5
-:1043800008005B2008005B3808005B2008005B2009
-:1043900008005B8408005B2008005A9808005B2036
-:1043A00008005B2008005B8408005B2008005B209D
-:1043B00008005B2008005B2008005B2008005B20F1
-:1043C00008005B2008005B2008005B2008005B20E1
-:1043D00008005B5808005B2008005B5808005B2061
-:1043E00008005B2008005B2008005B5C08005B584D
-:1043F00008005B2008005B2008005B2008005B20B1
-:1044000008005B2008005B2008005B2008005B20A0
-:1044100008005B2008005B2008005B2008005B2090
-:1044200008005B2008005B2008005B2008005B2080
-:1044300008005B2008005B2008005B2008005B2070
-:1044400008005B5C08005B5C08005B2008005B5CAC
-:1044500008005B2008005B2008005B2008005B2050
-:1044600008005B2008005B2008005B2008005B2040
-:1044700008005B2008005B2008005B2008005B2030
-:1044800008005B2008005B2008005B2008005B2020
-:1044900008005B2008005B2008005B2008005B2010
-:1044A00008005B2008005B2008005B2008005B2000
-:1044B00008005B2008005B2008005B2008005B20F0
-:1044C00008005B2008005B2008005B2008005B20E0
-:1044D00008005B2008005B2008005B2008005B20D0
-:1044E00008005B2008005B2008005B2008005B20C0
-:1044F00008005B2008005B2008005B2008005B20B0
-:1045000008005B2008005B2008005B2008005B209F
-:1045100008005B2008005B2008005B2008005B208F
-:1045200008005B2008005B2008005B2008005B207F
-:1045300008005B2008005B2008005B2008005B206F
-:1045400008005B2008005B2008005B2008005B205F
-:1045500008005B2008005B2008005B2008005B204F
-:1045600008005B2008005B2008005B2008005BA0BF
-:10457000080078F008007B54080078FC080076F00A
-:10458000080078FC08007988080078FC080076F0BC
-:10459000080076F0080076F0080076F0080076F063
-:1045A000080076F0080076F0080076F0080076F053
-:1045B000080076F00800791C0800790C080076F0F5
-:1045C000080076F0080076F0080076F0080076F033
-:1045D000080076F0080076F0080076F0080076F023
-:1045E000080076F0080076F0080076F00800790CF4
-:1045F0000800839C08008228080083640800822841
-:1046000008008334080081100800822808008228EE
-:1046100008008228080082280800822808008228D2
-:1046200008008228080082280800822808008228C2
-:1046300008008228080082280800825008008DD4D3
-:1046400008008F3008008F100800897808008DEC72
-:104650000A00012400000000000000000000000D1E
-:10466000747061362E322E31000000000602010106
-:10467000000000000000000000000000000000003A
-:10468000000000000000000000000000000000002A
-:10469000000000000000000000000000000000001A
-:1046A000000000000000000000000000000000000A
-:1046B00000000000000000000000000000000000FA
-:1046C00000000000000000000000000000000000EA
-:1046D00000000000000000000000000000000000DA
-:1046E0000000000010000003000000000000000DAA
-:1046F0000000000D3C020800244217203C03080083
-:1047000024632A10AC4000000043202B1480FFFDDE
-:10471000244200043C1D080037BD2FFC03A0F021FB
-:104720003C100800261004903C1C0800279C172011
-:104730000E000262000000000000000D2402FF8055
-:1047400027BDFFE000821024AFB00010AF42002070
-:10475000AFBF0018AFB10014936500043084007F30
-:10476000034418213C0200080062182130A50020F3
-:10477000036080213C080111277B000814A000027F
-:104780002466005C246600589202000497430104EA
-:10479000920400043047000F3063FFFF3084004074
-:1047A00000672823108000090000482192020005BC
-:1047B00030420004104000050000000010A000037B
-:1047C0000000000024A5FFFC24090004920200055B
-:1047D00030420004104000120000000010A0001041
-:1047E000000000009602000200A7202101044025DD
-:1047F0002442FFFEA7421016920300042402FF8009
-:1048000000431024304200FF104000033C0204002B
-:104810000A000174010240258CC20000AF4210184A
-:104820008F4201780440FFFE2402000AA7420140A3
-:1048300096020002240400093042000700021023FF
-:1048400030420007A7420142960200022442FFFEC6
-:10485000A7420144A740014697420104A7420148EC
-:104860008F42010830420020504000012404000122
-:104870009202000430420010144000023483001001
-:1048800000801821A743014A00000000000000003A
-:104890000000000000000000AF4810000000000011
-:1048A0000000000000000000000000008F42100027
-:1048B0000441FFFE3102FFFF10400007000000002E
-:1048C0009202000430420040144000030000000047
-:1048D0008F421018ACC20000960200063042FFFF63
-:1048E00024420002000210430002104003628821AB
-:1048F000962200001120000D3044FFFF00A7102178
-:104900008F8300388F45101C000210820002108037
-:1049100000431021AC45000030A6FFFF0E00058DBE
-:1049200000052C0200402021A62200009203000472
-:104930002402FF8000431024304200FF1040001F7B
-:104940000000000092020005304200021040001BEF
-:10495000000000009742100C2442FFFEA7421016F0
-:10496000000000003C02040034420030AF4210005E
-:104970000000000000000000000000000000000037
-:104980008F4210000441FFFE000000009742100C0F
-:104990008F45101C3042FFFF24420030000210827D
-:1049A00000021080005B1021AC45000030A6FFFF24
-:1049B0000E00058D00052C02A622000096040002C0
-:1049C000248400080E0001E93084FFFF97440104AD
-:1049D0000E0001F73084FFFF8FBF00188FB1001465
-:1049E0008FB000103C02100027BD002003E000083B
-:1049F000AF4201783084FFFF308200078F850024AA
-:104A000010400002248300073064FFF800A4102146
-:104A100030421FFF03421821247B4000AF8500284D
-:104A2000AF82002403E00008AF4200843084FFFF1F
-:104A30003082000F8F85002C8F86003410400002DA
-:104A40002483000F3064FFF000A410210046182BCF
-:104A5000AF8500300046202314600002AF82002C96
-:104A6000AF84002C8F82002C340480000342182174
-:104A700000641821AF83003803E00008AF420080D3
-:104A80008F820014104000088F8200048F82FFDCA8
-:104A9000144000058F8200043C02FFBF3442FFFF38
-:104AA000008220248F82000430430006240200028A
-:104AB0001062000F3C0201012C620003504000050F
-:104AC000240200041060000F3C0200010A000230C2
-:104AD0000000000010620005240200061462000CB1
-:104AE0003C0201110A000229008210253C0200113B
-:104AF00000821025AF421000240200010A0002309B
-:104B0000AF82000C00821025AF421000AF80000C75
-:104B100000000000000000000000000003E00008AA
-:104B2000000000008F82000C104000040000000014
-:104B30008F4210000441FFFE0000000003E0000867
-:104B4000000000008F8200102443F800000231C2F0
-:104B500024C2FFF02C630301106000030002104226
-:104B60000A000257AC8200008F85001800C5102B88
-:104B70001440000B0000182100C510232447000139
-:104B80008F82001C00A210212442FFFF0046102B40
-:104B9000544000042402FFFF0A000257AC870000C3
-:104BA0002402FFFF0A000260AC8200008C82000039
-:104BB00000021940006218210003188000621821C9
-:104BC000000318803C0208002442175C0062182190
-:104BD00003E000080060102127BDFFD8AFBF002010
-:104BE000AFB1001CAFB000183C0460088C825000CC
-:104BF0002403FF7F3C066000004310243442380C3D
-:104C0000AC8250008CC24C1C3C1A80000002160280
-:104C10003042000F10400007AF82001C8CC34C1CB8
-:104C20003C02001F3442FC0000621824000319C239
-:104C3000AF8300188F420008275B40003442000118
-:104C4000AF420008AF8000243C02601CAF400080EF
-:104C5000AF4000848C4500088CC3080834028000F3
-:104C6000034220212402FFF0006218243C0200804D
-:104C70003C010800AC2204203C025709AF840038F4
-:104C800014620004AF850034240200010A0002927D
-:104C9000AF820014AF8000148F4200003842000140
-:104CA000304200011440FFFC8F82001410400016B7
-:104CB0000000000097420104104000058F830000AF
-:104CC000146000072462FFFF0A0002A72C62000A9A
-:104CD0002C620010504000048F8300002462000109
-:104CE000AF8200008F8300002C62000A1440000392
-:104CF0002C6200070A0002AEAF80FFDC1040000209
-:104D000024020001AF82FFDC8F4301088F440100C1
-:104D100030622000AF83000410400008AF84001010
-:104D20003C0208008C42042C244200013C01080093
-:104D3000AC22042C0A00058A3C02400030650200C7
-:104D400014A0000324020F001482026024020D004C
-:104D500097420104104002C83C024000306240000B
-:104D6000144000AD8F8200388C4400088F420178D7
-:104D70000440FFFE24020800AF420178240200082C
-:104D8000A7420140A7400142974201048F840004DA
-:104D90003051FFFF308200011040000702208021C7
-:104DA0002623FFFE240200023070FFFFA7420146C7
-:104DB0000A0002DBA7430148A74001463C02080065
-:104DC0008C42043C1440000D8F8300103082002080
-:104DD0001440000224030009240300010060202184
-:104DE0008F83001024020900506200013484000403
-:104DF000A744014A0A0002F60000000024020F0046
-:104E00001462000530820020144000062403000DC7
-:104E10000A0002F5240300051440000224030009DF
-:104E200024030001A743014A3C0208008C420420ED
-:104E30003C0400480E00020C004420250E00023500
-:104E4000000000008F82000C1040003E00000000B7
-:104E50008F4210003C030020004310241040003912
-:104E60008F82000430420002104000360000000033
-:104E700097421014144000330000000097421008BD
-:104E80008F8800383042FFFF24420006000218825B
-:104E90000003388000E83021304300018CC400005A
-:104EA00010600004304200030000000D0A000337C8
-:104EB00000E81021544000103084FFFF3C05FFFF44
-:104EC00000852024008518260003182B0004102BD1
-:104ED0000043102410400005000000000000000006
-:104EE0000000000D00000000240002228CC200001F
-:104EF0000A000336004520253883FFFF0003182BE6
-:104F00000004102B00431024104000050000000096
-:104F1000000000000000000D000000002400022B33
-:104F20008CC200003444FFFF00E81021AC440000B4
-:104F30003C0208008C420430244200013C0108007D
-:104F4000AC2204308F6200008F840038AF820008EA
-:104F50008C8300003402FFFF1462000F0000102158
-:104F60003C0508008CA504543C0408008C840450C3
-:104F700000B0282100B0302B0082202100862021A3
-:104F80003C010800AC2504543C010800AC2404504A
-:104F90000A000580240400088C82000030420100D1
-:104FA0001040000F000010213C0508008CA5044CA7
-:104FB0003C0408008C84044800B0282100B0302B49
-:104FC00000822021008620213C010800AC25044CF1
-:104FD0003C010800AC2404480A00058024040008B1
-:104FE0003C0508008CA504443C0408008C84044063
-:104FF00000B0282100B0302B008220210086202123
-:105000003C010800AC2504443C010800AC240440E9
-:105010000A000580240400088F6200088F620000E7
-:1050200000021602304300F0240200301062000536
-:1050300024020040106200E08F8200200A000588F0
-:105040002442000114A00005000000000000000040
-:105050000000000D00000000240002568F4201787D
-:105060000440FFFE000000000E00023D27A40010D7
-:105070001440000500408021000000000000000DE9
-:10508000000000002400025D8E02000010400005B8
-:1050900000000000000000000000000D0000000003
-:1050A000240002608F62000C04430003240200010C
-:1050B0000A00042EAE000000AE0200008F8200380D
-:1050C0008C480008A20000078F65000C8F64000464
-:1050D00030A3FFFF0004240200852023308200FF5C
-:1050E0000043102124420005000230832CC20081BD
-:1050F000A605000A14400005A204000400000000F8
-:105100000000000D00000000240002788F850038A8
-:105110000E0005AB260400148F6200048F430108C3
-:10512000A60200083C02100000621824106000086B
-:105130000000000097420104920300072442FFECA4
-:10514000346300023045FFFF0A0003C3A2030007D7
-:10515000974201042442FFF03045FFFF9606000805
-:105160002CC200135440000592030007920200076E
-:1051700034420001A202000792030007240200014A
-:1051800010620005240200031062000B8F820038B9
-:105190000A0003E030C6FFFF8F8200383C04FFFFA7
-:1051A0008C43000C0064182400651825AC43000CE7
-:1051B0000A0003E030C6FFFF3C04FFFF8C430010F1
-:1051C0000064182400651825AC43001030C6FFFFAA
-:1051D00024C2000200021083A20200058F8300385F
-:1051E000304200FF00021080004328218CA80000FC
-:1051F0008CA20000240300040002170214430012D2
-:1052000000000000974201043C03FFFF0103182443
-:105210003042FFFF004610232442FFFE006240257B
-:10522000ACA8000092030005306200FF000210806D
-:1052300000501021904200143042000F0043102112
-:105240000A000415A20200068CA40004974201047F
-:105250009603000A3088FFFF3042FFFF004610230C
-:105260002442FFD60002140001024025ACA800042D
-:1052700092020007920400052463002800031883AB
-:105280000064182134420004A2030006A2020007B1
-:105290008F8200042403FFFB3442000200431024E9
-:1052A000AF820004920300068F8700380003188045
-:1052B000007010218C4400203C02FFF63442FFFFB6
-:1052C0000082402400671821AE04000CAC68000C7A
-:1052D000920500063C03FF7F8E02000C000528802B
-:1052E00000B020213463FFFF01033024948800269E
-:1052F00000A7282100431024AE02000CAC86002039
-:10530000AC880024ACA8001024020010A742014081
-:1053100024020002A7400142A7400144A7420146DF
-:10532000974201043C0400082442FFFEA7420148C2
-:10533000240200010E00020CA742014A9603000A53
-:105340009202000400431021244200023042000770
-:1053500000021023304200070E000235AE0200109A
-:105360008F6200003C0308008C6304442404001096
-:10537000AF820008974201043042FFFF2442FFFE43
-:1053800000403821000237C33C0208008C42044030
-:10539000006718210067282B0046102100451021C6
-:1053A0003C010800AC2304443C010800AC2204404A
-:1053B0000A0005150000000014A000050000000010
-:1053C000000000000000000D000000002400030A9F
-:1053D0008F4201780440FFFE000000000E00023DF5
-:1053E00027A40014144000050040802100000000A4
-:1053F0000000000D00000000240003118E020000D8
-:105400005440000692020007000000000000000D5A
-:10541000000000002400031C920200073042000438
-:10542000104000058F8200042403FFFB3442000279
-:1054300000431024AF8200048F620004044300087C
-:1054400092020007920200068E03000CAE000000DC
-:105450000002108000501021AC430020920200078F
-:1054600030420004544000099602000A92020005EE
-:105470003C03000100021080005010218C460018EF
-:1054800000C33021AC4600189602000A92060004C0
-:10549000277100080220202100C2302124C6000507
-:1054A000260500140E0005AB0006308292040006AB
-:1054B0008F6500043C027FFF0004208000912021C2
-:1054C0008C8300043442FFFF00A2282400651821C9
-:1054D000AC830004920200079204000592030004CA
-:1054E000304200041040001496070008308400FF8A
-:1054F00000042080009120218C8600049742010442
-:105500009605000A306300FF3042FFFF0043102180
-:105510000045102130E3FFFF004310232442FFD851
-:1055200030C6FFFF0002140000C23025AC86000424
-:105530000A0004C992030007308500FF0005288097
-:1055400000B128218CA4000097420104306300FFC1
-:105550003042FFFF00431021004710233C03FFFFB0
-:10556000008320243042FFFF00822025ACA40000ED
-:1055700092030007240200011062000600000000F0
-:105580002402000310620011000000000A0004EC75
-:105590008E03001097420104920300049605000A4E
-:1055A0008E24000C00431021004510212442FFF2FC
-:1055B0003C03FFFF008320243042FFFF00822025B0
-:1055C000AE24000C0A0004EC8E0300109742010484
-:1055D000920300049605000A8E2400100043102157
-:1055E000004510212442FFEE3C03FFFF00832024EE
-:1055F0003042FFFF00822025AE2400108E030010F1
-:105600002402000AA7420140A74301429603000A70
-:10561000920200043C04004000431021A7420144D0
-:10562000A740014697420104A74201482402000115
-:105630000E00020CA742014A0E00023500000000D5
-:105640008F6200009203000400002021AF82000856
-:10565000974201049606000A3042FFFF00621821BB
-:10566000006028213C0308008C6304443C020800CD
-:105670008C42044000651821004410210065382B3D
-:10568000004710213C010800AC2304443C01080001
-:10569000AC22044092040004008620212484000AE5
-:1056A0003084FFFF0E0001E9000000009744010470
-:1056B0003084FFFF0E0001F7000000003C021000E4
-:1056C000AF4201780A0005878F82002014820027EC
-:1056D0003062000697420104104000673C0240001F
-:1056E0003062400010400005000000000000000093
-:1056F0000000000D00000000240004208F4201780B
-:105700000440FFFE24020800AF4201782402000892
-:10571000A7420140A74001428F8200049743010441
-:1057200030420001104000073070FFFF2603FFFEEB
-:1057300024020002A7420146A74301480A00053F90
-:105740002402000DA74001462402000DA742014A91
-:105750008F62000024040008AF8200080E0001E9F7
-:10576000000000000A00051902002021104000423C
-:105770003C02400093620000304300F0240200101D
-:105780001062000524020070106200358F82002034
-:105790000A000588244200018F620000974301043B
-:1057A0003050FFFF3071FFFF8F4201780440FFFE51
-:1057B0003202000700021023304200072403000ACF
-:1057C0002604FFFEA7430140A7420142A74401442B
-:1057D000A7400146A75101488F42010830420020EE
-:1057E000144000022403000924030001A743014AD6
-:1057F0000E00020C3C0400400E00023500000000C8
-:105800003C0708008CE70444021110212442FFFEEB
-:105810003C0608008CC604400040182100E33821F3
-:10582000000010218F65000000E3402B00C23021F2
-:105830002604000800C830213084FFFFAF8500082F
-:105840003C010800AC2704443C010800AC2604409D
-:105850000E0001E9000000000A00051902202021C5
-:105860000E00013B000000008F8200202442000156
-:10587000AF8200203C024000AF4201380A00029291
-:10588000000000003084FFFF30C6FFFF00052C0041
-:1058900000A628253882FFFF004510210045282B4F
-:1058A0000045102100021C023042FFFF004310217E
-:1058B00000021C023042FFFF004310213842FFFF6C
-:1058C00003E000083042FFFF3084FFFF30A5FFFFF8
-:1058D0000000182110800007000000003082000145
-:1058E0001040000200042042006518210A0005A1B2
-:1058F0000005284003E000080060102110C00006E9
-:1059000024C6FFFF8CA2000024A50004AC82000086
-:105910000A0005AB2484000403E000080000000036
-:1059200010A0000824A3FFFFAC86000000000000C8
-:10593000000000002402FFFF2463FFFF1462FFFA4F
-:0C5940002484000403E0000800000000C4
-:04594C000000000156
-:105950000A00002A00000000000000000000000D06
-:10596000747870362E322E310000000006020100DD
-:1059700000000000000001360000EA6000000000A6
-:105980000000000000000000000000000000000017
-:105990000000000000000000000000000000000007
-:1059A00000000000000000000000000000000000F7
-:1059B00000000016000000000000000000000000D1
-:1059C00000000000000000000000000000000000D7
-:1059D00000000000000000000000000000000000C7
-:1059E000000000000000000000001388000000001C
-:1059F000000005DC000000000000000010000003B3
-:105A0000000000000000000D0000000D3C02080036
-:105A100024423D883C0308002463403CAC40000025
-:105A20000043202B1480FFFD244200043C1D08008D
-:105A300037BD7FFC03A0F0213C100800261000A811
-:105A40003C1C0800279C3D880E00044E000000000E
-:105A50000000000D27BDFFB4AFA10000AFA20004FD
-:105A6000AFA30008AFA4000CAFA50010AFA60014B0
-:105A7000AFA70018AFA8001CAFA90020AFAA002450
-:105A8000AFAB0028AFAC002CAFAD0030AFAE0034F0
-:105A9000AFAF0038AFB8003CAFB90040AFBC004476
-:105AA000AFBF00480E000591000000008FBF004806
-:105AB0008FBC00448FB900408FB8003C8FAF0038D6
-:105AC0008FAE00348FAD00308FAC002C8FAB002830
-:105AD0008FAA00248FA900208FA8001C8FA7001870
-:105AE0008FA600148FA500108FA4000C8FA30008B0
-:105AF0008FA200048FA1000027BD004C3C1B600456
-:105B00008F7A5030377B502803400008AF7A00006E
-:105B10008F86003C3C0390003C02800000862825D4
-:105B200000A32025AC4400203C0380008C670020AB
-:105B300004E0FFFE0000000003E000080000000099
-:105B40000A000070240400018F85003C3C048000A2
-:105B50003483000100A3102503E00008AC8200207C
-:105B600003E00008000010213084FFFF30A5FFFF94
-:105B70001080000700001821308200011040000250
-:105B800000042042006518211480FFFB0005284016
-:105B900003E000080060102110C0000700000000B2
-:105BA0008CA2000024C6FFFF24A50004AC820000E4
-:105BB00014C0FFFB2484000403E000080000000080
-:105BC00010A0000824A3FFFFAC8600000000000026
-:105BD000000000002402FFFF2463FFFF1462FFFAAD
-:105BE0002484000403E000080000000090AA0031B3
-:105BF0008FAB00108CAC00403C0300FF8D680004AC
-:105C0000AD6C00208CAD004400E060213462FFFFE9
-:105C1000AD6D00248CA700483C09FF000109C02499
-:105C2000AD6700288CAE004C0182C824031978258A
-:105C3000AD6F0004AD6E002C8CAD0038314A00FF12
-:105C4000AD6D001C94A900323128FFFFAD68001033
-:105C500090A70030A5600002A1600004A1670000C9
-:105C600090A30032306200FF00021982106000052C
-:105C7000240500011065000E0000000003E000088C
-:105C8000A16A00018CD80028354A0080AD78001840
-:105C90008CCF0014AD6F00148CCE0030AD6E0008B8
-:105CA0008CC4002CA16A000103E00008AD64000C64
-:105CB0008CCD001CAD6D00188CC90014AD690014AA
-:105CC0008CC80024AD6800088CC70020AD67000CAC
-:105CD0008CC200148C8300700043C82B1320000773
-:105CE000000000008CC20014144CFFE4000000000F
-:105CF000354A008003E00008A16A00018C82007030
-:105D00000A0000E6000000009089003027BDFFF87F
-:105D10008FA8001CA3A900008FA300003C0DFF80EA
-:105D200035A2FFFF8CAC002C00625824AFAB000002
-:105D3000A100000400C05821A7A000028D060004A5
-:105D400000A048210167C8218FA5000000805021D4
-:105D50003C18FF7F032C20263C0E00FF2C8C0001FA
-:105D6000370FFFFF35CDFFFF3C02FF0000AFC82417
-:105D700000EDC02400C27824000C1DC00323682558
-:105D800001F87025AD0D0000AD0E00048D24002437
-:105D9000AFAD0000AD0400088D2C00202404FFFFEF
-:105DA000AD0C000C9547003230E6FFFFAD06001049
-:105DB0009145004830A200FF000219C25060000166
-:105DC0008D240034AD0400148D4700388FAA0018CC
-:105DD00027BD0008AD0B0028AD0A0024AD07001C4C
-:105DE000AD00002CAD00001803E00008AD0000205D
-:105DF00027BDFFE0AFB20018AFB10014AFB0001084
-:105E0000AFBF001C9098003000C088213C0D00FFFF
-:105E1000330F007FA0CF0000908E003135ACFFFF24
-:105E20003C0AFF00A0CE000194A6001EA2200004A0
-:105E30008CAB00148E29000400A08021016C282462
-:105E4000012A40240080902101052025A626000279
-:105E5000AE24000426050020262400080E0000922F
-:105E6000240600029247003026050028262400144C
-:105E700000071E000003160324060004044000036C
-:105E80002403FFFF965900323323FFFF0E000092D8
-:105E9000AE230010262400248FBF001C8FB20018F0
-:105EA0008FB100148FB000102405000300003021D2
-:105EB0000A00009C27BD002027BDFFD8AFB1001C01
-:105EC000AFB00018AFBF002090A90030240200013D
-:105ED00000E050213123003F00A040218FB000405E
-:105EE0000080882100C04821106200148FA700386C
-:105EF000240B000500A0202100C02821106B0013F6
-:105F0000020030210E000128000000009225007CD4
-:105F100030A400021080000326030030AE000030E1
-:105F2000260300348FBF00208FB1001C8FB00018F3
-:105F30000060102103E0000827BD00280E0000A724
-:105F4000AFB000100A00016F000000008FA3003CFA
-:105F5000010020210120282101403021AFA30010A1
-:105F60000E0000EEAFB000140A00016F0000000048
-:105F70003C06800034C20E008C4400108F85004423
-:105F8000ACA400208C43001803E00008ACA300245C
-:105F90003C06800034C20E008C4400148F850044FF
-:105FA000ACA400208C43001C03E00008ACA3002438
-:105FB0009382000C1040001B2483000F2404FFF088
-:105FC0000064382410E00019978B00109784000EAD
-:105FD0009389000D3C0A601C0A0001AC0164402357
-:105FE00001037021006428231126000231C2FFFF43
-:105FF00030A2FFFF0047302B50C0000E00E44821C4
-:106000008D4D000C31A3FFFF00036400000C2C0336
-:1060100004A1FFF30000302130637FFF0A0001A4D8
-:106020002406000103E00008000000009784000E31
-:1060300000E448213123FFFF3168FFFF0068382B5F
-:1060400054E0FFF8A783000E938A000D114000056D
-:10605000240F0001006BC023A380000D03E00008A3
-:10606000A798000E006BC023A38F000D03E000086B
-:10607000A798000E03E000080000000027BDFFE81D
-:10608000AFB000103C10800036030140308BFFFFA2
-:1060900093AA002BAFBF0014A46B000436040E00BB
-:1060A0009488001630C600FF8FA90030A46800064F
-:1060B000AC650008A0660012A46A001AAC67002054
-:1060C0008FA5002CA4690018012020210E00019842
-:1060D000AC6500143C021000AE0201788FBF0014C2
-:1060E0008FB0001003E0000827BD00188F85000066
-:1060F0002484000727BDFFF83084FFF83C068000A9
-:1061000094CB008A316AFFFFAFAA00008FA900007C
-:10611000012540232507FFFF30E31FFF0064102BFC
-:106120001440FFF700056882000D288034CC400041
-:1061300000AC102103E0000827BD00088F8200009A
-:106140002486000730C5FFF800A2182130641FFF25
-:1061500003E00008AF8400008F87003C8F84004478
-:1061600027BDFFB0AFB70044AFB40038AFB1002CCB
-:10617000AFBF0048AFB60040AFB5003CAFB300348E
-:10618000AFB20030AFB000283C0B80008C860024FA
-:10619000AD6700808C8A002035670E0035690100EC
-:1061A000ACEA00108C8800248D2500040000B82182
-:1061B000ACE800188CE3001000A688230000A021A2
-:1061C000ACE300148CE20018ACE2001C122000FECC
-:1061D00000E0B021936C0008118000F40000000082
-:1061E000976F001031EEFFFF022E682B15A000EF15
-:1061F00000000000977200103250FFFFAED0000088
-:106200003C0380008C740000329300081260FFFD94
-:106210000000000096D800088EC700043305FFFF79
-:1062200030B5000112A000E4000000000000000DE5
-:1062300030BFA0402419004013F9011B30B4A00066
-:10624000128000DF00000000937300081260000855
-:1062500000000000976D001031ACFFFF00EC202B18
-:106260001080000330AE004011C000D500000000D7
-:10627000A7850040AF8700389363000802202821DB
-:10628000AFB10020146000F527B40020AF60000C0F
-:10629000978F004031F140001620000224030016C1
-:1062A0002403000E24054007A363000AAF65001411
-:1062B000938A00428F70001431550001001512407E
-:1062C00002024825AF690014979F00408F780014A0
-:1062D00033F9001003194025AF680014979200406D
-:1062E0003247000810E0016E000000008F670014C4
-:1062F0003C1210003C11800000F27825AF6F0014B2
-:1063000036230E00946E000A3C0D81002406000E18
-:1063100031CCFFFF018D2025AF640004A36600028D
-:106320009373000A3406FFFC266B0004A36B000A7B
-:1063300097980040330820001100015F0000000022
-:106340003C05800034A90E00979900409538000C58
-:1063500097870040001940423312C0003103000308
-:1063600000127B0330F11000006F682500117203EA
-:1063700001AE6025000C20C0A76400129793004076
-:10638000936A000A001359823175003C02AA102159
-:106390002450003CA3700009953F000C33F93FFFE7
-:1063A000A779001097700012936900090130F82155
-:1063B00027E5000230B900070019C02333080007A1
-:1063C000A368000B9371000997720012976F001079
-:1063D000322700FF8F910038978D004000F218217E
-:1063E000006F702101C6602131A6004010C0000579
-:1063F0003185FFFF00B1102B3C12800010400017C8
-:10640000000098210225A82B56A0013E8FA5002050
-:106410003C048000348A0E008D5300143C0680003A
-:10642000AD5300108D4B001CAD4B0018AD45000066
-:106430008CCD000031AC00081180FFFD34CE0E0081
-:1064400095C3000800A0882100009021A783004088
-:106450008DC6000424130001AF860038976F00102A
-:1064600031F5FFFF8E9F000003F1282310A0011FCC
-:10647000AE85000093620008144000DD00000000BB
-:106480000E0001E7240400108F90004800402821EE
-:106490003C023200320600FF000654000142F8259B
-:1064A00026090001AF890048ACBF000093790009BC
-:1064B00097780012936F000A332800FF3303FFFF21
-:1064C0000103382100076C0031EE00FF01AE6025AA
-:1064D000ACAC00048F840048978B0040316A2000E8
-:1064E0001140010AACA4000897640012308BFFFF32
-:1064F00006400108ACAB000C978E004031C5000887
-:1065000014A0000226280006262800023C1F800056
-:1065100037E70E0094F900148CE5001C8F67000427
-:10652000937800023324FFFF330300FFAFA3001072
-:106530008F6F0014AFA800180E0001CBAFAF00148E
-:10654000240400100E0001FB000000008E920000E9
-:1065500016400005000000008F7800142403FFBFE0
-:106560000303A024AF7400148F67000C00F5C8214A
-:10657000AF79000C9375000816A000080000000019
-:1065800012600006000000008F6800143C0AEFFF54
-:106590003549FFFE0109F824AF7F0014A3730008FA
-:1065A0008FA500200A00034F02202021AED1000059
-:1065B0000A00022D3C03800014E0FF1E30BFA04003
-:1065C0000E0001900000A0212E9100010237B0259D
-:1065D00012C000188FBF00488F87003C24170F009F
-:1065E00010F700D43C0680008CD901780720FFFE0C
-:1065F000241F0F0010FF00F634CA0E008D56001441
-:1066000034C7014024080240ACF600048D49001C48
-:106610003C141000ACE90008A0E00012A4E0001A4D
-:10662000ACE00020A4E00018ACE80014ACD4017881
-:106630008FBF00488FB700448FB600408FB5003C35
-:106640008FB400388FB300348FB200308FB1002C7C
-:106650008FB0002803E0000827BD00508F9100385C
-:10666000978800403C1280000220A821310700409A
-:1066700014E0FF7C00009821977900108F92003879
-:106680003338FFFF131200A8000020210080A02152
-:10669000108000F300A088211620FECE000000002C
-:1066A0000A00031F2E9100013C0380008C620178D8
-:1066B0000440FFFE240808008F860000AC680178C3
-:1066C0003C038000946D008A31ACFFFF01865823A3
-:1066D000256AFFFF31441FFF2C8900081520FFF9B0
-:1066E000000000008F8F0048347040008F83003C12
-:1066F00000E0A021240E0F0025E70001AF8700482D
-:1067000000D03021023488233C08800031F500FF9E
-:10671000106E000524070001939800423313000116
-:106720000013924036470001001524003C0A010086
-:10673000008A4825ACC900008F82004830BF00366F
-:1067400030B90008ACC200041320009900FF98255E
-:1067500035120E009650000A8F8700003C0F810012
-:106760003203FFFF24ED000835060140006F60256D
-:106770003C0E100031AB1FFF269200062405000ED0
-:10678000ACCC0020026E9825A4C5001AAF8B000087
-:10679000A4D20018162000083C1080008F89003C0D
-:1067A00024020F005122000224170001367300401A
-:1067B0000E0001883C10800036060E008CCB0014C1
-:1067C000360A014002402021AD4B00048CC5001C5C
-:1067D000AD450008A1550012AD5300140E000198FC
-:1067E0003C151000AE1501780A00035200000000AD
-:1067F000936F0009976E0012936D000B31E500FF57
-:1068000000AE202131AC00FF008C80212602000A5E
-:106810003050FFFF0E0001E7020020218F86004864
-:106820003C0341003C05800024CB0001AF8B0048B5
-:10683000936A00099769001230C600FF315F00FFBC
-:106840003128FFFF03E8382124F900020006C400C4
-:106850000319782501E37025AC4E00008F6D000C04
-:1068600034A40E00948B001401B26025AC4C0004DB
-:106870008C85001C8F670004936A00023164FFFF5F
-:10688000314900FFAFA900108F680014AFB10018A4
-:106890000E0001CBAFA800140A0002FD0200202167
-:1068A000AF600004A3600002979800403308200006
-:1068B0001500FEA300003021A7600012978400405D
-:1068C000936B000A3C10800030931F00001351832B
-:1068D000014BA82126A20028A362000936090E0058
-:1068E000953F000C0A000295A77F00108F700014DE
-:1068F000360900400E000188AF6900140A0002C981
-:10690000000000000A00034F000020210641FEFAAB
-:10691000ACA0000C8CAC000C3C0D8000018D9025CF
-:106920000A0002EAACB2000C000090210A0002C585
-:1069300024130001128000073C028000344B0E003B
-:106940009566000830D30040126000490000000046
-:106950003C0680008CD001780600FFFE34C50E0096
-:1069600094B500103C03050034CC014032B8FFFF61
-:1069700003039025AD92000C8CAF0014240D200071
-:106980003C041000AD8F00048CAE001CAD8E0008DE
-:10699000A1800012A580001AAD800020A5800018FB
-:1069A000AD8D0014ACC401780A0003263C068000BB
-:1069B0008F9F0000351801402692000227F9000839
-:1069C00033281FFFA71200180A000391AF880000A8
-:1069D0003C02800034450140ACA0000C1280001B3A
-:1069E00034530E0034510E008E370010ACB7000443
-:1069F0008E2400183C0B8000ACA4000835700140C8
-:106A000024040040A20000128FBF0048A600001A14
-:106A10008FB70044AE0000208FB60040A6000018DB
-:106A20008FB5003CAE0400148FB400388FB300342F
-:106A30008FB200308FB1002C8FB000283C021000C4
-:106A400027BD005003E00008AD6201788E66001497
-:106A5000ACA600048E64001C0A00042A3C0B8000D3
-:106A60000E0001902E9100010A0003200237B0258C
-:106A7000000000000000000D000000002400036979
-:106A80000A0004013C06800027BDFFD8AFBF0020EC
-:106A90003C0980003C1F20FFAFB200183C0760009B
-:106AA00035320E002402001037F9FFFDACE2300849
-:106AB000AFB3001CAFB10014AFB00010AE5900006E
-:106AC00000000000000000000000000000000000C6
-:106AD000000000003C1800FF3713FFFDAE5300001C
-:106AE0003C0B60048D7050002411FF7F3C0E0002AF
-:106AF0000211782435EC380C35CD0109ACED4C1879
-:106B0000240A0009AD6C50008CE80438AD2A000856
-:106B1000AD2000148CE54C1C3106FFFF38C42F71EA
-:106B200000051E023062000F2486C0B3104000072B
-:106B3000AF8200088CE54C1C3C09001F3528FC0086
-:106B400000A81824000321C2AF8400048CF10808B7
-:106B50003C0F57092412F0000232702435F0001067
-:106B600001D0602601CF68262DAA00012D8B0001DF
-:106B7000014B382550E00009A380000C3C1F601C2D
-:106B80008FF8000824190001A399000C33137C002E
-:106B9000A7930010A780000EA380000DAF800048CF
-:106BA00014C00003AF8000003C066000ACC0442C61
-:106BB0000E0005B93C1080000E000F2436110100B4
-:106BC0003C12080026523DF03C13080026733E702C
-:106BD0008E03000038640001308200011440FFFC85
-:106BE0003C0B800A8E2600002407FF8024C9024047
-:106BF000312A007F014B402101272824AE060020C6
-:106C0000AF880044AE0500243C048000AF86003C01
-:106C10008C8C01780580FFFE24180800922F000854
-:106C2000AC980178A38F0042938E004231CD0001D1
-:106C300011A0000F24050D0024DFF8002FF9030137
-:106C40001320001C000629C224A4FFF000041042F7
-:106C5000000231400E00020200D2D8213C02400066
-:106C60003C068000ACC201380A0004A0000000000D
-:106C700010C50023240D0F0010CD00273C1F8008F5
-:106C800037F9008093380000240E0050330F00FFC6
-:106C900015EEFFF33C0240000E000A400000000029
-:106CA0003C0240003C068000ACC201380A0004A04F
-:106CB000000000008F83000400A3402B1500000B90
-:106CC0008F8B0008006B50212547FFFF00E5482B04
-:106CD0001520000600A36023000C19400E000202DC
-:106CE0000073D8210A0004C43C0240000000000DDB
-:106CF0000E000202000000000A0004C43C02400032
-:106D00003C1B0800277B3F700E00020200000000C1
-:106D10000A0004C43C0240003C1B0800277B3F9053
-:106D20000E000202000000000A0004C43C02400001
-:106D30003C0660043C09080025290104ACC9502C1C
-:106D40008CC850003C0580003C02000235070080E2
-:106D5000ACC750003C040800248415A43C03080080
-:106D60002463155CACA50008ACA2000C3C01080033
-:106D7000AC243D803C010800AC233D8403E00008C6
-:106D80002402000100A030213C1C0800279C3D8803
-:106D90003C0C04003C0B0002008B3826008C402683
-:106DA0002CE200010007502B2D050001000A48804D
-:106DB0003C03080024633D80004520250123182161
-:106DC0001080000300001021AC66000024020001C6
-:106DD00003E00008000000003C1C0800279C3D88E0
-:106DE0003C0B04003C0A0002008A3026008B382647
-:106DF0002CC200010006482B2CE500010009408050
-:106E00003C03080024633D80004520250103182130
-:106E100010800005000010213C0C0800258C155C3A
-:106E2000AC6C00002402000103E000080000000038
-:106E30003C0900023C0804000088302600893826FE
-:106E40002CC30001008028212CE4000100831025C0
-:106E50001040000B000030213C1C0800279C3D889E
-:106E60003C0A80008D4E00082406000101CA6825F6
-:106E7000AD4D00088D4C000C01855825AD4B000C24
-:106E800003E0000800C010213C1C0800279C3D883E
-:106E90003C0580008CA6000C000420272402000181
-:106EA00000C4182403E00008ACA3000C3C0200025C
-:106EB0001082000B3C0560003C07040010870003B3
-:106EC0000000000003E00008000000008CA908D0CA
-:106ED000240AFFFD012A402403E00008ACA808D0E2
-:106EE0008CA408D02406FFFE0086182403E00008C6
-:106EF000ACA308D03C05601A34A600108CC30080F7
-:106F000027BDFFF88CC50084AFA3000093A4000048
-:106F10002402000110820003AFA5000403E0000872
-:106F200027BD000893A7000114E0001497AC0002ED
-:106F300097B800023C0F8000330EFFFC01CF6821A0
-:106F4000ADA50000A3A000003C0660008CC708D0DF
-:106F50002408FFFE3C04601A00E82824ACC508D0D1
-:106F60008FA300048FA200003499001027BD0008F1
-:106F7000AF22008003E00008AF2300843C0B8000B8
-:106F8000318AFFFC014B48218D2800000A00057D55
-:106F9000AFA8000427BDFFE8AFBF00103C1C0800ED
-:106FA000279C3D883C0580008CA4000C8CA200042A
-:106FB0003C0300020044282410A0000A00A3182467
-:106FC0003C0604003C0400021460000900A61024E2
-:106FD0001440000F3C0404000000000D3C1C08009D
-:106FE000279C3D888FBF001003E0000827BD0018D4
-:106FF0003C0208008C423D800040F809000000007F
-:107000003C1C0800279C3D880A0005A68FBF001085
-:107010003C0208008C423D840040F809000000005A
-:107020000A0005AC00000000000411C003E00008E5
-:10703000244202403C04080024843FD42405001A62
-:107040000A00009C0000302127BDFFE0AFB0001017
-:107050003C108000AFBF0018AFB100143611010022
-:10706000922200090E0005B63044007F8E3F0000DA
-:107070008F89003C3C0F008003E26021258800409E
-:107080000049F821240DFF80310E007831980078F6
-:1070900035F9000135F100020319382501D14825E1
-:1070A000010D302403ED5824018D2824240A0040CA
-:1070B00024040080240300C0AE0B0024AE0008109E
-:1070C000AE0A0814AE040818AE03081CAE05080486
-:1070D000AE070820AE060808AE09082436090900E4
-:1070E0009539000C3605098033ED007F3338FFFFFA
-:1070F000001889C0AE110800AE0F0828952C000CAE
-:107100008FBF00188FB10014318BFFFF000B51C0EF
-:10711000AE0A002C8CA400508FB000108CA3003C51
-:107120008D2700048CA8001C8CA600383C0E800A19
-:1071300001AE102127BD0020AF820044AF84005073
-:10714000AF830054AF87004CAF88005C03E00008B9
-:10715000AF8600603C09080091293FF924A800028D
-:107160003C05110000093C0000E8302500C5182549
-:1071700024820008AC83000003E00008AC80000417
-:107180003C098000352309009128010B906A001109
-:107190002402002800804821314700FF00A0702110
-:1071A00000C068213108004010E20002340C86DD86
-:1071B000240C08003C0A800035420A9A94470000DB
-:1071C000354B0A9C35460AA030F9FFFFAD39000067
-:1071D0008D780000354B0A8024040001AD3800048E
-:1071E0008CCF0000AD2F00089165001930A300037B
-:1071F0001064009A28640002148000B9240500027B
-:10720000106500A8240F0003106F00BE35450AA4C6
-:10721000240A0800118A004D0000000051000042BD
-:107220003C0B80003C04800034830900906700120E
-:1072300030E200FF004D7821000FC88027240001B4
-:107240003C0A8000354F090091E50019354C098052
-:107250008D87002830A300FF000315000047582544
-:107260000004C4003C19600001793025370806FF8E
-:10727000AD260000AD2800048DEA002C252800284A
-:10728000AD2A00088DEC0030AD2C000C8DE50034EB
-:10729000AD2500108DE40038AD2400148DE3001CF2
-:1072A000AD2300188DE70020AD27001C8DE20024DF
-:1072B000AD2200208DF90028AD3900243C09800062
-:1072C0003526093C8CCF0000352A0100AD0E0004A4
-:1072D000AD0F00008D4E000C3523090035250980C7
-:1072E000AD0E0008906C00128D47000C8CB9003474
-:1072F0003C18080093183FF8318200FF004D5821D8
-:1073000003277823000B37000018240000C47025E1
-:1073100031E9FFFC01C9682525020014AD0D000C00
-:1073200003E00008AD000010357809009306001254
-:107330003C05080094A53FE830C800FF010D50212E
-:10734000000A60800A00063C0185202115000060CB
-:10735000000000003C08080095083FEE3C060800CD
-:1073600094C63FE8010610213C0B800035790900E6
-:1073700093380011932A001935660A80330800FFFC
-:1073800094CF002A00086082314500FF978A005898
-:10739000000C1E00000524003047FFFF006410258C
-:1073A0000047C02501EA30213C0B4000030B40257B
-:1073B00000066400AD280000AD2C000493250018E1
-:1073C0003C0300062528001400053E0000E31025BC
-:1073D000AD2200088F24002C254F000131EB7FFFE8
-:1073E000AD24000C8F38001CA78B0058AD3800105E
-:1073F0003C0980003526093C8CCF0000352A01006D
-:10740000AD0E0004AD0F00008D4E000C35230900B9
-:1074100035250980AD0E0008906C00128D47000CD8
-:107420008CB900343C18080093183FF8318200FFF3
-:10743000004D582103277823000B37000018240043
-:1074400000C4702531E9FFFC01C96825250200143C
-:10745000AD0D000C03E00008AD0000103C02080078
-:1074600094423FF23C05080094A53FE835440AA445
-:107470003C07080094E73FE4948B00000045C821D6
-:107480000327C023000B1C002706FFF200665025CF
-:10749000AD2A000CAD200010AD2C00140A000630FF
-:1074A00025290018354F0AA495E5000095640028A9
-:1074B0000005140000043C003459810000EC5825FC
-:1074C000AD39000CAD2B00100A0006302529001440
-:1074D0003C0C0800958C3FEE0A00068625820001D0
-:1074E0005460FF4C240A080035580AA4970600008F
-:1074F00000061C00006C5025AD2A000C0A00063066
-:10750000252900103C03080094633FF23C07080063
-:1075100094E73FE83C0F080095EF3FE494A4000097
-:107520009579002800671021004F582300041C00A3
-:10753000001934002578FFEE00D87825346A8100E0
-:10754000AD2A000CAD2F0010AD200014AD2C00189A
-:107550000A0006302529001C03E00008240207D099
-:1075600027BDFFE0AFB20018AFB10014AFB00010FC
-:10757000AFBF001C0E00007C008088218F88005463
-:107580008F87004C3C05800834B20080011128210F
-:107590003C10800024020080240300C000A72023A8
-:1075A000AE0208183C068008AE03081C18800004D0
-:1075B000AF850054ACC500048CC90004AF89004CF1
-:1075C00012200009360409800E00070200000000A6
-:1075D000924C00278E0B007401825004014B302125
-:1075E000AE46000C360409808C8E001C8F8F005C28
-:1075F00001CF682319A000048FBF001C8C90001CD1
-:10760000AF90005C8FBF001C8FB200188FB10014C8
-:107610008FB000100A00007E27BD00208F8600502A
-:107620008F8300548F82004C3C05800834A4008076
-:10763000AC860050AC83003C03E00008ACA2000420
-:107640003C0308008C63005427BDFFF8308400FF22
-:107650002462000130A500FF3C010800AC22005468
-:1076600030C600FF3C0780008CE801780500FFFE73
-:107670003C0C7FFFA3A400038FAA0000358BFFFF03
-:10768000014B4824000627C001244025AFA8000074
-:1076900034E201009043000AA3A000023C1980FFDD
-:1076A000A3A300018FAF000030AE007F3738FFFF8B
-:1076B00001F86024000E6E003C0A002034E5014011
-:1076C000018D5825354920002406FF803C04100018
-:1076D00027BD0008ACAB000CACA90014A4A0001896
-:1076E000A0A6001203E00008ACE40178308800FF97
-:1076F00030A700FF3C0380008C6201780440FFFE4D
-:107700003C0C8000358A0A008D4B002035840140F6
-:1077100035850980AC8B00048D4900240007302B8F
-:1077200000061540AC890008A088001090A3004C0A
-:10773000A083002D03E00008A480001827BDFFE807
-:10774000308400FFAFBF00100E00076730A500FFB8
-:107750008F8300548FBF00103C06800034C5014069
-:10776000344700402404FF903C02100027BD00185D
-:10777000ACA3000CA0A40012ACA7001403E0000806
-:10778000ACC2017827BDFFE03C088008AFBF001CF9
-:10779000AFB20018AFB10014AFB0001035100080C8
-:1077A0008E0600183C078000309200FF00C720259D
-:1077B000AE0400180E00007C30B100FF92030005FB
-:1077C000346200080E00007EA20200050240202163
-:1077D0000E00077B02202821024020218FBF001CC1
-:1077E0008FB200188FB100148FB00010240500056F
-:1077F000240600010A00073C27BD00203C0580004C
-:1078000034A309809066000830C200081040000FC1
-:107810003C0A01013549080AAC8900008CA80074B3
-:10782000AC8800043C07080090E73FF830E5001002
-:1078300050A00008AC8000083C0D800835AC0080EA
-:107840008D8B0058AC8B00082484000C03E00008EA
-:10785000008010210A0007BF2484000C27BDFFE828
-:107860003C098000AFB00010AFBF0014352609807E
-:1078700090C800092402000600A05821310300FF2F
-:107880003527090000808021240500041062007B58
-:107890002408000294CF005C3C0E020431EDFFFF8F
-:1078A00001AE6025AE0C000090CA000831440020F3
-:1078B000108000080000000090C2004E3C1F010331
-:1078C00037F90300305800FF03193025240500085C
-:1078D000AE06000490F9001190E6001290E4001149
-:1078E000333800FF0018708230CF00FF01CF5021E5
-:1078F000014B6821308900FF31AAFFFF392300289E
-:10790000000A60801460002C020C482390E40012EE
-:107910003C198000372F0100308C00FF018B1821AB
-:10792000000310800045F821001F8400360706FF81
-:10793000AD270004373F090093EC001193EE0012CD
-:10794000372609800005C0828DE4000C8CC5003408
-:1079500031CD00FF01AB10210058182100A4F823FD
-:107960000008840000033F0000F0302533F9FFFFDA
-:10797000318F00FC00D970250158202101E96821D0
-:1079800000045080ADAE000C0E00007C012A802166
-:107990003C088008240B0004350500800E00007EA2
-:1079A000A0AB0009020010218FBF00148FB000109F
-:1079B00003E0000827BD001890EC001190E30019C7
-:1079C0003C18080097183FEE318200FF0002F88251
-:1079D000307000FF001FCE0000103C000327302550
-:1079E00000D870253C0F400001CF68253C1980006D
-:1079F000AD2D0000373F090093EC001193EE00120B
-:107A0000372F0100372609800005C0828DE4000C65
-:107A10008CC5003431CD00FF01AB10210058182176
-:107A200000A4F8230008840000033F0000F0302584
-:107A300033F9FFFF318F00FC00D970250158202158
-:107A400001E9682100045080ADAE000C0E00007CFE
-:107A5000012A80213C088008240B000435050080A1
-:107A60000E00007EA0AB0009020010218FBF0014A1
-:107A70008FB0001003E0000827BD00180A0007D1EE
-:107A80002408001227BDFFD03C038000AFB60028B9
-:107A9000AFB50024AFB40020AFB10014AFBF002CCD
-:107AA000AFB3001CAFB20018AFB0001034670100D4
-:107AB00090E6000B309400FF30B500FF30C200307C
-:107AC0000000B02110400099000088213464098032
-:107AD0009088000800082E0000051E03046000C006
-:107AE000240400048F8600543C010800A0243FF8C1
-:107AF0003C0C8000AD8000483C048000348E0100C6
-:107B000091CD000B31A5002010A000073C0780009C
-:107B100034930980927200080012860000107E03E0
-:107B200005E000C43C1F800834EC0100918A000B82
-:107B300034EB098091690008314400400004402B77
-:107B40003123000800C898231460000224120003A7
-:107B5000000090213C10800036180A80360409008D
-:107B6000970E002C90830011908900129305001845
-:107B7000307F00FF312800FF024810210002C8803A
-:107B8000930D0018033F782101F1302130B100FF3F
-:107B900000D11821A78E00583C010800A4263FEE12
-:107BA0003C010800A4233FF015A0000200000000E3
-:107BB0000000000D920B010B3065FFFF3C01080037
-:107BC000A4233FF2316A00403C010800A4203FE8B2
-:107BD0003C010800A4203FE41140000224A4000A54
-:107BE00024A4000B3091FFFF0E0001E702202021AA
-:107BF0009206010B3C0C0800958C3FF200402021BE
-:107C00000006698231A700010E00060101872821C4
-:107C100000402021026028210E00060C0240302185
-:107C20000E0007AB0040202116C000690040202153
-:107C30009212010B3256004012C000053C0500FFB5
-:107C40008C93000034AEFFFF026E8024AC900000E5
-:107C50000E0001FB022020213C0F080091EF3FF8AD
-:107C600031F10003122000163C1380088F8200546B
-:107C70003C09800835280080245F0001AD1F003CCE
-:107C80003C0580088CB9000403E02021033FC02399
-:107C90001B000002AF9F00548CA400040E000702DA
-:107CA000ACA400043C0780008CEB00743C0480080A
-:107CB00034830080004B5021AC6A000C3C138008D8
-:107CC000367000800280202102A02821A200006BD3
-:107CD0000E0007673C1480008F920054368C0140E0
-:107CE000AD92000C8F8600483C151000344D000604
-:107CF00024D60001AF9600488FBF002CA186001249
-:107D00008FB60028AD8D00148FB3001CAE9501789E
-:107D10008FB200188FB500248FB400208FB10014EB
-:107D20008FB0001003E0000827BD003034640980E4
-:107D3000908F0008000F7600000E6E0305A0003340
-:107D4000347F090093F8001B241900103C0108003F
-:107D5000A0393FF8331300021260FF678F8600548A
-:107D60008F8200601446FF653C0480000E00007C9A
-:107D7000000000003C0480083485008090A80009C1
-:107D800024060016310300FF1066000D00000000FD
-:107D900090AB00093C07080090E73FF82409000871
-:107DA000316400FF34EA00013C010800A02A3FF8DA
-:107DB0001089002F240C000A108C00282402000CCB
-:107DC0000E00007E000000000A00086A8F86005442
-:107DD0000E0007C3024028210A0008B800402021F5
-:107DE0003C0B8008356A00808D4600548CE9000CFD
-:107DF0001120FF3DAF860054240700143C01080009
-:107E0000A0273FF80A0008693C0C80009091000808
-:107E1000241200023C010800A0323FF8323000205A
-:107E20001200000B241600018F8600540A00086A15
-:107E30002411000837F800808F020038AFE20004F8
-:107E40008FF90004AF19003C0A0008763C07800057
-:107E50008F8600540A00086A24110004A0A20009B9
-:107E60000E00007E000000000A00086A8F860054A1
-:107E7000240200140A000944A0A2000927BDFFE85B
-:107E8000AFB000103C108000AFBF001436020100FC
-:107E9000904400090E000767240500013C04800897
-:107EA0009099000E34830080909F000F906F002601
-:107EB0009089000A33F800FF00196E000018740062
-:107EC00031EC00FF01AE5025000C5A00014B382563
-:107ED000312800FF360301403445600000E83025BA
-:107EE0002402FF813C041000AC66000C8FBF00141C
-:107EF000AC650014A0620012AE0401788FB00010CF
-:107F000003E0000827BD001827BDFFE8308400FF0C
-:107F1000AFBF00100E00076730A500FF3C058000D2
-:107F200034A40140344700402406FF92AC8700147B
-:107F3000A08600128F8300548FBF00103C021000F7
-:107F400027BD0018AC83000C03E00008ACA2017848
-:107F500027BDFFD8AFB00010308400FF30B000FF65
-:107F60003C058000AFB10014AFBF0020AFB3001CD0
-:107F7000AFB20018000410C234A6010032030002A0
-:107F8000305100011460000790D200093C098008BC
-:107F900035330080926800053107000810E0000CBE
-:107FA000308A0010024020210E00078D0220282177
-:107FB000240200018FBF00208FB3001C8FB2001875
-:107FC0008FB100148FB0001003E0000827BD002817
-:107FD0001540003434A50A008CB800248CAF00088A
-:107FE000130F004B000038213C0D800835B3008092
-:107FF000926C006824060002318B00FF1166008439
-:108000003C06800034C201009263004C9059000984
-:10801000307F00FF53F900043213007C10E0006948
-:10802000000000003213007C5660005C02402021FA
-:1080300016200009320D00013C0C8000358401003F
-:10804000358B0A008D6500248C86000414A6FFD9A8
-:1080500000001021320D000111A0000E024020216D
-:108060003C188000371001008E0F000C8F8E0050DE
-:1080700011EE0008000000000E00084D022028212B
-:108080008E19000C3C1F800837F00080AE1900509C
-:10809000024020210E00077B022028210A000999B6
-:1080A000240200013C0508008CA5006424A4000102
-:1080B0003C010800AC2400641600000D0000000024
-:1080C000022028210E00077B02402021926E0068CA
-:1080D000240C000231CD00FF11AC0022024020210F
-:1080E0000E00094B000000000A000999240200015B
-:1080F0000E00007024040001926B0025020B302555
-:108100000E00007EA26600250A0009DD022028215B
-:108110008E6200188CDF00048CB9002400021E025D
-:1081200017F9FFB13065007F9268004C26440001CA
-:108130003093007F12650040310300FF1464FFABF1
-:108140003C0D80082647000130F1007F30E200FF3F
-:108150001225000B24070001004090210A0009A607
-:1081600024110001240500040E00073C2406000130
-:108170000E00094B000000000A00099924020001CA
-:108180002405FF800245202400859026324200FF0E
-:10819000004090210A0009A6241100010E00084D9C
-:1081A000022028213207003010E0FFA132100082A7
-:1081B000024020210E00078D022028210A00099983
-:1081C000240200018E69001802402021022028218B
-:1081D000012640250E00096EAE6800189264004C1E
-:1081E00024050003240600010E00073C308400FF34
-:1081F0000E00007024040001927100250211502528
-:108200000E00007EA26A00250A00099924020001DE
-:108210008E6F00183C1880000240202101F8702564
-:10822000022028210E00077BAE6E00189264004CDD
-:108230000A000A2524050004324A008039490080DA
-:108240001469FF6A3C0D80080A0009FE26470001F8
-:1082500027BDFFC0AFB000183C108000AFBF003892
-:10826000AFB70034AFB60030AFB5002CAFB40028C4
-:10827000AFB30024AFB200200E0005BEAFB1001CAA
-:10828000360201009045000B0E0009809044000862
-:10829000144000E78FBF00383C0880083507008095
-:1082A000A0E0006B3606098090C500002403005052
-:1082B0003C17080026F73FB030A400FF3C1308002D
-:1082C00026733FC0108300033C1080000000B821DB
-:1082D00000009821241F00103611010036120A00F8
-:1082E000361509808E5800248E3400048EAF00208D
-:1082F0008F8C00543C010800A03F3FF836190A80DB
-:10830000972B002C8EF60000932A001802987023F9
-:1083100001EC68233C010800AC2E3FD43C0108006E
-:10832000AC2D3FD83C010800AC2C3FFCA78B00587B
-:1083300002C0F809315400FF30490002152000E95D
-:1083400030420001504000C49227000992A9000861
-:108350003128000815000002241500030000A821A0
-:108360003C0A80003543090035440A008C8D002406
-:108370009072001190700012907F0011325900FF2E
-:10838000321100FF02B110210002C08033EF00FF64
-:108390000319B021028F702102D4602125CB001077
-:1083A0003C010800A4363FEE3C010800AC2D400023
-:1083B0003C010800A42C3FF03C010800A42B3FEC3A
-:1083C000355601003554098035510E008F87005411
-:1083D0008F89005C8E850020240800060127302349
-:1083E0003C010800AC283FF400A7282304C000B5D6
-:1083F0000000902104A000B300C5502B114000B52F
-:10840000000000003C010800AC263FD88E6200004E
-:108410000040F809000000003046000214C000745B
-:1084200000408021304B0001556000118E62000435
-:108430003C0D08008DAD3FDC3C0EC0003C048000CC
-:1084400001AE6025AE2C00008C980000330F0008B0
-:1084500011E0FFFD00000000963F0008241200011B
-:10846000A79F00408E390004AF9900388E62000447
-:108470000040F809000000000202802532030002DB
-:10848000146000B3000000003C09080095293FE497
-:108490003C06080094C63FF03C0A0800954A3FE6B7
-:1084A0003C0708008CE73FDC012670213C030800F4
-:1084B0008C6340003C08080095083FFA01CA20215F
-:1084C0008ED9000C00E92821249F000200A8782101
-:1084D0000067C02133E4FFFFAF9900503C01080062
-:1084E000AC3840003C010800A42F3FE83C010800E4
-:1084F000A42E3FF20E0001E7000000008F8D00481F
-:10850000004020213C010800A02D3FF98E620008A8
-:1085100025AC0001AF8C00480040F80900000000C5
-:108520008F85005402A030210E00060C004020214F
-:108530000E0007AB004020218E6B000C0160F80993
-:10854000004020213C0A0800954A3FF23C06080002
-:1085500094C63FE601464821252800020E0001FB93
-:108560003104FFFF3C0508008CA53FD43C07080000
-:108570008CE73FDC00A720233C010800AC243FD45B
-:1085800014800006000000003C0208008C423FF40A
-:10859000344B00403C010800AC2B3FF41240004338
-:1085A0008F8E00448E2D00108F920044AE4D00201F
-:1085B0008E2C0018AE4C00243C04080094843FE844
-:1085C0000E000704000000008F9F00548E6700100B
-:1085D0003C010800AC3F3FFC00E0F809000000004F
-:1085E0003C1908008F393FD41720FF798F8700543A
-:1085F000979300583C11800E321601000E0007338D
-:10860000A633002C16C00045320300105460004C05
-:108610008EE50004320800405500001D8EF0000871
-:108620008EE4000C0080F809000000008FBF0038C5
-:108630008FB700348FB600308FB5002C8FB4002870
-:108640008FB300248FB200208FB1001C8FB00018B0
-:1086500003E0000827BD00408F86003C36110E0065
-:1086600000072E0000A62025AE0400808E430020C7
-:108670008E500024AFA30010AE2300148FB2001060
-:10868000AE320010AE30001C0A000A7FAE30001877
-:108690000200F809000000008EE4000C0080F809D8
-:1086A000000000000A000B388FBF003824180001BA
-:1086B000240F0001A5C00020A5D800220A000B1A33
-:1086C000ADCF00243C010800AC203FD80A000AB01E
-:1086D0008E6200003C010800AC253FD80A000AB0B9
-:1086E0008E620000922400090E00077B0000282102
-:1086F0008FBF00388FB700348FB600308FB5002C95
-:108700008FB400288FB300248FB200208FB1001CDB
-:108710008FB0001803E0000827BD00403C14800023
-:1087200092950109000028210E00084D32A400FF97
-:10873000320300105060FFB8320800408EE500049C
-:1087400000A0F809000000000A000B3232080040C7
-:108750005240FFA8979300588E3400148F93004422
-:10876000AE7400208E35001CAE7500240A000B2963
-:10877000979300588F8200140004218003E00008C2
-:10878000008210213C07800834E200809043006999
-:1087900000804021106000093C0401003C070800F3
-:1087A0008CE73FFC8F83003000E320230480000827
-:1087B0009389001C14E300030100202103E000085A
-:1087C000008010213C04010003E00008008010211B
-:1087D0001120000B006738233C0D800035AC098068
-:1087E000918B007C316A0002114000202409003482
-:1087F00000E9702B15C0FFF10100202100E93823AA
-:108800002403FFFC00A3C82400E3C02400F9782B54
-:1088100015E0FFEA0308202130C400030004102300
-:1088200014C00014304900030000302100A9782151
-:1088300001E6702100EE682B11A0FFE03C0401006E
-:108840002D3800010006C82B0105482103193824E2
-:1088500014E0FFDA2524FFFC2402FFFC00A2182408
-:108860000068202103E00008008010210A000BA806
-:10887000240900303C0C80003586098090CB007CB8
-:10888000316A00041540FFE9240600040A000BB712
-:10889000000030213C0308008C63005C8F820018CC
-:1088A00027BDFFE0AFBF0018AFB100141062000594
-:1088B000AFB00010000329C024A40280AF840014CC
-:1088C000AF8300183C10800036020A009445003245
-:1088D000361101000E000B8930A43FFF8E240000EA
-:1088E000241FFF803C1100800082C021031F6024F0
-:1088F0003309007F000CC94003294025330E00785E
-:10890000362F00033C0D1000010D502501CF5825D6
-:10891000AE0C002836080980AE0C080CAE0B082CF3
-:10892000AE0A0830910300693C06800C012638210C
-:1089300010600006AF8700348D09003C8D03006C89
-:108940000123382318E00082000000003C0B80085F
-:10895000356A00803C108000A1400069360609801D
-:108960008CC200383C06800034C50A0090A8003C48
-:10897000310C00201180001AAF820030240D00015C
-:108980003C0E800035D10A00A38D001CAF8000246E
-:108990008E2400248F850024240D0008AF80002041
-:1089A000AF8000283C010800A42D3FE63C010800F0
-:1089B000A4203FFA0E000B8D000030219228003CCD
-:1089C0008FBF00188FB100148FB0001000086142F3
-:1089D000AF82002C27BD002003E000083182000197
-:1089E00090B80032240E0001330F00FF000F2182E7
-:1089F000108E0041241900021099006434C40AC08A
-:108A00003C03800034640A008C8F002415E0001EB3
-:108A100034660900909F00302418000533F9003FA8
-:108A20001338004E240300018F860020A383001C0E
-:108A3000AF860028AF8600243C0E800035D10A00A6
-:108A40008E2400248F850024240D00083C0108009A
-:108A5000A42D3FE63C010800A4203FFA0E000B8D38
-:108A6000000000009228003C8FBF00188FB1001456
-:108A70008FB0001000086142AF82002C27BD00209B
-:108A800003E00008318200018C8A00088C8B0024EE
-:108A90008CD000643C0E800035D10A00014B2823A5
-:108AA000AF900024A380001CAF8500288E240024F2
-:108AB0008F8600208F850024240D00083C010800CB
-:108AC000A42D3FE63C010800A4203FFA0E000B8DC8
-:108AD000000000009228003C8FBF00188FB10014E6
-:108AE0008FB0001000086142AF82002C27BD00202B
-:108AF00003E000083182000190A200303051003FB5
-:108B00005224002834C50AC08CB00024160000226C
-:108B100034CB09008CA600483C0A7FFF3545FFFF97
-:108B200000C510243C0E8000AF82002035C509002E
-:108B30008F8800208CAD0060010D602B1580000235
-:108B4000010020218CA400600A000C2CAF840020BE
-:108B50008D02006C0A000C063C0680008C820048E6
-:108B60008F8600203C097FFF3527FFFF00478824C0
-:108B70003C04800824030001AF910028AC80006C05
-:108B8000A383001C0A000C3AAF8600248C9F0014BB
-:108B90000A000C2CAF9F00208D6200680A000C7642
-:108BA0003C0E800034C409808C8900708CA30014B2
-:108BB0000123382B10E00004000000008C820070BC
-:108BC0000A000C763C0E80008CA200140A000C7681
-:108BD0003C0E80008F85002427BDFFE0AFBF00184A
-:108BE000AFB1001414A00008AFB000103C04800026
-:108BF00034870A0090E600302402000530C3003FAD
-:108C0000106200B9348409008F91002000A08021F7
-:108C10003C048000348E0A008DCD00043C06080020
-:108C20008CC63FD831A73FFF00E6602B558000017E
-:108C300000E03021938F001C11E0007800D0282B39
-:108C4000349F098093F9007C3338000213000079C7
-:108C50002403003400C3102B144000D9000000008E
-:108C600000C3302300D0282B3C010800A4233FE49C
-:108C700014A0006E020018213C0408008C843FD42C
-:108C80000064402B55000001006020213C0580005D
-:108C900034A90A00912A003C3C010800AC243FDCC6
-:108CA00031430020146000030000482134AB0E0063
-:108CB0008D6900188F88002C0128202B1080005F00
-:108CC000000000003C0508008CA53FDC00A96821DD
-:108CD000010D602B1180005C00B0702B010938235E
-:108CE00000E028213C010800AC273FDC1200000313
-:108CF000240AFFFC10B0008D3224000300AA1824BF
-:108D00003C010800A4203FFA3C010800AC233FDCF2
-:108D1000006028218F840024120400063C0B800888
-:108D20008D6C006C02002021AF9100202590000185
-:108D3000AD70006C8F8D002800858823AF910024D2
-:108D400001A52023AF840028122000022407001868
-:108D5000240700103C1880083706008090CF006878
-:108D60003C010800A0273FF82407000131EE00FF76
-:108D700011C70047000000001480001800002821DF
-:108D80003C06800034D1098034CD010091A6000951
-:108D90008E2C001824C40001000C86023205007FCE
-:108DA000308B007F1165007F2407FF803C1980080D
-:108DB00037290080A124004C3C0808008D083FF4AE
-:108DC000241800023C010800A0384039350F000883
-:108DD0003C010800AC2F3FF4240500103C02800049
-:108DE00034440A009083003C307F002013E00005EB
-:108DF00000A02021240A00013C010800AC2A3FDC2D
-:108E000034A400018FBF00188FB100148FB0001080
-:108E10000080102103E0000827BD00203C0108006D
-:108E2000A4203FE410A0FF94020018210A000CCAFD
-:108E300000C018210A000CC1240300303C050800C2
-:108E40008CA53FDC00B0702B11C0FFA80000000013
-:108E50003C19080097393FE40325C0210307782B0C
-:108E600011E000072CAA00043C0360008C6254044B
-:108E7000305F003F17E0FFE3240400422CAA000407
-:108E80001140FF9A240400420A000D2E8FBF0018E3
-:108E90001528FFB9000000008CCA00183C1F800094
-:108EA00024020002015F1825ACC3001837F90A003C
-:108EB000A0C200689329003C2404000400A01021F3
-:108EC000312800203C010800A02440391100000294
-:108ED00024050010240200013C010800AC223FD40C
-:108EE0000A000D243C0280008F8800288C890060D5
-:108EF0000109282B14A00002010088218C91006038
-:108F00003C048000348B0E008D640018240A00019C
-:108F10000220282102203021A38A001C0E000B8D84
-:108F2000022080210A000CB0AF82002C00045823DC
-:108F300012200007316400033C0E800035C7098011
-:108F400090ED007C31AC000415800019248F0004E2
-:108F50003C010800A4243FFA3C1F080097FF3FFA99
-:108F600003E5C82100D9C02B1300FF6B8F840024B8
-:108F70002CA6000514C0FFA32404004230A2000365
-:108F80001440000200A2182324A3FFFC3C010800A7
-:108F9000AC233FDC3C010800A4203FFA0A000CF19E
-:108FA0000060282100C770240A000D1701C7202681
-:108FB0003C010800A42F3FFA0A000D8200000000C7
-:108FC0003C010800AC203FDC0A000D2D24040042C7
-:108FD0008F8300283C05800034AA0A001460000634
-:108FE00000001021914700302406000530E400FF06
-:108FF000108600030000000003E0000800000000ED
-:10900000914B0048316900FF000941C21500FFFA89
-:109010003C0680083C04080094843FE43C030800BC
-:109020008C633FFC3C1908008F393FDC3C0F080083
-:1090300095EF3FFA0064C0218CCD00040319702124
-:1090400001CF602134AB0E00018D282318A0001D34
-:1090500000000000914F004C8F8C0034956D001083
-:1090600031EE00FF8D89000401AE30238D8A0000AF
-:1090700030CEFFFF000E29000125C8210000382155
-:10908000014720210325182B0083C021AD9900043E
-:10909000AD980000918F000A01CF6821A18D000AD0
-:1090A000956500128F8A0034A5450008954B00385D
-:1090B00025690001A54900389148000D35070008D1
-:1090C000A147000D03E000080000000027BDFFD805
-:1090D000AFB000189388001C8FB000143C0A8000C9
-:1090E0003C197FFF8F8700243738FFFFAFBF002078
-:1090F000AFB1001C355F0A000218182493EB003C46
-:1091000000087FC03C02BFFF006F60252CF000010B
-:109110003449FFFF3C1F08008FFF3FFC8F99003050
-:109120003C18080097183FF2018978240010478006
-:109130003C07EFFF3C05F0FF01E818253C118000DB
-:109140003169002034E2FFFF34ADFFFF362E098085
-:1091500027A500102406000203F96023270B000254
-:10916000354A0E000062182400808021152000027C
-:10917000000040218D48001CA7AB0012058000397B
-:109180002407000030E800FF00083F000067582572
-:109190003C028008AFAB0014344F008091EA0068B5
-:1091A0003C08080091083FF93C09DFFF352CFFFF20
-:1091B000000AF82B3C02080094423FECA3A80011DF
-:1091C000016CC024001FCF40031918258FA7001081
-:1091D000AFA300143C0C0800918C3FFBA7A2001623
-:1091E0008FAB001400ED48243C0F01003C0A0FFF38
-:1091F000012FC82531980003355FFFFF016D402422
-:109200003C027000033F382400181E0000E248258D
-:1092100001037825AFAF0014AFA9001091CC007CFA
-:109220000E000092A3AC0015362D0A0091A6003C5A
-:1092300030C4002010800006260200083C110800FF
-:1092400096313FE8262EFFFF3C010800A42E3FE8A0
-:109250008FBF00208FB1001C8FB0001803E0000802
-:1092600027BD00288F8B002C010B502B5540FFC5CC
-:10927000240700010A000E0E30E800FF9383001C53
-:109280003C02800027BDFFD834480A0000805021EE
-:10929000AFBF002034460AC0010028211060000E34
-:1092A0003444098091070030240B00058F89002089
-:1092B00030EC003F118B000B00003821AFA90010EB
-:1092C0003C0B80088D69006CAFAA00180E00015A93
-:1092D000AFA90014A380001C8FBF002003E000088A
-:1092E00027BD00288D1F00483C1808008F183FDC60
-:1092F0008F9900283C027FFF8D0800443443FFFF14
-:10930000AFA900103C0B80088D69006C03E370244A
-:109310000319782101CF682301A83821AFAA0018CA
-:109320000E00015AAFA900140A000E62A380001CAF
-:109330003C05800034A60A0090C7003C3C060800AB
-:1093400094C63FFA3C0208008C423FF430E3002010
-:10935000000624001060001E004438253C088008E8
-:109360003505008090A30068000048212408000112
-:1093700000002821240400013C0680008CCD0178E7
-:1093800005A0FFFE34CF0140ADE800083C02080014
-:109390008C423FFCA5E50004A5E40006ADE2000C0C
-:1093A0003C04080090843FF93C0380083479008035
-:1093B000A1E40012ADE70014A5E900189338004CB1
-:1093C0003C0E1000A1F8002D03E00008ACCE01789F
-:1093D00034A90E008D28001C3C0C08008D8C3FDC4D
-:1093E000952B0016952A0014018648213164FFFF51
-:1093F0000A000E8A3145FFFF3C04800034830A00D6
-:109400009065003C30A200201040001934870E0007
-:109410000000402100003821000020213C0680008F
-:109420008CC901780520FFFE34CA014034CF010009
-:1094300091EB0009AD4800083C0E08008DCE3FFCC2
-:10944000240DFF91240C00403C081000A5440004AA
-:10945000A5470006AD4E000CA14D0012AD4C001406
-:10946000A5400018A14B002D03E00008ACC801780E
-:109470008CE8001894E6001294E4001030C7FFFF57
-:109480000A000EB33084FFFF3C04800034830A00DE
-:109490009065003C30A200201040002727BDFFF857
-:1094A0002409000100003821240800013C06800046
-:1094B0008CCA01780540FFFE3C0280FF34C40100E5
-:1094C000908D00093C0C0800918C4039A3AD00033D
-:1094D0008FAB00003185007F3459FFFF01665025B6
-:1094E000AFAA00009083000AA3A0000200057E003E
-:1094F000A3A300018FB8000034CB0140240C30003E
-:109500000319702401CF6825AD6D000C27BD00083C
-:10951000AD6C0014A5600018AD690008A5670004D3
-:109520002409FF80A56800063C081000A16900120C
-:1095300003E00008ACC8017834870E008CE90018FD
-:1095400094E6001294E4001030C8FFFF0A000ED722
-:109550003087FFFF27BDFFE0AFB100143C11800052
-:10956000AFB00010AFBF001836380A00970F0032B6
-:10957000363001000E000B8931E43FFF8E0E0000F3
-:10958000240DFF803C04200001C25821016D60249D
-:10959000000C4940316A007F012A4025010438252A
-:1095A0003C048008AE2708303486008090C50068EF
-:1095B0002403000230A200FF104300048F9F00200C
-:1095C0008F990024AC9F0068AC9900648FBF00188D
-:1095D0008FB100148FB0001003E0000827BD0020F9
-:1095E0003C0A0800254A3AA83C09080025293B38CE
-:1095F0003C08080025082F443C07080024E73C04E9
-:109600003C06080024C6392C3C05080024A53680F9
-:109610003C040800248432843C030800246339E0BD
-:109620003C0208002442377C3C010800AC2A3FB8C9
-:109630003C010800AC293FB43C010800AC283FB015
-:109640003C010800AC273FBC3C010800AC263FCCE5
-:109650003C010800AC253FC43C010800AC243FC0DD
-:109660003C010800AC233FD03C010800AC223FC8BD
-:0896700003E000080000000007
-:08967800800009408000090098
-:10968000800801008008008080080000800E000033
-:10969000800800808008000080000A8080000A00A6
-:0896A000800009808000090030
-:00000001FF
-/*
- * This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2004 - 2009 Broadcom Corporation.
- *
- * Permission is hereby granted for the distribution of this firmware data
- * in hexadecimal or equivalent format, provided this copyright notice is
- * accompanying it.
- */
diff --git a/firmware/bnx2/bnx2-mips-09-6.2.1a.fw.ihex b/firmware/bnx2/bnx2-mips-09-6.2.1a.fw.ihex
new file mode 100644
index 0000000..05e7102
--- /dev/null
+++ b/firmware/bnx2/bnx2-mips-09-6.2.1a.fw.ihex
@@ -0,0 +1,6512 @@
+:10000000080001180800000000005594000000C816
+:1000100000000000000000000000000008005594EF
+:10002000000000380000565C080000A00800000036
+:100030000000574400005694080059200000008436
+:100040000000ADD808005744000001C00000AE5CBD
+:100050000800321008000000000092340000B01CBC
+:1000600000000000000000000000000008009234C2
+:100070000000033C00014250080004900800040006
+:10008000000012FC0001458C000000000000000090
+:1000900000000000080016FC000000040001588861
+:1000A000080000A80800000000003D000001588C76
+:1000B00000000000000000000000000008003D00FB
+:0800C000000000300001958CE6
+:0800C8000A00004600000000E0
+:1000D000000000000000000D636F6D362E322E31DF
+:1000E00061000000060201020000000000000003A1
+:1000F000000000C800000032000000030000000003
+:1001000000000000000000000000000000000000EF
+:1001100000000010000001360000EA600000000549
+:1001200000000000000000000000000000000008C7
+:1001300000000000000000000000000000000000BF
+:1001400000000000000000000000000000000000AF
+:10015000000000000000000000000000000000009F
+:10016000000000020000000000000000000000008D
+:10017000000000000000000000000000000000007F
+:10018000000000000000000000000010000000005F
+:10019000000000000000000000000000000000005F
+:1001A000000000000000000000000000000000004F
+:1001B000000000000000000000000000000000003F
+:1001C000000000000000000000000000000000002F
+:1001D000000000000000000000000000000000001F
+:1001E0000000000010000003000000000000000DEF
+:1001F0000000000D3C020800244256083C030800A1
+:1002000024635754AC4000000043202B1480FFFDB2
+:10021000244200043C1D080037BD9FFC03A0F021D0
+:100220003C100800261001183C1C0800279C5608AA
+:100230000E000256000000000000000D27BDFFB4B4
+:10024000AFA10000AFA20004AFA30008AFA4000C50
+:10025000AFA50010AFA60014AFA70018AFA8001CF0
+:10026000AFA90020AFAA0024AFAB0028AFAC002C90
+:10027000AFAD0030AFAE0034AFAF0038AFB8003C28
+:10028000AFB90040AFBC0044AFBF00480E001544FA
+:10029000000000008FBF00488FBC00448FB90040B1
+:1002A0008FB8003C8FAF00388FAE00348FAD003078
+:1002B0008FAC002C8FAB00288FAA00248FA90020C0
+:1002C0008FA8001C8FA700188FA600148FA5001000
+:1002D0008FA4000C8FA300088FA200048FA1000040
+:1002E00027BD004C3C1B60108F7A5030377B502864
+:1002F00003400008AF7A00008F82002427BDFFE092
+:10030000AFB00010AFBF0018AFB100148C42000CAA
+:100310003C1080008E110100104000348FBF001887
+:100320000E000D84000000008F85002024047FFF54
+:100330000091202BACB100008E030104960201084D
+:1003400000031C003042FFFF00621825ACA300042C
+:100350009202010A96030114304200FF3063FFFF4E
+:100360000002140000431025ACA200089603010C03
+:100370009602010E00031C003042FFFF00621825A8
+:10038000ACA3000C960301109602011200031C009E
+:100390003042FFFF00621825ACA300108E02011846
+:1003A000ACA200148E02011CACA20018148000083C
+:1003B0008F820024978200003C0420050044182509
+:1003C00024420001ACA3001C0A0000C6A782000062
+:1003D0003C0340189442001E00431025ACA2001CB0
+:1003E0000E000DB8240400018FBF00188FB1001457
+:1003F0008FB000100000102103E0000827BD00208E
+:100400003C0780008CE202B834E50100044100089A
+:10041000240300013C0208008C42006024420001D9
+:100420003C010800AC22006003E0000800601021DD
+:100430003C0208008C42005C8CA4002094A30016AF
+:100440008CA6000494A5000E24420001ACE40280B6
+:100450002463FFFC3C010800AC22005C3C0210005D
+:10046000A4E30284A4E5028600001821ACE6028819
+:10047000ACE202B803E000080060102127BDFFE0F5
+:100480003C028000AFB0001034420100AFBF001C3E
+:10049000AFB20018AFB100148C43000094450008BF
+:1004A0002462FE002C42038110400003000381C23D
+:1004B0000A00010226100004240201001462000553
+:1004C0003C1180003C02800890420004305000FF44
+:1004D0003C11800036320100964300143202000FB6
+:1004E00000021500004310253C0308008C63004403
+:1004F00030A40004AE220080246300013C01080007
+:10050000AC2300441080000730A200028FBF001C03
+:100510008FB200188FB100148FB000100A0000CE07
+:1005200027BD00201040002D0000182130A20080BF
+:1005300010400005362200708E44001C0E000C672F
+:10054000240500A0362200708C4400008F82000C2D
+:10055000008210232C43012C10600004AF82001095
+:10056000240300010A000145AF84000C8E42000400
+:100570003C036020AF84000CAC6200143C02080015
+:100580008C42005850400015000018218C62000475
+:10059000240301FE304203FF144300100000182121
+:1005A0002E020004104000032E0200080A00014041
+:1005B0000000802114400003000000000A000140F8
+:1005C0002610FFF90000000D2402000202021004B0
+:1005D0003C036000AC626914000018218FBF001C4E
+:1005E0008FB200188FB100148FB00010006010217E
+:1005F00003E0000827BD00203C0480008C8301003C
+:1006000024020100506200033C0280080000000D3B
+:100610003C02800890430004000010213063000F6A
+:1006200000031D0003E00008AC8300800004188074
+:100630002782FF9C00621821000410C00044102390
+:100640008C640000000210C03C030800246356E4E0
+:10065000004310213C038000AC64009003E00008DC
+:10066000AF8200243C0208008C42011410400019A3
+:100670003084400030A2007F000231C03C02020002
+:100680001080001400A218253C026020AC43001426
+:100690003C0408008C8456B83C0308008C630110AD
+:1006A0003C02800024050900AC4500200086202182
+:1006B000246300013C028008AC4400643C01080053
+:1006C000AC2301103C010800AC2456B803E000083C
+:1006D000000000003C02602003E00008AC4500146C
+:1006E00003E000080000102103E0000800001021D2
+:1006F00030A2000810400008240201003C0208005B
+:100700008C42010C244200013C010800AC22010C87
+:1007100003E0000800000000148200080000000050
+:100720003C0208008C4200FC244200013C0108000D
+:10073000AC2200FC0A0001A330A200203C02080009
+:100740008C420084244200013C010800AC22008459
+:1007500030A200201040000830A200103C02080027
+:100760008C420108244200013C010800AC2201082F
+:1007700003E0000800000000104000080000000036
+:100780003C0208008C420104244200013C010800A4
+:10079000AC22010403E00008000000003C02080055
+:1007A0008C420100244200013C010800AC220100FF
+:1007B00003E000080000000027BDFFE0AFB1001417
+:1007C0003C118000AFB20018AFBF001CAFB00010EA
+:1007D0003632010096500008320200041040000733
+:1007E000320300028FBF001C8FB200188FB10014BB
+:1007F0008FB000100A0000CE27BD00201060000B53
+:10080000020028218E2401000E00018A0000000051
+:100810003202008010400003240500A10E000C6786
+:100820008E44001C0A0001E3240200018E2301040F
+:100830008F82000810430006020028218E24010048
+:100840000E00018A000000008E220104AF82000821
+:10085000000010218FBF001C8FB200188FB1001450
+:100860008FB0001003E0000827BD00202C82000498
+:1008700014400002000018212483FFFD240200021E
+:10088000006210043C03600003E00008AC626914DD
+:1008900027BDFFE0AFBF001CAFB20018AFB100141E
+:1008A000AFB000103C048000948201083043700017
+:1008B000240220001062000A2862200154400052E5
+:1008C0008FBF001C24024000106200482402600018
+:1008D0001062004A8FBF001C0A0002518FB200183C
+:1008E00034820100904300098C5000189451000C90
+:1008F000240200091062001C0000902128620009F7
+:10090000144000218F8200242402000A5062001249
+:10091000323100FF2402000B1062000F00000000C3
+:100920002402000C146200188F8200243C0208008C
+:100930008C4256B824030900AC83002000501021DB
+:100940003C038008AC6200643C010800AC2256B84D
+:100950000A0002508FBF001C0E0001E900102602A1
+:100960000A0002308F8200240E0001E900102602E6
+:100970003C0380089462001A8C72000C3042FFFF26
+:10098000020280258F8200248C42000C5040001E01
+:100990008FBF001C0E000D84000000003C02800090
+:1009A00034420100944300088F82002400031C009D
+:1009B0009444001E8F82002000641825AC50000073
+:1009C00024040001AC510004AC520008AC40000CFF
+:1009D000AC400010AC400014AC4000180E000DB844
+:1009E000AC43001C0A0002508FBF001C0E000440E4
+:1009F000000000000A0002508FBF001C0E000C9F78
+:100A0000000000008FBF001C8FB200188FB10014CF
+:100A10008FB000100000102103E0000827BD002067
+:100A200027BDFFD8AFB400203C036010AFBF002447
+:100A3000AFB3001CAFB20018AFB10014AFB00010DC
+:100A40008C6450002402FF7F3C1408002694563822
+:100A5000008220243484380CAC6450003C028000B6
+:100A6000240300370E0014B0AC4300083C07080014
+:100A700024E70618028010212404001D2484FFFFAF
+:100A8000AC4700000481FFFD244200043C02080042
+:100A9000244207C83C010800AC2256403C02080032
+:100AA000244202303C030800246306203C04080072
+:100AB000248403B43C05080024A506F03C06080085
+:100AC00024C62C9C3C010800AC2256803C02080045
+:100AD000244205303C010800AC2756843C01080044
+:100AE000AC2656943C010800AC23569C3C010800FF
+:100AF000AC2456A03C010800AC2556A43C010800DB
+:100B0000AC2256A83C010800AC23563C3C0108002E
+:100B1000AC2456443C010800AC2056603C0108005F
+:100B2000AC2556643C010800AC2056703C0108001E
+:100B3000AC27567C3C010800AC2656903C010800CE
+:100B4000AC2356980E00056E00000000AF80000C2C
+:100B50003C0280008C5300008F8300043C0208009C
+:100B60008C420020106200213262000700008821C0
+:100B70002792FF9C3C100800261056E43C02080017
+:100B80008C42002024050001022518040043202483
+:100B90008F820004004310245044000C26310001D1
+:100BA00010800008AF9000248E4300003C028000BB
+:100BB000AC4300900E000D4BAE05000C0A0002C1C4
+:100BC00026310001AE00000C263100012E22000269
+:100BD000261000381440FFE9265200043C020800A9
+:100BE0008C420020AF820004326200071040FFD91F
+:100BF0003C028000326200011040002D326200028F
+:100C00003C0580008CA2010000002021ACA2002045
+:100C10008CA301042C42078110400008ACA300A85B
+:100C200094A2010824032000304270001443000302
+:100C30003C02800890420005304400FF0E0001593C
+:100C4000000000003C0280009042010B304300FF96
+:100C50002C62001E54400004000310800E00018628
+:100C60000A0002EC00000000005410218C42000039
+:100C70000040F80900000000104000043C02800021
+:100C80008C4301043C026020AC4300143C02080089
+:100C90008C4200343C0440003C03800024420001AC
+:100CA000AC6401383C010800AC220034326200021E
+:100CB00010400010326200043C1080008E0201409F
+:100CC000000020210E000159AE0200200E00038317
+:100CD000000000003C024000AE0201783C02080027
+:100CE0008C420038244200013C010800AC2200384C
+:100CF000326200041040FF973C0280003C108000EC
+:100D00008E020180000020210E000159AE02002059
+:100D10008E03018024020F00546200073C02800809
+:100D20008E0201883C0300E03042FFFF00431025A3
+:100D30000A000328AE020080344200809042000086
+:100D400024030050304200FF14430007000000005D
+:100D50000E000362000000001440000300000000C9
+:100D60000E000971000000003C0208008C42003CAB
+:100D70003C0440003C03800024420001AC6401B804
+:100D80003C010800AC22003C0A0002A33C028000A7
+:100D90003C02900034420001008220253C02800089
+:100DA000AC4400203C0380008C6200200440FFFE25
+:100DB0000000000003E00008000000003C0280008A
+:100DC000344300010083202503E00008AC440020E8
+:100DD00027BDFFE0AFB10014AFB000100080882144
+:100DE000AFBF00180E00033230B000FF8F83FF94B6
+:100DF000022020219062002502028025A07000259B
+:100E00008C7000183C0280000E00033D020280241A
+:100E10001600000B8FBF00183C0480008C8201F884
+:100E20000440FFFE348201C024030002AC510000E4
+:100E3000A04300043C021000AC8201F88FBF0018F0
+:100E40008FB100148FB0001003E0000827BD002010
+:100E500027BDFFE83C028000AFBF00103442018094
+:100E6000944300048C4400083063020010600005C5
+:100E7000000028210E00100C000000000A0003787A
+:100E8000240500013C02FF000480000700821824B2
+:100E90003C02040014620004240500018F82FF94C8
+:100EA00090420008240500018FBF001000A010210F
+:100EB00003E0000827BD00188F82FF982405000179
+:100EC000A040001A3C028000344201400A00034264
+:100ED0008C4400008F85FF9427BDFFE0AFBF001C4E
+:100EE000AFB20018AFB10014AFB0001090A2000074
+:100EF000304400FF38830020388200300003182B74
+:100F00000002102B0062182410600003240200501D
+:100F1000148200A88FBF001C90A20005304200017F
+:100F2000104000A48FBF001C3C02800034420140EE
+:100F3000904200082443FFFF2C6200051040009EF1
+:100F40008FB20018000310803C030800246355ACE6
+:100F5000004310218C420000004000080000000007
+:100F60003C028000345101400E0003328E24000008
+:100F70008F92FF948E2200048E50000C1602000205
+:100F800024020001AE42000C0E00033D8E2400003E
+:100F90008E220004145000068FBF001C8FB2001870
+:100FA0008FB100148FB000100A000F7827BD002009
+:100FB0008E42000C0A000419000000003C0480006E
+:100FC0003482014094A300108C4200043063FFFF80
+:100FD0001443001C0000000024020001A4A2001021
+:100FE0008C8202380441000F3C0380003C02003F29
+:100FF0003448F0003C0760003C06FFC08CE22BBC8C
+:1010000000461824004810240002130200031D8229
+:10101000106200583C0280008C8202380440FFF7C6
+:101020003C038000346201408C44000034620200C2
+:10103000AC4400003C021000AC6202380A00043BE1
+:101040008FBF001C94A200100A00041900000000C9
+:10105000240200201482000F3C0280003C03800028
+:1010600094A20012346301408C6300043042FFFFFD
+:10107000146200050000000024020001A4A2001276
+:101080000A0004028FBF001C94A200120A00041977
+:1010900000000000345101400E0003328E24000095
+:1010A0008F92FF948E230004964200123050FFFF6F
+:1010B0001603000224020001A64200120E00033DA6
+:1010C0008E2400008E220004160200068FBF001C32
+:1010D0008FB200188FB100148FB000100A00037C8B
+:1010E00027BD0020964200120A00041900000000EB
+:1010F0003C03800094A20014346301408C6300041C
+:101100003042FFFF14620008240200018FBF001C60
+:101110008FB200188FB100148FB00010A4A2001479
+:101120000A00146327BD002094A20014144000217B
+:101130008FBF001C0A000435000000003C03800043
+:1011400094A20016346301408C6300043042FFFF18
+:101150001462000D240200018FBF001C8FB2001822
+:101160008FB100148FB00010A4A200160A000B1457
+:1011700027BD00209442007824420004A4A200105D
+:101180000A00043B8FBF001C94A200162403000138
+:101190003042FFFF144300078FBF001C3C020800D1
+:1011A0008C420070244200013C010800AC22007017
+:1011B0008FBF001C8FB200188FB100148FB00010C9
+:1011C00003E0000827BD002027BDFFD8AFB20018FC
+:1011D0008F92FF94AFB10014AFBF0020AFB3001CDB
+:1011E000AFB000103C028000345101008C5001006F
+:1011F0009242000092230009304400FF2402001FA5
+:10120000106200AB28620020104000192402003850
+:101210002862000A1040000D2402000B286200081A
+:101220001040002E8F820024046001042862000216
+:101230001440002A8F820024240200061062002637
+:101240008FBF00200A00055F8FB3001C1062006092
+:101250002862000B144000FA8FBF00202402000E09
+:10126000106200788F8200240A00055F8FB3001C93
+:10127000106200D2286200391040000A2402008067
+:1012800024020036106200E528620037104000C3D7
+:1012900024020035106200D98FBF00200A00055FCC
+:1012A0008FB3001C1062002D2862008110400006E0
+:1012B000240200C824020039106200C98FBF002038
+:1012C0000A00055F8FB3001C106200A28FBF0020D0
+:1012D0000A00055F8FB3001C8F8200248C42000C33
+:1012E000104000D78FBF00200E000D8400000000CA
+:1012F0003C038000346301008C6200008F85002075
+:10130000946700089466000CACA200008C64000492
+:101310008F82002400063400ACA400049448001E10
+:101320008C62001800073C0000E83825ACA20008D9
+:101330008C62001C24040001ACA2000C9062000A24
+:1013400000C23025ACA60010ACA00014ACA0001860
+:10135000ACA7001C0A00051D8FBF00208F8200244F
+:101360008C42000C104000B68FBF00200E000D8490
+:10137000000000008F820024962400089625000CAF
+:101380009443001E000422029626000E8F82002045
+:10139000000426000083202500052C003C0300806B
+:1013A00000A6282500832025AC400000AC400004A6
+:1013B000AC400008AC40000CAC450010AC40001440
+:1013C000AC400018AC44001C0A00051C24040001B9
+:1013D0009622000C14400018000000009242000504
+:1013E0003042001014400014000000000E000332D0
+:1013F0000200202192420005020020213442001008
+:101400000E00033DA242000592420000240300208A
+:10141000304200FF10430089020020218FBF0020CE
+:101420008FB3001C8FB200188FB100148FB0001062
+:101430000A00107527BD00280000000D0A00055E97
+:101440008FBF00208C42000C1040007D8FBF002019
+:101450000E000D84000000008E2200048F84002006
+:101460009623000CAC8200003C0280089445002CBE
+:101470008F82002400031C0030A5FFFF9446001E4D
+:101480003C02400E0065182500C23025AC830004E4
+:10149000AC800008AC80000CAC800010AC80001464
+:1014A000AC800018AC86001C0A00051C2404000156
+:1014B0000E000332020020218F93FF9802002021AA
+:1014C0000E00033DA660000C020020210E00034226
+:1014D000240500018F8200248C42000C104000582B
+:1014E0008FBF00200E000D84000000009622000C2B
+:1014F0008F83002000021400AC700000AC62000476
+:10150000AC6000088E4400388F820024AC64000C6C
+:101510008E46003C9445001E3C02401FAC66001005
+:1015200000A228258E62000424040001AC6200148D
+:10153000AC600018AC65001C8FBF00208FB3001C8E
+:101540008FB200188FB100148FB000100A000DB8D0
+:1015500027BD0028240200201082003A8FB3001C0F
+:101560000E000F5E00000000104000358FBF00200D
+:101570003C0480008C8201F80440FFFE348201C0EC
+:1015800024030002AC500000A04300043C02100001
+:10159000AC8201F80A00055E8FBF00200200202106
+:1015A0008FBF00208FB3001C8FB200188FB10014C2
+:1015B0008FB000100A000EA727BD00289625000C4A
+:1015C000020020218FBF00208FB3001C8FB20018B3
+:1015D0008FB100148FB000100A000ECC27BD002878
+:1015E000020020218FB3001C8FB200188FB10014AD
+:1015F0008FB000100A000EF727BD00289225000DBD
+:10160000020020218FB3001C8FB200188FB100148C
+:101610008FB000100A000F4827BD002802002021CB
+:101620008FBF00208FB3001C8FB200188FB1001441
+:101630008FB000100A000F1F27BD00288FBF0020A9
+:101640008FB3001C8FB200188FB100148FB0001040
+:1016500003E0000827BD00283C0580008CA202782A
+:101660000440FFFE34A2024024030002AC44000008
+:10167000A04300043C02100003E00008ACA2027882
+:10168000A380001803E00008A38000193C03800039
+:101690008C6202780440FFFE8F82001CAC62024024
+:1016A00024020002A06202443C02100003E0000891
+:1016B000AC6202783C02600003E000088C425404F3
+:1016C0009083003024020005008040213063003FF9
+:1016D0000000482114620005000050219082004C57
+:1016E0009483004E304900FF306AFFFFAD00000CCC
+:1016F000AD000010AD000024950200148D05001C03
+:101700008D0400183042FFFF004910230002110031
+:10171000000237C3004038210086202300A2102B8E
+:101720000082202300A72823AD05001CAD0400186B
+:10173000A5090014A5090020A50A001603E0000869
+:10174000A50A002203E000080000000027BDFFD822
+:10175000AFB200183C128008AFB40020AFB3001C39
+:10176000AFB10014AFBF0024AFB00010365101007C
+:101770003C0260008C4254049222000C3C1408008D
+:10178000929400F7304300FF2402000110620032FF
+:101790000080982124020002146200353650008037
+:1017A0000E00143D000000009202004C2403FF8054
+:1017B0003C0480003042007F000211C024420240FD
+:1017C0000262102100431824AC8300949245000863
+:1017D0009204004C3042007F3C03800614850007D1
+:1017E000004380212402FFFFA22200112402FFFFF8
+:1017F000A62200120A0005D22402FFFF9602002052
+:10180000A222001196020022A62200128E020024BB
+:101810003C048008AE2200143485008090A2004C65
+:1018200034830100A06200108CA2003CAC6200185E
+:101830008C820068AC6200F48C820064AC6200F0C0
+:101840008C82006CAC6200F824020001A0A2006847
+:101850000A0005EE3C0480080E001456000000004B
+:1018600036420080A04000680A0005EE3C04800873
+:10187000A2000068A20000690A0006293C02800854
+:10188000348300808C62003834850100AC62006CC7
+:1018900024020001A062006990A200D59083000894
+:1018A000305100FF3072007F12320019001111C058
+:1018B00024420240026210212403FF8000431824C6
+:1018C0003C048000AC8300943042007F3C038006DF
+:1018D000004380218E02000C1040000D02002021E8
+:1018E0000E00057E0000000026220001305100FF9E
+:1018F0009203003C023410260002102B0002102339
+:101900003063007F022288240A0005F8A203003C0D
+:101910003C088008350401008C8200E03507008017
+:10192000ACE2003C8C8200E0AD02000090E5004C8F
+:10193000908600D590E3004C908400D52402FF806F
+:1019400000A228243063007F308400FF00A62825F1
+:101950000064182A1060000230A500FF38A500803E
+:10196000A0E5004CA10500093C0280089043000E50
+:10197000344400803C058000A043000A8C8300189A
+:101980003C027FFF3442FFFF00621824AC83001842
+:101990008CA201F80440FFFE00000000ACB301C0BF
+:1019A0008FBF00248FB400208FB3001C8FB20018AB
+:1019B0008FB100148FB0001024020002A0A201C455
+:1019C00027BD00283C02100003E00008ACA201F88B
+:1019D00090A2000024420001A0A200003C030800E5
+:1019E0008C6300F4304200FF144300020080302179
+:1019F000A0A0000090A200008F84001C000211C073
+:101A00002442024024830040008220212402FF80DF
+:101A1000008220243063007F3C02800A006218218B
+:101A20003C028000AC44002403E00008ACC300008A
+:101A300094820006908300058C85000C8C86001033
+:101A40008C8700188C88001C8C8400203C010800C6
+:101A5000A42256C63C010800A02356C53C0108003C
+:101A6000AC2556CC3C010800AC2656D03C01080001
+:101A7000AC2756D83C010800AC2856DC3C010800D5
+:101A8000AC2456E003E00008000000003C0280089F
+:101A9000344201008C4400343C038000346504006F
+:101AA000AC6400388C420038AF850028AC62003C42
+:101AB0003C020005AC6200300000000000000000A5
+:101AC00003E00008000000003C020006308400FF34
+:101AD000008220253C028000AC4400300000000061
+:101AE00000000000000000003C0380008C62000049
+:101AF000304200101040FFFD3462040003E0000893
+:101B0000AF82002894C200003C080800950800CA73
+:101B100030E7FFFF0080482101021021A4C200002D
+:101B200094C200003042FFFF00E2102B544000013D
+:101B3000A4C7000094A200003C0308008C6300CC02
+:101B400024420001A4A2000094A200003042FFFF42
+:101B5000144300073C0280080107102BA4A00000DA
+:101B60005440000101003821A4C700003C02800855
+:101B7000344601008CC3002894A200003C0480007D
+:101B80003042FFFE000210C000621021AC82003C17
+:101B90008C82003C006218231860000400000000E2
+:101BA0008CC200240A0006BA244200018CC2002420
+:101BB000AC8200383C020050344200103C038000EC
+:101BC000AC620030000000000000000000000000D7
+:101BD0008C620000304200201040FFFD0000000039
+:101BE00094A200003C04800030420001000210C0BA
+:101BF000004410218C430400AD2300008C420404F7
+:101C0000AD2200043C02002003E00008AC8200305A
+:101C100027BDFFE0AFB20018AFB10014AFB00010A5
+:101C2000AFBF001C94C2000000C080213C1208001D
+:101C3000965200C624420001A6020000960300004E
+:101C400094E2000000E03021144300058FB1003021
+:101C50000E00068F024038210A0006F10000000045
+:101C60008C8300048C82000424420040046100073D
+:101C7000AC8200048C8200040440000400000000D8
+:101C80008C82000024420001AC8200009602000019
+:101C90003042FFFF50520001A600000096220000D3
+:101CA00024420001A62200003C02800834420100C8
+:101CB000962300009442003C144300048FBF001C94
+:101CC00024020001A62200008FBF001C8FB2001862
+:101CD0008FB100148FB0001003E0000827BD002072
+:101CE00027BDFFE03C028008AFBF0018344201006E
+:101CF0008C4800343C03800034690400AC68003830
+:101D00008C42003830E700FFAF890028AC62003C0D
+:101D10003C020005AC620030000000000000000042
+:101D200000000000000000000000000000000000B3
+:101D30008C82000C8C82000C97830016AD22000070
+:101D40008C82001000604021AD2200048C820018BB
+:101D5000AD2200088C82001CAD22000C8CA2001465
+:101D6000AD2200108C820020AD220014908200056C
+:101D7000304200FF00021200AD2200188CA20018B1
+:101D8000AD22001C8CA2000CAD2200208CA2001001
+:101D9000AD2200248CA2001CAD2200288CA20020C1
+:101DA000AD22002C3402FFFFAD260030AD20003400
+:101DB000506200013408FFFFAD28003850E00011E8
+:101DC0003C0280083C048008348401009482005066
+:101DD0003042FFFFAD22003C9483004494850044D0
+:101DE000240200013063FFFF000318C200641821C1
+:101DF0009064006430A5000700A210040A00075C8C
+:101E00000044102534420100AD20003C94430044BE
+:101E1000944400443063FFFF000318C2006218219D
+:101E200030840007906500642402000100821004E1
+:101E30000002102700451024A0620064000000008A
+:101E400000000000000000003C0200063442004098
+:101E50003C038000AC620030000000000000000085
+:101E6000000000008C620000304200101040FFFDB6
+:101E70003C06800834C201503463040034C7014A70
+:101E800034C4013434C5014034C60144AFA200104B
+:101E90000E0006D2AF8300288FBF001803E00008B1
+:101EA00027BD00208F8300143C0608008CC600E884
+:101EB0008F82001C30633FFF000319800046102111
+:101EC000004310212403FF80004318243C068000B7
+:101ED000ACC300283042007F3C03800C004330211B
+:101EE00090C2000D30A500FF0000382134420010E0
+:101EF000A0C2000D8F8900143C028008344201000A
+:101F00009443004400091382304800032402000176
+:101F1000A4C3000E1102000B2902000210400005AC
+:101F2000240200021100000C240300010A0007A48F
+:101F30000000182111020006000000000A0007A49A
+:101F4000000018218CC2002C0A0007A424430001C1
+:101F50008CC20014244300018CC200180043102BD3
+:101F60005040000A240700012402002714A20003A5
+:101F70003C0380080A0007B1240700013463010014
+:101F80009462004C24420001A462004C00091382B8
+:101F9000304300032C620002104000090080282119
+:101FA000146000040000000094C200340A0007C15D
+:101FB0003046FFFF8CC600380A0007C10080282188
+:101FC000000030213C040800248456C00A000706A3
+:101FD0000000000027BDFF90AFB60068AFB50064F9
+:101FE000AFB40060AFB3005CAFB20058AFB1005403
+:101FF000AFBF006CAFB000508C9000000080B021EB
+:102000003C0208008C4200E8960400328F83001CDA
+:102010002414FF8030843FFF0062182100042180D7
+:1020200000641821007410243C13800000A090214B
+:1020300090A50000AE620028920400323C02800CA1
+:102040003063007F00628821308400C02402004099
+:10205000148200320000A8218E3500388E2200182C
+:102060001440000224020001AE2200189202003C3B
+:10207000304200201440000E8F83001C000511C068
+:102080002442024000621821306400783C02008043
+:102090000082202500741824AE630800AE64081086
+:1020A0008E2200188E03000800431021AE22001873
+:1020B0008E22002C8E230018244200010062182B6F
+:1020C0001060004300000000924200002442000122
+:1020D000A24200003C0308008C6300F4304200FF81
+:1020E00050430001A2400000924200008F84001C77
+:1020F000000211C024420240248300403063007F6C
+:10210000008220213C02800A0094202400621821D1
+:10211000AE6400240A0008D2AEC30000920300326D
+:102120002402FFC000431024304200FF1440000589
+:1021300024020001AE220018962200340A00084250
+:102140003055FFFF8E22001424420001AE220018F9
+:102150009202003000021600000216030441001C27
+:10216000000000009602003227A400100080282101
+:10217000A7A20016960200320000302124070001B9
+:102180003042FFFFAF8200140E000706AFA0001C14
+:10219000960200328F83001C3C0408008C8400E807
+:1021A00030423FFF000211800064182100621821B4
+:1021B00000741024AE62002C3063007F3C02800E5D
+:1021C000006218219062000D3042007FA062000D75
+:1021D0009222000D304200105040007892420000E0
+:1021E0003C028008344401009482004C8EC30000FD
+:1021F0003C130800967300C62442FFFFA482004CE3
+:10220000946200329623000E3054FFFF3070FFFFBF
+:102210003C0308008C6300D000701807A7A30038A7
+:102220009482003E3063FFFF3042FFFF14620007DC
+:10223000000000008C8200303C038000244200300B
+:10224000AC62003C0A00086A8C82002C9482004038
+:102250003042FFFF5462000927A400408C820038FE
+:102260003C03800024420030AC62003C8C8200348D
+:10227000AC6200380A0008793C03800027A50038CA
+:1022800027A60048026038210E00068FA7A000484C
+:102290008FA300403C02800024630030AC43003830
+:1022A0008FA30044AC43003C3C0380003C0200058B
+:1022B000AC6200303C028008344401009482004249
+:1022C000346304003042FFFF0202102B1440000769
+:1022D000AF8300289482004E9483004202021021B2
+:1022E000004310230A00088F3043FFFF9483004E01
+:1022F00094820042026318210050102300621823C8
+:102300003063FFFF3C028008344401009482003CAB
+:102310003042FFFF14430003000000000A00089F42
+:10232000240300019482003C3042FFFF0062102B26
+:10233000144000058F8200289482003C0062102324
+:102340003043FFFF8F820028AC550000AC400004F2
+:10235000AC540008AC43000C3C02000634420010B0
+:102360003C038000AC620030000000000000000070
+:10237000000000008C620000304200101040FFFDA1
+:102380003C04800834840100001018C20064182145
+:102390009065006432020007240600010046100424
+:1023A00000451025A0620064948300429622000E2E
+:1023B00050430001A386001892420000244200010D
+:1023C000A24200003C0308008C6300F4304200FF8E
+:1023D00050430001A2400000924200008F84001C84
+:1023E000000211C0244202402483004000822021C8
+:1023F0002402FF80008220243063007F3C02800A98
+:10240000006218213C028000AC440024AEC30000EE
+:102410008FBF006C8FB600688FB500648FB400600A
+:102420008FB3005C8FB200588FB100548FB0005052
+:1024300003E0000827BD007027BDFFD8AFB3001C24
+:10244000AFB20018AFB10014AFB00010AFBF0020A2
+:102450000080982100E0802130B1FFFF0E000D8444
+:1024600030D200FF0000000000000000000000006B
+:102470008F8200208F830024AC510000AC520004F6
+:10248000AC530008AC40000CAC400010AC40001451
+:10249000AC4000189463001E02038025AC50001C61
+:1024A0000000000000000000000000002404000103
+:1024B0008FBF00208FB3001C8FB200188FB10014A3
+:1024C0008FB000100A000DB827BD002830A5FFFF0F
+:1024D0000A0008DC30C600FF3C02800834430100DB
+:1024E0009462000E3C080800950800C63046FFFFC5
+:1024F00014C000043402FFFF946500EA0A000929B1
+:102500008F84001C10C20027000000009462004E5F
+:102510009464003C3045FFFF00A6102300A6182B52
+:102520003087FFFF106000043044FFFF00C5102318
+:1025300000E210233044FFFF0088102B1040000EF3
+:1025400000E810233C028008344401002403000109
+:1025500034420080A44300162402FFFFA482000E30
+:10256000948500EA8F84001C0000302130A5FFFF15
+:102570000A0009013C0760200044102A10400009AD
+:102580003C0280083443008094620016304200010F
+:10259000104000043C0280009442007E244200145B
+:1025A000A462001603E000080000000027BDFFE061
+:1025B0003C028008AFBF001CAFB0001834420100DD
+:1025C000944300429442004C104000193068FFFFD1
+:1025D0009383001824020001146200298FBF001C9D
+:1025E0003C06800834D00100000810C200501021C1
+:1025F000904200643103000734C70148304200FFB5
+:10260000006210073042000134C9014E34C4012C6D
+:1026100034C5013E1040001634C601420E0006D2F9
+:10262000AFA90010960200420A0009463048FFFF99
+:102630003C028008344401009483004494820042A8
+:102640001043000F8FBF001C94820044A4820042FC
+:1026500094820050A482004E8C820038AC820030FC
+:1026600094820040A482003E9482004AA4820048E2
+:102670008FBF001C8FB000180A00090427BD00207E
+:102680008FB0001803E0000827BD002027BDFFA081
+:10269000AFB1004C3C118000AFBF0058AFB3005445
+:1026A000AFB20050AFB000483626018890C2000398
+:1026B0003044007FA3A400108E32018090C200003D
+:1026C0003043007F240200031062003BAF92001CE5
+:1026D00028620004104000062402000424020002C4
+:1026E000106200098FBF00580A000B0F8FB300540F
+:1026F0001062004D240200051062014E8FBF005889
+:102700000A000B0F8FB30054000411C002421021C5
+:102710002404FF8024420240004410242643004049
+:10272000AE2200243063007F3C02800A0062182140
+:102730009062003CAFA3003C00441025A062003C26
+:102740008FA3003C9062003C304200401040016C7E
+:102750008FBF00583C108008A3800018361001007D
+:102760008E0200E08C63003427A4003C27A50010F3
+:10277000004310210E0007C3AE0200E093A2001038
+:102780003C038000A20200D58C6202780440FFFE68
+:102790008F82001CAC62024024020002A06202444C
+:1027A0003C021000AC6202780E0009390000000003
+:1027B0000A000B0E8FBF00583C05800890C3000133
+:1027C00090A2000B1443014E8FBF005834A4008028
+:1027D0008C8200189082004C90A200083C0260009D
+:1027E0008C4254048C8300183C027FFF3442FFFF6C
+:1027F000006218243C0208008C4200B4AC8300182C
+:102800003C038000244200013C010800AC2200B4DB
+:102810008C6201F80440FFFE8F82001CAC6201C094
+:102820000A000AD6240200023C10800890C300016E
+:102830009202000B144301328FBF005827A40018E6
+:1028400036050110240600033C0260008C4254044B
+:102850000E000E470000000027A40028360501F0F6
+:102860000E000E47240600038FA200283603010045
+:10287000AE0200648FA2002CAE0200688FA200306E
+:10288000AE02006C93A40018906300D52402FF8070
+:102890000082102400431025304900FF3084007F5F
+:1028A0003122007F0082102A544000013929008023
+:1028B000000411C0244202402403FF800242102180
+:1028C00000431024AE220094264200403042007F94
+:1028D0003C038006004340218FA3001C2402FFFF1D
+:1028E000AFA800403C130800927300F71062003359
+:1028F00093A2001995030014304400FF3063FFFFDA
+:102900000064182B106000100000000095040014F3
+:102910008D07001C8D0600183084FFFF0044202323
+:102920000004210000E438210000102100E4202BE5
+:1029300000C2302100C43021AD07001CAD060018D4
+:102940000A000A2F93A20019950400148D07001C99
+:102950008D0600183084FFFF008220230004210030
+:10296000000010210080182100C2302300E4202B39
+:1029700000C4302300E33823AD07001CAD06001867
+:1029800093A200198FA30040A462001497A2001A1A
+:10299000A46200168FA2001CAC6200108FA2001C63
+:1029A000AC62000C93A20019A462002097A2001A46
+:1029B000A46200228FA2001CAC6200243C048008A8
+:1029C000348300808C6200388FA20020012088218F
+:1029D000AC62003C8FA20020AC82000093A20018E1
+:1029E000A062004C93A20018A0820009A0600068B9
+:1029F00093A20018105100512407FF803229007F54
+:102A0000000911C024420240024210213046007FDA
+:102A10003C03800000471024AC6200943C02800616
+:102A200000C2302190C2003CAFA60040000020212F
+:102A300000471025A0C2003C8FA80040950200026C
+:102A4000950300148D07001C3042FFFF3063FFFF29
+:102A50008D060018004310230002110000E2382107
+:102A600000E2102B00C4302100C23021AD07001C51
+:102A7000AD06001895020002A5020014A50000167C
+:102A80008D020008AD0200108D020008AD02000C9E
+:102A900095020002A5020020A50000228D02000878
+:102AA000AD0200249102003C304200401040001A68
+:102AB000262200013C108008A3A90038A38000183A
+:102AC000361001008E0200E08D03003427A4004080
+:102AD00027A50038004310210E0007C3AE0200E016
+:102AE00093A200383C038000A20200D58C620278D9
+:102AF0000440FFFE8F82001CAC62024024020002F0
+:102B0000A06202443C021000AC6202780E00093957
+:102B100000000000262200013043007F14730004EF
+:102B2000004020212403FF8002231024004320269C
+:102B300093A200180A000A4B309100FF93A40018DA
+:102B40008FA3001C2402FFFF1062000A308900FFDF
+:102B500024820001248300013042007F14530005C9
+:102B6000306900FF2403FF800083102400431026F7
+:102B7000304900FF3C028008904200080120882173
+:102B8000305000FF123000193222007F000211C0C5
+:102B900002421021244202402403FF8000431824F3
+:102BA0003C048000AC8300943042007F3C038006EC
+:102BB000004310218C43000C004020211060000BCA
+:102BC000AFA200400E00057E000000002623000199
+:102BD0002405FF803062007F145300020225202468
+:102BE000008518260A000AAF307100FF3C048008F7
+:102BF000348400808C8300183C027FFF3442FFFF46
+:102C000000621824AC8300183C0380008C6201F839
+:102C10000440FFFE00000000AC7201C0240200026C
+:102C2000A06201C43C021000AC6201F80A000B0E65
+:102C30008FBF00583C04800890C300019082000BB5
+:102C40001443002F8FBF0058349000809202000878
+:102C500030420040104000200000000092020008B6
+:102C60000002160000021603044100050240202164
+:102C70000E000ECC240500930A000B0E8FBF0058E7
+:102C80009202000924030018304200FF1443000D93
+:102C900002402021240500390E000E64000030217E
+:102CA0000E0003328F84001C8F82FF9424030012D5
+:102CB000A04300090E00033D8F84001C0A000B0E88
+:102CC0008FBF0058240500360E000E64000030212E
+:102CD0000A000B0E8FBF00580E0003320240202165
+:102CE000920200058F84001C344200200E00033D38
+:102CF000A20200050E0010758F84001C8FBF0058C3
+:102D00008FB300548FB200508FB1004C8FB0004889
+:102D100003E0000827BD00603C0280083445010044
+:102D20003C0280008C42014094A3000E0000302140
+:102D300000402021AF82001C3063FFFF3402FFFF00
+:102D4000106200063C0760202402FFFFA4A2000ED0
+:102D500094A500EA0A00090130A5FFFF03E000087E
+:102D60000000000027BDFFC83C0280003C06800830
+:102D7000AFB5002CAFB1001CAFBF0030AFB400281E
+:102D8000AFB30024AFB20020AFB00018345101003F
+:102D900034C501008C4301008E2200148CA400E491
+:102DA0000000A821AF83001C0044102318400052EB
+:102DB000A38000188E22001400005021ACA200E471
+:102DC00090C3000890A200D53073007FA3A200102A
+:102DD0008CB200E08CB400E4304200FF1053003BA2
+:102DE00093A200108F83001C2407FF80000211C0F3
+:102DF0000062102124420240246300400047102456
+:102E00003063007F3C0980003C08800A006818217C
+:102E1000AD2200248C62003427A4001427A50010E2
+:102E2000024280210290102304400028AFA3001426
+:102E30009062003C00E21024304200FF1440001970
+:102E4000020090219062003C34420040A062003CAD
+:102E50008F86001C93A3001024C200403042007FE4
+:102E6000004828213C0208008C4200F42463000141
+:102E7000306400FF14820002A3A30010A3A000107E
+:102E800093A20010AFA50014000211C0244202401A
+:102E900000C2102100471024AD2200240A000B4577
+:102EA00093A200100E0007C3000000003C0280083F
+:102EB00034420100AC5000E093A30010240A00014A
+:102EC000A04300D50A000B4593A200102402000184
+:102ED000154200093C0380008C6202780440FFFE2A
+:102EE0008F82001CAC62024024020002A0620244F5
+:102EF0003C021000AC6202789222000B2403000214
+:102F0000304200FF144300720000000096220008C7
+:102F1000304300FF24020082146200402402008437
+:102F20003C028000344901008D22000C95230006EC
+:102F3000000216023063FFFF3045003F24020027E5
+:102F400010A2000FAF83001428A200281040000830
+:102F5000240200312402002110A2000924020025CD
+:102F600010A20007938200190A000BBD00000000A8
+:102F700010A20007938200190A000BBD0000000098
+:102F80000E000777012020210A000C3D0000000000
+:102F90003C0380008C6202780440FFFE8F82001C9C
+:102FA000AC62024024020002A06202443C02100013
+:102FB000AC6202780A000C3D000000009523000678
+:102FC000912400058D25000C8D2600108D270018FA
+:102FD0008D28001C8D290020244200013C0108009E
+:102FE000A42356C63C010800A02456C53C01080095
+:102FF000AC2556CC3C010800AC2656D03C0108005C
+:10300000AC2756D83C010800AC2856DC3C0108002F
+:10301000AC2956E00A000C3DA38200191462000A94
+:10302000240200813C02800834420100944500EAF9
+:10303000922600058F84001C30A5FFFF30C600FFDC
+:103040000A000BFE3C0760211462005C00000000D7
+:103050009222000A304300FF306200201040000737
+:10306000306200403C02800834420100944500EA8E
+:103070008F84001C0A000BFC24060040104000074F
+:10308000000316003C02800834420100944500EA27
+:103090008F84001C0A000BFC24060041000216036A
+:1030A000044100463C02800834420100944500EA95
+:1030B0008F84001C2406004230A5FFFF3C076019E6
+:1030C0000E000901000000000A000C3D0000000095
+:1030D0009222000B24040016304200FF1044000628
+:1030E0003C0680009222000B24030017304200FFB0
+:1030F000144300320000000034C5010090A2000B10
+:10310000304200FF1444000B000080218CA20020FC
+:103110008CA400202403FF800043102400021140EF
+:103120003084007F004410253C032000004310251C
+:10313000ACC2083094A2000800021400000214037C
+:10314000044200012410000194A2000830420080D3
+:103150005040001A0200A82194A20008304220002A
+:10316000504000160200A8218CA300183C021C2D20
+:10317000344219ED106200110200A8213C0208003F
+:103180008C4200D4104000053C0280082403000457
+:1031900034420100A04300FC3C028008344201009C
+:1031A000944500EA8F84001C2406000630A5FFFF2A
+:1031B0000E0009013C0760210200A8210E00093918
+:1031C000000000009222000A304200081040000473
+:1031D00002A010210E0013790000000002A01021AF
+:1031E0008FBF00308FB5002C8FB400288FB3002420
+:1031F0008FB200208FB1001C8FB0001803E00008D0
+:1032000027BD00382402FF80008220243C02900069
+:1032100034420007008220253C028000AC4400209C
+:103220003C0380008C6200200440FFFE0000000090
+:1032300003E00008000000003C0380002402FF803F
+:10324000008220243462000700822025AC64002024
+:103250008C6200200440FFFE0000000003E0000834
+:103260000000000027BDFFD8AFB3001CAFB10014B1
+:10327000AFB00010AFBF0020AFB200183C1180000B
+:103280003C0280088E32002034530100AE2400201E
+:10329000966300EA000514003C074000004738250B
+:1032A00000A08021000030210E0009013065FFFFE1
+:1032B000240200A1160200022402FFFFA2620009FC
+:1032C000AE3200208FBF00208FB3001C8FB20018D9
+:1032D0008FB100148FB0001003E0000827BD002854
+:1032E0003C0280082403000527BDFFE834420100AA
+:1032F000A04300FCAFBF00103C0280008C420100E4
+:10330000240500A1004020210E000C67AF82001CA4
+:103310003C0380008C6202780440FFFE8F82001C18
+:103320008FBF001027BD0018AC62024024020002CB
+:10333000A06202443C021000AC62027803E0000884
+:103340000000000027BDFFE83C068000AFBF001072
+:1033500034C7010094E20008304400FF3883008243
+:10336000388200842C6300012C4200010062182581
+:103370001060002D24020083938200195040003B0E
+:103380008FBF00103C020800904256CC8CC4010054
+:103390003C06080094C656C63045003F38A30032AC
+:1033A00038A2003F2C6300012C4200010062182566
+:1033B000AF84001CAF860014A380001914600007BE
+:1033C00000E020212402002014A2001200000000CE
+:1033D0003402FFFF14C2000F00000000240200208E
+:1033E00014A2000500E028218CE300142402FFFF52
+:1033F0005062000B8FBF00103C040800248456C0AC
+:10340000000030210E000706240700010A000CD638
+:103410008FBF00100E000777000000008FBF001064
+:103420000A00093927BD001814820004240200850F
+:103430008CC501040A000CE1000020211482000662
+:103440002482FF808CC50104240440008FBF00103B
+:103450000A00016727BD0018304200FF2C4200021D
+:1034600010400004240200228FBF00100A000B2726
+:1034700027BD0018148200048F8200248FBF001023
+:103480000A000C8627BD00188C42000C1040001E5C
+:1034900000E0282190E300092402001814620003D0
+:1034A000240200160A000CFC240300081462000722
+:1034B00024020017240300123C02800834420080DA
+:1034C000A04300090A000D0994A7000854620007F0
+:1034D00094A700088F82FF942404FFFE9043000508
+:1034E00000641824A043000594A7000890A6001BC0
+:1034F0008CA4000094A500068FBF001000073C00BC
+:103500000A0008DC27BD00188FBF001003E0000888
+:1035100027BD00188F8500243C04800094A2002A57
+:103520008CA30034000230C02402FFF000C210243B
+:1035300000621821AC83003C8CA200303C03800068
+:10354000AC8200383C02005034420010AC620030C3
+:103550000000000000000000000000008C6200007D
+:10356000304200201040FFFD30C20008104000062D
+:103570003C0280008C620408ACA200208C62040C27
+:103580000A000D34ACA200248C430400ACA300203C
+:103590008C420404ACA200243C0300203C028000C6
+:1035A000AC4300303C0480008C8200300043102487
+:1035B0001440FFFD8F8600243C020040AC820030A6
+:1035C00094C3002A94C2002894C4002C94C5002EF1
+:1035D00024630001004410213064FFFFA4C20028CE
+:1035E00014850002A4C3002AA4C0002A03E0000836
+:1035F000000000008F84002427BDFFE83C05800404
+:1036000024840010AFBF00100E000E472406000AED
+:103610008F840024948200129483002E3042000F85
+:10362000244200030043180424027FFF0043102BB0
+:1036300010400002AC8300000000000D0E000D13CE
+:10364000000000008F8300248FBF001027BD0018EA
+:10365000946200149463001A3042000F00021500B7
+:10366000006218253C02800003E00008AC4300A083
+:103670008F8300243C028004944400069462001A64
+:103680008C650000A4640016004410233042FFFF44
+:103690000045102B03E00008384200018F8400240D
+:1036A0003C0780049486001A8C85000094E2000692
+:1036B000A482001694E3000600C310233042FFFFEB
+:1036C0000045102B384200011440FFF8A483001677
+:1036D00003E00008000000008F8400243C02800406
+:1036E000944200069483001A8C850000A482001680
+:1036F000006210233042FFFF0045102B38420001CA
+:103700005040000D8F850024006030213C0780046C
+:1037100094E20006A482001694E3000600C310237E
+:103720003042FFFF0045102B384200011440FFF8E3
+:10373000A48300168F8500243C03800034620400BB
+:103740008CA40020AF820020AC6400388CA200243E
+:10375000AC62003C3C020005AC62003003E00008B3
+:10376000ACA000048F8400243C0300068C8200047B
+:1037700000021140004310253C038000AC62003081
+:103780000000000000000000000000008C6200004B
+:10379000304200101040FFFD34620400AC80000491
+:1037A00003E00008AF8200208F86002427BDFFE0E1
+:1037B000AFB10014AFB00010AFBF00188CC300044D
+:1037C0008CC500248F820020309000FF94C4001A22
+:1037D00024630001244200202484000124A7002047
+:1037E000ACC30004AF820020A4C4001AACC70024FC
+:1037F00004A100060000882104E2000594C2001A1A
+:103800008CC2002024420001ACC2002094C2001AE5
+:1038100094C300282E040001004310262C4200010E
+:10382000004410245040000594C2001A24020001F4
+:10383000ACC2000894C2001A94C300280010202BC8
+:10384000004310262C4200010044102514400007BC
+:10385000000000008CC20008144000042402001084
+:103860008CC300041462000F8F8500240E000DA786
+:10387000241100018F820024944300289442001AEE
+:1038800014430003000000000E000D1300000000B0
+:10389000160000048F8500240E000D840000000037
+:1038A0008F85002494A2001E94A4001C24420001D1
+:1038B0003043FFFF14640002A4A2001EA4A0001E57
+:1038C0001200000A3C02800494A2001494A3001A7F
+:1038D0003042000F00021500006218253C028000F3
+:1038E000AC4300A00A000E1EACA0000894420006E3
+:1038F00094A3001A8CA40000A4A200160062102356
+:103900003042FFFF0044102B384200011040000DF0
+:1039100002201021006030213C07800494E2000660
+:10392000A4A2001694E3000600C310233042FFFF58
+:103930000044102B384200011440FFF8A4A30016E5
+:10394000022010218FBF00188FB100148FB000101B
+:1039500003E0000827BD002003E00008000000008D
+:103960008F82002C3C03000600021140004310250A
+:103970003C038000AC62003000000000000000004A
+:10398000000000008C620000304200101040FFFD7B
+:1039900034620400AF82002803E00008AF80002CEE
+:1039A00003E000080000102103E000080000000010
+:1039B0003084FFFF30A5FFFF0000182110800007B2
+:1039C000000000003082000110400002000420428C
+:1039D000006518210A000E3D0005284003E000089C
+:1039E0000060102110C0000624C6FFFF8CA200005A
+:1039F00024A50004AC8200000A000E4724840004C1
+:103A000003E000080000000010A0000824A3FFFF4E
+:103A1000AC86000000000000000000002402FFFF50
+:103A20002463FFFF1462FFFA2484000403E000080B
+:103A3000000000003C0280083442008024030001A2
+:103A4000AC43000CA4430010A4430012A443001490
+:103A500003E00008A44300168F82002427BDFFD88E
+:103A6000AFB3001CAFB20018AFB10014AFB000107C
+:103A7000AFBF00208C47000C248200802409FF8007
+:103A80003C08800E3043007F008080213C0A80008B
+:103A9000004920240068182130B100FF30D200FF17
+:103AA00010E000290000982126020100AD44002CFE
+:103AB000004928243042007F004820219062000005
+:103AC00024030050304200FF1443000400000000B3
+:103AD000AD45002C948200EA3053FFFF0E000D84A8
+:103AE000000000008F8200248F83002000112C0032
+:103AF0009442001E001224003484000100A22825F4
+:103B00003C02400000A22825AC7000008FBF0020BE
+:103B1000AC6000048FB20018AC7300088FB10014C1
+:103B2000AC60000C8FB3001CAC6400108FB00010B0
+:103B3000AC60001424040001AC60001827BD00280C
+:103B40000A000DB8AC65001C8FBF00208FB3001CAD
+:103B50008FB200188FB100148FB0001003E000087E
+:103B600027BD00283C06800034C201009043000FAE
+:103B7000240200101062000E2865001110A000073A
+:103B800024020012240200082405003A10620006F4
+:103B90000000302103E0000800000000240500358B
+:103BA0001462FFFC000030210A000E6400000000D7
+:103BB0008CC200748F83FF9424420FA003E000089E
+:103BC000AC62000C27BDFFE8AFBF00100E0003423F
+:103BD000240500013C0480088FBF0010240200016E
+:103BE00034830080A462001227BD00182402000163
+:103BF00003E00008A080001A27BDFFE0AFB2001864
+:103C0000AFB10014AFB00010AFBF001C30B2FFFF67
+:103C10000E000332008088213C028008345000806E
+:103C20009202000924030004304200FF1443000CF8
+:103C30003C028008124000082402000A0E000E5BBD
+:103C400000000000920200052403FFFE0043102440
+:103C5000A202000524020012A20200093C02800810
+:103C600034420080022020210E00033DA0400027A6
+:103C700016400003022020210E000EBF00000000AD
+:103C800002202021324600FF8FBF001C8FB2001897
+:103C90008FB100148FB00010240500380A000E64A4
+:103CA00027BD002027BDFFE0AFBF001CAFB200184A
+:103CB000AFB10014AFB000100E00033200808021BD
+:103CC0000E000E5B000000003C02800834450080BE
+:103CD00090A2000924120018305100FF1232000394
+:103CE0000200202124020012A0A2000990A20005D7
+:103CF0002403FFFE004310240E00033DA0A2000594
+:103D00000200202124050020163200070000302187
+:103D10008FBF001C8FB200188FB100148FB000103D
+:103D20000A00034227BD00208FBF001C8FB200187D
+:103D30008FB100148FB00010240500390A000E6402
+:103D400027BD002027BDFFE83C028000AFB0001077
+:103D5000AFBF0014344201009442000C2405003629
+:103D60000080802114400012304600FF0E00033214
+:103D7000000000003C02800834420080240300124E
+:103D8000A043000990430005346300100E000E5B51
+:103D9000A04300050E00033D020020210200202167
+:103DA0000E000342240500200A000F3C0000000022
+:103DB0000E000E64000000000E00033202002021FD
+:103DC0003C0280089043001B2405FF9F0200202135
+:103DD000006518248FBF00148FB00010A043001B93
+:103DE0000A00033D27BD001827BDFFE0AFBF001844
+:103DF000AFB10014AFB0001030B100FF0E000332BD
+:103E0000008080213C02800824030012344200809C
+:103E10000E000E5BA04300090E00033D02002021AE
+:103E200002002021022030218FBF00188FB1001422
+:103E30008FB00010240500350A000E6427BD002055
+:103E40003C0480089083000E9082000A1443000B0B
+:103E5000000028218F82FF942403005024050001D4
+:103E600090420000304200FF1443000400000000B4
+:103E70009082000E24420001A082000E03E00008A0
+:103E800000A010213C0380008C6201F80440FFFE7A
+:103E900024020002AC6401C0A06201C43C02100014
+:103EA00003E00008AC6201F827BDFFE0AFB20018E4
+:103EB0003C128008AFB10014AFBF001CAFB00010BF
+:103EC00036510080922200092403000A304200FF8C
+:103ED0001443003E000000008E4300048E22003890
+:103EE000506200808FBF001C92220000240300500B
+:103EF000304200FF144300253C0280008C42014008
+:103F00008E4300043642010002202821AC43001CED
+:103F10009622005C8E2300383042FFFF00021040E2
+:103F200000621821AE23001C8E4300048E2400384A
+:103F30009622005C006418233042FFFF0003184300
+:103F4000000210400043102A10400006000000004C
+:103F50008E4200048E230038004310230A000FAA6B
+:103F6000000220439622005C3042FFFF0002204006
+:103F70003C0280083443010034420080ACA4002C91
+:103F8000A040002424020001A062000C0E000F5E7D
+:103F900000000000104000538FBF001C3C02800056
+:103FA0008C4401403C0380008C6201F80440FFFE19
+:103FB00024020002AC6401C0A06201C43C021000F3
+:103FC000AC6201F80A0010078FBF001C92220009A2
+:103FD00024030010304200FF144300043C02800020
+:103FE0008C4401400A000FEE0000282192220009B3
+:103FF00024030016304200FF14430006240200147C
+:10400000A22200093C0280008C4401400A001001F9
+:104010008FBF001C8E2200388E23003C00431023EB
+:10402000044100308FBF001C92220027244200016F
+:10403000A2220027922200272C42000414400016DE
+:104040003C1080009222000924030004304200FF4B
+:10405000144300093C0280008C4401408FBF001CC7
+:104060008FB200188FB100148FB000102405009398
+:104070000A000ECC27BD00208C440140240500938B
+:104080008FBF001C8FB200188FB100148FB00010CA
+:104090000A000F4827BD00208E0401400E000332A5
+:1040A000000000008E4200042442FFFFAE420004E4
+:1040B0008E22003C2442FFFFAE22003C0E00033D56
+:1040C0008E0401408E0401408FBF001C8FB2001887
+:1040D0008FB100148FB00010240500040A000342C1
+:1040E00027BD00208FB200188FB100148FB00010D0
+:1040F00003E0000827BD00203C0680008CC2018838
+:104100003C038008346500809063000E00021402B6
+:10411000304400FF306300FF1464000E3C0280084E
+:1041200090A20026304200FF104400098F82FF94C5
+:10413000A0A400262403005090420000304200FF5B
+:1041400014430006000000000A0005A18CC4018091
+:104150003C02800834420080A044002603E00008AE
+:104160000000000027BDFFE030E700FFAFB20018FD
+:10417000AFBF001CAFB10014AFB0001000809021A1
+:1041800014E0000630C600FF000000000000000D33
+:10419000000000000A001060240001163C038008A3
+:1041A0009062000E304200FF14460023346200800B
+:1041B00090420026304200FF1446001F000000001D
+:1041C0009062000F304200FF1446001B0000000008
+:1041D0009062000A304200FF144600038F90FF9463
+:1041E0000000000D8F90FF948F82FF983C1180009B
+:1041F000AE05003CAC450000A066000A0E0003328C
+:104200008E240100A20000240E00033D8E24010034
+:104210003C0380008C6201F80440FFFE240200028F
+:10422000AC7201C0A06201C43C021000AC6201F893
+:104230000A0010618FBF001C000000000000000D8C
+:10424000000000002400013F8FBF001C8FB2001847
+:104250008FB100148FB0001003E0000827BD0020CC
+:104260008F83FF943C0280008C44010034420100A3
+:104270008C65003C9046001B0A00102724070001B3
+:104280003C0280089043000E9042000A0043102632
+:10429000304200FF03E000080002102B27BDFFE0C2
+:1042A0003C028008AFB10014AFB00010AFBF0018DF
+:1042B0003450008092020005240300303042003068
+:1042C00014430085008088218F8200248C42000CDA
+:1042D000104000828FBF00180E000D840000000007
+:1042E0008F860020ACD100009202000892030009E2
+:1042F000304200FF00021200306300FF004310252F
+:10430000ACC200049202004D000216000002160327
+:1043100004410005000000003C0308008C630048D5
+:104320000A00109F3C1080089202000830420040B2
+:10433000144000030000182192020027304300FFC0
+:104340003C108008361100809222004D00031E00B0
+:10435000304200FF0002140000621825ACC30008C0
+:104360008E2400308F820024ACC4000C8E250034D3
+:104370009443001E3C02C00BACC50010006218251F
+:104380008E22003800002021ACC200148E22003C96
+:10439000ACC200180E000DB8ACC3001C8E020004A5
+:1043A0008F8400203C058000AC8200008E2200201B
+:1043B000AC8200048E22001CAC8200088E220058C1
+:1043C0008CA3007400431021AC82000C8E22002CC0
+:1043D000AC8200108E2200408E23004400021400A4
+:1043E00000431025AC8200149222004D240300806B
+:1043F000304200FF1443000400000000AC800018AD
+:104400000A0010E38F8200248E23000C2402000196
+:104410001062000E2402FFFF92220008304200408A
+:104420001440000A2402FFFF8E23000C8CA20074AB
+:10443000006218233C0208000062102414400002AD
+:10444000000028210060282100051043AC820018DC
+:104450008F820024000020219443001E3C02C00CE7
+:10446000006218258F8200200E000DB8AC43001C9E
+:104470003C038008346201008C4200008F850020DC
+:10448000346300808FBF0018ACA20000ACA0000411
+:104490008C6400488F8200248FB10014ACA4000803
+:1044A000ACA0000CACA00010906300059446001E68
+:1044B0003C02400D00031E0000C23025ACA30014D6
+:1044C0008FB00010ACA0001824040001ACA6001CA2
+:1044D0000A000DB827BD00208FBF00188FB100144F
+:1044E0008FB0001003E0000827BD00203C028000D0
+:1044F0009443007C3C02800834460100308400FF75
+:104500003065FFFF2402000524A34650A0C4000C20
+:104510005482000C3065FFFF90C2000D2C42000752
+:104520001040000724A30A0090C3000D24020014C9
+:104530000062100400A210210A00111F3045FFFF85
+:104540003065FFFF3C0280083442008003E0000831
+:10455000A44500143C03800834680080AD05003891
+:10456000346701008CE2001C308400FF00A210239D
+:104570001840000330C600FF24A2FFFCACE2001C80
+:1045800030820001504000083C0380088D02003C4E
+:1045900000A2102304410012240400058C620004D0
+:1045A00010A2000F3C0380088C62000414A2001EBD
+:1045B000000000003C0208008C4200D8304200207D
+:1045C000104000093C0280083462008090630008BB
+:1045D0009042004C144300043C0280082404000470
+:1045E0000A00110900000000344300803442010039
+:1045F000A040000C24020001A462001410C0000AB4
+:104600003C0280008C4401003C0380008C6201F875
+:104610000440FFFE24020002AC6401C0A06201C499
+:104620003C021000AC6201F803E00008000000004A
+:1046300027BDFFE800A61823AFBF00101860008058
+:10464000308800FF3C02800834470080A0E000244E
+:1046500034440100A0E000278C82001C00A210233B
+:1046600004400056000000008CE2003C94E3005C33
+:104670008CE4002C004530233063FFFF00C3182179
+:104680000083202B1080000400E018218CE2002C15
+:104690000A00117800A2102194E2005C3042FFFF72
+:1046A00000C2102100A21021AC62001C3C02800854
+:1046B000344400809482005C8C83001C3042FFFFF5
+:1046C0000002104000A210210043102B10400004F3
+:1046D000000000008C82001C0A00118B3C06800840
+:1046E0009482005C3042FFFF0002104000A21021C3
+:1046F0003C06800834C3010034C70080AC82001C33
+:10470000A060000CACE500388C62001C00A21023F5
+:104710001840000224A2FFFCAC62001C3102000120
+:10472000104000083C0380088CE2003C00A21023EB
+:1047300004410012240400058CC2000410A20010E1
+:104740008FBF00108C62000414A2004F8FBF0010B6
+:104750003C0208008C4200D8304200201040000A81
+:104760003C02800834620080906300089042004C54
+:10477000144300053C028008240400048FBF00108D
+:104780000A00110927BD001834430080344201009B
+:10479000A040000C24020001A46200143C0280002E
+:1047A0008C4401003C0380008C6201F80440FFFE51
+:1047B000240200020A0011D8000000008CE2001C54
+:1047C000004610230043102B54400001ACE5001CB0
+:1047D00094E2005C3042FFFF0062102B144000079F
+:1047E0002402000294E2005C8CE3001C3042FFFFD4
+:1047F00000621821ACE3001C24020002ACE5003882
+:104800000E000F5EA082000C1040001F8FBF001032
+:104810003C0280008C4401003C0380008C6201F863
+:104820000440FFFE24020002AC6401C0A06201C487
+:104830003C021000AC6201F80A0011F08FBF0010BA
+:1048400031020010104000108FBF00103C028008A1
+:10485000344500808CA3001C94A2005C00661823E1
+:104860003042FFFF006218213C023FFF3444FFFF4B
+:104870000083102B544000010080182100C3102138
+:10488000ACA2001C8FBF001003E0000827BD001879
+:1048900027BDFFE800C0402100A63023AFBF0010B5
+:1048A00018C00026308A00FF3C028008344900808E
+:1048B0008D24001C8D23002C008820230064182BDD
+:1048C0001060000F344701008CE2002000461021E8
+:1048D000ACE200208CE200200044102B1440000BBE
+:1048E0003C023FFF8CE2002000441023ACE2002099
+:1048F0009522005C3042FFFF0A0012100082202146
+:10490000ACE00020008620213C023FFF3443FFFF43
+:104910000064102B54400001006020213C028008FC
+:104920003442008000851821AC43001CA0400024C4
+:10493000A04000270A0012623C03800831420010A8
+:10494000104000433C0380083C06800834C40080CB
+:104950008C82003C004810235840003E34660080A2
+:104960009082002424420001A0820024908200242E
+:104970003C0308008C630024304200FF0043102BEE
+:10498000144000688FBF001034C201008C42001C2C
+:1049900000A2102318400063000000008CC3000434
+:1049A0009482005C006818233042FFFF0003184324
+:1049B000000210400043102A1040000500000000D3
+:1049C0008CC20004004810230A0012450002104364
+:1049D0009482005C3042FFFF000210403C068008D9
+:1049E000AC82002C34C5008094A2005C8CA4002C06
+:1049F00094A3005C3042FFFF00021040008220219F
+:104A00003063FFFF0083202101041021ACA2001CB1
+:104A10008CC2000434C60100ACC2001C2402000297
+:104A20000E000F5EA0C2000C1040003E8FBF0010B1
+:104A30003C0280008C4401003C0380008C6201F841
+:104A40000440FFFE240200020A001292000000004F
+:104A500034660080ACC50038346401008C82001CD0
+:104A600000A210231840000224A2FFFCAC82001C0C
+:104A7000314200015040000A3C0380088CC2003CD7
+:104A800000A2102304430014240400058C620004D7
+:104A900014A200033C0380080A00128424040005C9
+:104AA0008C62000414A2001F8FBF00103C0208009B
+:104AB0008C4200D8304200201040000A3C0280089E
+:104AC00034620080906300089042004C144300055B
+:104AD0003C028008240400048FBF00100A00110962
+:104AE00027BD00183443008034420100A040000C70
+:104AF00024020001A46200143C0280008C440100E6
+:104B00003C0380008C6201F80440FFFE2402000296
+:104B1000AC6401C0A06201C43C021000AC6201F8A8
+:104B20008FBF001003E0000827BD001827BDFFE875
+:104B30003C0A8008AFBF0010354900808D22003C40
+:104B400000C04021308400FF004610231840009D23
+:104B500030E700FF354701002402000100A63023A2
+:104B6000A0E0000CA0E0000DA522001418C0002455
+:104B7000308200108D23001C8D22002C0068182329
+:104B80000043102B1040000F000000008CE20020BA
+:104B900000461021ACE200208CE200200043102BE4
+:104BA0001440000B3C023FFF8CE200200043102326
+:104BB000ACE200209522005C3042FFFF0A0012C1E7
+:104BC00000621821ACE00020006618213C023FFF83
+:104BD0003446FFFF00C3102B5440000100C01821D1
+:104BE0003C0280083442008000651821AC43001C60
+:104BF000A0400024A04000270A00130F3C038008B7
+:104C0000104000403C0380088D22003C00481023E7
+:104C10005840003D34670080912200242442000166
+:104C2000A1220024912200243C0308008C6300246C
+:104C3000304200FF0043102B1440009A8FBF001039
+:104C40008CE2001C00A21023184000960000000017
+:104C50008D4300049522005C006818233042FFFF5A
+:104C600000031843000210400043102A10400005C2
+:104C7000012020218D420004004810230A0012F276
+:104C8000000210439522005C3042FFFF00021040FA
+:104C90003C068008AC82002C34C5008094A2005CE5
+:104CA0008CA4002C94A3005C3042FFFF0002104053
+:104CB000008220213063FFFF0083182101031021AF
+:104CC000ACA2001C8CC2000434C60100ACC2001CA3
+:104CD000240200020E000F5EA0C2000C1040007102
+:104CE0008FBF00103C0280008C4401003C03800018
+:104CF0008C6201F80440FFFE240200020A0013390E
+:104D00000000000034670080ACE500383466010024
+:104D10008CC2001C00A210231840000224A2FFFC39
+:104D2000ACC2001C30820001504000083C038008E7
+:104D30008CE2003C00A2102304430051240400052F
+:104D40008C62000410A2003E3C0380088C620004C8
+:104D500054A200548FBF00103C0208008C4200D8BF
+:104D600030420020104000063C028008346200807F
+:104D7000906300089042004C104300403C028008C1
+:104D80003443008034420100A040000C24020001A2
+:104D9000A46200143C0280008C4401003C038000AB
+:104DA0008C6201F80440FFFE24020002AC6401C0E2
+:104DB000A06201C43C021000AC6201F80A00137743
+:104DC0008FBF001024020005A120002714E2000A72
+:104DD0003C038008354301009062000D2C42000620
+:104DE000504000053C0380089062000D2442000101
+:104DF000A062000D3C03800834670080ACE50038F9
+:104E0000346601008CC2001C00A21023184000026E
+:104E100024A2FFFCACC2001C308200015040000AFA
+:104E20003C0380088CE2003C00A2102304410014E3
+:104E3000240400058C62000414A200033C038008D3
+:104E40000A00136E240400058C62000414A20015ED
+:104E50008FBF00103C0208008C4200D83042002076
+:104E60001040000A3C028008346200809063000811
+:104E70009042004C144300053C02800824040004C6
+:104E80008FBF00100A00110927BD001834430080AD
+:104E900034420100A040000C24020001A46200146E
+:104EA0008FBF001003E0000827BD00183C0B8008EE
+:104EB00027BDFFE83C028000AFBF00103442010074
+:104EC000356A00809044000A356901008C45001461
+:104ED0008D4800389123000C308400FF0105102319
+:104EE0001C4000B3306700FF2CE20006504000B1C8
+:104EF0008FBF00102402000100E2300430C2000322
+:104F00005440000800A8302330C2000C144000A117
+:104F100030C20030144000A38FBF00100A00143BC1
+:104F20000000000018C00024308200108D43001CD7
+:104F30008D42002C006818230043102B1040000FF6
+:104F4000000000008D22002000461021AD2200202C
+:104F50008D2200200043102B1440000B3C023FFF29
+:104F60008D22002000431023AD2200209542005CDA
+:104F70003042FFFF0A0013AF00621821AD2000206D
+:104F8000006618213C023FFF3446FFFF00C3102B90
+:104F90005440000100C018213C02800834420080C7
+:104FA00000651821AC43001CA0400024A04000274D
+:104FB0000A0013FD3C038008104000403C038008B9
+:104FC0008D42003C004810231840003D34670080AB
+:104FD0009142002424420001A14200249142002475
+:104FE0003C0308008C630024304200FF0043102B78
+:104FF000144000708FBF00108D22001C00A21023EF
+:105000001840006C000000008D6300049542005CB5
+:10501000006818233042FFFF0003184300021040CD
+:105020000043102A10400005014020218D62000439
+:10503000004810230A0013E0000210439542005C70
+:105040003042FFFF000210403C068008AC82002C7A
+:1050500034C5008094A2005C8CA4002C94A3005C56
+:105060003042FFFF00021040008220213063FFFF2A
+:105070000083182101031021ACA2001C8CC2000483
+:1050800034C60100ACC2001C240200020E000F5EF8
+:10509000A0C2000C104000478FBF00103C028000EF
+:1050A0008C4401003C0380008C6201F80440FFFE48
+:1050B000240200020A00142D000000003467008062
+:1050C000ACE50038346601008CC2001C00A210233D
+:1050D0001840000224A2FFFCACC2001C3082000178
+:1050E0005040000A3C0380088CE2003C00A21023E0
+:1050F00004430014240400058C62000414A200037D
+:105100003C0380080A00141F240400058C6200047C
+:1051100014A200288FBF00103C0208008C4200D867
+:10512000304200201040000A3C02800834620080B7
+:10513000906300089042004C144300053C02800834
+:10514000240400048FBF00100A00110927BD0018B5
+:105150003443008034420100A040000C24020001CE
+:10516000A46200143C0280008C4401003C038000D7
+:105170008C6201F80440FFFE24020002AC6401C00E
+:10518000A06201C43C021000AC6201F80A00143BAA
+:105190008FBF00108FBF0010010030210A00115A8C
+:1051A00027BD0018010030210A00129927BD001800
+:1051B0008FBF001003E0000827BD00183C038008E3
+:1051C0003464010024020003A082000C8C620004FD
+:1051D00003E00008AC82001C3C05800834A300807A
+:1051E0009062002734A501002406004324420001F8
+:1051F000A0620027906300273C0208008C42004810
+:10520000306300FF146200043C07602194A500EAAB
+:105210000A00090130A5FFFF03E0000800000000BC
+:1052200027BDFFE8AFBF00103C0280000E00144411
+:105230008C4401803C02800834430100A060000CD3
+:105240008C4200048FBF001027BD001803E0000847
+:10525000AC62001C27BDFFE03C028008AFBF001815
+:10526000AFB10014AFB000103445008034460100E7
+:105270003C0880008D09014090C3000C8CA4003CC8
+:105280008CA200381482003B306700FF9502007C3E
+:1052900090A30027146000093045FFFF2402000599
+:1052A00054E200083C04800890C2000D2442000132
+:1052B000A0C2000D0A00147F3C048008A0C0000DAD
+:1052C0003C048008348201009042000C2403000555
+:1052D000304200FF1443000A24A205DC348300801E
+:1052E000906200272C4200075040000524A20A00CB
+:1052F00090630027240200140062100400A2102111
+:105300003C108008361000803045FFFF012020212E
+:105310000E001444A60500149602005C8E030038AB
+:105320003C1180003042FFFF000210400062182153
+:10533000AE03001C0E0003328E24014092020025B1
+:1053400034420040A20200250E00033D8E2401409D
+:105350008E2401403C0380008C6201F80440FFFE73
+:1053600024020002AC6401C0A06201C43C0210002F
+:10537000AC6201F88FBF00188FB100148FB000101D
+:1053800003E0000827BD00203C0360103C02080039
+:1053900024420174AC62502C8C6250003C048000AA
+:1053A00034420080AC6250003C0208002442547C2D
+:1053B0003C010800AC2256003C020800244254384C
+:1053C0003C010800AC2256043C020002AC840008F8
+:1053D000AC82000C03E000082402000100A0302190
+:1053E0003C1C0800279C56083C0200023C050400B7
+:1053F00000852826008220260004102B2CA5000101
+:105400002C840001000210803C0308002463560035
+:105410000085202500431821108000030000102182
+:10542000AC6600002402000103E000080000000058
+:105430003C1C0800279C56083C0200023C05040066
+:1054400000852826008220260004102B2CA50001B0
+:105450002C840001000210803C03080024635600E5
+:105460000085202500431821108000050000102130
+:105470003C02080024425438AC62000024020001BF
+:1054800003E00008000000003C0200023C030400AE
+:1054900000821026008318262C4200012C63000194
+:1054A000004310251040000B000028213C1C080080
+:1054B000279C56083C0380008C62000824050001EC
+:1054C00000431025AC6200088C62000C00441025DB
+:1054D000AC62000C03E0000800A010213C1C080096
+:1054E000279C56083C0580008CA3000C0004202754
+:1054F000240200010064182403E00008ACA3000C9F
+:105500003C020002148200063C0560008CA208D018
+:105510002403FFFE0043102403E00008ACA208D0DF
+:105520003C02040014820005000000008CA208D098
+:105530002403FFFD00431024ACA208D003E00008C0
+:10554000000000003C02601A344200108C430080CE
+:1055500027BDFFF88C440084AFA3000093A3000094
+:10556000240200041462001AAFA4000493A20001F4
+:105570001040000797A300023062FFFC3C0380004C
+:10558000004310218C4200000A001536AFA200042F
+:105590003062FFFC3C03800000431021AC4400005B
+:1055A000A3A000003C0560008CA208D02403FFFEED
+:1055B0003C04601A00431024ACA208D08FA300045E
+:1055C0008FA2000034840010AC830084AC82008081
+:1055D00003E0000827BD000827BDFFE8AFBF0010AB
+:1055E0003C1C0800279C56083C0280008C43000CA1
+:1055F0008C420004004318243C0200021060001496
+:10560000006228243C0204003C04000210A00005B3
+:10561000006210243C0208008C4256000A00155B10
+:1056200000000000104000073C0404003C02080099
+:105630008C4256040040F809000000000A00156082
+:10564000000000000000000D3C1C0800279C5608CC
+:0C5650008FBF001003E0000827BD001809
+:04565C008008024080
+:1056600080080100800800808008000000000C8095
+:105670000000320008000E9808000EF408000F88A1
+:1056800008001028080010748008010080080080BD
+:04569000800800008E
+:0C5694000A0000280000000000000000D8
+:1056A0000000000D6370362E322E316100000000C4
+:1056B00006020104000000000000000000000000DD
+:1056C000000000000000000038003C000000000066
+:1056D00000000000000000000000000000000020AA
+:1056E00000000000000000000000000000000000BA
+:1056F00000000000000000000000000000000000AA
+:10570000000000000000000021003800000000013F
+:105710000000002B000000000000000400030D400A
+:105720000000000000000000000000000000000079
+:105730000000000000000000100000030000000056
+:105740000000000D0000000D3C020800244259AC8E
+:105750003C03080024635BF4AC4000000043202BB2
+:105760001480FFFD244200043C1D080037BD9FFC4F
+:1057700003A0F0213C100800261000A03C1C0800EB
+:10578000279C59AC0E0002F6000000000000000D3E
+:1057900027BDFFB4AFA10000AFA20004AFA3000873
+:1057A000AFA4000CAFA50010AFA60014AFA700185F
+:1057B000AFA8001CAFA90020AFAA0024AFAB0028FF
+:1057C000AFAC002CAFAD0030AFAE0034AFAF00389F
+:1057D000AFB8003CAFB90040AFBC0044AFBF004819
+:1057E0000E000820000000008FBF00488FBC00445E
+:1057F0008FB900408FB8003C8FAF00388FAE0034B7
+:105800008FAD00308FAC002C8FAB00288FAA002406
+:105810008FA900208FA8001C8FA700188FA6001446
+:105820008FA500108FA4000C8FA300088FA2000486
+:105830008FA1000027BD004C3C1B60188F7A5030B0
+:10584000377B502803400008AF7A000000A01821E1
+:1058500000801021008028213C0460003C0760008B
+:105860002406000810600006348420788C42000072
+:10587000ACE220088C63000003E00008ACE3200CDD
+:105880000A000F8100000000240300403C02600079
+:1058900003E00008AC4320003C0760008F86000452
+:1058A0008CE520740086102100A2182B14600007DC
+:1058B000000028218F8AFDA024050001A1440013C7
+:1058C0008F89000401244021AF88000403E0000810
+:1058D00000A010218F84FDA08F8500049086001306
+:1058E00030C300FF00A31023AF82000403E00008D0
+:1058F000A08000138F84FDA027BDFFE8AFB000108B
+:10590000AFBF001490890011908700112402002875
+:10591000312800FF3906002830E300FF2485002CE1
+:105920002CD00001106200162484001C0E00006EB2
+:10593000000000008F8FFDA03C05600024020204DF
+:1059400095EE003E95ED003C000E5C0031ACFFFF93
+:10595000016C5025ACAA2010520000012402000462
+:10596000ACA22000000000000000000000000000C9
+:105970008FBF00148FB0001003E0000827BD00188F
+:105980000A0000A6000028218F85FDA027BDFFD8B2
+:10599000AFBF0020AFB3001CAFB20018AFB100140E
+:1059A000AFB000100080982190A4001124B0001C1A
+:1059B00024B1002C308300FF386200280E000090D4
+:1059C0002C5200010E00009800000000020020216F
+:1059D0001240000202202821000028210E00006E43
+:1059E000000000008F8DFDA03C0880003C05600099
+:1059F00095AC003E95AB003C02683025000C4C0095
+:105A0000316AFFFF012A3825ACA7201024020202C8
+:105A1000ACA6201452400001240200028FBF0020D7
+:105A20008FB3001C8FB200188FB100148FB000101C
+:105A300027BD002803E00008ACA2200027BDFFE03E
+:105A4000AFB20018AFB10014AFB00010AFBF001C70
+:105A50003C1160008E2320748F82000430D0FFFF41
+:105A600030F2FFFF1062000C2406008F0E00006E63
+:105A7000000000003C06801F0010440034C5FF00F9
+:105A80000112382524040002AE2720100000302126
+:105A9000AE252014AE2420008FBF001C8FB200184A
+:105AA0008FB100148FB0001000C0102103E0000877
+:105AB00027BD002027BDFFE0AFB0001030D0FFFFB2
+:105AC000AFBF0018AFB100140E00006E30F1FFFF41
+:105AD00000102400009180253C036000AC70201071
+:105AE0008FBF00188FB100148FB000102402000483
+:105AF000AC62200027BD002003E000080000102158
+:105B000027BDFFE03C046018AFBF0018AFB1001420
+:105B1000AFB000108C8850002403FF7F34028071E6
+:105B20000103382434E5380C241F00313C1980006F
+:105B3000AC8550003C11800AAC8253BCAF3F0008DA
+:105B40000E00054CAF9100400E00050A3C116000AC
+:105B50000E00007D000000008E3008083C0F570941
+:105B60002418FFF00218602435EEE00035EDF00057
+:105B7000018E5026018D58262D4600012D69000109
+:105B8000AF86004C0E000D09AF8900503C06601630
+:105B90008CC700003C0860148D0500A03C03FFFF8B
+:105BA00000E320243C02535300052FC2108200550D
+:105BB00034D07C00960201F2A780006C10400003F4
+:105BC000A780007C384B1E1EA78B006C960201F844
+:105BD000104000048F8D0050384C1E1EA78C007C96
+:105BE0008F8D005011A000058F83004C240E0020E3
+:105BF000A78E007CA78E006C8F83004C1060000580
+:105C00009785007C240F0020A78F007CA78F006C55
+:105C10009785007C2CB8008153000001240500808A
+:105C20009784006C2C91040152200001240404008C
+:105C30001060000B3C0260008FBF00188FB1001491
+:105C40008FB0001027BD0020A784006CA785007CC2
+:105C5000A380007EA780007403E00008A780009264
+:105C60008C4704382419103C30FFFFFF13F9000360
+:105C700030A8FFFF1100004624030050A380007EDF
+:105C80009386007E50C00024A785007CA780007CFE
+:105C90009798007CA780006CA7800074A780009272
+:105CA0003C010800AC3800800E00078700000000AF
+:105CB0003C0F60008DED0808240EFFF03C0B600ED9
+:105CC000260C0388356A00100000482100002821B6
+:105CD00001AE20243C105709AF8C0010AF8A004859
+:105CE000AF89001810900023AF8500148FBF0018F3
+:105CF0008FB100148FB0001027BD002003E0000812
+:105D0000AF80005400055080014648218D260004D4
+:105D10000A00014800D180219798007CA784006C7C
+:105D2000A7800074A78000923C010800AC38008076
+:105D30000E000787000000003C0F60008DED080892
+:105D4000240EFFF03C0B600E260C0388356A001011
+:105D5000000048210000282101AE20243C105709F2
+:105D6000AF8C0010AF8A0048AF8900181490FFDF95
+:105D7000AF85001424110001AF9100548FBF0018AB
+:105D80008FB100148FB0001003E0000827BD002081
+:105D90000A00017BA383007E3083FFFF8F880040D1
+:105DA0008F87003C000321403C0580003C020050EE
+:105DB000008248253C0660003C0A010034AC040027
+:105DC0008CCD08E001AA58241160000500000000F5
+:105DD0008CCF08E024E7000101EA7025ACCE08E092
+:105DE0008D19001001805821ACB900388D180014AD
+:105DF000ACB8003CACA9003000000000000000007E
+:105E00000000000000000000000000000000000092
+:105E100000000000000000003C0380008C640000D3
+:105E2000308200201040FFFD3C0F60008DED08E047
+:105E30003C0E010001AE18241460FFE100000000D8
+:105E4000AF87003C03E00008AF8B00588F8500400F
+:105E5000240BFFF03C06800094A7001A8CA90024B4
+:105E600030ECFFFF000C38C000EB5024012A402129
+:105E7000ACC8003C8CA400248CC3003C00831023DD
+:105E800018400033000000008CAD002025A2000166
+:105E90003C0F0050ACC2003835EE00103C068000CC
+:105EA000ACCE003000000000000000000000000048
+:105EB00000000000000000000000000000000000E2
+:105EC000000000003C0480008C9900003338002062
+:105ED0001300FFFD30E20008104000173C0980006D
+:105EE0008C880408ACA800108C83040CACA30014AC
+:105EF0003C1900203C188000AF19003094AE001807
+:105F000094AF001C01CF3021A4A6001894AD001A54
+:105F100025A70001A4A7001A94AB001A94AC001E98
+:105F2000118B00030000000003E0000800000000E7
+:105F300003E00008A4A0001A8D2A0400ACAA0010F7
+:105F40008D240404ACA400140A0002183C1900209B
+:105F50008CA200200A0002003C0F00500A0001EE53
+:105F60000000000027BDFFE8AFBF00100E000232A6
+:105F7000000000008F8900408FBF00103C038000AC
+:105F8000A520000A9528000A9527000427BD0018BF
+:105F90003105FFFF30E6000F0006150000A22025A6
+:105FA00003E00008AC6400803C0508008CA50020DC
+:105FB0008F83000C27BDFFE8AFB00010AFBF001407
+:105FC00010A300100000802124040001020430040A
+:105FD00000A6202400C3102450440006261000010F
+:105FE000001018802787FDA41480000A006718217C
+:105FF000261000012E0900025520FFF38F83000CAC
+:10600000AF85000C8FBF00148FB0001003E00008B4
+:1060100027BD00188C6800003C058000ACA8002457
+:106020000E000234261000013C0508008CA500205B
+:106030000A0002592E0900022405000100851804F7
+:106040003C0408008C84002027BDFFC8AFBF00348B
+:1060500000831024AFBE0030AFB7002CAFB60028CD
+:10606000AFB50024AFB40020AFB3001CAFB200182E
+:10607000AFB1001410400051AFB000108F84004049
+:10608000948700069488000A00E8302330D5FFFF8B
+:1060900012A0004B8FBF0034948B0018948C000A20
+:1060A000016C50233142FFFF02A2482B1520000251
+:1060B00002A02021004020212C8F000515E00002C5
+:1060C00000809821241300040E0001C102602021E9
+:1060D0008F87004002609021AF80004494F4000A52
+:1060E000026080211260004E3291FFFF3C1670006A
+:1060F0003C1440003C1E20003C1760008F99005863
+:106100008F380000031618241074004F0283F82BF8
+:1061100017E0003600000000107E00478F86004424
+:1061200014C0003A2403000102031023022320219B
+:106130003050FFFF1600FFF13091FFFF8F870040C6
+:106140003C1100203C108000AE11003094EB000A9E
+:106150003C178000024B5021A4EA000A94E9000A8F
+:1061600094E800043123FFFF3106000F00062D00E4
+:106170000065F025AEFE008094F3000A94F6001846
+:1061800012D30036001221408CFF00148CF4001052
+:1061900003E468210000C02101A4782B029870213B
+:1061A00001CF6021ACED0014ACEC001002B238233A
+:1061B00030F5FFFF16A0FFB88F8400408FBF00347A
+:1061C0008FBE00308FB7002C8FB600288FB500240B
+:1061D0008FB400208FB3001C8FB200188FB1001451
+:1061E0008FB0001003E0000827BD00381477FFCC03
+:1061F0008F8600440E000EE202002021004018218C
+:106200008F86004410C0FFC9020310230270702360
+:106210008F87004001C368210A0002E431B2FFFF0A
+:106220008F86004414C0FFC93C1100203C10800040
+:106230000A0002AEAE1100300E00046602002021FA
+:106240000A0002DB00401821020020210E0009395B
+:10625000022028210A0002DB004018210E0001EE76
+:10626000000000000A0002C702B2382327BDFFC8A1
+:10627000AFB7002CAFB60028AFB50024AFB40020F4
+:10628000AFB3001CAFB20018AFB10014AFB0001034
+:10629000AFBF00300E00011B241300013C047FFF40
+:1062A0003C0380083C0220003C010800AC20007048
+:1062B0003496FFFF34770080345200033C1512C03F
+:1062C000241400013C1080002411FF800E000245C0
+:1062D000000000008F8700488F8B00188F89001402
+:1062E0008CEA00EC8CE800E8014B302B01092823F4
+:1062F00000A6102314400006014B18231440000E82
+:106300003C05800002A3602B1180000B0000000000
+:106310003C0560008CEE00EC8CED00E88CA4180CC1
+:10632000AF8E001804800053AF8D00148F8F0010C3
+:10633000ADF400003C0580008CBF00003BF900017B
+:10634000333800011700FFE13C0380008C6201003C
+:1063500024060C0010460009000000008C680100B3
+:106360002D043080548000103C0480008C690100B2
+:106370002D2331811060000C3C0480008CAA0100A8
+:1063800011460004000020218CA6010024C5FF81D5
+:1063900030A400FF8E0B01000E000269AE0B00243A
+:1063A0000A00034F3C0480008C8D01002DAC3300AB
+:1063B00011800022000000003C0708008CE70098D4
+:1063C00024EE00013C010800AC2E00983C04800043
+:1063D0008C8201001440000300000000566000148D
+:1063E0003C0440008C9F01008C9801000000982123
+:1063F00003F1C82400193940330F007F00EF7025E6
+:1064000001D26825AC8D08308C8C01008C85010090
+:10641000258B0100017130240006514030A3007F1C
+:106420000143482501324025AC8808303C04400037
+:10643000AE0401380A00030E000000008C99010030
+:10644000240F0020AC99002092F80000330300FFD5
+:10645000106F000C241F0050547FFFDD3C048000AF
+:106460008C8401000E00154E000000000A00034F4E
+:106470003C04800000963824ACA7180C0A000327BF
+:106480008F8F00108C8501000E0008F72404008017
+:106490000A00034F3C04800000A4102B24030001D9
+:1064A00010400009000030210005284000A4102BF6
+:1064B00004A00003000318405440FFFC00052840DE
+:1064C0005060000A0004182B0085382B54E00004AB
+:1064D0000003184200C33025008520230003184222
+:1064E0001460FFF9000528420004182B03E000089F
+:1064F00000C310213084FFFF30C600FF3C0780003E
+:106500008CE201B80440FFFE00064C000124302557
+:106510003C08200000C820253C031000ACE00180AE
+:10652000ACE50184ACE4018803E00008ACE301B809
+:106530003C0660008CC5201C2402FFF03083020062
+:10654000308601001060000E00A2282434A500014E
+:106550003087300010E0000530830C0034A50004C3
+:106560003C04600003E00008AC85201C1060FFFDC7
+:106570003C04600034A5000803E00008AC85201C42
+:1065800054C0FFF334A500020A0003B03087300086
+:1065900027BDFFE8AFB00010AFBF00143C0760009C
+:1065A000240600021080001100A080218F83005873
+:1065B0000E0003A78C6400188F8200580000202171
+:1065C000240600018C45000C0E000398000000001A
+:1065D0001600000224020003000010218FBF0014E7
+:1065E0008FB0001003E0000827BD00188CE8201CC5
+:1065F0002409FFF001092824ACE5201C8F870058EE
+:106600000A0003CD8CE5000C3C02600E00804021A6
+:1066100034460100240900180000000000000000BA
+:10662000000000003C0A00503C0380003547020097
+:10663000AC68003834640400AC65003CAC670030E2
+:106640008C6C0000318B00201160FFFD2407FFFFE0
+:106650002403007F8C8D00002463FFFF248400044A
+:10666000ACCD00001467FFFB24C60004000000004E
+:10667000000000000000000024A402000085282B78
+:106680003C0300203C0E80002529FFFF010540212E
+:10669000ADC300301520FFE00080282103E0000892
+:1066A000000000008F82005827BDFFD8AFB3001C48
+:1066B000AFBF0020AFB20018AFB10014AFB00010F0
+:1066C00094460002008098218C5200182CC300814F
+:1066D0008C4800048C4700088C51000C8C49001039
+:1066E000106000078C4A00142CC4000414800013AE
+:1066F00030EB000730C5000310A0001000000000C0
+:106700002410008B02002021022028210E00039873
+:10671000240600031660000224020003000010217A
+:106720008FBF00208FB3001C8FB200188FB10014F0
+:106730008FB0001003E0000827BD00281560FFF1AE
+:106740002410008B3C0C80003C030020241F00011F
+:10675000AD830030AF9F0044000000000000000047
+:10676000000000002419FFF024D8000F031978243A
+:106770003C1000D0AD88003801F0702524CD000316
+:106780003C08600EAD87003C35850400AD8E0030BE
+:10679000000D38823504003C3C0380008C6B000007
+:1067A000316200201040FFFD0000000010E00008F2
+:1067B00024E3FFFF2407FFFF8CA800002463FFFFF2
+:1067C00024A50004AC8800001467FFFB24840004A7
+:1067D0003C05600EACA60038000000000000000080
+:1067E000000000008F8600543C0400203C0780001D
+:1067F000ACE4003054C000060120202102402021DA
+:106800000E0003A7000080210A00041D02002021C1
+:106810000E0003DD01402821024020210E0003A7C5
+:10682000000080210A00041D0200202127BDFFE096
+:10683000AFB200183092FFFFAFB10014AFBF001C21
+:10684000AFB000101640000D000088210A0004932C
+:106850000220102124050003508500278CE5000C40
+:106860000000000D262800013111FFFF24E2002066
+:106870000232802B12000019AF8200588F82004430
+:10688000144000168F8700583C0670003C0320001F
+:106890008CE5000000A62024148300108F84006083
+:1068A000000544023C09800000A980241480FFE90F
+:1068B000310600FF2CCA000B5140FFEB26280001D7
+:1068C000000668803C0E080025CE575801AE6021B6
+:1068D0008D8B0000016000080000000002201021E4
+:1068E0008FBF001C8FB200188FB100148FB0001042
+:1068F00003E0000827BD00200E0003982404008454
+:106900001600FFD88F8700580A000474AF8000601B
+:10691000020028210E0003BF240400018F870058C5
+:106920000A000474AF820060020028210E0003BF39
+:10693000000020210A0004A38F8700580E000404E1
+:10694000020020218F8700580A000474AF82006083
+:1069500030AFFFFF000F19C03C0480008C9001B8DD
+:106960000600FFFE3C1920043C181000AC83018097
+:10697000AC800184AC990188AC9801B80A00047518
+:106980002628000190E2000390E30002000020218D
+:106990000002FE0000033A0000FF2825240600083C
+:1069A0000E000398000000001600FFDC2402000324
+:1069B0008F870058000010210A000474AF82006025
+:1069C00090E8000200002021240600090A0004C308
+:1069D00000082E0090E4000C240900FF308500FF21
+:1069E00010A900150000302190F9000290F8000372
+:1069F000308F00FF94EB000400196E000018740043
+:106A0000000F62000186202501AE5025014B28258C
+:106A10003084FF8B0A0004C32406000A90E30002BE
+:106A200090FF0004000020210003360000DF28252D
+:106A30000A0004C32406000B0A0004D52406008BB8
+:106A4000000449C23127003F000443423C02800059
+:106A500000082040240316802CE60020AC43002CC4
+:106A600024EAFFE02482000114C0000330A900FFE3
+:106A700000801021314700FF000260803C0D800043
+:106A8000240A0001018D20213C0B000E00EA28049D
+:106A9000008B302111200005000538278CCE000026
+:106AA00001C5382503E00008ACC700008CD8000001
+:106AB0000307782403E00008ACCF000027BDFFE007
+:106AC000AFB10014AFB00010AFBF00183C076000BA
+:106AD0008CE408083402F0003C1160003083F000C0
+:106AE000240501C03C04800E000030211062000625
+:106AF000241000018CEA08083149F0003928E00030
+:106B00000008382B000780403C0D0200AE2D081411
+:106B1000240C16803C0B80008E2744000E000F8B47
+:106B2000AD6C002C120000043C02169124050001FB
+:106B3000120500103C023D2C345800E0AE384408E9
+:106B40003C1108008E31007C8FBF00183C066000AD
+:106B500000118540360F16808FB100148FB00010E1
+:106B60003C0E020027BD0020ACCF442003E000080B
+:106B7000ACCE08103C0218DA345800E0AE384408B5
+:106B80003C1108008E31007C8FBF00183C0660006D
+:106B900000118540360F16808FB100148FB00010A1
+:106BA0003C0E020027BD0020ACCF442003E00008CB
+:106BB000ACCE08100A0004EB240500010A0004EB27
+:106BC0000000282124020400A7820024A780001CC2
+:106BD000000020213C06080024C65A582405FFFF67
+:106BE00024890001000440803124FFFF01061821A0
+:106BF0002C87002014E0FFFAAC6500002404040098
+:106C0000A7840026A780001E000020213C06080063
+:106C100024C65AD82405FFFF248D0001000460809B
+:106C200031A4FFFF018658212C8A00201540FFFA6D
+:106C3000AD650000A7800028A7800020A780002263
+:106C4000000020213C06080024C65B582405FFFFF5
+:106C5000249900010004C0803324FFFF030678213B
+:106C60002C8E000415C0FFFAADE500003C05600065
+:106C70008CA73D002403E08F00E31024344601403C
+:106C800003E00008ACA63D002487007F000731C266
+:106C900024C5FFFF000518C2246400013082FFFFF5
+:106CA000000238C0A78400303C010800AC27003047
+:106CB000AF80002C0000282100002021000030219E
+:106CC0002489000100A728213124FFFF2CA81701E7
+:106CD000110000032C8300801460FFF924C600011A
+:106CE00000C02821AF86002C10C0001DA786002AF6
+:106CF00024CAFFFF000A11423C08080025085B581F
+:106D00001040000A00002021004030212407FFFF2E
+:106D1000248E00010004688031C4FFFF01A86021B7
+:106D20000086582B1560FFFAAD87000030A2001FC7
+:106D30005040000800043080240300010043C804D0
+:106D400000041080004878212738FFFF03E0000886
+:106D5000ADF8000000C820212405FFFFAC8500002D
+:106D600003E000080000000030A5FFFF30C6FFFF71
+:106D700030A8001F0080602130E700FF0005294295
+:106D80000000502110C0001D24090001240B000147
+:106D900025180001010B2004330800FF0126782686
+:106DA000390E00202DED00012DC2000101A2182591
+:106DB0001060000D014450250005C880032C4021BF
+:106DC0000100182110E0000F000A20278D040000A8
+:106DD000008A1825AD03000024AD00010000402109
+:106DE0000000502131A5FFFF252E000131C9FFFF12
+:106DF00000C9102B1040FFE72518000103E0000830
+:106E0000000000008D0A0000014440240A0005D162
+:106E1000AC68000027BDFFE830A5FFFF30C6FFFFCC
+:106E2000AFB00010AFBF001430E7FFFF00005021EB
+:106E30003410FFFF0000602124AF001F00C0482174
+:106E4000241800012419002005E0001601E010219B
+:106E50000002F943019F682A0009702B01AE40240B
+:106E600011000017000C18800064102110E00005CC
+:106E70008C4B000000F840040008382301675824B8
+:106E800000003821154000410000402155600016E7
+:106E90003169FFFF258B0001316CFFFF05E1FFEC3D
+:106EA00001E0102124A2003E0002F943019F682A5C
+:106EB0000009702B01AE40241500FFEB000C188078
+:106EC000154600053402FFFF020028210E0005B51B
+:106ED00000003821020010218FBF00148FB0001075
+:106EE00003E0000827BD00181520000301601821E9
+:106EF000000B1C0224080010306A00FF154000053A
+:106F0000306E000F250D000800031A0231A800FFA3
+:106F1000306E000F15C00005307F000325100004FF
+:106F200000031902320800FF307F000317E000055C
+:106F3000386900012502000200031882304800FF72
+:106F4000386900013123000110600004310300FFA3
+:106F5000250A0001314800FF310300FF000C6940A1
+:106F600001A34021240A000110CAFFD53110FFFF00
+:106F7000246E000131C800FF1119FFC638C9000195
+:106F80002D1F002053E0001C258B0001240D000163
+:106F90000A000648240E002051460017258B0001E8
+:106FA00025090001312800FF2D0900205120001281
+:106FB000258B000125430001010D5004014B1024D5
+:106FC000250900011440FFF4306AFFFF3127FFFF5D
+:106FD00010EE000C2582FFFF304CFFFF0000502117
+:106FE0003410FFFF312800FF2D0900205520FFF24B
+:106FF00025430001258B0001014648260A000602B0
+:10700000316CFFFF00003821000050210A000654B7
+:107010003410FFFF27BDFFD8AFB0001030F0FFFFE6
+:10702000AFB10014001039423211FFE000071080A8
+:10703000AFB3001C00B1282330D3FFFFAFB200185C
+:1070400030A5FFFF00809021026030210044202104
+:10705000AFBF00200E0005E03207001F022288218A
+:107060003403FFFF0240202102002821026030216A
+:1070700000003821104300093231FFFF02201021A7
+:107080008FBF00208FB3001C8FB200188FB1001487
+:107090008FB0001003E0000827BD00280E0005E0B7
+:1070A0000000000000408821022010218FBF002036
+:1070B0008FB3001C8FB200188FB100148FB0001076
+:1070C00003E0000827BD0028000424003C03600002
+:1070D000AC603D0810A00002348210063482101605
+:1070E00003E00008AC623D0427BDFFE0AFB0001034
+:1070F000309000FF2E020006AFBF001810400008BD
+:10710000AFB10014001030803C03080024635784A2
+:1071100000C328218CA400000080000800000000AB
+:10712000000020218FBF00188FB100148FB0001015
+:107130000080102103E0000827BD00209791002A5D
+:1071400016200051000020213C020800904200332C
+:107150000A0006BB00000000978D002615A0003134
+:10716000000020210A0006BB2402000897870024A3
+:1071700014E0001A00001821006020212402000100
+:107180001080FFE98FBF0018000429C2004530219C
+:1071900000A6582B1160FFE43C0880003C0720004B
+:1071A000000569C001A76025AD0C00203C038008E4
+:1071B0002402001F2442FFFFAC6000000441FFFDD9
+:1071C0002463000424A5000100A6702B15C0FFF560
+:1071D000000569C00A0006A58FBF00189787001C2C
+:1071E0003C04080024845A58240504000E0006605C
+:1071F00024060001978B002424440001308AFFFFFD
+:107200002569FFFF2D48040000402821150000409B
+:10721000A789002424AC3800000C19C00A0006B964
+:10722000A780001C9787001E3C04080024845AD8BD
+:10723000240504000E00066024060001979900262C
+:10724000244400013098FFFF272FFFFF2F0E04007A
+:107250000040882115C0002CA78F0026A780001EA3
+:107260003A020003262401003084FFFF0E00068D41
+:107270002C4500010011F8C027F00100001021C0CA
+:107280000A0006BB240200089785002E978700227B
+:107290003C04080024845B580E00066024060001AC
+:1072A0009787002A8F89002C2445000130A8FFFF12
+:1072B00024E3FFFF0109302B0040802114C0001897
+:1072C000A783002AA7800022978500300E000F7543
+:1072D00002002021244A05003144FFFF0E00068DE4
+:1072E000240500013C05080094A500320E000F752E
+:1072F00002002021244521003C0208009042003376
+:107300000A0006BB000521C00A0006F3A784001E80
+:1073100024AC3800000C19C00A0006B9A784001C70
+:107320000A00070DA7850022308400FF27BDFFE873
+:107330002C820006AFBF0014AFB000101040001543
+:1073400000A03821000440803C0308002463579CBF
+:10735000010328218CA40000008000080000000028
+:1073600024CC007F000751C2000C59C23170FFFFCE
+:107370002547C40030E5FFFF2784001C02003021B0
+:107380000E0005B52407000197860028020620217B
+:10739000A78400288FBF00148FB0001003E00008FE
+:1073A00027BD00183C0508008CA50030000779C2F5
+:1073B0000E00038125E4DF003045FFFF3C04080098
+:1073C00024845B58240600010E0005B52407000143
+:1073D000978E002A8FBF00148FB0001025CD0001BA
+:1073E00027BD001803E00008A78D002A0007C9C2C6
+:1073F0002738FF00001878C231F0FFFF3C04080076
+:1074000024845AD802002821240600010E0005B564
+:1074100024070001978D0026260E0100000E84002F
+:1074200025AC00013C0B6000A78C0026AD603D0838
+:1074300036040006000030213C0760008CE23D0469
+:10744000305F000617E0FFFD24C9000100061B00A5
+:10745000312600FF006440252CC50004ACE83D0443
+:1074600014A0FFF68FBF00148FB0001003E00008D7
+:1074700027BD0018000751C22549C8002406000195
+:10748000240700013C04080024845A580E0005B566
+:107490003125FFFF978700248FBF00148FB00010A5
+:1074A00024E6000127BD001803E00008A786002499
+:1074B0003C0660183C090800252900FCACC9502C8A
+:1074C0008CC850003C0580003C020002350700805B
+:1074D000ACC750003C04080024841FE03C030800B3
+:1074E00024631F98ACA50008ACA2000C3C01080066
+:1074F000AC2459A43C010800AC2359A803E00008BF
+:107500002402000100A030213C1C0800279C59AC3B
+:107510003C0C04003C0B0002008B3826008C4026FB
+:107520002CE200010007502B2D050001000A4880C5
+:107530003C030800246359A4004520250123182199
+:107540001080000300001021AC660000240200013E
+:1075500003E00008000000003C1C0800279C59AC18
+:107560003C0B04003C0A0002008A3026008B3826BF
+:107570002CC200010006482B2CE5000100094080C8
+:107580003C030800246359A4004520250103182169
+:1075900010800005000010213C0C0800258C1F986D
+:1075A000AC6C00002402000103E0000800000000B1
+:1075B0003C0900023C080400008830260089382677
+:1075C0002CC30001008028212CE400010083102539
+:1075D0001040000B000030213C1C0800279C59ACD7
+:1075E0003C0A80008D4E00082406000101CA68256F
+:1075F000AD4D00088D4C000C01855825AD4B000C9D
+:1076000003E0000800C010213C1C0800279C59AC76
+:107610003C0580008CA6000C0004202724020001F9
+:1076200000C4182403E00008ACA3000C3C020002D4
+:107630001082000B3C0560003C070400108700032B
+:107640000000000003E00008000000008CA908D042
+:10765000240AFFFD012A402403E00008ACA808D05A
+:107660008CA408D02406FFFE0086182403E000083E
+:10767000ACA308D03C05601A34A600108CC300806F
+:1076800027BDFFF88CC50084AFA3000093A40000C1
+:107690002402001010820003AFA5000403E00008DC
+:1076A00027BD000893A7000114E0001497AC000266
+:1076B00097B800023C0F8000330EFFFC01CF682119
+:1076C000ADA50000A3A000003C0660008CC708D058
+:1076D0002408FFFE3C04601A00E82824ACC508D04A
+:1076E0008FA300048FA200003499001027BD00086A
+:1076F000AF22008003E00008AF2300843C0B800031
+:10770000318AFFFC014B48218D2800000A00080C3B
+:10771000AFA8000427BDFFE8AFBF00103C1C080065
+:10772000279C59AC3C0580008CA4000C8CA2000462
+:107730003C0300020044282410A0000A00A31824DF
+:107740003C0604003C0400021460000900A610245A
+:107750001440000F3C0404000000000D3C1C080015
+:10776000279C59AC8FBF001003E0000827BD00180C
+:107770003C0208008C4259A40040F80900000000B7
+:107780003C1C0800279C59AC0A0008358FBF00102C
+:107790003C0208008C4259A80040F8090000000093
+:1077A0000A00083B000000003C0880008D0201B880
+:1077B0000440FFFE35090180AD2400003C031000A9
+:1077C00024040040AD250004A1240008A1260009DE
+:1077D000A527000A03E00008AD0301B83084FFFFCD
+:1077E0000080382130A5FFFF000020210A00084555
+:1077F000240600803087FFFF8CA400002406003898
+:107800000A000845000028218F8300788F860070C9
+:107810001066000B008040213C07080024E75B68ED
+:10782000000328C000A710218C440000246300013D
+:10783000108800053063000F5466FFFA000328C06B
+:1078400003E00008000010213C07080024E75B6CFF
+:1078500000A7302103E000088CC200003C03900028
+:1078600034620001008220253C038000AC640020CB
+:107870008C65002004A0FFFE0000000003E000086B
+:10788000000000003C0280003443000100832025FA
+:1078900003E00008AC44002027BDFFE0AFB10014B6
+:1078A0003091FFFFAFB00010AFBF001812200013DF
+:1078B00000A080218CA20000240400022406020003
+:1078C0001040000F004028210E0007250000000096
+:1078D00000001021AE000000022038218FBF0018E8
+:1078E0008FB100148FB0001000402021000028212B
+:1078F000000030210A00084527BD00208CA20000AE
+:10790000022038218FBF00188FB100148FB00010F3
+:107910000040202100002821000030210A000845F5
+:1079200027BD002000A010213087FFFF8CA5000498
+:107930008C4400000A000845240600068F83FD9C45
+:1079400027BDFFE8AFBF0014AFB00010906700087C
+:10795000008010210080282130E600400000202116
+:1079600010C000088C5000000E0000BD0200202155
+:10797000020020218FBF00148FB000100A000548BC
+:1079800027BD00180E0008A4000000000E0000BD76
+:1079900002002021020020218FBF00148FB00010B0
+:1079A0000A00054827BD001827BDFFE0AFB0001052
+:1079B0008F90FD9CAFBF001CAFB20018AFB1001498
+:1079C00092060001008088210E00087230D2000467
+:1079D00092040005001129C2A6050000348300406E
+:1079E000A20300050E00087C022020210E00054A9B
+:1079F0000220202124020001AE02000C02202821D6
+:107A0000A602001024040002A602001224060200AE
+:107A1000A60200140E000725A60200161640000F4D
+:107A20008FBF001C978C00743C0B08008D6B007896
+:107A30002588FFFF3109FFFF256A0001012A382B45
+:107A400010E00006A78800743C0F6006240E0016A4
+:107A500035ED0010ADAE00508FBF001C8FB2001886
+:107A60008FB100148FB0001003E0000827BD002084
+:107A700027BDFFE0AFB10014AFBF0018AFB00010DA
+:107A80001080000400A088212402008010820007DA
+:107A9000000000000000000D8FBF00188FB100141F
+:107AA0008FB0001003E0000827BD00200E00087210
+:107AB00000A020218F86FD9C0220202190C500057A
+:107AC0000E00087C30B000FF2403003E1603FFF1D7
+:107AD0003C0680008CC401780480FFFE34C801405D
+:107AE000240900073C071000AD11000002202021EE
+:107AF000A10900048FBF00188FB100148FB00010CF
+:107B0000ACC701780A0008C527BD002027BDFFE0EB
+:107B1000AFB00010AFBF0018AFB100143C10800030
+:107B20008E110020000000000E00054AAE04002067
+:107B3000AE1100208FBF00188FB100148FB000105D
+:107B400003E0000827BD00203084FFFF00803821BB
+:107B50002406003500A020210A0008450000282145
+:107B60003084FFFF008038212406003600A0202149
+:107B70000A0008450000282127BDFFD0AFB500242A
+:107B80003095FFFFAFB60028AFB40020AFBF002C88
+:107B9000AFB3001CAFB20018AFB10014AFB000100B
+:107BA00030B6FFFF12A000270000A0218F920058DE
+:107BB0008E4300003C0680002402004000033E0289
+:107BC00000032C0230E4007F006698241482001D1C
+:107BD00030A500FF8F8300682C68000A1100001098
+:107BE0008F8D0044000358803C0C0800258C57B84A
+:107BF000016C50218D4900000120000800000000A8
+:107C000002D4302130C5FFFF0E0008522404008446
+:107C1000166000028F920058AF8000688F8D00447C
+:107C20002659002026980001032090213314FFFFDD
+:107C300015A00004AF9900580295202B1480FFDC9A
+:107C400000000000028010218FBF002C8FB600289A
+:107C50008FB500248FB400208FB3001C8FB20018A2
+:107C60008FB100148FB0001003E0000827BD003072
+:107C70002407003414A70149000000009247000EB9
+:107C80008F9FFDA08F90FD9C24181600A3E700197C
+:107C90009242000D3C0880003C07800CA3E20018D3
+:107CA000964A00123C0D60003C117FFFA60A005C62
+:107CB000964400103623FFFF240200053099FFFF91
+:107CC000AE1900548E46001CAD1800288CEF000041
+:107CD0008DAE444801E6482601C93021AE06003881
+:107CE0008E05003824CB00013C0E7F00AE05003C21
+:107CF0008E0C003CAFEC0004AE0B00208E13002075
+:107D0000AE13001CA3E0001BAE03002CA3E2001284
+:107D10008E4A001424130050AE0A00348E0400343E
+:107D2000AFE400148E590018AE1900489258000CA8
+:107D3000A218004E920D000835AF0020A20F0008D7
+:107D40008E090018012E282434AC4000AE0C001817
+:107D5000920B0000317200FF1253027F2403FF8058
+:107D60003C04080024845BE80E0008AA0000000020
+:107D70003C1108008E315BE80E00087202202021C1
+:107D80002405000424080001A2050025022020216A
+:107D90000E00087CA20800053C0580008CB001782C
+:107DA0000600FFFE8F92005834AE0140240F0002FF
+:107DB0003C091000ADD10000A1CF0004ACA90178AE
+:107DC0000A000962AF8000682CAD003751A0FF9413
+:107DD0008F8D0044000580803C110800263157E05B
+:107DE000021178218DEE000001C0000800000000A3
+:107DF0002411000414B1008C3C0780003C080800EA
+:107E00008D085BE88F86FD9CACE800208E4500085D
+:107E10008F99FDA0240D0050ACC500308E4C000899
+:107E2000ACCC00508E4B000CACCB00348E43001019
+:107E3000ACC300388E4A0010ACCA00548E42001405
+:107E4000ACC2003C8E5F0018AF3F00048E50001C97
+:107E5000ACD0002090C40000309800FF130D024AFF
+:107E6000000000008CC400348CD00030009030231F
+:107E700004C000F12404008C126000EE2402000310
+:107E80000A000962AF8200682419000514B900666F
+:107E90003C0580003C0808008D085BE88F86FD9C4F
+:107EA000ACA800208E4C00048F8AFDA0240720007F
+:107EB000ACCC001C924B000824120008A14B001906
+:107EC0008F82005890430009A14300188F85005805
+:107ED00090BF000A33E400FF1092001028890009C7
+:107EE000152000BA240E0002240D0020108D000B76
+:107EF000340780002898002117000008240740005C
+:107F000024100040109000053C0700012419008057
+:107F1000109900023C070002240740008CC20018A0
+:107F20003C03FF00004350240147F825ACDF001854
+:107F300090B2000BA0D200278F8300589464000CED
+:107F4000108001FE000000009467000C3C1F8000C0
+:107F50002405FFBFA4C7005C9063000E2407000443
+:107F6000A0C300088F820058904A000FA0CA0009E1
+:107F70008F8900588D3200108FE400740244C823AA
+:107F8000ACD900588D300014ACD0002C95380018B6
+:107F9000330DFFFFACCD00409531001A322FFFFFAB
+:107FA000ACCF00448D2E001CACCE00489128000EB2
+:107FB000A0C8000890CC000801855824126001B6C2
+:107FC000A0CB00088F9200580A000962AF870068B2
+:107FD0002406000614A600143C0E80003C0F080086
+:107FE0008DEF5BE88F85FD98ADCF00208E4900189E
+:107FF0008F86FD9C8F8BFDA0ACA900008CC800383B
+:1080000024040005ACA800048CCC003C1260008164
+:10801000AD6C00000A000962AF84006824110007FB
+:1080200010B1004B240400063C05080024A55BE8C1
+:108030000E000881240400818F9200580013102B39
+:108040000A000962AF820068241F002314BFFFF6F4
+:108050003C0C80003C0508008CA55BE88F8BFDA0E4
+:10806000AD8500208F91FD9C8E4600042564002084
+:1080700026450014AE260028240600030E000F81BA
+:10808000257000308F87005802002021240600034D
+:108090000E000F8124E500083C04080024845BE8FE
+:1080A0000E0008AA0000000092230000240A0050DD
+:1080B000306200FF544AFFE18F9200580E000F6CAF
+:1080C000000000000A000A6A8F920058240800335A
+:1080D00014A800323C0380003C1108008E315BE89C
+:1080E0008F8FFDA0AC7100208E420008240D002867
+:1080F0008F89FD9CADE200308E4A000C24060009F9
+:10810000ADEA00348E5F0010ADFF00388E440014DD
+:10811000ADE400208E590018ADF900248E58001CE3
+:10812000ADF80028A1ED00118E4E00041260003160
+:10813000AD2E00288F9200580A000962AF860068B1
+:10814000240D002214ADFFB8000000002404000735
+:108150003C1008008E105BE83C188000AF10002037
+:108160005660FEAEAF8400683C04080024845BE8DF
+:108170000E0008AA241300508F84FD9C90920000EA
+:10818000325900FF1333014B000000008F9200585A
+:10819000000020210A000962AF8400683C05080045
+:1081A00024A55BE80E000858240400810A000A6A2E
+:1081B0008F92005802D498213265FFFF0E000852BA
+:1081C000240400840A0009628F920058108EFF5325
+:1081D000240704002887000310E00179241100041B
+:1081E000240F0001548FFF4D240740000A000A228B
+:1081F000240701003C05080024A55BE80E0008A444
+:10820000240400828F920058000030210A00096285
+:10821000AF8600683C04080024845BE88CC2003808
+:108220000E0008AA8CC3003C8F9200580A000AC0B6
+:1082300000002021240400823C05080024A55BE8FE
+:108240000E0008A4000000008F92005800001021CA
+:108250000A000962AF8200688E5000048F91FD9C75
+:108260003C078000ACF00020922C00050200282181
+:10827000318B0002156001562404008A8F92FDA004
+:108280002404008D9245001B30A6002014C001502C
+:1082900002002821922E00092408001231C900FF93
+:1082A0001128014B240400810E00087202002021D5
+:1082B0009258001B240F000402002021370D0042B9
+:1082C000A24D001B0E00087CA22F00253C0580005B
+:1082D0008CA401780480FFFE34B90140241F000201
+:1082E000AF300000A33F00048F9200583C101000F4
+:1082F000ACB001780A000A6B0013102B8E500004FA
+:108300008F91FD9C3C038000AC700020922A0005F8
+:108310000200282131420002144000172404008A80
+:10832000922C00092412000402002821318B00FF46
+:1083300011720011240400810E0008720200202135
+:108340008F89FDA0240800122405FFFE912F001B39
+:108350000200202135EE0020A12E001BA2280009DA
+:108360009226000500C538240E00087CA2270005CF
+:1083700002002821000020210E0009330000000027
+:108380000A000A6A8F9200588E4C00043C07800055
+:108390003C10080026105BE8ACEC00203C01080013
+:1083A000AC2C5BE8924B0003317100041220013BBE
+:1083B0008F84FD9C24020006A0820009924F001BBE
+:1083C000240EFFC031E9003F012E4025A08800089F
+:1083D0009245000330A6000114C0013200000000E5
+:1083E0008E420008AE0200083C0208008C425BF09E
+:1083F000104001318F90FDA0000219C28F8DFD9CAD
+:10840000A603000C8E4A000C24180001240400145A
+:10841000AE0A002C8E420010AE02001C965F0016C1
+:10842000A61F003C96590014A619003EADB8000CDA
+:10843000A5B80010A5B80012A5B80014A5B800167C
+:1084400012600144A2040011925100033232000272
+:108450002E5300018F920058266200080A0009621C
+:10846000AF8200688E4400043C1980003C068008FE
+:10847000AF2400208E45000890D80000240D005045
+:10848000331100FF122D009C2407008824060009E8
+:108490000E000845000000000A000A6A8F9200588A
+:1084A0008E5000043C0980003C118008AD30002053
+:1084B0009228000024050050310400FF10850110AF
+:1084C0002407008802002021000028210E00084512
+:1084D0002406000E922D00002418FF80020028219F
+:1084E00001B8802524040004240600300E0007256E
+:1084F000A23000000A000A6A8F9200588E500004D1
+:108500008F91FDA03C028000AC500020923F001BE8
+:1085100033F900101320006C240700810200202191
+:10852000000028212406001F0E000845000000005E
+:108530000A000A6A8F9200588E44001C0E00085DE3
+:1085400000000000104000E3004048218F880058E0
+:1085500024070089012020218D05001C240600012C
+:108560000E000845000000000A000A6A8F920058B9
+:10857000964900023C10080026105BE831280004F0
+:10858000110000973C0460008E4E001C3C0F8000E0
+:10859000ADEE00203C010800AC2E5BE896470002DF
+:1085A00030E40001148000E6000000008E42000468
+:1085B000AE0200083C1008008E105BF0120000ECC8
+:1085C0003C0F80008F92FD9C241000018E4E0018FD
+:1085D0008F8DFDA08F9FFD9801CF4825AE490018D3
+:1085E000A2400005AE50000C3C0808008D085BF06E
+:1085F0008F840058A6500010000839C2A6500012FF
+:10860000A6500014A6500016A5A7000C8C8C0008DC
+:108610008F8B00588F8A0058ADAC002C8D63000CF6
+:1086200024070002ADA3001C91460010A1A6001172
+:108630008F82005890450011A3E500088F990058DB
+:1086400093380012A258004E8F910058922F0013B9
+:10865000A1AF00128F920058964E0014A5AE003CB8
+:1086600096490016A5A9003E8E480018ADA8001432
+:108670005660FD6AAF8700683C05080024A55BE8EA
+:108680000E000881000020218F9200580000382140
+:108690000A000962AF8700683C05080024A55BE872
+:1086A0000E0008A4240400828F9200580A000A4D8C
+:1086B000000038210E000F6C000000008F9200585F
+:1086C0000A000AC0000020210E00087202002021CA
+:1086D0009223001B02002021346A00100E00087C47
+:1086E000A22A001B000038210200202100002821BE
+:1086F0000A000BA52406001F9242000C305F000107
+:1087000013E0000300000000964A000EA4CA002CEB
+:10871000924B000C316300025060000600003821CB
+:108720008E470014964C0012ACC7001CA4CC001A53
+:10873000000038210A000B7F240600093C050800D0
+:1087400024A55BE80E0008A42404008B8F92005837
+:108750000A000A4D0013382B3C0C08008D8C5BE896
+:1087600024DFFFFE25930100326B007F016790211B
+:1087700002638824AD110028AE4600E0AE4000E45C
+:108780000A0009B3AE5F001CACC000543C0D0800E9
+:108790008DAD5BE83C18800C37090100ACED00287A
+:1087A0008E510014AD3100E08E4F0014AD2F00E467
+:1087B0008E4E001025C7FFFE0A0009F4AD27001CED
+:1087C0005491FDD6240740000A000A222407100015
+:1087D0000E00092D000000000A000A6A8F9200585E
+:1087E0008C83442C3C12DEAD3651BEEF3C010800B8
+:1087F000AC205BE810710062000000003C196C6264
+:1088000037387970147800082404000297850074C2
+:108810009782006C2404009200A2F82B13E0001948
+:1088200002002821240400020E00069524050200FF
+:108830003C068000ACC200203C010800AC225BE892
+:108840001040000D8F8C0058240A002824040003D7
+:10885000918B0010316300FF546A00012404000171
+:108860000E0000810000000010400004240400837A
+:108870000A000BC28F920058240400833C050800B4
+:1088800024A55BE80E000881000000008F920058CC
+:108890000013382B0A000962AF8700680A000B49F1
+:1088A000240200128E4400080E00085D0000000043
+:1088B0000A000B55AE0200083C05080024A55BE841
+:1088C0000E000858240400878F9200580A000B728B
+:1088D0000013102B240400040E000695240500301C
+:1088E0001440002A004048218F8800582407008344
+:1088F000012020218D05001C0A000BB32406000175
+:108900008F8300788F8600701066FEEE000038219D
+:108910003C07080024E75B6C000320C00087282187
+:108920008CAE000011D0005D246F000131E3000F18
+:108930005466FFFA000320C00A000B8C00003821A7
+:108940008E4400040E00085D000000000A000BC801
+:10895000AE0200083C05080024A55BE80E0008A450
+:10896000240400828F9200580A000B72000010212C
+:108970003C05080024A55BE80A000C7C2404008761
+:108980008C83442C0A000C5B3C196C628F88005865
+:108990003C0780083C0C8000240B0050240A000196
+:1089A000AD820020A0EB0000A0EA000191030004CA
+:1089B000A0E3001891040005A0E400199106000648
+:1089C0003C04080024845B6CA0E6001A91020007B6
+:1089D0003C06080024C65B68A0E2001B9105000865
+:1089E000A0E5001C911F0009A0FF001D9119000ABD
+:1089F000A0F9001E9118000BA0F8001F9112000CA6
+:108A0000A0F200209111000DA0F100219110000EA4
+:108A1000A0F00022910F000FA0EF0023910E001094
+:108A2000A0EE0024910D0011A0ED0025950C00147E
+:108A3000A4EC0028950B00168F8A00708F920078A6
+:108A4000A4EB002A95030018000A10C02545000178
+:108A5000A4E3002C8D1F001C0044C0210046C82147
+:108A600030A5000FAF3F0000AF09000010B20006B4
+:108A7000AF850070000038218D05001C01202021E9
+:108A80000A000BB32406000124AD000131A7000F3A
+:108A9000AF8700780A000CF9000038213C06080076
+:108AA00024C65B680086902100003821ACA000003D
+:108AB0000A000B8CAE4000003C0482013C036000C5
+:108AC00034820E02AC603D68AF80009803E000087D
+:108AD000AC623D6C27BDFFE8AFB000103090FFFFE7
+:108AE000001018422C620041AFBF00141440000275
+:108AF00024040080240300403C010800AC300060E6
+:108B00003C010800AC2300640E000F7500602821B2
+:108B1000244802BF2409FF8001092824001039805D
+:108B2000001030408FBF00148FB0001000A720212C
+:108B300000861821AF8300803C010800AC25005856
+:108B40003C010800AC24005C03E0000827BD0018CD
+:108B5000308300FF30C6FFFF30E400FF3C08800098
+:108B60008D0201B80440FFFE000354000144382583
+:108B70003C09600000E920253C031000AD050180A0
+:108B8000AD060184AD04018803E00008AD0301B81F
+:108B90008F8500583C0A6012354800108CAC0004E8
+:108BA0003C0D600E35A60010318B00062D690001CA
+:108BB000AD0900C48CA70004ACC731808CA20008AA
+:108BC00094A40002ACC231848CA3001C0460000396
+:108BD000A784009003E00008000000008CAF00189C
+:108BE000ACCF31D08CAE001C03E00008ACCE31D449
+:108BF0008F8500588F87FF288F86FF308CAE00044A
+:108C00003C0F601235E80010ACEE00788CAD000827
+:108C1000ACED007C8CAC0010ACCC004C8CAB000CF0
+:108C2000ACCB004894CA00543C0208008C4200447B
+:108C300025490001A4C9005494C400543083FFFFA7
+:108C400010620017000000003C0208008C42004047
+:108C5000A4C200528CA30018ACE300308CA2001414
+:108C6000ACE2002C8CB90018ACF900388CB80014B8
+:108C700024050001ACF800348D0600BC50C5001975
+:108C80008D0200B48D0200B8A4E2004894E40048CC
+:108C9000A4E4004A94E800EA03E000083102FFFF80
+:108CA0003C0208008C420024A4C00054A4C200521C
+:108CB0008CA30018ACE300308CA20014ACE2002CB2
+:108CC0008CB90018ACF900388CB8001424050001E8
+:108CD000ACF800348D0600BC54C5FFEB8D0200B823
+:108CE0008D0200B4A4E2004894E40048A4E4004AE1
+:108CF00094E800EA03E000083102FFFF8F86005885
+:108D00003C0480008CC900088CC80008000929C0F8
+:108D1000000839C0AC87002090C30007306200040F
+:108D20001040003EAF85009490CB0007316A0008E8
+:108D30001140003D8F87FF2C8CCD000C8CCE001491
+:108D400001AE602B11800036000000008CC2000CC8
+:108D5000ACE200708CCB00188F85FF288F88FF3025
+:108D6000ACEB00748CCA00102402FFF8ACAA00D847
+:108D70008CC9000CAD0900608CC4001CACA400D0F0
+:108D800090E3007C0062C824A0F9007C90D8000722
+:108D9000330F000811E000040000000090ED007C9B
+:108DA00035AC0001A0EC007C90CF000731EE000153
+:108DB00011C000060000000090E3007C241800347D
+:108DC00034790002A0F9007CACB800DC90C2000746
+:108DD0003046000210C000040000000090E8007C53
+:108DE00035040004A0E4007C90ED007D3C0B600E97
+:108DF000356A001031AC003FA0EC007D8D4931D4C4
+:108E00003127000110E00002240E0001A0AE00098D
+:108E100094AF00EA03E0000831E2FFFF8F87FF2CE8
+:108E20000A000DAF8CC200140A000DB0ACE0007057
+:108E30008F8C005827BDFFD8AFB3001CAFB200180D
+:108E4000AFB00010AFBF0020AFB10014918F00157C
+:108E50003C13600E3673001031EB000FA38B009CA7
+:108E60008D8F00048D8B0008959F0012959900103E
+:108E70009584001A9598001E958E001C33EDFFFF17
+:108E8000332AFFFF3089FFFF3308FFFF31C7FFFFA1
+:108E90003C010800AC2D00243C010800AC29004432
+:108EA0003C010800AC2A0040AE683178AE67317CE6
+:108EB00091850015959100163C12601236520010F3
+:108EC00030A200FF3230FFFFAE623188AE5000B4F6
+:108ED00091830014959F0018240600010066C804C1
+:108EE00033F8FFFFAE5900B8AE5800BC918E0014A5
+:108EF000AF8F00843C08600631CD00FFAE4D00C04E
+:108F0000918A00159584000E3C07600A314900FFE4
+:108F1000AF8B00883084FFFFAE4900C835110010C8
+:108F20000E000D1034F004103C0208008C4200606A
+:108F30003C0308008C6300643C0608008CC60058A3
+:108F40003C0508008CA5005C8F8400808FBF00204A
+:108F5000AE23004CAE65319CAE030054AE4500DC40
+:108F6000AE6231A0AE6331A4AE663198AE22004845
+:108F70008FB3001CAE0200508FB10014AE4200E06F
+:108F8000AE4300E4AE4600D88FB000108FB2001898
+:108F90000A00057D27BD0028978500929783007CF5
+:108FA00027BDFFE8AFB0001000A3102BAFBF001427
+:108FB000240400058F900058104000552409000239
+:108FC0000E0006958F850080AF8200942404000374
+:108FD0001040004F240900023C0680000E00008172
+:108FE000ACC2002024070001240820001040004DDE
+:108FF00024040005978E00928F8AFF2C24090050CC
+:1090000025C50001A7850092A14900003C0D08007C
+:109010008DAD0064240380008F84FF28000D66005E
+:10902000AD4C0018A5400006954B000A8F85FF3017
+:109030002402FF8001633024A546000A915F000AE4
+:109040000000482103E2C825A159000AA0A0000899
+:10905000A140004CA08000D5961800029783009094
+:109060003C020004A49800EA960F00022418FFBFF7
+:1090700025EE2401A48E00BE8E0D0004ACAD00448C
+:109080008E0C0008ACAC0040A4A00050A4A000547A
+:109090008E0B000C240C0030AC8B00288E060010C8
+:1090A000AC860024A480003EA487004EA487005014
+:1090B000A483003CAD420074AC8800D8ACA800602A
+:1090C000A08700FC909F00D433F9007FA09900D4C2
+:1090D000909000D402187824A08F00D4914E007C88
+:1090E00035CD0001A14D007C938B009CAD480070F4
+:1090F000AC8C00DCA08B00D68F8800888F87008422
+:10910000AC8800C4AC8700C8A5400078A540007AB0
+:109110008FBF00148FB000100120102103E0000861
+:1091200027BD00188F8500940E0007258F860080CC
+:109130000A000E9F2409000227BDFFE0AFB0001017
+:109140008F900058AFB10014AFBF00188E09000413
+:109150000E00054A000921C08E0800048F84FF28F4
+:109160008F82FF30000839C03C068000ACC7002069
+:10917000948500EA904300131460001C30B1FFFF97
+:109180008F8CFF2C918B0008316A00401540000B3A
+:10919000000000008E0D0004022030218FBF001857
+:1091A0008FB100148FB00010240400220000382179
+:1091B000000D29C00A000D2F27BD00200E000098C9
+:1091C000000000008E0D0004022030218FBF001827
+:1091D0008FB100148FB00010240400220000382149
+:1091E000000D29C00A000D2F27BD00200E000090A1
+:1091F000000000008E0D0004022030218FBF0018F7
+:109200008FB100148FB00010240400220000382118
+:10921000000D29C00A000D2F27BD002027BDFFE04B
+:10922000AFB200183092FFFFAFB00010AFBF001C0C
+:10923000AFB100141240001E000080218F8600583C
+:109240008CC500002403000600053F02000514023F
+:1092500030E4000714830016304500FF2CA80006F8
+:1092600011000040000558803C0C0800258C58BCBB
+:10927000016C50218D490000012000080000000011
+:109280008F8E0098240D000111CD005024020002A1
+:10929000AF820098260900013130FFFF24C800206A
+:1092A0000212202B010030211480FFE5AF88005806
+:1092B000020010218FBF001C8FB200188FB1001464
+:1092C0008FB0001003E0000827BD00209387007EC8
+:1092D00054E00034000030210E000DE700000000D3
+:1092E0008F8600580A000EFF240200018F87009825
+:1092F0002405000210E50031240400130000282199
+:1093000000003021240700010E000D2F0000000096
+:109310000A000F008F8600588F83009824020002F5
+:109320001462FFF6240400120E000D9A00000000E3
+:109330008F85009400403021240400120E000D2F70
+:10934000000038210A000F008F8600588F83009894
+:109350002411000310710029241F0002107FFFCE8A
+:1093600026090001240400100000282100003021FB
+:109370000A000F1D240700018F91009824060002A7
+:109380001626FFF9240400100E000E410000000014
+:10939000144000238F9800588F8600580A000EFF53
+:1093A00024020003240400140E000D2F00002821C5
+:1093B0008F8600580A000EFF240200020E000EA93C
+:1093C000000000000A000F008F8600580E000D3FBD
+:1093D00000000000241900022404001400002821C9
+:1093E0000000302100003821AF9900980E000D2FA9
+:1093F000000000000A000F008F8600580E000D5775
+:10940000000000008F8500942419000200403021E4
+:1094100024040010000038210A000F56AF9900986C
+:109420000040382124040010970F0002000028217A
+:109430000E000D2F31E6FFFF8F8600580A000F0047
+:10944000AF9100988F84FF2C3C077FFF34E6FFFF2D
+:109450008C8500182402000100A61824AC83001893
+:1094600003E00008A08200053084FFFF30A5FFFF65
+:109470001080000700001821308200011040000217
+:1094800000042042006518211480FFFB00052840DD
+:1094900003E000080060102110C000070000000079
+:1094A0008CA2000024C6FFFF24A50004AC820000AB
+:1094B00014C0FFFB2484000403E000080000000047
+:1094C00010A0000824A3FFFFAC86000000000000ED
+:1094D000000000002402FFFF2463FFFF1462FFFA74
+:1094E0002484000403E0000800000000000411C010
+:1094F00003E000082442024027BDFFE8AFB000109F
+:1095000000808021AFBF00140E000F9600A0202124
+:1095100000504821240AFF808FBF00148FB0001034
+:10952000012A30243127007F3C08800A3C042100B6
+:1095300000E8102100C428253C03800027BD001846
+:10954000AC650024AF820038AC400000AC6500245C
+:1095500003E00008AC4000403C0D08008DAD005811
+:1095600000056180240AFF8001A45821016C482174
+:10957000012A30243127007F3C08800C3C04210064
+:1095800000E8102100C428253C038000AC650028B9
+:10959000AF82003403E00008AC40002430A5FFFF98
+:1095A0003C0680008CC201B80440FFFE3C086015F8
+:1095B00000A838253C031000ACC40180ACC0018475
+:1095C000ACC7018803E00008ACC301B83C0D08003B
+:1095D0008DAD005800056180240AFF8001A4582148
+:1095E000016C4021010A4824000931403107007F05
+:1095F00000C728253C04200000A418253C02800058
+:10960000AC43083003E00008AF80003427BDFFE81A
+:10961000AFB0001000808021AFBF00140E000F9685
+:1096200000A0202100504821240BFF80012B502452
+:10963000000A39403128007F3C0620008FBF00140B
+:109640008FB0001000E8282534C2000100A21825C0
+:109650003C04800027BD0018AC83083003E00008FC
+:10966000AF8000383C0580088CA700603C0680086D
+:109670000087102B144000112C8340008CA8006040
+:109680002D0340001060000F240340008CC90060CF
+:109690000089282B14A00002008018218CC30060D0
+:1096A00000035A42000B30803C0A0800254A59202A
+:1096B00000CA202103E000088C8200001460FFF340
+:1096C0002403400000035A42000B30803C0A08008B
+:1096D000254A592000CA202103E000088C8200009E
+:1096E0003C05800890A60008938400AB24C20001CA
+:1096F000304200FF3043007F1064000C0002382726
+:10970000A0A200083C0480008C85017804A0FFFE24
+:109710008F8A00A0240900023C081000AC8A014096
+:10972000A089014403E00008AC8801780A00101BFE
+:1097300030E2008027BDFFD8AFB200188F9200A49E
+:10974000AFBF0020AFB3001CAFB00010AFB100142A
+:109750008F9300348E5900283C1000803C0EFFEFA0
+:10976000AE7900008E580024A260000A35CDFFFFBC
+:10977000AE7800049251002C3C0BFF9F356AFFFF2E
+:10978000A271000C8E6F000C3C080040A271000B0F
+:1097900001F06025018D4824012A382400E8302595
+:1097A000AE66000C8E450004AE6000183C0400FF5D
+:1097B000AE6500148E43002C3482FFFFA6600008C3
+:1097C0000062F824AE7F00108E5900088F9000A030
+:1097D000964E0012AE7900208E51000C31D83FFF1A
+:1097E00000187980AE7100248E4D001401F06021C4
+:1097F00031CB0001AE6D00288E4A0018000C41C22A
+:10980000000B4B80AE6A002C8E46001C01093821EB
+:10981000A667001CAE660030964500028E4400200C
+:10982000A665001EAE64003492430033306200042B
+:1098300054400006924700003C0280083443010077
+:109840008C7F00D0AE7F0030924700008F860038BA
+:10985000A0C700309245003330A4000250800007BA
+:10986000925100018F880038240BFF80910A00304C
+:10987000014B4825A1090030925100018F9000381A
+:10988000240CFFBF2404FFDFA21100318F8D0038AC
+:109890003C1880083711008091AF003C31EE007F0A
+:1098A000A1AE003C8F890038912B003C016C502404
+:1098B000A12A003C8F9F00388E68001493E6003C7C
+:1098C0002D0700010007114000C4282400A218251C
+:1098D000A3E3003C8F87003896590012A4F90032A8
+:1098E0008E450004922E007C30B0000300107823D7
+:1098F00031ED000300AD102131CC000215800002D3
+:1099000024460034244600303C0280083443008062
+:10991000907F007C00BFC824333800041700000289
+:1099200024C2000400C010218F98003824190002BE
+:10993000ACE20034A3190000924F003F8F8E003834
+:109940003C0C8008358B0080A1CF00018F9100383E
+:10995000924D003F8E440004A62D0002956A005CE3
+:109960000E000FF43150FFFF00024B800209382532
+:109970003C08420000E82825AE2500048E4400384B
+:109980008F850038ACA400188E460034ACA6001CAD
+:10999000ACA0000CACA00010A4A00014A4A0001661
+:1099A000A4A00020A4A00022ACA000248E62001479
+:1099B00050400001240200018FBF00208FB3001C23
+:1099C0008FB200188FB100148FB00010ACA2000845
+:1099D0000A00101327BD002827BDFFC83C058008DA
+:1099E00034A40080AFBF0034AFBE0030AFB7002C4E
+:1099F000AFB60028AFB50024AFB40020AFB3001C51
+:109A0000AFB20018AFB10014AFB00010948300786B
+:109A10009482007A104300512405FFFF0080F0215A
+:109A20000A0011230080B821108B004D8FBF003435
+:109A30008F8600A03C1808008F18005C2411FF805E
+:109A40003C1680000306782101F18024AED0002C62
+:109A500096EE007A31EC007F3C0D800E31CB7FFF1B
+:109A6000018D5021000B4840012AA82196A4000036
+:109A70003C0808008D0800582405FF8030953FFF02
+:109A800001061821001539800067C8210325F82434
+:109A90003C02010003E290253338007F3C11800C2A
+:109AA000AED20028031190219250000D320F000415
+:109AB00011E0003702E0982196E3007A96E8007AF8
+:109AC00096E5007A2404800031077FFF24E300013B
+:109AD00030627FFF00A4F82403E2C825A6F9007ACB
+:109AE00096E6007A3C1408008E94006030D67FFF22
+:109AF00012D400C1000000008E5800188F8400A00E
+:109B000002A028212713FFFF0E000FCEAE53002C1A
+:109B100097D5007897D4007A12950010000028217C
+:109B20003C098008352401003C0A8008914800085F
+:109B3000908700D53114007F30E400FF0284302B81
+:109B400014C0FFB9268B0001938E00AB268C000158
+:109B5000008E682115ACFFB78F8600A08FBF003440
+:109B60008FBE00308FB7002C8FB600288FB5002431
+:109B70008FB400208FB3001C8FB200188FB1001477
+:109B80008FB0001000A0102103E0000827BD0038AE
+:109B900000C020210E000F99028028218E4B00105A
+:109BA0008E4C00308F84003824090002016C502351
+:109BB000AE4A0010A089000096E3005C8E4400309D
+:109BC0008F9100380E000FF43070FFFF00024380C9
+:109BD000020838253C02420000E22825AE25000498
+:109BE0008E5F00048F8A00388E590000240B000815
+:109BF000AD5F001CAD590018AD40000CAD40001029
+:109C00009246000A240400052408C00030D000FF5A
+:109C1000A550001496580008A55800169251000A45
+:109C20003C188008322F00FFA54F0020964E0008F8
+:109C300037110100A54E0022AD400024924D000BCB
+:109C400031AC00FFA54C0002A14B00018E49003051
+:109C50008F830038240BFFBFAC690008A06400307C
+:109C60008F9000382403FFDF9607003200E8282495
+:109C700000B51025A6020032921F003233F9003FD2
+:109C800037260040A20600328F8C0038AD800034A9
+:109C90008E2F00D0AD8F0038918E003C3C0F7FFF9F
+:109CA00031CD007FA18D003C8F84003835EEFFFF61
+:109CB000908A003C014B4824A089003C8F850038E5
+:109CC00090A8003C01033824A0A7003C8E42003439
+:109CD0008F9100383C038008AE2200408E59002C42
+:109CE0008E5F0030033F3023AE26004492300048A0
+:109CF0003218007FA23800488F8800388E4D00301F
+:109D00008D0C004801AE582401965024014B482583
+:109D1000AD0900489244000AA104004C964700088F
+:109D20008F850038A4A7004E8E5000308E4400303E
+:109D30000E0003818C65006092F9007C0002F940FE
+:109D4000004028210002110003E2302133360002D6
+:109D500012C00003020680210005B0800216802197
+:109D6000926D007C31B30004126000020005708027
+:109D7000020E80218E4B00308F8800382405800031
+:109D8000316A0003000A4823312400030204182129
+:109D9000AD03003496E4007A96F0007A96F1007AEA
+:109DA00032027FFF2447000130FF7FFF0225C824D5
+:109DB000033F3025A6E6007A96F8007A3C120800A8
+:109DC0008E520060330F7FFF11F200180000000078
+:109DD0008F8400A00E000FCE02A028218F8400A047
+:109DE0000E000FDE028028210E001013000000007C
+:109DF0000A00111F0000000096F1007A022480245E
+:109E0000A6F0007A92EF007A92EB007A31EE00FF32
+:109E1000000E69C2000D6027000C51C03169007F3F
+:109E2000012A20250A001119A2E4007A96E6007A98
+:109E300000C5C024A6F8007A92EF007A92F3007A67
+:109E400031F200FF001271C2000E6827000DB1C090
+:109E5000326C007F01962825A2E5007A0A0011D015
+:109E60008F8400A03C0380003084FFFF30A5FFFFFB
+:109E7000AC640018AC65001C03E000088C620014A0
+:109E800027BDFFA03C068008AFBF005CAFBE0058F6
+:109E9000AFB70054AFB60050AFB5004CAFB40048F8
+:109EA000AFB30044AFB20040AFB1003CAFB0003838
+:109EB00034C80100910500D590C700083084FFFF29
+:109EC00030A500FF30E2007F0045182AAFA4001043
+:109ED000A7A00018A7A0002610600055AFA000148E
+:109EE00090CA00083149007F00A9302324D3FFFF26
+:109EF0000013802B8FB400100014902B02128824C2
+:109F0000522000888FB300143C03800894790052DB
+:109F1000947E00508FB60010033EC0230018BC0092
+:109F2000001714030016FC0002C2A82A16A00002A3
+:109F3000001F2C030040282100133C0000072403CD
+:109F400000A4102A5440000100A020212885000907
+:109F500014A000020080A021241400083C0C8008FA
+:109F60008D860048001459808D88004C3C03800089
+:109F70003169FFFF3C0A0010012A202534710400DA
+:109F8000AC660038AF9100A4AC68003CAC64003013
+:109F900000000000000000000000000000000000C1
+:109FA00000000000000000000000000000000000B1
+:109FB0008C6E000031CD002011A0FFFD0014782A26
+:109FC00001F01024104000390000A8213C16800840
+:109FD00092D700083C1280008E44010032F6007FC8
+:109FE0000E000F9902C028218E3900108E44010006
+:109FF0000000902133373FFF0E000FB102E028210F
+:10A00000923800003302003F2C500008520000102C
+:10A0100000008821000210803C030800246358E4FB
+:10A020000043F8218FFE000003C00008000000007C
+:10A0300090CF0008938C00AB31EE007F00AE682318
+:10A04000018D58210A0012172573FFFF0000882197
+:10A050003C1E80008FC401000E000FCE02E02821BC
+:10A060008FC401000E000FDE02C028211220000F55
+:10A070000013802B8F8B00A426A400010004AC00E9
+:10A08000027298230015AC032578004002B4B02A70
+:10A090000013802B241700010300882102D0102414
+:10A0A000AF9800A41440FFC9AFB700143C07800864
+:10A0B00094E200508FAE00103C05800002A288217F
+:10A0C0003C060020A4F10050ACA6003094F40050EF
+:10A0D00094EF005201D51823306CFFFF11F4001EDD
+:10A0E000AFAC00108CEF004C001561808CF500487F
+:10A0F00001EC28210000202100AC582B02A4C02133
+:10A10000030BB021ACE5004CACF600488FB4001056
+:10A110000014902B021288241620FF7C3C03800838
+:10A120008FB300148FBF005C8FBE00583A620001ED
+:10A130008FB700548FB600508FB5004C8FB40048D5
+:10A140008FB300448FB200408FB1003C8FB0003815
+:10A1500003E0000827BD006094FE00548CF2004428
+:10A1600033C9FFFE0009C8C00259F821ACBF003C4A
+:10A170008CE800448CAD003C010D50231940003B9D
+:10A18000000000008CF7004026E20001ACA200387D
+:10A190003C05005034A700103C038000AC67003041
+:10A1A00000000000000000000000000000000000AF
+:10A1B000000000000000000000000000000000009F
+:10A1C0008C7800003316002012C0FFFD3C1180087F
+:10A1D000962200543C1580003C068008304E000159
+:10A1E000000E18C0007578218DEC04003C070800B3
+:10A1F0008CE700443C040020ACCC00488DF40404FF
+:10A20000240B0001ACD4004C10EB0260AEA4003073
+:10A21000963900523C0508008CA5004000B99021F9
+:10A22000A6320052963F005427ED0001A62D00549F
+:10A230009626005430C4FFFF5487FF2F8FB40010C0
+:10A2400030A5FFFF0E0011F4A62000543C070800C3
+:10A250008CE70024963E00520047B82303D74823DA
+:10A26000A62900520A0012198FB400108CE2004097
+:10A270000A0012BE00000000922400012407000121
+:10A280003085007F14A7001C97AD00268E2B00148C
+:10A29000240CC000316A3FFF01AC48243C06080092
+:10A2A0008CC60060012A402531043FFF0086882BC0
+:10A2B00012200011A7A800263C0508008CA5005814
+:10A2C0008F9100A0000439802402FF8000B1182182
+:10A2D0000067F82103E2F02433F8007F3C1280008D
+:10A2E0003C19800EAE5E002C0319702191D0000D38
+:10A2F000360F0004A1CF000D0E001028241200011B
+:10A30000241100013C1E80008FC401000E000FCEFE
+:10A3100002E028218FC401000E000FDE02C02821B8
+:10A320001620FF558F8B00A40A0012860013802B85
+:10A330008F8600A490C80001310400201080019194
+:10A34000241000013C048008348B0080916A007C5A
+:10A350008F9E0034AFA0002C314900011120000F66
+:10A36000AFB000288CCD00148C8E006001AE602B45
+:10A370001580000201A038218C8700603C188008FD
+:10A38000370300808C70007000F0782B15E000021D
+:10A3900000E020218C640070AFA4002C3C028008F7
+:10A3A000344500808CD200148CBF0070025FC82B33
+:10A3B00017200002024020218CA400708FA7002CDF
+:10A3C0000087182310600003AFA3003024050002AB
+:10A3D000AFA500288FA400280264882B162000BA9D
+:10A3E000000018218CD000388FCE000C3C0F00806C
+:10A3F000AFD000008CCD00343C0CFF9F01CF58251E
+:10A40000AFCD000490CA003F3586FFFF01662024CF
+:10A410003C0900203C08FFEFA3CA000B0089382547
+:10A420003511FFFF00F118243C0500088F8700A4B8
+:10A430000065C825AFD9000C8CE20014AFC000182D
+:10A440008FA60030AFC200148CF800188FB0002C1B
+:10A450003C1FFFFBAFD8001C8CEF000837F2FFFF5A
+:10A4600003326824AFCF00248CEC000C020670216C
+:10A47000AFCD000CA7C00038A7C0003AAFCE002C6B
+:10A48000AFCC0020AFC000288CEA00148FAB002CAA
+:10A49000014B48230126402311000011AFC80010D2
+:10A4A00090EB003D8FC900048FC80000000B5100E5
+:10A4B000012A28210000102100AA882B010218215E
+:10A4C0000071F821AFC50004AFDF000090F2003D3D
+:10A4D000A3D2000A8F9900A497380006A7D80008D5
+:10A4E0008F910038240800023C038008A228000055
+:10A4F0003465008094BF005C8FA4002C33F0FFFF14
+:10A500000E000FF48F9200380002CB808F8500A4DC
+:10A51000021978253C18420001F87025AE4E00045F
+:10A520008F8400388CAD0038AC8D00188CAC0034B2
+:10A53000AC8C001CAC80000CAC800010A48000141B
+:10A54000A4800016A4800020A4800022AC800024F7
+:10A5500090A6003F8FA7002CA486000250E0019235
+:10A56000240700018FA200305040000290A2003D5D
+:10A5700090A2003E244A0001A08A00018F84003886
+:10A580008FA9002CAC8900083C128008364D008051
+:10A5900091AC007C3186000214C000022407003414
+:10A5A000240700308F8500A43C198008373F0080C5
+:10A5B00090B0000093F9007C240E0004A0900030BD
+:10A5C0008F8F00A48FB8002C8F8D003891F200017E
+:10A5D0003304000301C46023A1B200318F8E003820
+:10A5E0008F8600A42402C00095CA003294C90012CC
+:10A5F0008FAB002C0142402431233FFF010388250B
+:10A60000A5D1003291D000323185000300EBF82152
+:10A610003218003F370F0040A1CF00328FA4002C2A
+:10A6200003E5382133280004108000028F850038AC
+:10A6300000E838213C0A8008ACA700343549010005
+:10A640008D2800D08FA3002C2419FFBFACA80038A0
+:10A6500090B1003C2C640001240FFFDF3227007F03
+:10A66000A0A7003C8F98003800049140931F003C45
+:10A6700003F98024A310003C8F8C0038918E003C9D
+:10A6800001CF682401B23025A186003C8F8900A447
+:10A690008F8800388D2B0020AD0B00408D220024C8
+:10A6A000AD0200448D2A0028AD0A00488D23002CFD
+:10A6B0000E001013AD03004C8FB1002824070002D8
+:10A6C000122700118FA300280003282B00058023E8
+:10A6D0000270982400608021006090210A00126FAF
+:10A6E0000010882B962900128F8400A00000902172
+:10A6F0003125FFFFA7A900180E000FC22411000189
+:10A700000A00131D3C1E80003C0B80003C12800898
+:10A710008D640100924900088F92FF340E000F995A
+:10A720003125007F8F9900388FA700288FA4003033
+:10A73000A3270000965F005C33F0FFFF0E000FF4CC
+:10A740008F91003800026B80020D80253C0842008A
+:10A750008F8D00A402085025AE2A00048DA5003874
+:10A760008F8A003800007821000F1100AD450018D5
+:10A770008DB800343C047FFF3488FFFFAD58001CC7
+:10A7800091A6003E8D4C001C8D4900180006190052
+:10A79000000677020183C821004E58250323882B29
+:10A7A000012B382100F1F821AD59001CAD5F0018D4
+:10A7B000AD40000CAD40001091B0003E8FA40030C1
+:10A7C00024090005A550001495A500042419C00013
+:10A7D00000884024A545001691B8003EA5580020E9
+:10A7E00095AF0004A54F0022AD40002491AE003F7C
+:10A7F000A54E000291A6003E91AC003D01861023BB
+:10A80000244B0001A14B00018F9100388FA3003031
+:10A810003C028008344B0100AE230008A22900301E
+:10A820008F8C00388F8700A4959F003294F000121F
+:10A830002407FFBF033FC02432053FFF03057825EF
+:10A84000A58F0032918E00322418FFDF31CD003FFA
+:10A8500035A60040A18600328F910038240DFFFFFD
+:10A86000240CFF80AE2000348D6A00D0AE2A003860
+:10A870009223003C3069007FA229003C8F90003871
+:10A880003C0380009219003C0327F824A21F003CDF
+:10A890008F8E003891C5003C00B87824A1CF003CD1
+:10A8A0008F8A00383C0E8008AD4D00408FA6002CEA
+:10A8B000AD46004491420048004C5825A14B004849
+:10A8C0008F9000388F9900A48E09004801238824B6
+:10A8D00002283825AE070048933F003EA21F004CD7
+:10A8E0008F9800A48F8F003897050004A5E5004ECF
+:10A8F0000E0003818DC500609246007C8FAC003055
+:10A9000000026940000291000040282130CB000283
+:10A9100001B21021156000AA018230213C0E80088E
+:10A9200035C20080904C007C31830004106000032D
+:10A930008FB900300005788000CF3021241F00043B
+:10A940008F910038332D000303ED8023320800037C
+:10A9500000C85021AE2A00343C188000A7C500383A
+:10A960003C0680088F04010090DE00080E000FDE18
+:10A9700033C5007F0E001013000000000A00140D04
+:10A980008FA300288F9800348CC90038241F00033F
+:10A99000A7000008AF0900008CC50034A300000A1E
+:10A9A0008F9900A4AF0500043C080080932D003F60
+:10A9B000A31F000C8F0A000C3C02FF9FA30D000B8D
+:10A9C0000148F0253451FFFF3C12FFEF8F9900A49E
+:10A9D00003D170243646FFFF01C61824AF03000CD4
+:10A9E0008F2C0014972900128F8400A0AF0C001048
+:10A9F0008F2F0014AF000018AF000020AF0F00141D
+:10AA0000AF0000248F270018312F3FFF000F59801F
+:10AA1000AF0700288F2500080164F821312D0001BF
+:10AA2000AF0500308F31000C8F920038001F51C2EB
+:10AA3000000D438001481021241E00023C068008BE
+:10AA4000A702001CA7000034AF11002CA25E00007A
+:10AA500034D20080964E005C8F9900383C0342004F
+:10AA600031CCFFFF01833825AF2700048F8B00A472
+:10AA7000240500012402C0008D640038240700343E
+:10AA8000AF2400188D690034AF29001CAF20000CE2
+:10AA9000AF200010A7200014A7200016A720002038
+:10AAA000A7200022AF200024A7300002A325000128
+:10AAB0008F8800388F9F00A4AD10000893ED000030
+:10AAC000A10D00308F8A00A48F98003891510001A9
+:10AAD000A31100318F8B0038957E003203C27024A1
+:10AAE00001CF6025A56C0032916300323064003FD5
+:10AAF000A16400329249007C3125000214A00002BA
+:10AB00008F840038240700303C198008AC8700345B
+:10AB1000373201008E5F00D0240AFFBF020090216F
+:10AB2000AC9F0038908D003C31A8007FA088003C8D
+:10AB30008F9E003893C2003C004A8824A3D1003C79
+:10AB40008F8300380010882B9066003C34CE0020A4
+:10AB5000A06E003C8F8400A48F9800388C8C00205D
+:10AB6000AF0C00408C8F0024AF0F00448C8700286E
+:10AB7000AF0700488C8B002CAF0B004C0E0010135D
+:10AB80003C1E80000A0012700000000094C80052B1
+:10AB90003C0A08008D4A002401488821A4D10052B3
+:10ABA0000A0012198FB40010A08700018F840038AA
+:10ABB000240B0001AC8B00080A0013BE3C12800875
+:10ABC000000520800A0014A200C4302127BDFFE048
+:10ABD0003C0D8008AFB20018AFB00010AFBF001C32
+:10ABE000AFB1001435B200808E4C001835A80100BA
+:10ABF000964B000695A70050910900FC000C5602E8
+:10AC0000016728233143007F312600FF240200031F
+:10AC1000AF8300A8AF8400A010C2001B30B0FFFFBC
+:10AC2000910600FC2412000530C200FF10520033D0
+:10AC300000000000160000098FBF001C8FB2001832
+:10AC40008FB100148FB00010240D0C003C0C80005C
+:10AC500027BD002003E00008AD8D00240E0011FB8D
+:10AC6000020020218FBF001C8FB200188FB100148A
+:10AC70008FB00010240D0C003C0C800027BD00207C
+:10AC800003E00008AD8D0024965800789651007AB4
+:10AC9000924E007D0238782631E8FFFF31C400C0B3
+:10ACA000148000092D11000116000037000000007B
+:10ACB0005620FFE28FBF001C0E0010D100000000E4
+:10ACC0000A00156A8FBF001C1620FFDA0000000082
+:10ACD0000E0010D1000000001440FFD88FBF001CF0
+:10ACE0001600002200000000925F007D33E2003F6A
+:10ACF000A242007D0A00156A8FBF001C950900EA78
+:10AD00008F86008000802821240400050E0007257E
+:10AD10003130FFFF978300923C0480002465FFFFE1
+:10AD2000A78500928C8A01B80540FFFE0000000054
+:10AD3000AC8001808FBF001CAC9001848FB20018E2
+:10AD40008FB100148FB000103C0760133C0B100053
+:10AD5000240D0C003C0C800027BD0020AC8701882E
+:10AD6000AC8B01B803E00008AD8D00240E0011FB90
+:10AD7000020020215040FFB18FBF001C925F007D78
+:10AD80000A00159733E2003F0E0011FB020020215C
+:10AD90001440FFAA8FBF001C122000070000000013
+:10ADA0009259007D3330003F36020040A242007DC0
+:10ADB0000A00156A8FBF001C0E0010D100000000B1
+:10ADC0005040FF9E8FBF001C9259007D3330003FE2
+:08ADD0000A0015C6360200401E
+:08ADD800000000000000001B58
+:10ADE0000000000F0000000A00000008000000063C
+:10ADF0000000000500000005000000040000000441
+:10AE00000000000300000003000000030000000336
+:10AE10000000000300000002000000020000000229
+:10AE2000000000020000000200000002000000021A
+:10AE3000000000020000000200000002000000020A
+:10AE400000000002000000020000000200000002FA
+:0CAE5000000000010000000100000001F3
+:04AE5C008008010069
+:10AE6000800800808008000000000C000000308096
+:10AE7000080011D00800127C08001294080012A8E3
+:10AE8000080012BC080011D0080011D0080012F010
+:10AE90000800132C080013400800138808001A8CBF
+:10AEA00008001A8C08001AC408001AC408001AD82E
+:10AEB00008001AA808001D0008001CCC08001D5836
+:10AEC00008001D5808001DE008001D108008024001
+:10AED000080027340800256C0800275C080027F4C8
+:10AEE0000800293C0800298808002AAC080029B479
+:10AEF00008002A38080025DC08002EDC08002EA4F3
+:10AF000008002588080025880800258808002B20CF
+:10AF100008002B20080025880800258808002DD06F
+:10AF2000080025880800258808002588080025884D
+:10AF300008002E0C080025880800258808002588B0
+:10AF4000080025880800258808002588080025882D
+:10AF5000080025880800258808002588080025881D
+:10AF6000080025880800258808002588080029A8E9
+:10AF7000080025880800258808002E680800258814
+:10AF800008002588080025880800258808002588ED
+:10AF900008002588080025880800258808002588DD
+:10AFA00008002588080025880800258808002588CD
+:10AFB00008002588080025880800258808002588BD
+:10AFC00008002CF4080025880800258808002C6853
+:10AFD00008002BC408003CE408003CB808003C848E
+:10AFE00008003C5808003C3808003BEC8008010091
+:10AFF00080080080800800008008008008004C6401
+:10B0000008004C9C08004BE408004C6408004C64A9
+:0CB01000080049B808004C6408005050CB
+:04B01C000A000C8496
+:10B0200000000000000000000000000D7278703683
+:10B030002E322E31610000000602010300000000E4
+:10B0400000000001000000000000000000000000FF
+:10B0500000000000000000000000000000000000F0
+:10B0600000000000000000000000000000000000E0
+:10B0700000000000000000000000000000000000D0
+:10B0800000000000000000000000000000000000C0
+:10B0900000000000000000000000000000000000B0
+:10B0A00000000000000000000000000000000000A0
+:10B0B0000000000000000000000000000000000090
+:10B0C0000000000000000000000000000000000080
+:10B0D0000000000000000000000000000000000070
+:10B0E0000000000000000000000000000000000060
+:10B0F0000000000000000000000000000000000050
+:10B10000000000000000000000000000000000003F
+:10B11000000000000000000000000000000000002F
+:10B12000000000000000000000000000000000001F
+:10B13000000000000000000000000000000000000F
+:10B1400000000000000000000000000000000000FF
+:10B1500000000000000000000000000000000000EF
+:10B1600000000000000000000000000000000000DF
+:10B1700000000000000000000000000000000000CF
+:10B1800000000000000000000000000000000000BF
+:10B1900000000000000000000000000000000000AF
+:10B1A000000000000000000000000000000000009F
+:10B1B000000000000000000000000000000000008F
+:10B1C000000000000000000000000000000000007F
+:10B1D000000000000000000000000000000000006F
+:10B1E000000000000000000000000000000000005F
+:10B1F000000000000000000000000000000000004F
+:10B20000000000000000000000000000000000003E
+:10B21000000000000000000000000000000000002E
+:10B22000000000000000000000000000000000001E
+:10B23000000000000000000000000000000000000E
+:10B2400000000000000000000000000000000000FE
+:10B2500000000000000000000000000000000000EE
+:10B2600000000000000000000000000000000000DE
+:10B2700000000000000000000000000000000000CE
+:10B2800000000000000000000000000000000000BE
+:10B2900000000000000000000000000000000000AE
+:10B2A000000000000000000000000000000000009E
+:10B2B000000000000000000000000000000000008E
+:10B2C000000000000000000000000000000000007E
+:10B2D000000000000000000000000000000000006E
+:10B2E000000000000000000000000000000000005E
+:10B2F000000000000000000000000000000000004E
+:10B30000000000000000000000000000000000003D
+:10B31000000000000000000000000000000000002D
+:10B32000000000000000000000000000000000001D
+:10B33000000000000000000000000000000000000D
+:10B3400000000000000000000000000000000000FD
+:10B3500000000000000000000000000000000000ED
+:10B3600000000000000000000000000000000000DD
+:10B3700000000000000000000000000000000000CD
+:10B3800000000000000000000000000000000000BD
+:10B3900000000000000000000000000000000000AD
+:10B3A000000000000000000000000000000000009D
+:10B3B000000000000000000000000000000000008D
+:10B3C000000000000000000000000000000000007D
+:10B3D000000000000000000000000000000000006D
+:10B3E000000000000000000000000000000000005D
+:10B3F000000000000000000000000000000000004D
+:10B40000000000000000000000000000000000003C
+:10B41000000000000000000000000000000000002C
+:10B42000000000000000000000000000000000001C
+:10B43000000000000000000000000000000000000C
+:10B4400000000000000000000000000000000000FC
+:10B4500000000000000000000000000000000000EC
+:10B4600000000000000000000000000000000000DC
+:10B4700000000000000000000000000000000000CC
+:10B4800000000000000000000000000000000000BC
+:10B4900000000000000000000000000000000000AC
+:10B4A000000000000000000000000000000000009C
+:10B4B000000000000000000000000000000000008C
+:10B4C000000000000000000000000000000000007C
+:10B4D000000000000000000000000000000000006C
+:10B4E000000000000000000000000000000000005C
+:10B4F000000000000000000000000000000000004C
+:10B50000000000000000000000000000000000003B
+:10B51000000000000000000000000000000000002B
+:10B52000000000000000000000000000000000001B
+:10B53000000000000000000000000000000000000B
+:10B5400000000000000000000000000000000000FB
+:10B5500000000000000000000000000000000000EB
+:10B5600000000000000000000000000000000000DB
+:10B5700000000000000000000000000000000000CB
+:10B5800000000000000000000000000000000000BB
+:10B5900000000000000000000000000000000000AB
+:10B5A000000000000000000000000000000000009B
+:10B5B000000000000000000000000000000000008B
+:10B5C000000000000000000000000000000000007B
+:10B5D000000000000000000000000000000000006B
+:10B5E000000000000000000000000000000000005B
+:10B5F000000000000000000000000000000000004B
+:10B60000000000000000000000000000000000003A
+:10B61000000000000000000000000000000000002A
+:10B62000000000000000000000000000000000001A
+:10B63000000000000000000000000000000000000A
+:10B6400000000000000000000000000000000000FA
+:10B6500000000000000000000000000000000000EA
+:10B6600000000000000000000000000000000000DA
+:10B6700000000000000000000000000000000000CA
+:10B6800000000000000000000000000000000000BA
+:10B6900000000000000000000000000000000000AA
+:10B6A000000000000000000000000000000000009A
+:10B6B000000000000000000000000000000000008A
+:10B6C000000000000000000000000000000000007A
+:10B6D000000000000000000000000000000000006A
+:10B6E000000000000000000000000000000000005A
+:10B6F000000000000000000000000000000000004A
+:10B700000000000000000000000000000000000039
+:10B710000000000000000000000000000000000029
+:10B720000000000000000000000000000000000019
+:10B730000000000000000000000000000000000009
+:10B7400000000000000000000000000000000000F9
+:10B7500000000000000000000000000000000000E9
+:10B7600000000000000000000000000000000000D9
+:10B7700000000000000000000000000000000000C9
+:10B7800000000000000000000000000000000000B9
+:10B7900000000000000000000000000000000000A9
+:10B7A0000000000000000000000000000000000099
+:10B7B0000000000000000000000000000000000089
+:10B7C0000000000000000000000000000000000079
+:10B7D0000000000000000000000000000000000069
+:10B7E0000000000000000000000000000000000059
+:10B7F0000000000000000000000000000000000049
+:10B800000000000000000000000000000000000038
+:10B810000000000000000000000000000000000028
+:10B820000000000000000000000000000000000018
+:10B830000000000000000000000000000000000008
+:10B8400000000000000000000000000000000000F8
+:10B8500000000000000000000000000000000000E8
+:10B8600000000000000000000000000000000000D8
+:10B8700000000000000000000000000000000000C8
+:10B8800000000000000000000000000000000000B8
+:10B8900000000000000000000000000000000000A8
+:10B8A0000000000000000000000000000000000098
+:10B8B0000000000000000000000000000000000088
+:10B8C0000000000000000000000000000000000078
+:10B8D0000000000000000000000000000000000068
+:10B8E0000000000000000000000000000000000058
+:10B8F0000000000000000000000000000000000048
+:10B900000000000000000000000000000000000037
+:10B910000000000000000000000000000000000027
+:10B920000000000000000000000000000000000017
+:10B930000000000000000000000000000000000007
+:10B9400000000000000000000000000000000000F7
+:10B9500000000000000000000000000000000000E7
+:10B9600000000000000000000000000000000000D7
+:10B9700000000000000000000000000000000000C7
+:10B9800000000000000000000000000000000000B7
+:10B9900000000000000000000000000000000000A7
+:10B9A0000000000000000000000000000000000097
+:10B9B0000000000000000000000000000000000087
+:10B9C0000000000000000000000000000000000077
+:10B9D0000000000000000000000000000000000067
+:10B9E0000000000000000000000000000000000057
+:10B9F0000000000000000000000000000000000047
+:10BA00000000000000000000000000000000000036
+:10BA10000000000000000000000000000000000026
+:10BA20000000000000000000000000000000000016
+:10BA30000000000000000000000000000000000006
+:10BA400000000000000000000000000000000000F6
+:10BA500000000000000000000000000000000000E6
+:10BA600000000000000000000000000000000000D6
+:10BA700000000000000000000000000000000000C6
+:10BA800000000000000000000000000000000000B6
+:10BA900000000000000000000000000000000000A6
+:10BAA0000000000000000000000000000000000096
+:10BAB0000000000000000000000000000000000086
+:10BAC0000000000000000000000000000000000076
+:10BAD0000000000000000000000000000000000066
+:10BAE0000000000000000000000000000000000056
+:10BAF0000000000000000000000000000000000046
+:10BB00000000000000000000000000000000000035
+:10BB10000000000000000000000000000000000025
+:10BB20000000000000000000000000000000000015
+:10BB30000000000000000000000000000000000005
+:10BB400000000000000000000000000000000000F5
+:10BB500000000000000000000000000000000000E5
+:10BB600000000000000000000000000000000000D5
+:10BB700000000000000000000000000000000000C5
+:10BB800000000000000000000000000000000000B5
+:10BB900000000000000000000000000000000000A5
+:10BBA0000000000000000000000000000000000095
+:10BBB0000000000000000000000000000000000085
+:10BBC0000000000000000000000000000000000075
+:10BBD0000000000000000000000000000000000065
+:10BBE0000000000000000000000000000000000055
+:10BBF0000000000000000000000000000000000045
+:10BC00000000000000000000000000000000000034
+:10BC10000000000000000000000000000000000024
+:10BC20000000000000000000000000000000000014
+:10BC30000000000000000000000000000000000004
+:10BC400000000000000000000000000000000000F4
+:10BC500000000000000000000000000000000000E4
+:10BC600000000000000000000000000000000000D4
+:10BC700000000000000000000000000000000000C4
+:10BC800000000000000000000000000000000000B4
+:10BC900000000000000000000000000000000000A4
+:10BCA0000000000000000000000000000000000094
+:10BCB0000000000000000000000000000000000084
+:10BCC0000000000000000000000000000000000074
+:10BCD0000000000000000000000000000000000064
+:10BCE0000000000000000000000000000000000054
+:10BCF0000000000000000000000000000000000044
+:10BD00000000000000000000000000000000000033
+:10BD10000000000000000000000000000000000023
+:10BD20000000000000000000000000000000000013
+:10BD30000000000000000000000000000000000003
+:10BD400000000000000000000000000000000000F3
+:10BD500000000000000000000000000000000000E3
+:10BD600000000000000000000000000000000000D3
+:10BD700000000000000000000000000000000000C3
+:10BD800000000000000000000000000000000000B3
+:10BD900000000000000000000000000000000000A3
+:10BDA0000000000000000000000000000000000093
+:10BDB0000000000000000000000000000000000083
+:10BDC0000000000000000000000000000000000073
+:10BDD0000000000000000000000000000000000063
+:10BDE0000000000000000000000000000000000053
+:10BDF0000000000000000000000000000000000043
+:10BE00000000000000000000000000000000000032
+:10BE10000000000000000000000000000000000022
+:10BE20000000000000000000000000000000000012
+:10BE30000000000000000000000000000000000002
+:10BE400000000000000000000000000000000000F2
+:10BE500000000000000000000000000000000000E2
+:10BE600000000000000000000000000000000000D2
+:10BE700000000000000000000000000000000000C2
+:10BE800000000000000000000000000000000000B2
+:10BE900000000000000000000000000000000000A2
+:10BEA0000000000000000000000000000000000092
+:10BEB0000000000000000000000000000000000082
+:10BEC0000000000000000000000000000000000072
+:10BED0000000000000000000000000000000000062
+:10BEE0000000000000000000000000000000000052
+:10BEF0000000000000000000000000000000000042
+:10BF00000000000000000000000000000000000031
+:10BF10000000000000000000000000000000000021
+:10BF20000000000000000000000000000000000011
+:10BF30000000000000000000000000000000000001
+:10BF400000000000000000000000000000000000F1
+:10BF500000000000000000000000000000000000E1
+:10BF600000000000000000000000000000000000D1
+:10BF700000000000000000000000000000000000C1
+:10BF800000000000000000000000000000000000B1
+:10BF900000000000000000000000000000000000A1
+:10BFA0000000000000000000000000000000000091
+:10BFB0000000000000000000000000000000000081
+:10BFC0000000000000000000000000000000000071
+:10BFD0000000000000000000000000000000000061
+:10BFE0000000000000000000000000000000000051
+:10BFF0000000000000000000000000000000000041
+:10C000000000000000000000000000000000000030
+:10C010000000000000000000000000000000000020
+:10C020000000000000000000000000000000000010
+:10C030000000000000000000000000000000000000
+:10C0400000000000000000000000000000000000F0
+:10C0500000000000000000000000000000000000E0
+:10C0600000000000000000000000000000000000D0
+:10C0700000000000000000000000000000000000C0
+:10C0800000000000000000000000000000000000B0
+:10C0900000000000000000000000000000000000A0
+:10C0A0000000000000000000000000000000000090
+:10C0B0000000000000000000000000000000000080
+:10C0C0000000000000000000000000000000000070
+:10C0D0000000000000000000000000000000000060
+:10C0E0000000000000000000000000000000000050
+:10C0F0000000000000000000000000000000000040
+:10C10000000000000000000000000000000000002F
+:10C11000000000000000000000000000000000001F
+:10C12000000000000000000000000000000000000F
+:10C1300000000000000000000000000000000000FF
+:10C1400000000000000000000000000000000000EF
+:10C1500000000000000000000000000000000000DF
+:10C1600000000000000000000000000000000000CF
+:10C1700000000000000000000000000000000000BF
+:10C1800000000000000000000000000000000000AF
+:10C19000000000000000000000000000000000009F
+:10C1A000000000000000000000000000000000008F
+:10C1B000000000000000000000000000000000007F
+:10C1C000000000000000000000000000000000006F
+:10C1D000000000000000000000000000000000005F
+:10C1E000000000000000000000000000000000004F
+:10C1F000000000000000000000000000000000003F
+:10C20000000000000000000000000000000000002E
+:10C21000000000000000000000000000000000001E
+:10C22000000000000000000000000000000000000E
+:10C2300000000000000000000000000000000000FE
+:10C2400000000000000000000000000000000000EE
+:10C2500000000000000000000000000000000000DE
+:10C2600000000000000000000000000000000000CE
+:10C2700000000000000000000000000000000000BE
+:10C2800000000000000000000000000000000000AE
+:10C29000000000000000000000000000000000009E
+:10C2A000000000000000000000000000000000008E
+:10C2B000000000000000000000000000000000007E
+:10C2C000000000000000000000000000000000006E
+:10C2D000000000000000000000000000000000005E
+:10C2E000000000000000000000000000000000004E
+:10C2F000000000000000000000000000000000003E
+:10C30000000000000000000000000000000000002D
+:10C31000000000000000000000000000000000001D
+:10C32000000000000000000000000000000000000D
+:10C3300000000000000000000000000000000000FD
+:10C3400000000000000000000000000000000000ED
+:10C3500000000000000000000000000000000000DD
+:10C3600000000000000000000000000000000000CD
+:10C3700000000000000000000000000000000000BD
+:10C3800000000000000000000000000000000000AD
+:10C39000000000000000000000000000000000009D
+:10C3A000000000000000000000000000000000008D
+:10C3B000000000000000000000000000000000007D
+:10C3C000000000000000000000000000000000006D
+:10C3D000000000000000000000000000000000005D
+:10C3E000000000000000000000000000000000004D
+:10C3F000000000000000000000000000000000003D
+:10C40000000000000000000000000000000000002C
+:10C41000000000000000000000000000000000001C
+:10C42000000000000000000000000000000000000C
+:10C4300000000000000000000000000000000000FC
+:10C4400000000000000000000000000000000000EC
+:10C4500000000000000000000000000000000000DC
+:10C4600000000000000000000000000000000000CC
+:10C4700000000000000000000000000000000000BC
+:10C4800000000000000000000000000000000000AC
+:10C49000000000000000000000000000000000009C
+:10C4A000000000000000000000000000000000008C
+:10C4B000000000000000000000000000000000007C
+:10C4C000000000000000000000000000000000006C
+:10C4D000000000000000000000000000000000005C
+:10C4E000000000000000000000000000000000004C
+:10C4F000000000000000000000000000000000003C
+:10C50000000000000000000000000000000000002B
+:10C51000000000000000000000000000000000001B
+:10C52000000000000000000000000000000000000B
+:10C5300000000000000000000000000000000000FB
+:10C5400000000000000000000000000000000000EB
+:10C5500000000000000000000000000000000000DB
+:10C5600000000000000000000000000000000000CB
+:10C5700000000000000000000000000000000000BB
+:10C5800000000000000000000000000000000000AB
+:10C59000000000000000000000000000000000009B
+:10C5A000000000000000000000000000000000008B
+:10C5B000000000000000000000000000000000007B
+:10C5C000000000000000000000000000000000006B
+:10C5D000000000000000000000000000000000005B
+:10C5E000000000000000000000000000000000004B
+:10C5F000000000000000000000000000000000003B
+:10C60000000000000000000000000000000000002A
+:10C61000000000000000000000000000000000001A
+:10C62000000000000000000000000000000000000A
+:10C6300000000000000000000000000000000000FA
+:10C6400000000000000000000000000000000000EA
+:10C6500000000000000000000000000000000000DA
+:10C6600000000000000000000000000000000000CA
+:10C6700000000000000000000000000000000000BA
+:10C6800000000000000000000000000000000000AA
+:10C69000000000000000000000000000000000009A
+:10C6A000000000000000000000000000000000008A
+:10C6B000000000000000000000000000000000007A
+:10C6C000000000000000000000000000000000006A
+:10C6D000000000000000000000000000000000005A
+:10C6E000000000000000000000000000000000004A
+:10C6F000000000000000000000000000000000003A
+:10C700000000000000000000000000000000000029
+:10C710000000000000000000000000000000000019
+:10C720000000000000000000000000000000000009
+:10C7300000000000000000000000000000000000F9
+:10C7400000000000000000000000000000000000E9
+:10C7500000000000000000000000000000000000D9
+:10C7600000000000000000000000000000000000C9
+:10C7700000000000000000000000000000000000B9
+:10C7800000000000000000000000000000000000A9
+:10C790000000000000000000000000000000000099
+:10C7A0000000000000000000000000000000000089
+:10C7B0000000000000000000000000000000000079
+:10C7C0000000000000000000000000000000000069
+:10C7D0000000000000000000000000000000000059
+:10C7E0000000000000000000000000000000000049
+:10C7F0000000000000000000000000000000000039
+:10C800000000000000000000000000000000000028
+:10C810000000000000000000000000000000000018
+:10C820000000000000000000000000000000000008
+:10C8300000000000000000000000000000000000F8
+:10C8400000000000000000000000000000000000E8
+:10C8500000000000000000000000000000000000D8
+:10C8600000000000000000000000000000000000C8
+:10C8700000000000000000000000000000000000B8
+:10C8800000000000000000000000000000000000A8
+:10C890000000000000000000000000000000000098
+:10C8A0000000000000000000000000000000000088
+:10C8B0000000000000000000000000000000000078
+:10C8C0000000000000000000000000000000000068
+:10C8D0000000000000000000000000000000000058
+:10C8E0000000000000000000000000000000000048
+:10C8F0000000000000000000000000000000000038
+:10C900000000000000000000000000000000000027
+:10C910000000000000000000000000000000000017
+:10C920000000000000000000000000000000000007
+:10C9300000000000000000000000000000000000F7
+:10C9400000000000000000000000000000000000E7
+:10C9500000000000000000000000000000000000D7
+:10C9600000000000000000000000000000000000C7
+:10C9700000000000000000000000000000000000B7
+:10C9800000000000000000000000000000000000A7
+:10C990000000000000000000000000000000000097
+:10C9A0000000000000000000000000000000000087
+:10C9B0000000000000000000000000000000000077
+:10C9C0000000000000000000000000000000000067
+:10C9D0000000000000000000000000000000000057
+:10C9E0000000000000000000000000000000000047
+:10C9F0000000000000000000000000000000000037
+:10CA00000000000000000000000000000000000026
+:10CA10000000000000000000000000000000000016
+:10CA20000000000000000000000000000000000006
+:10CA300000000000000000000000000000000000F6
+:10CA400000000000000000000000000000000000E6
+:10CA500000000000000000000000000000000000D6
+:10CA600000000000000000000000000000000000C6
+:10CA700000000000000000000000000000000000B6
+:10CA800000000000000000000000000000000000A6
+:10CA90000000000000000000000000000000000096
+:10CAA0000000000000000000000000000000000086
+:10CAB0000000000000000000000000000000000076
+:10CAC0000000000000000000000000000000000066
+:10CAD0000000000000000000000000000000000056
+:10CAE0000000000000000000000000000000000046
+:10CAF0000000000000000000000000000000000036
+:10CB00000000000000000000000000000000000025
+:10CB10000000000000000000000000000000000015
+:10CB20000000000000000000000000000000000005
+:10CB300000000000000000000000000000000000F5
+:10CB400000000000000000000000000000000000E5
+:10CB500000000000000000000000000000000000D5
+:10CB600000000000000000000000000000000000C5
+:10CB700000000000000000000000000000000000B5
+:10CB800000000000000000000000000000000000A5
+:10CB90000000000000000000000000000000000095
+:10CBA0000000000000000000000000000000000085
+:10CBB0000000000000000000000000000000000075
+:10CBC0000000000000000000000000000000000065
+:10CBD0000000000000000000000000000000000055
+:10CBE0000000000000000000000000000000000045
+:10CBF0000000000000000000000000000000000035
+:10CC00000000000000000000000000000000000024
+:10CC10000000000000000000000000000000000014
+:10CC20000000000000000000000000000000000004
+:10CC300000000000000000000000000000000000F4
+:10CC400000000000000000000000000000000000E4
+:10CC500000000000000000000000000000000000D4
+:10CC600000000000000000000000000000000000C4
+:10CC700000000000000000000000000000000000B4
+:10CC800000000000000000000000000000000000A4
+:10CC90000000000000000000000000000000000094
+:10CCA0000000000000000000000000000000000084
+:10CCB0000000000000000000000000000000000074
+:10CCC0000000000000000000000000000000000064
+:10CCD0000000000000000000000000000000000054
+:10CCE0000000000000000000000000000000000044
+:10CCF0000000000000000000000000000000000034
+:10CD00000000000000000000000000000000000023
+:10CD10000000000000000000000000000000000013
+:10CD20000000000000000000000000000000000003
+:10CD300000000000000000000000000000000000F3
+:10CD400000000000000000000000000000000000E3
+:10CD500000000000000000000000000000000000D3
+:10CD600000000000000000000000000000000000C3
+:10CD700000000000000000000000000000000000B3
+:10CD800000000000000000000000000000000000A3
+:10CD90000000000000000000000000000000000093
+:10CDA0000000000000000000000000000000000083
+:10CDB0000000000000000000000000000000000073
+:10CDC0000000000000000000000000000000000063
+:10CDD0000000000000000000000000000000000053
+:10CDE0000000000000000000000000000000000043
+:10CDF0000000000000000000000000000000000033
+:10CE00000000000000000000000000000000000022
+:10CE10000000000000000000000000000000000012
+:10CE20000000000000000000000000000000000002
+:10CE300000000000000000000000000000000000F2
+:10CE400000000000000000000000000000000000E2
+:10CE500000000000000000000000000000000000D2
+:10CE600000000000000000000000000000000000C2
+:10CE700000000000000000000000000000000000B2
+:10CE800000000000000000000000000000000000A2
+:10CE90000000000000000000000000000000000092
+:10CEA0000000000000000000000000000000000082
+:10CEB0000000000000000000000000000000000072
+:10CEC0000000000000000000000000000000000062
+:10CED0000000000000000000000000000000000052
+:10CEE0000000000000000000000000000000000042
+:10CEF0000000000000000000000000000000000032
+:10CF00000000000000000000000000000000000021
+:10CF10000000000000000000000000000000000011
+:10CF20000000000000000000000000000000000001
+:10CF300000000000000000000000000000000000F1
+:10CF400000000000000000000000000000000000E1
+:10CF500000000000000000000000000000000000D1
+:10CF600000000000000000000000000000000000C1
+:10CF700000000000000000000000000000000000B1
+:10CF800000000000000000000000000000000000A1
+:10CF90000000000000000000000000000000000091
+:10CFA0000000000000000000000000000000000081
+:10CFB0000000000000000000000000000000000071
+:10CFC0000000000000000000000000000000000061
+:10CFD0000000000000000000000000000000000051
+:10CFE0000000000000000000000000000000000041
+:10CFF0000000000000000000000000000000000031
+:10D000000000000000000000000000000000000020
+:10D010000000000000000000000000000000000010
+:10D020000000000000000000000000000000000000
+:10D0300000000000000000000000000000000000F0
+:10D0400000000000000000000000000000000000E0
+:10D0500000000000000000000000000000000000D0
+:10D0600000000000000000000000000000000000C0
+:10D0700000000000000000000000000000000000B0
+:10D0800000000000000000000000000000000000A0
+:10D090000000000000000000000000000000000090
+:10D0A0000000000000000000000000000000000080
+:10D0B0000000000000000000000000000000000070
+:10D0C0000000000000000000000000000000000060
+:10D0D0000000000000000000000000000000000050
+:10D0E0000000000000000000000000000000000040
+:10D0F0000000000000000000000000000000000030
+:10D10000000000000000000000000000000000001F
+:10D11000000000000000000000000000000000000F
+:10D1200000000000000000000000000000000000FF
+:10D1300000000000000000000000000000000000EF
+:10D1400000000000000000000000000000000000DF
+:10D1500000000000000000000000000000000000CF
+:10D1600000000000000000000000000000000000BF
+:10D1700000000000000000000000000000000000AF
+:10D18000000000000000000000000000000000009F
+:10D19000000000000000000000000000000000008F
+:10D1A000000000000000000000000000000000007F
+:10D1B000000000000000000000000000000000006F
+:10D1C000000000000000000000000000000000005F
+:10D1D000000000000000000000000000000000004F
+:10D1E000000000000000000000000000000000003F
+:10D1F000000000000000000000000000000000002F
+:10D20000000000000000000000000000000000001E
+:10D21000000000000000000000000000000000000E
+:10D2200000000000000000000000000000000000FE
+:10D2300000000000000000000000000000000000EE
+:10D2400000000000000000000000000000000000DE
+:10D2500000000000000000000000000000000000CE
+:10D2600000000000000000000000000000000000BE
+:10D2700000000000000000000000000000000000AE
+:10D28000000000000000000000000000000000009E
+:10D29000000000000000000000000000000000008E
+:10D2A000000000000000000000000000000000007E
+:10D2B000000000000000000000000000000000006E
+:10D2C000000000000000000000000000000000005E
+:10D2D000000000000000000000000000000000004E
+:10D2E000000000000000000000000000000000003E
+:10D2F000000000000000000000000000000000002E
+:10D30000000000000000000000000000000000001D
+:10D31000000000000000000000000000000000000D
+:10D3200000000000000000000000000000000000FD
+:10D3300000000000000000000000000000000000ED
+:10D3400000000000000000000000000000000000DD
+:10D3500000000000000000000000000000000000CD
+:10D3600000000000000000000000000000000000BD
+:10D3700000000000000000000000000000000000AD
+:10D38000000000000000000000000000000000009D
+:10D39000000000000000000000000000000000008D
+:10D3A000000000000000000000000000000000007D
+:10D3B000000000000000000000000000000000006D
+:10D3C000000000000000000000000000000000005D
+:10D3D000000000000000000000000000000000004D
+:10D3E000000000000000000000000000000000003D
+:10D3F000000000000000000000000000000000002D
+:10D40000000000000000000000000000000000001C
+:10D41000000000000000000000000000000000000C
+:10D4200000000000000000000000000000000000FC
+:10D4300000000000000000000000000000000000EC
+:10D4400000000000000000000000000000000000DC
+:10D4500000000000000000000000000000000000CC
+:10D4600000000000000000000000000000000000BC
+:10D4700000000000000000000000000000000000AC
+:10D48000000000000000000000000000000000009C
+:10D49000000000000000000000000000000000008C
+:10D4A000000000000000000000000000000000007C
+:10D4B000000000000000000000000000000000006C
+:10D4C000000000000000000000000000000000005C
+:10D4D000000000000000000000000000000000004C
+:10D4E000000000000000000000000000000000003C
+:10D4F000000000000000000000000000000000002C
+:10D50000000000000000000000000000000000001B
+:10D51000000000000000000000000000000000000B
+:10D5200000000000000000000000000000000000FB
+:10D5300000000000000000000000000000000000EB
+:10D5400000000000000000000000000000000000DB
+:10D5500000000000000000000000000000000000CB
+:10D5600000000000000000000000000000000000BB
+:10D5700000000000000000000000000000000000AB
+:10D58000000000000000000000000000000000009B
+:10D59000000000000000000000000000000000008B
+:10D5A000000000000000000000000000000000007B
+:10D5B000000000000000000000000000000000006B
+:10D5C000000000000000000000000000000000005B
+:10D5D000000000000000000000000000000000004B
+:10D5E000000000000000000000000000000000003B
+:10D5F000000000000000000000000000000000002B
+:10D60000000000000000000000000000000000001A
+:10D61000000000000000000000000000000000000A
+:10D6200000000000000000000000000000000000FA
+:10D6300000000000000000000000000000000000EA
+:10D6400000000000000000000000000000000000DA
+:10D6500000000000000000000000000000000000CA
+:10D6600000000000000000000000000000000000BA
+:10D6700000000000000000000000000000000000AA
+:10D68000000000000000000000000000000000009A
+:10D69000000000000000000000000000000000008A
+:10D6A000000000000000000000000000000000007A
+:10D6B000000000000000000000000000000000006A
+:10D6C000000000000000000000000000000000005A
+:10D6D000000000000000000000000000000000004A
+:10D6E000000000000000000000000000000000003A
+:10D6F000000000000000000000000000000000002A
+:10D700000000000000000000000000000000000019
+:10D710000000000000000000000000000000000009
+:10D7200000000000000000000000000000000000F9
+:10D7300000000000000000000000000000000000E9
+:10D7400000000000000000000000000000000000D9
+:10D7500000000000000000000000000000000000C9
+:10D7600000000000000000000000000000000000B9
+:10D7700000000000000000000000000000000000A9
+:10D780000000000000000000000000000000000099
+:10D790000000000000000000000000000000000089
+:10D7A0000000000000000000000000000000000079
+:10D7B0000000000000000000000000000000000069
+:10D7C0000000000000000000000000000000000059
+:10D7D0000000000000000000000000000000000049
+:10D7E0000000000000000000000000000000000039
+:10D7F0000000000000000000000000000000000029
+:10D800000000000000000000000000000000000018
+:10D810000000000000000000000000000000000008
+:10D8200000000000000000000000000000000000F8
+:10D8300000000000000000000000000000000000E8
+:10D8400000000000000000000000000000000000D8
+:10D8500000000000000000000000000000000000C8
+:10D8600000000000000000000000000000000000B8
+:10D8700000000000000000000000000000000000A8
+:10D880000000000000000000000000000000000098
+:10D890000000000000000000000000000000000088
+:10D8A0000000000000000000000000000000000078
+:10D8B0000000000000000000000000000000000068
+:10D8C0000000000000000000000000000000000058
+:10D8D0000000000000000000000000000000000048
+:10D8E0000000000000000000000000000000000038
+:10D8F0000000000000000000000000000000000028
+:10D900000000000000000000000000000000000017
+:10D910000000000000000000000000000000000007
+:10D9200000000000000000000000000000000000F7
+:10D9300000000000000000000000000000000000E7
+:10D9400000000000000000000000000000000000D7
+:10D9500000000000000000000000000000000000C7
+:10D9600000000000000000000000000000000000B7
+:10D9700000000000000000000000000000000000A7
+:10D980000000000000000000000000000000000097
+:10D990000000000000000000000000000000000087
+:10D9A0000000000000000000000000000000000077
+:10D9B0000000000000000000000000000000000067
+:10D9C0000000000000000000000000000000000057
+:10D9D0000000000000000000000000000000000047
+:10D9E0000000000000000000000000000000000037
+:10D9F0000000000000000000000000000000000027
+:10DA00000000000000000000000000000000000016
+:10DA10000000000000000000000000000000000006
+:10DA200000000000000000000000000000000000F6
+:10DA300000000000000000000000000000000000E6
+:10DA400000000000000000000000000000000000D6
+:10DA500000000000000000000000000000000000C6
+:10DA600000000000000000000000000000000000B6
+:10DA700000000000000000000000000000000000A6
+:10DA80000000000000000000000000000000000096
+:10DA90000000000000000000000000000000000086
+:10DAA0000000000000000000000000000000000076
+:10DAB0000000000000000000000000000000000066
+:10DAC0000000000000000000000000000000000056
+:10DAD0000000000000000000000000000000000046
+:10DAE0000000000000000000000000000000000036
+:10DAF0000000000000000000000000000000000026
+:10DB00000000000000000000000000000000000015
+:10DB10000000000000000000000000000000000005
+:10DB200000000000000000000000000000000000F5
+:10DB300000000000000000000000000000000000E5
+:10DB400000000000000000000000000000000000D5
+:10DB500000000000000000000000000000000000C5
+:10DB600000000000000000000000000000000000B5
+:10DB700000000000000000000000000000000000A5
+:10DB80000000000000000000000000000000000095
+:10DB90000000000000000000000000000000000085
+:10DBA0000000000000000000000000000000000075
+:10DBB0000000000000000000000000000000000065
+:10DBC0000000000000000000000000000000000055
+:10DBD0000000000000000000000000000000000045
+:10DBE0000000000000000000000000000000000035
+:10DBF0000000000000000000000000000000000025
+:10DC00000000000000000000000000000000000014
+:10DC10000000000000000000000000000000000004
+:10DC200000000000000000000000000000000000F4
+:10DC300000000000000000000000000000000000E4
+:10DC400000000000000000000000000000000000D4
+:10DC500000000000000000000000000000000000C4
+:10DC600000000000000000000000000000000000B4
+:10DC700000000000000000000000000000000000A4
+:10DC80000000000000000000000000000000000094
+:10DC90000000000000000000000000000000000084
+:10DCA0000000000000000000000000000000000074
+:10DCB0000000000000000000000000000000000064
+:10DCC0000000000000000000000000000000000054
+:10DCD0000000000000000000000000000000000044
+:10DCE0000000000000000000000000000000000034
+:10DCF0000000000000000000000000000000000024
+:10DD00000000000000000000000000000000000013
+:10DD10000000000000000000000000000000000003
+:10DD200000000000000000000000000000000000F3
+:10DD300000000000000000000000000000000000E3
+:10DD400000000000000000000000000000000000D3
+:10DD500000000000000000000000000000000000C3
+:10DD600000000000000000000000000000000000B3
+:10DD700000000000000000000000000000000000A3
+:10DD80000000000000000000000000000000000093
+:10DD90000000000000000000000000000000000083
+:10DDA0000000000000000000000000000000000073
+:10DDB0000000000000000000000000000000000063
+:10DDC0000000000000000000000000000000000053
+:10DDD0000000000000000000000000000000000043
+:10DDE0000000000000000000000000000000000033
+:10DDF0000000000000000000000000000000000023
+:10DE00000000000000000000000000000000000012
+:10DE10000000000000000000000000000000000002
+:10DE200000000000000000000000000000000000F2
+:10DE300000000000000000000000000000000000E2
+:10DE400000000000000000000000000000000000D2
+:10DE500000000000000000000000000000000000C2
+:10DE600000000000000000000000000000000000B2
+:10DE700000000000000000000000000000000000A2
+:10DE80000000000000000000000000000000000092
+:10DE90000000000000000000000000000000000082
+:10DEA0000000000000000000000000000000000072
+:10DEB0000000000000000000000000000000000062
+:10DEC0000000000000000000000000000000000052
+:10DED0000000000000000000000000000000000042
+:10DEE0000000000000000000000000000000000032
+:10DEF0000000000000000000000000000000000022
+:10DF00000000000000000000000000000000000011
+:10DF10000000000000000000000000000000000001
+:10DF200000000000000000000000000000000000F1
+:10DF300000000000000000000000000000000000E1
+:10DF400000000000000000000000000000000000D1
+:10DF500000000000000000000000000000000000C1
+:10DF600000000000000000000000000000000000B1
+:10DF700000000000000000000000000000000000A1
+:10DF80000000000000000000000000000000000091
+:10DF90000000000000000000000000000000000081
+:10DFA0000000000000000000000000000000000071
+:10DFB0000000000000000000000000000000000061
+:10DFC0000000000000000000000000000000000051
+:10DFD0000000000000000000000000000000000041
+:10DFE0000000000000000000000000000000000031
+:10DFF0000000000000000000000000000000000021
+:10E000000000000000000000000000000000000010
+:10E010000000000000000000000000000000000000
+:10E0200000000000000000000000000000000000F0
+:10E0300000000000000000000000000000000000E0
+:10E0400000000000000000000000000000000000D0
+:10E0500000000000000000000000000000000000C0
+:10E0600000000000000000000000000000000000B0
+:10E0700000000000000000000000000000000000A0
+:10E080000000000000000000000000000000000090
+:10E090000000000000000000000000000000000080
+:10E0A0000000000000000000000000000000000070
+:10E0B0000000000000000000000000000000000060
+:10E0C0000000000000000000000000000000000050
+:10E0D0000000000000000000000000000000000040
+:10E0E0000000000000000000000000000000000030
+:10E0F0000000000000000000000000000000000020
+:10E10000000000000000000000000000000000000F
+:10E1100000000000000000000000000000000000FF
+:10E1200000000000000000000000000000000000EF
+:10E1300000000000000000000000000000000000DF
+:10E1400000000000000000000000000000000000CF
+:10E1500000000000000000000000000000000000BF
+:10E1600000000000000000000000000000000000AF
+:10E17000000000000000000000000000000000009F
+:10E18000000000000000000000000000000000008F
+:10E19000000000000000000000000000000000007F
+:10E1A000000000000000000000000000000000006F
+:10E1B000000000000000000000000000000000005F
+:10E1C000000000000000000000000000000000004F
+:10E1D000000000000000000000000000000000003F
+:10E1E000000000000000000000000000000000002F
+:10E1F000000000000000000000000000000000809F
+:10E20000000000000000000000000000000000000E
+:10E2100000000000000000000000000000000000FE
+:10E220000000000A000000000000000000000000E4
+:10E2300010000003000000000000000D0000000DB1
+:10E240003C020801244295A03C030801246397DCAA
+:10E25000AC4000000043202B1480FFFD244200044A
+:10E260003C1D080037BD9FFC03A0F0213C100800B6
+:10E27000261032103C1C0801279C95A00E0012BEEF
+:10E28000000000000000000D3C02800030A5FFFFF0
+:10E2900030C600FF344301803C0880008D0901B87E
+:10E2A0000520FFFE00000000AC6400002404000212
+:10E2B000A4650008A066000AA064000BAC67001803
+:10E2C0003C03100003E00008AD0301B83C0560000A
+:10E2D0008CA24FF80440FFFE00000000ACA44FC029
+:10E2E0003C0310003C040200ACA44FC403E000084F
+:10E2F000ACA34FF89486000C00A050212488001491
+:10E3000000062B0200051080004448210109182B4B
+:10E310001060001100000000910300002C6400094F
+:10E320005080000991190001000360803C0D080134
+:10E3300025AD9234018D58218D67000000E0000862
+:10E340000000000091190001011940210109302B42
+:10E3500054C0FFF29103000003E000080000102108
+:10E360000A000CCC25080001910F0001240E000AC0
+:10E3700015EE00400128C8232F38000A1700003D81
+:10E38000250D00028D580000250F0006370E0100F4
+:10E39000AD4E0000910C000291AB000191A400026F
+:10E3A00091A60003000C2E00000B3C0000A71025D6
+:10E3B00000041A000043C8250326C025AD580004F8
+:10E3C000910E000691ED000191E7000291E5000336
+:10E3D000000E5E00000D6400016C30250007220075
+:10E3E00000C41025004518252508000A0A000CCC99
+:10E3F000AD430008910F000125040002240800022B
+:10E4000055E80001012020210A000CCC00804021A9
+:10E41000910C0001240B0003158B00160000000076
+:10E420008D580000910E000225080003370D0008EA
+:10E43000A14E00100A000CCCAD4D00009119000156
+:10E44000240F0004172F000B0000000091070002AA
+:10E45000910400038D43000000072A0000A410254A
+:10E460003466000425080004AD42000C0A000CCC00
+:10E47000AD46000003E000082402000127BDFFE8CC
+:10E48000AFBF0014AFB000100E00164E0080802108
+:10E490003C0480083485008090A600052403FFFE1C
+:10E4A0000200202100C310248FBF00148FB0001081
+:10E4B000A0A200050A00165827BD001827BDFFE8D6
+:10E4C000AFB00010AFBF00140E000FD40080802149
+:10E4D0003C06800834C5008090A40000240200504F
+:10E4E000308300FF106200073C09800002002021F9
+:10E4F0008FBF00148FB00010AD2001800A00108F74
+:10E5000027BD0018240801003C07800002002021DC
+:10E510008FBF00148FB00010ACE801800A00108F8C
+:10E5200027BD001827BDFF783C058008AFBE0080DE
+:10E53000AFB7007CAFB3006CAFB10064AFBF008475
+:10E54000AFB60078AFB50074AFB40070AFB200687A
+:10E55000AFB0006034A600803C0580008CB201287A
+:10E5600090C400098CA701043C020001309100FF17
+:10E5700000E218240000B8210000F021106000071C
+:10E58000000098213C0908008D2931F02413000176
+:10E59000252800013C010800AC2831F0ACA0008423
+:10E5A00090CC0005000C5827316A0001154000721C
+:10E5B000AFA0005090CD00002406002031A400FF41
+:10E5C00010860018240E0050108E009300000000EA
+:10E5D0003C1008008E1000DC260F00013C010800F2
+:10E5E000AC2F00DC0E0016C7000000000040182110
+:10E5F0008FBF00848FBE00808FB7007C8FB60078FD
+:10E600008FB500748FB400708FB3006C8FB2006848
+:10E610008FB100648FB000600060102103E000083B
+:10E6200027BD00880000000D3C1F8000AFA0003017
+:10E6300097E501168FE201043C04002030B9FFFF8A
+:10E64000004438240007182B00033140AFA60030E7
+:10E650008FF5010437F80C003C1600400338802188
+:10E6600002B6A02434C40040128000479215000D69
+:10E6700032A800201500000234860080008030217E
+:10E6800014C0009FAFA600303C0D800835A6008066
+:10E6900090CC0008318B0040516000063C06800899
+:10E6A000240E0004122E00A8240F0012122F003294
+:10E6B0003C06800834C401003C0280009447011AE3
+:10E6C0009619000E909F00088E18000830E3FFFF97
+:10E6D00003F9B00432B40004AFB6005CAFA3005835
+:10E6E0008E1600041280002EAFB8005434C3008090
+:10E6F000906800083105004014A0002500000000CB
+:10E700008C70005002D090230640000500000000ED
+:10E710008C71003402D1A82306A201678EE20008A2
+:10E72000126000063C1280003C1508008EB531F4E2
+:10E7300026B600013C010800AC3631F4AE4000447E
+:10E74000240300018FBF00848FBE00808FB7007C40
+:10E750008FB600788FB500748FB400708FB3006CE3
+:10E760008FB200688FB100648FB00060006010212C
+:10E7700003E0000827BD00880E000D2800002021BE
+:10E780000A000D75004018210A000D9500C02021D7
+:10E790000E00171702C020211440FFE10000000006
+:10E7A0003C0B8008356400808C8A003402CA482300
+:10E7B0000520001D000000003C1E08008FDE310017
+:10E7C00027D700013C010800AC3731001260000679
+:10E7D000024020213C1408008E9431F42690000160
+:10E7E0003C010800AC3031F40E00164E3C1E80088F
+:10E7F00037CD008091B700250240202136EE00047D
+:10E800000E001658A1AE00250E000CAC02402021CF
+:10E810000A000DCA240300013C17080126F796A040
+:10E820000A000D843C1F80008C86003002C66023E5
+:10E830001980000C2419000C908F004F3C14080024
+:10E840008E94310032B500FC35ED0001268E0001BA
+:10E850003C010800AC2E3100A08D004FAFA0005845
+:10E860002419000CAFB900308C9800300316A02397
+:10E870001A80010B8FA300580074F82A17E0FFD309
+:10E88000000000001074002A8FA5005802D4B021A7
+:10E8900000B410233044FFFFAFA4005832A8000298
+:10E8A0001100002E32AB00103C15800836B00080FD
+:10E8B0009216000832D30040526000FB8EE200083E
+:10E8C0000E00164E02402021240A0018A20A000958
+:10E8D000921100052409FFFE024020210229902404
+:10E8E0000E001658A2120005240400390000282149
+:10E8F0000E0016F2240600180A000DCA24030001B7
+:10E9000092FE000C3C0A800835490080001EBB00C6
+:10E910008D27003836F10081024020213225F08118
+:10E920000E000C9B30C600FF0A000DC10000000065
+:10E930003AA7000130E300011460FFA402D4B02123
+:10E940000A000E1D00000000024020210E001734B6
+:10E95000020028210A000D75004018211160FF7087
+:10E960003C0F80083C0D800835EE00808DC40038D7
+:10E970008FA300548DA60004006660231D80FF68ED
+:10E98000000000000064C02307020001AFA400548F
+:10E990003C1F08008FFF31E433F9000113200015FC
+:10E9A0008FAC00583C07800094E3011A10600012FD
+:10E9B0003C0680080E002161024020213C03080132
+:10E9C000906396D13064000214800145000000007D
+:10E9D000306C0004118000078FAC0058306600FBDB
+:10E9E0003C010801A02696D132B500FCAFA000582A
+:10E9F0008FAC00583C06800834D30080AFB40018B8
+:10EA0000AFB60010AFAC00143C088000950B01209D
+:10EA10008E6F0030966A005C8FA3005C8FBF003061
+:10EA20003169FFFF3144FFFF8FAE005401341021E4
+:10EA3000350540000064382B0045C82103E7C02598
+:10EA4000AFB90020AFAF0028AFB80030AFAF00249F
+:10EA5000AFA0002CAFAE0034926D000831B40008B6
+:10EA6000168000BB020020218EE200040040F8095D
+:10EA700027A400108FAF003031F300025660000170
+:10EA800032B500FE3C048008349F008093F90008F2
+:10EA900033380040530000138FA400248C850004F9
+:10EAA0008FA7005410A700D52404001432B0000131
+:10EAB0001200000C8FA400242414000C1234011A3C
+:10EAC0002A2D000D11A001022413000E240E000AAD
+:10EAD000522E0001241E00088FAF002425E40001FF
+:10EAE000AFA400248FAA00143C0B80083565008079
+:10EAF000008A48218CB10030ACA9003090A4004EAF
+:10EB00008CA700303408FFFF0088180400E3F821C8
+:10EB1000ACBF00348FA600308FB900548FB8005CB2
+:10EB200030C200081040000B033898218CAC002044
+:10EB3000119300D330C600FF92EE000C8FA7003473
+:10EB400002402021000E6B0035B400800E000C9BAB
+:10EB50003285F0803C028008345000808E0F0030F7
+:10EB600001F1302318C00097264800803C070800B8
+:10EB70008CE731E42404FF80010418243118007F5D
+:10EB80003C1F80003C19800430F10001AFE300908D
+:10EB900012200006031928213C030801906396D136
+:10EBA00030690008152000C6306A00F73C10800864
+:10EBB00036040080908C004F318B000115600042BC
+:10EBC000000000003C0608008CC6319830CE0010D2
+:10EBD00051C0004230F9000190AF006B55E0003F9A
+:10EBE00030F9000124180001A0B8006B3C1180002E
+:10EBF0009622007A24470064A48700123C0D800806
+:10EC000035A5008090B40008329000401600000442
+:10EC10003C03800832AE000115C0008B00000000EC
+:10EC2000346400808C86002010D3000A3463010015
+:10EC30008C67000002C7782319E000978FBF00544B
+:10EC4000AC93002024130001AC760000AFB3005059
+:10EC5000AC7F000417C0004E000000008FA90050D8
+:10EC60001520000B000000003C030801906396D1C2
+:10EC7000306A00011140002E8FAB0058306400FE56
+:10EC80003C010801A02496D10A000D75000018214E
+:10EC90000E000CAC024020210A000F1300000000FF
+:10ECA0000A000E200000A0210040F80924040017EB
+:10ECB0000A000DCA240300010040F80924040016CC
+:10ECC0000A000DCA240300019094004F240DFFFE9A
+:10ECD000028D2824A085004F30F900011320000682
+:10ECE0003C0480083C030801906396D1307F0010FB
+:10ECF00017E00051306800EF34900080240A0001D2
+:10ED0000024020210E00164EA60A00129203002592
+:10ED100024090001AFA90050346200010240202103
+:10ED20000E001658A20200250A000EF93C0D8008BC
+:10ED30001160FE83000018218FA5003030AC000464
+:10ED40001180FE2C8FBF00840A000DCB240300012C
+:10ED500027A500380E000CB6AFA000385440FF4382
+:10ED60008EE200048FB40038329001005200FF3F61
+:10ED70008EE200048FA3003C8E6E0058006E682364
+:10ED800005A3FF39AE6300580A000E948EE200041A
+:10ED90000E00164E024020213C038008346800809B
+:10EDA000024020210E001658A11E000903C0302188
+:10EDB000240400370E0016F2000028210A000F116B
+:10EDC0008FA900508FAB00185960FF8D3C0D800853
+:10EDD0000E00164E02402021920C00252405000151
+:10EDE000AFA5005035820004024020210E001658C5
+:10EDF000A20200250A000EF93C0D800812240059D9
+:10EE00002A2300151060004D240900162408000C68
+:10EE10005628FF2732B000013C0A8008914C001BA5
+:10EE20002406FFBD241E000E01865824A14B001BA2
+:10EE30000A000EA532B000013C010801A02896D1BD
+:10EE40000A000EF93C0D80088CB500308EFE0008DB
+:10EE50002404001826B6000103C0F809ACB600303F
+:10EE60003C030801906396D13077000116E0FF81E2
+:10EE7000306A00018FB200300A000D753243000481
+:10EE80003C1080009605011A50A0FF2B34C60010DC
+:10EE90000A000EC892EE000C8C6200001456FF6D42
+:10EEA000000000008C7800048FB9005403388823D8
+:10EEB0000621FF638FBF00540A000F0E0000000000
+:10EEC0003C010801A02A96D10A000F3030F9000158
+:10EED0001633FF028FAF00240A000EB0241E00106C
+:10EEE0000E00164E024020213C0B80083568008041
+:10EEF00091090025240A0001AFAA0050353300040F
+:10EF0000024020210E001658A11300253C050801DF
+:10EF100090A596D130A200FD3C010801A02296D117
+:10EF20000A000E6D004018212411000E53D1FEEA94
+:10EF3000241E00100A000EAF241E00165629FEDC07
+:10EF400032B000013C0A8008914C001B2406FFBD32
+:10EF5000241E001001865824A14B001B0A000EA598
+:10EF600032B000010A000EA4241E00123C038000EF
+:10EF70008C6201B80440FFFE24040800AC6401B8B0
+:10EF800003E000080000000030A5FFFF30C6FFFFCF
+:10EF90003C0780008CE201B80440FFFE34EA0180A7
+:10EFA000AD440000ACE400203C0480089483004899
+:10EFB0003068FFFF11000016AF88000824AB001274
+:10EFC000010B482B512000133C04800034EF01005A
+:10EFD00095EE00208F890000240D001A31CCFFFF30
+:10EFE00031274000A14D000B10E000362583FFFEC5
+:10EFF0000103C02B170000348F9900048F88000490
+:10F00000A5430014350700010A001003AF87000470
+:10F010003C04800024030003348201808F890000B7
+:10F020008F870004A043000B3C088000350C018052
+:10F03000A585000EA585001A8F85000C30EB800099
+:10F04000A5890010AD850028A58600081160000F75
+:10F050008F85001435190100972A00163158FFFCDE
+:10F06000270F000401E870218DCD400031A6FFFF7D
+:10F0700014C000072403BFFF3C02FFFF34487FFF9A
+:10F0800000E83824AF8700048F8500142403BFFFF5
+:10F090003C04800000E3582434830180A46B0026E4
+:10F0A000AC69002C10A0000300054C02A465001000
+:10F0B000A46900263C071000AC8701B803E00008F3
+:10F0C000000000008F990004240AFFFE032A382460
+:10F0D0000A001003AF87000427BDFFE88FA20028B5
+:10F0E00030A5FFFF30C6FFFFAFBF0010AF87000C99
+:10F0F000AF820014AF8000040E000FDBAF80000071
+:10F100008FBF001027BD001803E00008AF80001477
+:10F110003C06800034C4007034C701008C8A0000B3
+:10F1200090E500128F84000027BDFFF030A300FFA0
+:10F13000000318823082400010400037246500032D
+:10F140000005C8800326C0218F0E4000246F0004F4
+:10F15000000F6880AFAE000001A660218D8B4000DB
+:10F16000AFAB000494E900163128FFFC01063821FA
+:10F170008CE64000AFA600088FA9000800003021EF
+:10F18000000028213C07080024E701000A0010675E
+:10F19000240800089059000024A500012CAC000CA4
+:10F1A0000079C0210018788001E770218DCD000022
+:10F1B0001180000600CD302603A5102114A8FFF50C
+:10F1C00000051A005520FFF4905900003C0480000F
+:10F1D000348700703C0508008CA531048CE30000E6
+:10F1E0002CA2002010400009006A38230005488046
+:10F1F0003C0B0800256B3108012B402124AA00019B
+:10F20000AD0700003C010800AC2A310400C0102109
+:10F2100003E0000827BD0010308220001040000BE2
+:10F2200000055880016648218D24400024680004B0
+:10F2300000083880AFA4000000E618218C6540006B
+:10F24000AFA000080A001057AFA500040000000D91
+:10F250000A0010588FA9000827BDFFE03C07800076
+:10F2600034E60100AFBF001CAFB20018AFB100140C
+:10F27000AFB0001094C5000E8F87000030A4FFFFD0
+:10F280002483000430E2400010400010AF830028C7
+:10F290003C09002000E940241100000D30EC800002
+:10F2A0008F8A0004240BBFFF00EB38243543100085
+:10F2B000AF87000030F220001640000B3C1900041C
+:10F2C000241FFFBF0A0010B7007F102430EC80001D
+:10F2D000158000423C0E002030F220001240FFF862
+:10F2E0008F8300043C19000400F9C0241300FFF5CB
+:10F2F000241FFFBF34620040AF82000430E20100EF
+:10F300001040001130F010008F83002C10600006B8
+:10F310003C0F80003C05002000E52024148000C044
+:10F320003C0800043C0F800035EE010095CD001E26
+:10F3300095CC001C31AAFFFF000C5C00014B482556
+:10F34000AF89000C30F010001200000824110001F9
+:10F3500030F100201620008B3C18100000F890249B
+:10F36000164000823C040C002411000130E801002A
+:10F370001500000B3C0900018F85000430A94000F6
+:10F38000152000073C0900013C0C1F0100EC58242B
+:10F390003C0A1000116A01183C1080003C09000171
+:10F3A00000E9302410C000173C0B10003C18080086
+:10F3B0008F1800243307000214E0014024030001E9
+:10F3C0008FBF001C8FB200188FB100148FB00010D7
+:10F3D0000060102103E0000827BD002000EE682433
+:10F3E00011A0FFBE30F220008F8F00043C11FFFF00
+:10F3F00036307FFF00F0382435E380000A0010A685
+:10F40000AF87000000EB102450400065AF8000245F
+:10F410008F8C002C3C0D0F0000ED18241580008807
+:10F42000AF83001030E8010011000086938F0010B8
+:10F430003C0A0200106A00833C1280003650010032
+:10F44000920500139789002A3626000230AF00FF8C
+:10F4500025EE0004000E19C03C0480008C9801B811
+:10F460000700FFFE34880180AD0300003C198008CE
+:10F47000AC830020973100483225FFFF10A0015CCB
+:10F48000AF8500082523001200A3F82B53E0015993
+:10F490008F850004348D010095AC00202402001AF1
+:10F4A00030E44000318BFFFFA102000B108001927D
+:10F4B0002563FFFE00A3502B154001908F8F0004A1
+:10F4C000A50300148F88000435050001AF850004F2
+:10F4D0003C08800035190180A729000EA729001AD1
+:10F4E0008F89000C30B18000A7270010AF290028B9
+:10F4F000A72600081220000E3C04800035020100FF
+:10F50000944C0016318BFFFC256400040088182100
+:10F510008C7F400033E6FFFF14C000053C048000F0
+:10F520003C0AFFFF354D7FFF00AD2824AF85000466
+:10F53000240EBFFF00AE402434850180A4A800261D
+:10F54000ACA7002C3C071000AC8701B800001821C4
+:10F550008FBF001C8FB200188FB100148FB0001045
+:10F560000060102103E0000827BD00203C020BFFD3
+:10F5700000E41824345FFFFF03E3C82B5320FF7B14
+:10F58000241100013C0608008CC6002C24C5000193
+:10F590003C010800AC25002C0A0010D42411000501
+:10F5A0008F85002410A0002FAF80001090A30000D2
+:10F5B000146000792419000310A0002A30E601002D
+:10F5C00010C000CC8F860010241F000210DF00C97D
+:10F5D0008F8B000C3C0708008CE7003824E4FFFF09
+:10F5E00014E0000201641824000018213C0D0800FA
+:10F5F00025AD0038006D1021904C00048F85002847
+:10F6000025830004000321C030A5FFFF3626000239
+:10F610000E000FDB000000000A00114D0000182151
+:10F6200000E8302414C0FF403C0F80000E00103D65
+:10F63000000000008F8700000A0010CAAF82000C93
+:10F64000938F00103C18080127189620000F90C0D7
+:10F6500002588021AF9000248F85002414A0FFD38E
+:10F66000AF8F00103C0480008C86400030C5010044
+:10F6700010A000BC322300043C0C08008D8C002438
+:10F6800024120004106000C23190000D3C04800080
+:10F690008C8D40003402FFFF11A201003231FFFBCC
+:10F6A0008C884000310A01005540000124110010EF
+:10F6B00030EE080011C000BE2419FFFB8F9800280F
+:10F6C0002F0F03EF51E000010219802430E90100FF
+:10F6D00011200014320800018F87002C14E000FB79
+:10F6E0008F8C000C3C05800034AB0100917F00132F
+:10F6F00033E300FF246A00042403FFFE0203802496
+:10F70000000A21C012000002023230253226FFFF1B
+:10F710000E000FDB9785002A1200FF290000182138
+:10F72000320800011100000D32180004240E0001FF
+:10F73000120E0002023230253226FFFF9785002A82
+:10F740000E000FDB00002021240FFFFE020F80249B
+:10F750001200FF1B00001821321800045300FF188C
+:10F760002403000102323025241200045612000145
+:10F770003226FFFF9785002A0E000FDB24040100CC
+:10F780002419FFFB021988241220FF0D0000182104
+:10F790000A0010E9240300011079009C00003021C8
+:10F7A00090AD00012402000211A200BE30EA004028
+:10F7B00090B90001241800011338007F30E900409F
+:10F7C0008CA600049785002A00C020210E000FDBC4
+:10F7D0003626000200004021010018218FBF001CC6
+:10F7E0008FB200188FB100148FB00010006010218C
+:10F7F00003E0000827BD0020360F010095EE000C45
+:10F8000031CD020015A0FEE63C0900013C1880083D
+:10F81000971200489789002A362600023248FFFFD7
+:10F82000AF8800083C0380008C7101B80620FFFE01
+:10F83000346A0180AD4000001100008E3C0F800052
+:10F84000253F0012011FC82B1320008B240E00033C
+:10F85000346C0100958B00202402001A30E4400033
+:10F860003163FFFFA142000B108000A72463FFFE5D
+:10F870000103682B15A000A52408FFFE34A5000194
+:10F88000A5430014AF8500043C0480002412BFFF90
+:10F8900000B2802434850180A4A9000EA4A9001A16
+:10F8A000A4A60008A4B00026A4A700103C071000DE
+:10F8B000AC8701B80A00114D000018213C038000FC
+:10F8C00034640100949F000E3C1908008F3900D861
+:10F8D0002404008033E5FFFF273100013C010800CC
+:10F8E000AC3100D80E000FDB240600030A00114DD6
+:10F8F00000001821240A000210CA00598F85002830
+:10F900003C0308008C6300D0240E0001106E005EE2
+:10F910002CCF000C24D2FFFC2E5000041600002136
+:10F9200000002021241800021078001B2CD9000CA4
+:10F9300024DFFFF82FE900041520FF330000202109
+:10F9400030EB020051600004000621C054C00022C8
+:10F9500030A5FFFF000621C030A5FFFF0A00117D82
+:10F96000362600023C0908008D29002431300001B0
+:10F970005200FEF7000018219785002A3626000263
+:10F980000E000FDB000020210A00114D000018219D
+:10F990000A00119C241200021320FFE624DFFFF866
+:10F9A0000000202130A5FFFF0A00117D362600024D
+:10F9B0000A0011AC021980245120FF828CA6000499
+:10F9C0003C05080190A5962110A0FF7E24080001A7
+:10F9D0000A0011F0010018210E000FDB3226000191
+:10F9E0008F8600108F8500280A00124F000621C064
+:10F9F0008F8500043C18800024120003371001801A
+:10FA0000A212000B0A00112E3C08800090A30001F6
+:10FA1000241100011071FF70240800012409000264
+:10FA20005069000430E60040240800010A0011F08B
+:10FA30000100182150C0FFFD240800013C0C80008B
+:10FA4000358B01009563001094A40002307FFFFF06
+:10FA5000509FFF62010018210A001284240800014F
+:10FA60002CA803EF1100FE56240300010A001239EE
+:10FA700000000000240E000335EA0180A14E000BB7
+:10FA80000A00121C3C04800011E0FFA2000621C005
+:10FA900030A5FFFF0A00117D362600020A0011A5DD
+:10FAA000241100201140FFC63C1280003650010096
+:10FAB000960F001094AE000231E80FFF15C8FFC08A
+:10FAC000000000000A0011E690B900013C060800A1
+:10FAD0008CC6003824C4FFFF14C00002018418241F
+:10FAE000000018213C0D080025AD0038006D1021E4
+:10FAF0000A0011B6904300048F8F0004240EFFFE0D
+:10FB00000A00112C01EE28242408FFFE0A00121A14
+:10FB100000A8282427BDFFC8AFB00010AFBF003435
+:10FB20003C10600CAFBE0030AFB7002CAFB6002861
+:10FB3000AFB50024AFB40020AFB3001CAFB20018C3
+:10FB4000AFB100148E0E5000240FFF7F3C068000E2
+:10FB500001CF682435AC380C240B0003AE0C5000E8
+:10FB6000ACCB00083C010800AC2000200E001819A6
+:10FB7000000000003C0A0010354980513C06601628
+:10FB8000AE09537C8CC700003C0860148D0500A0B2
+:10FB90003C03FFFF00E320243C02535300051FC237
+:10FBA0001482000634C57C000003A08002869821E0
+:10FBB0008E7200043C116000025128218CBF007C31
+:10FBC0008CA200783C1E600037C420203C05080150
+:10FBD00024A59264AF820018AF9F001C0E0016DDB2
+:10FBE0002406000A3C190001273996203C01080030
+:10FBF000AC3931DC0E0020D4AF8000148FD7080858
+:10FC00002418FFF03C15570902F8B02412D502F56C
+:10FC100024040001AF80002C3C1480003697018042
+:10FC20003C1E080127DE9624369301008E900000CA
+:10FC30003205000310A0FFFD3207000110E000882C
+:10FC4000320600028E7100283C048000AE91002034
+:10FC50008E6500048E66000000A0382100C040219F
+:10FC60008C8301B80460FFFE3C0B0010240A0800DE
+:10FC700000AB4824AC8A01B8552000E0240BBFFF3C
+:10FC80009675000E3C1208008E52002030AC4000E9
+:10FC900032AFFFFF264E000125ED00043C010800B5
+:10FCA000AC2E0020118000E8AF8D00283C18002009
+:10FCB00000B8B02412C000E530B980002408BFFFAE
+:10FCC00000A8382434C81000AF87000030E62000B8
+:10FCD00010C000E92409FFBF3C03000400E328240E
+:10FCE00010A00002010910243502004030EA010092
+:10FCF00011400010AF8200048F8B002C11600007B0
+:10FD00003C0D002000ED6024118000043C0F000435
+:10FD100000EF702411C00239000000009668001E38
+:10FD20009678001C3115FFFF0018B40002B690252C
+:10FD3000AF92000C30F910001320001324150001BD
+:10FD400030FF002017E0000A3C04100000E41024FB
+:10FD50001040000D3C0A0C003C090BFF00EA18247F
+:10FD60003525FFFF00A3302B10C0000830ED010047
+:10FD70003C0C08008D8C002C24150005258B0001FF
+:10FD80003C010800AC2B002C30ED010015A0000B4D
+:10FD90003C0500018F85000430AE400055C00007CF
+:10FDA0003C0500013C161F0100F690243C0F10009A
+:10FDB000124F01CE000000003C05000100E5302498
+:10FDC00010C000AF3C0C10003C1F08008FFF002447
+:10FDD00033E90002152000712403000100601021A6
+:10FDE000104000083C0680003C08800035180100E7
+:10FDF0008F0F00243C056020ACAF00140000000011
+:10FE00003C0680003C194000ACD9013800000000DD
+:10FE10005220001332060002262B0140262C0080BF
+:10FE2000240EFF80016E2024018E6824000D1940ED
+:10FE3000318A007F0004A9403172007F3C16200007
+:10FE400036C20002006A482502B2382500E2882541
+:10FE50000122F825ACDF0830ACD1083032060002B0
+:10FE600010C0FF723C188000370501408CA80000CC
+:10FE700024100040AF08002090AF000831E300706C
+:10FE8000107000D428790041532000082405006038
+:10FE9000241100201071000E3C0A40003C09800033
+:10FEA000AD2A01780A001304000000001465FFFB6E
+:10FEB0003C0A40000E001FF1000000003C0A400018
+:10FEC0003C098000AD2A01780A00130400000000FC
+:10FED00090A90009241F00048CA70000312800FF0E
+:10FEE000111F01B22503FFFA2C7200061240001404
+:10FEF0003C0680008CA9000494A4000A310500FF90
+:10FF000000095E022D6A00083086FFFF15400002DE
+:10FF10002567000424070003240C000910AC01FA33
+:10FF200028AD000A11A001DE2410000A240E0008EA
+:10FF300010AE0028000731C000C038213C06800008
+:10FF40008CD501B806A0FFFE34D20180AE47000078
+:10FF500034CB0140916E0008240300023C0A4000AB
+:10FF600031C400FF00046A0001A86025A64C000807
+:10FF7000A243000B9562000A3C0810003C09800077
+:10FF8000A64200108D670004AE470024ACC801B83B
+:10FF9000AD2A01780A001304000000003C0A80002A
+:10FFA000354401009483000E3C0208008C4200D8C6
+:10FFB000240400803065FFFF245500013C01080047
+:10FFC000AC3500D80E000FDB240600030A001370C6
+:10FFD000000018210009320230D900FF2418000166
+:10FFE0001738FFD5000731C08F910020262200016D
+:10FFF000AF8200200A0013C800C0382100CB2024A3
+:020000040001F9
+:10000000AF85000010800008AF860004240D87FF34
+:1000100000CD6024158000083C0E006000AE302446
+:1000200010C00005000000000E000D42000000009E
+:100030000A001371000000000E0016050000000009
+:100040000A0013710000000030B980005320FF1F28
+:10005000AF8500003C02002000A2F82453E0FF1B03
+:10006000AF8500003C07FFFF34E47FFF00A4382485
+:100070000A00132B34C880000A001334010910242D
+:1000800000EC58245160005AAF8000248F8D002C62
+:100090003C0E0F0000EE182415A00075AF83001071
+:1000A00030EF010011E00073939800103C12020041
+:1000B000107200703C06800034D9010093280013B0
+:1000C0009789002A36A60002311800FF271600047F
+:1000D000001619C03C0480008C8501B804A0FFFE06
+:1000E00034880180AD0300003C158008AC830020FB
+:1000F00096BF004833E5FFFF10A001BCAF850008A4
+:100100002523001200A3102B504001B98F85000455
+:10011000348D010095AC0020240B001A30E440001F
+:10012000318AFFFFA10B000B108001BA2543FFFEAF
+:1001300000A3702B15C001B88F9600048F8F0004A8
+:10014000A503001435E50001AF8500043C088000DC
+:1001500035150180A6A9000EA6A9001A8F89000CEA
+:1001600030BF8000A6A70010AEA90028A6A60008F0
+:1001700013E0000F3C0F8000350C0100958B00163A
+:10018000316AFFFC25440004008818218C6240007D
+:100190003046FFFF14C000072416BFFF3C0EFFFFD0
+:1001A00035CD7FFF00AD2824AF8500043C0F8000D3
+:1001B0002416BFFF00B6902435E50180A4B20026C6
+:1001C000ACA7002C3C071000ADE701B80A00137083
+:1001D000000018210E00165D000000003C0A4000DF
+:1001E0003C098000AD2A01780A00130400000000D9
+:1001F0008F85002410A00027AF80001090A300007E
+:10020000106000742409000310690101000030210E
+:1002100090AE0001240D000211CD014230EF0040EC
+:1002200090A90001241F0001113F000930E20040A5
+:100230008CA600049785002A00C020210E000FDB49
+:1002400036A60002000040210A00137001001821A8
+:100250005040FFF88CA600043C07080190E7962167
+:1002600010E0FFF4240800010A00137001001821B7
+:10027000939800103C1F080127FF96200018C8C063
+:10028000033F4021AF8800248F85002414A0FFDBAA
+:10029000AF9800103C0480008C86400030C50100FF
+:1002A00010A0008732AB00043C0C08008D8C0024A9
+:1002B00024160004156000033192000D241600027C
+:1002C0003C0480008C8E4000340DFFFF11CD0113E3
+:1002D00032B5FFFB8C984000330F010055E0000160
+:1002E0002415001030E80800110000382409FFFB35
+:1002F0008F9F00282FF903EF53200001024990241B
+:1003000030E2010010400014325F00018F87002CA2
+:1003100014E0010E8F8C000C3C0480003486010038
+:1003200090C5001330AA00FF25430004000321C03C
+:100330002419FFFE025990241240000202B6302513
+:1003400032A6FFFF0E000FDB9785002A1240FEA3A6
+:1003500000001821325F000113E0000D3247000455
+:10036000240900011249000202B6302532A6FFFF1F
+:100370009785002A0E000FDB000020212402FFFEDB
+:10038000024290241240FE950000182132470004DA
+:1003900050E0FE922403000102B63025241600042A
+:1003A0005656000132A6FFFF9785002A0E000FDB8C
+:1003B000240401002403FFFB0243A82412A0FE87AB
+:1003C000000018210A001370240300010A0014B968
+:1003D0000249902410A0FFAF30E5010010A00017E3
+:1003E0008F8600102403000210C300148F84000CB9
+:1003F0003C0608008CC6003824CAFFFF14C0000267
+:10040000008A1024000010213C0E080025CE003880
+:10041000004E682191AC00048F850028258B0004D4
+:10042000000B21C030A5FFFF36A600020E000FDB37
+:10043000000000000A00137000001821240F0002C1
+:1004400010CF0088241600013C0308008C6300D004
+:100450001076008D8F85002824D9FFFC2F280004FA
+:100460001500006300002021241F0002107F005DA2
+:100470002CC9000C24C3FFF82C6200041440FFE9CF
+:100480000000202130EA020051400004000621C093
+:1004900054C0000530A5FFFF000621C030A5FFFFB6
+:1004A0000A00150436A600020E000FDB32A600017A
+:1004B0008F8600108F8500280A001520000621C0B5
+:1004C0003C0A08008D4A0024315200015240FE438C
+:1004D000000018219785002A36A600020E000FDBC7
+:1004E000000020210A001370000018219668000CFB
+:1004F000311802005700FE313C0500013C1F800806
+:1005000097F900489789002A36A600023328FFFF92
+:10051000AF8800083C0380008C7501B806A0FFFE80
+:100520003C04800034820180AC400000110000B621
+:1005300024180003252A0012010A182B106000B2AB
+:1005400000000000966F00203C0E8000240D001A71
+:1005500031ECFFFF35CA018030EB4000A14D000BAC
+:10056000116000B02583FFFE0103902B164000AE02
+:100570002416FFFE34A50001A5430014AF85000436
+:100580002419BFFF00B94024A6E9000EA6E9001A0D
+:10059000A6E60008A6E80026A6E700103C07100023
+:1005A000AE8701B80A001370000018213C048000D7
+:1005B0008C8201B80440FFFE349601802415001C93
+:1005C000AEC70000A2D5000B3C071000AC8701B8F5
+:1005D0003C0A40003C098000AD2A01780A0013045F
+:1005E000000000005120FFA424C3FFF800002021D8
+:1005F00030A5FFFF0A00150436A600020E00103DCC
+:10060000000000008F8700000A001346AF82000C34
+:1006100090A30001241500011075FF0B24080001B0
+:10062000240600021066000430E2004024080001A5
+:100630000A001370010018215040FFFD240800013A
+:100640003C0C8000358B0100956A001094A40002D8
+:100650003143FFFF5083FDE1010018210A00158599
+:10066000240800018F8500282CB203EF1240FDDB27
+:10067000240300013C0308008C6300D02416000111
+:100680001476FF7624D9FFFC2CD8000C1300FF72DF
+:10069000000621C030A5FFFF0A00150436A600029F
+:1006A00010B00037240F000B14AFFE23000731C039
+:1006B000312600FF00065600000A4E0305220047BF
+:1006C00030C6007F0006F8C03C16080126D69620EA
+:1006D00003F68021A2000001A20000003C0F600090
+:1006E0008DF918202405000100C588040011302769
+:1006F0000326C024000731C000C03821ADF81820FF
+:100700000A0013C8A60000028F850020000731C030
+:1007100024A2FFFF0A0013F6AF8200200A0014B2E1
+:100720002415002011E0FECC3C1980003728010080
+:100730009518001094B6000233120FFF16D2FEC6B1
+:10074000000000000A00148290A900013C0B080080
+:100750008D6B0038256DFFFF15600002018D1024A0
+:10076000000010213C080800250800380048C0217E
+:10077000930F000425EE00040A0014C5000E21C0EA
+:1007800000065202241F00FF115FFDEB000731C07D
+:10079000000A20C03C0E080125CE9620008EA8211C
+:1007A000009E602100095C02240D00013C076000EE
+:1007B000A2AD0000AD860000A2AB00018CF21820B3
+:1007C00024030001014310040242B025ACF61820B6
+:1007D00000C038210A0013C8A6A900020A0015AA01
+:1007E000AF8000200A0012FFAF84002C8F85000428
+:1007F0003C1980002408000337380180A308000B4F
+:100800000A00144D3C088000A2F8000B0A00155A9B
+:100810002419BFFF8F9600042412FFFE0A00144B18
+:1008200002D228242416FFFE0A00155800B62824F8
+:100830003C038000346401008C85000030A2003E3F
+:100840001440000800000000AC6000488C870000E5
+:1008500030E607C010C0000500000000AC60004C8E
+:10086000AC60005003E0000824020001AC600054BA
+:10087000AC6000408C880000310438001080FFF923
+:10088000000000002402000103E00008AC60004406
+:100890003C0380008C6201B80440FFFE3467018095
+:1008A000ACE4000024080001ACE00004A4E500086A
+:1008B00024050002A0E8000A34640140A0E5000B12
+:1008C0009483000A14C00008A4E30010ACE00024E4
+:1008D0003C07800034E901803C041000AD20002872
+:1008E00003E00008ACE401B88C8600043C0410006E
+:1008F000ACE600243C07800034E90180AD200028EC
+:1009000003E00008ACE401B83C0680008CC201B8EA
+:100910000440FFFE34C7018024090002ACE400005B
+:10092000ACE40004A4E50008A0E9000A34C50140D5
+:10093000A0E9000B94A8000A3C041000A4E80010F1
+:10094000ACE000248CA30004ACE3002803E0000822
+:10095000ACC401B83C039000346200010082202541
+:100960003C038000AC6400208C65002004A0FFFEE6
+:100970000000000003E00008000000003C028000CE
+:10098000344300010083202503E00008AC4400202C
+:1009900027BDFFE03C098000AFBF0018AFB10014D5
+:1009A000AFB00010352801408D10000091040009FF
+:1009B0009107000891050008308400FF30E600FF31
+:1009C00000061A002C820081008330251040002A86
+:1009D00030A50080000460803C0D080125AD928C9C
+:1009E000018D58218D6A00000140000800000000C0
+:1009F0003C038000346201409445000A14A0001EAC
+:100A00008F91FCBC9227000530E6000414C0001A48
+:100A1000000000000E00164E02002021922A000560
+:100A200002002021354900040E001658A2290005B5
+:100A30009228000531040004148000020000000028
+:100A40000000000D922D0000240B002031AC00FFAF
+:100A5000158B00093C0580008CAE01B805C0FFFE77
+:100A600034B10180AE3000003C0F100024100005AE
+:100A7000A230000BACAF01B80000000D8FBF001812
+:100A80008FB100148FB0001003E0000827BD0020D4
+:100A90000200202100C028218FBF00188FB1001450
+:100AA0008FB00010240600010A00161D27BD00208B
+:100AB0000000000D0200202100C028218FBF001877
+:100AC0008FB100148FB00010000030210A00161DF5
+:100AD00027BD002014A0FFE8000000000200202134
+:100AE0008FBF00188FB100148FB0001000C02821F4
+:100AF0000A00163B27BD00203C0780008CEE01B8A1
+:100B000005C0FFFE34F00180241F0002A21F000B6D
+:100B100034F80140A60600089719000A3C0F10009F
+:100B2000A61900108F110004A6110012ACEF01B835
+:100B30000A0016998FBF001827BDFFE8AFBF00104D
+:100B40000E000FD4000000003C0280008FBF001098
+:100B500000002021AC4001800A00108F27BD001842
+:100B60003084FFFF30A5FFFF108000070000182130
+:100B7000308200011040000200042042006518216C
+:100B80001480FFFB0005284003E0000800601021EE
+:100B900010C00007000000008CA2000024C6FFFF68
+:100BA00024A50004AC82000014C0FFFB24840004D0
+:100BB00003E000080000000010A0000824A3FFFFCD
+:100BC000AC86000000000000000000002402FFFFCF
+:100BD0002463FFFF1462FFFA2484000403E000088A
+:100BE000000000003C03800027BDFFF83462018054
+:100BF000AFA20000308C00FF30AD00FF30CE00FF10
+:100C00003C0B80008D6401B80480FFFE00000000F2
+:100C10008FA900008D6801288FAA00008FA700000F
+:100C20008FA400002405000124020002A085000A10
+:100C30008FA30000359940003C051000A062000B16
+:100C40008FB800008FAC00008FA600008FAF0000AF
+:100C500027BD0008AD280000AD400004AD80002491
+:100C6000ACC00028A4F90008A70D0010A5EE0012E2
+:100C700003E00008AD6501B83C06800827BDFFE829
+:100C800034C50080AFBF001090A7000924020012F5
+:100C900030E300FF1062000B008030218CA8005070
+:100CA00000882023048000088FBF00108CAA003425
+:100CB000240400390000282100CA4823052000052B
+:100CC000240600128FBF00102402000103E0000878
+:100CD00027BD00180E0016F2000000008FBF0010A4
+:100CE0002402000103E0000827BD001827BDFFC84B
+:100CF000AFB20030AFB00028AFBF0034AFB1002CAE
+:100D000000A0802190A5000D30A6001010C000109A
+:100D1000008090213C0280088C4400048E0300086F
+:100D20001064000C30A7000530A6000510C0009329
+:100D3000240400018FBF00348FB200308FB1002C2B
+:100D40008FB000280080102103E0000827BD003884
+:100D500030A7000510E0000F30AB001210C00006F5
+:100D6000240400013C0980088E0800088D25000439
+:100D70005105009C240400388FBF00348FB200302E
+:100D80008FB1002C8FB000280080102103E00008F4
+:100D900027BD0038240A0012156AFFE6240400016A
+:100DA0000200202127A500100E000CB6AFA00010F5
+:100DB0001440007C3C19800837240080909800087B
+:100DC000331100081220000A8FA7001030FF010025
+:100DD00013E000A48FA300148C8600580066102333
+:100DE000044000043C0A8008AC8300588FA7001020
+:100DF0003C0A800835480080910900083124000829
+:100E00001480000224080003000040213C1F8008D9
+:100E100093F1001193F9001237E600808CCC005456
+:100E2000333800FF03087821322D00FF000F708057
+:100E300001AE282100AC582B1160006F00000000AB
+:100E400094CA005C8CC900543144FFFF0125102373
+:100E50000082182B14600068000000008CCB005446
+:100E60000165182330EC00041180006C000830800C
+:100E70008FA8001C0068102B1040006230ED0004A9
+:100E8000006610232C46008010C00002004088211C
+:100E9000241100800E00164E024020213C0D8008D7
+:100EA00035A6008024070001ACC7000C90C80008DC
+:100EB0000011484035A70100310C007FA0CC00088C
+:100EC0008E05000424AB0001ACCB0030A4D1005C43
+:100ED0008CCA003C9602000E01422021ACC40020C6
+:100EE0008CC3003C0069F821ACDF001C8E190004A3
+:100EF000ACF900008E180008ACF800048FB10010A7
+:100F0000322F000855E0004793A60020A0C0004EF5
+:100F100090D8004E2411FFDFA0F8000890CF000801
+:100F200001F17024A0CE00088E0500083C0B80085B
+:100F300035690080AD2500388D6A00148D2200309F
+:100F40002419005001422021AD24003491230000D7
+:100F5000307F00FF13F90036264F01000E001658AF
+:100F60000240202124040038000028210E0016F23F
+:100F70002406000A0A001757240400010E000D2859
+:100F8000000020218FBF00348FB200308FB1002CC1
+:100F90008FB00028004020210080102103E00008CD
+:100FA00027BD00388E0E00083C0F800835F0008009
+:100FB000AE0E005402402021AE0000300E00164E4E
+:100FC00000000000920D00250240202135AC0020D9
+:100FD0000E001658A20C00250E000CAC0240202179
+:100FE000240400382405008D0E0016F22406001299
+:100FF0000A0017572404000194C5005C0A001792E8
+:1010000030A3FFFF2407021811A0FF9E00E6102363
+:101010008FAE001C0A00179A01C610230A0017970A
+:101020002C620218A0E600080A0017C48E0500080A
+:101030002406FF8001E6C0243C118000AE38002861
+:101040008E0D000831E7007F3C0E800C00EE602121
+:10105000AD8D00E08E080008AF8C00380A0017D074
+:10106000AD8800E4AC800058908500082403FFF7A9
+:1010700000A33824A08700080A0017758FA7001066
+:101080003C05080024A560A83C04080024846FF4F3
+:101090003C020800244260B0240300063C01080121
+:1010A000AC2596A03C010801AC2496A43C010801A3
+:1010B000AC2296A83C010801A02396AC03E00008EE
+:1010C0000000000003E00008240200013C02800050
+:1010D000308800FF344701803C0680008CC301B893
+:1010E0000460FFFE000000008CC501282418FF806A
+:1010F0003C0D800A24AF010001F8702431EC007F20
+:10110000ACCE0024018D2021ACE50000948B00EAD8
+:101110003509600024080002316AFFFFACEA0004D0
+:1011200024020001A4E90008A0E8000BACE00024C0
+:101130003C071000ACC701B8AF84003803E00008DA
+:10114000AF85006C938800488F8900608F820038DB
+:1011500030C600FF0109382330E900FF01221821C1
+:1011600030A500FF2468008810C000020124382147
+:101170000080382130E400031480000330AA00030B
+:101180001140000D312B000310A0000900001021B8
+:1011900090ED0000244E000131C200FF0045602B9D
+:1011A000A10D000024E700011580FFF925080001CA
+:1011B00003E00008000000001560FFF300000000DD
+:1011C00010A0FFFB000010218CF80000245900043F
+:1011D000332200FF0045782BAD18000024E70004FF
+:1011E00015E0FFF92508000403E0000800000000F6
+:1011F00093850048938800588F8700600004320070
+:101200003103007F00E5102B30C47F001040000F39
+:10121000006428258F8400383C0980008C8A00EC0B
+:10122000AD2A00A43C03800000A35825AC6B00A0AD
+:101230008C6C00A00580FFFE000000008C6D00ACEF
+:10124000AC8D00EC03E000088C6200A80A00188254
+:101250008F840038938800593C0280000080502120
+:10126000310300FEA383005930ABFFFF30CC00FFF9
+:1012700030E7FFFF344801803C0980008D2401B82D
+:101280000480FFFE8F8D006C24180016AD0D000049
+:101290008D2201248F8D0038AD0200048D5900206D
+:1012A000A5070008240201C4A119000AA118000B17
+:1012B000952F01208D4E00088D4700049783005C18
+:1012C0008D59002401CF302100C7282100A32023FD
+:1012D0002418FFFFA504000CA50B000EA5020010AA
+:1012E000A50C0012AD190018AD18002495AF00E848
+:1012F0003C0B10002407FFF731EEFFFFAD0E002876
+:101300008DAC0084AD0C002CAD2B01B88D460020B7
+:1013100000C7282403E00008AD4500208F8800386E
+:101320000080582130E7FFFF910900D63C02800081
+:1013300030A5FFFF312400FF00041A00006750258C
+:1013400030C600FF344701803C0980008D2C01B875
+:101350000580FFFE8F82006C240F0017ACE20000B6
+:101360008D390124ACF900048D780020A4EA00082E
+:10137000241901C4A0F8000AA0EF000B9523012056
+:101380008D6E00088D6D00049784005C01C35021B0
+:10139000014D602101841023A4E2000CA4E5000E9D
+:1013A000A4F90010A4E60012ACE000148D7800242B
+:1013B000240DFFFFACF800188D0F007CACEF001C73
+:1013C0008D0E00783C0F1000ACEE0020ACED002438
+:1013D000950A00BE240DFFF73146FFFFACE600285A
+:1013E000950C00809504008231837FFF0003CA00C2
+:1013F0003082FFFF0322C021ACF8002CAD2F01B8D2
+:10140000950E00828D6A002000AE3021014D282407
+:10141000A506008203E00008AD6500203C028000C4
+:10142000344501803C0480008C8301B80460FFFED9
+:101430008F8A0044240600199549001C3128FFFFBB
+:10144000000839C0ACA70000A0A6000B3C051000A6
+:1014500003E00008AC8501B88F87004C0080402174
+:1014600030C400FF3C0680008CC201B80440FFFE7F
+:101470008F89006C9383006834996000ACA90000E8
+:10148000A0A300058CE20010240F00022403FFF744
+:10149000A4A20006A4B900088D180020A0B8000A74
+:1014A000A0AF000B8CEE0000ACAE00108CED000481
+:1014B000ACAD00148CEC001CACAC00248CEB002018
+:1014C000ACAB00288CEA002C3C071000ACAA002C26
+:1014D0008D090024ACA90018ACC701B88D05002007
+:1014E00000A3202403E00008AD0400208F8600380C
+:1014F00027BDFFE0AFB10014AFBF0018AFB00010C0
+:1015000090C300D430A500FF3062002010400008D6
+:10151000008088218CCB00D02409FFDF256A0001E0
+:10152000ACCA00D090C800D401093824A0C700D4A8
+:1015300014A000403C0C80008F840038908700D4B9
+:101540002418FFBF2406FFEF30E3007FA08300D400
+:10155000979F005C8F8200608F8D003803E2C82364
+:10156000A799005CA5A000BC91AF00D401F870243D
+:10157000A1AE00D48F8C0038A18000D78F8A0038AC
+:10158000A5400082AD4000EC914500D400A658244F
+:10159000A14B00D48F9000348F8400609786005C4C
+:1015A0000204282110C0000FAF850034A38000582A
+:1015B0003C0780008E2C000894ED01208E2B000447
+:1015C000018D5021014B8021020620233086FFFF30
+:1015D00030C8000F3909000131310001162000091F
+:1015E000A3880058938600488FBF00188FB100145D
+:1015F0008FB0001027BD0020AF85006403E0000815
+:10160000AF86006000C870238FBF00189386004823
+:101610008FB100148FB0001034EF0C00010F28219F
+:1016200027BD0020ACEE0084AF85006403E0000815
+:10163000AF86006035900180020028210E00190F4E
+:10164000240600828F840038908600D430C5004084
+:1016500050A0FFBAA38000688F85004C3C06800034
+:101660008CCD01B805A0FFFE8F89006C2408608234
+:1016700024070002AE090000A6080008A207000B1C
+:101680008CA300083C0E1000AE0300108CA2000CCE
+:10169000AE0200148CBF0014AE1F00188CB90018E5
+:1016A000AE1900248CB80024AE1800288CAF002896
+:1016B000AE0F002CACCE01B80A001948A380006818
+:1016C0008F8A003827BDFFE0AFB10014AFB0001023
+:1016D0008F880060AFBF00189389003C954200BC22
+:1016E00030D100FF0109182B0080802130AC00FFB1
+:1016F0003047FFFF0000582114600003310600FF4F
+:1017000001203021010958239783005C0068202BB9
+:101710001480002700000000106800562419000102
+:101720001199006334E708803165FFFF0E0018C08F
+:10173000020020218F83006C3C07800034E601808A
+:101740003C0580008CAB01B80560FFFE240A001840
+:101750008F840038ACC30000A0CA000B948900BE7F
+:101760003C081000A4C90010ACC00030ACA801B8FF
+:101770009482008024430001A4830080949F008011
+:101780003C0608008CC6318833EC7FFF1186005E72
+:101790000000000002002021022028218FBF001835
+:1017A0008FB100148FB000100A00193427BD00203B
+:1017B000914400D42403FF8000838825A15100D4E4
+:1017C0009784005C3088FFFF51000023938C003C1D
+:1017D0008F8500382402EFFF008B782394AE00BC85
+:1017E0000168502B31E900FF01C26824A4AD00BCA0
+:1017F00051400039010058213C1F800037E60100AC
+:101800008CD800043C190001031940245500000144
+:1018100034E740008E0A00202403FFFB241100015E
+:1018200001432024AE0400201191002D34E78000F4
+:1018300002002021012030210E0018C03165FFFF79
+:101840009787005C8F890060A780005C0127802358
+:10185000AF900060938C003C8F8B00388FBF0018D6
+:101860008FB100148FB0001027BD002003E00008E6
+:10187000A16C00D73C0D800035AA01008D48000402
+:101880003C0900010109282454A0000134E740006C
+:101890008E0F00202418FFFB34E7800001F870242D
+:1018A00024190001AE0E00201599FF9F34E708802F
+:1018B000020020210E00188E3165FFFF020020215A
+:1018C000022028218FBF00188FB100148FB00010A4
+:1018D0000A00193427BD00200A0019F7000048212A
+:1018E00002002021012030210E00188E3165FFFFFB
+:1018F0009787005C8F890060A780005C01278023A8
+:101900000A001A0EAF900060948C0080241F8000A3
+:10191000019F3024A4860080908B0080908F0080EF
+:10192000316700FF0007C9C20019C027001871C045
+:1019300031ED007F01AE2825A08500800A0019DF67
+:1019400002002021938500682403000127BDFFE8E1
+:1019500000A330042CA20020AFB00010AFBF0014D1
+:1019600000C01821104000132410FFFE3C0708009F
+:101970008CE7319000E610243C088000350501809A
+:1019800014400005240600848F890038240A0004CE
+:101990002410FFFFA12A00FC0E00190F0000000018
+:1019A000020010218FBF00148FB0001003E0000868
+:1019B00027BD00183C0608008CC631940A001A574F
+:1019C00000C310248F87004427BDFFE0AFB200188A
+:1019D000AFB10014AFB00010AFBF001C30D000FF9B
+:1019E00090E6000D00A088210080902130C5007F86
+:1019F000A0E5000D8F8500388E2300188CA200D042
+:101A00001062002E240A000E0E001A4AA38A0068F3
+:101A10002409FFFF104900222404FFFF5200002088
+:101A2000000020218E2600003C0C001000CC582421
+:101A3000156000393C0E000800CE682455A0003F18
+:101A4000024020213C18000200D880241200001F10
+:101A50003C0A00048F8700448CE200148CE30010E1
+:101A60008CE500140043F82303E5C82B1320000580
+:101A7000024020218E24002C8CF1001010910031A6
+:101A80000240202124020012A38200680E001A4A9C
+:101A90002412FFFF105200022404FFFF0000202147
+:101AA0008FBF001C8FB200188FB100148FB00010D0
+:101AB0000080102103E0000827BD002090A800D47A
+:101AC000350400200A001A80A0A400D400CA4824CB
+:101AD0001520000B8F8B00448F8D00448DAC0010BF
+:101AE0001580000B024020218E2E002C51C0FFECEF
+:101AF00000002021024020210A001A9B2402001726
+:101B00008D66001050C0FFE6000020210240202119
+:101B10000A001A9B24020011024020212402001511
+:101B20000E001A4AA3820068240FFFFF104FFFDC4B
+:101B30002404FFFF0A001A8A8E2600000A001AC138
+:101B4000240200143C08000400C8382450E0FFD4EC
+:101B500000002021024020210A001A9B24020013C9
+:101B60008F85003827BDFFD8AFB3001CAFB2001877
+:101B7000AFB10014AFB00010AFBF002090A700D4E9
+:101B80008F90004C2412FFFF34E2004092060000C8
+:101B9000A0A200D48E0300100080982110720006CD
+:101BA00030D1003F2408000D0E001A4AA3880068B7
+:101BB000105200252404FFFF8F8A00388E09001878
+:101BC0008D4400D01124000702602021240C000E57
+:101BD0000E001A4AA38C0068240BFFFF104B001A5A
+:101BE0002404FFFF24040020122400048F8D0038F9
+:101BF00091AF00D435EE0020A1AE00D48F85005403
+:101C000010A00019000000001224004A8F9800382C
+:101C10008F92FCBC971000809651000A5230004809
+:101C20008F9300403C1F08008FFF318C03E5C82BC9
+:101C30001720001E02602021000028210E0019A993
+:101C400024060001000020218FBF00208FB3001C5C
+:101C50008FB200188FB100148FB0001000801021D7
+:101C600003E0000827BD00285224002A8E05001436
+:101C70008F840038948A008025490001A48900805F
+:101C8000948800803C0208008C42318831077FFF35
+:101C900010E2000E00000000026020210E00193446
+:101CA000240500010A001B0B000020212402002D46
+:101CB0000E001A4AA38200682403FFFF1443FFE1C9
+:101CC0002404FFFF0A001B0C8FBF002094990080A2
+:101CD000241F800024050001033FC024A498008035
+:101CE00090920080908E0080325100FF001181C2DE
+:101CF00000107827000F69C031CC007F018D582576
+:101D0000A08B00800E001934026020210A001B0BFA
+:101D1000000020212406FFFF54A6FFD68F84003840
+:101D2000026020210E001934240500010A001B0B5B
+:101D300000002021026020210A001B252402000A45
+:101D40002404FFFD0A001B0BAF9300608F8800384E
+:101D500027BDFFE8AFB00010AFBF0014910A00D458
+:101D60008F87004C00808021354900408CE60010B0
+:101D7000A10900D43C0208008C4231B030C53FFFBD
+:101D800000A2182B106000078F850050240DFF80E3
+:101D900090AE000D01AE6024318B00FF156000088D
+:101DA0000006C382020020212403000D8FBF00140F
+:101DB0008FB0001027BD00180A001A4AA3830068DC
+:101DC00033060003240F000254CFFFF70200202146
+:101DD00094A2001C8F85003824190023A4A200E8D7
+:101DE0008CE8000000081E02307F003F13F9003528
+:101DF0003C0A00838CE800188CA600D0110600086D
+:101E0000000000002405000E0E001A4AA385006899
+:101E10002407FFFF104700182404FFFF8F850038B8
+:101E200090A900D435240020A0A400D48F8C0044B5
+:101E3000918E000D31CD007FA18D000D8F83005458
+:101E40001060001C020020218F8400508C9800102C
+:101E50000303782B11E0000D241900180200202143
+:101E6000A39900680E001A4A2410FFFF10500002C8
+:101E70002404FFFF000020218FBF00148FB000104A
+:101E80000080102103E0000827BD00188C86001098
+:101E90008F9F00440200202100C31023AFE20010F6
+:101EA000240500010E0019A9240600010A001B9751
+:101EB000000020210E001934240500010A001B97A0
+:101EC00000002021010A5824156AFFD98F8C004494
+:101ED000A0A600FC0A001B84A386005A30A500FFC0
+:101EE0002406000124A9000100C9102B1040000C99
+:101EF00000004021240A000100A61823308B0001B5
+:101F000024C60001006A3804000420421160000267
+:101F100000C9182B010740251460FFF800A61823FC
+:101F200003E000080100102127BDFFD8AFB0001862
+:101F30008F90004CAFB1001CAFBF00202403FFFF07
+:101F40002411002FAFA30010920600002405000802
+:101F500026100001006620260E001BB0308400FF12
+:101F600000021E003C021EDC34466F410A001BD8F2
+:101F70000000102110A00009008018212445000154
+:101F800030A2FFFF2C4500080461FFFA0003204047
+:101F90000086202614A0FFF9008018210E001BB037
+:101FA000240500208FA300102629FFFF313100FFF8
+:101FB00000034202240700FF1627FFE20102182651
+:101FC00000035027AFAA0014AFAA00100000302170
+:101FD00027A8001027A7001400E6782391ED00033E
+:101FE00024CE000100C8602131C600FF2CCB0004C4
+:101FF0001560FFF9A18D00008FA200108FBF002097
+:102000008FB1001C8FB0001803E0000827BD002826
+:1020100027BDFFD0AFB3001CAFB00010AFBF00288A
+:10202000AFB50024AFB40020AFB20018AFB10014B8
+:102030003C0C80008D880128240FFF803C06800A1C
+:1020400025100100250B0080020F68243205007F57
+:10205000016F7024AD8E009000A62821AD8D002464
+:1020600090A600FC3169007F3C0A8004012A1821F7
+:10207000A386005A9067007C00809821AF830030CF
+:1020800030E20002AF88006CAF85003800A0182154
+:10209000144000022404003424040030A3840048C7
+:1020A0008C7200DC30D100FF24040004AF92006089
+:1020B00012240004A38000688E7400041680001EA1
+:1020C0003C0880009386005930C7000150E0000FA3
+:1020D0008F8600608CA400848CA800842413FF8069
+:1020E00000936024000C49403110007F01307825B6
+:1020F0003C19200001F9682530DF00FE3C03800018
+:10210000AC6D0830A39F00598F8600608FBF0028F8
+:102110008FB500248FB400208FB3001C8FB200183D
+:102120008FB100148FB000102402000127BD0030D1
+:1021300003E00008ACA600DC8E7F000895020120B9
+:102140008E67001003E2C8213326FFFF30D8000F4E
+:1021500033150001AF87003416A00058A39800582B
+:1021600035090C000309382100D81823AD03008479
+:10217000AF8700648E6A00043148FFFF1100007EC3
+:10218000A78A005C90AC00D42407FF8000EC3024C8
+:1021900030CB00FF1560004B9786005C938E005A91
+:1021A000240D000230D5FFFF11CD02A20000A021B6
+:1021B0008F85006002A5802B160000BC9388004824
+:1021C0003C11800096240120310400FF1485008812
+:1021D0008F8400648F9800343312000356400085CA
+:1021E00030A500FF8F900064310C00FF24060034FE
+:1021F00011860095AF90004C9204000414800119E0
+:102200008F8E0038A380003C8E0D00048DC800D84E
+:102210003C0600FF34CCFFFF01AC30240106182B34
+:1022200014600121AF8600548F8700609798005C8E
+:10223000AF8700400307402310C000C7A788005C99
+:102240008F91003030C3000300035823922A007C92
+:102250003171000302261021000A20823092000111
+:102260000012488000492821311FFFFF03E5C82BD9
+:10227000132001208F8800388F8500348F880064F8
+:102280001105025A3C0E3F018E0600003C0C250051
+:1022900000CE682411AC01638F84004C30E500FF50
+:1022A0000E00184A000030218F8800388F870060A8
+:1022B0008F8500340A001DB78F8600540A001C5613
+:1022C000AF87006490AC00D400EC2024309000FF75
+:1022D000120000169386005990B5008890B400D77C
+:1022E00024A8008832A2003F2446FFE02CD1002021
+:1022F000A394003C1220000CAF88004C240E000177
+:1023000000CE2004308A00191540012B3C068000C5
+:1023100034D80002009858241560022E3092002014
+:1023200016400234000000009386005930CE0001B0
+:1023300011C0000F9788005C8CA900848CAF0084CA
+:102340002410FF800130C8240019194031ED007FAE
+:10235000006D38253C1F200000FF902530CB00FE8B
+:102360003C188000AF120830A38B00599788005C9E
+:102370001500FF84000000008E630020306C000414
+:102380001180FF51938600592404FFFB0064302420
+:102390003C038000AE660020346601808C7301B877
+:1023A0000660FFFE8F8E006C346A01003C15000150
+:1023B000ACCE00008C62012424076085ACC200040E
+:1023C0008D54000402958824522000012407608364
+:1023D000241200023C1810003C0B8000A4C7000827
+:1023E000A0D2000BAD7801B80A001C2B93860059CF
+:1023F00030A500FF0E00184A240600018F88006CEB
+:102400003C05800034A90900250201889388004812
+:10241000304A0007304B00783C0340802407FF809F
+:102420000163C825014980210047F824310C00FFD1
+:1024300024060034ACBF0800AF90004CACB90810C3
+:102440005586FF6E920400048F8400388E11003090
+:10245000908E00D431CD001015A000108F83006045
+:102460002C6F000515E000E400000000909800D4F7
+:102470002465FFFC331200101640000830A400FF52
+:102480008F9F00648F99003413F90004388700018E
+:1024900030E20001144001C8000000000E001BC320
+:1024A000000000000A001DF8000000008F84006496
+:1024B00030C500FF0E00184A24060001938E004824
+:1024C000240A003411CA00A08F8500388F8600606E
+:1024D0009783005C3062FFFF00C28823AF910060E9
+:1024E000A780005C1280FF90028018212414FFFD59
+:1024F0005474FFA28E6300208E6900042403FFBF82
+:10250000240BFFEF0135C823AE79000490AF00D44F
+:1025100031ED007FA0AD00D48E6600208F9800388A
+:10252000A780005C34DF0002AE7F0020A70000BC63
+:10253000931200D402434024A30800D48F9500389E
+:10254000AEA000EC92AE00D401CB5024A2AA00D4DD
+:102550000A001CD78F8500388F910034AF8000604F
+:1025600002275821AF8B0034000020212403FFFFF5
+:10257000108301B48F8500388E0C00103C0D0800CC
+:102580008DAD31B09208000031843FFF008D802B6B
+:1025900012000023310D003F3C1908008F3931A88B
+:1025A0008F9F006C000479802408FF80033F202166
+:1025B000008FC821938500590328F8243C06008029
+:1025C0003C0F800034D80001001F91403331007F60
+:1025D0008F8600380251502535EE0940332B0078A4
+:1025E000333000073C0310003C02800C017890253A
+:1025F000020E48210143C0250222382134AE0001D9
+:10260000ADFF0804AF890050ADF20814AF87004455
+:10261000ADFF0028ACD90084ADF80830A38E005976
+:102620009383005A240700035067002825A3FFE086
+:10263000240C0001146CFFAB8F850038241100239B
+:1026400011B10084000000002402000B0260202170
+:102650000E001A4AA38200680040A0210A001D3221
+:102660008F85003802602021240B000C0E001A4ACE
+:10267000A38B0068240AFFFF104AFFBC2404FFFF5D
+:102680008F8E0038A380003C8E0D00048DC800D8CA
+:102690003C0600FF34CCFFFF01AC30240106182BB0
+:1026A0001060FEE1AF860054026020212412001960
+:1026B0000E001A4AA3920068240FFFFF104FFFABD1
+:1026C0002404FFFF0A001C838F8600542C74002012
+:1026D0001280FFDE2402000B000328803C11080159
+:1026E0002631949000B148218D2D000001A00008F2
+:1026F000000000008F85003400A710219385003C66
+:10270000AF82003402251821A383003C951F00BC32
+:102710000226282137F91000A51900BC5240FF926B
+:10272000AF850060246A0004A38A003C950900BCC0
+:1027300024A40004AF84006035322000A51200BC40
+:102740000A001D54000020218F8600602CCB00055C
+:102750001560FF609783005C3072FFFF00D240235A
+:102760002D18000513000003306400FF24DFFFFC78
+:1027700033E400FF8F8500648F86003410A60004C8
+:10278000388F000131ED000115A001380000000074
+:102790008F840038908C00D435870010A08700D437
+:1027A0008F8500388F8600609783005CACA000ECBA
+:1027B0000A001D2F3062FFFF8CAA00848CB50084B4
+:1027C0003C041000014710240002894032B4007F0D
+:1027D0000234302500C460253C0880002405000137
+:1027E00002602021240600010E0019A9AD0C08305A
+:1027F0000A001CC38F8500388C8200EC1222FE7EFA
+:102800000260202124090005A38900680E001A4AED
+:102810002411FFFF1451FE782404FFFF0A001D5508
+:102820002403FFFF8F8F004C8F8800388DF8000045
+:10283000AD1800888DE70010AD0700988F87006005
+:102840000A001DB78F8600542407FFFF118700057B
+:10285000000000000E001B4C026020210A001D90A9
+:102860000040A0210E001AD1026020210A001D9014
+:102870000040A0218F90004C3C0908008D2931B008
+:102880008E11001032323FFF0249682B11A0000C5C
+:10289000240AFF808F85005090AE000D014E102459
+:1028A000304C00FF11800007026020210011C3821C
+:1028B00033030003240B0001106B0105000000002E
+:1028C000026020212418000D0E001A4AA398006807
+:1028D000004020218F8500380A001D320080A02191
+:1028E0008F90004C3C0A08008D4A31B08F85005013
+:1028F0008E0400100000A0218CB1001430823FFF34
+:10290000004A602B8CB200205180FFEE0260202133
+:1029100090B8000D240BFF800178702431C300FFB4
+:102920005060FFE80260202100044382310600036A
+:1029300014C0FFE40260202194BF001C8F9900386E
+:102940008E060028A73F00E88CAF0010022F20233E
+:1029500014C40139026020218F83005400C3682110
+:10296000022D382B14E00135240200188F8A004410
+:102970008F820030024390218D4B00100163702341
+:10298000AD4E0010AD5200208C4C00740192282BEB
+:1029900014A00156026020218F8400508E0800246C
+:1029A0008C86002411060007026020212419001CD7
+:1029B0000E001A4AA3990068240FFFFF104FFFC5AD
+:1029C0002404FFFF8F8400448C87002424FF00012F
+:1029D000AC9F0024125101338F8D00308DB10074F3
+:1029E000123201303C0B00808E0E000001CB5024CF
+:1029F00015400075000000008E0300142411FFFF35
+:102A000010710006026020212418001B0E001A4AD3
+:102A1000A39800681051FFAF2404FFFF8E0300004D
+:102A20003C0800010068302410C000133C04008002
+:102A30000064A024168000090200282102602021E1
+:102A40002419001A0E001A4AA3990068240FFFFFE8
+:102A5000104FFFA02404FFFF020028210260202164
+:102A60000E001A6A240600012410FFFF1050FF997F
+:102A70002404FFFF241400018F9F004402602021E2
+:102A80000280302197F1003424050001262700013F
+:102A9000A7E700340E0019A9000000000000202163
+:102AA0008F8500380A001D320080A0218F90004CD5
+:102AB0003C1408008E9431B08E07001030E83FFFC0
+:102AC0000114302B10C000618F860050241FFF803E
+:102AD00090C5000D03E52024309200FF5240005CB9
+:102AE000026020218F8D005411A0000700078B8207
+:102AF0008F8500388F89FCBC94AF00809539000A1F
+:102B0000132F00F68F870040322C000315800063DE
+:102B10000000000092020002104000D700000000F8
+:102B20008E0A0024154000D8026020219204000380
+:102B300024060002308800FF15060005308500FFDE
+:102B40008F940054528000F202602021308500FFF3
+:102B500038AD00102DA400012CBF000103E4302586
+:102B6000020028210E001A6A026020212410FFFFB3
+:102B7000105000BE8F8500388F830054106000C451
+:102B8000240500013C1908008F39318C0323782B70
+:102B900015E000B12409002D026020210000282149
+:102BA0000E0019A9240600018F85003800001821A5
+:102BB0000A001D320060A0210E0018750000000000
+:102BC0000A001DF800000000AC8000200A001E78FA
+:102BD0008E03001400002821026020210E0019A994
+:102BE000240600010A001CC38F8500380A001DB7A7
+:102BF0008F8800388CB000848CB900843C031000AE
+:102C00000207482400096940332F007F01AFF825EF
+:102C100003E32825ACC50830910700012405000115
+:102C2000026020210E0019A930E600010A001CC331
+:102C30008F850038938F00482403FFFD0A001D3460
+:102C4000AF8F00600A001D342403FFFF02602021C3
+:102C50002410000D0E001A4AA390006800401821AD
+:102C60008F8500380A001D320060A0210E00187503
+:102C7000000000009783005C8F8600603070FFFFCB
+:102C800000D048232D3900051320FE128F8500380F
+:102C9000ACA200EC0A001D2F3062FFFF90C3000DB4
+:102CA000307800085700FFA2920400030260202140
+:102CB000240200100E001A4AA38200682403FFFFBA
+:102CC0005443FF9B920400030A001F128F850038B3
+:102CD00090A8000D3106000810C000958F94005494
+:102CE0001680009E026020218E0F000C8CA4002014
+:102CF00055E40005026020218E1F00088CB90024D5
+:102D000013F9003A02602021240200200E001A4A22
+:102D1000A38200682405FFFF1045FEEE2404FFFF98
+:102D20008F8F0044240CFFF72403FF8091E9000DEE
+:102D30003C14800E3C0B8000012CC824A1F9000D2E
+:102D40008F8F00303C0708008CE731AC8F8D006C12
+:102D500095E500788F99004400ED902130BF7FFF0A
+:102D6000001F20400244302130C8007F00C3C0242F
+:102D700001147021AD78002CA5D100008F2A002805
+:102D800025420001AF2200288F29002C8E0C002C38
+:102D9000012C6821AF2D002C8E07002CAF270030AE
+:102DA0008E050014AF250034973F003A27E4000158
+:102DB000A724003A95F200783C1008008E1031B03C
+:102DC0002643000130717FFF1230005C006030212B
+:102DD0008F83003002602021240500010E00193489
+:102DE000A46600780A001EA1000020218E070014AE
+:102DF0002412FFFF10F200638F8C00388E09001838
+:102E00008D8D00D0152D005D026020218E0A0024DA
+:102E10008CA2002811420053240200210E001A4AFD
+:102E2000A38200681452FFBE2404FFFF8F85003880
+:102E30000A001D320080A0212402001F0E001A4A41
+:102E4000A38200682409FFFF1049FEA22404FFFFAB
+:102E50000A001E548F830054026020210E001A4A7B
+:102E6000A38900681450FF518F8500382403FFFFA9
+:102E70000A001D320060A0218CCE00248E0B00249D
+:102E8000116EFF2A026020210A001F262402000F73
+:102E90000E001934026020218F8500380A001EE5DB
+:102EA000000018218E0900003C05008001259024B7
+:102EB0001640FF452402001A026020210E001A4A23
+:102EC000A3820068240CFFFF144CFECB2404FFFFF8
+:102ED0008F8500380A001D320080A0212403FFFDE9
+:102EE0000060A0210A001D32AF8700602418001D79
+:102EF0000E001A4AA39800682403FFFF1443FEA69D
+:102F00002404FFFF8F8500380A001D320080A021B5
+:102F10002412002C0E001A4AA39200682403FFFF1B
+:102F20001043FF508F8500380A001ECC9204000326
+:102F3000026020210A001F3C24020024240B800090
+:102F4000006B702431CAFFFF000A13C2305100FF2A
+:102F5000001180270A001F6D001033C00A001F3CBB
+:102F6000240200278E0600288CAE002C10CE00080C
+:102F7000026020210A001F802402001F0A001F8017
+:102F80002402000E026020210A001F802402002576
+:102F90008E04002C1080000D8F8300308C7800741C
+:102FA0000304582B5560000C026020218CA80014EB
+:102FB0000086A0210114302B10C0FF5A8F8F0044CF
+:102FC000026020210A001F802402002202602021CA
+:102FD0000A001F80240200230A001F80240200260A
+:102FE00027BDFFD8AFB3001CAFB10014AFBF0020A6
+:102FF000AFB20018AFB000103C0280008C5201400C
+:103000008C4B01483C048000000B8C02322300FFF3
+:10301000317300FF8C8501B804A0FFFE349001805D
+:10302000AE1200008C8701442464FFF024060002E5
+:103030002C830013AE070004A6110008A206000BA3
+:10304000AE1300241060004F8FBF002000044880A2
+:103050003C0A0801254A9510012A40218D040000F0
+:1030600000800008000000003C0308008C6331A8C9
+:1030700031693FFF0009998000728021021370219D
+:103080002405FF80264D0100264C00803C02800074
+:1030900031B1007F3198007F31CA007F3C1F800A28
+:1030A0003C1980043C0F800C01C5202401A530246C
+:1030B00001853824014F1821AC460024023F4021ED
+:1030C00003194821AC470090AC440028AF8300446A
+:1030D000AF880038AF8900300E00190001608021F0
+:1030E0003C0380008C6B01B80560FFFE8F870044B5
+:1030F0008F8600383465018090E8000DACB2000086
+:10310000A4B0000600082600000416030002902761
+:10311000001227C21080008124C20088241F608210
+:10312000A4BF0008A0A0000524020002A0A2000B7A
+:103130008F8B0030000424003C0827000088902575
+:10314000ACB20010ACA00014ACA00024ACA00028CD
+:10315000ACA0002C8D6900382413FF80ACA90018A6
+:1031600090E3000D02638024320500FF10A00005EB
+:103170008FBF002090ED000D31AC007FA0EC000D62
+:103180008FBF00208FB3001C8FB200188FB10014C6
+:103190008FB000103C0A10003C0E800027BD0028B4
+:1031A00003E00008ADCA01B8265F01002405FF80D6
+:1031B00033F8007F3C06800003E578243C19800A40
+:1031C00003192021ACCF0024908E00D400AE6824D7
+:1031D00031AC00FF11800024AF840038248E0088B9
+:1031E00095CD00123C0C08008D8C31A831AB3FFF0F
+:1031F00001924821000B5180012A40210105202421
+:10320000ACC400283107007F3C06800C00E620217A
+:103210009083000D00A31024304500FF10A0FFD8BC
+:10322000AF8400449098000D330F001015E0FFD5D7
+:103230008FBF00200E001900000000003C0380003A
+:103240008C7901B80720FFFE00000000AE120000DC
+:103250008C7F0144AE1F0004A61100082411000257
+:10326000A211000BAE1300243C130801927396D0F8
+:10327000327000015200FFC38FBF00200E00213DBD
+:10328000024020210A00205A8FBF00203C1260001B
+:103290008E452C083C03F0033462FFFF00A2F824A3
+:1032A000AE5F2C088E582C083C1901C003199825D4
+:1032B000AE532C080A00205A8FBF0020264D010073
+:1032C00031AF007F3C10800A240EFF8001F02821DE
+:1032D00001AE60243C0B8000AD6C00241660FFA89A
+:1032E000AF85003824110003A0B100FC0A00205A69
+:1032F0008FBF002026480100310A007F3C0B800A66
+:103300002409FF80014B3021010920243C07800063
+:10331000ACE400240A002059AF860038944E001215
+:10332000320C3FFF31CD3FFF15ACFF7D241F608283
+:1033300090D900D42418FF800319782431EA00FFC3
+:103340001140FF770000000024070004A0C700FC24
+:103350008F870044241160842406000DA4B1000866
+:10336000A0A600050A002044240200023C0400013B
+:10337000248496BC24030014240200FE3C010800AF
+:10338000AC2431EC3C010800AC2331E83C010801DD
+:10339000A42296D83C040801248496D80000182161
+:1033A00000643021A0C30004246300012C6500FFE9
+:1033B00054A0FFFC006430213C07080024E7010012
+:1033C00003E00008AF87007800A058210080482162
+:1033D0000000102114A00012000050210A00213921
+:1033E000000000003C010801A42096D83C0508011B
+:1033F00094A596D88F8200783C0C0801258C96D82D
+:1034000000E2182100AC2021014B302BA0890004E0
+:1034100000001021A460000810C0003901004821FC
+:103420008F8600780009384000E940210008388084
+:1034300000E6282190A8000B90B9000A000820405F
+:1034400000881021000218800066C021A319000A1C
+:103450008F85007800E5782191EE000A91E6000B57
+:10346000000E684001AE6021000C20800085102114
+:10347000A046000B3C030801906396D21060002226
+:103480002462FFFF8F8300383C010801A02296D2FE
+:10349000906C00FF1180000400000000906E00FF9F
+:1034A00025CDFFFFA06D00FF3C190801973996D884
+:1034B000272300013078FFFF2F0F00FF11E0FFC925
+:1034C000254A00013C010801A42396D83C050801C7
+:1034D00094A596D88F8200783C0C0801258C96D84C
+:1034E00000E2182100AC2021014B302BA089000400
+:1034F00000001021A460000814C0FFC90100482189
+:1035000003E000080000000003E0000824020002BD
+:1035100027BDFFE0248501002407FF80AFB0001025
+:10352000AFBF0018AFB1001400A718243C108000F2
+:1035300030A4007F3C06800A008628218E110024DA
+:10354000AE03002490A200FF14400008AF850038AD
+:10355000A0A000098FBF0018AE1100248FB1001485
+:103560008FB0001003E0000827BD002090A900FDE7
+:1035700090A800FF312400FF0E0020EB310500FF72
+:103580008F8500388FBF0018A0A00009AE1100245D
+:103590008FB100148FB0001003E0000827BD002099
+:1035A00027BDFFD0AFB20020AFB1001CAFB00018F4
+:1035B000AFBF002CAFB40028AFB300243C0980009B
+:1035C0009533011635320C00952F011A3271FFFF29
+:1035D000023280218E08000431EEFFFF248B0100AF
+:1035E000010E6821240CFF8025A5FFFF016C5024EB
+:1035F0003166007F3C07800AAD2A002400C73021D5
+:10360000AF850074AF8800703C010801A02096D1FE
+:1036100090C300090200D02100809821306300FF90
+:103620002862000510400048AF8600382864000278
+:103630001480008E24140001240D00053C010801B3
+:10364000A02D96B590CC00FD3C010801A02096B6B7
+:103650003C010801A02096B790CB000A240AFF8005
+:10366000318500FF014B4824312700FF10E0000C9A
+:10367000000058213C128008365100808E2F003007
+:103680008CD0005C01F0702305C0018E8F87007024
+:1036900090D4000A3284007FA0C4000A8F860038CC
+:1036A0003C118008363000808E0F00308F8700700C
+:1036B00000EF702319C000EE0000000090D4000954
+:1036C00024120002328400FF109202470000000022
+:1036D0008CC2005800E2F82327F9FFFF1B200130BD
+:1036E0000000000090C500092408000430A300FF7A
+:1036F00010680057240A00013C010801A02A96B571
+:1037000090C900FF252700013C010801A02796B4BD
+:103710003C030801906396B5240600051066006A14
+:103720002C780005130000C4000090210003F880ED
+:103730003C0408012484955C03E4C8218F25000023
+:1037400000A0000800000000241800FF1078005CB2
+:103750000000000090CC000A90CA00093C08080153
+:10376000910896D13187008000EA48253C01080184
+:10377000A02996BC90C500FD3C140801929496D2F5
+:10378000311100013C010801A02596BD90DF00FE2B
+:103790003C010801A03F96BE90D200FF3C01080109
+:1037A000A03296BF8CD900543C010801AC3996C0B8
+:1037B0008CD000583C010801AC3096C48CC3005C2E
+:1037C0003C010801AC3496CC3C010801AC2396C8FE
+:1037D000162000088FBF002C8FB400288FB3002460
+:1037E0008FB200208FB1001C8FB0001803E00008DA
+:1037F00027BD00303C1180009624010E0E000FD42E
+:103800003094FFFF3C0B08018D6B96D40260382189
+:1038100002802821AE2B01803C1308018E7396B4E0
+:1038200001602021240600830E00102FAFB300108A
+:103830008FBF002C8FB400288FB300248FB20020DC
+:103840008FB1001C8FB0001803E0000827BD0030C6
+:103850003C1808008F1831FC270F00013C010800BC
+:10386000AC2F31FC0A0021CE000000001474FFB917
+:1038700000000000A0C000FF3C0508008CA531E45A
+:103880003C0308008C6331E03C0208008C423204A7
+:103890008F99003834A80001241F00023C01080160
+:1038A000AC2396D43C010801A02896D03C01080125
+:1038B000A02296D3A33F00090A0021878F860038F3
+:1038C0000E00213D000000000A0021CE8F86003846
+:1038D0003C1F080193FF96B42419000113F9022933
+:1038E0008F8700703C100801921096B83C060801C2
+:1038F00090C696B610C000050200A0213C04080145
+:10390000908496B9109001E48F8700780010884069
+:103910008F9F0078023048210009C880033F702142
+:1039200095D80008270F0001A5CF00083C04080126
+:10393000908496B93C05080190A596B60E0020EB40
+:10394000000000008F8700780230202100043080C2
+:1039500000C720218C8500048F82007400A24023C0
+:1039600005020006AC8200048C8A00008F83007080
+:10397000014310235C400001AC8300008F860038B7
+:1039800090CB00FF2D6C00025580002D2414000107
+:103990000230F821001F40800107282190B9000B58
+:1039A0008CAE00040019C04003197821000F188064
+:1039B000006710218C4D000001AE88232630FFFFE8
+:1039C0005E00001F241400018C4400048CAA000037
+:1039D000008A482319200019240E00043C01080124
+:1039E000A02E96B590AD000B8CAB0004000D884066
+:1039F000022D802100101080004710218C4400040B
+:103A000001646023058202009443000890DF00FEF9
+:103A100090B9000B33E500FF54B900040107A02161
+:103A2000A0D400FE8F8700780107A0219284000BAC
+:103A30000E0020EB240500018F86003824140001BD
+:103A4000125400962E500001160000423C08FFFF61
+:103A5000241900021659FF3F00000000A0C000FF1B
+:103A60008F860038A0D200090A0021CE8F86003848
+:103A700090C700092404000230E300FF1064016FC6
+:103A800024090004106901528F8800748CCE005400
+:103A9000010E682325B100010620017524180004D9
+:103AA0003C010801A03896B53C010801A02096B45D
+:103AB00090D400FD90D200FF2E4F000215E0FF14BD
+:103AC000328400FF000438408F89007890DF00FFC7
+:103AD00000E41021000220800089C8212FE50002A7
+:103AE0009324000B14A0FF0A2407000200041840CE
+:103AF0000064802100105880016928218CAC0004EA
+:103B0000010C50230540FF02000000003C030801A7
+:103B1000906396B614600005246F00013C01080113
+:103B2000A02496B93C010801A02796B73C010801E2
+:103B3000A02F96B690CE00FF24E7000131CD00FF04
+:103B400001A7882B1220FFE990A4000B0A0021BDD9
+:103B5000000000003C0508018CA596B43C1200044E
+:103B600000A8F82413F20006240200053C0908010D
+:103B7000912996B5152000022402000324020005B5
+:103B80003C010801A02296D190C700FF14E001205B
+:103B900024020002A0C200090A0021CE8F8600384C
+:103BA00090CC00FF1180FEDA240A00018F8C007493
+:103BB0008F890078240F0003018068211160001EA6
+:103BC000240E0002000540400105A02100142080C1
+:103BD000008990218E510004019180230600FECCC3
+:103BE000000000003C020801904296B61440000517
+:103BF000245800013C010801A02A96B73C010801A5
+:103C0000A02596B93C010801A03896B690DF00FFC8
+:103C1000010510210002C88033E500FF254A00019C
+:103C20000329202100AA402B1500FEB99085000B26
+:103C30001560FFE5000540400005404001051821E2
+:103C4000000310803C010801A02A96B43C01080141
+:103C5000A02596B8004918218C64000400E4F823DC
+:103C600027F9FFFF1F20FFE9000000008C63000020
+:103C700000E358230560013A01A3882310E30117EC
+:103C80000184C0231B00FEA2000000003C010801CB
+:103C9000A02E96B50A0022FC240B0001240E00047D
+:103CA000A0CE00093C0D08008DAD31F88F8600389C
+:103CB00025A200013C010800AC2231F80A0021CE07
+:103CC000000000008CD9005C00F9C0231F00FE7BBF
+:103CD000000000008CDF005C10FFFF658F84007423
+:103CE0008CC3005C00834023250200011C40FF6060
+:103CF000000000008CC9005C2487000100E9282B2B
+:103D000010A0FE943C0D80008DAB01043C0C000122
+:103D1000016C50241140FE8F240200103C01080168
+:103D2000A02296D10A0021CE000000008F910074DD
+:103D30008F86003826220001ACC2005C0A0022896E
+:103D4000241400018F8700382404FF80000088219C
+:103D500090E9000A2414000101243025A0E6000A9D
+:103D60003C05080190A596B63C040801908496B9DC
+:103D70000E0020EB000000008F8600388F85007851
+:103D800090C800FD310700FF000740400107F821FF
+:103D9000001FC0800305C8219323000BA0C300FDB2
+:103DA0008F8500788F86003803056021918F000B86
+:103DB000000F704001CF6821000D808002051021A6
+:103DC0008C4B0000ACCB00548D8400048F830074B6
+:103DD0000064502319400002248200012462000183
+:103DE00001074821ACC2005C0009308000C54021B9
+:103DF00000E02021240500010E0020EB9110000BB3
+:103E00008F86003890C500FF10A0FF0C0010704096
+:103E10008F85007801D06821000D10800045582161
+:103E20008D6400008F8C00740184502325470001AD
+:103E300004E0FF02263100013C030801906396B6BE
+:103E40002E2F0002247800013C010801A03896B60C
+:103E50003C010801A03496B711E0FEF802003821B9
+:103E60000A00235C000740408F8400388F83007471
+:103E70008C85005800A340230502FE9AAC830058AD
+:103E80000A002232000000003C07080190E796D2A9
+:103E9000240200FF10E200BE8F8600383C110801AA
+:103EA000963196DA3C030801246396D82625000152
+:103EB0003230FFFF30ABFFFF020360212D6A00FFAD
+:103EC0001540008D918700043C010801A42096DA7A
+:103ED0008F8800380007484001272821911800FFEB
+:103EE000000530802405000127140001A11400FF03
+:103EF0003C120801925296D28F8800788F8E007003
+:103F0000264F000100C820213C010801A02F96D2B5
+:103F1000AC8E00008F8D0074A4850008AC8D000469
+:103F20003C030801906396B4146000770000902170
+:103F30003C010801A02596B4A087000B8F8C007867
+:103F400000CC5021A147000A8F820038A04700FD15
+:103F50008F840038A08700FE8F8600388F9F007006
+:103F6000ACDF00548F990074ACD900588F8D007865
+:103F70000127C02100185880016DA021928F000AEE
+:103F8000000F704001CF182100038880022D80218E
+:103F9000A207000B8F86007801666021918A000BD2
+:103FA000000A1040004A20210004288000A6402179
+:103FB000A107000A3C07800834E900808D22003008
+:103FC0008F860038ACC2005C0A00228924140001EC
+:103FD00090CA00FF1540FEAD8F880074A0C4000990
+:103FE0000A0021CE8F860038A0C000FD8F980038CF
+:103FF00024060001A30000FE3C010801A02696B59E
+:104000003C010801A02096B40A0021BD0000000078
+:1040100090CB00FF3C040801908496D3316C00FFE4
+:104020000184502B1540000F2402000324020004D9
+:10403000A0C200090A0021CE8F86003890C3000A72
+:104040002410FF8002035824316C00FF1180FDC151
+:10405000000000003C010801A02096B50A0021BD27
+:1040600000000000A0C200090A0021CE8F8600389F
+:1040700090D4000A2412FF8002544824312800FF03
+:104080001500FFF4240200083C010801A02296D18B
+:104090000A0021CE00000000001088408F8B0070C5
+:1040A000023018210003688001A72021AC8B00009A
+:1040B0008F8A0074240C0001A48C0008AC8A0004D0
+:1040C0003C05080190A596B62402000110A2FE1E30
+:1040D00024A5FFFF0A0022489084000B0184A0233E
+:1040E0001A80FD8B000000003C010801A02E96B54F
+:1040F0000A0022FC240B00013C010801A42596DAE9
+:104100000A0023AE8F880038240B0001106B0022B8
+:104110008F9800388F85003890BF00FF33F900FF7B
+:104120001079002B000000003C1F080193FF96B897
+:10413000001FC840033FC0210018A08002887821DA
+:1041400091EE000AA08E000A8F8D00783C030801D2
+:10415000906396B800CD88210A0023D4A223000BD7
+:10416000263000010600003101A490230640002BF8
+:10417000240200033C010801A02F96B50A0022FC8E
+:10418000240B00018F8900380A002232AD27005429
+:104190000A00228824120001931400FDA094000B51
+:1041A0008F8800388F8F0078910E00FE00CF682135
+:1041B000A1AE000A8F910038A22700FD8F83007006
+:1041C0008F900038AE0300540A0023D58F8D0078FD
+:1041D00090B000FEA090000A8F8B00388F8C007882
+:1041E000916A00FD00CC1021A04A000B8F8400389A
+:1041F000A08700FE8F8600748F850038ACA600581B
+:104200000A0023D58F8D007894B80008ACA4000470
+:10421000030378210A00227CA4AF00083C010801B6
+:10422000A02296B50A0021BD0000000090CF000931
+:10423000240D000431EE00FF11CDFD8524020001A4
+:104240003C010801A02296B50A0021BD0000000033
+:10425000080033440800334408003420080033F4D5
+:10426000080033D808003328080033280800332812
+:104270000800334C8008010080080080800800009E
+:104280005F865437E4AC62CC50103A4536621985EB
+:10429000BF14C0E81BC27A1E84F4B556094EA6FEB0
+:1042A0007DDA01E7C04D748108005A7408005AB8DD
+:1042B00008005A5C08005A5C08005A5C08005A5C06
+:1042C00008005A7408005A5C08005A5C08005AC07A
+:1042D00008005A5C080059D408005A5C08005A5C6F
+:1042E00008005AC008005A5C08005A5C08005A5C72
+:1042F00008005A5C08005A5C08005A5C08005A5CC6
+:1043000008005A5C08005A5C08005A5C08005A947D
+:1043100008005A5C08005A9408005A5C08005A5C6D
+:1043200008005A5C08005A9808005A9408005A5C21
+:1043300008005A5C08005A5C08005A5C08005A5C85
+:1043400008005A5C08005A5C08005A5C08005A5C75
+:1043500008005A5C08005A5C08005A5C08005A5C65
+:1043600008005A5C08005A5C08005A5C08005A5C55
+:1043700008005A5C08005A5C08005A5C08005A9809
+:1043800008005A9808005A5C08005A9808005A5CBD
+:1043900008005A5C08005A5C08005A5C08005A5C25
+:1043A00008005A5C08005A5C08005A5C08005A5C15
+:1043B00008005A5C08005A5C08005A5C08005A5C05
+:1043C00008005A5C08005A5C08005A5C08005A5CF5
+:1043D00008005A5C08005A5C08005A5C08005A5CE5
+:1043E00008005A5C08005A5C08005A5C08005A5CD5
+:1043F00008005A5C08005A5C08005A5C08005A5CC5
+:1044000008005A5C08005A5C08005A5C08005A5CB4
+:1044100008005A5C08005A5C08005A5C08005A5CA4
+:1044200008005A5C08005A5C08005A5C08005A5C94
+:1044300008005A5C08005A5C08005A5C08005A5C84
+:1044400008005A5C08005A5C08005A5C08005A5C74
+:1044500008005A5C08005A5C08005A5C08005A5C64
+:1044600008005A5C08005A5C08005A5C08005A5C54
+:1044700008005A5C08005A5C08005A5C08005A5C44
+:1044800008005A5C08005A5C08005A5C08005A5C34
+:1044900008005A5C08005A5C08005A5C08005A5C24
+:1044A00008005A5C08005A5C08005ADC0800782CA6
+:1044B00008007A90080078380800762C08007838D0
+:1044C000080078C4080078380800762C0800762C9C
+:1044D0000800762C0800762C0800762C0800762C34
+:1044E0000800762C0800762C0800762C0800762C24
+:1044F00008007858080078480800762C0800762CC8
+:104500000800762C0800762C0800762C0800762C03
+:104510000800762C0800762C0800762C0800762CF3
+:104520000800762C0800762C08007848080082D80D
+:1045300008008164080082A008008164080082707D
+:104540000800804C080081640800816408008164D0
+:1045500008008164080081640800816408008164A7
+:104560000800816408008164080081640800816497
+:10457000080081640800818C08008D1008008E6C92
+:0C45800008008E4C080088B408008D284C
+:04458C000A000124FC
+:1045900000000000000000000000000D7470613693
+:1045A0002E322E31610000000602010100000000E1
+:1045B00000000000000000000000000000000000FB
+:1045C00000000000000000000000000000000000EB
+:1045D00000000000000000000000000000000000DB
+:1045E00000000000000000000000000000000000CB
+:1045F00000000000000000000000000000000000BB
+:1046000000000000000000000000000000000000AA
+:10461000000000000000000000000000000000009A
+:1046200010000003000000000000000D0000000D5D
+:104630003C020800244217203C03080024632A108F
+:10464000AC4000000043202B1480FFFD24420004F6
+:104650003C1D080037BD2FFC03A0F0213C100800D2
+:10466000261004903C1C0800279C17200E000262B4
+:10467000000000000000000D2402FF8027BDFFE0C5
+:1046800000821024AFB00010AF420020AFBF00186E
+:10469000AFB10014936500043084007F03441821F7
+:1046A0003C0200080062182130A500200360802130
+:1046B0003C080111277B000814A000022466005C5E
+:1046C00024660058920200049743010492040004F7
+:1046D0003047000F3063FFFF30840040006728231D
+:1046E00010800009000048219202000530420004B9
+:1046F000104000050000000010A0000300000000B2
+:1047000024A5FFFC240900049202000530420004A5
+:10471000104000120000000010A000100000000077
+:104720009602000200A72021010440252442FFFE3A
+:10473000A7421016920300042402FF8000431024B5
+:10474000304200FF104000033C0204000A000174E4
+:10475000010240258CC20000AF4210188F42017840
+:104760000440FFFE2402000AA74201409602000214
+:1047700024040009304200070002102330420007E1
+:10478000A7420142960200022442FFFEA7420144D2
+:10479000A740014697420104A74201488F42010801
+:1047A0003042002050400001240400019202000425
+:1047B00030420010144000023483001000801821A1
+:1047C000A743014A000000000000000000000000B4
+:1047D00000000000AF4810000000000000000000D2
+:1047E00000000000000000008F4210000441FFFEA6
+:1047F0003102FFFF10400007000000009202000499
+:104800003042004014400003000000008F421018A6
+:10481000ACC20000960200063042FFFF24420002B4
+:10482000000210430002104003628821962200001B
+:104830001120000D3044FFFF00A710218F830038A6
+:104840008F45101C000210820002108000431021CE
+:10485000AC45000030A6FFFF0E00058D00052C02C0
+:1048600000402021A6220000920300042402FF80C1
+:1048700000431024304200FF1040001F00000000E1
+:1048800092020005304200021040001B00000000B0
+:104890009742100C2442FFFEA742101600000000B1
+:1048A0003C02040034420030AF421000000000001F
+:1048B0000000000000000000000000008F42100017
+:1048C0000441FFFE000000009742100C8F45101CB1
+:1048D0003042FFFF244200300002108200021080AC
+:1048E000005B1021AC45000030A6FFFF0E00058DD7
+:1048F00000052C02A6220000960400022484000871
+:104900000E0001E93084FFFF974401040E0001F717
+:104910003084FFFF8FBF00188FB100148FB00010DC
+:104920003C02100027BD002003E00008AF420178E0
+:104930003084FFFF308200078F8500241040000282
+:10494000248300073064FFF800A4102130421FFFC9
+:1049500003421821247B4000AF850028AF82002449
+:1049600003E00008AF4200843084FFFF3082000F74
+:104970008F85002C8F860034104000022483000FA6
+:104980003064FFF000A410210046182BAF850030E2
+:104990000046202314600002AF82002CAF84002C5C
+:1049A0008F82002C340480000342182100641821F7
+:1049B000AF83003803E00008AF4200808F8200140C
+:1049C000104000088F8200048F82FFDC1440000535
+:1049D0008F8200043C02FFBF3442FFFF008220248C
+:1049E0008F82000430430006240200021062000F90
+:1049F0003C0201012C620003504000052402000427
+:104A00001060000F3C0200010A00023000000000AC
+:104A100010620005240200061462000C3C02011121
+:104A20000A000229008210253C0200110082102594
+:104A3000AF421000240200010A000230AF82000CD5
+:104A400000821025AF421000AF80000C0000000073
+:104A5000000000000000000003E00008000000006B
+:104A60008F82000C10400004000000008F421000F4
+:104A70000441FFFE0000000003E000080000000009
+:104A80008F8200102443F800000231C224C2FFF0DC
+:104A90002C63030110600003000210420A00025759
+:104AA000AC8200008F85001800C5102B1440000B4D
+:104AB0000000182100C51023244700018F82001C2C
+:104AC00000A210212442FFFF0046102B5440000496
+:104AD0002402FFFF0A000257AC8700002402FFFFF8
+:104AE0000A000260AC8200008C82000000021940C3
+:104AF000006218210003188000621821000318804A
+:104B00003C0208002442175C0062182103E0000800
+:104B10000060102127BDFFD8AFBF0020AFB1001C3F
+:104B2000AFB000183C0460088C8250002403FF7F63
+:104B30003C066000004310243442380CAC82500024
+:104B40008CC24C1C3C1A8000000216023042000F3E
+:104B500010400007AF82001C8CC34C1C3C02001F9D
+:104B60003442FC0000621824000319C2AF8300180D
+:104B70008F420008275B400034420001AF4200082A
+:104B8000AF8000243C02601CAF400080AF40008436
+:104B90008C4500088CC308083402800003422021A1
+:104BA0002402FFF0006218243C0200803C0108004F
+:104BB000AC2204203C025709AF8400381462000480
+:104BC000AF850034240200010A000292AF82001473
+:104BD000AF8000148F4200003842000130420001D3
+:104BE0001440FFFC8F8200141040001600000000EB
+:104BF00097420104104000058F83000014600007F5
+:104C00002462FFFF0A0002A72C62000A2C62001037
+:104C1000504000048F83000024620001AF82000036
+:104C20008F8300002C62000A144000032C620007EE
+:104C30000A0002AEAF80FFDC104000022402000137
+:104C4000AF82FFDC8F4301088F44010030622000F7
+:104C5000AF83000410400008AF8400103C0208003D
+:104C60008C42042C244200013C010800AC22042C9C
+:104C70000A00058A3C0240003065020014A00003CF
+:104C800024020F001482026024020D0097420104E6
+:104C9000104002C83C02400030624000144000ADA9
+:104CA0008F8200388C4400088F4201780440FFFE58
+:104CB00024020800AF42017824020008A742014004
+:104CC000A7400142974201048F8400043051FFFF46
+:104CD0003082000110400007022080212623FFFEC1
+:104CE000240200023070FFFFA74201460A0002DBE7
+:104CF000A7430148A74001463C0208008C42043CFF
+:104D00001440000D8F8300103082002014400002F8
+:104D10002403000924030001006020218F83001078
+:104D2000240209005062000134840004A744014AAF
+:104D30000A0002F60000000024020F0014620005C1
+:104D400030820020144000062403000D0A0002F502
+:104D50002403000514400002240300092403000179
+:104D6000A743014A3C0208008C4204203C0400484E
+:104D70000E00020C004420250E0002350000000049
+:104D80008F82000C1040003E000000008F42100097
+:104D90003C03002000431024104000398F8200049F
+:104DA000304200021040003600000000974210140C
+:104DB0001440003300000000974210088F8800382C
+:104DC0003042FFFF244200060002188200033880B0
+:104DD00000E83021304300018CC400001060000462
+:104DE000304200030000000D0A00033700E81021E4
+:104DF000544000103084FFFF3C05FFFF0085202455
+:104E0000008518260003182B0004102B00431024E3
+:104E10001040000500000000000000000000000D30
+:104E200000000000240002228CC200000A000336A9
+:104E3000004520253883FFFF0003182B0004102BAA
+:104E40000043102410400005000000000000000096
+:104E50000000000D000000002400022B8CC20000A6
+:104E60003444FFFF00E81021AC4400003C0208007D
+:104E70008C420430244200013C010800AC22043082
+:104E80008F6200008F840038AF8200088C8300009E
+:104E90003402FFFF1462000F000010213C050800DF
+:104EA0008CA504543C0408008C84045000B02821D4
+:104EB00000B0302B00822021008620213C01080018
+:104EC000AC2504543C010800AC2404500A000580C1
+:104ED000240400088C820000304201001040000FC2
+:104EE000000010213C0508008CA5044C3C0408007F
+:104EF0008C84044800B0282100B0302B008220218F
+:104F0000008620213C010800AC25044C3C0108002F
+:104F1000AC2404480A000580240400083C0508006D
+:104F20008CA504443C0408008C84044000B0282173
+:104F300000B0302B00822021008620213C01080097
+:104F4000AC2504443C010800AC2404400A00058060
+:104F5000240400088F6200088F620000000216021D
+:104F6000304300F0240200301062000524020040AB
+:104F7000106200E08F8200200A00058824420001B0
+:104F800014A0000500000000000000000000000D5B
+:104F900000000000240002568F4201780440FFFE0A
+:104FA000000000000E00023D27A400101440000580
+:104FB00000408021000000000000000D0000000003
+:104FC0002400025D8E020000104000050000000079
+:104FD000000000000000000D00000000240002603E
+:104FE0008F62000C04430003240200010A00042E17
+:104FF000AE000000AE0200008F8200388C4800082E
+:10500000A20000078F65000C8F64000430A3FFFF2F
+:105010000004240200852023308200FF0043102179
+:1050200024420005000230832CC20081A605000A3C
+:1050300014400005A2040004000000000000000D60
+:1050400000000000240002788F8500380E0005ABB8
+:10505000260400148F6200048F430108A602000892
+:105060003C021000006218241060000800000000DC
+:1050700097420104920300072442FFEC34630002CC
+:105080003045FFFF0A0003C3A20300079742010453
+:105090002442FFF03045FFFF960600082CC20013A3
+:1050A00054400005920300079202000734420001B9
+:1050B000A20200079203000724020001106200050B
+:1050C000240200031062000B8F8200380A0003E004
+:1050D00030C6FFFF8F8200383C04FFFF8C43000C7A
+:1050E0000064182400651825AC43000C0A0003E096
+:1050F00030C6FFFF3C04FFFF8C43001000641824FF
+:1051000000651825AC43001030C6FFFF24C2000222
+:1051100000021083A20200058F830038304200FF96
+:1051200000021080004328218CA800008CA20000FF
+:1051300024030004000217021443001200000000C0
+:10514000974201043C03FFFF010318243042FFFF94
+:10515000004610232442FFFE00624025ACA8000058
+:1051600092030005306200FF000210800050102101
+:10517000904200143042000F004310210A00041531
+:10518000A20200068CA40004974201049603000AC0
+:105190003088FFFF3042FFFF004610232442FFD635
+:1051A0000002140001024025ACA80004920200078E
+:1051B000920400052463002800031883006418216A
+:1051C00034420004A2030006A20200078F820004FA
+:1051D0002403FFFB3442000200431024AF8200048A
+:1051E000920300068F87003800031880007010219A
+:1051F0008C4400203C02FFF63442FFFF0082402432
+:1052000000671821AE04000CAC68000C9205000683
+:105210003C03FF7F8E02000C0005288000B0202197
+:105220003463FFFF010330249488002600A728215F
+:1052300000431024AE02000CAC860020AC88002491
+:10524000ACA8001024020010A74201402402000272
+:10525000A7400142A7400144A742014697420104EA
+:105260003C0400082442FFFEA7420148240200013A
+:105270000E00020CA742014A9603000A92020004A3
+:105280000043102124420002304200070002102394
+:10529000304200070E000235AE0200108F6200009F
+:1052A0003C0308008C63044424040010AF8200080F
+:1052B000974201043042FFFF2442FFFE00403821A4
+:1052C000000237C33C0208008C42044000671821EA
+:1052D0000067282B00461021004510213C010800E2
+:1052E000AC2304443C010800AC2204400A0005152C
+:1052F0000000000014A000050000000000000000F5
+:105300000000000D000000002400030A8F42017815
+:105310000440FFFE000000000E00023D27A4001420
+:105320001440000500408021000000000000000D36
+:1053300000000000240003118E020000544000060B
+:1053400092020007000000000000000D00000000B5
+:105350002400031C920200073042000410400005A4
+:105360008F8200042403FFFB344200020043102418
+:10537000AF8200048F620004044300089202000719
+:10538000920200068E03000CAE00000000021080A6
+:1053900000501021AC43002092020007304200046C
+:1053A000544000099602000A920200053C030001E5
+:1053B00000021080005010218C46001800C33021DC
+:1053C000AC4600189602000A9206000427710008F5
+:1053D0000220202100C2302124C600052605001429
+:1053E0000E0005AB00063082920400068F650004B3
+:1053F0003C027FFF00042080009120218C83000468
+:105400003442FFFF00A2282400651821AC83000469
+:105410009202000792040005920300043042000447
+:105420001040001496070008308400FF000420801C
+:10543000009120218C860004974201049605000A01
+:10544000306300FF3042FFFF004310210045102170
+:1054500030E3FFFF004310232442FFD830C6FFFF94
+:105460000002140000C23025AC8600040A0004C902
+:1054700092030007308500FF0005288000B1282135
+:105480008CA4000097420104306300FF3042FFFF0C
+:1054900000431021004710233C03FFFF008320241A
+:1054A0003042FFFF00822025ACA4000092030007D9
+:1054B0002402000110620006000000002402000324
+:1054C00010620011000000000A0004EC8E030010BE
+:1054D00097420104920300049605000A8E24000CF2
+:1054E00000431021004510212442FFF23C03FFFF3E
+:1054F000008320243042FFFF00822025AE24000CD0
+:105500000A0004EC8E030010974201049203000489
+:105510009605000A8E24001000431021004510213A
+:105520002442FFEE3C03FFFF008320243042FFFFB4
+:1055300000822025AE2400108E0300102402000AF1
+:10554000A7420140A74301429603000A92020004C9
+:105550003C04004000431021A7420144A7400146FB
+:1055600097420104A7420148240200010E00020CE8
+:10557000A742014A0E000235000000008F620000C1
+:105580009203000400002021AF820008974201042A
+:105590009606000A3042FFFF0062182100602821B1
+:1055A0003C0308008C6304443C0208008C42044025
+:1055B00000651821004410210065382B0047102198
+:1055C0003C010800AC2304443C010800AC22044028
+:1055D00092040004008620212484000A3084FFFF06
+:1055E0000E0001E900000000974401043084FFFF31
+:1055F0000E0001F7000000003C021000AF420178ED
+:105600000A0005878F82002014820027306200067E
+:1056100097420104104000673C02400030624000A5
+:105620001040000500000000000000000000000D18
+:1056300000000000240004208F4201780440FFFE97
+:1056400024020800AF42017824020008A74201406A
+:10565000A74001428F8200049743010430420001B9
+:10566000104000073070FFFF2603FFFE24020002F7
+:10567000A7420146A74301480A00053F2402000D46
+:10568000A74001462402000DA742014A8F62000094
+:1056900024040008AF8200080E0001E900000000A9
+:1056A0000A00051902002021104000423C0240007F
+:1056B00093620000304300F02402001010620005E5
+:1056C00024020070106200358F8200200A000588D5
+:1056D000244200018F620000974301043050FFFF15
+:1056E0003071FFFF8F4201780440FFFE3202000755
+:1056F00000021023304200072403000A2604FFFEA4
+:10570000A7430140A7420142A7440144A7400146E4
+:10571000A75101488F420108304200201440000286
+:105720002403000924030001A743014A0E00020CD0
+:105730003C0400400E000235000000003C07080059
+:105740008CE70444021110212442FFFE3C060800AD
+:105750008CC604400040182100E3382100001021CD
+:105760008F65000000E3402B00C2302126040008B2
+:1057700000C830213084FFFFAF8500083C010800DD
+:10578000AC2704443C010800AC2604400E0001E9AB
+:10579000000000000A000519022020210E00013B34
+:1057A000000000008F82002024420001AF82002010
+:1057B0003C024000AF4201380A00029200000000A3
+:1057C0003084FFFF30C6FFFF00052C0000A628250F
+:1057D0003882FFFF004510210045282B004510218D
+:1057E00000021C023042FFFF0043102100021C0295
+:1057F0003042FFFF004310213842FFFF03E0000862
+:105800003042FFFF3084FFFF30A5FFFF000018216A
+:1058100010800007000000003082000110400002EC
+:1058200000042042006518210A0005A10005284057
+:1058300003E000080060102110C0000624C6FFFF2E
+:105840008CA2000024A50004AC8200000A0005AB75
+:105850002484000403E000080000000010A00008F9
+:1058600024A3FFFFAC860000000000000000000041
+:105870002402FFFF2463FFFF1462FFFA2484000464
+:0858800003E000080000000035
+:04588800000000011B
+:04588C000A00002AE4
+:1058900000000000000000000000000D7478703669
+:1058A0002E322E31610000000602010000000000CF
+:1058B000000001360000EA60000000000000000067
+:1058C00000000000000000000000000000000000D8
+:1058D00000000000000000000000000000000000C8
+:1058E00000000000000000000000000000000016A2
+:1058F00000000000000000000000000000000000A8
+:105900000000000000000000000000000000000097
+:105910000000000000000000000000000000000087
+:10592000000000000000138800000000000005DCFB
+:105930000000000000000000100000030000000054
+:105940000000000D0000000D3C02080024423D68EC
+:105950003C0308002463401CAC4000000043202BA3
+:105960001480FFFD244200043C1D080037BD7FFC6D
+:1059700003A0F0213C100800261000A83C1C0800E1
+:10598000279C3D680E00044E000000000000000D42
+:1059900027BDFFB4AFA10000AFA20004AFA3000871
+:1059A000AFA4000CAFA50010AFA60014AFA700185D
+:1059B000AFA8001CAFA90020AFAA0024AFAB0028FD
+:1059C000AFAC002CAFAD0030AFAE0034AFAF00389D
+:1059D000AFB8003CAFB90040AFBC0044AFBF004817
+:1059E0000E000591000000008FBF00488FBC0044EE
+:1059F0008FB900408FB8003C8FAF00388FAE0034B5
+:105A00008FAD00308FAC002C8FAB00288FAA002404
+:105A10008FA900208FA8001C8FA700188FA6001444
+:105A20008FA500108FA4000C8FA300088FA2000484
+:105A30008FA1000027BD004C3C1B60048F7A5030C2
+:105A4000377B502803400008AF7A00008F86003C67
+:105A50003C0390003C0280000086282500A32025FE
+:105A6000AC4400203C0380008C67002004E0FFFE73
+:105A70000000000003E00008000000000A000070C1
+:105A8000240400018F85003C3C0480003483000125
+:105A900000A3102503E00008AC82002003E000080A
+:105AA000000010213084FFFF30A5FFFF10800007A9
+:105AB0000000182130820001104000020004204242
+:105AC000006518211480FFFB0005284003E0000852
+:105AD0000060102110C00007000000008CA2000030
+:105AE00024C6FFFF24A50004AC82000014C0FFFB05
+:105AF0002484000403E000080000000010A0000857
+:105B000024A3FFFFAC86000000000000000000009E
+:105B10002402FFFF2463FFFF1462FFFA24840004C1
+:105B200003E000080000000090AA00318FAB0010D5
+:105B30008CAC00403C0300FF8D680004AD6C00207D
+:105B40008CAD004400E060213462FFFFAD6D0024A5
+:105B50008CA700483C09FF000109C024AD6700285C
+:105B60008CAE004C0182C82403197825AD6F000467
+:105B7000AD6E002C8CAD0038314A00FFAD6D001CBD
+:105B800094A900323128FFFFAD68001090A70030C3
+:105B9000A5600002A1600004A167000090A300328C
+:105BA000306200FF00021982106000052405000128
+:105BB0001065000E0000000003E00008A16A00016B
+:105BC0008CD80028354A0080AD7800188CCF00149E
+:105BD000AD6F00148CCE0030AD6E00088CC4002C6C
+:105BE000A16A000103E00008AD64000C8CCD001C2C
+:105BF000AD6D00188CC90014AD6900148CC8002468
+:105C0000AD6800088CC70020AD67000C8CC2001482
+:105C10008C8300700043C82B132000070000000095
+:105C20008CC20014144CFFE400000000354A0080D0
+:105C300003E00008A16A00018C8200700A0000E6FF
+:105C4000000000009089003027BDFFF88FA8001CDD
+:105C5000A3A900008FA300003C0DFF8035A2FFFF29
+:105C60008CAC002C00625824AFAB0000A1000004F3
+:105C700000C05821A7A000028D06000400A0482102
+:105C80000167C8218FA50000008050213C18FF7FCC
+:105C9000032C20263C0E00FF2C8C0001370FFFFF49
+:105CA00035CDFFFF3C02FF0000AFC82400EDC0244B
+:105CB00000C27824000C1DC00323682501F870255C
+:105CC000AD0D0000AD0E00048D240024AFAD00002A
+:105CD000AD0400088D2C00202404FFFFAD0C000C47
+:105CE0009547003230E6FFFFAD06001091450048B1
+:105CF00030A200FF000219C2506000018D24003460
+:105D0000AD0400148D4700388FAA001827BD000885
+:105D1000AD0B0028AD0A0024AD07001CAD00002C1F
+:105D2000AD00001803E00008AD00002027BDFFE033
+:105D3000AFB20018AFB10014AFB00010AFBF001C7D
+:105D40009098003000C088213C0D00FF330F007F89
+:105D5000A0CF0000908E003135ACFFFF3C0AFF0061
+:105D6000A0CE000194A6001EA22000048CAB00145B
+:105D70008E29000400A08021016C2824012A4024DF
+:105D80000080902101052025A6260002AE240004F3
+:105D900026050020262400080E000092240600029A
+:105DA00092470030260500282624001400071E0014
+:105DB0000003160324060004044000032403FFFF2D
+:105DC000965900323323FFFF0E000092AE230010DD
+:105DD000262400248FBF001C8FB200188FB100143E
+:105DE0008FB0001024050003000030210A00009C41
+:105DF00027BD002027BDFFD8AFB1001CAFB00018F1
+:105E0000AFBF002090A900302402000100E0502123
+:105E10003123003F00A040218FB000400080882146
+:105E200000C04821106200148FA70038240B000521
+:105E300000A0202100C02821106B00130200302197
+:105E40000E000128000000009225007C30A4000212
+:105E50001080000326030030AE000030260300341B
+:105E60008FBF00208FB1001C8FB000180060102180
+:105E700003E0000827BD00280E0000A7AFB0001007
+:105E80000A00016F000000008FA3003C01002021E8
+:105E90000120282101403021AFA300100E0000EEA8
+:105EA000AFB000140A00016F000000003C06800043
+:105EB00034C20E008C4400108F850044ACA4002036
+:105EC0008C43001803E00008ACA300243C068000CB
+:105ED00034C20E008C4400148F850044ACA4002012
+:105EE0008C43001C03E00008ACA300249382000C48
+:105EF0001040001B2483000F2404FFF000643824AA
+:105F000010E00019978B00109784000E9389000D04
+:105F10003C0A601C0A0001AC0164402301037021AB
+:105F2000006428231126000231C2FFFF30A2FFFFC8
+:105F30000047302B50C0000E00E448218D4D000C6E
+:105F400031A3FFFF00036400000C2C0304A1FFF346
+:105F50000000302130637FFF0A0001A42406000105
+:105F600003E00008000000009784000E00E44821D0
+:105F70003123FFFF3168FFFF0068382B54E0FFF842
+:105F8000A783000E938A000D11400005240F000125
+:105F9000006BC023A380000D03E00008A798000E4B
+:105FA000006BC023A38F000D03E00008A798000E2C
+:105FB00003E000080000000027BDFFE8AFB00010BC
+:105FC0003C10800036030140308BFFFF93AA002B6A
+:105FD000AFBF0014A46B000436040E0094880016B2
+:105FE00030C600FF8FA90030A4680006AC65000829
+:105FF000A0660012A46A001AAC6700208FA5002CCE
+:10600000A4690018012020210E000198AC6500143D
+:106010003C021000AE0201788FBF00148FB0001058
+:1060200003E0000827BD00188F85000024840007C6
+:1060300027BDFFF83084FFF83C06800094CB008A2F
+:10604000316AFFFFAFAA00008FA90000012540239D
+:106050002507FFFF30E31FFF0064102B1440FFF7FC
+:1060600000056882000D288034CC400000AC10216F
+:1060700003E0000827BD00088F8200002486000787
+:1060800030C5FFF800A2182130641FFF03E00008AC
+:10609000AF8400008F87003C8F84004427BDFFB091
+:1060A000AFB70044AFB40038AFB1002CAFBF004869
+:1060B000AFB60040AFB5003CAFB30034AFB2003074
+:1060C000AFB000283C0B80008C860024AD670080B8
+:1060D0008C8A002035670E0035690100ACEA00109B
+:1060E0008C8800248D2500040000B821ACE800183D
+:1060F0008CE3001000A688230000A021ACE300146C
+:106100008CE20018ACE2001C122000FE00E0B0217E
+:10611000936C0008118000F400000000976F0010DD
+:1061200031EEFFFF022E682B15A000EF00000000EB
+:10613000977200103250FFFFAED000003C03800089
+:106140008C740000329300081260FFFD0000000014
+:1061500096D800088EC700043305FFFF30B5000154
+:1061600012A000E4000000000000000D30BFA040BD
+:106170002419004013F9011B30B4A000128000DF85
+:106180000000000093730008126000080000000087
+:10619000976D001031ACFFFF00EC202B1080000346
+:1061A00030AE004011C000D500000000A7850040BF
+:1061B000AF8700389363000802202821AFB1002088
+:1061C000146000F527B40020AF60000C978F0040EA
+:1061D00031F1400016200002240300162403000EB3
+:1061E00024054007A363000AAF650014938A0042A8
+:1061F0008F7000143155000100151240020248252D
+:10620000AF690014979F00408F78001433F9001095
+:1062100003194025AF6800149792004032470008E8
+:1062200010E0016E000000008F6700143C121000A7
+:106230003C11800000F27825AF6F001436230E0069
+:10624000946E000A3C0D81002406000E31CCFFFF45
+:10625000018D2025AF640004A36600029373000A39
+:106260003406FFFC266B0004A36B000A97980040DD
+:10627000330820001100015F000000003C05800091
+:1062800034A90E00979900409538000C978700407C
+:10629000001940423312C0003103000300127B0397
+:1062A00030F11000006F68250011720301AE602507
+:1062B000000C20C0A764001297930040936A000A64
+:1062C000001359823175003C02AA10212450003C71
+:1062D000A3700009953F000C33F93FFFA779001028
+:1062E00097700012936900090130F82127E5000238
+:1062F00030B900070019C02333080007A368000B5A
+:106300009371000997720012976F0010322700FFF7
+:106310008F910038978D004000F21821006F702196
+:1063200001C6602131A6004010C000053185FFFF85
+:1063300000B1102B3C128000104000170000982183
+:106340000225A82B56A0013E8FA500203C0480000A
+:10635000348A0E008D5300143C068000AD530010AB
+:106360008D4B001CAD4B0018AD4500008CCD0000DE
+:1063700031AC00081180FFFD34CE0E0095C300083B
+:1063800000A0882100009021A78300408DC6000452
+:1063900024130001AF860038976F001031F5FFFF1E
+:1063A0008E9F000003F1282310A0011FAE8500007E
+:1063B00093620008144000DD000000000E0001E7B9
+:1063C000240400108F900048004028213C02320035
+:1063D000320600FF000654000142F825260900019C
+:1063E000AF890048ACBF000093790009977800128C
+:1063F000936F000A332800FF3303FFFF01033821A6
+:1064000000076C0031EE00FF01AE6025ACAC00046B
+:106410008F840048978B0040316A20001140010AA8
+:10642000ACA4000897640012308BFFFF06400108FF
+:10643000ACAB000C978E004031C5000814A00002E0
+:1064400026280006262800023C1F800037E70E00A1
+:1064500094F900148CE5001C8F6700049378000207
+:106460003324FFFF330300FFAFA300108F6F00142E
+:10647000AFA800180E0001CBAFAF00142404001029
+:106480000E0001FB000000008E9200001640000587
+:10649000000000008F7800142403FFBF0303A02432
+:1064A000AF7400148F67000C00F5C821AF79000CA1
+:1064B0009375000816A00008000000001260000696
+:1064C000000000008F6800143C0AEFFF3549FFFE12
+:1064D0000109F824AF7F0014A37300088FA50020E2
+:1064E0000A00034F02202021AED100000A00022D35
+:1064F0003C03800014E0FF1E30BFA0400E0001905E
+:106500000000A0212E9100010237B02512C0001812
+:106510008FBF00488F87003C24170F0010F700D46E
+:106520003C0680008CD901780720FFFE241F0F0055
+:1065300010FF00F634CA0E008D56001434C7014017
+:1065400024080240ACF600048D49001C3C141000E5
+:10655000ACE90008A0E00012A4E0001AACE00020C2
+:10656000A4E00018ACE80014ACD401788FBF004858
+:106570008FB700448FB600408FB5003C8FB4003811
+:106580008FB300348FB200308FB1002C8FB0002851
+:1065900003E0000827BD00508F9100389788004025
+:1065A0003C1280000220A8213107004014E0FF7C4B
+:1065B00000009821977900108F9200383338FFFF40
+:1065C000131200A8000020210080A021108000F3F9
+:1065D00000A088211620FECE000000000A00031F44
+:1065E0002E9100013C0380008C6201780440FFFE84
+:1065F000240808008F860000AC6801783C03800006
+:10660000946D008A31ACFFFF01865823256AFFFF95
+:1066100031441FFF2C8900081520FFF900000000FD
+:106620008F8F0048347040008F83003C00E0A02131
+:10663000240E0F0025E70001AF87004800D030216D
+:10664000023488233C08800031F500FF106E0005FD
+:106650002407000193980042331300010013924075
+:1066600036470001001524003C0A0100008A482535
+:10667000ACC900008F82004830BF003630B9000836
+:10668000ACC200041320009900FF982535120E00BB
+:106690009650000A8F8700003C0F81003203FFFFF5
+:1066A00024ED000835060140006F60253C0E100007
+:1066B00031AB1FFF269200062405000EACCC002053
+:1066C000026E9825A4C5001AAF8B0000A4D2001852
+:1066D000162000083C1080008F89003C24020F0027
+:1066E0005122000224170001367300400E00018879
+:1066F0003C10800036060E008CCB0014360A014098
+:1067000002402021AD4B00048CC5001CAD450008A3
+:10671000A1550012AD5300140E0001983C15100055
+:10672000AE1501780A00035200000000936F0009C3
+:10673000976E0012936D000B31E500FF00AE202133
+:1067400031AC00FF008C80212602000A3050FFFF90
+:106750000E0001E7020020218F8600483C03410023
+:106760003C05800024CB0001AF8B0048936A0009F0
+:106770009769001230C600FF315F00FF3128FFFF2C
+:1067800003E8382124F900020006C4000319782523
+:1067900001E37025AC4E00008F6D000C34A40E0098
+:1067A000948B001401B26025AC4C00048C85001C55
+:1067B0008F670004936A00023164FFFF314900FFD4
+:1067C000AFA900108F680014AFB100180E0001CB04
+:1067D000AFA800140A0002FD02002021AF600004EF
+:1067E000A360000297980040330820001500FEA324
+:1067F00000003021A760001297840040936B000ACC
+:106800003C10800030931F0000135183014BA821DE
+:1068100026A20028A362000936090E00953F000C4D
+:106820000A000295A77F00108F70001436090040FF
+:106830000E000188AF6900140A0002C900000000C0
+:106840000A00034F000020210641FEFAACA0000C14
+:106850008CAC000C3C0D8000018D90250A0002EAF2
+:10686000ACB2000C000090210A0002C52413000104
+:10687000128000073C028000344B0E009566000831
+:1068800030D3004012600049000000003C06800048
+:106890008CD001780600FFFE34C50E0094B50010C0
+:1068A0003C03050034CC014032B8FFFF03039025C0
+:1068B000AD92000C8CAF0014240D20003C0410009D
+:1068C000AD8F00048CAE001CAD8E0008A1800012BC
+:1068D000A580001AAD800020A5800018AD8D0014A1
+:1068E000ACC401780A0003263C0680008F9F00009C
+:1068F000351801402692000227F9000833281FFFAF
+:10690000A71200180A000391AF8800003C02800023
+:1069100034450140ACA0000C1280001B34530E0023
+:1069200034510E008E370010ACB700048E240018CE
+:106930003C0B8000ACA400083570014024040040EA
+:10694000A20000128FBF0048A600001A8FB70044B3
+:10695000AE0000208FB60040A60000188FB5003CA6
+:10696000AE0400148FB400388FB300348FB20030FF
+:106970008FB1002C8FB000283C02100027BD0050C2
+:1069800003E00008AD6201788E660014ACA6000436
+:106990008E64001C0A00042A3C0B80000E0001904B
+:1069A0002E9100010A0003200237B02500000000EC
+:1069B0000000000D00000000240003690A0004012B
+:1069C0003C06800027BDFFD8AFBF00203C098000F7
+:1069D0003C1F20FFAFB200183C07600035320E00AC
+:1069E0002402001037F9FFFDACE23008AFB3001C01
+:1069F000AFB10014AFB00010AE59000000000000AD
+:106A00000000000000000000000000000000000086
+:106A10003C1800FF3713FFFDAE5300003C0B600431
+:106A20008D7050002411FF7F3C0E0002021178246B
+:106A300035EC380C35CD0109ACED4C18240A0009B1
+:106A4000AD6C50008CE80438AD2A0008AD2000146D
+:106A50008CE54C1C3106FFFF38C42F7100051E0267
+:106A60003062000F2486C0B310400007AF820008D8
+:106A70008CE54C1C3C09001F3528FC0000A818249C
+:106A8000000321C2AF8400048CF108083C0F5709B1
+:106A90002412F0000232702435F0001001D060267C
+:106AA00001CF68262DAA00012D8B0001014B38254E
+:106AB00050E00009A380000C3C1F601C8FF8000808
+:106AC00024190001A399000C33137C00A793001034
+:106AD000A780000EA380000DAF80004814C0000303
+:106AE000AF8000003C066000ACC0442C0E0005B92D
+:106AF0003C1080000E000F1A361101003C120800F5
+:106B000026523DD03C13080026733E508E030000F1
+:106B100038640001308200011440FFFC3C0B800A05
+:106B20008E2600002407FF8024C90240312A007FFE
+:106B3000014B402101272824AE060020AF880044E5
+:106B4000AE0500243C048000AF86003C8C8C0178AC
+:106B50000580FFFE24180800922F0008AC980178E9
+:106B6000A38F0042938E004231CD000111A0000F8F
+:106B700024050D0024DFF8002FF903011320001C69
+:106B8000000629C224A4FFF0000410420002314094
+:106B90000E00020200D2D8213C0240003C068000D8
+:106BA000ACC201380A0004A00000000010C5002398
+:106BB000240D0F0010CD00273C1F800837F90080FE
+:106BC00093380000240E0050330F00FF15EEFFF342
+:106BD0003C0240000E000A36000000003C0240006B
+:106BE0003C068000ACC201380A0004A0000000008E
+:106BF0008F83000400A3402B1500000B8F8B00082F
+:106C0000006B50212547FFFF00E5482B15200006AB
+:106C100000A36023000C19400E0002020073D8216B
+:106C20000A0004C43C0240000000000D0E000202F5
+:106C3000000000000A0004C43C0240003C1B0800A5
+:106C4000277B3F500E000202000000000A0004C42F
+:106C50003C0240003C1B0800277B3F700E000202F4
+:106C6000000000000A0004C43C0240003C0660042E
+:106C70003C09080025290104ACC9502C8CC85000DF
+:106C80003C0580003C02000235070080ACC7500084
+:106C90003C040800248415A43C0308002463155C0C
+:106CA000ACA50008ACA2000C3C010800AC243D607F
+:106CB0003C010800AC233D6403E00008240200010D
+:106CC00000A030213C1C0800279C3D683C0C0400BF
+:106CD0003C0B0002008B3826008C40262CE2000181
+:106CE0000007502B2D050001000A48803C030800D6
+:106CF00024633D60004520250123182110800003F6
+:106D000000001021AC6600002402000103E000082E
+:106D1000000000003C1C0800279C3D683C0B040060
+:106D20003C0A0002008A3026008B38262CC2000163
+:106D30000006482B2CE50001000940803C030800B8
+:106D400024633D60004520250103182110800005C3
+:106D5000000010213C0C0800258C155CAC6C000078
+:106D60002402000103E00008000000003C090002CA
+:106D70003C08040000883026008938262CC3000116
+:106D8000008028212CE40001008310251040000B16
+:106D9000000030213C1C0800279C3D683C0A800014
+:106DA0008D4E00082406000101CA6825AD4D00087B
+:106DB0008D4C000C01855825AD4B000C03E00008FC
+:106DC00000C010213C1C0800279C3D683C05800049
+:106DD0008CA6000C000420272402000100C4182403
+:106DE00003E00008ACA3000C3C0200021082000B80
+:106DF0003C0560003C070400108700030000000011
+:106E000003E00008000000008CA908D0240AFFFD60
+:106E1000012A402403E00008ACA808D08CA408D0C4
+:106E20002406FFFE0086182403E00008ACA308D067
+:106E30003C05601A34A600108CC3008027BDFFF803
+:106E40008CC50084AFA3000093A4000024020001BD
+:106E500010820003AFA5000403E0000827BD00086E
+:106E600093A7000114E0001497AC000297B8000249
+:106E70003C0F8000330EFFFC01CF6821ADA5000060
+:106E8000A3A000003C0660008CC708D02408FFFEC9
+:106E90003C04601A00E82824ACC508D08FA3000485
+:106EA0008FA200003499001027BD0008AF22008097
+:106EB00003E00008AF2300843C0B8000318AFFFC14
+:106EC000014B48218D2800000A00057DAFA8000471
+:106ED00027BDFFE8AFBF00103C1C0800279C3D68A1
+:106EE0003C0580008CA4000C8CA200043C03000232
+:106EF0000044282410A0000A00A318243C06040023
+:106F00003C0400021460000900A610241440000F85
+:106F10003C0404000000000D3C1C0800279C3D6858
+:106F20008FBF001003E0000827BD00183C020800D6
+:106F30008C423D600040F809000000003C1C080045
+:106F4000279C3D680A0005A68FBF00103C02080080
+:106F50008C423D640040F809000000000A0005ACC6
+:106F600000000000000411C003E0000824420240B9
+:106F70003C04080024843FB42405001A0A00009C45
+:106F80000000302127BDFFE0AFB000103C108000B2
+:106F9000AFBF0018AFB100143611010092220009F2
+:106FA0000E0005B63044007F8E3F00008F89003C04
+:106FB0003C0F008003E26021258800400049F82151
+:106FC000240DFF80310E00783198007835F90001EA
+:106FD00035F100020319382501D14825010D30246F
+:106FE00003ED5824018D2824240A00402404008045
+:106FF000240300C0AE0B0024AE000810AE0A081433
+:10700000AE040818AE03081CAE050804AE0708203D
+:10701000AE060808AE090824360909009539000CA7
+:107020003605098033ED007F3338FFFF001889C033
+:10703000AE110800AE0F0828952C000C8FBF001869
+:107040008FB10014318BFFFF000B51C0AE0A002C32
+:107050008CA400508FB000108CA3003C8D2700043E
+:107060008CA8001C8CA600383C0E800A01AE1021B2
+:1070700027BD0020AF820044AF840050AF8300548E
+:10708000AF87004CAF88005C03E00008AF8600606B
+:107090003C09080091293FD924A800023C051100B1
+:1070A00000093C0000E8302500C5182524820008AE
+:1070B000AC83000003E00008AC8000043C098000C1
+:1070C000352309009128010B906A00112402002841
+:1070D00000804821314700FF00A0702100C06821D6
+:1070E0003108004010E20002340C86DD240C080058
+:1070F0003C0A800035420A9A94470000354B0A9CAE
+:1071000035460AA030F9FFFFAD3900008D78000048
+:10711000354B0A8024040001AD3800048CCF0000F8
+:10712000AD2F00089165001930A300031064009092
+:1071300028640002148000AF240500021065009E40
+:10714000240F0003106F00B435450AA4240A080078
+:10715000118A0048000000005100003D3C0B8000F7
+:107160003C048000348309009067001230E200FF85
+:10717000004D7821000FC880272400013C0A8000C0
+:10718000354F090091E50019354C09808D8700289D
+:1071900030A300FF00031500004758250004C40079
+:1071A0003C19600001793025370806FFAD26000044
+:1071B000AD2800048DEA002C25280028AD2A0008FF
+:1071C0008DEC0030AD2C000C8DE50034AD250010A9
+:1071D0008DE400383C05800034AC093CAD2400143B
+:1071E0008DE3001CAD2300188DE70020AD27001CA7
+:1071F0008DE20024AD2200208DF9002834A2010088
+:10720000AD3900248D830000AD0E000434B90900AF
+:10721000AD0300008C47000C25020014AD070008E8
+:10722000932B00123C04080090843FD8AD0000105E
+:10723000317800FF030D302100064F0000047C0070
+:10724000012F702535CDFFFC03E00008AD0D000CCB
+:1072500035780900930600123C05080094A53FC844
+:1072600030C800FF010D5021000A60800A00063C72
+:10727000018520211500005B000000003C0808008B
+:1072800095083FCE3C06080094C63FC80106102171
+:107290003C0B80003579090093380011932A0019BE
+:1072A00035660A80330800FF94CF002A0008608208
+:1072B000314500FF978A0058000C1E00000524008D
+:1072C0003047FFFF006410250047C02501EA302148
+:1072D0003C0B4000030B402500066400AD28000075
+:1072E000AD2C0004932500183C030006252800144B
+:1072F00000053E0000E31025AD2200088F24002C7D
+:107300003C05800034AC093CAD24000C8F38001CD7
+:1073100034A20100254F0001AD3800108D8300001C
+:10732000AD0E000431EB7FFFAD0300008C47000C75
+:1073300034B90900A78B0058AD070008932B001241
+:107340003C04080090843FD825020014317800FFE7
+:10735000030D302100064F0000047C00012F702532
+:1073600035CDFFFCAD00001003E00008AD0D000CB2
+:107370003C02080094423FD23C05080094A53FC857
+:1073800035440AA43C07080094E73FC4948B0000EE
+:107390000045C8210327C023000B1C002706FFF26D
+:1073A00000665025AD2A000CAD200010AD2C001455
+:1073B0000A00063025290018354F0AA495E500007B
+:1073C000956400280005140000043C003459810035
+:1073D00000EC5825AD39000CAD2B00100A0006302A
+:1073E000252900143C0C0800958C3FCE0A0006812C
+:1073F000258200015460FF56240A080035580AA46B
+:107400009706000000061C00006C5025AD2A000CF9
+:107410000A000630252900103C03080094633FD27F
+:107420003C07080094E73FC83C0F080095EF3FC4B5
+:1074300094A400009579002800671021004F58237C
+:1074400000041C00001934002578FFEE00D87825D0
+:10745000346A8100AD2A000CAD2F0010AD2000145D
+:10746000AD2C00180A0006302529001C03E0000896
+:10747000240207D027BDFFE0AFB20018AFB100145F
+:10748000AFB00010AFBF001C0E00007C0080882150
+:107490008F8800548F87004C3C05800834B20080F0
+:1074A000011128213C10800024020080240300C028
+:1074B00000A72023AE0208183C068008AE03081C73
+:1074C00018800004AF850054ACC500048CC90004CA
+:1074D000AF89004C12200009360409800E0006F81E
+:1074E00000000000924C00278E0B007401825004B3
+:1074F000014B3021AE46000C360409808C8E001CF6
+:107500008F8F005C01CF682319A000048FBF001C7F
+:107510008C90001CAF90005C8FBF001C8FB20018D5
+:107520008FB100148FB000100A00007E27BD00202C
+:107530008F8600508F8300548F82004C3C0580085A
+:1075400034A40080AC860050AC83003C03E000080B
+:10755000ACA200043C0308008C63005427BDFFF874
+:10756000308400FF2462000130A500FF3C010800C8
+:10757000AC22005430C600FF3C0780008CE8017844
+:107580000500FFFE3C0C7FFFA3A400038FAA0000B0
+:10759000358BFFFF014B4824000627C001244025FE
+:1075A000AFA8000034E201009043000AA3A000024B
+:1075B0003C1980FFA3A300018FAF000030AE007F15
+:1075C0003738FFFF01F86024000E6E003C0A0020EF
+:1075D00034E50140018D5825354920002406FF80FF
+:1075E0003C04100027BD0008ACAB000CACA9001493
+:1075F000A4A00018A0A6001203E00008ACE40178E3
+:10760000308800FF30A700FF3C0380008C620178C7
+:107610000440FFFE3C0C8000358A0A008D4B0020A0
+:107620003584014035850980AC8B00048D490024E8
+:107630000007302B00061540AC890008A088001018
+:1076400090A3004CA083002D03E00008A480001844
+:1076500027BDFFE8308400FFAFBF00100E00075DBC
+:1076600030A500FF8F8300548FBF00103C068000C0
+:1076700034C50140344700402404FF903C02100010
+:1076800027BD0018ACA3000CA0A40012ACA70014E6
+:1076900003E00008ACC2017827BDFFE03C08800889
+:1076A000AFBF001CAFB20018AFB10014AFB00010F4
+:1076B000351000808E0600183C078000309200FFD5
+:1076C00000C72025AE0400180E00007C30B100FF7A
+:1076D00092030005346200080E00007EA20200053D
+:1076E000024020210E0007710220282102402021A3
+:1076F0008FBF001C8FB200188FB100148FB0001024
+:1077000024050005240600010A00073227BD0020D9
+:107710003C05800034A309809066000830C2000850
+:107720001040000F3C0A01013549080AAC890000ED
+:107730008CA80074AC8800043C07080090E73FD890
+:1077400030E5001050A00008AC8000083C0D800817
+:1077500035AC00808D8B0058AC8B00082484000C65
+:1077600003E00008008010210A0007B52484000C03
+:1077700027BDFFE83C098000AFB00010AFBF001488
+:107780003526098090C800092402000600A058216F
+:10779000310300FF35270900008080212405000403
+:1077A0001062007B2408000294CF005C3C0E0204AF
+:1077B00031EDFFFF01AE6025AE0C000090CA00085D
+:1077C00031440020108000080000000090C2004EEC
+:1077D0003C1F010337F90300305800FF031930251F
+:1077E00024050008AE06000490F9001190E600128E
+:1077F00090E40011333800FF0018708230CF00FF92
+:1078000001CF5021014B6821308900FF31AAFFFFD1
+:1078100039230028000A60801460002C020C4823E1
+:1078200090E400123C198000372F0100308C00FFDB
+:10783000018B1821000310800045F821001F8400EF
+:10784000360706FFAD270004373F090093EC00110F
+:1078500093EE0012372609800005C0828DE4000CEB
+:107860008CC5003431CD00FF01AB10210058182128
+:1078700000A4F8230008840000033F0000F0302536
+:1078800033F9FFFF318F00FC00D97025015820210A
+:1078900001E9682100045080ADAE000C0E00007CB0
+:1078A000012A80213C088008240B00043505008053
+:1078B0000E00007EA0AB0009020010218FBF001453
+:1078C0008FB0001003E0000827BD001890EC0011F5
+:1078D00090E300193C18080097183FCE318200FF52
+:1078E0000002F882307000FF001FCE0000103C0044
+:1078F0000327302500D870253C0F400001CF6825B4
+:107900003C198000AD2D0000373F090093EC0011B9
+:1079100093EE0012372F0100372609800005C08240
+:107920008DE4000C8CC5003431CD00FF01AB10217B
+:107930000058182100A4F8230008840000033F0029
+:1079400000F0302533F9FFFF318F00FC00D970259E
+:107950000158202101E9682100045080ADAE000CDF
+:107960000E00007C012A80213C088008240B0004C2
+:10797000350500800E00007EA0AB0009020010213A
+:107980008FBF00148FB0001003E0000827BD00185F
+:107990000A0007C72408001227BDFFD03C0380005F
+:1079A000AFB60028AFB50024AFB40020AFB10014CB
+:1079B000AFBF002CAFB3001CAFB20018AFB00010C7
+:1079C0003467010090E6000B309400FF30B500FFF3
+:1079D00030C200300000B021104000990000882122
+:1079E000346409809088000800082E0000051E03FA
+:1079F000046000C0240400048F8600543C01080089
+:107A0000A0243FD83C0C8000AD8000483C0480009E
+:107A1000348E010091CD000B31A5002010A000078D
+:107A20003C0780003493098092720008001286009F
+:107A300000107E0305E000C43C1F800834EC010008
+:107A4000918A000B34EB09809169000831440040B1
+:107A50000004402B3123000800C898231460000262
+:107A600024120003000090213C10800036180A8088
+:107A700036040900970E002C9083001190890012A3
+:107A800093050018307F00FF312800FF02481021C5
+:107A90000002C880930D0018033F782101F13021C6
+:107AA00030B100FF00D11821A78E00583C0108001A
+:107AB000A4263FCE3C010800A4233FD015A000021D
+:107AC000000000000000000D920B010B3065FFFF6D
+:107AD0003C010800A4233FD2316A00403C01080069
+:107AE000A4203FC83C010800A4203FC4114000026C
+:107AF00024A4000A24A4000B3091FFFF0E0001E72C
+:107B0000022020219206010B3C0C0800958C3FD2EC
+:107B1000004020210006698231A700010E00060105
+:107B20000187282100402021026028210E00060C38
+:107B3000024030210E0007A10040202116C000693C
+:107B4000004020219212010B3256004012C0000565
+:107B50003C0500FF8C93000034AEFFFF026E8024D2
+:107B6000AC9000000E0001FB022020213C0F080019
+:107B700091EF3FD831F10003122000163C1380082A
+:107B80008F8200543C09800835280080245F000162
+:107B9000AD1F003C3C0580088CB9000403E02021A7
+:107BA000033FC0231B000002AF9F00548CA40004BD
+:107BB0000E0006F8ACA400043C0780008CEB0074B7
+:107BC0003C04800834830080004B5021AC6A000CD8
+:107BD0003C138008367000800280202102A02821FA
+:107BE000A200006B0E00075D3C1480008F920054D1
+:107BF000368C0140AD92000C8F8600483C15100079
+:107C0000344D000624D60001AF9600488FBF002CEB
+:107C1000A18600128FB60028AD8D00148FB3001C12
+:107C2000AE9501788FB200188FB500248FB4002074
+:107C30008FB100148FB0001003E0000827BD0030A2
+:107C400034640980908F0008000F7600000E6E03E8
+:107C500005A00033347F090093F8001B241900109D
+:107C60003C010800A0393FD8331300021260FF67BF
+:107C70008F8600548F8200601446FF653C048000AC
+:107C80000E00007C000000003C0480083485008069
+:107C900090A8000924060016310300FF1066000DAD
+:107CA0000000000090AB00093C07080090E73FD8B7
+:107CB00024090008316400FF34EA00013C01080097
+:107CC000A02A3FD81089002F240C000A108C00280D
+:107CD0002402000C0E00007E000000000A00086074
+:107CE0008F8600540E0007B9024028210A0008AE12
+:107CF000004020213C0B8008356A00808D460054EE
+:107D00008CE9000C1120FF3DAF86005424070014BD
+:107D10003C010800A0273FD80A00085F3C0C800007
+:107D200090910008241200023C010800A0323FD8C4
+:107D3000323000201200000B241600018F86005400
+:107D40000A0008602411000837F800808F0200380C
+:107D5000AFE200048FF90004AF19003C0A00086C80
+:107D60003C0780008F8600540A000860241100043C
+:107D7000A0A200090E00007E000000000A000860BA
+:107D80008F860054240200140A00093AA0A20009B8
+:107D900027BDFFE8AFB000103C108000AFBF00145B
+:107DA00036020100904400090E00075D2405000121
+:107DB0003C0480089099000E34830080909F000F4F
+:107DC000906F00269089000A33F800FF00196E00BA
+:107DD0000018740031EC00FF01AE5025000C5A0071
+:107DE000014B3825312800FF36030140344560003F
+:107DF00000E830252402FF813C041000AC66000C32
+:107E00008FBF0014AC650014A0620012AE040178AC
+:107E10008FB0001003E0000827BD001827BDFFE861
+:107E2000308400FFAFBF00100E00075D30A500FFDB
+:107E30003C05800034A40140344700402406FF92F2
+:107E4000AC870014A08600128F8300548FBF0010EF
+:107E50003C02100027BD0018AC83000C03E00008B2
+:107E6000ACA2017827BDFFD8AFB00010308400FF6E
+:107E700030B000FF3C058000AFB10014AFBF002060
+:107E8000AFB3001CAFB20018000410C234A601004A
+:107E900032030002305100011460000790D2000943
+:107EA0003C098008353300809268000531070008DE
+:107EB00010E0000C308A0010024020210E000783E1
+:107EC00002202821240200018FBF00208FB3001C54
+:107ED0008FB200188FB100148FB0001003E00008BB
+:107EE00027BD00281540003434A50A008CB80024B2
+:107EF0008CAF0008130F004B000038213C0D8008A8
+:107F000035B30080926C006824060002318B00FFBC
+:107F1000116600843C06800034C201009263004C6C
+:107F200090590009307F00FF53F900043213007CA0
+:107F300010E00069000000003213007C5660005C15
+:107F40000240202116200009320D00013C0C800067
+:107F500035840100358B0A008D6500248C86000471
+:107F600014A6FFD900001021320D000111A0000E4F
+:107F7000024020213C188000371001008E0F000CB9
+:107F80008F8E005011EE0008000000000E00084324
+:107F9000022028218E19000C3C1F800837F0008039
+:107FA000AE190050024020210E0007710220282146
+:107FB0000A00098F240200013C0508008CA500641A
+:107FC00024A400013C010800AC2400641600000D4C
+:107FD00000000000022028210E000771024020212D
+:107FE000926E0068240C000231CD00FF11AC00221B
+:107FF000024020210E000941000000000A00098F04
+:10800000240200010E00007024040001926B002580
+:10801000020B30250E00007EA26600250A0009D35F
+:10802000022028218E6200188CDF00048CB9002405
+:1080300000021E0217F9FFB13065007F9268004C04
+:10804000264400013093007F12650040310300FF99
+:108050001464FFAB3C0D80082647000130F1007F1F
+:1080600030E200FF1225000B2407000100409021A0
+:108070000A00099C24110001240500040E000732A7
+:10808000240600010E000941000000000A00098FCB
+:10809000240200012405FF8002452024008590264B
+:1080A000324200FF004090210A00099C2411000187
+:1080B0000E000843022028213207003010E0FFA103
+:1080C00032100082024020210E0007830220282166
+:1080D0000A00098F240200018E6900180240202145
+:1080E00002202821012640250E000964AE680018F0
+:1080F0009264004C24050003240600010E000732A0
+:10810000308400FF0E0000702404000192710025ED
+:10811000021150250E00007EA26A00250A00098F78
+:10812000240200018E6F00183C18800002402021BC
+:1081300001F87025022028210E000771AE6E00188C
+:108140009264004C0A000A1B24050004324A008095
+:10815000394900801469FF6A3C0D80080A0009F45F
+:108160002647000127BDFFC0AFB000183C108000BB
+:10817000AFBF0038AFB70034AFB60030AFB5002C9A
+:10818000AFB40028AFB30024AFB200200E0005BE8C
+:10819000AFB1001C360201009045000B0E000976BD
+:1081A00090440008144000E78FBF00383C08800866
+:1081B00035070080A0E0006B3606098090C50000FE
+:1081C000240300503C17080026F73F9030A400FF1E
+:1081D0003C13080026733FA0108300033C1080006E
+:1081E0000000B82100009821241F00103611010062
+:1081F00036120A00361509808E5800248E34000489
+:108200008EAF00208F8C00543C010800A03F3FD867
+:1082100036190A80972B002C8EF60000932A00183E
+:108220000298702301EC68233C010800AC2E3FB497
+:108230003C010800AC2D3FB83C010800AC2C3FDCF1
+:10824000A78B005802C0F809315400FF30490002E2
+:10825000152000E930420001504000C49227000977
+:1082600092A9000831280008150000022415000317
+:108270000000A8213C0A80003543090035440A006B
+:108280008C8D00249072001190700012907F00116C
+:10829000325900FF321100FF02B110210002C080EC
+:1082A00033EF00FF0319B021028F702102D4602147
+:1082B00025CB00103C010800A4363FCE3C0108004D
+:1082C000AC2D3FE03C010800A42C3FD03C0108004D
+:1082D000A42B3FCC355601003554098035510E0092
+:1082E0008F8700548F89005C8E850020240800064B
+:1082F000012730233C010800AC283FD400A72823E5
+:1083000004C000B50000902104A000B300C5502BAC
+:10831000114000B5000000003C010800AC263FB849
+:108320008E6200000040F8090000000030460002A4
+:1083300014C0007400408021304B000155600011D2
+:108340008E6200043C0D08008DAD3FBC3C0EC000A9
+:108350003C04800001AE6025AE2C00008C9800002B
+:10836000330F000811E0FFFD00000000963F0008F9
+:1083700024120001A79F00408E390004AF990038F5
+:108380008E6200040040F80900000000020280250F
+:1083900032030002146000B3000000003C09080032
+:1083A00095293FC43C06080094C63FD03C0A08000B
+:1083B000954A3FC63C0708008CE73FBC0126702168
+:1083C0003C0308008C633FE03C08080095083FDA56
+:1083D00001CA20218ED9000C00E92821249F000227
+:1083E00000A878210067C02133E4FFFFAF99005057
+:1083F0003C010800AC383FE03C010800A42F3FC816
+:108400003C010800A42E3FD20E0001E7000000004E
+:108410008F8D0048004020213C010800A02D3FD94D
+:108420008E62000825AC0001AF8C00480040F809BE
+:10843000000000008F85005402A030210E00060CC1
+:10844000004020210E0007A1004020218E6B000C6F
+:108450000160F809004020213C0A0800954A3FD2FB
+:108460003C06080094C63FC6014648212528000264
+:108470000E0001FB3104FFFF3C0508008CA53FB452
+:108480003C0708008CE73FBC00A720233C01080004
+:10849000AC243FB414800006000000003C02080039
+:1084A0008C423FD4344B00403C010800AC2B3FD4FD
+:1084B000124000438F8E00448E2D00108F92004496
+:1084C000AE4D00208E2C0018AE4C00243C04080059
+:1084D00094843FC80E0006FA000000008F9F0054ED
+:1084E0008E6700103C010800AC3F3FDC00E0F8095B
+:1084F000000000003C1908008F393FB41720FF79B5
+:108500008F870054979300583C11800E321601005B
+:108510000E000729A633002C16C0004532030010B8
+:108520005460004C8EE50004320800405500001DE8
+:108530008EF000088EE4000C0080F80900000000B6
+:108540008FBF00388FB700348FB600308FB5002C46
+:108550008FB400288FB300248FB200208FB1001C8D
+:108560008FB0001803E0000827BD00408F86003C54
+:1085700036110E0000072E0000A62025AE04008054
+:108580008E4300208E500024AFA30010AE230014B1
+:108590008FB20010AE320010AE30001C0A000A7517
+:1085A000AE3000180200F809000000008EE4000C54
+:1085B0000080F809000000000A000B2E8FBF003871
+:1085C00024180001240F0001A5C00020A5D8002216
+:1085D0000A000B10ADCF00243C010800AC203FB8CE
+:1085E0000A000AA68E6200003C010800AC253FB8D4
+:1085F0000A000AA68E620000922400090E0007718C
+:10860000000028218FBF00388FB700348FB60030AC
+:108610008FB5002C8FB400288FB300248FB20020B8
+:108620008FB1001C8FB0001803E0000827BD004088
+:108630003C14800092950109000028210E00084397
+:1086400032A400FF320300105060FFB8320800402F
+:108650008EE5000400A0F809000000000A000B28C5
+:10866000320800405240FFA8979300588E340014FF
+:108670008F930044AE7400208E35001CAE7500242C
+:108680000A000B1F979300588F820014000421806A
+:1086900003E00008008210213C07800834E20080DB
+:1086A0009043006900804021106000093C040100F3
+:1086B0003C0708008CE73FDC8F83003000E3202379
+:1086C000048000089389001C14E3000301002021AA
+:1086D00003E00008008010213C04010003E00008D2
+:1086E000008010211120000B006738233C0D800012
+:1086F00035AC0980918B007C316A0002114000206A
+:108700002409003400E9702B15C0FFF1010020217D
+:1087100000E938232403FFFC00A3C82400E3C0249D
+:1087200000F9782B15E0FFEA0308202130C400038C
+:108730000004102314C0001430490003000030214D
+:1087400000A9782101E6702100EE682B11A0FFE05E
+:108750003C0401002D3800010006C82B010548210A
+:108760000319382414E0FFDA2524FFFC2402FFFC5F
+:1087700000A218240068202103E0000800801021D6
+:108780000A000B9E240900303C0C800035860980CD
+:1087900090CB007C316A00041540FFE924060004F8
+:1087A0000A000BAD000030213C0308008C63005C24
+:1087B0008F82001827BDFFE0AFBF0018AFB10014D3
+:1087C00010620005AFB00010000329C024A402808D
+:1087D000AF840014AF8300183C10800036020A00FA
+:1087E00094450032361101000E000B7F30A43FFF8C
+:1087F0008E240000241FFF803C1100800082C021D5
+:10880000031F60243309007F000CC9400329402561
+:10881000330E0078362F00033C0D1000010D50255B
+:1088200001CF5825AE0C002836080980AE0C080C84
+:10883000AE0B082CAE0A0830910300693C06800C90
+:108840000126382110600006AF8700348D09003CF6
+:108850008D03006C0123382318E000820000000023
+:108860003C0B8008356A00803C108000A140006904
+:10887000360609808CC200383C06800034C50A00E8
+:1088800090A8003C310C00201180001AAF8200300B
+:10889000240D00013C0E800035D10A00A38D001C80
+:1088A000AF8000248E2400248F850024240D00082E
+:1088B000AF800020AF8000283C010800A42D3FC6F7
+:1088C0003C010800A4203FDA0E000B830000302199
+:1088D0009228003C8FBF00188FB100148FB0001099
+:1088E00000086142AF82002C27BD002003E0000891
+:1088F0003182000190B80032240E0001330F00FFD6
+:10890000000F2182108E004124190002109900648A
+:1089100034C40AC03C03800034640A008C8F0024F5
+:1089200015E0001E34660900909F003024180005F1
+:1089300033F9003F1338004E240300018F860020D6
+:10894000A383001CAF860028AF8600243C0E800065
+:1089500035D10A008E2400248F850024240D0008C0
+:108960003C010800A42D3FC63C010800A4203FDACA
+:108970000E000B83000000009228003C8FBF0018FF
+:108980008FB100148FB0001000086142AF82002C3C
+:1089900027BD002003E00008318200018C8A000816
+:1089A0008C8B00248CD000643C0E800035D10A00F2
+:1089B000014B2823AF900024A380001CAF85002822
+:1089C0008E2400248F8600208F850024240D00082B
+:1089D0003C010800A42D3FC63C010800A4203FDA5A
+:1089E0000E000B83000000009228003C8FBF00188F
+:1089F0008FB100148FB0001000086142AF82002CCC
+:108A000027BD002003E000083182000190A2003061
+:108A10003051003F5224002834C50AC08CB00024D5
+:108A20001600002234CB09008CA600483C0A7FFFC8
+:108A30003545FFFF00C510243C0E8000AF820020AA
+:108A400035C509008F8800208CAD0060010D602BBA
+:108A500015800002010020218CA400600A000C2275
+:108A6000AF8400208D02006C0A000BFC3C068000E5
+:108A70008C8200488F8600203C097FFF3527FFFF4E
+:108A8000004788243C04800824030001AF9100289B
+:108A9000AC80006CA383001C0A000C30AF8600245D
+:108AA0008C9F00140A000C22AF9F00208D6200688A
+:108AB0000A000C6C3C0E800034C409808C89007064
+:108AC0008CA300140123382B10E0000400000000E8
+:108AD0008C8200700A000C6C3C0E80008CA200148A
+:108AE0000A000C6C3C0E80008F85002427BDFFE03F
+:108AF000AFBF0018AFB1001414A00008AFB0001051
+:108B00003C04800034870A0090E60030240200050F
+:108B100030C3003F106200B9348409008F910020F7
+:108B200000A080213C048000348E0A008DCD00041A
+:108B30003C0608008CC63FB831A73FFF00E6602B1B
+:108B40005580000100E03021938F001C11E0007877
+:108B500000D0282B349F098093F9007C3338000221
+:108B6000130000792403003400C3102B144000D9F3
+:108B70000000000000C3302300D0282B3C01080077
+:108B8000A4233FC414A0006E020018213C04080076
+:108B90008C843FB40064402B55000001006020210C
+:108BA0003C05800034A90A00912A003C3C010800E1
+:108BB000AC243FBC31430020146000030000482176
+:108BC00034AB0E008D6900188F88002C0128202BF3
+:108BD0001080005F000000003C0508008CA53FBC31
+:108BE00000A96821010D602B1180005C00B0702B82
+:108BF0000109382300E028213C010800AC273FBCD4
+:108C000012000003240AFFFC10B0008D3224000380
+:108C100000AA18243C010800A4203FDA3C01080007
+:108C2000AC233FBC006028218F840024120400067E
+:108C30003C0B80088D6C006C02002021AF9100205D
+:108C400025900001AD70006C8F8D00280085882371
+:108C5000AF91002401A52023AF8400281220000238
+:108C600024070018240700103C18800837060080ED
+:108C700090CF00683C010800A0273FD824070001DE
+:108C800031EE00FF11C700470000000014800018FB
+:108C9000000028213C06800034D1098034CD010039
+:108CA00091A600098E2C001824C40001000C860235
+:108CB0003205007F308B007F1165007F2407FF8025
+:108CC0003C19800837290080A124004C3C0808008A
+:108CD0008D083FD4241800023C010800A038401938
+:108CE000350F00083C010800AC2F3FD424050010CC
+:108CF0003C02800034440A009083003C307F002016
+:108D000013E0000500A02021240A00013C01080016
+:108D1000AC2A3FBC34A400018FBF00188FB10014EF
+:108D20008FB000100080102103E0000827BD002054
+:108D30003C010800A4203FC410A0FF9402001821A9
+:108D40000A000CC000C018210A000CB72403003030
+:108D50003C0508008CA53FBC00B0702B11C0FFA8DB
+:108D6000000000003C19080097393FC40325C021CA
+:108D70000307782B11E000072CAA00043C036000D5
+:108D80008C625404305F003F17E0FFE3240400428C
+:108D90002CAA00041140FF9A240400420A000D246A
+:108DA0008FBF00181528FFB9000000008CCA0018FA
+:108DB0003C1F800024020002015F1825ACC300188C
+:108DC00037F90A00A0C200689329003C240400047B
+:108DD00000A01021312800203C010800A0244019E7
+:108DE0001100000224050010240200013C010800CB
+:108DF000AC223FB40A000D1A3C0280008F88002884
+:108E00008C8900600109282B14A000020100882130
+:108E10008C9100603C048000348B0E008D6400183F
+:108E2000240A00010220282102203021A38A001CEC
+:108E30000E000B83022080210A000CA6AF82002CBA
+:108E40000004582312200007316400033C0E800008
+:108E500035C7098090ED007C31AC00041580001905
+:108E6000248F00043C010800A4243FDA3C1F0800C2
+:108E700097FF3FDA03E5C82100D9C02B1300FF6B31
+:108E80008F8400242CA6000514C0FFA324040042F4
+:108E900030A200031440000200A2182324A3FFFC08
+:108EA0003C010800AC233FBC3C010800A4203FDA91
+:108EB0000A000CE70060282100C770240A000D0D8D
+:108EC00001C720263C010800A42F3FDA0A000D78D4
+:108ED000000000003C010800AC203FBC0A000D234C
+:108EE000240400428F8300283C05800034AA0A0035
+:108EF0001460000600001021914700302406000590
+:108F000030E400FF108600030000000003E00008CA
+:108F100000000000914B0048316900FF000941C288
+:108F20001500FFFA3C0680083C04080094843FC406
+:108F30003C0308008C633FDC3C1908008F393FBCC0
+:108F40003C0F080095EF3FDA0064C0218CCD00048F
+:108F50000319702101CF602134AB0E00018D28234D
+:108F600018A0001D00000000914F004C8F8C0034B1
+:108F7000956D001031EE00FF8D89000401AE3023A5
+:108F80008D8A000030CEFFFF000E29000125C82188
+:108F900000003821014720210325182B0083C02120
+:108FA000AD990004AD980000918F000A01CF6821AF
+:108FB000A18D000A956500128F8A0034A54500082E
+:108FC000954B003825690001A54900389148000DEE
+:108FD00035070008A147000D03E00008000000006D
+:108FE00027BDFFD8AFB000189388001C8FB00014C5
+:108FF0003C0A80003C197FFF8F8700243738FFFF31
+:10900000AFBF0020AFB1001C355F0A000218182462
+:1090100093EB003C00087FC03C02BFFF006F60255F
+:109020002CF000013449FFFF3C1F08008FFF3FDC9C
+:109030008F9900303C18080097183FD20189782496
+:10904000001047803C07EFFF3C05F0FF01E81825C2
+:109050003C1180003169002034E2FFFF34ADFFFF96
+:10906000362E098027A500102406000203F960238C
+:10907000270B0002354A0E00006218240080802170
+:1090800015200002000040218D48001CA7AB0012F3
+:10909000058000392407000030E800FF00083F0089
+:1090A000006758253C028008AFAB0014344F0080A5
+:1090B00091EA00683C08080091083FD93C09DFFFAD
+:1090C000352CFFFF000AF82B3C02080094423FCCED
+:1090D000A3A80011016CC024001FCF40031918255C
+:1090E0008FA70010AFA300143C0C0800918C3FDB4D
+:1090F000A7A200168FAB001400ED48243C0F01001E
+:109100003C0A0FFF012FC82531980003355FFFFF90
+:10911000016D40243C027000033F382400181E00FB
+:1091200000E2482501037825AFAF0014AFA9001075
+:1091300091CC007C0E000092A3AC0015362D0A00E5
+:1091400091A6003C30C400201080000626020008D2
+:109150003C11080096313FC8262EFFFF3C01080055
+:10916000A42E3FC88FBF00208FB1001C8FB0001805
+:1091700003E0000827BD00288F8B002C010B502B2B
+:109180005540FFC5240700010A000E0430E800FF27
+:109190009383001C3C02800027BDFFD834480A009E
+:1091A00000805021AFBF002034460AC001002821B2
+:1091B0001060000E3444098091070030240B000534
+:1091C0008F89002030EC003F118B000B000038210C
+:1091D000AFA900103C0B80088D69006CAFAA001885
+:1091E0000E00015AAFA90014A380001C8FBF0020FD
+:1091F00003E0000827BD00288D1F00483C18080028
+:109200008F183FBC8F9900283C027FFF8D080044D7
+:109210003443FFFFAFA900103C0B80088D69006C40
+:1092200003E370240319782101CF682301A83821B2
+:10923000AFAA00180E00015AAFA900140A000E5878
+:10924000A380001C3C05800034A60A0090C7003CA7
+:109250003C06080094C63FDA3C0208008C423FD42A
+:1092600030E30020000624001060001E0044382572
+:109270003C0880083505008090A300680000482164
+:109280002408000100002821240400013C0680007D
+:109290008CCD017805A0FFFE34CF0140ADE8000879
+:1092A0003C0208008C423FDCA5E50004A5E4000672
+:1092B000ADE2000C3C04080090843FD93C038008D8
+:1092C00034790080A1E40012ADE70014A5E900188C
+:1092D0009338004C3C0E1000A1F8002D03E000086C
+:1092E000ACCE017834A90E008D28001C3C0C08007F
+:1092F0008D8C3FBC952B0016952A001401864821C1
+:109300003164FFFF0A000E803145FFFF3C048000FE
+:1093100034830A009065003C30A200201040001900
+:1093200034870E0000004021000038210000202179
+:109330003C0680008CC901780520FFFE34CA01403C
+:1093400034CF010091EB0009AD4800083C0E080045
+:109350008DCE3FDC240DFF91240C00403C08100012
+:10936000A5440004A5470006AD4E000CA14D001217
+:10937000AD4C0014A5400018A14B002D03E00008DF
+:10938000ACC801788CE8001894E6001294E4001050
+:1093900030C7FFFF0A000EA93084FFFF3C048000A5
+:1093A00034830A009065003C30A200201040002762
+:1093B00027BDFFF82409000100003821240800011E
+:1093C0003C0680008CCA01780540FFFE3C0280FF0D
+:1093D00034C40100908D00093C0C0800918C4019A8
+:1093E000A3AD00038FAB00003185007F3459FFFF30
+:1093F00001665025AFAA00009083000AA3A00002D6
+:1094000000057E00A3A300018FB8000034CB01400B
+:10941000240C30000319702401CF6825AD6D000CB9
+:1094200027BD0008AD6C0014A5600018AD690008E8
+:10943000A56700042409FF80A56800063C08100009
+:10944000A169001203E00008ACC8017834870E005F
+:109450008CE9001894E6001294E4001030C8FFFF75
+:109460000A000ECD3087FFFF27BDFFE0AFB100142B
+:109470003C118000AFB00010AFBF001836380A00B2
+:10948000970F0032363001000E000B7F31E43FFFB2
+:109490008E0E0000240DFF803C04200001C25821E4
+:1094A000016D6024000C4940316A007F012A40258B
+:1094B000010438253C048008AE270830348600803B
+:1094C00090C500682403000230A200FF104300048E
+:1094D0008F9F00208F990024AC9F0068AC99006496
+:1094E0008FBF00188FB100148FB0001003E0000888
+:1094F00027BD00203C0A0800254A3A803C090800A4
+:1095000025293B103C08080025082F1C3C070800B3
+:1095100024E73BDC3C06080024C639043C0508006F
+:1095200024A536583C0408002484325C3C0308001F
+:10953000246339B83C020800244237543C01080037
+:10954000AC2A3F983C010800AC293F943C0108003C
+:10955000AC283F903C010800AC273F9C3C01080030
+:10956000AC263FAC3C010800AC253FA43C01080000
+:10957000AC243FA03C010800AC233FB03C010800F4
+:0C958000AC223FA803E00008000000003F
+:04958C008000094012
+:109590008000090080080100800800808008000029
+:1095A000800E0000800800808008000080000A8093
+:0C95B00080000A00800009808000090093
+:00000001FF
+/*
+ * This file contains firmware data derived from proprietary unpublished
+ * source code, Copyright (c) 2004 - 2009 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware data
+ * in hexadecimal or equivalent format, provided this copyright notice is
+ * accompanying it.
+ */
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 02a2cf6..33aa116 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -21,8 +21,8 @@
 #include <linux/posix_acl_xattr.h>
 #include "xattr.h"
 #include "acl.h"
-#include "v9fs_vfs.h"
 #include "v9fs.h"
+#include "v9fs_vfs.h"
 
 static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
 {
@@ -59,7 +59,8 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
 	struct v9fs_session_info *v9ses;
 
 	v9ses = v9fs_inode2v9ses(inode);
-	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
+	if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) ||
+			((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {
 		set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL);
 		set_cached_acl(inode, ACL_TYPE_ACCESS, NULL);
 		return 0;
@@ -71,11 +72,15 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
 	if (!IS_ERR(dacl) && !IS_ERR(pacl)) {
 		set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl);
 		set_cached_acl(inode, ACL_TYPE_ACCESS, pacl);
-		posix_acl_release(dacl);
-		posix_acl_release(pacl);
 	} else
 		retval = -EIO;
 
+	if (!IS_ERR(dacl))
+		posix_acl_release(dacl);
+
+	if (!IS_ERR(pacl))
+		posix_acl_release(pacl);
+
 	return retval;
 }
 
@@ -100,9 +105,10 @@ int v9fs_check_acl(struct inode *inode, int mask, unsigned int flags)
 		return -ECHILD;
 
 	v9ses = v9fs_inode2v9ses(inode);
-	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) {
+	if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) ||
+			((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) {
 		/*
-		 * On access = client mode get the acl
+		 * On access = client  and acl = on mode get the acl
 		 * values from the server
 		 */
 		return 0;
@@ -128,6 +134,10 @@ static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl)
 	struct inode *inode = dentry->d_inode;
 
 	set_cached_acl(inode, type, acl);
+
+	if (!acl)
+		return 0;
+
 	/* Set a setxattr request to server */
 	size = posix_acl_xattr_size(acl->a_count);
 	buffer = kmalloc(size, GFP_KERNEL);
@@ -177,10 +187,8 @@ int v9fs_acl_chmod(struct dentry *dentry)
 int v9fs_set_create_acl(struct dentry *dentry,
 			struct posix_acl *dpacl, struct posix_acl *pacl)
 {
-	if (dpacl)
-		v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl);
-	if (pacl)
-		v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl);
+	v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl);
+	v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl);
 	posix_acl_release(dpacl);
 	posix_acl_release(pacl);
 	return 0;
@@ -254,7 +262,7 @@ static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	/*
 	 * We allow set/get/list of acl when access=client is not specified
 	 */
@@ -304,7 +312,7 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
 	if (strcmp(name, "") != 0)
 		return -EINVAL;
 
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	/*
 	 * set the attribute on the remote. Without even looking at the
 	 * xattr value. We leave it to the server to validate
diff --git a/fs/9p/cache.c b/fs/9p/cache.c
index 0dbe0d1..5b335c5 100644
--- a/fs/9p/cache.c
+++ b/fs/9p/cache.c
@@ -33,67 +33,11 @@
 
 #define CACHETAG_LEN  11
 
-struct kmem_cache *vcookie_cache;
-
 struct fscache_netfs v9fs_cache_netfs = {
 	.name 		= "9p",
 	.version 	= 0,
 };
 
-static void init_once(void *foo)
-{
-	struct v9fs_cookie *vcookie = (struct v9fs_cookie *) foo;
-	vcookie->fscache = NULL;
-	vcookie->qid = NULL;
-	inode_init_once(&vcookie->inode);
-}
-
-/**
- * v9fs_init_vcookiecache - initialize a cache for vcookies to maintain
- *			    vcookie to inode mapping
- *
- * Returns 0 on success.
- */
-
-static int v9fs_init_vcookiecache(void)
-{
-	vcookie_cache = kmem_cache_create("vcookie_cache",
-					  sizeof(struct v9fs_cookie),
-					  0, (SLAB_RECLAIM_ACCOUNT|
-					      SLAB_MEM_SPREAD),
-					  init_once);
-	if (!vcookie_cache)
-		return -ENOMEM;
-
-	return 0;
-}
-
-/**
- * v9fs_destroy_vcookiecache - destroy the cache of vcookies
- *
- */
-
-static void v9fs_destroy_vcookiecache(void)
-{
-	kmem_cache_destroy(vcookie_cache);
-}
-
-int __v9fs_cache_register(void)
-{
-	int ret;
-	ret = v9fs_init_vcookiecache();
-	if (ret < 0)
-		return ret;
-
-	return fscache_register_netfs(&v9fs_cache_netfs);
-}
-
-void __v9fs_cache_unregister(void)
-{
-	v9fs_destroy_vcookiecache();
-	fscache_unregister_netfs(&v9fs_cache_netfs);
-}
-
 /**
  * v9fs_random_cachetag - Generate a random tag to be associated
  *			  with a new cache session.
@@ -133,9 +77,9 @@ static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data,
 }
 
 const struct fscache_cookie_def v9fs_cache_session_index_def = {
-	.name 		= "9P.session",
-	.type 		= FSCACHE_COOKIE_TYPE_INDEX,
-	.get_key 	= v9fs_cache_session_get_key,
+	.name		= "9P.session",
+	.type		= FSCACHE_COOKIE_TYPE_INDEX,
+	.get_key	= v9fs_cache_session_get_key,
 };
 
 void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses)
@@ -163,33 +107,33 @@ void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses)
 static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data,
 					 void *buffer, uint16_t bufmax)
 {
-	const struct v9fs_cookie *vcookie = cookie_netfs_data;
-	memcpy(buffer, &vcookie->qid->path, sizeof(vcookie->qid->path));
-
-	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &vcookie->inode,
-		   vcookie->qid->path);
-	return sizeof(vcookie->qid->path);
+	const struct v9fs_inode *v9inode = cookie_netfs_data;
+	memcpy(buffer, &v9inode->fscache_key->path,
+	       sizeof(v9inode->fscache_key->path));
+	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get key %llu", &v9inode->vfs_inode,
+		   v9inode->fscache_key->path);
+	return sizeof(v9inode->fscache_key->path);
 }
 
 static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data,
 				      uint64_t *size)
 {
-	const struct v9fs_cookie *vcookie = cookie_netfs_data;
-	*size = i_size_read(&vcookie->inode);
+	const struct v9fs_inode *v9inode = cookie_netfs_data;
+	*size = i_size_read(&v9inode->vfs_inode);
 
-	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get attr %llu", &vcookie->inode,
+	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get attr %llu", &v9inode->vfs_inode,
 		   *size);
 }
 
 static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data,
 					 void *buffer, uint16_t buflen)
 {
-	const struct v9fs_cookie *vcookie = cookie_netfs_data;
-	memcpy(buffer, &vcookie->qid->version, sizeof(vcookie->qid->version));
-
-	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &vcookie->inode,
-		   vcookie->qid->version);
-	return sizeof(vcookie->qid->version);
+	const struct v9fs_inode *v9inode = cookie_netfs_data;
+	memcpy(buffer, &v9inode->fscache_key->version,
+	       sizeof(v9inode->fscache_key->version));
+	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get aux %u", &v9inode->vfs_inode,
+		   v9inode->fscache_key->version);
+	return sizeof(v9inode->fscache_key->version);
 }
 
 static enum
@@ -197,13 +141,13 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
 					    const void *buffer,
 					    uint16_t buflen)
 {
-	const struct v9fs_cookie *vcookie = cookie_netfs_data;
+	const struct v9fs_inode *v9inode = cookie_netfs_data;
 
-	if (buflen != sizeof(vcookie->qid->version))
+	if (buflen != sizeof(v9inode->fscache_key->version))
 		return FSCACHE_CHECKAUX_OBSOLETE;
 
-	if (memcmp(buffer, &vcookie->qid->version,
-		   sizeof(vcookie->qid->version)))
+	if (memcmp(buffer, &v9inode->fscache_key->version,
+		   sizeof(v9inode->fscache_key->version)))
 		return FSCACHE_CHECKAUX_OBSOLETE;
 
 	return FSCACHE_CHECKAUX_OKAY;
@@ -211,7 +155,7 @@ fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data,
 
 static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data)
 {
-	struct v9fs_cookie *vcookie = cookie_netfs_data;
+	struct v9fs_inode *v9inode = cookie_netfs_data;
 	struct pagevec pvec;
 	pgoff_t first;
 	int loop, nr_pages;
@@ -220,7 +164,7 @@ static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data)
 	first = 0;
 
 	for (;;) {
-		nr_pages = pagevec_lookup(&pvec, vcookie->inode.i_mapping,
+		nr_pages = pagevec_lookup(&pvec, v9inode->vfs_inode.i_mapping,
 					  first,
 					  PAGEVEC_SIZE - pagevec_count(&pvec));
 		if (!nr_pages)
@@ -249,115 +193,114 @@ const struct fscache_cookie_def v9fs_cache_inode_index_def = {
 
 void v9fs_cache_inode_get_cookie(struct inode *inode)
 {
-	struct v9fs_cookie *vcookie;
+	struct v9fs_inode *v9inode;
 	struct v9fs_session_info *v9ses;
 
 	if (!S_ISREG(inode->i_mode))
 		return;
 
-	vcookie = v9fs_inode2cookie(inode);
-	if (vcookie->fscache)
+	v9inode = V9FS_I(inode);
+	if (v9inode->fscache)
 		return;
 
 	v9ses = v9fs_inode2v9ses(inode);
-	vcookie->fscache = fscache_acquire_cookie(v9ses->fscache,
+	v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
 						  &v9fs_cache_inode_index_def,
-						  vcookie);
+						  v9inode);
 
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p get cookie %p", inode,
-		   vcookie->fscache);
+		   v9inode->fscache);
 }
 
 void v9fs_cache_inode_put_cookie(struct inode *inode)
 {
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	if (!vcookie->fscache)
+	if (!v9inode->fscache)
 		return;
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p put cookie %p", inode,
-		   vcookie->fscache);
+		   v9inode->fscache);
 
-	fscache_relinquish_cookie(vcookie->fscache, 0);
-	vcookie->fscache = NULL;
+	fscache_relinquish_cookie(v9inode->fscache, 0);
+	v9inode->fscache = NULL;
 }
 
 void v9fs_cache_inode_flush_cookie(struct inode *inode)
 {
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	if (!vcookie->fscache)
+	if (!v9inode->fscache)
 		return;
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p flush cookie %p", inode,
-		   vcookie->fscache);
+		   v9inode->fscache);
 
-	fscache_relinquish_cookie(vcookie->fscache, 1);
-	vcookie->fscache = NULL;
+	fscache_relinquish_cookie(v9inode->fscache, 1);
+	v9inode->fscache = NULL;
 }
 
 void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp)
 {
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 	struct p9_fid *fid;
 
-	if (!vcookie->fscache)
+	if (!v9inode->fscache)
 		return;
 
-	spin_lock(&vcookie->lock);
+	spin_lock(&v9inode->fscache_lock);
 	fid = filp->private_data;
 	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
 		v9fs_cache_inode_flush_cookie(inode);
 	else
 		v9fs_cache_inode_get_cookie(inode);
 
-	spin_unlock(&vcookie->lock);
+	spin_unlock(&v9inode->fscache_lock);
 }
 
 void v9fs_cache_inode_reset_cookie(struct inode *inode)
 {
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 	struct v9fs_session_info *v9ses;
 	struct fscache_cookie *old;
 
-	if (!vcookie->fscache)
+	if (!v9inode->fscache)
 		return;
 
-	old = vcookie->fscache;
+	old = v9inode->fscache;
 
-	spin_lock(&vcookie->lock);
-	fscache_relinquish_cookie(vcookie->fscache, 1);
+	spin_lock(&v9inode->fscache_lock);
+	fscache_relinquish_cookie(v9inode->fscache, 1);
 
 	v9ses = v9fs_inode2v9ses(inode);
-	vcookie->fscache = fscache_acquire_cookie(v9ses->fscache,
+	v9inode->fscache = fscache_acquire_cookie(v9ses->fscache,
 						  &v9fs_cache_inode_index_def,
-						  vcookie);
-
+						  v9inode);
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p",
-		   inode, old, vcookie->fscache);
+		   inode, old, v9inode->fscache);
 
-	spin_unlock(&vcookie->lock);
+	spin_unlock(&v9inode->fscache_lock);
 }
 
 int __v9fs_fscache_release_page(struct page *page, gfp_t gfp)
 {
 	struct inode *inode = page->mapping->host;
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	BUG_ON(!vcookie->fscache);
+	BUG_ON(!v9inode->fscache);
 
-	return fscache_maybe_release_page(vcookie->fscache, page, gfp);
+	return fscache_maybe_release_page(v9inode->fscache, page, gfp);
 }
 
 void __v9fs_fscache_invalidate_page(struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 
-	BUG_ON(!vcookie->fscache);
+	BUG_ON(!v9inode->fscache);
 
 	if (PageFsCache(page)) {
-		fscache_wait_on_page_write(vcookie->fscache, page);
+		fscache_wait_on_page_write(v9inode->fscache, page);
 		BUG_ON(!PageLocked(page));
-		fscache_uncache_page(vcookie->fscache, page);
+		fscache_uncache_page(v9inode->fscache, page);
 	}
 }
 
@@ -380,13 +323,13 @@ static void v9fs_vfs_readpage_complete(struct page *page, void *data,
 int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page)
 {
 	int ret;
-	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	const struct v9fs_inode *v9inode = V9FS_I(inode);
 
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page);
-	if (!vcookie->fscache)
+	if (!v9inode->fscache)
 		return -ENOBUFS;
 
-	ret = fscache_read_or_alloc_page(vcookie->fscache,
+	ret = fscache_read_or_alloc_page(v9inode->fscache,
 					 page,
 					 v9fs_vfs_readpage_complete,
 					 NULL,
@@ -418,13 +361,13 @@ int __v9fs_readpages_from_fscache(struct inode *inode,
 				  unsigned *nr_pages)
 {
 	int ret;
-	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	const struct v9fs_inode *v9inode = V9FS_I(inode);
 
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p pages %u", inode, *nr_pages);
-	if (!vcookie->fscache)
+	if (!v9inode->fscache)
 		return -ENOBUFS;
 
-	ret = fscache_read_or_alloc_pages(vcookie->fscache,
+	ret = fscache_read_or_alloc_pages(v9inode->fscache,
 					  mapping, pages, nr_pages,
 					  v9fs_vfs_readpage_complete,
 					  NULL,
@@ -453,11 +396,22 @@ int __v9fs_readpages_from_fscache(struct inode *inode,
 void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page)
 {
 	int ret;
-	const struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
+	const struct v9fs_inode *v9inode = V9FS_I(inode);
 
 	P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page);
-	ret = fscache_write_page(vcookie->fscache, page, GFP_KERNEL);
+	ret = fscache_write_page(v9inode->fscache, page, GFP_KERNEL);
 	P9_DPRINTK(P9_DEBUG_FSC, "ret =  %d", ret);
 	if (ret != 0)
 		v9fs_uncache_page(inode, page);
 }
+
+/*
+ * wait for a page to complete writing to the cache
+ */
+void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
+{
+	const struct v9fs_inode *v9inode = V9FS_I(inode);
+	P9_DPRINTK(P9_DEBUG_FSC, "inode %p page %p", inode, page);
+	if (PageFsCache(page))
+		fscache_wait_on_page_write(v9inode->fscache, page);
+}
diff --git a/fs/9p/cache.h b/fs/9p/cache.h
index a94192b..049507a 100644
--- a/fs/9p/cache.h
+++ b/fs/9p/cache.h
@@ -25,20 +25,6 @@
 #include <linux/fscache.h>
 #include <linux/spinlock.h>
 
-extern struct kmem_cache *vcookie_cache;
-
-struct v9fs_cookie {
-	spinlock_t lock;
-	struct inode inode;
-	struct fscache_cookie *fscache;
-	struct p9_qid *qid;
-};
-
-static inline struct v9fs_cookie *v9fs_inode2cookie(const struct inode *inode)
-{
-	return container_of(inode, struct v9fs_cookie, inode);
-}
-
 extern struct fscache_netfs v9fs_cache_netfs;
 extern const struct fscache_cookie_def v9fs_cache_session_index_def;
 extern const struct fscache_cookie_def v9fs_cache_inode_index_def;
@@ -64,23 +50,8 @@ extern int __v9fs_readpages_from_fscache(struct inode *inode,
 					 struct list_head *pages,
 					 unsigned *nr_pages);
 extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page);
-
-
-/**
- * v9fs_cache_register - Register v9fs file system with the cache
- */
-static inline int v9fs_cache_register(void)
-{
-	return __v9fs_cache_register();
-}
-
-/**
- * v9fs_cache_unregister - Unregister v9fs from the cache
- */
-static inline void v9fs_cache_unregister(void)
-{
-	__v9fs_cache_unregister();
-}
+extern void __v9fs_fscache_wait_on_page_write(struct inode *inode,
+					      struct page *page);
 
 static inline int v9fs_fscache_release_page(struct page *page,
 					    gfp_t gfp)
@@ -117,28 +88,27 @@ static inline void v9fs_readpage_to_fscache(struct inode *inode,
 
 static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
 {
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
-	fscache_uncache_page(vcookie->fscache, page);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+	fscache_uncache_page(v9inode->fscache, page);
 	BUG_ON(PageFsCache(page));
 }
 
-static inline void v9fs_vcookie_set_qid(struct inode *inode,
+static inline void v9fs_fscache_set_key(struct inode *inode,
 					struct p9_qid *qid)
 {
-	struct v9fs_cookie *vcookie = v9fs_inode2cookie(inode);
-	spin_lock(&vcookie->lock);
-	vcookie->qid = qid;
-	spin_unlock(&vcookie->lock);
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+	spin_lock(&v9inode->fscache_lock);
+	v9inode->fscache_key = qid;
+	spin_unlock(&v9inode->fscache_lock);
 }
 
-#else /* CONFIG_9P_FSCACHE */
-
-static inline int v9fs_cache_register(void)
+static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
+						   struct page *page)
 {
-	return 1;
+	return __v9fs_fscache_wait_on_page_write(inode, page);
 }
 
-static inline void v9fs_cache_unregister(void) {}
+#else /* CONFIG_9P_FSCACHE */
 
 static inline int v9fs_fscache_release_page(struct page *page,
 					    gfp_t gfp) {
@@ -168,9 +138,11 @@ static inline void v9fs_readpage_to_fscache(struct inode *inode,
 static inline void v9fs_uncache_page(struct inode *inode, struct page *page)
 {}
 
-static inline void v9fs_vcookie_set_qid(struct inode *inode,
-					struct p9_qid *qid)
-{}
+static inline void v9fs_fscache_wait_on_page_write(struct inode *inode,
+						   struct page *page)
+{
+	return;
+}
 
 #endif /* CONFIG_9P_FSCACHE */
 #endif /* _9P_CACHE_H */
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index b00223c..0ee5945 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -125,46 +125,17 @@ err_out:
 	return -ENOMEM;
 }
 
-/**
- * v9fs_fid_lookup - lookup for a fid, try to walk if not found
- * @dentry: dentry to look for fid in
- *
- * Look for a fid in the specified dentry for the current user.
- * If no fid is found, try to create one walking from a fid from the parent
- * dentry (if it has one), or the root dentry. If the user haven't accessed
- * the fs yet, attach now and walk from the root.
- */
-
-struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
+static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry,
+					       uid_t uid, int any)
 {
-	int i, n, l, clone, any, access;
-	u32 uid;
-	struct p9_fid *fid, *old_fid = NULL;
 	struct dentry *ds;
-	struct v9fs_session_info *v9ses;
 	char **wnames, *uname;
+	int i, n, l, clone, access;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *fid, *old_fid = NULL;
 
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	access = v9ses->flags & V9FS_ACCESS_MASK;
-	switch (access) {
-	case V9FS_ACCESS_SINGLE:
-	case V9FS_ACCESS_USER:
-	case V9FS_ACCESS_CLIENT:
-		uid = current_fsuid();
-		any = 0;
-		break;
-
-	case V9FS_ACCESS_ANY:
-		uid = v9ses->uid;
-		any = 1;
-		break;
-
-	default:
-		uid = ~0;
-		any = 0;
-		break;
-	}
-
 	fid = v9fs_fid_find(dentry, uid, any);
 	if (fid)
 		return fid;
@@ -250,6 +221,45 @@ err_out:
 	return fid;
 }
 
+/**
+ * v9fs_fid_lookup - lookup for a fid, try to walk if not found
+ * @dentry: dentry to look for fid in
+ *
+ * Look for a fid in the specified dentry for the current user.
+ * If no fid is found, try to create one walking from a fid from the parent
+ * dentry (if it has one), or the root dentry. If the user haven't accessed
+ * the fs yet, attach now and walk from the root.
+ */
+
+struct p9_fid *v9fs_fid_lookup(struct dentry *dentry)
+{
+	uid_t uid;
+	int  any, access;
+	struct v9fs_session_info *v9ses;
+
+	v9ses = v9fs_dentry2v9ses(dentry);
+	access = v9ses->flags & V9FS_ACCESS_MASK;
+	switch (access) {
+	case V9FS_ACCESS_SINGLE:
+	case V9FS_ACCESS_USER:
+	case V9FS_ACCESS_CLIENT:
+		uid = current_fsuid();
+		any = 0;
+		break;
+
+	case V9FS_ACCESS_ANY:
+		uid = v9ses->uid;
+		any = 1;
+		break;
+
+	default:
+		uid = ~0;
+		any = 0;
+		break;
+	}
+	return v9fs_fid_lookup_with_uid(dentry, uid, any);
+}
+
 struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 {
 	struct p9_fid *fid, *ret;
@@ -261,3 +271,50 @@ struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
 	ret = p9_client_walk(fid, 0, NULL, 1);
 	return ret;
 }
+
+static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, uid_t uid)
+{
+	struct p9_fid *fid, *ret;
+
+	fid = v9fs_fid_lookup_with_uid(dentry, uid, 0);
+	if (IS_ERR(fid))
+		return fid;
+
+	ret = p9_client_walk(fid, 0, NULL, 1);
+	return ret;
+}
+
+struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
+{
+	int err, flags;
+	struct p9_fid *fid;
+	struct v9fs_session_info *v9ses;
+
+	v9ses = v9fs_dentry2v9ses(dentry);
+	fid = v9fs_fid_clone_with_uid(dentry, 0);
+	if (IS_ERR(fid))
+		goto error_out;
+	/*
+	 * writeback fid will only be used to write back the
+	 * dirty pages. We always request for the open fid in read-write
+	 * mode so that a partial page write which result in page
+	 * read can work.
+	 *
+	 * we don't have a tsyncfs operation for older version
+	 * of protocol. So make sure the write back fid is
+	 * opened in O_SYNC mode.
+	 */
+	if (!v9fs_proto_dotl(v9ses))
+		flags = O_RDWR | O_SYNC;
+	else
+		flags = O_RDWR;
+
+	err = p9_client_open(fid, flags);
+	if (err < 0) {
+		p9_client_clunk(fid);
+		fid = ERR_PTR(err);
+		goto error_out;
+	}
+error_out:
+	return fid;
+}
diff --git a/fs/9p/fid.h b/fs/9p/fid.h
index c3bbd6a..bb0b6e7 100644
--- a/fs/9p/fid.h
+++ b/fs/9p/fid.h
@@ -19,7 +19,8 @@
  *  Boston, MA  02111-1301  USA
  *
  */
-
+#ifndef FS_9P_FID_H
+#define FS_9P_FID_H
 #include <linux/list.h>
 
 /**
@@ -45,3 +46,5 @@ struct v9fs_dentry {
 struct p9_fid *v9fs_fid_lookup(struct dentry *dentry);
 struct p9_fid *v9fs_fid_clone(struct dentry *dentry);
 int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid);
+struct p9_fid *v9fs_writeback_fid(struct dentry *dentry);
+#endif
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 2f77cd3..c82b017 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -39,6 +39,7 @@
 
 static DEFINE_SPINLOCK(v9fs_sessionlist_lock);
 static LIST_HEAD(v9fs_sessionlist);
+struct kmem_cache *v9fs_inode_cache;
 
 /*
  * Option Parsing (code inspired by NFS code)
@@ -55,7 +56,7 @@ enum {
 	/* Cache options */
 	Opt_cache_loose, Opt_fscache,
 	/* Access options */
-	Opt_access,
+	Opt_access, Opt_posixacl,
 	/* Error token */
 	Opt_err
 };
@@ -73,6 +74,7 @@ static const match_table_t tokens = {
 	{Opt_fscache, "fscache"},
 	{Opt_cachetag, "cachetag=%s"},
 	{Opt_access, "access=%s"},
+	{Opt_posixacl, "posixacl"},
 	{Opt_err, NULL}
 };
 
@@ -194,15 +196,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 			else if (strcmp(s, "any") == 0)
 				v9ses->flags |= V9FS_ACCESS_ANY;
 			else if (strcmp(s, "client") == 0) {
-#ifdef CONFIG_9P_FS_POSIX_ACL
 				v9ses->flags |= V9FS_ACCESS_CLIENT;
-#else
-				P9_DPRINTK(P9_DEBUG_ERROR,
-					"access=client option not supported\n");
-				kfree(s);
-				ret = -EINVAL;
-				goto free_and_return;
-#endif
 			} else {
 				v9ses->flags |= V9FS_ACCESS_SINGLE;
 				v9ses->uid = simple_strtoul(s, &e, 10);
@@ -212,6 +206,16 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts)
 			kfree(s);
 			break;
 
+		case Opt_posixacl:
+#ifdef CONFIG_9P_FS_POSIX_ACL
+			v9ses->flags |= V9FS_POSIX_ACL;
+#else
+			P9_DPRINTK(P9_DEBUG_ERROR,
+					"Not defined CONFIG_9P_FS_POSIX_ACL. "
+					"Ignoring posixacl option\n");
+#endif
+			break;
+
 		default:
 			continue;
 		}
@@ -260,19 +264,12 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 	list_add(&v9ses->slist, &v9fs_sessionlist);
 	spin_unlock(&v9fs_sessionlist_lock);
 
-	v9ses->flags = V9FS_ACCESS_USER;
 	strcpy(v9ses->uname, V9FS_DEFUSER);
 	strcpy(v9ses->aname, V9FS_DEFANAME);
 	v9ses->uid = ~0;
 	v9ses->dfltuid = V9FS_DEFUID;
 	v9ses->dfltgid = V9FS_DEFGID;
 
-	rc = v9fs_parse_options(v9ses, data);
-	if (rc < 0) {
-		retval = rc;
-		goto error;
-	}
-
 	v9ses->clnt = p9_client_create(dev_name, data);
 	if (IS_ERR(v9ses->clnt)) {
 		retval = PTR_ERR(v9ses->clnt);
@@ -281,10 +278,20 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 		goto error;
 	}
 
-	if (p9_is_proto_dotl(v9ses->clnt))
+	v9ses->flags = V9FS_ACCESS_USER;
+
+	if (p9_is_proto_dotl(v9ses->clnt)) {
+		v9ses->flags = V9FS_ACCESS_CLIENT;
 		v9ses->flags |= V9FS_PROTO_2000L;
-	else if (p9_is_proto_dotu(v9ses->clnt))
+	} else if (p9_is_proto_dotu(v9ses->clnt)) {
 		v9ses->flags |= V9FS_PROTO_2000U;
+	}
+
+	rc = v9fs_parse_options(v9ses, data);
+	if (rc < 0) {
+		retval = rc;
+		goto error;
+	}
 
 	v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ;
 
@@ -306,6 +313,14 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses,
 		v9ses->flags |= V9FS_ACCESS_ANY;
 		v9ses->uid = ~0;
 	}
+	if (!v9fs_proto_dotl(v9ses) ||
+		!((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) {
+		/*
+		 * We support ACL checks on clinet only if the protocol is
+		 * 9P2000.L and access is V9FS_ACCESS_CLIENT.
+		 */
+		v9ses->flags &= ~V9FS_ACL_MASK;
+	}
 
 	fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0,
 							v9ses->aname);
@@ -467,6 +482,63 @@ static void v9fs_sysfs_cleanup(void)
 	kobject_put(v9fs_kobj);
 }
 
+static void v9fs_inode_init_once(void *foo)
+{
+	struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;
+#ifdef CONFIG_9P_FSCACHE
+	v9inode->fscache = NULL;
+	v9inode->fscache_key = NULL;
+#endif
+	inode_init_once(&v9inode->vfs_inode);
+}
+
+/**
+ * v9fs_init_inode_cache - initialize a cache for 9P
+ * Returns 0 on success.
+ */
+static int v9fs_init_inode_cache(void)
+{
+	v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache",
+					  sizeof(struct v9fs_inode),
+					  0, (SLAB_RECLAIM_ACCOUNT|
+					      SLAB_MEM_SPREAD),
+					  v9fs_inode_init_once);
+	if (!v9fs_inode_cache)
+		return -ENOMEM;
+
+	return 0;
+}
+
+/**
+ * v9fs_destroy_inode_cache - destroy the cache of 9P inode
+ *
+ */
+static void v9fs_destroy_inode_cache(void)
+{
+	kmem_cache_destroy(v9fs_inode_cache);
+}
+
+static int v9fs_cache_register(void)
+{
+	int ret;
+	ret = v9fs_init_inode_cache();
+	if (ret < 0)
+		return ret;
+#ifdef CONFIG_9P_FSCACHE
+	return fscache_register_netfs(&v9fs_cache_netfs);
+#else
+	return ret;
+#endif
+}
+
+static void v9fs_cache_unregister(void)
+{
+	v9fs_destroy_inode_cache();
+#ifdef CONFIG_9P_FSCACHE
+	fscache_unregister_netfs(&v9fs_cache_netfs);
+#endif
+}
+
 /**
  * init_v9fs - Initialize module
  *
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index c4b5d88..9665c2b 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -20,6 +20,9 @@
  *  Boston, MA  02111-1301  USA
  *
  */
+#ifndef FS_9P_V9FS_H
+#define FS_9P_V9FS_H
+
 #include <linux/backing-dev.h>
 
 /**
@@ -28,8 +31,10 @@
  * @V9FS_PROTO_2000L: whether or not to use 9P2000.l extensions
  * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy
  * @V9FS_ACCESS_USER: a new attach will be issued for every user (default)
+ * @V9FS_ACCESS_CLIENT: Just like user, but access check is performed on client.
  * @V9FS_ACCESS_ANY: use a single attach for all users
  * @V9FS_ACCESS_MASK: bit mask of different ACCESS options
+ * @V9FS_POSIX_ACL: POSIX ACLs are enforced
  *
  * Session flags reflect options selected by users at mount time
  */
@@ -37,13 +42,15 @@
 			 V9FS_ACCESS_USER |   \
 			 V9FS_ACCESS_CLIENT)
 #define V9FS_ACCESS_MASK V9FS_ACCESS_ANY
+#define V9FS_ACL_MASK V9FS_POSIX_ACL
 
 enum p9_session_flags {
 	V9FS_PROTO_2000U	= 0x01,
 	V9FS_PROTO_2000L	= 0x02,
 	V9FS_ACCESS_SINGLE	= 0x04,
 	V9FS_ACCESS_USER	= 0x08,
-	V9FS_ACCESS_CLIENT	= 0x10
+	V9FS_ACCESS_CLIENT	= 0x10,
+	V9FS_POSIX_ACL		= 0x20
 };
 
 /* possible values of ->cache */
@@ -109,8 +116,29 @@ struct v9fs_session_info {
 	struct list_head slist; /* list of sessions registered with v9fs */
 	struct backing_dev_info bdi;
 	struct rw_semaphore rename_sem;
+	struct p9_fid *root_fid; /* Used for file system sync */
+};
+
+/* cache_validity flags */
+#define V9FS_INO_INVALID_ATTR 0x01
+
+struct v9fs_inode {
+#ifdef CONFIG_9P_FSCACHE
+	spinlock_t fscache_lock;
+	struct fscache_cookie *fscache;
+	struct p9_qid *fscache_key;
+#endif
+	unsigned int cache_validity;
+	struct p9_fid *writeback_fid;
+	struct mutex v_mutex;
+	struct inode vfs_inode;
 };
 
+static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
+{
+	return container_of(inode, struct v9fs_inode, vfs_inode);
+}
+
 struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *,
 									char *);
 extern void v9fs_session_close(struct v9fs_session_info *v9ses);
@@ -124,16 +152,15 @@ extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 			struct inode *new_dir, struct dentry *new_dentry);
 extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
 			void *p);
-extern struct inode *v9fs_inode(struct v9fs_session_info *v9ses,
-			struct p9_fid *fid,
-			struct super_block *sb);
-
+extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
+					 struct p9_fid *fid,
+					 struct super_block *sb);
 extern const struct inode_operations v9fs_dir_inode_operations_dotl;
 extern const struct inode_operations v9fs_file_inode_operations_dotl;
 extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
-extern struct inode *v9fs_inode_dotl(struct v9fs_session_info *v9ses,
-			struct p9_fid *fid,
-			struct super_block *sb);
+extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
+					      struct p9_fid *fid,
+					      struct super_block *sb);
 
 /* other default globals */
 #define V9FS_PORT	564
@@ -147,6 +174,11 @@ static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode)
 	return (inode->i_sb->s_fs_info);
 }
 
+static inline struct v9fs_session_info *v9fs_dentry2v9ses(struct dentry *dentry)
+{
+	return dentry->d_sb->s_fs_info;
+}
+
 static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses)
 {
 	return v9ses->flags & V9FS_PROTO_2000U;
@@ -158,7 +190,7 @@ static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
 }
 
 /**
- * v9fs_inode_from_fid - Helper routine to populate an inode by
+ * v9fs_get_inode_from_fid - Helper routine to populate an inode by
  * issuing a attribute request
  * @v9ses: session information
  * @fid: fid to issue attribute request for
@@ -166,11 +198,12 @@ static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
  *
  */
 static inline struct inode *
-v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-				struct super_block *sb)
+v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+			struct super_block *sb)
 {
 	if (v9fs_proto_dotl(v9ses))
-		return v9fs_inode_dotl(v9ses, fid, sb);
+		return v9fs_inode_from_fid_dotl(v9ses, fid, sb);
 	else
-		return v9fs_inode(v9ses, fid, sb);
+		return v9fs_inode_from_fid(v9ses, fid, sb);
 }
+#endif
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index b789f8e..4014160 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -20,6 +20,8 @@
  *  Boston, MA  02111-1301  USA
  *
  */
+#ifndef FS_9P_V9FS_VFS_H
+#define FS_9P_V9FS_VFS_H
 
 /* plan9 semantics are that created files are implicitly opened.
  * But linux semantics are that you call create, then open.
@@ -36,6 +38,7 @@
  * unlink calls remove, which is an implicit clunk. So we have to track
  * that kind of thing so that we don't try to clunk a dead fid.
  */
+#define P9_LOCK_TIMEOUT (30*HZ)
 
 extern struct file_system_type v9fs_fs_type;
 extern const struct address_space_operations v9fs_addr_operations;
@@ -45,13 +48,15 @@ extern const struct file_operations v9fs_dir_operations;
 extern const struct file_operations v9fs_dir_operations_dotl;
 extern const struct dentry_operations v9fs_dentry_operations;
 extern const struct dentry_operations v9fs_cached_dentry_operations;
+extern const struct file_operations v9fs_cached_file_operations;
+extern const struct file_operations v9fs_cached_file_operations_dotl;
+extern struct kmem_cache *v9fs_inode_cache;
 
-#ifdef CONFIG_9P_FSCACHE
 struct inode *v9fs_alloc_inode(struct super_block *sb);
 void v9fs_destroy_inode(struct inode *inode);
-#endif
-
 struct inode *v9fs_get_inode(struct super_block *sb, int mode);
+int v9fs_init_inode(struct v9fs_session_info *v9ses,
+		    struct inode *inode, int mode);
 void v9fs_evict_inode(struct inode *inode);
 ino_t v9fs_qid2ino(struct p9_qid *qid);
 void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *);
@@ -62,8 +67,19 @@ void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat);
 int v9fs_uflags2omode(int uflags, int extended);
 
 ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
+ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64);
 void v9fs_blank_wstat(struct p9_wstat *wstat);
 int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
 int v9fs_file_fsync_dotl(struct file *filp, int datasync);
-
-#define P9_LOCK_TIMEOUT (30*HZ)
+ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *,
+				 const char __user *, size_t, loff_t *, int);
+int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode);
+int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode);
+static inline void v9fs_invalidate_inode_attr(struct inode *inode)
+{
+	struct v9fs_inode *v9inode;
+	v9inode = V9FS_I(inode);
+	v9inode->cache_validity |= V9FS_INO_INVALID_ATTR;
+	return;
+}
+#endif
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index b7f2a8e..2524e4c 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -39,16 +39,16 @@
 #include "v9fs.h"
 #include "v9fs_vfs.h"
 #include "cache.h"
+#include "fid.h"
 
 /**
- * v9fs_vfs_readpage - read an entire page in from 9P
+ * v9fs_fid_readpage - read an entire page in from 9P
  *
- * @filp: file being read
+ * @fid: fid being read
  * @page: structure to page
  *
  */
-
-static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
 {
 	int retval;
 	loff_t offset;
@@ -67,7 +67,7 @@ static int v9fs_vfs_readpage(struct file *filp, struct page *page)
 	buffer = kmap(page);
 	offset = page_offset(page);
 
-	retval = v9fs_file_readn(filp, buffer, NULL, PAGE_CACHE_SIZE, offset);
+	retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset);
 	if (retval < 0) {
 		v9fs_uncache_page(inode, page);
 		goto done;
@@ -87,6 +87,19 @@ done:
 }
 
 /**
+ * v9fs_vfs_readpage - read an entire page in from 9P
+ *
+ * @filp: file being read
+ * @page: structure to page
+ *
+ */
+
+static int v9fs_vfs_readpage(struct file *filp, struct page *page)
+{
+	return v9fs_fid_readpage(filp->private_data, page);
+}
+
+/**
  * v9fs_vfs_readpages - read a set of pages from 9P
  *
  * @filp: file being read
@@ -124,7 +137,6 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
 {
 	if (PagePrivate(page))
 		return 0;
-
 	return v9fs_fscache_release_page(page, gfp);
 }
 
@@ -137,20 +149,89 @@ static int v9fs_release_page(struct page *page, gfp_t gfp)
 
 static void v9fs_invalidate_page(struct page *page, unsigned long offset)
 {
+	/*
+	 * If called with zero offset, we should release
+	 * the private state assocated with the page
+	 */
 	if (offset == 0)
 		v9fs_fscache_invalidate_page(page);
 }
 
+static int v9fs_vfs_writepage_locked(struct page *page)
+{
+	char *buffer;
+	int retval, len;
+	loff_t offset, size;
+	mm_segment_t old_fs;
+	struct v9fs_inode *v9inode;
+	struct inode *inode = page->mapping->host;
+
+	v9inode = V9FS_I(inode);
+	size = i_size_read(inode);
+	if (page->index == size >> PAGE_CACHE_SHIFT)
+		len = size & ~PAGE_CACHE_MASK;
+	else
+		len = PAGE_CACHE_SIZE;
+
+	set_page_writeback(page);
+
+	buffer = kmap(page);
+	offset = page_offset(page);
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+	/* We should have writeback_fid always set */
+	BUG_ON(!v9inode->writeback_fid);
+
+	retval = v9fs_file_write_internal(inode,
+					  v9inode->writeback_fid,
+					  (__force const char __user *)buffer,
+					  len, &offset, 0);
+	if (retval > 0)
+		retval = 0;
+
+	set_fs(old_fs);
+	kunmap(page);
+	end_page_writeback(page);
+	return retval;
+}
+
+static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+	int retval;
+
+	retval = v9fs_vfs_writepage_locked(page);
+	if (retval < 0) {
+		if (retval == -EAGAIN) {
+			redirty_page_for_writepage(wbc, page);
+			retval = 0;
+		} else {
+			SetPageError(page);
+			mapping_set_error(page->mapping, retval);
+		}
+	} else
+		retval = 0;
+
+	unlock_page(page);
+	return retval;
+}
+
 /**
  * v9fs_launder_page - Writeback a dirty page
- * Since the writes go directly to the server, we simply return a 0
- * here to indicate success.
- *
  * Returns 0 on success.
  */
 
 static int v9fs_launder_page(struct page *page)
 {
+	int retval;
+	struct inode *inode = page->mapping->host;
+
+	v9fs_fscache_wait_on_page_write(inode, page);
+	if (clear_page_dirty_for_io(page)) {
+		retval = v9fs_vfs_writepage_locked(page);
+		if (retval)
+			return retval;
+	}
 	return 0;
 }
 
@@ -173,9 +254,15 @@ static int v9fs_launder_page(struct page *page)
  * with an error.
  *
  */
-ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
-		loff_t pos, unsigned long nr_segs)
+static ssize_t
+v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+	       loff_t pos, unsigned long nr_segs)
 {
+	/*
+	 * FIXME
+	 * Now that we do caching with cache mode enabled, We need
+	 * to support direct IO
+	 */
 	P9_DPRINTK(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) "
 			"off/no(%lld/%lu) EINVAL\n",
 			iocb->ki_filp->f_path.dentry->d_name.name,
@@ -183,11 +270,84 @@ ssize_t v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
 
 	return -EINVAL;
 }
+
+static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
+			    loff_t pos, unsigned len, unsigned flags,
+			    struct page **pagep, void **fsdata)
+{
+	int retval = 0;
+	struct page *page;
+	struct v9fs_inode *v9inode;
+	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+	struct inode *inode = mapping->host;
+
+	v9inode = V9FS_I(inode);
+start:
+	page = grab_cache_page_write_begin(mapping, index, flags);
+	if (!page) {
+		retval = -ENOMEM;
+		goto out;
+	}
+	BUG_ON(!v9inode->writeback_fid);
+	if (PageUptodate(page))
+		goto out;
+
+	if (len == PAGE_CACHE_SIZE)
+		goto out;
+
+	retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
+	page_cache_release(page);
+	if (!retval)
+		goto start;
+out:
+	*pagep = page;
+	return retval;
+}
+
+static int v9fs_write_end(struct file *filp, struct address_space *mapping,
+			  loff_t pos, unsigned len, unsigned copied,
+			  struct page *page, void *fsdata)
+{
+	loff_t last_pos = pos + copied;
+	struct inode *inode = page->mapping->host;
+
+	if (unlikely(copied < len)) {
+		/*
+		 * zero out the rest of the area
+		 */
+		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
+
+		zero_user(page, from + copied, len - copied);
+		flush_dcache_page(page);
+	}
+
+	if (!PageUptodate(page))
+		SetPageUptodate(page);
+	/*
+	 * No need to use i_size_read() here, the i_size
+	 * cannot change under us because we hold the i_mutex.
+	 */
+	if (last_pos > inode->i_size) {
+		inode_add_bytes(inode, last_pos - inode->i_size);
+		i_size_write(inode, last_pos);
+	}
+	set_page_dirty(page);
+	unlock_page(page);
+	page_cache_release(page);
+
+	return copied;
+}
+
+
 const struct address_space_operations v9fs_addr_operations = {
-      .readpage = v9fs_vfs_readpage,
-      .readpages = v9fs_vfs_readpages,
-      .releasepage = v9fs_release_page,
-      .invalidatepage = v9fs_invalidate_page,
-      .launder_page = v9fs_launder_page,
-      .direct_IO = v9fs_direct_IO,
+	.readpage = v9fs_vfs_readpage,
+	.readpages = v9fs_vfs_readpages,
+	.set_page_dirty = __set_page_dirty_nobuffers,
+	.writepage = v9fs_vfs_writepage,
+	.write_begin = v9fs_write_begin,
+	.write_end = v9fs_write_end,
+	.releasepage = v9fs_release_page,
+	.invalidatepage = v9fs_invalidate_page,
+	.launder_page = v9fs_launder_page,
+	.direct_IO = v9fs_direct_IO,
 };
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c
index 233b7d4..b6a3b9f 100644
--- a/fs/9p/vfs_dentry.c
+++ b/fs/9p/vfs_dentry.c
@@ -63,20 +63,15 @@ static int v9fs_dentry_delete(const struct dentry *dentry)
  * v9fs_cached_dentry_delete - called when dentry refcount equals 0
  * @dentry:  dentry in question
  *
- * Only return 1 if our inode is invalid.  Only non-synthetic files
- * (ones without mtime == 0) should be calling this function.
- *
  */
-
 static int v9fs_cached_dentry_delete(const struct dentry *dentry)
 {
-	struct inode *inode = dentry->d_inode;
-	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name,
-									dentry);
+	P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n",
+		   dentry->d_name.name, dentry);
 
-	if(!inode)
+	/* Don't cache negative dentries */
+	if (!dentry->d_inode)
 		return 1;
-
 	return 0;
 }
 
@@ -105,7 +100,41 @@ static void v9fs_dentry_release(struct dentry *dentry)
 	}
 }
 
+static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+	struct p9_fid *fid;
+	struct inode *inode;
+	struct v9fs_inode *v9inode;
+
+	if (nd->flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	inode = dentry->d_inode;
+	if (!inode)
+		goto out_valid;
+
+	v9inode = V9FS_I(inode);
+	if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
+		int retval;
+		struct v9fs_session_info *v9ses;
+		fid = v9fs_fid_lookup(dentry);
+		if (IS_ERR(fid))
+			return PTR_ERR(fid);
+
+		v9ses = v9fs_inode2v9ses(inode);
+		if (v9fs_proto_dotl(v9ses))
+			retval = v9fs_refresh_inode_dotl(fid, inode);
+		else
+			retval = v9fs_refresh_inode(fid, inode);
+		if (retval <= 0)
+			return retval;
+	}
+out_valid:
+	return 1;
+}
+
 const struct dentry_operations v9fs_cached_dentry_operations = {
+	.d_revalidate = v9fs_lookup_revalidate,
 	.d_delete = v9fs_cached_dentry_delete,
 	.d_release = v9fs_dentry_release,
 };
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c
index b84ebe8..9c2bdda 100644
--- a/fs/9p/vfs_dir.c
+++ b/fs/9p/vfs_dir.c
@@ -295,7 +295,6 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
 	P9_DPRINTK(P9_DEBUG_VFS,
 			"v9fs_dir_release: inode: %p filp: %p fid: %d\n",
 			inode, filp, fid ? fid->fid : -1);
-	filemap_write_and_wait(inode->i_mapping);
 	if (fid)
 		p9_client_clunk(fid);
 	return 0;
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
index 240c306..ffed558 100644
--- a/fs/9p/vfs_file.c
+++ b/fs/9p/vfs_file.c
@@ -44,8 +44,7 @@
 #include "fid.h"
 #include "cache.h"
 
-static const struct file_operations v9fs_cached_file_operations;
-static const struct file_operations v9fs_cached_file_operations_dotl;
+static const struct vm_operations_struct v9fs_file_vm_ops;
 
 /**
  * v9fs_file_open - open a file (or directory)
@@ -57,11 +56,13 @@ static const struct file_operations v9fs_cached_file_operations_dotl;
 int v9fs_file_open(struct inode *inode, struct file *file)
 {
 	int err;
+	struct v9fs_inode *v9inode;
 	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid;
 	int omode;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file);
+	v9inode = V9FS_I(inode);
 	v9ses = v9fs_inode2v9ses(inode);
 	if (v9fs_proto_dotl(v9ses))
 		omode = file->f_flags;
@@ -89,20 +90,34 @@ int v9fs_file_open(struct inode *inode, struct file *file)
 	}
 
 	file->private_data = fid;
-	if ((fid->qid.version) && (v9ses->cache)) {
-		P9_DPRINTK(P9_DEBUG_VFS, "cached");
-		/* enable cached file options */
-		if(file->f_op == &v9fs_file_operations)
-			file->f_op = &v9fs_cached_file_operations;
-		else if (file->f_op == &v9fs_file_operations_dotl)
-			file->f_op = &v9fs_cached_file_operations_dotl;
-
+	mutex_lock(&v9inode->v_mutex);
+	if (v9ses->cache && !v9inode->writeback_fid &&
+	    ((file->f_flags & O_ACCMODE) != O_RDONLY)) {
+		/*
+		 * clone a fid and add it to writeback_fid
+		 * we do it during open time instead of
+		 * page dirty time via write_begin/page_mkwrite
+		 * because we want write after unlink usecase
+		 * to work.
+		 */
+		fid = v9fs_writeback_fid(file->f_path.dentry);
+		if (IS_ERR(fid)) {
+			err = PTR_ERR(fid);
+			mutex_unlock(&v9inode->v_mutex);
+			goto out_error;
+		}
+		v9inode->writeback_fid = (void *) fid;
+	}
+	mutex_unlock(&v9inode->v_mutex);
 #ifdef CONFIG_9P_FSCACHE
+	if (v9ses->cache)
 		v9fs_cache_inode_set_cookie(inode, file);
 #endif
-	}
-
 	return 0;
+out_error:
+	p9_client_clunk(file->private_data);
+	file->private_data = NULL;
+	return err;
 }
 
 /**
@@ -335,25 +350,22 @@ out_err:
 }
 
 /**
- * v9fs_file_readn - read from a file
- * @filp: file pointer to read
+ * v9fs_fid_readn - read from a fid
+ * @fid: fid to read
  * @data: data buffer to read data into
  * @udata: user data buffer to read data into
  * @count: size of buffer
  * @offset: offset at which to read data
  *
  */
-
 ssize_t
-v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
+v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count,
 	       u64 offset)
 {
 	int n, total, size;
-	struct p9_fid *fid = filp->private_data;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid,
-					(long long unsigned) offset, count);
-
+		   (long long unsigned) offset, count);
 	n = 0;
 	total = 0;
 	size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ;
@@ -379,6 +391,22 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
 }
 
 /**
+ * v9fs_file_readn - read from a file
+ * @filp: file pointer to read
+ * @data: data buffer to read data into
+ * @udata: user data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+ssize_t
+v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count,
+	       u64 offset)
+{
+	return v9fs_fid_readn(filp->private_data, data, udata, count, offset);
+}
+
+/**
  * v9fs_file_read - read from a file
  * @filp: file pointer to read
  * @udata: user data buffer to read data into
@@ -410,45 +438,22 @@ v9fs_file_read(struct file *filp, char __user *udata, size_t count,
 	return ret;
 }
 
-/**
- * v9fs_file_write - write to a file
- * @filp: file pointer to write
- * @data: data buffer to write data from
- * @count: size of buffer
- * @offset: offset at which to write data
- *
- */
-
-static ssize_t
-v9fs_file_write(struct file *filp, const char __user * data,
-		size_t count, loff_t * offset)
+ssize_t
+v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid,
+			 const char __user *data, size_t count,
+			 loff_t *offset, int invalidate)
 {
-	ssize_t retval;
-	size_t total = 0;
 	int n;
-	struct p9_fid *fid;
+	loff_t i_size;
+	size_t total = 0;
 	struct p9_client *clnt;
-	struct inode *inode = filp->f_path.dentry->d_inode;
 	loff_t origin = *offset;
 	unsigned long pg_start, pg_end;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data,
 		(int)count, (int)*offset);
 
-	fid = filp->private_data;
 	clnt = fid->clnt;
-
-	retval = generic_write_checks(filp, &origin, &count, 0);
-	if (retval)
-		goto out;
-
-	retval = -EINVAL;
-	if ((ssize_t) count < 0)
-		goto out;
-	retval = 0;
-	if (!count)
-		goto out;
-
 	do {
 		n = p9_client_write(fid, NULL, data+total, origin+total, count);
 		if (n <= 0)
@@ -457,25 +462,63 @@ v9fs_file_write(struct file *filp, const char __user * data,
 		total += n;
 	} while (count > 0);
 
-	if (total > 0) {
+	if (invalidate && (total > 0)) {
 		pg_start = origin >> PAGE_CACHE_SHIFT;
 		pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT;
 		if (inode->i_mapping && inode->i_mapping->nrpages)
 			invalidate_inode_pages2_range(inode->i_mapping,
 						      pg_start, pg_end);
 		*offset += total;
-		i_size_write(inode, i_size_read(inode) + total);
-		inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
+		i_size = i_size_read(inode);
+		if (*offset > i_size) {
+			inode_add_bytes(inode, *offset - i_size);
+			i_size_write(inode, *offset);
+		}
 	}
-
 	if (n < 0)
-		retval = n;
-	else
-		retval = total;
+		return n;
+
+	return total;
+}
+
+/**
+ * v9fs_file_write - write to a file
+ * @filp: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+static ssize_t
+v9fs_file_write(struct file *filp, const char __user * data,
+		size_t count, loff_t *offset)
+{
+	ssize_t retval = 0;
+	loff_t origin = *offset;
+
+
+	retval = generic_write_checks(filp, &origin, &count, 0);
+	if (retval)
+		goto out;
+
+	retval = -EINVAL;
+	if ((ssize_t) count < 0)
+		goto out;
+	retval = 0;
+	if (!count)
+		goto out;
+
+	retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode,
+					filp->private_data,
+					data, count, &origin, 1);
+	/* update offset on successful write */
+	if (retval > 0)
+		*offset = origin;
 out:
 	return retval;
 }
 
+
 static int v9fs_file_fsync(struct file *filp, int datasync)
 {
 	struct p9_fid *fid;
@@ -505,28 +548,182 @@ int v9fs_file_fsync_dotl(struct file *filp, int datasync)
 	return retval;
 }
 
-static const struct file_operations v9fs_cached_file_operations = {
+static int
+v9fs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	int retval;
+
+	retval = generic_file_mmap(file, vma);
+	if (!retval)
+		vma->vm_ops = &v9fs_file_vm_ops;
+
+	return retval;
+}
+
+static int
+v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	struct v9fs_inode *v9inode;
+	struct page *page = vmf->page;
+	struct file *filp = vma->vm_file;
+	struct inode *inode = filp->f_path.dentry->d_inode;
+
+
+	P9_DPRINTK(P9_DEBUG_VFS, "page %p fid %lx\n",
+		   page, (unsigned long)filp->private_data);
+
+	v9inode = V9FS_I(inode);
+	/* make sure the cache has finished storing the page */
+	v9fs_fscache_wait_on_page_write(inode, page);
+	BUG_ON(!v9inode->writeback_fid);
+	lock_page(page);
+	if (page->mapping != inode->i_mapping)
+		goto out_unlock;
+
+	return VM_FAULT_LOCKED;
+out_unlock:
+	unlock_page(page);
+	return VM_FAULT_NOPAGE;
+}
+
+static ssize_t
+v9fs_direct_read(struct file *filp, char __user *udata, size_t count,
+		 loff_t *offsetp)
+{
+	loff_t size, offset;
+	struct inode *inode;
+	struct address_space *mapping;
+
+	offset = *offsetp;
+	mapping = filp->f_mapping;
+	inode = mapping->host;
+	if (!count)
+		return 0;
+	size = i_size_read(inode);
+	if (offset < size)
+		filemap_write_and_wait_range(mapping, offset,
+					     offset + count - 1);
+
+	return v9fs_file_read(filp, udata, count, offsetp);
+}
+
+/**
+ * v9fs_cached_file_read - read from a file
+ * @filp: file pointer to read
+ * @udata: user data buffer to read data into
+ * @count: size of buffer
+ * @offset: offset at which to read data
+ *
+ */
+static ssize_t
+v9fs_cached_file_read(struct file *filp, char __user *data, size_t count,
+		      loff_t *offset)
+{
+	if (filp->f_flags & O_DIRECT)
+		return v9fs_direct_read(filp, data, count, offset);
+	return do_sync_read(filp, data, count, offset);
+}
+
+static ssize_t
+v9fs_direct_write(struct file *filp, const char __user * data,
+		  size_t count, loff_t *offsetp)
+{
+	loff_t offset;
+	ssize_t retval;
+	struct inode *inode;
+	struct address_space *mapping;
+
+	offset = *offsetp;
+	mapping = filp->f_mapping;
+	inode = mapping->host;
+	if (!count)
+		return 0;
+
+	mutex_lock(&inode->i_mutex);
+	retval = filemap_write_and_wait_range(mapping, offset,
+					      offset + count - 1);
+	if (retval)
+		goto err_out;
+	/*
+	 * After a write we want buffered reads to be sure to go to disk to get
+	 * the new data.  We invalidate clean cached page from the region we're
+	 * about to write.  We do this *before* the write so that if we fail
+	 * here we fall back to buffered write
+	 */
+	if (mapping->nrpages) {
+		pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT;
+		pgoff_t pg_end   = (offset + count - 1) >> PAGE_CACHE_SHIFT;
+
+		retval = invalidate_inode_pages2_range(mapping,
+							pg_start, pg_end);
+		/*
+		 * If a page can not be invalidated, fall back
+		 * to buffered write.
+		 */
+		if (retval) {
+			if (retval == -EBUSY)
+				goto buff_write;
+			goto err_out;
+		}
+	}
+	retval = v9fs_file_write(filp, data, count, offsetp);
+err_out:
+	mutex_unlock(&inode->i_mutex);
+	return retval;
+
+buff_write:
+	mutex_unlock(&inode->i_mutex);
+	return do_sync_write(filp, data, count, offsetp);
+}
+
+/**
+ * v9fs_cached_file_write - write to a file
+ * @filp: file pointer to write
+ * @data: data buffer to write data from
+ * @count: size of buffer
+ * @offset: offset at which to write data
+ *
+ */
+static ssize_t
+v9fs_cached_file_write(struct file *filp, const char __user * data,
+		       size_t count, loff_t *offset)
+{
+
+	if (filp->f_flags & O_DIRECT)
+		return v9fs_direct_write(filp, data, count, offset);
+	return do_sync_write(filp, data, count, offset);
+}
+
+static const struct vm_operations_struct v9fs_file_vm_ops = {
+	.fault = filemap_fault,
+	.page_mkwrite = v9fs_vm_page_mkwrite,
+};
+
+
+const struct file_operations v9fs_cached_file_operations = {
 	.llseek = generic_file_llseek,
-	.read = do_sync_read,
+	.read = v9fs_cached_file_read,
+	.write = v9fs_cached_file_write,
 	.aio_read = generic_file_aio_read,
-	.write = v9fs_file_write,
+	.aio_write = generic_file_aio_write,
 	.open = v9fs_file_open,
 	.release = v9fs_dir_release,
 	.lock = v9fs_file_lock,
-	.mmap = generic_file_readonly_mmap,
+	.mmap = v9fs_file_mmap,
 	.fsync = v9fs_file_fsync,
 };
 
-static const struct file_operations v9fs_cached_file_operations_dotl = {
+const struct file_operations v9fs_cached_file_operations_dotl = {
 	.llseek = generic_file_llseek,
-	.read = do_sync_read,
+	.read = v9fs_cached_file_read,
+	.write = v9fs_cached_file_write,
 	.aio_read = generic_file_aio_read,
-	.write = v9fs_file_write,
+	.aio_write = generic_file_aio_write,
 	.open = v9fs_file_open,
 	.release = v9fs_dir_release,
 	.lock = v9fs_file_lock_dotl,
 	.flock = v9fs_file_flock_dotl,
-	.mmap = generic_file_readonly_mmap,
+	.mmap = v9fs_file_mmap,
 	.fsync = v9fs_file_fsync_dotl,
 };
 
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index b76a40b..7f6c677 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -203,26 +203,26 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
 	wstat->extension = NULL;
 }
 
-#ifdef CONFIG_9P_FSCACHE
 /**
  * v9fs_alloc_inode - helper function to allocate an inode
- * This callback is executed before setting up the inode so that we
- * can associate a vcookie with each inode.
  *
  */
-
 struct inode *v9fs_alloc_inode(struct super_block *sb)
 {
-	struct v9fs_cookie *vcookie;
-	vcookie = (struct v9fs_cookie *)kmem_cache_alloc(vcookie_cache,
-							 GFP_KERNEL);
-	if (!vcookie)
+	struct v9fs_inode *v9inode;
+	v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache,
+							GFP_KERNEL);
+	if (!v9inode)
 		return NULL;
-
-	vcookie->fscache = NULL;
-	vcookie->qid = NULL;
-	spin_lock_init(&vcookie->lock);
-	return &vcookie->inode;
+#ifdef CONFIG_9P_FSCACHE
+	v9inode->fscache = NULL;
+	v9inode->fscache_key = NULL;
+	spin_lock_init(&v9inode->fscache_lock);
+#endif
+	v9inode->writeback_fid = NULL;
+	v9inode->cache_validity = 0;
+	mutex_init(&v9inode->v_mutex);
+	return &v9inode->vfs_inode;
 }
 
 /**
@@ -234,35 +234,18 @@ static void v9fs_i_callback(struct rcu_head *head)
 {
 	struct inode *inode = container_of(head, struct inode, i_rcu);
 	INIT_LIST_HEAD(&inode->i_dentry);
-	kmem_cache_free(vcookie_cache, v9fs_inode2cookie(inode));
+	kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
 }
 
 void v9fs_destroy_inode(struct inode *inode)
 {
 	call_rcu(&inode->i_rcu, v9fs_i_callback);
 }
-#endif
-
-/**
- * v9fs_get_inode - helper function to setup an inode
- * @sb: superblock
- * @mode: mode to setup inode with
- *
- */
 
-struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+int v9fs_init_inode(struct v9fs_session_info *v9ses,
+		    struct inode *inode, int mode)
 {
-	int err;
-	struct inode *inode;
-	struct v9fs_session_info *v9ses = sb->s_fs_info;
-
-	P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
-
-	inode = new_inode(sb);
-	if (!inode) {
-		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
-		return ERR_PTR(-ENOMEM);
-	}
+	int err = 0;
 
 	inode_init_owner(inode, NULL, mode);
 	inode->i_blocks = 0;
@@ -292,14 +275,20 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 	case S_IFREG:
 		if (v9fs_proto_dotl(v9ses)) {
 			inode->i_op = &v9fs_file_inode_operations_dotl;
-			inode->i_fop = &v9fs_file_operations_dotl;
+			if (v9ses->cache)
+				inode->i_fop =
+					&v9fs_cached_file_operations_dotl;
+			else
+				inode->i_fop = &v9fs_file_operations_dotl;
 		} else {
 			inode->i_op = &v9fs_file_inode_operations;
-			inode->i_fop = &v9fs_file_operations;
+			if (v9ses->cache)
+				inode->i_fop = &v9fs_cached_file_operations;
+			else
+				inode->i_fop = &v9fs_file_operations;
 		}
 
 		break;
-
 	case S_IFLNK:
 		if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) {
 			P9_DPRINTK(P9_DEBUG_ERROR, "extended modes used with "
@@ -335,12 +324,37 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 		err = -EINVAL;
 		goto error;
 	}
+error:
+	return err;
 
-	return inode;
+}
 
-error:
-	iput(inode);
-	return ERR_PTR(err);
+/**
+ * v9fs_get_inode - helper function to setup an inode
+ * @sb: superblock
+ * @mode: mode to setup inode with
+ *
+ */
+
+struct inode *v9fs_get_inode(struct super_block *sb, int mode)
+{
+	int err;
+	struct inode *inode;
+	struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+	P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
+
+	inode = new_inode(sb);
+	if (!inode) {
+		P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	err = v9fs_init_inode(v9ses, inode, mode);
+	if (err) {
+		iput(inode);
+		return ERR_PTR(err);
+	}
+	return inode;
 }
 
 /*
@@ -403,6 +417,8 @@ error:
  */
 void v9fs_evict_inode(struct inode *inode)
 {
+	struct v9fs_inode *v9inode = V9FS_I(inode);
+
 	truncate_inode_pages(inode->i_mapping, 0);
 	end_writeback(inode);
 	filemap_fdatawrite(inode->i_mapping);
@@ -410,41 +426,67 @@ void v9fs_evict_inode(struct inode *inode)
 #ifdef CONFIG_9P_FSCACHE
 	v9fs_cache_inode_put_cookie(inode);
 #endif
+	/* clunk the fid stashed in writeback_fid */
+	if (v9inode->writeback_fid) {
+		p9_client_clunk(v9inode->writeback_fid);
+		v9inode->writeback_fid = NULL;
+	}
 }
 
-struct inode *
-v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-	struct super_block *sb)
+static struct inode *v9fs_qid_iget(struct super_block *sb,
+				   struct p9_qid *qid,
+				   struct p9_wstat *st)
 {
-	int err, umode;
-	struct inode *ret = NULL;
-	struct p9_wstat *st;
-
-	st = p9_client_stat(fid);
-	if (IS_ERR(st))
-		return ERR_CAST(st);
+	int retval, umode;
+	unsigned long i_ino;
+	struct inode *inode;
+	struct v9fs_session_info *v9ses = sb->s_fs_info;
 
+	i_ino = v9fs_qid2ino(qid);
+	inode = iget_locked(sb, i_ino);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	if (!(inode->i_state & I_NEW))
+		return inode;
+	/*
+	 * initialize the inode with the stat info
+	 * FIXME!! we may need support for stale inodes
+	 * later.
+	 */
 	umode = p9mode2unixmode(v9ses, st->mode);
-	ret = v9fs_get_inode(sb, umode);
-	if (IS_ERR(ret)) {
-		err = PTR_ERR(ret);
+	retval = v9fs_init_inode(v9ses, inode, umode);
+	if (retval)
 		goto error;
-	}
-
-	v9fs_stat2inode(st, ret, sb);
-	ret->i_ino = v9fs_qid2ino(&st->qid);
 
+	v9fs_stat2inode(st, inode, sb);
 #ifdef CONFIG_9P_FSCACHE
-	v9fs_vcookie_set_qid(ret, &st->qid);
-	v9fs_cache_inode_get_cookie(ret);
+	v9fs_fscache_set_key(inode, &st->qid);
+	v9fs_cache_inode_get_cookie(inode);
 #endif
-	p9stat_free(st);
-	kfree(st);
-	return ret;
+	unlock_new_inode(inode);
+	return inode;
 error:
+	unlock_new_inode(inode);
+	iput(inode);
+	return ERR_PTR(retval);
+
+}
+
+struct inode *
+v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+		    struct super_block *sb)
+{
+	struct p9_wstat *st;
+	struct inode *inode = NULL;
+
+	st = p9_client_stat(fid);
+	if (IS_ERR(st))
+		return ERR_CAST(st);
+
+	inode = v9fs_qid_iget(sb, &st->qid, st);
 	p9stat_free(st);
 	kfree(st);
-	return ERR_PTR(err);
+	return inode;
 }
 
 /**
@@ -458,8 +500,8 @@ error:
 static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
 {
 	int retval;
-	struct inode *file_inode;
 	struct p9_fid *v9fid;
+	struct inode *file_inode;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %d\n", dir, file,
 		rmdir);
@@ -470,8 +512,20 @@ static int v9fs_remove(struct inode *dir, struct dentry *file, int rmdir)
 		return PTR_ERR(v9fid);
 
 	retval = p9_client_remove(v9fid);
-	if (!retval)
-		drop_nlink(file_inode);
+	if (!retval) {
+		/*
+		 * directories on unlink should have zero
+		 * link count
+		 */
+		if (rmdir) {
+			clear_nlink(file_inode);
+			drop_nlink(dir);
+		} else
+			drop_nlink(file_inode);
+
+		v9fs_invalidate_inode_attr(file_inode);
+		v9fs_invalidate_inode_attr(dir);
+	}
 	return retval;
 }
 
@@ -531,7 +585,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 	}
 
 	/* instantiate inode and assign the unopened fid to the dentry */
-	inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -570,9 +624,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	int err;
 	u32 perm;
 	int flags;
-	struct v9fs_session_info *v9ses;
-	struct p9_fid *fid;
 	struct file *filp;
+	struct v9fs_inode *v9inode;
+	struct v9fs_session_info *v9ses;
+	struct p9_fid *fid, *inode_fid;
 
 	err = 0;
 	fid = NULL;
@@ -592,8 +647,29 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 		goto error;
 	}
 
+	v9fs_invalidate_inode_attr(dir);
 	/* if we are opening a file, assign the open fid to the file */
 	if (nd && nd->flags & LOOKUP_OPEN) {
+		v9inode = V9FS_I(dentry->d_inode);
+		mutex_lock(&v9inode->v_mutex);
+		if (v9ses->cache && !v9inode->writeback_fid &&
+		    ((flags & O_ACCMODE) != O_RDONLY)) {
+			/*
+			 * clone a fid and add it to writeback_fid
+			 * we do it during open time instead of
+			 * page dirty time via write_begin/page_mkwrite
+			 * because we want write after unlink usecase
+			 * to work.
+			 */
+			inode_fid = v9fs_writeback_fid(dentry);
+			if (IS_ERR(inode_fid)) {
+				err = PTR_ERR(inode_fid);
+				mutex_unlock(&v9inode->v_mutex);
+				goto error;
+			}
+			v9inode->writeback_fid = (void *) inode_fid;
+		}
+		mutex_unlock(&v9inode->v_mutex);
 		filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
 		if (IS_ERR(filp)) {
 			err = PTR_ERR(filp);
@@ -601,6 +677,10 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 		}
 
 		filp->private_data = fid;
+#ifdef CONFIG_9P_FSCACHE
+		if (v9ses->cache)
+			v9fs_cache_inode_set_cookie(dentry->d_inode, filp);
+#endif
 	} else
 		p9_client_clunk(fid);
 
@@ -625,8 +705,8 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	int err;
 	u32 perm;
-	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid;
+	struct v9fs_session_info *v9ses;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
 	err = 0;
@@ -636,6 +716,9 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	if (IS_ERR(fid)) {
 		err = PTR_ERR(fid);
 		fid = NULL;
+	} else {
+		inc_nlink(dir);
+		v9fs_invalidate_inode_attr(dir);
 	}
 
 	if (fid)
@@ -687,7 +770,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
 		return ERR_PTR(result);
 	}
 
-	inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		result = PTR_ERR(inode);
 		inode = NULL;
@@ -747,17 +830,19 @@ int
 v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 		struct inode *new_dir, struct dentry *new_dentry)
 {
+	int retval;
 	struct inode *old_inode;
+	struct inode *new_inode;
 	struct v9fs_session_info *v9ses;
 	struct p9_fid *oldfid;
 	struct p9_fid *olddirfid;
 	struct p9_fid *newdirfid;
 	struct p9_wstat wstat;
-	int retval;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "\n");
 	retval = 0;
 	old_inode = old_dentry->d_inode;
+	new_inode = new_dentry->d_inode;
 	v9ses = v9fs_inode2v9ses(old_inode);
 	oldfid = v9fs_fid_lookup(old_dentry);
 	if (IS_ERR(oldfid))
@@ -798,9 +883,30 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	retval = p9_client_wstat(oldfid, &wstat);
 
 clunk_newdir:
-	if (!retval)
+	if (!retval) {
+		if (new_inode) {
+			if (S_ISDIR(new_inode->i_mode))
+				clear_nlink(new_inode);
+			else
+				drop_nlink(new_inode);
+			/*
+			 * Work around vfs rename rehash bug with
+			 * FS_RENAME_DOES_D_MOVE
+			 */
+			v9fs_invalidate_inode_attr(new_inode);
+		}
+		if (S_ISDIR(old_inode->i_mode)) {
+			if (!new_inode)
+				inc_nlink(new_dir);
+			drop_nlink(old_dir);
+		}
+		v9fs_invalidate_inode_attr(old_inode);
+		v9fs_invalidate_inode_attr(old_dir);
+		v9fs_invalidate_inode_attr(new_dir);
+
 		/* successful rename */
 		d_move(old_dentry, new_dentry);
+	}
 	up_write(&v9ses->rename_sem);
 	p9_client_clunk(newdirfid);
 
@@ -830,10 +936,11 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
 	P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
 	err = -EPERM;
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
-		return simple_getattr(mnt, dentry, stat);
-
+	v9ses = v9fs_dentry2v9ses(dentry);
+	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
+		generic_fillattr(dentry->d_inode, stat);
+		return 0;
+	}
 	fid = v9fs_fid_lookup(dentry);
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
@@ -865,8 +972,12 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 	struct p9_wstat wstat;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "\n");
+	retval = inode_change_ok(dentry->d_inode, iattr);
+	if (retval)
+		return retval;
+
 	retval = -EPERM;
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	fid = v9fs_fid_lookup(dentry);
 	if(IS_ERR(fid))
 		return PTR_ERR(fid);
@@ -892,16 +1003,19 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
 			wstat.n_gid = iattr->ia_gid;
 	}
 
+	/* Write all dirty data */
+	if (S_ISREG(dentry->d_inode->i_mode))
+		filemap_write_and_wait(dentry->d_inode->i_mapping);
+
 	retval = p9_client_wstat(fid, &wstat);
 	if (retval < 0)
 		return retval;
 
 	if ((iattr->ia_valid & ATTR_SIZE) &&
-	    iattr->ia_size != i_size_read(dentry->d_inode)) {
-		retval = vmtruncate(dentry->d_inode, iattr->ia_size);
-		if (retval)
-			return retval;
-	}
+	    iattr->ia_size != i_size_read(dentry->d_inode))
+		truncate_setsize(dentry->d_inode, iattr->ia_size);
+
+	v9fs_invalidate_inode_attr(dentry->d_inode);
 
 	setattr_copy(dentry->d_inode, iattr);
 	mark_inode_dirty(dentry->d_inode);
@@ -924,6 +1038,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
 	char tag_name[14];
 	unsigned int i_nlink;
 	struct v9fs_session_info *v9ses = sb->s_fs_info;
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 
 	inode->i_nlink = 1;
 
@@ -983,6 +1098,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
 
 	/* not real number of blocks, but 512 byte ones ... */
 	inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9;
+	v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
 }
 
 /**
@@ -1023,7 +1139,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
 
 	P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name);
 	retval = -EPERM;
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	fid = v9fs_fid_lookup(dentry);
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
@@ -1115,8 +1231,8 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 	int mode, const char *extension)
 {
 	u32 perm;
-	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid;
+	struct v9fs_session_info *v9ses;
 
 	v9ses = v9fs_inode2v9ses(dir);
 	if (!v9fs_proto_dotu(v9ses)) {
@@ -1130,6 +1246,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 
+	v9fs_invalidate_inode_attr(dir);
 	p9_client_clunk(fid);
 	return 0;
 }
@@ -1166,8 +1283,8 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
 	      struct dentry *dentry)
 {
 	int retval;
-	struct p9_fid *oldfid;
 	char *name;
+	struct p9_fid *oldfid;
 
 	P9_DPRINTK(P9_DEBUG_VFS,
 		" %lu,%s,%s\n", dir->i_ino, dentry->d_name.name,
@@ -1186,7 +1303,10 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir,
 	sprintf(name, "%d\n", oldfid->fid);
 	retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name);
 	__putname(name);
-
+	if (!retval) {
+		v9fs_refresh_inode(oldfid, old_dentry->d_inode);
+		v9fs_invalidate_inode_attr(dir);
+	}
 clunk_fid:
 	p9_client_clunk(oldfid);
 	return retval;
@@ -1237,6 +1357,32 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 	return retval;
 }
 
+int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
+{
+	loff_t i_size;
+	struct p9_wstat *st;
+	struct v9fs_session_info *v9ses;
+
+	v9ses = v9fs_inode2v9ses(inode);
+	st = p9_client_stat(fid);
+	if (IS_ERR(st))
+		return PTR_ERR(st);
+
+	spin_lock(&inode->i_lock);
+	/*
+	 * We don't want to refresh inode->i_size,
+	 * because we may have cached data
+	 */
+	i_size = inode->i_size;
+	v9fs_stat2inode(st, inode, inode->i_sb);
+	if (v9ses->cache)
+		inode->i_size = i_size;
+	spin_unlock(&inode->i_lock);
+	p9stat_free(st);
+	kfree(st);
+	return 0;
+}
+
 static const struct inode_operations v9fs_dir_inode_operations_dotu = {
 	.create = v9fs_vfs_create,
 	.lookup = v9fs_vfs_lookup,
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index fe3ffa9..ffbb113 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -86,40 +86,63 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
 	return dentry;
 }
 
+static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
+					struct p9_qid *qid,
+					struct p9_fid *fid,
+					struct p9_stat_dotl *st)
+{
+	int retval;
+	unsigned long i_ino;
+	struct inode *inode;
+	struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+	i_ino = v9fs_qid2ino(qid);
+	inode = iget_locked(sb, i_ino);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+	if (!(inode->i_state & I_NEW))
+		return inode;
+	/*
+	 * initialize the inode with the stat info
+	 * FIXME!! we may need support for stale inodes
+	 * later.
+	 */
+	retval = v9fs_init_inode(v9ses, inode, st->st_mode);
+	if (retval)
+		goto error;
+
+	v9fs_stat2inode_dotl(st, inode);
+#ifdef CONFIG_9P_FSCACHE
+	v9fs_fscache_set_key(inode, &st->qid);
+	v9fs_cache_inode_get_cookie(inode);
+#endif
+	retval = v9fs_get_acl(inode, fid);
+	if (retval)
+		goto error;
+
+	unlock_new_inode(inode);
+	return inode;
+error:
+	unlock_new_inode(inode);
+	iput(inode);
+	return ERR_PTR(retval);
+
+}
+
 struct inode *
-v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-	struct super_block *sb)
+v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+			 struct super_block *sb)
 {
-	struct inode *ret = NULL;
-	int err;
 	struct p9_stat_dotl *st;
+	struct inode *inode = NULL;
 
 	st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
 	if (IS_ERR(st))
 		return ERR_CAST(st);
 
-	ret = v9fs_get_inode(sb, st->st_mode);
-	if (IS_ERR(ret)) {
-		err = PTR_ERR(ret);
-		goto error;
-	}
-
-	v9fs_stat2inode_dotl(st, ret);
-	ret->i_ino = v9fs_qid2ino(&st->qid);
-#ifdef CONFIG_9P_FSCACHE
-	v9fs_vcookie_set_qid(ret, &st->qid);
-	v9fs_cache_inode_get_cookie(ret);
-#endif
-	err = v9fs_get_acl(ret, fid);
-	if (err) {
-		iput(ret);
-		goto error;
-	}
+	inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st);
 	kfree(st);
-	return ret;
-error:
-	kfree(st);
-	return ERR_PTR(err);
+	return inode;
 }
 
 /**
@@ -136,16 +159,17 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		struct nameidata *nd)
 {
 	int err = 0;
-	char *name = NULL;
 	gid_t gid;
 	int flags;
 	mode_t mode;
-	struct v9fs_session_info *v9ses;
-	struct p9_fid *fid = NULL;
-	struct p9_fid *dfid, *ofid;
+	char *name = NULL;
 	struct file *filp;
 	struct p9_qid qid;
 	struct inode *inode;
+	struct p9_fid *fid = NULL;
+	struct v9fs_inode *v9inode;
+	struct p9_fid *dfid, *ofid, *inode_fid;
+	struct v9fs_session_info *v9ses;
 	struct posix_acl *pacl = NULL, *dacl = NULL;
 
 	v9ses = v9fs_inode2v9ses(dir);
@@ -196,6 +220,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 				err);
 		goto error;
 	}
+	v9fs_invalidate_inode_attr(dir);
 
 	/* instantiate inode and assign the unopened fid to the dentry */
 	fid = p9_client_walk(dfid, 1, &name, 1);
@@ -205,7 +230,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		fid = NULL;
 		goto error;
 	}
-	inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+	inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
 	if (IS_ERR(inode)) {
 		err = PTR_ERR(inode);
 		P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -219,6 +244,26 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 	/* Now set the ACL based on the default value */
 	v9fs_set_create_acl(dentry, dacl, pacl);
 
+	v9inode = V9FS_I(inode);
+	mutex_lock(&v9inode->v_mutex);
+	if (v9ses->cache && !v9inode->writeback_fid &&
+	    ((flags & O_ACCMODE) != O_RDONLY)) {
+		/*
+		 * clone a fid and add it to writeback_fid
+		 * we do it during open time instead of
+		 * page dirty time via write_begin/page_mkwrite
+		 * because we want write after unlink usecase
+		 * to work.
+		 */
+		inode_fid = v9fs_writeback_fid(dentry);
+		if (IS_ERR(inode_fid)) {
+			err = PTR_ERR(inode_fid);
+			mutex_unlock(&v9inode->v_mutex);
+			goto error;
+		}
+		v9inode->writeback_fid = (void *) inode_fid;
+	}
+	mutex_unlock(&v9inode->v_mutex);
 	/* Since we are opening a file, assign the open fid to the file */
 	filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
 	if (IS_ERR(filp)) {
@@ -226,6 +271,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		return PTR_ERR(filp);
 	}
 	filp->private_data = ofid;
+#ifdef CONFIG_9P_FSCACHE
+	if (v9ses->cache)
+		v9fs_cache_inode_set_cookie(inode, filp);
+#endif
 	return 0;
 
 error:
@@ -300,7 +349,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
 			goto error;
 		}
 
-		inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -327,7 +376,8 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
 	}
 	/* Now set the ACL based on the default value */
 	v9fs_set_create_acl(dentry, dacl, pacl);
-
+	inc_nlink(dir);
+	v9fs_invalidate_inode_attr(dir);
 error:
 	if (fid)
 		p9_client_clunk(fid);
@@ -345,10 +395,11 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
 
 	P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry);
 	err = -EPERM;
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
-	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE)
-		return simple_getattr(mnt, dentry, stat);
-
+	v9ses = v9fs_dentry2v9ses(dentry);
+	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
+		generic_fillattr(dentry->d_inode, stat);
+		return 0;
+	}
 	fid = v9fs_fid_lookup(dentry);
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
@@ -401,22 +452,24 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
 	p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec;
 
 	retval = -EPERM;
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	fid = v9fs_fid_lookup(dentry);
 	if (IS_ERR(fid))
 		return PTR_ERR(fid);
 
+	/* Write all dirty data */
+	if (S_ISREG(dentry->d_inode->i_mode))
+		filemap_write_and_wait(dentry->d_inode->i_mapping);
+
 	retval = p9_client_setattr(fid, &p9attr);
 	if (retval < 0)
 		return retval;
 
 	if ((iattr->ia_valid & ATTR_SIZE) &&
-	    iattr->ia_size != i_size_read(dentry->d_inode)) {
-		retval = vmtruncate(dentry->d_inode, iattr->ia_size);
-		if (retval)
-			return retval;
-	}
+	    iattr->ia_size != i_size_read(dentry->d_inode))
+		truncate_setsize(dentry->d_inode, iattr->ia_size);
 
+	v9fs_invalidate_inode_attr(dentry->d_inode);
 	setattr_copy(dentry->d_inode, iattr);
 	mark_inode_dirty(dentry->d_inode);
 	if (iattr->ia_valid & ATTR_MODE) {
@@ -439,6 +492,7 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
 void
 v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
 {
+	struct v9fs_inode *v9inode = V9FS_I(inode);
 
 	if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) {
 		inode->i_atime.tv_sec = stat->st_atime_sec;
@@ -497,20 +551,21 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
 	/* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
 	 * because the inode structure does not have fields for them.
 	 */
+	v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR;
 }
 
 static int
 v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
 		const char *symname)
 {
-	struct v9fs_session_info *v9ses;
-	struct p9_fid *dfid;
-	struct p9_fid *fid = NULL;
-	struct inode *inode;
-	struct p9_qid qid;
-	char *name;
 	int err;
 	gid_t gid;
+	char *name;
+	struct p9_qid qid;
+	struct inode *inode;
+	struct p9_fid *dfid;
+	struct p9_fid *fid = NULL;
+	struct v9fs_session_info *v9ses;
 
 	name = (char *) dentry->d_name.name;
 	P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n",
@@ -534,6 +589,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
 		goto error;
 	}
 
+	v9fs_invalidate_inode_attr(dir);
 	if (v9ses->cache) {
 		/* Now walk from the parent so we can get an unopened fid. */
 		fid = p9_client_walk(dfid, 1, &name, 1);
@@ -546,7 +602,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
 		}
 
 		/* instantiate inode and assign the unopened fid to dentry */
-		inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -588,10 +644,10 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 		struct dentry *dentry)
 {
 	int err;
-	struct p9_fid *dfid, *oldfid;
 	char *name;
-	struct v9fs_session_info *v9ses;
 	struct dentry *dir_dentry;
+	struct p9_fid *dfid, *oldfid;
+	struct v9fs_session_info *v9ses;
 
 	P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n",
 			dir->i_ino, old_dentry->d_name.name,
@@ -616,29 +672,17 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
 		return err;
 	}
 
+	v9fs_invalidate_inode_attr(dir);
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 		/* Get the latest stat info from server. */
 		struct p9_fid *fid;
-		struct p9_stat_dotl *st;
-
 		fid = v9fs_fid_lookup(old_dentry);
 		if (IS_ERR(fid))
 			return PTR_ERR(fid);
 
-		st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
-		if (IS_ERR(st))
-			return PTR_ERR(st);
-
-		v9fs_stat2inode_dotl(st, old_dentry->d_inode);
-
-		kfree(st);
-	} else {
-		/* Caching disabled. No need to get upto date stat info.
-		 * This dentry will be released immediately. So, just hold the
-		 * inode
-		 */
-		ihold(old_dentry->d_inode);
+		v9fs_refresh_inode_dotl(fid, old_dentry->d_inode);
 	}
+	ihold(old_dentry->d_inode);
 	d_instantiate(dentry, old_dentry->d_inode);
 
 	return err;
@@ -657,12 +701,12 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
 		dev_t rdev)
 {
 	int err;
+	gid_t gid;
 	char *name;
 	mode_t mode;
 	struct v9fs_session_info *v9ses;
 	struct p9_fid *fid = NULL, *dfid = NULL;
 	struct inode *inode;
-	gid_t gid;
 	struct p9_qid qid;
 	struct dentry *dir_dentry;
 	struct posix_acl *dacl = NULL, *pacl = NULL;
@@ -699,6 +743,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
 	if (err < 0)
 		goto error;
 
+	v9fs_invalidate_inode_attr(dir);
 	/* instantiate inode and assign the unopened fid to the dentry */
 	if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
 		fid = p9_client_walk(dfid, 1, &name, 1);
@@ -710,7 +755,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
 			goto error;
 		}
 
-		inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
+		inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -782,6 +827,31 @@ ndset:
 	return NULL;
 }
 
+int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
+{
+	loff_t i_size;
+	struct p9_stat_dotl *st;
+	struct v9fs_session_info *v9ses;
+
+	v9ses = v9fs_inode2v9ses(inode);
+	st = p9_client_getattr_dotl(fid, P9_STATS_ALL);
+	if (IS_ERR(st))
+		return PTR_ERR(st);
+
+	spin_lock(&inode->i_lock);
+	/*
+	 * We don't want to refresh inode->i_size,
+	 * because we may have cached data
+	 */
+	i_size = inode->i_size;
+	v9fs_stat2inode_dotl(st, inode);
+	if (v9ses->cache)
+		inode->i_size = i_size;
+	spin_unlock(&inode->i_lock);
+	kfree(st);
+	return 0;
+}
+
 const struct inode_operations v9fs_dir_inode_operations_dotl = {
 	.create = v9fs_vfs_create_dotl,
 	.lookup = v9fs_vfs_lookup,
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index dbaabe3..f3eed33 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -86,12 +86,15 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
 	} else
 		sb->s_op = &v9fs_super_ops;
 	sb->s_bdi = &v9ses->bdi;
+	if (v9ses->cache)
+		sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE;
 
-	sb->s_flags = flags | MS_ACTIVE | MS_SYNCHRONOUS | MS_DIRSYNC |
-	    MS_NOATIME;
+	sb->s_flags = flags | MS_ACTIVE | MS_DIRSYNC | MS_NOATIME;
+	if (!v9ses->cache)
+		sb->s_flags |= MS_SYNCHRONOUS;
 
 #ifdef CONFIG_9P_FS_POSIX_ACL
-	if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)
+	if ((v9ses->flags & V9FS_ACL_MASK) == V9FS_POSIX_ACL)
 		sb->s_flags |= MS_POSIXACL;
 #endif
 
@@ -151,7 +154,6 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 		retval = PTR_ERR(inode);
 		goto release_sb;
 	}
-
 	root = d_alloc_root(inode);
 	if (!root) {
 		iput(inode);
@@ -166,7 +168,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 			retval = PTR_ERR(st);
 			goto release_sb;
 		}
-
+		root->d_inode->i_ino = v9fs_qid2ino(&st->qid);
 		v9fs_stat2inode_dotl(st, root->d_inode);
 		kfree(st);
 	} else {
@@ -183,10 +185,21 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
 		p9stat_free(st);
 		kfree(st);
 	}
+	v9fs_fid_add(root, fid);
 	retval = v9fs_get_acl(inode, fid);
 	if (retval)
 		goto release_sb;
-	v9fs_fid_add(root, fid);
+	/*
+	 * Add the root fid to session info. This is used
+	 * for file system sync. We want a cloned fid here
+	 * so that we can do a sync_filesystem after a
+	 * shrink_dcache_for_umount
+	 */
+	v9ses->root_fid = v9fs_fid_clone(root);
+	if (IS_ERR(v9ses->root_fid)) {
+		retval = PTR_ERR(v9ses->root_fid);
+		goto release_sb;
+	}
 
 	P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
 	return dget(sb->s_root);
@@ -197,15 +210,11 @@ close_session:
 	v9fs_session_close(v9ses);
 	kfree(v9ses);
 	return ERR_PTR(retval);
-
 release_sb:
 	/*
-	 * we will do the session_close and root dentry release
-	 * in the below call. But we need to clunk fid, because we haven't
-	 * attached the fid to dentry so it won't get clunked
-	 * automatically.
+	 * we will do the session_close and root dentry
+	 * release in the below call.
 	 */
-	p9_client_clunk(fid);
 	deactivate_locked_super(sb);
 	return ERR_PTR(retval);
 }
@@ -223,7 +232,7 @@ static void v9fs_kill_super(struct super_block *s)
 	P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
 
 	kill_anon_super(s);
-
+	p9_client_clunk(v9ses->root_fid);
 	v9fs_session_cancel(v9ses);
 	v9fs_session_close(v9ses);
 	kfree(v9ses);
@@ -253,7 +262,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf)
 		goto done;
 	}
 
-	v9ses = v9fs_inode2v9ses(dentry->d_inode);
+	v9ses = v9fs_dentry2v9ses(dentry);
 	if (v9fs_proto_dotl(v9ses)) {
 		res = p9_client_statfs(fid, &rs);
 		if (res == 0) {
@@ -276,11 +285,31 @@ done:
 	return res;
 }
 
+static int v9fs_sync_fs(struct super_block *sb, int wait)
+{
+	struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+	P9_DPRINTK(P9_DEBUG_VFS, "v9fs_sync_fs: super_block %p\n", sb);
+	return p9_client_sync_fs(v9ses->root_fid);
+}
+
+static int v9fs_drop_inode(struct inode *inode)
+{
+	struct v9fs_session_info *v9ses;
+	v9ses = v9fs_inode2v9ses(inode);
+	if (v9ses->cache)
+		return generic_drop_inode(inode);
+	/*
+	 * in case of non cached mode always drop the
+	 * the inode because we want the inode attribute
+	 * to always match that on the server.
+	 */
+	return 1;
+}
+
 static const struct super_operations v9fs_super_ops = {
-#ifdef CONFIG_9P_FSCACHE
 	.alloc_inode = v9fs_alloc_inode,
 	.destroy_inode = v9fs_destroy_inode,
-#endif
 	.statfs = simple_statfs,
 	.evict_inode = v9fs_evict_inode,
 	.show_options = generic_show_options,
@@ -288,11 +317,11 @@ static const struct super_operations v9fs_super_ops = {
 };
 
 static const struct super_operations v9fs_super_ops_dotl = {
-#ifdef CONFIG_9P_FSCACHE
 	.alloc_inode = v9fs_alloc_inode,
 	.destroy_inode = v9fs_destroy_inode,
-#endif
+	.sync_fs = v9fs_sync_fs,
 	.statfs = v9fs_statfs,
+	.drop_inode = v9fs_drop_inode,
 	.evict_inode = v9fs_evict_inode,
 	.show_options = generic_show_options,
 	.umount_begin = v9fs_umount_begin,
@@ -303,5 +332,5 @@ struct file_system_type v9fs_fs_type = {
 	.mount = v9fs_mount,
 	.kill_sb = v9fs_kill_super,
 	.owner = THIS_MODULE,
-	.fs_flags = FS_RENAME_DOES_D_MOVE,
+	.fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT,
 };
diff --git a/fs/Kconfig b/fs/Kconfig
index 3db9caa..f3aa9b0 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -47,7 +47,7 @@ config FS_POSIX_ACL
 	def_bool n
 
 config EXPORTFS
-	tristate
+	bool
 
 config FILE_LOCKING
 	bool "Enable POSIX file locking API" if EXPERT
@@ -187,6 +187,7 @@ source "fs/omfs/Kconfig"
 source "fs/hpfs/Kconfig"
 source "fs/qnx4/Kconfig"
 source "fs/romfs/Kconfig"
+source "fs/pstore/Kconfig"
 source "fs/sysv/Kconfig"
 source "fs/ufs/Kconfig"
 source "fs/exofs/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index a7f7cef..fb68c2b 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -48,6 +48,8 @@ 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_FHANDLE)		+= fhandle.o
+
 obj-y				+= quota/
 
 obj-$(CONFIG_PROC_FS)		+= proc/
@@ -121,3 +123,4 @@ obj-$(CONFIG_BTRFS_FS)		+= btrfs/
 obj-$(CONFIG_GFS2_FS)           += gfs2/
 obj-$(CONFIG_EXOFS_FS)          += exofs/
 obj-$(CONFIG_CEPH_FS)		+= ceph/
+obj-$(CONFIG_PSTORE)		+= pstore/
diff --git a/fs/adfs/Kconfig b/fs/adfs/Kconfig
index 1dd5f34..e55182a 100644
--- a/fs/adfs/Kconfig
+++ b/fs/adfs/Kconfig
@@ -1,7 +1,6 @@
 config ADFS_FS
 	tristate "ADFS file system support (EXPERIMENTAL)"
 	depends on BLOCK && EXPERIMENTAL
-	depends on BKL # need to fix
 	help
 	  The Acorn Disc Filing System is the standard file system of the
 	  RiscOS operating system which runs on Acorn's ARM-based Risc PC
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index 2ff622f..a8a58d8 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -50,6 +50,7 @@ struct adfs_sb_info {
 	gid_t		s_gid;		/* owner gid				 */
 	umode_t		s_owner_mask;	/* ADFS owner perm -> unix perm		 */
 	umode_t		s_other_mask;	/* ADFS other perm -> unix perm		 */
+	int		s_ftsuffix;	/* ,xyz hex filetype suffix option */
 
 	__u32		s_ids_per_zone;	/* max. no ids in one zone		 */
 	__u32		s_idlen;	/* length of ID in map			 */
@@ -79,6 +80,10 @@ struct adfs_dir {
 
 	int			nr_buffers;
 	struct buffer_head	*bh[4];
+
+	/* big directories need allocated buffers */
+	struct buffer_head	**bh_fplus;
+
 	unsigned int		pos;
 	unsigned int		parent_id;
 
@@ -89,7 +94,7 @@ struct adfs_dir {
 /*
  * This is the overall maximum name length
  */
-#define ADFS_MAX_NAME_LEN	256
+#define ADFS_MAX_NAME_LEN	(256 + 4) /* +4 for ,xyz hex filetype suffix */
 struct object_info {
 	__u32		parent_id;		/* parent object id	*/
 	__u32		file_id;		/* object id		*/
@@ -97,10 +102,26 @@ struct object_info {
 	__u32		execaddr;		/* execution address	*/
 	__u32		size;			/* size			*/
 	__u8		attr;			/* RISC OS attributes	*/
-	unsigned char	name_len;		/* name length		*/
+	unsigned int	name_len;		/* name length		*/
 	char		name[ADFS_MAX_NAME_LEN];/* file name		*/
+
+	/* RISC OS file type (12-bit: derived from loadaddr) */
+	__u16		filetype;
 };
 
+/* RISC OS 12-bit filetype converts to ,xyz hex filename suffix */
+static inline int append_filetype_suffix(char *buf, __u16 filetype)
+{
+	if (filetype == -1)
+		return 0;
+
+	*buf++ = ',';
+	*buf++ = hex_asc_lo(filetype >> 8);
+	*buf++ = hex_asc_lo(filetype >> 4);
+	*buf++ = hex_asc_lo(filetype >> 0);
+	return 4;
+}
+
 struct adfs_dir_ops {
 	int	(*read)(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir);
 	int	(*setpos)(struct adfs_dir *dir, unsigned int fpos);
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 3b4a764..3d83075a 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -9,7 +9,6 @@
  *
  *  Common directory handling for ADFS
  */
-#include <linux/smp_lock.h>
 #include "adfs.h"
 
 /*
@@ -27,8 +26,6 @@ adfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	struct adfs_dir dir;
 	int ret = 0;
 
-	lock_kernel();	
-
 	if (filp->f_pos >> 32)
 		goto out;
 
@@ -70,7 +67,6 @@ free_out:
 	ops->free(&dir);
 
 out:
-	unlock_kernel();
 	return ret;
 }
 
@@ -276,7 +272,6 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 	struct object_info obj;
 	int error;
 
-	lock_kernel();
 	error = adfs_dir_lookup_byname(dir, &dentry->d_name, &obj);
 	if (error == 0) {
 		error = -EACCES;
@@ -288,7 +283,6 @@ adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 		if (inode)
 			error = 0;
 	}
-	unlock_kernel();
 	d_add(dentry, inode);
 	return ERR_PTR(error);
 }
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
index bafc712..4bbe853 100644
--- a/fs/adfs/dir_f.c
+++ b/fs/adfs/dir_f.c
@@ -52,7 +52,6 @@ static inline int adfs_readname(char *buf, char *ptr, int maxlen)
 			*buf++ = *ptr;
 		ptr++;
 	}
-	*buf = '\0';
 
 	return buf - old_buf;
 }
@@ -208,7 +207,8 @@ release_buffers:
  * convert a disk-based directory entry to a Linux ADFS directory entry
  */
 static inline void
-adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de)
+adfs_dir2obj(struct adfs_dir *dir, struct object_info *obj,
+	struct adfs_direntry *de)
 {
 	obj->name_len =	adfs_readname(obj->name, de->dirobname, ADFS_F_NAME_LEN);
 	obj->file_id  = adfs_readval(de->dirinddiscadd, 3);
@@ -216,6 +216,23 @@ adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de)
 	obj->execaddr = adfs_readval(de->direxec, 4);
 	obj->size     = adfs_readval(de->dirlen,  4);
 	obj->attr     = de->newdiratts;
+	obj->filetype = -1;
+
+	/*
+	 * object is a file and is filetyped and timestamped?
+	 * RISC OS 12-bit filetype is stored in load_address[19:8]
+	 */
+	if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) &&
+		(0xfff00000 == (0xfff00000 & obj->loadaddr))) {
+		obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8);
+
+		/* optionally append the ,xyz hex filetype suffix */
+		if (ADFS_SB(dir->sb)->s_ftsuffix)
+			obj->name_len +=
+				append_filetype_suffix(
+					&obj->name[obj->name_len],
+					obj->filetype);
+	}
 }
 
 /*
@@ -260,7 +277,7 @@ __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
 	if (!de.dirobname[0])
 		return -ENOENT;
 
-	adfs_dir2obj(obj, &de);
+	adfs_dir2obj(dir, obj, &de);
 
 	return 0;
 }
diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
index 1796bb3..d9e3bee 100644
--- a/fs/adfs/dir_fplus.c
+++ b/fs/adfs/dir_fplus.c
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 #include <linux/buffer_head.h>
+#include <linux/slab.h>
 #include "adfs.h"
 #include "dir_fplus.h"
 
@@ -22,30 +23,53 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct
 
 	dir->nr_buffers = 0;
 
+	/* start off using fixed bh set - only alloc for big dirs */
+	dir->bh_fplus = &dir->bh[0];
+
 	block = __adfs_block_map(sb, id, 0);
 	if (!block) {
 		adfs_error(sb, "dir object %X has a hole at offset 0", id);
 		goto out;
 	}
 
-	dir->bh[0] = sb_bread(sb, block);
-	if (!dir->bh[0])
+	dir->bh_fplus[0] = sb_bread(sb, block);
+	if (!dir->bh_fplus[0])
 		goto out;
 	dir->nr_buffers += 1;
 
-	h = (struct adfs_bigdirheader *)dir->bh[0]->b_data;
+	h = (struct adfs_bigdirheader *)dir->bh_fplus[0]->b_data;
 	size = le32_to_cpu(h->bigdirsize);
 	if (size != sz) {
-		printk(KERN_WARNING "adfs: adfs_fplus_read: directory header size\n"
-				" does not match directory size\n");
+		printk(KERN_WARNING "adfs: adfs_fplus_read:"
+					" directory header size %X\n"
+					" does not match directory size %X\n",
+					size, sz);
 	}
 
 	if (h->bigdirversion[0] != 0 || h->bigdirversion[1] != 0 ||
 	    h->bigdirversion[2] != 0 || size & 2047 ||
-	    h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME))
+	    h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME)) {
+		printk(KERN_WARNING "adfs: dir object %X has"
+					" malformed dir header\n", id);
 		goto out;
+	}
 
 	size >>= sb->s_blocksize_bits;
+	if (size > sizeof(dir->bh)/sizeof(dir->bh[0])) {
+		/* this directory is too big for fixed bh set, must allocate */
+		struct buffer_head **bh_fplus =
+			kzalloc(size * sizeof(struct buffer_head *),
+				GFP_KERNEL);
+		if (!bh_fplus) {
+			adfs_error(sb, "not enough memory for"
+					" dir object %X (%d blocks)", id, size);
+			goto out;
+		}
+		dir->bh_fplus = bh_fplus;
+		/* copy over the pointer to the block that we've already read */
+		dir->bh_fplus[0] = dir->bh[0];
+	}
+
 	for (blk = 1; blk < size; blk++) {
 		block = __adfs_block_map(sb, id, blk);
 		if (!block) {
@@ -53,25 +77,44 @@ adfs_fplus_read(struct super_block *sb, unsigned int id, unsigned int sz, struct
 			goto out;
 		}
 
-		dir->bh[blk] = sb_bread(sb, block);
-		if (!dir->bh[blk])
+		dir->bh_fplus[blk] = sb_bread(sb, block);
+		if (!dir->bh_fplus[blk]) {
+			adfs_error(sb,	"dir object %X failed read for"
+					" offset %d, mapped block %X",
+					id, blk, block);
 			goto out;
-		dir->nr_buffers = blk;
+		}
+
+		dir->nr_buffers += 1;
 	}
 
-	t = (struct adfs_bigdirtail *)(dir->bh[size - 1]->b_data + (sb->s_blocksize - 8));
+	t = (struct adfs_bigdirtail *)
+		(dir->bh_fplus[size - 1]->b_data + (sb->s_blocksize - 8));
 
 	if (t->bigdirendname != cpu_to_le32(BIGDIRENDNAME) ||
 	    t->bigdirendmasseq != h->startmasseq ||
-	    t->reserved[0] != 0 || t->reserved[1] != 0)
+	    t->reserved[0] != 0 || t->reserved[1] != 0) {
+		printk(KERN_WARNING "adfs: dir object %X has "
+					"malformed dir end\n", id);
 		goto out;
+	}
 
 	dir->parent_id = le32_to_cpu(h->bigdirparent);
 	dir->sb = sb;
 	return 0;
+
 out:
-	for (i = 0; i < dir->nr_buffers; i++)
-		brelse(dir->bh[i]);
+	if (dir->bh_fplus) {
+		for (i = 0; i < dir->nr_buffers; i++)
+			brelse(dir->bh_fplus[i]);
+
+		if (&dir->bh[0] != dir->bh_fplus)
+			kfree(dir->bh_fplus);
+
+		dir->bh_fplus = NULL;
+	}
+
+	dir->nr_buffers = 0;
 	dir->sb = NULL;
 	return ret;
 }
@@ -79,7 +122,8 @@ out:
 static int
 adfs_fplus_setpos(struct adfs_dir *dir, unsigned int fpos)
 {
-	struct adfs_bigdirheader *h = (struct adfs_bigdirheader *)dir->bh[0]->b_data;
+	struct adfs_bigdirheader *h =
+		(struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data;
 	int ret = -ENOENT;
 
 	if (fpos <= le32_to_cpu(h->bigdirentries)) {
@@ -102,21 +146,27 @@ dir_memcpy(struct adfs_dir *dir, unsigned int offset, void *to, int len)
 	partial = sb->s_blocksize - offset;
 
 	if (partial >= len)
-		memcpy(to, dir->bh[buffer]->b_data + offset, len);
+		memcpy(to, dir->bh_fplus[buffer]->b_data + offset, len);
 	else {
 		char *c = (char *)to;
 
 		remainder = len - partial;
 
-		memcpy(c, dir->bh[buffer]->b_data + offset, partial);
-		memcpy(c + partial, dir->bh[buffer + 1]->b_data, remainder);
+		memcpy(c,
+			dir->bh_fplus[buffer]->b_data + offset,
+			partial);
+
+		memcpy(c + partial,
+			dir->bh_fplus[buffer + 1]->b_data,
+			remainder);
 	}
 }
 
 static int
 adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
 {
-	struct adfs_bigdirheader *h = (struct adfs_bigdirheader *)dir->bh[0]->b_data;
+	struct adfs_bigdirheader *h =
+		(struct adfs_bigdirheader *) dir->bh_fplus[0]->b_data;
 	struct adfs_bigdirentry bde;
 	unsigned int offset;
 	int i, ret = -ENOENT;
@@ -147,6 +197,24 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
 		if (obj->name[i] == '/')
 			obj->name[i] = '.';
 
+	obj->filetype = -1;
+
+	/*
+	 * object is a file and is filetyped and timestamped?
+	 * RISC OS 12-bit filetype is stored in load_address[19:8]
+	 */
+	if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) &&
+		(0xfff00000 == (0xfff00000 & obj->loadaddr))) {
+		obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8);
+
+		/* optionally append the ,xyz hex filetype suffix */
+		if (ADFS_SB(dir->sb)->s_ftsuffix)
+			obj->name_len +=
+				append_filetype_suffix(
+					&obj->name[obj->name_len],
+					obj->filetype);
+	}
+
 	dir->pos += 1;
 	ret = 0;
 out:
@@ -160,7 +228,7 @@ adfs_fplus_sync(struct adfs_dir *dir)
 	int i;
 
 	for (i = dir->nr_buffers - 1; i >= 0; i--) {
-		struct buffer_head *bh = dir->bh[i];
+		struct buffer_head *bh = dir->bh_fplus[i];
 		sync_dirty_buffer(bh);
 		if (buffer_req(bh) && !buffer_uptodate(bh))
 			err = -EIO;
@@ -174,8 +242,17 @@ adfs_fplus_free(struct adfs_dir *dir)
 {
 	int i;
 
-	for (i = 0; i < dir->nr_buffers; i++)
-		brelse(dir->bh[i]);
+	if (dir->bh_fplus) {
+		for (i = 0; i < dir->nr_buffers; i++)
+			brelse(dir->bh_fplus[i]);
+
+		if (&dir->bh[0] != dir->bh_fplus)
+			kfree(dir->bh_fplus);
+
+		dir->bh_fplus = NULL;
+	}
+
+	dir->nr_buffers = 0;
 	dir->sb = NULL;
 }
 
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 65794b8..92444e9 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -7,7 +7,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 #include "adfs.h"
@@ -79,26 +78,13 @@ static const struct address_space_operations adfs_aops = {
 	.bmap		= _adfs_bmap
 };
 
-static inline unsigned int
-adfs_filetype(struct inode *inode)
-{
-	unsigned int type;
-
-	if (ADFS_I(inode)->stamped)
-		type = (ADFS_I(inode)->loadaddr >> 8) & 0xfff;
-	else
-		type = (unsigned int) -1;
-
-	return type;
-}
-
 /*
  * Convert ADFS attributes and filetype to Linux permission.
  */
 static umode_t
 adfs_atts2mode(struct super_block *sb, struct inode *inode)
 {
-	unsigned int filetype, attr = ADFS_I(inode)->attr;
+	unsigned int attr = ADFS_I(inode)->attr;
 	umode_t mode, rmask;
 	struct adfs_sb_info *asb = ADFS_SB(sb);
 
@@ -107,9 +93,7 @@ adfs_atts2mode(struct super_block *sb, struct inode *inode)
 		return S_IFDIR | S_IXUGO | mode;
 	}
 
-	filetype = adfs_filetype(inode);
-
-	switch (filetype) {
+	switch (ADFS_I(inode)->filetype) {
 	case 0xfc0:	/* LinkFS */
 		return S_IFLNK|S_IRWXUGO;
 
@@ -175,50 +159,48 @@ adfs_mode2atts(struct super_block *sb, struct inode *inode)
 
 /*
  * Convert an ADFS time to Unix time.  ADFS has a 40-bit centi-second time
- * referenced to 1 Jan 1900 (til 2248)
+ * referenced to 1 Jan 1900 (til 2248) so we need to discard 2208988800 seconds
+ * of time to convert from RISC OS epoch to Unix epoch.
  */
 static void
 adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
 {
 	unsigned int high, low;
+	/* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since
+	 * 01 Jan 1900 00:00:00 (RISC OS epoch)
+	 */
+	static const s64 nsec_unix_epoch_diff_risc_os_epoch =
+							2208988800000000000LL;
+	s64 nsec;
 
 	if (ADFS_I(inode)->stamped == 0)
 		goto cur_time;
 
-	high = ADFS_I(inode)->loadaddr << 24;
-	low  = ADFS_I(inode)->execaddr;
+	high = ADFS_I(inode)->loadaddr & 0xFF; /* top 8 bits of timestamp */
+	low  = ADFS_I(inode)->execaddr;    /* bottom 32 bits of timestamp */
 
-	high |= low >> 8;
-	low  &= 255;
+	/* convert 40-bit centi-seconds to 32-bit seconds
+	 * going via nanoseconds to retain precision
+	 */
+	nsec = (((s64) high << 32) | (s64) low) * 10000000; /* cs to ns */
 
 	/* Files dated pre  01 Jan 1970 00:00:00. */
-	if (high < 0x336e996a)
+	if (nsec < nsec_unix_epoch_diff_risc_os_epoch)
 		goto too_early;
 
-	/* Files dated post 18 Jan 2038 03:14:05. */
-	if (high >= 0x656e9969)
-		goto too_late;
-
-	/* discard 2208988800 (0x336e996a00) seconds of time */
-	high -= 0x336e996a;
+	/* convert from RISC OS to Unix epoch */
+	nsec -= nsec_unix_epoch_diff_risc_os_epoch;
 
-	/* convert 40-bit centi-seconds to 32-bit seconds */
-	tv->tv_sec = (((high % 100) << 8) + low) / 100 + (high / 100 << 8);
-	tv->tv_nsec = 0;
+	*tv = ns_to_timespec(nsec);
 	return;
 
  cur_time:
-	*tv = CURRENT_TIME_SEC;
+	*tv = CURRENT_TIME;
 	return;
 
  too_early:
 	tv->tv_sec = tv->tv_nsec = 0;
 	return;
-
- too_late:
-	tv->tv_sec = 0x7ffffffd;
-	tv->tv_nsec = 0;
-	return;
 }
 
 /*
@@ -280,7 +262,8 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
 	ADFS_I(inode)->loadaddr  = obj->loadaddr;
 	ADFS_I(inode)->execaddr  = obj->execaddr;
 	ADFS_I(inode)->attr      = obj->attr;
-	ADFS_I(inode)->stamped	  = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
+	ADFS_I(inode)->filetype  = obj->filetype;
+	ADFS_I(inode)->stamped   = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
 
 	inode->i_mode	 = adfs_atts2mode(sb, inode);
 	adfs_adfs2unix_time(&inode->i_mtime, inode);
@@ -316,8 +299,6 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
 	unsigned int ia_valid = attr->ia_valid;
 	int error;
 	
-	lock_kernel();
-
 	error = inode_change_ok(inode, attr);
 
 	/*
@@ -359,7 +340,6 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
 	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
 		mark_inode_dirty(inode);
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -374,7 +354,6 @@ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	struct object_info obj;
 	int ret;
 
-	lock_kernel();
 	obj.file_id	= inode->i_ino;
 	obj.name_len	= 0;
 	obj.parent_id	= ADFS_I(inode)->parent_id;
@@ -384,6 +363,5 @@ int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
 	obj.size	= inode->i_size;
 
 	ret = adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
-	unlock_kernel();
 	return ret;
 }
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 2d79540..c8bf36a 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -14,7 +14,6 @@
 #include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/statfs.h>
 #include "adfs.h"
 #include "dir_f.h"
@@ -120,15 +119,11 @@ static void adfs_put_super(struct super_block *sb)
 	int i;
 	struct adfs_sb_info *asb = ADFS_SB(sb);
 
-	lock_kernel();
-
 	for (i = 0; i < asb->s_map_size; i++)
 		brelse(asb->s_map[i].dm_bh);
 	kfree(asb->s_map);
 	kfree(asb);
 	sb->s_fs_info = NULL;
-
-	unlock_kernel();
 }
 
 static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
@@ -143,17 +138,20 @@ static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt)
 		seq_printf(seq, ",ownmask=%o", asb->s_owner_mask);
 	if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK)
 		seq_printf(seq, ",othmask=%o", asb->s_other_mask);
+	if (asb->s_ftsuffix != 0)
+		seq_printf(seq, ",ftsuffix=%u", asb->s_ftsuffix);
 
 	return 0;
 }
 
-enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_err};
+enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix, Opt_err};
 
 static const match_table_t tokens = {
 	{Opt_uid, "uid=%u"},
 	{Opt_gid, "gid=%u"},
 	{Opt_ownmask, "ownmask=%o"},
 	{Opt_othmask, "othmask=%o"},
+	{Opt_ftsuffix, "ftsuffix=%u"},
 	{Opt_err, NULL}
 };
 
@@ -194,6 +192,11 @@ static int parse_options(struct super_block *sb, char *options)
 				return -EINVAL;
 			asb->s_other_mask = option;
 			break;
+		case Opt_ftsuffix:
+			if (match_int(args, &option))
+				return -EINVAL;
+			asb->s_ftsuffix = option;
+			break;
 		default:
 			printk("ADFS-fs: unrecognised mount option \"%s\" "
 					"or missing value\n", p);
@@ -359,15 +362,11 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 	struct adfs_sb_info *asb;
 	struct inode *root;
 
-	lock_kernel();
-
 	sb->s_flags |= MS_NODIRATIME;
 
 	asb = kzalloc(sizeof(*asb), GFP_KERNEL);
-	if (!asb) {
-		unlock_kernel();
+	if (!asb)
 		return -ENOMEM;
-	}
 	sb->s_fs_info = asb;
 
 	/* set default options */
@@ -375,6 +374,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 	asb->s_gid = 0;
 	asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK;
 	asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK;
+	asb->s_ftsuffix = 0;
 
 	if (parse_options(sb, data))
 		goto error;
@@ -454,11 +454,13 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 
 	root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root);
 	root_obj.name_len  = 0;
-	root_obj.loadaddr  = 0;
-	root_obj.execaddr  = 0;
+	/* Set root object date as 01 Jan 1987 00:00:00 */
+	root_obj.loadaddr  = 0xfff0003f;
+	root_obj.execaddr  = 0xec22c000;
 	root_obj.size	   = ADFS_NEWDIR_SIZE;
 	root_obj.attr	   = ADFS_NDA_DIRECTORY   | ADFS_NDA_OWNER_READ |
 			     ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ;
+	root_obj.filetype  = -1;
 
 	/*
 	 * If this is a F+ disk with variable length directories,
@@ -472,6 +474,12 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 		asb->s_dir     = &adfs_f_dir_ops;
 		asb->s_namelen = ADFS_F_NAME_LEN;
 	}
+	/*
+	 * ,xyz hex filetype suffix may be added by driver
+	 * to files that have valid RISC OS filetype
+	 */
+	if (asb->s_ftsuffix)
+		asb->s_namelen += 4;
 
 	sb->s_d_op = &adfs_dentry_operations;
 	root = adfs_iget(sb, &root_obj);
@@ -485,7 +493,6 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 		adfs_error(sb, "get root inode failed\n");
 		goto error;
 	}
-	unlock_kernel();
 	return 0;
 
 error_free_bh:
@@ -493,7 +500,6 @@ error_free_bh:
 error:
 	sb->s_fs_info = NULL;
 	kfree(asb);
-	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/affs/Makefile b/fs/affs/Makefile
index b2c4f54..3988b4a 100644
--- a/fs/affs/Makefile
+++ b/fs/affs/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Linux affs filesystem routines.
 #
 
-#EXTRA_CFLAGS=-DDEBUG=1
+#ccflags-y := -DDEBUG=1
 
 obj-$(CONFIG_AFFS_FS) += affs.o
 
diff --git a/fs/aio.c b/fs/aio.c
index 26869cd..ebb6a22 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -85,7 +85,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 = create_workqueue("aio");
+	aio_wq = alloc_workqueue("aio", 0, 1);	/* used to limit concurrency */
 	abe_pool = mempool_create_kmalloc_pool(1, sizeof(struct aio_batch_entry));
 	BUG_ON(!aio_wq || !abe_pool);
 
@@ -520,7 +520,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
 	ctx->reqs_active--;
 
 	if (unlikely(!ctx->reqs_active && ctx->dead))
-		wake_up(&ctx->wait);
+		wake_up_all(&ctx->wait);
 }
 
 static void aio_fput_routine(struct work_struct *data)
@@ -577,7 +577,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 		spin_lock(&fput_lock);
 		list_add(&req->ki_list, &fput_head);
 		spin_unlock(&fput_lock);
-		queue_work(aio_wq, &fput_work);
+		schedule_work(&fput_work);
 	} else {
 		req->ki_filp = NULL;
 		really_put_req(ctx, req);
@@ -1229,7 +1229,7 @@ static void io_destroy(struct kioctx *ioctx)
 	 * by other CPUs at this point.  Right now, we rely on the
 	 * locking done by the above calls to ensure this consistency.
 	 */
-	wake_up(&ioctx->wait);
+	wake_up_all(&ioctx->wait);
 	put_ioctx(ioctx);	/* once for the lookup */
 }
 
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 014e7ab..e6f84d2 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -36,7 +36,7 @@ static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
 static int autofs4_dir_open(struct inode *inode, struct file *file);
 static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
 static struct vfsmount *autofs4_d_automount(struct path *);
-static int autofs4_d_manage(struct dentry *, bool, bool);
+static int autofs4_d_manage(struct dentry *, bool);
 static void autofs4_dentry_release(struct dentry *);
 
 const struct file_operations autofs4_root_operations = {
@@ -446,7 +446,7 @@ done:
 	return NULL;
 }
 
-int autofs4_d_manage(struct dentry *dentry, bool mounting_here, bool rcu_walk)
+int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
 {
 	struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
 
@@ -454,7 +454,7 @@ int autofs4_d_manage(struct dentry *dentry, bool mounting_here, bool rcu_walk)
 		dentry, dentry->d_name.len, dentry->d_name.name);
 
 	/* The daemon never waits. */
-	if (autofs4_oz_mode(sbi) || mounting_here) {
+	if (autofs4_oz_mode(sbi)) {
 		if (!d_mountpoint(dentry))
 			return -EISDIR;
 		return 0;
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 685ecff..b14cebf 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -97,7 +97,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	if (!inode)
 		return -ENOSPC;
 	mutex_lock(&info->bfs_lock);
-	ino = find_first_zero_bit(info->si_imap, info->si_lasti);
+	ino = find_first_zero_bit(info->si_imap, info->si_lasti + 1);
 	if (ino > info->si_lasti) {
 		mutex_unlock(&info->bfs_lock);
 		iput(inode);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index d5b640b..b2fae009 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -570,7 +570,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 	unsigned long elf_entry;
 	unsigned long interp_load_addr = 0;
 	unsigned long start_code, end_code, start_data, end_data;
-	unsigned long reloc_func_desc = 0;
+	unsigned long reloc_func_desc __maybe_unused = 0;
 	int executable_stack = EXSTACK_DEFAULT;
 	unsigned long def_flags = 0;
 	struct {
diff --git a/fs/bio.c b/fs/bio.c
index 4bd454f..4cf2a52 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -111,7 +111,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
 	if (!slab)
 		goto out_unlock;
 
-	printk("bio: create slab <%s> at %d\n", bslab->name, entry);
+	printk(KERN_INFO "bio: create slab <%s> at %d\n", bslab->name, entry);
 	bslab->slab = slab;
 	bslab->slab_ref = 1;
 	bslab->slab_size = sz;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index e1aa8d6..100b07f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2493,7 +2493,7 @@ int close_ctree(struct btrfs_root *root)
 	 * ERROR state on disk.
 	 *
 	 * 2. when btrfs flips readonly just in btrfs_commit_super,
-	 * and in such case, btrfs cannnot write sb via btrfs_commit_super,
+	 * and in such case, btrfs cannot write sb via btrfs_commit_super,
 	 * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag,
 	 * btrfs will cleanup all FS resources first and write sb then.
 	 */
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index ff27d7a..b4ffad8 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -21,9 +21,13 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
 	int len = *max_len;
 	int type;
 
-	if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) ||
-	    (connectable && len < BTRFS_FID_SIZE_CONNECTABLE))
+	if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
+		*max_len = BTRFS_FID_SIZE_CONNECTABLE;
 		return 255;
+	} else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
+		*max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
+		return 255;
+	}
 
 	len  = BTRFS_FID_SIZE_NON_CONNECTABLE;
 	type = FILEID_BTRFS_WITHOUT_PARENT;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 9007bbd..512c3d1 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -90,13 +90,14 @@ static noinline int cow_file_range(struct inode *inode,
 				   unsigned long *nr_written, int unlock);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
-				     struct inode *inode,  struct inode *dir)
+				     struct inode *inode,  struct inode *dir,
+				     const struct qstr *qstr)
 {
 	int err;
 
 	err = btrfs_init_acl(trans, inode, dir);
 	if (!err)
-		err = btrfs_xattr_security_init(trans, inode, dir);
+		err = btrfs_xattr_security_init(trans, inode, dir, qstr);
 	return err;
 }
 
@@ -4704,7 +4705,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(trans, inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -4765,7 +4766,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(trans, inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
@@ -4806,9 +4807,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
 	int err;
 	int drop_inode = 0;
 
-	if (inode->i_nlink == 0)
-		return -ENOENT;
-
 	/* do not allow sys_link's with other subvols of the same device */
 	if (root->objectid != BTRFS_I(inode)->root->objectid)
 		return -EPERM;
@@ -4894,7 +4892,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
 	drop_on_err = 1;
 
-	err = btrfs_init_inode_security(trans, inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
 	if (err)
 		goto out_fail;
 
@@ -7106,7 +7104,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
 	if (IS_ERR(inode))
 		goto out_unlock;
 
-	err = btrfs_init_inode_security(trans, inode, dir);
+	err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
 	if (err) {
 		drop_inode = 1;
 		goto out_unlock;
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index a577653..d779cef 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -370,7 +370,8 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
 }
 
 int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
-			      struct inode *inode, struct inode *dir)
+			      struct inode *inode, struct inode *dir,
+			      const struct qstr *qstr)
 {
 	int err;
 	size_t len;
@@ -378,7 +379,8 @@ int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
 	char *suffix;
 	char *name;
 
-	err = security_inode_init_security(inode, dir, &suffix, &value, &len);
+	err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
+					   &len);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			return 0;
diff --git a/fs/btrfs/xattr.h b/fs/btrfs/xattr.h
index 7a43fd6..b3cc803 100644
--- a/fs/btrfs/xattr.h
+++ b/fs/btrfs/xattr.h
@@ -37,6 +37,7 @@ extern int btrfs_setxattr(struct dentry *dentry, const char *name,
 extern int btrfs_removexattr(struct dentry *dentry, const char *name);
 
 extern int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
-				     struct inode *inode, struct inode *dir);
+				     struct inode *inode, struct inode *dir,
+				     const struct qstr *qstr);
 
 #endif /* __XATTR__ */
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c
index f5ec2d4..faccd47 100644
--- a/fs/btrfs/zlib.c
+++ b/fs/btrfs/zlib.c
@@ -57,7 +57,8 @@ static struct list_head *zlib_alloc_workspace(void)
 	if (!workspace)
 		return ERR_PTR(-ENOMEM);
 
-	workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize());
+	workspace->def_strm.workspace = vmalloc(zlib_deflate_workspacesize(
+						MAX_WBITS, MAX_MEM_LEVEL));
 	workspace->inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
 	workspace->buf = kmalloc(PAGE_CACHE_SIZE, GFP_NOFS);
 	if (!workspace->def_strm.workspace ||
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 42c7faf..a0358c2 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -275,6 +275,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 				  bool preemptive)
 {
 	struct dentry *grave, *trap;
+	struct path path, path_to_graveyard;
 	char nbuffer[8 + 8 + 1];
 	int ret;
 
@@ -287,10 +288,18 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 	/* non-directories can just be unlinked */
 	if (!S_ISDIR(rep->d_inode->i_mode)) {
 		_debug("unlink stale object");
-		ret = vfs_unlink(dir->d_inode, rep);
 
-		if (preemptive)
-			cachefiles_mark_object_buried(cache, rep);
+		path.mnt = cache->mnt;
+		path.dentry = dir;
+		ret = security_path_unlink(&path, rep);
+		if (ret < 0) {
+			cachefiles_io_error(cache, "Unlink security error");
+		} else {
+			ret = vfs_unlink(dir->d_inode, rep);
+
+			if (preemptive)
+				cachefiles_mark_object_buried(cache, rep);
+		}
 
 		mutex_unlock(&dir->d_inode->i_mutex);
 
@@ -379,12 +388,23 @@ try_again:
 	}
 
 	/* attempt the rename */
-	ret = vfs_rename(dir->d_inode, rep, cache->graveyard->d_inode, grave);
-	if (ret != 0 && ret != -ENOMEM)
-		cachefiles_io_error(cache, "Rename failed with error %d", ret);
+	path.mnt = cache->mnt;
+	path.dentry = dir;
+	path_to_graveyard.mnt = cache->mnt;
+	path_to_graveyard.dentry = cache->graveyard;
+	ret = security_path_rename(&path, rep, &path_to_graveyard, grave);
+	if (ret < 0) {
+		cachefiles_io_error(cache, "Rename security error %d", ret);
+	} else {
+		ret = vfs_rename(dir->d_inode, rep,
+				 cache->graveyard->d_inode, grave);
+		if (ret != 0 && ret != -ENOMEM)
+			cachefiles_io_error(cache,
+					    "Rename failed with error %d", ret);
 
-	if (preemptive)
-		cachefiles_mark_object_buried(cache, rep);
+		if (preemptive)
+			cachefiles_mark_object_buried(cache, rep);
+	}
 
 	unlock_rename(cache->graveyard, dir);
 	dput(grave);
@@ -448,6 +468,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
 {
 	struct cachefiles_cache *cache;
 	struct dentry *dir, *next = NULL;
+	struct path path;
 	unsigned long start;
 	const char *name;
 	int ret, nlen;
@@ -458,6 +479,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
 
 	cache = container_of(parent->fscache.cache,
 			     struct cachefiles_cache, cache);
+	path.mnt = cache->mnt;
 
 	ASSERT(parent->dentry);
 	ASSERT(parent->dentry->d_inode);
@@ -511,6 +533,10 @@ lookup_again:
 			if (ret < 0)
 				goto create_error;
 
+			path.dentry = dir;
+			ret = security_path_mkdir(&path, next, 0);
+			if (ret < 0)
+				goto create_error;
 			start = jiffies;
 			ret = vfs_mkdir(dir->d_inode, next, 0);
 			cachefiles_hist(cachefiles_mkdir_histogram, start);
@@ -536,6 +562,10 @@ lookup_again:
 			if (ret < 0)
 				goto create_error;
 
+			path.dentry = dir;
+			ret = security_path_mknod(&path, next, S_IFREG, 0);
+			if (ret < 0)
+				goto create_error;
 			start = jiffies;
 			ret = vfs_create(dir->d_inode, next, S_IFREG, NULL);
 			cachefiles_hist(cachefiles_create_histogram, start);
@@ -692,6 +722,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
 {
 	struct dentry *subdir;
 	unsigned long start;
+	struct path path;
 	int ret;
 
 	_enter(",,%s", dirname);
@@ -719,6 +750,11 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
 
 		_debug("attempt mkdir");
 
+		path.mnt = cache->mnt;
+		path.dentry = dir;
+		ret = security_path_mkdir(&path, subdir, 0700);
+		if (ret < 0)
+			goto mkdir_error;
 		ret = vfs_mkdir(dir->d_inode, subdir, 0700);
 		if (ret < 0)
 			goto mkdir_error;
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 08f65fa..0dba691 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -210,8 +210,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 	if (!fsc->debugfs_congestion_kb)
 		goto out;
 
-	dout("a\n");
-
 	snprintf(name, sizeof(name), "../../bdi/%s",
 		 dev_name(fsc->backing_dev_info.dev));
 	fsc->debugfs_bdi =
@@ -221,7 +219,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 	if (!fsc->debugfs_bdi)
 		goto out;
 
-	dout("b\n");
 	fsc->debugfs_mdsmap = debugfs_create_file("mdsmap",
 					0600,
 					fsc->client->debugfs_dir,
@@ -230,7 +227,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 	if (!fsc->debugfs_mdsmap)
 		goto out;
 
-	dout("ca\n");
 	fsc->debugfs_mdsc = debugfs_create_file("mdsc",
 						0600,
 						fsc->client->debugfs_dir,
@@ -239,7 +235,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 	if (!fsc->debugfs_mdsc)
 		goto out;
 
-	dout("da\n");
 	fsc->debugfs_caps = debugfs_create_file("caps",
 						   0400,
 						   fsc->client->debugfs_dir,
@@ -248,7 +243,6 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc)
 	if (!fsc->debugfs_caps)
 		goto out;
 
-	dout("ea\n");
 	fsc->debugfs_dentry_lru = debugfs_create_file("dentry_lru",
 					0600,
 					fsc->client->debugfs_dir,
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index ebafa65..1a867a3 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -161,7 +161,7 @@ more:
 	filp->f_pos = di->offset;
 	err = filldir(dirent, dentry->d_name.name,
 		      dentry->d_name.len, di->offset,
-		      dentry->d_inode->i_ino,
+		      ceph_translate_ino(dentry->d_sb, dentry->d_inode->i_ino),
 		      dentry->d_inode->i_mode >> 12);
 
 	if (last) {
@@ -245,15 +245,17 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 		dout("readdir off 0 -> '.'\n");
 		if (filldir(dirent, ".", 1, ceph_make_fpos(0, 0),
-			    inode->i_ino, inode->i_mode >> 12) < 0)
+			    ceph_translate_ino(inode->i_sb, inode->i_ino),
+			    inode->i_mode >> 12) < 0)
 			return 0;
 		filp->f_pos = 1;
 		off = 1;
 	}
 	if (filp->f_pos == 1) {
+		ino_t ino = filp->f_dentry->d_parent->d_inode->i_ino;
 		dout("readdir off 1 -> '..'\n");
 		if (filldir(dirent, "..", 2, ceph_make_fpos(0, 1),
-			    filp->f_dentry->d_parent->d_inode->i_ino,
+			    ceph_translate_ino(inode->i_sb, ino),
 			    inode->i_mode >> 12) < 0)
 			return 0;
 		filp->f_pos = 2;
@@ -377,7 +379,8 @@ more:
 		if (filldir(dirent,
 			    rinfo->dir_dname[off - fi->offset],
 			    rinfo->dir_dname_len[off - fi->offset],
-			    pos, ino, ftype) < 0) {
+			    pos,
+			    ceph_translate_ino(inode->i_sb, ino), ftype) < 0) {
 			dout("filldir stopping us...\n");
 			return 0;
 		}
@@ -1024,14 +1027,13 @@ out_touch:
 }
 
 /*
- * When a dentry is released, clear the dir I_COMPLETE if it was part
- * of the current dir gen or if this is in the snapshot namespace.
+ * Release our ceph_dentry_info.
  */
-static void ceph_dentry_release(struct dentry *dentry)
+static void ceph_d_release(struct dentry *dentry)
 {
 	struct ceph_dentry_info *di = ceph_dentry(dentry);
 
-	dout("dentry_release %p\n", dentry);
+	dout("d_release %p\n", dentry);
 	if (di) {
 		ceph_dentry_lru_del(dentry);
 		if (di->lease_session)
@@ -1256,14 +1258,14 @@ const struct inode_operations ceph_dir_iops = {
 
 const struct dentry_operations ceph_dentry_ops = {
 	.d_revalidate = ceph_d_revalidate,
-	.d_release = ceph_dentry_release,
+	.d_release = ceph_d_release,
 };
 
 const struct dentry_operations ceph_snapdir_dentry_ops = {
 	.d_revalidate = ceph_snapdir_d_revalidate,
-	.d_release = ceph_dentry_release,
+	.d_release = ceph_d_release,
 };
 
 const struct dentry_operations ceph_snap_dentry_ops = {
-	.d_release = ceph_dentry_release,
+	.d_release = ceph_d_release,
 };
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 7d0e4a8..159b512 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -564,11 +564,19 @@ more:
 			 * start_request so that a tid has been assigned.
 			 */
 			spin_lock(&ci->i_unsafe_lock);
-			list_add(&req->r_unsafe_item, &ci->i_unsafe_writes);
+			list_add_tail(&req->r_unsafe_item,
+				      &ci->i_unsafe_writes);
 			spin_unlock(&ci->i_unsafe_lock);
 			ceph_get_cap_refs(ci, CEPH_CAP_FILE_WR);
 		}
+		
 		ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
+		if (ret < 0 && req->r_safe_callback) {
+			spin_lock(&ci->i_unsafe_lock);
+			list_del_init(&req->r_unsafe_item);
+			spin_unlock(&ci->i_unsafe_lock);
+			ceph_put_cap_refs(ci, CEPH_CAP_FILE_WR);
+		}
 	}
 
 	if (file->f_flags & O_DIRECT)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 193bfa5..b54c97d 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -36,6 +36,13 @@ static void ceph_vmtruncate_work(struct work_struct *work);
 /*
  * find or create an inode, given the ceph ino number
  */
+static int ceph_set_ino_cb(struct inode *inode, void *data)
+{
+	ceph_inode(inode)->i_vino = *(struct ceph_vino *)data;
+	inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data);
+	return 0;
+}
+
 struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino)
 {
 	struct inode *inode;
@@ -1030,9 +1037,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 			dout("fill_trace doing d_move %p -> %p\n",
 			     req->r_old_dentry, dn);
 
-			/* d_move screws up d_subdirs order */
-			ceph_i_clear(dir, CEPH_I_COMPLETE);
-
 			d_move(req->r_old_dentry, dn);
 			dout(" src %p '%.*s' dst %p '%.*s'\n",
 			     req->r_old_dentry,
@@ -1044,12 +1048,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req,
 			   rehashing bug in vfs_rename_dir */
 			ceph_invalidate_dentry_lease(dn);
 
-			/* take overwritten dentry's readdir offset */
-			dout("dn %p gets %p offset %lld (old offset %lld)\n",
-			     req->r_old_dentry, dn, ceph_dentry(dn)->offset,
+			/*
+			 * d_move() puts the renamed dentry at the end of
+			 * d_subdirs.  We need to assign it an appropriate
+			 * directory offset so we can behave when holding
+			 * I_COMPLETE.
+			 */
+			ceph_set_dentry_offset(req->r_old_dentry);
+			dout("dn %p gets new offset %lld\n", req->r_old_dentry, 
 			     ceph_dentry(req->r_old_dentry)->offset);
-			ceph_dentry(req->r_old_dentry)->offset =
-				ceph_dentry(dn)->offset;
 
 			dn = req->r_old_dentry;  /* use old_dentry */
 			in = dn->d_inode;
@@ -1809,7 +1816,7 @@ int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	err = ceph_do_getattr(inode, CEPH_STAT_CAP_INODE_ALL);
 	if (!err) {
 		generic_fillattr(inode, stat);
-		stat->ino = inode->i_ino;
+		stat->ino = ceph_translate_ino(inode->i_sb, inode->i_ino);
 		if (ceph_snap(inode) != CEPH_NOSNAP)
 			stat->dev = ceph_snap(inode);
 		else
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 9c50854..a9e78b4 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -131,6 +131,7 @@ enum {
 	Opt_rbytes,
 	Opt_norbytes,
 	Opt_noasyncreaddir,
+	Opt_ino32,
 };
 
 static match_table_t fsopt_tokens = {
@@ -150,6 +151,7 @@ static match_table_t fsopt_tokens = {
 	{Opt_rbytes, "rbytes"},
 	{Opt_norbytes, "norbytes"},
 	{Opt_noasyncreaddir, "noasyncreaddir"},
+	{Opt_ino32, "ino32"},
 	{-1, NULL}
 };
 
@@ -225,6 +227,9 @@ static int parse_fsopt_token(char *c, void *private)
 	case Opt_noasyncreaddir:
 		fsopt->flags |= CEPH_MOUNT_OPT_NOASYNCREADDIR;
 		break;
+	case Opt_ino32:
+		fsopt->flags |= CEPH_MOUNT_OPT_INO32;
+		break;
 	default:
 		BUG_ON(token);
 	}
@@ -288,7 +293,7 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt,
         fsopt->sb_flags = flags;
         fsopt->flags = CEPH_MOUNT_OPT_DEFAULT;
 
-        fsopt->rsize = CEPH_MOUNT_RSIZE_DEFAULT;
+        fsopt->rsize = CEPH_RSIZE_DEFAULT;
         fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL);
 	fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT;
 	fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT;
@@ -370,7 +375,7 @@ static int ceph_show_options(struct seq_file *m, struct vfsmount *mnt)
 
 	if (fsopt->wsize)
 		seq_printf(m, ",wsize=%d", fsopt->wsize);
-	if (fsopt->rsize != CEPH_MOUNT_RSIZE_DEFAULT)
+	if (fsopt->rsize != CEPH_RSIZE_DEFAULT)
 		seq_printf(m, ",rsize=%d", fsopt->rsize);
 	if (fsopt->congestion_kb != default_congestion_kb())
 		seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 20b907d..619fe71 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -27,6 +27,7 @@
 #define CEPH_MOUNT_OPT_DIRSTAT         (1<<4) /* `cat dirname` for stats */
 #define CEPH_MOUNT_OPT_RBYTES          (1<<5) /* dir st_bytes = rbytes */
 #define CEPH_MOUNT_OPT_NOASYNCREADDIR  (1<<7) /* no dcache readdir */
+#define CEPH_MOUNT_OPT_INO32           (1<<8) /* 32 bit inos */
 
 #define CEPH_MOUNT_OPT_DEFAULT    (CEPH_MOUNT_OPT_RBYTES)
 
@@ -35,6 +36,7 @@
 #define ceph_test_mount_opt(fsc, opt) \
 	(!!((fsc)->mount_options->flags & CEPH_MOUNT_OPT_##opt))
 
+#define CEPH_RSIZE_DEFAULT             (512*1024) /* readahead */
 #define CEPH_MAX_READDIR_DEFAULT        1024
 #define CEPH_MAX_READDIR_BYTES_DEFAULT  (512*1024)
 #define CEPH_SNAPDIRNAME_DEFAULT        ".snap"
@@ -319,6 +321,16 @@ static inline struct ceph_inode_info *ceph_inode(struct inode *inode)
 	return container_of(inode, struct ceph_inode_info, vfs_inode);
 }
 
+static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode)
+{
+	return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
+}
+
+static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb)
+{
+	return (struct ceph_fs_client *)sb->s_fs_info;
+}
+
 static inline struct ceph_vino ceph_vino(struct inode *inode)
 {
 	return ceph_inode(inode)->i_vino;
@@ -327,19 +339,49 @@ static inline struct ceph_vino ceph_vino(struct inode *inode)
 /*
  * ino_t is <64 bits on many architectures, blech.
  *
- * don't include snap in ino hash, at least for now.
+ *               i_ino (kernel inode)   st_ino (userspace)
+ * i386          32                     32
+ * x86_64+ino32  64                     32
+ * x86_64        64                     64
+ */
+static inline u32 ceph_ino_to_ino32(ino_t ino)
+{
+	ino ^= ino >> (sizeof(ino) * 8 - 32);
+	if (!ino)
+		ino = 1;
+	return ino;
+}
+
+/*
+ * kernel i_ino value
  */
 static inline ino_t ceph_vino_to_ino(struct ceph_vino vino)
 {
 	ino_t ino = (ino_t)vino.ino;  /* ^ (vino.snap << 20); */
 #if BITS_PER_LONG == 32
-	ino ^= vino.ino >> (sizeof(u64)-sizeof(ino_t)) * 8;
-	if (!ino)
-		ino = 1;
+	ino = ceph_ino_to_ino32(ino);
 #endif
 	return ino;
 }
 
+/*
+ * user-visible ino (stat, filldir)
+ */
+#if BITS_PER_LONG == 32
+static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino)
+{
+	return ino;
+}
+#else
+static inline ino_t ceph_translate_ino(struct super_block *sb, ino_t ino)
+{
+	if (ceph_test_mount_opt(ceph_sb_to_client(sb), INO32))
+		ino = ceph_ino_to_ino32(ino);
+	return ino;
+}
+#endif
+
+
 /* for printf-style formatting */
 #define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
 
@@ -428,13 +470,6 @@ static inline loff_t ceph_make_fpos(unsigned frag, unsigned off)
 	return ((loff_t)frag << 32) | (loff_t)off;
 }
 
-static inline int ceph_set_ino_cb(struct inode *inode, void *data)
-{
-	ceph_inode(inode)->i_vino = *(struct ceph_vino *)data;
-	inode->i_ino = ceph_vino_to_ino(*(struct ceph_vino *)data);
-	return 0;
-}
-
 /*
  * caps helpers
  */
@@ -503,15 +538,6 @@ extern void ceph_reservation_status(struct ceph_fs_client *client,
 				    int *total, int *avail, int *used,
 				    int *reserved, int *min);
 
-static inline struct ceph_fs_client *ceph_inode_to_client(struct inode *inode)
-{
-	return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
-}
-
-static inline struct ceph_fs_client *ceph_sb_to_client(struct super_block *sb)
-{
-	return (struct ceph_fs_client *)sb->s_fs_info;
-}
 
 
 /*
diff --git a/fs/coda/Makefile b/fs/coda/Makefile
index 6c22e61..1bab69a 100644
--- a/fs/coda/Makefile
+++ b/fs/coda/Makefile
@@ -9,4 +9,4 @@ coda-objs := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o \
 
 # If you want debugging output, please uncomment the following line.
 
-# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1
+# ccflags-y := -DDEBUG -DDEBUG_SMB_MALLOC=1
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index c6405ce..06d27a4 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -13,7 +13,6 @@
 
 #ifdef CONFIG_SYSCTL
 static struct ctl_table_header *fs_table_header;
-#endif
 
 static ctl_table coda_table[] = {
 	{
@@ -40,7 +39,6 @@ static ctl_table coda_table[] = {
 	{}
 };
 
-#ifdef CONFIG_SYSCTL
 static ctl_table fs_table[] = {
 	{
 		.procname	= "coda",
@@ -49,22 +47,18 @@ static ctl_table fs_table[] = {
 	},
 	{}
 };
-#endif
 
 void coda_sysctl_init(void)
 {
-#ifdef CONFIG_SYSCTL
 	if ( !fs_table_header )
 		fs_table_header = register_sysctl_table(fs_table);
-#endif
 }
 
 void coda_sysctl_clean(void)
 {
-#ifdef CONFIG_SYSCTL
 	if ( fs_table_header ) {
 		unregister_sysctl_table(fs_table_header);
 		fs_table_header = NULL;
 	}
-#endif
 }
+#endif
diff --git a/fs/compat.c b/fs/compat.c
index 691c3fd..72fe6cd 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -262,35 +262,19 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *
  */
 asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
 {
-	struct path path;
-	int error;
-
-	error = user_path(pathname, &path);
-	if (!error) {
-		struct kstatfs tmp;
-		error = vfs_statfs(&path, &tmp);
-		if (!error)
-			error = put_compat_statfs(buf, &tmp);
-		path_put(&path);
-	}
+	struct kstatfs tmp;
+	int error = user_statfs(pathname, &tmp);
+	if (!error)
+		error = put_compat_statfs(buf, &tmp);
 	return error;
 }
 
 asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf)
 {
-	struct file * file;
 	struct kstatfs tmp;
-	int error;
-
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-	error = vfs_statfs(&file->f_path, &tmp);
+	int error = fd_statfs(fd, &tmp);
 	if (!error)
 		error = put_compat_statfs(buf, &tmp);
-	fput(file);
-out:
 	return error;
 }
 
@@ -329,41 +313,29 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat
 
 asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
-	struct path path;
+	struct kstatfs tmp;
 	int error;
 
 	if (sz != sizeof(*buf))
 		return -EINVAL;
 
-	error = user_path(pathname, &path);
-	if (!error) {
-		struct kstatfs tmp;
-		error = vfs_statfs(&path, &tmp);
-		if (!error)
-			error = put_compat_statfs64(buf, &tmp);
-		path_put(&path);
-	}
+	error = user_statfs(pathname, &tmp);
+	if (!error)
+		error = put_compat_statfs64(buf, &tmp);
 	return error;
 }
 
 asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
-	struct file * file;
 	struct kstatfs tmp;
 	int error;
 
 	if (sz != sizeof(*buf))
 		return -EINVAL;
 
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-	error = vfs_statfs(&file->f_path, &tmp);
+	error = fd_statfs(fd, &tmp);
 	if (!error)
 		error = put_compat_statfs64(buf, &tmp);
-	fput(file);
-out:
 	return error;
 }
 
@@ -1699,9 +1671,6 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
  * Update: ERESTARTSYS breaks at least the xview clock binary, so
  * I'm trying ERESTARTNOHAND which restart only when you want to.
  */
-#define MAX_SELECT_SECONDS \
-	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-
 int compat_core_sys_select(int n, compat_ulong_t __user *inp,
 	compat_ulong_t __user *outp, compat_ulong_t __user *exp,
 	struct timespec *end_time)
@@ -2312,3 +2281,16 @@ asmlinkage long compat_sys_timerfd_gettime(int ufd,
 }
 
 #endif /* CONFIG_TIMERFD */
+
+#ifdef CONFIG_FHANDLE
+/*
+ * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
+ * doesn't set the O_LARGEFILE flag.
+ */
+asmlinkage long
+compat_sys_open_by_handle_at(int mountdirfd,
+			     struct file_handle __user *handle, int flags)
+{
+	return do_handle_open(mountdirfd, handle, flags);
+}
+#endif
diff --git a/fs/dcache.c b/fs/dcache.c
index 611ffe9..ad25c4c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -296,8 +296,12 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
 	__releases(parent->d_lock)
 	__releases(dentry->d_inode->i_lock)
 {
-	dentry->d_parent = NULL;
 	list_del(&dentry->d_u.d_child);
+	/*
+	 * Inform try_to_ascend() that we are no longer attached to the
+	 * dentry tree
+	 */
+	dentry->d_flags |= DCACHE_DISCONNECTED;
 	if (parent)
 		spin_unlock(&parent->d_lock);
 	dentry_iput(dentry);
@@ -1012,6 +1016,35 @@ void shrink_dcache_for_umount(struct super_block *sb)
 }
 
 /*
+ * This tries to ascend one level of parenthood, but
+ * we can race with renaming, so we need to re-check
+ * the parenthood after dropping the lock and check
+ * that the sequence number still matches.
+ */
+static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq)
+{
+	struct dentry *new = old->d_parent;
+
+	rcu_read_lock();
+	spin_unlock(&old->d_lock);
+	spin_lock(&new->d_lock);
+
+	/*
+	 * might go back up the wrong parent if we have had a rename
+	 * or deletion
+	 */
+	if (new != old->d_parent ||
+		 (old->d_flags & DCACHE_DISCONNECTED) ||
+		 (!locked && read_seqretry(&rename_lock, seq))) {
+		spin_unlock(&new->d_lock);
+		new = NULL;
+	}
+	rcu_read_unlock();
+	return new;
+}
+
+
+/*
  * Search for at least 1 mount point in the dentry's subdirs.
  * We descend to the next level whenever the d_subdirs
  * list is non-empty and continue searching.
@@ -1066,24 +1099,10 @@ resume:
 	 * All done at this level ... ascend and resume the search.
 	 */
 	if (this_parent != parent) {
-		struct dentry *tmp;
-		struct dentry *child;
-
-		tmp = this_parent->d_parent;
-		rcu_read_lock();
-		spin_unlock(&this_parent->d_lock);
-		child = this_parent;
-		this_parent = tmp;
-		spin_lock(&this_parent->d_lock);
-		/* might go back up the wrong parent if we have had a rename
-		 * or deletion */
-		if (this_parent != child->d_parent ||
-			 (!locked && read_seqretry(&rename_lock, seq))) {
-			spin_unlock(&this_parent->d_lock);
-			rcu_read_unlock();
+		struct dentry *child = this_parent;
+		this_parent = try_to_ascend(this_parent, locked, seq);
+		if (!this_parent)
 			goto rename_retry;
-		}
-		rcu_read_unlock();
 		next = child->d_u.d_child.next;
 		goto resume;
 	}
@@ -1181,24 +1200,10 @@ resume:
 	 * All done at this level ... ascend and resume the search.
 	 */
 	if (this_parent != parent) {
-		struct dentry *tmp;
-		struct dentry *child;
-
-		tmp = this_parent->d_parent;
-		rcu_read_lock();
-		spin_unlock(&this_parent->d_lock);
-		child = this_parent;
-		this_parent = tmp;
-		spin_lock(&this_parent->d_lock);
-		/* might go back up the wrong parent if we have had a rename
-		 * or deletion */
-		if (this_parent != child->d_parent ||
-			(!locked && read_seqretry(&rename_lock, seq))) {
-			spin_unlock(&this_parent->d_lock);
-			rcu_read_unlock();
+		struct dentry *child = this_parent;
+		this_parent = try_to_ascend(this_parent, locked, seq);
+		if (!this_parent)
 			goto rename_retry;
-		}
-		rcu_read_unlock();
 		next = child->d_u.d_child.next;
 		goto resume;
 	}
@@ -1607,10 +1612,13 @@ struct dentry *d_obtain_alias(struct inode *inode)
 	__bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
 	spin_unlock(&tmp->d_lock);
 	spin_unlock(&inode->i_lock);
+	security_d_instantiate(tmp, inode);
 
 	return tmp;
 
  out_iput:
+	if (res && !IS_ERR(res))
+		security_d_instantiate(res, inode);
 	iput(inode);
 	return res;
 }
@@ -1803,7 +1811,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
 	 * false-negative result. d_lookup() protects against concurrent
 	 * renames using rename_lock seqlock.
 	 *
-	 * See Documentation/vfs/dcache-locking.txt for more details.
+	 * See Documentation/filesystems/path-lookup.txt for more details.
 	 */
 	hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
 		struct inode *i;
@@ -1923,7 +1931,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
 	 * false-negative result. d_lookup() protects against concurrent
 	 * renames using rename_lock seqlock.
 	 *
-	 * See Documentation/vfs/dcache-locking.txt for more details.
+	 * See Documentation/filesystems/path-lookup.txt for more details.
 	 */
 	rcu_read_lock();
 	
@@ -2942,28 +2950,14 @@ resume:
 		spin_unlock(&dentry->d_lock);
 	}
 	if (this_parent != root) {
-		struct dentry *tmp;
-		struct dentry *child;
-
-		tmp = this_parent->d_parent;
+		struct dentry *child = this_parent;
 		if (!(this_parent->d_flags & DCACHE_GENOCIDE)) {
 			this_parent->d_flags |= DCACHE_GENOCIDE;
 			this_parent->d_count--;
 		}
-		rcu_read_lock();
-		spin_unlock(&this_parent->d_lock);
-		child = this_parent;
-		this_parent = tmp;
-		spin_lock(&this_parent->d_lock);
-		/* might go back up the wrong parent if we have had a rename
-		 * or deletion */
-		if (this_parent != child->d_parent ||
-			 (!locked && read_seqretry(&rename_lock, seq))) {
-			spin_unlock(&this_parent->d_lock);
-			rcu_read_unlock();
+		this_parent = try_to_ascend(this_parent, locked, seq);
+		if (!this_parent)
 			goto rename_retry;
-		}
-		rcu_read_unlock();
 		next = child->d_u.d_child.next;
 		goto resume;
 	}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 37a8ca7..e7a7a2f 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -13,9 +13,6 @@
  *
  */
 
-/* uncomment to get debug messages from the debug filesystem, ah the irony. */
-/* #define DEBUG */
-
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mount.h>
@@ -310,7 +307,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
 }
 EXPORT_SYMBOL_GPL(debugfs_create_symlink);
 
-static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)
+static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
 {
 	int ret = 0;
 
@@ -333,6 +330,7 @@ static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)
 			dput(dentry);
 		}
 	}
+	return ret;
 }
 
 /**
@@ -351,7 +349,8 @@ static void __debugfs_remove(struct dentry *dentry, struct dentry *parent)
 void debugfs_remove(struct dentry *dentry)
 {
 	struct dentry *parent;
-	
+	int ret;
+
 	if (!dentry)
 		return;
 
@@ -360,9 +359,10 @@ void debugfs_remove(struct dentry *dentry)
 		return;
 
 	mutex_lock(&parent->d_inode->i_mutex);
-	__debugfs_remove(dentry, parent);
+	ret = __debugfs_remove(dentry, parent);
 	mutex_unlock(&parent->d_inode->i_mutex);
-	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+	if (!ret)
+		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
@@ -540,17 +540,5 @@ static int __init debugfs_init(void)
 
 	return retval;
 }
-
-static void __exit debugfs_exit(void)
-{
-	debugfs_registered = false;
-
-	simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-	unregister_filesystem(&debug_fs_type);
-	kobject_put(debug_kobj);
-}
-
 core_initcall(debugfs_init);
-module_exit(debugfs_exit);
-MODULE_LICENSE("GPL");
 
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 1bb547c..2f27e57 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -479,6 +479,7 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
 	struct dentry *root = sb->s_root;
 	struct pts_fs_info *fsi = DEVPTS_SB(sb);
 	struct pts_mount_opts *opts = &fsi->mount_opts;
+	int ret = 0;
 	char s[12];
 
 	/* We're supposed to be given the slave end of a pty */
@@ -501,14 +502,17 @@ int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
 	mutex_lock(&root->d_inode->i_mutex);
 
 	dentry = d_alloc_name(root, s);
-	if (!IS_ERR(dentry)) {
+	if (dentry) {
 		d_add(dentry, inode);
 		fsnotify_create(root->d_inode, dentry);
+	} else {
+		iput(inode);
+		ret = -ENOMEM;
 	}
 
 	mutex_unlock(&root->d_inode->i_mutex);
 
-	return 0;
+	return ret;
 }
 
 struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
@@ -544,17 +548,12 @@ void devpts_pty_kill(struct tty_struct *tty)
 	mutex_lock(&root->d_inode->i_mutex);
 
 	dentry = d_find_alias(inode);
-	if (IS_ERR(dentry))
-		goto out;
-
-	if (dentry) {
-		inode->i_nlink--;
-		d_delete(dentry);
-		dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
-	}
 
+	inode->i_nlink--;
+	d_delete(dentry);
+	dput(dentry);	/* d_alloc_name() in devpts_pty_new() */
 	dput(dentry);		/* d_find_alias above */
-out:
+
 	mutex_unlock(&root->d_inode->i_mutex);
 }
 
diff --git a/fs/direct-io.c b/fs/direct-io.c
index b044705..dcb5577 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -645,11 +645,11 @@ static int dio_send_cur_page(struct dio *dio)
 		/*
 		 * See whether this new request is contiguous with the old.
 		 *
-		 * Btrfs cannot handl having logically non-contiguous requests
-		 * submitted.  For exmple if you have
+		 * Btrfs cannot handle having logically non-contiguous requests
+		 * submitted.  For example if you have
 		 *
 		 * Logical:  [0-4095][HOLE][8192-12287]
-		 * Phyiscal: [0-4095]      [4096-8181]
+		 * Physical: [0-4095]      [4096-8191]
 		 *
 		 * We cannot submit those pages together as one BIO.  So if our
 		 * current logical offset in the file does not equal what would
diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
index 4314f0d..abc49f2 100644
--- a/fs/dlm/ast.c
+++ b/fs/dlm/ast.c
@@ -18,6 +18,7 @@
 
 #define WAKE_ASTS  0
 
+static uint64_t			ast_seq_count;
 static struct list_head		ast_queue;
 static spinlock_t		ast_queue_lock;
 static struct task_struct *	astd_task;
@@ -25,40 +26,186 @@ static unsigned long		astd_wakeflags;
 static struct mutex		astd_running;
 
 
+static void dlm_dump_lkb_callbacks(struct dlm_lkb *lkb)
+{
+	int i;
+
+	log_print("last_bast %x %llu flags %x mode %d sb %d %x",
+		  lkb->lkb_id,
+		  (unsigned long long)lkb->lkb_last_bast.seq,
+		  lkb->lkb_last_bast.flags,
+		  lkb->lkb_last_bast.mode,
+		  lkb->lkb_last_bast.sb_status,
+		  lkb->lkb_last_bast.sb_flags);
+
+	log_print("last_cast %x %llu flags %x mode %d sb %d %x",
+		  lkb->lkb_id,
+		  (unsigned long long)lkb->lkb_last_cast.seq,
+		  lkb->lkb_last_cast.flags,
+		  lkb->lkb_last_cast.mode,
+		  lkb->lkb_last_cast.sb_status,
+		  lkb->lkb_last_cast.sb_flags);
+
+	for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
+		log_print("cb %x %llu flags %x mode %d sb %d %x",
+			  lkb->lkb_id,
+			  (unsigned long long)lkb->lkb_callbacks[i].seq,
+			  lkb->lkb_callbacks[i].flags,
+			  lkb->lkb_callbacks[i].mode,
+			  lkb->lkb_callbacks[i].sb_status,
+			  lkb->lkb_callbacks[i].sb_flags);
+	}
+}
+
 void dlm_del_ast(struct dlm_lkb *lkb)
 {
 	spin_lock(&ast_queue_lock);
-	if (lkb->lkb_ast_type & (AST_COMP | AST_BAST))
-		list_del(&lkb->lkb_astqueue);
+	if (!list_empty(&lkb->lkb_astqueue))
+		list_del_init(&lkb->lkb_astqueue);
 	spin_unlock(&ast_queue_lock);
 }
 
-void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode)
+int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
+			 int status, uint32_t sbflags, uint64_t seq)
 {
+	struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+	uint64_t prev_seq;
+	int prev_mode;
+	int i;
+
+	for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
+		if (lkb->lkb_callbacks[i].seq)
+			continue;
+
+		/*
+		 * Suppress some redundant basts here, do more on removal.
+		 * Don't even add a bast if the callback just before it
+		 * is a bast for the same mode or a more restrictive mode.
+		 * (the addional > PR check is needed for PR/CW inversion)
+		 */
+
+		if ((i > 0) && (flags & DLM_CB_BAST) &&
+		    (lkb->lkb_callbacks[i-1].flags & DLM_CB_BAST)) {
+
+			prev_seq = lkb->lkb_callbacks[i-1].seq;
+			prev_mode = lkb->lkb_callbacks[i-1].mode;
+
+			if ((prev_mode == mode) ||
+			    (prev_mode > mode && prev_mode > DLM_LOCK_PR)) {
+
+				log_debug(ls, "skip %x add bast %llu mode %d "
+					  "for bast %llu mode %d",
+					  lkb->lkb_id,
+					  (unsigned long long)seq,
+					  mode,
+					  (unsigned long long)prev_seq,
+					  prev_mode);
+				return 0;
+			}
+		}
+
+		lkb->lkb_callbacks[i].seq = seq;
+		lkb->lkb_callbacks[i].flags = flags;
+		lkb->lkb_callbacks[i].mode = mode;
+		lkb->lkb_callbacks[i].sb_status = status;
+		lkb->lkb_callbacks[i].sb_flags = (sbflags & 0x000000FF);
+		break;
+	}
+
+	if (i == DLM_CALLBACKS_SIZE) {
+		log_error(ls, "no callbacks %x %llu flags %x mode %d sb %d %x",
+			  lkb->lkb_id, (unsigned long long)seq,
+			  flags, mode, status, sbflags);
+		dlm_dump_lkb_callbacks(lkb);
+		return -1;
+	}
+
+	return 0;
+}
+
+int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
+			 struct dlm_callback *cb, int *resid)
+{
+	int i;
+
+	*resid = 0;
+
+	if (!lkb->lkb_callbacks[0].seq)
+		return -ENOENT;
+
+	/* oldest undelivered cb is callbacks[0] */
+
+	memcpy(cb, &lkb->lkb_callbacks[0], sizeof(struct dlm_callback));
+	memset(&lkb->lkb_callbacks[0], 0, sizeof(struct dlm_callback));
+
+	/* shift others down */
+
+	for (i = 1; i < DLM_CALLBACKS_SIZE; i++) {
+		if (!lkb->lkb_callbacks[i].seq)
+			break;
+		memcpy(&lkb->lkb_callbacks[i-1], &lkb->lkb_callbacks[i],
+		       sizeof(struct dlm_callback));
+		memset(&lkb->lkb_callbacks[i], 0, sizeof(struct dlm_callback));
+		(*resid)++;
+	}
+
+	/* if cb is a bast, it should be skipped if the blocking mode is
+	   compatible with the last granted mode */
+
+	if ((cb->flags & DLM_CB_BAST) && lkb->lkb_last_cast.seq) {
+		if (dlm_modes_compat(cb->mode, lkb->lkb_last_cast.mode)) {
+			cb->flags |= DLM_CB_SKIP;
+
+			log_debug(ls, "skip %x bast %llu mode %d "
+				  "for cast %llu mode %d",
+				  lkb->lkb_id,
+				  (unsigned long long)cb->seq,
+				  cb->mode,
+				  (unsigned long long)lkb->lkb_last_cast.seq,
+				  lkb->lkb_last_cast.mode);
+			return 0;
+		}
+	}
+
+	if (cb->flags & DLM_CB_CAST) {
+		memcpy(&lkb->lkb_last_cast, cb, sizeof(struct dlm_callback));
+		lkb->lkb_last_cast_time = ktime_get();
+	}
+
+	if (cb->flags & DLM_CB_BAST) {
+		memcpy(&lkb->lkb_last_bast, cb, sizeof(struct dlm_callback));
+		lkb->lkb_last_bast_time = ktime_get();
+	}
+
+	return 0;
+}
+
+void dlm_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
+		 uint32_t sbflags)
+{
+	uint64_t seq;
+	int rv;
+
+	spin_lock(&ast_queue_lock);
+
+	seq = ++ast_seq_count;
+
 	if (lkb->lkb_flags & DLM_IFL_USER) {
-		dlm_user_add_ast(lkb, type, mode);
+		spin_unlock(&ast_queue_lock);
+		dlm_user_add_ast(lkb, flags, mode, status, sbflags, seq);
 		return;
 	}
 
-	spin_lock(&ast_queue_lock);
-	if (!(lkb->lkb_ast_type & (AST_COMP | AST_BAST))) {
+	rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, seq);
+	if (rv < 0) {
+		spin_unlock(&ast_queue_lock);
+		return;
+	}
+
+	if (list_empty(&lkb->lkb_astqueue)) {
 		kref_get(&lkb->lkb_ref);
 		list_add_tail(&lkb->lkb_astqueue, &ast_queue);
-		lkb->lkb_ast_first = type;
 	}
-
-	/* sanity check, this should not happen */
-
-	if ((type == AST_COMP) && (lkb->lkb_ast_type & AST_COMP))
-		log_print("repeat cast %d castmode %d lock %x %s",
-			  mode, lkb->lkb_castmode,
-			  lkb->lkb_id, lkb->lkb_resource->res_name);
-
-	lkb->lkb_ast_type |= type;
-	if (type == AST_BAST)
-		lkb->lkb_bastmode = mode;
-	else
-		lkb->lkb_castmode = mode;
 	spin_unlock(&ast_queue_lock);
 
 	set_bit(WAKE_ASTS, &astd_wakeflags);
@@ -72,7 +219,8 @@ static void process_asts(void)
 	struct dlm_lkb *lkb;
 	void (*castfn) (void *astparam);
 	void (*bastfn) (void *astparam, int mode);
-	int type, first, bastmode, castmode, do_bast, do_cast, last_castmode;
+	struct dlm_callback callbacks[DLM_CALLBACKS_SIZE];
+	int i, rv, resid;
 
 repeat:
 	spin_lock(&ast_queue_lock);
@@ -83,54 +231,45 @@ repeat:
 		if (dlm_locking_stopped(ls))
 			continue;
 
-		list_del(&lkb->lkb_astqueue);
-		type = lkb->lkb_ast_type;
-		lkb->lkb_ast_type = 0;
-		first = lkb->lkb_ast_first;
-		lkb->lkb_ast_first = 0;
-		bastmode = lkb->lkb_bastmode;
-		castmode = lkb->lkb_castmode;
+		/* we remove from astqueue list and remove everything in
+		   lkb_callbacks before releasing the spinlock so empty
+		   lkb_astqueue is always consistent with empty lkb_callbacks */
+
+		list_del_init(&lkb->lkb_astqueue);
+
 		castfn = lkb->lkb_astfn;
 		bastfn = lkb->lkb_bastfn;
-		spin_unlock(&ast_queue_lock);
 
-		do_cast = (type & AST_COMP) && castfn;
-		do_bast = (type & AST_BAST) && bastfn;
+		memset(&callbacks, 0, sizeof(callbacks));
 
-		/* Skip a bast if its blocking mode is compatible with the
-		   granted mode of the preceding cast. */
+		for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
+			rv = dlm_rem_lkb_callback(ls, lkb, &callbacks[i], &resid);
+			if (rv < 0)
+				break;
+		}
+		spin_unlock(&ast_queue_lock);
 
-		if (do_bast) {
-			if (first == AST_COMP)
-				last_castmode = castmode;
-			else
-				last_castmode = lkb->lkb_castmode_done;
-			if (dlm_modes_compat(bastmode, last_castmode))
-				do_bast = 0;
+		if (resid) {
+			/* shouldn't happen, for loop should have removed all */
+			log_error(ls, "callback resid %d lkb %x",
+				  resid, lkb->lkb_id);
 		}
 
-		if (first == AST_COMP) {
-			if (do_cast)
-				castfn(lkb->lkb_astparam);
-			if (do_bast)
-				bastfn(lkb->lkb_astparam, bastmode);
-		} else if (first == AST_BAST) {
-			if (do_bast)
-				bastfn(lkb->lkb_astparam, bastmode);
-			if (do_cast)
+		for (i = 0; i < DLM_CALLBACKS_SIZE; i++) {
+			if (!callbacks[i].seq)
+				break;
+			if (callbacks[i].flags & DLM_CB_SKIP) {
+				continue;
+			} else if (callbacks[i].flags & DLM_CB_BAST) {
+				bastfn(lkb->lkb_astparam, callbacks[i].mode);
+			} else if (callbacks[i].flags & DLM_CB_CAST) {
+				lkb->lkb_lksb->sb_status = callbacks[i].sb_status;
+				lkb->lkb_lksb->sb_flags = callbacks[i].sb_flags;
 				castfn(lkb->lkb_astparam);
-		} else {
-			log_error(ls, "bad ast_first %d ast_type %d",
-				  first, type);
+			}
 		}
 
-		if (do_cast)
-			lkb->lkb_castmode_done = castmode;
-		if (do_bast)
-			lkb->lkb_bastmode_done = bastmode;
-
-		/* this removes the reference added by dlm_add_ast
-		   and may result in the lkb being freed */
+		/* removes ref for ast_queue, may cause lkb to be freed */
 		dlm_put_lkb(lkb);
 
 		cond_resched();
diff --git a/fs/dlm/ast.h b/fs/dlm/ast.h
index bcb1aab..8aa89c9 100644
--- a/fs/dlm/ast.h
+++ b/fs/dlm/ast.h
@@ -13,8 +13,13 @@
 #ifndef __ASTD_DOT_H__
 #define __ASTD_DOT_H__
 
-void dlm_add_ast(struct dlm_lkb *lkb, int type, int mode);
 void dlm_del_ast(struct dlm_lkb *lkb);
+int dlm_add_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
+                         int status, uint32_t sbflags, uint64_t seq);
+int dlm_rem_lkb_callback(struct dlm_ls *ls, struct dlm_lkb *lkb,
+                         struct dlm_callback *cb, int *resid);
+void dlm_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode, int status,
+		 uint32_t sbflags);
 
 void dlm_astd_wake(void);
 int dlm_astd_start(void);
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index b54bca0..0d329ff 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -977,9 +977,9 @@ int dlm_our_addr(struct sockaddr_storage *addr, int num)
 /* Config file defaults */
 #define DEFAULT_TCP_PORT       21064
 #define DEFAULT_BUFFER_SIZE     4096
-#define DEFAULT_RSBTBL_SIZE      256
+#define DEFAULT_RSBTBL_SIZE     1024
 #define DEFAULT_LKBTBL_SIZE     1024
-#define DEFAULT_DIRTBL_SIZE      512
+#define DEFAULT_DIRTBL_SIZE     1024
 #define DEFAULT_RECOVER_TIMER      5
 #define DEFAULT_TOSS_SECS         10
 #define DEFAULT_SCAN_SECS          5
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 6b42ba8..5977923 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -257,12 +257,12 @@ static int print_format3_lock(struct seq_file *s, struct dlm_lkb *lkb,
 			lkb->lkb_status,
 			lkb->lkb_grmode,
 			lkb->lkb_rqmode,
-			lkb->lkb_bastmode,
+			lkb->lkb_last_bast.mode,
 			rsb_lookup,
 			lkb->lkb_wait_type,
 			lkb->lkb_lvbseq,
 			(unsigned long long)ktime_to_ns(lkb->lkb_timestamp),
-			(unsigned long long)ktime_to_ns(lkb->lkb_time_bast));
+			(unsigned long long)ktime_to_ns(lkb->lkb_last_bast_time));
 	return rv;
 }
 
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index f632b58..b942049 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -192,11 +192,6 @@ struct dlm_args {
  * lkb is a process copy, the nodeid specifies the lock master.
  */
 
-/* lkb_ast_type */
-
-#define AST_COMP		1
-#define AST_BAST		2
-
 /* lkb_status */
 
 #define DLM_LKSTS_WAITING	1
@@ -217,6 +212,20 @@ struct dlm_args {
 #define DLM_IFL_USER		0x00000001
 #define DLM_IFL_ORPHAN		0x00000002
 
+#define DLM_CALLBACKS_SIZE	6
+
+#define DLM_CB_CAST		0x00000001
+#define DLM_CB_BAST		0x00000002
+#define DLM_CB_SKIP		0x00000004
+
+struct dlm_callback {
+	uint64_t		seq;
+	uint32_t		flags;		/* DLM_CBF_ */
+	int			sb_status;	/* copy to lksb status */
+	uint8_t			sb_flags;	/* copy to lksb flags */
+	int8_t			mode; /* rq mode of bast, gr mode of cast */
+};
+
 struct dlm_lkb {
 	struct dlm_rsb		*lkb_resource;	/* the rsb */
 	struct kref		lkb_ref;
@@ -236,13 +245,6 @@ struct dlm_lkb {
 
 	int8_t			lkb_wait_type;	/* type of reply waiting for */
 	int8_t			lkb_wait_count;
-	int8_t			lkb_ast_type;	/* type of ast queued for */
-	int8_t			lkb_ast_first;	/* type of first ast queued */
-
-	int8_t			lkb_bastmode;	/* req mode of queued bast */
-	int8_t			lkb_castmode;	/* gr mode of queued cast */
-	int8_t			lkb_bastmode_done; /* last delivered bastmode */
-	int8_t			lkb_castmode_done; /* last delivered castmode */
 
 	struct list_head	lkb_idtbl_list;	/* lockspace lkbtbl */
 	struct list_head	lkb_statequeue;	/* rsb g/c/w list */
@@ -251,10 +253,15 @@ struct dlm_lkb {
 	struct list_head	lkb_astqueue;	/* need ast to be sent */
 	struct list_head	lkb_ownqueue;	/* list of locks for a process */
 	struct list_head	lkb_time_list;
-	ktime_t			lkb_time_bast;	/* for debugging */
 	ktime_t			lkb_timestamp;
 	unsigned long		lkb_timeout_cs;
 
+	struct dlm_callback	lkb_callbacks[DLM_CALLBACKS_SIZE];
+	struct dlm_callback	lkb_last_cast;
+	struct dlm_callback	lkb_last_bast;
+	ktime_t			lkb_last_cast_time;	/* for debugging */
+	ktime_t			lkb_last_bast_time;	/* for debugging */
+
 	char			*lkb_lvbptr;
 	struct dlm_lksb		*lkb_lksb;      /* caller's status block */
 	void			(*lkb_astfn) (void *astparam);
@@ -544,8 +551,6 @@ struct dlm_user_args {
 					  (dlm_user_proc) on the struct file,
 					  the process's locks point back to it*/
 	struct dlm_lksb		lksb;
-	int			old_mode;
-	int			update_user_lvb;
 	struct dlm_lksb __user	*user_lksb;
 	void __user		*castparam;
 	void __user		*castaddr;
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index 64e5f3e..04b8c44 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -160,10 +160,10 @@ static const int __quecvt_compat_matrix[8][8] = {
 void dlm_print_lkb(struct dlm_lkb *lkb)
 {
 	printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x\n"
-	       "     status %d rqmode %d grmode %d wait_type %d ast_type %d\n",
+	       "     status %d rqmode %d grmode %d wait_type %d\n",
 	       lkb->lkb_nodeid, lkb->lkb_id, lkb->lkb_remid, lkb->lkb_exflags,
 	       lkb->lkb_flags, lkb->lkb_status, lkb->lkb_rqmode,
-	       lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_ast_type);
+	       lkb->lkb_grmode, lkb->lkb_wait_type);
 }
 
 static void dlm_print_rsb(struct dlm_rsb *r)
@@ -305,10 +305,7 @@ static void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv)
 		rv = -EDEADLK;
 	}
 
-	lkb->lkb_lksb->sb_status = rv;
-	lkb->lkb_lksb->sb_flags = lkb->lkb_sbflags;
-
-	dlm_add_ast(lkb, AST_COMP, lkb->lkb_grmode);
+	dlm_add_ast(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, lkb->lkb_sbflags);
 }
 
 static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
@@ -319,13 +316,10 @@ static inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb)
 
 static void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode)
 {
-	lkb->lkb_time_bast = ktime_get();
-
 	if (is_master_copy(lkb)) {
-		lkb->lkb_bastmode = rqmode; /* printed by debugfs */
 		send_bast(r, lkb, rqmode);
 	} else {
-		dlm_add_ast(lkb, AST_BAST, rqmode);
+		dlm_add_ast(lkb, DLM_CB_BAST, rqmode, 0, 0);
 	}
 }
 
@@ -600,6 +594,7 @@ static int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret)
 	INIT_LIST_HEAD(&lkb->lkb_ownqueue);
 	INIT_LIST_HEAD(&lkb->lkb_rsb_lookup);
 	INIT_LIST_HEAD(&lkb->lkb_time_list);
+	INIT_LIST_HEAD(&lkb->lkb_astqueue);
 
 	get_random_bytes(&bucket, sizeof(bucket));
 	bucket &= (ls->ls_lkbtbl_size - 1);
@@ -2819,9 +2814,9 @@ static void send_args(struct dlm_rsb *r, struct dlm_lkb *lkb,
 	   not from lkb fields */
 
 	if (lkb->lkb_bastfn)
-		ms->m_asts |= AST_BAST;
+		ms->m_asts |= DLM_CB_BAST;
 	if (lkb->lkb_astfn)
-		ms->m_asts |= AST_COMP;
+		ms->m_asts |= DLM_CB_CAST;
 
 	/* compare with switch in create_message; send_remove() doesn't
 	   use send_args() */
@@ -3122,8 +3117,8 @@ static int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 	lkb->lkb_grmode = DLM_LOCK_IV;
 	lkb->lkb_rqmode = ms->m_rqmode;
 
-	lkb->lkb_bastfn = (ms->m_asts & AST_BAST) ? &fake_bastfn : NULL;
-	lkb->lkb_astfn = (ms->m_asts & AST_COMP) ? &fake_astfn : NULL;
+	lkb->lkb_bastfn = (ms->m_asts & DLM_CB_BAST) ? &fake_bastfn : NULL;
+	lkb->lkb_astfn = (ms->m_asts & DLM_CB_CAST) ? &fake_astfn : NULL;
 
 	if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
 		/* lkb was just created so there won't be an lvb yet */
@@ -4412,8 +4407,8 @@ static int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
 	lkb->lkb_grmode = rl->rl_grmode;
 	/* don't set lkb_status because add_lkb wants to itself */
 
-	lkb->lkb_bastfn = (rl->rl_asts & AST_BAST) ? &fake_bastfn : NULL;
-	lkb->lkb_astfn = (rl->rl_asts & AST_COMP) ? &fake_astfn : NULL;
+	lkb->lkb_bastfn = (rl->rl_asts & DLM_CB_BAST) ? &fake_bastfn : NULL;
+	lkb->lkb_astfn = (rl->rl_asts & DLM_CB_CAST) ? &fake_astfn : NULL;
 
 	if (lkb->lkb_exflags & DLM_LKF_VALBLK) {
 		int lvblen = rc->rc_header.h_length - sizeof(struct dlm_rcom) -
@@ -4589,7 +4584,6 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua,
 	error = set_lock_args(mode, &ua->lksb, flags, namelen, timeout_cs,
 			      fake_astfn, ua, fake_bastfn, &args);
 	lkb->lkb_flags |= DLM_IFL_USER;
-	ua->old_mode = DLM_LOCK_IV;
 
 	if (error) {
 		__put_lkb(ls, lkb);
@@ -4658,7 +4652,6 @@ int dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp,
 	ua->bastparam = ua_tmp->bastparam;
 	ua->bastaddr = ua_tmp->bastaddr;
 	ua->user_lksb = ua_tmp->user_lksb;
-	ua->old_mode = lkb->lkb_grmode;
 
 	error = set_lock_args(mode, &ua->lksb, flags, 0, timeout_cs,
 			      fake_astfn, ua, fake_bastfn, &args);
@@ -4917,8 +4910,9 @@ void dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
 	}
 
 	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
-		lkb->lkb_ast_type = 0;
-		list_del(&lkb->lkb_astqueue);
+		memset(&lkb->lkb_callbacks, 0,
+		       sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE);
+		list_del_init(&lkb->lkb_astqueue);
 		dlm_put_lkb(lkb);
 	}
 
@@ -4958,7 +4952,9 @@ static void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc)
 
 	spin_lock(&proc->asts_spin);
 	list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_astqueue) {
-		list_del(&lkb->lkb_astqueue);
+		memset(&lkb->lkb_callbacks, 0,
+		       sizeof(struct dlm_callback) * DLM_CALLBACKS_SIZE);
+		list_del_init(&lkb->lkb_astqueue);
 		dlm_put_lkb(lkb);
 	}
 	spin_unlock(&proc->asts_spin);
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 2d8c87b..bffa1e7 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1468,13 +1468,15 @@ static void work_stop(void)
 
 static int work_start(void)
 {
-	recv_workqueue = create_singlethread_workqueue("dlm_recv");
+	recv_workqueue = alloc_workqueue("dlm_recv",
+					 WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
 	if (!recv_workqueue) {
 		log_print("can't start dlm_recv");
 		return -ENOMEM;
 	}
 
-	send_workqueue = create_singlethread_workqueue("dlm_send");
+	send_workqueue = alloc_workqueue("dlm_send",
+					 WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
 	if (!send_workqueue) {
 		log_print("can't start dlm_send");
 		destroy_workqueue(recv_workqueue);
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 3c83a49..f10a50f 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -321,9 +321,9 @@ static void pack_rcom_lock(struct dlm_rsb *r, struct dlm_lkb *lkb,
 	rl->rl_wait_type = cpu_to_le16(lkb->lkb_wait_type);
 
 	if (lkb->lkb_bastfn)
-		rl->rl_asts |= AST_BAST;
+		rl->rl_asts |= DLM_CB_BAST;
 	if (lkb->lkb_astfn)
-		rl->rl_asts |= AST_COMP;
+		rl->rl_asts |= DLM_CB_CAST;
 
 	rl->rl_namelen = cpu_to_le16(r->res_length);
 	memcpy(rl->rl_name, r->res_name, r->res_length);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index 66d6c16..d5ab3fe 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -24,6 +24,7 @@
 #include "lock.h"
 #include "lvb_table.h"
 #include "user.h"
+#include "ast.h"
 
 static const char name_prefix[] = "dlm";
 static const struct file_operations device_fops;
@@ -152,19 +153,16 @@ static void compat_output(struct dlm_lock_result *res,
    not related to the lifetime of the lkb struct which is managed
    entirely by refcount. */
 
-static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
+static int lkb_is_endoflife(int mode, int status)
 {
-	switch (sb_status) {
+	switch (status) {
 	case -DLM_EUNLOCK:
 		return 1;
 	case -DLM_ECANCEL:
 	case -ETIMEDOUT:
 	case -EDEADLK:
-		if (lkb->lkb_grmode == DLM_LOCK_IV)
-			return 1;
-		break;
 	case -EAGAIN:
-		if (type == AST_COMP && lkb->lkb_grmode == DLM_LOCK_IV)
+		if (mode == DLM_LOCK_IV)
 			return 1;
 		break;
 	}
@@ -174,12 +172,13 @@ static int lkb_is_endoflife(struct dlm_lkb *lkb, int sb_status, int type)
 /* we could possibly check if the cancel of an orphan has resulted in the lkb
    being removed and then remove that lkb from the orphans list and free it */
 
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
+void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode,
+		      int status, uint32_t sbflags, uint64_t seq)
 {
 	struct dlm_ls *ls;
 	struct dlm_user_args *ua;
 	struct dlm_user_proc *proc;
-	int eol = 0, ast_type;
+	int rv;
 
 	if (lkb->lkb_flags & (DLM_IFL_ORPHAN | DLM_IFL_DEAD))
 		return;
@@ -200,49 +199,29 @@ void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode)
 	ua = lkb->lkb_ua;
 	proc = ua->proc;
 
-	if (type == AST_BAST && ua->bastaddr == NULL)
+	if ((flags & DLM_CB_BAST) && ua->bastaddr == NULL)
 		goto out;
 
+	if ((flags & DLM_CB_CAST) && lkb_is_endoflife(mode, status))
+		lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
+
 	spin_lock(&proc->asts_spin);
 
-	ast_type = lkb->lkb_ast_type;
-	lkb->lkb_ast_type |= type;
-	if (type == AST_BAST)
-		lkb->lkb_bastmode = mode;
-	else
-		lkb->lkb_castmode = mode;
+	rv = dlm_add_lkb_callback(lkb, flags, mode, status, sbflags, seq);
+	if (rv < 0) {
+		spin_unlock(&proc->asts_spin);
+		goto out;
+	}
 
-	if (!ast_type) {
+	if (list_empty(&lkb->lkb_astqueue)) {
 		kref_get(&lkb->lkb_ref);
 		list_add_tail(&lkb->lkb_astqueue, &proc->asts);
-		lkb->lkb_ast_first = type;
 		wake_up_interruptible(&proc->wait);
 	}
-	if (type == AST_COMP && (ast_type & AST_COMP))
-		log_debug(ls, "ast overlap %x status %x %x",
-			  lkb->lkb_id, ua->lksb.sb_status, lkb->lkb_flags);
-
-	eol = lkb_is_endoflife(lkb, ua->lksb.sb_status, type);
-	if (eol) {
-		lkb->lkb_flags |= DLM_IFL_ENDOFLIFE;
-	}
-
-	/* We want to copy the lvb to userspace when the completion
-	   ast is read if the status is 0, the lock has an lvb and
-	   lvb_ops says we should.  We could probably have set_lvb_lock()
-	   set update_user_lvb instead and not need old_mode */
-
-	if ((lkb->lkb_ast_type & AST_COMP) &&
-	    (lkb->lkb_lksb->sb_status == 0) &&
-	    lkb->lkb_lksb->sb_lvbptr &&
-	    dlm_lvb_operations[ua->old_mode + 1][lkb->lkb_grmode + 1])
-		ua->update_user_lvb = 1;
-	else
-		ua->update_user_lvb = 0;
-
 	spin_unlock(&proc->asts_spin);
 
-	if (eol) {
+	if (lkb->lkb_flags & DLM_IFL_ENDOFLIFE) {
+		/* N.B. spin_lock locks_spin, not asts_spin */
 		spin_lock(&proc->locks_spin);
 		if (!list_empty(&lkb->lkb_ownqueue)) {
 			list_del_init(&lkb->lkb_ownqueue);
@@ -705,8 +684,9 @@ static int device_close(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
-			       int mode, char __user *buf, size_t count)
+static int copy_result_to_user(struct dlm_user_args *ua, int compat,
+			       uint32_t flags, int mode, int copy_lvb,
+			       char __user *buf, size_t count)
 {
 #ifdef CONFIG_COMPAT
 	struct dlm_lock_result32 result32;
@@ -730,7 +710,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
 	   notes that a new blocking AST address and parameter are set even if
 	   the conversion fails, so maybe we should just do that. */
 
-	if (type == AST_BAST) {
+	if (flags & DLM_CB_BAST) {
 		result.user_astaddr = ua->bastaddr;
 		result.user_astparam = ua->bastparam;
 		result.bast_mode = mode;
@@ -750,8 +730,7 @@ static int copy_result_to_user(struct dlm_user_args *ua, int compat, int type,
 	/* copy lvb to userspace if there is one, it's been updated, and
 	   the user buffer has space for it */
 
-	if (ua->update_user_lvb && ua->lksb.sb_lvbptr &&
-	    count >= len + DLM_USER_LVB_LEN) {
+	if (copy_lvb && ua->lksb.sb_lvbptr && count >= len + DLM_USER_LVB_LEN) {
 		if (copy_to_user(buf+len, ua->lksb.sb_lvbptr,
 				 DLM_USER_LVB_LEN)) {
 			error = -EFAULT;
@@ -801,13 +780,12 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
 	struct dlm_user_proc *proc = file->private_data;
 	struct dlm_lkb *lkb;
 	DECLARE_WAITQUEUE(wait, current);
-	int error = 0, removed;
-	int ret_type, ret_mode;
-	int bastmode, castmode, do_bast, do_cast;
+	struct dlm_callback cb;
+	int rv, resid, copy_lvb = 0;
 
 	if (count == sizeof(struct dlm_device_version)) {
-		error = copy_version_to_user(buf, count);
-		return error;
+		rv = copy_version_to_user(buf, count);
+		return rv;
 	}
 
 	if (!proc) {
@@ -854,92 +832,57 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
 		}
 	}
 
-	/* there may be both completion and blocking asts to return for
-	   the lkb, don't remove lkb from asts list unless no asts remain */
+	/* if we empty lkb_callbacks, we don't want to unlock the spinlock
+	   without removing lkb_astqueue; so empty lkb_astqueue is always
+	   consistent with empty lkb_callbacks */
 
 	lkb = list_entry(proc->asts.next, struct dlm_lkb, lkb_astqueue);
 
-	removed = 0;
-	ret_type = 0;
-	ret_mode = 0;
-	do_bast = lkb->lkb_ast_type & AST_BAST;
-	do_cast = lkb->lkb_ast_type & AST_COMP;
-	bastmode = lkb->lkb_bastmode;
-	castmode = lkb->lkb_castmode;
-
-	/* when both are queued figure out which to do first and
-	   switch first so the other goes in the next read */
-
-	if (do_cast && do_bast) {
-		if (lkb->lkb_ast_first == AST_COMP) {
-			ret_type = AST_COMP;
-			ret_mode = castmode;
-			lkb->lkb_ast_type &= ~AST_COMP;
-			lkb->lkb_ast_first = AST_BAST;
-		} else {
-			ret_type = AST_BAST;
-			ret_mode = bastmode;
-			lkb->lkb_ast_type &= ~AST_BAST;
-			lkb->lkb_ast_first = AST_COMP;
-		}
-	} else {
-		ret_type = lkb->lkb_ast_first;
-		ret_mode = (ret_type == AST_COMP) ? castmode : bastmode;
-		lkb->lkb_ast_type &= ~ret_type;
-		lkb->lkb_ast_first = 0;
+	rv = dlm_rem_lkb_callback(lkb->lkb_resource->res_ls, lkb, &cb, &resid);
+	if (rv < 0) {
+		/* this shouldn't happen; lkb should have been removed from
+		   list when resid was zero */
+		log_print("dlm_rem_lkb_callback empty %x", lkb->lkb_id);
+		list_del_init(&lkb->lkb_astqueue);
+		spin_unlock(&proc->asts_spin);
+		/* removes ref for proc->asts, may cause lkb to be freed */
+		dlm_put_lkb(lkb);
+		goto try_another;
 	}
+	if (!resid)
+		list_del_init(&lkb->lkb_astqueue);
+	spin_unlock(&proc->asts_spin);
 
-	/* if we're doing a bast but the bast is unnecessary, then
-	   switch to do nothing or do a cast if that was needed next */
-
-	if ((ret_type == AST_BAST) &&
-	    dlm_modes_compat(bastmode, lkb->lkb_castmode_done)) {
-		ret_type = 0;
-		ret_mode = 0;
-
-		if (do_cast) {
-			ret_type = AST_COMP;
-			ret_mode = castmode;
-			lkb->lkb_ast_type &= ~AST_COMP;
-			lkb->lkb_ast_first = 0;
-		}
+	if (cb.flags & DLM_CB_SKIP) {
+		/* removes ref for proc->asts, may cause lkb to be freed */
+		if (!resid)
+			dlm_put_lkb(lkb);
+		goto try_another;
 	}
 
-	if (lkb->lkb_ast_first != lkb->lkb_ast_type) {
-		log_print("device_read %x ast_first %x ast_type %x",
-			  lkb->lkb_id, lkb->lkb_ast_first, lkb->lkb_ast_type);
-	}
+	if (cb.flags & DLM_CB_CAST) {
+		int old_mode, new_mode;
 
-	if (!lkb->lkb_ast_type) {
-		list_del(&lkb->lkb_astqueue);
-		removed = 1;
-	}
-	spin_unlock(&proc->asts_spin);
+		old_mode = lkb->lkb_last_cast.mode;
+		new_mode = cb.mode;
 
-	if (ret_type) {
-		error = copy_result_to_user(lkb->lkb_ua,
-				test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
-				ret_type, ret_mode, buf, count);
+		if (!cb.sb_status && lkb->lkb_lksb->sb_lvbptr &&
+		    dlm_lvb_operations[old_mode + 1][new_mode + 1])
+			copy_lvb = 1;
 
-		if (ret_type == AST_COMP)
-			lkb->lkb_castmode_done = castmode;
-		if (ret_type == AST_BAST)
-			lkb->lkb_bastmode_done = bastmode;
+		lkb->lkb_lksb->sb_status = cb.sb_status;
+		lkb->lkb_lksb->sb_flags = cb.sb_flags;
 	}
 
-	/* removes reference for the proc->asts lists added by
-	   dlm_user_add_ast() and may result in the lkb being freed */
+	rv = copy_result_to_user(lkb->lkb_ua,
+				 test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
+				 cb.flags, cb.mode, copy_lvb, buf, count);
 
-	if (removed)
+	/* removes ref for proc->asts, may cause lkb to be freed */
+	if (!resid)
 		dlm_put_lkb(lkb);
 
-	/* the bast that was queued was eliminated (see unnecessary above),
-	   leaving nothing to return */
-
-	if (!ret_type)
-		goto try_another;
-
-	return error;
+	return rv;
 }
 
 static unsigned int device_poll(struct file *file, poll_table *wait)
diff --git a/fs/dlm/user.h b/fs/dlm/user.h
index f196091..00499ab 100644
--- a/fs/dlm/user.h
+++ b/fs/dlm/user.h
@@ -9,7 +9,8 @@
 #ifndef __USER_DOT_H__
 #define __USER_DOT_H__
 
-void dlm_user_add_ast(struct dlm_lkb *lkb, int type, int mode);
+void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode,
+                      int status, uint32_t sbflags, uint64_t seq);
 int dlm_user_init(void);
 void dlm_user_exit(void);
 int dlm_device_deregister(struct dlm_ls *ls);
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 4a09af9..ed38801 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -62,7 +62,7 @@
  * This mutex is acquired by ep_free() during the epoll file
  * cleanup path and it is also acquired by eventpoll_release_file()
  * if a file has been pushed inside an epoll set and it is then
- * close()d without a previous call toepoll_ctl(EPOLL_CTL_DEL).
+ * close()d without a previous call to epoll_ctl(EPOLL_CTL_DEL).
  * It is also acquired when inserting an epoll fd onto another epoll
  * fd. We do this so that we walk the epoll tree and ensure that this
  * insertion does not create a cycle of epoll file descriptors, which
@@ -152,11 +152,11 @@ struct epitem {
 
 /*
  * This structure is stored inside the "private_data" member of the file
- * structure and rapresent the main data sructure for the eventpoll
+ * structure and represents the main data structure for the eventpoll
  * interface.
  */
 struct eventpoll {
-	/* Protect the this structure access */
+	/* Protect the access to this structure */
 	spinlock_t lock;
 
 	/*
@@ -316,6 +316,19 @@ static void ep_nested_calls_init(struct nested_calls *ncalls)
 }
 
 /**
+ * ep_events_available - Checks if ready events might be available.
+ *
+ * @ep: Pointer to the eventpoll context.
+ *
+ * Returns: Returns a value different than zero if ready events are available,
+ *          or zero otherwise.
+ */
+static inline int ep_events_available(struct eventpoll *ep)
+{
+	return !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR;
+}
+
+/**
  * ep_call_nested - Perform a bound (possibly) nested call, by checking
  *                  that the recursion limit is not exceeded, and that
  *                  the same nested call (by the meaning of same cookie) is
@@ -793,7 +806,7 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
 
 /*
  * This is the callback that is passed to the wait queue wakeup
- * machanism. It is called by the stored file descriptors when they
+ * mechanism. It is called by the stored file descriptors when they
  * have events to report.
  */
 static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
@@ -824,9 +837,9 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
 		goto out_unlock;
 
 	/*
-	 * If we are trasfering events to userspace, we can hold no locks
+	 * If we are transferring events to userspace, we can hold no locks
 	 * (because we're accessing user memory, and because of linux f_op->poll()
-	 * semantics). All the events that happens during that period of time are
+	 * semantics). All the events that happen during that period of time are
 	 * chained in ep->ovflist and requeued later on.
 	 */
 	if (unlikely(ep->ovflist != EP_UNACTIVE_PTR)) {
@@ -1135,12 +1148,29 @@ static inline struct timespec ep_set_mstimeout(long ms)
 	return timespec_add_safe(now, ts);
 }
 
+/**
+ * ep_poll - Retrieves ready events, and delivers them to the caller supplied
+ *           event buffer.
+ *
+ * @ep: Pointer to the eventpoll context.
+ * @events: Pointer to the userspace buffer where the ready events should be
+ *          stored.
+ * @maxevents: Size (in terms of number of events) of the caller event buffer.
+ * @timeout: Maximum timeout for the ready events fetch operation, in
+ *           milliseconds. If the @timeout is zero, the function will not block,
+ *           while if the @timeout is less than zero, the function will block
+ *           until at least one event has been retrieved (or an error
+ *           occurred).
+ *
+ * Returns: Returns the number of ready events which have been fetched, or an
+ *          error code, in case of error.
+ */
 static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
 		   int maxevents, long timeout)
 {
-	int res, eavail, timed_out = 0;
+	int res = 0, eavail, timed_out = 0;
 	unsigned long flags;
-	long slack;
+	long slack = 0;
 	wait_queue_t wait;
 	ktime_t expires, *to = NULL;
 
@@ -1151,14 +1181,19 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
 		to = &expires;
 		*to = timespec_to_ktime(end_time);
 	} else if (timeout == 0) {
+		/*
+		 * Avoid the unnecessary trip to the wait queue loop, if the
+		 * caller specified a non blocking operation.
+		 */
 		timed_out = 1;
+		spin_lock_irqsave(&ep->lock, flags);
+		goto check_events;
 	}
 
-retry:
+fetch_events:
 	spin_lock_irqsave(&ep->lock, flags);
 
-	res = 0;
-	if (list_empty(&ep->rdllist)) {
+	if (!ep_events_available(ep)) {
 		/*
 		 * We don't have any available event to return to the caller.
 		 * We need to sleep here, and we will be wake up by
@@ -1174,7 +1209,7 @@ retry:
 			 * to TASK_INTERRUPTIBLE before doing the checks.
 			 */
 			set_current_state(TASK_INTERRUPTIBLE);
-			if (!list_empty(&ep->rdllist) || timed_out)
+			if (ep_events_available(ep) || timed_out)
 				break;
 			if (signal_pending(current)) {
 				res = -EINTR;
@@ -1191,8 +1226,9 @@ retry:
 
 		set_current_state(TASK_RUNNING);
 	}
+check_events:
 	/* Is it worth to try to dig for events ? */
-	eavail = !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR;
+	eavail = ep_events_available(ep);
 
 	spin_unlock_irqrestore(&ep->lock, flags);
 
@@ -1203,7 +1239,7 @@ retry:
 	 */
 	if (!res && eavail &&
 	    !(res = ep_send_events(ep, events, maxevents)) && !timed_out)
-		goto retry;
+		goto fetch_events;
 
 	return res;
 }
diff --git a/fs/exec.c b/fs/exec.c
index 52a447d..5e62d26 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -115,13 +115,16 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
 	struct file *file;
 	char *tmp = getname(library);
 	int error = PTR_ERR(tmp);
+	static const struct open_flags uselib_flags = {
+		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
+		.acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN,
+		.intent = LOOKUP_OPEN
+	};
 
 	if (IS_ERR(tmp))
 		goto out;
 
-	file = do_filp_open(AT_FDCWD, tmp,
-				O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
-				MAY_READ | MAY_EXEC | MAY_OPEN);
+	file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW);
 	putname(tmp);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
@@ -721,10 +724,13 @@ struct file *open_exec(const char *name)
 {
 	struct file *file;
 	int err;
+	static const struct open_flags open_exec_flags = {
+		.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
+		.acc_mode = MAY_EXEC | MAY_OPEN,
+		.intent = LOOKUP_OPEN
+	};
 
-	file = do_filp_open(AT_FDCWD, name,
-				O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
-				MAY_EXEC | MAY_OPEN);
+	file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
 	if (IS_ERR(file))
 		goto out;
 
@@ -1869,7 +1875,7 @@ static void wait_for_dump_helpers(struct file *file)
 
 
 /*
- * uhm_pipe_setup
+ * umh_pipe_setup
  * helper function to customize the process used
  * to collect the core in userspace.  Specifically
  * it sets up a pipe and installs it as fd 0 (stdin)
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
index 4b68257..b05acb7 100644
--- a/fs/exportfs/expfs.c
+++ b/fs/exportfs/expfs.c
@@ -320,9 +320,14 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
 	struct inode * inode = dentry->d_inode;
 	int len = *max_len;
 	int type = FILEID_INO32_GEN;
-	
-	if (len < 2 || (connectable && len < 4))
+
+	if (connectable && (len < 4)) {
+		*max_len = 4;
+		return 255;
+	} else if (len < 2) {
+		*max_len = 2;
 		return 255;
+	}
 
 	len = 2;
 	fid->i32.ino = inode->i_ino;
@@ -369,6 +374,8 @@ struct dentry *exportfs_decode_fh(struct vfsmount *mnt, struct fid *fid,
 	/*
 	 * Try to get any dentry for the given file handle from the filesystem.
 	 */
+	if (!nop || !nop->fh_to_dentry)
+		return ERR_PTR(-ESTALE);
 	result = nop->fh_to_dentry(mnt->mnt_sb, fid, fh_len, fileid_type);
 	if (!result)
 		result = ERR_PTR(-ESTALE);
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 6346a2a..1b48c33 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -110,7 +110,7 @@ extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
 extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int);
 
 /* ialloc.c */
-extern struct inode * ext2_new_inode (struct inode *, int);
+extern struct inode * ext2_new_inode (struct inode *, int, const struct qstr *);
 extern void ext2_free_inode (struct inode *);
 extern unsigned long ext2_count_free_inodes (struct super_block *);
 extern void ext2_check_inodes_bitmap (struct super_block *);
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index ad70479..ee9ed31 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -429,7 +429,8 @@ found:
 	return group;
 }
 
-struct inode *ext2_new_inode(struct inode *dir, int mode)
+struct inode *ext2_new_inode(struct inode *dir, int mode,
+			     const struct qstr *qstr)
 {
 	struct super_block *sb;
 	struct buffer_head *bitmap_bh = NULL;
@@ -585,7 +586,7 @@ got:
 	if (err)
 		goto fail_free_drop;
 
-	err = ext2_init_security(inode,dir);
+	err = ext2_init_security(inode, dir, qstr);
 	if (err)
 		goto fail_free_drop;
 
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index adb9185..ed5c5d4 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -104,7 +104,7 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
 
 	dquot_initialize(dir);
 
-	inode = ext2_new_inode(dir, mode);
+	inode = ext2_new_inode(dir, mode, &dentry->d_name);
 	if (IS_ERR(inode))
 		return PTR_ERR(inode);
 
@@ -133,7 +133,7 @@ static int ext2_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_
 
 	dquot_initialize(dir);
 
-	inode = ext2_new_inode (dir, mode);
+	inode = ext2_new_inode (dir, mode, &dentry->d_name);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
@@ -159,7 +159,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
 
 	dquot_initialize(dir);
 
-	inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO);
+	inode = ext2_new_inode (dir, S_IFLNK | S_IRWXUGO, &dentry->d_name);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out;
@@ -230,7 +230,7 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 
 	inode_inc_link_count(dir);
 
-	inode = ext2_new_inode (dir, S_IFDIR | mode);
+	inode = ext2_new_inode(dir, S_IFDIR | mode, &dentry->d_name);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_dir;
diff --git a/fs/ext2/xattr.h b/fs/ext2/xattr.h
index a1a1c21..5e41ccc 100644
--- a/fs/ext2/xattr.h
+++ b/fs/ext2/xattr.h
@@ -116,9 +116,11 @@ exit_ext2_xattr(void)
 # endif  /* CONFIG_EXT2_FS_XATTR */
 
 #ifdef CONFIG_EXT2_FS_SECURITY
-extern int ext2_init_security(struct inode *inode, struct inode *dir);
+extern int ext2_init_security(struct inode *inode, struct inode *dir,
+			      const struct qstr *qstr);
 #else
-static inline int ext2_init_security(struct inode *inode, struct inode *dir)
+static inline int ext2_init_security(struct inode *inode, struct inode *dir,
+				     const struct qstr *qstr)
 {
 	return 0;
 }
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 3004e15..5d979b4 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -47,14 +47,15 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
 }
 
 int
-ext2_init_security(struct inode *inode, struct inode *dir)
+ext2_init_security(struct inode *inode, struct inode *dir,
+		   const struct qstr *qstr)
 {
 	int err;
 	size_t len;
 	void *value;
 	char *name;
 
-	err = security_inode_init_security(inode, dir, &name, &value, &len);
+	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			return 0;
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 045995c..1532421 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -1991,6 +1991,7 @@ ext3_grpblk_t ext3_trim_all_free(struct super_block *sb, unsigned int group,
 		spin_unlock(sb_bgl_lock(sbi, group));
 		percpu_counter_sub(&sbi->s_freeblocks_counter, next - start);
 
+		free_blocks -= next - start;
 		/* Do not issue a TRIM on extents smaller than minblocks */
 		if ((next - start) < minblocks)
 			goto free_extent;
@@ -2040,7 +2041,7 @@ free_extent:
 		cond_resched();
 
 		/* No more suitable extents */
-		if ((free_blocks - count) < minblocks)
+		if (free_blocks < minblocks)
 			break;
 	}
 
@@ -2090,7 +2091,8 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
 	ext3_fsblk_t max_blks = le32_to_cpu(es->s_blocks_count);
 	int ret = 0;
 
-	start = range->start >> sb->s_blocksize_bits;
+	start = (range->start >> sb->s_blocksize_bits) +
+		le32_to_cpu(es->s_first_data_block);
 	len = range->len >> sb->s_blocksize_bits;
 	minlen = range->minlen >> sb->s_blocksize_bits;
 	trimmed = 0;
@@ -2099,10 +2101,6 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
 		return -EINVAL;
 	if (start >= max_blks)
 		goto out;
-	if (start < le32_to_cpu(es->s_first_data_block)) {
-		len -= le32_to_cpu(es->s_first_data_block) - start;
-		start = le32_to_cpu(es->s_first_data_block);
-	}
 	if (start + len > max_blks)
 		len = max_blks - start;
 
@@ -2129,10 +2127,15 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
 		if (free_blocks < minlen)
 			continue;
 
-		if (len >= EXT3_BLOCKS_PER_GROUP(sb))
-			len -= (EXT3_BLOCKS_PER_GROUP(sb) - first_block);
-		else
+		/*
+		 * For all the groups except the last one, last block will
+		 * always be EXT3_BLOCKS_PER_GROUP(sb), so we only need to
+		 * change it for the last group in which case first_block +
+		 * len < EXT3_BLOCKS_PER_GROUP(sb).
+		 */
+		if (first_block + len < EXT3_BLOCKS_PER_GROUP(sb))
 			last_block = first_block + len;
+		len -= last_block - first_block;
 
 		ret = ext3_trim_all_free(sb, group, first_block,
 					last_block, minlen);
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index 9724aef..bfc2dc4 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -404,7 +404,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)
  * For other inodes, search forward from the parent directory's block
  * group to find a free inode.
  */
-struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
+struct inode *ext3_new_inode(handle_t *handle, struct inode * dir,
+			     const struct qstr *qstr, int mode)
 {
 	struct super_block *sb;
 	struct buffer_head *bitmap_bh = NULL;
@@ -589,7 +590,7 @@ got:
 	if (err)
 		goto fail_free_drop;
 
-	err = ext3_init_security(handle,inode, dir);
+	err = ext3_init_security(handle, inode, dir, qstr);
 	if (err)
 		goto fail_free_drop;
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index b27ba71..32f3b86 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1540,8 +1540,8 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
 			goto cleanup;
 		node2 = (struct dx_node *)(bh2->b_data);
 		entries2 = node2->entries;
+		memset(&node2->fake, 0, sizeof(struct fake_dirent));
 		node2->fake.rec_len = ext3_rec_len_to_disk(sb->s_blocksize);
-		node2->fake.inode = 0;
 		BUFFER_TRACE(frame->bh, "get_write_access");
 		err = ext3_journal_get_write_access(handle, frame->bh);
 		if (err)
@@ -1710,7 +1710,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, mode);
+	inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ext3_file_inode_operations;
@@ -1746,7 +1746,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, mode);
+	inode = ext3_new_inode (handle, dir, &dentry->d_name, mode);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		init_special_inode(inode, inode->i_mode, rdev);
@@ -1784,7 +1784,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, S_IFDIR | mode);
+	inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFDIR | mode);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -2206,7 +2206,7 @@ retry:
 	if (IS_DIRSYNC(dir))
 		handle->h_sync = 1;
 
-	inode = ext3_new_inode (handle, dir, S_IFLNK|S_IRWXUGO);
+	inode = ext3_new_inode (handle, dir, &dentry->d_name, S_IFLNK|S_IRWXUGO);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
 		goto out_stop;
@@ -2253,13 +2253,6 @@ static int ext3_link (struct dentry * old_dentry,
 
 	dquot_initialize(dir);
 
-	/*
-	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
-	 * otherwise has the potential to corrupt the orphan inode list.
-	 */
-	if (inode->i_nlink == 0)
-		return -ENOENT;
-
 retry:
 	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 85c8cc8..071689f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -1464,6 +1464,13 @@ static void ext3_orphan_cleanup (struct super_block * sb,
 		return;
 	}
 
+	/* Check if feature set allows readwrite operations */
+	if (EXT3_HAS_RO_COMPAT_FEATURE(sb, ~EXT3_FEATURE_RO_COMPAT_SUPP)) {
+		ext3_msg(sb, KERN_INFO, "Skipping orphan cleanup due to "
+			 "unknown ROCOMPAT features");
+		return;
+	}
+
 	if (EXT3_SB(sb)->s_mount_state & EXT3_ERROR_FS) {
 		if (es->s_last_orphan)
 			jbd_debug(1, "Errors on filesystem, "
@@ -1936,6 +1943,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 	sb->s_qcop = &ext3_qctl_operations;
 	sb->dq_op = &ext3_quota_operations;
 #endif
+	memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
 	mutex_init(&sbi->s_orphan_lock);
 	mutex_init(&sbi->s_resize_lock);
diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h
index 377fe72..2be4f69 100644
--- a/fs/ext3/xattr.h
+++ b/fs/ext3/xattr.h
@@ -128,10 +128,10 @@ exit_ext3_xattr(void)
 
 #ifdef CONFIG_EXT3_FS_SECURITY
 extern int ext3_init_security(handle_t *handle, struct inode *inode,
-				struct inode *dir);
+			      struct inode *dir, const struct qstr *qstr);
 #else
 static inline int ext3_init_security(handle_t *handle, struct inode *inode,
-				struct inode *dir)
+				     struct inode *dir, const struct qstr *qstr)
 {
 	return 0;
 }
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index 03a99bf..b8d9f83 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -49,14 +49,15 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
 }
 
 int
-ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
+ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
+		   const struct qstr *qstr)
 {
 	int err;
 	size_t len;
 	void *value;
 	char *name;
 
-	err = security_inode_init_security(inode, dir, &name, &value, &len);
+	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			return 0;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ccce8a7..7516fb9 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -131,7 +131,7 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode,
 		 * fragmenting the file system's free space.  Maybe we
 		 * should have some hueristics or some way to allow
 		 * userspace to pass a hint to file system,
-		 * especiially if the latter case turns out to be
+		 * especially if the latter case turns out to be
 		 * common.
 		 */
 		ex = path[depth].p_ext;
@@ -2844,7 +2844,7 @@ fix_extent_len:
  * ext4_get_blocks_dio_write() when DIO to write
  * to an uninitialized extent.
  *
- * Writing to an uninitized extent may result in splitting the uninitialized
+ * Writing to an uninitialized extent may result in splitting the uninitialized
  * extent into multiple /initialized uninitialized extents (up to three)
  * There are three possibilities:
  *   a> There is no split required: Entire extent should be uninitialized
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index eb9097a..78b79e1 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1042,7 +1042,7 @@ got:
 	if (err)
 		goto fail_free_drop;
 
-	err = ext4_init_security(handle, inode, dir);
+	err = ext4_init_security(handle, inode, dir, qstr);
 	if (err)
 		goto fail_free_drop;
 
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 5485390..e781b7e 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2304,13 +2304,6 @@ static int ext4_link(struct dentry *old_dentry,
 
 	dquot_initialize(dir);
 
-	/*
-	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
-	 * otherwise has the potential to corrupt the orphan inode list.
-	 */
-	if (inode->i_nlink == 0)
-		return -ENOENT;
-
 retry:
 	handle = ext4_journal_start(dir, EXT4_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT4_INDEX_EXTRA_TRANS_BLOCKS);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index f6a318f..203f9e4 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3415,6 +3415,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	sb->s_qcop = &ext4_qctl_operations;
 	sb->dq_op = &ext4_quota_operations;
 #endif
+	memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid));
+
 	INIT_LIST_HEAD(&sbi->s_orphan); /* unlinked but open files */
 	mutex_init(&sbi->s_orphan_lock);
 	mutex_init(&sbi->s_resize_lock);
@@ -3509,7 +3511,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 	percpu_counter_set(&sbi->s_dirtyblocks_counter, 0);
 
 no_journal:
-	EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");
+	/*
+	 * The maximum number of concurrent works can be high and
+	 * concurrency isn't really necessary.  Limit it to 1.
+	 */
+	EXT4_SB(sb)->dio_unwritten_wq =
+		alloc_workqueue("ext4-dio-unwritten", WQ_MEM_RECLAIM, 1);
 	if (!EXT4_SB(sb)->dio_unwritten_wq) {
 		printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");
 		goto failed_mount_wq;
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index 1ef1652..25b7387 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -145,10 +145,10 @@ ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
 
 #ifdef CONFIG_EXT4_FS_SECURITY
 extern int ext4_init_security(handle_t *handle, struct inode *inode,
-				struct inode *dir);
+			      struct inode *dir, const struct qstr *qstr);
 #else
 static inline int ext4_init_security(handle_t *handle, struct inode *inode,
-				struct inode *dir)
+				     struct inode *dir, const struct qstr *qstr)
 {
 	return 0;
 }
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 9b21268..007c3bf 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -49,14 +49,15 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
 }
 
 int
-ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
+ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
+		   const struct qstr *qstr)
 {
 	int err;
 	size_t len;
 	void *value;
 	char *name;
 
-	err = security_inode_init_security(inode, dir, &name, &value, &len);
+	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			return 0;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 86753fe..0e277ec 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -757,8 +757,10 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
 	struct inode *inode =  de->d_inode;
 	u32 ipos_h, ipos_m, ipos_l;
 
-	if (len < 5)
+	if (len < 5) {
+		*lenp = 5;
 		return 255; /* no room */
+	}
 
 	ipos_h = MSDOS_I(inode)->i_pos >> 8;
 	ipos_m = (MSDOS_I(inode)->i_pos & 0xf0) << 24;
diff --git a/fs/fcntl.c b/fs/fcntl.c
index cb10261..6c82e5b 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -131,7 +131,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
 SYSCALL_DEFINE1(dup, unsigned int, fildes)
 {
 	int ret = -EBADF;
-	struct file *file = fget(fildes);
+	struct file *file = fget_raw(fildes);
 
 	if (file) {
 		ret = get_unused_fd();
@@ -426,15 +426,35 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
 	return err;
 }
 
+static int check_fcntl_cmd(unsigned cmd)
+{
+	switch (cmd) {
+	case F_DUPFD:
+	case F_DUPFD_CLOEXEC:
+	case F_GETFD:
+	case F_SETFD:
+	case F_GETFL:
+		return 1;
+	}
+	return 0;
+}
+
 SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
 {	
 	struct file *filp;
 	long err = -EBADF;
 
-	filp = fget(fd);
+	filp = fget_raw(fd);
 	if (!filp)
 		goto out;
 
+	if (unlikely(filp->f_mode & FMODE_PATH)) {
+		if (!check_fcntl_cmd(cmd)) {
+			fput(filp);
+			goto out;
+		}
+	}
+
 	err = security_file_fcntl(filp, cmd, arg);
 	if (err) {
 		fput(filp);
@@ -456,10 +476,17 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
 	long err;
 
 	err = -EBADF;
-	filp = fget(fd);
+	filp = fget_raw(fd);
 	if (!filp)
 		goto out;
 
+	if (unlikely(filp->f_mode & FMODE_PATH)) {
+		if (!check_fcntl_cmd(cmd)) {
+			fput(filp);
+			goto out;
+		}
+	}
+
 	err = security_file_fcntl(filp, cmd, arg);
 	if (err) {
 		fput(filp);
@@ -808,14 +835,14 @@ static int __init fcntl_init(void)
 	 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 	 * is defined as O_NONBLOCK on some platforms and not on others.
 	 */
-	BUILD_BUG_ON(18 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
+	BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
 		O_RDONLY	| O_WRONLY	| O_RDWR	|
 		O_CREAT		| O_EXCL	| O_NOCTTY	|
 		O_TRUNC		| O_APPEND	| /* O_NONBLOCK	| */
 		__O_SYNC	| O_DSYNC	| FASYNC	|
 		O_DIRECT	| O_LARGEFILE	| O_DIRECTORY	|
 		O_NOFOLLOW	| O_NOATIME	| O_CLOEXEC	|
-		__FMODE_EXEC
+		__FMODE_EXEC	| O_PATH
 		));
 
 	fasync_cache = kmem_cache_create("fasync_cache",
diff --git a/fs/fhandle.c b/fs/fhandle.c
new file mode 100644
index 0000000..bf93ad2
--- /dev/null
+++ b/fs/fhandle.c
@@ -0,0 +1,265 @@
+#include <linux/syscalls.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/exportfs.h>
+#include <linux/fs_struct.h>
+#include <linux/fsnotify.h>
+#include <asm/uaccess.h>
+#include "internal.h"
+
+static long do_sys_name_to_handle(struct path *path,
+				  struct file_handle __user *ufh,
+				  int __user *mnt_id)
+{
+	long retval;
+	struct file_handle f_handle;
+	int handle_dwords, handle_bytes;
+	struct file_handle *handle = NULL;
+
+	/*
+	 * We need t make sure wether the file system
+	 * support decoding of the file handle
+	 */
+	if (!path->mnt->mnt_sb->s_export_op ||
+	    !path->mnt->mnt_sb->s_export_op->fh_to_dentry)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle)))
+		return -EFAULT;
+
+	if (f_handle.handle_bytes > MAX_HANDLE_SZ)
+		return -EINVAL;
+
+	handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
+			 GFP_KERNEL);
+	if (!handle)
+		return -ENOMEM;
+
+	/* convert handle size to  multiple of sizeof(u32) */
+	handle_dwords = f_handle.handle_bytes >> 2;
+
+	/* we ask for a non connected handle */
+	retval = exportfs_encode_fh(path->dentry,
+				    (struct fid *)handle->f_handle,
+				    &handle_dwords,  0);
+	handle->handle_type = retval;
+	/* convert handle size to bytes */
+	handle_bytes = handle_dwords * sizeof(u32);
+	handle->handle_bytes = handle_bytes;
+	if ((handle->handle_bytes > f_handle.handle_bytes) ||
+	    (retval == 255) || (retval == -ENOSPC)) {
+		/* As per old exportfs_encode_fh documentation
+		 * we could return ENOSPC to indicate overflow
+		 * But file system returned 255 always. So handle
+		 * both the values
+		 */
+		/*
+		 * set the handle size to zero so we copy only
+		 * non variable part of the file_handle
+		 */
+		handle_bytes = 0;
+		retval = -EOVERFLOW;
+	} else
+		retval = 0;
+	/* copy the mount id */
+	if (copy_to_user(mnt_id, &path->mnt->mnt_id, sizeof(*mnt_id)) ||
+	    copy_to_user(ufh, handle,
+			 sizeof(struct file_handle) + handle_bytes))
+		retval = -EFAULT;
+	kfree(handle);
+	return retval;
+}
+
+/**
+ * sys_name_to_handle_at: convert name to handle
+ * @dfd: directory relative to which name is interpreted if not absolute
+ * @name: name that should be converted to handle.
+ * @handle: resulting file handle
+ * @mnt_id: mount id of the file system containing the file
+ * @flag: flag value to indicate whether to follow symlink or not
+ *
+ * @handle->handle_size indicate the space available to store the
+ * variable part of the file handle in bytes. If there is not
+ * enough space, the field is updated to return the minimum
+ * value required.
+ */
+SYSCALL_DEFINE5(name_to_handle_at, int, dfd, const char __user *, name,
+		struct file_handle __user *, handle, int __user *, mnt_id,
+		int, flag)
+{
+	struct path path;
+	int lookup_flags;
+	int err;
+
+	if ((flag & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
+		return -EINVAL;
+
+	lookup_flags = (flag & AT_SYMLINK_FOLLOW) ? LOOKUP_FOLLOW : 0;
+	if (flag & AT_EMPTY_PATH)
+		lookup_flags |= LOOKUP_EMPTY;
+	err = user_path_at(dfd, name, lookup_flags, &path);
+	if (!err) {
+		err = do_sys_name_to_handle(&path, handle, mnt_id);
+		path_put(&path);
+	}
+	return err;
+}
+
+static struct vfsmount *get_vfsmount_from_fd(int fd)
+{
+	struct path path;
+
+	if (fd == AT_FDCWD) {
+		struct fs_struct *fs = current->fs;
+		spin_lock(&fs->lock);
+		path = fs->pwd;
+		mntget(path.mnt);
+		spin_unlock(&fs->lock);
+	} else {
+		int fput_needed;
+		struct file *file = fget_light(fd, &fput_needed);
+		if (!file)
+			return ERR_PTR(-EBADF);
+		path = file->f_path;
+		mntget(path.mnt);
+		fput_light(file, fput_needed);
+	}
+	return path.mnt;
+}
+
+static int vfs_dentry_acceptable(void *context, struct dentry *dentry)
+{
+	return 1;
+}
+
+static int do_handle_to_path(int mountdirfd, struct file_handle *handle,
+			     struct path *path)
+{
+	int retval = 0;
+	int handle_dwords;
+
+	path->mnt = get_vfsmount_from_fd(mountdirfd);
+	if (IS_ERR(path->mnt)) {
+		retval = PTR_ERR(path->mnt);
+		goto out_err;
+	}
+	/* change the handle size to multiple of sizeof(u32) */
+	handle_dwords = handle->handle_bytes >> 2;
+	path->dentry = exportfs_decode_fh(path->mnt,
+					  (struct fid *)handle->f_handle,
+					  handle_dwords, handle->handle_type,
+					  vfs_dentry_acceptable, NULL);
+	if (IS_ERR(path->dentry)) {
+		retval = PTR_ERR(path->dentry);
+		goto out_mnt;
+	}
+	return 0;
+out_mnt:
+	mntput(path->mnt);
+out_err:
+	return retval;
+}
+
+static int handle_to_path(int mountdirfd, struct file_handle __user *ufh,
+		   struct path *path)
+{
+	int retval = 0;
+	struct file_handle f_handle;
+	struct file_handle *handle = NULL;
+
+	/*
+	 * With handle we don't look at the execute bit on the
+	 * the directory. Ideally we would like CAP_DAC_SEARCH.
+	 * But we don't have that
+	 */
+	if (!capable(CAP_DAC_READ_SEARCH)) {
+		retval = -EPERM;
+		goto out_err;
+	}
+	if (copy_from_user(&f_handle, ufh, sizeof(struct file_handle))) {
+		retval = -EFAULT;
+		goto out_err;
+	}
+	if ((f_handle.handle_bytes > MAX_HANDLE_SZ) ||
+	    (f_handle.handle_bytes == 0)) {
+		retval = -EINVAL;
+		goto out_err;
+	}
+	handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
+			 GFP_KERNEL);
+	if (!handle) {
+		retval = -ENOMEM;
+		goto out_err;
+	}
+	/* copy the full handle */
+	if (copy_from_user(handle, ufh,
+			   sizeof(struct file_handle) +
+			   f_handle.handle_bytes)) {
+		retval = -EFAULT;
+		goto out_handle;
+	}
+
+	retval = do_handle_to_path(mountdirfd, handle, path);
+
+out_handle:
+	kfree(handle);
+out_err:
+	return retval;
+}
+
+long do_handle_open(int mountdirfd,
+		    struct file_handle __user *ufh, int open_flag)
+{
+	long retval = 0;
+	struct path path;
+	struct file *file;
+	int fd;
+
+	retval = handle_to_path(mountdirfd, ufh, &path);
+	if (retval)
+		return retval;
+
+	fd = get_unused_fd_flags(open_flag);
+	if (fd < 0) {
+		path_put(&path);
+		return fd;
+	}
+	file = file_open_root(path.dentry, path.mnt, "", open_flag);
+	if (IS_ERR(file)) {
+		put_unused_fd(fd);
+		retval =  PTR_ERR(file);
+	} else {
+		retval = fd;
+		fsnotify_open(file);
+		fd_install(fd, file);
+	}
+	path_put(&path);
+	return retval;
+}
+
+/**
+ * sys_open_by_handle_at: Open the file handle
+ * @mountdirfd: directory file descriptor
+ * @handle: file handle to be opened
+ * @flag: open flags.
+ *
+ * @mountdirfd indicate the directory file descriptor
+ * of the mount point. file handle is decoded relative
+ * to the vfsmount pointed by the @mountdirfd. @flags
+ * value is same as the open(2) flags.
+ */
+SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
+		struct file_handle __user *, handle,
+		int, flags)
+{
+	long ret;
+
+	if (force_o_largefile())
+		flags |= O_LARGEFILE;
+
+	ret = do_handle_open(mountdirfd, handle, flags);
+	return ret;
+}
diff --git a/fs/fifo.c b/fs/fifo.c
index 4e303c2..b1a524d 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -66,8 +66,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
 				/* suppress POLLHUP until we have
 				 * seen a writer */
 				filp->f_version = pipe->w_counter;
-			} else 
-			{
+			} else {
 				wait_for_partner(inode, &pipe->w_counter);
 				if(signal_pending(current))
 					goto err_rd;
diff --git a/fs/file_table.c b/fs/file_table.c
index eb36b6b..01e4c1e 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -190,7 +190,8 @@ struct file *alloc_file(struct path *path, fmode_t mode,
 		file_take_write(file);
 		WARN_ON(mnt_clone_write(path->mnt));
 	}
-	ima_counts_get(file);
+	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		i_readcount_inc(path->dentry->d_inode);
 	return file;
 }
 EXPORT_SYMBOL(alloc_file);
@@ -246,11 +247,15 @@ static void __fput(struct file *file)
 		file->f_op->release(inode, file);
 	security_file_free(file);
 	ima_file_free(file);
-	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
+	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL &&
+		     !(file->f_mode & FMODE_PATH))) {
 		cdev_put(inode->i_cdev);
+	}
 	fops_put(file->f_op);
 	put_pid(file->f_owner.pid);
 	file_sb_list_del(file);
+	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		i_readcount_dec(inode);
 	if (file->f_mode & FMODE_WRITE)
 		drop_file_write_access(file);
 	file->f_path.dentry = NULL;
@@ -276,11 +281,10 @@ struct file *fget(unsigned int fd)
 	rcu_read_lock();
 	file = fcheck_files(files, fd);
 	if (file) {
-		if (!atomic_long_inc_not_zero(&file->f_count)) {
-			/* File object ref couldn't be taken */
-			rcu_read_unlock();
-			return NULL;
-		}
+		/* File object ref couldn't be taken */
+		if (file->f_mode & FMODE_PATH ||
+		    !atomic_long_inc_not_zero(&file->f_count))
+			file = NULL;
 	}
 	rcu_read_unlock();
 
@@ -289,6 +293,25 @@ struct file *fget(unsigned int fd)
 
 EXPORT_SYMBOL(fget);
 
+struct file *fget_raw(unsigned int fd)
+{
+	struct file *file;
+	struct files_struct *files = current->files;
+
+	rcu_read_lock();
+	file = fcheck_files(files, fd);
+	if (file) {
+		/* File object ref couldn't be taken */
+		if (!atomic_long_inc_not_zero(&file->f_count))
+			file = NULL;
+	}
+	rcu_read_unlock();
+
+	return file;
+}
+
+EXPORT_SYMBOL(fget_raw);
+
 /*
  * Lightweight file lookup - no refcnt increment if fd table isn't shared.
  *
@@ -313,6 +336,33 @@ struct file *fget_light(unsigned int fd, int *fput_needed)
 	*fput_needed = 0;
 	if (atomic_read(&files->count) == 1) {
 		file = fcheck_files(files, fd);
+		if (file && (file->f_mode & FMODE_PATH))
+			file = NULL;
+	} else {
+		rcu_read_lock();
+		file = fcheck_files(files, fd);
+		if (file) {
+			if (!(file->f_mode & FMODE_PATH) &&
+			    atomic_long_inc_not_zero(&file->f_count))
+				*fput_needed = 1;
+			else
+				/* Didn't get the reference, someone's freed */
+				file = NULL;
+		}
+		rcu_read_unlock();
+	}
+
+	return file;
+}
+
+struct file *fget_raw_light(unsigned int fd, int *fput_needed)
+{
+	struct file *file;
+	struct files_struct *files = current->files;
+
+	*fput_needed = 0;
+	if (atomic_read(&files->count) == 1) {
+		file = fcheck_files(files, fd);
 	} else {
 		rcu_read_lock();
 		file = fcheck_files(files, fd);
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 3e87cce..b6cca47 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -305,7 +305,7 @@ static void cuse_gendev_release(struct device *dev)
 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 {
 	struct cuse_conn *cc = fc_to_cc(fc);
-	struct cuse_init_out *arg = &req->misc.cuse_init_out;
+	struct cuse_init_out *arg = req->out.args[0].value;
 	struct page *page = req->pages[0];
 	struct cuse_devinfo devinfo = { };
 	struct device *dev;
@@ -384,6 +384,7 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 	dev_set_uevent_suppress(dev, 0);
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 out:
+	kfree(arg);
 	__free_page(page);
 	return;
 
@@ -405,6 +406,7 @@ static int cuse_send_init(struct cuse_conn *cc)
 	struct page *page;
 	struct fuse_conn *fc = &cc->fc;
 	struct cuse_init_in *arg;
+	void *outarg;
 
 	BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
 
@@ -419,6 +421,10 @@ static int cuse_send_init(struct cuse_conn *cc)
 	if (!page)
 		goto err_put_req;
 
+	outarg = kzalloc(sizeof(struct cuse_init_out), GFP_KERNEL);
+	if (!outarg)
+		goto err_free_page;
+
 	arg = &req->misc.cuse_init_in;
 	arg->major = FUSE_KERNEL_VERSION;
 	arg->minor = FUSE_KERNEL_MINOR_VERSION;
@@ -429,7 +435,7 @@ static int cuse_send_init(struct cuse_conn *cc)
 	req->in.args[0].value = arg;
 	req->out.numargs = 2;
 	req->out.args[0].size = sizeof(struct cuse_init_out);
-	req->out.args[0].value = &req->misc.cuse_init_out;
+	req->out.args[0].value = outarg;
 	req->out.args[1].size = CUSE_INIT_INFO_MAX;
 	req->out.argvar = 1;
 	req->out.argpages = 1;
@@ -440,6 +446,8 @@ static int cuse_send_init(struct cuse_conn *cc)
 
 	return 0;
 
+err_free_page:
+	__free_page(page);
 err_put_req:
 	fuse_put_request(fc, req);
 err:
@@ -458,7 +466,7 @@ static void cuse_fc_release(struct fuse_conn *fc)
  * @file: file struct being opened
  *
  * Userland CUSE server can create a CUSE device by opening /dev/cuse
- * and replying to the initilaization request kernel sends.  This
+ * and replying to the initialization request kernel sends.  This
  * function is responsible for handling CUSE device initialization.
  * Because the fd opened by this function is used during
  * initialization, this function only creates cuse_conn and sends
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index cf8d28d..640fc22 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -737,14 +737,12 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
 	if (WARN_ON(PageMlocked(oldpage)))
 		goto out_fallback_unlock;
 
-	remove_from_page_cache(oldpage);
-	page_cache_release(oldpage);
-
-	err = add_to_page_cache_locked(newpage, mapping, index, GFP_KERNEL);
+	err = replace_page_cache_page(oldpage, newpage, GFP_KERNEL);
 	if (err) {
-		printk(KERN_WARNING "fuse_try_move_page: failed to add page");
-		goto out_fallback_unlock;
+		unlock_page(newpage);
+		return err;
 	}
+
 	page_cache_get(newpage);
 
 	if (!(buf->flags & PIPE_BUF_FLAG_LRU))
@@ -1910,6 +1908,21 @@ __acquires(fc->lock)
 		kfree(dequeue_forget(fc, 1, NULL));
 }
 
+static void end_polls(struct fuse_conn *fc)
+{
+	struct rb_node *p;
+
+	p = rb_first(&fc->polled_files);
+
+	while (p) {
+		struct fuse_file *ff;
+		ff = rb_entry(p, struct fuse_file, polled_node);
+		wake_up_interruptible_all(&ff->poll_wait);
+
+		p = rb_next(p);
+	}
+}
+
 /*
  * Abort all requests.
  *
@@ -1937,6 +1950,7 @@ void fuse_abort_conn(struct fuse_conn *fc)
 		fc->blocked = 0;
 		end_io_requests(fc);
 		end_queued_requests(fc);
+		end_polls(fc);
 		wake_up_all(&fc->waitq);
 		wake_up_all(&fc->blocked_waitq);
 		kill_fasync(&fc->fasync, SIGIO, POLL_IN);
@@ -1953,6 +1967,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
 		fc->connected = 0;
 		fc->blocked = 0;
 		end_queued_requests(fc);
+		end_polls(fc);
 		wake_up_all(&fc->blocked_waitq);
 		spin_unlock(&fc->lock);
 		fuse_conn_put(fc);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8bd0ef9..c6ba49b 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -158,10 +158,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
 {
 	struct inode *inode;
 
-	if (nd && nd->flags & LOOKUP_RCU)
-		return -ECHILD;
-
-	inode = entry->d_inode;
+	inode = ACCESS_ONCE(entry->d_inode);
 	if (inode && is_bad_inode(inode))
 		return 0;
 	else if (fuse_dentry_time(entry) < get_jiffies_64()) {
@@ -177,6 +174,9 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
 		if (!inode)
 			return 0;
 
+		if (nd->flags & LOOKUP_RCU)
+			return -ECHILD;
+
 		fc = get_fuse_conn(inode);
 		req = fuse_get_req(fc);
 		if (IS_ERR(req))
@@ -970,6 +970,14 @@ static int fuse_access(struct inode *inode, int mask)
 	return err;
 }
 
+static int fuse_perm_getattr(struct inode *inode, int flags)
+{
+	if (flags & IPERM_FLAG_RCU)
+		return -ECHILD;
+
+	return fuse_do_getattr(inode, NULL, NULL);
+}
+
 /*
  * Check permission.  The two basic access models of FUSE are:
  *
@@ -989,9 +997,6 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 	bool refreshed = false;
 	int err = 0;
 
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
-
 	if (!fuse_allow_task(fc, current))
 		return -EACCES;
 
@@ -1000,9 +1005,15 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 	 */
 	if ((fc->flags & FUSE_DEFAULT_PERMISSIONS) ||
 	    ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))) {
-		err = fuse_update_attributes(inode, NULL, NULL, &refreshed);
-		if (err)
-			return err;
+		struct fuse_inode *fi = get_fuse_inode(inode);
+
+		if (fi->i_time < get_jiffies_64()) {
+			refreshed = true;
+
+			err = fuse_perm_getattr(inode, flags);
+			if (err)
+				return err;
+		}
 	}
 
 	if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
@@ -1012,7 +1023,7 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 		   attributes.  This is also needed, because the root
 		   node will at first have no permissions */
 		if (err == -EACCES && !refreshed) {
-			err = fuse_do_getattr(inode, NULL, NULL);
+			err = fuse_perm_getattr(inode, flags);
 			if (!err)
 				err = generic_permission(inode, mask,
 							flags, NULL);
@@ -1023,13 +1034,16 @@ static int fuse_permission(struct inode *inode, int mask, unsigned int flags)
 		   noticed immediately, only after the attribute
 		   timeout has expired */
 	} else if (mask & (MAY_ACCESS | MAY_CHDIR)) {
+		if (flags & IPERM_FLAG_RCU)
+			return -ECHILD;
+
 		err = fuse_access(inode, mask);
 	} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
 		if (!(inode->i_mode & S_IXUGO)) {
 			if (refreshed)
 				return -EACCES;
 
-			err = fuse_do_getattr(inode, NULL, NULL);
+			err = fuse_perm_getattr(inode, flags);
 			if (!err && !(inode->i_mode & S_IXUGO))
 				return -EACCES;
 		}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 9e0832d..6ea0073 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -222,7 +222,7 @@ static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode)
 		rb_erase(&ff->polled_node, &fc->polled_files);
 	spin_unlock(&fc->lock);
 
-	wake_up_interruptible_sync(&ff->poll_wait);
+	wake_up_interruptible_all(&ff->poll_wait);
 
 	inarg->fh = ff->fh;
 	inarg->flags = flags;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d428694..b788bec 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -272,7 +272,6 @@ struct fuse_req {
 		struct fuse_init_in init_in;
 		struct fuse_init_out init_out;
 		struct cuse_init_in cuse_init_in;
-		struct cuse_init_out cuse_init_out;
 		struct {
 			struct fuse_read_in in;
 			u64 attr_ver;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 9e3f68c..051b1a0 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -637,8 +637,10 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
 	u64 nodeid;
 	u32 generation;
 
-	if (*max_len < len)
+	if (*max_len < len) {
+		*max_len = len;
 		return  255;
+	}
 
 	nodeid = get_fuse_inode(inode)->nodeid;
 	generation = inode->i_generation;
diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile
index 21f7e46..f3d23ef 100644
--- a/fs/gfs2/Makefile
+++ b/fs/gfs2/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -I$(src)
+ccflags-y := -I$(src)
 obj-$(CONFIG_GFS2_FS) += gfs2.o
 gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \
 	glops.o inode.o log.o lops.o main.o meta_io.o \
diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c
index 7118f1a..cbc0715 100644
--- a/fs/gfs2/acl.c
+++ b/fs/gfs2/acl.c
@@ -80,8 +80,11 @@ int gfs2_check_acl(struct inode *inode, int mask, unsigned int flags)
 	struct posix_acl *acl;
 	int error;
 
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
+	if (flags & IPERM_FLAG_RCU) {
+		if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
+			return -ECHILD;
+		return -EAGAIN;
+	}
 
 	acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS);
 	if (IS_ERR(acl))
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 4f36f88..aad77e4 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -695,6 +695,7 @@ out:
 	if (error == 0)
 		return 0;
 
+	unlock_page(page);
 	page_cache_release(page);
 
 	gfs2_trans_end(sdp);
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 3c4039d..ef3dc4b 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -21,6 +21,7 @@
 #include "meta_io.h"
 #include "quota.h"
 #include "rgrp.h"
+#include "super.h"
 #include "trans.h"
 #include "dir.h"
 #include "util.h"
@@ -757,7 +758,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrp_list rlist;
 	u64 bn, bstart;
-	u32 blen;
+	u32 blen, btotal;
 	__be64 *p;
 	unsigned int rg_blocks = 0;
 	int metadata;
@@ -839,6 +840,7 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 
 	bstart = 0;
 	blen = 0;
+	btotal = 0;
 
 	for (p = top; p < bottom; p++) {
 		if (!*p)
@@ -851,9 +853,11 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 		else {
 			if (bstart) {
 				if (metadata)
-					gfs2_free_meta(ip, bstart, blen);
+					__gfs2_free_meta(ip, bstart, blen);
 				else
-					gfs2_free_data(ip, bstart, blen);
+					__gfs2_free_data(ip, bstart, blen);
+
+				btotal += blen;
 			}
 
 			bstart = bn;
@@ -865,11 +869,17 @@ static int do_strip(struct gfs2_inode *ip, struct buffer_head *dibh,
 	}
 	if (bstart) {
 		if (metadata)
-			gfs2_free_meta(ip, bstart, blen);
+			__gfs2_free_meta(ip, bstart, blen);
 		else
-			gfs2_free_data(ip, bstart, blen);
+			__gfs2_free_data(ip, bstart, blen);
+
+		btotal += blen;
 	}
 
+	gfs2_statfs_change(sdp, 0, +btotal, 0);
+	gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
+			  ip->i_inode.i_gid);
+
 	ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
 
 	gfs2_dinode_out(ip, dibh->b_data);
diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c
index 9023db8..b5a5e60 100644
--- a/fs/gfs2/export.c
+++ b/fs/gfs2/export.c
@@ -36,9 +36,13 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
 	struct super_block *sb = inode->i_sb;
 	struct gfs2_inode *ip = GFS2_I(inode);
 
-	if (*len < GFS2_SMALL_FH_SIZE ||
-	    (connectable && *len < GFS2_LARGE_FH_SIZE))
+	if (connectable && (*len < GFS2_LARGE_FH_SIZE)) {
+		*len = GFS2_LARGE_FH_SIZE;
 		return 255;
+	} else if (*len < GFS2_SMALL_FH_SIZE) {
+		*len = GFS2_SMALL_FH_SIZE;
+		return 255;
+	}
 
 	fh[0] = cpu_to_be32(ip->i_no_formal_ino >> 32);
 	fh[1] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 7cfdcb9..4074b95 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -448,15 +448,20 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
 
-	if (!(file->f_flags & O_NOATIME)) {
+	if (!(file->f_flags & O_NOATIME) &&
+	    !IS_NOATIME(&ip->i_inode)) {
 		struct gfs2_holder i_gh;
 		int error;
 
-		gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh);
+		gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
 		error = gfs2_glock_nq(&i_gh);
-		file_accessed(file);
-		if (error == 0)
-			gfs2_glock_dq_uninit(&i_gh);
+		if (error == 0) {
+			file_accessed(file);
+			gfs2_glock_dq(&i_gh);
+		}
+		gfs2_holder_uninit(&i_gh);
+		if (error)
+			return error;
 	}
 	vma->vm_ops = &gfs2_vm_ops;
 	vma->vm_flags |= VM_CAN_NONLINEAR;
@@ -617,8 +622,7 @@ static void empty_write_end(struct page *page, unsigned from,
 {
 	struct gfs2_inode *ip = GFS2_I(page->mapping->host);
 
-	page_zero_new_buffers(page, from, to);
-	flush_dcache_page(page);
+	zero_user(page, from, to-from);
 	mark_page_accessed(page);
 
 	if (!gfs2_is_writeback(ip))
@@ -627,36 +631,43 @@ static void empty_write_end(struct page *page, unsigned from,
 	block_commit_write(page, from, to);
 }
 
-static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
+static int needs_empty_write(sector_t block, struct inode *inode)
 {
-	unsigned start, end, next;
-	struct buffer_head *bh, *head;
 	int error;
+	struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 };
 
-	if (!page_has_buffers(page)) {
-		error = __block_write_begin(page, from, to - from, gfs2_block_map);
-		if (unlikely(error))
-			return error;
+	bh_map.b_size = 1 << inode->i_blkbits;
+	error = gfs2_block_map(inode, block, &bh_map, 0);
+	if (unlikely(error))
+		return error;
+	return !buffer_mapped(&bh_map);
+}
 
-		empty_write_end(page, from, to);
-		return 0;
-	}
+static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
+{
+	struct inode *inode = page->mapping->host;
+	unsigned start, end, next, blksize;
+	sector_t block = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	int ret;
 
-	bh = head = page_buffers(page);
+	blksize = 1 << inode->i_blkbits;
 	next = end = 0;
 	while (next < from) {
-		next += bh->b_size;
-		bh = bh->b_this_page;
+		next += blksize;
+		block++;
 	}
 	start = next;
 	do {
-		next += bh->b_size;
-		if (buffer_mapped(bh)) {
+		next += blksize;
+		ret = needs_empty_write(block, inode);
+		if (unlikely(ret < 0))
+			return ret;
+		if (ret == 0) {
 			if (end) {
-				error = __block_write_begin(page, start, end - start,
-							    gfs2_block_map);
-				if (unlikely(error))
-					return error;
+				ret = __block_write_begin(page, start, end - start,
+							  gfs2_block_map);
+				if (unlikely(ret))
+					return ret;
 				empty_write_end(page, start, end);
 				end = 0;
 			}
@@ -664,13 +675,13 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
 		}
 		else
 			end = next;
-		bh = bh->b_this_page;
+		block++;
 	} while (next < to);
 
 	if (end) {
-		error = __block_write_begin(page, start, end - start, gfs2_block_map);
-		if (unlikely(error))
-			return error;
+		ret = __block_write_begin(page, start, end - start, gfs2_block_map);
+		if (unlikely(ret))
+			return ret;
 		empty_write_end(page, start, end);
 	}
 
@@ -976,8 +987,10 @@ static void do_unflock(struct file *file, struct file_lock *fl)
 
 	mutex_lock(&fp->f_fl_mutex);
 	flock_lock_file_wait(file, fl);
-	if (fl_gh->gh_gl)
-		gfs2_glock_dq_uninit(fl_gh);
+	if (fl_gh->gh_gl) {
+		gfs2_glock_dq_wait(fl_gh);
+		gfs2_holder_uninit(fl_gh);
+	}
 	mutex_unlock(&fp->f_fl_mutex);
 }
 
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 7cd9a5a..e243131 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -26,6 +26,9 @@
 #include <linux/freezer.h>
 #include <linux/workqueue.h>
 #include <linux/jiffies.h>
+#include <linux/rcupdate.h>
+#include <linux/rculist_bl.h>
+#include <linux/bit_spinlock.h>
 
 #include "gfs2.h"
 #include "incore.h"
@@ -41,10 +44,6 @@
 #define CREATE_TRACE_POINTS
 #include "trace_gfs2.h"
 
-struct gfs2_gl_hash_bucket {
-        struct hlist_head hb_list;
-};
-
 struct gfs2_glock_iter {
 	int hash;			/* hash bucket index         */
 	struct gfs2_sbd *sdp;		/* incore superblock         */
@@ -54,7 +53,6 @@ struct gfs2_glock_iter {
 
 typedef void (*glock_examiner) (struct gfs2_glock * gl);
 
-static int gfs2_dump_lockstate(struct gfs2_sbd *sdp);
 static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl);
 #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0)
 static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target);
@@ -70,57 +68,9 @@ static DEFINE_SPINLOCK(lru_lock);
 #define GFS2_GL_HASH_SIZE       (1 << GFS2_GL_HASH_SHIFT)
 #define GFS2_GL_HASH_MASK       (GFS2_GL_HASH_SIZE - 1)
 
-static struct gfs2_gl_hash_bucket gl_hash_table[GFS2_GL_HASH_SIZE];
+static struct hlist_bl_head gl_hash_table[GFS2_GL_HASH_SIZE];
 static struct dentry *gfs2_root;
 
-/*
- * Despite what you might think, the numbers below are not arbitrary :-)
- * They are taken from the ipv4 routing hash code, which is well tested
- * and thus should be nearly optimal. Later on we might tweek the numbers
- * but for now this should be fine.
- *
- * The reason for putting the locks in a separate array from the list heads
- * is that we can have fewer locks than list heads and save memory. We use
- * the same hash function for both, but with a different hash mask.
- */
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) || \
-	defined(CONFIG_PROVE_LOCKING)
-
-#ifdef CONFIG_LOCKDEP
-# define GL_HASH_LOCK_SZ        256
-#else
-# if NR_CPUS >= 32
-#  define GL_HASH_LOCK_SZ       4096
-# elif NR_CPUS >= 16
-#  define GL_HASH_LOCK_SZ       2048
-# elif NR_CPUS >= 8
-#  define GL_HASH_LOCK_SZ       1024
-# elif NR_CPUS >= 4
-#  define GL_HASH_LOCK_SZ       512
-# else
-#  define GL_HASH_LOCK_SZ       256
-# endif
-#endif
-
-/* We never want more locks than chains */
-#if GFS2_GL_HASH_SIZE < GL_HASH_LOCK_SZ
-# undef GL_HASH_LOCK_SZ
-# define GL_HASH_LOCK_SZ GFS2_GL_HASH_SIZE
-#endif
-
-static rwlock_t gl_hash_locks[GL_HASH_LOCK_SZ];
-
-static inline rwlock_t *gl_lock_addr(unsigned int x)
-{
-	return &gl_hash_locks[x & (GL_HASH_LOCK_SZ-1)];
-}
-#else /* not SMP, so no spinlocks required */
-static inline rwlock_t *gl_lock_addr(unsigned int x)
-{
-	return NULL;
-}
-#endif
-
 /**
  * gl_hash() - Turn glock number into hash bucket number
  * @lock: The glock number
@@ -141,25 +91,35 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp,
 	return h;
 }
 
-/**
- * glock_free() - Perform a few checks and then release struct gfs2_glock
- * @gl: The glock to release
- *
- * Also calls lock module to release its internal structure for this glock.
- *
- */
+static inline void spin_lock_bucket(unsigned int hash)
+{
+	struct hlist_bl_head *bl = &gl_hash_table[hash];
+	bit_spin_lock(0, (unsigned long *)bl);
+}
 
-static void glock_free(struct gfs2_glock *gl)
+static inline void spin_unlock_bucket(unsigned int hash)
+{
+	struct hlist_bl_head *bl = &gl_hash_table[hash];
+	__bit_spin_unlock(0, (unsigned long *)bl);
+}
+
+static void gfs2_glock_dealloc(struct rcu_head *rcu)
+{
+	struct gfs2_glock *gl = container_of(rcu, struct gfs2_glock, gl_rcu);
+
+	if (gl->gl_ops->go_flags & GLOF_ASPACE)
+		kmem_cache_free(gfs2_glock_aspace_cachep, gl);
+	else
+		kmem_cache_free(gfs2_glock_cachep, gl);
+}
+
+void gfs2_glock_free(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
-	struct address_space *mapping = gfs2_glock2aspace(gl);
-	struct kmem_cache *cachep = gfs2_glock_cachep;
 
-	GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
-	trace_gfs2_glock_put(gl);
-	if (mapping)
-		cachep = gfs2_glock_aspace_cachep;
-	sdp->sd_lockstruct.ls_ops->lm_put_lock(cachep, gl);
+	call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
+	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
+		wake_up(&sdp->sd_glock_wait);
 }
 
 /**
@@ -185,34 +145,49 @@ static int demote_ok(const struct gfs2_glock *gl)
 {
 	const struct gfs2_glock_operations *glops = gl->gl_ops;
 
+	/* assert_spin_locked(&gl->gl_spin); */
+
 	if (gl->gl_state == LM_ST_UNLOCKED)
 		return 0;
-	if (!list_empty(&gl->gl_holders))
+	if (test_bit(GLF_LFLUSH, &gl->gl_flags))
+		return 0;
+	if ((gl->gl_name.ln_type != LM_TYPE_INODE) &&
+	    !list_empty(&gl->gl_holders))
 		return 0;
 	if (glops->go_demote_ok)
 		return glops->go_demote_ok(gl);
 	return 1;
 }
 
+
 /**
- * gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
+ * __gfs2_glock_schedule_for_reclaim - Add a glock to the reclaim list
  * @gl: the glock
  *
+ * If the glock is demotable, then we add it (or move it) to the end
+ * of the glock LRU list.
  */
 
-static void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
+static void __gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
 {
-	int may_reclaim;
-	may_reclaim = (demote_ok(gl) &&
-		       (atomic_read(&gl->gl_ref) == 1 ||
-			(gl->gl_name.ln_type == LM_TYPE_INODE &&
-			 atomic_read(&gl->gl_ref) <= 2)));
-	spin_lock(&lru_lock);
-	if (list_empty(&gl->gl_lru) && may_reclaim) {
+	if (demote_ok(gl)) {
+		spin_lock(&lru_lock);
+
+		if (!list_empty(&gl->gl_lru))
+			list_del_init(&gl->gl_lru);
+		else
+			atomic_inc(&lru_count);
+
 		list_add_tail(&gl->gl_lru, &lru_list);
-		atomic_inc(&lru_count);
+		spin_unlock(&lru_lock);
 	}
-	spin_unlock(&lru_lock);
+}
+
+void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl)
+{
+	spin_lock(&gl->gl_spin);
+	__gfs2_glock_schedule_for_reclaim(gl);
+	spin_unlock(&gl->gl_spin);
 }
 
 /**
@@ -227,7 +202,6 @@ void gfs2_glock_put_nolock(struct gfs2_glock *gl)
 {
 	if (atomic_dec_and_test(&gl->gl_ref))
 		GLOCK_BUG_ON(gl, 1);
-	gfs2_glock_schedule_for_reclaim(gl);
 }
 
 /**
@@ -236,30 +210,26 @@ void gfs2_glock_put_nolock(struct gfs2_glock *gl)
  *
  */
 
-int gfs2_glock_put(struct gfs2_glock *gl)
+void gfs2_glock_put(struct gfs2_glock *gl)
 {
-	int rv = 0;
+	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct address_space *mapping = gfs2_glock2aspace(gl);
 
-	write_lock(gl_lock_addr(gl->gl_hash));
-	if (atomic_dec_and_lock(&gl->gl_ref, &lru_lock)) {
-		hlist_del(&gl->gl_list);
+	if (atomic_dec_and_test(&gl->gl_ref)) {
+		spin_lock_bucket(gl->gl_hash);
+		hlist_bl_del_rcu(&gl->gl_list);
+		spin_unlock_bucket(gl->gl_hash);
+		spin_lock(&lru_lock);
 		if (!list_empty(&gl->gl_lru)) {
 			list_del_init(&gl->gl_lru);
 			atomic_dec(&lru_count);
 		}
 		spin_unlock(&lru_lock);
-		write_unlock(gl_lock_addr(gl->gl_hash));
 		GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));
-		glock_free(gl);
-		rv = 1;
-		goto out;
+		GLOCK_BUG_ON(gl, mapping && mapping->nrpages);
+		trace_gfs2_glock_put(gl);
+		sdp->sd_lockstruct.ls_ops->lm_put_lock(gl);
 	}
-	spin_lock(&gl->gl_spin);
-	gfs2_glock_schedule_for_reclaim(gl);
-	spin_unlock(&gl->gl_spin);
-	write_unlock(gl_lock_addr(gl->gl_hash));
-out:
-	return rv;
 }
 
 /**
@@ -275,17 +245,15 @@ static struct gfs2_glock *search_bucket(unsigned int hash,
 					const struct lm_lockname *name)
 {
 	struct gfs2_glock *gl;
-	struct hlist_node *h;
+	struct hlist_bl_node *h;
 
-	hlist_for_each_entry(gl, h, &gl_hash_table[hash].hb_list, gl_list) {
+	hlist_bl_for_each_entry_rcu(gl, h, &gl_hash_table[hash], gl_list) {
 		if (!lm_name_equal(&gl->gl_name, name))
 			continue;
 		if (gl->gl_sbd != sdp)
 			continue;
-
-		atomic_inc(&gl->gl_ref);
-
-		return gl;
+		if (atomic_inc_not_zero(&gl->gl_ref))
+			return gl;
 	}
 
 	return NULL;
@@ -743,10 +711,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 	struct gfs2_glock *gl, *tmp;
 	unsigned int hash = gl_hash(sdp, &name);
 	struct address_space *mapping;
+	struct kmem_cache *cachep;
 
-	read_lock(gl_lock_addr(hash));
+	rcu_read_lock();
 	gl = search_bucket(hash, sdp, &name);
-	read_unlock(gl_lock_addr(hash));
+	rcu_read_unlock();
 
 	*glp = gl;
 	if (gl)
@@ -755,9 +724,10 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 		return -ENOENT;
 
 	if (glops->go_flags & GLOF_ASPACE)
-		gl = kmem_cache_alloc(gfs2_glock_aspace_cachep, GFP_KERNEL);
+		cachep = gfs2_glock_aspace_cachep;
 	else
-		gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL);
+		cachep = gfs2_glock_cachep;
+	gl = kmem_cache_alloc(cachep, GFP_KERNEL);
 	if (!gl)
 		return -ENOMEM;
 
@@ -790,15 +760,16 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number,
 		mapping->writeback_index = 0;
 	}
 
-	write_lock(gl_lock_addr(hash));
+	spin_lock_bucket(hash);
 	tmp = search_bucket(hash, sdp, &name);
 	if (tmp) {
-		write_unlock(gl_lock_addr(hash));
-		glock_free(gl);
+		spin_unlock_bucket(hash);
+		kmem_cache_free(cachep, gl);
+		atomic_dec(&sdp->sd_glock_disposal);
 		gl = tmp;
 	} else {
-		hlist_add_head(&gl->gl_list, &gl_hash_table[hash].hb_list);
-		write_unlock(gl_lock_addr(hash));
+		hlist_bl_add_head_rcu(&gl->gl_list, &gl_hash_table[hash]);
+		spin_unlock_bucket(hash);
 	}
 
 	*glp = gl;
@@ -1007,13 +978,13 @@ fail:
 			insert_pt = &gh2->gh_list;
 	}
 	set_bit(GLF_QUEUED, &gl->gl_flags);
+	trace_gfs2_glock_queue(gh, 1);
 	if (likely(insert_pt == NULL)) {
 		list_add_tail(&gh->gh_list, &gl->gl_holders);
 		if (unlikely(gh->gh_flags & LM_FLAG_PRIORITY))
 			goto do_cancel;
 		return;
 	}
-	trace_gfs2_glock_queue(gh, 1);
 	list_add_tail(&gh->gh_list, insert_pt);
 do_cancel:
 	gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list);
@@ -1113,6 +1084,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh)
 		    !test_bit(GLF_DEMOTE, &gl->gl_flags))
 			fast_path = 1;
 	}
+	__gfs2_glock_schedule_for_reclaim(gl);
 	trace_gfs2_glock_queue(gh, 0);
 	spin_unlock(&gl->gl_spin);
 	if (likely(fast_path))
@@ -1276,10 +1248,8 @@ int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
 
 void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs)
 {
-	unsigned int x;
-
-	for (x = 0; x < num_gh; x++)
-		gfs2_glock_dq(&ghs[x]);
+	while (num_gh--)
+		gfs2_glock_dq(&ghs[num_gh]);
 }
 
 /**
@@ -1291,10 +1261,8 @@ void gfs2_glock_dq_m(unsigned int num_gh, struct gfs2_holder *ghs)
 
 void gfs2_glock_dq_uninit_m(unsigned int num_gh, struct gfs2_holder *ghs)
 {
-	unsigned int x;
-
-	for (x = 0; x < num_gh; x++)
-		gfs2_glock_dq_uninit(&ghs[x]);
+	while (num_gh--)
+		gfs2_glock_dq_uninit(&ghs[num_gh]);
 }
 
 void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
@@ -1440,42 +1408,30 @@ static struct shrinker glock_shrinker = {
  * @sdp: the filesystem
  * @bucket: the bucket
  *
- * Returns: 1 if the bucket has entries
  */
 
-static int examine_bucket(glock_examiner examiner, struct gfs2_sbd *sdp,
+static void examine_bucket(glock_examiner examiner, const struct gfs2_sbd *sdp,
 			  unsigned int hash)
 {
-	struct gfs2_glock *gl, *prev = NULL;
-	int has_entries = 0;
-	struct hlist_head *head = &gl_hash_table[hash].hb_list;
+	struct gfs2_glock *gl;
+	struct hlist_bl_head *head = &gl_hash_table[hash];
+	struct hlist_bl_node *pos;
 
-	read_lock(gl_lock_addr(hash));
-	/* Can't use hlist_for_each_entry - don't want prefetch here */
-	if (hlist_empty(head))
-		goto out;
-	gl = list_entry(head->first, struct gfs2_glock, gl_list);
-	while(1) {
-		if (!sdp || gl->gl_sbd == sdp) {
-			gfs2_glock_hold(gl);
-			read_unlock(gl_lock_addr(hash));
-			if (prev)
-				gfs2_glock_put(prev);
-			prev = gl;
+	rcu_read_lock();
+	hlist_bl_for_each_entry_rcu(gl, pos, head, gl_list) {
+		if ((gl->gl_sbd == sdp) && atomic_read(&gl->gl_ref))
 			examiner(gl);
-			has_entries = 1;
-			read_lock(gl_lock_addr(hash));
-		}
-		if (gl->gl_list.next == NULL)
-			break;
-		gl = list_entry(gl->gl_list.next, struct gfs2_glock, gl_list);
 	}
-out:
-	read_unlock(gl_lock_addr(hash));
-	if (prev)
-		gfs2_glock_put(prev);
+	rcu_read_unlock();
 	cond_resched();
-	return has_entries;
+}
+
+static void glock_hash_walk(glock_examiner examiner, const struct gfs2_sbd *sdp)
+{
+	unsigned x;
+
+	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
+		examine_bucket(examiner, sdp, x);
 }
 
 
@@ -1529,10 +1485,21 @@ static void clear_glock(struct gfs2_glock *gl)
 
 void gfs2_glock_thaw(struct gfs2_sbd *sdp)
 {
-	unsigned x;
+	glock_hash_walk(thaw_glock, sdp);
+}
 
-	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
-		examine_bucket(thaw_glock, sdp, x);
+static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
+{
+	int ret;
+	spin_lock(&gl->gl_spin);
+	ret = __dump_glock(seq, gl);
+	spin_unlock(&gl->gl_spin);
+	return ret;
+}
+
+static void dump_glock_func(struct gfs2_glock *gl)
+{
+	dump_glock(NULL, gl);
 }
 
 /**
@@ -1545,13 +1512,10 @@ void gfs2_glock_thaw(struct gfs2_sbd *sdp)
 
 void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
 {
-	unsigned int x;
-
-	for (x = 0; x < GFS2_GL_HASH_SIZE; x++)
-		examine_bucket(clear_glock, sdp, x);
+	glock_hash_walk(clear_glock, sdp);
 	flush_workqueue(glock_workqueue);
 	wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0);
-	gfs2_dump_lockstate(sdp);
+	glock_hash_walk(dump_glock_func, sdp);
 }
 
 void gfs2_glock_finish_truncate(struct gfs2_inode *ip)
@@ -1717,66 +1681,15 @@ out:
 	return error;
 }
 
-static int dump_glock(struct seq_file *seq, struct gfs2_glock *gl)
-{
-	int ret;
-	spin_lock(&gl->gl_spin);
-	ret = __dump_glock(seq, gl);
-	spin_unlock(&gl->gl_spin);
-	return ret;
-}
 
-/**
- * gfs2_dump_lockstate - print out the current lockstate
- * @sdp: the filesystem
- * @ub: the buffer to copy the information into
- *
- * If @ub is NULL, dump the lockstate to the console.
- *
- */
-
-static int gfs2_dump_lockstate(struct gfs2_sbd *sdp)
-{
-	struct gfs2_glock *gl;
-	struct hlist_node *h;
-	unsigned int x;
-	int error = 0;
-
-	for (x = 0; x < GFS2_GL_HASH_SIZE; x++) {
-
-		read_lock(gl_lock_addr(x));
-
-		hlist_for_each_entry(gl, h, &gl_hash_table[x].hb_list, gl_list) {
-			if (gl->gl_sbd != sdp)
-				continue;
-
-			error = dump_glock(NULL, gl);
-			if (error)
-				break;
-		}
-
-		read_unlock(gl_lock_addr(x));
-
-		if (error)
-			break;
-	}
-
-
-	return error;
-}
 
 
 int __init gfs2_glock_init(void)
 {
 	unsigned i;
 	for(i = 0; i < GFS2_GL_HASH_SIZE; i++) {
-		INIT_HLIST_HEAD(&gl_hash_table[i].hb_list);
-	}
-#ifdef GL_HASH_LOCK_SZ
-	for(i = 0; i < GL_HASH_LOCK_SZ; i++) {
-		rwlock_init(&gl_hash_locks[i]);
+		INIT_HLIST_BL_HEAD(&gl_hash_table[i]);
 	}
-#endif
 
 	glock_workqueue = alloc_workqueue("glock_workqueue", WQ_MEM_RECLAIM |
 					  WQ_HIGHPRI | WQ_FREEZABLE, 0);
@@ -1802,62 +1715,54 @@ void gfs2_glock_exit(void)
 	destroy_workqueue(gfs2_delete_workqueue);
 }
 
+static inline struct gfs2_glock *glock_hash_chain(unsigned hash)
+{
+	return hlist_bl_entry(hlist_bl_first_rcu(&gl_hash_table[hash]),
+			      struct gfs2_glock, gl_list);
+}
+
+static inline struct gfs2_glock *glock_hash_next(struct gfs2_glock *gl)
+{
+	return hlist_bl_entry(rcu_dereference(gl->gl_list.next),
+			      struct gfs2_glock, gl_list);
+}
+
 static int gfs2_glock_iter_next(struct gfs2_glock_iter *gi)
 {
 	struct gfs2_glock *gl;
 
-restart:
-	read_lock(gl_lock_addr(gi->hash));
-	gl = gi->gl;
-	if (gl) {
-		gi->gl = hlist_entry(gl->gl_list.next,
-				     struct gfs2_glock, gl_list);
-	} else {
-		gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
-				     struct gfs2_glock, gl_list);
-	}
-	if (gi->gl)
-		gfs2_glock_hold(gi->gl);
-	read_unlock(gl_lock_addr(gi->hash));
-	if (gl)
-		gfs2_glock_put(gl);
-	while (gi->gl == NULL) {
-		gi->hash++;
-		if (gi->hash >= GFS2_GL_HASH_SIZE)
-			return 1;
-		read_lock(gl_lock_addr(gi->hash));
-		gi->gl = hlist_entry(gl_hash_table[gi->hash].hb_list.first,
-				     struct gfs2_glock, gl_list);
-		if (gi->gl)
-			gfs2_glock_hold(gi->gl);
-		read_unlock(gl_lock_addr(gi->hash));
-	}
-
-	if (gi->sdp != gi->gl->gl_sbd)
-		goto restart;
+	do {
+		gl = gi->gl;
+		if (gl) {
+			gi->gl = glock_hash_next(gl);
+		} else {
+			gi->gl = glock_hash_chain(gi->hash);
+		}
+		while (gi->gl == NULL) {
+			gi->hash++;
+			if (gi->hash >= GFS2_GL_HASH_SIZE) {
+				rcu_read_unlock();
+				return 1;
+			}
+			gi->gl = glock_hash_chain(gi->hash);
+		}
+	/* Skip entries for other sb and dead entries */
+	} while (gi->sdp != gi->gl->gl_sbd || atomic_read(&gi->gl->gl_ref) == 0);
 
 	return 0;
 }
 
-static void gfs2_glock_iter_free(struct gfs2_glock_iter *gi)
-{
-	if (gi->gl)
-		gfs2_glock_put(gi->gl);
-	gi->gl = NULL;
-}
-
 static void *gfs2_glock_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	struct gfs2_glock_iter *gi = seq->private;
 	loff_t n = *pos;
 
 	gi->hash = 0;
+	rcu_read_lock();
 
 	do {
-		if (gfs2_glock_iter_next(gi)) {
-			gfs2_glock_iter_free(gi);
+		if (gfs2_glock_iter_next(gi))
 			return NULL;
-		}
 	} while (n--);
 
 	return gi->gl;
@@ -1870,10 +1775,8 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
 
 	(*pos)++;
 
-	if (gfs2_glock_iter_next(gi)) {
-		gfs2_glock_iter_free(gi);
+	if (gfs2_glock_iter_next(gi))
 		return NULL;
-	}
 
 	return gi->gl;
 }
@@ -1881,7 +1784,10 @@ static void *gfs2_glock_seq_next(struct seq_file *seq, void *iter_ptr,
 static void gfs2_glock_seq_stop(struct seq_file *seq, void *iter_ptr)
 {
 	struct gfs2_glock_iter *gi = seq->private;
-	gfs2_glock_iter_free(gi);
+
+	if (gi->gl)
+		rcu_read_unlock();
+	gi->gl = NULL;
 }
 
 static int gfs2_glock_seq_show(struct seq_file *seq, void *iter_ptr)
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
index 691851c..aea1606 100644
--- a/fs/gfs2/glock.h
+++ b/fs/gfs2/glock.h
@@ -118,7 +118,7 @@ struct lm_lockops {
 	int (*lm_mount) (struct gfs2_sbd *sdp, const char *fsname);
  	void (*lm_unmount) (struct gfs2_sbd *sdp);
 	void (*lm_withdraw) (struct gfs2_sbd *sdp);
-	void (*lm_put_lock) (struct kmem_cache *cachep, struct gfs2_glock *gl);
+	void (*lm_put_lock) (struct gfs2_glock *gl);
 	int (*lm_lock) (struct gfs2_glock *gl, unsigned int req_state,
 			unsigned int flags);
 	void (*lm_cancel) (struct gfs2_glock *gl);
@@ -174,7 +174,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp,
 		   int create, struct gfs2_glock **glp);
 void gfs2_glock_hold(struct gfs2_glock *gl);
 void gfs2_glock_put_nolock(struct gfs2_glock *gl);
-int gfs2_glock_put(struct gfs2_glock *gl);
+void gfs2_glock_put(struct gfs2_glock *gl);
 void gfs2_holder_init(struct gfs2_glock *gl, unsigned int state, unsigned flags,
 		      struct gfs2_holder *gh);
 void gfs2_holder_reinit(unsigned int state, unsigned flags,
@@ -223,25 +223,22 @@ static inline int gfs2_glock_nq_init(struct gfs2_glock *gl,
 	return error;
 }
 
-/*  Lock Value Block functions  */
-
-int gfs2_lvb_hold(struct gfs2_glock *gl);
-void gfs2_lvb_unhold(struct gfs2_glock *gl);
-
-void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
-void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
-void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
-void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
-void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
-void gfs2_glock_thaw(struct gfs2_sbd *sdp);
-
-int __init gfs2_glock_init(void);
-void gfs2_glock_exit(void);
-
-int gfs2_create_debugfs_file(struct gfs2_sbd *sdp);
-void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
-int gfs2_register_debugfs(void);
-void gfs2_unregister_debugfs(void);
+extern void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state);
+extern void gfs2_glock_complete(struct gfs2_glock *gl, int ret);
+extern void gfs2_reclaim_glock(struct gfs2_sbd *sdp);
+extern void gfs2_gl_hash_clear(struct gfs2_sbd *sdp);
+extern void gfs2_glock_finish_truncate(struct gfs2_inode *ip);
+extern void gfs2_glock_thaw(struct gfs2_sbd *sdp);
+extern void gfs2_glock_schedule_for_reclaim(struct gfs2_glock *gl);
+extern void gfs2_glock_free(struct gfs2_glock *gl);
+
+extern int __init gfs2_glock_init(void);
+extern void gfs2_glock_exit(void);
+
+extern int gfs2_create_debugfs_file(struct gfs2_sbd *sdp);
+extern void gfs2_delete_debugfs_file(struct gfs2_sbd *sdp);
+extern int gfs2_register_debugfs(void);
+extern void gfs2_unregister_debugfs(void);
 
 extern const struct lm_lockops gfs2_dlm_ops;
 
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 263561b..3754e3c 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -56,20 +56,26 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl)
 	BUG_ON(current->journal_info);
 	current->journal_info = &tr;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_ail_lock);
 	while (!list_empty(head)) {
 		bd = list_entry(head->next, struct gfs2_bufdata,
 				bd_ail_gl_list);
 		bh = bd->bd_bh;
 		gfs2_remove_from_ail(bd);
+		spin_unlock(&sdp->sd_ail_lock);
+
 		bd->bd_bh = NULL;
 		bh->b_private = NULL;
 		bd->bd_blkno = bh->b_blocknr;
+		gfs2_log_lock(sdp);
 		gfs2_assert_withdraw(sdp, !buffer_busy(bh));
 		gfs2_trans_add_revoke(sdp, bd);
+		gfs2_log_unlock(sdp);
+
+		spin_lock(&sdp->sd_ail_lock);
 	}
 	gfs2_assert_withdraw(sdp, !atomic_read(&gl->gl_ail_count));
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_ail_lock);
 
 	gfs2_trans_end(sdp);
 	gfs2_log_flush(sdp, NULL);
@@ -206,8 +212,17 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)
 static int inode_go_demote_ok(const struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
+	struct gfs2_holder *gh;
+
 	if (sdp->sd_jindex == gl->gl_object || sdp->sd_rindex == gl->gl_object)
 		return 0;
+
+	if (!list_empty(&gl->gl_holders)) {
+		gh = list_entry(gl->gl_holders.next, struct gfs2_holder, gh_list);
+		if (gh->gh_list.next != &gl->gl_holders)
+			return 0;
+	}
+
 	return 1;
 }
 
@@ -272,19 +287,6 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl)
 }
 
 /**
- * rgrp_go_demote_ok - Check to see if it's ok to unlock a RG's glock
- * @gl: the glock
- *
- * Returns: 1 if it's ok
- */
-
-static int rgrp_go_demote_ok(const struct gfs2_glock *gl)
-{
-	const struct address_space *mapping = (const struct address_space *)(gl + 1);
-	return !mapping->nrpages;
-}
-
-/**
  * rgrp_go_lock - operation done after an rgrp lock is locked by
  *    a first holder on this node.
  * @gl: the glock
@@ -410,7 +412,6 @@ const struct gfs2_glock_operations gfs2_inode_glops = {
 const struct gfs2_glock_operations gfs2_rgrp_glops = {
 	.go_xmote_th = rgrp_go_sync,
 	.go_inval = rgrp_go_inval,
-	.go_demote_ok = rgrp_go_demote_ok,
 	.go_lock = rgrp_go_lock,
 	.go_unlock = rgrp_go_unlock,
 	.go_dump = gfs2_rgrp_dump,
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index a79790c..870a89d 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -15,6 +15,8 @@
 #include <linux/workqueue.h>
 #include <linux/dlm.h>
 #include <linux/buffer_head.h>
+#include <linux/rcupdate.h>
+#include <linux/rculist_bl.h>
 
 #define DIO_WAIT	0x00000010
 #define DIO_METADATA	0x00000020
@@ -201,7 +203,7 @@ enum {
 };
 
 struct gfs2_glock {
-	struct hlist_node gl_list;
+	struct hlist_bl_node gl_list;
 	unsigned long gl_flags;		/* GLF_... */
 	struct lm_lockname gl_name;
 	atomic_t gl_ref;
@@ -234,6 +236,7 @@ struct gfs2_glock {
 	atomic_t gl_ail_count;
 	struct delayed_work gl_work;
 	struct work_struct gl_delete;
+	struct rcu_head gl_rcu;
 };
 
 #define GFS2_MIN_LVB_SIZE 32	/* Min size of LVB that gfs2 supports */
@@ -314,6 +317,7 @@ enum {
 	QDF_USER		= 0,
 	QDF_CHANGE		= 1,
 	QDF_LOCKED		= 2,
+	QDF_REFRESH		= 3,
 };
 
 struct gfs2_quota_data {
@@ -647,6 +651,7 @@ struct gfs2_sbd {
 	unsigned int sd_log_flush_head;
 	u64 sd_log_flush_wrapped;
 
+	spinlock_t sd_ail_lock;
 	struct list_head sd_ail1_list;
 	struct list_head sd_ail2_list;
 	u64 sd_ail_sync_gen;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 7aa7d4f..97d54a2 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -763,14 +763,15 @@ fail:
 	return error;
 }
 
-static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip)
+static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
+			      const struct qstr *qstr)
 {
 	int err;
 	size_t len;
 	void *value;
 	char *name;
 
-	err = security_inode_init_security(&ip->i_inode, &dip->i_inode,
+	err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
 					   &name, &value, &len);
 
 	if (err) {
@@ -854,7 +855,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
 	if (error)
 		goto fail_gunlock2;
 
-	error = gfs2_security_init(dip, GFS2_I(inode));
+	error = gfs2_security_init(dip, GFS2_I(inode), name);
 	if (error)
 		goto fail_gunlock2;
 
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index 6e493ae..98c80d8 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -22,7 +22,6 @@ static void gdlm_ast(void *arg)
 {
 	struct gfs2_glock *gl = arg;
 	unsigned ret = gl->gl_state;
-	struct gfs2_sbd *sdp = gl->gl_sbd;
 
 	BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
 
@@ -31,12 +30,7 @@ static void gdlm_ast(void *arg)
 
 	switch (gl->gl_lksb.sb_status) {
 	case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */
-		if (gl->gl_ops->go_flags & GLOF_ASPACE)
-			kmem_cache_free(gfs2_glock_aspace_cachep, gl);
-		else
-			kmem_cache_free(gfs2_glock_cachep, gl);
-		if (atomic_dec_and_test(&sdp->sd_glock_disposal))
-			wake_up(&sdp->sd_glock_wait);
+		gfs2_glock_free(gl);
 		return;
 	case -DLM_ECANCEL: /* Cancel while getting lock */
 		ret |= LM_OUT_CANCELED;
@@ -164,16 +158,14 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
 			GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
 }
 
-static void gdlm_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
+static void gdlm_put_lock(struct gfs2_glock *gl)
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
 	int error;
 
 	if (gl->gl_lksb.sb_lkid == 0) {
-		kmem_cache_free(cachep, gl);
-		if (atomic_dec_and_test(&sdp->sd_glock_disposal))
-			wake_up(&sdp->sd_glock_wait);
+		gfs2_glock_free(gl);
 		return;
 	}
 
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index eb01f35..e7ed31f 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -67,7 +67,7 @@ unsigned int gfs2_struct2blk(struct gfs2_sbd *sdp, unsigned int nstruct,
  * @mapping: The associated mapping (maybe NULL)
  * @bd: The gfs2_bufdata to remove
  *
- * The log lock _must_ be held when calling this function
+ * The ail lock _must_ be held when calling this function
  *
  */
 
@@ -88,8 +88,8 @@ void gfs2_remove_from_ail(struct gfs2_bufdata *bd)
  */
 
 static void gfs2_ail1_start_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai)
-__releases(&sdp->sd_log_lock)
-__acquires(&sdp->sd_log_lock)
+__releases(&sdp->sd_ail_lock)
+__acquires(&sdp->sd_ail_lock)
 {
 	struct gfs2_bufdata *bd, *s;
 	struct buffer_head *bh;
@@ -117,7 +117,7 @@ __acquires(&sdp->sd_log_lock)
 			list_move(&bd->bd_ail_st_list, &ai->ai_ail1_list);
 
 			get_bh(bh);
-			gfs2_log_unlock(sdp);
+			spin_unlock(&sdp->sd_ail_lock);
 			lock_buffer(bh);
 			if (test_clear_buffer_dirty(bh)) {
 				bh->b_end_io = end_buffer_write_sync;
@@ -126,7 +126,7 @@ __acquires(&sdp->sd_log_lock)
 				unlock_buffer(bh);
 				brelse(bh);
 			}
-			gfs2_log_lock(sdp);
+			spin_lock(&sdp->sd_ail_lock);
 
 			retry = 1;
 			break;
@@ -175,10 +175,10 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp)
 	struct gfs2_ail *ai;
 	int done = 0;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_ail_lock);
 	head = &sdp->sd_ail1_list;
 	if (list_empty(head)) {
-		gfs2_log_unlock(sdp);
+		spin_unlock(&sdp->sd_ail_lock);
 		return;
 	}
 	sync_gen = sdp->sd_ail_sync_gen++;
@@ -189,13 +189,13 @@ static void gfs2_ail1_start(struct gfs2_sbd *sdp)
 			if (ai->ai_sync_gen >= sync_gen)
 				continue;
 			ai->ai_sync_gen = sync_gen;
-			gfs2_ail1_start_one(sdp, ai); /* This may drop log lock */
+			gfs2_ail1_start_one(sdp, ai); /* This may drop ail lock */
 			done = 0;
 			break;
 		}
 	}
 
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_ail_lock);
 }
 
 static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
@@ -203,7 +203,7 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
 	struct gfs2_ail *ai, *s;
 	int ret;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_ail_lock);
 
 	list_for_each_entry_safe_reverse(ai, s, &sdp->sd_ail1_list, ai_list) {
 		if (gfs2_ail1_empty_one(sdp, ai, flags))
@@ -214,7 +214,7 @@ static int gfs2_ail1_empty(struct gfs2_sbd *sdp, int flags)
 
 	ret = list_empty(&sdp->sd_ail1_list);
 
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_ail_lock);
 
 	return ret;
 }
@@ -247,7 +247,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
 	int wrap = (new_tail < old_tail);
 	int a, b, rm;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_ail_lock);
 
 	list_for_each_entry_safe(ai, safe, &sdp->sd_ail2_list, ai_list) {
 		a = (old_tail <= ai->ai_first);
@@ -263,7 +263,7 @@ static void ail2_empty(struct gfs2_sbd *sdp, unsigned int new_tail)
 		kfree(ai);
 	}
 
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_ail_lock);
 }
 
 /**
@@ -421,7 +421,7 @@ static unsigned int current_tail(struct gfs2_sbd *sdp)
 	struct gfs2_ail *ai;
 	unsigned int tail;
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_ail_lock);
 
 	if (list_empty(&sdp->sd_ail1_list)) {
 		tail = sdp->sd_log_head;
@@ -430,7 +430,7 @@ static unsigned int current_tail(struct gfs2_sbd *sdp)
 		tail = ai->ai_first;
 	}
 
-	gfs2_log_unlock(sdp);
+	spin_unlock(&sdp->sd_ail_lock);
 
 	return tail;
 }
@@ -743,10 +743,12 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl)
 	sdp->sd_log_commited_databuf = 0;
 	sdp->sd_log_commited_revoke = 0;
 
+	spin_lock(&sdp->sd_ail_lock);
 	if (!list_empty(&ai->ai_ail1_list)) {
 		list_add(&ai->ai_list, &sdp->sd_ail1_list);
 		ai = NULL;
 	}
+	spin_unlock(&sdp->sd_ail_lock);
 	gfs2_log_unlock(sdp);
 	trace_gfs2_log_flush(sdp, 0);
 	up_write(&sdp->sd_log_flush_lock);
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index bf33f82..e919abf 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -51,8 +51,10 @@ static void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh)
 	/* If this buffer is in the AIL and it has already been written
 	 * to in-place disk block, remove it from the AIL.
 	 */
+	spin_lock(&sdp->sd_ail_lock);
 	if (bd->bd_ail)
 		list_move(&bd->bd_ail_st_list, &bd->bd_ail->ai_ail2_list);
+	spin_unlock(&sdp->sd_ail_lock);
 	get_bh(bh);
 	atomic_inc(&sdp->sd_log_pinned);
 	trace_gfs2_pin(bd, 1);
@@ -80,7 +82,7 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
 	mark_buffer_dirty(bh);
 	clear_buffer_pinned(bh);
 
-	gfs2_log_lock(sdp);
+	spin_lock(&sdp->sd_ail_lock);
 	if (bd->bd_ail) {
 		list_del(&bd->bd_ail_st_list);
 		brelse(bh);
@@ -91,9 +93,11 @@ static void gfs2_unpin(struct gfs2_sbd *sdp, struct buffer_head *bh,
 	}
 	bd->bd_ail = ai;
 	list_add(&bd->bd_ail_st_list, &ai->ai_ail1_list);
-	clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
+	spin_unlock(&sdp->sd_ail_lock);
+
+	if (test_and_clear_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags))
+		gfs2_glock_schedule_for_reclaim(bd->bd_gl);
 	trace_gfs2_pin(bd, 0);
-	gfs2_log_unlock(sdp);
 	unlock_buffer(bh);
 	atomic_dec(&sdp->sd_log_pinned);
 }
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c
index 72c31a3..888a5f5 100644
--- a/fs/gfs2/main.c
+++ b/fs/gfs2/main.c
@@ -14,6 +14,8 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gfs2_ondisk.h>
+#include <linux/rcupdate.h>
+#include <linux/rculist_bl.h>
 #include <asm/atomic.h>
 
 #include "gfs2.h"
@@ -45,7 +47,7 @@ static void gfs2_init_glock_once(void *foo)
 {
 	struct gfs2_glock *gl = foo;
 
-	INIT_HLIST_NODE(&gl->gl_list);
+	INIT_HLIST_BL_NODE(&gl->gl_list);
 	spin_lock_init(&gl->gl_spin);
 	INIT_LIST_HEAD(&gl->gl_holders);
 	INIT_LIST_HEAD(&gl->gl_lru);
@@ -191,6 +193,8 @@ static void __exit exit_gfs2_fs(void)
 	unregister_filesystem(&gfs2meta_fs_type);
 	destroy_workqueue(gfs_recovery_wq);
 
+	rcu_barrier();
+
 	kmem_cache_destroy(gfs2_quotad_cachep);
 	kmem_cache_destroy(gfs2_rgrpd_cachep);
 	kmem_cache_destroy(gfs2_bufdata_cachep);
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 939739c..01d97f4 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -326,6 +326,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
 		brelse(bh);
 	}
 	if (bd) {
+		spin_lock(&sdp->sd_ail_lock);
 		if (bd->bd_ail) {
 			gfs2_remove_from_ail(bd);
 			bh->b_private = NULL;
@@ -333,6 +334,7 @@ void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int
 			bd->bd_blkno = bh->b_blocknr;
 			gfs2_trans_add_revoke(sdp, bd);
 		}
+		spin_unlock(&sdp->sd_ail_lock);
 	}
 	clear_buffer_dirty(bh);
 	clear_buffer_uptodate(bh);
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 777927c..42ef243 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -99,6 +99,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
 
 	init_waitqueue_head(&sdp->sd_log_waitq);
 	init_waitqueue_head(&sdp->sd_logd_waitq);
+	spin_lock_init(&sdp->sd_ail_lock);
 	INIT_LIST_HEAD(&sdp->sd_ail1_list);
 	INIT_LIST_HEAD(&sdp->sd_ail2_list);
 
@@ -928,17 +929,9 @@ static const match_table_t nolock_tokens = {
 	{ Opt_err, NULL },
 };
 
-static void nolock_put_lock(struct kmem_cache *cachep, struct gfs2_glock *gl)
-{
-	struct gfs2_sbd *sdp = gl->gl_sbd;
-	kmem_cache_free(cachep, gl);
-	if (atomic_dec_and_test(&sdp->sd_glock_disposal))
-		wake_up(&sdp->sd_glock_wait);
-}
-
 static const struct lm_lockops nolock_ops = {
 	.lm_proto_name = "lock_nolock",
-	.lm_put_lock = nolock_put_lock,
+	.lm_put_lock = gfs2_glock_free,
 	.lm_tokens = &nolock_tokens,
 };
 
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c
index d8b26ac..09e436a 100644
--- a/fs/gfs2/ops_inode.c
+++ b/fs/gfs2/ops_inode.c
@@ -1026,9 +1026,9 @@ static void gfs2_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
 
 /**
  * gfs2_permission -
- * @inode:
- * @mask:
- * @nd: passed from Linux VFS, ignored by us
+ * @inode: The inode
+ * @mask: The mask to be tested
+ * @flags: Indicates whether this is an RCU path walk or not
  *
  * This may be called from the VFS directly, or from within GFS2 with the
  * inode locked, so we look to see if the glock is already locked and only
@@ -1044,11 +1044,11 @@ int gfs2_permission(struct inode *inode, int mask, unsigned int flags)
 	int error;
 	int unlock = 0;
 
-	if (flags & IPERM_FLAG_RCU)
-		return -ECHILD;
 
 	ip = GFS2_I(inode);
 	if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) {
+		if (flags & IPERM_FLAG_RCU)
+			return -ECHILD;
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
 		if (error)
 			return error;
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index a689901..e23d986 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -834,6 +834,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
 			goto out_end_trans;
 
 		do_qc(qd, -qd->qd_change_sync);
+		set_bit(QDF_REFRESH, &qd->qd_flags);
 	}
 
 	error = 0;
@@ -929,6 +930,7 @@ int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_alloc *al = ip->i_alloc;
+	struct gfs2_quota_data *qd;
 	unsigned int x;
 	int error = 0;
 
@@ -942,7 +944,11 @@ int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid)
 	     sort_qd, NULL);
 
 	for (x = 0; x < al->al_qd_num; x++) {
-		error = do_glock(al->al_qd[x], NO_FORCE, &al->al_qd_ghs[x]);
+		int force = NO_FORCE;
+		qd = al->al_qd[x];
+		if (test_and_clear_bit(QDF_REFRESH, &qd->qd_flags))
+			force = FORCE;
+		error = do_glock(qd, force, &al->al_qd_ghs[x]);
 		if (error)
 			break;
 	}
@@ -1587,6 +1593,8 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
 
 	offset = qd2offset(qd);
 	alloc_required = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota));
+	if (gfs2_is_stuffed(ip))
+		alloc_required = 1;
 	if (alloc_required) {
 		al = gfs2_alloc_get(ip);
 		if (al == NULL)
@@ -1600,7 +1608,9 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
 		blocks += gfs2_rg_blocks(al);
 	}
 
-	error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0);
+	/* Some quotas span block boundaries and can update two blocks,
+	   adding an extra block to the transaction to handle such quotas */
+	error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 2, 0);
 	if (error)
 		goto out_release;
 
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 7293ea2..cf930cd 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -1602,7 +1602,7 @@ rgrp_error:
  *
  */
 
-void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *rgd;
@@ -1617,7 +1617,21 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
 	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
 
 	gfs2_trans_add_rg(rgd);
+}
 
+/**
+ * gfs2_free_data - free a contiguous run of data block(s)
+ * @ip: the inode these blocks are being freed from
+ * @bstart: first block of a run of contiguous blocks
+ * @blen: the length of the block run
+ *
+ */
+
+void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+
+	__gfs2_free_data(ip, bstart, blen);
 	gfs2_statfs_change(sdp, 0, +blen, 0);
 	gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
 }
@@ -1630,7 +1644,7 @@ void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen)
  *
  */
 
-void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
+void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
 {
 	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
 	struct gfs2_rgrpd *rgd;
@@ -1645,10 +1659,24 @@ void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
 	gfs2_rgrp_out(rgd, rgd->rd_bits[0].bi_bh->b_data);
 
 	gfs2_trans_add_rg(rgd);
+	gfs2_meta_wipe(ip, bstart, blen);
+}
 
+/**
+ * gfs2_free_meta - free a contiguous run of data block(s)
+ * @ip: the inode these blocks are being freed from
+ * @bstart: first block of a run of contiguous blocks
+ * @blen: the length of the block run
+ *
+ */
+
+void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen)
+{
+	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+
+	__gfs2_free_meta(ip, bstart, blen);
 	gfs2_statfs_change(sdp, 0, +blen, 0);
 	gfs2_quota_change(ip, -(s64)blen, ip->i_inode.i_uid, ip->i_inode.i_gid);
-	gfs2_meta_wipe(ip, bstart, blen);
 }
 
 void gfs2_unlink_di(struct inode *inode)
diff --git a/fs/gfs2/rgrp.h b/fs/gfs2/rgrp.h
index 50c2bb0..a80e303 100644
--- a/fs/gfs2/rgrp.h
+++ b/fs/gfs2/rgrp.h
@@ -52,7 +52,9 @@ extern int gfs2_ri_update(struct gfs2_inode *ip);
 extern int gfs2_alloc_block(struct gfs2_inode *ip, u64 *bn, unsigned int *n);
 extern int gfs2_alloc_di(struct gfs2_inode *ip, u64 *bn, u64 *generation);
 
+extern void __gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
 extern void gfs2_free_data(struct gfs2_inode *ip, u64 bstart, u32 blen);
+extern void __gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
 extern void gfs2_free_meta(struct gfs2_inode *ip, u64 bstart, u32 blen);
 extern void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip);
 extern void gfs2_unlink_di(struct inode *inode);
diff --git a/fs/hpfs/Kconfig b/fs/hpfs/Kconfig
index 63b6f56..0c39dc3 100644
--- a/fs/hpfs/Kconfig
+++ b/fs/hpfs/Kconfig
@@ -1,7 +1,7 @@
 config HPFS_FS
 	tristate "OS/2 HPFS file system support"
 	depends on BLOCK
-	depends on BKL # nontrivial to fix
+	depends on BROKEN || !PREEMPT
 	help
 	  OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
 	  is the file system used for organizing files on OS/2 hard disk
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index d32f63a..b3d7c0d 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -6,16 +6,15 @@
  *  directory VFS functions
  */
 
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include "hpfs_fn.h"
 
 static int hpfs_dir_release(struct inode *inode, struct file *filp)
 {
-	lock_kernel();
+	hpfs_lock(inode->i_sb);
 	hpfs_del_pos(inode, &filp->f_pos);
 	/*hpfs_write_if_changed(inode);*/
-	unlock_kernel();
+	hpfs_unlock(inode->i_sb);
 	return 0;
 }
 
@@ -30,7 +29,7 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
 	struct super_block *s = i->i_sb;
 
-	lock_kernel();
+	hpfs_lock(s);
 
 	/*printk("dir lseek\n");*/
 	if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
@@ -43,12 +42,12 @@ static loff_t hpfs_dir_lseek(struct file *filp, loff_t off, int whence)
 	}
 	mutex_unlock(&i->i_mutex);
 ok:
-	unlock_kernel();
+	hpfs_unlock(s);
 	return filp->f_pos = new_off;
 fail:
 	mutex_unlock(&i->i_mutex);
 	/*printk("illegal lseek: %016llx\n", new_off);*/
-	unlock_kernel();
+	hpfs_unlock(s);
 	return -ESPIPE;
 }
 
@@ -64,7 +63,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 	int c1, c2 = 0;
 	int ret = 0;
 
-	lock_kernel();
+	hpfs_lock(inode->i_sb);
 
 	if (hpfs_sb(inode->i_sb)->sb_chk) {
 		if (hpfs_chk_sectors(inode->i_sb, inode->i_ino, 1, "dir_fnode")) {
@@ -167,7 +166,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 		hpfs_brelse4(&qbh);
 	}
 out:
-	unlock_kernel();
+	hpfs_unlock(inode->i_sb);
 	return ret;
 }
 
@@ -197,10 +196,10 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
 	struct inode *result = NULL;
 	struct hpfs_inode_info *hpfs_result;
 
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	if ((err = hpfs_chk_name(name, &len))) {
 		if (err == -ENAMETOOLONG) {
-			unlock_kernel();
+			hpfs_unlock(dir->i_sb);
 			return ERR_PTR(-ENAMETOOLONG);
 		}
 		goto end_add;
@@ -298,7 +297,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
 
 	end:
 	end_add:
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	d_add(dentry, result);
 	return NULL;
 
@@ -311,7 +310,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
 	
 	/*bail:*/
 
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return ERR_PTR(-ENOENT);
 }
 
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index c034088..2dbae20 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -6,16 +6,15 @@
  *  file VFS functions
  */
 
-#include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
 #define BLOCKS(size) (((size) + 511) >> 9)
 
 static int hpfs_file_release(struct inode *inode, struct file *file)
 {
-	lock_kernel();
+	hpfs_lock(inode->i_sb);
 	hpfs_write_if_changed(inode);
-	unlock_kernel();
+	hpfs_unlock(inode->i_sb);
 	return 0;
 }
 
@@ -49,14 +48,14 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
 static void hpfs_truncate(struct inode *i)
 {
 	if (IS_IMMUTABLE(i)) return /*-EPERM*/;
-	lock_kernel();
+	hpfs_lock(i->i_sb);
 	hpfs_i(i)->i_n_secs = 0;
 	i->i_blocks = 1 + ((i->i_size + 511) >> 9);
 	hpfs_i(i)->mmu_private = i->i_size;
 	hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
 	hpfs_write_inode(i);
 	hpfs_i(i)->i_n_secs = 0;
-	unlock_kernel();
+	hpfs_unlock(i->i_sb);
 }
 
 static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 1c43dbe..c15adbc 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -342,3 +342,25 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t)
 	extern struct timezone sys_tz;
 	return t - sys_tz.tz_minuteswest * 60 - hpfs_sb(s)->sb_timeshift;
 }
+
+/*
+ * Locking:
+ *
+ * hpfs_lock() is a leftover from the big kernel lock.
+ * Right now, these functions are empty and only left
+ * for documentation purposes. The file system no longer
+ * works on SMP systems, so the lock is not needed
+ * any more.
+ *
+ * If someone is interested in making it work again, this
+ * would be the place to start by adding a per-superblock
+ * mutex and fixing all the bugs and performance issues
+ * caused by that.
+ */
+static inline void hpfs_lock(struct super_block *s)
+{
+}
+
+static inline void hpfs_unlock(struct super_block *s)
+{
+}
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index 1ae35ba..87f1f78 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -6,7 +6,6 @@
  *  inode VFS functions
  */
 
-#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include "hpfs_fn.h"
 
@@ -267,7 +266,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
 	struct inode *inode = dentry->d_inode;
 	int error = -EINVAL;
 
-	lock_kernel();
+	hpfs_lock(inode->i_sb);
 	if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root)
 		goto out_unlock;
 	if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
@@ -290,7 +289,7 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
 	hpfs_write_inode(inode);
 
  out_unlock:
-	unlock_kernel();
+	hpfs_unlock(inode->i_sb);
 	return error;
 }
 
@@ -307,8 +306,8 @@ void hpfs_evict_inode(struct inode *inode)
 	truncate_inode_pages(&inode->i_data, 0);
 	end_writeback(inode);
 	if (!inode->i_nlink) {
-		lock_kernel();
+		hpfs_lock(inode->i_sb);
 		hpfs_remove_fnode(inode->i_sb, inode->i_ino);
-		unlock_kernel();
+		hpfs_unlock(inode->i_sb);
 	}
 }
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index f4ad9e3..d5f8c8a 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -6,7 +6,6 @@
  *  adding & removing files & directories
  */
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include "hpfs_fn.h"
 
 static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -25,7 +24,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	struct hpfs_dirent dee;
 	int err;
 	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	err = -ENOSPC;
 	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
 	if (!fnode)
@@ -103,7 +102,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	}
 	d_instantiate(dentry, result);
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return 0;
 bail3:
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
@@ -115,7 +114,7 @@ bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
 bail:
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return err;
 }
 
@@ -132,7 +131,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
 	int err;
 	if ((err = hpfs_chk_name(name, &len)))
 		return err==-ENOENT ? -EINVAL : err;
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	err = -ENOSPC;
 	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
 	if (!fnode)
@@ -195,7 +194,7 @@ static int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struc
 	}
 	d_instantiate(dentry, result);
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return 0;
 
 bail2:
@@ -205,7 +204,7 @@ bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
 bail:
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return err;
 }
 
@@ -224,7 +223,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
 	if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
 	if (!new_valid_dev(rdev))
 		return -EINVAL;
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	err = -ENOSPC;
 	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
 	if (!fnode)
@@ -274,7 +273,7 @@ static int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t
 	d_instantiate(dentry, result);
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
 	brelse(bh);
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return 0;
 bail2:
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
@@ -283,7 +282,7 @@ bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
 bail:
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return err;
 }
 
@@ -299,9 +298,9 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
 	struct inode *result;
 	int err;
 	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	if (hpfs_sb(dir->i_sb)->sb_eas < 2) {
-		unlock_kernel();
+		hpfs_unlock(dir->i_sb);
 		return -EPERM;
 	}
 	err = -ENOSPC;
@@ -354,7 +353,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
 	hpfs_write_inode_nolock(result);
 	d_instantiate(dentry, result);
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return 0;
 bail2:
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
@@ -363,7 +362,7 @@ bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
 bail:
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return err;
 }
 
@@ -380,7 +379,7 @@ static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
 	int rep = 0;
 	int err;
 
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	hpfs_adjust_length(name, &len);
 again:
 	mutex_lock(&hpfs_i(inode)->i_parent_mutex);
@@ -416,7 +415,7 @@ again:
 		dentry_unhash(dentry);
 		if (!d_unhashed(dentry)) {
 			dput(dentry);
-			unlock_kernel();
+			hpfs_unlock(dir->i_sb);
 			return -ENOSPC;
 		}
 		if (generic_permission(inode, MAY_WRITE, 0, NULL) ||
@@ -435,7 +434,7 @@ again:
 			if (!err)
 				goto again;
 		}
-		unlock_kernel();
+		hpfs_unlock(dir->i_sb);
 		return -ENOSPC;
 	default:
 		drop_nlink(inode);
@@ -448,7 +447,7 @@ out1:
 out:
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
 	mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return err;
 }
 
@@ -466,7 +465,7 @@ static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
 	int r;
 
 	hpfs_adjust_length(name, &len);
-	lock_kernel();
+	hpfs_lock(dir->i_sb);
 	mutex_lock(&hpfs_i(inode)->i_parent_mutex);
 	mutex_lock(&hpfs_i(dir)->i_mutex);
 	err = -ENOENT;
@@ -508,7 +507,7 @@ out1:
 out:
 	mutex_unlock(&hpfs_i(dir)->i_mutex);
 	mutex_unlock(&hpfs_i(inode)->i_parent_mutex);
-	unlock_kernel();
+	hpfs_unlock(dir->i_sb);
 	return err;
 }
 
@@ -521,21 +520,21 @@ static int hpfs_symlink_readpage(struct file *file, struct page *page)
 	int err;
 
 	err = -EIO;
-	lock_kernel();
+	hpfs_lock(i->i_sb);
 	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
 		goto fail;
 	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
 	brelse(bh);
 	if (err)
 		goto fail;
-	unlock_kernel();
+	hpfs_unlock(i->i_sb);
 	SetPageUptodate(page);
 	kunmap(page);
 	unlock_page(page);
 	return 0;
 
 fail:
-	unlock_kernel();
+	hpfs_unlock(i->i_sb);
 	SetPageError(page);
 	kunmap(page);
 	unlock_page(page);
@@ -567,7 +566,7 @@ static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 	err = 0;
 	hpfs_adjust_length(old_name, &old_len);
 
-	lock_kernel();
+	hpfs_lock(i->i_sb);
 	/* order doesn't matter, due to VFS exclusion */
 	mutex_lock(&hpfs_i(i)->i_parent_mutex);
 	if (new_inode)
@@ -659,7 +658,7 @@ end1:
 	mutex_unlock(&hpfs_i(i)->i_parent_mutex);
 	if (new_inode)
 		mutex_unlock(&hpfs_i(new_inode)->i_parent_mutex);
-	unlock_kernel();
+	hpfs_unlock(i->i_sb);
 	return err;
 }
 
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index b30426b..c89b408 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -13,7 +13,6 @@
 #include <linux/statfs.h>
 #include <linux/magic.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/bitmap.h>
 #include <linux/slab.h>
 
@@ -103,15 +102,11 @@ static void hpfs_put_super(struct super_block *s)
 {
 	struct hpfs_sb_info *sbi = hpfs_sb(s);
 
-	lock_kernel();
-
 	kfree(sbi->sb_cp_table);
 	kfree(sbi->sb_bmp_dir);
 	unmark_dirty(s);
 	s->s_fs_info = NULL;
 	kfree(sbi);
-
-	unlock_kernel();
 }
 
 unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
@@ -143,7 +138,7 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	struct super_block *s = dentry->d_sb;
 	struct hpfs_sb_info *sbi = hpfs_sb(s);
 	u64 id = huge_encode_dev(s->s_bdev->bd_dev);
-	lock_kernel();
+	hpfs_lock(s);
 
 	/*if (sbi->sb_n_free == -1) {*/
 		sbi->sb_n_free = count_bitmaps(s);
@@ -160,7 +155,7 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	buf->f_fsid.val[1] = (u32)(id >> 32);
 	buf->f_namelen = 254;
 
-	unlock_kernel();
+	hpfs_unlock(s);
 
 	return 0;
 }
@@ -406,7 +401,7 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 	
 	*flags |= MS_NOATIME;
 	
-	lock_kernel();
+	hpfs_lock(s);
 	lock_super(s);
 	uid = sbi->sb_uid; gid = sbi->sb_gid;
 	umask = 0777 & ~sbi->sb_mode;
@@ -441,12 +436,12 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
 	replace_mount_options(s, new_opts);
 
 	unlock_super(s);
-	unlock_kernel();
+	hpfs_unlock(s);
 	return 0;
 
 out_err:
 	unlock_super(s);
-	unlock_kernel();
+	hpfs_unlock(s);
 	kfree(new_opts);
 	return -EINVAL;
 }
@@ -484,13 +479,15 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
 	int o;
 
-	lock_kernel();
+	if (num_possible_cpus() > 1) {
+		printk(KERN_ERR "HPFS is not SMP safe\n");
+		return -EINVAL;
+	}
 
 	save_mount_options(s, options);
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi) {
-		unlock_kernel();
 		return -ENOMEM;
 	}
 	s->s_fs_info = sbi;
@@ -677,7 +674,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 			root->i_blocks = 5;
 		hpfs_brelse4(&qbh);
 	}
-	unlock_kernel();
 	return 0;
 
 bail4:	brelse(bh2);
@@ -689,7 +685,6 @@ bail0:
 	kfree(sbi->sb_cp_table);
 	s->s_fs_info = NULL;
 	kfree(sbi);
-	unlock_kernel();
 	return -EINVAL;
 }
 
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 9885082..b9eeb1c 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -332,8 +332,7 @@ static void truncate_huge_page(struct page *page)
 {
 	cancel_dirty_page(page, /* No IO accounting for huge pages? */0);
 	ClearPageUptodate(page);
-	remove_from_page_cache(page);
-	put_page(page);
+	delete_from_page_cache(page);
 }
 
 static void truncate_hugepages(struct inode *inode, loff_t lstart)
diff --git a/fs/inode.c b/fs/inode.c
index 0647d80..16fefd3 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -84,16 +84,13 @@ static struct hlist_head *inode_hashtable __read_mostly;
 DEFINE_SPINLOCK(inode_lock);
 
 /*
- * iprune_sem provides exclusion between the kswapd or try_to_free_pages
- * icache shrinking path, and the umount path.  Without this exclusion,
- * by the time prune_icache calls iput for the inode whose pages it has
- * been invalidating, or by the time it calls clear_inode & destroy_inode
- * from its final dispose_list, the struct super_block they refer to
- * (for inode->i_sb->s_op) may already have been freed and reused.
+ * iprune_sem provides exclusion between the icache shrinking and the
+ * umount path.
  *
- * We make this an rwsem because the fastpath is icache shrinking. In
- * some cases a filesystem may be doing a significant amount of work in
- * its inode reclaim code, so this should improve parallelism.
+ * We don't actually need it to protect anything in the umount path,
+ * but only need to cycle through it to make sure any inode that
+ * prune_icache took off the LRU list has been fully torn down by the
+ * time we are past evict_inodes.
  */
 static DECLARE_RWSEM(iprune_sem);
 
@@ -516,17 +513,12 @@ void evict_inodes(struct super_block *sb)
 	struct inode *inode, *next;
 	LIST_HEAD(dispose);
 
-	down_write(&iprune_sem);
-
 	spin_lock(&inode_lock);
 	list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
 		if (atomic_read(&inode->i_count))
 			continue;
-
-		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) {
-			WARN_ON(1);
+		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
 			continue;
-		}
 
 		inode->i_state |= I_FREEING;
 
@@ -542,6 +534,13 @@ void evict_inodes(struct super_block *sb)
 	spin_unlock(&inode_lock);
 
 	dispose_list(&dispose);
+
+	/*
+	 * Cycle through iprune_sem to make sure any inode that prune_icache
+	 * moved off the list before we took the lock has been fully torn
+	 * down.
+	 */
+	down_write(&iprune_sem);
 	up_write(&iprune_sem);
 }
 
@@ -561,8 +560,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
 	struct inode *inode, *next;
 	LIST_HEAD(dispose);
 
-	down_write(&iprune_sem);
-
 	spin_lock(&inode_lock);
 	list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
 		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))
@@ -590,7 +587,6 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
 	spin_unlock(&inode_lock);
 
 	dispose_list(&dispose);
-	up_write(&iprune_sem);
 
 	return busy;
 }
@@ -1719,7 +1715,7 @@ void init_special_inode(struct inode *inode, umode_t mode, dev_t rdev)
 EXPORT_SYMBOL(init_special_inode);
 
 /**
- * Init uid,gid,mode for new inode according to posix standards
+ * inode_init_owner - Init uid,gid,mode for new inode according to posix standards
  * @inode: New inode
  * @dir: Directory inode
  * @mode: mode of the new inode
diff --git a/fs/internal.h b/fs/internal.h
index 9b976b5..8318059 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -12,6 +12,7 @@
 #include <linux/lglock.h>
 
 struct super_block;
+struct file_system_type;
 struct linux_binprm;
 struct path;
 
@@ -61,10 +62,9 @@ extern int check_unsafe_exec(struct linux_binprm *);
 extern int copy_mount_options(const void __user *, unsigned long *);
 extern int copy_mount_string(const void __user *, char **);
 
-extern void free_vfsmnt(struct vfsmount *);
-extern struct vfsmount *alloc_vfsmnt(const char *);
 extern unsigned int mnt_get_count(struct vfsmount *mnt);
 extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
+extern struct vfsmount *lookup_mnt(struct path *);
 extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
 				struct vfsmount *);
 extern void release_mounts(struct list_head *);
@@ -99,6 +99,8 @@ extern struct file *get_empty_filp(void);
 extern int do_remount_sb(struct super_block *, int, void *, int);
 extern void __put_super(struct super_block *sb);
 extern void put_super(struct super_block *sb);
+extern struct dentry *mount_fs(struct file_system_type *,
+			       int, const char *, void *);
 
 /*
  * open.c
@@ -106,6 +108,19 @@ extern void put_super(struct super_block *sb);
 struct nameidata;
 extern struct file *nameidata_to_filp(struct nameidata *);
 extern void release_open_intent(struct nameidata *);
+struct open_flags {
+	int open_flag;
+	int mode;
+	int acc_mode;
+	int intent;
+};
+extern struct file *do_filp_open(int dfd, const char *pathname,
+		const struct open_flags *op, int lookup_flags);
+extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
+		const char *, const struct open_flags *, int lookup_flags);
+
+extern long do_handle_open(int mountdirfd,
+			   struct file_handle __user *ufh, int open_flag);
 
 /*
  * inode.c
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 1eebeb7..1d9b9fc 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -548,6 +548,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 {
 	int error = 0;
 	int __user *argp = (int __user *)arg;
+	struct inode *inode = filp->f_path.dentry->d_inode;
 
 	switch (cmd) {
 	case FIOCLEX:
@@ -567,13 +568,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 		break;
 
 	case FIOQSIZE:
-		if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) ||
-		    S_ISREG(filp->f_path.dentry->d_inode->i_mode) ||
-		    S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) {
-			loff_t res =
-				inode_get_bytes(filp->f_path.dentry->d_inode);
-			error = copy_to_user((loff_t __user *)arg, &res,
-					     sizeof(res)) ? -EFAULT : 0;
+		if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) ||
+		    S_ISLNK(inode->i_mode)) {
+			loff_t res = inode_get_bytes(inode);
+			error = copy_to_user(argp, &res, sizeof(res)) ?
+					-EFAULT : 0;
 		} else
 			error = -ENOTTY;
 		break;
@@ -590,14 +589,10 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
 		return ioctl_fiemap(filp, arg);
 
 	case FIGETBSZ:
-	{
-		struct inode *inode = filp->f_path.dentry->d_inode;
-		int __user *p = (int __user *)arg;
-		return put_user(inode->i_sb->s_blocksize, p);
-	}
+		return put_user(inode->i_sb->s_blocksize, argp);
 
 	default:
-		if (S_ISREG(filp->f_path.dentry->d_inode->i_mode))
+		if (S_ISREG(inode->i_mode))
 			error = file_ioctl(filp, cmd, arg);
 		else
 			error = vfs_ioctl(filp, cmd, arg);
diff --git a/fs/isofs/export.c b/fs/isofs/export.c
index ed752cb..dd4687f 100644
--- a/fs/isofs/export.c
+++ b/fs/isofs/export.c
@@ -124,9 +124,13 @@ isofs_export_encode_fh(struct dentry *dentry,
 	 * offset of the inode and the upper 16 bits of fh32[1] to
 	 * hold the offset of the parent.
 	 */
-
-	if (len < 3 || (connectable && len < 5))
+	if (connectable && (len < 5)) {
+		*max_len = 5;
+		return 255;
+	} else if (len < 3) {
+		*max_len = 3;
 		return 255;
+	}
 
 	len = 3;
 	fh32[0] = ei->i_iget5_block;
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index da1b5e4..eb11601 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -839,7 +839,7 @@ journal_t * journal_init_inode (struct inode *inode)
 	err = journal_bmap(journal, 0, &blocknr);
 	/* If that failed, give up */
 	if (err) {
-		printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
+		printk(KERN_ERR "%s: Cannot locate journal superblock\n",
 		       __func__);
 		goto out_err;
 	}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 97e7346..90407b8 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -991,7 +991,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
 	err = jbd2_journal_bmap(journal, 0, &blocknr);
 	/* If that failed, give up */
 	if (err) {
-		printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
+		printk(KERN_ERR "%s: Cannot locate journal superblock\n",
 		       __func__);
 		goto out_err;
 	}
diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
index fd05a0b..5a00102 100644
--- a/fs/jffs2/compr_zlib.c
+++ b/fs/jffs2/compr_zlib.c
@@ -40,12 +40,13 @@ static z_stream inf_strm, def_strm;
 
 static int __init alloc_workspaces(void)
 {
-	def_strm.workspace = vmalloc(zlib_deflate_workspacesize());
+	def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS,
+							MAX_MEM_LEVEL));
 	if (!def_strm.workspace) {
-		printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize());
+		printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
 		return -ENOMEM;
 	}
-	D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize()));
+	D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)));
 	inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
 	if (!inf_strm.workspace) {
 		printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize());
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 9297865..82faddd 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -215,8 +215,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
 	   no chance of AB-BA deadlock involving its f->sem). */
 	mutex_unlock(&f->sem);
 
-	ret = jffs2_do_create(c, dir_f, f, ri,
-			      dentry->d_name.name, dentry->d_name.len);
+	ret = jffs2_do_create(c, dir_f, f, ri, &dentry->d_name);
 	if (ret)
 		goto fail;
 
@@ -386,7 +385,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 
 	jffs2_complete_reservation(c);
 
-	ret = jffs2_init_security(inode, dir_i);
+	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
 	if (ret)
 		goto fail;
 
@@ -530,7 +529,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
 
 	jffs2_complete_reservation(c);
 
-	ret = jffs2_init_security(inode, dir_i);
+	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
 	if (ret)
 		goto fail;
 
@@ -703,7 +702,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de
 
 	jffs2_complete_reservation(c);
 
-	ret = jffs2_init_security(inode, dir_i);
+	ret = jffs2_init_security(inode, dir_i, &dentry->d_name);
 	if (ret)
 		goto fail;
 
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 5a53d9b..e4619b0 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -401,7 +401,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 			    struct jffs2_raw_inode *ri, unsigned char *buf,
 			    uint32_t offset, uint32_t writelen, uint32_t *retlen);
 int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
-		    struct jffs2_raw_inode *ri, const char *name, int namelen);
+		    struct jffs2_raw_inode *ri, const struct qstr *qstr);
 int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
 		    int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
 int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index 239f512..cfeb716 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -23,14 +23,15 @@
 #include "nodelist.h"
 
 /* ---- Initial Security Label Attachment -------------- */
-int jffs2_init_security(struct inode *inode, struct inode *dir)
+int jffs2_init_security(struct inode *inode, struct inode *dir,
+			const struct qstr *qstr)
 {
 	int rc;
 	size_t len;
 	void *value;
 	char *name;
 
-	rc = security_inode_init_security(inode, dir, &name, &value, &len);
+	rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
 	if (rc) {
 		if (rc == -EOPNOTSUPP)
 			return 0;
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index c819eb0..30d175b 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -424,7 +424,9 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 	return ret;
 }
 
-int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen)
+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+		    struct jffs2_inode_info *f, struct jffs2_raw_inode *ri,
+		    const struct qstr *qstr)
 {
 	struct jffs2_raw_dirent *rd;
 	struct jffs2_full_dnode *fn;
@@ -466,15 +468,15 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
 	mutex_unlock(&f->sem);
 	jffs2_complete_reservation(c);
 
-	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode);
+	ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode, qstr);
 	if (ret)
 		return ret;
 	ret = jffs2_init_acl_post(&f->vfs_inode);
 	if (ret)
 		return ret;
 
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+	ret = jffs2_reserve_space(c, sizeof(*rd)+qstr->len, &alloclen,
+				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(qstr->len));
 
 	if (ret) {
 		/* Eep. */
@@ -493,19 +495,19 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
 
 	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
 	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
-	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
+	rd->totlen = cpu_to_je32(sizeof(*rd) + qstr->len);
 	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
 
 	rd->pino = cpu_to_je32(dir_f->inocache->ino);
 	rd->version = cpu_to_je32(++dir_f->highest_version);
 	rd->ino = ri->ino;
 	rd->mctime = ri->ctime;
-	rd->nsize = namelen;
+	rd->nsize = qstr->len;
 	rd->type = DT_REG;
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
-	rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
+	rd->name_crc = cpu_to_je32(crc32(0, qstr->name, qstr->len));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, qstr->name, qstr->len, ALLOC_NORMAL);
 
 	jffs2_free_raw_dirent(rd);
 
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
index cf4f575..7be4beb 100644
--- a/fs/jffs2/xattr.h
+++ b/fs/jffs2/xattr.h
@@ -121,10 +121,11 @@ extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
 #endif /* CONFIG_JFFS2_FS_XATTR */
 
 #ifdef CONFIG_JFFS2_FS_SECURITY
-extern int jffs2_init_security(struct inode *inode, struct inode *dir);
+extern int jffs2_init_security(struct inode *inode, struct inode *dir,
+			       const struct qstr *qstr);
 extern const struct xattr_handler jffs2_security_xattr_handler;
 #else
-#define jffs2_init_security(inode,dir)	(0)
+#define jffs2_init_security(inode,dir,qstr)	(0)
 #endif /* CONFIG_JFFS2_FS_SECURITY */
 
 #endif /* _JFFS2_FS_XATTR_H_ */
diff --git a/fs/jfs/Makefile b/fs/jfs/Makefile
index 3adb639..a58fa72 100644
--- a/fs/jfs/Makefile
+++ b/fs/jfs/Makefile
@@ -13,4 +13,4 @@ jfs-y    := super.o file.o inode.o namei.o jfs_mount.o jfs_umount.o \
 
 jfs-$(CONFIG_JFS_POSIX_ACL) += acl.o
 
-EXTRA_CFLAGS += -D_JFS_4K
+ccflags-y := -D_JFS_4K
diff --git a/fs/jfs/jfs_xattr.h b/fs/jfs/jfs_xattr.h
index 88b6cc5..e9e100f 100644
--- a/fs/jfs/jfs_xattr.h
+++ b/fs/jfs/jfs_xattr.h
@@ -62,10 +62,11 @@ extern ssize_t jfs_listxattr(struct dentry *, char *, size_t);
 extern int jfs_removexattr(struct dentry *, const char *);
 
 #ifdef CONFIG_JFS_SECURITY
-extern int jfs_init_security(tid_t, struct inode *, struct inode *);
+extern int jfs_init_security(tid_t, struct inode *, struct inode *,
+			     const struct qstr *);
 #else
 static inline int jfs_init_security(tid_t tid, struct inode *inode,
-				    struct inode *dir)
+				    struct inode *dir, const struct qstr *qstr)
 {
 	return 0;
 }
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 5a2b269..eaaf2b5 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -115,7 +115,7 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
 	if (rc)
 		goto out3;
 
-	rc = jfs_init_security(tid, ip, dip);
+	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
 	if (rc) {
 		txAbort(tid, 0);
 		goto out3;
@@ -253,7 +253,7 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode)
 	if (rc)
 		goto out3;
 
-	rc = jfs_init_security(tid, ip, dip);
+	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
 	if (rc) {
 		txAbort(tid, 0);
 		goto out3;
@@ -809,9 +809,6 @@ static int jfs_link(struct dentry *old_dentry,
 	if (ip->i_nlink == JFS_LINK_MAX)
 		return -EMLINK;
 
-	if (ip->i_nlink == 0)
-		return -ENOENT;
-
 	dquot_initialize(dir);
 
 	tid = txBegin(ip->i_sb, 0);
@@ -932,7 +929,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
 	mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT);
 	mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD);
 
-	rc = jfs_init_security(tid, ip, dip);
+	rc = jfs_init_security(tid, ip, dip, &dentry->d_name);
 	if (rc)
 		goto out3;
 
@@ -1395,7 +1392,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
 	if (rc)
 		goto out3;
 
-	rc = jfs_init_security(tid, ip, dir);
+	rc = jfs_init_security(tid, ip, dir, &dentry->d_name);
 	if (rc) {
 		txAbort(tid, 0);
 		goto out3;
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 2d7f165..3fa4c32 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -1091,7 +1091,8 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
 }
 
 #ifdef CONFIG_JFS_SECURITY
-int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir)
+int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
+		      const struct qstr *qstr)
 {
 	int rc;
 	size_t len;
@@ -1099,7 +1100,8 @@ int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir)
 	char *suffix;
 	char *name;
 
-	rc = security_inode_init_security(inode, dir, &suffix, &value, &len);
+	rc = security_inode_init_security(inode, dir, qstr, &suffix, &value,
+					  &len);
 	if (rc) {
 		if (rc == -EOPNOTSUPP)
 			return 0;
diff --git a/fs/locks.c b/fs/locks.c
index 0f39982..822c3d1 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -145,7 +145,6 @@ static DEFINE_SPINLOCK(file_lock_lock);
 
 /*
  * Protects the two list heads above, plus the inode->i_flock list
- * FIXME: should use a spinlock, once lockd and ceph are ready.
  */
 void lock_flocks(void)
 {
diff --git a/fs/logfs/compr.c b/fs/logfs/compr.c
index 44bbfd2..961f02b 100644
--- a/fs/logfs/compr.c
+++ b/fs/logfs/compr.c
@@ -81,7 +81,7 @@ error:
 
 int __init logfs_compr_init(void)
 {
-	size_t size = max(zlib_deflate_workspacesize(),
+	size_t size = max(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL),
 			zlib_inflate_workspacesize());
 	stream.workspace = vmalloc(size);
 	if (!stream.workspace)
diff --git a/fs/namei.c b/fs/namei.c
index a4689eb..5a9a6c3 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -136,7 +136,7 @@ static int do_getname(const char __user *filename, char *page)
 	return retval;
 }
 
-char * getname(const char __user * filename)
+static char *getname_flags(const char __user * filename, int flags)
 {
 	char *tmp, *result;
 
@@ -147,14 +147,21 @@ char * getname(const char __user * filename)
 
 		result = tmp;
 		if (retval < 0) {
-			__putname(tmp);
-			result = ERR_PTR(retval);
+			if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
+				__putname(tmp);
+				result = ERR_PTR(retval);
+			}
 		}
 	}
 	audit_getname(result);
 	return result;
 }
 
+char *getname(const char __user * filename)
+{
+	return getname_flags(filename, 0);
+}
+
 #ifdef CONFIG_AUDITSYSCALL
 void putname(const char *name)
 {
@@ -401,9 +408,11 @@ static int nameidata_drop_rcu(struct nameidata *nd)
 {
 	struct fs_struct *fs = current->fs;
 	struct dentry *dentry = nd->path.dentry;
+	int want_root = 0;
 
 	BUG_ON(!(nd->flags & LOOKUP_RCU));
-	if (nd->root.mnt) {
+	if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
+		want_root = 1;
 		spin_lock(&fs->lock);
 		if (nd->root.mnt != fs->root.mnt ||
 				nd->root.dentry != fs->root.dentry)
@@ -414,7 +423,7 @@ static int nameidata_drop_rcu(struct nameidata *nd)
 		goto err;
 	BUG_ON(nd->inode != dentry->d_inode);
 	spin_unlock(&dentry->d_lock);
-	if (nd->root.mnt) {
+	if (want_root) {
 		path_get(&nd->root);
 		spin_unlock(&fs->lock);
 	}
@@ -427,7 +436,7 @@ static int nameidata_drop_rcu(struct nameidata *nd)
 err:
 	spin_unlock(&dentry->d_lock);
 err_root:
-	if (nd->root.mnt)
+	if (want_root)
 		spin_unlock(&fs->lock);
 	return -ECHILD;
 }
@@ -454,9 +463,11 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
 {
 	struct fs_struct *fs = current->fs;
 	struct dentry *parent = nd->path.dentry;
+	int want_root = 0;
 
 	BUG_ON(!(nd->flags & LOOKUP_RCU));
-	if (nd->root.mnt) {
+	if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
+		want_root = 1;
 		spin_lock(&fs->lock);
 		if (nd->root.mnt != fs->root.mnt ||
 				nd->root.dentry != fs->root.dentry)
@@ -476,7 +487,7 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry
 	parent->d_count++;
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&parent->d_lock);
-	if (nd->root.mnt) {
+	if (want_root) {
 		path_get(&nd->root);
 		spin_unlock(&fs->lock);
 	}
@@ -490,7 +501,7 @@ err:
 	spin_unlock(&dentry->d_lock);
 	spin_unlock(&parent->d_lock);
 err_root:
-	if (nd->root.mnt)
+	if (want_root)
 		spin_unlock(&fs->lock);
 	return -ECHILD;
 }
@@ -498,8 +509,16 @@ err_root:
 /* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing.  */
 static inline int nameidata_dentry_drop_rcu_maybe(struct nameidata *nd, struct dentry *dentry)
 {
-	if (nd->flags & LOOKUP_RCU)
-		return nameidata_dentry_drop_rcu(nd, dentry);
+	if (nd->flags & LOOKUP_RCU) {
+		if (unlikely(nameidata_dentry_drop_rcu(nd, dentry))) {
+			nd->flags &= ~LOOKUP_RCU;
+			if (!(nd->flags & LOOKUP_ROOT))
+				nd->root.mnt = NULL;
+			rcu_read_unlock();
+			br_read_unlock(vfsmount_lock);
+			return -ECHILD;
+		}
+	}
 	return 0;
 }
 
@@ -518,7 +537,8 @@ static int nameidata_drop_rcu_last(struct nameidata *nd)
 
 	BUG_ON(!(nd->flags & LOOKUP_RCU));
 	nd->flags &= ~LOOKUP_RCU;
-	nd->root.mnt = NULL;
+	if (!(nd->flags & LOOKUP_ROOT))
+		nd->root.mnt = NULL;
 	spin_lock(&dentry->d_lock);
 	if (!__d_rcu_to_refcount(dentry, nd->seq))
 		goto err_unlock;
@@ -539,14 +559,6 @@ err_unlock:
 	return -ECHILD;
 }
 
-/* Try to drop out of rcu-walk mode if we were in it, otherwise do nothing.  */
-static inline int nameidata_drop_rcu_last_maybe(struct nameidata *nd)
-{
-	if (likely(nd->flags & LOOKUP_RCU))
-		return nameidata_drop_rcu_last(nd);
-	return 0;
-}
-
 /**
  * release_open_intent - free up open intent resources
  * @nd: pointer to nameidata
@@ -590,42 +602,8 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd)
 	return dentry;
 }
 
-static inline struct dentry *
-do_revalidate_rcu(struct dentry *dentry, struct nameidata *nd)
-{
-	int status = d_revalidate(dentry, nd);
-	if (likely(status > 0))
-		return dentry;
-	if (status == -ECHILD) {
-		if (nameidata_dentry_drop_rcu(nd, dentry))
-			return ERR_PTR(-ECHILD);
-		return do_revalidate(dentry, nd);
-	}
-	if (status < 0)
-		return ERR_PTR(status);
-	/* Don't d_invalidate in rcu-walk mode */
-	if (nameidata_dentry_drop_rcu(nd, dentry))
-		return ERR_PTR(-ECHILD);
-	if (!d_invalidate(dentry)) {
-		dput(dentry);
-		dentry = NULL;
-	}
-	return dentry;
-}
-
-static inline int need_reval_dot(struct dentry *dentry)
-{
-	if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
-		return 0;
-
-	if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)))
-		return 0;
-
-	return 1;
-}
-
 /*
- * force_reval_path - force revalidation of a dentry
+ * handle_reval_path - force revalidation of a dentry
  *
  * In some situations the path walking code will trust dentries without
  * revalidating them. This causes problems for filesystems that depend on
@@ -639,27 +617,28 @@ static inline int need_reval_dot(struct dentry *dentry)
  * invalidate the dentry. It's up to the caller to handle putting references
  * to the path if necessary.
  */
-static int
-force_reval_path(struct path *path, struct nameidata *nd)
+static inline int handle_reval_path(struct nameidata *nd)
 {
+	struct dentry *dentry = nd->path.dentry;
 	int status;
-	struct dentry *dentry = path->dentry;
 
-	/*
-	 * only check on filesystems where it's possible for the dentry to
-	 * become stale.
-	 */
-	if (!need_reval_dot(dentry))
+	if (likely(!(nd->flags & LOOKUP_JUMPED)))
+		return 0;
+
+	if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE)))
+		return 0;
+
+	if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)))
 		return 0;
 
+	/* Note: we do not d_invalidate() */
 	status = d_revalidate(dentry, nd);
 	if (status > 0)
 		return 0;
 
-	if (!status) {
-		d_invalidate(dentry);
+	if (!status)
 		status = -ESTALE;
-	}
+
 	return status;
 }
 
@@ -728,6 +707,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l
 		path_put(&nd->path);
 		nd->path = nd->root;
 		path_get(&nd->root);
+		nd->flags |= LOOKUP_JUMPED;
 	}
 	nd->inode = nd->path.dentry->d_inode;
 
@@ -757,19 +737,42 @@ static inline void path_to_nameidata(const struct path *path,
 	nd->path.dentry = path->dentry;
 }
 
+static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
+{
+	struct inode *inode = link->dentry->d_inode;
+	if (!IS_ERR(cookie) && inode->i_op->put_link)
+		inode->i_op->put_link(link->dentry, nd, cookie);
+	path_put(link);
+}
+
 static __always_inline int
-__do_follow_link(const struct path *link, struct nameidata *nd, void **p)
+follow_link(struct path *link, struct nameidata *nd, void **p)
 {
 	int error;
 	struct dentry *dentry = link->dentry;
 
 	BUG_ON(nd->flags & LOOKUP_RCU);
 
+	if (link->mnt == nd->path.mnt)
+		mntget(link->mnt);
+
+	if (unlikely(current->total_link_count >= 40)) {
+		*p = ERR_PTR(-ELOOP); /* no ->put_link(), please */
+		path_put(&nd->path);
+		return -ELOOP;
+	}
+	cond_resched();
+	current->total_link_count++;
+
 	touch_atime(link->mnt, dentry);
 	nd_set_link(nd, NULL);
 
-	if (link->mnt == nd->path.mnt)
-		mntget(link->mnt);
+	error = security_inode_follow_link(link->dentry, nd);
+	if (error) {
+		*p = ERR_PTR(error); /* no ->put_link(), please */
+		path_put(&nd->path);
+		return error;
+	}
 
 	nd->last_type = LAST_BIND;
 	*p = dentry->d_inode->i_op->follow_link(dentry, nd);
@@ -780,56 +783,18 @@ __do_follow_link(const struct path *link, struct nameidata *nd, void **p)
 		if (s)
 			error = __vfs_follow_link(nd, s);
 		else if (nd->last_type == LAST_BIND) {
-			error = force_reval_path(&nd->path, nd);
-			if (error)
+			nd->flags |= LOOKUP_JUMPED;
+			nd->inode = nd->path.dentry->d_inode;
+			if (nd->inode->i_op->follow_link) {
+				/* stepped on a _really_ weird one */
 				path_put(&nd->path);
+				error = -ELOOP;
+			}
 		}
 	}
 	return error;
 }
 
-/*
- * This limits recursive symlink follows to 8, while
- * limiting consecutive symlinks to 40.
- *
- * Without that kind of total limit, nasty chains of consecutive
- * symlinks can cause almost arbitrarily long lookups. 
- */
-static inline int do_follow_link(struct inode *inode, struct path *path, struct nameidata *nd)
-{
-	void *cookie;
-	int err = -ELOOP;
-
-	/* We drop rcu-walk here */
-	if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry))
-		return -ECHILD;
-	BUG_ON(inode != path->dentry->d_inode);
-
-	if (current->link_count >= MAX_NESTED_LINKS)
-		goto loop;
-	if (current->total_link_count >= 40)
-		goto loop;
-	BUG_ON(nd->depth >= MAX_NESTED_LINKS);
-	cond_resched();
-	err = security_inode_follow_link(path->dentry, nd);
-	if (err)
-		goto loop;
-	current->link_count++;
-	current->total_link_count++;
-	nd->depth++;
-	err = __do_follow_link(path, nd, &cookie);
-	if (!IS_ERR(cookie) && path->dentry->d_inode->i_op->put_link)
-		path->dentry->d_inode->i_op->put_link(path->dentry, nd, cookie);
-	path_put(path);
-	current->link_count--;
-	nd->depth--;
-	return err;
-loop:
-	path_put_conditional(path, nd);
-	path_put(&nd->path);
-	return err;
-}
-
 static int follow_up_rcu(struct path *path)
 {
 	struct vfsmount *parent;
@@ -968,8 +933,7 @@ static int follow_managed(struct path *path, unsigned flags)
 		if (managed & DCACHE_MANAGE_TRANSIT) {
 			BUG_ON(!path->dentry->d_op);
 			BUG_ON(!path->dentry->d_op->d_manage);
-			ret = path->dentry->d_op->d_manage(path->dentry,
-							   false, false);
+			ret = path->dentry->d_op->d_manage(path->dentry, false);
 			if (ret < 0)
 				return ret == -EISDIR ? 0 : ret;
 		}
@@ -1034,7 +998,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
 		struct vfsmount *mounted;
 		if (unlikely(path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) &&
 		    !reverse_transit &&
-		    path->dentry->d_op->d_manage(path->dentry, false, true) < 0)
+		    path->dentry->d_op->d_manage(path->dentry, true) < 0)
 			return false;
 		mounted = __lookup_mnt(path->mnt, path->dentry, 1);
 		if (!mounted)
@@ -1068,7 +1032,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
 
 			seq = read_seqcount_begin(&parent->d_seq);
 			if (read_seqcount_retry(&old->d_seq, nd->seq))
-				return -ECHILD;
+				goto failed;
 			inode = parent->d_inode;
 			nd->path.dentry = parent;
 			nd->seq = seq;
@@ -1081,8 +1045,15 @@ static int follow_dotdot_rcu(struct nameidata *nd)
 	}
 	__follow_mount_rcu(nd, &nd->path, &inode, true);
 	nd->inode = inode;
-
 	return 0;
+
+failed:
+	nd->flags &= ~LOOKUP_RCU;
+	if (!(nd->flags & LOOKUP_ROOT))
+		nd->root.mnt = NULL;
+	rcu_read_unlock();
+	br_read_unlock(vfsmount_lock);
+	return -ECHILD;
 }
 
 /*
@@ -1093,7 +1064,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
  * Care must be taken as namespace_sem may be held (indicated by mounting_here
  * being true).
  */
-int follow_down(struct path *path, bool mounting_here)
+int follow_down(struct path *path)
 {
 	unsigned managed;
 	int ret;
@@ -1114,7 +1085,7 @@ int follow_down(struct path *path, bool mounting_here)
 			BUG_ON(!path->dentry->d_op);
 			BUG_ON(!path->dentry->d_op->d_manage);
 			ret = path->dentry->d_op->d_manage(
-				path->dentry, mounting_here, false);
+				path->dentry, false);
 			if (ret < 0)
 				return ret == -EISDIR ? 0 : ret;
 		}
@@ -1216,68 +1187,85 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
 {
 	struct vfsmount *mnt = nd->path.mnt;
 	struct dentry *dentry, *parent = nd->path.dentry;
-	struct inode *dir;
+	int need_reval = 1;
+	int status = 1;
 	int err;
 
 	/*
-	 * See if the low-level filesystem might want
-	 * to use its own hash..
-	 */
-	if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
-		err = parent->d_op->d_hash(parent, nd->inode, name);
-		if (err < 0)
-			return err;
-	}
-
-	/*
 	 * Rename seqlock is not required here because in the off chance
 	 * of a false negative due to a concurrent rename, we're going to
 	 * do the non-racy lookup, below.
 	 */
 	if (nd->flags & LOOKUP_RCU) {
 		unsigned seq;
-
 		*inode = nd->inode;
 		dentry = __d_lookup_rcu(parent, name, &seq, inode);
-		if (!dentry) {
-			if (nameidata_drop_rcu(nd))
-				return -ECHILD;
-			goto need_lookup;
-		}
+		if (!dentry)
+			goto unlazy;
+
 		/* Memory barrier in read_seqcount_begin of child is enough */
 		if (__read_seqcount_retry(&parent->d_seq, nd->seq))
 			return -ECHILD;
-
 		nd->seq = seq;
+
 		if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
-			dentry = do_revalidate_rcu(dentry, nd);
-			if (!dentry)
-				goto need_lookup;
-			if (IS_ERR(dentry))
-				goto fail;
-			if (!(nd->flags & LOOKUP_RCU))
-				goto done;
+			status = d_revalidate(dentry, nd);
+			if (unlikely(status <= 0)) {
+				if (status != -ECHILD)
+					need_reval = 0;
+				goto unlazy;
+			}
 		}
 		path->mnt = mnt;
 		path->dentry = dentry;
 		if (likely(__follow_mount_rcu(nd, path, inode, false)))
 			return 0;
-		if (nameidata_drop_rcu(nd))
-			return -ECHILD;
-		/* fallthru */
+unlazy:
+		if (dentry) {
+			if (nameidata_dentry_drop_rcu(nd, dentry))
+				return -ECHILD;
+		} else {
+			if (nameidata_drop_rcu(nd))
+				return -ECHILD;
+		}
+	} else {
+		dentry = __d_lookup(parent, name);
 	}
-	dentry = __d_lookup(parent, name);
-	if (!dentry)
-		goto need_lookup;
-found:
-	if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
-		dentry = do_revalidate(dentry, nd);
-		if (!dentry)
-			goto need_lookup;
-		if (IS_ERR(dentry))
-			goto fail;
+
+retry:
+	if (unlikely(!dentry)) {
+		struct inode *dir = parent->d_inode;
+		BUG_ON(nd->inode != dir);
+
+		mutex_lock(&dir->i_mutex);
+		dentry = d_lookup(parent, name);
+		if (likely(!dentry)) {
+			dentry = d_alloc_and_lookup(parent, name, nd);
+			if (IS_ERR(dentry)) {
+				mutex_unlock(&dir->i_mutex);
+				return PTR_ERR(dentry);
+			}
+			/* known good */
+			need_reval = 0;
+			status = 1;
+		}
+		mutex_unlock(&dir->i_mutex);
+	}
+	if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
+		status = d_revalidate(dentry, nd);
+	if (unlikely(status <= 0)) {
+		if (status < 0) {
+			dput(dentry);
+			return status;
+		}
+		if (!d_invalidate(dentry)) {
+			dput(dentry);
+			dentry = NULL;
+			need_reval = 1;
+			goto retry;
+		}
 	}
-done:
+
 	path->mnt = mnt;
 	path->dentry = dentry;
 	err = follow_managed(path, nd->flags);
@@ -1287,39 +1275,113 @@ done:
 	}
 	*inode = path->dentry->d_inode;
 	return 0;
+}
+
+static inline int may_lookup(struct nameidata *nd)
+{
+	if (nd->flags & LOOKUP_RCU) {
+		int err = exec_permission(nd->inode, IPERM_FLAG_RCU);
+		if (err != -ECHILD)
+			return err;
+		if (nameidata_drop_rcu(nd))
+			return -ECHILD;
+	}
+	return exec_permission(nd->inode, 0);
+}
 
-need_lookup:
-	dir = parent->d_inode;
-	BUG_ON(nd->inode != dir);
+static inline int handle_dots(struct nameidata *nd, int type)
+{
+	if (type == LAST_DOTDOT) {
+		if (nd->flags & LOOKUP_RCU) {
+			if (follow_dotdot_rcu(nd))
+				return -ECHILD;
+		} else
+			follow_dotdot(nd);
+	}
+	return 0;
+}
 
-	mutex_lock(&dir->i_mutex);
-	/*
-	 * First re-do the cached lookup just in case it was created
-	 * while we waited for the directory semaphore, or the first
-	 * lookup failed due to an unrelated rename.
-	 *
-	 * This could use version numbering or similar to avoid unnecessary
-	 * cache lookups, but then we'd have to do the first lookup in the
-	 * non-racy way. However in the common case here, everything should
-	 * be hot in cache, so would it be a big win?
-	 */
-	dentry = d_lookup(parent, name);
-	if (likely(!dentry)) {
-		dentry = d_alloc_and_lookup(parent, name, nd);
-		mutex_unlock(&dir->i_mutex);
-		if (IS_ERR(dentry))
-			goto fail;
-		goto done;
+static void terminate_walk(struct nameidata *nd)
+{
+	if (!(nd->flags & LOOKUP_RCU)) {
+		path_put(&nd->path);
+	} else {
+		nd->flags &= ~LOOKUP_RCU;
+		if (!(nd->flags & LOOKUP_ROOT))
+			nd->root.mnt = NULL;
+		rcu_read_unlock();
+		br_read_unlock(vfsmount_lock);
 	}
+}
+
+static inline int walk_component(struct nameidata *nd, struct path *path,
+		struct qstr *name, int type, int follow)
+{
+	struct inode *inode;
+	int err;
 	/*
-	 * Uhhuh! Nasty case: the cache was re-populated while
-	 * we waited on the semaphore. Need to revalidate.
+	 * "." and ".." are special - ".." especially so because it has
+	 * to be able to know about the current root directory and
+	 * parent relationships.
 	 */
-	mutex_unlock(&dir->i_mutex);
-	goto found;
+	if (unlikely(type != LAST_NORM))
+		return handle_dots(nd, type);
+	err = do_lookup(nd, name, path, &inode);
+	if (unlikely(err)) {
+		terminate_walk(nd);
+		return err;
+	}
+	if (!inode) {
+		path_to_nameidata(path, nd);
+		terminate_walk(nd);
+		return -ENOENT;
+	}
+	if (unlikely(inode->i_op->follow_link) && follow) {
+		if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry))
+			return -ECHILD;
+		BUG_ON(inode != path->dentry->d_inode);
+		return 1;
+	}
+	path_to_nameidata(path, nd);
+	nd->inode = inode;
+	return 0;
+}
 
-fail:
-	return PTR_ERR(dentry);
+/*
+ * This limits recursive symlink follows to 8, while
+ * limiting consecutive symlinks to 40.
+ *
+ * Without that kind of total limit, nasty chains of consecutive
+ * symlinks can cause almost arbitrarily long lookups.
+ */
+static inline int nested_symlink(struct path *path, struct nameidata *nd)
+{
+	int res;
+
+	BUG_ON(nd->depth >= MAX_NESTED_LINKS);
+	if (unlikely(current->link_count >= MAX_NESTED_LINKS)) {
+		path_put_conditional(path, nd);
+		path_put(&nd->path);
+		return -ELOOP;
+	}
+
+	nd->depth++;
+	current->link_count++;
+
+	do {
+		struct path link = *path;
+		void *cookie;
+
+		res = follow_link(&link, nd, &cookie);
+		if (!res)
+			res = walk_component(nd, path, &nd->last,
+					     nd->last_type, LOOKUP_FOLLOW);
+		put_link(nd, &link, cookie);
+	} while (res > 0);
+
+	current->link_count--;
+	nd->depth--;
+	return res;
 }
 
 /*
@@ -1339,30 +1401,18 @@ static int link_path_walk(const char *name, struct nameidata *nd)
 	while (*name=='/')
 		name++;
 	if (!*name)
-		goto return_reval;
-
-	if (nd->depth)
-		lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE);
+		return 0;
 
 	/* At this point we know we have a real path component. */
 	for(;;) {
-		struct inode *inode;
 		unsigned long hash;
 		struct qstr this;
 		unsigned int c;
+		int type;
 
 		nd->flags |= LOOKUP_CONTINUE;
-		if (nd->flags & LOOKUP_RCU) {
-			err = exec_permission(nd->inode, IPERM_FLAG_RCU);
-			if (err == -ECHILD) {
-				if (nameidata_drop_rcu(nd))
-					return -ECHILD;
-				goto exec_again;
-			}
-		} else {
-exec_again:
-			err = exec_permission(nd->inode, 0);
-		}
+
+		err = may_lookup(nd);
  		if (err)
 			break;
 
@@ -1378,52 +1428,43 @@ exec_again:
 		this.len = name - (const char *) this.name;
 		this.hash = end_name_hash(hash);
 
+		type = LAST_NORM;
+		if (this.name[0] == '.') switch (this.len) {
+			case 2:
+				if (this.name[1] == '.') {
+					type = LAST_DOTDOT;
+					nd->flags |= LOOKUP_JUMPED;
+				}
+				break;
+			case 1:
+				type = LAST_DOT;
+		}
+		if (likely(type == LAST_NORM)) {
+			struct dentry *parent = nd->path.dentry;
+			nd->flags &= ~LOOKUP_JUMPED;
+			if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
+				err = parent->d_op->d_hash(parent, nd->inode,
+							   &this);
+				if (err < 0)
+					break;
+			}
+		}
+
 		/* remove trailing slashes? */
 		if (!c)
 			goto last_component;
 		while (*++name == '/');
 		if (!*name)
-			goto last_with_slashes;
+			goto last_component;
 
-		/*
-		 * "." and ".." are special - ".." especially so because it has
-		 * to be able to know about the current root directory and
-		 * parent relationships.
-		 */
-		if (this.name[0] == '.') switch (this.len) {
-			default:
-				break;
-			case 2:
-				if (this.name[1] != '.')
-					break;
-				if (nd->flags & LOOKUP_RCU) {
-					if (follow_dotdot_rcu(nd))
-						return -ECHILD;
-				} else
-					follow_dotdot(nd);
-				/* fallthrough */
-			case 1:
-				continue;
-		}
-		/* This does the actual lookups.. */
-		err = do_lookup(nd, &this, &next, &inode);
-		if (err)
-			break;
-		err = -ENOENT;
-		if (!inode)
-			goto out_dput;
+		err = walk_component(nd, &next, &this, type, LOOKUP_FOLLOW);
+		if (err < 0)
+			return err;
 
-		if (inode->i_op->follow_link) {
-			err = do_follow_link(inode, &next, nd);
+		if (err) {
+			err = nested_symlink(&next, nd);
 			if (err)
-				goto return_err;
-			nd->inode = nd->path.dentry->d_inode;
-			err = -ENOENT;
-			if (!nd->inode)
-				break;
-		} else {
-			path_to_nameidata(&next, nd);
-			nd->inode = inode;
+				return err;
 		}
 		err = -ENOTDIR; 
 		if (!nd->inode->i_op->lookup)
@@ -1431,210 +1472,109 @@ exec_again:
 		continue;
 		/* here ends the main loop */
 
-last_with_slashes:
-		lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 last_component:
 		/* Clear LOOKUP_CONTINUE iff it was previously unset */
 		nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
-		if (lookup_flags & LOOKUP_PARENT)
-			goto lookup_parent;
-		if (this.name[0] == '.') switch (this.len) {
-			default:
-				break;
-			case 2:
-				if (this.name[1] != '.')
-					break;
-				if (nd->flags & LOOKUP_RCU) {
-					if (follow_dotdot_rcu(nd))
-						return -ECHILD;
-				} else
-					follow_dotdot(nd);
-				/* fallthrough */
-			case 1:
-				goto return_reval;
-		}
-		err = do_lookup(nd, &this, &next, &inode);
-		if (err)
-			break;
-		if (inode && unlikely(inode->i_op->follow_link) &&
-		    (lookup_flags & LOOKUP_FOLLOW)) {
-			err = do_follow_link(inode, &next, nd);
-			if (err)
-				goto return_err;
-			nd->inode = nd->path.dentry->d_inode;
-		} else {
-			path_to_nameidata(&next, nd);
-			nd->inode = inode;
-		}
-		err = -ENOENT;
-		if (!nd->inode)
-			break;
-		if (lookup_flags & LOOKUP_DIRECTORY) {
-			err = -ENOTDIR; 
-			if (!nd->inode->i_op->lookup)
-				break;
-		}
-		goto return_base;
-lookup_parent:
 		nd->last = this;
-		nd->last_type = LAST_NORM;
-		if (this.name[0] != '.')
-			goto return_base;
-		if (this.len == 1)
-			nd->last_type = LAST_DOT;
-		else if (this.len == 2 && this.name[1] == '.')
-			nd->last_type = LAST_DOTDOT;
-		else
-			goto return_base;
-return_reval:
-		/*
-		 * We bypassed the ordinary revalidation routines.
-		 * We may need to check the cached dentry for staleness.
-		 */
-		if (need_reval_dot(nd->path.dentry)) {
-			if (nameidata_drop_rcu_last_maybe(nd))
-				return -ECHILD;
-			/* Note: we do not d_invalidate() */
-			err = d_revalidate(nd->path.dentry, nd);
-			if (!err)
-				err = -ESTALE;
-			if (err < 0)
-				break;
-			return 0;
-		}
-return_base:
-		if (nameidata_drop_rcu_last_maybe(nd))
-			return -ECHILD;
+		nd->last_type = type;
 		return 0;
-out_dput:
-		if (!(nd->flags & LOOKUP_RCU))
-			path_put_conditional(&next, nd);
-		break;
 	}
-	if (!(nd->flags & LOOKUP_RCU))
-		path_put(&nd->path);
-return_err:
+	terminate_walk(nd);
 	return err;
 }
 
-static inline int path_walk_rcu(const char *name, struct nameidata *nd)
-{
-	current->total_link_count = 0;
-
-	return link_path_walk(name, nd);
-}
-
-static inline int path_walk_simple(const char *name, struct nameidata *nd)
-{
-	current->total_link_count = 0;
-
-	return link_path_walk(name, nd);
-}
-
-static int path_walk(const char *name, struct nameidata *nd)
-{
-	struct path save = nd->path;
-	int result;
-
-	current->total_link_count = 0;
-
-	/* make sure the stuff we saved doesn't go away */
-	path_get(&save);
-
-	result = link_path_walk(name, nd);
-	if (result == -ESTALE) {
-		/* nd->path had been dropped */
-		current->total_link_count = 0;
-		nd->path = save;
-		nd->inode = save.dentry->d_inode;
-		path_get(&nd->path);
-		nd->flags |= LOOKUP_REVAL;
-		result = link_path_walk(name, nd);
-	}
-
-	path_put(&save);
-
-	return result;
-}
-
-static void path_finish_rcu(struct nameidata *nd)
-{
-	if (nd->flags & LOOKUP_RCU) {
-		/* RCU dangling. Cancel it. */
-		nd->flags &= ~LOOKUP_RCU;
-		nd->root.mnt = NULL;
-		rcu_read_unlock();
-		br_read_unlock(vfsmount_lock);
-	}
-	if (nd->file)
-		fput(nd->file);
-}
-
-static int path_init_rcu(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
+static int path_init(int dfd, const char *name, unsigned int flags,
+		     struct nameidata *nd, struct file **fp)
 {
 	int retval = 0;
 	int fput_needed;
 	struct file *file;
 
 	nd->last_type = LAST_ROOT; /* if there are only slashes... */
-	nd->flags = flags | LOOKUP_RCU;
+	nd->flags = flags | LOOKUP_JUMPED;
 	nd->depth = 0;
+	if (flags & LOOKUP_ROOT) {
+		struct inode *inode = nd->root.dentry->d_inode;
+		if (*name) {
+			if (!inode->i_op->lookup)
+				return -ENOTDIR;
+			retval = inode_permission(inode, MAY_EXEC);
+			if (retval)
+				return retval;
+		}
+		nd->path = nd->root;
+		nd->inode = inode;
+		if (flags & LOOKUP_RCU) {
+			br_read_lock(vfsmount_lock);
+			rcu_read_lock();
+			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
+		} else {
+			path_get(&nd->path);
+		}
+		return 0;
+	}
+
 	nd->root.mnt = NULL;
-	nd->file = NULL;
 
 	if (*name=='/') {
-		struct fs_struct *fs = current->fs;
-		unsigned seq;
-
-		br_read_lock(vfsmount_lock);
-		rcu_read_lock();
-
-		do {
-			seq = read_seqcount_begin(&fs->seq);
-			nd->root = fs->root;
-			nd->path = nd->root;
-			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-		} while (read_seqcount_retry(&fs->seq, seq));
-
+		if (flags & LOOKUP_RCU) {
+			br_read_lock(vfsmount_lock);
+			rcu_read_lock();
+			set_root_rcu(nd);
+		} else {
+			set_root(nd);
+			path_get(&nd->root);
+		}
+		nd->path = nd->root;
 	} else if (dfd == AT_FDCWD) {
-		struct fs_struct *fs = current->fs;
-		unsigned seq;
-
-		br_read_lock(vfsmount_lock);
-		rcu_read_lock();
+		if (flags & LOOKUP_RCU) {
+			struct fs_struct *fs = current->fs;
+			unsigned seq;
 
-		do {
-			seq = read_seqcount_begin(&fs->seq);
-			nd->path = fs->pwd;
-			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-		} while (read_seqcount_retry(&fs->seq, seq));
+			br_read_lock(vfsmount_lock);
+			rcu_read_lock();
 
+			do {
+				seq = read_seqcount_begin(&fs->seq);
+				nd->path = fs->pwd;
+				nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
+			} while (read_seqcount_retry(&fs->seq, seq));
+		} else {
+			get_fs_pwd(current->fs, &nd->path);
+		}
 	} else {
 		struct dentry *dentry;
 
-		file = fget_light(dfd, &fput_needed);
+		file = fget_raw_light(dfd, &fput_needed);
 		retval = -EBADF;
 		if (!file)
 			goto out_fail;
 
 		dentry = file->f_path.dentry;
 
-		retval = -ENOTDIR;
-		if (!S_ISDIR(dentry->d_inode->i_mode))
-			goto fput_fail;
+		if (*name) {
+			retval = -ENOTDIR;
+			if (!S_ISDIR(dentry->d_inode->i_mode))
+				goto fput_fail;
 
-		retval = file_permission(file, MAY_EXEC);
-		if (retval)
-			goto fput_fail;
+			retval = file_permission(file, MAY_EXEC);
+			if (retval)
+				goto fput_fail;
+		}
 
 		nd->path = file->f_path;
-		if (fput_needed)
-			nd->file = file;
-
-		nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-		br_read_lock(vfsmount_lock);
-		rcu_read_lock();
+		if (flags & LOOKUP_RCU) {
+			if (fput_needed)
+				*fp = file;
+			nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
+			br_read_lock(vfsmount_lock);
+			rcu_read_lock();
+		} else {
+			path_get(&file->f_path);
+			fput_light(file, fput_needed);
+		}
 	}
+
 	nd->inode = nd->path.dentry->d_inode;
 	return 0;
 
@@ -1644,60 +1584,23 @@ out_fail:
 	return retval;
 }
 
-static int path_init(int dfd, const char *name, unsigned int flags, struct nameidata *nd)
+static inline int lookup_last(struct nameidata *nd, struct path *path)
 {
-	int retval = 0;
-	int fput_needed;
-	struct file *file;
-
-	nd->last_type = LAST_ROOT; /* if there are only slashes... */
-	nd->flags = flags;
-	nd->depth = 0;
-	nd->root.mnt = NULL;
-
-	if (*name=='/') {
-		set_root(nd);
-		nd->path = nd->root;
-		path_get(&nd->root);
-	} else if (dfd == AT_FDCWD) {
-		get_fs_pwd(current->fs, &nd->path);
-	} else {
-		struct dentry *dentry;
-
-		file = fget_light(dfd, &fput_needed);
-		retval = -EBADF;
-		if (!file)
-			goto out_fail;
-
-		dentry = file->f_path.dentry;
-
-		retval = -ENOTDIR;
-		if (!S_ISDIR(dentry->d_inode->i_mode))
-			goto fput_fail;
-
-		retval = file_permission(file, MAY_EXEC);
-		if (retval)
-			goto fput_fail;
-
-		nd->path = file->f_path;
-		path_get(&file->f_path);
-
-		fput_light(file, fput_needed);
-	}
-	nd->inode = nd->path.dentry->d_inode;
-	return 0;
+	if (nd->last_type == LAST_NORM && nd->last.name[nd->last.len])
+		nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
 
-fput_fail:
-	fput_light(file, fput_needed);
-out_fail:
-	return retval;
+	nd->flags &= ~LOOKUP_PARENT;
+	return walk_component(nd, path, &nd->last, nd->last_type,
+					nd->flags & LOOKUP_FOLLOW);
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-static int do_path_lookup(int dfd, const char *name,
+static int path_lookupat(int dfd, const char *name,
 				unsigned int flags, struct nameidata *nd)
 {
-	int retval;
+	struct file *base = NULL;
+	struct path path;
+	int err;
 
 	/*
 	 * Path walking is largely split up into 2 different synchronisation
@@ -1713,44 +1616,75 @@ static int do_path_lookup(int dfd, const char *name,
 	 * be handled by restarting a traditional ref-walk (which will always
 	 * be able to complete).
 	 */
-	retval = path_init_rcu(dfd, name, flags, nd);
-	if (unlikely(retval))
-		return retval;
-	retval = path_walk_rcu(name, nd);
-	path_finish_rcu(nd);
-	if (nd->root.mnt) {
-		path_put(&nd->root);
-		nd->root.mnt = NULL;
+	err = path_init(dfd, name, flags | LOOKUP_PARENT, nd, &base);
+
+	if (unlikely(err))
+		return err;
+
+	current->total_link_count = 0;
+	err = link_path_walk(name, nd);
+
+	if (!err && !(flags & LOOKUP_PARENT)) {
+		err = lookup_last(nd, &path);
+		while (err > 0) {
+			void *cookie;
+			struct path link = path;
+			nd->flags |= LOOKUP_PARENT;
+			err = follow_link(&link, nd, &cookie);
+			if (!err)
+				err = lookup_last(nd, &path);
+			put_link(nd, &link, cookie);
+		}
 	}
 
-	if (unlikely(retval == -ECHILD || retval == -ESTALE)) {
-		/* slower, locked walk */
-		if (retval == -ESTALE)
-			flags |= LOOKUP_REVAL;
-		retval = path_init(dfd, name, flags, nd);
-		if (unlikely(retval))
-			return retval;
-		retval = path_walk(name, nd);
-		if (nd->root.mnt) {
-			path_put(&nd->root);
-			nd->root.mnt = NULL;
+	if (nd->flags & LOOKUP_RCU) {
+		/* went all way through without dropping RCU */
+		BUG_ON(err);
+		if (nameidata_drop_rcu_last(nd))
+			err = -ECHILD;
+	}
+
+	if (!err)
+		err = handle_reval_path(nd);
+
+	if (!err && nd->flags & LOOKUP_DIRECTORY) {
+		if (!nd->inode->i_op->lookup) {
+			path_put(&nd->path);
+			return -ENOTDIR;
 		}
 	}
 
+	if (base)
+		fput(base);
+
+	if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
+		path_put(&nd->root);
+		nd->root.mnt = NULL;
+	}
+	return err;
+}
+
+static int do_path_lookup(int dfd, const char *name,
+				unsigned int flags, struct nameidata *nd)
+{
+	int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd);
+	if (unlikely(retval == -ECHILD))
+		retval = path_lookupat(dfd, name, flags, nd);
+	if (unlikely(retval == -ESTALE))
+		retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd);
+
 	if (likely(!retval)) {
 		if (unlikely(!audit_dummy_context())) {
 			if (nd->path.dentry && nd->inode)
 				audit_inode(name, nd->path.dentry);
 		}
 	}
-
 	return retval;
 }
 
-int path_lookup(const char *name, unsigned int flags,
-			struct nameidata *nd)
+int kern_path_parent(const char *name, struct nameidata *nd)
 {
-	return do_path_lookup(AT_FDCWD, name, flags, nd);
+	return do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, nd);
 }
 
 int kern_path(const char *name, unsigned int flags, struct path *path)
@@ -1774,29 +1708,10 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
 		    const char *name, unsigned int flags,
 		    struct nameidata *nd)
 {
-	int retval;
-
-	/* same as do_path_lookup */
-	nd->last_type = LAST_ROOT;
-	nd->flags = flags;
-	nd->depth = 0;
-
-	nd->path.dentry = dentry;
-	nd->path.mnt = mnt;
-	path_get(&nd->path);
-	nd->root = nd->path;
-	path_get(&nd->root);
-	nd->inode = nd->path.dentry->d_inode;
-
-	retval = path_walk(name, nd);
-	if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
-				nd->inode))
-		audit_inode(name, nd->path.dentry);
-
-	path_put(&nd->root);
-	nd->root.mnt = NULL;
-
-	return retval;
+	nd->root.dentry = dentry;
+	nd->root.mnt = mnt;
+	/* the first argument of do_path_lookup() is ignored with LOOKUP_ROOT */
+	return do_path_lookup(AT_FDCWD, name, flags | LOOKUP_ROOT, nd);
 }
 
 static struct dentry *__lookup_hash(struct qstr *name,
@@ -1811,17 +1726,6 @@ static struct dentry *__lookup_hash(struct qstr *name,
 		return ERR_PTR(err);
 
 	/*
-	 * See if the low-level filesystem might want
-	 * to use its own hash..
-	 */
-	if (base->d_flags & DCACHE_OP_HASH) {
-		err = base->d_op->d_hash(base, inode, name);
-		dentry = ERR_PTR(err);
-		if (err < 0)
-			goto out;
-	}
-
-	/*
 	 * Don't bother with __d_lookup: callers are for creat as
 	 * well as unlink, so a lot of the time it would cost
 	 * a double lookup.
@@ -1833,7 +1737,7 @@ static struct dentry *__lookup_hash(struct qstr *name,
 
 	if (!dentry)
 		dentry = d_alloc_and_lookup(base, name, nd);
-out:
+
 	return dentry;
 }
 
@@ -1847,28 +1751,6 @@ static struct dentry *lookup_hash(struct nameidata *nd)
 	return __lookup_hash(&nd->last, nd->path.dentry, nd);
 }
 
-static int __lookup_one_len(const char *name, struct qstr *this,
-		struct dentry *base, int len)
-{
-	unsigned long hash;
-	unsigned int c;
-
-	this->name = name;
-	this->len = len;
-	if (!len)
-		return -EACCES;
-
-	hash = init_name_hash();
-	while (len--) {
-		c = *(const unsigned char *)name++;
-		if (c == '/' || c == '\0')
-			return -EACCES;
-		hash = partial_name_hash(c, hash);
-	}
-	this->hash = end_name_hash(hash);
-	return 0;
-}
-
 /**
  * lookup_one_len - filesystem helper to lookup single pathname component
  * @name:	pathname component to lookup
@@ -1882,14 +1764,34 @@ static int __lookup_one_len(const char *name, struct qstr *this,
  */
 struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
 {
-	int err;
 	struct qstr this;
+	unsigned long hash;
+	unsigned int c;
 
 	WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex));
 
-	err = __lookup_one_len(name, &this, base, len);
-	if (err)
-		return ERR_PTR(err);
+	this.name = name;
+	this.len = len;
+	if (!len)
+		return ERR_PTR(-EACCES);
+
+	hash = init_name_hash();
+	while (len--) {
+		c = *(const unsigned char *)name++;
+		if (c == '/' || c == '\0')
+			return ERR_PTR(-EACCES);
+		hash = partial_name_hash(c, hash);
+	}
+	this.hash = end_name_hash(hash);
+	/*
+	 * See if the low-level filesystem might want
+	 * to use its own hash..
+	 */
+	if (base->d_flags & DCACHE_OP_HASH) {
+		int err = base->d_op->d_hash(base, base->d_inode, &this);
+		if (err < 0)
+			return ERR_PTR(err);
+	}
 
 	return __lookup_hash(&this, base, NULL);
 }
@@ -1898,7 +1800,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
 		 struct path *path)
 {
 	struct nameidata nd;
-	char *tmp = getname(name);
+	char *tmp = getname_flags(name, flags);
 	int err = PTR_ERR(tmp);
 	if (!IS_ERR(tmp)) {
 
@@ -2078,12 +1980,16 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	return error;
 }
 
-int may_open(struct path *path, int acc_mode, int flag)
+static int may_open(struct path *path, int acc_mode, int flag)
 {
 	struct dentry *dentry = path->dentry;
 	struct inode *inode = dentry->d_inode;
 	int error;
 
+	/* O_PATH? */
+	if (!acc_mode)
+		return 0;
+
 	if (!inode)
 		return -ENOENT;
 
@@ -2152,34 +2058,6 @@ static int handle_truncate(struct file *filp)
 }
 
 /*
- * Be careful about ever adding any more callers of this
- * function.  Its flags must be in the namei format, not
- * what get passed to sys_open().
- */
-static int __open_namei_create(struct nameidata *nd, struct path *path,
-				int open_flag, int mode)
-{
-	int error;
-	struct dentry *dir = nd->path.dentry;
-
-	if (!IS_POSIXACL(dir->d_inode))
-		mode &= ~current_umask();
-	error = security_path_mknod(&nd->path, path->dentry, mode, 0);
-	if (error)
-		goto out_unlock;
-	error = vfs_create(dir->d_inode, path->dentry, mode, nd);
-out_unlock:
-	mutex_unlock(&dir->d_inode->i_mutex);
-	dput(nd->path.dentry);
-	nd->path.dentry = path->dentry;
-
-	if (error)
-		return error;
-	/* Don't check for write permission, don't truncate */
-	return may_open(&nd->path, 0, open_flag & ~O_TRUNC);
-}
-
-/*
  * Note that while the flag value (low two bits) for sys_open means:
  *	00 - read-only
  *	01 - write-only
@@ -2203,126 +2081,115 @@ static inline int open_to_namei_flags(int flag)
 	return flag;
 }
 
-static int open_will_truncate(int flag, struct inode *inode)
-{
-	/*
-	 * We'll never write to the fs underlying
-	 * a device file.
-	 */
-	if (special_file(inode->i_mode))
-		return 0;
-	return (flag & O_TRUNC);
-}
-
-static struct file *finish_open(struct nameidata *nd,
-				int open_flag, int acc_mode)
-{
-	struct file *filp;
-	int will_truncate;
-	int error;
-
-	will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode);
-	if (will_truncate) {
-		error = mnt_want_write(nd->path.mnt);
-		if (error)
-			goto exit;
-	}
-	error = may_open(&nd->path, acc_mode, open_flag);
-	if (error) {
-		if (will_truncate)
-			mnt_drop_write(nd->path.mnt);
-		goto exit;
-	}
-	filp = nameidata_to_filp(nd);
-	if (!IS_ERR(filp)) {
-		error = ima_file_check(filp, acc_mode);
-		if (error) {
-			fput(filp);
-			filp = ERR_PTR(error);
-		}
-	}
-	if (!IS_ERR(filp)) {
-		if (will_truncate) {
-			error = handle_truncate(filp);
-			if (error) {
-				fput(filp);
-				filp = ERR_PTR(error);
-			}
-		}
-	}
-	/*
-	 * It is now safe to drop the mnt write
-	 * because the filp has had a write taken
-	 * on its behalf.
-	 */
-	if (will_truncate)
-		mnt_drop_write(nd->path.mnt);
-	path_put(&nd->path);
-	return filp;
-
-exit:
-	path_put(&nd->path);
-	return ERR_PTR(error);
-}
-
 /*
- * Handle O_CREAT case for do_filp_open
+ * Handle the last step of open()
  */
 static struct file *do_last(struct nameidata *nd, struct path *path,
-			    int open_flag, int acc_mode,
-			    int mode, const char *pathname)
+			    const struct open_flags *op, const char *pathname)
 {
 	struct dentry *dir = nd->path.dentry;
+	struct dentry *dentry;
+	int open_flag = op->open_flag;
+	int will_truncate = open_flag & O_TRUNC;
+	int want_write = 0;
+	int acc_mode = op->acc_mode;
 	struct file *filp;
-	int error = -EISDIR;
+	int error;
+
+	nd->flags &= ~LOOKUP_PARENT;
+	nd->flags |= op->intent;
 
 	switch (nd->last_type) {
 	case LAST_DOTDOT:
-		follow_dotdot(nd);
-		dir = nd->path.dentry;
 	case LAST_DOT:
-		if (need_reval_dot(dir)) {
-			int status = d_revalidate(nd->path.dentry, nd);
-			if (!status)
-				status = -ESTALE;
-			if (status < 0) {
-				error = status;
-				goto exit;
-			}
-		}
+		error = handle_dots(nd, nd->last_type);
+		if (error)
+			return ERR_PTR(error);
 		/* fallthrough */
 	case LAST_ROOT:
-		goto exit;
+		if (nd->flags & LOOKUP_RCU) {
+			if (nameidata_drop_rcu_last(nd))
+				return ERR_PTR(-ECHILD);
+		}
+		error = handle_reval_path(nd);
+		if (error)
+			goto exit;
+		audit_inode(pathname, nd->path.dentry);
+		if (open_flag & O_CREAT) {
+			error = -EISDIR;
+			goto exit;
+		}
+		goto ok;
 	case LAST_BIND:
+		/* can't be RCU mode here */
+		error = handle_reval_path(nd);
+		if (error)
+			goto exit;
 		audit_inode(pathname, dir);
 		goto ok;
 	}
 
+	if (!(open_flag & O_CREAT)) {
+		int symlink_ok = 0;
+		if (nd->last.name[nd->last.len])
+			nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
+		if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
+			symlink_ok = 1;
+		/* we _can_ be in RCU mode here */
+		error = walk_component(nd, path, &nd->last, LAST_NORM,
+					!symlink_ok);
+		if (error < 0)
+			return ERR_PTR(error);
+		if (error) /* symlink */
+			return NULL;
+		/* sayonara */
+		if (nd->flags & LOOKUP_RCU) {
+			if (nameidata_drop_rcu_last(nd))
+				return ERR_PTR(-ECHILD);
+		}
+
+		error = -ENOTDIR;
+		if (nd->flags & LOOKUP_DIRECTORY) {
+			if (!nd->inode->i_op->lookup)
+				goto exit;
+		}
+		audit_inode(pathname, nd->path.dentry);
+		goto ok;
+	}
+
+	/* create side of things */
+
+	if (nd->flags & LOOKUP_RCU) {
+		if (nameidata_drop_rcu_last(nd))
+			return ERR_PTR(-ECHILD);
+	}
+
+	audit_inode(pathname, dir);
+	error = -EISDIR;
 	/* trailing slashes? */
 	if (nd->last.name[nd->last.len])
 		goto exit;
 
 	mutex_lock(&dir->d_inode->i_mutex);
 
-	path->dentry = lookup_hash(nd);
-	path->mnt = nd->path.mnt;
-
-	error = PTR_ERR(path->dentry);
-	if (IS_ERR(path->dentry)) {
+	dentry = lookup_hash(nd);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry)) {
 		mutex_unlock(&dir->d_inode->i_mutex);
 		goto exit;
 	}
 
-	if (IS_ERR(nd->intent.open.file)) {
-		error = PTR_ERR(nd->intent.open.file);
-		goto exit_mutex_unlock;
-	}
+	path->dentry = dentry;
+	path->mnt = nd->path.mnt;
 
 	/* Negative dentry, just create the file */
-	if (!path->dentry->d_inode) {
+	if (!dentry->d_inode) {
+		int mode = op->mode;
+		if (!IS_POSIXACL(dir->d_inode))
+			mode &= ~current_umask();
 		/*
 		 * This write is needed to ensure that a
-		 * ro->rw transition does not occur between
+		 * rw->ro transition does not occur between
 		 * the time when the file is created and when
 		 * a permanent write count is taken through
 		 * the 'struct file' in nameidata_to_filp().
@@ -2330,22 +2197,21 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
 		error = mnt_want_write(nd->path.mnt);
 		if (error)
 			goto exit_mutex_unlock;
-		error = __open_namei_create(nd, path, open_flag, mode);
-		if (error) {
-			mnt_drop_write(nd->path.mnt);
-			goto exit;
-		}
-		filp = nameidata_to_filp(nd);
-		mnt_drop_write(nd->path.mnt);
-		path_put(&nd->path);
-		if (!IS_ERR(filp)) {
-			error = ima_file_check(filp, acc_mode);
-			if (error) {
-				fput(filp);
-				filp = ERR_PTR(error);
-			}
-		}
-		return filp;
+		want_write = 1;
+		/* Don't check for write permission, don't truncate */
+		open_flag &= ~O_TRUNC;
+		will_truncate = 0;
+		acc_mode = MAY_OPEN;
+		error = security_path_mknod(&nd->path, dentry, mode, 0);
+		if (error)
+			goto exit_mutex_unlock;
+		error = vfs_create(dir->d_inode, dentry, mode, nd);
+		if (error)
+			goto exit_mutex_unlock;
+		mutex_unlock(&dir->d_inode->i_mutex);
+		dput(nd->path.dentry);
+		nd->path.dentry = dentry;
+		goto common;
 	}
 
 	/*
@@ -2375,7 +2241,40 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
 	if (S_ISDIR(nd->inode->i_mode))
 		goto exit;
 ok:
-	filp = finish_open(nd, open_flag, acc_mode);
+	if (!S_ISREG(nd->inode->i_mode))
+		will_truncate = 0;
+
+	if (will_truncate) {
+		error = mnt_want_write(nd->path.mnt);
+		if (error)
+			goto exit;
+		want_write = 1;
+	}
+common:
+	error = may_open(&nd->path, acc_mode, open_flag);
+	if (error)
+		goto exit;
+	filp = nameidata_to_filp(nd);
+	if (!IS_ERR(filp)) {
+		error = ima_file_check(filp, op->acc_mode);
+		if (error) {
+			fput(filp);
+			filp = ERR_PTR(error);
+		}
+	}
+	if (!IS_ERR(filp)) {
+		if (will_truncate) {
+			error = handle_truncate(filp);
+			if (error) {
+				fput(filp);
+				filp = ERR_PTR(error);
+			}
+		}
+	}
+out:
+	if (want_write)
+		mnt_drop_write(nd->path.mnt);
+	path_put(&nd->path);
 	return filp;
 
 exit_mutex_unlock:
@@ -2383,204 +2282,103 @@ exit_mutex_unlock:
 exit_dput:
 	path_put_conditional(path, nd);
 exit:
-	path_put(&nd->path);
-	return ERR_PTR(error);
+	filp = ERR_PTR(error);
+	goto out;
 }
 
-/*
- * Note that the low bits of the passed in "open_flag"
- * are not the same as in the local variable "flag". See
- * open_to_namei_flags() for more details.
- */
-struct file *do_filp_open(int dfd, const char *pathname,
-		int open_flag, int mode, int acc_mode)
+static struct file *path_openat(int dfd, const char *pathname,
+		struct nameidata *nd, const struct open_flags *op, int flags)
 {
+	struct file *base = NULL;
 	struct file *filp;
-	struct nameidata nd;
-	int error;
 	struct path path;
-	int count = 0;
-	int flag = open_to_namei_flags(open_flag);
-	int flags;
-
-	if (!(open_flag & O_CREAT))
-		mode = 0;
-
-	/* Must never be set by userspace */
-	open_flag &= ~FMODE_NONOTIFY;
-
-	/*
-	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
-	 * check for O_DSYNC if the need any syncing at all we enforce it's
-	 * always set instead of having to deal with possibly weird behaviour
-	 * for malicious applications setting only __O_SYNC.
-	 */
-	if (open_flag & __O_SYNC)
-		open_flag |= O_DSYNC;
-
-	if (!acc_mode)
-		acc_mode = MAY_OPEN | ACC_MODE(open_flag);
-
-	/* O_TRUNC implies we need access checks for write permissions */
-	if (open_flag & O_TRUNC)
-		acc_mode |= MAY_WRITE;
-
-	/* Allow the LSM permission hook to distinguish append 
-	   access from general write access. */
-	if (open_flag & O_APPEND)
-		acc_mode |= MAY_APPEND;
-
-	flags = LOOKUP_OPEN;
-	if (open_flag & O_CREAT) {
-		flags |= LOOKUP_CREATE;
-		if (open_flag & O_EXCL)
-			flags |= LOOKUP_EXCL;
-	}
-	if (open_flag & O_DIRECTORY)
-		flags |= LOOKUP_DIRECTORY;
-	if (!(open_flag & O_NOFOLLOW))
-		flags |= LOOKUP_FOLLOW;
+	int error;
 
 	filp = get_empty_filp();
 	if (!filp)
 		return ERR_PTR(-ENFILE);
 
-	filp->f_flags = open_flag;
-	nd.intent.open.file = filp;
-	nd.intent.open.flags = flag;
-	nd.intent.open.create_mode = mode;
-
-	if (open_flag & O_CREAT)
-		goto creat;
+	filp->f_flags = op->open_flag;
+	nd->intent.open.file = filp;
+	nd->intent.open.flags = open_to_namei_flags(op->open_flag);
+	nd->intent.open.create_mode = op->mode;
 
-	/* !O_CREAT, simple open */
-	error = do_path_lookup(dfd, pathname, flags, &nd);
+	error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
 	if (unlikely(error))
-		goto out_filp2;
-	error = -ELOOP;
-	if (!(nd.flags & LOOKUP_FOLLOW)) {
-		if (nd.inode->i_op->follow_link)
-			goto out_path2;
-	}
-	error = -ENOTDIR;
-	if (nd.flags & LOOKUP_DIRECTORY) {
-		if (!nd.inode->i_op->lookup)
-			goto out_path2;
-	}
-	audit_inode(pathname, nd.path.dentry);
-	filp = finish_open(&nd, open_flag, acc_mode);
-out2:
-	release_open_intent(&nd);
-	return filp;
-
-out_path2:
-	path_put(&nd.path);
-out_filp2:
-	filp = ERR_PTR(error);
-	goto out2;
-
-creat:
-	/* OK, have to create the file. Find the parent. */
-	error = path_init_rcu(dfd, pathname,
-			LOOKUP_PARENT | (flags & LOOKUP_REVAL), &nd);
-	if (error)
 		goto out_filp;
-	error = path_walk_rcu(pathname, &nd);
-	path_finish_rcu(&nd);
-	if (unlikely(error == -ECHILD || error == -ESTALE)) {
-		/* slower, locked walk */
-		if (error == -ESTALE) {
-reval:
-			flags |= LOOKUP_REVAL;
-		}
-		error = path_init(dfd, pathname,
-				LOOKUP_PARENT | (flags & LOOKUP_REVAL), &nd);
-		if (error)
-			goto out_filp;
 
-		error = path_walk_simple(pathname, &nd);
-	}
+	current->total_link_count = 0;
+	error = link_path_walk(pathname, nd);
 	if (unlikely(error))
 		goto out_filp;
-	if (unlikely(!audit_dummy_context()))
-		audit_inode(pathname, nd.path.dentry);
 
-	/*
-	 * We have the parent and last component.
-	 */
-	nd.flags = flags;
-	filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
+	filp = do_last(nd, &path, op, pathname);
 	while (unlikely(!filp)) { /* trailing symlink */
 		struct path link = path;
-		struct inode *linki = link.dentry->d_inode;
 		void *cookie;
-		error = -ELOOP;
-		if (!(nd.flags & LOOKUP_FOLLOW))
-			goto exit_dput;
-		if (count++ == 32)
-			goto exit_dput;
-		/*
-		 * This is subtle. Instead of calling do_follow_link() we do
-		 * the thing by hands. The reason is that this way we have zero
-		 * link_count and path_walk() (called from ->follow_link)
-		 * honoring LOOKUP_PARENT.  After that we have the parent and
-		 * last component, i.e. we are in the same situation as after
-		 * the first path_walk().  Well, almost - if the last component
-		 * is normal we get its copy stored in nd->last.name and we will
-		 * have to putname() it when we are done. Procfs-like symlinks
-		 * just set LAST_BIND.
-		 */
-		nd.flags |= LOOKUP_PARENT;
-		error = security_inode_follow_link(link.dentry, &nd);
-		if (error)
-			goto exit_dput;
-		error = __do_follow_link(&link, &nd, &cookie);
-		if (unlikely(error)) {
-			if (!IS_ERR(cookie) && linki->i_op->put_link)
-				linki->i_op->put_link(link.dentry, &nd, cookie);
-			/* nd.path had been dropped */
-			nd.path = link;
-			goto out_path;
+		if (!(nd->flags & LOOKUP_FOLLOW)) {
+			path_put_conditional(&path, nd);
+			path_put(&nd->path);
+			filp = ERR_PTR(-ELOOP);
+			break;
 		}
-		nd.flags &= ~LOOKUP_PARENT;
-		filp = do_last(&nd, &path, open_flag, acc_mode, mode, pathname);
-		if (linki->i_op->put_link)
-			linki->i_op->put_link(link.dentry, &nd, cookie);
-		path_put(&link);
+		nd->flags |= LOOKUP_PARENT;
+		nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
+		error = follow_link(&link, nd, &cookie);
+		if (unlikely(error))
+			filp = ERR_PTR(error);
+		else
+			filp = do_last(nd, &path, op, pathname);
+		put_link(nd, &link, cookie);
 	}
 out:
-	if (nd.root.mnt)
-		path_put(&nd.root);
-	if (filp == ERR_PTR(-ESTALE) && !(flags & LOOKUP_REVAL))
-		goto reval;
-	release_open_intent(&nd);
+	if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))
+		path_put(&nd->root);
+	if (base)
+		fput(base);
+	release_open_intent(nd);
 	return filp;
 
-exit_dput:
-	path_put_conditional(&path, &nd);
-out_path:
-	path_put(&nd.path);
 out_filp:
 	filp = ERR_PTR(error);
 	goto out;
 }
 
-/**
- * filp_open - open file and return file pointer
- *
- * @filename:	path to open
- * @flags:	open flags as per the open(2) second argument
- * @mode:	mode for the new file if O_CREAT is set, else ignored
- *
- * This is the helper to open a file from kernelspace if you really
- * have to.  But in generally you should not do this, so please move
- * along, nothing to see here..
- */
-struct file *filp_open(const char *filename, int flags, int mode)
+struct file *do_filp_open(int dfd, const char *pathname,
+		const struct open_flags *op, int flags)
+{
+	struct nameidata nd;
+	struct file *filp;
+
+	filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
+	if (unlikely(filp == ERR_PTR(-ECHILD)))
+		filp = path_openat(dfd, pathname, &nd, op, flags);
+	if (unlikely(filp == ERR_PTR(-ESTALE)))
+		filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_REVAL);
+	return filp;
+}
+
+struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
+		const char *name, const struct open_flags *op, int flags)
 {
-	return do_filp_open(AT_FDCWD, filename, flags, mode, 0);
+	struct nameidata nd;
+	struct file *file;
+
+	nd.root.mnt = mnt;
+	nd.root.dentry = dentry;
+
+	flags |= LOOKUP_ROOT;
+
+	if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
+		return ERR_PTR(-ELOOP);
+
+	file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
+	if (unlikely(file == ERR_PTR(-ECHILD)))
+		file = path_openat(-1, name, &nd, op, flags);
+	if (unlikely(file == ERR_PTR(-ESTALE)))
+		file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
+	return file;
 }
-EXPORT_SYMBOL(filp_open);
 
 /**
  * lookup_create - lookup a dentry, creating it if it doesn't exist
@@ -3119,7 +2917,11 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
 		return error;
 
 	mutex_lock(&inode->i_mutex);
-	error = dir->i_op->link(old_dentry, dir, new_dentry);
+	/* Make sure we don't allow creating hardlink to an unlinked file */
+	if (inode->i_nlink == 0)
+		error =  -ENOENT;
+	else
+		error = dir->i_op->link(old_dentry, dir, new_dentry);
 	mutex_unlock(&inode->i_mutex);
 	if (!error)
 		fsnotify_link(dir, inode, new_dentry);
@@ -3141,15 +2943,27 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
 	struct dentry *new_dentry;
 	struct nameidata nd;
 	struct path old_path;
+	int how = 0;
 	int error;
 	char *to;
 
-	if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
+	if ((flags & ~(AT_SYMLINK_FOLLOW | AT_EMPTY_PATH)) != 0)
 		return -EINVAL;
+	/*
+	 * To use null names we require CAP_DAC_READ_SEARCH
+	 * This ensures that not everyone will be able to create
+	 * handlink using the passed filedescriptor.
+	 */
+	if (flags & AT_EMPTY_PATH) {
+		if (!capable(CAP_DAC_READ_SEARCH))
+			return -ENOENT;
+		how = LOOKUP_EMPTY;
+	}
+
+	if (flags & AT_SYMLINK_FOLLOW)
+		how |= LOOKUP_FOLLOW;
 
-	error = user_path_at(olddfd, oldname,
-			     flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
-			     &old_path);
+	error = user_path_at(olddfd, oldname, how, &old_path);
 	if (error)
 		return error;
 
@@ -3586,7 +3400,7 @@ EXPORT_SYMBOL(page_readlink);
 EXPORT_SYMBOL(__page_symlink);
 EXPORT_SYMBOL(page_symlink);
 EXPORT_SYMBOL(page_symlink_inode_operations);
-EXPORT_SYMBOL(path_lookup);
+EXPORT_SYMBOL(kern_path_parent);
 EXPORT_SYMBOL(kern_path);
 EXPORT_SYMBOL(vfs_path_lookup);
 EXPORT_SYMBOL(inode_permission);
diff --git a/fs/namespace.c b/fs/namespace.c
index d1edf26..7dba2ed 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -196,7 +196,7 @@ unsigned int mnt_get_count(struct vfsmount *mnt)
 #endif
 }
 
-struct vfsmount *alloc_vfsmnt(const char *name)
+static struct vfsmount *alloc_vfsmnt(const char *name)
 {
 	struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
 	if (mnt) {
@@ -466,15 +466,7 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt)
 	br_write_unlock(vfsmount_lock);
 }
 
-void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
-{
-	mnt->mnt_sb = sb;
-	mnt->mnt_root = dget(sb->s_root);
-}
-
-EXPORT_SYMBOL(simple_set_mnt);
-
-void free_vfsmnt(struct vfsmount *mnt)
+static void free_vfsmnt(struct vfsmount *mnt)
 {
 	kfree(mnt->mnt_devname);
 	mnt_free_id(mnt);
@@ -678,6 +670,36 @@ static struct vfsmount *skip_mnt_tree(struct vfsmount *p)
 	return p;
 }
 
+struct vfsmount *
+vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
+{
+	struct vfsmount *mnt;
+	struct dentry *root;
+
+	if (!type)
+		return ERR_PTR(-ENODEV);
+
+	mnt = alloc_vfsmnt(name);
+	if (!mnt)
+		return ERR_PTR(-ENOMEM);
+
+	if (flags & MS_KERNMOUNT)
+		mnt->mnt_flags = MNT_INTERNAL;
+
+	root = mount_fs(type, flags, name, data);
+	if (IS_ERR(root)) {
+		free_vfsmnt(mnt);
+		return ERR_CAST(root);
+	}
+
+	mnt->mnt_root = root;
+	mnt->mnt_sb = root->d_sb;
+	mnt->mnt_mountpoint = mnt->mnt_root;
+	mnt->mnt_parent = mnt;
+	return mnt;
+}
+EXPORT_SYMBOL_GPL(vfs_kern_mount);
+
 static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
 					int flag)
 {
@@ -978,7 +1000,13 @@ static int show_vfsmnt(struct seq_file *m, void *v)
 	int err = 0;
 	struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
 
-	mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+	if (mnt->mnt_sb->s_op->show_devname) {
+		err = mnt->mnt_sb->s_op->show_devname(m, mnt);
+		if (err)
+			goto out;
+	} else {
+		mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+	}
 	seq_putc(m, ' ');
 	seq_path(m, &mnt_path, " \t\n\\");
 	seq_putc(m, ' ');
@@ -1002,6 +1030,18 @@ const struct seq_operations mounts_op = {
 	.show	= show_vfsmnt
 };
 
+static int uuid_is_nil(u8 *uuid)
+{
+	int i;
+	u8  *cp = (u8 *)uuid;
+
+	for (i = 0; i < 16; i++) {
+		if (*cp++)
+			return 0;
+	}
+	return 1;
+}
+
 static int show_mountinfo(struct seq_file *m, void *v)
 {
 	struct proc_mounts *p = m->private;
@@ -1013,7 +1053,12 @@ static int show_mountinfo(struct seq_file *m, void *v)
 
 	seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id,
 		   MAJOR(sb->s_dev), MINOR(sb->s_dev));
-	seq_dentry(m, mnt->mnt_root, " \t\n\\");
+	if (sb->s_op->show_path)
+		err = sb->s_op->show_path(m, mnt);
+	else
+		seq_dentry(m, mnt->mnt_root, " \t\n\\");
+	if (err)
+		goto out;
 	seq_putc(m, ' ');
 	seq_path_root(m, &mnt_path, &root, " \t\n\\");
 	if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) {
@@ -1040,11 +1085,20 @@ static int show_mountinfo(struct seq_file *m, void *v)
 	if (IS_MNT_UNBINDABLE(mnt))
 		seq_puts(m, " unbindable");
 
+	if (!uuid_is_nil(mnt->mnt_sb->s_uuid))
+		/* print the uuid */
+		seq_printf(m, " uuid:%pU", mnt->mnt_sb->s_uuid);
+
 	/* Filesystem specific data */
 	seq_puts(m, " - ");
 	show_type(m, sb);
 	seq_putc(m, ' ');
-	mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+	if (sb->s_op->show_devname)
+		err = sb->s_op->show_devname(m, mnt);
+	else
+		mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
+	if (err)
+		goto out;
 	seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
 	err = show_sb_opts(m, sb);
 	if (err)
@@ -1070,11 +1124,15 @@ static int show_vfsstat(struct seq_file *m, void *v)
 	int err = 0;
 
 	/* device */
-	if (mnt->mnt_devname) {
-		seq_puts(m, "device ");
-		mangle(m, mnt->mnt_devname);
-	} else
-		seq_puts(m, "no device");
+	if (mnt->mnt_sb->s_op->show_devname) {
+		err = mnt->mnt_sb->s_op->show_devname(m, mnt);
+	} else {
+		if (mnt->mnt_devname) {
+			seq_puts(m, "device ");
+			mangle(m, mnt->mnt_devname);
+		} else
+			seq_puts(m, "no device");
+	}
 
 	/* mount point */
 	seq_puts(m, " mounted on ");
@@ -1088,7 +1146,8 @@ static int show_vfsstat(struct seq_file *m, void *v)
 	/* optional statistics */
 	if (mnt->mnt_sb->s_op->show_stats) {
 		seq_putc(m, ' ');
-		err = mnt->mnt_sb->s_op->show_stats(m, mnt);
+		if (!err)
+			err = mnt->mnt_sb->s_op->show_stats(m, mnt);
 	}
 
 	seq_putc(m, '\n');
@@ -1604,9 +1663,35 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt,
 	return err;
 }
 
+static int lock_mount(struct path *path)
+{
+	struct vfsmount *mnt;
+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;
+	}
+	down_write(&namespace_sem);
+	mnt = lookup_mnt(path);
+	if (likely(!mnt))
+		return 0;
+	up_write(&namespace_sem);
+	mutex_unlock(&path->dentry->d_inode->i_mutex);
+	path_put(path);
+	path->mnt = mnt;
+	path->dentry = dget(mnt->mnt_root);
+	goto retry;
+}
+
+static void unlock_mount(struct path *path)
+{
+	up_write(&namespace_sem);
+	mutex_unlock(&path->dentry->d_inode->i_mutex);
+}
+
 static int graft_tree(struct vfsmount *mnt, struct path *path)
 {
-	int err;
 	if (mnt->mnt_sb->s_flags & MS_NOUSER)
 		return -EINVAL;
 
@@ -1614,16 +1699,10 @@ static int graft_tree(struct vfsmount *mnt, struct path *path)
 	      S_ISDIR(mnt->mnt_root->d_inode->i_mode))
 		return -ENOTDIR;
 
-	err = -ENOENT;
-	mutex_lock(&path->dentry->d_inode->i_mutex);
-	if (cant_mount(path->dentry))
-		goto out_unlock;
+	if (d_unlinked(path->dentry))
+		return -ENOENT;
 
-	if (!d_unlinked(path->dentry))
-		err = attach_recursive_mnt(mnt, path, NULL);
-out_unlock:
-	mutex_unlock(&path->dentry->d_inode->i_mutex);
-	return err;
+	return attach_recursive_mnt(mnt, path, NULL);
 }
 
 /*
@@ -1686,6 +1765,7 @@ static int do_change_type(struct path *path, int flag)
 static int do_loopback(struct path *path, char *old_name,
 				int recurse)
 {
+	LIST_HEAD(umount_list);
 	struct path old_path;
 	struct vfsmount *mnt = NULL;
 	int err = mount_is_safe(path);
@@ -1697,13 +1777,16 @@ static int do_loopback(struct path *path, char *old_name,
 	if (err)
 		return err;
 
-	down_write(&namespace_sem);
+	err = lock_mount(path);
+	if (err)
+		goto out;
+
 	err = -EINVAL;
 	if (IS_MNT_UNBINDABLE(old_path.mnt))
-		goto out;
+		goto out2;
 
 	if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt))
-		goto out;
+		goto out2;
 
 	err = -ENOMEM;
 	if (recurse)
@@ -1712,20 +1795,18 @@ static int do_loopback(struct path *path, char *old_name,
 		mnt = clone_mnt(old_path.mnt, old_path.dentry, 0);
 
 	if (!mnt)
-		goto out;
+		goto out2;
 
 	err = graft_tree(mnt, path);
 	if (err) {
-		LIST_HEAD(umount_list);
-
 		br_write_lock(vfsmount_lock);
 		umount_tree(mnt, 0, &umount_list);
 		br_write_unlock(vfsmount_lock);
-		release_mounts(&umount_list);
 	}
-
+out2:
+	unlock_mount(path);
+	release_mounts(&umount_list);
 out:
-	up_write(&namespace_sem);
 	path_put(&old_path);
 	return err;
 }
@@ -1767,6 +1848,10 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
 	if (path->dentry != path->mnt->mnt_root)
 		return -EINVAL;
 
+	err = security_sb_remount(sb, data);
+	if (err)
+		return err;
+
 	down_write(&sb->s_umount);
 	if (flags & MS_BIND)
 		err = change_mount_flags(path->mnt, flags);
@@ -1810,18 +1895,12 @@ static int do_move_mount(struct path *path, char *old_name)
 	if (err)
 		return err;
 
-	down_write(&namespace_sem);
-	err = follow_down(path, true);
+	err = lock_mount(path);
 	if (err < 0)
 		goto out;
 
 	err = -EINVAL;
 	if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt))
-		goto out;
-
-	err = -ENOENT;
-	mutex_lock(&path->dentry->d_inode->i_mutex);
-	if (cant_mount(path->dentry))
 		goto out1;
 
 	if (d_unlinked(path->dentry))
@@ -1863,16 +1942,87 @@ static int do_move_mount(struct path *path, char *old_name)
 	 * automatically */
 	list_del_init(&old_path.mnt->mnt_expire);
 out1:
-	mutex_unlock(&path->dentry->d_inode->i_mutex);
+	unlock_mount(path);
 out:
-	up_write(&namespace_sem);
 	if (!err)
 		path_put(&parent_path);
 	path_put(&old_path);
 	return err;
 }
 
-static int do_add_mount(struct vfsmount *, struct path *, int);
+static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
+{
+	int err;
+	const char *subtype = strchr(fstype, '.');
+	if (subtype) {
+		subtype++;
+		err = -EINVAL;
+		if (!subtype[0])
+			goto err;
+	} else
+		subtype = "";
+
+	mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
+	err = -ENOMEM;
+	if (!mnt->mnt_sb->s_subtype)
+		goto err;
+	return mnt;
+
+ err:
+	mntput(mnt);
+	return ERR_PTR(err);
+}
+
+struct vfsmount *
+do_kern_mount(const char *fstype, int flags, const char *name, void *data)
+{
+	struct file_system_type *type = get_fs_type(fstype);
+	struct vfsmount *mnt;
+	if (!type)
+		return ERR_PTR(-ENODEV);
+	mnt = vfs_kern_mount(type, flags, name, data);
+	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
+	    !mnt->mnt_sb->s_subtype)
+		mnt = fs_set_subtype(mnt, fstype);
+	put_filesystem(type);
+	return mnt;
+}
+EXPORT_SYMBOL_GPL(do_kern_mount);
+
+/*
+ * add a mount into a namespace's mount tree
+ */
+static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
+{
+	int err;
+
+	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
+
+	err = lock_mount(path);
+	if (err)
+		return err;
+
+	err = -EINVAL;
+	if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
+		goto unlock;
+
+	/* Refuse the same filesystem on the same mount point */
+	err = -EBUSY;
+	if (path->mnt->mnt_sb == newmnt->mnt_sb &&
+	    path->mnt->mnt_root == path->dentry)
+		goto unlock;
+
+	err = -EINVAL;
+	if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
+		goto unlock;
+
+	newmnt->mnt_flags = mnt_flags;
+	err = graft_tree(newmnt, path);
+
+unlock:
+	unlock_mount(path);
+	return err;
+}
 
 /*
  * create a new mount for userspace and request it to be added into the
@@ -1932,43 +2082,6 @@ fail:
 	return err;
 }
 
-/*
- * add a mount into a namespace's mount tree
- */
-static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags)
-{
-	int err;
-
-	mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL);
-
-	down_write(&namespace_sem);
-	/* Something was mounted here while we slept */
-	err = follow_down(path, true);
-	if (err < 0)
-		goto unlock;
-
-	err = -EINVAL;
-	if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
-		goto unlock;
-
-	/* Refuse the same filesystem on the same mount point */
-	err = -EBUSY;
-	if (path->mnt->mnt_sb == newmnt->mnt_sb &&
-	    path->mnt->mnt_root == path->dentry)
-		goto unlock;
-
-	err = -EINVAL;
-	if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
-		goto unlock;
-
-	newmnt->mnt_flags = mnt_flags;
-	err = graft_tree(newmnt, path);
-
-unlock:
-	up_write(&namespace_sem);
-	return err;
-}
-
 /**
  * mnt_set_expiry - Put a mount on an expiration list
  * @mnt: The mount to list.
@@ -2469,65 +2582,60 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	error = user_path_dir(new_root, &new);
 	if (error)
 		goto out0;
-	error = -EINVAL;
-	if (!check_mnt(new.mnt))
-		goto out1;
 
 	error = user_path_dir(put_old, &old);
 	if (error)
 		goto out1;
 
 	error = security_sb_pivotroot(&old, &new);
-	if (error) {
-		path_put(&old);
-		goto out1;
-	}
+	if (error)
+		goto out2;
 
 	get_fs_root(current->fs, &root);
-	down_write(&namespace_sem);
-	mutex_lock(&old.dentry->d_inode->i_mutex);
+	error = lock_mount(&old);
+	if (error)
+		goto out3;
+
 	error = -EINVAL;
 	if (IS_MNT_SHARED(old.mnt) ||
 		IS_MNT_SHARED(new.mnt->mnt_parent) ||
 		IS_MNT_SHARED(root.mnt->mnt_parent))
-		goto out2;
-	if (!check_mnt(root.mnt))
-		goto out2;
+		goto out4;
+	if (!check_mnt(root.mnt) || !check_mnt(new.mnt))
+		goto out4;
 	error = -ENOENT;
-	if (cant_mount(old.dentry))
-		goto out2;
 	if (d_unlinked(new.dentry))
-		goto out2;
+		goto out4;
 	if (d_unlinked(old.dentry))
-		goto out2;
+		goto out4;
 	error = -EBUSY;
 	if (new.mnt == root.mnt ||
 	    old.mnt == root.mnt)
-		goto out2; /* loop, on the same file system  */
+		goto out4; /* loop, on the same file system  */
 	error = -EINVAL;
 	if (root.mnt->mnt_root != root.dentry)
-		goto out2; /* not a mountpoint */
+		goto out4; /* not a mountpoint */
 	if (root.mnt->mnt_parent == root.mnt)
-		goto out2; /* not attached */
+		goto out4; /* not attached */
 	if (new.mnt->mnt_root != new.dentry)
-		goto out2; /* not a mountpoint */
+		goto out4; /* not a mountpoint */
 	if (new.mnt->mnt_parent == new.mnt)
-		goto out2; /* not attached */
+		goto out4; /* not attached */
 	/* make sure we can reach put_old from new_root */
 	tmp = old.mnt;
-	br_write_lock(vfsmount_lock);
 	if (tmp != new.mnt) {
 		for (;;) {
 			if (tmp->mnt_parent == tmp)
-				goto out3; /* already mounted on put_old */
+				goto out4; /* already mounted on put_old */
 			if (tmp->mnt_parent == new.mnt)
 				break;
 			tmp = tmp->mnt_parent;
 		}
 		if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
-			goto out3;
+			goto out4;
 	} else if (!is_subdir(old.dentry, new.dentry))
-		goto out3;
+		goto out4;
+	br_write_lock(vfsmount_lock);
 	detach_mnt(new.mnt, &parent_path);
 	detach_mnt(root.mnt, &root_parent);
 	/* mount old root on put_old */
@@ -2537,22 +2645,21 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
 	br_write_unlock(vfsmount_lock);
 	chroot_fs_refs(&root, &new);
-
 	error = 0;
-	path_put(&root_parent);
-	path_put(&parent_path);
-out2:
-	mutex_unlock(&old.dentry->d_inode->i_mutex);
-	up_write(&namespace_sem);
+out4:
+	unlock_mount(&old);
+	if (!error) {
+		path_put(&root_parent);
+		path_put(&parent_path);
+	}
+out3:
 	path_put(&root);
+out2:
 	path_put(&old);
 out1:
 	path_put(&new);
 out0:
 	return error;
-out3:
-	br_write_unlock(vfsmount_lock);
-	goto out2;
 }
 
 static void __init init_mount_tree(void)
@@ -2594,7 +2701,7 @@ void __init mnt_init(void)
 	if (!mount_hashtable)
 		panic("Failed to allocate mount hash table\n");
 
-	printk("Mount-cache hash table entries: %lu\n", HASH_SIZE);
+	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]);
@@ -2627,3 +2734,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
 	kfree(ns);
 }
 EXPORT_SYMBOL(put_mnt_ns);
+
+struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
+{
+	return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
+}
+EXPORT_SYMBOL_GPL(kern_mount_data);
diff --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile
index 68ea095..c66af56 100644
--- a/fs/ncpfs/Makefile
+++ b/fs/ncpfs/Makefile
@@ -11,6 +11,6 @@ ncpfs-$(CONFIG_NCPFS_EXTRAS)   += symlink.o
 ncpfs-$(CONFIG_NCPFS_NFS_NS)   += symlink.o
 
 # If you want debugging output, please uncomment the following line
-# EXTRA_CFLAGS += -DDEBUG_NCP=1
+# ccflags-y := -DDEBUG_NCP=1
 
 CFLAGS_ncplib_kernel.o := -finline-functions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index 8958757..2f41dcce 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -188,10 +188,10 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
 			rv = NFS4ERR_DELAY;
 		list_del_init(&lo->plh_bulk_recall);
 		spin_unlock(&ino->i_lock);
+		pnfs_free_lseg_list(&free_me_list);
 		put_layout_hdr(lo);
 		iput(ino);
 	}
-	pnfs_free_lseg_list(&free_me_list);
 	return rv;
 }
 
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bd3ca32..139be96 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -82,6 +82,11 @@ retry:
 #endif /* CONFIG_NFS_V4 */
 
 /*
+ * Turn off NFSv4 uid/gid mapping when using AUTH_SYS
+ */
+static int nfs4_disable_idmapping = 0;
+
+/*
  * RPC cruft for NFS
  */
 static struct rpc_version *nfs_version[5] = {
@@ -481,7 +486,12 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
  * Look up a client by IP address and protocol version
  * - creates a new record if one doesn't yet exist
  */
-static struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
+static struct nfs_client *
+nfs_get_client(const struct nfs_client_initdata *cl_init,
+	       const struct rpc_timeout *timeparms,
+	       const char *ip_addr,
+	       rpc_authflavor_t authflavour,
+	       int noresvport)
 {
 	struct nfs_client *clp, *new = NULL;
 	int error;
@@ -512,6 +522,13 @@ install_client:
 	clp = new;
 	list_add(&clp->cl_share_link, &nfs_client_list);
 	spin_unlock(&nfs_client_lock);
+
+	error = cl_init->rpc_ops->init_client(clp, timeparms, ip_addr,
+					      authflavour, noresvport);
+	if (error < 0) {
+		nfs_put_client(clp);
+		return ERR_PTR(error);
+	}
 	dprintk("--> nfs_get_client() = %p [new]\n", clp);
 	return clp;
 
@@ -767,9 +784,9 @@ static int nfs_init_server_rpcclient(struct nfs_server *server,
 /*
  * Initialise an NFS2 or NFS3 client
  */
-static int nfs_init_client(struct nfs_client *clp,
-			   const struct rpc_timeout *timeparms,
-			   const struct nfs_parsed_mount_data *data)
+int nfs_init_client(struct nfs_client *clp, const struct rpc_timeout *timeparms,
+		    const char *ip_addr, rpc_authflavor_t authflavour,
+		    int noresvport)
 {
 	int error;
 
@@ -784,7 +801,7 @@ static int nfs_init_client(struct nfs_client *clp,
 	 * - RFC 2623, sec 2.3.2
 	 */
 	error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX,
-				      0, data->flags & NFS_MOUNT_NORESVPORT);
+				      0, noresvport);
 	if (error < 0)
 		goto error;
 	nfs_mark_client_ready(clp, NFS_CS_READY);
@@ -820,19 +837,17 @@ static int nfs_init_server(struct nfs_server *server,
 		cl_init.rpc_ops = &nfs_v3_clientops;
 #endif
 
+	nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
+			data->timeo, data->retrans);
+
 	/* Allocate or find a client reference we can use */
-	clp = nfs_get_client(&cl_init);
+	clp = nfs_get_client(&cl_init, &timeparms, NULL, RPC_AUTH_UNIX,
+			     data->flags & NFS_MOUNT_NORESVPORT);
 	if (IS_ERR(clp)) {
 		dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
 		return PTR_ERR(clp);
 	}
 
-	nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
-			data->timeo, data->retrans);
-	error = nfs_init_client(clp, &timeparms, data);
-	if (error < 0)
-		goto error;
-
 	server->nfs_client = clp;
 
 	/* Initialise the client representation from the mount data */
@@ -1009,14 +1024,19 @@ static void nfs_server_insert_lists(struct nfs_server *server)
 	spin_lock(&nfs_client_lock);
 	list_add_tail_rcu(&server->client_link, &clp->cl_superblocks);
 	list_add_tail(&server->master_link, &nfs_volume_list);
+	clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
 	spin_unlock(&nfs_client_lock);
 
 }
 
 static void nfs_server_remove_lists(struct nfs_server *server)
 {
+	struct nfs_client *clp = server->nfs_client;
+
 	spin_lock(&nfs_client_lock);
 	list_del_rcu(&server->client_link);
+	if (clp && list_empty(&clp->cl_superblocks))
+		set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
 	list_del(&server->master_link);
 	spin_unlock(&nfs_client_lock);
 
@@ -1307,11 +1327,11 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp)
 /*
  * Initialise an NFS4 client record
  */
-static int nfs4_init_client(struct nfs_client *clp,
-		const struct rpc_timeout *timeparms,
-		const char *ip_addr,
-		rpc_authflavor_t authflavour,
-		int flags)
+int nfs4_init_client(struct nfs_client *clp,
+		     const struct rpc_timeout *timeparms,
+		     const char *ip_addr,
+		     rpc_authflavor_t authflavour,
+		     int noresvport)
 {
 	int error;
 
@@ -1325,7 +1345,7 @@ static int nfs4_init_client(struct nfs_client *clp,
 	clp->rpc_ops = &nfs_v4_clientops;
 
 	error = nfs_create_rpc_client(clp, timeparms, authflavour,
-				      1, flags & NFS_MOUNT_NORESVPORT);
+				      1, noresvport);
 	if (error < 0)
 		goto error;
 	strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
@@ -1378,27 +1398,71 @@ static int nfs4_set_client(struct nfs_server *server,
 	dprintk("--> nfs4_set_client()\n");
 
 	/* Allocate or find a client reference we can use */
-	clp = nfs_get_client(&cl_init);
+	clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour,
+			     server->flags & NFS_MOUNT_NORESVPORT);
 	if (IS_ERR(clp)) {
 		error = PTR_ERR(clp);
 		goto error;
 	}
-	error = nfs4_init_client(clp, timeparms, ip_addr, authflavour,
-					server->flags);
-	if (error < 0)
-		goto error_put;
+
+	/*
+	 * Query for the lease time on clientid setup or renewal
+	 *
+	 * Note that this will be set on nfs_clients that were created
+	 * only for the DS role and did not set this bit, but now will
+	 * serve a dual role.
+	 */
+	set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
 
 	server->nfs_client = clp;
 	dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
 	return 0;
-
-error_put:
-	nfs_put_client(clp);
 error:
 	dprintk("<-- nfs4_set_client() = xerror %d\n", error);
 	return error;
 }
 
+/*
+ * Set up a pNFS Data Server client.
+ *
+ * Return any existing nfs_client that matches server address,port,version
+ * and minorversion.
+ *
+ * For a new nfs_client, use a soft mount (default), a low retrans and a
+ * low timeout interval so that if a connection is lost, we retry through
+ * the MDS.
+ */
+struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+		const struct sockaddr *ds_addr,
+		int ds_addrlen, int ds_proto)
+{
+	struct nfs_client_initdata cl_init = {
+		.addr = ds_addr,
+		.addrlen = ds_addrlen,
+		.rpc_ops = &nfs_v4_clientops,
+		.proto = ds_proto,
+		.minorversion = mds_clp->cl_minorversion,
+	};
+	struct rpc_timeout ds_timeout = {
+		.to_initval = 15 * HZ,
+		.to_maxval = 15 * HZ,
+		.to_retries = 1,
+		.to_exponential = 1,
+	};
+	struct nfs_client *clp;
+
+	/*
+	 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
+	 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
+	 * (section 13.1 RFC 5661).
+	 */
+	clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr,
+			     mds_clp->cl_rpcclient->cl_auth->au_flavor, 0);
+
+	dprintk("<-- %s %p\n", __func__, clp);
+	return clp;
+}
+EXPORT_SYMBOL(nfs4_set_ds_client);
 
 /*
  * Session has been established, and the client marked ready.
@@ -1435,6 +1499,10 @@ static int nfs4_server_common_setup(struct nfs_server *server,
 	BUG_ON(!server->nfs_client->rpc_ops);
 	BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops);
 
+	/* data servers support only a subset of NFSv4.1 */
+	if (is_ds_only_client(server->nfs_client))
+		return -EPROTONOSUPPORT;
+
 	fattr = nfs_alloc_fattr();
 	if (fattr == NULL)
 		return -ENOMEM;
@@ -1504,6 +1572,13 @@ 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)
@@ -1921,3 +1996,7 @@ void nfs_fs_proc_exit(void)
 }
 
 #endif /* CONFIG_PROC_FS */
+
+module_param(nfs4_disable_idmapping, bool, 0644);
+MODULE_PARM_DESC(nfs4_disable_idmapping,
+		"Turn off NFSv4 idmapping when using 'sec=sys'");
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 2c3eb33..abdf38d 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1169,11 +1169,23 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 	iput(inode);
 }
 
+static void nfs_d_release(struct dentry *dentry)
+{
+	/* free cached devname value, if it survived that far */
+	if (unlikely(dentry->d_fsdata)) {
+		if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
+			WARN_ON(1);
+		else
+			kfree(dentry->d_fsdata);
+	}
+}
+
 const struct dentry_operations nfs_dentry_operations = {
 	.d_revalidate	= nfs_lookup_revalidate,
 	.d_delete	= nfs_dentry_delete,
 	.d_iput		= nfs_dentry_iput,
 	.d_automount	= nfs_d_automount,
+	.d_release	= nfs_d_release,
 };
 
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
@@ -1248,6 +1260,7 @@ const struct dentry_operations nfs4_dentry_operations = {
 	.d_delete	= nfs_dentry_delete,
 	.d_iput		= nfs_dentry_iput,
 	.d_automount	= nfs_d_automount,
+	.d_release	= nfs_d_release,
 };
 
 /*
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 9943a75..8eea253 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -45,6 +45,7 @@
 #include <linux/pagemap.h>
 #include <linux/kref.h>
 #include <linux/slab.h>
+#include <linux/task_io_accounting_ops.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
@@ -649,8 +650,7 @@ static void nfs_direct_write_result(struct rpc_task *task, void *calldata)
 {
 	struct nfs_write_data *data = calldata;
 
-	if (nfs_writeback_done(task, data) != 0)
-		return;
+	nfs_writeback_done(task, data);
 }
 
 /*
@@ -938,6 +938,8 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov,
 	if (retval)
 		goto out;
 
+	task_io_account_read(count);
+
 	retval = nfs_direct_read(iocb, iov, nr_segs, pos);
 	if (retval > 0)
 		iocb->ki_pos = pos + retval;
@@ -999,6 +1001,8 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
 	if (retval)
 		goto out;
 
+	task_io_account_write(count);
+
 	retval = nfs_direct_write(iocb, iov, nr_segs, pos, count);
 
 	if (retval > 0)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 7bf029e..d85a534 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -387,10 +387,6 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
 		file->f_path.dentry->d_name.name,
 		mapping->host->i_ino, len, (long long) pos);
 
-	pnfs_update_layout(mapping->host,
-			   nfs_file_open_context(file),
-			   IOMODE_RW);
-
 start:
 	/*
 	 * Prevent starvation issues if someone is doing a consistency
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c
index b5ffe8f..1084792 100644
--- a/fs/nfs/getroot.c
+++ b/fs/nfs/getroot.c
@@ -75,18 +75,25 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
 /*
  * get an NFS2/NFS3 root dentry from the root filehandle
  */
-struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+			    const char *devname)
 {
 	struct nfs_server *server = NFS_SB(sb);
 	struct nfs_fsinfo fsinfo;
 	struct dentry *ret;
 	struct inode *inode;
+	void *name = kstrdup(devname, GFP_KERNEL);
 	int error;
 
+	if (!name)
+		return ERR_PTR(-ENOMEM);
+
 	/* get the actual root for this mount */
 	fsinfo.fattr = nfs_alloc_fattr();
-	if (fsinfo.fattr == NULL)
+	if (fsinfo.fattr == NULL) {
+		kfree(name);
 		return ERR_PTR(-ENOMEM);
+	}
 
 	error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo);
 	if (error < 0) {
@@ -119,7 +126,15 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	}
 
 	security_d_instantiate(ret, inode);
+	spin_lock(&ret->d_lock);
+	if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+		ret->d_fsdata = name;
+		name = NULL;
+	}
+	spin_unlock(&ret->d_lock);
 out:
+	if (name)
+		kfree(name);
 	nfs_free_fattr(fsinfo.fattr);
 	return ret;
 }
@@ -169,27 +184,35 @@ out:
 /*
  * get an NFS4 root dentry from the root filehandle
  */
-struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
+struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh,
+			     const char *devname)
 {
 	struct nfs_server *server = NFS_SB(sb);
 	struct nfs_fattr *fattr = NULL;
 	struct dentry *ret;
 	struct inode *inode;
+	void *name = kstrdup(devname, GFP_KERNEL);
 	int error;
 
 	dprintk("--> nfs4_get_root()\n");
 
+	if (!name)
+		return ERR_PTR(-ENOMEM);
+
 	/* get the info about the server and filesystem */
 	error = nfs4_server_capabilities(server, mntfh);
 	if (error < 0) {
 		dprintk("nfs_get_root: getcaps error = %d\n",
 			-error);
+		kfree(name);
 		return ERR_PTR(error);
 	}
 
 	fattr = nfs_alloc_fattr();
-	if (fattr == NULL)
-		return ERR_PTR(-ENOMEM);;
+	if (fattr == NULL) {
+		kfree(name);
+		return ERR_PTR(-ENOMEM);
+	}
 
 	/* get the actual root for this mount */
 	error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr);
@@ -223,8 +246,15 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh)
 	}
 
 	security_d_instantiate(ret, inode);
-
+	spin_lock(&ret->d_lock);
+	if (IS_ROOT(ret) && !(ret->d_flags & DCACHE_NFSFS_RENAMED)) {
+		ret->d_fsdata = name;
+		name = NULL;
+	}
+	spin_unlock(&ret->d_lock);
 out:
+	if (name)
+		kfree(name);
 	nfs_free_fattr(fattr);
 	dprintk("<-- nfs4_get_root()\n");
 	return ret;
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 1869688..79664a1 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -33,16 +33,41 @@
  *  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/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res)
+{
+	unsigned long val;
+	char buf[16];
+
+	if (memchr(name, '@', namelen) != NULL || namelen >= sizeof(buf))
+		return 0;
+	memcpy(buf, name, namelen);
+	buf[namelen] = '\0';
+	if (strict_strtoul(buf, 0, &val) != 0)
+		return 0;
+	*res = val;
+	return 1;
+}
+
+static int nfs_map_numeric_to_string(__u32 id, char *buf, size_t buflen)
+{
+	return snprintf(buf, buflen, "%u", id);
+}
 
 #ifdef CONFIG_NFS_USE_NEW_IDMAPPER
 
 #include <linux/slab.h>
 #include <linux/cred.h>
+#include <linux/sunrpc/sched.h>
+#include <linux/nfs4.h>
+#include <linux/nfs_fs_sb.h>
 #include <linux/nfs_idmap.h>
 #include <linux/keyctl.h>
 #include <linux/key-type.h>
 #include <linux/rcupdate.h>
-#include <linux/kernel.h>
 #include <linux/err.h>
 
 #include <keys/user-type.h>
@@ -219,23 +244,39 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen,
 	return ret;
 }
 
-int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
 {
+	if (nfs_map_string_to_numeric(name, namelen, uid))
+		return 0;
 	return nfs_idmap_lookup_id(name, namelen, "uid", uid);
 }
 
-int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *gid)
+int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *gid)
 {
+	if (nfs_map_string_to_numeric(name, namelen, gid))
+		return 0;
 	return nfs_idmap_lookup_id(name, namelen, "gid", gid);
 }
 
-int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
+int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
 {
-	return nfs_idmap_lookup_name(uid, "user", buf, buflen);
+	int ret = -EINVAL;
+
+	if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
+		ret = nfs_idmap_lookup_name(uid, "user", buf, buflen);
+	if (ret < 0)
+		ret = nfs_map_numeric_to_string(uid, buf, buflen);
+	return ret;
 }
-int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t buflen)
+int nfs_map_gid_to_group(const struct nfs_server *server, __u32 gid, char *buf, size_t buflen)
 {
-	return nfs_idmap_lookup_name(gid, "group", buf, buflen);
+	int ret = -EINVAL;
+
+	if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
+		ret = nfs_idmap_lookup_name(gid, "group", buf, buflen);
+	if (ret < 0)
+		ret = nfs_map_numeric_to_string(gid, buf, buflen);
+	return ret;
 }
 
 #else  /* CONFIG_NFS_USE_NEW_IDMAPPER not defined */
@@ -243,7 +284,6 @@ int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t bu
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
-#include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/in.h>
@@ -695,31 +735,45 @@ static unsigned int fnvhash32(const void *buf, size_t buflen)
 	return hash;
 }
 
-int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
 {
-	struct idmap *idmap = clp->cl_idmap;
+	struct idmap *idmap = server->nfs_client->cl_idmap;
 
+	if (nfs_map_string_to_numeric(name, namelen, uid))
+		return 0;
 	return nfs_idmap_id(idmap, &idmap->idmap_user_hash, name, namelen, uid);
 }
 
-int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid)
+int nfs_map_group_to_gid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid)
 {
-	struct idmap *idmap = clp->cl_idmap;
+	struct idmap *idmap = server->nfs_client->cl_idmap;
 
+	if (nfs_map_string_to_numeric(name, namelen, uid))
+		return 0;
 	return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid);
 }
 
-int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
+int nfs_map_uid_to_name(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
 {
-	struct idmap *idmap = clp->cl_idmap;
+	struct idmap *idmap = server->nfs_client->cl_idmap;
+	int ret = -EINVAL;
 
-	return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
+	if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
+		ret = nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
+	if (ret < 0)
+		ret = nfs_map_numeric_to_string(uid, buf, buflen);
+	return ret;
 }
-int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
+int nfs_map_gid_to_group(const struct nfs_server *server, __u32 uid, char *buf, size_t buflen)
 {
-	struct idmap *idmap = clp->cl_idmap;
+	struct idmap *idmap = server->nfs_client->cl_idmap;
+	int ret = -EINVAL;
 
-	return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
+	if (!(server->caps & NFS_CAP_UIDGID_NOMAP))
+		ret = nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
+	if (ret < 0)
+		ret = nfs_map_numeric_to_string(uid, buf, buflen);
+	return ret;
 }
 
 #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 2f8e618..01768e5 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1518,7 +1518,7 @@ static int nfsiod_start(void)
 {
 	struct workqueue_struct *wq;
 	dprintk("RPC:       creating workqueue nfsiod\n");
-	wq = alloc_workqueue("nfsiod", WQ_RESCUER, 0);
+	wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM, 0);
 	if (wq == NULL)
 		return -ENOMEM;
 	nfsiod_workqueue = wq;
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index cf9fdbd..72e0bdd 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -148,6 +148,9 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *,
 					   struct nfs_fattr *);
 extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
 extern int nfs4_check_client_ready(struct nfs_client *clp);
+extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
+					     const struct sockaddr *ds_addr,
+					     int ds_addrlen, int ds_proto);
 #ifdef CONFIG_PROC_FS
 extern int __init nfs_fs_proc_init(void);
 extern void nfs_fs_proc_exit(void);
@@ -163,10 +166,10 @@ static inline void nfs_fs_proc_exit(void)
 
 /* nfs4namespace.c */
 #ifdef CONFIG_NFS_V4
-extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
+extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
 #else
 static inline
-struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct dentry *dentry)
 {
 	return ERR_PTR(-ENOENT);
 }
@@ -213,8 +216,14 @@ extern const u32 nfs41_maxwrite_overhead;
 extern struct rpc_procinfo nfs4_procedures[];
 #endif
 
+extern int nfs4_init_ds_session(struct nfs_client *clp);
+
 /* proc.c */
 void nfs_close_context(struct nfs_open_context *ctx, int is_sync);
+extern int nfs_init_client(struct nfs_client *clp,
+			   const struct rpc_timeout *timeparms,
+			   const char *ip_addr, rpc_authflavor_t authflavour,
+			   int noresvport);
 
 /* dir.c */
 extern int nfs_access_cache_shrinker(struct shrinker *shrink,
@@ -247,24 +256,30 @@ extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
 
 /* namespace.c */
-extern char *nfs_path(const char *base,
-		      const struct dentry *droot,
-		      const struct dentry *dentry,
+extern char *nfs_path(char **p, struct dentry *dentry,
 		      char *buffer, ssize_t buflen);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 
 /* getroot.c */
-extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *);
+extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *,
+				   const char *);
 #ifdef CONFIG_NFS_V4
-extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *);
+extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
+				    const char *);
 
 extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh);
 #endif
 
 /* read.c */
+extern int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt,
+			     const struct rpc_call_ops *call_ops);
 extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
 
 /* write.c */
+extern int nfs_initiate_write(struct nfs_write_data *data,
+			      struct rpc_clnt *clnt,
+			      const struct rpc_call_ops *call_ops,
+			      int how);
 extern void nfs_write_prepare(struct rpc_task *task, void *calldata);
 #ifdef CONFIG_MIGRATION
 extern int nfs_migrate_page(struct address_space *,
@@ -274,6 +289,13 @@ extern int nfs_migrate_page(struct address_space *,
 #endif
 
 /* nfs4proc.c */
+extern void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data);
+extern int nfs4_init_client(struct nfs_client *clp,
+			    const struct rpc_timeout *timeparms,
+			    const char *ip_addr,
+			    rpc_authflavor_t authflavour,
+			    int noresvport);
+extern void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data);
 extern int _nfs4_call_sync(struct nfs_server *server,
 			   struct rpc_message *msg,
 			   struct nfs4_sequence_args *args,
@@ -288,12 +310,11 @@ extern int _nfs4_call_sync_session(struct nfs_server *server,
 /*
  * Determine the device name as a string
  */
-static inline char *nfs_devname(const struct vfsmount *mnt_parent,
-				const struct dentry *dentry,
+static inline char *nfs_devname(struct dentry *dentry,
 				char *buffer, ssize_t buflen)
 {
-	return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root,
-			dentry, buffer, buflen);
+	char *dummy;
+	return nfs_path(&dummy, dentry, buffer, buflen);
 }
 
 /*
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index f32b860..bf1c680 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -25,33 +25,30 @@ static LIST_HEAD(nfs_automount_list);
 static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
-static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-					const struct dentry *dentry,
+static struct vfsmount *nfs_do_submount(struct dentry *dentry,
 					struct nfs_fh *fh,
 					struct nfs_fattr *fattr);
 
 /*
  * nfs_path - reconstruct the path given an arbitrary dentry
- * @base - arbitrary string to prepend to the path
- * @droot - pointer to root dentry for mountpoint
+ * @base - used to return pointer to the end of devname part of path
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
  *
- * Helper function for constructing the path from the
- * root dentry to an arbitrary hashed dentry.
+ * Helper function for constructing the server pathname
+ * by arbitrary hashed dentry.
  *
  * This is mainly for use in figuring out the path on the
- * server side when automounting on top of an existing partition.
+ * server side when automounting on top of an existing partition
+ * and in generating /proc/mounts and friends.
  */
-char *nfs_path(const char *base,
-	       const struct dentry *droot,
-	       const struct dentry *dentry,
-	       char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
 {
 	char *end;
 	int namelen;
 	unsigned seq;
+	const char *base;
 
 rename_retry:
 	end = buffer+buflen;
@@ -60,7 +57,10 @@ rename_retry:
 
 	seq = read_seqbegin(&rename_lock);
 	rcu_read_lock();
-	while (!IS_ROOT(dentry) && dentry != droot) {
+	while (1) {
+		spin_lock(&dentry->d_lock);
+		if (IS_ROOT(dentry))
+			break;
 		namelen = dentry->d_name.len;
 		buflen -= namelen + 1;
 		if (buflen < 0)
@@ -68,27 +68,47 @@ rename_retry:
 		end -= namelen;
 		memcpy(end, dentry->d_name.name, namelen);
 		*--end = '/';
+		spin_unlock(&dentry->d_lock);
 		dentry = dentry->d_parent;
 	}
-	rcu_read_unlock();
-	if (read_seqretry(&rename_lock, seq))
+	if (read_seqretry(&rename_lock, seq)) {
+		spin_unlock(&dentry->d_lock);
+		rcu_read_unlock();
 		goto rename_retry;
+	}
 	if (*end != '/') {
-		if (--buflen < 0)
+		if (--buflen < 0) {
+			spin_unlock(&dentry->d_lock);
+			rcu_read_unlock();
 			goto Elong;
+		}
 		*--end = '/';
 	}
+	*p = end;
+	base = dentry->d_fsdata;
+	if (!base) {
+		spin_unlock(&dentry->d_lock);
+		rcu_read_unlock();
+		WARN_ON(1);
+		return end;
+	}
 	namelen = strlen(base);
 	/* Strip off excess slashes in base string */
 	while (namelen > 0 && base[namelen - 1] == '/')
 		namelen--;
 	buflen -= namelen;
-	if (buflen < 0)
+	if (buflen < 0) {
+		spin_unlock(&dentry->d_lock);
+		rcu_read_unlock();
 		goto Elong;
+	}
 	end -= namelen;
 	memcpy(end, base, namelen);
+	spin_unlock(&dentry->d_lock);
+	rcu_read_unlock();
 	return end;
 Elong_unlock:
+	spin_unlock(&dentry->d_lock);
 	rcu_read_unlock();
 	if (read_seqretry(&rename_lock, seq))
 		goto rename_retry;
@@ -143,9 +163,9 @@ struct vfsmount *nfs_d_automount(struct path *path)
 	}
 
 	if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
-		mnt = nfs_do_refmount(path->mnt, path->dentry);
+		mnt = nfs_do_refmount(path->dentry);
 	else
-		mnt = nfs_do_submount(path->mnt, path->dentry, fh, fattr);
+		mnt = nfs_do_submount(path->dentry, fh, fattr);
 	if (IS_ERR(mnt))
 		goto out;
 
@@ -209,19 +229,17 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
 
 /**
  * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
- * @mnt_parent - mountpoint of parent directory
  * @dentry - parent directory
  * @fh - filehandle for new root dentry
  * @fattr - attributes for new root inode
  *
  */
-static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-					const struct dentry *dentry,
+static struct vfsmount *nfs_do_submount(struct dentry *dentry,
 					struct nfs_fh *fh,
 					struct nfs_fattr *fattr)
 {
 	struct nfs_clone_mount mountdata = {
-		.sb = mnt_parent->mnt_sb,
+		.sb = dentry->d_sb,
 		.dentry = dentry,
 		.fh = fh,
 		.fattr = fattr,
@@ -237,11 +255,11 @@ static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
 			dentry->d_name.name);
 	if (page == NULL)
 		goto out;
-	devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
+	devname = nfs_devname(dentry, page, PAGE_SIZE);
 	mnt = (struct vfsmount *)devname;
 	if (IS_ERR(devname))
 		goto free_page;
-	mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata);
+	mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
 free_page:
 	free_page((unsigned long)page);
 out:
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index ce939c0..d0c80d8 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -885,4 +885,5 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
 	.lock		= nfs3_proc_lock,
 	.clear_acl_cache = nfs3_forget_cached_acls,
 	.close_context	= nfs_close_context,
+	.init_client	= nfs_init_client,
 };
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 1be36cf..c64be1c 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -252,6 +252,9 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser
 extern int nfs4_setup_sequence(const struct nfs_server *server,
 		struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
 		int cache_reply, struct rpc_task *task);
+extern int nfs41_setup_sequence(struct nfs4_session *session,
+		struct nfs4_sequence_args *args, struct nfs4_sequence_res *res,
+		int cache_reply, struct rpc_task *task);
 extern void nfs4_destroy_session(struct nfs4_session *session);
 extern struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp);
 extern int nfs4_proc_create_session(struct nfs_client *);
@@ -259,6 +262,19 @@ extern int nfs4_proc_destroy_session(struct nfs4_session *);
 extern int nfs4_init_session(struct nfs_server *server);
 extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
 		struct nfs_fsinfo *fsinfo);
+
+static inline bool
+is_ds_only_client(struct nfs_client *clp)
+{
+	return (clp->cl_exchange_flags & EXCHGID4_FLAG_MASK_PNFS) ==
+		EXCHGID4_FLAG_USE_PNFS_DS;
+}
+
+static inline bool
+is_ds_client(struct nfs_client *clp)
+{
+	return clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_DS;
+}
 #else /* CONFIG_NFS_v4_1 */
 static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server)
 {
@@ -276,6 +292,18 @@ static inline int nfs4_init_session(struct nfs_server *server)
 {
 	return 0;
 }
+
+static inline bool
+is_ds_only_client(struct nfs_client *clp)
+{
+	return false;
+}
+
+static inline bool
+is_ds_client(struct nfs_client *clp)
+{
+	return false;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[];
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 23f930c..4285584 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -40,32 +40,309 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
 MODULE_DESCRIPTION("The NFSv4 file layout driver");
 
-static int
-filelayout_set_layoutdriver(struct nfs_server *nfss)
+#define FILELAYOUT_POLL_RETRY_MAX     (15*HZ)
+
+static loff_t
+filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg,
+			    loff_t offset)
 {
-	int status = pnfs_alloc_init_deviceid_cache(nfss->nfs_client,
-						nfs4_fl_free_deviceid_callback);
-	if (status) {
-		printk(KERN_WARNING "%s: deviceid cache could not be "
-			"initialized\n", __func__);
-		return status;
+	u32 stripe_width = flseg->stripe_unit * flseg->dsaddr->stripe_count;
+	u64 tmp;
+
+	offset -= flseg->pattern_offset;
+	tmp = offset;
+	do_div(tmp, stripe_width);
+
+	return tmp * flseg->stripe_unit + do_div(offset, flseg->stripe_unit);
+}
+
+/* This function is used by the layout driver to calculate the
+ * offset of the file on the dserver based on whether the
+ * layout type is STRIPE_DENSE or STRIPE_SPARSE
+ */
+static loff_t
+filelayout_get_dserver_offset(struct pnfs_layout_segment *lseg, loff_t offset)
+{
+	struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
+
+	switch (flseg->stripe_type) {
+	case STRIPE_SPARSE:
+		return offset;
+
+	case STRIPE_DENSE:
+		return filelayout_get_dense_offset(flseg, offset);
 	}
-	dprintk("%s: deviceid cache has been initialized successfully\n",
-		__func__);
+
+	BUG();
+}
+
+/* For data server errors we don't recover from */
+static void
+filelayout_set_lo_fail(struct pnfs_layout_segment *lseg)
+{
+	if (lseg->pls_range.iomode == IOMODE_RW) {
+		dprintk("%s Setting layout IOMODE_RW fail bit\n", __func__);
+		set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
+	} else {
+		dprintk("%s Setting layout IOMODE_READ fail bit\n", __func__);
+		set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
+	}
+}
+
+static int filelayout_async_handle_error(struct rpc_task *task,
+					 struct nfs4_state *state,
+					 struct nfs_client *clp,
+					 int *reset)
+{
+	if (task->tk_status >= 0)
+		return 0;
+
+	*reset = 0;
+
+	switch (task->tk_status) {
+	case -NFS4ERR_BADSESSION:
+	case -NFS4ERR_BADSLOT:
+	case -NFS4ERR_BAD_HIGH_SLOT:
+	case -NFS4ERR_DEADSESSION:
+	case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+	case -NFS4ERR_SEQ_FALSE_RETRY:
+	case -NFS4ERR_SEQ_MISORDERED:
+		dprintk("%s ERROR %d, Reset session. Exchangeid "
+			"flags 0x%x\n", __func__, task->tk_status,
+			clp->cl_exchange_flags);
+		nfs4_schedule_session_recovery(clp->cl_session);
+		break;
+	case -NFS4ERR_DELAY:
+	case -NFS4ERR_GRACE:
+	case -EKEYEXPIRED:
+		rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX);
+		break;
+	default:
+		dprintk("%s DS error. Retry through MDS %d\n", __func__,
+			task->tk_status);
+		*reset = 1;
+		break;
+	}
+	task->tk_status = 0;
+	return -EAGAIN;
+}
+
+/* NFS_PROTO call done callback routines */
+
+static int filelayout_read_done_cb(struct rpc_task *task,
+				struct nfs_read_data *data)
+{
+	struct nfs_client *clp = data->ds_clp;
+	int reset = 0;
+
+	dprintk("%s DS read\n", __func__);
+
+	if (filelayout_async_handle_error(task, data->args.context->state,
+					  data->ds_clp, &reset) == -EAGAIN) {
+		dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n",
+			__func__, data->ds_clp, data->ds_clp->cl_session);
+		if (reset) {
+			filelayout_set_lo_fail(data->lseg);
+			nfs4_reset_read(task, data);
+			clp = NFS_SERVER(data->inode)->nfs_client;
+		}
+		nfs_restart_rpc(task, clp);
+		return -EAGAIN;
+	}
+
 	return 0;
 }
 
-/* Clear out the layout by destroying its device list */
-static int
-filelayout_clear_layoutdriver(struct nfs_server *nfss)
+/*
+ * Call ops for the async read/write cases
+ * In the case of dense layouts, the offset needs to be reset to its
+ * original value.
+ */
+static void filelayout_read_prepare(struct rpc_task *task, void *data)
 {
-	dprintk("--> %s\n", __func__);
+	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
+
+	rdata->read_done_cb = filelayout_read_done_cb;
+
+	if (nfs41_setup_sequence(rdata->ds_clp->cl_session,
+				&rdata->args.seq_args, &rdata->res.seq_res,
+				0, task))
+		return;
+
+	rpc_call_start(task);
+}
+
+static void filelayout_read_call_done(struct rpc_task *task, void *data)
+{
+	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
+
+	dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status);
+
+	/* Note this may cause RPC to be resent */
+	rdata->mds_ops->rpc_call_done(task, data);
+}
+
+static void filelayout_read_release(void *data)
+{
+	struct nfs_read_data *rdata = (struct nfs_read_data *)data;
+
+	rdata->mds_ops->rpc_release(data);
+}
+
+static int filelayout_write_done_cb(struct rpc_task *task,
+				struct nfs_write_data *data)
+{
+	int reset = 0;
+
+	if (filelayout_async_handle_error(task, data->args.context->state,
+					  data->ds_clp, &reset) == -EAGAIN) {
+		struct nfs_client *clp;
+
+		dprintk("%s calling restart ds_clp %p ds_clp->cl_session %p\n",
+			__func__, data->ds_clp, data->ds_clp->cl_session);
+		if (reset) {
+			filelayout_set_lo_fail(data->lseg);
+			nfs4_reset_write(task, data);
+			clp = NFS_SERVER(data->inode)->nfs_client;
+		} else
+			clp = data->ds_clp;
+		nfs_restart_rpc(task, clp);
+		return -EAGAIN;
+	}
 
-	if (nfss->nfs_client->cl_devid_cache)
-		pnfs_put_deviceid_cache(nfss->nfs_client);
 	return 0;
 }
 
+static void filelayout_write_prepare(struct rpc_task *task, void *data)
+{
+	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+	if (nfs41_setup_sequence(wdata->ds_clp->cl_session,
+				&wdata->args.seq_args, &wdata->res.seq_res,
+				0, task))
+		return;
+
+	rpc_call_start(task);
+}
+
+static void filelayout_write_call_done(struct rpc_task *task, void *data)
+{
+	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+	/* Note this may cause RPC to be resent */
+	wdata->mds_ops->rpc_call_done(task, data);
+}
+
+static void filelayout_write_release(void *data)
+{
+	struct nfs_write_data *wdata = (struct nfs_write_data *)data;
+
+	wdata->mds_ops->rpc_release(data);
+}
+
+struct rpc_call_ops filelayout_read_call_ops = {
+	.rpc_call_prepare = filelayout_read_prepare,
+	.rpc_call_done = filelayout_read_call_done,
+	.rpc_release = filelayout_read_release,
+};
+
+struct rpc_call_ops filelayout_write_call_ops = {
+	.rpc_call_prepare = filelayout_write_prepare,
+	.rpc_call_done = filelayout_write_call_done,
+	.rpc_release = filelayout_write_release,
+};
+
+static enum pnfs_try_status
+filelayout_read_pagelist(struct nfs_read_data *data)
+{
+	struct pnfs_layout_segment *lseg = data->lseg;
+	struct nfs4_pnfs_ds *ds;
+	loff_t offset = data->args.offset;
+	u32 j, idx;
+	struct nfs_fh *fh;
+	int status;
+
+	dprintk("--> %s ino %lu pgbase %u req %Zu@%llu\n",
+		__func__, data->inode->i_ino,
+		data->args.pgbase, (size_t)data->args.count, offset);
+
+	/* Retrieve the correct rpc_client for the byte range */
+	j = nfs4_fl_calc_j_index(lseg, offset);
+	idx = nfs4_fl_calc_ds_index(lseg, j);
+	ds = nfs4_fl_prepare_ds(lseg, idx);
+	if (!ds) {
+		/* Either layout fh index faulty, or ds connect failed */
+		set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
+		set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
+		return PNFS_NOT_ATTEMPTED;
+	}
+	dprintk("%s USE DS:ip %x %hu\n", __func__,
+		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+
+	/* No multipath support. Use first DS */
+	data->ds_clp = ds->ds_clp;
+	fh = nfs4_fl_select_ds_fh(lseg, j);
+	if (fh)
+		data->args.fh = fh;
+
+	data->args.offset = filelayout_get_dserver_offset(lseg, offset);
+	data->mds_offset = offset;
+
+	/* Perform an asynchronous read to ds */
+	status = nfs_initiate_read(data, ds->ds_clp->cl_rpcclient,
+				   &filelayout_read_call_ops);
+	BUG_ON(status != 0);
+	return PNFS_ATTEMPTED;
+}
+
+/* Perform async writes. */
+static enum pnfs_try_status
+filelayout_write_pagelist(struct nfs_write_data *data, int sync)
+{
+	struct pnfs_layout_segment *lseg = data->lseg;
+	struct nfs4_pnfs_ds *ds;
+	loff_t offset = data->args.offset;
+	u32 j, idx;
+	struct nfs_fh *fh;
+	int status;
+
+	/* Retrieve the correct rpc_client for the byte range */
+	j = nfs4_fl_calc_j_index(lseg, offset);
+	idx = nfs4_fl_calc_ds_index(lseg, j);
+	ds = nfs4_fl_prepare_ds(lseg, idx);
+	if (!ds) {
+		printk(KERN_ERR "%s: prepare_ds failed, use MDS\n", __func__);
+		set_bit(lo_fail_bit(IOMODE_RW), &lseg->pls_layout->plh_flags);
+		set_bit(lo_fail_bit(IOMODE_READ), &lseg->pls_layout->plh_flags);
+		return PNFS_NOT_ATTEMPTED;
+	}
+	dprintk("%s ino %lu sync %d req %Zu@%llu DS:%x:%hu\n", __func__,
+		data->inode->i_ino, sync, (size_t) data->args.count, offset,
+		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+
+	/* We can't handle commit to ds yet */
+	if (!FILELAYOUT_LSEG(lseg)->commit_through_mds)
+		data->args.stable = NFS_FILE_SYNC;
+
+	data->write_done_cb = filelayout_write_done_cb;
+	data->ds_clp = ds->ds_clp;
+	fh = nfs4_fl_select_ds_fh(lseg, j);
+	if (fh)
+		data->args.fh = fh;
+	/*
+	 * Get the file offset on the dserver. Set the write offset to
+	 * this offset and save the original offset.
+	 */
+	data->args.offset = filelayout_get_dserver_offset(lseg, offset);
+	data->mds_offset = offset;
+
+	/* Perform an asynchronous write */
+	status = nfs_initiate_write(data, ds->ds_clp->cl_rpcclient,
+				    &filelayout_write_call_ops, sync);
+	BUG_ON(status != 0);
+	return PNFS_ATTEMPTED;
+}
+
 /*
  * filelayout_check_layout()
  *
@@ -92,14 +369,14 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
 		goto out;
 	}
 
-	if (fl->stripe_unit % PAGE_SIZE) {
-		dprintk("%s Stripe unit (%u) not page aligned\n",
+	if (!fl->stripe_unit || fl->stripe_unit % PAGE_SIZE) {
+		dprintk("%s Invalid stripe unit (%u)\n",
 			__func__, fl->stripe_unit);
 		goto out;
 	}
 
 	/* find and reference the deviceid */
-	dsaddr = nfs4_fl_find_get_deviceid(nfss->nfs_client, id);
+	dsaddr = nfs4_fl_find_get_deviceid(id);
 	if (dsaddr == NULL) {
 		dsaddr = get_device_info(lo->plh_inode, id);
 		if (dsaddr == NULL)
@@ -134,7 +411,7 @@ out:
 	dprintk("--> %s returns %d\n", __func__, status);
 	return status;
 out_put:
-	pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache, &dsaddr->deviceid);
+	nfs4_fl_put_deviceid(dsaddr);
 	goto out;
 }
 
@@ -243,23 +520,47 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
 static void
 filelayout_free_lseg(struct pnfs_layout_segment *lseg)
 {
-	struct nfs_server *nfss = NFS_SERVER(lseg->pls_layout->plh_inode);
 	struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
 
 	dprintk("--> %s\n", __func__);
-	pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache,
-			  &fl->dsaddr->deviceid);
+	nfs4_fl_put_deviceid(fl->dsaddr);
 	_filelayout_free_lseg(fl);
 }
 
+/*
+ * filelayout_pg_test(). Called by nfs_can_coalesce_requests()
+ *
+ * return 1 :  coalesce page
+ * return 0 :  don't coalesce page
+ */
+int
+filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
+		   struct nfs_page *req)
+{
+	u64 p_stripe, r_stripe;
+	u32 stripe_unit;
+
+	if (!pgio->pg_lseg)
+		return 1;
+	p_stripe = (u64)prev->wb_index << PAGE_CACHE_SHIFT;
+	r_stripe = (u64)req->wb_index << PAGE_CACHE_SHIFT;
+	stripe_unit = FILELAYOUT_LSEG(pgio->pg_lseg)->stripe_unit;
+
+	do_div(p_stripe, stripe_unit);
+	do_div(r_stripe, stripe_unit);
+
+	return (p_stripe == r_stripe);
+}
+
 static struct pnfs_layoutdriver_type filelayout_type = {
-	.id = LAYOUT_NFSV4_1_FILES,
-	.name = "LAYOUT_NFSV4_1_FILES",
-	.owner = THIS_MODULE,
-	.set_layoutdriver = filelayout_set_layoutdriver,
-	.clear_layoutdriver = filelayout_clear_layoutdriver,
-	.alloc_lseg              = filelayout_alloc_lseg,
-	.free_lseg               = filelayout_free_lseg,
+	.id			= LAYOUT_NFSV4_1_FILES,
+	.name			= "LAYOUT_NFSV4_1_FILES",
+	.owner			= THIS_MODULE,
+	.alloc_lseg		= filelayout_alloc_lseg,
+	.free_lseg		= filelayout_free_lseg,
+	.pg_test		= filelayout_pg_test,
+	.read_pagelist		= filelayout_read_pagelist,
+	.write_pagelist		= filelayout_write_pagelist,
 };
 
 static int __init nfs4filelayout_init(void)
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index bbf60dd..ee0c907 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -55,8 +55,14 @@ struct nfs4_pnfs_ds {
 	atomic_t		ds_count;
 };
 
+/* nfs4_file_layout_dsaddr flags */
+#define NFS4_DEVICE_ID_NEG_ENTRY	0x00000001
+
 struct nfs4_file_layout_dsaddr {
-	struct pnfs_deviceid_node	deviceid;
+	struct hlist_node		node;
+	struct nfs4_deviceid		deviceid;
+	atomic_t			ref;
+	unsigned long			flags;
 	u32				stripe_count;
 	u8				*stripe_indices;
 	u32				ds_num;
@@ -83,11 +89,18 @@ FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
 			    generic_hdr);
 }
 
-extern void nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *);
+extern struct nfs_fh *
+nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
+
 extern void print_ds(struct nfs4_pnfs_ds *ds);
 extern void print_deviceid(struct nfs4_deviceid *dev_id);
+u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset);
+u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);
+struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg,
+					u32 ds_idx);
 extern struct nfs4_file_layout_dsaddr *
-nfs4_fl_find_get_deviceid(struct nfs_client *, struct nfs4_deviceid *dev_id);
+nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id);
+extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
 get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id);
 
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index b73c343..68143c1 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -37,6 +37,30 @@
 #define NFSDBG_FACILITY		NFSDBG_PNFS_LD
 
 /*
+ * Device ID RCU cache. A device ID is unique per client ID and layout type.
+ */
+#define NFS4_FL_DEVICE_ID_HASH_BITS	5
+#define NFS4_FL_DEVICE_ID_HASH_SIZE	(1 << NFS4_FL_DEVICE_ID_HASH_BITS)
+#define NFS4_FL_DEVICE_ID_HASH_MASK	(NFS4_FL_DEVICE_ID_HASH_SIZE - 1)
+
+static inline u32
+nfs4_fl_deviceid_hash(struct nfs4_deviceid *id)
+{
+	unsigned char *cptr = (unsigned char *)id->data;
+	unsigned int nbytes = NFS4_DEVICEID4_SIZE;
+	u32 x = 0;
+
+	while (nbytes--) {
+		x *= 37;
+		x += *cptr++;
+	}
+	return x & NFS4_FL_DEVICE_ID_HASH_MASK;
+}
+
+static struct hlist_head filelayout_deviceid_cache[NFS4_FL_DEVICE_ID_HASH_SIZE];
+static DEFINE_SPINLOCK(filelayout_deviceid_lock);
+
+/*
  * Data server cache
  *
  * Data servers can be mapped to different device ids.
@@ -104,6 +128,67 @@ _data_server_lookup_locked(u32 ip_addr, u32 port)
 	return NULL;
 }
 
+/*
+ * Create an rpc connection to the nfs4_pnfs_ds data server
+ * Currently only support IPv4
+ */
+static int
+nfs4_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds)
+{
+	struct nfs_client *clp;
+	struct sockaddr_in sin;
+	int status = 0;
+
+	dprintk("--> %s ip:port %x:%hu au_flavor %d\n", __func__,
+		ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
+		mds_srv->nfs_client->cl_rpcclient->cl_auth->au_flavor);
+
+	sin.sin_family = AF_INET;
+	sin.sin_addr.s_addr = ds->ds_ip_addr;
+	sin.sin_port = ds->ds_port;
+
+	clp = nfs4_set_ds_client(mds_srv->nfs_client, (struct sockaddr *)&sin,
+				 sizeof(sin), IPPROTO_TCP);
+	if (IS_ERR(clp)) {
+		status = PTR_ERR(clp);
+		goto out;
+	}
+
+	if ((clp->cl_exchange_flags & EXCHGID4_FLAG_MASK_PNFS) != 0) {
+		if (!is_ds_client(clp)) {
+			status = -ENODEV;
+			goto out_put;
+		}
+		ds->ds_clp = clp;
+		dprintk("%s [existing] ip=%x, port=%hu\n", __func__,
+			ntohl(ds->ds_ip_addr), ntohs(ds->ds_port));
+		goto out;
+	}
+
+	/*
+	 * Do not set NFS_CS_CHECK_LEASE_TIME instead set the DS lease to
+	 * be equal to the MDS lease. Renewal is scheduled in create_session.
+	 */
+	spin_lock(&mds_srv->nfs_client->cl_lock);
+	clp->cl_lease_time = mds_srv->nfs_client->cl_lease_time;
+	spin_unlock(&mds_srv->nfs_client->cl_lock);
+	clp->cl_last_renewal = jiffies;
+
+	/* New nfs_client */
+	status = nfs4_init_ds_session(clp);
+	if (status)
+		goto out_put;
+
+	ds->ds_clp = clp;
+	dprintk("%s [new] ip=%x, port=%hu\n", __func__, ntohl(ds->ds_ip_addr),
+		ntohs(ds->ds_port));
+out:
+	return status;
+out_put:
+	nfs_put_client(clp);
+	goto out;
+}
+
 static void
 destroy_ds(struct nfs4_pnfs_ds *ds)
 {
@@ -122,7 +207,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
 	struct nfs4_pnfs_ds *ds;
 	int i;
 
-	print_deviceid(&dsaddr->deviceid.de_id);
+	print_deviceid(&dsaddr->deviceid);
 
 	for (i = 0; i < dsaddr->ds_num; i++) {
 		ds = dsaddr->ds_list[i];
@@ -139,15 +224,6 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
 	kfree(dsaddr);
 }
 
-void
-nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *device)
-{
-	struct nfs4_file_layout_dsaddr *dsaddr =
-		container_of(device, struct nfs4_file_layout_dsaddr, deviceid);
-
-	nfs4_fl_free_deviceid(dsaddr);
-}
-
 static struct nfs4_pnfs_ds *
 nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port)
 {
@@ -300,7 +376,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
 	dsaddr->stripe_count = cnt;
 	dsaddr->ds_num = num;
 
-	memcpy(&dsaddr->deviceid.de_id, &pdev->dev_id, sizeof(pdev->dev_id));
+	memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id));
 
 	/* Go back an read stripe indices */
 	p = indicesp;
@@ -350,28 +426,37 @@ out_err:
 }
 
 /*
- * Decode the opaque device specified in 'dev'
- * and add it to the list of available devices.
- * If the deviceid is already cached, nfs4_add_deviceid will return
- * a pointer to the cached struct and throw away the new.
+ * Decode the opaque device specified in 'dev' and add it to the cache of
+ * available devices.
  */
-static struct nfs4_file_layout_dsaddr*
+static struct nfs4_file_layout_dsaddr *
 decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
 {
-	struct nfs4_file_layout_dsaddr *dsaddr;
-	struct pnfs_deviceid_node *d;
+	struct nfs4_file_layout_dsaddr *d, *new;
+	long hash;
 
-	dsaddr = decode_device(inode, dev);
-	if (!dsaddr) {
+	new = decode_device(inode, dev);
+	if (!new) {
 		printk(KERN_WARNING "%s: Could not decode or add device\n",
 			__func__);
 		return NULL;
 	}
 
-	d = pnfs_add_deviceid(NFS_SERVER(inode)->nfs_client->cl_devid_cache,
-			      &dsaddr->deviceid);
+	spin_lock(&filelayout_deviceid_lock);
+	d = nfs4_fl_find_get_deviceid(&new->deviceid);
+	if (d) {
+		spin_unlock(&filelayout_deviceid_lock);
+		nfs4_fl_free_deviceid(new);
+		return d;
+	}
+
+	INIT_HLIST_NODE(&new->node);
+	atomic_set(&new->ref, 1);
+	hash = nfs4_fl_deviceid_hash(&new->deviceid);
+	hlist_add_head_rcu(&new->node, &filelayout_deviceid_cache[hash]);
+	spin_unlock(&filelayout_deviceid_lock);
 
-	return container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
+	return new;
 }
 
 /*
@@ -446,12 +531,123 @@ out_free:
 	return dsaddr;
 }
 
+void
+nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
+{
+	if (atomic_dec_and_lock(&dsaddr->ref, &filelayout_deviceid_lock)) {
+		hlist_del_rcu(&dsaddr->node);
+		spin_unlock(&filelayout_deviceid_lock);
+
+		synchronize_rcu();
+		nfs4_fl_free_deviceid(dsaddr);
+	}
+}
+
 struct nfs4_file_layout_dsaddr *
-nfs4_fl_find_get_deviceid(struct nfs_client *clp, struct nfs4_deviceid *id)
+nfs4_fl_find_get_deviceid(struct nfs4_deviceid *id)
+{
+	struct nfs4_file_layout_dsaddr *d;
+	struct hlist_node *n;
+	long hash = nfs4_fl_deviceid_hash(id);
+
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(d, n, &filelayout_deviceid_cache[hash], node) {
+		if (!memcmp(&d->deviceid, id, sizeof(*id))) {
+			if (!atomic_inc_not_zero(&d->ref))
+				goto fail;
+			rcu_read_unlock();
+			return d;
+		}
+	}
+fail:
+	rcu_read_unlock();
+	return NULL;
+}
+
+/*
+ * Want res = (offset - layout->pattern_offset)/ layout->stripe_unit
+ * Then: ((res + fsi) % dsaddr->stripe_count)
+ */
+u32
+nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset)
+{
+	struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
+	u64 tmp;
+
+	tmp = offset - flseg->pattern_offset;
+	do_div(tmp, flseg->stripe_unit);
+	tmp += flseg->first_stripe_index;
+	return do_div(tmp, flseg->dsaddr->stripe_count);
+}
+
+u32
+nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j)
+{
+	return FILELAYOUT_LSEG(lseg)->dsaddr->stripe_indices[j];
+}
+
+struct nfs_fh *
+nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j)
+{
+	struct nfs4_filelayout_segment *flseg = FILELAYOUT_LSEG(lseg);
+	u32 i;
+
+	if (flseg->stripe_type == STRIPE_SPARSE) {
+		if (flseg->num_fh == 1)
+			i = 0;
+		else if (flseg->num_fh == 0)
+			/* Use the MDS OPEN fh set in nfs_read_rpcsetup */
+			return NULL;
+		else
+			i = nfs4_fl_calc_ds_index(lseg, j);
+	} else
+		i = j;
+	return flseg->fh_array[i];
+}
+
+static void
+filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr,
+			       int err, u32 ds_addr)
+{
+	u32 *p = (u32 *)&dsaddr->deviceid;
+
+	printk(KERN_ERR "NFS: data server %x connection error %d."
+		" Deviceid [%x%x%x%x] marked out of use.\n",
+		ds_addr, err, p[0], p[1], p[2], p[3]);
+
+	spin_lock(&filelayout_deviceid_lock);
+	dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY;
+	spin_unlock(&filelayout_deviceid_lock);
+}
+
+struct nfs4_pnfs_ds *
+nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx)
 {
-	struct pnfs_deviceid_node *d;
+	struct nfs4_file_layout_dsaddr *dsaddr = FILELAYOUT_LSEG(lseg)->dsaddr;
+	struct nfs4_pnfs_ds *ds = dsaddr->ds_list[ds_idx];
 
-	d = pnfs_find_get_deviceid(clp->cl_devid_cache, id);
-	return (d == NULL) ? NULL :
-		container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
+	if (ds == NULL) {
+		printk(KERN_ERR "%s: No data server for offset index %d\n",
+			__func__, ds_idx);
+		return NULL;
+	}
+
+	if (!ds->ds_clp) {
+		struct nfs_server *s = NFS_SERVER(lseg->pls_layout->plh_inode);
+		int err;
+
+		if (dsaddr->flags & NFS4_DEVICE_ID_NEG_ENTRY) {
+			/* Already tried to connect, don't try again */
+			dprintk("%s Deviceid marked out of use\n", __func__);
+			return NULL;
+		}
+		err = nfs4_ds_connect(s, ds);
+		if (err) {
+			filelayout_mark_devid_negative(dsaddr, err,
+						       ntohl(ds->ds_ip_addr));
+			return NULL;
+		}
+	}
+	return ds;
 }
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 3c2a172..bb80c49 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -54,33 +54,29 @@ Elong:
 /*
  * Determine the mount path as a string
  */
-static char *nfs4_path(const struct vfsmount *mnt_parent,
-		       const struct dentry *dentry,
-		       char *buffer, ssize_t buflen)
+static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
-	const char *srvpath;
-
-	srvpath = strchr(mnt_parent->mnt_devname, ':');
-	if (srvpath)
-		srvpath++;
-	else
-		srvpath = mnt_parent->mnt_devname;
-
-	return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen);
+	char *limit;
+	char *path = nfs_path(&limit, dentry, buffer, buflen);
+	if (!IS_ERR(path)) {
+		char *colon = strchr(path, ':');
+		if (colon && colon < limit)
+			path = colon + 1;
+	}
+	return path;
 }
 
 /*
  * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we
  * believe to be the server path to this dentry
  */
-static int nfs4_validate_fspath(const struct vfsmount *mnt_parent,
-				const struct dentry *dentry,
+static int nfs4_validate_fspath(struct dentry *dentry,
 				const struct nfs4_fs_locations *locations,
 				char *page, char *page2)
 {
 	const char *path, *fs_path;
 
-	path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE);
+	path = nfs4_path(dentry, page, PAGE_SIZE);
 	if (IS_ERR(path))
 		return PTR_ERR(path);
 
@@ -165,20 +161,18 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
 
 /**
  * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
- * @mnt_parent - mountpoint of parent directory
  * @dentry - parent directory
  * @locations - array of NFSv4 server location information
  *
  */
-static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
-					    const struct dentry *dentry,
+static struct vfsmount *nfs_follow_referral(struct dentry *dentry,
 					    const struct nfs4_fs_locations *locations)
 {
 	struct vfsmount *mnt = ERR_PTR(-ENOENT);
 	struct nfs_clone_mount mountdata = {
-		.sb = mnt_parent->mnt_sb,
+		.sb = dentry->d_sb,
 		.dentry = dentry,
-		.authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
+		.authflavor = NFS_SB(dentry->d_sb)->client->cl_auth->au_flavor,
 	};
 	char *page = NULL, *page2 = NULL;
 	int loc, error;
@@ -198,7 +192,7 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
 		goto out;
 
 	/* Ensure fs path is a prefix of current dentry path */
-	error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2);
+	error = nfs4_validate_fspath(dentry, locations, page, page2);
 	if (error < 0) {
 		mnt = ERR_PTR(error);
 		goto out;
@@ -225,11 +219,10 @@ out:
 
 /*
  * nfs_do_refmount - handle crossing a referral on server
- * @mnt_parent - mountpoint of referral
  * @dentry - dentry of referral
  *
  */
-struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct dentry *dentry)
 {
 	struct vfsmount *mnt = ERR_PTR(-ENOMEM);
 	struct dentry *parent;
@@ -262,7 +255,7 @@ struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentr
 	    fs_locations->fs_path.ncomponents <= 0)
 		goto out_free;
 
-	mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations);
+	mnt = nfs_follow_referral(dentry, fs_locations);
 out_free:
 	__free_page(page);
 	kfree(fs_locations);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 0a07e35..1d84e70 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -85,6 +85,9 @@ static int nfs4_map_errors(int err)
 	switch (err) {
 	case -NFS4ERR_RESOURCE:
 		return -EREMOTEIO;
+	case -NFS4ERR_BADOWNER:
+	case -NFS4ERR_BADNAME:
+		return -EINVAL;
 	default:
 		dprintk("%s could not handle NFSv4 error %d\n",
 				__func__, -err);
@@ -241,7 +244,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
 /* This is the error handling routine for processes that are allowed
  * to sleep.
  */
-static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception)
 {
 	struct nfs_client *clp = server->nfs_client;
 	struct nfs4_state *state = exception->state;
@@ -293,6 +296,19 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
 				break;
 		case -NFS4ERR_OLD_STATEID:
 			exception->retry = 1;
+			break;
+		case -NFS4ERR_BADOWNER:
+			/* The following works around a Linux server bug! */
+		case -NFS4ERR_BADNAME:
+			if (server->caps & NFS_CAP_UIDGID_NOMAP) {
+				server->caps &= ~NFS_CAP_UIDGID_NOMAP;
+				exception->retry = 1;
+				printk(KERN_WARNING "NFS: v4 server %s "
+						"does not accept raw "
+						"uid/gids. "
+						"Reenabling the idmapper.\n",
+						server->nfs_client->cl_hostname);
+			}
 	}
 	/* We failed to handle the error */
 	return nfs4_map_errors(ret);
@@ -505,7 +521,7 @@ out:
 	return ret_id;
 }
 
-static int nfs41_setup_sequence(struct nfs4_session *session,
+int nfs41_setup_sequence(struct nfs4_session *session,
 				struct nfs4_sequence_args *args,
 				struct nfs4_sequence_res *res,
 				int cache_reply,
@@ -571,6 +587,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
 	res->sr_status = 1;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(nfs41_setup_sequence);
 
 int nfs4_setup_sequence(const struct nfs_server *server,
 			struct nfs4_sequence_args *args,
@@ -1573,9 +1590,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
 	return 0;
 }
 
-static int nfs4_recover_expired_lease(struct nfs_server *server)
+static int nfs4_client_recover_expired_lease(struct nfs_client *clp)
 {
-	struct nfs_client *clp = server->nfs_client;
 	unsigned int loop;
 	int ret;
 
@@ -1592,6 +1608,11 @@ static int nfs4_recover_expired_lease(struct nfs_server *server)
 	return ret;
 }
 
+static int nfs4_recover_expired_lease(struct nfs_server *server)
+{
+	return nfs4_client_recover_expired_lease(server->nfs_client);
+}
+
 /*
  * OPEN_EXPIRED:
  * 	reclaim state on the server after a network partition.
@@ -3069,15 +3090,10 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
 	return err;
 }
 
-static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
+static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_read_data *data)
 {
 	struct nfs_server *server = NFS_SERVER(data->inode);
 
-	dprintk("--> %s\n", __func__);
-
-	if (!nfs4_sequence_done(task, &data->res.seq_res))
-		return -EAGAIN;
-
 	if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) {
 		nfs_restart_rpc(task, server->nfs_client);
 		return -EAGAIN;
@@ -3089,19 +3105,44 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
 	return 0;
 }
 
+static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data)
+{
+
+	dprintk("--> %s\n", __func__);
+
+	if (!nfs4_sequence_done(task, &data->res.seq_res))
+		return -EAGAIN;
+
+	return data->read_done_cb(task, data);
+}
+
 static void nfs4_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
 {
 	data->timestamp   = jiffies;
+	data->read_done_cb = nfs4_read_done_cb;
 	msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
 }
 
-static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
+/* Reset the the nfs_read_data to send the read to the MDS. */
+void nfs4_reset_read(struct rpc_task *task, struct nfs_read_data *data)
+{
+	dprintk("%s Reset task for i/o through\n", __func__);
+	put_lseg(data->lseg);
+	data->lseg = NULL;
+	/* offsets will differ in the dense stripe case */
+	data->args.offset = data->mds_offset;
+	data->ds_clp = NULL;
+	data->args.fh     = NFS_FH(data->inode);
+	data->read_done_cb = nfs4_read_done_cb;
+	task->tk_ops = data->mds_ops;
+	rpc_task_reset_client(task, NFS_CLIENT(data->inode));
+}
+EXPORT_SYMBOL_GPL(nfs4_reset_read);
+
+static int nfs4_write_done_cb(struct rpc_task *task, struct nfs_write_data *data)
 {
 	struct inode *inode = data->inode;
 	
-	if (!nfs4_sequence_done(task, &data->res.seq_res))
-		return -EAGAIN;
-
 	if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) {
 		nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client);
 		return -EAGAIN;
@@ -3113,11 +3154,41 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data)
 	return 0;
 }
 
+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;
+	return data->write_done_cb(task, data);
+}
+
+/* Reset the the nfs_write_data to send the write to the MDS. */
+void nfs4_reset_write(struct rpc_task *task, struct nfs_write_data *data)
+{
+	dprintk("%s Reset task for i/o through\n", __func__);
+	put_lseg(data->lseg);
+	data->lseg          = NULL;
+	data->ds_clp        = NULL;
+	data->write_done_cb = nfs4_write_done_cb;
+	data->args.fh       = NFS_FH(data->inode);
+	data->args.bitmask  = data->res.server->cache_consistency_bitmask;
+	data->args.offset   = data->mds_offset;
+	data->res.fattr     = &data->fattr;
+	task->tk_ops        = data->mds_ops;
+	rpc_task_reset_client(task, NFS_CLIENT(data->inode));
+}
+EXPORT_SYMBOL_GPL(nfs4_reset_write);
+
 static void nfs4_proc_write_setup(struct nfs_write_data *data, struct rpc_message *msg)
 {
 	struct nfs_server *server = NFS_SERVER(data->inode);
 
-	data->args.bitmask = server->cache_consistency_bitmask;
+	if (data->lseg) {
+		data->args.bitmask = NULL;
+		data->res.fattr = NULL;
+	} else
+		data->args.bitmask = server->cache_consistency_bitmask;
+	if (!data->write_done_cb)
+		data->write_done_cb = nfs4_write_done_cb;
 	data->res.server = server;
 	data->timestamp   = jiffies;
 
@@ -5118,6 +5189,27 @@ int nfs4_init_session(struct nfs_server *server)
 	return ret;
 }
 
+int nfs4_init_ds_session(struct nfs_client *clp)
+{
+	struct nfs4_session *session = clp->cl_session;
+	int ret;
+
+	if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state))
+		return 0;
+
+	ret = nfs4_client_recover_expired_lease(clp);
+	if (!ret)
+		/* Test for the DS role */
+		if (!is_ds_client(clp))
+			ret = -ENODEV;
+	if (!ret)
+		ret = nfs4_check_client_ready(clp);
+	return ret;
+
+}
+EXPORT_SYMBOL_GPL(nfs4_init_ds_session);
+
+
 /*
  * Renew the cl_session lease.
  */
@@ -5648,6 +5740,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
 	.clear_acl_cache = nfs4_zap_acl_attr,
 	.close_context  = nfs4_close_context,
 	.open_context	= nfs4_atomic_open,
+	.init_client	= nfs4_init_client,
 };
 
 static const struct xattr_handler nfs4_xattr_nfs4_acl_handler = {
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 402143d..df8e7f3 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -64,12 +64,8 @@ nfs4_renew_state(struct work_struct *work)
 	ops = clp->cl_mvops->state_renewal_ops;
 	dprintk("%s: start\n", __func__);
 
-	rcu_read_lock();
-	if (list_empty(&clp->cl_superblocks)) {
-		rcu_read_unlock();
+	if (test_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state))
 		goto out;
-	}
-	rcu_read_unlock();
 
 	spin_lock(&clp->cl_lock);
 	lease = clp->cl_lease_time;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0592288..ab1bf5b 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -153,6 +153,11 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp)
 	int status;
 	struct nfs_fsinfo fsinfo;
 
+	if (!test_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state)) {
+		nfs4_schedule_state_renewal(clp);
+		return 0;
+	}
+
 	status = nfs4_proc_get_lease_time(clp, &fsinfo);
 	if (status == 0) {
 		/* Update lease time and schedule renewal */
@@ -1448,6 +1453,7 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session)
 {
 	nfs4_schedule_lease_recovery(session->clp);
 }
+EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery);
 
 void nfs41_handle_recall_slot(struct nfs_client *clp)
 {
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 94d50e8..0cf560f 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -844,7 +844,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
 	if (iap->ia_valid & ATTR_MODE)
 		len += 4;
 	if (iap->ia_valid & ATTR_UID) {
-		owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name, IDMAP_NAMESZ);
+		owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
 		if (owner_namelen < 0) {
 			dprintk("nfs: couldn't resolve uid %d to string\n",
 					iap->ia_uid);
@@ -856,7 +856,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
 		len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
 	}
 	if (iap->ia_valid & ATTR_GID) {
-		owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group, IDMAP_NAMESZ);
+		owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
 		if (owner_grouplen < 0) {
 			dprintk("nfs: couldn't resolve gid %d to string\n",
 					iap->ia_gid);
@@ -1384,7 +1384,7 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
 	hdr->replen += decode_putrootfh_maxsz;
 }
 
-static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx)
+static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx, int zero_seqid)
 {
 	nfs4_stateid stateid;
 	__be32 *p;
@@ -1392,6 +1392,8 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context
 	p = reserve_space(xdr, NFS4_STATEID_SIZE);
 	if (ctx->state != NULL) {
 		nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid);
+		if (zero_seqid)
+			stateid.stateid.seqid = 0;
 		xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
 	} else
 		xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
@@ -1404,7 +1406,8 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
 	p = reserve_space(xdr, 4);
 	*p = cpu_to_be32(OP_READ);
 
-	encode_stateid(xdr, args->context, args->lock_context);
+	encode_stateid(xdr, args->context, args->lock_context,
+		       hdr->minorversion);
 
 	p = reserve_space(xdr, 12);
 	p = xdr_encode_hyper(p, args->offset);
@@ -1592,7 +1595,8 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
 	p = reserve_space(xdr, 4);
 	*p = cpu_to_be32(OP_WRITE);
 
-	encode_stateid(xdr, args->context, args->lock_context);
+	encode_stateid(xdr, args->context, args->lock_context,
+		       hdr->minorversion);
 
 	p = reserve_space(xdr, 16);
 	p = xdr_encode_hyper(p, args->offset);
@@ -2271,7 +2275,8 @@ static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr,
 	encode_putfh(xdr, args->fh, &hdr);
 	encode_write(xdr, args, &hdr);
 	req->rq_snd_buf.flags |= XDRBUF_WRITE;
-	encode_getfattr(xdr, args->bitmask, &hdr);
+	if (args->bitmask)
+		encode_getfattr(xdr, args->bitmask, &hdr);
 	encode_nops(&hdr);
 }
 
@@ -3382,7 +3387,7 @@ out_overflow:
 }
 
 static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
-		struct nfs_client *clp, uint32_t *uid, int may_sleep)
+		const struct nfs_server *server, uint32_t *uid, int may_sleep)
 {
 	uint32_t len;
 	__be32 *p;
@@ -3402,7 +3407,7 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
 		if (!may_sleep) {
 			/* do nothing */
 		} else if (len < XDR_MAX_NETOBJ) {
-			if (nfs_map_name_to_uid(clp, (char *)p, len, uid) == 0)
+			if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0)
 				ret = NFS_ATTR_FATTR_OWNER;
 			else
 				dprintk("%s: nfs_map_name_to_uid failed!\n",
@@ -3420,7 +3425,7 @@ out_overflow:
 }
 
 static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
-		struct nfs_client *clp, uint32_t *gid, int may_sleep)
+		const struct nfs_server *server, uint32_t *gid, int may_sleep)
 {
 	uint32_t len;
 	__be32 *p;
@@ -3440,7 +3445,7 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
 		if (!may_sleep) {
 			/* do nothing */
 		} else if (len < XDR_MAX_NETOBJ) {
-			if (nfs_map_group_to_gid(clp, (char *)p, len, gid) == 0)
+			if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0)
 				ret = NFS_ATTR_FATTR_GROUP;
 			else
 				dprintk("%s: nfs_map_group_to_gid failed!\n",
@@ -3939,14 +3944,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
 		goto xdr_error;
 	fattr->valid |= status;
 
-	status = decode_attr_owner(xdr, bitmap, server->nfs_client,
-			&fattr->uid, may_sleep);
+	status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep);
 	if (status < 0)
 		goto xdr_error;
 	fattr->valid |= status;
 
-	status = decode_attr_group(xdr, bitmap, server->nfs_client,
-			&fattr->gid, may_sleep);
+	status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep);
 	if (status < 0)
 		goto xdr_error;
 	fattr->valid |= status;
@@ -5690,8 +5693,9 @@ static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
 	status = decode_write(xdr, res);
 	if (status)
 		goto out;
-	decode_getfattr(xdr, res->fattr, res->server,
-			!RPC_IS_ASYNC(rqstp->rq_task));
+	if (res->fattr)
+		decode_getfattr(xdr, res->fattr, res->server,
+				!RPC_IS_ASYNC(rqstp->rq_task));
 	if (!status)
 		status = res->count;
 out:
@@ -6167,8 +6171,6 @@ static struct {
 	{ NFS4ERR_DQUOT,	-EDQUOT		},
 	{ NFS4ERR_STALE,	-ESTALE		},
 	{ NFS4ERR_BADHANDLE,	-EBADHANDLE	},
-	{ NFS4ERR_BADOWNER,	-EINVAL		},
-	{ NFS4ERR_BADNAME,	-EINVAL		},
 	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
 	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
 	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index e1164e3..23e7944 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -20,6 +20,7 @@
 #include <linux/nfs_mount.h>
 
 #include "internal.h"
+#include "pnfs.h"
 
 static struct kmem_cache *nfs_page_cachep;
 
@@ -213,7 +214,7 @@ nfs_wait_on_request(struct nfs_page *req)
  */
 void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 		     struct inode *inode,
-		     int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+		     int (*doio)(struct nfs_pageio_descriptor *),
 		     size_t bsize,
 		     int io_flags)
 {
@@ -226,6 +227,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 	desc->pg_doio = doio;
 	desc->pg_ioflags = io_flags;
 	desc->pg_error = 0;
+	desc->pg_lseg = NULL;
 }
 
 /**
@@ -240,7 +242,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
  * Return 'true' if this is the case, else return 'false'.
  */
 static int nfs_can_coalesce_requests(struct nfs_page *prev,
-				     struct nfs_page *req)
+				     struct nfs_page *req,
+				     struct nfs_pageio_descriptor *pgio)
 {
 	if (req->wb_context->cred != prev->wb_context->cred)
 		return 0;
@@ -254,6 +257,12 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev,
 		return 0;
 	if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
 		return 0;
+	/*
+	 * Non-whole file layouts need to check that req is inside of
+	 * pgio->pg_lseg.
+	 */
+	if (pgio->pg_test && !pgio->pg_test(pgio, prev, req))
+		return 0;
 	return 1;
 }
 
@@ -286,7 +295,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
 		if (newlen > desc->pg_bsize)
 			return 0;
 		prev = nfs_list_entry(desc->pg_list.prev);
-		if (!nfs_can_coalesce_requests(prev, req))
+		if (!nfs_can_coalesce_requests(prev, req, desc))
 			return 0;
 	} else
 		desc->pg_base = req->wb_pgbase;
@@ -302,12 +311,7 @@ static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
 static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
 {
 	if (!list_empty(&desc->pg_list)) {
-		int error = desc->pg_doio(desc->pg_inode,
-					  &desc->pg_list,
-					  nfs_page_array_len(desc->pg_base,
-							     desc->pg_count),
-					  desc->pg_count,
-					  desc->pg_ioflags);
+		int error = desc->pg_doio(desc);
 		if (error < 0)
 			desc->pg_error = error;
 		else
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 1b1bc1a..f38813a 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -30,6 +30,7 @@
 #include <linux/nfs_fs.h>
 #include "internal.h"
 #include "pnfs.h"
+#include "iostat.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PNFS
 
@@ -74,10 +75,8 @@ find_pnfs_driver(u32 id)
 void
 unset_pnfs_layoutdriver(struct nfs_server *nfss)
 {
-	if (nfss->pnfs_curr_ld) {
-		nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
+	if (nfss->pnfs_curr_ld)
 		module_put(nfss->pnfs_curr_ld->owner);
-	}
 	nfss->pnfs_curr_ld = NULL;
 }
 
@@ -115,13 +114,7 @@ set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
 		goto out_no_driver;
 	}
 	server->pnfs_curr_ld = ld_type;
-	if (ld_type->set_layoutdriver(server)) {
-		printk(KERN_ERR
-		       "%s: Error initializing mount point for layout driver %u.\n",
-		       __func__, id);
-		module_put(ld_type->owner);
-		goto out_no_driver;
-	}
+
 	dprintk("%s: pNFS module for %u set\n", __func__, id);
 	return;
 
@@ -230,37 +223,41 @@ static void free_lseg(struct pnfs_layout_segment *lseg)
 	put_layout_hdr(NFS_I(ino)->layout);
 }
 
-/* The use of tmp_list is necessary because pnfs_curr_ld->free_lseg
- * could sleep, so must be called outside of the lock.
- * Returns 1 if object was removed, otherwise return 0.
- */
-static int
-put_lseg_locked(struct pnfs_layout_segment *lseg,
-		struct list_head *tmp_list)
+static void
+put_lseg_common(struct pnfs_layout_segment *lseg)
+{
+	struct inode *inode = lseg->pls_layout->plh_inode;
+
+	BUG_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
+	list_del_init(&lseg->pls_list);
+	if (list_empty(&lseg->pls_layout->plh_segs)) {
+		set_bit(NFS_LAYOUT_DESTROYED, &lseg->pls_layout->plh_flags);
+		/* Matched by initial refcount set in alloc_init_layout_hdr */
+		put_layout_hdr_locked(lseg->pls_layout);
+	}
+	rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
+}
+
+void
+put_lseg(struct pnfs_layout_segment *lseg)
 {
+	struct inode *inode;
+
+	if (!lseg)
+		return;
+
 	dprintk("%s: lseg %p ref %d valid %d\n", __func__, lseg,
 		atomic_read(&lseg->pls_refcount),
 		test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
-	if (atomic_dec_and_test(&lseg->pls_refcount)) {
-		struct inode *ino = lseg->pls_layout->plh_inode;
+	inode = lseg->pls_layout->plh_inode;
+	if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
+		LIST_HEAD(free_me);
 
-		BUG_ON(test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
-		list_del(&lseg->pls_list);
-		if (list_empty(&lseg->pls_layout->plh_segs)) {
-			struct nfs_client *clp;
-
-			clp = NFS_SERVER(ino)->nfs_client;
-			spin_lock(&clp->cl_lock);
-			/* List does not take a reference, so no need for put here */
-			list_del_init(&lseg->pls_layout->plh_layouts);
-			spin_unlock(&clp->cl_lock);
-			clear_bit(NFS_LAYOUT_BULK_RECALL, &lseg->pls_layout->plh_flags);
-		}
-		rpc_wake_up(&NFS_SERVER(ino)->roc_rpcwaitq);
-		list_add(&lseg->pls_list, tmp_list);
-		return 1;
+		put_lseg_common(lseg);
+		list_add(&lseg->pls_list, &free_me);
+		spin_unlock(&inode->i_lock);
+		pnfs_free_lseg_list(&free_me);
 	}
-	return 0;
 }
 
 static bool
@@ -281,7 +278,13 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
 		 * list.  It will now be removed when all
 		 * outstanding io is finished.
 		 */
-		rv = put_lseg_locked(lseg, tmp_list);
+		dprintk("%s: lseg %p ref %d\n", __func__, lseg,
+			atomic_read(&lseg->pls_refcount));
+		if (atomic_dec_and_test(&lseg->pls_refcount)) {
+			put_lseg_common(lseg);
+			list_add(&lseg->pls_list, tmp_list);
+			rv = 1;
+		}
 	}
 	return rv;
 }
@@ -299,6 +302,11 @@ mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
 
 	dprintk("%s:Begin lo %p\n", __func__, lo);
 
+	if (list_empty(&lo->plh_segs)) {
+		if (!test_and_set_bit(NFS_LAYOUT_DESTROYED, &lo->plh_flags))
+			put_layout_hdr_locked(lo);
+		return 0;
+	}
 	list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
 		if (should_free_lseg(lseg->pls_range.iomode, iomode)) {
 			dprintk("%s: freeing lseg %p iomode %d "
@@ -312,11 +320,27 @@ mark_matching_lsegs_invalid(struct pnfs_layout_hdr *lo,
 	return invalid - removed;
 }
 
+/* note free_me must contain lsegs from a single layout_hdr */
 void
 pnfs_free_lseg_list(struct list_head *free_me)
 {
 	struct pnfs_layout_segment *lseg, *tmp;
+	struct pnfs_layout_hdr *lo;
+
+	if (list_empty(free_me))
+		return;
 
+	lo = list_first_entry(free_me, struct pnfs_layout_segment,
+			      pls_list)->pls_layout;
+
+	if (test_bit(NFS_LAYOUT_DESTROYED, &lo->plh_flags)) {
+		struct nfs_client *clp;
+
+		clp = NFS_SERVER(lo->plh_inode)->nfs_client;
+		spin_lock(&clp->cl_lock);
+		list_del_init(&lo->plh_layouts);
+		spin_unlock(&clp->cl_lock);
+	}
 	list_for_each_entry_safe(lseg, tmp, free_me, pls_list) {
 		list_del(&lseg->pls_list);
 		free_lseg(lseg);
@@ -332,10 +356,8 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
 	spin_lock(&nfsi->vfs_inode.i_lock);
 	lo = nfsi->layout;
 	if (lo) {
-		set_bit(NFS_LAYOUT_DESTROYED, &nfsi->layout->plh_flags);
+		lo->plh_block_lgets++; /* permanently block new LAYOUTGETs */
 		mark_matching_lsegs_invalid(lo, &tmp_list, IOMODE_ANY);
-		/* Matched by refcount set to 1 in alloc_init_layout_hdr */
-		put_layout_hdr_locked(lo);
 	}
 	spin_unlock(&nfsi->vfs_inode.i_lock);
 	pnfs_free_lseg_list(&tmp_list);
@@ -403,6 +425,7 @@ pnfs_layoutgets_blocked(struct pnfs_layout_hdr *lo, nfs4_stateid *stateid,
 	    (int)(lo->plh_barrier - be32_to_cpu(stateid->stateid.seqid)) >= 0)
 		return true;
 	return lo->plh_block_lgets ||
+		test_bit(NFS_LAYOUT_DESTROYED, &lo->plh_flags) ||
 		test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags) ||
 		(list_empty(&lo->plh_segs) &&
 		 (atomic_read(&lo->plh_outstanding) > lget));
@@ -674,7 +697,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)
 	list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
 		if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags) &&
 		    is_matching_lseg(lseg, iomode)) {
-			ret = lseg;
+			ret = get_lseg(lseg);
 			break;
 		}
 		if (cmp_layout(iomode, lseg->pls_range.iomode) > 0)
@@ -699,6 +722,7 @@ pnfs_update_layout(struct inode *ino,
 	struct nfs_client *clp = NFS_SERVER(ino)->nfs_client;
 	struct pnfs_layout_hdr *lo;
 	struct pnfs_layout_segment *lseg = NULL;
+	bool first = false;
 
 	if (!pnfs_enabled_sb(NFS_SERVER(ino)))
 		return NULL;
@@ -715,21 +739,25 @@ pnfs_update_layout(struct inode *ino,
 		dprintk("%s matches recall, use MDS\n", __func__);
 		goto out_unlock;
 	}
-	/* Check to see if the layout for the given range already exists */
-	lseg = pnfs_find_lseg(lo, iomode);
-	if (lseg)
-		goto out_unlock;
 
 	/* if LAYOUTGET already failed once we don't try again */
 	if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags))
 		goto out_unlock;
 
+	/* Check to see if the layout for the given range already exists */
+	lseg = pnfs_find_lseg(lo, iomode);
+	if (lseg)
+		goto out_unlock;
+
 	if (pnfs_layoutgets_blocked(lo, NULL, 0))
 		goto out_unlock;
 	atomic_inc(&lo->plh_outstanding);
 
 	get_layout_hdr(lo);
-	if (list_empty(&lo->plh_segs)) {
+	if (list_empty(&lo->plh_segs))
+		first = true;
+	spin_unlock(&ino->i_lock);
+	if (first) {
 		/* The lo must be on the clp list if there is any
 		 * chance of a CB_LAYOUTRECALL(FILE) coming in.
 		 */
@@ -738,24 +766,18 @@ pnfs_update_layout(struct inode *ino,
 		list_add_tail(&lo->plh_layouts, &clp->cl_layouts);
 		spin_unlock(&clp->cl_lock);
 	}
-	spin_unlock(&ino->i_lock);
 
 	lseg = send_layoutget(lo, ctx, iomode);
-	if (!lseg) {
-		spin_lock(&ino->i_lock);
-		if (list_empty(&lo->plh_segs)) {
-			spin_lock(&clp->cl_lock);
-			list_del_init(&lo->plh_layouts);
-			spin_unlock(&clp->cl_lock);
-			clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
-		}
-		spin_unlock(&ino->i_lock);
+	if (!lseg && first) {
+		spin_lock(&clp->cl_lock);
+		list_del_init(&lo->plh_layouts);
+		spin_unlock(&clp->cl_lock);
 	}
 	atomic_dec(&lo->plh_outstanding);
 	put_layout_hdr(lo);
 out:
 	dprintk("%s end, state 0x%lx lseg %p\n", __func__,
-		nfsi->layout->plh_flags, lseg);
+		nfsi->layout ? nfsi->layout->plh_flags : -1, lseg);
 	return lseg;
 out_unlock:
 	spin_unlock(&ino->i_lock);
@@ -808,7 +830,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
 	}
 	init_lseg(lo, lseg);
 	lseg->pls_range = res->range;
-	*lgp->lsegpp = lseg;
+	*lgp->lsegpp = get_lseg(lseg);
 	pnfs_insert_layout(lo, lseg);
 
 	if (res->return_on_close) {
@@ -829,137 +851,97 @@ out_forget_reply:
 	goto out;
 }
 
-/*
- * Device ID cache. Currently supports one layout type per struct nfs_client.
- * Add layout type to the lookup key to expand to support multiple types.
- */
-int
-pnfs_alloc_init_deviceid_cache(struct nfs_client *clp,
-			 void (*free_callback)(struct pnfs_deviceid_node *))
+static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio,
+			     struct nfs_page *prev,
+			     struct nfs_page *req)
 {
-	struct pnfs_deviceid_cache *c;
-
-	c = kzalloc(sizeof(struct pnfs_deviceid_cache), GFP_KERNEL);
-	if (!c)
-		return -ENOMEM;
-	spin_lock(&clp->cl_lock);
-	if (clp->cl_devid_cache != NULL) {
-		atomic_inc(&clp->cl_devid_cache->dc_ref);
-		dprintk("%s [kref [%d]]\n", __func__,
-			atomic_read(&clp->cl_devid_cache->dc_ref));
-		kfree(c);
-	} else {
-		/* kzalloc initializes hlists */
-		spin_lock_init(&c->dc_lock);
-		atomic_set(&c->dc_ref, 1);
-		c->dc_free_callback = free_callback;
-		clp->cl_devid_cache = c;
-		dprintk("%s [new]\n", __func__);
+	if (pgio->pg_count == prev->wb_bytes) {
+		/* This is first coelesce call for a series of nfs_pages */
+		pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+						   prev->wb_context,
+						   IOMODE_READ);
 	}
-	spin_unlock(&clp->cl_lock);
-	return 0;
+	return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
 }
-EXPORT_SYMBOL_GPL(pnfs_alloc_init_deviceid_cache);
 
-/*
- * Called from pnfs_layoutdriver_type->free_lseg
- * last layout segment reference frees deviceid
- */
 void
-pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
-		  struct pnfs_deviceid_node *devid)
+pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode)
 {
-	struct nfs4_deviceid *id = &devid->de_id;
-	struct pnfs_deviceid_node *d;
-	struct hlist_node *n;
-	long h = nfs4_deviceid_hash(id);
+	struct pnfs_layoutdriver_type *ld;
 
-	dprintk("%s [%d]\n", __func__, atomic_read(&devid->de_ref));
-	if (!atomic_dec_and_lock(&devid->de_ref, &c->dc_lock))
-		return;
+	ld = NFS_SERVER(inode)->pnfs_curr_ld;
+	pgio->pg_test = (ld && ld->pg_test) ? pnfs_read_pg_test : NULL;
+}
 
-	hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[h], de_node)
-		if (!memcmp(&d->de_id, id, sizeof(*id))) {
-			hlist_del_rcu(&d->de_node);
-			spin_unlock(&c->dc_lock);
-			synchronize_rcu();
-			c->dc_free_callback(devid);
-			return;
-		}
-	spin_unlock(&c->dc_lock);
-	/* Why wasn't it found in  the list? */
-	BUG();
-}
-EXPORT_SYMBOL_GPL(pnfs_put_deviceid);
-
-/* Find and reference a deviceid */
-struct pnfs_deviceid_node *
-pnfs_find_get_deviceid(struct pnfs_deviceid_cache *c, struct nfs4_deviceid *id)
-{
-	struct pnfs_deviceid_node *d;
-	struct hlist_node *n;
-	long hash = nfs4_deviceid_hash(id);
-
-	dprintk("--> %s hash %ld\n", __func__, hash);
-	rcu_read_lock();
-	hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[hash], de_node) {
-		if (!memcmp(&d->de_id, id, sizeof(*id))) {
-			if (!atomic_inc_not_zero(&d->de_ref)) {
-				goto fail;
-			} else {
-				rcu_read_unlock();
-				return d;
-			}
-		}
+static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio,
+			      struct nfs_page *prev,
+			      struct nfs_page *req)
+{
+	if (pgio->pg_count == prev->wb_bytes) {
+		/* This is first coelesce call for a series of nfs_pages */
+		pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
+						   prev->wb_context,
+						   IOMODE_RW);
 	}
-fail:
-	rcu_read_unlock();
-	return NULL;
+	return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
+}
+
+void
+pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode)
+{
+	struct pnfs_layoutdriver_type *ld;
+
+	ld = NFS_SERVER(inode)->pnfs_curr_ld;
+	pgio->pg_test = (ld && ld->pg_test) ? pnfs_write_pg_test : NULL;
+}
+
+enum pnfs_try_status
+pnfs_try_to_write_data(struct nfs_write_data *wdata,
+			const struct rpc_call_ops *call_ops, int how)
+{
+	struct inode *inode = wdata->inode;
+	enum pnfs_try_status trypnfs;
+	struct nfs_server *nfss = NFS_SERVER(inode);
+
+	wdata->mds_ops = call_ops;
+
+	dprintk("%s: Writing ino:%lu %u@%llu (how %d)\n", __func__,
+		inode->i_ino, wdata->args.count, wdata->args.offset, how);
+
+	trypnfs = nfss->pnfs_curr_ld->write_pagelist(wdata, how);
+	if (trypnfs == PNFS_NOT_ATTEMPTED) {
+		put_lseg(wdata->lseg);
+		wdata->lseg = NULL;
+	} else
+		nfs_inc_stats(inode, NFSIOS_PNFS_WRITE);
+
+	dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
+	return trypnfs;
 }
-EXPORT_SYMBOL_GPL(pnfs_find_get_deviceid);
 
 /*
- * Add a deviceid to the cache.
- * GETDEVICEINFOs for same deviceid can race. If deviceid is found, discard new
+ * Call the appropriate parallel I/O subsystem read function.
  */
-struct pnfs_deviceid_node *
-pnfs_add_deviceid(struct pnfs_deviceid_cache *c, struct pnfs_deviceid_node *new)
-{
-	struct pnfs_deviceid_node *d;
-	long hash = nfs4_deviceid_hash(&new->de_id);
-
-	dprintk("--> %s hash %ld\n", __func__, hash);
-	spin_lock(&c->dc_lock);
-	d = pnfs_find_get_deviceid(c, &new->de_id);
-	if (d) {
-		spin_unlock(&c->dc_lock);
-		dprintk("%s [discard]\n", __func__);
-		c->dc_free_callback(new);
-		return d;
-	}
-	INIT_HLIST_NODE(&new->de_node);
-	atomic_set(&new->de_ref, 1);
-	hlist_add_head_rcu(&new->de_node, &c->dc_deviceids[hash]);
-	spin_unlock(&c->dc_lock);
-	dprintk("%s [new]\n", __func__);
-	return new;
-}
-EXPORT_SYMBOL_GPL(pnfs_add_deviceid);
-
-void
-pnfs_put_deviceid_cache(struct nfs_client *clp)
+enum pnfs_try_status
+pnfs_try_to_read_data(struct nfs_read_data *rdata,
+		       const struct rpc_call_ops *call_ops)
 {
-	struct pnfs_deviceid_cache *local = clp->cl_devid_cache;
+	struct inode *inode = rdata->inode;
+	struct nfs_server *nfss = NFS_SERVER(inode);
+	enum pnfs_try_status trypnfs;
 
-	dprintk("--> %s ({%d})\n", __func__, atomic_read(&local->dc_ref));
-	if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) {
-		int i;
-		/* Verify cache is empty */
-		for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i++)
-			BUG_ON(!hlist_empty(&local->dc_deviceids[i]));
-		clp->cl_devid_cache = NULL;
-		spin_unlock(&clp->cl_lock);
-		kfree(local);
+	rdata->mds_ops = call_ops;
+
+	dprintk("%s: Reading ino:%lu %u@%llu\n",
+		__func__, inode->i_ino, rdata->args.count, rdata->args.offset);
+
+	trypnfs = nfss->pnfs_curr_ld->read_pagelist(rdata);
+	if (trypnfs == PNFS_NOT_ATTEMPTED) {
+		put_lseg(rdata->lseg);
+		rdata->lseg = NULL;
+	} else {
+		nfs_inc_stats(inode, NFSIOS_PNFS_READ);
 	}
+	dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
+	return trypnfs;
 }
-EXPORT_SYMBOL_GPL(pnfs_put_deviceid_cache);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index e2612ea..6380b94 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -30,6 +30,8 @@
 #ifndef FS_NFS_PNFS_H
 #define FS_NFS_PNFS_H
 
+#include <linux/nfs_page.h>
+
 enum {
 	NFS_LSEG_VALID = 0,	/* cleared when lseg is recalled/returned */
 	NFS_LSEG_ROC,		/* roc bit received from server */
@@ -43,6 +45,11 @@ struct pnfs_layout_segment {
 	struct pnfs_layout_hdr *pls_layout;
 };
 
+enum pnfs_try_status {
+	PNFS_ATTEMPTED     = 0,
+	PNFS_NOT_ATTEMPTED = 1,
+};
+
 #ifdef CONFIG_NFS_V4_1
 
 #define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"
@@ -61,10 +68,18 @@ struct pnfs_layoutdriver_type {
 	const u32 id;
 	const char *name;
 	struct module *owner;
-	int (*set_layoutdriver) (struct nfs_server *);
-	int (*clear_layoutdriver) (struct nfs_server *);
 	struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr);
 	void (*free_lseg) (struct pnfs_layout_segment *lseg);
+
+	/* test for nfs page cache coalescing */
+	int (*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
+
+	/*
+	 * Return PNFS_ATTEMPTED to indicate the layout code has attempted
+	 * I/O, else return PNFS_NOT_ATTEMPTED to fall back to normal NFS
+	 */
+	enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data);
+	enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data, int how);
 };
 
 struct pnfs_layout_hdr {
@@ -90,52 +105,6 @@ struct pnfs_device {
 	unsigned int  pglen;
 };
 
-/*
- * Device ID RCU cache. A device ID is unique per client ID and layout type.
- */
-#define NFS4_DEVICE_ID_HASH_BITS	5
-#define NFS4_DEVICE_ID_HASH_SIZE	(1 << NFS4_DEVICE_ID_HASH_BITS)
-#define NFS4_DEVICE_ID_HASH_MASK	(NFS4_DEVICE_ID_HASH_SIZE - 1)
-
-static inline u32
-nfs4_deviceid_hash(struct nfs4_deviceid *id)
-{
-	unsigned char *cptr = (unsigned char *)id->data;
-	unsigned int nbytes = NFS4_DEVICEID4_SIZE;
-	u32 x = 0;
-
-	while (nbytes--) {
-		x *= 37;
-		x += *cptr++;
-	}
-	return x & NFS4_DEVICE_ID_HASH_MASK;
-}
-
-struct pnfs_deviceid_node {
-	struct hlist_node	de_node;
-	struct nfs4_deviceid	de_id;
-	atomic_t		de_ref;
-};
-
-struct pnfs_deviceid_cache {
-	spinlock_t		dc_lock;
-	atomic_t		dc_ref;
-	void			(*dc_free_callback)(struct pnfs_deviceid_node *);
-	struct hlist_head	dc_deviceids[NFS4_DEVICE_ID_HASH_SIZE];
-};
-
-extern int pnfs_alloc_init_deviceid_cache(struct nfs_client *,
-			void (*free_callback)(struct pnfs_deviceid_node *));
-extern void pnfs_put_deviceid_cache(struct nfs_client *);
-extern struct pnfs_deviceid_node *pnfs_find_get_deviceid(
-				struct pnfs_deviceid_cache *,
-				struct nfs4_deviceid *);
-extern struct pnfs_deviceid_node *pnfs_add_deviceid(
-				struct pnfs_deviceid_cache *,
-				struct pnfs_deviceid_node *);
-extern void pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
-			      struct pnfs_deviceid_node *devid);
-
 extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
 extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
 
@@ -146,11 +115,18 @@ extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
 
 /* pnfs.c */
 void get_layout_hdr(struct pnfs_layout_hdr *lo);
+void put_lseg(struct pnfs_layout_segment *lseg);
 struct pnfs_layout_segment *
 pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
 		   enum pnfs_iomode access_type);
 void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
 void unset_pnfs_layoutdriver(struct nfs_server *);
+enum pnfs_try_status pnfs_try_to_write_data(struct nfs_write_data *,
+					     const struct rpc_call_ops *, int);
+enum pnfs_try_status pnfs_try_to_read_data(struct nfs_read_data *,
+					    const struct rpc_call_ops *);
+void pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *);
+void pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *);
 int pnfs_layout_process(struct nfs4_layoutget *lgp);
 void pnfs_free_lseg_list(struct list_head *tmp_list);
 void pnfs_destroy_layout(struct nfs_inode *);
@@ -177,6 +153,16 @@ static inline int lo_fail_bit(u32 iomode)
 			 NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
 }
 
+static inline struct pnfs_layout_segment *
+get_lseg(struct pnfs_layout_segment *lseg)
+{
+	if (lseg) {
+		atomic_inc(&lseg->pls_refcount);
+		smp_mb__after_atomic_inc();
+	}
+	return lseg;
+}
+
 /* Return true if a layout driver is being used for this mountpoint */
 static inline int pnfs_enabled_sb(struct nfs_server *nfss)
 {
@@ -194,12 +180,36 @@ static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
 }
 
 static inline struct pnfs_layout_segment *
+get_lseg(struct pnfs_layout_segment *lseg)
+{
+	return NULL;
+}
+
+static inline void put_lseg(struct pnfs_layout_segment *lseg)
+{
+}
+
+static inline struct pnfs_layout_segment *
 pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
 		   enum pnfs_iomode access_type)
 {
 	return NULL;
 }
 
+static inline enum pnfs_try_status
+pnfs_try_to_read_data(struct nfs_read_data *data,
+		      const struct rpc_call_ops *call_ops)
+{
+	return PNFS_NOT_ATTEMPTED;
+}
+
+static inline enum pnfs_try_status
+pnfs_try_to_write_data(struct nfs_write_data *data,
+		       const struct rpc_call_ops *call_ops, int how)
+{
+	return PNFS_NOT_ATTEMPTED;
+}
+
 static inline bool
 pnfs_roc(struct inode *ino)
 {
@@ -230,6 +240,18 @@ static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
 {
 }
 
+static inline void
+pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *ino)
+{
+	pgio->pg_test = NULL;
+}
+
+static inline void
+pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *ino)
+{
+	pgio->pg_test = NULL;
+}
+
 #endif /* CONFIG_NFS_V4_1 */
 
 #endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 77d5e21..b8ec170 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -741,4 +741,5 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
 	.lock		= nfs_proc_lock,
 	.lock_check_bounds = nfs_lock_check_bounds,
 	.close_context	= nfs_close_context,
+	.init_client	= nfs_init_client,
 };
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index aedcaa7..7cded2b 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -18,19 +18,20 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
+#include "pnfs.h"
 
 #include "nfs4_fs.h"
 #include "internal.h"
 #include "iostat.h"
 #include "fscache.h"
-#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
-static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int);
-static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int);
+static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc);
+static int nfs_pagein_one(struct nfs_pageio_descriptor *desc);
 static const struct rpc_call_ops nfs_read_partial_ops;
 static const struct rpc_call_ops nfs_read_full_ops;
 
@@ -69,6 +70,7 @@ void nfs_readdata_free(struct nfs_read_data *p)
 
 static void nfs_readdata_release(struct nfs_read_data *rdata)
 {
+	put_lseg(rdata->lseg);
 	put_nfs_open_context(rdata->args.context);
 	nfs_readdata_free(rdata);
 }
@@ -114,14 +116,13 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
 int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
 		       struct page *page)
 {
-	LIST_HEAD(one_request);
 	struct nfs_page	*new;
 	unsigned int len;
+	struct nfs_pageio_descriptor pgio;
 
 	len = nfs_page_length(page);
 	if (len == 0)
 		return nfs_return_empty_page(page);
-	pnfs_update_layout(inode, ctx, IOMODE_READ);
 	new = nfs_create_request(ctx, inode, page, 0, len);
 	if (IS_ERR(new)) {
 		unlock_page(page);
@@ -130,11 +131,14 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
 	if (len < PAGE_CACHE_SIZE)
 		zero_user_segment(page, len, PAGE_CACHE_SIZE);
 
-	nfs_list_add_request(new, &one_request);
+	nfs_pageio_init(&pgio, inode, NULL, 0, 0);
+	nfs_list_add_request(new, &pgio.pg_list);
+	pgio.pg_count = len;
+
 	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
-		nfs_pagein_multi(inode, &one_request, 1, len, 0);
+		nfs_pagein_multi(&pgio);
 	else
-		nfs_pagein_one(inode, &one_request, 1, len, 0);
+		nfs_pagein_one(&pgio);
 	return 0;
 }
 
@@ -155,24 +159,20 @@ static void nfs_readpage_release(struct nfs_page *req)
 	nfs_release_request(req);
 }
 
-/*
- * Set up the NFS read request struct
- */
-static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
-		const struct rpc_call_ops *call_ops,
-		unsigned int count, unsigned int offset)
+int nfs_initiate_read(struct nfs_read_data *data, struct rpc_clnt *clnt,
+		      const struct rpc_call_ops *call_ops)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct inode *inode = data->inode;
 	int swap_flags = IS_SWAPFILE(inode) ? NFS_RPC_SWAPFLAGS : 0;
 	struct rpc_task *task;
 	struct rpc_message msg = {
 		.rpc_argp = &data->args,
 		.rpc_resp = &data->res,
-		.rpc_cred = req->wb_context->cred,
+		.rpc_cred = data->cred,
 	};
 	struct rpc_task_setup task_setup_data = {
 		.task = &data->task,
-		.rpc_client = NFS_CLIENT(inode),
+		.rpc_client = clnt,
 		.rpc_message = &msg,
 		.callback_ops = call_ops,
 		.callback_data = data,
@@ -180,9 +180,39 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
 		.flags = RPC_TASK_ASYNC | swap_flags,
 	};
 
+	/* Set up the initial task struct. */
+	NFS_PROTO(inode)->read_setup(data, &msg);
+
+	dprintk("NFS: %5u initiated read call (req %s/%lld, %u bytes @ "
+			"offset %llu)\n",
+			data->task.tk_pid,
+			inode->i_sb->s_id,
+			(long long)NFS_FILEID(inode),
+			data->args.count,
+			(unsigned long long)data->args.offset);
+
+	task = rpc_run_task(&task_setup_data);
+	if (IS_ERR(task))
+		return PTR_ERR(task);
+	rpc_put_task(task);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nfs_initiate_read);
+
+/*
+ * Set up the NFS read request struct
+ */
+static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
+		const struct rpc_call_ops *call_ops,
+		unsigned int count, unsigned int offset,
+		struct pnfs_layout_segment *lseg)
+{
+	struct inode *inode = req->wb_context->path.dentry->d_inode;
+
 	data->req	  = req;
 	data->inode	  = inode;
-	data->cred	  = msg.rpc_cred;
+	data->cred	  = req->wb_context->cred;
+	data->lseg	  = get_lseg(lseg);
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
@@ -197,21 +227,11 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
 	data->res.eof     = 0;
 	nfs_fattr_init(&data->fattr);
 
-	/* Set up the initial task struct. */
-	NFS_PROTO(inode)->read_setup(data, &msg);
-
-	dprintk("NFS: %5u initiated read call (req %s/%Ld, %u bytes @ offset %Lu)\n",
-			data->task.tk_pid,
-			inode->i_sb->s_id,
-			(long long)NFS_FILEID(inode),
-			count,
-			(unsigned long long)data->args.offset);
+	if (data->lseg &&
+	    (pnfs_try_to_read_data(data, call_ops) == PNFS_ATTEMPTED))
+		return 0;
 
-	task = rpc_run_task(&task_setup_data);
-	if (IS_ERR(task))
-		return PTR_ERR(task);
-	rpc_put_task(task);
-	return 0;
+	return nfs_initiate_read(data, NFS_CLIENT(inode), call_ops);
 }
 
 static void
@@ -240,20 +260,21 @@ nfs_async_read_error(struct list_head *head)
  * won't see the new data until our attribute cache is updated.  This is more
  * or less conventional NFS client behavior.
  */
-static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
+static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc)
 {
-	struct nfs_page *req = nfs_list_entry(head->next);
+	struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
 	struct page *page = req->wb_page;
 	struct nfs_read_data *data;
-	size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
+	size_t rsize = NFS_SERVER(desc->pg_inode)->rsize, nbytes;
 	unsigned int offset;
 	int requests = 0;
 	int ret = 0;
+	struct pnfs_layout_segment *lseg;
 	LIST_HEAD(list);
 
 	nfs_list_remove_request(req);
 
-	nbytes = count;
+	nbytes = desc->pg_count;
 	do {
 		size_t len = min(nbytes,rsize);
 
@@ -266,9 +287,11 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
 	} while(nbytes != 0);
 	atomic_set(&req->wb_complete, requests);
 
+	BUG_ON(desc->pg_lseg != NULL);
+	lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ);
 	ClearPageError(page);
 	offset = 0;
-	nbytes = count;
+	nbytes = desc->pg_count;
 	do {
 		int ret2;
 
@@ -280,12 +303,14 @@ static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigne
 		if (nbytes < rsize)
 			rsize = nbytes;
 		ret2 = nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
-				  rsize, offset);
+					 rsize, offset, lseg);
 		if (ret == 0)
 			ret = ret2;
 		offset += rsize;
 		nbytes -= rsize;
 	} while (nbytes != 0);
+	put_lseg(lseg);
+	desc->pg_lseg = NULL;
 
 	return ret;
 
@@ -300,16 +325,21 @@ out_bad:
 	return -ENOMEM;
 }
 
-static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
+static int nfs_pagein_one(struct nfs_pageio_descriptor *desc)
 {
 	struct nfs_page		*req;
 	struct page		**pages;
 	struct nfs_read_data	*data;
+	struct list_head *head = &desc->pg_list;
+	struct pnfs_layout_segment *lseg = desc->pg_lseg;
 	int ret = -ENOMEM;
 
-	data = nfs_readdata_alloc(npages);
-	if (!data)
-		goto out_bad;
+	data = nfs_readdata_alloc(nfs_page_array_len(desc->pg_base,
+						     desc->pg_count));
+	if (!data) {
+		nfs_async_read_error(head);
+		goto out;
+	}
 
 	pages = data->pagevec;
 	while (!list_empty(head)) {
@@ -320,10 +350,14 @@ static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned
 		*pages++ = req->wb_page;
 	}
 	req = nfs_list_entry(data->pages.next);
+	if ((!lseg) && list_is_singular(&data->pages))
+		lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_READ);
 
-	return nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
-out_bad:
-	nfs_async_read_error(head);
+	ret = nfs_read_rpcsetup(req, data, &nfs_read_full_ops, desc->pg_count,
+				0, lseg);
+out:
+	put_lseg(lseg);
+	desc->pg_lseg = NULL;
 	return ret;
 }
 
@@ -366,6 +400,7 @@ static void nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data
 		return;
 
 	/* Yes, so retry the read at the end of the data */
+	data->mds_offset += resp->count;
 	argp->offset += resp->count;
 	argp->pgbase += resp->count;
 	argp->count -= resp->count;
@@ -625,7 +660,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
 	if (ret == 0)
 		goto read_complete; /* all pages were read */
 
-	pnfs_update_layout(inode, desc.ctx, IOMODE_READ);
+	pnfs_pageio_init_read(&pgio, inode);
 	if (rsize < PAGE_CACHE_SIZE)
 		nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
 	else
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index b68c860..2b8e9a5 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -263,8 +263,11 @@ static match_table_t nfs_local_lock_tokens = {
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+static int  nfs_show_devname(struct seq_file *, struct vfsmount *);
+static int  nfs_show_path(struct seq_file *, struct vfsmount *);
 static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
-static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
+static struct dentry *nfs_fs_mount(struct file_system_type *,
+		int, const char *, void *);
 static struct dentry *nfs_xdev_mount(struct file_system_type *fs_type,
 		int flags, const char *dev_name, void *raw_data);
 static void nfs_put_super(struct super_block *);
@@ -274,7 +277,7 @@ static int nfs_remount(struct super_block *sb, int *flags, char *raw_data);
 static struct file_system_type nfs_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "nfs",
-	.get_sb		= nfs_get_sb,
+	.mount		= nfs_fs_mount,
 	.kill_sb	= nfs_kill_super,
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
@@ -296,6 +299,8 @@ static const struct super_operations nfs_sops = {
 	.evict_inode	= nfs_evict_inode,
 	.umount_begin	= nfs_umount_begin,
 	.show_options	= nfs_show_options,
+	.show_devname	= nfs_show_devname,
+	.show_path	= nfs_show_path,
 	.show_stats	= nfs_show_stats,
 	.remount_fs	= nfs_remount,
 };
@@ -303,16 +308,16 @@ static const struct super_operations nfs_sops = {
 #ifdef CONFIG_NFS_V4
 static int nfs4_validate_text_mount_data(void *options,
 	struct nfs_parsed_mount_data *args, const char *dev_name);
-static int nfs4_try_mount(int flags, const char *dev_name,
-	struct nfs_parsed_mount_data *data, struct vfsmount *mnt);
-static int nfs4_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+	struct nfs_parsed_mount_data *data);
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_remote_mount(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_xdev_mount(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *raw_data);
-static int nfs4_referral_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data);
 static struct dentry *nfs4_remote_referral_mount(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *raw_data);
 static void nfs4_kill_super(struct super_block *sb);
@@ -320,7 +325,7 @@ static void nfs4_kill_super(struct super_block *sb);
 static struct file_system_type nfs4_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "nfs4",
-	.get_sb		= nfs4_get_sb,
+	.mount		= nfs4_mount,
 	.kill_sb	= nfs4_kill_super,
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
@@ -352,7 +357,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = {
 struct file_system_type nfs4_referral_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "nfs4",
-	.get_sb		= nfs4_referral_get_sb,
+	.mount		= nfs4_referral_mount,
 	.kill_sb	= nfs4_kill_super,
 	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
 };
@@ -366,6 +371,8 @@ static const struct super_operations nfs4_sops = {
 	.evict_inode	= nfs4_evict_inode,
 	.umount_begin	= nfs_umount_begin,
 	.show_options	= nfs_show_options,
+	.show_devname	= nfs_show_devname,
+	.show_path	= nfs_show_path,
 	.show_stats	= nfs_show_stats,
 	.remount_fs	= nfs_remount,
 };
@@ -726,6 +733,28 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
 	return 0;
 }
 
+static int nfs_show_devname(struct seq_file *m, struct vfsmount *mnt)
+{
+	char *page = (char *) __get_free_page(GFP_KERNEL);
+	char *devname, *dummy;
+	int err = 0;
+	if (!page)
+		return -ENOMEM;
+	devname = nfs_path(&dummy, mnt->mnt_root, page, PAGE_SIZE);
+	if (IS_ERR(devname))
+		err = PTR_ERR(devname);
+	else
+		seq_escape(m, devname, " \t\n\\");
+	free_page((unsigned long)page);
+	return err;
+}
+
+static int nfs_show_path(struct seq_file *m, struct vfsmount *mnt)
+{
+	seq_puts(m, "/");
+	return 0;
+}
+
 /*
  * Present statistical information for this VFS mountpoint
  */
@@ -979,6 +1008,27 @@ static int nfs_parse_security_flavors(char *value,
 	return 1;
 }
 
+static int nfs_get_option_str(substring_t args[], char **option)
+{
+	kfree(*option);
+	*option = match_strdup(args);
+	return !option;
+}
+
+static int nfs_get_option_ul(substring_t args[], unsigned long *option)
+{
+	int rc;
+	char *string;
+
+	string = match_strdup(args);
+	if (string == NULL)
+		return -ENOMEM;
+	rc = strict_strtoul(string, 10, option);
+	kfree(string);
+
+	return rc;
+}
+
 /*
  * Error-check and convert a string of mount options from user space into
  * a data structure.  The whole mount string is processed; bad options are
@@ -1127,155 +1177,82 @@ static int nfs_parse_mount_options(char *raw,
 		 * options that take numeric values
 		 */
 		case Opt_port:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0 || option > USHRT_MAX)
+			if (nfs_get_option_ul(args, &option) ||
+			    option > USHRT_MAX)
 				goto out_invalid_value;
 			mnt->nfs_server.port = option;
 			break;
 		case Opt_rsize:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->rsize = option;
 			break;
 		case Opt_wsize:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->wsize = option;
 			break;
 		case Opt_bsize:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->bsize = option;
 			break;
 		case Opt_timeo:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0 || option == 0)
+			if (nfs_get_option_ul(args, &option) || option == 0)
 				goto out_invalid_value;
 			mnt->timeo = option;
 			break;
 		case Opt_retrans:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0 || option == 0)
+			if (nfs_get_option_ul(args, &option) || option == 0)
 				goto out_invalid_value;
 			mnt->retrans = option;
 			break;
 		case Opt_acregmin:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->acregmin = option;
 			break;
 		case Opt_acregmax:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->acregmax = option;
 			break;
 		case Opt_acdirmin:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->acdirmin = option;
 			break;
 		case Opt_acdirmax:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->acdirmax = option;
 			break;
 		case Opt_actimeo:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->acregmin = mnt->acregmax =
 			mnt->acdirmin = mnt->acdirmax = option;
 			break;
 		case Opt_namelen:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			mnt->namlen = option;
 			break;
 		case Opt_mountport:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0 || option > USHRT_MAX)
+			if (nfs_get_option_ul(args, &option) ||
+			    option > USHRT_MAX)
 				goto out_invalid_value;
 			mnt->mount_server.port = option;
 			break;
 		case Opt_mountvers:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0 ||
+			if (nfs_get_option_ul(args, &option) ||
 			    option < NFS_MNT_VERSION ||
 			    option > NFS_MNT3_VERSION)
 				goto out_invalid_value;
 			mnt->mount_server.version = option;
 			break;
 		case Opt_nfsvers:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			switch (option) {
 			case NFS2_VERSION:
@@ -1295,12 +1272,7 @@ static int nfs_parse_mount_options(char *raw,
 			}
 			break;
 		case Opt_minorversion:
-			string = match_strdup(args);
-			if (string == NULL)
-				goto out_nomem;
-			rc = strict_strtoul(string, 10, &option);
-			kfree(string);
-			if (rc != 0)
+			if (nfs_get_option_ul(args, &option))
 				goto out_invalid_value;
 			if (option > NFS4_MAX_MINOR_VERSION)
 				goto out_invalid_value;
@@ -1336,21 +1308,18 @@ static int nfs_parse_mount_options(char *raw,
 			case Opt_xprt_udp:
 				mnt->flags &= ~NFS_MOUNT_TCP;
 				mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP;
-				kfree(string);
 				break;
 			case Opt_xprt_tcp6:
 				protofamily = AF_INET6;
 			case Opt_xprt_tcp:
 				mnt->flags |= NFS_MOUNT_TCP;
 				mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP;
-				kfree(string);
 				break;
 			case Opt_xprt_rdma:
 				/* vector side protocols to TCP */
 				mnt->flags |= NFS_MOUNT_TCP;
 				mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA;
 				xprt_load_transport(string);
-				kfree(string);
 				break;
 			default:
 				dfprintk(MOUNT, "NFS:   unrecognized "
@@ -1358,6 +1327,7 @@ static int nfs_parse_mount_options(char *raw,
 				kfree(string);
 				return 0;
 			}
+			kfree(string);
 			break;
 		case Opt_mountproto:
 			string = match_strdup(args);
@@ -1400,18 +1370,13 @@ static int nfs_parse_mount_options(char *raw,
 				goto out_invalid_address;
 			break;
 		case Opt_clientaddr:
-			string = match_strdup(args);
-			if (string == NULL)
+			if (nfs_get_option_str(args, &mnt->client_address))
 				goto out_nomem;
-			kfree(mnt->client_address);
-			mnt->client_address = string;
 			break;
 		case Opt_mounthost:
-			string = match_strdup(args);
-			if (string == NULL)
+			if (nfs_get_option_str(args,
+					       &mnt->mount_server.hostname))
 				goto out_nomem;
-			kfree(mnt->mount_server.hostname);
-			mnt->mount_server.hostname = string;
 			break;
 		case Opt_mountaddr:
 			string = match_strdup(args);
@@ -1451,11 +1416,8 @@ static int nfs_parse_mount_options(char *raw,
 			};
 			break;
 		case Opt_fscache_uniq:
-			string = match_strdup(args);
-			if (string == NULL)
+			if (nfs_get_option_str(args, &mnt->fscache_uniq))
 				goto out_nomem;
-			kfree(mnt->fscache_uniq);
-			mnt->fscache_uniq = string;
 			mnt->options |= NFS_OPTION_FSCACHE;
 			break;
 		case Opt_local_lock:
@@ -1665,99 +1627,59 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
 	return nfs_walk_authlist(args, &request);
 }
 
-static int nfs_parse_simple_hostname(const char *dev_name,
-				     char **hostname, size_t maxnamlen,
-				     char **export_path, size_t maxpathlen)
+/*
+ * Split "dev_name" into "hostname:export_path".
+ *
+ * The leftmost colon demarks the split between the server's hostname
+ * and the export path.  If the hostname starts with a left square
+ * bracket, then it may contain colons.
+ *
+ * Note: caller frees hostname and export path, even on error.
+ */
+static int nfs_parse_devname(const char *dev_name,
+			     char **hostname, size_t maxnamlen,
+			     char **export_path, size_t maxpathlen)
 {
 	size_t len;
-	char *colon, *comma;
-
-	colon = strchr(dev_name, ':');
-	if (colon == NULL)
-		goto out_bad_devname;
-
-	len = colon - dev_name;
-	if (len > maxnamlen)
-		goto out_hostname;
+	char *end;
 
-	/* N.B. caller will free nfs_server.hostname in all cases */
-	*hostname = kstrndup(dev_name, len, GFP_KERNEL);
-	if (!*hostname)
-		goto out_nomem;
-
-	/* kill possible hostname list: not supported */
-	comma = strchr(*hostname, ',');
-	if (comma != NULL) {
-		if (comma == *hostname)
+	/* Is the host name protected with square brakcets? */
+	if (*dev_name == '[') {
+		end = strchr(++dev_name, ']');
+		if (end == NULL || end[1] != ':')
 			goto out_bad_devname;
-		*comma = '\0';
-	}
 
-	colon++;
-	len = strlen(colon);
-	if (len > maxpathlen)
-		goto out_path;
-	*export_path = kstrndup(colon, len, GFP_KERNEL);
-	if (!*export_path)
-		goto out_nomem;
-
-	dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path);
-	return 0;
-
-out_bad_devname:
-	dfprintk(MOUNT, "NFS: device name not in host:path format\n");
-	return -EINVAL;
-
-out_nomem:
-	dfprintk(MOUNT, "NFS: not enough memory to parse device name\n");
-	return -ENOMEM;
-
-out_hostname:
-	dfprintk(MOUNT, "NFS: server hostname too long\n");
-	return -ENAMETOOLONG;
-
-out_path:
-	dfprintk(MOUNT, "NFS: export pathname too long\n");
-	return -ENAMETOOLONG;
-}
-
-/*
- * Hostname has square brackets around it because it contains one or
- * more colons.  We look for the first closing square bracket, and a
- * colon must follow it.
- */
-static int nfs_parse_protected_hostname(const char *dev_name,
-					char **hostname, size_t maxnamlen,
-					char **export_path, size_t maxpathlen)
-{
-	size_t len;
-	char *start, *end;
+		len = end - dev_name;
+		end++;
+	} else {
+		char *comma;
 
-	start = (char *)(dev_name + 1);
+		end = strchr(dev_name, ':');
+		if (end == NULL)
+			goto out_bad_devname;
+		len = end - dev_name;
 
-	end = strchr(start, ']');
-	if (end == NULL)
-		goto out_bad_devname;
-	if (*(end + 1) != ':')
-		goto out_bad_devname;
+		/* kill possible hostname list: not supported */
+		comma = strchr(dev_name, ',');
+		if (comma != NULL && comma < end)
+			*comma = 0;
+	}
 
-	len = end - start;
 	if (len > maxnamlen)
 		goto out_hostname;
 
 	/* N.B. caller will free nfs_server.hostname in all cases */
-	*hostname = kstrndup(start, len, GFP_KERNEL);
+	*hostname = kstrndup(dev_name, len, GFP_KERNEL);
 	if (*hostname == NULL)
 		goto out_nomem;
-
-	end += 2;
-	len = strlen(end);
+	len = strlen(++end);
 	if (len > maxpathlen)
 		goto out_path;
 	*export_path = kstrndup(end, len, GFP_KERNEL);
 	if (!*export_path)
 		goto out_nomem;
 
+	dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *export_path);
 	return 0;
 
 out_bad_devname:
@@ -1778,29 +1700,6 @@ out_path:
 }
 
 /*
- * Split "dev_name" into "hostname:export_path".
- *
- * The leftmost colon demarks the split between the server's hostname
- * and the export path.  If the hostname starts with a left square
- * bracket, then it may contain colons.
- *
- * Note: caller frees hostname and export path, even on error.
- */
-static int nfs_parse_devname(const char *dev_name,
-			     char **hostname, size_t maxnamlen,
-			     char **export_path, size_t maxpathlen)
-{
-	if (*dev_name == '[')
-		return nfs_parse_protected_hostname(dev_name,
-						    hostname, maxnamlen,
-						    export_path, maxpathlen);
-
-	return nfs_parse_simple_hostname(dev_name,
-					 hostname, maxnamlen,
-					 export_path, maxpathlen);
-}
-
-/*
  * Validate the NFS2/NFS3 mount data
  * - fills in the mount root filehandle
  *
@@ -2267,19 +2166,19 @@ static int nfs_bdi_register(struct nfs_server *server)
 	return bdi_register_dev(&server->backing_dev_info, server->s_dev);
 }
 
-static int nfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data)
 {
 	struct nfs_server *server = NULL;
 	struct super_block *s;
 	struct nfs_parsed_mount_data *data;
 	struct nfs_fh *mntfh;
-	struct dentry *mntroot;
+	struct dentry *mntroot = ERR_PTR(-ENOMEM);
 	int (*compare_super)(struct super_block *, void *) = nfs_compare_super;
 	struct nfs_sb_mountdata sb_mntdata = {
 		.mntflags = flags,
 	};
-	int error = -ENOMEM;
+	int error;
 
 	data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
 	mntfh = nfs_alloc_fhandle();
@@ -2290,12 +2189,14 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 
 	/* Validate the mount data */
 	error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
-	if (error < 0)
+	if (error < 0) {
+		mntroot = ERR_PTR(error);
 		goto out;
+	}
 
 #ifdef CONFIG_NFS_V4
 	if (data->version == 4) {
-		error = nfs4_try_mount(flags, dev_name, data, mnt);
+		mntroot = nfs4_try_mount(flags, dev_name, data);
 		kfree(data->client_address);
 		kfree(data->nfs_server.export_path);
 		goto out;
@@ -2305,7 +2206,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 	/* Get a volume representation */
 	server = nfs_create_server(data, mntfh);
 	if (IS_ERR(server)) {
-		error = PTR_ERR(server);
+		mntroot = ERR_CAST(server);
 		goto out;
 	}
 	sb_mntdata.server = server;
@@ -2316,7 +2217,7 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 	/* Get a superblock - note that we may end up sharing one that already exists */
 	s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
 	if (IS_ERR(s)) {
-		error = PTR_ERR(s);
+		mntroot = ERR_CAST(s);
 		goto out_err_nosb;
 	}
 
@@ -2325,8 +2226,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 		server = NULL;
 	} else {
 		error = nfs_bdi_register(server);
-		if (error)
+		if (error) {
+			mntroot = ERR_PTR(error);
 			goto error_splat_bdi;
+		}
 	}
 
 	if (!s->s_root) {
@@ -2336,20 +2239,15 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 			s, data ? data->fscache_uniq : NULL, NULL);
 	}
 
-	mntroot = nfs_get_root(s, mntfh);
-	if (IS_ERR(mntroot)) {
-		error = PTR_ERR(mntroot);
+	mntroot = nfs_get_root(s, mntfh, dev_name);
+	if (IS_ERR(mntroot))
 		goto error_splat_super;
-	}
 
 	error = security_sb_set_mnt_opts(s, &data->lsm_opts);
 	if (error)
 		goto error_splat_root;
 
 	s->s_flags |= MS_ACTIVE;
-	mnt->mnt_sb = s;
-	mnt->mnt_root = mntroot;
-	error = 0;
 
 out:
 	kfree(data->nfs_server.hostname);
@@ -2359,7 +2257,7 @@ out:
 out_free_fh:
 	nfs_free_fhandle(mntfh);
 	kfree(data);
-	return error;
+	return mntroot;
 
 out_err_nosb:
 	nfs_free_server(server);
@@ -2367,6 +2265,7 @@ out_err_nosb:
 
 error_splat_root:
 	dput(mntroot);
+	mntroot = ERR_PTR(error);
 error_splat_super:
 	if (server && !s->s_root)
 		bdi_unregister(&server->backing_dev_info);
@@ -2450,7 +2349,7 @@ nfs_xdev_mount(struct file_system_type *fs_type, int flags,
 		nfs_fscache_get_super_cookie(s, NULL, data);
 	}
 
-	mntroot = nfs_get_root(s, data->fh);
+	mntroot = nfs_get_root(s, data->fh, dev_name);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -2718,7 +2617,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
 			s, data ? data->fscache_uniq : NULL, NULL);
 	}
 
-	mntroot = nfs4_get_root(s, mntfh);
+	mntroot = nfs4_get_root(s, mntfh, dev_name);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -2771,27 +2670,6 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
 	return root_mnt;
 }
 
-static void nfs_fix_devname(const struct path *path, struct vfsmount *mnt)
-{
-	char *page = (char *) __get_free_page(GFP_KERNEL);
-	char *devname, *tmp;
-
-	if (page == NULL)
-		return;
-	devname = nfs_path(path->mnt->mnt_devname,
-			path->mnt->mnt_root, path->dentry,
-			page, PAGE_SIZE);
-	if (IS_ERR(devname))
-		goto out_freepage;
-	tmp = kstrdup(devname, GFP_KERNEL);
-	if (tmp == NULL)
-		goto out_freepage;
-	kfree(mnt->mnt_devname);
-	mnt->mnt_devname = tmp;
-out_freepage:
-	free_page((unsigned long)page);
-}
-
 struct nfs_referral_count {
 	struct list_head list;
 	const struct task_struct *task;
@@ -2858,17 +2736,18 @@ static void nfs_referral_loop_unprotect(void)
 	kfree(p);
 }
 
-static int nfs_follow_remote_path(struct vfsmount *root_mnt,
-		const char *export_path, struct vfsmount *mnt_target)
+static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
+		const char *export_path)
 {
 	struct nameidata *nd = NULL;
 	struct mnt_namespace *ns_private;
 	struct super_block *s;
+	struct dentry *dentry;
 	int ret;
 
 	nd = kmalloc(sizeof(*nd), GFP_KERNEL);
 	if (nd == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	ns_private = create_mnt_ns(root_mnt);
 	ret = PTR_ERR(ns_private);
@@ -2890,32 +2769,27 @@ static int nfs_follow_remote_path(struct vfsmount *root_mnt,
 
 	s = nd->path.mnt->mnt_sb;
 	atomic_inc(&s->s_active);
-	mnt_target->mnt_sb = s;
-	mnt_target->mnt_root = dget(nd->path.dentry);
-
-	/* Correct the device pathname */
-	nfs_fix_devname(&nd->path, mnt_target);
+	dentry = dget(nd->path.dentry);
 
 	path_put(&nd->path);
 	kfree(nd);
 	down_write(&s->s_umount);
-	return 0;
+	return dentry;
 out_put_mnt_ns:
 	put_mnt_ns(ns_private);
 out_mntput:
 	mntput(root_mnt);
 out_err:
 	kfree(nd);
-	return ret;
+	return ERR_PTR(ret);
 }
 
-static int nfs4_try_mount(int flags, const char *dev_name,
-			 struct nfs_parsed_mount_data *data,
-			 struct vfsmount *mnt)
+static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
+			 struct nfs_parsed_mount_data *data)
 {
 	char *export_path;
 	struct vfsmount *root_mnt;
-	int error;
+	struct dentry *res;
 
 	dfprintk(MOUNT, "--> nfs4_try_mount()\n");
 
@@ -2925,26 +2799,25 @@ static int nfs4_try_mount(int flags, const char *dev_name,
 			data->nfs_server.hostname);
 	data->nfs_server.export_path = export_path;
 
-	error = PTR_ERR(root_mnt);
-	if (IS_ERR(root_mnt))
-		goto out;
-
-	error = nfs_follow_remote_path(root_mnt, export_path, mnt);
+	res = ERR_CAST(root_mnt);
+	if (!IS_ERR(root_mnt))
+		res = nfs_follow_remote_path(root_mnt, export_path);
 
-out:
-	dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", error,
-			error != 0 ? " [error]" : "");
-	return error;
+	dfprintk(MOUNT, "<-- nfs4_try_mount() = %ld%s\n",
+			IS_ERR(res) ? PTR_ERR(res) : 0,
+			IS_ERR(res) ? " [error]" : "");
+	return res;
 }
 
 /*
  * Get the superblock for an NFS4 mountpoint
  */
-static int nfs4_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+static struct dentry *nfs4_mount(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data)
 {
 	struct nfs_parsed_mount_data *data;
 	int error = -ENOMEM;
+	struct dentry *res = ERR_PTR(-ENOMEM);
 
 	data = nfs_alloc_parsed_mount_data(4);
 	if (data == NULL)
@@ -2952,10 +2825,14 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
 
 	/* Validate the mount data */
 	error = nfs4_validate_mount_data(raw_data, data, dev_name);
-	if (error < 0)
+	if (error < 0) {
+		res = ERR_PTR(error);
 		goto out;
+	}
 
-	error = nfs4_try_mount(flags, dev_name, data, mnt);
+	res = nfs4_try_mount(flags, dev_name, data);
+	if (IS_ERR(res))
+		error = PTR_ERR(res);
 
 out:
 	kfree(data->client_address);
@@ -2964,9 +2841,9 @@ out:
 	kfree(data->fscache_uniq);
 out_free_data:
 	kfree(data);
-	dprintk("<-- nfs4_get_sb() = %d%s\n", error,
+	dprintk("<-- nfs4_mount() = %d%s\n", error,
 			error != 0 ? " [error]" : "");
-	return error;
+	return res;
 }
 
 static void nfs4_kill_super(struct super_block *sb)
@@ -3033,7 +2910,7 @@ nfs4_xdev_mount(struct file_system_type *fs_type, int flags,
 		nfs_fscache_get_super_cookie(s, NULL, data);
 	}
 
-	mntroot = nfs4_get_root(s, data->fh);
+	mntroot = nfs4_get_root(s, data->fh, dev_name);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -3120,7 +2997,7 @@ nfs4_remote_referral_mount(struct file_system_type *fs_type, int flags,
 		nfs_fscache_get_super_cookie(s, NULL, data);
 	}
 
-	mntroot = nfs4_get_root(s, mntfh);
+	mntroot = nfs4_get_root(s, mntfh, dev_name);
 	if (IS_ERR(mntroot)) {
 		error = PTR_ERR(mntroot);
 		goto error_splat_super;
@@ -3160,16 +3037,15 @@ error_splat_bdi:
 /*
  * Create an NFS4 server record on referral traversal
  */
-static int nfs4_referral_get_sb(struct file_system_type *fs_type,
-		int flags, const char *dev_name, void *raw_data,
-		struct vfsmount *mnt)
+static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data)
 {
 	struct nfs_clone_mount *data = raw_data;
 	char *export_path;
 	struct vfsmount *root_mnt;
-	int error;
+	struct dentry *res;
 
-	dprintk("--> nfs4_referral_get_sb()\n");
+	dprintk("--> nfs4_referral_mount()\n");
 
 	export_path = data->mnt_path;
 	data->mnt_path = "/";
@@ -3178,15 +3054,13 @@ static int nfs4_referral_get_sb(struct file_system_type *fs_type,
 			flags, data, data->hostname);
 	data->mnt_path = export_path;
 
-	error = PTR_ERR(root_mnt);
-	if (IS_ERR(root_mnt))
-		goto out;
-
-	error = nfs_follow_remote_path(root_mnt, export_path, mnt);
-out:
-	dprintk("<-- nfs4_referral_get_sb() = %d%s\n", error,
-			error != 0 ? " [error]" : "");
-	return error;
+	res = ERR_CAST(root_mnt);
+	if (!IS_ERR(root_mnt))
+		res = nfs_follow_remote_path(root_mnt, export_path);
+	dprintk("<-- nfs4_referral_mount() = %ld%s\n",
+			IS_ERR(res) ? PTR_ERR(res) : 0,
+			IS_ERR(res) ? " [error]" : "");
+	return res;
 }
 
 #endif /* CONFIG_NFS_V4 */
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index 6481d53..8d6864c 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -148,6 +148,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
 	alias = d_lookup(parent, &data->args.name);
 	if (alias != NULL) {
 		int ret = 0;
+		void *devname_garbage = NULL;
 
 		/*
 		 * Hey, we raced with lookup... See if we need to transfer
@@ -157,6 +158,7 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
 		spin_lock(&alias->d_lock);
 		if (alias->d_inode != NULL &&
 		    !(alias->d_flags & DCACHE_NFSFS_RENAMED)) {
+			devname_garbage = alias->d_fsdata;
 			alias->d_fsdata = data;
 			alias->d_flags |= DCACHE_NFSFS_RENAMED;
 			ret = 1;
@@ -164,6 +166,13 @@ static int nfs_do_call_unlink(struct dentry *parent, struct inode *dir, struct n
 		spin_unlock(&alias->d_lock);
 		nfs_dec_sillycount(dir);
 		dput(alias);
+		/*
+		 * If we'd displaced old cached devname, free it.  At that
+		 * point dentry is definitely not a root, so we won't need
+		 * that anymore.
+		 */
+		if (devname_garbage)
+			kfree(devname_garbage);
 		return ret;
 	}
 	data->dir = igrab(dir);
@@ -252,6 +261,7 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct nfs_unlinkdata *data;
 	int status = -ENOMEM;
+	void *devname_garbage = NULL;
 
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (data == NULL)
@@ -269,8 +279,16 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
 		goto out_unlock;
 	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
+	devname_garbage = dentry->d_fsdata;
 	dentry->d_fsdata = data;
 	spin_unlock(&dentry->d_lock);
+	/*
+	 * If we'd displaced old cached devname, free it.  At that
+	 * point dentry is definitely not a root, so we won't need
+	 * that anymore.
+	 */
+	if (devname_garbage)
+		kfree(devname_garbage);
 	return 0;
 out_unlock:
 	spin_unlock(&dentry->d_lock);
@@ -299,6 +317,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
 		dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
 		data = dentry->d_fsdata;
+		dentry->d_fsdata = NULL;
 	}
 	spin_unlock(&dentry->d_lock);
 
@@ -315,6 +334,7 @@ nfs_cancel_async_unlink(struct dentry *dentry)
 		struct nfs_unlinkdata *data = dentry->d_fsdata;
 
 		dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
+		dentry->d_fsdata = NULL;
 		spin_unlock(&dentry->d_lock);
 		nfs_free_unlinkdata(data);
 		return;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 42b92d7..47a3ad6 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -28,6 +28,7 @@
 #include "iostat.h"
 #include "nfs4_fs.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PAGECACHE
 
@@ -96,6 +97,7 @@ void nfs_writedata_free(struct nfs_write_data *p)
 
 static void nfs_writedata_release(struct nfs_write_data *wdata)
 {
+	put_lseg(wdata->lseg);
 	put_nfs_open_context(wdata->args.context);
 	nfs_writedata_free(wdata);
 }
@@ -781,25 +783,21 @@ static int flush_task_priority(int how)
 	return RPC_PRIORITY_NORMAL;
 }
 
-/*
- * Set up the argument/result storage required for the RPC call.
- */
-static int nfs_write_rpcsetup(struct nfs_page *req,
-		struct nfs_write_data *data,
-		const struct rpc_call_ops *call_ops,
-		unsigned int count, unsigned int offset,
-		int how)
+int nfs_initiate_write(struct nfs_write_data *data,
+		       struct rpc_clnt *clnt,
+		       const struct rpc_call_ops *call_ops,
+		       int how)
 {
-	struct inode *inode = req->wb_context->path.dentry->d_inode;
+	struct inode *inode = data->inode;
 	int priority = flush_task_priority(how);
 	struct rpc_task *task;
 	struct rpc_message msg = {
 		.rpc_argp = &data->args,
 		.rpc_resp = &data->res,
-		.rpc_cred = req->wb_context->cred,
+		.rpc_cred = data->cred,
 	};
 	struct rpc_task_setup task_setup_data = {
-		.rpc_client = NFS_CLIENT(inode),
+		.rpc_client = clnt,
 		.task = &data->task,
 		.rpc_message = &msg,
 		.callback_ops = call_ops,
@@ -810,12 +808,52 @@ static int nfs_write_rpcsetup(struct nfs_page *req,
 	};
 	int ret = 0;
 
+	/* Set up the initial task struct.  */
+	NFS_PROTO(inode)->write_setup(data, &msg);
+
+	dprintk("NFS: %5u initiated write call "
+		"(req %s/%lld, %u bytes @ offset %llu)\n",
+		data->task.tk_pid,
+		inode->i_sb->s_id,
+		(long long)NFS_FILEID(inode),
+		data->args.count,
+		(unsigned long long)data->args.offset);
+
+	task = rpc_run_task(&task_setup_data);
+	if (IS_ERR(task)) {
+		ret = PTR_ERR(task);
+		goto out;
+	}
+	if (how & FLUSH_SYNC) {
+		ret = rpc_wait_for_completion_task(task);
+		if (ret == 0)
+			ret = task->tk_status;
+	}
+	rpc_put_task(task);
+out:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(nfs_initiate_write);
+
+/*
+ * Set up the argument/result storage required for the RPC call.
+ */
+static int nfs_write_rpcsetup(struct nfs_page *req,
+		struct nfs_write_data *data,
+		const struct rpc_call_ops *call_ops,
+		unsigned int count, unsigned int offset,
+		struct pnfs_layout_segment *lseg,
+		int how)
+{
+	struct inode *inode = req->wb_context->path.dentry->d_inode;
+
 	/* Set up the RPC argument and reply structs
 	 * NB: take care not to mess about with data->commit et al. */
 
 	data->req = req;
 	data->inode = inode = req->wb_context->path.dentry->d_inode;
-	data->cred = msg.rpc_cred;
+	data->cred = req->wb_context->cred;
+	data->lseg = get_lseg(lseg);
 
 	data->args.fh     = NFS_FH(inode);
 	data->args.offset = req_offset(req) + offset;
@@ -836,30 +874,11 @@ static int nfs_write_rpcsetup(struct nfs_page *req,
 	data->res.verf    = &data->verf;
 	nfs_fattr_init(&data->fattr);
 
-	/* Set up the initial task struct.  */
-	NFS_PROTO(inode)->write_setup(data, &msg);
-
-	dprintk("NFS: %5u initiated write call "
-		"(req %s/%lld, %u bytes @ offset %llu)\n",
-		data->task.tk_pid,
-		inode->i_sb->s_id,
-		(long long)NFS_FILEID(inode),
-		count,
-		(unsigned long long)data->args.offset);
+	if (data->lseg &&
+	    (pnfs_try_to_write_data(data, call_ops, how) == PNFS_ATTEMPTED))
+		return 0;
 
-	task = rpc_run_task(&task_setup_data);
-	if (IS_ERR(task)) {
-		ret = PTR_ERR(task);
-		goto out;
-	}
-	if (how & FLUSH_SYNC) {
-		ret = rpc_wait_for_completion_task(task);
-		if (ret == 0)
-			ret = task->tk_status;
-	}
-	rpc_put_task(task);
-out:
-	return ret;
+	return nfs_initiate_write(data, NFS_CLIENT(inode), call_ops, how);
 }
 
 /* If a nfs_flush_* function fails, it should remove reqs from @head and
@@ -879,20 +898,21 @@ static void nfs_redirty_request(struct nfs_page *req)
  * Generate multiple small requests to write out a single
  * contiguous dirty area on one page.
  */
-static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
+static int nfs_flush_multi(struct nfs_pageio_descriptor *desc)
 {
-	struct nfs_page *req = nfs_list_entry(head->next);
+	struct nfs_page *req = nfs_list_entry(desc->pg_list.next);
 	struct page *page = req->wb_page;
 	struct nfs_write_data *data;
-	size_t wsize = NFS_SERVER(inode)->wsize, nbytes;
+	size_t wsize = NFS_SERVER(desc->pg_inode)->wsize, nbytes;
 	unsigned int offset;
 	int requests = 0;
 	int ret = 0;
+	struct pnfs_layout_segment *lseg;
 	LIST_HEAD(list);
 
 	nfs_list_remove_request(req);
 
-	nbytes = count;
+	nbytes = desc->pg_count;
 	do {
 		size_t len = min(nbytes, wsize);
 
@@ -905,9 +925,11 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
 	} while (nbytes != 0);
 	atomic_set(&req->wb_complete, requests);
 
+	BUG_ON(desc->pg_lseg);
+	lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW);
 	ClearPageError(page);
 	offset = 0;
-	nbytes = count;
+	nbytes = desc->pg_count;
 	do {
 		int ret2;
 
@@ -919,13 +941,15 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
 		if (nbytes < wsize)
 			wsize = nbytes;
 		ret2 = nfs_write_rpcsetup(req, data, &nfs_write_partial_ops,
-				   wsize, offset, how);
+					  wsize, offset, lseg, desc->pg_ioflags);
 		if (ret == 0)
 			ret = ret2;
 		offset += wsize;
 		nbytes -= wsize;
 	} while (nbytes != 0);
 
+	put_lseg(lseg);
+	desc->pg_lseg = NULL;
 	return ret;
 
 out_bad:
@@ -946,16 +970,26 @@ out_bad:
  * This is the case if nfs_updatepage detects a conflicting request
  * that has been written but not committed.
  */
-static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int how)
+static int nfs_flush_one(struct nfs_pageio_descriptor *desc)
 {
 	struct nfs_page		*req;
 	struct page		**pages;
 	struct nfs_write_data	*data;
+	struct list_head *head = &desc->pg_list;
+	struct pnfs_layout_segment *lseg = desc->pg_lseg;
+	int ret;
 
-	data = nfs_writedata_alloc(npages);
-	if (!data)
-		goto out_bad;
-
+	data = nfs_writedata_alloc(nfs_page_array_len(desc->pg_base,
+						      desc->pg_count));
+	if (!data) {
+		while (!list_empty(head)) {
+			req = nfs_list_entry(head->next);
+			nfs_list_remove_request(req);
+			nfs_redirty_request(req);
+		}
+		ret = -ENOMEM;
+		goto out;
+	}
 	pages = data->pagevec;
 	while (!list_empty(head)) {
 		req = nfs_list_entry(head->next);
@@ -965,16 +999,15 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
 		*pages++ = req->wb_page;
 	}
 	req = nfs_list_entry(data->pages.next);
+	if ((!lseg) && list_is_singular(&data->pages))
+		lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW);
 
 	/* Set up the argument struct */
-	return nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
- out_bad:
-	while (!list_empty(head)) {
-		req = nfs_list_entry(head->next);
-		nfs_list_remove_request(req);
-		nfs_redirty_request(req);
-	}
-	return -ENOMEM;
+	ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags);
+out:
+	put_lseg(lseg); /* Cleans any gotten in ->pg_test */
+	desc->pg_lseg = NULL;
+	return ret;
 }
 
 static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
@@ -982,6 +1015,8 @@ static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
 {
 	size_t wsize = NFS_SERVER(inode)->wsize;
 
+	pnfs_pageio_init_write(pgio, inode);
+
 	if (wsize < PAGE_CACHE_SIZE)
 		nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
 	else
@@ -1132,7 +1167,7 @@ static const struct rpc_call_ops nfs_write_full_ops = {
 /*
  * This function is called when the WRITE call is complete.
  */
-int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
+void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 {
 	struct nfs_writeargs	*argp = &data->args;
 	struct nfs_writeres	*resp = &data->res;
@@ -1151,7 +1186,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 	 */
 	status = NFS_PROTO(data->inode)->write_done(task, data);
 	if (status != 0)
-		return status;
+		return;
 	nfs_add_stats(data->inode, NFSIOS_SERVERWRITTENBYTES, resp->count);
 
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
@@ -1166,6 +1201,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 		 */
 		static unsigned long    complain;
 
+		/* Note this will print the MDS for a DS write */
 		if (time_before(complain, jiffies)) {
 			dprintk("NFS:       faulty NFS server %s:"
 				" (committed = %d) != (stable = %d)\n",
@@ -1186,6 +1222,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 			/* Was this an NFSv2 write or an NFSv3 stable write? */
 			if (resp->verf->committed != NFS_UNSTABLE) {
 				/* Resend from where the server left off */
+				data->mds_offset += resp->count;
 				argp->offset += resp->count;
 				argp->pgbase += resp->count;
 				argp->count -= resp->count;
@@ -1196,7 +1233,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 				argp->stable = NFS_FILE_SYNC;
 			}
 			nfs_restart_rpc(task, server->nfs_client);
-			return -EAGAIN;
+			return;
 		}
 		if (time_before(complain, jiffies)) {
 			printk(KERN_WARNING
@@ -1207,7 +1244,7 @@ int nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data)
 		/* Can't do anything about it except throw an error. */
 		task->tk_status = -EIO;
 	}
-	return 0;
+	return;
 }
 
 
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index bf9cbd2..124e8fc 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -22,30 +22,17 @@
 
 static struct file *do_open(char *name, int flags)
 {
-	struct nameidata nd;
 	struct vfsmount *mnt;
-	int error;
+	struct file *file;
 
 	mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
 	if (IS_ERR(mnt))
 		return (struct file *)mnt;
 
-	error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd);
-	mntput(mnt);	/* drop do_kern_mount reference */
-	if (error)
-		return ERR_PTR(error);
-
-	if (flags == O_RDWR)
-		error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags);
-	else
-		error = may_open(&nd.path, MAY_WRITE, flags);
+	file = file_open_root(mnt->mnt_root, mnt, name, flags);
 
-	if (!error)
-		return dentry_open(nd.path.dentry, nd.path.mnt, flags,
-				   current_cred());
-
-	path_put(&nd.path);
-	return ERR_PTR(error);
+	mntput(mnt);	/* drop do_kern_mount reference */
+	return file;
 }
 
 static struct {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index da1d970..ff93025 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -87,7 +87,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
 			    .dentry = dget(dentry)};
 	int err = 0;
 
-	err = follow_down(&path, false);
+	err = follow_down(&path);
 	if (err < 0)
 		goto out;
 
diff --git a/fs/nilfs2/alloc.c b/fs/nilfs2/alloc.c
index d7fd696..0a0a66d 100644
--- a/fs/nilfs2/alloc.c
+++ b/fs/nilfs2/alloc.c
@@ -521,8 +521,8 @@ void nilfs_palloc_commit_free_entry(struct inode *inode,
 				    group_offset, bitmap))
 		printk(KERN_WARNING "%s: entry number %llu already freed\n",
 		       __func__, (unsigned long long)req->pr_entry_nr);
-
-	nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
+	else
+		nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
 
 	kunmap(req->pr_bitmap_bh->b_page);
 	kunmap(req->pr_desc_bh->b_page);
@@ -558,8 +558,8 @@ void nilfs_palloc_abort_alloc_entry(struct inode *inode,
 				    group_offset, bitmap))
 		printk(KERN_WARNING "%s: entry number %llu already freed\n",
 		       __func__, (unsigned long long)req->pr_entry_nr);
-
-	nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
+	else
+		nilfs_palloc_group_desc_add_entries(inode, group, desc, 1);
 
 	kunmap(req->pr_bitmap_bh->b_page);
 	kunmap(req->pr_desc_bh->b_page);
@@ -665,7 +665,7 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
 		for (j = i, n = 0;
 		     (j < nitems) && nilfs_palloc_group_is_in(inode, group,
 							      entry_nrs[j]);
-		     j++, n++) {
+		     j++) {
 			nilfs_palloc_group(inode, entry_nrs[j], &group_offset);
 			if (!nilfs_clear_bit_atomic(
 				    nilfs_mdt_bgl_lock(inode, group),
@@ -674,6 +674,8 @@ int nilfs_palloc_freev(struct inode *inode, __u64 *entry_nrs, size_t nitems)
 				       "%s: entry number %llu already freed\n",
 				       __func__,
 				       (unsigned long long)entry_nrs[j]);
+			} else {
+				n++;
 			}
 		}
 		nilfs_palloc_group_desc_add_entries(inode, group, desc, n);
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c
index 3ee67c6..4723f04 100644
--- a/fs/nilfs2/bmap.c
+++ b/fs/nilfs2/bmap.c
@@ -25,7 +25,6 @@
 #include <linux/errno.h>
 #include "nilfs.h"
 #include "bmap.h"
-#include "sb.h"
 #include "btree.h"
 #include "direct.h"
 #include "btnode.h"
@@ -425,17 +424,6 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *bmap)
 /*
  * Internal use only
  */
-
-void nilfs_bmap_add_blocks(const struct nilfs_bmap *bmap, int n)
-{
-	inode_add_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
-}
-
-void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
-{
-	inode_sub_bytes(bmap->b_inode, (1 << bmap->b_inode->i_blkbits) * n);
-}
-
 __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
 			      const struct buffer_head *bh)
 {
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h
index bde1c0a..40d9f45 100644
--- a/fs/nilfs2/bmap.h
+++ b/fs/nilfs2/bmap.h
@@ -240,9 +240,6 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
 __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
 __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
 
-void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
-void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
-
 
 /* Assume that bmap semaphore is locked. */
 static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 300c2bc..d451ae0 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -1174,7 +1174,7 @@ static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr)
 	if (ret < 0)
 		goto out;
 	nilfs_btree_commit_insert(btree, path, level, key, ptr);
-	nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
+	nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
 
  out:
 	nilfs_btree_free_path(path);
@@ -1511,7 +1511,7 @@ static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key)
 	if (ret < 0)
 		goto out;
 	nilfs_btree_commit_delete(btree, path, level, dat);
-	nilfs_bmap_sub_blocks(btree, stats.bs_nblocks);
+	nilfs_inode_sub_blocks(btree->b_inode, stats.bs_nblocks);
 
 out:
 	nilfs_btree_free_path(path);
@@ -1776,7 +1776,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree,
 		return ret;
 	nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n,
 					      di, ni, bh);
-	nilfs_bmap_add_blocks(btree, stats.bs_nblocks);
+	nilfs_inode_add_blocks(btree->b_inode, stats.bs_nblocks);
 	return 0;
 }
 
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 9d45773..3a19239 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -440,7 +440,6 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de,
 	nilfs_commit_chunk(page, mapping, from, to);
 	nilfs_put_page(page);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-/*	NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
 }
 
 /*
@@ -531,7 +530,6 @@ got_it:
 	nilfs_set_de_type(de, inode);
 	nilfs_commit_chunk(page, page->mapping, from, to);
 	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-/*	NILFS_I(dir)->i_flags &= ~NILFS_BTREE_FL; */
 	nilfs_mark_inode_dirty(dir);
 	/* OFFSET_CACHE */
 out_put:
@@ -579,7 +577,6 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page)
 	dir->inode = 0;
 	nilfs_commit_chunk(page, mapping, from, to);
 	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
-/*	NILFS_I(inode)->i_flags &= ~NILFS_BTREE_FL; */
 out:
 	nilfs_put_page(page);
 	return err;
@@ -684,7 +681,7 @@ const struct file_operations nilfs_dir_operations = {
 	.readdir	= nilfs_readdir,
 	.unlocked_ioctl	= nilfs_ioctl,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl	= nilfs_ioctl,
+	.compat_ioctl	= nilfs_compat_ioctl,
 #endif	/* CONFIG_COMPAT */
 	.fsync		= nilfs_sync_file,
 
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c
index 324d80c..82f4865 100644
--- a/fs/nilfs2/direct.c
+++ b/fs/nilfs2/direct.c
@@ -146,7 +146,7 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
 		if (NILFS_BMAP_USE_VBN(bmap))
 			nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr);
 
-		nilfs_bmap_add_blocks(bmap, 1);
+		nilfs_inode_add_blocks(bmap->b_inode, 1);
 	}
 	return ret;
 }
@@ -168,7 +168,7 @@ static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key)
 	if (!ret) {
 		nilfs_bmap_commit_end_ptr(bmap, &req, dat);
 		nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR);
-		nilfs_bmap_sub_blocks(bmap, 1);
+		nilfs_inode_sub_blocks(bmap->b_inode, 1);
 	}
 	return ret;
 }
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
index 2f560c9..93589fc 100644
--- a/fs/nilfs2/file.c
+++ b/fs/nilfs2/file.c
@@ -59,7 +59,7 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 	struct nilfs_transaction_info ti;
 	int ret;
 
-	if (unlikely(nilfs_near_disk_full(NILFS_SB(inode->i_sb)->s_nilfs)))
+	if (unlikely(nilfs_near_disk_full(inode->i_sb->s_fs_info)))
 		return VM_FAULT_SIGBUS; /* -ENOSPC */
 
 	lock_page(page);
@@ -142,7 +142,7 @@ const struct file_operations nilfs_file_operations = {
 	.aio_write	= generic_file_aio_write,
 	.unlocked_ioctl	= nilfs_ioctl,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl	= nilfs_ioctl,
+	.compat_ioctl	= nilfs_compat_ioctl,
 #endif	/* CONFIG_COMPAT */
 	.mmap		= nilfs_file_mmap,
 	.open		= generic_file_open,
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 2fd440d..d5625be 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -41,6 +41,24 @@ struct nilfs_iget_args {
 	int for_gc;
 };
 
+void nilfs_inode_add_blocks(struct inode *inode, int n)
+{
+	struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+	inode_add_bytes(inode, (1 << inode->i_blkbits) * n);
+	if (root)
+		atomic_add(n, &root->blocks_count);
+}
+
+void nilfs_inode_sub_blocks(struct inode *inode, int n)
+{
+	struct nilfs_root *root = NILFS_I(inode)->i_root;
+
+	inode_sub_bytes(inode, (1 << inode->i_blkbits) * n);
+	if (root)
+		atomic_sub(n, &root->blocks_count);
+}
+
 /**
  * nilfs_get_block() - get a file block on the filesystem (callback function)
  * @inode - inode struct of the target file
@@ -277,7 +295,7 @@ const struct address_space_operations nilfs_aops = {
 struct inode *nilfs_new_inode(struct inode *dir, int mode)
 {
 	struct super_block *sb = dir->i_sb;
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct inode *inode;
 	struct nilfs_inode_info *ii;
 	struct nilfs_root *root;
@@ -315,19 +333,16 @@ struct inode *nilfs_new_inode(struct inode *dir, int mode)
 		/* No lock is needed; iget() ensures it. */
 	}
 
-	ii->i_flags = NILFS_I(dir)->i_flags;
-	if (S_ISLNK(mode))
-		ii->i_flags &= ~(NILFS_IMMUTABLE_FL | NILFS_APPEND_FL);
-	if (!S_ISDIR(mode))
-		ii->i_flags &= ~NILFS_DIRSYNC_FL;
+	ii->i_flags = nilfs_mask_flags(
+		mode, NILFS_I(dir)->i_flags & NILFS_FL_INHERITED);
 
 	/* ii->i_file_acl = 0; */
 	/* ii->i_dir_acl = 0; */
 	ii->i_dir_start_lookup = 0;
 	nilfs_set_inode_flags(inode);
-	spin_lock(&sbi->s_next_gen_lock);
-	inode->i_generation = sbi->s_next_generation++;
-	spin_unlock(&sbi->s_next_gen_lock);
+	spin_lock(&nilfs->ns_next_gen_lock);
+	inode->i_generation = nilfs->ns_next_generation++;
+	spin_unlock(&nilfs->ns_next_gen_lock);
 	insert_inode_hash(inode);
 
 	err = nilfs_init_acl(inode, dir);
@@ -359,17 +374,15 @@ void nilfs_set_inode_flags(struct inode *inode)
 
 	inode->i_flags &= ~(S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME |
 			    S_DIRSYNC);
-	if (flags & NILFS_SYNC_FL)
+	if (flags & FS_SYNC_FL)
 		inode->i_flags |= S_SYNC;
-	if (flags & NILFS_APPEND_FL)
+	if (flags & FS_APPEND_FL)
 		inode->i_flags |= S_APPEND;
-	if (flags & NILFS_IMMUTABLE_FL)
+	if (flags & FS_IMMUTABLE_FL)
 		inode->i_flags |= S_IMMUTABLE;
-#ifndef NILFS_ATIME_DISABLE
-	if (flags & NILFS_NOATIME_FL)
-#endif
+	if (flags & FS_NOATIME_FL)
 		inode->i_flags |= S_NOATIME;
-	if (flags & NILFS_DIRSYNC_FL)
+	if (flags & FS_DIRSYNC_FL)
 		inode->i_flags |= S_DIRSYNC;
 	mapping_set_gfp_mask(inode->i_mapping,
 			     mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
@@ -420,7 +433,7 @@ static int __nilfs_read_inode(struct super_block *sb,
 			      struct nilfs_root *root, unsigned long ino,
 			      struct inode *inode)
 {
-	struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct buffer_head *bh;
 	struct nilfs_inode *raw_inode;
 	int err;
@@ -707,6 +720,7 @@ void nilfs_evict_inode(struct inode *inode)
 	struct nilfs_transaction_info ti;
 	struct super_block *sb = inode->i_sb;
 	struct nilfs_inode_info *ii = NILFS_I(inode);
+	int ret;
 
 	if (inode->i_nlink || !ii->i_root || unlikely(is_bad_inode(inode))) {
 		if (inode->i_data.nrpages)
@@ -725,8 +739,9 @@ void nilfs_evict_inode(struct inode *inode)
 	nilfs_mark_inode_dirty(inode);
 	end_writeback(inode);
 
-	nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
-	atomic_dec(&ii->i_root->inodes_count);
+	ret = nilfs_ifile_delete_inode(ii->i_root->ifile, inode->i_ino);
+	if (!ret)
+		atomic_dec(&ii->i_root->inodes_count);
 
 	nilfs_clear_inode(inode);
 
@@ -792,18 +807,18 @@ int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
 
 int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_inode_info *ii = NILFS_I(inode);
 	int err;
 
-	spin_lock(&sbi->s_inode_lock);
+	spin_lock(&nilfs->ns_inode_lock);
 	if (ii->i_bh == NULL) {
-		spin_unlock(&sbi->s_inode_lock);
+		spin_unlock(&nilfs->ns_inode_lock);
 		err = nilfs_ifile_get_inode_block(ii->i_root->ifile,
 						  inode->i_ino, pbh);
 		if (unlikely(err))
 			return err;
-		spin_lock(&sbi->s_inode_lock);
+		spin_lock(&nilfs->ns_inode_lock);
 		if (ii->i_bh == NULL)
 			ii->i_bh = *pbh;
 		else {
@@ -814,36 +829,36 @@ int nilfs_load_inode_block(struct inode *inode, struct buffer_head **pbh)
 		*pbh = ii->i_bh;
 
 	get_bh(*pbh);
-	spin_unlock(&sbi->s_inode_lock);
+	spin_unlock(&nilfs->ns_inode_lock);
 	return 0;
 }
 
 int nilfs_inode_dirty(struct inode *inode)
 {
 	struct nilfs_inode_info *ii = NILFS_I(inode);
-	struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	int ret = 0;
 
 	if (!list_empty(&ii->i_dirty)) {
-		spin_lock(&sbi->s_inode_lock);
+		spin_lock(&nilfs->ns_inode_lock);
 		ret = test_bit(NILFS_I_DIRTY, &ii->i_state) ||
 			test_bit(NILFS_I_BUSY, &ii->i_state);
-		spin_unlock(&sbi->s_inode_lock);
+		spin_unlock(&nilfs->ns_inode_lock);
 	}
 	return ret;
 }
 
 int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(inode->i_sb);
 	struct nilfs_inode_info *ii = NILFS_I(inode);
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 
-	atomic_add(nr_dirty, &sbi->s_nilfs->ns_ndirtyblks);
+	atomic_add(nr_dirty, &nilfs->ns_ndirtyblks);
 
 	if (test_and_set_bit(NILFS_I_DIRTY, &ii->i_state))
 		return 0;
 
-	spin_lock(&sbi->s_inode_lock);
+	spin_lock(&nilfs->ns_inode_lock);
 	if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
 	    !test_bit(NILFS_I_BUSY, &ii->i_state)) {
 		/* Because this routine may race with nilfs_dispose_list(),
@@ -851,18 +866,18 @@ int nilfs_set_file_dirty(struct inode *inode, unsigned nr_dirty)
 		if (list_empty(&ii->i_dirty) && igrab(inode) == NULL) {
 			/* This will happen when somebody is freeing
 			   this inode. */
-			nilfs_warning(sbi->s_super, __func__,
+			nilfs_warning(inode->i_sb, __func__,
 				      "cannot get inode (ino=%lu)\n",
 				      inode->i_ino);
-			spin_unlock(&sbi->s_inode_lock);
+			spin_unlock(&nilfs->ns_inode_lock);
 			return -EINVAL; /* NILFS_I_DIRTY may remain for
 					   freeing inode */
 		}
 		list_del(&ii->i_dirty);
-		list_add_tail(&ii->i_dirty, &sbi->s_dirty_files);
+		list_add_tail(&ii->i_dirty, &nilfs->ns_dirty_files);
 		set_bit(NILFS_I_QUEUED, &ii->i_state);
 	}
-	spin_unlock(&sbi->s_inode_lock);
+	spin_unlock(&nilfs->ns_inode_lock);
 	return 0;
 }
 
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 4967389..95c04c2 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -26,7 +26,9 @@
 #include <linux/capability.h>	/* capable() */
 #include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
 #include <linux/vmalloc.h>
+#include <linux/compat.h>	/* compat_ptr() */
 #include <linux/mount.h>	/* mnt_want_write(), mnt_drop_write() */
+#include <linux/buffer_head.h>
 #include <linux/nilfs2_fs.h>
 #include "nilfs.h"
 #include "segment.h"
@@ -97,11 +99,74 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
 	return ret;
 }
 
+static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
+{
+	unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
+
+	return put_user(flags, (int __user *)argp);
+}
+
+static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
+				void __user *argp)
+{
+	struct nilfs_transaction_info ti;
+	unsigned int flags, oldflags;
+	int ret;
+
+	if (!is_owner_or_cap(inode))
+		return -EACCES;
+
+	if (get_user(flags, (int __user *)argp))
+		return -EFAULT;
+
+	ret = mnt_want_write(filp->f_path.mnt);
+	if (ret)
+		return ret;
+
+	flags = nilfs_mask_flags(inode->i_mode, flags);
+
+	mutex_lock(&inode->i_mutex);
+
+	oldflags = NILFS_I(inode)->i_flags;
+
+	/*
+	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
+	 * relevant capability.
+	 */
+	ret = -EPERM;
+	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
+	    !capable(CAP_LINUX_IMMUTABLE))
+		goto out;
+
+	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
+	if (ret)
+		goto out;
+
+	NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
+		(flags & FS_FL_USER_MODIFIABLE);
+
+	nilfs_set_inode_flags(inode);
+	inode->i_ctime = CURRENT_TIME;
+	if (IS_SYNC(inode))
+		nilfs_set_transaction_flag(NILFS_TI_SYNC);
+
+	nilfs_mark_inode_dirty(inode);
+	ret = nilfs_transaction_commit(inode->i_sb);
+out:
+	mutex_unlock(&inode->i_mutex);
+	mnt_drop_write(filp->f_path.mnt);
+	return ret;
+}
+
+static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
+{
+	return put_user(inode->i_generation, (int __user *)argp);
+}
+
 static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
 				     unsigned int cmd, void __user *argp)
 {
-	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
-	struct inode *cpfile = nilfs->ns_cpfile;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_transaction_info ti;
 	struct nilfs_cpmode cpmode;
 	int ret;
@@ -121,7 +186,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
 
 	nilfs_transaction_begin(inode->i_sb, &ti, 0);
 	ret = nilfs_cpfile_change_cpmode(
-		cpfile, cpmode.cm_cno, cpmode.cm_mode);
+		nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
 	if (unlikely(ret < 0))
 		nilfs_transaction_abort(inode->i_sb);
 	else
@@ -137,7 +202,7 @@ static int
 nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
 			      unsigned int cmd, void __user *argp)
 {
-	struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_transaction_info ti;
 	__u64 cno;
 	int ret;
@@ -154,7 +219,7 @@ nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
 		goto out;
 
 	nilfs_transaction_begin(inode->i_sb, &ti, 0);
-	ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
+	ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
 	if (unlikely(ret < 0))
 		nilfs_transaction_abort(inode->i_sb);
 	else
@@ -180,7 +245,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
 				  unsigned int cmd, void __user *argp)
 {
-	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_cpstat cpstat;
 	int ret;
 
@@ -211,7 +276,7 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
 static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
 				  unsigned int cmd, void __user *argp)
 {
-	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_sustat sustat;
 	int ret;
 
@@ -267,7 +332,7 @@ nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
 static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
 				  unsigned int cmd, void __user *argp)
 {
-	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_argv argv;
 	int ret;
 
@@ -336,7 +401,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
 				   struct nilfs_argv *argv, void *buf)
 {
 	size_t nmembs = argv->v_nmembs;
-	struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct inode *inode;
 	struct nilfs_vdesc *vdesc;
 	struct buffer_head *bh, *n;
@@ -550,7 +615,7 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
 		ret = PTR_ERR(kbufs[4]);
 		goto out;
 	}
-	nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+	nilfs = inode->i_sb->s_fs_info;
 
 	for (n = 0; n < 4; n++) {
 		ret = -EINVAL;
@@ -623,7 +688,7 @@ static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
 		return ret;
 
 	if (argp != NULL) {
-		nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+		nilfs = inode->i_sb->s_fs_info;
 		down_read(&nilfs->ns_segctor_sem);
 		cno = nilfs->ns_cno - 1;
 		up_read(&nilfs->ns_segctor_sem);
@@ -641,7 +706,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
 						  void *, size_t, size_t))
 
 {
-	struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
+	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
 	struct nilfs_argv argv;
 	int ret;
 
@@ -666,6 +731,12 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	void __user *argp = (void __user *)arg;
 
 	switch (cmd) {
+	case FS_IOC_GETFLAGS:
+		return nilfs_ioctl_getflags(inode, argp);
+	case FS_IOC_SETFLAGS:
+		return nilfs_ioctl_setflags(inode, filp, argp);
+	case FS_IOC_GETVERSION:
+		return nilfs_ioctl_getversion(inode, argp);
 	case NILFS_IOCTL_CHANGE_CPMODE:
 		return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
 	case NILFS_IOCTL_DELETE_CHECKPOINT:
@@ -696,3 +767,23 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		return -ENOTTY;
 	}
 }
+
+#ifdef CONFIG_COMPAT
+long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case FS_IOC32_GETFLAGS:
+		cmd = FS_IOC_GETFLAGS;
+		break;
+	case FS_IOC32_SETFLAGS:
+		cmd = FS_IOC_SETFLAGS;
+		break;
+	case FS_IOC32_GETVERSION:
+		cmd = FS_IOC_GETVERSION;
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
diff --git a/fs/nilfs2/mdt.h b/fs/nilfs2/mdt.h
index b13734b..ed68563 100644
--- a/fs/nilfs2/mdt.h
+++ b/fs/nilfs2/mdt.h
@@ -66,7 +66,7 @@ static inline struct nilfs_mdt_info *NILFS_MDT(const struct inode *inode)
 
 static inline struct the_nilfs *NILFS_I_NILFS(struct inode *inode)
 {
-	return NILFS_SB(inode->i_sb)->s_nilfs;
+	return inode->i_sb->s_fs_info;
 }
 
 /* Default GFP flags using highmem */
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 161791d..546849b 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -482,7 +482,7 @@ static struct dentry *nilfs_get_dentry(struct super_block *sb, u64 cno,
 	if (ino < NILFS_FIRST_INO(sb) && ino != NILFS_ROOT_INO)
 		return ERR_PTR(-ESTALE);
 
-	root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+	root = nilfs_lookup_root(sb->s_fs_info, cno);
 	if (!root)
 		return ERR_PTR(-ESTALE);
 
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 777e8fd..856e8e4 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -30,7 +30,6 @@
 #include <linux/blkdev.h>
 #include <linux/nilfs2_fs.h>
 #include "the_nilfs.h"
-#include "sb.h"
 #include "bmap.h"
 
 /*
@@ -122,7 +121,7 @@ enum {
 #define NILFS_SYS_INO_BITS   \
   ((unsigned int)(1 << NILFS_ROOT_INO) | NILFS_MDT_INO_BITS)
 
-#define NILFS_FIRST_INO(sb)  (NILFS_SB(sb)->s_nilfs->ns_first_ino)
+#define NILFS_FIRST_INO(sb) (((struct the_nilfs *)sb->s_fs_info)->ns_first_ino)
 
 #define NILFS_MDT_INODE(sb, ino) \
   ((ino) < NILFS_FIRST_INO(sb) && (NILFS_MDT_INO_BITS & (1 << (ino))))
@@ -212,6 +211,23 @@ static inline int nilfs_init_acl(struct inode *inode, struct inode *dir)
 
 #define NILFS_ATIME_DISABLE
 
+/* Flags that should be inherited by new inodes from their parent. */
+#define NILFS_FL_INHERITED						\
+	(FS_SECRM_FL | FS_UNRM_FL | FS_COMPR_FL | FS_SYNC_FL |		\
+	 FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL |\
+	 FS_COMPRBLK_FL | FS_NOCOMP_FL | FS_NOTAIL_FL | FS_DIRSYNC_FL)
+
+/* Mask out flags that are inappropriate for the given type of inode. */
+static inline __u32 nilfs_mask_flags(umode_t mode, __u32 flags)
+{
+	if (S_ISDIR(mode))
+		return flags;
+	else if (S_ISREG(mode))
+		return flags & ~(FS_DIRSYNC_FL | FS_TOPDIR_FL);
+	else
+		return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
+}
+
 /* dir.c */
 extern int nilfs_add_link(struct dentry *, struct inode *);
 extern ino_t nilfs_inode_by_name(struct inode *, const struct qstr *);
@@ -229,10 +245,13 @@ extern int nilfs_sync_file(struct file *, int);
 
 /* ioctl.c */
 long nilfs_ioctl(struct file *, unsigned int, unsigned long);
+long nilfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *, struct nilfs_argv *,
 				       void **);
 
 /* inode.c */
+void nilfs_inode_add_blocks(struct inode *inode, int n);
+void nilfs_inode_sub_blocks(struct inode *inode, int n);
 extern struct inode *nilfs_new_inode(struct inode *, int);
 extern void nilfs_free_inode(struct inode *);
 extern int nilfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
@@ -275,11 +294,11 @@ extern int nilfs_check_feature_compatibility(struct super_block *,
 					     struct nilfs_super_block *);
 extern void nilfs_set_log_cursor(struct nilfs_super_block *,
 				 struct the_nilfs *);
-extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *,
-						      int flip);
-extern int nilfs_commit_super(struct nilfs_sb_info *, int);
-extern int nilfs_cleanup_super(struct nilfs_sb_info *);
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
+					       int flip);
+int nilfs_commit_super(struct super_block *sb, int flag);
+int nilfs_cleanup_super(struct super_block *sb);
+int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
 			    struct nilfs_root **root);
 int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno);
 
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 3dfcd3b..ba4a645 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -425,7 +425,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
 }
 
 static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
-					      struct nilfs_sb_info *sbi,
+					      struct super_block *sb,
 					      struct nilfs_recovery_info *ri)
 {
 	struct list_head *head = &ri->ri_used_segments;
@@ -501,7 +501,7 @@ static int nilfs_recovery_copy_block(struct the_nilfs *nilfs,
 }
 
 static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
-				      struct nilfs_sb_info *sbi,
+				      struct super_block *sb,
 				      struct nilfs_root *root,
 				      struct list_head *head,
 				      unsigned long *nr_salvaged_blocks)
@@ -514,7 +514,7 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
 	int err = 0, err2 = 0;
 
 	list_for_each_entry_safe(rb, n, head, list) {
-		inode = nilfs_iget(sbi->s_super, root, rb->ino);
+		inode = nilfs_iget(sb, root, rb->ino);
 		if (IS_ERR(inode)) {
 			err = PTR_ERR(inode);
 			inode = NULL;
@@ -572,11 +572,11 @@ static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs,
  * nilfs_do_roll_forward - salvage logical segments newer than the latest
  * checkpoint
  * @nilfs: nilfs object
- * @sbi: nilfs_sb_info
+ * @sb: super block instance
  * @ri: pointer to a nilfs_recovery_info
  */
 static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
-				 struct nilfs_sb_info *sbi,
+				 struct super_block *sb,
 				 struct nilfs_root *root,
 				 struct nilfs_recovery_info *ri)
 {
@@ -648,7 +648,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
 				goto failed;
 			if (flags & NILFS_SS_LOGEND) {
 				err = nilfs_recover_dsync_blocks(
-					nilfs, sbi, root, &dsync_blocks,
+					nilfs, sb, root, &dsync_blocks,
 					&nsalvaged_blocks);
 				if (unlikely(err))
 					goto failed;
@@ -681,7 +681,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
 
 	if (nsalvaged_blocks) {
 		printk(KERN_INFO "NILFS (device %s): salvaged %lu blocks\n",
-		       sbi->s_super->s_id, nsalvaged_blocks);
+		       sb->s_id, nsalvaged_blocks);
 		ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE;
 	}
  out:
@@ -695,7 +695,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs,
 	printk(KERN_ERR
 	       "NILFS (device %s): Error roll-forwarding "
 	       "(err=%d, pseg block=%llu). ",
-	       sbi->s_super->s_id, err, (unsigned long long)pseg_start);
+	       sb->s_id, err, (unsigned long long)pseg_start);
 	goto out;
 }
 
@@ -724,7 +724,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
 /**
  * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint
  * @nilfs: nilfs object
- * @sbi: nilfs_sb_info
+ * @sb: super block instance
  * @ri: pointer to a nilfs_recovery_info struct to store search results.
  *
  * Return Value: On success, 0 is returned.  On error, one of the following
@@ -741,7 +741,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs,
  * %-ENOMEM - Insufficient memory available.
  */
 int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
-			      struct nilfs_sb_info *sbi,
+			      struct super_block *sb,
 			      struct nilfs_recovery_info *ri)
 {
 	struct nilfs_root *root;
@@ -750,32 +750,32 @@ int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs,
 	if (ri->ri_lsegs_start == 0 || ri->ri_lsegs_end == 0)
 		return 0;
 
-	err = nilfs_attach_checkpoint(sbi, ri->ri_cno, true, &root);
+	err = nilfs_attach_checkpoint(sb, ri->ri_cno, true, &root);
 	if (unlikely(err)) {
 		printk(KERN_ERR
 		       "NILFS: error loading the latest checkpoint.\n");
 		return err;
 	}
 
-	err = nilfs_do_roll_forward(nilfs, sbi, root, ri);
+	err = nilfs_do_roll_forward(nilfs, sb, root, ri);
 	if (unlikely(err))
 		goto failed;
 
 	if (ri->ri_need_recovery == NILFS_RECOVERY_ROLLFORWARD_DONE) {
-		err = nilfs_prepare_segment_for_recovery(nilfs, sbi, ri);
+		err = nilfs_prepare_segment_for_recovery(nilfs, sb, ri);
 		if (unlikely(err)) {
 			printk(KERN_ERR "NILFS: Error preparing segments for "
 			       "recovery.\n");
 			goto failed;
 		}
 
-		err = nilfs_attach_segment_constructor(sbi, root);
+		err = nilfs_attach_log_writer(sb, root);
 		if (unlikely(err))
 			goto failed;
 
 		set_nilfs_discontinued(nilfs);
-		err = nilfs_construct_segment(sbi->s_super);
-		nilfs_detach_segment_constructor(sbi);
+		err = nilfs_construct_segment(sb);
+		nilfs_detach_log_writer(sb);
 
 		if (unlikely(err)) {
 			printk(KERN_ERR "NILFS: Oops! recovery failed. "
diff --git a/fs/nilfs2/sb.h b/fs/nilfs2/sb.h
deleted file mode 100644
index 7a17715..0000000
--- a/fs/nilfs2/sb.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * sb.h - NILFS on-memory super block structure.
- *
- * Copyright (C) 2005-2008 Nippon Telegraph and Telephone 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 St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Written by Ryusuke Konishi <ryusuke@osrg.net>
- *
- */
-
-#ifndef _NILFS_SB
-#define _NILFS_SB
-
-#include <linux/types.h>
-#include <linux/fs.h>
-
-struct the_nilfs;
-struct nilfs_sc_info;
-
-/*
- * NILFS super-block data in memory
- */
-struct nilfs_sb_info {
-	/* Mount options */
-	unsigned long s_mount_opt;
-	uid_t s_resuid;
-	gid_t s_resgid;
-
-	unsigned long s_interval;	/* construction interval */
-	unsigned long s_watermark;	/* threshold of data amount
-					   for the segment construction */
-
-	/* Fundamental members */
-	struct super_block *s_super;	/* reverse pointer to super_block */
-	struct the_nilfs *s_nilfs;
-
-	/* Segment constructor */
-	struct list_head s_dirty_files;	/* dirty files list */
-	struct nilfs_sc_info *s_sc_info; /* segment constructor info */
-	spinlock_t s_inode_lock;	/* Lock for the nilfs inode.
-					   It covers s_dirty_files list */
-
-	/* Inode allocator */
-	spinlock_t s_next_gen_lock;
-	u32 s_next_generation;
-};
-
-static inline struct nilfs_sb_info *NILFS_SB(struct super_block *sb)
-{
-	return sb->s_fs_info;
-}
-
-static inline struct nilfs_sc_info *NILFS_SC(struct nilfs_sb_info *sbi)
-{
-	return sbi->s_sc_info;
-}
-
-/*
- * Bit operations for the mount option
- */
-#define nilfs_clear_opt(sbi, opt)  \
-	do { (sbi)->s_mount_opt &= ~NILFS_MOUNT_##opt; } while (0)
-#define nilfs_set_opt(sbi, opt)  \
-	do { (sbi)->s_mount_opt |= NILFS_MOUNT_##opt; } while (0)
-#define nilfs_test_opt(sbi, opt)   ((sbi)->s_mount_opt & NILFS_MOUNT_##opt)
-#define nilfs_write_opt(sbi, mask, opt)					\
-	do { (sbi)->s_mount_opt =					\
-		(((sbi)->s_mount_opt & ~NILFS_MOUNT_##mask) |		\
-		 NILFS_MOUNT_##opt);					\
-	} while (0)
-
-#endif /* _NILFS_SB */
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 2de9f63..afe4f21 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -104,8 +104,7 @@ struct nilfs_sc_operations {
 static void nilfs_segctor_start_timer(struct nilfs_sc_info *);
 static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int);
 static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *);
-static void nilfs_dispose_list(struct nilfs_sb_info *, struct list_head *,
-			       int);
+static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);
 
 #define nilfs_cnt32_gt(a, b)   \
 	(typecheck(__u32, a) && typecheck(__u32, b) && \
@@ -182,7 +181,6 @@ int nilfs_transaction_begin(struct super_block *sb,
 			    struct nilfs_transaction_info *ti,
 			    int vacancy_check)
 {
-	struct nilfs_sb_info *sbi;
 	struct the_nilfs *nilfs;
 	int ret = nilfs_prepare_segment_lock(ti);
 
@@ -193,8 +191,7 @@ int nilfs_transaction_begin(struct super_block *sb,
 
 	vfs_check_frozen(sb, SB_FREEZE_WRITE);
 
-	sbi = NILFS_SB(sb);
-	nilfs = sbi->s_nilfs;
+	nilfs = sb->s_fs_info;
 	down_read(&nilfs->ns_segctor_sem);
 	if (vacancy_check && nilfs_near_disk_full(nilfs)) {
 		up_read(&nilfs->ns_segctor_sem);
@@ -225,8 +222,7 @@ int nilfs_transaction_begin(struct super_block *sb,
 int nilfs_transaction_commit(struct super_block *sb)
 {
 	struct nilfs_transaction_info *ti = current->journal_info;
-	struct nilfs_sb_info *sbi;
-	struct nilfs_sc_info *sci;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	int err = 0;
 
 	BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
@@ -235,16 +231,15 @@ int nilfs_transaction_commit(struct super_block *sb)
 		ti->ti_count--;
 		return 0;
 	}
-	sbi = NILFS_SB(sb);
-	sci = NILFS_SC(sbi);
-	if (sci != NULL) {
+	if (nilfs->ns_writer) {
+		struct nilfs_sc_info *sci = nilfs->ns_writer;
+
 		if (ti->ti_flags & NILFS_TI_COMMIT)
 			nilfs_segctor_start_timer(sci);
-		if (atomic_read(&sbi->s_nilfs->ns_ndirtyblks) >
-		    sci->sc_watermark)
+		if (atomic_read(&nilfs->ns_ndirtyblks) > sci->sc_watermark)
 			nilfs_segctor_do_flush(sci, 0);
 	}
-	up_read(&sbi->s_nilfs->ns_segctor_sem);
+	up_read(&nilfs->ns_segctor_sem);
 	current->journal_info = ti->ti_save;
 
 	if (ti->ti_flags & NILFS_TI_SYNC)
@@ -257,13 +252,14 @@ int nilfs_transaction_commit(struct super_block *sb)
 void nilfs_transaction_abort(struct super_block *sb)
 {
 	struct nilfs_transaction_info *ti = current->journal_info;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 
 	BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
 	if (ti->ti_count > 0) {
 		ti->ti_count--;
 		return;
 	}
-	up_read(&NILFS_SB(sb)->s_nilfs->ns_segctor_sem);
+	up_read(&nilfs->ns_segctor_sem);
 
 	current->journal_info = ti->ti_save;
 	if (ti->ti_flags & NILFS_TI_DYNAMIC_ALLOC)
@@ -272,9 +268,8 @@ void nilfs_transaction_abort(struct super_block *sb)
 
 void nilfs_relax_pressure_in_lock(struct super_block *sb)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct nilfs_sc_info *sci = NILFS_SC(sbi);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
+	struct nilfs_sc_info *sci = nilfs->ns_writer;
 
 	if (!sci || !sci->sc_flush_request)
 		return;
@@ -294,11 +289,13 @@ void nilfs_relax_pressure_in_lock(struct super_block *sb)
 	downgrade_write(&nilfs->ns_segctor_sem);
 }
 
-static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,
+static void nilfs_transaction_lock(struct super_block *sb,
 				   struct nilfs_transaction_info *ti,
 				   int gcflag)
 {
 	struct nilfs_transaction_info *cur_ti = current->journal_info;
+	struct the_nilfs *nilfs = sb->s_fs_info;
+	struct nilfs_sc_info *sci = nilfs->ns_writer;
 
 	WARN_ON(cur_ti);
 	ti->ti_flags = NILFS_TI_WRITER;
@@ -309,30 +306,31 @@ static void nilfs_transaction_lock(struct nilfs_sb_info *sbi,
 	current->journal_info = ti;
 
 	for (;;) {
-		down_write(&sbi->s_nilfs->ns_segctor_sem);
-		if (!test_bit(NILFS_SC_PRIOR_FLUSH, &NILFS_SC(sbi)->sc_flags))
+		down_write(&nilfs->ns_segctor_sem);
+		if (!test_bit(NILFS_SC_PRIOR_FLUSH, &sci->sc_flags))
 			break;
 
-		nilfs_segctor_do_immediate_flush(NILFS_SC(sbi));
+		nilfs_segctor_do_immediate_flush(sci);
 
-		up_write(&sbi->s_nilfs->ns_segctor_sem);
+		up_write(&nilfs->ns_segctor_sem);
 		yield();
 	}
 	if (gcflag)
 		ti->ti_flags |= NILFS_TI_GC;
 }
 
-static void nilfs_transaction_unlock(struct nilfs_sb_info *sbi)
+static void nilfs_transaction_unlock(struct super_block *sb)
 {
 	struct nilfs_transaction_info *ti = current->journal_info;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 
 	BUG_ON(ti == NULL || ti->ti_magic != NILFS_TI_MAGIC);
 	BUG_ON(ti->ti_count > 0);
 
-	up_write(&sbi->s_nilfs->ns_segctor_sem);
+	up_write(&nilfs->ns_segctor_sem);
 	current->journal_info = ti->ti_save;
 	if (!list_empty(&ti->ti_garbage))
-		nilfs_dispose_list(sbi, &ti->ti_garbage, 0);
+		nilfs_dispose_list(nilfs, &ti->ti_garbage, 0);
 }
 
 static void *nilfs_segctor_map_segsum_entry(struct nilfs_sc_info *sci,
@@ -714,7 +712,7 @@ static void nilfs_lookup_dirty_node_buffers(struct inode *inode,
 	}
 }
 
-static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
+static void nilfs_dispose_list(struct the_nilfs *nilfs,
 			       struct list_head *head, int force)
 {
 	struct nilfs_inode_info *ii, *n;
@@ -722,7 +720,7 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
 	unsigned nv = 0;
 
 	while (!list_empty(head)) {
-		spin_lock(&sbi->s_inode_lock);
+		spin_lock(&nilfs->ns_inode_lock);
 		list_for_each_entry_safe(ii, n, head, i_dirty) {
 			list_del_init(&ii->i_dirty);
 			if (force) {
@@ -733,14 +731,14 @@ static void nilfs_dispose_list(struct nilfs_sb_info *sbi,
 			} else if (test_bit(NILFS_I_DIRTY, &ii->i_state)) {
 				set_bit(NILFS_I_QUEUED, &ii->i_state);
 				list_add_tail(&ii->i_dirty,
-					      &sbi->s_dirty_files);
+					      &nilfs->ns_dirty_files);
 				continue;
 			}
 			ivec[nv++] = ii;
 			if (nv == SC_N_INODEVEC)
 				break;
 		}
-		spin_unlock(&sbi->s_inode_lock);
+		spin_unlock(&nilfs->ns_inode_lock);
 
 		for (pii = ivec; nv > 0; pii++, nv--)
 			iput(&(*pii)->vfs_inode);
@@ -773,24 +771,23 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)
 
 static int nilfs_segctor_confirm(struct nilfs_sc_info *sci)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	int ret = 0;
 
-	if (nilfs_test_metadata_dirty(sbi->s_nilfs, sci->sc_root))
+	if (nilfs_test_metadata_dirty(nilfs, sci->sc_root))
 		set_bit(NILFS_SC_DIRTY, &sci->sc_flags);
 
-	spin_lock(&sbi->s_inode_lock);
-	if (list_empty(&sbi->s_dirty_files) && nilfs_segctor_clean(sci))
+	spin_lock(&nilfs->ns_inode_lock);
+	if (list_empty(&nilfs->ns_dirty_files) && nilfs_segctor_clean(sci))
 		ret++;
 
-	spin_unlock(&sbi->s_inode_lock);
+	spin_unlock(&nilfs->ns_inode_lock);
 	return ret;
 }
 
 static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 
 	nilfs_mdt_clear_dirty(sci->sc_root->ifile);
 	nilfs_mdt_clear_dirty(nilfs->ns_cpfile);
@@ -800,7 +797,7 @@ static void nilfs_segctor_clear_metadata_dirty(struct nilfs_sc_info *sci)
 
 static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
 {
-	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	struct buffer_head *bh_cp;
 	struct nilfs_checkpoint *raw_cp;
 	int err;
@@ -824,8 +821,7 @@ static int nilfs_segctor_create_checkpoint(struct nilfs_sc_info *sci)
 
 static int nilfs_segctor_fill_in_checkpoint(struct nilfs_sc_info *sci)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	struct buffer_head *bh_cp;
 	struct nilfs_checkpoint *raw_cp;
 	int err;
@@ -1049,8 +1045,7 @@ static int nilfs_segctor_scan_file_dsync(struct nilfs_sc_info *sci,
 
 static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	struct list_head *head;
 	struct nilfs_inode_info *ii;
 	size_t ndone;
@@ -1859,7 +1854,7 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci)
 {
 	struct nilfs_segment_buffer *segbuf;
 	struct page *bd_page = NULL, *fs_page = NULL;
-	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	int update_sr = false;
 
 	list_for_each_entry(segbuf, &sci->sc_write_logs, sb_list) {
@@ -1963,30 +1958,30 @@ static int nilfs_segctor_wait(struct nilfs_sc_info *sci)
 	return ret;
 }
 
-static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
-					struct nilfs_sb_info *sbi)
+static int nilfs_segctor_collect_dirty_files(struct nilfs_sc_info *sci,
+					     struct the_nilfs *nilfs)
 {
 	struct nilfs_inode_info *ii, *n;
 	struct inode *ifile = sci->sc_root->ifile;
 
-	spin_lock(&sbi->s_inode_lock);
+	spin_lock(&nilfs->ns_inode_lock);
  retry:
-	list_for_each_entry_safe(ii, n, &sbi->s_dirty_files, i_dirty) {
+	list_for_each_entry_safe(ii, n, &nilfs->ns_dirty_files, i_dirty) {
 		if (!ii->i_bh) {
 			struct buffer_head *ibh;
 			int err;
 
-			spin_unlock(&sbi->s_inode_lock);
+			spin_unlock(&nilfs->ns_inode_lock);
 			err = nilfs_ifile_get_inode_block(
 				ifile, ii->vfs_inode.i_ino, &ibh);
 			if (unlikely(err)) {
-				nilfs_warning(sbi->s_super, __func__,
+				nilfs_warning(sci->sc_super, __func__,
 					      "failed to get inode block.\n");
 				return err;
 			}
 			nilfs_mdt_mark_buffer_dirty(ibh);
 			nilfs_mdt_mark_dirty(ifile);
-			spin_lock(&sbi->s_inode_lock);
+			spin_lock(&nilfs->ns_inode_lock);
 			if (likely(!ii->i_bh))
 				ii->i_bh = ibh;
 			else
@@ -1999,18 +1994,18 @@ static int nilfs_segctor_check_in_files(struct nilfs_sc_info *sci,
 		list_del(&ii->i_dirty);
 		list_add_tail(&ii->i_dirty, &sci->sc_dirty_files);
 	}
-	spin_unlock(&sbi->s_inode_lock);
+	spin_unlock(&nilfs->ns_inode_lock);
 
 	return 0;
 }
 
-static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
-					  struct nilfs_sb_info *sbi)
+static void nilfs_segctor_drop_written_files(struct nilfs_sc_info *sci,
+					     struct the_nilfs *nilfs)
 {
 	struct nilfs_transaction_info *ti = current->journal_info;
 	struct nilfs_inode_info *ii, *n;
 
-	spin_lock(&sbi->s_inode_lock);
+	spin_lock(&nilfs->ns_inode_lock);
 	list_for_each_entry_safe(ii, n, &sci->sc_dirty_files, i_dirty) {
 		if (!test_and_clear_bit(NILFS_I_UPDATED, &ii->i_state) ||
 		    test_bit(NILFS_I_DIRTY, &ii->i_state))
@@ -2022,7 +2017,7 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
 		list_del(&ii->i_dirty);
 		list_add_tail(&ii->i_dirty, &ti->ti_garbage);
 	}
-	spin_unlock(&sbi->s_inode_lock);
+	spin_unlock(&nilfs->ns_inode_lock);
 }
 
 /*
@@ -2030,15 +2025,14 @@ static void nilfs_segctor_check_out_files(struct nilfs_sc_info *sci,
  */
 static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	struct page *failed_page;
 	int err;
 
 	sci->sc_stage.scnt = NILFS_ST_INIT;
 	sci->sc_cno = nilfs->ns_cno;
 
-	err = nilfs_segctor_check_in_files(sci, sbi);
+	err = nilfs_segctor_collect_dirty_files(sci, nilfs);
 	if (unlikely(err))
 		goto out;
 
@@ -2116,7 +2110,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
 	} while (sci->sc_stage.scnt != NILFS_ST_DONE);
 
  out:
-	nilfs_segctor_check_out_files(sci, sbi);
+	nilfs_segctor_drop_written_files(sci, nilfs);
 	return err;
 
  failed_to_write:
@@ -2169,8 +2163,8 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *sci, int bn)
  */
 void nilfs_flush_segment(struct super_block *sb, ino_t ino)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct nilfs_sc_info *sci = NILFS_SC(sbi);
+	struct the_nilfs *nilfs = sb->s_fs_info;
+	struct nilfs_sc_info *sci = nilfs->ns_writer;
 
 	if (!sci || nilfs_doing_construction())
 		return;
@@ -2259,8 +2253,8 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
  */
 int nilfs_construct_segment(struct super_block *sb)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct nilfs_sc_info *sci = NILFS_SC(sbi);
+	struct the_nilfs *nilfs = sb->s_fs_info;
+	struct nilfs_sc_info *sci = nilfs->ns_writer;
 	struct nilfs_transaction_info *ti;
 	int err;
 
@@ -2297,8 +2291,8 @@ int nilfs_construct_segment(struct super_block *sb)
 int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
 				  loff_t start, loff_t end)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct nilfs_sc_info *sci = NILFS_SC(sbi);
+	struct the_nilfs *nilfs = sb->s_fs_info;
+	struct nilfs_sc_info *sci = nilfs->ns_writer;
 	struct nilfs_inode_info *ii;
 	struct nilfs_transaction_info ti;
 	int err = 0;
@@ -2306,33 +2300,33 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
 	if (!sci)
 		return -EROFS;
 
-	nilfs_transaction_lock(sbi, &ti, 0);
+	nilfs_transaction_lock(sb, &ti, 0);
 
 	ii = NILFS_I(inode);
 	if (test_bit(NILFS_I_INODE_DIRTY, &ii->i_state) ||
-	    nilfs_test_opt(sbi, STRICT_ORDER) ||
+	    nilfs_test_opt(nilfs, STRICT_ORDER) ||
 	    test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags) ||
-	    nilfs_discontinued(sbi->s_nilfs)) {
-		nilfs_transaction_unlock(sbi);
+	    nilfs_discontinued(nilfs)) {
+		nilfs_transaction_unlock(sb);
 		err = nilfs_segctor_sync(sci);
 		return err;
 	}
 
-	spin_lock(&sbi->s_inode_lock);
+	spin_lock(&nilfs->ns_inode_lock);
 	if (!test_bit(NILFS_I_QUEUED, &ii->i_state) &&
 	    !test_bit(NILFS_I_BUSY, &ii->i_state)) {
-		spin_unlock(&sbi->s_inode_lock);
-		nilfs_transaction_unlock(sbi);
+		spin_unlock(&nilfs->ns_inode_lock);
+		nilfs_transaction_unlock(sb);
 		return 0;
 	}
-	spin_unlock(&sbi->s_inode_lock);
+	spin_unlock(&nilfs->ns_inode_lock);
 	sci->sc_dsync_inode = ii;
 	sci->sc_dsync_start = start;
 	sci->sc_dsync_end = end;
 
 	err = nilfs_segctor_do_construct(sci, SC_LSEG_DSYNC);
 
-	nilfs_transaction_unlock(sbi);
+	nilfs_transaction_unlock(sb);
 	return err;
 }
 
@@ -2388,8 +2382,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
  */
 static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	struct nilfs_super_block **sbp;
 	int err = 0;
 
@@ -2407,11 +2400,12 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode)
 		    nilfs_discontinued(nilfs)) {
 			down_write(&nilfs->ns_sem);
 			err = -EIO;
-			sbp = nilfs_prepare_super(sbi,
+			sbp = nilfs_prepare_super(sci->sc_super,
 						  nilfs_sb_will_flip(nilfs));
 			if (likely(sbp)) {
 				nilfs_set_log_cursor(sbp[0], nilfs);
-				err = nilfs_commit_super(sbi, NILFS_SB_COMMIT);
+				err = nilfs_commit_super(sci->sc_super,
+							 NILFS_SB_COMMIT);
 			}
 			up_write(&nilfs->ns_sem);
 		}
@@ -2443,16 +2437,15 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head)
 int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
 			 void **kbufs)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct nilfs_sc_info *sci = NILFS_SC(sbi);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
+	struct nilfs_sc_info *sci = nilfs->ns_writer;
 	struct nilfs_transaction_info ti;
 	int err;
 
 	if (unlikely(!sci))
 		return -EROFS;
 
-	nilfs_transaction_lock(sbi, &ti, 1);
+	nilfs_transaction_lock(sb, &ti, 1);
 
 	err = nilfs_mdt_save_to_shadow_map(nilfs->ns_dat);
 	if (unlikely(err))
@@ -2480,14 +2473,14 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(sci->sc_interval);
 	}
-	if (nilfs_test_opt(sbi, DISCARD)) {
+	if (nilfs_test_opt(nilfs, DISCARD)) {
 		int ret = nilfs_discard_segments(nilfs, sci->sc_freesegs,
 						 sci->sc_nfreesegs);
 		if (ret) {
 			printk(KERN_WARNING
 			       "NILFS warning: error %d on discard request, "
 			       "turning discards off for the device\n", ret);
-			nilfs_clear_opt(sbi, DISCARD);
+			nilfs_clear_opt(nilfs, DISCARD);
 		}
 	}
 
@@ -2495,16 +2488,15 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
 	sci->sc_freesegs = NULL;
 	sci->sc_nfreesegs = 0;
 	nilfs_mdt_clear_shadow_map(nilfs->ns_dat);
-	nilfs_transaction_unlock(sbi);
+	nilfs_transaction_unlock(sb);
 	return err;
 }
 
 static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
 	struct nilfs_transaction_info ti;
 
-	nilfs_transaction_lock(sbi, &ti, 0);
+	nilfs_transaction_lock(sci->sc_super, &ti, 0);
 	nilfs_segctor_construct(sci, mode);
 
 	/*
@@ -2515,7 +2507,7 @@ static void nilfs_segctor_thread_construct(struct nilfs_sc_info *sci, int mode)
 	if (test_bit(NILFS_SC_UNCLOSED, &sci->sc_flags))
 		nilfs_segctor_start_timer(sci);
 
-	nilfs_transaction_unlock(sbi);
+	nilfs_transaction_unlock(sci->sc_super);
 }
 
 static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *sci)
@@ -2561,7 +2553,7 @@ static int nilfs_segctor_flush_mode(struct nilfs_sc_info *sci)
 static int nilfs_segctor_thread(void *arg)
 {
 	struct nilfs_sc_info *sci = (struct nilfs_sc_info *)arg;
-	struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	int timeout = 0;
 
 	sci->sc_timer.data = (unsigned long)current;
@@ -2672,17 +2664,17 @@ static void nilfs_segctor_kill_thread(struct nilfs_sc_info *sci)
 /*
  * Setup & clean-up functions
  */
-static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi,
+static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
 					       struct nilfs_root *root)
 {
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_sc_info *sci;
 
 	sci = kzalloc(sizeof(*sci), GFP_KERNEL);
 	if (!sci)
 		return NULL;
 
-	sci->sc_sbi = sbi;
-	sci->sc_super = sbi->s_super;
+	sci->sc_super = sb;
 
 	nilfs_get_root(root);
 	sci->sc_root = root;
@@ -2702,10 +2694,10 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi,
 	sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ;
 	sci->sc_watermark = NILFS_SC_DEFAULT_WATERMARK;
 
-	if (sbi->s_interval)
-		sci->sc_interval = sbi->s_interval;
-	if (sbi->s_watermark)
-		sci->sc_watermark = sbi->s_watermark;
+	if (nilfs->ns_interval)
+		sci->sc_interval = nilfs->ns_interval;
+	if (nilfs->ns_watermark)
+		sci->sc_watermark = nilfs->ns_watermark;
 	return sci;
 }
 
@@ -2716,12 +2708,11 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
 	/* The segctord thread was stopped and its timer was removed.
 	   But some tasks remain. */
 	do {
-		struct nilfs_sb_info *sbi = sci->sc_sbi;
 		struct nilfs_transaction_info ti;
 
-		nilfs_transaction_lock(sbi, &ti, 0);
+		nilfs_transaction_lock(sci->sc_super, &ti, 0);
 		ret = nilfs_segctor_construct(sci, SC_LSEG_SR);
-		nilfs_transaction_unlock(sbi);
+		nilfs_transaction_unlock(sci->sc_super);
 
 	} while (ret && retrycount-- > 0);
 }
@@ -2736,10 +2727,10 @@ static void nilfs_segctor_write_out(struct nilfs_sc_info *sci)
  */
 static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 {
-	struct nilfs_sb_info *sbi = sci->sc_sbi;
+	struct the_nilfs *nilfs = sci->sc_super->s_fs_info;
 	int flag;
 
-	up_write(&sbi->s_nilfs->ns_segctor_sem);
+	up_write(&nilfs->ns_segctor_sem);
 
 	spin_lock(&sci->sc_state_lock);
 	nilfs_segctor_kill_thread(sci);
@@ -2753,9 +2744,9 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 	WARN_ON(!list_empty(&sci->sc_copied_buffers));
 
 	if (!list_empty(&sci->sc_dirty_files)) {
-		nilfs_warning(sbi->s_super, __func__,
+		nilfs_warning(sci->sc_super, __func__,
 			      "dirty file(s) after the final construction\n");
-		nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1);
+		nilfs_dispose_list(nilfs, &sci->sc_dirty_files, 1);
 	}
 
 	WARN_ON(!list_empty(&sci->sc_segbufs));
@@ -2763,79 +2754,78 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
 
 	nilfs_put_root(sci->sc_root);
 
-	down_write(&sbi->s_nilfs->ns_segctor_sem);
+	down_write(&nilfs->ns_segctor_sem);
 
 	del_timer_sync(&sci->sc_timer);
 	kfree(sci);
 }
 
 /**
- * nilfs_attach_segment_constructor - attach a segment constructor
- * @sbi: nilfs_sb_info
+ * nilfs_attach_log_writer - attach log writer
+ * @sb: super block instance
  * @root: root object of the current filesystem tree
  *
- * nilfs_attach_segment_constructor() allocates a struct nilfs_sc_info,
- * initializes it, and starts the segment constructor.
+ * This allocates a log writer object, initializes it, and starts the
+ * log writer.
  *
  * Return Value: On success, 0 is returned. On error, one of the following
  * negative error code is returned.
  *
  * %-ENOMEM - Insufficient memory available.
  */
-int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
-				     struct nilfs_root *root)
+int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root)
 {
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	int err;
 
-	if (NILFS_SC(sbi)) {
+	if (nilfs->ns_writer) {
 		/*
 		 * This happens if the filesystem was remounted
 		 * read/write after nilfs_error degenerated it into a
 		 * read-only mount.
 		 */
-		nilfs_detach_segment_constructor(sbi);
+		nilfs_detach_log_writer(sb);
 	}
 
-	sbi->s_sc_info = nilfs_segctor_new(sbi, root);
-	if (!sbi->s_sc_info)
+	nilfs->ns_writer = nilfs_segctor_new(sb, root);
+	if (!nilfs->ns_writer)
 		return -ENOMEM;
 
-	err = nilfs_segctor_start_thread(NILFS_SC(sbi));
+	err = nilfs_segctor_start_thread(nilfs->ns_writer);
 	if (err) {
-		kfree(sbi->s_sc_info);
-		sbi->s_sc_info = NULL;
+		kfree(nilfs->ns_writer);
+		nilfs->ns_writer = NULL;
 	}
 	return err;
 }
 
 /**
- * nilfs_detach_segment_constructor - destroy the segment constructor
- * @sbi: nilfs_sb_info
+ * nilfs_detach_log_writer - destroy log writer
+ * @sb: super block instance
  *
- * nilfs_detach_segment_constructor() kills the segment constructor daemon,
- * frees the struct nilfs_sc_info, and destroy the dirty file list.
+ * This kills log writer daemon, frees the log writer object, and
+ * destroys list of dirty files.
  */
-void nilfs_detach_segment_constructor(struct nilfs_sb_info *sbi)
+void nilfs_detach_log_writer(struct super_block *sb)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	LIST_HEAD(garbage_list);
 
 	down_write(&nilfs->ns_segctor_sem);
-	if (NILFS_SC(sbi)) {
-		nilfs_segctor_destroy(NILFS_SC(sbi));
-		sbi->s_sc_info = NULL;
+	if (nilfs->ns_writer) {
+		nilfs_segctor_destroy(nilfs->ns_writer);
+		nilfs->ns_writer = NULL;
 	}
 
 	/* Force to free the list of dirty files */
-	spin_lock(&sbi->s_inode_lock);
-	if (!list_empty(&sbi->s_dirty_files)) {
-		list_splice_init(&sbi->s_dirty_files, &garbage_list);
-		nilfs_warning(sbi->s_super, __func__,
-			      "Non empty dirty list after the last "
-			      "segment construction\n");
-	}
-	spin_unlock(&sbi->s_inode_lock);
+	spin_lock(&nilfs->ns_inode_lock);
+	if (!list_empty(&nilfs->ns_dirty_files)) {
+		list_splice_init(&nilfs->ns_dirty_files, &garbage_list);
+		nilfs_warning(sb, __func__,
+			      "Hit dirty file after stopped log writer\n");
+	}
+	spin_unlock(&nilfs->ns_inode_lock);
 	up_write(&nilfs->ns_segctor_sem);
 
-	nilfs_dispose_list(sbi, &garbage_list, 1);
+	nilfs_dispose_list(nilfs, &garbage_list, 1);
 }
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index cd8056e..6c02a86 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -27,7 +27,7 @@
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
 #include <linux/nilfs2_fs.h>
-#include "sb.h"
+#include "nilfs.h"
 
 struct nilfs_root;
 
@@ -88,7 +88,6 @@ struct nilfs_segsum_pointer {
 /**
  * struct nilfs_sc_info - Segment constructor information
  * @sc_super: Back pointer to super_block struct
- * @sc_sbi: Back pointer to nilfs_sb_info struct
  * @sc_root: root object of the current filesystem tree
  * @sc_nblk_inc: Block count of current generation
  * @sc_dirty_files: List of files to be written
@@ -131,7 +130,6 @@ struct nilfs_segsum_pointer {
  */
 struct nilfs_sc_info {
 	struct super_block     *sc_super;
-	struct nilfs_sb_info   *sc_sbi;
 	struct nilfs_root      *sc_root;
 
 	unsigned long		sc_nblk_inc;
@@ -235,18 +233,16 @@ extern void nilfs_flush_segment(struct super_block *, ino_t);
 extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
 				void **);
 
-int nilfs_attach_segment_constructor(struct nilfs_sb_info *sbi,
-				     struct nilfs_root *root);
-extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
+int nilfs_attach_log_writer(struct super_block *sb, struct nilfs_root *root);
+void nilfs_detach_log_writer(struct super_block *sb);
 
 /* recovery.c */
 extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t,
 				       struct buffer_head **, int);
 extern int nilfs_search_super_root(struct the_nilfs *,
 				   struct nilfs_recovery_info *);
-extern int nilfs_salvage_orphan_logs(struct the_nilfs *,
-				     struct nilfs_sb_info *,
-				     struct nilfs_recovery_info *);
+int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, struct super_block *sb,
+			      struct nilfs_recovery_info *ri);
 extern void nilfs_dispose_segment_list(struct list_head *);
 
 #endif /* _NILFS_SEGMENT_H */
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 1673b3d..062cca0 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -43,7 +43,6 @@
 #include <linux/init.h>
 #include <linux/blkdev.h>
 #include <linux/parser.h>
-#include <linux/random.h>
 #include <linux/crc32.h>
 #include <linux/vfs.h>
 #include <linux/writeback.h>
@@ -72,23 +71,23 @@ struct kmem_cache *nilfs_transaction_cachep;
 struct kmem_cache *nilfs_segbuf_cachep;
 struct kmem_cache *nilfs_btree_path_cache;
 
-static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount);
+static int nilfs_setup_super(struct super_block *sb, int is_mount);
 static int nilfs_remount(struct super_block *sb, int *flags, char *data);
 
-static void nilfs_set_error(struct nilfs_sb_info *sbi)
+static void nilfs_set_error(struct super_block *sb)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_super_block **sbp;
 
 	down_write(&nilfs->ns_sem);
 	if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) {
 		nilfs->ns_mount_state |= NILFS_ERROR_FS;
-		sbp = nilfs_prepare_super(sbi, 0);
+		sbp = nilfs_prepare_super(sb, 0);
 		if (likely(sbp)) {
 			sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
 			if (sbp[1])
 				sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS);
-			nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL);
+			nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
 		}
 	}
 	up_write(&nilfs->ns_sem);
@@ -109,7 +108,7 @@ static void nilfs_set_error(struct nilfs_sb_info *sbi)
 void nilfs_error(struct super_block *sb, const char *function,
 		 const char *fmt, ...)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct va_format vaf;
 	va_list args;
 
@@ -124,15 +123,15 @@ void nilfs_error(struct super_block *sb, const char *function,
 	va_end(args);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		nilfs_set_error(sbi);
+		nilfs_set_error(sb);
 
-		if (nilfs_test_opt(sbi, ERRORS_RO)) {
+		if (nilfs_test_opt(nilfs, ERRORS_RO)) {
 			printk(KERN_CRIT "Remounting filesystem read-only\n");
 			sb->s_flags |= MS_RDONLY;
 		}
 	}
 
-	if (nilfs_test_opt(sbi, ERRORS_PANIC))
+	if (nilfs_test_opt(nilfs, ERRORS_PANIC))
 		panic("NILFS (device %s): panic forced after error\n",
 		      sb->s_id);
 }
@@ -189,14 +188,14 @@ void nilfs_destroy_inode(struct inode *inode)
 	call_rcu(&inode->i_rcu, nilfs_i_callback);
 }
 
-static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag)
+static int nilfs_sync_super(struct super_block *sb, int flag)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	int err;
 
  retry:
 	set_buffer_dirty(nilfs->ns_sbh[0]);
-	if (nilfs_test_opt(sbi, BARRIER)) {
+	if (nilfs_test_opt(nilfs, BARRIER)) {
 		err = __sync_dirty_buffer(nilfs->ns_sbh[0],
 					  WRITE_SYNC | WRITE_FLUSH_FUA);
 	} else {
@@ -263,10 +262,10 @@ void nilfs_set_log_cursor(struct nilfs_super_block *sbp,
 	spin_unlock(&nilfs->ns_last_segment_lock);
 }
 
-struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
+struct nilfs_super_block **nilfs_prepare_super(struct super_block *sb,
 					       int flip)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
 
 	/* nilfs->ns_sem must be locked by the caller. */
@@ -276,7 +275,7 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
 			memcpy(sbp[0], sbp[1], nilfs->ns_sbsize);
 		} else {
 			printk(KERN_CRIT "NILFS: superblock broke on dev %s\n",
-			       sbi->s_super->s_id);
+			       sb->s_id);
 			return NULL;
 		}
 	} else if (sbp[1] &&
@@ -290,9 +289,9 @@ struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi,
 	return sbp;
 }
 
-int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag)
+int nilfs_commit_super(struct super_block *sb, int flag)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
 	time_t t;
 
@@ -312,27 +311,28 @@ int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag)
 					    nilfs->ns_sbsize));
 	}
 	clear_nilfs_sb_dirty(nilfs);
-	return nilfs_sync_super(sbi, flag);
+	return nilfs_sync_super(sb, flag);
 }
 
 /**
  * nilfs_cleanup_super() - write filesystem state for cleanup
- * @sbi: nilfs_sb_info to be unmounted or degraded to read-only
+ * @sb: super block instance to be unmounted or degraded to read-only
  *
  * This function restores state flags in the on-disk super block.
  * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the
  * filesystem was not clean previously.
  */
-int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
+int nilfs_cleanup_super(struct super_block *sb)
 {
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_super_block **sbp;
 	int flag = NILFS_SB_COMMIT;
 	int ret = -EIO;
 
-	sbp = nilfs_prepare_super(sbi, 0);
+	sbp = nilfs_prepare_super(sb, 0);
 	if (sbp) {
-		sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state);
-		nilfs_set_log_cursor(sbp[0], sbi->s_nilfs);
+		sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state);
+		nilfs_set_log_cursor(sbp[0], nilfs);
 		if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) {
 			/*
 			 * make the "clean" flag also to the opposite
@@ -342,21 +342,20 @@ int nilfs_cleanup_super(struct nilfs_sb_info *sbi)
 			sbp[1]->s_state = sbp[0]->s_state;
 			flag = NILFS_SB_COMMIT_ALL;
 		}
-		ret = nilfs_commit_super(sbi, flag);
+		ret = nilfs_commit_super(sb, flag);
 	}
 	return ret;
 }
 
 static void nilfs_put_super(struct super_block *sb)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 
-	nilfs_detach_segment_constructor(sbi);
+	nilfs_detach_log_writer(sb);
 
 	if (!(sb->s_flags & MS_RDONLY)) {
 		down_write(&nilfs->ns_sem);
-		nilfs_cleanup_super(sbi);
+		nilfs_cleanup_super(sb);
 		up_write(&nilfs->ns_sem);
 	}
 
@@ -365,15 +364,12 @@ static void nilfs_put_super(struct super_block *sb)
 	iput(nilfs->ns_dat);
 
 	destroy_nilfs(nilfs);
-	sbi->s_super = NULL;
 	sb->s_fs_info = NULL;
-	kfree(sbi);
 }
 
 static int nilfs_sync_fs(struct super_block *sb, int wait)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_super_block **sbp;
 	int err = 0;
 
@@ -383,10 +379,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
 
 	down_write(&nilfs->ns_sem);
 	if (nilfs_sb_dirty(nilfs)) {
-		sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs));
+		sbp = nilfs_prepare_super(sb, nilfs_sb_will_flip(nilfs));
 		if (likely(sbp)) {
 			nilfs_set_log_cursor(sbp[0], nilfs);
-			nilfs_commit_super(sbi, NILFS_SB_COMMIT);
+			nilfs_commit_super(sb, NILFS_SB_COMMIT);
 		}
 	}
 	up_write(&nilfs->ns_sem);
@@ -394,10 +390,10 @@ static int nilfs_sync_fs(struct super_block *sb, int wait)
 	return err;
 }
 
-int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
+int nilfs_attach_checkpoint(struct super_block *sb, __u64 cno, int curr_mnt,
 			    struct nilfs_root **rootp)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_root *root;
 	struct nilfs_checkpoint *raw_cp;
 	struct buffer_head *bh_cp;
@@ -426,7 +422,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
 		goto failed;
 	}
 
-	err = nilfs_ifile_read(sbi->s_super, root, nilfs->ns_inode_size,
+	err = nilfs_ifile_read(sb, root, nilfs->ns_inode_size,
 			       &raw_cp->cp_ifile_inode, &root->ifile);
 	if (err)
 		goto failed_bh;
@@ -450,8 +446,7 @@ int nilfs_attach_checkpoint(struct nilfs_sb_info *sbi, __u64 cno, int curr_mnt,
 
 static int nilfs_freeze(struct super_block *sb)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	int err;
 
 	if (sb->s_flags & MS_RDONLY)
@@ -459,21 +454,20 @@ static int nilfs_freeze(struct super_block *sb)
 
 	/* Mark super block clean */
 	down_write(&nilfs->ns_sem);
-	err = nilfs_cleanup_super(sbi);
+	err = nilfs_cleanup_super(sb);
 	up_write(&nilfs->ns_sem);
 	return err;
 }
 
 static int nilfs_unfreeze(struct super_block *sb)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 
 	if (sb->s_flags & MS_RDONLY)
 		return 0;
 
 	down_write(&nilfs->ns_sem);
-	nilfs_setup_super(sbi, false);
+	nilfs_setup_super(sb, false);
 	up_write(&nilfs->ns_sem);
 	return 0;
 }
@@ -530,22 +524,22 @@ static int nilfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
 {
 	struct super_block *sb = vfs->mnt_sb;
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_root *root = NILFS_I(vfs->mnt_root->d_inode)->i_root;
 
-	if (!nilfs_test_opt(sbi, BARRIER))
+	if (!nilfs_test_opt(nilfs, BARRIER))
 		seq_puts(seq, ",nobarrier");
 	if (root->cno != NILFS_CPTREE_CURRENT_CNO)
 		seq_printf(seq, ",cp=%llu", (unsigned long long)root->cno);
-	if (nilfs_test_opt(sbi, ERRORS_PANIC))
+	if (nilfs_test_opt(nilfs, ERRORS_PANIC))
 		seq_puts(seq, ",errors=panic");
-	if (nilfs_test_opt(sbi, ERRORS_CONT))
+	if (nilfs_test_opt(nilfs, ERRORS_CONT))
 		seq_puts(seq, ",errors=continue");
-	if (nilfs_test_opt(sbi, STRICT_ORDER))
+	if (nilfs_test_opt(nilfs, STRICT_ORDER))
 		seq_puts(seq, ",order=strict");
-	if (nilfs_test_opt(sbi, NORECOVERY))
+	if (nilfs_test_opt(nilfs, NORECOVERY))
 		seq_puts(seq, ",norecovery");
-	if (nilfs_test_opt(sbi, DISCARD))
+	if (nilfs_test_opt(nilfs, DISCARD))
 		seq_puts(seq, ",discard");
 
 	return 0;
@@ -594,7 +588,7 @@ static match_table_t tokens = {
 
 static int parse_options(char *options, struct super_block *sb, int is_remount)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
 
@@ -609,29 +603,29 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
 		token = match_token(p, tokens, args);
 		switch (token) {
 		case Opt_barrier:
-			nilfs_set_opt(sbi, BARRIER);
+			nilfs_set_opt(nilfs, BARRIER);
 			break;
 		case Opt_nobarrier:
-			nilfs_clear_opt(sbi, BARRIER);
+			nilfs_clear_opt(nilfs, BARRIER);
 			break;
 		case Opt_order:
 			if (strcmp(args[0].from, "relaxed") == 0)
 				/* Ordered data semantics */
-				nilfs_clear_opt(sbi, STRICT_ORDER);
+				nilfs_clear_opt(nilfs, STRICT_ORDER);
 			else if (strcmp(args[0].from, "strict") == 0)
 				/* Strict in-order semantics */
-				nilfs_set_opt(sbi, STRICT_ORDER);
+				nilfs_set_opt(nilfs, STRICT_ORDER);
 			else
 				return 0;
 			break;
 		case Opt_err_panic:
-			nilfs_write_opt(sbi, ERROR_MODE, ERRORS_PANIC);
+			nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_PANIC);
 			break;
 		case Opt_err_ro:
-			nilfs_write_opt(sbi, ERROR_MODE, ERRORS_RO);
+			nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_RO);
 			break;
 		case Opt_err_cont:
-			nilfs_write_opt(sbi, ERROR_MODE, ERRORS_CONT);
+			nilfs_write_opt(nilfs, ERROR_MODE, ERRORS_CONT);
 			break;
 		case Opt_snapshot:
 			if (is_remount) {
@@ -642,13 +636,13 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
 			}
 			break;
 		case Opt_norecovery:
-			nilfs_set_opt(sbi, NORECOVERY);
+			nilfs_set_opt(nilfs, NORECOVERY);
 			break;
 		case Opt_discard:
-			nilfs_set_opt(sbi, DISCARD);
+			nilfs_set_opt(nilfs, DISCARD);
 			break;
 		case Opt_nodiscard:
-			nilfs_clear_opt(sbi, DISCARD);
+			nilfs_clear_opt(nilfs, DISCARD);
 			break;
 		default:
 			printk(KERN_ERR
@@ -660,22 +654,24 @@ static int parse_options(char *options, struct super_block *sb, int is_remount)
 }
 
 static inline void
-nilfs_set_default_options(struct nilfs_sb_info *sbi,
+nilfs_set_default_options(struct super_block *sb,
 			  struct nilfs_super_block *sbp)
 {
-	sbi->s_mount_opt =
+	struct the_nilfs *nilfs = sb->s_fs_info;
+
+	nilfs->ns_mount_opt =
 		NILFS_MOUNT_ERRORS_RO | NILFS_MOUNT_BARRIER;
 }
 
-static int nilfs_setup_super(struct nilfs_sb_info *sbi, int is_mount)
+static int nilfs_setup_super(struct super_block *sb, int is_mount)
 {
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_super_block **sbp;
 	int max_mnt_count;
 	int mnt_count;
 
 	/* nilfs->ns_sem must be locked by the caller. */
-	sbp = nilfs_prepare_super(sbi, 0);
+	sbp = nilfs_prepare_super(sb, 0);
 	if (!sbp)
 		return -EIO;
 
@@ -706,7 +702,7 @@ skip_mount_setup:
 	/* synchronize sbp[1] with sbp[0] */
 	if (sbp[1])
 		memcpy(sbp[1], sbp[0], nilfs->ns_sbsize);
-	return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL);
+	return nilfs_commit_super(sb, NILFS_SB_COMMIT_ALL);
 }
 
 struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb,
@@ -727,7 +723,7 @@ int nilfs_store_magic_and_option(struct super_block *sb,
 				 struct nilfs_super_block *sbp,
 				 char *data)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
+	struct the_nilfs *nilfs = sb->s_fs_info;
 
 	sb->s_magic = le16_to_cpu(sbp->s_magic);
 
@@ -736,12 +732,12 @@ int nilfs_store_magic_and_option(struct super_block *sb,
 	sb->s_flags |= MS_NOATIME;
 #endif
 
-	nilfs_set_default_options(sbi, sbp);
+	nilfs_set_default_options(sb, sbp);
 
-	sbi->s_resuid = le16_to_cpu(sbp->s_def_resuid);
-	sbi->s_resgid = le16_to_cpu(sbp->s_def_resgid);
-	sbi->s_interval = le32_to_cpu(sbp->s_c_interval);
-	sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max);
+	nilfs->ns_resuid = le16_to_cpu(sbp->s_def_resuid);
+	nilfs->ns_resgid = le16_to_cpu(sbp->s_def_resgid);
+	nilfs->ns_interval = le32_to_cpu(sbp->s_c_interval);
+	nilfs->ns_watermark = le32_to_cpu(sbp->s_c_block_max);
 
 	return !parse_options(data, sb, 0) ? -EINVAL : 0 ;
 }
@@ -822,7 +818,7 @@ static int nilfs_get_root_dentry(struct super_block *sb,
 static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
 				 struct dentry **root_dentry)
 {
-	struct the_nilfs *nilfs = NILFS_SB(s)->s_nilfs;
+	struct the_nilfs *nilfs = s->s_fs_info;
 	struct nilfs_root *root;
 	int ret;
 
@@ -840,7 +836,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno,
 		goto out;
 	}
 
-	ret = nilfs_attach_checkpoint(NILFS_SB(s), cno, false, &root);
+	ret = nilfs_attach_checkpoint(s, cno, false, &root);
 	if (ret) {
 		printk(KERN_ERR "NILFS: error loading snapshot "
 		       "(checkpoint number=%llu).\n",
@@ -874,7 +870,7 @@ static int nilfs_try_to_shrink_tree(struct dentry *root_dentry)
 
 int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
 {
-	struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	struct nilfs_root *root;
 	struct inode *inode;
 	struct dentry *dentry;
@@ -887,7 +883,7 @@ int nilfs_checkpoint_is_mounted(struct super_block *sb, __u64 cno)
 		return true;	/* protect recent checkpoints */
 
 	ret = false;
-	root = nilfs_lookup_root(NILFS_SB(sb)->s_nilfs, cno);
+	root = nilfs_lookup_root(nilfs, cno);
 	if (root) {
 		inode = nilfs_ilookup(sb, root, NILFS_ROOT_INO);
 		if (inode) {
@@ -917,43 +913,21 @@ static int
 nilfs_fill_super(struct super_block *sb, void *data, int silent)
 {
 	struct the_nilfs *nilfs;
-	struct nilfs_sb_info *sbi;
 	struct nilfs_root *fsroot;
 	struct backing_dev_info *bdi;
 	__u64 cno;
 	int err;
 
-	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
+	nilfs = alloc_nilfs(sb->s_bdev);
+	if (!nilfs)
 		return -ENOMEM;
 
-	sb->s_fs_info = sbi;
-	sbi->s_super = sb;
-
-	nilfs = alloc_nilfs(sb->s_bdev);
-	if (!nilfs) {
-		err = -ENOMEM;
-		goto failed_sbi;
-	}
-	sbi->s_nilfs = nilfs;
+	sb->s_fs_info = nilfs;
 
-	err = init_nilfs(nilfs, sbi, (char *)data);
+	err = init_nilfs(nilfs, sb, (char *)data);
 	if (err)
 		goto failed_nilfs;
 
-	spin_lock_init(&sbi->s_inode_lock);
-	INIT_LIST_HEAD(&sbi->s_dirty_files);
-
-	/*
-	 * Following initialization is overlapped because
-	 * nilfs_sb_info structure has been cleared at the beginning.
-	 * But we reserve them to keep our interest and make ready
-	 * for the future change.
-	 */
-	get_random_bytes(&sbi->s_next_generation,
-			 sizeof(sbi->s_next_generation));
-	spin_lock_init(&sbi->s_next_gen_lock);
-
 	sb->s_op = &nilfs_sops;
 	sb->s_export_op = &nilfs_export_ops;
 	sb->s_root = NULL;
@@ -962,12 +936,12 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 	bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
 	sb->s_bdi = bdi ? : &default_backing_dev_info;
 
-	err = load_nilfs(nilfs, sbi);
+	err = load_nilfs(nilfs, sb);
 	if (err)
 		goto failed_nilfs;
 
 	cno = nilfs_last_cno(nilfs);
-	err = nilfs_attach_checkpoint(sbi, cno, true, &fsroot);
+	err = nilfs_attach_checkpoint(sb, cno, true, &fsroot);
 	if (err) {
 		printk(KERN_ERR "NILFS: error loading last checkpoint "
 		       "(checkpoint number=%llu).\n", (unsigned long long)cno);
@@ -975,7 +949,7 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 	}
 
 	if (!(sb->s_flags & MS_RDONLY)) {
-		err = nilfs_attach_segment_constructor(sbi, fsroot);
+		err = nilfs_attach_log_writer(sb, fsroot);
 		if (err)
 			goto failed_checkpoint;
 	}
@@ -988,14 +962,14 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 
 	if (!(sb->s_flags & MS_RDONLY)) {
 		down_write(&nilfs->ns_sem);
-		nilfs_setup_super(sbi, true);
+		nilfs_setup_super(sb, true);
 		up_write(&nilfs->ns_sem);
 	}
 
 	return 0;
 
  failed_segctor:
-	nilfs_detach_segment_constructor(sbi);
+	nilfs_detach_log_writer(sb);
 
  failed_checkpoint:
 	nilfs_put_root(fsroot);
@@ -1007,23 +981,18 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent)
 
  failed_nilfs:
 	destroy_nilfs(nilfs);
-
- failed_sbi:
-	sb->s_fs_info = NULL;
-	kfree(sbi);
 	return err;
 }
 
 static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 {
-	struct nilfs_sb_info *sbi = NILFS_SB(sb);
-	struct the_nilfs *nilfs = sbi->s_nilfs;
+	struct the_nilfs *nilfs = sb->s_fs_info;
 	unsigned long old_sb_flags;
 	unsigned long old_mount_opt;
 	int err;
 
 	old_sb_flags = sb->s_flags;
-	old_mount_opt = sbi->s_mount_opt;
+	old_mount_opt = nilfs->ns_mount_opt;
 
 	if (!parse_options(data, sb, 1)) {
 		err = -EINVAL;
@@ -1043,8 +1012,8 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		goto out;
 	if (*flags & MS_RDONLY) {
-		/* Shutting down the segment constructor */
-		nilfs_detach_segment_constructor(sbi);
+		/* Shutting down log writer */
+		nilfs_detach_log_writer(sb);
 		sb->s_flags |= MS_RDONLY;
 
 		/*
@@ -1052,7 +1021,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 		 * the RDONLY flag and then mark the partition as valid again.
 		 */
 		down_write(&nilfs->ns_sem);
-		nilfs_cleanup_super(sbi);
+		nilfs_cleanup_super(sb);
 		up_write(&nilfs->ns_sem);
 	} else {
 		__u64 features;
@@ -1079,12 +1048,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 		sb->s_flags &= ~MS_RDONLY;
 
 		root = NILFS_I(sb->s_root->d_inode)->i_root;
-		err = nilfs_attach_segment_constructor(sbi, root);
+		err = nilfs_attach_log_writer(sb, root);
 		if (err)
 			goto restore_opts;
 
 		down_write(&nilfs->ns_sem);
-		nilfs_setup_super(sbi, true);
+		nilfs_setup_super(sb, true);
 		up_write(&nilfs->ns_sem);
 	}
  out:
@@ -1092,13 +1061,12 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
 
  restore_opts:
 	sb->s_flags = old_sb_flags;
-	sbi->s_mount_opt = old_mount_opt;
+	nilfs->ns_mount_opt = old_mount_opt;
 	return err;
 }
 
 struct nilfs_super_data {
 	struct block_device *bdev;
-	struct nilfs_sb_info *sbi;
 	__u64 cno;
 	int flags;
 };
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index ad4ac60..d2acd1a 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
+#include <linux/random.h>
 #include <linux/crc32.h>
 #include "nilfs.h"
 #include "segment.h"
@@ -75,7 +76,10 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev)
 	nilfs->ns_bdev = bdev;
 	atomic_set(&nilfs->ns_ndirtyblks, 0);
 	init_rwsem(&nilfs->ns_sem);
+	INIT_LIST_HEAD(&nilfs->ns_dirty_files);
 	INIT_LIST_HEAD(&nilfs->ns_gc_inodes);
+	spin_lock_init(&nilfs->ns_inode_lock);
+	spin_lock_init(&nilfs->ns_next_gen_lock);
 	spin_lock_init(&nilfs->ns_last_segment_lock);
 	nilfs->ns_cptree = RB_ROOT;
 	spin_lock_init(&nilfs->ns_cptree_lock);
@@ -197,16 +201,16 @@ static int nilfs_store_log_cursor(struct the_nilfs *nilfs,
 /**
  * load_nilfs - load and recover the nilfs
  * @nilfs: the_nilfs structure to be released
- * @sbi: nilfs_sb_info used to recover past segment
+ * @sb: super block isntance used to recover past segment
  *
  * load_nilfs() searches and load the latest super root,
  * attaches the last segment, and does recovery if needed.
  * The caller must call this exclusively for simultaneous mounts.
  */
-int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
+int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb)
 {
 	struct nilfs_recovery_info ri;
-	unsigned int s_flags = sbi->s_super->s_flags;
+	unsigned int s_flags = sb->s_flags;
 	int really_read_only = bdev_read_only(nilfs->ns_bdev);
 	int valid_fs = nilfs_valid_fs(nilfs);
 	int err;
@@ -271,7 +275,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 			goto scan_error;
 	}
 
-	err = nilfs_load_super_root(nilfs, sbi->s_super, ri.ri_super_root);
+	err = nilfs_load_super_root(nilfs, sb, ri.ri_super_root);
 	if (unlikely(err)) {
 		printk(KERN_ERR "NILFS: error loading super root.\n");
 		goto failed;
@@ -283,7 +287,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 	if (s_flags & MS_RDONLY) {
 		__u64 features;
 
-		if (nilfs_test_opt(sbi, NORECOVERY)) {
+		if (nilfs_test_opt(nilfs, NORECOVERY)) {
 			printk(KERN_INFO "NILFS: norecovery option specified. "
 			       "skipping roll-forward recovery\n");
 			goto skip_recovery;
@@ -304,21 +308,21 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 			err = -EROFS;
 			goto failed_unload;
 		}
-		sbi->s_super->s_flags &= ~MS_RDONLY;
-	} else if (nilfs_test_opt(sbi, NORECOVERY)) {
+		sb->s_flags &= ~MS_RDONLY;
+	} else if (nilfs_test_opt(nilfs, NORECOVERY)) {
 		printk(KERN_ERR "NILFS: recovery cancelled because norecovery "
 		       "option was specified for a read/write mount\n");
 		err = -EINVAL;
 		goto failed_unload;
 	}
 
-	err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri);
+	err = nilfs_salvage_orphan_logs(nilfs, sb, &ri);
 	if (err)
 		goto failed_unload;
 
 	down_write(&nilfs->ns_sem);
 	nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */
-	err = nilfs_cleanup_super(sbi);
+	err = nilfs_cleanup_super(sb);
 	up_write(&nilfs->ns_sem);
 
 	if (err) {
@@ -330,7 +334,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 
  skip_recovery:
 	nilfs_clear_recovery_info(&ri);
-	sbi->s_super->s_flags = s_flags;
+	sb->s_flags = s_flags;
 	return 0;
 
  scan_error:
@@ -344,7 +348,7 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
 
  failed:
 	nilfs_clear_recovery_info(&ri);
-	sbi->s_super->s_flags = s_flags;
+	sb->s_flags = s_flags;
 	return err;
 }
 
@@ -475,10 +479,13 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
 			return -EIO;
 		}
 		printk(KERN_WARNING
-		       "NILFS warning: unable to read primary superblock\n");
-	} else if (!sbp[1])
+		       "NILFS warning: unable to read primary superblock "
+		       "(blocksize = %d)\n", blocksize);
+	} else if (!sbp[1]) {
 		printk(KERN_WARNING
-		       "NILFS warning: unable to read secondary superblock\n");
+		       "NILFS warning: unable to read secondary superblock "
+		       "(blocksize = %d)\n", blocksize);
+	}
 
 	/*
 	 * Compare two super blocks and set 1 in swp if the secondary
@@ -505,7 +512,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
 
 	if (!valid[!swp])
 		printk(KERN_WARNING "NILFS warning: broken superblock. "
-		       "using spare superblock.\n");
+		       "using spare superblock (blocksize = %d).\n", blocksize);
 	if (swp)
 		nilfs_swap_super_block(nilfs);
 
@@ -519,7 +526,6 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
 /**
  * init_nilfs - initialize a NILFS instance.
  * @nilfs: the_nilfs structure
- * @sbi: nilfs_sb_info
  * @sb: super block
  * @data: mount options
  *
@@ -530,9 +536,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
  * Return Value: On success, 0 is returned. On error, a negative error
  * code is returned.
  */
-int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
+int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data)
 {
-	struct super_block *sb = sbi->s_super;
 	struct nilfs_super_block *sbp;
 	int blocksize;
 	int err;
@@ -588,6 +593,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data)
 	nilfs->ns_blocksize_bits = sb->s_blocksize_bits;
 	nilfs->ns_blocksize = blocksize;
 
+	get_random_bytes(&nilfs->ns_next_generation,
+			 sizeof(nilfs->ns_next_generation));
+
 	err = nilfs_store_disk_layout(nilfs, sbp);
 	if (err)
 		goto failed_sbh;
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h
index fd85e4c..f496814 100644
--- a/fs/nilfs2/the_nilfs.h
+++ b/fs/nilfs2/the_nilfs.h
@@ -31,7 +31,8 @@
 #include <linux/blkdev.h>
 #include <linux/backing-dev.h>
 #include <linux/slab.h>
-#include "sb.h"
+
+struct nilfs_sc_info;
 
 /* the_nilfs struct */
 enum {
@@ -65,13 +66,23 @@ enum {
  * @ns_last_cno: checkpoint number of the latest segment
  * @ns_prot_seq: least sequence number of segments which must not be reclaimed
  * @ns_prev_seq: base sequence number used to decide if advance log cursor
- * @ns_segctor_sem: segment constructor semaphore
+ * @ns_writer: log writer
+ * @ns_segctor_sem: semaphore protecting log write
  * @ns_dat: DAT file inode
  * @ns_cpfile: checkpoint file inode
  * @ns_sufile: segusage file inode
  * @ns_cptree: rb-tree of all mounted checkpoints (nilfs_root)
  * @ns_cptree_lock: lock protecting @ns_cptree
+ * @ns_dirty_files: list of dirty files
+ * @ns_inode_lock: lock protecting @ns_dirty_files
  * @ns_gc_inodes: dummy inodes to keep live blocks
+ * @ns_next_generation: next generation number for inodes
+ * @ns_next_gen_lock: lock protecting @ns_next_generation
+ * @ns_mount_opt: mount options
+ * @ns_resuid: uid for reserved blocks
+ * @ns_resgid: gid for reserved blocks
+ * @ns_interval: checkpoint creation interval
+ * @ns_watermark: watermark for the number of dirty buffers
  * @ns_blocksize_bits: bit length of block size
  * @ns_blocksize: block size
  * @ns_nsegments: number of segments in filesystem
@@ -131,6 +142,7 @@ struct the_nilfs {
 	u64			ns_prot_seq;
 	u64			ns_prev_seq;
 
+	struct nilfs_sc_info   *ns_writer;
 	struct rw_semaphore	ns_segctor_sem;
 
 	/*
@@ -145,9 +157,25 @@ struct the_nilfs {
 	struct rb_root		ns_cptree;
 	spinlock_t		ns_cptree_lock;
 
+	/* Dirty inode list */
+	struct list_head	ns_dirty_files;
+	spinlock_t		ns_inode_lock;
+
 	/* GC inode list */
 	struct list_head	ns_gc_inodes;
 
+	/* Inode allocator */
+	u32			ns_next_generation;
+	spinlock_t		ns_next_gen_lock;
+
+	/* Mount options */
+	unsigned long		ns_mount_opt;
+
+	uid_t			ns_resuid;
+	gid_t			ns_resgid;
+	unsigned long		ns_interval;
+	unsigned long		ns_watermark;
+
 	/* Disk layout information (static) */
 	unsigned int		ns_blocksize_bits;
 	unsigned int		ns_blocksize;
@@ -180,6 +208,20 @@ THE_NILFS_FNS(DISCONTINUED, discontinued)
 THE_NILFS_FNS(GC_RUNNING, gc_running)
 THE_NILFS_FNS(SB_DIRTY, sb_dirty)
 
+/*
+ * Mount option operations
+ */
+#define nilfs_clear_opt(nilfs, opt)  \
+	do { (nilfs)->ns_mount_opt &= ~NILFS_MOUNT_##opt; } while (0)
+#define nilfs_set_opt(nilfs, opt)  \
+	do { (nilfs)->ns_mount_opt |= NILFS_MOUNT_##opt; } while (0)
+#define nilfs_test_opt(nilfs, opt) ((nilfs)->ns_mount_opt & NILFS_MOUNT_##opt)
+#define nilfs_write_opt(nilfs, mask, opt)				\
+	do { (nilfs)->ns_mount_opt =					\
+		(((nilfs)->ns_mount_opt & ~NILFS_MOUNT_##mask) |	\
+		 NILFS_MOUNT_##opt);					\
+	} while (0)
+
 /**
  * struct nilfs_root - nilfs root object
  * @cno: checkpoint number
@@ -224,15 +266,14 @@ static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs)
 void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64);
 struct the_nilfs *alloc_nilfs(struct block_device *bdev);
 void destroy_nilfs(struct the_nilfs *nilfs);
-int init_nilfs(struct the_nilfs *, struct nilfs_sb_info *, char *);
-int load_nilfs(struct the_nilfs *, struct nilfs_sb_info *);
+int init_nilfs(struct the_nilfs *nilfs, struct super_block *sb, char *data);
+int load_nilfs(struct the_nilfs *nilfs, struct super_block *sb);
 int nilfs_discard_segments(struct the_nilfs *, __u64 *, size_t);
 int nilfs_count_free_blocks(struct the_nilfs *, sector_t *);
 struct nilfs_root *nilfs_lookup_root(struct the_nilfs *nilfs, __u64 cno);
 struct nilfs_root *nilfs_find_or_create_root(struct the_nilfs *nilfs,
 					     __u64 cno);
 void nilfs_put_root(struct nilfs_root *root);
-struct nilfs_sb_info *nilfs_find_sbinfo(struct the_nilfs *, int, __u64);
 int nilfs_near_disk_full(struct the_nilfs *);
 void nilfs_fall_back_super_block(struct the_nilfs *);
 void nilfs_swap_super_block(struct the_nilfs *);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 8b61220..6b1305d 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -876,7 +876,7 @@ SYSCALL_ALIAS(sys_fanotify_mark, SyS_fanotify_mark);
 #endif
 
 /*
- * fanotify_user_setup - Our initialization function.  Note that we cannnot return
+ * fanotify_user_setup - Our initialization function.  Note that we cannot return
  * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
  * must result in panic().
  */
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 4cd5d5d..bd46e7c 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -841,7 +841,7 @@ out:
 }
 
 /*
- * inotify_user_setup - Our initialization function.  Note that we cannnot return
+ * inotify_user_setup - Our initialization function.  Note that we cannot return
  * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
  * must result in panic().
  */
diff --git a/fs/ntfs/Makefile b/fs/ntfs/Makefile
index 4ff028f..30206b2 100644
--- a/fs/ntfs/Makefile
+++ b/fs/ntfs/Makefile
@@ -2,18 +2,13 @@
 
 obj-$(CONFIG_NTFS_FS) += ntfs.o
 
-ntfs-objs := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
-	     index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
-	     unistr.o upcase.o
+ntfs-y := aops.o attrib.o collate.o compress.o debug.o dir.o file.o \
+	  index.o inode.o mft.o mst.o namei.o runlist.o super.o sysctl.o \
+	  unistr.o upcase.o
 
-EXTRA_CFLAGS = -DNTFS_VERSION=\"2.1.30\"
+ntfs-$(CONFIG_NTFS_RW) += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o
 
-ifeq ($(CONFIG_NTFS_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-y := -DNTFS_VERSION=\"2.1.30\"
+ccflags-$(CONFIG_NTFS_DEBUG)	+= -DDEBUG
+ccflags-$(CONFIG_NTFS_RW)	+= -DNTFS_RW
 
-ifeq ($(CONFIG_NTFS_RW),y)
-EXTRA_CFLAGS += -DNTFS_RW
-
-ntfs-objs += bitmap.o lcnalloc.o logfile.o quota.o usnjrnl.o
-endif
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 07d9fd8..d8a0313 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -1,6 +1,6 @@
-EXTRA_CFLAGS += -Ifs/ocfs2
+ccflags-y := -Ifs/ocfs2
 
-EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
+ccflags-y += -DCATCH_BH_JBD_RACES
 
 obj-$(CONFIG_OCFS2_FS) += 	\
 	ocfs2.o			\
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index d417b3f..f97b6f1 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -354,7 +354,7 @@ static inline int ocfs2_match(int len,
 /*
  * Returns 0 if not found, -1 on failure, and 1 on success
  */
-static int inline ocfs2_search_dirblock(struct buffer_head *bh,
+static inline int ocfs2_search_dirblock(struct buffer_head *bh,
 					struct inode *dir,
 					const char *name, int namelen,
 					unsigned long offset,
diff --git a/fs/ocfs2/dlm/Makefile b/fs/ocfs2/dlm/Makefile
index dcebf0d..c8a044e 100644
--- a/fs/ocfs2/dlm/Makefile
+++ b/fs/ocfs2/dlm/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -Ifs/ocfs2
+ccflags-y := -Ifs/ocfs2
 
 obj-$(CONFIG_OCFS2_FS_O2CB) += ocfs2_dlm.o
 
diff --git a/fs/ocfs2/dlmfs/Makefile b/fs/ocfs2/dlmfs/Makefile
index df69b48..f14be89 100644
--- a/fs/ocfs2/dlmfs/Makefile
+++ b/fs/ocfs2/dlmfs/Makefile
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -Ifs/ocfs2
+ccflags-y := -Ifs/ocfs2
 
 obj-$(CONFIG_OCFS2_FS) += ocfs2_dlmfs.o
 
diff --git a/fs/ocfs2/export.c b/fs/ocfs2/export.c
index 5dbc306..254652a 100644
--- a/fs/ocfs2/export.c
+++ b/fs/ocfs2/export.c
@@ -197,8 +197,12 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
 		   dentry->d_name.len, dentry->d_name.name,
 		   fh, len, connectable);
 
-	if (len < 3 || (connectable && len < 6)) {
-		mlog(ML_ERROR, "fh buffer is too small for encoding\n");
+	if (connectable && (len < 6)) {
+		*max_len = 6;
+		type = 255;
+		goto bail;
+	} else if (len < 3) {
+		*max_len = 3;
 		type = 255;
 		goto bail;
 	}
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 849fb4a..d6c25d7 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -293,7 +293,7 @@ static int ocfs2_mknod(struct inode *dir,
 	}
 
 	/* get security xattr */
-	status = ocfs2_init_security_get(inode, dir, &si);
+	status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si);
 	if (status) {
 		if (status == -EOPNOTSUPP)
 			si.enable = 0;
@@ -1665,7 +1665,7 @@ static int ocfs2_symlink(struct inode *dir,
 	}
 
 	/* get security xattr */
-	status = ocfs2_init_security_get(inode, dir, &si);
+	status = ocfs2_init_security_get(inode, dir, &dentry->d_name, &si);
 	if (status) {
 		if (status == -EOPNOTSUPP)
 			si.enable = 0;
diff --git a/fs/ocfs2/quota.h b/fs/ocfs2/quota.h
index 196fcb5..d5ab56c 100644
--- a/fs/ocfs2/quota.h
+++ b/fs/ocfs2/quota.h
@@ -114,7 +114,4 @@ int ocfs2_local_write_dquot(struct dquot *dquot);
 extern const struct dquot_operations ocfs2_quota_operations;
 extern struct quota_format_type ocfs2_quota_format;
 
-int ocfs2_quota_setup(void);
-void ocfs2_quota_shutdown(void);
-
 #endif /* _OCFS2_QUOTA_H */
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 4607923..a73f641 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -63,8 +63,6 @@
  *        write to gf
  */
 
-static struct workqueue_struct *ocfs2_quota_wq = NULL;
-
 static void qsync_work_fn(struct work_struct *work);
 
 static void ocfs2_global_disk2memdqb(struct dquot *dquot, void *dp)
@@ -400,8 +398,8 @@ int ocfs2_global_read_info(struct super_block *sb, int type)
 						OCFS2_QBLK_RESERVED_SPACE;
 	oinfo->dqi_gi.dqi_qtree_depth = qtree_depth(&oinfo->dqi_gi);
 	INIT_DELAYED_WORK(&oinfo->dqi_sync_work, qsync_work_fn);
-	queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
-			   msecs_to_jiffies(oinfo->dqi_syncms));
+	schedule_delayed_work(&oinfo->dqi_sync_work,
+			      msecs_to_jiffies(oinfo->dqi_syncms));
 
 out_err:
 	mlog_exit(status);
@@ -635,8 +633,8 @@ static void qsync_work_fn(struct work_struct *work)
 	struct super_block *sb = oinfo->dqi_gqinode->i_sb;
 
 	dquot_scan_active(sb, ocfs2_sync_dquot_helper, oinfo->dqi_type);
-	queue_delayed_work(ocfs2_quota_wq, &oinfo->dqi_sync_work,
-			   msecs_to_jiffies(oinfo->dqi_syncms));
+	schedule_delayed_work(&oinfo->dqi_sync_work,
+			      msecs_to_jiffies(oinfo->dqi_syncms));
 }
 
 /*
@@ -923,20 +921,3 @@ const struct dquot_operations ocfs2_quota_operations = {
 	.alloc_dquot	= ocfs2_alloc_dquot,
 	.destroy_dquot	= ocfs2_destroy_dquot,
 };
-
-int ocfs2_quota_setup(void)
-{
-	ocfs2_quota_wq = create_workqueue("o2quot");
-	if (!ocfs2_quota_wq)
-		return -ENOMEM;
-	return 0;
-}
-
-void ocfs2_quota_shutdown(void)
-{
-	if (ocfs2_quota_wq) {
-		flush_workqueue(ocfs2_quota_wq);
-		destroy_workqueue(ocfs2_quota_wq);
-		ocfs2_quota_wq = NULL;
-	}
-}
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index 19ebc5a..c384d63 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -4328,7 +4328,8 @@ static int ocfs2_reflink(struct dentry *old_dentry, struct inode *dir,
 
 	/* If the security isn't preserved, we need to re-initialize them. */
 	if (!preserve) {
-		error = ocfs2_init_security_and_acl(dir, new_orphan_inode);
+		error = ocfs2_init_security_and_acl(dir, new_orphan_inode,
+						    &new_dentry->d_name);
 		if (error)
 			mlog_errno(error);
 	}
@@ -4379,7 +4380,7 @@ static int ocfs2_user_path_parent(const char __user *path,
 	if (IS_ERR(s))
 		return PTR_ERR(s);
 
-	error = path_lookup(s, LOOKUP_PARENT, nd);
+	error = kern_path_parent(s, nd);
 	if (error)
 		putname(s);
 	else
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 36c423f..236ed1b 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1657,16 +1657,11 @@ static int __init ocfs2_init(void)
 		mlog(ML_ERROR, "Unable to create ocfs2 debugfs root.\n");
 	}
 
-	status = ocfs2_quota_setup();
-	if (status)
-		goto leave;
-
 	ocfs2_set_locking_protocol();
 
 	status = register_quota_format(&ocfs2_quota_format);
 leave:
 	if (status < 0) {
-		ocfs2_quota_shutdown();
 		ocfs2_free_mem_caches();
 		exit_ocfs2_uptodate_cache();
 	}
@@ -1683,8 +1678,6 @@ static void __exit ocfs2_exit(void)
 {
 	mlog_entry_void();
 
-	ocfs2_quota_shutdown();
-
 	if (ocfs2_wq) {
 		flush_workqueue(ocfs2_wq);
 		destroy_workqueue(ocfs2_wq);
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 67cd439..6bb6024 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7185,7 +7185,8 @@ out:
  * must not hold any lock expect i_mutex.
  */
 int ocfs2_init_security_and_acl(struct inode *dir,
-				struct inode *inode)
+				struct inode *inode,
+				const struct qstr *qstr)
 {
 	int ret = 0;
 	struct buffer_head *dir_bh = NULL;
@@ -7193,7 +7194,7 @@ int ocfs2_init_security_and_acl(struct inode *dir,
 		.enable = 1,
 	};
 
-	ret = ocfs2_init_security_get(inode, dir, &si);
+	ret = ocfs2_init_security_get(inode, dir, qstr, &si);
 	if (!ret) {
 		ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
 				      si.name, si.value, si.value_len,
@@ -7261,13 +7262,14 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
 
 int ocfs2_init_security_get(struct inode *inode,
 			    struct inode *dir,
+			    const struct qstr *qstr,
 			    struct ocfs2_security_xattr_info *si)
 {
 	/* check whether ocfs2 support feature xattr */
 	if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))
 		return -EOPNOTSUPP;
-	return security_inode_init_security(inode, dir, &si->name, &si->value,
-					    &si->value_len);
+	return security_inode_init_security(inode, dir, qstr, &si->name,
+					    &si->value, &si->value_len);
 }
 
 int ocfs2_init_security_set(handle_t *handle,
diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h
index aa64bb3..d63cfb7 100644
--- a/fs/ocfs2/xattr.h
+++ b/fs/ocfs2/xattr.h
@@ -57,6 +57,7 @@ int ocfs2_has_inline_xattr_value_outside(struct inode *inode,
 					 struct ocfs2_dinode *di);
 int ocfs2_xattr_remove(struct inode *, struct buffer_head *);
 int ocfs2_init_security_get(struct inode *, struct inode *,
+			    const struct qstr *,
 			    struct ocfs2_security_xattr_info *);
 int ocfs2_init_security_set(handle_t *, struct inode *,
 			    struct buffer_head *,
@@ -94,5 +95,6 @@ int ocfs2_reflink_xattrs(struct inode *old_inode,
 			 struct buffer_head *new_bh,
 			 bool preserve_security);
 int ocfs2_init_security_and_acl(struct inode *dir,
-				struct inode *inode);
+				struct inode *inode,
+				const struct qstr *qstr);
 #endif /* OCFS2_XATTR_H */
diff --git a/fs/omfs/dir.c b/fs/omfs/dir.c
index 393f3f6..de4ff29 100644
--- a/fs/omfs/dir.c
+++ b/fs/omfs/dir.c
@@ -235,33 +235,22 @@ static int omfs_dir_is_empty(struct inode *inode)
 	return *ptr != ~0;
 }
 
-static int omfs_unlink(struct inode *dir, struct dentry *dentry)
+static int omfs_remove(struct inode *dir, struct dentry *dentry)
 {
-	int ret;
 	struct inode *inode = dentry->d_inode;
+	int ret;
+
+	if (S_ISDIR(inode->i_mode) && !omfs_dir_is_empty(inode))
+		return -ENOTEMPTY;
 
 	ret = omfs_delete_entry(dentry);
 	if (ret)
-		goto end_unlink;
-
-	inode_dec_link_count(inode);
+		return ret;
+	
+	clear_nlink(inode);
+	mark_inode_dirty(inode);
 	mark_inode_dirty(dir);
-
-end_unlink:
-	return ret;
-}
-
-static int omfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	int err = -ENOTEMPTY;
-	struct inode *inode = dentry->d_inode;
-
-	if (omfs_dir_is_empty(inode)) {
-		err = omfs_unlink(dir, dentry);
-		if (!err)
-			inode_dec_link_count(inode);
-	}
-	return err;
+	return 0;
 }
 
 static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode)
@@ -372,9 +361,10 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir,
 
 		res = filldir(dirent, oi->i_name, strnlen(oi->i_name,
 			OMFS_NAMELEN), filp->f_pos, self, d_type);
-		if (res == 0)
-			filp->f_pos++;
 		brelse(bh);
+		if (res < 0)
+			break;
+		filp->f_pos++;
 	}
 out:
 	return res;
@@ -385,44 +375,28 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 {
 	struct inode *new_inode = new_dentry->d_inode;
 	struct inode *old_inode = old_dentry->d_inode;
-	struct buffer_head *bh;
-	int is_dir;
 	int err;
 
-	is_dir = S_ISDIR(old_inode->i_mode);
-
 	if (new_inode) {
 		/* overwriting existing file/dir */
-		err = -ENOTEMPTY;
-		if (is_dir && !omfs_dir_is_empty(new_inode))
-			goto out;
-
-		err = -ENOENT;
-		bh = omfs_find_entry(new_dir, new_dentry->d_name.name,
-			new_dentry->d_name.len);
-		if (IS_ERR(bh))
-			goto out;
-		brelse(bh);
-
-		err = omfs_unlink(new_dir, new_dentry);
+		err = omfs_remove(new_dir, new_dentry);
 		if (err)
 			goto out;
 	}
 
 	/* since omfs locates files by name, we need to unlink _before_
 	 * adding the new link or we won't find the old one */
-	inode_inc_link_count(old_inode);
-	err = omfs_unlink(old_dir, old_dentry);
-	if (err) {
-		inode_dec_link_count(old_inode);
+	err = omfs_delete_entry(old_dentry);
+	if (err)
 		goto out;
-	}
 
+	mark_inode_dirty(old_dir);
 	err = omfs_add_link(new_dentry, old_inode);
 	if (err)
 		goto out;
 
 	old_inode->i_ctime = CURRENT_TIME_SEC;
+	mark_inode_dirty(old_inode);
 out:
 	return err;
 }
@@ -488,8 +462,8 @@ const struct inode_operations omfs_dir_inops = {
 	.mkdir = omfs_mkdir,
 	.rename = omfs_rename,
 	.create = omfs_create,
-	.unlink = omfs_unlink,
-	.rmdir = omfs_rmdir,
+	.unlink = omfs_remove,
+	.rmdir = omfs_remove,
 };
 
 const struct file_operations omfs_dir_operations = {
diff --git a/fs/open.c b/fs/open.c
index b47aab3..b52cf01 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -573,13 +573,15 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
 {
 	struct path path;
 	int error = -EINVAL;
-	int follow;
+	int lookup_flags;
 
-	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
+	if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
 		goto out;
 
-	follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
-	error = user_path_at(dfd, filename, follow, &path);
+	lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
+	if (flag & AT_EMPTY_PATH)
+		lookup_flags |= LOOKUP_EMPTY;
+	error = user_path_at(dfd, filename, lookup_flags, &path);
 	if (error)
 		goto out;
 	error = mnt_want_write(path.mnt);
@@ -669,11 +671,16 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 					int (*open)(struct inode *, struct file *),
 					const struct cred *cred)
 {
+	static const struct file_operations empty_fops = {};
 	struct inode *inode;
 	int error;
 
 	f->f_mode = OPEN_FMODE(f->f_flags) | FMODE_LSEEK |
 				FMODE_PREAD | FMODE_PWRITE;
+
+	if (unlikely(f->f_flags & O_PATH))
+		f->f_mode = FMODE_PATH;
+
 	inode = dentry->d_inode;
 	if (f->f_mode & FMODE_WRITE) {
 		error = __get_file_write_access(inode, mnt);
@@ -687,9 +694,15 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 	f->f_path.dentry = dentry;
 	f->f_path.mnt = mnt;
 	f->f_pos = 0;
-	f->f_op = fops_get(inode->i_fop);
 	file_sb_list_add(f, inode->i_sb);
 
+	if (unlikely(f->f_mode & FMODE_PATH)) {
+		f->f_op = &empty_fops;
+		return f;
+	}
+
+	f->f_op = fops_get(inode->i_fop);
+
 	error = security_dentry_open(f, cred);
 	if (error)
 		goto cleanup_all;
@@ -701,7 +714,8 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 		if (error)
 			goto cleanup_all;
 	}
-	ima_counts_get(f);
+	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+		i_readcount_inc(inode);
 
 	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
@@ -821,17 +835,8 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
 
 	validate_creds(cred);
 
-	/*
-	 * We must always pass in a valid mount pointer.   Historically
-	 * callers got away with not passing it, but we must enforce this at
-	 * the earliest possible point now to avoid strange problems deep in the
-	 * filesystem stack.
-	 */
-	if (!mnt) {
-		printk(KERN_WARNING "%s called with NULL vfsmount\n", __func__);
-		dump_stack();
-		return ERR_PTR(-EINVAL);
-	}
+	/* We must always pass in a valid mount pointer. */
+	BUG_ON(!mnt);
 
 	error = -ENFILE;
 	f = get_empty_filp();
@@ -890,15 +895,110 @@ void fd_install(unsigned int fd, struct file *file)
 
 EXPORT_SYMBOL(fd_install);
 
+static inline int build_open_flags(int flags, int mode, struct open_flags *op)
+{
+	int lookup_flags = 0;
+	int acc_mode;
+
+	if (!(flags & O_CREAT))
+		mode = 0;
+	op->mode = mode;
+
+	/* Must never be set by userspace */
+	flags &= ~FMODE_NONOTIFY;
+
+	/*
+	 * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
+	 * check for O_DSYNC if the need any syncing at all we enforce it's
+	 * always set instead of having to deal with possibly weird behaviour
+	 * for malicious applications setting only __O_SYNC.
+	 */
+	if (flags & __O_SYNC)
+		flags |= O_DSYNC;
+
+	/*
+	 * If we have O_PATH in the open flag. Then we
+	 * cannot have anything other than the below set of flags
+	 */
+	if (flags & O_PATH) {
+		flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
+		acc_mode = 0;
+	} else {
+		acc_mode = MAY_OPEN | ACC_MODE(flags);
+	}
+
+	op->open_flag = flags;
+
+	/* O_TRUNC implies we need access checks for write permissions */
+	if (flags & O_TRUNC)
+		acc_mode |= MAY_WRITE;
+
+	/* Allow the LSM permission hook to distinguish append
+	   access from general write access. */
+	if (flags & O_APPEND)
+		acc_mode |= MAY_APPEND;
+
+	op->acc_mode = acc_mode;
+
+	op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;
+
+	if (flags & O_CREAT) {
+		op->intent |= LOOKUP_CREATE;
+		if (flags & O_EXCL)
+			op->intent |= LOOKUP_EXCL;
+	}
+
+	if (flags & O_DIRECTORY)
+		lookup_flags |= LOOKUP_DIRECTORY;
+	if (!(flags & O_NOFOLLOW))
+		lookup_flags |= LOOKUP_FOLLOW;
+	return lookup_flags;
+}
+
+/**
+ * filp_open - open file and return file pointer
+ *
+ * @filename:	path to open
+ * @flags:	open flags as per the open(2) second argument
+ * @mode:	mode for the new file if O_CREAT is set, else ignored
+ *
+ * This is the helper to open a file from kernelspace if you really
+ * have to.  But in generally you should not do this, so please move
+ * along, nothing to see here..
+ */
+struct file *filp_open(const char *filename, int flags, int mode)
+{
+	struct open_flags op;
+	int lookup = build_open_flags(flags, mode, &op);
+	return do_filp_open(AT_FDCWD, filename, &op, lookup);
+}
+EXPORT_SYMBOL(filp_open);
+
+struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
+			    const char *filename, int flags)
+{
+	struct open_flags op;
+	int lookup = build_open_flags(flags, 0, &op);
+	if (flags & O_CREAT)
+		return ERR_PTR(-EINVAL);
+	if (!filename && (flags & O_DIRECTORY))
+		if (!dentry->d_inode->i_op->lookup)
+			return ERR_PTR(-ENOTDIR);
+	return do_file_open_root(dentry, mnt, filename, &op, lookup);
+}
+EXPORT_SYMBOL(file_open_root);
+
 long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
 {
+	struct open_flags op;
+	int lookup = build_open_flags(flags, mode, &op);
 	char *tmp = getname(filename);
 	int fd = PTR_ERR(tmp);
 
 	if (!IS_ERR(tmp)) {
 		fd = get_unused_fd_flags(flags);
 		if (fd >= 0) {
-			struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
+			struct file *f = do_filp_open(dfd, tmp, &op, lookup);
 			if (IS_ERR(f)) {
 				put_unused_fd(fd);
 				fd = PTR_ERR(f);
@@ -968,8 +1068,10 @@ int filp_close(struct file *filp, fl_owner_t id)
 	if (filp->f_op && filp->f_op->flush)
 		retval = filp->f_op->flush(filp, id);
 
-	dnotify_flush(filp, id);
-	locks_remove_posix(filp, id);
+	if (likely(!(filp->f_mode & FMODE_PATH))) {
+		dnotify_flush(filp, id);
+		locks_remove_posix(filp, id);
+	}
 	fput(filp);
 	return retval;
 }
diff --git a/fs/partitions/osf.c b/fs/partitions/osf.c
index be03a0b..764b86a 100644
--- a/fs/partitions/osf.c
+++ b/fs/partitions/osf.c
@@ -10,7 +10,7 @@
 #include "check.h"
 #include "osf.h"
 
-#define MAX_OSF_PARTITIONS 8
+#define MAX_OSF_PARTITIONS 18
 
 int osf_partition(struct parsed_partitions *state)
 {
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 8eb2522..f50133c 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -32,7 +32,6 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
 	ei->sysctl_entry = table;
 
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-	inode->i_flags |= S_PRIVATE; /* tell selinux to ignore this inode */
 	inode->i_mode = table->mode;
 	if (!table->child) {
 		inode->i_mode |= S_IFREG;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 60b9148..93381aa 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1,5 +1,6 @@
 #include <linux/mm.h>
 #include <linux/hugetlb.h>
+#include <linux/huge_mm.h>
 #include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <linux/highmem.h>
@@ -7,6 +8,7 @@
 #include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/mempolicy.h>
+#include <linux/rmap.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
 
@@ -329,58 +331,86 @@ struct mem_size_stats {
 	unsigned long private_dirty;
 	unsigned long referenced;
 	unsigned long anonymous;
+	unsigned long anonymous_thp;
 	unsigned long swap;
 	u64 pss;
 };
 
-static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-			   struct mm_walk *walk)
+
+static void smaps_pte_entry(pte_t ptent, unsigned long addr,
+		unsigned long ptent_size, struct mm_walk *walk)
 {
 	struct mem_size_stats *mss = walk->private;
 	struct vm_area_struct *vma = mss->vma;
-	pte_t *pte, ptent;
-	spinlock_t *ptl;
 	struct page *page;
 	int mapcount;
 
-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
-	for (; addr != end; pte++, addr += PAGE_SIZE) {
-		ptent = *pte;
-
-		if (is_swap_pte(ptent)) {
-			mss->swap += PAGE_SIZE;
-			continue;
-		}
+	if (is_swap_pte(ptent)) {
+		mss->swap += ptent_size;
+		return;
+	}
 
-		if (!pte_present(ptent))
-			continue;
+	if (!pte_present(ptent))
+		return;
+
+	page = vm_normal_page(vma, addr, ptent);
+	if (!page)
+		return;
+
+	if (PageAnon(page))
+		mss->anonymous += ptent_size;
+
+	mss->resident += ptent_size;
+	/* Accumulate the size in pages that have been accessed. */
+	if (pte_young(ptent) || PageReferenced(page))
+		mss->referenced += ptent_size;
+	mapcount = page_mapcount(page);
+	if (mapcount >= 2) {
+		if (pte_dirty(ptent) || PageDirty(page))
+			mss->shared_dirty += ptent_size;
+		else
+			mss->shared_clean += ptent_size;
+		mss->pss += (ptent_size << PSS_SHIFT) / mapcount;
+	} else {
+		if (pte_dirty(ptent) || PageDirty(page))
+			mss->private_dirty += ptent_size;
+		else
+			mss->private_clean += ptent_size;
+		mss->pss += (ptent_size << PSS_SHIFT);
+	}
+}
 
-		page = vm_normal_page(vma, addr, ptent);
-		if (!page)
-			continue;
+static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+			   struct mm_walk *walk)
+{
+	struct mem_size_stats *mss = walk->private;
+	struct vm_area_struct *vma = mss->vma;
+	pte_t *pte;
+	spinlock_t *ptl;
 
-		if (PageAnon(page))
-			mss->anonymous += PAGE_SIZE;
-
-		mss->resident += PAGE_SIZE;
-		/* Accumulate the size in pages that have been accessed. */
-		if (pte_young(ptent) || PageReferenced(page))
-			mss->referenced += PAGE_SIZE;
-		mapcount = page_mapcount(page);
-		if (mapcount >= 2) {
-			if (pte_dirty(ptent) || PageDirty(page))
-				mss->shared_dirty += PAGE_SIZE;
-			else
-				mss->shared_clean += PAGE_SIZE;
-			mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+	spin_lock(&walk->mm->page_table_lock);
+	if (pmd_trans_huge(*pmd)) {
+		if (pmd_trans_splitting(*pmd)) {
+			spin_unlock(&walk->mm->page_table_lock);
+			wait_split_huge_page(vma->anon_vma, pmd);
 		} else {
-			if (pte_dirty(ptent) || PageDirty(page))
-				mss->private_dirty += PAGE_SIZE;
-			else
-				mss->private_clean += PAGE_SIZE;
-			mss->pss += (PAGE_SIZE << PSS_SHIFT);
+			smaps_pte_entry(*(pte_t *)pmd, addr,
+					HPAGE_PMD_SIZE, walk);
+			spin_unlock(&walk->mm->page_table_lock);
+			mss->anonymous_thp += HPAGE_PMD_SIZE;
+			return 0;
 		}
+	} else {
+		spin_unlock(&walk->mm->page_table_lock);
 	}
+	/*
+	 * The mmap_sem held all the way back in m_start() is what
+	 * keeps khugepaged out of here and from collapsing things
+	 * in here.
+	 */
+	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+	for (; addr != end; pte++, addr += PAGE_SIZE)
+		smaps_pte_entry(*pte, addr, PAGE_SIZE, walk);
 	pte_unmap_unlock(pte - 1, ptl);
 	cond_resched();
 	return 0;
@@ -416,6 +446,7 @@ static int show_smap(struct seq_file *m, void *v)
 		   "Private_Dirty:  %8lu kB\n"
 		   "Referenced:     %8lu kB\n"
 		   "Anonymous:      %8lu kB\n"
+		   "AnonHugePages:  %8lu kB\n"
 		   "Swap:           %8lu kB\n"
 		   "KernelPageSize: %8lu kB\n"
 		   "MMUPageSize:    %8lu kB\n"
@@ -429,6 +460,7 @@ static int show_smap(struct seq_file *m, void *v)
 		   mss.private_dirty >> 10,
 		   mss.referenced >> 10,
 		   mss.anonymous >> 10,
+		   mss.anonymous_thp >> 10,
 		   mss.swap >> 10,
 		   vma_kernel_pagesize(vma) >> 10,
 		   vma_mmu_pagesize(vma) >> 10,
@@ -467,6 +499,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
 	spinlock_t *ptl;
 	struct page *page;
 
+	split_huge_page_pmd(walk->mm, pmd);
+
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE) {
 		ptent = *pte;
@@ -623,6 +657,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
 	pte_t *pte;
 	int err = 0;
 
+	split_huge_page_pmd(walk->mm, pmd);
+
 	/* find the first VMA at or above 'addr' */
 	vma = find_vma(walk->mm, addr);
 	for (; addr != end; addr += PAGE_SIZE) {
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig
new file mode 100644
index 0000000..867d0ac
--- /dev/null
+++ b/fs/pstore/Kconfig
@@ -0,0 +1,13 @@
+config PSTORE
+	bool "Persistant store support"
+	default n
+	help
+	   This option enables generic access to platform level
+	   persistent storage via "pstore" filesystem that can
+	   be mounted as /dev/pstore.  Only useful if you have
+	   a platform level driver that registers with pstore to
+	   provide the data, so you probably should just go say "Y"
+	   (or "M") to a platform specific persistent store driver
+	   (e.g. ACPI_APEI on X86) which will select this for you.
+	   If you don't have a platform persistent store driver,
+	   say N.
diff --git a/fs/pstore/Makefile b/fs/pstore/Makefile
new file mode 100644
index 0000000..760f4bc
--- /dev/null
+++ b/fs/pstore/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux pstorefs routines.
+#
+
+obj-y += pstore.o
+
+pstore-objs += inode.o platform.o
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
new file mode 100644
index 0000000..977ed27
--- /dev/null
+++ b/fs/pstore/inode.c
@@ -0,0 +1,311 @@
+/*
+ * Persistent Storage - ramfs parts.
+ *
+ * Copyright (C) 2010 Intel Corporation <tony.luck@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/fs.h>
+#include <linux/fsnotify.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/mount.h>
+#include <linux/ramfs.h>
+#include <linux/parser.h>
+#include <linux/sched.h>
+#include <linux/magic.h>
+#include <linux/pstore.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "internal.h"
+
+#define	PSTORE_NAMELEN	64
+
+struct pstore_private {
+	u64	id;
+	int	(*erase)(u64);
+	ssize_t	size;
+	char	data[];
+};
+
+static int pstore_file_open(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
+						size_t count, loff_t *ppos)
+{
+	struct pstore_private *ps = file->private_data;
+
+	return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size);
+}
+
+static const struct file_operations pstore_file_operations = {
+	.open	= pstore_file_open,
+	.read	= pstore_file_read,
+	.llseek	= default_llseek,
+};
+
+/*
+ * When a file is unlinked from our file system we call the
+ * platform driver to erase the record from persistent store.
+ */
+static int pstore_unlink(struct inode *dir, struct dentry *dentry)
+{
+	struct pstore_private *p = dentry->d_inode->i_private;
+
+	p->erase(p->id);
+
+	return simple_unlink(dir, dentry);
+}
+
+static void pstore_evict_inode(struct inode *inode)
+{
+	end_writeback(inode);
+	kfree(inode->i_private);
+}
+
+static const struct inode_operations pstore_dir_inode_operations = {
+	.lookup		= simple_lookup,
+	.unlink		= pstore_unlink,
+};
+
+static struct inode *pstore_get_inode(struct super_block *sb,
+					const struct inode *dir, int mode, dev_t dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_ino = get_next_ino();
+		inode->i_uid = inode->i_gid = 0;
+		inode->i_mode = mode;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		case S_IFREG:
+			inode->i_fop = &pstore_file_operations;
+			break;
+		case S_IFDIR:
+			inode->i_op = &pstore_dir_inode_operations;
+			inode->i_fop = &simple_dir_operations;
+			inc_nlink(inode);
+			break;
+		}
+	}
+	return inode;
+}
+
+enum {
+	Opt_kmsg_bytes, Opt_err
+};
+
+static const match_table_t tokens = {
+	{Opt_kmsg_bytes, "kmsg_bytes=%u"},
+	{Opt_err, NULL}
+};
+
+static void parse_options(char *options)
+{
+	char		*p;
+	substring_t	args[MAX_OPT_ARGS];
+	int		option;
+
+	if (!options)
+		return;
+
+	while ((p = strsep(&options, ",")) != NULL) {
+		int token;
+
+		if (!*p)
+			continue;
+
+		token = match_token(p, tokens, args);
+		switch (token) {
+		case Opt_kmsg_bytes:
+			if (!match_int(&args[0], &option))
+				pstore_set_kmsg_bytes(option);
+			break;
+		}
+	}
+}
+
+static int pstore_remount(struct super_block *sb, int *flags, char *data)
+{
+	parse_options(data);
+
+	return 0;
+}
+
+static const struct super_operations pstore_ops = {
+	.statfs		= simple_statfs,
+	.drop_inode	= generic_delete_inode,
+	.evict_inode	= pstore_evict_inode,
+	.remount_fs	= pstore_remount,
+	.show_options	= generic_show_options,
+};
+
+static struct super_block *pstore_sb;
+
+int pstore_is_mounted(void)
+{
+	return pstore_sb != NULL;
+}
+
+/*
+ * Make a regular file in the root directory of our file system.
+ * Load it up with "size" bytes of data from "buf".
+ * Set the mtime & ctime to the date that this record was originally stored.
+ */
+int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
+			      char *data, size_t size,
+			      struct timespec time, int (*erase)(u64))
+{
+	struct dentry		*root = pstore_sb->s_root;
+	struct dentry		*dentry;
+	struct inode		*inode;
+	int			rc;
+	char			name[PSTORE_NAMELEN];
+	struct pstore_private	*private;
+
+	rc = -ENOMEM;
+	inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0);
+	if (!inode)
+		goto fail;
+	private = kmalloc(sizeof *private + size, GFP_KERNEL);
+	if (!private)
+		goto fail_alloc;
+	private->id = id;
+	private->erase = erase;
+
+	switch (type) {
+	case PSTORE_TYPE_DMESG:
+		sprintf(name, "dmesg-%s-%lld", psname, id);
+		break;
+	case PSTORE_TYPE_MCE:
+		sprintf(name, "mce-%s-%lld", psname, id);
+		break;
+	case PSTORE_TYPE_UNKNOWN:
+		sprintf(name, "unknown-%s-%lld", psname, id);
+		break;
+	default:
+		sprintf(name, "type%d-%s-%lld", type, psname, id);
+		break;
+	}
+
+	mutex_lock(&root->d_inode->i_mutex);
+
+	rc = -ENOSPC;
+	dentry = d_alloc_name(root, name);
+	if (IS_ERR(dentry))
+		goto fail_lockedalloc;
+
+	memcpy(private->data, data, size);
+	inode->i_size = private->size = size;
+
+	inode->i_private = private;
+
+	if (time.tv_sec)
+		inode->i_mtime = inode->i_ctime = time;
+
+	d_add(dentry, inode);
+
+	mutex_unlock(&root->d_inode->i_mutex);
+
+	return 0;
+
+fail_lockedalloc:
+	mutex_unlock(&root->d_inode->i_mutex);
+	kfree(private);
+fail_alloc:
+	iput(inode);
+
+fail:
+	return rc;
+}
+
+int pstore_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *inode = NULL;
+	struct dentry *root;
+	int err;
+
+	save_mount_options(sb, data);
+
+	pstore_sb = sb;
+
+	sb->s_maxbytes		= MAX_LFS_FILESIZE;
+	sb->s_blocksize		= PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits	= PAGE_CACHE_SHIFT;
+	sb->s_magic		= PSTOREFS_MAGIC;
+	sb->s_op		= &pstore_ops;
+	sb->s_time_gran		= 1;
+
+	parse_options(data);
+
+	inode = pstore_get_inode(sb, NULL, S_IFDIR | 0755, 0);
+	if (!inode) {
+		err = -ENOMEM;
+		goto fail;
+	}
+	/* override ramfs "dir" options so we catch unlink(2) */
+	inode->i_op = &pstore_dir_inode_operations;
+
+	root = d_alloc_root(inode);
+	sb->s_root = root;
+	if (!root) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	pstore_get_records();
+
+	return 0;
+fail:
+	iput(inode);
+	return err;
+}
+
+static struct dentry *pstore_mount(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data)
+{
+	return mount_single(fs_type, flags, data, pstore_fill_super);
+}
+
+static void pstore_kill_sb(struct super_block *sb)
+{
+	kill_litter_super(sb);
+	pstore_sb = NULL;
+}
+
+static struct file_system_type pstore_fs_type = {
+	.name		= "pstore",
+	.mount		= pstore_mount,
+	.kill_sb	= pstore_kill_sb,
+};
+
+static int __init init_pstore_fs(void)
+{
+	return register_filesystem(&pstore_fs_type);
+}
+module_init(init_pstore_fs)
+
+MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
new file mode 100644
index 0000000..8c9f23e
--- /dev/null
+++ b/fs/pstore/internal.h
@@ -0,0 +1,6 @@
+extern void	pstore_set_kmsg_bytes(int);
+extern void	pstore_get_records(void);
+extern int	pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
+			      char *data, size_t size,
+			      struct timespec time, int (*erase)(u64));
+extern int	pstore_is_mounted(void);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
new file mode 100644
index 0000000..ce9ad84
--- /dev/null
+++ b/fs/pstore/platform.c
@@ -0,0 +1,192 @@
+/*
+ * Persistent Storage - platform driver interface parts.
+ *
+ * Copyright (C) 2010 Intel Corporation <tony.luck@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/atomic.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kmsg_dump.h>
+#include <linux/module.h>
+#include <linux/pstore.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "internal.h"
+
+/*
+ * pstore_lock just protects "psinfo" during
+ * calls to pstore_register()
+ */
+static DEFINE_SPINLOCK(pstore_lock);
+static struct pstore_info *psinfo;
+
+/* How much of the console log to snapshot */
+static unsigned long kmsg_bytes = 10240;
+
+void pstore_set_kmsg_bytes(int bytes)
+{
+	kmsg_bytes = bytes;
+}
+
+/* Tag each group of saved records with a sequence number */
+static int	oopscount;
+
+/*
+ * callback from kmsg_dump. (s2,l2) has the most recently
+ * written bytes, older bytes are in (s1,l1). Save as much
+ * as we can from the end of the buffer.
+ */
+static void pstore_dump(struct kmsg_dumper *dumper,
+	    enum kmsg_dump_reason reason,
+	    const char *s1, unsigned long l1,
+	    const char *s2, unsigned long l2)
+{
+	unsigned long	s1_start, s2_start;
+	unsigned long	l1_cpy, l2_cpy;
+	unsigned long	size, total = 0;
+	char		*dst;
+	u64		id;
+	int		hsize, part = 1;
+
+	mutex_lock(&psinfo->buf_mutex);
+	oopscount++;
+	while (total < kmsg_bytes) {
+		dst = psinfo->buf;
+		hsize = sprintf(dst, "Oops#%d Part%d\n", oopscount, part++);
+		size = psinfo->bufsize - hsize;
+		dst += hsize;
+
+		l2_cpy = min(l2, size);
+		l1_cpy = min(l1, size - l2_cpy);
+
+		if (l1_cpy + l2_cpy == 0)
+			break;
+
+		s2_start = l2 - l2_cpy;
+		s1_start = l1 - l1_cpy;
+
+		memcpy(dst, s1 + s1_start, l1_cpy);
+		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
+
+		id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy);
+		if (pstore_is_mounted())
+			pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
+				      psinfo->buf, hsize + l1_cpy + l2_cpy,
+				      CURRENT_TIME, psinfo->erase);
+		l1 -= l1_cpy;
+		l2 -= l2_cpy;
+		total += l1_cpy + l2_cpy;
+	}
+	mutex_unlock(&psinfo->buf_mutex);
+}
+
+static struct kmsg_dumper pstore_dumper = {
+	.dump = pstore_dump,
+};
+
+/*
+ * platform specific persistent storage driver registers with
+ * us here. If pstore is already mounted, call the platform
+ * read function right away to populate the file system. If not
+ * then the pstore mount code will call us later to fill out
+ * the file system.
+ *
+ * Register with kmsg_dump to save last part of console log on panic.
+ */
+int pstore_register(struct pstore_info *psi)
+{
+	struct module *owner = psi->owner;
+
+	spin_lock(&pstore_lock);
+	if (psinfo) {
+		spin_unlock(&pstore_lock);
+		return -EBUSY;
+	}
+	psinfo = psi;
+	spin_unlock(&pstore_lock);
+
+	if (owner && !try_module_get(owner)) {
+		psinfo = NULL;
+		return -EINVAL;
+	}
+
+	if (pstore_is_mounted())
+		pstore_get_records();
+
+	kmsg_dump_register(&pstore_dumper);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pstore_register);
+
+/*
+ * Read all the records from the persistent store. Create and
+ * file files in our filesystem.
+ */
+void pstore_get_records(void)
+{
+	struct pstore_info *psi = psinfo;
+	size_t			size;
+	u64			id;
+	enum pstore_type_id	type;
+	struct timespec		time;
+	int			failed = 0;
+
+	if (!psi)
+		return;
+
+	mutex_lock(&psinfo->buf_mutex);
+	while ((size = psi->read(&id, &type, &time)) > 0) {
+		if (pstore_mkfile(type, psi->name, id, psi->buf, size,
+				  time, psi->erase))
+			failed++;
+	}
+	mutex_unlock(&psinfo->buf_mutex);
+
+	if (failed)
+		printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
+		       failed, psi->name);
+}
+
+/*
+ * Call platform driver to write a record to the
+ * persistent store.
+ */
+int pstore_write(enum pstore_type_id type, char *buf, size_t size)
+{
+	u64	id;
+
+	if (!psinfo)
+		return -ENODEV;
+
+	if (size > psinfo->bufsize)
+		return -EFBIG;
+
+	mutex_lock(&psinfo->buf_mutex);
+	memcpy(psinfo->buf, buf, size);
+	id = psinfo->write(type, size);
+	if (pstore_is_mounted())
+		pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
+			      size, CURRENT_TIME, psinfo->erase);
+	mutex_unlock(&psinfo->buf_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pstore_write);
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c
index 65444d2..f1ab360 100644
--- a/fs/quota/quota_v2.c
+++ b/fs/quota/quota_v2.c
@@ -112,7 +112,7 @@ static int v2_read_file_info(struct super_block *sb, int type)
 	if (!info->dqi_priv) {
 		printk(KERN_WARNING
 		       "Not enough memory for quota information structure.\n");
-		return -1;
+		return -ENOMEM;
 	}
 	qinfo = info->dqi_priv;
 	if (version == 0) {
diff --git a/fs/reiserfs/Makefile b/fs/reiserfs/Makefile
index 792b3cb..3c3b001 100644
--- a/fs/reiserfs/Makefile
+++ b/fs/reiserfs/Makefile
@@ -31,9 +31,7 @@ endif
 # and causing a panic. Since this behavior only affects ppc32, this ifeq
 # will work around it. If any other architecture displays this behavior,
 # add it here.
-ifeq ($(CONFIG_PPC32),y)
-EXTRA_CFLAGS := $(call cc-ifversion, -lt, 0400, -O1)
-endif
+ccflags-$(CONFIG_PPC32) := $(call cc-ifversion, -lt, 0400, -O1)
 
 TAGS:
 	etags *.c
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 0bae036..1bba24b 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1593,8 +1593,13 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
 	struct inode *inode = dentry->d_inode;
 	int maxlen = *lenp;
 
-	if (maxlen < 3)
+	if (need_parent && (maxlen < 5)) {
+		*lenp = 5;
 		return 255;
+	} else if (maxlen < 3) {
+		*lenp = 3;
+		return 255;
+	}
 
 	data[0] = inode->i_ino;
 	data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3eea859..c77514b 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2876,7 +2876,7 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
 	reiserfs_mounted_fs_count++;
 	if (reiserfs_mounted_fs_count <= 1) {
 		reiserfs_write_unlock(sb);
-		commit_wq = create_workqueue("reiserfs");
+		commit_wq = alloc_workqueue("reiserfs", WQ_MEM_RECLAIM, 0);
 		reiserfs_write_lock(sb);
 	}
 
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 68fdf45..1186626 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -593,7 +593,7 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode,
 	new_inode_init(inode, dir, mode);
 
 	jbegin_count += reiserfs_cache_default_acl(dir);
-	retval = reiserfs_security_init(dir, inode, &security);
+	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
 	if (retval < 0) {
 		drop_new_inode(inode);
 		return retval;
@@ -667,7 +667,7 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 	new_inode_init(inode, dir, mode);
 
 	jbegin_count += reiserfs_cache_default_acl(dir);
-	retval = reiserfs_security_init(dir, inode, &security);
+	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
 	if (retval < 0) {
 		drop_new_inode(inode);
 		return retval;
@@ -747,7 +747,7 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	new_inode_init(inode, dir, mode);
 
 	jbegin_count += reiserfs_cache_default_acl(dir);
-	retval = reiserfs_security_init(dir, inode, &security);
+	retval = reiserfs_security_init(dir, inode, &dentry->d_name, &security);
 	if (retval < 0) {
 		drop_new_inode(inode);
 		return retval;
@@ -1032,7 +1032,8 @@ static int reiserfs_symlink(struct inode *parent_dir,
 	}
 	new_inode_init(inode, parent_dir, mode);
 
-	retval = reiserfs_security_init(parent_dir, inode, &security);
+	retval = reiserfs_security_init(parent_dir, inode, &dentry->d_name,
+					&security);
 	if (retval < 0) {
 		drop_new_inode(inode);
 		return retval;
@@ -1122,10 +1123,6 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir,
 		reiserfs_write_unlock(dir->i_sb);
 		return -EMLINK;
 	}
-	if (inode->i_nlink == 0) {
-		reiserfs_write_unlock(dir->i_sb);
-		return -ENOENT;
-	}
 
 	/* inc before scheduling so reiserfs_unlink knows we are here */
 	inc_nlink(inode);
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 237c692..ef66c18 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -54,6 +54,7 @@ static size_t security_list(struct dentry *dentry, char *list, size_t list_len,
  * of blocks needed for the transaction. If successful, reiserfs_security
  * must be released using reiserfs_security_free when the caller is done. */
 int reiserfs_security_init(struct inode *dir, struct inode *inode,
+			   const struct qstr *qstr,
 			   struct reiserfs_security_handle *sec)
 {
 	int blocks = 0;
@@ -65,7 +66,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
 	if (IS_PRIVATE(dir))
 		return 0;
 
-	error = security_inode_init_security(inode, dir, &sec->name,
+	error = security_inode_init_security(inode, dir, qstr, &sec->name,
 					     &sec->value, &sec->length);
 	if (error) {
 		if (error == -EOPNOTSUPP)
diff --git a/fs/select.c b/fs/select.c
index e56560d..d33418f 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -517,9 +517,6 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
  * Update: ERESTARTSYS breaks at least the xview clock binary, so
  * I'm trying ERESTARTNOHAND which restart only when you want to.
  */
-#define MAX_SELECT_SECONDS \
-	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
-
 int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
 			   fd_set __user *exp, struct timespec *end_time)
 {
diff --git a/fs/stat.c b/fs/stat.c
index d5c61cf..9610391 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -75,13 +75,16 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
 	int error = -EINVAL;
 	int lookup_flags = 0;
 
-	if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)) != 0)
+	if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
+		      AT_EMPTY_PATH)) != 0)
 		goto out;
 
 	if (!(flag & AT_SYMLINK_NOFOLLOW))
 		lookup_flags |= LOOKUP_FOLLOW;
 	if (flag & AT_NO_AUTOMOUNT)
 		lookup_flags |= LOOKUP_NO_AUTOMOUNT;
+	if (flag & AT_EMPTY_PATH)
+		lookup_flags |= LOOKUP_EMPTY;
 
 	error = user_path_at(dfd, filename, lookup_flags, &path);
 	if (error)
@@ -297,7 +300,7 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
 	if (bufsiz <= 0)
 		return -EINVAL;
 
-	error = user_path_at(dfd, pathname, 0, &path);
+	error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path);
 	if (!error) {
 		struct inode *inode = path.dentry->d_inode;
 
diff --git a/fs/statfs.c b/fs/statfs.c
index 30ea8c8..8244924 100644
--- a/fs/statfs.c
+++ b/fs/statfs.c
@@ -73,149 +73,135 @@ int vfs_statfs(struct path *path, struct kstatfs *buf)
 }
 EXPORT_SYMBOL(vfs_statfs);
 
-static int do_statfs_native(struct path *path, struct statfs *buf)
+int user_statfs(const char __user *pathname, struct kstatfs *st)
 {
-	struct kstatfs st;
-	int retval;
+	struct path path;
+	int error = user_path(pathname, &path);
+	if (!error) {
+		error = vfs_statfs(&path, st);
+		path_put(&path);
+	}
+	return error;
+}
 
-	retval = vfs_statfs(path, &st);
-	if (retval)
-		return retval;
+int fd_statfs(int fd, struct kstatfs *st)
+{
+	struct file *file = fget(fd);
+	int error = -EBADF;
+	if (file) {
+		error = vfs_statfs(&file->f_path, st);
+		fput(file);
+	}
+	return error;
+}
 
-	if (sizeof(*buf) == sizeof(st))
-		memcpy(buf, &st, sizeof(st));
+static int do_statfs_native(struct kstatfs *st, struct statfs __user *p)
+{
+	struct statfs buf;
+
+	if (sizeof(buf) == sizeof(*st))
+		memcpy(&buf, st, sizeof(*st));
 	else {
-		if (sizeof buf->f_blocks == 4) {
-			if ((st.f_blocks | st.f_bfree | st.f_bavail |
-			     st.f_bsize | st.f_frsize) &
+		if (sizeof buf.f_blocks == 4) {
+			if ((st->f_blocks | st->f_bfree | st->f_bavail |
+			     st->f_bsize | st->f_frsize) &
 			    0xffffffff00000000ULL)
 				return -EOVERFLOW;
 			/*
 			 * f_files and f_ffree may be -1; it's okay to stuff
 			 * that into 32 bits
 			 */
-			if (st.f_files != -1 &&
-			    (st.f_files & 0xffffffff00000000ULL))
+			if (st->f_files != -1 &&
+			    (st->f_files & 0xffffffff00000000ULL))
 				return -EOVERFLOW;
-			if (st.f_ffree != -1 &&
-			    (st.f_ffree & 0xffffffff00000000ULL))
+			if (st->f_ffree != -1 &&
+			    (st->f_ffree & 0xffffffff00000000ULL))
 				return -EOVERFLOW;
 		}
 
-		buf->f_type = st.f_type;
-		buf->f_bsize = st.f_bsize;
-		buf->f_blocks = st.f_blocks;
-		buf->f_bfree = st.f_bfree;
-		buf->f_bavail = st.f_bavail;
-		buf->f_files = st.f_files;
-		buf->f_ffree = st.f_ffree;
-		buf->f_fsid = st.f_fsid;
-		buf->f_namelen = st.f_namelen;
-		buf->f_frsize = st.f_frsize;
-		buf->f_flags = st.f_flags;
-		memset(buf->f_spare, 0, sizeof(buf->f_spare));
+		buf.f_type = st->f_type;
+		buf.f_bsize = st->f_bsize;
+		buf.f_blocks = st->f_blocks;
+		buf.f_bfree = st->f_bfree;
+		buf.f_bavail = st->f_bavail;
+		buf.f_files = st->f_files;
+		buf.f_ffree = st->f_ffree;
+		buf.f_fsid = st->f_fsid;
+		buf.f_namelen = st->f_namelen;
+		buf.f_frsize = st->f_frsize;
+		buf.f_flags = st->f_flags;
+		memset(buf.f_spare, 0, sizeof(buf.f_spare));
 	}
+	if (copy_to_user(p, &buf, sizeof(buf)))
+		return -EFAULT;
 	return 0;
 }
 
-static int do_statfs64(struct path *path, struct statfs64 *buf)
+static int do_statfs64(struct kstatfs *st, struct statfs64 __user *p)
 {
-	struct kstatfs st;
-	int retval;
-
-	retval = vfs_statfs(path, &st);
-	if (retval)
-		return retval;
-
-	if (sizeof(*buf) == sizeof(st))
-		memcpy(buf, &st, sizeof(st));
+	struct statfs64 buf;
+	if (sizeof(buf) == sizeof(*st))
+		memcpy(&buf, st, sizeof(*st));
 	else {
-		buf->f_type = st.f_type;
-		buf->f_bsize = st.f_bsize;
-		buf->f_blocks = st.f_blocks;
-		buf->f_bfree = st.f_bfree;
-		buf->f_bavail = st.f_bavail;
-		buf->f_files = st.f_files;
-		buf->f_ffree = st.f_ffree;
-		buf->f_fsid = st.f_fsid;
-		buf->f_namelen = st.f_namelen;
-		buf->f_frsize = st.f_frsize;
-		buf->f_flags = st.f_flags;
-		memset(buf->f_spare, 0, sizeof(buf->f_spare));
+		buf.f_type = st->f_type;
+		buf.f_bsize = st->f_bsize;
+		buf.f_blocks = st->f_blocks;
+		buf.f_bfree = st->f_bfree;
+		buf.f_bavail = st->f_bavail;
+		buf.f_files = st->f_files;
+		buf.f_ffree = st->f_ffree;
+		buf.f_fsid = st->f_fsid;
+		buf.f_namelen = st->f_namelen;
+		buf.f_frsize = st->f_frsize;
+		buf.f_flags = st->f_flags;
+		memset(buf.f_spare, 0, sizeof(buf.f_spare));
 	}
+	if (copy_to_user(p, &buf, sizeof(buf)))
+		return -EFAULT;
 	return 0;
 }
 
 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
 {
-	struct path path;
-	int error;
-
-	error = user_path(pathname, &path);
-	if (!error) {
-		struct statfs tmp;
-		error = do_statfs_native(&path, &tmp);
-		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-			error = -EFAULT;
-		path_put(&path);
-	}
+	struct kstatfs st;
+	int error = user_statfs(pathname, &st);
+	if (!error)
+		error = do_statfs_native(&st, buf);
 	return error;
 }
 
 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
 {
-	struct path path;
-	long error;
-
+	struct kstatfs st;
+	int error;
 	if (sz != sizeof(*buf))
 		return -EINVAL;
-	error = user_path(pathname, &path);
-	if (!error) {
-		struct statfs64 tmp;
-		error = do_statfs64(&path, &tmp);
-		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-			error = -EFAULT;
-		path_put(&path);
-	}
+	error = user_statfs(pathname, &st);
+	if (!error)
+		error = do_statfs64(&st, buf);
 	return error;
 }
 
 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
 {
-	struct file *file;
-	struct statfs tmp;
-	int error;
-
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-	error = do_statfs_native(&file->f_path, &tmp);
-	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-		error = -EFAULT;
-	fput(file);
-out:
+	struct kstatfs st;
+	int error = fd_statfs(fd, &st);
+	if (!error)
+		error = do_statfs_native(&st, buf);
 	return error;
 }
 
 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
 {
-	struct file *file;
-	struct statfs64 tmp;
+	struct kstatfs st;
 	int error;
 
 	if (sz != sizeof(*buf))
 		return -EINVAL;
 
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-	error = do_statfs64(&file->f_path, &tmp);
-	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-		error = -EFAULT;
-	fput(file);
-out:
+	error = fd_statfs(fd, &st);
+	if (!error)
+		error = do_statfs64(&st, buf);
 	return error;
 }
 
diff --git a/fs/super.c b/fs/super.c
index 7e9dd4c..e848649 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -843,23 +843,6 @@ error:
 }
 EXPORT_SYMBOL(mount_bdev);
 
-int get_sb_bdev(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
-	struct vfsmount *mnt)
-{
-	struct dentry *root;
-
-	root = mount_bdev(fs_type, flags, dev_name, data, fill_super);
-	if (IS_ERR(root))
-		return PTR_ERR(root);
-	mnt->mnt_root = root;
-	mnt->mnt_sb = root->d_sb;
-	return 0;
-}
-
-EXPORT_SYMBOL(get_sb_bdev);
-
 void kill_block_super(struct super_block *sb)
 {
 	struct block_device *bdev = sb->s_bdev;
@@ -897,22 +880,6 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
 }
 EXPORT_SYMBOL(mount_nodev);
 
-int get_sb_nodev(struct file_system_type *fs_type,
-	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
-	struct vfsmount *mnt)
-{
-	struct dentry *root;
-
-	root = mount_nodev(fs_type, flags, data, fill_super);
-	if (IS_ERR(root))
-		return PTR_ERR(root);
-	mnt->mnt_root = root;
-	mnt->mnt_sb = root->d_sb;
-	return 0;
-}
-EXPORT_SYMBOL(get_sb_nodev);
-
 static int compare_single(struct super_block *s, void *p)
 {
 	return 1;
@@ -943,69 +910,35 @@ struct dentry *mount_single(struct file_system_type *fs_type,
 }
 EXPORT_SYMBOL(mount_single);
 
-int get_sb_single(struct file_system_type *fs_type,
-	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
-	struct vfsmount *mnt)
-{
-	struct dentry *root;
-	root = mount_single(fs_type, flags, data, fill_super);
-	if (IS_ERR(root))
-		return PTR_ERR(root);
-	mnt->mnt_root = root;
-	mnt->mnt_sb = root->d_sb;
-	return 0;
-}
-
-EXPORT_SYMBOL(get_sb_single);
-
-struct vfsmount *
-vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
+struct dentry *
+mount_fs(struct file_system_type *type, int flags, const char *name, void *data)
 {
-	struct vfsmount *mnt;
 	struct dentry *root;
+	struct super_block *sb;
 	char *secdata = NULL;
-	int error;
-
-	if (!type)
-		return ERR_PTR(-ENODEV);
-
-	error = -ENOMEM;
-	mnt = alloc_vfsmnt(name);
-	if (!mnt)
-		goto out;
-
-	if (flags & MS_KERNMOUNT)
-		mnt->mnt_flags = MNT_INTERNAL;
+	int error = -ENOMEM;
 
 	if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
 		secdata = alloc_secdata();
 		if (!secdata)
-			goto out_mnt;
+			goto out;
 
 		error = security_sb_copy_data(data, secdata);
 		if (error)
 			goto out_free_secdata;
 	}
 
-	if (type->mount) {
-		root = type->mount(type, flags, name, data);
-		if (IS_ERR(root)) {
-			error = PTR_ERR(root);
-			goto out_free_secdata;
-		}
-		mnt->mnt_root = root;
-		mnt->mnt_sb = root->d_sb;
-	} else {
-		error = type->get_sb(type, flags, name, data, mnt);
-		if (error < 0)
-			goto out_free_secdata;
+	root = type->mount(type, flags, name, data);
+	if (IS_ERR(root)) {
+		error = PTR_ERR(root);
+		goto out_free_secdata;
 	}
-	BUG_ON(!mnt->mnt_sb);
-	WARN_ON(!mnt->mnt_sb->s_bdi);
-	mnt->mnt_sb->s_flags |= MS_BORN;
+	sb = root->d_sb;
+	BUG_ON(!sb);
+	WARN_ON(!sb->s_bdi);
+	sb->s_flags |= MS_BORN;
 
-	error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata);
+	error = security_sb_kern_mount(sb, flags, secdata);
 	if (error)
 		goto out_sb;
 
@@ -1016,27 +949,21 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
 	 * violate this rule. This warning should be either removed or
 	 * converted to a BUG() in 2.6.34.
 	 */
-	WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
-		"negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes);
+	WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
+		"negative value (%lld)\n", type->name, sb->s_maxbytes);
 
-	mnt->mnt_mountpoint = mnt->mnt_root;
-	mnt->mnt_parent = mnt;
-	up_write(&mnt->mnt_sb->s_umount);
+	up_write(&sb->s_umount);
 	free_secdata(secdata);
-	return mnt;
+	return root;
 out_sb:
-	dput(mnt->mnt_root);
-	deactivate_locked_super(mnt->mnt_sb);
+	dput(root);
+	deactivate_locked_super(sb);
 out_free_secdata:
 	free_secdata(secdata);
-out_mnt:
-	free_vfsmnt(mnt);
 out:
 	return ERR_PTR(error);
 }
 
-EXPORT_SYMBOL_GPL(vfs_kern_mount);
-
 /**
  * freeze_super - lock the filesystem and force it into a consistent state
  * @sb: the super to lock
@@ -1126,49 +1053,3 @@ out:
 	return 0;
 }
 EXPORT_SYMBOL(thaw_super);
-
-static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype)
-{
-	int err;
-	const char *subtype = strchr(fstype, '.');
-	if (subtype) {
-		subtype++;
-		err = -EINVAL;
-		if (!subtype[0])
-			goto err;
-	} else
-		subtype = "";
-
-	mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL);
-	err = -ENOMEM;
-	if (!mnt->mnt_sb->s_subtype)
-		goto err;
-	return mnt;
-
- err:
-	mntput(mnt);
-	return ERR_PTR(err);
-}
-
-struct vfsmount *
-do_kern_mount(const char *fstype, int flags, const char *name, void *data)
-{
-	struct file_system_type *type = get_fs_type(fstype);
-	struct vfsmount *mnt;
-	if (!type)
-		return ERR_PTR(-ENODEV);
-	mnt = vfs_kern_mount(type, flags, name, data);
-	if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
-	    !mnt->mnt_sb->s_subtype)
-		mnt = fs_set_subtype(mnt, fstype);
-	put_filesystem(type);
-	return mnt;
-}
-EXPORT_SYMBOL_GPL(do_kern_mount);
-
-struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
-{
-	return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
-}
-
-EXPORT_SYMBOL_GPL(kern_mount_data);
diff --git a/fs/sync.c b/fs/sync.c
index ba76b96..92ca208 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -7,6 +7,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/namei.h>
 #include <linux/sched.h>
 #include <linux/writeback.h>
 #include <linux/syscalls.h>
@@ -128,6 +129,29 @@ void emergency_sync(void)
 	}
 }
 
+/*
+ * sync a single super
+ */
+SYSCALL_DEFINE1(syncfs, int, fd)
+{
+	struct file *file;
+	struct super_block *sb;
+	int ret;
+	int fput_needed;
+
+	file = fget_light(fd, &fput_needed);
+	if (!file)
+		return -EBADF;
+	sb = file->f_dentry->d_sb;
+
+	down_read(&sb->s_umount);
+	ret = sync_filesystem(sb);
+	up_read(&sb->s_umount);
+
+	fput_light(file, fput_needed);
+	return ret;
+}
+
 /**
  * vfs_fsync_range - helper to sync a range of data & metadata to disk
  * @file:		file to sync
diff --git a/fs/ubifs/Kconfig b/fs/ubifs/Kconfig
index 830e3f7..1d1859d 100644
--- a/fs/ubifs/Kconfig
+++ b/fs/ubifs/Kconfig
@@ -44,23 +44,20 @@ config UBIFS_FS_ZLIB
 
 # Debugging-related stuff
 config UBIFS_FS_DEBUG
-	bool "Enable debugging"
+	bool "Enable debugging support"
 	depends on UBIFS_FS
 	select DEBUG_FS
 	select KALLSYMS_ALL
 	help
-	  This option enables UBIFS debugging.
-
-config UBIFS_FS_DEBUG_MSG_LVL
-	int "Default message level (0 = no extra messages, 3 = lots)"
-	depends on UBIFS_FS_DEBUG
-	default "0"
-	help
-	  This controls the amount of debugging messages produced by UBIFS.
-	  If reporting bugs, please try to have available a full dump of the
-	  messages at level 1 while the misbehaviour was occurring. Level 2
-	  may become necessary if level 1 messages were not enough to find the
-	  bug. Generally Level 3 should be avoided.
+	  This option enables UBIFS debugging support. It makes sure various
+	  assertions, self-checks, debugging messages and test modes are compiled
+	  in (this all is compiled out otherwise). Assertions are light-weight
+	  and this option also enables them. Self-checks, debugging messages and
+	  test modes are switched off by default. Thus, it is safe and actually
+	  recommended to have debugging support enabled, and it should not slow
+	  down UBIFS. You can then further enable / disable individual  debugging
+	  features using UBIFS module parameters and the corresponding sysfs
+	  interfaces.
 
 config UBIFS_FS_DEBUG_CHKS
 	bool "Enable extra checks"
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 02429d8..b148fbc 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -48,6 +48,56 @@
 #include <linux/slab.h>
 #include "ubifs.h"
 
+/*
+ * nothing_to_commit - check if there is nothing to commit.
+ * @c: UBIFS file-system description object
+ *
+ * This is a helper function which checks if there is anything to commit. It is
+ * used as an optimization to avoid starting the commit if it is not really
+ * necessary. Indeed, the commit operation always assumes flash I/O (e.g.,
+ * writing the commit start node to the log), and it is better to avoid doing
+ * this unnecessarily. E.g., 'ubifs_sync_fs()' runs the commit, but if there is
+ * nothing to commit, it is more optimal to avoid any flash I/O.
+ *
+ * This function has to be called with @c->commit_sem locked for writing -
+ * this function does not take LPT/TNC locks because the @c->commit_sem
+ * guarantees that we have exclusive access to the TNC and LPT data structures.
+ *
+ * This function returns %1 if there is nothing to commit and %0 otherwise.
+ */
+static int nothing_to_commit(struct ubifs_info *c)
+{
+	/*
+	 * During mounting or remounting from R/O mode to R/W mode we may
+	 * commit for various recovery-related reasons.
+	 */
+	if (c->mounting || c->remounting_rw)
+		return 0;
+
+	/*
+	 * If the root TNC node is dirty, we definitely have something to
+	 * commit.
+	 */
+	if (c->zroot.znode && test_bit(DIRTY_ZNODE, &c->zroot.znode->flags))
+		return 0;
+
+	/*
+	 * Even though the TNC is clean, the LPT tree may have dirty nodes. For
+	 * example, this may happen if the budgeting subsystem invoked GC to
+	 * make some free space, and the GC found an LEB with only dirty and
+	 * free space. In this case GC would just change the lprops of this
+	 * LEB (by turning all space into free space) and unmap it.
+	 */
+	if (c->nroot && test_bit(DIRTY_CNODE, &c->nroot->flags))
+		return 0;
+
+	ubifs_assert(atomic_long_read(&c->dirty_zn_cnt) == 0);
+	ubifs_assert(c->dirty_pn_cnt == 0);
+	ubifs_assert(c->dirty_nn_cnt == 0);
+
+	return 1;
+}
+
 /**
  * do_commit - commit the journal.
  * @c: UBIFS file-system description object
@@ -70,6 +120,12 @@ static int do_commit(struct ubifs_info *c)
 		goto out_up;
 	}
 
+	if (nothing_to_commit(c)) {
+		up_write(&c->commit_sem);
+		err = 0;
+		goto out_cancel;
+	}
+
 	/* Sync all write buffers (necessary for recovery) */
 	for (i = 0; i < c->jhead_cnt; i++) {
 		err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
@@ -162,12 +218,12 @@ static int do_commit(struct ubifs_info *c)
 	if (err)
 		goto out;
 
+out_cancel:
 	spin_lock(&c->cs_lock);
 	c->cmt_state = COMMIT_RESTING;
 	wake_up(&c->cmt_wq);
 	dbg_cmt("commit end");
 	spin_unlock(&c->cs_lock);
-
 	return 0;
 
 out_up:
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 0bee4db..01c2b02 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -43,8 +43,8 @@ DEFINE_SPINLOCK(dbg_lock);
 static char dbg_key_buf0[128];
 static char dbg_key_buf1[128];
 
-unsigned int ubifs_msg_flags = UBIFS_MSG_FLAGS_DEFAULT;
-unsigned int ubifs_chk_flags = UBIFS_CHK_FLAGS_DEFAULT;
+unsigned int ubifs_msg_flags;
+unsigned int ubifs_chk_flags;
 unsigned int ubifs_tst_flags;
 
 module_param_named(debug_msgs, ubifs_msg_flags, uint, S_IRUGO | S_IWUSR);
@@ -810,16 +810,24 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 {
 	struct ubifs_scan_leb *sleb;
 	struct ubifs_scan_node *snod;
+	void *buf;
 
 	if (dbg_failure_mode)
 		return;
 
 	printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
 	       current->pid, lnum);
-	sleb = ubifs_scan(c, lnum, 0, c->dbg->buf, 0);
+
+	buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubifs_err("cannot allocate memory for dumping LEB %d", lnum);
+		return;
+	}
+
+	sleb = ubifs_scan(c, lnum, 0, buf, 0);
 	if (IS_ERR(sleb)) {
 		ubifs_err("scan error %d", (int)PTR_ERR(sleb));
-		return;
+		goto out;
 	}
 
 	printk(KERN_DEBUG "LEB %d has %d nodes ending at %d\n", lnum,
@@ -835,6 +843,9 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 	printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n",
 	       current->pid, lnum);
 	ubifs_scan_destroy(sleb);
+
+out:
+	vfree(buf);
 	return;
 }
 
@@ -2690,16 +2701,8 @@ int ubifs_debugging_init(struct ubifs_info *c)
 	if (!c->dbg)
 		return -ENOMEM;
 
-	c->dbg->buf = vmalloc(c->leb_size);
-	if (!c->dbg->buf)
-		goto out;
-
 	failure_mode_init(c);
 	return 0;
-
-out:
-	kfree(c->dbg);
-	return -ENOMEM;
 }
 
 /**
@@ -2709,7 +2712,6 @@ out:
 void ubifs_debugging_exit(struct ubifs_info *c)
 {
 	failure_mode_exit(c);
-	vfree(c->dbg->buf);
 	kfree(c->dbg);
 }
 
@@ -2813,19 +2815,19 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
 	}
 
 	fname = "dump_lprops";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_lprops = dent;
 
 	fname = "dump_budg";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_budg = dent;
 
 	fname = "dump_tnc";
-	dent = debugfs_create_file(fname, S_IWUGO, d->dfs_dir, c, &dfs_fops);
+	dent = debugfs_create_file(fname, S_IWUSR, d->dfs_dir, c, &dfs_fops);
 	if (IS_ERR(dent))
 		goto out_remove;
 	d->dfs_dump_tnc = dent;
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 69ebe47..919f0de 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -27,7 +27,6 @@
 
 /**
  * ubifs_debug_info - per-FS debugging information.
- * @buf: a buffer of LEB size, used for various purposes
  * @old_zroot: old index root - used by 'dbg_check_old_index()'
  * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
  * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
@@ -54,7 +53,6 @@
  * dfs_dump_tnc: "dump TNC" debugfs knob
  */
 struct ubifs_debug_info {
-	void *buf;
 	struct ubifs_zbranch old_zroot;
 	int old_zroot_level;
 	unsigned long long old_zroot_sqnum;
@@ -173,7 +171,7 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 #define dbg_rcvry(fmt, ...) dbg_do_msg(UBIFS_MSG_RCVRY, fmt, ##__VA_ARGS__)
 
 /*
- * Debugging message type flags (must match msg_type_names in debug.c).
+ * Debugging message type flags.
  *
  * UBIFS_MSG_GEN: general messages
  * UBIFS_MSG_JNL: journal messages
@@ -205,14 +203,8 @@ enum {
 	UBIFS_MSG_RCVRY = 0x1000,
 };
 
-/* Debugging message type flags for each default debug message level */
-#define UBIFS_MSG_LVL_0 0
-#define UBIFS_MSG_LVL_1 0x1
-#define UBIFS_MSG_LVL_2 0x7f
-#define UBIFS_MSG_LVL_3 0xffff
-
 /*
- * Debugging check flags (must match chk_names in debug.c).
+ * Debugging check flags.
  *
  * UBIFS_CHK_GEN: general checks
  * UBIFS_CHK_TNC: check TNC
@@ -233,7 +225,7 @@ enum {
 };
 
 /*
- * Special testing flags (must match tst_names in debug.c).
+ * Special testing flags.
  *
  * UBIFS_TST_FORCE_IN_THE_GAPS: force the use of in-the-gaps method
  * UBIFS_TST_RCVRY: failure mode for recovery testing
@@ -243,22 +235,6 @@ enum {
 	UBIFS_TST_RCVRY             = 0x4,
 };
 
-#if CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 1
-#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_1
-#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 2
-#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_2
-#elif CONFIG_UBIFS_FS_DEBUG_MSG_LVL == 3
-#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_3
-#else
-#define UBIFS_MSG_FLAGS_DEFAULT UBIFS_MSG_LVL_0
-#endif
-
-#ifdef CONFIG_UBIFS_FS_DEBUG_CHKS
-#define UBIFS_CHK_FLAGS_DEFAULT 0xffffffff
-#else
-#define UBIFS_CHK_FLAGS_DEFAULT 0
-#endif
-
 extern spinlock_t dbg_lock;
 
 extern unsigned int ubifs_msg_flags;
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 14f64b6..7217d67 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -522,24 +522,6 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
 	ubifs_assert(mutex_is_locked(&dir->i_mutex));
 	ubifs_assert(mutex_is_locked(&inode->i_mutex));
 
-	/*
-	 * Return -ENOENT if we've raced with unlink and i_nlink is 0.  Doing
-	 * otherwise has the potential to corrupt the orphan inode list.
-	 *
-	 * Indeed, consider a scenario when 'vfs_link(dirA/fileA)' and
-	 * 'vfs_unlink(dirA/fileA, dirB/fileB)' race. 'vfs_link()' does not
-	 * lock 'dirA->i_mutex', so this is possible. Both of the functions
-	 * lock 'fileA->i_mutex' though. Suppose 'vfs_unlink()' wins, and takes
-	 * 'fileA->i_mutex' mutex first. Suppose 'fileA->i_nlink' is 1. In this
-	 * case 'ubifs_unlink()' will drop the last reference, and put 'inodeA'
-	 * to the list of orphans. After this, 'vfs_link()' will link
-	 * 'dirB/fileB' to 'inodeA'. This is a problem because, for example,
-	 * the subsequent 'vfs_unlink(dirB/fileB)' will add the same inode
-	 * to the list of orphans.
-	 */
-	 if (inode->i_nlink == 0)
-		 return -ENOENT;
-
 	err = dbg_check_synced_i_size(inode);
 	if (err)
 		return err;
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index d821731..dfd168b 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -31,6 +31,26 @@
  * buffer is full or when it is not used for some time (by timer). This is
  * similar to the mechanism is used by JFFS2.
  *
+ * UBIFS distinguishes between minimum write size (@c->min_io_size) and maximum
+ * write size (@c->max_write_size). The latter is the maximum amount of bytes
+ * the underlying flash is able to program at a time, and writing in
+ * @c->max_write_size units should presumably be faster. Obviously,
+ * @c->min_io_size <= @c->max_write_size. Write-buffers are of
+ * @c->max_write_size bytes in size for maximum performance. However, when a
+ * write-buffer is flushed, only the portion of it (aligned to @c->min_io_size
+ * boundary) which contains data is written, not the whole write-buffer,
+ * because this is more space-efficient.
+ *
+ * This optimization adds few complications to the code. Indeed, on the one
+ * hand, we want to write in optimal @c->max_write_size bytes chunks, which
+ * also means aligning writes at the @c->max_write_size bytes offsets. On the
+ * other hand, we do not want to waste space when synchronizing the write
+ * buffer, so during synchronization we writes in smaller chunks. And this makes
+ * the next write offset to be not aligned to @c->max_write_size bytes. So the
+ * have to make sure that the write-buffer offset (@wbuf->offs) becomes aligned
+ * to @c->max_write_size bytes again. We do this by temporarily shrinking
+ * write-buffer size (@wbuf->size).
+ *
  * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by
  * mutexes defined inside these objects. Since sometimes upper-level code
  * has to lock the write-buffer (e.g. journal space reservation code), many
@@ -46,8 +66,8 @@
  * UBIFS uses padding when it pads to the next min. I/O unit. In this case it
  * uses padding nodes or padding bytes, if the padding node does not fit.
  *
- * All UBIFS nodes are protected by CRC checksums and UBIFS checks all nodes
- * every time they are read from the flash media.
+ * All UBIFS nodes are protected by CRC checksums and UBIFS checks CRC when
+ * they are read from the flash media.
  */
 
 #include <linux/crc32.h>
@@ -88,8 +108,12 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
  * This function may skip data nodes CRC checking if @c->no_chk_data_crc is
  * true, which is controlled by corresponding UBIFS mount option. However, if
  * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is
- * checked. Similarly, if @c->always_chk_crc is true, @c->no_chk_data_crc is
- * ignored and CRC is checked.
+ * checked. Similarly, if @c->mounting or @c->remounting_rw is true (we are
+ * mounting or re-mounting to R/W mode), @c->no_chk_data_crc is ignored and CRC
+ * is checked. This is because during mounting or re-mounting from R/O mode to
+ * R/W mode we may read journal nodes (when replying the journal or doing the
+ * recovery) and the journal nodes may potentially be corrupted, so checking is
+ * required.
  *
  * This function returns zero in case of success and %-EUCLEAN in case of bad
  * CRC or magic.
@@ -131,8 +155,8 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
 		   node_len > c->ranges[type].max_len)
 		goto out_len;
 
-	if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc &&
-	     c->no_chk_data_crc)
+	if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->mounting &&
+	    !c->remounting_rw && c->no_chk_data_crc)
 		return 0;
 
 	crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
@@ -343,11 +367,17 @@ static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
  *
  * This function synchronizes write-buffer @buf and returns zero in case of
  * success or a negative error code in case of failure.
+ *
+ * Note, although write-buffers are of @c->max_write_size, this function does
+ * not necessarily writes all @c->max_write_size bytes to the flash. Instead,
+ * if the write-buffer is only partially filled with data, only the used part
+ * of the write-buffer (aligned on @c->min_io_size boundary) is synchronized.
+ * This way we waste less space.
  */
 int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
 {
 	struct ubifs_info *c = wbuf->c;
-	int err, dirt;
+	int err, dirt, sync_len;
 
 	cancel_wbuf_timer_nolock(wbuf);
 	if (!wbuf->used || wbuf->lnum == -1)
@@ -357,27 +387,53 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
 	dbg_io("LEB %d:%d, %d bytes, jhead %s",
 	       wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));
 	ubifs_assert(!(wbuf->avail & 7));
-	ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
+	ubifs_assert(wbuf->offs + wbuf->size <= c->leb_size);
+	ubifs_assert(wbuf->size >= c->min_io_size);
+	ubifs_assert(wbuf->size <= c->max_write_size);
+	ubifs_assert(wbuf->size % c->min_io_size == 0);
 	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->leb_size - wbuf->offs >= c->max_write_size)
+		ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size ));
 
 	if (c->ro_error)
 		return -EROFS;
 
-	ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail);
+	/*
+	 * Do not write whole write buffer but write only the minimum necessary
+	 * amount of min. I/O units.
+	 */
+	sync_len = ALIGN(wbuf->used, c->min_io_size);
+	dirt = sync_len - wbuf->used;
+	if (dirt)
+		ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
 	err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-			    c->min_io_size, wbuf->dtype);
+			    sync_len, wbuf->dtype);
 	if (err) {
 		ubifs_err("cannot write %d bytes to LEB %d:%d",
-			  c->min_io_size, wbuf->lnum, wbuf->offs);
+			  sync_len, wbuf->lnum, wbuf->offs);
 		dbg_dump_stack();
 		return err;
 	}
 
-	dirt = wbuf->avail;
-
 	spin_lock(&wbuf->lock);
-	wbuf->offs += c->min_io_size;
-	wbuf->avail = c->min_io_size;
+	wbuf->offs += sync_len;
+	/*
+	 * Now @wbuf->offs is not necessarily aligned to @c->max_write_size.
+	 * But our goal is to optimize writes and make sure we write in
+	 * @c->max_write_size chunks and to @c->max_write_size-aligned offset.
+	 * Thus, if @wbuf->offs is not aligned to @c->max_write_size now, make
+	 * sure that @wbuf->offs + @wbuf->size is aligned to
+	 * @c->max_write_size. This way we make sure that after next
+	 * write-buffer flush we are again at the optimal offset (aligned to
+	 * @c->max_write_size).
+	 */
+	if (c->leb_size - wbuf->offs < c->max_write_size)
+		wbuf->size = c->leb_size - wbuf->offs;
+	else if (wbuf->offs & (c->max_write_size - 1))
+		wbuf->size = ALIGN(wbuf->offs, c->max_write_size) - wbuf->offs;
+	else
+		wbuf->size = c->max_write_size;
+	wbuf->avail = wbuf->size;
 	wbuf->used = 0;
 	wbuf->next_ino = 0;
 	spin_unlock(&wbuf->lock);
@@ -420,7 +476,13 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
 	spin_lock(&wbuf->lock);
 	wbuf->lnum = lnum;
 	wbuf->offs = offs;
-	wbuf->avail = c->min_io_size;
+	if (c->leb_size - wbuf->offs < c->max_write_size)
+		wbuf->size = c->leb_size - wbuf->offs;
+	else if (wbuf->offs & (c->max_write_size - 1))
+		wbuf->size = ALIGN(wbuf->offs, c->max_write_size) - wbuf->offs;
+	else
+		wbuf->size = c->max_write_size;
+	wbuf->avail = wbuf->size;
 	wbuf->used = 0;
 	spin_unlock(&wbuf->lock);
 	wbuf->dtype = dtype;
@@ -500,8 +562,9 @@ out_timers:
  *
  * This function writes data to flash via write-buffer @wbuf. This means that
  * the last piece of the node won't reach the flash media immediately if it
- * does not take whole minimal I/O unit. Instead, the node will sit in RAM
- * until the write-buffer is synchronized (e.g., by timer).
+ * does not take whole max. write unit (@c->max_write_size). Instead, the node
+ * will sit in RAM until the write-buffer is synchronized (e.g., by timer, or
+ * because more data are appended to the write-buffer).
  *
  * This function returns zero in case of success and a negative error code in
  * case of failure. If the node cannot be written because there is no more
@@ -518,9 +581,14 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 	ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
 	ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
 	ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
-	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size);
+	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= wbuf->size);
+	ubifs_assert(wbuf->size >= c->min_io_size);
+	ubifs_assert(wbuf->size <= c->max_write_size);
+	ubifs_assert(wbuf->size % c->min_io_size == 0);
 	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
 	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->leb_size - wbuf->offs >= c->max_write_size)
+		ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size ));
 
 	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {
 		err = -ENOSPC;
@@ -543,14 +611,18 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 			dbg_io("flush jhead %s wbuf to LEB %d:%d",
 			       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
 			err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
-					    wbuf->offs, c->min_io_size,
+					    wbuf->offs, wbuf->size,
 					    wbuf->dtype);
 			if (err)
 				goto out;
 
 			spin_lock(&wbuf->lock);
-			wbuf->offs += c->min_io_size;
-			wbuf->avail = c->min_io_size;
+			wbuf->offs += wbuf->size;
+			if (c->leb_size - wbuf->offs >= c->max_write_size)
+				wbuf->size = c->max_write_size;
+			else
+				wbuf->size = c->leb_size - wbuf->offs;
+			wbuf->avail = wbuf->size;
 			wbuf->used = 0;
 			wbuf->next_ino = 0;
 			spin_unlock(&wbuf->lock);
@@ -564,33 +636,57 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		goto exit;
 	}
 
-	/*
-	 * The node is large enough and does not fit entirely within current
-	 * minimal I/O unit. We have to fill and flush write-buffer and switch
-	 * to the next min. I/O unit.
-	 */
-	dbg_io("flush jhead %s wbuf to LEB %d:%d",
-	       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
-	memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
-	err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-			    c->min_io_size, wbuf->dtype);
-	if (err)
-		goto out;
+	offs = wbuf->offs;
+	written = 0;
 
-	offs = wbuf->offs + c->min_io_size;
-	len -= wbuf->avail;
-	aligned_len -= wbuf->avail;
-	written = wbuf->avail;
+	if (wbuf->used) {
+		/*
+		 * The node is large enough and does not fit entirely within
+		 * current available space. We have to fill and flush
+		 * write-buffer and switch to the next max. write unit.
+		 */
+		dbg_io("flush jhead %s wbuf to LEB %d:%d",
+		       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
+		memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
+		err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
+				    wbuf->size, wbuf->dtype);
+		if (err)
+			goto out;
+
+		offs += wbuf->size;
+		len -= wbuf->avail;
+		aligned_len -= wbuf->avail;
+		written += wbuf->avail;
+	} else if (wbuf->offs & (c->max_write_size - 1)) {
+		/*
+		 * The write-buffer offset is not aligned to
+		 * @c->max_write_size and @wbuf->size is less than
+		 * @c->max_write_size. Write @wbuf->size bytes to make sure the
+		 * following writes are done in optimal @c->max_write_size
+		 * chunks.
+		 */
+		dbg_io("write %d bytes to LEB %d:%d",
+		       wbuf->size, wbuf->lnum, wbuf->offs);
+		err = ubi_leb_write(c->ubi, wbuf->lnum, buf, wbuf->offs,
+				    wbuf->size, wbuf->dtype);
+		if (err)
+			goto out;
+
+		offs += wbuf->size;
+		len -= wbuf->size;
+		aligned_len -= wbuf->size;
+		written += wbuf->size;
+	}
 
 	/*
-	 * The remaining data may take more whole min. I/O units, so write the
-	 * remains multiple to min. I/O unit size directly to the flash media.
+	 * The remaining data may take more whole max. write units, so write the
+	 * remains multiple to max. write unit size directly to the flash media.
 	 * We align node length to 8-byte boundary because we anyway flash wbuf
 	 * if the remaining space is less than 8 bytes.
 	 */
-	n = aligned_len >> c->min_io_shift;
+	n = aligned_len >> c->max_write_shift;
 	if (n) {
-		n <<= c->min_io_shift;
+		n <<= c->max_write_shift;
 		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, offs);
 		err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written, offs, n,
 				    wbuf->dtype);
@@ -606,14 +702,18 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 	if (aligned_len)
 		/*
 		 * And now we have what's left and what does not take whole
-		 * min. I/O unit, so write it to the write-buffer and we are
+		 * max. write unit, so write it to the write-buffer and we are
 		 * done.
 		 */
 		memcpy(wbuf->buf, buf + written, len);
 
 	wbuf->offs = offs;
+	if (c->leb_size - wbuf->offs >= c->max_write_size)
+		wbuf->size = c->max_write_size;
+	else
+		wbuf->size = c->leb_size - wbuf->offs;
+	wbuf->avail = wbuf->size - aligned_len;
 	wbuf->used = aligned_len;
-	wbuf->avail = c->min_io_size - aligned_len;
 	wbuf->next_ino = 0;
 	spin_unlock(&wbuf->lock);
 
@@ -837,11 +937,11 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 {
 	size_t size;
 
-	wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
+	wbuf->buf = kmalloc(c->max_write_size, GFP_KERNEL);
 	if (!wbuf->buf)
 		return -ENOMEM;
 
-	size = (c->min_io_size / UBIFS_CH_SZ + 1) * sizeof(ino_t);
+	size = (c->max_write_size / UBIFS_CH_SZ + 1) * sizeof(ino_t);
 	wbuf->inodes = kmalloc(size, GFP_KERNEL);
 	if (!wbuf->inodes) {
 		kfree(wbuf->buf);
@@ -851,7 +951,14 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
 
 	wbuf->used = 0;
 	wbuf->lnum = wbuf->offs = -1;
-	wbuf->avail = c->min_io_size;
+	/*
+	 * If the LEB starts at the max. write size aligned address, then
+	 * write-buffer size has to be set to @c->max_write_size. Otherwise,
+	 * set it to something smaller so that it ends at the closest max.
+	 * write size boundary.
+	 */
+	size = c->max_write_size - (c->leb_start % c->max_write_size);
+	wbuf->avail = wbuf->size = size;
 	wbuf->dtype = UBI_UNKNOWN;
 	wbuf->sync_callback = NULL;
 	mutex_init(&wbuf->io_mutex);
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 914f1bd..aed25e8 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -690,7 +690,7 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 {
 	struct ubifs_data_node *data;
 	int err, lnum, offs, compr_type, out_len;
-	int dlen = UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR;
+	int dlen = COMPRESSED_DATA_NODE_BUF_SZ, allocated = 1;
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
 	dbg_jnl("ino %lu, blk %u, len %d, key %s",
@@ -698,9 +698,19 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 		DBGKEY(key));
 	ubifs_assert(len <= UBIFS_BLOCK_SIZE);
 
-	data = kmalloc(dlen, GFP_NOFS);
-	if (!data)
-		return -ENOMEM;
+	data = kmalloc(dlen, GFP_NOFS | __GFP_NOWARN);
+	if (!data) {
+		/*
+		 * Fall-back to the write reserve buffer. Note, we might be
+		 * currently on the memory reclaim path, when the kernel is
+		 * trying to free some memory by writing out dirty pages. The
+		 * write reserve buffer helps us to guarantee that we are
+		 * always able to write the data.
+		 */
+		allocated = 0;
+		mutex_lock(&c->write_reserve_mutex);
+		data = c->write_reserve_buf;
+	}
 
 	data->ch.node_type = UBIFS_DATA_NODE;
 	key_write(c, key, &data->key);
@@ -736,7 +746,10 @@ int ubifs_jnl_write_data(struct ubifs_info *c, const struct inode *inode,
 		goto out_ro;
 
 	finish_reservation(c);
-	kfree(data);
+	if (!allocated)
+		mutex_unlock(&c->write_reserve_mutex);
+	else
+		kfree(data);
 	return 0;
 
 out_release:
@@ -745,7 +758,10 @@ out_ro:
 	ubifs_ro_mode(c, err);
 	finish_reservation(c);
 out_free:
-	kfree(data);
+	if (!allocated)
+		mutex_unlock(&c->write_reserve_mutex);
+	else
+		kfree(data);
 	return err;
 }
 
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index 4d4ca38..c7b25e2 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -1035,7 +1035,8 @@ static int scan_check_cb(struct ubifs_info *c,
 	struct ubifs_scan_leb *sleb;
 	struct ubifs_scan_node *snod;
 	struct ubifs_lp_stats *lst = &data->lst;
-	int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty;
+	int cat, lnum = lp->lnum, is_idx = 0, used = 0, free, dirty, ret;
+	void *buf = NULL;
 
 	cat = lp->flags & LPROPS_CAT_MASK;
 	if (cat != LPROPS_UNCAT) {
@@ -1093,7 +1094,13 @@ static int scan_check_cb(struct ubifs_info *c,
 		}
 	}
 
-	sleb = ubifs_scan(c, lnum, 0, c->dbg->buf, 0);
+	buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubifs_err("cannot allocate memory to scan LEB %d", lnum);
+		goto out;
+	}
+
+	sleb = ubifs_scan(c, lnum, 0, buf, 0);
 	if (IS_ERR(sleb)) {
 		/*
 		 * After an unclean unmount, empty and freeable LEBs
@@ -1105,7 +1112,8 @@ static int scan_check_cb(struct ubifs_info *c,
 			lst->empty_lebs += 1;
 			lst->total_free += c->leb_size;
 			lst->total_dark += ubifs_calc_dark(c, c->leb_size);
-			return LPT_SCAN_CONTINUE;
+			ret = LPT_SCAN_CONTINUE;
+			goto exit;
 		}
 
 		if (lp->free + lp->dirty == c->leb_size &&
@@ -1115,10 +1123,12 @@ static int scan_check_cb(struct ubifs_info *c,
 			lst->total_free  += lp->free;
 			lst->total_dirty += lp->dirty;
 			lst->total_dark  +=  ubifs_calc_dark(c, c->leb_size);
-			return LPT_SCAN_CONTINUE;
+			ret = LPT_SCAN_CONTINUE;
+			goto exit;
 		}
 		data->err = PTR_ERR(sleb);
-		return LPT_SCAN_STOP;
+		ret = LPT_SCAN_STOP;
+		goto exit;
 	}
 
 	is_idx = -1;
@@ -1236,7 +1246,10 @@ static int scan_check_cb(struct ubifs_info *c,
 	}
 
 	ubifs_scan_destroy(sleb);
-	return LPT_SCAN_CONTINUE;
+	ret = LPT_SCAN_CONTINUE;
+exit:
+	vfree(buf);
+	return ret;
 
 out_print:
 	ubifs_err("bad accounting of LEB %d: free %d, dirty %d flags %#x, "
@@ -1246,6 +1259,7 @@ out_print:
 out_destroy:
 	ubifs_scan_destroy(sleb);
 out:
+	vfree(buf);
 	data->err = -EINVAL;
 	return LPT_SCAN_STOP;
 }
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index 5c90dec..0a3c2c3 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -1628,29 +1628,35 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 {
 	int err, len = c->leb_size, dirty = 0, node_type, node_num, node_len;
 	int ret;
-	void *buf = c->dbg->buf;
+	void *buf, *p;
 
 	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
 		return 0;
 
+	buf = p = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubifs_err("cannot allocate memory for ltab checking");
+		return 0;
+	}
+
 	dbg_lp("LEB %d", lnum);
 	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
 	if (err) {
 		dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err);
-		return err;
+		goto out;
 	}
 	while (1) {
-		if (!is_a_node(c, buf, len)) {
+		if (!is_a_node(c, p, len)) {
 			int i, pad_len;
 
-			pad_len = get_pad_len(c, buf, len);
+			pad_len = get_pad_len(c, p, len);
 			if (pad_len) {
-				buf += pad_len;
+				p += pad_len;
 				len -= pad_len;
 				dirty += pad_len;
 				continue;
 			}
-			if (!dbg_is_all_ff(buf, len)) {
+			if (!dbg_is_all_ff(p, len)) {
 				dbg_msg("invalid empty space in LEB %d at %d",
 					lnum, c->leb_size - len);
 				err = -EINVAL;
@@ -1668,16 +1674,21 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 					lnum, dirty, c->ltab[i].dirty);
 				err = -EINVAL;
 			}
-			return err;
+			goto out;
 		}
-		node_type = get_lpt_node_type(c, buf, &node_num);
+		node_type = get_lpt_node_type(c, p, &node_num);
 		node_len = get_lpt_node_len(c, node_type);
 		ret = dbg_is_node_dirty(c, node_type, lnum, c->leb_size - len);
 		if (ret == 1)
 			dirty += node_len;
-		buf += node_len;
+		p += node_len;
 		len -= node_len;
 	}
+
+	err = 0;
+out:
+	vfree(buf);
+	return err;
 }
 
 /**
@@ -1870,25 +1881,31 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
 static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
 {
 	int err, len = c->leb_size, node_type, node_num, node_len, offs;
-	void *buf = c->dbg->buf;
+	void *buf, *p;
 
 	printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
 	       current->pid, lnum);
+	buf = p = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubifs_err("cannot allocate memory to dump LPT");
+		return;
+	}
+
 	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
 	if (err) {
 		ubifs_err("cannot read LEB %d, error %d", lnum, err);
-		return;
+		goto out;
 	}
 	while (1) {
 		offs = c->leb_size - len;
-		if (!is_a_node(c, buf, len)) {
+		if (!is_a_node(c, p, len)) {
 			int pad_len;
 
-			pad_len = get_pad_len(c, buf, len);
+			pad_len = get_pad_len(c, p, len);
 			if (pad_len) {
 				printk(KERN_DEBUG "LEB %d:%d, pad %d bytes\n",
 				       lnum, offs, pad_len);
-				buf += pad_len;
+				p += pad_len;
 				len -= pad_len;
 				continue;
 			}
@@ -1898,7 +1915,7 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
 			break;
 		}
 
-		node_type = get_lpt_node_type(c, buf, &node_num);
+		node_type = get_lpt_node_type(c, p, &node_num);
 		switch (node_type) {
 		case UBIFS_LPT_PNODE:
 		{
@@ -1923,7 +1940,7 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
 			else
 				printk(KERN_DEBUG "LEB %d:%d, nnode, ",
 				       lnum, offs);
-			err = ubifs_unpack_nnode(c, buf, &nnode);
+			err = ubifs_unpack_nnode(c, p, &nnode);
 			for (i = 0; i < UBIFS_LPT_FANOUT; i++) {
 				printk(KERN_CONT "%d:%d", nnode.nbranch[i].lnum,
 				       nnode.nbranch[i].offs);
@@ -1944,15 +1961,18 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
 			break;
 		default:
 			ubifs_err("LPT node type %d not recognized", node_type);
-			return;
+			goto out;
 		}
 
-		buf += node_len;
+		p += node_len;
 		len -= node_len;
 	}
 
 	printk(KERN_DEBUG "(pid %d) finish dumping LEB %d\n",
 	       current->pid, lnum);
+out:
+	vfree(buf);
+	return;
 }
 
 /**
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index 82009c7..2cdbd31 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -892,15 +892,22 @@ static int dbg_read_orphans(struct check_info *ci, struct ubifs_scan_leb *sleb)
 static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci)
 {
 	int lnum, err = 0;
+	void *buf;
 
 	/* Check no-orphans flag and skip this if no orphans */
 	if (c->no_orphs)
 		return 0;
 
+	buf = __vmalloc(c->leb_size, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubifs_err("cannot allocate memory to check orphans");
+		return 0;
+	}
+
 	for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
 		struct ubifs_scan_leb *sleb;
 
-		sleb = ubifs_scan(c, lnum, 0, c->dbg->buf, 0);
+		sleb = ubifs_scan(c, lnum, 0, buf, 0);
 		if (IS_ERR(sleb)) {
 			err = PTR_ERR(sleb);
 			break;
@@ -912,6 +919,7 @@ static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci)
 			break;
 	}
 
+	vfree(buf);
 	return err;
 }
 
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 77e9b87..936f2cb 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -28,6 +28,23 @@
  * UBIFS always cleans away all remnants of an unclean un-mount, so that
  * errors do not accumulate. However UBIFS defers recovery if it is mounted
  * read-only, and the flash is not modified in that case.
+ *
+ * The general UBIFS approach to the recovery is that it recovers from
+ * corruptions which could be caused by power cuts, but it refuses to recover
+ * from corruption caused by other reasons. And UBIFS tries to distinguish
+ * between these 2 reasons of corruptions and silently recover in the former
+ * case and loudly complain in the latter case.
+ *
+ * UBIFS writes only to erased LEBs, so it writes only to the flash space
+ * containing only 0xFFs. UBIFS also always writes strictly from the beginning
+ * of the LEB to the end. And UBIFS assumes that the underlying flash media
+ * writes in @c->max_write_size bytes at a time.
+ *
+ * Hence, if UBIFS finds a corrupted node at offset X, it expects only the min.
+ * I/O unit corresponding to offset X to contain corrupted data, all the
+ * following min. I/O units have to contain empty space (all 0xFFs). If this is
+ * not true, the corruption cannot be the result of a power cut, and UBIFS
+ * refuses to mount.
  */
 
 #include <linux/crc32.h>
@@ -362,8 +379,9 @@ int ubifs_write_rcvrd_mst_node(struct ubifs_info *c)
  * @offs: offset to check
  *
  * This function returns %1 if @offs was in the last write to the LEB whose data
- * is in @buf, otherwise %0 is returned.  The determination is made by checking
- * for subsequent empty space starting from the next @c->min_io_size boundary.
+ * is in @buf, otherwise %0 is returned. The determination is made by checking
+ * for subsequent empty space starting from the next @c->max_write_size
+ * boundary.
  */
 static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
 {
@@ -371,10 +389,10 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
 	uint8_t *p;
 
 	/*
-	 * Round up to the next @c->min_io_size boundary i.e. @offs is in the
-	 * last wbuf written. After that should be empty space.
+	 * Round up to the next @c->max_write_size boundary i.e. @offs is in
+	 * the last wbuf written. After that should be empty space.
 	 */
-	empty_offs = ALIGN(offs + 1, c->min_io_size);
+	empty_offs = ALIGN(offs + 1, c->max_write_size);
 	check_len = c->leb_size - empty_offs;
 	p = buf + empty_offs - offs;
 	return is_empty(p, check_len);
@@ -429,7 +447,7 @@ static int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
 	int skip, dlen = le32_to_cpu(ch->len);
 
 	/* Check for empty space after the corrupt node's common header */
-	skip = ALIGN(offs + UBIFS_CH_SZ, c->min_io_size) - offs;
+	skip = ALIGN(offs + UBIFS_CH_SZ, c->max_write_size) - offs;
 	if (is_empty(buf + skip, len - skip))
 		return 1;
 	/*
@@ -441,7 +459,7 @@ static int no_more_nodes(const struct ubifs_info *c, void *buf, int len,
 		return 0;
 	}
 	/* Now we know the corrupt node's length we can skip over it */
-	skip = ALIGN(offs + dlen, c->min_io_size) - offs;
+	skip = ALIGN(offs + dlen, c->max_write_size) - offs;
 	/* After which there should be empty space */
 	if (is_empty(buf + skip, len - skip))
 		return 1;
@@ -671,10 +689,14 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 		} else {
 			int corruption = first_non_ff(buf, len);
 
+			/*
+			 * See header comment for this file for more
+			 * explanations about the reasons we have this check.
+			 */
 			ubifs_err("corrupt empty space LEB %d:%d, corruption "
 				  "starts at %d", lnum, offs, corruption);
 			/* Make sure we dump interesting non-0xFF data */
-			offs = corruption;
+			offs += corruption;
 			buf += corruption;
 			goto corrupted;
 		}
@@ -836,12 +858,8 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 static int recover_head(const struct ubifs_info *c, int lnum, int offs,
 			void *sbuf)
 {
-	int len, err;
+	int len = c->max_write_size, err;
 
-	if (c->min_io_size > 1)
-		len = c->min_io_size;
-	else
-		len = 512;
 	if (offs + len > c->leb_size)
 		len = c->leb_size - offs;
 
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 3e1ee57..36216b4 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -328,7 +328,7 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
 		if (!quiet)
 			ubifs_err("empty space starts at non-aligned offset %d",
 				  offs);
-		goto corrupted;;
+		goto corrupted;
 	}
 
 	ubifs_end_scan(c, sleb, lnum, offs);
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 6e11c29..e5dc1e1 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -512,9 +512,12 @@ static int init_constants_early(struct ubifs_info *c)
 
 	c->leb_cnt = c->vi.size;
 	c->leb_size = c->vi.usable_leb_size;
+	c->leb_start = c->di.leb_start;
 	c->half_leb_size = c->leb_size / 2;
 	c->min_io_size = c->di.min_io_size;
 	c->min_io_shift = fls(c->min_io_size) - 1;
+	c->max_write_size = c->di.max_write_size;
+	c->max_write_shift = fls(c->max_write_size) - 1;
 
 	if (c->leb_size < UBIFS_MIN_LEB_SZ) {
 		ubifs_err("too small LEBs (%d bytes), min. is %d bytes",
@@ -534,6 +537,18 @@ static int init_constants_early(struct ubifs_info *c)
 	}
 
 	/*
+	 * Maximum write size has to be greater or equivalent to min. I/O
+	 * size, and be multiple of min. I/O size.
+	 */
+	if (c->max_write_size < c->min_io_size ||
+	    c->max_write_size % c->min_io_size ||
+	    !is_power_of_2(c->max_write_size)) {
+		ubifs_err("bad write buffer size %d for %d min. I/O unit",
+			  c->max_write_size, c->min_io_size);
+		return -EINVAL;
+	}
+
+	/*
 	 * UBIFS aligns all node to 8-byte boundary, so to make function in
 	 * io.c simpler, assume minimum I/O unit size to be 8 bytes if it is
 	 * less than 8.
@@ -541,6 +556,10 @@ static int init_constants_early(struct ubifs_info *c)
 	if (c->min_io_size < 8) {
 		c->min_io_size = 8;
 		c->min_io_shift = 3;
+		if (c->max_write_size < c->min_io_size) {
+			c->max_write_size = c->min_io_size;
+			c->max_write_shift = c->min_io_shift;
+		}
 	}
 
 	c->ref_node_alsz = ALIGN(UBIFS_REF_NODE_SZ, c->min_io_size);
@@ -1202,11 +1221,14 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (c->bulk_read == 1)
 		bu_init(c);
 
-	/*
-	 * We have to check all CRCs, even for data nodes, when we mount the FS
-	 * (specifically, when we are replaying).
-	 */
-	c->always_chk_crc = 1;
+	if (!c->ro_mount) {
+		c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ,
+					       GFP_KERNEL);
+		if (!c->write_reserve_buf)
+			goto out_free;
+	}
+
+	c->mounting = 1;
 
 	err = ubifs_read_superblock(c);
 	if (err)
@@ -1382,7 +1404,7 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		goto out_infos;
 
-	c->always_chk_crc = 0;
+	c->mounting = 0;
 
 	ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
 		  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
@@ -1403,6 +1425,7 @@ static int mount_ubifs(struct ubifs_info *c)
 
 	dbg_msg("compiled on:         " __DATE__ " at " __TIME__);
 	dbg_msg("min. I/O unit size:  %d bytes", c->min_io_size);
+	dbg_msg("max. write size:     %d bytes", c->max_write_size);
 	dbg_msg("LEB size:            %d bytes (%d KiB)",
 		c->leb_size, c->leb_size >> 10);
 	dbg_msg("data journal heads:  %d",
@@ -1432,9 +1455,9 @@ static int mount_ubifs(struct ubifs_info *c)
 		UBIFS_TRUN_NODE_SZ, UBIFS_SB_NODE_SZ, UBIFS_MST_NODE_SZ);
 	dbg_msg("node sizes:          ref %zu, cmt. start %zu, orph %zu",
 		UBIFS_REF_NODE_SZ, UBIFS_CS_NODE_SZ, UBIFS_ORPH_NODE_SZ);
-	dbg_msg("max. node sizes:     data %zu, inode %zu dentry %zu",
+	dbg_msg("max. node sizes:     data %zu, inode %zu dentry %zu, idx %d",
 	        UBIFS_MAX_DATA_NODE_SZ, UBIFS_MAX_INO_NODE_SZ,
-		UBIFS_MAX_DENT_NODE_SZ);
+		UBIFS_MAX_DENT_NODE_SZ, ubifs_idx_node_sz(c, c->fanout));
 	dbg_msg("dead watermark:      %d", c->dead_wm);
 	dbg_msg("dark watermark:      %d", c->dark_wm);
 	dbg_msg("LEB overhead:        %d", c->leb_overhead);
@@ -1474,6 +1497,7 @@ out_wbufs:
 out_cbuf:
 	kfree(c->cbuf);
 out_free:
+	kfree(c->write_reserve_buf);
 	kfree(c->bu.buf);
 	vfree(c->ileb_buf);
 	vfree(c->sbuf);
@@ -1512,6 +1536,7 @@ static void ubifs_umount(struct ubifs_info *c)
 	kfree(c->cbuf);
 	kfree(c->rcvrd_mst_node);
 	kfree(c->mst_node);
+	kfree(c->write_reserve_buf);
 	kfree(c->bu.buf);
 	vfree(c->ileb_buf);
 	vfree(c->sbuf);
@@ -1543,7 +1568,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 	mutex_lock(&c->umount_mutex);
 	dbg_save_space_info(c);
 	c->remounting_rw = 1;
-	c->always_chk_crc = 1;
 
 	err = check_free_space(c);
 	if (err)
@@ -1598,6 +1622,10 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 		goto out;
 	}
 
+	c->write_reserve_buf = kmalloc(COMPRESSED_DATA_NODE_BUF_SZ, GFP_KERNEL);
+	if (!c->write_reserve_buf)
+		goto out;
+
 	err = ubifs_lpt_init(c, 0, 1);
 	if (err)
 		goto out;
@@ -1650,7 +1678,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 	dbg_gen("re-mounted read-write");
 	c->ro_mount = 0;
 	c->remounting_rw = 0;
-	c->always_chk_crc = 0;
 	err = dbg_check_space_info(c);
 	mutex_unlock(&c->umount_mutex);
 	return err;
@@ -1663,11 +1690,12 @@ out:
 		c->bgt = NULL;
 	}
 	free_wbufs(c);
+	kfree(c->write_reserve_buf);
+	c->write_reserve_buf = NULL;
 	vfree(c->ileb_buf);
 	c->ileb_buf = NULL;
 	ubifs_lpt_free(c, 1);
 	c->remounting_rw = 0;
-	c->always_chk_crc = 0;
 	mutex_unlock(&c->umount_mutex);
 	return err;
 }
@@ -1707,6 +1735,8 @@ static void ubifs_remount_ro(struct ubifs_info *c)
 	free_wbufs(c);
 	vfree(c->orph_buf);
 	c->orph_buf = NULL;
+	kfree(c->write_reserve_buf);
+	c->write_reserve_buf = NULL;
 	vfree(c->ileb_buf);
 	c->ileb_buf = NULL;
 	ubifs_lpt_free(c, 1);
@@ -1937,6 +1967,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 	mutex_init(&c->mst_mutex);
 	mutex_init(&c->umount_mutex);
 	mutex_init(&c->bu_mutex);
+	mutex_init(&c->write_reserve_mutex);
 	init_waitqueue_head(&c->cmt_wq);
 	c->buds = RB_ROOT;
 	c->old_idx = RB_ROOT;
@@ -1954,6 +1985,7 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
 	INIT_LIST_HEAD(&c->old_buds);
 	INIT_LIST_HEAD(&c->orph_list);
 	INIT_LIST_HEAD(&c->orph_new);
+	c->no_chk_data_crc = 1;
 
 	c->vfs_sb = sb;
 	c->highest_inum = UBIFS_FIRST_INO;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index ad9cf01..de48597 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -447,8 +447,11 @@ static int tnc_read_node_nm(struct ubifs_info *c, struct ubifs_zbranch *zbr,
  *
  * Note, this function does not check CRC of data nodes if @c->no_chk_data_crc
  * is true (it is controlled by corresponding mount option). However, if
- * @c->always_chk_crc is true, @c->no_chk_data_crc is ignored and CRC is always
- * checked.
+ * @c->mounting or @c->remounting_rw is true (we are mounting or re-mounting to
+ * R/W mode), @c->no_chk_data_crc is ignored and CRC is checked. This is
+ * because during mounting or re-mounting from R/O mode to R/W mode we may read
+ * journal nodes (when replying the journal or doing the recovery) and the
+ * journal nodes may potentially be corrupted, so checking is required.
  */
 static int try_read_node(const struct ubifs_info *c, void *buf, int type,
 			 int len, int lnum, int offs)
@@ -476,7 +479,8 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
 	if (node_len != len)
 		return 0;
 
-	if (type == UBIFS_DATA_NODE && !c->always_chk_crc && c->no_chk_data_crc)
+	if (type == UBIFS_DATA_NODE && c->no_chk_data_crc && !c->mounting &&
+	    !c->remounting_rw)
 		return 1;
 
 	crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 381d6b2..8c40ad3 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -151,6 +151,12 @@
  */
 #define WORST_COMPR_FACTOR 2
 
+/*
+ * How much memory is needed for a buffer where we comress a data node.
+ */
+#define COMPRESSED_DATA_NODE_BUF_SZ \
+	(UBIFS_DATA_NODE_SZ + UBIFS_BLOCK_SIZE * WORST_COMPR_FACTOR)
+
 /* Maximum expected tree height for use by bottom_up_buf */
 #define BOTTOM_UP_HEIGHT 64
 
@@ -646,6 +652,7 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
  * @offs: write-buffer offset in this logical eraseblock
  * @avail: number of bytes available in the write-buffer
  * @used:  number of used bytes in the write-buffer
+ * @size: write-buffer size (in [@c->min_io_size, @c->max_write_size] range)
  * @dtype: type of data stored in this LEB (%UBI_LONGTERM, %UBI_SHORTTERM,
  * %UBI_UNKNOWN)
  * @jhead: journal head the mutex belongs to (note, needed only to shut lockdep
@@ -680,6 +687,7 @@ struct ubifs_wbuf {
 	int offs;
 	int avail;
 	int used;
+	int size;
 	int dtype;
 	int jhead;
 	int (*sync_callback)(struct ubifs_info *c, int lnum, int free, int pad);
@@ -1003,6 +1011,11 @@ struct ubifs_debug_info;
  * @bu_mutex: protects the pre-allocated bulk-read buffer and @c->bu
  * @bu: pre-allocated bulk-read information
  *
+ * @write_reserve_mutex: protects @write_reserve_buf
+ * @write_reserve_buf: on the write path we allocate memory, which might
+ *                     sometimes be unavailable, in which case we use this
+ *                     write reserve buffer
+ *
  * @log_lebs: number of logical eraseblocks in the log
  * @log_bytes: log size in bytes
  * @log_last: last LEB of the log
@@ -1024,7 +1037,12 @@ struct ubifs_debug_info;
  *
  * @min_io_size: minimal input/output unit size
  * @min_io_shift: number of bits in @min_io_size minus one
+ * @max_write_size: maximum amount of bytes the underlying flash can write at a
+ *                  time (MTD write buffer size)
+ * @max_write_shift: number of bits in @max_write_size minus one
  * @leb_size: logical eraseblock size in bytes
+ * @leb_start: starting offset of logical eraseblocks within physical
+ *             eraseblocks
  * @half_leb_size: half LEB size
  * @idx_leb_size: how many bytes of an LEB are effectively available when it is
  *                used to store indexing nodes (@leb_size - @max_idx_node_sz)
@@ -1166,22 +1184,21 @@ struct ubifs_debug_info;
  * @rp_uid: reserved pool user ID
  * @rp_gid: reserved pool group ID
  *
- * @empty: if the UBI device is empty
+ * @empty: %1 if the UBI device is empty
+ * @need_recovery: %1 if the file-system needs recovery
+ * @replaying: %1 during journal replay
+ * @mounting: %1 while mounting
+ * @remounting_rw: %1 while re-mounting from R/O mode to R/W mode
  * @replay_tree: temporary tree used during journal replay
  * @replay_list: temporary list used during journal replay
  * @replay_buds: list of buds to replay
  * @cs_sqnum: sequence number of first node in the log (commit start node)
  * @replay_sqnum: sequence number of node currently being replayed
- * @need_recovery: file-system needs recovery
- * @replaying: set to %1 during journal replay
  * @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W
  *                    mode
  * @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted
  *                  FS to R/W mode
  * @size_tree: inode size information for recovery
- * @remounting_rw: set while re-mounting from R/O mode to R/W mode
- * @always_chk_crc: always check CRCs (while mounting and remounting to R/W
- *                  mode)
  * @mount_opts: UBIFS-specific mount options
  *
  * @dbg: debugging-related information
@@ -1250,6 +1267,9 @@ struct ubifs_info {
 	struct mutex bu_mutex;
 	struct bu_info bu;
 
+	struct mutex write_reserve_mutex;
+	void *write_reserve_buf;
+
 	int log_lebs;
 	long long log_bytes;
 	int log_last;
@@ -1271,7 +1291,10 @@ struct ubifs_info {
 
 	int min_io_size;
 	int min_io_shift;
+	int max_write_size;
+	int max_write_shift;
 	int leb_size;
+	int leb_start;
 	int half_leb_size;
 	int idx_leb_size;
 	int leb_cnt;
@@ -1402,19 +1425,19 @@ struct ubifs_info {
 	gid_t rp_gid;
 
 	/* The below fields are used only during mounting and re-mounting */
-	int empty;
+	unsigned int empty:1;
+	unsigned int need_recovery:1;
+	unsigned int replaying:1;
+	unsigned int mounting:1;
+	unsigned int remounting_rw:1;
 	struct rb_root replay_tree;
 	struct list_head replay_list;
 	struct list_head replay_buds;
 	unsigned long long cs_sqnum;
 	unsigned long long replay_sqnum;
-	int need_recovery;
-	int replaying;
 	struct list_head unclean_leb_list;
 	struct ubifs_mst_node *rcvrd_mst_node;
 	struct rb_root size_tree;
-	int remounting_rw;
-	int always_chk_crc;
 	struct ubifs_mount_opts mount_opts;
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 306ee39..8994dd0 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -31,7 +31,7 @@
 #define udf_set_bit(nr, addr) ext2_set_bit(nr, addr)
 #define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
 #define udf_find_next_one_bit(addr, size, offset) \
-		ext2_find_next_bit(addr, size, offset)
+		ext2_find_next_bit((unsigned long *)(addr), size, offset)
 
 static int read_block_bitmap(struct super_block *sb,
 			     struct udf_bitmap *bitmap, unsigned int block,
@@ -297,7 +297,7 @@ repeat:
 				break;
 			}
 		} else {
-			bit = udf_find_next_one_bit((char *)bh->b_data,
+			bit = udf_find_next_one_bit(bh->b_data,
 						    sb->s_blocksize << 3,
 						    group_start << 3);
 			if (bit < sb->s_blocksize << 3)
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 89c7848..f391a2a 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -123,8 +123,8 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 		if (inode->i_sb->s_blocksize <
 				(udf_file_entry_alloc_offset(inode) +
 						pos + count)) {
-			udf_expand_file_adinicb(inode, pos + count, &err);
-			if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+			err = udf_expand_file_adinicb(inode);
+			if (err) {
 				udf_debug("udf_expand_adinicb: err=%d\n", err);
 				up_write(&iinfo->i_data_sem);
 				return err;
@@ -237,7 +237,7 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
 
 	if ((attr->ia_valid & ATTR_SIZE) &&
 	    attr->ia_size != i_size_read(inode)) {
-		error = vmtruncate(inode, attr->ia_size);
+		error = udf_setsize(inode, attr->ia_size);
 		if (error)
 			return error;
 	}
@@ -249,5 +249,4 @@ static int udf_setattr(struct dentry *dentry, struct iattr *attr)
 
 const struct inode_operations udf_file_inode_operations = {
 	.setattr		= udf_setattr,
-	.truncate		= udf_truncate,
 };
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c6a2e78..ccc8143 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -73,14 +73,12 @@ void udf_evict_inode(struct inode *inode)
 	struct udf_inode_info *iinfo = UDF_I(inode);
 	int want_delete = 0;
 
-	truncate_inode_pages(&inode->i_data, 0);
-
 	if (!inode->i_nlink && !is_bad_inode(inode)) {
 		want_delete = 1;
-		inode->i_size = 0;
-		udf_truncate(inode);
+		udf_setsize(inode, 0);
 		udf_update_inode(inode, IS_SYNC(inode));
-	}
+	} else
+		truncate_inode_pages(&inode->i_data, 0);
 	invalidate_inode_buffers(inode);
 	end_writeback(inode);
 	if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB &&
@@ -117,9 +115,18 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
 
 	ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block);
 	if (unlikely(ret)) {
-		loff_t isize = mapping->host->i_size;
-		if (pos + len > isize)
-			vmtruncate(mapping->host, isize);
+		struct inode *inode = mapping->host;
+		struct udf_inode_info *iinfo = UDF_I(inode);
+		loff_t isize = inode->i_size;
+
+		if (pos + len > isize) {
+			truncate_pagecache(inode, pos + len, isize);
+			if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
+				down_write(&iinfo->i_data_sem);
+				udf_truncate_extents(inode);
+				up_write(&iinfo->i_data_sem);
+			}
+		}
 	}
 
 	return ret;
@@ -139,30 +146,31 @@ const struct address_space_operations udf_aops = {
 	.bmap		= udf_bmap,
 };
 
-void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)
+int udf_expand_file_adinicb(struct inode *inode)
 {
 	struct page *page;
 	char *kaddr;
 	struct udf_inode_info *iinfo = UDF_I(inode);
+	int err;
 	struct writeback_control udf_wbc = {
 		.sync_mode = WB_SYNC_NONE,
 		.nr_to_write = 1,
 	};
 
-	/* from now on we have normal address_space methods */
-	inode->i_data.a_ops = &udf_aops;
-
 	if (!iinfo->i_lenAlloc) {
 		if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
 			iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
 		else
 			iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
+		/* from now on we have normal address_space methods */
+		inode->i_data.a_ops = &udf_aops;
 		mark_inode_dirty(inode);
-		return;
+		return 0;
 	}
 
-	page = grab_cache_page(inode->i_mapping, 0);
-	BUG_ON(!PageLocked(page));
+	page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
+	if (!page)
+		return -ENOMEM;
 
 	if (!PageUptodate(page)) {
 		kaddr = kmap(page);
@@ -181,11 +189,24 @@ void udf_expand_file_adinicb(struct inode *inode, int newsize, int *err)
 		iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
 	else
 		iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
-
-	inode->i_data.a_ops->writepage(page, &udf_wbc);
+	/* from now on we have normal address_space methods */
+	inode->i_data.a_ops = &udf_aops;
+	err = inode->i_data.a_ops->writepage(page, &udf_wbc);
+	if (err) {
+		/* Restore everything back so that we don't lose data... */
+		lock_page(page);
+		kaddr = kmap(page);
+		memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr,
+		       inode->i_size);
+		kunmap(page);
+		unlock_page(page);
+		iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
+		inode->i_data.a_ops = &udf_adinicb_aops;
+	}
 	page_cache_release(page);
-
 	mark_inode_dirty(inode);
+
+	return err;
 }
 
 struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block,
@@ -348,8 +369,10 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block,
 }
 
 /* Extend the file by 'blocks' blocks, return the number of extents added */
-int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
-		    struct kernel_long_ad *last_ext, sector_t blocks)
+static int udf_do_extend_file(struct inode *inode,
+			      struct extent_position *last_pos,
+			      struct kernel_long_ad *last_ext,
+			      sector_t blocks)
 {
 	sector_t add;
 	int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK);
@@ -357,6 +380,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
 	struct kernel_lb_addr prealloc_loc = {};
 	int prealloc_len = 0;
 	struct udf_inode_info *iinfo;
+	int err;
 
 	/* The previous extent is fake and we should not extend by anything
 	 * - there's nothing to do... */
@@ -422,26 +446,29 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos,
 	/* Create enough extents to cover the whole hole */
 	while (blocks > add) {
 		blocks -= add;
-		if (udf_add_aext(inode, last_pos, &last_ext->extLocation,
-				 last_ext->extLength, 1) == -1)
-			return -1;
+		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
+				   last_ext->extLength, 1);
+		if (err)
+			return err;
 		count++;
 	}
 	if (blocks) {
 		last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED |
 			(blocks << sb->s_blocksize_bits);
-		if (udf_add_aext(inode, last_pos, &last_ext->extLocation,
-				 last_ext->extLength, 1) == -1)
-			return -1;
+		err = udf_add_aext(inode, last_pos, &last_ext->extLocation,
+				   last_ext->extLength, 1);
+		if (err)
+			return err;
 		count++;
 	}
 
 out:
 	/* Do we have some preallocated blocks saved? */
 	if (prealloc_len) {
-		if (udf_add_aext(inode, last_pos, &prealloc_loc,
-				 prealloc_len, 1) == -1)
-			return -1;
+		err = udf_add_aext(inode, last_pos, &prealloc_loc,
+				   prealloc_len, 1);
+		if (err)
+			return err;
 		last_ext->extLocation = prealloc_loc;
 		last_ext->extLength = prealloc_len;
 		count++;
@@ -453,11 +480,68 @@ out:
 	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 		last_pos->offset -= sizeof(struct long_ad);
 	else
-		return -1;
+		return -EIO;
 
 	return count;
 }
 
+static int udf_extend_file(struct inode *inode, loff_t newsize)
+{
+
+	struct extent_position epos;
+	struct kernel_lb_addr eloc;
+	uint32_t elen;
+	int8_t etype;
+	struct super_block *sb = inode->i_sb;
+	sector_t first_block = newsize >> sb->s_blocksize_bits, offset;
+	int adsize;
+	struct udf_inode_info *iinfo = UDF_I(inode);
+	struct kernel_long_ad extent;
+	int err;
+
+	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
+		adsize = sizeof(struct short_ad);
+	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
+		adsize = sizeof(struct long_ad);
+	else
+		BUG();
+
+	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
+
+	/* File has extent covering the new size (could happen when extending
+	 * inside a block)? */
+	if (etype != -1)
+		return 0;
+	if (newsize & (sb->s_blocksize - 1))
+		offset++;
+	/* Extended file just to the boundary of the last file block? */
+	if (offset == 0)
+		return 0;
+
+	/* Truncate is extending the file by 'offset' blocks */
+	if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) ||
+	    (epos.bh && epos.offset == sizeof(struct allocExtDesc))) {
+		/* File has no extents at all or has empty last
+		 * indirect extent! Create a fake extent... */
+		extent.extLocation.logicalBlockNum = 0;
+		extent.extLocation.partitionReferenceNum = 0;
+		extent.extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
+	} else {
+		epos.offset -= adsize;
+		etype = udf_next_aext(inode, &epos, &extent.extLocation,
+				      &extent.extLength, 0);
+		extent.extLength |= etype << 30;
+	}
+	err = udf_do_extend_file(inode, &epos, &extent, offset);
+	if (err < 0)
+		goto out;
+	err = 0;
+	iinfo->i_lenExtents = newsize;
+out:
+	brelse(epos.bh);
+	return err;
+}
+
 static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
 					int *err, sector_t *phys, int *new)
 {
@@ -540,7 +624,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
 			elen = EXT_RECORDED_ALLOCATED |
 				((elen + inode->i_sb->s_blocksize - 1) &
 				 ~(inode->i_sb->s_blocksize - 1));
-			etype = udf_write_aext(inode, &cur_epos, &eloc, elen, 1);
+			udf_write_aext(inode, &cur_epos, &eloc, elen, 1);
 		}
 		brelse(prev_epos.bh);
 		brelse(cur_epos.bh);
@@ -564,19 +648,17 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block,
 			memset(&laarr[0].extLocation, 0x00,
 				sizeof(struct kernel_lb_addr));
 			laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED;
-			/* Will udf_extend_file() create real extent from
+			/* Will udf_do_extend_file() create real extent from
 			   a fake one? */
 			startnum = (offset > 0);
 		}
 		/* Create extents for the hole between EOF and offset */
-		ret = udf_extend_file(inode, &prev_epos, laarr, offset);
-		if (ret == -1) {
+		ret = udf_do_extend_file(inode, &prev_epos, laarr, offset);
+		if (ret < 0) {
 			brelse(prev_epos.bh);
 			brelse(cur_epos.bh);
 			brelse(next_epos.bh);
-			/* We don't really know the error here so we just make
-			 * something up */
-			*err = -ENOSPC;
+			*err = ret;
 			return NULL;
 		}
 		c = 0;
@@ -1005,52 +1087,66 @@ struct buffer_head *udf_bread(struct inode *inode, int block,
 	return NULL;
 }
 
-void udf_truncate(struct inode *inode)
+int udf_setsize(struct inode *inode, loff_t newsize)
 {
-	int offset;
 	int err;
 	struct udf_inode_info *iinfo;
+	int bsize = 1 << inode->i_blkbits;
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	      S_ISLNK(inode->i_mode)))
-		return;
+		return -EINVAL;
 	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		return;
+		return -EPERM;
 
 	iinfo = UDF_I(inode);
-	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+	if (newsize > inode->i_size) {
 		down_write(&iinfo->i_data_sem);
-		if (inode->i_sb->s_blocksize <
-				(udf_file_entry_alloc_offset(inode) +
-				 inode->i_size)) {
-			udf_expand_file_adinicb(inode, inode->i_size, &err);
-			if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
-				inode->i_size = iinfo->i_lenAlloc;
-				up_write(&iinfo->i_data_sem);
-				return;
+		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+			if (bsize <
+			    (udf_file_entry_alloc_offset(inode) + newsize)) {
+				err = udf_expand_file_adinicb(inode);
+				if (err) {
+					up_write(&iinfo->i_data_sem);
+					return err;
+				}
 			} else
-				udf_truncate_extents(inode);
-		} else {
-			offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
-			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + offset,
-				0x00, inode->i_sb->s_blocksize -
-				offset - udf_file_entry_alloc_offset(inode));
-			iinfo->i_lenAlloc = inode->i_size;
+				iinfo->i_lenAlloc = newsize;
+		}
+		err = udf_extend_file(inode, newsize);
+		if (err) {
+			up_write(&iinfo->i_data_sem);
+			return err;
 		}
+		truncate_setsize(inode, newsize);
 		up_write(&iinfo->i_data_sem);
 	} else {
-		block_truncate_page(inode->i_mapping, inode->i_size,
-				    udf_get_block);
+		if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
+			down_write(&iinfo->i_data_sem);
+			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize,
+			       0x00, bsize - newsize -
+			       udf_file_entry_alloc_offset(inode));
+			iinfo->i_lenAlloc = newsize;
+			truncate_setsize(inode, newsize);
+			up_write(&iinfo->i_data_sem);
+			goto update_time;
+		}
+		err = block_truncate_page(inode->i_mapping, newsize,
+					  udf_get_block);
+		if (err)
+			return err;
 		down_write(&iinfo->i_data_sem);
+		truncate_setsize(inode, newsize);
 		udf_truncate_extents(inode);
 		up_write(&iinfo->i_data_sem);
 	}
-
+update_time:
 	inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb);
 	if (IS_SYNC(inode))
 		udf_sync_inode(inode);
 	else
 		mark_inode_dirty(inode);
+	return 0;
 }
 
 static void __udf_read_inode(struct inode *inode)
@@ -1637,14 +1733,13 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
 	return NULL;
 }
 
-int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
-		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)
+int udf_add_aext(struct inode *inode, struct extent_position *epos,
+		 struct kernel_lb_addr *eloc, uint32_t elen, int inc)
 {
 	int adsize;
 	struct short_ad *sad = NULL;
 	struct long_ad *lad = NULL;
 	struct allocExtDesc *aed;
-	int8_t etype;
 	uint8_t *ptr;
 	struct udf_inode_info *iinfo = UDF_I(inode);
 
@@ -1660,7 +1755,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
 	else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG)
 		adsize = sizeof(struct long_ad);
 	else
-		return -1;
+		return -EIO;
 
 	if (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {
 		unsigned char *sptr, *dptr;
@@ -1672,12 +1767,12 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
 						obloc.partitionReferenceNum,
 						obloc.logicalBlockNum, &err);
 		if (!epos->block.logicalBlockNum)
-			return -1;
+			return -ENOSPC;
 		nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,
 								 &epos->block,
 								 0));
 		if (!nbh)
-			return -1;
+			return -EIO;
 		lock_buffer(nbh);
 		memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);
 		set_buffer_uptodate(nbh);
@@ -1746,7 +1841,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
 		epos->bh = nbh;
 	}
 
-	etype = udf_write_aext(inode, epos, eloc, elen, inc);
+	udf_write_aext(inode, epos, eloc, elen, inc);
 
 	if (!epos->bh) {
 		iinfo->i_lenAlloc += adsize;
@@ -1764,11 +1859,11 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos,
 		mark_buffer_dirty_inode(epos->bh, inode);
 	}
 
-	return etype;
+	return 0;
 }
 
-int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
-		      struct kernel_lb_addr *eloc, uint32_t elen, int inc)
+void udf_write_aext(struct inode *inode, struct extent_position *epos,
+		    struct kernel_lb_addr *eloc, uint32_t elen, int inc)
 {
 	int adsize;
 	uint8_t *ptr;
@@ -1798,7 +1893,7 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
 		adsize = sizeof(struct long_ad);
 		break;
 	default:
-		return -1;
+		return;
 	}
 
 	if (epos->bh) {
@@ -1817,8 +1912,6 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
 
 	if (inc)
 		epos->offset += adsize;
-
-	return (elen >> 30);
 }
 
 int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index b7c338d..f1dce84 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -1286,8 +1286,13 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp,
 	struct fid *fid = (struct fid *)fh;
 	int type = FILEID_UDF_WITHOUT_PARENT;
 
-	if (len < 3 || (connectable && len < 5))
+	if (connectable && (len < 5)) {
+		*lenp = 5;
+		return 255;
+	} else if (len < 3) {
+		*lenp = 3;
 		return 255;
+	}
 
 	*lenp = 3;
 	fid->udf.block = location.logicalBlockNum;
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 225527c..8424308 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -197,6 +197,11 @@ static void udf_update_alloc_ext_desc(struct inode *inode,
 	mark_buffer_dirty_inode(epos->bh, inode);
 }
 
+/*
+ * Truncate extents of inode to inode->i_size. This function can be used only
+ * for making file shorter. For making file longer, udf_extend_file() has to
+ * be used.
+ */
 void udf_truncate_extents(struct inode *inode)
 {
 	struct extent_position epos;
@@ -219,96 +224,65 @@ void udf_truncate_extents(struct inode *inode)
 	etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset);
 	byte_offset = (offset << sb->s_blocksize_bits) +
 		(inode->i_size & (sb->s_blocksize - 1));
-	if (etype != -1) {
-		epos.offset -= adsize;
-		extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset);
-		epos.offset += adsize;
-		if (byte_offset)
-			lenalloc = epos.offset;
-		else
-			lenalloc = epos.offset - adsize;
-
-		if (!epos.bh)
-			lenalloc -= udf_file_entry_alloc_offset(inode);
-		else
-			lenalloc -= sizeof(struct allocExtDesc);
-
-		while ((etype = udf_current_aext(inode, &epos, &eloc,
-						 &elen, 0)) != -1) {
-			if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
-				udf_write_aext(inode, &epos, &neloc, nelen, 0);
-				if (indirect_ext_len) {
-					/* We managed to free all extents in the
-					 * indirect extent - free it too */
-					BUG_ON(!epos.bh);
-					udf_free_blocks(sb, inode, &epos.block,
-							0, indirect_ext_len);
-				} else if (!epos.bh) {
-					iinfo->i_lenAlloc = lenalloc;
-					mark_inode_dirty(inode);
-				} else
-					udf_update_alloc_ext_desc(inode,
-							&epos, lenalloc);
-				brelse(epos.bh);
-				epos.offset = sizeof(struct allocExtDesc);
-				epos.block = eloc;
-				epos.bh = udf_tread(sb,
-						udf_get_lb_pblock(sb, &eloc, 0));
-				if (elen)
-					indirect_ext_len =
-						(elen + sb->s_blocksize - 1) >>
-						sb->s_blocksize_bits;
-				else
-					indirect_ext_len = 1;
-			} else {
-				extent_trunc(inode, &epos, &eloc, etype,
-					     elen, 0);
-				epos.offset += adsize;
-			}
-		}
+	if (etype == -1) {
+		/* We should extend the file? */
+		WARN_ON(byte_offset);
+		return;
+	}
+	epos.offset -= adsize;
+	extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset);
+	epos.offset += adsize;
+	if (byte_offset)
+		lenalloc = epos.offset;
+	else
+		lenalloc = epos.offset - adsize;
 
-		if (indirect_ext_len) {
-			BUG_ON(!epos.bh);
-			udf_free_blocks(sb, inode, &epos.block, 0,
-					indirect_ext_len);
-		} else if (!epos.bh) {
-			iinfo->i_lenAlloc = lenalloc;
-			mark_inode_dirty(inode);
-		} else
-			udf_update_alloc_ext_desc(inode, &epos, lenalloc);
-	} else if (inode->i_size) {
-		if (byte_offset) {
-			struct kernel_long_ad extent;
+	if (!epos.bh)
+		lenalloc -= udf_file_entry_alloc_offset(inode);
+	else
+		lenalloc -= sizeof(struct allocExtDesc);
 
-			/*
-			 *  OK, there is not extent covering inode->i_size and
-			 *  no extent above inode->i_size => truncate is
-			 *  extending the file by 'offset' blocks.
-			 */
-			if ((!epos.bh &&
-			     epos.offset ==
-					udf_file_entry_alloc_offset(inode)) ||
-			    (epos.bh && epos.offset ==
-						sizeof(struct allocExtDesc))) {
-				/* File has no extents at all or has empty last
-				 * indirect extent! Create a fake extent... */
-				extent.extLocation.logicalBlockNum = 0;
-				extent.extLocation.partitionReferenceNum = 0;
-				extent.extLength =
-					EXT_NOT_RECORDED_NOT_ALLOCATED;
-			} else {
-				epos.offset -= adsize;
-				etype = udf_next_aext(inode, &epos,
-						      &extent.extLocation,
-						      &extent.extLength, 0);
-				extent.extLength |= etype << 30;
-			}
-			udf_extend_file(inode, &epos, &extent,
-					offset +
-					((inode->i_size &
-						(sb->s_blocksize - 1)) != 0));
+	while ((etype = udf_current_aext(inode, &epos, &eloc,
+					 &elen, 0)) != -1) {
+		if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
+			udf_write_aext(inode, &epos, &neloc, nelen, 0);
+			if (indirect_ext_len) {
+				/* We managed to free all extents in the
+				 * indirect extent - free it too */
+				BUG_ON(!epos.bh);
+				udf_free_blocks(sb, inode, &epos.block,
+						0, indirect_ext_len);
+			} else if (!epos.bh) {
+				iinfo->i_lenAlloc = lenalloc;
+				mark_inode_dirty(inode);
+			} else
+				udf_update_alloc_ext_desc(inode,
+						&epos, lenalloc);
+			brelse(epos.bh);
+			epos.offset = sizeof(struct allocExtDesc);
+			epos.block = eloc;
+			epos.bh = udf_tread(sb,
+					udf_get_lb_pblock(sb, &eloc, 0));
+			if (elen)
+				indirect_ext_len =
+					(elen + sb->s_blocksize - 1) >>
+					sb->s_blocksize_bits;
+			else
+				indirect_ext_len = 1;
+		} else {
+			extent_trunc(inode, &epos, &eloc, etype, elen, 0);
+			epos.offset += adsize;
 		}
 	}
+
+	if (indirect_ext_len) {
+		BUG_ON(!epos.bh);
+		udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len);
+	} else if (!epos.bh) {
+		iinfo->i_lenAlloc = lenalloc;
+		mark_inode_dirty(inode);
+	} else
+		udf_update_alloc_ext_desc(inode, &epos, lenalloc);
 	iinfo->i_lenExtents = inode->i_size;
 
 	brelse(epos.bh);
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index eba4820..dbd52d4 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -136,22 +136,20 @@ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
 extern long udf_ioctl(struct file *, unsigned int, unsigned long);
 /* inode.c */
 extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *);
-extern void udf_expand_file_adinicb(struct inode *, int, int *);
+extern int udf_expand_file_adinicb(struct inode *);
 extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
 extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
-extern void udf_truncate(struct inode *);
+extern int udf_setsize(struct inode *, loff_t);
 extern void udf_read_inode(struct inode *);
 extern void udf_evict_inode(struct inode *);
 extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
 extern long udf_block_map(struct inode *, sector_t);
-extern int udf_extend_file(struct inode *, struct extent_position *,
-			   struct kernel_long_ad *, sector_t);
 extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *,
 			 struct kernel_lb_addr *, uint32_t *, sector_t *);
-extern int8_t udf_add_aext(struct inode *, struct extent_position *,
+extern int udf_add_aext(struct inode *, struct extent_position *,
+			struct kernel_lb_addr *, uint32_t, int);
+extern void udf_write_aext(struct inode *, struct extent_position *,
 			   struct kernel_lb_addr *, uint32_t, int);
-extern int8_t udf_write_aext(struct inode *, struct extent_position *,
-			     struct kernel_lb_addr *, uint32_t, int);
 extern int8_t udf_delete_aext(struct inode *, struct extent_position,
 			      struct kernel_lb_addr, uint32_t);
 extern int8_t udf_next_aext(struct inode *, struct extent_position *,
diff --git a/fs/ufs/Kconfig b/fs/ufs/Kconfig
index 30c8f22..e4f10a4 100644
--- a/fs/ufs/Kconfig
+++ b/fs/ufs/Kconfig
@@ -1,7 +1,6 @@
 config UFS_FS
 	tristate "UFS file system support (read only)"
 	depends on BLOCK
-	depends on BKL # probably fixable
 	help
 	  BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
 	  OpenBSD and NeXTstep) use a file system called UFS. Some System V
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 2b251f2..03c255f 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -34,7 +34,6 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/writeback.h>
 
@@ -43,7 +42,7 @@
 #include "swab.h"
 #include "util.h"
 
-static u64 ufs_frag_map(struct inode *inode, sector_t frag);
+static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock);
 
 static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4])
 {
@@ -82,7 +81,7 @@ static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t off
  * the begining of the filesystem.
  */
 
-static u64 ufs_frag_map(struct inode *inode, sector_t frag)
+static u64 ufs_frag_map(struct inode *inode, sector_t frag, bool needs_lock)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block *sb = inode->i_sb;
@@ -107,7 +106,8 @@ static u64 ufs_frag_map(struct inode *inode, sector_t frag)
 
 	p = offsets;
 
-	lock_kernel();
+	if (needs_lock)
+		lock_ufs(sb);
 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
 		goto ufs2;
 
@@ -152,7 +152,8 @@ ufs2:
 	ret = temp + (u64) (frag & uspi->s_fpbmask);
 
 out:
-	unlock_kernel();
+	if (needs_lock)
+		unlock_ufs(sb);
 	return ret;
 }
 
@@ -415,14 +416,16 @@ out:
 int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
 {
 	struct super_block * sb = inode->i_sb;
-	struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
+	struct ufs_sb_info * sbi = UFS_SB(sb);
+	struct ufs_sb_private_info * uspi = sbi->s_uspi;
 	struct buffer_head * bh;
 	int ret, err, new;
 	unsigned long ptr,phys;
 	u64 phys64 = 0;
+	bool needs_lock = (sbi->mutex_owner != current);
 	
 	if (!create) {
-		phys64 = ufs_frag_map(inode, fragment);
+		phys64 = ufs_frag_map(inode, fragment, needs_lock);
 		UFSD("phys64 = %llu\n", (unsigned long long)phys64);
 		if (phys64)
 			map_bh(bh_result, sb, phys64);
@@ -436,7 +439,8 @@ int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head
 	ret = 0;
 	bh = NULL;
 
-	lock_kernel();
+	if (needs_lock)
+		lock_ufs(sb);
 
 	UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment);
 	if (fragment >
@@ -498,7 +502,9 @@ out:
 		set_buffer_new(bh_result);
 	map_bh(bh_result, sb, phys);
 abort:
-	unlock_kernel();
+	if (needs_lock)
+		unlock_ufs(sb);
+
 	return err;
 
 abort_too_big:
@@ -506,48 +512,6 @@ abort_too_big:
 	goto abort;
 }
 
-static struct buffer_head *ufs_getfrag(struct inode *inode,
-				       unsigned int fragment,
-				       int create, int *err)
-{
-	struct buffer_head dummy;
-	int error;
-
-	dummy.b_state = 0;
-	dummy.b_blocknr = -1000;
-	error = ufs_getfrag_block(inode, fragment, &dummy, create);
-	*err = error;
-	if (!error && buffer_mapped(&dummy)) {
-		struct buffer_head *bh;
-		bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
-		if (buffer_new(&dummy)) {
-			memset(bh->b_data, 0, inode->i_sb->s_blocksize);
-			set_buffer_uptodate(bh);
-			mark_buffer_dirty(bh);
-		}
-		return bh;
-	}
-	return NULL;
-}
-
-struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
-	int create, int * err)
-{
-	struct buffer_head * bh;
-
-	UFSD("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment);
-	bh = ufs_getfrag (inode, fragment, create, err);
-	if (!bh || buffer_uptodate(bh)) 		
-		return bh;
-	ll_rw_block (READ, 1, &bh);
-	wait_on_buffer (bh);
-	if (buffer_uptodate(bh))
-		return bh;
-	brelse (bh);
-	*err = -EIO;
-	return NULL;
-}
-
 static int ufs_writepage(struct page *page, struct writeback_control *wbc)
 {
 	return block_write_full_page(page,ufs_getfrag_block,wbc);
@@ -900,9 +864,9 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
 int ufs_write_inode(struct inode *inode, struct writeback_control *wbc)
 {
 	int ret;
-	lock_kernel();
+	lock_ufs(inode->i_sb);
 	ret = ufs_update_inode(inode, wbc->sync_mode == WB_SYNC_ALL);
-	unlock_kernel();
+	unlock_ufs(inode->i_sb);
 	return ret;
 }
 
@@ -922,22 +886,22 @@ void ufs_evict_inode(struct inode * inode)
 	if (want_delete) {
 		loff_t old_i_size;
 		/*UFS_I(inode)->i_dtime = CURRENT_TIME;*/
-		lock_kernel();
+		lock_ufs(inode->i_sb);
 		mark_inode_dirty(inode);
 		ufs_update_inode(inode, IS_SYNC(inode));
 		old_i_size = inode->i_size;
 		inode->i_size = 0;
 		if (inode->i_blocks && ufs_truncate(inode, old_i_size))
 			ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n");
-		unlock_kernel();
+		unlock_ufs(inode->i_sb);
 	}
 
 	invalidate_inode_buffers(inode);
 	end_writeback(inode);
 
 	if (want_delete) {
-		lock_kernel();
+		lock_ufs(inode->i_sb);
 		ufs_free_inode (inode);
-		unlock_kernel();
+		unlock_ufs(inode->i_sb);
 	}
 }
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index d6f6815..29309e2 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -29,7 +29,6 @@
 
 #include <linux/time.h>
 #include <linux/fs.h>
-#include <linux/smp_lock.h>
 
 #include "ufs_fs.h"
 #include "ufs.h"
@@ -55,16 +54,16 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
 	if (dentry->d_name.len > UFS_MAXNAMLEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	lock_kernel();
+	lock_ufs(dir->i_sb);
 	ino = ufs_inode_by_name(dir, &dentry->d_name);
 	if (ino) {
 		inode = ufs_iget(dir->i_sb, ino);
 		if (IS_ERR(inode)) {
-			unlock_kernel();
+			unlock_ufs(dir->i_sb);
 			return ERR_CAST(inode);
 		}
 	}
-	unlock_kernel();
+	unlock_ufs(dir->i_sb);
 	d_add(dentry, inode);
 	return NULL;
 }
@@ -93,9 +92,9 @@ static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
 		inode->i_fop = &ufs_file_operations;
 		inode->i_mapping->a_ops = &ufs_aops;
 		mark_inode_dirty(inode);
-		lock_kernel();
+		lock_ufs(dir->i_sb);
 		err = ufs_add_nondir(dentry, inode);
-		unlock_kernel();
+		unlock_ufs(dir->i_sb);
 	}
 	UFSD("END: err=%d\n", err);
 	return err;
@@ -115,9 +114,9 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t
 		init_special_inode(inode, mode, rdev);
 		ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
 		mark_inode_dirty(inode);
-		lock_kernel();
+		lock_ufs(dir->i_sb);
 		err = ufs_add_nondir(dentry, inode);
-		unlock_kernel();
+		unlock_ufs(dir->i_sb);
 	}
 	return err;
 }
@@ -133,7 +132,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
 	if (l > sb->s_blocksize)
 		goto out_notlocked;
 
-	lock_kernel();
+	lock_ufs(dir->i_sb);
 	inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
 	err = PTR_ERR(inode);
 	if (IS_ERR(inode))
@@ -156,7 +155,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
 
 	err = ufs_add_nondir(dentry, inode);
 out:
-	unlock_kernel();
+	unlock_ufs(dir->i_sb);
 out_notlocked:
 	return err;
 
@@ -172,9 +171,9 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
 	struct inode *inode = old_dentry->d_inode;
 	int error;
 
-	lock_kernel();
+	lock_ufs(dir->i_sb);
 	if (inode->i_nlink >= UFS_LINK_MAX) {
-		unlock_kernel();
+		unlock_ufs(dir->i_sb);
 		return -EMLINK;
 	}
 
@@ -183,7 +182,7 @@ static int ufs_link (struct dentry * old_dentry, struct inode * dir,
 	ihold(inode);
 
 	error = ufs_add_nondir(dentry, inode);
-	unlock_kernel();
+	unlock_ufs(dir->i_sb);
 	return error;
 }
 
@@ -195,7 +194,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 	if (dir->i_nlink >= UFS_LINK_MAX)
 		goto out;
 
-	lock_kernel();
+	lock_ufs(dir->i_sb);
 	inode_inc_link_count(dir);
 
 	inode = ufs_new_inode(dir, S_IFDIR|mode);
@@ -216,7 +215,7 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
 	err = ufs_add_link(dentry, inode);
 	if (err)
 		goto out_fail;
-	unlock_kernel();
+	unlock_ufs(dir->i_sb);
 
 	d_instantiate(dentry, inode);
 out:
@@ -228,7 +227,7 @@ out_fail:
 	iput (inode);
 out_dir:
 	inode_dec_link_count(dir);
-	unlock_kernel();
+	unlock_ufs(dir->i_sb);
 	goto out;
 }
 
@@ -259,7 +258,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 	struct inode * inode = dentry->d_inode;
 	int err= -ENOTEMPTY;
 
-	lock_kernel();
+	lock_ufs(dir->i_sb);
 	if (ufs_empty_dir (inode)) {
 		err = ufs_unlink(dir, dentry);
 		if (!err) {
@@ -268,7 +267,7 @@ static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
 			inode_dec_link_count(dir);
 		}
 	}
-	unlock_kernel();
+	unlock_ufs(dir->i_sb);
 	return err;
 }
 
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 2c61ac5..7693d62 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -84,7 +84,6 @@
 #include <linux/blkdev.h>
 #include <linux/init.h>
 #include <linux/parser.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 #include <linux/log2.h>
@@ -96,6 +95,26 @@
 #include "swab.h"
 #include "util.h"
 
+void lock_ufs(struct super_block *sb)
+{
+#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT)
+	struct ufs_sb_info *sbi = UFS_SB(sb);
+
+	mutex_lock(&sbi->mutex);
+	sbi->mutex_owner = current;
+#endif
+}
+
+void unlock_ufs(struct super_block *sb)
+{
+#if defined(CONFIG_SMP) || defined (CONFIG_PREEMPT)
+	struct ufs_sb_info *sbi = UFS_SB(sb);
+
+	sbi->mutex_owner = NULL;
+	mutex_unlock(&sbi->mutex);
+#endif
+}
+
 static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 generation)
 {
 	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
@@ -313,7 +332,6 @@ void ufs_panic (struct super_block * sb, const char * function,
 	struct ufs_super_block_first * usb1;
 	va_list args;
 	
-	lock_kernel();
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 	
@@ -521,7 +539,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
 	 */
 	size = uspi->s_cssize;
 	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
-	base = space = kmalloc(size, GFP_KERNEL);
+	base = space = kmalloc(size, GFP_NOFS);
 	if (!base)
 		goto failed; 
 	sbi->s_csp = (struct ufs_csum *)space;
@@ -546,7 +564,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
 	 * Read cylinder group (we read only first fragment from block
 	 * at this time) and prepare internal data structures for cg caching.
 	 */
-	if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_KERNEL)))
+	if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS)))
 		goto failed;
 	for (i = 0; i < uspi->s_ncg; i++) 
 		sbi->s_ucg[i] = NULL;
@@ -564,7 +582,7 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
 		ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data);
 	}
 	for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
-		if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL)))
+		if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_NOFS)))
 			goto failed;
 		sbi->s_cgno[i] = UFS_CGNO_EMPTY;
 	}
@@ -646,8 +664,6 @@ static void ufs_put_super_internal(struct super_block *sb)
 	
 	UFSD("ENTER\n");
 
-	lock_kernel();
-
 	ufs_put_cstotal(sb);
 	size = uspi->s_cssize;
 	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
@@ -676,8 +692,6 @@ static void ufs_put_super_internal(struct super_block *sb)
 	kfree (sbi->s_ucg);
 	kfree (base);
 
-	unlock_kernel();
-
 	UFSD("EXIT\n");
 }
 
@@ -696,8 +710,6 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 	unsigned maxsymlen;
 	int ret = -EINVAL;
 
-	lock_kernel();
-
 	uspi = NULL;
 	ubh = NULL;
 	flags = 0;
@@ -718,6 +730,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 		goto failed;
 	}
 #endif
+	mutex_init(&sbi->mutex);
 	/*
 	 * Set default mount options
 	 * Parse mount options
@@ -1165,7 +1178,6 @@ magic_found:
 			goto failed;
 
 	UFSD("EXIT\n");
-	unlock_kernel();
 	return 0;
 
 dalloc_failed:
@@ -1177,12 +1189,10 @@ failed:
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 	UFSD("EXIT (FAILED)\n");
-	unlock_kernel();
 	return ret;
 
 failed_nomem:
 	UFSD("EXIT (NOMEM)\n");
-	unlock_kernel();
 	return -ENOMEM;
 }
 
@@ -1193,8 +1203,8 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
 	struct ufs_super_block_third * usb3;
 	unsigned flags;
 
+	lock_ufs(sb);
 	lock_super(sb);
-	lock_kernel();
 
 	UFSD("ENTER\n");
 
@@ -1213,8 +1223,8 @@ static int ufs_sync_fs(struct super_block *sb, int wait)
 	sb->s_dirt = 0;
 
 	UFSD("EXIT\n");
-	unlock_kernel();
 	unlock_super(sb);
+	unlock_ufs(sb);
 
 	return 0;
 }
@@ -1256,7 +1266,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 	unsigned new_mount_opt, ufstype;
 	unsigned flags;
 
-	lock_kernel();
+	lock_ufs(sb);
 	lock_super(sb);
 	uspi = UFS_SB(sb)->s_uspi;
 	flags = UFS_SB(sb)->s_flags;
@@ -1272,7 +1282,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 	ufs_set_opt (new_mount_opt, ONERROR_LOCK);
 	if (!ufs_parse_options (data, &new_mount_opt)) {
 		unlock_super(sb);
-		unlock_kernel();
+		unlock_ufs(sb);
 		return -EINVAL;
 	}
 	if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
@@ -1280,14 +1290,14 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 	} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
 		printk("ufstype can't be changed during remount\n");
 		unlock_super(sb);
-		unlock_kernel();
+		unlock_ufs(sb);
 		return -EINVAL;
 	}
 
 	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
 		UFS_SB(sb)->s_mount_opt = new_mount_opt;
 		unlock_super(sb);
-		unlock_kernel();
+		unlock_ufs(sb);
 		return 0;
 	}
 	
@@ -1313,7 +1323,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 		printk("ufs was compiled with read-only support, "
 		"can't be mounted as read-write\n");
 		unlock_super(sb);
-		unlock_kernel();
+		unlock_ufs(sb);
 		return -EINVAL;
 #else
 		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
@@ -1323,13 +1333,13 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 		    ufstype != UFS_MOUNT_UFSTYPE_UFS2) {
 			printk("this ufstype is read-only supported\n");
 			unlock_super(sb);
-			unlock_kernel();
+			unlock_ufs(sb);
 			return -EINVAL;
 		}
 		if (!ufs_read_cylinder_structures(sb)) {
 			printk("failed during remounting\n");
 			unlock_super(sb);
-			unlock_kernel();
+			unlock_ufs(sb);
 			return -EPERM;
 		}
 		sb->s_flags &= ~MS_RDONLY;
@@ -1337,7 +1347,7 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 	}
 	UFS_SB(sb)->s_mount_opt = new_mount_opt;
 	unlock_super(sb);
-	unlock_kernel();
+	unlock_ufs(sb);
 	return 0;
 }
 
@@ -1371,7 +1381,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	struct ufs_super_block_third *usb3;
 	u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
 
-	lock_kernel();
+	lock_ufs(sb);
 
 	usb1 = ubh_get_usb_first(uspi);
 	usb2 = ubh_get_usb_second(uspi);
@@ -1395,7 +1405,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
 	buf->f_fsid.val[0] = (u32)id;
 	buf->f_fsid.val[1] = (u32)(id >> 32);
 
-	unlock_kernel();
+	unlock_ufs(sb);
 
 	return 0;
 }
@@ -1405,7 +1415,7 @@ static struct kmem_cache * ufs_inode_cachep;
 static struct inode *ufs_alloc_inode(struct super_block *sb)
 {
 	struct ufs_inode_info *ei;
-	ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_KERNEL);
+	ei = (struct ufs_inode_info *)kmem_cache_alloc(ufs_inode_cachep, GFP_NOFS);
 	if (!ei)
 		return NULL;
 	ei->vfs_inode.i_version = 1;
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index a58f915..e56a4f5 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -40,7 +40,6 @@
 #include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
 #include <linux/sched.h>
@@ -467,7 +466,6 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
 
 	block_truncate_page(inode->i_mapping, inode->i_size, ufs_getfrag_block);
 
-	lock_kernel();
 	while (1) {
 		retry = ufs_trunc_direct(inode);
 		retry |= ufs_trunc_indirect(inode, UFS_IND_BLOCK,
@@ -487,7 +485,6 @@ int ufs_truncate(struct inode *inode, loff_t old_i_size)
 
 	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
 	ufsi->i_lastfrag = DIRECT_FRAGMENT;
-	unlock_kernel();
 	mark_inode_dirty(inode);
 out:
 	UFSD("EXIT: err %d\n", err);
@@ -510,7 +507,9 @@ int ufs_setattr(struct dentry *dentry, struct iattr *attr)
 		/* XXX(truncate): truncate_setsize should be called last */
 		truncate_setsize(inode, attr->ia_size);
 
+		lock_ufs(inode->i_sb);
 		error = ufs_truncate(inode, old_i_size);
+		unlock_ufs(inode->i_sb);
 		if (error)
 			return error;
 	}
diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h
index c08782e..5be2755 100644
--- a/fs/ufs/ufs.h
+++ b/fs/ufs/ufs.h
@@ -18,6 +18,8 @@ struct ufs_sb_info {
 	unsigned s_cgno[UFS_MAX_GROUP_LOADED];
 	unsigned short s_cg_loaded;
 	unsigned s_mount_opt;
+	struct mutex mutex;
+	struct task_struct *mutex_owner;
 };
 
 struct ufs_inode_info {
@@ -109,7 +111,6 @@ extern struct inode *ufs_iget(struct super_block *, unsigned long);
 extern int ufs_write_inode (struct inode *, struct writeback_control *);
 extern int ufs_sync_inode (struct inode *);
 extern void ufs_evict_inode (struct inode *);
-extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
 extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
 
 /* namei.c */
@@ -154,4 +155,7 @@ static inline u32 ufs_dtogd(struct ufs_sb_private_info * uspi, u64 b)
 	return do_div(b, uspi->s_fpg);
 }
 
+extern void lock_ufs(struct super_block *sb);
+extern void unlock_ufs(struct super_block *sb);
+
 #endif /* _UFS_UFS_H */
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index d2c36d5..95425b5 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -27,7 +27,7 @@ struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
 	if (count > UFS_MAXFRAG)
 		return NULL;
 	ubh = (struct ufs_buffer_head *)
-		kmalloc (sizeof (struct ufs_buffer_head), GFP_KERNEL);
+		kmalloc (sizeof (struct ufs_buffer_head), GFP_NOFS);
 	if (!ubh)
 		return NULL;
 	ubh->fragment = fragment;
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index faca449..284a7c8 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -16,14 +16,11 @@
 # Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #
 
-EXTRA_CFLAGS +=	 -I$(src) -I$(src)/linux-2.6
+ccflags-y := -I$(src) -I$(src)/linux-2.6
+ccflags-$(CONFIG_XFS_DEBUG) += -g
 
 XFS_LINUX := linux-2.6
 
-ifeq ($(CONFIG_XFS_DEBUG),y)
-	EXTRA_CFLAGS += -g
-endif
-
 obj-$(CONFIG_XFS_FS)		+= xfs.o
 
 xfs-y				+= linux-2.6/xfs_trace.o
@@ -105,11 +102,10 @@ xfs-y				+= $(addprefix $(XFS_LINUX)/, \
 				   xfs_globals.o \
 				   xfs_ioctl.o \
 				   xfs_iops.o \
+				   xfs_message.o \
 				   xfs_super.o \
 				   xfs_sync.o \
 				   xfs_xattr.o)
 
 # Objects in support/
-xfs-y				+= $(addprefix support/, \
-				   debug.o \
-				   uuid.o)
+xfs-y				+= support/uuid.o
diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
index 666c9db..a907de5 100644
--- a/fs/xfs/linux-2.6/kmem.c
+++ b/fs/xfs/linux-2.6/kmem.c
@@ -23,6 +23,7 @@
 #include <linux/backing-dev.h>
 #include "time.h"
 #include "kmem.h"
+#include "xfs_message.h"
 
 /*
  * Greedy allocation.  May fail and may return vmalloced memory.
@@ -56,8 +57,8 @@ kmem_alloc(size_t size, unsigned int __nocast flags)
 		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 			return ptr;
 		if (!(++retries % 100))
-			printk(KERN_ERR "XFS: possible memory allocation "
-					"deadlock in %s (mode:0x%x)\n",
+			xfs_err(NULL,
+		"possible memory allocation deadlock in %s (mode:0x%x)",
 					__func__, lflags);
 		congestion_wait(BLK_RW_ASYNC, HZ/50);
 	} while (1);
@@ -112,8 +113,8 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags)
 		if (ptr || (flags & (KM_MAYFAIL|KM_NOSLEEP)))
 			return ptr;
 		if (!(++retries % 100))
-			printk(KERN_ERR "XFS: possible memory allocation "
-					"deadlock in %s (mode:0x%x)\n",
+			xfs_err(NULL,
+		"possible memory allocation deadlock in %s (mode:0x%x)",
 					__func__, lflags);
 		congestion_wait(BLK_RW_ASYNC, HZ/50);
 	} while (1);
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index ec7bbb5..8c5c872 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -854,7 +854,7 @@ xfs_aops_discard_page(
 	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
 		goto out_invalidate;
 
-	xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+	xfs_alert(ip->i_mount,
 		"page discard on page %p, inode 0x%llx, offset %llu.",
 			page, ip->i_ino, offset);
 
@@ -872,7 +872,7 @@ xfs_aops_discard_page(
 		if (error) {
 			/* something screwed, just bail */
 			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-				xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+				xfs_alert(ip->i_mount,
 			"page discard unable to remove delalloc mapping.");
 			}
 			break;
@@ -1411,7 +1411,7 @@ xfs_vm_write_failed(
 		if (error) {
 			/* something screwed, just bail */
 			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-				xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+				xfs_alert(ip->i_mount,
 			"xfs_vm_write_failed: unable to clean up ino %lld",
 						ip->i_ino);
 			}
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index ac1c7e8..5cb230f 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -401,9 +401,8 @@ _xfs_buf_lookup_pages(
 			 * handle buffer allocation failures we can't do much.
 			 */
 			if (!(++retries % 100))
-				printk(KERN_ERR
-					"XFS: possible memory allocation "
-					"deadlock in %s (mode:0x%x)\n",
+				xfs_err(NULL,
+		"possible memory allocation deadlock in %s (mode:0x%x)",
 					__func__, gfp_mask);
 
 			XFS_STATS_INC(xb_page_retries);
@@ -615,8 +614,8 @@ xfs_buf_get(
 	if (!(bp->b_flags & XBF_MAPPED)) {
 		error = _xfs_buf_map_pages(bp, flags);
 		if (unlikely(error)) {
-			printk(KERN_WARNING "%s: failed to map pages\n",
-					__func__);
+			xfs_warn(target->bt_mount,
+				"%s: failed to map pages\n", __func__);
 			goto no_buffer;
 		}
 	}
@@ -850,8 +849,8 @@ xfs_buf_get_uncached(
 
 	error = _xfs_buf_map_pages(bp, XBF_MAPPED);
 	if (unlikely(error)) {
-		printk(KERN_WARNING "%s: failed to map pages\n",
-				__func__);
+		xfs_warn(target->bt_mount,
+			"%s: failed to map pages\n", __func__);
 		goto fail_free_mem;
 	}
 
@@ -1617,8 +1616,8 @@ xfs_setsize_buftarg_flags(
 	btp->bt_smask = sectorsize - 1;
 
 	if (set_blocksize(btp->bt_bdev, sectorsize)) {
-		printk(KERN_WARNING
-			"XFS: Cannot set_blocksize to %u on device %s\n",
+		xfs_warn(btp->bt_mount,
+			"Cannot set_blocksize to %u on device %s\n",
 			sectorsize, XFS_BUFTARG_NAME(btp));
 		return EINVAL;
 	}
@@ -2022,11 +2021,12 @@ xfs_buf_init(void)
 	if (!xfslogd_workqueue)
 		goto out_free_buf_zone;
 
-	xfsdatad_workqueue = create_workqueue("xfsdatad");
+	xfsdatad_workqueue = alloc_workqueue("xfsdatad", WQ_MEM_RECLAIM, 1);
 	if (!xfsdatad_workqueue)
 		goto out_destroy_xfslogd_workqueue;
 
-	xfsconvertd_workqueue = create_workqueue("xfsconvertd");
+	xfsconvertd_workqueue = alloc_workqueue("xfsconvertd",
+						WQ_MEM_RECLAIM, 1);
 	if (!xfsconvertd_workqueue)
 		goto out_destroy_xfsdatad_workqueue;
 
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index fc0114d..f4f878f 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -89,8 +89,10 @@ xfs_fs_encode_fh(
 	 * seven combinations work.  The real answer is "don't use v2".
 	 */
 	len = xfs_fileid_length(fileid_type);
-	if (*max_len < len)
+	if (*max_len < len) {
+		*max_len = len;
 		return 255;
+	}
 	*max_len = len;
 
 	switch (fileid_type) {
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index bd57278..9ff7fc6 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -102,7 +102,8 @@ xfs_mark_inode_dirty(
 STATIC int
 xfs_init_security(
 	struct inode	*inode,
-	struct inode	*dir)
+	struct inode	*dir,
+	const struct qstr *qstr)
 {
 	struct xfs_inode *ip = XFS_I(inode);
 	size_t		length;
@@ -110,7 +111,7 @@ xfs_init_security(
 	unsigned char	*name;
 	int		error;
 
-	error = security_inode_init_security(inode, dir, (char **)&name,
+	error = security_inode_init_security(inode, dir, qstr, (char **)&name,
 					     &value, &length);
 	if (error) {
 		if (error == -EOPNOTSUPP)
@@ -194,7 +195,7 @@ xfs_vn_mknod(
 
 	inode = VFS_I(ip);
 
-	error = xfs_init_security(inode, dir);
+	error = xfs_init_security(inode, dir, &dentry->d_name);
 	if (unlikely(error))
 		goto out_cleanup_inode;
 
@@ -367,7 +368,7 @@ xfs_vn_symlink(
 
 	inode = VFS_I(cip);
 
-	error = xfs_init_security(inode, dir);
+	error = xfs_init_security(inode, dir, &dentry->d_name);
 	if (unlikely(error))
 		goto out_cleanup_inode;
 
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 0964949..244be9c 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -39,7 +39,6 @@
 #include <mrlock.h>
 #include <time.h>
 
-#include <support/debug.h>
 #include <support/uuid.h>
 
 #include <linux/semaphore.h>
@@ -86,6 +85,7 @@
 #include <xfs_aops.h>
 #include <xfs_super.h>
 #include <xfs_buf.h>
+#include <xfs_message.h>
 
 /*
  * Feature macros (disable/enable)
@@ -280,4 +280,25 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
 #define __arch_pack
 #endif
 
+#define ASSERT_ALWAYS(expr)	\
+	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+
+#ifndef DEBUG
+#define ASSERT(expr)	((void)0)
+
+#ifndef STATIC
+# define STATIC static noinline
+#endif
+
+#else /* DEBUG */
+
+#define ASSERT(expr)	\
+	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
+
+#ifndef STATIC
+# define STATIC noinline
+#endif
+
+#endif /* DEBUG */
+
 #endif /* __XFS_LINUX__ */
diff --git a/fs/xfs/linux-2.6/xfs_message.c b/fs/xfs/linux-2.6/xfs_message.c
new file mode 100644
index 0000000..508e06f
--- /dev/null
+++ b/fs/xfs/linux-2.6/xfs_message.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 Red Hat, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_types.h"
+#include "xfs_log.h"
+#include "xfs_inum.h"
+#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
+#include "xfs_mount.h"
+
+/*
+ * XFS logging functions
+ */
+static int
+__xfs_printk(
+	const char		*level,
+	const struct xfs_mount	*mp,
+	struct va_format	*vaf)
+{
+	if (mp && mp->m_fsname)
+		return printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf);
+	return printk("%sXFS: %pV\n", level, vaf);
+}
+
+int xfs_printk(
+	const char		*level,
+	const struct xfs_mount	*mp,
+	const char		*fmt, ...)
+{
+	struct va_format	vaf;
+	va_list			args;
+	int			 r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = __xfs_printk(level, mp, &vaf);
+	va_end(args);
+
+	return r;
+}
+
+#define define_xfs_printk_level(func, kern_level)		\
+int func(const struct xfs_mount *mp, const char *fmt, ...)	\
+{								\
+	struct va_format	vaf;				\
+	va_list			args;				\
+	int			r;				\
+								\
+	va_start(args, fmt);					\
+								\
+	vaf.fmt = fmt;						\
+	vaf.va = &args;						\
+								\
+	r = __xfs_printk(kern_level, mp, &vaf);			\
+	va_end(args);						\
+								\
+	return r;						\
+}								\
+
+define_xfs_printk_level(xfs_emerg, KERN_EMERG);
+define_xfs_printk_level(xfs_alert, KERN_ALERT);
+define_xfs_printk_level(xfs_crit, KERN_CRIT);
+define_xfs_printk_level(xfs_err, KERN_ERR);
+define_xfs_printk_level(xfs_warn, KERN_WARNING);
+define_xfs_printk_level(xfs_notice, KERN_NOTICE);
+define_xfs_printk_level(xfs_info, KERN_INFO);
+#ifdef DEBUG
+define_xfs_printk_level(xfs_debug, KERN_DEBUG);
+#endif
+
+int
+xfs_alert_tag(
+	const struct xfs_mount	*mp,
+	int			panic_tag,
+	const char		*fmt, ...)
+{
+	struct va_format	vaf;
+	va_list			args;
+	int			do_panic = 0;
+	int			r;
+
+	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) {
+		xfs_printk(KERN_ALERT, mp,
+			"XFS: Transforming an alert into a BUG.");
+		do_panic = 1;
+	}
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = __xfs_printk(KERN_ALERT, mp, &vaf);
+	va_end(args);
+
+	BUG_ON(do_panic);
+
+	return r;
+}
+
+void
+assfail(char *expr, char *file, int line)
+{
+	xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d",
+		expr, file, line);
+	BUG();
+}
+
+void
+xfs_hex_dump(void *p, int length)
+{
+	print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1);
+}
diff --git a/fs/xfs/linux-2.6/xfs_message.h b/fs/xfs/linux-2.6/xfs_message.h
new file mode 100644
index 0000000..e77ffa1
--- /dev/null
+++ b/fs/xfs/linux-2.6/xfs_message.h
@@ -0,0 +1,38 @@
+#ifndef __XFS_MESSAGE_H
+#define __XFS_MESSAGE_H 1
+
+struct xfs_mount;
+
+extern int xfs_printk(const char *level, const struct xfs_mount *mp,
+                      const char *fmt, ...)
+        __attribute__ ((format (printf, 3, 4)));
+extern int xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_alert(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_alert_tag(const struct xfs_mount *mp, int tag,
+			 const char *fmt, ...)
+        __attribute__ ((format (printf, 3, 4)));
+extern int xfs_crit(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_err(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_warn(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_notice(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+extern int xfs_info(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+
+#ifdef DEBUG
+extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...)
+        __attribute__ ((format (printf, 2, 3)));
+#else
+#define xfs_debug(mp, fmt, ...)	(0)
+#endif
+
+extern void assfail(char *expr, char *f, int l);
+
+extern void xfs_hex_dump(void *p, int length);
+
+#endif	/* __XFS_MESSAGE_H */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 9731898..818c4cf 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -173,6 +173,15 @@ xfs_parseargs(
 	__uint8_t		iosizelog = 0;
 
 	/*
+	 * set up the mount name first so all the errors will refer to the
+	 * correct device.
+	 */
+	mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL);
+	if (!mp->m_fsname)
+		return ENOMEM;
+	mp->m_fsname_len = strlen(mp->m_fsname) + 1;
+
+	/*
 	 * Copy binary VFS mount flags we are interested in.
 	 */
 	if (sb->s_flags & MS_RDONLY)
@@ -189,6 +198,7 @@ xfs_parseargs(
 	mp->m_flags |= XFS_MOUNT_BARRIER;
 	mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
 	mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
+	mp->m_flags |= XFS_MOUNT_DELAYLOG;
 
 	/*
 	 * These can be overridden by the mount option parsing.
@@ -207,24 +217,21 @@ xfs_parseargs(
 
 		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			mp->m_logbufs = simple_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			mp->m_logbsize = suffix_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -232,14 +239,12 @@ xfs_parseargs(
 			if (!mp->m_logname)
 				return ENOMEM;
 		} else if (!strcmp(this_char, MNTOPT_MTPT)) {
-			cmn_err(CE_WARN,
-				"XFS: %s option not allowed on this system",
+			xfs_warn(mp, "%s option not allowed on this system",
 				this_char);
 			return EINVAL;
 		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -248,8 +253,7 @@ xfs_parseargs(
 				return ENOMEM;
 		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -257,8 +261,7 @@ xfs_parseargs(
 			iosizelog = ffs(iosize) - 1;
 		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -280,16 +283,14 @@ xfs_parseargs(
 			mp->m_flags |= XFS_MOUNT_SWALLOC;
 		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			dsunit = simple_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
 			if (!value || !*value) {
-				cmn_err(CE_WARN,
-					"XFS: %s option requires an argument",
+				xfs_warn(mp, "%s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -297,8 +298,7 @@ xfs_parseargs(
 		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
 			mp->m_flags &= ~XFS_MOUNT_SMALL_INUMS;
 #if !XFS_BIG_INUMS
-			cmn_err(CE_WARN,
-				"XFS: %s option not allowed on this system",
+			xfs_warn(mp, "%s option not allowed on this system",
 				this_char);
 			return EINVAL;
 #endif
@@ -356,20 +356,19 @@ xfs_parseargs(
 		} else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
 			mp->m_flags &= ~XFS_MOUNT_DELAYLOG;
 		} else if (!strcmp(this_char, "ihashsize")) {
-			cmn_err(CE_WARN,
-	"XFS: ihashsize no longer used, option is deprecated.");
+			xfs_warn(mp,
+	"ihashsize no longer used, option is deprecated.");
 		} else if (!strcmp(this_char, "osyncisdsync")) {
-			cmn_err(CE_WARN,
-	"XFS: osyncisdsync has no effect, option is deprecated.");
+			xfs_warn(mp,
+	"osyncisdsync has no effect, option is deprecated.");
 		} else if (!strcmp(this_char, "osyncisosync")) {
-			cmn_err(CE_WARN,
-	"XFS: osyncisosync has no effect, option is deprecated.");
+			xfs_warn(mp,
+	"osyncisosync has no effect, option is deprecated.");
 		} else if (!strcmp(this_char, "irixsgid")) {
-			cmn_err(CE_WARN,
-	"XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
+			xfs_warn(mp,
+	"irixsgid is now a sysctl(2) variable, option is deprecated.");
 		} else {
-			cmn_err(CE_WARN,
-				"XFS: unknown mount option [%s].", this_char);
+			xfs_warn(mp, "unknown mount option [%s].", this_char);
 			return EINVAL;
 		}
 	}
@@ -379,40 +378,37 @@ xfs_parseargs(
 	 */
 	if ((mp->m_flags & XFS_MOUNT_NORECOVERY) &&
 	    !(mp->m_flags & XFS_MOUNT_RDONLY)) {
-		cmn_err(CE_WARN, "XFS: no-recovery mounts must be read-only.");
+		xfs_warn(mp, "no-recovery mounts must be read-only.");
 		return EINVAL;
 	}
 
 	if ((mp->m_flags & XFS_MOUNT_NOALIGN) && (dsunit || dswidth)) {
-		cmn_err(CE_WARN,
-	"XFS: sunit and swidth options incompatible with the noalign option");
+		xfs_warn(mp,
+	"sunit and swidth options incompatible with the noalign option");
 		return EINVAL;
 	}
 
 #ifndef CONFIG_XFS_QUOTA
 	if (XFS_IS_QUOTA_RUNNING(mp)) {
-		cmn_err(CE_WARN,
-			"XFS: quota support not available in this kernel.");
+		xfs_warn(mp, "quota support not available in this kernel.");
 		return EINVAL;
 	}
 #endif
 
 	if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
 	    (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) {
-		cmn_err(CE_WARN,
-			"XFS: cannot mount with both project and group quota");
+		xfs_warn(mp, "cannot mount with both project and group quota");
 		return EINVAL;
 	}
 
 	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
-		cmn_err(CE_WARN,
-			"XFS: sunit and swidth must be specified together");
+		xfs_warn(mp, "sunit and swidth must be specified together");
 		return EINVAL;
 	}
 
 	if (dsunit && (dswidth % dsunit != 0)) {
-		cmn_err(CE_WARN,
-	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
+		xfs_warn(mp,
+	"stripe width (%d) must be a multiple of the stripe unit (%d)",
 			dswidth, dsunit);
 		return EINVAL;
 	}
@@ -438,8 +434,7 @@ done:
 	    mp->m_logbufs != 0 &&
 	    (mp->m_logbufs < XLOG_MIN_ICLOGS ||
 	     mp->m_logbufs > XLOG_MAX_ICLOGS)) {
-		cmn_err(CE_WARN,
-			"XFS: invalid logbufs value: %d [not %d-%d]",
+		xfs_warn(mp, "invalid logbufs value: %d [not %d-%d]",
 			mp->m_logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
 		return XFS_ERROR(EINVAL);
 	}
@@ -448,22 +443,16 @@ done:
 	    (mp->m_logbsize < XLOG_MIN_RECORD_BSIZE ||
 	     mp->m_logbsize > XLOG_MAX_RECORD_BSIZE ||
 	     !is_power_of_2(mp->m_logbsize))) {
-		cmn_err(CE_WARN,
-	"XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
+		xfs_warn(mp,
+			"invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
 			mp->m_logbsize);
 		return XFS_ERROR(EINVAL);
 	}
 
-	mp->m_fsname = kstrndup(sb->s_id, MAXNAMELEN, GFP_KERNEL);
-	if (!mp->m_fsname)
-		return ENOMEM;
-	mp->m_fsname_len = strlen(mp->m_fsname) + 1;
-
 	if (iosizelog) {
 		if (iosizelog > XFS_MAX_IO_LOG ||
 		    iosizelog < XFS_MIN_IO_LOG) {
-			cmn_err(CE_WARN,
-		"XFS: invalid log iosize: %d [not %d-%d]",
+			xfs_warn(mp, "invalid log iosize: %d [not %d-%d]",
 				iosizelog, XFS_MIN_IO_LOG,
 				XFS_MAX_IO_LOG);
 			return XFS_ERROR(EINVAL);
@@ -610,7 +599,7 @@ xfs_blkdev_get(
 				    mp);
 	if (IS_ERR(*bdevp)) {
 		error = PTR_ERR(*bdevp);
-		printk("XFS: Invalid device [%s], error=%d\n", name, error);
+		xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error);
 	}
 
 	return -error;
@@ -664,23 +653,23 @@ xfs_mountfs_check_barriers(xfs_mount_t *mp)
 	int error;
 
 	if (mp->m_logdev_targp != mp->m_ddev_targp) {
-		xfs_fs_cmn_err(CE_NOTE, mp,
+		xfs_notice(mp,
 		  "Disabling barriers, not supported with external log device");
 		mp->m_flags &= ~XFS_MOUNT_BARRIER;
 		return;
 	}
 
 	if (xfs_readonly_buftarg(mp->m_ddev_targp)) {
-		xfs_fs_cmn_err(CE_NOTE, mp,
-		  "Disabling barriers, underlying device is readonly");
+		xfs_notice(mp,
+			"Disabling barriers, underlying device is readonly");
 		mp->m_flags &= ~XFS_MOUNT_BARRIER;
 		return;
 	}
 
 	error = xfs_barrier_test(mp);
 	if (error) {
-		xfs_fs_cmn_err(CE_NOTE, mp,
-		  "Disabling barriers, trial barrier write failed");
+		xfs_notice(mp,
+			"Disabling barriers, trial barrier write failed");
 		mp->m_flags &= ~XFS_MOUNT_BARRIER;
 		return;
 	}
@@ -743,8 +732,8 @@ xfs_open_devices(
 			goto out_close_logdev;
 
 		if (rtdev == ddev || rtdev == logdev) {
-			cmn_err(CE_WARN,
-	"XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
+			xfs_warn(mp,
+	"Cannot mount filesystem with identical rtdev and ddev/logdev.");
 			error = EINVAL;
 			goto out_close_rtdev;
 		}
@@ -1345,8 +1334,8 @@ xfs_fs_remount(
 			 * options that we can't actually change.
 			 */
 #if 0
-			printk(KERN_INFO
-	"XFS: mount option \"%s\" not supported for remount\n", p);
+			xfs_info(mp,
+		"mount option \"%s\" not supported for remount\n", p);
 			return -EINVAL;
 #else
 			break;
@@ -1367,8 +1356,7 @@ xfs_fs_remount(
 		if (mp->m_update_flags) {
 			error = xfs_mount_log_sb(mp, mp->m_update_flags);
 			if (error) {
-				cmn_err(CE_WARN,
-					"XFS: failed to write sb changes");
+				xfs_warn(mp, "failed to write sb changes");
 				return error;
 			}
 			mp->m_update_flags = 0;
@@ -1452,15 +1440,15 @@ xfs_finish_flags(
 			mp->m_logbsize = mp->m_sb.sb_logsunit;
 		} else if (mp->m_logbsize > 0 &&
 			   mp->m_logbsize < mp->m_sb.sb_logsunit) {
-			cmn_err(CE_WARN,
-	"XFS: logbuf size must be greater than or equal to log stripe size");
+			xfs_warn(mp,
+		"logbuf size must be greater than or equal to log stripe size");
 			return XFS_ERROR(EINVAL);
 		}
 	} else {
 		/* Fail a mount if the logbuf is larger than 32K */
 		if (mp->m_logbsize > XLOG_BIG_RECORD_BSIZE) {
-			cmn_err(CE_WARN,
-	"XFS: logbuf size for version 1 logs must be 16K or 32K");
+			xfs_warn(mp,
+		"logbuf size for version 1 logs must be 16K or 32K");
 			return XFS_ERROR(EINVAL);
 		}
 	}
@@ -1477,8 +1465,8 @@ xfs_finish_flags(
 	 * prohibit r/w mounts of read-only filesystems
 	 */
 	if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
-		cmn_err(CE_WARN,
-	"XFS: cannot mount a read-only filesystem as read-write");
+		xfs_warn(mp,
+			"cannot mount a read-only filesystem as read-write");
 		return XFS_ERROR(EROFS);
 	}
 
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index e22f005..6c10f1d 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -425,8 +425,7 @@ xfs_quiesce_attr(
 	/* Push the superblock and write an unmount record */
 	error = xfs_log_sbcount(mp, 1);
 	if (error)
-		xfs_fs_cmn_err(CE_WARN, mp,
-				"xfs_attr_quiesce: failed to log sb changes. "
+		xfs_warn(mp, "xfs_attr_quiesce: failed to log sb changes. "
 				"Frozen image may not be consistent.");
 	xfs_log_unmount_write(mp);
 	xfs_unmountfs_writesb(mp);
@@ -806,7 +805,7 @@ xfs_reclaim_inode(
 	 * pass on the error.
 	 */
 	if (error && error != EAGAIN && !XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-		xfs_fs_cmn_err(CE_WARN, ip->i_mount,
+		xfs_warn(ip->i_mount,
 			"inode 0x%llx background reclaim flush failed with %d",
 			(long long)ip->i_ino, error);
 	}
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index ee3cee0..ee2d2ad 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -37,7 +37,7 @@ xfs_stats_clear_proc_handler(
 	ret = proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
 
 	if (!ret && write && *valp) {
-		printk("XFS Clearing xfsstats\n");
+		xfs_notice(NULL, "Clearing xfsstats");
 		for_each_possible_cpu(c) {
 			preempt_disable();
 			/* save vn_active, it's a universal truth! */
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index d22aa31..7e24164 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -544,9 +544,10 @@ xfs_qm_dqtobp(
 	/*
 	 * A simple sanity check in case we got a corrupted dquot...
 	 */
-	if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
+	error = xfs_qm_dqcheck(mp, ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
 			   flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
-			   "dqtobp")) {
+			   "dqtobp");
+	if (error) {
 		if (!(flags & XFS_QMOPT_DQREPAIR)) {
 			xfs_trans_brelse(tp, bp);
 			return XFS_ERROR(EIO);
@@ -827,7 +828,7 @@ xfs_qm_dqget(
 	if (xfs_do_dqerror) {
 		if ((xfs_dqerror_target == mp->m_ddev_targp) &&
 		    (xfs_dqreq_num++ % xfs_dqerror_mod) == 0) {
-			cmn_err(CE_DEBUG, "Returning error in dqget");
+			xfs_debug(mp, "Returning error in dqget");
 			return (EIO);
 		}
 	}
@@ -1207,8 +1208,9 @@ xfs_qm_dqflush(
 	/*
 	 * A simple sanity check in case we got a corrupted dquot..
 	 */
-	if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), 0,
-			   XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
+	error = xfs_qm_dqcheck(mp, &dqp->q_core, be32_to_cpu(ddqp->d_id), 0,
+			   XFS_QMOPT_DOWARN, "dqflush (incore copy)");
+	if (error) {
 		xfs_buf_relse(bp);
 		xfs_dqfunlock(dqp);
 		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
@@ -1391,8 +1393,8 @@ xfs_qm_dqpurge(
 		 */
 		error = xfs_qm_dqflush(dqp, SYNC_WAIT);
 		if (error)
-			xfs_fs_cmn_err(CE_WARN, mp,
-				"xfs_qm_dqpurge: dquot %p flush failed", dqp);
+			xfs_warn(mp, "%s: dquot %p flush failed",
+				__func__, dqp);
 		xfs_dqflock(dqp);
 	}
 	ASSERT(atomic_read(&dqp->q_pincount) == 0);
@@ -1425,36 +1427,38 @@ xfs_qm_dqpurge(
 void
 xfs_qm_dqprint(xfs_dquot_t *dqp)
 {
-	cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
-	cmn_err(CE_DEBUG, "---- dquotID =  %d",
+	struct xfs_mount	*mp = dqp->q_mount;
+
+	xfs_debug(mp, "-----------KERNEL DQUOT----------------");
+	xfs_debug(mp, "---- dquotID =  %d",
 		(int)be32_to_cpu(dqp->q_core.d_id));
-	cmn_err(CE_DEBUG, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
-	cmn_err(CE_DEBUG, "---- fs      =  0x%p", dqp->q_mount);
-	cmn_err(CE_DEBUG, "---- blkno   =  0x%x", (int) dqp->q_blkno);
-	cmn_err(CE_DEBUG, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
-	cmn_err(CE_DEBUG, "---- blkhlimit =  %Lu (0x%x)",
+	xfs_debug(mp, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
+	xfs_debug(mp, "---- fs      =  0x%p", dqp->q_mount);
+	xfs_debug(mp, "---- blkno   =  0x%x", (int) dqp->q_blkno);
+	xfs_debug(mp, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
+	xfs_debug(mp, "---- blkhlimit =  %Lu (0x%x)",
 		be64_to_cpu(dqp->q_core.d_blk_hardlimit),
 		(int)be64_to_cpu(dqp->q_core.d_blk_hardlimit));
-	cmn_err(CE_DEBUG, "---- blkslimit =  %Lu (0x%x)",
+	xfs_debug(mp, "---- blkslimit =  %Lu (0x%x)",
 		be64_to_cpu(dqp->q_core.d_blk_softlimit),
 		(int)be64_to_cpu(dqp->q_core.d_blk_softlimit));
-	cmn_err(CE_DEBUG, "---- inohlimit =  %Lu (0x%x)",
+	xfs_debug(mp, "---- inohlimit =  %Lu (0x%x)",
 		be64_to_cpu(dqp->q_core.d_ino_hardlimit),
 		(int)be64_to_cpu(dqp->q_core.d_ino_hardlimit));
-	cmn_err(CE_DEBUG, "---- inoslimit =  %Lu (0x%x)",
+	xfs_debug(mp, "---- inoslimit =  %Lu (0x%x)",
 		be64_to_cpu(dqp->q_core.d_ino_softlimit),
 		(int)be64_to_cpu(dqp->q_core.d_ino_softlimit));
-	cmn_err(CE_DEBUG, "---- bcount  =  %Lu (0x%x)",
+	xfs_debug(mp, "---- bcount  =  %Lu (0x%x)",
 		be64_to_cpu(dqp->q_core.d_bcount),
 		(int)be64_to_cpu(dqp->q_core.d_bcount));
-	cmn_err(CE_DEBUG, "---- icount  =  %Lu (0x%x)",
+	xfs_debug(mp, "---- icount  =  %Lu (0x%x)",
 		be64_to_cpu(dqp->q_core.d_icount),
 		(int)be64_to_cpu(dqp->q_core.d_icount));
-	cmn_err(CE_DEBUG, "---- btimer  =  %d",
+	xfs_debug(mp, "---- btimer  =  %d",
 		(int)be32_to_cpu(dqp->q_core.d_btimer));
-	cmn_err(CE_DEBUG, "---- itimer  =  %d",
+	xfs_debug(mp, "---- itimer  =  %d",
 		(int)be32_to_cpu(dqp->q_core.d_itimer));
-	cmn_err(CE_DEBUG, "---------------------------");
+	xfs_debug(mp, "---------------------------");
 }
 #endif
 
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 2a1f3dc..9e0e2fa 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -136,9 +136,8 @@ xfs_qm_dquot_logitem_push(
 	 */
 	error = xfs_qm_dqflush(dqp, 0);
 	if (error)
-		xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
-			"xfs_qm_dquot_logitem_push: push error %d on dqp %p",
-			error, dqp);
+		xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p",
+			__func__, error, dqp);
 	xfs_dqunlock(dqp);
 }
 
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 206a281..254ee06 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -80,7 +80,7 @@ xfs_qm_dquot_list_print(
 	int		i = 0;
 
 	list_for_each_entry(dqp, &mp->m_quotainfo->qi_dqlist_lock, qi_mplist) {
-		cmn_err(CE_DEBUG, "   %d. \"%d (%s)\"   "
+		xfs_debug(mp, "   %d. \"%d (%s)\"   "
 				  "bcnt = %lld, icnt = %lld, refs = %d",
 			i++, be32_to_cpu(dqp->q_core.d_id),
 			DQFLAGTO_TYPESTR(dqp),
@@ -205,7 +205,7 @@ xfs_qm_destroy(
 	list_for_each_entry_safe(dqp, n, &xqm->qm_dqfrlist, q_freelist) {
 		xfs_dqlock(dqp);
 #ifdef QUOTADEBUG
-		cmn_err(CE_DEBUG, "FREELIST destroy 0x%p", dqp);
+		xfs_debug(dqp->q_mount, "FREELIST destroy 0x%p", dqp);
 #endif
 		list_del_init(&dqp->q_freelist);
 		xfs_Gqm->qm_dqfrlist_cnt--;
@@ -341,9 +341,7 @@ xfs_qm_mount_quotas(
 	 * quotas immediately.
 	 */
 	if (mp->m_sb.sb_rextents) {
-		cmn_err(CE_NOTE,
-			"Cannot turn on quotas for realtime filesystem %s",
-			mp->m_fsname);
+		xfs_notice(mp, "Cannot turn on quotas for realtime filesystem");
 		mp->m_qflags = 0;
 		goto write_changes;
 	}
@@ -402,14 +400,13 @@ xfs_qm_mount_quotas(
 			 * off, but the on disk superblock doesn't know that !
 			 */
 			ASSERT(!(XFS_IS_QUOTA_RUNNING(mp)));
-			xfs_fs_cmn_err(CE_ALERT, mp,
-				"XFS mount_quotas: Superblock update failed!");
+			xfs_alert(mp, "%s: Superblock update failed!",
+				__func__);
 		}
 	}
 
 	if (error) {
-		xfs_fs_cmn_err(CE_WARN, mp,
-			"Failed to initialize disk quotas.");
+		xfs_warn(mp, "Failed to initialize disk quotas.");
 		return;
 	}
 
@@ -1230,13 +1227,6 @@ xfs_qm_qino_alloc(
 	}
 
 	/*
-	 * Keep an extra reference to this quota inode. This inode is
-	 * locked exclusively and joined to the transaction already.
-	 */
-	ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL));
-	IHOLD(*ip);
-
-	/*
 	 * Make the changes in the superblock, and log those too.
 	 * sbfields arg may contain fields other than *QUOTINO;
 	 * VERSIONNUM for example.
@@ -1264,7 +1254,7 @@ xfs_qm_qino_alloc(
 	xfs_mod_sb(tp, sbfields);
 
 	if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {
-		xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!");
+		xfs_alert(mp, "%s failed (error %d)!", __func__, error);
 		return error;
 	}
 	return 0;
@@ -1299,7 +1289,7 @@ xfs_qm_reset_dqcounts(
 		 * output any warnings because it's perfectly possible to
 		 * find uninitialised dquot blks. See comment in xfs_qm_dqcheck.
 		 */
-		(void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR,
+		(void) xfs_qm_dqcheck(mp, ddq, id+j, type, XFS_QMOPT_DQREPAIR,
 				      "xfs_quotacheck");
 		ddq->d_bcount = 0;
 		ddq->d_icount = 0;
@@ -1676,7 +1666,7 @@ xfs_qm_quotacheck(
 	 */
 	ASSERT(list_empty(&mp->m_quotainfo->qi_dqlist));
 
-	cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
+	xfs_notice(mp, "Quotacheck needed: Please wait.");
 
 	/*
 	 * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
@@ -1754,9 +1744,9 @@ xfs_qm_quotacheck(
 
  error_return:
 	if (error) {
-		cmn_err(CE_WARN, "XFS quotacheck %s: Unsuccessful (Error %d): "
-			"Disabling quotas.",
-			mp->m_fsname, error);
+		xfs_warn(mp,
+	"Quotacheck: Unsuccessful (Error %d): Disabling quotas.",
+			error);
 		/*
 		 * We must turn off quotas.
 		 */
@@ -1764,12 +1754,11 @@ xfs_qm_quotacheck(
 		ASSERT(xfs_Gqm != NULL);
 		xfs_qm_destroy_quotainfo(mp);
 		if (xfs_mount_reset_sbqflags(mp)) {
-			cmn_err(CE_WARN, "XFS quotacheck %s: "
-				"Failed to reset quota flags.", mp->m_fsname);
+			xfs_warn(mp,
+				"Quotacheck: Failed to reset quota flags.");
 		}
-	} else {
-		cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
-	}
+	} else
+		xfs_notice(mp, "Quotacheck: Done.");
 	return (error);
 }
 
@@ -1937,8 +1926,8 @@ again:
 			 */
 			error = xfs_qm_dqflush(dqp, 0);
 			if (error) {
-				xfs_fs_cmn_err(CE_WARN, mp,
-			"xfs_qm_dqreclaim: dquot %p flush failed", dqp);
+				xfs_warn(mp, "%s: dquot %p flush failed",
+					__func__, dqp);
 			}
 			goto dqunlock;
 		}
@@ -2115,7 +2104,7 @@ xfs_qm_write_sb_changes(
 	int		error;
 
 #ifdef QUOTADEBUG
-	cmn_err(CE_NOTE, "Writing superblock quota changes :%s", mp->m_fsname);
+	xfs_notice(mp, "Writing superblock quota changes");
 #endif
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
 	if ((error = xfs_trans_reserve(tp, 0,
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index 45b5cb1..774d7ec 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -119,8 +119,7 @@ xfs_qm_newmount(
 	     (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
 	    (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&
 	    xfs_dev_is_read_only(mp, "changing quota state")) {
-		cmn_err(CE_WARN,
-			"XFS: please mount with%s%s%s%s.",
+		xfs_warn(mp, "please mount with%s%s%s%s.",
 			(!quotaondisk ? "out quota" : ""),
 			(uquotaondisk ? " usrquota" : ""),
 			(pquotaondisk ? " prjquota" : ""),
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index bdebc18..c82f067 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -41,12 +41,6 @@
 #include "xfs_qm.h"
 #include "xfs_trace.h"
 
-#ifdef DEBUG
-# define qdprintk(s, args...)	cmn_err(CE_DEBUG, s, ## args)
-#else
-# define qdprintk(s, args...)	do { } while (0)
-#endif
-
 STATIC int	xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
 STATIC int	xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
 					uint);
@@ -294,7 +288,8 @@ xfs_qm_scall_trunc_qfiles(
 	int		error = 0, error2 = 0;
 
 	if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
-		qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
+		xfs_debug(mp, "%s: flags=%x m_qflags=%x\n",
+			__func__, flags, mp->m_qflags);
 		return XFS_ERROR(EINVAL);
 	}
 
@@ -331,7 +326,8 @@ xfs_qm_scall_quotaon(
 	sbflags = 0;
 
 	if (flags == 0) {
-		qdprintk("quotaon: zero flags, m_qflags=%x\n", mp->m_qflags);
+		xfs_debug(mp, "%s: zero flags, m_qflags=%x\n",
+			__func__, mp->m_qflags);
 		return XFS_ERROR(EINVAL);
 	}
 
@@ -352,8 +348,9 @@ xfs_qm_scall_quotaon(
 	    (flags & XFS_GQUOTA_ACCT) == 0 &&
 	    (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
 	    (flags & XFS_OQUOTA_ENFD))) {
-		qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
-			flags, mp->m_sb.sb_qflags);
+		xfs_debug(mp,
+			"%s: Can't enforce without acct, flags=%x sbflags=%x\n",
+			__func__, flags, mp->m_sb.sb_qflags);
 		return XFS_ERROR(EINVAL);
 	}
 	/*
@@ -541,7 +538,7 @@ xfs_qm_scall_setqlim(
 			q->qi_bsoftlimit = soft;
 		}
 	} else {
-		qdprintk("blkhard %Ld < blksoft %Ld\n", hard, soft);
+		xfs_debug(mp, "blkhard %Ld < blksoft %Ld\n", hard, soft);
 	}
 	hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
 		(xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
@@ -557,7 +554,7 @@ xfs_qm_scall_setqlim(
 			q->qi_rtbsoftlimit = soft;
 		}
 	} else {
-		qdprintk("rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
+		xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld\n", hard, soft);
 	}
 
 	hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
@@ -574,7 +571,7 @@ xfs_qm_scall_setqlim(
 			q->qi_isoftlimit = soft;
 		}
 	} else {
-		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
+		xfs_debug(mp, "ihard %Ld < isoft %Ld\n", hard, soft);
 	}
 
 	/*
@@ -939,10 +936,11 @@ struct mutex  qcheck_lock;
 #define DQTEST_LIST_PRINT(l, NXT, title) \
 { \
 	  xfs_dqtest_t	*dqp; int i = 0;\
-	  cmn_err(CE_DEBUG, "%s (#%d)", title, (int) (l)->qh_nelems); \
+	  xfs_debug(NULL, "%s (#%d)", title, (int) (l)->qh_nelems); \
 	  for (dqp = (xfs_dqtest_t *)(l)->qh_next; dqp != NULL; \
 	       dqp = (xfs_dqtest_t *)dqp->NXT) { \
-		cmn_err(CE_DEBUG, "  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
+		xfs_debug(dqp->q_mount,		\
+			"  %d. \"%d (%s)\"  bcnt = %d, icnt = %d", \
 			 ++i, dqp->d_id, DQFLAGTO_TYPESTR(dqp),	     \
 			 dqp->d_bcount, dqp->d_icount); } \
 }
@@ -966,16 +964,17 @@ xfs_qm_hashinsert(xfs_dqhash_t *h, xfs_dqtest_t *dqp)
 }
 STATIC void
 xfs_qm_dqtest_print(
-	xfs_dqtest_t	*d)
+	struct xfs_mount	*mp,
+	struct dqtest		*d)
 {
-	cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
-	cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
-	cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount);
-	cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)",
+	xfs_debug(mp, "-----------DQTEST DQUOT----------------");
+	xfs_debug(mp, "---- dquot ID = %d", d->d_id);
+	xfs_debug(mp, "---- fs       = 0x%p", d->q_mount);
+	xfs_debug(mp, "---- bcount   = %Lu (0x%x)",
 		d->d_bcount, (int)d->d_bcount);
-	cmn_err(CE_DEBUG, "---- icount   = %Lu (0x%x)",
+	xfs_debug(mp, "---- icount   = %Lu (0x%x)",
 		d->d_icount, (int)d->d_icount);
-	cmn_err(CE_DEBUG, "---------------------------");
+	xfs_debug(mp, "---------------------------");
 }
 
 STATIC void
@@ -989,12 +988,14 @@ xfs_qm_dqtest_failed(
 {
 	qmtest_nfails++;
 	if (error)
-		cmn_err(CE_DEBUG, "quotacheck failed id=%d, err=%d\nreason: %s",
-		       d->d_id, error, reason);
+		xfs_debug(dqp->q_mount,
+			"quotacheck failed id=%d, err=%d\nreason: %s",
+			d->d_id, error, reason);
 	else
-		cmn_err(CE_DEBUG, "quotacheck failed id=%d (%s) [%d != %d]",
-		       d->d_id, reason, (int)a, (int)b);
-	xfs_qm_dqtest_print(d);
+		xfs_debug(dqp->q_mount,
+			"quotacheck failed id=%d (%s) [%d != %d]",
+			d->d_id, reason, (int)a, (int)b);
+	xfs_qm_dqtest_print(dqp->q_mount, d);
 	if (dqp)
 		xfs_qm_dqprint(dqp);
 }
@@ -1021,9 +1022,9 @@ xfs_dqtest_cmp2(
 	    be64_to_cpu(dqp->q_core.d_bcount) >=
 	    be64_to_cpu(dqp->q_core.d_blk_softlimit)) {
 		if (!dqp->q_core.d_btimer && dqp->q_core.d_id) {
-			cmn_err(CE_DEBUG,
-				"%d [%s] [0x%p] BLK TIMER NOT STARTED",
-				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
+			xfs_debug(dqp->q_mount,
+				"%d [%s] BLK TIMER NOT STARTED",
+				d->d_id, DQFLAGTO_TYPESTR(d));
 			err++;
 		}
 	}
@@ -1031,16 +1032,16 @@ xfs_dqtest_cmp2(
 	    be64_to_cpu(dqp->q_core.d_icount) >=
 	    be64_to_cpu(dqp->q_core.d_ino_softlimit)) {
 		if (!dqp->q_core.d_itimer && dqp->q_core.d_id) {
-			cmn_err(CE_DEBUG,
-				"%d [%s] [0x%p] INO TIMER NOT STARTED",
-				d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
+			xfs_debug(dqp->q_mount,
+				"%d [%s] INO TIMER NOT STARTED",
+				d->d_id, DQFLAGTO_TYPESTR(d));
 			err++;
 		}
 	}
 #ifdef QUOTADEBUG
 	if (!err) {
-		cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
-			d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
+		xfs_debug(dqp->q_mount, "%d [%s] qchecked",
+			d->d_id, DQFLAGTO_TYPESTR(d));
 	}
 #endif
 	return (err);
@@ -1137,8 +1138,8 @@ xfs_qm_internalqcheck_adjust(
 
 	if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
 		*res = BULKSTAT_RV_NOTHING;
-		qdprintk("internalqcheck: ino=%llu, uqino=%llu, gqino=%llu\n",
-			(unsigned long long) ino,
+		xfs_debug(mp, "%s: ino=%llu, uqino=%llu, gqino=%llu\n",
+			__func__, (unsigned long long) ino,
 			(unsigned long long) mp->m_sb.sb_uquotino,
 			(unsigned long long) mp->m_sb.sb_gquotino);
 		return XFS_ERROR(EINVAL);
@@ -1223,12 +1224,12 @@ xfs_qm_internalqcheck(
 				 xfs_qm_internalqcheck_adjust,
 				 0, NULL, &done);
 		if (error) {
-			cmn_err(CE_DEBUG, "Bulkstat returned error 0x%x", error);
+			xfs_debug(mp, "Bulkstat returned error 0x%x", error);
 			break;
 		}
 	} while (!done);
 
-	cmn_err(CE_DEBUG, "Checking results against system dquots");
+	xfs_debug(mp, "Checking results against system dquots");
 	for (i = 0; i < qmtest_hashmask; i++) {
 		xfs_dqtest_t	*d, *n;
 		xfs_dqhash_t	*h;
@@ -1246,10 +1247,10 @@ xfs_qm_internalqcheck(
 	}
 
 	if (qmtest_nfails) {
-		cmn_err(CE_DEBUG, "******** quotacheck failed  ********");
-		cmn_err(CE_DEBUG, "failures = %d", qmtest_nfails);
+		xfs_debug(mp, "******** quotacheck failed  ********");
+		xfs_debug(mp, "failures = %d", qmtest_nfails);
 	} else {
-		cmn_err(CE_DEBUG, "******** quotacheck successful! ********");
+		xfs_debug(mp, "******** quotacheck successful! ********");
 	}
 	kmem_free(qmtest_udqtab);
 	kmem_free(qmtest_gdqtab);
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 7de91d1..2a36487 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -643,8 +643,9 @@ xfs_trans_dqresv(
 	     (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&
 	      (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {
 #ifdef QUOTADEBUG
-		cmn_err(CE_DEBUG, "BLK Res: nblks=%ld + resbcount=%Ld"
-			  " > hardlimit=%Ld?", nblks, *resbcountp, hardlimit);
+		xfs_debug(mp,
+			"BLK Res: nblks=%ld + resbcount=%Ld > hardlimit=%Ld?",
+			nblks, *resbcountp, hardlimit);
 #endif
 		if (nblks > 0) {
 			/*
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
deleted file mode 100644
index 0df8889..0000000
--- a/fs/xfs/support/debug.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include <xfs.h>
-#include "debug.h"
-
-/* xfs_mount.h drags a lot of crap in, sorry.. */
-#include "xfs_sb.h"
-#include "xfs_inum.h"
-#include "xfs_ag.h"
-#include "xfs_mount.h"
-#include "xfs_error.h"
-
-void
-cmn_err(
-	const char	*lvl,
-	const char	*fmt,
-	...)
-{
-	struct va_format vaf;
-	va_list		args;
-
-	va_start(args, fmt);
-	vaf.fmt = fmt;
-	vaf.va = &args;
-
-	printk("%s%pV", lvl, &vaf);
-	va_end(args);
-
-	BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0);
-}
-
-void
-xfs_fs_cmn_err(
-	const char		*lvl,
-	struct xfs_mount	*mp,
-	const char		*fmt,
-	...)
-{
-	struct va_format	vaf;
-	va_list			args;
-
-	va_start(args, fmt);
-	vaf.fmt = fmt;
-	vaf.va = &args;
-
-	printk("%sFilesystem %s: %pV", lvl, mp->m_fsname, &vaf);
-	va_end(args);
-
-	BUG_ON(strncmp(lvl, KERN_EMERG, strlen(KERN_EMERG)) == 0);
-}
-
-/* All callers to xfs_cmn_err use CE_ALERT, so don't bother testing lvl */
-void
-xfs_cmn_err(
-	int			panic_tag,
-	const char		*lvl,
-	struct xfs_mount	*mp,
-	const char		*fmt,
-	...)
-{
-	struct va_format	vaf;
-	va_list			args;
-	int			do_panic = 0;
-
-	if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) {
-		printk(KERN_ALERT "XFS: Transforming an alert into a BUG.");
-		do_panic = 1;
-	}
-
-	va_start(args, fmt);
-	vaf.fmt = fmt;
-	vaf.va = &args;
-
-	printk(KERN_ALERT "Filesystem %s: %pV", mp->m_fsname, &vaf);
-	va_end(args);
-
-	BUG_ON(do_panic);
-}
-
-void
-assfail(char *expr, char *file, int line)
-{
-	printk(KERN_CRIT "Assertion failed: %s, file: %s, line: %d\n", expr,
-	       file, line);
-	BUG();
-}
-
-void
-xfs_hex_dump(void *p, int length)
-{
-	print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_ADDRESS, 16, 1, p, length, 1);
-}
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
deleted file mode 100644
index 05699f6..0000000
--- a/fs/xfs/support/debug.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef	__XFS_SUPPORT_DEBUG_H__
-#define	__XFS_SUPPORT_DEBUG_H__
-
-#include <stdarg.h>
-
-struct xfs_mount;
-
-#define CE_DEBUG        KERN_DEBUG
-#define CE_CONT         KERN_INFO
-#define CE_NOTE         KERN_NOTICE
-#define CE_WARN         KERN_WARNING
-#define CE_ALERT        KERN_ALERT
-#define CE_PANIC        KERN_EMERG
-
-void cmn_err(const char *lvl, const char *fmt, ...)
-		__attribute__ ((format (printf, 2, 3)));
-void xfs_fs_cmn_err( const char *lvl, struct xfs_mount *mp,
-		const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
-void xfs_cmn_err( int panic_tag, const char *lvl, struct xfs_mount *mp,
-		const char *fmt, ...) __attribute__ ((format (printf, 4, 5)));
-
-extern void assfail(char *expr, char *f, int l);
-
-#define ASSERT_ALWAYS(expr)	\
-	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
-
-#ifndef DEBUG
-#define ASSERT(expr)	((void)0)
-
-#ifndef STATIC
-# define STATIC static noinline
-#endif
-
-#else /* DEBUG */
-
-#define ASSERT(expr)	\
-	(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
-
-#ifndef STATIC
-# define STATIC noinline
-#endif
-
-#endif /* DEBUG */
-#endif  /* __XFS_SUPPORT_DEBUG_H__ */
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index f322798..4bc3c64 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -147,10 +147,9 @@ xfs_alloc_get_rec(
  */
 STATIC void
 xfs_alloc_compute_aligned(
+	xfs_alloc_arg_t	*args,		/* allocation argument structure */
 	xfs_agblock_t	foundbno,	/* starting block in found extent */
 	xfs_extlen_t	foundlen,	/* length in found extent */
-	xfs_extlen_t	alignment,	/* alignment for allocation */
-	xfs_extlen_t	minlen,		/* minimum length for allocation */
 	xfs_agblock_t	*resbno,	/* result block number */
 	xfs_extlen_t	*reslen)	/* result length */
 {
@@ -158,8 +157,8 @@ xfs_alloc_compute_aligned(
 	xfs_extlen_t	diff;
 	xfs_extlen_t	len;
 
-	if (alignment > 1 && foundlen >= minlen) {
-		bno = roundup(foundbno, alignment);
+	if (args->alignment > 1 && foundlen >= args->minlen) {
+		bno = roundup(foundbno, args->alignment);
 		diff = bno - foundbno;
 		len = diff >= foundlen ? 0 : foundlen - diff;
 	} else {
@@ -464,6 +463,27 @@ xfs_alloc_read_agfl(
 	return 0;
 }
 
+STATIC int
+xfs_alloc_update_counters(
+	struct xfs_trans	*tp,
+	struct xfs_perag	*pag,
+	struct xfs_buf		*agbp,
+	long			len)
+{
+	struct xfs_agf		*agf = XFS_BUF_TO_AGF(agbp);
+
+	pag->pagf_freeblks += len;
+	be32_add_cpu(&agf->agf_freeblks, len);
+
+	xfs_trans_agblocks_delta(tp, len);
+	if (unlikely(be32_to_cpu(agf->agf_freeblks) >
+		     be32_to_cpu(agf->agf_length)))
+		return EFSCORRUPTED;
+
+	xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
+	return 0;
+}
+
 /*
  * Allocation group level functions.
  */
@@ -505,49 +525,44 @@ xfs_alloc_ag_vextent(
 		ASSERT(0);
 		/* NOTREACHED */
 	}
-	if (error)
+
+	if (error || args->agbno == NULLAGBLOCK)
 		return error;
-	/*
-	 * If the allocation worked, need to change the agf structure
-	 * (and log it), and the superblock.
-	 */
-	if (args->agbno != NULLAGBLOCK) {
-		xfs_agf_t	*agf;	/* allocation group freelist header */
-		long		slen = (long)args->len;
 
-		ASSERT(args->len >= args->minlen && args->len <= args->maxlen);
-		ASSERT(!(args->wasfromfl) || !args->isfl);
-		ASSERT(args->agbno % args->alignment == 0);
-		if (!(args->wasfromfl)) {
-
-			agf = XFS_BUF_TO_AGF(args->agbp);
-			be32_add_cpu(&agf->agf_freeblks, -(args->len));
-			xfs_trans_agblocks_delta(args->tp,
-						 -((long)(args->len)));
-			args->pag->pagf_freeblks -= args->len;
-			ASSERT(be32_to_cpu(agf->agf_freeblks) <=
-				be32_to_cpu(agf->agf_length));
-			xfs_alloc_log_agf(args->tp, args->agbp,
-						XFS_AGF_FREEBLKS);
-			/*
-			 * Search the busylist for these blocks and mark the
-			 * transaction as synchronous if blocks are found. This
-			 * avoids the need to block due to a synchronous log
-			 * force to ensure correct ordering as the synchronous
-			 * transaction will guarantee that for us.
-			 */
-			if (xfs_alloc_busy_search(args->mp, args->agno,
-						args->agbno, args->len))
-				xfs_trans_set_sync(args->tp);
-		}
-		if (!args->isfl)
-			xfs_trans_mod_sb(args->tp,
-				args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS :
-					XFS_TRANS_SB_FDBLOCKS, -slen);
-		XFS_STATS_INC(xs_allocx);
-		XFS_STATS_ADD(xs_allocb, args->len);
+	ASSERT(args->len >= args->minlen);
+	ASSERT(args->len <= args->maxlen);
+	ASSERT(!args->wasfromfl || !args->isfl);
+	ASSERT(args->agbno % args->alignment == 0);
+
+	if (!args->wasfromfl) {
+		error = xfs_alloc_update_counters(args->tp, args->pag,
+						  args->agbp,
+						  -((long)(args->len)));
+		if (error)
+			return error;
+
+		/*
+		 * Search the busylist for these blocks and mark the
+		 * transaction as synchronous if blocks are found. This
+		 * avoids the need to block due to a synchronous log
+		 * force to ensure correct ordering as the synchronous
+		 * transaction will guarantee that for us.
+		 */
+		if (xfs_alloc_busy_search(args->mp, args->agno,
+					args->agbno, args->len))
+			xfs_trans_set_sync(args->tp);
 	}
-	return 0;
+
+	if (!args->isfl) {
+		xfs_trans_mod_sb(args->tp, args->wasdel ?
+				 XFS_TRANS_SB_RES_FDBLOCKS :
+				 XFS_TRANS_SB_FDBLOCKS,
+				 -((long)(args->len)));
+	}
+
+	XFS_STATS_INC(xs_allocx);
+	XFS_STATS_ADD(xs_allocb, args->len);
+	return error;
 }
 
 /*
@@ -693,8 +708,7 @@ xfs_alloc_find_best_extent(
 		if (error)
 			goto error0;
 		XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-		xfs_alloc_compute_aligned(*sbno, *slen, args->alignment,
-					  args->minlen, &bno, slena);
+		xfs_alloc_compute_aligned(args, *sbno, *slen, &bno, slena);
 
 		/*
 		 * The good extent is closer than this one.
@@ -866,8 +880,8 @@ xfs_alloc_ag_vextent_near(
 			if ((error = xfs_alloc_get_rec(cnt_cur, &ltbno, &ltlen, &i)))
 				goto error0;
 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-			xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
-					args->minlen, &ltbnoa, &ltlena);
+			xfs_alloc_compute_aligned(args, ltbno, ltlen,
+						  &ltbnoa, &ltlena);
 			if (ltlena < args->minlen)
 				continue;
 			args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
@@ -987,8 +1001,8 @@ xfs_alloc_ag_vextent_near(
 			if ((error = xfs_alloc_get_rec(bno_cur_lt, &ltbno, &ltlen, &i)))
 				goto error0;
 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-			xfs_alloc_compute_aligned(ltbno, ltlen, args->alignment,
-					args->minlen, &ltbnoa, &ltlena);
+			xfs_alloc_compute_aligned(args, ltbno, ltlen,
+						  &ltbnoa, &ltlena);
 			if (ltlena >= args->minlen)
 				break;
 			if ((error = xfs_btree_decrement(bno_cur_lt, 0, &i)))
@@ -1003,8 +1017,8 @@ xfs_alloc_ag_vextent_near(
 			if ((error = xfs_alloc_get_rec(bno_cur_gt, &gtbno, &gtlen, &i)))
 				goto error0;
 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
-			xfs_alloc_compute_aligned(gtbno, gtlen, args->alignment,
-					args->minlen, &gtbnoa, &gtlena);
+			xfs_alloc_compute_aligned(args, gtbno, gtlen,
+						  &gtbnoa, &gtlena);
 			if (gtlena >= args->minlen)
 				break;
 			if ((error = xfs_btree_increment(bno_cur_gt, 0, &i)))
@@ -1183,8 +1197,7 @@ xfs_alloc_ag_vextent_size(
 	 * once aligned; if not, we search left for something better.
 	 * This can't happen in the second case above.
 	 */
-	xfs_alloc_compute_aligned(fbno, flen, args->alignment, args->minlen,
-		&rbno, &rlen);
+	xfs_alloc_compute_aligned(args, fbno, flen, &rbno, &rlen);
 	rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
 	XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
 			(rlen <= flen && rbno + rlen <= fbno + flen), error0);
@@ -1209,8 +1222,8 @@ xfs_alloc_ag_vextent_size(
 			XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 			if (flen < bestrlen)
 				break;
-			xfs_alloc_compute_aligned(fbno, flen, args->alignment,
-				args->minlen, &rbno, &rlen);
+			xfs_alloc_compute_aligned(args, fbno, flen,
+						  &rbno, &rlen);
 			rlen = XFS_EXTLEN_MIN(args->maxlen, rlen);
 			XFS_WANT_CORRUPTED_GOTO(rlen == 0 ||
 				(rlen <= flen && rbno + rlen <= fbno + flen),
@@ -1388,6 +1401,7 @@ xfs_free_ag_extent(
 	xfs_mount_t	*mp;		/* mount point struct for filesystem */
 	xfs_agblock_t	nbno;		/* new starting block of freespace */
 	xfs_extlen_t	nlen;		/* new length of freespace */
+	xfs_perag_t	*pag;		/* per allocation group data */
 
 	mp = tp->t_mountp;
 	/*
@@ -1586,30 +1600,20 @@ xfs_free_ag_extent(
 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 	xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
 	cnt_cur = NULL;
+
 	/*
 	 * Update the freespace totals in the ag and superblock.
 	 */
-	{
-		xfs_agf_t	*agf;
-		xfs_perag_t	*pag;		/* per allocation group data */
-
-		pag = xfs_perag_get(mp, agno);
-		pag->pagf_freeblks += len;
-		xfs_perag_put(pag);
-
-		agf = XFS_BUF_TO_AGF(agbp);
-		be32_add_cpu(&agf->agf_freeblks, len);
-		xfs_trans_agblocks_delta(tp, len);
-		XFS_WANT_CORRUPTED_GOTO(
-			be32_to_cpu(agf->agf_freeblks) <=
-			be32_to_cpu(agf->agf_length),
-			error0);
-		xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS);
-		if (!isfl)
-			xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
-		XFS_STATS_INC(xs_freex);
-		XFS_STATS_ADD(xs_freeb, len);
-	}
+	pag = xfs_perag_get(mp, agno);
+	error = xfs_alloc_update_counters(tp, pag, agbp, len);
+	xfs_perag_put(pag);
+	if (error)
+		goto error0;
+
+	if (!isfl)
+		xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len);
+	XFS_STATS_INC(xs_freex);
+	XFS_STATS_ADD(xs_freeb, len);
 
 	trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright);
 
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index dc3afd7..fa00788 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2365,6 +2365,13 @@ xfs_bmap_rtalloc(
 	 */
 	if (ralen * mp->m_sb.sb_rextsize >= MAXEXTLEN)
 		ralen = MAXEXTLEN / mp->m_sb.sb_rextsize;
+
+	/*
+	 * Lock out other modifications to the RT bitmap inode.
+	 */
+	xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+	xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
 	/*
 	 * If it's an allocation to an empty file at offset 0,
 	 * pick an extent that will space things out in the rt area.
@@ -3519,7 +3526,7 @@ xfs_bmap_search_extents(
 
 	if (unlikely(!(gotp->br_startblock) && (*lastxp != NULLEXTNUM) &&
 		     !(XFS_IS_REALTIME_INODE(ip) && fork == XFS_DATA_FORK))) {
-		xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+		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",
@@ -4193,12 +4200,11 @@ xfs_bmap_read_extents(
 		num_recs = xfs_btree_get_numrecs(block);
 		if (unlikely(i + num_recs > room)) {
 			ASSERT(i + num_recs <= room);
-			xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+			xfs_warn(ip->i_mount,
 				"corrupt dinode %Lu, (btree extents).",
 				(unsigned long long) ip->i_ino);
-			XFS_ERROR_REPORT("xfs_bmap_read_extents(1)",
-					 XFS_ERRLEVEL_LOW,
-					ip->i_mount);
+			XFS_CORRUPTION_ERROR("xfs_bmap_read_extents(1)",
+				XFS_ERRLEVEL_LOW, ip->i_mount, block);
 			goto error0;
 		}
 		XFS_WANT_CORRUPTED_GOTO(
@@ -5772,7 +5778,7 @@ xfs_check_block(
 			else
 				thispa = XFS_BMBT_PTR_ADDR(mp, block, j, dmxr);
 			if (*thispa == *pp) {
-				cmn_err(CE_WARN, "%s: thispa(%d) == pp(%d) %Ld",
+				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",
@@ -5937,11 +5943,11 @@ xfs_bmap_check_leaf_extents(
 	return;
 
 error0:
-	cmn_err(CE_WARN, "%s: at error0", __func__);
+	xfs_warn(mp, "%s: at error0", __func__);
 	if (bp_release)
 		xfs_trans_brelse(NULL, bp);
 error_norelse:
-	cmn_err(CE_WARN, "%s: BAD after btree leaves for %d extents",
+	xfs_warn(mp, "%s: BAD after btree leaves for %d extents",
 		__func__, i);
 	panic("%s: CORRUPTED BTREE OR SOMETHING", __func__);
 	return;
@@ -6144,7 +6150,7 @@ xfs_bmap_punch_delalloc_range(
 		if (error) {
 			/* something screwed, just bail */
 			if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-				xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+				xfs_alert(ip->i_mount,
 			"Failed delalloc mapping lookup ino %lld fsb %lld.",
 						ip->i_ino, start_fsb);
 			}
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 6f8c21c..e5413d9 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -130,10 +130,12 @@ xfs_buf_item_log_check(
 	orig = bip->bli_orig;
 	buffer = XFS_BUF_PTR(bp);
 	for (x = 0; x < XFS_BUF_COUNT(bp); x++) {
-		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x))
-			cmn_err(CE_PANIC,
-	"xfs_buf_item_log_check bip %x buffer %x orig %x index %d",
-				bip, bp, orig, x);
+		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x)) {
+			xfs_emerg(bp->b_mount,
+				"%s: bip %x buffer %x orig %x index %d",
+				__func__, bip, bp, orig, x);
+			ASSERT(0);
+		}
 	}
 }
 #else
@@ -983,10 +985,9 @@ xfs_buf_iodone_callbacks(
 	if (XFS_BUF_TARGET(bp) != lasttarg ||
 	    time_after(jiffies, (lasttime + 5*HZ))) {
 		lasttime = jiffies;
-		cmn_err(CE_ALERT, "Device %s, XFS metadata write error"
-				" block 0x%llx in %s",
+		xfs_alert(mp, "Device %s: metadata write error block 0x%llx",
 			XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
-		      (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname);
+		      (__uint64_t)XFS_BUF_ADDR(bp));
 	}
 	lasttarg = XFS_BUF_TARGET(bp);
 
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 1c00bed..6102ac6 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -1995,13 +1995,12 @@ xfs_da_do_buf(
 		error = mappedbno == -2 ? 0 : XFS_ERROR(EFSCORRUPTED);
 		if (unlikely(error == EFSCORRUPTED)) {
 			if (xfs_error_level >= XFS_ERRLEVEL_LOW) {
-				cmn_err(CE_ALERT, "xfs_da_do_buf: bno %lld\n",
-					(long long)bno);
-				cmn_err(CE_ALERT, "dir: inode %lld\n",
+				xfs_alert(mp, "%s: bno %lld dir: inode %lld",
+					__func__, (long long)bno,
 					(long long)dp->i_ino);
 				for (i = 0; i < nmap; i++) {
-					cmn_err(CE_ALERT,
-						"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d\n",
+					xfs_alert(mp,
+"[%02d] br_startoff %lld br_startblock %lld br_blockcount %lld br_state %d",
 						i,
 						(long long)mapp[i].br_startoff,
 						(long long)mapp[i].br_startblock,
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index e60490b..be62867 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -270,9 +270,9 @@ xfs_swap_extents(
 	/* check inode formats now that data is flushed */
 	error = xfs_swap_extents_check_format(ip, tip);
 	if (error) {
-		xfs_fs_cmn_err(CE_NOTE, mp,
+		xfs_notice(mp,
 		    "%s: inode 0x%llx format is incompatible for exchanging.",
-				__FILE__, ip->i_ino);
+				__func__, ip->i_ino);
 		goto out_unlock;
 	}
 
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index a1321bc..dba7a71 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -159,7 +159,7 @@ xfs_dir_ino_validate(
 		XFS_AGINO_TO_INO(mp, agno, agino) == ino;
 	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
 			XFS_RANDOM_DIR_INO_VALIDATE))) {
-		xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
+		xfs_warn(mp, "Invalid inode number 0x%Lx",
 				(unsigned long long) ino);
 		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
 		return XFS_ERROR(EFSCORRUPTED);
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index f9a0864..a0aab7d 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -899,10 +899,9 @@ xfs_dir2_leafn_rebalance(
 	if(blk2->index < 0) {
 		state->inleaf = 1;
 		blk2->index = 0;
-		cmn_err(CE_ALERT,
-			"xfs_dir2_leafn_rebalance: picked the wrong leaf? reverting original leaf: "
-			"blk1->index %d\n",
-			blk1->index);
+		xfs_alert(args->dp->i_mount,
+	"%s: picked the wrong leaf? reverting original leaf: blk1->index %d\n",
+			__func__, blk1->index);
 	}
 }
 
@@ -1641,26 +1640,22 @@ xfs_dir2_node_addname_int(
 			}
 
 			if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
-				cmn_err(CE_ALERT,
-					"xfs_dir2_node_addname_int: dir ino "
-					"%llu needed freesp block %lld for\n"
-					"  data block %lld, got %lld\n"
-					"  ifbno %llu lastfbno %d\n",
-					(unsigned long long)dp->i_ino,
+				xfs_alert(mp,
+			"%s: dir ino " "%llu needed freesp block %lld for\n"
+			"  data block %lld, got %lld ifbno %llu lastfbno %d",
+					__func__, (unsigned long long)dp->i_ino,
 					(long long)xfs_dir2_db_to_fdb(mp, dbno),
 					(long long)dbno, (long long)fbno,
 					(unsigned long long)ifbno, lastfbno);
 				if (fblk) {
-					cmn_err(CE_ALERT,
-						" fblk 0x%p blkno %llu "
-						"index %d magic 0x%x\n",
+					xfs_alert(mp,
+				" fblk 0x%p blkno %llu index %d magic 0x%x",
 						fblk,
 						(unsigned long long)fblk->blkno,
 						fblk->index,
 						fblk->magic);
 				} else {
-					cmn_err(CE_ALERT,
-						" ... fblk is NULL\n");
+					xfs_alert(mp, " ... fblk is NULL");
 				}
 				XFS_ERROR_REPORT("xfs_dir2_node_addname_int",
 						 XFS_ERRLEVEL_LOW, mp);
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 4c7db74..39f0633 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -48,7 +48,7 @@ xfs_error_trap(int e)
 			break;
 		if (e != xfs_etrap[i])
 			continue;
-		cmn_err(CE_NOTE, "xfs_error_trap: error %d", e);
+		xfs_notice(NULL, "%s: error %d", __func__, e);
 		BUG();
 		break;
 	}
@@ -74,7 +74,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression,
 
 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
 		if (xfs_etest[i] == error_tag && xfs_etest_fsid[i] == fsid) {
-			cmn_err(CE_WARN,
+			xfs_warn(NULL,
 	"Injecting error (%s) at file %s, line %d, on filesystem \"%s\"",
 				expression, file, line, xfs_etest_fsname[i]);
 			return 1;
@@ -95,14 +95,14 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
 
 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
 		if (xfs_etest_fsid[i] == fsid && xfs_etest[i] == error_tag) {
-			cmn_err(CE_WARN, "XFS error tag #%d on", error_tag);
+			xfs_warn(mp, "error tag #%d on", error_tag);
 			return 0;
 		}
 	}
 
 	for (i = 0; i < XFS_NUM_INJECT_ERROR; i++)  {
 		if (xfs_etest[i] == 0) {
-			cmn_err(CE_WARN, "Turned on XFS error tag #%d",
+			xfs_warn(mp, "Turned on XFS error tag #%d",
 				error_tag);
 			xfs_etest[i] = error_tag;
 			xfs_etest_fsid[i] = fsid;
@@ -114,7 +114,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp)
 		}
 	}
 
-	cmn_err(CE_WARN, "error tag overflow, too many turned on");
+	xfs_warn(mp, "error tag overflow, too many turned on");
 
 	return 1;
 }
@@ -133,7 +133,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
 		if ((fsid == 0LL || xfs_etest_fsid[i] == fsid) &&
 		     xfs_etest[i] != 0) {
 			cleared = 1;
-			cmn_err(CE_WARN, "Clearing XFS error tag #%d",
+			xfs_warn(mp, "Clearing XFS error tag #%d",
 				xfs_etest[i]);
 			xfs_etest[i] = 0;
 			xfs_etest_fsid[i] = 0LL;
@@ -144,9 +144,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud)
 	}
 
 	if (loud || cleared)
-		cmn_err(CE_WARN,
-			"Cleared all XFS error tags for filesystem \"%s\"",
-			mp->m_fsname);
+		xfs_warn(mp, "Cleared all XFS error tags for filesystem");
 
 	return 0;
 }
@@ -162,9 +160,8 @@ xfs_error_report(
 	inst_t			*ra)
 {
 	if (level <= xfs_error_level) {
-		xfs_cmn_err(XFS_PTAG_ERROR_REPORT,
-			    CE_ALERT, mp,
-		"XFS internal error %s at line %d of file %s.  Caller 0x%p\n",
+		xfs_alert_tag(mp, XFS_PTAG_ERROR_REPORT,
+		"Internal error %s at line %d of file %s.  Caller 0x%p\n",
 			    tag, linenum, filename, ra);
 
 		xfs_stack_trace();
@@ -184,4 +181,5 @@ xfs_corruption_error(
 	if (level <= xfs_error_level)
 		xfs_hex_dump(p, 16);
 	xfs_error_report(tag, level, mp, filename, linenum, ra);
+	xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
 }
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 10dce54..079a367 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -145,10 +145,8 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);
 #endif /* DEBUG */
 
 /*
- * XFS panic tags -- allow a call to xfs_cmn_err() be turned into
- *			a panic by setting xfs_panic_mask in a
- *			sysctl.  update xfs_max[XFS_PARAM] if
- *			more are added.
+ * XFS panic tags -- allow a call to xfs_alert_tag() be turned into
+ *			a panic by setting xfs_panic_mask in a sysctl.
  */
 #define		XFS_NO_PTAG			0
 #define		XFS_PTAG_IFLUSH			0x00000001
@@ -160,17 +158,4 @@ extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud);
 #define		XFS_PTAG_SHUTDOWN_LOGERROR	0x00000040
 #define		XFS_PTAG_FSBLOCK_ZERO		0x00000080
 
-struct xfs_mount;
-
-extern void xfs_hex_dump(void *p, int length);
-
-#define xfs_fs_repair_cmn_err(level, mp, fmt, args...) \
-	xfs_fs_cmn_err(level, mp, fmt "  Unmount and run xfs_repair.", ## args)
-
-#define xfs_fs_mount_cmn_err(f, fmt, args...) \
-	do { \
-		if (!(f & XFS_MFSI_QUIET)) 	\
-			cmn_err(CE_WARN, "XFS: " fmt, ## args); \
-	} while (0)
-
 #endif	/* __XFS_ERROR_H__ */
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 85668ef..9153d2c 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -385,8 +385,8 @@ xfs_growfs_data_private(
 				  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
 				  XFS_FSS_TO_BB(mp, 1), 0, &bp);
 		if (error) {
-			xfs_fs_cmn_err(CE_WARN, mp,
-			"error %d reading secondary superblock for ag %d",
+			xfs_warn(mp,
+		"error %d reading secondary superblock for ag %d",
 				error, agno);
 			break;
 		}
@@ -399,7 +399,7 @@ xfs_growfs_data_private(
 		if (!(error = xfs_bwrite(mp, bp))) {
 			continue;
 		} else {
-			xfs_fs_cmn_err(CE_WARN, mp,
+			xfs_warn(mp,
 		"write error %d updating secondary superblock for ag %d",
 				error, agno);
 			break; /* no point in continuing */
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index 0626a32..84ebeec 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -1055,28 +1055,23 @@ xfs_difree(
 	 */
 	agno = XFS_INO_TO_AGNO(mp, inode);
 	if (agno >= mp->m_sb.sb_agcount)  {
-		cmn_err(CE_WARN,
-			"xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s.  Returning EINVAL.",
-			agno, mp->m_sb.sb_agcount, mp->m_fsname);
+		xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).",
+			__func__, agno, mp->m_sb.sb_agcount);
 		ASSERT(0);
 		return XFS_ERROR(EINVAL);
 	}
 	agino = XFS_INO_TO_AGINO(mp, inode);
 	if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {
-		cmn_err(CE_WARN,
-			"xfs_difree: inode != XFS_AGINO_TO_INO() "
-			"(%llu != %llu) on %s.  Returning EINVAL.",
-			(unsigned long long)inode,
-			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino),
-			mp->m_fsname);
+		xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).",
+			__func__, (unsigned long long)inode,
+			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino));
 		ASSERT(0);
 		return XFS_ERROR(EINVAL);
 	}
 	agbno = XFS_AGINO_TO_AGBNO(mp, agino);
 	if (agbno >= mp->m_sb.sb_agblocks)  {
-		cmn_err(CE_WARN,
-			"xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s.  Returning EINVAL.",
-			agbno, mp->m_sb.sb_agblocks, mp->m_fsname);
+		xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
+			__func__, agbno, mp->m_sb.sb_agblocks);
 		ASSERT(0);
 		return XFS_ERROR(EINVAL);
 	}
@@ -1085,9 +1080,8 @@ xfs_difree(
 	 */
 	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
 	if (error) {
-		cmn_err(CE_WARN,
-			"xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s.  Returning error.",
-			error, mp->m_fsname);
+		xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
+			__func__, error);
 		return error;
 	}
 	agi = XFS_BUF_TO_AGI(agbp);
@@ -1106,17 +1100,15 @@ xfs_difree(
 	 * Look for the entry describing this inode.
 	 */
 	if ((error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &i))) {
-		cmn_err(CE_WARN,
-			"xfs_difree: xfs_inobt_lookup returned()  an error %d on %s.  Returning error.",
-			error, mp->m_fsname);
+		xfs_warn(mp, "%s: xfs_inobt_lookup() returned error %d.",
+			__func__, error);
 		goto error0;
 	}
 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
 	error = xfs_inobt_get_rec(cur, &rec, &i);
 	if (error) {
-		cmn_err(CE_WARN,
-			"xfs_difree: xfs_inobt_get_rec()  returned an error %d on %s.  Returning error.",
-			error, mp->m_fsname);
+		xfs_warn(mp, "%s: xfs_inobt_get_rec() returned error %d.",
+			__func__, error);
 		goto error0;
 	}
 	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
@@ -1157,8 +1149,8 @@ xfs_difree(
 		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
 
 		if ((error = xfs_btree_delete(cur, &i))) {
-			cmn_err(CE_WARN, "xfs_difree: xfs_btree_delete returned an error %d on %s.\n",
-				error, mp->m_fsname);
+			xfs_warn(mp, "%s: xfs_btree_delete returned error %d.",
+				__func__, error);
 			goto error0;
 		}
 
@@ -1170,9 +1162,8 @@ xfs_difree(
 
 		error = xfs_inobt_update(cur, &rec);
 		if (error) {
-			cmn_err(CE_WARN,
-	"xfs_difree: xfs_inobt_update returned an error %d on %s.",
-				error, mp->m_fsname);
+			xfs_warn(mp, "%s: xfs_inobt_update returned error %d.",
+				__func__, error);
 			goto error0;
 		}
 
@@ -1218,10 +1209,9 @@ xfs_imap_lookup(
 
 	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
 	if (error) {
-		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-				"xfs_ialloc_read_agi() returned "
-				"error %d, agno %d",
-				error, agno);
+		xfs_alert(mp,
+			"%s: xfs_ialloc_read_agi() returned error %d, agno %d",
+			__func__, error, agno);
 		return error;
 	}
 
@@ -1299,24 +1289,21 @@ xfs_imap(
 		if (flags & XFS_IGET_UNTRUSTED)
 			return XFS_ERROR(EINVAL);
 		if (agno >= mp->m_sb.sb_agcount) {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-					"xfs_imap: agno (%d) >= "
-					"mp->m_sb.sb_agcount (%d)",
-					agno,  mp->m_sb.sb_agcount);
+			xfs_alert(mp,
+				"%s: agno (%d) >= mp->m_sb.sb_agcount (%d)",
+				__func__, agno, mp->m_sb.sb_agcount);
 		}
 		if (agbno >= mp->m_sb.sb_agblocks) {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-					"xfs_imap: agbno (0x%llx) >= "
-					"mp->m_sb.sb_agblocks (0x%lx)",
-					(unsigned long long) agbno,
-					(unsigned long) mp->m_sb.sb_agblocks);
+			xfs_alert(mp,
+		"%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)",
+				__func__, (unsigned long long)agbno,
+				(unsigned long)mp->m_sb.sb_agblocks);
 		}
 		if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-					"xfs_imap: ino (0x%llx) != "
-					"XFS_AGINO_TO_INO(mp, agno, agino) "
-					"(0x%llx)",
-					ino, XFS_AGINO_TO_INO(mp, agno, agino));
+			xfs_alert(mp,
+		"%s: ino (0x%llx) != XFS_AGINO_TO_INO() (0x%llx)",
+				__func__, ino,
+				XFS_AGINO_TO_INO(mp, agno, agino));
 		}
 		xfs_stack_trace();
 #endif /* DEBUG */
@@ -1388,10 +1375,9 @@ out_map:
 	 */
 	if ((imap->im_blkno + imap->im_len) >
 	    XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)) {
-		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_imap: "
-			"(imap->im_blkno (0x%llx) + imap->im_len (0x%llx)) > "
-			" XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) (0x%llx)",
-			(unsigned long long) imap->im_blkno,
+		xfs_alert(mp,
+	"%s: (im_blkno (0x%llx) + im_len (0x%llx)) > sb_dblocks (0x%llx)",
+			__func__, (unsigned long long) imap->im_blkno,
 			(unsigned long long) imap->im_len,
 			XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks));
 		return XFS_ERROR(EINVAL);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index be7cf62..da871f5 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -110,8 +110,8 @@ xfs_inobp_check(
 		dip = (xfs_dinode_t *)xfs_buf_offset(bp,
 					i * mp->m_sb.sb_inodesize);
 		if (!dip->di_next_unlinked)  {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-				"Detected a bogus zero next_unlinked field in incore inode buffer 0x%p.  About to pop an ASSERT.",
+			xfs_alert(mp,
+	"Detected bogus zero next_unlinked field in incore inode buffer 0x%p.",
 				bp);
 			ASSERT(dip->di_next_unlinked);
 		}
@@ -142,10 +142,9 @@ xfs_imap_to_bp(
 				   (int)imap->im_len, buf_flags, &bp);
 	if (error) {
 		if (error != EAGAIN) {
-			cmn_err(CE_WARN,
-				"xfs_imap_to_bp: xfs_trans_read_buf()returned "
-				"an error %d on %s.  Returning error.",
-				error, mp->m_fsname);
+			xfs_warn(mp,
+				"%s: xfs_trans_read_buf() returned error %d.",
+				__func__, error);
 		} else {
 			ASSERT(buf_flags & XBF_TRYLOCK);
 		}
@@ -180,12 +179,11 @@ xfs_imap_to_bp(
 			XFS_CORRUPTION_ERROR("xfs_imap_to_bp",
 						XFS_ERRLEVEL_HIGH, mp, dip);
 #ifdef DEBUG
-			cmn_err(CE_PANIC,
-					"Device %s - bad inode magic/vsn "
-					"daddr %lld #%d (magic=%x)",
-				XFS_BUFTARG_NAME(mp->m_ddev_targp),
+			xfs_emerg(mp,
+				"bad inode magic/vsn daddr %lld #%d (magic=%x)",
 				(unsigned long long)imap->im_blkno, i,
 				be16_to_cpu(dip->di_magic));
+			ASSERT(0);
 #endif
 			xfs_trans_brelse(tp, bp);
 			return XFS_ERROR(EFSCORRUPTED);
@@ -317,7 +315,7 @@ xfs_iformat(
 	if (unlikely(be32_to_cpu(dip->di_nextents) +
 		     be16_to_cpu(dip->di_anextents) >
 		     be64_to_cpu(dip->di_nblocks))) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+		xfs_warn(ip->i_mount,
 			"corrupt dinode %Lu, extent total = %d, nblocks = %Lu.",
 			(unsigned long long)ip->i_ino,
 			(int)(be32_to_cpu(dip->di_nextents) +
@@ -330,8 +328,7 @@ xfs_iformat(
 	}
 
 	if (unlikely(dip->di_forkoff > ip->i_mount->m_sb.sb_inodesize)) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt dinode %Lu, forkoff = 0x%x.",
+		xfs_warn(ip->i_mount, "corrupt dinode %Lu, forkoff = 0x%x.",
 			(unsigned long long)ip->i_ino,
 			dip->di_forkoff);
 		XFS_CORRUPTION_ERROR("xfs_iformat(2)", XFS_ERRLEVEL_LOW,
@@ -341,7 +338,7 @@ xfs_iformat(
 
 	if (unlikely((ip->i_d.di_flags & XFS_DIFLAG_REALTIME) &&
 		     !ip->i_mount->m_rtdev_targp)) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
+		xfs_warn(ip->i_mount,
 			"corrupt dinode %Lu, has realtime flag set.",
 			ip->i_ino);
 		XFS_CORRUPTION_ERROR("xfs_iformat(realtime)",
@@ -373,9 +370,8 @@ xfs_iformat(
 			 * no local regular files yet
 			 */
 			if (unlikely((be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFREG)) {
-				xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-					"corrupt inode %Lu "
-					"(local format for regular file).",
+				xfs_warn(ip->i_mount,
+			"corrupt inode %Lu (local format for regular file).",
 					(unsigned long long) ip->i_ino);
 				XFS_CORRUPTION_ERROR("xfs_iformat(4)",
 						     XFS_ERRLEVEL_LOW,
@@ -385,9 +381,8 @@ xfs_iformat(
 
 			di_size = be64_to_cpu(dip->di_size);
 			if (unlikely(di_size > XFS_DFORK_DSIZE(dip, ip->i_mount))) {
-				xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-					"corrupt inode %Lu "
-					"(bad size %Ld for local inode).",
+				xfs_warn(ip->i_mount,
+			"corrupt inode %Lu (bad size %Ld for local inode).",
 					(unsigned long long) ip->i_ino,
 					(long long) di_size);
 				XFS_CORRUPTION_ERROR("xfs_iformat(5)",
@@ -431,9 +426,8 @@ xfs_iformat(
 		size = be16_to_cpu(atp->hdr.totsize);
 
 		if (unlikely(size < sizeof(struct xfs_attr_sf_hdr))) {
-			xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-				"corrupt inode %Lu "
-				"(bad attr fork size %Ld).",
+			xfs_warn(ip->i_mount,
+				"corrupt inode %Lu (bad attr fork size %Ld).",
 				(unsigned long long) ip->i_ino,
 				(long long) size);
 			XFS_CORRUPTION_ERROR("xfs_iformat(8)",
@@ -488,9 +482,8 @@ xfs_iformat_local(
 	 * kmem_alloc() or memcpy() below.
 	 */
 	if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt inode %Lu "
-			"(bad size %d for local fork, size = %d).",
+		xfs_warn(ip->i_mount,
+	"corrupt inode %Lu (bad size %d for local fork, size = %d).",
 			(unsigned long long) ip->i_ino, size,
 			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
 		XFS_CORRUPTION_ERROR("xfs_iformat_local", XFS_ERRLEVEL_LOW,
@@ -547,8 +540,7 @@ xfs_iformat_extents(
 	 * kmem_alloc() or memcpy() below.
 	 */
 	if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt inode %Lu ((a)extents = %d).",
+		xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
 			(unsigned long long) ip->i_ino, nex);
 		XFS_CORRUPTION_ERROR("xfs_iformat_extents(1)", XFS_ERRLEVEL_LOW,
 				     ip->i_mount, dip);
@@ -623,11 +615,10 @@ xfs_iformat_btree(
 	    || XFS_BMDR_SPACE_CALC(nrecs) >
 			XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)
 	    || XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks)) {
-		xfs_fs_repair_cmn_err(CE_WARN, ip->i_mount,
-			"corrupt inode %Lu (btree).",
+		xfs_warn(ip->i_mount, "corrupt inode %Lu (btree).",
 			(unsigned long long) ip->i_ino);
-		XFS_ERROR_REPORT("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
-				 ip->i_mount);
+		XFS_CORRUPTION_ERROR("xfs_iformat_btree", XFS_ERRLEVEL_LOW,
+				 ip->i_mount, dip);
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -813,11 +804,9 @@ xfs_iread(
 	 */
 	if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC) {
 #ifdef DEBUG
-		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
-				"dip->di_magic (0x%x) != "
-				"XFS_DINODE_MAGIC (0x%x)",
-				be16_to_cpu(dip->di_magic),
-				XFS_DINODE_MAGIC);
+		xfs_alert(mp,
+			"%s: dip->di_magic (0x%x) != XFS_DINODE_MAGIC (0x%x)",
+			__func__, be16_to_cpu(dip->di_magic), XFS_DINODE_MAGIC);
 #endif /* DEBUG */
 		error = XFS_ERROR(EINVAL);
 		goto out_brelse;
@@ -835,9 +824,8 @@ xfs_iread(
 		error = xfs_iformat(ip, dip);
 		if (error)  {
 #ifdef DEBUG
-			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_iread: "
-					"xfs_iformat() returned error %d",
-					error);
+			xfs_alert(mp, "%s: xfs_iformat() returned error %d",
+				__func__, error);
 #endif /* DEBUG */
 			goto out_brelse;
 		}
@@ -1016,8 +1004,8 @@ xfs_ialloc(
 	 * This is because we're setting fields here we need
 	 * to prevent others from looking at until we're done.
 	 */
-	error = xfs_trans_iget(tp->t_mountp, tp, ino,
-				XFS_IGET_CREATE, XFS_ILOCK_EXCL, &ip);
+	error = xfs_iget(tp->t_mountp, tp, ino, XFS_IGET_CREATE,
+			 XFS_ILOCK_EXCL, &ip);
 	if (error)
 		return error;
 	ASSERT(ip != NULL);
@@ -1166,6 +1154,7 @@ xfs_ialloc(
 	/*
 	 * Log the new values stuffed into the inode.
 	 */
+	xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
 	xfs_trans_log_inode(tp, ip, flags);
 
 	/* now that we have an i_mode we can setup inode ops and unlock */
@@ -1820,9 +1809,8 @@ xfs_iunlink_remove(
 		 */
 		error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
 		if (error) {
-			cmn_err(CE_WARN,
-				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
-				error, mp->m_fsname);
+			xfs_warn(mp, "%s: xfs_itobp() returned error %d.",
+				__func__, error);
 			return error;
 		}
 		next_agino = be32_to_cpu(dip->di_next_unlinked);
@@ -1867,9 +1855,9 @@ xfs_iunlink_remove(
 			error = xfs_inotobp(mp, tp, next_ino, &last_dip,
 					    &last_ibp, &last_offset, 0);
 			if (error) {
-				cmn_err(CE_WARN,
-			"xfs_iunlink_remove: xfs_inotobp()  returned an error %d on %s.  Returning error.",
-					error, mp->m_fsname);
+				xfs_warn(mp,
+					"%s: xfs_inotobp() returned error %d.",
+					__func__, error);
 				return error;
 			}
 			next_agino = be32_to_cpu(last_dip->di_next_unlinked);
@@ -1882,9 +1870,8 @@ xfs_iunlink_remove(
 		 */
 		error = xfs_itobp(mp, tp, ip, &dip, &ibp, XBF_LOCK);
 		if (error) {
-			cmn_err(CE_WARN,
-				"xfs_iunlink_remove: xfs_itobp()  returned an error %d on %s.  Returning error.",
-				error, mp->m_fsname);
+			xfs_warn(mp, "%s: xfs_itobp(2) returned error %d.",
+				__func__, error);
 			return error;
 		}
 		next_agino = be32_to_cpu(dip->di_next_unlinked);
@@ -2939,16 +2926,16 @@ xfs_iflush_int(
 
 	if (XFS_TEST_ERROR(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC,
 			       mp, XFS_ERRTAG_IFLUSH_1, XFS_RANDOM_IFLUSH_1)) {
-		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-		    "xfs_iflush: Bad inode %Lu magic number 0x%x, ptr 0x%p",
-			ip->i_ino, be16_to_cpu(dip->di_magic), dip);
+		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+			"%s: Bad inode %Lu magic number 0x%x, ptr 0x%p",
+			__func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip);
 		goto corrupt_out;
 	}
 	if (XFS_TEST_ERROR(ip->i_d.di_magic != XFS_DINODE_MAGIC,
 				mp, XFS_ERRTAG_IFLUSH_2, XFS_RANDOM_IFLUSH_2)) {
-		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-			"xfs_iflush: Bad inode %Lu, ptr 0x%p, magic number 0x%x",
-			ip->i_ino, ip, ip->i_d.di_magic);
+		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+			"%s: Bad inode %Lu, ptr 0x%p, magic number 0x%x",
+			__func__, ip->i_ino, ip, ip->i_d.di_magic);
 		goto corrupt_out;
 	}
 	if ((ip->i_d.di_mode & S_IFMT) == S_IFREG) {
@@ -2956,9 +2943,9 @@ xfs_iflush_int(
 		    (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS) &&
 		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE),
 		    mp, XFS_ERRTAG_IFLUSH_3, XFS_RANDOM_IFLUSH_3)) {
-			xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-				"xfs_iflush: Bad regular inode %Lu, ptr 0x%p",
-				ip->i_ino, ip);
+			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+				"%s: Bad regular inode %Lu, ptr 0x%p",
+				__func__, ip->i_ino, ip);
 			goto corrupt_out;
 		}
 	} else if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
@@ -2967,28 +2954,28 @@ xfs_iflush_int(
 		    (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) &&
 		    (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL),
 		    mp, XFS_ERRTAG_IFLUSH_4, XFS_RANDOM_IFLUSH_4)) {
-			xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-				"xfs_iflush: Bad directory inode %Lu, ptr 0x%p",
-				ip->i_ino, ip);
+			xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+				"%s: Bad directory inode %Lu, ptr 0x%p",
+				__func__, ip->i_ino, ip);
 			goto corrupt_out;
 		}
 	}
 	if (XFS_TEST_ERROR(ip->i_d.di_nextents + ip->i_d.di_anextents >
 				ip->i_d.di_nblocks, mp, XFS_ERRTAG_IFLUSH_5,
 				XFS_RANDOM_IFLUSH_5)) {
-		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-			"xfs_iflush: detected corrupt incore inode %Lu, total extents = %d, nblocks = %Ld, ptr 0x%p",
-			ip->i_ino,
+		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+			"%s: detected corrupt incore inode %Lu, "
+			"total extents = %d, nblocks = %Ld, ptr 0x%p",
+			__func__, ip->i_ino,
 			ip->i_d.di_nextents + ip->i_d.di_anextents,
-			ip->i_d.di_nblocks,
-			ip);
+			ip->i_d.di_nblocks, ip);
 		goto corrupt_out;
 	}
 	if (XFS_TEST_ERROR(ip->i_d.di_forkoff > mp->m_sb.sb_inodesize,
 				mp, XFS_ERRTAG_IFLUSH_6, XFS_RANDOM_IFLUSH_6)) {
-		xfs_cmn_err(XFS_PTAG_IFLUSH, CE_ALERT, mp,
-			"xfs_iflush: bad inode %Lu, forkoff 0x%x, ptr 0x%p",
-			ip->i_ino, ip->i_d.di_forkoff, ip);
+		xfs_alert_tag(mp, XFS_PTAG_IFLUSH,
+			"%s: bad inode %Lu, forkoff 0x%x, ptr 0x%p",
+			__func__, ip->i_ino, ip->i_d.di_forkoff, ip);
 		goto corrupt_out;
 	}
 	/*
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 5c95fa8..f753200 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -409,28 +409,35 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
 /*
  * Flags for lockdep annotations.
  *
- * XFS_I[O]LOCK_PARENT - for operations that require locking two inodes
- * (ie directory operations that require locking a directory inode and
- * an entry inode).  The first inode gets locked with this flag so it
- * gets a lockdep subclass of 1 and the second lock will have a lockdep
- * subclass of 0.
+ * XFS_LOCK_PARENT - for directory operations that require locking a
+ * parent directory inode and a child entry inode.  The parent gets locked
+ * with this flag so it gets a lockdep subclass of 1 and the child entry
+ * lock will have a lockdep subclass of 0.
+ *
+ * XFS_LOCK_RTBITMAP/XFS_LOCK_RTSUM - the realtime device bitmap and summary
+ * inodes do not participate in the normal lock order, and thus have their
+ * own subclasses.
  *
  * XFS_LOCK_INUMORDER - for locking several inodes at the some time
  * with xfs_lock_inodes().  This flag is used as the starting subclass
  * and each subsequent lock acquired will increment the subclass by one.
- * So the first lock acquired will have a lockdep subclass of 2, the
- * second lock will have a lockdep subclass of 3, and so on. It is
+ * So the first lock acquired will have a lockdep subclass of 4, the
+ * second lock will have a lockdep subclass of 5, and so on. It is
  * the responsibility of the class builder to shift this to the correct
  * portion of the lock_mode lockdep mask.
  */
 #define XFS_LOCK_PARENT		1
-#define XFS_LOCK_INUMORDER	2
+#define XFS_LOCK_RTBITMAP	2
+#define XFS_LOCK_RTSUM		3
+#define XFS_LOCK_INUMORDER	4
 
 #define XFS_IOLOCK_SHIFT	16
 #define	XFS_IOLOCK_PARENT	(XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT)
 
 #define XFS_ILOCK_SHIFT		24
 #define	XFS_ILOCK_PARENT	(XFS_LOCK_PARENT << XFS_ILOCK_SHIFT)
+#define	XFS_ILOCK_RTBITMAP	(XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT)
+#define	XFS_ILOCK_RTSUM		(XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT)
 
 #define XFS_IOLOCK_DEP_MASK	0x00ff0000
 #define XFS_ILOCK_DEP_MASK	0xff000000
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 8a0f044..091d82b 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -101,11 +101,11 @@ xfs_iomap_eof_align_last_fsb(
 }
 
 STATIC int
-xfs_cmn_err_fsblock_zero(
+xfs_alert_fsblock_zero(
 	xfs_inode_t	*ip,
 	xfs_bmbt_irec_t	*imap)
 {
-	xfs_cmn_err(XFS_PTAG_FSBLOCK_ZERO, CE_ALERT, ip->i_mount,
+	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\n",
@@ -246,7 +246,7 @@ xfs_iomap_write_direct(
 	}
 
 	if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) {
-		error = xfs_cmn_err_fsblock_zero(ip, imap);
+		error = xfs_alert_fsblock_zero(ip, imap);
 		goto error_out;
 	}
 
@@ -464,7 +464,7 @@ retry:
 	}
 
 	if (!(imap[0].br_startblock || XFS_IS_REALTIME_INODE(ip)))
-		return xfs_cmn_err_fsblock_zero(ip, &imap[0]);
+		return xfs_alert_fsblock_zero(ip, &imap[0]);
 
 	*ret_imap = imap[0];
 	return 0;
@@ -614,7 +614,7 @@ xfs_iomap_write_allocate(
 		 * covers at least part of the callers request
 		 */
 		if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip)))
-			return xfs_cmn_err_fsblock_zero(ip, imap);
+			return xfs_alert_fsblock_zero(ip, imap);
 
 		if ((offset_fsb >= imap->br_startoff) &&
 		    (offset_fsb < (imap->br_startoff +
@@ -724,7 +724,7 @@ xfs_iomap_write_unwritten(
 			return XFS_ERROR(error);
 
 		if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip)))
-			return xfs_cmn_err_fsblock_zero(ip, &imap);
+			return xfs_alert_fsblock_zero(ip, &imap);
 
 		if ((numblks_fsb = imap.br_blockcount) == 0) {
 			/*
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index ae6fef1..25efa9b 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -374,11 +374,10 @@ xfs_log_mount(
 	int		error;
 
 	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY))
-		cmn_err(CE_NOTE, "XFS mounting filesystem %s", mp->m_fsname);
+		xfs_notice(mp, "Mounting Filesystem");
 	else {
-		cmn_err(CE_NOTE,
-			"Mounting filesystem \"%s\" in no-recovery mode.  Filesystem will be inconsistent.",
-			mp->m_fsname);
+		xfs_notice(mp,
+"Mounting filesystem in no-recovery mode.  Filesystem will be inconsistent.");
 		ASSERT(mp->m_flags & XFS_MOUNT_RDONLY);
 	}
 
@@ -393,7 +392,7 @@ xfs_log_mount(
 	 */
 	error = xfs_trans_ail_init(mp);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error);
+		xfs_warn(mp, "AIL initialisation failed: error %d", error);
 		goto out_free_log;
 	}
 	mp->m_log->l_ailp = mp->m_ail;
@@ -413,7 +412,8 @@ xfs_log_mount(
 		if (readonly)
 			mp->m_flags |= XFS_MOUNT_RDONLY;
 		if (error) {
-			cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
+			xfs_warn(mp, "log mount/recovery failed: error %d",
+				error);
 			goto out_destroy_ail;
 		}
 	}
@@ -542,10 +542,8 @@ xfs_log_unmount_write(xfs_mount_t *mp)
 			 */
 		}
 
-		if (error) {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-				"xfs_log_unmount: unmount record failed");
-		}
+		if (error)
+			xfs_alert(mp, "%s: unmount record failed", __func__);
 
 
 		spin_lock(&log->l_icloglock);
@@ -852,7 +850,7 @@ xlog_space_left(
 		 * In this case we just want to return the size of the
 		 * log as the amount of space left.
 		 */
-		xfs_fs_cmn_err(CE_ALERT, log->l_mp,
+		xfs_alert(log->l_mp,
 			"xlog_space_left: head behind tail\n"
 			"  tail_cycle = %d, tail_bytes = %d\n"
 			"  GH   cycle = %d, GH   bytes = %d",
@@ -1001,7 +999,7 @@ xlog_alloc_log(xfs_mount_t	*mp,
 
 	log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL);
 	if (!log) {
-		xlog_warn("XFS: Log allocation failed: No memory!");
+		xfs_warn(mp, "Log allocation failed: No memory!");
 		goto out;
 	}
 
@@ -1029,24 +1027,24 @@ xlog_alloc_log(xfs_mount_t	*mp,
 	if (xfs_sb_version_hassector(&mp->m_sb)) {
 	        log2_size = mp->m_sb.sb_logsectlog;
 		if (log2_size < BBSHIFT) {
-			xlog_warn("XFS: Log sector size too small "
-				"(0x%x < 0x%x)", log2_size, BBSHIFT);
+			xfs_warn(mp, "Log sector size too small (0x%x < 0x%x)",
+				log2_size, BBSHIFT);
 			goto out_free_log;
 		}
 
 	        log2_size -= BBSHIFT;
 		if (log2_size > mp->m_sectbb_log) {
-			xlog_warn("XFS: Log sector size too large "
-				"(0x%x > 0x%x)", log2_size, mp->m_sectbb_log);
+			xfs_warn(mp, "Log sector size too large (0x%x > 0x%x)",
+				log2_size, mp->m_sectbb_log);
 			goto out_free_log;
 		}
 
 		/* for larger sector sizes, must have v2 or external log */
 		if (log2_size && log->l_logBBstart > 0 &&
 			    !xfs_sb_version_haslogv2(&mp->m_sb)) {
-
-			xlog_warn("XFS: log sector size (0x%x) invalid "
-				  "for configuration.", log2_size);
+			xfs_warn(mp,
+		"log sector size (0x%x) invalid for configuration.",
+				log2_size);
 			goto out_free_log;
 		}
 	}
@@ -1563,38 +1561,36 @@ xlog_print_tic_res(
 	    "SWAPEXT"
 	};
 
-	xfs_fs_cmn_err(CE_WARN, mp,
-			"xfs_log_write: reservation summary:\n"
-			"  trans type  = %s (%u)\n"
-			"  unit res    = %d bytes\n"
-			"  current res = %d bytes\n"
-			"  total reg   = %u bytes (o/flow = %u bytes)\n"
-			"  ophdrs      = %u (ophdr space = %u bytes)\n"
-			"  ophdr + reg = %u bytes\n"
-			"  num regions = %u\n",
-			((ticket->t_trans_type <= 0 ||
-			  ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
-			  "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
-			ticket->t_trans_type,
-			ticket->t_unit_res,
-			ticket->t_curr_res,
-			ticket->t_res_arr_sum, ticket->t_res_o_flow,
-			ticket->t_res_num_ophdrs, ophdr_spc,
-			ticket->t_res_arr_sum + 
-			ticket->t_res_o_flow + ophdr_spc,
-			ticket->t_res_num);
+	xfs_warn(mp,
+		"xfs_log_write: reservation summary:\n"
+		"  trans type  = %s (%u)\n"
+		"  unit res    = %d bytes\n"
+		"  current res = %d bytes\n"
+		"  total reg   = %u bytes (o/flow = %u bytes)\n"
+		"  ophdrs      = %u (ophdr space = %u bytes)\n"
+		"  ophdr + reg = %u bytes\n"
+		"  num regions = %u\n",
+		((ticket->t_trans_type <= 0 ||
+		  ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
+		  "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
+		ticket->t_trans_type,
+		ticket->t_unit_res,
+		ticket->t_curr_res,
+		ticket->t_res_arr_sum, ticket->t_res_o_flow,
+		ticket->t_res_num_ophdrs, ophdr_spc,
+		ticket->t_res_arr_sum +
+		ticket->t_res_o_flow + ophdr_spc,
+		ticket->t_res_num);
 
 	for (i = 0; i < ticket->t_res_num; i++) {
-		uint r_type = ticket->t_res_arr[i].r_type; 
-		cmn_err(CE_WARN,
-			    "region[%u]: %s - %u bytes\n",
-			    i, 
+		uint r_type = ticket->t_res_arr[i].r_type;
+		xfs_warn(mp, "region[%u]: %s - %u bytes\n", i,
 			    ((r_type <= 0 || r_type > XLOG_REG_TYPE_MAX) ?
 			    "bad-rtype" : res_type_str[r_type-1]),
 			    ticket->t_res_arr[i].r_len);
 	}
 
-	xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
+	xfs_alert_tag(mp, XFS_PTAG_LOGRES,
 		"xfs_log_write: reservation ran out. Need to up reservation");
 	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 }
@@ -1682,7 +1678,7 @@ xlog_write_setup_ophdr(
 	case XFS_LOG:
 		break;
 	default:
-		xfs_fs_cmn_err(CE_WARN, log->l_mp,
+		xfs_warn(log->l_mp,
 			"Bad XFS transaction clientid 0x%x in ticket 0x%p",
 			ophdr->oh_clientid, ticket);
 		return NULL;
@@ -2264,7 +2260,7 @@ xlog_state_do_callback(
 		if (repeats > 5000) {
 			flushcnt += repeats;
 			repeats = 0;
-			xfs_fs_cmn_err(CE_WARN, log->l_mp,
+			xfs_warn(log->l_mp,
 				"%s: possible infinite loop (%d iterations)",
 				__func__, flushcnt);
 		}
@@ -3052,10 +3048,8 @@ xfs_log_force(
 	int	error;
 
 	error = _xfs_log_force(mp, flags, NULL);
-	if (error) {
-		xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
-			"error %d returned.", error);
-	}
+	if (error)
+		xfs_warn(mp, "%s: error %d returned.", __func__, error);
 }
 
 /*
@@ -3204,10 +3198,8 @@ xfs_log_force_lsn(
 	int	error;
 
 	error = _xfs_log_force_lsn(mp, lsn, flags, NULL);
-	if (error) {
-		xfs_fs_cmn_err(CE_WARN, mp, "xfs_log_force: "
-			"error %d returned.", error);
-	}
+	if (error)
+		xfs_warn(mp, "%s: error %d returned.", __func__, error);
 }
 
 /*
@@ -3412,7 +3404,7 @@ xlog_verify_dest_ptr(
 	}
 
 	if (!good_ptr)
-		xlog_panic("xlog_verify_dest_ptr: invalid ptr");
+		xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);
 }
 
 STATIC void
@@ -3448,16 +3440,16 @@ xlog_verify_tail_lsn(xlog_t	    *log,
 	blocks =
 	    log->l_logBBsize - (log->l_prev_block - BLOCK_LSN(tail_lsn));
 	if (blocks < BTOBB(iclog->ic_offset)+BTOBB(log->l_iclog_hsize))
-	    xlog_panic("xlog_verify_tail_lsn: ran out of log space");
+		xfs_emerg(log->l_mp, "%s: ran out of log space", __func__);
     } else {
 	ASSERT(CYCLE_LSN(tail_lsn)+1 == log->l_prev_cycle);
 
 	if (BLOCK_LSN(tail_lsn) == log->l_prev_block)
-	    xlog_panic("xlog_verify_tail_lsn: tail wrapped");
+		xfs_emerg(log->l_mp, "%s: tail wrapped", __func__);
 
 	blocks = BLOCK_LSN(tail_lsn) - log->l_prev_block;
 	if (blocks < BTOBB(iclog->ic_offset) + 1)
-	    xlog_panic("xlog_verify_tail_lsn: ran out of log space");
+		xfs_emerg(log->l_mp, "%s: ran out of log space", __func__);
     }
 }	/* xlog_verify_tail_lsn */
 
@@ -3497,22 +3489,23 @@ xlog_verify_iclog(xlog_t	 *log,
 	icptr = log->l_iclog;
 	for (i=0; i < log->l_iclog_bufs; i++) {
 		if (icptr == NULL)
-			xlog_panic("xlog_verify_iclog: invalid ptr");
+			xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);
 		icptr = icptr->ic_next;
 	}
 	if (icptr != log->l_iclog)
-		xlog_panic("xlog_verify_iclog: corrupt iclog ring");
+		xfs_emerg(log->l_mp, "%s: corrupt iclog ring", __func__);
 	spin_unlock(&log->l_icloglock);
 
 	/* check log magic numbers */
 	if (be32_to_cpu(iclog->ic_header.h_magicno) != XLOG_HEADER_MAGIC_NUM)
-		xlog_panic("xlog_verify_iclog: invalid magic num");
+		xfs_emerg(log->l_mp, "%s: invalid magic num", __func__);
 
 	ptr = (xfs_caddr_t) &iclog->ic_header;
 	for (ptr += BBSIZE; ptr < ((xfs_caddr_t)&iclog->ic_header) + count;
 	     ptr += BBSIZE) {
 		if (be32_to_cpu(*(__be32 *)ptr) == XLOG_HEADER_MAGIC_NUM)
-			xlog_panic("xlog_verify_iclog: unexpected magic num");
+			xfs_emerg(log->l_mp, "%s: unexpected magic num",
+				__func__);
 	}
 
 	/* check fields */
@@ -3542,9 +3535,10 @@ xlog_verify_iclog(xlog_t	 *log,
 			}
 		}
 		if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
-			cmn_err(CE_WARN, "xlog_verify_iclog: "
-				"invalid clientid %d op 0x%p offset 0x%lx",
-				clientid, ophead, (unsigned long)field_offset);
+			xfs_warn(log->l_mp,
+				"%s: invalid clientid %d op 0x%p offset 0x%lx",
+				__func__, clientid, ophead,
+				(unsigned long)field_offset);
 
 		/* check length */
 		field_offset = (__psint_t)
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index d5f8be8..15dbf1f 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -87,10 +87,6 @@ static inline uint xlog_get_client_id(__be32 i)
 	return be32_to_cpu(i) >> 24;
 }
 
-#define xlog_panic(args...)	cmn_err(CE_PANIC, ## args)
-#define xlog_exit(args...)	cmn_err(CE_PANIC, ## args)
-#define xlog_warn(args...)	cmn_err(CE_WARN, ## args)
-
 /*
  * In core log state
  */
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index aa0ebb7..0c4a561 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -92,7 +92,7 @@ xlog_get_bp(
 	int		nbblks)
 {
 	if (!xlog_buf_bbcount_valid(log, nbblks)) {
-		xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
 			nbblks);
 		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
 		return NULL;
@@ -160,7 +160,7 @@ xlog_bread_noalign(
 	int		error;
 
 	if (!xlog_buf_bbcount_valid(log, nbblks)) {
-		xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
 			nbblks);
 		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
 		return EFSCORRUPTED;
@@ -219,7 +219,7 @@ xlog_bwrite(
 	int		error;
 
 	if (!xlog_buf_bbcount_valid(log, nbblks)) {
-		xlog_warn("XFS: Invalid block length (0x%x) given for buffer",
+		xfs_warn(log->l_mp, "Invalid block length (0x%x) for buffer",
 			nbblks);
 		XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_HIGH, log->l_mp);
 		return EFSCORRUPTED;
@@ -254,9 +254,9 @@ xlog_header_check_dump(
 	xfs_mount_t		*mp,
 	xlog_rec_header_t	*head)
 {
-	cmn_err(CE_DEBUG, "%s:  SB : uuid = %pU, fmt = %d\n",
+	xfs_debug(mp, "%s:  SB : uuid = %pU, fmt = %d\n",
 		__func__, &mp->m_sb.sb_uuid, XLOG_FMT);
-	cmn_err(CE_DEBUG, "    log : uuid = %pU, fmt = %d\n",
+	xfs_debug(mp, "    log : uuid = %pU, fmt = %d\n",
 		&head->h_fs_uuid, be32_to_cpu(head->h_fmt));
 }
 #else
@@ -279,15 +279,15 @@ xlog_header_check_recover(
 	 * a dirty log created in IRIX.
 	 */
 	if (unlikely(be32_to_cpu(head->h_fmt) != XLOG_FMT)) {
-		xlog_warn(
-	"XFS: dirty log written in incompatible format - can't recover");
+		xfs_warn(mp,
+	"dirty log written in incompatible format - can't recover");
 		xlog_header_check_dump(mp, head);
 		XFS_ERROR_REPORT("xlog_header_check_recover(1)",
 				 XFS_ERRLEVEL_HIGH, mp);
 		return XFS_ERROR(EFSCORRUPTED);
 	} else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
-		xlog_warn(
-	"XFS: dirty log entry has mismatched uuid - can't recover");
+		xfs_warn(mp,
+	"dirty log entry has mismatched uuid - can't recover");
 		xlog_header_check_dump(mp, head);
 		XFS_ERROR_REPORT("xlog_header_check_recover(2)",
 				 XFS_ERRLEVEL_HIGH, mp);
@@ -312,9 +312,9 @@ xlog_header_check_mount(
 		 * h_fs_uuid is nil, we assume this log was last mounted
 		 * by IRIX and continue.
 		 */
-		xlog_warn("XFS: nil uuid in log - IRIX style log");
+		xfs_warn(mp, "nil uuid in log - IRIX style log");
 	} else if (unlikely(!uuid_equal(&mp->m_sb.sb_uuid, &head->h_fs_uuid))) {
-		xlog_warn("XFS: log has mismatched uuid - can't recover");
+		xfs_warn(mp, "log has mismatched uuid - can't recover");
 		xlog_header_check_dump(mp, head);
 		XFS_ERROR_REPORT("xlog_header_check_mount",
 				 XFS_ERRLEVEL_HIGH, mp);
@@ -490,8 +490,8 @@ xlog_find_verify_log_record(
 	for (i = (*last_blk) - 1; i >= 0; i--) {
 		if (i < start_blk) {
 			/* valid log record not found */
-			xlog_warn(
-		"XFS: Log inconsistent (didn't find previous header)");
+			xfs_warn(log->l_mp,
+		"Log inconsistent (didn't find previous header)");
 			ASSERT(0);
 			error = XFS_ERROR(EIO);
 			goto out;
@@ -591,12 +591,12 @@ xlog_find_head(
 			 * mkfs etc write a dummy unmount record to a fresh
 			 * log so we can store the uuid in there
 			 */
-			xlog_warn("XFS: totally zeroed log");
+			xfs_warn(log->l_mp, "totally zeroed log");
 		}
 
 		return 0;
 	} else if (error) {
-		xlog_warn("XFS: empty log check failed");
+		xfs_warn(log->l_mp, "empty log check failed");
 		return error;
 	}
 
@@ -819,7 +819,7 @@ validate_head:
 	xlog_put_bp(bp);
 
 	if (error)
-	    xlog_warn("XFS: failed to find log head");
+		xfs_warn(log->l_mp, "failed to find log head");
 	return error;
 }
 
@@ -912,7 +912,7 @@ xlog_find_tail(
 		}
 	}
 	if (!found) {
-		xlog_warn("XFS: xlog_find_tail: couldn't find sync record");
+		xfs_warn(log->l_mp, "%s: couldn't find sync record", __func__);
 		ASSERT(0);
 		return XFS_ERROR(EIO);
 	}
@@ -1028,7 +1028,7 @@ done:
 	xlog_put_bp(bp);
 
 	if (error)
-		xlog_warn("XFS: failed to locate log tail");
+		xfs_warn(log->l_mp, "failed to locate log tail");
 	return error;
 }
 
@@ -1092,7 +1092,8 @@ xlog_find_zeroed(
 		 * the first block must be 1. If it's not, maybe we're
 		 * not looking at a log... Bail out.
 		 */
-		xlog_warn("XFS: Log inconsistent or not a log (last==0, first!=1)");
+		xfs_warn(log->l_mp,
+			"Log inconsistent or not a log (last==0, first!=1)");
 		return XFS_ERROR(EINVAL);
 	}
 
@@ -1506,8 +1507,8 @@ xlog_recover_add_to_trans(
 	if (list_empty(&trans->r_itemq)) {
 		/* we need to catch log corruptions here */
 		if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) {
-			xlog_warn("XFS: xlog_recover_add_to_trans: "
-				  "bad header magic number");
+			xfs_warn(log->l_mp, "%s: bad header magic number",
+				__func__);
 			ASSERT(0);
 			return XFS_ERROR(EIO);
 		}
@@ -1534,8 +1535,8 @@ xlog_recover_add_to_trans(
 	if (item->ri_total == 0) {		/* first region to be added */
 		if (in_f->ilf_size == 0 ||
 		    in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) {
-			xlog_warn(
-	"XFS: bad number of regions (%d) in inode log format",
+			xfs_warn(log->l_mp,
+		"bad number of regions (%d) in inode log format",
 				  in_f->ilf_size);
 			ASSERT(0);
 			return XFS_ERROR(EIO);
@@ -1592,8 +1593,9 @@ xlog_recover_reorder_trans(
 			list_move_tail(&item->ri_list, &trans->r_itemq);
 			break;
 		default:
-			xlog_warn(
-	"XFS: xlog_recover_reorder_trans: unrecognized type of log operation");
+			xfs_warn(log->l_mp,
+				"%s: unrecognized type of log operation",
+				__func__);
 			ASSERT(0);
 			return XFS_ERROR(EIO);
 		}
@@ -1803,8 +1805,9 @@ xlog_recover_do_inode_buffer(
 		logged_nextp = item->ri_buf[item_index].i_addr +
 				next_unlinked_offset - reg_buf_offset;
 		if (unlikely(*logged_nextp == 0)) {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-				"bad inode buffer log record (ptr = 0x%p, bp = 0x%p).  XFS trying to replay bad (0) inode di_next_unlinked field",
+			xfs_alert(mp,
+		"Bad inode buffer log record (ptr = 0x%p, bp = 0x%p). "
+		"Trying to replay bad (0) inode di_next_unlinked field.",
 				item, bp);
 			XFS_ERROR_REPORT("xlog_recover_do_inode_buf",
 					 XFS_ERRLEVEL_LOW, mp);
@@ -1863,17 +1866,17 @@ xlog_recover_do_reg_buffer(
 		if (buf_f->blf_flags &
 		   (XFS_BLF_UDQUOT_BUF|XFS_BLF_PDQUOT_BUF|XFS_BLF_GDQUOT_BUF)) {
 			if (item->ri_buf[i].i_addr == NULL) {
-				cmn_err(CE_ALERT,
+				xfs_alert(mp,
 					"XFS: NULL dquot in %s.", __func__);
 				goto next;
 			}
 			if (item->ri_buf[i].i_len < sizeof(xfs_disk_dquot_t)) {
-				cmn_err(CE_ALERT,
+				xfs_alert(mp,
 					"XFS: dquot too small (%d) in %s.",
 					item->ri_buf[i].i_len, __func__);
 				goto next;
 			}
-			error = xfs_qm_dqcheck(item->ri_buf[i].i_addr,
+			error = xfs_qm_dqcheck(mp, item->ri_buf[i].i_addr,
 					       -1, 0, XFS_QMOPT_DOWARN,
 					       "dquot_buf_recover");
 			if (error)
@@ -1898,6 +1901,7 @@ xlog_recover_do_reg_buffer(
  */
 int
 xfs_qm_dqcheck(
+	struct xfs_mount *mp,
 	xfs_disk_dquot_t *ddq,
 	xfs_dqid_t	 id,
 	uint		 type,	  /* used only when IO_dorepair is true */
@@ -1924,14 +1928,14 @@ xfs_qm_dqcheck(
 	 */
 	if (be16_to_cpu(ddq->d_magic) != XFS_DQUOT_MAGIC) {
 		if (flags & XFS_QMOPT_DOWARN)
-			cmn_err(CE_ALERT,
+			xfs_alert(mp,
 			"%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x",
 			str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC);
 		errs++;
 	}
 	if (ddq->d_version != XFS_DQUOT_VERSION) {
 		if (flags & XFS_QMOPT_DOWARN)
-			cmn_err(CE_ALERT,
+			xfs_alert(mp,
 			"%s : XFS dquot ID 0x%x, version 0x%x != 0x%x",
 			str, id, ddq->d_version, XFS_DQUOT_VERSION);
 		errs++;
@@ -1941,7 +1945,7 @@ xfs_qm_dqcheck(
 	    ddq->d_flags != XFS_DQ_PROJ &&
 	    ddq->d_flags != XFS_DQ_GROUP) {
 		if (flags & XFS_QMOPT_DOWARN)
-			cmn_err(CE_ALERT,
+			xfs_alert(mp,
 			"%s : XFS dquot ID 0x%x, unknown flags 0x%x",
 			str, id, ddq->d_flags);
 		errs++;
@@ -1949,7 +1953,7 @@ xfs_qm_dqcheck(
 
 	if (id != -1 && id != be32_to_cpu(ddq->d_id)) {
 		if (flags & XFS_QMOPT_DOWARN)
-			cmn_err(CE_ALERT,
+			xfs_alert(mp,
 			"%s : ondisk-dquot 0x%p, ID mismatch: "
 			"0x%x expected, found id 0x%x",
 			str, ddq, id, be32_to_cpu(ddq->d_id));
@@ -1962,9 +1966,8 @@ xfs_qm_dqcheck(
 				be64_to_cpu(ddq->d_blk_softlimit)) {
 			if (!ddq->d_btimer) {
 				if (flags & XFS_QMOPT_DOWARN)
-					cmn_err(CE_ALERT,
-					"%s : Dquot ID 0x%x (0x%p) "
-					"BLK TIMER NOT STARTED",
+					xfs_alert(mp,
+			"%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED",
 					str, (int)be32_to_cpu(ddq->d_id), ddq);
 				errs++;
 			}
@@ -1974,9 +1977,8 @@ xfs_qm_dqcheck(
 				be64_to_cpu(ddq->d_ino_softlimit)) {
 			if (!ddq->d_itimer) {
 				if (flags & XFS_QMOPT_DOWARN)
-					cmn_err(CE_ALERT,
-					"%s : Dquot ID 0x%x (0x%p) "
-					"INODE TIMER NOT STARTED",
+					xfs_alert(mp,
+			"%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED",
 					str, (int)be32_to_cpu(ddq->d_id), ddq);
 				errs++;
 			}
@@ -1986,9 +1988,8 @@ xfs_qm_dqcheck(
 				be64_to_cpu(ddq->d_rtb_softlimit)) {
 			if (!ddq->d_rtbtimer) {
 				if (flags & XFS_QMOPT_DOWARN)
-					cmn_err(CE_ALERT,
-					"%s : Dquot ID 0x%x (0x%p) "
-					"RTBLK TIMER NOT STARTED",
+					xfs_alert(mp,
+			"%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED",
 					str, (int)be32_to_cpu(ddq->d_id), ddq);
 				errs++;
 			}
@@ -1999,7 +2000,7 @@ xfs_qm_dqcheck(
 		return errs;
 
 	if (flags & XFS_QMOPT_DOWARN)
-		cmn_err(CE_NOTE, "Re-initializing dquot ID 0x%x", id);
+		xfs_notice(mp, "Re-initializing dquot ID 0x%x", id);
 
 	/*
 	 * Typically, a repair is only requested by quotacheck.
@@ -2218,9 +2219,9 @@ xlog_recover_inode_pass2(
 	 */
 	if (unlikely(be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC)) {
 		xfs_buf_relse(bp);
-		xfs_fs_cmn_err(CE_ALERT, mp,
-			"xfs_inode_recover: Bad inode magic number, dino ptr = 0x%p, dino bp = 0x%p, ino = %Ld",
-			dip, bp, in_f->ilf_ino);
+		xfs_alert(mp,
+	"%s: Bad inode magic number, dip = 0x%p, dino bp = 0x%p, ino = %Ld",
+			__func__, dip, bp, in_f->ilf_ino);
 		XFS_ERROR_REPORT("xlog_recover_inode_pass2(1)",
 				 XFS_ERRLEVEL_LOW, mp);
 		error = EFSCORRUPTED;
@@ -2229,9 +2230,9 @@ xlog_recover_inode_pass2(
 	dicp = item->ri_buf[1].i_addr;
 	if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
 		xfs_buf_relse(bp);
-		xfs_fs_cmn_err(CE_ALERT, mp,
-			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, ino %Ld",
-			item, in_f->ilf_ino);
+		xfs_alert(mp,
+			"%s: Bad inode log record, rec ptr 0x%p, ino %Ld",
+			__func__, item, in_f->ilf_ino);
 		XFS_ERROR_REPORT("xlog_recover_inode_pass2(2)",
 				 XFS_ERRLEVEL_LOW, mp);
 		error = EFSCORRUPTED;
@@ -2263,9 +2264,10 @@ xlog_recover_inode_pass2(
 			XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
 					 XFS_ERRLEVEL_LOW, mp, dicp);
 			xfs_buf_relse(bp);
-			xfs_fs_cmn_err(CE_ALERT, mp,
-				"xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
-				item, dip, bp, in_f->ilf_ino);
+			xfs_alert(mp,
+		"%s: Bad regular inode log record, rec ptr 0x%p, "
+		"ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
+				__func__, item, dip, bp, in_f->ilf_ino);
 			error = EFSCORRUPTED;
 			goto error;
 		}
@@ -2276,9 +2278,10 @@ xlog_recover_inode_pass2(
 			XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
 					     XFS_ERRLEVEL_LOW, mp, dicp);
 			xfs_buf_relse(bp);
-			xfs_fs_cmn_err(CE_ALERT, mp,
-				"xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
-				item, dip, bp, in_f->ilf_ino);
+			xfs_alert(mp,
+		"%s: Bad dir inode log record, rec ptr 0x%p, "
+		"ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
+				__func__, item, dip, bp, in_f->ilf_ino);
 			error = EFSCORRUPTED;
 			goto error;
 		}
@@ -2287,9 +2290,10 @@ xlog_recover_inode_pass2(
 		XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
 				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
-		xfs_fs_cmn_err(CE_ALERT, mp,
-			"xfs_inode_recover: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
-			item, dip, bp, in_f->ilf_ino,
+		xfs_alert(mp,
+	"%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
+	"dino bp 0x%p, ino %Ld, total extents = %d, nblocks = %Ld",
+			__func__, item, dip, bp, in_f->ilf_ino,
 			dicp->di_nextents + dicp->di_anextents,
 			dicp->di_nblocks);
 		error = EFSCORRUPTED;
@@ -2299,8 +2303,9 @@ xlog_recover_inode_pass2(
 		XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
 				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
-		xfs_fs_cmn_err(CE_ALERT, mp,
-			"xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
+		xfs_alert(mp,
+	"%s: Bad inode log record, rec ptr 0x%p, dino ptr 0x%p, "
+	"dino bp 0x%p, ino %Ld, forkoff 0x%x", __func__,
 			item, dip, bp, in_f->ilf_ino, dicp->di_forkoff);
 		error = EFSCORRUPTED;
 		goto error;
@@ -2309,9 +2314,9 @@ xlog_recover_inode_pass2(
 		XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
 				     XFS_ERRLEVEL_LOW, mp, dicp);
 		xfs_buf_relse(bp);
-		xfs_fs_cmn_err(CE_ALERT, mp,
-			"xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
-			item->ri_buf[1].i_len, item);
+		xfs_alert(mp,
+			"%s: Bad inode log record length %d, rec ptr 0x%p",
+			__func__, item->ri_buf[1].i_len, item);
 		error = EFSCORRUPTED;
 		goto error;
 	}
@@ -2398,7 +2403,7 @@ xlog_recover_inode_pass2(
 			break;
 
 		default:
-			xlog_warn("XFS: xlog_recover_inode_pass2: Invalid flag");
+			xfs_warn(log->l_mp, "%s: Invalid flag", __func__);
 			ASSERT(0);
 			xfs_buf_relse(bp);
 			error = EIO;
@@ -2467,13 +2472,11 @@ xlog_recover_dquot_pass2(
 
 	recddq = item->ri_buf[1].i_addr;
 	if (recddq == NULL) {
-		cmn_err(CE_ALERT,
-			"XFS: NULL dquot in %s.", __func__);
+		xfs_alert(log->l_mp, "NULL dquot in %s.", __func__);
 		return XFS_ERROR(EIO);
 	}
 	if (item->ri_buf[1].i_len < sizeof(xfs_disk_dquot_t)) {
-		cmn_err(CE_ALERT,
-			"XFS: dquot too small (%d) in %s.",
+		xfs_alert(log->l_mp, "dquot too small (%d) in %s.",
 			item->ri_buf[1].i_len, __func__);
 		return XFS_ERROR(EIO);
 	}
@@ -2498,12 +2501,10 @@ xlog_recover_dquot_pass2(
 	 */
 	dq_f = item->ri_buf[0].i_addr;
 	ASSERT(dq_f);
-	if ((error = xfs_qm_dqcheck(recddq,
-			   dq_f->qlf_id,
-			   0, XFS_QMOPT_DOWARN,
-			   "xlog_recover_dquot_pass2 (log copy)"))) {
+	error = xfs_qm_dqcheck(mp, recddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
+			   "xlog_recover_dquot_pass2 (log copy)");
+	if (error)
 		return XFS_ERROR(EIO);
-	}
 	ASSERT(dq_f->qlf_len == 1);
 
 	error = xfs_read_buf(mp, mp->m_ddev_targp,
@@ -2523,8 +2524,9 @@ xlog_recover_dquot_pass2(
 	 * was among a chunk of dquots created earlier, and we did some
 	 * minimal initialization then.
 	 */
-	if (xfs_qm_dqcheck(ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
-			   "xlog_recover_dquot_pass2")) {
+	error = xfs_qm_dqcheck(mp, ddq, dq_f->qlf_id, 0, XFS_QMOPT_DOWARN,
+			   "xlog_recover_dquot_pass2");
+	if (error) {
 		xfs_buf_relse(bp);
 		return XFS_ERROR(EIO);
 	}
@@ -2676,9 +2678,8 @@ xlog_recover_commit_pass1(
 		/* nothing to do in pass 1 */
 		return 0;
 	default:
-		xlog_warn(
-	"XFS: invalid item type (%d) xlog_recover_commit_pass1",
-			ITEM_TYPE(item));
+		xfs_warn(log->l_mp, "%s: invalid item type (%d)",
+			__func__, ITEM_TYPE(item));
 		ASSERT(0);
 		return XFS_ERROR(EIO);
 	}
@@ -2707,9 +2708,8 @@ xlog_recover_commit_pass2(
 		/* nothing to do in pass2 */
 		return 0;
 	default:
-		xlog_warn(
-	"XFS: invalid item type (%d) xlog_recover_commit_pass2",
-			ITEM_TYPE(item));
+		xfs_warn(log->l_mp, "%s: invalid item type (%d)",
+			__func__, ITEM_TYPE(item));
 		ASSERT(0);
 		return XFS_ERROR(EIO);
 	}
@@ -2751,10 +2751,11 @@ xlog_recover_commit_trans(
 
 STATIC int
 xlog_recover_unmount_trans(
+	struct log		*log,
 	xlog_recover_t		*trans)
 {
 	/* Do nothing now */
-	xlog_warn("XFS: xlog_recover_unmount_trans: Unmount LR");
+	xfs_warn(log->l_mp, "%s: Unmount LR", __func__);
 	return 0;
 }
 
@@ -2797,8 +2798,8 @@ xlog_recover_process_data(
 		dp += sizeof(xlog_op_header_t);
 		if (ohead->oh_clientid != XFS_TRANSACTION &&
 		    ohead->oh_clientid != XFS_LOG) {
-			xlog_warn(
-		"XFS: xlog_recover_process_data: bad clientid");
+			xfs_warn(log->l_mp, "%s: bad clientid 0x%x",
+					__func__, ohead->oh_clientid);
 			ASSERT(0);
 			return (XFS_ERROR(EIO));
 		}
@@ -2811,8 +2812,8 @@ xlog_recover_process_data(
 					be64_to_cpu(rhead->h_lsn));
 		} else {
 			if (dp + be32_to_cpu(ohead->oh_len) > lp) {
-				xlog_warn(
-			"XFS: xlog_recover_process_data: bad length");
+				xfs_warn(log->l_mp, "%s: bad length 0x%x",
+					__func__, be32_to_cpu(ohead->oh_len));
 				WARN_ON(1);
 				return (XFS_ERROR(EIO));
 			}
@@ -2825,7 +2826,7 @@ xlog_recover_process_data(
 								trans, pass);
 				break;
 			case XLOG_UNMOUNT_TRANS:
-				error = xlog_recover_unmount_trans(trans);
+				error = xlog_recover_unmount_trans(log, trans);
 				break;
 			case XLOG_WAS_CONT_TRANS:
 				error = xlog_recover_add_to_cont_trans(log,
@@ -2833,8 +2834,8 @@ xlog_recover_process_data(
 						be32_to_cpu(ohead->oh_len));
 				break;
 			case XLOG_START_TRANS:
-				xlog_warn(
-			"XFS: xlog_recover_process_data: bad transaction");
+				xfs_warn(log->l_mp, "%s: bad transaction",
+					__func__);
 				ASSERT(0);
 				error = XFS_ERROR(EIO);
 				break;
@@ -2844,8 +2845,8 @@ xlog_recover_process_data(
 						dp, be32_to_cpu(ohead->oh_len));
 				break;
 			default:
-				xlog_warn(
-			"XFS: xlog_recover_process_data: bad flag");
+				xfs_warn(log->l_mp, "%s: bad flag 0x%x",
+					__func__, flags);
 				ASSERT(0);
 				error = XFS_ERROR(EIO);
 				break;
@@ -3030,8 +3031,7 @@ xlog_recover_clear_agi_bucket(
 out_abort:
 	xfs_trans_cancel(tp, XFS_TRANS_ABORT);
 out_error:
-	xfs_fs_cmn_err(CE_WARN, mp, "xlog_recover_clear_agi_bucket: "
-			"failed to clear agi %d. Continuing.", agno);
+	xfs_warn(mp, "%s: failed to clear agi %d. Continuing.", __func__, agno);
 	return;
 }
 
@@ -3282,7 +3282,7 @@ xlog_valid_rec_header(
 	if (unlikely(
 	    (!rhead->h_version ||
 	    (be32_to_cpu(rhead->h_version) & (~XLOG_VERSION_OKBITS))))) {
-		xlog_warn("XFS: %s: unrecognised log version (%d).",
+		xfs_warn(log->l_mp, "%s: unrecognised log version (%d).",
 			__func__, be32_to_cpu(rhead->h_version));
 		return XFS_ERROR(EIO);
 	}
@@ -3740,10 +3740,9 @@ xlog_recover(
 			return error;
 		}
 
-		cmn_err(CE_NOTE,
-			"Starting XFS recovery on filesystem: %s (logdev: %s)",
-			log->l_mp->m_fsname, log->l_mp->m_logname ?
-			log->l_mp->m_logname : "internal");
+		xfs_notice(log->l_mp, "Starting recovery (logdev: %s)",
+				log->l_mp->m_logname ? log->l_mp->m_logname
+						     : "internal");
 
 		error = xlog_do_recover(log, head_blk, tail_blk);
 		log->l_flags |= XLOG_RECOVERY_NEEDED;
@@ -3776,9 +3775,7 @@ xlog_recover_finish(
 		int	error;
 		error = xlog_recover_process_efis(log);
 		if (error) {
-			cmn_err(CE_ALERT,
-				"Failed to recover EFIs on filesystem: %s",
-				log->l_mp->m_fsname);
+			xfs_alert(log->l_mp, "Failed to recover EFIs");
 			return error;
 		}
 		/*
@@ -3793,15 +3790,12 @@ xlog_recover_finish(
 
 		xlog_recover_check_summary(log);
 
-		cmn_err(CE_NOTE,
-			"Ending XFS recovery on filesystem: %s (logdev: %s)",
-			log->l_mp->m_fsname, log->l_mp->m_logname ?
-			log->l_mp->m_logname : "internal");
+		xfs_notice(log->l_mp, "Ending recovery (logdev: %s)",
+				log->l_mp->m_logname ? log->l_mp->m_logname
+						     : "internal");
 		log->l_flags &= ~XLOG_RECOVERY_NEEDED;
 	} else {
-		cmn_err(CE_DEBUG,
-			"Ending clean XFS mount for filesystem: %s\n",
-			log->l_mp->m_fsname);
+		xfs_info(log->l_mp, "Ending clean mount");
 	}
 	return 0;
 }
@@ -3834,10 +3828,8 @@ xlog_recover_check_summary(
 	for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
 		error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);
 		if (error) {
-			xfs_fs_cmn_err(CE_ALERT, mp,
-					"xlog_recover_check_summary(agf)"
-					"agf read failed agno %d error %d",
-							agno, error);
+			xfs_alert(mp, "%s agf read failed agno %d error %d",
+						__func__, agno, error);
 		} else {
 			agfp = XFS_BUF_TO_AGF(agfbp);
 			freeblks += be32_to_cpu(agfp->agf_freeblks) +
@@ -3846,7 +3838,10 @@ xlog_recover_check_summary(
 		}
 
 		error = xfs_read_agi(mp, NULL, agno, &agibp);
-		if (!error) {
+		if (error) {
+			xfs_alert(mp, "%s agi read failed agno %d error %d",
+						__func__, agno, error);
+		} else {
 			struct xfs_agi	*agi = XFS_BUF_TO_AGI(agibp);
 
 			itotal += be32_to_cpu(agi->agi_count);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d447aef..bb3f9a7 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -133,9 +133,7 @@ xfs_uuid_mount(
 		return 0;
 
 	if (uuid_is_nil(uuid)) {
-		cmn_err(CE_WARN,
-			"XFS: Filesystem %s has nil UUID - can't mount",
-			mp->m_fsname);
+		xfs_warn(mp, "Filesystem has nil UUID - can't mount");
 		return XFS_ERROR(EINVAL);
 	}
 
@@ -163,8 +161,7 @@ xfs_uuid_mount(
 
  out_duplicate:
 	mutex_unlock(&xfs_uuid_table_mutex);
-	cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount",
-			 mp->m_fsname);
+	xfs_warn(mp, "Filesystem has duplicate UUID - can't mount");
 	return XFS_ERROR(EINVAL);
 }
 
@@ -311,6 +308,8 @@ xfs_mount_validate_sb(
 	xfs_sb_t	*sbp,
 	int		flags)
 {
+	int		loud = !(flags & XFS_MFSI_QUIET);
+
 	/*
 	 * If the log device and data device have the
 	 * same device number, the log is internal.
@@ -319,28 +318,32 @@ xfs_mount_validate_sb(
 	 * a volume filesystem in a non-volume manner.
 	 */
 	if (sbp->sb_magicnum != XFS_SB_MAGIC) {
-		xfs_fs_mount_cmn_err(flags, "bad magic number");
+		if (loud)
+			xfs_warn(mp, "bad magic number");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (!xfs_sb_good_version(sbp)) {
-		xfs_fs_mount_cmn_err(flags, "bad version");
+		if (loud)
+			xfs_warn(mp, "bad version");
 		return XFS_ERROR(EWRONGFS);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
-		xfs_fs_mount_cmn_err(flags,
-			"filesystem is marked as having an external log; "
-			"specify logdev on the\nmount command line.");
+		if (loud)
+			xfs_warn(mp,
+		"filesystem is marked as having an external log; "
+		"specify logdev on the mount command line.");
 		return XFS_ERROR(EINVAL);
 	}
 
 	if (unlikely(
 	    sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
-		xfs_fs_mount_cmn_err(flags,
-			"filesystem is marked as having an internal log; "
-			"do not specify logdev on\nthe mount command line.");
+		if (loud)
+			xfs_warn(mp,
+		"filesystem is marked as having an internal log; "
+		"do not specify logdev on the mount command line.");
 		return XFS_ERROR(EINVAL);
 	}
 
@@ -369,7 +372,8 @@ xfs_mount_validate_sb(
 	    (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE)	||
 	    (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE)	||
 	    (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) {
-		xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
+		if (loud)
+			xfs_warn(mp, "SB sanity check 1 failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -382,7 +386,8 @@ xfs_mount_validate_sb(
 	     (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
 	    sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
 			      sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
-		xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
+		if (loud)
+			xfs_warn(mp, "SB sanity check 2 failed");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -390,12 +395,12 @@ xfs_mount_validate_sb(
 	 * Until this is fixed only page-sized or smaller data blocks work.
 	 */
 	if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
-		xfs_fs_mount_cmn_err(flags,
-			"file system with blocksize %d bytes",
-			sbp->sb_blocksize);
-		xfs_fs_mount_cmn_err(flags,
-			"only pagesize (%ld) or less will currently work.",
-			PAGE_SIZE);
+		if (loud) {
+			xfs_warn(mp,
+		"File system with blocksize %d bytes. "
+		"Only pagesize (%ld) or less will currently work.",
+				sbp->sb_blocksize, PAGE_SIZE);
+		}
 		return XFS_ERROR(ENOSYS);
 	}
 
@@ -409,21 +414,23 @@ xfs_mount_validate_sb(
 	case 2048:
 		break;
 	default:
-		xfs_fs_mount_cmn_err(flags,
-			"inode size of %d bytes not supported",
-			sbp->sb_inodesize);
+		if (loud)
+			xfs_warn(mp, "inode size of %d bytes not supported",
+				sbp->sb_inodesize);
 		return XFS_ERROR(ENOSYS);
 	}
 
 	if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
 	    xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
-		xfs_fs_mount_cmn_err(flags,
-			"file system too large to be mounted on this system.");
+		if (loud)
+			xfs_warn(mp,
+		"file system too large to be mounted on this system.");
 		return XFS_ERROR(EFBIG);
 	}
 
 	if (unlikely(sbp->sb_inprogress)) {
-		xfs_fs_mount_cmn_err(flags, "file system busy");
+		if (loud)
+			xfs_warn(mp, "file system busy");
 		return XFS_ERROR(EFSCORRUPTED);
 	}
 
@@ -431,8 +438,9 @@ xfs_mount_validate_sb(
 	 * Version 1 directory format has never worked on Linux.
 	 */
 	if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
-		xfs_fs_mount_cmn_err(flags,
-			"file system using version 1 directory format");
+		if (loud)
+			xfs_warn(mp,
+				"file system using version 1 directory format");
 		return XFS_ERROR(ENOSYS);
 	}
 
@@ -673,6 +681,7 @@ xfs_readsb(xfs_mount_t *mp, int flags)
 	unsigned int	sector_size;
 	xfs_buf_t	*bp;
 	int		error;
+	int		loud = !(flags & XFS_MFSI_QUIET);
 
 	ASSERT(mp->m_sb_bp == NULL);
 	ASSERT(mp->m_ddev_targp != NULL);
@@ -688,7 +697,8 @@ reread:
 	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
 					XFS_SB_DADDR, sector_size, 0);
 	if (!bp) {
-		xfs_fs_mount_cmn_err(flags, "SB buffer read failed");
+		if (loud)
+			xfs_warn(mp, "SB buffer read failed");
 		return EIO;
 	}
 
@@ -699,7 +709,8 @@ reread:
 	xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
 	error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
 	if (error) {
-		xfs_fs_mount_cmn_err(flags, "SB validate failed");
+		if (loud)
+			xfs_warn(mp, "SB validate failed");
 		goto release_buf;
 	}
 
@@ -707,9 +718,9 @@ reread:
 	 * We must be able to do sector-sized and sector-aligned IO.
 	 */
 	if (sector_size > mp->m_sb.sb_sectsize) {
-		xfs_fs_mount_cmn_err(flags,
-			"device supports only %u byte sectors (not %u)",
-			sector_size, mp->m_sb.sb_sectsize);
+		if (loud)
+			xfs_warn(mp, "device supports %u byte sectors (not %u)",
+				sector_size, mp->m_sb.sb_sectsize);
 		error = ENOSYS;
 		goto release_buf;
 	}
@@ -853,8 +864,7 @@ xfs_update_alignment(xfs_mount_t *mp)
 		if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
 		    (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
 			if (mp->m_flags & XFS_MOUNT_RETERR) {
-				cmn_err(CE_WARN,
-					"XFS: alignment check 1 failed");
+				xfs_warn(mp, "alignment check 1 failed");
 				return XFS_ERROR(EINVAL);
 			}
 			mp->m_dalign = mp->m_swidth = 0;
@@ -867,8 +877,9 @@ xfs_update_alignment(xfs_mount_t *mp)
 				if (mp->m_flags & XFS_MOUNT_RETERR) {
 					return XFS_ERROR(EINVAL);
 				}
-				xfs_fs_cmn_err(CE_WARN, mp,
-"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)",
+				xfs_warn(mp,
+		"stripe alignment turned off: sunit(%d)/swidth(%d) "
+		"incompatible with agsize(%d)",
 					mp->m_dalign, mp->m_swidth,
 					sbp->sb_agblocks);
 
@@ -878,9 +889,9 @@ xfs_update_alignment(xfs_mount_t *mp)
 				mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
 			} else {
 				if (mp->m_flags & XFS_MOUNT_RETERR) {
-					xfs_fs_cmn_err(CE_WARN, mp,
-"stripe alignment turned off: sunit(%d) less than bsize(%d)",
-                                        	mp->m_dalign,
+					xfs_warn(mp,
+		"stripe alignment turned off: sunit(%d) less than bsize(%d)",
+						mp->m_dalign,
 						mp->m_blockmask +1);
 					return XFS_ERROR(EINVAL);
 				}
@@ -1026,14 +1037,14 @@ xfs_check_sizes(xfs_mount_t *mp)
 
 	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
 	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
-		cmn_err(CE_WARN, "XFS: filesystem size mismatch detected");
+		xfs_warn(mp, "filesystem size mismatch detected");
 		return XFS_ERROR(EFBIG);
 	}
 	bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp,
 					d - XFS_FSS_TO_BB(mp, 1),
 					BBTOB(XFS_FSS_TO_BB(mp, 1)), 0);
 	if (!bp) {
-		cmn_err(CE_WARN, "XFS: last sector read failed");
+		xfs_warn(mp, "last sector read failed");
 		return EIO;
 	}
 	xfs_buf_relse(bp);
@@ -1041,14 +1052,14 @@ xfs_check_sizes(xfs_mount_t *mp)
 	if (mp->m_logdev_targp != mp->m_ddev_targp) {
 		d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
 		if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
-			cmn_err(CE_WARN, "XFS: log size mismatch detected");
+			xfs_warn(mp, "log size mismatch detected");
 			return XFS_ERROR(EFBIG);
 		}
 		bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp,
 					d - XFS_FSB_TO_BB(mp, 1),
 					XFS_FSB_TO_B(mp, 1), 0);
 		if (!bp) {
-			cmn_err(CE_WARN, "XFS: log device read failed");
+			xfs_warn(mp, "log device read failed");
 			return EIO;
 		}
 		xfs_buf_relse(bp);
@@ -1086,7 +1097,7 @@ xfs_mount_reset_sbqflags(
 		return 0;
 
 #ifdef QUOTADEBUG
-	xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
+	xfs_notice(mp, "Writing superblock quota changes");
 #endif
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
@@ -1094,8 +1105,7 @@ xfs_mount_reset_sbqflags(
 				      XFS_DEFAULT_LOG_COUNT);
 	if (error) {
 		xfs_trans_cancel(tp, 0);
-		xfs_fs_cmn_err(CE_ALERT, mp,
-			"xfs_mount_reset_sbqflags: Superblock update failed!");
+		xfs_alert(mp, "%s: Superblock update failed!", __func__);
 		return error;
 	}
 
@@ -1161,8 +1171,7 @@ xfs_mountfs(
 	 * transaction subsystem is online.
 	 */
 	if (xfs_sb_has_mismatched_features2(sbp)) {
-		cmn_err(CE_WARN,
-			"XFS: correcting sb_features alignment problem");
+		xfs_warn(mp, "correcting sb_features alignment problem");
 		sbp->sb_features2 |= sbp->sb_bad_features2;
 		sbp->sb_bad_features2 = sbp->sb_features2;
 		mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
@@ -1241,7 +1250,7 @@ xfs_mountfs(
 	 */
 	error = xfs_rtmount_init(mp);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: RT mount failed");
+		xfs_warn(mp, "RT mount failed");
 		goto out_remove_uuid;
 	}
 
@@ -1272,12 +1281,12 @@ xfs_mountfs(
 	INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
 	error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error);
+		xfs_warn(mp, "Failed per-ag init: %d", error);
 		goto out_remove_uuid;
 	}
 
 	if (!sbp->sb_logblocks) {
-		cmn_err(CE_WARN, "XFS: no log defined");
+		xfs_warn(mp, "no log defined");
 		XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);
 		error = XFS_ERROR(EFSCORRUPTED);
 		goto out_free_perag;
@@ -1290,7 +1299,7 @@ xfs_mountfs(
 			      XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
 			      XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
 	if (error) {
-		cmn_err(CE_WARN, "XFS: log mount failed");
+		xfs_warn(mp, "log mount failed");
 		goto out_free_perag;
 	}
 
@@ -1327,16 +1336,14 @@ xfs_mountfs(
 	 */
 	error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: failed to read root inode");
+		xfs_warn(mp, "failed to read root inode");
 		goto out_log_dealloc;
 	}
 
 	ASSERT(rip != NULL);
 
 	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
-		cmn_err(CE_WARN, "XFS: corrupted root inode");
-		cmn_err(CE_WARN, "Device %s - root %llu is not a directory",
-			XFS_BUFTARG_NAME(mp->m_ddev_targp),
+		xfs_warn(mp, "corrupted root inode %llu: not a directory",
 			(unsigned long long)rip->i_ino);
 		xfs_iunlock(rip, XFS_ILOCK_EXCL);
 		XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
@@ -1356,7 +1363,7 @@ xfs_mountfs(
 		/*
 		 * Free up the root inode.
 		 */
-		cmn_err(CE_WARN, "XFS: failed to read RT inodes");
+		xfs_warn(mp, "failed to read RT inodes");
 		goto out_rele_rip;
 	}
 
@@ -1368,7 +1375,7 @@ xfs_mountfs(
 	if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
 		error = xfs_mount_log_sb(mp, mp->m_update_flags);
 		if (error) {
-			cmn_err(CE_WARN, "XFS: failed to write sb changes");
+			xfs_warn(mp, "failed to write sb changes");
 			goto out_rtunmount;
 		}
 	}
@@ -1389,10 +1396,7 @@ xfs_mountfs(
 		 * quotachecked license.
 		 */
 		if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
-			cmn_err(CE_NOTE,
-				"XFS: resetting qflags for filesystem %s",
-				mp->m_fsname);
-
+			xfs_notice(mp, "resetting quota flags");
 			error = xfs_mount_reset_sbqflags(mp);
 			if (error)
 				return error;
@@ -1406,7 +1410,7 @@ xfs_mountfs(
 	 */
 	error = xfs_log_mount_finish(mp);
 	if (error) {
-		cmn_err(CE_WARN, "XFS: log mount finish failed");
+		xfs_warn(mp, "log mount finish failed");
 		goto out_rtunmount;
 	}
 
@@ -1435,8 +1439,8 @@ xfs_mountfs(
 		resblks = xfs_default_resblks(mp);
 		error = xfs_reserve_blocks(mp, &resblks, NULL);
 		if (error)
-			cmn_err(CE_WARN, "XFS: Unable to allocate reserve "
-				"blocks. Continuing without a reserve pool.");
+			xfs_warn(mp,
+	"Unable to allocate reserve blocks. Continuing without reserve pool.");
 	}
 
 	return 0;
@@ -1525,12 +1529,12 @@ xfs_unmountfs(
 	resblks = 0;
 	error = xfs_reserve_blocks(mp, &resblks, NULL);
 	if (error)
-		cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. "
+		xfs_warn(mp, "Unable to free reserved block pool. "
 				"Freespace may not be correct on next mount.");
 
 	error = xfs_log_sbcount(mp, 1);
 	if (error)
-		cmn_err(CE_WARN, "XFS: Unable to update superblock counters. "
+		xfs_warn(mp, "Unable to update superblock counters. "
 				"Freespace may not be correct on next mount.");
 	xfs_unmountfs_writesb(mp);
 	xfs_unmountfs_wait(mp); 		/* wait for async bufs */
@@ -2013,10 +2017,8 @@ xfs_dev_is_read_only(
 	if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
 	    xfs_readonly_buftarg(mp->m_logdev_targp) ||
 	    (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
-		cmn_err(CE_NOTE,
-			"XFS: %s required on read-only device.", message);
-		cmn_err(CE_NOTE,
-			"XFS: write access unavailable, cannot proceed.");
+		xfs_notice(mp, "%s required on read-only device.", message);
+		xfs_notice(mp, "write access unavailable, cannot proceed.");
 		return EROFS;
 	}
 	return 0;
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
index edfa178..4aff563 100644
--- a/fs/xfs/xfs_mru_cache.c
+++ b/fs/xfs/xfs_mru_cache.c
@@ -309,7 +309,7 @@ xfs_mru_cache_init(void)
 	if (!xfs_mru_elem_zone)
 		goto out;
 
-	xfs_mru_reap_wq = create_singlethread_workqueue("xfs_mru_cache");
+	xfs_mru_reap_wq = alloc_workqueue("xfs_mru_cache", WQ_MEM_RECLAIM, 1);
 	if (!xfs_mru_reap_wq)
 		goto out_destroy_mru_elem_zone;
 
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 9bb6eda..a595f29 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -382,7 +382,8 @@ static inline int xfs_qm_sync(struct xfs_mount *mp, int flags)
 	xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \
 				f | XFS_QMOPT_RES_REGBLKS)
 
-extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
+extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
+				xfs_dqid_t, uint, uint, char *);
 extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
 
 #endif	/* __KERNEL__ */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 12a1913..8f76fdf 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -76,7 +76,7 @@ xfs_growfs_rt_alloc(
 	xfs_mount_t	*mp,		/* file system mount point */
 	xfs_extlen_t	oblocks,	/* old count of blocks */
 	xfs_extlen_t	nblocks,	/* new count of blocks */
-	xfs_ino_t	ino)		/* inode number (bitmap/summary) */
+	xfs_inode_t	*ip)		/* inode (bitmap/summary) */
 {
 	xfs_fileoff_t	bno;		/* block number in file */
 	xfs_buf_t	*bp;		/* temporary buffer for zeroing */
@@ -86,7 +86,6 @@ xfs_growfs_rt_alloc(
 	xfs_fsblock_t	firstblock;	/* first block allocated in xaction */
 	xfs_bmap_free_t	flist;		/* list of freed blocks */
 	xfs_fsblock_t	fsbno;		/* filesystem block for bno */
-	xfs_inode_t	*ip;		/* pointer to incore inode */
 	xfs_bmbt_irec_t	map;		/* block map output */
 	int		nmap;		/* number of block maps */
 	int		resblks;	/* space reservation */
@@ -112,9 +111,9 @@ xfs_growfs_rt_alloc(
 		/*
 		 * Lock the inode.
 		 */
-		if ((error = xfs_trans_iget(mp, tp, ino, 0,
-						XFS_ILOCK_EXCL, &ip)))
-			goto error_cancel;
+		xfs_ilock(ip, XFS_ILOCK_EXCL);
+		xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
+
 		xfs_bmap_init(&flist, &firstblock);
 		/*
 		 * Allocate blocks to the bitmap file.
@@ -155,9 +154,8 @@ xfs_growfs_rt_alloc(
 			/*
 			 * Lock the bitmap inode.
 			 */
-			if ((error = xfs_trans_iget(mp, tp, ino, 0,
-							XFS_ILOCK_EXCL, &ip)))
-				goto error_cancel;
+			xfs_ilock(ip, XFS_ILOCK_EXCL);
+			xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
 			/*
 			 * Get a buffer for the block.
 			 */
@@ -1854,7 +1852,6 @@ xfs_growfs_rt(
 	xfs_rtblock_t	bmbno;		/* bitmap block number */
 	xfs_buf_t	*bp;		/* temporary buffer */
 	int		error;		/* error return value */
-	xfs_inode_t	*ip;		/* bitmap inode, used as lock */
 	xfs_mount_t	*nmp;		/* new (fake) mount structure */
 	xfs_drfsbno_t	nrblocks;	/* new number of realtime blocks */
 	xfs_extlen_t	nrbmblocks;	/* new number of rt bitmap blocks */
@@ -1918,11 +1915,11 @@ xfs_growfs_rt(
 	/*
 	 * Allocate space to the bitmap and summary files, as necessary.
 	 */
-	if ((error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks,
-			mp->m_sb.sb_rbmino)))
+	error = xfs_growfs_rt_alloc(mp, rbmblocks, nrbmblocks, mp->m_rbmip);
+	if (error)
 		return error;
-	if ((error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks,
-			mp->m_sb.sb_rsumino)))
+	error = xfs_growfs_rt_alloc(mp, rsumblocks, nrsumblocks, mp->m_rsumip);
+	if (error)
 		return error;
 	/*
 	 * Allocate a new (fake) mount/sb.
@@ -1972,10 +1969,8 @@ xfs_growfs_rt(
 		/*
 		 * Lock out other callers by grabbing the bitmap inode lock.
 		 */
-		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-						XFS_ILOCK_EXCL, &ip)))
-			goto error_cancel;
-		ASSERT(ip == mp->m_rbmip);
+		xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+		xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
 		/*
 		 * Update the bitmap inode's size.
 		 */
@@ -1986,10 +1981,8 @@ xfs_growfs_rt(
 		/*
 		 * Get the summary inode into the transaction.
 		 */
-		if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rsumino, 0,
-						XFS_ILOCK_EXCL, &ip)))
-			goto error_cancel;
-		ASSERT(ip == mp->m_rsumip);
+		xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL);
+		xfs_trans_ijoin_ref(tp, mp->m_rsumip, XFS_ILOCK_EXCL);
 		/*
 		 * Update the summary inode's size.
 		 */
@@ -2075,15 +2068,15 @@ xfs_rtallocate_extent(
 	xfs_extlen_t	prod,		/* extent product factor */
 	xfs_rtblock_t	*rtblock)	/* out: start block allocated */
 {
+	xfs_mount_t	*mp = tp->t_mountp;
 	int		error;		/* error value */
-	xfs_inode_t	*ip;		/* inode for bitmap file */
-	xfs_mount_t	*mp;		/* file system mount structure */
 	xfs_rtblock_t	r;		/* result allocated block */
 	xfs_fsblock_t	sb;		/* summary file block number */
 	xfs_buf_t	*sumbp;		/* summary file block buffer */
 
+	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
 	ASSERT(minlen > 0 && minlen <= maxlen);
-	mp = tp->t_mountp;
+
 	/*
 	 * If prod is set then figure out what to do to minlen and maxlen.
 	 */
@@ -2099,12 +2092,7 @@ xfs_rtallocate_extent(
 			return 0;
 		}
 	}
-	/*
-	 * Lock out other callers by grabbing the bitmap inode lock.
-	 */
-	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-					XFS_ILOCK_EXCL, &ip)))
-		return error;
+
 	sumbp = NULL;
 	/*
 	 * Allocate by size, or near another block, or exactly at some block.
@@ -2123,11 +2111,12 @@ xfs_rtallocate_extent(
 				len, &sumbp, &sb, prod, &r);
 		break;
 	default:
+		error = EIO;
 		ASSERT(0);
 	}
-	if (error) {
+	if (error)
 		return error;
-	}
+
 	/*
 	 * If it worked, update the superblock.
 	 */
@@ -2155,7 +2144,6 @@ xfs_rtfree_extent(
 	xfs_extlen_t	len)		/* length of extent freed */
 {
 	int		error;		/* error value */
-	xfs_inode_t	*ip;		/* bitmap file inode */
 	xfs_mount_t	*mp;		/* file system mount structure */
 	xfs_fsblock_t	sb;		/* summary file block number */
 	xfs_buf_t	*sumbp;		/* summary file block buffer */
@@ -2164,9 +2152,9 @@ xfs_rtfree_extent(
 	/*
 	 * Synchronize by locking the bitmap inode.
 	 */
-	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-					XFS_ILOCK_EXCL, &ip)))
-		return error;
+	xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL);
+	xfs_trans_ijoin_ref(tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+
 #if defined(__KERNEL__) && defined(DEBUG)
 	/*
 	 * Check to see that this whole range is currently allocated.
@@ -2199,10 +2187,10 @@ xfs_rtfree_extent(
 	 */
 	if (tp->t_frextents_delta + mp->m_sb.sb_frextents ==
 	    mp->m_sb.sb_rextents) {
-		if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
-			ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
-		*(__uint64_t *)&ip->i_d.di_atime = 0;
-		xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+		if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM))
+			mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
+		*(__uint64_t *)&mp->m_rbmip->i_d.di_atime = 0;
+		xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
 	}
 	return 0;
 }
@@ -2222,8 +2210,8 @@ xfs_rtmount_init(
 	if (sbp->sb_rblocks == 0)
 		return 0;
 	if (mp->m_rtdev_targp == NULL) {
-		cmn_err(CE_WARN,
-	"XFS: This filesystem has a realtime volume, use rtdev=device option");
+		xfs_warn(mp,
+	"Filesystem has a realtime volume, use rtdev=device option");
 		return XFS_ERROR(ENODEV);
 	}
 	mp->m_rsumlevels = sbp->sb_rextslog + 1;
@@ -2237,7 +2225,7 @@ xfs_rtmount_init(
 	 */
 	d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
 	if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_rblocks) {
-		cmn_err(CE_WARN, "XFS: realtime mount -- %llu != %llu",
+		xfs_warn(mp, "realtime mount -- %llu != %llu",
 			(unsigned long long) XFS_BB_TO_FSB(mp, d),
 			(unsigned long long) mp->m_sb.sb_rblocks);
 		return XFS_ERROR(EFBIG);
@@ -2246,7 +2234,7 @@ xfs_rtmount_init(
 					d - XFS_FSB_TO_BB(mp, 1),
 					XFS_FSB_TO_B(mp, 1), 0);
 	if (!bp) {
-		cmn_err(CE_WARN, "XFS: realtime device size check failed");
+		xfs_warn(mp, "realtime device size check failed");
 		return EIO;
 	}
 	xfs_buf_relse(bp);
@@ -2306,20 +2294,16 @@ xfs_rtpick_extent(
 	xfs_rtblock_t	*pick)		/* result rt extent */
 {
 	xfs_rtblock_t	b;		/* result block */
-	int		error;		/* error return value */
-	xfs_inode_t	*ip;		/* bitmap incore inode */
 	int		log2;		/* log of sequence number */
 	__uint64_t	resid;		/* residual after log removed */
 	__uint64_t	seq;		/* sequence number of file creation */
 	__uint64_t	*seqp;		/* pointer to seqno in inode */
 
-	if ((error = xfs_trans_iget(mp, tp, mp->m_sb.sb_rbmino, 0,
-					XFS_ILOCK_EXCL, &ip)))
-		return error;
-	ASSERT(ip == mp->m_rbmip);
-	seqp = (__uint64_t *)&ip->i_d.di_atime;
-	if (!(ip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
-		ip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
+	ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL));
+
+	seqp = (__uint64_t *)&mp->m_rbmip->i_d.di_atime;
+	if (!(mp->m_rbmip->i_d.di_flags & XFS_DIFLAG_NEWRTBM)) {
+		mp->m_rbmip->i_d.di_flags |= XFS_DIFLAG_NEWRTBM;
 		*seqp = 0;
 	}
 	seq = *seqp;
@@ -2335,7 +2319,7 @@ xfs_rtpick_extent(
 			b = mp->m_sb.sb_rextents - len;
 	}
 	*seqp = seq + 1;
-	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+	xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE);
 	*pick = b;
 	return 0;
 }
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index ff614c2..09e1f4f 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -154,7 +154,7 @@ xfs_rtmount_init(
 	if (mp->m_sb.sb_rblocks == 0)
 		return 0;
 
-	cmn_err(CE_WARN, "XFS: Not built with CONFIG_XFS_RT");
+	xfs_warn(mp, "Not built with CONFIG_XFS_RT");
 	return ENOSYS;
 }
 # define xfs_rtmount_inodes(m)  (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS))
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index 56861d5..d6d6fdf 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -49,9 +49,9 @@ xfs_do_force_shutdown(
 	logerror = flags & SHUTDOWN_LOG_IO_ERROR;
 
 	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
-		cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from "
-				 "line %d of file %s.  Return address = 0x%p",
-			mp->m_fsname, flags, lnnum, fname, __return_address);
+		xfs_notice(mp,
+	"%s(0x%x) called from line %d of file %s.  Return address = 0x%p",
+			__func__, flags, lnnum, fname, __return_address);
 	}
 	/*
 	 * No need to duplicate efforts.
@@ -69,30 +69,25 @@ xfs_do_force_shutdown(
 		return;
 
 	if (flags & SHUTDOWN_CORRUPT_INCORE) {
-		xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
-    "Corruption of in-memory data detected.  Shutting down filesystem: %s",
-			mp->m_fsname);
-		if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
+		xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT,
+    "Corruption of in-memory data detected.  Shutting down filesystem");
+		if (XFS_ERRLEVEL_HIGH <= xfs_error_level)
 			xfs_stack_trace();
-		}
 	} else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
 		if (logerror) {
-			xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
-		"Log I/O Error Detected.  Shutting down filesystem: %s",
-				mp->m_fsname);
+			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR,
+		"Log I/O Error Detected.  Shutting down filesystem");
 		} else if (flags & SHUTDOWN_DEVICE_REQ) {
-			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
-		"All device paths lost.  Shutting down filesystem: %s",
-				mp->m_fsname);
+			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
+		"All device paths lost.  Shutting down filesystem");
 		} else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
-			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
-		"I/O Error Detected.  Shutting down filesystem: %s",
-				mp->m_fsname);
+			xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
+		"I/O Error Detected. Shutting down filesystem");
 		}
 	}
 	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
-		cmn_err(CE_ALERT, "Please umount the filesystem, "
-				  "and rectify the problem(s)");
+		xfs_alert(mp,
+	"Please umount the filesystem and rectify the problem(s)");
 	}
 }
 
@@ -106,10 +101,9 @@ xfs_ioerror_alert(
 	xfs_buf_t		*bp,
 	xfs_daddr_t		blkno)
 {
-	cmn_err(CE_ALERT,
- "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx"
- "       (\"%s\") error %d buf count %zd",
-		(!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname,
+	xfs_alert(mp,
+		 "I/O error occurred: meta-data dev %s block 0x%llx"
+		 "       (\"%s\") error %d buf count %zd",
 		XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
 		(__uint64_t)blkno, func,
 		XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
@@ -173,17 +167,9 @@ xfs_extlen_t
 xfs_get_extsz_hint(
 	struct xfs_inode	*ip)
 {
-	xfs_extlen_t		extsz;
-
-	if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
-		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
-				? ip->i_d.di_extsize
-				: ip->i_mount->m_sb.sb_rextsize;
-		ASSERT(extsz);
-	} else {
-		extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
-				? ip->i_d.di_extsize : 0;
-	}
-
-	return extsz;
+	if ((ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) && ip->i_d.di_extsize)
+		return ip->i_d.di_extsize;
+	if (XFS_IS_REALTIME_INODE(ip))
+		return ip->i_mount->m_sb.sb_rextsize;
+	return 0;
 }
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c2042b7..06a9759 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -469,8 +469,6 @@ void		xfs_trans_inode_buf(xfs_trans_t *, struct xfs_buf *);
 void		xfs_trans_stale_inode_buf(xfs_trans_t *, struct xfs_buf *);
 void		xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint);
 void		xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *);
-int		xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
-			       xfs_ino_t , uint, uint, struct xfs_inode **);
 void		xfs_trans_ichgtime(struct xfs_trans *, struct xfs_inode *, int);
 void		xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint);
 void		xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *);
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index c5bbbc4..12aff95 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -563,7 +563,7 @@ xfs_trans_ail_delete_bulk(
 
 			spin_unlock(&ailp->xa_lock);
 			if (!XFS_FORCED_SHUTDOWN(mp)) {
-				xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
+				xfs_alert_tag(mp, XFS_PTAG_AILDELETE,
 		"%s: attempting to delete a log item that is not in the AIL",
 						__func__);
 				xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index c47918c..3bea661 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -305,7 +305,7 @@ xfs_trans_read_buf(
 			if (xfs_error_target == target) {
 				if (((xfs_req_num++) % xfs_error_mod) == 0) {
 					xfs_buf_relse(bp);
-					cmn_err(CE_DEBUG, "Returning error!\n");
+					xfs_debug(mp, "Returning error!");
 					return XFS_ERROR(EIO);
 				}
 			}
@@ -403,7 +403,7 @@ xfs_trans_read_buf(
 				xfs_force_shutdown(tp->t_mountp,
 						   SHUTDOWN_META_IO_ERROR);
 				xfs_buf_relse(bp);
-				cmn_err(CE_DEBUG, "Returning trans error!\n");
+				xfs_debug(mp, "Returning trans error!");
 				return XFS_ERROR(EIO);
 			}
 		}
@@ -427,7 +427,7 @@ shutdown_abort:
 	 */
 #if defined(DEBUG)
 	if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp))
-		cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp);
+		xfs_notice(mp, "about to pop assert, bp == 0x%p", bp);
 #endif
 	ASSERT((XFS_BUF_BFLAGS(bp) & (XBF_STALE|XBF_DELWRI)) !=
 				     (XBF_STALE|XBF_DELWRI));
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index ccb3453..16084d8 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -44,28 +44,6 @@ xfs_trans_inode_broot_debug(
 #endif
 
 /*
- * Get an inode and join it to the transaction.
- */
-int
-xfs_trans_iget(
-	xfs_mount_t	*mp,
-	xfs_trans_t	*tp,
-	xfs_ino_t	ino,
-	uint		flags,
-	uint		lock_flags,
-	xfs_inode_t	**ipp)
-{
-	int			error;
-
-	error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp);
-	if (!error && tp) {
-		xfs_trans_ijoin(tp, *ipp);
-		(*ipp)->i_itemp->ili_lock_flags = lock_flags;
-	}
-	return error;
-}
-
-/*
  * Add a locked inode to the transaction.
  *
  * The inode must be locked, and it cannot be associated with any transaction.
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index d8e6f8c..37d8146 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1189,9 +1189,8 @@ xfs_inactive(
 		 * inode might be lost for a long time or forever.
 		 */
 		if (!XFS_FORCED_SHUTDOWN(mp)) {
-			cmn_err(CE_NOTE,
-		"xfs_inactive:	xfs_ifree() returned an error = %d on %s",
-				error, mp->m_fsname);
+			xfs_notice(mp, "%s: xfs_ifree returned error %d",
+				__func__, error);
 			xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 		}
 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
@@ -1208,12 +1207,12 @@ xfs_inactive(
 		 */
 		error = xfs_bmap_finish(&tp,  &free_list, &committed);
 		if (error)
-			xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
-				"xfs_bmap_finish() returned error %d", error);
+			xfs_notice(mp, "%s: xfs_bmap_finish returned error %d",
+				__func__, error);
 		error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
 		if (error)
-			xfs_fs_cmn_err(CE_NOTE, mp, "xfs_inactive: "
-				"xfs_trans_commit() returned error %d", error);
+			xfs_notice(mp, "%s: xfs_trans_commit returned error %d",
+				__func__, error);
 	}
 
 	/*
@@ -1310,7 +1309,7 @@ xfs_create(
 	error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
 			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
-		goto std_return;
+		return error;
 
 	if (is_dir) {
 		rdev = 0;
@@ -1390,12 +1389,6 @@ xfs_create(
 	}
 
 	/*
-	 * At this point, we've gotten a newly allocated inode.
-	 * It is locked (and joined to the transaction).
-	 */
-	ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
-	/*
 	 * Now we join the directory inode to the transaction.  We do not do it
 	 * earlier because xfs_dir_ialloc might commit the previous transaction
 	 * (and release all the locks).  An error from here on will result in
@@ -1440,22 +1433,13 @@ xfs_create(
 	 */
 	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
 
-	/*
-	 * xfs_trans_commit normally decrements the vnode ref count
-	 * when it unlocks the inode. Since we want to return the
-	 * vnode to the caller, we bump the vnode ref count now.
-	 */
-	IHOLD(ip);
-
 	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error)
-		goto out_abort_rele;
+		goto out_bmap_cancel;
 
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
-	if (error) {
-		IRELE(ip);
-		goto out_dqrele;
-	}
+	if (error)
+		goto out_release_inode;
 
 	xfs_qm_dqrele(udqp);
 	xfs_qm_dqrele(gdqp);
@@ -1469,27 +1453,21 @@ xfs_create(
 	cancel_flags |= XFS_TRANS_ABORT;
  out_trans_cancel:
 	xfs_trans_cancel(tp, cancel_flags);
- out_dqrele:
+ out_release_inode:
+	/*
+	 * Wait until after the current transaction is aborted to
+	 * release the inode.  This prevents recursive transactions
+	 * and deadlocks from xfs_inactive.
+	 */
+	if (ip)
+		IRELE(ip);
+
 	xfs_qm_dqrele(udqp);
 	xfs_qm_dqrele(gdqp);
 
 	if (unlock_dp_on_error)
 		xfs_iunlock(dp, XFS_ILOCK_EXCL);
- std_return:
 	return error;
-
- out_abort_rele:
-	/*
-	 * Wait until after the current transaction is aborted to
-	 * release the inode.  This prevents recursive transactions
-	 * and deadlocks from xfs_inactive.
-	 */
-	xfs_bmap_cancel(&free_list);
-	cancel_flags |= XFS_TRANS_ABORT;
-	xfs_trans_cancel(tp, cancel_flags);
-	IRELE(ip);
-	unlock_dp_on_error = B_FALSE;
-	goto out_dqrele;
 }
 
 #ifdef DEBUG
@@ -2114,9 +2092,8 @@ xfs_symlink(
 				  XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
 				  &first_block, resblks, mval, &nmaps,
 				  &free_list);
-		if (error) {
-			goto error1;
-		}
+		if (error)
+			goto error2;
 
 		if (resblks)
 			resblks -= fs_blocks;
@@ -2148,7 +2125,7 @@ xfs_symlink(
 	error = xfs_dir_createname(tp, dp, link_name, ip->i_ino,
 					&first_block, &free_list, resblks);
 	if (error)
-		goto error1;
+		goto error2;
 	xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
@@ -2161,13 +2138,6 @@ xfs_symlink(
 		xfs_trans_set_sync(tp);
 	}
 
-	/*
-	 * xfs_trans_commit normally decrements the vnode ref count
-	 * when it unlocks the inode. Since we want to return the
-	 * vnode to the caller, we bump the vnode ref count now.
-	 */
-	IHOLD(ip);
-
 	error = xfs_bmap_finish(&tp, &free_list, &committed);
 	if (error) {
 		goto error2;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 78ca429..ff103ba 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -381,7 +381,7 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 int acpi_pm_device_sleep_state(struct device *, int *);
 #else
 static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
diff --git a/include/asm-generic/cputime.h b/include/asm-generic/cputime.h
index 2bcc5c7..61e03dd 100644
--- a/include/asm-generic/cputime.h
+++ b/include/asm-generic/cputime.h
@@ -30,6 +30,9 @@ typedef u64 cputime64_t;
 #define cputime64_to_jiffies64(__ct)	(__ct)
 #define jiffies64_to_cputime64(__jif)	(__jif)
 #define cputime_to_cputime64(__ct)	((u64) __ct)
+#define cputime64_gt(__a, __b)		((__a) >  (__b))
+
+#define nsecs_to_cputime64(__ct)	nsecs_to_jiffies64(__ct)
 
 
 /*
diff --git a/include/asm-generic/errno.h b/include/asm-generic/errno.h
index 28cc03b..a1331ce 100644
--- a/include/asm-generic/errno.h
+++ b/include/asm-generic/errno.h
@@ -108,4 +108,6 @@
 
 #define ERFKILL		132	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	133	/* Memory page has hardware error */
+
 #endif
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index 0fc16e3..84793c7 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -80,6 +80,10 @@
 #define O_SYNC		(__O_SYNC|O_DSYNC)
 #endif
 
+#ifndef O_PATH
+#define O_PATH		010000000
+#endif
+
 #ifndef O_NDELAY
 #define O_NDELAY	O_NONBLOCK
 #endif
diff --git a/include/asm-generic/ftrace.h b/include/asm-generic/ftrace.h
new file mode 100644
index 0000000..51abba9
--- /dev/null
+++ b/include/asm-generic/ftrace.h
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-generic/ftrace.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_GENERIC_FTRACE_H__
+#define __ASM_GENERIC_FTRACE_H__
+
+/*
+ * Not all architectures need their own ftrace.h, the most
+ * common definitions are already in linux/ftrace.h.
+ */
+
+#endif /* __ASM_GENERIC_FTRACE_H__ */
diff --git a/include/asm-generic/futex.h b/include/asm-generic/futex.h
index 3c2344f..01f227e 100644
--- a/include/asm-generic/futex.h
+++ b/include/asm-generic/futex.h
@@ -6,7 +6,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -16,7 +16,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -48,7 +48,8 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 4644c9a..e0ffa3d 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -94,6 +94,10 @@ static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
 #define writeq(b,addr) __raw_writeq(__cpu_to_le64(b),addr)
 #endif
 
+#ifndef PCI_IOBASE
+#define PCI_IOBASE ((void __iomem *) 0)
+#endif
+
 /*****************************************************************************/
 /*
  * traditional input/output functions
@@ -101,32 +105,32 @@ static inline void __raw_writeq(u64 b, volatile void __iomem *addr)
 
 static inline u8 inb(unsigned long addr)
 {
-	return readb((volatile void __iomem *) addr);
+	return readb(addr + PCI_IOBASE);
 }
 
 static inline u16 inw(unsigned long addr)
 {
-	return readw((volatile void __iomem *) addr);
+	return readw(addr + PCI_IOBASE);
 }
 
 static inline u32 inl(unsigned long addr)
 {
-	return readl((volatile void __iomem *) addr);
+	return readl(addr + PCI_IOBASE);
 }
 
 static inline void outb(u8 b, unsigned long addr)
 {
-	writeb(b, (volatile void __iomem *) addr);
+	writeb(b, addr + PCI_IOBASE);
 }
 
 static inline void outw(u16 b, unsigned long addr)
 {
-	writew(b, (volatile void __iomem *) addr);
+	writew(b, addr + PCI_IOBASE);
 }
 
 static inline void outl(u32 b, unsigned long addr)
 {
-	writel(b, (volatile void __iomem *) addr);
+	writel(b, addr + PCI_IOBASE);
 }
 
 #define inb_p(addr)	inb(addr)
@@ -213,32 +217,32 @@ static inline void outsl(unsigned long addr, const void *buffer, int count)
 
 static inline void readsl(const void __iomem *addr, void *buf, int len)
 {
-	insl((unsigned long)addr, buf, len);
+	insl(addr - PCI_IOBASE, buf, len);
 }
 
 static inline void readsw(const void __iomem *addr, void *buf, int len)
 {
-	insw((unsigned long)addr, buf, len);
+	insw(addr - PCI_IOBASE, buf, len);
 }
 
 static inline void readsb(const void __iomem *addr, void *buf, int len)
 {
-	insb((unsigned long)addr, buf, len);
+	insb(addr - PCI_IOBASE, buf, len);
 }
 
 static inline void writesl(const void __iomem *addr, const void *buf, int len)
 {
-	outsl((unsigned long)addr, buf, len);
+	outsl(addr - PCI_IOBASE, buf, len);
 }
 
 static inline void writesw(const void __iomem *addr, const void *buf, int len)
 {
-	outsw((unsigned long)addr, buf, len);
+	outsw(addr - PCI_IOBASE, buf, len);
 }
 
 static inline void writesb(const void __iomem *addr, const void *buf, int len)
 {
-	outsb((unsigned long)addr, buf, len);
+	outsb(addr - PCI_IOBASE, buf, len);
 }
 
 #ifndef CONFIG_GENERIC_IOMAP
@@ -269,8 +273,9 @@ static inline void writesb(const void __iomem *addr, const void *buf, int len)
 	outsl((unsigned long) (p), (src), (count))
 #endif /* CONFIG_GENERIC_IOMAP */
 
-
-#define IO_SPACE_LIMIT 0xffffffff
+#ifndef IO_SPACE_LIMIT
+#define IO_SPACE_LIMIT 0xffff
+#endif
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-generic/ioctls.h b/include/asm-generic/ioctls.h
index 3f3f2d1..199975f 100644
--- a/include/asm-generic/ioctls.h
+++ b/include/asm-generic/ioctls.h
@@ -73,6 +73,7 @@
 #define TCSETXF		0x5434
 #define TCSETXW		0x5435
 #define TIOCSIG		_IOW('T', 0x36, int)  /* pty: generate signal */
+#define TIOCVHANGUP	0x5437
 
 #define FIONCLEX	0x5450
 #define FIOCLEX		0x5451
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b3bfabc..c1a1216 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -11,6 +11,7 @@ extern char _sinittext[], _einittext[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
 extern char __kprobes_text_start[], __kprobes_text_end[];
+extern char __entry_text_start[], __entry_text_end[];
 extern char __initdata_begin[], __initdata_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/sizes.h b/include/asm-generic/sizes.h
new file mode 100644
index 0000000..ea5d4ef
--- /dev/null
+++ b/include/asm-generic/sizes.h
@@ -0,0 +1,47 @@
+/*
+ * linux/include/asm-generic/sizes.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_GENERIC_SIZES_H__
+#define __ASM_GENERIC_SIZES_H__
+
+#define SZ_1				0x00000001
+#define SZ_2				0x00000002
+#define SZ_4				0x00000004
+#define SZ_8				0x00000008
+#define SZ_16				0x00000010
+#define SZ_32				0x00000020
+#define SZ_64				0x00000040
+#define SZ_128				0x00000080
+#define SZ_256				0x00000100
+#define SZ_512				0x00000200
+
+#define SZ_1K				0x00000400
+#define SZ_2K				0x00000800
+#define SZ_4K				0x00001000
+#define SZ_8K				0x00002000
+#define SZ_16K				0x00004000
+#define SZ_32K				0x00008000
+#define SZ_64K				0x00010000
+#define SZ_128K				0x00020000
+#define SZ_256K				0x00040000
+#define SZ_512K				0x00080000
+
+#define SZ_1M				0x00100000
+#define SZ_2M				0x00200000
+#define SZ_4M				0x00400000
+#define SZ_8M				0x00800000
+#define SZ_16M				0x01000000
+#define SZ_32M				0x02000000
+#define SZ_64M				0x04000000
+#define SZ_128M				0x08000000
+#define SZ_256M				0x10000000
+#define SZ_512M				0x20000000
+
+#define SZ_1G				0x40000000
+#define SZ_2G				0x80000000
+
+#endif /* __ASM_GENERIC_SIZES_H__ */
diff --git a/include/asm-generic/types.h b/include/asm-generic/types.h
index fba7d33..7a0f69e 100644
--- a/include/asm-generic/types.h
+++ b/include/asm-generic/types.h
@@ -12,31 +12,4 @@ typedef unsigned short umode_t;
 
 #endif /* __ASSEMBLY__ */
 
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-/*
- * DMA addresses may be very different from physical addresses
- * and pointers. i386 and powerpc may have 64 bit DMA on 32 bit
- * systems, while sparc64 uses 32 bit DMA addresses for 64 bit
- * physical addresses.
- * This default defines dma_addr_t to have the same size as
- * phys_addr_t, which is the most common way.
- * Do not define the dma64_addr_t type, which never really
- * worked.
- */
-#ifndef dma_addr_t
-#ifdef CONFIG_PHYS_ADDR_T_64BIT
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif /* CONFIG_PHYS_ADDR_T_64BIT */
-#endif /* dma_addr_t */
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_GENERIC_TYPES_H */
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index b218b85..ac68c99 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -288,14 +288,16 @@ strncpy_from_user(char *dst, const char __user *src, long count)
  *
  * Return 0 on exception, a value greater than N if too long
  */
-#ifndef strnlen_user
+#ifndef __strnlen_user
+#define __strnlen_user strnlen
+#endif
+
 static inline long strnlen_user(const char __user *src, long n)
 {
 	if (!access_ok(VERIFY_READ, src, 1))
 		return 0;
-	return strlen((void * __force)src) + 1;
+	return __strnlen_user(src, n);
 }
-#endif
 
 static inline long strlen_user(const char __user *src)
 {
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index b969770..07c40d5 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -646,9 +646,17 @@ __SYSCALL(__NR_prlimit64, sys_prlimit64)
 __SYSCALL(__NR_fanotify_init, sys_fanotify_init)
 #define __NR_fanotify_mark 263
 __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
+#define __NR_name_to_handle_at		264
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at		265
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
+#define __NR_clock_adjtime 266
+__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
+#define __NR_syncfs 267
+__SYSCALL(__NR_syncfs, sys_syncfs)
 
 #undef __NR_syscalls
-#define __NR_syscalls 264
+#define __NR_syscalls 268
 
 /*
  * All syscalls below here should go away really,
diff --git a/include/asm-generic/user.h b/include/asm-generic/user.h
index 8b9c3c9..35638c3 100644
--- a/include/asm-generic/user.h
+++ b/include/asm-generic/user.h
@@ -1,8 +1,8 @@
 #ifndef __ASM_GENERIC_USER_H
 #define __ASM_GENERIC_USER_H
 /*
- * This file may define a 'struct user' structure. However, it it only
- * used for a.out file, which are not supported on new architectures.
+ * This file may define a 'struct user' structure. However, it is only
+ * used for a.out files, which are not supported on new architectures.
  */
 
 #endif	/* __ASM_GENERIC_USER_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index fe77e33..32c45e5 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -15,7 +15,7 @@
  *	HEAD_TEXT_SECTION
  *	INIT_TEXT_SECTION(PAGE_SIZE)
  *	INIT_DATA_SECTION(...)
- *	PERCPU(PAGE_SIZE)
+ *	PERCPU(CACHELINE_SIZE, PAGE_SIZE)
  *	__init_end = .;
  *
  *	_stext = .;
@@ -424,6 +424,12 @@
 		*(.kprobes.text)					\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
+#define ENTRY_TEXT							\
+		ALIGN_FUNCTION();					\
+		VMLINUX_SYMBOL(__entry_text_start) = .;			\
+		*(.entry.text)						\
+		VMLINUX_SYMBOL(__entry_text_end) = .;
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 #define IRQENTRY_TEXT							\
 		ALIGN_FUNCTION();					\
@@ -683,13 +689,18 @@
 
 /**
  * PERCPU_VADDR - define output section for percpu area
+ * @cacheline: cacheline size
  * @vaddr: explicit base address (optional)
  * @phdr: destination PHDR (optional)
  *
- * Macro which expands to output section for percpu area.  If @vaddr
- * is not blank, it specifies explicit base address and all percpu
- * symbols will be offset from the given address.  If blank, @vaddr
- * always equals @laddr + LOAD_OFFSET.
+ * Macro which expands to output section for percpu area.
+ *
+ * @cacheline is used to align subsections to avoid false cacheline
+ * sharing between subsections for different purposes.
+ *
+ * If @vaddr is not blank, it specifies explicit base address and all
+ * percpu symbols will be offset from the given address.  If blank,
+ * @vaddr always equals @laddr + LOAD_OFFSET.
  *
  * @phdr defines the output PHDR to use if not blank.  Be warned that
  * output PHDR is sticky.  If @phdr is specified, the next output
@@ -700,7 +711,7 @@
  * If there is no need to put the percpu section at a predetermined
  * address, use PERCPU().
  */
-#define PERCPU_VADDR(vaddr, phdr)					\
+#define PERCPU_VADDR(cacheline, vaddr, phdr)				\
 	VMLINUX_SYMBOL(__per_cpu_load) = .;				\
 	.data..percpu vaddr : AT(VMLINUX_SYMBOL(__per_cpu_load)		\
 				- LOAD_OFFSET) {			\
@@ -708,7 +719,9 @@
 		*(.data..percpu..first)					\
 		. = ALIGN(PAGE_SIZE);					\
 		*(.data..percpu..page_aligned)				\
+		. = ALIGN(cacheline);					\
 		*(.data..percpu..readmostly)				\
+		. = ALIGN(cacheline);					\
 		*(.data..percpu)					\
 		*(.data..percpu..shared_aligned)			\
 		VMLINUX_SYMBOL(__per_cpu_end) = .;			\
@@ -717,18 +730,18 @@
 
 /**
  * PERCPU - define output section for percpu area, simple version
+ * @cacheline: cacheline size
  * @align: required alignment
  *
- * Align to @align and outputs output section for percpu area.  This
- * macro doesn't maniuplate @vaddr or @phdr and __per_cpu_load and
+ * Align to @align and outputs output section for percpu area.  This macro
+ * doesn't manipulate @vaddr or @phdr and __per_cpu_load and
  * __per_cpu_start will be identical.
  *
- * This macro is equivalent to ALIGN(align); PERCPU_VADDR( , ) except
- * that __per_cpu_load is defined as a relative symbol against
- * .data..percpu which is required for relocatable x86_32
- * configuration.
+ * This macro is equivalent to ALIGN(@align); PERCPU_VADDR(@cacheline,,)
+ * except that __per_cpu_load is defined as a relative symbol against
+ * .data..percpu which is required for relocatable x86_32 configuration.
  */
-#define PERCPU(align)							\
+#define PERCPU(cacheline, align)					\
 	. = ALIGN(align);						\
 	.data..percpu	: AT(ADDR(.data..percpu) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__per_cpu_load) = .;			\
@@ -736,7 +749,9 @@
 		*(.data..percpu..first)					\
 		. = ALIGN(PAGE_SIZE);					\
 		*(.data..percpu..page_aligned)				\
+		. = ALIGN(cacheline);					\
 		*(.data..percpu..readmostly)				\
+		. = ALIGN(cacheline);					\
 		*(.data..percpu)					\
 		*(.data..percpu..shared_aligned)			\
 		VMLINUX_SYMBOL(__per_cpu_end) = .;			\
diff --git a/include/drm/Kbuild b/include/drm/Kbuild
index ffec177..3a60ac8 100644
--- a/include/drm/Kbuild
+++ b/include/drm/Kbuild
@@ -2,7 +2,6 @@ header-y += drm.h
 header-y += drm_mode.h
 header-y += drm_sarea.h
 header-y += i810_drm.h
-header-y += i830_drm.h
 header-y += i915_drm.h
 header-y += mga_drm.h
 header-y += nouveau_drm.h
diff --git a/include/drm/drm.h b/include/drm/drm.h
index e5f7061..9ac4313 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -608,6 +608,12 @@ struct drm_gem_open {
 	__u64 size;
 };
 
+/** DRM_IOCTL_GET_CAP ioctl argument type */
+struct drm_get_cap {
+	__u64 capability;
+	__u64 value;
+};
+
 #include "drm_mode.h"
 
 #define DRM_IOCTL_BASE			'd'
@@ -628,6 +634,7 @@ struct drm_gem_open {
 #define DRM_IOCTL_GEM_CLOSE		DRM_IOW (0x09, struct drm_gem_close)
 #define DRM_IOCTL_GEM_FLINK		DRM_IOWR(0x0a, struct drm_gem_flink)
 #define DRM_IOCTL_GEM_OPEN		DRM_IOWR(0x0b, struct drm_gem_open)
+#define DRM_IOCTL_GET_CAP		DRM_IOWR(0x0c, struct drm_get_cap)
 
 #define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
 #define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
@@ -701,6 +708,10 @@ struct drm_gem_open {
 #define DRM_IOCTL_MODE_PAGE_FLIP	DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
 #define DRM_IOCTL_MODE_DIRTYFB		DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
 
+#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
+#define DRM_IOCTL_MODE_MAP_DUMB    DRM_IOWR(0xB3, struct drm_mode_map_dumb)
+#define DRM_IOCTL_MODE_DESTROY_DUMB    DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x99.
@@ -741,6 +752,8 @@ struct drm_event_vblank {
 	__u32 reserved;
 };
 
+#define DRM_CAP_DUMB_BUFFER 0x1
+
 /* typedef area */
 #ifndef __KERNEL__
 typedef struct drm_clip_rect drm_clip_rect_t;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 348843b..ad5770f 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -145,7 +145,10 @@ extern void drm_ut_debug_printk(unsigned int request_level,
 #define DRIVER_IRQ_VBL2    0x800
 #define DRIVER_GEM         0x1000
 #define DRIVER_MODESET     0x2000
-#define DRIVER_USE_PLATFORM_DEVICE  0x4000
+
+#define DRIVER_BUS_PCI 0x1
+#define DRIVER_BUS_PLATFORM 0x2
+#define DRIVER_BUS_USB 0x3
 
 /***********************************************************************/
 /** \name Begin the DRM... */
@@ -698,6 +701,19 @@ struct drm_master {
 #define DRM_SCANOUTPOS_INVBL        (1 << 1)
 #define DRM_SCANOUTPOS_ACCURATE     (1 << 2)
 
+struct drm_bus {
+	int bus_type;
+	int (*get_irq)(struct drm_device *dev);
+	const char *(*get_name)(struct drm_device *dev);
+	int (*set_busid)(struct drm_device *dev, struct drm_master *master);
+	int (*set_unique)(struct drm_device *dev, struct drm_master *master,
+			  struct drm_unique *unique);
+	int (*irq_by_busid)(struct drm_device *dev, struct drm_irq_busid *p);
+	/* hooks that are for PCI */
+	int (*agp_init)(struct drm_device *dev);
+
+};
+
 /**
  * DRM driver structure. This structure represent the common code for
  * a family of cards. There will one drm_device for each card present
@@ -880,6 +896,17 @@ struct drm_driver {
 	/* vga arb irq handler */
 	void (*vgaarb_irq)(struct drm_device *dev, bool state);
 
+	/* dumb alloc support */
+	int (*dumb_create)(struct drm_file *file_priv,
+			   struct drm_device *dev,
+			   struct drm_mode_create_dumb *args);
+	int (*dumb_map_offset)(struct drm_file *file_priv,
+			       struct drm_device *dev, uint32_t handle,
+			       uint64_t *offset);
+	int (*dumb_destroy)(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    uint32_t handle);
+
 	/* Driver private ops for this object */
 	struct vm_operations_struct *gem_vm_ops;
 
@@ -895,8 +922,13 @@ struct drm_driver {
 	struct drm_ioctl_desc *ioctls;
 	int num_ioctls;
 	struct file_operations fops;
-	struct pci_driver pci_driver;
-	struct platform_device *platform_device;
+	union {
+		struct pci_driver *pci;
+		struct platform_device *platform_device;
+		struct usb_driver *usb;
+	} kdriver;
+	struct drm_bus *bus;
+
 	/* List of devices hanging off this driver */
 	struct list_head device_list;
 };
@@ -1099,6 +1131,7 @@ struct drm_device {
 #endif
 
 	struct platform_device *platformdev; /**< Platform device struture */
+	struct usb_device *usbdev;
 
 	struct drm_sg_mem *sg;	/**< Scatter gather memory */
 	unsigned int num_crtcs;                  /**< Number of CRTCs on this device */
@@ -1136,28 +1169,9 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev,
 
 static inline int drm_dev_to_irq(struct drm_device *dev)
 {
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
-		return platform_get_irq(dev->platformdev, 0);
-	else
-		return dev->pdev->irq;
+	return dev->driver->bus->get_irq(dev);
 }
 
-static inline int drm_get_pci_domain(struct drm_device *dev)
-{
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
-		return 0;
-
-#ifndef __alpha__
-	/* For historical reasons, drm_get_pci_domain() is busticated
-	 * on most archs and has to remain so for userspace interface
-	 * < 1.4, except on alpha which was right from the beginning
-	 */
-	if (dev->if_version < 0x10004)
-		return 0;
-#endif /* __alpha__ */
-
-	return pci_domain_nr(dev->pdev->bus);
-}
 
 #if __OS_HAS_AGP
 static inline int drm_core_has_AGP(struct drm_device *dev)
@@ -1211,8 +1225,6 @@ static inline int drm_mtrr_del(int handle, unsigned long offset,
 /*@{*/
 
 				/* Driver support (drm_drv.h) */
-extern int drm_init(struct drm_driver *driver);
-extern void drm_exit(struct drm_driver *driver);
 extern long drm_ioctl(struct file *filp,
 		      unsigned int cmd, unsigned long arg);
 extern long drm_compat_ioctl(struct file *filp,
@@ -1264,6 +1276,8 @@ extern int drm_getclient(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int drm_getstats(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
+extern int drm_getcap(struct drm_device *dev, void *data,
+		      struct drm_file *file_priv);
 extern int drm_setversion(struct drm_device *dev, void *data,
 			  struct drm_file *file_priv);
 extern int drm_noop(struct drm_device *dev, void *data,
@@ -1422,11 +1436,7 @@ extern int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
 struct drm_master *drm_master_create(struct drm_minor *minor);
 extern struct drm_master *drm_master_get(struct drm_master *master);
 extern void drm_master_put(struct drm_master **master);
-extern int drm_get_pci_dev(struct pci_dev *pdev,
-			   const struct pci_device_id *ent,
-			   struct drm_driver *driver);
-extern int drm_get_platform_dev(struct platform_device *pdev,
-				struct drm_driver *driver);
+
 extern void drm_put_dev(struct drm_device *dev);
 extern int drm_put_minor(struct drm_minor **minor);
 extern unsigned int drm_debug;
@@ -1544,6 +1554,7 @@ drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
 int drm_gem_handle_create(struct drm_file *file_priv,
 			  struct drm_gem_object *obj,
 			  u32 *handlep);
+int drm_gem_handle_delete(struct drm_file *filp, u32 handle);
 
 static inline void
 drm_gem_object_handle_reference(struct drm_gem_object *obj)
@@ -1616,11 +1627,21 @@ static __inline__ struct drm_local_map *drm_core_findmap(struct drm_device *dev,
 	return NULL;
 }
 
-static __inline__ int drm_device_is_agp(struct drm_device *dev)
+static __inline__ void drm_core_dropmap(struct drm_local_map *map)
 {
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
-		return 0;
+}
 
+#include "drm_mem_util.h"
+
+extern int drm_fill_in_dev(struct drm_device *dev,
+			   const struct pci_device_id *ent,
+			   struct drm_driver *driver);
+int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type);
+/*@}*/
+
+/* PCI section */
+static __inline__ int drm_pci_device_is_agp(struct drm_device *dev)
+{
 	if (dev->driver->device_is_agp != NULL) {
 		int err = (*dev->driver->device_is_agp) (dev);
 
@@ -1632,35 +1653,26 @@ static __inline__ int drm_device_is_agp(struct drm_device *dev)
 	return pci_find_capability(dev->pdev, PCI_CAP_ID_AGP);
 }
 
-static __inline__ int drm_device_is_pcie(struct drm_device *dev)
-{
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
-		return 0;
-	else
-		return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
-}
 
-static __inline__ void drm_core_dropmap(struct drm_local_map *map)
+static __inline__ int drm_pci_device_is_pcie(struct drm_device *dev)
 {
+	return pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
 }
 
-#include "drm_mem_util.h"
-
-static inline void *drm_get_device(struct drm_device *dev)
-{
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
-		return dev->platformdev;
-	else
-		return dev->pdev;
-}
 
-extern int drm_platform_init(struct drm_driver *driver);
-extern int drm_pci_init(struct drm_driver *driver);
-extern int drm_fill_in_dev(struct drm_device *dev,
+extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
+extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
+extern int drm_get_pci_dev(struct pci_dev *pdev,
 			   const struct pci_device_id *ent,
 			   struct drm_driver *driver);
-int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type);
-/*@}*/
+
+
+/* platform section */
+extern int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device);
+extern void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device);
+
+extern int drm_get_platform_dev(struct platform_device *pdev,
+				struct drm_driver *driver);
 
 #endif				/* __KERNEL__ */
 #endif
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 801be59..60edf9b 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -659,7 +659,7 @@ extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid
 extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
 extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode);
 extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
-						   struct drm_display_mode *mode);
+						   const struct drm_display_mode *mode);
 extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode);
 extern void drm_mode_config_init(struct drm_device *dev);
 extern void drm_mode_config_reset(struct drm_device *dev);
@@ -685,8 +685,8 @@ extern void drm_mode_validate_size(struct drm_device *dev,
 extern void drm_mode_prune_invalid(struct drm_device *dev,
 				   struct list_head *mode_list, bool verbose);
 extern void drm_mode_sort(struct list_head *mode_list);
-extern int drm_mode_hsync(struct drm_display_mode *mode);
-extern int drm_mode_vrefresh(struct drm_display_mode *mode);
+extern int drm_mode_hsync(const struct drm_display_mode *mode);
+extern int drm_mode_vrefresh(const struct drm_display_mode *mode);
 extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
 				  int adjust_flags);
 extern void drm_mode_connector_list_update(struct drm_connector *connector);
@@ -798,4 +798,11 @@ extern int drm_add_modes_noedid(struct drm_connector *connector,
 extern bool drm_edid_is_valid(struct edid *edid);
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh);
+
+extern int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+				      void *data, struct drm_file *file_priv);
+extern int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+				    void *data, struct drm_file *file_priv);
+extern int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+				      void *data, struct drm_file *file_priv);
 #endif /* __DRM_CRTC_H__ */
diff --git a/include/drm/drm_hashtab.h b/include/drm/drm_hashtab.h
index 0af087a..3650d5d 100644
--- a/include/drm/drm_hashtab.h
+++ b/include/drm/drm_hashtab.h
@@ -45,14 +45,10 @@ struct drm_hash_item {
 };
 
 struct drm_open_hash {
-	unsigned int size;
-	unsigned int order;
-	unsigned int fill;
 	struct hlist_head *table;
-	int use_vmalloc;
+	u8 order;
 };
 
-
 extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
 extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
 extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index e391777..b1e7809 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -42,23 +42,25 @@
 #endif
 
 struct drm_mm_node {
-	struct list_head free_stack;
 	struct list_head node_list;
-	unsigned free : 1;
+	struct list_head hole_stack;
+	unsigned hole_follows : 1;
 	unsigned scanned_block : 1;
 	unsigned scanned_prev_free : 1;
 	unsigned scanned_next_free : 1;
+	unsigned scanned_preceeds_hole : 1;
+	unsigned allocated : 1;
 	unsigned long start;
 	unsigned long size;
 	struct drm_mm *mm;
 };
 
 struct drm_mm {
-	/* List of free memory blocks, most recently freed ordered. */
-	struct list_head free_stack;
-	/* List of all memory nodes, ordered according to the (increasing) start
-	 * address of the memory node. */
-	struct list_head node_list;
+	/* List of all memory nodes that immediatly preceed a free hole. */
+	struct list_head hole_stack;
+	/* head_node.node_list is the list of all memory nodes, ordered
+	 * according to the (increasing) start address of the memory node. */
+	struct drm_mm_node head_node;
 	struct list_head unused_nodes;
 	int num_unused;
 	spinlock_t unused_lock;
@@ -70,8 +72,28 @@ struct drm_mm {
 	unsigned scanned_blocks;
 	unsigned long scan_start;
 	unsigned long scan_end;
+	struct drm_mm_node *prev_scanned_node;
 };
 
+static inline bool drm_mm_node_allocated(struct drm_mm_node *node)
+{
+	return node->allocated;
+}
+
+static inline bool drm_mm_initialized(struct drm_mm *mm)
+{
+	return mm->hole_stack.next;
+}
+#define drm_mm_for_each_node(entry, mm) list_for_each_entry(entry, \
+						&(mm)->head_node.node_list, \
+						node_list);
+#define drm_mm_for_each_scanned_node_reverse(entry, n, mm) \
+	for (entry = (mm)->prev_scanned_node, \
+		next = entry ? list_entry(entry->node_list.next, \
+			struct drm_mm_node, node_list) : NULL; \
+	     entry != NULL; entry = next, \
+		next = entry ? list_entry(entry->node_list.next, \
+			struct drm_mm_node, node_list) : NULL) \
 /*
  * Basic range manager support (drm_mm.c)
  */
@@ -118,7 +140,15 @@ static inline struct drm_mm_node *drm_mm_get_block_atomic_range(
 	return drm_mm_get_block_range_generic(parent, size, alignment,
 						start, end, 1);
 }
+extern int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
+			      unsigned long size, unsigned alignment);
+extern int drm_mm_insert_node_in_range(struct drm_mm *mm,
+				       struct drm_mm_node *node,
+				       unsigned long size, unsigned alignment,
+				       unsigned long start, unsigned long end);
 extern void drm_mm_put_block(struct drm_mm_node *cur);
+extern void drm_mm_remove_node(struct drm_mm_node *node);
+extern void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new);
 extern struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
 					      unsigned long size,
 					      unsigned alignment,
@@ -134,11 +164,6 @@ extern int drm_mm_init(struct drm_mm *mm, unsigned long start,
 		       unsigned long size);
 extern void drm_mm_takedown(struct drm_mm *mm);
 extern int drm_mm_clean(struct drm_mm *mm);
-extern unsigned long drm_mm_tail_space(struct drm_mm *mm);
-extern int drm_mm_remove_space_from_tail(struct drm_mm *mm,
-					 unsigned long size);
-extern int drm_mm_add_space_to_tail(struct drm_mm *mm,
-				    unsigned long size, int atomic);
 extern int drm_mm_pre_get(struct drm_mm *mm);
 
 static inline struct drm_mm *drm_get_mm(struct drm_mm_node *block)
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index 0fc7397..ae6b7a3 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -344,4 +344,33 @@ struct drm_mode_crtc_page_flip {
 	__u64 user_data;
 };
 
+/* create a dumb scanout buffer */
+struct drm_mode_create_dumb {
+	uint32_t height;
+	uint32_t width;
+	uint32_t bpp;
+	uint32_t flags;
+	/* handle, pitch, size will be returned */
+	uint32_t handle;
+	uint32_t pitch;
+	uint64_t size;
+};
+
+/* set up for mmap of a dumb scanout buffer */
+struct drm_mode_map_dumb {
+	/** Handle for the object being mapped. */
+	__u32 handle;
+	__u32 pad;
+	/**
+	 * Fake offset to use for subsequent mmap call
+	 *
+	 * This is a fixed-size type for 32/64 compatibility.
+	 */
+	__u64 offset;
+};
+
+struct drm_mode_destroy_dumb {
+	uint32_t handle;
+};
+
 #endif
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 5ff1194..820ee90 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -141,6 +141,20 @@
 	{0x1002, 0x5e4c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x5e4f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6703, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6704, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6705, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6707, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6708, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6709, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6718, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x6719, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x671c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+	{0x1002, 0x671d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
 	{0x1002, 0x6722, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
diff --git a/include/drm/drm_usb.h b/include/drm/drm_usb.h
new file mode 100644
index 0000000..33506c11
--- /dev/null
+++ b/include/drm/drm_usb.h
@@ -0,0 +1,15 @@
+#ifndef DRM_USB_H
+#define DRM_USB_H
+
+#include <drmP.h>
+
+#include <linux/usb.h>
+
+extern int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver);
+extern void drm_usb_exit(struct drm_driver *driver, struct usb_driver *udriver);
+
+int drm_get_usb_dev(struct usb_interface *interface,
+		    const struct usb_device_id *id,
+		    struct drm_driver *driver);
+
+#endif
diff --git a/include/drm/i830_drm.h b/include/drm/i830_drm.h
deleted file mode 100644
index 61315c2..0000000
--- a/include/drm/i830_drm.h
+++ /dev/null
@@ -1,342 +0,0 @@
-#ifndef _I830_DRM_H_
-#define _I830_DRM_H_
-
-/* WARNING: These defines must be the same as what the Xserver uses.
- * if you change them, you must change the defines in the Xserver.
- *
- * KW: Actually, you can't ever change them because doing so would
- * break backwards compatibility.
- */
-
-#ifndef _I830_DEFINES_
-#define _I830_DEFINES_
-
-#define I830_DMA_BUF_ORDER		12
-#define I830_DMA_BUF_SZ			(1<<I830_DMA_BUF_ORDER)
-#define I830_DMA_BUF_NR			256
-#define I830_NR_SAREA_CLIPRECTS		8
-
-/* Each region is a minimum of 64k, and there are at most 64 of them.
- */
-#define I830_NR_TEX_REGIONS 64
-#define I830_LOG_MIN_TEX_REGION_SIZE 16
-
-/* KW: These aren't correct but someone set them to two and then
- * released the module.  Now we can't change them as doing so would
- * break backwards compatibility.
- */
-#define I830_TEXTURE_COUNT	2
-#define I830_TEXBLEND_COUNT	I830_TEXTURE_COUNT
-
-#define I830_TEXBLEND_SIZE	12	/* (4 args + op) * 2 + COLOR_FACTOR */
-
-#define I830_UPLOAD_CTX			0x1
-#define I830_UPLOAD_BUFFERS		0x2
-#define I830_UPLOAD_CLIPRECTS		0x4
-#define I830_UPLOAD_TEX0_IMAGE		0x100	/* handled clientside */
-#define I830_UPLOAD_TEX0_CUBE		0x200	/* handled clientside */
-#define I830_UPLOAD_TEX1_IMAGE		0x400	/* handled clientside */
-#define I830_UPLOAD_TEX1_CUBE		0x800	/* handled clientside */
-#define I830_UPLOAD_TEX2_IMAGE		0x1000	/* handled clientside */
-#define I830_UPLOAD_TEX2_CUBE		0x2000	/* handled clientside */
-#define I830_UPLOAD_TEX3_IMAGE		0x4000	/* handled clientside */
-#define I830_UPLOAD_TEX3_CUBE		0x8000	/* handled clientside */
-#define I830_UPLOAD_TEX_N_IMAGE(n)	(0x100 << (n * 2))
-#define I830_UPLOAD_TEX_N_CUBE(n)	(0x200 << (n * 2))
-#define I830_UPLOAD_TEXIMAGE_MASK	0xff00
-#define I830_UPLOAD_TEX0			0x10000
-#define I830_UPLOAD_TEX1			0x20000
-#define I830_UPLOAD_TEX2			0x40000
-#define I830_UPLOAD_TEX3			0x80000
-#define I830_UPLOAD_TEX_N(n)		(0x10000 << (n))
-#define I830_UPLOAD_TEX_MASK		0xf0000
-#define I830_UPLOAD_TEXBLEND0		0x100000
-#define I830_UPLOAD_TEXBLEND1		0x200000
-#define I830_UPLOAD_TEXBLEND2		0x400000
-#define I830_UPLOAD_TEXBLEND3		0x800000
-#define I830_UPLOAD_TEXBLEND_N(n)	(0x100000 << (n))
-#define I830_UPLOAD_TEXBLEND_MASK	0xf00000
-#define I830_UPLOAD_TEX_PALETTE_N(n)    (0x1000000 << (n))
-#define I830_UPLOAD_TEX_PALETTE_SHARED	0x4000000
-#define I830_UPLOAD_STIPPLE		0x8000000
-
-/* Indices into buf.Setup where various bits of state are mirrored per
- * context and per buffer.  These can be fired at the card as a unit,
- * or in a piecewise fashion as required.
- */
-
-/* Destbuffer state
- *    - backbuffer linear offset and pitch -- invarient in the current dri
- *    - zbuffer linear offset and pitch -- also invarient
- *    - drawing origin in back and depth buffers.
- *
- * Keep the depth/back buffer state here to accommodate private buffers
- * in the future.
- */
-
-#define I830_DESTREG_CBUFADDR 0
-#define I830_DESTREG_DBUFADDR 1
-#define I830_DESTREG_DV0 2
-#define I830_DESTREG_DV1 3
-#define I830_DESTREG_SENABLE 4
-#define I830_DESTREG_SR0 5
-#define I830_DESTREG_SR1 6
-#define I830_DESTREG_SR2 7
-#define I830_DESTREG_DR0 8
-#define I830_DESTREG_DR1 9
-#define I830_DESTREG_DR2 10
-#define I830_DESTREG_DR3 11
-#define I830_DESTREG_DR4 12
-#define I830_DEST_SETUP_SIZE 13
-
-/* Context state
- */
-#define I830_CTXREG_STATE1		0
-#define I830_CTXREG_STATE2		1
-#define I830_CTXREG_STATE3		2
-#define I830_CTXREG_STATE4		3
-#define I830_CTXREG_STATE5		4
-#define I830_CTXREG_IALPHAB		5
-#define I830_CTXREG_STENCILTST		6
-#define I830_CTXREG_ENABLES_1		7
-#define I830_CTXREG_ENABLES_2		8
-#define I830_CTXREG_AA			9
-#define I830_CTXREG_FOGCOLOR		10
-#define I830_CTXREG_BLENDCOLR0		11
-#define I830_CTXREG_BLENDCOLR		12	/* Dword 1 of 2 dword command */
-#define I830_CTXREG_VF			13
-#define I830_CTXREG_VF2			14
-#define I830_CTXREG_MCSB0		15
-#define I830_CTXREG_MCSB1		16
-#define I830_CTX_SETUP_SIZE		17
-
-/* 1.3: Stipple state
- */
-#define I830_STPREG_ST0 0
-#define I830_STPREG_ST1 1
-#define I830_STP_SETUP_SIZE 2
-
-/* Texture state (per tex unit)
- */
-
-#define I830_TEXREG_MI0	0	/* GFX_OP_MAP_INFO (6 dwords) */
-#define I830_TEXREG_MI1	1
-#define I830_TEXREG_MI2	2
-#define I830_TEXREG_MI3	3
-#define I830_TEXREG_MI4	4
-#define I830_TEXREG_MI5	5
-#define I830_TEXREG_MF	6	/* GFX_OP_MAP_FILTER */
-#define I830_TEXREG_MLC	7	/* GFX_OP_MAP_LOD_CTL */
-#define I830_TEXREG_MLL	8	/* GFX_OP_MAP_LOD_LIMITS */
-#define I830_TEXREG_MCS	9	/* GFX_OP_MAP_COORD_SETS */
-#define I830_TEX_SETUP_SIZE 10
-
-#define I830_TEXREG_TM0LI      0	/* load immediate 2 texture map n */
-#define I830_TEXREG_TM0S0      1
-#define I830_TEXREG_TM0S1      2
-#define I830_TEXREG_TM0S2      3
-#define I830_TEXREG_TM0S3      4
-#define I830_TEXREG_TM0S4      5
-#define I830_TEXREG_NOP0       6	/* noop */
-#define I830_TEXREG_NOP1       7	/* noop */
-#define I830_TEXREG_NOP2       8	/* noop */
-#define __I830_TEXREG_MCS      9	/* GFX_OP_MAP_COORD_SETS -- shared */
-#define __I830_TEX_SETUP_SIZE   10
-
-#define I830_FRONT   0x1
-#define I830_BACK    0x2
-#define I830_DEPTH   0x4
-
-#endif				/* _I830_DEFINES_ */
-
-typedef struct _drm_i830_init {
-	enum {
-		I830_INIT_DMA = 0x01,
-		I830_CLEANUP_DMA = 0x02
-	} func;
-	unsigned int mmio_offset;
-	unsigned int buffers_offset;
-	int sarea_priv_offset;
-	unsigned int ring_start;
-	unsigned int ring_end;
-	unsigned int ring_size;
-	unsigned int front_offset;
-	unsigned int back_offset;
-	unsigned int depth_offset;
-	unsigned int w;
-	unsigned int h;
-	unsigned int pitch;
-	unsigned int pitch_bits;
-	unsigned int back_pitch;
-	unsigned int depth_pitch;
-	unsigned int cpp;
-} drm_i830_init_t;
-
-/* Warning: If you change the SAREA structure you must change the Xserver
- * structure as well */
-
-typedef struct _drm_i830_tex_region {
-	unsigned char next, prev;	/* indices to form a circular LRU  */
-	unsigned char in_use;	/* owned by a client, or free? */
-	int age;		/* tracked by clients to update local LRU's */
-} drm_i830_tex_region_t;
-
-typedef struct _drm_i830_sarea {
-	unsigned int ContextState[I830_CTX_SETUP_SIZE];
-	unsigned int BufferState[I830_DEST_SETUP_SIZE];
-	unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE];
-	unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE];
-	unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT];
-	unsigned int Palette[2][256];
-	unsigned int dirty;
-
-	unsigned int nbox;
-	struct drm_clip_rect boxes[I830_NR_SAREA_CLIPRECTS];
-
-	/* Maintain an LRU of contiguous regions of texture space.  If
-	 * you think you own a region of texture memory, and it has an
-	 * age different to the one you set, then you are mistaken and
-	 * it has been stolen by another client.  If global texAge
-	 * hasn't changed, there is no need to walk the list.
-	 *
-	 * These regions can be used as a proxy for the fine-grained
-	 * texture information of other clients - by maintaining them
-	 * in the same lru which is used to age their own textures,
-	 * clients have an approximate lru for the whole of global
-	 * texture space, and can make informed decisions as to which
-	 * areas to kick out.  There is no need to choose whether to
-	 * kick out your own texture or someone else's - simply eject
-	 * them all in LRU order.
-	 */
-
-	drm_i830_tex_region_t texList[I830_NR_TEX_REGIONS + 1];
-	/* Last elt is sentinal */
-	int texAge;		/* last time texture was uploaded */
-	int last_enqueue;	/* last time a buffer was enqueued */
-	int last_dispatch;	/* age of the most recently dispatched buffer */
-	int last_quiescent;	/*  */
-	int ctxOwner;		/* last context to upload state */
-
-	int vertex_prim;
-
-	int pf_enabled;		/* is pageflipping allowed? */
-	int pf_active;
-	int pf_current_page;	/* which buffer is being displayed? */
-
-	int perf_boxes;		/* performance boxes to be displayed */
-
-	/* Here's the state for texunits 2,3:
-	 */
-	unsigned int TexState2[I830_TEX_SETUP_SIZE];
-	unsigned int TexBlendState2[I830_TEXBLEND_SIZE];
-	unsigned int TexBlendStateWordsUsed2;
-
-	unsigned int TexState3[I830_TEX_SETUP_SIZE];
-	unsigned int TexBlendState3[I830_TEXBLEND_SIZE];
-	unsigned int TexBlendStateWordsUsed3;
-
-	unsigned int StippleState[I830_STP_SETUP_SIZE];
-} drm_i830_sarea_t;
-
-/* Flags for perf_boxes
- */
-#define I830_BOX_RING_EMPTY    0x1	/* populated by kernel */
-#define I830_BOX_FLIP          0x2	/* populated by kernel */
-#define I830_BOX_WAIT          0x4	/* populated by kernel & client */
-#define I830_BOX_TEXTURE_LOAD  0x8	/* populated by kernel */
-#define I830_BOX_LOST_CONTEXT  0x10	/* populated by client */
-
-/* I830 specific ioctls
- * The device specific ioctl range is 0x40 to 0x79.
- */
-#define DRM_I830_INIT	0x00
-#define DRM_I830_VERTEX	0x01
-#define DRM_I830_CLEAR	0x02
-#define DRM_I830_FLUSH	0x03
-#define DRM_I830_GETAGE	0x04
-#define DRM_I830_GETBUF	0x05
-#define DRM_I830_SWAP	0x06
-#define DRM_I830_COPY	0x07
-#define DRM_I830_DOCOPY	0x08
-#define DRM_I830_FLIP	0x09
-#define DRM_I830_IRQ_EMIT	0x0a
-#define DRM_I830_IRQ_WAIT	0x0b
-#define DRM_I830_GETPARAM	0x0c
-#define DRM_I830_SETPARAM	0x0d
-
-#define DRM_IOCTL_I830_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I830_INIT, drm_i830_init_t)
-#define DRM_IOCTL_I830_VERTEX		DRM_IOW( DRM_COMMAND_BASE + DRM_I830_VERTEX, drm_i830_vertex_t)
-#define DRM_IOCTL_I830_CLEAR		DRM_IOW( DRM_COMMAND_BASE + DRM_I830_CLEAR, drm_i830_clear_t)
-#define DRM_IOCTL_I830_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I830_FLUSH)
-#define DRM_IOCTL_I830_GETAGE		DRM_IO ( DRM_COMMAND_BASE + DRM_I830_GETAGE)
-#define DRM_IOCTL_I830_GETBUF		DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_GETBUF, drm_i830_dma_t)
-#define DRM_IOCTL_I830_SWAP		DRM_IO ( DRM_COMMAND_BASE + DRM_I830_SWAP)
-#define DRM_IOCTL_I830_COPY		DRM_IOW( DRM_COMMAND_BASE + DRM_I830_COPY, drm_i830_copy_t)
-#define DRM_IOCTL_I830_DOCOPY		DRM_IO ( DRM_COMMAND_BASE + DRM_I830_DOCOPY)
-#define DRM_IOCTL_I830_FLIP		DRM_IO ( DRM_COMMAND_BASE + DRM_I830_FLIP)
-#define DRM_IOCTL_I830_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_IRQ_EMIT, drm_i830_irq_emit_t)
-#define DRM_IOCTL_I830_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I830_IRQ_WAIT, drm_i830_irq_wait_t)
-#define DRM_IOCTL_I830_GETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_GETPARAM, drm_i830_getparam_t)
-#define DRM_IOCTL_I830_SETPARAM         DRM_IOWR(DRM_COMMAND_BASE + DRM_I830_SETPARAM, drm_i830_setparam_t)
-
-typedef struct _drm_i830_clear {
-	int clear_color;
-	int clear_depth;
-	int flags;
-	unsigned int clear_colormask;
-	unsigned int clear_depthmask;
-} drm_i830_clear_t;
-
-/* These may be placeholders if we have more cliprects than
- * I830_NR_SAREA_CLIPRECTS.  In that case, the client sets discard to
- * false, indicating that the buffer will be dispatched again with a
- * new set of cliprects.
- */
-typedef struct _drm_i830_vertex {
-	int idx;		/* buffer index */
-	int used;		/* nr bytes in use */
-	int discard;		/* client is finished with the buffer? */
-} drm_i830_vertex_t;
-
-typedef struct _drm_i830_copy_t {
-	int idx;		/* buffer index */
-	int used;		/* nr bytes in use */
-	void __user *address;	/* Address to copy from */
-} drm_i830_copy_t;
-
-typedef struct drm_i830_dma {
-	void __user *virtual;
-	int request_idx;
-	int request_size;
-	int granted;
-} drm_i830_dma_t;
-
-/* 1.3: Userspace can request & wait on irq's:
- */
-typedef struct drm_i830_irq_emit {
-	int __user *irq_seq;
-} drm_i830_irq_emit_t;
-
-typedef struct drm_i830_irq_wait {
-	int irq_seq;
-} drm_i830_irq_wait_t;
-
-/* 1.3: New ioctl to query kernel params:
- */
-#define I830_PARAM_IRQ_ACTIVE            1
-
-typedef struct drm_i830_getparam {
-	int param;
-	int __user *value;
-} drm_i830_getparam_t;
-
-/* 1.3: New ioctl to set kernel params:
- */
-#define I830_SETPARAM_USE_MI_BATCHBUFFER_START            1
-
-typedef struct drm_i830_setparam {
-	int param;
-	int value;
-} drm_i830_setparam_t;
-
-#endif				/* _I830_DRM_H_ */
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 0039f1f..c4d6dbf 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -290,6 +290,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_RELAXED_FENCING	 12
 #define I915_PARAM_HAS_COHERENT_RINGS	 13
 #define I915_PARAM_HAS_EXEC_CONSTANTS	 14
+#define I915_PARAM_HAS_RELAXED_DELTA	 15
 
 typedef struct drm_i915_getparam {
 	int param;
diff --git a/include/drm/nouveau_drm.h b/include/drm/nouveau_drm.h
index e2cfe80..5edd3a7 100644
--- a/include/drm/nouveau_drm.h
+++ b/include/drm/nouveau_drm.h
@@ -94,6 +94,7 @@ struct drm_nouveau_setparam {
 #define NOUVEAU_GEM_DOMAIN_GART      (1 << 2)
 #define NOUVEAU_GEM_DOMAIN_MAPPABLE  (1 << 3)
 
+#define NOUVEAU_GEM_TILE_COMP        0x00030000 /* nv50-only */
 #define NOUVEAU_GEM_TILE_LAYOUT_MASK 0x0000ff00
 #define NOUVEAU_GEM_TILE_16BPP       0x00000001
 #define NOUVEAU_GEM_TILE_32BPP       0x00000002
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index e5c607a..3dec41c 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -908,6 +908,7 @@ struct drm_radeon_cs {
 #define RADEON_INFO_WANT_HYPERZ		0x07
 #define RADEON_INFO_WANT_CMASK		0x08 /* get access to CMASK on r300 */
 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ	0x09 /* clock crystal frequency */
+#define RADEON_INFO_NUM_BACKENDS	0x0a /* DB/backends for r600+ - need for OQ */
 
 struct drm_radeon_info {
 	uint32_t		request;
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h
index 1da8af6..efed082 100644
--- a/include/drm/ttm/ttm_bo_driver.h
+++ b/include/drm/ttm/ttm_bo_driver.h
@@ -50,13 +50,15 @@ struct ttm_backend_func {
 	 * @pages: Array of pointers to ttm pages.
 	 * @dummy_read_page: Page to be used instead of NULL pages in the
 	 * array @pages.
+	 * @dma_addrs: Array of DMA (bus) address of the ttm pages.
 	 *
 	 * Populate the backend with ttm pages. Depending on the backend,
 	 * it may or may not copy the @pages array.
 	 */
 	int (*populate) (struct ttm_backend *backend,
 			 unsigned long num_pages, struct page **pages,
-			 struct page *dummy_read_page);
+			 struct page *dummy_read_page,
+			 dma_addr_t *dma_addrs);
 	/**
 	 * struct ttm_backend_func member clear
 	 *
@@ -149,6 +151,7 @@ enum ttm_caching_state {
  * @swap_storage: Pointer to shmem struct file for swap storage.
  * @caching_state: The current caching state of the pages.
  * @state: The current binding state of the pages.
+ * @dma_address: The DMA (bus) addresses of the pages (if TTM_PAGE_FLAG_DMA32)
  *
  * This is a structure holding the pages, caching- and aperture binding
  * status for a buffer object that isn't backed by fixed (VRAM / AGP)
@@ -173,6 +176,7 @@ struct ttm_tt {
 		tt_unbound,
 		tt_unpopulated,
 	} state;
+	dma_addr_t *dma_address;
 };
 
 #define TTM_MEMTYPE_FLAG_FIXED         (1 << 0)	/* Fixed (on-card) PCI memory */
diff --git a/include/drm/ttm/ttm_page_alloc.h b/include/drm/ttm/ttm_page_alloc.h
index 1168214..8062890 100644
--- a/include/drm/ttm/ttm_page_alloc.h
+++ b/include/drm/ttm/ttm_page_alloc.h
@@ -36,11 +36,13 @@
  * @flags: ttm flags for page allocation.
  * @cstate: ttm caching state for the page.
  * @count: number of pages to allocate.
+ * @dma_address: The DMA (bus) address of pages (if TTM_PAGE_FLAG_DMA32 set).
  */
 int ttm_get_pages(struct list_head *pages,
 		  int flags,
 		  enum ttm_caching_state cstate,
-		  unsigned count);
+		  unsigned count,
+		  dma_addr_t *dma_address);
 /**
  * Put linked list of pages to pool.
  *
@@ -49,11 +51,13 @@ int ttm_get_pages(struct list_head *pages,
  * count.
  * @flags: ttm flags for page allocation.
  * @cstate: ttm caching state.
+ * @dma_address: The DMA (bus) address of pages (if TTM_PAGE_FLAG_DMA32 set).
  */
 void ttm_put_pages(struct list_head *pages,
 		   unsigned page_count,
 		   int flags,
-		   enum ttm_caching_state cstate);
+		   enum ttm_caching_state cstate,
+		   dma_addr_t *dma_address);
 /**
  * Initialize pool allocator.
  */
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 9e7f259..fcbbe71 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -43,12 +43,12 @@ struct amba_id {
 
 struct amba_driver {
 	struct device_driver	drv;
-	int			(*probe)(struct amba_device *, struct amba_id *);
+	int			(*probe)(struct amba_device *, const struct amba_id *);
 	int			(*remove)(struct amba_device *);
 	void			(*shutdown)(struct amba_device *);
 	int			(*suspend)(struct amba_device *, pm_message_t);
 	int			(*resume)(struct amba_device *);
-	struct amba_id		*id_table;
+	const struct amba_id	*id_table;
 };
 
 enum amba_vendor {
@@ -56,6 +56,10 @@ enum amba_vendor {
 	AMBA_VENDOR_ST = 0x80,
 };
 
+extern struct bus_type amba_bustype;
+
+#define to_amba_device(d)	container_of(d, struct amba_device, dev)
+
 #define amba_get_drvdata(d)	dev_get_drvdata(&d->dev)
 #define amba_set_drvdata(d,p)	dev_set_drvdata(&d->dev, p)
 
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index f4ee9ac..f602270 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -6,6 +6,9 @@
 
 #include <linux/mmc/host.h>
 
+/* Just some dummy forwarding */
+struct dma_chan;
+
 /**
  * struct mmci_platform_data - platform configuration for the MMCI
  * (also known as PL180) block.
@@ -27,6 +30,17 @@
  * @cd_invert: true if the gpio_cd pin value is active low
  * @capabilities: the capabilities of the block as implemented in
  * this platform, signify anything MMC_CAP_* from mmc/host.h
+ * @dma_filter: function used to select an apropriate RX and TX
+ * DMA channel to be used for DMA, if and only if you're deploying the
+ * generic DMA engine
+ * @dma_rx_param: parameter passed to the DMA allocation
+ * filter in order to select an apropriate RX channel. If
+ * there is a bidirectional RX+TX channel, then just specify
+ * this and leave dma_tx_param set to NULL
+ * @dma_tx_param: parameter passed to the DMA allocation
+ * filter in order to select an apropriate TX channel. If this
+ * is NULL the driver will attempt to use the RX channel as a
+ * bidirectional channel
  */
 struct mmci_platform_data {
 	unsigned int f_max;
@@ -38,6 +52,9 @@ struct mmci_platform_data {
 	int	gpio_cd;
 	bool	cd_invert;
 	unsigned long capabilities;
+	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+	void *dma_rx_param;
+	void *dma_tx_param;
 };
 
 #endif
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 0c4929f..32df2b6 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -89,6 +89,7 @@ enum {
 	ATA_ID_SPG		= 98,
 	ATA_ID_LBA_CAPACITY_2	= 100,
 	ATA_ID_SECTOR_SIZE	= 106,
+	ATA_ID_WWN		= 108,
 	ATA_ID_LOGICAL_SECTOR_SIZE	= 117,	/* and 118 */
 	ATA_ID_LAST_LUN		= 126,
 	ATA_ID_DLF		= 128,
@@ -103,6 +104,7 @@ enum {
 	ATA_ID_SERNO_LEN	= 20,
 	ATA_ID_FW_REV_LEN	= 8,
 	ATA_ID_PROD_LEN		= 40,
+	ATA_ID_WWN_LEN		= 8,
 
 	ATA_PCI_CTL_OFS		= 2,
 
@@ -598,42 +600,42 @@ static inline bool ata_id_has_dipm(const u16 *id)
 }
 
 
-static inline int ata_id_has_fua(const u16 *id)
+static inline bool ata_id_has_fua(const u16 *id)
 {
 	if ((id[ATA_ID_CFSSE] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_CFSSE] & (1 << 6);
 }
 
-static inline int ata_id_has_flush(const u16 *id)
+static inline bool ata_id_has_flush(const u16 *id)
 {
 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_COMMAND_SET_2] & (1 << 12);
 }
 
-static inline int ata_id_flush_enabled(const u16 *id)
+static inline bool ata_id_flush_enabled(const u16 *id)
 {
 	if (ata_id_has_flush(id) == 0)
-		return 0;
+		return false;
 	if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_CFS_ENABLE_2] & (1 << 12);
 }
 
-static inline int ata_id_has_flush_ext(const u16 *id)
+static inline bool ata_id_has_flush_ext(const u16 *id)
 {
 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_COMMAND_SET_2] & (1 << 13);
 }
 
-static inline int ata_id_flush_ext_enabled(const u16 *id)
+static inline bool ata_id_flush_ext_enabled(const u16 *id)
 {
 	if (ata_id_has_flush_ext(id) == 0)
-		return 0;
+		return false;
 	if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	/*
 	 * some Maxtor disks have bit 13 defined incorrectly
 	 * so check bit 10 too
@@ -686,64 +688,64 @@ static inline u16 ata_id_logical_sector_offset(const u16 *id,
 	return 0;
 }
 
-static inline int ata_id_has_lba48(const u16 *id)
+static inline bool ata_id_has_lba48(const u16 *id)
 {
 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	if (!ata_id_u64(id, ATA_ID_LBA_CAPACITY_2))
-		return 0;
+		return false;
 	return id[ATA_ID_COMMAND_SET_2] & (1 << 10);
 }
 
-static inline int ata_id_lba48_enabled(const u16 *id)
+static inline bool ata_id_lba48_enabled(const u16 *id)
 {
 	if (ata_id_has_lba48(id) == 0)
-		return 0;
+		return false;
 	if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_CFS_ENABLE_2] & (1 << 10);
 }
 
-static inline int ata_id_hpa_enabled(const u16 *id)
+static inline bool ata_id_hpa_enabled(const u16 *id)
 {
 	/* Yes children, word 83 valid bits cover word 82 data */
 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	/* And 87 covers 85-87 */
 	if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	/* Check command sets enabled as well as supported */
 	if ((id[ATA_ID_CFS_ENABLE_1] & (1 << 10)) == 0)
-		return 0;
+		return false;
 	return id[ATA_ID_COMMAND_SET_1] & (1 << 10);
 }
 
-static inline int ata_id_has_wcache(const u16 *id)
+static inline bool ata_id_has_wcache(const u16 *id)
 {
 	/* Yes children, word 83 valid bits cover word 82 data */
 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_COMMAND_SET_1] & (1 << 5);
 }
 
-static inline int ata_id_has_pm(const u16 *id)
+static inline bool ata_id_has_pm(const u16 *id)
 {
 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_COMMAND_SET_1] & (1 << 3);
 }
 
-static inline int ata_id_rahead_enabled(const u16 *id)
+static inline bool ata_id_rahead_enabled(const u16 *id)
 {
 	if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_CFS_ENABLE_1] & (1 << 6);
 }
 
-static inline int ata_id_wcache_enabled(const u16 *id)
+static inline bool ata_id_wcache_enabled(const u16 *id)
 {
 	if ((id[ATA_ID_CSF_DEFAULT] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[ATA_ID_CFS_ENABLE_1] & (1 << 5);
 }
 
@@ -773,7 +775,7 @@ static inline unsigned int ata_id_major_version(const u16 *id)
 	return mver;
 }
 
-static inline int ata_id_is_sata(const u16 *id)
+static inline bool ata_id_is_sata(const u16 *id)
 {
 	/*
 	 * See if word 93 is 0 AND drive is at least ATA-5 compatible
@@ -782,37 +784,40 @@ static inline int ata_id_is_sata(const u16 *id)
 	 * 0x0000 and 0xffff along with the earlier ATA revisions...
 	 */
 	if (id[ATA_ID_HW_CONFIG] == 0 && (short)id[ATA_ID_MAJOR_VER] >= 0x0020)
-		return 1;
-	return 0;
+		return true;
+	return false;
 }
 
-static inline int ata_id_has_tpm(const u16 *id)
+static inline bool ata_id_has_tpm(const u16 *id)
 {
 	/* The TPM bits are only valid on ATA8 */
 	if (ata_id_major_version(id) < 8)
-		return 0;
+		return false;
 	if ((id[48] & 0xC000) != 0x4000)
-		return 0;
+		return false;
 	return id[48] & (1 << 0);
 }
 
-static inline int ata_id_has_dword_io(const u16 *id)
+static inline bool ata_id_has_dword_io(const u16 *id)
 {
 	/* ATA 8 reuses this flag for "trusted" computing */
 	if (ata_id_major_version(id) > 7)
-		return 0;
-	if (id[ATA_ID_DWORD_IO] & (1 << 0))
-		return 1;
-	return 0;
+		return false;
+	return id[ATA_ID_DWORD_IO] & (1 << 0);
 }
 
-static inline int ata_id_has_unload(const u16 *id)
+static inline bool ata_id_has_unload(const u16 *id)
 {
 	if (ata_id_major_version(id) >= 7 &&
 	    (id[ATA_ID_CFSSE] & 0xC000) == 0x4000 &&
 	    id[ATA_ID_CFSSE] & (1 << 13))
-		return 1;
-	return 0;
+		return true;
+	return false;
+}
+
+static inline bool ata_id_has_wwn(const u16 *id)
+{
+	return (id[ATA_ID_CSF_DEFAULT] & 0xC100) == 0x4100;
 }
 
 static inline int ata_id_form_factor(const u16 *id)
@@ -843,25 +848,25 @@ static inline int ata_id_rotation_rate(const u16 *id)
 	return val;
 }
 
-static inline int ata_id_has_trim(const u16 *id)
+static inline bool ata_id_has_trim(const u16 *id)
 {
 	if (ata_id_major_version(id) >= 7 &&
 	    (id[ATA_ID_DATA_SET_MGMT] & 1))
-		return 1;
-	return 0;
+		return true;
+	return false;
 }
 
-static inline int ata_id_has_zero_after_trim(const u16 *id)
+static inline bool ata_id_has_zero_after_trim(const u16 *id)
 {
 	/* DSM supported, deterministic read, and read zero after trim set */
 	if (ata_id_has_trim(id) &&
 	    (id[ATA_ID_ADDITIONAL_SUPP] & 0x4020) == 0x4020)
-		return 1;
+		return true;
 
-	return 0;
+	return false;
 }
 
-static inline int ata_id_current_chs_valid(const u16 *id)
+static inline bool ata_id_current_chs_valid(const u16 *id)
 {
 	/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
 	   has not been issued to the device then the values of
@@ -873,11 +878,11 @@ static inline int ata_id_current_chs_valid(const u16 *id)
 		id[ATA_ID_CUR_SECTORS];    /* sectors in current translation */
 }
 
-static inline int ata_id_is_cfa(const u16 *id)
+static inline bool ata_id_is_cfa(const u16 *id)
 {
 	if ((id[ATA_ID_CONFIG] == 0x848A) ||	/* Traditional CF */
 	    (id[ATA_ID_CONFIG] == 0x844A))	/* Delkin Devices CF */
-		return 1;
+		return true;
 	/*
 	 * CF specs don't require specific value in the word 0 anymore and yet
 	 * they forbid to report the ATA version in the word 80 and require the
@@ -886,44 +891,40 @@ static inline int ata_id_is_cfa(const u16 *id)
 	 * and while those that don't indicate CFA feature support need some
 	 * sort of quirk list, it seems impractical for the ones that do...
 	 */
-	if ((id[ATA_ID_COMMAND_SET_2] & 0xC004) == 0x4004)
-		return 1;
-	return 0;
+	return (id[ATA_ID_COMMAND_SET_2] & 0xC004) == 0x4004;
 }
 
-static inline int ata_id_is_ssd(const u16 *id)
+static inline bool ata_id_is_ssd(const u16 *id)
 {
 	return id[ATA_ID_ROT_SPEED] == 0x01;
 }
 
-static inline int ata_id_pio_need_iordy(const u16 *id, const u8 pio)
+static inline bool ata_id_pio_need_iordy(const u16 *id, const u8 pio)
 {
 	/* CF spec. r4.1 Table 22 says no IORDY on PIO5 and PIO6. */
 	if (pio > 4 && ata_id_is_cfa(id))
-		return 0;
+		return false;
 	/* For PIO3 and higher it is mandatory. */
 	if (pio > 2)
-		return 1;
+		return true;
 	/* Turn it on when possible. */
-	if (ata_id_has_iordy(id))
-		return 1;
-	return 0;
+	return ata_id_has_iordy(id);
 }
 
-static inline int ata_drive_40wire(const u16 *dev_id)
+static inline bool ata_drive_40wire(const u16 *dev_id)
 {
 	if (ata_id_is_sata(dev_id))
-		return 0;	/* SATA */
+		return false;	/* SATA */
 	if ((dev_id[ATA_ID_HW_CONFIG] & 0xE000) == 0x6000)
-		return 0;	/* 80 wire */
-	return 1;
+		return false;	/* 80 wire */
+	return true;
 }
 
-static inline int ata_drive_40wire_relaxed(const u16 *dev_id)
+static inline bool ata_drive_40wire_relaxed(const u16 *dev_id)
 {
 	if ((dev_id[ATA_ID_HW_CONFIG] & 0x2000) == 0x2000)
-		return 0;	/* 80 wire */
-	return 1;
+		return false;	/* 80 wire */
+	return true;
 }
 
 static inline int atapi_cdb_len(const u16 *dev_id)
@@ -936,12 +937,12 @@ static inline int atapi_cdb_len(const u16 *dev_id)
 	}
 }
 
-static inline int atapi_command_packet_set(const u16 *dev_id)
+static inline bool atapi_command_packet_set(const u16 *dev_id)
 {
 	return (dev_id[ATA_ID_CONFIG] >> 8) & 0x1f;
 }
 
-static inline int atapi_id_dmadir(const u16 *dev_id)
+static inline bool atapi_id_dmadir(const u16 *dev_id)
 {
 	return ata_id_major_version(dev_id) >= 7 && (dev_id[62] & 0x8000);
 }
@@ -954,13 +955,13 @@ static inline int atapi_id_dmadir(const u16 *dev_id)
  *
  * It is called only once for each device.
  */
-static inline int ata_id_is_lba_capacity_ok(u16 *id)
+static inline bool ata_id_is_lba_capacity_ok(u16 *id)
 {
 	unsigned long lba_sects, chs_sects, head, tail;
 
 	/* No non-LBA info .. so valid! */
 	if (id[ATA_ID_CYLS] == 0)
-		return 1;
+		return true;
 
 	lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
 
@@ -975,13 +976,13 @@ static inline int ata_id_is_lba_capacity_ok(u16 *id)
 	    id[ATA_ID_SECTORS] == 63 &&
 	    (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
 	    (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS]))
-		return 1;
+		return true;
 
 	chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS];
 
 	/* perform a rough sanity check on lba_sects: within 10% is OK */
 	if (lba_sects - chs_sects < chs_sects/10)
-		return 1;
+		return true;
 
 	/* some drives have the word order reversed */
 	head = (lba_sects >> 16) & 0xffff;
@@ -990,10 +991,10 @@ static inline int ata_id_is_lba_capacity_ok(u16 *id)
 
 	if (lba_sects - chs_sects < chs_sects/10) {
 		*(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects);
-		return 1;	/* LBA capacity is (now) good */
+		return true;	/* LBA capacity is (now) good */
 	}
 
-	return 0;	/* LBA capacity value may be bad */
+	return false;	/* LBA capacity value may be bad */
 }
 
 static inline void ata_id_to_hd_driveid(u16 *id)
@@ -1051,19 +1052,19 @@ static inline int is_multi_taskfile(struct ata_taskfile *tf)
 	       (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
 }
 
-static inline int ata_ok(u8 status)
+static inline bool ata_ok(u8 status)
 {
 	return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
 			== ATA_DRDY);
 }
 
-static inline int lba_28_ok(u64 block, u32 n_block)
+static inline bool lba_28_ok(u64 block, u32 n_block)
 {
 	/* check the ending block number: must be LESS THAN 0x0fffffff */
 	return ((block + n_block) < ((1 << 28) - 1)) && (n_block <= 256);
 }
 
-static inline int lba_48_ok(u64 block, u32 n_block)
+static inline bool lba_48_ok(u64 block, u32 n_block)
 {
 	/* check the ending block number */
 	return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536);
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 359df04..9d339eb 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -103,6 +103,8 @@
 #define AUDIT_BPRM_FCAPS	1321	/* Information about fcaps increasing perms */
 #define AUDIT_CAPSET		1322	/* Record showing argument to sys_capset */
 #define AUDIT_MMAP		1323	/* Record showing descriptor and flags in mmap */
+#define AUDIT_NETFILTER_PKT	1324	/* Packets traversing netfilter chains */
+#define AUDIT_NETFILTER_CFG	1325	/* Netfilter chain modifications */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 4a3d52e..5ffc6dd 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -32,6 +32,13 @@ enum backlight_update_reason {
 	BACKLIGHT_UPDATE_SYSFS,
 };
 
+enum backlight_type {
+	BACKLIGHT_RAW = 1,
+	BACKLIGHT_PLATFORM,
+	BACKLIGHT_FIRMWARE,
+	BACKLIGHT_TYPE_MAX,
+};
+
 struct backlight_device;
 struct fb_info;
 
@@ -62,6 +69,8 @@ struct backlight_properties {
 	/* FB Blanking active? (values as for power) */
 	/* Due to be removed, please use (state & BL_CORE_FBBLANK) */
 	int fb_blank;
+	/* Backlight type */
+	enum backlight_type type;
 	/* Flags used to signal drivers of state changes */
 	/* Upper 4 bits are reserved for driver internal use */
 	unsigned int state;
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
index 09dcc0c..b8e995f 100644
--- a/include/linux/ceph/ceph_fs.h
+++ b/include/linux/ceph/ceph_fs.h
@@ -136,9 +136,18 @@ struct ceph_dir_layout {
 
 
 /* osd */
-#define CEPH_MSG_OSD_MAP          41
-#define CEPH_MSG_OSD_OP           42
-#define CEPH_MSG_OSD_OPREPLY      43
+#define CEPH_MSG_OSD_MAP                41
+#define CEPH_MSG_OSD_OP                 42
+#define CEPH_MSG_OSD_OPREPLY            43
+#define CEPH_MSG_WATCH_NOTIFY           44
+
+
+/* watch-notify operations */
+enum {
+  WATCH_NOTIFY				= 1, /* notifying watcher */
+  WATCH_NOTIFY_COMPLETE			= 2, /* notifier notified when done */
+};
+
 
 /* pool operations */
 enum {
@@ -213,8 +222,10 @@ struct ceph_client_mount {
 	struct ceph_mon_request_header monhdr;
 } __attribute__ ((packed));
 
+#define CEPH_SUBSCRIBE_ONETIME    1  /* i want only 1 update after have */
+
 struct ceph_mon_subscribe_item {
-	__le64 have_version;	__le64 have;
+	__le64 have_version;    __le64 have;
 	__u8 onetime;
 } __attribute__ ((packed));
 
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 72c72bf..0d2e0ff 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -71,7 +71,6 @@ struct ceph_options {
 #define CEPH_OSD_TIMEOUT_DEFAULT    60  /* seconds */
 #define CEPH_OSD_KEEPALIVE_DEFAULT  5
 #define CEPH_OSD_IDLE_TTL_DEFAULT    60
-#define CEPH_MOUNT_RSIZE_DEFAULT    (512*1024) /* readahead */
 
 #define CEPH_MSG_MAX_FRONT_LEN	(16*1024*1024)
 #define CEPH_MSG_MAX_DATA_LEN	(16*1024*1024)
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index a1af296..f88eacb 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -32,6 +32,7 @@ struct ceph_osd {
 	struct rb_node o_node;
 	struct ceph_connection o_con;
 	struct list_head o_requests;
+	struct list_head o_linger_requests;
 	struct list_head o_osd_lru;
 	struct ceph_authorizer *o_authorizer;
 	void *o_authorizer_buf, *o_authorizer_reply_buf;
@@ -47,6 +48,8 @@ struct ceph_osd_request {
 	struct rb_node  r_node;
 	struct list_head r_req_lru_item;
 	struct list_head r_osd_item;
+	struct list_head r_linger_item;
+	struct list_head r_linger_osd;
 	struct ceph_osd *r_osd;
 	struct ceph_pg   r_pgid;
 	int              r_pg_osds[CEPH_PG_MAX_SIZE];
@@ -59,6 +62,7 @@ struct ceph_osd_request {
 	int               r_flags;     /* any additional flags for the osd */
 	u32               r_sent;      /* >0 if r_request is sending/sent */
 	int               r_got_reply;
+	int		  r_linger;
 
 	struct ceph_osd_client *r_osdc;
 	struct kref       r_kref;
@@ -74,7 +78,6 @@ struct ceph_osd_request {
 	char              r_oid[40];          /* object name */
 	int               r_oid_len;
 	unsigned long     r_stamp;            /* send OR check time */
-	bool              r_resend;           /* msg send failed, needs retry */
 
 	struct ceph_file_layout r_file_layout;
 	struct ceph_snap_context *r_snapc;    /* snap context for writes */
@@ -90,6 +93,26 @@ struct ceph_osd_request {
 	struct ceph_pagelist *r_trail;	      /* trailing part of the data */
 };
 
+struct ceph_osd_event {
+	u64 cookie;
+	int one_shot;
+	struct ceph_osd_client *osdc;
+	void (*cb)(u64, u64, u8, void *);
+	void *data;
+	struct rb_node node;
+	struct list_head osd_node;
+	struct kref kref;
+	struct completion completion;
+};
+
+struct ceph_osd_event_work {
+	struct work_struct work;
+	struct ceph_osd_event *event;
+        u64 ver;
+        u64 notify_id;
+        u8 opcode;
+};
+
 struct ceph_osd_client {
 	struct ceph_client     *client;
 
@@ -104,7 +127,10 @@ struct ceph_osd_client {
 	u64                    timeout_tid;   /* tid of timeout triggering rq */
 	u64                    last_tid;      /* tid of last request */
 	struct rb_root         requests;      /* pending requests */
-	struct list_head       req_lru;	      /* pending requests lru */
+	struct list_head       req_lru;	      /* in-flight lru */
+	struct list_head       req_unsent;    /* unsent/need-resend queue */
+	struct list_head       req_notarget;  /* map to no osd */
+	struct list_head       req_linger;    /* lingering requests */
 	int                    num_requests;
 	struct delayed_work    timeout_work;
 	struct delayed_work    osds_timeout_work;
@@ -116,6 +142,12 @@ struct ceph_osd_client {
 
 	struct ceph_msgpool	msgpool_op;
 	struct ceph_msgpool	msgpool_op_reply;
+
+	spinlock_t		event_lock;
+	struct rb_root		event_tree;
+	u64			event_count;
+
+	struct workqueue_struct	*notify_wq;
 };
 
 struct ceph_osd_req_op {
@@ -150,6 +182,13 @@ struct ceph_osd_req_op {
 	        struct {
 		        u64 snapid;
 	        } snap;
+		struct {
+			u64 cookie;
+			u64 ver;
+			__u8 flag;
+			u32 prot_ver;
+			u32 timeout;
+		} watch;
 	};
 	u32 payload_len;
 };
@@ -198,6 +237,11 @@ extern struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *,
 				      bool use_mempool, int num_reply,
 				      int page_align);
 
+extern void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc,
+					 struct ceph_osd_request *req);
+extern void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc,
+						struct ceph_osd_request *req);
+
 static inline void ceph_osdc_get_request(struct ceph_osd_request *req)
 {
 	kref_get(&req->r_kref);
@@ -233,5 +277,14 @@ extern int ceph_osdc_writepages(struct ceph_osd_client *osdc,
 				struct page **pages, int nr_pages,
 				int flags, int do_sync, bool nofail);
 
+/* watch/notify events */
+extern int ceph_osdc_create_event(struct ceph_osd_client *osdc,
+				  void (*event_cb)(u64, u64, u8, void *),
+				  int one_shot, void *data,
+				  struct ceph_osd_event **pevent);
+extern void ceph_osdc_cancel_event(struct ceph_osd_event *event);
+extern int ceph_osdc_wait_event(struct ceph_osd_event *event,
+				unsigned long timeout);
+extern void ceph_osdc_put_event(struct ceph_osd_event *event);
 #endif
 
diff --git a/include/linux/ceph/rados.h b/include/linux/ceph/rados.h
index 6d5247f..0a99099 100644
--- a/include/linux/ceph/rados.h
+++ b/include/linux/ceph/rados.h
@@ -12,9 +12,9 @@
  * osdmap encoding versions
  */
 #define CEPH_OSDMAP_INC_VERSION     5
-#define CEPH_OSDMAP_INC_VERSION_EXT 5
+#define CEPH_OSDMAP_INC_VERSION_EXT 6
 #define CEPH_OSDMAP_VERSION         5
-#define CEPH_OSDMAP_VERSION_EXT     5
+#define CEPH_OSDMAP_VERSION_EXT     6
 
 /*
  * fs id
@@ -181,9 +181,17 @@ enum {
 	/* read */
 	CEPH_OSD_OP_READ      = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 1,
 	CEPH_OSD_OP_STAT      = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 2,
+	CEPH_OSD_OP_MAPEXT    = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 3,
 
 	/* fancy read */
-	CEPH_OSD_OP_MASKTRUNC = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 4,
+	CEPH_OSD_OP_MASKTRUNC   = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 4,
+	CEPH_OSD_OP_SPARSE_READ = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 5,
+
+	CEPH_OSD_OP_NOTIFY    = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 6,
+	CEPH_OSD_OP_NOTIFY_ACK = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 7,
+
+	/* versioning */
+	CEPH_OSD_OP_ASSERT_VER = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 8,
 
 	/* write */
 	CEPH_OSD_OP_WRITE     = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_DATA | 1,
@@ -205,6 +213,8 @@ enum {
 	CEPH_OSD_OP_CREATE  = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_DATA | 13,
 	CEPH_OSD_OP_ROLLBACK= CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_DATA | 14,
 
+	CEPH_OSD_OP_WATCH   = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_DATA | 15,
+
 	/** attrs **/
 	/* read */
 	CEPH_OSD_OP_GETXATTR  = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_ATTR | 1,
@@ -218,11 +228,14 @@ enum {
 	CEPH_OSD_OP_RMXATTR   = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_ATTR | 4,
 
 	/** subop **/
-	CEPH_OSD_OP_PULL           = CEPH_OSD_OP_MODE_SUB | 1,
-	CEPH_OSD_OP_PUSH           = CEPH_OSD_OP_MODE_SUB | 2,
-	CEPH_OSD_OP_BALANCEREADS   = CEPH_OSD_OP_MODE_SUB | 3,
-	CEPH_OSD_OP_UNBALANCEREADS = CEPH_OSD_OP_MODE_SUB | 4,
-	CEPH_OSD_OP_SCRUB          = CEPH_OSD_OP_MODE_SUB | 5,
+	CEPH_OSD_OP_PULL            = CEPH_OSD_OP_MODE_SUB | 1,
+	CEPH_OSD_OP_PUSH            = CEPH_OSD_OP_MODE_SUB | 2,
+	CEPH_OSD_OP_BALANCEREADS    = CEPH_OSD_OP_MODE_SUB | 3,
+	CEPH_OSD_OP_UNBALANCEREADS  = CEPH_OSD_OP_MODE_SUB | 4,
+	CEPH_OSD_OP_SCRUB           = CEPH_OSD_OP_MODE_SUB | 5,
+	CEPH_OSD_OP_SCRUB_RESERVE   = CEPH_OSD_OP_MODE_SUB | 6,
+	CEPH_OSD_OP_SCRUB_UNRESERVE = CEPH_OSD_OP_MODE_SUB | 7,
+	CEPH_OSD_OP_SCRUB_STOP      = CEPH_OSD_OP_MODE_SUB | 8,
 
 	/** lock **/
 	CEPH_OSD_OP_WRLOCK    = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_LOCK | 1,
@@ -328,6 +341,8 @@ enum {
 	CEPH_OSD_CMPXATTR_MODE_U64    = 2
 };
 
+#define RADOS_NOTIFY_VER	1
+
 /*
  * an individual object operation.  each may be accompanied by some data
  * payload
@@ -359,7 +374,12 @@ struct ceph_osd_op {
 	        struct {
 		        __le64 snapid;
 	        } __attribute__ ((packed)) snap;
-	};
+		struct {
+			__le64 cookie;
+			__le64 ver;
+			__u8 flag;	/* 0 = unwatch, 1 = watch */
+		} __attribute__ ((packed)) watch;
+};
 	__le32 payload_len;
 } __attribute__ ((packed));
 
@@ -402,4 +422,5 @@ struct ceph_osd_reply_head {
 } __attribute__ ((packed));
 
 
+
 #endif
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index ce104e3..e654fa2 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -474,7 +474,8 @@ struct cgroup_subsys {
 			struct cgroup *old_cgrp, struct task_struct *tsk,
 			bool threadgroup);
 	void (*fork)(struct cgroup_subsys *ss, struct task_struct *task);
-	void (*exit)(struct cgroup_subsys *ss, struct task_struct *task);
+	void (*exit)(struct cgroup_subsys *ss, struct cgroup *cgrp,
+			struct cgroup *old_cgrp, struct task_struct *task);
 	int (*populate)(struct cgroup_subsys *ss,
 			struct cgroup *cgrp);
 	void (*post_clone)(struct cgroup_subsys *ss, struct cgroup *cgrp);
@@ -626,6 +627,7 @@ bool css_is_ancestor(struct cgroup_subsys_state *cg,
 /* Get id and depth of css */
 unsigned short css_id(struct cgroup_subsys_state *css);
 unsigned short css_depth(struct cgroup_subsys_state *css);
+struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id);
 
 #else /* !CONFIG_CGROUPS */
 
diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h
index ccefff0..cdbfcb8 100644
--- a/include/linux/cgroup_subsys.h
+++ b/include/linux/cgroup_subsys.h
@@ -65,4 +65,8 @@ SUBSYS(net_cls)
 SUBSYS(blkio)
 #endif
 
+#ifdef CONFIG_CGROUP_PERF
+SUBSYS(perf)
+#endif
+
 /* */
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index dfa2ed4..cc9f7a4 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -11,9 +11,6 @@
 /* The full zone was compacted */
 #define COMPACT_COMPLETE	3
 
-#define COMPACT_MODE_DIRECT_RECLAIM	0
-#define COMPACT_MODE_KSWAPD		1
-
 #ifdef CONFIG_COMPACTION
 extern int sysctl_compact_memory;
 extern int sysctl_compaction_handler(struct ctl_table *table, int write,
@@ -28,8 +25,7 @@ extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
 			bool sync);
 extern unsigned long compaction_suitable(struct zone *zone, int order);
 extern unsigned long compact_zone_order(struct zone *zone, int order,
-					gfp_t gfp_mask, bool sync,
-					int compact_mode);
+					gfp_t gfp_mask, bool sync);
 
 /* Do not skip compaction more than 64 times */
 #define COMPACT_MAX_DEFER_SHIFT 6
@@ -74,8 +70,7 @@ static inline unsigned long compaction_suitable(struct zone *zone, int order)
 }
 
 static inline unsigned long compact_zone_order(struct zone *zone, int order,
-					       gfp_t gfp_mask, bool sync,
-					       int compact_mode)
+					       gfp_t gfp_mask, bool sync)
 {
 	return COMPACT_CONTINUE;
 }
diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h
index 16508bc..cb4c1eb 100644
--- a/include/linux/compiler-gcc.h
+++ b/include/linux/compiler-gcc.h
@@ -92,3 +92,11 @@
 #if !defined(__noclone)
 #define __noclone	/* not needed */
 #endif
+
+/*
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
+ */
+#define uninitialized_var(x) x = x
+
+#define __always_inline		inline __attribute__((always_inline))
diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
index b721129..37d4124 100644
--- a/include/linux/compiler-gcc3.h
+++ b/include/linux/compiler-gcc3.h
@@ -21,11 +21,3 @@
 #   error "GCOV profiling support for gcc versions below 3.4 not included"
 # endif /* __GNUC_MINOR__ */
 #endif /* CONFIG_GCOV_KERNEL */
-
-/*
- * A trick to suppress uninitialized variable warning without generating any
- * code
- */
-#define uninitialized_var(x) x = x
-
-#define __always_inline		inline __attribute__((always_inline))
diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
index fcfa5b9..64b7c00 100644
--- a/include/linux/compiler-gcc4.h
+++ b/include/linux/compiler-gcc4.h
@@ -12,13 +12,6 @@
 #define __used			__attribute__((__used__))
 #define __must_check 		__attribute__((warn_unused_result))
 #define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
-#define __always_inline		inline __attribute__((always_inline))
-
-/*
- * A trick to suppress uninitialized variable warning without generating any
- * code
- */
-#define uninitialized_var(x) x = x
 
 #if __GNUC_MINOR__ >= 3
 /* Mark functions as cold. gcc will assume any path leading to a call
@@ -53,7 +46,6 @@
 #define __noclone	__attribute__((__noclone__))
 
 #endif
-
 #endif
 
 #if __GNUC_MINOR__ > 0
diff --git a/include/linux/connector.h b/include/linux/connector.h
index 7e8ca75..bcafc94 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -42,8 +42,9 @@
 #define CN_VAL_DM_USERSPACE_LOG		0x1
 #define CN_IDX_DRBD			0x8
 #define CN_VAL_DRBD			0x1
+#define CN_KVP_IDX			0x9	/* HyperV KVP */
 
-#define CN_NETLINK_USERS		8
+#define CN_NETLINK_USERS		9
 
 /*
  * Maximum connector's message size.
@@ -128,14 +129,17 @@ struct cn_dev {
 	struct cn_queue_dev *cbdev;
 };
 
-int cn_add_callback(struct cb_id *, char *, void (*callback) (struct cn_msg *, struct netlink_skb_parms *));
+int cn_add_callback(struct cb_id *id, const char *name,
+		    void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
 void cn_del_callback(struct cb_id *);
 int cn_netlink_send(struct cn_msg *, u32, gfp_t);
 
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
+int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
+			  struct cb_id *id,
+			  void (*callback)(struct cn_msg *, struct netlink_skb_parms *));
 void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id);
 
-struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *);
+struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *);
 void cn_queue_free_dev(struct cn_queue_dev *dev);
 
 int cn_cb_equal(struct cb_id *, struct cb_id *);
diff --git a/include/linux/cpu_rmap.h b/include/linux/cpu_rmap.h
new file mode 100644
index 0000000..473771a
--- /dev/null
+++ b/include/linux/cpu_rmap.h
@@ -0,0 +1,73 @@
+/*
+ * cpu_rmap.c: CPU affinity reverse-map support
+ * Copyright 2011 Solarflare Communications 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, incorporated herein by reference.
+ */
+
+#include <linux/cpumask.h>
+#include <linux/gfp.h>
+#include <linux/slab.h>
+
+/**
+ * struct cpu_rmap - CPU affinity reverse-map
+ * @size: Number of objects to be reverse-mapped
+ * @used: Number of objects added
+ * @obj: Pointer to array of object pointers
+ * @near: For each CPU, the index and distance to the nearest object,
+ *      based on affinity masks
+ */
+struct cpu_rmap {
+	u16		size, used;
+	void		**obj;
+	struct {
+		u16	index;
+		u16	dist;
+	}		near[0];
+};
+#define CPU_RMAP_DIST_INF 0xffff
+
+extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags);
+
+/**
+ * free_cpu_rmap - free CPU affinity reverse-map
+ * @rmap: Reverse-map allocated with alloc_cpu_rmap(), or %NULL
+ */
+static inline void free_cpu_rmap(struct cpu_rmap *rmap)
+{
+	kfree(rmap);
+}
+
+extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj);
+extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index,
+			   const struct cpumask *affinity);
+
+static inline u16 cpu_rmap_lookup_index(struct cpu_rmap *rmap, unsigned int cpu)
+{
+	return rmap->near[cpu].index;
+}
+
+static inline void *cpu_rmap_lookup_obj(struct cpu_rmap *rmap, unsigned int cpu)
+{
+	return rmap->obj[rmap->near[cpu].index];
+}
+
+#ifdef CONFIG_GENERIC_HARDIRQS
+
+/**
+ * alloc_irq_cpu_rmap - allocate CPU affinity reverse-map for IRQs
+ * @size: Number of objects to be mapped
+ *
+ * Must be called in process context.
+ */
+static inline struct cpu_rmap *alloc_irq_cpu_rmap(unsigned int size)
+{
+	return alloc_cpu_rmap(size, GFP_KERNEL);
+}
+extern void free_irq_cpu_rmap(struct cpu_rmap *rmap);
+
+extern int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq);
+
+#endif
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index c3e9de8..9343dd3 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -230,7 +230,7 @@ struct cpufreq_driver {
 	int	(*bios_limit)	(int cpu, unsigned int *limit);
 
 	int	(*exit)		(struct cpufreq_policy *policy);
-	int	(*suspend)	(struct cpufreq_policy *policy, pm_message_t pmsg);
+	int	(*suspend)	(struct cpufreq_policy *policy);
 	int	(*resume)	(struct cpufreq_policy *policy);
 	struct freq_attr	**attr;
 };
@@ -281,19 +281,10 @@ __ATTR(_name, 0444, show_##_name, NULL)
 static struct freq_attr _name =			\
 __ATTR(_name, _perm, show_##_name, NULL)
 
-#define cpufreq_freq_attr_ro_old(_name)		\
-static struct freq_attr _name##_old =		\
-__ATTR(_name, 0444, show_##_name##_old, NULL)
-
 #define cpufreq_freq_attr_rw(_name)		\
 static struct freq_attr _name =			\
 __ATTR(_name, 0644, show_##_name, store_##_name)
 
-#define cpufreq_freq_attr_rw_old(_name)		\
-static struct freq_attr _name##_old =		\
-__ATTR(_name, 0644, show_##_name##_old, store_##_name##_old)
-
-
 struct global_attr {
 	struct attribute attr;
 	ssize_t (*show)(struct kobject *kobj,
diff --git a/include/linux/crc32.h b/include/linux/crc32.h
index e20dd1f..391a259 100644
--- a/include/linux/crc32.h
+++ b/include/linux/crc32.h
@@ -11,7 +11,7 @@
 extern u32  crc32_le(u32 crc, unsigned char const *p, size_t len);
 extern u32  crc32_be(u32 crc, unsigned char const *p, size_t len);
 
-#define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)data, length)
+#define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)(data), length)
 
 /*
  * Helpers for hash table generation of ethernet nics:
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index f958c19..f2afed4 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -168,7 +168,7 @@ struct dentry_operations {
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)(struct dentry *, char *, int);
 	struct vfsmount *(*d_automount)(struct path *);
-	int (*d_manage)(struct dentry *, bool, bool);
+	int (*d_manage)(struct dentry *, bool);
 } ____cacheline_aligned;
 
 /*
@@ -416,7 +416,6 @@ static inline bool d_mountpoint(struct dentry *dentry)
 	return dentry->d_flags & DCACHE_MOUNTED;
 }
 
-extern struct vfsmount *lookup_mnt(struct path *);
 extern struct dentry *lookup_create(struct nameidata *nd, int is_dir);
 
 extern int sysctl_vfs_cache_pressure;
diff --git a/include/linux/dcbnl.h b/include/linux/dcbnl.h
index 66900e3..c522800 100644
--- a/include/linux/dcbnl.h
+++ b/include/linux/dcbnl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Intel Corporation.
+ * Copyright (c) 2008-2011, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -25,9 +25,14 @@
 /* IEEE 802.1Qaz std supported values */
 #define IEEE_8021QAZ_MAX_TCS	8
 
+#define IEEE_8021QAZ_TSA_STRICT		0
+#define IEEE_8021QAZ_TSA_CB_SHAPER	1
+#define IEEE_8021QAZ_TSA_ETS		2
+#define IEEE_8021QAZ_TSA_VENDOR		255
+
 /* This structure contains the IEEE 802.1Qaz ETS managed object
  *
- * @willing: willing bit in ETS configuratin TLV
+ * @willing: willing bit in ETS configuration TLV
  * @ets_cap: indicates supported capacity of ets feature
  * @cbs: credit based shaper ets algorithm supported
  * @tc_tx_bw: tc tx bandwidth indexed by traffic class
@@ -82,6 +87,50 @@ struct ieee_pfc {
 	__u64	indications[IEEE_8021QAZ_MAX_TCS];
 };
 
+/* CEE DCBX std supported values */
+#define CEE_DCBX_MAX_PGS	8
+#define CEE_DCBX_MAX_PRIO	8
+
+/**
+ * struct cee_pg - CEE Priority-Group managed object
+ *
+ * @willing: willing bit in the PG tlv
+ * @error: error bit in the PG tlv
+ * @pg_en: enable bit of the PG feature
+ * @tcs_supported: number of traffic classes supported
+ * @pg_bw: bandwidth percentage for each priority group
+ * @prio_pg: priority to PG mapping indexed by priority
+ */
+struct cee_pg {
+	__u8    willing;
+	__u8    error;
+	__u8    pg_en;
+	__u8    tcs_supported;
+	__u8    pg_bw[CEE_DCBX_MAX_PGS];
+	__u8    prio_pg[CEE_DCBX_MAX_PGS];
+};
+
+/**
+ * struct cee_pfc - CEE PFC managed object
+ *
+ * @willing: willing bit in the PFC tlv
+ * @error: error bit in the PFC tlv
+ * @pfc_en: bitmap indicating pfc enabled traffic classes
+ * @tcs_supported: number of traffic classes supported
+ */
+struct cee_pfc {
+	__u8    willing;
+	__u8    error;
+	__u8    pfc_en;
+	__u8    tcs_supported;
+};
+
+/* IEEE 802.1Qaz std supported values */
+#define IEEE_8021QAZ_APP_SEL_ETHERTYPE	1
+#define IEEE_8021QAZ_APP_SEL_STREAM	2
+#define IEEE_8021QAZ_APP_SEL_DGRAM	3
+#define IEEE_8021QAZ_APP_SEL_ANY	4
+
 /* This structure contains the IEEE 802.1Qaz APP managed object. This
  * object is also used for the CEE std as well. There is no difference
  * between the objects.
@@ -105,6 +154,20 @@ struct dcb_app {
 	__u16	protocol;
 };
 
+/**
+ * struct dcb_peer_app_info - APP feature information sent by the peer
+ *
+ * @willing: willing bit in the peer APP tlv
+ * @error: error bit in the peer APP tlv
+ *
+ * In addition to this information the full peer APP tlv also contains
+ * a table of 'app_count' APP objects defined above.
+ */
+struct dcb_peer_app_info {
+	__u8	willing;
+	__u8	error;
+};
+
 struct dcbmsg {
 	__u8               dcb_family;
 	__u8               cmd;
@@ -139,6 +202,7 @@ struct dcbmsg {
  * @DCB_CMD_SDCBX: set DCBX engine configuration
  * @DCB_CMD_GFEATCFG: get DCBX features flags
  * @DCB_CMD_SFEATCFG: set DCBX features negotiation flags
+ * @DCB_CMD_CEE_GET: get CEE aggregated configuration
  */
 enum dcbnl_commands {
 	DCB_CMD_UNDEFINED,
@@ -181,6 +245,8 @@ enum dcbnl_commands {
 	DCB_CMD_GFEATCFG,
 	DCB_CMD_SFEATCFG,
 
+	DCB_CMD_CEE_GET,
+
 	__DCB_CMD_ENUM_MAX,
 	DCB_CMD_MAX = __DCB_CMD_ENUM_MAX - 1,
 };
@@ -203,6 +269,7 @@ enum dcbnl_commands {
  * @DCB_ATTR_IEEE: IEEE 802.1Qaz supported attributes (NLA_NESTED)
  * @DCB_ATTR_DCBX: DCBX engine configuration in the device (NLA_U8)
  * @DCB_ATTR_FEATCFG: DCBX features flags (NLA_NESTED)
+ * @DCB_ATTR_CEE: CEE std supported attributes (NLA_NESTED)
  */
 enum dcbnl_attrs {
 	DCB_ATTR_UNDEFINED,
@@ -226,15 +293,32 @@ enum dcbnl_attrs {
 	DCB_ATTR_DCBX,
 	DCB_ATTR_FEATCFG,
 
+	/* CEE nested attributes */
+	DCB_ATTR_CEE,
+
 	__DCB_ATTR_ENUM_MAX,
 	DCB_ATTR_MAX = __DCB_ATTR_ENUM_MAX - 1,
 };
 
+/**
+ * enum ieee_attrs - IEEE 802.1Qaz get/set attributes
+ *
+ * @DCB_ATTR_IEEE_UNSPEC: unspecified
+ * @DCB_ATTR_IEEE_ETS: negotiated ETS configuration
+ * @DCB_ATTR_IEEE_PFC: negotiated PFC configuration
+ * @DCB_ATTR_IEEE_APP_TABLE: negotiated APP configuration
+ * @DCB_ATTR_IEEE_PEER_ETS: peer ETS configuration - get only
+ * @DCB_ATTR_IEEE_PEER_PFC: peer PFC configuration - get only
+ * @DCB_ATTR_IEEE_PEER_APP: peer APP tlv - get only
+ */
 enum ieee_attrs {
 	DCB_ATTR_IEEE_UNSPEC,
 	DCB_ATTR_IEEE_ETS,
 	DCB_ATTR_IEEE_PFC,
 	DCB_ATTR_IEEE_APP_TABLE,
+	DCB_ATTR_IEEE_PEER_ETS,
+	DCB_ATTR_IEEE_PEER_PFC,
+	DCB_ATTR_IEEE_PEER_APP,
 	__DCB_ATTR_IEEE_MAX
 };
 #define DCB_ATTR_IEEE_MAX (__DCB_ATTR_IEEE_MAX - 1)
@@ -247,6 +331,31 @@ enum ieee_attrs_app {
 #define DCB_ATTR_IEEE_APP_MAX (__DCB_ATTR_IEEE_APP_MAX - 1)
 
 /**
+ * enum cee_attrs - CEE DCBX get attributes
+ *
+ * @DCB_ATTR_CEE_UNSPEC: unspecified
+ * @DCB_ATTR_CEE_PEER_PG: peer PG configuration - get only
+ * @DCB_ATTR_CEE_PEER_PFC: peer PFC configuration - get only
+ * @DCB_ATTR_CEE_PEER_APP: peer APP tlv - get only
+ */
+enum cee_attrs {
+	DCB_ATTR_CEE_UNSPEC,
+	DCB_ATTR_CEE_PEER_PG,
+	DCB_ATTR_CEE_PEER_PFC,
+	DCB_ATTR_CEE_PEER_APP_TABLE,
+	__DCB_ATTR_CEE_MAX
+};
+#define DCB_ATTR_CEE_MAX (__DCB_ATTR_CEE_MAX - 1)
+
+enum peer_app_attr {
+	DCB_ATTR_CEE_PEER_APP_UNSPEC,
+	DCB_ATTR_CEE_PEER_APP_INFO,
+	DCB_ATTR_CEE_PEER_APP,
+	__DCB_ATTR_CEE_PEER_APP_MAX
+};
+#define DCB_ATTR_CEE_PEER_APP_MAX (__DCB_ATTR_CEE_PEER_APP_MAX - 1)
+
+/**
  * enum dcbnl_pfc_attrs - DCB Priority Flow Control user priority nested attrs
  *
  * @DCB_PFC_UP_ATTR_UNDEFINED: unspecified attribute to catch errors
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 010e2d8..d638e85 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -279,8 +279,6 @@ enum dccp_state {
 	DCCP_MAX_STATES
 };
 
-#define DCCP_STATE_MASK 0x1f
-
 enum {
 	DCCPF_OPEN	      = TCPF_ESTABLISHED,
 	DCCPF_REQUESTING      = TCPF_SYN_SENT,
diff --git a/include/linux/debugobjects.h b/include/linux/debugobjects.h
index 597692f..65970b8 100644
--- a/include/linux/debugobjects.h
+++ b/include/linux/debugobjects.h
@@ -34,7 +34,10 @@ struct debug_obj {
 
 /**
  * struct debug_obj_descr - object type specific debug description structure
+ *
  * @name:		name of the object typee
+ * @debug_hint:		function returning address, which have associated
+ *			kernel symbol, to allow identify the object
  * @fixup_init:		fixup function, which is called when the init check
  *			fails
  * @fixup_activate:	fixup function, which is called when the activate check
@@ -46,7 +49,7 @@ struct debug_obj {
  */
 struct debug_obj_descr {
 	const char		*name;
-
+	void *(*debug_hint)	(void *addr);
 	int (*fixup_init)	(void *addr, enum debug_obj_state state);
 	int (*fixup_activate)	(void *addr, enum debug_obj_state state);
 	int (*fixup_destroy)	(void *addr, enum debug_obj_state state);
diff --git a/include/linux/device.h b/include/linux/device.h
index 1bf5cf0..144ec13 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -128,9 +128,7 @@ struct device_driver {
 
 	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */
 
-#if defined(CONFIG_OF)
 	const struct of_device_id	*of_match_table;
-#endif
 
 	int (*probe) (struct device *dev);
 	int (*remove) (struct device *dev);
@@ -422,6 +420,7 @@ struct device {
 	void		*platform_data;	/* Platform specific data, device
 					   core doesn't touch it */
 	struct dev_pm_info	power;
+	struct dev_power_domain	*pwr_domain;
 
 #ifdef CONFIG_NUMA
 	int		numa_node;	/* NUMA node this device is close to */
@@ -441,9 +440,9 @@ struct device {
 					     override */
 	/* arch specific additions */
 	struct dev_archdata	archdata;
-#ifdef CONFIG_OF
-	struct device_node	*of_node;
-#endif
+
+	struct device_node	*of_node; /* associated device tree node */
+	const struct of_device_id *of_match; /* matching of_device_id from driver */
 
 	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
 
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 90e087f..f156cca 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -23,6 +23,53 @@ enum dmi_device_type {
 	DMI_DEV_TYPE_DEV_ONBOARD = -3,
 };
 
+enum dmi_entry_type {
+	DMI_ENTRY_BIOS = 0,
+	DMI_ENTRY_SYSTEM,
+	DMI_ENTRY_BASEBOARD,
+	DMI_ENTRY_CHASSIS,
+	DMI_ENTRY_PROCESSOR,
+	DMI_ENTRY_MEM_CONTROLLER,
+	DMI_ENTRY_MEM_MODULE,
+	DMI_ENTRY_CACHE,
+	DMI_ENTRY_PORT_CONNECTOR,
+	DMI_ENTRY_SYSTEM_SLOT,
+	DMI_ENTRY_ONBOARD_DEVICE,
+	DMI_ENTRY_OEMSTRINGS,
+	DMI_ENTRY_SYSCONF,
+	DMI_ENTRY_BIOS_LANG,
+	DMI_ENTRY_GROUP_ASSOC,
+	DMI_ENTRY_SYSTEM_EVENT_LOG,
+	DMI_ENTRY_PHYS_MEM_ARRAY,
+	DMI_ENTRY_MEM_DEVICE,
+	DMI_ENTRY_32_MEM_ERROR,
+	DMI_ENTRY_MEM_ARRAY_MAPPED_ADDR,
+	DMI_ENTRY_MEM_DEV_MAPPED_ADDR,
+	DMI_ENTRY_BUILTIN_POINTING_DEV,
+	DMI_ENTRY_PORTABLE_BATTERY,
+	DMI_ENTRY_SYSTEM_RESET,
+	DMI_ENTRY_HW_SECURITY,
+	DMI_ENTRY_SYSTEM_POWER_CONTROLS,
+	DMI_ENTRY_VOLTAGE_PROBE,
+	DMI_ENTRY_COOLING_DEV,
+	DMI_ENTRY_TEMP_PROBE,
+	DMI_ENTRY_ELECTRICAL_CURRENT_PROBE,
+	DMI_ENTRY_OOB_REMOTE_ACCESS,
+	DMI_ENTRY_BIS_ENTRY,
+	DMI_ENTRY_SYSTEM_BOOT,
+	DMI_ENTRY_MGMT_DEV,
+	DMI_ENTRY_MGMT_DEV_COMPONENT,
+	DMI_ENTRY_MGMT_DEV_THRES,
+	DMI_ENTRY_MEM_CHANNEL,
+	DMI_ENTRY_IPMI_DEV,
+	DMI_ENTRY_SYS_POWER_SUPPLY,
+	DMI_ENTRY_ADDITIONAL,
+	DMI_ENTRY_ONBOARD_DEV_EXT,
+	DMI_ENTRY_MGMT_CONTROLLER_HOST,
+	DMI_ENTRY_INACTIVE = 126,
+	DMI_ENTRY_END_OF_TABLE = 127,
+};
+
 struct dmi_header {
 	u8 type;
 	u8 length;
diff --git a/include/linux/dw_dmac.h b/include/linux/dw_dmac.h
index c8aad71..6998d93 100644
--- a/include/linux/dw_dmac.h
+++ b/include/linux/dw_dmac.h
@@ -16,9 +16,18 @@
 /**
  * struct dw_dma_platform_data - Controller configuration parameters
  * @nr_channels: Number of channels supported by hardware (max 8)
+ * @is_private: The device channels should be marked as private and not for
+ *	by the general purpose DMA channel allocator.
  */
 struct dw_dma_platform_data {
 	unsigned int	nr_channels;
+	bool		is_private;
+#define CHAN_ALLOCATION_ASCENDING	0	/* zero to seven */
+#define CHAN_ALLOCATION_DESCENDING	1	/* seven to zero */
+	unsigned char	chan_allocation_order;
+#define CHAN_PRIORITY_ASCENDING		0	/* chan0 highest */
+#define CHAN_PRIORITY_DESCENDING	1	/* chan7 highest */
+	unsigned char	chan_priority;
 };
 
 /**
@@ -33,6 +42,30 @@ enum dw_dma_slave_width {
 	DW_DMA_SLAVE_WIDTH_32BIT,
 };
 
+/* bursts size */
+enum dw_dma_msize {
+	DW_DMA_MSIZE_1,
+	DW_DMA_MSIZE_4,
+	DW_DMA_MSIZE_8,
+	DW_DMA_MSIZE_16,
+	DW_DMA_MSIZE_32,
+	DW_DMA_MSIZE_64,
+	DW_DMA_MSIZE_128,
+	DW_DMA_MSIZE_256,
+};
+
+/* flow controller */
+enum dw_dma_fc {
+	DW_DMA_FC_D_M2M,
+	DW_DMA_FC_D_M2P,
+	DW_DMA_FC_D_P2M,
+	DW_DMA_FC_D_P2P,
+	DW_DMA_FC_P_P2M,
+	DW_DMA_FC_SP_P2P,
+	DW_DMA_FC_P_M2P,
+	DW_DMA_FC_DP_P2P,
+};
+
 /**
  * struct dw_dma_slave - Controller-specific information about a slave
  *
@@ -44,6 +77,11 @@ enum dw_dma_slave_width {
  * @reg_width: peripheral register width
  * @cfg_hi: Platform-specific initializer for the CFG_HI register
  * @cfg_lo: Platform-specific initializer for the CFG_LO register
+ * @src_master: src master for transfers on allocated channel.
+ * @dst_master: dest master for transfers on allocated channel.
+ * @src_msize: src burst size.
+ * @dst_msize: dest burst size.
+ * @fc: flow controller for DMA transfer
  */
 struct dw_dma_slave {
 	struct device		*dma_dev;
@@ -52,6 +90,11 @@ struct dw_dma_slave {
 	enum dw_dma_slave_width	reg_width;
 	u32			cfg_hi;
 	u32			cfg_lo;
+	u8			src_master;
+	u8			dst_master;
+	u8			src_msize;
+	u8			dst_msize;
+	u8			fc;
 };
 
 /* Platform-configurable bits in CFG_HI */
@@ -62,7 +105,6 @@ struct dw_dma_slave {
 #define DWC_CFGH_DST_PER(x)	((x) << 11)
 
 /* Platform-configurable bits in CFG_LO */
-#define DWC_CFGL_PRIO(x)	((x) << 5)	/* priority */
 #define DWC_CFGL_LOCK_CH_XFER	(0 << 12)	/* scope of LOCK_CH */
 #define DWC_CFGL_LOCK_CH_BLOCK	(1 << 12)
 #define DWC_CFGL_LOCK_CH_XACT	(2 << 12)
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 1c70028..0c9653f 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -31,6 +31,10 @@ struct _ddebug {
 	 * writes commands to <debugfs>/dynamic_debug/control
 	 */
 #define _DPRINTK_FLAGS_PRINT   (1<<0)  /* printk() a message using the format */
+#define _DPRINTK_FLAGS_INCL_MODNAME	(1<<1)
+#define _DPRINTK_FLAGS_INCL_FUNCNAME	(1<<2)
+#define _DPRINTK_FLAGS_INCL_LINENO	(1<<3)
+#define _DPRINTK_FLAGS_INCL_TID		(1<<4)
 #define _DPRINTK_FLAGS_DEFAULT 0
 	unsigned int flags:8;
 	char enabled;
@@ -42,6 +46,8 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
 extern int ddebug_remove_module(const char *mod_name);
+extern int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
+	__attribute__ ((format (printf, 2, 3)));
 
 #define dynamic_pr_debug(fmt, ...) do {					\
 	static struct _ddebug descriptor				\
@@ -50,7 +56,7 @@ extern int ddebug_remove_module(const char *mod_name);
 	{ KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__,		\
 		_DPRINTK_FLAGS_DEFAULT };				\
 	if (unlikely(descriptor.enabled))				\
-		printk(KERN_DEBUG pr_fmt(fmt),	##__VA_ARGS__);		\
+		__dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \
 	} while (0)
 
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index fb737bc..33fa120 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -397,4 +397,41 @@ static inline void memrange_efi_to_native(u64 *addr, u64 *npages)
 	*addr &= PAGE_MASK;
 }
 
+#if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
+/*
+ * EFI Variable support.
+ *
+ * Different firmware drivers can expose their EFI-like variables using
+ * the following.
+ */
+
+struct efivar_operations {
+	efi_get_variable_t *get_variable;
+	efi_get_next_variable_t *get_next_variable;
+	efi_set_variable_t *set_variable;
+};
+
+struct efivars {
+	/*
+	 * ->lock protects two things:
+	 * 1) ->list - adds, removals, reads, writes
+	 * 2) ops.[gs]et_variable() calls.
+	 * It must not be held when creating sysfs entries or calling kmalloc.
+	 * ops.get_next_variable() is only called from register_efivars(),
+	 * which is protected by the BKL, so that path is safe.
+	 */
+	spinlock_t lock;
+	struct list_head list;
+	struct kset *kset;
+	struct bin_attribute *new_var, *del_var;
+	const struct efivar_operations *ops;
+};
+
+int register_efivars(struct efivars *efivars,
+		     const struct efivar_operations *ops,
+		     struct kobject *parent_kobj);
+void unregister_efivars(struct efivars *efivars);
+
+#endif /* CONFIG_EFI_VARS */
+
 #endif /* _LINUX_EFI_H */
diff --git a/include/linux/err.h b/include/linux/err.h
index 448afc1..f2edce2 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -52,6 +52,14 @@ static inline void * __must_check ERR_CAST(const void *ptr)
 	return (void *) ptr;
 }
 
+static inline int __must_check PTR_RET(const void *ptr)
+{
+	if (IS_ERR(ptr))
+		return PTR_ERR(ptr);
+	else
+		return 0;
+}
+
 #endif
 
 #endif /* _LINUX_ERR_H */
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 1908929..b297f28 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -13,6 +13,9 @@
 #ifndef _LINUX_ETHTOOL_H
 #define _LINUX_ETHTOOL_H
 
+#ifdef __KERNEL__
+#include <linux/compat.h>
+#endif
 #include <linux/types.h>
 #include <linux/if_ether.h>
 
@@ -251,6 +254,7 @@ enum ethtool_stringset {
 	ETH_SS_STATS,
 	ETH_SS_PRIV_FLAGS,
 	ETH_SS_NTUPLE_FILTERS,
+	ETH_SS_FEATURES,
 };
 
 /* for passing string sets for data tagging */
@@ -449,6 +453,37 @@ struct ethtool_rxnfc {
 	__u32				rule_locs[0];
 };
 
+#ifdef __KERNEL__
+#ifdef CONFIG_COMPAT
+
+struct compat_ethtool_rx_flow_spec {
+	u32		flow_type;
+	union {
+		struct ethtool_tcpip4_spec		tcp_ip4_spec;
+		struct ethtool_tcpip4_spec		udp_ip4_spec;
+		struct ethtool_tcpip4_spec		sctp_ip4_spec;
+		struct ethtool_ah_espip4_spec		ah_ip4_spec;
+		struct ethtool_ah_espip4_spec		esp_ip4_spec;
+		struct ethtool_usrip4_spec		usr_ip4_spec;
+		struct ethhdr				ether_spec;
+		u8					hdata[72];
+	} h_u, m_u;
+	compat_u64	ring_cookie;
+	u32		location;
+};
+
+struct compat_ethtool_rxnfc {
+	u32				cmd;
+	u32				flow_type;
+	compat_u64			data;
+	struct compat_ethtool_rx_flow_spec fs;
+	u32				rule_cnt;
+	u32				rule_locs[0];
+};
+
+#endif /* CONFIG_COMPAT */
+#endif /* __KERNEL__ */
+
 /**
  * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
  * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
@@ -523,6 +558,92 @@ struct ethtool_flash {
 	char	data[ETHTOOL_FLASH_MAX_FILENAME];
 };
 
+/* for returning and changing feature sets */
+
+/**
+ * struct ethtool_get_features_block - block with state of 32 features
+ * @available: mask of changeable features
+ * @requested: mask of features requested to be enabled if possible
+ * @active: mask of currently enabled features
+ * @never_changed: mask of features not changeable for any device
+ */
+struct ethtool_get_features_block {
+	__u32	available;
+	__u32	requested;
+	__u32	active;
+	__u32	never_changed;
+};
+
+/**
+ * struct ethtool_gfeatures - command to get state of device's features
+ * @cmd: command number = %ETHTOOL_GFEATURES
+ * @size: in: number of elements in the features[] array;
+ *       out: number of elements in features[] needed to hold all features
+ * @features: state of features
+ */
+struct ethtool_gfeatures {
+	__u32	cmd;
+	__u32	size;
+	struct ethtool_get_features_block features[0];
+};
+
+/**
+ * struct ethtool_set_features_block - block with request for 32 features
+ * @valid: mask of features to be changed
+ * @requested: values of features to be changed
+ */
+struct ethtool_set_features_block {
+	__u32	valid;
+	__u32	requested;
+};
+
+/**
+ * struct ethtool_sfeatures - command to request change in device's features
+ * @cmd: command number = %ETHTOOL_SFEATURES
+ * @size: array size of the features[] array
+ * @features: feature change masks
+ */
+struct ethtool_sfeatures {
+	__u32	cmd;
+	__u32	size;
+	struct ethtool_set_features_block features[0];
+};
+
+/*
+ * %ETHTOOL_SFEATURES changes features present in features[].valid to the
+ * values of corresponding bits in features[].requested. Bits in .requested
+ * not set in .valid or not changeable are ignored.
+ *
+ * Returns %EINVAL when .valid contains undefined or never-changable bits
+ * or size is not equal to required number of features words (32-bit blocks).
+ * Returns >= 0 if request was completed; bits set in the value mean:
+ *   %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not
+ *	changeable (not present in %ETHTOOL_GFEATURES' features[].available)
+ *	those bits were ignored.
+ *   %ETHTOOL_F_WISH - some or all changes requested were recorded but the
+ *      resulting state of bits masked by .valid is not equal to .requested.
+ *      Probably there are other device-specific constraints on some features
+ *      in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
+ *      here as though ignored bits were cleared.
+ *   %ETHTOOL_F_COMPAT - some or all changes requested were made by calling
+ *      compatibility functions. Requested offload state cannot be properly
+ *      managed by kernel.
+ *
+ * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
+ * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
+ * for ETH_SS_FEATURES string set. First entry in the table corresponds to least
+ * significant bit in features[0] fields. Empty strings mark undefined features.
+ */
+enum ethtool_sfeatures_retval_bits {
+	ETHTOOL_F_UNSUPPORTED__BIT,
+	ETHTOOL_F_WISH__BIT,
+	ETHTOOL_F_COMPAT__BIT,
+};
+
+#define ETHTOOL_F_UNSUPPORTED   (1 << ETHTOOL_F_UNSUPPORTED__BIT)
+#define ETHTOOL_F_WISH          (1 << ETHTOOL_F_WISH__BIT)
+#define ETHTOOL_F_COMPAT        (1 << ETHTOOL_F_COMPAT__BIT)
+
 #ifdef __KERNEL__
 
 #include <linux/rculist.h>
@@ -543,7 +664,6 @@ struct net_device;
 
 /* Some generic methods drivers may use in their ethtool_ops */
 u32 ethtool_op_get_link(struct net_device *dev);
-u32 ethtool_op_get_rx_csum(struct net_device *dev);
 u32 ethtool_op_get_tx_csum(struct net_device *dev);
 int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
 int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
@@ -744,6 +864,9 @@ struct ethtool_ops {
 #define ETHTOOL_GRXFHINDIR	0x00000038 /* Get RX flow hash indir'n table */
 #define ETHTOOL_SRXFHINDIR	0x00000039 /* Set RX flow hash indir'n table */
 
+#define ETHTOOL_GFEATURES	0x0000003a /* Get device offload settings */
+#define ETHTOOL_SFEATURES	0x0000003b /* Change device offload settings */
+
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
 #define SPARC_ETH_SSET		ETHTOOL_SSET
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index 2802898..33a42f2 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -8,6 +8,9 @@ struct inode;
 struct super_block;
 struct vfsmount;
 
+/* limit the handle size to NFSv4 handle size now */
+#define MAX_HANDLE_SZ 128
+
 /*
  * The fileid_type identifies how the file within the filesystem is encoded.
  * In theory this is freely set and parsed by the filesystem, but we try to
@@ -121,8 +124,10 @@ struct fid {
  *    set, the encode_fh() should store sufficient information so that a good
  *    attempt can be made to find not only the file but also it's place in the
  *    filesystem.   This typically means storing a reference to de->d_parent in
- *    the filehandle fragment.  encode_fh() should return the number of bytes
- *    stored or a negative error code such as %-ENOSPC
+ *    the filehandle fragment.  encode_fh() should return the fileid_type on
+ *    success and on error returns 255 (if the space needed to encode fh is
+ *    greater than @max_len*4 bytes). On error @max_len contains the minimum
+ *    size(in 4 byte unit) needed to encode the file handle.
  *
  * fh_to_dentry:
  *    @fh_to_dentry is given a &struct super_block (@sb) and a file handle
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 65990ef..6043c64 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -884,7 +884,8 @@ extern int ext3fs_dirhash(const char *name, int len, struct
 			  dx_hash_info *hinfo);
 
 /* ialloc.c */
-extern struct inode * ext3_new_inode (handle_t *, struct inode *, int);
+extern struct inode * ext3_new_inode (handle_t *, struct inode *,
+				      const struct qstr *, int);
 extern void ext3_free_inode (handle_t *, struct inode *);
 extern struct inode * ext3_orphan_get (struct super_block *, unsigned long);
 extern unsigned long ext3_count_free_inodes (struct super_block *);
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 68ba85a..b2a3639 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -152,6 +152,8 @@
 #define FB_ACCEL_PROSAVAGE_DDR  0x8d	/* S3 ProSavage DDR             */
 #define FB_ACCEL_PROSAVAGE_DDRK 0x8e	/* S3 ProSavage DDR-K           */
 
+#define FB_ACCEL_PUV3_UNIGFX	0xa0	/* PKUnity-v3 Unigfx		*/
+
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
 	unsigned long smem_start;	/* Start of frame buffer mem */
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index a562fa5..f550f89 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -46,6 +46,7 @@
                                            unlinking file.  */
 #define AT_SYMLINK_FOLLOW	0x400   /* Follow symbolic links.  */
 #define AT_NO_AUTOMOUNT		0x800	/* Suppress terminal automount traversal */
+#define AT_EMPTY_PATH		0x1000	/* Allow empty relative pathname */
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/file.h b/include/linux/file.h
index e85baeb..21a7995 100644
--- a/include/linux/file.h
+++ b/include/linux/file.h
@@ -29,6 +29,8 @@ static inline void fput_light(struct file *file, int fput_needed)
 
 extern struct file *fget(unsigned int fd);
 extern struct file *fget_light(unsigned int fd, int *fput_needed);
+extern struct file *fget_raw(unsigned int fd);
+extern struct file *fget_raw_light(unsigned int fd, int *fput_needed);
 extern void set_close_on_exec(unsigned int fd, int flag);
 extern void put_filp(struct file *);
 extern int alloc_fd(unsigned start, unsigned flags);
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index 9a3f5f9..c64f368 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -42,6 +42,10 @@
 #define CSR_BROADCAST_CHANNEL		0x234
 #define CSR_CONFIG_ROM			0x400
 #define CSR_CONFIG_ROM_END		0x800
+#define CSR_OMPR			0x900
+#define CSR_OPCR(i)			(0x904 + (i) * 4)
+#define CSR_IMPR			0x980
+#define CSR_IPCR(i)			(0x984 + (i) * 4)
 #define CSR_FCP_COMMAND			0xB00
 #define CSR_FCP_RESPONSE		0xD00
 #define CSR_FCP_END			0xF00
@@ -89,7 +93,7 @@ struct fw_card {
 	int current_tlabel;
 	u64 tlabel_mask;
 	struct list_head transaction_list;
-	unsigned long reset_jiffies;
+	u64 reset_jiffies;
 
 	u32 split_timeout_hi;
 	u32 split_timeout_lo;
@@ -441,5 +445,8 @@ int fw_iso_context_start(struct fw_iso_context *ctx,
 			 int cycle, int sync, int tags);
 int fw_iso_context_stop(struct fw_iso_context *ctx);
 void fw_iso_context_destroy(struct fw_iso_context *ctx);
+void fw_iso_resource_manage(struct fw_card *card, int generation,
+			    u64 channels_mask, int *channel, int *bandwidth,
+			    bool allocate, __be32 buffer[2]);
 
 #endif /* _LINUX_FIREWIRE_H */
diff --git a/include/linux/firmware.h b/include/linux/firmware.h
index 53d1e6c..21b3e75 100644
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -39,7 +39,7 @@ struct builtin_fw {
 int request_firmware(const struct firmware **fw, const char *name,
 		     struct device *device);
 int request_firmware_nowait(
-	struct module *module, int uevent,
+	struct module *module, bool uevent,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context));
 
@@ -52,7 +52,7 @@ static inline int request_firmware(const struct firmware **fw,
 	return -EINVAL;
 }
 static inline int request_firmware_nowait(
-	struct module *module, int uevent,
+	struct module *module, bool uevent,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e38b50a..12529e9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -102,6 +102,9 @@ struct inodes_stat_t {
 /* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
 #define FMODE_UNSIGNED_OFFSET	((__force fmode_t)0x2000)
 
+/* File is opened with O_PATH; almost nothing can be done with it */
+#define FMODE_PATH		((__force fmode_t)0x4000)
+
 /* File was opened by fanotify and shouldn't generate fanotify events */
 #define FMODE_NONOTIFY		((__force fmode_t)0x1000000)
 
@@ -659,9 +662,9 @@ struct address_space {
 
 struct block_device {
 	dev_t			bd_dev;  /* not a kdev_t - it's a search key */
+	int			bd_openers;
 	struct inode *		bd_inode;	/* will die */
 	struct super_block *	bd_super;
-	int			bd_openers;
 	struct mutex		bd_mutex;	/* open/close mutex */
 	struct list_head	bd_inodes;
 	void *			bd_claiming;
@@ -798,8 +801,7 @@ struct inode {
 #endif
 
 #ifdef CONFIG_IMA
-	/* protected by i_lock */
-	unsigned int		i_readcount; /* struct files open RO */
+	atomic_t		i_readcount; /* struct files open RO */
 #endif
 	atomic_t		i_writecount;
 #ifdef CONFIG_SECURITY
@@ -978,6 +980,13 @@ struct file {
 #endif
 };
 
+struct file_handle {
+	__u32 handle_bytes;
+	int handle_type;
+	/* file identifier */
+	unsigned char f_handle[0];
+};
+
 #define get_file(x)	atomic_long_inc(&(x)->f_count)
 #define fput_atomic(x)	atomic_long_add_unless(&(x)->f_count, -1, 1)
 #define file_count(x)	atomic_long_read(&(x)->f_count)
@@ -1401,6 +1410,7 @@ struct super_block {
 	wait_queue_head_t	s_wait_unfrozen;
 
 	char s_id[32];				/* Informational name */
+	u8 s_uuid[16];				/* UUID */
 
 	void 			*s_fs_info;	/* Filesystem private info */
 	fmode_t			s_mode;
@@ -1621,6 +1631,8 @@ struct super_operations {
 	void (*umount_begin) (struct super_block *);
 
 	int (*show_options)(struct seq_file *, struct vfsmount *);
+	int (*show_devname)(struct seq_file *, struct vfsmount *);
+	int (*show_path)(struct seq_file *, struct vfsmount *);
 	int (*show_stats)(struct seq_file *, struct vfsmount *);
 #ifdef CONFIG_QUOTA
 	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
@@ -1784,8 +1796,6 @@ int sync_inode_metadata(struct inode *inode, int wait);
 struct file_system_type {
 	const char *name;
 	int fs_flags;
-	int (*get_sb) (struct file_system_type *, int,
-		       const char *, void *, struct vfsmount *);
 	struct dentry *(*mount) (struct file_system_type *, int,
 		       const char *, void *);
 	void (*kill_sb) (struct super_block *);
@@ -1808,24 +1818,12 @@ extern struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
 extern struct dentry *mount_bdev(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
-extern int get_sb_bdev(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
-	struct vfsmount *mnt);
 extern struct dentry *mount_single(struct file_system_type *fs_type,
 	int flags, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
-extern int get_sb_single(struct file_system_type *fs_type,
-	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
-	struct vfsmount *mnt);
 extern struct dentry *mount_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
 	int (*fill_super)(struct super_block *, void *, int));
-extern int get_sb_nodev(struct file_system_type *fs_type,
-	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int),
-	struct vfsmount *mnt);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);
@@ -1841,7 +1839,6 @@ extern struct dentry *mount_pseudo(struct file_system_type *, char *,
 	const struct super_operations *ops,
 	const struct dentry_operations *dops,
 	unsigned long);
-extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
 
 static inline void sb_mark_dirty(struct super_block *sb)
 {
@@ -1874,6 +1871,8 @@ extern void drop_collected_mounts(struct vfsmount *);
 extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *,
 			  struct vfsmount *);
 extern int vfs_statfs(struct path *, struct kstatfs *);
+extern int user_statfs(const char __user *, struct kstatfs *);
+extern int fd_statfs(int, struct kstatfs *);
 extern int statfs_by_dentry(struct dentry *, struct kstatfs *);
 extern int freeze_super(struct super_block *super);
 extern int thaw_super(struct super_block *super);
@@ -1990,6 +1989,8 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
 extern long do_sys_open(int dfd, const char __user *filename, int flags,
 			int mode);
 extern struct file *filp_open(const char *, int, int);
+extern struct file *file_open_root(struct dentry *, struct vfsmount *,
+				   const char *, int);
 extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
 				 const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
@@ -2200,15 +2201,31 @@ static inline void allow_write_access(struct file *file)
 	if (file)
 		atomic_inc(&file->f_path.dentry->d_inode->i_writecount);
 }
+#ifdef CONFIG_IMA
+static inline void i_readcount_dec(struct inode *inode)
+{
+	BUG_ON(!atomic_read(&inode->i_readcount));
+	atomic_dec(&inode->i_readcount);
+}
+static inline void i_readcount_inc(struct inode *inode)
+{
+	atomic_inc(&inode->i_readcount);
+}
+#else
+static inline void i_readcount_dec(struct inode *inode)
+{
+	return;
+}
+static inline void i_readcount_inc(struct inode *inode)
+{
+	return;
+}
+#endif
 extern int do_pipe_flags(int *, int);
 extern struct file *create_read_pipe(struct file *f, int flags);
 extern struct file *create_write_pipe(int flags);
 extern void free_write_pipe(struct file *);
 
-extern struct file *do_filp_open(int dfd, const char *pathname,
-		int open_flag, int mode, int acc_mode);
-extern int may_open(struct path *, int, int);
-
 extern int kernel_read(struct file *, loff_t, char *, unsigned long);
 extern struct file * open_exec(const char *);
  
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index dcd6a7c..ca29e03 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -428,6 +428,7 @@ extern void unregister_ftrace_graph(void);
 
 extern void ftrace_graph_init_task(struct task_struct *t);
 extern void ftrace_graph_exit_task(struct task_struct *t);
+extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu);
 
 static inline int task_curr_ret_stack(struct task_struct *t)
 {
@@ -451,6 +452,7 @@ static inline void unpause_graph_tracing(void)
 
 static inline void ftrace_graph_init_task(struct task_struct *t) { }
 static inline void ftrace_graph_exit_task(struct task_struct *t) { }
+static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { }
 
 static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc,
 			  trace_func_graph_ent_t entryfunc)
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 47e3997..22b32af 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -37,7 +37,6 @@ struct trace_entry {
 	unsigned char		flags;
 	unsigned char		preempt_count;
 	int			pid;
-	int			lock_depth;
 };
 
 #define FTRACE_MAX_EVENT						\
@@ -208,7 +207,6 @@ struct ftrace_event_call {
 
 #define PERF_MAX_TRACE_SIZE	2048
 
-#define MAX_FILTER_PRED		32
 #define MAX_FILTER_STR_VAL	256	/* Should handle KSYM_SYMBOL_LEN */
 
 extern void destroy_preds(struct ftrace_event_call *call);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index dca3176..bfb8f93 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -35,6 +35,7 @@ struct vm_area_struct;
 #define ___GFP_NOTRACK		0
 #endif
 #define ___GFP_NO_KSWAPD	0x400000u
+#define ___GFP_OTHER_NODE	0x800000u
 
 /*
  * GFP bitmasks..
@@ -83,6 +84,7 @@ struct vm_area_struct;
 #define __GFP_NOTRACK	((__force gfp_t)___GFP_NOTRACK)  /* Don't track with kmemcheck */
 
 #define __GFP_NO_KSWAPD	((__force gfp_t)___GFP_NO_KSWAPD)
+#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index 32f9fd6..ba36217 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -93,13 +93,6 @@
  */
 #define in_nmi()	(preempt_count() & NMI_MASK)
 
-#if defined(CONFIG_PREEMPT) && defined(CONFIG_BKL)
-# include <linux/sched.h>
-# define PREEMPT_INATOMIC_BASE (current->lock_depth >= 0)
-#else
-# define PREEMPT_INATOMIC_BASE 0
-#endif
-
 #if defined(CONFIG_PREEMPT)
 # define PREEMPT_CHECK_OFFSET 1
 #else
@@ -113,7 +106,7 @@
  * used in the general case to determine whether sleeping is possible.
  * Do not use in_atomic() in driver code.
  */
-#define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_INATOMIC_BASE)
+#define in_atomic()	((preempt_count() & ~PREEMPT_ACTIVE) != 0)
 
 /*
  * Check whether we were atomic before we did preempt_disable():
diff --git a/include/linux/hid-roccat.h b/include/linux/hid-roccat.h
new file mode 100644
index 0000000..24e1ca0
--- /dev/null
+++ b/include/linux/hid-roccat.h
@@ -0,0 +1,29 @@
+#ifndef __HID_ROCCAT_H
+#define __HID_ROCCAT_H
+
+/*
+ * Copyright (c) 2010 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/hid.h>
+#include <linux/types.h>
+
+#define ROCCATIOCGREPSIZE _IOR('H', 0xf1, int)
+
+#ifdef __KERNEL__
+
+int roccat_connect(struct class *klass, struct hid_device *hid,
+		int report_size);
+void roccat_disconnect(int minor);
+int roccat_report_event(int minor, u8 const *data);
+
+#endif
+
+#endif
diff --git a/include/linux/hid.h b/include/linux/hid.h
index d91c25e..bb29bb1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -504,6 +504,9 @@ struct hid_device {							/* device report descriptor */
 				  struct hid_usage *, __s32);
 	void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
 
+	/* handler for raw input (Get_Report) data, used by hidraw */
+	int (*hid_get_raw_report) (struct hid_device *, unsigned char, __u8 *, size_t, unsigned char);
+
 	/* handler for raw output data, used by hidraw */
 	int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
 
@@ -638,7 +641,7 @@ struct hid_driver {
 			struct hid_input *hidinput, struct hid_field *field,
 			struct hid_usage *usage, unsigned long **bit, int *max);
 	void (*feature_mapping)(struct hid_device *hdev,
-			struct hid_input *hidinput, struct hid_field *field,
+			struct hid_field *field,
 			struct hid_usage *usage);
 #ifdef CONFIG_PM
 	int (*suspend)(struct hid_device *hdev, pm_message_t message);
diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h
index dd8d692..4b88e69 100644
--- a/include/linux/hidraw.h
+++ b/include/linux/hidraw.h
@@ -35,6 +35,9 @@ struct hidraw_devinfo {
 #define HIDIOCGRAWINFO		_IOR('H', 0x03, struct hidraw_devinfo)
 #define HIDIOCGRAWNAME(len)     _IOC(_IOC_READ, 'H', 0x04, len)
 #define HIDIOCGRAWPHYS(len)     _IOC(_IOC_READ, 'H', 0x05, len)
+/* The first byte of SFEATURE and GFEATURE is the report number */
+#define HIDIOCSFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
+#define HIDIOCGFEATURE(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
 
 #define HIDRAW_FIRST_MINOR 0
 #define HIDRAW_MAX_DEVICES 64
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index f376ddc..62f500c 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -54,11 +54,13 @@ enum hrtimer_restart {
  * 0x00		inactive
  * 0x01		enqueued into rbtree
  * 0x02		callback function running
+ * 0x04		timer is migrated to another cpu
  *
  * Special cases:
  * 0x03		callback function running and enqueued
  *		(was requeued on another CPU)
- * 0x09		timer was migrated on CPU hotunplug
+ * 0x05		timer was migrated on CPU hotunplug
+ *
  * The "callback function running and enqueued" status is only possible on
  * SMP. It happens for example when a posix timer expired and the callback
  * queued a signal. Between dropping the lock which protects the posix timer
@@ -67,8 +69,11 @@ enum hrtimer_restart {
  * as otherwise the timer could be removed before the softirq code finishes the
  * the handling of the timer.
  *
- * The HRTIMER_STATE_ENQUEUED bit is always or'ed to the current state to
- * preserve the HRTIMER_STATE_CALLBACK bit in the above scenario.
+ * The HRTIMER_STATE_ENQUEUED bit is always or'ed to the current state
+ * to preserve the HRTIMER_STATE_CALLBACK in the above scenario. This
+ * also affects HRTIMER_STATE_MIGRATE where the preservation is not
+ * necessary. HRTIMER_STATE_MIGRATE is cleared after the timer is
+ * enqueued on the new cpu.
  *
  * All state transitions are protected by cpu_base->lock.
  */
@@ -148,7 +153,12 @@ struct hrtimer_clock_base {
 #endif
 };
 
-#define HRTIMER_MAX_CLOCK_BASES 2
+enum  hrtimer_base_type {
+	HRTIMER_BASE_REALTIME,
+	HRTIMER_BASE_MONOTONIC,
+	HRTIMER_BASE_BOOTTIME,
+	HRTIMER_MAX_CLOCK_BASES,
+};
 
 /*
  * struct hrtimer_cpu_base - the per cpu clock bases
@@ -308,6 +318,7 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer)
 
 extern ktime_t ktime_get(void);
 extern ktime_t ktime_get_real(void);
+extern ktime_t ktime_get_boottime(void);
 
 
 DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
@@ -370,8 +381,9 @@ extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
 extern ktime_t hrtimer_get_next_event(void);
 
 /*
- * A timer is active, when it is enqueued into the rbtree or the callback
- * function is running.
+ * A timer is active, when it is enqueued into the rbtree or the
+ * callback function is running or it's in the state of being migrated
+ * to another cpu.
  */
 static inline int hrtimer_active(const struct hrtimer *timer)
 {
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h
new file mode 100644
index 0000000..8390efc
--- /dev/null
+++ b/include/linux/hwspinlock.h
@@ -0,0 +1,292 @@
+/*
+ * Hardware spinlock public header
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#ifndef __LINUX_HWSPINLOCK_H
+#define __LINUX_HWSPINLOCK_H
+
+#include <linux/err.h>
+#include <linux/sched.h>
+
+/* hwspinlock mode argument */
+#define HWLOCK_IRQSTATE	0x01	/* Disable interrupts, save state */
+#define HWLOCK_IRQ	0x02	/* Disable interrupts, don't save state */
+
+struct hwspinlock;
+
+#if defined(CONFIG_HWSPINLOCK) || defined(CONFIG_HWSPINLOCK_MODULE)
+
+int hwspin_lock_register(struct hwspinlock *lock);
+struct hwspinlock *hwspin_lock_unregister(unsigned int id);
+struct hwspinlock *hwspin_lock_request(void);
+struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
+int hwspin_lock_free(struct hwspinlock *hwlock);
+int hwspin_lock_get_id(struct hwspinlock *hwlock);
+int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int,
+							unsigned long *);
+int __hwspin_trylock(struct hwspinlock *, int, unsigned long *);
+void __hwspin_unlock(struct hwspinlock *, int, unsigned long *);
+
+#else /* !CONFIG_HWSPINLOCK */
+
+/*
+ * We don't want these functions to fail if CONFIG_HWSPINLOCK is not
+ * enabled. We prefer to silently succeed in this case, and let the
+ * code path get compiled away. This way, if CONFIG_HWSPINLOCK is not
+ * required on a given setup, users will still work.
+ *
+ * The only exception is hwspin_lock_register/hwspin_lock_unregister, with which
+ * we _do_ want users to fail (no point in registering hwspinlock instances if
+ * the framework is not available).
+ *
+ * Note: ERR_PTR(-ENODEV) will still be considered a success for NULL-checking
+ * users. Others, which care, can still check this with IS_ERR.
+ */
+static inline struct hwspinlock *hwspin_lock_request(void)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+static inline int hwspin_lock_free(struct hwspinlock *hwlock)
+{
+	return 0;
+}
+
+static inline
+int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to,
+					int mode, unsigned long *flags)
+{
+	return 0;
+}
+
+static inline
+int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
+{
+	return 0;
+}
+
+static inline
+void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
+{
+	return 0;
+}
+
+static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
+{
+	return 0;
+}
+
+static inline int hwspin_lock_register(struct hwspinlock *hwlock)
+{
+	return -ENODEV;
+}
+
+static inline struct hwspinlock *hwspin_lock_unregister(unsigned int id)
+{
+	return NULL;
+}
+
+#endif /* !CONFIG_HWSPINLOCK */
+
+/**
+ * hwspin_trylock_irqsave() - try to lock an hwspinlock, disable interrupts
+ * @hwlock: an hwspinlock which we want to trylock
+ * @flags: a pointer to where the caller's interrupt state will be saved at
+ *
+ * This function attempts to lock the underlying hwspinlock, and will
+ * immediately fail if the hwspinlock is already locked.
+ *
+ * Upon a successful return from this function, preemption and local
+ * interrupts are disabled (previous interrupts state is saved at @flags),
+ * so the caller must not sleep, and is advised to release the hwspinlock
+ * as soon as possible.
+ *
+ * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
+ * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
+ */
+static inline
+int hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags)
+{
+	return __hwspin_trylock(hwlock, HWLOCK_IRQSTATE, flags);
+}
+
+/**
+ * hwspin_trylock_irq() - try to lock an hwspinlock, disable interrupts
+ * @hwlock: an hwspinlock which we want to trylock
+ *
+ * This function attempts to lock the underlying hwspinlock, and will
+ * immediately fail if the hwspinlock is already locked.
+ *
+ * Upon a successful return from this function, preemption and local
+ * interrupts are disabled, so the caller must not sleep, and is advised
+ * to release the hwspinlock as soon as possible.
+ *
+ * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
+ * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
+ */
+static inline int hwspin_trylock_irq(struct hwspinlock *hwlock)
+{
+	return __hwspin_trylock(hwlock, HWLOCK_IRQ, NULL);
+}
+
+/**
+ * hwspin_trylock() - attempt to lock a specific hwspinlock
+ * @hwlock: an hwspinlock which we want to trylock
+ *
+ * This function attempts to lock an hwspinlock, and will immediately fail
+ * if the hwspinlock is already taken.
+ *
+ * Upon a successful return from this function, preemption is disabled,
+ * so the caller must not sleep, and is advised to release the hwspinlock
+ * as soon as possible. This is required in order to minimize remote cores
+ * polling on the hardware interconnect.
+ *
+ * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
+ * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
+ */
+static inline int hwspin_trylock(struct hwspinlock *hwlock)
+{
+	return __hwspin_trylock(hwlock, 0, NULL);
+}
+
+/**
+ * hwspin_lock_timeout_irqsave() - lock hwspinlock, with timeout, disable irqs
+ * @hwlock: the hwspinlock to be locked
+ * @to: timeout value in msecs
+ * @flags: a pointer to where the caller's interrupt state will be saved at
+ *
+ * This function locks the underlying @hwlock. If the @hwlock
+ * is already taken, the function will busy loop waiting for it to
+ * be released, but give up when @timeout msecs have elapsed.
+ *
+ * Upon a successful return from this function, preemption and local interrupts
+ * are disabled (plus previous interrupt state is saved), so the caller must
+ * not sleep, and is advised to release the hwspinlock as soon as possible.
+ *
+ * Returns 0 when the @hwlock was successfully taken, and an appropriate
+ * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
+ * busy after @timeout msecs). The function will never sleep.
+ */
+static inline int hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock,
+				unsigned int to, unsigned long *flags)
+{
+	return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQSTATE, flags);
+}
+
+/**
+ * hwspin_lock_timeout_irq() - lock hwspinlock, with timeout, disable irqs
+ * @hwlock: the hwspinlock to be locked
+ * @to: timeout value in msecs
+ *
+ * This function locks the underlying @hwlock. If the @hwlock
+ * is already taken, the function will busy loop waiting for it to
+ * be released, but give up when @timeout msecs have elapsed.
+ *
+ * Upon a successful return from this function, preemption and local interrupts
+ * are disabled so the caller must not sleep, and is advised to release the
+ * hwspinlock as soon as possible.
+ *
+ * Returns 0 when the @hwlock was successfully taken, and an appropriate
+ * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
+ * busy after @timeout msecs). The function will never sleep.
+ */
+static inline
+int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int to)
+{
+	return __hwspin_lock_timeout(hwlock, to, HWLOCK_IRQ, NULL);
+}
+
+/**
+ * hwspin_lock_timeout() - lock an hwspinlock with timeout limit
+ * @hwlock: the hwspinlock to be locked
+ * @to: timeout value in msecs
+ *
+ * This function locks the underlying @hwlock. If the @hwlock
+ * is already taken, the function will busy loop waiting for it to
+ * be released, but give up when @timeout msecs have elapsed.
+ *
+ * Upon a successful return from this function, preemption is disabled
+ * so the caller must not sleep, and is advised to release the hwspinlock
+ * as soon as possible.
+ * This is required in order to minimize remote cores polling on the
+ * hardware interconnect.
+ *
+ * Returns 0 when the @hwlock was successfully taken, and an appropriate
+ * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
+ * busy after @timeout msecs). The function will never sleep.
+ */
+static inline
+int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to)
+{
+	return __hwspin_lock_timeout(hwlock, to, 0, NULL);
+}
+
+/**
+ * hwspin_unlock_irqrestore() - unlock hwspinlock, restore irq state
+ * @hwlock: a previously-acquired hwspinlock which we want to unlock
+ * @flags: previous caller's interrupt state to restore
+ *
+ * This function will unlock a specific hwspinlock, enable preemption and
+ * restore the previous state of the local interrupts. It should be used
+ * to undo, e.g., hwspin_trylock_irqsave().
+ *
+ * @hwlock must be already locked before calling this function: it is a bug
+ * to call unlock on a @hwlock that is already unlocked.
+ */
+static inline void hwspin_unlock_irqrestore(struct hwspinlock *hwlock,
+							unsigned long *flags)
+{
+	__hwspin_unlock(hwlock, HWLOCK_IRQSTATE, flags);
+}
+
+/**
+ * hwspin_unlock_irq() - unlock hwspinlock, enable interrupts
+ * @hwlock: a previously-acquired hwspinlock which we want to unlock
+ *
+ * This function will unlock a specific hwspinlock, enable preemption and
+ * enable local interrupts. Should be used to undo hwspin_lock_irq().
+ *
+ * @hwlock must be already locked (e.g. by hwspin_trylock_irq()) before
+ * calling this function: it is a bug to call unlock on a @hwlock that is
+ * already unlocked.
+ */
+static inline void hwspin_unlock_irq(struct hwspinlock *hwlock)
+{
+	__hwspin_unlock(hwlock, HWLOCK_IRQ, NULL);
+}
+
+/**
+ * hwspin_unlock() - unlock hwspinlock
+ * @hwlock: a previously-acquired hwspinlock which we want to unlock
+ *
+ * This function will unlock a specific hwspinlock and enable preemption
+ * back.
+ *
+ * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling
+ * this function: it is a bug to call unlock on a @hwlock that is already
+ * unlocked.
+ */
+static inline void hwspin_unlock(struct hwspinlock *hwlock)
+{
+	__hwspin_unlock(hwlock, 0, NULL);
+}
+
+#endif /* __LINUX_HWSPINLOCK_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
deleted file mode 100644
index 4bef5c5..0000000
--- a/include/linux/i2c-id.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/*									     */
-/* i2c-id.h - identifier values for i2c drivers and adapters		     */
-/*									     */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 1995-1999 Simon G. Vogl
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
-/* ------------------------------------------------------------------------- */
-
-#ifndef LINUX_I2C_ID_H
-#define LINUX_I2C_ID_H
-
-/* Please note that I2C driver IDs are optional. They are only needed if a
-   legacy chip driver needs to identify a bus or a bus driver needs to
-   identify a legacy client. If you don't need them, just don't set them. */
-
-/*
- * ---- Adapter types ----------------------------------------------------
- */
-
-/* --- Bit algorithm adapters						*/
-#define I2C_HW_B_CX2388x	0x01001b /* connexant 2388x based tv cards */
-
-#endif /* LINUX_I2C_ID_H */
diff --git a/include/linux/i2c-tegra.h b/include/linux/i2c-tegra.h
new file mode 100644
index 0000000..9c85da4
--- /dev/null
+++ b/include/linux/i2c-tegra.h
@@ -0,0 +1,25 @@
+/*
+ * 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 903576d..f1e3ff5 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -29,7 +29,6 @@
 #include <linux/types.h>
 #ifdef __KERNEL__
 #include <linux/module.h>
-#include <linux/i2c-id.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>	/* for struct device */
 #include <linux/sched.h>	/* for completion */
@@ -105,8 +104,8 @@ 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 (for legacy drivers)
- * @detach_adapter: Callback for bus removal (for legacy drivers)
+ * @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
@@ -144,11 +143,11 @@ 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 if you can, it will probably
-	 * be removed in a near future.
+	 * removed. You should avoid using this, it will be removed in a
+	 * near future.
 	 */
-	int (*attach_adapter)(struct i2c_adapter *);
-	int (*detach_adapter)(struct i2c_adapter *);
+	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 *);
@@ -258,9 +257,7 @@ struct i2c_board_info {
 	unsigned short	addr;
 	void		*platform_data;
 	struct dev_archdata	*archdata;
-#ifdef CONFIG_OF
 	struct device_node *of_node;
-#endif
 	int		irq;
 };
 
@@ -356,7 +353,6 @@ struct i2c_algorithm {
  */
 struct i2c_adapter {
 	struct module *owner;
-	unsigned int id __deprecated;
 	unsigned int class;		  /* classes to allow probing for */
 	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
 	void *algo_data;
@@ -398,6 +394,8 @@ i2c_parent_is_i2c_adapter(const struct i2c_adapter *adapter)
 		return NULL;
 }
 
+int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *));
+
 /* Adapter locking functions, exported for shared pin cases */
 void i2c_lock_adapter(struct i2c_adapter *);
 void i2c_unlock_adapter(struct i2c_adapter *);
@@ -449,7 +447,7 @@ extern void i2c_release_client(struct i2c_client *client);
 extern void i2c_clients_command(struct i2c_adapter *adap,
 				unsigned int cmd, void *arg);
 
-extern struct i2c_adapter *i2c_get_adapter(int id);
+extern struct i2c_adapter *i2c_get_adapter(int nr);
 extern void i2c_put_adapter(struct i2c_adapter *adap);
 
 
diff --git a/include/linux/i2c/ads1015.h b/include/linux/i2c/ads1015.h
new file mode 100644
index 0000000..d5aa2a0
--- /dev/null
+++ b/include/linux/i2c/ads1015.h
@@ -0,0 +1,36 @@
+/*
+ * Platform Data for ADS1015 12-bit 4-input ADC
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef LINUX_ADS1015_H
+#define LINUX_ADS1015_H
+
+#define ADS1015_CHANNELS 8
+
+struct ads1015_channel_data {
+	bool enabled;
+	unsigned int pga;
+	unsigned int data_rate;
+};
+
+struct ads1015_platform_data {
+	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+};
+
+#endif /* LINUX_ADS1015_H */
diff --git a/include/linux/i2c/atmel_mxt_ts.h b/include/linux/i2c/atmel_mxt_ts.h
new file mode 100644
index 0000000..f027f7a
--- /dev/null
+++ b/include/linux/i2c/atmel_mxt_ts.h
@@ -0,0 +1,44 @@
+/*
+ * Atmel maXTouch Touchscreen driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@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.
+ */
+
+#ifndef __LINUX_ATMEL_MXT_TS_H
+#define __LINUX_ATMEL_MXT_TS_H
+
+#include <linux/types.h>
+
+/* Orient */
+#define MXT_NORMAL		0x0
+#define MXT_DIAGONAL		0x1
+#define MXT_HORIZONTAL_FLIP	0x2
+#define MXT_ROTATED_90_COUNTER	0x3
+#define MXT_VERTICAL_FLIP	0x4
+#define MXT_ROTATED_90		0x5
+#define MXT_ROTATED_180		0x6
+#define MXT_DIAGONAL_COUNTER	0x7
+
+/* The platform data for the Atmel maXTouch touchscreen driver */
+struct mxt_platform_data {
+	const u8 *config;
+	size_t config_length;
+
+	unsigned int x_line;
+	unsigned int y_line;
+	unsigned int x_size;
+	unsigned int y_size;
+	unsigned int blen;
+	unsigned int threshold;
+	unsigned int voltage;
+	unsigned char orient;
+	unsigned long irqflags;
+};
+
+#endif /* __LINUX_ATMEL_MXT_TS_H */
diff --git a/include/linux/i2c/max6639.h b/include/linux/i2c/max6639.h
new file mode 100644
index 0000000..6011c42
--- /dev/null
+++ b/include/linux/i2c/max6639.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MAX6639_H
+#define _LINUX_MAX6639_H
+
+#include <linux/types.h>
+
+/* platform data for the MAX6639 temperature sensor and fan control */
+
+struct max6639_platform_data {
+	bool pwm_polarity;	/* Polarity low (0) or high (1, default) */
+	int ppr;		/* Pulses per rotation 1..4 (default == 2) */
+	int rpm_range;		/* 2000, 4000 (default), 8000 or 16000 */
+};
+
+#endif /* _LINUX_MAX6639_H */
diff --git a/include/linux/i2c/mcs.h b/include/linux/i2c/mcs.h
index 725ae7c..61bb18a 100644
--- a/include/linux/i2c/mcs.h
+++ b/include/linux/i2c/mcs.h
@@ -18,6 +18,7 @@
 #define MCS_KEY_CODE(v)		((v) & 0xffff)
 
 struct mcs_platform_data {
+	void (*poweron)(bool);
 	void (*cfg_pin)(void);
 
 	/* touchscreen */
diff --git a/include/linux/i2c/pmbus.h b/include/linux/i2c/pmbus.h
new file mode 100644
index 0000000..69280db
--- /dev/null
+++ b/include/linux/i2c/pmbus.h
@@ -0,0 +1,45 @@
+/*
+ * Hardware monitoring driver for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 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.
+ *
+ * You 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 _PMBUS_H_
+#define _PMBUS_H_
+
+/* flags */
+
+/*
+ * PMBUS_SKIP_STATUS_CHECK
+ *
+ * During register detection, skip checking the status register for
+ * communication or command errors.
+ *
+ * Some PMBus chips respond with valid data when trying to read an unsupported
+ * register. For such chips, checking the status register is mandatory when
+ * trying to determine if a chip register exists or not.
+ * Other PMBus chips don't support the STATUS_CML register, or report
+ * communication errors for no explicable reason. For such chips, checking
+ * the status register must be disabled.
+ */
+#define PMBUS_SKIP_STATUS_CHECK	(1 << 0)
+
+struct pmbus_platform_data {
+	u32 flags;		/* Device specific flags */
+};
+
+#endif /* _PMBUS_H_ */
diff --git a/include/linux/i2c/pxa-i2c.h b/include/linux/i2c/pxa-i2c.h
new file mode 100644
index 0000000..1a9f65e
--- /dev/null
+++ b/include/linux/i2c/pxa-i2c.h
@@ -0,0 +1,82 @@
+/*
+ *  i2c_pxa.h
+ *
+ *  Copyright (C) 2002 Intrinsyc Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ */
+#ifndef _I2C_PXA_H_
+#define _I2C_PXA_H_
+
+#if 0
+#define DEF_TIMEOUT             3
+#else
+/* need a longer timeout if we're dealing with the fact we may well be
+ * looking at a multi-master environment
+*/
+#define DEF_TIMEOUT             32
+#endif
+
+#define BUS_ERROR               (-EREMOTEIO)
+#define XFER_NAKED              (-ECONNREFUSED)
+#define I2C_RETRY               (-2000) /* an error has occurred retry transmit */
+
+/* ICR initialize bit values
+*
+*  15. FM       0 (100 Khz operation)
+*  14. UR       0 (No unit reset)
+*  13. SADIE    0 (Disables the unit from interrupting on slave addresses
+*                                       matching its slave address)
+*  12. ALDIE    0 (Disables the unit from interrupt when it loses arbitration
+*                                       in master mode)
+*  11. SSDIE    0 (Disables interrupts from a slave stop detected, in slave mode)
+*  10. BEIE     1 (Enable interrupts from detected bus errors, no ACK sent)
+*  9.  IRFIE    1 (Enable interrupts from full buffer received)
+*  8.  ITEIE    1 (Enables the I2C unit to interrupt when transmit buffer empty)
+*  7.  GCD      1 (Disables i2c unit response to general call messages as a slave)
+*  6.  IUE      0 (Disable unit until we change settings)
+*  5.  SCLE     1 (Enables the i2c clock output for master mode (drives SCL)
+*  4.  MA       0 (Only send stop with the ICR stop bit)
+*  3.  TB       0 (We are not transmitting a byte initially)
+*  2.  ACKNAK   0 (Send an ACK after the unit receives a byte)
+*  1.  STOP     0 (Do not send a STOP)
+*  0.  START    0 (Do not send a START)
+*
+*/
+#define I2C_ICR_INIT	(ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE)
+
+/* I2C status register init values
+ *
+ * 10. BED      1 (Clear bus error detected)
+ * 9.  SAD      1 (Clear slave address detected)
+ * 7.  IRF      1 (Clear IDBR Receive Full)
+ * 6.  ITE      1 (Clear IDBR Transmit Empty)
+ * 5.  ALD      1 (Clear Arbitration Loss Detected)
+ * 4.  SSD      1 (Clear Slave Stop Detected)
+ */
+#define I2C_ISR_INIT	0x7FF  /* status register init */
+
+struct i2c_slave_client;
+
+struct i2c_pxa_platform_data {
+	unsigned int		slave_addr;
+	struct i2c_slave_client	*slave;
+	unsigned int		class;
+	unsigned int		use_pio :1;
+	unsigned int		fast_mode :1;
+};
+
+extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info);
+
+#ifdef CONFIG_PXA27x
+extern void pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info);
+#endif
+
+#ifdef CONFIG_PXA3xx
+extern void pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info);
+#endif
+
+#endif
diff --git a/include/linux/i2c/qt602240_ts.h b/include/linux/i2c/qt602240_ts.h
deleted file mode 100644
index c5033e1..0000000
--- a/include/linux/i2c/qt602240_ts.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * AT42QT602240/ATMXT224 Touchscreen driver
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@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.
- */
-
-#ifndef __LINUX_QT602240_TS_H
-#define __LINUX_QT602240_TS_H
-
-/* Orient */
-#define QT602240_NORMAL			0x0
-#define QT602240_DIAGONAL		0x1
-#define QT602240_HORIZONTAL_FLIP	0x2
-#define QT602240_ROTATED_90_COUNTER	0x3
-#define QT602240_VERTICAL_FLIP		0x4
-#define QT602240_ROTATED_90		0x5
-#define QT602240_ROTATED_180		0x6
-#define QT602240_DIAGONAL_COUNTER	0x7
-
-/* The platform data for the AT42QT602240/ATMXT224 touchscreen driver */
-struct qt602240_platform_data {
-	unsigned int x_line;
-	unsigned int y_line;
-	unsigned int x_size;
-	unsigned int y_size;
-	unsigned int blen;
-	unsigned int threshold;
-	unsigned int voltage;
-	unsigned char orient;
-};
-
-#endif /* __LINUX_QT602240_TS_H */
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 61b9609..58afd9d 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -600,6 +600,8 @@ struct twl4030_usb_data {
 	int		(*phy_power)(struct device *dev, int iD, int on);
 	/* enable/disable  phy clocks */
 	int		(*phy_set_clock)(struct device *dev, int on);
+	/* suspend/resume of phy */
+	int		(*phy_suspend)(struct device *dev, int suspend);
 };
 
 struct twl4030_ins {
@@ -637,7 +639,6 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
 extern int twl4030_remove_script(u8 flags);
 
 struct twl4030_codec_audio_data {
-	unsigned int audio_mclk; /* not used, will be removed */
 	unsigned int digimic_delay; /* in ms */
 	unsigned int ramp_delay_value;
 	unsigned int offset_cncl_path;
@@ -648,7 +649,6 @@ struct twl4030_codec_audio_data {
 };
 
 struct twl4030_codec_vibra_data {
-	unsigned int	audio_mclk;
 	unsigned int	coexist;
 };
 
diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
index 4c4c74e..ba45e6b 100644
--- a/include/linux/icmpv6.h
+++ b/include/linux/icmpv6.h
@@ -183,10 +183,10 @@ extern void				icmpv6_cleanup(void);
 extern void				icmpv6_param_prob(struct sk_buff *skb,
 							  u8 code, int pos);
 
-struct flowi;
+struct flowi6;
 struct in6_addr;
 extern void				icmpv6_flow_init(struct sock *sk,
-							 struct flowi *fl,
+							 struct flowi6 *fl6,
 							 u8 type,
 							 const struct in6_addr *saddr,
 							 const struct in6_addr *daddr,
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 294169e..2d1c611 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1325,6 +1325,9 @@ enum {
 /* Although the spec says 8 I'm seeing 6 in practice */
 #define IEEE80211_COUNTRY_IE_MIN_LEN	6
 
+/* The Country String field of the element shall be 3 octets in length */
+#define IEEE80211_COUNTRY_STRING_LEN	3
+
 /*
  * For regulatory extension stuff see IEEE 802.11-2007
  * Annex I (page 1141) and Annex J (page 1147). Also
diff --git a/include/linux/if.h b/include/linux/if.h
index 1239599..3bc63e6 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -71,11 +71,10 @@
 					 * release skb->dst
 					 */
 #define IFF_DONT_BRIDGE 0x800		/* disallow bridging this ether dev */
-#define IFF_IN_NETPOLL	0x1000		/* whether we are processing netpoll */
-#define IFF_DISABLE_NETPOLL	0x2000	/* disable netpoll at run-time */
-#define IFF_MACVLAN_PORT	0x4000	/* device used as macvlan port */
-#define IFF_BRIDGE_PORT	0x8000		/* device used as bridge port */
-#define IFF_OVS_DATAPATH	0x10000	/* device used as Open vSwitch
+#define IFF_DISABLE_NETPOLL	0x1000	/* disable netpoll at run-time */
+#define IFF_MACVLAN_PORT	0x2000	/* device used as macvlan port */
+#define IFF_BRIDGE_PORT	0x4000		/* device used as bridge port */
+#define IFF_OVS_DATAPATH	0x8000	/* device used as Open vSwitch
 					 * datapath port */
 
 #define IF_GET_IFACE	0x0001		/* for querying only */
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 6485d2a..f4a2e6b 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -135,6 +135,7 @@ enum {
 	IFLA_VF_PORTS,
 	IFLA_PORT_SELF,
 	IFLA_AF_SPEC,
+	IFLA_GROUP,		/* Group the device belongs to */
 	__IFLA_MAX
 };
 
diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h
index fcef103..c9ad383 100644
--- a/include/linux/if_ppp.h
+++ b/include/linux/if_ppp.h
@@ -114,14 +114,14 @@ struct pppol2tp_ioc_stats {
 	__u16		tunnel_id;	/* redundant */
 	__u16		session_id;	/* if zero, get tunnel stats */
 	__u32		using_ipsec:1;	/* valid only for session_id == 0 */
-	aligned_u64	tx_packets;
-	aligned_u64	tx_bytes;
-	aligned_u64	tx_errors;
-	aligned_u64	rx_packets;
-	aligned_u64	rx_bytes;
-	aligned_u64	rx_seq_discards;
-	aligned_u64	rx_oos_packets;
-	aligned_u64	rx_errors;
+	__aligned_u64	tx_packets;
+	__aligned_u64	tx_bytes;
+	__aligned_u64	tx_errors;
+	__aligned_u64	rx_packets;
+	__aligned_u64	rx_bytes;
+	__aligned_u64	rx_seq_discards;
+	__aligned_u64	rx_oos_packets;
+	__aligned_u64	rx_errors;
 };
 
 #define ifr__name       b.ifr_ifrn.ifrn_name
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 74cfcff..82de336 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -217,7 +217,7 @@ struct ip_mc_list {
 #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
 #define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value)
 
-extern int ip_check_mc(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u16 proto);
+extern int ip_check_mc_rcu(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u16 proto);
 extern int igmp_rcv(struct sk_buff *);
 extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
 extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 975837e..09e6e62 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -20,7 +20,6 @@ extern void ima_inode_free(struct inode *inode);
 extern int ima_file_check(struct file *file, int mask);
 extern void ima_file_free(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
-extern void ima_counts_get(struct file *file);
 
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
@@ -53,10 +52,5 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot)
 	return 0;
 }
 
-static inline void ima_counts_get(struct file *file)
-{
-	return;
-}
-
 #endif /* CONFIG_IMA_H */
 #endif /* _LINUX_IMA_H */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index ae8fdc5..5f81466 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -144,6 +144,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev)
 #define IN_DEV_ARP_NOTIFY(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_NOTIFY)
 
 struct in_ifaddr {
+	struct hlist_node	hash;
 	struct in_ifaddr	*ifa_next;
 	struct in_device	*ifa_dev;
 	struct rcu_head		rcu_head;
diff --git a/include/linux/input-polldev.h b/include/linux/input-polldev.h
index 5e3dddf..ce0b724 100644
--- a/include/linux/input-polldev.h
+++ b/include/linux/input-polldev.h
@@ -22,12 +22,12 @@
  * @poll: driver-supplied method that polls the device and posts
  *	input events (mandatory).
  * @poll_interval: specifies how often the poll() method should be called.
- *	Defaults to 500 msec unless overriden when registering the device.
+ *	Defaults to 500 msec unless overridden when registering the device.
  * @poll_interval_max: specifies upper bound for the poll interval.
  *	Defaults to the initial value of @poll_interval.
  * @poll_interval_min: specifies lower bound for the poll interval.
  *	Defaults to 0.
- * @input: input device structire associated with the polled device.
+ * @input: input device structure associated with the polled device.
  *	Must be properly initialized by the driver (id, name, phys, bits).
  *
  * Polled input device provides a skeleton for supporting simple input
diff --git a/include/linux/input.h b/include/linux/input.h
index e428382..056ae8a 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1154,8 +1154,6 @@ struct ff_effect {
  *	sparse keymaps. If not supplied default mechanism will be used.
  *	The method is being called while holding event_lock and thus must
  *	not sleep
- * @getkeycode_new: transition method
- * @setkeycode_new: transition method
  * @ff: force feedback structure associated with the device if device
  *	supports force feedback effects
  * @repeat_key: stores key code of the last key pressed; used to implement
@@ -1234,14 +1232,10 @@ struct input_dev {
 	void *keycode;
 
 	int (*setkeycode)(struct input_dev *dev,
-			  unsigned int scancode, unsigned int keycode);
+			  const struct input_keymap_entry *ke,
+			  unsigned int *old_keycode);
 	int (*getkeycode)(struct input_dev *dev,
-			  unsigned int scancode, unsigned int *keycode);
-	int (*setkeycode_new)(struct input_dev *dev,
-			      const struct input_keymap_entry *ke,
-			      unsigned int *old_keycode);
-	int (*getkeycode_new)(struct input_dev *dev,
-			      struct input_keymap_entry *ke);
+			  struct input_keymap_entry *ke);
 
 	struct ff_device *ff;
 
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 55e0d42..59b72ca 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -14,6 +14,8 @@
 #include <linux/smp.h>
 #include <linux/percpu.h>
 #include <linux/hrtimer.h>
+#include <linux/kref.h>
+#include <linux/workqueue.h>
 
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
@@ -55,7 +57,8 @@
  *                Used by threaded interrupts which need to keep the
  *                irq line disabled until the threaded handler has been run.
  * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
- *
+ * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
+ * IRQF_NO_THREAD - Interrupt cannot be threaded
  */
 #define IRQF_DISABLED		0x00000020
 #define IRQF_SAMPLE_RANDOM	0x00000040
@@ -67,22 +70,10 @@
 #define IRQF_IRQPOLL		0x00001000
 #define IRQF_ONESHOT		0x00002000
 #define IRQF_NO_SUSPEND		0x00004000
+#define IRQF_FORCE_RESUME	0x00008000
+#define IRQF_NO_THREAD		0x00010000
 
-#define IRQF_TIMER		(__IRQF_TIMER | IRQF_NO_SUSPEND)
-
-/*
- * Bits used by threaded handlers:
- * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
- * IRQTF_DIED      - handler thread died
- * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
- * IRQTF_AFFINITY  - irq thread is requested to adjust affinity
- */
-enum {
-	IRQTF_RUNTHREAD,
-	IRQTF_DIED,
-	IRQTF_WARNED,
-	IRQTF_AFFINITY,
-};
+#define IRQF_TIMER		(__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
 
 /*
  * These values can be returned by request_any_context_irq() and
@@ -110,6 +101,7 @@ typedef irqreturn_t (*irq_handler_t)(int, void *);
  * @thread_fn:	interupt handler function for threaded interrupts
  * @thread:	thread pointer for threaded interrupts
  * @thread_flags:	flags related to @thread
+ * @thread_mask:	bitmask for keeping track of @thread activity
  */
 struct irqaction {
 	irq_handler_t handler;
@@ -120,6 +112,7 @@ struct irqaction {
 	irq_handler_t thread_fn;
 	struct task_struct *thread;
 	unsigned long thread_flags;
+	unsigned long thread_mask;
 	const char *name;
 	struct proc_dir_entry *dir;
 } ____cacheline_internodealigned_in_smp;
@@ -240,6 +233,35 @@ extern int irq_can_set_affinity(unsigned int irq);
 extern int irq_select_affinity(unsigned int irq);
 
 extern int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m);
+
+/**
+ * struct irq_affinity_notify - context for notification of IRQ affinity changes
+ * @irq:		Interrupt to which notification applies
+ * @kref:		Reference count, for internal use
+ * @work:		Work item, for internal use
+ * @notify:		Function to be called on change.  This will be
+ *			called in process context.
+ * @release:		Function to be called on release.  This will be
+ *			called in process context.  Once registered, the
+ *			structure must only be freed when this function is
+ *			called or later.
+ */
+struct irq_affinity_notify {
+	unsigned int irq;
+	struct kref kref;
+	struct work_struct work;
+	void (*notify)(struct irq_affinity_notify *, const cpumask_t *mask);
+	void (*release)(struct kref *ref);
+};
+
+extern int
+irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
+
+static inline void irq_run_affinity_notifiers(void)
+{
+	flush_scheduled_work();
+}
+
 #else /* CONFIG_SMP */
 
 static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m)
@@ -255,7 +277,7 @@ static inline int irq_can_set_affinity(unsigned int irq)
 static inline int irq_select_affinity(unsigned int irq)  { return 0; }
 
 static inline int irq_set_affinity_hint(unsigned int irq,
-                                        const struct cpumask *m)
+					const struct cpumask *m)
 {
 	return -EINVAL;
 }
@@ -314,16 +336,24 @@ static inline void enable_irq_lockdep_irqrestore(unsigned int irq, unsigned long
 }
 
 /* IRQ wakeup (PM) control: */
-extern int set_irq_wake(unsigned int irq, unsigned int on);
+extern int irq_set_irq_wake(unsigned int irq, unsigned int on);
+
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+/* Please do not use: Use the replacement functions instead */
+static inline int set_irq_wake(unsigned int irq, unsigned int on)
+{
+	return irq_set_irq_wake(irq, on);
+}
+#endif
 
 static inline int enable_irq_wake(unsigned int irq)
 {
-	return set_irq_wake(irq, 1);
+	return irq_set_irq_wake(irq, 1);
 }
 
 static inline int disable_irq_wake(unsigned int irq)
 {
-	return set_irq_wake(irq, 0);
+	return irq_set_irq_wake(irq, 0);
 }
 
 #else /* !CONFIG_GENERIC_HARDIRQS */
@@ -353,6 +383,13 @@ static inline int disable_irq_wake(unsigned int irq)
 }
 #endif /* CONFIG_GENERIC_HARDIRQS */
 
+
+#ifdef CONFIG_IRQ_FORCED_THREADING
+extern bool force_irqthreads;
+#else
+#define force_irqthreads	(0)
+#endif
+
 #ifndef __ARCH_SET_SOFTIRQ_PENDING
 #define set_softirq_pending(x) (local_softirq_pending() = (x))
 #define or_softirq_pending(x)  (local_softirq_pending() |= (x))
@@ -426,6 +463,13 @@ extern void raise_softirq(unsigned int nr);
  */
 DECLARE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
 
+DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
+
+static inline struct task_struct *this_cpu_ksoftirqd(void)
+{
+	return this_cpu_read(ksoftirqd);
+}
+
 /* Try to send a softirq to a remote cpu.  If this cannot be done, the
  * work will be queued to the local cpu.
  */
@@ -645,6 +689,7 @@ static inline void init_irq_proc(void)
 
 struct seq_file;
 int show_interrupts(struct seq_file *p, void *v);
+int arch_show_interrupts(struct seq_file *p, int prec);
 
 extern int early_irq_init(void);
 extern int arch_probe_nr_irqs(void);
diff --git a/include/linux/ip_vs.h b/include/linux/ip_vs.h
index 5f43a3b..4deb383 100644
--- a/include/linux/ip_vs.h
+++ b/include/linux/ip_vs.h
@@ -89,6 +89,14 @@
 #define IP_VS_CONN_F_TEMPLATE	0x1000		/* template, not connection */
 #define IP_VS_CONN_F_ONE_PACKET	0x2000		/* forward only one packet */
 
+#define IP_VS_CONN_F_BACKUP_MASK (IP_VS_CONN_F_FWD_MASK | \
+				  IP_VS_CONN_F_NOOUTPUT | \
+				  IP_VS_CONN_F_INACTIVE | \
+				  IP_VS_CONN_F_SEQ_MASK | \
+				  IP_VS_CONN_F_NO_CPORT | \
+				  IP_VS_CONN_F_TEMPLATE \
+				 )
+
 /* Flags that are not sent to backup server start from bit 16 */
 #define IP_VS_CONN_F_NFCT	(1 << 16)	/* use netfilter conntrack */
 
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 80fcb53..1d3577f 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -29,61 +29,104 @@
 #include <asm/irq_regs.h>
 
 struct irq_desc;
+struct irq_data;
 typedef	void (*irq_flow_handler_t)(unsigned int irq,
 					    struct irq_desc *desc);
-
+typedef	void (*irq_preflow_handler_t)(struct irq_data *data);
 
 /*
  * IRQ line status.
  *
- * Bits 0-7 are reserved for the IRQF_* bits in linux/interrupt.h
+ * Bits 0-7 are the same as the IRQF_* bits in linux/interrupt.h
+ *
+ * IRQ_TYPE_NONE		- default, unspecified type
+ * IRQ_TYPE_EDGE_RISING		- rising edge triggered
+ * IRQ_TYPE_EDGE_FALLING	- falling edge triggered
+ * IRQ_TYPE_EDGE_BOTH		- rising and falling edge triggered
+ * IRQ_TYPE_LEVEL_HIGH		- high level triggered
+ * IRQ_TYPE_LEVEL_LOW		- low level triggered
+ * IRQ_TYPE_LEVEL_MASK		- Mask to filter out the level bits
+ * IRQ_TYPE_SENSE_MASK		- Mask for all the above bits
+ * IRQ_TYPE_PROBE		- Special flag for probing in progress
+ *
+ * Bits which can be modified via irq_set/clear/modify_status_flags()
+ * IRQ_LEVEL			- Interrupt is level type. Will be also
+ *				  updated in the code when the above trigger
+ *				  bits are modified via set_irq_type()
+ * IRQ_PER_CPU			- Mark an interrupt PER_CPU. Will protect
+ *				  it from affinity setting
+ * IRQ_NOPROBE			- Interrupt cannot be probed by autoprobing
+ * IRQ_NOREQUEST		- Interrupt cannot be requested via
+ *				  request_irq()
+ * IRQ_NOAUTOEN			- Interrupt is not automatically enabled in
+ *				  request/setup_irq()
+ * IRQ_NO_BALANCING		- Interrupt cannot be balanced (affinity set)
+ * IRQ_MOVE_PCNTXT		- Interrupt can be migrated from process context
+ * IRQ_NESTED_TRHEAD		- Interrupt nests into another thread
+ *
+ * Deprecated bits. They are kept updated as long as
+ * CONFIG_GENERIC_HARDIRQS_NO_COMPAT is not set. Will go away soon. These bits
+ * are internal state of the core code and if you really need to acces
+ * them then talk to the genirq maintainer instead of hacking
+ * something weird.
  *
- * IRQ types
  */
-#define IRQ_TYPE_NONE		0x00000000	/* Default, unspecified type */
-#define IRQ_TYPE_EDGE_RISING	0x00000001	/* Edge rising type */
-#define IRQ_TYPE_EDGE_FALLING	0x00000002	/* Edge falling type */
-#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
-#define IRQ_TYPE_LEVEL_HIGH	0x00000004	/* Level high type */
-#define IRQ_TYPE_LEVEL_LOW	0x00000008	/* Level low type */
-#define IRQ_TYPE_SENSE_MASK	0x0000000f	/* Mask of the above */
-#define IRQ_TYPE_PROBE		0x00000010	/* Probing in progress */
-
-/* Internal flags */
-#define IRQ_INPROGRESS		0x00000100	/* IRQ handler active - do not enter! */
-#define IRQ_DISABLED		0x00000200	/* IRQ disabled - do not enter! */
-#define IRQ_PENDING		0x00000400	/* IRQ pending - replay on enable */
-#define IRQ_REPLAY		0x00000800	/* IRQ has been replayed but not acked yet */
-#define IRQ_AUTODETECT		0x00001000	/* IRQ is being autodetected */
-#define IRQ_WAITING		0x00002000	/* IRQ not yet seen - for autodetection */
-#define IRQ_LEVEL		0x00004000	/* IRQ level triggered */
-#define IRQ_MASKED		0x00008000	/* IRQ masked - shouldn't be seen again */
-#define IRQ_PER_CPU		0x00010000	/* IRQ is per CPU */
-#define IRQ_NOPROBE		0x00020000	/* IRQ is not valid for probing */
-#define IRQ_NOREQUEST		0x00040000	/* IRQ cannot be requested */
-#define IRQ_NOAUTOEN		0x00080000	/* IRQ will not be enabled on request irq */
-#define IRQ_WAKEUP		0x00100000	/* IRQ triggers system wakeup */
-#define IRQ_MOVE_PENDING	0x00200000	/* need to re-target IRQ destination */
-#define IRQ_NO_BALANCING	0x00400000	/* IRQ is excluded from balancing */
-#define IRQ_SPURIOUS_DISABLED	0x00800000	/* IRQ was disabled by the spurious trap */
-#define IRQ_MOVE_PCNTXT		0x01000000	/* IRQ migration from process context */
-#define IRQ_AFFINITY_SET	0x02000000	/* IRQ affinity was set from userspace*/
-#define IRQ_SUSPENDED		0x04000000	/* IRQ has gone through suspend sequence */
-#define IRQ_ONESHOT		0x08000000	/* IRQ is not unmasked after hardirq */
-#define IRQ_NESTED_THREAD	0x10000000	/* IRQ is nested into another, no own handler thread */
+enum {
+	IRQ_TYPE_NONE		= 0x00000000,
+	IRQ_TYPE_EDGE_RISING	= 0x00000001,
+	IRQ_TYPE_EDGE_FALLING	= 0x00000002,
+	IRQ_TYPE_EDGE_BOTH	= (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING),
+	IRQ_TYPE_LEVEL_HIGH	= 0x00000004,
+	IRQ_TYPE_LEVEL_LOW	= 0x00000008,
+	IRQ_TYPE_LEVEL_MASK	= (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
+	IRQ_TYPE_SENSE_MASK	= 0x0000000f,
+
+	IRQ_TYPE_PROBE		= 0x00000010,
+
+	IRQ_LEVEL		= (1 <<  8),
+	IRQ_PER_CPU		= (1 <<  9),
+	IRQ_NOPROBE		= (1 << 10),
+	IRQ_NOREQUEST		= (1 << 11),
+	IRQ_NOAUTOEN		= (1 << 12),
+	IRQ_NO_BALANCING	= (1 << 13),
+	IRQ_MOVE_PCNTXT		= (1 << 14),
+	IRQ_NESTED_THREAD	= (1 << 15),
+
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+	IRQ_INPROGRESS		= (1 << 16),
+	IRQ_REPLAY		= (1 << 17),
+	IRQ_WAITING		= (1 << 18),
+	IRQ_DISABLED		= (1 << 19),
+	IRQ_PENDING		= (1 << 20),
+	IRQ_MASKED		= (1 << 21),
+	IRQ_MOVE_PENDING	= (1 << 22),
+	IRQ_AFFINITY_SET	= (1 << 23),
+	IRQ_WAKEUP		= (1 << 24),
+#endif
+};
 
 #define IRQF_MODIFY_MASK	\
 	(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
 	 IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
-	 IRQ_PER_CPU)
+	 IRQ_PER_CPU | IRQ_NESTED_THREAD)
 
-#ifdef CONFIG_IRQ_PER_CPU
-# define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
-# define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
-#else
-# define CHECK_IRQ_PER_CPU(var) 0
-# define IRQ_NO_BALANCING_MASK	IRQ_NO_BALANCING
-#endif
+#define IRQ_NO_BALANCING_MASK	(IRQ_PER_CPU | IRQ_NO_BALANCING)
+
+static inline __deprecated bool CHECK_IRQ_PER_CPU(unsigned int status)
+{
+	return status & IRQ_PER_CPU;
+}
+
+/*
+ * Return value for chip->irq_set_affinity()
+ *
+ * IRQ_SET_MASK_OK	- OK, core updates irq_data.affinity
+ * IRQ_SET_MASK_NOCPY	- OK, chip did update irq_data.affinity
+ */
+enum {
+	IRQ_SET_MASK_OK = 0,
+	IRQ_SET_MASK_OK_NOCOPY,
+};
 
 struct msi_desc;
 
@@ -91,6 +134,8 @@ struct msi_desc;
  * struct irq_data - per irq and irq chip data passed down to chip functions
  * @irq:		interrupt number
  * @node:		node index useful for balancing
+ * @state_use_accessor: status information for irq chip functions.
+ *			Use accessor functions to deal with it
  * @chip:		low level interrupt hardware access
  * @handler_data:	per-IRQ data for the irq_chip methods
  * @chip_data:		platform-specific per-chip private data for the chip
@@ -105,6 +150,7 @@ struct msi_desc;
 struct irq_data {
 	unsigned int		irq;
 	unsigned int		node;
+	unsigned int		state_use_accessors;
 	struct irq_chip		*chip;
 	void			*handler_data;
 	void			*chip_data;
@@ -114,6 +160,80 @@ struct irq_data {
 #endif
 };
 
+/*
+ * Bit masks for irq_data.state
+ *
+ * IRQD_TRIGGER_MASK		- Mask for the trigger type bits
+ * IRQD_SETAFFINITY_PENDING	- Affinity setting is pending
+ * IRQD_NO_BALANCING		- Balancing disabled for this IRQ
+ * IRQD_PER_CPU			- Interrupt is per cpu
+ * IRQD_AFFINITY_SET		- Interrupt affinity was set
+ * IRQD_LEVEL			- Interrupt is level triggered
+ * IRQD_WAKEUP_STATE		- Interrupt is configured for wakeup
+ *				  from suspend
+ * IRDQ_MOVE_PCNTXT		- Interrupt can be moved in process
+ *				  context
+ */
+enum {
+	IRQD_TRIGGER_MASK		= 0xf,
+	IRQD_SETAFFINITY_PENDING	= (1 <<  8),
+	IRQD_NO_BALANCING		= (1 << 10),
+	IRQD_PER_CPU			= (1 << 11),
+	IRQD_AFFINITY_SET		= (1 << 12),
+	IRQD_LEVEL			= (1 << 13),
+	IRQD_WAKEUP_STATE		= (1 << 14),
+	IRQD_MOVE_PCNTXT		= (1 << 15),
+};
+
+static inline bool irqd_is_setaffinity_pending(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_SETAFFINITY_PENDING;
+}
+
+static inline bool irqd_is_per_cpu(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_PER_CPU;
+}
+
+static inline bool irqd_can_balance(struct irq_data *d)
+{
+	return !(d->state_use_accessors & (IRQD_PER_CPU | IRQD_NO_BALANCING));
+}
+
+static inline bool irqd_affinity_was_set(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_AFFINITY_SET;
+}
+
+static inline u32 irqd_get_trigger_type(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_TRIGGER_MASK;
+}
+
+/*
+ * Must only be called inside irq_chip.irq_set_type() functions.
+ */
+static inline void irqd_set_trigger_type(struct irq_data *d, u32 type)
+{
+	d->state_use_accessors &= ~IRQD_TRIGGER_MASK;
+	d->state_use_accessors |= type & IRQD_TRIGGER_MASK;
+}
+
+static inline bool irqd_is_level_type(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_LEVEL;
+}
+
+static inline bool irqd_is_wakeup_set(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_WAKEUP_STATE;
+}
+
+static inline bool irqd_can_move_in_process_context(struct irq_data *d)
+{
+	return d->state_use_accessors & IRQD_MOVE_PCNTXT;
+}
+
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
@@ -150,6 +270,7 @@ struct irq_data {
  * @irq_set_wake:	enable/disable power-management wake-on of an IRQ
  * @irq_bus_lock:	function to lock access to slow bus (i2c) chips
  * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
+ * @flags:		chip specific flags
  *
  * @release:		release function solely used by UML
  */
@@ -196,12 +317,27 @@ struct irq_chip {
 	void		(*irq_bus_lock)(struct irq_data *data);
 	void		(*irq_bus_sync_unlock)(struct irq_data *data);
 
+	unsigned long	flags;
+
 	/* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
 	void		(*release)(unsigned int irq, void *dev_id);
 #endif
 };
 
+/*
+ * irq_chip specific flags
+ *
+ * IRQCHIP_SET_TYPE_MASKED:	Mask before calling chip.irq_set_type()
+ * IRQCHIP_EOI_IF_HANDLED:	Only issue irq_eoi() when irq was handled
+ * IRQCHIP_MASK_ON_SUSPEND:	Mask non wake irqs in the suspend path
+ */
+enum {
+	IRQCHIP_SET_TYPE_MASKED		= (1 <<  0),
+	IRQCHIP_EOI_IF_HANDLED		= (1 <<  1),
+	IRQCHIP_MASK_ON_SUSPEND		= (1 <<  2),
+};
+
 /* This include will go away once we isolated irq_desc usage to core code */
 #include <linux/irqdesc.h>
 
@@ -218,7 +354,7 @@ struct irq_chip {
 # define ARCH_IRQ_INIT_FLAGS	0
 #endif
 
-#define IRQ_DEFAULT_INIT_FLAGS	(IRQ_DISABLED | ARCH_IRQ_INIT_FLAGS)
+#define IRQ_DEFAULT_INIT_FLAGS	ARCH_IRQ_INIT_FLAGS
 
 struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
@@ -229,9 +365,13 @@ extern void remove_irq(unsigned int irq, struct irqaction *act);
 #if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
 void move_native_irq(int irq);
 void move_masked_irq(int irq);
+void irq_move_irq(struct irq_data *data);
+void irq_move_masked_irq(struct irq_data *data);
 #else
 static inline void move_native_irq(int irq) { }
 static inline void move_masked_irq(int irq) { }
+static inline void irq_move_irq(struct irq_data *data) { }
+static inline void irq_move_masked_irq(struct irq_data *data) { }
 #endif
 
 extern int no_irq_affinity;
@@ -267,23 +407,23 @@ extern struct irq_chip no_irq_chip;
 extern struct irq_chip dummy_irq_chip;
 
 extern void
-set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
-			 irq_flow_handler_t handle);
-extern void
-set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
+irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
 			      irq_flow_handler_t handle, const char *name);
 
+static inline void irq_set_chip_and_handler(unsigned int irq, struct irq_chip *chip,
+					    irq_flow_handler_t handle)
+{
+	irq_set_chip_and_handler_name(irq, chip, handle, NULL);
+}
+
 extern void
-__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name);
 
-/*
- * Set a highlevel flow handler for a given IRQ:
- */
 static inline void
-set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
+irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
 {
-	__set_irq_handler(irq, handle, 0, NULL);
+	__irq_set_handler(irq, handle, 0, NULL);
 }
 
 /*
@@ -292,14 +432,11 @@ set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
  *  IRQ_NOREQUEST and IRQ_NOPROBE)
  */
 static inline void
-set_irq_chained_handler(unsigned int irq,
-			irq_flow_handler_t handle)
+irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
 {
-	__set_irq_handler(irq, handle, 1, NULL);
+	__irq_set_handler(irq, handle, 1, NULL);
 }
 
-extern void set_irq_nested_thread(unsigned int irq, int nest);
-
 void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set);
 
 static inline void irq_set_status_flags(unsigned int irq, unsigned long set)
@@ -312,16 +449,24 @@ static inline void irq_clear_status_flags(unsigned int irq, unsigned long clr)
 	irq_modify_status(irq, clr, 0);
 }
 
-static inline void set_irq_noprobe(unsigned int irq)
+static inline void irq_set_noprobe(unsigned int irq)
 {
 	irq_modify_status(irq, 0, IRQ_NOPROBE);
 }
 
-static inline void set_irq_probe(unsigned int irq)
+static inline void irq_set_probe(unsigned int irq)
 {
 	irq_modify_status(irq, IRQ_NOPROBE, 0);
 }
 
+static inline void irq_set_nested_thread(unsigned int irq, bool nest)
+{
+	if (nest)
+		irq_set_status_flags(irq, IRQ_NESTED_THREAD);
+	else
+		irq_clear_status_flags(irq, IRQ_NESTED_THREAD);
+}
+
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
@@ -338,14 +483,14 @@ static inline void dynamic_irq_init(unsigned int irq)
 }
 
 /* Set/get chip/data for an IRQ: */
-extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
-extern int set_irq_data(unsigned int irq, void *data);
-extern int set_irq_chip_data(unsigned int irq, void *data);
-extern int set_irq_type(unsigned int irq, unsigned int type);
-extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
+extern int irq_set_chip(unsigned int irq, struct irq_chip *chip);
+extern int irq_set_handler_data(unsigned int irq, void *data);
+extern int irq_set_chip_data(unsigned int irq, void *data);
+extern int irq_set_irq_type(unsigned int irq, unsigned int type);
+extern int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry);
 extern struct irq_data *irq_get_irq_data(unsigned int irq);
 
-static inline struct irq_chip *get_irq_chip(unsigned int irq)
+static inline struct irq_chip *irq_get_chip(unsigned int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
 	return d ? d->chip : NULL;
@@ -356,7 +501,7 @@ static inline struct irq_chip *irq_data_get_irq_chip(struct irq_data *d)
 	return d->chip;
 }
 
-static inline void *get_irq_chip_data(unsigned int irq)
+static inline void *irq_get_chip_data(unsigned int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
 	return d ? d->chip_data : NULL;
@@ -367,18 +512,18 @@ static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
 	return d->chip_data;
 }
 
-static inline void *get_irq_data(unsigned int irq)
+static inline void *irq_get_handler_data(unsigned int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
 	return d ? d->handler_data : NULL;
 }
 
-static inline void *irq_data_get_irq_data(struct irq_data *d)
+static inline void *irq_data_get_irq_handler_data(struct irq_data *d)
 {
 	return d->handler_data;
 }
 
-static inline struct msi_desc *get_irq_msi(unsigned int irq)
+static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
 {
 	struct irq_data *d = irq_get_irq_data(irq);
 	return d ? d->msi_desc : NULL;
@@ -389,6 +534,89 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
 	return d->msi_desc;
 }
 
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+/* Please do not use: Use the replacement functions instead */
+static inline int set_irq_chip(unsigned int irq, struct irq_chip *chip)
+{
+	return irq_set_chip(irq, chip);
+}
+static inline int set_irq_data(unsigned int irq, void *data)
+{
+	return irq_set_handler_data(irq, data);
+}
+static inline int set_irq_chip_data(unsigned int irq, void *data)
+{
+	return irq_set_chip_data(irq, data);
+}
+static inline int set_irq_type(unsigned int irq, unsigned int type)
+{
+	return irq_set_irq_type(irq, type);
+}
+static inline int set_irq_msi(unsigned int irq, struct msi_desc *entry)
+{
+	return irq_set_msi_desc(irq, entry);
+}
+static inline struct irq_chip *get_irq_chip(unsigned int irq)
+{
+	return irq_get_chip(irq);
+}
+static inline void *get_irq_chip_data(unsigned int irq)
+{
+	return irq_get_chip_data(irq);
+}
+static inline void *get_irq_data(unsigned int irq)
+{
+	return irq_get_handler_data(irq);
+}
+static inline void *irq_data_get_irq_data(struct irq_data *d)
+{
+	return irq_data_get_irq_handler_data(d);
+}
+static inline struct msi_desc *get_irq_msi(unsigned int irq)
+{
+	return irq_get_msi_desc(irq);
+}
+static inline void set_irq_noprobe(unsigned int irq)
+{
+	irq_set_noprobe(irq);
+}
+static inline void set_irq_probe(unsigned int irq)
+{
+	irq_set_probe(irq);
+}
+static inline void set_irq_nested_thread(unsigned int irq, int nest)
+{
+	irq_set_nested_thread(irq, nest);
+}
+static inline void
+set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
+			      irq_flow_handler_t handle, const char *name)
+{
+	irq_set_chip_and_handler_name(irq, chip, handle, name);
+}
+static inline void
+set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
+			 irq_flow_handler_t handle)
+{
+	irq_set_chip_and_handler(irq, chip, handle);
+}
+static inline void
+__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+		  const char *name)
+{
+	__irq_set_handler(irq, handle, is_chained, name);
+}
+static inline void set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
+{
+	irq_set_handler(irq, handle);
+}
+static inline void
+set_irq_chained_handler(unsigned int irq, irq_flow_handler_t handle)
+{
+	irq_set_chained_handler(irq, handle);
+}
+#endif
+
 int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
 void irq_free_descs(unsigned int irq, unsigned int cnt);
 int irq_reserve_irqs(unsigned int from, unsigned int cnt);
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index c1a95b7..0021837 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -8,6 +8,7 @@
  * For now it's included from <linux/irq.h>
  */
 
+struct irq_affinity_notify;
 struct proc_dir_entry;
 struct timer_rand_state;
 /**
@@ -18,13 +19,16 @@ struct timer_rand_state;
  * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()]
  * @action:		the irq action chain
  * @status:		status information
+ * @core_internal_state__do_not_mess_with_it: core internal status information
  * @depth:		disable-depth, for nested irq_disable() calls
  * @wake_depth:		enable depth, for multiple set_irq_wake() callers
  * @irq_count:		stats field to detect stalled irqs
  * @last_unhandled:	aging timer for unhandled count
  * @irqs_unhandled:	stats field for spurious unhandled interrupts
  * @lock:		locking for SMP
+ * @affinity_notify:	context for notification of affinity changes
  * @pending_mask:	pending rebalanced interrupts
+ * @threads_oneshot:	bitfield to handle shared oneshot threads
  * @threads_active:	number of irqaction threads currently running
  * @wait_for_threads:	wait queue for sync_irq to wait for threaded handlers
  * @dir:		/proc/irq/ procfs entry
@@ -45,6 +49,7 @@ struct irq_desc {
 		struct {
 			unsigned int		irq;
 			unsigned int		node;
+			unsigned int		pad_do_not_even_think_about_it;
 			struct irq_chip		*chip;
 			void			*handler_data;
 			void			*chip_data;
@@ -59,9 +64,16 @@ struct irq_desc {
 	struct timer_rand_state *timer_rand_state;
 	unsigned int __percpu	*kstat_irqs;
 	irq_flow_handler_t	handle_irq;
+#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+	irq_preflow_handler_t	preflow_handler;
+#endif
 	struct irqaction	*action;	/* IRQ action list */
+#ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+	unsigned int		status_use_accessors;
+#else
 	unsigned int		status;		/* IRQ status */
-
+#endif
+	unsigned int		core_internal_state__do_not_mess_with_it;
 	unsigned int		depth;		/* nested irq disables */
 	unsigned int		wake_depth;	/* nested wake enables */
 	unsigned int		irq_count;	/* For detecting broken IRQs */
@@ -70,10 +82,12 @@ struct irq_desc {
 	raw_spinlock_t		lock;
 #ifdef CONFIG_SMP
 	const struct cpumask	*affinity_hint;
+	struct irq_affinity_notify *affinity_notify;
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	cpumask_var_t		pending_mask;
 #endif
 #endif
+	unsigned long		threads_oneshot;
 	atomic_t		threads_active;
 	wait_queue_head_t       wait_for_threads;
 #ifdef CONFIG_PROC_FS
@@ -95,10 +109,51 @@ static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 
-#define get_irq_desc_chip(desc)		((desc)->irq_data.chip)
-#define get_irq_desc_chip_data(desc)	((desc)->irq_data.chip_data)
-#define get_irq_desc_data(desc)		((desc)->irq_data.handler_data)
-#define get_irq_desc_msi(desc)		((desc)->irq_data.msi_desc)
+static inline struct irq_data *irq_desc_get_irq_data(struct irq_desc *desc)
+{
+	return &desc->irq_data;
+}
+
+static inline struct irq_chip *irq_desc_get_chip(struct irq_desc *desc)
+{
+	return desc->irq_data.chip;
+}
+
+static inline void *irq_desc_get_chip_data(struct irq_desc *desc)
+{
+	return desc->irq_data.chip_data;
+}
+
+static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
+{
+	return desc->irq_data.handler_data;
+}
+
+static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc)
+{
+	return desc->irq_data.msi_desc;
+}
+
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+static inline struct irq_chip *get_irq_desc_chip(struct irq_desc *desc)
+{
+	return irq_desc_get_chip(desc);
+}
+static inline void *get_irq_desc_data(struct irq_desc *desc)
+{
+	return irq_desc_get_handler_data(desc);
+}
+
+static inline void *get_irq_desc_chip_data(struct irq_desc *desc)
+{
+	return irq_desc_get_chip_data(desc);
+}
+
+static inline struct msi_desc *get_irq_desc_msi(struct irq_desc *desc)
+{
+	return irq_desc_get_msi_desc(desc);
+}
+#endif
 
 /*
  * Architectures call this to let the generic IRQ layer
@@ -123,6 +178,7 @@ static inline int irq_has_action(unsigned int irq)
 	return desc->action != NULL;
 }
 
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
 static inline int irq_balancing_disabled(unsigned int irq)
 {
 	struct irq_desc *desc;
@@ -130,6 +186,7 @@ static inline int irq_balancing_disabled(unsigned int irq)
 	desc = irq_to_desc(irq);
 	return desc->status & IRQ_NO_BALANCING_MASK;
 }
+#endif
 
 /* caller has locked the irq_desc and both params are valid */
 static inline void __set_irq_handler_unlocked(int irq,
@@ -140,6 +197,17 @@ static inline void __set_irq_handler_unlocked(int irq,
 	desc = irq_to_desc(irq);
 	desc->handle_irq = handler;
 }
+
+#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+static inline void
+__irq_set_preflow_handler(unsigned int irq, irq_preflow_handler_t handler)
+{
+	struct irq_desc *desc;
+
+	desc = irq_to_desc(irq);
+	desc->preflow_handler = handler;
+}
+#endif
 #endif
 
 #endif
diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h
index 6811f4b..922aa31 100644
--- a/include/linux/jiffies.h
+++ b/include/linux/jiffies.h
@@ -307,6 +307,7 @@ extern clock_t jiffies_to_clock_t(long x);
 extern unsigned long clock_t_to_jiffies(unsigned long x);
 extern u64 jiffies_64_to_clock_t(u64 x);
 extern u64 nsec_to_clock_t(u64 x);
+extern u64 nsecs_to_jiffies64(u64 n);
 extern unsigned long nsecs_to_jiffies(u64 n);
 
 #define TIMESTAMP_SIZE	30
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 506ad20..ec2d17b 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -50,11 +50,12 @@ struct kbd_struct {
 #define VC_CAPSLOCK	2	/* capslock mode */
 #define VC_KANALOCK	3	/* kanalock mode */
 
-	unsigned char kbdmode:2;	/* one 2-bit value */
+	unsigned char kbdmode:3;	/* one 3-bit value */
 #define VC_XLATE	0	/* translate keycodes using keymap */
 #define VC_MEDIUMRAW	1	/* medium raw (keycode) mode */
 #define VC_RAW		2	/* raw (scancode) mode */
 #define VC_UNICODE	3	/* Unicode mode */
+#define VC_OFF		4	/* disabled mode */
 
 	unsigned char modeflags:5;
 #define VC_APPLIC	0	/* application key mode */
@@ -158,7 +159,7 @@ static inline void con_schedule_flip(struct tty_struct *t)
 	if (t->buf.tail != NULL)
 		t->buf.tail->commit = t->buf.tail->used;
 	spin_unlock_irqrestore(&t->buf.lock, flags);
-	schedule_delayed_work(&t->buf.work, 0);
+	schedule_work(&t->buf.work);
 }
 
 #endif
diff --git a/include/linux/kd.h b/include/linux/kd.h
index 15f2853..c36d847 100644
--- a/include/linux/kd.h
+++ b/include/linux/kd.h
@@ -81,6 +81,7 @@ struct unimapinit {
 #define		K_XLATE		0x01
 #define		K_MEDIUMRAW	0x02
 #define		K_UNICODE	0x03
+#define		K_OFF		0x04
 #define KDGKBMODE	0x4B44	/* gets current keyboard mode */
 #define KDSKBMODE	0x4B45	/* sets current keyboard mode */
 
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2fe6e84..00cec4d 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -187,14 +187,76 @@ NORET_TYPE void do_exit(long error_code)
 	ATTRIB_NORET;
 NORET_TYPE void complete_and_exit(struct completion *, long)
 	ATTRIB_NORET;
+
+/* Internal, do not use. */
+int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res);
+int __must_check _kstrtol(const char *s, unsigned int base, long *res);
+
+int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res);
+int __must_check kstrtoll(const char *s, unsigned int base, long long *res);
+static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+	/*
+	 * We want to shortcut function call, but
+	 * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0.
+	 */
+	if (sizeof(unsigned long) == sizeof(unsigned long long) &&
+	    __alignof__(unsigned long) == __alignof__(unsigned long long))
+		return kstrtoull(s, base, (unsigned long long *)res);
+	else
+		return _kstrtoul(s, base, res);
+}
+
+static inline int __must_check kstrtol(const char *s, unsigned int base, long *res)
+{
+	/*
+	 * We want to shortcut function call, but
+	 * __builtin_types_compatible_p(long, long long) = 0.
+	 */
+	if (sizeof(long) == sizeof(long long) &&
+	    __alignof__(long) == __alignof__(long long))
+		return kstrtoll(s, base, (long long *)res);
+	else
+		return _kstrtol(s, base, res);
+}
+
+int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res);
+int __must_check kstrtoint(const char *s, unsigned int base, int *res);
+
+static inline int __must_check kstrtou64(const char *s, unsigned int base, u64 *res)
+{
+	return kstrtoull(s, base, res);
+}
+
+static inline int __must_check kstrtos64(const char *s, unsigned int base, s64 *res)
+{
+	return kstrtoll(s, base, res);
+}
+
+static inline int __must_check kstrtou32(const char *s, unsigned int base, u32 *res)
+{
+	return kstrtouint(s, base, res);
+}
+
+static inline int __must_check kstrtos32(const char *s, unsigned int base, s32 *res)
+{
+	return kstrtoint(s, base, res);
+}
+
+int __must_check kstrtou16(const char *s, unsigned int base, u16 *res);
+int __must_check kstrtos16(const char *s, unsigned int base, s16 *res);
+int __must_check kstrtou8(const char *s, unsigned int base, u8 *res);
+int __must_check kstrtos8(const char *s, unsigned int base, s8 *res);
+
 extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
 extern long long simple_strtoll(const char *,char **,unsigned int);
-extern int __must_check strict_strtoul(const char *, unsigned int, unsigned long *);
-extern int __must_check strict_strtol(const char *, unsigned int, long *);
-extern int __must_check strict_strtoull(const char *, unsigned int, unsigned long long *);
-extern int __must_check strict_strtoll(const char *, unsigned int, long long *);
+#define strict_strtoul	kstrtoul
+#define strict_strtol	kstrtol
+#define strict_strtoull	kstrtoull
+#define strict_strtoll	kstrtoll
+
 extern int sprintf(char * buf, const char * fmt, ...)
 	__attribute__ ((format (printf, 2, 3)));
 extern int vsprintf(char *buf, const char *, va_list)
diff --git a/include/linux/key-type.h b/include/linux/key-type.h
index 65833d4..9efd081 100644
--- a/include/linux/key-type.h
+++ b/include/linux/key-type.h
@@ -41,6 +41,9 @@ struct key_type {
 	 */
 	size_t def_datalen;
 
+	/* vet a description */
+	int (*vet_description)(const char *description);
+
 	/* instantiate a key of this type
 	 * - this method should call key_payload_reserve() to determine if the
 	 *   user's quota will hold the payload
@@ -102,11 +105,20 @@ extern int key_instantiate_and_link(struct key *key,
 				    size_t datalen,
 				    struct key *keyring,
 				    struct key *instkey);
-extern int key_negate_and_link(struct key *key,
+extern int key_reject_and_link(struct key *key,
 			       unsigned timeout,
+			       unsigned error,
 			       struct key *keyring,
 			       struct key *instkey);
 extern void complete_request_key(struct key_construction *cons, int error);
 
+static inline int key_negate_and_link(struct key *key,
+				      unsigned timeout,
+				      struct key *keyring,
+				      struct key *instkey)
+{
+	return key_reject_and_link(key, timeout, ENOKEY, keyring, instkey);
+}
+
 #endif /* CONFIG_KEYS */
 #endif /* _LINUX_KEY_TYPE_H */
diff --git a/include/linux/key.h b/include/linux/key.h
index 3db0adc..b2bb017 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -170,6 +170,7 @@ struct key {
 		struct list_head	link;
 		unsigned long		x[2];
 		void			*p[2];
+		int			reject_error;
 	} type_data;
 
 	/* key data
@@ -275,6 +276,10 @@ static inline key_serial_t key_serial(struct key *key)
 	return key ? key->serial : 0;
 }
 
+#define rcu_dereference_key(KEY)					\
+	(rcu_dereference_protected((KEY)->payload.rcudata,		\
+				   rwsem_is_locked(&((struct key *)(KEY))->sem)))
+
 #ifdef CONFIG_SYSCTL
 extern ctl_table key_sysctls[];
 #endif
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index bd383f1..9b0b865 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -53,5 +53,7 @@
 #define KEYCTL_ASSUME_AUTHORITY		16	/* assume request_key() authorisation */
 #define KEYCTL_GET_SECURITY		17	/* get key security label */
 #define KEYCTL_SESSION_TO_PARENT	18	/* apply session keyring to parent process */
+#define KEYCTL_REJECT			19	/* reject a partially constructed key */
+#define KEYCTL_INSTANTIATE_IOV		20	/* instantiate a partially constructed key */
 
 #endif /*  _LINUX_KEYCTL_H */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 8f6d121..9229b64 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -85,11 +85,13 @@ static inline const char *kobject_name(const struct kobject *kobj)
 extern void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
 extern int __must_check kobject_add(struct kobject *kobj,
 				    struct kobject *parent,
-				    const char *fmt, ...);
+				    const char *fmt, ...)
+	__attribute__((format(printf, 3, 4)));
 extern int __must_check kobject_init_and_add(struct kobject *kobj,
 					     struct kobj_type *ktype,
 					     struct kobject *parent,
-					     const char *fmt, ...);
+					     const char *fmt, ...)
+	__attribute__((format(printf, 4, 5)));
 
 extern void kobject_del(struct kobject *kobj);
 
@@ -224,8 +226,8 @@ static inline int kobject_uevent_env(struct kobject *kobj,
 				      char *envp[])
 { return 0; }
 
-static inline int add_uevent_var(struct kobj_uevent_env *env,
-				 const char *format, ...)
+static inline __attribute__((format(printf, 2, 3)))
+int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
 { return 0; }
 
 static inline int kobject_action_type(const char *buf, size_t count,
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index ce0775a..1e923e5 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -4,10 +4,15 @@
 #include <linux/err.h>
 #include <linux/sched.h>
 
-struct task_struct *kthread_create(int (*threadfn)(void *data),
-				   void *data,
-				   const char namefmt[], ...)
-	__attribute__((format(printf, 3, 4)));
+struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
+					   void *data,
+					   int node,
+					   const char namefmt[], ...)
+	__attribute__((format(printf, 4, 5)));
+
+#define kthread_create(threadfn, data, namefmt, arg...) \
+	kthread_create_on_node(threadfn, data, -1, namefmt, ##arg)
+
 
 /**
  * kthread_run - create and wake a thread.
@@ -34,6 +39,7 @@ void *kthread_data(struct task_struct *k);
 
 int kthreadd(void *unused);
 extern struct task_struct *kthreadd_task;
+extern int tsk_fork_get_node(struct task_struct *tsk);
 
 /*
  * Simple work processor based on kthread.
@@ -64,7 +70,7 @@ struct kthread_work {
 };
 
 #define KTHREAD_WORKER_INIT(worker)	{				\
-	.lock = SPIN_LOCK_UNLOCKED,					\
+	.lock = __SPIN_LOCK_UNLOCKED((worker).lock),			\
 	.work_list = LIST_HEAD_INIT((worker).work_list),		\
 	}
 
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b5021db..ab42855 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -43,6 +43,7 @@
 #define KVM_REQ_DEACTIVATE_FPU    10
 #define KVM_REQ_EVENT             11
 #define KVM_REQ_APF_HALT          12
+#define KVM_REQ_NMI               13
 
 #define KVM_USERSPACE_IRQ_SOURCE_ID	0
 
@@ -98,23 +99,31 @@ int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, gfn_t gfn,
 int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu);
 #endif
 
+enum {
+	OUTSIDE_GUEST_MODE,
+	IN_GUEST_MODE,
+	EXITING_GUEST_MODE
+};
+
 struct kvm_vcpu {
 	struct kvm *kvm;
 #ifdef CONFIG_PREEMPT_NOTIFIERS
 	struct preempt_notifier preempt_notifier;
 #endif
+	int cpu;
 	int vcpu_id;
-	struct mutex mutex;
-	int   cpu;
-	atomic_t guest_mode;
-	struct kvm_run *run;
+	int srcu_idx;
+	int mode;
 	unsigned long requests;
 	unsigned long guest_debug;
-	int srcu_idx;
+
+	struct mutex mutex;
+	struct kvm_run *run;
 
 	int fpu_active;
 	int guest_fpu_loaded, guest_xcr0_loaded;
 	wait_queue_head_t wq;
+	struct pid *pid;
 	int sigset_active;
 	sigset_t sigset;
 	struct kvm_vcpu_stat stat;
@@ -140,6 +149,11 @@ struct kvm_vcpu {
 	struct kvm_vcpu_arch arch;
 };
 
+static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
+{
+	return cmpxchg(&vcpu->mode, IN_GUEST_MODE, EXITING_GUEST_MODE);
+}
+
 /*
  * Some of the bitops functions do not support too long bitmaps.
  * This number must be determined not to exceed such limits.
@@ -212,7 +226,6 @@ struct kvm_memslots {
 
 struct kvm {
 	spinlock_t mmu_lock;
-	raw_spinlock_t requests_lock;
 	struct mutex slots_lock;
 	struct mm_struct *mm; /* userspace tied to this vm */
 	struct kvm_memslots *memslots;
@@ -223,6 +236,7 @@ struct kvm {
 #endif
 	struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
 	atomic_t online_vcpus;
+	int last_boosted_vcpu;
 	struct list_head vm_list;
 	struct mutex lock;
 	struct kvm_io_bus *buses[KVM_NR_BUSES];
@@ -719,11 +733,6 @@ static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
 	set_bit(req, &vcpu->requests);
 }
 
-static inline bool kvm_make_check_request(int req, struct kvm_vcpu *vcpu)
-{
-	return test_and_set_bit(req, &vcpu->requests);
-}
-
 static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
 {
 	if (test_bit(req, &vcpu->requests)) {
diff --git a/include/linux/led-lm3530.h b/include/linux/led-lm3530.h
new file mode 100644
index 0000000..bb69d20
--- /dev/null
+++ b/include/linux/led-lm3530.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson SA.
+ * Copyright (C) 2009 Motorola, Inc.
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Simple driver for National Semiconductor LM35330 Backlight driver chip
+ *
+ * Author: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>
+ * based on leds-lm3530.c by Dan Murphy <D.Murphy@motorola.com>
+ */
+
+#ifndef _LINUX_LED_LM3530_H__
+#define _LINUX_LED_LM3530_H__
+
+#define LM3530_FS_CURR_5mA		(0) /* Full Scale Current */
+#define LM3530_FS_CURR_8mA		(1)
+#define LM3530_FS_CURR_12mA		(2)
+#define LM3530_FS_CURR_15mA		(3)
+#define LM3530_FS_CURR_19mA		(4)
+#define LM3530_FS_CURR_22mA		(5)
+#define LM3530_FS_CURR_26mA		(6)
+#define LM3530_FS_CURR_29mA		(7)
+
+#define LM3530_ALS_AVRG_TIME_32ms	(0) /* ALS Averaging Time */
+#define LM3530_ALS_AVRG_TIME_64ms	(1)
+#define LM3530_ALS_AVRG_TIME_128ms	(2)
+#define LM3530_ALS_AVRG_TIME_256ms	(3)
+#define LM3530_ALS_AVRG_TIME_512ms	(4)
+#define LM3530_ALS_AVRG_TIME_1024ms	(5)
+#define LM3530_ALS_AVRG_TIME_2048ms	(6)
+#define LM3530_ALS_AVRG_TIME_4096ms	(7)
+
+#define LM3530_RAMP_TIME_1ms		(0) /* Brigtness Ramp Time */
+#define LM3530_RAMP_TIME_130ms		(1) /* Max to 0 and vice versa */
+#define LM3530_RAMP_TIME_260ms		(2)
+#define LM3530_RAMP_TIME_520ms		(3)
+#define LM3530_RAMP_TIME_1s		(4)
+#define LM3530_RAMP_TIME_2s		(5)
+#define LM3530_RAMP_TIME_4s		(6)
+#define LM3530_RAMP_TIME_8s		(7)
+
+/* ALS Resistor Select */
+#define LM3530_ALS_IMPD_Z		(0x00) /* ALS Impedence */
+#define LM3530_ALS_IMPD_13_53kOhm	(0x01)
+#define LM3530_ALS_IMPD_9_01kOhm	(0x02)
+#define LM3530_ALS_IMPD_5_41kOhm	(0x03)
+#define LM3530_ALS_IMPD_2_27kOhm	(0x04)
+#define LM3530_ALS_IMPD_1_94kOhm	(0x05)
+#define LM3530_ALS_IMPD_1_81kOhm	(0x06)
+#define LM3530_ALS_IMPD_1_6kOhm		(0x07)
+#define LM3530_ALS_IMPD_1_138kOhm	(0x08)
+#define LM3530_ALS_IMPD_1_05kOhm	(0x09)
+#define LM3530_ALS_IMPD_1_011kOhm	(0x0A)
+#define LM3530_ALS_IMPD_941Ohm		(0x0B)
+#define LM3530_ALS_IMPD_759Ohm		(0x0C)
+#define LM3530_ALS_IMPD_719Ohm		(0x0D)
+#define LM3530_ALS_IMPD_700Ohm		(0x0E)
+#define LM3530_ALS_IMPD_667Ohm		(0x0F)
+
+enum lm3530_mode {
+	LM3530_BL_MODE_MANUAL = 0,	/* "man" */
+	LM3530_BL_MODE_ALS,		/* "als" */
+	LM3530_BL_MODE_PWM,		/* "pwm" */
+};
+
+/* ALS input select */
+enum lm3530_als_mode {
+	LM3530_INPUT_AVRG = 0,	/* ALS1 and ALS2 input average */
+	LM3530_INPUT_ALS1,	/* ALS1 Input */
+	LM3530_INPUT_ALS2,	/* ALS2 Input */
+	LM3530_INPUT_CEIL,	/* Max of ALS1 and ALS2 */
+};
+
+/**
+ * struct lm3530_platform_data
+ * @mode: mode of operation i.e. Manual, ALS or PWM
+ * @als_input_mode: select source of ALS input - ALS1/2 or average
+ * @max_current: full scale LED current
+ * @pwm_pol_hi: PWM input polarity - active high/active low
+ * @als_avrg_time: ALS input averaging time
+ * @brt_ramp_law: brightness mapping mode - exponential/linear
+ * @brt_ramp_fall: rate of fall of led current
+ * @brt_ramp_rise: rate of rise of led current
+ * @als1_resistor_sel: internal resistance from ALS1 input to ground
+ * @als2_resistor_sel: internal resistance from ALS2 input to ground
+ * @brt_val: brightness value (0-255)
+ */
+struct lm3530_platform_data {
+	enum lm3530_mode mode;
+	enum lm3530_als_mode als_input_mode;
+
+	u8 max_current;
+	bool pwm_pol_hi;
+	u8 als_avrg_time;
+
+	bool brt_ramp_law;
+	u8 brt_ramp_fall;
+	u8 brt_ramp_rise;
+
+	u8 als1_resistor_sel;
+	u8 als2_resistor_sel;
+
+	u8 brt_val;
+};
+
+#endif	/* _LINUX_LED_LM3530_H__ */
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 0f19df9..383811d 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -194,11 +194,11 @@ struct gpio_led {
 
 struct gpio_led_platform_data {
 	int 		num_leds;
-	struct gpio_led *leds;
+	const struct gpio_led *leds;
 
 #define GPIO_LED_NO_BLINK_LOW	0	/* No blink GPIO state low */
 #define GPIO_LED_NO_BLINK_HIGH	1	/* No blink GPIO state high */
-#define GPIO_LED_BLINK		2	/* Plase, blink */
+#define GPIO_LED_BLINK		2	/* Please, blink */
 	int		(*gpio_blink_set)(unsigned gpio, int state,
 					unsigned long *delay_on,
 					unsigned long *delay_off);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index c9c5d7a..c71f469 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -179,10 +179,6 @@ enum {
 	ATA_FLAG_SLAVE_POSS	= (1 << 0), /* host supports slave dev */
 					    /* (doesn't imply presence) */
 	ATA_FLAG_SATA		= (1 << 1),
-	ATA_FLAG_NO_LEGACY	= (1 << 2), /* no legacy mode check */
-	ATA_FLAG_MMIO		= (1 << 3), /* use MMIO, not PIO */
-	ATA_FLAG_SRST		= (1 << 4), /* (obsolete) use ATA SRST, not E.D.D. */
-	ATA_FLAG_SATA_RESET	= (1 << 5), /* (obsolete) use COMRESET */
 	ATA_FLAG_NO_ATAPI	= (1 << 6), /* No ATAPI support */
 	ATA_FLAG_PIO_DMA	= (1 << 7), /* PIO cmds via DMA */
 	ATA_FLAG_PIO_LBA48	= (1 << 8), /* Host DMA engine is LBA28 only */
@@ -198,7 +194,6 @@ enum {
 	ATA_FLAG_ACPI_SATA	= (1 << 17), /* need native SATA ACPI layout */
 	ATA_FLAG_AN		= (1 << 18), /* controller supports AN */
 	ATA_FLAG_PMP		= (1 << 19), /* controller supports PMP */
-	ATA_FLAG_LPM		= (1 << 20), /* driver can handle LPM */
 	ATA_FLAG_EM		= (1 << 21), /* driver supports enclosure
 					      * management */
 	ATA_FLAG_SW_ACTIVITY	= (1 << 22), /* driver supports sw activity
@@ -1050,6 +1045,8 @@ extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
 				       int queue_depth, int reason);
 extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
+extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
+extern void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, struct list_head *eh_q);
 
 extern int ata_cable_40wire(struct ata_port *ap);
 extern int ata_cable_80wire(struct ata_port *ap);
@@ -1613,6 +1610,9 @@ extern void ata_sff_irq_on(struct ata_port *ap);
 extern void ata_sff_irq_clear(struct ata_port *ap);
 extern int ata_sff_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
 			    u8 status, int in_wq);
+extern void ata_sff_queue_work(struct work_struct *work);
+extern void ata_sff_queue_delayed_work(struct delayed_work *dwork,
+		unsigned long delay);
 extern void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay);
 extern unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc);
 extern bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc);
diff --git a/include/linux/magic.h b/include/linux/magic.h
index 62730ea..1e5df2a 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -23,10 +23,12 @@
 #define XENFS_SUPER_MAGIC	0xabba1974
 #define EXT4_SUPER_MAGIC	0xEF53
 #define BTRFS_SUPER_MAGIC	0x9123683E
+#define NILFS_SUPER_MAGIC	0x3434
 #define HPFS_SUPER_MAGIC	0xf995e849
 #define ISOFS_SUPER_MAGIC	0x9660
 #define JFFS2_SUPER_MAGIC	0x72b6
 #define ANON_INODE_FS_MAGIC	0x09041934
+#define PSTOREFS_MAGIC		0x6165676C
 
 #define MINIX_SUPER_MAGIC	0x137F		/* original minix fs */
 #define MINIX_SUPER_MAGIC2	0x138F		/* minix fs, 30 char names */
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index f512e18..5bb7be2 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -62,6 +62,7 @@ extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 					gfp_t gfp_mask);
 extern void mem_cgroup_add_lru_list(struct page *page, enum lru_list lru);
 extern void mem_cgroup_del_lru_list(struct page *page, enum lru_list lru);
+extern void mem_cgroup_rotate_reclaimable_page(struct page *page);
 extern void mem_cgroup_rotate_lru_list(struct page *page, enum lru_list lru);
 extern void mem_cgroup_del_lru(struct page *page);
 extern void mem_cgroup_move_lists(struct page *page,
@@ -96,7 +97,7 @@ extern struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem);
 
 extern int
 mem_cgroup_prepare_migration(struct page *page,
-	struct page *newpage, struct mem_cgroup **ptr);
+	struct page *newpage, struct mem_cgroup **ptr, gfp_t gfp_mask);
 extern void mem_cgroup_end_migration(struct mem_cgroup *mem,
 	struct page *oldpage, struct page *newpage, bool migration_ok);
 
@@ -211,6 +212,11 @@ static inline void mem_cgroup_del_lru_list(struct page *page, int lru)
 	return ;
 }
 
+static inline inline void mem_cgroup_rotate_reclaimable_page(struct page *page)
+{
+	return ;
+}
+
 static inline void mem_cgroup_rotate_lru_list(struct page *page, int lru)
 {
 	return ;
@@ -249,7 +255,7 @@ static inline struct cgroup_subsys_state *mem_cgroup_css(struct mem_cgroup *mem)
 
 static inline int
 mem_cgroup_prepare_migration(struct page *page, struct page *newpage,
-	struct mem_cgroup **ptr)
+	struct mem_cgroup **ptr, gfp_t gfp_mask)
 {
 	return 0;
 }
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 06c1fa0..e1e3b2b 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -21,7 +21,8 @@
 #include <linux/mutex.h>
 
 struct memory_block {
-	unsigned long phys_index;
+	unsigned long start_section_nr;
+	unsigned long end_section_nr;
 	unsigned long state;
 	int section_count;
 
diff --git a/include/linux/mfd/ti_ssp.h b/include/linux/mfd/ti_ssp.h
new file mode 100644
index 0000000..dbb4b43
--- /dev/null
+++ b/include/linux/mfd/ti_ssp.h
@@ -0,0 +1,93 @@
+/*
+ * Sequencer Serial Port (SSP) driver for Texas Instruments' SoCs
+ *
+ * Copyright (C) 2010 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __TI_SSP_H__
+#define __TI_SSP_H__
+
+struct ti_ssp_dev_data {
+	const char	*dev_name;
+	void		*pdata;
+	size_t		pdata_size;
+};
+
+struct ti_ssp_data {
+	unsigned long		out_clock;
+	struct ti_ssp_dev_data	dev_data[2];
+};
+
+struct ti_ssp_spi_data {
+	unsigned long	iosel;
+	int		num_cs;
+	void		(*select)(int cs);
+};
+
+/*
+ * Sequencer port IO pin configuration bits.  These do not correlate 1-1 with
+ * the hardware.  The iosel field in the port data combines iosel1 and iosel2,
+ * and is therefore not a direct map to register space.  It is best to use the
+ * macros below to construct iosel values.
+ *
+ * least significant 16 bits --> iosel1
+ * most significant 16 bits  --> iosel2
+ */
+
+#define SSP_IN			0x0000
+#define SSP_DATA		0x0001
+#define SSP_CLOCK		0x0002
+#define SSP_CHIPSEL		0x0003
+#define SSP_OUT			0x0004
+#define SSP_PIN_SEL(pin, v)	((v) << ((pin) * 3))
+#define SSP_PIN_MASK(pin)	SSP_PIN_SEL(pin, 0x7)
+#define SSP_INPUT_SEL(pin)	((pin) << 16)
+
+/* Sequencer port config bits */
+#define SSP_EARLY_DIN		BIT(8)
+#define SSP_DELAY_DOUT		BIT(9)
+
+/* Sequence map definitions */
+#define SSP_CLK_HIGH		BIT(0)
+#define SSP_CLK_LOW		0
+#define SSP_DATA_HIGH		BIT(1)
+#define SSP_DATA_LOW		0
+#define SSP_CS_HIGH		BIT(2)
+#define SSP_CS_LOW		0
+#define SSP_OUT_MODE		BIT(3)
+#define SSP_IN_MODE		0
+#define SSP_DATA_REG		BIT(4)
+#define SSP_ADDR_REG		0
+
+#define SSP_OPCODE_DIRECT	((0x0) << 5)
+#define SSP_OPCODE_TOGGLE	((0x1) << 5)
+#define SSP_OPCODE_SHIFT	((0x2) << 5)
+#define SSP_OPCODE_BRANCH0	((0x4) << 5)
+#define SSP_OPCODE_BRANCH1	((0x5) << 5)
+#define SSP_OPCODE_BRANCH	((0x6) << 5)
+#define SSP_OPCODE_STOP		((0x7) << 5)
+#define SSP_BRANCH(addr)	((addr) << 8)
+#define SSP_COUNT(cycles)	((cycles) << 8)
+
+int ti_ssp_raw_read(struct device *dev);
+int ti_ssp_raw_write(struct device *dev, u32 val);
+int ti_ssp_load(struct device *dev, int offs, u32* prog, int len);
+int ti_ssp_run(struct device *dev, u32 pc, u32 input, u32 *output);
+int ti_ssp_set_mode(struct device *dev, int mode);
+int ti_ssp_set_iosel(struct device *dev, u32 iosel);
+
+#endif /* __TI_SSP_H__ */
diff --git a/include/linux/mfd/wm831x/pdata.h b/include/linux/mfd/wm831x/pdata.h
index fd322ac..173086d 100644
--- a/include/linux/mfd/wm831x/pdata.h
+++ b/include/linux/mfd/wm831x/pdata.h
@@ -80,7 +80,8 @@ struct wm831x_touch_pdata {
 	int isel;              /** Current for pen down (uA) */
 	int rpu;               /** Pen down sensitivity resistor divider */
 	int pressure;          /** Report pressure (boolean) */
-	int data_irq;          /** Touch data ready IRQ */
+	unsigned int data_irq; /** Touch data ready IRQ */
+	unsigned int pd_irq;   /** Touch pendown detect IRQ */
 };
 
 enum wm831x_watchdog_action {
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
index 9eab263..466b1c7 100644
--- a/include/linux/mfd/wm8994/pdata.h
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -103,13 +103,21 @@ struct wm8994_pdata {
         unsigned int lineout1fb:1;
         unsigned int lineout2fb:1;
 
-        /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
+	/* IRQ for microphone detection if brought out directly as a
+	 * signal.
+	 */
+	int micdet_irq;
+
+        /* WM8994 microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
         unsigned int micbias1_lvl:1;
         unsigned int micbias2_lvl:1;
 
-        /* Jack detect threashold levels, see datasheet for values */
+        /* WM8994 jack detect threashold levels, see datasheet for values */
         unsigned int jd_scthr:2;
         unsigned int jd_thr:2;
+
+	/* WM8958 microphone bias configuration */
+	int micbias[2];
 };
 
 #endif
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
index be072fa..f3ee842 100644
--- a/include/linux/mfd/wm8994/registers.h
+++ b/include/linux/mfd/wm8994/registers.h
@@ -63,6 +63,8 @@
 #define WM8994_MICBIAS                          0x3A
 #define WM8994_LDO_1                            0x3B
 #define WM8994_LDO_2                            0x3C
+#define WM8958_MICBIAS1				0x3D
+#define WM8958_MICBIAS2				0x3E
 #define WM8994_CHARGE_PUMP_1                    0x4C
 #define WM8958_CHARGE_PUMP_2                    0x4D
 #define WM8994_CLASS_W_1                        0x51
diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h
new file mode 100644
index 0000000..dd8da34
--- /dev/null
+++ b/include/linux/micrel_phy.h
@@ -0,0 +1,16 @@
+#ifndef _MICREL_PHY_H
+#define _MICREL_PHY_H
+
+#define MICREL_PHY_ID_MASK	0x00fffff0
+
+#define PHY_ID_KSZ9021		0x00221611
+#define PHY_ID_KS8737		0x00221720
+#define PHY_ID_KS8041		0x00221510
+#define PHY_ID_KS8051		0x00221550
+/* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
+#define PHY_ID_KS8001		0x0022161A
+
+/* struct phy_device dev_flags definitions */
+#define MICREL_PHY_50MHZ_CLK	0x00000001
+
+#endif /* _MICREL_PHY_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index f6385fc..294104e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -151,6 +151,7 @@ extern pgprot_t protection_map[16];
 #define FAULT_FLAG_NONLINEAR	0x02	/* Fault was via a nonlinear mapping */
 #define FAULT_FLAG_MKWRITE	0x04	/* Fault was mkwrite of existing pte */
 #define FAULT_FLAG_ALLOW_RETRY	0x08	/* Retry fault if blocking */
+#define FAULT_FLAG_RETRY_NOWAIT	0x10	/* Don't drop mmap_sem and wait when retrying */
 
 /*
  * This interface is used by x86 PAT code to identify a pfn mapping that is
@@ -402,16 +403,23 @@ static inline void init_page_count(struct page *page)
 /*
  * PageBuddy() indicate that the page is free and in the buddy system
  * (see mm/page_alloc.c).
+ *
+ * PAGE_BUDDY_MAPCOUNT_VALUE must be <= -2 but better not too close to
+ * -2 so that an underflow of the page_mapcount() won't be mistaken
+ * for a genuine PAGE_BUDDY_MAPCOUNT_VALUE. -128 can be created very
+ * efficiently by most CPU architectures.
  */
+#define PAGE_BUDDY_MAPCOUNT_VALUE (-128)
+
 static inline int PageBuddy(struct page *page)
 {
-	return atomic_read(&page->_mapcount) == -2;
+	return atomic_read(&page->_mapcount) == PAGE_BUDDY_MAPCOUNT_VALUE;
 }
 
 static inline void __SetPageBuddy(struct page *page)
 {
 	VM_BUG_ON(atomic_read(&page->_mapcount) != -1);
-	atomic_set(&page->_mapcount, -2);
+	atomic_set(&page->_mapcount, PAGE_BUDDY_MAPCOUNT_VALUE);
 }
 
 static inline void __ClearPageBuddy(struct page *page)
@@ -852,7 +860,14 @@ extern void pagefault_out_of_memory(void);
 
 #define offset_in_page(p)	((unsigned long)(p) & ~PAGE_MASK)
 
+/*
+ * Flags passed to __show_mem() and __show_free_areas() to suppress output in
+ * various contexts.
+ */
+#define SHOW_MEM_FILTER_NODES	(0x0001u)	/* filter disallowed nodes */
+
 extern void show_free_areas(void);
+extern void __show_free_areas(unsigned int flags);
 
 int shmem_lock(struct file *file, int lock, struct user_struct *user);
 struct file *shmem_file_setup(const char *name, loff_t size, unsigned long flags);
@@ -899,6 +914,9 @@ unsigned long unmap_vmas(struct mmu_gather **tlb,
  * @pgd_entry: if set, called for each non-empty PGD (top-level) entry
  * @pud_entry: if set, called for each non-empty PUD (2nd-level) entry
  * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry
+ *	       this handler is required to be able to handle
+ *	       pmd_trans_huge() pmds.  They may simply choose to
+ *	       split_huge_page() instead of handling it explicitly.
  * @pte_entry: if set, called for each non-empty PTE (4th-level) entry
  * @pte_hole: if set, called for each hole at all levels
  * @hugetlb_entry: if set, called for each hugetlb entry
@@ -965,6 +983,10 @@ static inline int handle_mm_fault(struct mm_struct *mm,
 extern int make_pages_present(unsigned long addr, unsigned long end);
 extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write);
 
+int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+		     unsigned long start, int len, unsigned int foll_flags,
+		     struct page **pages, struct vm_area_struct **vmas,
+		     int *nonblocking);
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 			unsigned long start, int nr_pages, int write, int force,
 			struct page **pages, struct vm_area_struct **vmas);
@@ -1309,8 +1331,6 @@ int add_from_early_node_map(struct range *range, int az,
 				   int nr_range, int nid);
 u64 __init find_memory_core_early(int nid, u64 size, u64 align,
 					u64 goal, u64 limit);
-void *__alloc_memory_core_early(int nodeid, u64 size, u64 align,
-				 u64 goal, u64 limit);
 typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
 extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
 extern void sparse_memory_present_with_active_regions(int nid);
@@ -1339,6 +1359,7 @@ extern void calculate_zone_inactive_ratio(struct zone *zone);
 extern void mem_init(void);
 extern void __init mmap_init(void);
 extern void show_mem(void);
+extern void __show_mem(unsigned int flags);
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
 extern int after_bootmem;
@@ -1528,8 +1549,11 @@ struct page *follow_page(struct vm_area_struct *, unsigned long address,
 #define FOLL_GET	0x04	/* do get_page on page */
 #define FOLL_DUMP	0x08	/* give error on hole if it would be zero */
 #define FOLL_FORCE	0x10	/* get_user_pages read/write w/o permission */
+#define FOLL_NOWAIT	0x20	/* if a disk transfer is needed, start the IO
+				 * and return without waiting upon it */
 #define FOLL_MLOCK	0x40	/* mark page as mlocked */
 #define FOLL_SPLIT	0x80	/* don't return transhuge pages, split them */
+#define FOLL_HWPOISON	0x100	/* check page is hwpoisoned */
 
 typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr,
 			void *data);
@@ -1622,14 +1646,6 @@ extern int sysctl_memory_failure_recovery;
 extern void shake_page(struct page *p, int access);
 extern atomic_long_t mce_bad_pages;
 extern int soft_offline_page(struct page *page, int flags);
-#ifdef CONFIG_MEMORY_FAILURE
-int is_hwpoison_address(unsigned long addr);
-#else
-static inline int is_hwpoison_address(unsigned long addr)
-{
-	return 0;
-}
-#endif
 
 extern void dump_page(struct page *page);
 
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 26bc4e2..02aa561 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -237,8 +237,9 @@ struct mm_struct {
 	atomic_t mm_users;			/* How many users with user space? */
 	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
 	int map_count;				/* number of VMAs */
-	struct rw_semaphore mmap_sem;
+
 	spinlock_t page_table_lock;		/* Protects page tables and some counters */
+	struct rw_semaphore mmap_sem;
 
 	struct list_head mmlist;		/* List of maybe swapped mm's.	These are globally strung
 						 * together off init_mm.mmlist, and are protected
@@ -281,6 +282,9 @@ struct mm_struct {
 	unsigned int token_priority;
 	unsigned int last_interval;
 
+	/* How many tasks sharing this mm are OOM_DISABLE */
+	atomic_t oom_disable_count;
+
 	unsigned long flags; /* Must use atomic bitops to access the bits */
 
 	struct core_state *core_state; /* coredumping support */
@@ -313,8 +317,6 @@ struct mm_struct {
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 	pgtable_t pmd_huge_pte; /* protected by page_table_lock */
 #endif
-	/* How many tasks sharing this mm are OOM_DISABLE */
-	atomic_t oom_disable_count;
 };
 
 /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 8ce0827..adb4888 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -54,6 +54,9 @@ struct mmc_ext_csd {
 	unsigned int		sec_trim_mult;	/* Secure trim multiplier  */
 	unsigned int		sec_erase_mult;	/* Secure erase multiplier */
 	unsigned int		trim_timeout;		/* In milliseconds */
+	bool			enhanced_area_en;	/* enable bit */
+	unsigned long long	enhanced_area_offset;	/* Units: Byte */
+	unsigned int		enhanced_area_size;	/* Units: KB */
 };
 
 struct sd_scr {
@@ -121,6 +124,7 @@ struct mmc_card {
 						/* for byte mode */
 #define MMC_QUIRK_NONSTD_SDIO	(1<<2)		/* non-standard SDIO card attached */
 						/* (missing CIA registers) */
+#define MMC_QUIRK_BROKEN_CLK_GATING (1<<3)	/* clock gating the sdio bus will make card fail */
 
 	unsigned int		erase_size;	/* erase size in sectors */
  	unsigned int		erase_shift;	/* if erase unit is power 2 */
@@ -148,6 +152,8 @@ struct mmc_card {
 	struct dentry		*debugfs_root;
 };
 
+void mmc_fixup_device(struct mmc_card *dev);
+
 #define mmc_card_mmc(c)		((c)->type == MMC_TYPE_MMC)
 #define mmc_card_sd(c)		((c)->type == MMC_TYPE_SD)
 #define mmc_card_sdio(c)	((c)->type == MMC_TYPE_SDIO)
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
index 64e013f..07f27af 100644
--- a/include/linux/mmc/core.h
+++ b/include/linux/mmc/core.h
@@ -160,6 +160,7 @@ extern unsigned int mmc_align_data_size(struct mmc_card *, unsigned int);
 
 extern int __mmc_claim_host(struct mmc_host *host, atomic_t *abort);
 extern void mmc_release_host(struct mmc_host *host);
+extern void mmc_do_release_host(struct mmc_host *host);
 extern int mmc_try_claim_host(struct mmc_host *host);
 
 /**
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 16b0261..c0207a7 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -140,6 +140,7 @@ struct dw_mci {
 	u32			bus_hz;
 	u32			current_speed;
 	u32			num_slots;
+	u32			fifoth_val;
 	struct platform_device	*pdev;
 	struct dw_mci_board	*pdata;
 	struct dw_mci_slot	*slot[MAX_MCI_SLOTS];
@@ -151,6 +152,8 @@ struct dw_mci {
 
 	/* Workaround flags */
 	u32			quirks;
+
+	struct regulator	*vmmc;	/* Power regulator */
 };
 
 /* DMA ops for Internal/External DMAC interface */
@@ -165,14 +168,14 @@ struct dw_mci_dma_ops {
 };
 
 /* IP Quirks/flags. */
-/* No special quirks or flags to cater for */
-#define DW_MCI_QUIRK_NONE		0
 /* DTO fix for command transmission with IDMAC configured */
-#define DW_MCI_QUIRK_IDMAC_DTO		1
+#define DW_MCI_QUIRK_IDMAC_DTO			BIT(0)
 /* delay needed between retries on some 2.11a implementations */
-#define DW_MCI_QUIRK_RETRY_DELAY	2
+#define DW_MCI_QUIRK_RETRY_DELAY		BIT(1)
 /* High Speed Capable - Supports HS cards (upto 50MHz) */
-#define DW_MCI_QUIRK_HIGHSPEED		4
+#define DW_MCI_QUIRK_HIGHSPEED			BIT(2)
+/* Unreliable card detection */
+#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION	BIT(3)
 
 
 struct dma_pdata;
@@ -192,6 +195,8 @@ struct dw_mci_board {
 	u32 quirks; /* Workaround / Quirk flags */
 	unsigned int bus_hz; /* Bus speed */
 
+	unsigned int caps;	/* Capabilities */
+
 	/* delay in mS before detecting cards after interrupt */
 	u32 detect_delay_ms;
 
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h
index 612301f..264ba54 100644
--- a/include/linux/mmc/mmc.h
+++ b/include/linux/mmc/mmc.h
@@ -253,6 +253,8 @@ struct _mmc_csd {
  * EXT_CSD fields
  */
 
+#define EXT_CSD_PARTITION_ATTRIBUTE	156	/* R/W */
+#define EXT_CSD_PARTITION_SUPPORT	160	/* RO */
 #define EXT_CSD_ERASE_GROUP_DEF		175	/* R/W */
 #define EXT_CSD_ERASED_MEM_CONT		181	/* RO */
 #define EXT_CSD_BUS_WIDTH		183	/* R/W */
@@ -262,6 +264,7 @@ struct _mmc_csd {
 #define EXT_CSD_CARD_TYPE		196	/* RO */
 #define EXT_CSD_SEC_CNT			212	/* RO, 4 bytes */
 #define EXT_CSD_S_A_TIMEOUT		217	/* RO */
+#define EXT_CSD_HC_WP_GRP_SIZE		221	/* RO */
 #define EXT_CSD_ERASE_TIMEOUT_MULT	223	/* RO */
 #define EXT_CSD_HC_ERASE_GRP_SIZE	224	/* RO */
 #define EXT_CSD_SEC_TRIM_MULT		229	/* RO */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 02ecb01..e56f835 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -472,7 +472,7 @@ static inline int zone_is_oom_locked(const struct zone *zone)
 #ifdef CONFIG_NUMA
 
 /*
- * The NUMA zonelists are doubled becausse we need zonelists that restrict the
+ * The NUMA zonelists are doubled because we need zonelists that restrict the
  * allocations to a single node for GFP_THISNODE.
  *
  * [0]	: Zonelist with fallback
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index d11fe0f..fe722c1 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -32,6 +32,7 @@ enum {
 	MDP_Y_CBCR_H2V1,	/* Y and CrCb, pseduo planar w/ Cr is in MSB */
 	MDP_RGBA_8888,		/* ARGB 888 */
 	MDP_BGRA_8888,		/* ABGR 888 */
+	MDP_RGBX_8888,		/* RGBX 888 */
 	MDP_IMGTYPE_LIMIT	/* Non valid image type after this enum */
 };
 
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index cd6f3b4..d60130f 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -168,6 +168,7 @@
 #define ONENAND_SYS_CFG1_INT		(1 << 6)
 #define ONENAND_SYS_CFG1_IOBE		(1 << 5)
 #define ONENAND_SYS_CFG1_RDY_CONF	(1 << 4)
+#define ONENAND_SYS_CFG1_VHF		(1 << 3)
 #define ONENAND_SYS_CFG1_HF		(1 << 2)
 #define ONENAND_SYS_CFG1_SYNC_WRITE	(1 << 1)
 
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index b31bd9e..84854ed 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -116,18 +116,40 @@ struct ubi_volume_info {
  * struct ubi_device_info - UBI device description data structure.
  * @ubi_num: ubi device number
  * @leb_size: logical eraseblock size on this UBI device
+ * @leb_start: starting offset of logical eraseblocks within physical
+ *             eraseblocks
  * @min_io_size: minimal I/O unit size
+ * @max_write_size: maximum amount of bytes the underlying flash can write at a
+ *                  time (MTD write buffer size)
  * @ro_mode: if this device is in read-only mode
  * @cdev: UBI character device major and minor numbers
  *
  * Note, @leb_size is the logical eraseblock size offered by the UBI device.
  * Volumes of this UBI device may have smaller logical eraseblock size if their
  * alignment is not equivalent to %1.
+ *
+ * The @max_write_size field describes flash write maximum write unit. For
+ * example, NOR flash allows for changing individual bytes, so @min_io_size is
+ * %1. However, it does not mean than NOR flash has to write data byte-by-byte.
+ * Instead, CFI NOR flashes have a write-buffer of, e.g., 64 bytes, and when
+ * writing large chunks of data, they write 64-bytes at a time. Obviously, this
+ * improves write throughput.
+ *
+ * Also, the MTD device may have N interleaved (striped) flash chips
+ * underneath, in which case @min_io_size can be physical min. I/O size of
+ * single flash chip, while @max_write_size can be N * @min_io_size.
+ *
+ * The @max_write_size field is always greater or equivalent to @min_io_size.
+ * E.g., some NOR flashes may have (@min_io_size = 1, @max_write_size = 64). In
+ * contrast, NAND flashes usually have @min_io_size = @max_write_size = NAND
+ * page size.
  */
 struct ubi_device_info {
 	int ubi_num;
 	int leb_size;
+	int leb_start;
 	int min_io_size;
+	int max_write_size;
 	int ro_mode;
 	dev_t cdev;
 };
diff --git a/include/linux/namei.h b/include/linux/namei.h
index f276d4f..eba45ea 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -19,7 +19,6 @@ struct nameidata {
 	struct path	path;
 	struct qstr	last;
 	struct path	root;
-	struct file	*file;
 	struct inode	*inode; /* path.dentry.d_inode */
 	unsigned int	flags;
 	unsigned	seq;
@@ -63,6 +62,10 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_EXCL		0x0400
 #define LOOKUP_RENAME_TARGET	0x0800
 
+#define LOOKUP_JUMPED		0x1000
+#define LOOKUP_ROOT		0x2000
+#define LOOKUP_EMPTY		0x4000
+
 extern int user_path_at(int, const char __user *, unsigned, struct path *);
 
 #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path)
@@ -72,7 +75,7 @@ extern int user_path_at(int, const char __user *, unsigned, struct path *);
 
 extern int kern_path(const char *, unsigned, struct path *);
 
-extern int path_lookup(const char *, unsigned, struct nameidata *);
+extern int kern_path_parent(const char *, struct nameidata *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
 			   const char *, unsigned int, struct nameidata *);
 
@@ -82,7 +85,7 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
 
 extern int follow_down_one(struct path *);
-extern int follow_down(struct path *, bool);
+extern int follow_down(struct path *);
 extern int follow_up(struct path *);
 
 extern struct dentry *lock_rename(struct dentry *, struct dentry *);
diff --git a/include/linux/net.h b/include/linux/net.h
index 16faa13..94de83c 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -118,6 +118,7 @@ enum sock_shutdown_cmd {
 };
 
 struct socket_wq {
+	/* Note: wait MUST be first field of socket_wq */
 	wait_queue_head_t	wait;
 	struct fasync_struct	*fasync_list;
 	struct rcu_head		rcu;
@@ -142,7 +143,7 @@ struct socket {
 
 	unsigned long		flags;
 
-	struct socket_wq	*wq;
+	struct socket_wq __rcu	*wq;
 
 	struct file		*file;
 	struct sock		*sk;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 71caf7a..5eeb2cd 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -138,6 +138,9 @@ static inline bool dev_xmit_complete(int rc)
 
 #define MAX_ADDR_LEN	32		/* Largest hardware address length */
 
+/* Initial net device group. All devices belong to group 0 by default. */
+#define INIT_NETDEV_GROUP	0
+
 #ifdef  __KERNEL__
 /*
  *	Compute the worst case header length according to the protocols
@@ -387,7 +390,55 @@ enum gro_result {
 };
 typedef enum gro_result gro_result_t;
 
-typedef struct sk_buff *rx_handler_func_t(struct sk_buff *skb);
+/*
+ * enum rx_handler_result - Possible return values for rx_handlers.
+ * @RX_HANDLER_CONSUMED: skb was consumed by rx_handler, do not process it
+ * further.
+ * @RX_HANDLER_ANOTHER: Do another round in receive path. This is indicated in
+ * case skb->dev was changed by rx_handler.
+ * @RX_HANDLER_EXACT: Force exact delivery, no wildcard.
+ * @RX_HANDLER_PASS: Do nothing, passe the skb as if no rx_handler was called.
+ *
+ * rx_handlers are functions called from inside __netif_receive_skb(), to do
+ * special processing of the skb, prior to delivery to protocol handlers.
+ *
+ * Currently, a net_device can only have a single rx_handler registered. Trying
+ * to register a second rx_handler will return -EBUSY.
+ *
+ * To register a rx_handler on a net_device, use netdev_rx_handler_register().
+ * To unregister a rx_handler on a net_device, use
+ * netdev_rx_handler_unregister().
+ *
+ * Upon return, rx_handler is expected to tell __netif_receive_skb() what to
+ * do with the skb.
+ *
+ * If the rx_handler consumed to skb in some way, it should return
+ * RX_HANDLER_CONSUMED. This is appropriate when the rx_handler arranged for
+ * the skb to be delivered in some other ways.
+ *
+ * If the rx_handler changed skb->dev, to divert the skb to another
+ * net_device, it should return RX_HANDLER_ANOTHER. The rx_handler for the
+ * new device will be called if it exists.
+ *
+ * If the rx_handler consider the skb should be ignored, it should return
+ * RX_HANDLER_EXACT. The skb will only be delivered to protocol handlers that
+ * are registred on exact device (ptype->dev == skb->dev).
+ *
+ * If the rx_handler didn't changed skb->dev, but want the skb to be normally
+ * delivered, it should return RX_HANDLER_PASS.
+ *
+ * A device without a registered rx_handler will behave as if rx_handler
+ * returned RX_HANDLER_PASS.
+ */
+
+enum rx_handler_result {
+	RX_HANDLER_CONSUMED,
+	RX_HANDLER_ANOTHER,
+	RX_HANDLER_EXACT,
+	RX_HANDLER_PASS,
+};
+typedef enum rx_handler_result rx_handler_result_t;
+typedef rx_handler_result_t rx_handler_func_t(struct sk_buff **pskb);
 
 extern void __napi_schedule(struct napi_struct *n);
 
@@ -551,14 +602,16 @@ struct rps_map {
 #define RPS_MAP_SIZE(_num) (sizeof(struct rps_map) + (_num * sizeof(u16)))
 
 /*
- * The rps_dev_flow structure contains the mapping of a flow to a CPU and the
- * tail pointer for that CPU's input queue at the time of last enqueue.
+ * The rps_dev_flow structure contains the mapping of a flow to a CPU, the
+ * tail pointer for that CPU's input queue at the time of last enqueue, and
+ * a hardware filter index.
  */
 struct rps_dev_flow {
 	u16 cpu;
-	u16 fill;
+	u16 filter;
 	unsigned int last_qtail;
 };
+#define RPS_NO_FILTER 0xffff
 
 /*
  * The rps_dev_flow_table structure contains a table of flow mappings.
@@ -608,6 +661,11 @@ static inline void rps_reset_sock_flow(struct rps_sock_flow_table *table,
 
 extern struct rps_sock_flow_table __rcu *rps_sock_flow_table;
 
+#ifdef CONFIG_RFS_ACCEL
+extern bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index,
+				u32 flow_id, u16 filter_id);
+#endif
+
 /* This structure contains an instance of an RX queue. */
 struct netdev_rx_queue {
 	struct rps_map __rcu		*rps_map;
@@ -643,6 +701,14 @@ struct xps_dev_maps {
     (nr_cpu_ids * sizeof(struct xps_map *)))
 #endif /* CONFIG_XPS */
 
+#define TC_MAX_QUEUE	16
+#define TC_BITMASK	15
+/* HW offloaded queuing disciplines txq count and offset maps */
+struct netdev_tc_txq {
+	u16 count;
+	u16 offset;
+};
+
 /*
  * This structure defines the management hooks for network devices.
  * The following hooks can be defined; unless noted otherwise, they are
@@ -753,6 +819,74 @@ struct xps_dev_maps {
  * int (*ndo_set_vf_port)(struct net_device *dev, int vf,
  *			  struct nlattr *port[]);
  * int (*ndo_get_vf_port)(struct net_device *dev, int vf, struct sk_buff *skb);
+ * int (*ndo_setup_tc)(struct net_device *dev, u8 tc)
+ * 	Called to setup 'tc' number of traffic classes in the net device. This
+ * 	is always called from the stack with the rtnl lock held and netif tx
+ * 	queues stopped. This allows the netdevice to perform queue management
+ * 	safely.
+ *
+ *	Fiber Channel over Ethernet (FCoE) offload functions.
+ * int (*ndo_fcoe_enable)(struct net_device *dev);
+ *	Called when the FCoE protocol stack wants to start using LLD for FCoE
+ *	so the underlying device can perform whatever needed configuration or
+ *	initialization to support acceleration of FCoE traffic.
+ *
+ * int (*ndo_fcoe_disable)(struct net_device *dev);
+ *	Called when the FCoE protocol stack wants to stop using LLD for FCoE
+ *	so the underlying device can perform whatever needed clean-ups to
+ *	stop supporting acceleration of FCoE traffic.
+ *
+ * int (*ndo_fcoe_ddp_setup)(struct net_device *dev, u16 xid,
+ *			     struct scatterlist *sgl, unsigned int sgc);
+ *	Called when the FCoE Initiator wants to initialize an I/O that
+ *	is a possible candidate for Direct Data Placement (DDP). The LLD can
+ *	perform necessary setup and returns 1 to indicate the device is set up
+ *	successfully to perform DDP on this I/O, otherwise this returns 0.
+ *
+ * int (*ndo_fcoe_ddp_done)(struct net_device *dev,  u16 xid);
+ *	Called when the FCoE Initiator/Target is done with the DDPed I/O as
+ *	indicated by the FC exchange id 'xid', so the underlying device can
+ *	clean up and reuse resources for later DDP requests.
+ *
+ * int (*ndo_fcoe_ddp_target)(struct net_device *dev, u16 xid,
+ *			      struct scatterlist *sgl, unsigned int sgc);
+ *	Called when the FCoE Target wants to initialize an I/O that
+ *	is a possible candidate for Direct Data Placement (DDP). The LLD can
+ *	perform necessary setup and returns 1 to indicate the device is set up
+ *	successfully to perform DDP on this I/O, otherwise this returns 0.
+ *
+ * int (*ndo_fcoe_get_wwn)(struct net_device *dev, u64 *wwn, int type);
+ *	Called when the underlying device wants to override default World Wide
+ *	Name (WWN) generation mechanism in FCoE protocol stack to pass its own
+ *	World Wide Port Name (WWPN) or World Wide Node Name (WWNN) to the FCoE
+ *	protocol stack to use.
+ *
+ *	RFS acceleration.
+ * int (*ndo_rx_flow_steer)(struct net_device *dev, const struct sk_buff *skb,
+ *			    u16 rxq_index, u32 flow_id);
+ *	Set hardware filter for RFS.  rxq_index is the target queue index;
+ *	flow_id is a flow ID to be passed to rps_may_expire_flow() later.
+ *	Return the filter ID on success, or a negative error code.
+ *
+ *	Slave management functions (for bridge, bonding, etc). User should
+ *	call netdev_set_master() to set dev->master properly.
+ * int (*ndo_add_slave)(struct net_device *dev, struct net_device *slave_dev);
+ *	Called to make another netdev an underling.
+ *
+ * int (*ndo_del_slave)(struct net_device *dev, struct net_device *slave_dev);
+ *	Called to release previously enslaved netdev.
+ *
+ *      Feature/offload setting functions.
+ * u32 (*ndo_fix_features)(struct net_device *dev, u32 features);
+ *	Adjusts the requested feature flags according to device-specific
+ *	constraints, and returns the resulting flags. Must not modify
+ *	the device state.
+ *
+ * int (*ndo_set_features)(struct net_device *dev, u32 features);
+ *	Called to update device configuration to new features. Passed
+ *	feature set might be less than what was returned by ndo_fix_features()).
+ *	Must return >0 or -errno if it changed dev->features itself.
+ *
  */
 #define HAVE_NET_DEVICE_OPS
 struct net_device_ops {
@@ -811,6 +945,7 @@ struct net_device_ops {
 						   struct nlattr *port[]);
 	int			(*ndo_get_vf_port)(struct net_device *dev,
 						   int vf, struct sk_buff *skb);
+	int			(*ndo_setup_tc)(struct net_device *dev, u8 tc);
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
 	int			(*ndo_fcoe_enable)(struct net_device *dev);
 	int			(*ndo_fcoe_disable)(struct net_device *dev);
@@ -820,11 +955,29 @@ struct net_device_ops {
 						      unsigned int sgc);
 	int			(*ndo_fcoe_ddp_done)(struct net_device *dev,
 						     u16 xid);
+	int			(*ndo_fcoe_ddp_target)(struct net_device *dev,
+						       u16 xid,
+						       struct scatterlist *sgl,
+						       unsigned int sgc);
 #define NETDEV_FCOE_WWNN 0
 #define NETDEV_FCOE_WWPN 1
 	int			(*ndo_fcoe_get_wwn)(struct net_device *dev,
 						    u64 *wwn, int type);
 #endif
+#ifdef CONFIG_RFS_ACCEL
+	int			(*ndo_rx_flow_steer)(struct net_device *dev,
+						     const struct sk_buff *skb,
+						     u16 rxq_index,
+						     u32 flow_id);
+#endif
+	int			(*ndo_add_slave)(struct net_device *dev,
+						 struct net_device *slave_dev);
+	int			(*ndo_del_slave)(struct net_device *dev,
+						 struct net_device *slave_dev);
+	u32			(*ndo_fix_features)(struct net_device *dev,
+						    u32 features);
+	int			(*ndo_set_features)(struct net_device *dev,
+						    u32 features);
 };
 
 /*
@@ -876,8 +1029,18 @@ struct net_device {
 	struct list_head	napi_list;
 	struct list_head	unreg_list;
 
-	/* Net device features */
-	unsigned long		features;
+	/* currently active device features */
+	u32			features;
+	/* user-changeable features */
+	u32			hw_features;
+	/* user-requested features */
+	u32			wanted_features;
+	/* VLAN feature mask */
+	u32			vlan_features;
+
+	/* Net device feature bits; if you change something,
+	 * also update netdev_features_strings[] in ethtool.c */
+
 #define NETIF_F_SG		1	/* Scatter/gather IO. */
 #define NETIF_F_IP_CSUM		2	/* Can checksum TCP/UDP over IPv4. */
 #define NETIF_F_NO_CSUM		4	/* Does not require checksum. F.e. loopack. */
@@ -902,6 +1065,7 @@ struct net_device {
 #define NETIF_F_FCOE_MTU	(1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
 #define NETIF_F_NTUPLE		(1 << 27) /* N-tuple filters supported */
 #define NETIF_F_RXHASH		(1 << 28) /* Receive hashing offload */
+#define NETIF_F_RXCSUM		(1 << 29) /* Receive checksumming offload */
 
 	/* Segmentation offload features */
 #define NETIF_F_GSO_SHIFT	16
@@ -913,6 +1077,12 @@ struct net_device {
 #define NETIF_F_TSO6		(SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT)
 #define NETIF_F_FSO		(SKB_GSO_FCOE << NETIF_F_GSO_SHIFT)
 
+	/* Features valid for ethtool to change */
+	/* = all defined minus driver/device-class-related */
+#define NETIF_F_NEVER_CHANGE	(NETIF_F_HIGHDMA | NETIF_F_VLAN_CHALLENGED | \
+				  NETIF_F_LLTX | NETIF_F_NETNS_LOCAL)
+#define NETIF_F_ETHTOOL_BITS	(0x3f3fffff & ~NETIF_F_NEVER_CHANGE)
+
 	/* List of features with software fallbacks. */
 #define NETIF_F_GSO_SOFTWARE	(NETIF_F_TSO | NETIF_F_TSO_ECN | \
 				 NETIF_F_TSO6 | NETIF_F_UFO)
@@ -923,6 +1093,12 @@ struct net_device {
 #define NETIF_F_V6_CSUM		(NETIF_F_GEN_CSUM | NETIF_F_IPV6_CSUM)
 #define NETIF_F_ALL_CSUM	(NETIF_F_V4_CSUM | NETIF_F_V6_CSUM)
 
+#define NETIF_F_ALL_TSO 	(NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
+
+#define NETIF_F_ALL_TX_OFFLOADS	(NETIF_F_ALL_CSUM | NETIF_F_SG | \
+				 NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
+				 NETIF_F_SCTP_CSUM | NETIF_F_FCOE_CRC)
+
 	/*
 	 * If one device supports one of these features, then enable them
 	 * for all in netdev_increment_features.
@@ -931,6 +1107,9 @@ struct net_device {
 				 NETIF_F_SG | NETIF_F_HIGHDMA |		\
 				 NETIF_F_FRAGLIST)
 
+	/* changeable features with no special hardware requirements */
+#define NETIF_F_SOFT_FEATURES	(NETIF_F_GSO | NETIF_F_GRO)
+
 	/* Interface index. Unique device identifier	*/
 	int			ifindex;
 	int			iflink;
@@ -1039,6 +1218,13 @@ 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;
@@ -1132,9 +1318,6 @@ struct net_device {
 	/* rtnetlink link ops */
 	const struct rtnl_link_ops *rtnl_link_ops;
 
-	/* VLAN feature mask */
-	unsigned long vlan_features;
-
 	/* for setting kernel sock attribute on TCP connection setup */
 #define GSO_MAX_SIZE		65536
 	unsigned int		gso_max_size;
@@ -1143,6 +1326,9 @@ struct net_device {
 	/* Data Center Bridging netlink ops */
 	const struct dcbnl_rtnl_ops *dcbnl_ops;
 #endif
+	u8 num_tc;
+	struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE];
+	u8 prio_tc_map[TC_BITMASK + 1];
 
 #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
 	/* max exchange id for FCoE LRO by ddp */
@@ -1153,12 +1339,66 @@ struct net_device {
 
 	/* phy device may attach itself for hardware timestamping */
 	struct phy_device *phydev;
+
+	/* group the device belongs to */
+	int group;
 };
 #define to_net_dev(d) container_of(d, struct net_device, dev)
 
 #define	NETDEV_ALIGN		32
 
 static inline
+int netdev_get_prio_tc_map(const struct net_device *dev, u32 prio)
+{
+	return dev->prio_tc_map[prio & TC_BITMASK];
+}
+
+static inline
+int netdev_set_prio_tc_map(struct net_device *dev, u8 prio, u8 tc)
+{
+	if (tc >= dev->num_tc)
+		return -EINVAL;
+
+	dev->prio_tc_map[prio & TC_BITMASK] = tc & TC_BITMASK;
+	return 0;
+}
+
+static inline
+void netdev_reset_tc(struct net_device *dev)
+{
+	dev->num_tc = 0;
+	memset(dev->tc_to_txq, 0, sizeof(dev->tc_to_txq));
+	memset(dev->prio_tc_map, 0, sizeof(dev->prio_tc_map));
+}
+
+static inline
+int netdev_set_tc_queue(struct net_device *dev, u8 tc, u16 count, u16 offset)
+{
+	if (tc >= dev->num_tc)
+		return -EINVAL;
+
+	dev->tc_to_txq[tc].count = count;
+	dev->tc_to_txq[tc].offset = offset;
+	return 0;
+}
+
+static inline
+int netdev_set_num_tc(struct net_device *dev, u8 num_tc)
+{
+	if (num_tc > TC_MAX_QUEUE)
+		return -EINVAL;
+
+	dev->num_tc = num_tc;
+	return 0;
+}
+
+static inline
+int netdev_get_num_tc(struct net_device *dev)
+{
+	return dev->num_tc;
+}
+
+static inline
 struct netdev_queue *netdev_get_tx_queue(const struct net_device *dev,
 					 unsigned int index)
 {
@@ -1300,7 +1540,7 @@ struct packet_type {
 					 struct packet_type *,
 					 struct net_device *);
 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
-						int features);
+						u32 features);
 	int			(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff		**(*gro_receive)(struct sk_buff **head,
 					       struct sk_buff *skb);
@@ -1345,7 +1585,7 @@ static inline struct net_device *next_net_device_rcu(struct net_device *dev)
 	struct net *net;
 
 	net = dev_net(dev);
-	lh = rcu_dereference(dev->dev_list.next);
+	lh = rcu_dereference(list_next_rcu(&dev->dev_list));
 	return lh == &net->dev_base_head ? NULL : net_device_entry(lh);
 }
 
@@ -1355,6 +1595,13 @@ static inline struct net_device *first_net_device(struct net *net)
 		net_device_entry(net->dev_base_head.next);
 }
 
+static inline struct net_device *first_net_device_rcu(struct net *net)
+{
+	struct list_head *lh = rcu_dereference(list_next_rcu(&net->dev_base_head));
+
+	return lh == &net->dev_base_head ? NULL : net_device_entry(lh);
+}
+
 extern int 			netdev_boot_setup_check(struct net_device *dev);
 extern unsigned long		netdev_boot_base(const char *prefix, int unit);
 extern struct net_device *dev_getbyhwaddr_rcu(struct net *net, unsigned short type,
@@ -1606,8 +1853,7 @@ static inline void netif_tx_wake_all_queues(struct net_device *dev)
 static inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
 {
 	if (WARN_ON(!dev_queue)) {
-		printk(KERN_INFO "netif_stop_queue() cannot be called before "
-		       "register_netdev()");
+		pr_info("netif_stop_queue() cannot be called before register_netdev()\n");
 		return;
 	}
 	set_bit(__QUEUE_STATE_XOFF, &dev_queue->state);
@@ -1844,6 +2090,7 @@ extern int		dev_set_alias(struct net_device *, const char *, size_t);
 extern int		dev_change_net_namespace(struct net_device *,
 						 struct net *, const char *);
 extern int		dev_set_mtu(struct net_device *, int);
+extern void		dev_set_group(struct net_device *, int);
 extern int		dev_set_mac_address(struct net_device *,
 					    struct sockaddr *);
 extern int		dev_hard_start_xmit(struct sk_buff *skb,
@@ -2267,8 +2514,10 @@ extern int		netdev_max_backlog;
 extern int		netdev_tstamp_prequeue;
 extern int		weight_p;
 extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
+extern int netdev_set_bond_master(struct net_device *dev,
+				  struct net_device *master);
 extern int skb_checksum_help(struct sk_buff *skb);
-extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, u32 features);
 #ifdef CONFIG_BUG
 extern void netdev_rx_csum_fault(struct net_device *dev);
 #else
@@ -2295,22 +2544,26 @@ extern char *netdev_drivername(const struct net_device *dev, char *buffer, int l
 
 extern void linkwatch_run_queue(void);
 
-unsigned long netdev_increment_features(unsigned long all, unsigned long one,
-					unsigned long mask);
-unsigned long netdev_fix_features(unsigned long features, const char *name);
+static inline u32 netdev_get_wanted_features(struct net_device *dev)
+{
+	return (dev->features & ~dev->hw_features) | dev->wanted_features;
+}
+u32 netdev_increment_features(u32 all, u32 one, u32 mask);
+u32 netdev_fix_features(struct net_device *dev, u32 features);
+void netdev_update_features(struct net_device *dev);
 
 void netif_stacked_transfer_operstate(const struct net_device *rootdev,
 					struct net_device *dev);
 
-int netif_skb_features(struct sk_buff *skb);
+u32 netif_skb_features(struct sk_buff *skb);
 
-static inline int net_gso_ok(int features, int gso_type)
+static inline int net_gso_ok(u32 features, int gso_type)
 {
 	int feature = gso_type << NETIF_F_GSO_SHIFT;
 	return (features & feature) == feature;
 }
 
-static inline int skb_gso_ok(struct sk_buff *skb, int features)
+static inline int skb_gso_ok(struct sk_buff *skb, u32 features)
 {
 	return net_gso_ok(features, skb_shinfo(skb)->gso_type) &&
 	       (!skb_has_frag_list(skb) || (features & NETIF_F_FRAGLIST));
@@ -2328,15 +2581,9 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
 	dev->gso_max_size = size;
 }
 
-extern int __skb_bond_should_drop(struct sk_buff *skb,
-				  struct net_device *master);
-
-static inline int skb_bond_should_drop(struct sk_buff *skb,
-				       struct net_device *master)
+static inline int netif_is_bond_slave(struct net_device *dev)
 {
-	if (master)
-		return __skb_bond_should_drop(skb, master);
-	return 0;
+	return dev->flags & IFF_SLAVE && dev->priv_flags & IFF_BONDING;
 }
 
 extern struct pernet_operations __net_initdata loopback_net_ops;
@@ -2351,6 +2598,8 @@ static inline int dev_ethtool_get_settings(struct net_device *dev,
 
 static inline u32 dev_ethtool_get_rx_csum(struct net_device *dev)
 {
+	if (dev->hw_features & NETIF_F_RXCSUM)
+		return !!(dev->features & NETIF_F_RXCSUM);
 	if (!dev->ethtool_ops || !dev->ethtool_ops->get_rx_csum)
 		return 0;
 	return dev->ethtool_ops->get_rx_csum(dev);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 1893837..eeec00a 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -24,16 +24,20 @@
 #define NF_MAX_VERDICT NF_STOP
 
 /* we overload the higher bits for encoding auxiliary data such as the queue
- * number. Not nice, but better than additional function arguments. */
-#define NF_VERDICT_MASK 0x0000ffff
-#define NF_VERDICT_BITS 16
+ * number or errno values. Not nice, but better than additional function
+ * arguments. */
+#define NF_VERDICT_MASK 0x000000ff
+
+/* extra verdict flags have mask 0x0000ff00 */
+#define NF_VERDICT_FLAG_QUEUE_BYPASS	0x00008000
 
+/* queue number (NF_QUEUE) or errno (NF_DROP) */
 #define NF_VERDICT_QMASK 0xffff0000
 #define NF_VERDICT_QBITS 16
 
-#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE)
+#define NF_QUEUE_NR(x) ((((x) << 16) & NF_VERDICT_QMASK) | NF_QUEUE)
 
-#define NF_DROP_ERR(x) (((-x) << NF_VERDICT_BITS) | NF_DROP)
+#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP)
 
 /* only for userspace compatibility */
 #ifndef __KERNEL__
@@ -41,6 +45,9 @@
    <= 0x2000 is used for protocol-flags. */
 #define NFC_UNKNOWN 0x4000
 #define NFC_ALTERED 0x8000
+
+/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */
+#define NF_VERDICT_BITS 16
 #endif
 
 enum nf_inet_hooks {
@@ -72,6 +79,10 @@ union nf_inet_addr {
 
 #ifdef __KERNEL__
 #ifdef CONFIG_NETFILTER
+static inline int NF_DROP_GETERR(int verdict)
+{
+	return -(verdict >> NF_VERDICT_QBITS);
+}
 
 static inline int nf_inet_addr_cmp(const union nf_inet_addr *a1,
 				   const union nf_inet_addr *a2)
@@ -267,7 +278,7 @@ struct nf_afinfo {
 	int		route_key_size;
 };
 
-extern const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO];
+extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO];
 static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)
 {
 	return rcu_dereference(nf_afinfo[family]);
@@ -357,9 +368,9 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
 #endif /*CONFIG_NETFILTER*/
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
-extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
+extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu;
 extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
-extern void (*nf_ct_destroy)(struct nf_conntrack *);
+extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu;
 #else
 static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
 #endif
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index 9d40eff..a1b410c 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -1,3 +1,5 @@
+header-y += ipset/
+
 header-y += nf_conntrack_common.h
 header-y += nf_conntrack_ftp.h
 header-y += nf_conntrack_sctp.h
@@ -9,6 +11,7 @@ header-y += nfnetlink_conntrack.h
 header-y += nfnetlink_log.h
 header-y += nfnetlink_queue.h
 header-y += x_tables.h
+header-y += xt_AUDIT.h
 header-y += xt_CHECKSUM.h
 header-y += xt_CLASSIFY.h
 header-y += xt_CONNMARK.h
@@ -26,6 +29,7 @@ header-y += xt_TCPMSS.h
 header-y += xt_TCPOPTSTRIP.h
 header-y += xt_TEE.h
 header-y += xt_TPROXY.h
+header-y += xt_addrtype.h
 header-y += xt_cluster.h
 header-y += xt_comment.h
 header-y += xt_connbytes.h
@@ -34,6 +38,7 @@ header-y += xt_connmark.h
 header-y += xt_conntrack.h
 header-y += xt_cpu.h
 header-y += xt_dccp.h
+header-y += xt_devgroup.h
 header-y += xt_dscp.h
 header-y += xt_esp.h
 header-y += xt_hashlimit.h
@@ -54,7 +59,9 @@ header-y += xt_quota.h
 header-y += xt_rateest.h
 header-y += xt_realm.h
 header-y += xt_recent.h
+header-y += xt_set.h
 header-y += xt_sctp.h
+header-y += xt_socket.h
 header-y += xt_state.h
 header-y += xt_statistic.h
 header-y += xt_string.h
diff --git a/include/linux/netfilter/ipset/Kbuild b/include/linux/netfilter/ipset/Kbuild
new file mode 100644
index 0000000..601fe71
--- /dev/null
+++ b/include/linux/netfilter/ipset/Kbuild
@@ -0,0 +1,4 @@
+header-y += ip_set.h
+header-y += ip_set_bitmap.h
+header-y += ip_set_hash.h
+header-y += ip_set_list.h
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
new file mode 100644
index 0000000..ec333d8
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -0,0 +1,452 @@
+#ifndef _IP_SET_H
+#define _IP_SET_H
+
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ *                         Patrick Schaaf <bof@bof.de>
+ *                         Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* The protocol version */
+#define IPSET_PROTOCOL		6
+
+/* The max length of strings including NUL: set and type identifiers */
+#define IPSET_MAXNAMELEN	32
+
+/* Message types and commands */
+enum ipset_cmd {
+	IPSET_CMD_NONE,
+	IPSET_CMD_PROTOCOL,	/* 1: Return protocol version */
+	IPSET_CMD_CREATE,	/* 2: Create a new (empty) set */
+	IPSET_CMD_DESTROY,	/* 3: Destroy a (empty) set */
+	IPSET_CMD_FLUSH,	/* 4: Remove all elements from a set */
+	IPSET_CMD_RENAME,	/* 5: Rename a set */
+	IPSET_CMD_SWAP,		/* 6: Swap two sets */
+	IPSET_CMD_LIST,		/* 7: List sets */
+	IPSET_CMD_SAVE,		/* 8: Save sets */
+	IPSET_CMD_ADD,		/* 9: Add an element to a set */
+	IPSET_CMD_DEL,		/* 10: Delete an element from a set */
+	IPSET_CMD_TEST,		/* 11: Test an element in a set */
+	IPSET_CMD_HEADER,	/* 12: Get set header data only */
+	IPSET_CMD_TYPE,		/* 13: Get set type */
+	IPSET_MSG_MAX,		/* Netlink message commands */
+
+	/* Commands in userspace: */
+	IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
+	IPSET_CMD_HELP,		/* 15: Get help */
+	IPSET_CMD_VERSION,	/* 16: Get program version */
+	IPSET_CMD_QUIT,		/* 17: Quit from interactive mode */
+
+	IPSET_CMD_MAX,
+
+	IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
+};
+
+/* Attributes at command level */
+enum {
+	IPSET_ATTR_UNSPEC,
+	IPSET_ATTR_PROTOCOL,	/* 1: Protocol version */
+	IPSET_ATTR_SETNAME,	/* 2: Name of the set */
+	IPSET_ATTR_TYPENAME,	/* 3: Typename */
+	IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
+	IPSET_ATTR_REVISION,	/* 4: Settype revision */
+	IPSET_ATTR_FAMILY,	/* 5: Settype family */
+	IPSET_ATTR_FLAGS,	/* 6: Flags at command level */
+	IPSET_ATTR_DATA,	/* 7: Nested attributes */
+	IPSET_ATTR_ADT,		/* 8: Multiple data containers */
+	IPSET_ATTR_LINENO,	/* 9: Restore lineno */
+	IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
+	IPSET_ATTR_REVISION_MIN	= IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
+	__IPSET_ATTR_CMD_MAX,
+};
+#define IPSET_ATTR_CMD_MAX	(__IPSET_ATTR_CMD_MAX - 1)
+
+/* CADT specific attributes */
+enum {
+	IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
+	IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
+	IPSET_ATTR_IP_TO,	/* 2 */
+	IPSET_ATTR_CIDR,	/* 3 */
+	IPSET_ATTR_PORT,	/* 4 */
+	IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
+	IPSET_ATTR_PORT_TO,	/* 5 */
+	IPSET_ATTR_TIMEOUT,	/* 6 */
+	IPSET_ATTR_PROTO,	/* 7 */
+	IPSET_ATTR_CADT_FLAGS,	/* 8 */
+	IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO,	/* 9 */
+	/* Reserve empty slots */
+	IPSET_ATTR_CADT_MAX = 16,
+	/* Create-only specific attributes */
+	IPSET_ATTR_GC,
+	IPSET_ATTR_HASHSIZE,
+	IPSET_ATTR_MAXELEM,
+	IPSET_ATTR_NETMASK,
+	IPSET_ATTR_PROBES,
+	IPSET_ATTR_RESIZE,
+	IPSET_ATTR_SIZE,
+	/* Kernel-only */
+	IPSET_ATTR_ELEMENTS,
+	IPSET_ATTR_REFERENCES,
+	IPSET_ATTR_MEMSIZE,
+
+	__IPSET_ATTR_CREATE_MAX,
+};
+#define IPSET_ATTR_CREATE_MAX	(__IPSET_ATTR_CREATE_MAX - 1)
+
+/* ADT specific attributes */
+enum {
+	IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
+	IPSET_ATTR_NAME,
+	IPSET_ATTR_NAMEREF,
+	IPSET_ATTR_IP2,
+	IPSET_ATTR_CIDR2,
+	__IPSET_ATTR_ADT_MAX,
+};
+#define IPSET_ATTR_ADT_MAX	(__IPSET_ATTR_ADT_MAX - 1)
+
+/* IP specific attributes */
+enum {
+	IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
+	IPSET_ATTR_IPADDR_IPV6,
+	__IPSET_ATTR_IPADDR_MAX,
+};
+#define IPSET_ATTR_IPADDR_MAX	(__IPSET_ATTR_IPADDR_MAX - 1)
+
+/* Error codes */
+enum ipset_errno {
+	IPSET_ERR_PRIVATE = 4096,
+	IPSET_ERR_PROTOCOL,
+	IPSET_ERR_FIND_TYPE,
+	IPSET_ERR_MAX_SETS,
+	IPSET_ERR_BUSY,
+	IPSET_ERR_EXIST_SETNAME2,
+	IPSET_ERR_TYPE_MISMATCH,
+	IPSET_ERR_EXIST,
+	IPSET_ERR_INVALID_CIDR,
+	IPSET_ERR_INVALID_NETMASK,
+	IPSET_ERR_INVALID_FAMILY,
+	IPSET_ERR_TIMEOUT,
+	IPSET_ERR_REFERENCED,
+	IPSET_ERR_IPADDR_IPV4,
+	IPSET_ERR_IPADDR_IPV6,
+
+	/* Type specific error codes */
+	IPSET_ERR_TYPE_SPECIFIC = 4352,
+};
+
+/* Flags at command level */
+enum ipset_cmd_flags {
+	IPSET_FLAG_BIT_EXIST	= 0,
+	IPSET_FLAG_EXIST	= (1 << IPSET_FLAG_BIT_EXIST),
+};
+
+/* Flags at CADT attribute level */
+enum ipset_cadt_flags {
+	IPSET_FLAG_BIT_BEFORE	= 0,
+	IPSET_FLAG_BEFORE	= (1 << IPSET_FLAG_BIT_BEFORE),
+};
+
+/* Commands with settype-specific attributes */
+enum ipset_adt {
+	IPSET_ADD,
+	IPSET_DEL,
+	IPSET_TEST,
+	IPSET_ADT_MAX,
+	IPSET_CREATE = IPSET_ADT_MAX,
+	IPSET_CADT_MAX,
+};
+
+#ifdef __KERNEL__
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/vmalloc.h>
+#include <net/netlink.h>
+
+/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
+ * and IPSET_INVALID_ID if you want to increase the max number of sets.
+ */
+typedef u16 ip_set_id_t;
+
+#define IPSET_INVALID_ID		65535
+
+enum ip_set_dim {
+	IPSET_DIM_ZERO = 0,
+	IPSET_DIM_ONE,
+	IPSET_DIM_TWO,
+	IPSET_DIM_THREE,
+	/* Max dimension in elements.
+	 * If changed, new revision of iptables match/target is required.
+	 */
+	IPSET_DIM_MAX = 6,
+};
+
+/* Option flags for kernel operations */
+enum ip_set_kopt {
+	IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
+	IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
+	IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
+	IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
+};
+
+/* Set features */
+enum ip_set_feature {
+	IPSET_TYPE_IP_FLAG = 0,
+	IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),
+	IPSET_TYPE_PORT_FLAG = 1,
+	IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),
+	IPSET_TYPE_MAC_FLAG = 2,
+	IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),
+	IPSET_TYPE_IP2_FLAG = 3,
+	IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
+	IPSET_TYPE_NAME_FLAG = 4,
+	IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
+	/* Strictly speaking not a feature, but a flag for dumping:
+	 * this settype must be dumped last */
+	IPSET_DUMP_LAST_FLAG = 7,
+	IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
+};
+
+struct ip_set;
+
+typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
+
+/* Set type, variant-specific part */
+struct ip_set_type_variant {
+	/* Kernelspace: test/add/del entries
+	 *		returns negative error code,
+	 *			zero for no match/success to add/delete
+	 *			positive for matching element */
+	int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
+		    enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
+
+	/* Userspace: test/add/del entries
+	 *		returns negative error code,
+	 *			zero for no match/success to add/delete
+	 *			positive for matching element */
+	int (*uadt)(struct ip_set *set, struct nlattr *tb[],
+		    enum ipset_adt adt, u32 *lineno, u32 flags);
+
+	/* Low level add/del/test functions */
+	ipset_adtfn adt[IPSET_ADT_MAX];
+
+	/* When adding entries and set is full, try to resize the set */
+	int (*resize)(struct ip_set *set, bool retried);
+	/* Destroy the set */
+	void (*destroy)(struct ip_set *set);
+	/* Flush the elements */
+	void (*flush)(struct ip_set *set);
+	/* Expire entries before listing */
+	void (*expire)(struct ip_set *set);
+	/* List set header data */
+	int (*head)(struct ip_set *set, struct sk_buff *skb);
+	/* List elements */
+	int (*list)(const struct ip_set *set, struct sk_buff *skb,
+		    struct netlink_callback *cb);
+
+	/* Return true if "b" set is the same as "a"
+	 * according to the create set parameters */
+	bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
+};
+
+/* The core set type structure */
+struct ip_set_type {
+	struct list_head list;
+
+	/* Typename */
+	char name[IPSET_MAXNAMELEN];
+	/* Protocol version */
+	u8 protocol;
+	/* Set features to control swapping */
+	u8 features;
+	/* Set type dimension */
+	u8 dimension;
+	/* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
+	u8 family;
+	/* Type revision */
+	u8 revision;
+
+	/* Create set */
+	int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags);
+
+	/* Attribute policies */
+	const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1];
+	const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1];
+
+	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
+	struct module *me;
+};
+
+/* register and unregister set type */
+extern int ip_set_type_register(struct ip_set_type *set_type);
+extern void ip_set_type_unregister(struct ip_set_type *set_type);
+
+/* A generic IP set */
+struct ip_set {
+	/* The name of the set */
+	char name[IPSET_MAXNAMELEN];
+	/* Lock protecting the set data */
+	rwlock_t lock;
+	/* References to the set */
+	atomic_t ref;
+	/* The core set type */
+	struct ip_set_type *type;
+	/* The type variant doing the real job */
+	const struct ip_set_type_variant *variant;
+	/* The actual INET family of the set */
+	u8 family;
+	/* The type specific data */
+	void *data;
+};
+
+/* register and unregister set references */
+extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
+extern void ip_set_put_byindex(ip_set_id_t index);
+extern const char * ip_set_name_byindex(ip_set_id_t index);
+extern ip_set_id_t ip_set_nfnl_get(const char *name);
+extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
+extern void ip_set_nfnl_put(ip_set_id_t index);
+
+/* API for iptables set match, and SET target */
+extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
+		      u8 family, u8 dim, u8 flags);
+extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
+		      u8 family, u8 dim, u8 flags);
+extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
+		       u8 family, u8 dim, u8 flags);
+
+/* Utility functions */
+extern void * ip_set_alloc(size_t size);
+extern void ip_set_free(void *members);
+extern int ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr);
+extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
+
+static inline int
+ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
+{
+	__be32 ip;
+	int ret = ip_set_get_ipaddr4(nla, &ip);
+	
+	if (ret)
+		return ret;
+	*ipaddr = ntohl(ip);
+	return 0;
+}
+
+/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
+static inline bool
+ip_set_eexist(int ret, u32 flags)
+{
+	return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
+}
+
+/* Check the NLA_F_NET_BYTEORDER flag */
+static inline bool
+ip_set_attr_netorder(struct nlattr *tb[], int type)
+{
+	return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
+}
+
+static inline bool
+ip_set_optattr_netorder(struct nlattr *tb[], int type)
+{
+	return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
+}
+
+/* Useful converters */
+static inline u32
+ip_set_get_h32(const struct nlattr *attr)
+{
+	return ntohl(nla_get_be32(attr));
+}
+
+static inline u16
+ip_set_get_h16(const struct nlattr *attr)
+{
+	return ntohs(nla_get_be16(attr));
+}
+
+#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
+#define ipset_nest_end(skb, start)  nla_nest_end(skb, start)
+
+#define NLA_PUT_IPADDR4(skb, type, ipaddr)			\
+do {								\
+	struct nlattr *__nested = ipset_nest_start(skb, type);	\
+								\
+	if (!__nested)						\
+		goto nla_put_failure;				\
+	NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr);	\
+	ipset_nest_end(skb, __nested);				\
+} while (0)
+
+#define NLA_PUT_IPADDR6(skb, type, ipaddrptr)			\
+do {								\
+	struct nlattr *__nested = ipset_nest_start(skb, type);	\
+								\
+	if (!__nested)						\
+		goto nla_put_failure;				\
+	NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6,			\
+		sizeof(struct in6_addr), ipaddrptr);		\
+	ipset_nest_end(skb, __nested);				\
+} while (0)
+
+/* Get address from skbuff */
+static inline __be32
+ip4addr(const struct sk_buff *skb, bool src)
+{
+	return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
+}
+
+static inline void
+ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
+{
+	*addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
+}
+
+static inline void
+ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
+{
+	memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,
+	       sizeof(*addr));
+}
+
+/* Calculate the bytes required to store the inclusive range of a-b */
+static inline int
+bitmap_bytes(u32 a, u32 b)
+{
+	return 4 * ((((b - a + 8) / 8) + 3) / 4);
+}
+
+/* Interface to iptables/ip6tables */
+
+#define SO_IP_SET		83
+
+union ip_set_name_index {
+	char name[IPSET_MAXNAMELEN];
+	ip_set_id_t index;
+};
+
+#define IP_SET_OP_GET_BYNAME	0x00000006	/* Get set index by name */
+struct ip_set_req_get_set {
+	unsigned op;
+	unsigned version;
+	union ip_set_name_index set;
+};
+
+#define IP_SET_OP_GET_BYINDEX	0x00000007	/* Get set name by index */
+/* Uses ip_set_req_get_set */
+
+#define IP_SET_OP_VERSION	0x00000100	/* Ask kernel version */
+struct ip_set_req_version {
+	unsigned op;
+	unsigned version;
+};
+
+#endif	/* __KERNEL__ */
+
+#endif /*_IP_SET_H */
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
new file mode 100644
index 0000000..ec9d9be
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -0,0 +1,1074 @@
+#ifndef _IP_SET_AHASH_H
+#define _IP_SET_AHASH_H
+
+#include <linux/rcupdate.h>
+#include <linux/jhash.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+
+/* Hashing which uses arrays to resolve clashing. The hash table is resized
+ * (doubled) when searching becomes too long.
+ * Internally jhash is used with the assumption that the size of the
+ * stored data is a multiple of sizeof(u32). If storage supports timeout,
+ * the timeout field must be the last one in the data structure - that field
+ * is ignored when computing the hash key.
+ *
+ * Readers and resizing
+ *
+ * Resizing can be triggered by userspace command only, and those
+ * are serialized by the nfnl mutex. During resizing the set is
+ * read-locked, so the only possible concurrent operations are
+ * the kernel side readers. Those must be protected by proper RCU locking.
+ */
+
+/* Number of elements to store in an initial array block */
+#define AHASH_INIT_SIZE			4
+/* Max number of elements to store in an array block */
+#define AHASH_MAX_SIZE			(3*4)
+
+/* A hash bucket */
+struct hbucket {
+	void *value;		/* the array of the values */
+	u8 size;		/* size of the array */
+	u8 pos;			/* position of the first free entry */
+};
+
+/* The hash table: the table size stored here in order to make resizing easy */
+struct htable {
+	u8 htable_bits;		/* size of hash table == 2^htable_bits */
+	struct hbucket bucket[0]; /* hashtable buckets */
+};
+
+#define hbucket(h, i)		&((h)->bucket[i])
+
+/* Book-keeping of the prefixes added to the set */
+struct ip_set_hash_nets {
+	u8 cidr;		/* the different cidr values in the set */
+	u32 nets;		/* number of elements per cidr */
+};
+
+/* The generic ip_set hash structure */
+struct ip_set_hash {
+	struct htable *table;	/* the hash table */
+	u32 maxelem;		/* max elements in the hash */
+	u32 elements;		/* current element (vs timeout) */
+	u32 initval;		/* random jhash init value */
+	u32 timeout;		/* timeout value, if enabled */
+	struct timer_list gc;	/* garbage collection when timeout enabled */
+#ifdef IP_SET_HASH_WITH_NETMASK
+	u8 netmask;		/* netmask value for subnets to store */
+#endif
+#ifdef IP_SET_HASH_WITH_NETS
+	struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */
+#endif
+};
+
+/* Compute htable_bits from the user input parameter hashsize */
+static u8
+htable_bits(u32 hashsize)
+{
+	/* Assume that hashsize == 2^htable_bits */
+	u8 bits = fls(hashsize - 1);
+	if (jhash_size(bits) != hashsize)
+		/* Round up to the first 2^n value */
+		bits = fls(hashsize);
+
+	return bits;
+}
+
+#ifdef IP_SET_HASH_WITH_NETS
+
+#define SET_HOST_MASK(family)	(family == AF_INET ? 32 : 128)
+
+/* Network cidr size book keeping when the hash stores different
+ * sized networks */
+static void
+add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
+{
+	u8 i;
+
+	++h->nets[cidr-1].nets;
+
+	pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);
+
+	if (h->nets[cidr-1].nets > 1)
+		return;
+
+	/* New cidr size */
+	for (i = 0; i < host_mask && h->nets[i].cidr; i++) {
+		/* Add in increasing prefix order, so larger cidr first */
+		if (h->nets[i].cidr < cidr)
+			swap(h->nets[i].cidr, cidr);
+	}
+	if (i < host_mask)
+		h->nets[i].cidr = cidr;
+}
+
+static void
+del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
+{
+	u8 i;
+
+	--h->nets[cidr-1].nets;
+
+	pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
+
+	if (h->nets[cidr-1].nets != 0)
+		return;
+
+	/* All entries with this cidr size deleted, so cleanup h->cidr[] */
+	for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) {
+		if (h->nets[i].cidr == cidr)
+			h->nets[i].cidr = cidr = h->nets[i+1].cidr;
+	}
+	h->nets[i - 1].cidr = 0;
+}
+#endif
+
+/* Destroy the hashtable part of the set */
+static void
+ahash_destroy(struct htable *t)
+{
+	struct hbucket *n;
+	u32 i;
+
+	for (i = 0; i < jhash_size(t->htable_bits); i++) {
+		n = hbucket(t, i);
+		if (n->size)
+			/* FIXME: use slab cache */
+			kfree(n->value);
+	}
+
+	ip_set_free(t);
+}
+
+/* Calculate the actual memory size of the set data */
+static size_t
+ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)
+{
+	u32 i;
+	struct htable *t = h->table;
+	size_t memsize = sizeof(*h)
+			 + sizeof(*t)
+#ifdef IP_SET_HASH_WITH_NETS
+			 + sizeof(struct ip_set_hash_nets) * host_mask
+#endif
+			 + jhash_size(t->htable_bits) * sizeof(struct hbucket);
+
+	for (i = 0; i < jhash_size(t->htable_bits); i++)
+			memsize += t->bucket[i].size * dsize;
+
+	return memsize;
+}
+
+/* Flush a hash type of set: destroy all elements */
+static void
+ip_set_hash_flush(struct ip_set *set)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	struct hbucket *n;
+	u32 i;
+
+	for (i = 0; i < jhash_size(t->htable_bits); i++) {
+		n = hbucket(t, i);
+		if (n->size) {
+			n->size = n->pos = 0;
+			/* FIXME: use slab cache */
+			kfree(n->value);
+		}
+	}
+#ifdef IP_SET_HASH_WITH_NETS
+	memset(h->nets, 0, sizeof(struct ip_set_hash_nets)
+			   * SET_HOST_MASK(set->family));
+#endif
+	h->elements = 0;
+}
+
+/* Destroy a hash type of set */
+static void
+ip_set_hash_destroy(struct ip_set *set)
+{
+	struct ip_set_hash *h = set->data;
+
+	if (with_timeout(h->timeout))
+		del_timer_sync(&h->gc);
+
+	ahash_destroy(h->table);
+	kfree(h);
+
+	set->data = NULL;
+}
+
+#define HKEY(data, initval, htable_bits)				 \
+(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \
+	& jhash_mask(htable_bits))
+
+#endif /* _IP_SET_AHASH_H */
+
+#define CONCAT(a, b, c)		a##b##c
+#define TOKEN(a, b, c)		CONCAT(a, b, c)
+
+/* Type/family dependent function prototypes */
+
+#define type_pf_data_equal	TOKEN(TYPE, PF, _data_equal)
+#define type_pf_data_isnull	TOKEN(TYPE, PF, _data_isnull)
+#define type_pf_data_copy	TOKEN(TYPE, PF, _data_copy)
+#define type_pf_data_zero_out	TOKEN(TYPE, PF, _data_zero_out)
+#define type_pf_data_netmask	TOKEN(TYPE, PF, _data_netmask)
+#define type_pf_data_list	TOKEN(TYPE, PF, _data_list)
+#define type_pf_data_tlist	TOKEN(TYPE, PF, _data_tlist)
+
+#define type_pf_elem		TOKEN(TYPE, PF, _elem)
+#define type_pf_telem		TOKEN(TYPE, PF, _telem)
+#define type_pf_data_timeout	TOKEN(TYPE, PF, _data_timeout)
+#define type_pf_data_expired	TOKEN(TYPE, PF, _data_expired)
+#define type_pf_data_timeout_set TOKEN(TYPE, PF, _data_timeout_set)
+
+#define type_pf_elem_add	TOKEN(TYPE, PF, _elem_add)
+#define type_pf_add		TOKEN(TYPE, PF, _add)
+#define type_pf_del		TOKEN(TYPE, PF, _del)
+#define type_pf_test_cidrs	TOKEN(TYPE, PF, _test_cidrs)
+#define type_pf_test		TOKEN(TYPE, PF, _test)
+
+#define type_pf_elem_tadd	TOKEN(TYPE, PF, _elem_tadd)
+#define type_pf_del_telem	TOKEN(TYPE, PF, _ahash_del_telem)
+#define type_pf_expire		TOKEN(TYPE, PF, _expire)
+#define type_pf_tadd		TOKEN(TYPE, PF, _tadd)
+#define type_pf_tdel		TOKEN(TYPE, PF, _tdel)
+#define type_pf_ttest_cidrs	TOKEN(TYPE, PF, _ahash_ttest_cidrs)
+#define type_pf_ttest		TOKEN(TYPE, PF, _ahash_ttest)
+
+#define type_pf_resize		TOKEN(TYPE, PF, _resize)
+#define type_pf_tresize		TOKEN(TYPE, PF, _tresize)
+#define type_pf_flush		ip_set_hash_flush
+#define type_pf_destroy		ip_set_hash_destroy
+#define type_pf_head		TOKEN(TYPE, PF, _head)
+#define type_pf_list		TOKEN(TYPE, PF, _list)
+#define type_pf_tlist		TOKEN(TYPE, PF, _tlist)
+#define type_pf_same_set	TOKEN(TYPE, PF, _same_set)
+#define type_pf_kadt		TOKEN(TYPE, PF, _kadt)
+#define type_pf_uadt		TOKEN(TYPE, PF, _uadt)
+#define type_pf_gc		TOKEN(TYPE, PF, _gc)
+#define type_pf_gc_init		TOKEN(TYPE, PF, _gc_init)
+#define type_pf_variant		TOKEN(TYPE, PF, _variant)
+#define type_pf_tvariant	TOKEN(TYPE, PF, _tvariant)
+
+/* Flavour without timeout */
+
+/* Get the ith element from the array block n */
+#define ahash_data(n, i)	\
+	((struct type_pf_elem *)((n)->value) + (i))
+
+/* Add an element to the hash table when resizing the set:
+ * we spare the maintenance of the internal counters. */
+static int
+type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value)
+{
+	if (n->pos >= n->size) {
+		void *tmp;
+
+		if (n->size >= AHASH_MAX_SIZE)
+			/* Trigger rehashing */
+			return -EAGAIN;
+
+		tmp = kzalloc((n->size + AHASH_INIT_SIZE)
+			      * sizeof(struct type_pf_elem),
+			      GFP_ATOMIC);
+		if (!tmp)
+			return -ENOMEM;
+		if (n->size) {
+			memcpy(tmp, n->value,
+			       sizeof(struct type_pf_elem) * n->size);
+			kfree(n->value);
+		}
+		n->value = tmp;
+		n->size += AHASH_INIT_SIZE;
+	}
+	type_pf_data_copy(ahash_data(n, n->pos++), value);
+	return 0;
+}
+
+/* Resize a hash: create a new hash table with doubling the hashsize
+ * and inserting the elements to it. Repeat until we succeed or
+ * fail due to memory pressures. */
+static int
+type_pf_resize(struct ip_set *set, bool retried)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t, *orig = h->table;
+	u8 htable_bits = orig->htable_bits;
+	const struct type_pf_elem *data;
+	struct hbucket *n, *m;
+	u32 i, j;
+	int ret;
+
+retry:
+	ret = 0;
+	htable_bits++;
+	pr_debug("attempt to resize set %s from %u to %u, t %p\n",
+		 set->name, orig->htable_bits, htable_bits, orig);
+	if (!htable_bits)
+		/* In case we have plenty of memory :-) */
+		return -IPSET_ERR_HASH_FULL;
+	t = ip_set_alloc(sizeof(*t)
+			 + jhash_size(htable_bits) * sizeof(struct hbucket));
+	if (!t)
+		return -ENOMEM;
+	t->htable_bits = htable_bits;
+
+	read_lock_bh(&set->lock);
+	for (i = 0; i < jhash_size(orig->htable_bits); i++) {
+		n = hbucket(orig, i);
+		for (j = 0; j < n->pos; j++) {
+			data = ahash_data(n, j);
+			m = hbucket(t, HKEY(data, h->initval, htable_bits));
+			ret = type_pf_elem_add(m, data);
+			if (ret < 0) {
+				read_unlock_bh(&set->lock);
+				ahash_destroy(t);
+				if (ret == -EAGAIN)
+					goto retry;
+				return ret;
+			}
+		}
+	}
+
+	rcu_assign_pointer(h->table, t);
+	read_unlock_bh(&set->lock);
+
+	/* Give time to other readers of the set */
+	synchronize_rcu_bh();
+
+	pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
+		 orig->htable_bits, orig, t->htable_bits, t);
+	ahash_destroy(orig);
+
+	return 0;
+}
+
+/* Add an element to a hash and update the internal counters when succeeded,
+ * otherwise report the proper error code. */
+static int
+type_pf_add(struct ip_set *set, void *value, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t;
+	const struct type_pf_elem *d = value;
+	struct hbucket *n;
+	int i, ret = 0;
+	u32 key;
+
+	if (h->elements >= h->maxelem)
+		return -IPSET_ERR_HASH_FULL;
+
+	rcu_read_lock_bh();
+	t = rcu_dereference_bh(h->table);
+	key = HKEY(value, h->initval, t->htable_bits);
+	n = hbucket(t, key);
+	for (i = 0; i < n->pos; i++)
+		if (type_pf_data_equal(ahash_data(n, i), d)) {
+			ret = -IPSET_ERR_EXIST;
+			goto out;
+		}
+
+	ret = type_pf_elem_add(n, value);
+	if (ret != 0)
+		goto out;
+
+#ifdef IP_SET_HASH_WITH_NETS
+	add_cidr(h, d->cidr, HOST_MASK);
+#endif
+	h->elements++;
+out:
+	rcu_read_unlock_bh();
+	return ret;
+}
+
+/* Delete an element from the hash: swap it with the last element
+ * and free up space if possible.
+ */
+static int
+type_pf_del(struct ip_set *set, void *value, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	const struct type_pf_elem *d = value;
+	struct hbucket *n;
+	int i;
+	struct type_pf_elem *data;
+	u32 key;
+
+	key = HKEY(value, h->initval, t->htable_bits);
+	n = hbucket(t, key);
+	for (i = 0; i < n->pos; i++) {
+		data = ahash_data(n, i);
+		if (!type_pf_data_equal(data, d))
+			continue;
+		if (i != n->pos - 1)
+			/* Not last one */
+			type_pf_data_copy(data, ahash_data(n, n->pos - 1));
+
+		n->pos--;
+		h->elements--;
+#ifdef IP_SET_HASH_WITH_NETS
+		del_cidr(h, d->cidr, HOST_MASK);
+#endif
+		if (n->pos + AHASH_INIT_SIZE < n->size) {
+			void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
+					    * sizeof(struct type_pf_elem),
+					    GFP_ATOMIC);
+			if (!tmp)
+				return 0;
+			n->size -= AHASH_INIT_SIZE;
+			memcpy(tmp, n->value,
+			       n->size * sizeof(struct type_pf_elem));
+			kfree(n->value);
+			n->value = tmp;
+		}
+		return 0;
+	}
+
+	return -IPSET_ERR_EXIST;
+}
+
+#ifdef IP_SET_HASH_WITH_NETS
+
+/* Special test function which takes into account the different network
+ * sizes added to the set */
+static int
+type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	struct hbucket *n;
+	const struct type_pf_elem *data;
+	int i, j = 0;
+	u32 key;
+	u8 host_mask = SET_HOST_MASK(set->family);
+
+	pr_debug("test by nets\n");
+	for (; j < host_mask && h->nets[j].cidr; j++) {
+		type_pf_data_netmask(d, h->nets[j].cidr);
+		key = HKEY(d, h->initval, t->htable_bits);
+		n = hbucket(t, key);
+		for (i = 0; i < n->pos; i++) {
+			data = ahash_data(n, i);
+			if (type_pf_data_equal(data, d))
+				return 1;
+		}
+	}
+	return 0;
+}
+#endif
+
+/* Test whether the element is added to the set */
+static int
+type_pf_test(struct ip_set *set, void *value, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	struct type_pf_elem *d = value;
+	struct hbucket *n;
+	const struct type_pf_elem *data;
+	int i;
+	u32 key;
+
+#ifdef IP_SET_HASH_WITH_NETS
+	/* If we test an IP address and not a network address,
+	 * try all possible network sizes */
+	if (d->cidr == SET_HOST_MASK(set->family))
+		return type_pf_test_cidrs(set, d, timeout);
+#endif
+
+	key = HKEY(d, h->initval, t->htable_bits);
+	n = hbucket(t, key);
+	for (i = 0; i < n->pos; i++) {
+		data = ahash_data(n, i);
+		if (type_pf_data_equal(data, d))
+			return 1;
+	}
+	return 0;
+}
+
+/* Reply a HEADER request: fill out the header part of the set */
+static int
+type_pf_head(struct ip_set *set, struct sk_buff *skb)
+{
+	const struct ip_set_hash *h = set->data;
+	struct nlattr *nested;
+	size_t memsize;
+
+	read_lock_bh(&set->lock);
+	memsize = ahash_memsize(h, with_timeout(h->timeout)
+					? sizeof(struct type_pf_telem)
+					: sizeof(struct type_pf_elem),
+				set->family == AF_INET ? 32 : 128);
+	read_unlock_bh(&set->lock);
+
+	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+	if (!nested)
+		goto nla_put_failure;
+	NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE,
+		      htonl(jhash_size(h->table->htable_bits)));
+	NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem));
+#ifdef IP_SET_HASH_WITH_NETMASK
+	if (h->netmask != HOST_MASK)
+		NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
+#endif
+	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
+		      htonl(atomic_read(&set->ref) - 1));
+	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));
+	if (with_timeout(h->timeout))
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout));
+	ipset_nest_end(skb, nested);
+
+	return 0;
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+/* Reply a LIST/SAVE request: dump the elements of the specified set */
+static int
+type_pf_list(const struct ip_set *set,
+	     struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct ip_set_hash *h = set->data;
+	const struct htable *t = h->table;
+	struct nlattr *atd, *nested;
+	const struct hbucket *n;
+	const struct type_pf_elem *data;
+	u32 first = cb->args[2];
+	/* We assume that one hash bucket fills into one page */
+	void *incomplete;
+	int i;
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	pr_debug("list hash set %s\n", set->name);
+	for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
+		incomplete = skb_tail_pointer(skb);
+		n = hbucket(t, cb->args[2]);
+		pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);
+		for (i = 0; i < n->pos; i++) {
+			data = ahash_data(n, i);
+			pr_debug("list hash %lu hbucket %p i %u, data %p\n",
+				 cb->args[2], n, i, data);
+			nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+			if (!nested) {
+				if (cb->args[2] == first) {
+					nla_nest_cancel(skb, atd);
+					return -EMSGSIZE;
+				} else
+					goto nla_put_failure;
+			}
+			if (type_pf_data_list(skb, data))
+				goto nla_put_failure;
+			ipset_nest_end(skb, nested);
+		}
+	}
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nlmsg_trim(skb, incomplete);
+	ipset_nest_end(skb, atd);
+	if (unlikely(first == cb->args[2])) {
+		pr_warning("Can't list set %s: one bucket does not fit into "
+			   "a message. Please report it!\n", set->name);
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+static int
+type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
+	     enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
+static int
+type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
+	     enum ipset_adt adt, u32 *lineno, u32 flags);
+
+static const struct ip_set_type_variant type_pf_variant = {
+	.kadt	= type_pf_kadt,
+	.uadt	= type_pf_uadt,
+	.adt	= {
+		[IPSET_ADD] = type_pf_add,
+		[IPSET_DEL] = type_pf_del,
+		[IPSET_TEST] = type_pf_test,
+	},
+	.destroy = type_pf_destroy,
+	.flush	= type_pf_flush,
+	.head	= type_pf_head,
+	.list	= type_pf_list,
+	.resize	= type_pf_resize,
+	.same_set = type_pf_same_set,
+};
+
+/* Flavour with timeout support */
+
+#define ahash_tdata(n, i) \
+	(struct type_pf_elem *)((struct type_pf_telem *)((n)->value) + (i))
+
+static inline u32
+type_pf_data_timeout(const struct type_pf_elem *data)
+{
+	const struct type_pf_telem *tdata =
+		(const struct type_pf_telem *) data;
+
+	return tdata->timeout;
+}
+
+static inline bool
+type_pf_data_expired(const struct type_pf_elem *data)
+{
+	const struct type_pf_telem *tdata =
+		(const struct type_pf_telem *) data;
+
+	return ip_set_timeout_expired(tdata->timeout);
+}
+
+static inline void
+type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
+{
+	struct type_pf_telem *tdata = (struct type_pf_telem *) data;
+
+	tdata->timeout = ip_set_timeout_set(timeout);
+}
+
+static int
+type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
+		  u32 timeout)
+{
+	struct type_pf_elem *data;
+
+	if (n->pos >= n->size) {
+		void *tmp;
+
+		if (n->size >= AHASH_MAX_SIZE)
+			/* Trigger rehashing */
+			return -EAGAIN;
+
+		tmp = kzalloc((n->size + AHASH_INIT_SIZE)
+			      * sizeof(struct type_pf_telem),
+			      GFP_ATOMIC);
+		if (!tmp)
+			return -ENOMEM;
+		if (n->size) {
+			memcpy(tmp, n->value,
+			       sizeof(struct type_pf_telem) * n->size);
+			kfree(n->value);
+		}
+		n->value = tmp;
+		n->size += AHASH_INIT_SIZE;
+	}
+	data = ahash_tdata(n, n->pos++);
+	type_pf_data_copy(data, value);
+	type_pf_data_timeout_set(data, timeout);
+	return 0;
+}
+
+/* Delete expired elements from the hashtable */
+static void
+type_pf_expire(struct ip_set_hash *h)
+{
+	struct htable *t = h->table;
+	struct hbucket *n;
+	struct type_pf_elem *data;
+	u32 i;
+	int j;
+
+	for (i = 0; i < jhash_size(t->htable_bits); i++) {
+		n = hbucket(t, i);
+		for (j = 0; j < n->pos; j++) {
+			data = ahash_tdata(n, j);
+			if (type_pf_data_expired(data)) {
+				pr_debug("expired %u/%u\n", i, j);
+#ifdef IP_SET_HASH_WITH_NETS
+				del_cidr(h, data->cidr, HOST_MASK);
+#endif
+				if (j != n->pos - 1)
+					/* Not last one */
+					type_pf_data_copy(data,
+						ahash_tdata(n, n->pos - 1));
+				n->pos--;
+				h->elements--;
+			}
+		}
+		if (n->pos + AHASH_INIT_SIZE < n->size) {
+			void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
+					    * sizeof(struct type_pf_telem),
+					    GFP_ATOMIC);
+			if (!tmp)
+				/* Still try to delete expired elements */
+				continue;
+			n->size -= AHASH_INIT_SIZE;
+			memcpy(tmp, n->value,
+			       n->size * sizeof(struct type_pf_telem));
+			kfree(n->value);
+			n->value = tmp;
+		}
+	}
+}
+
+static int
+type_pf_tresize(struct ip_set *set, bool retried)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t, *orig = h->table;
+	u8 htable_bits = orig->htable_bits;
+	const struct type_pf_elem *data;
+	struct hbucket *n, *m;
+	u32 i, j;
+	int ret;
+
+	/* Try to cleanup once */
+	if (!retried) {
+		i = h->elements;
+		write_lock_bh(&set->lock);
+		type_pf_expire(set->data);
+		write_unlock_bh(&set->lock);
+		if (h->elements <  i)
+			return 0;
+	}
+
+retry:
+	ret = 0;
+	htable_bits++;
+	if (!htable_bits)
+		/* In case we have plenty of memory :-) */
+		return -IPSET_ERR_HASH_FULL;
+	t = ip_set_alloc(sizeof(*t)
+			 + jhash_size(htable_bits) * sizeof(struct hbucket));
+	if (!t)
+		return -ENOMEM;
+	t->htable_bits = htable_bits;
+
+	read_lock_bh(&set->lock);
+	for (i = 0; i < jhash_size(orig->htable_bits); i++) {
+		n = hbucket(orig, i);
+		for (j = 0; j < n->pos; j++) {
+			data = ahash_tdata(n, j);
+			m = hbucket(t, HKEY(data, h->initval, htable_bits));
+			ret = type_pf_elem_tadd(m, data,
+						type_pf_data_timeout(data));
+			if (ret < 0) {
+				read_unlock_bh(&set->lock);
+				ahash_destroy(t);
+				if (ret == -EAGAIN)
+					goto retry;
+				return ret;
+			}
+		}
+	}
+
+	rcu_assign_pointer(h->table, t);
+	read_unlock_bh(&set->lock);
+
+	/* Give time to other readers of the set */
+	synchronize_rcu_bh();
+
+	ahash_destroy(orig);
+
+	return 0;
+}
+
+static int
+type_pf_tadd(struct ip_set *set, void *value, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	const struct type_pf_elem *d = value;
+	struct hbucket *n;
+	struct type_pf_elem *data;
+	int ret = 0, i, j = AHASH_MAX_SIZE + 1;
+	u32 key;
+
+	if (h->elements >= h->maxelem)
+		/* FIXME: when set is full, we slow down here */
+		type_pf_expire(h);
+	if (h->elements >= h->maxelem)
+		return -IPSET_ERR_HASH_FULL;
+
+	rcu_read_lock_bh();
+	t = rcu_dereference_bh(h->table);
+	key = HKEY(d, h->initval, t->htable_bits);
+	n = hbucket(t, key);
+	for (i = 0; i < n->pos; i++) {
+		data = ahash_tdata(n, i);
+		if (type_pf_data_equal(data, d)) {
+			if (type_pf_data_expired(data))
+				j = i;
+			else {
+				ret = -IPSET_ERR_EXIST;
+				goto out;
+			}
+		} else if (j == AHASH_MAX_SIZE + 1 &&
+			   type_pf_data_expired(data))
+			j = i;
+	}
+	if (j != AHASH_MAX_SIZE + 1) {
+		data = ahash_tdata(n, j);
+#ifdef IP_SET_HASH_WITH_NETS
+		del_cidr(h, data->cidr, HOST_MASK);
+		add_cidr(h, d->cidr, HOST_MASK);
+#endif
+		type_pf_data_copy(data, d);
+		type_pf_data_timeout_set(data, timeout);
+		goto out;
+	}
+	ret = type_pf_elem_tadd(n, d, timeout);
+	if (ret != 0)
+		goto out;
+
+#ifdef IP_SET_HASH_WITH_NETS
+	add_cidr(h, d->cidr, HOST_MASK);
+#endif
+	h->elements++;
+out:
+	rcu_read_unlock_bh();
+	return ret;
+}
+
+static int
+type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	const struct type_pf_elem *d = value;
+	struct hbucket *n;
+	int i, ret = 0;
+	struct type_pf_elem *data;
+	u32 key;
+
+	key = HKEY(value, h->initval, t->htable_bits);
+	n = hbucket(t, key);
+	for (i = 0; i < n->pos; i++) {
+		data = ahash_tdata(n, i);
+		if (!type_pf_data_equal(data, d))
+			continue;
+		if (type_pf_data_expired(data))
+			ret = -IPSET_ERR_EXIST;
+		if (i != n->pos - 1)
+			/* Not last one */
+			type_pf_data_copy(data, ahash_tdata(n, n->pos - 1));
+
+		n->pos--;
+		h->elements--;
+#ifdef IP_SET_HASH_WITH_NETS
+		del_cidr(h, d->cidr, HOST_MASK);
+#endif
+		if (n->pos + AHASH_INIT_SIZE < n->size) {
+			void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
+					    * sizeof(struct type_pf_telem),
+					    GFP_ATOMIC);
+			if (!tmp)
+				return 0;
+			n->size -= AHASH_INIT_SIZE;
+			memcpy(tmp, n->value,
+			       n->size * sizeof(struct type_pf_telem));
+			kfree(n->value);
+			n->value = tmp;
+		}
+		return 0;
+	}
+
+	return -IPSET_ERR_EXIST;
+}
+
+#ifdef IP_SET_HASH_WITH_NETS
+static int
+type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	struct type_pf_elem *data;
+	struct hbucket *n;
+	int i, j = 0;
+	u32 key;
+	u8 host_mask = SET_HOST_MASK(set->family);
+
+	for (; j < host_mask && h->nets[j].cidr; j++) {
+		type_pf_data_netmask(d, h->nets[j].cidr);
+		key = HKEY(d, h->initval, t->htable_bits);
+		n = hbucket(t, key);
+		for (i = 0; i < n->pos; i++) {
+			data = ahash_tdata(n, i);
+			if (type_pf_data_equal(data, d))
+				return !type_pf_data_expired(data);
+		}
+	}
+	return 0;
+}
+#endif
+
+static int
+type_pf_ttest(struct ip_set *set, void *value, u32 timeout)
+{
+	struct ip_set_hash *h = set->data;
+	struct htable *t = h->table;
+	struct type_pf_elem *data, *d = value;
+	struct hbucket *n;
+	int i;
+	u32 key;
+
+#ifdef IP_SET_HASH_WITH_NETS
+	if (d->cidr == SET_HOST_MASK(set->family))
+		return type_pf_ttest_cidrs(set, d, timeout);
+#endif
+	key = HKEY(d, h->initval, t->htable_bits);
+	n = hbucket(t, key);
+	for (i = 0; i < n->pos; i++) {
+		data = ahash_tdata(n, i);
+		if (type_pf_data_equal(data, d))
+			return !type_pf_data_expired(data);
+	}
+	return 0;
+}
+
+static int
+type_pf_tlist(const struct ip_set *set,
+	      struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct ip_set_hash *h = set->data;
+	const struct htable *t = h->table;
+	struct nlattr *atd, *nested;
+	const struct hbucket *n;
+	const struct type_pf_elem *data;
+	u32 first = cb->args[2];
+	/* We assume that one hash bucket fills into one page */
+	void *incomplete;
+	int i;
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) {
+		incomplete = skb_tail_pointer(skb);
+		n = hbucket(t, cb->args[2]);
+		for (i = 0; i < n->pos; i++) {
+			data = ahash_tdata(n, i);
+			pr_debug("list %p %u\n", n, i);
+			if (type_pf_data_expired(data))
+				continue;
+			pr_debug("do list %p %u\n", n, i);
+			nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+			if (!nested) {
+				if (cb->args[2] == first) {
+					nla_nest_cancel(skb, atd);
+					return -EMSGSIZE;
+				} else
+					goto nla_put_failure;
+			}
+			if (type_pf_data_tlist(skb, data))
+				goto nla_put_failure;
+			ipset_nest_end(skb, nested);
+		}
+	}
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nlmsg_trim(skb, incomplete);
+	ipset_nest_end(skb, atd);
+	if (unlikely(first == cb->args[2])) {
+		pr_warning("Can't list set %s: one bucket does not fit into "
+			   "a message. Please report it!\n", set->name);
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+static const struct ip_set_type_variant type_pf_tvariant = {
+	.kadt	= type_pf_kadt,
+	.uadt	= type_pf_uadt,
+	.adt	= {
+		[IPSET_ADD] = type_pf_tadd,
+		[IPSET_DEL] = type_pf_tdel,
+		[IPSET_TEST] = type_pf_ttest,
+	},
+	.destroy = type_pf_destroy,
+	.flush	= type_pf_flush,
+	.head	= type_pf_head,
+	.list	= type_pf_tlist,
+	.resize	= type_pf_tresize,
+	.same_set = type_pf_same_set,
+};
+
+static void
+type_pf_gc(unsigned long ul_set)
+{
+	struct ip_set *set = (struct ip_set *) ul_set;
+	struct ip_set_hash *h = set->data;
+
+	pr_debug("called\n");
+	write_lock_bh(&set->lock);
+	type_pf_expire(h);
+	write_unlock_bh(&set->lock);
+
+	h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
+	add_timer(&h->gc);
+}
+
+static void
+type_pf_gc_init(struct ip_set *set)
+{
+	struct ip_set_hash *h = set->data;
+
+	init_timer(&h->gc);
+	h->gc.data = (unsigned long) set;
+	h->gc.function = type_pf_gc;
+	h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
+	add_timer(&h->gc);
+	pr_debug("gc initialized, run in every %u\n",
+		 IPSET_GC_PERIOD(h->timeout));
+}
+
+#undef type_pf_data_equal
+#undef type_pf_data_isnull
+#undef type_pf_data_copy
+#undef type_pf_data_zero_out
+#undef type_pf_data_list
+#undef type_pf_data_tlist
+
+#undef type_pf_elem
+#undef type_pf_telem
+#undef type_pf_data_timeout
+#undef type_pf_data_expired
+#undef type_pf_data_netmask
+#undef type_pf_data_timeout_set
+
+#undef type_pf_elem_add
+#undef type_pf_add
+#undef type_pf_del
+#undef type_pf_test_cidrs
+#undef type_pf_test
+
+#undef type_pf_elem_tadd
+#undef type_pf_expire
+#undef type_pf_tadd
+#undef type_pf_tdel
+#undef type_pf_ttest_cidrs
+#undef type_pf_ttest
+
+#undef type_pf_resize
+#undef type_pf_tresize
+#undef type_pf_flush
+#undef type_pf_destroy
+#undef type_pf_head
+#undef type_pf_list
+#undef type_pf_tlist
+#undef type_pf_same_set
+#undef type_pf_kadt
+#undef type_pf_uadt
+#undef type_pf_gc
+#undef type_pf_gc_init
+#undef type_pf_variant
+#undef type_pf_tvariant
diff --git a/include/linux/netfilter/ipset/ip_set_bitmap.h b/include/linux/netfilter/ipset/ip_set_bitmap.h
new file mode 100644
index 0000000..61a9e87
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_bitmap.h
@@ -0,0 +1,31 @@
+#ifndef __IP_SET_BITMAP_H
+#define __IP_SET_BITMAP_H
+
+/* Bitmap type specific error codes */
+enum {
+	/* The element is out of the range of the set */
+	IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
+	/* The range exceeds the size limit of the set type */
+	IPSET_ERR_BITMAP_RANGE_SIZE,
+};
+
+#ifdef __KERNEL__
+#define IPSET_BITMAP_MAX_RANGE	0x0000FFFF
+
+/* Common functions */
+
+static inline u32
+range_to_mask(u32 from, u32 to, u8 *bits)
+{
+	u32 mask = 0xFFFFFFFE;
+
+	*bits = 32;
+	while (--(*bits) > 0 && mask && (to & mask) != from)
+		mask <<= 1;
+
+	return mask;
+}
+
+#endif /* __KERNEL__ */
+
+#endif /* __IP_SET_BITMAP_H */
diff --git a/include/linux/netfilter/ipset/ip_set_getport.h b/include/linux/netfilter/ipset/ip_set_getport.h
new file mode 100644
index 0000000..5aebd17
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_getport.h
@@ -0,0 +1,31 @@
+#ifndef _IP_SET_GETPORT_H
+#define _IP_SET_GETPORT_H
+
+extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
+				__be16 *port, u8 *proto);
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
+				__be16 *port, u8 *proto);
+#else
+static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
+				       __be16 *port, u8 *proto)
+{
+	return false;
+}
+#endif
+
+extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src,
+				__be16 *port);
+
+static inline bool ip_set_proto_with_ports(u8 proto)
+{
+	switch (proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+		return true;
+	}
+	return false;
+}
+
+#endif /*_IP_SET_GETPORT_H*/
diff --git a/include/linux/netfilter/ipset/ip_set_hash.h b/include/linux/netfilter/ipset/ip_set_hash.h
new file mode 100644
index 0000000..b86f15c
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_hash.h
@@ -0,0 +1,26 @@
+#ifndef __IP_SET_HASH_H
+#define __IP_SET_HASH_H
+
+/* Hash type specific error codes */
+enum {
+	/* Hash is full */
+	IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
+	/* Null-valued element */
+	IPSET_ERR_HASH_ELEM,
+	/* Invalid protocol */
+	IPSET_ERR_INVALID_PROTO,
+	/* Protocol missing but must be specified */
+	IPSET_ERR_MISSING_PROTO,
+};
+
+#ifdef __KERNEL__
+
+#define IPSET_DEFAULT_HASHSIZE		1024
+#define IPSET_MIMINAL_HASHSIZE		64
+#define IPSET_DEFAULT_MAXELEM		65536
+#define IPSET_DEFAULT_PROBES		4
+#define IPSET_DEFAULT_RESIZE		100
+
+#endif /* __KERNEL__ */
+
+#endif /* __IP_SET_HASH_H */
diff --git a/include/linux/netfilter/ipset/ip_set_list.h b/include/linux/netfilter/ipset/ip_set_list.h
new file mode 100644
index 0000000..40a63f3
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_list.h
@@ -0,0 +1,27 @@
+#ifndef __IP_SET_LIST_H
+#define __IP_SET_LIST_H
+
+/* List type specific error codes */
+enum {
+	/* Set name to be added/deleted/tested does not exist. */
+	IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
+	/* list:set type is not permitted to add */
+	IPSET_ERR_LOOP,
+	/* Missing reference set */
+	IPSET_ERR_BEFORE,
+	/* Reference set does not exist */
+	IPSET_ERR_NAMEREF,
+	/* Set is full */
+	IPSET_ERR_LIST_FULL,
+	/* Reference set is not added to the set */
+	IPSET_ERR_REF_EXIST,
+};
+
+#ifdef __KERNEL__
+
+#define IP_SET_LIST_DEFAULT_SIZE	8
+#define IP_SET_LIST_MIN_SIZE		4
+
+#endif /* __KERNEL__ */
+
+#endif /* __IP_SET_LIST_H */
diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
new file mode 100644
index 0000000..9f30c5f
--- /dev/null
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -0,0 +1,127 @@
+#ifndef _IP_SET_TIMEOUT_H
+#define _IP_SET_TIMEOUT_H
+
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifdef __KERNEL__
+
+/* How often should the gc be run by default */
+#define IPSET_GC_TIME			(3 * 60)
+
+/* Timeout period depending on the timeout value of the given set */
+#define IPSET_GC_PERIOD(timeout) \
+	((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)
+
+/* Set is defined without timeout support: timeout value may be 0 */
+#define IPSET_NO_TIMEOUT	UINT_MAX
+
+#define with_timeout(timeout)	((timeout) != IPSET_NO_TIMEOUT)
+
+static inline unsigned int
+ip_set_timeout_uget(struct nlattr *tb)
+{
+	unsigned int timeout = ip_set_get_h32(tb);
+
+	/* Userspace supplied TIMEOUT parameter: adjust crazy size */
+	return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
+}
+
+#ifdef IP_SET_BITMAP_TIMEOUT
+
+/* Bitmap specific timeout constants and macros for the entries */
+
+/* Bitmap entry is unset */
+#define IPSET_ELEM_UNSET	0
+/* Bitmap entry is set with no timeout value */
+#define IPSET_ELEM_PERMANENT	(UINT_MAX/2)
+
+static inline bool
+ip_set_timeout_test(unsigned long timeout)
+{
+	return timeout != IPSET_ELEM_UNSET &&
+	       (timeout == IPSET_ELEM_PERMANENT ||
+		time_after(timeout, jiffies));
+}
+
+static inline bool
+ip_set_timeout_expired(unsigned long timeout)
+{
+	return timeout != IPSET_ELEM_UNSET &&
+	       timeout != IPSET_ELEM_PERMANENT &&
+	       time_before(timeout, jiffies);
+}
+
+static inline unsigned long
+ip_set_timeout_set(u32 timeout)
+{
+	unsigned long t;
+
+	if (!timeout)
+		return IPSET_ELEM_PERMANENT;
+
+	t = timeout * HZ + jiffies;
+	if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
+		/* Bingo! */
+		t++;
+
+	return t;
+}
+
+static inline u32
+ip_set_timeout_get(unsigned long timeout)
+{
+	return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
+}
+
+#else
+
+/* Hash specific timeout constants and macros for the entries */
+
+/* Hash entry is set with no timeout value */
+#define IPSET_ELEM_PERMANENT	0
+
+static inline bool
+ip_set_timeout_test(unsigned long timeout)
+{
+	return timeout == IPSET_ELEM_PERMANENT ||
+	       time_after(timeout, jiffies);
+}
+
+static inline bool
+ip_set_timeout_expired(unsigned long timeout)
+{
+	return timeout != IPSET_ELEM_PERMANENT &&
+	       time_before(timeout, jiffies);
+}
+
+static inline unsigned long
+ip_set_timeout_set(u32 timeout)
+{
+	unsigned long t;
+
+	if (!timeout)
+		return IPSET_ELEM_PERMANENT;
+
+	t = timeout * HZ + jiffies;
+	if (t == IPSET_ELEM_PERMANENT)
+		/* Bingo! :-) */
+		t++;
+
+	return t;
+}
+
+static inline u32
+ip_set_timeout_get(unsigned long timeout)
+{
+	return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
+}
+#endif /* ! IP_SET_BITMAP_TIMEOUT */
+
+#endif	/* __KERNEL__ */
+
+#endif /* _IP_SET_TIMEOUT_H */
diff --git a/include/linux/netfilter/ipset/pfxlen.h b/include/linux/netfilter/ipset/pfxlen.h
new file mode 100644
index 0000000..0e1fb50
--- /dev/null
+++ b/include/linux/netfilter/ipset/pfxlen.h
@@ -0,0 +1,35 @@
+#ifndef _PFXLEN_H
+#define _PFXLEN_H
+
+#include <asm/byteorder.h>
+#include <linux/netfilter.h> 
+
+/* Prefixlen maps, by Jan Engelhardt  */
+extern const union nf_inet_addr ip_set_netmask_map[];
+extern const union nf_inet_addr ip_set_hostmask_map[];
+
+static inline __be32
+ip_set_netmask(u8 pfxlen)
+{
+	return ip_set_netmask_map[pfxlen].ip;
+}
+
+static inline const __be32 *
+ip_set_netmask6(u8 pfxlen)
+{
+	return &ip_set_netmask_map[pfxlen].ip6[0];
+}
+
+static inline u32
+ip_set_hostmask(u8 pfxlen)
+{
+	return (__force u32) ip_set_hostmask_map[pfxlen].ip;
+}
+
+static inline const __be32 *
+ip_set_hostmask6(u8 pfxlen)
+{
+	return &ip_set_hostmask_map[pfxlen].ip6[0];
+}
+
+#endif /*_PFXLEN_H */
diff --git a/include/linux/netfilter/nf_conntrack_snmp.h b/include/linux/netfilter/nf_conntrack_snmp.h
new file mode 100644
index 0000000..064bc63
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_snmp.h
@@ -0,0 +1,9 @@
+#ifndef _NF_CONNTRACK_SNMP_H
+#define _NF_CONNTRACK_SNMP_H
+
+extern int (*nf_nat_snmp_hook)(struct sk_buff *skb,
+				unsigned int protoff,
+				struct nf_conn *ct,
+				enum ip_conntrack_info ctinfo);
+
+#endif /* _NF_CONNTRACK_SNMP_H */
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 361d6b5..2b11fc1 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -47,7 +47,8 @@ struct nfgenmsg {
 #define NFNL_SUBSYS_QUEUE		3
 #define NFNL_SUBSYS_ULOG		4
 #define NFNL_SUBSYS_OSF			5
-#define NFNL_SUBSYS_COUNT		6
+#define NFNL_SUBSYS_IPSET		6
+#define NFNL_SUBSYS_COUNT		7
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 19711e3..debf1ae 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -42,6 +42,7 @@ enum ctattr_type {
 	CTA_SECMARK,		/* obsolete */
 	CTA_ZONE,
 	CTA_SECCTX,
+	CTA_TIMESTAMP,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -127,6 +128,14 @@ enum ctattr_counters {
 };
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
 
+enum ctattr_tstamp {
+	CTA_TIMESTAMP_UNSPEC,
+	CTA_TIMESTAMP_START,
+	CTA_TIMESTAMP_STOP,
+	__CTA_TIMESTAMP_MAX
+};
+#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1)
+
 enum ctattr_nat {
 	CTA_NAT_UNSPEC,
 	CTA_NAT_MINIP,
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index ea9b8d3..90c2c95 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -28,8 +28,8 @@ struct nfulnl_msg_packet_hw {
 };
 
 struct nfulnl_msg_packet_timestamp {
-	aligned_be64	sec;
-	aligned_be64	usec;
+	__aligned_be64	sec;
+	__aligned_be64	usec;
 };
 
 enum nfulnl_attr_type {
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index 2455fe5..af94e00 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -25,8 +25,8 @@ struct nfqnl_msg_packet_hw {
 };
 
 struct nfqnl_msg_packet_timestamp {
-	aligned_be64	sec;
-	aligned_be64	usec;
+	__aligned_be64	sec;
+	__aligned_be64	usec;
 };
 
 enum nfqnl_attr_type {
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 6712e71..3721952 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -611,8 +611,9 @@ struct _compat_xt_align {
 extern void xt_compat_lock(u_int8_t af);
 extern void xt_compat_unlock(u_int8_t af);
 
-extern int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta);
+extern int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta);
 extern void xt_compat_flush_offsets(u_int8_t af);
+extern void xt_compat_init_offsets(u_int8_t af, unsigned int number);
 extern int xt_compat_calc_jump(u_int8_t af, unsigned int offset);
 
 extern int xt_compat_match_offset(const struct xt_match *match);
diff --git a/include/linux/netfilter/xt_AUDIT.h b/include/linux/netfilter/xt_AUDIT.h
new file mode 100644
index 0000000..38751d2
--- /dev/null
+++ b/include/linux/netfilter/xt_AUDIT.h
@@ -0,0 +1,30 @@
+/*
+ * Header file for iptables xt_AUDIT target
+ *
+ * (C) 2010-2011 Thomas Graf <tgraf@redhat.com>
+ * (C) 2010-2011 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _XT_AUDIT_TARGET_H
+#define _XT_AUDIT_TARGET_H
+
+#include <linux/types.h>
+
+enum {
+	XT_AUDIT_TYPE_ACCEPT = 0,
+	XT_AUDIT_TYPE_DROP,
+	XT_AUDIT_TYPE_REJECT,
+	__XT_AUDIT_TYPE_MAX,
+};
+
+#define XT_AUDIT_TYPE_MAX (__XT_AUDIT_TYPE_MAX - 1)
+
+struct xt_audit_info {
+	__u8 type; /* XT_AUDIT_TYPE_* */
+};
+
+#endif /* _XT_AUDIT_TARGET_H */
diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h
index 1b56410..b56e768 100644
--- a/include/linux/netfilter/xt_CT.h
+++ b/include/linux/netfilter/xt_CT.h
@@ -1,14 +1,16 @@
 #ifndef _XT_CT_H
 #define _XT_CT_H
 
+#include <linux/types.h>
+
 #define XT_CT_NOTRACK	0x1
 
 struct xt_ct_target_info {
-	u_int16_t	flags;
-	u_int16_t	zone;
-	u_int32_t	ct_events;
-	u_int32_t	exp_events;
-	char		helper[16];
+	__u16 flags;
+	__u16 zone;
+	__u32 ct_events;
+	__u32 exp_events;
+	char helper[16];
 
 	/* Used internally by the kernel */
 	struct nf_conn	*ct __attribute__((aligned(8)));
diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h
index 2584f4a..9eafdbb 100644
--- a/include/linux/netfilter/xt_NFQUEUE.h
+++ b/include/linux/netfilter/xt_NFQUEUE.h
@@ -20,4 +20,10 @@ struct xt_NFQ_info_v1 {
 	__u16 queues_total;
 };
 
+struct xt_NFQ_info_v2 {
+	__u16 queuenum;
+	__u16 queues_total;
+	__u16 bypass;
+};
+
 #endif /* _XT_NFQ_TARGET_H */
diff --git a/include/linux/netfilter/xt_TCPOPTSTRIP.h b/include/linux/netfilter/xt_TCPOPTSTRIP.h
index 2db5432..7157318 100644
--- a/include/linux/netfilter/xt_TCPOPTSTRIP.h
+++ b/include/linux/netfilter/xt_TCPOPTSTRIP.h
@@ -1,13 +1,15 @@
 #ifndef _XT_TCPOPTSTRIP_H
 #define _XT_TCPOPTSTRIP_H
 
+#include <linux/types.h>
+
 #define tcpoptstrip_set_bit(bmap, idx) \
 	(bmap[(idx) >> 5] |= 1U << (idx & 31))
 #define tcpoptstrip_test_bit(bmap, idx) \
 	(((1U << (idx & 31)) & bmap[(idx) >> 5]) != 0)
 
 struct xt_tcpoptstrip_target_info {
-	u_int32_t strip_bmap[8];
+	__u32 strip_bmap[8];
 };
 
 #endif /* _XT_TCPOPTSTRIP_H */
diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
index 3f3d693..902043c 100644
--- a/include/linux/netfilter/xt_TPROXY.h
+++ b/include/linux/netfilter/xt_TPROXY.h
@@ -1,19 +1,21 @@
 #ifndef _XT_TPROXY_H
 #define _XT_TPROXY_H
 
+#include <linux/types.h>
+
 /* TPROXY target is capable of marking the packet to perform
  * redirection. We can get rid of that whenever we get support for
  * mutliple targets in the same rule. */
 struct xt_tproxy_target_info {
-	u_int32_t mark_mask;
-	u_int32_t mark_value;
+	__u32 mark_mask;
+	__u32 mark_value;
 	__be32 laddr;
 	__be16 lport;
 };
 
 struct xt_tproxy_target_info_v1 {
-	u_int32_t mark_mask;
-	u_int32_t mark_value;
+	__u32 mark_mask;
+	__u32 mark_value;
 	union nf_inet_addr laddr;
 	__be16 lport;
 };
diff --git a/include/linux/netfilter/xt_addrtype.h b/include/linux/netfilter/xt_addrtype.h
new file mode 100644
index 0000000..b156baa
--- /dev/null
+++ b/include/linux/netfilter/xt_addrtype.h
@@ -0,0 +1,44 @@
+#ifndef _XT_ADDRTYPE_H
+#define _XT_ADDRTYPE_H
+
+#include <linux/types.h>
+
+enum {
+	XT_ADDRTYPE_INVERT_SOURCE	= 0x0001,
+	XT_ADDRTYPE_INVERT_DEST		= 0x0002,
+	XT_ADDRTYPE_LIMIT_IFACE_IN	= 0x0004,
+	XT_ADDRTYPE_LIMIT_IFACE_OUT	= 0x0008,
+};
+
+
+/* rtn_type enum values from rtnetlink.h, but shifted */
+enum {
+	XT_ADDRTYPE_UNSPEC = 1 << 0,
+	XT_ADDRTYPE_UNICAST = 1 << 1,	/* 1 << RTN_UNICAST */
+	XT_ADDRTYPE_LOCAL  = 1 << 2,	/* 1 << RTN_LOCAL, etc */
+	XT_ADDRTYPE_BROADCAST = 1 << 3,
+	XT_ADDRTYPE_ANYCAST = 1 << 4,
+	XT_ADDRTYPE_MULTICAST = 1 << 5,
+	XT_ADDRTYPE_BLACKHOLE = 1 << 6,
+	XT_ADDRTYPE_UNREACHABLE = 1 << 7,
+	XT_ADDRTYPE_PROHIBIT = 1 << 8,
+	XT_ADDRTYPE_THROW = 1 << 9,
+	XT_ADDRTYPE_NAT = 1 << 10,
+	XT_ADDRTYPE_XRESOLVE = 1 << 11,
+};
+
+struct xt_addrtype_info_v1 {
+	__u16	source;		/* source-type mask */
+	__u16	dest;		/* dest-type mask */
+	__u32	flags;
+};
+
+/* revision 0 */
+struct xt_addrtype_info {
+	__u16	source;		/* source-type mask */
+	__u16	dest;		/* dest-type mask */
+	__u32	invert_source;
+	__u32	invert_dest;
+};
+
+#endif
diff --git a/include/linux/netfilter/xt_cluster.h b/include/linux/netfilter/xt_cluster.h
index 8866826..9b883c8 100644
--- a/include/linux/netfilter/xt_cluster.h
+++ b/include/linux/netfilter/xt_cluster.h
@@ -1,15 +1,17 @@
 #ifndef _XT_CLUSTER_MATCH_H
 #define _XT_CLUSTER_MATCH_H
 
+#include <linux/types.h>
+
 enum xt_cluster_flags {
 	XT_CLUSTER_F_INV	= (1 << 0)
 };
 
 struct xt_cluster_match_info {
-	u_int32_t		total_nodes;
-	u_int32_t		node_mask;
-	u_int32_t		hash_seed;
-	u_int32_t		flags;
+	__u32 total_nodes;
+	__u32 node_mask;
+	__u32 hash_seed;
+	__u32 flags;
 };
 
 #define XT_CLUSTER_NODES_MAX	32
diff --git a/include/linux/netfilter/xt_comment.h b/include/linux/netfilter/xt_comment.h
index eacfedc..0ea5e79 100644
--- a/include/linux/netfilter/xt_comment.h
+++ b/include/linux/netfilter/xt_comment.h
@@ -4,7 +4,7 @@
 #define XT_MAX_COMMENT_LEN 256
 
 struct xt_comment_info {
-	unsigned char comment[XT_MAX_COMMENT_LEN];
+	char comment[XT_MAX_COMMENT_LEN];
 };
 
 #endif /* XT_COMMENT_H */
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h
index 92fcbb0..f1d6c15 100644
--- a/include/linux/netfilter/xt_connbytes.h
+++ b/include/linux/netfilter/xt_connbytes.h
@@ -17,8 +17,8 @@ enum xt_connbytes_direction {
 
 struct xt_connbytes_info {
 	struct {
-		aligned_u64 from;	/* count to be matched */
-		aligned_u64 to;		/* count to be matched */
+		__aligned_u64 from;	/* count to be matched */
+		__aligned_u64 to;	/* count to be matched */
 	} count;
 	__u8 what;		/* ipt_connbytes_what */
 	__u8 direction;	/* ipt_connbytes_direction */
diff --git a/include/linux/netfilter/xt_connlimit.h b/include/linux/netfilter/xt_connlimit.h
index 7e3284b..0ca66e9 100644
--- a/include/linux/netfilter/xt_connlimit.h
+++ b/include/linux/netfilter/xt_connlimit.h
@@ -1,8 +1,15 @@
 #ifndef _XT_CONNLIMIT_H
 #define _XT_CONNLIMIT_H
 
+#include <linux/types.h>
+
 struct xt_connlimit_data;
 
+enum {
+	XT_CONNLIMIT_INVERT = 1 << 0,
+	XT_CONNLIMIT_DADDR  = 1 << 1,
+};
+
 struct xt_connlimit_info {
 	union {
 		union nf_inet_addr mask;
@@ -13,7 +20,14 @@ struct xt_connlimit_info {
 		};
 #endif
 	};
-	unsigned int limit, inverse;
+	unsigned int limit;
+	union {
+		/* revision 0 */
+		unsigned int inverse;
+
+		/* revision 1 */
+		__u32 flags;
+	};
 
 	/* Used internally by the kernel */
 	struct xt_connlimit_data *data __attribute__((aligned(8)));
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index 54f47a2..74b904d 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -58,4 +58,19 @@ struct xt_conntrack_mtinfo2 {
 	__u16 state_mask, status_mask;
 };
 
+struct xt_conntrack_mtinfo3 {
+	union nf_inet_addr origsrc_addr, origsrc_mask;
+	union nf_inet_addr origdst_addr, origdst_mask;
+	union nf_inet_addr replsrc_addr, replsrc_mask;
+	union nf_inet_addr repldst_addr, repldst_mask;
+	__u32 expires_min, expires_max;
+	__u16 l4proto;
+	__u16 origsrc_port, origdst_port;
+	__u16 replsrc_port, repldst_port;
+	__u16 match_flags, invert_flags;
+	__u16 state_mask, status_mask;
+	__u16 origsrc_port_high, origdst_port_high;
+	__u16 replsrc_port_high, repldst_port_high;
+};
+
 #endif /*_XT_CONNTRACK_H*/
diff --git a/include/linux/netfilter/xt_devgroup.h b/include/linux/netfilter/xt_devgroup.h
new file mode 100644
index 0000000..1babde0
--- /dev/null
+++ b/include/linux/netfilter/xt_devgroup.h
@@ -0,0 +1,21 @@
+#ifndef _XT_DEVGROUP_H
+#define _XT_DEVGROUP_H
+
+#include <linux/types.h>
+
+enum xt_devgroup_flags {
+	XT_DEVGROUP_MATCH_SRC	= 0x1,
+	XT_DEVGROUP_INVERT_SRC	= 0x2,
+	XT_DEVGROUP_MATCH_DST	= 0x4,
+	XT_DEVGROUP_INVERT_DST	= 0x8,
+};
+
+struct xt_devgroup_info {
+	__u32	flags;
+	__u32	src_group;
+	__u32	src_mask;
+	__u32	dst_group;
+	__u32	dst_mask;
+};
+
+#endif /* _XT_DEVGROUP_H */
diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h
index b0d28c6..9314723 100644
--- a/include/linux/netfilter/xt_quota.h
+++ b/include/linux/netfilter/xt_quota.h
@@ -1,6 +1,8 @@
 #ifndef _XT_QUOTA_H
 #define _XT_QUOTA_H
 
+#include <linux/types.h>
+
 enum xt_quota_flags {
 	XT_QUOTA_INVERT		= 0x1,
 };
@@ -9,9 +11,9 @@ enum xt_quota_flags {
 struct xt_quota_priv;
 
 struct xt_quota_info {
-	u_int32_t		flags;
-	u_int32_t		pad;
-	aligned_u64		quota;
+	__u32 flags;
+	__u32 pad;
+	__aligned_u64 quota;
 
 	/* Used internally by the kernel */
 	struct xt_quota_priv	*master;
diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h
new file mode 100644
index 0000000..081f1de
--- /dev/null
+++ b/include/linux/netfilter/xt_set.h
@@ -0,0 +1,56 @@
+#ifndef _XT_SET_H
+#define _XT_SET_H
+
+#include <linux/types.h>
+#include <linux/netfilter/ipset/ip_set.h>
+
+/* Revision 0 interface: backward compatible with netfilter/iptables */
+
+/*
+ * Option flags for kernel operations (xt_set_info_v0)
+ */
+#define IPSET_SRC		0x01	/* Source match/add */
+#define IPSET_DST		0x02	/* Destination match/add */
+#define IPSET_MATCH_INV		0x04	/* Inverse matching */
+
+struct xt_set_info_v0 {
+	ip_set_id_t index;
+	union {
+		__u32 flags[IPSET_DIM_MAX + 1];
+		struct {
+			__u32 __flags[IPSET_DIM_MAX];
+			__u8 dim;
+			__u8 flags;
+		} compat;
+	} u;
+};
+
+/* match and target infos */
+struct xt_set_info_match_v0 {
+	struct xt_set_info_v0 match_set;
+};
+
+struct xt_set_info_target_v0 {
+	struct xt_set_info_v0 add_set;
+	struct xt_set_info_v0 del_set;
+};
+
+/* Revision 1: current interface to netfilter/iptables */
+
+struct xt_set_info {
+	ip_set_id_t index;
+	__u8 dim;
+	__u8 flags;
+};
+
+/* match and target infos */
+struct xt_set_info_match {
+	struct xt_set_info match_set;
+};
+
+struct xt_set_info_target {
+	struct xt_set_info add_set;
+	struct xt_set_info del_set;
+};
+
+#endif /*_XT_SET_H*/
diff --git a/include/linux/netfilter/xt_socket.h b/include/linux/netfilter/xt_socket.h
index 6f475b8..26d7217 100644
--- a/include/linux/netfilter/xt_socket.h
+++ b/include/linux/netfilter/xt_socket.h
@@ -1,6 +1,8 @@
 #ifndef _XT_SOCKET_H
 #define _XT_SOCKET_H
 
+#include <linux/types.h>
+
 enum {
 	XT_SOCKET_TRANSPARENT = 1 << 0,
 };
diff --git a/include/linux/netfilter/xt_time.h b/include/linux/netfilter/xt_time.h
index 14b6df4..7c37fac 100644
--- a/include/linux/netfilter/xt_time.h
+++ b/include/linux/netfilter/xt_time.h
@@ -1,14 +1,16 @@
 #ifndef _XT_TIME_H
 #define _XT_TIME_H 1
 
+#include <linux/types.h>
+
 struct xt_time_info {
-	u_int32_t date_start;
-	u_int32_t date_stop;
-	u_int32_t daytime_start;
-	u_int32_t daytime_stop;
-	u_int32_t monthdays_match;
-	u_int8_t weekdays_match;
-	u_int8_t flags;
+	__u32 date_start;
+	__u32 date_stop;
+	__u32 daytime_start;
+	__u32 daytime_stop;
+	__u32 monthdays_match;
+	__u8 weekdays_match;
+	__u8 flags;
 };
 
 enum {
diff --git a/include/linux/netfilter/xt_u32.h b/include/linux/netfilter/xt_u32.h
index 9947f56..04d1bfe 100644
--- a/include/linux/netfilter/xt_u32.h
+++ b/include/linux/netfilter/xt_u32.h
@@ -1,6 +1,8 @@
 #ifndef _XT_U32_H
 #define _XT_U32_H 1
 
+#include <linux/types.h>
+
 enum xt_u32_ops {
 	XT_U32_AND,
 	XT_U32_LEFTSH,
@@ -9,13 +11,13 @@ enum xt_u32_ops {
 };
 
 struct xt_u32_location_element {
-	u_int32_t number;
-	u_int8_t nextop;
+	__u32 number;
+	__u8 nextop;
 };
 
 struct xt_u32_value_element {
-	u_int32_t min;
-	u_int32_t max;
+	__u32 min;
+	__u32 max;
 };
 
 /*
@@ -27,14 +29,14 @@ struct xt_u32_value_element {
 struct xt_u32_test {
 	struct xt_u32_location_element location[XT_U32_MAXSIZE+1];
 	struct xt_u32_value_element value[XT_U32_MAXSIZE+1];
-	u_int8_t nnums;
-	u_int8_t nvalues;
+	__u8 nnums;
+	__u8 nvalues;
 };
 
 struct xt_u32 {
 	struct xt_u32_test tests[XT_U32_MAXSIZE+1];
-	u_int8_t ntests;
-	u_int8_t invert;
+	__u8 ntests;
+	__u8 invert;
 };
 
 #endif /* _XT_U32_H */
diff --git a/include/linux/netfilter_bridge/ebt_802_3.h b/include/linux/netfilter_bridge/ebt_802_3.h
index c73ef0b..be5be15 100644
--- a/include/linux/netfilter_bridge/ebt_802_3.h
+++ b/include/linux/netfilter_bridge/ebt_802_3.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_802_3_H
 #define __LINUX_BRIDGE_EBT_802_3_H
 
+#include <linux/types.h>
+
 #define EBT_802_3_SAP 0x01
 #define EBT_802_3_TYPE 0x02
 
@@ -24,24 +26,24 @@
 
 /* ui has one byte ctrl, ni has two */
 struct hdr_ui {
-	uint8_t dsap;
-	uint8_t ssap;
-	uint8_t ctrl;
-	uint8_t orig[3];
+	__u8 dsap;
+	__u8 ssap;
+	__u8 ctrl;
+	__u8 orig[3];
 	__be16 type;
 };
 
 struct hdr_ni {
-	uint8_t dsap;
-	uint8_t ssap;
+	__u8 dsap;
+	__u8 ssap;
 	__be16 ctrl;
-	uint8_t  orig[3];
+	__u8  orig[3];
 	__be16 type;
 };
 
 struct ebt_802_3_hdr {
-	uint8_t  daddr[6];
-	uint8_t  saddr[6];
+	__u8  daddr[6];
+	__u8  saddr[6];
 	__be16 len;
 	union {
 		struct hdr_ui ui;
@@ -59,10 +61,10 @@ static inline struct ebt_802_3_hdr *ebt_802_3_hdr(const struct sk_buff *skb)
 #endif
 
 struct ebt_802_3_info {
-	uint8_t  sap;
+	__u8  sap;
 	__be16 type;
-	uint8_t  bitmask;
-	uint8_t  invflags;
+	__u8  bitmask;
+	__u8  invflags;
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_among.h b/include/linux/netfilter_bridge/ebt_among.h
index 0009558..bd4e3ad 100644
--- a/include/linux/netfilter_bridge/ebt_among.h
+++ b/include/linux/netfilter_bridge/ebt_among.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_AMONG_H
 #define __LINUX_BRIDGE_EBT_AMONG_H
 
+#include <linux/types.h>
+
 #define EBT_AMONG_DST 0x01
 #define EBT_AMONG_SRC 0x02
 
@@ -30,7 +32,7 @@
  */
 
 struct ebt_mac_wormhash_tuple {
-	uint32_t cmp[2];
+	__u32 cmp[2];
 	__be32 ip;
 };
 
diff --git a/include/linux/netfilter_bridge/ebt_arp.h b/include/linux/netfilter_bridge/ebt_arp.h
index cbf4843..522f3e4 100644
--- a/include/linux/netfilter_bridge/ebt_arp.h
+++ b/include/linux/netfilter_bridge/ebt_arp.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_ARP_H
 #define __LINUX_BRIDGE_EBT_ARP_H
 
+#include <linux/types.h>
+
 #define EBT_ARP_OPCODE 0x01
 #define EBT_ARP_HTYPE 0x02
 #define EBT_ARP_PTYPE 0x04
@@ -27,8 +29,8 @@ struct ebt_arp_info
 	unsigned char smmsk[ETH_ALEN];
 	unsigned char dmaddr[ETH_ALEN];
 	unsigned char dmmsk[ETH_ALEN];
-	uint8_t  bitmask;
-	uint8_t  invflags;
+	__u8  bitmask;
+	__u8  invflags;
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h
index 6a708fb..c4bbc41 100644
--- a/include/linux/netfilter_bridge/ebt_ip.h
+++ b/include/linux/netfilter_bridge/ebt_ip.h
@@ -15,6 +15,8 @@
 #ifndef __LINUX_BRIDGE_EBT_IP_H
 #define __LINUX_BRIDGE_EBT_IP_H
 
+#include <linux/types.h>
+
 #define EBT_IP_SOURCE 0x01
 #define EBT_IP_DEST 0x02
 #define EBT_IP_TOS 0x04
@@ -31,12 +33,12 @@ struct ebt_ip_info {
 	__be32 daddr;
 	__be32 smsk;
 	__be32 dmsk;
-	uint8_t  tos;
-	uint8_t  protocol;
-	uint8_t  bitmask;
-	uint8_t  invflags;
-	uint16_t sport[2];
-	uint16_t dport[2];
+	__u8  tos;
+	__u8  protocol;
+	__u8  bitmask;
+	__u8  invflags;
+	__u16 sport[2];
+	__u16 dport[2];
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_ip6.h b/include/linux/netfilter_bridge/ebt_ip6.h
index e5de987..42b8896 100644
--- a/include/linux/netfilter_bridge/ebt_ip6.h
+++ b/include/linux/netfilter_bridge/ebt_ip6.h
@@ -12,14 +12,19 @@
 #ifndef __LINUX_BRIDGE_EBT_IP6_H
 #define __LINUX_BRIDGE_EBT_IP6_H
 
+#include <linux/types.h>
+
 #define EBT_IP6_SOURCE 0x01
 #define EBT_IP6_DEST 0x02
 #define EBT_IP6_TCLASS 0x04
 #define EBT_IP6_PROTO 0x08
 #define EBT_IP6_SPORT 0x10
 #define EBT_IP6_DPORT 0x20
+#define EBT_IP6_ICMP6 0x40
+
 #define EBT_IP6_MASK (EBT_IP6_SOURCE | EBT_IP6_DEST | EBT_IP6_TCLASS |\
-		      EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT)
+		      EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT | \
+		      EBT_IP6_ICMP6)
 #define EBT_IP6_MATCH "ip6"
 
 /* the same values are used for the invflags */
@@ -28,12 +33,18 @@ struct ebt_ip6_info {
 	struct in6_addr daddr;
 	struct in6_addr smsk;
 	struct in6_addr dmsk;
-	uint8_t  tclass;
-	uint8_t  protocol;
-	uint8_t  bitmask;
-	uint8_t  invflags;
-	uint16_t sport[2];
-	uint16_t dport[2];
+	__u8  tclass;
+	__u8  protocol;
+	__u8  bitmask;
+	__u8  invflags;
+	union {
+		__u16 sport[2];
+		__u8 icmpv6_type[2];
+	};
+	union {
+		__u16 dport[2];
+		__u8 icmpv6_code[2];
+	};
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_limit.h b/include/linux/netfilter_bridge/ebt_limit.h
index 4bf76b7..66d80b3 100644
--- a/include/linux/netfilter_bridge/ebt_limit.h
+++ b/include/linux/netfilter_bridge/ebt_limit.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_LIMIT_H
 #define __LINUX_BRIDGE_EBT_LIMIT_H
 
+#include <linux/types.h>
+
 #define EBT_LIMIT_MATCH "limit"
 
 /* timings are in milliseconds. */
@@ -10,13 +12,13 @@
    seconds, or one every 59 hours. */
 
 struct ebt_limit_info {
-	u_int32_t avg;    /* Average secs between packets * scale */
-	u_int32_t burst;  /* Period multiplier for upper limit. */
+	__u32 avg;    /* Average secs between packets * scale */
+	__u32 burst;  /* Period multiplier for upper limit. */
 
 	/* Used internally by the kernel */
 	unsigned long prev;
-	u_int32_t credit;
-	u_int32_t credit_cap, cost;
+	__u32 credit;
+	__u32 credit_cap, cost;
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_log.h b/include/linux/netfilter_bridge/ebt_log.h
index cc2cdfb..7e7f1d1 100644
--- a/include/linux/netfilter_bridge/ebt_log.h
+++ b/include/linux/netfilter_bridge/ebt_log.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_LOG_H
 #define __LINUX_BRIDGE_EBT_LOG_H
 
+#include <linux/types.h>
+
 #define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */
 #define EBT_LOG_ARP 0x02
 #define EBT_LOG_NFLOG 0x04
@@ -10,9 +12,9 @@
 #define EBT_LOG_WATCHER "log"
 
 struct ebt_log_info {
-	uint8_t loglevel;
-	uint8_t prefix[EBT_LOG_PREFIX_SIZE];
-	uint32_t bitmask;
+	__u8 loglevel;
+	__u8 prefix[EBT_LOG_PREFIX_SIZE];
+	__u32 bitmask;
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_mark_m.h b/include/linux/netfilter_bridge/ebt_mark_m.h
index 9ceb10e..410f9e5 100644
--- a/include/linux/netfilter_bridge/ebt_mark_m.h
+++ b/include/linux/netfilter_bridge/ebt_mark_m.h
@@ -1,13 +1,15 @@
 #ifndef __LINUX_BRIDGE_EBT_MARK_M_H
 #define __LINUX_BRIDGE_EBT_MARK_M_H
 
+#include <linux/types.h>
+
 #define EBT_MARK_AND 0x01
 #define EBT_MARK_OR 0x02
 #define EBT_MARK_MASK (EBT_MARK_AND | EBT_MARK_OR)
 struct ebt_mark_m_info {
 	unsigned long mark, mask;
-	uint8_t invert;
-	uint8_t bitmask;
+	__u8 invert;
+	__u8 bitmask;
 };
 #define EBT_MARK_MATCH "mark_m"
 
diff --git a/include/linux/netfilter_bridge/ebt_nflog.h b/include/linux/netfilter_bridge/ebt_nflog.h
index 0528178..df829fc 100644
--- a/include/linux/netfilter_bridge/ebt_nflog.h
+++ b/include/linux/netfilter_bridge/ebt_nflog.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_NFLOG_H
 #define __LINUX_BRIDGE_EBT_NFLOG_H
 
+#include <linux/types.h>
+
 #define EBT_NFLOG_MASK 0x0
 
 #define EBT_NFLOG_PREFIX_SIZE 64
@@ -10,11 +12,11 @@
 #define EBT_NFLOG_DEFAULT_THRESHOLD	1
 
 struct ebt_nflog_info {
-	u_int32_t len;
-	u_int16_t group;
-	u_int16_t threshold;
-	u_int16_t flags;
-	u_int16_t pad;
+	__u32 len;
+	__u16 group;
+	__u16 threshold;
+	__u16 flags;
+	__u16 pad;
 	char prefix[EBT_NFLOG_PREFIX_SIZE];
 };
 
diff --git a/include/linux/netfilter_bridge/ebt_pkttype.h b/include/linux/netfilter_bridge/ebt_pkttype.h
index 51a7998..c241bad 100644
--- a/include/linux/netfilter_bridge/ebt_pkttype.h
+++ b/include/linux/netfilter_bridge/ebt_pkttype.h
@@ -1,9 +1,11 @@
 #ifndef __LINUX_BRIDGE_EBT_PKTTYPE_H
 #define __LINUX_BRIDGE_EBT_PKTTYPE_H
 
+#include <linux/types.h>
+
 struct ebt_pkttype_info {
-	uint8_t pkt_type;
-	uint8_t invert;
+	__u8 pkt_type;
+	__u8 invert;
 };
 #define EBT_PKTTYPE_MATCH "pkttype"
 
diff --git a/include/linux/netfilter_bridge/ebt_stp.h b/include/linux/netfilter_bridge/ebt_stp.h
index e503a0a..1025b9f 100644
--- a/include/linux/netfilter_bridge/ebt_stp.h
+++ b/include/linux/netfilter_bridge/ebt_stp.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_STP_H
 #define __LINUX_BRIDGE_EBT_STP_H
 
+#include <linux/types.h>
+
 #define EBT_STP_TYPE		0x0001
 
 #define EBT_STP_FLAGS		0x0002
@@ -21,24 +23,24 @@
 #define EBT_STP_MATCH "stp"
 
 struct ebt_stp_config_info {
-	uint8_t flags;
-	uint16_t root_priol, root_priou;
+	__u8 flags;
+	__u16 root_priol, root_priou;
 	char root_addr[6], root_addrmsk[6];
-	uint32_t root_costl, root_costu;
-	uint16_t sender_priol, sender_priou;
+	__u32 root_costl, root_costu;
+	__u16 sender_priol, sender_priou;
 	char sender_addr[6], sender_addrmsk[6];
-	uint16_t portl, portu;
-	uint16_t msg_agel, msg_ageu;
-	uint16_t max_agel, max_ageu;
-	uint16_t hello_timel, hello_timeu;
-	uint16_t forward_delayl, forward_delayu;
+	__u16 portl, portu;
+	__u16 msg_agel, msg_ageu;
+	__u16 max_agel, max_ageu;
+	__u16 hello_timel, hello_timeu;
+	__u16 forward_delayl, forward_delayu;
 };
 
 struct ebt_stp_info {
-	uint8_t type;
+	__u8 type;
 	struct ebt_stp_config_info config;
-	uint16_t bitmask;
-	uint16_t invflags;
+	__u16 bitmask;
+	__u16 invflags;
 };
 
 #endif
diff --git a/include/linux/netfilter_bridge/ebt_ulog.h b/include/linux/netfilter_bridge/ebt_ulog.h
index b677e26..89a6bec 100644
--- a/include/linux/netfilter_bridge/ebt_ulog.h
+++ b/include/linux/netfilter_bridge/ebt_ulog.h
@@ -1,6 +1,8 @@
 #ifndef _EBT_ULOG_H
 #define _EBT_ULOG_H
 
+#include <linux/types.h>
+
 #define EBT_ULOG_DEFAULT_NLGROUP 0
 #define EBT_ULOG_DEFAULT_QTHRESHOLD 1
 #define EBT_ULOG_MAXNLGROUPS 32 /* hardcoded netlink max */
@@ -10,7 +12,7 @@
 #define EBT_ULOG_VERSION 1
 
 struct ebt_ulog_info {
-	uint32_t nlgroup;
+	__u32 nlgroup;
 	unsigned int cprange;
 	unsigned int qthreshold;
 	char prefix[EBT_ULOG_PREFIX_LEN];
diff --git a/include/linux/netfilter_bridge/ebt_vlan.h b/include/linux/netfilter_bridge/ebt_vlan.h
index 1d98be4..967d1d5 100644
--- a/include/linux/netfilter_bridge/ebt_vlan.h
+++ b/include/linux/netfilter_bridge/ebt_vlan.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_BRIDGE_EBT_VLAN_H
 #define __LINUX_BRIDGE_EBT_VLAN_H
 
+#include <linux/types.h>
+
 #define EBT_VLAN_ID	0x01
 #define EBT_VLAN_PRIO	0x02
 #define EBT_VLAN_ENCAP	0x04
@@ -8,12 +10,12 @@
 #define EBT_VLAN_MATCH "vlan"
 
 struct ebt_vlan_info {
-	uint16_t id;		/* VLAN ID {1-4095} */
-	uint8_t prio;		/* VLAN User Priority {0-7} */
+	__u16 id;		/* VLAN ID {1-4095} */
+	__u8 prio;		/* VLAN User Priority {0-7} */
 	__be16 encap;		/* VLAN Encapsulated frame code {0-65535} */
-	uint8_t bitmask;		/* Args bitmask bit 1=1 - ID arg,
+	__u8 bitmask;		/* Args bitmask bit 1=1 - ID arg,
 				   bit 2=1 User-Priority arg, bit 3=1 encap*/
-	uint8_t invflags;		/* Inverse bitmask  bit 1=1 - inversed ID arg, 
+	__u8 invflags;		/* Inverse bitmask  bit 1=1 - inversed ID arg, 
 				   bit 2=1 - inversed Pirority arg */
 };
 
diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index e5a3687..c6a204c 100644
--- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -1,6 +1,8 @@
 #ifndef _IPT_CLUSTERIP_H_target
 #define _IPT_CLUSTERIP_H_target
 
+#include <linux/types.h>
+
 enum clusterip_hashmode {
     CLUSTERIP_HASHMODE_SIP = 0,
     CLUSTERIP_HASHMODE_SIP_SPT,
@@ -17,15 +19,15 @@ struct clusterip_config;
 
 struct ipt_clusterip_tgt_info {
 
-	u_int32_t flags;
+	__u32 flags;
 
 	/* only relevant for new ones */
-	u_int8_t clustermac[6];
-	u_int16_t num_total_nodes;
-	u_int16_t num_local_nodes;
-	u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
-	u_int32_t hash_mode;
-	u_int32_t hash_initval;
+	__u8 clustermac[6];
+	__u16 num_total_nodes;
+	__u16 num_local_nodes;
+	__u16 local_nodes[CLUSTERIP_MAX_NODES];
+	__u32 hash_mode;
+	__u32 hash_initval;
 
 	/* Used internally by the kernel */
 	struct clusterip_config *config;
diff --git a/include/linux/netfilter_ipv4/ipt_ECN.h b/include/linux/netfilter_ipv4/ipt_ECN.h
index 7ca4591..bb88d53 100644
--- a/include/linux/netfilter_ipv4/ipt_ECN.h
+++ b/include/linux/netfilter_ipv4/ipt_ECN.h
@@ -8,6 +8,8 @@
 */
 #ifndef _IPT_ECN_TARGET_H
 #define _IPT_ECN_TARGET_H
+
+#include <linux/types.h>
 #include <linux/netfilter/xt_DSCP.h>
 
 #define IPT_ECN_IP_MASK	(~XT_DSCP_MASK)
@@ -19,11 +21,11 @@
 #define IPT_ECN_OP_MASK		0xce
 
 struct ipt_ECN_info {
-	u_int8_t operation;	/* bitset of operations */
-	u_int8_t ip_ect;	/* ECT codepoint of IPv4 header, pre-shifted */
+	__u8 operation;	/* bitset of operations */
+	__u8 ip_ect;	/* ECT codepoint of IPv4 header, pre-shifted */
 	union {
 		struct {
-			u_int8_t ece:1, cwr:1; /* TCP ECT bits */
+			__u8 ece:1, cwr:1; /* TCP ECT bits */
 		} tcp;
 	} proto;
 };
diff --git a/include/linux/netfilter_ipv4/ipt_SAME.h b/include/linux/netfilter_ipv4/ipt_SAME.h
index 2529660..5bca782 100644
--- a/include/linux/netfilter_ipv4/ipt_SAME.h
+++ b/include/linux/netfilter_ipv4/ipt_SAME.h
@@ -1,15 +1,17 @@
 #ifndef _IPT_SAME_H
 #define _IPT_SAME_H
 
+#include <linux/types.h>
+
 #define IPT_SAME_MAX_RANGE	10
 
 #define IPT_SAME_NODST		0x01
 
 struct ipt_same_info {
 	unsigned char info;
-	u_int32_t rangesize;
-	u_int32_t ipnum;
-	u_int32_t *iparray;
+	__u32 rangesize;
+	__u32 ipnum;
+	__u32 *iparray;
 
 	/* hangs off end. */
 	struct nf_nat_range range[IPT_SAME_MAX_RANGE];
diff --git a/include/linux/netfilter_ipv4/ipt_TTL.h b/include/linux/netfilter_ipv4/ipt_TTL.h
index ee6611e..f6ac169 100644
--- a/include/linux/netfilter_ipv4/ipt_TTL.h
+++ b/include/linux/netfilter_ipv4/ipt_TTL.h
@@ -4,6 +4,8 @@
 #ifndef _IPT_TTL_H
 #define _IPT_TTL_H
 
+#include <linux/types.h>
+
 enum {
 	IPT_TTL_SET = 0,
 	IPT_TTL_INC,
@@ -13,8 +15,8 @@ enum {
 #define IPT_TTL_MAXMODE	IPT_TTL_DEC
 
 struct ipt_TTL_info {
-	u_int8_t	mode;
-	u_int8_t	ttl;
+	__u8	mode;
+	__u8	ttl;
 };
 
 
diff --git a/include/linux/netfilter_ipv4/ipt_addrtype.h b/include/linux/netfilter_ipv4/ipt_addrtype.h
index 446de6a..0da4223 100644
--- a/include/linux/netfilter_ipv4/ipt_addrtype.h
+++ b/include/linux/netfilter_ipv4/ipt_addrtype.h
@@ -1,6 +1,8 @@
 #ifndef _IPT_ADDRTYPE_H
 #define _IPT_ADDRTYPE_H
 
+#include <linux/types.h>
+
 enum {
 	IPT_ADDRTYPE_INVERT_SOURCE	= 0x0001,
 	IPT_ADDRTYPE_INVERT_DEST	= 0x0002,
@@ -9,17 +11,17 @@ enum {
 };
 
 struct ipt_addrtype_info_v1 {
-	u_int16_t	source;		/* source-type mask */
-	u_int16_t	dest;		/* dest-type mask */
-	u_int32_t	flags;
+	__u16	source;		/* source-type mask */
+	__u16	dest;		/* dest-type mask */
+	__u32	flags;
 };
 
 /* revision 0 */
 struct ipt_addrtype_info {
-	u_int16_t	source;		/* source-type mask */
-	u_int16_t	dest;		/* dest-type mask */
-	u_int32_t	invert_source;
-	u_int32_t	invert_dest;
+	__u16	source;		/* source-type mask */
+	__u16	dest;		/* dest-type mask */
+	__u32	invert_source;
+	__u32	invert_dest;
 };
 
 #endif
diff --git a/include/linux/netfilter_ipv4/ipt_ah.h b/include/linux/netfilter_ipv4/ipt_ah.h
index 2e555b4..4e02bb0 100644
--- a/include/linux/netfilter_ipv4/ipt_ah.h
+++ b/include/linux/netfilter_ipv4/ipt_ah.h
@@ -1,9 +1,11 @@
 #ifndef _IPT_AH_H
 #define _IPT_AH_H
 
+#include <linux/types.h>
+
 struct ipt_ah {
-	u_int32_t spis[2];			/* Security Parameter Index */
-	u_int8_t  invflags;			/* Inverse flags */
+	__u32 spis[2];			/* Security Parameter Index */
+	__u8  invflags;			/* Inverse flags */
 };
 
 
diff --git a/include/linux/netfilter_ipv4/ipt_ecn.h b/include/linux/netfilter_ipv4/ipt_ecn.h
index 9945baa..eabf95f 100644
--- a/include/linux/netfilter_ipv4/ipt_ecn.h
+++ b/include/linux/netfilter_ipv4/ipt_ecn.h
@@ -8,6 +8,8 @@
 */
 #ifndef _IPT_ECN_H
 #define _IPT_ECN_H
+
+#include <linux/types.h>
 #include <linux/netfilter/xt_dscp.h>
 
 #define IPT_ECN_IP_MASK	(~XT_DSCP_MASK)
@@ -20,12 +22,12 @@
 
 /* match info */
 struct ipt_ecn_info {
-	u_int8_t operation;
-	u_int8_t invert;
-	u_int8_t ip_ect;
+	__u8 operation;
+	__u8 invert;
+	__u8 ip_ect;
 	union {
 		struct {
-			u_int8_t ect;
+			__u8 ect;
 		} tcp;
 	} proto;
 };
diff --git a/include/linux/netfilter_ipv4/ipt_ttl.h b/include/linux/netfilter_ipv4/ipt_ttl.h
index ee24fd8..37bee44 100644
--- a/include/linux/netfilter_ipv4/ipt_ttl.h
+++ b/include/linux/netfilter_ipv4/ipt_ttl.h
@@ -4,6 +4,8 @@
 #ifndef _IPT_TTL_H
 #define _IPT_TTL_H
 
+#include <linux/types.h>
+
 enum {
 	IPT_TTL_EQ = 0,		/* equals */
 	IPT_TTL_NE,		/* not equals */
@@ -13,8 +15,8 @@ enum {
 
 
 struct ipt_ttl_info {
-	u_int8_t	mode;
-	u_int8_t	ttl;
+	__u8	mode;
+	__u8	ttl;
 };
 
 
diff --git a/include/linux/netfilter_ipv6/ip6t_HL.h b/include/linux/netfilter_ipv6/ip6t_HL.h
index afb7813..ebd8ead 100644
--- a/include/linux/netfilter_ipv6/ip6t_HL.h
+++ b/include/linux/netfilter_ipv6/ip6t_HL.h
@@ -5,6 +5,8 @@
 #ifndef _IP6T_HL_H
 #define _IP6T_HL_H
 
+#include <linux/types.h>
+
 enum {
 	IP6T_HL_SET = 0,
 	IP6T_HL_INC,
@@ -14,8 +16,8 @@ enum {
 #define IP6T_HL_MAXMODE	IP6T_HL_DEC
 
 struct ip6t_HL_info {
-	u_int8_t	mode;
-	u_int8_t	hop_limit;
+	__u8	mode;
+	__u8	hop_limit;
 };
 
 
diff --git a/include/linux/netfilter_ipv6/ip6t_REJECT.h b/include/linux/netfilter_ipv6/ip6t_REJECT.h
index 6be6504..205ed62 100644
--- a/include/linux/netfilter_ipv6/ip6t_REJECT.h
+++ b/include/linux/netfilter_ipv6/ip6t_REJECT.h
@@ -1,6 +1,8 @@
 #ifndef _IP6T_REJECT_H
 #define _IP6T_REJECT_H
 
+#include <linux/types.h>
+
 enum ip6t_reject_with {
 	IP6T_ICMP6_NO_ROUTE,
 	IP6T_ICMP6_ADM_PROHIBITED,
@@ -12,7 +14,7 @@ enum ip6t_reject_with {
 };
 
 struct ip6t_reject_info {
-	u_int32_t	with;	/* reject type */
+	__u32	with;	/* reject type */
 };
 
 #endif /*_IP6T_REJECT_H*/
diff --git a/include/linux/netfilter_ipv6/ip6t_ah.h b/include/linux/netfilter_ipv6/ip6t_ah.h
index 17a745c..5da2b65 100644
--- a/include/linux/netfilter_ipv6/ip6t_ah.h
+++ b/include/linux/netfilter_ipv6/ip6t_ah.h
@@ -1,11 +1,13 @@
 #ifndef _IP6T_AH_H
 #define _IP6T_AH_H
 
+#include <linux/types.h>
+
 struct ip6t_ah {
-	u_int32_t spis[2];			/* Security Parameter Index */
-	u_int32_t hdrlen;			/* Header Length */
-	u_int8_t  hdrres;			/* Test of the Reserved Filed */
-	u_int8_t  invflags;			/* Inverse flags */
+	__u32 spis[2];			/* Security Parameter Index */
+	__u32 hdrlen;			/* Header Length */
+	__u8  hdrres;			/* Test of the Reserved Filed */
+	__u8  invflags;			/* Inverse flags */
 };
 
 #define IP6T_AH_SPI 0x01
diff --git a/include/linux/netfilter_ipv6/ip6t_frag.h b/include/linux/netfilter_ipv6/ip6t_frag.h
index 3724d08..b47f61b 100644
--- a/include/linux/netfilter_ipv6/ip6t_frag.h
+++ b/include/linux/netfilter_ipv6/ip6t_frag.h
@@ -1,11 +1,13 @@
 #ifndef _IP6T_FRAG_H
 #define _IP6T_FRAG_H
 
+#include <linux/types.h>
+
 struct ip6t_frag {
-	u_int32_t ids[2];			/* Security Parameter Index */
-	u_int32_t hdrlen;			/* Header Length */
-	u_int8_t  flags;			/*  */
-	u_int8_t  invflags;			/* Inverse flags */
+	__u32 ids[2];			/* Security Parameter Index */
+	__u32 hdrlen;			/* Header Length */
+	__u8  flags;			/*  */
+	__u8  invflags;			/* Inverse flags */
 };
 
 #define IP6T_FRAG_IDS 		0x01
diff --git a/include/linux/netfilter_ipv6/ip6t_hl.h b/include/linux/netfilter_ipv6/ip6t_hl.h
index 5ef91b8..6e76dbc 100644
--- a/include/linux/netfilter_ipv6/ip6t_hl.h
+++ b/include/linux/netfilter_ipv6/ip6t_hl.h
@@ -5,6 +5,8 @@
 #ifndef _IP6T_HL_H
 #define _IP6T_HL_H
 
+#include <linux/types.h>
+
 enum {
 	IP6T_HL_EQ = 0,		/* equals */
 	IP6T_HL_NE,		/* not equals */
@@ -14,8 +16,8 @@ enum {
 
 
 struct ip6t_hl_info {
-	u_int8_t	mode;
-	u_int8_t	hop_limit;
+	__u8	mode;
+	__u8	hop_limit;
 };
 
 
diff --git a/include/linux/netfilter_ipv6/ip6t_ipv6header.h b/include/linux/netfilter_ipv6/ip6t_ipv6header.h
index 01dfd44..efae3a2 100644
--- a/include/linux/netfilter_ipv6/ip6t_ipv6header.h
+++ b/include/linux/netfilter_ipv6/ip6t_ipv6header.h
@@ -8,10 +8,12 @@ on whether they contain certain headers */
 #ifndef __IPV6HEADER_H
 #define __IPV6HEADER_H
 
+#include <linux/types.h>
+
 struct ip6t_ipv6header_info {
-	u_int8_t matchflags;
-	u_int8_t invflags;
-	u_int8_t modeflag;
+	__u8 matchflags;
+	__u8 invflags;
+	__u8 modeflag;
 };
 
 #define MASK_HOPOPTS    128
diff --git a/include/linux/netfilter_ipv6/ip6t_mh.h b/include/linux/netfilter_ipv6/ip6t_mh.h
index 18549bc..a7729a5 100644
--- a/include/linux/netfilter_ipv6/ip6t_mh.h
+++ b/include/linux/netfilter_ipv6/ip6t_mh.h
@@ -1,10 +1,12 @@
 #ifndef _IP6T_MH_H
 #define _IP6T_MH_H
 
+#include <linux/types.h>
+
 /* MH matching stuff */
 struct ip6t_mh {
-	u_int8_t types[2];	/* MH type range */
-	u_int8_t invflags;	/* Inverse flags */
+	__u8 types[2];	/* MH type range */
+	__u8 invflags;	/* Inverse flags */
 };
 
 /* Values for "invflags" field in struct ip6t_mh. */
diff --git a/include/linux/netfilter_ipv6/ip6t_opts.h b/include/linux/netfilter_ipv6/ip6t_opts.h
index 62d89bc..17d419a 100644
--- a/include/linux/netfilter_ipv6/ip6t_opts.h
+++ b/include/linux/netfilter_ipv6/ip6t_opts.h
@@ -1,14 +1,16 @@
 #ifndef _IP6T_OPTS_H
 #define _IP6T_OPTS_H
 
+#include <linux/types.h>
+
 #define IP6T_OPTS_OPTSNR 16
 
 struct ip6t_opts {
-	u_int32_t hdrlen;			/* Header Length */
-	u_int8_t flags;				/*  */
-	u_int8_t invflags;			/* Inverse flags */
-	u_int16_t opts[IP6T_OPTS_OPTSNR];	/* opts */
-	u_int8_t optsnr;			/* Nr of OPts */
+	__u32 hdrlen;			/* Header Length */
+	__u8 flags;				/*  */
+	__u8 invflags;			/* Inverse flags */
+	__u16 opts[IP6T_OPTS_OPTSNR];	/* opts */
+	__u8 optsnr;			/* Nr of OPts */
 };
 
 #define IP6T_OPTS_LEN 		0x01
diff --git a/include/linux/netfilter_ipv6/ip6t_rt.h b/include/linux/netfilter_ipv6/ip6t_rt.h
index ab91bfd..7605a5f 100644
--- a/include/linux/netfilter_ipv6/ip6t_rt.h
+++ b/include/linux/netfilter_ipv6/ip6t_rt.h
@@ -1,18 +1,19 @@
 #ifndef _IP6T_RT_H
 #define _IP6T_RT_H
 
+#include <linux/types.h>
 /*#include <linux/in6.h>*/
 
 #define IP6T_RT_HOPS 16
 
 struct ip6t_rt {
-	u_int32_t rt_type;			/* Routing Type */
-	u_int32_t segsleft[2];			/* Segments Left */
-	u_int32_t hdrlen;			/* Header Length */
-	u_int8_t  flags;			/*  */
-	u_int8_t  invflags;			/* Inverse flags */
+	__u32 rt_type;			/* Routing Type */
+	__u32 segsleft[2];			/* Segments Left */
+	__u32 hdrlen;			/* Header Length */
+	__u8  flags;			/*  */
+	__u8  invflags;			/* Inverse flags */
 	struct in6_addr addrs[IP6T_RT_HOPS];	/* Hops */
-	u_int8_t addrnr;			/* Nr of Addresses */
+	__u8 addrnr;			/* Nr of Addresses */
 };
 
 #define IP6T_RT_TYP 		0x01
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index e2b9e63..4c4ac3f 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -160,10 +160,6 @@ struct netlink_skb_parms {
 	struct ucred		creds;		/* Skb credentials	*/
 	__u32			pid;
 	__u32			dst_group;
-	kernel_cap_t		eff_cap;
-	__u32			loginuid;	/* Login (audit) uid */
-	__u32			sessionid;	/* Session id (audit) */
-	__u32			sid;		/* SELinux security id */
 };
 
 #define NETLINK_CB(skb)		(*(struct netlink_skb_parms*)&((skb)->cb))
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 6023efa..f88522b 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -501,7 +501,7 @@ extern int  nfs_writepage(struct page *page, struct writeback_control *wbc);
 extern int  nfs_writepages(struct address_space *, struct writeback_control *);
 extern int  nfs_flush_incompatible(struct file *file, struct page *page);
 extern int  nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
-extern int nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
+extern void nfs_writeback_done(struct rpc_task *, struct nfs_write_data *);
 
 /*
  * Try to write back everything synchronously (but check the
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 3e112de..216cea5 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -30,6 +30,8 @@ struct nfs_client {
 #define NFS_CS_CALLBACK		1		/* - callback started */
 #define NFS_CS_IDMAP		2		/* - idmap started */
 #define NFS_CS_RENEWD		3		/* - renewd started */
+#define NFS_CS_STOP_RENEW	4		/* no more state to renew */
+#define NFS_CS_CHECK_LEASE_TIME	5		/* need to check lease time */
 	struct sockaddr_storage	cl_addr;	/* server identifier */
 	size_t			cl_addrlen;
 	char *			cl_hostname;	/* hostname of server */
@@ -75,7 +77,6 @@ struct nfs_client {
 	u32			cl_exchange_flags;
 	struct nfs4_session	*cl_session; 	/* sharred session */
 	struct list_head	cl_layouts;
-	struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */
 #endif /* CONFIG_NFS_V4 */
 
 #ifdef CONFIG_NFS_FSCACHE
@@ -176,6 +177,7 @@ struct nfs_server {
 #define NFS_CAP_CTIME		(1U << 12)
 #define NFS_CAP_MTIME		(1U << 13)
 #define NFS_CAP_POSIX_LOCK	(1U << 14)
+#define NFS_CAP_UIDGID_NOMAP	(1U << 15)
 
 
 /* maximum number of slots to use */
diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h
index e8352dc..ae7d6a3 100644
--- a/include/linux/nfs_idmap.h
+++ b/include/linux/nfs_idmap.h
@@ -65,6 +65,7 @@ struct idmap_msg {
 
 /* Forward declaration to make this header independent of others */
 struct nfs_client;
+struct nfs_server;
 
 #ifdef CONFIG_NFS_USE_NEW_IDMAPPER
 
@@ -96,10 +97,10 @@ void nfs_idmap_delete(struct nfs_client *);
 
 #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
 
-int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *);
-int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *);
-int nfs_map_uid_to_name(struct nfs_client *, __u32, char *, size_t);
-int nfs_map_gid_to_group(struct nfs_client *, __u32, char *, size_t);
+int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *);
+int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *);
+int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t);
+int nfs_map_gid_to_group(const struct nfs_server *, __u32, char *, size_t);
 
 extern unsigned int nfs_idmap_cache_timeout;
 #endif /* __KERNEL__ */
diff --git a/include/linux/nfs_iostat.h b/include/linux/nfs_iostat.h
index 68b10f5..8866bb3 100644
--- a/include/linux/nfs_iostat.h
+++ b/include/linux/nfs_iostat.h
@@ -113,6 +113,8 @@ enum nfs_stat_eventcounters {
 	NFSIOS_SHORTREAD,
 	NFSIOS_SHORTWRITE,
 	NFSIOS_DELAY,
+	NFSIOS_PNFS_READ,
+	NFSIOS_PNFS_WRITE,
 	__NFSIOS_COUNTSMAX,
 };
 
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index d55cee7..90907ad 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -59,9 +59,11 @@ struct nfs_pageio_descriptor {
 	unsigned int		pg_base;
 
 	struct inode		*pg_inode;
-	int			(*pg_doio)(struct inode *, struct list_head *, unsigned int, size_t, int);
+	int			(*pg_doio)(struct nfs_pageio_descriptor *);
 	int 			pg_ioflags;
 	int			pg_error;
+	struct pnfs_layout_segment *pg_lseg;
+	int			(*pg_test)(struct nfs_pageio_descriptor *, struct nfs_page *, struct nfs_page *);
 };
 
 #define NFS_WBACK_BUSY(req)	(test_bit(PG_BUSY,&(req)->wb_flags))
@@ -79,7 +81,7 @@ extern	int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *dst,
 			  pgoff_t idx_start, unsigned int npages, int tag);
 extern	void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
 			     struct inode *inode,
-			     int (*doio)(struct inode *, struct list_head *, unsigned int, size_t, int),
+			     int (*doio)(struct nfs_pageio_descriptor *desc),
 			     size_t bsize,
 			     int how);
 extern	int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index b006857..2c2c67d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1016,9 +1016,12 @@ struct nfs_read_data {
 	unsigned int		npages;	/* Max length of pagevec */
 	struct nfs_readargs args;
 	struct nfs_readres  res;
-#ifdef CONFIG_NFS_V4
 	unsigned long		timestamp;	/* For lease renewal */
-#endif
+	struct pnfs_layout_segment *lseg;
+	struct nfs_client	*ds_clp;	/* pNFS data server */
+	const struct rpc_call_ops *mds_ops;
+	int (*read_done_cb) (struct rpc_task *task, struct nfs_read_data *data);
+	__u64			mds_offset;
 	struct page		*page_array[NFS_PAGEVEC_SIZE];
 };
 
@@ -1035,13 +1038,20 @@ struct nfs_write_data {
 	unsigned int		npages;		/* Max length of pagevec */
 	struct nfs_writeargs	args;		/* argument struct */
 	struct nfs_writeres	res;		/* result struct */
+	struct pnfs_layout_segment *lseg;
+	struct nfs_client	*ds_clp;	/* pNFS data server */
+	const struct rpc_call_ops *mds_ops;
+	int (*write_done_cb) (struct rpc_task *task, struct nfs_write_data *data);
 #ifdef CONFIG_NFS_V4
 	unsigned long		timestamp;	/* For lease renewal */
 #endif
+	__u64			mds_offset;	/* Filelayout dense stripe */
 	struct page		*page_array[NFS_PAGEVEC_SIZE];
 };
 
 struct nfs_access_entry;
+struct nfs_client;
+struct rpc_timeout;
 
 /*
  * RPC procedure vector for NFSv2/NFSv3 demuxing
@@ -1106,6 +1116,8 @@ struct nfs_rpc_ops {
 				struct nfs_open_context *ctx,
 				int open_flags,
 				struct iattr *iattr);
+	int	(*init_client) (struct nfs_client *, const struct rpc_timeout *,
+				const char *, rpc_authflavor_t, int);
 };
 
 /*
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h
index 227e49d..8768c46 100644
--- a/include/linux/nilfs2_fs.h
+++ b/include/linux/nilfs2_fs.h
@@ -40,26 +40,7 @@
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
-
-/*
- * Inode flags stored in nilfs_inode and on-memory nilfs inode
- *
- * We define these flags based on ext2-fs because of the
- * compatibility reason; to avoid problems in chattr(1)
- */
-#define NILFS_SECRM_FL		0x00000001 /* Secure deletion */
-#define NILFS_UNRM_FL		0x00000002 /* Undelete */
-#define NILFS_SYNC_FL		0x00000008 /* Synchronous updates */
-#define NILFS_IMMUTABLE_FL	0x00000010 /* Immutable file */
-#define NILFS_APPEND_FL		0x00000020 /* writes to file may only append */
-#define NILFS_NODUMP_FL		0x00000040 /* do not dump file */
-#define NILFS_NOATIME_FL	0x00000080 /* do not update atime */
-/* Reserved for compression usage... */
-#define NILFS_NOTAIL_FL		0x00008000 /* file tail should not be merged */
-#define NILFS_DIRSYNC_FL	0x00010000 /* dirsync behaviour */
-
-#define NILFS_FL_USER_VISIBLE	0x0003DFFF /* User visible flags */
-#define NILFS_FL_USER_MODIFIABLE	0x000380FF /* User modifiable flags */
+#include <linux/magic.h>
 
 
 #define NILFS_INODE_BMAP_SIZE	7
@@ -236,8 +217,10 @@ struct nilfs_super_block {
  * If there is a bit set in the incompatible feature set that the kernel
  * doesn't know about, it should refuse to mount the filesystem.
  */
+#define NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT	0x00000001ULL
+
 #define NILFS_FEATURE_COMPAT_SUPP	0ULL
-#define NILFS_FEATURE_COMPAT_RO_SUPP	0ULL
+#define NILFS_FEATURE_COMPAT_RO_SUPP	NILFS_FEATURE_COMPAT_RO_BLOCK_COUNT
 #define NILFS_FEATURE_INCOMPAT_SUPP	0ULL
 
 /*
@@ -260,7 +243,6 @@ struct nilfs_super_block {
 #define NILFS_USER_INO		11	/* Fisrt user's file inode number */
 
 #define NILFS_SB_OFFSET_BYTES	1024	/* byte offset of nilfs superblock */
-#define NILFS_SUPER_MAGIC	0x3434	/* NILFS filesystem  magic number */
 
 #define NILFS_SEG_MIN_BLOCKS	16	/* Minimum number of blocks in
 					   a full segment */
@@ -346,17 +328,21 @@ static inline unsigned nilfs_rec_len_from_disk(__le16 dlen)
 {
 	unsigned len = le16_to_cpu(dlen);
 
+#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
 	if (len == NILFS_MAX_REC_LEN)
 		return 1 << 16;
+#endif
 	return len;
 }
 
 static inline __le16 nilfs_rec_len_to_disk(unsigned len)
 {
+#if !defined(__KERNEL__) || (PAGE_CACHE_SIZE >= 65536)
 	if (len == (1 << 16))
 		return cpu_to_le16(NILFS_MAX_REC_LEN);
 	else if (len > (1 << 16))
 		BUG();
+#endif
 	return cpu_to_le16(len);
 }
 
@@ -525,7 +511,7 @@ struct nilfs_checkpoint {
 	__le64 cp_create;
 	__le64 cp_nblk_inc;
 	__le64 cp_inodes_count;
-	__le64 cp_blocks_count;		/* Reserved (might be deleted) */
+	__le64 cp_blocks_count;
 
 	/* Do not change the byte offset of ifile inode.
 	   To keep the compatibility of the disk format,
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 821ffb9..3002218 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1243,6 +1243,8 @@ enum nl80211_rate_info {
  * @NL80211_STA_INFO_LLID: the station's mesh LLID
  * @NL80211_STA_INFO_PLID: the station's mesh PLID
  * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station
+ * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested
+ *	attribute, like NL80211_STA_INFO_TX_BITRATE.
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
  */
@@ -1261,6 +1263,7 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_TX_RETRIES,
 	NL80211_STA_INFO_TX_FAILED,
 	NL80211_STA_INFO_SIGNAL_AVG,
+	NL80211_STA_INFO_RX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/linux/node.h b/include/linux/node.h
index 1466945..92370e2 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -39,7 +39,8 @@ extern int register_cpu_under_node(unsigned int cpu, unsigned int nid);
 extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
 extern int register_mem_sect_under_node(struct memory_block *mem_blk,
 						int nid);
-extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk);
+extern int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+					   unsigned long phys_index);
 
 #ifdef CONFIG_HUGETLBFS
 extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
@@ -67,7 +68,8 @@ static inline int register_mem_sect_under_node(struct memory_block *mem_blk,
 {
 	return 0;
 }
-static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+static inline int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+						  unsigned long phys_index)
 {
 	return 0;
 }
diff --git a/include/linux/of.h b/include/linux/of.h
index cad7cf0..bfc0ed1 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -23,8 +23,6 @@
 
 #include <asm/byteorder.h>
 
-#ifdef CONFIG_OF
-
 typedef u32 phandle;
 typedef u32 ihandle;
 
@@ -65,11 +63,18 @@ struct device_node {
 #endif
 };
 
+#ifdef CONFIG_OF
+
 /* Pointer for first entry in chain of all nodes. */
 extern struct device_node *allnodes;
 extern struct device_node *of_chosen;
 extern rwlock_t devtree_lock;
 
+static inline bool of_have_populated_dt(void)
+{
+	return allnodes != NULL;
+}
+
 static inline bool of_node_is_root(const struct device_node *node)
 {
 	return node && (node->parent == NULL);
@@ -103,7 +108,7 @@ extern void of_node_put(struct device_node *node);
 #endif
 
 /*
- * OF address retreival & translation
+ * OF address retrieval & translation
  */
 
 /* Helper to read a big number; size is in cells (not bytes) */
@@ -222,5 +227,12 @@ extern void of_attach_node(struct device_node *);
 extern void of_detach_node(struct device_node *);
 #endif
 
+#else
+
+static inline bool of_have_populated_dt(void)
+{
+	return false;
+}
+
 #endif /* CONFIG_OF */
 #endif /* _LINUX_OF_H */
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 975d347..8bfe6c1 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -18,10 +18,11 @@ extern void of_device_make_bus_id(struct device *dev);
  * @drv: the device_driver structure to test
  * @dev: the device structure to match against
  */
-static inline int of_driver_match_device(const struct device *dev,
+static inline int of_driver_match_device(struct device *dev,
 					 const struct device_driver *drv)
 {
-	return of_match_device(drv->of_match_table, dev) != NULL;
+	dev->of_match = of_match_device(drv->of_match_table, dev);
+	return dev->of_match != NULL;
 }
 
 extern struct platform_device *of_dev_get(struct platform_device *dev);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
new file mode 100644
index 0000000..85a27b6
--- /dev/null
+++ b/include/linux/of_pci.h
@@ -0,0 +1,9 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+struct pci_dev;
+struct of_irq;
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
+#endif
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index a68716a..17c7e21 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -23,13 +23,7 @@
  * of_platform_driver - Legacy of-aware driver for platform devices.
  *
  * An of_platform_driver driver is attached to a basic platform_device on
- * ether the "platform bus" (platform_bus_type), or the ibm ebus
- * (ibmebus_bus_type).
- *
- * of_platform_driver is being phased out when used with the platform_bus_type,
- * and regular platform_drivers should be used instead.  When the transition
- * is complete, only ibmebus will be using this structure, and the
- * platform_driver member of this structure will be removed.
+ * the ibm ebus (ibmebus_bus_type).
  */
 struct of_platform_driver
 {
@@ -42,26 +36,16 @@ struct of_platform_driver
 	int	(*shutdown)(struct platform_device* dev);
 
 	struct device_driver	driver;
-	struct platform_driver	platform_driver;
 };
 #define	to_of_platform_driver(drv) \
 	container_of(drv,struct of_platform_driver, driver)
 
-extern int of_register_driver(struct of_platform_driver *drv,
-			      struct bus_type *bus);
-extern void of_unregister_driver(struct of_platform_driver *drv);
-
 /* Platform drivers register/unregister */
-extern int of_register_platform_driver(struct of_platform_driver *drv);
-extern void of_unregister_platform_driver(struct of_platform_driver *drv);
-
 extern struct platform_device *of_device_alloc(struct device_node *np,
 					 const char *bus_id,
 					 struct device *parent);
 extern struct platform_device *of_find_device_by_node(struct device_node *np);
 
-extern int of_bus_type_init(struct bus_type *bus, const char *name);
-
 #if !defined(CONFIG_SPARC) /* SPARC has its own device registration method */
 /* Platform devices and busses creation */
 extern struct platform_device *of_platform_device_create(struct device_node *np,
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h
index 1ca6411..7f5cfd3 100644
--- a/include/linux/oprofile.h
+++ b/include/linux/oprofile.h
@@ -106,6 +106,13 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event);
 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
 				unsigned long event, int is_kernel);
 
+/**
+ * Add an hardware sample.
+ */
+void oprofile_add_ext_hw_sample(unsigned long pc, struct pt_regs * const regs,
+	unsigned long event, int is_kernel,
+	struct task_struct *task);
+
 /* Use this instead when the PC value is not from the regs. Doesn't
  * backtrace. */
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 0db8037..811183d 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -196,7 +196,7 @@ static inline int __TestClearPage##uname(struct page *page) { return 0; }
 
 struct page;	/* forward declaration */
 
-TESTPAGEFLAG(Locked, locked) TESTSETFLAG(Locked, locked)
+TESTPAGEFLAG(Locked, locked)
 PAGEFLAG(Error, error) TESTCLEARFLAG(Error, error)
 PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
 PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 9c66e99..29ebba5 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -455,8 +455,9 @@ int add_to_page_cache_locked(struct page *page, struct address_space *mapping,
 				pgoff_t index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
 				pgoff_t index, gfp_t gfp_mask);
-extern void remove_from_page_cache(struct page *page);
-extern void __remove_from_page_cache(struct page *page);
+extern void delete_from_page_cache(struct page *page);
+extern void __delete_from_page_cache(struct page *page);
+int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask);
 
 /*
  * Like add_to_page_cache_locked, but used to add newly allocated pages:
diff --git a/include/linux/pata_arasan_cf_data.h b/include/linux/pata_arasan_cf_data.h
new file mode 100644
index 0000000..a6ee9aa
--- /dev/null
+++ b/include/linux/pata_arasan_cf_data.h
@@ -0,0 +1,49 @@
+/*
+ * include/linux/pata_arasan_cf_data.h
+ *
+ * Arasan Compact Flash host controller platform data header file
+ *
+ * Copyright (C) 2011 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef _PATA_ARASAN_CF_DATA_H
+#define _PATA_ARASAN_CF_DATA_H
+
+#include <linux/platform_device.h>
+
+struct arasan_cf_pdata {
+	u8 cf_if_clk;
+	#define CF_IF_CLK_100M			(0x0)
+	#define CF_IF_CLK_75M			(0x1)
+	#define CF_IF_CLK_66M			(0x2)
+	#define CF_IF_CLK_50M			(0x3)
+	#define CF_IF_CLK_40M			(0x4)
+	#define CF_IF_CLK_33M			(0x5)
+	#define CF_IF_CLK_25M			(0x6)
+	#define CF_IF_CLK_125M			(0x7)
+	#define CF_IF_CLK_150M			(0x8)
+	#define CF_IF_CLK_166M			(0x9)
+	#define CF_IF_CLK_200M			(0xA)
+	/*
+	 * Platform specific incapabilities of CF controller is handled via
+	 * quirks
+	 */
+	u32 quirk;
+	#define CF_BROKEN_PIO			(1)
+	#define CF_BROKEN_MWDMA			(1 << 1)
+	#define CF_BROKEN_UDMA			(1 << 2)
+	/* This is platform specific data for the DMA controller */
+	void *dma_priv;
+};
+
+static inline void
+set_arasan_cf_pdata(struct platform_device *pdev, struct arasan_cf_pdata *data)
+{
+	pdev->dev.platform_data = data;
+}
+#endif /* _PATA_ARASAN_CF_DATA_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 559d028..16c9f2e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1191,6 +1191,11 @@ static inline int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 	return 0;
 }
 
+static inline int pci_wake_from_d3(struct pci_dev *dev, bool enable)
+{
+	return 0;
+}
+
 static inline pci_power_t pci_choose_state(struct pci_dev *dev,
 					   pm_message_t state)
 {
@@ -1479,6 +1484,7 @@ void pci_request_acs(void);
 #define PCI_VPD_RO_KEYWORD_PARTNO	"PN"
 #define PCI_VPD_RO_KEYWORD_MFR_ID	"MN"
 #define PCI_VPD_RO_KEYWORD_VENDOR0	"V0"
+#define PCI_VPD_RO_KEYWORD_CHKSUM	"RV"
 
 /**
  * pci_vpd_lrdt_size - Extracts the Large Resource Data Type length
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 3adb06e..bda221d 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -517,7 +517,8 @@
 #define PCI_DEVICE_ID_AMD_11H_NB_DRAM	0x1302
 #define PCI_DEVICE_ID_AMD_11H_NB_MISC	0x1303
 #define PCI_DEVICE_ID_AMD_11H_NB_LINK	0x1304
-#define PCI_DEVICE_ID_AMD_15H_NB_MISC	0x1603
+#define PCI_DEVICE_ID_AMD_15H_NB_F3	0x1603
+#define PCI_DEVICE_ID_AMD_15H_NB_LINK	0x1604
 #define PCI_DEVICE_ID_AMD_CNB17H_F3	0x1703
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
@@ -2078,6 +2079,8 @@
 #define PCI_DEVICE_ID_TIGON3_5723	0x165b
 #define PCI_DEVICE_ID_TIGON3_5705M	0x165d
 #define PCI_DEVICE_ID_TIGON3_5705M_2	0x165e
+#define PCI_DEVICE_ID_NX2_57712		0x1662
+#define PCI_DEVICE_ID_NX2_57712E	0x1663
 #define PCI_DEVICE_ID_TIGON3_5714	0x1668
 #define PCI_DEVICE_ID_TIGON3_5714S	0x1669
 #define PCI_DEVICE_ID_TIGON3_5780	0x166a
@@ -2480,6 +2483,9 @@
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS	0x1d22
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0	0x1d40
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1	0x1d41
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN	0x2310
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX	0x231f
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330
 #define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3	0x2413
diff --git a/include/linux/percpu.h b/include/linux/percpu.h
index 27c3c6f..3a5c444 100644
--- a/include/linux/percpu.h
+++ b/include/linux/percpu.h
@@ -255,6 +255,30 @@ extern void __bad_size_call_parameter(void);
 	pscr2_ret__;							\
 })
 
+/*
+ * Special handling for cmpxchg_double.  cmpxchg_double is passed two
+ * percpu variables.  The first has to be aligned to a double word
+ * boundary and the second has to follow directly thereafter.
+ */
+#define __pcpu_double_call_return_bool(stem, pcp1, pcp2, ...)		\
+({									\
+	bool pdcrb_ret__;						\
+	__verify_pcpu_ptr(&pcp1);					\
+	BUILD_BUG_ON(sizeof(pcp1) != sizeof(pcp2));			\
+	VM_BUG_ON((unsigned long)(&pcp1) % (2 * sizeof(pcp1)));		\
+	VM_BUG_ON((unsigned long)(&pcp2) !=				\
+		  (unsigned long)(&pcp1) + sizeof(pcp1));		\
+	switch(sizeof(pcp1)) {						\
+	case 1: pdcrb_ret__ = stem##1(pcp1, pcp2, __VA_ARGS__); break;	\
+	case 2: pdcrb_ret__ = stem##2(pcp1, pcp2, __VA_ARGS__); break;	\
+	case 4: pdcrb_ret__ = stem##4(pcp1, pcp2, __VA_ARGS__); break;	\
+	case 8: pdcrb_ret__ = stem##8(pcp1, pcp2, __VA_ARGS__); break;	\
+	default:							\
+		__bad_size_call_parameter(); break;			\
+	}								\
+	pdcrb_ret__;							\
+})
+
 #define __pcpu_size_call(stem, variable, ...)				\
 do {									\
 	__verify_pcpu_ptr(&(variable));					\
@@ -501,6 +525,45 @@ do {									\
 #endif
 
 /*
+ * cmpxchg_double replaces two adjacent scalars at once.  The first
+ * two parameters are per cpu variables which have to be of the same
+ * size.  A truth value is returned to indicate success or failure
+ * (since a double register result is difficult to handle).  There is
+ * very limited hardware support for these operations, so only certain
+ * sizes may work.
+ */
+#define _this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+({									\
+	int ret__;							\
+	preempt_disable();						\
+	ret__ = __this_cpu_generic_cmpxchg_double(pcp1, pcp2,		\
+			oval1, oval2, nval1, nval2);			\
+	preempt_enable();						\
+	ret__;								\
+})
+
+#ifndef this_cpu_cmpxchg_double
+# ifndef this_cpu_cmpxchg_double_1
+#  define this_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	_this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef this_cpu_cmpxchg_double_2
+#  define this_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	_this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef this_cpu_cmpxchg_double_4
+#  define this_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	_this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef this_cpu_cmpxchg_double_8
+#  define this_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	_this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# define this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__pcpu_double_call_return_bool(this_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
+#endif
+
+/*
  * Generic percpu operations that do not require preemption handling.
  * Either we do not care about races or the caller has the
  * responsibility of handling preemptions issues. Arch code can still
@@ -703,6 +766,39 @@ do {									\
 	__pcpu_size_call_return2(__this_cpu_cmpxchg_, pcp, oval, nval)
 #endif
 
+#define __this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+({									\
+	int __ret = 0;							\
+	if (__this_cpu_read(pcp1) == (oval1) &&				\
+			 __this_cpu_read(pcp2)  == (oval2)) {		\
+		__this_cpu_write(pcp1, (nval1));			\
+		__this_cpu_write(pcp2, (nval2));			\
+		__ret = 1;						\
+	}								\
+	(__ret);							\
+})
+
+#ifndef __this_cpu_cmpxchg_double
+# ifndef __this_cpu_cmpxchg_double_1
+#  define __this_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef __this_cpu_cmpxchg_double_2
+#  define __this_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef __this_cpu_cmpxchg_double_4
+#  define __this_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef __this_cpu_cmpxchg_double_8
+#  define __this_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__this_cpu_generic_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# define __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__pcpu_double_call_return_bool(__this_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
+#endif
+
 /*
  * IRQ safe versions of the per cpu RMW operations. Note that these operations
  * are *not* safe against modification of the same variable from another
@@ -823,4 +919,36 @@ do {									\
 	__pcpu_size_call_return2(irqsafe_cpu_cmpxchg_, (pcp), oval, nval)
 #endif
 
+#define irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+({									\
+	int ret__;							\
+	unsigned long flags;						\
+	local_irq_save(flags);						\
+	ret__ = __this_cpu_generic_cmpxchg_double(pcp1, pcp2,		\
+			oval1, oval2, nval1, nval2);			\
+	local_irq_restore(flags);					\
+	ret__;								\
+})
+
+#ifndef irqsafe_cpu_cmpxchg_double
+# ifndef irqsafe_cpu_cmpxchg_double_1
+#  define irqsafe_cpu_cmpxchg_double_1(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_double_2
+#  define irqsafe_cpu_cmpxchg_double_2(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_double_4
+#  define irqsafe_cpu_cmpxchg_double_4(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# ifndef irqsafe_cpu_cmpxchg_double_8
+#  define irqsafe_cpu_cmpxchg_double_8(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+# endif
+# define irqsafe_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)	\
+	__pcpu_double_call_return_int(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
+#endif
+
 #endif /* __LINUX_PERCPU_H */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index dda5b0a..f495c01 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -225,8 +225,14 @@ struct perf_event_attr {
 	};
 
 	__u32			bp_type;
-	__u64			bp_addr;
-	__u64			bp_len;
+	union {
+		__u64		bp_addr;
+		__u64		config1; /* extension of config */
+	};
+	union {
+		__u64		bp_len;
+		__u64		config2; /* extension of config1 */
+	};
 };
 
 /*
@@ -464,6 +470,7 @@ enum perf_callchain_context {
 
 #define PERF_FLAG_FD_NO_GROUP	(1U << 0)
 #define PERF_FLAG_FD_OUTPUT	(1U << 1)
+#define PERF_FLAG_PID_CGROUP	(1U << 2) /* pid=cgroup id, per-cpu mode only */
 
 #ifdef __KERNEL__
 /*
@@ -471,6 +478,7 @@ enum perf_callchain_context {
  */
 
 #ifdef CONFIG_PERF_EVENTS
+# include <linux/cgroup.h>
 # include <asm/perf_event.h>
 # include <asm/local64.h>
 #endif
@@ -539,6 +547,9 @@ struct hw_perf_event {
 			unsigned long	event_base;
 			int		idx;
 			int		last_cpu;
+			unsigned int	extra_reg;
+			u64		extra_config;
+			int		extra_alloc;
 		};
 		struct { /* software */
 			struct hrtimer	hrtimer;
@@ -716,6 +727,22 @@ 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_event - performance event kernel representation:
  */
@@ -832,6 +859,11 @@ struct perf_event {
 	struct event_filter		*filter;
 #endif
 
+#ifdef CONFIG_CGROUP_PERF
+	struct perf_cgroup		*cgrp; /* cgroup event is attach to */
+	int				cgrp_defer_enabled;
+#endif
+
 #endif /* CONFIG_PERF_EVENTS */
 };
 
@@ -846,8 +878,8 @@ enum perf_event_context_type {
  * Used as a container for task events and CPU events as well:
  */
 struct perf_event_context {
-	enum perf_event_context_type	type;
 	struct pmu			*pmu;
+	enum perf_event_context_type	type;
 	/*
 	 * Protect the states of the events in the list,
 	 * nr_active, and the list:
@@ -886,6 +918,7 @@ struct perf_event_context {
 	u64				generation;
 	int				pin_count;
 	struct rcu_head			rcu_head;
+	int				nr_cgroups; /* cgroup events present */
 };
 
 /*
@@ -905,6 +938,9 @@ struct perf_cpu_context {
 	struct list_head		rotation_list;
 	int				jiffies_interval;
 	struct pmu			*active_pmu;
+#ifdef CONFIG_CGROUP_PERF
+	struct perf_cgroup		*cgrp;
+#endif
 };
 
 struct perf_output_handle {
@@ -1040,11 +1076,11 @@ have_event:
 	__perf_sw_event(event_id, nr, nmi, regs, addr);
 }
 
-extern atomic_t perf_task_events;
+extern atomic_t perf_sched_events;
 
 static inline void perf_event_task_sched_in(struct task_struct *task)
 {
-	COND_STMT(&perf_task_events, __perf_event_task_sched_in(task));
+	COND_STMT(&perf_sched_events, __perf_event_task_sched_in(task));
 }
 
 static inline
@@ -1052,7 +1088,7 @@ void perf_event_task_sched_out(struct task_struct *task, struct task_struct *nex
 {
 	perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0);
 
-	COND_STMT(&perf_task_events, __perf_event_task_sched_out(task, next));
+	COND_STMT(&perf_sched_events, __perf_event_task_sched_out(task, next));
 }
 
 extern void perf_event_mmap(struct vm_area_struct *vma);
@@ -1083,6 +1119,10 @@ extern int sysctl_perf_event_paranoid;
 extern int sysctl_perf_event_mlock;
 extern int sysctl_perf_event_sample_rate;
 
+extern int perf_proc_update_handler(struct ctl_table *table, int write,
+		void __user *buffer, size_t *lenp,
+		loff_t *ppos);
+
 static inline bool perf_paranoid_tracepoint_raw(void)
 {
 	return sysctl_perf_event_paranoid > -1;
diff --git a/include/linux/phonet.h b/include/linux/phonet.h
index 26c8df7..6fb1384 100644
--- a/include/linux/phonet.h
+++ b/include/linux/phonet.h
@@ -36,9 +36,7 @@
 /* Socket options for SOL_PNPIPE level */
 #define PNPIPE_ENCAP		1
 #define PNPIPE_IFINDEX		2
-#define PNPIPE_PIPE_HANDLE	3
-#define PNPIPE_ENABLE           4
-/* unused slot */
+#define PNPIPE_HANDLE		3
 
 #define PNADDR_ANY		0
 #define PNADDR_BROADCAST	0xFC
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 2cfa4bc..b1032a3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -247,6 +247,35 @@ struct tc_gred_sopt {
 	__u16		pad1;
 };
 
+/* CHOKe section */
+
+enum {
+	TCA_CHOKE_UNSPEC,
+	TCA_CHOKE_PARMS,
+	TCA_CHOKE_STAB,
+	__TCA_CHOKE_MAX,
+};
+
+#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1)
+
+struct tc_choke_qopt {
+	__u32		limit;		/* Hard queue length (packets)	*/
+	__u32		qth_min;	/* Min average threshold (packets) */
+	__u32		qth_max;	/* Max average threshold (packets) */
+	unsigned char   Wlog;		/* log(W)		*/
+	unsigned char   Plog;		/* log(P_max/(qth_max-qth_min))	*/
+	unsigned char   Scell_log;	/* cell size for idle damping */
+	unsigned char	flags;		/* see RED flags */
+};
+
+struct tc_choke_xstats {
+	__u32		early;          /* Early drops */
+	__u32		pdrop;          /* Drops due to queue limits */
+	__u32		other;          /* Drops due to drop() calls */
+	__u32		marked;         /* Marked packets */
+	__u32		matched;	/* Drops due to flow match */
+};
+
 /* HTB section */
 #define TC_HTB_NUMPRIO		8
 #define TC_HTB_MAXDEPTH		8
@@ -435,6 +464,7 @@ enum {
 	TCA_NETEM_DELAY_DIST,
 	TCA_NETEM_REORDER,
 	TCA_NETEM_CORRUPT,
+	TCA_NETEM_LOSS,
 	__TCA_NETEM_MAX,
 };
 
@@ -465,7 +495,33 @@ struct tc_netem_corrupt {
 	__u32	correlation;
 };
 
+enum {
+	NETEM_LOSS_UNSPEC,
+	NETEM_LOSS_GI,		/* General Intuitive - 4 state model */
+	NETEM_LOSS_GE,		/* Gilbert Elliot models */
+	__NETEM_LOSS_MAX
+};
+#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
+
+/* State transition probablities for 4 state model */
+struct tc_netem_gimodel {
+	__u32	p13;
+	__u32	p31;
+	__u32	p32;
+	__u32	p14;
+	__u32	p23;
+};
+
+/* Gilbert-Elliot models */
+struct tc_netem_gemodel {
+	__u32 p;
+	__u32 r;
+	__u32 h;
+	__u32 k1;
+};
+
 #define NETEM_DIST_SCALE	8192
+#define NETEM_DIST_MAX		16384
 
 /* DRR */
 
@@ -481,4 +537,55 @@ struct tc_drr_stats {
 	__u32	deficit;
 };
 
+/* MQPRIO */
+#define TC_QOPT_BITMASK 15
+#define TC_QOPT_MAX_QUEUE 16
+
+struct tc_mqprio_qopt {
+	__u8	num_tc;
+	__u8	prio_tc_map[TC_QOPT_BITMASK + 1];
+	__u8	hw;
+	__u16	count[TC_QOPT_MAX_QUEUE];
+	__u16	offset[TC_QOPT_MAX_QUEUE];
+};
+
+/* SFB */
+
+enum {
+	TCA_SFB_UNSPEC,
+	TCA_SFB_PARMS,
+	__TCA_SFB_MAX,
+};
+
+#define TCA_SFB_MAX (__TCA_SFB_MAX - 1)
+
+/*
+ * Note: increment, decrement are Q0.16 fixed-point values.
+ */
+struct tc_sfb_qopt {
+	__u32 rehash_interval;	/* delay between hash move, in ms */
+	__u32 warmup_time;	/* double buffering warmup time in ms (warmup_time < rehash_interval) */
+	__u32 max;		/* max len of qlen_min */
+	__u32 bin_size;		/* maximum queue length per bin */
+	__u32 increment;	/* probability increment, (d1 in Blue) */
+	__u32 decrement;	/* probability decrement, (d2 in Blue) */
+	__u32 limit;		/* max SFB queue length */
+	__u32 penalty_rate;	/* inelastic flows are rate limited to 'rate' pps */
+	__u32 penalty_burst;
+};
+
+struct tc_sfb_xstats {
+	__u32 earlydrop;
+	__u32 penaltydrop;
+	__u32 bucketdrop;
+	__u32 queuedrop;
+	__u32 childdrop; /* drops in child qdisc */
+	__u32 marked;
+	__u32 maxqlen;
+	__u32 maxprob;
+	__u32 avgprob;
+};
+
+#define SFB_MAX_PROB 0xFFFF
+
 #endif
diff --git a/include/linux/platform_data/msm_serial_hs.h b/include/linux/platform_data/msm_serial_hs.h
new file mode 100644
index 0000000..98a2046
--- /dev/null
+++ b/include/linux/platform_data/msm_serial_hs.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Nick Pelly <npelly@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 __ASM_ARCH_MSM_SERIAL_HS_H
+#define __ASM_ARCH_MSM_SERIAL_HS_H
+
+#include <linux/serial_core.h>
+
+/* API to request the uart clock off or on for low power management
+ * Clients should call request_clock_off() when no uart data is expected,
+ * and must call request_clock_on() before any further uart data can be
+ * received. */
+extern void msm_hs_request_clock_off(struct uart_port *uport);
+extern void msm_hs_request_clock_on(struct uart_port *uport);
+
+/**
+ * struct msm_serial_hs_platform_data
+ * @rx_wakeup_irq: Rx activity irq
+ * @rx_to_inject: extra character to be inserted to Rx tty on wakeup
+ * @inject_rx: 1 = insert rx_to_inject. 0 = do not insert extra character
+ * @exit_lpm_cb: function called before every Tx transaction
+ *
+ * This is an optional structure required for UART Rx GPIO IRQ based
+ * wakeup from low power state. UART wakeup can be triggered by RX activity
+ * (using a wakeup GPIO on the UART RX pin). This should only be used if
+ * there is not a wakeup GPIO on the UART CTS, and the first RX byte is
+ * known (eg., with the Bluetooth Texas Instruments HCILL protocol),
+ * since the first RX byte will always be lost. RTS will be asserted even
+ * while the UART is clocked off in this mode of operation.
+ */
+struct msm_serial_hs_platform_data {
+	int rx_wakeup_irq;
+	unsigned char inject_rx_on_wakeup;
+	char rx_to_inject;
+	void (*exit_lpm_cb)(struct uart_port *);
+};
+
+#endif
diff --git a/include/linux/platform_data/tegra_usb.h b/include/linux/platform_data/tegra_usb.h
new file mode 100644
index 0000000..6bca5b5
--- /dev/null
+++ b/include/linux/platform_data/tegra_usb.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef _TEGRA_USB_H_
+#define _TEGRA_USB_H_
+
+enum tegra_usb_operating_modes {
+	TEGRA_USB_DEVICE,
+	TEGRA_USB_HOST,
+	TEGRA_USB_OTG,
+};
+
+struct tegra_ehci_platform_data {
+	enum tegra_usb_operating_modes operating_mode;
+	/* power down the phy on bus suspend */
+	int power_down_on_bus_suspend;
+	void *phy_config;
+};
+
+#endif /* _TEGRA_USB_H_ */
diff --git a/include/linux/platform_data/uio_pruss.h b/include/linux/platform_data/uio_pruss.h
new file mode 100644
index 0000000..f39140a
--- /dev/null
+++ b/include/linux/platform_data/uio_pruss.h
@@ -0,0 +1,25 @@
+/*
+ * include/linux/platform_data/uio_pruss.h
+ *
+ * Platform data for uio_pruss driver
+ *
+ * Copyright (C) 2010-11 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 version 2.
+ *
+ * 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 _UIO_PRUSS_H_
+#define _UIO_PRUSS_H_
+
+/* To configure the PRUSS INTC base offset for UIO driver */
+struct uio_pruss_pdata {
+	u32	pintc_base;
+};
+#endif /* _UIO_PRUSS_H_ */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 2e700ec..d96db98 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -130,8 +130,15 @@ extern void platform_driver_unregister(struct platform_driver *);
 extern int platform_driver_probe(struct platform_driver *driver,
 		int (*probe)(struct platform_device *));
 
-#define platform_get_drvdata(_dev)	dev_get_drvdata(&(_dev)->dev)
-#define platform_set_drvdata(_dev,data)	dev_set_drvdata(&(_dev)->dev, (data))
+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)
+{
+	dev_set_drvdata(&pdev->dev, data);
+}
 
 extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
 					int (*probe)(struct platform_device *),
diff --git a/include/linux/plist.h b/include/linux/plist.h
index 7254eda..c9b9f32 100644
--- a/include/linux/plist.h
+++ b/include/linux/plist.h
@@ -31,15 +31,17 @@
  *
  * Simple ASCII art explanation:
  *
- * |HEAD          |
- * |              |
- * |prio_list.prev|<------------------------------------|
- * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-|
- * |10            |   |10|   |21|   |21|   |21|   |40|   (prio)
- * |              |   |  |   |  |   |  |   |  |   |  |
- * |              |   |  |   |  |   |  |   |  |   |  |
- * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|
- * |node_list.prev|<------------------------------------|
+ * pl:prio_list (only for plist_node)
+ * nl:node_list
+ *   HEAD|             NODE(S)
+ *       |
+ *       ||------------------------------------|
+ *       ||->|pl|<->|pl|<--------------->|pl|<-|
+ *       |   |10|   |21|   |21|   |21|   |40|   (prio)
+ *       |   |  |   |  |   |  |   |  |   |  |
+ *       |   |  |   |  |   |  |   |  |   |  |
+ * |->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|
+ * |-------------------------------------------|
  *
  * The nodes on the prio_list list are sorted by priority to simplify
  * the insertion of new nodes. There are no nodes with duplicate
@@ -78,7 +80,6 @@
 #include <linux/spinlock_types.h>
 
 struct plist_head {
-	struct list_head prio_list;
 	struct list_head node_list;
 #ifdef CONFIG_DEBUG_PI_LIST
 	raw_spinlock_t *rawlock;
@@ -88,7 +89,8 @@ struct plist_head {
 
 struct plist_node {
 	int			prio;
-	struct plist_head	plist;
+	struct list_head	prio_list;
+	struct list_head	node_list;
 };
 
 #ifdef CONFIG_DEBUG_PI_LIST
@@ -100,7 +102,6 @@ struct plist_node {
 #endif
 
 #define _PLIST_HEAD_INIT(head)				\
-	.prio_list = LIST_HEAD_INIT((head).prio_list),	\
 	.node_list = LIST_HEAD_INIT((head).node_list)
 
 /**
@@ -133,7 +134,8 @@ struct plist_node {
 #define PLIST_NODE_INIT(node, __prio)			\
 {							\
 	.prio  = (__prio),				\
-	.plist = { _PLIST_HEAD_INIT((node).plist) },	\
+	.prio_list = LIST_HEAD_INIT((node).prio_list),	\
+	.node_list = LIST_HEAD_INIT((node).node_list),	\
 }
 
 /**
@@ -144,7 +146,6 @@ struct plist_node {
 static inline void
 plist_head_init(struct plist_head *head, spinlock_t *lock)
 {
-	INIT_LIST_HEAD(&head->prio_list);
 	INIT_LIST_HEAD(&head->node_list);
 #ifdef CONFIG_DEBUG_PI_LIST
 	head->spinlock = lock;
@@ -160,7 +161,6 @@ plist_head_init(struct plist_head *head, spinlock_t *lock)
 static inline void
 plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock)
 {
-	INIT_LIST_HEAD(&head->prio_list);
 	INIT_LIST_HEAD(&head->node_list);
 #ifdef CONFIG_DEBUG_PI_LIST
 	head->rawlock = lock;
@@ -176,7 +176,8 @@ plist_head_init_raw(struct plist_head *head, raw_spinlock_t *lock)
 static inline void plist_node_init(struct plist_node *node, int prio)
 {
 	node->prio = prio;
-	plist_head_init(&node->plist, NULL);
+	INIT_LIST_HEAD(&node->prio_list);
+	INIT_LIST_HEAD(&node->node_list);
 }
 
 extern void plist_add(struct plist_node *node, struct plist_head *head);
@@ -188,7 +189,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head);
  * @head:	the head for your list
  */
 #define plist_for_each(pos, head)	\
-	 list_for_each_entry(pos, &(head)->node_list, plist.node_list)
+	 list_for_each_entry(pos, &(head)->node_list, node_list)
 
 /**
  * plist_for_each_safe - iterate safely over a plist of given type
@@ -199,7 +200,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head);
  * Iterate over a plist of given type, safe against removal of list entry.
  */
 #define plist_for_each_safe(pos, n, head)	\
-	 list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list)
+	 list_for_each_entry_safe(pos, n, &(head)->node_list, node_list)
 
 /**
  * plist_for_each_entry	- iterate over list of given type
@@ -208,7 +209,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head);
  * @mem:	the name of the list_struct within the struct
  */
 #define plist_for_each_entry(pos, head, mem)	\
-	 list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list)
+	 list_for_each_entry(pos, &(head)->node_list, mem.node_list)
 
 /**
  * plist_for_each_entry_safe - iterate safely over list of given type
@@ -220,7 +221,7 @@ extern void plist_del(struct plist_node *node, struct plist_head *head);
  * Iterate over list of given type, safe against removal of list entry.
  */
 #define plist_for_each_entry_safe(pos, n, head, m)	\
-	list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list)
+	list_for_each_entry_safe(pos, n, &(head)->node_list, m.node_list)
 
 /**
  * plist_head_empty - return !0 if a plist_head is empty
@@ -237,7 +238,7 @@ static inline int plist_head_empty(const struct plist_head *head)
  */
 static inline int plist_node_empty(const struct plist_node *node)
 {
-	return plist_head_empty(&node->plist);
+	return list_empty(&node->node_list);
 }
 
 /* All functions below assume the plist_head is not empty. */
@@ -285,7 +286,7 @@ static inline int plist_node_empty(const struct plist_node *node)
 static inline struct plist_node *plist_first(const struct plist_head *head)
 {
 	return list_entry(head->node_list.next,
-			  struct plist_node, plist.node_list);
+			  struct plist_node, node_list);
 }
 
 /**
@@ -297,7 +298,7 @@ static inline struct plist_node *plist_first(const struct plist_head *head)
 static inline struct plist_node *plist_last(const struct plist_head *head)
 {
 	return list_entry(head->node_list.prev,
-			  struct plist_node, plist.node_list);
+			  struct plist_node, node_list);
 }
 
 #endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 21415cc..6618216 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -267,7 +267,7 @@ const struct dev_pm_ops name = { \
  * callbacks provided by device drivers supporting both the system sleep PM and
  * runtime PM, make the pm member point to generic_subsys_pm_ops.
  */
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 extern struct dev_pm_ops generic_subsys_pm_ops;
 #define GENERIC_SUBSYS_PM_OPS	(&generic_subsys_pm_ops)
 #else
@@ -465,6 +465,14 @@ struct dev_pm_info {
 
 extern void update_pm_runtime_accounting(struct device *dev);
 
+/*
+ * Power domains provide callbacks that are executed during system suspend,
+ * hibernation, system resume and during runtime PM transitions along with
+ * subsystem-level and driver-level callbacks.
+ */
+struct dev_power_domain {
+	struct dev_pm_ops	ops;
+};
 
 /*
  * The PM_EVENT_ messages are also used by drivers implementing the legacy
@@ -565,15 +573,6 @@ enum dpm_order {
 	DPM_ORDER_DEV_LAST,
 };
 
-/*
- * Global Power Management flags
- * Used to keep APM and ACPI from both being active
- */
-extern unsigned int	pm_flags;
-
-#define PM_APM	1
-#define PM_ACPI	2
-
 extern int pm_generic_suspend(struct device *dev);
 extern int pm_generic_resume(struct device *dev);
 extern int pm_generic_freeze(struct device *dev);
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index d34f067..8de9aa6 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -87,6 +87,11 @@ static inline bool pm_runtime_enabled(struct device *dev)
 	return !dev->power.disable_depth;
 }
 
+static inline bool pm_runtime_callbacks_present(struct device *dev)
+{
+	return !dev->power.no_callbacks;
+}
+
 static inline void pm_runtime_mark_last_busy(struct device *dev)
 {
 	ACCESS_ONCE(dev->power.last_busy) = jiffies;
@@ -133,6 +138,7 @@ static inline int pm_generic_runtime_resume(struct device *dev) { return 0; }
 static inline void pm_runtime_no_callbacks(struct device *dev) {}
 static inline void pm_runtime_irq_safe(struct device *dev) {}
 
+static inline bool pm_runtime_callbacks_present(struct device *dev) { return false; }
 static inline void pm_runtime_mark_last_busy(struct device *dev) {}
 static inline void __pm_runtime_use_autosuspend(struct device *dev,
 						bool use) {}
diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h
index 03a67db..a32da96 100644
--- a/include/linux/pm_wakeup.h
+++ b/include/linux/pm_wakeup.h
@@ -62,18 +62,11 @@ struct wakeup_source {
  * Changes to device_may_wakeup take effect on the next pm state change.
  */
 
-static inline void device_set_wakeup_capable(struct device *dev, bool capable)
-{
-	dev->power.can_wakeup = capable;
-}
-
 static inline bool device_can_wakeup(struct device *dev)
 {
 	return dev->power.can_wakeup;
 }
 
-
-
 static inline bool device_may_wakeup(struct device *dev)
 {
 	return dev->power.can_wakeup && !!dev->power.wakeup;
@@ -88,6 +81,7 @@ extern struct wakeup_source *wakeup_source_register(const char *name);
 extern void wakeup_source_unregister(struct wakeup_source *ws);
 extern int device_wakeup_enable(struct device *dev);
 extern int device_wakeup_disable(struct device *dev);
+extern void device_set_wakeup_capable(struct device *dev, bool capable);
 extern int device_init_wakeup(struct device *dev, bool val);
 extern int device_set_wakeup_enable(struct device *dev, bool enable);
 extern void __pm_stay_awake(struct wakeup_source *ws);
diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h
new file mode 100644
index 0000000..369e19d
--- /dev/null
+++ b/include/linux/posix-clock.h
@@ -0,0 +1,150 @@
+/*
+ * posix-clock.h - support for dynamic clock devices
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _LINUX_POSIX_CLOCK_H_
+#define _LINUX_POSIX_CLOCK_H_
+
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/posix-timers.h>
+
+struct posix_clock;
+
+/**
+ * struct posix_clock_operations - functional interface to the clock
+ *
+ * Every posix clock is represented by a character device. Drivers may
+ * optionally offer extended capabilities by implementing the
+ * character device methods. The character device file operations are
+ * first handled by the clock device layer, then passed on to the
+ * driver by calling these functions.
+ *
+ * @owner:          The clock driver should set to THIS_MODULE
+ * @clock_adjtime:  Adjust the clock
+ * @clock_gettime:  Read the current time
+ * @clock_getres:   Get the clock resolution
+ * @clock_settime:  Set the current time value
+ * @timer_create:   Create a new timer
+ * @timer_delete:   Remove a previously created timer
+ * @timer_gettime:  Get remaining time and interval of a timer
+ * @timer_setttime: Set a timer's initial expiration and interval
+ * @fasync:         Optional character device fasync method
+ * @mmap:           Optional character device mmap method
+ * @open:           Optional character device open method
+ * @release:        Optional character device release method
+ * @ioctl:          Optional character device ioctl method
+ * @read:           Optional character device read method
+ * @poll:           Optional character device poll method
+ */
+struct posix_clock_operations {
+	struct module *owner;
+
+	int  (*clock_adjtime)(struct posix_clock *pc, struct timex *tx);
+
+	int  (*clock_gettime)(struct posix_clock *pc, struct timespec *ts);
+
+	int  (*clock_getres) (struct posix_clock *pc, struct timespec *ts);
+
+	int  (*clock_settime)(struct posix_clock *pc,
+			      const struct timespec *ts);
+
+	int  (*timer_create) (struct posix_clock *pc, struct k_itimer *kit);
+
+	int  (*timer_delete) (struct posix_clock *pc, struct k_itimer *kit);
+
+	void (*timer_gettime)(struct posix_clock *pc,
+			      struct k_itimer *kit, struct itimerspec *tsp);
+
+	int  (*timer_settime)(struct posix_clock *pc,
+			      struct k_itimer *kit, int flags,
+			      struct itimerspec *tsp, struct itimerspec *old);
+	/*
+	 * Optional character device methods:
+	 */
+	int     (*fasync)  (struct posix_clock *pc,
+			    int fd, struct file *file, int on);
+
+	long    (*ioctl)   (struct posix_clock *pc,
+			    unsigned int cmd, unsigned long arg);
+
+	int     (*mmap)    (struct posix_clock *pc,
+			    struct vm_area_struct *vma);
+
+	int     (*open)    (struct posix_clock *pc, fmode_t f_mode);
+
+	uint    (*poll)    (struct posix_clock *pc,
+			    struct file *file, poll_table *wait);
+
+	int     (*release) (struct posix_clock *pc);
+
+	ssize_t (*read)    (struct posix_clock *pc,
+			    uint flags, char __user *buf, size_t cnt);
+};
+
+/**
+ * struct posix_clock - represents a dynamic posix clock
+ *
+ * @ops:     Functional interface to the clock
+ * @cdev:    Character device instance for this clock
+ * @kref:    Reference count.
+ * @mutex:   Protects the 'zombie' field from concurrent access.
+ * @zombie:  If 'zombie' is true, then the hardware has disappeared.
+ * @release: A function to free the structure when the reference count reaches
+ *           zero. May be NULL if structure is statically allocated.
+ *
+ * Drivers should embed their struct posix_clock within a private
+ * structure, obtaining a reference to it during callbacks using
+ * container_of().
+ */
+struct posix_clock {
+	struct posix_clock_operations ops;
+	struct cdev cdev;
+	struct kref kref;
+	struct mutex mutex;
+	bool zombie;
+	void (*release)(struct posix_clock *clk);
+};
+
+/**
+ * posix_clock_register() - register a new clock
+ * @clk:   Pointer to the clock. Caller must provide 'ops' and 'release'
+ * @devid: Allocated device id
+ *
+ * A clock driver calls this function to register itself with the
+ * clock device subsystem. If 'clk' points to dynamically allocated
+ * memory, then the caller must provide a 'release' function to free
+ * that memory.
+ *
+ * Returns zero on success, non-zero otherwise.
+ */
+int posix_clock_register(struct posix_clock *clk, dev_t devid);
+
+/**
+ * posix_clock_unregister() - unregister a clock
+ * @clk: Clock instance previously registered via posix_clock_register()
+ *
+ * A clock driver calls this function to remove itself from the clock
+ * device subsystem. The posix_clock itself will remain (in an
+ * inactive state) until its reference count drops to zero, at which
+ * point it will be deallocated with its 'release' method.
+ */
+void posix_clock_unregister(struct posix_clock *clk);
+
+#endif
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3e23844a..d51243a 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -4,6 +4,7 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/sched.h>
+#include <linux/timex.h>
 
 union cpu_time_count {
 	cputime_t cpu;
@@ -17,10 +18,21 @@ struct cpu_timer_list {
 	int firing;
 };
 
+/*
+ * Bit fields within a clockid:
+ *
+ * The most significant 29 bits hold either a pid or a file descriptor.
+ *
+ * Bit 2 indicates whether a cpu clock refers to a thread or a process.
+ *
+ * Bits 1 and 0 give the type: PROF=0, VIRT=1, SCHED=2, or FD=3.
+ *
+ * A clockid is invalid if bits 2, 1, and 0 are all set.
+ */
 #define CPUCLOCK_PID(clock)		((pid_t) ~((clock) >> 3))
 #define CPUCLOCK_PERTHREAD(clock) \
 	(((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
-#define CPUCLOCK_PID_MASK	7
+
 #define CPUCLOCK_PERTHREAD_MASK	4
 #define CPUCLOCK_WHICH(clock)	((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK)
 #define CPUCLOCK_CLOCK_MASK	3
@@ -28,12 +40,17 @@ struct cpu_timer_list {
 #define CPUCLOCK_VIRT		1
 #define CPUCLOCK_SCHED		2
 #define CPUCLOCK_MAX		3
+#define CLOCKFD			CPUCLOCK_MAX
+#define CLOCKFD_MASK		(CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK)
 
 #define MAKE_PROCESS_CPUCLOCK(pid, clock) \
 	((~(clockid_t) (pid) << 3) | (clockid_t) (clock))
 #define MAKE_THREAD_CPUCLOCK(tid, clock) \
 	MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK)
 
+#define FD_TO_CLOCKID(fd)	((~(clockid_t) (fd) << 3) | CLOCKFD)
+#define CLOCKID_TO_FD(clk)	((unsigned int) ~((clk) >> 3))
+
 /* POSIX.1b interval timer structure. */
 struct k_itimer {
 	struct list_head list;		/* free/ allocate list */
@@ -67,10 +84,11 @@ struct k_itimer {
 };
 
 struct k_clock {
-	int res;		/* in nanoseconds */
 	int (*clock_getres) (const clockid_t which_clock, struct timespec *tp);
-	int (*clock_set) (const clockid_t which_clock, struct timespec * tp);
+	int (*clock_set) (const clockid_t which_clock,
+			  const struct timespec *tp);
 	int (*clock_get) (const clockid_t which_clock, struct timespec * tp);
+	int (*clock_adj) (const clockid_t which_clock, struct timex *tx);
 	int (*timer_create) (struct k_itimer *timer);
 	int (*nsleep) (const clockid_t which_clock, int flags,
 		       struct timespec *, struct timespec __user *);
@@ -84,28 +102,14 @@ struct k_clock {
 			   struct itimerspec * cur_setting);
 };
 
-void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock);
+extern struct k_clock clock_posix_cpu;
+extern struct k_clock clock_posix_dynamic;
 
-/* error handlers for timer_create, nanosleep and settime */
-int do_posix_clock_nonanosleep(const clockid_t, int flags, struct timespec *,
-			       struct timespec __user *);
-int do_posix_clock_nosettime(const clockid_t, struct timespec *tp);
+void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock);
 
 /* function to call to trigger timer event */
 int posix_timer_event(struct k_itimer *timr, int si_private);
 
-int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *ts);
-int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *ts);
-int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *ts);
-int posix_cpu_timer_create(struct k_itimer *timer);
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-		     struct timespec *rqtp, struct timespec __user *rmtp);
-long posix_cpu_nsleep_restart(struct restart_block *restart_block);
-int posix_cpu_timer_set(struct k_itimer *timer, int flags,
-			struct itimerspec *new, struct itimerspec *old);
-int posix_cpu_timer_del(struct k_itimer *timer);
-void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp);
-
 void posix_cpu_timer_schedule(struct k_itimer *timer);
 
 void run_posix_cpu_timers(struct task_struct *task);
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
new file mode 100644
index 0000000..4197773
--- /dev/null
+++ b/include/linux/pstore.h
@@ -0,0 +1,60 @@
+/*
+ * Persistent Storage - pstore.h
+ *
+ * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com>
+ *
+ * This code is the generic layer to export data records from platform
+ * level persistent storage via a file system.
+ *
+ *  This program is free software; you can 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 _LINUX_PSTORE_H
+#define _LINUX_PSTORE_H
+
+/* types */
+enum pstore_type_id {
+	PSTORE_TYPE_DMESG	= 0,
+	PSTORE_TYPE_MCE		= 1,
+	PSTORE_TYPE_UNKNOWN	= 255
+};
+
+struct pstore_info {
+	struct module	*owner;
+	char		*name;
+	struct mutex	buf_mutex;	/* serialize access to 'buf' */
+	char		*buf;
+	size_t		bufsize;
+	size_t		(*read)(u64 *id, enum pstore_type_id *type,
+			struct timespec *time);
+	u64		(*write)(enum pstore_type_id type, size_t size);
+	int		(*erase)(u64 id);
+};
+
+#ifdef CONFIG_PSTORE
+extern int pstore_register(struct pstore_info *);
+extern int pstore_write(enum pstore_type_id type, char *buf, size_t size);
+#else
+static inline int
+pstore_register(struct pstore_info *psi)
+{
+	return -ENODEV;
+}
+static inline int
+pstore_write(enum pstore_type_id type, char *buf, size_t size)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif /*_LINUX_PSTORE_H*/
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index e031e1a..5e3e25a 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -4,6 +4,8 @@
 #ifndef __LINUX_PWM_BACKLIGHT_H
 #define __LINUX_PWM_BACKLIGHT_H
 
+#include <linux/backlight.h>
+
 struct platform_pwm_backlight_data {
 	int pwm_id;
 	unsigned int max_brightness;
@@ -13,6 +15,7 @@ struct platform_pwm_backlight_data {
 	int (*init)(struct device *dev);
 	int (*notify)(struct device *dev, int brightness);
 	void (*exit)(struct device *dev);
+	int (*check_fb)(struct device *dev, struct fb_info *info);
 };
 
 #endif
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 3b94c91..6deef5d 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -63,6 +63,7 @@ extern const struct xattr_handler reiserfs_xattr_trusted_handler;
 extern const struct xattr_handler reiserfs_xattr_security_handler;
 #ifdef CONFIG_REISERFS_FS_SECURITY
 int reiserfs_security_init(struct inode *dir, struct inode *inode,
+			   const struct qstr *qstr,
 			   struct reiserfs_security_handle *sec);
 int reiserfs_security_write(struct reiserfs_transaction_handle *th,
 			    struct inode *inode,
@@ -130,6 +131,7 @@ static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
 #ifndef CONFIG_REISERFS_FS_SECURITY
 static inline int reiserfs_security_init(struct inode *dir,
 					 struct inode *inode,
+					 const struct qstr *qstr,
 					 struct reiserfs_security_handle *sec)
 {
 	return 0;
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
index 8d3a248..ab38ac8 100644
--- a/include/linux/ring_buffer.h
+++ b/include/linux/ring_buffer.h
@@ -100,6 +100,8 @@ void ring_buffer_free(struct ring_buffer *buffer);
 
 int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size);
 
+void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val);
+
 struct ring_buffer_event *ring_buffer_lock_reserve(struct ring_buffer *buffer,
 						   unsigned long length);
 int ring_buffer_unlock_commit(struct ring_buffer *buffer,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index e9fd04c..830e65d 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -27,18 +27,15 @@
 struct anon_vma {
 	struct anon_vma *root;	/* Root of this anon_vma tree */
 	spinlock_t lock;	/* Serialize access to vma list */
-#if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
-
 	/*
-	 * The external_refcount is taken by either KSM or page migration
-	 * to take a reference to an anon_vma when there is no
+	 * The refcount is taken on an anon_vma when there is no
 	 * guarantee that the vma of page tables will exist for
 	 * the duration of the operation. A caller that takes
 	 * the reference is responsible for clearing up the
 	 * anon_vma if they are the last user on release
 	 */
-	atomic_t external_refcount;
-#endif
+	atomic_t refcount;
+
 	/*
 	 * NOTE: the LSB of the head.next is set by
 	 * mm_take_all_locks() _after_ taking the above lock. So the
@@ -71,42 +68,19 @@ struct anon_vma_chain {
 };
 
 #ifdef CONFIG_MMU
-#if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
-static inline void anonvma_external_refcount_init(struct anon_vma *anon_vma)
-{
-	atomic_set(&anon_vma->external_refcount, 0);
-}
-
-static inline int anonvma_external_refcount(struct anon_vma *anon_vma)
-{
-	return atomic_read(&anon_vma->external_refcount);
-}
-
 static inline void get_anon_vma(struct anon_vma *anon_vma)
 {
-	atomic_inc(&anon_vma->external_refcount);
+	atomic_inc(&anon_vma->refcount);
 }
 
-void drop_anon_vma(struct anon_vma *);
-#else
-static inline void anonvma_external_refcount_init(struct anon_vma *anon_vma)
-{
-}
+void __put_anon_vma(struct anon_vma *anon_vma);
 
-static inline int anonvma_external_refcount(struct anon_vma *anon_vma)
-{
-	return 0;
-}
-
-static inline void get_anon_vma(struct anon_vma *anon_vma)
+static inline void put_anon_vma(struct anon_vma *anon_vma)
 {
+	if (atomic_dec_and_test(&anon_vma->refcount))
+		__put_anon_vma(anon_vma);
 }
 
-static inline void drop_anon_vma(struct anon_vma *anon_vma)
-{
-}
-#endif /* CONFIG_KSM */
-
 static inline struct anon_vma *page_anon_vma(struct page *page)
 {
 	if (((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) !=
@@ -148,7 +122,6 @@ void unlink_anon_vmas(struct vm_area_struct *);
 int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
 int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
 void __anon_vma_link(struct vm_area_struct *);
-void anon_vma_free(struct anon_vma *);
 
 static inline void anon_vma_merge(struct vm_area_struct *vma,
 				  struct vm_area_struct *next)
@@ -157,6 +130,8 @@ static inline void anon_vma_merge(struct vm_area_struct *vma,
 	unlink_anon_vmas(next);
 }
 
+struct anon_vma *page_get_anon_vma(struct page *page);
+
 /*
  * rmap interfaces called when adding or removing pte of page
  */
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 89c3e51..2ca7e8a 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -133,7 +133,6 @@ extern struct class *rtc_class;
  * The (current) exceptions are mostly filesystem hooks:
  *   - the proc() hook for procfs
  *   - non-ioctl() chardev hooks:  open(), release(), read_callback()
- *   - periodic irq calls:  irq_set_state(), irq_set_freq()
  *
  * REVISIT those periodic irq calls *do* have ops_lock when they're
  * issued through ioctl() ...
@@ -148,11 +147,8 @@ struct rtc_class_ops {
 	int (*set_alarm)(struct device *, struct rtc_wkalrm *);
 	int (*proc)(struct device *, struct seq_file *);
 	int (*set_mmss)(struct device *, unsigned long secs);
-	int (*irq_set_state)(struct device *, int enabled);
-	int (*irq_set_freq)(struct device *, int freq);
 	int (*read_callback)(struct device *, int data);
 	int (*alarm_irq_enable)(struct device *, unsigned int enabled);
-	int (*update_irq_enable)(struct device *, unsigned int enabled);
 };
 
 #define RTC_DEVICE_NAME_SIZE 20
@@ -227,6 +223,7 @@ extern void rtc_device_unregister(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);
 extern int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs);
+int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm);
 extern int rtc_read_alarm(struct rtc_device *rtc,
 			struct rtc_wkalrm *alrm);
 extern int rtc_set_alarm(struct rtc_device *rtc,
diff --git a/include/linux/rwlock_types.h b/include/linux/rwlock_types.h
index bd31808..cc0072e 100644
--- a/include/linux/rwlock_types.h
+++ b/include/linux/rwlock_types.h
@@ -43,14 +43,6 @@ typedef struct {
 				RW_DEP_MAP_INIT(lockname) }
 #endif
 
-/*
- * RW_LOCK_UNLOCKED defeat lockdep state tracking and is hence
- * deprecated.
- *
- * Please use DEFINE_RWLOCK() or __RW_LOCK_UNLOCKED() as appropriate.
- */
-#define RW_LOCK_UNLOCKED	__RW_LOCK_UNLOCKED(old_style_rw_init)
-
 #define DEFINE_RWLOCK(x)	rwlock_t x = __RW_LOCK_UNLOCKED(x)
 
 #endif /* __LINUX_RWLOCK_TYPES_H */
diff --git a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h
index bdfcc25..3470124 100644
--- a/include/linux/rwsem-spinlock.h
+++ b/include/linux/rwsem-spinlock.h
@@ -12,15 +12,7 @@
 #error "please don't include linux/rwsem-spinlock.h directly, use linux/rwsem.h instead"
 #endif
 
-#include <linux/spinlock.h>
-#include <linux/list.h>
-
 #ifdef __KERNEL__
-
-#include <linux/types.h>
-
-struct rwsem_waiter;
-
 /*
  * the rw-semaphore definition
  * - if activity is 0 then there are no active readers or writers
@@ -37,28 +29,7 @@ struct rw_semaphore {
 #endif
 };
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
-{ 0, __SPIN_LOCK_UNLOCKED(name.wait_lock), LIST_HEAD_INIT((name).wait_list) \
-  __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)						\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__init_rwsem((sem), #sem, &__key);			\
-} while (0)
+#define RWSEM_UNLOCKED_VALUE		0x00000000
 
 extern void __down_read(struct rw_semaphore *sem);
 extern int __down_read_trylock(struct rw_semaphore *sem);
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index efd348f..a8afe9c 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -11,6 +11,9 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
 #include <asm/system.h>
 #include <asm/atomic.h>
 
@@ -19,9 +22,57 @@ struct rw_semaphore;
 #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
 #include <linux/rwsem-spinlock.h> /* use a generic implementation */
 #else
-#include <asm/rwsem.h> /* use an arch-specific implementation */
+/* All arch specific implementations share the same struct */
+struct rw_semaphore {
+	long			count;
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	struct lockdep_map	dep_map;
+#endif
+};
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+/* Include the arch specific part */
+#include <asm/rwsem.h>
+
+/* In all implementations count != 0 means locked */
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return sem->count != 0;
+}
+
+#endif
+
+/* Common initializer macros and functions */
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
+#else
+# define __RWSEM_DEP_MAP_INIT(lockname)
 #endif
 
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED(name.wait_lock),	\
+	  LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
+
+#define DECLARE_RWSEM(name) \
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
+			 struct lock_class_key *key);
+
+#define init_rwsem(sem)						\
+do {								\
+	static struct lock_class_key __key;			\
+								\
+	__init_rwsem((sem), #sem, &__key);			\
+} while (0)
+
 /*
  * lock for reading
  */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 777d8a5..4b601be 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1058,6 +1058,7 @@ struct sched_class {
 	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);
 
@@ -1084,12 +1085,10 @@ struct sched_class {
 	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,
-			       int running);
-	void (*switched_to) (struct rq *this_rq, struct task_struct *task,
-			     int running);
+	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, int running);
+			     int oldprio);
 
 	unsigned int (*get_rr_interval) (struct rq *rq,
 					 struct task_struct *task);
@@ -1472,6 +1471,7 @@ struct task_struct {
 #ifdef CONFIG_NUMA
 	struct mempolicy *mempolicy;	/* Protected by alloc_lock */
 	short il_next;
+	short pref_node_fork;
 #endif
 	atomic_t fs_excl;	/* holding fs exclusive resources */
 	struct rcu_head rcu;
@@ -1715,7 +1715,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 /*
  * Per process flags
  */
-#define PF_KSOFTIRQD	0x00000001	/* I am ksoftirqd */
 #define PF_STARTING	0x00000002	/* being created */
 #define PF_EXITING	0x00000004	/* getting shut down */
 #define PF_EXITPIDONE	0x00000008	/* pi exit done on shut down */
@@ -1945,8 +1944,6 @@ int sched_rt_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp,
 		loff_t *ppos);
 
-extern unsigned int sysctl_sched_compat_yield;
-
 #ifdef CONFIG_SCHED_AUTOGROUP
 extern unsigned int sysctl_sched_autogroup_enabled;
 
@@ -1977,6 +1974,7 @@ static inline int rt_mutex_getprio(struct task_struct *p)
 # define rt_mutex_adjust_pi(p)		do { } while (0)
 #endif
 
+extern bool yield_to(struct task_struct *p, bool preempt);
 extern void set_user_nice(struct task_struct *p, long nice);
 extern int task_prio(const struct task_struct *p);
 extern int task_nice(const struct task_struct *p);
@@ -2049,7 +2047,7 @@ extern void release_uids(struct user_namespace *ns);
 
 #include <asm/current.h>
 
-extern void do_timer(unsigned long ticks);
+extern void xtime_update(unsigned long ticks);
 
 extern int wake_up_state(struct task_struct *tsk, unsigned int state);
 extern int wake_up_process(struct task_struct *tsk);
@@ -2578,13 +2576,6 @@ static inline void inc_syscw(struct task_struct *tsk)
 #define TASK_SIZE_OF(tsk)	TASK_SIZE
 #endif
 
-/*
- * Call the function if the target task is executing on a CPU right now:
- */
-extern void task_oncpu_function_call(struct task_struct *p,
-				     void (*func) (void *info), void *info);
-
-
 #ifdef CONFIG_MM_OWNER
 extern void mm_update_next_owner(struct mm_struct *mm);
 extern void mm_init_owner(struct mm_struct *mm, struct task_struct *p);
diff --git a/include/linux/security.h b/include/linux/security.h
index b2b7f97..56cac52 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -25,6 +25,7 @@
 #include <linux/fs.h>
 #include <linux/fsnotify.h>
 #include <linux/binfmts.h>
+#include <linux/dcache.h>
 #include <linux/signal.h>
 #include <linux/resource.h>
 #include <linux/sem.h>
@@ -53,7 +54,7 @@ struct audit_krule;
  */
 extern int cap_capable(struct task_struct *tsk, const struct cred *cred,
 		       int cap, int audit);
-extern int cap_settime(struct timespec *ts, struct timezone *tz);
+extern int cap_settime(const struct timespec *ts, const struct timezone *tz);
 extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
 extern int cap_ptrace_traceme(struct task_struct *parent);
 extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -267,6 +268,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@orig the original mount data copied from userspace.
  *	@copy copied data which will be passed to the security module.
  *	Returns 0 if the copy was successful.
+ * @sb_remount:
+ *	Extracts security system specifc mount options and verifys no changes
+ *	are being made to those options.
+ *	@sb superblock being remounted
+ *	@data contains the filesystem-specific data.
+ *	Return 0 if permission is granted.
  * @sb_umount:
  *	Check permission before the @mnt file system is unmounted.
  *	@mnt contains the mounted file system.
@@ -315,6 +322,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	then it should return -EOPNOTSUPP to skip this processing.
  *	@inode contains the inode structure of the newly created inode.
  *	@dir contains the inode structure of the parent directory.
+ *	@qstr contains the last path component of the new object
  *	@name will be set to the allocated name suffix (e.g. selinux).
  *	@value will be set to the allocated attribute value.
  *	@len will be set to the length of the value.
@@ -1257,12 +1265,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	@cap contains the capability <include/linux/capability.h>.
  *	@audit: Whether to write an audit message or not
  *	Return 0 if the capability is granted for @tsk.
- * @sysctl:
- *	Check permission before accessing the @table sysctl variable in the
- *	manner specified by @op.
- *	@table contains the ctl_table structure for the sysctl variable.
- *	@op contains the operation (001 = search, 002 = write, 004 = read).
- *	Return 0 if permission is granted.
  * @syslog:
  *	Check permission before accessing the kernel message ring or changing
  *	logging to the console.
@@ -1383,11 +1385,10 @@ struct security_operations {
 		       const kernel_cap_t *permitted);
 	int (*capable) (struct task_struct *tsk, const struct cred *cred,
 			int cap, int audit);
-	int (*sysctl) (struct ctl_table *table, int op);
 	int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
 	int (*quota_on) (struct dentry *dentry);
 	int (*syslog) (int type);
-	int (*settime) (struct timespec *ts, struct timezone *tz);
+	int (*settime) (const struct timespec *ts, const struct timezone *tz);
 	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
 
 	int (*bprm_set_creds) (struct linux_binprm *bprm);
@@ -1399,6 +1400,7 @@ struct security_operations {
 	int (*sb_alloc_security) (struct super_block *sb);
 	void (*sb_free_security) (struct super_block *sb);
 	int (*sb_copy_data) (char *orig, char *copy);
+	int (*sb_remount) (struct super_block *sb, void *data);
 	int (*sb_kern_mount) (struct super_block *sb, int flags, void *data);
 	int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
 	int (*sb_statfs) (struct dentry *dentry);
@@ -1435,7 +1437,8 @@ struct security_operations {
 	int (*inode_alloc_security) (struct inode *inode);
 	void (*inode_free_security) (struct inode *inode);
 	int (*inode_init_security) (struct inode *inode, struct inode *dir,
-				    char **name, void **value, size_t *len);
+				    const struct qstr *qstr, char **name,
+				    void **value, size_t *len);
 	int (*inode_create) (struct inode *dir,
 			     struct dentry *dentry, int mode);
 	int (*inode_link) (struct dentry *old_dentry,
@@ -1623,7 +1626,7 @@ struct security_operations {
 	int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
 	int (*xfrm_state_pol_flow_match) (struct xfrm_state *x,
 					  struct xfrm_policy *xp,
-					  struct flowi *fl);
+					  const struct flowi *fl);
 	int (*xfrm_decode_session) (struct sk_buff *skb, u32 *secid, int ckall);
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 
@@ -1665,11 +1668,10 @@ int security_capset(struct cred *new, const struct cred *old,
 int security_capable(const struct cred *cred, int cap);
 int security_real_capable(struct task_struct *tsk, int cap);
 int security_real_capable_noaudit(struct task_struct *tsk, int cap);
-int security_sysctl(struct ctl_table *table, int op);
 int security_quotactl(int cmds, int type, int id, struct super_block *sb);
 int security_quota_on(struct dentry *dentry);
 int security_syslog(int type);
-int security_settime(struct timespec *ts, struct timezone *tz);
+int security_settime(const struct timespec *ts, const struct timezone *tz);
 int security_vm_enough_memory(long pages);
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
 int security_vm_enough_memory_kern(long pages);
@@ -1681,6 +1683,7 @@ int security_bprm_secureexec(struct linux_binprm *bprm);
 int security_sb_alloc(struct super_block *sb);
 void security_sb_free(struct super_block *sb);
 int security_sb_copy_data(char *orig, char *copy);
+int security_sb_remount(struct super_block *sb, void *data);
 int security_sb_kern_mount(struct super_block *sb, int flags, void *data);
 int security_sb_show_options(struct seq_file *m, struct super_block *sb);
 int security_sb_statfs(struct dentry *dentry);
@@ -1696,7 +1699,8 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-				  char **name, void **value, size_t *len);
+				 const struct qstr *qstr, char **name,
+				 void **value, size_t *len);
 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
 			 struct dentry *new_dentry);
@@ -1883,11 +1887,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap)
 	return ret;
 }
 
-static inline int security_sysctl(struct ctl_table *table, int op)
-{
-	return 0;
-}
-
 static inline int security_quotactl(int cmds, int type, int id,
 				     struct super_block *sb)
 {
@@ -1904,7 +1903,8 @@ static inline int security_syslog(int type)
 	return 0;
 }
 
-static inline int security_settime(struct timespec *ts, struct timezone *tz)
+static inline int security_settime(const struct timespec *ts,
+				   const struct timezone *tz)
 {
 	return cap_settime(ts, tz);
 }
@@ -1964,6 +1964,11 @@ static inline int security_sb_copy_data(char *orig, char *copy)
 	return 0;
 }
 
+static inline int security_sb_remount(struct super_block *sb, void *data)
+{
+	return 0;
+}
+
 static inline int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
 	return 0;
@@ -2023,6 +2028,7 @@ static inline void security_inode_free(struct inode *inode)
 
 static inline int security_inode_init_security(struct inode *inode,
 						struct inode *dir,
+						const struct qstr *qstr,
 						char **name,
 						void **value,
 						size_t *len)
@@ -2761,7 +2767,8 @@ int security_xfrm_state_delete(struct xfrm_state *x);
 void security_xfrm_state_free(struct xfrm_state *x);
 int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
 int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
-				       struct xfrm_policy *xp, struct flowi *fl);
+				       struct xfrm_policy *xp,
+				       const struct flowi *fl);
 int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
 void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
 
@@ -2813,7 +2820,7 @@ static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_s
 }
 
 static inline int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
-			struct xfrm_policy *xp, struct flowi *fl)
+			struct xfrm_policy *xp, const struct flowi *fl)
 {
 	return 1;
 }
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 1630d9c..a2afc9f 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -34,28 +34,32 @@ enum {
 	SCIx_NR_IRQS,
 };
 
+#define SCIx_IRQ_MUXED(irq)		\
+{					\
+	[SCIx_ERI_IRQ]	= (irq),	\
+	[SCIx_RXI_IRQ]	= (irq),	\
+	[SCIx_TXI_IRQ]	= (irq),	\
+	[SCIx_BRI_IRQ]	= (irq),	\
+}
+
 struct device;
 
 /*
  * Platform device specific platform_data struct
  */
 struct plat_sci_port {
-	void __iomem	*membase;		/* io cookie */
 	unsigned long	mapbase;		/* resource base */
 	unsigned int	irqs[SCIx_NR_IRQS];	/* ERI, RXI, TXI, BRI */
 	unsigned int	type;			/* SCI / SCIF / IRDA */
 	upf_t		flags;			/* UPF_* flags */
-	char		*clk;			/* clock string */
 
 	unsigned int	scbrr_algo_id;		/* SCBRR calculation algo */
 	unsigned int	scscr;			/* SCSCR initialization */
 
 	struct device	*dma_dev;
 
-#ifdef CONFIG_SERIAL_SH_SCI_DMA
-	unsigned int dma_slave_tx;
-	unsigned int dma_slave_rx;
-#endif
+	unsigned int	dma_slave_tx;
+	unsigned int	dma_slave_rx;
 };
 
 #endif /* __LINUX_SERIAL_SCI_H */
diff --git a/include/linux/sigma.h b/include/linux/sigma.h
new file mode 100644
index 0000000..e2accb3
--- /dev/null
+++ b/include/linux/sigma.h
@@ -0,0 +1,60 @@
+/*
+ * Load firmware files from Analog Devices SigmaStudio
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __SIGMA_FIRMWARE_H__
+#define __SIGMA_FIRMWARE_H__
+
+#include <linux/firmware.h>
+#include <linux/types.h>
+
+struct i2c_client;
+
+#define SIGMA_MAGIC "ADISIGM"
+
+struct sigma_firmware {
+	const struct firmware *fw;
+	size_t pos;
+};
+
+struct sigma_firmware_header {
+	unsigned char magic[7];
+	u8 version;
+	u32 crc;
+};
+
+enum {
+	SIGMA_ACTION_WRITEXBYTES = 0,
+	SIGMA_ACTION_WRITESINGLE,
+	SIGMA_ACTION_WRITESAFELOAD,
+	SIGMA_ACTION_DELAY,
+	SIGMA_ACTION_PLLWAIT,
+	SIGMA_ACTION_NOOP,
+	SIGMA_ACTION_END,
+};
+
+struct sigma_action {
+	u8 instr;
+	u8 len_hi;
+	u16 len;
+	u16 addr;
+	unsigned char payload[];
+};
+
+static inline u32 sigma_action_len(struct sigma_action *sa)
+{
+	return (sa->len_hi << 16) | sa->len;
+}
+
+static inline size_t sigma_action_size(struct sigma_action *sa, u32 payload_len)
+{
+	return sizeof(*sa) + payload_len + (payload_len % 2);
+}
+
+extern int process_sigma_firmware(struct i2c_client *client, const char *name);
+
+#endif
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index bf221d6..24cfa62 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -388,10 +388,7 @@ struct sk_buff {
 	kmemcheck_bitfield_begin(flags2);
 	__u16			queue_mapping:16;
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
-	__u8			ndisc_nodetype:2,
-				deliver_no_wcard:1;
-#else
-	__u8			deliver_no_wcard:1;
+	__u8			ndisc_nodetype:2;
 #endif
 	__u8			ooo_okay:1;
 	kmemcheck_bitfield_end(flags2);
@@ -1801,6 +1798,15 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
 		     prefetch(skb->prev), (skb != (struct sk_buff *)(queue));	\
 		     skb = skb->prev)
 
+#define skb_queue_reverse_walk_safe(queue, skb, tmp)				\
+		for (skb = (queue)->prev, tmp = skb->prev;			\
+		     skb != (struct sk_buff *)(queue);				\
+		     skb = tmp, tmp = skb->prev)
+
+#define skb_queue_reverse_walk_from_safe(queue, skb, tmp)			\
+		for (tmp = skb->prev;						\
+		     skb != (struct sk_buff *)(queue);				\
+		     skb = tmp, tmp = skb->prev)
 
 static inline bool skb_has_frag_list(const struct sk_buff *skb)
 {
@@ -1868,7 +1874,7 @@ extern void	       skb_split(struct sk_buff *skb,
 extern int	       skb_shift(struct sk_buff *tgt, struct sk_buff *skb,
 				 int shiftlen);
 
-extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
+extern struct sk_buff *skb_segment(struct sk_buff *skb, u32 features);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 				       int len, void *buffer)
diff --git a/include/linux/slab.h b/include/linux/slab.h
index fa90866..ad4dd1c 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -105,7 +105,6 @@ void kmem_cache_destroy(struct kmem_cache *);
 int kmem_cache_shrink(struct kmem_cache *);
 void kmem_cache_free(struct kmem_cache *, void *);
 unsigned int kmem_cache_size(struct kmem_cache *);
-const char *kmem_cache_name(struct kmem_cache *);
 
 /*
  * Please use this macro to create slab caches. Simply specify the
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index 8b6e8ae..45ca123 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -32,10 +32,14 @@ enum stat_item {
 	DEACTIVATE_TO_TAIL,	/* Cpu slab was moved to the tail of partials */
 	DEACTIVATE_REMOTE_FREES,/* Slab contained remotely freed objects */
 	ORDER_FALLBACK,		/* Number of times fallback was necessary */
+	CMPXCHG_DOUBLE_CPU_FAIL,/* Failure of this_cpu_cmpxchg_double */
 	NR_SLUB_STAT_ITEMS };
 
 struct kmem_cache_cpu {
-	void **freelist;	/* Pointer to first free per cpu object */
+	void **freelist;	/* Pointer to next available object */
+#ifdef CONFIG_CMPXCHG_LOCAL
+	unsigned long tid;	/* Globally unique transaction id */
+#endif
 	struct page *page;	/* The slab from which we are allocating */
 	int node;		/* The node of the page (or -1 for debug) */
 #ifdef CONFIG_SLUB_STATS
@@ -70,6 +74,7 @@ struct kmem_cache {
 	struct kmem_cache_cpu __percpu *cpu_slab;
 	/* Used for retriving partial slabs etc */
 	unsigned long flags;
+	unsigned long min_partial;
 	int size;		/* The size of an object including meta data */
 	int objsize;		/* The size of an object without meta data */
 	int offset;		/* Free pointer offset. */
@@ -83,7 +88,7 @@ struct kmem_cache {
 	void (*ctor)(void *);
 	int inuse;		/* Offset to metadata */
 	int align;		/* Alignment */
-	unsigned long min_partial;
+	int reserved;		/* Reserved bytes at the end of slabs */
 	const char *name;	/* Name (only for display!) */
 	struct list_head list;	/* List of slab caches */
 #ifdef CONFIG_SYSFS
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 6dc95ca..74243c8 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/cpumask.h>
+#include <linux/init.h>
 
 extern void cpu_idle(void);
 
@@ -114,6 +115,8 @@ int on_each_cpu(smp_call_func_t func, void *info, int wait);
 void smp_prepare_boot_cpu(void);
 
 extern unsigned int setup_max_cpus;
+extern void __init setup_nr_cpu_ids(void);
+extern void __init smp_init(void);
 
 #else /* !SMP */
 
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
deleted file mode 100644
index 3a19882..0000000
--- a/include/linux/smp_lock.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef __LINUX_SMPLOCK_H
-#define __LINUX_SMPLOCK_H
-
-#ifdef CONFIG_LOCK_KERNEL
-#include <linux/sched.h>
-
-extern int __lockfunc __reacquire_kernel_lock(void);
-extern void __lockfunc __release_kernel_lock(void);
-
-/*
- * Release/re-acquire global kernel lock for the scheduler
- */
-#define release_kernel_lock(tsk) do { 		\
-	if (unlikely((tsk)->lock_depth >= 0))	\
-		__release_kernel_lock();	\
-} while (0)
-
-static inline int reacquire_kernel_lock(struct task_struct *task)
-{
-	if (unlikely(task->lock_depth >= 0))
-		return __reacquire_kernel_lock();
-	return 0;
-}
-
-extern void __lockfunc
-_lock_kernel(const char *func, const char *file, int line)
-__acquires(kernel_lock);
-
-extern void __lockfunc
-_unlock_kernel(const char *func, const char *file, int line)
-__releases(kernel_lock);
-
-#define lock_kernel() do {					\
-	_lock_kernel(__func__, __FILE__, __LINE__);		\
-} while (0)
-
-#define unlock_kernel()	do {					\
-	_unlock_kernel(__func__, __FILE__, __LINE__);		\
-} while (0)
-
-/*
- * Various legacy drivers don't really need the BKL in a specific
- * function, but they *do* need to know that the BKL became available.
- * This function just avoids wrapping a bunch of lock/unlock pairs
- * around code which doesn't really need it.
- */
-static inline void cycle_kernel_lock(void)
-{
-	lock_kernel();
-	unlock_kernel();
-}
-
-#else
-
-#ifdef CONFIG_BKL /* provoke build bug if not set */
-#define lock_kernel()
-#define unlock_kernel()
-#define cycle_kernel_lock()			do { } while(0)
-#endif /* CONFIG_BKL */
-
-#define release_kernel_lock(task)		do { } while(0)
-#define reacquire_kernel_lock(task)		0
-
-#endif /* CONFIG_LOCK_KERNEL */
-#endif /* __LINUX_SMPLOCK_H */
diff --git a/include/linux/sockios.h b/include/linux/sockios.h
index 241f179..7997a50 100644
--- a/include/linux/sockios.h
+++ b/include/linux/sockios.h
@@ -22,7 +22,7 @@
 
 /* Linux-specific socket ioctls */
 #define SIOCINQ		FIONREAD
-#define SIOCOUTQ	TIOCOUTQ
+#define SIOCOUTQ	TIOCOUTQ        /* output queue size (not sent + not acked) */
 
 /* Routing table calls. */
 #define SIOCADDRT	0x890B		/* add routing table entry	*/
@@ -83,6 +83,8 @@
 
 #define SIOCWANDEV	0x894A		/* get/set netdev parameters	*/
 
+#define SIOCOUTQNSD	0x894B		/* output queue size (not sent only) */
+
 /* ARP cache control calls. */
 		    /*  0x8950 - 0x8952  * obsolete calls, don't re-use */
 #define SIOCDARP	0x8953		/* delete ARP table entry	*/
diff --git a/include/linux/spi/dw_spi.h b/include/linux/spi/dw_spi.h
deleted file mode 100644
index 6cd10f6..0000000
--- a/include/linux/spi/dw_spi.h
+++ /dev/null
@@ -1,233 +0,0 @@
-#ifndef DW_SPI_HEADER_H
-#define DW_SPI_HEADER_H
-
-#include <linux/io.h>
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-
-#define SPI_TMOD_OFFSET			8
-#define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-/* Bit fields in ISR, IMR, RISR, 7 bits */
-#define SPI_INT_TXEI			(1 << 0)
-#define SPI_INT_TXOI			(1 << 1)
-#define SPI_INT_RXUI			(1 << 2)
-#define SPI_INT_RXOI			(1 << 3)
-#define SPI_INT_RXFI			(1 << 4)
-#define SPI_INT_MSTI			(1 << 5)
-
-/* TX RX interrupt level threshhold, max can be 256 */
-#define SPI_INT_THRESHOLD		32
-
-enum dw_ssi_type {
-	SSI_MOTO_SPI = 0,
-	SSI_TI_SSP,
-	SSI_NS_MICROWIRE,
-};
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-	u32	dr;		/* Currently oper as 32 bits,
-				though only low 16 bits matters */
-} __packed;
-
-struct dw_spi;
-struct dw_spi_dma_ops {
-	int (*dma_init)(struct dw_spi *dws);
-	void (*dma_exit)(struct dw_spi *dws);
-	int (*dma_transfer)(struct dw_spi *dws, int cs_change);
-};
-
-struct dw_spi {
-	struct spi_master	*master;
-	struct spi_device	*cur_dev;
-	struct device		*parent_dev;
-	enum dw_ssi_type	type;
-
-	void __iomem		*regs;
-	unsigned long		paddr;
-	u32			iolen;
-	int			irq;
-	u32			fifo_len;	/* depth of the FIFO buffer */
-	u32			max_freq;	/* max bus freq supported */
-
-	u16			bus_num;
-	u16			num_cs;		/* supported slave numbers */
-
-	/* Driver message queue */
-	struct workqueue_struct	*workqueue;
-	struct work_struct	pump_messages;
-	spinlock_t		lock;
-	struct list_head	queue;
-	int			busy;
-	int			run;
-
-	/* Message Transfer pump */
-	struct tasklet_struct	pump_transfers;
-
-	/* Current message transfer state info */
-	struct spi_message	*cur_msg;
-	struct spi_transfer	*cur_transfer;
-	struct chip_data	*cur_chip;
-	struct chip_data	*prev_chip;
-	size_t			len;
-	void			*tx;
-	void			*tx_end;
-	void			*rx;
-	void			*rx_end;
-	int			dma_mapped;
-	dma_addr_t		rx_dma;
-	dma_addr_t		tx_dma;
-	size_t			rx_map_len;
-	size_t			tx_map_len;
-	u8			n_bytes;	/* current is a 1/2 bytes op */
-	u8			max_bits_per_word;	/* maxim is 16b */
-	u32			dma_width;
-	int			cs_change;
-	int			(*write)(struct dw_spi *dws);
-	int			(*read)(struct dw_spi *dws);
-	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
-	void			(*cs_control)(u32 command);
-
-	/* Dma info */
-	int			dma_inited;
-	struct dma_chan		*txchan;
-	struct scatterlist	tx_sgl;
-	struct dma_chan		*rxchan;
-	struct scatterlist	rx_sgl;
-	int			dma_chan_done;
-	struct device		*dma_dev;
-	dma_addr_t		dma_addr; /* phy address of the Data register */
-	struct dw_spi_dma_ops	*dma_ops;
-	void			*dma_priv; /* platform relate info */
-	struct pci_dev		*dmac;
-
-	/* Bus interface info */
-	void			*priv;
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *debugfs;
-#endif
-};
-
-#define dw_readl(dw, name) \
-	__raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writel(dw, name, val) \
-	__raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_readw(dw, name) \
-	__raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
-#define dw_writew(dw, name, val) \
-	__raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
-
-static inline void spi_enable_chip(struct dw_spi *dws, int enable)
-{
-	dw_writel(dws, ssienr, (enable ? 1 : 0));
-}
-
-static inline void spi_set_clk(struct dw_spi *dws, u16 div)
-{
-	dw_writel(dws, baudr, div);
-}
-
-static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
-{
-	if (cs > dws->num_cs)
-		return;
-
-	if (dws->cs_control)
-		dws->cs_control(1);
-
-	dw_writel(dws, ser, 1 << cs);
-}
-
-/* Disable IRQ bits */
-static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
-{
-	u32 new_mask;
-
-	new_mask = dw_readl(dws, imr) & ~mask;
-	dw_writel(dws, imr, new_mask);
-}
-
-/* Enable IRQ bits */
-static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
-{
-	u32 new_mask;
-
-	new_mask = dw_readl(dws, imr) | mask;
-	dw_writel(dws, imr, new_mask);
-}
-
-/*
- * Each SPI slave device to work with dw_api controller should
- * has such a structure claiming its working mode (PIO/DMA etc),
- * which can be save in the "controller_data" member of the
- * struct spi_device
- */
-struct dw_spi_chip {
-	u8 poll_mode;	/* 0 for contoller polling mode */
-	u8 type;	/* SPI/SSP/Micrwire */
-	u8 enable_dma;
-	void (*cs_control)(u32 command);
-};
-
-extern int dw_spi_add_host(struct dw_spi *dws);
-extern void dw_spi_remove_host(struct dw_spi *dws);
-extern int dw_spi_suspend_host(struct dw_spi *dws);
-extern int dw_spi_resume_host(struct dw_spi *dws);
-extern void dw_spi_xfer_done(struct dw_spi *dws);
-
-/* platform related setup */
-extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
-#endif /* DW_SPI_HEADER_H */
diff --git a/include/linux/spi/ifx_modem.h b/include/linux/spi/ifx_modem.h
index a68f3b1..394fec9 100644
--- a/include/linux/spi/ifx_modem.h
+++ b/include/linux/spi/ifx_modem.h
@@ -2,13 +2,18 @@
 #define LINUX_IFX_MODEM_H
 
 struct ifx_modem_platform_data {
-	unsigned short rst_out; /* modem reset out */
-	unsigned short pwr_on;  /* power on */
-	unsigned short rst_pmu; /* reset modem */
-	unsigned short tx_pwr;  /* modem power threshold */
-	unsigned short srdy;    /* SRDY */
-	unsigned short mrdy;    /* MRDY */
-	unsigned short is_6160;	/* Modem type */
+	unsigned short rst_out;		/* modem reset out */
+	unsigned short pwr_on;		/* power on */
+	unsigned short rst_pmu;		/* reset modem */
+	unsigned short tx_pwr;		/* modem power threshold */
+	unsigned short srdy;		/* SRDY */
+	unsigned short mrdy;		/* MRDY */
+	unsigned char modem_type;	/* Modem type */
+	unsigned long max_hz;		/* max SPI frequency */
+	unsigned short use_dma:1;	/* spi protocol driver supplies
+					   dma-able addrs */
 };
+#define IFX_MODEM_6160	1
+#define IFX_MODEM_6260	2
 
 #endif
diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h
index 22ef107..c42cff8 100644
--- a/include/linux/spi/mcp23s08.h
+++ b/include/linux/spi/mcp23s08.h
@@ -2,21 +2,24 @@
 /* FIXME driver should be able to handle IRQs...  */
 
 struct mcp23s08_chip_info {
-	bool	is_present;		/* true iff populated */
-	u8	pullups;		/* BIT(x) means enable pullup x */
+	bool		is_present;	/* true if populated */
+	unsigned	pullups;	/* BIT(x) means enable pullup x */
 };
 
 struct mcp23s08_platform_data {
-	/* Four slaves (numbered 0..3) can share one SPI chipselect, and
-	 * will provide 8..32 GPIOs using 1..4 gpio_chip instances.
+	/* For mcp23s08, up to 4 slaves (numbered 0..3) can share one SPI
+	 * chipselect, each providing 1 gpio_chip instance with 8 gpios.
+	 * For mpc23s17, up to 8 slaves (numbered 0..7) can share one SPI
+	 * chipselect, each providing 1 gpio_chip (port A + port B) with
+	 * 16 gpios.
 	 */
-	struct mcp23s08_chip_info	chip[4];
+	struct mcp23s08_chip_info	chip[8];
 
 	/* "base" is the number of the first GPIO.  Dynamic assignment is
 	 * not currently supported, and even if there are gaps in chip
 	 * addressing the GPIO numbers are sequential .. so for example
 	 * if only slaves 0 and 3 are present, their GPIOs range from
-	 * base to base+15.
+	 * base to base+15 (or base+31 for s17 variant).
 	 */
 	unsigned	base;
 
diff --git a/include/linux/spi/spi_oc_tiny.h b/include/linux/spi/spi_oc_tiny.h
new file mode 100644
index 0000000..1ac529c
--- /dev/null
+++ b/include/linux/spi/spi_oc_tiny.h
@@ -0,0 +1,20 @@
+#ifndef _LINUX_SPI_SPI_OC_TINY_H
+#define _LINUX_SPI_SPI_OC_TINY_H
+
+/**
+ * struct tiny_spi_platform_data - platform data of the OpenCores tiny SPI
+ * @freq:	input clock freq to the core.
+ * @baudwidth:	baud rate divider width of the core.
+ * @gpio_cs_count:	number of gpio pins used for chipselect.
+ * @gpio_cs:	array of gpio pins used for chipselect.
+ *
+ * freq and baudwidth are used only if the divider is programmable.
+ */
+struct tiny_spi_platform_data {
+	unsigned int freq;
+	unsigned int baudwidth;
+	unsigned int gpio_cs_count;
+	int *gpio_cs;
+};
+
+#endif /* _LINUX_SPI_SPI_OC_TINY_H */
diff --git a/include/linux/spi/tsc2005.h b/include/linux/spi/tsc2005.h
new file mode 100644
index 0000000..d9b0c84
--- /dev/null
+++ b/include/linux/spi/tsc2005.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of TSC2005 touchscreen driver
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Contact: Aaro Koskinen <aaro.koskinen@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _LINUX_SPI_TSC2005_H
+#define _LINUX_SPI_TSC2005_H
+
+#include <linux/types.h>
+
+struct tsc2005_platform_data {
+	int		ts_pressure_max;
+	int		ts_pressure_fudge;
+	int		ts_x_max;
+	int		ts_x_fudge;
+	int		ts_y_max;
+	int		ts_y_fudge;
+	int		ts_x_plate_ohm;
+	unsigned int	esd_timeout_ms;
+	void		(*set_reset)(bool enable);
+};
+
+#endif
diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h
index 851b778..73548eb 100644
--- a/include/linux/spinlock_types.h
+++ b/include/linux/spinlock_types.h
@@ -81,14 +81,6 @@ typedef struct spinlock {
 #define __SPIN_LOCK_UNLOCKED(lockname) \
 	(spinlock_t ) __SPIN_LOCK_INITIALIZER(lockname)
 
-/*
- * SPIN_LOCK_UNLOCKED defeats lockdep state tracking and is hence
- * deprecated.
- * Please use DEFINE_SPINLOCK() or __SPIN_LOCK_UNLOCKED() as
- * appropriate.
- */
-#define SPIN_LOCK_UNLOCKED	__SPIN_LOCK_UNLOCKED(old_style_spin_init)
-
 #define DEFINE_SPINLOCK(x)	spinlock_t x = __SPIN_LOCK_UNLOCKED(x)
 
 #include <linux/rwlock_types.h>
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index 489f7b6..402955a 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -85,6 +85,8 @@
 #define  SSB_IMSTATE_AP_RSV	0x00000030 /* Reserved */
 #define  SSB_IMSTATE_IBE	0x00020000 /* In Band Error */
 #define  SSB_IMSTATE_TO		0x00040000 /* Timeout */
+#define  SSB_IMSTATE_BUSY	0x01800000 /* Busy (Backplane rev >= 2.3 only) */
+#define  SSB_IMSTATE_REJECT	0x02000000 /* Reject (Backplane rev >= 2.3 only) */
 #define SSB_INTVEC		0x0F94     /* SB Interrupt Mask */
 #define  SSB_INTVEC_PCI		0x00000001 /* Enable interrupts for PCI */
 #define  SSB_INTVEC_ENET0	0x00000002 /* Enable interrupts for enet 0 */
@@ -97,7 +99,6 @@
 #define  SSB_TMSLOW_RESET	0x00000001 /* Reset */
 #define  SSB_TMSLOW_REJECT_22	0x00000002 /* Reject (Backplane rev 2.2) */
 #define  SSB_TMSLOW_REJECT_23	0x00000004 /* Reject (Backplane rev 2.3) */
-#define  SSB_TMSLOW_PHYCLK	0x00000010 /* MAC PHY Clock Control Enable */
 #define  SSB_TMSLOW_CLOCK	0x00010000 /* Clock Enable */
 #define  SSB_TMSLOW_FGC		0x00020000 /* Force Gated Clocks On */
 #define  SSB_TMSLOW_PE		0x40000000 /* Power Management Enable */
@@ -268,6 +269,8 @@
 /* SPROM Revision 4 */
 #define SSB_SPROM4_BFLLO		0x0044	/* Boardflags (low 16 bits) */
 #define SSB_SPROM4_BFLHI		0x0046  /* Board Flags Hi */
+#define SSB_SPROM4_BFL2LO		0x0048	/* Board flags 2 (low 16 bits) */
+#define SSB_SPROM4_BFL2HI		0x004A	/* Board flags 2 Hi */
 #define SSB_SPROM4_IL0MAC		0x004C	/* 6 byte MAC address for a/b/g/n */
 #define SSB_SPROM4_CCODE		0x0052	/* Country Code (2 bytes) */
 #define SSB_SPROM4_GPIOA		0x0056	/* Gen. Purpose IO # 0 and 1 */
@@ -358,6 +361,8 @@
 #define SSB_SPROM5_CCODE		0x0044	/* Country Code (2 bytes) */
 #define SSB_SPROM5_BFLLO		0x004A	/* Boardflags (low 16 bits) */
 #define SSB_SPROM5_BFLHI		0x004C  /* Board Flags Hi */
+#define SSB_SPROM5_BFL2LO		0x004E	/* Board flags 2 (low 16 bits) */
+#define SSB_SPROM5_BFL2HI		0x0050	/* Board flags 2 Hi */
 #define SSB_SPROM5_IL0MAC		0x0052	/* 6 byte MAC address for a/b/g/n */
 #define SSB_SPROM5_GPIOA		0x0076	/* Gen. Purpose IO # 0 and 1 */
 #define  SSB_SPROM5_GPIOA_P0		0x00FF	/* Pin 0 */
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index ef9476a..db7bcaf 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -129,6 +129,7 @@ struct rpc_create_args {
 struct rpc_clnt *rpc_create(struct rpc_create_args *args);
 struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
 				struct rpc_program *, u32);
+void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 void		rpc_shutdown_client(struct rpc_clnt *);
 void		rpc_release_client(struct rpc_clnt *);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index bef0f53..a0f998c 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -12,7 +12,6 @@
 #include <linux/uio.h>
 #include <linux/socket.h>
 #include <linux/in.h>
-#include <linux/kref.h>
 #include <linux/ktime.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/xdr.h>
@@ -146,7 +145,7 @@ enum xprt_transports {
 };
 
 struct rpc_xprt {
-	struct kref		kref;		/* Reference count */
+	atomic_t		count;		/* Reference count */
 	struct rpc_xprt_ops *	ops;		/* transport methods */
 
 	const struct rpc_timeout *timeout;	/* timeout parms */
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 4d55932..ed6ebe6 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -155,6 +155,15 @@ enum {
 #define SWAP_CLUSTER_MAX 32
 #define COMPACT_CLUSTER_MAX SWAP_CLUSTER_MAX
 
+/*
+ * Ratio between the present memory in the zone and the "gap" that
+ * we're allowing kswapd to shrink in addition to the per-zone high
+ * wmark, even for zones that already have the high wmark satisfied,
+ * in order to provide better per-zone lru behavior. We are ok to
+ * spend not more than 1% of the memory for this zone balancing "gap".
+ */
+#define KSWAPD_ZONE_BALANCE_GAP_RATIO 100
+
 #define SWAP_MAP_MAX	0x3e	/* Max duplication count, in first swap_map */
 #define SWAP_MAP_BAD	0x3f	/* Note pageblock is bad, in first swap_map */
 #define SWAP_HAS_CACHE	0x40	/* Flag page is cached, in first swap_map */
@@ -215,6 +224,7 @@ extern void mark_page_accessed(struct page *);
 extern void lru_add_drain(void);
 extern int lru_add_drain_all(void);
 extern void rotate_reclaimable_page(struct page *page);
+extern void deactivate_page(struct page *page);
 extern void swap_setup(void);
 
 extern void add_page_to_unevictable_list(struct page *page);
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 98664db..83ecc17 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -62,6 +62,7 @@ struct robust_list_head;
 struct getcpu_cache;
 struct old_linux_dirent;
 struct perf_event_attr;
+struct file_handle;
 
 #include <linux/types.h>
 #include <linux/aio_abi.h>
@@ -132,11 +133,11 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 		.class			= &event_class_syscall_enter,	\
 		.event.funcs            = &enter_syscall_print_funcs,	\
 		.data			= (void *)&__syscall_meta_##sname,\
+		.flags			= TRACE_EVENT_FL_CAP_ANY,	\
 	};								\
 	static struct ftrace_event_call __used				\
 	  __attribute__((section("_ftrace_events")))			\
-	 *__event_enter_##sname = &event_enter_##sname;			\
-	__TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)
+	 *__event_enter_##sname = &event_enter_##sname;
 
 #define SYSCALL_TRACE_EXIT_EVENT(sname)					\
 	static struct syscall_metadata __syscall_meta_##sname;		\
@@ -146,11 +147,11 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 		.class			= &event_class_syscall_exit,	\
 		.event.funcs		= &exit_syscall_print_funcs,	\
 		.data			= (void *)&__syscall_meta_##sname,\
+		.flags			= TRACE_EVENT_FL_CAP_ANY,	\
 	};								\
 	static struct ftrace_event_call __used				\
 	  __attribute__((section("_ftrace_events")))			\
-	*__event_exit_##sname = &event_exit_##sname;			\
-	__TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY)
+	*__event_exit_##sname = &event_exit_##sname;
 
 #define SYSCALL_METADATA(sname, nb)				\
 	SYSCALL_TRACE_ENTER_EVENT(sname);			\
@@ -158,6 +159,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 	static struct syscall_metadata __used			\
 	  __syscall_meta_##sname = {				\
 		.name 		= "sys"#sname,			\
+		.syscall_nr	= -1,	/* Filled in at boot */	\
 		.nb_args 	= nb,				\
 		.types		= types_##sname,		\
 		.args		= args_##sname,			\
@@ -175,6 +177,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
 	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,		\
@@ -313,6 +316,8 @@ asmlinkage long sys_clock_settime(clockid_t which_clock,
 				const struct timespec __user *tp);
 asmlinkage long sys_clock_gettime(clockid_t which_clock,
 				struct timespec __user *tp);
+asmlinkage long sys_clock_adjtime(clockid_t which_clock,
+				struct timex __user *tx);
 asmlinkage long sys_clock_getres(clockid_t which_clock,
 				struct timespec __user *tp);
 asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
@@ -820,6 +825,7 @@ asmlinkage long sys_fanotify_init(unsigned int flags, unsigned int event_f_flags
 asmlinkage long sys_fanotify_mark(int fanotify_fd, unsigned int flags,
 				  u64 mask, int fd,
 				  const char  __user *pathname);
+asmlinkage long sys_syncfs(int fd);
 
 int kernel_execve(const char *filename, const char *const argv[], const char *const envp[]);
 
@@ -832,5 +838,10 @@ asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
 			unsigned long prot, unsigned long flags,
 			unsigned long fd, unsigned long pgoff);
 asmlinkage long sys_old_mmap(struct mmap_arg_struct __user *arg);
-
+asmlinkage long sys_name_to_handle_at(int dfd, const char __user *name,
+				      struct file_handle __user *handle,
+				      int __user *mnt_id, int flag);
+asmlinkage long sys_open_by_handle_at(int mountdirfd,
+				      struct file_handle __user *handle,
+				      int flags);
 #endif
diff --git a/include/linux/syscore_ops.h b/include/linux/syscore_ops.h
new file mode 100644
index 0000000..27b3b0b
--- /dev/null
+++ b/include/linux/syscore_ops.h
@@ -0,0 +1,29 @@
+/*
+ *  syscore_ops.h - System core operations.
+ *
+ *  Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ *  This file is released under the GPLv2.
+ */
+
+#ifndef _LINUX_SYSCORE_OPS_H
+#define _LINUX_SYSCORE_OPS_H
+
+#include <linux/list.h>
+
+struct syscore_ops {
+	struct list_head node;
+	int (*suspend)(void);
+	void (*resume)(void);
+	void (*shutdown)(void);
+};
+
+extern void register_syscore_ops(struct syscore_ops *ops);
+extern void unregister_syscore_ops(struct syscore_ops *ops);
+#ifdef CONFIG_PM_SLEEP
+extern int syscore_suspend(void);
+extern void syscore_resume(void);
+#endif
+extern void syscore_shutdown(void);
+
+#endif
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index c906965..20fc303 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -18,9 +18,6 @@ struct compat_timespec;
 struct restart_block {
 	long (*fn)(struct restart_block *);
 	union {
-		struct {
-			unsigned long arg0, arg1, arg2, arg3;
-		};
 		/* For futex_wait and futex_wait_requeue_pi */
 		struct {
 			u32 __user *uaddr;
diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h
index 4c7be22..7071ec5 100644
--- a/include/linux/ti_wilink_st.h
+++ b/include/linux/ti_wilink_st.h
@@ -26,15 +26,6 @@
 #define TI_WILINK_ST_H
 
 /**
- * enum kim_gpio_state - Few protocols such as FM have ACTIVE LOW
- *	gpio states for their chip/core enable gpios
- */
-enum kim_gpio_state {
-	KIM_GPIO_INACTIVE,
-	KIM_GPIO_ACTIVE,
-};
-
-/**
  * enum proto-type - The protocol on WiLink chips which share a
  *	common physical interface like UART.
  */
@@ -42,7 +33,7 @@ enum proto_type {
 	ST_BT,
 	ST_FM,
 	ST_GPS,
-	ST_MAX,
+	ST_MAX_CHANNELS = 16,
 };
 
 /**
@@ -62,6 +53,17 @@ enum proto_type {
  * @priv_data: privdate data holder for the protocol drivers, sent
  *	from the protocol drivers during registration, and sent back on
  *	reg_complete_cb and recv.
+ * @chnl_id: channel id the protocol driver is interested in, the channel
+ *	id is nothing but the 1st byte of the packet in UART frame.
+ * @max_frame_size: size of the largest frame the protocol can receive.
+ * @hdr_len: length of the header structure of the protocol.
+ * @offset_len_in_hdr: this provides the offset of the length field in the
+ *	header structure of the protocol header, to assist ST to know
+ *	how much to receive, if the data is split across UART frames.
+ * @len_size: whether the length field inside the header is 2 bytes
+ *	or 1 byte.
+ * @reserve: the number of bytes ST needs to reserve in the skb being
+ *	prepared for the protocol driver.
  */
 struct st_proto_s {
 	enum proto_type type;
@@ -70,10 +72,17 @@ struct st_proto_s {
 	void (*reg_complete_cb) (void *, char data);
 	long (*write) (struct sk_buff *skb);
 	void *priv_data;
+
+	unsigned char chnl_id;
+	unsigned short max_frame_size;
+	unsigned char hdr_len;
+	unsigned char offset_len_in_hdr;
+	unsigned char len_size;
+	unsigned char reserve;
 };
 
 extern long st_register(struct st_proto_s *);
-extern long st_unregister(enum proto_type);
+extern long st_unregister(struct st_proto_s *);
 
 
 /*
@@ -114,6 +123,7 @@ extern long st_unregister(enum proto_type);
  * @rx_skb: the skb where all data for a protocol gets accumulated,
  *	since tty might not call receive when a complete event packet
  *	is received, the states, count and the skb needs to be maintained.
+ * @rx_chnl: the channel ID for which the data is getting accumalated for.
  * @txq: the list of skbs which needs to be sent onto the TTY.
  * @tx_waitq: if the chip is not in AWAKE state, the skbs needs to be queued
  *	up in here, PM(WAKEUP_IND) data needs to be sent and then the skbs
@@ -135,10 +145,11 @@ struct st_data_s {
 #define ST_TX_SENDING	1
 #define ST_TX_WAKEUP	2
 	unsigned long tx_state;
-	struct st_proto_s *list[ST_MAX];
+	struct st_proto_s *list[ST_MAX_CHANNELS];
 	unsigned long rx_state;
 	unsigned long rx_count;
 	struct sk_buff *rx_skb;
+	unsigned char rx_chnl;
 	struct sk_buff_head txq, tx_waitq;
 	spinlock_t lock;
 	unsigned char	protos_registered;
@@ -146,6 +157,11 @@ struct st_data_s {
 	void *kim_data;
 };
 
+/*
+ * wrapper around tty->ops->write_room to check
+ * availability during firmware download
+ */
+int st_get_uart_wr_room(struct st_data_s *st_gdata);
 /**
  * st_int_write -
  * point this to tty->driver->write or tty->ops->write
@@ -186,8 +202,9 @@ void gps_chrdrv_stub_init(void);
 /* time in msec to wait for
  * line discipline to be installed
  */
-#define LDISC_TIME	500
-#define CMD_RESP_TIME	500
+#define LDISC_TIME	1000
+#define CMD_RESP_TIME	800
+#define CMD_WR_TIME	5000
 #define MAKEWORD(a, b)  ((unsigned short)(((unsigned char)(a)) \
 	| ((unsigned short)((unsigned char)(b))) << 8))
 
@@ -210,6 +227,7 @@ struct chip_version {
 	unsigned short maj_ver;
 };
 
+#define UART_DEV_NAME_LEN 32
 /**
  * struct kim_data_s - the KIM internal data, embedded as the
  *	platform's drv data. One for each ST device in the system.
@@ -225,14 +243,11 @@ struct chip_version {
  *	the ldisc was properly installed.
  * @resp_buffer: data buffer for the .bts fw file name.
  * @fw_entry: firmware class struct to request/release the fw.
- * @gpios: the list of core/chip enable gpios for BT, FM and GPS cores.
  * @rx_state: the rx state for kim's receive func during fw download.
  * @rx_count: the rx count for the kim's receive func during fw download.
  * @rx_skb: all of fw data might not come at once, and hence data storage for
  *	whole of the fw response, only HCI_EVENTs and hence diff from ST's
  *	response.
- * @rfkill: rfkill data for each of the cores to be registered with rfkill.
- * @rf_protos: proto types of the data registered with rfkill sub-system.
  * @core_data: ST core's data, which mainly is the tty's disc_data
  * @version: chip version available via a sysfs entry.
  *
@@ -243,14 +258,16 @@ struct kim_data_s {
 	struct completion kim_rcvd, ldisc_installed;
 	char resp_buffer[30];
 	const struct firmware *fw_entry;
-	long gpios[ST_MAX];
+	long nshutdown;
 	unsigned long rx_state;
 	unsigned long rx_count;
 	struct sk_buff *rx_skb;
-	struct rfkill *rfkill[ST_MAX];
-	enum proto_type rf_protos[ST_MAX];
 	struct st_data_s *core_data;
 	struct chip_version version;
+	unsigned char ldisc_install;
+	unsigned char dev_name[UART_DEV_NAME_LEN];
+	unsigned char flow_cntrl;
+	unsigned long baud_rate;
 };
 
 /**
@@ -262,7 +279,6 @@ long st_kim_start(void *);
 long st_kim_stop(void *);
 
 void st_kim_recv(void *, const unsigned char *, long count);
-void st_kim_chip_toggle(enum proto_type, enum kim_gpio_state);
 void st_kim_complete(void *);
 void kim_st_list_protocols(struct st_data_s *, void *);
 
@@ -338,12 +354,8 @@ struct hci_command {
 
 /* ST LL receiver states */
 #define ST_W4_PACKET_TYPE       0
-#define ST_BT_W4_EVENT_HDR      1
-#define ST_BT_W4_ACL_HDR        2
-#define ST_BT_W4_SCO_HDR        3
-#define ST_BT_W4_DATA           4
-#define ST_FM_W4_EVENT_HDR      5
-#define ST_GPS_W4_EVENT_HDR	6
+#define ST_W4_HEADER		1
+#define ST_W4_DATA		2
 
 /* ST LL state machines */
 #define ST_LL_ASLEEP               0
@@ -397,4 +409,14 @@ struct gps_event_hdr {
 	u16 plen;
 } __attribute__ ((packed));
 
+/* platform data */
+struct ti_st_plat_data {
+	long nshutdown_gpio;
+	unsigned char dev_name[UART_DEV_NAME_LEN]; /* uart name */
+	unsigned char flow_cntrl; /* flow control flag */
+	unsigned long baud_rate;
+	int (*suspend)(struct platform_device *, pm_message_t);
+	int (*resume)(struct platform_device *);
+};
+
 #endif /* TI_WILINK_ST_H */
diff --git a/include/linux/time.h b/include/linux/time.h
index 1e6d3b5..454a262 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -113,8 +113,6 @@ static inline struct timespec timespec_sub(struct timespec lhs,
 #define timespec_valid(ts) \
 	(((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
 
-extern seqlock_t xtime_lock;
-
 extern void read_persistent_clock(struct timespec *ts);
 extern void read_boot_clock(struct timespec *ts);
 extern int update_persistent_clock(struct timespec now);
@@ -125,8 +123,9 @@ extern int timekeeping_suspended;
 unsigned long get_seconds(void);
 struct timespec current_kernel_time(void);
 struct timespec __current_kernel_time(void); /* does not take xtime_lock */
-struct timespec __get_wall_to_monotonic(void); /* does not take xtime_lock */
 struct timespec get_monotonic_coarse(void);
+void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
+				struct timespec *wtom, struct timespec *sleep);
 
 #define CURRENT_TIME		(current_kernel_time())
 #define CURRENT_TIME_SEC	((struct timespec) { get_seconds(), 0 })
@@ -147,8 +146,9 @@ static inline u32 arch_gettimeoffset(void) { return 0; }
 #endif
 
 extern void do_gettimeofday(struct timeval *tv);
-extern int do_settimeofday(struct timespec *tv);
-extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz);
+extern int do_settimeofday(const struct timespec *tv);
+extern int do_sys_settimeofday(const struct timespec *tv,
+			       const struct timezone *tz);
 #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts)
 extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
 struct itimerval;
@@ -162,12 +162,13 @@ extern void getnstime_raw_and_real(struct timespec *ts_raw,
 		struct timespec *ts_real);
 extern void getboottime(struct timespec *ts);
 extern void monotonic_to_bootbased(struct timespec *ts);
+extern void get_monotonic_boottime(struct timespec *ts);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
 extern int timekeeping_valid_for_hres(void);
 extern u64 timekeeping_max_deferment(void);
-extern void update_wall_time(void);
 extern void timekeeping_leap_insert(int leapsecond);
+extern int timekeeping_inject_offset(struct timespec *ts);
 
 struct tms;
 extern void do_sys_times(struct tms *);
@@ -292,6 +293,7 @@ struct itimerval {
 #define CLOCK_MONOTONIC_RAW		4
 #define CLOCK_REALTIME_COARSE		5
 #define CLOCK_MONOTONIC_COARSE		6
+#define CLOCK_BOOTTIME			7
 
 /*
  * The IDs of various hardware clocks:
diff --git a/include/linux/timex.h b/include/linux/timex.h
index d23999f..aa60fe7 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -73,7 +73,7 @@ struct timex {
 	long tolerance;		/* clock frequency tolerance (ppm)
 				 * (read only)
 				 */
-	struct timeval time;	/* (read only) */
+	struct timeval time;	/* (read only, except for ADJ_SETOFFSET) */
 	long tick;		/* (modified) usecs between clock ticks */
 
 	long ppsfreq;           /* pps frequency (scaled ppm) (ro) */
@@ -102,6 +102,7 @@ struct timex {
 #define ADJ_STATUS		0x0010	/* clock status */
 #define ADJ_TIMECONST		0x0020	/* pll time constant */
 #define ADJ_TAI			0x0080	/* set TAI offset */
+#define ADJ_SETOFFSET		0x0100  /* add 'time' to current time */
 #define ADJ_MICRO		0x1000	/* select microsecond resolution */
 #define ADJ_NANO		0x2000	/* select nanosecond resolution */
 #define ADJ_TICK		0x4000	/* tick value */
diff --git a/include/linux/tipc.h b/include/linux/tipc.h
index 1eefa3f..a5b994a 100644
--- a/include/linux/tipc.h
+++ b/include/linux/tipc.h
@@ -2,7 +2,7 @@
  * include/linux/tipc.h: Include file for TIPC socket interface
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -130,12 +130,6 @@ static inline unsigned int tipc_node(__u32 addr)
 #define TIPC_SUB_PORTS		0x01	/* filter for port availability */
 #define TIPC_SUB_SERVICE	0x02	/* filter for service availability */
 #define TIPC_SUB_CANCEL		0x04	/* cancel a subscription */
-#if 0
-/* The following filter options are not currently implemented */
-#define TIPC_SUB_NO_BIND_EVTS	0x04	/* filter out "publish" events */
-#define TIPC_SUB_NO_UNBIND_EVTS	0x08	/* filter out "withdraw" events */
-#define TIPC_SUB_SINGLE_EVT	0x10	/* expire after first event */
-#endif
 
 #define TIPC_WAIT_FOREVER	(~0)	/* timeout for permanent subscription */
 
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h
index 7d42460a..0db2395 100644
--- a/include/linux/tipc_config.h
+++ b/include/linux/tipc_config.h
@@ -2,7 +2,7 @@
  * include/linux/tipc_config.h: Include file for TIPC configuration interface
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005-2007, Wind River Systems
+ * Copyright (c) 2005-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -76,13 +76,6 @@
 #define  TIPC_CMD_SHOW_LINK_STATS   0x000B    /* tx link_name, rx ultra_string */
 #define  TIPC_CMD_SHOW_STATS        0x000F    /* tx unsigned, rx ultra_string */
 
-#if 0
-#define  TIPC_CMD_SHOW_PORT_STATS   0x0008    /* tx port_ref, rx ultra_string */
-#define  TIPC_CMD_RESET_PORT_STATS  0x0009    /* tx port_ref, rx none */
-#define  TIPC_CMD_GET_ROUTES        0x000A    /* tx ?, rx ? */
-#define  TIPC_CMD_GET_LINK_PEER     0x000D    /* tx link_name, rx ? */
-#endif
-
 /*
  * Protected commands:
  * May only be issued by "network administration capable" process.
@@ -96,7 +89,7 @@
 #define  TIPC_CMD_GET_MAX_SUBSCR    0x4006    /* tx none, rx unsigned */
 #define  TIPC_CMD_GET_MAX_ZONES     0x4007    /* obsoleted */
 #define  TIPC_CMD_GET_MAX_CLUSTERS  0x4008    /* obsoleted */
-#define  TIPC_CMD_GET_MAX_NODES     0x4009    /* tx none, rx unsigned */
+#define  TIPC_CMD_GET_MAX_NODES     0x4009    /* obsoleted */
 #define  TIPC_CMD_GET_MAX_SLAVES    0x400A    /* obsoleted */
 #define  TIPC_CMD_GET_NETID         0x400B    /* tx none, rx unsigned */
 
@@ -109,13 +102,6 @@
 #define  TIPC_CMD_DUMP_LOG          0x410B    /* tx none, rx ultra_string */
 #define  TIPC_CMD_RESET_LINK_STATS  0x410C    /* tx link_name, rx none */
 
-#if 0
-#define  TIPC_CMD_CREATE_LINK       0x4103    /* tx link_create, rx none */
-#define  TIPC_CMD_REMOVE_LINK       0x4104    /* tx link_name, rx none */
-#define  TIPC_CMD_BLOCK_LINK        0x4105    /* tx link_name, rx none */
-#define  TIPC_CMD_UNBLOCK_LINK      0x4106    /* tx link_name, rx none */
-#endif
-
 /*
  * Private commands:
  * May only be issued by "network administration capable" process.
@@ -123,16 +109,13 @@
  */
 
 #define  TIPC_CMD_SET_NODE_ADDR     0x8001    /* tx net_addr, rx none */
-#if 0
-#define  TIPC_CMD_SET_ZONE_MASTER   0x8002    /* tx none, rx none */
-#endif
 #define  TIPC_CMD_SET_REMOTE_MNG    0x8003    /* tx unsigned, rx none */
 #define  TIPC_CMD_SET_MAX_PORTS     0x8004    /* tx unsigned, rx none */
 #define  TIPC_CMD_SET_MAX_PUBL      0x8005    /* tx unsigned, rx none */
 #define  TIPC_CMD_SET_MAX_SUBSCR    0x8006    /* tx unsigned, rx none */
 #define  TIPC_CMD_SET_MAX_ZONES     0x8007    /* obsoleted */
 #define  TIPC_CMD_SET_MAX_CLUSTERS  0x8008    /* obsoleted */
-#define  TIPC_CMD_SET_MAX_NODES     0x8009    /* tx unsigned, rx none */
+#define  TIPC_CMD_SET_MAX_NODES     0x8009    /* obsoleted */
 #define  TIPC_CMD_SET_MAX_SLAVES    0x800A    /* obsoleted */
 #define  TIPC_CMD_SET_NETID         0x800B    /* tx unsigned, rx none */
 
@@ -193,6 +176,10 @@
 #define TIPC_DEF_LINK_TOL 1500
 #define TIPC_MAX_LINK_TOL 30000
 
+#if (TIPC_MIN_LINK_TOL < 16)
+#error "TIPC_MIN_LINK_TOL is too small (abort limit may be NaN)"
+#endif
+
 /*
  * Link window limits (min, default, max), in packets
  */
@@ -215,7 +202,7 @@ struct tipc_link_info {
 
 struct tipc_bearer_config {
 	__be32 priority;		/* Range [1,31]. Override per link  */
-	__be32 detect_scope;
+	__be32 disc_domain;		/* <Z.C.N> describing desired nodes */
 	char name[TIPC_MAX_BEARER_NAME];
 };
 
@@ -247,15 +234,6 @@ struct tipc_name_table_query {
 #define TIPC_CFG_NOT_SUPPORTED  "\x84"	/* request is not supported by TIPC */
 #define TIPC_CFG_INVALID_VALUE  "\x85"  /* request has invalid argument value */
 
-#if 0
-/* prototypes TLV structures for proposed commands */
-struct tipc_link_create {
-	__u32   domain;
-	struct tipc_media_addr peer_addr;
-	char bearer_name[TIPC_MAX_BEARER_NAME];
-};
-#endif
-
 /*
  * A TLV consists of a descriptor, followed by the TLV value.
  * TLV descriptor fields are stored in network byte order;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 54e4eaa..9f469c7 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -82,7 +82,7 @@ struct tty_buffer {
 
 
 struct tty_bufhead {
-	struct delayed_work work;
+	struct work_struct work;
 	spinlock_t lock;
 	struct tty_buffer *head;	/* Queue head */
 	struct tty_buffer *tail;	/* Active buffer */
@@ -448,6 +448,7 @@ extern void tty_encode_baud_rate(struct tty_struct *tty,
 						speed_t ibaud, speed_t obaud);
 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);
 
 extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
 extern void tty_ldisc_deref(struct tty_ldisc *);
@@ -584,10 +585,10 @@ extern int pcxe_open(struct tty_struct *tty, struct file *filp);
 
 /* vt.c */
 
-extern int vt_ioctl(struct tty_struct *tty, struct file *file,
+extern int vt_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg);
 
-extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
+extern long vt_compat_ioctl(struct tty_struct *tty,
 		     unsigned int cmd, unsigned long arg);
 
 /* tty_mutex.c */
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index c3d43eb..9deeac8 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -98,8 +98,7 @@
  *
  *	Note: Do not call this function directly, call tty_write_room
  * 
- * int  (*ioctl)(struct tty_struct *tty, struct file * file,
- * 	    unsigned int cmd, unsigned long arg);
+ * int  (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg);
  *
  * 	This routine allows the tty driver to implement
  *	device-specific ioctls.  If the ioctl number passed in cmd
@@ -107,7 +106,7 @@
  *
  *	Optional
  *
- * long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ * long (*compat_ioctl)(struct tty_struct *tty,,
  * 	                unsigned int cmd, unsigned long arg);
  *
  * 	implement ioctl processing for 32 bit process on 64 bit system
@@ -256,9 +255,9 @@ struct tty_operations {
 	void (*flush_chars)(struct tty_struct *tty);
 	int  (*write_room)(struct tty_struct *tty);
 	int  (*chars_in_buffer)(struct tty_struct *tty);
-	int  (*ioctl)(struct tty_struct *tty, struct file * file,
+	int  (*ioctl)(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg);
-	long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+	long (*compat_ioctl)(struct tty_struct *tty,
 			     unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
 	void (*throttle)(struct tty_struct * tty);
@@ -271,8 +270,8 @@ struct tty_operations {
 	void (*set_ldisc)(struct tty_struct *tty);
 	void (*wait_until_sent)(struct tty_struct *tty, int timeout);
 	void (*send_xchar)(struct tty_struct *tty, char ch);
-	int (*tiocmget)(struct tty_struct *tty, struct file *file);
-	int (*tiocmset)(struct tty_struct *tty, struct file *file,
+	int (*tiocmget)(struct tty_struct *tty);
+	int (*tiocmset)(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
 	int (*resize)(struct tty_struct *tty, struct winsize *ws);
 	int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew);
diff --git a/include/linux/types.h b/include/linux/types.h
index c2a9eb4..176da8c 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -150,6 +150,12 @@ typedef unsigned long blkcnt_t;
 #define pgoff_t unsigned long
 #endif
 
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+typedef u64 dma_addr_t;
+#else
+typedef u32 dma_addr_t;
+#endif /* dma_addr_t */
+
 #endif /* __KERNEL__ */
 
 /*
diff --git a/include/linux/usb.h b/include/linux/usb.h
index bd69b65..e63efeb 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -976,6 +976,7 @@ extern int usb_disabled(void);
 #define URB_SETUP_MAP_SINGLE	0x00100000	/* Setup packet DMA mapped */
 #define URB_SETUP_MAP_LOCAL	0x00200000	/* HCD-local setup packet */
 #define URB_DMA_SG_COMBINED	0x00400000	/* S-G entries were combined */
+#define URB_ALIGNED_TEMP_BUFFER	0x00800000	/* Temp buffer was alloc'd */
 
 struct usb_iso_packet_descriptor {
 	unsigned int offset;
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 51410e0..ed91fb6 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -2,6 +2,7 @@ header-y += audio.h
 header-y += cdc.h
 header-y += ch9.h
 header-y += ch11.h
+header-y += functionfs.h
 header-y += gadgetfs.h
 header-y += midi.h
 header-y += g_printer.h
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
index 10ec069..4ebaf08 100644
--- a/include/linux/usb/ch11.h
+++ b/include/linux/usb/ch11.h
@@ -26,6 +26,7 @@
 #define HUB_RESET_TT		9
 #define HUB_GET_TT_STATE	10
 #define HUB_STOP_TT		11
+#define HUB_SET_DEPTH		12
 
 /*
  * Hub class additional requests defined by USB 3.0 spec
@@ -61,6 +62,12 @@
 #define USB_PORT_FEAT_TEST              21
 #define USB_PORT_FEAT_INDICATOR         22
 #define USB_PORT_FEAT_C_PORT_L1         23
+#define USB_PORT_FEAT_C_PORT_LINK_STATE	25
+#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26
+#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27
+#define USB_PORT_FEAT_BH_PORT_RESET     28
+#define USB_PORT_FEAT_C_BH_PORT_RESET   29
+#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30
 
 /*
  * Port feature selectors added by USB 3.0 spec.
@@ -102,7 +109,6 @@ struct usb_port_status {
 #define USB_PORT_STAT_TEST              0x0800
 #define USB_PORT_STAT_INDICATOR         0x1000
 /* bits 13 to 15 are reserved */
-#define USB_PORT_STAT_SUPER_SPEED	0x8000	/* Linux-internal */
 
 /*
  * Additions to wPortStatus bit field from USB 3.0
@@ -110,8 +116,14 @@ struct usb_port_status {
  */
 #define USB_PORT_STAT_LINK_STATE	0x01e0
 #define USB_SS_PORT_STAT_POWER		0x0200
+#define USB_SS_PORT_STAT_SPEED		0x1c00
 #define USB_PORT_STAT_SPEED_5GBPS	0x0000
 /* Valid only if port is enabled */
+/* Bits that are the same from USB 2.0 */
+#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION |	    \
+				USB_PORT_STAT_ENABLE |	    \
+				USB_PORT_STAT_OVERCURRENT | \
+				USB_PORT_STAT_RESET)
 
 /*
  * Definitions for PORT_LINK_STATE values
@@ -132,8 +144,8 @@ struct usb_port_status {
 
 /*
  * wPortChange bit field
- * See USB 2.0 spec Table 11-22
- * Bits 0 to 4 shown, bits 5 to 15 are reserved
+ * See USB 2.0 spec Table 11-22 and USB 2.0 LPM ECN Table-4.10
+ * Bits 0 to 5 shown, bits 6 to 15 are reserved
  */
 #define USB_PORT_STAT_C_CONNECTION	0x0001
 #define USB_PORT_STAT_C_ENABLE		0x0002
@@ -141,6 +153,13 @@ struct usb_port_status {
 #define USB_PORT_STAT_C_OVERCURRENT	0x0008
 #define USB_PORT_STAT_C_RESET		0x0010
 #define USB_PORT_STAT_C_L1		0x0020
+/*
+ * USB 3.0 wPortChange bit fields
+ * See USB 3.0 spec Table 10-11
+ */
+#define USB_PORT_STAT_C_BH_RESET	0x0020
+#define USB_PORT_STAT_C_LINK_STATE	0x0040
+#define USB_PORT_STAT_C_CONFIG_ERROR	0x0080
 
 /*
  * wHubCharacteristics (masks)
@@ -175,7 +194,9 @@ struct usb_hub_status {
  */
 
 #define USB_DT_HUB			(USB_TYPE_CLASS | 0x09)
+#define USB_DT_SS_HUB			(USB_TYPE_CLASS | 0x0a)
 #define USB_DT_HUB_NONVAR_SIZE		7
+#define USB_DT_SS_HUB_SIZE              12
 
 struct usb_hub_descriptor {
 	__u8  bDescLength;
@@ -184,11 +205,22 @@ struct usb_hub_descriptor {
 	__le16 wHubCharacteristics;
 	__u8  bPwrOn2PwrGood;
 	__u8  bHubContrCurrent;
-		/* add 1 bit for hub status change; round to bytes */
-	__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
-	__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
-} __attribute__ ((packed));
 
+	/* 2.0 and 3.0 hubs differ here */
+	union {
+		struct {
+			/* add 1 bit for hub status change; round to bytes */
+			__u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+			__u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
+		}  __attribute__ ((packed)) hs;
+
+		struct {
+			__u8 bHubHdrDecLat;
+			__u16 wHubDelay;
+			__u16 DeviceRemovable;
+		}  __attribute__ ((packed)) ss;
+	} u;
+} __attribute__ ((packed));
 
 /* port indicator status selectors, tables 11-7 and 11-25 */
 #define HUB_LED_AUTO	0
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index ab46194..b72f305 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -584,7 +584,9 @@ struct usb_ss_ep_comp_descriptor {
 
 #define USB_DT_SS_EP_COMP_SIZE		6
 /* Bits 4:0 of bmAttributes if this is a bulk endpoint */
-#define USB_SS_MAX_STREAMS(p)		(1 << (p & 0x1f))
+#define USB_SS_MAX_STREAMS(p)		(1 << ((p) & 0x1f))
+/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
+#define USB_SS_MULT(p)			(1 + ((p) & 0x3))
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index 2e262cb..6563802 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -127,7 +127,9 @@ struct ehci_regs {
 #define PORT_WKDISC_E	(1<<21)		/* wake on disconnect (enable) */
 #define PORT_WKCONN_E	(1<<20)		/* wake on connect (enable) */
 /* 19:16 for port testing */
-#define PORT_TEST_PKT	(0x4<<16)	/* Port Test Control - packet test */
+#define PORT_TEST(x)	(((x)&0xf)<<16)	/* Port Test Control */
+#define PORT_TEST_PKT	PORT_TEST(0x4)	/* Port Test Control - packet test */
+#define PORT_TEST_FORCE	PORT_TEST(0x5)	/* Port Test Control - force enable */
 #define PORT_LED_OFF	(0<<14)
 #define PORT_LED_AMBER	(1<<14)
 #define PORT_LED_GREEN	(2<<14)
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index a854fe8..0097136 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -76,6 +76,10 @@ struct usb_hcd {
 	struct kref		kref;		/* reference counter */
 
 	const char		*product_desc;	/* product/vendor string */
+	int			speed;		/* Speed for this roothub.
+						 * May be different from
+						 * hcd->driver->flags & HCD_MASK
+						 */
 	char			irq_descr[24];	/* driver + bus # */
 
 	struct timer_list	rh_timer;	/* drives root-hub polling */
@@ -99,6 +103,8 @@ struct usb_hcd {
 #define HCD_FLAG_POLL_RH		2	/* poll for rh status? */
 #define HCD_FLAG_POLL_PENDING		3	/* status has changed? */
 #define HCD_FLAG_WAKEUP_PENDING		4	/* root hub is resuming? */
+#define HCD_FLAG_RH_RUNNING		5	/* root hub is running? */
+#define HCD_FLAG_DEAD			6	/* controller has died? */
 
 	/* The flags can be tested using these macros; they are likely to
 	 * be slightly faster than test_bit().
@@ -108,6 +114,8 @@ struct usb_hcd {
 #define HCD_POLL_RH(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_RH))
 #define HCD_POLL_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_POLL_PENDING))
 #define HCD_WAKEUP_PENDING(hcd)	((hcd)->flags & (1U << HCD_FLAG_WAKEUP_PENDING))
+#define HCD_RH_RUNNING(hcd)	((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
+#define HCD_DEAD(hcd)		((hcd)->flags & (1U << HCD_FLAG_DEAD))
 
 	/* Flags that get set only during HCD registration or removal. */
 	unsigned		rh_registered:1;/* is root hub registered? */
@@ -138,7 +146,9 @@ struct usb_hcd {
 	 * bandwidth_mutex should be dropped after a successful control message
 	 * to the device, or resetting the bandwidth after a failed attempt.
 	 */
-	struct mutex		bandwidth_mutex;
+	struct mutex		*bandwidth_mutex;
+	struct usb_hcd		*shared_hcd;
+	struct usb_hcd		*primary_hcd;
 
 
 #define HCD_BUFFER_POOLS	4
@@ -201,6 +211,7 @@ struct hc_driver {
 	int	flags;
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
 #define	HCD_LOCAL_MEM	0x0002		/* HC needs local memory */
+#define	HCD_SHARED	0x0004		/* Two (or more) usb_hcds share HW */
 #define	HCD_USB11	0x0010		/* USB 1.1 */
 #define	HCD_USB2	0x0020		/* USB 2.0 */
 #define	HCD_USB3	0x0040		/* USB 3.0 */
@@ -234,6 +245,19 @@ struct hc_driver {
 	int	(*urb_dequeue)(struct usb_hcd *hcd,
 				struct urb *urb, int status);
 
+	/*
+	 * (optional) these hooks allow an HCD to override the default DMA
+	 * mapping and unmapping routines.  In general, they shouldn't be
+	 * necessary unless the host controller has special DMA requirements,
+	 * such as alignment contraints.  If these are not specified, the
+	 * general usb_hcd_(un)?map_urb_for_dma functions will be used instead
+	 * (and it may be a good idea to call these functions in your HCD
+	 * implementation)
+	 */
+	int	(*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,
+				   gfp_t mem_flags);
+	void    (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);
+
 	/* hw synch, freeing endpoint resources that urb_dequeue can't */
 	void	(*endpoint_disable)(struct usb_hcd *hcd,
 			struct usb_host_endpoint *ep);
@@ -330,8 +354,10 @@ extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_hcd_unlink_urb(struct urb *urb, int status);
 extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
 		int status);
-extern void unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *);
-extern void unmap_urb_for_dma(struct usb_hcd *, struct urb *);
+extern int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+		gfp_t mem_flags);
+extern void usb_hcd_unmap_urb_setup_for_dma(struct usb_hcd *, struct urb *);
+extern void usb_hcd_unmap_urb_for_dma(struct usb_hcd *, struct urb *);
 extern void usb_hcd_flush_endpoint(struct usb_device *udev,
 		struct usb_host_endpoint *ep);
 extern void usb_hcd_disable_endpoint(struct usb_device *udev,
@@ -347,8 +373,12 @@ extern int usb_hcd_get_frame_number(struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver,
 		struct device *dev, const char *bus_name);
+extern struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
+		struct device *dev, const char *bus_name,
+		struct usb_hcd *shared_hcd);
 extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd);
 extern void usb_put_hcd(struct usb_hcd *hcd);
+extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
 		unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
@@ -622,13 +652,6 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
 
 /*-------------------------------------------------------------------------*/
 
-/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */
-/* bleech -- resurfaced in 2.4.11 or 2.4.12 */
-#define bitmap	DeviceRemovable
-
-
-/*-------------------------------------------------------------------------*/
-
 /* random stuff */
 
 #define	RUN_CONTEXT (in_irq() ? "in_irq" \
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 3675e03..3657403 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -55,7 +55,7 @@ enum otg_control_type {
 
 /**
  * struct msm_otg_platform_data - platform device data
- *              for msm72k_otg driver.
+ *              for msm_otg driver.
  * @phy_init_seq: PHY configuration sequence. val, reg pairs
  *              terminated by -1.
  * @vbus_power: VBUS power on/off routine.
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index a1a1e7a..6e40718 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -66,6 +66,7 @@ struct otg_transceiver {
 
 	u8			default_a;
 	enum usb_otg_state	state;
+	enum usb_xceiv_events	last_event;
 
 	struct usb_bus		*host;
 	struct usb_gadget	*gadget;
@@ -74,7 +75,7 @@ struct otg_transceiver {
 	void __iomem			*io_priv;
 
 	/* for notification of usb_xceiv_events */
-	struct blocking_notifier_head	notifier;
+	struct atomic_notifier_head	notifier;
 
 	/* to pass extra port status to the root hub */
 	u16			port_status;
@@ -234,13 +235,13 @@ otg_start_srp(struct otg_transceiver *otg)
 static inline int
 otg_register_notifier(struct otg_transceiver *otg, struct notifier_block *nb)
 {
-	return blocking_notifier_chain_register(&otg->notifier, nb);
+	return atomic_notifier_chain_register(&otg->notifier, nb);
 }
 
 static inline void
 otg_unregister_notifier(struct otg_transceiver *otg, struct notifier_block *nb)
 {
-	blocking_notifier_chain_unregister(&otg->notifier, nb);
+	atomic_notifier_chain_unregister(&otg->notifier, nb);
 }
 
 /* for OTG controller drivers (and maybe other stuff) */
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index c904913..b29f70b 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -191,7 +191,8 @@ static inline void usb_set_serial_data(struct usb_serial *serial, void *data)
  * @id_table: pointer to a list of usb_device_id structures that define all
  *	of the devices this structure can support.
  * @num_ports: the number of different ports this device will have.
- * @bulk_in_size: bytes to allocate for bulk-in buffer (0 = end-point size)
+ * @bulk_in_size: minimum number of bytes to allocate for bulk-in buffer
+ *	(0 = end-point size)
  * @bulk_out_size: bytes to allocate for bulk-out buffer (0 = end-point size)
  * @calc_num_ports: pointer to a function to determine how many ports this
  *	device has dynamically.  It will be called after the probe()
@@ -260,7 +261,7 @@ struct usb_serial_driver {
 			const unsigned char *buf, int count);
 	/* Called only by the tty layer */
 	int  (*write_room)(struct tty_struct *tty);
-	int  (*ioctl)(struct tty_struct *tty, struct file *file,
+	int  (*ioctl)(struct tty_struct *tty,
 		      unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty,
 			struct usb_serial_port *port, struct ktermios *old);
@@ -268,8 +269,8 @@ struct usb_serial_driver {
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	void (*throttle)(struct tty_struct *tty);
 	void (*unthrottle)(struct tty_struct *tty);
-	int  (*tiocmget)(struct tty_struct *tty, struct file *file);
-	int  (*tiocmset)(struct tty_struct *tty, struct file *file,
+	int  (*tiocmget)(struct tty_struct *tty);
+	int  (*tiocmset)(struct tty_struct *tty,
 			 unsigned int set, unsigned int clear);
 	int  (*get_icount)(struct tty_struct *tty,
 			struct serial_icounter_struct *icount);
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index 82b1507..9595796 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -184,4 +184,9 @@
 struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops,
 					unsigned int flags);
 
+#ifdef CONFIG_USB_ULPI_VIEWPORT
+/* access ops for controllers with a viewport register */
+extern struct otg_io_access_ops ulpi_viewport_access_ops;
+#endif
+
 #endif /* __LINUX_USB_ULPI_H */
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index 833e676..461c011 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -220,12 +220,12 @@ static inline unsigned long node_page_state(int node,
 		zone_page_state(&zones[ZONE_MOVABLE], item);
 }
 
-extern void zone_statistics(struct zone *, struct zone *);
+extern void zone_statistics(struct zone *, struct zone *, gfp_t gfp);
 
 #else
 
 #define node_page_state(node, item) global_page_state(item)
-#define zone_statistics(_zl,_z) do { } while (0)
+#define zone_statistics(_zl, _z, gfp) do { } while (0)
 
 #endif /* CONFIG_NUMA */
 
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index 6625cc1..4d05e14 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -142,14 +142,6 @@ static inline bool vt_force_oops_output(struct vc_data *vc)
 	return false;
 }
 
-/*
- * vc_screen.c shares this temporary buffer with the console write code so that
- * we can easily avoid touching user space while holding the console spinlock.
- */
-
-#define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
-extern char con_buf[CON_BUF_SIZE];
-extern struct mutex con_buf_mtx;
 extern char vt_dont_switch;
 extern int default_utf8;
 extern int global_cursor_default;
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index f7998a3..f584aba 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -286,11 +286,15 @@ enum {
  * any specific CPU, not concurrency managed, and all queued works are
  * executed immediately as long as max_active limit is not reached and
  * resources are available.
+ *
+ * system_freezable_wq is equivalent to system_wq except that it's
+ * freezable.
  */
 extern struct workqueue_struct *system_wq;
 extern struct workqueue_struct *system_long_wq;
 extern struct workqueue_struct *system_nrt_wq;
 extern struct workqueue_struct *system_unbound_wq;
+extern struct workqueue_struct *system_freezable_wq;
 
 extern struct workqueue_struct *
 __alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index e6131ef..6050783 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -42,11 +42,13 @@
 #define XATTR_SMACK_IPOUT "SMACK64IPOUT"
 #define XATTR_SMACK_EXEC "SMACK64EXEC"
 #define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE"
+#define XATTR_SMACK_MMAP "SMACK64MMAP"
 #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX
 #define XATTR_NAME_SMACKIPIN	XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
 #define XATTR_NAME_SMACKIPOUT	XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
 #define XATTR_NAME_SMACKEXEC	XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC
 #define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE
+#define XATTR_NAME_SMACKMMAP XATTR_SECURITY_PREFIX XATTR_SMACK_MMAP
 
 #define XATTR_CAPS_SUFFIX "capability"
 #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 930fdd2..22e61fd 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -84,6 +84,16 @@ struct xfrm_replay_state {
 	__u32	bitmap;
 };
 
+struct xfrm_replay_state_esn {
+	unsigned int	bmp_len;
+	__u32		oseq;
+	__u32		seq;
+	__u32		oseq_hi;
+	__u32		seq_hi;
+	__u32		replay_window;
+	__u32		bmp[0];
+};
+
 struct xfrm_algo {
 	char		alg_name[64];
 	unsigned int	alg_key_len;    /* in bits */
@@ -284,6 +294,7 @@ enum xfrm_attr_type_t {
 	XFRMA_ALG_AUTH_TRUNC,	/* struct xfrm_algo_auth */
 	XFRMA_MARK,		/* struct xfrm_mark */
 	XFRMA_TFCPAD,		/* __u32 */
+	XFRMA_REPLAY_ESN_VAL,	/* struct xfrm_replay_esn */
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -350,6 +361,8 @@ struct xfrm_usersa_info {
 #define XFRM_STATE_WILDRECV	8
 #define XFRM_STATE_ICMP		16
 #define XFRM_STATE_AF_UNSPEC	32
+#define XFRM_STATE_ALIGN4	64
+#define XFRM_STATE_ESN		128
 };
 
 struct xfrm_usersa_id {
diff --git a/include/linux/zlib.h b/include/linux/zlib.h
index 40c49cb..9c5a6b4 100644
--- a/include/linux/zlib.h
+++ b/include/linux/zlib.h
@@ -179,11 +179,16 @@ typedef z_stream *z_streamp;
 
                         /* basic functions */
 
-extern int zlib_deflate_workspacesize (void);
+extern int zlib_deflate_workspacesize (int windowBits, int memLevel);
 /*
    Returns the number of bytes that needs to be allocated for a per-
-   stream workspace.  A pointer to this number of bytes should be
-   returned in stream->workspace before calling zlib_deflateInit().
+   stream workspace with the specified parameters.  A pointer to this
+   number of bytes should be returned in stream->workspace before
+   you call zlib_deflateInit() or zlib_deflateInit2().  If you call
+   zlib_deflateInit(), specify windowBits = MAX_WBITS and memLevel =
+   MAX_MEM_LEVEL here.  If you call zlib_deflateInit2(), the windowBits
+   and memLevel parameters passed to zlib_deflateInit2() must not
+   exceed those passed here.
 */
 
 /* 
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index 071fd7a..6b75a69 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -139,6 +139,8 @@ do { \
  */
 
 enum p9_msg_t {
+	P9_TSYNCFS = 0,
+	P9_RSYNCFS,
 	P9_TLERROR = 6,
 	P9_RLERROR,
 	P9_TSTATFS = 8,
@@ -688,7 +690,11 @@ struct p9_rwstat {
  * @id: protocol operating identifier of type &p9_msg_t
  * @tag: transaction id of the request
  * @offset: used by marshalling routines to track currentposition in buffer
- * @capacity: used by marshalling routines to track total capacity
+ * @capacity: used by marshalling routines to track total malloc'd capacity
+ * @pubuf: Payload user buffer given by the caller
+ * @pubuf: Payload kernel buffer given by the caller
+ * @pbuf_size: pubuf/pkbuf(only one will be !NULL) size to be read/write.
+ * @private: For transport layer's use.
  * @sdata: payload
  *
  * &p9_fcall represents the structure for all 9P RPC
@@ -705,6 +711,10 @@ struct p9_fcall {
 
 	size_t offset;
 	size_t capacity;
+	char __user *pubuf;
+	char *pkbuf;
+	size_t pbuf_size;
+	void *private;
 
 	uint8_t *sdata;
 };
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 83ba6a4..0a30977 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -230,6 +230,7 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
 		gid_t gid, struct p9_qid *qid);
 int p9_client_clunk(struct p9_fid *fid);
 int p9_client_fsync(struct p9_fid *fid, int datasync);
+int p9_client_sync_fs(struct p9_fid *fid);
 int p9_client_remove(struct p9_fid *fid);
 int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
 							u64 offset, u32 count);
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 6d5886e..82868f1 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -26,11 +26,19 @@
 #ifndef NET_9P_TRANSPORT_H
 #define NET_9P_TRANSPORT_H
 
+#define P9_TRANS_PREF_PAYLOAD_MASK 0x1
+
+/* Default. Add Payload to PDU before sending it down to transport layer */
+#define P9_TRANS_PREF_PAYLOAD_DEF  0x0
+/* Send pay load seperately to transport layer along with PDU.*/
+#define P9_TRANS_PREF_PAYLOAD_SEP  0x1
+
 /**
  * struct p9_trans_module - transport module interface
  * @list: used to maintain a list of currently available transports
  * @name: the human-readable name of the transport
  * @maxsize: transport provided maximum packet size
+ * @pref: Preferences of this transport
  * @def: set if this transport should be considered the default
  * @create: member function to create a new connection on this transport
  * @request: member function to issue a request to the transport
@@ -47,6 +55,7 @@ struct p9_trans_module {
 	struct list_head list;
 	char *name;		/* name of transport */
 	int maxsize;		/* max message size of transport */
+	int pref;               /* Preferences of this transport */
 	int def;		/* this transport should be default */
 	struct module *owner;
 	int (*create)(struct p9_client *, const char *, char *);
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 0c5e725..4375043 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -64,6 +64,11 @@ struct bt_security {
 
 #define BT_DEFER_SETUP	7
 
+#define BT_FLUSHABLE	8
+
+#define BT_FLUSHABLE_OFF	0
+#define BT_FLUSHABLE_ON		1
+
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
 #define BT_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -200,4 +205,32 @@ extern void bt_sysfs_cleanup(void);
 
 extern struct dentry *bt_debugfs;
 
+#ifdef CONFIG_BT_L2CAP
+int l2cap_init(void);
+void l2cap_exit(void);
+#else
+static inline int l2cap_init(void)
+{
+	return 0;
+}
+
+static inline void l2cap_exit(void)
+{
+}
+#endif
+
+#ifdef CONFIG_BT_SCO
+int sco_init(void);
+void sco_exit(void);
+#else
+static inline int sco_init(void)
+{
+	return 0;
+}
+
+static inline void sco_exit(void)
+{
+}
+#endif
+
 #endif /* __BLUETOOTH_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 29a7a8c..ec6acf2 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -76,6 +76,14 @@ enum {
 	HCI_INQUIRY,
 
 	HCI_RAW,
+
+	HCI_SETUP,
+	HCI_AUTO_OFF,
+	HCI_MGMT,
+	HCI_PAIRABLE,
+	HCI_SERVICE_CACHE,
+	HCI_LINK_KEYS,
+	HCI_DEBUG_KEYS,
 };
 
 /* HCI ioctl defines */
@@ -111,6 +119,7 @@ enum {
 #define HCI_PAIRING_TIMEOUT	(60000)	/* 60 seconds */
 #define HCI_IDLE_TIMEOUT	(6000)	/* 6 seconds */
 #define HCI_INIT_TIMEOUT	(10000)	/* 10 seconds */
+#define HCI_CMD_TIMEOUT		(1000)	/* 1 seconds */
 
 /* HCI data types */
 #define HCI_COMMAND_PKT		0x01
@@ -150,6 +159,7 @@ enum {
 #define EDR_ESCO_MASK  (ESCO_2EV3 | ESCO_3EV3 | ESCO_2EV5 | ESCO_3EV5)
 
 /* ACL flags */
+#define ACL_START_NO_FLUSH	0x00
 #define ACL_CONT		0x01
 #define ACL_START		0x02
 #define ACL_ACTIVE_BCAST	0x04
@@ -159,6 +169,8 @@ enum {
 #define SCO_LINK	0x00
 #define ACL_LINK	0x01
 #define ESCO_LINK	0x02
+/* Low Energy links do not have defined link type. Use invented one */
+#define LE_LINK		0x80
 
 /* LMP features */
 #define LMP_3SLOT	0x01
@@ -183,17 +195,25 @@ enum {
 #define LMP_PSCHEME	0x02
 #define LMP_PCONTROL	0x04
 
+#define LMP_RSSI_INQ	0x40
 #define LMP_ESCO	0x80
 
 #define LMP_EV4		0x01
 #define LMP_EV5		0x02
+#define LMP_LE		0x40
 
 #define LMP_SNIFF_SUBR	0x02
+#define LMP_PAUSE_ENC	0x04
 #define LMP_EDR_ESCO_2M	0x20
 #define LMP_EDR_ESCO_3M	0x40
 #define LMP_EDR_3S_ESCO	0x80
 
+#define LMP_EXT_INQ	0x01
 #define LMP_SIMPLE_PAIR	0x08
+#define LMP_NO_FLUSH	0x40
+
+#define LMP_LSTO	0x01
+#define LMP_INQ_TX_PWR	0x02
 
 /* Connection modes */
 #define HCI_CM_ACTIVE	0x0000
@@ -225,6 +245,8 @@ enum {
 #define HCI_AT_GENERAL_BONDING_MITM	0x05
 
 /* -----  HCI Commands ---- */
+#define HCI_OP_NOP			0x0000
+
 #define HCI_OP_INQUIRY			0x0401
 struct hci_cp_inquiry {
 	__u8     lap[3];
@@ -292,11 +314,19 @@ struct hci_cp_pin_code_reply {
 	__u8     pin_len;
 	__u8     pin_code[16];
 } __packed;
+struct hci_rp_pin_code_reply {
+	__u8     status;
+	bdaddr_t bdaddr;
+} __packed;
 
 #define HCI_OP_PIN_CODE_NEG_REPLY	0x040e
 struct hci_cp_pin_code_neg_reply {
 	bdaddr_t bdaddr;
 } __packed;
+struct hci_rp_pin_code_neg_reply {
+	__u8     status;
+	bdaddr_t bdaddr;
+} __packed;
 
 #define HCI_OP_CHANGE_CONN_PTYPE	0x040f
 struct hci_cp_change_conn_ptype {
@@ -377,6 +407,31 @@ struct hci_cp_reject_sync_conn_req {
 	__u8     reason;
 } __packed;
 
+#define HCI_OP_IO_CAPABILITY_REPLY	0x042b
+struct hci_cp_io_capability_reply {
+	bdaddr_t bdaddr;
+	__u8     capability;
+	__u8     oob_data;
+	__u8     authentication;
+} __packed;
+
+#define HCI_OP_USER_CONFIRM_REPLY		0x042c
+struct hci_cp_user_confirm_reply {
+	bdaddr_t bdaddr;
+} __packed;
+struct hci_rp_user_confirm_reply {
+	__u8     status;
+	bdaddr_t bdaddr;
+} __packed;
+
+#define HCI_OP_USER_CONFIRM_NEG_REPLY	0x042d
+
+#define HCI_OP_IO_CAPABILITY_NEG_REPLY	0x0434
+struct hci_cp_io_capability_neg_reply {
+	bdaddr_t bdaddr;
+	__u8     reason;
+} __packed;
+
 #define HCI_OP_SNIFF_MODE		0x0803
 struct hci_cp_sniff_mode {
 	__le16   handle;
@@ -474,6 +529,12 @@ struct hci_cp_set_event_flt {
 #define HCI_CONN_SETUP_AUTO_OFF	0x01
 #define HCI_CONN_SETUP_AUTO_ON	0x02
 
+#define HCI_OP_DELETE_STORED_LINK_KEY	0x0c12
+struct hci_cp_delete_stored_link_key {
+	bdaddr_t bdaddr;
+	__u8     delete_all;
+} __packed;
+
 #define HCI_OP_WRITE_LOCAL_NAME		0x0c13
 struct hci_cp_write_local_name {
 	__u8     name[248];
@@ -537,6 +598,8 @@ struct hci_cp_host_buffer_size {
 	__le16   sco_max_pkt;
 } __packed;
 
+#define HCI_OP_WRITE_INQUIRY_MODE	0x0c45
+
 #define HCI_OP_READ_SSP_MODE		0x0c55
 struct hci_rp_read_ssp_mode {
 	__u8     status;
@@ -548,6 +611,8 @@ struct hci_cp_write_ssp_mode {
 	__u8     mode;
 } __packed;
 
+#define HCI_OP_READ_INQ_RSP_TX_POWER	0x0c58
+
 #define HCI_OP_READ_LOCAL_VERSION	0x1001
 struct hci_rp_read_local_version {
 	__u8     status;
@@ -593,6 +658,47 @@ struct hci_rp_read_bd_addr {
 	bdaddr_t bdaddr;
 } __packed;
 
+#define HCI_OP_LE_SET_EVENT_MASK	0x2001
+struct hci_cp_le_set_event_mask {
+	__u8     mask[8];
+} __packed;
+
+#define HCI_OP_LE_READ_BUFFER_SIZE	0x2002
+struct hci_rp_le_read_buffer_size {
+	__u8     status;
+	__le16   le_mtu;
+	__u8     le_max_pkt;
+} __packed;
+
+#define HCI_OP_LE_CREATE_CONN		0x200d
+struct hci_cp_le_create_conn {
+	__le16   scan_interval;
+	__le16   scan_window;
+	__u8     filter_policy;
+	__u8     peer_addr_type;
+	bdaddr_t peer_addr;
+	__u8     own_address_type;
+	__le16   conn_interval_min;
+	__le16   conn_interval_max;
+	__le16   conn_latency;
+	__le16   supervision_timeout;
+	__le16   min_ce_len;
+	__le16   max_ce_len;
+} __packed;
+
+#define HCI_OP_LE_CREATE_CONN_CANCEL	0x200e
+
+#define HCI_OP_LE_CONN_UPDATE		0x2013
+struct hci_cp_le_conn_update {
+	__le16   handle;
+	__le16   conn_interval_min;
+	__le16   conn_interval_max;
+	__le16   conn_latency;
+	__le16   supervision_timeout;
+	__le16   min_ce_len;
+	__le16   max_ce_len;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE		0x01
 
@@ -833,6 +939,20 @@ struct hci_ev_io_capa_request {
 	bdaddr_t bdaddr;
 } __packed;
 
+#define HCI_EV_IO_CAPA_REPLY		0x32
+struct hci_ev_io_capa_reply {
+	bdaddr_t bdaddr;
+	__u8     capability;
+	__u8     oob_data;
+	__u8     authentication;
+} __packed;
+
+#define HCI_EV_USER_CONFIRM_REQUEST	0x33
+struct hci_ev_user_confirm_req {
+	bdaddr_t	bdaddr;
+	__le32		passkey;
+} __packed;
+
 #define HCI_EV_SIMPLE_PAIR_COMPLETE	0x36
 struct hci_ev_simple_pair_complete {
 	__u8     status;
@@ -845,6 +965,25 @@ struct hci_ev_remote_host_features {
 	__u8     features[8];
 } __packed;
 
+#define HCI_EV_LE_META			0x3e
+struct hci_ev_le_meta {
+	__u8     subevent;
+} __packed;
+
+/* Low energy meta events */
+#define HCI_EV_LE_CONN_COMPLETE		0x01
+struct hci_ev_le_conn_complete {
+	__u8     status;
+	__le16   handle;
+	__u8     role;
+	__u8     bdaddr_type;
+	bdaddr_t bdaddr;
+	__le16   interval;
+	__le16   latency;
+	__le16   supervision_timeout;
+	__u8     clk_accurancy;
+} __packed;
+
 /* Internal events generated by Bluetooth stack */
 #define HCI_EV_STACK_INTERNAL	0xfd
 struct hci_ev_stack_internal {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d2cf884..441dadb 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -60,12 +60,28 @@ struct hci_conn_hash {
 	spinlock_t       lock;
 	unsigned int     acl_num;
 	unsigned int     sco_num;
+	unsigned int     le_num;
 };
 
 struct bdaddr_list {
 	struct list_head list;
 	bdaddr_t bdaddr;
 };
+
+struct bt_uuid {
+	struct list_head list;
+	u8 uuid[16];
+	u8 svc_hint;
+};
+
+struct link_key {
+	struct list_head list;
+	bdaddr_t bdaddr;
+	u8 type;
+	u8 val[16];
+	u8 pin_len;
+};
+
 #define NUM_REASSEMBLY 4
 struct hci_dev {
 	struct list_head list;
@@ -80,13 +96,18 @@ struct hci_dev {
 	bdaddr_t	bdaddr;
 	__u8		dev_name[248];
 	__u8		dev_class[3];
+	__u8		major_class;
+	__u8		minor_class;
 	__u8		features[8];
 	__u8		commands[64];
 	__u8		ssp_mode;
 	__u8		hci_ver;
 	__u16		hci_rev;
+	__u8		lmp_ver;
 	__u16		manufacturer;
+	__le16		lmp_subver;
 	__u16		voice_setting;
+	__u8		io_capability;
 
 	__u16		pkt_type;
 	__u16		esco_type;
@@ -102,18 +123,26 @@ struct hci_dev {
 	atomic_t	cmd_cnt;
 	unsigned int	acl_cnt;
 	unsigned int	sco_cnt;
+	unsigned int	le_cnt;
 
 	unsigned int	acl_mtu;
 	unsigned int	sco_mtu;
+	unsigned int	le_mtu;
 	unsigned int	acl_pkts;
 	unsigned int	sco_pkts;
+	unsigned int	le_pkts;
 
-	unsigned long	cmd_last_tx;
 	unsigned long	acl_last_tx;
 	unsigned long	sco_last_tx;
+	unsigned long	le_last_tx;
 
 	struct workqueue_struct	*workqueue;
 
+	struct work_struct	power_on;
+	struct work_struct	power_off;
+	struct timer_list	off_timer;
+
+	struct timer_list	cmd_timer;
 	struct tasklet_struct	cmd_task;
 	struct tasklet_struct	rx_task;
 	struct tasklet_struct	tx_task;
@@ -129,12 +158,17 @@ struct hci_dev {
 	wait_queue_head_t	req_wait_q;
 	__u32			req_status;
 	__u32			req_result;
-	__u16			req_last_cmd;
+
+	__u16			init_last_cmd;
 
 	struct inquiry_cache	inq_cache;
 	struct hci_conn_hash	conn_hash;
 	struct list_head	blacklist;
 
+	struct list_head	uuids;
+
+	struct list_head	link_keys;
+
 	struct hci_dev_stats	stat;
 
 	struct sk_buff_head	driver_init;
@@ -165,31 +199,37 @@ struct hci_dev {
 struct hci_conn {
 	struct list_head list;
 
-	atomic_t	 refcnt;
-	spinlock_t	 lock;
-
-	bdaddr_t	 dst;
-	__u16		 handle;
-	__u16		 state;
-	__u8             mode;
-	__u8		 type;
-	__u8		 out;
-	__u8		 attempt;
-	__u8		 dev_class[3];
-	__u8             features[8];
-	__u8             ssp_mode;
-	__u16            interval;
-	__u16            pkt_type;
-	__u16            link_policy;
-	__u32		 link_mode;
-	__u8             auth_type;
-	__u8             sec_level;
-	__u8		 pending_sec_level;
-	__u8             power_save;
-	__u16            disc_timeout;
-	unsigned long	 pend;
-
-	unsigned int	 sent;
+	atomic_t	refcnt;
+	spinlock_t	lock;
+
+	bdaddr_t	dst;
+	__u16		handle;
+	__u16		state;
+	__u8		mode;
+	__u8		type;
+	__u8		out;
+	__u8		attempt;
+	__u8		dev_class[3];
+	__u8		features[8];
+	__u8		ssp_mode;
+	__u16		interval;
+	__u16		pkt_type;
+	__u16		link_policy;
+	__u32		link_mode;
+	__u8		auth_type;
+	__u8		sec_level;
+	__u8		pending_sec_level;
+	__u8		pin_length;
+	__u8		io_capability;
+	__u8		power_save;
+	__u16		disc_timeout;
+	unsigned long	pend;
+
+	__u8		remote_cap;
+	__u8		remote_oob;
+	__u8		remote_auth;
+
+	unsigned int	sent;
 
 	struct sk_buff_head data_q;
 
@@ -208,6 +248,10 @@ struct hci_conn {
 	void		*priv;
 
 	struct hci_conn	*link;
+
+	void (*connect_cfm_cb)	(struct hci_conn *conn, u8 status);
+	void (*security_cfm_cb)	(struct hci_conn *conn, u8 status);
+	void (*disconn_cfm_cb)	(struct hci_conn *conn, u8 reason);
 };
 
 extern struct hci_proto *hci_proto[];
@@ -274,24 +318,40 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
 	list_add(&c->list, &h->list);
-	if (c->type == ACL_LINK)
+	switch (c->type) {
+	case ACL_LINK:
 		h->acl_num++;
-	else
+		break;
+	case LE_LINK:
+		h->le_num++;
+		break;
+	case SCO_LINK:
+	case ESCO_LINK:
 		h->sco_num++;
+		break;
+	}
 }
 
 static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
 	list_del(&c->list);
-	if (c->type == ACL_LINK)
+	switch (c->type) {
+	case ACL_LINK:
 		h->acl_num--;
-	else
+		break;
+	case LE_LINK:
+		h->le_num--;
+		break;
+	case SCO_LINK:
+	case ESCO_LINK:
 		h->sco_num--;
+		break;
+	}
 }
 
 static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
-					__u16 handle)
+								__u16 handle)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
 	struct list_head *p;
@@ -306,7 +366,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
 }
 
 static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
-					__u8 type, bdaddr_t *ba)
+							__u8 type, bdaddr_t *ba)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
 	struct list_head *p;
@@ -321,7 +381,7 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
 }
 
 static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
-					__u8 type, __u16 state)
+							__u8 type, __u16 state)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
 	struct list_head *p;
@@ -437,6 +497,16 @@ int hci_inquiry(void __user *arg);
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_blacklist_clear(struct hci_dev *hdev);
 
+int hci_uuids_clear(struct hci_dev *hdev);
+
+int hci_link_keys_clear(struct hci_dev *hdev);
+struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
+						u8 *key, u8 type, u8 pin_len);
+int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
+
+void hci_del_off_timer(struct hci_dev *hdev);
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
 
 int hci_recv_frame(struct sk_buff *skb);
@@ -458,6 +528,8 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
 #define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO)
 #define lmp_ssp_capable(dev)       ((dev)->features[6] & LMP_SIMPLE_PAIR)
+#define lmp_no_flush_capable(dev)  ((dev)->features[6] & LMP_NO_FLUSH)
+#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE)
 
 /* ----- HCI protocols ----- */
 struct hci_proto {
@@ -503,6 +575,9 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
 	hp = hci_proto[HCI_PROTO_SCO];
 	if (hp && hp->connect_cfm)
 		hp->connect_cfm(conn, status);
+
+	if (conn->connect_cfm_cb)
+		conn->connect_cfm_cb(conn, status);
 }
 
 static inline int hci_proto_disconn_ind(struct hci_conn *conn)
@@ -532,6 +607,9 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
 	hp = hci_proto[HCI_PROTO_SCO];
 	if (hp && hp->disconn_cfm)
 		hp->disconn_cfm(conn, reason);
+
+	if (conn->disconn_cfm_cb)
+		conn->disconn_cfm_cb(conn, reason);
 }
 
 static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
@@ -551,6 +629,9 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
 	hp = hci_proto[HCI_PROTO_SCO];
 	if (hp && hp->security_cfm)
 		hp->security_cfm(conn, status, encrypt);
+
+	if (conn->security_cfm_cb)
+		conn->security_cfm_cb(conn, status);
 }
 
 static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
@@ -564,6 +645,9 @@ static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u
 	hp = hci_proto[HCI_PROTO_SCO];
 	if (hp && hp->security_cfm)
 		hp->security_cfm(conn, status, encrypt);
+
+	if (conn->security_cfm_cb)
+		conn->security_cfm_cb(conn, status);
 }
 
 int hci_register_proto(struct hci_proto *hproto);
@@ -660,12 +744,29 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
 void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
 
 /* ----- HCI Sockets ----- */
-void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
+void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
+							struct sock *skip_sk);
 
 /* Management interface */
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
 int mgmt_index_added(u16 index);
 int mgmt_index_removed(u16 index);
+int mgmt_powered(u16 index, u8 powered);
+int mgmt_discoverable(u16 index, u8 discoverable);
+int mgmt_connectable(u16 index, u8 connectable);
+int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type);
+int mgmt_connected(u16 index, bdaddr_t *bdaddr);
+int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
+int mgmt_disconnect_failed(u16 index);
+int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
+int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
+int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value);
+int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
+int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
+								u8 status);
+int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
 
 /* HCI info for socket */
 #define hci_pi(sk) ((struct hci_pinfo *) sk)
@@ -697,4 +798,6 @@ struct hci_sec_filter {
 
 void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
 
+void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
+					u16 latency, u16 to_multiplier);
 #endif /* __HCI_CORE_H */
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7ad25ca..4f4bff1 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -38,6 +38,7 @@
 #define L2CAP_DEFAULT_MAX_PDU_SIZE	1009    /* Sized for 3-DH5 packet */
 #define L2CAP_DEFAULT_ACK_TO		200
 #define L2CAP_LOCAL_BUSY_TRIES		12
+#define L2CAP_LE_DEFAULT_MTU		23
 
 #define L2CAP_CONN_TIMEOUT	(40000) /* 40 seconds */
 #define L2CAP_INFO_TIMEOUT	(4000)  /*  4 seconds */
@@ -88,6 +89,8 @@ struct l2cap_conninfo {
 #define L2CAP_ECHO_RSP		0x09
 #define L2CAP_INFO_REQ		0x0a
 #define L2CAP_INFO_RSP		0x0b
+#define L2CAP_CONN_PARAM_UPDATE_REQ	0x12
+#define L2CAP_CONN_PARAM_UPDATE_RSP	0x13
 
 /* L2CAP feature mask */
 #define L2CAP_FEAT_FLOWCTL	0x00000001
@@ -160,6 +163,9 @@ struct l2cap_conn_rsp {
 /* channel indentifier */
 #define L2CAP_CID_SIGNALING	0x0001
 #define L2CAP_CID_CONN_LESS	0x0002
+#define L2CAP_CID_LE_DATA	0x0004
+#define L2CAP_CID_LE_SIGNALING	0x0005
+#define L2CAP_CID_SMP		0x0006
 #define L2CAP_CID_DYN_START	0x0040
 #define L2CAP_CID_DYN_END	0xffff
 
@@ -255,6 +261,21 @@ struct l2cap_info_rsp {
 #define L2CAP_IR_SUCCESS    0x0000
 #define L2CAP_IR_NOTSUPP    0x0001
 
+struct l2cap_conn_param_update_req {
+	__le16      min;
+	__le16      max;
+	__le16      latency;
+	__le16      to_multiplier;
+} __packed;
+
+struct l2cap_conn_param_update_rsp {
+	__le16      result;
+} __packed;
+
+/* Connection Parameters result */
+#define L2CAP_CONN_PARAM_ACCEPTED	0x0000
+#define L2CAP_CONN_PARAM_REJECTED	0x0001
+
 /* ----- L2CAP connections ----- */
 struct l2cap_chan_list {
 	struct sock	*head;
@@ -327,6 +348,7 @@ struct l2cap_pinfo {
 	__u8		sec_level;
 	__u8		role_switch;
 	__u8		force_reliable;
+	__u8		flushable;
 
 	__u8		conf_req[64];
 	__u8		conf_len;
@@ -423,6 +445,35 @@ static inline int l2cap_tx_window_full(struct sock *sk)
 #define __is_sframe(ctrl)	((ctrl) & L2CAP_CTRL_FRAME_TYPE)
 #define __is_sar_start(ctrl)	(((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
 
-void l2cap_load(void);
+extern int disable_ertm;
+extern const struct proto_ops l2cap_sock_ops;
+extern struct bt_sock_list l2cap_sk_list;
+
+int l2cap_init_sockets(void);
+void l2cap_cleanup_sockets(void);
+
+u8 l2cap_get_ident(struct l2cap_conn *conn);
+void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
+int l2cap_build_conf_req(struct sock *sk, void *data);
+int __l2cap_wait_ack(struct sock *sk);
+
+struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
+int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len);
+void l2cap_do_send(struct sock *sk, struct sk_buff *skb);
+void l2cap_streaming_send(struct sock *sk);
+int l2cap_ertm_send(struct sock *sk);
+
+void l2cap_sock_set_timer(struct sock *sk, long timeout);
+void l2cap_sock_clear_timer(struct sock *sk);
+void __l2cap_sock_close(struct sock *sk, int reason);
+void l2cap_sock_kill(struct sock *sk);
+void l2cap_sock_init(struct sock *sk, struct sock *parent);
+struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+							int proto, gfp_t prio);
+void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
+void l2cap_chan_del(struct sock *sk, int err);
+int l2cap_do_connect(struct sock *sk);
 
 #endif /* __L2CAP_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index ca29c13..5fabfa8 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -21,11 +21,13 @@
    SOFTWARE IS DISCLAIMED.
 */
 
+#define MGMT_INDEX_NONE			0xFFFF
+
 struct mgmt_hdr {
 	__le16 opcode;
+	__le16 index;
 	__le16 len;
 } __packed;
-#define MGMT_HDR_SIZE			4
 
 #define MGMT_OP_READ_VERSION		0x0001
 struct mgmt_rp_read_version {
@@ -40,13 +42,10 @@ struct mgmt_rp_read_index_list {
 } __packed;
 
 #define MGMT_OP_READ_INFO		0x0004
-struct mgmt_cp_read_info {
-	__le16 index;
-} __packed;
 struct mgmt_rp_read_info {
-	__le16 index;
 	__u8 type;
 	__u8 powered;
+	__u8 connectable;
 	__u8 discoverable;
 	__u8 pairable;
 	__u8 sec_mode;
@@ -58,6 +57,116 @@ struct mgmt_rp_read_info {
 	__u16 hci_rev;
 } __packed;
 
+struct mgmt_mode {
+	__u8 val;
+} __packed;
+
+#define MGMT_OP_SET_POWERED		0x0005
+
+#define MGMT_OP_SET_DISCOVERABLE	0x0006
+
+#define MGMT_OP_SET_CONNECTABLE		0x0007
+
+#define MGMT_OP_SET_PAIRABLE		0x0008
+
+#define MGMT_OP_ADD_UUID		0x0009
+struct mgmt_cp_add_uuid {
+	__u8 uuid[16];
+	__u8 svc_hint;
+} __packed;
+
+#define MGMT_OP_REMOVE_UUID		0x000A
+struct mgmt_cp_remove_uuid {
+	__u8 uuid[16];
+} __packed;
+
+#define MGMT_OP_SET_DEV_CLASS		0x000B
+struct mgmt_cp_set_dev_class {
+	__u8 major;
+	__u8 minor;
+} __packed;
+
+#define MGMT_OP_SET_SERVICE_CACHE	0x000C
+struct mgmt_cp_set_service_cache {
+	__u8 enable;
+} __packed;
+
+struct mgmt_key_info {
+	bdaddr_t bdaddr;
+	u8 type;
+	u8 val[16];
+	u8 pin_len;
+} __packed;
+
+#define MGMT_OP_LOAD_KEYS		0x000D
+struct mgmt_cp_load_keys {
+	__u8 debug_keys;
+	__le16 key_count;
+	struct mgmt_key_info keys[0];
+} __packed;
+
+#define MGMT_OP_REMOVE_KEY		0x000E
+struct mgmt_cp_remove_key {
+	bdaddr_t bdaddr;
+	__u8 disconnect;
+} __packed;
+
+#define MGMT_OP_DISCONNECT		0x000F
+struct mgmt_cp_disconnect {
+	bdaddr_t bdaddr;
+} __packed;
+struct mgmt_rp_disconnect {
+	bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_GET_CONNECTIONS		0x0010
+struct mgmt_rp_get_connections {
+	__le16 conn_count;
+	bdaddr_t conn[0];
+} __packed;
+
+#define MGMT_OP_PIN_CODE_REPLY		0x0011
+struct mgmt_cp_pin_code_reply {
+	bdaddr_t bdaddr;
+	__u8 pin_len;
+	__u8 pin_code[16];
+} __packed;
+struct mgmt_rp_pin_code_reply {
+	bdaddr_t bdaddr;
+	uint8_t status;
+} __packed;
+
+#define MGMT_OP_PIN_CODE_NEG_REPLY	0x0012
+struct mgmt_cp_pin_code_neg_reply {
+	bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_SET_IO_CAPABILITY	0x0013
+struct mgmt_cp_set_io_capability {
+	__u8 io_capability;
+} __packed;
+
+#define MGMT_OP_PAIR_DEVICE		0x0014
+struct mgmt_cp_pair_device {
+	bdaddr_t bdaddr;
+	__u8 io_cap;
+} __packed;
+struct mgmt_rp_pair_device {
+	bdaddr_t bdaddr;
+	__u8 status;
+} __packed;
+
+#define MGMT_OP_USER_CONFIRM_REPLY	0x0015
+struct mgmt_cp_user_confirm_reply {
+	bdaddr_t bdaddr;
+} __packed;
+struct mgmt_rp_user_confirm_reply {
+	bdaddr_t bdaddr;
+	__u8 status;
+} __packed;
+
+#define MGMT_OP_USER_CONFIRM_NEG_REPLY	0x0016
+
 #define MGMT_EV_CMD_COMPLETE		0x0001
 struct mgmt_ev_cmd_complete {
 	__le16 opcode;
@@ -72,16 +181,56 @@ struct mgmt_ev_cmd_status {
 
 #define MGMT_EV_CONTROLLER_ERROR	0x0003
 struct mgmt_ev_controller_error {
-	__le16 index;
 	__u8 error_code;
 } __packed;
 
 #define MGMT_EV_INDEX_ADDED		0x0004
-struct mgmt_ev_index_added {
-	__le16 index;
-} __packed;
 
 #define MGMT_EV_INDEX_REMOVED		0x0005
-struct mgmt_ev_index_removed {
-	__le16 index;
+
+#define MGMT_EV_POWERED			0x0006
+
+#define MGMT_EV_DISCOVERABLE		0x0007
+
+#define MGMT_EV_CONNECTABLE		0x0008
+
+#define MGMT_EV_PAIRABLE		0x0009
+
+#define MGMT_EV_NEW_KEY			0x000A
+struct mgmt_ev_new_key {
+	struct mgmt_key_info key;
+	__u8 old_key_type;
+} __packed;
+
+#define MGMT_EV_CONNECTED		0x000B
+struct mgmt_ev_connected {
+	bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_EV_DISCONNECTED		0x000C
+struct mgmt_ev_disconnected {
+	bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_EV_CONNECT_FAILED		0x000D
+struct mgmt_ev_connect_failed {
+	bdaddr_t bdaddr;
+	__u8 status;
+} __packed;
+
+#define MGMT_EV_PIN_CODE_REQUEST	0x000E
+struct mgmt_ev_pin_code_request {
+	bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_EV_USER_CONFIRM_REQUEST	0x000F
+struct mgmt_ev_user_confirm_request {
+	bdaddr_t bdaddr;
+	__le32 value;
+} __packed;
+
+#define MGMT_EV_AUTH_FAILED		0x0010
+struct mgmt_ev_auth_failed {
+	bdaddr_t bdaddr;
+	__u8 status;
 } __packed;
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
new file mode 100644
index 0000000..8f2edbf
--- /dev/null
+++ b/include/net/bluetooth/smp.h
@@ -0,0 +1,76 @@
+#ifndef __SMP_H
+#define __SMP_H
+
+struct smp_command_hdr {
+	__u8	code;
+} __packed;
+
+#define SMP_CMD_PAIRING_REQ	0x01
+#define SMP_CMD_PAIRING_RSP	0x02
+struct smp_cmd_pairing {
+	__u8	io_capability;
+	__u8	oob_flag;
+	__u8	auth_req;
+	__u8	max_key_size;
+	__u8	init_key_dist;
+	__u8	resp_key_dist;
+} __packed;
+
+#define SMP_CMD_PAIRING_CONFIRM	0x03
+struct smp_cmd_pairing_confirm {
+	__u8	confirm_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_RANDOM	0x04
+struct smp_cmd_pairing_random {
+	__u8	rand_val[16];
+} __packed;
+
+#define SMP_CMD_PAIRING_FAIL	0x05
+struct smp_cmd_pairing_fail {
+	__u8	reason;
+} __packed;
+
+#define SMP_CMD_ENCRYPT_INFO	0x06
+struct smp_cmd_encrypt_info {
+	__u8	ltk[16];
+} __packed;
+
+#define SMP_CMD_MASTER_IDENT	0x07
+struct smp_cmd_master_ident {
+	__u16	ediv;
+	__u8	rand[8];
+} __packed;
+
+#define SMP_CMD_IDENT_INFO	0x08
+struct smp_cmd_ident_info {
+	__u8	irk[16];
+} __packed;
+
+#define SMP_CMD_IDENT_ADDR_INFO	0x09
+struct smp_cmd_ident_addr_info {
+	__u8	addr_type;
+	bdaddr_t bdaddr;
+} __packed;
+
+#define SMP_CMD_SIGN_INFO	0x0a
+struct smp_cmd_sign_info {
+	__u8	csrk[16];
+} __packed;
+
+#define SMP_CMD_SECURITY_REQ	0x0b
+struct smp_cmd_security_req {
+	__u8	auth_req;
+} __packed;
+
+#define SMP_PASSKEY_ENTRY_FAILED	0x01
+#define SMP_OOB_NOT_AVAIL		0x02
+#define SMP_AUTH_REQUIREMENTS		0x03
+#define SMP_CONFIRM_FAILED		0x04
+#define SMP_PAIRING_NOTSUPP		0x05
+#define SMP_ENC_KEY_SIZE		0x06
+#define SMP_CMD_NOTSUPP		0x07
+#define SMP_UNSPECIFIED		0x08
+#define SMP_REPEATED_ATTEMPTS		0x09
+
+#endif /* __SMP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1322695..60f7876 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -413,7 +413,7 @@ struct station_parameters {
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
  * @STATION_INFO_SIGNAL: @signal filled
- * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ * @STATION_INFO_TX_BITRATE: @txrate fields are filled
  *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  * @STATION_INFO_RX_PACKETS: @rx_packets filled
  * @STATION_INFO_TX_PACKETS: @tx_packets filled
@@ -421,6 +421,7 @@ struct station_parameters {
  * @STATION_INFO_TX_FAILED: @tx_failed filled
  * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
  * @STATION_INFO_SIGNAL_AVG: @signal_avg filled
+ * @STATION_INFO_RX_BITRATE: @rxrate fields are filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -437,6 +438,7 @@ enum station_info_flags {
 	STATION_INFO_TX_FAILED		= 1<<11,
 	STATION_INFO_RX_DROP_MISC	= 1<<12,
 	STATION_INFO_SIGNAL_AVG		= 1<<13,
+	STATION_INFO_RX_BITRATE		= 1<<14,
 };
 
 /**
@@ -506,6 +508,7 @@ struct station_info {
 	s8 signal;
 	s8 signal_avg;
 	struct rate_info txrate;
+	struct rate_info rxrate;
 	u32 rx_packets;
 	u32 tx_packets;
 	u32 tx_retries;
@@ -1194,6 +1197,10 @@ struct cfg80211_pmksa {
  *	(also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX).
  *
  * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant).
+ *
+ * @set_ringparam: Set tx and rx ring sizes.
+ *
+ * @get_ringparam: Get tx and rx ring current and maximum sizes.
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy);
@@ -1361,6 +1368,10 @@ struct cfg80211_ops {
 
 	int	(*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
 	int	(*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
+
+	int	(*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx);
+	void	(*get_ringparam)(struct wiphy *wiphy,
+				 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
 };
 
 /*
@@ -1790,8 +1801,9 @@ static inline void *wdev_priv(struct wireless_dev *wdev)
 /**
  * ieee80211_channel_to_frequency - convert channel number to frequency
  * @chan: channel number
+ * @band: band, necessary due to channel number overlap
  */
-extern int ieee80211_channel_to_frequency(int chan);
+extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band);
 
 /**
  * ieee80211_frequency_to_channel - convert frequency to channel number
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index a8e7852..e5983c9 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -43,6 +43,8 @@ struct dcbnl_rtnl_ops {
 	int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *);
 	int (*ieee_getapp) (struct net_device *, struct dcb_app *);
 	int (*ieee_setapp) (struct net_device *, struct dcb_app *);
+	int (*ieee_peer_getets) (struct net_device *, struct ieee_ets *);
+	int (*ieee_peer_getpfc) (struct net_device *, struct ieee_pfc *);
 
 	/* CEE std */
 	u8   (*getstate)(struct net_device *);
@@ -77,7 +79,14 @@ struct dcbnl_rtnl_ops {
 	u8   (*getdcbx)(struct net_device *);
 	u8   (*setdcbx)(struct net_device *, u8);
 
+	/* peer apps */
+	int (*peer_getappinfo)(struct net_device *, struct dcb_peer_app_info *,
+			       u16 *);
+	int (*peer_getapptable)(struct net_device *, struct dcb_app *);
 
+	/* CEE peer */
+	int (*cee_peer_getpg) (struct net_device *, struct cee_pg *);
+	int (*cee_peer_getpfc) (struct net_device *, struct cee_pfc *);
 };
 
 #endif /* __NET_DCBNL_H__ */
diff --git a/include/net/dn.h b/include/net/dn.h
index a514a3c..298521e 100644
--- a/include/net/dn.h
+++ b/include/net/dn.h
@@ -192,10 +192,10 @@ static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr)
 	ethaddr[5] = (__u8)(a >> 8);
 }
 
-static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp)
+static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
 {
-	fl->uli_u.dnports.sport = scp->addrloc;
-	fl->uli_u.dnports.dport = scp->addrrem;
+	fld->fld_sport = scp->addrloc;
+	fld->fld_dport = scp->addrrem;
 }
 
 extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu);
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
index bbcde32..782ef7c 100644
--- a/include/net/dn_fib.h
+++ b/include/net/dn_fib.h
@@ -98,7 +98,7 @@ struct dn_fib_table {
 	int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
 			struct dn_kern_rta *rta, struct nlmsghdr *n,
 			struct netlink_skb_parms *req);
-	int (*lookup)(struct dn_fib_table *t, const struct flowi *fl,
+	int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
 			struct dn_fib_res *res);
 	int (*flush)(struct dn_fib_table *t);
 	int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
@@ -119,12 +119,12 @@ extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
 				struct dn_kern_rta *rta, 
 				const struct nlmsghdr *nlh, int *errp);
 extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi, 
-			const struct flowi *fl,
+			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 flowi *fl,
+extern void dn_fib_select_multipath(const struct flowidn *fld,
 					struct dn_fib_res *res);
 
 /*
@@ -141,7 +141,7 @@ extern void dn_fib_table_cleanup(void);
 extern void dn_fib_rules_init(void);
 extern void dn_fib_rules_cleanup(void);
 extern unsigned dnet_addr_type(__le16 addr);
-extern int dn_fib_lookup(struct flowi *fl, struct dn_fib_res *res);
+extern int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
 
 extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
 
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index 9b185df..81712cf 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -16,7 +16,7 @@
 *******************************************************************************/
 
 extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
-extern int dn_route_output_sock(struct dst_entry **pprt, struct flowi *, struct sock *sk, int flags);
+extern int dn_route_output_sock(struct dst_entry **pprt, struct flowidn *, struct sock *sk, int flags);
 extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
 extern void dn_rt_cache_flush(int delay);
 
@@ -67,7 +67,7 @@ extern void dn_rt_cache_flush(int delay);
 struct dn_route {
 	struct dst_entry dst;
 
-	struct flowi fl;
+	struct flowidn fld;
 
 	__le16 rt_saddr;
 	__le16 rt_daddr;
@@ -82,12 +82,12 @@ struct dn_route {
 
 static inline bool dn_is_input_route(struct dn_route *rt)
 {
-	return rt->fl.iif != 0;
+	return rt->fld.flowidn_iif != 0;
 }
 
 static inline bool dn_is_output_route(struct dn_route *rt)
 {
-	return rt->fl.iif == 0;
+	return rt->fld.flowidn_iif == 0;
 }
 
 extern void dn_route_init(void);
diff --git a/include/net/dst.h b/include/net/dst.h
index 93b0310..2a46cba 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -40,24 +40,10 @@ struct dst_entry {
 	struct rcu_head		rcu_head;
 	struct dst_entry	*child;
 	struct net_device       *dev;
-	short			error;
-	short			obsolete;
-	int			flags;
-#define DST_HOST		0x0001
-#define DST_NOXFRM		0x0002
-#define DST_NOPOLICY		0x0004
-#define DST_NOHASH		0x0008
-#define DST_NOCACHE		0x0010
+	struct  dst_ops	        *ops;
+	unsigned long		_metrics;
 	unsigned long		expires;
-
-	unsigned short		header_len;	/* more space at head required */
-	unsigned short		trailer_len;	/* space to reserve at tail */
-
-	unsigned int		rate_tokens;
-	unsigned long		rate_last;	/* rate limiting for ICMP */
-
 	struct dst_entry	*path;
-
 	struct neighbour	*neighbour;
 	struct hh_cache		*hh;
 #ifdef CONFIG_XFRM
@@ -68,17 +54,16 @@ struct dst_entry {
 	int			(*input)(struct sk_buff*);
 	int			(*output)(struct sk_buff*);
 
-	struct  dst_ops	        *ops;
-
-	u32			_metrics[RTAX_MAX];
-
-#ifdef CONFIG_NET_CLS_ROUTE
+	short			error;
+	short			obsolete;
+	unsigned short		header_len;	/* more space at head required */
+	unsigned short		trailer_len;	/* space to reserve at tail */
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	__u32			tclassid;
 #else
 	__u32			__pad2;
 #endif
 
-
 	/*
 	 * Align __refcnt to a 64 bytes alignment
 	 * (L1_CACHE_SIZE would be too much)
@@ -93,6 +78,12 @@ struct dst_entry {
 	atomic_t		__refcnt;	/* client references	*/
 	int			__use;
 	unsigned long		lastuse;
+	int			flags;
+#define DST_HOST		0x0001
+#define DST_NOXFRM		0x0002
+#define DST_NOPOLICY		0x0004
+#define DST_NOHASH		0x0008
+#define DST_NOCACHE		0x0010
 	union {
 		struct dst_entry	*next;
 		struct rtable __rcu	*rt_next;
@@ -103,10 +94,70 @@ struct dst_entry {
 
 #ifdef __KERNEL__
 
+extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
+extern const u32 dst_default_metrics[RTAX_MAX];
+
+#define DST_METRICS_READ_ONLY	0x1UL
+#define __DST_METRICS_PTR(Y)	\
+	((u32 *)((Y) & ~DST_METRICS_READ_ONLY))
+#define DST_METRICS_PTR(X)	__DST_METRICS_PTR((X)->_metrics)
+
+static inline bool dst_metrics_read_only(const struct dst_entry *dst)
+{
+	return dst->_metrics & DST_METRICS_READ_ONLY;
+}
+
+extern void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old);
+
+static inline void dst_destroy_metrics_generic(struct dst_entry *dst)
+{
+	unsigned long val = dst->_metrics;
+	if (!(val & DST_METRICS_READ_ONLY))
+		__dst_destroy_metrics_generic(dst, val);
+}
+
+static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst)
+{
+	unsigned long p = dst->_metrics;
+
+	if (p & DST_METRICS_READ_ONLY)
+		return dst->ops->cow_metrics(dst, p);
+	return __DST_METRICS_PTR(p);
+}
+
+/* This may only be invoked before the entry has reached global
+ * visibility.
+ */
+static inline void dst_init_metrics(struct dst_entry *dst,
+				    const u32 *src_metrics,
+				    bool read_only)
+{
+	dst->_metrics = ((unsigned long) src_metrics) |
+		(read_only ? DST_METRICS_READ_ONLY : 0);
+}
+
+static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
+{
+	u32 *dst_metrics = dst_metrics_write_ptr(dest);
+
+	if (dst_metrics) {
+		u32 *src_metrics = DST_METRICS_PTR(src);
+
+		memcpy(dst_metrics, src_metrics, RTAX_MAX * sizeof(u32));
+	}
+}
+
+static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
+{
+	return DST_METRICS_PTR(dst);
+}
+
 static inline u32
 dst_metric_raw(const struct dst_entry *dst, const int metric)
 {
-	return dst->_metrics[metric-1];
+	u32 *p = DST_METRICS_PTR(dst);
+
+	return p[metric-1];
 }
 
 static inline u32
@@ -131,22 +182,10 @@ dst_metric_advmss(const struct dst_entry *dst)
 
 static inline void dst_metric_set(struct dst_entry *dst, int metric, u32 val)
 {
-	dst->_metrics[metric-1] = val;
-}
+	u32 *p = dst_metrics_write_ptr(dst);
 
-static inline void dst_import_metrics(struct dst_entry *dst, const u32 *src_metrics)
-{
-	memcpy(dst->_metrics, src_metrics, RTAX_MAX * sizeof(u32));
-}
-
-static inline void dst_copy_metrics(struct dst_entry *dest, const struct dst_entry *src)
-{
-	dst_import_metrics(dest, src->_metrics);
-}
-
-static inline u32 *dst_metrics_ptr(struct dst_entry *dst)
-{
-	return dst->_metrics;
+	if (p)
+		p[metric-1] = val;
 }
 
 static inline u32
@@ -181,8 +220,6 @@ static inline u32
 dst_allfrag(const struct dst_entry *dst)
 {
 	int ret = dst_feature(dst,  RTAX_FEATURE_ALLFRAG);
-	/* Yes, _exactly_. This is paranoia. */
-	barrier();
 	return ret;
 }
 
@@ -315,7 +352,7 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 }
 
 extern int dst_discard(struct sk_buff *skb);
-extern void * dst_alloc(struct dst_ops * ops);
+extern void *dst_alloc(struct dst_ops * ops, int initial_ref);
 extern void __dst_free(struct dst_entry * dst);
 extern struct dst_entry *dst_destroy(struct dst_entry * dst);
 
@@ -384,27 +421,22 @@ extern void		dst_init(void);
 
 /* Flags for xfrm_lookup flags argument. */
 enum {
-	XFRM_LOOKUP_WAIT = 1 << 0,
-	XFRM_LOOKUP_ICMP = 1 << 1,
+	XFRM_LOOKUP_ICMP = 1 << 0,
 };
 
 struct flowi;
 #ifndef CONFIG_XFRM
-static inline int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
-			      struct flowi *fl, struct sock *sk, int flags)
+static inline struct dst_entry *xfrm_lookup(struct net *net,
+					    struct dst_entry *dst_orig,
+					    const struct flowi *fl, struct sock *sk,
+					    int flags)
 {
-	return 0;
+	return dst_orig;
 } 
-static inline int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
-				struct flowi *fl, struct sock *sk, int flags)
-{
-	return 0;
-}
 #else
-extern int xfrm_lookup(struct net *net, struct dst_entry **dst_p,
-		       struct flowi *fl, struct sock *sk, int flags);
-extern int __xfrm_lookup(struct net *net, struct dst_entry **dst_p,
-			 struct flowi *fl, struct sock *sk, int flags);
+extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
+				     const struct flowi *fl, struct sock *sk,
+				     int flags);
 #endif
 #endif
 
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index 21a320b..dc07463 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -18,6 +18,7 @@ struct dst_ops {
 	struct dst_entry *	(*check)(struct dst_entry *, __u32 cookie);
 	unsigned int		(*default_advmss)(const struct dst_entry *);
 	unsigned int		(*default_mtu)(const struct dst_entry *);
+	u32 *			(*cow_metrics)(struct dst_entry *, unsigned long);
 	void			(*destroy)(struct dst_entry *);
 	void			(*ifdown)(struct dst_entry *,
 					  struct net_device *dev, int how);
diff --git a/include/net/flow.h b/include/net/flow.h
index 240b7f3..7fe5a0f 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -10,78 +10,136 @@
 #include <linux/in6.h>
 #include <asm/atomic.h>
 
-struct flowi {
-	int	oif;
-	int	iif;
-	__u32	mark;
+struct flowi_common {
+	int	flowic_oif;
+	int	flowic_iif;
+	__u32	flowic_mark;
+	__u8	flowic_tos;
+	__u8	flowic_scope;
+	__u8	flowic_proto;
+	__u8	flowic_flags;
+#define FLOWI_FLAG_ANYSRC		0x01
+#define FLOWI_FLAG_PRECOW_METRICS	0x02
+#define FLOWI_FLAG_CAN_SLEEP		0x04
+	__u32	flowic_secid;
+};
 
+union flowi_uli {
+	struct {
+		__be16	sport;
+		__be16	dport;
+	} ports;
+
+	struct {
+		__u8	type;
+		__u8	code;
+	} icmpt;
+
+	struct {
+		__le16	sport;
+		__le16	dport;
+	} dnports;
+
+	__be32		spi;
+	__be32		gre_key;
+
+	struct {
+		__u8	type;
+	} mht;
+};
+
+struct flowi4 {
+	struct flowi_common	__fl_common;
+#define flowi4_oif		__fl_common.flowic_oif
+#define flowi4_iif		__fl_common.flowic_iif
+#define flowi4_mark		__fl_common.flowic_mark
+#define flowi4_tos		__fl_common.flowic_tos
+#define flowi4_scope		__fl_common.flowic_scope
+#define flowi4_proto		__fl_common.flowic_proto
+#define flowi4_flags		__fl_common.flowic_flags
+#define flowi4_secid		__fl_common.flowic_secid
+	__be32			daddr;
+	__be32			saddr;
+	union flowi_uli		uli;
+#define fl4_sport		uli.ports.sport
+#define fl4_dport		uli.ports.dport
+#define fl4_icmp_type		uli.icmpt.type
+#define fl4_icmp_code		uli.icmpt.code
+#define fl4_ipsec_spi		uli.spi
+#define fl4_mh_type		uli.mht.type
+#define fl4_gre_key		uli.gre_key
+};
+
+struct flowi6 {
+	struct flowi_common	__fl_common;
+#define flowi6_oif		__fl_common.flowic_oif
+#define flowi6_iif		__fl_common.flowic_iif
+#define flowi6_mark		__fl_common.flowic_mark
+#define flowi6_tos		__fl_common.flowic_tos
+#define flowi6_scope		__fl_common.flowic_scope
+#define flowi6_proto		__fl_common.flowic_proto
+#define flowi6_flags		__fl_common.flowic_flags
+#define flowi6_secid		__fl_common.flowic_secid
+	struct in6_addr		daddr;
+	struct in6_addr		saddr;
+	__be32			flowlabel;
+	union flowi_uli		uli;
+#define fl6_sport		uli.ports.sport
+#define fl6_dport		uli.ports.dport
+#define fl6_icmp_type		uli.icmpt.type
+#define fl6_icmp_code		uli.icmpt.code
+#define fl6_ipsec_spi		uli.spi
+#define fl6_mh_type		uli.mht.type
+#define fl6_gre_key		uli.gre_key
+};
+
+struct flowidn {
+	struct flowi_common	__fl_common;
+#define flowidn_oif		__fl_common.flowic_oif
+#define flowidn_iif		__fl_common.flowic_iif
+#define flowidn_mark		__fl_common.flowic_mark
+#define flowidn_scope		__fl_common.flowic_scope
+#define flowidn_proto		__fl_common.flowic_proto
+#define flowidn_flags		__fl_common.flowic_flags
+	__le16			daddr;
+	__le16			saddr;
+	union flowi_uli		uli;
+#define fld_sport		uli.ports.sport
+#define fld_dport		uli.ports.dport
+};
+
+struct flowi {
 	union {
-		struct {
-			__be32			daddr;
-			__be32			saddr;
-			__u8			tos;
-			__u8			scope;
-		} ip4_u;
-		
-		struct {
-			struct in6_addr		daddr;
-			struct in6_addr		saddr;
-			__be32			flowlabel;
-		} ip6_u;
-
-		struct {
-			__le16			daddr;
-			__le16			saddr;
-			__u8			scope;
-		} dn_u;
-	} nl_u;
-#define fld_dst		nl_u.dn_u.daddr
-#define fld_src		nl_u.dn_u.saddr
-#define fld_scope	nl_u.dn_u.scope
-#define fl6_dst		nl_u.ip6_u.daddr
-#define fl6_src		nl_u.ip6_u.saddr
-#define fl6_flowlabel	nl_u.ip6_u.flowlabel
-#define fl4_dst		nl_u.ip4_u.daddr
-#define fl4_src		nl_u.ip4_u.saddr
-#define fl4_tos		nl_u.ip4_u.tos
-#define fl4_scope	nl_u.ip4_u.scope
-
-	__u8	proto;
-	__u8	flags;
-#define FLOWI_FLAG_ANYSRC 0x01
-	union {
-		struct {
-			__be16	sport;
-			__be16	dport;
-		} ports;
-
-		struct {
-			__u8	type;
-			__u8	code;
-		} icmpt;
-
-		struct {
-			__le16	sport;
-			__le16	dport;
-		} dnports;
-
-		__be32		spi;
-		__be32		gre_key;
-
-		struct {
-			__u8	type;
-		} mht;
-	} uli_u;
-#define fl_ip_sport	uli_u.ports.sport
-#define fl_ip_dport	uli_u.ports.dport
-#define fl_icmp_type	uli_u.icmpt.type
-#define fl_icmp_code	uli_u.icmpt.code
-#define fl_ipsec_spi	uli_u.spi
-#define fl_mh_type	uli_u.mht.type
-#define fl_gre_key	uli_u.gre_key
-	__u32           secid;	/* used by xfrm; see secid.txt */
+		struct flowi_common	__fl_common;
+		struct flowi4		ip4;
+		struct flowi6		ip6;
+		struct flowidn		dn;
+	} u;
+#define flowi_oif	u.__fl_common.flowic_oif
+#define flowi_iif	u.__fl_common.flowic_iif
+#define flowi_mark	u.__fl_common.flowic_mark
+#define flowi_tos	u.__fl_common.flowic_tos
+#define flowi_scope	u.__fl_common.flowic_scope
+#define flowi_proto	u.__fl_common.flowic_proto
+#define flowi_flags	u.__fl_common.flowic_flags
+#define flowi_secid	u.__fl_common.flowic_secid
 } __attribute__((__aligned__(BITS_PER_LONG/8)));
 
+static inline struct flowi *flowi4_to_flowi(struct flowi4 *fl4)
+{
+	return container_of(fl4, struct flowi, u.ip4);
+}
+
+static inline struct flowi *flowi6_to_flowi(struct flowi6 *fl6)
+{
+	return container_of(fl6, struct flowi, u.ip6);
+}
+
+static inline struct flowi *flowidn_to_flowi(struct flowidn *fldn)
+{
+	return container_of(fldn, struct flowi, u.dn);
+}
+
 #define FLOW_DIR_IN	0
 #define FLOW_DIR_OUT	1
 #define FLOW_DIR_FWD	2
@@ -101,20 +159,14 @@ struct flow_cache_ops {
 };
 
 typedef struct flow_cache_object *(*flow_resolve_t)(
-		struct net *net, struct flowi *key, u16 family,
+		struct net *net, const struct flowi *key, u16 family,
 		u8 dir, struct flow_cache_object *oldobj, void *ctx);
 
 extern struct flow_cache_object *flow_cache_lookup(
-		struct net *net, struct flowi *key, u16 family,
+		struct net *net, const struct flowi *key, u16 family,
 		u8 dir, flow_resolve_t resolver, void *ctx);
 
 extern void flow_cache_flush(void);
 extern atomic_t flow_cache_genid;
 
-static inline int flow_cache_uli_match(struct flowi *fl1, struct flowi *fl2)
-{
-	return (fl1->proto == fl2->proto &&
-		!memcmp(&fl1->uli_u, &fl2->uli_u, sizeof(fl1->uli_u)));
-}
-
 #endif
diff --git a/include/net/icmp.h b/include/net/icmp.h
index 6e991e0..f0698b9 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -45,7 +45,4 @@ extern int	icmp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 extern int	icmp_init(void);
 extern void	icmp_out_count(struct net *net, unsigned char type);
 
-/* Move into dst.h ? */
-extern int 	xrlim_allow(struct dst_entry *dst, int timeout);
-
 #endif	/* _ICMP_H */
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index af49f8a..b0be5fb 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -178,6 +178,11 @@ struct ieee80211_radiotap_header {
  *
  *     Number of unicast retries a transmitted frame used.
  *
+ * IEEE80211_RADIOTAP_MCS	u8, u8, u8		unitless
+ *
+ *     Contains a bitmap of known fields/flags, the flags, and
+ *     the MCS index.
+ *
  */
 enum ieee80211_radiotap_type {
 	IEEE80211_RADIOTAP_TSFT = 0,
@@ -199,6 +204,8 @@ enum ieee80211_radiotap_type {
 	IEEE80211_RADIOTAP_RTS_RETRIES = 16,
 	IEEE80211_RADIOTAP_DATA_RETRIES = 17,
 
+	IEEE80211_RADIOTAP_MCS = 19,
+
 	/* valid in every it_present bitmap, even vendor namespaces */
 	IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
 	IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
@@ -245,6 +252,24 @@ enum ieee80211_radiotap_type {
 #define IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
 #define IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */
 
+
+/* For IEEE80211_RADIOTAP_MCS */
+#define IEEE80211_RADIOTAP_MCS_HAVE_BW		0x01
+#define IEEE80211_RADIOTAP_MCS_HAVE_MCS		0x02
+#define IEEE80211_RADIOTAP_MCS_HAVE_GI		0x04
+#define IEEE80211_RADIOTAP_MCS_HAVE_FMT		0x08
+#define IEEE80211_RADIOTAP_MCS_HAVE_FEC		0x10
+
+#define IEEE80211_RADIOTAP_MCS_BW_MASK		0x03
+#define		IEEE80211_RADIOTAP_MCS_BW_20	0
+#define		IEEE80211_RADIOTAP_MCS_BW_40	1
+#define		IEEE80211_RADIOTAP_MCS_BW_20L	2
+#define		IEEE80211_RADIOTAP_MCS_BW_20U	3
+#define IEEE80211_RADIOTAP_MCS_SGI		0x04
+#define IEEE80211_RADIOTAP_MCS_FMT_GF		0x08
+#define IEEE80211_RADIOTAP_MCS_FEC_LDPC		0x10
+
+
 /* Ugly macro to convert literal channel numbers into their mhz equivalents
  * There are certianly some conditions that will break this (like feeding it '30')
  * but they shouldn't arise since nothing talks on channel 30. */
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 8181498..7a37369 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -86,6 +86,19 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
 	return (struct inet_request_sock *)sk;
 }
 
+struct inet_cork {
+	unsigned int		flags;
+	unsigned int		fragsize;
+	struct ip_options	*opt;
+	struct dst_entry	*dst;
+	int			length; /* Total length of all frames */
+	__be32			addr;
+	struct flowi		fl;
+	struct page		*page;
+	u32			off;
+	u8			tx_flags;
+};
+
 struct ip_mc_socklist;
 struct ipv6_pinfo;
 struct rtable;
@@ -143,15 +156,7 @@ struct inet_sock {
 	int			mc_index;
 	__be32			mc_addr;
 	struct ip_mc_socklist __rcu	*mc_list;
-	struct {
-		unsigned int		flags;
-		unsigned int		fragsize;
-		struct ip_options	*opt;
-		struct dst_entry	*dst;
-		int			length; /* Total length of all frames */
-		__be32			addr;
-		struct flowi		fl;
-	} cork;
+	struct inet_cork	cork;
 };
 
 #define IPCORK_OPT	1	/* ip-options has been held in ipcork.opt */
@@ -219,7 +224,13 @@ static inline struct request_sock *inet_reqsk_alloc(struct request_sock_ops *ops
 
 static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
 {
-	return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0;
+	__u8 flags = 0;
+
+	if (inet_sk(sk)->transparent)
+		flags |= FLOWI_FLAG_ANYSRC;
+	if (sk->sk_protocol == IPPROTO_TCP)
+		flags |= FLOWI_FLAG_PRECOW_METRICS;
+	return flags;
 }
 
 #endif	/* _INET_SOCK_H */
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 599d96e..e6dd8da6 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -11,15 +11,20 @@
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/spinlock.h>
+#include <linux/rtnetlink.h>
 #include <net/ipv6.h>
 #include <asm/atomic.h>
 
-struct inetpeer_addr {
+struct inetpeer_addr_base {
 	union {
-		__be32		a4;
-		__be32		a6[4];
+		__be32			a4;
+		__be32			a6[4];
 	};
-	__u16	family;
+};
+
+struct inetpeer_addr {
+	struct inetpeer_addr_base	addr;
+	__u16				family;
 };
 
 struct inet_peer {
@@ -33,15 +38,22 @@ struct inet_peer {
 	atomic_t		refcnt;
 	/*
 	 * Once inet_peer is queued for deletion (refcnt == -1), following fields
-	 * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
-	 * We can share memory with rcu_head to keep inet_peer small
+	 * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp, metrics
+	 * We can share memory with rcu_head to help keep inet_peer small.
 	 */
 	union {
 		struct {
-			atomic_t	rid;		/* Frag reception counter */
-			atomic_t	ip_id_count;	/* IP ID for the next packet */
-			__u32		tcp_ts;
-			__u32		tcp_ts_stamp;
+			atomic_t			rid;		/* Frag reception counter */
+			atomic_t			ip_id_count;	/* IP ID for the next packet */
+			__u32				tcp_ts;
+			__u32				tcp_ts_stamp;
+			u32				metrics[RTAX_MAX];
+			u32				rate_tokens;	/* rate limiting for ICMP */
+			unsigned long			rate_last;
+			unsigned long			pmtu_expires;
+			u32				pmtu_orig;
+			u32				pmtu_learned;
+			struct inetpeer_addr_base	redirect_learned;
 		};
 		struct rcu_head         rcu;
 	};
@@ -49,6 +61,13 @@ struct inet_peer {
 
 void			inet_initpeers(void) __init;
 
+#define INETPEER_METRICS_NEW	(~(u32) 0)
+
+static inline bool inet_metrics_new(const struct inet_peer *p)
+{
+	return p->metrics[RTAX_LOCK-1] == INETPEER_METRICS_NEW;
+}
+
 /* can be called with or without local BH being disabled */
 struct inet_peer	*inet_getpeer(struct inetpeer_addr *daddr, int create);
 
@@ -56,7 +75,7 @@ static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create)
 {
 	struct inetpeer_addr daddr;
 
-	daddr.a4 = v4daddr;
+	daddr.addr.a4 = v4daddr;
 	daddr.family = AF_INET;
 	return inet_getpeer(&daddr, create);
 }
@@ -65,13 +84,14 @@ static inline struct inet_peer *inet_getpeer_v6(struct in6_addr *v6daddr, int cr
 {
 	struct inetpeer_addr daddr;
 
-	ipv6_addr_copy((struct in6_addr *)daddr.a6, v6daddr);
+	ipv6_addr_copy((struct in6_addr *)daddr.addr.a6, v6daddr);
 	daddr.family = AF_INET6;
 	return inet_getpeer(&daddr, create);
 }
 
 /* can be called from BH context or outside */
 extern void inet_putpeer(struct inet_peer *p);
+extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
 
 /*
  * temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
diff --git a/include/net/ip.h b/include/net/ip.h
index 67fac78..a4f6311 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -116,8 +116,24 @@ extern int		ip_append_data(struct sock *sk,
 extern int		ip_generic_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb);
 extern ssize_t		ip_append_page(struct sock *sk, struct page *page,
 				int offset, size_t size, int flags);
+extern struct sk_buff  *__ip_make_skb(struct sock *sk,
+				      struct sk_buff_head *queue,
+				      struct inet_cork *cork);
+extern int		ip_send_skb(struct sk_buff *skb);
 extern int		ip_push_pending_frames(struct sock *sk);
 extern void		ip_flush_pending_frames(struct sock *sk);
+extern struct sk_buff  *ip_make_skb(struct sock *sk,
+				    int getfrag(void *from, char *to, int offset, int len,
+						int odd, struct sk_buff *skb),
+				    void *from, int length, int transhdrlen,
+				    struct ipcm_cookie *ipc,
+				    struct rtable **rtp,
+				    unsigned int flags);
+
+static inline struct sk_buff *ip_finish_skb(struct sock *sk)
+{
+	return __ip_make_skb(sk, &sk->sk_write_queue, &inet_sk(sk)->cork);
+}
 
 /* datagram.c */
 extern int		ip4_datagram_connect(struct sock *sk, 
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 708ff7c..bc3cde0 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -108,6 +108,7 @@ struct rt6_info {
 	u32				rt6i_flags;
 	struct rt6key			rt6i_src;
 	u32				rt6i_metric;
+	u32				rt6i_peer_genid;
 
 	struct inet6_dev		*rt6i_idev;
 	struct inet_peer		*rt6i_peer;
@@ -182,7 +183,7 @@ struct fib6_table {
 
 typedef struct rt6_info *(*pol_lookup_t)(struct net *,
 					 struct fib6_table *,
-					 struct flowi *, int);
+					 struct flowi6 *, int);
 
 /*
  *	exported functions
@@ -191,7 +192,7 @@ typedef struct rt6_info *(*pol_lookup_t)(struct net *,
 extern struct fib6_table        *fib6_get_table(struct net *net, u32 id);
 extern struct fib6_table        *fib6_new_table(struct net *net, u32 id);
 extern struct dst_entry         *fib6_rule_lookup(struct net *net,
-						  struct flowi *fl, int flags,
+						  struct flowi6 *fl6, int flags,
 						  pol_lookup_t lookup);
 
 extern struct fib6_node		*fib6_lookup(struct fib6_node *root,
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 8552f0a..642a80b 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -71,7 +71,7 @@ extern void			ip6_route_input(struct sk_buff *skb);
 
 extern struct dst_entry *	ip6_route_output(struct net *net,
 						 struct sock *sk,
-						 struct flowi *fl);
+						 struct flowi6 *fl6);
 
 extern int			ip6_route_init(void);
 extern void			ip6_route_cleanup(void);
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 07bdb5e..a1a8580 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -51,15 +51,17 @@ struct fib_nh {
 	struct fib_info		*nh_parent;
 	unsigned		nh_flags;
 	unsigned char		nh_scope;
+	unsigned char		nh_cfg_scope;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	int			nh_weight;
 	int			nh_power;
 #endif
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	__u32			nh_tclassid;
 #endif
 	int			nh_oif;
 	__be32			nh_gw;
+	__be32			nh_saddr;
 };
 
 /*
@@ -77,7 +79,7 @@ struct fib_info {
 	int			fib_protocol;
 	__be32			fib_prefsrc;
 	u32			fib_priority;
-	u32			fib_metrics[RTAX_MAX];
+	u32			*fib_metrics;
 #define fib_mtu fib_metrics[RTAX_MTU-1]
 #define fib_window fib_metrics[RTAX_WINDOW-1]
 #define fib_rtt fib_metrics[RTAX_RTT-1]
@@ -96,12 +98,15 @@ struct fib_info {
 struct fib_rule;
 #endif
 
+struct fib_table;
 struct fib_result {
 	unsigned char	prefixlen;
 	unsigned char	nh_sel;
 	unsigned char	type;
 	unsigned char	scope;
 	struct fib_info *fi;
+	struct fib_table *table;
+	struct list_head *fa_head;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	struct fib_rule	*r;
 #endif
@@ -136,11 +141,13 @@ struct fib_result_nl {
 
 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
 
-#define FIB_RES_PREFSRC(res)		((res).fi->fib_prefsrc ? : __fib_res_prefsrc(&res))
+#define FIB_RES_SADDR(res)		(FIB_RES_NH(res).nh_saddr)
 #define FIB_RES_GW(res)			(FIB_RES_NH(res).nh_gw)
 #define FIB_RES_DEV(res)		(FIB_RES_NH(res).nh_dev)
 #define FIB_RES_OIF(res)		(FIB_RES_NH(res).nh_oif)
 
+#define FIB_RES_PREFSRC(res)		((res).fi->fib_prefsrc ? : FIB_RES_SADDR(res))
+
 struct fib_table {
 	struct hlist_node tb_hlist;
 	u32		tb_id;
@@ -148,16 +155,13 @@ struct fib_table {
 	unsigned char	tb_data[0];
 };
 
-extern int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
+extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 			    struct fib_result *res, int fib_flags);
 extern int fib_table_insert(struct fib_table *, struct fib_config *);
 extern int fib_table_delete(struct fib_table *, struct fib_config *);
 extern int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
 			  struct netlink_callback *cb);
 extern int fib_table_flush(struct fib_table *table);
-extern void fib_table_select_default(struct fib_table *table,
-				     const struct flowi *flp,
-				     struct fib_result *res);
 extern void fib_free_table(struct fib_table *tb);
 
 
@@ -182,7 +186,7 @@ static inline struct fib_table *fib_new_table(struct net *net, u32 id)
 	return fib_get_table(net, id);
 }
 
-static inline int fib_lookup(struct net *net, const struct flowi *flp,
+static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
 			     struct fib_result *res)
 {
 	struct fib_table *table;
@@ -201,11 +205,11 @@ static inline int fib_lookup(struct net *net, const struct flowi *flp,
 extern int __net_init fib4_rules_init(struct net *net);
 extern void __net_exit fib4_rules_exit(struct net *net);
 
-#ifdef CONFIG_NET_CLS_ROUTE
-extern u32 fib_rules_tclass(struct fib_result *res);
+#ifdef CONFIG_IP_ROUTE_CLASSID
+extern u32 fib_rules_tclass(const struct fib_result *res);
 #endif
 
-extern int fib_lookup(struct net *n, struct flowi *flp, struct fib_result *res);
+extern int fib_lookup(struct net *n, struct flowi4 *flp, struct fib_result *res);
 
 extern struct fib_table *fib_new_table(struct net *net, u32 id);
 extern struct fib_table *fib_get_table(struct net *net, u32 id);
@@ -218,24 +222,23 @@ extern void		ip_fib_init(void);
 extern int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 			       struct net_device *dev, __be32 *spec_dst,
 			       u32 *itag, u32 mark);
-extern void fib_select_default(struct net *net, const struct flowi *flp,
-			       struct fib_result *res);
+extern void fib_select_default(struct fib_result *res);
 
 /* Exported by fib_semantics.c */
 extern int ip_fib_check_default(__be32 gw, struct net_device *dev);
 extern int fib_sync_down_dev(struct net_device *dev, int force);
 extern int fib_sync_down_addr(struct net *net, __be32 local);
+extern void fib_update_nh_saddrs(struct net_device *dev);
 extern int fib_sync_up(struct net_device *dev);
-extern __be32  __fib_res_prefsrc(struct fib_result *res);
-extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res);
+extern void fib_select_multipath(struct fib_result *res);
 
-/* Exported by fib_{hash|trie}.c */
-extern void fib_hash_init(void);
-extern struct fib_table *fib_hash_table(u32 id);
+/* Exported by fib_trie.c */
+extern void fib_trie_init(void);
+extern struct fib_table *fib_trie_table(u32 id);
 
-static inline void fib_combine_itag(u32 *itag, struct fib_result *res)
+static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
 {
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	u32 rtag;
 #endif
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index b7bbd6c..30b49ed 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -28,6 +28,80 @@
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 #include <net/netfilter/nf_conntrack.h>
 #endif
+#include <net/net_namespace.h>		/* Netw namespace */
+
+/*
+ * Generic access of ipvs struct
+ */
+static inline struct netns_ipvs *net_ipvs(struct net* net)
+{
+	return net->ipvs;
+}
+/*
+ * Get net ptr from skb in traffic cases
+ * use skb_sknet when call is from userland (ioctl or netlink)
+ */
+static inline struct net *skb_net(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_NS
+#ifdef CONFIG_IP_VS_DEBUG
+	/*
+	 * This is used for debug only.
+	 * Start with the most likely hit
+	 * End with BUG
+	 */
+	if (likely(skb->dev && skb->dev->nd_net))
+		return dev_net(skb->dev);
+	if (skb_dst(skb)->dev)
+		return dev_net(skb_dst(skb)->dev);
+	WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",
+		      __func__, __LINE__);
+	if (likely(skb->sk && skb->sk->sk_net))
+		return sock_net(skb->sk);
+	pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
+		__func__, __LINE__);
+	BUG();
+#else
+	return dev_net(skb->dev ? : skb_dst(skb)->dev);
+#endif
+#else
+	return &init_net;
+#endif
+}
+
+static inline struct net *skb_sknet(const struct sk_buff *skb)
+{
+#ifdef CONFIG_NET_NS
+#ifdef CONFIG_IP_VS_DEBUG
+	/* Start with the most likely hit */
+	if (likely(skb->sk && skb->sk->sk_net))
+		return sock_net(skb->sk);
+	WARN(skb->dev, "Maybe skb_net should be used instead in %s() line:%d\n",
+		       __func__, __LINE__);
+	if (likely(skb->dev && skb->dev->nd_net))
+		return dev_net(skb->dev);
+	pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
+		__func__, __LINE__);
+	BUG();
+#else
+	return sock_net(skb->sk);
+#endif
+#else
+	return &init_net;
+#endif
+}
+/*
+ * This one needed for single_open_net since net is stored directly in
+ * private not as a struct i.e. seq_file_net cant be used.
+ */
+static inline struct net *seq_file_single_net(struct seq_file *seq)
+{
+#ifdef CONFIG_NET_NS
+	return (struct net *)seq->private;
+#else
+	return &init_net;
+#endif
+}
 
 /* Connections' size value needed by ip_vs_ctl.c */
 extern int ip_vs_conn_tab_size;
@@ -258,6 +332,23 @@ struct ip_vs_seq {
 						   before last resized pkt */
 };
 
+/*
+ * counters per cpu
+ */
+struct ip_vs_counters {
+	__u32		conns;		/* connections scheduled */
+	__u32		inpkts;		/* incoming packets */
+	__u32		outpkts;	/* outgoing packets */
+	__u64		inbytes;	/* incoming bytes */
+	__u64		outbytes;	/* outgoing bytes */
+};
+/*
+ * Stats per cpu
+ */
+struct ip_vs_cpu_stats {
+	struct ip_vs_counters   ustats;
+	struct u64_stats_sync   syncp;
+};
 
 /*
  *	IPVS statistics objects
@@ -279,10 +370,11 @@ struct ip_vs_estimator {
 };
 
 struct ip_vs_stats {
-	struct ip_vs_stats_user	ustats;         /* statistics */
+	struct ip_vs_stats_user	ustats;		/* statistics */
 	struct ip_vs_estimator	est;		/* estimator */
-
-	spinlock_t              lock;           /* spin lock */
+	struct ip_vs_cpu_stats	*cpustats;	/* per cpu counters */
+	spinlock_t		lock;		/* spin lock */
+	struct ip_vs_stats_user	ustats0;	/* reset values */
 };
 
 struct dst_entry;
@@ -290,6 +382,7 @@ struct iphdr;
 struct ip_vs_conn;
 struct ip_vs_app;
 struct sk_buff;
+struct ip_vs_proto_data;
 
 struct ip_vs_protocol {
 	struct ip_vs_protocol	*next;
@@ -297,21 +390,22 @@ struct ip_vs_protocol {
 	u16			protocol;
 	u16			num_states;
 	int			dont_defrag;
-	atomic_t		appcnt;		/* counter of proto app incs */
-	int			*timeout_table;	/* protocol timeout table */
 
 	void (*init)(struct ip_vs_protocol *pp);
 
 	void (*exit)(struct ip_vs_protocol *pp);
 
+	void (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
+
+	void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd);
+
 	int (*conn_schedule)(int af, struct sk_buff *skb,
-			     struct ip_vs_protocol *pp,
+			     struct ip_vs_proto_data *pd,
 			     int *verdict, struct ip_vs_conn **cpp);
 
 	struct ip_vs_conn *
 	(*conn_in_get)(int af,
 		       const struct sk_buff *skb,
-		       struct ip_vs_protocol *pp,
 		       const struct ip_vs_iphdr *iph,
 		       unsigned int proto_off,
 		       int inverse);
@@ -319,7 +413,6 @@ struct ip_vs_protocol {
 	struct ip_vs_conn *
 	(*conn_out_get)(int af,
 			const struct sk_buff *skb,
-			struct ip_vs_protocol *pp,
 			const struct ip_vs_iphdr *iph,
 			unsigned int proto_off,
 			int inverse);
@@ -337,11 +430,11 @@ struct ip_vs_protocol {
 
 	int (*state_transition)(struct ip_vs_conn *cp, int direction,
 				const struct sk_buff *skb,
-				struct ip_vs_protocol *pp);
+				struct ip_vs_proto_data *pd);
 
-	int (*register_app)(struct ip_vs_app *inc);
+	int (*register_app)(struct net *net, struct ip_vs_app *inc);
 
-	void (*unregister_app)(struct ip_vs_app *inc);
+	void (*unregister_app)(struct net *net, struct ip_vs_app *inc);
 
 	int (*app_conn_bind)(struct ip_vs_conn *cp);
 
@@ -350,14 +443,26 @@ struct ip_vs_protocol {
 			     int offset,
 			     const char *msg);
 
-	void (*timeout_change)(struct ip_vs_protocol *pp, int flags);
+	void (*timeout_change)(struct ip_vs_proto_data *pd, int flags);
+};
 
-	int (*set_state_timeout)(struct ip_vs_protocol *pp, char *sname, int to);
+/*
+ * protocol data per netns
+ */
+struct ip_vs_proto_data {
+	struct ip_vs_proto_data	*next;
+	struct ip_vs_protocol	*pp;
+	int			*timeout_table;	/* protocol timeout table */
+	atomic_t		appcnt;		/* counter of proto app incs. */
+	struct tcp_states_t	*tcp_state_table;
 };
 
-extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto);
+extern struct ip_vs_protocol   *ip_vs_proto_get(unsigned short proto);
+extern struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net,
+						     unsigned short proto);
 
 struct ip_vs_conn_param {
+	struct net			*net;
 	const union nf_inet_addr	*caddr;
 	const union nf_inet_addr	*vaddr;
 	__be16				cport;
@@ -374,17 +479,20 @@ struct ip_vs_conn_param {
  *	IP_VS structure allocated for each dynamically scheduled connection
  */
 struct ip_vs_conn {
-	struct list_head        c_list;         /* hashed list heads */
-
+	struct hlist_node	c_list;         /* hashed list heads */
+#ifdef CONFIG_NET_NS
+	struct net              *net;           /* Name space */
+#endif
 	/* Protocol, addresses and port numbers */
-	u16                      af;		/* address family */
-	union nf_inet_addr       caddr;          /* client address */
-	union nf_inet_addr       vaddr;          /* virtual address */
-	union nf_inet_addr       daddr;          /* destination address */
-	volatile __u32           flags;          /* status flags */
-	__be16                   cport;
-	__be16                   vport;
-	__be16                   dport;
+	u16                     af;             /* address family */
+	__be16                  cport;
+	__be16                  vport;
+	__be16                  dport;
+	__u32                   fwmark;         /* Fire wall mark from skb */
+	union nf_inet_addr      caddr;          /* client address */
+	union nf_inet_addr      vaddr;          /* virtual address */
+	union nf_inet_addr      daddr;          /* destination address */
+	volatile __u32          flags;          /* status flags */
 	__u16                   protocol;       /* Which protocol (TCP/UDP) */
 
 	/* counter and timer */
@@ -422,10 +530,38 @@ struct ip_vs_conn {
 	struct ip_vs_seq        in_seq;         /* incoming seq. struct */
 	struct ip_vs_seq        out_seq;        /* outgoing seq. struct */
 
+	const struct ip_vs_pe	*pe;
 	char			*pe_data;
 	__u8			pe_data_len;
 };
 
+/*
+ *  To save some memory in conn table when name space is disabled.
+ */
+static inline struct net *ip_vs_conn_net(const struct ip_vs_conn *cp)
+{
+#ifdef CONFIG_NET_NS
+	return cp->net;
+#else
+	return &init_net;
+#endif
+}
+static inline void ip_vs_conn_net_set(struct ip_vs_conn *cp, struct net *net)
+{
+#ifdef CONFIG_NET_NS
+	cp->net = net;
+#endif
+}
+
+static inline int ip_vs_conn_net_eq(const struct ip_vs_conn *cp,
+				    struct net *net)
+{
+#ifdef CONFIG_NET_NS
+	return cp->net == net;
+#else
+	return 1;
+#endif
+}
 
 /*
  *	Extended internal versions of struct ip_vs_service_user and
@@ -485,6 +621,7 @@ struct ip_vs_service {
 	unsigned		flags;	  /* service status flags */
 	unsigned		timeout;  /* persistent timeout in ticks */
 	__be32			netmask;  /* grouping granularity */
+	struct net		*net;
 
 	struct list_head	destinations;  /* real server d-linked list */
 	__u32			num_dests;     /* number of servers */
@@ -510,8 +647,8 @@ struct ip_vs_dest {
 	struct list_head	d_list;   /* for table with all the dests */
 
 	u16			af;		/* address family */
-	union nf_inet_addr	addr;		/* IP address of the server */
 	__be16			port;		/* port number of the server */
+	union nf_inet_addr	addr;		/* IP address of the server */
 	volatile unsigned	flags;		/* dest status flags */
 	atomic_t		conn_flags;	/* flags to copy to conn */
 	atomic_t		weight;		/* server weight */
@@ -538,8 +675,8 @@ struct ip_vs_dest {
 	/* for virtual service */
 	struct ip_vs_service	*svc;		/* service it belongs to */
 	__u16			protocol;	/* which protocol (TCP/UDP) */
-	union nf_inet_addr	vaddr;		/* virtual IP address */
 	__be16			vport;		/* virtual port number */
+	union nf_inet_addr	vaddr;		/* virtual IP address */
 	__u32			vfwmark;	/* firewall mark of service */
 };
 
@@ -651,6 +788,169 @@ struct ip_vs_app {
 	void (*timeout_change)(struct ip_vs_app *app, int flags);
 };
 
+/* IPVS in network namespace */
+struct netns_ipvs {
+	int			gen;		/* Generation */
+	/*
+	 *	Hash table: for real service lookups
+	 */
+	#define IP_VS_RTAB_BITS 4
+	#define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
+	#define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1)
+
+	struct list_head	rs_table[IP_VS_RTAB_SIZE];
+	/* ip_vs_app */
+	struct list_head	app_list;
+
+	/* ip_vs_proto */
+	#define IP_VS_PROTO_TAB_SIZE	32	/* must be power of 2 */
+	struct ip_vs_proto_data *proto_data_table[IP_VS_PROTO_TAB_SIZE];
+	/* ip_vs_proto_tcp */
+#ifdef CONFIG_IP_VS_PROTO_TCP
+	#define	TCP_APP_TAB_BITS	4
+	#define	TCP_APP_TAB_SIZE	(1 << TCP_APP_TAB_BITS)
+	#define	TCP_APP_TAB_MASK	(TCP_APP_TAB_SIZE - 1)
+	struct list_head	tcp_apps[TCP_APP_TAB_SIZE];
+	spinlock_t		tcp_app_lock;
+#endif
+	/* ip_vs_proto_udp */
+#ifdef CONFIG_IP_VS_PROTO_UDP
+	#define	UDP_APP_TAB_BITS	4
+	#define	UDP_APP_TAB_SIZE	(1 << UDP_APP_TAB_BITS)
+	#define	UDP_APP_TAB_MASK	(UDP_APP_TAB_SIZE - 1)
+	struct list_head	udp_apps[UDP_APP_TAB_SIZE];
+	spinlock_t		udp_app_lock;
+#endif
+	/* ip_vs_proto_sctp */
+#ifdef CONFIG_IP_VS_PROTO_SCTP
+	#define SCTP_APP_TAB_BITS	4
+	#define SCTP_APP_TAB_SIZE	(1 << SCTP_APP_TAB_BITS)
+	#define SCTP_APP_TAB_MASK	(SCTP_APP_TAB_SIZE - 1)
+	/* Hash table for SCTP application incarnations	 */
+	struct list_head	sctp_apps[SCTP_APP_TAB_SIZE];
+	spinlock_t		sctp_app_lock;
+#endif
+	/* ip_vs_conn */
+	atomic_t		conn_count;      /*  connection counter */
+
+	/* ip_vs_ctl */
+	struct ip_vs_stats		tot_stats;  /* Statistics & est. */
+
+	int			num_services;    /* no of virtual services */
+
+	rwlock_t		rs_lock;         /* real services table */
+	/* semaphore for IPVS sockopts. And, [gs]etsockopt may sleep. */
+	struct lock_class_key	ctl_key;	/* ctl_mutex debuging */
+	/* Trash for destinations */
+	struct list_head	dest_trash;
+	/* Service counters */
+	atomic_t		ftpsvc_counter;
+	atomic_t		nullsvc_counter;
+
+#ifdef CONFIG_SYSCTL
+	/* 1/rate drop and drop-entry variables */
+	struct delayed_work	defense_work;   /* Work handler */
+	int			drop_rate;
+	int			drop_counter;
+	atomic_t		dropentry;
+	/* locks in ctl.c */
+	spinlock_t		dropentry_lock;  /* drop entry handling */
+	spinlock_t		droppacket_lock; /* drop packet handling */
+	spinlock_t		securetcp_lock;  /* state and timeout tables */
+
+	/* sys-ctl struct */
+	struct ctl_table_header	*sysctl_hdr;
+	struct ctl_table	*sysctl_tbl;
+#endif
+
+	/* sysctl variables */
+	int			sysctl_amemthresh;
+	int			sysctl_am_droprate;
+	int			sysctl_drop_entry;
+	int			sysctl_drop_packet;
+	int			sysctl_secure_tcp;
+#ifdef CONFIG_IP_VS_NFCT
+	int			sysctl_conntrack;
+#endif
+	int			sysctl_snat_reroute;
+	int			sysctl_sync_ver;
+	int			sysctl_cache_bypass;
+	int			sysctl_expire_nodest_conn;
+	int			sysctl_expire_quiescent_template;
+	int			sysctl_sync_threshold[2];
+	int			sysctl_nat_icmp_send;
+
+	/* ip_vs_lblc */
+	int			sysctl_lblc_expiration;
+	struct ctl_table_header	*lblc_ctl_header;
+	struct ctl_table	*lblc_ctl_table;
+	/* ip_vs_lblcr */
+	int			sysctl_lblcr_expiration;
+	struct ctl_table_header	*lblcr_ctl_header;
+	struct ctl_table	*lblcr_ctl_table;
+	/* ip_vs_est */
+	struct list_head	est_list;	/* estimator list */
+	spinlock_t		est_lock;
+	struct timer_list	est_timer;	/* Estimation timer */
+	/* ip_vs_sync */
+	struct list_head	sync_queue;
+	spinlock_t		sync_lock;
+	struct ip_vs_sync_buff  *sync_buff;
+	spinlock_t		sync_buff_lock;
+	struct sockaddr_in	sync_mcast_addr;
+	struct task_struct	*master_thread;
+	struct task_struct	*backup_thread;
+	int			send_mesg_maxlen;
+	int			recv_mesg_maxlen;
+	volatile int		sync_state;
+	volatile int		master_syncid;
+	volatile int		backup_syncid;
+	/* multicast interface name */
+	char			master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
+	char			backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
+	/* net name space ptr */
+	struct net		*net;            /* Needed by timer routines */
+};
+
+#define DEFAULT_SYNC_THRESHOLD	3
+#define DEFAULT_SYNC_PERIOD	50
+#define DEFAULT_SYNC_VER	1
+
+#ifdef CONFIG_SYSCTL
+
+static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
+{
+	return ipvs->sysctl_sync_threshold[0];
+}
+
+static inline int sysctl_sync_period(struct netns_ipvs *ipvs)
+{
+	return ipvs->sysctl_sync_threshold[1];
+}
+
+static inline int sysctl_sync_ver(struct netns_ipvs *ipvs)
+{
+	return ipvs->sysctl_sync_ver;
+}
+
+#else
+
+static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
+{
+	return DEFAULT_SYNC_THRESHOLD;
+}
+
+static inline int sysctl_sync_period(struct netns_ipvs *ipvs)
+{
+	return DEFAULT_SYNC_PERIOD;
+}
+
+static inline int sysctl_sync_ver(struct netns_ipvs *ipvs)
+{
+	return DEFAULT_SYNC_VER;
+}
+
+#endif
 
 /*
  *      IPVS core functions
@@ -674,13 +974,14 @@ enum {
 	IP_VS_DIR_LAST,
 };
 
-static inline void ip_vs_conn_fill_param(int af, int protocol,
+static inline void ip_vs_conn_fill_param(struct net *net, int af, int protocol,
 					 const union nf_inet_addr *caddr,
 					 __be16 cport,
 					 const union nf_inet_addr *vaddr,
 					 __be16 vport,
 					 struct ip_vs_conn_param *p)
 {
+	p->net = net;
 	p->af = af;
 	p->protocol = protocol;
 	p->caddr = caddr;
@@ -695,7 +996,6 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
 struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
 
 struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
-					    struct ip_vs_protocol *pp,
 					    const struct ip_vs_iphdr *iph,
 					    unsigned int proto_off,
 					    int inverse);
@@ -703,7 +1003,6 @@ struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
 struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
 
 struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
-					     struct ip_vs_protocol *pp,
 					     const struct ip_vs_iphdr *iph,
 					     unsigned int proto_off,
 					     int inverse);
@@ -719,14 +1018,14 @@ extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
 struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p,
 				  const union nf_inet_addr *daddr,
 				  __be16 dport, unsigned flags,
-				  struct ip_vs_dest *dest);
+				  struct ip_vs_dest *dest, __u32 fwmark);
 extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
 
 extern const char * ip_vs_state_name(__u16 proto, int state);
 
-extern void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp);
+extern void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp);
 extern int ip_vs_check_template(struct ip_vs_conn *ct);
-extern void ip_vs_random_dropentry(void);
+extern void ip_vs_random_dropentry(struct net *net);
 extern int ip_vs_conn_init(void);
 extern void ip_vs_conn_cleanup(void);
 
@@ -796,12 +1095,12 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
  *      (from ip_vs_app.c)
  */
 #define IP_VS_APP_MAX_PORTS  8
-extern int register_ip_vs_app(struct ip_vs_app *app);
-extern void unregister_ip_vs_app(struct ip_vs_app *app);
+extern int register_ip_vs_app(struct net *net, struct ip_vs_app *app);
+extern void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app);
 extern int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
 extern void ip_vs_unbind_app(struct ip_vs_conn *cp);
-extern int
-register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port);
+extern int register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app,
+				  __u16 proto, __u16 port);
 extern int ip_vs_app_inc_get(struct ip_vs_app *inc);
 extern void ip_vs_app_inc_put(struct ip_vs_app *inc);
 
@@ -814,15 +1113,27 @@ void ip_vs_bind_pe(struct ip_vs_service *svc, struct ip_vs_pe *pe);
 void ip_vs_unbind_pe(struct ip_vs_service *svc);
 int register_ip_vs_pe(struct ip_vs_pe *pe);
 int unregister_ip_vs_pe(struct ip_vs_pe *pe);
-extern struct ip_vs_pe *ip_vs_pe_get(const char *name);
-extern void ip_vs_pe_put(struct ip_vs_pe *pe);
+struct ip_vs_pe *ip_vs_pe_getbyname(const char *name);
+struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name);
+
+static inline void ip_vs_pe_get(const struct ip_vs_pe *pe)
+{
+	if (pe && pe->module)
+		__module_get(pe->module);
+}
+
+static inline void ip_vs_pe_put(const struct ip_vs_pe *pe)
+{
+	if (pe && pe->module)
+		module_put(pe->module);
+}
 
 /*
  *	IPVS protocol functions (from ip_vs_proto.c)
  */
 extern int ip_vs_protocol_init(void);
 extern void ip_vs_protocol_cleanup(void);
-extern void ip_vs_protocol_timeout_change(int flags);
+extern void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags);
 extern int *ip_vs_create_timeout_table(int *table, int size);
 extern int
 ip_vs_set_state_timeout(int *table, int num, const char *const *names,
@@ -852,26 +1163,23 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
 extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
 extern struct ip_vs_conn *
 ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
-	       struct ip_vs_protocol *pp, int *ignored);
+	       struct ip_vs_proto_data *pd, int *ignored);
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
-			struct ip_vs_protocol *pp);
+			struct ip_vs_proto_data *pd);
+
+extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
 
 
 /*
  *      IPVS control data and functions (from ip_vs_ctl.c)
  */
-extern int sysctl_ip_vs_cache_bypass;
-extern int sysctl_ip_vs_expire_nodest_conn;
-extern int sysctl_ip_vs_expire_quiescent_template;
-extern int sysctl_ip_vs_sync_threshold[2];
-extern int sysctl_ip_vs_nat_icmp_send;
-extern int sysctl_ip_vs_conntrack;
-extern int sysctl_ip_vs_snat_reroute;
 extern struct ip_vs_stats ip_vs_stats;
 extern const struct ctl_path net_vs_ctl_path[];
+extern int sysctl_ip_vs_sync_ver;
 
+extern void ip_vs_sync_switch_mode(struct net *net, int mode);
 extern struct ip_vs_service *
-ip_vs_service_get(int af, __u32 fwmark, __u16 protocol,
+ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
 		  const union nf_inet_addr *vaddr, __be16 vport);
 
 static inline void ip_vs_service_put(struct ip_vs_service *svc)
@@ -880,7 +1188,7 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc)
 }
 
 extern struct ip_vs_dest *
-ip_vs_lookup_real_service(int af, __u16 protocol,
+ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
 			  const union nf_inet_addr *daddr, __be16 dport);
 
 extern int ip_vs_use_count_inc(void);
@@ -888,8 +1196,9 @@ extern void ip_vs_use_count_dec(void);
 extern int ip_vs_control_init(void);
 extern void ip_vs_control_cleanup(void);
 extern struct ip_vs_dest *
-ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport,
-		const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol);
+ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr,
+		__be16 dport, const union nf_inet_addr *vaddr, __be16 vport,
+		__u16 protocol, __u32 fwmark);
 extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
 
 
@@ -897,14 +1206,12 @@ extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
  *      IPVS sync daemon data and function prototypes
  *      (from ip_vs_sync.c)
  */
-extern volatile int ip_vs_sync_state;
-extern volatile int ip_vs_master_syncid;
-extern volatile int ip_vs_backup_syncid;
-extern char ip_vs_master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
-extern char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
-extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
-extern int stop_sync_thread(int state);
-extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
+extern int start_sync_thread(struct net *net, int state, char *mcast_ifn,
+			     __u8 syncid);
+extern int stop_sync_thread(struct net *net, int state);
+extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp);
+extern int ip_vs_sync_init(void);
+extern void ip_vs_sync_cleanup(void);
 
 
 /*
@@ -912,9 +1219,11 @@ extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
  */
 extern int ip_vs_estimator_init(void);
 extern void ip_vs_estimator_cleanup(void);
-extern void ip_vs_new_estimator(struct ip_vs_stats *stats);
-extern void ip_vs_kill_estimator(struct ip_vs_stats *stats);
+extern void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats);
+extern void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats);
 extern void ip_vs_zero_estimator(struct ip_vs_stats *stats);
+extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
+				 struct ip_vs_stats *stats);
 
 /*
  *	Various IPVS packet transmitters (from ip_vs_xmit.c)
@@ -947,21 +1256,25 @@ extern int ip_vs_icmp_xmit_v6
  int offset);
 #endif
 
+#ifdef CONFIG_SYSCTL
 /*
  *	This is a simple mechanism to ignore packets when
  *	we are loaded. Just set ip_vs_drop_rate to 'n' and
  *	we start to drop 1/rate of the packets
  */
-extern int ip_vs_drop_rate;
-extern int ip_vs_drop_counter;
 
-static __inline__ int ip_vs_todrop(void)
+static inline int ip_vs_todrop(struct netns_ipvs *ipvs)
 {
-	if (!ip_vs_drop_rate) return 0;
-	if (--ip_vs_drop_counter > 0) return 0;
-	ip_vs_drop_counter = ip_vs_drop_rate;
+	if (!ipvs->drop_rate)
+		return 0;
+	if (--ipvs->drop_counter > 0)
+		return 0;
+	ipvs->drop_counter = ipvs->drop_rate;
 	return 1;
 }
+#else
+static inline int ip_vs_todrop(struct netns_ipvs *ipvs) { return 0; }
+#endif
 
 /*
  *      ip_vs_fwd_tag returns the forwarding tag of the connection
@@ -1031,7 +1344,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
 {
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	enum ip_conntrack_info ctinfo;
-	struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+	struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
 	if (!ct || !nf_ct_is_untracked(ct)) {
 		nf_reset(skb);
@@ -1047,9 +1360,13 @@ static inline void ip_vs_notrack(struct sk_buff *skb)
  *      Netfilter connection tracking
  *      (from ip_vs_nfct.c)
  */
-static inline int ip_vs_conntrack_enabled(void)
+static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs)
 {
-	return sysctl_ip_vs_conntrack;
+#ifdef CONFIG_SYSCTL
+	return ipvs->sysctl_conntrack;
+#else
+	return 0;
+#endif
 }
 
 extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
@@ -1062,7 +1379,7 @@ extern void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp);
 
 #else
 
-static inline int ip_vs_conntrack_enabled(void)
+static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs)
 {
 	return 0;
 }
@@ -1084,6 +1401,20 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
 /* CONFIG_IP_VS_NFCT */
 #endif
 
+static inline unsigned int
+ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
+{
+	/*
+	 * We think the overhead of processing active connections is 256
+	 * times higher than that of inactive connections in average. (This
+	 * 256 times might not be accurate, we will change it later) We
+	 * use the following formula to estimate the overhead now:
+	 *		  dest->activeconns*256 + dest->inactconns
+	 */
+	return (atomic_read(&dest->activeconns) << 8) +
+		atomic_read(&dest->inactconns);
+}
+
 #endif /* __KERNEL__ */
 
 #endif	/* _NET_IP_VS_H */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 96e50e0..34200f9 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -492,7 +492,7 @@ extern int			ip6_rcv_finish(struct sk_buff *skb);
  */
 extern int			ip6_xmit(struct sock *sk,
 					 struct sk_buff *skb,
-					 struct flowi *fl,
+					 struct flowi6 *fl6,
 					 struct ipv6_txoptions *opt);
 
 extern int			ip6_nd_hdr(struct sock *sk,
@@ -512,7 +512,7 @@ extern int			ip6_append_data(struct sock *sk,
 		      				int hlimit,
 		      				int tclass,
 						struct ipv6_txoptions *opt,
-						struct flowi *fl,
+						struct flowi6 *fl6,
 						struct rt6_info *rt,
 						unsigned int flags,
 						int dontfrag);
@@ -523,13 +523,17 @@ extern void			ip6_flush_pending_frames(struct sock *sk);
 
 extern int			ip6_dst_lookup(struct sock *sk,
 					       struct dst_entry **dst,
-					       struct flowi *fl);
-extern int			ip6_dst_blackhole(struct sock *sk,
-						  struct dst_entry **dst,
-						  struct flowi *fl);
-extern int			ip6_sk_dst_lookup(struct sock *sk,
-						  struct dst_entry **dst,
-						  struct flowi *fl);
+					       struct flowi6 *fl6);
+extern struct dst_entry *	ip6_dst_lookup_flow(struct sock *sk,
+						    struct flowi6 *fl6,
+						    const struct in6_addr *final_dst,
+						    bool can_sleep);
+extern struct dst_entry *	ip6_sk_dst_lookup_flow(struct sock *sk,
+						       struct flowi6 *fl6,
+						       const struct in6_addr *final_dst,
+						       bool can_sleep);
+extern struct dst_entry *	ip6_blackhole_route(struct net *net,
+						    struct dst_entry *orig_dst);
 
 /*
  *	skb processing functions
@@ -562,7 +566,7 @@ extern int 			ipv6_ext_hdr(u8 nexthdr);
 
 extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
 
-extern struct in6_addr *fl6_update_dst(struct flowi *fl,
+extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
 				       const struct ipv6_txoptions *opt,
 				       struct in6_addr *orig);
 
@@ -596,8 +600,8 @@ extern int 			ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
 extern int 			ipv6_recv_rxpmtu(struct sock *sk, struct msghdr *msg, int len);
 extern void			ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port,
 						u32 info, u8 *payload);
-extern void			ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info);
-extern void			ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu);
+extern void			ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info);
+extern void			ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu);
 
 extern int inet6_release(struct socket *sock);
 extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr, 
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index eea2e61..59ba38bc 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -120,10 +120,10 @@ struct ircomm_tty_cb {
 void ircomm_tty_start(struct tty_struct *tty);
 void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self);
 
-extern int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file);
-extern int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+extern int ircomm_tty_tiocmget(struct tty_struct *tty);
+extern int ircomm_tty_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear);
-extern int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file, 
+extern int ircomm_tty_ioctl(struct tty_struct *tty, 
 			    unsigned int cmd, unsigned long arg);
 extern void ircomm_tty_set_termios(struct tty_struct *tty, 
 				   struct ktermios *old_termios);
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 62c0ce2..8650e7b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -341,6 +341,9 @@ struct ieee80211_bss_conf {
  *	the off-channel channel when a remain-on-channel offload is done
  *	in hardware -- normal packets still flow and are expected to be
  *	handled properly by the device.
+ * @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP
+ *	testing. It will be sent out with incorrect Michael MIC key to allow
+ *	TKIP countermeasures to be tested.
  *
  * Note: If you have to add new flags to the enumeration, then don't
  *	 forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
@@ -370,6 +373,7 @@ enum mac80211_tx_control_flags {
 	IEEE80211_TX_CTL_LDPC			= BIT(22),
 	IEEE80211_TX_CTL_STBC			= BIT(23) | BIT(24),
 	IEEE80211_TX_CTL_TX_OFFCHAN		= BIT(25),
+	IEEE80211_TX_INTFL_TKIP_MIC_FAILURE	= BIT(26),
 };
 
 #define IEEE80211_TX_CTL_STBC_SHIFT		23
@@ -595,9 +599,10 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
  *	the frame.
  * @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
  *	the frame.
- * @RX_FLAG_TSFT: The timestamp passed in the RX status (@mactime field)
- *	is valid. This is useful in monitor mode and necessary for beacon frames
- *	to enable IBSS merging.
+ * @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime
+ *	field) is valid and contains the time the first symbol of the MPDU
+ *	was received. This is useful in monitor mode and for proper IBSS
+ *	merging.
  * @RX_FLAG_SHORTPRE: Short preamble was used for this frame
  * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
  * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
@@ -610,7 +615,7 @@ enum mac80211_rx_flags {
 	RX_FLAG_IV_STRIPPED	= 1<<4,
 	RX_FLAG_FAILED_FCS_CRC	= 1<<5,
 	RX_FLAG_FAILED_PLCP_CRC = 1<<6,
-	RX_FLAG_TSFT		= 1<<7,
+	RX_FLAG_MACTIME_MPDU	= 1<<7,
 	RX_FLAG_SHORTPRE	= 1<<8,
 	RX_FLAG_HT		= 1<<9,
 	RX_FLAG_40MHZ		= 1<<10,
@@ -1069,6 +1074,13 @@ enum ieee80211_tkip_key_type {
  *	to decrypt group addressed frames, then IBSS RSN support is still
  *	possible but software crypto will be used. Advertise the wiphy flag
  *	only in that case.
+ *
+ * @IEEE80211_HW_AP_LINK_PS: When operating in AP mode the device
+ *	autonomously manages the PS status of connected stations. When
+ *	this flag is set mac80211 will not trigger PS mode for connected
+ *	stations based on the PM bit of incoming frames.
+ *	Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure
+ *	the PS mode of connected stations.
  */
 enum ieee80211_hw_flags {
 	IEEE80211_HW_HAS_RATE_CONTROL			= 1<<0,
@@ -1093,6 +1105,7 @@ enum ieee80211_hw_flags {
 	IEEE80211_HW_CONNECTION_MONITOR			= 1<<19,
 	IEEE80211_HW_SUPPORTS_CQM_RSSI			= 1<<20,
 	IEEE80211_HW_SUPPORTS_PER_STA_GTK		= 1<<21,
+	IEEE80211_HW_AP_LINK_PS				= 1<<22,
 };
 
 /**
@@ -1147,6 +1160,17 @@ enum ieee80211_hw_flags {
  * @napi_weight: weight used for NAPI polling.  You must specify an
  *	appropriate value here if a napi_poll operation is provided
  *	by your driver.
+
+ * @max_rx_aggregation_subframes: maximum buffer size (number of
+ *	sub-frames) to be used for A-MPDU block ack receiver
+ *	aggregation.
+ *	This is only relevant if the device has restrictions on the
+ *	number of subframes, if it relies on mac80211 to do reordering
+ *	it shouldn't be set.
+ *
+ * @max_tx_aggregation_subframes: maximum number of subframes in an
+ *	aggregate an HT driver will transmit, used by the peer as a
+ *	hint to size its reorder buffer.
  */
 struct ieee80211_hw {
 	struct ieee80211_conf conf;
@@ -1165,6 +1189,8 @@ struct ieee80211_hw {
 	u8 max_rates;
 	u8 max_report_rates;
 	u8 max_rate_tries;
+	u8 max_rx_aggregation_subframes;
+	u8 max_tx_aggregation_subframes;
 };
 
 /**
@@ -1688,7 +1714,9 @@ enum ieee80211_ampdu_mlme_action {
  *	station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
  *
  * @sta_notify: Notifies low level driver about power state transition of an
- *	associated station, AP,  IBSS/WDS/mesh peer etc. Must be atomic.
+ *	associated station, AP,  IBSS/WDS/mesh peer etc. For a VIF operating
+ *	in AP mode, this callback will not be called when the flag
+ *	%IEEE80211_HW_AP_LINK_PS is set. Must be atomic.
  *
  * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
  *	bursting) for a hardware TX queue.
@@ -1723,6 +1751,10 @@ enum ieee80211_ampdu_mlme_action {
  * 	ieee80211_ampdu_mlme_action. Starting sequence number (@ssn)
  * 	is the first frame we expect to perform the action on. Notice
  * 	that TX/RX_STOP can pass NULL for this parameter.
+ *	The @buf_size parameter is only valid when the action is set to
+ *	%IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
+ *	buffer size (number of subframes) for this session -- aggregates
+ *	containing more subframes than this may not be transmitted to the peer.
  *	Returns a negative error code on failure.
  *	The callback can sleep.
  *
@@ -1767,9 +1799,18 @@ enum ieee80211_ampdu_mlme_action {
  *	ieee80211_remain_on_channel_expired(). This callback may sleep.
  * @cancel_remain_on_channel: Requests that an ongoing off-channel period is
  *	aborted before it expires. This callback may sleep.
+ * @offchannel_tx: Transmit frame on another channel, wait for a response
+ *	and return. Reliable TX status must be reported for the frame. If the
+ *	return value is 1, then the @remain_on_channel will be used with a
+ *	regular transmission (if supported.)
+ * @offchannel_tx_cancel_wait: cancel wait associated with offchannel TX
+ *
+ * @set_ringparam: Set tx and rx ring sizes.
+ *
+ * @get_ringparam: Get tx and rx ring current and maximum sizes.
  */
 struct ieee80211_ops {
-	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
+	void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
 	int (*start)(struct ieee80211_hw *hw);
 	void (*stop)(struct ieee80211_hw *hw);
 	int (*add_interface)(struct ieee80211_hw *hw,
@@ -1825,7 +1866,8 @@ struct ieee80211_ops {
 	int (*ampdu_action)(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
 	int (*get_survey)(struct ieee80211_hw *hw, int idx,
 		struct survey_info *survey);
 	void (*rfkill_poll)(struct ieee80211_hw *hw);
@@ -1845,6 +1887,14 @@ struct ieee80211_ops {
 				 enum nl80211_channel_type channel_type,
 				 int duration);
 	int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
+	int (*offchannel_tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
+			     struct ieee80211_channel *chan,
+			     enum nl80211_channel_type channel_type,
+			     unsigned int wait);
+	int (*offchannel_tx_cancel_wait)(struct ieee80211_hw *hw);
+	int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
+	void (*get_ringparam)(struct ieee80211_hw *hw,
+			      u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
 };
 
 /**
@@ -2113,6 +2163,48 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
 	local_bh_enable();
 }
 
+/**
+ * ieee80211_sta_ps_transition - PS transition for connected sta
+ *
+ * When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS
+ * flag set, use this function to inform mac80211 about a connected station
+ * entering/leaving PS mode.
+ *
+ * This function may not be called in IRQ context or with softirqs enabled.
+ *
+ * Calls to this function for a single hardware must be synchronized against
+ * each other.
+ *
+ * The function returns -EINVAL when the requested PS mode is already set.
+ *
+ * @sta: currently connected sta
+ * @start: start or stop PS
+ */
+int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start);
+
+/**
+ * ieee80211_sta_ps_transition_ni - PS transition for connected sta
+ *                                  (in process context)
+ *
+ * Like ieee80211_sta_ps_transition() but can be called in process context
+ * (internally disables bottom halves). Concurrent call restriction still
+ * applies.
+ *
+ * @sta: currently connected sta
+ * @start: start or stop PS
+ */
+static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
+						  bool start)
+{
+	int ret;
+
+	local_bh_disable();
+	ret = ieee80211_sta_ps_transition(sta, start);
+	local_bh_enable();
+
+	return ret;
+}
+
 /*
  * The TX headroom reserved by mac80211 for its own tx_status functions.
  * This is enough for the radiotap header.
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 1bf812b..3ae4919 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -27,6 +27,7 @@ struct sock;
 struct ctl_table_header;
 struct net_generic;
 struct sock;
+struct netns_ipvs;
 
 
 #define NETDEV_HASHBITS    8
@@ -94,6 +95,7 @@ struct net {
 #ifdef CONFIG_XFRM
 	struct netns_xfrm	xfrm;
 #endif
+	struct netns_ipvs	*ipvs;
 };
 
 
diff --git a/include/net/netevent.h b/include/net/netevent.h
index e82b7ba..22b239c 100644
--- a/include/net/netevent.h
+++ b/include/net/netevent.h
@@ -21,7 +21,6 @@ struct netevent_redirect {
 
 enum netevent_notif_type {
 	NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */
-	NETEVENT_PMTU_UPDATE,	   /* arg is struct dst_entry ptr */
 	NETEVENT_REDIRECT,	   /* arg is struct netevent_redirect ptr */
 };
 
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index d85cff1..d0d1337 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -50,11 +50,24 @@ union nf_conntrack_expect_proto {
 /* per conntrack: application helper private data */
 union nf_conntrack_help {
 	/* insert conntrack helper private data (master) here */
+#if defined(CONFIG_NF_CONNTRACK_FTP) || defined(CONFIG_NF_CONNTRACK_FTP_MODULE)
 	struct nf_ct_ftp_master ct_ftp_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_PPTP) || \
+    defined(CONFIG_NF_CONNTRACK_PPTP_MODULE)
 	struct nf_ct_pptp_master ct_pptp_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_H323) || \
+    defined(CONFIG_NF_CONNTRACK_H323_MODULE)
 	struct nf_ct_h323_master ct_h323_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_SANE) || \
+    defined(CONFIG_NF_CONNTRACK_SANE_MODULE)
 	struct nf_ct_sane_master ct_sane_info;
+#endif
+#if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE)
 	struct nf_ct_sip_master ct_sip_info;
+#endif
 };
 
 #include <linux/types.h>
@@ -116,14 +129,14 @@ struct nf_conn {
 	u_int32_t secmark;
 #endif
 
-	/* Storage reserved for other modules: */
-	union nf_conntrack_proto proto;
-
 	/* Extensions */
 	struct nf_ct_ext *ext;
 #ifdef CONFIG_NET_NS
 	struct net *ct_net;
 #endif
+
+	/* Storage reserved for other modules, must be the last member */
+	union nf_conntrack_proto proto;
 };
 
 static inline struct nf_conn *
@@ -189,9 +202,9 @@ extern void nf_ct_l3proto_module_put(unsigned short l3proto);
  * Allocate a hashtable of hlist_head (if nulls == 0),
  * or hlist_nulls_head (if nulls == 1)
  */
-extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls);
+extern void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
 
-extern void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size);
+extern void nf_ct_free_hashtable(void *hash, unsigned int size);
 
 extern struct nf_conntrack_tuple_hash *
 __nf_conntrack_find(struct net *net, u16 zone,
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 349cefe..4283508 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -23,12 +23,17 @@ struct nf_conntrack_ecache {
 static inline struct nf_conntrack_ecache *
 nf_ct_ecache_find(const struct nf_conn *ct)
 {
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
 	return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
+#else
+	return NULL;
+#endif
 }
 
 static inline struct nf_conntrack_ecache *
 nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
 {
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
 	struct net *net = nf_ct_net(ct);
 	struct nf_conntrack_ecache *e;
 
@@ -45,6 +50,9 @@ nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
 		e->expmask = expmask;
 	}
 	return e;
+#else
+	return NULL;
+#endif
 };
 
 #ifdef CONFIG_NF_CONNTRACK_EVENTS
@@ -59,7 +67,7 @@ struct nf_ct_event_notifier {
 	int (*fcn)(unsigned int events, struct nf_ct_event *item);
 };
 
-extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
+extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
 extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
 extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
 
@@ -156,7 +164,7 @@ struct nf_exp_event_notifier {
 	int (*fcn)(unsigned int events, struct nf_exp_event *item);
 };
 
-extern struct nf_exp_event_notifier *nf_expect_event_cb;
+extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
 extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
 extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
 
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h
index 0772d29..2dcf317 100644
--- a/include/net/netfilter/nf_conntrack_extend.h
+++ b/include/net/netfilter/nf_conntrack_extend.h
@@ -7,10 +7,19 @@
 
 enum nf_ct_ext_id {
 	NF_CT_EXT_HELPER,
+#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
 	NF_CT_EXT_NAT,
+#endif
 	NF_CT_EXT_ACCT,
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
 	NF_CT_EXT_ECACHE,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_ZONES
 	NF_CT_EXT_ZONE,
+#endif
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+	NF_CT_EXT_TSTAMP,
+#endif
 	NF_CT_EXT_NUM,
 };
 
@@ -19,6 +28,7 @@ enum nf_ct_ext_id {
 #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
 #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
 #define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone
+#define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp
 
 /* Extensions: optional stuff which isn't permanently in struct. */
 struct nf_ct_ext {
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 32c305d..f1c1311 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -63,4 +63,10 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
 extern int nf_conntrack_helper_init(void);
 extern void nf_conntrack_helper_fini(void);
 
+extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
+				       unsigned int protoff,
+				       struct nf_conn *ct,
+				       enum ip_conntrack_info ctinfo,
+				       unsigned int timeout);
+
 #endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index a754761..e8010f4 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -73,7 +73,7 @@ struct nf_conntrack_l3proto {
 	struct module *me;
 };
 
-extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX];
+extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
 
 /* Protocol registration. */
 extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
diff --git a/include/net/netfilter/nf_conntrack_timestamp.h b/include/net/netfilter/nf_conntrack_timestamp.h
new file mode 100644
index 0000000..fc9c82b
--- /dev/null
+++ b/include/net/netfilter/nf_conntrack_timestamp.h
@@ -0,0 +1,65 @@
+#ifndef _NF_CONNTRACK_TSTAMP_H
+#define _NF_CONNTRACK_TSTAMP_H
+
+#include <net/net_namespace.h>
+#include <linux/netfilter/nf_conntrack_common.h>
+#include <linux/netfilter/nf_conntrack_tuple_common.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+
+struct nf_conn_tstamp {
+	u_int64_t start;
+	u_int64_t stop;
+};
+
+static inline
+struct nf_conn_tstamp *nf_conn_tstamp_find(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+	return nf_ct_ext_find(ct, NF_CT_EXT_TSTAMP);
+#else
+	return NULL;
+#endif
+}
+
+static inline
+struct nf_conn_tstamp *nf_ct_tstamp_ext_add(struct nf_conn *ct, gfp_t gfp)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+	struct net *net = nf_ct_net(ct);
+
+	if (!net->ct.sysctl_tstamp)
+		return NULL;
+
+	return nf_ct_ext_add(ct, NF_CT_EXT_TSTAMP, gfp);
+#else
+	return NULL;
+#endif
+};
+
+static inline bool nf_ct_tstamp_enabled(struct net *net)
+{
+	return net->ct.sysctl_tstamp != 0;
+}
+
+static inline void nf_ct_set_tstamp(struct net *net, bool enable)
+{
+	net->ct.sysctl_tstamp = enable;
+}
+
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+extern int nf_conntrack_tstamp_init(struct net *net);
+extern void nf_conntrack_tstamp_fini(struct net *net);
+#else
+static inline int nf_conntrack_tstamp_init(struct net *net)
+{
+	return 0;
+}
+
+static inline void nf_conntrack_tstamp_fini(struct net *net)
+{
+	return;
+}
+#endif /* CONFIG_NF_CONNTRACK_TIMESTAMP */
+
+#endif /* _NF_CONNTRACK_TSTAMP_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index f5f09f0..aff80b1 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -56,7 +56,9 @@ struct nf_nat_multi_range_compat {
 /* per conntrack: nat application helper private data */
 union nf_conntrack_nat_help {
 	/* insert nat helper private data here */
+#if defined(CONFIG_NF_NAT_PPTP) || defined(CONFIG_NF_NAT_PPTP_MODULE)
 	struct nf_nat_pptp nat_pptp_info;
+#endif
 };
 
 struct nf_conn;
@@ -84,7 +86,11 @@ extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
 
 static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
 {
+#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
 	return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
+#else
+	return NULL;
+#endif
 }
 
 #else  /* !__KERNEL__: iptables wants this to compile. */
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 33602ab..3dc7b98 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -21,9 +21,9 @@ static inline int nf_nat_initialized(struct nf_conn *ct,
 				     enum nf_nat_manip_type manip)
 {
 	if (manip == IP_NAT_MANIP_SRC)
-		return test_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
+		return ct->status & IPS_SRC_NAT_DONE;
 	else
-		return test_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
+		return ct->status & IPS_DST_NAT_DONE;
 }
 
 struct nlattr;
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 373f1a9..8a3906a 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -856,18 +856,27 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,
 #define NLA_PUT_BE16(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, __be16, attrtype, value)
 
+#define NLA_PUT_NET16(skb, attrtype, value) \
+	NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
+
 #define NLA_PUT_U32(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, u32, attrtype, value)
 
 #define NLA_PUT_BE32(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, __be32, attrtype, value)
 
+#define NLA_PUT_NET32(skb, attrtype, value) \
+	NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
+
 #define NLA_PUT_U64(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, u64, attrtype, value)
 
 #define NLA_PUT_BE64(skb, attrtype, value) \
 	NLA_PUT_TYPE(skb, __be64, attrtype, value)
 
+#define NLA_PUT_NET64(skb, attrtype, value) \
+	NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
+
 #define NLA_PUT_STRING(skb, attrtype, value) \
 	NLA_PUT(skb, attrtype, strlen(value) + 1, value)
 
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index d4958d4..341eb08 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -21,15 +21,15 @@ struct netns_ct {
 	int			sysctl_events;
 	unsigned int		sysctl_events_retry_timeout;
 	int			sysctl_acct;
+	int			sysctl_tstamp;
 	int			sysctl_checksum;
 	unsigned int		sysctl_log_invalid; /* Log invalid packets */
 #ifdef CONFIG_SYSCTL
 	struct ctl_table_header	*sysctl_header;
 	struct ctl_table_header	*acct_sysctl_header;
+	struct ctl_table_header	*tstamp_sysctl_header;
 	struct ctl_table_header	*event_sysctl_header;
 #endif
-	int			hash_vmalloc;
-	int			expect_vmalloc;
 	char			*slabname;
 };
 #endif
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index d68c3f1..e2e2ef5 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -43,7 +43,6 @@ struct netns_ipv4 {
 	struct xt_table		*nat_table;
 	struct hlist_head	*nat_bysource;
 	unsigned int		nat_htable_size;
-	int			nat_vmalloced;
 #endif
 
 	int sysctl_icmp_echo_ignore_all;
diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
index b60b28c..b669fe6 100644
--- a/include/net/phonet/pep.h
+++ b/include/net/phonet/pep.h
@@ -28,7 +28,6 @@ struct pep_sock {
 
 	/* XXX: union-ify listening vs connected stuff ? */
 	/* Listening socket stuff: */
-	struct hlist_head	ackq;
 	struct hlist_head	hlist;
 
 	/* Connected socket stuff: */
@@ -45,10 +44,6 @@ struct pep_sock {
 	u8			tx_fc;	/* TX flow control */
 	u8			init_enable;	/* auto-enable at creation */
 	u8			aligned;
-#ifdef CONFIG_PHONET_PIPECTRLR
-	u8			pipe_state;
-	struct sockaddr_pn	remote_pep;
-#endif
 };
 
 static inline struct pep_sock *pep_sk(struct sock *sk)
@@ -158,6 +153,7 @@ enum {
 	PN_LEGACY_FLOW_CONTROL,
 	PN_ONE_CREDIT_FLOW_CONTROL,
 	PN_MULTI_CREDIT_FLOW_CONTROL,
+	PN_MAX_FLOW_CONTROL,
 };
 
 #define pn_flow_safe(fc) ((fc) >> 1)
@@ -169,21 +165,4 @@ enum {
 	PEP_IND_READY,
 };
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-#define PNS_PEP_CONNECT_UTID           0x02
-#define PNS_PIPE_CREATED_IND_UTID      0x04
-#define PNS_PIPE_ENABLE_UTID           0x0A
-#define PNS_PIPE_ENABLED_IND_UTID      0x0C
-#define PNS_PIPE_DISABLE_UTID          0x0F
-#define PNS_PIPE_DISABLED_IND_UTID     0x11
-#define PNS_PEP_DISCONNECT_UTID        0x06
-
-/* Used for tracking state of a pipe */
-enum {
-	PIPE_IDLE,
-	PIPE_DISABLED,
-	PIPE_ENABLED,
-};
-#endif /* CONFIG_PHONET_PIPECTRLR */
-
 #endif
diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
index 5395e09..68e5097 100644
--- a/include/net/phonet/phonet.h
+++ b/include/net/phonet/phonet.h
@@ -36,6 +36,7 @@
 struct pn_sock {
 	struct sock	sk;
 	u16		sobject;
+	u16		dobject;
 	u8		resource;
 };
 
diff --git a/include/net/protocol.h b/include/net/protocol.h
index dc07495..6f7eb80 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -38,7 +38,7 @@ struct net_protocol {
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
 	int			(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
-					       int features);
+					       u32 features);
 	struct sk_buff	      **(*gro_receive)(struct sk_buff **head,
 					       struct sk_buff *skb);
 	int			(*gro_complete)(struct sk_buff *skb);
@@ -57,7 +57,7 @@ struct inet6_protocol {
 
 	int	(*gso_send_check)(struct sk_buff *skb);
 	struct sk_buff *(*gso_segment)(struct sk_buff *skb,
-				       int features);
+				       u32 features);
 	struct sk_buff **(*gro_receive)(struct sk_buff **head,
 					struct sk_buff *skb);
 	int	(*gro_complete)(struct sk_buff *skb);
diff --git a/include/net/route.h b/include/net/route.h
index 93e10c4..30d6cae 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -49,36 +49,43 @@
 
 struct fib_nh;
 struct inet_peer;
+struct fib_info;
 struct rtable {
 	struct dst_entry	dst;
 
-	/* Cache lookup keys */
-	struct flowi		fl;
+	/* Lookup key. */
+	__be32			rt_key_dst;
+	__be32			rt_key_src;
 
 	int			rt_genid;
 	unsigned		rt_flags;
 	__u16			rt_type;
+	__u8			rt_tos;
 
 	__be32			rt_dst;	/* Path destination	*/
 	__be32			rt_src;	/* Path source		*/
 	int			rt_iif;
+	int			rt_oif;
+	__u32			rt_mark;
 
 	/* Info on neighbour */
 	__be32			rt_gateway;
 
 	/* Miscellaneous cached information */
 	__be32			rt_spec_dst; /* RFC1122 specific destination */
+	u32			rt_peer_genid;
 	struct inet_peer	*peer; /* long-living peer info */
+	struct fib_info		*fi; /* for client ref to shared metrics */
 };
 
 static inline bool rt_is_input_route(struct rtable *rt)
 {
-	return rt->fl.iif != 0;
+	return rt->rt_iif != 0;
 }
 
 static inline bool rt_is_output_route(struct rtable *rt)
 {
-	return rt->fl.iif == 0;
+	return rt->rt_iif == 0;
 }
 
 struct ip_rt_acct {
@@ -115,9 +122,63 @@ extern void		ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw,
 				       __be32 src, struct net_device *dev);
 extern void		rt_cache_flush(struct net *net, int how);
 extern void		rt_cache_flush_batch(struct net *net);
-extern int		__ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp);
-extern int		ip_route_output_key(struct net *, struct rtable **, struct flowi *flp);
-extern int		ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags);
+extern struct rtable *__ip_route_output_key(struct net *, const struct flowi4 *flp);
+extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
+					   struct sock *sk);
+extern struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig);
+
+static inline struct rtable *ip_route_output_key(struct net *net, struct flowi4 *flp)
+{
+	return ip_route_output_flow(net, flp, NULL);
+}
+
+static inline struct rtable *ip_route_output(struct net *net, __be32 daddr,
+					     __be32 saddr, u8 tos, int oif)
+{
+	struct flowi4 fl4 = {
+		.flowi4_oif = oif,
+		.daddr = daddr,
+		.saddr = saddr,
+		.flowi4_tos = tos,
+	};
+	return ip_route_output_key(net, &fl4);
+}
+
+static inline struct rtable *ip_route_output_ports(struct net *net, struct sock *sk,
+						   __be32 daddr, __be32 saddr,
+						   __be16 dport, __be16 sport,
+						   __u8 proto, __u8 tos, int oif)
+{
+	struct flowi4 fl4 = {
+		.flowi4_oif = oif,
+		.flowi4_flags = sk ? inet_sk_flowi_flags(sk) : 0,
+		.flowi4_mark = sk ? sk->sk_mark : 0,
+		.daddr = daddr,
+		.saddr = saddr,
+		.flowi4_tos = tos,
+		.flowi4_proto = proto,
+		.fl4_dport = dport,
+		.fl4_sport = sport,
+	};
+	if (sk)
+		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+	return ip_route_output_flow(net, &fl4, sk);
+}
+
+static inline struct rtable *ip_route_output_gre(struct net *net,
+						 __be32 daddr, __be32 saddr,
+						 __be32 gre_key, __u8 tos, int oif)
+{
+	struct flowi4 fl4 = {
+		.flowi4_oif = oif,
+		.daddr = daddr,
+		.saddr = saddr,
+		.flowi4_tos = tos,
+		.flowi4_proto = IPPROTO_GRE,
+		.fl4_gre_key = gre_key,
+	};
+	return ip_route_output_key(net, &fl4);
+}
 
 extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src,
 				 u8 tos, struct net_device *devin, bool noref);
@@ -162,57 +223,68 @@ static inline char rt_tos2priority(u8 tos)
 	return ip_tos2prio[IPTOS_TOS(tos)>>1];
 }
 
-static inline int ip_route_connect(struct rtable **rp, __be32 dst,
-				   __be32 src, u32 tos, int oif, u8 protocol,
-				   __be16 sport, __be16 dport, struct sock *sk,
-				   int flags)
+static inline struct rtable *ip_route_connect(__be32 dst, __be32 src, u32 tos,
+					      int oif, u8 protocol,
+					      __be16 sport, __be16 dport,
+					      struct sock *sk, bool can_sleep)
 {
-	struct flowi fl = { .oif = oif,
-			    .mark = sk->sk_mark,
-			    .fl4_dst = dst,
-			    .fl4_src = src,
-			    .fl4_tos = tos,
-			    .proto = protocol,
-			    .fl_ip_sport = sport,
-			    .fl_ip_dport = dport };
-	int err;
+	struct flowi4 fl4 = {
+		.flowi4_oif = oif,
+		.flowi4_mark = sk->sk_mark,
+		.daddr = dst,
+		.saddr = src,
+		.flowi4_tos = tos,
+		.flowi4_proto = protocol,
+		.fl4_sport = sport,
+		.fl4_dport = dport,
+	};
 	struct net *net = sock_net(sk);
+	struct rtable *rt;
 
 	if (inet_sk(sk)->transparent)
-		fl.flags |= FLOWI_FLAG_ANYSRC;
+		fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+	if (protocol == IPPROTO_TCP)
+		fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS;
+	if (can_sleep)
+		fl4.flowi4_flags |= FLOWI_FLAG_CAN_SLEEP;
 
 	if (!dst || !src) {
-		err = __ip_route_output_key(net, rp, &fl);
-		if (err)
-			return err;
-		fl.fl4_dst = (*rp)->rt_dst;
-		fl.fl4_src = (*rp)->rt_src;
-		ip_rt_put(*rp);
-		*rp = NULL;
+		rt = __ip_route_output_key(net, &fl4);
+		if (IS_ERR(rt))
+			return rt;
+		fl4.daddr = rt->rt_dst;
+		fl4.saddr = rt->rt_src;
+		ip_rt_put(rt);
 	}
-	security_sk_classify_flow(sk, &fl);
-	return ip_route_output_flow(net, rp, &fl, sk, flags);
+	security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+	return ip_route_output_flow(net, &fl4, sk);
 }
 
-static inline int ip_route_newports(struct rtable **rp, u8 protocol,
-				    __be16 sport, __be16 dport, struct sock *sk)
+static inline struct rtable *ip_route_newports(struct rtable *rt,
+					       u8 protocol, __be16 orig_sport,
+					       __be16 orig_dport, __be16 sport,
+					       __be16 dport, struct sock *sk)
 {
-	if (sport != (*rp)->fl.fl_ip_sport ||
-	    dport != (*rp)->fl.fl_ip_dport) {
-		struct flowi fl;
-
-		memcpy(&fl, &(*rp)->fl, sizeof(fl));
-		fl.fl_ip_sport = sport;
-		fl.fl_ip_dport = dport;
-		fl.proto = protocol;
+	if (sport != orig_sport || dport != orig_dport) {
+		struct flowi4 fl4 = {
+			.flowi4_oif = rt->rt_oif,
+			.flowi4_mark = rt->rt_mark,
+			.daddr = rt->rt_key_dst,
+			.saddr = rt->rt_key_src,
+			.flowi4_tos = rt->rt_tos,
+			.flowi4_proto = protocol,
+			.fl4_sport = sport,
+			.fl4_dport = dport
+		};
 		if (inet_sk(sk)->transparent)
-			fl.flags |= FLOWI_FLAG_ANYSRC;
-		ip_rt_put(*rp);
-		*rp = NULL;
-		security_sk_classify_flow(sk, &fl);
-		return ip_route_output_flow(sock_net(sk), rp, &fl, sk, 0);
+			fl4.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+		if (protocol == IPPROTO_TCP)
+			fl4.flowi4_flags |= FLOWI_FLAG_PRECOW_METRICS;
+		ip_rt_put(rt);
+		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+		return ip_route_output_flow(sock_net(sk), &fl4, sk);
 	}
-	return 0;
+	return rt;
 }
 
 extern void rt_bind_peer(struct rtable *rt, int create);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 04f8556..a9505b6 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -31,10 +31,12 @@ enum qdisc_state_t {
  * following bits are only changed while qdisc lock is held
  */
 enum qdisc___state_t {
-	__QDISC___STATE_RUNNING,
+	__QDISC___STATE_RUNNING = 1,
+	__QDISC___STATE_THROTTLED = 2,
 };
 
 struct qdisc_size_table {
+	struct rcu_head		rcu;
 	struct list_head	list;
 	struct tc_sizespec	szopts;
 	int			refcnt;
@@ -46,14 +48,13 @@ struct Qdisc {
 	struct sk_buff *	(*dequeue)(struct Qdisc *dev);
 	unsigned		flags;
 #define TCQ_F_BUILTIN		1
-#define TCQ_F_THROTTLED		2
-#define TCQ_F_INGRESS		4
-#define TCQ_F_CAN_BYPASS	8
-#define TCQ_F_MQROOT		16
+#define TCQ_F_INGRESS		2
+#define TCQ_F_CAN_BYPASS	4
+#define TCQ_F_MQROOT		8
 #define TCQ_F_WARN_NONWC	(1 << 16)
 	int			padded;
 	struct Qdisc_ops	*ops;
-	struct qdisc_size_table	*stab;
+	struct qdisc_size_table	__rcu *stab;
 	struct list_head	list;
 	u32			handle;
 	u32			parent;
@@ -78,25 +79,44 @@ struct Qdisc {
 	unsigned long		state;
 	struct sk_buff_head	q;
 	struct gnet_stats_basic_packed bstats;
-	unsigned long		__state;
+	unsigned int		__state;
 	struct gnet_stats_queue	qstats;
 	struct rcu_head		rcu_head;
 	spinlock_t		busylock;
+	u32			limit;
 };
 
-static inline bool qdisc_is_running(struct Qdisc *qdisc)
+static inline bool qdisc_is_running(const struct Qdisc *qdisc)
 {
-	return test_bit(__QDISC___STATE_RUNNING, &qdisc->__state);
+	return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false;
 }
 
 static inline bool qdisc_run_begin(struct Qdisc *qdisc)
 {
-	return !__test_and_set_bit(__QDISC___STATE_RUNNING, &qdisc->__state);
+	if (qdisc_is_running(qdisc))
+		return false;
+	qdisc->__state |= __QDISC___STATE_RUNNING;
+	return true;
 }
 
 static inline void qdisc_run_end(struct Qdisc *qdisc)
 {
-	__clear_bit(__QDISC___STATE_RUNNING, &qdisc->__state);
+	qdisc->__state &= ~__QDISC___STATE_RUNNING;
+}
+
+static inline bool qdisc_is_throttled(const struct Qdisc *qdisc)
+{
+	return (qdisc->__state & __QDISC___STATE_THROTTLED) ? true : false;
+}
+
+static inline void qdisc_throttled(struct Qdisc *qdisc)
+{
+	qdisc->__state |= __QDISC___STATE_THROTTLED;
+}
+
+static inline void qdisc_unthrottled(struct Qdisc *qdisc)
+{
+	qdisc->__state &= ~__QDISC___STATE_THROTTLED;
 }
 
 struct Qdisc_class_ops {
@@ -331,8 +351,8 @@ extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 				 struct Qdisc_ops *ops);
 extern struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
 				       struct Qdisc_ops *ops, u32 parentid);
-extern void qdisc_calculate_pkt_len(struct sk_buff *skb,
-				   struct qdisc_size_table *stab);
+extern void __qdisc_calculate_pkt_len(struct sk_buff *skb,
+				      const struct qdisc_size_table *stab);
 extern void tcf_destroy(struct tcf_proto *tp);
 extern void tcf_destroy_chain(struct tcf_proto **fl);
 
@@ -411,12 +431,20 @@ enum net_xmit_qdisc_t {
 #define net_xmit_drop_count(e)	(1)
 #endif
 
-static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+static inline void qdisc_calculate_pkt_len(struct sk_buff *skb,
+					   const struct Qdisc *sch)
 {
 #ifdef CONFIG_NET_SCHED
-	if (sch->stab)
-		qdisc_calculate_pkt_len(skb, sch->stab);
+	struct qdisc_size_table *stab = rcu_dereference_bh(sch->stab);
+
+	if (stab)
+		__qdisc_calculate_pkt_len(skb, stab);
 #endif
+}
+
+static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	qdisc_calculate_pkt_len(skb, sch);
 	return sch->enqueue(skb, sch);
 }
 
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 762e2ab..27461d6 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -150,7 +150,7 @@ struct linux_xfrm_mib {
 #define SNMP_UPD_PO_STATS_BH(mib, basefield, addend)	\
 	do { \
 		__typeof__(*mib[0]) *ptr = \
-			__this_cpu_ptr((mib)[!in_softirq()]); \
+			__this_cpu_ptr((mib)[0]); \
 		ptr->mibs[basefield##PKTS]++; \
 		ptr->mibs[basefield##OCTETS] += addend;\
 	} while (0)
@@ -202,7 +202,7 @@ struct linux_xfrm_mib {
 #define SNMP_UPD_PO_STATS64_BH(mib, basefield, addend)			\
 	do {								\
 		__typeof__(*mib[0]) *ptr;				\
-		ptr = __this_cpu_ptr((mib)[!in_softirq()]);		\
+		ptr = __this_cpu_ptr((mib)[0]);				\
 		u64_stats_update_begin(&ptr->syncp);			\
 		ptr->mibs[basefield##PKTS]++;				\
 		ptr->mibs[basefield##OCTETS] += addend;			\
diff --git a/include/net/sock.h b/include/net/sock.h
index bc1cf7d8..da0534d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -281,7 +281,7 @@ struct sock {
 	int			sk_rcvbuf;
 
 	struct sk_filter __rcu	*sk_filter;
-	struct socket_wq	*sk_wq;
+	struct socket_wq __rcu	*sk_wq;
 
 #ifdef CONFIG_NET_DMA
 	struct sk_buff_head	sk_async_wait_queue;
@@ -1191,7 +1191,7 @@ extern void sk_filter_release_rcu(struct rcu_head *rcu);
 static inline void sk_filter_release(struct sk_filter *fp)
 {
 	if (atomic_dec_and_test(&fp->refcnt))
-		call_rcu_bh(&fp->rcu, sk_filter_release_rcu);
+		call_rcu(&fp->rcu, sk_filter_release_rcu);
 }
 
 static inline void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
@@ -1266,7 +1266,8 @@ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
 
 static inline wait_queue_head_t *sk_sleep(struct sock *sk)
 {
-	return &sk->sk_wq->wait;
+	BUILD_BUG_ON(offsetof(struct socket_wq, wait) != 0);
+	return &rcu_dereference_raw(sk->sk_wq)->wait;
 }
 /* Detach socket from process context.
  * Announce socket dead, detach it from wait queue and inode.
@@ -1287,7 +1288,7 @@ static inline void sock_orphan(struct sock *sk)
 static inline void sock_graft(struct sock *sk, struct socket *parent)
 {
 	write_lock_bh(&sk->sk_callback_lock);
-	rcu_assign_pointer(sk->sk_wq, parent->wq);
+	sk->sk_wq = parent->wq;
 	parent->sk = sk;
 	sk_set_socket(sk, parent);
 	security_sock_graft(sk, parent);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 38509f0..cda30ea 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -196,6 +196,9 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
 /* TCP thin-stream limits */
 #define TCP_THIN_LINEAR_RETRIES 6       /* After 6 linear retries, do exp. backoff */
 
+/* TCP initial congestion window as per draft-hkchu-tcpm-initcwnd-01 */
+#define TCP_INIT_CWND		10
+
 extern struct inet_timewait_death_row tcp_death_row;
 
 /* sysctl variables for tcp */
@@ -799,15 +802,6 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk)
 /* Use define here intentionally to get WARN_ON location shown at the caller */
 #define tcp_verify_left_out(tp)	WARN_ON(tcp_left_out(tp) > tp->packets_out)
 
-/*
- * Convert RFC 3390 larger initial window into an equivalent number of packets.
- * This is based on the numbers specified in RFC 5681, 3.1.
- */
-static inline u32 rfc3390_bytes_to_packets(const u32 smss)
-{
-	return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
-}
-
 extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);
 extern __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst);
 
@@ -1074,8 +1068,6 @@ static inline int tcp_paws_reject(const struct tcp_options_received *rx_opt,
 	return 1;
 }
 
-#define TCP_CHECK_TIMER(sk) do { } while (0)
-
 static inline void tcp_mib_init(struct net *net)
 {
 	/* See RFC 2012 */
@@ -1404,7 +1396,7 @@ extern struct request_sock_ops tcp6_request_sock_ops;
 extern void tcp_v4_destroy_sock(struct sock *sk);
 
 extern int tcp_v4_gso_send_check(struct sk_buff *skb);
-extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, u32 features);
 extern struct sk_buff **tcp_gro_receive(struct sk_buff **head,
 					struct sk_buff *skb);
 extern struct sk_buff **tcp4_gro_receive(struct sk_buff **head,
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index 42a0eb6..eeb077d 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -14,7 +14,7 @@ extern struct proto udpv6_prot;
 extern struct proto udplitev6_prot;
 extern struct proto tcpv6_prot;
 
-struct flowi;
+struct flowi6;
 
 /* extention headers */
 extern int				ipv6_exthdrs_init(void);
@@ -42,7 +42,7 @@ extern int			datagram_recv_ctl(struct sock *sk,
 
 extern int			datagram_send_ctl(struct net *net,
 						  struct msghdr *msg,
-						  struct flowi *fl,
+						  struct flowi6 *fl6,
 						  struct ipv6_txoptions *opt,
 						  int *hlimit, int *tclass,
 						  int *dontfrag);
diff --git a/include/net/udp.h b/include/net/udp.h
index bb967dd..67ea6fc 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -144,6 +144,17 @@ static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb)
 	return csum;
 }
 
+static inline __wsum udp_csum(struct sk_buff *skb)
+{
+	__wsum csum = csum_partial(skb_transport_header(skb),
+				   sizeof(struct udphdr), skb->csum);
+
+	for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next) {
+		csum = csum_add(csum, skb->csum);
+	}
+	return csum;
+}
+
 /* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
 static inline void udp_lib_hash(struct sock *sk)
 {
@@ -245,5 +256,5 @@ extern void udp4_proc_exit(void);
 extern void udp_init(void);
 
 extern int udp4_ufo_send_check(struct sk_buff *skb);
-extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, int features);
+extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, u32 features);
 #endif	/* _UDP_H */
diff --git a/include/net/udplite.h b/include/net/udplite.h
index afdffe6..673a024 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -115,6 +115,18 @@ static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb)
 	return csum;
 }
 
+static inline __wsum udplite_csum(struct sk_buff *skb)
+{
+	struct sock *sk = skb->sk;
+	int cscov = udplite_sender_cscov(udp_sk(sk), udp_hdr(skb));
+	const int off = skb_transport_offset(skb);
+	const int len = skb->len - off;
+
+	skb->ip_summed = CHECKSUM_NONE;     /* no HW support for checksumming */
+
+	return skb_checksum(skb, off, min(cscov, len), 0);
+}
+
 extern void	udplite4_register(void);
 extern int 	udplite_get_port(struct sock *sk, unsigned short snum,
 			int (*scmp)(const struct sock *, const struct sock *));
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index b9f385d..cffa5dc 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -36,6 +36,7 @@
 #define XFRM_PROTO_ROUTING	IPPROTO_ROUTING
 #define XFRM_PROTO_DSTOPTS	IPPROTO_DSTOPTS
 
+#define XFRM_ALIGN4(len)	(((len) + 3) & ~3)
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
 #define MODULE_ALIAS_XFRM_MODE(family, encap) \
 	MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
@@ -185,9 +186,14 @@ struct xfrm_state {
 
 	/* State for replay detection */
 	struct xfrm_replay_state replay;
+	struct xfrm_replay_state_esn *replay_esn;
 
 	/* Replay detection state at the time we sent the last notification */
 	struct xfrm_replay_state preplay;
+	struct xfrm_replay_state_esn *preplay_esn;
+
+	/* The functions for replay detection. */
+	struct xfrm_replay	*repl;
 
 	/* internal flag that only holds state for delayed aevent at the
 	 * moment
@@ -258,6 +264,15 @@ struct km_event {
 	struct net *net;
 };
 
+struct xfrm_replay {
+	void	(*advance)(struct xfrm_state *x, __be32 net_seq);
+	int	(*check)(struct xfrm_state *x,
+			 struct sk_buff *skb,
+			 __be32 net_seq);
+	void	(*notify)(struct xfrm_state *x, int event);
+	int	(*overflow)(struct xfrm_state *x, struct sk_buff *skb);
+};
+
 struct net_device;
 struct xfrm_type;
 struct xfrm_dst;
@@ -266,25 +281,26 @@ struct xfrm_policy_afinfo {
 	struct dst_ops		*dst_ops;
 	void			(*garbage_collect)(struct net *net);
 	struct dst_entry	*(*dst_lookup)(struct net *net, int tos,
-					       xfrm_address_t *saddr,
-					       xfrm_address_t *daddr);
+					       const xfrm_address_t *saddr,
+					       const xfrm_address_t *daddr);
 	int			(*get_saddr)(struct net *net, xfrm_address_t *saddr, xfrm_address_t *daddr);
 	void			(*decode_session)(struct sk_buff *skb,
 						  struct flowi *fl,
 						  int reverse);
-	int			(*get_tos)(struct flowi *fl);
+	int			(*get_tos)(const struct flowi *fl);
 	int			(*init_path)(struct xfrm_dst *path,
 					     struct dst_entry *dst,
 					     int nfheader_len);
 	int			(*fill_dst)(struct xfrm_dst *xdst,
 					    struct net_device *dev,
-					    struct flowi *fl);
+					    const struct flowi *fl);
+	struct dst_entry	*(*blackhole_route)(struct net *net, struct dst_entry *orig);
 };
 
 extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
 extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
-extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
-extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
+extern void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c);
+extern void km_state_notify(struct xfrm_state *x, const struct km_event *c);
 
 struct xfrm_tmpl;
 extern int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
@@ -299,9 +315,12 @@ struct xfrm_state_afinfo {
 	const struct xfrm_type	*type_map[IPPROTO_MAX];
 	struct xfrm_mode	*mode_map[XFRM_MODE_MAX];
 	int			(*init_flags)(struct xfrm_state *x);
-	void			(*init_tempsel)(struct xfrm_selector *sel, struct flowi *fl);
-	void			(*init_temprop)(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
-						xfrm_address_t *daddr, xfrm_address_t *saddr);
+	void			(*init_tempsel)(struct xfrm_selector *sel,
+						const struct flowi *fl);
+	void			(*init_temprop)(struct xfrm_state *x,
+						const struct xfrm_tmpl *tmpl,
+						const xfrm_address_t *daddr,
+						const xfrm_address_t *saddr);
 	int			(*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
 	int			(*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
 	int			(*output)(struct sk_buff *skb);
@@ -332,7 +351,8 @@ struct xfrm_type {
 	void			(*destructor)(struct xfrm_state *);
 	int			(*input)(struct xfrm_state *, struct sk_buff *skb);
 	int			(*output)(struct xfrm_state *, struct sk_buff *pskb);
-	int			(*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);
+	int			(*reject)(struct xfrm_state *, struct sk_buff *,
+					  const struct flowi *);
 	int			(*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);
 	/* Estimate maximal size of result of transformation of a dgram */
 	u32			(*get_mtu)(struct xfrm_state *, int size);
@@ -501,7 +521,7 @@ struct xfrm_policy {
 	struct xfrm_tmpl       	xfrm_vec[XFRM_MAX_DEPTH];
 };
 
-static inline struct net *xp_net(struct xfrm_policy *xp)
+static inline struct net *xp_net(const struct xfrm_policy *xp)
 {
 	return read_pnet(&xp->xp_net);
 }
@@ -545,13 +565,17 @@ struct xfrm_migrate {
 struct xfrm_mgr {
 	struct list_head	list;
 	char			*id;
-	int			(*notify)(struct xfrm_state *x, struct km_event *c);
+	int			(*notify)(struct xfrm_state *x, const struct km_event *c);
 	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
 	struct xfrm_policy	*(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, __be16 sport);
-	int			(*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
+	int			(*notify_policy)(struct xfrm_policy *x, int dir, const struct km_event *c);
 	int			(*report)(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);
-	int			(*migrate)(struct xfrm_selector *sel, u8 dir, u8 type, struct xfrm_migrate *m, int num_bundles, struct xfrm_kmaddress *k);
+	int			(*migrate)(const struct xfrm_selector *sel,
+					   u8 dir, u8 type,
+					   const struct xfrm_migrate *m,
+					   int num_bundles,
+					   const struct xfrm_kmaddress *k);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -570,8 +594,14 @@ struct xfrm_skb_cb {
 
         /* Sequence number for replay protection. */
 	union {
-		u64 output;
-		__be32 input;
+		struct {
+			__u32 low;
+			__u32 hi;
+		} output;
+		struct {
+			__be32 low;
+			__be32 hi;
+		} input;
 	} seq;
 };
 
@@ -675,6 +705,8 @@ extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
 				    u32 auid, u32 ses, u32 secid);
 extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
 					     struct sk_buff *skb);
+extern void xfrm_audit_state_replay(struct xfrm_state *x,
+				    struct sk_buff *skb, __be32 net_seq);
 extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
 extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
 				      __be32 net_spi, __be32 net_seq);
@@ -707,6 +739,11 @@ static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
 {
 }
 
+static inline void xfrm_audit_state_replay(struct xfrm_state *x,
+					   struct sk_buff *skb, __be32 net_seq)
+{
+}
+
 static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
 				      u16 family)
 {
@@ -762,10 +799,11 @@ static inline void xfrm_state_hold(struct xfrm_state *x)
 	atomic_inc(&x->refcnt);
 }
 
-static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
+static inline bool addr_match(const void *token1, const void *token2,
+			      int prefixlen)
 {
-	__be32 *a1 = token1;
-	__be32 *a2 = token2;
+	const __be32 *a1 = token1;
+	const __be32 *a2 = token2;
 	int pdw;
 	int pbi;
 
@@ -774,7 +812,7 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
 
 	if (pdw)
 		if (memcmp(a1, a2, pdw << 2))
-			return 0;
+			return false;
 
 	if (pbi) {
 		__be32 mask;
@@ -782,32 +820,32 @@ static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
 		mask = htonl((0xffffffff) << (32 - pbi));
 
 		if ((a1[pdw] ^ a2[pdw]) & mask)
-			return 0;
+			return false;
 	}
 
-	return 1;
+	return true;
 }
 
 static __inline__
-__be16 xfrm_flowi_sport(struct flowi *fl)
+__be16 xfrm_flowi_sport(const struct flowi *fl, const union flowi_uli *uli)
 {
 	__be16 port;
-	switch(fl->proto) {
+	switch(fl->flowi_proto) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE:
 	case IPPROTO_SCTP:
-		port = fl->fl_ip_sport;
+		port = uli->ports.sport;
 		break;
 	case IPPROTO_ICMP:
 	case IPPROTO_ICMPV6:
-		port = htons(fl->fl_icmp_type);
+		port = htons(uli->icmpt.type);
 		break;
 	case IPPROTO_MH:
-		port = htons(fl->fl_mh_type);
+		port = htons(uli->mht.type);
 		break;
 	case IPPROTO_GRE:
-		port = htons(ntohl(fl->fl_gre_key) >> 16);
+		port = htons(ntohl(uli->gre_key) >> 16);
 		break;
 	default:
 		port = 0;	/*XXX*/
@@ -816,22 +854,22 @@ __be16 xfrm_flowi_sport(struct flowi *fl)
 }
 
 static __inline__
-__be16 xfrm_flowi_dport(struct flowi *fl)
+__be16 xfrm_flowi_dport(const struct flowi *fl, const union flowi_uli *uli)
 {
 	__be16 port;
-	switch(fl->proto) {
+	switch(fl->flowi_proto) {
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
 	case IPPROTO_UDPLITE:
 	case IPPROTO_SCTP:
-		port = fl->fl_ip_dport;
+		port = uli->ports.dport;
 		break;
 	case IPPROTO_ICMP:
 	case IPPROTO_ICMPV6:
-		port = htons(fl->fl_icmp_code);
+		port = htons(uli->icmpt.code);
 		break;
 	case IPPROTO_GRE:
-		port = htons(ntohl(fl->fl_gre_key) & 0xffff);
+		port = htons(ntohl(uli->gre_key) & 0xffff);
 		break;
 	default:
 		port = 0;	/*XXX*/
@@ -839,7 +877,8 @@ __be16 xfrm_flowi_dport(struct flowi *fl)
 	return port;
 }
 
-extern int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
+extern int xfrm_selector_match(const struct xfrm_selector *sel,
+			       const struct flowi *fl,
 			       unsigned short family);
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -947,7 +986,7 @@ secpath_reset(struct sk_buff *skb)
 }
 
 static inline int
-xfrm_addr_any(xfrm_address_t *addr, unsigned short family)
+xfrm_addr_any(const xfrm_address_t *addr, unsigned short family)
 {
 	switch (family) {
 	case AF_INET:
@@ -959,21 +998,21 @@ xfrm_addr_any(xfrm_address_t *addr, unsigned short family)
 }
 
 static inline int
-__xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+__xfrm4_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x)
 {
 	return	(tmpl->saddr.a4 &&
 		 tmpl->saddr.a4 != x->props.saddr.a4);
 }
 
 static inline int
-__xfrm6_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x)
+__xfrm6_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x)
 {
 	return	(!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) &&
 		 ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr));
 }
 
 static inline int
-xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short family)
+xfrm_state_addr_cmp(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x, unsigned short family)
 {
 	switch (family) {
 	case AF_INET:
@@ -1126,49 +1165,49 @@ static inline int xfrm6_policy_check_reverse(struct sock *sk, int dir,
 #endif
 
 static __inline__
-xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family)
+xfrm_address_t *xfrm_flowi_daddr(const struct flowi *fl, unsigned short family)
 {
 	switch (family){
 	case AF_INET:
-		return (xfrm_address_t *)&fl->fl4_dst;
+		return (xfrm_address_t *)&fl->u.ip4.daddr;
 	case AF_INET6:
-		return (xfrm_address_t *)&fl->fl6_dst;
+		return (xfrm_address_t *)&fl->u.ip6.daddr;
 	}
 	return NULL;
 }
 
 static __inline__
-xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family)
+xfrm_address_t *xfrm_flowi_saddr(const struct flowi *fl, unsigned short family)
 {
 	switch (family){
 	case AF_INET:
-		return (xfrm_address_t *)&fl->fl4_src;
+		return (xfrm_address_t *)&fl->u.ip4.saddr;
 	case AF_INET6:
-		return (xfrm_address_t *)&fl->fl6_src;
+		return (xfrm_address_t *)&fl->u.ip6.saddr;
 	}
 	return NULL;
 }
 
 static __inline__
-void xfrm_flowi_addr_get(struct flowi *fl,
+void xfrm_flowi_addr_get(const struct flowi *fl,
 			 xfrm_address_t *saddr, xfrm_address_t *daddr,
 			 unsigned short family)
 {
 	switch(family) {
 	case AF_INET:
-		memcpy(&saddr->a4, &fl->fl4_src, sizeof(saddr->a4));
-		memcpy(&daddr->a4, &fl->fl4_dst, sizeof(daddr->a4));
+		memcpy(&saddr->a4, &fl->u.ip4.saddr, sizeof(saddr->a4));
+		memcpy(&daddr->a4, &fl->u.ip4.daddr, sizeof(daddr->a4));
 		break;
 	case AF_INET6:
-		ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->fl6_src);
-		ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->fl6_dst);
+		ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->u.ip6.saddr);
+		ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->u.ip6.daddr);
 		break;
 	}
 }
 
 static __inline__ int
-__xfrm4_state_addr_check(struct xfrm_state *x,
-			 xfrm_address_t *daddr, xfrm_address_t *saddr)
+__xfrm4_state_addr_check(const struct xfrm_state *x,
+			 const xfrm_address_t *daddr, const xfrm_address_t *saddr)
 {
 	if (daddr->a4 == x->id.daddr.a4 &&
 	    (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4))
@@ -1177,8 +1216,8 @@ __xfrm4_state_addr_check(struct xfrm_state *x,
 }
 
 static __inline__ int
-__xfrm6_state_addr_check(struct xfrm_state *x,
-			 xfrm_address_t *daddr, xfrm_address_t *saddr)
+__xfrm6_state_addr_check(const struct xfrm_state *x,
+			 const xfrm_address_t *daddr, const xfrm_address_t *saddr)
 {
 	if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) &&
 	    (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)|| 
@@ -1189,8 +1228,8 @@ __xfrm6_state_addr_check(struct xfrm_state *x,
 }
 
 static __inline__ int
-xfrm_state_addr_check(struct xfrm_state *x,
-		      xfrm_address_t *daddr, xfrm_address_t *saddr,
+xfrm_state_addr_check(const struct xfrm_state *x,
+		      const xfrm_address_t *daddr, const xfrm_address_t *saddr,
 		      unsigned short family)
 {
 	switch (family) {
@@ -1203,23 +1242,23 @@ xfrm_state_addr_check(struct xfrm_state *x,
 }
 
 static __inline__ int
-xfrm_state_addr_flow_check(struct xfrm_state *x, struct flowi *fl,
+xfrm_state_addr_flow_check(const struct xfrm_state *x, const struct flowi *fl,
 			   unsigned short family)
 {
 	switch (family) {
 	case AF_INET:
 		return __xfrm4_state_addr_check(x,
-						(xfrm_address_t *)&fl->fl4_dst,
-						(xfrm_address_t *)&fl->fl4_src);
+						(const xfrm_address_t *)&fl->u.ip4.daddr,
+						(const xfrm_address_t *)&fl->u.ip4.saddr);
 	case AF_INET6:
 		return __xfrm6_state_addr_check(x,
-						(xfrm_address_t *)&fl->fl6_dst,
-						(xfrm_address_t *)&fl->fl6_src);
+						(const xfrm_address_t *)&fl->u.ip6.daddr,
+						(const xfrm_address_t *)&fl->u.ip6.saddr);
 	}
 	return 0;
 }
 
-static inline int xfrm_state_kern(struct xfrm_state *x)
+static inline int xfrm_state_kern(const struct xfrm_state *x)
 {
 	return atomic_read(&x->tunnel_users);
 }
@@ -1323,8 +1362,10 @@ extern int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk,
 			   int (*func)(struct xfrm_state *, int, void*), void *);
 extern void xfrm_state_walk_done(struct xfrm_state_walk *walk);
 extern struct xfrm_state *xfrm_state_alloc(struct net *net);
-extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, 
-					  struct flowi *fl, struct xfrm_tmpl *tmpl,
+extern struct xfrm_state *xfrm_state_find(const xfrm_address_t *daddr,
+					  const xfrm_address_t *saddr,
+					  const struct flowi *fl,
+					  struct xfrm_tmpl *tmpl,
 					  struct xfrm_policy *pol, int *err,
 					  unsigned short family);
 extern struct xfrm_state *xfrm_stateonly_find(struct net *net, u32 mark,
@@ -1337,11 +1378,11 @@ extern void xfrm_state_insert(struct xfrm_state *x);
 extern int xfrm_state_add(struct xfrm_state *x);
 extern int xfrm_state_update(struct xfrm_state *x);
 extern struct xfrm_state *xfrm_state_lookup(struct net *net, u32 mark,
-					    xfrm_address_t *daddr, __be32 spi,
+					    const xfrm_address_t *daddr, __be32 spi,
 					    u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_state_lookup_byaddr(struct net *net, u32 mark,
-						   xfrm_address_t *daddr,
-						   xfrm_address_t *saddr,
+						   const xfrm_address_t *daddr,
+						   const xfrm_address_t *saddr,
 						   u8 proto,
 						   unsigned short family);
 #ifdef CONFIG_XFRM_SUB_POLICY
@@ -1386,11 +1427,10 @@ extern int xfrm_state_delete(struct xfrm_state *x);
 extern int xfrm_state_flush(struct net *net, u8 proto, struct xfrm_audit *audit_info);
 extern void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
 extern void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
-extern int xfrm_replay_check(struct xfrm_state *x,
-			     struct sk_buff *skb, __be32 seq);
-extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
-extern void xfrm_replay_notify(struct xfrm_state *x, int event);
+extern u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq);
+extern int xfrm_init_replay(struct xfrm_state *x);
 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int __xfrm_init_state(struct xfrm_state *x, bool init_replay);
 extern int xfrm_init_state(struct xfrm_state *x);
 extern int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
@@ -1468,19 +1508,19 @@ u32 xfrm_get_acqseq(void);
 extern int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
 struct xfrm_state *xfrm_find_acq(struct net *net, struct xfrm_mark *mark,
 				 u8 mode, u32 reqid, u8 proto,
-				 xfrm_address_t *daddr,
-				 xfrm_address_t *saddr, int create,
+				 const xfrm_address_t *daddr,
+				 const xfrm_address_t *saddr, int create,
 				 unsigned short family);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 
 #ifdef CONFIG_XFRM_MIGRATE
-extern int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
-		      struct xfrm_migrate *m, int num_bundles,
-		      struct xfrm_kmaddress *k);
+extern int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+		      const struct xfrm_migrate *m, int num_bundles,
+		      const struct xfrm_kmaddress *k);
 extern struct xfrm_state * xfrm_migrate_state_find(struct xfrm_migrate *m);
 extern struct xfrm_state * xfrm_state_migrate(struct xfrm_state *x,
 					      struct xfrm_migrate *m);
-extern int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+extern int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
 			struct xfrm_migrate *m, int num_bundles,
 			struct xfrm_kmaddress *k);
 #endif
@@ -1500,10 +1540,10 @@ extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx);
 extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id);
 extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id);
 extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
-extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
-extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
-extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);
-extern struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len,
+extern struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe);
+extern struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len,
 						   int probe);
 
 struct hash_desc;
@@ -1511,7 +1551,8 @@ struct scatterlist;
 typedef int (icv_update_fn_t)(struct hash_desc *, struct scatterlist *,
 			      unsigned int);
 
-static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b,
+static inline int xfrm_addr_cmp(const xfrm_address_t *a,
+				const xfrm_address_t *b,
 				int family)
 {
 	switch (family) {
@@ -1544,16 +1585,21 @@ static inline int xfrm_aevent_is_on(struct net *net)
 }
 #endif
 
-static inline int xfrm_alg_len(struct xfrm_algo *alg)
+static inline int xfrm_alg_len(const struct xfrm_algo *alg)
 {
 	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
 }
 
-static inline int xfrm_alg_auth_len(struct xfrm_algo_auth *alg)
+static inline int xfrm_alg_auth_len(const struct xfrm_algo_auth *alg)
 {
 	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
 }
 
+static inline int xfrm_replay_state_esn_len(struct xfrm_replay_state_esn *replay_esn)
+{
+	return sizeof(*replay_esn) + replay_esn->bmp_len * sizeof(__u32);
+}
+
 #ifdef CONFIG_XFRM_MIGRATE
 static inline struct xfrm_algo *xfrm_algo_clone(struct xfrm_algo *orig)
 {
@@ -1597,7 +1643,7 @@ static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m)
 	return m->v & m->m;
 }
 
-static inline int xfrm_mark_put(struct sk_buff *skb, struct xfrm_mark *m)
+static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m)
 {
 	if (m->m | m->v)
 		NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m);
diff --git a/include/scsi/fc/fc_ns.h b/include/scsi/fc/fc_ns.h
index 185015d..f7751d5 100644
--- a/include/scsi/fc/fc_ns.h
+++ b/include/scsi/fc/fc_ns.h
@@ -41,6 +41,7 @@ enum fc_ns_req {
 	FC_NS_GI_A =	0x0101,		/* get identifiers - scope */
 	FC_NS_GPN_ID =	0x0112,		/* get port name by ID */
 	FC_NS_GNN_ID =	0x0113,		/* get node name by ID */
+	FC_NS_GSPN_ID = 0x0118,		/* get symbolic port name */
 	FC_NS_GID_PN =	0x0121,		/* get ID for port name */
 	FC_NS_GID_NN =	0x0131,		/* get IDs for node name */
 	FC_NS_GID_FT =	0x0171,		/* get IDs by FC4 type */
@@ -144,7 +145,7 @@ struct fc_ns_gid_pn {
 };
 
 /*
- * GID_PN response
+ * GID_PN response or GSPN_ID request
  */
 struct fc_gid_pn_resp {
 	__u8      fp_resvd;
@@ -152,6 +153,14 @@ struct fc_gid_pn_resp {
 };
 
 /*
+ * GSPN_ID response
+ */
+struct fc_gspn_resp {
+	__u8	fp_name_len;
+	char	fp_name[];
+};
+
+/*
  * RFT_ID request - register FC-4 types for ID.
  */
 struct fc_ns_rft_id {
diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h
index 6d293c8..be418d8 100644
--- a/include/scsi/fc_encode.h
+++ b/include/scsi/fc_encode.h
@@ -46,16 +46,11 @@ struct fc_ct_req {
 	} payload;
 };
 
-/**
- * fill FC header fields in specified fc_frame
- */
-static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
-				  u32 did, u32 sid, enum fc_fh_type type,
-				  u32 f_ctl, u32 parm_offset)
+static inline void __fc_fill_fc_hdr(struct fc_frame_header *fh,
+				    enum fc_rctl r_ctl,
+				    u32 did, u32 sid, enum fc_fh_type type,
+				    u32 f_ctl, u32 parm_offset)
 {
-	struct fc_frame_header *fh;
-
-	fh = fc_frame_header_get(fp);
 	WARN_ON(r_ctl == 0);
 	fh->fh_r_ctl = r_ctl;
 	hton24(fh->fh_d_id, did);
@@ -68,6 +63,19 @@ static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
 }
 
 /**
+ * fill FC header fields in specified fc_frame
+ */
+static inline void fc_fill_fc_hdr(struct fc_frame *fp, enum fc_rctl r_ctl,
+				  u32 did, u32 sid, enum fc_fh_type type,
+				  u32 f_ctl, u32 parm_offset)
+{
+	struct fc_frame_header *fh;
+
+	fh = fc_frame_header_get(fp);
+	__fc_fill_fc_hdr(fh, r_ctl, did, sid, type, f_ctl, parm_offset);
+}
+
+/**
  * fc_adisc_fill() - Fill in adisc request frame
  * @lport: local port.
  * @fp: fc frame where payload will be placed.
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index f53c8e3..24193c1 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -35,6 +35,8 @@
 
 #include <scsi/fc_frame.h>
 
+#define	FC_FC4_PROV_SIZE	(FC_TYPE_FCP + 1)	/* size of tables */
+
 /*
  * libfc error codes
  */
@@ -156,6 +158,7 @@ struct fc_rport_libfc_priv {
 	#define FC_RP_FLAGS_REC_SUPPORTED	(1 << 0)
 	#define FC_RP_FLAGS_RETRY		(1 << 1)
 	#define FC_RP_STARTED			(1 << 2)
+	#define FC_RP_FLAGS_CONF_REQ		(1 << 3)
 	unsigned int	           e_d_tov;
 	unsigned int	           r_a_tov;
 };
@@ -179,6 +182,7 @@ struct fc_rport_libfc_priv {
  * @rp_mutex:       The mutex that protects the remote port
  * @retry_work:     Handle for retries
  * @event_callback: Callback when READY, FAILED or LOGO states complete
+ * @prli_count:     Count of open PRLI sessions in providers
  * @rcu:	    Structure used for freeing in an RCU-safe manner
  */
 struct fc_rport_priv {
@@ -202,7 +206,13 @@ struct fc_rport_priv {
 	struct list_head            peers;
 	struct work_struct          event_work;
 	u32			    supported_classes;
+	u16                         prli_count;
 	struct rcu_head		    rcu;
+	u16			    sp_features;
+	u8			    spp_type;
+	void			    (*lld_event_callback)(struct fc_lport *,
+						      struct fc_rport_priv *,
+						      enum fc_rport_event);
 };
 
 /**
@@ -551,6 +561,16 @@ struct libfc_function_template {
 	struct fc_seq *(*seq_start_next)(struct fc_seq *);
 
 	/*
+	 * Set a response handler for the exchange of the sequence.
+	 *
+	 * STATUS: OPTIONAL
+	 */
+	void (*seq_set_resp)(struct fc_seq *sp,
+			     void (*resp)(struct fc_seq *, struct fc_frame *,
+					  void *),
+			     void *arg);
+
+	/*
 	 * Assign a sequence for an incoming request frame.
 	 *
 	 * STATUS: OPTIONAL
@@ -558,6 +578,13 @@ struct libfc_function_template {
 	struct fc_seq *(*seq_assign)(struct fc_lport *, struct fc_frame *);
 
 	/*
+	 * Release the reference on the sequence returned by seq_assign().
+	 *
+	 * STATUS: OPTIONAL
+	 */
+	void (*seq_release)(struct fc_seq *);
+
+	/*
 	 * Reset an exchange manager, completing all sequences and exchanges.
 	 * If s_id is non-zero, reset only exchanges originating from that FID.
 	 * If d_id is non-zero, reset only exchanges sending to that FID.
@@ -656,6 +683,15 @@ struct libfc_function_template {
 	void (*rport_destroy)(struct kref *);
 
 	/*
+	 * Callback routine after the remote port is logged in
+	 *
+	 * STATUS: OPTIONAL
+	 */
+	void (*rport_event_callback)(struct fc_lport *,
+				     struct fc_rport_priv *,
+				     enum fc_rport_event);
+
+	/*
 	 * Send a fcp cmd from fsp pkt.
 	 * Called with the SCSI host lock unlocked and irqs disabled.
 	 *
@@ -749,6 +785,15 @@ struct fc_disc {
 			      enum fc_disc_event);
 };
 
+/*
+ * Local port notifier and events.
+ */
+extern struct blocking_notifier_head fc_lport_notifier_head;
+enum fc_lport_event {
+	FC_LPORT_EV_ADD,
+	FC_LPORT_EV_DEL,
+};
+
 /**
  * struct fc_lport - Local port
  * @host:                  The SCSI host associated with a local port
@@ -789,8 +834,10 @@ struct fc_disc {
  * @lso_max:               The maximum large offload send size
  * @fcts:                  FC-4 type mask
  * @lp_mutex:              Mutex to protect the local port
- * @list:                  Handle for list of local ports
+ * @list:                  Linkage on list of vport peers
  * @retry_work:            Handle to local port for delayed retry context
+ * @prov:		   Pointers available for use by passive FC-4 providers
+ * @lport_list:            Linkage on module-wide list of local ports
  */
 struct fc_lport {
 	/* Associations */
@@ -846,8 +893,32 @@ struct fc_lport {
 	struct mutex                   lp_mutex;
 	struct list_head               list;
 	struct delayed_work	       retry_work;
+	void			       *prov[FC_FC4_PROV_SIZE];
+	struct list_head               lport_list;
 };
 
+/**
+ * struct fc4_prov - FC-4 provider registration
+ * @prli:               Handler for incoming PRLI
+ * @prlo:               Handler for session reset
+ * @recv:		Handler for incoming request
+ * @module:		Pointer to module.  May be NULL.
+ */
+struct fc4_prov {
+	int (*prli)(struct fc_rport_priv *, u32 spp_len,
+		    const struct fc_els_spp *spp_in,
+		    struct fc_els_spp *spp_out);
+	void (*prlo)(struct fc_rport_priv *);
+	void (*recv)(struct fc_lport *, struct fc_frame *);
+	struct module *module;
+};
+
+/*
+ * Register FC-4 provider with libfc.
+ */
+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *);
+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *);
+
 /*
  * FC_LPORT HELPER FUNCTIONS
  *****************************/
@@ -978,6 +1049,7 @@ struct fc_lport *libfc_vport_create(struct fc_vport *, int privsize);
 struct fc_lport *fc_vport_id_lookup(struct fc_lport *, u32 port_id);
 int fc_lport_bsg_request(struct fc_bsg_job *);
 void fc_lport_set_local_id(struct fc_lport *, u32 port_id);
+void fc_lport_iterate(void (*func)(struct fc_lport *, void *), void *);
 
 /*
  * REMOTE PORT LAYER
diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h
index feb6a94..8c1638b 100644
--- a/include/scsi/libfcoe.h
+++ b/include/scsi/libfcoe.h
@@ -33,6 +33,12 @@
 #define FCOE_MAX_CMD_LEN	16	/* Supported CDB length */
 
 /*
+ * Max MTU for FCoE: 14 (FCoE header) + 24 (FC header) + 2112 (max FC payload)
+ * + 4 (FC CRC) + 4 (FCoE trailer) =  2158 bytes
+ */
+#define FCOE_MTU	2158
+
+/*
  * FIP tunable parameters.
  */
 #define FCOE_CTLR_START_DELAY	2000	/* mS after first adv. to choose FCF */
@@ -221,6 +227,8 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *, struct fc_lport *,
 u64 fcoe_wwn_from_mac(unsigned char mac[], unsigned int, unsigned int);
 int fcoe_libfc_config(struct fc_lport *, struct fcoe_ctlr *,
 		      const struct libfc_function_template *, int init_fcp);
+u32 fcoe_fc_crc(struct fc_frame *fp);
+int fcoe_start_io(struct sk_buff *skb);
 
 /**
  * is_fip_mode() - returns true if FIP mode selected.
@@ -231,5 +239,102 @@ static inline bool is_fip_mode(struct fcoe_ctlr *fip)
 	return fip->state == FIP_ST_ENABLED;
 }
 
+/* helper for FCoE SW HBA drivers, can include subven and subdev if needed. The
+ * modpost would use pci_device_id table to auto-generate formatted module alias
+ * into the corresponding .mod.c file, but there may or may not be a pci device
+ * id table for FCoE drivers so we use the following helper for build the fcoe
+ * driver module alias.
+ */
+#define MODULE_ALIAS_FCOE_PCI(ven, dev) \
+	MODULE_ALIAS("fcoe-pci:"	\
+		"v" __stringify(ven)	\
+		"d" __stringify(dev) "sv*sd*bc*sc*i*")
+
+/* the name of the default FCoE transport driver fcoe.ko */
+#define FCOE_TRANSPORT_DEFAULT	"fcoe"
+
+/* struct fcoe_transport - The FCoE transport interface
+ * @name:	a vendor specific name for their FCoE transport driver
+ * @attached:	whether this transport is already attached
+ * @list:	list linkage to all attached transports
+ * @match:	handler to allow the transport driver to match up a given netdev
+ * @create:	handler to sysfs entry of create for FCoE instances
+ * @destroy:	handler to sysfs entry of destroy for FCoE instances
+ * @enable:	handler to sysfs entry of enable for FCoE instances
+ * @disable:	handler to sysfs entry of disable for FCoE instances
+ */
+struct fcoe_transport {
+	char name[IFNAMSIZ];
+	bool attached;
+	struct list_head list;
+	bool (*match) (struct net_device *device);
+	int (*create) (struct net_device *device, enum fip_state fip_mode);
+	int (*destroy) (struct net_device *device);
+	int (*enable) (struct net_device *device);
+	int (*disable) (struct net_device *device);
+};
+
+/**
+ * struct fcoe_percpu_s - The context for FCoE receive thread(s)
+ * @thread:	    The thread context
+ * @fcoe_rx_list:   The queue of pending packets to process
+ * @page:	    The memory page for calculating frame trailer CRCs
+ * @crc_eof_offset: The offset into the CRC page pointing to available
+ *		    memory for a new trailer
+ */
+struct fcoe_percpu_s {
+	struct task_struct *thread;
+	struct sk_buff_head fcoe_rx_list;
+	struct page *crc_eof_page;
+	int crc_eof_offset;
+};
+
+/**
+ * struct fcoe_port - The FCoE private structure
+ * @priv:		       The associated fcoe interface. The structure is
+ *			       defined by the low level driver
+ * @lport:		       The associated local port
+ * @fcoe_pending_queue:	       The pending Rx queue of skbs
+ * @fcoe_pending_queue_active: Indicates if the pending queue is active
+ * @max_queue_depth:	       Max queue depth of pending queue
+ * @min_queue_depth:	       Min queue depth of pending queue
+ * @timer:		       The queue timer
+ * @destroy_work:	       Handle for work context
+ *			       (to prevent RTNL deadlocks)
+ * @data_srt_addr:	       Source address for data
+ *
+ * An instance of this structure is to be allocated along with the
+ * Scsi_Host and libfc fc_lport structures.
+ */
+struct fcoe_port {
+	void		      *priv;
+	struct fc_lport	      *lport;
+	struct sk_buff_head   fcoe_pending_queue;
+	u8		      fcoe_pending_queue_active;
+	u32		      max_queue_depth;
+	u32		      min_queue_depth;
+	struct timer_list     timer;
+	struct work_struct    destroy_work;
+	u8		      data_src_addr[ETH_ALEN];
+};
+void fcoe_clean_pending_queue(struct fc_lport *);
+void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb);
+void fcoe_queue_timer(ulong lport);
+int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
+			   struct fcoe_percpu_s *fps);
+
+/**
+ * struct netdev_list
+ * A mapping from netdevice to fcoe_transport
+ */
+struct fcoe_netdev_mapping {
+	struct list_head list;
+	struct net_device *netdev;
+	struct fcoe_transport *ft;
+};
+
+/* fcoe transports registration and deregistration */
+int fcoe_transport_attach(struct fcoe_transport *ft);
+int fcoe_transport_detach(struct fcoe_transport *ft);
 
 #endif /* _LIBFCOE_H */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 748382b..0f43677 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -212,9 +212,6 @@ struct iscsi_conn {
 	/* values userspace uses to id a conn */
 	int			persistent_port;
 	char			*persistent_address;
-	/* remote portal currently connected to */
-	int			portal_port;
-	char			portal_address[ISCSI_ADDRESS_BUF_LEN];
 
 	/* MIB-statistics */
 	uint64_t		txdata_octets;
@@ -319,9 +316,6 @@ struct iscsi_host {
 	/* hw address or netdev iscsi connection is bound to */
 	char			*hwaddress;
 	char			*netdev;
-	/* local address */
-	int			local_port;
-	char			local_address[ISCSI_ADDRESS_BUF_LEN];
 
 	wait_queue_head_t	session_removal_wq;
 	/* protects sessions and state */
@@ -394,6 +388,8 @@ extern void iscsi_session_failure(struct iscsi_session *session,
 				  enum iscsi_err err);
 extern int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
 				enum iscsi_param param, char *buf);
+extern int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
+				     enum iscsi_param param, char *buf);
 extern void iscsi_suspend_tx(struct iscsi_conn *conn);
 extern void iscsi_suspend_queue(struct iscsi_conn *conn);
 extern void iscsi_conn_queue_work(struct iscsi_conn *conn);
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index c583193..9c159f7 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -39,6 +39,11 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev,
 			       struct scsi_target *starget);
 
 void sas_ata_task_abort(struct sas_task *task);
+void sas_ata_strategy_handler(struct Scsi_Host *shost);
+int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
+		      enum blk_eh_timer_return *rtn);
+int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
+	       struct list_head *done_q);
 
 #else
 
@@ -55,6 +60,23 @@ static inline int sas_ata_init_host_and_port(struct domain_device *found_dev,
 static inline void sas_ata_task_abort(struct sas_task *task)
 {
 }
+
+static inline void sas_ata_strategy_handler(struct Scsi_Host *shost)
+{
+}
+
+static inline int sas_ata_timed_out(struct scsi_cmnd *cmd,
+				    struct sas_task *task,
+				    enum blk_eh_timer_return *rtn)
+{
+	return 0;
+}
+static inline int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
+			     struct list_head *done_q)
+{
+	return 0;
+}
+
 #endif
 
 #endif /* _SAS_ATA_H_ */
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index b76d400..3668903 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -435,6 +435,10 @@ static inline int scsi_is_wlun(unsigned int lun)
 				      * recover the link. Transport class will
 				      * retry or fail IO */
 #define DID_TRANSPORT_FAILFAST	0x0f /* Transport class fastfailed the io */
+#define DID_TARGET_FAILURE 0x10 /* Permanent target failure, do not retry on
+				 * other paths */
+#define DID_NEXUS_FAILURE 0x11  /* Permanent nexus failure, retry on other
+				 * paths might yield different results */
 #define DRIVER_OK       0x00	/* Driver status                           */
 
 /*
@@ -464,6 +468,7 @@ static inline int scsi_is_wlun(unsigned int lun)
 #define TIMEOUT_ERROR   0x2007
 #define SCSI_RETURN_NOT_HANDLED   0x2008
 #define FAST_IO_FAIL	0x2009
+#define TARGET_ERROR    0x200A
 
 /*
  * Midlevel queue return values.
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 85867dc..f171c65 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -184,6 +184,7 @@ typedef void (*activate_complete)(void *, int);
 struct scsi_device_handler {
 	/* Used by the infrastructure */
 	struct list_head list; /* list of scsi_device_handlers */
+	int idx;
 
 	/* Filled by the hardware handler */
 	struct module *module;
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 7fff94b..bf8f529 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -101,6 +101,8 @@ struct iscsi_transport {
 	void (*destroy_conn) (struct iscsi_cls_conn *conn);
 	int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
 			  char *buf, int buflen);
+	int (*get_ep_param) (struct iscsi_endpoint *ep, enum iscsi_param param,
+			     char *buf);
 	int (*get_conn_param) (struct iscsi_cls_conn *conn,
 			       enum iscsi_param param, char *buf);
 	int (*get_session_param) (struct iscsi_cls_session *session,
@@ -160,8 +162,9 @@ struct iscsi_cls_conn {
 	void *dd_data;			/* LLD private data */
 	struct iscsi_transport *transport;
 	uint32_t cid;			/* connection id */
+	struct mutex ep_mutex;
+	struct iscsi_endpoint *ep;
 
-	int active;			/* must be accessed with the connlock */
 	struct device dev;		/* sysfs transport/container device */
 };
 
@@ -222,6 +225,7 @@ struct iscsi_endpoint {
 	void *dd_data;			/* LLD private data */
 	struct device dev;
 	uint64_t id;
+	struct iscsi_cls_conn *conn;
 };
 
 /*
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index b602f47..f1dcefe4 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -96,6 +96,10 @@
 #define AC97_FUNC_INFO		0x68	/* Function Information */
 #define AC97_SENSE_INFO		0x6a	/* Sense Details */
 
+/* volume controls */
+#define AC97_MUTE_MASK_MONO	0x8000
+#define AC97_MUTE_MASK_STEREO	0x8080
+
 /* slot allocation */
 #define AC97_SLOT_TAG		0
 #define AC97_SLOT_CMD_ADDR	1
@@ -138,6 +142,7 @@
 #define AC97_BC_18BIT_ADC	0x0100	/* 18-bit ADC resolution */
 #define AC97_BC_20BIT_ADC	0x0200	/* 20-bit ADC resolution */
 #define AC97_BC_ADC_MASK	0x0300
+#define AC97_BC_3D_TECH_ID_MASK	0x7c00	/* Per-vendor ID of 3D enhancement */
 
 /* general purpose */
 #define AC97_GP_DRSS_MASK	0x0c00	/* double rate slot select */
diff --git a/include/sound/control.h b/include/sound/control.h
index 7715e6f..e67db28 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -115,6 +115,8 @@ int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
 int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol);
 int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id);
 int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id);
+int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
+			int active);
 struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid);
 struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id);
 
diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h
new file mode 100644
index 0000000..50a059e
--- /dev/null
+++ b/include/sound/cs4271.h
@@ -0,0 +1,24 @@
+/*
+ * Definitions for CS4271 ASoC codec driver
+ *
+ * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 __CS4271_H
+#define __CS4271_H
+
+struct cs4271_platform_data {
+	int gpio_nreset;	/* GPIO driving Reset pin, if any */
+};
+
+#endif /* __CS4271_H */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
index 81990b2..1774ff5 100644
--- a/include/sound/hdspm.h
+++ b/include/sound/hdspm.h
@@ -3,8 +3,8 @@
 /*
  *   Copyright (C) 2003 Winfried Ritsch (IEM)
  *   based on hdsp.h from Thomas Charbonnel (thomas@undata.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
@@ -23,50 +23,41 @@
 /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
 #define HDSPM_MAX_CHANNELS      64
 
-/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-
-/* peam rms level structure like we get from hardware 
-  
-   maybe in future we can memory map it so I just copy it
-   to user on ioctl call now an dont change anything
-   rms are made out of low and high values
-   where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24)
-   (i asume so from the code)
-*/
-
-struct hdspm_peak_rms {
-
-	unsigned int level_offset[1024];
+enum hdspm_io_type {
+	MADI,
+	MADIface,
+	AIO,
+	AES32,
+	RayDAT
+};
 
-	unsigned int input_peak[64];
-	unsigned int playback_peak[64];
-	unsigned int output_peak[64];
-	unsigned int xxx_peak[64];	/* not used */
+enum hdspm_speed {
+	ss,
+	ds,
+	qs
+};
 
-	unsigned int reserved[256];	/* not used */
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
 
-	unsigned int input_rms_l[64];
-	unsigned int playback_rms_l[64];
-	unsigned int output_rms_l[64];
-	unsigned int xxx_rms_l[64];	/* not used */
+struct hdspm_peak_rms {
+	uint32_t input_peaks[64];
+	uint32_t playback_peaks[64];
+	uint32_t output_peaks[64];
 
-	unsigned int input_rms_h[64];
-	unsigned int playback_rms_h[64];
-	unsigned int output_rms_h[64];
-	unsigned int xxx_rms_h[64];	/* not used */
-};
+	uint64_t input_rms[64];
+	uint64_t playback_rms[64];
+	uint64_t output_rms[64];
 
-struct hdspm_peak_rms_ioctl {
-	struct hdspm_peak_rms *peak;
+	uint8_t speed; /* enum {ss, ds, qs} */
+	int status2;
 };
 
-/* use indirect access due to the limit of ioctl bit size */
 #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
-	_IOR('H', 0x40, struct hdspm_peak_rms_ioctl)
+	_IOR('H', 0x42, struct hdspm_peak_rms)
 
 /* ------------ CONFIG block IOCTL ---------------------- */
 
-struct hdspm_config_info {
+struct hdspm_config {
 	unsigned char pref_sync_ref;
 	unsigned char wordclock_sync_check;
 	unsigned char madi_sync_check;
@@ -80,18 +71,121 @@ struct hdspm_config_info {
 	unsigned int analog_out;
 };
 
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO \
-	_IOR('H', 0x41, struct hdspm_config_info)
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
+	_IOR('H', 0x41, struct hdspm_config)
+
+/**
+ * If there's a TCO (TimeCode Option) board installed,
+ * there are further options and status data available.
+ * The hdspm_ltc structure contains the current SMPTE
+ * timecode and some status information and can be
+ * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
+ * hdspm_status struct.
+ **/
+
+enum hdspm_ltc_format {
+	format_invalid,
+	fps_24,
+	fps_25,
+	fps_2997,
+	fps_30
+};
+
+enum hdspm_ltc_frame {
+	frame_invalid,
+	drop_frame,
+	full_frame
+};
+
+enum hdspm_ltc_input_format {
+	ntsc,
+	pal,
+	no_video
+};
+
+struct hdspm_ltc {
+	unsigned int ltc;
 
+	enum hdspm_ltc_format format;
+	enum hdspm_ltc_frame frame;
+	enum hdspm_ltc_input_format input_format;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
+
+/**
+ * The status data reflects the device's current state
+ * as determined by the card's configuration and
+ * connection status.
+ **/
+
+enum hdspm_sync {
+	hdspm_sync_no_lock = 0,
+	hdspm_sync_lock = 1,
+	hdspm_sync_sync = 2
+};
 
-/* get Soundcard Version */
+enum hdspm_madi_input {
+	hdspm_input_optical = 0,
+	hdspm_input_coax = 1
+};
+
+enum hdspm_madi_channel_format {
+	hdspm_format_ch_64 = 0,
+	hdspm_format_ch_56 = 1
+};
+
+enum hdspm_madi_frame_format {
+	hdspm_frame_48 = 0,
+	hdspm_frame_96 = 1
+};
+
+enum hdspm_syncsource {
+	syncsource_wc = 0,
+	syncsource_madi = 1,
+	syncsource_tco = 2,
+	syncsource_sync = 3,
+	syncsource_none = 4
+};
+
+struct hdspm_status {
+	uint8_t card_type; /* enum hdspm_io_type */
+	enum hdspm_syncsource autosync_source;
+
+	uint64_t card_clock;
+	uint32_t master_period;
+
+	union {
+		struct {
+			uint8_t sync_wc; /* enum hdspm_sync */
+			uint8_t sync_madi; /* enum hdspm_sync */
+			uint8_t sync_tco; /* enum hdspm_sync */
+			uint8_t sync_in; /* enum hdspm_sync */
+			uint8_t madi_input; /* enum hdspm_madi_input */
+			uint8_t channel_format; /* enum hdspm_madi_channel_format */
+			uint8_t frame_format; /* enum hdspm_madi_frame_format */
+		} madi;
+	} card_specific;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_STATUS \
+	_IOR('H', 0x47, struct hdspm_status)
+
+/**
+ * Get information about the card and its add-ons.
+ **/
+
+#define HDSPM_ADDON_TCO 1
 
 struct hdspm_version {
+	uint8_t card_type; /* enum hdspm_io_type */
+	char cardname[20];
+	unsigned int serial;
 	unsigned short firmware_rev;
+	int addons;
 };
 
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdspm_version)
-
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
 
 /* ------------- get Matrix Mixer IOCTL --------------- */
 
@@ -103,7 +197,7 @@ struct hdspm_version {
 /* equivalent to hardware definition, maybe for future feature of mmap of
  * them
  */
-/* each of 64 outputs has 64 infader and 64 outfader: 
+/* each of 64 outputs has 64 infader and 64 outfader:
    Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
 
 #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
@@ -131,4 +225,5 @@ typedef struct hdspm_version hdspm_version_t;
 typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
 typedef struct hdspm_mixer hdspm_mixer_t;
 
-#endif				/* __SOUND_HDSPM_H */
+
+#endif
diff --git a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
index 51fbcb4..13cb0b4 100644
--- a/include/sound/mixer_oss.h
+++ b/include/sound/mixer_oss.h
@@ -73,6 +73,9 @@ struct snd_mixer_oss_file {
 	struct snd_mixer_oss *mixer;
 };
 
+int snd_mixer_oss_ioctl_card(struct snd_card *card,
+			     unsigned int cmd, unsigned long arg);
+
 #endif /* CONFIG_SND_MIXER_OSS */
 
 #endif /* __SOUND_MIXER_OSS_H */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index e731f8d..430a9cc 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -136,48 +136,49 @@ struct snd_pcm_ops {
 					 SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
 #define SNDRV_PCM_RATE_8000_192000	(SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\
 					 SNDRV_PCM_RATE_192000)
-#define SNDRV_PCM_FMTBIT_S8		(1ULL << SNDRV_PCM_FORMAT_S8)
-#define SNDRV_PCM_FMTBIT_U8		(1ULL << SNDRV_PCM_FORMAT_U8)
-#define SNDRV_PCM_FMTBIT_S16_LE		(1ULL << SNDRV_PCM_FORMAT_S16_LE)
-#define SNDRV_PCM_FMTBIT_S16_BE		(1ULL << SNDRV_PCM_FORMAT_S16_BE)
-#define SNDRV_PCM_FMTBIT_U16_LE		(1ULL << SNDRV_PCM_FORMAT_U16_LE)
-#define SNDRV_PCM_FMTBIT_U16_BE		(1ULL << SNDRV_PCM_FORMAT_U16_BE)
-#define SNDRV_PCM_FMTBIT_S24_LE		(1ULL << SNDRV_PCM_FORMAT_S24_LE)
-#define SNDRV_PCM_FMTBIT_S24_BE		(1ULL << SNDRV_PCM_FORMAT_S24_BE)
-#define SNDRV_PCM_FMTBIT_U24_LE		(1ULL << SNDRV_PCM_FORMAT_U24_LE)
-#define SNDRV_PCM_FMTBIT_U24_BE		(1ULL << SNDRV_PCM_FORMAT_U24_BE)
-#define SNDRV_PCM_FMTBIT_S32_LE		(1ULL << SNDRV_PCM_FORMAT_S32_LE)
-#define SNDRV_PCM_FMTBIT_S32_BE		(1ULL << SNDRV_PCM_FORMAT_S32_BE)
-#define SNDRV_PCM_FMTBIT_U32_LE		(1ULL << SNDRV_PCM_FORMAT_U32_LE)
-#define SNDRV_PCM_FMTBIT_U32_BE		(1ULL << SNDRV_PCM_FORMAT_U32_BE)
-#define SNDRV_PCM_FMTBIT_FLOAT_LE	(1ULL << SNDRV_PCM_FORMAT_FLOAT_LE)
-#define SNDRV_PCM_FMTBIT_FLOAT_BE	(1ULL << SNDRV_PCM_FORMAT_FLOAT_BE)
-#define SNDRV_PCM_FMTBIT_FLOAT64_LE	(1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE)
-#define SNDRV_PCM_FMTBIT_FLOAT64_BE	(1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE)
-#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
-#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE)
-#define SNDRV_PCM_FMTBIT_MU_LAW		(1ULL << SNDRV_PCM_FORMAT_MU_LAW)
-#define SNDRV_PCM_FMTBIT_A_LAW		(1ULL << SNDRV_PCM_FORMAT_A_LAW)
-#define SNDRV_PCM_FMTBIT_IMA_ADPCM	(1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM)
-#define SNDRV_PCM_FMTBIT_MPEG		(1ULL << SNDRV_PCM_FORMAT_MPEG)
-#define SNDRV_PCM_FMTBIT_GSM		(1ULL << SNDRV_PCM_FORMAT_GSM)
-#define SNDRV_PCM_FMTBIT_SPECIAL	(1ULL << SNDRV_PCM_FORMAT_SPECIAL)
-#define SNDRV_PCM_FMTBIT_S24_3LE	(1ULL << SNDRV_PCM_FORMAT_S24_3LE)
-#define SNDRV_PCM_FMTBIT_U24_3LE	(1ULL << SNDRV_PCM_FORMAT_U24_3LE)
-#define SNDRV_PCM_FMTBIT_S24_3BE	(1ULL << SNDRV_PCM_FORMAT_S24_3BE)
-#define SNDRV_PCM_FMTBIT_U24_3BE	(1ULL << SNDRV_PCM_FORMAT_U24_3BE)
-#define SNDRV_PCM_FMTBIT_S20_3LE	(1ULL << SNDRV_PCM_FORMAT_S20_3LE)
-#define SNDRV_PCM_FMTBIT_U20_3LE	(1ULL << SNDRV_PCM_FORMAT_U20_3LE)
-#define SNDRV_PCM_FMTBIT_S20_3BE	(1ULL << SNDRV_PCM_FORMAT_S20_3BE)
-#define SNDRV_PCM_FMTBIT_U20_3BE	(1ULL << SNDRV_PCM_FORMAT_U20_3BE)
-#define SNDRV_PCM_FMTBIT_S18_3LE	(1ULL << SNDRV_PCM_FORMAT_S18_3LE)
-#define SNDRV_PCM_FMTBIT_U18_3LE	(1ULL << SNDRV_PCM_FORMAT_U18_3LE)
-#define SNDRV_PCM_FMTBIT_S18_3BE	(1ULL << SNDRV_PCM_FORMAT_S18_3BE)
-#define SNDRV_PCM_FMTBIT_U18_3BE	(1ULL << SNDRV_PCM_FORMAT_U18_3BE)
-#define SNDRV_PCM_FMTBIT_G723_24	(1ULL << SNDRV_PCM_FORMAT_G723_24)
-#define SNDRV_PCM_FMTBIT_G723_24_1B	(1ULL << SNDRV_PCM_FORMAT_G723_24_1B)
-#define SNDRV_PCM_FMTBIT_G723_40	(1ULL << SNDRV_PCM_FORMAT_G723_40)
-#define SNDRV_PCM_FMTBIT_G723_40_1B	(1ULL << SNDRV_PCM_FORMAT_G723_40_1B)
+#define _SNDRV_PCM_FMTBIT(fmt)		(1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt)
+#define SNDRV_PCM_FMTBIT_S8		_SNDRV_PCM_FMTBIT(S8)
+#define SNDRV_PCM_FMTBIT_U8		_SNDRV_PCM_FMTBIT(U8)
+#define SNDRV_PCM_FMTBIT_S16_LE		_SNDRV_PCM_FMTBIT(S16_LE)
+#define SNDRV_PCM_FMTBIT_S16_BE		_SNDRV_PCM_FMTBIT(S16_BE)
+#define SNDRV_PCM_FMTBIT_U16_LE		_SNDRV_PCM_FMTBIT(U16_LE)
+#define SNDRV_PCM_FMTBIT_U16_BE		_SNDRV_PCM_FMTBIT(U16_BE)
+#define SNDRV_PCM_FMTBIT_S24_LE		_SNDRV_PCM_FMTBIT(S24_LE)
+#define SNDRV_PCM_FMTBIT_S24_BE		_SNDRV_PCM_FMTBIT(S24_BE)
+#define SNDRV_PCM_FMTBIT_U24_LE		_SNDRV_PCM_FMTBIT(U24_LE)
+#define SNDRV_PCM_FMTBIT_U24_BE		_SNDRV_PCM_FMTBIT(U24_BE)
+#define SNDRV_PCM_FMTBIT_S32_LE		_SNDRV_PCM_FMTBIT(S32_LE)
+#define SNDRV_PCM_FMTBIT_S32_BE		_SNDRV_PCM_FMTBIT(S32_BE)
+#define SNDRV_PCM_FMTBIT_U32_LE		_SNDRV_PCM_FMTBIT(U32_LE)
+#define SNDRV_PCM_FMTBIT_U32_BE		_SNDRV_PCM_FMTBIT(U32_BE)
+#define SNDRV_PCM_FMTBIT_FLOAT_LE	_SNDRV_PCM_FMTBIT(FLOAT_LE)
+#define SNDRV_PCM_FMTBIT_FLOAT_BE	_SNDRV_PCM_FMTBIT(FLOAT_BE)
+#define SNDRV_PCM_FMTBIT_FLOAT64_LE	_SNDRV_PCM_FMTBIT(FLOAT64_LE)
+#define SNDRV_PCM_FMTBIT_FLOAT64_BE	_SNDRV_PCM_FMTBIT(FLOAT64_BE)
+#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_LE)
+#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_BE)
+#define SNDRV_PCM_FMTBIT_MU_LAW		_SNDRV_PCM_FMTBIT(MU_LAW)
+#define SNDRV_PCM_FMTBIT_A_LAW		_SNDRV_PCM_FMTBIT(A_LAW)
+#define SNDRV_PCM_FMTBIT_IMA_ADPCM	_SNDRV_PCM_FMTBIT(IMA_ADPCM)
+#define SNDRV_PCM_FMTBIT_MPEG		_SNDRV_PCM_FMTBIT(MPEG)
+#define SNDRV_PCM_FMTBIT_GSM		_SNDRV_PCM_FMTBIT(GSM)
+#define SNDRV_PCM_FMTBIT_SPECIAL	_SNDRV_PCM_FMTBIT(SPECIAL)
+#define SNDRV_PCM_FMTBIT_S24_3LE	_SNDRV_PCM_FMTBIT(S24_3LE)
+#define SNDRV_PCM_FMTBIT_U24_3LE	_SNDRV_PCM_FMTBIT(U24_3LE)
+#define SNDRV_PCM_FMTBIT_S24_3BE	_SNDRV_PCM_FMTBIT(S24_3BE)
+#define SNDRV_PCM_FMTBIT_U24_3BE	_SNDRV_PCM_FMTBIT(U24_3BE)
+#define SNDRV_PCM_FMTBIT_S20_3LE	_SNDRV_PCM_FMTBIT(S20_3LE)
+#define SNDRV_PCM_FMTBIT_U20_3LE	_SNDRV_PCM_FMTBIT(U20_3LE)
+#define SNDRV_PCM_FMTBIT_S20_3BE	_SNDRV_PCM_FMTBIT(S20_3BE)
+#define SNDRV_PCM_FMTBIT_U20_3BE	_SNDRV_PCM_FMTBIT(U20_3BE)
+#define SNDRV_PCM_FMTBIT_S18_3LE	_SNDRV_PCM_FMTBIT(S18_3LE)
+#define SNDRV_PCM_FMTBIT_U18_3LE	_SNDRV_PCM_FMTBIT(U18_3LE)
+#define SNDRV_PCM_FMTBIT_S18_3BE	_SNDRV_PCM_FMTBIT(S18_3BE)
+#define SNDRV_PCM_FMTBIT_U18_3BE	_SNDRV_PCM_FMTBIT(U18_3BE)
+#define SNDRV_PCM_FMTBIT_G723_24	_SNDRV_PCM_FMTBIT(G723_24)
+#define SNDRV_PCM_FMTBIT_G723_24_1B	_SNDRV_PCM_FMTBIT(G723_24_1B)
+#define SNDRV_PCM_FMTBIT_G723_40	_SNDRV_PCM_FMTBIT(G723_40)
+#define SNDRV_PCM_FMTBIT_G723_40_1B	_SNDRV_PCM_FMTBIT(G723_40_1B)
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #define SNDRV_PCM_FMTBIT_S16		SNDRV_PCM_FMTBIT_S16_LE
@@ -490,7 +491,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
 int snd_pcm_status(struct snd_pcm_substream *substream,
 		   struct snd_pcm_status *status);
 int snd_pcm_start(struct snd_pcm_substream *substream);
-int snd_pcm_stop(struct snd_pcm_substream *substream, int status);
+int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
 #ifdef CONFIG_PM
 int snd_pcm_suspend(struct snd_pcm_substream *substream);
@@ -748,8 +749,8 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc
 	return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
 }
 
-#define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))
-#define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT))
+#define params_access(p) ((__force snd_pcm_access_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)))
+#define params_format(p) ((__force snd_pcm_format_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)))
 #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
 #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min
 #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index d798941..9a155f9 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -15,67 +15,29 @@
 #define FSI_PORT_A	0
 #define FSI_PORT_B	1
 
-/* flags format
-
- * 0xABCDEEFF
- *
- * A:  channel size for TDM (input)
- * B:  channel size for TDM (ooutput)
- * C:  inversion
- * D:  mode
- * E:  input format
- * F:  output format
- */
-
 #include <linux/clk.h>
 #include <sound/soc.h>
 
-/* TDM channel */
-#define SH_FSI_SET_CH_I(x)	((x & 0xF) << 28)
-#define SH_FSI_SET_CH_O(x)	((x & 0xF) << 24)
-
-#define SH_FSI_CH_IMASK		0xF0000000
-#define SH_FSI_CH_OMASK		0x0F000000
-#define SH_FSI_GET_CH_I(x)	((x & SH_FSI_CH_IMASK) >> 28)
-#define SH_FSI_GET_CH_O(x)	((x & SH_FSI_CH_OMASK) >> 24)
-
-/* clock inversion */
-#define SH_FSI_INVERSION_MASK	0x00F00000
-#define SH_FSI_LRM_INV		(1 << 20)
-#define SH_FSI_BRM_INV		(1 << 21)
-#define SH_FSI_LRS_INV		(1 << 22)
-#define SH_FSI_BRS_INV		(1 << 23)
-
-/* mode */
-#define SH_FSI_MODE_MASK	0x000F0000
-#define SH_FSI_IN_SLAVE_MODE	(1 << 16)  /* default master mode */
-#define SH_FSI_OUT_SLAVE_MODE	(1 << 17)  /* default master mode */
-
-/* DI format */
-#define SH_FSI_FMT_MASK		0x000000FF
-#define SH_FSI_IFMT(x)		(((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8)
-#define SH_FSI_OFMT(x)		(((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0)
-#define SH_FSI_GET_IFMT(x)	((x >> 8) & SH_FSI_FMT_MASK)
-#define SH_FSI_GET_OFMT(x)	((x >> 0) & SH_FSI_FMT_MASK)
-
-#define SH_FSI_FMT_MONO		0
-#define SH_FSI_FMT_MONO_DELAY	1
-#define SH_FSI_FMT_PCM		2
-#define SH_FSI_FMT_I2S		3
-#define SH_FSI_FMT_TDM		4
-#define SH_FSI_FMT_TDM_DELAY	5
-#define SH_FSI_FMT_SPDIF	6
-
-
-#define SH_FSI_IFMT_TDM_CH(x) \
-	(SH_FSI_IFMT(TDM)	| SH_FSI_SET_CH_I(x))
-#define SH_FSI_IFMT_TDM_DELAY_CH(x) \
-	(SH_FSI_IFMT(TDM_DELAY)	| SH_FSI_SET_CH_I(x))
+/*
+ * flags format
+ *
+ * 0x000000BA
+ *
+ * A:  inversion
+ * B:  format mode
+ */
 
-#define SH_FSI_OFMT_TDM_CH(x) \
-	(SH_FSI_OFMT(TDM)	| SH_FSI_SET_CH_O(x))
-#define SH_FSI_OFMT_TDM_DELAY_CH(x) \
-	(SH_FSI_OFMT(TDM_DELAY)	| SH_FSI_SET_CH_O(x))
+/* A: clock inversion */
+#define SH_FSI_INVERSION_MASK	0x0000000F
+#define SH_FSI_LRM_INV		(1 << 0)
+#define SH_FSI_BRM_INV		(1 << 1)
+#define SH_FSI_LRS_INV		(1 << 2)
+#define SH_FSI_BRS_INV		(1 << 3)
+
+/* B: format mode */
+#define SH_FSI_FMT_MASK		0x000000F0
+#define SH_FSI_FMT_DAI		(0 << 4)
+#define SH_FSI_FMT_SPDIF	(1 << 4)
 
 
 /*
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 8031769..979ed84 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -157,6 +157,18 @@
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
 	.event = wevent, .event_flags = wflags}
 
+/* additional sequencing control within an event type */
+#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
+	wevent, wflags) \
+{	.id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .event = wevent, .event_flags = wflags, \
+	.subseq = wsubseq}
+#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
+	wflags)	\
+{	.id = snd_soc_dapm_supply, .name = wname, .reg = wreg,	\
+	.shift = wshift, .invert = winvert, .event = wevent, \
+	.event_flags = wflags, .subseq = wsubseq}
+
 /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
 #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
 	wevent, wflags) \
@@ -450,6 +462,7 @@ struct snd_soc_dapm_widget {
 	unsigned char ext:1;			/* has external widgets */
 	unsigned char force:1;			/* force state */
 	unsigned char ignore_suspend:1;         /* kept enabled over suspend */
+	int subseq;				/* sort within widget type */
 
 	int (*power_check)(struct snd_soc_dapm_widget *w);
 
@@ -487,6 +500,9 @@ struct snd_soc_dapm_context {
 
 	struct snd_soc_dapm_update *update;
 
+	void (*seq_notifier)(struct snd_soc_dapm_context *,
+			     enum snd_soc_dapm_type, int);
+
 	struct device *dev; /* from parent - for debug */
 	struct snd_soc_codec *codec; /* parent codec */
 	struct snd_soc_card *card; /* parent card */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 74921f2..bfa4836 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -234,6 +234,7 @@ struct snd_soc_codec;
 struct snd_soc_codec_driver;
 struct soc_enum;
 struct snd_soc_jack;
+struct snd_soc_jack_zone;
 struct snd_soc_jack_pin;
 struct snd_soc_cache_ops;
 #include <sound/soc-dapm.h>
@@ -258,6 +259,16 @@ enum snd_soc_compress_type {
 	SND_SOC_RBTREE_COMPRESSION
 };
 
+int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+			     unsigned int freq, int dir);
+int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
+			  unsigned int freq_in, unsigned int freq_out);
+
+int snd_soc_register_card(struct snd_soc_card *card);
+int snd_soc_unregister_card(struct snd_soc_card *card);
+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);
 void snd_soc_unregister_platform(struct device *dev);
@@ -265,7 +276,8 @@ 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_codec_volatile_register(struct snd_soc_codec *codec, int reg);
+int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
+				    unsigned int reg);
 int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 			       int addr_bits, int data_bits,
 			       enum snd_soc_control_type control);
@@ -276,6 +288,10 @@ int snd_soc_cache_write(struct snd_soc_codec *codec,
 			unsigned int reg, unsigned int value);
 int snd_soc_cache_read(struct snd_soc_codec *codec,
 		       unsigned int reg, unsigned int *value);
+int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
+				      unsigned int reg);
+int snd_soc_default_readable_register(struct snd_soc_codec *codec,
+				      unsigned int reg);
 
 /* Utility functions to get clock rates from various things */
 int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
@@ -297,6 +313,9 @@ void snd_soc_jack_notifier_register(struct snd_soc_jack *jack,
 				    struct notifier_block *nb);
 void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack,
 				      struct notifier_block *nb);
+int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count,
+			  struct snd_soc_jack_zone *zones);
+int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage);
 #ifdef CONFIG_GPIOLIB
 int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
 			struct snd_soc_jack_gpio *gpios);
@@ -321,7 +340,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
  *Controls
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-	void *data, char *long_name);
+				  void *data, char *long_name,
+				  const char *prefix);
 int snd_soc_add_controls(struct snd_soc_codec *codec,
 	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
@@ -367,6 +387,22 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 
 /**
+ * struct snd_soc_reg_access - Describes whether a given register is
+ * readable, writable or volatile.
+ *
+ * @reg: the register number
+ * @read: whether this register is readable
+ * @write: whether this register is writable
+ * @vol: whether this register is volatile
+ */
+struct snd_soc_reg_access {
+	u16 reg;
+	u16 read;
+	u16 write;
+	u16 vol;
+};
+
+/**
  * struct snd_soc_jack_pin - Describes a pin to update based on jack detection
  *
  * @pin:    name of the pin to update
@@ -381,6 +417,24 @@ struct snd_soc_jack_pin {
 };
 
 /**
+ * struct snd_soc_jack_zone - Describes voltage zones of jack detection
+ *
+ * @min_mv: start voltage in mv
+ * @max_mv: end voltage in mv
+ * @jack_type: type of jack that is expected for this voltage
+ * @debounce_time: debounce_time for jack, codec driver should wait for this
+ *		duration before reading the adc for voltages
+ * @:list: list container
+ */
+struct snd_soc_jack_zone {
+	unsigned int min_mv;
+	unsigned int max_mv;
+	unsigned int jack_type;
+	unsigned int debounce_time;
+	struct list_head list;
+};
+
+/**
  * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
  *
  * @gpio:         gpio number
@@ -388,6 +442,10 @@ struct snd_soc_jack_pin {
  * @report:       value to report when jack detected
  * @invert:       report presence in low state
  * @debouce_time: debouce time in ms
+ * @wake:	  enable as wake source
+ * @jack_status_check: callback function which overrides the detection
+ *		       to provide more complex checks (eg, reading an
+ *		       ADC).
  */
 #ifdef CONFIG_GPIOLIB
 struct snd_soc_jack_gpio {
@@ -396,6 +454,8 @@ struct snd_soc_jack_gpio {
 	int report;
 	int invert;
 	int debounce_time;
+	bool wake;
+
 	struct snd_soc_jack *jack;
 	struct delayed_work work;
 
@@ -409,6 +469,7 @@ struct snd_soc_jack {
 	struct list_head pins;
 	int status;
 	struct blocking_notifier_head notifier;
+	struct list_head jack_zones;
 };
 
 /* SoC PCM stream information */
@@ -459,18 +520,22 @@ struct snd_soc_codec {
 	struct list_head card_list;
 	int num_dai;
 	enum snd_soc_compress_type compress_type;
+	size_t reg_size;	/* reg_cache_size * reg_word_size */
+	int (*volatile_register)(struct snd_soc_codec *, unsigned int);
+	int (*readable_register)(struct snd_soc_codec *, unsigned int);
 
 	/* runtime */
 	struct snd_ac97 *ac97;  /* for ad-hoc ac97 devices */
 	unsigned int active;
-	unsigned int cache_only:1;  /* Suppress writes to hardware */
-	unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
+	unsigned int cache_bypass:1; /* Suppress access to the cache */
 	unsigned int suspended:1; /* Codec is in suspend PM state */
 	unsigned int probed:1; /* Codec has been probed */
 	unsigned int ac97_registered:1; /* Codec has been AC97 registered */
 	unsigned int ac97_created:1; /* Codec has been created by SoC */
 	unsigned int sysfs_registered:1; /* codec has been sysfs registered */
 	unsigned int cache_init:1; /* codec cache has been initialized */
+	u32 cache_only;  /* Suppress writes to hardware */
+	u32 cache_sync; /* Cache needs to be synced to hardware */
 
 	/* codec IO */
 	void *control_data; /* codec control (i2c/3wire) data */
@@ -503,22 +568,39 @@ struct snd_soc_codec_driver {
 			pm_message_t state);
 	int (*resume)(struct snd_soc_codec *);
 
+	/* Default DAPM setup, added after probe() is run */
+	const struct snd_soc_dapm_widget *dapm_widgets;
+	int num_dapm_widgets;
+	const struct snd_soc_dapm_route *dapm_routes;
+	int num_dapm_routes;
+
+	/* codec wide operations */
+	int (*set_sysclk)(struct snd_soc_codec *codec,
+			  int clk_id, unsigned int freq, int dir);
+	int (*set_pll)(struct snd_soc_codec *codec, int pll_id, int source,
+		unsigned int freq_in, unsigned int freq_out);
+
 	/* codec IO */
 	unsigned int (*read)(struct snd_soc_codec *, unsigned int);
 	int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
 	int (*display_register)(struct snd_soc_codec *, char *,
 				size_t, unsigned int);
-	int (*volatile_register)(unsigned int);
-	int (*readable_register)(unsigned int);
+	int (*volatile_register)(struct snd_soc_codec *, unsigned int);
+	int (*readable_register)(struct snd_soc_codec *, unsigned int);
 	short reg_cache_size;
 	short reg_cache_step;
 	short reg_word_size;
 	const void *reg_cache_default;
+	short reg_access_size;
+	const struct snd_soc_reg_access *reg_access_default;
 	enum snd_soc_compress_type compress_type;
 
 	/* codec bias level */
 	int (*set_bias_level)(struct snd_soc_codec *,
 			      enum snd_soc_bias_level level);
+
+	void (*seq_notifier)(struct snd_soc_dapm_context *,
+			     enum snd_soc_dapm_type, int);
 };
 
 /* SoC platform interface */
@@ -617,15 +699,16 @@ struct snd_soc_card {
 
 	bool instantiated;
 
-	int (*probe)(struct platform_device *pdev);
-	int (*remove)(struct platform_device *pdev);
+	int (*probe)(struct snd_soc_card *card);
+	int (*late_probe)(struct snd_soc_card *card);
+	int (*remove)(struct snd_soc_card *card);
 
 	/* the pre and post PM functions are used to do any PM work before and
 	 * after the codec and DAI's do any PM work. */
-	int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
-	int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
-	int (*resume_pre)(struct platform_device *pdev);
-	int (*resume_post)(struct platform_device *pdev);
+	int (*suspend_pre)(struct snd_soc_card *card);
+	int (*suspend_post)(struct snd_soc_card *card);
+	int (*resume_pre)(struct snd_soc_card *card);
+	int (*resume_post)(struct snd_soc_card *card);
 
 	/* callbacks */
 	int (*set_bias_level)(struct snd_soc_card *,
@@ -654,6 +737,14 @@ struct snd_soc_card {
 	struct snd_soc_pcm_runtime *rtd_aux;
 	int num_aux_rtd;
 
+	/*
+	 * Card-specific routes and widgets.
+	 */
+	struct snd_soc_dapm_widget *dapm_widgets;
+	int num_dapm_widgets;
+	struct snd_soc_dapm_route *dapm_routes;
+	int num_dapm_routes;
+
 	struct work_struct deferred_resume_work;
 
 	/* lists of probed devices belonging to this card */
@@ -665,11 +756,16 @@ struct snd_soc_card {
 	struct list_head paths;
 	struct list_head dapm_list;
 
+	/* Generic DAPM context for the card */
+	struct snd_soc_dapm_context dapm;
+
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_card_root;
 	struct dentry *debugfs_pop_time;
 #endif
 	u32 pop_time;
+
+	void *drvdata;
 };
 
 /* SoC machine DAI configuration, glues a codec and cpu DAI together */
@@ -721,6 +817,17 @@ unsigned int snd_soc_write(struct snd_soc_codec *codec,
 
 /* device driver data */
 
+static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card,
+		void *data)
+{
+	card->drvdata = data;
+}
+
+static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card)
+{
+	return card->drvdata;
+}
+
 static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
 		void *data)
 {
@@ -754,6 +861,22 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
 	return dev_get_drvdata(&rtd->dev);
 }
 
+static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
+{
+	INIT_LIST_HEAD(&card->dai_dev_list);
+	INIT_LIST_HEAD(&card->codec_dev_list);
+	INIT_LIST_HEAD(&card->platform_dev_list);
+	INIT_LIST_HEAD(&card->widgets);
+	INIT_LIST_HEAD(&card->paths);
+	INIT_LIST_HEAD(&card->dapm_list);
+}
+
 #include <sound/soc-dai.h>
 
+#ifdef CONFIG_DEBUG_FS
+extern struct dentry *snd_soc_debugfs_root;
+#endif
+
+extern const struct dev_pm_ops snd_soc_pm_ops;
+
 #endif
diff --git a/include/sound/tlv320aic32x4.h b/include/sound/tlv320aic32x4.h
new file mode 100644
index 0000000..c009f70
--- /dev/null
+++ b/include/sound/tlv320aic32x4.h
@@ -0,0 +1,31 @@
+/*
+ * tlv320aic32x4.h  --  TLV320AIC32X4 Soc Audio driver platform data
+ *
+ * Copyright 2011 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.
+ */
+
+#ifndef _AIC32X4_PDATA_H
+#define _AIC32X4_PDATA_H
+
+#define AIC32X4_PWR_MICBIAS_2075_LDOIN		0x00000001
+#define AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE	0x00000002
+#define AIC32X4_PWR_AIC32X4_LDO_ENABLE		0x00000004
+#define AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36	0x00000008
+#define AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED	0x00000010
+
+#define AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K	0x00000001
+#define AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K	0x00000002
+
+struct aic32x4_pdata {
+	u32 power_cfg;
+	u32 micpga_routing;
+	bool swapdacs;
+};
+
+#endif
diff --git a/include/sound/version.h b/include/sound/version.h
index bf69a5b..8fc5321 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h */
-#define CONFIG_SND_VERSION "1.0.23"
+#define CONFIG_SND_VERSION "1.0.24"
 #define CONFIG_SND_DATE ""
diff --git a/include/sound/wm8903.h b/include/sound/wm8903.h
index 1eeebd5..cf7ccb7 100644
--- a/include/sound/wm8903.h
+++ b/include/sound/wm8903.h
@@ -33,6 +33,21 @@
 #define WM8903_MICBIAS_ENA_WIDTH                     1  /* MICBIAS_ENA */
 
 /*
+ * WM8903_GPn_FN values
+ *
+ * See datasheets for list of valid values per pin
+ */
+#define WM8903_GPn_FN_GPIO_OUTPUT                    0
+#define WM8903_GPn_FN_BCLK                           1
+#define WM8903_GPn_FN_IRQ_OUTPT                      2
+#define WM8903_GPn_FN_GPIO_INPUT                     3
+#define WM8903_GPn_FN_MICBIAS_CURRENT_DETECT         4
+#define WM8903_GPn_FN_MICBIAS_SHORT_DETECT           5
+#define WM8903_GPn_FN_DMIC_LR_CLK_OUTPUT             6
+#define WM8903_GPn_FN_FLL_LOCK_OUTPUT                8
+#define WM8903_GPn_FN_FLL_CLOCK_OUTPUT               9
+
+/*
  * R116 (0x74) - GPIO Control 1
  */
 #define WM8903_GP1_FN_MASK                      0x1F00  /* GP1_FN - [12:8] */
@@ -227,6 +242,8 @@
 #define WM8903_GP5_DB_SHIFT                          0  /* GP5_DB */
 #define WM8903_GP5_DB_WIDTH                          1  /* GP5_DB */
 
+#define WM8903_NUM_GPIO 5
+
 struct wm8903_platform_data {
 	bool irq_active_low;   /* Set if IRQ active low, default high */
 
@@ -239,7 +256,8 @@ struct wm8903_platform_data {
 
 	int micdet_delay;      /* Delay after microphone detection (ms) */
 
-	u32 gpio_cfg[5];       /* Default register values for GPIO pin mux */
+	int gpio_base;
+	u32 gpio_cfg[WM8903_NUM_GPIO]; /* Default register values for GPIO pin mux */
 };
 
 #endif
diff --git a/include/sound/wm9081.h b/include/sound/wm9081.h
index e173ddb..f34b0b1 100644
--- a/include/sound/wm9081.h
+++ b/include/sound/wm9081.h
@@ -17,9 +17,12 @@ struct wm9081_retune_mobile_setting {
 	u16 config[20];
 };
 
-struct wm9081_retune_mobile_config {
-	struct wm9081_retune_mobile_setting *configs;
-	int num_configs;
+struct wm9081_pdata {
+	bool irq_high;   /* IRQ is active high */
+	bool irq_cmos;   /* IRQ is in CMOS mode */
+
+	struct wm9081_retune_mobile_setting *retune_configs;
+	int num_retune_configs;
 };
 
 #endif
diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
index 186e84d..ae973d2 100644
--- a/include/trace/events/asoc.h
+++ b/include/trace/events/asoc.h
@@ -229,6 +229,31 @@ TRACE_EVENT(snd_soc_jack_notify,
 	TP_printk("jack=%s %x", __get_str(name), (int)__entry->val)
 );
 
+TRACE_EVENT(snd_soc_cache_sync,
+
+	TP_PROTO(struct snd_soc_codec *codec, const char *type,
+		 const char *status),
+
+	TP_ARGS(codec, type, status),
+
+	TP_STRUCT__entry(
+		__string(	name,		codec->name	)
+		__string(	status,		status		)
+		__string(	type,		type		)
+		__field(	int,		id		)
+	),
+
+	TP_fast_assign(
+		__assign_str(name, codec->name);
+		__assign_str(status, status);
+		__assign_str(type, type);
+		__entry->id = codec->id;
+	),
+
+	TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
+		  (int)__entry->id, __get_str(type), __get_str(status))
+);
+
 #endif /* _TRACE_ASOC_H */
 
 /* This part must be outside protection */
diff --git a/include/trace/events/bkl.h b/include/trace/events/bkl.h
deleted file mode 100644
index 1af72dc..0000000
--- a/include/trace/events/bkl.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM bkl
-
-#if !defined(_TRACE_BKL_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_BKL_H
-
-#include <linux/tracepoint.h>
-
-TRACE_EVENT(lock_kernel,
-
-	TP_PROTO(const char *func, const char *file, int line),
-
-	TP_ARGS(func, file, line),
-
-	TP_STRUCT__entry(
-		__field(	int,		depth			)
-		__field_ext(	const char *,	func, FILTER_PTR_STRING	)
-		__field_ext(	const char *,	file, FILTER_PTR_STRING	)
-		__field(	int,		line			)
-	),
-
-	TP_fast_assign(
-		/* We want to record the lock_depth after lock is acquired */
-		__entry->depth = current->lock_depth + 1;
-		__entry->func = func;
-		__entry->file = file;
-		__entry->line = line;
-	),
-
-	TP_printk("depth=%d file:line=%s:%d func=%s()", __entry->depth,
-		  __entry->file, __entry->line, __entry->func)
-);
-
-TRACE_EVENT(unlock_kernel,
-
-	TP_PROTO(const char *func, const char *file, int line),
-
-	TP_ARGS(func, file, line),
-
-	TP_STRUCT__entry(
-		__field(int,		depth		)
-		__field(const char *,	func		)
-		__field(const char *,	file		)
-		__field(int,		line		)
-	),
-
-	TP_fast_assign(
-		__entry->depth = current->lock_depth;
-		__entry->func = func;
-		__entry->file = file;
-		__entry->line = line;
-	),
-
-	TP_printk("depth=%d file:line=%s:%d func=%s()", __entry->depth,
-		  __entry->file, __entry->line, __entry->func)
-);
-
-#endif /* _TRACE_BKL_H */
-
-/* This part must be outside protection */
-#include <trace/define_trace.h>
diff --git a/include/trace/events/mce.h b/include/trace/events/mce.h
index 7eee778..4cbbcef 100644
--- a/include/trace/events/mce.h
+++ b/include/trace/events/mce.h
@@ -17,36 +17,36 @@ TRACE_EVENT(mce_record,
 	TP_STRUCT__entry(
 		__field(	u64,		mcgcap		)
 		__field(	u64,		mcgstatus	)
-		__field(	u8,		bank		)
 		__field(	u64,		status		)
 		__field(	u64,		addr		)
 		__field(	u64,		misc		)
 		__field(	u64,		ip		)
-		__field(	u8,		cs		)
 		__field(	u64,		tsc		)
 		__field(	u64,		walltime	)
 		__field(	u32,		cpu		)
 		__field(	u32,		cpuid		)
 		__field(	u32,		apicid		)
 		__field(	u32,		socketid	)
+		__field(	u8,		cs		)
+		__field(	u8,		bank		)
 		__field(	u8,		cpuvendor	)
 	),
 
 	TP_fast_assign(
 		__entry->mcgcap		= m->mcgcap;
 		__entry->mcgstatus	= m->mcgstatus;
-		__entry->bank		= m->bank;
 		__entry->status		= m->status;
 		__entry->addr		= m->addr;
 		__entry->misc		= m->misc;
 		__entry->ip		= m->ip;
-		__entry->cs		= m->cs;
 		__entry->tsc		= m->tsc;
 		__entry->walltime	= m->time;
 		__entry->cpu		= m->extcpu;
 		__entry->cpuid		= m->cpuid;
 		__entry->apicid		= m->apicid;
 		__entry->socketid	= m->socketid;
+		__entry->cs		= m->cs;
+		__entry->bank		= m->bank;
 		__entry->cpuvendor	= m->cpuvendor;
 	),
 
diff --git a/include/trace/events/module.h b/include/trace/events/module.h
index c6bae36..21a546d 100644
--- a/include/trace/events/module.h
+++ b/include/trace/events/module.h
@@ -108,14 +108,14 @@ TRACE_EVENT(module_request,
 	TP_ARGS(name, wait, ip),
 
 	TP_STRUCT__entry(
-		__field(	bool,		wait		)
 		__field(	unsigned long,	ip		)
+		__field(	bool,		wait		)
 		__string(	name,		name		)
 	),
 
 	TP_fast_assign(
-		__entry->wait	= wait;
 		__entry->ip	= ip;
+		__entry->wait	= wait;
 		__assign_str(name, name);
 	),
 
@@ -129,4 +129,3 @@ TRACE_EVENT(module_request,
 
 /* This part must be outside protection */
 #include <trace/define_trace.h>
-
diff --git a/include/trace/events/scsi.h b/include/trace/events/scsi.h
index 25fbefd..db6c935 100644
--- a/include/trace/events/scsi.h
+++ b/include/trace/events/scsi.h
@@ -184,6 +184,17 @@
 		scsi_statusbyte_name(SAM_STAT_ACA_ACTIVE),	\
 		scsi_statusbyte_name(SAM_STAT_TASK_ABORTED))
 
+#define scsi_prot_op_name(result)	{ result, #result }
+#define show_prot_op_name(val)					\
+	__print_symbolic(val,					\
+		scsi_prot_op_name(SCSI_PROT_NORMAL),		\
+		scsi_prot_op_name(SCSI_PROT_READ_INSERT),	\
+		scsi_prot_op_name(SCSI_PROT_WRITE_STRIP),	\
+		scsi_prot_op_name(SCSI_PROT_READ_STRIP),	\
+		scsi_prot_op_name(SCSI_PROT_WRITE_INSERT),	\
+		scsi_prot_op_name(SCSI_PROT_READ_PASS),		\
+		scsi_prot_op_name(SCSI_PROT_WRITE_PASS))
+
 const char *scsi_trace_parse_cdb(struct trace_seq*, unsigned char*, int);
 #define __parse_cdb(cdb, len) scsi_trace_parse_cdb(p, cdb, len)
 
@@ -202,6 +213,7 @@ TRACE_EVENT(scsi_dispatch_cmd_start,
 		__field( unsigned int,	cmd_len )
 		__field( unsigned int,	data_sglen )
 		__field( unsigned int,	prot_sglen )
+		__field( unsigned char,	prot_op )
 		__dynamic_array(unsigned char,	cmnd, cmd->cmd_len)
 	),
 
@@ -214,13 +226,15 @@ TRACE_EVENT(scsi_dispatch_cmd_start,
 		__entry->cmd_len	= cmd->cmd_len;
 		__entry->data_sglen	= scsi_sg_count(cmd);
 		__entry->prot_sglen	= scsi_prot_sg_count(cmd);
+		__entry->prot_op	= scsi_get_prot_op(cmd);
 		memcpy(__get_dynamic_array(cmnd), cmd->cmnd, cmd->cmd_len);
 	),
 
 	TP_printk("host_no=%u channel=%u id=%u lun=%u data_sgl=%u prot_sgl=%u" \
-		  " cmnd=(%s %s raw=%s)",
+		  " prot_op=%s cmnd=(%s %s raw=%s)",
 		  __entry->host_no, __entry->channel, __entry->id,
 		  __entry->lun, __entry->data_sglen, __entry->prot_sglen,
+		  show_prot_op_name(__entry->prot_op),
 		  show_opcode_name(__entry->opcode),
 		  __parse_cdb(__get_dynamic_array(cmnd), __entry->cmd_len),
 		  __print_hex(__get_dynamic_array(cmnd), __entry->cmd_len))
@@ -242,6 +256,7 @@ TRACE_EVENT(scsi_dispatch_cmd_error,
 		__field( unsigned int,	cmd_len )
 		__field( unsigned int,	data_sglen )
 		__field( unsigned int,	prot_sglen )
+		__field( unsigned char,	prot_op )
 		__dynamic_array(unsigned char,	cmnd, cmd->cmd_len)
 	),
 
@@ -255,13 +270,15 @@ TRACE_EVENT(scsi_dispatch_cmd_error,
 		__entry->cmd_len	= cmd->cmd_len;
 		__entry->data_sglen	= scsi_sg_count(cmd);
 		__entry->prot_sglen	= scsi_prot_sg_count(cmd);
+		__entry->prot_op	= scsi_get_prot_op(cmd);
 		memcpy(__get_dynamic_array(cmnd), cmd->cmnd, cmd->cmd_len);
 	),
 
 	TP_printk("host_no=%u channel=%u id=%u lun=%u data_sgl=%u prot_sgl=%u" \
-		  " cmnd=(%s %s raw=%s) rtn=%d",
+		  " prot_op=%s cmnd=(%s %s raw=%s) rtn=%d",
 		  __entry->host_no, __entry->channel, __entry->id,
 		  __entry->lun, __entry->data_sglen, __entry->prot_sglen,
+		  show_prot_op_name(__entry->prot_op),
 		  show_opcode_name(__entry->opcode),
 		  __parse_cdb(__get_dynamic_array(cmnd), __entry->cmd_len),
 		  __print_hex(__get_dynamic_array(cmnd), __entry->cmd_len),
@@ -284,6 +301,7 @@ DECLARE_EVENT_CLASS(scsi_cmd_done_timeout_template,
 		__field( unsigned int,	cmd_len )
 		__field( unsigned int,	data_sglen )
 		__field( unsigned int,	prot_sglen )
+		__field( unsigned char,	prot_op )
 		__dynamic_array(unsigned char,	cmnd, cmd->cmd_len)
 	),
 
@@ -297,14 +315,16 @@ DECLARE_EVENT_CLASS(scsi_cmd_done_timeout_template,
 		__entry->cmd_len	= cmd->cmd_len;
 		__entry->data_sglen	= scsi_sg_count(cmd);
 		__entry->prot_sglen	= scsi_prot_sg_count(cmd);
+		__entry->prot_op	= scsi_get_prot_op(cmd);
 		memcpy(__get_dynamic_array(cmnd), cmd->cmnd, cmd->cmd_len);
 	),
 
 	TP_printk("host_no=%u channel=%u id=%u lun=%u data_sgl=%u " \
-		  "prot_sgl=%u cmnd=(%s %s raw=%s) result=(driver=%s host=%s " \
-		  "message=%s status=%s)",
+		  "prot_sgl=%u prot_op=%s cmnd=(%s %s raw=%s) result=(driver=" \
+		  "%s host=%s message=%s status=%s)",
 		  __entry->host_no, __entry->channel, __entry->id,
 		  __entry->lun, __entry->data_sglen, __entry->prot_sglen,
+		  show_prot_op_name(__entry->prot_op),
 		  show_opcode_name(__entry->opcode),
 		  __parse_cdb(__get_dynamic_array(cmnd), __entry->cmd_len),
 		  __print_hex(__get_dynamic_array(cmnd), __entry->cmd_len),
diff --git a/include/trace/events/skb.h b/include/trace/events/skb.h
index f10293c..0c68ae22 100644
--- a/include/trace/events/skb.h
+++ b/include/trace/events/skb.h
@@ -19,14 +19,14 @@ TRACE_EVENT(kfree_skb,
 
 	TP_STRUCT__entry(
 		__field(	void *,		skbaddr		)
-		__field(	unsigned short,	protocol	)
 		__field(	void *,		location	)
+		__field(	unsigned short,	protocol	)
 	),
 
 	TP_fast_assign(
 		__entry->skbaddr = skb;
-		__entry->protocol = ntohs(skb->protocol);
 		__entry->location = location;
+		__entry->protocol = ntohs(skb->protocol);
 	),
 
 	TP_printk("skbaddr=%p protocol=%u location=%p",
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index daabae5..2c8d369 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -59,6 +59,8 @@ struct sh_mobile_lcdc_board_cfg {
 			       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 	void (*display_on)(void *board_data, struct fb_info *info);
 	void (*display_off)(void *board_data);
+	int (*set_brightness)(void *board_data, int brightness);
+	int (*get_brightness)(void *board_data);
 };
 
 struct sh_mobile_lcdc_lcd_size_cfg { /* width and height of panel in mm */
@@ -66,6 +68,12 @@ struct sh_mobile_lcdc_lcd_size_cfg { /* width and height of panel in mm */
 	unsigned long height;
 };
 
+/* backlight info */
+struct sh_mobile_lcdc_bl_info {
+	const char *name;
+	int max_brightness;
+};
+
 struct sh_mobile_lcdc_chan_cfg {
 	int chan;
 	int bpp;
@@ -76,7 +84,9 @@ struct sh_mobile_lcdc_chan_cfg {
 	int num_cfg;
 	struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg;
 	struct sh_mobile_lcdc_board_cfg board_cfg;
+	struct sh_mobile_lcdc_bl_info bl_info;
 	struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
+	int nonstd;
 };
 
 struct sh_mobile_lcdc_info {
diff --git a/include/xen/balloon.h b/include/xen/balloon.h
new file mode 100644
index 0000000..a2b22f0
--- /dev/null
+++ b/include/xen/balloon.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ * Xen balloon functionality
+ */
+
+#define RETRY_UNLIMITED	0
+
+struct balloon_stats {
+	/* We aim for 'current allocation' == 'target allocation'. */
+	unsigned long current_pages;
+	unsigned long target_pages;
+	/* Number of pages in high- and low-memory balloons. */
+	unsigned long balloon_low;
+	unsigned long balloon_high;
+	unsigned long schedule_delay;
+	unsigned long max_schedule_delay;
+	unsigned long retry_count;
+	unsigned long max_retry_count;
+};
+
+extern struct balloon_stats balloon_stats;
+
+void balloon_set_new_target(unsigned long target);
+
+int alloc_xenballooned_pages(int nr_pages, struct page** pages);
+void free_xenballooned_pages(int nr_pages, struct page** pages);
diff --git a/include/xen/events.h b/include/xen/events.h
index 00f53dd..f1b87ad 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -23,6 +23,12 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
 			   unsigned long irqflags,
 			   const char *devname,
 			   void *dev_id);
+int bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
+					  unsigned int remote_port,
+					  irq_handler_t handler,
+					  unsigned long irqflags,
+					  const char *devname,
+					  void *dev_id);
 
 /*
  * Common unbind function for all event sources. Takes IRQ to unbind from.
@@ -41,9 +47,9 @@ static inline void notify_remote_via_evtchn(int port)
 	(void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);
 }
 
-extern void notify_remote_via_irq(int irq);
+void notify_remote_via_irq(int irq);
 
-extern void xen_irq_resume(void);
+void xen_irq_resume(void);
 
 /* Clear an irq's pending state, in preparation for polling on it */
 void xen_clear_irq_pending(int irq);
@@ -62,35 +68,29 @@ void xen_poll_irq_timeout(int irq, u64 timeout);
 unsigned irq_from_evtchn(unsigned int evtchn);
 
 /* Xen HVM evtchn vector callback */
-extern void xen_hvm_callback_vector(void);
+void xen_hvm_callback_vector(void);
 extern int xen_have_vector_callback;
 int xen_set_callback_via(uint64_t via);
 void xen_evtchn_do_upcall(struct pt_regs *regs);
 void xen_hvm_evtchn_do_upcall(void);
 
-/* Allocate an irq for a physical interrupt, given a gsi.  "Legacy"
- * GSIs are identity mapped; others are dynamically allocated as
- * usual. */
-int xen_allocate_pirq(unsigned gsi, int shareable, char *name);
-int xen_map_pirq_gsi(unsigned pirq, unsigned gsi, int shareable, char *name);
+/* Allocate a pirq for a physical interrupt, given a gsi. */
+int xen_allocate_pirq_gsi(unsigned gsi);
+/* Bind a pirq for a physical interrupt to an irq. */
+int xen_bind_pirq_gsi_to_irq(unsigned gsi,
+			     unsigned pirq, int shareable, char *name);
 
 #ifdef CONFIG_PCI_MSI
-/* Allocate an irq and a pirq to be used with MSIs. */
-#define XEN_ALLOC_PIRQ (1 << 0)
-#define XEN_ALLOC_IRQ  (1 << 1)
-void xen_allocate_pirq_msi(char *name, int *irq, int *pirq, int alloc_mask);
-int xen_create_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int type);
+/* Allocate a pirq for a MSI style physical interrupt. */
+int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc);
+/* Bind an PSI pirq to an irq. */
+int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
+			     int pirq, int vector, const char *name);
 #endif
 
 /* De-allocates the above mentioned physical interrupt. */
 int xen_destroy_irq(int irq);
 
-/* Return vector allocated to pirq */
-int xen_vector_from_irq(unsigned pirq);
-
-/* Return gsi allocated to pirq */
-int xen_gsi_from_irq(unsigned pirq);
-
 /* Return irq from pirq */
 int xen_irq_from_pirq(unsigned pirq);
 
diff --git a/include/xen/gntalloc.h b/include/xen/gntalloc.h
new file mode 100644
index 0000000..76bd580
--- /dev/null
+++ b/include/xen/gntalloc.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ * gntalloc.h
+ *
+ * Interface to /dev/xen/gntalloc.
+ *
+ * Author: Daniel De Graaf <dgdegra@tycho.nsa.gov>
+ *
+ * This file is in the public domain.
+ */
+
+#ifndef __LINUX_PUBLIC_GNTALLOC_H__
+#define __LINUX_PUBLIC_GNTALLOC_H__
+
+/*
+ * Allocates a new page and creates a new grant reference.
+ */
+#define IOCTL_GNTALLOC_ALLOC_GREF \
+_IOC(_IOC_NONE, 'G', 5, sizeof(struct ioctl_gntalloc_alloc_gref))
+struct ioctl_gntalloc_alloc_gref {
+	/* IN parameters */
+	/* The ID of the domain to be given access to the grants. */
+	uint16_t domid;
+	/* Flags for this mapping */
+	uint16_t flags;
+	/* Number of pages to map */
+	uint32_t count;
+	/* OUT parameters */
+	/* The offset to be used on a subsequent call to mmap(). */
+	uint64_t index;
+	/* The grant references of the newly created grant, one per page */
+	/* Variable size, depending on count */
+	uint32_t gref_ids[1];
+};
+
+#define GNTALLOC_FLAG_WRITABLE 1
+
+/*
+ * Deallocates the grant reference, allowing the associated page to be freed if
+ * no other domains are using it.
+ */
+#define IOCTL_GNTALLOC_DEALLOC_GREF \
+_IOC(_IOC_NONE, 'G', 6, sizeof(struct ioctl_gntalloc_dealloc_gref))
+struct ioctl_gntalloc_dealloc_gref {
+	/* IN parameters */
+	/* The offset returned in the map operation */
+	uint64_t index;
+	/* Number of references to unmap */
+	uint32_t count;
+};
+
+/*
+ * Sets up an unmap notification within the page, so that the other side can do
+ * cleanup if this side crashes. Required to implement cross-domain robust
+ * mutexes or close notification on communication channels.
+ *
+ * Each mapped page only supports one notification; multiple calls referring to
+ * the same page overwrite the previous notification. You must clear the
+ * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
+ * to occur.
+ */
+#define IOCTL_GNTALLOC_SET_UNMAP_NOTIFY \
+_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntalloc_unmap_notify))
+struct ioctl_gntalloc_unmap_notify {
+	/* IN parameters */
+	/* Offset in the file descriptor for a byte within the page (same as
+	 * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to
+	 * be cleared. Otherwise, it can be any byte in the page whose
+	 * notification we are adjusting.
+	 */
+	uint64_t index;
+	/* Action(s) to take on unmap */
+	uint32_t action;
+	/* Event channel to notify */
+	uint32_t event_channel_port;
+};
+
+/* Clear (set to zero) the byte specified by index */
+#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
+/* Send an interrupt on the indicated event channel */
+#define UNMAP_NOTIFY_SEND_EVENT 0x2
+
+#endif /* __LINUX_PUBLIC_GNTALLOC_H__ */
diff --git a/include/xen/gntdev.h b/include/xen/gntdev.h
index eb23f41..5304bd3 100644
--- a/include/xen/gntdev.h
+++ b/include/xen/gntdev.h
@@ -116,4 +116,35 @@ struct ioctl_gntdev_set_max_grants {
 	uint32_t count;
 };
 
+/*
+ * Sets up an unmap notification within the page, so that the other side can do
+ * cleanup if this side crashes. Required to implement cross-domain robust
+ * mutexes or close notification on communication channels.
+ *
+ * Each mapped page only supports one notification; multiple calls referring to
+ * the same page overwrite the previous notification. You must clear the
+ * notification prior to the IOCTL_GNTALLOC_DEALLOC_GREF if you do not want it
+ * to occur.
+ */
+#define IOCTL_GNTDEV_SET_UNMAP_NOTIFY \
+_IOC(_IOC_NONE, 'G', 7, sizeof(struct ioctl_gntdev_unmap_notify))
+struct ioctl_gntdev_unmap_notify {
+	/* IN parameters */
+	/* Offset in the file descriptor for a byte within the page (same as
+	 * used in mmap). If using UNMAP_NOTIFY_CLEAR_BYTE, this is the byte to
+	 * be cleared. Otherwise, it can be any byte in the page whose
+	 * notification we are adjusting.
+	 */
+	uint64_t index;
+	/* Action(s) to take on unmap */
+	uint32_t action;
+	/* Event channel to notify */
+	uint32_t event_channel_port;
+};
+
+/* Clear (set to zero) the byte specified by index */
+#define UNMAP_NOTIFY_CLEAR_BYTE 0x1
+/* Send an interrupt on the indicated event channel */
+#define UNMAP_NOTIFY_SEND_EVENT 0x2
+
 #endif /* __LINUX_PUBLIC_GNTDEV_H__ */
diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h
index c2d1fa4..61e523a 100644
--- a/include/xen/interface/io/blkif.h
+++ b/include/xen/interface/io/blkif.h
@@ -51,11 +51,7 @@ typedef uint64_t blkif_sector_t;
  */
 #define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
 
-struct blkif_request {
-	uint8_t        operation;    /* BLKIF_OP_???                         */
-	uint8_t        nr_segments;  /* number of segments                   */
-	blkif_vdev_t   handle;       /* only for read/write requests         */
-	uint64_t       id;           /* private guest value, echoed in resp  */
+struct blkif_request_rw {
 	blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
 	struct blkif_request_segment {
 		grant_ref_t gref;        /* reference to I/O buffer frame        */
@@ -65,6 +61,16 @@ struct blkif_request {
 	} seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
+struct blkif_request {
+	uint8_t        operation;    /* BLKIF_OP_???                         */
+	uint8_t        nr_segments;  /* number of segments                   */
+	blkif_vdev_t   handle;       /* only for read/write requests         */
+	uint64_t       id;           /* private guest value, echoed in resp  */
+	union {
+		struct blkif_request_rw rw;
+	} u;
+};
+
 struct blkif_response {
 	uint64_t        id;              /* copied from request */
 	uint8_t         operation;       /* copied from request */
@@ -91,4 +97,25 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
 #define VDISK_REMOVABLE    0x2
 #define VDISK_READONLY     0x4
 
+/* Xen-defined major numbers for virtual disks, they look strangely
+ * familiar */
+#define XEN_IDE0_MAJOR	3
+#define XEN_IDE1_MAJOR	22
+#define XEN_SCSI_DISK0_MAJOR	8
+#define XEN_SCSI_DISK1_MAJOR	65
+#define XEN_SCSI_DISK2_MAJOR	66
+#define XEN_SCSI_DISK3_MAJOR	67
+#define XEN_SCSI_DISK4_MAJOR	68
+#define XEN_SCSI_DISK5_MAJOR	69
+#define XEN_SCSI_DISK6_MAJOR	70
+#define XEN_SCSI_DISK7_MAJOR	71
+#define XEN_SCSI_DISK8_MAJOR	128
+#define XEN_SCSI_DISK9_MAJOR	129
+#define XEN_SCSI_DISK10_MAJOR	130
+#define XEN_SCSI_DISK11_MAJOR	131
+#define XEN_SCSI_DISK12_MAJOR	132
+#define XEN_SCSI_DISK13_MAJOR	133
+#define XEN_SCSI_DISK14_MAJOR	134
+#define XEN_SCSI_DISK15_MAJOR	135
+
 #endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
diff --git a/include/xen/interface/io/netif.h b/include/xen/interface/io/netif.h
index 518481c..cb94668 100644
--- a/include/xen/interface/io/netif.h
+++ b/include/xen/interface/io/netif.h
@@ -22,50 +22,50 @@
 
 /*
  * This is the 'wire' format for packets:
- *  Request 1: netif_tx_request -- NETTXF_* (any flags)
- * [Request 2: netif_tx_extra]  (only if request 1 has NETTXF_extra_info)
- * [Request 3: netif_tx_extra]  (only if request 2 has XEN_NETIF_EXTRA_MORE)
- *  Request 4: netif_tx_request -- NETTXF_more_data
- *  Request 5: netif_tx_request -- NETTXF_more_data
+ *  Request 1: xen_netif_tx_request  -- XEN_NETTXF_* (any flags)
+ * [Request 2: xen_netif_extra_info]    (only if request 1 has XEN_NETTXF_extra_info)
+ * [Request 3: xen_netif_extra_info]    (only if request 2 has XEN_NETIF_EXTRA_MORE)
+ *  Request 4: xen_netif_tx_request  -- XEN_NETTXF_more_data
+ *  Request 5: xen_netif_tx_request  -- XEN_NETTXF_more_data
  *  ...
- *  Request N: netif_tx_request -- 0
+ *  Request N: xen_netif_tx_request  -- 0
  */
 
 /* Protocol checksum field is blank in the packet (hardware offload)? */
-#define _NETTXF_csum_blank     (0)
-#define  NETTXF_csum_blank     (1U<<_NETTXF_csum_blank)
+#define _XEN_NETTXF_csum_blank		(0)
+#define  XEN_NETTXF_csum_blank		(1U<<_XEN_NETTXF_csum_blank)
 
 /* Packet data has been validated against protocol checksum. */
-#define _NETTXF_data_validated (1)
-#define  NETTXF_data_validated (1U<<_NETTXF_data_validated)
+#define _XEN_NETTXF_data_validated	(1)
+#define  XEN_NETTXF_data_validated	(1U<<_XEN_NETTXF_data_validated)
 
 /* Packet continues in the next request descriptor. */
-#define _NETTXF_more_data      (2)
-#define  NETTXF_more_data      (1U<<_NETTXF_more_data)
+#define _XEN_NETTXF_more_data		(2)
+#define  XEN_NETTXF_more_data		(1U<<_XEN_NETTXF_more_data)
 
 /* Packet to be followed by extra descriptor(s). */
-#define _NETTXF_extra_info     (3)
-#define  NETTXF_extra_info     (1U<<_NETTXF_extra_info)
+#define _XEN_NETTXF_extra_info		(3)
+#define  XEN_NETTXF_extra_info		(1U<<_XEN_NETTXF_extra_info)
 
 struct xen_netif_tx_request {
     grant_ref_t gref;      /* Reference to buffer page */
     uint16_t offset;       /* Offset within buffer page */
-    uint16_t flags;        /* NETTXF_* */
+    uint16_t flags;        /* XEN_NETTXF_* */
     uint16_t id;           /* Echoed in response message. */
     uint16_t size;         /* Packet size in bytes.       */
 };
 
-/* Types of netif_extra_info descriptors. */
-#define XEN_NETIF_EXTRA_TYPE_NONE  (0)  /* Never used - invalid */
-#define XEN_NETIF_EXTRA_TYPE_GSO   (1)  /* u.gso */
-#define XEN_NETIF_EXTRA_TYPE_MAX   (2)
+/* Types of xen_netif_extra_info descriptors. */
+#define XEN_NETIF_EXTRA_TYPE_NONE	(0)  /* Never used - invalid */
+#define XEN_NETIF_EXTRA_TYPE_GSO	(1)  /* u.gso */
+#define XEN_NETIF_EXTRA_TYPE_MAX	(2)
 
-/* netif_extra_info flags. */
-#define _XEN_NETIF_EXTRA_FLAG_MORE (0)
-#define XEN_NETIF_EXTRA_FLAG_MORE  (1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
+/* xen_netif_extra_info flags. */
+#define _XEN_NETIF_EXTRA_FLAG_MORE	(0)
+#define  XEN_NETIF_EXTRA_FLAG_MORE	(1U<<_XEN_NETIF_EXTRA_FLAG_MORE)
 
 /* GSO types - only TCPv4 currently supported. */
-#define XEN_NETIF_GSO_TYPE_TCPV4        (1)
+#define XEN_NETIF_GSO_TYPE_TCPV4	(1)
 
 /*
  * This structure needs to fit within both netif_tx_request and
@@ -107,7 +107,7 @@ struct xen_netif_extra_info {
 
 struct xen_netif_tx_response {
 	uint16_t id;
-	int16_t  status;       /* NETIF_RSP_* */
+	int16_t  status;       /* XEN_NETIF_RSP_* */
 };
 
 struct xen_netif_rx_request {
@@ -116,25 +116,29 @@ struct xen_netif_rx_request {
 };
 
 /* Packet data has been validated against protocol checksum. */
-#define _NETRXF_data_validated (0)
-#define  NETRXF_data_validated (1U<<_NETRXF_data_validated)
+#define _XEN_NETRXF_data_validated	(0)
+#define  XEN_NETRXF_data_validated	(1U<<_XEN_NETRXF_data_validated)
 
 /* Protocol checksum field is blank in the packet (hardware offload)? */
-#define _NETRXF_csum_blank     (1)
-#define  NETRXF_csum_blank     (1U<<_NETRXF_csum_blank)
+#define _XEN_NETRXF_csum_blank		(1)
+#define  XEN_NETRXF_csum_blank		(1U<<_XEN_NETRXF_csum_blank)
 
 /* Packet continues in the next request descriptor. */
-#define _NETRXF_more_data      (2)
-#define  NETRXF_more_data      (1U<<_NETRXF_more_data)
+#define _XEN_NETRXF_more_data		(2)
+#define  XEN_NETRXF_more_data		(1U<<_XEN_NETRXF_more_data)
 
 /* Packet to be followed by extra descriptor(s). */
-#define _NETRXF_extra_info     (3)
-#define  NETRXF_extra_info     (1U<<_NETRXF_extra_info)
+#define _XEN_NETRXF_extra_info		(3)
+#define  XEN_NETRXF_extra_info		(1U<<_XEN_NETRXF_extra_info)
+
+/* GSO Prefix descriptor. */
+#define _XEN_NETRXF_gso_prefix		(4)
+#define  XEN_NETRXF_gso_prefix		(1U<<_XEN_NETRXF_gso_prefix)
 
 struct xen_netif_rx_response {
     uint16_t id;
     uint16_t offset;       /* Offset in page of start of received packet  */
-    uint16_t flags;        /* NETRXF_* */
+    uint16_t flags;        /* XEN_NETRXF_* */
     int16_t  status;       /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
 };
 
@@ -149,10 +153,10 @@ DEFINE_RING_TYPES(xen_netif_rx,
 		  struct xen_netif_rx_request,
 		  struct xen_netif_rx_response);
 
-#define NETIF_RSP_DROPPED         -2
-#define NETIF_RSP_ERROR           -1
-#define NETIF_RSP_OKAY             0
-/* No response: used for auxiliary requests (e.g., netif_tx_extra). */
-#define NETIF_RSP_NULL             1
+#define XEN_NETIF_RSP_DROPPED	-2
+#define XEN_NETIF_RSP_ERROR	-1
+#define XEN_NETIF_RSP_OKAY	 0
+/* No response: used for auxiliary requests (e.g., xen_netif_extra_info). */
+#define XEN_NETIF_RSP_NULL	 1
 
 #endif
diff --git a/include/xen/interface/sched.h b/include/xen/interface/sched.h
index 5fec575..dd55dac 100644
--- a/include/xen/interface/sched.h
+++ b/include/xen/interface/sched.h
@@ -65,6 +65,39 @@ struct sched_poll {
 DEFINE_GUEST_HANDLE_STRUCT(sched_poll);
 
 /*
+ * Declare a shutdown for another domain. The main use of this function is
+ * in interpreting shutdown requests and reasons for fully-virtualized
+ * domains.  A para-virtualized domain may use SCHEDOP_shutdown directly.
+ * @arg == pointer to sched_remote_shutdown structure.
+ */
+#define SCHEDOP_remote_shutdown        4
+struct sched_remote_shutdown {
+    domid_t domain_id;         /* Remote domain ID */
+    unsigned int reason;       /* SHUTDOWN_xxx reason */
+};
+
+/*
+ * Latch a shutdown code, so that when the domain later shuts down it
+ * reports this code to the control tools.
+ * @arg == as for SCHEDOP_shutdown.
+ */
+#define SCHEDOP_shutdown_code 5
+
+/*
+ * Setup, poke and destroy a domain watchdog timer.
+ * @arg == pointer to sched_watchdog structure.
+ * With id == 0, setup a domain watchdog timer to cause domain shutdown
+ *               after timeout, returns watchdog id.
+ * With id != 0 and timeout == 0, destroy domain watchdog timer.
+ * With id != 0 and timeout != 0, poke watchdog timer and set new timeout.
+ */
+#define SCHEDOP_watchdog    6
+struct sched_watchdog {
+    uint32_t id;                /* watchdog ID */
+    uint32_t timeout;           /* timeout */
+};
+
+/*
  * Reason codes for SCHEDOP_shutdown. These may be interpreted by control
  * software to determine the appropriate action. For the most part, Xen does
  * not care about the shutdown code.
@@ -73,5 +106,6 @@ DEFINE_GUEST_HANDLE_STRUCT(sched_poll);
 #define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
 #define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
 #define SHUTDOWN_crash      3  /* Tell controller we've crashed.             */
+#define SHUTDOWN_watchdog   4  /* Restart because watchdog time expired.     */
 
 #endif /* __XEN_PUBLIC_SCHED_H__ */
diff --git a/include/xen/interface/xen.h b/include/xen/interface/xen.h
index 2befa3e..b33257b 100644
--- a/include/xen/interface/xen.h
+++ b/include/xen/interface/xen.h
@@ -30,7 +30,7 @@
 #define __HYPERVISOR_stack_switch          3
 #define __HYPERVISOR_set_callbacks         4
 #define __HYPERVISOR_fpu_taskswitch        5
-#define __HYPERVISOR_sched_op              6
+#define __HYPERVISOR_sched_op_compat       6
 #define __HYPERVISOR_dom0_op               7
 #define __HYPERVISOR_set_debugreg          8
 #define __HYPERVISOR_get_debugreg          9
@@ -52,7 +52,7 @@
 #define __HYPERVISOR_mmuext_op            26
 #define __HYPERVISOR_acm_op               27
 #define __HYPERVISOR_nmi_op               28
-#define __HYPERVISOR_sched_op_new         29
+#define __HYPERVISOR_sched_op             29
 #define __HYPERVISOR_callback_op          30
 #define __HYPERVISOR_xenoprof_op          31
 #define __HYPERVISOR_event_channel_op     32
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 98b9215..03c85d7 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -5,9 +5,9 @@
 
 DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
 
-void xen_pre_suspend(void);
-void xen_post_suspend(int suspend_cancelled);
-void xen_hvm_post_suspend(int suspend_cancelled);
+void xen_arch_pre_suspend(void);
+void xen_arch_post_suspend(int suspend_cancelled);
+void xen_arch_hvm_post_suspend(int suspend_cancelled);
 
 void xen_mm_pin_all(void);
 void xen_mm_unpin_all(void);
diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
index 7a1d15f..5467369 100644
--- a/include/xen/xenbus.h
+++ b/include/xen/xenbus.h
@@ -92,7 +92,7 @@ struct xenbus_driver {
 	void (*otherend_changed)(struct xenbus_device *dev,
 				 enum xenbus_state backend_state);
 	int (*remove)(struct xenbus_device *dev);
-	int (*suspend)(struct xenbus_device *dev, pm_message_t state);
+	int (*suspend)(struct xenbus_device *dev);
 	int (*resume)(struct xenbus_device *dev);
 	int (*uevent)(struct xenbus_device *, struct kobj_uevent_env *);
 	struct device_driver driver;
diff --git a/init/Kconfig b/init/Kconfig
index be788c0..56240e7 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -69,11 +69,6 @@ config BROKEN_ON_SMP
 	depends on BROKEN || !SMP
 	default y
 
-config LOCK_KERNEL
-	bool
-	depends on (SMP || PREEMPT) && BKL
-	default y
-
 config INIT_ENV_ARG_LIMIT
 	int
 	default 32 if !UML
@@ -287,6 +282,18 @@ config BSD_PROCESS_ACCT_V3
 	  for processing it. A preliminary version of these tools is available
 	  at <http://www.gnu.org/software/acct/>.
 
+config FHANDLE
+	bool "open by fhandle syscalls"
+	select EXPORTFS
+	help
+	  If you say Y here, a user level program will be able to map
+	  file names to handle and then later use the handle for
+	  different file system operations. This is useful in implementing
+	  userspace file servers, which now track files using handles instead
+	  of names. The handle would remain the same even if file names
+	  get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2)
+	  syscalls.
+
 config TASKSTATS
 	bool "Export task/process statistics through netlink (EXPERIMENTAL)"
 	depends on NET
@@ -683,6 +690,16 @@ config CGROUP_MEM_RES_CTLR_SWAP_ENABLED
 	  select this option (if, for some reason, they need to disable it
 	  then noswapaccount does the trick).
 
+config CGROUP_PERF
+	bool "Enable perf_event per-cpu per-container group (cgroup) monitoring"
+	depends on PERF_EVENTS && CGROUPS
+	help
+	  This option extends the per-cpu mode to restrict monitoring to
+	  threads which belong to the cgroup specified and run on the
+	  designated cpu.
+
+	  Say N if unsure.
+
 menuconfig CGROUP_SCHED
 	bool "Group CPU scheduler"
 	depends on EXPERIMENTAL
@@ -728,9 +745,9 @@ config BLK_CGROUP
 
 	This option only enables generic Block IO controller infrastructure.
 	One needs to also enable actual IO controlling logic/policy. For
-	enabling proportional weight division of disk bandwidth in CFQ seti
-	CONFIG_CFQ_GROUP_IOSCHED=y and for enabling throttling policy set
-	CONFIG_BLK_THROTTLE=y.
+	enabling proportional weight division of disk bandwidth in CFQ, set
+	CONFIG_CFQ_GROUP_IOSCHED=y; for enabling throttling policy, set
+	CONFIG_BLK_DEV_THROTTLING=y.
 
 	See Documentation/cgroups/blkio-controller.txt for more information.
 
@@ -814,7 +831,7 @@ config MM_OWNER
 	bool
 
 config SYSFS_DEPRECATED
-	bool "enable deprecated sysfs features to support old userspace tools"
+	bool "Enable deprecated sysfs features to support old userspace tools"
 	depends on SYSFS
 	default n
 	help
@@ -837,7 +854,7 @@ config SYSFS_DEPRECATED
 	  need to say Y here.
 
 config SYSFS_DEPRECATED_V2
-	bool "enabled deprecated sysfs features by default"
+	bool "Enable deprecated sysfs features by default"
 	default n
 	depends on SYSFS
 	depends on SYSFS_DEPRECATED
diff --git a/init/calibrate.c b/init/calibrate.c
index 24fe022..76ac919 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -110,8 +110,8 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
 
 /*
  * This is the number of bits of precision for the loops_per_jiffy.  Each
- * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
- * better than 1%
+ * time we refine our estimate after the first takes 1.5/HZ seconds, so try
+ * to start with a good estimate.
  * For the boot cpu we can skip the delay calibration and assign it a value
  * calculated based on the timer frequency.
  * For the rest of the CPUs we cannot assume that the timer frequency is same as
@@ -119,10 +119,72 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;}
  */
 #define LPS_PREC 8
 
+static unsigned long __cpuinit calibrate_delay_converge(void)
+{
+	/* First stage - slowly accelerate to find initial bounds */
+	unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;
+	int trials = 0, band = 0, trial_in_band = 0;
+
+	lpj = (1<<12);
+
+	/* wait for "start of" clock tick */
+	ticks = jiffies;
+	while (ticks == jiffies)
+		; /* nothing */
+	/* Go .. */
+	ticks = jiffies;
+	do {
+		if (++trial_in_band == (1<<band)) {
+			++band;
+			trial_in_band = 0;
+		}
+		__delay(lpj * band);
+		trials += band;
+	} while (ticks == jiffies);
+	/*
+	 * We overshot, so retreat to a clear underestimate. Then estimate
+	 * the largest likely undershoot. This defines our chop bounds.
+	 */
+	trials -= band;
+	loopadd_base = lpj * band;
+	lpj_base = lpj * trials;
+
+recalibrate:
+	lpj = lpj_base;
+	loopadd = loopadd_base;
+
+	/*
+	 * Do a binary approximation to get lpj set to
+	 * equal one clock (up to LPS_PREC bits)
+	 */
+	chop_limit = lpj >> LPS_PREC;
+	while (loopadd > chop_limit) {
+		lpj += loopadd;
+		ticks = jiffies;
+		while (ticks == jiffies)
+			; /* nothing */
+		ticks = jiffies;
+		__delay(lpj);
+		if (jiffies != ticks)	/* longer than 1 tick */
+			lpj -= loopadd;
+		loopadd >>= 1;
+	}
+	/*
+	 * If we incremented every single time possible, presume we've
+	 * massively underestimated initially, and retry with a higher
+	 * start, and larger range. (Only seen on x86_64, due to SMIs)
+	 */
+	if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {
+		lpj_base = lpj;
+		loopadd_base <<= 2;
+		goto recalibrate;
+	}
+
+	return lpj;
+}
+
 void __cpuinit calibrate_delay(void)
 {
-	unsigned long ticks, loopbit;
-	int lps_precision = LPS_PREC;
 	static bool printed;
 
 	if (preset_lpj) {
@@ -139,39 +201,9 @@ void __cpuinit calibrate_delay(void)
 			pr_info("Calibrating delay using timer "
 				"specific routine.. ");
 	} else {
-		loops_per_jiffy = (1<<12);
-
 		if (!printed)
 			pr_info("Calibrating delay loop... ");
-		while ((loops_per_jiffy <<= 1) != 0) {
-			/* wait for "start of" clock tick */
-			ticks = jiffies;
-			while (ticks == jiffies)
-				/* nothing */;
-			/* Go .. */
-			ticks = jiffies;
-			__delay(loops_per_jiffy);
-			ticks = jiffies - ticks;
-			if (ticks)
-				break;
-		}
-
-		/*
-		 * Do a binary approximation to get loops_per_jiffy set to
-		 * equal one clock (up to lps_precision bits)
-		 */
-		loops_per_jiffy >>= 1;
-		loopbit = loops_per_jiffy;
-		while (lps_precision-- && (loopbit >>= 1)) {
-			loops_per_jiffy |= loopbit;
-			ticks = jiffies;
-			while (ticks == jiffies)
-				/* nothing */;
-			ticks = jiffies;
-			__delay(loops_per_jiffy);
-			if (jiffies != ticks)	/* longer than 1 tick */
-				loops_per_jiffy &= ~loopbit;
-		}
+		loops_per_jiffy = calibrate_delay_converge();
 	}
 	if (!printed)
 		pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 2b54bef..3e01121 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -293,7 +293,8 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
 
 	sys_chdir((const char __user __force *)"/root");
 	ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
-	printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
+	printk(KERN_INFO
+	       "VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
 	       current->fs->pwd.mnt->mnt_sb->s_type->name,
 	       current->fs->pwd.mnt->mnt_sb->s_flags & MS_RDONLY ?
 	       " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c
index 6e1ee69..fe9acb0 100644
--- a/init/do_mounts_rd.c
+++ b/init/do_mounts_rd.c
@@ -64,7 +64,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
 
 	buf = kmalloc(size, GFP_KERNEL);
 	if (!buf)
-		return -1;
+		return -ENOMEM;
 
 	minixsb = (struct minix_super_block *) buf;
 	ext2sb = (struct ext2_super_block *) buf;
diff --git a/init/main.c b/init/main.c
index 33c37c3..3627bb3 100644
--- a/init/main.c
+++ b/init/main.c
@@ -129,63 +129,6 @@ static char *static_command_line;
 static char *execute_command;
 static char *ramdisk_execute_command;
 
-#ifdef CONFIG_SMP
-/* Setup configured maximum number of CPUs to activate */
-unsigned int setup_max_cpus = NR_CPUS;
-EXPORT_SYMBOL(setup_max_cpus);
-
-
-/*
- * Setup routine for controlling SMP activation
- *
- * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
- * activation entirely (the MPS table probe still happens, though).
- *
- * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- * greater than 0, limits the maximum number of CPUs activated in
- * SMP mode to <NUM>.
- */
-
-void __weak arch_disable_smp_support(void) { }
-
-static int __init nosmp(char *str)
-{
-	setup_max_cpus = 0;
-	arch_disable_smp_support();
-
-	return 0;
-}
-
-early_param("nosmp", nosmp);
-
-/* this is hard limit */
-static int __init nrcpus(char *str)
-{
-	int nr_cpus;
-
-	get_option(&str, &nr_cpus);
-	if (nr_cpus > 0 && nr_cpus < nr_cpu_ids)
-		nr_cpu_ids = nr_cpus;
-
-	return 0;
-}
-
-early_param("nr_cpus", nrcpus);
-
-static int __init maxcpus(char *str)
-{
-	get_option(&str, &setup_max_cpus);
-	if (setup_max_cpus == 0)
-		arch_disable_smp_support();
-
-	return 0;
-}
-
-early_param("maxcpus", maxcpus);
-#else
-static const unsigned int setup_max_cpus = NR_CPUS;
-#endif
-
 /*
  * If set, this is an indication to the drivers that reset the underlying
  * device before going ahead with the initialization otherwise driver might
@@ -362,7 +305,7 @@ static int __init rdinit_setup(char *str)
 __setup("rdinit=", rdinit_setup);
 
 #ifndef CONFIG_SMP
-
+static const unsigned int setup_max_cpus = NR_CPUS;
 #ifdef CONFIG_X86_LOCAL_APIC
 static void __init smp_init(void)
 {
@@ -374,37 +317,6 @@ static void __init smp_init(void)
 
 static inline void setup_nr_cpu_ids(void) { }
 static inline void smp_prepare_cpus(unsigned int maxcpus) { }
-
-#else
-
-/* Setup number of possible processor ids */
-int nr_cpu_ids __read_mostly = NR_CPUS;
-EXPORT_SYMBOL(nr_cpu_ids);
-
-/* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
-static void __init setup_nr_cpu_ids(void)
-{
-	nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
-}
-
-/* Called by boot processor to activate the rest. */
-static void __init smp_init(void)
-{
-	unsigned int cpu;
-
-	/* FIXME: This should be done in userspace --RR */
-	for_each_present_cpu(cpu) {
-		if (num_online_cpus() >= setup_max_cpus)
-			break;
-		if (!cpu_online(cpu))
-			cpu_up(cpu);
-	}
-
-	/* Any cleanup work */
-	printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
-	smp_cpus_done(setup_max_cpus);
-}
-
 #endif
 
 /*
diff --git a/kernel/audit.c b/kernel/audit.c
index e495624..9395003 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -74,6 +74,8 @@ static int	audit_initialized;
 int		audit_enabled;
 int		audit_ever_enabled;
 
+EXPORT_SYMBOL_GPL(audit_enabled);
+
 /* Default state when kernel boots without any parameters. */
 static int	audit_default;
 
@@ -671,9 +673,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
 	pid  = NETLINK_CREDS(skb)->pid;
 	uid  = NETLINK_CREDS(skb)->uid;
-	loginuid = NETLINK_CB(skb).loginuid;
-	sessionid = NETLINK_CB(skb).sessionid;
-	sid  = NETLINK_CB(skb).sid;
+	loginuid = audit_get_loginuid(current);
+	sessionid = audit_get_sessionid(current);
+	security_task_getsecid(current, &sid);
 	seq  = nlh->nlmsg_seq;
 	data = NLMSG_DATA(nlh);
 
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index d2e3c78..e683869 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -144,9 +144,9 @@ int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
 }
 
 /* Initialize a parent watch entry. */
-static struct audit_parent *audit_init_parent(struct nameidata *ndp)
+static struct audit_parent *audit_init_parent(struct path *path)
 {
-	struct inode *inode = ndp->path.dentry->d_inode;
+	struct inode *inode = path->dentry->d_inode;
 	struct audit_parent *parent;
 	int ret;
 
@@ -353,53 +353,40 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 }
 
 /* Get path information necessary for adding watches. */
-static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
+static int audit_get_nd(struct audit_watch *watch, struct path *parent)
 {
-	struct nameidata *ndparent, *ndwatch;
+	struct nameidata nd;
+	struct dentry *d;
 	int err;
 
-	ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL);
-	if (unlikely(!ndparent))
-		return -ENOMEM;
+	err = kern_path_parent(watch->path, &nd);
+	if (err)
+		return err;
 
-	ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL);
-	if (unlikely(!ndwatch)) {
-		kfree(ndparent);
-		return -ENOMEM;
+	if (nd.last_type != LAST_NORM) {
+		path_put(&nd.path);
+		return -EINVAL;
 	}
 
-	err = path_lookup(path, LOOKUP_PARENT, ndparent);
-	if (err) {
-		kfree(ndparent);
-		kfree(ndwatch);
-		return err;
+	mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+	d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
+	if (IS_ERR(d)) {
+		mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+		path_put(&nd.path);
+		return PTR_ERR(d);
 	}
-
-	err = path_lookup(path, 0, ndwatch);
-	if (err) {
-		kfree(ndwatch);
-		ndwatch = NULL;
+	if (d->d_inode) {
+		/* update watch filter fields */
+		watch->dev = d->d_inode->i_sb->s_dev;
+		watch->ino = d->d_inode->i_ino;
 	}
+	mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
 
-	*ndp = ndparent;
-	*ndw = ndwatch;
-
+	*parent = nd.path;
+	dput(d);
 	return 0;
 }
 
-/* Release resources used for watch path information. */
-static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
-{
-	if (ndp) {
-		path_put(&ndp->path);
-		kfree(ndp);
-	}
-	if (ndw) {
-		path_put(&ndw->path);
-		kfree(ndw);
-	}
-}
-
 /* Associate the given rule with an existing parent.
  * Caller must hold audit_filter_mutex. */
 static void audit_add_to_parent(struct audit_krule *krule,
@@ -440,31 +427,24 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 {
 	struct audit_watch *watch = krule->watch;
 	struct audit_parent *parent;
-	struct nameidata *ndp = NULL, *ndw = NULL;
+	struct path parent_path;
 	int h, ret = 0;
 
 	mutex_unlock(&audit_filter_mutex);
 
 	/* Avoid calling path_lookup under audit_filter_mutex. */
-	ret = audit_get_nd(watch->path, &ndp, &ndw);
-	if (ret) {
-		/* caller expects mutex locked */
-		mutex_lock(&audit_filter_mutex);
-		goto error;
-	}
+	ret = audit_get_nd(watch, &parent_path);
 
+	/* caller expects mutex locked */
 	mutex_lock(&audit_filter_mutex);
 
-	/* update watch filter fields */
-	if (ndw) {
-		watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev;
-		watch->ino = ndw->path.dentry->d_inode->i_ino;
-	}
+	if (ret)
+		return ret;
 
 	/* either find an old parent or attach a new one */
-	parent = audit_find_parent(ndp->path.dentry->d_inode);
+	parent = audit_find_parent(parent_path.dentry->d_inode);
 	if (!parent) {
-		parent = audit_init_parent(ndp);
+		parent = audit_init_parent(&parent_path);
 		if (IS_ERR(parent)) {
 			ret = PTR_ERR(parent);
 			goto error;
@@ -479,9 +459,8 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 	h = audit_hash_ino((u32)watch->ino);
 	*list = &audit_inode_hash[h];
 error:
-	audit_put_nd(ndp, ndw);		/* NULL args OK */
+	path_put(&parent_path);
 	return ret;
-
 }
 
 void audit_remove_watch_rule(struct audit_krule *krule)
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index add2819..f8277c8 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1238,6 +1238,7 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb,
 	for (i = 0; i < rule->field_count; i++) {
 		struct audit_field *f = &rule->fields[i];
 		int result = 0;
+		u32 sid;
 
 		switch (f->type) {
 		case AUDIT_PID:
@@ -1250,19 +1251,22 @@ static int audit_filter_user_rules(struct netlink_skb_parms *cb,
 			result = audit_comparator(cb->creds.gid, f->op, f->val);
 			break;
 		case AUDIT_LOGINUID:
-			result = audit_comparator(cb->loginuid, f->op, f->val);
+			result = audit_comparator(audit_get_loginuid(current),
+						  f->op, f->val);
 			break;
 		case AUDIT_SUBJ_USER:
 		case AUDIT_SUBJ_ROLE:
 		case AUDIT_SUBJ_TYPE:
 		case AUDIT_SUBJ_SEN:
 		case AUDIT_SUBJ_CLR:
-			if (f->lsm_rule)
-				result = security_audit_rule_match(cb->sid,
+			if (f->lsm_rule) {
+				security_task_getsecid(current, &sid);
+				result = security_audit_rule_match(sid,
 								   f->type,
 								   f->op,
 								   f->lsm_rule,
 								   NULL);
+			}
 			break;
 		}
 
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index b24d702..e31b220 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1813,10 +1813,8 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
 
 	/* Update the css_set linked lists if we're using them */
 	write_lock(&css_set_lock);
-	if (!list_empty(&tsk->cg_list)) {
-		list_del(&tsk->cg_list);
-		list_add(&tsk->cg_list, &newcg->tasks);
-	}
+	if (!list_empty(&tsk->cg_list))
+		list_move(&tsk->cg_list, &newcg->tasks);
 	write_unlock(&css_set_lock);
 
 	for_each_subsys(root, ss) {
@@ -3655,12 +3653,12 @@ again:
 	spin_lock(&release_list_lock);
 	set_bit(CGRP_REMOVED, &cgrp->flags);
 	if (!list_empty(&cgrp->release_list))
-		list_del(&cgrp->release_list);
+		list_del_init(&cgrp->release_list);
 	spin_unlock(&release_list_lock);
 
 	cgroup_lock_hierarchy(cgrp->root);
 	/* delete this cgroup from parent->children */
-	list_del(&cgrp->sibling);
+	list_del_init(&cgrp->sibling);
 	cgroup_unlock_hierarchy(cgrp->root);
 
 	d = dget(cgrp->dentry);
@@ -3879,7 +3877,7 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss)
 	subsys[ss->subsys_id] = NULL;
 
 	/* remove subsystem from rootnode's list of subsystems */
-	list_del(&ss->sibling);
+	list_del_init(&ss->sibling);
 
 	/*
 	 * disentangle the css from all css_sets attached to the dummytop. as
@@ -4230,20 +4228,8 @@ void cgroup_post_fork(struct task_struct *child)
  */
 void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 {
-	int i;
 	struct css_set *cg;
-
-	if (run_callbacks && need_forkexit_callback) {
-		/*
-		 * modular subsystems can't use callbacks, so no need to lock
-		 * the subsys array
-		 */
-		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
-			struct cgroup_subsys *ss = subsys[i];
-			if (ss->exit)
-				ss->exit(ss, tsk);
-		}
-	}
+	int i;
 
 	/*
 	 * Unlink from the css_set task list if necessary.
@@ -4253,7 +4239,7 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 	if (!list_empty(&tsk->cg_list)) {
 		write_lock(&css_set_lock);
 		if (!list_empty(&tsk->cg_list))
-			list_del(&tsk->cg_list);
+			list_del_init(&tsk->cg_list);
 		write_unlock(&css_set_lock);
 	}
 
@@ -4261,7 +4247,24 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
 	task_lock(tsk);
 	cg = tsk->cgroups;
 	tsk->cgroups = &init_css_set;
+
+	if (run_callbacks && need_forkexit_callback) {
+		/*
+		 * modular subsystems can't use callbacks, so no need to lock
+		 * the subsys array
+		 */
+		for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
+			struct cgroup_subsys *ss = subsys[i];
+			if (ss->exit) {
+				struct cgroup *old_cgrp =
+					rcu_dereference_raw(cg->subsys[i])->cgroup;
+				struct cgroup *cgrp = task_cgroup(tsk, i);
+				ss->exit(ss, cgrp, old_cgrp, tsk);
+			}
+		}
+	}
 	task_unlock(tsk);
+
 	if (cg)
 		put_css_set_taskexit(cg);
 }
@@ -4813,6 +4816,29 @@ css_get_next(struct cgroup_subsys *ss, int id,
 	return ret;
 }
 
+/*
+ * get corresponding css from file open on cgroupfs directory
+ */
+struct cgroup_subsys_state *cgroup_css_from_dir(struct file *f, int id)
+{
+	struct cgroup *cgrp;
+	struct inode *inode;
+	struct cgroup_subsys_state *css;
+
+	inode = f->f_dentry->d_inode;
+	/* check in cgroup filesystem dir */
+	if (inode->i_op != &cgroup_dir_inode_operations)
+		return ERR_PTR(-EBADF);
+
+	if (id < 0 || id >= CGROUP_SUBSYS_COUNT)
+		return ERR_PTR(-EINVAL);
+
+	/* get cgroup */
+	cgrp = __d_cgrp(f->f_dentry);
+	css = cgrp->subsys[id];
+	return css ? css : ERR_PTR(-ENOENT);
+}
+
 #ifdef CONFIG_CGROUP_DEBUG
 static struct cgroup_subsys_state *debug_create(struct cgroup_subsys *ss,
 						   struct cgroup *cont)
diff --git a/kernel/compat.c b/kernel/compat.c
index c9e2ec0..38b1d2c 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -52,6 +52,64 @@ static int compat_put_timeval(struct compat_timeval __user *o,
 		put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
 }
 
+static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
+{
+	memset(txc, 0, sizeof(struct timex));
+
+	if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
+			__get_user(txc->modes, &utp->modes) ||
+			__get_user(txc->offset, &utp->offset) ||
+			__get_user(txc->freq, &utp->freq) ||
+			__get_user(txc->maxerror, &utp->maxerror) ||
+			__get_user(txc->esterror, &utp->esterror) ||
+			__get_user(txc->status, &utp->status) ||
+			__get_user(txc->constant, &utp->constant) ||
+			__get_user(txc->precision, &utp->precision) ||
+			__get_user(txc->tolerance, &utp->tolerance) ||
+			__get_user(txc->time.tv_sec, &utp->time.tv_sec) ||
+			__get_user(txc->time.tv_usec, &utp->time.tv_usec) ||
+			__get_user(txc->tick, &utp->tick) ||
+			__get_user(txc->ppsfreq, &utp->ppsfreq) ||
+			__get_user(txc->jitter, &utp->jitter) ||
+			__get_user(txc->shift, &utp->shift) ||
+			__get_user(txc->stabil, &utp->stabil) ||
+			__get_user(txc->jitcnt, &utp->jitcnt) ||
+			__get_user(txc->calcnt, &utp->calcnt) ||
+			__get_user(txc->errcnt, &utp->errcnt) ||
+			__get_user(txc->stbcnt, &utp->stbcnt))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
+{
+	if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
+			__put_user(txc->modes, &utp->modes) ||
+			__put_user(txc->offset, &utp->offset) ||
+			__put_user(txc->freq, &utp->freq) ||
+			__put_user(txc->maxerror, &utp->maxerror) ||
+			__put_user(txc->esterror, &utp->esterror) ||
+			__put_user(txc->status, &utp->status) ||
+			__put_user(txc->constant, &utp->constant) ||
+			__put_user(txc->precision, &utp->precision) ||
+			__put_user(txc->tolerance, &utp->tolerance) ||
+			__put_user(txc->time.tv_sec, &utp->time.tv_sec) ||
+			__put_user(txc->time.tv_usec, &utp->time.tv_usec) ||
+			__put_user(txc->tick, &utp->tick) ||
+			__put_user(txc->ppsfreq, &utp->ppsfreq) ||
+			__put_user(txc->jitter, &utp->jitter) ||
+			__put_user(txc->shift, &utp->shift) ||
+			__put_user(txc->stabil, &utp->stabil) ||
+			__put_user(txc->jitcnt, &utp->jitcnt) ||
+			__put_user(txc->calcnt, &utp->calcnt) ||
+			__put_user(txc->errcnt, &utp->errcnt) ||
+			__put_user(txc->stbcnt, &utp->stbcnt) ||
+			__put_user(txc->tai, &utp->tai))
+		return -EFAULT;
+	return 0;
+}
+
 asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
 		struct timezone __user *tz)
 {
@@ -617,6 +675,29 @@ long compat_sys_clock_gettime(clockid_t which_clock,
 	return err;
 }
 
+long compat_sys_clock_adjtime(clockid_t which_clock,
+		struct compat_timex __user *utp)
+{
+	struct timex txc;
+	mm_segment_t oldfs;
+	int err, ret;
+
+	err = compat_get_timex(&txc, utp);
+	if (err)
+		return err;
+
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
+	set_fs(oldfs);
+
+	err = compat_put_timex(utp, &txc);
+	if (err)
+		return err;
+
+	return ret;
+}
+
 long compat_sys_clock_getres(clockid_t which_clock,
 		struct compat_timespec __user *tp)
 {
@@ -951,58 +1032,17 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp)
 {
 	struct timex txc;
-	int ret;
-
-	memset(&txc, 0, sizeof(struct timex));
+	int err, ret;
 
-	if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
-			__get_user(txc.modes, &utp->modes) ||
-			__get_user(txc.offset, &utp->offset) ||
-			__get_user(txc.freq, &utp->freq) ||
-			__get_user(txc.maxerror, &utp->maxerror) ||
-			__get_user(txc.esterror, &utp->esterror) ||
-			__get_user(txc.status, &utp->status) ||
-			__get_user(txc.constant, &utp->constant) ||
-			__get_user(txc.precision, &utp->precision) ||
-			__get_user(txc.tolerance, &utp->tolerance) ||
-			__get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
-			__get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
-			__get_user(txc.tick, &utp->tick) ||
-			__get_user(txc.ppsfreq, &utp->ppsfreq) ||
-			__get_user(txc.jitter, &utp->jitter) ||
-			__get_user(txc.shift, &utp->shift) ||
-			__get_user(txc.stabil, &utp->stabil) ||
-			__get_user(txc.jitcnt, &utp->jitcnt) ||
-			__get_user(txc.calcnt, &utp->calcnt) ||
-			__get_user(txc.errcnt, &utp->errcnt) ||
-			__get_user(txc.stbcnt, &utp->stbcnt))
-		return -EFAULT;
+	err = compat_get_timex(&txc, utp);
+	if (err)
+		return err;
 
 	ret = do_adjtimex(&txc);
 
-	if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
-			__put_user(txc.modes, &utp->modes) ||
-			__put_user(txc.offset, &utp->offset) ||
-			__put_user(txc.freq, &utp->freq) ||
-			__put_user(txc.maxerror, &utp->maxerror) ||
-			__put_user(txc.esterror, &utp->esterror) ||
-			__put_user(txc.status, &utp->status) ||
-			__put_user(txc.constant, &utp->constant) ||
-			__put_user(txc.precision, &utp->precision) ||
-			__put_user(txc.tolerance, &utp->tolerance) ||
-			__put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
-			__put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
-			__put_user(txc.tick, &utp->tick) ||
-			__put_user(txc.ppsfreq, &utp->ppsfreq) ||
-			__put_user(txc.jitter, &utp->jitter) ||
-			__put_user(txc.shift, &utp->shift) ||
-			__put_user(txc.stabil, &utp->stabil) ||
-			__put_user(txc.jitcnt, &utp->jitcnt) ||
-			__put_user(txc.calcnt, &utp->calcnt) ||
-			__put_user(txc.errcnt, &utp->errcnt) ||
-			__put_user(txc.stbcnt, &utp->stbcnt) ||
-			__put_user(txc.tai, &utp->tai))
-		ret = -EFAULT;
+	err = compat_put_timex(utp, &txc);
+	if (err)
+		return err;
 
 	return ret;
 }
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 156cc55..c95fc4d 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -160,7 +160,6 @@ static void cpu_notify_nofail(unsigned long val, void *v)
 {
 	BUG_ON(cpu_notify(val, v));
 }
-
 EXPORT_SYMBOL(register_cpu_notifier);
 
 void __ref unregister_cpu_notifier(struct notifier_block *nb)
@@ -205,7 +204,6 @@ static int __ref take_cpu_down(void *_param)
 		return err;
 
 	cpu_notify(CPU_DYING | param->mod, param->hcpu);
-
 	return 0;
 }
 
@@ -227,6 +225,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
 		return -EINVAL;
 
 	cpu_hotplug_begin();
+
 	err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls);
 	if (err) {
 		nr_calls--;
@@ -304,7 +303,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen)
 	ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls);
 	if (ret) {
 		nr_calls--;
-		printk("%s: attempt to bring up CPU %u failed\n",
+		printk(KERN_WARNING "%s: attempt to bring up CPU %u failed\n",
 				__func__, cpu);
 		goto out_notify;
 	}
@@ -450,14 +449,14 @@ void __ref enable_nonboot_cpus(void)
 	if (cpumask_empty(frozen_cpus))
 		goto out;
 
-	printk("Enabling non-boot CPUs ...\n");
+	printk(KERN_INFO "Enabling non-boot CPUs ...\n");
 
 	arch_enable_nonboot_cpus_begin();
 
 	for_each_cpu(cpu, frozen_cpus) {
 		error = _cpu_up(cpu, 1);
 		if (!error) {
-			printk("CPU%d is up\n", cpu);
+			printk(KERN_INFO "CPU%d is up\n", cpu);
 			continue;
 		}
 		printk(KERN_WARNING "Error taking CPU%d up: %d\n", cpu, error);
@@ -509,7 +508,7 @@ void __cpuinit notify_cpu_starting(unsigned int cpu)
  */
 
 /* cpu_bit_bitmap[0] is empty - so we can back into it */
-#define MASK_DECLARE_1(x)	[x+1][0] = 1UL << (x)
+#define MASK_DECLARE_1(x)	[x+1][0] = (1UL << (x))
 #define MASK_DECLARE_2(x)	MASK_DECLARE_1(x), MASK_DECLARE_1(x+1)
 #define MASK_DECLARE_4(x)	MASK_DECLARE_2(x), MASK_DECLARE_2(x+2)
 #define MASK_DECLARE_8(x)	MASK_DECLARE_4(x), MASK_DECLARE_4(x+4)
diff --git a/kernel/cred.c b/kernel/cred.c
index 3a9d6dd..2343c13 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -35,7 +35,7 @@ static struct kmem_cache *cred_jar;
 static struct thread_group_cred init_tgcred = {
 	.usage	= ATOMIC_INIT(2),
 	.tgid	= 0,
-	.lock	= SPIN_LOCK_UNLOCKED,
+	.lock	= __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock),
 };
 #endif
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 25e4291..f2b494d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -40,6 +40,7 @@
 #include <linux/tracehook.h>
 #include <linux/futex.h>
 #include <linux/compat.h>
+#include <linux/kthread.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/rcupdate.h>
 #include <linux/ptrace.h>
@@ -109,20 +110,25 @@ int nr_processes(void)
 }
 
 #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-# define alloc_task_struct()	kmem_cache_alloc(task_struct_cachep, GFP_KERNEL)
-# define free_task_struct(tsk)	kmem_cache_free(task_struct_cachep, (tsk))
+# define alloc_task_struct_node(node)		\
+		kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node)
+# define free_task_struct(tsk)			\
+		kmem_cache_free(task_struct_cachep, (tsk))
 static struct kmem_cache *task_struct_cachep;
 #endif
 
 #ifndef __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-static inline struct thread_info *alloc_thread_info(struct task_struct *tsk)
+static struct thread_info *alloc_thread_info_node(struct task_struct *tsk,
+						  int node)
 {
 #ifdef CONFIG_DEBUG_STACK_USAGE
 	gfp_t mask = GFP_KERNEL | __GFP_ZERO;
 #else
 	gfp_t mask = GFP_KERNEL;
 #endif
-	return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+	struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER);
+
+	return page ? page_address(page) : NULL;
 }
 
 static inline void free_thread_info(struct thread_info *ti)
@@ -193,6 +199,7 @@ void __put_task_struct(struct task_struct *tsk)
 	if (!profile_handoff_task(tsk))
 		free_task(tsk);
 }
+EXPORT_SYMBOL_GPL(__put_task_struct);
 
 /*
  * macro override instead of weak attribute alias, to workaround
@@ -248,16 +255,16 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 	struct task_struct *tsk;
 	struct thread_info *ti;
 	unsigned long *stackend;
-
+	int node = tsk_fork_get_node(orig);
 	int err;
 
 	prepare_to_copy(orig);
 
-	tsk = alloc_task_struct();
+	tsk = alloc_task_struct_node(node);
 	if (!tsk)
 		return NULL;
 
-	ti = alloc_thread_info(tsk);
+	ti = alloc_thread_info_node(tsk, node);
 	if (!ti) {
 		free_task_struct(tsk);
 		return NULL;
@@ -1512,38 +1519,24 @@ void __init proc_caches_init(void)
 }
 
 /*
- * Check constraints on flags passed to the unshare system call and
- * force unsharing of additional process context as appropriate.
+ * Check constraints on flags passed to the unshare system call.
  */
-static void check_unshare_flags(unsigned long *flags_ptr)
+static int check_unshare_flags(unsigned long unshare_flags)
 {
+	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
+				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
+				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
+		return -EINVAL;
 	/*
-	 * If unsharing a thread from a thread group, must also
-	 * unshare vm.
-	 */
-	if (*flags_ptr & CLONE_THREAD)
-		*flags_ptr |= CLONE_VM;
-
-	/*
-	 * If unsharing vm, must also unshare signal handlers.
-	 */
-	if (*flags_ptr & CLONE_VM)
-		*flags_ptr |= CLONE_SIGHAND;
-
-	/*
-	 * If unsharing namespace, must also unshare filesystem information.
+	 * Not implemented, but pretend it works if there is nothing to
+	 * unshare. Note that unsharing CLONE_THREAD or CLONE_SIGHAND
+	 * needs to unshare vm.
 	 */
-	if (*flags_ptr & CLONE_NEWNS)
-		*flags_ptr |= CLONE_FS;
-}
-
-/*
- * Unsharing of tasks created with CLONE_THREAD is not supported yet
- */
-static int unshare_thread(unsigned long unshare_flags)
-{
-	if (unshare_flags & CLONE_THREAD)
-		return -EINVAL;
+	if (unshare_flags & (CLONE_THREAD | CLONE_SIGHAND | CLONE_VM)) {
+		/* FIXME: get_task_mm() increments ->mm_users */
+		if (atomic_read(&current->mm->mm_users) > 1)
+			return -EINVAL;
+	}
 
 	return 0;
 }
@@ -1570,34 +1563,6 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
 }
 
 /*
- * Unsharing of sighand is not supported yet
- */
-static int unshare_sighand(unsigned long unshare_flags, struct sighand_struct **new_sighp)
-{
-	struct sighand_struct *sigh = current->sighand;
-
-	if ((unshare_flags & CLONE_SIGHAND) && atomic_read(&sigh->count) > 1)
-		return -EINVAL;
-	else
-		return 0;
-}
-
-/*
- * Unshare vm if it is being shared
- */
-static int unshare_vm(unsigned long unshare_flags, struct mm_struct **new_mmp)
-{
-	struct mm_struct *mm = current->mm;
-
-	if ((unshare_flags & CLONE_VM) &&
-	    (mm && atomic_read(&mm->mm_users) > 1)) {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/*
  * Unshare file descriptor table if it is being shared
  */
 static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp)
@@ -1625,45 +1590,37 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp
  */
 SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 {
-	int err = 0;
 	struct fs_struct *fs, *new_fs = NULL;
-	struct sighand_struct *new_sigh = NULL;
-	struct mm_struct *mm, *new_mm = NULL, *active_mm = NULL;
 	struct files_struct *fd, *new_fd = NULL;
 	struct nsproxy *new_nsproxy = NULL;
 	int do_sysvsem = 0;
+	int err;
 
-	check_unshare_flags(&unshare_flags);
-
-	/* Return -EINVAL for all unsupported flags */
-	err = -EINVAL;
-	if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND|
-				CLONE_VM|CLONE_FILES|CLONE_SYSVSEM|
-				CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET))
+	err = check_unshare_flags(unshare_flags);
+	if (err)
 		goto bad_unshare_out;
 
 	/*
+	 * If unsharing namespace, must also unshare filesystem information.
+	 */
+	if (unshare_flags & CLONE_NEWNS)
+		unshare_flags |= CLONE_FS;
+	/*
 	 * CLONE_NEWIPC must also detach from the undolist: after switching
 	 * to a new ipc namespace, the semaphore arrays from the old
 	 * namespace are unreachable.
 	 */
 	if (unshare_flags & (CLONE_NEWIPC|CLONE_SYSVSEM))
 		do_sysvsem = 1;
-	if ((err = unshare_thread(unshare_flags)))
-		goto bad_unshare_out;
 	if ((err = unshare_fs(unshare_flags, &new_fs)))
-		goto bad_unshare_cleanup_thread;
-	if ((err = unshare_sighand(unshare_flags, &new_sigh)))
-		goto bad_unshare_cleanup_fs;
-	if ((err = unshare_vm(unshare_flags, &new_mm)))
-		goto bad_unshare_cleanup_sigh;
+		goto bad_unshare_out;
 	if ((err = unshare_fd(unshare_flags, &new_fd)))
-		goto bad_unshare_cleanup_vm;
+		goto bad_unshare_cleanup_fs;
 	if ((err = unshare_nsproxy_namespaces(unshare_flags, &new_nsproxy,
 			new_fs)))
 		goto bad_unshare_cleanup_fd;
 
-	if (new_fs ||  new_mm || new_fd || do_sysvsem || new_nsproxy) {
+	if (new_fs || new_fd || do_sysvsem || new_nsproxy) {
 		if (do_sysvsem) {
 			/*
 			 * CLONE_SYSVSEM is equivalent to sys_exit().
@@ -1689,19 +1646,6 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
 			spin_unlock(&fs->lock);
 		}
 
-		if (new_mm) {
-			mm = current->mm;
-			active_mm = current->active_mm;
-			current->mm = new_mm;
-			current->active_mm = new_mm;
-			if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
-				atomic_dec(&mm->oom_disable_count);
-				atomic_inc(&new_mm->oom_disable_count);
-			}
-			activate_mm(active_mm, new_mm);
-			new_mm = mm;
-		}
-
 		if (new_fd) {
 			fd = current->files;
 			current->files = new_fd;
@@ -1718,20 +1662,10 @@ bad_unshare_cleanup_fd:
 	if (new_fd)
 		put_files_struct(new_fd);
 
-bad_unshare_cleanup_vm:
-	if (new_mm)
-		mmput(new_mm);
-
-bad_unshare_cleanup_sigh:
-	if (new_sigh)
-		if (atomic_dec_and_test(&new_sigh->count))
-			kmem_cache_free(sighand_cachep, new_sigh);
-
 bad_unshare_cleanup_fs:
 	if (new_fs)
 		free_fs_struct(new_fs);
 
-bad_unshare_cleanup_thread:
 bad_unshare_out:
 	return err;
 }
diff --git a/kernel/futex.c b/kernel/futex.c
index b766d28..bda4157 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -381,15 +381,16 @@ static struct futex_q *futex_top_waiter(struct futex_hash_bucket *hb,
 	return NULL;
 }
 
-static u32 cmpxchg_futex_value_locked(u32 __user *uaddr, u32 uval, u32 newval)
+static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr,
+				      u32 uval, u32 newval)
 {
-	u32 curval;
+	int ret;
 
 	pagefault_disable();
-	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	ret = futex_atomic_cmpxchg_inatomic(curval, uaddr, uval, newval);
 	pagefault_enable();
 
-	return curval;
+	return ret;
 }
 
 static int get_futex_value_locked(u32 *dest, u32 __user *from)
@@ -674,7 +675,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
 				struct task_struct *task, int set_waiters)
 {
 	int lock_taken, ret, ownerdied = 0;
-	u32 uval, newval, curval;
+	u32 uval, newval, curval, vpid = task_pid_vnr(task);
 
 retry:
 	ret = lock_taken = 0;
@@ -684,19 +685,17 @@ retry:
 	 * (by doing a 0 -> TID atomic cmpxchg), while holding all
 	 * the locks. It will most likely not succeed.
 	 */
-	newval = task_pid_vnr(task);
+	newval = vpid;
 	if (set_waiters)
 		newval |= FUTEX_WAITERS;
 
-	curval = cmpxchg_futex_value_locked(uaddr, 0, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, 0, newval)))
 		return -EFAULT;
 
 	/*
 	 * Detect deadlocks.
 	 */
-	if ((unlikely((curval & FUTEX_TID_MASK) == task_pid_vnr(task))))
+	if ((unlikely((curval & FUTEX_TID_MASK) == vpid)))
 		return -EDEADLK;
 
 	/*
@@ -723,14 +722,12 @@ retry:
 	 */
 	if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
 		/* Keep the OWNER_DIED bit */
-		newval = (curval & ~FUTEX_TID_MASK) | task_pid_vnr(task);
+		newval = (curval & ~FUTEX_TID_MASK) | vpid;
 		ownerdied = 0;
 		lock_taken = 1;
 	}
 
-	curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-	if (unlikely(curval == -EFAULT))
+	if (unlikely(cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)))
 		return -EFAULT;
 	if (unlikely(curval != uval))
 		goto retry;
@@ -775,6 +772,24 @@ retry:
 	return ret;
 }
 
+/**
+ * __unqueue_futex() - Remove the futex_q from its futex_hash_bucket
+ * @q:	The futex_q to unqueue
+ *
+ * The q->lock_ptr must not be NULL and must be held by the caller.
+ */
+static void __unqueue_futex(struct futex_q *q)
+{
+	struct futex_hash_bucket *hb;
+
+	if (WARN_ON(!q->lock_ptr || !spin_is_locked(q->lock_ptr)
+			|| plist_node_empty(&q->list)))
+		return;
+
+	hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock);
+	plist_del(&q->list, &hb->chain);
+}
+
 /*
  * The hash bucket lock must be held when this is called.
  * Afterwards, the futex_q must not be accessed.
@@ -792,7 +807,7 @@ static void wake_futex(struct futex_q *q)
 	 */
 	get_task_struct(p);
 
-	plist_del(&q->list, &q->list.plist);
+	__unqueue_futex(q);
 	/*
 	 * The waiting task can free the futex_q as soon as
 	 * q->lock_ptr = NULL is written, without taking any locks. A
@@ -843,9 +858,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
 
 		newval = FUTEX_WAITERS | task_pid_vnr(new_owner);
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			ret = -EFAULT;
 		else if (curval != uval)
 			ret = -EINVAL;
@@ -880,10 +893,8 @@ static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
 	 * There is no waiter, so we unlock the futex. The owner died
 	 * bit has not to be preserved here. We are the owner:
 	 */
-	oldval = cmpxchg_futex_value_locked(uaddr, uval, 0);
-
-	if (oldval == -EFAULT)
-		return oldval;
+	if (cmpxchg_futex_value_locked(&oldval, uaddr, uval, 0))
+		return -EFAULT;
 	if (oldval != uval)
 		return -EAGAIN;
 
@@ -1071,9 +1082,6 @@ void requeue_futex(struct futex_q *q, struct futex_hash_bucket *hb1,
 		plist_del(&q->list, &hb1->chain);
 		plist_add(&q->list, &hb2->chain);
 		q->lock_ptr = &hb2->lock;
-#ifdef CONFIG_DEBUG_PI_LIST
-		q->list.plist.spinlock = &hb2->lock;
-#endif
 	}
 	get_futex_key_refs(key2);
 	q->key = *key2;
@@ -1100,16 +1108,12 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
 	get_futex_key_refs(key);
 	q->key = *key;
 
-	WARN_ON(plist_node_empty(&q->list));
-	plist_del(&q->list, &q->list.plist);
+	__unqueue_futex(q);
 
 	WARN_ON(!q->rt_waiter);
 	q->rt_waiter = NULL;
 
 	q->lock_ptr = &hb->lock;
-#ifdef CONFIG_DEBUG_PI_LIST
-	q->list.plist.spinlock = &hb->lock;
-#endif
 
 	wake_up_state(q->task, TASK_NORMAL);
 }
@@ -1457,9 +1461,6 @@ static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
 	prio = min(current->normal_prio, MAX_RT_PRIO);
 
 	plist_node_init(&q->list, prio);
-#ifdef CONFIG_DEBUG_PI_LIST
-	q->list.plist.spinlock = &hb->lock;
-#endif
 	plist_add(&q->list, &hb->chain);
 	q->task = current;
 	spin_unlock(&hb->lock);
@@ -1504,8 +1505,7 @@ retry:
 			spin_unlock(lock_ptr);
 			goto retry;
 		}
-		WARN_ON(plist_node_empty(&q->list));
-		plist_del(&q->list, &q->list.plist);
+		__unqueue_futex(q);
 
 		BUG_ON(q->pi_state);
 
@@ -1525,8 +1525,7 @@ retry:
 static void unqueue_me_pi(struct futex_q *q)
 	__releases(q->lock_ptr)
 {
-	WARN_ON(plist_node_empty(&q->list));
-	plist_del(&q->list, &q->list.plist);
+	__unqueue_futex(q);
 
 	BUG_ON(!q->pi_state);
 	free_pi_state(q->pi_state);
@@ -1556,10 +1555,10 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q,
 
 	/*
 	 * We are here either because we stole the rtmutex from the
-	 * pending owner or we are the pending owner which failed to
-	 * get the rtmutex. We have to replace the pending owner TID
-	 * in the user space variable. This must be atomic as we have
-	 * to preserve the owner died bit here.
+	 * previous highest priority waiter or we are the highest priority
+	 * waiter but failed to get the rtmutex the first time.
+	 * We have to replace the newowner TID in the user space variable.
+	 * This must be atomic as we have to preserve the owner died bit here.
 	 *
 	 * Note: We write the user space value _before_ changing the pi_state
 	 * because we can fault here. Imagine swapped out pages or a fork
@@ -1578,9 +1577,7 @@ retry:
 	while (1) {
 		newval = (uval & FUTEX_OWNER_DIED) | newtid;
 
-		curval = cmpxchg_futex_value_locked(uaddr, uval, newval);
-
-		if (curval == -EFAULT)
+		if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval))
 			goto handle_fault;
 		if (curval == uval)
 			break;
@@ -1608,8 +1605,8 @@ retry:
 
 	/*
 	 * To handle the page fault we need to drop the hash bucket
-	 * lock here. That gives the other task (either the pending
-	 * owner itself or the task which stole the rtmutex) the
+	 * lock here. That gives the other task (either the highest priority
+	 * waiter itself or the task which stole the rtmutex) the
 	 * chance to try the fixup of the pi_state. So once we are
 	 * back from handling the fault we need to check the pi_state
 	 * after reacquiring the hash bucket lock and before trying to
@@ -1685,18 +1682,20 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
 		/*
 		 * pi_state is incorrect, some other task did a lock steal and
 		 * we returned due to timeout or signal without taking the
-		 * rt_mutex. Too late. We can access the rt_mutex_owner without
-		 * locking, as the other task is now blocked on the hash bucket
-		 * lock. Fix the state up.
+		 * rt_mutex. Too late.
 		 */
+		raw_spin_lock(&q->pi_state->pi_mutex.wait_lock);
 		owner = rt_mutex_owner(&q->pi_state->pi_mutex);
+		if (!owner)
+			owner = rt_mutex_next_owner(&q->pi_state->pi_mutex);
+		raw_spin_unlock(&q->pi_state->pi_mutex.wait_lock);
 		ret = fixup_pi_state_owner(uaddr, q, owner);
 		goto out;
 	}
 
 	/*
 	 * Paranoia check. If we did not take the lock, then we should not be
-	 * the owner, nor the pending owner, of the rt_mutex.
+	 * the owner of the rt_mutex.
 	 */
 	if (rt_mutex_owner(&q->pi_state->pi_mutex) == current)
 		printk(KERN_ERR "fixup_owner: ret = %d pi-mutex: %p "
@@ -1781,13 +1780,14 @@ static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
 	 *
 	 * The basic logical guarantee of a futex is that it blocks ONLY
 	 * if cond(var) is known to be true at the time of blocking, for
-	 * any cond.  If we queued after testing *uaddr, that would open
-	 * a race condition where we could block indefinitely with
+	 * any cond.  If we locked the hash-bucket after testing *uaddr, that
+	 * would open a race condition where we could block indefinitely with
 	 * cond(var) false, which would violate the guarantee.
 	 *
-	 * A consequence is that futex_wait() can return zero and absorb
-	 * a wakeup when *uaddr != val on entry to the syscall.  This is
-	 * rare, but normal.
+	 * On the other hand, we insert q and release the hash-bucket only
+	 * after testing *uaddr.  This guarantees that futex_wait() will NOT
+	 * absorb a wakeup if *uaddr does not match the desired values
+	 * while the syscall executes.
 	 */
 retry:
 	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q->key);
@@ -2046,9 +2046,9 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags)
 {
 	struct futex_hash_bucket *hb;
 	struct futex_q *this, *next;
-	u32 uval;
 	struct plist_head *head;
 	union futex_key key = FUTEX_KEY_INIT;
+	u32 uval, vpid = task_pid_vnr(current);
 	int ret;
 
 retry:
@@ -2057,7 +2057,7 @@ retry:
 	/*
 	 * We release only a lock we actually own:
 	 */
-	if ((uval & FUTEX_TID_MASK) != task_pid_vnr(current))
+	if ((uval & FUTEX_TID_MASK) != vpid)
 		return -EPERM;
 
 	ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &key);
@@ -2072,17 +2072,14 @@ retry:
 	 * again. If it succeeds then we can return without waking
 	 * anyone else up:
 	 */
-	if (!(uval & FUTEX_OWNER_DIED))
-		uval = cmpxchg_futex_value_locked(uaddr, task_pid_vnr(current), 0);
-
-
-	if (unlikely(uval == -EFAULT))
+	if (!(uval & FUTEX_OWNER_DIED) &&
+	    cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0))
 		goto pi_faulted;
 	/*
 	 * Rare case: we managed to release the lock atomically,
 	 * no need to wake anyone else up:
 	 */
-	if (unlikely(uval == task_pid_vnr(current)))
+	if (unlikely(uval == vpid))
 		goto out_unlock;
 
 	/*
@@ -2167,7 +2164,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
 		 * We were woken prior to requeue by a timeout or a signal.
 		 * Unqueue the futex_q and determine which it was.
 		 */
-		plist_del(&q->list, &q->list.plist);
+		plist_del(&q->list, &hb->chain);
 
 		/* Handle spurious wakeups gracefully */
 		ret = -EWOULDBLOCK;
@@ -2463,11 +2460,20 @@ retry:
 		 * userspace.
 		 */
 		mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED;
-		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval, mval);
-
-		if (nval == -EFAULT)
-			return -1;
-
+		/*
+		 * We are not holding a lock here, but we want to have
+		 * the pagefault_disable/enable() protection because
+		 * we want to handle the fault gracefully. If the
+		 * access fails we try to fault in the futex with R/W
+		 * verification via get_user_pages. get_user() above
+		 * does not guarantee R/W access. If that fails we
+		 * give up and leave the futex locked.
+		 */
+		if (cmpxchg_futex_value_locked(&nval, uaddr, uval, mval)) {
+			if (fault_in_user_writeable(uaddr))
+				return -1;
+			goto retry;
+		}
 		if (nval != uval)
 			goto retry;
 
@@ -2678,8 +2684,7 @@ static int __init futex_init(void)
 	 * implementation, the non-functional ones will return
 	 * -ENOSYS.
 	 */
-	curval = cmpxchg_futex_value_locked(NULL, 0, 0);
-	if (curval == -EFAULT)
+	if (cmpxchg_futex_value_locked(&curval, NULL, 0, 0) == -EFAULT)
 		futex_cmpxchg_enabled = 1;
 
 	for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index 70a298d..b8cadf7 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -34,7 +34,7 @@ config GCOV_KERNEL
 config GCOV_PROFILE_ALL
 	bool "Profile entire Kernel"
 	depends on GCOV_KERNEL
-	depends on S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE
+	depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE
 	default n
 	---help---
 	This options activates profiling for the entire kernel.
diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index 3f76100..e97ca59 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -1,3 +1,3 @@
-EXTRA_CFLAGS := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
+ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
 
 obj-$(CONFIG_GCOV_KERNEL) := base.o fs.o gcc_3_4.o
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 0c8d7c0..9017478 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -53,11 +53,10 @@
 /*
  * The timer bases:
  *
- * Note: If we want to add new timer bases, we have to skip the two
- * clock ids captured by the cpu-timers. We do this by holding empty
- * entries rather than doing math adjustment of the clock ids.
- * This ensures that we capture erroneous accesses to these clock ids
- * rather than moving them into the range of valid clock id's.
+ * There are more clockids then hrtimer bases. Thus, we index
+ * into the timer bases by the hrtimer_base_type enum. When trying
+ * to reach a base using a clockid, hrtimer_clockid_to_base()
+ * is used to convert from clockid to the proper hrtimer_base_type.
  */
 DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
@@ -74,30 +73,39 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 			.get_time = &ktime_get,
 			.resolution = KTIME_LOW_RES,
 		},
+		{
+			.index = CLOCK_BOOTTIME,
+			.get_time = &ktime_get_boottime,
+			.resolution = KTIME_LOW_RES,
+		},
 	}
 };
 
+static int hrtimer_clock_to_base_table[MAX_CLOCKS];
+
+static inline int hrtimer_clockid_to_base(clockid_t clock_id)
+{
+	return hrtimer_clock_to_base_table[clock_id];
+}
+
+
 /*
  * Get the coarse grained time at the softirq based on xtime and
  * wall_to_monotonic.
  */
 static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
 {
-	ktime_t xtim, tomono;
-	struct timespec xts, tom;
-	unsigned long seq;
+	ktime_t xtim, mono, boot;
+	struct timespec xts, tom, slp;
 
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		xts = __current_kernel_time();
-		tom = __get_wall_to_monotonic();
-	} while (read_seqretry(&xtime_lock, seq));
+	get_xtime_and_monotonic_and_sleep_offset(&xts, &tom, &slp);
 
 	xtim = timespec_to_ktime(xts);
-	tomono = timespec_to_ktime(tom);
-	base->clock_base[CLOCK_REALTIME].softirq_time = xtim;
-	base->clock_base[CLOCK_MONOTONIC].softirq_time =
-		ktime_add(xtim, tomono);
+	mono = ktime_add(xtim, timespec_to_ktime(tom));
+	boot = ktime_add(mono, timespec_to_ktime(slp));
+	base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim;
+	base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono;
+	base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot;
 }
 
 /*
@@ -184,10 +192,11 @@ switch_hrtimer_base(struct hrtimer *timer, struct hrtimer_clock_base *base,
 	struct hrtimer_cpu_base *new_cpu_base;
 	int this_cpu = smp_processor_id();
 	int cpu = hrtimer_get_target(this_cpu, pinned);
+	int basenum = hrtimer_clockid_to_base(base->index);
 
 again:
 	new_cpu_base = &per_cpu(hrtimer_bases, cpu);
-	new_base = &new_cpu_base->clock_base[base->index];
+	new_base = &new_cpu_base->clock_base[basenum];
 
 	if (base != new_base) {
 		/*
@@ -334,6 +343,11 @@ EXPORT_SYMBOL_GPL(ktime_add_safe);
 
 static struct debug_obj_descr hrtimer_debug_descr;
 
+static void *hrtimer_debug_hint(void *addr)
+{
+	return ((struct hrtimer *) addr)->function;
+}
+
 /*
  * fixup_init is called when:
  * - an active object is initialized
@@ -393,6 +407,7 @@ static int hrtimer_fixup_free(void *addr, enum debug_obj_state state)
 
 static struct debug_obj_descr hrtimer_debug_descr = {
 	.name		= "hrtimer",
+	.debug_hint	= hrtimer_debug_hint,
 	.fixup_init	= hrtimer_fixup_init,
 	.fixup_activate	= hrtimer_fixup_activate,
 	.fixup_free	= hrtimer_fixup_free,
@@ -611,24 +626,23 @@ static int hrtimer_reprogram(struct hrtimer *timer,
 static void retrigger_next_event(void *arg)
 {
 	struct hrtimer_cpu_base *base;
-	struct timespec realtime_offset, wtm;
-	unsigned long seq;
+	struct timespec realtime_offset, wtm, sleep;
 
 	if (!hrtimer_hres_active())
 		return;
 
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		wtm = __get_wall_to_monotonic();
-	} while (read_seqretry(&xtime_lock, seq));
+	get_xtime_and_monotonic_and_sleep_offset(&realtime_offset, &wtm,
+							&sleep);
 	set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec);
 
 	base = &__get_cpu_var(hrtimer_bases);
 
 	/* Adjust CLOCK_REALTIME offset */
 	raw_spin_lock(&base->lock);
-	base->clock_base[CLOCK_REALTIME].offset =
+	base->clock_base[HRTIMER_BASE_REALTIME].offset =
 		timespec_to_ktime(realtime_offset);
+	base->clock_base[HRTIMER_BASE_BOOTTIME].offset =
+		timespec_to_ktime(sleep);
 
 	hrtimer_force_reprogram(base, 0);
 	raw_spin_unlock(&base->lock);
@@ -673,14 +687,6 @@ static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base)
 }
 
 /*
- * Initialize the high resolution related parts of a hrtimer
- */
-static inline void hrtimer_init_timer_hres(struct hrtimer *timer)
-{
-}
-
-
-/*
  * When High resolution timers are active, try to reprogram. Note, that in case
  * the state has HRTIMER_STATE_CALLBACK set, no reprogramming and no expiry
  * check happens. The timer gets enqueued into the rbtree. The reprogramming
@@ -725,8 +731,9 @@ static int hrtimer_switch_to_hres(void)
 		return 0;
 	}
 	base->hres_active = 1;
-	base->clock_base[CLOCK_REALTIME].resolution = KTIME_HIGH_RES;
-	base->clock_base[CLOCK_MONOTONIC].resolution = KTIME_HIGH_RES;
+	base->clock_base[HRTIMER_BASE_REALTIME].resolution = KTIME_HIGH_RES;
+	base->clock_base[HRTIMER_BASE_MONOTONIC].resolution = KTIME_HIGH_RES;
+	base->clock_base[HRTIMER_BASE_BOOTTIME].resolution = KTIME_HIGH_RES;
 
 	tick_setup_sched_timer();
 
@@ -750,7 +757,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
 	return 0;
 }
 static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { }
-static inline void hrtimer_init_timer_hres(struct hrtimer *timer) { }
 
 #endif /* CONFIG_HIGH_RES_TIMERS */
 
@@ -1121,6 +1127,7 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
 			   enum hrtimer_mode mode)
 {
 	struct hrtimer_cpu_base *cpu_base;
+	int base;
 
 	memset(timer, 0, sizeof(struct hrtimer));
 
@@ -1129,8 +1136,8 @@ static void __hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
 	if (clock_id == CLOCK_REALTIME && mode != HRTIMER_MODE_ABS)
 		clock_id = CLOCK_MONOTONIC;
 
-	timer->base = &cpu_base->clock_base[clock_id];
-	hrtimer_init_timer_hres(timer);
+	base = hrtimer_clockid_to_base(clock_id);
+	timer->base = &cpu_base->clock_base[base];
 	timerqueue_init(&timer->node);
 
 #ifdef CONFIG_TIMER_STATS
@@ -1165,9 +1172,10 @@ EXPORT_SYMBOL_GPL(hrtimer_init);
 int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
 {
 	struct hrtimer_cpu_base *cpu_base;
+	int base = hrtimer_clockid_to_base(which_clock);
 
 	cpu_base = &__raw_get_cpu_var(hrtimer_bases);
-	*tp = ktime_to_timespec(cpu_base->clock_base[which_clock].resolution);
+	*tp = ktime_to_timespec(cpu_base->clock_base[base].resolution);
 
 	return 0;
 }
@@ -1714,6 +1722,10 @@ static struct notifier_block __cpuinitdata hrtimers_nb = {
 
 void __init hrtimers_init(void)
 {
+	hrtimer_clock_to_base_table[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME;
+	hrtimer_clock_to_base_table[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC;
+	hrtimer_clock_to_base_table[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME;
+
 	hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
 			  (void *)(long)smp_processor_id());
 	register_cpu_notifier(&hrtimers_nb);
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 8e42fec..09bef82 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -1,5 +1,6 @@
+# Select this to activate the generic irq options below
 config HAVE_GENERIC_HARDIRQS
-	def_bool n
+	bool
 
 if HAVE_GENERIC_HARDIRQS
 menu "IRQ subsystem"
@@ -11,26 +12,44 @@ config GENERIC_HARDIRQS
 
 # Select this to disable the deprecated stuff
 config GENERIC_HARDIRQS_NO_DEPRECATED
-       def_bool n
+       bool
+
+config GENERIC_HARDIRQS_NO_COMPAT
+       bool
 
 # Options selectable by the architecture code
+
+# Make sparse irq Kconfig switch below available
 config HAVE_SPARSE_IRQ
-       def_bool n
+       bool
 
+# Enable the generic irq autoprobe mechanism
 config GENERIC_IRQ_PROBE
-	def_bool n
+	bool
+
+# Use the generic /proc/interrupts implementation
+config GENERIC_IRQ_SHOW
+       bool
 
+# Support for delayed migration from interrupt context
 config GENERIC_PENDING_IRQ
-	def_bool n
+	bool
 
+# Alpha specific irq affinity mechanism
 config AUTO_IRQ_AFFINITY
-       def_bool n
-
-config IRQ_PER_CPU
-       def_bool n
+       bool
 
+# Tasklet based software resend for pending interrupts on enable_irq()
 config HARDIRQS_SW_RESEND
-       def_bool n
+       bool
+
+# Preflow handler support for fasteoi (sparc64)
+config IRQ_PREFLOW_FASTEOI
+       bool
+
+# Support forced irq threading
+config IRQ_FORCED_THREADING
+       bool
 
 config SPARSE_IRQ
 	bool "Support sparse irq numbering"
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c
index 505798f..394784c 100644
--- a/kernel/irq/autoprobe.c
+++ b/kernel/irq/autoprobe.c
@@ -17,7 +17,7 @@
 /*
  * Autodetection depends on the fact that any interrupt that
  * comes in on to an unassigned handler will get stuck with
- * "IRQ_WAITING" cleared and the interrupt disabled.
+ * "IRQS_WAITING" cleared and the interrupt disabled.
  */
 static DEFINE_MUTEX(probing_active);
 
@@ -32,7 +32,6 @@ unsigned long probe_irq_on(void)
 {
 	struct irq_desc *desc;
 	unsigned long mask = 0;
-	unsigned int status;
 	int i;
 
 	/*
@@ -46,13 +45,7 @@ unsigned long probe_irq_on(void)
 	 */
 	for_each_irq_desc_reverse(i, desc) {
 		raw_spin_lock_irq(&desc->lock);
-		if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
-			/*
-			 * An old-style architecture might still have
-			 * the handle_bad_irq handler there:
-			 */
-			compat_irq_chip_set_default_handler(desc);
-
+		if (!desc->action && irq_settings_can_probe(desc)) {
 			/*
 			 * Some chips need to know about probing in
 			 * progress:
@@ -60,7 +53,7 @@ unsigned long probe_irq_on(void)
 			if (desc->irq_data.chip->irq_set_type)
 				desc->irq_data.chip->irq_set_type(&desc->irq_data,
 							 IRQ_TYPE_PROBE);
-			desc->irq_data.chip->irq_startup(&desc->irq_data);
+			irq_startup(desc);
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
@@ -75,10 +68,12 @@ unsigned long probe_irq_on(void)
 	 */
 	for_each_irq_desc_reverse(i, desc) {
 		raw_spin_lock_irq(&desc->lock);
-		if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
-			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
-			if (desc->irq_data.chip->irq_startup(&desc->irq_data))
-				desc->status |= IRQ_PENDING;
+		if (!desc->action && irq_settings_can_probe(desc)) {
+			desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
+			if (irq_startup(desc)) {
+				irq_compat_set_pending(desc);
+				desc->istate |= IRQS_PENDING;
+			}
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
@@ -93,13 +88,12 @@ unsigned long probe_irq_on(void)
 	 */
 	for_each_irq_desc(i, desc) {
 		raw_spin_lock_irq(&desc->lock);
-		status = desc->status;
 
-		if (status & IRQ_AUTODETECT) {
+		if (desc->istate & IRQS_AUTODETECT) {
 			/* It triggered already - consider it spurious. */
-			if (!(status & IRQ_WAITING)) {
-				desc->status = status & ~IRQ_AUTODETECT;
-				desc->irq_data.chip->irq_shutdown(&desc->irq_data);
+			if (!(desc->istate & IRQS_WAITING)) {
+				desc->istate &= ~IRQS_AUTODETECT;
+				irq_shutdown(desc);
 			} else
 				if (i < 32)
 					mask |= 1 << i;
@@ -125,20 +119,18 @@ EXPORT_SYMBOL(probe_irq_on);
  */
 unsigned int probe_irq_mask(unsigned long val)
 {
-	unsigned int status, mask = 0;
+	unsigned int mask = 0;
 	struct irq_desc *desc;
 	int i;
 
 	for_each_irq_desc(i, desc) {
 		raw_spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			if (i < 16 && !(status & IRQ_WAITING))
+		if (desc->istate & IRQS_AUTODETECT) {
+			if (i < 16 && !(desc->istate & IRQS_WAITING))
 				mask |= 1 << i;
 
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->irq_data.chip->irq_shutdown(&desc->irq_data);
+			desc->istate &= ~IRQS_AUTODETECT;
+			irq_shutdown(desc);
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
@@ -169,20 +161,18 @@ int probe_irq_off(unsigned long val)
 {
 	int i, irq_found = 0, nr_of_irqs = 0;
 	struct irq_desc *desc;
-	unsigned int status;
 
 	for_each_irq_desc(i, desc) {
 		raw_spin_lock_irq(&desc->lock);
-		status = desc->status;
 
-		if (status & IRQ_AUTODETECT) {
-			if (!(status & IRQ_WAITING)) {
+		if (desc->istate & IRQS_AUTODETECT) {
+			if (!(desc->istate & IRQS_WAITING)) {
 				if (!nr_of_irqs)
 					irq_found = i;
 				nr_of_irqs++;
 			}
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->irq_data.chip->irq_shutdown(&desc->irq_data);
+			desc->istate &= ~IRQS_AUTODETECT;
+			irq_shutdown(desc);
 		}
 		raw_spin_unlock_irq(&desc->lock);
 	}
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index baa5c4a..c9c0601 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -19,140 +19,110 @@
 #include "internals.h"
 
 /**
- *	set_irq_chip - set the irq chip for an irq
+ *	irq_set_chip - set the irq chip for an irq
  *	@irq:	irq number
  *	@chip:	pointer to irq chip description structure
  */
-int set_irq_chip(unsigned int irq, struct irq_chip *chip)
+int irq_set_chip(unsigned int irq, struct irq_chip *chip)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
 
-	if (!desc) {
-		WARN(1, KERN_ERR "Trying to install chip for IRQ%d\n", irq);
+	if (!desc)
 		return -EINVAL;
-	}
 
 	if (!chip)
 		chip = &no_irq_chip;
 
-	raw_spin_lock_irqsave(&desc->lock, flags);
 	irq_chip_set_defaults(chip);
 	desc->irq_data.chip = chip;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-
+	irq_put_desc_unlock(desc, flags);
 	return 0;
 }
-EXPORT_SYMBOL(set_irq_chip);
+EXPORT_SYMBOL(irq_set_chip);
 
 /**
- *	set_irq_type - set the irq trigger type for an irq
+ *	irq_set_type - set the irq trigger type for an irq
  *	@irq:	irq number
  *	@type:	IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
  */
-int set_irq_type(unsigned int irq, unsigned int type)
+int irq_set_irq_type(unsigned int irq, unsigned int type)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
-	int ret = -ENXIO;
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+	int ret = 0;
 
-	if (!desc) {
-		printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq);
-		return -ENODEV;
-	}
+	if (!desc)
+		return -EINVAL;
 
 	type &= IRQ_TYPE_SENSE_MASK;
-	if (type == IRQ_TYPE_NONE)
-		return 0;
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	ret = __irq_set_trigger(desc, irq, type);
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	if (type != IRQ_TYPE_NONE)
+		ret = __irq_set_trigger(desc, irq, type);
+	irq_put_desc_busunlock(desc, flags);
 	return ret;
 }
-EXPORT_SYMBOL(set_irq_type);
+EXPORT_SYMBOL(irq_set_irq_type);
 
 /**
- *	set_irq_data - set irq type data for an irq
+ *	irq_set_handler_data - set irq handler data for an irq
  *	@irq:	Interrupt number
  *	@data:	Pointer to interrupt specific data
  *
  *	Set the hardware irq controller data for an irq
  */
-int set_irq_data(unsigned int irq, void *data)
+int irq_set_handler_data(unsigned int irq, void *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
 
-	if (!desc) {
-		printk(KERN_ERR
-		       "Trying to install controller data for IRQ%d\n", irq);
+	if (!desc)
 		return -EINVAL;
-	}
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
 	desc->irq_data.handler_data = data;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	irq_put_desc_unlock(desc, flags);
 	return 0;
 }
-EXPORT_SYMBOL(set_irq_data);
+EXPORT_SYMBOL(irq_set_handler_data);
 
 /**
- *	set_irq_msi - set MSI descriptor data for an irq
+ *	irq_set_msi_desc - set MSI descriptor data for an irq
  *	@irq:	Interrupt number
  *	@entry:	Pointer to MSI descriptor data
  *
  *	Set the MSI descriptor entry for an irq
  */
-int set_irq_msi(unsigned int irq, struct msi_desc *entry)
+int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
 
-	if (!desc) {
-		printk(KERN_ERR
-		       "Trying to install msi data for IRQ%d\n", irq);
+	if (!desc)
 		return -EINVAL;
-	}
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
 	desc->irq_data.msi_desc = entry;
 	if (entry)
 		entry->irq = irq;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	irq_put_desc_unlock(desc, flags);
 	return 0;
 }
 
 /**
- *	set_irq_chip_data - set irq chip data for an irq
+ *	irq_set_chip_data - set irq chip data for an irq
  *	@irq:	Interrupt number
  *	@data:	Pointer to chip specific data
  *
  *	Set the hardware irq chip data for an irq
  */
-int set_irq_chip_data(unsigned int irq, void *data)
+int irq_set_chip_data(unsigned int irq, void *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
 
-	if (!desc) {
-		printk(KERN_ERR
-		       "Trying to install chip data for IRQ%d\n", irq);
-		return -EINVAL;
-	}
-
-	if (!desc->irq_data.chip) {
-		printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq);
+	if (!desc)
 		return -EINVAL;
-	}
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
 	desc->irq_data.chip_data = data;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-
+	irq_put_desc_unlock(desc, flags);
 	return 0;
 }
-EXPORT_SYMBOL(set_irq_chip_data);
+EXPORT_SYMBOL(irq_set_chip_data);
 
 struct irq_data *irq_get_irq_data(unsigned int irq)
 {
@@ -162,72 +132,75 @@ struct irq_data *irq_get_irq_data(unsigned int irq)
 }
 EXPORT_SYMBOL_GPL(irq_get_irq_data);
 
-/**
- *	set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq
- *
- *	@irq:	Interrupt number
- *	@nest:	0 to clear / 1 to set the IRQ_NESTED_THREAD flag
- *
- *	The IRQ_NESTED_THREAD flag indicates that on
- *	request_threaded_irq() no separate interrupt thread should be
- *	created for the irq as the handler are called nested in the
- *	context of a demultiplexing interrupt handler thread.
- */
-void set_irq_nested_thread(unsigned int irq, int nest)
+static void irq_state_clr_disabled(struct irq_desc *desc)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	unsigned long flags;
-
-	if (!desc)
-		return;
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	if (nest)
-		desc->status |= IRQ_NESTED_THREAD;
-	else
-		desc->status &= ~IRQ_NESTED_THREAD;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	desc->istate &= ~IRQS_DISABLED;
+	irq_compat_clr_disabled(desc);
 }
-EXPORT_SYMBOL_GPL(set_irq_nested_thread);
 
-/*
- * default enable function
- */
-static void default_enable(struct irq_data *data)
+static void irq_state_set_disabled(struct irq_desc *desc)
 {
-	struct irq_desc *desc = irq_data_to_desc(data);
+	desc->istate |= IRQS_DISABLED;
+	irq_compat_set_disabled(desc);
+}
 
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-	desc->status &= ~IRQ_MASKED;
+static void irq_state_clr_masked(struct irq_desc *desc)
+{
+	desc->istate &= ~IRQS_MASKED;
+	irq_compat_clr_masked(desc);
 }
 
-/*
- * default disable function
- */
-static void default_disable(struct irq_data *data)
+static void irq_state_set_masked(struct irq_desc *desc)
 {
+	desc->istate |= IRQS_MASKED;
+	irq_compat_set_masked(desc);
 }
 
-/*
- * default startup function
- */
-static unsigned int default_startup(struct irq_data *data)
+int irq_startup(struct irq_desc *desc)
 {
-	struct irq_desc *desc = irq_data_to_desc(data);
+	irq_state_clr_disabled(desc);
+	desc->depth = 0;
+
+	if (desc->irq_data.chip->irq_startup) {
+		int ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
+		irq_state_clr_masked(desc);
+		return ret;
+	}
 
-	desc->irq_data.chip->irq_enable(data);
+	irq_enable(desc);
 	return 0;
 }
 
-/*
- * default shutdown function
- */
-static void default_shutdown(struct irq_data *data)
+void irq_shutdown(struct irq_desc *desc)
 {
-	struct irq_desc *desc = irq_data_to_desc(data);
+	irq_state_set_disabled(desc);
+	desc->depth = 1;
+	if (desc->irq_data.chip->irq_shutdown)
+		desc->irq_data.chip->irq_shutdown(&desc->irq_data);
+	if (desc->irq_data.chip->irq_disable)
+		desc->irq_data.chip->irq_disable(&desc->irq_data);
+	else
+		desc->irq_data.chip->irq_mask(&desc->irq_data);
+	irq_state_set_masked(desc);
+}
 
-	desc->irq_data.chip->irq_mask(&desc->irq_data);
-	desc->status |= IRQ_MASKED;
+void irq_enable(struct irq_desc *desc)
+{
+	irq_state_clr_disabled(desc);
+	if (desc->irq_data.chip->irq_enable)
+		desc->irq_data.chip->irq_enable(&desc->irq_data);
+	else
+		desc->irq_data.chip->irq_unmask(&desc->irq_data);
+	irq_state_clr_masked(desc);
+}
+
+void irq_disable(struct irq_desc *desc)
+{
+	irq_state_set_disabled(desc);
+	if (desc->irq_data.chip->irq_disable) {
+		desc->irq_data.chip->irq_disable(&desc->irq_data);
+		irq_state_set_masked(desc);
+	}
 }
 
 #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
@@ -315,10 +288,6 @@ static void compat_bus_sync_unlock(struct irq_data *data)
 void irq_chip_set_defaults(struct irq_chip *chip)
 {
 #ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
-	/*
-	 * Compat fixup functions need to be before we set the
-	 * defaults for enable/disable/startup/shutdown
-	 */
 	if (chip->enable)
 		chip->irq_enable = compat_irq_enable;
 	if (chip->disable)
@@ -327,33 +296,8 @@ void irq_chip_set_defaults(struct irq_chip *chip)
 		chip->irq_shutdown = compat_irq_shutdown;
 	if (chip->startup)
 		chip->irq_startup = compat_irq_startup;
-#endif
-	/*
-	 * The real defaults
-	 */
-	if (!chip->irq_enable)
-		chip->irq_enable = default_enable;
-	if (!chip->irq_disable)
-		chip->irq_disable = default_disable;
-	if (!chip->irq_startup)
-		chip->irq_startup = default_startup;
-	/*
-	 * We use chip->irq_disable, when the user provided its own. When
-	 * we have default_disable set for chip->irq_disable, then we need
-	 * to use default_shutdown, otherwise the irq line is not
-	 * disabled on free_irq():
-	 */
-	if (!chip->irq_shutdown)
-		chip->irq_shutdown = chip->irq_disable != default_disable ?
-			chip->irq_disable : default_shutdown;
-
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
 	if (!chip->end)
 		chip->end = dummy_irq_chip.end;
-
-	/*
-	 * Now fix up the remaining compat handlers
-	 */
 	if (chip->bus_lock)
 		chip->irq_bus_lock = compat_bus_lock;
 	if (chip->bus_sync_unlock)
@@ -388,22 +332,22 @@ static inline void mask_ack_irq(struct irq_desc *desc)
 		if (desc->irq_data.chip->irq_ack)
 			desc->irq_data.chip->irq_ack(&desc->irq_data);
 	}
-	desc->status |= IRQ_MASKED;
+	irq_state_set_masked(desc);
 }
 
-static inline void mask_irq(struct irq_desc *desc)
+void mask_irq(struct irq_desc *desc)
 {
 	if (desc->irq_data.chip->irq_mask) {
 		desc->irq_data.chip->irq_mask(&desc->irq_data);
-		desc->status |= IRQ_MASKED;
+		irq_state_set_masked(desc);
 	}
 }
 
-static inline void unmask_irq(struct irq_desc *desc)
+void unmask_irq(struct irq_desc *desc)
 {
 	if (desc->irq_data.chip->irq_unmask) {
 		desc->irq_data.chip->irq_unmask(&desc->irq_data);
-		desc->status &= ~IRQ_MASKED;
+		irq_state_clr_masked(desc);
 	}
 }
 
@@ -428,10 +372,11 @@ void handle_nested_irq(unsigned int irq)
 	kstat_incr_irqs_this_cpu(irq, desc);
 
 	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+	if (unlikely(!action || (desc->istate & IRQS_DISABLED)))
 		goto out_unlock;
 
-	desc->status |= IRQ_INPROGRESS;
+	irq_compat_set_progress(desc);
+	desc->istate |= IRQS_INPROGRESS;
 	raw_spin_unlock_irq(&desc->lock);
 
 	action_ret = action->thread_fn(action->irq, action->dev_id);
@@ -439,13 +384,21 @@ void handle_nested_irq(unsigned int irq)
 		note_interrupt(irq, desc, action_ret);
 
 	raw_spin_lock_irq(&desc->lock);
-	desc->status &= ~IRQ_INPROGRESS;
+	desc->istate &= ~IRQS_INPROGRESS;
+	irq_compat_clr_progress(desc);
 
 out_unlock:
 	raw_spin_unlock_irq(&desc->lock);
 }
 EXPORT_SYMBOL_GPL(handle_nested_irq);
 
+static bool irq_check_poll(struct irq_desc *desc)
+{
+	if (!(desc->istate & IRQS_POLL_INPROGRESS))
+		return false;
+	return irq_wait_for_poll(desc);
+}
+
 /**
  *	handle_simple_irq - Simple and software-decoded IRQs.
  *	@irq:	the interrupt number
@@ -461,29 +414,20 @@ EXPORT_SYMBOL_GPL(handle_nested_irq);
 void
 handle_simple_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct irqaction *action;
-	irqreturn_t action_ret;
-
 	raw_spin_lock(&desc->lock);
 
-	if (unlikely(desc->status & IRQ_INPROGRESS))
-		goto out_unlock;
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+	if (unlikely(desc->istate & IRQS_INPROGRESS))
+		if (!irq_check_poll(desc))
+			goto out_unlock;
+
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
 	kstat_incr_irqs_this_cpu(irq, desc);
 
-	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+	if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED)))
 		goto out_unlock;
 
-	desc->status |= IRQ_INPROGRESS;
-	raw_spin_unlock(&desc->lock);
+	handle_irq_event(desc);
 
-	action_ret = handle_IRQ_event(irq, action);
-	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret);
-
-	raw_spin_lock(&desc->lock);
-	desc->status &= ~IRQ_INPROGRESS;
 out_unlock:
 	raw_spin_unlock(&desc->lock);
 }
@@ -501,42 +445,42 @@ out_unlock:
 void
 handle_level_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct irqaction *action;
-	irqreturn_t action_ret;
-
 	raw_spin_lock(&desc->lock);
 	mask_ack_irq(desc);
 
-	if (unlikely(desc->status & IRQ_INPROGRESS))
-		goto out_unlock;
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+	if (unlikely(desc->istate & IRQS_INPROGRESS))
+		if (!irq_check_poll(desc))
+			goto out_unlock;
+
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
 	kstat_incr_irqs_this_cpu(irq, desc);
 
 	/*
 	 * If its disabled or no action available
 	 * keep it masked and get out of here
 	 */
-	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+	if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED)))
 		goto out_unlock;
 
-	desc->status |= IRQ_INPROGRESS;
-	raw_spin_unlock(&desc->lock);
-
-	action_ret = handle_IRQ_event(irq, action);
-	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret);
+	handle_irq_event(desc);
 
-	raw_spin_lock(&desc->lock);
-	desc->status &= ~IRQ_INPROGRESS;
-
-	if (!(desc->status & (IRQ_DISABLED | IRQ_ONESHOT)))
+	if (!(desc->istate & (IRQS_DISABLED | IRQS_ONESHOT)))
 		unmask_irq(desc);
 out_unlock:
 	raw_spin_unlock(&desc->lock);
 }
 EXPORT_SYMBOL_GPL(handle_level_irq);
 
+#ifdef CONFIG_IRQ_PREFLOW_FASTEOI
+static inline void preflow_handler(struct irq_desc *desc)
+{
+	if (desc->preflow_handler)
+		desc->preflow_handler(&desc->irq_data);
+}
+#else
+static inline void preflow_handler(struct irq_desc *desc) { }
+#endif
+
 /**
  *	handle_fasteoi_irq - irq handler for transparent controllers
  *	@irq:	the interrupt number
@@ -550,42 +494,41 @@ EXPORT_SYMBOL_GPL(handle_level_irq);
 void
 handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct irqaction *action;
-	irqreturn_t action_ret;
-
 	raw_spin_lock(&desc->lock);
 
-	if (unlikely(desc->status & IRQ_INPROGRESS))
-		goto out;
+	if (unlikely(desc->istate & IRQS_INPROGRESS))
+		if (!irq_check_poll(desc))
+			goto out;
 
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
 	kstat_incr_irqs_this_cpu(irq, desc);
 
 	/*
 	 * If its disabled or no action available
 	 * then mask it and get out of here:
 	 */
-	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
-		desc->status |= IRQ_PENDING;
+	if (unlikely(!desc->action || (desc->istate & IRQS_DISABLED))) {
+		irq_compat_set_pending(desc);
+		desc->istate |= IRQS_PENDING;
 		mask_irq(desc);
 		goto out;
 	}
 
-	desc->status |= IRQ_INPROGRESS;
-	desc->status &= ~IRQ_PENDING;
-	raw_spin_unlock(&desc->lock);
+	if (desc->istate & IRQS_ONESHOT)
+		mask_irq(desc);
 
-	action_ret = handle_IRQ_event(irq, action);
-	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret);
+	preflow_handler(desc);
+	handle_irq_event(desc);
 
-	raw_spin_lock(&desc->lock);
-	desc->status &= ~IRQ_INPROGRESS;
-out:
+out_eoi:
 	desc->irq_data.chip->irq_eoi(&desc->irq_data);
-
+out_unlock:
 	raw_spin_unlock(&desc->lock);
+	return;
+out:
+	if (!(desc->irq_data.chip->flags & IRQCHIP_EOI_IF_HANDLED))
+		goto out_eoi;
+	goto out_unlock;
 }
 
 /**
@@ -609,32 +552,28 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
 {
 	raw_spin_lock(&desc->lock);
 
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-
+	desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
 	/*
 	 * If we're currently running this IRQ, or its disabled,
 	 * we shouldn't process the IRQ. Mark it pending, handle
 	 * the necessary masking and go out
 	 */
-	if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
-		    !desc->action)) {
-		desc->status |= (IRQ_PENDING | IRQ_MASKED);
-		mask_ack_irq(desc);
-		goto out_unlock;
+	if (unlikely((desc->istate & (IRQS_DISABLED | IRQS_INPROGRESS) ||
+		      !desc->action))) {
+		if (!irq_check_poll(desc)) {
+			irq_compat_set_pending(desc);
+			desc->istate |= IRQS_PENDING;
+			mask_ack_irq(desc);
+			goto out_unlock;
+		}
 	}
 	kstat_incr_irqs_this_cpu(irq, desc);
 
 	/* Start handling the irq */
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-	/* Mark the IRQ currently in progress.*/
-	desc->status |= IRQ_INPROGRESS;
-
 	do {
-		struct irqaction *action = desc->action;
-		irqreturn_t action_ret;
-
-		if (unlikely(!action)) {
+		if (unlikely(!desc->action)) {
 			mask_irq(desc);
 			goto out_unlock;
 		}
@@ -644,22 +583,17 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
 		 * one, we could have masked the irq.
 		 * Renable it, if it was not disabled in meantime.
 		 */
-		if (unlikely((desc->status &
-			       (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
-			      (IRQ_PENDING | IRQ_MASKED))) {
-			unmask_irq(desc);
+		if (unlikely(desc->istate & IRQS_PENDING)) {
+			if (!(desc->istate & IRQS_DISABLED) &&
+			    (desc->istate & IRQS_MASKED))
+				unmask_irq(desc);
 		}
 
-		desc->status &= ~IRQ_PENDING;
-		raw_spin_unlock(&desc->lock);
-		action_ret = handle_IRQ_event(irq, action);
-		if (!noirqdebug)
-			note_interrupt(irq, desc, action_ret);
-		raw_spin_lock(&desc->lock);
+		handle_irq_event(desc);
 
-	} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
+	} while ((desc->istate & IRQS_PENDING) &&
+		 !(desc->istate & IRQS_DISABLED));
 
-	desc->status &= ~IRQ_INPROGRESS;
 out_unlock:
 	raw_spin_unlock(&desc->lock);
 }
@@ -674,103 +608,84 @@ out_unlock:
 void
 handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
 {
-	irqreturn_t action_ret;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 
 	kstat_incr_irqs_this_cpu(irq, desc);
 
-	if (desc->irq_data.chip->irq_ack)
-		desc->irq_data.chip->irq_ack(&desc->irq_data);
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
 
-	action_ret = handle_IRQ_event(irq, desc->action);
-	if (!noirqdebug)
-		note_interrupt(irq, desc, action_ret);
+	handle_irq_event_percpu(desc, desc->action);
 
-	if (desc->irq_data.chip->irq_eoi)
-		desc->irq_data.chip->irq_eoi(&desc->irq_data);
+	if (chip->irq_eoi)
+		chip->irq_eoi(&desc->irq_data);
 }
 
 void
-__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
 		  const char *name)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
 
-	if (!desc) {
-		printk(KERN_ERR
-		       "Trying to install type control for IRQ%d\n", irq);
+	if (!desc)
 		return;
-	}
 
-	if (!handle)
+	if (!handle) {
 		handle = handle_bad_irq;
-	else if (desc->irq_data.chip == &no_irq_chip) {
-		printk(KERN_WARNING "Trying to install %sinterrupt handler "
-		       "for IRQ%d\n", is_chained ? "chained " : "", irq);
-		/*
-		 * Some ARM implementations install a handler for really dumb
-		 * interrupt hardware without setting an irq_chip. This worked
-		 * with the ARM no_irq_chip but the check in setup_irq would
-		 * prevent us to setup the interrupt at all. Switch it to
-		 * dummy_irq_chip for easy transition.
-		 */
-		desc->irq_data.chip = &dummy_irq_chip;
+	} else {
+		if (WARN_ON(desc->irq_data.chip == &no_irq_chip))
+			goto out;
 	}
 
-	chip_bus_lock(desc);
-	raw_spin_lock_irqsave(&desc->lock, flags);
-
 	/* Uninstall? */
 	if (handle == handle_bad_irq) {
 		if (desc->irq_data.chip != &no_irq_chip)
 			mask_ack_irq(desc);
-		desc->status |= IRQ_DISABLED;
+		irq_compat_set_disabled(desc);
+		desc->istate |= IRQS_DISABLED;
 		desc->depth = 1;
 	}
 	desc->handle_irq = handle;
 	desc->name = name;
 
 	if (handle != handle_bad_irq && is_chained) {
-		desc->status &= ~IRQ_DISABLED;
-		desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE;
-		desc->depth = 0;
-		desc->irq_data.chip->irq_startup(&desc->irq_data);
+		irq_settings_set_noprobe(desc);
+		irq_settings_set_norequest(desc);
+		irq_startup(desc);
 	}
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	chip_bus_sync_unlock(desc);
-}
-EXPORT_SYMBOL_GPL(__set_irq_handler);
-
-void
-set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
-			 irq_flow_handler_t handle)
-{
-	set_irq_chip(irq, chip);
-	__set_irq_handler(irq, handle, 0, NULL);
+out:
+	irq_put_desc_busunlock(desc, flags);
 }
+EXPORT_SYMBOL_GPL(__irq_set_handler);
 
 void
-set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
+irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,
 			      irq_flow_handler_t handle, const char *name)
 {
-	set_irq_chip(irq, chip);
-	__set_irq_handler(irq, handle, 0, name);
+	irq_set_chip(irq, chip);
+	__irq_set_handler(irq, handle, 0, name);
 }
 
 void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
 
 	if (!desc)
 		return;
+	irq_settings_clr_and_set(desc, clr, set);
+
+	irqd_clear(&desc->irq_data, IRQD_NO_BALANCING | IRQD_PER_CPU |
+		   IRQD_TRIGGER_MASK | IRQD_LEVEL | IRQD_MOVE_PCNTXT);
+	if (irq_settings_has_no_balance_set(desc))
+		irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
+	if (irq_settings_is_per_cpu(desc))
+		irqd_set(&desc->irq_data, IRQD_PER_CPU);
+	if (irq_settings_can_move_pcntxt(desc))
+		irqd_set(&desc->irq_data, IRQD_MOVE_PCNTXT);
 
-	/* Sanitize flags */
-	set &= IRQF_MODIFY_MASK;
-	clr &= IRQF_MODIFY_MASK;
+	irqd_set(&desc->irq_data, irq_settings_get_trigger_mask(desc));
 
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->status &= ~clr;
-	desc->status |= set;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	irq_put_desc_unlock(desc, flags);
 }
diff --git a/kernel/irq/compat.h b/kernel/irq/compat.h
new file mode 100644
index 0000000..6bbaf66
--- /dev/null
+++ b/kernel/irq/compat.h
@@ -0,0 +1,72 @@
+/*
+ * Compat layer for transition period
+ */
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+static inline void irq_compat_set_progress(struct irq_desc *desc)
+{
+	desc->status |= IRQ_INPROGRESS;
+}
+
+static inline void irq_compat_clr_progress(struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_INPROGRESS;
+}
+static inline void irq_compat_set_disabled(struct irq_desc *desc)
+{
+	desc->status |= IRQ_DISABLED;
+}
+static inline void irq_compat_clr_disabled(struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_DISABLED;
+}
+static inline void irq_compat_set_pending(struct irq_desc *desc)
+{
+	desc->status |= IRQ_PENDING;
+}
+
+static inline void irq_compat_clr_pending(struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_PENDING;
+}
+static inline void irq_compat_set_masked(struct irq_desc *desc)
+{
+	desc->status |= IRQ_MASKED;
+}
+
+static inline void irq_compat_clr_masked(struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_MASKED;
+}
+static inline void irq_compat_set_move_pending(struct irq_desc *desc)
+{
+	desc->status |= IRQ_MOVE_PENDING;
+}
+
+static inline void irq_compat_clr_move_pending(struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_MOVE_PENDING;
+}
+static inline void irq_compat_set_affinity(struct irq_desc *desc)
+{
+	desc->status |= IRQ_AFFINITY_SET;
+}
+
+static inline void irq_compat_clr_affinity(struct irq_desc *desc)
+{
+	desc->status &= ~IRQ_AFFINITY_SET;
+}
+#else
+static inline void irq_compat_set_progress(struct irq_desc *desc) { }
+static inline void irq_compat_clr_progress(struct irq_desc *desc) { }
+static inline void irq_compat_set_disabled(struct irq_desc *desc) { }
+static inline void irq_compat_clr_disabled(struct irq_desc *desc) { }
+static inline void irq_compat_set_pending(struct irq_desc *desc) { }
+static inline void irq_compat_clr_pending(struct irq_desc *desc) { }
+static inline void irq_compat_set_masked(struct irq_desc *desc) { }
+static inline void irq_compat_clr_masked(struct irq_desc *desc) { }
+static inline void irq_compat_set_move_pending(struct irq_desc *desc) { }
+static inline void irq_compat_clr_move_pending(struct irq_desc *desc) { }
+static inline void irq_compat_set_affinity(struct irq_desc *desc) { }
+static inline void irq_compat_clr_affinity(struct irq_desc *desc) { }
+#endif
+
diff --git a/kernel/irq/debug.h b/kernel/irq/debug.h
new file mode 100644
index 0000000..d1a33b7
--- /dev/null
+++ b/kernel/irq/debug.h
@@ -0,0 +1,40 @@
+/*
+ * Debugging printout:
+ */
+
+#include <linux/kallsyms.h>
+
+#define P(f) if (desc->status & f) printk("%14s set\n", #f)
+#define PS(f) if (desc->istate & f) printk("%14s set\n", #f)
+
+static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
+{
+	printk("irq %d, desc: %p, depth: %d, count: %d, unhandled: %d\n",
+		irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled);
+	printk("->handle_irq():  %p, ", desc->handle_irq);
+	print_symbol("%s\n", (unsigned long)desc->handle_irq);
+	printk("->irq_data.chip(): %p, ", desc->irq_data.chip);
+	print_symbol("%s\n", (unsigned long)desc->irq_data.chip);
+	printk("->action(): %p\n", desc->action);
+	if (desc->action) {
+		printk("->action->handler(): %p, ", desc->action->handler);
+		print_symbol("%s\n", (unsigned long)desc->action->handler);
+	}
+
+	P(IRQ_LEVEL);
+	P(IRQ_PER_CPU);
+	P(IRQ_NOPROBE);
+	P(IRQ_NOREQUEST);
+	P(IRQ_NOAUTOEN);
+
+	PS(IRQS_AUTODETECT);
+	PS(IRQS_INPROGRESS);
+	PS(IRQS_REPLAY);
+	PS(IRQS_WAITING);
+	PS(IRQS_DISABLED);
+	PS(IRQS_PENDING);
+	PS(IRQS_MASKED);
+}
+
+#undef P
+#undef PS
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 3540a71..517561f 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -51,30 +51,92 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
 	       "but no thread function available.", irq, action->name);
 }
 
-/**
- * handle_IRQ_event - irq action chain handler
- * @irq:	the interrupt number
- * @action:	the interrupt action chain for this irq
- *
- * Handles the action chain of an irq event
- */
-irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
+static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
+{
+	/*
+	 * Wake up the handler thread for this action. In case the
+	 * thread crashed and was killed we just pretend that we
+	 * handled the interrupt. The hardirq handler has disabled the
+	 * device interrupt, so no irq storm is lurking. If the
+	 * RUNTHREAD bit is already set, nothing to do.
+	 */
+	if (test_bit(IRQTF_DIED, &action->thread_flags) ||
+	    test_and_set_bit(IRQTF_RUNTHREAD, &action->thread_flags))
+		return;
+
+	/*
+	 * It's safe to OR the mask lockless here. We have only two
+	 * places which write to threads_oneshot: This code and the
+	 * irq thread.
+	 *
+	 * This code is the hard irq context and can never run on two
+	 * cpus in parallel. If it ever does we have more serious
+	 * problems than this bitmask.
+	 *
+	 * The irq threads of this irq which clear their "running" bit
+	 * in threads_oneshot are serialized via desc->lock against
+	 * each other and they are serialized against this code by
+	 * IRQS_INPROGRESS.
+	 *
+	 * Hard irq handler:
+	 *
+	 *	spin_lock(desc->lock);
+	 *	desc->state |= IRQS_INPROGRESS;
+	 *	spin_unlock(desc->lock);
+	 *	set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
+	 *	desc->threads_oneshot |= mask;
+	 *	spin_lock(desc->lock);
+	 *	desc->state &= ~IRQS_INPROGRESS;
+	 *	spin_unlock(desc->lock);
+	 *
+	 * irq thread:
+	 *
+	 * again:
+	 *	spin_lock(desc->lock);
+	 *	if (desc->state & IRQS_INPROGRESS) {
+	 *		spin_unlock(desc->lock);
+	 *		while(desc->state & IRQS_INPROGRESS)
+	 *			cpu_relax();
+	 *		goto again;
+	 *	}
+	 *	if (!test_bit(IRQTF_RUNTHREAD, &action->thread_flags))
+	 *		desc->threads_oneshot &= ~mask;
+	 *	spin_unlock(desc->lock);
+	 *
+	 * So either the thread waits for us to clear IRQS_INPROGRESS
+	 * or we are waiting in the flow handler for desc->lock to be
+	 * released before we reach this point. The thread also checks
+	 * IRQTF_RUNTHREAD under desc->lock. If set it leaves
+	 * threads_oneshot untouched and runs the thread another time.
+	 */
+	desc->threads_oneshot |= action->thread_mask;
+	wake_up_process(action->thread);
+}
+
+irqreturn_t
+handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
 {
-	irqreturn_t ret, retval = IRQ_NONE;
-	unsigned int status = 0;
+	irqreturn_t retval = IRQ_NONE;
+	unsigned int random = 0, irq = desc->irq_data.irq;
 
 	do {
+		irqreturn_t res;
+
 		trace_irq_handler_entry(irq, action);
-		ret = action->handler(irq, action->dev_id);
-		trace_irq_handler_exit(irq, action, ret);
+		res = action->handler(irq, action->dev_id);
+		trace_irq_handler_exit(irq, action, res);
 
-		switch (ret) {
+		if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pF enabled interrupts\n",
+			      irq, action->handler))
+			local_irq_disable();
+
+		switch (res) {
 		case IRQ_WAKE_THREAD:
 			/*
 			 * Set result to handled so the spurious check
 			 * does not trigger.
 			 */
-			ret = IRQ_HANDLED;
+			res = IRQ_HANDLED;
 
 			/*
 			 * Catch drivers which return WAKE_THREAD but
@@ -85,36 +147,56 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
 				break;
 			}
 
-			/*
-			 * Wake up the handler thread for this
-			 * action. In case the thread crashed and was
-			 * killed we just pretend that we handled the
-			 * interrupt. The hardirq handler above has
-			 * disabled the device interrupt, so no irq
-			 * storm is lurking.
-			 */
-			if (likely(!test_bit(IRQTF_DIED,
-					     &action->thread_flags))) {
-				set_bit(IRQTF_RUNTHREAD, &action->thread_flags);
-				wake_up_process(action->thread);
-			}
+			irq_wake_thread(desc, action);
 
 			/* Fall through to add to randomness */
 		case IRQ_HANDLED:
-			status |= action->flags;
+			random |= action->flags;
 			break;
 
 		default:
 			break;
 		}
 
-		retval |= ret;
+		retval |= res;
 		action = action->next;
 	} while (action);
 
-	if (status & IRQF_SAMPLE_RANDOM)
+	if (random & IRQF_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
-	local_irq_disable();
 
+	if (!noirqdebug)
+		note_interrupt(irq, desc, retval);
 	return retval;
 }
+
+irqreturn_t handle_irq_event(struct irq_desc *desc)
+{
+	struct irqaction *action = desc->action;
+	irqreturn_t ret;
+
+	irq_compat_clr_pending(desc);
+	desc->istate &= ~IRQS_PENDING;
+	irq_compat_set_progress(desc);
+	desc->istate |= IRQS_INPROGRESS;
+	raw_spin_unlock(&desc->lock);
+
+	ret = handle_irq_event_percpu(desc, action);
+
+	raw_spin_lock(&desc->lock);
+	desc->istate &= ~IRQS_INPROGRESS;
+	irq_compat_clr_progress(desc);
+	return ret;
+}
+
+/**
+ * handle_IRQ_event - irq action chain handler
+ * @irq:	the interrupt number
+ * @action:	the interrupt action chain for this irq
+ *
+ * Handles the action chain of an irq event
+ */
+irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
+{
+	return handle_irq_event_percpu(irq_to_desc(irq), action);
+}
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 99c3bc8..6c6ec9a 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -1,5 +1,9 @@
 /*
  * IRQ subsystem internal functions and variables:
+ *
+ * Do not ever include this file from anything else than
+ * kernel/irq/. Do not even think about using any information outside
+ * of this file for your non core code.
  */
 #include <linux/irqdesc.h>
 
@@ -9,25 +13,89 @@
 # define IRQ_BITMAP_BITS	NR_IRQS
 #endif
 
+#define istate core_internal_state__do_not_mess_with_it
+
+#ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT
+# define status status_use_accessors
+#endif
+
 extern int noirqdebug;
 
+/*
+ * Bits used by threaded handlers:
+ * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run
+ * IRQTF_DIED      - handler thread died
+ * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
+ * IRQTF_AFFINITY  - irq thread is requested to adjust affinity
+ * IRQTF_FORCED_THREAD  - irq action is force threaded
+ */
+enum {
+	IRQTF_RUNTHREAD,
+	IRQTF_DIED,
+	IRQTF_WARNED,
+	IRQTF_AFFINITY,
+	IRQTF_FORCED_THREAD,
+};
+
+/*
+ * Bit masks for desc->state
+ *
+ * IRQS_AUTODETECT		- autodetection in progress
+ * IRQS_SPURIOUS_DISABLED	- was disabled due to spurious interrupt
+ *				  detection
+ * IRQS_POLL_INPROGRESS		- polling in progress
+ * IRQS_INPROGRESS		- Interrupt in progress
+ * IRQS_ONESHOT			- irq is not unmasked in primary handler
+ * IRQS_REPLAY			- irq is replayed
+ * IRQS_WAITING			- irq is waiting
+ * IRQS_DISABLED		- irq is disabled
+ * IRQS_PENDING			- irq is pending and replayed later
+ * IRQS_MASKED			- irq is masked
+ * IRQS_SUSPENDED		- irq is suspended
+ */
+enum {
+	IRQS_AUTODETECT		= 0x00000001,
+	IRQS_SPURIOUS_DISABLED	= 0x00000002,
+	IRQS_POLL_INPROGRESS	= 0x00000008,
+	IRQS_INPROGRESS		= 0x00000010,
+	IRQS_ONESHOT		= 0x00000020,
+	IRQS_REPLAY		= 0x00000040,
+	IRQS_WAITING		= 0x00000080,
+	IRQS_DISABLED		= 0x00000100,
+	IRQS_PENDING		= 0x00000200,
+	IRQS_MASKED		= 0x00000400,
+	IRQS_SUSPENDED		= 0x00000800,
+};
+
+#include "compat.h"
+#include "debug.h"
+#include "settings.h"
+
 #define irq_data_to_desc(data)	container_of(data, struct irq_desc, irq_data)
 
 /* Set default functions for irq_chip structures: */
 extern void irq_chip_set_defaults(struct irq_chip *chip);
 
-/* Set default handler: */
-extern void compat_irq_chip_set_default_handler(struct irq_desc *desc);
-
 extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 		unsigned long flags);
 extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
 extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
 
+extern int irq_startup(struct irq_desc *desc);
+extern void irq_shutdown(struct irq_desc *desc);
+extern void irq_enable(struct irq_desc *desc);
+extern void irq_disable(struct irq_desc *desc);
+extern void mask_irq(struct irq_desc *desc);
+extern void unmask_irq(struct irq_desc *desc);
+
 extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
 
+irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action);
+irqreturn_t handle_irq_event(struct irq_desc *desc);
+
 /* Resending of interrupts :*/
 void check_irq_resend(struct irq_desc *desc, unsigned int irq);
+bool irq_wait_for_poll(struct irq_desc *desc);
 
 #ifdef CONFIG_PROC_FS
 extern void register_irq_proc(unsigned int irq, struct irq_desc *desc);
@@ -43,20 +111,10 @@ static inline void unregister_handler_proc(unsigned int irq,
 					   struct irqaction *action) { }
 #endif
 
-extern int irq_select_affinity_usr(unsigned int irq);
+extern int irq_select_affinity_usr(unsigned int irq, struct cpumask *mask);
 
 extern void irq_set_thread_affinity(struct irq_desc *desc);
 
-#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
-static inline void irq_end(unsigned int irq, struct irq_desc *desc)
-{
-	if (desc->irq_data.chip && desc->irq_data.chip->end)
-		desc->irq_data.chip->end(irq);
-}
-#else
-static inline void irq_end(unsigned int irq, struct irq_desc *desc) { }
-#endif
-
 /* Inline functions for support of irq chips on slow busses */
 static inline void chip_bus_lock(struct irq_desc *desc)
 {
@@ -70,43 +128,60 @@ static inline void chip_bus_sync_unlock(struct irq_desc *desc)
 		desc->irq_data.chip->irq_bus_sync_unlock(&desc->irq_data);
 }
 
+struct irq_desc *
+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus);
+void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus);
+
+static inline struct irq_desc *
+irq_get_desc_buslock(unsigned int irq, unsigned long *flags)
+{
+	return __irq_get_desc_lock(irq, flags, true);
+}
+
+static inline void
+irq_put_desc_busunlock(struct irq_desc *desc, unsigned long flags)
+{
+	__irq_put_desc_unlock(desc, flags, true);
+}
+
+static inline struct irq_desc *
+irq_get_desc_lock(unsigned int irq, unsigned long *flags)
+{
+	return __irq_get_desc_lock(irq, flags, false);
+}
+
+static inline void
+irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags)
+{
+	__irq_put_desc_unlock(desc, flags, false);
+}
+
 /*
- * Debugging printout:
+ * Manipulation functions for irq_data.state
  */
+static inline void irqd_set_move_pending(struct irq_data *d)
+{
+	d->state_use_accessors |= IRQD_SETAFFINITY_PENDING;
+	irq_compat_set_move_pending(irq_data_to_desc(d));
+}
 
-#include <linux/kallsyms.h>
-
-#define P(f) if (desc->status & f) printk("%14s set\n", #f)
+static inline void irqd_clr_move_pending(struct irq_data *d)
+{
+	d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING;
+	irq_compat_clr_move_pending(irq_data_to_desc(d));
+}
 
-static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
+static inline void irqd_clear(struct irq_data *d, unsigned int mask)
 {
-	printk("irq %d, desc: %p, depth: %d, count: %d, unhandled: %d\n",
-		irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled);
-	printk("->handle_irq():  %p, ", desc->handle_irq);
-	print_symbol("%s\n", (unsigned long)desc->handle_irq);
-	printk("->irq_data.chip(): %p, ", desc->irq_data.chip);
-	print_symbol("%s\n", (unsigned long)desc->irq_data.chip);
-	printk("->action(): %p\n", desc->action);
-	if (desc->action) {
-		printk("->action->handler(): %p, ", desc->action->handler);
-		print_symbol("%s\n", (unsigned long)desc->action->handler);
-	}
-
-	P(IRQ_INPROGRESS);
-	P(IRQ_DISABLED);
-	P(IRQ_PENDING);
-	P(IRQ_REPLAY);
-	P(IRQ_AUTODETECT);
-	P(IRQ_WAITING);
-	P(IRQ_LEVEL);
-	P(IRQ_MASKED);
-#ifdef CONFIG_IRQ_PER_CPU
-	P(IRQ_PER_CPU);
-#endif
-	P(IRQ_NOPROBE);
-	P(IRQ_NOREQUEST);
-	P(IRQ_NOAUTOEN);
+	d->state_use_accessors &= ~mask;
 }
 
-#undef P
+static inline void irqd_set(struct irq_data *d, unsigned int mask)
+{
+	d->state_use_accessors |= mask;
+}
 
+static inline bool irqd_has_set(struct irq_data *d, unsigned int mask)
+{
+	return d->state_use_accessors & mask;
+}
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 2039bea..dbccc79 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -79,7 +79,8 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
 	desc->irq_data.chip_data = NULL;
 	desc->irq_data.handler_data = NULL;
 	desc->irq_data.msi_desc = NULL;
-	desc->status = IRQ_DEFAULT_INIT_FLAGS;
+	irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
+	desc->istate = IRQS_DISABLED;
 	desc->handle_irq = handle_bad_irq;
 	desc->depth = 1;
 	desc->irq_count = 0;
@@ -206,6 +207,14 @@ struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
 	return NULL;
 }
 
+static int irq_expand_nr_irqs(unsigned int nr)
+{
+	if (nr > IRQ_BITMAP_BITS)
+		return -ENOMEM;
+	nr_irqs = nr;
+	return 0;
+}
+
 int __init early_irq_init(void)
 {
 	int i, initcnt, node = first_online_node;
@@ -238,7 +247,7 @@ int __init early_irq_init(void)
 
 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
 	[0 ... NR_IRQS-1] = {
-		.status		= IRQ_DEFAULT_INIT_FLAGS,
+		.istate		= IRQS_DISABLED,
 		.handle_irq	= handle_bad_irq,
 		.depth		= 1,
 		.lock		= __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
@@ -260,8 +269,8 @@ int __init early_irq_init(void)
 	for (i = 0; i < count; i++) {
 		desc[i].irq_data.irq = i;
 		desc[i].irq_data.chip = &no_irq_chip;
-		/* TODO : do this allocation on-demand ... */
 		desc[i].kstat_irqs = alloc_percpu(unsigned int);
+		irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
 		alloc_masks(desc + i, GFP_KERNEL, node);
 		desc_smp_init(desc + i, node);
 		lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
@@ -286,24 +295,14 @@ static void free_desc(unsigned int irq)
 
 static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
 {
-#if defined(CONFIG_KSTAT_IRQS_ONDEMAND)
-	struct irq_desc *desc;
-	unsigned int i;
-
-	for (i = 0; i < cnt; i++) {
-		desc = irq_to_desc(start + i);
-		if (desc && !desc->kstat_irqs) {
-			unsigned int __percpu *stats = alloc_percpu(unsigned int);
-
-			if (!stats)
-				return -1;
-			if (cmpxchg(&desc->kstat_irqs, NULL, stats) != NULL)
-				free_percpu(stats);
-		}
-	}
-#endif
 	return start;
 }
+
+static int irq_expand_nr_irqs(unsigned int nr)
+{
+	return -ENOMEM;
+}
+
 #endif /* !CONFIG_SPARSE_IRQ */
 
 /* Dynamic interrupt handling */
@@ -347,14 +346,17 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
 
 	mutex_lock(&sparse_irq_lock);
 
-	start = bitmap_find_next_zero_area(allocated_irqs, nr_irqs, from, cnt, 0);
+	start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
+					   from, cnt, 0);
 	ret = -EEXIST;
 	if (irq >=0 && start != irq)
 		goto err;
 
-	ret = -ENOMEM;
-	if (start >= nr_irqs)
-		goto err;
+	if (start + cnt > nr_irqs) {
+		ret = irq_expand_nr_irqs(start + cnt);
+		if (ret)
+			goto err;
+	}
 
 	bitmap_set(allocated_irqs, start, cnt);
 	mutex_unlock(&sparse_irq_lock);
@@ -401,6 +403,26 @@ unsigned int irq_get_next_irq(unsigned int offset)
 	return find_next_bit(allocated_irqs, nr_irqs, offset);
 }
 
+struct irq_desc *
+__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+
+	if (desc) {
+		if (bus)
+			chip_bus_lock(desc);
+		raw_spin_lock_irqsave(&desc->lock, *flags);
+	}
+	return desc;
+}
+
+void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus)
+{
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	if (bus)
+		chip_bus_sync_unlock(desc);
+}
+
 /**
  * dynamic_irq_cleanup - cleanup a dynamically allocated irq
  * @irq:	irq number to initialize
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 9033c1c..0a2aa73 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -17,6 +17,17 @@
 
 #include "internals.h"
 
+#ifdef CONFIG_IRQ_FORCED_THREADING
+__read_mostly bool force_irqthreads;
+
+static int __init setup_forced_irqthreads(char *arg)
+{
+	force_irqthreads = true;
+	return 0;
+}
+early_param("threadirqs", setup_forced_irqthreads);
+#endif
+
 /**
  *	synchronize_irq - wait for pending IRQ handlers (on other CPUs)
  *	@irq: interrupt number to wait for
@@ -30,7 +41,7 @@
 void synchronize_irq(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
-	unsigned int status;
+	unsigned int state;
 
 	if (!desc)
 		return;
@@ -42,16 +53,16 @@ void synchronize_irq(unsigned int irq)
 		 * Wait until we're out of the critical section.  This might
 		 * give the wrong answer due to the lack of memory barriers.
 		 */
-		while (desc->status & IRQ_INPROGRESS)
+		while (desc->istate & IRQS_INPROGRESS)
 			cpu_relax();
 
 		/* Ok, that indicated we're done: double-check carefully. */
 		raw_spin_lock_irqsave(&desc->lock, flags);
-		status = desc->status;
+		state = desc->istate;
 		raw_spin_unlock_irqrestore(&desc->lock, flags);
 
 		/* Oops, that failed? */
-	} while (status & IRQ_INPROGRESS);
+	} while (state & IRQS_INPROGRESS);
 
 	/*
 	 * We made sure that no hardirq handler is running. Now verify
@@ -73,8 +84,8 @@ int irq_can_set_affinity(unsigned int irq)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (CHECK_IRQ_PER_CPU(desc->status) || !desc->irq_data.chip ||
-	    !desc->irq_data.chip->irq_set_affinity)
+	if (!desc || !irqd_can_balance(&desc->irq_data) ||
+	    !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity)
 		return 0;
 
 	return 1;
@@ -100,67 +111,169 @@ void irq_set_thread_affinity(struct irq_desc *desc)
 	}
 }
 
+#ifdef CONFIG_GENERIC_PENDING_IRQ
+static inline bool irq_can_move_pcntxt(struct irq_desc *desc)
+{
+	return irq_settings_can_move_pcntxt(desc);
+}
+static inline bool irq_move_pending(struct irq_desc *desc)
+{
+	return irqd_is_setaffinity_pending(&desc->irq_data);
+}
+static inline void
+irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask)
+{
+	cpumask_copy(desc->pending_mask, mask);
+}
+static inline void
+irq_get_pending(struct cpumask *mask, struct irq_desc *desc)
+{
+	cpumask_copy(mask, desc->pending_mask);
+}
+#else
+static inline bool irq_can_move_pcntxt(struct irq_desc *desc) { return true; }
+static inline bool irq_move_pending(struct irq_desc *desc) { return false; }
+static inline void
+irq_copy_pending(struct irq_desc *desc, const struct cpumask *mask) { }
+static inline void
+irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { }
+#endif
+
 /**
  *	irq_set_affinity - Set the irq affinity of a given irq
  *	@irq:		Interrupt to set affinity
  *	@cpumask:	cpumask
  *
  */
-int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+int irq_set_affinity(unsigned int irq, const struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	struct irq_chip *chip = desc->irq_data.chip;
 	unsigned long flags;
+	int ret = 0;
 
 	if (!chip->irq_set_affinity)
 		return -EINVAL;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-	if (desc->status & IRQ_MOVE_PCNTXT) {
-		if (!chip->irq_set_affinity(&desc->irq_data, cpumask, false)) {
-			cpumask_copy(desc->irq_data.affinity, cpumask);
+	if (irq_can_move_pcntxt(desc)) {
+		ret = chip->irq_set_affinity(&desc->irq_data, mask, false);
+		switch (ret) {
+		case IRQ_SET_MASK_OK:
+			cpumask_copy(desc->irq_data.affinity, mask);
+		case IRQ_SET_MASK_OK_NOCOPY:
 			irq_set_thread_affinity(desc);
+			ret = 0;
 		}
+	} else {
+		irqd_set_move_pending(&desc->irq_data);
+		irq_copy_pending(desc, mask);
 	}
-	else {
-		desc->status |= IRQ_MOVE_PENDING;
-		cpumask_copy(desc->pending_mask, cpumask);
-	}
-#else
-	if (!chip->irq_set_affinity(&desc->irq_data, cpumask, false)) {
-		cpumask_copy(desc->irq_data.affinity, cpumask);
-		irq_set_thread_affinity(desc);
+
+	if (desc->affinity_notify) {
+		kref_get(&desc->affinity_notify->kref);
+		schedule_work(&desc->affinity_notify->work);
 	}
-#endif
-	desc->status |= IRQ_AFFINITY_SET;
+	irq_compat_set_affinity(desc);
+	irqd_set(&desc->irq_data, IRQD_AFFINITY_SET);
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	return 0;
+	return ret;
 }
 
 int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
 {
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+
+	if (!desc)
+		return -EINVAL;
+	desc->affinity_hint = m;
+	irq_put_desc_unlock(desc, flags);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(irq_set_affinity_hint);
+
+static void irq_affinity_notify(struct work_struct *work)
+{
+	struct irq_affinity_notify *notify =
+		container_of(work, struct irq_affinity_notify, work);
+	struct irq_desc *desc = irq_to_desc(notify->irq);
+	cpumask_var_t cpumask;
+	unsigned long flags;
+
+	if (!desc || !alloc_cpumask_var(&cpumask, GFP_KERNEL))
+		goto out;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+	if (irq_move_pending(desc))
+		irq_get_pending(cpumask, desc);
+	else
+		cpumask_copy(cpumask, desc->irq_data.affinity);
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+
+	notify->notify(notify, cpumask);
+
+	free_cpumask_var(cpumask);
+out:
+	kref_put(&notify->kref, notify->release);
+}
+
+/**
+ *	irq_set_affinity_notifier - control notification of IRQ affinity changes
+ *	@irq:		Interrupt for which to enable/disable notification
+ *	@notify:	Context for notification, or %NULL to disable
+ *			notification.  Function pointers must be initialised;
+ *			the other fields will be initialised by this function.
+ *
+ *	Must be called in process context.  Notification may only be enabled
+ *	after the IRQ is allocated and must be disabled before the IRQ is
+ *	freed using free_irq().
+ */
+int
+irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
+{
 	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_affinity_notify *old_notify;
 	unsigned long flags;
 
+	/* The release function is promised process context */
+	might_sleep();
+
 	if (!desc)
 		return -EINVAL;
 
+	/* Complete initialisation of *notify */
+	if (notify) {
+		notify->irq = irq;
+		kref_init(&notify->kref);
+		INIT_WORK(&notify->work, irq_affinity_notify);
+	}
+
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->affinity_hint = m;
+	old_notify = desc->affinity_notify;
+	desc->affinity_notify = notify;
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
 
+	if (old_notify)
+		kref_put(&old_notify->kref, old_notify->release);
+
 	return 0;
 }
-EXPORT_SYMBOL_GPL(irq_set_affinity_hint);
+EXPORT_SYMBOL_GPL(irq_set_affinity_notifier);
 
 #ifndef CONFIG_AUTO_IRQ_AFFINITY
 /*
  * Generic version of the affinity autoselector.
  */
-static int setup_affinity(unsigned int irq, struct irq_desc *desc)
+static int
+setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct cpumask *set = irq_default_affinity;
+	int ret;
+
+	/* Excludes PER_CPU and NO_BALANCE interrupts */
 	if (!irq_can_set_affinity(irq))
 		return 0;
 
@@ -168,22 +281,29 @@ static int setup_affinity(unsigned int irq, struct irq_desc *desc)
 	 * Preserve an userspace affinity setup, but make sure that
 	 * one of the targets is online.
 	 */
-	if (desc->status & (IRQ_AFFINITY_SET | IRQ_NO_BALANCING)) {
-		if (cpumask_any_and(desc->irq_data.affinity, cpu_online_mask)
-		    < nr_cpu_ids)
-			goto set_affinity;
-		else
-			desc->status &= ~IRQ_AFFINITY_SET;
+	if (irqd_has_set(&desc->irq_data, IRQD_AFFINITY_SET)) {
+		if (cpumask_intersects(desc->irq_data.affinity,
+				       cpu_online_mask))
+			set = desc->irq_data.affinity;
+		else {
+			irq_compat_clr_affinity(desc);
+			irqd_clear(&desc->irq_data, IRQD_AFFINITY_SET);
+		}
 	}
 
-	cpumask_and(desc->irq_data.affinity, cpu_online_mask, irq_default_affinity);
-set_affinity:
-	desc->irq_data.chip->irq_set_affinity(&desc->irq_data, desc->irq_data.affinity, false);
-
+	cpumask_and(mask, cpu_online_mask, set);
+	ret = chip->irq_set_affinity(&desc->irq_data, mask, false);
+	switch (ret) {
+	case IRQ_SET_MASK_OK:
+		cpumask_copy(desc->irq_data.affinity, mask);
+	case IRQ_SET_MASK_OK_NOCOPY:
+		irq_set_thread_affinity(desc);
+	}
 	return 0;
 }
 #else
-static inline int setup_affinity(unsigned int irq, struct irq_desc *d)
+static inline int
+setup_affinity(unsigned int irq, struct irq_desc *d, struct cpumask *mask)
 {
 	return irq_select_affinity(irq);
 }
@@ -192,23 +312,21 @@ static inline int setup_affinity(unsigned int irq, struct irq_desc *d)
 /*
  * Called when affinity is set via /proc/irq
  */
-int irq_select_affinity_usr(unsigned int irq)
+int irq_select_affinity_usr(unsigned int irq, struct cpumask *mask)
 {
 	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
 	int ret;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
-	ret = setup_affinity(irq, desc);
-	if (!ret)
-		irq_set_thread_affinity(desc);
+	ret = setup_affinity(irq, desc, mask);
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
-
 	return ret;
 }
 
 #else
-static inline int setup_affinity(unsigned int irq, struct irq_desc *desc)
+static inline int
+setup_affinity(unsigned int irq, struct irq_desc *desc, struct cpumask *mask)
 {
 	return 0;
 }
@@ -219,13 +337,23 @@ void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
 	if (suspend) {
 		if (!desc->action || (desc->action->flags & IRQF_NO_SUSPEND))
 			return;
-		desc->status |= IRQ_SUSPENDED;
+		desc->istate |= IRQS_SUSPENDED;
 	}
 
-	if (!desc->depth++) {
-		desc->status |= IRQ_DISABLED;
-		desc->irq_data.chip->irq_disable(&desc->irq_data);
-	}
+	if (!desc->depth++)
+		irq_disable(desc);
+}
+
+static int __disable_irq_nosync(unsigned int irq)
+{
+	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
+
+	if (!desc)
+		return -EINVAL;
+	__disable_irq(desc, irq, false);
+	irq_put_desc_busunlock(desc, flags);
+	return 0;
 }
 
 /**
@@ -241,17 +369,7 @@ void __disable_irq(struct irq_desc *desc, unsigned int irq, bool suspend)
  */
 void disable_irq_nosync(unsigned int irq)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	unsigned long flags;
-
-	if (!desc)
-		return;
-
-	chip_bus_lock(desc);
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	__disable_irq(desc, irq, false);
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	chip_bus_sync_unlock(desc);
+	__disable_irq_nosync(irq);
 }
 EXPORT_SYMBOL(disable_irq_nosync);
 
@@ -269,21 +387,24 @@ EXPORT_SYMBOL(disable_irq_nosync);
  */
 void disable_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	if (!desc)
-		return;
-
-	disable_irq_nosync(irq);
-	if (desc->action)
+	if (!__disable_irq_nosync(irq))
 		synchronize_irq(irq);
 }
 EXPORT_SYMBOL(disable_irq);
 
 void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
 {
-	if (resume)
-		desc->status &= ~IRQ_SUSPENDED;
+	if (resume) {
+		if (!(desc->istate & IRQS_SUSPENDED)) {
+			if (!desc->action)
+				return;
+			if (!(desc->action->flags & IRQF_FORCE_RESUME))
+				return;
+			/* Pretend that it got disabled ! */
+			desc->depth++;
+		}
+		desc->istate &= ~IRQS_SUSPENDED;
+	}
 
 	switch (desc->depth) {
 	case 0:
@@ -291,12 +412,11 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
 		WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);
 		break;
 	case 1: {
-		unsigned int status = desc->status & ~IRQ_DISABLED;
-
-		if (desc->status & IRQ_SUSPENDED)
+		if (desc->istate & IRQS_SUSPENDED)
 			goto err_out;
 		/* Prevent probing on this irq: */
-		desc->status = status | IRQ_NOPROBE;
+		irq_settings_set_noprobe(desc);
+		irq_enable(desc);
 		check_irq_resend(desc, irq);
 		/* fall-through */
 	}
@@ -318,21 +438,18 @@ void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume)
  */
 void enable_irq(unsigned int irq)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
 
 	if (!desc)
 		return;
+	if (WARN(!desc->irq_data.chip,
+		 KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
+		goto out;
 
-	if (WARN(!desc->irq_data.chip || !desc->irq_data.chip->irq_enable,
-	    KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
-		return;
-
-	chip_bus_lock(desc);
-	raw_spin_lock_irqsave(&desc->lock, flags);
 	__enable_irq(desc, irq, false);
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	chip_bus_sync_unlock(desc);
+out:
+	irq_put_desc_busunlock(desc, flags);
 }
 EXPORT_SYMBOL(enable_irq);
 
@@ -348,7 +465,7 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on)
 }
 
 /**
- *	set_irq_wake - control irq power management wakeup
+ *	irq_set_irq_wake - control irq power management wakeup
  *	@irq:	interrupt to control
  *	@on:	enable/disable power management wakeup
  *
@@ -359,23 +476,22 @@ static int set_irq_wake_real(unsigned int irq, unsigned int on)
  *	Wakeup mode lets this IRQ wake the system from sleep
  *	states like "suspend to RAM".
  */
-int set_irq_wake(unsigned int irq, unsigned int on)
+int irq_set_irq_wake(unsigned int irq, unsigned int on)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_buslock(irq, &flags);
 	int ret = 0;
 
 	/* wakeup-capable irqs can be shared between drivers that
 	 * don't need to have the same sleep mode behaviors.
 	 */
-	raw_spin_lock_irqsave(&desc->lock, flags);
 	if (on) {
 		if (desc->wake_depth++ == 0) {
 			ret = set_irq_wake_real(irq, on);
 			if (ret)
 				desc->wake_depth = 0;
 			else
-				desc->status |= IRQ_WAKEUP;
+				irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);
 		}
 	} else {
 		if (desc->wake_depth == 0) {
@@ -385,14 +501,13 @@ int set_irq_wake(unsigned int irq, unsigned int on)
 			if (ret)
 				desc->wake_depth = 1;
 			else
-				desc->status &= ~IRQ_WAKEUP;
+				irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE);
 		}
 	}
-
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	irq_put_desc_busunlock(desc, flags);
 	return ret;
 }
-EXPORT_SYMBOL(set_irq_wake);
+EXPORT_SYMBOL(irq_set_irq_wake);
 
 /*
  * Internal function that tells the architecture code whether a
@@ -401,43 +516,27 @@ EXPORT_SYMBOL(set_irq_wake);
  */
 int can_request_irq(unsigned int irq, unsigned long irqflags)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irqaction *action;
 	unsigned long flags;
+	struct irq_desc *desc = irq_get_desc_lock(irq, &flags);
+	int canrequest = 0;
 
 	if (!desc)
 		return 0;
 
-	if (desc->status & IRQ_NOREQUEST)
-		return 0;
-
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	action = desc->action;
-	if (action)
-		if (irqflags & action->flags & IRQF_SHARED)
-			action = NULL;
-
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-
-	return !action;
-}
-
-void compat_irq_chip_set_default_handler(struct irq_desc *desc)
-{
-	/*
-	 * If the architecture still has not overriden
-	 * the flow handler then zap the default. This
-	 * should catch incorrect flow-type setting.
-	 */
-	if (desc->handle_irq == &handle_bad_irq)
-		desc->handle_irq = NULL;
+	if (irq_settings_can_request(desc)) {
+		if (desc->action)
+			if (irqflags & desc->action->flags & IRQF_SHARED)
+				canrequest =1;
+	}
+	irq_put_desc_unlock(desc, flags);
+	return canrequest;
 }
 
 int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 		      unsigned long flags)
 {
-	int ret;
 	struct irq_chip *chip = desc->irq_data.chip;
+	int ret, unmask = 0;
 
 	if (!chip || !chip->irq_set_type) {
 		/*
@@ -449,23 +548,43 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
 		return 0;
 	}
 
+	flags &= IRQ_TYPE_SENSE_MASK;
+
+	if (chip->flags & IRQCHIP_SET_TYPE_MASKED) {
+		if (!(desc->istate & IRQS_MASKED))
+			mask_irq(desc);
+		if (!(desc->istate & IRQS_DISABLED))
+			unmask = 1;
+	}
+
 	/* caller masked out all except trigger mode flags */
 	ret = chip->irq_set_type(&desc->irq_data, flags);
 
-	if (ret)
-		pr_err("setting trigger mode %lu for irq %u failed (%pF)\n",
-		       flags, irq, chip->irq_set_type);
-	else {
-		if (flags & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-			flags |= IRQ_LEVEL;
-		/* note that IRQF_TRIGGER_MASK == IRQ_TYPE_SENSE_MASK */
-		desc->status &= ~(IRQ_LEVEL | IRQ_TYPE_SENSE_MASK);
-		desc->status |= flags;
+	switch (ret) {
+	case IRQ_SET_MASK_OK:
+		irqd_clear(&desc->irq_data, IRQD_TRIGGER_MASK);
+		irqd_set(&desc->irq_data, flags);
+
+	case IRQ_SET_MASK_OK_NOCOPY:
+		flags = irqd_get_trigger_type(&desc->irq_data);
+		irq_settings_set_trigger_mask(desc, flags);
+		irqd_clear(&desc->irq_data, IRQD_LEVEL);
+		irq_settings_clr_level(desc);
+		if (flags & IRQ_TYPE_LEVEL_MASK) {
+			irq_settings_set_level(desc);
+			irqd_set(&desc->irq_data, IRQD_LEVEL);
+		}
 
 		if (chip != desc->irq_data.chip)
 			irq_chip_set_defaults(desc->irq_data.chip);
+		ret = 0;
+		break;
+	default:
+		pr_err("setting trigger mode %lu for irq %u failed (%pF)\n",
+		       flags, irq, chip->irq_set_type);
 	}
-
+	if (unmask)
+		unmask_irq(desc);
 	return ret;
 }
 
@@ -509,8 +628,11 @@ static int irq_wait_for_interrupt(struct irqaction *action)
  * handler finished. unmask if the interrupt has not been disabled and
  * is marked MASKED.
  */
-static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
+static void irq_finalize_oneshot(struct irq_desc *desc,
+				 struct irqaction *action, bool force)
 {
+	if (!(desc->istate & IRQS_ONESHOT))
+		return;
 again:
 	chip_bus_lock(desc);
 	raw_spin_lock_irq(&desc->lock);
@@ -522,26 +644,44 @@ again:
 	 * The thread is faster done than the hard interrupt handler
 	 * on the other CPU. If we unmask the irq line then the
 	 * interrupt can come in again and masks the line, leaves due
-	 * to IRQ_INPROGRESS and the irq line is masked forever.
+	 * to IRQS_INPROGRESS and the irq line is masked forever.
+	 *
+	 * This also serializes the state of shared oneshot handlers
+	 * versus "desc->threads_onehsot |= action->thread_mask;" in
+	 * irq_wake_thread(). See the comment there which explains the
+	 * serialization.
 	 */
-	if (unlikely(desc->status & IRQ_INPROGRESS)) {
+	if (unlikely(desc->istate & IRQS_INPROGRESS)) {
 		raw_spin_unlock_irq(&desc->lock);
 		chip_bus_sync_unlock(desc);
 		cpu_relax();
 		goto again;
 	}
 
-	if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
-		desc->status &= ~IRQ_MASKED;
+	/*
+	 * Now check again, whether the thread should run. Otherwise
+	 * we would clear the threads_oneshot bit of this thread which
+	 * was just set.
+	 */
+	if (!force && test_bit(IRQTF_RUNTHREAD, &action->thread_flags))
+		goto out_unlock;
+
+	desc->threads_oneshot &= ~action->thread_mask;
+
+	if (!desc->threads_oneshot && !(desc->istate & IRQS_DISABLED) &&
+	    (desc->istate & IRQS_MASKED)) {
+		irq_compat_clr_masked(desc);
+		desc->istate &= ~IRQS_MASKED;
 		desc->irq_data.chip->irq_unmask(&desc->irq_data);
 	}
+out_unlock:
 	raw_spin_unlock_irq(&desc->lock);
 	chip_bus_sync_unlock(desc);
 }
 
 #ifdef CONFIG_SMP
 /*
- * Check whether we need to change the affinity of the interrupt thread.
+ * Check whether we need to chasnge the affinity of the interrupt thread.
  */
 static void
 irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
@@ -573,6 +713,32 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
 #endif
 
 /*
+ * Interrupts which are not explicitely requested as threaded
+ * interrupts rely on the implicit bh/preempt disable of the hard irq
+ * context. So we need to disable bh here to avoid deadlocks and other
+ * side effects.
+ */
+static void
+irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
+{
+	local_bh_disable();
+	action->thread_fn(action->irq, action->dev_id);
+	irq_finalize_oneshot(desc, action, false);
+	local_bh_enable();
+}
+
+/*
+ * Interrupts explicitely requested as threaded interupts want to be
+ * preemtible - many of them need to sleep and wait for slow busses to
+ * complete.
+ */
+static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action)
+{
+	action->thread_fn(action->irq, action->dev_id);
+	irq_finalize_oneshot(desc, action, false);
+}
+
+/*
  * Interrupt handler thread
  */
 static int irq_thread(void *data)
@@ -582,7 +748,14 @@ static int irq_thread(void *data)
 	};
 	struct irqaction *action = data;
 	struct irq_desc *desc = irq_to_desc(action->irq);
-	int wake, oneshot = desc->status & IRQ_ONESHOT;
+	void (*handler_fn)(struct irq_desc *desc, struct irqaction *action);
+	int wake;
+
+	if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
+					&action->thread_flags))
+		handler_fn = irq_forced_thread_fn;
+	else
+		handler_fn = irq_thread_fn;
 
 	sched_setscheduler(current, SCHED_FIFO, &param);
 	current->irqaction = action;
@@ -594,23 +767,20 @@ static int irq_thread(void *data)
 		atomic_inc(&desc->threads_active);
 
 		raw_spin_lock_irq(&desc->lock);
-		if (unlikely(desc->status & IRQ_DISABLED)) {
+		if (unlikely(desc->istate & IRQS_DISABLED)) {
 			/*
 			 * CHECKME: We might need a dedicated
 			 * IRQ_THREAD_PENDING flag here, which
 			 * retriggers the thread in check_irq_resend()
-			 * but AFAICT IRQ_PENDING should be fine as it
+			 * but AFAICT IRQS_PENDING should be fine as it
 			 * retriggers the interrupt itself --- tglx
 			 */
-			desc->status |= IRQ_PENDING;
+			irq_compat_set_pending(desc);
+			desc->istate |= IRQS_PENDING;
 			raw_spin_unlock_irq(&desc->lock);
 		} else {
 			raw_spin_unlock_irq(&desc->lock);
-
-			action->thread_fn(action->irq, action->dev_id);
-
-			if (oneshot)
-				irq_finalize_oneshot(action->irq, desc);
+			handler_fn(desc, action);
 		}
 
 		wake = atomic_dec_and_test(&desc->threads_active);
@@ -619,6 +789,9 @@ static int irq_thread(void *data)
 			wake_up(&desc->wait_for_threads);
 	}
 
+	/* Prevent a stale desc->threads_oneshot */
+	irq_finalize_oneshot(desc, action, true);
+
 	/*
 	 * Clear irqaction. Otherwise exit_irq_thread() would make
 	 * fuzz about an active irq thread going into nirvana.
@@ -633,6 +806,7 @@ static int irq_thread(void *data)
 void exit_irq_thread(void)
 {
 	struct task_struct *tsk = current;
+	struct irq_desc *desc;
 
 	if (!tsk->irqaction)
 		return;
@@ -641,6 +815,14 @@ void exit_irq_thread(void)
 	       "exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
 	       tsk->comm ? tsk->comm : "", tsk->pid, tsk->irqaction->irq);
 
+	desc = irq_to_desc(tsk->irqaction->irq);
+
+	/*
+	 * Prevent a stale desc->threads_oneshot. Must be called
+	 * before setting the IRQTF_DIED flag.
+	 */
+	irq_finalize_oneshot(desc, tsk->irqaction, true);
+
 	/*
 	 * Set the THREAD DIED flag to prevent further wakeups of the
 	 * soon to be gone threaded handler.
@@ -648,6 +830,22 @@ void exit_irq_thread(void)
 	set_bit(IRQTF_DIED, &tsk->irqaction->flags);
 }
 
+static void irq_setup_forced_threading(struct irqaction *new)
+{
+	if (!force_irqthreads)
+		return;
+	if (new->flags & (IRQF_NO_THREAD | IRQF_PERCPU | IRQF_ONESHOT))
+		return;
+
+	new->flags |= IRQF_ONESHOT;
+
+	if (!new->thread_fn) {
+		set_bit(IRQTF_FORCED_THREAD, &new->thread_flags);
+		new->thread_fn = new->handler;
+		new->handler = irq_default_primary_handler;
+	}
+}
+
 /*
  * Internal function to register an irqaction - typically used to
  * allocate special interrupts that are part of the architecture.
@@ -657,9 +855,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 {
 	struct irqaction *old, **old_ptr;
 	const char *old_name = NULL;
-	unsigned long flags;
-	int nested, shared = 0;
-	int ret;
+	unsigned long flags, thread_mask = 0;
+	int ret, nested, shared = 0;
+	cpumask_var_t mask;
 
 	if (!desc)
 		return -EINVAL;
@@ -683,15 +881,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		rand_initialize_irq(irq);
 	}
 
-	/* Oneshot interrupts are not allowed with shared */
-	if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED))
-		return -EINVAL;
-
 	/*
 	 * Check whether the interrupt nests into another interrupt
 	 * thread.
 	 */
-	nested = desc->status & IRQ_NESTED_THREAD;
+	nested = irq_settings_is_nested_thread(desc);
 	if (nested) {
 		if (!new->thread_fn)
 			return -EINVAL;
@@ -701,6 +895,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		 * dummy function which warns when called.
 		 */
 		new->handler = irq_nested_primary_handler;
+	} else {
+		irq_setup_forced_threading(new);
 	}
 
 	/*
@@ -724,6 +920,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		new->thread = t;
 	}
 
+	if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto out_thread;
+	}
+
 	/*
 	 * The following block of code has to be executed atomically
 	 */
@@ -735,29 +936,40 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 		 * Can't share interrupts unless both agree to and are
 		 * the same type (level, edge, polarity). So both flag
 		 * fields must have IRQF_SHARED set and the bits which
-		 * set the trigger type must match.
+		 * set the trigger type must match. Also all must
+		 * agree on ONESHOT.
 		 */
 		if (!((old->flags & new->flags) & IRQF_SHARED) ||
-		    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK)) {
+		    ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) ||
+		    ((old->flags ^ new->flags) & IRQF_ONESHOT)) {
 			old_name = old->name;
 			goto mismatch;
 		}
 
-#if defined(CONFIG_IRQ_PER_CPU)
 		/* All handlers must agree on per-cpuness */
 		if ((old->flags & IRQF_PERCPU) !=
 		    (new->flags & IRQF_PERCPU))
 			goto mismatch;
-#endif
 
 		/* add new interrupt at end of irq queue */
 		do {
+			thread_mask |= old->thread_mask;
 			old_ptr = &old->next;
 			old = *old_ptr;
 		} while (old);
 		shared = 1;
 	}
 
+	/*
+	 * Setup the thread mask for this irqaction. Unlikely to have
+	 * 32 resp 64 irqs sharing one line, but who knows.
+	 */
+	if (new->flags & IRQF_ONESHOT && thread_mask == ~0UL) {
+		ret = -EBUSY;
+		goto out_mask;
+	}
+	new->thread_mask = 1 << ffz(thread_mask);
+
 	if (!shared) {
 		irq_chip_set_defaults(desc->irq_data.chip);
 
@@ -769,42 +981,44 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 					new->flags & IRQF_TRIGGER_MASK);
 
 			if (ret)
-				goto out_thread;
-		} else
-			compat_irq_chip_set_default_handler(desc);
-#if defined(CONFIG_IRQ_PER_CPU)
-		if (new->flags & IRQF_PERCPU)
-			desc->status |= IRQ_PER_CPU;
-#endif
+				goto out_mask;
+		}
+
+		desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \
+				  IRQS_INPROGRESS | IRQS_ONESHOT | \
+				  IRQS_WAITING);
 
-		desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |
-				  IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
+		if (new->flags & IRQF_PERCPU) {
+			irqd_set(&desc->irq_data, IRQD_PER_CPU);
+			irq_settings_set_per_cpu(desc);
+		}
 
 		if (new->flags & IRQF_ONESHOT)
-			desc->status |= IRQ_ONESHOT;
+			desc->istate |= IRQS_ONESHOT;
 
-		if (!(desc->status & IRQ_NOAUTOEN)) {
-			desc->depth = 0;
-			desc->status &= ~IRQ_DISABLED;
-			desc->irq_data.chip->irq_startup(&desc->irq_data);
-		} else
+		if (irq_settings_can_autoenable(desc))
+			irq_startup(desc);
+		else
 			/* Undo nested disables: */
 			desc->depth = 1;
 
 		/* Exclude IRQ from balancing if requested */
-		if (new->flags & IRQF_NOBALANCING)
-			desc->status |= IRQ_NO_BALANCING;
+		if (new->flags & IRQF_NOBALANCING) {
+			irq_settings_set_no_balancing(desc);
+			irqd_set(&desc->irq_data, IRQD_NO_BALANCING);
+		}
 
 		/* Set default affinity mask once everything is setup */
-		setup_affinity(irq, desc);
-
-	} else if ((new->flags & IRQF_TRIGGER_MASK)
-			&& (new->flags & IRQF_TRIGGER_MASK)
-				!= (desc->status & IRQ_TYPE_SENSE_MASK)) {
-		/* hope the handler works with the actual trigger mode... */
-		pr_warning("IRQ %d uses trigger mode %d; requested %d\n",
-				irq, (int)(desc->status & IRQ_TYPE_SENSE_MASK),
-				(int)(new->flags & IRQF_TRIGGER_MASK));
+		setup_affinity(irq, desc, mask);
+
+	} else if (new->flags & IRQF_TRIGGER_MASK) {
+		unsigned int nmsk = new->flags & IRQF_TRIGGER_MASK;
+		unsigned int omsk = irq_settings_get_trigger_mask(desc);
+
+		if (nmsk != omsk)
+			/* hope the handler works with current  trigger mode */
+			pr_warning("IRQ %d uses trigger mode %u; requested %u\n",
+				   irq, nmsk, omsk);
 	}
 
 	new->irq = irq;
@@ -818,8 +1032,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
 	 * Check whether we disabled the irq via the spurious handler
 	 * before. Reenable it and give it another chance.
 	 */
-	if (shared && (desc->status & IRQ_SPURIOUS_DISABLED)) {
-		desc->status &= ~IRQ_SPURIOUS_DISABLED;
+	if (shared && (desc->istate & IRQS_SPURIOUS_DISABLED)) {
+		desc->istate &= ~IRQS_SPURIOUS_DISABLED;
 		__enable_irq(desc, irq, false);
 	}
 
@@ -849,8 +1063,11 @@ mismatch:
 #endif
 	ret = -EBUSY;
 
-out_thread:
+out_mask:
 	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	free_cpumask_var(mask);
+
+out_thread:
 	if (new->thread) {
 		struct task_struct *t = new->thread;
 
@@ -871,9 +1088,14 @@ out_thread:
  */
 int setup_irq(unsigned int irq, struct irqaction *act)
 {
+	int retval;
 	struct irq_desc *desc = irq_to_desc(irq);
 
-	return __setup_irq(irq, desc, act);
+	chip_bus_lock(desc);
+	retval = __setup_irq(irq, desc, act);
+	chip_bus_sync_unlock(desc);
+
+	return retval;
 }
 EXPORT_SYMBOL_GPL(setup_irq);
 
@@ -924,13 +1146,8 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 #endif
 
 	/* If this was the last handler, shut down the IRQ line: */
-	if (!desc->action) {
-		desc->status |= IRQ_DISABLED;
-		if (desc->irq_data.chip->irq_shutdown)
-			desc->irq_data.chip->irq_shutdown(&desc->irq_data);
-		else
-			desc->irq_data.chip->irq_disable(&desc->irq_data);
-	}
+	if (!desc->action)
+		irq_shutdown(desc);
 
 #ifdef CONFIG_SMP
 	/* make sure affinity_hint is cleaned up */
@@ -1004,6 +1221,11 @@ void free_irq(unsigned int irq, void *dev_id)
 	if (!desc)
 		return;
 
+#ifdef CONFIG_SMP
+	if (WARN_ON(desc->affinity_notify))
+		desc->affinity_notify = NULL;
+#endif
+
 	chip_bus_lock(desc);
 	kfree(__free_irq(irq, dev_id));
 	chip_bus_sync_unlock(desc);
@@ -1074,7 +1296,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
 	if (!desc)
 		return -EINVAL;
 
-	if (desc->status & IRQ_NOREQUEST)
+	if (!irq_settings_can_request(desc))
 		return -EINVAL;
 
 	if (!handler) {
@@ -1149,7 +1371,7 @@ int request_any_context_irq(unsigned int irq, irq_handler_t handler,
 	if (!desc)
 		return -EINVAL;
 
-	if (desc->status & IRQ_NESTED_THREAD) {
+	if (irq_settings_is_nested_thread(desc)) {
 		ret = request_threaded_irq(irq, NULL, handler,
 					   flags, name, dev_id);
 		return !ret ? IRQC_IS_NESTED : ret;
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 441fd62..ec4806d 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -4,23 +4,23 @@
 
 #include "internals.h"
 
-void move_masked_irq(int irq)
+void irq_move_masked_irq(struct irq_data *idata)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	struct irq_chip *chip = desc->irq_data.chip;
+	struct irq_desc *desc = irq_data_to_desc(idata);
+	struct irq_chip *chip = idata->chip;
 
-	if (likely(!(desc->status & IRQ_MOVE_PENDING)))
+	if (likely(!irqd_is_setaffinity_pending(&desc->irq_data)))
 		return;
 
 	/*
 	 * Paranoia: cpu-local interrupts shouldn't be calling in here anyway.
 	 */
-	if (CHECK_IRQ_PER_CPU(desc->status)) {
+	if (!irqd_can_balance(&desc->irq_data)) {
 		WARN_ON(1);
 		return;
 	}
 
-	desc->status &= ~IRQ_MOVE_PENDING;
+	irqd_clr_move_pending(&desc->irq_data);
 
 	if (unlikely(cpumask_empty(desc->pending_mask)))
 		return;
@@ -53,15 +53,20 @@ void move_masked_irq(int irq)
 	cpumask_clear(desc->pending_mask);
 }
 
-void move_native_irq(int irq)
+void move_masked_irq(int irq)
+{
+	irq_move_masked_irq(irq_get_irq_data(irq));
+}
+
+void irq_move_irq(struct irq_data *idata)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_desc *desc = irq_data_to_desc(idata);
 	bool masked;
 
-	if (likely(!(desc->status & IRQ_MOVE_PENDING)))
+	if (likely(!irqd_is_setaffinity_pending(idata)))
 		return;
 
-	if (unlikely(desc->status & IRQ_DISABLED))
+	if (unlikely(desc->istate & IRQS_DISABLED))
 		return;
 
 	/*
@@ -69,10 +74,15 @@ void move_native_irq(int irq)
 	 * threaded interrupt with ONESHOT set, we can end up with an
 	 * interrupt storm.
 	 */
-	masked = desc->status & IRQ_MASKED;
+	masked = desc->istate & IRQS_MASKED;
 	if (!masked)
-		desc->irq_data.chip->irq_mask(&desc->irq_data);
-	move_masked_irq(irq);
+		idata->chip->irq_mask(idata);
+	irq_move_masked_irq(idata);
 	if (!masked)
-		desc->irq_data.chip->irq_unmask(&desc->irq_data);
+		idata->chip->irq_unmask(idata);
+}
+
+void move_native_irq(int irq)
+{
+	irq_move_irq(irq_get_irq_data(irq));
 }
diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c
index 0d4005d8..f76fc00 100644
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -18,7 +18,7 @@
  * During system-wide suspend or hibernation device drivers need to be prevented
  * from receiving interrupts and this function is provided for this purpose.
  * It marks all interrupt lines in use, except for the timer ones, as disabled
- * and sets the IRQ_SUSPENDED flag for each of them.
+ * and sets the IRQS_SUSPENDED flag for each of them.
  */
 void suspend_device_irqs(void)
 {
@@ -34,7 +34,7 @@ void suspend_device_irqs(void)
 	}
 
 	for_each_irq_desc(irq, desc)
-		if (desc->status & IRQ_SUSPENDED)
+		if (desc->istate & IRQS_SUSPENDED)
 			synchronize_irq(irq);
 }
 EXPORT_SYMBOL_GPL(suspend_device_irqs);
@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);
  * resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs()
  *
  * Enable all interrupt lines previously disabled by suspend_device_irqs() that
- * have the IRQ_SUSPENDED flag set.
+ * have the IRQS_SUSPENDED flag set.
  */
 void resume_device_irqs(void)
 {
@@ -53,9 +53,6 @@ void resume_device_irqs(void)
 	for_each_irq_desc(irq, desc) {
 		unsigned long flags;
 
-		if (!(desc->status & IRQ_SUSPENDED))
-			continue;
-
 		raw_spin_lock_irqsave(&desc->lock, flags);
 		__enable_irq(desc, irq, true);
 		raw_spin_unlock_irqrestore(&desc->lock, flags);
@@ -71,9 +68,24 @@ int check_wakeup_irqs(void)
 	struct irq_desc *desc;
 	int irq;
 
-	for_each_irq_desc(irq, desc)
-		if ((desc->status & IRQ_WAKEUP) && (desc->status & IRQ_PENDING))
-			return -EBUSY;
+	for_each_irq_desc(irq, desc) {
+		if (irqd_is_wakeup_set(&desc->irq_data)) {
+			if (desc->istate & IRQS_PENDING)
+				return -EBUSY;
+			continue;
+		}
+		/*
+		 * Check the non wakeup interrupts whether they need
+		 * to be masked before finally going into suspend
+		 * state. That's for hardware which has no wakeup
+		 * source configuration facility. The chip
+		 * implementation indicates that with
+		 * IRQCHIP_MASK_ON_SUSPEND.
+		 */
+		if (desc->istate & IRQS_SUSPENDED &&
+		    irq_desc_get_chip(desc)->flags & IRQCHIP_MASK_ON_SUSPEND)
+			mask_irq(desc);
+	}
 
 	return 0;
 }
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 6c8a2a9..760248d 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -11,6 +11,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
 
 #include "internals.h"
 
@@ -24,7 +25,7 @@ static int irq_affinity_proc_show(struct seq_file *m, void *v)
 	const struct cpumask *mask = desc->irq_data.affinity;
 
 #ifdef CONFIG_GENERIC_PENDING_IRQ
-	if (desc->status & IRQ_MOVE_PENDING)
+	if (irqd_is_setaffinity_pending(&desc->irq_data))
 		mask = desc->pending_mask;
 #endif
 	seq_cpumask(m, mask);
@@ -65,8 +66,7 @@ static ssize_t irq_affinity_proc_write(struct file *file,
 	cpumask_var_t new_value;
 	int err;
 
-	if (!irq_to_desc(irq)->irq_data.chip->irq_set_affinity || no_irq_affinity ||
-	    irq_balancing_disabled(irq))
+	if (!irq_can_set_affinity(irq) || no_irq_affinity)
 		return -EIO;
 
 	if (!alloc_cpumask_var(&new_value, GFP_KERNEL))
@@ -89,7 +89,7 @@ static ssize_t irq_affinity_proc_write(struct file *file,
 	if (!cpumask_intersects(new_value, cpu_online_mask)) {
 		/* Special case for empty set - allow the architecture
 		   code to set default SMP affinity. */
-		err = irq_select_affinity_usr(irq) ? -EINVAL : count;
+		err = irq_select_affinity_usr(irq, new_value) ? -EINVAL : count;
 	} else {
 		irq_set_affinity(irq, new_value);
 		err = count;
@@ -357,3 +357,66 @@ void init_irq_proc(void)
 	}
 }
 
+#ifdef CONFIG_GENERIC_IRQ_SHOW
+
+int __weak arch_show_interrupts(struct seq_file *p, int prec)
+{
+	return 0;
+}
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	static int prec;
+
+	unsigned long flags, any_count = 0;
+	int i = *(loff_t *) v, j;
+	struct irqaction *action;
+	struct irq_desc *desc;
+
+	if (i > nr_irqs)
+		return 0;
+
+	if (i == nr_irqs)
+		return arch_show_interrupts(p, prec);
+
+	/* print header and calculate the width of the first column */
+	if (i == 0) {
+		for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
+			j *= 10;
+
+		seq_printf(p, "%*s", prec + 8, "");
+		for_each_online_cpu(j)
+			seq_printf(p, "CPU%-8d", j);
+		seq_putc(p, '\n');
+	}
+
+	desc = irq_to_desc(i);
+	if (!desc)
+		return 0;
+
+	raw_spin_lock_irqsave(&desc->lock, flags);
+	for_each_online_cpu(j)
+		any_count |= kstat_irqs_cpu(i, j);
+	action = desc->action;
+	if (!action && !any_count)
+		goto out;
+
+	seq_printf(p, "%*d: ", prec, i);
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
+	seq_printf(p, " %8s", desc->irq_data.chip->name);
+	if (desc->name)
+		seq_printf(p, "-%-8s", desc->name);
+
+	if (action) {
+		seq_printf(p, "  %s", action->name);
+		while ((action = action->next) != NULL)
+			seq_printf(p, ", %s", action->name);
+	}
+
+	seq_putc(p, '\n');
+out:
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
+	return 0;
+}
+#endif
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index dc49358..ad683a9 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -55,20 +55,19 @@ static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0);
  */
 void check_irq_resend(struct irq_desc *desc, unsigned int irq)
 {
-	unsigned int status = desc->status;
-
-	/*
-	 * Make sure the interrupt is enabled, before resending it:
-	 */
-	desc->irq_data.chip->irq_enable(&desc->irq_data);
-
 	/*
 	 * We do not resend level type interrupts. Level type
 	 * interrupts are resent by hardware when they are still
 	 * active.
 	 */
-	if ((status & (IRQ_LEVEL | IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-		desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY;
+	if (irq_settings_is_level(desc))
+		return;
+	if (desc->istate & IRQS_REPLAY)
+		return;
+	if (desc->istate & IRQS_PENDING) {
+		irq_compat_clr_pending(desc);
+		desc->istate &= ~IRQS_PENDING;
+		desc->istate |= IRQS_REPLAY;
 
 		if (!desc->irq_data.chip->irq_retrigger ||
 		    !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h
new file mode 100644
index 0000000..0227ad3
--- /dev/null
+++ b/kernel/irq/settings.h
@@ -0,0 +1,138 @@
+/*
+ * Internal header to deal with irq_desc->status which will be renamed
+ * to irq_desc->settings.
+ */
+enum {
+	_IRQ_DEFAULT_INIT_FLAGS	= IRQ_DEFAULT_INIT_FLAGS,
+	_IRQ_PER_CPU		= IRQ_PER_CPU,
+	_IRQ_LEVEL		= IRQ_LEVEL,
+	_IRQ_NOPROBE		= IRQ_NOPROBE,
+	_IRQ_NOREQUEST		= IRQ_NOREQUEST,
+	_IRQ_NOAUTOEN		= IRQ_NOAUTOEN,
+	_IRQ_MOVE_PCNTXT	= IRQ_MOVE_PCNTXT,
+	_IRQ_NO_BALANCING	= IRQ_NO_BALANCING,
+	_IRQ_NESTED_THREAD	= IRQ_NESTED_THREAD,
+	_IRQF_MODIFY_MASK	= IRQF_MODIFY_MASK,
+};
+
+#define IRQ_INPROGRESS		GOT_YOU_MORON
+#define IRQ_REPLAY		GOT_YOU_MORON
+#define IRQ_WAITING		GOT_YOU_MORON
+#define IRQ_DISABLED		GOT_YOU_MORON
+#define IRQ_PENDING		GOT_YOU_MORON
+#define IRQ_MASKED		GOT_YOU_MORON
+#define IRQ_WAKEUP		GOT_YOU_MORON
+#define IRQ_MOVE_PENDING	GOT_YOU_MORON
+#define IRQ_PER_CPU		GOT_YOU_MORON
+#define IRQ_NO_BALANCING	GOT_YOU_MORON
+#define IRQ_AFFINITY_SET	GOT_YOU_MORON
+#define IRQ_LEVEL		GOT_YOU_MORON
+#define IRQ_NOPROBE		GOT_YOU_MORON
+#define IRQ_NOREQUEST		GOT_YOU_MORON
+#define IRQ_NOAUTOEN		GOT_YOU_MORON
+#define IRQ_NESTED_THREAD	GOT_YOU_MORON
+#undef IRQF_MODIFY_MASK
+#define IRQF_MODIFY_MASK	GOT_YOU_MORON
+
+static inline void
+irq_settings_clr_and_set(struct irq_desc *desc, u32 clr, u32 set)
+{
+	desc->status &= ~(clr & _IRQF_MODIFY_MASK);
+	desc->status |= (set & _IRQF_MODIFY_MASK);
+}
+
+static inline bool irq_settings_is_per_cpu(struct irq_desc *desc)
+{
+	return desc->status & _IRQ_PER_CPU;
+}
+
+static inline void irq_settings_set_per_cpu(struct irq_desc *desc)
+{
+	desc->status |= _IRQ_PER_CPU;
+}
+
+static inline void irq_settings_set_no_balancing(struct irq_desc *desc)
+{
+	desc->status |= _IRQ_NO_BALANCING;
+}
+
+static inline bool irq_settings_has_no_balance_set(struct irq_desc *desc)
+{
+	return desc->status & _IRQ_NO_BALANCING;
+}
+
+static inline u32 irq_settings_get_trigger_mask(struct irq_desc *desc)
+{
+	return desc->status & IRQ_TYPE_SENSE_MASK;
+}
+
+static inline void
+irq_settings_set_trigger_mask(struct irq_desc *desc, u32 mask)
+{
+	desc->status &= ~IRQ_TYPE_SENSE_MASK;
+	desc->status |= mask & IRQ_TYPE_SENSE_MASK;
+}
+
+static inline bool irq_settings_is_level(struct irq_desc *desc)
+{
+	return desc->status & _IRQ_LEVEL;
+}
+
+static inline void irq_settings_clr_level(struct irq_desc *desc)
+{
+	desc->status &= ~_IRQ_LEVEL;
+}
+
+static inline void irq_settings_set_level(struct irq_desc *desc)
+{
+	desc->status |= _IRQ_LEVEL;
+}
+
+static inline bool irq_settings_can_request(struct irq_desc *desc)
+{
+	return !(desc->status & _IRQ_NOREQUEST);
+}
+
+static inline void irq_settings_clr_norequest(struct irq_desc *desc)
+{
+	desc->status &= ~_IRQ_NOREQUEST;
+}
+
+static inline void irq_settings_set_norequest(struct irq_desc *desc)
+{
+	desc->status |= _IRQ_NOREQUEST;
+}
+
+static inline bool irq_settings_can_probe(struct irq_desc *desc)
+{
+	return !(desc->status & _IRQ_NOPROBE);
+}
+
+static inline void irq_settings_clr_noprobe(struct irq_desc *desc)
+{
+	desc->status &= ~_IRQ_NOPROBE;
+}
+
+static inline void irq_settings_set_noprobe(struct irq_desc *desc)
+{
+	desc->status |= _IRQ_NOPROBE;
+}
+
+static inline bool irq_settings_can_move_pcntxt(struct irq_desc *desc)
+{
+	return desc->status & _IRQ_MOVE_PCNTXT;
+}
+
+static inline bool irq_settings_can_autoenable(struct irq_desc *desc)
+{
+	return !(desc->status & _IRQ_NOAUTOEN);
+}
+
+static inline bool irq_settings_is_nested_thread(struct irq_desc *desc)
+{
+	return desc->status & _IRQ_NESTED_THREAD;
+}
+
+/* Nothing should touch desc->status from now on */
+#undef status
+#define status		USE_THE_PROPER_WRAPPERS_YOU_MORON
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 3089d3b..dd586eb 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -21,70 +21,94 @@ static int irqfixup __read_mostly;
 #define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)
 static void poll_spurious_irqs(unsigned long dummy);
 static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0);
+static int irq_poll_cpu;
+static atomic_t irq_poll_active;
+
+/*
+ * We wait here for a poller to finish.
+ *
+ * If the poll runs on this CPU, then we yell loudly and return
+ * false. That will leave the interrupt line disabled in the worst
+ * case, but it should never happen.
+ *
+ * We wait until the poller is done and then recheck disabled and
+ * action (about to be disabled). Only if it's still active, we return
+ * true and let the handler run.
+ */
+bool irq_wait_for_poll(struct irq_desc *desc)
+{
+	if (WARN_ONCE(irq_poll_cpu == smp_processor_id(),
+		      "irq poll in progress on cpu %d for irq %d\n",
+		      smp_processor_id(), desc->irq_data.irq))
+		return false;
+
+#ifdef CONFIG_SMP
+	do {
+		raw_spin_unlock(&desc->lock);
+		while (desc->istate & IRQS_INPROGRESS)
+			cpu_relax();
+		raw_spin_lock(&desc->lock);
+	} while (desc->istate & IRQS_INPROGRESS);
+	/* Might have been disabled in meantime */
+	return !(desc->istate & IRQS_DISABLED) && desc->action;
+#else
+	return false;
+#endif
+}
+
 
 /*
  * Recovery handler for misrouted interrupts.
  */
-static int try_one_irq(int irq, struct irq_desc *desc)
+static int try_one_irq(int irq, struct irq_desc *desc, bool force)
 {
+	irqreturn_t ret = IRQ_NONE;
 	struct irqaction *action;
-	int ok = 0, work = 0;
 
 	raw_spin_lock(&desc->lock);
-	/* Already running on another processor */
-	if (desc->status & IRQ_INPROGRESS) {
-		/*
-		 * Already running: If it is shared get the other
-		 * CPU to go looking for our mystery interrupt too
-		 */
-		if (desc->action && (desc->action->flags & IRQF_SHARED))
-			desc->status |= IRQ_PENDING;
-		raw_spin_unlock(&desc->lock);
-		return ok;
-	}
-	/* Honour the normal IRQ locking */
-	desc->status |= IRQ_INPROGRESS;
-	action = desc->action;
-	raw_spin_unlock(&desc->lock);
 
-	while (action) {
-		/* Only shared IRQ handlers are safe to call */
-		if (action->flags & IRQF_SHARED) {
-			if (action->handler(irq, action->dev_id) ==
-				IRQ_HANDLED)
-				ok = 1;
-		}
-		action = action->next;
-	}
-	local_irq_disable();
-	/* Now clean up the flags */
-	raw_spin_lock(&desc->lock);
-	action = desc->action;
+	/* PER_CPU and nested thread interrupts are never polled */
+	if (irq_settings_is_per_cpu(desc) || irq_settings_is_nested_thread(desc))
+		goto out;
 
 	/*
-	 * While we were looking for a fixup someone queued a real
-	 * IRQ clashing with our walk:
+	 * Do not poll disabled interrupts unless the spurious
+	 * disabled poller asks explicitely.
 	 */
-	while ((desc->status & IRQ_PENDING) && action) {
+	if ((desc->istate & IRQS_DISABLED) && !force)
+		goto out;
+
+	/*
+	 * All handlers must agree on IRQF_SHARED, so we test just the
+	 * first. Check for action->next as well.
+	 */
+	action = desc->action;
+	if (!action || !(action->flags & IRQF_SHARED) ||
+	    (action->flags & __IRQF_TIMER) || !action->next)
+		goto out;
+
+	/* Already running on another processor */
+	if (desc->istate & IRQS_INPROGRESS) {
 		/*
-		 * Perform real IRQ processing for the IRQ we deferred
+		 * Already running: If it is shared get the other
+		 * CPU to go looking for our mystery interrupt too
 		 */
-		work = 1;
-		raw_spin_unlock(&desc->lock);
-		handle_IRQ_event(irq, action);
-		raw_spin_lock(&desc->lock);
-		desc->status &= ~IRQ_PENDING;
+		irq_compat_set_pending(desc);
+		desc->istate |= IRQS_PENDING;
+		goto out;
 	}
-	desc->status &= ~IRQ_INPROGRESS;
-	/*
-	 * If we did actual work for the real IRQ line we must let the
-	 * IRQ controller clean up too
-	 */
-	if (work)
-		irq_end(irq, desc);
-	raw_spin_unlock(&desc->lock);
 
-	return ok;
+	/* Mark it poll in progress */
+	desc->istate |= IRQS_POLL_INPROGRESS;
+	do {
+		if (handle_irq_event(desc) == IRQ_HANDLED)
+			ret = IRQ_HANDLED;
+		action = desc->action;
+	} while ((desc->istate & IRQS_PENDING) && action);
+	desc->istate &= ~IRQS_POLL_INPROGRESS;
+out:
+	raw_spin_unlock(&desc->lock);
+	return ret == IRQ_HANDLED;
 }
 
 static int misrouted_irq(int irq)
@@ -92,6 +116,11 @@ static int misrouted_irq(int irq)
 	struct irq_desc *desc;
 	int i, ok = 0;
 
+	if (atomic_inc_return(&irq_poll_active) == 1)
+		goto out;
+
+	irq_poll_cpu = smp_processor_id();
+
 	for_each_irq_desc(i, desc) {
 		if (!i)
 			 continue;
@@ -99,9 +128,11 @@ static int misrouted_irq(int irq)
 		if (i == irq)	/* Already tried */
 			continue;
 
-		if (try_one_irq(i, desc))
+		if (try_one_irq(i, desc, false))
 			ok = 1;
 	}
+out:
+	atomic_dec(&irq_poll_active);
 	/* So the caller can adjust the irq error counts */
 	return ok;
 }
@@ -111,23 +142,28 @@ static void poll_spurious_irqs(unsigned long dummy)
 	struct irq_desc *desc;
 	int i;
 
+	if (atomic_inc_return(&irq_poll_active) != 1)
+		goto out;
+	irq_poll_cpu = smp_processor_id();
+
 	for_each_irq_desc(i, desc) {
-		unsigned int status;
+		unsigned int state;
 
 		if (!i)
 			 continue;
 
 		/* Racy but it doesn't matter */
-		status = desc->status;
+		state = desc->istate;
 		barrier();
-		if (!(status & IRQ_SPURIOUS_DISABLED))
+		if (!(state & IRQS_SPURIOUS_DISABLED))
 			continue;
 
 		local_irq_disable();
-		try_one_irq(i, desc);
+		try_one_irq(i, desc, true);
 		local_irq_enable();
 	}
-
+out:
+	atomic_dec(&irq_poll_active);
 	mod_timer(&poll_spurious_irq_timer,
 		  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
 }
@@ -139,15 +175,13 @@ static void poll_spurious_irqs(unsigned long dummy)
  *
  * (The other 100-of-100,000 interrupts may have been a correctly
  *  functioning device sharing an IRQ with the failing one)
- *
- * Called under desc->lock
  */
-
 static void
 __report_bad_irq(unsigned int irq, struct irq_desc *desc,
 		 irqreturn_t action_ret)
 {
 	struct irqaction *action;
+	unsigned long flags;
 
 	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
 		printk(KERN_ERR "irq event %d: bogus return value %x\n",
@@ -159,6 +193,13 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
 	dump_stack();
 	printk(KERN_ERR "handlers:\n");
 
+	/*
+	 * We need to take desc->lock here. note_interrupt() is called
+	 * w/o desc->lock held, but IRQ_PROGRESS set. We might race
+	 * with something else removing an action. It's ok to take
+	 * desc->lock here. See synchronize_irq().
+	 */
+	raw_spin_lock_irqsave(&desc->lock, flags);
 	action = desc->action;
 	while (action) {
 		printk(KERN_ERR "[<%p>]", action->handler);
@@ -167,6 +208,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
 		printk("\n");
 		action = action->next;
 	}
+	raw_spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 static void
@@ -218,6 +260,9 @@ try_misrouted_irq(unsigned int irq, struct irq_desc *desc,
 void note_interrupt(unsigned int irq, struct irq_desc *desc,
 		    irqreturn_t action_ret)
 {
+	if (desc->istate & IRQS_POLL_INPROGRESS)
+		return;
+
 	if (unlikely(action_ret != IRQ_HANDLED)) {
 		/*
 		 * If we are seeing only the odd spurious IRQ caused by
@@ -254,9 +299,9 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
 		 * Now kill the IRQ
 		 */
 		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
-		desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
+		desc->istate |= IRQS_SPURIOUS_DISABLED;
 		desc->depth++;
-		desc->irq_data.chip->irq_disable(&desc->irq_data);
+		irq_disable(desc);
 
 		mod_timer(&poll_spurious_irq_timer,
 			  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c
index 6f6d091..75dcca3 100644
--- a/kernel/kallsyms.c
+++ b/kernel/kallsyms.c
@@ -477,13 +477,11 @@ static int s_show(struct seq_file *m, void *p)
 		 */
 		type = iter->exported ? toupper(iter->type) :
 					tolower(iter->type);
-		seq_printf(m, "%0*lx %c %s\t[%s]\n",
-			   (int)(2 * sizeof(void *)),
-			   iter->value, type, iter->name, iter->module_name);
+		seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
+			   type, iter->name, iter->module_name);
 	} else
-		seq_printf(m, "%0*lx %c %s\n",
-			   (int)(2 * sizeof(void *)),
-			   iter->value, iter->type, iter->name);
+		seq_printf(m, "%pK %c %s\n", (void *)iter->value,
+			   iter->type, iter->name);
 	return 0;
 }
 
diff --git a/kernel/kthread.c b/kernel/kthread.c
index c55afba..684ab3f 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -27,6 +27,7 @@ struct kthread_create_info
 	/* Information passed to kthread() from kthreadd. */
 	int (*threadfn)(void *data);
 	void *data;
+	int node;
 
 	/* Result passed back to kthread_create() from kthreadd. */
 	struct task_struct *result;
@@ -98,10 +99,23 @@ static int kthread(void *_create)
 	do_exit(ret);
 }
 
+/* called from do_fork() to get node information for about to be created task */
+int tsk_fork_get_node(struct task_struct *tsk)
+{
+#ifdef CONFIG_NUMA
+	if (tsk == kthreadd_task)
+		return tsk->pref_node_fork;
+#endif
+	return numa_node_id();
+}
+
 static void create_kthread(struct kthread_create_info *create)
 {
 	int pid;
 
+#ifdef CONFIG_NUMA
+	current->pref_node_fork = create->node;
+#endif
 	/* We want our own signal handler (we take no signals by default). */
 	pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
 	if (pid < 0) {
@@ -111,15 +125,18 @@ static void create_kthread(struct kthread_create_info *create)
 }
 
 /**
- * kthread_create - create a kthread.
+ * kthread_create_on_node - create a kthread.
  * @threadfn: the function to run until signal_pending(current).
  * @data: data ptr for @threadfn.
+ * @node: memory node number.
  * @namefmt: printf-style name for the thread.
  *
  * Description: This helper function creates and names a kernel
  * thread.  The thread will be stopped: use wake_up_process() to start
  * it.  See also kthread_run().
  *
+ * If thread is going to be bound on a particular cpu, give its node
+ * in @node, to get NUMA affinity for kthread stack, or else give -1.
  * When woken, the thread will run @threadfn() with @data as its
  * argument. @threadfn() can either call do_exit() directly if it is a
  * standalone thread for which noone will call kthread_stop(), or
@@ -129,15 +146,17 @@ static void create_kthread(struct kthread_create_info *create)
  *
  * Returns a task_struct or ERR_PTR(-ENOMEM).
  */
-struct task_struct *kthread_create(int (*threadfn)(void *data),
-				   void *data,
-				   const char namefmt[],
-				   ...)
+struct task_struct *kthread_create_on_node(int (*threadfn)(void *data),
+					   void *data,
+					   int node,
+					   const char namefmt[],
+					   ...)
 {
 	struct kthread_create_info create;
 
 	create.threadfn = threadfn;
 	create.data = data;
+	create.node = node;
 	init_completion(&create.done);
 
 	spin_lock(&kthread_create_lock);
@@ -164,7 +183,7 @@ struct task_struct *kthread_create(int (*threadfn)(void *data),
 	}
 	return create.result;
 }
-EXPORT_SYMBOL(kthread_create);
+EXPORT_SYMBOL(kthread_create_on_node);
 
 /**
  * kthread_bind - bind a just-created kthread to a cpu.
diff --git a/kernel/module.c b/kernel/module.c
index efa290e..1f9f7bc 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1168,7 +1168,7 @@ static ssize_t module_sect_show(struct module_attribute *mattr,
 {
 	struct module_sect_attr *sattr =
 		container_of(mattr, struct module_sect_attr, mattr);
-	return sprintf(buf, "0x%lx\n", sattr->address);
+	return sprintf(buf, "0x%pK\n", (void *)sattr->address);
 }
 
 static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
@@ -3224,7 +3224,7 @@ static int m_show(struct seq_file *m, void *p)
 		   mod->state == MODULE_STATE_COMING ? "Loading":
 		   "Live");
 	/* Used by oprofile and other similar tools. */
-	seq_printf(m, " 0x%p", mod->module_core);
+	seq_printf(m, " 0x%pK", mod->module_core);
 
 	/* Taints info */
 	if (mod->taints)
diff --git a/kernel/panic.c b/kernel/panic.c
index 991bb87..6923167 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -433,3 +433,13 @@ EXPORT_SYMBOL(__stack_chk_fail);
 
 core_param(panic, panic_timeout, int, 0644);
 core_param(pause_on_oops, pause_on_oops, int, 0644);
+
+static int __init oops_setup(char *s)
+{
+	if (!s)
+		return -EINVAL;
+	if (!strcmp(s, "panic"))
+		panic_on_oops = 1;
+	return 0;
+}
+early_param("oops", oops_setup);
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index 656222f..3472bb1 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -38,13 +38,96 @@
 
 #include <asm/irq_regs.h>
 
+struct remote_function_call {
+	struct task_struct *p;
+	int (*func)(void *info);
+	void *info;
+	int ret;
+};
+
+static void remote_function(void *data)
+{
+	struct remote_function_call *tfc = data;
+	struct task_struct *p = tfc->p;
+
+	if (p) {
+		tfc->ret = -EAGAIN;
+		if (task_cpu(p) != smp_processor_id() || !task_curr(p))
+			return;
+	}
+
+	tfc->ret = tfc->func(tfc->info);
+}
+
+/**
+ * task_function_call - call a function on the cpu on which a task runs
+ * @p:		the task to evaluate
+ * @func:	the function to be called
+ * @info:	the function call argument
+ *
+ * Calls the function @func when the task is currently running. This might
+ * be on the current CPU, which just calls the function directly
+ *
+ * returns: @func return value, or
+ *	    -ESRCH  - when the process isn't running
+ *	    -EAGAIN - when the process moved away
+ */
+static int
+task_function_call(struct task_struct *p, int (*func) (void *info), void *info)
+{
+	struct remote_function_call data = {
+		.p = p,
+		.func = func,
+		.info = info,
+		.ret = -ESRCH, /* No such (running) process */
+	};
+
+	if (task_curr(p))
+		smp_call_function_single(task_cpu(p), remote_function, &data, 1);
+
+	return data.ret;
+}
+
+/**
+ * cpu_function_call - call a function on the cpu
+ * @func:	the function to be called
+ * @info:	the function call argument
+ *
+ * Calls the function @func on the remote cpu.
+ *
+ * returns: @func return value or -ENXIO when the cpu is offline
+ */
+static int cpu_function_call(int cpu, int (*func) (void *info), void *info)
+{
+	struct remote_function_call data = {
+		.p = NULL,
+		.func = func,
+		.info = info,
+		.ret = -ENXIO, /* No such CPU */
+	};
+
+	smp_call_function_single(cpu, remote_function, &data, 1);
+
+	return data.ret;
+}
+
+#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\
+		       PERF_FLAG_FD_OUTPUT  |\
+		       PERF_FLAG_PID_CGROUP)
+
 enum event_type_t {
 	EVENT_FLEXIBLE = 0x1,
 	EVENT_PINNED = 0x2,
 	EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED,
 };
 
-atomic_t perf_task_events __read_mostly;
+/*
+ * perf_sched_events : >0 events exist
+ * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu
+ */
+atomic_t perf_sched_events __read_mostly;
+static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
+
 static atomic_t nr_mmap_events __read_mostly;
 static atomic_t nr_comm_events __read_mostly;
 static atomic_t nr_task_events __read_mostly;
@@ -67,7 +150,24 @@ int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
 /*
  * max perf event sample rate
  */
-int sysctl_perf_event_sample_rate __read_mostly = 100000;
+#define DEFAULT_MAX_SAMPLE_RATE 100000
+int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE;
+static int max_samples_per_tick __read_mostly =
+	DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ);
+
+int perf_proc_update_handler(struct ctl_table *table, int write,
+		void __user *buffer, size_t *lenp,
+		loff_t *ppos)
+{
+	int ret = proc_dointvec(table, write, buffer, lenp, ppos);
+
+	if (ret || !write)
+		return ret;
+
+	max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
+
+	return 0;
+}
 
 static atomic64_t perf_event_id;
 
@@ -75,7 +175,11 @@ static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx,
 			      enum event_type_t event_type);
 
 static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
-			     enum event_type_t event_type);
+			     enum event_type_t event_type,
+			     struct task_struct *task);
+
+static void update_context_time(struct perf_event_context *ctx);
+static u64 perf_event_time(struct perf_event *event);
 
 void __weak perf_event_print_debug(void)	{ }
 
@@ -89,6 +193,360 @@ static inline u64 perf_clock(void)
 	return local_clock();
 }
 
+static inline struct perf_cpu_context *
+__get_cpu_context(struct perf_event_context *ctx)
+{
+	return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
+}
+
+#ifdef CONFIG_CGROUP_PERF
+
+/*
+ * 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.
+ */
+static inline struct perf_cgroup *
+perf_cgroup_from_task(struct task_struct *task)
+{
+	return container_of(task_subsys_state(task, perf_subsys_id),
+			struct perf_cgroup, css);
+}
+
+static inline bool
+perf_cgroup_match(struct perf_event *event)
+{
+	struct perf_event_context *ctx = event->ctx;
+	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
+
+	return !event->cgrp || event->cgrp == cpuctx->cgrp;
+}
+
+static inline void perf_get_cgroup(struct perf_event *event)
+{
+	css_get(&event->cgrp->css);
+}
+
+static inline void perf_put_cgroup(struct perf_event *event)
+{
+	css_put(&event->cgrp->css);
+}
+
+static inline void perf_detach_cgroup(struct perf_event *event)
+{
+	perf_put_cgroup(event);
+	event->cgrp = NULL;
+}
+
+static inline int is_cgroup_event(struct perf_event *event)
+{
+	return event->cgrp != NULL;
+}
+
+static inline u64 perf_cgroup_event_time(struct perf_event *event)
+{
+	struct perf_cgroup_info *t;
+
+	t = per_cpu_ptr(event->cgrp->info, event->cpu);
+	return t->time;
+}
+
+static inline void __update_cgrp_time(struct perf_cgroup *cgrp)
+{
+	struct perf_cgroup_info *info;
+	u64 now;
+
+	now = perf_clock();
+
+	info = this_cpu_ptr(cgrp->info);
+
+	info->time += now - info->timestamp;
+	info->timestamp = now;
+}
+
+static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
+{
+	struct perf_cgroup *cgrp_out = cpuctx->cgrp;
+	if (cgrp_out)
+		__update_cgrp_time(cgrp_out);
+}
+
+static inline void update_cgrp_time_from_event(struct perf_event *event)
+{
+	struct perf_cgroup *cgrp;
+
+	/*
+	 * ensure we access cgroup data only when needed and
+	 * when we know the cgroup is pinned (css_get)
+	 */
+	if (!is_cgroup_event(event))
+		return;
+
+	cgrp = perf_cgroup_from_task(current);
+	/*
+	 * Do not update time when cgroup is not active
+	 */
+	if (cgrp == event->cgrp)
+		__update_cgrp_time(event->cgrp);
+}
+
+static inline void
+perf_cgroup_set_timestamp(struct task_struct *task,
+			  struct perf_event_context *ctx)
+{
+	struct perf_cgroup *cgrp;
+	struct perf_cgroup_info *info;
+
+	/*
+	 * ctx->lock held by caller
+	 * ensure we do not access cgroup data
+	 * unless we have the cgroup pinned (css_get)
+	 */
+	if (!task || !ctx->nr_cgroups)
+		return;
+
+	cgrp = perf_cgroup_from_task(task);
+	info = this_cpu_ptr(cgrp->info);
+	info->timestamp = ctx->timestamp;
+}
+
+#define PERF_CGROUP_SWOUT	0x1 /* cgroup switch out every event */
+#define PERF_CGROUP_SWIN	0x2 /* cgroup switch in events based on task */
+
+/*
+ * reschedule events based on the cgroup constraint of task.
+ *
+ * mode SWOUT : schedule out everything
+ * mode SWIN : schedule in based on cgroup for next
+ */
+void perf_cgroup_switch(struct task_struct *task, int mode)
+{
+	struct perf_cpu_context *cpuctx;
+	struct pmu *pmu;
+	unsigned long flags;
+
+	/*
+	 * disable interrupts to avoid geting nr_cgroup
+	 * changes via __perf_event_disable(). Also
+	 * avoids preemption.
+	 */
+	local_irq_save(flags);
+
+	/*
+	 * we reschedule only in the presence of cgroup
+	 * constrained events.
+	 */
+	rcu_read_lock();
+
+	list_for_each_entry_rcu(pmu, &pmus, entry) {
+
+		cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
+
+		perf_pmu_disable(cpuctx->ctx.pmu);
+
+		/*
+		 * perf_cgroup_events says at least one
+		 * context on this CPU has cgroup events.
+		 *
+		 * ctx->nr_cgroups reports the number of cgroup
+		 * events for a context.
+		 */
+		if (cpuctx->ctx.nr_cgroups > 0) {
+
+			if (mode & PERF_CGROUP_SWOUT) {
+				cpu_ctx_sched_out(cpuctx, EVENT_ALL);
+				/*
+				 * must not be done before ctxswout due
+				 * to event_filter_match() in event_sched_out()
+				 */
+				cpuctx->cgrp = NULL;
+			}
+
+			if (mode & PERF_CGROUP_SWIN) {
+				/* set cgrp before ctxsw in to
+				 * allow event_filter_match() to not
+				 * have to pass task around
+				 */
+				cpuctx->cgrp = perf_cgroup_from_task(task);
+				cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
+			}
+		}
+
+		perf_pmu_enable(cpuctx->ctx.pmu);
+	}
+
+	rcu_read_unlock();
+
+	local_irq_restore(flags);
+}
+
+static inline void perf_cgroup_sched_out(struct task_struct *task)
+{
+	perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
+}
+
+static inline void perf_cgroup_sched_in(struct task_struct *task)
+{
+	perf_cgroup_switch(task, PERF_CGROUP_SWIN);
+}
+
+static inline int perf_cgroup_connect(int fd, struct perf_event *event,
+				      struct perf_event_attr *attr,
+				      struct perf_event *group_leader)
+{
+	struct perf_cgroup *cgrp;
+	struct cgroup_subsys_state *css;
+	struct file *file;
+	int ret = 0, fput_needed;
+
+	file = fget_light(fd, &fput_needed);
+	if (!file)
+		return -EBADF;
+
+	css = cgroup_css_from_dir(file, perf_subsys_id);
+	if (IS_ERR(css)) {
+		ret = PTR_ERR(css);
+		goto out;
+	}
+
+	cgrp = container_of(css, struct perf_cgroup, css);
+	event->cgrp = cgrp;
+
+	/* must be done before we fput() the file */
+	perf_get_cgroup(event);
+
+	/*
+	 * all events in a group must monitor
+	 * the same cgroup because a task belongs
+	 * to only one perf cgroup at a time
+	 */
+	if (group_leader && group_leader->cgrp != cgrp) {
+		perf_detach_cgroup(event);
+		ret = -EINVAL;
+	}
+out:
+	fput_light(file, fput_needed);
+	return ret;
+}
+
+static inline void
+perf_cgroup_set_shadow_time(struct perf_event *event, u64 now)
+{
+	struct perf_cgroup_info *t;
+	t = per_cpu_ptr(event->cgrp->info, event->cpu);
+	event->shadow_ctx_time = now - t->timestamp;
+}
+
+static inline void
+perf_cgroup_defer_enabled(struct perf_event *event)
+{
+	/*
+	 * when the current task's perf cgroup does not match
+	 * the event's, we need to remember to call the
+	 * perf_mark_enable() function the first time a task with
+	 * a matching perf cgroup is scheduled in.
+	 */
+	if (is_cgroup_event(event) && !perf_cgroup_match(event))
+		event->cgrp_defer_enabled = 1;
+}
+
+static inline void
+perf_cgroup_mark_enabled(struct perf_event *event,
+			 struct perf_event_context *ctx)
+{
+	struct perf_event *sub;
+	u64 tstamp = perf_event_time(event);
+
+	if (!event->cgrp_defer_enabled)
+		return;
+
+	event->cgrp_defer_enabled = 0;
+
+	event->tstamp_enabled = tstamp - event->total_time_enabled;
+	list_for_each_entry(sub, &event->sibling_list, group_entry) {
+		if (sub->state >= PERF_EVENT_STATE_INACTIVE) {
+			sub->tstamp_enabled = tstamp - sub->total_time_enabled;
+			sub->cgrp_defer_enabled = 0;
+		}
+	}
+}
+#else /* !CONFIG_CGROUP_PERF */
+
+static inline bool
+perf_cgroup_match(struct perf_event *event)
+{
+	return true;
+}
+
+static inline void perf_detach_cgroup(struct perf_event *event)
+{}
+
+static inline int is_cgroup_event(struct perf_event *event)
+{
+	return 0;
+}
+
+static inline u64 perf_cgroup_event_cgrp_time(struct perf_event *event)
+{
+	return 0;
+}
+
+static inline void update_cgrp_time_from_event(struct perf_event *event)
+{
+}
+
+static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx)
+{
+}
+
+static inline void perf_cgroup_sched_out(struct task_struct *task)
+{
+}
+
+static inline void perf_cgroup_sched_in(struct task_struct *task)
+{
+}
+
+static inline int perf_cgroup_connect(pid_t pid, struct perf_event *event,
+				      struct perf_event_attr *attr,
+				      struct perf_event *group_leader)
+{
+	return -EINVAL;
+}
+
+static inline void
+perf_cgroup_set_timestamp(struct task_struct *task,
+			  struct perf_event_context *ctx)
+{
+}
+
+void
+perf_cgroup_switch(struct task_struct *task, struct task_struct *next)
+{
+}
+
+static inline void
+perf_cgroup_set_shadow_time(struct perf_event *event, u64 now)
+{
+}
+
+static inline u64 perf_cgroup_event_time(struct perf_event *event)
+{
+	return 0;
+}
+
+static inline void
+perf_cgroup_defer_enabled(struct perf_event *event)
+{
+}
+
+static inline void
+perf_cgroup_mark_enabled(struct perf_event *event,
+			 struct perf_event_context *ctx)
+{
+}
+#endif
+
 void perf_pmu_disable(struct pmu *pmu)
 {
 	int *count = this_cpu_ptr(pmu->pmu_disable_count);
@@ -254,7 +712,6 @@ static void perf_unpin_context(struct perf_event_context *ctx)
 	raw_spin_lock_irqsave(&ctx->lock, flags);
 	--ctx->pin_count;
 	raw_spin_unlock_irqrestore(&ctx->lock, flags);
-	put_ctx(ctx);
 }
 
 /*
@@ -271,6 +728,10 @@ static void update_context_time(struct perf_event_context *ctx)
 static u64 perf_event_time(struct perf_event *event)
 {
 	struct perf_event_context *ctx = event->ctx;
+
+	if (is_cgroup_event(event))
+		return perf_cgroup_event_time(event);
+
 	return ctx ? ctx->time : 0;
 }
 
@@ -285,9 +746,20 @@ static void update_event_times(struct perf_event *event)
 	if (event->state < PERF_EVENT_STATE_INACTIVE ||
 	    event->group_leader->state < PERF_EVENT_STATE_INACTIVE)
 		return;
-
-	if (ctx->is_active)
+	/*
+	 * in cgroup mode, time_enabled represents
+	 * the time the event was enabled AND active
+	 * tasks were in the monitored cgroup. This is
+	 * independent of the activity of the context as
+	 * there may be a mix of cgroup and non-cgroup events.
+	 *
+	 * That is why we treat cgroup events differently
+	 * here.
+	 */
+	if (is_cgroup_event(event))
 		run_end = perf_event_time(event);
+	else if (ctx->is_active)
+		run_end = ctx->time;
 	else
 		run_end = event->tstamp_stopped;
 
@@ -299,6 +771,7 @@ static void update_event_times(struct perf_event *event)
 		run_end = perf_event_time(event);
 
 	event->total_time_running = run_end - event->tstamp_running;
+
 }
 
 /*
@@ -347,6 +820,9 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx)
 		list_add_tail(&event->group_entry, list);
 	}
 
+	if (is_cgroup_event(event))
+		ctx->nr_cgroups++;
+
 	list_add_rcu(&event->event_entry, &ctx->event_list);
 	if (!ctx->nr_events)
 		perf_pmu_rotate_start(ctx->pmu);
@@ -473,6 +949,9 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 
 	event->attach_state &= ~PERF_ATTACH_CONTEXT;
 
+	if (is_cgroup_event(event))
+		ctx->nr_cgroups--;
+
 	ctx->nr_events--;
 	if (event->attr.inherit_stat)
 		ctx->nr_stat--;
@@ -544,7 +1023,8 @@ out:
 static inline int
 event_filter_match(struct perf_event *event)
 {
-	return event->cpu == -1 || event->cpu == smp_processor_id();
+	return (event->cpu == -1 || event->cpu == smp_processor_id())
+	    && perf_cgroup_match(event);
 }
 
 static void
@@ -562,7 +1042,7 @@ event_sched_out(struct perf_event *event,
 	 */
 	if (event->state == PERF_EVENT_STATE_INACTIVE
 	    && !event_filter_match(event)) {
-		delta = ctx->time - event->tstamp_stopped;
+		delta = tstamp - event->tstamp_stopped;
 		event->tstamp_running += delta;
 		event->tstamp_stopped = tstamp;
 	}
@@ -606,47 +1086,30 @@ group_sched_out(struct perf_event *group_event,
 		cpuctx->exclusive = 0;
 }
 
-static inline struct perf_cpu_context *
-__get_cpu_context(struct perf_event_context *ctx)
-{
-	return this_cpu_ptr(ctx->pmu->pmu_cpu_context);
-}
-
 /*
  * Cross CPU call to remove a performance event
  *
  * We disable the event on the hardware level first. After that we
  * remove it from the context list.
  */
-static void __perf_event_remove_from_context(void *info)
+static int __perf_remove_from_context(void *info)
 {
 	struct perf_event *event = info;
 	struct perf_event_context *ctx = event->ctx;
 	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 
-	/*
-	 * If this is a task context, we need to check whether it is
-	 * the current task context of this cpu. If not it has been
-	 * scheduled out before the smp call arrived.
-	 */
-	if (ctx->task && cpuctx->task_ctx != ctx)
-		return;
-
 	raw_spin_lock(&ctx->lock);
-
 	event_sched_out(event, cpuctx, ctx);
-
 	list_del_event(event, ctx);
-
 	raw_spin_unlock(&ctx->lock);
+
+	return 0;
 }
 
 
 /*
  * Remove the event from a task's (or a CPU's) list of events.
  *
- * Must be called with ctx->mutex held.
- *
  * CPU events are removed with a smp call. For task events we only
  * call when the task is on a CPU.
  *
@@ -657,49 +1120,48 @@ static void __perf_event_remove_from_context(void *info)
  * When called from perf_event_exit_task, it's OK because the
  * context has been detached from its task.
  */
-static void perf_event_remove_from_context(struct perf_event *event)
+static void perf_remove_from_context(struct perf_event *event)
 {
 	struct perf_event_context *ctx = event->ctx;
 	struct task_struct *task = ctx->task;
 
+	lockdep_assert_held(&ctx->mutex);
+
 	if (!task) {
 		/*
 		 * Per cpu events are removed via an smp call and
 		 * the removal is always successful.
 		 */
-		smp_call_function_single(event->cpu,
-					 __perf_event_remove_from_context,
-					 event, 1);
+		cpu_function_call(event->cpu, __perf_remove_from_context, event);
 		return;
 	}
 
 retry:
-	task_oncpu_function_call(task, __perf_event_remove_from_context,
-				 event);
+	if (!task_function_call(task, __perf_remove_from_context, event))
+		return;
 
 	raw_spin_lock_irq(&ctx->lock);
 	/*
-	 * If the context is active we need to retry the smp call.
+	 * If we failed to find a running task, but find the context active now
+	 * that we've acquired the ctx->lock, retry.
 	 */
-	if (ctx->nr_active && !list_empty(&event->group_entry)) {
+	if (ctx->is_active) {
 		raw_spin_unlock_irq(&ctx->lock);
 		goto retry;
 	}
 
 	/*
-	 * The lock prevents that this context is scheduled in so we
-	 * can remove the event safely, if the call above did not
-	 * succeed.
+	 * Since the task isn't running, its safe to remove the event, us
+	 * holding the ctx->lock ensures the task won't get scheduled in.
 	 */
-	if (!list_empty(&event->group_entry))
-		list_del_event(event, ctx);
+	list_del_event(event, ctx);
 	raw_spin_unlock_irq(&ctx->lock);
 }
 
 /*
  * Cross CPU call to disable a performance event
  */
-static void __perf_event_disable(void *info)
+static int __perf_event_disable(void *info)
 {
 	struct perf_event *event = info;
 	struct perf_event_context *ctx = event->ctx;
@@ -708,9 +1170,12 @@ static void __perf_event_disable(void *info)
 	/*
 	 * If this is a per-task event, need to check whether this
 	 * event's task is the current task on this cpu.
+	 *
+	 * Can trigger due to concurrent perf_event_context_sched_out()
+	 * flipping contexts around.
 	 */
 	if (ctx->task && cpuctx->task_ctx != ctx)
-		return;
+		return -EINVAL;
 
 	raw_spin_lock(&ctx->lock);
 
@@ -720,6 +1185,7 @@ static void __perf_event_disable(void *info)
 	 */
 	if (event->state >= PERF_EVENT_STATE_INACTIVE) {
 		update_context_time(ctx);
+		update_cgrp_time_from_event(event);
 		update_group_times(event);
 		if (event == event->group_leader)
 			group_sched_out(event, cpuctx, ctx);
@@ -729,6 +1195,8 @@ static void __perf_event_disable(void *info)
 	}
 
 	raw_spin_unlock(&ctx->lock);
+
+	return 0;
 }
 
 /*
@@ -753,13 +1221,13 @@ void perf_event_disable(struct perf_event *event)
 		/*
 		 * Disable the event on the cpu that it's on
 		 */
-		smp_call_function_single(event->cpu, __perf_event_disable,
-					 event, 1);
+		cpu_function_call(event->cpu, __perf_event_disable, event);
 		return;
 	}
 
 retry:
-	task_oncpu_function_call(task, __perf_event_disable, event);
+	if (!task_function_call(task, __perf_event_disable, event))
+		return;
 
 	raw_spin_lock_irq(&ctx->lock);
 	/*
@@ -767,6 +1235,11 @@ retry:
 	 */
 	if (event->state == PERF_EVENT_STATE_ACTIVE) {
 		raw_spin_unlock_irq(&ctx->lock);
+		/*
+		 * Reload the task pointer, it might have been changed by
+		 * a concurrent perf_event_context_sched_out().
+		 */
+		task = ctx->task;
 		goto retry;
 	}
 
@@ -778,10 +1251,44 @@ retry:
 		update_group_times(event);
 		event->state = PERF_EVENT_STATE_OFF;
 	}
-
 	raw_spin_unlock_irq(&ctx->lock);
 }
 
+static void perf_set_shadow_time(struct perf_event *event,
+				 struct perf_event_context *ctx,
+				 u64 tstamp)
+{
+	/*
+	 * use the correct time source for the time snapshot
+	 *
+	 * We could get by without this by leveraging the
+	 * fact that to get to this function, the caller
+	 * has most likely already called update_context_time()
+	 * and update_cgrp_time_xx() and thus both timestamp
+	 * are identical (or very close). Given that tstamp is,
+	 * already adjusted for cgroup, we could say that:
+	 *    tstamp - ctx->timestamp
+	 * is equivalent to
+	 *    tstamp - cgrp->timestamp.
+	 *
+	 * Then, in perf_output_read(), the calculation would
+	 * work with no changes because:
+	 * - event is guaranteed scheduled in
+	 * - no scheduled out in between
+	 * - thus the timestamp would be the same
+	 *
+	 * But this is a bit hairy.
+	 *
+	 * So instead, we have an explicit cgroup call to remain
+	 * within the time time source all along. We believe it
+	 * is cleaner and simpler to understand.
+	 */
+	if (is_cgroup_event(event))
+		perf_cgroup_set_shadow_time(event, tstamp);
+	else
+		event->shadow_ctx_time = tstamp - ctx->timestamp;
+}
+
 #define MAX_INTERRUPTS (~0ULL)
 
 static void perf_log_throttle(struct perf_event *event, int enable);
@@ -822,7 +1329,7 @@ event_sched_in(struct perf_event *event,
 
 	event->tstamp_running += tstamp - event->tstamp_stopped;
 
-	event->shadow_ctx_time = tstamp - ctx->timestamp;
+	perf_set_shadow_time(event, ctx, tstamp);
 
 	if (!is_software_event(event))
 		cpuctx->active_oncpu++;
@@ -943,12 +1450,15 @@ static void add_event_to_ctx(struct perf_event *event,
 	event->tstamp_stopped = tstamp;
 }
 
+static void perf_event_context_sched_in(struct perf_event_context *ctx,
+					struct task_struct *tsk);
+
 /*
  * Cross CPU call to install and enable a performance event
  *
  * Must be called with ctx->mutex held
  */
-static void __perf_install_in_context(void *info)
+static int  __perf_install_in_context(void *info)
 {
 	struct perf_event *event = info;
 	struct perf_event_context *ctx = event->ctx;
@@ -957,21 +1467,22 @@ static void __perf_install_in_context(void *info)
 	int err;
 
 	/*
-	 * If this is a task context, we need to check whether it is
-	 * the current task context of this cpu. If not it has been
-	 * scheduled out before the smp call arrived.
-	 * Or possibly this is the right context but it isn't
-	 * on this cpu because it had no events.
+	 * In case we're installing a new context to an already running task,
+	 * could also happen before perf_event_task_sched_in() on architectures
+	 * which do context switches with IRQs enabled.
 	 */
-	if (ctx->task && cpuctx->task_ctx != ctx) {
-		if (cpuctx->task_ctx || ctx->task != current)
-			return;
-		cpuctx->task_ctx = ctx;
-	}
+	if (ctx->task && !cpuctx->task_ctx)
+		perf_event_context_sched_in(ctx, ctx->task);
 
 	raw_spin_lock(&ctx->lock);
 	ctx->is_active = 1;
 	update_context_time(ctx);
+	/*
+	 * update cgrp time only if current cgrp
+	 * matches event->cgrp. Must be done before
+	 * calling add_event_to_ctx()
+	 */
+	update_cgrp_time_from_event(event);
 
 	add_event_to_ctx(event, ctx);
 
@@ -1012,6 +1523,8 @@ static void __perf_install_in_context(void *info)
 
 unlock:
 	raw_spin_unlock(&ctx->lock);
+
+	return 0;
 }
 
 /*
@@ -1023,8 +1536,6 @@ unlock:
  * If the event is attached to a task which is on a CPU we use a smp
  * call to enable it in the task context. The task might have been
  * scheduled away, but we check this in the smp call again.
- *
- * Must be called with ctx->mutex held.
  */
 static void
 perf_install_in_context(struct perf_event_context *ctx,
@@ -1033,6 +1544,8 @@ perf_install_in_context(struct perf_event_context *ctx,
 {
 	struct task_struct *task = ctx->task;
 
+	lockdep_assert_held(&ctx->mutex);
+
 	event->ctx = ctx;
 
 	if (!task) {
@@ -1040,31 +1553,29 @@ perf_install_in_context(struct perf_event_context *ctx,
 		 * Per cpu events are installed via an smp call and
 		 * the install is always successful.
 		 */
-		smp_call_function_single(cpu, __perf_install_in_context,
-					 event, 1);
+		cpu_function_call(cpu, __perf_install_in_context, event);
 		return;
 	}
 
 retry:
-	task_oncpu_function_call(task, __perf_install_in_context,
-				 event);
+	if (!task_function_call(task, __perf_install_in_context, event))
+		return;
 
 	raw_spin_lock_irq(&ctx->lock);
 	/*
-	 * we need to retry the smp call.
+	 * If we failed to find a running task, but find the context active now
+	 * that we've acquired the ctx->lock, retry.
 	 */
-	if (ctx->is_active && list_empty(&event->group_entry)) {
+	if (ctx->is_active) {
 		raw_spin_unlock_irq(&ctx->lock);
 		goto retry;
 	}
 
 	/*
-	 * The lock prevents that this context is scheduled in so we
-	 * can add the event safely, if it the call above did not
-	 * succeed.
+	 * Since the task isn't running, its safe to add the event, us holding
+	 * the ctx->lock ensures the task won't get scheduled in.
 	 */
-	if (list_empty(&event->group_entry))
-		add_event_to_ctx(event, ctx);
+	add_event_to_ctx(event, ctx);
 	raw_spin_unlock_irq(&ctx->lock);
 }
 
@@ -1093,7 +1604,7 @@ static void __perf_event_mark_enabled(struct perf_event *event,
 /*
  * Cross CPU call to enable a performance event
  */
-static void __perf_event_enable(void *info)
+static int __perf_event_enable(void *info)
 {
 	struct perf_event *event = info;
 	struct perf_event_context *ctx = event->ctx;
@@ -1101,26 +1612,27 @@ static void __perf_event_enable(void *info)
 	struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
 	int err;
 
-	/*
-	 * If this is a per-task event, need to check whether this
-	 * event's task is the current task on this cpu.
-	 */
-	if (ctx->task && cpuctx->task_ctx != ctx) {
-		if (cpuctx->task_ctx || ctx->task != current)
-			return;
-		cpuctx->task_ctx = ctx;
-	}
+	if (WARN_ON_ONCE(!ctx->is_active))
+		return -EINVAL;
 
 	raw_spin_lock(&ctx->lock);
-	ctx->is_active = 1;
 	update_context_time(ctx);
 
 	if (event->state >= PERF_EVENT_STATE_INACTIVE)
 		goto unlock;
+
+	/*
+	 * set current task's cgroup time reference point
+	 */
+	perf_cgroup_set_timestamp(current, ctx);
+
 	__perf_event_mark_enabled(event, ctx);
 
-	if (!event_filter_match(event))
+	if (!event_filter_match(event)) {
+		if (is_cgroup_event(event))
+			perf_cgroup_defer_enabled(event);
 		goto unlock;
+	}
 
 	/*
 	 * If the event is in a group and isn't the group leader,
@@ -1153,6 +1665,8 @@ static void __perf_event_enable(void *info)
 
 unlock:
 	raw_spin_unlock(&ctx->lock);
+
+	return 0;
 }
 
 /*
@@ -1173,8 +1687,7 @@ void perf_event_enable(struct perf_event *event)
 		/*
 		 * Enable the event on the cpu that it's on
 		 */
-		smp_call_function_single(event->cpu, __perf_event_enable,
-					 event, 1);
+		cpu_function_call(event->cpu, __perf_event_enable, event);
 		return;
 	}
 
@@ -1193,8 +1706,15 @@ void perf_event_enable(struct perf_event *event)
 		event->state = PERF_EVENT_STATE_OFF;
 
 retry:
+	if (!ctx->is_active) {
+		__perf_event_mark_enabled(event, ctx);
+		goto out;
+	}
+
 	raw_spin_unlock_irq(&ctx->lock);
-	task_oncpu_function_call(task, __perf_event_enable, event);
+
+	if (!task_function_call(task, __perf_event_enable, event))
+		return;
 
 	raw_spin_lock_irq(&ctx->lock);
 
@@ -1202,15 +1722,14 @@ retry:
 	 * If the context is active and the event is still off,
 	 * we need to retry the cross-call.
 	 */
-	if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF)
+	if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) {
+		/*
+		 * task could have been flipped by a concurrent
+		 * perf_event_context_sched_out()
+		 */
+		task = ctx->task;
 		goto retry;
-
-	/*
-	 * Since we have the lock this context can't be scheduled
-	 * in, so we can change the state safely.
-	 */
-	if (event->state == PERF_EVENT_STATE_OFF)
-		__perf_event_mark_enabled(event, ctx);
+	}
 
 out:
 	raw_spin_unlock_irq(&ctx->lock);
@@ -1242,6 +1761,7 @@ static void ctx_sched_out(struct perf_event_context *ctx,
 	if (likely(!ctx->nr_events))
 		goto out;
 	update_context_time(ctx);
+	update_cgrp_time_from_cpuctx(cpuctx);
 
 	if (!ctx->nr_active)
 		goto out;
@@ -1354,8 +1874,8 @@ static void perf_event_sync_stat(struct perf_event_context *ctx,
 	}
 }
 
-void perf_event_context_sched_out(struct task_struct *task, int ctxn,
-				  struct task_struct *next)
+static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
+					 struct task_struct *next)
 {
 	struct perf_event_context *ctx = task->perf_event_ctxp[ctxn];
 	struct perf_event_context *next_ctx;
@@ -1431,6 +1951,14 @@ void __perf_event_task_sched_out(struct task_struct *task,
 
 	for_each_task_context_nr(ctxn)
 		perf_event_context_sched_out(task, ctxn, next);
+
+	/*
+	 * if cgroup events exist on this CPU, then we need
+	 * to check if we have to switch out PMU state.
+	 * cgroup event are system-wide mode only
+	 */
+	if (atomic_read(&__get_cpu_var(perf_cgroup_events)))
+		perf_cgroup_sched_out(task);
 }
 
 static void task_ctx_sched_out(struct perf_event_context *ctx,
@@ -1469,6 +1997,10 @@ ctx_pinned_sched_in(struct perf_event_context *ctx,
 		if (!event_filter_match(event))
 			continue;
 
+		/* may need to reset tstamp_enabled */
+		if (is_cgroup_event(event))
+			perf_cgroup_mark_enabled(event, ctx);
+
 		if (group_can_go_on(event, cpuctx, 1))
 			group_sched_in(event, cpuctx, ctx);
 
@@ -1501,6 +2033,10 @@ ctx_flexible_sched_in(struct perf_event_context *ctx,
 		if (!event_filter_match(event))
 			continue;
 
+		/* may need to reset tstamp_enabled */
+		if (is_cgroup_event(event))
+			perf_cgroup_mark_enabled(event, ctx);
+
 		if (group_can_go_on(event, cpuctx, can_add_hw)) {
 			if (group_sched_in(event, cpuctx, ctx))
 				can_add_hw = 0;
@@ -1511,15 +2047,19 @@ ctx_flexible_sched_in(struct perf_event_context *ctx,
 static void
 ctx_sched_in(struct perf_event_context *ctx,
 	     struct perf_cpu_context *cpuctx,
-	     enum event_type_t event_type)
+	     enum event_type_t event_type,
+	     struct task_struct *task)
 {
+	u64 now;
+
 	raw_spin_lock(&ctx->lock);
 	ctx->is_active = 1;
 	if (likely(!ctx->nr_events))
 		goto out;
 
-	ctx->timestamp = perf_clock();
-
+	now = perf_clock();
+	ctx->timestamp = now;
+	perf_cgroup_set_timestamp(task, ctx);
 	/*
 	 * First go through the list and put on any pinned groups
 	 * in order to give them the best chance of going on.
@@ -1536,11 +2076,12 @@ out:
 }
 
 static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx,
-			     enum event_type_t event_type)
+			     enum event_type_t event_type,
+			     struct task_struct *task)
 {
 	struct perf_event_context *ctx = &cpuctx->ctx;
 
-	ctx_sched_in(ctx, cpuctx, event_type);
+	ctx_sched_in(ctx, cpuctx, event_type, task);
 }
 
 static void task_ctx_sched_in(struct perf_event_context *ctx,
@@ -1548,15 +2089,16 @@ static void task_ctx_sched_in(struct perf_event_context *ctx,
 {
 	struct perf_cpu_context *cpuctx;
 
-       	cpuctx = __get_cpu_context(ctx);
+	cpuctx = __get_cpu_context(ctx);
 	if (cpuctx->task_ctx == ctx)
 		return;
 
-	ctx_sched_in(ctx, cpuctx, event_type);
+	ctx_sched_in(ctx, cpuctx, event_type, NULL);
 	cpuctx->task_ctx = ctx;
 }
 
-void perf_event_context_sched_in(struct perf_event_context *ctx)
+static void perf_event_context_sched_in(struct perf_event_context *ctx,
+					struct task_struct *task)
 {
 	struct perf_cpu_context *cpuctx;
 
@@ -1572,9 +2114,9 @@ void perf_event_context_sched_in(struct perf_event_context *ctx)
 	 */
 	cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
 
-	ctx_sched_in(ctx, cpuctx, EVENT_PINNED);
-	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE);
-	ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE);
+	ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task);
+	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task);
+	ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task);
 
 	cpuctx->task_ctx = ctx;
 
@@ -1607,8 +2149,15 @@ void __perf_event_task_sched_in(struct task_struct *task)
 		if (likely(!ctx))
 			continue;
 
-		perf_event_context_sched_in(ctx);
+		perf_event_context_sched_in(ctx, task);
 	}
+	/*
+	 * if cgroup events exist on this CPU, then we need
+	 * to check if we have to switch in PMU state.
+	 * cgroup event are system-wide mode only
+	 */
+	if (atomic_read(&__get_cpu_var(perf_cgroup_events)))
+		perf_cgroup_sched_in(task);
 }
 
 static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
@@ -1638,7 +2187,7 @@ static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
 	 * Reduce accuracy by one bit such that @a and @b converge
 	 * to a similar magnitude.
 	 */
-#define REDUCE_FLS(a, b) 		\
+#define REDUCE_FLS(a, b)		\
 do {					\
 	if (a##_fls > b##_fls) {	\
 		a >>= 1;		\
@@ -1808,7 +2357,7 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx)
 	if (ctx)
 		rotate_ctx(ctx);
 
-	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE);
+	cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, current);
 	if (ctx)
 		task_ctx_sched_in(ctx, EVENT_FLEXIBLE);
 
@@ -1887,7 +2436,7 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
 
 	raw_spin_unlock(&ctx->lock);
 
-	perf_event_context_sched_in(ctx);
+	perf_event_context_sched_in(ctx, ctx->task);
 out:
 	local_irq_restore(flags);
 }
@@ -1912,8 +2461,10 @@ static void __perf_event_read(void *info)
 		return;
 
 	raw_spin_lock(&ctx->lock);
-	if (ctx->is_active)
+	if (ctx->is_active) {
 		update_context_time(ctx);
+		update_cgrp_time_from_event(event);
+	}
 	update_event_times(event);
 	if (event->state == PERF_EVENT_STATE_ACTIVE)
 		event->pmu->read(event);
@@ -1944,8 +2495,10 @@ static u64 perf_event_read(struct perf_event *event)
 		 * (e.g., thread is blocked), in that case
 		 * we cannot update context time
 		 */
-		if (ctx->is_active)
+		if (ctx->is_active) {
 			update_context_time(ctx);
+			update_cgrp_time_from_event(event);
+		}
 		update_event_times(event);
 		raw_spin_unlock_irqrestore(&ctx->lock, flags);
 	}
@@ -2224,6 +2777,9 @@ errout:
 
 }
 
+/*
+ * Returns a matching context with refcount and pincount.
+ */
 static struct perf_event_context *
 find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
 {
@@ -2248,6 +2804,7 @@ find_get_context(struct pmu *pmu, struct task_struct *task, int cpu)
 		cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
 		ctx = &cpuctx->ctx;
 		get_ctx(ctx);
+		++ctx->pin_count;
 
 		return ctx;
 	}
@@ -2261,6 +2818,7 @@ retry:
 	ctx = perf_lock_task_context(task, ctxn, &flags);
 	if (ctx) {
 		unclone_ctx(ctx);
+		++ctx->pin_count;
 		raw_spin_unlock_irqrestore(&ctx->lock, flags);
 	}
 
@@ -2282,8 +2840,10 @@ retry:
 			err = -ESRCH;
 		else if (task->perf_event_ctxp[ctxn])
 			err = -EAGAIN;
-		else
+		else {
+			++ctx->pin_count;
 			rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx);
+		}
 		mutex_unlock(&task->perf_event_mutex);
 
 		if (unlikely(err)) {
@@ -2323,7 +2883,7 @@ static void free_event(struct perf_event *event)
 
 	if (!event->parent) {
 		if (event->attach_state & PERF_ATTACH_TASK)
-			jump_label_dec(&perf_task_events);
+			jump_label_dec(&perf_sched_events);
 		if (event->attr.mmap || event->attr.mmap_data)
 			atomic_dec(&nr_mmap_events);
 		if (event->attr.comm)
@@ -2332,6 +2892,10 @@ static void free_event(struct perf_event *event)
 			atomic_dec(&nr_task_events);
 		if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN)
 			put_callchain_buffers();
+		if (is_cgroup_event(event)) {
+			atomic_dec(&per_cpu(perf_cgroup_events, event->cpu));
+			jump_label_dec(&perf_sched_events);
+		}
 	}
 
 	if (event->buffer) {
@@ -2339,6 +2903,9 @@ static void free_event(struct perf_event *event)
 		event->buffer = NULL;
 	}
 
+	if (is_cgroup_event(event))
+		perf_detach_cgroup(event);
+
 	if (event->destroy)
 		event->destroy(event);
 
@@ -4406,26 +4973,14 @@ static int __perf_event_overflow(struct perf_event *event, int nmi,
 	if (unlikely(!is_sampling_event(event)))
 		return 0;
 
-	if (!throttle) {
-		hwc->interrupts++;
-	} else {
-		if (hwc->interrupts != MAX_INTERRUPTS) {
-			hwc->interrupts++;
-			if (HZ * hwc->interrupts >
-					(u64)sysctl_perf_event_sample_rate) {
-				hwc->interrupts = MAX_INTERRUPTS;
-				perf_log_throttle(event, 0);
-				ret = 1;
-			}
-		} else {
-			/*
-			 * Keep re-disabling events even though on the previous
-			 * pass we disabled it - just in case we raced with a
-			 * sched-in and the event got enabled again:
-			 */
+	if (unlikely(hwc->interrupts >= max_samples_per_tick)) {
+		if (throttle) {
+			hwc->interrupts = MAX_INTERRUPTS;
+			perf_log_throttle(event, 0);
 			ret = 1;
 		}
-	}
+	} else
+		hwc->interrupts++;
 
 	if (event->attr.freq) {
 		u64 now = perf_clock();
@@ -4567,7 +5122,7 @@ static int perf_exclude_event(struct perf_event *event,
 			      struct pt_regs *regs)
 {
 	if (event->hw.state & PERF_HES_STOPPED)
-		return 0;
+		return 1;
 
 	if (regs) {
 		if (event->attr.exclude_user && user_mode(regs))
@@ -4923,6 +5478,8 @@ static int perf_tp_event_match(struct perf_event *event,
 				struct perf_sample_data *data,
 				struct pt_regs *regs)
 {
+	if (event->hw.state & PERF_HES_STOPPED)
+		return 0;
 	/*
 	 * All tracepoints are from kernel-space.
 	 */
@@ -5062,6 +5619,10 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
 	u64 period;
 
 	event = container_of(hrtimer, struct perf_event, hw.hrtimer);
+
+	if (event->state != PERF_EVENT_STATE_ACTIVE)
+		return HRTIMER_NORESTART;
+
 	event->pmu->read(event);
 
 	perf_sample_data_init(&data, 0);
@@ -5088,9 +5649,6 @@ static void perf_swevent_start_hrtimer(struct perf_event *event)
 	if (!is_sampling_event(event))
 		return;
 
-	hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	hwc->hrtimer.function = perf_swevent_hrtimer;
-
 	period = local64_read(&hwc->period_left);
 	if (period) {
 		if (period < 0)
@@ -5117,6 +5675,30 @@ static void perf_swevent_cancel_hrtimer(struct perf_event *event)
 	}
 }
 
+static void perf_swevent_init_hrtimer(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	if (!is_sampling_event(event))
+		return;
+
+	hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	hwc->hrtimer.function = perf_swevent_hrtimer;
+
+	/*
+	 * Since hrtimers have a fixed rate, we can do a static freq->period
+	 * mapping and avoid the whole period adjust feedback stuff.
+	 */
+	if (event->attr.freq) {
+		long freq = event->attr.sample_freq;
+
+		event->attr.sample_period = NSEC_PER_SEC / freq;
+		hwc->sample_period = event->attr.sample_period;
+		local64_set(&hwc->period_left, hwc->sample_period);
+		event->attr.freq = 0;
+	}
+}
+
 /*
  * Software event: cpu wall time clock
  */
@@ -5169,6 +5751,8 @@ static int cpu_clock_event_init(struct perf_event *event)
 	if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK)
 		return -ENOENT;
 
+	perf_swevent_init_hrtimer(event);
+
 	return 0;
 }
 
@@ -5224,16 +5808,9 @@ static void task_clock_event_del(struct perf_event *event, int flags)
 
 static void task_clock_event_read(struct perf_event *event)
 {
-	u64 time;
-
-	if (!in_nmi()) {
-		update_context_time(event->ctx);
-		time = event->ctx->time;
-	} else {
-		u64 now = perf_clock();
-		u64 delta = now - event->ctx->timestamp;
-		time = event->ctx->time + delta;
-	}
+	u64 now = perf_clock();
+	u64 delta = now - event->ctx->timestamp;
+	u64 time = event->ctx->time + delta;
 
 	task_clock_event_update(event, time);
 }
@@ -5246,6 +5823,8 @@ static int task_clock_event_init(struct perf_event *event)
 	if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK)
 		return -ENOENT;
 
+	perf_swevent_init_hrtimer(event);
+
 	return 0;
 }
 
@@ -5517,17 +6096,22 @@ struct pmu *perf_init_event(struct perf_event *event)
 {
 	struct pmu *pmu = NULL;
 	int idx;
+	int ret;
 
 	idx = srcu_read_lock(&pmus_srcu);
 
 	rcu_read_lock();
 	pmu = idr_find(&pmu_idr, event->attr.type);
 	rcu_read_unlock();
-	if (pmu)
+	if (pmu) {
+		ret = pmu->event_init(event);
+		if (ret)
+			pmu = ERR_PTR(ret);
 		goto unlock;
+	}
 
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
-		int ret = pmu->event_init(event);
+		ret = pmu->event_init(event);
 		if (!ret)
 			goto unlock;
 
@@ -5653,7 +6237,7 @@ done:
 
 	if (!event->parent) {
 		if (event->attach_state & PERF_ATTACH_TASK)
-			jump_label_inc(&perf_task_events);
+			jump_label_inc(&perf_sched_events);
 		if (event->attr.mmap || event->attr.mmap_data)
 			atomic_inc(&nr_mmap_events);
 		if (event->attr.comm)
@@ -5828,7 +6412,7 @@ SYSCALL_DEFINE5(perf_event_open,
 	int err;
 
 	/* for future expandability... */
-	if (flags & ~(PERF_FLAG_FD_NO_GROUP | PERF_FLAG_FD_OUTPUT))
+	if (flags & ~PERF_FLAG_ALL)
 		return -EINVAL;
 
 	err = perf_copy_attr(attr_uptr, &attr);
@@ -5845,6 +6429,15 @@ SYSCALL_DEFINE5(perf_event_open,
 			return -EINVAL;
 	}
 
+	/*
+	 * In cgroup mode, the pid argument is used to pass the fd
+	 * opened to the cgroup directory in cgroupfs. The cpu argument
+	 * designates the cpu on which to monitor threads from that
+	 * cgroup.
+	 */
+	if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1))
+		return -EINVAL;
+
 	event_fd = get_unused_fd_flags(O_RDWR);
 	if (event_fd < 0)
 		return event_fd;
@@ -5862,7 +6455,7 @@ SYSCALL_DEFINE5(perf_event_open,
 			group_leader = NULL;
 	}
 
-	if (pid != -1) {
+	if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) {
 		task = find_lively_task_by_vpid(pid);
 		if (IS_ERR(task)) {
 			err = PTR_ERR(task);
@@ -5876,6 +6469,19 @@ SYSCALL_DEFINE5(perf_event_open,
 		goto err_task;
 	}
 
+	if (flags & PERF_FLAG_PID_CGROUP) {
+		err = perf_cgroup_connect(pid, event, &attr, group_leader);
+		if (err)
+			goto err_alloc;
+		/*
+		 * one more event:
+		 * - that has cgroup constraint on event->cpu
+		 * - that may need work on context switch
+		 */
+		atomic_inc(&per_cpu(perf_cgroup_events, event->cpu));
+		jump_label_inc(&perf_sched_events);
+	}
+
 	/*
 	 * Special case software events and allow them to be part of
 	 * any hardware group.
@@ -5961,10 +6567,10 @@ SYSCALL_DEFINE5(perf_event_open,
 		struct perf_event_context *gctx = group_leader->ctx;
 
 		mutex_lock(&gctx->mutex);
-		perf_event_remove_from_context(group_leader);
+		perf_remove_from_context(group_leader);
 		list_for_each_entry(sibling, &group_leader->sibling_list,
 				    group_entry) {
-			perf_event_remove_from_context(sibling);
+			perf_remove_from_context(sibling);
 			put_ctx(gctx);
 		}
 		mutex_unlock(&gctx->mutex);
@@ -5987,6 +6593,7 @@ SYSCALL_DEFINE5(perf_event_open,
 
 	perf_install_in_context(ctx, event, cpu);
 	++ctx->generation;
+	perf_unpin_context(ctx);
 	mutex_unlock(&ctx->mutex);
 
 	event->owner = current;
@@ -6012,6 +6619,7 @@ SYSCALL_DEFINE5(perf_event_open,
 	return event_fd;
 
 err_context:
+	perf_unpin_context(ctx);
 	put_ctx(ctx);
 err_alloc:
 	free_event(event);
@@ -6062,6 +6670,7 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
 	mutex_lock(&ctx->mutex);
 	perf_install_in_context(ctx, event, cpu);
 	++ctx->generation;
+	perf_unpin_context(ctx);
 	mutex_unlock(&ctx->mutex);
 
 	return event;
@@ -6113,17 +6722,20 @@ __perf_event_exit_task(struct perf_event *child_event,
 			 struct perf_event_context *child_ctx,
 			 struct task_struct *child)
 {
-	struct perf_event *parent_event;
+	if (child_event->parent) {
+		raw_spin_lock_irq(&child_ctx->lock);
+		perf_group_detach(child_event);
+		raw_spin_unlock_irq(&child_ctx->lock);
+	}
 
-	perf_event_remove_from_context(child_event);
+	perf_remove_from_context(child_event);
 
-	parent_event = child_event->parent;
 	/*
-	 * It can happen that parent exits first, and has events
+	 * It can happen that the parent exits first, and has events
 	 * that are still around due to the child reference. These
-	 * events need to be zapped - but otherwise linger.
+	 * events need to be zapped.
 	 */
-	if (parent_event) {
+	if (child_event->parent) {
 		sync_child_event(child_event, child);
 		free_event(child_event);
 	}
@@ -6422,7 +7034,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent,
 		return 0;
 	}
 
-       	child_ctx = child->perf_event_ctxp[ctxn];
+	child_ctx = child->perf_event_ctxp[ctxn];
 	if (!child_ctx) {
 		/*
 		 * This is executed from the parent task context, so
@@ -6537,6 +7149,7 @@ int perf_event_init_context(struct task_struct *child, int ctxn)
 	mutex_unlock(&parent_ctx->mutex);
 
 	perf_unpin_context(parent_ctx);
+	put_ctx(parent_ctx);
 
 	return ret;
 }
@@ -6606,9 +7219,9 @@ static void __perf_event_exit_context(void *__info)
 	perf_pmu_rotate_stop(ctx->pmu);
 
 	list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, group_entry)
-		__perf_event_remove_from_context(event);
+		__perf_remove_from_context(event);
 	list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, group_entry)
-		__perf_event_remove_from_context(event);
+		__perf_remove_from_context(event);
 }
 
 static void perf_event_exit_cpu_context(int cpu)
@@ -6732,3 +7345,83 @@ unlock:
 	return ret;
 }
 device_initcall(perf_event_sysfs_init);
+
+#ifdef CONFIG_CGROUP_PERF
+static struct cgroup_subsys_state *perf_cgroup_create(
+	struct cgroup_subsys *ss, struct cgroup *cont)
+{
+	struct perf_cgroup *jc;
+
+	jc = kzalloc(sizeof(*jc), GFP_KERNEL);
+	if (!jc)
+		return ERR_PTR(-ENOMEM);
+
+	jc->info = alloc_percpu(struct perf_cgroup_info);
+	if (!jc->info) {
+		kfree(jc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	return &jc->css;
+}
+
+static void perf_cgroup_destroy(struct cgroup_subsys *ss,
+				struct cgroup *cont)
+{
+	struct perf_cgroup *jc;
+	jc = container_of(cgroup_subsys_state(cont, perf_subsys_id),
+			  struct perf_cgroup, css);
+	free_percpu(jc->info);
+	kfree(jc);
+}
+
+static int __perf_cgroup_move(void *info)
+{
+	struct task_struct *task = info;
+	perf_cgroup_switch(task, PERF_CGROUP_SWOUT | PERF_CGROUP_SWIN);
+	return 0;
+}
+
+static void perf_cgroup_move(struct task_struct *task)
+{
+	task_function_call(task, __perf_cgroup_move, task);
+}
+
+static void perf_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
+		struct cgroup *old_cgrp, struct task_struct *task,
+		bool threadgroup)
+{
+	perf_cgroup_move(task);
+	if (threadgroup) {
+		struct task_struct *c;
+		rcu_read_lock();
+		list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
+			perf_cgroup_move(c);
+		}
+		rcu_read_unlock();
+	}
+}
+
+static void perf_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
+		struct cgroup *old_cgrp, struct task_struct *task)
+{
+	/*
+	 * cgroup_exit() is called in the copy_process() failure path.
+	 * Ignore this case since the task hasn't ran yet, this avoids
+	 * trying to poke a half freed task state from generic code.
+	 */
+	if (!(task->flags & PF_EXITING))
+		return;
+
+	perf_cgroup_move(task);
+}
+
+struct cgroup_subsys perf_subsys = {
+	.name = "perf_event",
+	.subsys_id = perf_subsys_id,
+	.create = perf_cgroup_create,
+	.destroy = perf_cgroup_destroy,
+	.exit = perf_cgroup_exit,
+	.attach = perf_cgroup_attach,
+};
+#endif /* CONFIG_CGROUP_PERF */
diff --git a/kernel/pid.c b/kernel/pid.c
index 39b65b6..02f2212 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -435,6 +435,7 @@ struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
 	rcu_read_unlock();
 	return pid;
 }
+EXPORT_SYMBOL_GPL(get_task_pid);
 
 struct task_struct *get_pid_task(struct pid *pid, enum pid_type type)
 {
@@ -446,6 +447,7 @@ struct task_struct *get_pid_task(struct pid *pid, enum pid_type type)
 	rcu_read_unlock();
 	return result;
 }
+EXPORT_SYMBOL_GPL(get_pid_task);
 
 struct pid *find_get_pid(pid_t nr)
 {
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index aeaa7f8..0da058b 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -103,11 +103,14 @@ static struct pm_qos_object *pm_qos_array[] = {
 
 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
 		size_t count, loff_t *f_pos);
+static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
+		size_t count, loff_t *f_pos);
 static int pm_qos_power_open(struct inode *inode, struct file *filp);
 static int pm_qos_power_release(struct inode *inode, struct file *filp);
 
 static const struct file_operations pm_qos_power_fops = {
 	.write = pm_qos_power_write,
+	.read = pm_qos_power_read,
 	.open = pm_qos_power_open,
 	.release = pm_qos_power_release,
 	.llseek = noop_llseek,
@@ -376,6 +379,27 @@ static int pm_qos_power_release(struct inode *inode, struct file *filp)
 }
 
 
+static ssize_t pm_qos_power_read(struct file *filp, char __user *buf,
+		size_t count, loff_t *f_pos)
+{
+	s32 value;
+	unsigned long flags;
+	struct pm_qos_object *o;
+	struct pm_qos_request_list *pm_qos_req = filp->private_data;;
+
+	if (!pm_qos_req)
+		return -EINVAL;
+	if (!pm_qos_request_active(pm_qos_req))
+		return -EINVAL;
+
+	o = pm_qos_array[pm_qos_req->pm_qos_class];
+	spin_lock_irqsave(&pm_qos_lock, flags);
+	value = pm_qos_get_value(o);
+	spin_unlock_irqrestore(&pm_qos_lock, flags);
+
+	return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32));
+}
+
 static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
 		size_t count, loff_t *f_pos)
 {
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 05bb717..67fea9d 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -176,7 +176,8 @@ static inline cputime_t virt_ticks(struct task_struct *p)
 	return p->utime;
 }
 
-int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
+static int
+posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
 {
 	int error = check_clock(which_clock);
 	if (!error) {
@@ -194,7 +195,8 @@ int posix_cpu_clock_getres(const clockid_t which_clock, struct timespec *tp)
 	return error;
 }
 
-int posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
+static int
+posix_cpu_clock_set(const clockid_t which_clock, const struct timespec *tp)
 {
 	/*
 	 * You can never reset a CPU clock, but we check for other errors
@@ -317,7 +319,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
 }
 
 
-int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
+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;
@@ -379,7 +381,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp)
  * This is called from sys_timer_create() and do_cpu_nanosleep() with the
  * new timer already all-zeros initialized.
  */
-int posix_cpu_timer_create(struct k_itimer *new_timer)
+static int posix_cpu_timer_create(struct k_itimer *new_timer)
 {
 	int ret = 0;
 	const pid_t pid = CPUCLOCK_PID(new_timer->it_clock);
@@ -425,7 +427,7 @@ int posix_cpu_timer_create(struct k_itimer *new_timer)
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
  * and try again.  (This happens when the timer is in the middle of firing.)
  */
-int posix_cpu_timer_del(struct k_itimer *timer)
+static int posix_cpu_timer_del(struct k_itimer *timer)
 {
 	struct task_struct *p = timer->it.cpu.task;
 	int ret = 0;
@@ -665,8 +667,8 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
  * and try again.  (This happens when the timer is in the middle of firing.)
  */
-int posix_cpu_timer_set(struct k_itimer *timer, int flags,
-			struct itimerspec *new, struct itimerspec *old)
+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;
@@ -820,7 +822,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
 	return ret;
 }
 
-void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
+static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
 {
 	union cpu_time_count now;
 	struct task_struct *p = timer->it.cpu.task;
@@ -1481,11 +1483,13 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 	return error;
 }
 
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-		     struct timespec *rqtp, struct timespec __user *rmtp)
+static long posix_cpu_nsleep_restart(struct restart_block *restart_block);
+
+static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+			    struct timespec *rqtp, struct timespec __user *rmtp)
 {
 	struct restart_block *restart_block =
-	    &current_thread_info()->restart_block;
+		&current_thread_info()->restart_block;
 	struct itimerspec it;
 	int error;
 
@@ -1501,56 +1505,47 @@ int posix_cpu_nsleep(const clockid_t which_clock, int flags,
 
 	if (error == -ERESTART_RESTARTBLOCK) {
 
-	       	if (flags & TIMER_ABSTIME)
+		if (flags & TIMER_ABSTIME)
 			return -ERESTARTNOHAND;
 		/*
-	 	 * Report back to the user the time still remaining.
-	 	 */
-		if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+		 * Report back to the user the time still remaining.
+		 */
+		if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
 			return -EFAULT;
 
 		restart_block->fn = posix_cpu_nsleep_restart;
-		restart_block->arg0 = which_clock;
-		restart_block->arg1 = (unsigned long) rmtp;
-		restart_block->arg2 = rqtp->tv_sec;
-		restart_block->arg3 = rqtp->tv_nsec;
+		restart_block->nanosleep.index = which_clock;
+		restart_block->nanosleep.rmtp = rmtp;
+		restart_block->nanosleep.expires = timespec_to_ns(rqtp);
 	}
 	return error;
 }
 
-long posix_cpu_nsleep_restart(struct restart_block *restart_block)
+static long posix_cpu_nsleep_restart(struct restart_block *restart_block)
 {
-	clockid_t which_clock = restart_block->arg0;
-	struct timespec __user *rmtp;
+	clockid_t which_clock = restart_block->nanosleep.index;
 	struct timespec t;
 	struct itimerspec it;
 	int error;
 
-	rmtp = (struct timespec __user *) restart_block->arg1;
-	t.tv_sec = restart_block->arg2;
-	t.tv_nsec = restart_block->arg3;
+	t = ns_to_timespec(restart_block->nanosleep.expires);
 
-	restart_block->fn = do_no_restart_syscall;
 	error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
 
 	if (error == -ERESTART_RESTARTBLOCK) {
+		struct timespec __user *rmtp = restart_block->nanosleep.rmtp;
 		/*
-	 	 * Report back to the user the time still remaining.
-	 	 */
-		if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+		 * Report back to the user the time still remaining.
+		 */
+		if (rmtp && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
 			return -EFAULT;
 
-		restart_block->fn = posix_cpu_nsleep_restart;
-		restart_block->arg0 = which_clock;
-		restart_block->arg1 = (unsigned long) rmtp;
-		restart_block->arg2 = t.tv_sec;
-		restart_block->arg3 = t.tv_nsec;
+		restart_block->nanosleep.expires = timespec_to_ns(&t);
 	}
 	return error;
 
 }
 
-
 #define PROCESS_CLOCK	MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)
 #define THREAD_CLOCK	MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)
 
@@ -1594,38 +1589,37 @@ static int thread_cpu_timer_create(struct k_itimer *timer)
 	timer->it_clock = THREAD_CLOCK;
 	return posix_cpu_timer_create(timer);
 }
-static int thread_cpu_nsleep(const clockid_t which_clock, int flags,
-			      struct timespec *rqtp, struct timespec __user *rmtp)
-{
-	return -EINVAL;
-}
-static long thread_cpu_nsleep_restart(struct restart_block *restart_block)
-{
-	return -EINVAL;
-}
+
+struct k_clock clock_posix_cpu = {
+	.clock_getres	= posix_cpu_clock_getres,
+	.clock_set	= posix_cpu_clock_set,
+	.clock_get	= posix_cpu_clock_get,
+	.timer_create	= posix_cpu_timer_create,
+	.nsleep		= posix_cpu_nsleep,
+	.nsleep_restart	= posix_cpu_nsleep_restart,
+	.timer_set	= posix_cpu_timer_set,
+	.timer_del	= posix_cpu_timer_del,
+	.timer_get	= posix_cpu_timer_get,
+};
 
 static __init int init_posix_cpu_timers(void)
 {
 	struct k_clock process = {
-		.clock_getres = process_cpu_clock_getres,
-		.clock_get = process_cpu_clock_get,
-		.clock_set = do_posix_clock_nosettime,
-		.timer_create = process_cpu_timer_create,
-		.nsleep = process_cpu_nsleep,
-		.nsleep_restart = process_cpu_nsleep_restart,
+		.clock_getres	= process_cpu_clock_getres,
+		.clock_get	= process_cpu_clock_get,
+		.timer_create	= process_cpu_timer_create,
+		.nsleep		= process_cpu_nsleep,
+		.nsleep_restart	= process_cpu_nsleep_restart,
 	};
 	struct k_clock thread = {
-		.clock_getres = thread_cpu_clock_getres,
-		.clock_get = thread_cpu_clock_get,
-		.clock_set = do_posix_clock_nosettime,
-		.timer_create = thread_cpu_timer_create,
-		.nsleep = thread_cpu_nsleep,
-		.nsleep_restart = thread_cpu_nsleep_restart,
+		.clock_getres	= thread_cpu_clock_getres,
+		.clock_get	= thread_cpu_clock_get,
+		.timer_create	= thread_cpu_timer_create,
 	};
 	struct timespec ts;
 
-	register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
-	register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
+	posix_timers_register_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
+	posix_timers_register_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
 
 	cputime_to_timespec(cputime_one_jiffy, &ts);
 	onecputick = ts.tv_nsec;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index 93bd2eb..4c01249 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -41,6 +41,7 @@
 #include <linux/init.h>
 #include <linux/compiler.h>
 #include <linux/idr.h>
+#include <linux/posix-clock.h>
 #include <linux/posix-timers.h>
 #include <linux/syscalls.h>
 #include <linux/wait.h>
@@ -81,6 +82,14 @@ static DEFINE_SPINLOCK(idr_lock);
 #error "SIGEV_THREAD_ID must not share bit with other SIGEV values!"
 #endif
 
+/*
+ * parisc wants ENOTSUP instead of EOPNOTSUPP
+ */
+#ifndef ENOTSUP
+# define ENANOSLEEP_NOTSUP EOPNOTSUPP
+#else
+# define ENANOSLEEP_NOTSUP ENOTSUP
+#endif
 
 /*
  * The timer ID is turned into a timer address by idr_find().
@@ -94,11 +103,7 @@ static DEFINE_SPINLOCK(idr_lock);
 /*
  * CLOCKs: The POSIX standard calls for a couple of clocks and allows us
  *	    to implement others.  This structure defines the various
- *	    clocks and allows the possibility of adding others.	 We
- *	    provide an interface to add clocks to the table and expect
- *	    the "arch" code to add at least one clock that is high
- *	    resolution.	 Here we define the standard CLOCK_REALTIME as a
- *	    1/HZ resolution clock.
+ *	    clocks.
  *
  * RESOLUTION: Clock resolution is used to round up timer and interval
  *	    times, NOT to report clock times, which are reported with as
@@ -108,20 +113,13 @@ static DEFINE_SPINLOCK(idr_lock);
  *	    necessary code is written.	The standard says we should say
  *	    something about this issue in the documentation...
  *
- * FUNCTIONS: The CLOCKs structure defines possible functions to handle
- *	    various clock functions.  For clocks that use the standard
- *	    system timer code these entries should be NULL.  This will
- *	    allow dispatch without the overhead of indirect function
- *	    calls.  CLOCKS that depend on other sources (e.g. WWV or GPS)
- *	    must supply functions here, even if the function just returns
- *	    ENOSYS.  The standard POSIX timer management code assumes the
- *	    following: 1.) The k_itimer struct (sched.h) is used for the
- *	    timer.  2.) The list, it_lock, it_clock, it_id and it_pid
- *	    fields are not modified by timer code.
+ * FUNCTIONS: The CLOCKs structure defines possible functions to
+ *	    handle various clock functions.
  *
- *          At this time all functions EXCEPT clock_nanosleep can be
- *          redirected by the CLOCKS structure.  Clock_nanosleep is in
- *          there, but the code ignores it.
+ *	    The standard POSIX timer management code assumes the
+ *	    following: 1.) The k_itimer struct (sched.h) is used for
+ *	    the timer.  2.) The list, it_lock, it_clock, it_id and
+ *	    it_pid fields are not modified by timer code.
  *
  * Permissions: It is assumed that the clock_settime() function defined
  *	    for each clock will take care of permission checks.	 Some
@@ -138,6 +136,7 @@ static struct k_clock posix_clocks[MAX_CLOCKS];
  */
 static int common_nsleep(const clockid_t, int flags, struct timespec *t,
 			 struct timespec __user *rmtp);
+static int common_timer_create(struct k_itimer *new_timer);
 static void common_timer_get(struct k_itimer *, struct itimerspec *);
 static int common_timer_set(struct k_itimer *, int,
 			    struct itimerspec *, struct itimerspec *);
@@ -158,76 +157,24 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
 	spin_unlock_irqrestore(&timr->it_lock, flags);
 }
 
-/*
- * Call the k_clock hook function if non-null, or the default function.
- */
-#define CLOCK_DISPATCH(clock, call, arglist) \
- 	((clock) < 0 ? posix_cpu_##call arglist : \
- 	 (posix_clocks[clock].call != NULL \
- 	  ? (*posix_clocks[clock].call) arglist : common_##call arglist))
-
-/*
- * Default clock hook functions when the struct k_clock passed
- * to register_posix_clock leaves a function pointer null.
- *
- * The function common_CALL is the default implementation for
- * the function pointer CALL in struct k_clock.
- */
-
-static inline int common_clock_getres(const clockid_t which_clock,
-				      struct timespec *tp)
-{
-	tp->tv_sec = 0;
-	tp->tv_nsec = posix_clocks[which_clock].res;
-	return 0;
-}
-
-/*
- * Get real time for posix timers
- */
-static int common_clock_get(clockid_t which_clock, struct timespec *tp)
+/* Get clock_realtime */
+static int posix_clock_realtime_get(clockid_t which_clock, struct timespec *tp)
 {
 	ktime_get_real_ts(tp);
 	return 0;
 }
 
-static inline int common_clock_set(const clockid_t which_clock,
-				   struct timespec *tp)
+/* Set clock_realtime */
+static int posix_clock_realtime_set(const clockid_t which_clock,
+				    const struct timespec *tp)
 {
 	return do_sys_settimeofday(tp, NULL);
 }
 
-static int common_timer_create(struct k_itimer *new_timer)
-{
-	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0);
-	return 0;
-}
-
-static int no_timer_create(struct k_itimer *new_timer)
-{
-	return -EOPNOTSUPP;
-}
-
-static int no_nsleep(const clockid_t which_clock, int flags,
-		     struct timespec *tsave, struct timespec __user *rmtp)
-{
-	return -EOPNOTSUPP;
-}
-
-/*
- * Return nonzero if we know a priori this clockid_t value is bogus.
- */
-static inline int invalid_clockid(const clockid_t which_clock)
+static int posix_clock_realtime_adj(const clockid_t which_clock,
+				    struct timex *t)
 {
-	if (which_clock < 0)	/* CPU clock, posix_cpu_* will check it */
-		return 0;
-	if ((unsigned) which_clock >= MAX_CLOCKS)
-		return 1;
-	if (posix_clocks[which_clock].clock_getres != NULL)
-		return 0;
-	if (posix_clocks[which_clock].res != 0)
-		return 0;
-	return 1;
+	return do_adjtimex(t);
 }
 
 /*
@@ -240,7 +187,7 @@ static int posix_ktime_get_ts(clockid_t which_clock, struct timespec *tp)
 }
 
 /*
- * Get monotonic time for posix timers
+ * Get monotonic-raw time for posix timers
  */
 static int posix_get_monotonic_raw(clockid_t which_clock, struct timespec *tp)
 {
@@ -267,46 +214,70 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec *tp
 	*tp = ktime_to_timespec(KTIME_LOW_RES);
 	return 0;
 }
+
+static int posix_get_boottime(const clockid_t which_clock, struct timespec *tp)
+{
+	get_monotonic_boottime(tp);
+	return 0;
+}
+
+
 /*
  * Initialize everything, well, just everything in Posix clocks/timers ;)
  */
 static __init int init_posix_timers(void)
 {
 	struct k_clock clock_realtime = {
-		.clock_getres = hrtimer_get_res,
+		.clock_getres	= hrtimer_get_res,
+		.clock_get	= posix_clock_realtime_get,
+		.clock_set	= posix_clock_realtime_set,
+		.clock_adj	= posix_clock_realtime_adj,
+		.nsleep		= common_nsleep,
+		.nsleep_restart	= hrtimer_nanosleep_restart,
+		.timer_create	= common_timer_create,
+		.timer_set	= common_timer_set,
+		.timer_get	= common_timer_get,
+		.timer_del	= common_timer_del,
 	};
 	struct k_clock clock_monotonic = {
-		.clock_getres = hrtimer_get_res,
-		.clock_get = posix_ktime_get_ts,
-		.clock_set = do_posix_clock_nosettime,
+		.clock_getres	= hrtimer_get_res,
+		.clock_get	= posix_ktime_get_ts,
+		.nsleep		= common_nsleep,
+		.nsleep_restart	= hrtimer_nanosleep_restart,
+		.timer_create	= common_timer_create,
+		.timer_set	= common_timer_set,
+		.timer_get	= common_timer_get,
+		.timer_del	= common_timer_del,
 	};
 	struct k_clock clock_monotonic_raw = {
-		.clock_getres = hrtimer_get_res,
-		.clock_get = posix_get_monotonic_raw,
-		.clock_set = do_posix_clock_nosettime,
-		.timer_create = no_timer_create,
-		.nsleep = no_nsleep,
+		.clock_getres	= hrtimer_get_res,
+		.clock_get	= posix_get_monotonic_raw,
 	};
 	struct k_clock clock_realtime_coarse = {
-		.clock_getres = posix_get_coarse_res,
-		.clock_get = posix_get_realtime_coarse,
-		.clock_set = do_posix_clock_nosettime,
-		.timer_create = no_timer_create,
-		.nsleep = no_nsleep,
+		.clock_getres	= posix_get_coarse_res,
+		.clock_get	= posix_get_realtime_coarse,
 	};
 	struct k_clock clock_monotonic_coarse = {
-		.clock_getres = posix_get_coarse_res,
-		.clock_get = posix_get_monotonic_coarse,
-		.clock_set = do_posix_clock_nosettime,
-		.timer_create = no_timer_create,
-		.nsleep = no_nsleep,
+		.clock_getres	= posix_get_coarse_res,
+		.clock_get	= posix_get_monotonic_coarse,
+	};
+	struct k_clock clock_boottime = {
+		.clock_getres	= hrtimer_get_res,
+		.clock_get	= posix_get_boottime,
+		.nsleep		= common_nsleep,
+		.nsleep_restart	= hrtimer_nanosleep_restart,
+		.timer_create	= common_timer_create,
+		.timer_set	= common_timer_set,
+		.timer_get	= common_timer_get,
+		.timer_del	= common_timer_del,
 	};
 
-	register_posix_clock(CLOCK_REALTIME, &clock_realtime);
-	register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic);
-	register_posix_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);
-	register_posix_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse);
-	register_posix_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse);
+	posix_timers_register_clock(CLOCK_REALTIME, &clock_realtime);
+	posix_timers_register_clock(CLOCK_MONOTONIC, &clock_monotonic);
+	posix_timers_register_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw);
+	posix_timers_register_clock(CLOCK_REALTIME_COARSE, &clock_realtime_coarse);
+	posix_timers_register_clock(CLOCK_MONOTONIC_COARSE, &clock_monotonic_coarse);
+	posix_timers_register_clock(CLOCK_BOOTTIME, &clock_boottime);
 
 	posix_timers_cache = kmem_cache_create("posix_timers_cache",
 					sizeof (struct k_itimer), 0, SLAB_PANIC,
@@ -482,17 +453,29 @@ static struct pid *good_sigevent(sigevent_t * event)
 	return task_pid(rtn);
 }
 
-void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock)
+void posix_timers_register_clock(const clockid_t clock_id,
+				 struct k_clock *new_clock)
 {
 	if ((unsigned) clock_id >= MAX_CLOCKS) {
-		printk("POSIX clock register failed for clock_id %d\n",
+		printk(KERN_WARNING "POSIX clock register failed for clock_id %d\n",
+		       clock_id);
+		return;
+	}
+
+	if (!new_clock->clock_get) {
+		printk(KERN_WARNING "POSIX clock id %d lacks clock_get()\n",
+		       clock_id);
+		return;
+	}
+	if (!new_clock->clock_getres) {
+		printk(KERN_WARNING "POSIX clock id %d lacks clock_getres()\n",
 		       clock_id);
 		return;
 	}
 
 	posix_clocks[clock_id] = *new_clock;
 }
-EXPORT_SYMBOL_GPL(register_posix_clock);
+EXPORT_SYMBOL_GPL(posix_timers_register_clock);
 
 static struct k_itimer * alloc_posix_timer(void)
 {
@@ -523,19 +506,39 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
 	kmem_cache_free(posix_timers_cache, tmr);
 }
 
+static struct k_clock *clockid_to_kclock(const clockid_t id)
+{
+	if (id < 0)
+		return (id & CLOCKFD_MASK) == CLOCKFD ?
+			&clock_posix_dynamic : &clock_posix_cpu;
+
+	if (id >= MAX_CLOCKS || !posix_clocks[id].clock_getres)
+		return NULL;
+	return &posix_clocks[id];
+}
+
+static int common_timer_create(struct k_itimer *new_timer)
+{
+	hrtimer_init(&new_timer->it.real.timer, new_timer->it_clock, 0);
+	return 0;
+}
+
 /* Create a POSIX.1b interval timer. */
 
 SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
 		struct sigevent __user *, timer_event_spec,
 		timer_t __user *, created_timer_id)
 {
+	struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct k_itimer *new_timer;
 	int error, new_timer_id;
 	sigevent_t event;
 	int it_id_set = IT_ID_NOT_SET;
 
-	if (invalid_clockid(which_clock))
+	if (!kc)
 		return -EINVAL;
+	if (!kc->timer_create)
+		return -EOPNOTSUPP;
 
 	new_timer = alloc_posix_timer();
 	if (unlikely(!new_timer))
@@ -597,7 +600,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
 		goto out;
 	}
 
-	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+	error = kc->timer_create(new_timer);
 	if (error)
 		goto out;
 
@@ -607,7 +610,7 @@ SYSCALL_DEFINE3(timer_create, const clockid_t, which_clock,
 	spin_unlock_irq(&current->sighand->siglock);
 
 	return 0;
- 	/*
+	/*
 	 * In the case of the timer belonging to another task, after
 	 * the task is unlocked, the timer is owned by the other task
 	 * and may cease to exist at any time.  Don't use or modify
@@ -709,22 +712,28 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
 		struct itimerspec __user *, setting)
 {
-	struct k_itimer *timr;
 	struct itimerspec cur_setting;
+	struct k_itimer *timr;
+	struct k_clock *kc;
 	unsigned long flags;
+	int ret = 0;
 
 	timr = lock_timer(timer_id, &flags);
 	if (!timr)
 		return -EINVAL;
 
-	CLOCK_DISPATCH(timr->it_clock, timer_get, (timr, &cur_setting));
+	kc = clockid_to_kclock(timr->it_clock);
+	if (WARN_ON_ONCE(!kc || !kc->timer_get))
+		ret = -EINVAL;
+	else
+		kc->timer_get(timr, &cur_setting);
 
 	unlock_timer(timr, flags);
 
-	if (copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
+	if (!ret && copy_to_user(setting, &cur_setting, sizeof (cur_setting)))
 		return -EFAULT;
 
-	return 0;
+	return ret;
 }
 
 /*
@@ -813,6 +822,7 @@ SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
 	int error = 0;
 	unsigned long flag;
 	struct itimerspec *rtn = old_setting ? &old_spec : NULL;
+	struct k_clock *kc;
 
 	if (!new_setting)
 		return -EINVAL;
@@ -828,8 +838,11 @@ retry:
 	if (!timr)
 		return -EINVAL;
 
-	error = CLOCK_DISPATCH(timr->it_clock, timer_set,
-			       (timr, flags, &new_spec, rtn));
+	kc = clockid_to_kclock(timr->it_clock);
+	if (WARN_ON_ONCE(!kc || !kc->timer_set))
+		error = -EINVAL;
+	else
+		error = kc->timer_set(timr, flags, &new_spec, rtn);
 
 	unlock_timer(timr, flag);
 	if (error == TIMER_RETRY) {
@@ -844,7 +857,7 @@ retry:
 	return error;
 }
 
-static inline int common_timer_del(struct k_itimer *timer)
+static int common_timer_del(struct k_itimer *timer)
 {
 	timer->it.real.interval.tv64 = 0;
 
@@ -855,7 +868,11 @@ static inline int common_timer_del(struct k_itimer *timer)
 
 static inline int timer_delete_hook(struct k_itimer *timer)
 {
-	return CLOCK_DISPATCH(timer->it_clock, timer_del, (timer));
+	struct k_clock *kc = clockid_to_kclock(timer->it_clock);
+
+	if (WARN_ON_ONCE(!kc || !kc->timer_del))
+		return -EINVAL;
+	return kc->timer_del(timer);
 }
 
 /* Delete a POSIX.1b interval timer. */
@@ -927,69 +944,76 @@ void exit_itimers(struct signal_struct *sig)
 	}
 }
 
-/* Not available / possible... functions */
-int do_posix_clock_nosettime(const clockid_t clockid, struct timespec *tp)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(do_posix_clock_nosettime);
-
-int do_posix_clock_nonanosleep(const clockid_t clock, int flags,
-			       struct timespec *t, struct timespec __user *r)
-{
-#ifndef ENOTSUP
-	return -EOPNOTSUPP;	/* aka ENOTSUP in userland for POSIX */
-#else  /*  parisc does define it separately.  */
-	return -ENOTSUP;
-#endif
-}
-EXPORT_SYMBOL_GPL(do_posix_clock_nonanosleep);
-
 SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
 		const struct timespec __user *, tp)
 {
+	struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct timespec new_tp;
 
-	if (invalid_clockid(which_clock))
+	if (!kc || !kc->clock_set)
 		return -EINVAL;
+
 	if (copy_from_user(&new_tp, tp, sizeof (*tp)))
 		return -EFAULT;
 
-	return CLOCK_DISPATCH(which_clock, clock_set, (which_clock, &new_tp));
+	return kc->clock_set(which_clock, &new_tp);
 }
 
 SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
 		struct timespec __user *,tp)
 {
+	struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct timespec kernel_tp;
 	int error;
 
-	if (invalid_clockid(which_clock))
+	if (!kc)
 		return -EINVAL;
-	error = CLOCK_DISPATCH(which_clock, clock_get,
-			       (which_clock, &kernel_tp));
+
+	error = kc->clock_get(which_clock, &kernel_tp);
+
 	if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
 		error = -EFAULT;
 
 	return error;
+}
+
+SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock,
+		struct timex __user *, utx)
+{
+	struct k_clock *kc = clockid_to_kclock(which_clock);
+	struct timex ktx;
+	int err;
+
+	if (!kc)
+		return -EINVAL;
+	if (!kc->clock_adj)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&ktx, utx, sizeof(ktx)))
+		return -EFAULT;
+
+	err = kc->clock_adj(which_clock, &ktx);
+
+	if (!err && copy_to_user(utx, &ktx, sizeof(ktx)))
+		return -EFAULT;
 
+	return err;
 }
 
 SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock,
 		struct timespec __user *, tp)
 {
+	struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct timespec rtn_tp;
 	int error;
 
-	if (invalid_clockid(which_clock))
+	if (!kc)
 		return -EINVAL;
 
-	error = CLOCK_DISPATCH(which_clock, clock_getres,
-			       (which_clock, &rtn_tp));
+	error = kc->clock_getres(which_clock, &rtn_tp);
 
-	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) {
+	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
 		error = -EFAULT;
-	}
 
 	return error;
 }
@@ -1009,10 +1033,13 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 		const struct timespec __user *, rqtp,
 		struct timespec __user *, rmtp)
 {
+	struct k_clock *kc = clockid_to_kclock(which_clock);
 	struct timespec t;
 
-	if (invalid_clockid(which_clock))
+	if (!kc)
 		return -EINVAL;
+	if (!kc->nsleep)
+		return -ENANOSLEEP_NOTSUP;
 
 	if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
 		return -EFAULT;
@@ -1020,27 +1047,20 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 	if (!timespec_valid(&t))
 		return -EINVAL;
 
-	return CLOCK_DISPATCH(which_clock, nsleep,
-			      (which_clock, flags, &t, rmtp));
-}
-
-/*
- * nanosleep_restart for monotonic and realtime clocks
- */
-static int common_nsleep_restart(struct restart_block *restart_block)
-{
-	return hrtimer_nanosleep_restart(restart_block);
+	return kc->nsleep(which_clock, flags, &t, rmtp);
 }
 
 /*
  * This will restart clock_nanosleep. This is required only by
  * compat_clock_nanosleep_restart for now.
  */
-long
-clock_nanosleep_restart(struct restart_block *restart_block)
+long clock_nanosleep_restart(struct restart_block *restart_block)
 {
-	clockid_t which_clock = restart_block->arg0;
+	clockid_t which_clock = restart_block->nanosleep.index;
+	struct k_clock *kc = clockid_to_kclock(which_clock);
+
+	if (WARN_ON_ONCE(!kc || !kc->nsleep_restart))
+		return -EINVAL;
 
-	return CLOCK_DISPATCH(which_clock, nsleep_restart,
-			      (restart_block));
+	return kc->nsleep_restart(restart_block);
 }
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 2657299..4603f08 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -1,125 +1,12 @@
-config PM
-	bool "Power Management support"
-	depends on !IA64_HP_SIM
-	---help---
-	  "Power Management" means that parts of your computer are shut
-	  off or put into a power conserving "sleep" mode if they are not
-	  being used.  There are two competing standards for doing this: APM
-	  and ACPI.  If you want to use either one, say Y here and then also
-	  to the requisite support below.
-
-	  Power Management is most important for battery powered laptop
-	  computers; if you have a laptop, check out the Linux Laptop home
-	  page on the WWW at <http://www.linux-on-laptops.com/> or
-	  Tuxmobil - Linux on Mobile Computers at <http://www.tuxmobil.org/>
-	  and the Battery Powered Linux mini-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  Note that, even if you say N here, Linux on the x86 architecture
-	  will issue the hlt instruction if nothing is to be done, thereby
-	  sending the processor to sleep and saving power.
-
-config PM_DEBUG
-	bool "Power Management Debug Support"
-	depends on PM
-	---help---
-	This option enables various debugging support in the Power Management
-	code. This is helpful when debugging and reporting PM bugs, like
-	suspend support.
-
-config PM_ADVANCED_DEBUG
-	bool "Extra PM attributes in sysfs for low-level debugging/testing"
-	depends on PM_DEBUG
-	default n
-	---help---
-	Add extra sysfs attributes allowing one to access some Power Management
-	fields of device objects from user space.  If you are not a kernel
-	developer interested in debugging/testing Power Management, say "no".
-
-config PM_VERBOSE
-	bool "Verbose Power Management debugging"
-	depends on PM_DEBUG
-	default n
-	---help---
-	This option enables verbose messages from the Power Management code.
-
-config CAN_PM_TRACE
-	def_bool y
-	depends on PM_DEBUG && PM_SLEEP && EXPERIMENTAL
-
-config PM_TRACE
-	bool
-	help
-	  This enables code to save the last PM event point across
-	  reboot. The architecture needs to support this, x86 for
-	  example does by saving things in the RTC, see below.
-
-	  The architecture specific code must provide the extern
-	  functions from <linux/resume-trace.h> as well as the
-	  <asm/resume-trace.h> header with a TRACE_RESUME() macro.
-
-	  The way the information is presented is architecture-
-	  dependent, x86 will print the information during a
-	  late_initcall.
-
-config PM_TRACE_RTC
-	bool "Suspend/resume event tracing"
-	depends on CAN_PM_TRACE
-	depends on X86
-	select PM_TRACE
-	default n
-	---help---
-	This enables some cheesy code to save the last PM event point in the
-	RTC across reboots, so that you can debug a machine that just hangs
-	during suspend (or more commonly, during resume).
-
-	To use this debugging feature you should attempt to suspend the
-	machine, reboot it and then run
-
-		dmesg -s 1000000 | grep 'hash matches'
-
-	CAUTION: this option will cause your machine's real-time clock to be
-	set to an invalid time after a resume.
-
-config PM_SLEEP_SMP
-	bool
-	depends on SMP
-	depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE
-	depends on PM_SLEEP
-	select HOTPLUG
-	select HOTPLUG_CPU
-	default y
-
-config PM_SLEEP
-	bool
-	depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
-	default y
-
-config PM_SLEEP_ADVANCED_DEBUG
-	bool
-	depends on PM_ADVANCED_DEBUG
-	default n
-
 config SUSPEND
 	bool "Suspend to RAM and standby"
-	depends on PM && ARCH_SUSPEND_POSSIBLE
+	depends on ARCH_SUSPEND_POSSIBLE
 	default y
 	---help---
 	  Allow the system to enter sleep states in which main memory is
 	  powered and thus its contents are preserved, such as the
 	  suspend-to-RAM state (e.g. the ACPI S3 state).
 
-config PM_TEST_SUSPEND
-	bool "Test suspend/resume and wakealarm during bootup"
-	depends on SUSPEND && PM_DEBUG && RTC_CLASS=y
-	---help---
-	This option will let you suspend your machine during bootup, and
-	make it wake up a few seconds later using an RTC wakeup alarm.
-	Enable this with a kernel parameter like "test_suspend=mem".
-
-	You probably want to have your system's RTC driver statically
-	linked, ensuring that it's available when this test runs.
-
 config SUSPEND_FREEZER
 	bool "Enable freezer for suspend to RAM/standby" \
 		if ARCH_WANTS_FREEZER_CONTROL || BROKEN
@@ -133,7 +20,7 @@ config SUSPEND_FREEZER
 
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
-	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
+	depends on SWAP && ARCH_HIBERNATION_POSSIBLE
 	select LZO_COMPRESS
 	select LZO_DECOMPRESS
 	---help---
@@ -196,6 +83,106 @@ config PM_STD_PARTITION
 	  suspended image to. It will simply pick the first available swap 
 	  device.
 
+config PM_SLEEP
+	def_bool y
+	depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
+
+config PM_SLEEP_SMP
+	def_bool y
+	depends on SMP
+	depends on ARCH_SUSPEND_POSSIBLE || ARCH_HIBERNATION_POSSIBLE
+	depends on PM_SLEEP
+	select HOTPLUG
+	select HOTPLUG_CPU
+
+config PM_RUNTIME
+	bool "Run-time PM core functionality"
+	depends on !IA64_HP_SIM
+	---help---
+	  Enable functionality allowing I/O devices to be put into energy-saving
+	  (low power) states at run time (or autosuspended) after a specified
+	  period of inactivity and woken up in response to a hardware-generated
+	  wake-up event or a driver's request.
+
+	  Hardware support is generally required for this functionality to work
+	  and the bus type drivers of the buses the devices are on are
+	  responsible for the actual handling of the autosuspend requests and
+	  wake-up events.
+
+config PM
+	def_bool y
+	depends on PM_SLEEP || PM_RUNTIME
+
+config PM_DEBUG
+	bool "Power Management Debug Support"
+	depends on PM
+	---help---
+	This option enables various debugging support in the Power Management
+	code. This is helpful when debugging and reporting PM bugs, like
+	suspend support.
+
+config PM_VERBOSE
+	bool "Verbose Power Management debugging"
+	depends on PM_DEBUG
+	---help---
+	This option enables verbose messages from the Power Management code.
+
+config PM_ADVANCED_DEBUG
+	bool "Extra PM attributes in sysfs for low-level debugging/testing"
+	depends on PM_DEBUG
+	---help---
+	Add extra sysfs attributes allowing one to access some Power Management
+	fields of device objects from user space.  If you are not a kernel
+	developer interested in debugging/testing Power Management, say "no".
+
+config PM_TEST_SUSPEND
+	bool "Test suspend/resume and wakealarm during bootup"
+	depends on SUSPEND && PM_DEBUG && RTC_CLASS=y
+	---help---
+	This option will let you suspend your machine during bootup, and
+	make it wake up a few seconds later using an RTC wakeup alarm.
+	Enable this with a kernel parameter like "test_suspend=mem".
+
+	You probably want to have your system's RTC driver statically
+	linked, ensuring that it's available when this test runs.
+
+config CAN_PM_TRACE
+	def_bool y
+	depends on PM_DEBUG && PM_SLEEP
+
+config PM_TRACE
+	bool
+	help
+	  This enables code to save the last PM event point across
+	  reboot. The architecture needs to support this, x86 for
+	  example does by saving things in the RTC, see below.
+
+	  The architecture specific code must provide the extern
+	  functions from <linux/resume-trace.h> as well as the
+	  <asm/resume-trace.h> header with a TRACE_RESUME() macro.
+
+	  The way the information is presented is architecture-
+	  dependent, x86 will print the information during a
+	  late_initcall.
+
+config PM_TRACE_RTC
+	bool "Suspend/resume event tracing"
+	depends on CAN_PM_TRACE
+	depends on X86
+	select PM_TRACE
+	---help---
+	This enables some cheesy code to save the last PM event point in the
+	RTC across reboots, so that you can debug a machine that just hangs
+	during suspend (or more commonly, during resume).
+
+	To use this debugging feature you should attempt to suspend the
+	machine, reboot it and then run
+
+		dmesg -s 1000000 | grep 'hash matches'
+
+	CAUTION: this option will cause your machine's real-time clock to be
+	set to an invalid time after a resume.
+
 config APM_EMULATION
 	tristate "Advanced Power Management Emulation"
 	depends on PM && SYS_SUPPORTS_APM_EMULATION
@@ -222,31 +209,11 @@ config APM_EMULATION
 	  anything, try disabling/enabling this option (or disabling/enabling
 	  APM in your BIOS).
 
-config PM_RUNTIME
-	bool "Run-time PM core functionality"
-	depends on PM
-	---help---
-	  Enable functionality allowing I/O devices to be put into energy-saving
-	  (low power) states at run time (or autosuspended) after a specified
-	  period of inactivity and woken up in response to a hardware-generated
-	  wake-up event or a driver's request.
-
-	  Hardware support is generally required for this functionality to work
-	  and the bus type drivers of the buses the devices are on are
-	  responsible for the actual handling of the autosuspend requests and
-	  wake-up events.
-
-config PM_OPS
-	bool
-	depends on PM_SLEEP || PM_RUNTIME
-	default y
-
 config ARCH_HAS_OPP
 	bool
 
 config PM_OPP
 	bool "Operating Performance Point (OPP) Layer library"
-	depends on PM
 	depends on ARCH_HAS_OPP
 	---help---
 	  SOCs have a standard set of tuples consisting of frequency and
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index c350e18..c5ebc6a 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -1,4 +1,5 @@
-ccflags-$(CONFIG_PM_DEBUG)	:=	-DDEBUG
+
+ccflags-$(CONFIG_PM_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_PM)		+= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 1832bd2..aeabd26 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -23,6 +23,7 @@
 #include <linux/cpu.h>
 #include <linux/freezer.h>
 #include <linux/gfp.h>
+#include <linux/syscore_ops.h>
 #include <scsi/scsi_scan.h>
 #include <asm/suspend.h>
 
@@ -272,6 +273,8 @@ static int create_image(int platform_mode)
 	local_irq_disable();
 
 	error = sysdev_suspend(PMSG_FREEZE);
+	if (!error)
+		error = syscore_suspend();
 	if (error) {
 		printk(KERN_ERR "PM: Some system devices failed to power down, "
 			"aborting hibernation\n");
@@ -295,6 +298,7 @@ static int create_image(int platform_mode)
 	}
 
  Power_up:
+	syscore_resume();
 	sysdev_resume();
 	/* NOTE:  dpm_resume_noirq() is just a resume() for devices
 	 * that suspended with irqs off ... no overall powerup.
@@ -403,6 +407,8 @@ static int resume_target_kernel(bool platform_mode)
 	local_irq_disable();
 
 	error = sysdev_suspend(PMSG_QUIESCE);
+	if (!error)
+		error = syscore_suspend();
 	if (error)
 		goto Enable_irqs;
 
@@ -429,6 +435,7 @@ static int resume_target_kernel(bool platform_mode)
 	restore_processor_state();
 	touch_softlockup_watchdog();
 
+	syscore_resume();
 	sysdev_resume();
 
  Enable_irqs:
@@ -516,6 +523,7 @@ int hibernation_platform_enter(void)
 
 	local_irq_disable();
 	sysdev_suspend(PMSG_HIBERNATE);
+	syscore_suspend();
 	if (pm_wakeup_pending()) {
 		error = -EAGAIN;
 		goto Power_up;
@@ -526,6 +534,7 @@ int hibernation_platform_enter(void)
 	while (1);
 
  Power_up:
+	syscore_resume();
 	sysdev_resume();
 	local_irq_enable();
 	enable_nonboot_cpus();
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 7018530..8eaba5f 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -17,9 +17,6 @@
 
 DEFINE_MUTEX(pm_mutex);
 
-unsigned int pm_flags;
-EXPORT_SYMBOL(pm_flags);
-
 #ifdef CONFIG_PM_SLEEP
 
 /* Routines for PM-transition notifications */
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 64db648..ca0aacc 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -42,15 +42,15 @@ static void swsusp_unset_page_forbidden(struct page *);
 
 /*
  * Preferred image size in bytes (tunable via /sys/power/image_size).
- * When it is set to N, swsusp will do its best to ensure the image
- * size will not exceed N bytes, but if that is impossible, it will
- * try to create the smallest image possible.
+ * When it is set to N, the image creating code will do its best to
+ * ensure the image size will not exceed N bytes, but if that is
+ * impossible, it will try to create the smallest image possible.
  */
 unsigned long image_size;
 
 void __init hibernate_image_size_init(void)
 {
-	image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE;
+	image_size = (totalram_pages / 3) * PAGE_SIZE;
 }
 
 /* List of PBEs needed for restoring the pages that were allocated before
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index de6f86b..2814c32 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -22,6 +22,7 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
+#include <linux/syscore_ops.h>
 #include <trace/events/power.h>
 
 #include "power.h"
@@ -163,11 +164,14 @@ static int suspend_enter(suspend_state_t state)
 	BUG_ON(!irqs_disabled());
 
 	error = sysdev_suspend(PMSG_SUSPEND);
+	if (!error)
+		error = syscore_suspend();
 	if (!error) {
 		if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
 			error = suspend_ops->enter(state);
 			events_check_enabled = false;
 		}
+		syscore_resume();
 		sysdev_resume();
 	}
 
diff --git a/kernel/printk.c b/kernel/printk.c
index 3623152..da8ca81 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -53,7 +53,7 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
 #define __LOG_BUF_LEN	(1 << CONFIG_LOG_BUF_SHIFT)
 
 /* printk's without a loglevel use this.. */
-#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
+#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL
 
 /* We show everything that is MORE important than this.. */
 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
@@ -113,6 +113,11 @@ static unsigned con_start;	/* Index into log_buf: next char to be sent to consol
 static unsigned log_end;	/* Index into log_buf: most-recently-written-char + 1 */
 
 /*
+ * If exclusive_console is non-NULL then only this console is to be printed to.
+ */
+static struct console *exclusive_console;
+
+/*
  *	Array of consoles built from command line options (console=)
  */
 struct console_cmdline
@@ -476,6 +481,8 @@ static void __call_console_drivers(unsigned start, unsigned end)
 	struct console *con;
 
 	for_each_console(con) {
+		if (exclusive_console && con != exclusive_console)
+			continue;
 		if ((con->flags & CON_ENABLED) && con->write &&
 				(cpu_online(smp_processor_id()) ||
 				(con->flags & CON_ANYTIME)))
@@ -515,6 +522,71 @@ static void _call_console_drivers(unsigned start,
 }
 
 /*
+ * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the
+ * lower 3 bit are the log level, the rest are the log facility. In case
+ * userspace passes usual userspace syslog messages to /dev/kmsg or
+ * /dev/ttyprintk, the log prefix might contain the facility. Printk needs
+ * to extract the correct log level for in-kernel processing, and not mangle
+ * the original value.
+ *
+ * If a prefix is found, the length of the prefix is returned. If 'level' is
+ * passed, it will be filled in with the log level without a possible facility
+ * value. If 'special' is passed, the special printk prefix chars are accepted
+ * and returned. If no valid header is found, 0 is returned and the passed
+ * variables are not touched.
+ */
+static size_t log_prefix(const char *p, unsigned int *level, char *special)
+{
+	unsigned int lev = 0;
+	char sp = '\0';
+	size_t len;
+
+	if (p[0] != '<' || !p[1])
+		return 0;
+	if (p[2] == '>') {
+		/* usual single digit level number or special char */
+		switch (p[1]) {
+		case '0' ... '7':
+			lev = p[1] - '0';
+			break;
+		case 'c': /* KERN_CONT */
+		case 'd': /* KERN_DEFAULT */
+			sp = p[1];
+			break;
+		default:
+			return 0;
+		}
+		len = 3;
+	} else {
+		/* multi digit including the level and facility number */
+		char *endp = NULL;
+
+		if (p[1] < '0' && p[1] > '9')
+			return 0;
+
+		lev = (simple_strtoul(&p[1], &endp, 10) & 7);
+		if (endp == NULL || endp[0] != '>')
+			return 0;
+		len = (endp + 1) - p;
+	}
+
+	/* do not accept special char if not asked for */
+	if (sp && !special)
+		return 0;
+
+	if (special) {
+		*special = sp;
+		/* return special char, do not touch level */
+		if (sp)
+			return len;
+	}
+
+	if (level)
+		*level = lev;
+	return len;
+}
+
+/*
  * Call the console drivers, asking them to write out
  * log_buf[start] to log_buf[end - 1].
  * The console_lock must be held.
@@ -529,13 +601,9 @@ static void call_console_drivers(unsigned start, unsigned end)
 	cur_index = start;
 	start_print = start;
 	while (cur_index != end) {
-		if (msg_level < 0 && ((end - cur_index) > 2) &&
-				LOG_BUF(cur_index + 0) == '<' &&
-				LOG_BUF(cur_index + 1) >= '0' &&
-				LOG_BUF(cur_index + 1) <= '7' &&
-				LOG_BUF(cur_index + 2) == '>') {
-			msg_level = LOG_BUF(cur_index + 1) - '0';
-			cur_index += 3;
+		if (msg_level < 0 && ((end - cur_index) > 2)) {
+			/* strip log prefix */
+			cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL);
 			start_print = cur_index;
 		}
 		while (cur_index != end) {
@@ -733,6 +801,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 	unsigned long flags;
 	int this_cpu;
 	char *p;
+	size_t plen;
+	char special;
 
 	boot_delay_msec();
 	printk_delay();
@@ -773,45 +843,52 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 	printed_len += vscnprintf(printk_buf + printed_len,
 				  sizeof(printk_buf) - printed_len, fmt, args);
 
-
 	p = printk_buf;
 
-	/* Do we have a loglevel in the string? */
-	if (p[0] == '<') {
-		unsigned char c = p[1];
-		if (c && p[2] == '>') {
-			switch (c) {
-			case '0' ... '7': /* loglevel */
-				current_log_level = c - '0';
-			/* Fallthrough - make sure we're on a new line */
-			case 'd': /* KERN_DEFAULT */
-				if (!new_text_line) {
-					emit_log_char('\n');
-					new_text_line = 1;
-				}
-			/* Fallthrough - skip the loglevel */
-			case 'c': /* KERN_CONT */
-				p += 3;
-				break;
+	/* Read log level and handle special printk prefix */
+	plen = log_prefix(p, &current_log_level, &special);
+	if (plen) {
+		p += plen;
+
+		switch (special) {
+		case 'c': /* Strip <c> KERN_CONT, continue line */
+			plen = 0;
+			break;
+		case 'd': /* Strip <d> KERN_DEFAULT, start new line */
+			plen = 0;
+		default:
+			if (!new_text_line) {
+				emit_log_char('\n');
+				new_text_line = 1;
 			}
 		}
 	}
 
 	/*
-	 * Copy the output into log_buf.  If the caller didn't provide
-	 * appropriate log level tags, we insert them here
+	 * Copy the output into log_buf. If the caller didn't provide
+	 * the appropriate log prefix, we insert them here
 	 */
-	for ( ; *p; p++) {
+	for (; *p; p++) {
 		if (new_text_line) {
-			/* Always output the token */
-			emit_log_char('<');
-			emit_log_char(current_log_level + '0');
-			emit_log_char('>');
-			printed_len += 3;
 			new_text_line = 0;
 
+			if (plen) {
+				/* Copy original log prefix */
+				int i;
+
+				for (i = 0; i < plen; i++)
+					emit_log_char(printk_buf[i]);
+				printed_len += plen;
+			} else {
+				/* Add log prefix */
+				emit_log_char('<');
+				emit_log_char(current_log_level + '0');
+				emit_log_char('>');
+				printed_len += 3;
+			}
+
 			if (printk_time) {
-				/* Follow the token with the time */
+				/* Add the current time stamp */
 				char tbuf[50], *tp;
 				unsigned tlen;
 				unsigned long long t;
@@ -1160,6 +1237,11 @@ void console_unlock(void)
 		local_irq_restore(flags);
 	}
 	console_locked = 0;
+
+	/* Release the exclusive_console once it is used */
+	if (unlikely(exclusive_console))
+		exclusive_console = NULL;
+
 	up(&console_sem);
 	spin_unlock_irqrestore(&logbuf_lock, flags);
 	if (wake_klogd)
@@ -1246,6 +1328,18 @@ void console_start(struct console *console)
 }
 EXPORT_SYMBOL(console_start);
 
+static int __read_mostly keep_bootcon;
+
+static int __init keep_bootcon_setup(char *str)
+{
+	keep_bootcon = 1;
+	printk(KERN_INFO "debug: skip boot console de-registration.\n");
+
+	return 0;
+}
+
+early_param("keep_bootcon", keep_bootcon_setup);
+
 /*
  * The console driver calls this routine during kernel initialization
  * to register the console printing procedure with printk() and to
@@ -1382,6 +1476,12 @@ void register_console(struct console *newcon)
 		spin_lock_irqsave(&logbuf_lock, flags);
 		con_start = log_start;
 		spin_unlock_irqrestore(&logbuf_lock, flags);
+		/*
+		 * We're about to replay the log buffer.  Only do this to the
+		 * just-registered console to avoid excessive message spam to
+		 * the already-registered consoles.
+		 */
+		exclusive_console = newcon;
 	}
 	console_unlock();
 	console_sysfs_notify();
@@ -1393,7 +1493,9 @@ void register_console(struct console *newcon)
 	 * users know there might be something in the kernel's log buffer that
 	 * went to the bootconsole (that they do not see on the real console)
 	 */
-	if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) {
+	if (bcon &&
+	    ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+	    !keep_bootcon) {
 		/* we need to iterate through twice, to make sure we print
 		 * everything out, before we unregister the console(s)
 		 */
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index a23a57a..f3240e9 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -214,11 +214,12 @@ static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)
 		 * Ensure that queued callbacks are all executed.
 		 * If we detect that we are nested in a RCU read-side critical
 		 * section, we should simply fail, otherwise we would deadlock.
+		 * Note that the machinery to reliably determine whether
+		 * or not we are in an RCU read-side critical section
+		 * exists only in the preemptible RCU implementations
+		 * (TINY_PREEMPT_RCU and TREE_PREEMPT_RCU), which is why
+		 * DEBUG_OBJECTS_RCU_HEAD is disallowed if !PREEMPT.
 		 */
-#ifndef CONFIG_PREEMPT
-		WARN_ON(1);
-		return 0;
-#else
 		if (rcu_preempt_depth() != 0 || preempt_count() != 0 ||
 		    irqs_disabled()) {
 			WARN_ON(1);
@@ -229,7 +230,6 @@ static int rcuhead_fixup_free(void *addr, enum debug_obj_state state)
 		rcu_barrier_bh();
 		debug_object_free(head, &rcuhead_debug_descr);
 		return 1;
-#endif
 	default:
 		return 0;
 	}
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 015abae..3cb8e36 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -852,7 +852,7 @@ void exit_rcu(void)
 	if (t->rcu_read_lock_nesting == 0)
 		return;
 	t->rcu_read_lock_nesting = 1;
-	rcu_read_unlock();
+	__rcu_read_unlock();
 }
 
 #else /* #ifdef CONFIG_TINY_PREEMPT_RCU */
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 89613f9..c224da4 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -47,7 +47,6 @@
 #include <linux/srcu.h>
 #include <linux/slab.h>
 #include <asm/byteorder.h>
-#include <linux/sched.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
index ddabb54..3c7cbc2 100644
--- a/kernel/rtmutex-debug.c
+++ b/kernel/rtmutex-debug.c
@@ -215,7 +215,6 @@ void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
 	put_pid(waiter->deadlock_task_pid);
 	TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry));
 	TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
-	TRACE_WARN_ON(waiter->task);
 	memset(waiter, 0x22, sizeof(*waiter));
 }
 
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 66cb89b..5c9ccd3 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -9,7 +9,6 @@
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
 #include <linux/timer.h>
@@ -27,7 +26,6 @@ struct test_thread_data {
 	int			opcode;
 	int			opdata;
 	int			mutexes[MAX_RT_TEST_MUTEXES];
-	int			bkl;
 	int			event;
 	struct sys_device	sysdev;
 };
@@ -46,9 +44,8 @@ enum test_opcodes {
 	RTTEST_LOCKINTNOWAIT,	/* 6 Lock interruptible no wait in wakeup, data = lockindex */
 	RTTEST_LOCKCONT,	/* 7 Continue locking after the wakeup delay */
 	RTTEST_UNLOCK,		/* 8 Unlock, data = lockindex */
-	RTTEST_LOCKBKL,		/* 9 Lock BKL */
-	RTTEST_UNLOCKBKL,	/* 10 Unlock BKL */
-	RTTEST_SIGNAL,		/* 11 Signal other test thread, data = thread id */
+	/* 9, 10 - reserved for BKL commemoration */
+	RTTEST_SIGNAL = 11,	/* 11 Signal other test thread, data = thread id */
 	RTTEST_RESETEVENT = 98,	/* 98 Reset event counter */
 	RTTEST_RESET = 99,	/* 99 Reset all pending operations */
 };
@@ -74,13 +71,6 @@ static int handle_op(struct test_thread_data *td, int lockwakeup)
 				td->mutexes[i] = 0;
 			}
 		}
-
-		if (!lockwakeup && td->bkl == 4) {
-#ifdef CONFIG_LOCK_KERNEL
-			unlock_kernel();
-#endif
-			td->bkl = 0;
-		}
 		return 0;
 
 	case RTTEST_RESETEVENT:
@@ -131,25 +121,6 @@ static int handle_op(struct test_thread_data *td, int lockwakeup)
 		td->mutexes[id] = 0;
 		return 0;
 
-	case RTTEST_LOCKBKL:
-		if (td->bkl)
-			return 0;
-		td->bkl = 1;
-#ifdef CONFIG_LOCK_KERNEL
-		lock_kernel();
-#endif
-		td->bkl = 4;
-		return 0;
-
-	case RTTEST_UNLOCKBKL:
-		if (td->bkl != 4)
-			break;
-#ifdef CONFIG_LOCK_KERNEL
-		unlock_kernel();
-#endif
-		td->bkl = 0;
-		return 0;
-
 	default:
 		break;
 	}
@@ -196,7 +167,6 @@ void schedule_rt_mutex_test(struct rt_mutex *mutex)
 		td->event = atomic_add_return(1, &rttest_event);
 		break;
 
-	case RTTEST_LOCKBKL:
 	default:
 		break;
 	}
@@ -229,8 +199,6 @@ void schedule_rt_mutex_test(struct rt_mutex *mutex)
 		td->event = atomic_add_return(1, &rttest_event);
 		return;
 
-	case RTTEST_LOCKBKL:
-		return;
 	default:
 		return;
 	}
@@ -380,11 +348,11 @@ static ssize_t sysfs_test_status(struct sys_device *dev, struct sysdev_attribute
 	spin_lock(&rttest_lock);
 
 	curr += sprintf(curr,
-		"O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, K: %d, M:",
+		"O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, M:",
 		td->opcode, td->event, tsk->state,
 			(MAX_RT_PRIO - 1) - tsk->prio,
 			(MAX_RT_PRIO - 1) - tsk->normal_prio,
-		tsk->pi_blocked_on, td->bkl);
+		tsk->pi_blocked_on);
 
 	for (i = MAX_RT_TEST_MUTEXES - 1; i >=0 ; i--)
 		curr += sprintf(curr, "%d", td->mutexes[i]);
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
index a960481..ab44911 100644
--- a/kernel/rtmutex.c
+++ b/kernel/rtmutex.c
@@ -20,41 +20,34 @@
 /*
  * lock->owner state tracking:
  *
- * lock->owner holds the task_struct pointer of the owner. Bit 0 and 1
- * are used to keep track of the "owner is pending" and "lock has
- * waiters" state.
+ * lock->owner holds the task_struct pointer of the owner. Bit 0
+ * is used to keep track of the "lock has waiters" state.
  *
- * owner	bit1	bit0
- * NULL		0	0	lock is free (fast acquire possible)
- * NULL		0	1	invalid state
- * NULL		1	0	Transitional State*
- * NULL		1	1	invalid state
- * taskpointer	0	0	lock is held (fast release possible)
- * taskpointer	0	1	task is pending owner
- * taskpointer	1	0	lock is held and has waiters
- * taskpointer	1	1	task is pending owner and lock has more waiters
- *
- * Pending ownership is assigned to the top (highest priority)
- * waiter of the lock, when the lock is released. The thread is woken
- * up and can now take the lock. Until the lock is taken (bit 0
- * cleared) a competing higher priority thread can steal the lock
- * which puts the woken up thread back on the waiters list.
+ * owner	bit0
+ * NULL		0	lock is free (fast acquire possible)
+ * NULL		1	lock is free and has waiters and the top waiter
+ *				is going to take the lock*
+ * taskpointer	0	lock is held (fast release possible)
+ * taskpointer	1	lock is held and has waiters**
  *
  * The fast atomic compare exchange based acquire and release is only
- * possible when bit 0 and 1 of lock->owner are 0.
+ * possible when bit 0 of lock->owner is 0.
+ *
+ * (*) It also can be a transitional state when grabbing the lock
+ * with ->wait_lock is held. To prevent any fast path cmpxchg to the lock,
+ * we need to set the bit0 before looking at the lock, and the owner may be
+ * NULL in this small time, hence this can be a transitional state.
  *
- * (*) There's a small time where the owner can be NULL and the
- * "lock has waiters" bit is set.  This can happen when grabbing the lock.
- * To prevent a cmpxchg of the owner releasing the lock, we need to set this
- * bit before looking at the lock, hence the reason this is a transitional
- * state.
+ * (**) There is a small time when bit 0 is set but there are no
+ * waiters. This can happen when grabbing the lock in the slow path.
+ * To prevent a cmpxchg of the owner releasing the lock, we need to
+ * set this bit before looking at the lock.
  */
 
 static void
-rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
-		   unsigned long mask)
+rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner)
 {
-	unsigned long val = (unsigned long)owner | mask;
+	unsigned long val = (unsigned long)owner;
 
 	if (rt_mutex_has_waiters(lock))
 		val |= RT_MUTEX_HAS_WAITERS;
@@ -203,15 +196,14 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
 	 * reached or the state of the chain has changed while we
 	 * dropped the locks.
 	 */
-	if (!waiter || !waiter->task)
+	if (!waiter)
 		goto out_unlock_pi;
 
 	/*
 	 * Check the orig_waiter state. After we dropped the locks,
-	 * the previous owner of the lock might have released the lock
-	 * and made us the pending owner:
+	 * the previous owner of the lock might have released the lock.
 	 */
-	if (orig_waiter && !orig_waiter->task)
+	if (orig_waiter && !rt_mutex_owner(orig_lock))
 		goto out_unlock_pi;
 
 	/*
@@ -254,6 +246,17 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
 
 	/* Release the task */
 	raw_spin_unlock_irqrestore(&task->pi_lock, flags);
+	if (!rt_mutex_owner(lock)) {
+		/*
+		 * If the requeue above changed the top waiter, then we need
+		 * to wake the new top waiter up to try to get the lock.
+		 */
+
+		if (top_waiter != rt_mutex_top_waiter(lock))
+			wake_up_process(rt_mutex_top_waiter(lock)->task);
+		raw_spin_unlock(&lock->wait_lock);
+		goto out_put_task;
+	}
 	put_task_struct(task);
 
 	/* Grab the next task */
@@ -296,78 +299,16 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
 }
 
 /*
- * Optimization: check if we can steal the lock from the
- * assigned pending owner [which might not have taken the
- * lock yet]:
- */
-static inline int try_to_steal_lock(struct rt_mutex *lock,
-				    struct task_struct *task)
-{
-	struct task_struct *pendowner = rt_mutex_owner(lock);
-	struct rt_mutex_waiter *next;
-	unsigned long flags;
-
-	if (!rt_mutex_owner_pending(lock))
-		return 0;
-
-	if (pendowner == task)
-		return 1;
-
-	raw_spin_lock_irqsave(&pendowner->pi_lock, flags);
-	if (task->prio >= pendowner->prio) {
-		raw_spin_unlock_irqrestore(&pendowner->pi_lock, flags);
-		return 0;
-	}
-
-	/*
-	 * Check if a waiter is enqueued on the pending owners
-	 * pi_waiters list. Remove it and readjust pending owners
-	 * priority.
-	 */
-	if (likely(!rt_mutex_has_waiters(lock))) {
-		raw_spin_unlock_irqrestore(&pendowner->pi_lock, flags);
-		return 1;
-	}
-
-	/* No chain handling, pending owner is not blocked on anything: */
-	next = rt_mutex_top_waiter(lock);
-	plist_del(&next->pi_list_entry, &pendowner->pi_waiters);
-	__rt_mutex_adjust_prio(pendowner);
-	raw_spin_unlock_irqrestore(&pendowner->pi_lock, flags);
-
-	/*
-	 * We are going to steal the lock and a waiter was
-	 * enqueued on the pending owners pi_waiters queue. So
-	 * we have to enqueue this waiter into
-	 * task->pi_waiters list. This covers the case,
-	 * where task is boosted because it holds another
-	 * lock and gets unboosted because the booster is
-	 * interrupted, so we would delay a waiter with higher
-	 * priority as task->normal_prio.
-	 *
-	 * Note: in the rare case of a SCHED_OTHER task changing
-	 * its priority and thus stealing the lock, next->task
-	 * might be task:
-	 */
-	if (likely(next->task != task)) {
-		raw_spin_lock_irqsave(&task->pi_lock, flags);
-		plist_add(&next->pi_list_entry, &task->pi_waiters);
-		__rt_mutex_adjust_prio(task);
-		raw_spin_unlock_irqrestore(&task->pi_lock, flags);
-	}
-	return 1;
-}
-
-/*
  * Try to take an rt-mutex
  *
- * This fails
- * - when the lock has a real owner
- * - when a different pending owner exists and has higher priority than current
- *
  * Must be called with lock->wait_lock held.
+ *
+ * @lock:   the lock to be acquired.
+ * @task:   the task which wants to acquire the lock
+ * @waiter: the waiter that is queued to the lock's wait list. (could be NULL)
  */
-static int try_to_take_rt_mutex(struct rt_mutex *lock)
+static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
+		struct rt_mutex_waiter *waiter)
 {
 	/*
 	 * We have to be careful here if the atomic speedups are
@@ -390,15 +331,52 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock)
 	 */
 	mark_rt_mutex_waiters(lock);
 
-	if (rt_mutex_owner(lock) && !try_to_steal_lock(lock, current))
+	if (rt_mutex_owner(lock))
 		return 0;
 
+	/*
+	 * It will get the lock because of one of these conditions:
+	 * 1) there is no waiter
+	 * 2) higher priority than waiters
+	 * 3) it is top waiter
+	 */
+	if (rt_mutex_has_waiters(lock)) {
+		if (task->prio >= rt_mutex_top_waiter(lock)->list_entry.prio) {
+			if (!waiter || waiter != rt_mutex_top_waiter(lock))
+				return 0;
+		}
+	}
+
+	if (waiter || rt_mutex_has_waiters(lock)) {
+		unsigned long flags;
+		struct rt_mutex_waiter *top;
+
+		raw_spin_lock_irqsave(&task->pi_lock, flags);
+
+		/* remove the queued waiter. */
+		if (waiter) {
+			plist_del(&waiter->list_entry, &lock->wait_list);
+			task->pi_blocked_on = NULL;
+		}
+
+		/*
+		 * We have to enqueue the top waiter(if it exists) into
+		 * task->pi_waiters list.
+		 */
+		if (rt_mutex_has_waiters(lock)) {
+			top = rt_mutex_top_waiter(lock);
+			top->pi_list_entry.prio = top->list_entry.prio;
+			plist_add(&top->pi_list_entry, &task->pi_waiters);
+		}
+		raw_spin_unlock_irqrestore(&task->pi_lock, flags);
+	}
+
 	/* We got the lock. */
 	debug_rt_mutex_lock(lock);
 
-	rt_mutex_set_owner(lock, current, 0);
+	rt_mutex_set_owner(lock, task);
 
-	rt_mutex_deadlock_account_lock(lock, current);
+	rt_mutex_deadlock_account_lock(lock, task);
 
 	return 1;
 }
@@ -436,6 +414,9 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
 
 	raw_spin_unlock_irqrestore(&task->pi_lock, flags);
 
+	if (!owner)
+		return 0;
+
 	if (waiter == rt_mutex_top_waiter(lock)) {
 		raw_spin_lock_irqsave(&owner->pi_lock, flags);
 		plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
@@ -472,21 +453,18 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
 /*
  * Wake up the next waiter on the lock.
  *
- * Remove the top waiter from the current tasks waiter list and from
- * the lock waiter list. Set it as pending owner. Then wake it up.
+ * Remove the top waiter from the current tasks waiter list and wake it up.
  *
  * Called with lock->wait_lock held.
  */
 static void wakeup_next_waiter(struct rt_mutex *lock)
 {
 	struct rt_mutex_waiter *waiter;
-	struct task_struct *pendowner;
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&current->pi_lock, flags);
 
 	waiter = rt_mutex_top_waiter(lock);
-	plist_del(&waiter->list_entry, &lock->wait_list);
 
 	/*
 	 * Remove it from current->pi_waiters. We do not adjust a
@@ -495,43 +473,19 @@ static void wakeup_next_waiter(struct rt_mutex *lock)
 	 * lock->wait_lock.
 	 */
 	plist_del(&waiter->pi_list_entry, &current->pi_waiters);
-	pendowner = waiter->task;
-	waiter->task = NULL;
 
-	rt_mutex_set_owner(lock, pendowner, RT_MUTEX_OWNER_PENDING);
+	rt_mutex_set_owner(lock, NULL);
 
 	raw_spin_unlock_irqrestore(&current->pi_lock, flags);
 
-	/*
-	 * Clear the pi_blocked_on variable and enqueue a possible
-	 * waiter into the pi_waiters list of the pending owner. This
-	 * prevents that in case the pending owner gets unboosted a
-	 * waiter with higher priority than pending-owner->normal_prio
-	 * is blocked on the unboosted (pending) owner.
-	 */
-	raw_spin_lock_irqsave(&pendowner->pi_lock, flags);
-
-	WARN_ON(!pendowner->pi_blocked_on);
-	WARN_ON(pendowner->pi_blocked_on != waiter);
-	WARN_ON(pendowner->pi_blocked_on->lock != lock);
-
-	pendowner->pi_blocked_on = NULL;
-
-	if (rt_mutex_has_waiters(lock)) {
-		struct rt_mutex_waiter *next;
-
-		next = rt_mutex_top_waiter(lock);
-		plist_add(&next->pi_list_entry, &pendowner->pi_waiters);
-	}
-	raw_spin_unlock_irqrestore(&pendowner->pi_lock, flags);
-
-	wake_up_process(pendowner);
+	wake_up_process(waiter->task);
 }
 
 /*
- * Remove a waiter from a lock
+ * Remove a waiter from a lock and give up
  *
- * Must be called with lock->wait_lock held
+ * Must be called with lock->wait_lock held and
+ * have just failed to try_to_take_rt_mutex().
  */
 static void remove_waiter(struct rt_mutex *lock,
 			  struct rt_mutex_waiter *waiter)
@@ -543,11 +497,13 @@ static void remove_waiter(struct rt_mutex *lock,
 
 	raw_spin_lock_irqsave(&current->pi_lock, flags);
 	plist_del(&waiter->list_entry, &lock->wait_list);
-	waiter->task = NULL;
 	current->pi_blocked_on = NULL;
 	raw_spin_unlock_irqrestore(&current->pi_lock, flags);
 
-	if (first && owner != current) {
+	if (!owner)
+		return;
+
+	if (first) {
 
 		raw_spin_lock_irqsave(&owner->pi_lock, flags);
 
@@ -614,21 +570,19 @@ void rt_mutex_adjust_pi(struct task_struct *task)
  * 			 or TASK_UNINTERRUPTIBLE)
  * @timeout:		 the pre-initialized and started timer, or NULL for none
  * @waiter:		 the pre-initialized rt_mutex_waiter
- * @detect_deadlock:	 passed to task_blocks_on_rt_mutex
  *
  * lock->wait_lock must be held by the caller.
  */
 static int __sched
 __rt_mutex_slowlock(struct rt_mutex *lock, int state,
 		    struct hrtimer_sleeper *timeout,
-		    struct rt_mutex_waiter *waiter,
-		    int detect_deadlock)
+		    struct rt_mutex_waiter *waiter)
 {
 	int ret = 0;
 
 	for (;;) {
 		/* Try to acquire the lock: */
-		if (try_to_take_rt_mutex(lock))
+		if (try_to_take_rt_mutex(lock, current, waiter))
 			break;
 
 		/*
@@ -645,39 +599,11 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state,
 				break;
 		}
 
-		/*
-		 * waiter->task is NULL the first time we come here and
-		 * when we have been woken up by the previous owner
-		 * but the lock got stolen by a higher prio task.
-		 */
-		if (!waiter->task) {
-			ret = task_blocks_on_rt_mutex(lock, waiter, current,
-						      detect_deadlock);
-			/*
-			 * If we got woken up by the owner then start loop
-			 * all over without going into schedule to try
-			 * to get the lock now:
-			 */
-			if (unlikely(!waiter->task)) {
-				/*
-				 * Reset the return value. We might
-				 * have returned with -EDEADLK and the
-				 * owner released the lock while we
-				 * were walking the pi chain.
-				 */
-				ret = 0;
-				continue;
-			}
-			if (unlikely(ret))
-				break;
-		}
-
 		raw_spin_unlock(&lock->wait_lock);
 
 		debug_rt_mutex_print_deadlock(waiter);
 
-		if (waiter->task)
-			schedule_rt_mutex(lock);
+		schedule_rt_mutex(lock);
 
 		raw_spin_lock(&lock->wait_lock);
 		set_current_state(state);
@@ -698,12 +624,11 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
 	int ret = 0;
 
 	debug_rt_mutex_init_waiter(&waiter);
-	waiter.task = NULL;
 
 	raw_spin_lock(&lock->wait_lock);
 
 	/* Try to acquire the lock again: */
-	if (try_to_take_rt_mutex(lock)) {
+	if (try_to_take_rt_mutex(lock, current, NULL)) {
 		raw_spin_unlock(&lock->wait_lock);
 		return 0;
 	}
@@ -717,12 +642,14 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
 			timeout->task = NULL;
 	}
 
-	ret = __rt_mutex_slowlock(lock, state, timeout, &waiter,
-				  detect_deadlock);
+	ret = task_blocks_on_rt_mutex(lock, &waiter, current, detect_deadlock);
+
+	if (likely(!ret))
+		ret = __rt_mutex_slowlock(lock, state, timeout, &waiter);
 
 	set_current_state(TASK_RUNNING);
 
-	if (unlikely(waiter.task))
+	if (unlikely(ret))
 		remove_waiter(lock, &waiter);
 
 	/*
@@ -737,14 +664,6 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
 	if (unlikely(timeout))
 		hrtimer_cancel(&timeout->timer);
 
-	/*
-	 * Readjust priority, when we did not get the lock. We might
-	 * have been the pending owner and boosted. Since we did not
-	 * take the lock, the PI boost has to go.
-	 */
-	if (unlikely(ret))
-		rt_mutex_adjust_prio(current);
-
 	debug_rt_mutex_free_waiter(&waiter);
 
 	return ret;
@@ -762,7 +681,7 @@ rt_mutex_slowtrylock(struct rt_mutex *lock)
 
 	if (likely(rt_mutex_owner(lock) != current)) {
 
-		ret = try_to_take_rt_mutex(lock);
+		ret = try_to_take_rt_mutex(lock, current, NULL);
 		/*
 		 * try_to_take_rt_mutex() sets the lock waiters
 		 * bit unconditionally. Clean this up.
@@ -992,7 +911,7 @@ void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
 {
 	__rt_mutex_init(lock, NULL);
 	debug_rt_mutex_proxy_lock(lock, proxy_owner);
-	rt_mutex_set_owner(lock, proxy_owner, 0);
+	rt_mutex_set_owner(lock, proxy_owner);
 	rt_mutex_deadlock_account_lock(lock, proxy_owner);
 }
 
@@ -1008,7 +927,7 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock,
 			   struct task_struct *proxy_owner)
 {
 	debug_rt_mutex_proxy_unlock(lock);
-	rt_mutex_set_owner(lock, NULL, 0);
+	rt_mutex_set_owner(lock, NULL);
 	rt_mutex_deadlock_account_unlock(proxy_owner);
 }
 
@@ -1034,20 +953,14 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 
 	raw_spin_lock(&lock->wait_lock);
 
-	mark_rt_mutex_waiters(lock);
-
-	if (!rt_mutex_owner(lock) || try_to_steal_lock(lock, task)) {
-		/* We got the lock for task. */
-		debug_rt_mutex_lock(lock);
-		rt_mutex_set_owner(lock, task, 0);
+	if (try_to_take_rt_mutex(lock, task, NULL)) {
 		raw_spin_unlock(&lock->wait_lock);
-		rt_mutex_deadlock_account_lock(lock, task);
 		return 1;
 	}
 
 	ret = task_blocks_on_rt_mutex(lock, waiter, task, detect_deadlock);
 
-	if (ret && !waiter->task) {
+	if (ret && !rt_mutex_owner(lock)) {
 		/*
 		 * Reset the return value. We might have
 		 * returned with -EDEADLK and the owner
@@ -1056,6 +969,10 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 		 */
 		ret = 0;
 	}
+
+	if (unlikely(ret))
+		remove_waiter(lock, waiter);
+
 	raw_spin_unlock(&lock->wait_lock);
 
 	debug_rt_mutex_print_deadlock(waiter);
@@ -1110,12 +1027,11 @@ int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
 
 	set_current_state(TASK_INTERRUPTIBLE);
 
-	ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter,
-				  detect_deadlock);
+	ret = __rt_mutex_slowlock(lock, TASK_INTERRUPTIBLE, to, waiter);
 
 	set_current_state(TASK_RUNNING);
 
-	if (unlikely(waiter->task))
+	if (unlikely(ret))
 		remove_waiter(lock, waiter);
 
 	/*
@@ -1126,13 +1042,5 @@ int rt_mutex_finish_proxy_lock(struct rt_mutex *lock,
 
 	raw_spin_unlock(&lock->wait_lock);
 
-	/*
-	 * Readjust priority, when we did not get the lock. We might have been
-	 * the pending owner and boosted. Since we did not take the lock, the
-	 * PI boost has to go.
-	 */
-	if (unlikely(ret))
-		rt_mutex_adjust_prio(current);
-
 	return ret;
 }
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
index 97a2f81..53a66c8 100644
--- a/kernel/rtmutex_common.h
+++ b/kernel/rtmutex_common.h
@@ -91,9 +91,8 @@ task_top_pi_waiter(struct task_struct *p)
 /*
  * lock->owner state tracking:
  */
-#define RT_MUTEX_OWNER_PENDING	1UL
-#define RT_MUTEX_HAS_WAITERS	2UL
-#define RT_MUTEX_OWNER_MASKALL	3UL
+#define RT_MUTEX_HAS_WAITERS	1UL
+#define RT_MUTEX_OWNER_MASKALL	1UL
 
 static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
 {
@@ -101,17 +100,6 @@ static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
 		((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
 }
 
-static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock)
-{
-	return (struct task_struct *)
-		((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
-}
-
-static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock)
-{
-	return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING;
-}
-
 /*
  * PI-futex support (proxy locking functions, etc.):
  */
diff --git a/kernel/sched.c b/kernel/sched.c
index 42eab5a..a172494 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -32,7 +32,6 @@
 #include <linux/init.h>
 #include <linux/uaccess.h>
 #include <linux/highmem.h>
-#include <linux/smp_lock.h>
 #include <asm/mmu_context.h>
 #include <linux/interrupt.h>
 #include <linux/capability.h>
@@ -324,7 +323,7 @@ struct cfs_rq {
 	 * 'curr' points to currently running entity on this cfs_rq.
 	 * It is set to NULL otherwise (i.e when none are currently running).
 	 */
-	struct sched_entity *curr, *next, *last;
+	struct sched_entity *curr, *next, *last, *skip;
 
 	unsigned int nr_spread_over;
 
@@ -606,9 +605,6 @@ static inline struct task_group *task_group(struct task_struct *p)
 	struct task_group *tg;
 	struct cgroup_subsys_state *css;
 
-	if (p->flags & PF_EXITING)
-		return &root_task_group;
-
 	css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
 			lockdep_is_held(&task_rq(p)->lock));
 	tg = container_of(css, struct task_group, css);
@@ -664,10 +660,9 @@ static void update_rq_clock(struct rq *rq)
 #endif
 
 /**
- * runqueue_is_locked
+ * runqueue_is_locked - Returns true if the current cpu runqueue is locked
  * @cpu: the processor in question.
  *
- * Returns true if the current cpu runqueue is locked.
  * This interface allows printk to be called with the runqueue lock
  * held and know whether or not it is OK to wake up the klogd.
  */
@@ -1686,6 +1681,39 @@ static void double_rq_unlock(struct rq *rq1, struct rq *rq2)
 		__release(rq2->lock);
 }
 
+#else /* CONFIG_SMP */
+
+/*
+ * double_rq_lock - safely lock two runqueues
+ *
+ * Note this does not disable interrupts like task_rq_lock,
+ * you need to do so manually before calling.
+ */
+static void double_rq_lock(struct rq *rq1, struct rq *rq2)
+	__acquires(rq1->lock)
+	__acquires(rq2->lock)
+{
+	BUG_ON(!irqs_disabled());
+	BUG_ON(rq1 != rq2);
+	raw_spin_lock(&rq1->lock);
+	__acquire(rq2->lock);	/* Fake it out ;) */
+}
+
+/*
+ * double_rq_unlock - safely unlock two runqueues
+ *
+ * Note this does not restore interrupts like task_rq_unlock,
+ * you need to do so manually after calling.
+ */
+static void double_rq_unlock(struct rq *rq1, struct rq *rq2)
+	__releases(rq1->lock)
+	__releases(rq2->lock)
+{
+	BUG_ON(rq1 != rq2);
+	raw_spin_unlock(&rq1->lock);
+	__release(rq2->lock);
+}
+
 #endif
 
 static void calc_load_account_idle(struct rq *this_rq);
@@ -1880,7 +1908,7 @@ void account_system_vtime(struct task_struct *curr)
 	 */
 	if (hardirq_count())
 		__this_cpu_add(cpu_hardirq_time, delta);
-	else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
+	else if (in_serving_softirq() && curr != this_cpu_ksoftirqd())
 		__this_cpu_add(cpu_softirq_time, delta);
 
 	irq_time_write_end();
@@ -1920,8 +1948,40 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
 		sched_rt_avg_update(rq, irq_delta);
 }
 
+static int irqtime_account_hi_update(void)
+{
+	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+	unsigned long flags;
+	u64 latest_ns;
+	int ret = 0;
+
+	local_irq_save(flags);
+	latest_ns = this_cpu_read(cpu_hardirq_time);
+	if (cputime64_gt(nsecs_to_cputime64(latest_ns), cpustat->irq))
+		ret = 1;
+	local_irq_restore(flags);
+	return ret;
+}
+
+static int irqtime_account_si_update(void)
+{
+	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+	unsigned long flags;
+	u64 latest_ns;
+	int ret = 0;
+
+	local_irq_save(flags);
+	latest_ns = this_cpu_read(cpu_softirq_time);
+	if (cputime64_gt(nsecs_to_cputime64(latest_ns), cpustat->softirq))
+		ret = 1;
+	local_irq_restore(flags);
+	return ret;
+}
+
 #else /* CONFIG_IRQ_TIME_ACCOUNTING */
 
+#define sched_clock_irqtime	(0)
+
 static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
 	rq->clock_task += delta;
@@ -2025,14 +2085,14 @@ inline int task_curr(const struct task_struct *p)
 
 static inline void check_class_changed(struct rq *rq, struct task_struct *p,
 				       const struct sched_class *prev_class,
-				       int oldprio, int running)
+				       int oldprio)
 {
 	if (prev_class != p->sched_class) {
 		if (prev_class->switched_from)
-			prev_class->switched_from(rq, p, running);
-		p->sched_class->switched_to(rq, p, running);
-	} else
-		p->sched_class->prio_changed(rq, p, oldprio, running);
+			prev_class->switched_from(rq, p);
+		p->sched_class->switched_to(rq, p);
+	} else if (oldprio != p->prio)
+		p->sched_class->prio_changed(rq, p, oldprio);
 }
 
 static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
@@ -2224,7 +2284,10 @@ unsigned long wait_task_inactive(struct task_struct *p, long match_state)
 		 * yield - it could be a while.
 		 */
 		if (unlikely(on_rq)) {
-			schedule_timeout_uninterruptible(1);
+			ktime_t to = ktime_set(0, NSEC_PER_SEC/HZ);
+
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_hrtimeout(&to, HRTIMER_MODE_REL);
 			continue;
 		}
 
@@ -2265,27 +2328,6 @@ void kick_process(struct task_struct *p)
 EXPORT_SYMBOL_GPL(kick_process);
 #endif /* CONFIG_SMP */
 
-/**
- * task_oncpu_function_call - call a function on the cpu on which a task runs
- * @p:		the task to evaluate
- * @func:	the function to be called
- * @info:	the function call argument
- *
- * Calls the function @func when the task is currently running. This might
- * be on the current CPU, which just calls the function directly
- */
-void task_oncpu_function_call(struct task_struct *p,
-			      void (*func) (void *info), void *info)
-{
-	int cpu;
-
-	preempt_disable();
-	cpu = task_cpu(p);
-	if (task_curr(p))
-		smp_call_function_single(cpu, func, info, 1);
-	preempt_enable();
-}
-
 #ifdef CONFIG_SMP
 /*
  * ->cpus_allowed is protected by either TASK_WAKING or rq->lock held.
@@ -2566,6 +2608,7 @@ static void __sched_fork(struct task_struct *p)
 	p->se.sum_exec_runtime		= 0;
 	p->se.prev_sum_exec_runtime	= 0;
 	p->se.nr_migrations		= 0;
+	p->se.vruntime			= 0;
 
 #ifdef CONFIG_SCHEDSTATS
 	memset(&p->se.statistics, 0, sizeof(p->se.statistics));
@@ -2776,9 +2819,12 @@ static inline void
 prepare_task_switch(struct rq *rq, struct task_struct *prev,
 		    struct task_struct *next)
 {
+	sched_info_switch(prev, next);
+	perf_event_task_sched_out(prev, next);
 	fire_sched_out_preempt_notifiers(prev, next);
 	prepare_lock_switch(rq, next);
 	prepare_arch_switch(next);
+	trace_sched_switch(prev, next);
 }
 
 /**
@@ -2911,7 +2957,7 @@ context_switch(struct rq *rq, struct task_struct *prev,
 	struct mm_struct *mm, *oldmm;
 
 	prepare_task_switch(rq, prev, next);
-	trace_sched_switch(prev, next);
+
 	mm = next->mm;
 	oldmm = prev->active_mm;
 	/*
@@ -3568,6 +3614,32 @@ static void account_guest_time(struct task_struct *p, cputime_t cputime,
 }
 
 /*
+ * Account system cpu time to a process and desired cpustat field
+ * @p: the process that the cpu time gets accounted to
+ * @cputime: the cpu time spent in kernel space since the last update
+ * @cputime_scaled: cputime scaled by cpu frequency
+ * @target_cputime64: pointer to cpustat field that has to be updated
+ */
+static inline
+void __account_system_time(struct task_struct *p, cputime_t cputime,
+			cputime_t cputime_scaled, cputime64_t *target_cputime64)
+{
+	cputime64_t tmp = cputime_to_cputime64(cputime);
+
+	/* Add system time to process. */
+	p->stime = cputime_add(p->stime, cputime);
+	p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
+	account_group_system_time(p, cputime);
+
+	/* Add system time to cpustat. */
+	*target_cputime64 = cputime64_add(*target_cputime64, tmp);
+	cpuacct_update_stats(p, CPUACCT_STAT_SYSTEM, cputime);
+
+	/* Account for system time used */
+	acct_update_integrals(p);
+}
+
+/*
  * Account system cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @hardirq_offset: the offset to subtract from hardirq_count()
@@ -3578,36 +3650,26 @@ void account_system_time(struct task_struct *p, int hardirq_offset,
 			 cputime_t cputime, cputime_t cputime_scaled)
 {
 	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
-	cputime64_t tmp;
+	cputime64_t *target_cputime64;
 
 	if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) {
 		account_guest_time(p, cputime, cputime_scaled);
 		return;
 	}
 
-	/* Add system time to process. */
-	p->stime = cputime_add(p->stime, cputime);
-	p->stimescaled = cputime_add(p->stimescaled, cputime_scaled);
-	account_group_system_time(p, cputime);
-
-	/* Add system time to cpustat. */
-	tmp = cputime_to_cputime64(cputime);
 	if (hardirq_count() - hardirq_offset)
-		cpustat->irq = cputime64_add(cpustat->irq, tmp);
+		target_cputime64 = &cpustat->irq;
 	else if (in_serving_softirq())
-		cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
+		target_cputime64 = &cpustat->softirq;
 	else
-		cpustat->system = cputime64_add(cpustat->system, tmp);
-
-	cpuacct_update_stats(p, CPUACCT_STAT_SYSTEM, cputime);
+		target_cputime64 = &cpustat->system;
 
-	/* Account for system time used */
-	acct_update_integrals(p);
+	__account_system_time(p, cputime, cputime_scaled, target_cputime64);
 }
 
 /*
  * Account for involuntary wait time.
- * @steal: the cpu time spent in involuntary wait
+ * @cputime: the cpu time spent in involuntary wait
  */
 void account_steal_time(cputime_t cputime)
 {
@@ -3635,6 +3697,73 @@ void account_idle_time(cputime_t cputime)
 
 #ifndef CONFIG_VIRT_CPU_ACCOUNTING
 
+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
+/*
+ * Account a tick to a process and cpustat
+ * @p: the process that the cpu time gets accounted to
+ * @user_tick: is the tick from userspace
+ * @rq: the pointer to rq
+ *
+ * Tick demultiplexing follows the order
+ * - pending hardirq update
+ * - pending softirq update
+ * - user_time
+ * - idle_time
+ * - system time
+ *   - check for guest_time
+ *   - else account as system_time
+ *
+ * Check for hardirq is done both for system and user time as there is
+ * no timer going off while we are on hardirq and hence we may never get an
+ * opportunity to update it solely in system time.
+ * p->stime and friends are only updated on system time and not on irq
+ * softirq as those do not count in task exec_runtime any more.
+ */
+static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
+						struct rq *rq)
+{
+	cputime_t one_jiffy_scaled = cputime_to_scaled(cputime_one_jiffy);
+	cputime64_t tmp = cputime_to_cputime64(cputime_one_jiffy);
+	struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
+
+	if (irqtime_account_hi_update()) {
+		cpustat->irq = cputime64_add(cpustat->irq, tmp);
+	} else if (irqtime_account_si_update()) {
+		cpustat->softirq = cputime64_add(cpustat->softirq, tmp);
+	} else if (this_cpu_ksoftirqd() == p) {
+		/*
+		 * ksoftirqd time do not get accounted in cpu_softirq_time.
+		 * So, we have to handle it separately here.
+		 * Also, p->stime needs to be updated for ksoftirqd.
+		 */
+		__account_system_time(p, cputime_one_jiffy, one_jiffy_scaled,
+					&cpustat->softirq);
+	} else if (user_tick) {
+		account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
+	} else if (p == rq->idle) {
+		account_idle_time(cputime_one_jiffy);
+	} else if (p->flags & PF_VCPU) { /* System time or guest time */
+		account_guest_time(p, cputime_one_jiffy, one_jiffy_scaled);
+	} else {
+		__account_system_time(p, cputime_one_jiffy, one_jiffy_scaled,
+					&cpustat->system);
+	}
+}
+
+static void irqtime_account_idle_ticks(int ticks)
+{
+	int i;
+	struct rq *rq = this_rq();
+
+	for (i = 0; i < ticks; i++)
+		irqtime_account_process_tick(current, 0, rq);
+}
+#else /* CONFIG_IRQ_TIME_ACCOUNTING */
+static void irqtime_account_idle_ticks(int ticks) {}
+static void irqtime_account_process_tick(struct task_struct *p, int user_tick,
+						struct rq *rq) {}
+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
+
 /*
  * Account a single tick of cpu time.
  * @p: the process that the cpu time gets accounted to
@@ -3645,6 +3774,11 @@ 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 (sched_clock_irqtime) {
+		irqtime_account_process_tick(p, user_tick, rq);
+		return;
+	}
+
 	if (user_tick)
 		account_user_time(p, cputime_one_jiffy, one_jiffy_scaled);
 	else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
@@ -3670,6 +3804,12 @@ void account_steal_ticks(unsigned long 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));
 }
 
@@ -3945,9 +4085,6 @@ need_resched:
 	rcu_note_context_switch(cpu);
 	prev = rq->curr;
 
-	release_kernel_lock(prev);
-need_resched_nonpreemptible:
-
 	schedule_debug(prev);
 
 	if (sched_feat(HRTICK))
@@ -3989,9 +4126,6 @@ need_resched_nonpreemptible:
 	rq->skip_clock_update = 0;
 
 	if (likely(prev != next)) {
-		sched_info_switch(prev, next);
-		perf_event_task_sched_out(prev, next);
-
 		rq->nr_switches++;
 		rq->curr = next;
 		++*switch_count;
@@ -4010,9 +4144,6 @@ need_resched_nonpreemptible:
 
 	post_schedule(rq);
 
-	if (unlikely(reacquire_kernel_lock(prev)))
-		goto need_resched_nonpreemptible;
-
 	preempt_enable_no_resched();
 	if (need_resched())
 		goto need_resched;
@@ -4571,11 +4702,10 @@ void rt_mutex_setprio(struct task_struct *p, int prio)
 
 	if (running)
 		p->sched_class->set_curr_task(rq);
-	if (on_rq) {
+	if (on_rq)
 		enqueue_task(rq, p, oldprio < prio ? ENQUEUE_HEAD : 0);
 
-		check_class_changed(rq, p, prev_class, oldprio, running);
-	}
+	check_class_changed(rq, p, prev_class, oldprio);
 	task_rq_unlock(rq, &flags);
 }
 
@@ -4823,12 +4953,15 @@ recheck:
 			    param->sched_priority > rlim_rtprio)
 				return -EPERM;
 		}
+
 		/*
-		 * Like positive nice levels, dont allow tasks to
-		 * move out of SCHED_IDLE either:
+		 * Treat SCHED_IDLE as nice 20. Only allow a switch to
+		 * SCHED_NORMAL if the RLIMIT_NICE would normally permit it.
 		 */
-		if (p->policy == SCHED_IDLE && policy != SCHED_IDLE)
-			return -EPERM;
+		if (p->policy == SCHED_IDLE && policy != SCHED_IDLE) {
+			if (!can_nice(p, TASK_NICE(p)))
+				return -EPERM;
+		}
 
 		/* can't change other user's priorities */
 		if (!check_same_owner(p))
@@ -4903,11 +5036,10 @@ recheck:
 
 	if (running)
 		p->sched_class->set_curr_task(rq);
-	if (on_rq) {
+	if (on_rq)
 		activate_task(rq, p, 0);
 
-		check_class_changed(rq, p, prev_class, oldprio, running);
-	}
+	check_class_changed(rq, p, prev_class, oldprio);
 	__task_rq_unlock(rq);
 	raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
@@ -5324,6 +5456,65 @@ void __sched yield(void)
 }
 EXPORT_SYMBOL(yield);
 
+/**
+ * yield_to - yield the current processor to another thread in
+ * your thread group, or accelerate that thread toward the
+ * processor it's on.
+ *
+ * It's the caller's job to ensure that the target task struct
+ * can't go away on us before we can do any checks.
+ *
+ * Returns true if we indeed boosted the target task.
+ */
+bool __sched yield_to(struct task_struct *p, bool preempt)
+{
+	struct task_struct *curr = current;
+	struct rq *rq, *p_rq;
+	unsigned long flags;
+	bool yielded = 0;
+
+	local_irq_save(flags);
+	rq = this_rq();
+
+again:
+	p_rq = task_rq(p);
+	double_rq_lock(rq, p_rq);
+	while (task_rq(p) != p_rq) {
+		double_rq_unlock(rq, p_rq);
+		goto again;
+	}
+
+	if (!curr->sched_class->yield_to_task)
+		goto out;
+
+	if (curr->sched_class != p->sched_class)
+		goto out;
+
+	if (task_running(p_rq, p) || p->state)
+		goto out;
+
+	yielded = curr->sched_class->yield_to_task(rq, p, preempt);
+	if (yielded) {
+		schedstat_inc(rq, yld_count);
+		/*
+		 * Make p's CPU reschedule; pick_next_entity takes care of
+		 * fairness.
+		 */
+		if (preempt && rq != p_rq)
+			resched_task(p_rq->curr);
+	}
+
+out:
+	double_rq_unlock(rq, p_rq);
+	local_irq_restore(flags);
+
+	if (yielded)
+		schedule();
+
+	return yielded;
+}
+EXPORT_SYMBOL_GPL(yield_to);
+
 /*
  * This task is about to go to sleep on IO. Increment rq->nr_iowait so
  * that process accounting knows that this is a task in IO wait state.
@@ -5572,7 +5763,7 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu)
 	 * The idle tasks have their own, simple scheduling class:
 	 */
 	idle->sched_class = &idle_sched_class;
-	ftrace_graph_init_task(idle);
+	ftrace_graph_init_idle_task(idle, cpu);
 }
 
 /*
@@ -7797,6 +7988,10 @@ static void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq)
 	INIT_LIST_HEAD(&cfs_rq->tasks);
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	cfs_rq->rq = rq;
+	/* allow initial update_cfs_load() to truncate */
+#ifdef CONFIG_SMP
+	cfs_rq->load_stamp = 1;
+#endif
 #endif
 	cfs_rq->min_vruntime = (u64)(-(1LL << 20));
 }
@@ -8075,7 +8270,7 @@ static inline int preempt_count_equals(int preempt_offset)
 {
 	int nested = (preempt_count() & ~PREEMPT_ACTIVE) + rcu_preempt_depth();
 
-	return (nested == PREEMPT_INATOMIC_BASE + preempt_offset);
+	return (nested == preempt_offset);
 }
 
 void __might_sleep(const char *file, int line, int preempt_offset)
@@ -8110,6 +8305,8 @@ EXPORT_SYMBOL(__might_sleep);
 #ifdef CONFIG_MAGIC_SYSRQ
 static void normalize_task(struct rq *rq, struct task_struct *p)
 {
+	const struct sched_class *prev_class = p->sched_class;
+	int old_prio = p->prio;
 	int on_rq;
 
 	on_rq = p->se.on_rq;
@@ -8120,6 +8317,8 @@ static void normalize_task(struct rq *rq, struct task_struct *p)
 		activate_task(rq, p, 0);
 		resched_task(rq->curr);
 	}
+
+	check_class_changed(rq, p, prev_class, old_prio);
 }
 
 void normalize_rt_tasks(void)
@@ -8511,7 +8710,7 @@ int sched_group_set_shares(struct task_group *tg, unsigned long shares)
 		/* Propagate contribution to hierarchy */
 		raw_spin_lock_irqsave(&rq->lock, flags);
 		for_each_sched_entity(se)
-			update_cfs_shares(group_cfs_rq(se), 0);
+			update_cfs_shares(group_cfs_rq(se));
 		raw_spin_unlock_irqrestore(&rq->lock, flags);
 	}
 
@@ -8885,7 +9084,8 @@ cpu_cgroup_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
 }
 
 static void
-cpu_cgroup_exit(struct cgroup_subsys *ss, struct task_struct *task)
+cpu_cgroup_exit(struct cgroup_subsys *ss, struct cgroup *cgrp,
+		struct cgroup *old_cgrp, struct task_struct *task)
 {
 	/*
 	 * cgroup_exit() is called in the copy_process() failure path.
diff --git a/kernel/sched_autogroup.c b/kernel/sched_autogroup.c
index 9fb6562..5946ac5 100644
--- a/kernel/sched_autogroup.c
+++ b/kernel/sched_autogroup.c
@@ -12,7 +12,6 @@ static atomic_t autogroup_seq_nr;
 static void __init autogroup_init(struct task_struct *init_task)
 {
 	autogroup_default.tg = &root_task_group;
-	root_task_group.autogroup = &autogroup_default;
 	kref_init(&autogroup_default.kref);
 	init_rwsem(&autogroup_default.lock);
 	init_task->signal->autogroup = &autogroup_default;
@@ -130,7 +129,7 @@ task_wants_autogroup(struct task_struct *p, struct task_group *tg)
 
 static inline bool task_group_is_autogroup(struct task_group *tg)
 {
-	return tg != &root_task_group && tg->autogroup;
+	return !!tg->autogroup;
 }
 
 static inline struct task_group *
@@ -161,11 +160,15 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag)
 
 	p->signal->autogroup = autogroup_kref_get(ag);
 
+	if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled))
+		goto out;
+
 	t = p;
 	do {
 		sched_move_task(t);
 	} while_each_thread(p, t);
 
+out:
 	unlock_task_sighand(p, &flags);
 	autogroup_kref_put(prev);
 }
@@ -247,10 +250,14 @@ void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
 {
 	struct autogroup *ag = autogroup_task_get(p);
 
+	if (!task_group_is_autogroup(ag->tg))
+		goto out;
+
 	down_read(&ag->lock);
 	seq_printf(m, "/autogroup-%ld nice %d\n", ag->id, ag->nice);
 	up_read(&ag->lock);
 
+out:
 	autogroup_kref_put(ag);
 }
 #endif /* CONFIG_PROC_FS */
@@ -258,9 +265,7 @@ void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m)
 #ifdef CONFIG_SCHED_DEBUG
 static inline int autogroup_path(struct task_group *tg, char *buf, int buflen)
 {
-	int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
-
-	if (!enabled || !tg->autogroup)
+	if (!task_group_is_autogroup(tg))
 		return 0;
 
 	return snprintf(buf, buflen, "%s-%ld", "/autogroup", tg->autogroup->id);
diff --git a/kernel/sched_autogroup.h b/kernel/sched_autogroup.h
index 7b859ff..0557705 100644
--- a/kernel/sched_autogroup.h
+++ b/kernel/sched_autogroup.h
@@ -1,6 +1,11 @@
 #ifdef CONFIG_SCHED_AUTOGROUP
 
 struct autogroup {
+	/*
+	 * reference doesn't mean how many thread attach to this
+	 * autogroup now. It just stands for the number of task
+	 * could use this autogroup.
+	 */
 	struct kref		kref;
 	struct task_group	*tg;
 	struct rw_semaphore	lock;
diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c
index eb6cb8e..7bacd83 100644
--- a/kernel/sched_debug.c
+++ b/kernel/sched_debug.c
@@ -179,7 +179,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
 
 	raw_spin_lock_irqsave(&rq->lock, flags);
 	if (cfs_rq->rb_leftmost)
-		MIN_vruntime = (__pick_next_entity(cfs_rq))->vruntime;
+		MIN_vruntime = (__pick_first_entity(cfs_rq))->vruntime;
 	last = __pick_last_entity(cfs_rq);
 	if (last)
 		max_vruntime = last->vruntime;
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c
index 0c26e2d..3f7ec9e 100644
--- a/kernel/sched_fair.c
+++ b/kernel/sched_fair.c
@@ -69,14 +69,6 @@ static unsigned int sched_nr_latency = 8;
 unsigned int sysctl_sched_child_runs_first __read_mostly;
 
 /*
- * sys_sched_yield() compat mode
- *
- * This option switches the agressive yield implementation of the
- * old scheduler back on.
- */
-unsigned int __read_mostly sysctl_sched_compat_yield;
-
-/*
  * SCHED_OTHER wake-up granularity.
  * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds)
  *
@@ -419,7 +411,7 @@ static void __dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 	rb_erase(&se->run_node, &cfs_rq->tasks_timeline);
 }
 
-static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
+static struct sched_entity *__pick_first_entity(struct cfs_rq *cfs_rq)
 {
 	struct rb_node *left = cfs_rq->rb_leftmost;
 
@@ -429,6 +421,17 @@ static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq)
 	return rb_entry(left, struct sched_entity, run_node);
 }
 
+static struct sched_entity *__pick_next_entity(struct sched_entity *se)
+{
+	struct rb_node *next = rb_next(&se->run_node);
+
+	if (!next)
+		return NULL;
+
+	return rb_entry(next, struct sched_entity, run_node);
+}
+
+#ifdef CONFIG_SCHED_DEBUG
 static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
 {
 	struct rb_node *last = rb_last(&cfs_rq->tasks_timeline);
@@ -443,7 +446,6 @@ static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq)
  * Scheduling class statistics methods:
  */
 
-#ifdef CONFIG_SCHED_DEBUG
 int sched_proc_update_handler(struct ctl_table *table, int write,
 		void __user *buffer, size_t *lenp,
 		loff_t *ppos)
@@ -540,7 +542,7 @@ static u64 sched_vslice(struct cfs_rq *cfs_rq, struct sched_entity *se)
 }
 
 static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update);
-static void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta);
+static void update_cfs_shares(struct cfs_rq *cfs_rq);
 
 /*
  * Update the current task's runtime statistics. Skip current tasks that
@@ -733,6 +735,7 @@ static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
 	    now - cfs_rq->load_last > 4 * period) {
 		cfs_rq->load_period = 0;
 		cfs_rq->load_avg = 0;
+		delta = period - 1;
 	}
 
 	cfs_rq->load_stamp = now;
@@ -763,16 +766,15 @@ static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
 		list_del_leaf_cfs_rq(cfs_rq);
 }
 
-static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg,
-				long weight_delta)
+static long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
 {
 	long load_weight, load, shares;
 
-	load = cfs_rq->load.weight + weight_delta;
+	load = cfs_rq->load.weight;
 
 	load_weight = atomic_read(&tg->load_weight);
-	load_weight -= cfs_rq->load_contribution;
 	load_weight += load;
+	load_weight -= cfs_rq->load_contribution;
 
 	shares = (tg->shares * load);
 	if (load_weight)
@@ -790,7 +792,7 @@ static void update_entity_shares_tick(struct cfs_rq *cfs_rq)
 {
 	if (cfs_rq->load_unacc_exec_time > sysctl_sched_shares_window) {
 		update_cfs_load(cfs_rq, 0);
-		update_cfs_shares(cfs_rq, 0);
+		update_cfs_shares(cfs_rq);
 	}
 }
 # else /* CONFIG_SMP */
@@ -798,8 +800,7 @@ static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
 {
 }
 
-static inline long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg,
-				long weight_delta)
+static inline long calc_cfs_shares(struct cfs_rq *cfs_rq, struct task_group *tg)
 {
 	return tg->shares;
 }
@@ -824,7 +825,7 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
 		account_entity_enqueue(cfs_rq, se);
 }
 
-static void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta)
+static void update_cfs_shares(struct cfs_rq *cfs_rq)
 {
 	struct task_group *tg;
 	struct sched_entity *se;
@@ -838,7 +839,7 @@ static void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta)
 	if (likely(se->load.weight == tg->shares))
 		return;
 #endif
-	shares = calc_cfs_shares(cfs_rq, tg, weight_delta);
+	shares = calc_cfs_shares(cfs_rq, tg);
 
 	reweight_entity(cfs_rq_of(se), se, shares);
 }
@@ -847,7 +848,7 @@ static void update_cfs_load(struct cfs_rq *cfs_rq, int global_update)
 {
 }
 
-static inline void update_cfs_shares(struct cfs_rq *cfs_rq, long weight_delta)
+static inline void update_cfs_shares(struct cfs_rq *cfs_rq)
 {
 }
 
@@ -978,8 +979,8 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 	 */
 	update_curr(cfs_rq);
 	update_cfs_load(cfs_rq, 0);
-	update_cfs_shares(cfs_rq, se->load.weight);
 	account_entity_enqueue(cfs_rq, se);
+	update_cfs_shares(cfs_rq);
 
 	if (flags & ENQUEUE_WAKEUP) {
 		place_entity(cfs_rq, se, 0);
@@ -996,19 +997,49 @@ enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 		list_add_leaf_cfs_rq(cfs_rq);
 }
 
-static void __clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
+static void __clear_buddies_last(struct sched_entity *se)
+{
+	for_each_sched_entity(se) {
+		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+		if (cfs_rq->last == se)
+			cfs_rq->last = NULL;
+		else
+			break;
+	}
+}
+
+static void __clear_buddies_next(struct sched_entity *se)
 {
-	if (!se || cfs_rq->last == se)
-		cfs_rq->last = NULL;
+	for_each_sched_entity(se) {
+		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+		if (cfs_rq->next == se)
+			cfs_rq->next = NULL;
+		else
+			break;
+	}
+}
 
-	if (!se || cfs_rq->next == se)
-		cfs_rq->next = NULL;
+static void __clear_buddies_skip(struct sched_entity *se)
+{
+	for_each_sched_entity(se) {
+		struct cfs_rq *cfs_rq = cfs_rq_of(se);
+		if (cfs_rq->skip == se)
+			cfs_rq->skip = NULL;
+		else
+			break;
+	}
 }
 
 static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
 {
-	for_each_sched_entity(se)
-		__clear_buddies(cfs_rq_of(se), se);
+	if (cfs_rq->last == se)
+		__clear_buddies_last(se);
+
+	if (cfs_rq->next == se)
+		__clear_buddies_next(se);
+
+	if (cfs_rq->skip == se)
+		__clear_buddies_skip(se);
 }
 
 static void
@@ -1041,7 +1072,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
 	update_cfs_load(cfs_rq, 0);
 	account_entity_dequeue(cfs_rq, se);
 	update_min_vruntime(cfs_rq);
-	update_cfs_shares(cfs_rq, 0);
+	update_cfs_shares(cfs_rq);
 
 	/*
 	 * Normalize the entity after updating the min_vruntime because the
@@ -1084,7 +1115,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
 		return;
 
 	if (cfs_rq->nr_running > 1) {
-		struct sched_entity *se = __pick_next_entity(cfs_rq);
+		struct sched_entity *se = __pick_first_entity(cfs_rq);
 		s64 delta = curr->vruntime - se->vruntime;
 
 		if (delta < 0)
@@ -1128,13 +1159,27 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se)
 static int
 wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se);
 
+/*
+ * Pick the next process, keeping these things in mind, in this order:
+ * 1) keep things fair between processes/task groups
+ * 2) pick the "next" process, since someone really wants that to run
+ * 3) pick the "last" process, for cache locality
+ * 4) do not run the "skip" process, if something else is available
+ */
 static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
 {
-	struct sched_entity *se = __pick_next_entity(cfs_rq);
+	struct sched_entity *se = __pick_first_entity(cfs_rq);
 	struct sched_entity *left = se;
 
-	if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, left) < 1)
-		se = cfs_rq->next;
+	/*
+	 * Avoid running the skip buddy, if running something else can
+	 * be done without getting too unfair.
+	 */
+	if (cfs_rq->skip == se) {
+		struct sched_entity *second = __pick_next_entity(se);
+		if (second && wakeup_preempt_entity(second, left) < 1)
+			se = second;
+	}
 
 	/*
 	 * Prefer last buddy, try to return the CPU to a preempted task.
@@ -1142,6 +1187,12 @@ static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq)
 	if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, left) < 1)
 		se = cfs_rq->last;
 
+	/*
+	 * Someone really wants this to run. If it's not unfair, run it.
+	 */
+	if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, left) < 1)
+		se = cfs_rq->next;
+
 	clear_buddies(cfs_rq, se);
 
 	return se;
@@ -1282,7 +1333,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 		struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
 		update_cfs_load(cfs_rq, 0);
-		update_cfs_shares(cfs_rq, 0);
+		update_cfs_shares(cfs_rq);
 	}
 
 	hrtick_update(rq);
@@ -1312,58 +1363,12 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
 		struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
 		update_cfs_load(cfs_rq, 0);
-		update_cfs_shares(cfs_rq, 0);
+		update_cfs_shares(cfs_rq);
 	}
 
 	hrtick_update(rq);
 }
 
-/*
- * sched_yield() support is very simple - we dequeue and enqueue.
- *
- * If compat_yield is turned on then we requeue to the end of the tree.
- */
-static void yield_task_fair(struct rq *rq)
-{
-	struct task_struct *curr = rq->curr;
-	struct cfs_rq *cfs_rq = task_cfs_rq(curr);
-	struct sched_entity *rightmost, *se = &curr->se;
-
-	/*
-	 * Are we the only task in the tree?
-	 */
-	if (unlikely(cfs_rq->nr_running == 1))
-		return;
-
-	clear_buddies(cfs_rq, se);
-
-	if (likely(!sysctl_sched_compat_yield) && curr->policy != SCHED_BATCH) {
-		update_rq_clock(rq);
-		/*
-		 * Update run-time statistics of the 'current'.
-		 */
-		update_curr(cfs_rq);
-
-		return;
-	}
-	/*
-	 * Find the rightmost entry in the rbtree:
-	 */
-	rightmost = __pick_last_entity(cfs_rq);
-	/*
-	 * Already in the rightmost position?
-	 */
-	if (unlikely(!rightmost || entity_before(rightmost, se)))
-		return;
-
-	/*
-	 * Minimally necessary key value to be last in the tree:
-	 * Upon rescheduling, sched_class::put_prev_task() will place
-	 * 'current' within the tree based on its new key value.
-	 */
-	se->vruntime = rightmost->vruntime + 1;
-}
-
 #ifdef CONFIG_SMP
 
 static void task_waking_fair(struct rq *rq, struct task_struct *p)
@@ -1834,6 +1839,14 @@ static void set_next_buddy(struct sched_entity *se)
 	}
 }
 
+static void set_skip_buddy(struct sched_entity *se)
+{
+	if (likely(task_of(se)->policy != SCHED_IDLE)) {
+		for_each_sched_entity(se)
+			cfs_rq_of(se)->skip = se;
+	}
+}
+
 /*
  * Preempt the current task with a newly woken task if needed:
  */
@@ -1857,16 +1870,18 @@ static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int wake_
 	if (test_tsk_need_resched(curr))
 		return;
 
+	/* Idle tasks are by definition preempted by non-idle tasks. */
+	if (unlikely(curr->policy == SCHED_IDLE) &&
+	    likely(p->policy != SCHED_IDLE))
+		goto preempt;
+
 	/*
-	 * Batch and idle tasks do not preempt (their preemption is driven by
-	 * the tick):
+	 * Batch and idle tasks do not preempt non-idle tasks (their preemption
+	 * is driven by the tick):
 	 */
 	if (unlikely(p->policy != SCHED_NORMAL))
 		return;
 
-	/* Idle tasks are by definition preempted by everybody. */
-	if (unlikely(curr->policy == SCHED_IDLE))
-		goto preempt;
 
 	if (!sched_feat(WAKEUP_PREEMPT))
 		return;
@@ -1932,6 +1947,51 @@ static void put_prev_task_fair(struct rq *rq, struct task_struct *prev)
 	}
 }
 
+/*
+ * sched_yield() is very simple
+ *
+ * The magic of dealing with the ->skip buddy is in pick_next_entity.
+ */
+static void yield_task_fair(struct rq *rq)
+{
+	struct task_struct *curr = rq->curr;
+	struct cfs_rq *cfs_rq = task_cfs_rq(curr);
+	struct sched_entity *se = &curr->se;
+
+	/*
+	 * Are we the only task in the tree?
+	 */
+	if (unlikely(rq->nr_running == 1))
+		return;
+
+	clear_buddies(cfs_rq, se);
+
+	if (curr->policy != SCHED_BATCH) {
+		update_rq_clock(rq);
+		/*
+		 * Update run-time statistics of the 'current'.
+		 */
+		update_curr(cfs_rq);
+	}
+
+	set_skip_buddy(se);
+}
+
+static bool yield_to_task_fair(struct rq *rq, struct task_struct *p, bool preempt)
+{
+	struct sched_entity *se = &p->se;
+
+	if (!se->on_rq)
+		return false;
+
+	/* Tell the scheduler that we'd really like pse to run next. */
+	set_next_buddy(se);
+
+	yield_task_fair(rq);
+
+	return true;
+}
+
 #ifdef CONFIG_SMP
 /**************************************************
  * Fair scheduling class load-balancing methods:
@@ -2123,7 +2183,7 @@ static int update_shares_cpu(struct task_group *tg, int cpu)
 	 * We need to update shares after updating tg->load_weight in
 	 * order to adjust the weight of groups with long running tasks.
 	 */
-	update_cfs_shares(cfs_rq, 0);
+	update_cfs_shares(cfs_rq);
 
 	raw_spin_unlock_irqrestore(&rq->lock, flags);
 
@@ -2610,7 +2670,6 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
  * @this_cpu: Cpu for which load balance is currently performed.
  * @idle: Idle status of this_cpu
  * @load_idx: Load index of sched_domain of this_cpu for load calc.
- * @sd_idle: Idle status of the sched_domain containing group.
  * @local_group: Does group contain this_cpu.
  * @cpus: Set of cpus considered for load balancing.
  * @balance: Should we balance.
@@ -2618,7 +2677,7 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
  */
 static inline void update_sg_lb_stats(struct sched_domain *sd,
 			struct sched_group *group, int this_cpu,
-			enum cpu_idle_type idle, int load_idx, int *sd_idle,
+			enum cpu_idle_type idle, int load_idx,
 			int local_group, const struct cpumask *cpus,
 			int *balance, struct sg_lb_stats *sgs)
 {
@@ -2638,9 +2697,6 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
 	for_each_cpu_and(i, sched_group_cpus(group), cpus) {
 		struct rq *rq = cpu_rq(i);
 
-		if (*sd_idle && rq->nr_running)
-			*sd_idle = 0;
-
 		/* Bias balancing toward cpus of our domain */
 		if (local_group) {
 			if (idle_cpu(i) && !first_idle_cpu) {
@@ -2685,7 +2741,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
 
 	/*
 	 * Consider the group unbalanced when the imbalance is larger
-	 * than the average weight of two tasks.
+	 * than the average weight of a task.
 	 *
 	 * APZ: with cgroup the avg task weight can vary wildly and
 	 *      might not be a suitable number - should we keep a
@@ -2695,7 +2751,7 @@ static inline void update_sg_lb_stats(struct sched_domain *sd,
 	if (sgs->sum_nr_running)
 		avg_load_per_task = sgs->sum_weighted_load / sgs->sum_nr_running;
 
-	if ((max_cpu_load - min_cpu_load) > 2*avg_load_per_task && max_nr_running > 1)
+	if ((max_cpu_load - min_cpu_load) >= avg_load_per_task && max_nr_running > 1)
 		sgs->group_imb = 1;
 
 	sgs->group_capacity = DIV_ROUND_CLOSEST(group->cpu_power, SCHED_LOAD_SCALE);
@@ -2755,15 +2811,13 @@ static bool update_sd_pick_busiest(struct sched_domain *sd,
  * @sd: sched_domain whose statistics are to be updated.
  * @this_cpu: Cpu for which load balance is currently performed.
  * @idle: Idle status of this_cpu
- * @sd_idle: Idle status of the sched_domain containing sg.
  * @cpus: Set of cpus considered for load balancing.
  * @balance: Should we balance.
  * @sds: variable to hold the statistics for this sched_domain.
  */
 static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
-			enum cpu_idle_type idle, int *sd_idle,
-			const struct cpumask *cpus, int *balance,
-			struct sd_lb_stats *sds)
+			enum cpu_idle_type idle, const struct cpumask *cpus,
+			int *balance, struct sd_lb_stats *sds)
 {
 	struct sched_domain *child = sd->child;
 	struct sched_group *sg = sd->groups;
@@ -2781,7 +2835,7 @@ static inline void update_sd_lb_stats(struct sched_domain *sd, int this_cpu,
 
 		local_group = cpumask_test_cpu(this_cpu, sched_group_cpus(sg));
 		memset(&sgs, 0, sizeof(sgs));
-		update_sg_lb_stats(sd, sg, this_cpu, idle, load_idx, sd_idle,
+		update_sg_lb_stats(sd, sg, this_cpu, idle, load_idx,
 				local_group, cpus, balance, &sgs);
 
 		if (local_group && !(*balance))
@@ -3033,7 +3087,6 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
  * @imbalance: Variable which stores amount of weighted load which should
  *		be moved to restore balance/put a group to idle.
  * @idle: The idle status of this_cpu.
- * @sd_idle: The idleness of sd
  * @cpus: The set of CPUs under consideration for load-balancing.
  * @balance: Pointer to a variable indicating if this_cpu
  *	is the appropriate cpu to perform load balancing at this_level.
@@ -3046,7 +3099,7 @@ static inline void calculate_imbalance(struct sd_lb_stats *sds, int this_cpu,
 static struct sched_group *
 find_busiest_group(struct sched_domain *sd, int this_cpu,
 		   unsigned long *imbalance, enum cpu_idle_type idle,
-		   int *sd_idle, const struct cpumask *cpus, int *balance)
+		   const struct cpumask *cpus, int *balance)
 {
 	struct sd_lb_stats sds;
 
@@ -3056,22 +3109,11 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
 	 * Compute the various statistics relavent for load balancing at
 	 * this level.
 	 */
-	update_sd_lb_stats(sd, this_cpu, idle, sd_idle, cpus,
-					balance, &sds);
-
-	/* Cases where imbalance does not exist from POV of this_cpu */
-	/* 1) this_cpu is not the appropriate cpu to perform load balancing
-	 *    at this level.
-	 * 2) There is no busy sibling group to pull from.
-	 * 3) This group is the busiest group.
-	 * 4) This group is more busy than the avg busieness at this
-	 *    sched_domain.
-	 * 5) The imbalance is within the specified limit.
-	 *
-	 * Note: when doing newidle balance, if the local group has excess
-	 * capacity (i.e. nr_running < group_capacity) and the busiest group
-	 * does not have any capacity, we force a load balance to pull tasks
-	 * to the local group. In this case, we skip past checks 3, 4 and 5.
+	update_sd_lb_stats(sd, this_cpu, idle, cpus, balance, &sds);
+
+	/*
+	 * this_cpu is not the appropriate cpu to perform load balancing at
+	 * this level.
 	 */
 	if (!(*balance))
 		goto ret;
@@ -3080,41 +3122,55 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
 	    check_asym_packing(sd, &sds, this_cpu, imbalance))
 		return sds.busiest;
 
+	/* There is no busy sibling group to pull tasks from */
 	if (!sds.busiest || sds.busiest_nr_running == 0)
 		goto out_balanced;
 
-	/*  SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
+	/*
+	 * If the busiest group is imbalanced the below checks don't
+	 * work because they assumes all things are equal, which typically
+	 * isn't true due to cpus_allowed constraints and the like.
+	 */
+	if (sds.group_imb)
+		goto force_balance;
+
+	/* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
 	if (idle == CPU_NEWLY_IDLE && sds.this_has_capacity &&
 			!sds.busiest_has_capacity)
 		goto force_balance;
 
+	/*
+	 * If the local group is more busy than the selected busiest group
+	 * don't try and pull any tasks.
+	 */
 	if (sds.this_load >= sds.max_load)
 		goto out_balanced;
 
+	/*
+	 * Don't pull any tasks if this group is already above the domain
+	 * average load.
+	 */
 	sds.avg_load = (SCHED_LOAD_SCALE * sds.total_load) / sds.total_pwr;
-
 	if (sds.this_load >= sds.avg_load)
 		goto out_balanced;
 
-	/*
-	 * In the CPU_NEWLY_IDLE, use imbalance_pct to be conservative.
-	 * And to check for busy balance use !idle_cpu instead of
-	 * CPU_NOT_IDLE. This is because HT siblings will use CPU_NOT_IDLE
-	 * even when they are idle.
-	 */
-	if (idle == CPU_NEWLY_IDLE || !idle_cpu(this_cpu)) {
-		if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
-			goto out_balanced;
-	} else {
+	if (idle == CPU_IDLE) {
 		/*
 		 * This cpu is idle. If the busiest group load doesn't
 		 * have more tasks than the number of available cpu's and
 		 * there is no imbalance between this and busiest group
 		 * wrt to idle cpu's, it is balanced.
 		 */
-		if ((sds.this_idle_cpus  <= sds.busiest_idle_cpus + 1) &&
+		if ((sds.this_idle_cpus <= sds.busiest_idle_cpus + 1) &&
 		    sds.busiest_nr_running <= sds.busiest_group_weight)
 			goto out_balanced;
+	} else {
+		/*
+		 * In the CPU_NEWLY_IDLE, CPU_NOT_IDLE cases, use
+		 * imbalance_pct to be conservative.
+		 */
+		if (100 * sds.max_load <= sd->imbalance_pct * sds.this_load)
+			goto out_balanced;
 	}
 
 force_balance:
@@ -3193,7 +3249,7 @@ find_busiest_queue(struct sched_domain *sd, struct sched_group *group,
 /* Working cpumask for load_balance and load_balance_newidle. */
 static DEFINE_PER_CPU(cpumask_var_t, load_balance_tmpmask);
 
-static int need_active_balance(struct sched_domain *sd, int sd_idle, int idle,
+static int need_active_balance(struct sched_domain *sd, int idle,
 			       int busiest_cpu, int this_cpu)
 {
 	if (idle == CPU_NEWLY_IDLE) {
@@ -3225,10 +3281,6 @@ static int need_active_balance(struct sched_domain *sd, int sd_idle, int idle,
 		 * move_tasks() will succeed.  ld_moved will be true and this
 		 * active balance code will not be triggered.
 		 */
-		if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
-		    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
-			return 0;
-
 		if (sched_mc_power_savings < POWERSAVINGS_BALANCE_WAKEUP)
 			return 0;
 	}
@@ -3246,7 +3298,7 @@ static int load_balance(int this_cpu, struct rq *this_rq,
 			struct sched_domain *sd, enum cpu_idle_type idle,
 			int *balance)
 {
-	int ld_moved, all_pinned = 0, active_balance = 0, sd_idle = 0;
+	int ld_moved, all_pinned = 0, active_balance = 0;
 	struct sched_group *group;
 	unsigned long imbalance;
 	struct rq *busiest;
@@ -3255,20 +3307,10 @@ static int load_balance(int this_cpu, struct rq *this_rq,
 
 	cpumask_copy(cpus, cpu_active_mask);
 
-	/*
-	 * When power savings policy is enabled for the parent domain, idle
-	 * sibling can pick up load irrespective of busy siblings. In this case,
-	 * let the state of idle sibling percolate up as CPU_IDLE, instead of
-	 * portraying it as CPU_NOT_IDLE.
-	 */
-	if (idle != CPU_NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
-	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
-		sd_idle = 1;
-
 	schedstat_inc(sd, lb_count[idle]);
 
 redo:
-	group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle,
+	group = find_busiest_group(sd, this_cpu, &imbalance, idle,
 				   cpus, balance);
 
 	if (*balance == 0)
@@ -3330,8 +3372,7 @@ redo:
 		if (idle != CPU_NEWLY_IDLE)
 			sd->nr_balance_failed++;
 
-		if (need_active_balance(sd, sd_idle, idle, cpu_of(busiest),
-					this_cpu)) {
+		if (need_active_balance(sd, idle, cpu_of(busiest), this_cpu)) {
 			raw_spin_lock_irqsave(&busiest->lock, flags);
 
 			/* don't kick the active_load_balance_cpu_stop,
@@ -3386,10 +3427,6 @@ redo:
 			sd->balance_interval *= 2;
 	}
 
-	if (!ld_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
-	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
-		ld_moved = -1;
-
 	goto out;
 
 out_balanced:
@@ -3403,11 +3440,7 @@ out_one_pinned:
 			(sd->balance_interval < sd->max_interval))
 		sd->balance_interval *= 2;
 
-	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
-	    !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE))
-		ld_moved = -1;
-	else
-		ld_moved = 0;
+	ld_moved = 0;
 out:
 	return ld_moved;
 }
@@ -3831,8 +3864,7 @@ static void rebalance_domains(int cpu, enum cpu_idle_type idle)
 			if (load_balance(cpu, rq, sd, idle, &balance)) {
 				/*
 				 * We've pulled tasks over so either we're no
-				 * longer idle, or one of our SMT siblings is
-				 * not idle.
+				 * longer idle.
 				 */
 				idle = CPU_NOT_IDLE;
 			}
@@ -4079,33 +4111,62 @@ static void task_fork_fair(struct task_struct *p)
  * Priority of the task has changed. Check to see if we preempt
  * the current task.
  */
-static void prio_changed_fair(struct rq *rq, struct task_struct *p,
-			      int oldprio, int running)
+static void
+prio_changed_fair(struct rq *rq, struct task_struct *p, int oldprio)
 {
+	if (!p->se.on_rq)
+		return;
+
 	/*
 	 * Reschedule if we are currently running on this runqueue and
 	 * our priority decreased, or if we are not currently running on
 	 * this runqueue and our priority is higher than the current's
 	 */
-	if (running) {
+	if (rq->curr == p) {
 		if (p->prio > oldprio)
 			resched_task(rq->curr);
 	} else
 		check_preempt_curr(rq, p, 0);
 }
 
+static void switched_from_fair(struct rq *rq, struct task_struct *p)
+{
+	struct sched_entity *se = &p->se;
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+	/*
+	 * Ensure the task's vruntime is normalized, so that when its
+	 * switched back to the fair class the enqueue_entity(.flags=0) will
+	 * do the right thing.
+	 *
+	 * If it was on_rq, then the dequeue_entity(.flags=0) will already
+	 * have normalized the vruntime, if it was !on_rq, then only when
+	 * the task is sleeping will it still have non-normalized vruntime.
+	 */
+	if (!se->on_rq && p->state != TASK_RUNNING) {
+		/*
+		 * Fix up our vruntime so that the current sleep doesn't
+		 * cause 'unlimited' sleep bonus.
+		 */
+		place_entity(cfs_rq, se, 0);
+		se->vruntime -= cfs_rq->min_vruntime;
+	}
+}
+
 /*
  * We switched to the sched_fair class.
  */
-static void switched_to_fair(struct rq *rq, struct task_struct *p,
-			     int running)
+static void switched_to_fair(struct rq *rq, struct task_struct *p)
 {
+	if (!p->se.on_rq)
+		return;
+
 	/*
 	 * We were most likely switched from sched_rt, so
 	 * kick off the schedule if running, otherwise just see
 	 * if we can still preempt the current task.
 	 */
-	if (running)
+	if (rq->curr == p)
 		resched_task(rq->curr);
 	else
 		check_preempt_curr(rq, p, 0);
@@ -4171,6 +4232,7 @@ static const struct sched_class fair_sched_class = {
 	.enqueue_task		= enqueue_task_fair,
 	.dequeue_task		= dequeue_task_fair,
 	.yield_task		= yield_task_fair,
+	.yield_to_task		= yield_to_task_fair,
 
 	.check_preempt_curr	= check_preempt_wakeup,
 
@@ -4191,6 +4253,7 @@ static const struct sched_class fair_sched_class = {
 	.task_fork		= task_fork_fair,
 
 	.prio_changed		= prio_changed_fair,
+	.switched_from		= switched_from_fair,
 	.switched_to		= switched_to_fair,
 
 	.get_rr_interval	= get_rr_interval_fair,
diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c
index 9fa0f40..c82f26c 100644
--- a/kernel/sched_idletask.c
+++ b/kernel/sched_idletask.c
@@ -52,31 +52,15 @@ static void set_curr_task_idle(struct rq *rq)
 {
 }
 
-static void switched_to_idle(struct rq *rq, struct task_struct *p,
-			     int running)
+static void switched_to_idle(struct rq *rq, struct task_struct *p)
 {
-	/* Can this actually happen?? */
-	if (running)
-		resched_task(rq->curr);
-	else
-		check_preempt_curr(rq, p, 0);
+	BUG();
 }
 
-static void prio_changed_idle(struct rq *rq, struct task_struct *p,
-			      int oldprio, int running)
+static void
+prio_changed_idle(struct rq *rq, struct task_struct *p, int oldprio)
 {
-	/* This can happen for hot plug CPUS */
-
-	/*
-	 * Reschedule if we are currently running on this runqueue and
-	 * our priority decreased, or if we are not currently running on
-	 * this runqueue and our priority is higher than the current's
-	 */
-	if (running) {
-		if (p->prio > oldprio)
-			resched_task(rq->curr);
-	} else
-		check_preempt_curr(rq, p, 0);
+	BUG();
 }
 
 static unsigned int get_rr_interval_idle(struct rq *rq, struct task_struct *task)
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 01f75a5..db308cb 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1599,8 +1599,7 @@ static void rq_offline_rt(struct rq *rq)
  * When switch from the rt queue, we bring ourselves to a position
  * that we might want to pull RT tasks from other runqueues.
  */
-static void switched_from_rt(struct rq *rq, struct task_struct *p,
-			   int running)
+static void switched_from_rt(struct rq *rq, struct task_struct *p)
 {
 	/*
 	 * If there are other RT tasks then we will reschedule
@@ -1609,7 +1608,7 @@ static void switched_from_rt(struct rq *rq, struct task_struct *p,
 	 * we may need to handle the pulling of RT tasks
 	 * now.
 	 */
-	if (!rq->rt.rt_nr_running)
+	if (p->se.on_rq && !rq->rt.rt_nr_running)
 		pull_rt_task(rq);
 }
 
@@ -1628,8 +1627,7 @@ static inline void init_sched_rt_class(void)
  * with RT tasks. In this case we try to push them off to
  * other runqueues.
  */
-static void switched_to_rt(struct rq *rq, struct task_struct *p,
-			   int running)
+static void switched_to_rt(struct rq *rq, struct task_struct *p)
 {
 	int check_resched = 1;
 
@@ -1640,7 +1638,7 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p,
 	 * If that current running task is also an RT task
 	 * then see if we can move to another run queue.
 	 */
-	if (!running) {
+	if (p->se.on_rq && rq->curr != p) {
 #ifdef CONFIG_SMP
 		if (rq->rt.overloaded && push_rt_task(rq) &&
 		    /* Don't resched if we changed runqueues */
@@ -1656,10 +1654,13 @@ static void switched_to_rt(struct rq *rq, struct task_struct *p,
  * Priority of the task has changed. This may cause
  * us to initiate a push or pull.
  */
-static void prio_changed_rt(struct rq *rq, struct task_struct *p,
-			    int oldprio, int running)
+static void
+prio_changed_rt(struct rq *rq, struct task_struct *p, int oldprio)
 {
-	if (running) {
+	if (!p->se.on_rq)
+		return;
+
+	if (rq->curr == p) {
 #ifdef CONFIG_SMP
 		/*
 		 * If our priority decreases while running, we
diff --git a/kernel/sched_stoptask.c b/kernel/sched_stoptask.c
index 2bf6b47..84ec9bc 100644
--- a/kernel/sched_stoptask.c
+++ b/kernel/sched_stoptask.c
@@ -59,14 +59,13 @@ static void set_curr_task_stop(struct rq *rq)
 {
 }
 
-static void switched_to_stop(struct rq *rq, struct task_struct *p,
-			     int running)
+static void switched_to_stop(struct rq *rq, struct task_struct *p)
 {
 	BUG(); /* its impossible to change to this class */
 }
 
-static void prio_changed_stop(struct rq *rq, struct task_struct *p,
-			      int oldprio, int running)
+static void
+prio_changed_stop(struct rq *rq, struct task_struct *p, int oldprio)
 {
 	BUG(); /* how!?, what priority? */
 }
diff --git a/kernel/signal.c b/kernel/signal.c
index 4e3cff1..3175186 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2421,9 +2421,13 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
 		return -EFAULT;
 
 	/* Not even root can pretend to send signals from the kernel.
-	   Nor can they impersonate a kill(), which adds source info.  */
-	if (info.si_code >= 0)
+	 * Nor can they impersonate a kill()/tgkill(), which adds source info.
+	 */
+	if (info.si_code != SI_QUEUE) {
+		/* We used to allow any < 0 si_code */
+		WARN_ON_ONCE(info.si_code < 0);
 		return -EPERM;
+	}
 	info.si_signo = sig;
 
 	/* POSIX.1b doesn't mention process groups.  */
@@ -2437,9 +2441,13 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
 		return -EINVAL;
 
 	/* Not even root can pretend to send signals from the kernel.
-	   Nor can they impersonate a kill(), which adds source info.  */
-	if (info->si_code >= 0)
+	 * Nor can they impersonate a kill()/tgkill(), which adds source info.
+	 */
+	if (info->si_code != SI_QUEUE) {
+		/* We used to allow any < 0 si_code */
+		WARN_ON_ONCE(info->si_code < 0);
 		return -EPERM;
+	}
 	info->si_signo = sig;
 
 	return do_send_specific(tgid, pid, sig, info);
diff --git a/kernel/smp.c b/kernel/smp.c
index 9910744..73a1951 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -194,7 +194,7 @@ void generic_smp_call_function_interrupt(void)
 	 */
 	list_for_each_entry_rcu(data, &call_function.queue, csd.list) {
 		int refs;
-		void (*func) (void *info);
+		smp_call_func_t func;
 
 		/*
 		 * Since we walk the list without any locks, we might
@@ -214,17 +214,17 @@ void generic_smp_call_function_interrupt(void)
 		if (atomic_read(&data->refs) == 0)
 			continue;
 
-		func = data->csd.func;			/* for later warn */
-		data->csd.func(data->csd.info);
+		func = data->csd.func;		/* save for later warn */
+		func(data->csd.info);
 
 		/*
-		 * If the cpu mask is not still set then it enabled interrupts,
-		 * we took another smp interrupt, and executed the function
-		 * twice on this cpu.  In theory that copy decremented refs.
+		 * If the cpu mask is not still set then func enabled
+		 * interrupts (BUG), and this cpu took another smp call
+		 * function interrupt and executed func(info) twice
+		 * on this cpu.  That nested execution decremented refs.
 		 */
 		if (!cpumask_test_and_clear_cpu(cpu, data->cpumask)) {
-			WARN(1, "%pS enabled interrupts and double executed\n",
-			     func);
+			WARN(1, "%pf enabled interrupts and double executed\n", func);
 			continue;
 		}
 
@@ -450,7 +450,7 @@ void smp_call_function_many(const struct cpumask *mask,
 {
 	struct call_function_data *data;
 	unsigned long flags;
-	int cpu, next_cpu, this_cpu = smp_processor_id();
+	int refs, cpu, next_cpu, this_cpu = smp_processor_id();
 
 	/*
 	 * Can deadlock when called with interrupts disabled.
@@ -461,7 +461,7 @@ void smp_call_function_many(const struct cpumask *mask,
 	WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
 		     && !oops_in_progress && !early_boot_irqs_disabled);
 
-	/* So, what's a CPU they want? Ignoring this one. */
+	/* Try to fastpath.  So, what's a CPU they want? Ignoring this one. */
 	cpu = cpumask_first_and(mask, cpu_online_mask);
 	if (cpu == this_cpu)
 		cpu = cpumask_next_and(cpu, mask, cpu_online_mask);
@@ -483,22 +483,49 @@ void smp_call_function_many(const struct cpumask *mask,
 
 	data = &__get_cpu_var(cfd_data);
 	csd_lock(&data->csd);
+
+	/* This BUG_ON verifies our reuse assertions and can be removed */
 	BUG_ON(atomic_read(&data->refs) || !cpumask_empty(data->cpumask));
 
+	/*
+	 * The global call function queue list add and delete are protected
+	 * by a lock, but the list is traversed without any lock, relying
+	 * on the rcu list add and delete to allow safe concurrent traversal.
+	 * We reuse the call function data without waiting for any grace
+	 * period after some other cpu removes it from the global queue.
+	 * This means a cpu might find our data block as it is being
+	 * filled out.
+	 *
+	 * We hold off the interrupt handler on the other cpu by
+	 * ordering our writes to the cpu mask vs our setting of the
+	 * refs counter.  We assert only the cpu owning the data block
+	 * will set a bit in cpumask, and each bit will only be cleared
+	 * by the subject cpu.  Each cpu must first find its bit is
+	 * set and then check that refs is set indicating the element is
+	 * ready to be processed, otherwise it must skip the entry.
+	 *
+	 * On the previous iteration refs was set to 0 by another cpu.
+	 * To avoid the use of transitivity, set the counter to 0 here
+	 * so the wmb will pair with the rmb in the interrupt handler.
+	 */
+	atomic_set(&data->refs, 0);	/* convert 3rd to 1st party write */
+
 	data->csd.func = func;
 	data->csd.info = info;
-	cpumask_and(data->cpumask, mask, cpu_online_mask);
-	cpumask_clear_cpu(this_cpu, data->cpumask);
 
-	/*
-	 * To ensure the interrupt handler gets an complete view
-	 * we order the cpumask and refs writes and order the read
-	 * of them in the interrupt handler.  In addition we may
-	 * only clear our own cpu bit from the mask.
-	 */
+	/* Ensure 0 refs is visible before mask.  Also orders func and info */
 	smp_wmb();
 
-	atomic_set(&data->refs, cpumask_weight(data->cpumask));
+	/* We rely on the "and" being processed before the store */
+	cpumask_and(data->cpumask, mask, cpu_online_mask);
+	cpumask_clear_cpu(this_cpu, data->cpumask);
+	refs = cpumask_weight(data->cpumask);
+
+	/* Some callers race with other cpus changing the passed mask */
+	if (unlikely(!refs)) {
+		csd_unlock(&data->csd);
+		return;
+	}
 
 	raw_spin_lock_irqsave(&call_function.lock, flags);
 	/*
@@ -507,6 +534,12 @@ void smp_call_function_many(const struct cpumask *mask,
 	 * will not miss any other list entries:
 	 */
 	list_add_rcu(&data->csd.list, &call_function.queue);
+	/*
+	 * We rely on the wmb() in list_add_rcu to complete our writes
+	 * to the cpumask before this write to refs, which indicates
+	 * data is on the list and is ready to be processed.
+	 */
+	atomic_set(&data->refs, refs);
 	raw_spin_unlock_irqrestore(&call_function.lock, flags);
 
 	/*
@@ -571,6 +604,87 @@ void ipi_call_unlock_irq(void)
 }
 #endif /* USE_GENERIC_SMP_HELPERS */
 
+/* Setup configured maximum number of CPUs to activate */
+unsigned int setup_max_cpus = NR_CPUS;
+EXPORT_SYMBOL(setup_max_cpus);
+
+
+/*
+ * Setup routine for controlling SMP activation
+ *
+ * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
+ * activation entirely (the MPS table probe still happens, though).
+ *
+ * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
+ * greater than 0, limits the maximum number of CPUs activated in
+ * SMP mode to <NUM>.
+ */
+
+void __weak arch_disable_smp_support(void) { }
+
+static int __init nosmp(char *str)
+{
+	setup_max_cpus = 0;
+	arch_disable_smp_support();
+
+	return 0;
+}
+
+early_param("nosmp", nosmp);
+
+/* this is hard limit */
+static int __init nrcpus(char *str)
+{
+	int nr_cpus;
+
+	get_option(&str, &nr_cpus);
+	if (nr_cpus > 0 && nr_cpus < nr_cpu_ids)
+		nr_cpu_ids = nr_cpus;
+
+	return 0;
+}
+
+early_param("nr_cpus", nrcpus);
+
+static int __init maxcpus(char *str)
+{
+	get_option(&str, &setup_max_cpus);
+	if (setup_max_cpus == 0)
+		arch_disable_smp_support();
+
+	return 0;
+}
+
+early_param("maxcpus", maxcpus);
+
+/* Setup number of possible processor ids */
+int nr_cpu_ids __read_mostly = NR_CPUS;
+EXPORT_SYMBOL(nr_cpu_ids);
+
+/* An arch may set nr_cpu_ids earlier if needed, so this would be redundant */
+void __init setup_nr_cpu_ids(void)
+{
+	nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
+}
+
+/* Called by boot processor to activate the rest. */
+void __init smp_init(void)
+{
+	unsigned int cpu;
+
+	/* FIXME: This should be done in userspace --RR */
+	for_each_present_cpu(cpu) {
+		if (num_online_cpus() >= setup_max_cpus)
+			break;
+		if (!cpu_online(cpu))
+			cpu_up(cpu);
+	}
+
+	/* Any cleanup work */
+	printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
+	smp_cpus_done(setup_max_cpus);
+}
+
 /*
  * Call a function on all processors.  May be used during early boot while
  * early_boot_irqs_disabled is set.  Use local_irq_save/restore() instead
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 68eb5ef..735d870 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(irq_stat);
 
 static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
 
-static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
 char *softirq_to_name[NR_SOFTIRQS] = {
 	"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
@@ -311,9 +311,21 @@ void irq_enter(void)
 }
 
 #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
-# define invoke_softirq()	__do_softirq()
+static inline void invoke_softirq(void)
+{
+	if (!force_irqthreads)
+		__do_softirq();
+	else
+		wakeup_softirqd();
+}
 #else
-# define invoke_softirq()	do_softirq()
+static inline void invoke_softirq(void)
+{
+	if (!force_irqthreads)
+		do_softirq();
+	else
+		wakeup_softirqd();
+}
 #endif
 
 /*
@@ -721,7 +733,6 @@ static int run_ksoftirqd(void * __bind_cpu)
 {
 	set_current_state(TASK_INTERRUPTIBLE);
 
-	current->flags |= PF_KSOFTIRQD;
 	while (!kthread_should_stop()) {
 		preempt_disable();
 		if (!local_softirq_pending()) {
@@ -738,7 +749,10 @@ static int run_ksoftirqd(void * __bind_cpu)
 			   don't process */
 			if (cpu_is_offline((long)__bind_cpu))
 				goto wait_to_die;
-			do_softirq();
+			local_irq_disable();
+			if (local_softirq_pending())
+				__do_softirq();
+			local_irq_enable();
 			preempt_enable_no_resched();
 			cond_resched();
 			preempt_disable();
@@ -831,7 +845,10 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb,
 	switch (action) {
 	case CPU_UP_PREPARE:
 	case CPU_UP_PREPARE_FROZEN:
-		p = kthread_create(run_ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
+		p = kthread_create_on_node(run_ksoftirqd,
+					   hcpu,
+					   cpu_to_node(hotcpu),
+					   "ksoftirqd/%d", hotcpu);
 		if (IS_ERR(p)) {
 			printk("ksoftirqd for %i failed\n", hotcpu);
 			return notifier_from_errno(PTR_ERR(p));
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 2df820b..e3516b2 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -301,8 +301,10 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
 	case CPU_UP_PREPARE:
 		BUG_ON(stopper->thread || stopper->enabled ||
 		       !list_empty(&stopper->works));
-		p = kthread_create(cpu_stopper_thread, stopper, "migration/%d",
-				   cpu);
+		p = kthread_create_on_node(cpu_stopper_thread,
+					   stopper,
+					   cpu_to_node(cpu),
+					   "migration/%d", cpu);
 		if (IS_ERR(p))
 			return notifier_from_errno(PTR_ERR(p));
 		get_task_struct(p);
diff --git a/kernel/sys.c b/kernel/sys.c
index 18da702..1ad48b3 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -37,6 +37,7 @@
 #include <linux/ptrace.h>
 #include <linux/fs_struct.h>
 #include <linux/gfp.h>
+#include <linux/syscore_ops.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
@@ -298,6 +299,7 @@ void kernel_restart_prepare(char *cmd)
 	system_state = SYSTEM_RESTART;
 	device_shutdown();
 	sysdev_shutdown();
+	syscore_shutdown();
 }
 
 /**
@@ -336,6 +338,7 @@ void kernel_halt(void)
 {
 	kernel_shutdown_prepare(SYSTEM_HALT);
 	sysdev_shutdown();
+	syscore_shutdown();
 	printk(KERN_EMERG "System halted.\n");
 	kmsg_dump(KMSG_DUMP_HALT);
 	machine_halt();
@@ -355,6 +358,7 @@ void kernel_power_off(void)
 		pm_power_off_prepare();
 	disable_nonboot_cpus();
 	sysdev_shutdown();
+	syscore_shutdown();
 	printk(KERN_EMERG "Power down.\n");
 	kmsg_dump(KMSG_DUMP_POWEROFF);
 	machine_power_off();
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index c782fe9..25cc41c 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -186,3 +186,8 @@ cond_syscall(sys_perf_event_open);
 /* fanotify! */
 cond_syscall(sys_fanotify_init);
 cond_syscall(sys_fanotify_mark);
+
+/* open by handle */
+cond_syscall(sys_name_to_handle_at);
+cond_syscall(sys_open_by_handle_at);
+cond_syscall(compat_sys_open_by_handle_at);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 4eed0af..40245d6 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -361,20 +361,13 @@ static struct ctl_table kern_table[] = {
 		.mode		= 0644,
 		.proc_handler	= sched_rt_handler,
 	},
-	{
-		.procname	= "sched_compat_yield",
-		.data		= &sysctl_sched_compat_yield,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
 #ifdef CONFIG_SCHED_AUTOGROUP
 	{
 		.procname	= "sched_autogroup_enabled",
 		.data		= &sysctl_sched_autogroup_enabled,
 		.maxlen		= sizeof(unsigned int),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= proc_dointvec_minmax,
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
@@ -948,7 +941,7 @@ static struct ctl_table kern_table[] = {
 		.data		= &sysctl_perf_event_sample_rate,
 		.maxlen		= sizeof(sysctl_perf_event_sample_rate),
 		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
+		.proc_handler	= perf_proc_update_handler,
 	},
 #endif
 #ifdef CONFIG_KMEMCHECK
@@ -1690,13 +1683,8 @@ static int test_perm(int mode, int op)
 
 int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
 {
-	int error;
 	int mode;
 
-	error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC));
-	if (error)
-		return error;
-
 	if (root->permissions)
 		mode = root->permissions(root, current->nsproxy, table);
 	else
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index b875bed..3b8e028 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1321,13 +1321,11 @@ static ssize_t binary_sysctl(const int *name, int nlen,
 	void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
 {
 	const struct bin_table *table = NULL;
-	struct nameidata nd;
 	struct vfsmount *mnt;
 	struct file *file;
 	ssize_t result;
 	char *pathname;
 	int flags;
-	int acc_mode;
 
 	pathname = sysctl_getname(name, nlen, &table);
 	result = PTR_ERR(pathname);
@@ -1337,28 +1335,17 @@ static ssize_t binary_sysctl(const int *name, int nlen,
 	/* How should the sysctl be accessed? */
 	if (oldval && oldlen && newval && newlen) {
 		flags = O_RDWR;
-		acc_mode = MAY_READ | MAY_WRITE;
 	} else if (newval && newlen) {
 		flags = O_WRONLY;
-		acc_mode = MAY_WRITE;
 	} else if (oldval && oldlen) {
 		flags = O_RDONLY;
-		acc_mode = MAY_READ;
 	} else {
 		result = 0;
 		goto out_putname;
 	}
 
 	mnt = current->nsproxy->pid_ns->proc_mnt;
-	result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
-	if (result)
-		goto out_putname;
-
-	result = may_open(&nd.path, acc_mode, flags);
-	if (result)
-		goto out_putpath;
-
-	file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
+	file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
 	result = PTR_ERR(file);
 	if (IS_ERR(file))
 		goto out_putname;
@@ -1370,10 +1357,6 @@ out_putname:
 	putname(pathname);
 out:
 	return result;
-
-out_putpath:
-	path_put(&nd.path);
-	goto out_putname;
 }
 
 
diff --git a/kernel/time.c b/kernel/time.c
index 3217435..8e8dc6d 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -150,7 +150,7 @@ static inline void warp_clock(void)
  * various programs will get confused when the clock gets warped.
  */
 
-int do_sys_settimeofday(struct timespec *tv, struct timezone *tz)
+int do_sys_settimeofday(const struct timespec *tv, const struct timezone *tz)
 {
 	static int firsttime = 1;
 	int error = 0;
@@ -645,7 +645,7 @@ u64 nsec_to_clock_t(u64 x)
 }
 
 /**
- * nsecs_to_jiffies - Convert nsecs in u64 to jiffies
+ * nsecs_to_jiffies64 - Convert nsecs in u64 to jiffies64
  *
  * @n:	nsecs in u64
  *
@@ -657,7 +657,7 @@ u64 nsec_to_clock_t(u64 x)
  *   NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
  *   ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
  */
-unsigned long nsecs_to_jiffies(u64 n)
+u64 nsecs_to_jiffies64(u64 n)
 {
 #if (NSEC_PER_SEC % HZ) == 0
 	/* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */
@@ -674,22 +674,23 @@ unsigned long nsecs_to_jiffies(u64 n)
 #endif
 }
 
-#if (BITS_PER_LONG < 64)
-u64 get_jiffies_64(void)
+/**
+ * nsecs_to_jiffies - Convert nsecs in u64 to jiffies
+ *
+ * @n:	nsecs in u64
+ *
+ * Unlike {m,u}secs_to_jiffies, type of input is not unsigned int but u64.
+ * And this doesn't return MAX_JIFFY_OFFSET since this function is designed
+ * for scheduler, not for use in device drivers to calculate timeout value.
+ *
+ * note:
+ *   NSEC_PER_SEC = 10^9 = (5^9 * 2^9) = (1953125 * 512)
+ *   ULLONG_MAX ns = 18446744073.709551615 secs = about 584 years
+ */
+unsigned long nsecs_to_jiffies(u64 n)
 {
-	unsigned long seq;
-	u64 ret;
-
-	do {
-		seq = read_seqbegin(&xtime_lock);
-		ret = jiffies_64;
-	} while (read_seqretry(&xtime_lock, seq));
-	return ret;
+	return (unsigned long)nsecs_to_jiffies64(n);
 }
-EXPORT_SYMBOL(get_jiffies_64);
-#endif
-
-EXPORT_SYMBOL(jiffies);
 
 /*
  * Add two timespec values and do a safety check for overflow.
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index ee26662..b042599 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,4 +1,5 @@
-obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o timeconv.o
+obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o
+obj-y += timeconv.o posix-clock.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)		+= clockevents.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS)		+= tick-common.o
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index d7395fd..0d74b9b 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -18,7 +18,6 @@
 #include <linux/notifier.h>
 #include <linux/smp.h>
 #include <linux/sysdev.h>
-#include <linux/tick.h>
 
 #include "tick-internal.h"
 
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index 5404a84..b2fa506 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -22,8 +22,11 @@
 ************************************************************************/
 #include <linux/clocksource.h>
 #include <linux/jiffies.h>
+#include <linux/module.h>
 #include <linux/init.h>
 
+#include "tick-internal.h"
+
 /* The Jiffies based clocksource is the lowest common
  * denominator clock source which should function on
  * all systems. It has the same coarse resolution as
@@ -64,6 +67,23 @@ struct clocksource clocksource_jiffies = {
 	.shift		= JIFFIES_SHIFT,
 };
 
+#if (BITS_PER_LONG < 64)
+u64 get_jiffies_64(void)
+{
+	unsigned long seq;
+	u64 ret;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		ret = jiffies_64;
+	} while (read_seqretry(&xtime_lock, seq));
+	return ret;
+}
+EXPORT_SYMBOL(get_jiffies_64);
+#endif
+
+EXPORT_SYMBOL(jiffies);
+
 static int __init init_jiffies_clocksource(void)
 {
 	return clocksource_register(&clocksource_jiffies);
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 5c00242..5f1bb8e 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -16,6 +16,8 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 
+#include "tick-internal.h"
+
 /*
  * NTP timekeeping variables:
  */
@@ -646,6 +648,17 @@ int do_adjtimex(struct timex *txc)
 			hrtimer_cancel(&leap_timer);
 	}
 
+	if (txc->modes & ADJ_SETOFFSET) {
+		struct timespec delta;
+		delta.tv_sec  = txc->time.tv_sec;
+		delta.tv_nsec = txc->time.tv_usec;
+		if (!(txc->modes & ADJ_NANO))
+			delta.tv_nsec *= 1000;
+		result = timekeeping_inject_offset(&delta);
+		if (result)
+			return result;
+	}
+
 	getnstimeofday(&ts);
 
 	write_seqlock_irq(&xtime_lock);
diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c
new file mode 100644
index 0000000..25028dd
--- /dev/null
+++ b/kernel/time/posix-clock.c
@@ -0,0 +1,451 @@
+/*
+ * posix-clock.c - support for dynamic clock devices
+ *
+ * Copyright (C) 2010 OMICRON electronics GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You 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/device.h>
+#include <linux/file.h>
+#include <linux/mutex.h>
+#include <linux/posix-clock.h>
+#include <linux/slab.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+
+static void delete_clock(struct kref *kref);
+
+/*
+ * Returns NULL if the posix_clock instance attached to 'fp' is old and stale.
+ */
+static struct posix_clock *get_posix_clock(struct file *fp)
+{
+	struct posix_clock *clk = fp->private_data;
+
+	mutex_lock(&clk->mutex);
+
+	if (!clk->zombie)
+		return clk;
+
+	mutex_unlock(&clk->mutex);
+
+	return NULL;
+}
+
+static void put_posix_clock(struct posix_clock *clk)
+{
+	mutex_unlock(&clk->mutex);
+}
+
+static ssize_t posix_clock_read(struct file *fp, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct posix_clock *clk = get_posix_clock(fp);
+	int err = -EINVAL;
+
+	if (!clk)
+		return -ENODEV;
+
+	if (clk->ops.read)
+		err = clk->ops.read(clk, fp->f_flags, buf, count);
+
+	put_posix_clock(clk);
+
+	return err;
+}
+
+static unsigned int posix_clock_poll(struct file *fp, poll_table *wait)
+{
+	struct posix_clock *clk = get_posix_clock(fp);
+	int result = 0;
+
+	if (!clk)
+		return -ENODEV;
+
+	if (clk->ops.poll)
+		result = clk->ops.poll(clk, fp, wait);
+
+	put_posix_clock(clk);
+
+	return result;
+}
+
+static int posix_clock_fasync(int fd, struct file *fp, int on)
+{
+	struct posix_clock *clk = get_posix_clock(fp);
+	int err = 0;
+
+	if (!clk)
+		return -ENODEV;
+
+	if (clk->ops.fasync)
+		err = clk->ops.fasync(clk, fd, fp, on);
+
+	put_posix_clock(clk);
+
+	return err;
+}
+
+static int posix_clock_mmap(struct file *fp, struct vm_area_struct *vma)
+{
+	struct posix_clock *clk = get_posix_clock(fp);
+	int err = -ENODEV;
+
+	if (!clk)
+		return -ENODEV;
+
+	if (clk->ops.mmap)
+		err = clk->ops.mmap(clk, vma);
+
+	put_posix_clock(clk);
+
+	return err;
+}
+
+static long posix_clock_ioctl(struct file *fp,
+			      unsigned int cmd, unsigned long arg)
+{
+	struct posix_clock *clk = get_posix_clock(fp);
+	int err = -ENOTTY;
+
+	if (!clk)
+		return -ENODEV;
+
+	if (clk->ops.ioctl)
+		err = clk->ops.ioctl(clk, cmd, arg);
+
+	put_posix_clock(clk);
+
+	return err;
+}
+
+#ifdef CONFIG_COMPAT
+static long posix_clock_compat_ioctl(struct file *fp,
+				     unsigned int cmd, unsigned long arg)
+{
+	struct posix_clock *clk = get_posix_clock(fp);
+	int err = -ENOTTY;
+
+	if (!clk)
+		return -ENODEV;
+
+	if (clk->ops.ioctl)
+		err = clk->ops.ioctl(clk, cmd, arg);
+
+	put_posix_clock(clk);
+
+	return err;
+}
+#endif
+
+static int posix_clock_open(struct inode *inode, struct file *fp)
+{
+	int err;
+	struct posix_clock *clk =
+		container_of(inode->i_cdev, struct posix_clock, cdev);
+
+	mutex_lock(&clk->mutex);
+
+	if (clk->zombie) {
+		err = -ENODEV;
+		goto out;
+	}
+	if (clk->ops.open)
+		err = clk->ops.open(clk, fp->f_mode);
+	else
+		err = 0;
+
+	if (!err) {
+		kref_get(&clk->kref);
+		fp->private_data = clk;
+	}
+out:
+	mutex_unlock(&clk->mutex);
+	return err;
+}
+
+static int posix_clock_release(struct inode *inode, struct file *fp)
+{
+	struct posix_clock *clk = fp->private_data;
+	int err = 0;
+
+	if (clk->ops.release)
+		err = clk->ops.release(clk);
+
+	kref_put(&clk->kref, delete_clock);
+
+	fp->private_data = NULL;
+
+	return err;
+}
+
+static const struct file_operations posix_clock_file_operations = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.read		= posix_clock_read,
+	.poll		= posix_clock_poll,
+	.unlocked_ioctl	= posix_clock_ioctl,
+	.open		= posix_clock_open,
+	.release	= posix_clock_release,
+	.fasync		= posix_clock_fasync,
+	.mmap		= posix_clock_mmap,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= posix_clock_compat_ioctl,
+#endif
+};
+
+int posix_clock_register(struct posix_clock *clk, dev_t devid)
+{
+	int err;
+
+	kref_init(&clk->kref);
+	mutex_init(&clk->mutex);
+
+	cdev_init(&clk->cdev, &posix_clock_file_operations);
+	clk->cdev.owner = clk->ops.owner;
+	err = cdev_add(&clk->cdev, devid, 1);
+	if (err)
+		goto no_cdev;
+
+	return err;
+no_cdev:
+	mutex_destroy(&clk->mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(posix_clock_register);
+
+static void delete_clock(struct kref *kref)
+{
+	struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
+	mutex_destroy(&clk->mutex);
+	if (clk->release)
+		clk->release(clk);
+}
+
+void posix_clock_unregister(struct posix_clock *clk)
+{
+	cdev_del(&clk->cdev);
+
+	mutex_lock(&clk->mutex);
+	clk->zombie = true;
+	mutex_unlock(&clk->mutex);
+
+	kref_put(&clk->kref, delete_clock);
+}
+EXPORT_SYMBOL_GPL(posix_clock_unregister);
+
+struct posix_clock_desc {
+	struct file *fp;
+	struct posix_clock *clk;
+};
+
+static int get_clock_desc(const clockid_t id, struct posix_clock_desc *cd)
+{
+	struct file *fp = fget(CLOCKID_TO_FD(id));
+	int err = -EINVAL;
+
+	if (!fp)
+		return err;
+
+	if (fp->f_op->open != posix_clock_open || !fp->private_data)
+		goto out;
+
+	cd->fp = fp;
+	cd->clk = get_posix_clock(fp);
+
+	err = cd->clk ? 0 : -ENODEV;
+out:
+	if (err)
+		fput(fp);
+	return err;
+}
+
+static void put_clock_desc(struct posix_clock_desc *cd)
+{
+	put_posix_clock(cd->clk);
+	fput(cd->fp);
+}
+
+static int pc_clock_adjtime(clockid_t id, struct timex *tx)
+{
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if ((cd.fp->f_mode & FMODE_WRITE) == 0) {
+		err = -EACCES;
+		goto out;
+	}
+
+	if (cd.clk->ops.clock_adjtime)
+		err = cd.clk->ops.clock_adjtime(cd.clk, tx);
+	else
+		err = -EOPNOTSUPP;
+out:
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+static int pc_clock_gettime(clockid_t id, struct timespec *ts)
+{
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if (cd.clk->ops.clock_gettime)
+		err = cd.clk->ops.clock_gettime(cd.clk, ts);
+	else
+		err = -EOPNOTSUPP;
+
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+static int pc_clock_getres(clockid_t id, struct timespec *ts)
+{
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if (cd.clk->ops.clock_getres)
+		err = cd.clk->ops.clock_getres(cd.clk, ts);
+	else
+		err = -EOPNOTSUPP;
+
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+static int pc_clock_settime(clockid_t id, const struct timespec *ts)
+{
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if ((cd.fp->f_mode & FMODE_WRITE) == 0) {
+		err = -EACCES;
+		goto out;
+	}
+
+	if (cd.clk->ops.clock_settime)
+		err = cd.clk->ops.clock_settime(cd.clk, ts);
+	else
+		err = -EOPNOTSUPP;
+out:
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+static int pc_timer_create(struct k_itimer *kit)
+{
+	clockid_t id = kit->it_clock;
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if (cd.clk->ops.timer_create)
+		err = cd.clk->ops.timer_create(cd.clk, kit);
+	else
+		err = -EOPNOTSUPP;
+
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+static int pc_timer_delete(struct k_itimer *kit)
+{
+	clockid_t id = kit->it_clock;
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if (cd.clk->ops.timer_delete)
+		err = cd.clk->ops.timer_delete(cd.clk, kit);
+	else
+		err = -EOPNOTSUPP;
+
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+static void pc_timer_gettime(struct k_itimer *kit, struct itimerspec *ts)
+{
+	clockid_t id = kit->it_clock;
+	struct posix_clock_desc cd;
+
+	if (get_clock_desc(id, &cd))
+		return;
+
+	if (cd.clk->ops.timer_gettime)
+		cd.clk->ops.timer_gettime(cd.clk, kit, ts);
+
+	put_clock_desc(&cd);
+}
+
+static int pc_timer_settime(struct k_itimer *kit, int flags,
+			    struct itimerspec *ts, struct itimerspec *old)
+{
+	clockid_t id = kit->it_clock;
+	struct posix_clock_desc cd;
+	int err;
+
+	err = get_clock_desc(id, &cd);
+	if (err)
+		return err;
+
+	if (cd.clk->ops.timer_settime)
+		err = cd.clk->ops.timer_settime(cd.clk, kit, flags, ts, old);
+	else
+		err = -EOPNOTSUPP;
+
+	put_clock_desc(&cd);
+
+	return err;
+}
+
+struct k_clock clock_posix_dynamic = {
+	.clock_getres	= pc_clock_getres,
+	.clock_set	= pc_clock_settime,
+	.clock_get	= pc_clock_gettime,
+	.clock_adj	= pc_clock_adjtime,
+	.timer_create	= pc_timer_create,
+	.timer_set	= pc_timer_settime,
+	.timer_del	= pc_timer_delete,
+	.timer_get	= pc_timer_gettime,
+};
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index a3b5aff..da800ff 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -18,7 +18,6 @@
 #include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
-#include <linux/tick.h>
 
 #include "tick-internal.h"
 
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c
index ed228ef..119528d 100644
--- a/kernel/time/tick-common.c
+++ b/kernel/time/tick-common.c
@@ -18,7 +18,6 @@
 #include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
-#include <linux/tick.h>
 
 #include <asm/irq_regs.h>
 
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index f65d3a7..1009b06 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -1,6 +1,10 @@
 /*
  * tick internal variable and functions used by low/high res code
  */
+#include <linux/hrtimer.h>
+#include <linux/tick.h>
+
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BUILD
 
 #define TICK_DO_TIMER_NONE	-1
 #define TICK_DO_TIMER_BOOT	-2
@@ -135,3 +139,8 @@ static inline int tick_device_is_functional(struct clock_event_device *dev)
 {
 	return !(dev->features & CLOCK_EVT_FEAT_DUMMY);
 }
+
+#endif
+
+extern void do_timer(unsigned long ticks);
+extern seqlock_t xtime_lock;
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c
index 5cbc101..2d04411 100644
--- a/kernel/time/tick-oneshot.c
+++ b/kernel/time/tick-oneshot.c
@@ -18,7 +18,6 @@
 #include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
-#include <linux/tick.h>
 
 #include "tick-internal.h"
 
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index c55ea24..d5097c4 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -19,7 +19,6 @@
 #include <linux/percpu.h>
 #include <linux/profile.h>
 #include <linux/sched.h>
-#include <linux/tick.h>
 #include <linux/module.h>
 
 #include <asm/irq_regs.h>
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d27c756..3bd7e3d 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -353,7 +353,7 @@ EXPORT_SYMBOL(do_gettimeofday);
  *
  * Sets the time of day to the new time and update NTP and notify hrtimers
  */
-int do_settimeofday(struct timespec *tv)
+int do_settimeofday(const struct timespec *tv)
 {
 	struct timespec ts_delta;
 	unsigned long flags;
@@ -387,6 +387,42 @@ int do_settimeofday(struct timespec *tv)
 
 EXPORT_SYMBOL(do_settimeofday);
 
+
+/**
+ * timekeeping_inject_offset - Adds or subtracts from the current time.
+ * @tv:		pointer to the timespec variable containing the offset
+ *
+ * Adds or subtracts an offset value from the current time.
+ */
+int timekeeping_inject_offset(struct timespec *ts)
+{
+	unsigned long flags;
+
+	if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	timekeeping_forward_now();
+
+	xtime = timespec_add(xtime, *ts);
+	wall_to_monotonic = timespec_sub(wall_to_monotonic, *ts);
+
+	timekeeper.ntp_error = 0;
+	ntp_clear();
+
+	update_vsyscall(&xtime, &wall_to_monotonic, timekeeper.clock,
+				timekeeper.mult);
+
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	/* signal hrtimers about time change */
+	clock_was_set();
+
+	return 0;
+}
+EXPORT_SYMBOL(timekeeping_inject_offset);
+
 /**
  * change_clocksource - Swaps clocksources if a new one is available
  *
@@ -779,7 +815,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
  *
  * Called from the timer interrupt, must hold a write on xtime_lock.
  */
-void update_wall_time(void)
+static void update_wall_time(void)
 {
 	struct clocksource *clock;
 	cycle_t offset;
@@ -871,7 +907,7 @@ void update_wall_time(void)
  * getboottime - Return the real time of system boot.
  * @ts:		pointer to the timespec to be set
  *
- * Returns the time of day in a timespec.
+ * Returns the wall-time of boot in a timespec.
  *
  * This is based on the wall_to_monotonic offset and the total suspend
  * time. Calls to settimeofday will affect the value returned (which
@@ -889,6 +925,55 @@ void getboottime(struct timespec *ts)
 }
 EXPORT_SYMBOL_GPL(getboottime);
 
+
+/**
+ * get_monotonic_boottime - Returns monotonic time since boot
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the monotonic time since boot in a timespec.
+ *
+ * This is similar to CLOCK_MONTONIC/ktime_get_ts, but also
+ * includes the time spent in suspend.
+ */
+void get_monotonic_boottime(struct timespec *ts)
+{
+	struct timespec tomono, sleep;
+	unsigned int seq;
+	s64 nsecs;
+
+	WARN_ON(timekeeping_suspended);
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		*ts = xtime;
+		tomono = wall_to_monotonic;
+		sleep = total_sleep_time;
+		nsecs = timekeeping_get_ns();
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec,
+			ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec + nsecs);
+}
+EXPORT_SYMBOL_GPL(get_monotonic_boottime);
+
+/**
+ * ktime_get_boottime - Returns monotonic time since boot in a ktime
+ *
+ * Returns the monotonic time since boot in a ktime
+ *
+ * This is similar to CLOCK_MONTONIC/ktime_get, but also
+ * includes the time spent in suspend.
+ */
+ktime_t ktime_get_boottime(void)
+{
+	struct timespec ts;
+
+	get_monotonic_boottime(&ts);
+	return timespec_to_ktime(ts);
+}
+EXPORT_SYMBOL_GPL(ktime_get_boottime);
+
 /**
  * monotonic_to_bootbased - Convert the monotonic time to boot based.
  * @ts:		pointer to the timespec to be converted
@@ -910,11 +995,6 @@ struct timespec __current_kernel_time(void)
 	return xtime;
 }
 
-struct timespec __get_wall_to_monotonic(void)
-{
-	return wall_to_monotonic;
-}
-
 struct timespec current_kernel_time(void)
 {
 	struct timespec now;
@@ -946,3 +1026,48 @@ struct timespec get_monotonic_coarse(void)
 				now.tv_nsec + mono.tv_nsec);
 	return now;
 }
+
+/*
+ * The 64-bit jiffies value is not atomic - you MUST NOT read it
+ * without sampling the sequence number in xtime_lock.
+ * jiffies is defined in the linker script...
+ */
+void do_timer(unsigned long ticks)
+{
+	jiffies_64 += ticks;
+	update_wall_time();
+	calc_global_load(ticks);
+}
+
+/**
+ * get_xtime_and_monotonic_and_sleep_offset() - get xtime, wall_to_monotonic,
+ *    and sleep offsets.
+ * @xtim:	pointer to timespec to be set with xtime
+ * @wtom:	pointer to timespec to be set with wall_to_monotonic
+ * @sleep:	pointer to timespec to be set with time in suspend
+ */
+void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
+				struct timespec *wtom, struct timespec *sleep)
+{
+	unsigned long seq;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+		*xtim = xtime;
+		*wtom = wall_to_monotonic;
+		*sleep = total_sleep_time;
+	} while (read_seqretry(&xtime_lock, seq));
+}
+
+/**
+ * xtime_update() - advances the timekeeping infrastructure
+ * @ticks:	number of ticks, that have elapsed since the last call.
+ *
+ * Must be called with interrupts disabled.
+ */
+void xtime_update(unsigned long ticks)
+{
+	write_seqlock(&xtime_lock);
+	do_timer(ticks);
+	write_sequnlock(&xtime_lock);
+}
diff --git a/kernel/timer.c b/kernel/timer.c
index d645992..fd61986 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -404,6 +404,11 @@ static void timer_stats_account_timer(struct timer_list *timer) {}
 
 static struct debug_obj_descr timer_debug_descr;
 
+static void *timer_debug_hint(void *addr)
+{
+	return ((struct timer_list *) addr)->function;
+}
+
 /*
  * fixup_init is called when:
  * - an active object is initialized
@@ -477,6 +482,7 @@ static int timer_fixup_free(void *addr, enum debug_obj_state state)
 
 static struct debug_obj_descr timer_debug_descr = {
 	.name		= "timer_list",
+	.debug_hint	= timer_debug_hint,
 	.fixup_init	= timer_fixup_init,
 	.fixup_activate	= timer_fixup_activate,
 	.fixup_free	= timer_fixup_free,
@@ -964,6 +970,25 @@ EXPORT_SYMBOL(try_to_del_timer_sync);
  * add_timer_on(). Upon exit the timer is not queued and the handler is
  * not running on any CPU.
  *
+ * Note: You must not hold locks that are held in interrupt context
+ *   while calling this function. Even if the lock has nothing to do
+ *   with the timer in question.  Here's why:
+ *
+ *    CPU0                             CPU1
+ *    ----                             ----
+ *                                   <SOFTIRQ>
+ *                                   call_timer_fn();
+ *                                     base->running_timer = mytimer;
+ *  spin_lock_irq(somelock);
+ *                                     <IRQ>
+ *                                        spin_lock(somelock);
+ *  del_timer_sync(mytimer);
+ *   while (base->running_timer == mytimer);
+ *
+ * Now del_timer_sync() will never return and never release somelock.
+ * The interrupt on the other CPU is waiting to grab somelock but
+ * it has interrupted the softirq that CPU0 is waiting to finish.
+ *
  * The function returns whether it has deactivated a pending timer or not.
  */
 int del_timer_sync(struct timer_list *timer)
@@ -971,6 +996,10 @@ int del_timer_sync(struct timer_list *timer)
 #ifdef CONFIG_LOCKDEP
 	unsigned long flags;
 
+	/*
+	 * If lockdep gives a backtrace here, please reference
+	 * the synchronization rules above.
+	 */
 	local_irq_save(flags);
 	lock_map_acquire(&timer->lockdep_map);
 	lock_map_release(&timer->lockdep_map);
@@ -1295,19 +1324,6 @@ void run_local_timers(void)
 	raise_softirq(TIMER_SOFTIRQ);
 }
 
-/*
- * The 64-bit jiffies value is not atomic - you MUST NOT read it
- * without sampling the sequence number in xtime_lock.
- * jiffies is defined in the linker script...
- */
-
-void do_timer(unsigned long ticks)
-{
-	jiffies_64 += ticks;
-	update_wall_time();
-	calc_global_load(ticks);
-}
-
 #ifdef __ARCH_WANT_SYS_ALARM
 
 /*
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 14674dc..61d7d59f 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -275,7 +275,7 @@ config PROFILE_ANNOTATED_BRANCHES
 	  This tracer profiles all the the likely and unlikely macros
 	  in the kernel. It will display the results in:
 
-	  /sys/kernel/debug/tracing/profile_annotated_branch
+	  /sys/kernel/debug/tracing/trace_stat/branch_annotated
 
 	  Note: this will add a significant overhead; only turn this
 	  on if you need to profile the system's use of these macros.
@@ -288,7 +288,7 @@ config PROFILE_ALL_BRANCHES
 	  taken in the kernel is recorded whether it hit or miss.
 	  The results will be displayed in:
 
-	  /sys/kernel/debug/tracing/profile_branch
+	  /sys/kernel/debug/tracing/trace_stat/branch_all
 
 	  This option also enables the likely/unlikely profiler.
 
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f3dadae..888b611 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3328,7 +3328,7 @@ static int start_graph_tracing(void)
 	/* The cpu_boot init_task->ret_stack will never be freed */
 	for_each_online_cpu(cpu) {
 		if (!idle_task(cpu)->ret_stack)
-			ftrace_graph_init_task(idle_task(cpu));
+			ftrace_graph_init_idle_task(idle_task(cpu), cpu);
 	}
 
 	do {
@@ -3418,6 +3418,49 @@ void unregister_ftrace_graph(void)
 	mutex_unlock(&ftrace_lock);
 }
 
+static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack);
+
+static void
+graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
+{
+	atomic_set(&t->tracing_graph_pause, 0);
+	atomic_set(&t->trace_overrun, 0);
+	t->ftrace_timestamp = 0;
+	/* make curr_ret_stack visable before we add the ret_stack */
+	smp_wmb();
+	t->ret_stack = ret_stack;
+}
+
+/*
+ * Allocate a return stack for the idle task. May be the first
+ * time through, or it may be done by CPU hotplug online.
+ */
+void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
+{
+	t->curr_ret_stack = -1;
+	/*
+	 * The idle task has no parent, it either has its own
+	 * stack or no stack at all.
+	 */
+	if (t->ret_stack)
+		WARN_ON(t->ret_stack != per_cpu(idle_ret_stack, cpu));
+
+	if (ftrace_graph_active) {
+		struct ftrace_ret_stack *ret_stack;
+
+		ret_stack = per_cpu(idle_ret_stack, cpu);
+		if (!ret_stack) {
+			ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
+					    * sizeof(struct ftrace_ret_stack),
+					    GFP_KERNEL);
+			if (!ret_stack)
+				return;
+			per_cpu(idle_ret_stack, cpu) = ret_stack;
+		}
+		graph_init_task(t, ret_stack);
+	}
+}
+
 /* Allocate a return stack for newly created task */
 void ftrace_graph_init_task(struct task_struct *t)
 {
@@ -3433,12 +3476,7 @@ void ftrace_graph_init_task(struct task_struct *t)
 				GFP_KERNEL);
 		if (!ret_stack)
 			return;
-		atomic_set(&t->tracing_graph_pause, 0);
-		atomic_set(&t->trace_overrun, 0);
-		t->ftrace_timestamp = 0;
-		/* make curr_ret_stack visable before we add the ret_stack */
-		smp_wmb();
-		t->ret_stack = ret_stack;
+		graph_init_task(t, ret_stack);
 	}
 }
 
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index bd1c35a..d9c8bca 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -5,7 +5,6 @@
  */
 #include <linux/ring_buffer.h>
 #include <linux/trace_clock.h>
-#include <linux/ftrace_irq.h>
 #include <linux/spinlock.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
@@ -669,7 +668,7 @@ static struct list_head *rb_list_head(struct list_head *list)
  * the reader page). But if the next page is a header page,
  * its flags will be non zero.
  */
-static int inline
+static inline int
 rb_is_head_page(struct ring_buffer_per_cpu *cpu_buffer,
 		struct buffer_page *page, struct list_head *list)
 {
@@ -1429,6 +1428,17 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size)
 }
 EXPORT_SYMBOL_GPL(ring_buffer_resize);
 
+void ring_buffer_change_overwrite(struct ring_buffer *buffer, int val)
+{
+	mutex_lock(&buffer->mutex);
+	if (val)
+		buffer->flags |= RB_FL_OVERWRITE;
+	else
+		buffer->flags &= ~RB_FL_OVERWRITE;
+	mutex_unlock(&buffer->mutex);
+}
+EXPORT_SYMBOL_GPL(ring_buffer_change_overwrite);
+
 static inline void *
 __rb_data_page_index(struct buffer_data_page *bpage, unsigned index)
 {
@@ -2162,11 +2172,19 @@ rb_reserve_next_event(struct ring_buffer *buffer,
 	if (likely(ts >= cpu_buffer->write_stamp)) {
 		delta = diff;
 		if (unlikely(test_time_stamp(delta))) {
+			int local_clock_stable = 1;
+#ifdef CONFIG_HAVE_UNSTABLE_SCHED_CLOCK
+			local_clock_stable = sched_clock_stable;
+#endif
 			WARN_ONCE(delta > (1ULL << 59),
-				  KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n",
+				  KERN_WARNING "Delta way too big! %llu ts=%llu write stamp = %llu\n%s",
 				  (unsigned long long)delta,
 				  (unsigned long long)ts,
-				  (unsigned long long)cpu_buffer->write_stamp);
+				  (unsigned long long)cpu_buffer->write_stamp,
+				  local_clock_stable ? "" :
+				  "If you just came from a suspend/resume,\n"
+				  "please switch to the trace global clock:\n"
+				  "  echo global > /sys/kernel/debug/tracing/trace_clock\n");
 			add_timestamp = 1;
 		}
 	}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index dc53ecb..9541c27 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -41,8 +41,6 @@
 #include "trace.h"
 #include "trace_output.h"
 
-#define TRACE_BUFFER_FLAGS	(RB_FL_OVERWRITE)
-
 /*
  * 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.
@@ -340,7 +338,7 @@ 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_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE;
 
 static int trace_stop_count;
 static DEFINE_SPINLOCK(tracing_start_lock);
@@ -425,6 +423,7 @@ static const char *trace_options[] = {
 	"sleep-time",
 	"graph-time",
 	"record-cmd",
+	"overwrite",
 	NULL
 };
 
@@ -780,6 +779,11 @@ __acquires(kernel_lock)
 		tracing_reset_online_cpus(tr);
 
 		current_trace = type;
+
+		/* If we expanded the buffers, make sure the max is expanded too */
+		if (ring_buffer_expanded && type->use_max_tr)
+			ring_buffer_resize(max_tr.buffer, trace_buf_size);
+
 		/* the test is responsible for initializing and enabling */
 		pr_info("Testing tracer %s: ", type->name);
 		ret = type->selftest(type, tr);
@@ -792,6 +796,10 @@ __acquires(kernel_lock)
 		/* Only reset on passing, to avoid touching corrupted buffers */
 		tracing_reset_online_cpus(tr);
 
+		/* Shrink the max buffer again */
+		if (ring_buffer_expanded && type->use_max_tr)
+			ring_buffer_resize(max_tr.buffer, 1);
+
 		printk(KERN_CONT "PASSED\n");
 	}
 #endif
@@ -1102,7 +1110,6 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags,
 
 	entry->preempt_count		= pc & 0xff;
 	entry->pid			= (tsk) ? tsk->pid : 0;
-	entry->lock_depth		= (tsk) ? tsk->lock_depth : 0;
 	entry->flags =
 #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT
 		(irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
@@ -1749,10 +1756,9 @@ static void print_lat_help_header(struct seq_file *m)
 	seq_puts(m, "#                | / _----=> need-resched    \n");
 	seq_puts(m, "#                || / _---=> hardirq/softirq \n");
 	seq_puts(m, "#                ||| / _--=> preempt-depth   \n");
-	seq_puts(m, "#                |||| /_--=> lock-depth       \n");
-	seq_puts(m, "#                |||||/     delay             \n");
-	seq_puts(m, "#  cmd     pid   |||||| time  |   caller      \n");
-	seq_puts(m, "#     \\   /      ||||||   \\   |   /           \n");
+	seq_puts(m, "#                |||| /     delay             \n");
+	seq_puts(m, "#  cmd     pid   ||||| time  |   caller      \n");
+	seq_puts(m, "#     \\   /      |||||  \\    |   /           \n");
 }
 
 static void print_func_help_header(struct seq_file *m)
@@ -2529,6 +2535,9 @@ static void set_tracer_flags(unsigned int mask, int enabled)
 
 	if (mask == TRACE_ITER_RECORD_CMD)
 		trace_event_enable_cmd_record(enabled);
+
+	if (mask == TRACE_ITER_OVERWRITE)
+		ring_buffer_change_overwrite(global_trace.buffer, enabled);
 }
 
 static ssize_t
@@ -2710,6 +2719,10 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf,
 
 	mutex_lock(&trace_types_lock);
 	if (tracer_enabled ^ val) {
+
+		/* Only need to warn if this is used to change the state */
+		WARN_ONCE(1, "tracing_enabled is deprecated. Use tracing_on");
+
 		if (val) {
 			tracer_enabled = 1;
 			if (current_trace->start)
@@ -4551,9 +4564,11 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode)
 __init static int tracer_alloc_buffers(void)
 {
 	int ring_buf_size;
+	enum ring_buffer_flags rb_flags;
 	int i;
 	int ret = -ENOMEM;
 
+
 	if (!alloc_cpumask_var(&tracing_buffer_mask, GFP_KERNEL))
 		goto out;
 
@@ -4566,12 +4581,13 @@ __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);
 
 	/* TODO: make the number of buffers hot pluggable with CPUS */
-	global_trace.buffer = ring_buffer_alloc(ring_buf_size,
-						   TRACE_BUFFER_FLAGS);
+	global_trace.buffer = ring_buffer_alloc(ring_buf_size, rb_flags);
 	if (!global_trace.buffer) {
 		printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
 		WARN_ON(1);
@@ -4581,7 +4597,7 @@ __init static int tracer_alloc_buffers(void)
 
 
 #ifdef CONFIG_TRACER_MAX_TRACE
-	max_tr.buffer = ring_buffer_alloc(1, TRACE_BUFFER_FLAGS);
+	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);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 9021f8c..5e9dfc6 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -272,8 +272,8 @@ struct tracer {
 	/* If you handled the flag setting, return 0 */
 	int			(*set_flag)(u32 old_flags, u32 bit, int set);
 	struct tracer		*next;
-	int			print_max;
 	struct tracer_flags	*flags;
+	int			print_max;
 	int			use_max_tr;
 };
 
@@ -606,6 +606,7 @@ enum trace_iterator_flags {
 	TRACE_ITER_SLEEP_TIME		= 0x40000,
 	TRACE_ITER_GRAPH_TIME		= 0x80000,
 	TRACE_ITER_RECORD_CMD		= 0x100000,
+	TRACE_ITER_OVERWRITE		= 0x200000,
 };
 
 /*
@@ -661,8 +662,10 @@ struct ftrace_event_field {
 };
 
 struct event_filter {
-	int			n_preds;
-	struct filter_pred	**preds;
+	int			n_preds;	/* Number assigned */
+	int			a_preds;	/* allocated */
+	struct filter_pred	*preds;
+	struct filter_pred	*root;
 	char			*filter_string;
 };
 
@@ -674,11 +677,23 @@ struct event_subsystem {
 	int			nr_events;
 };
 
+#define FILTER_PRED_INVALID	((unsigned short)-1)
+#define FILTER_PRED_IS_RIGHT	(1 << 15)
+#define FILTER_PRED_FOLD	(1 << 15)
+
+/*
+ * The max preds is the size of unsigned short with
+ * two flags at the MSBs. One bit is used for both the IS_RIGHT
+ * and FOLD flags. The other is reserved.
+ *
+ * 2^14 preds is way more than enough.
+ */
+#define MAX_FILTER_PRED		16384
+
 struct filter_pred;
 struct regex;
 
-typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
-				 int val1, int val2);
+typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
 
 typedef int (*regex_match_func)(char *str, struct regex *r, int len);
 
@@ -700,11 +715,23 @@ struct filter_pred {
 	filter_pred_fn_t 	fn;
 	u64 			val;
 	struct regex		regex;
-	char 			*field_name;
+	/*
+	 * Leaf nodes use field_name, ops is used by AND and OR
+	 * nodes. The field_name is always freed when freeing a pred.
+	 * We can overload field_name for ops and have it freed
+	 * as well.
+	 */
+	union {
+		char		*field_name;
+		unsigned short	*ops;
+	};
 	int 			offset;
 	int 			not;
 	int 			op;
-	int 			pop_n;
+	unsigned short		index;
+	unsigned short		parent;
+	unsigned short		left;
+	unsigned short		right;
 };
 
 extern struct list_head ftrace_common_fields;
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index 6cf2237..1516cb3 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -109,12 +109,12 @@ FTRACE_ENTRY(funcgraph_exit, ftrace_graph_ret_entry,
  */
 #define FTRACE_CTX_FIELDS					\
 	__field(	unsigned int,	prev_pid	)	\
+	__field(	unsigned int,	next_pid	)	\
+	__field(	unsigned int,	next_cpu	)       \
 	__field(	unsigned char,	prev_prio	)	\
 	__field(	unsigned char,	prev_state	)	\
-	__field(	unsigned int,	next_pid	)	\
 	__field(	unsigned char,	next_prio	)	\
-	__field(	unsigned char,	next_state	)	\
-	__field(	unsigned int,	next_cpu	)
+	__field(	unsigned char,	next_state	)
 
 FTRACE_ENTRY(context_switch, ctx_switch_entry,
 
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 5f499e0..e88f74f 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -116,7 +116,6 @@ static int trace_define_common_fields(void)
 	__common_field(unsigned char, flags);
 	__common_field(unsigned char, preempt_count);
 	__common_field(int, pid);
-	__common_field(int, lock_depth);
 
 	return ret;
 }
@@ -326,6 +325,7 @@ int trace_set_clr_event(const char *system, const char *event, int set)
 {
 	return __ftrace_set_clr_event(NULL, system, event, set);
 }
+EXPORT_SYMBOL_GPL(trace_set_clr_event);
 
 /* 128 should be much more than enough */
 #define EVENT_BUF_SIZE		127
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 36d4010..8008ddc 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -123,9 +123,13 @@ struct filter_parse_state {
 	} operand;
 };
 
+struct pred_stack {
+	struct filter_pred	**preds;
+	int			index;
+};
+
 #define DEFINE_COMPARISON_PRED(type)					\
-static int filter_pred_##type(struct filter_pred *pred, void *event,	\
-			      int val1, int val2)			\
+static int filter_pred_##type(struct filter_pred *pred, void *event)	\
 {									\
 	type *addr = (type *)(event + pred->offset);			\
 	type val = (type)pred->val;					\
@@ -152,8 +156,7 @@ static int filter_pred_##type(struct filter_pred *pred, void *event,	\
 }
 
 #define DEFINE_EQUALITY_PRED(size)					\
-static int filter_pred_##size(struct filter_pred *pred, void *event,	\
-			      int val1, int val2)			\
+static int filter_pred_##size(struct filter_pred *pred, void *event)	\
 {									\
 	u##size *addr = (u##size *)(event + pred->offset);		\
 	u##size val = (u##size)pred->val;				\
@@ -178,23 +181,8 @@ DEFINE_EQUALITY_PRED(32);
 DEFINE_EQUALITY_PRED(16);
 DEFINE_EQUALITY_PRED(8);
 
-static int filter_pred_and(struct filter_pred *pred __attribute((unused)),
-			   void *event __attribute((unused)),
-			   int val1, int val2)
-{
-	return val1 && val2;
-}
-
-static int filter_pred_or(struct filter_pred *pred __attribute((unused)),
-			  void *event __attribute((unused)),
-			  int val1, int val2)
-{
-	return val1 || val2;
-}
-
 /* Filter predicate for fixed sized arrays of characters */
-static int filter_pred_string(struct filter_pred *pred, void *event,
-			      int val1, int val2)
+static int filter_pred_string(struct filter_pred *pred, void *event)
 {
 	char *addr = (char *)(event + pred->offset);
 	int cmp, match;
@@ -207,8 +195,7 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
 }
 
 /* Filter predicate for char * pointers */
-static int filter_pred_pchar(struct filter_pred *pred, void *event,
-			     int val1, int val2)
+static int filter_pred_pchar(struct filter_pred *pred, void *event)
 {
 	char **addr = (char **)(event + pred->offset);
 	int cmp, match;
@@ -231,8 +218,7 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,
  * and add it to the address of the entry, and at last we have
  * the address of the string.
  */
-static int filter_pred_strloc(struct filter_pred *pred, void *event,
-			      int val1, int val2)
+static int filter_pred_strloc(struct filter_pred *pred, void *event)
 {
 	u32 str_item = *(u32 *)(event + pred->offset);
 	int str_loc = str_item & 0xffff;
@@ -247,8 +233,7 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event,
 	return match;
 }
 
-static int filter_pred_none(struct filter_pred *pred, void *event,
-			    int val1, int val2)
+static int filter_pred_none(struct filter_pred *pred, void *event)
 {
 	return 0;
 }
@@ -377,32 +362,147 @@ static void filter_build_regex(struct filter_pred *pred)
 	pred->not ^= not;
 }
 
+enum move_type {
+	MOVE_DOWN,
+	MOVE_UP_FROM_LEFT,
+	MOVE_UP_FROM_RIGHT
+};
+
+static struct filter_pred *
+get_pred_parent(struct filter_pred *pred, struct filter_pred *preds,
+		int index, enum move_type *move)
+{
+	if (pred->parent & FILTER_PRED_IS_RIGHT)
+		*move = MOVE_UP_FROM_RIGHT;
+	else
+		*move = MOVE_UP_FROM_LEFT;
+	pred = &preds[pred->parent & ~FILTER_PRED_IS_RIGHT];
+
+	return pred;
+}
+
+/*
+ * A series of AND or ORs where found together. Instead of
+ * climbing up and down the tree branches, an array of the
+ * ops were made in order of checks. We can just move across
+ * the array and short circuit if needed.
+ */
+static int process_ops(struct filter_pred *preds,
+		       struct filter_pred *op, void *rec)
+{
+	struct filter_pred *pred;
+	int match = 0;
+	int type;
+	int i;
+
+	/*
+	 * Micro-optimization: We set type to true if op
+	 * is an OR and false otherwise (AND). Then we
+	 * just need to test if the match is equal to
+	 * the type, and if it is, we can short circuit the
+	 * rest of the checks:
+	 *
+	 * if ((match && op->op == OP_OR) ||
+	 *     (!match && op->op == OP_AND))
+	 *	  return match;
+	 */
+	type = op->op == OP_OR;
+
+	for (i = 0; i < op->val; i++) {
+		pred = &preds[op->ops[i]];
+		match = pred->fn(pred, rec);
+		if (!!match == type)
+			return match;
+	}
+	return match;
+}
+
 /* return 1 if event matches, 0 otherwise (discard) */
 int filter_match_preds(struct event_filter *filter, void *rec)
 {
-	int match, top = 0, val1 = 0, val2 = 0;
-	int stack[MAX_FILTER_PRED];
+	int match = -1;
+	enum move_type move = MOVE_DOWN;
+	struct filter_pred *preds;
 	struct filter_pred *pred;
-	int i;
+	struct filter_pred *root;
+	int n_preds;
+	int done = 0;
+
+	/* no filter is considered a match */
+	if (!filter)
+		return 1;
+
+	n_preds = filter->n_preds;
+
+	if (!n_preds)
+		return 1;
+
+	/*
+	 * n_preds, root and filter->preds are protect with preemption disabled.
+	 */
+	preds = rcu_dereference_sched(filter->preds);
+	root = rcu_dereference_sched(filter->root);
+	if (!root)
+		return 1;
+
+	pred = root;
 
-	for (i = 0; i < filter->n_preds; i++) {
-		pred = filter->preds[i];
-		if (!pred->pop_n) {
-			match = pred->fn(pred, rec, val1, val2);
-			stack[top++] = match;
+	/* match is currently meaningless */
+	match = -1;
+
+	do {
+		switch (move) {
+		case MOVE_DOWN:
+			/* only AND and OR have children */
+			if (pred->left != FILTER_PRED_INVALID) {
+				/* If ops is set, then it was folded. */
+				if (!pred->ops) {
+					/* keep going to down the left side */
+					pred = &preds[pred->left];
+					continue;
+				}
+				/* We can treat folded ops as a leaf node */
+				match = process_ops(preds, pred, rec);
+			} else
+				match = pred->fn(pred, rec);
+			/* If this pred is the only pred */
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		case MOVE_UP_FROM_LEFT:
+			/*
+			 * Check for short circuits.
+			 *
+			 * Optimization: !!match == (pred->op == OP_OR)
+			 *   is the same as:
+			 * if ((match && pred->op == OP_OR) ||
+			 *     (!match && pred->op == OP_AND))
+			 */
+			if (!!match == (pred->op == OP_OR)) {
+				if (pred == root)
+					break;
+				pred = get_pred_parent(pred, preds,
+						       pred->parent, &move);
+				continue;
+			}
+			/* now go down the right side of the tree. */
+			pred = &preds[pred->right];
+			move = MOVE_DOWN;
+			continue;
+		case MOVE_UP_FROM_RIGHT:
+			/* We finished this equation. */
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
 			continue;
 		}
-		if (pred->pop_n > top) {
-			WARN_ON_ONCE(1);
-			return 0;
-		}
-		val1 = stack[--top];
-		val2 = stack[--top];
-		match = pred->fn(pred, rec, val1, val2);
-		stack[top++] = match;
-	}
+		done = 1;
+	} while (!done);
 
-	return stack[--top];
+	return match;
 }
 EXPORT_SYMBOL_GPL(filter_match_preds);
 
@@ -414,6 +514,9 @@ static void parse_error(struct filter_parse_state *ps, int err, int pos)
 
 static void remove_filter_string(struct event_filter *filter)
 {
+	if (!filter)
+		return;
+
 	kfree(filter->filter_string);
 	filter->filter_string = NULL;
 }
@@ -473,9 +576,10 @@ static void append_filter_err(struct filter_parse_state *ps,
 
 void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
 {
-	struct event_filter *filter = call->filter;
+	struct event_filter *filter;
 
 	mutex_lock(&event_mutex);
+	filter = call->filter;
 	if (filter && filter->filter_string)
 		trace_seq_printf(s, "%s\n", filter->filter_string);
 	else
@@ -486,9 +590,10 @@ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
 void print_subsystem_event_filter(struct event_subsystem *system,
 				  struct trace_seq *s)
 {
-	struct event_filter *filter = system->filter;
+	struct event_filter *filter;
 
 	mutex_lock(&event_mutex);
+	filter = system->filter;
 	if (filter && filter->filter_string)
 		trace_seq_printf(s, "%s\n", filter->filter_string);
 	else
@@ -539,10 +644,58 @@ static void filter_clear_pred(struct filter_pred *pred)
 	pred->regex.len = 0;
 }
 
-static int filter_set_pred(struct filter_pred *dest,
+static int __alloc_pred_stack(struct pred_stack *stack, int n_preds)
+{
+	stack->preds = kzalloc(sizeof(*stack->preds)*(n_preds + 1), GFP_KERNEL);
+	if (!stack->preds)
+		return -ENOMEM;
+	stack->index = n_preds;
+	return 0;
+}
+
+static void __free_pred_stack(struct pred_stack *stack)
+{
+	kfree(stack->preds);
+	stack->index = 0;
+}
+
+static int __push_pred_stack(struct pred_stack *stack,
+			     struct filter_pred *pred)
+{
+	int index = stack->index;
+
+	if (WARN_ON(index == 0))
+		return -ENOSPC;
+
+	stack->preds[--index] = pred;
+	stack->index = index;
+	return 0;
+}
+
+static struct filter_pred *
+__pop_pred_stack(struct pred_stack *stack)
+{
+	struct filter_pred *pred;
+	int index = stack->index;
+
+	pred = stack->preds[index++];
+	if (!pred)
+		return NULL;
+
+	stack->index = index;
+	return pred;
+}
+
+static int filter_set_pred(struct event_filter *filter,
+			   int idx,
+			   struct pred_stack *stack,
 			   struct filter_pred *src,
 			   filter_pred_fn_t fn)
 {
+	struct filter_pred *dest = &filter->preds[idx];
+	struct filter_pred *left;
+	struct filter_pred *right;
+
 	*dest = *src;
 	if (src->field_name) {
 		dest->field_name = kstrdup(src->field_name, GFP_KERNEL);
@@ -550,116 +703,140 @@ static int filter_set_pred(struct filter_pred *dest,
 			return -ENOMEM;
 	}
 	dest->fn = fn;
+	dest->index = idx;
 
-	return 0;
+	if (dest->op == OP_OR || dest->op == OP_AND) {
+		right = __pop_pred_stack(stack);
+		left = __pop_pred_stack(stack);
+		if (!left || !right)
+			return -EINVAL;
+		/*
+		 * If both children can be folded
+		 * and they are the same op as this op or a leaf,
+		 * then this op can be folded.
+		 */
+		if (left->index & FILTER_PRED_FOLD &&
+		    (left->op == dest->op ||
+		     left->left == FILTER_PRED_INVALID) &&
+		    right->index & FILTER_PRED_FOLD &&
+		    (right->op == dest->op ||
+		     right->left == FILTER_PRED_INVALID))
+			dest->index |= FILTER_PRED_FOLD;
+
+		dest->left = left->index & ~FILTER_PRED_FOLD;
+		dest->right = right->index & ~FILTER_PRED_FOLD;
+		left->parent = dest->index & ~FILTER_PRED_FOLD;
+		right->parent = dest->index | FILTER_PRED_IS_RIGHT;
+	} else {
+		/*
+		 * Make dest->left invalid to be used as a quick
+		 * way to know this is a leaf node.
+		 */
+		dest->left = FILTER_PRED_INVALID;
+
+		/* All leafs allow folding the parent ops. */
+		dest->index |= FILTER_PRED_FOLD;
+	}
+
+	return __push_pred_stack(stack, dest);
 }
 
-static void filter_disable_preds(struct ftrace_event_call *call)
+static void __free_preds(struct event_filter *filter)
 {
-	struct event_filter *filter = call->filter;
 	int i;
 
-	call->flags &= ~TRACE_EVENT_FL_FILTERED;
+	if (filter->preds) {
+		for (i = 0; i < filter->a_preds; i++)
+			kfree(filter->preds[i].field_name);
+		kfree(filter->preds);
+		filter->preds = NULL;
+	}
+	filter->a_preds = 0;
 	filter->n_preds = 0;
-
-	for (i = 0; i < MAX_FILTER_PRED; i++)
-		filter->preds[i]->fn = filter_pred_none;
 }
 
-static void __free_preds(struct event_filter *filter)
+static void filter_disable(struct ftrace_event_call *call)
 {
-	int i;
+	call->flags &= ~TRACE_EVENT_FL_FILTERED;
+}
 
+static void __free_filter(struct event_filter *filter)
+{
 	if (!filter)
 		return;
 
-	for (i = 0; i < MAX_FILTER_PRED; i++) {
-		if (filter->preds[i])
-			filter_free_pred(filter->preds[i]);
-	}
-	kfree(filter->preds);
+	__free_preds(filter);
 	kfree(filter->filter_string);
 	kfree(filter);
 }
 
+/*
+ * Called when destroying the ftrace_event_call.
+ * The call is being freed, so we do not need to worry about
+ * the call being currently used. This is for module code removing
+ * the tracepoints from within it.
+ */
 void destroy_preds(struct ftrace_event_call *call)
 {
-	__free_preds(call->filter);
+	__free_filter(call->filter);
 	call->filter = NULL;
-	call->flags &= ~TRACE_EVENT_FL_FILTERED;
 }
 
-static struct event_filter *__alloc_preds(void)
+static struct event_filter *__alloc_filter(void)
 {
 	struct event_filter *filter;
+
+	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
+	return filter;
+}
+
+static int __alloc_preds(struct event_filter *filter, int n_preds)
+{
 	struct filter_pred *pred;
 	int i;
 
-	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
-	if (!filter)
-		return ERR_PTR(-ENOMEM);
+	if (filter->preds)
+		__free_preds(filter);
 
-	filter->n_preds = 0;
+	filter->preds =
+		kzalloc(sizeof(*filter->preds) * n_preds, GFP_KERNEL);
 
-	filter->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
 	if (!filter->preds)
-		goto oom;
+		return -ENOMEM;
 
-	for (i = 0; i < MAX_FILTER_PRED; i++) {
-		pred = kzalloc(sizeof(*pred), GFP_KERNEL);
-		if (!pred)
-			goto oom;
+	filter->a_preds = n_preds;
+	filter->n_preds = 0;
+
+	for (i = 0; i < n_preds; i++) {
+		pred = &filter->preds[i];
 		pred->fn = filter_pred_none;
-		filter->preds[i] = pred;
 	}
 
-	return filter;
-
-oom:
-	__free_preds(filter);
-	return ERR_PTR(-ENOMEM);
-}
-
-static int init_preds(struct ftrace_event_call *call)
-{
-	if (call->filter)
-		return 0;
-
-	call->flags &= ~TRACE_EVENT_FL_FILTERED;
-	call->filter = __alloc_preds();
-	if (IS_ERR(call->filter))
-		return PTR_ERR(call->filter);
-
 	return 0;
 }
 
-static int init_subsystem_preds(struct event_subsystem *system)
+static void filter_free_subsystem_preds(struct event_subsystem *system)
 {
 	struct ftrace_event_call *call;
-	int err;
 
 	list_for_each_entry(call, &ftrace_events, list) {
 		if (strcmp(call->class->system, system->name) != 0)
 			continue;
 
-		err = init_preds(call);
-		if (err)
-			return err;
+		filter_disable(call);
+		remove_filter_string(call->filter);
 	}
-
-	return 0;
 }
 
-static void filter_free_subsystem_preds(struct event_subsystem *system)
+static void filter_free_subsystem_filters(struct event_subsystem *system)
 {
 	struct ftrace_event_call *call;
 
 	list_for_each_entry(call, &ftrace_events, list) {
 		if (strcmp(call->class->system, system->name) != 0)
 			continue;
-
-		filter_disable_preds(call);
-		remove_filter_string(call->filter);
+		__free_filter(call->filter);
+		call->filter = NULL;
 	}
 }
 
@@ -667,18 +844,19 @@ static int filter_add_pred_fn(struct filter_parse_state *ps,
 			      struct ftrace_event_call *call,
 			      struct event_filter *filter,
 			      struct filter_pred *pred,
+			      struct pred_stack *stack,
 			      filter_pred_fn_t fn)
 {
 	int idx, err;
 
-	if (filter->n_preds == MAX_FILTER_PRED) {
+	if (WARN_ON(filter->n_preds == filter->a_preds)) {
 		parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
 		return -ENOSPC;
 	}
 
 	idx = filter->n_preds;
-	filter_clear_pred(filter->preds[idx]);
-	err = filter_set_pred(filter->preds[idx], pred, fn);
+	filter_clear_pred(&filter->preds[idx]);
+	err = filter_set_pred(filter, idx, stack, pred, fn);
 	if (err)
 		return err;
 
@@ -763,6 +941,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
 			   struct ftrace_event_call *call,
 			   struct event_filter *filter,
 			   struct filter_pred *pred,
+			   struct pred_stack *stack,
 			   bool dry_run)
 {
 	struct ftrace_event_field *field;
@@ -770,17 +949,12 @@ static int filter_add_pred(struct filter_parse_state *ps,
 	unsigned long long val;
 	int ret;
 
-	pred->fn = filter_pred_none;
+	fn = pred->fn = filter_pred_none;
 
-	if (pred->op == OP_AND) {
-		pred->pop_n = 2;
-		fn = filter_pred_and;
+	if (pred->op == OP_AND)
 		goto add_pred_fn;
-	} else if (pred->op == OP_OR) {
-		pred->pop_n = 2;
-		fn = filter_pred_or;
+	else if (pred->op == OP_OR)
 		goto add_pred_fn;
-	}
 
 	field = find_event_field(call, pred->field_name);
 	if (!field) {
@@ -829,7 +1003,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
 
 add_pred_fn:
 	if (!dry_run)
-		return filter_add_pred_fn(ps, call, filter, pred, fn);
+		return filter_add_pred_fn(ps, call, filter, pred, stack, fn);
 	return 0;
 }
 
@@ -1187,6 +1361,234 @@ static int check_preds(struct filter_parse_state *ps)
 	return 0;
 }
 
+static int count_preds(struct filter_parse_state *ps)
+{
+	struct postfix_elt *elt;
+	int n_preds = 0;
+
+	list_for_each_entry(elt, &ps->postfix, list) {
+		if (elt->op == OP_NONE)
+			continue;
+		n_preds++;
+	}
+
+	return n_preds;
+}
+
+/*
+ * The tree is walked at filtering of an event. If the tree is not correctly
+ * built, it may cause an infinite loop. Check here that the tree does
+ * indeed terminate.
+ */
+static int check_pred_tree(struct event_filter *filter,
+			   struct filter_pred *root)
+{
+	struct filter_pred *preds;
+	struct filter_pred *pred;
+	enum move_type move = MOVE_DOWN;
+	int count = 0;
+	int done = 0;
+	int max;
+
+	/*
+	 * The max that we can hit a node is three times.
+	 * Once going down, once coming up from left, and
+	 * once coming up from right. This is more than enough
+	 * since leafs are only hit a single time.
+	 */
+	max = 3 * filter->n_preds;
+
+	preds = filter->preds;
+	if  (!preds)
+		return -EINVAL;
+	pred = root;
+
+	do {
+		if (WARN_ON(count++ > max))
+			return -EINVAL;
+
+		switch (move) {
+		case MOVE_DOWN:
+			if (pred->left != FILTER_PRED_INVALID) {
+				pred = &preds[pred->left];
+				continue;
+			}
+			/* A leaf at the root is just a leaf in the tree */
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		case MOVE_UP_FROM_LEFT:
+			pred = &preds[pred->right];
+			move = MOVE_DOWN;
+			continue;
+		case MOVE_UP_FROM_RIGHT:
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		}
+		done = 1;
+	} while (!done);
+
+	/* We are fine. */
+	return 0;
+}
+
+static int count_leafs(struct filter_pred *preds, struct filter_pred *root)
+{
+	struct filter_pred *pred;
+	enum move_type move = MOVE_DOWN;
+	int count = 0;
+	int done = 0;
+
+	pred = root;
+
+	do {
+		switch (move) {
+		case MOVE_DOWN:
+			if (pred->left != FILTER_PRED_INVALID) {
+				pred = &preds[pred->left];
+				continue;
+			}
+			/* A leaf at the root is just a leaf in the tree */
+			if (pred == root)
+				return 1;
+			count++;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		case MOVE_UP_FROM_LEFT:
+			pred = &preds[pred->right];
+			move = MOVE_DOWN;
+			continue;
+		case MOVE_UP_FROM_RIGHT:
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		}
+		done = 1;
+	} while (!done);
+
+	return count;
+}
+
+static int fold_pred(struct filter_pred *preds, struct filter_pred *root)
+{
+	struct filter_pred *pred;
+	enum move_type move = MOVE_DOWN;
+	int count = 0;
+	int children;
+	int done = 0;
+
+	/* No need to keep the fold flag */
+	root->index &= ~FILTER_PRED_FOLD;
+
+	/* If the root is a leaf then do nothing */
+	if (root->left == FILTER_PRED_INVALID)
+		return 0;
+
+	/* count the children */
+	children = count_leafs(preds, &preds[root->left]);
+	children += count_leafs(preds, &preds[root->right]);
+
+	root->ops = kzalloc(sizeof(*root->ops) * children, GFP_KERNEL);
+	if (!root->ops)
+		return -ENOMEM;
+
+	root->val = children;
+
+	pred = root;
+	do {
+		switch (move) {
+		case MOVE_DOWN:
+			if (pred->left != FILTER_PRED_INVALID) {
+				pred = &preds[pred->left];
+				continue;
+			}
+			if (WARN_ON(count == children))
+				return -EINVAL;
+			pred->index &= ~FILTER_PRED_FOLD;
+			root->ops[count++] = pred->index;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		case MOVE_UP_FROM_LEFT:
+			pred = &preds[pred->right];
+			move = MOVE_DOWN;
+			continue;
+		case MOVE_UP_FROM_RIGHT:
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		}
+		done = 1;
+	} while (!done);
+
+	return 0;
+}
+
+/*
+ * To optimize the processing of the ops, if we have several "ors" or
+ * "ands" together, we can put them in an array and process them all
+ * together speeding up the filter logic.
+ */
+static int fold_pred_tree(struct event_filter *filter,
+			   struct filter_pred *root)
+{
+	struct filter_pred *preds;
+	struct filter_pred *pred;
+	enum move_type move = MOVE_DOWN;
+	int done = 0;
+	int err;
+
+	preds = filter->preds;
+	if  (!preds)
+		return -EINVAL;
+	pred = root;
+
+	do {
+		switch (move) {
+		case MOVE_DOWN:
+			if (pred->index & FILTER_PRED_FOLD) {
+				err = fold_pred(preds, pred);
+				if (err)
+					return err;
+				/* Folded nodes are like leafs */
+			} else if (pred->left != FILTER_PRED_INVALID) {
+				pred = &preds[pred->left];
+				continue;
+			}
+
+			/* A leaf at the root is just a leaf in the tree */
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		case MOVE_UP_FROM_LEFT:
+			pred = &preds[pred->right];
+			move = MOVE_DOWN;
+			continue;
+		case MOVE_UP_FROM_RIGHT:
+			if (pred == root)
+				break;
+			pred = get_pred_parent(pred, preds,
+					       pred->parent, &move);
+			continue;
+		}
+		done = 1;
+	} while (!done);
+
+	return 0;
+}
+
 static int replace_preds(struct ftrace_event_call *call,
 			 struct event_filter *filter,
 			 struct filter_parse_state *ps,
@@ -1195,14 +1597,32 @@ static int replace_preds(struct ftrace_event_call *call,
 {
 	char *operand1 = NULL, *operand2 = NULL;
 	struct filter_pred *pred;
+	struct filter_pred *root;
 	struct postfix_elt *elt;
+	struct pred_stack stack = { }; /* init to NULL */
 	int err;
 	int n_preds = 0;
 
+	n_preds = count_preds(ps);
+	if (n_preds >= MAX_FILTER_PRED) {
+		parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
+		return -ENOSPC;
+	}
+
 	err = check_preds(ps);
 	if (err)
 		return err;
 
+	if (!dry_run) {
+		err = __alloc_pred_stack(&stack, n_preds);
+		if (err)
+			return err;
+		err = __alloc_preds(filter, n_preds);
+		if (err)
+			goto fail;
+	}
+
+	n_preds = 0;
 	list_for_each_entry(elt, &ps->postfix, list) {
 		if (elt->op == OP_NONE) {
 			if (!operand1)
@@ -1211,14 +1631,16 @@ static int replace_preds(struct ftrace_event_call *call,
 				operand2 = elt->operand;
 			else {
 				parse_error(ps, FILT_ERR_TOO_MANY_OPERANDS, 0);
-				return -EINVAL;
+				err = -EINVAL;
+				goto fail;
 			}
 			continue;
 		}
 
-		if (n_preds++ == MAX_FILTER_PRED) {
+		if (WARN_ON(n_preds++ == MAX_FILTER_PRED)) {
 			parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
-			return -ENOSPC;
+			err = -ENOSPC;
+			goto fail;
 		}
 
 		if (elt->op == OP_AND || elt->op == OP_OR) {
@@ -1228,76 +1650,181 @@ static int replace_preds(struct ftrace_event_call *call,
 
 		if (!operand1 || !operand2) {
 			parse_error(ps, FILT_ERR_MISSING_FIELD, 0);
-			return -EINVAL;
+			err = -EINVAL;
+			goto fail;
 		}
 
 		pred = create_pred(elt->op, operand1, operand2);
 add_pred:
-		if (!pred)
-			return -ENOMEM;
-		err = filter_add_pred(ps, call, filter, pred, dry_run);
+		if (!pred) {
+			err = -ENOMEM;
+			goto fail;
+		}
+		err = filter_add_pred(ps, call, filter, pred, &stack, dry_run);
 		filter_free_pred(pred);
 		if (err)
-			return err;
+			goto fail;
 
 		operand1 = operand2 = NULL;
 	}
 
-	return 0;
+	if (!dry_run) {
+		/* We should have one item left on the stack */
+		pred = __pop_pred_stack(&stack);
+		if (!pred)
+			return -EINVAL;
+		/* This item is where we start from in matching */
+		root = pred;
+		/* Make sure the stack is empty */
+		pred = __pop_pred_stack(&stack);
+		if (WARN_ON(pred)) {
+			err = -EINVAL;
+			filter->root = NULL;
+			goto fail;
+		}
+		err = check_pred_tree(filter, root);
+		if (err)
+			goto fail;
+
+		/* Optimize the tree */
+		err = fold_pred_tree(filter, root);
+		if (err)
+			goto fail;
+
+		/* We don't set root until we know it works */
+		barrier();
+		filter->root = root;
+	}
+
+	err = 0;
+fail:
+	__free_pred_stack(&stack);
+	return err;
 }
 
+struct filter_list {
+	struct list_head	list;
+	struct event_filter	*filter;
+};
+
 static int replace_system_preds(struct event_subsystem *system,
 				struct filter_parse_state *ps,
 				char *filter_string)
 {
 	struct ftrace_event_call *call;
+	struct filter_list *filter_item;
+	struct filter_list *tmp;
+	LIST_HEAD(filter_list);
 	bool fail = true;
 	int err;
 
 	list_for_each_entry(call, &ftrace_events, list) {
-		struct event_filter *filter = call->filter;
 
 		if (strcmp(call->class->system, system->name) != 0)
 			continue;
 
-		/* try to see if the filter can be applied */
-		err = replace_preds(call, filter, ps, filter_string, true);
+		/*
+		 * Try to see if the filter can be applied
+		 *  (filter arg is ignored on dry_run)
+		 */
+		err = replace_preds(call, NULL, ps, filter_string, true);
 		if (err)
+			goto fail;
+	}
+
+	list_for_each_entry(call, &ftrace_events, list) {
+		struct event_filter *filter;
+
+		if (strcmp(call->class->system, system->name) != 0)
 			continue;
 
-		/* really apply the filter */
-		filter_disable_preds(call);
-		err = replace_preds(call, filter, ps, filter_string, false);
+		filter_item = kzalloc(sizeof(*filter_item), GFP_KERNEL);
+		if (!filter_item)
+			goto fail_mem;
+
+		list_add_tail(&filter_item->list, &filter_list);
+
+		filter_item->filter = __alloc_filter();
+		if (!filter_item->filter)
+			goto fail_mem;
+		filter = filter_item->filter;
+
+		/* Can only fail on no memory */
+		err = replace_filter_string(filter, filter_string);
 		if (err)
-			filter_disable_preds(call);
-		else {
+			goto fail_mem;
+
+		err = replace_preds(call, filter, ps, filter_string, false);
+		if (err) {
+			filter_disable(call);
+			parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
+			append_filter_err(ps, filter);
+		} else
 			call->flags |= TRACE_EVENT_FL_FILTERED;
-			replace_filter_string(filter, filter_string);
-		}
+		/*
+		 * Regardless of if this returned an error, we still
+		 * replace the filter for the call.
+		 */
+		filter = call->filter;
+		call->filter = filter_item->filter;
+		filter_item->filter = filter;
+
 		fail = false;
 	}
 
-	if (fail) {
-		parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
-		return -EINVAL;
+	if (fail)
+		goto fail;
+
+	/*
+	 * The calls can still be using the old filters.
+	 * Do a synchronize_sched() to ensure all calls are
+	 * done with them before we free them.
+	 */
+	synchronize_sched();
+	list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
+		__free_filter(filter_item->filter);
+		list_del(&filter_item->list);
+		kfree(filter_item);
 	}
 	return 0;
+ fail:
+	/* No call succeeded */
+	list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
+		list_del(&filter_item->list);
+		kfree(filter_item);
+	}
+	parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
+	return -EINVAL;
+ fail_mem:
+	/* If any call succeeded, we still need to sync */
+	if (!fail)
+		synchronize_sched();
+	list_for_each_entry_safe(filter_item, tmp, &filter_list, list) {
+		__free_filter(filter_item->filter);
+		list_del(&filter_item->list);
+		kfree(filter_item);
+	}
+	return -ENOMEM;
 }
 
 int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
 {
-	int err;
 	struct filter_parse_state *ps;
+	struct event_filter *filter;
+	struct event_filter *tmp;
+	int err = 0;
 
 	mutex_lock(&event_mutex);
 
-	err = init_preds(call);
-	if (err)
-		goto out_unlock;
-
 	if (!strcmp(strstrip(filter_string), "0")) {
-		filter_disable_preds(call);
-		remove_filter_string(call->filter);
+		filter_disable(call);
+		filter = call->filter;
+		if (!filter)
+			goto out_unlock;
+		call->filter = NULL;
+		/* Make sure the filter is not being used */
+		synchronize_sched();
+		__free_filter(filter);
 		goto out_unlock;
 	}
 
@@ -1306,22 +1833,41 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
 	if (!ps)
 		goto out_unlock;
 
-	filter_disable_preds(call);
-	replace_filter_string(call->filter, filter_string);
+	filter = __alloc_filter();
+	if (!filter) {
+		kfree(ps);
+		goto out_unlock;
+	}
+
+	replace_filter_string(filter, filter_string);
 
 	parse_init(ps, filter_ops, filter_string);
 	err = filter_parse(ps);
 	if (err) {
-		append_filter_err(ps, call->filter);
+		append_filter_err(ps, filter);
 		goto out;
 	}
 
-	err = replace_preds(call, call->filter, ps, filter_string, false);
-	if (err)
-		append_filter_err(ps, call->filter);
-	else
+	err = replace_preds(call, filter, ps, filter_string, false);
+	if (err) {
+		filter_disable(call);
+		append_filter_err(ps, filter);
+	} else
 		call->flags |= TRACE_EVENT_FL_FILTERED;
 out:
+	/*
+	 * Always swap the call filter with the new filter
+	 * even if there was an error. If there was an error
+	 * in the filter, we disable the filter and show the error
+	 * string
+	 */
+	tmp = call->filter;
+	call->filter = filter;
+	if (tmp) {
+		/* Make sure the call is done with the filter */
+		synchronize_sched();
+		__free_filter(tmp);
+	}
 	filter_opstack_clear(ps);
 	postfix_clear(ps);
 	kfree(ps);
@@ -1334,18 +1880,21 @@ out_unlock:
 int apply_subsystem_event_filter(struct event_subsystem *system,
 				 char *filter_string)
 {
-	int err;
 	struct filter_parse_state *ps;
+	struct event_filter *filter;
+	int err = 0;
 
 	mutex_lock(&event_mutex);
 
-	err = init_subsystem_preds(system);
-	if (err)
-		goto out_unlock;
-
 	if (!strcmp(strstrip(filter_string), "0")) {
 		filter_free_subsystem_preds(system);
 		remove_filter_string(system->filter);
+		filter = system->filter;
+		system->filter = NULL;
+		/* Ensure all filters are no longer used */
+		synchronize_sched();
+		filter_free_subsystem_filters(system);
+		__free_filter(filter);
 		goto out_unlock;
 	}
 
@@ -1354,7 +1903,17 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
 	if (!ps)
 		goto out_unlock;
 
-	replace_filter_string(system->filter, filter_string);
+	filter = __alloc_filter();
+	if (!filter)
+		goto out;
+
+	replace_filter_string(filter, filter_string);
+	/*
+	 * No event actually uses the system filter
+	 * we can free it without synchronize_sched().
+	 */
+	__free_filter(system->filter);
+	system->filter = filter;
 
 	parse_init(ps, filter_ops, filter_string);
 	err = filter_parse(ps);
@@ -1384,7 +1943,7 @@ void ftrace_profile_free_filter(struct perf_event *event)
 	struct event_filter *filter = event->filter;
 
 	event->filter = NULL;
-	__free_preds(filter);
+	__free_filter(filter);
 }
 
 int ftrace_profile_set_filter(struct perf_event *event, int event_id,
@@ -1410,8 +1969,8 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
 	if (event->filter)
 		goto out_unlock;
 
-	filter = __alloc_preds();
-	if (IS_ERR(filter)) {
+	filter = __alloc_filter();
+	if (!filter) {
 		err = PTR_ERR(filter);
 		goto out_unlock;
 	}
@@ -1419,7 +1978,7 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
 	err = -ENOMEM;
 	ps = kzalloc(sizeof(*ps), GFP_KERNEL);
 	if (!ps)
-		goto free_preds;
+		goto free_filter;
 
 	parse_init(ps, filter_ops, filter_str);
 	err = filter_parse(ps);
@@ -1435,9 +1994,9 @@ free_ps:
 	postfix_clear(ps);
 	kfree(ps);
 
-free_preds:
+free_filter:
 	if (err)
-		__free_preds(filter);
+		__free_filter(filter);
 
 out_unlock:
 	mutex_unlock(&event_mutex);
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 2dec9bc..8435b43 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -353,6 +353,43 @@ static __kprobes void free_deref_fetch_param(struct deref_fetch_param *data)
 	kfree(data);
 }
 
+/* Bitfield fetch function */
+struct bitfield_fetch_param {
+	struct fetch_param orig;
+	unsigned char hi_shift;
+	unsigned char low_shift;
+};
+
+#define DEFINE_FETCH_bitfield(type)					\
+static __kprobes void FETCH_FUNC_NAME(bitfield, type)(struct pt_regs *regs,\
+					    void *data, void *dest)	\
+{									\
+	struct bitfield_fetch_param *bprm = data;			\
+	type buf = 0;							\
+	call_fetch(&bprm->orig, regs, &buf);				\
+	if (buf) {							\
+		buf <<= bprm->hi_shift;					\
+		buf >>= bprm->low_shift;				\
+	}								\
+	*(type *)dest = buf;						\
+}
+DEFINE_BASIC_FETCH_FUNCS(bitfield)
+#define fetch_bitfield_string NULL
+#define fetch_bitfield_string_size NULL
+
+static __kprobes void
+free_bitfield_fetch_param(struct bitfield_fetch_param *data)
+{
+	/*
+	 * Don't check the bitfield itself, because this must be the
+	 * last fetch function.
+	 */
+	if (CHECK_FETCH_FUNCS(deref, data->orig.fn))
+		free_deref_fetch_param(data->orig.data);
+	else if (CHECK_FETCH_FUNCS(symbol, data->orig.fn))
+		free_symbol_cache(data->orig.data);
+	kfree(data);
+}
 /* Default (unsigned long) fetch type */
 #define __DEFAULT_FETCH_TYPE(t) u##t
 #define _DEFAULT_FETCH_TYPE(t) __DEFAULT_FETCH_TYPE(t)
@@ -367,6 +404,7 @@ enum {
 	FETCH_MTD_memory,
 	FETCH_MTD_symbol,
 	FETCH_MTD_deref,
+	FETCH_MTD_bitfield,
 	FETCH_MTD_END,
 };
 
@@ -387,6 +425,7 @@ ASSIGN_FETCH_FUNC(retval, ftype),			\
 ASSIGN_FETCH_FUNC(memory, ftype),			\
 ASSIGN_FETCH_FUNC(symbol, ftype),			\
 ASSIGN_FETCH_FUNC(deref, ftype),			\
+ASSIGN_FETCH_FUNC(bitfield, ftype),			\
 	  }						\
 	}
 
@@ -430,9 +469,33 @@ static const struct fetch_type *find_fetch_type(const char *type)
 	if (!type)
 		type = DEFAULT_FETCH_TYPE_STR;
 
+	/* Special case: bitfield */
+	if (*type == 'b') {
+		unsigned long bs;
+		type = strchr(type, '/');
+		if (!type)
+			goto fail;
+		type++;
+		if (strict_strtoul(type, 0, &bs))
+			goto fail;
+		switch (bs) {
+		case 8:
+			return find_fetch_type("u8");
+		case 16:
+			return find_fetch_type("u16");
+		case 32:
+			return find_fetch_type("u32");
+		case 64:
+			return find_fetch_type("u64");
+		default:
+			goto fail;
+		}
+	}
+
 	for (i = 0; i < ARRAY_SIZE(fetch_type_table); i++)
 		if (strcmp(type, fetch_type_table[i].name) == 0)
 			return &fetch_type_table[i];
+fail:
 	return NULL;
 }
 
@@ -586,7 +649,9 @@ error:
 
 static void free_probe_arg(struct probe_arg *arg)
 {
-	if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
+	if (CHECK_FETCH_FUNCS(bitfield, arg->fetch.fn))
+		free_bitfield_fetch_param(arg->fetch.data);
+	else if (CHECK_FETCH_FUNCS(deref, arg->fetch.fn))
 		free_deref_fetch_param(arg->fetch.data);
 	else if (CHECK_FETCH_FUNCS(symbol, arg->fetch.fn))
 		free_symbol_cache(arg->fetch.data);
@@ -767,16 +832,15 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t,
 		}
 		break;
 	case '+':	/* deref memory */
+		arg++;	/* Skip '+', because strict_strtol() rejects it. */
 	case '-':
 		tmp = strchr(arg, '(');
 		if (!tmp)
 			break;
 		*tmp = '\0';
-		ret = strict_strtol(arg + 1, 0, &offset);
+		ret = strict_strtol(arg, 0, &offset);
 		if (ret)
 			break;
-		if (arg[0] == '-')
-			offset = -offset;
 		arg = tmp + 1;
 		tmp = strrchr(arg, ')');
 		if (tmp) {
@@ -807,6 +871,41 @@ static int __parse_probe_arg(char *arg, const struct fetch_type *t,
 	return ret;
 }
 
+#define BYTES_TO_BITS(nb)	((BITS_PER_LONG * (nb)) / sizeof(long))
+
+/* Bitfield type needs to be parsed into a fetch function */
+static int __parse_bitfield_probe_arg(const char *bf,
+				      const struct fetch_type *t,
+				      struct fetch_param *f)
+{
+	struct bitfield_fetch_param *bprm;
+	unsigned long bw, bo;
+	char *tail;
+
+	if (*bf != 'b')
+		return 0;
+
+	bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
+	if (!bprm)
+		return -ENOMEM;
+	bprm->orig = *f;
+	f->fn = t->fetch[FETCH_MTD_bitfield];
+	f->data = (void *)bprm;
+
+	bw = simple_strtoul(bf + 1, &tail, 0);	/* Use simple one */
+	if (bw == 0 || *tail != '@')
+		return -EINVAL;
+
+	bf = tail + 1;
+	bo = simple_strtoul(bf, &tail, 0);
+	if (tail == bf || *tail != '/')
+		return -EINVAL;
+
+	bprm->hi_shift = BYTES_TO_BITS(t->size) - (bw + bo);
+	bprm->low_shift = bprm->hi_shift + bo;
+	return (BYTES_TO_BITS(t->size) < (bw + bo)) ? -EINVAL : 0;
+}
+
 /* String length checking wrapper */
 static int parse_probe_arg(char *arg, struct trace_probe *tp,
 			   struct probe_arg *parg, int is_return)
@@ -836,6 +935,8 @@ static int parse_probe_arg(char *arg, struct trace_probe *tp,
 	parg->offset = tp->size;
 	tp->size += parg->type->size;
 	ret = __parse_probe_arg(arg, parg->type, &parg->fetch, is_return);
+	if (ret >= 0 && t != NULL)
+		ret = __parse_bitfield_probe_arg(t, parg->type, &parg->fetch);
 	if (ret >= 0) {
 		parg->fetch_size.fn = get_fetch_size_function(parg->type,
 							      parg->fetch.fn);
@@ -1130,7 +1231,7 @@ static int command_trace_probe(const char *buf)
 	return ret;
 }
 
-#define WRITE_BUFSIZE 128
+#define WRITE_BUFSIZE 4096
 
 static ssize_t probes_write(struct file *file, const char __user *buffer,
 			    size_t count, loff_t *ppos)
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 02272ba..456be90 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -529,24 +529,34 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags)
  * @entry: The trace entry field from the ring buffer
  *
  * Prints the generic fields of irqs off, in hard or softirq, preempt
- * count and lock depth.
+ * count.
  */
 int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
 {
-	int hardirq, softirq;
+	char hardsoft_irq;
+	char need_resched;
+	char irqs_off;
+	int hardirq;
+	int softirq;
 	int ret;
 
 	hardirq = entry->flags & TRACE_FLAG_HARDIRQ;
 	softirq = entry->flags & TRACE_FLAG_SOFTIRQ;
 
+	irqs_off =
+		(entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
+		(entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' :
+		'.';
+	need_resched =
+		(entry->flags & TRACE_FLAG_NEED_RESCHED) ? 'N' : '.';
+	hardsoft_irq =
+		(hardirq && softirq) ? 'H' :
+		hardirq ? 'h' :
+		softirq ? 's' :
+		'.';
+
 	if (!trace_seq_printf(s, "%c%c%c",
-			      (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
-				(entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
-				  'X' : '.',
-			      (entry->flags & TRACE_FLAG_NEED_RESCHED) ?
-				'N' : '.',
-			      (hardirq && softirq) ? 'H' :
-				hardirq ? 'h' : softirq ? 's' : '.'))
+			      irqs_off, need_resched, hardsoft_irq))
 		return 0;
 
 	if (entry->preempt_count)
@@ -554,13 +564,7 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
 	else
 		ret = trace_seq_putc(s, '.');
 
-	if (!ret)
-		return 0;
-
-	if (entry->lock_depth < 0)
-		return trace_seq_putc(s, '.');
-
-	return trace_seq_printf(s, "%d", entry->lock_depth);
+	return ret;
 }
 
 static int
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index 8f758d0..7e62c0a 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -247,51 +247,3 @@ void tracing_sched_switch_assign_trace(struct trace_array *tr)
 	ctx_trace = tr;
 }
 
-static void stop_sched_trace(struct trace_array *tr)
-{
-	tracing_stop_sched_switch_record();
-}
-
-static int sched_switch_trace_init(struct trace_array *tr)
-{
-	ctx_trace = tr;
-	tracing_reset_online_cpus(tr);
-	tracing_start_sched_switch_record();
-	return 0;
-}
-
-static void sched_switch_trace_reset(struct trace_array *tr)
-{
-	if (sched_ref)
-		stop_sched_trace(tr);
-}
-
-static void sched_switch_trace_start(struct trace_array *tr)
-{
-	sched_stopped = 0;
-}
-
-static void sched_switch_trace_stop(struct trace_array *tr)
-{
-	sched_stopped = 1;
-}
-
-static struct tracer sched_switch_trace __read_mostly =
-{
-	.name		= "sched_switch",
-	.init		= sched_switch_trace_init,
-	.reset		= sched_switch_trace_reset,
-	.start		= sched_switch_trace_start,
-	.stop		= sched_switch_trace_stop,
-	.wait_pipe	= poll_wait_pipe,
-#ifdef CONFIG_FTRACE_SELFTEST
-	.selftest    = trace_selftest_startup_sched_switch,
-#endif
-};
-
-__init static int init_sched_switch_trace(void)
-{
-	return register_tracer(&sched_switch_trace);
-}
-device_initcall(init_sched_switch_trace);
-
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 5c9fe08..ee7b5a0 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -60,6 +60,19 @@ extern struct syscall_metadata *__stop_syscalls_metadata[];
 
 static struct syscall_metadata **syscalls_metadata;
 
+#ifndef ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+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
+	 * mismatch.
+	 */
+	return !strcmp(sym + 3, name + 3);
+}
+#endif
+
 static __init struct syscall_metadata *
 find_syscall_meta(unsigned long syscall)
 {
@@ -72,14 +85,11 @@ find_syscall_meta(unsigned long syscall)
 	stop = __stop_syscalls_metadata;
 	kallsyms_lookup(syscall, NULL, NULL, NULL, str);
 
+	if (arch_syscall_match_sym_name(str, "sys_ni_syscall"))
+		return NULL;
+
 	for ( ; start < stop; start++) {
-		/*
-		 * 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
-		 * mismatch.
-		 */
-		if ((*start)->name && !strcmp((*start)->name + 3, str + 3))
+		if ((*start)->name && arch_syscall_match_sym_name(str, (*start)->name))
 			return *start;
 	}
 	return NULL;
@@ -359,7 +369,7 @@ int reg_event_syscall_enter(struct ftrace_event_call *call)
 	int num;
 
 	num = ((struct syscall_metadata *)call->data)->syscall_nr;
-	if (num < 0 || num >= NR_syscalls)
+	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return -ENOSYS;
 	mutex_lock(&syscall_trace_lock);
 	if (!sys_refcount_enter)
@@ -377,7 +387,7 @@ void unreg_event_syscall_enter(struct ftrace_event_call *call)
 	int num;
 
 	num = ((struct syscall_metadata *)call->data)->syscall_nr;
-	if (num < 0 || num >= NR_syscalls)
+	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return;
 	mutex_lock(&syscall_trace_lock);
 	sys_refcount_enter--;
@@ -393,7 +403,7 @@ int reg_event_syscall_exit(struct ftrace_event_call *call)
 	int num;
 
 	num = ((struct syscall_metadata *)call->data)->syscall_nr;
-	if (num < 0 || num >= NR_syscalls)
+	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return -ENOSYS;
 	mutex_lock(&syscall_trace_lock);
 	if (!sys_refcount_exit)
@@ -411,7 +421,7 @@ void unreg_event_syscall_exit(struct ftrace_event_call *call)
 	int num;
 
 	num = ((struct syscall_metadata *)call->data)->syscall_nr;
-	if (num < 0 || num >= NR_syscalls)
+	if (WARN_ON_ONCE(num < 0 || num >= NR_syscalls))
 		return;
 	mutex_lock(&syscall_trace_lock);
 	sys_refcount_exit--;
@@ -424,6 +434,14 @@ void unreg_event_syscall_exit(struct ftrace_event_call *call)
 int init_syscall_trace(struct ftrace_event_call *call)
 {
 	int id;
+	int num;
+
+	num = ((struct syscall_metadata *)call->data)->syscall_nr;
+	if (num < 0 || num >= NR_syscalls) {
+		pr_debug("syscall %s metadata not mapped, disabling ftrace event\n",
+				((struct syscall_metadata *)call->data)->name);
+		return -ENOSYS;
+	}
 
 	if (set_syscall_print_fmt(call) < 0)
 		return -ENOMEM;
@@ -438,7 +456,7 @@ int init_syscall_trace(struct ftrace_event_call *call)
 	return id;
 }
 
-unsigned long __init arch_syscall_addr(int nr)
+unsigned long __init __weak arch_syscall_addr(int nr)
 {
 	return (unsigned long)sys_call_table[nr];
 }
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 18bb157..140dce7 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -48,12 +48,15 @@ static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
  * Should we panic when a soft-lockup or hard-lockup occurs:
  */
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
-static int hardlockup_panic;
+static int hardlockup_panic =
+			CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
 
 static int __init hardlockup_panic_setup(char *str)
 {
 	if (!strncmp(str, "panic", 5))
 		hardlockup_panic = 1;
+	else if (!strncmp(str, "nopanic", 7))
+		hardlockup_panic = 0;
 	else if (!strncmp(str, "0", 1))
 		watchdog_enabled = 0;
 	return 1;
@@ -415,19 +418,22 @@ static int watchdog_prepare_cpu(int cpu)
 static int watchdog_enable(int cpu)
 {
 	struct task_struct *p = per_cpu(softlockup_watchdog, cpu);
-	int err;
+	int err = 0;
 
 	/* enable the perf event */
 	err = watchdog_nmi_enable(cpu);
-	if (err)
-		return err;
+
+	/* Regardless of err above, fall through and start softlockup */
 
 	/* create the watchdog thread */
 	if (!p) {
 		p = kthread_create(watchdog, (void *)(unsigned long)cpu, "watchdog/%d", cpu);
 		if (IS_ERR(p)) {
 			printk(KERN_ERR "softlockup watchdog for %i failed\n", cpu);
-			return PTR_ERR(p);
+			if (!err)
+				/* if hardlockup hasn't already set this */
+				err = PTR_ERR(p);
+			goto out;
 		}
 		kthread_bind(p, cpu);
 		per_cpu(watchdog_touch_ts, cpu) = 0;
@@ -435,7 +441,8 @@ static int watchdog_enable(int cpu)
 		wake_up_process(p);
 	}
 
-	return 0;
+out:
+	return err;
 }
 
 static void watchdog_disable(int cpu)
@@ -547,7 +554,13 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 		break;
 #endif /* CONFIG_HOTPLUG_CPU */
 	}
-	return notifier_from_errno(err);
+
+	/*
+	 * hardlockup and softlockup are not important enough
+	 * to block cpu bring up.  Just always succeed and
+	 * rely on printk output to flag problems.
+	 */
+	return NOTIFY_OK;
 }
 
 static struct notifier_block __cpuinitdata cpu_nfb = {
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index ee6578b..04ef830 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -251,10 +251,12 @@ struct workqueue_struct *system_wq __read_mostly;
 struct workqueue_struct *system_long_wq __read_mostly;
 struct workqueue_struct *system_nrt_wq __read_mostly;
 struct workqueue_struct *system_unbound_wq __read_mostly;
+struct workqueue_struct *system_freezable_wq __read_mostly;
 EXPORT_SYMBOL_GPL(system_wq);
 EXPORT_SYMBOL_GPL(system_long_wq);
 EXPORT_SYMBOL_GPL(system_nrt_wq);
 EXPORT_SYMBOL_GPL(system_unbound_wq);
+EXPORT_SYMBOL_GPL(system_freezable_wq);
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/workqueue.h>
@@ -316,6 +318,11 @@ static inline int __next_wq_cpu(int cpu, const struct cpumask *mask,
 
 static struct debug_obj_descr work_debug_descr;
 
+static void *work_debug_hint(void *addr)
+{
+	return ((struct work_struct *) addr)->func;
+}
+
 /*
  * fixup_init is called when:
  * - an active object is initialized
@@ -387,6 +394,7 @@ static int work_fixup_free(void *addr, enum debug_obj_state state)
 
 static struct debug_obj_descr work_debug_descr = {
 	.name		= "work_struct",
+	.debug_hint	= work_debug_hint,
 	.fixup_init	= work_fixup_init,
 	.fixup_activate	= work_fixup_activate,
 	.fixup_free	= work_fixup_free,
@@ -1358,8 +1366,10 @@ static struct worker *create_worker(struct global_cwq *gcwq, bool bind)
 	worker->id = id;
 
 	if (!on_unbound_cpu)
-		worker->task = kthread_create(worker_thread, worker,
-					      "kworker/%u:%d", gcwq->cpu, id);
+		worker->task = kthread_create_on_node(worker_thread,
+						      worker,
+						      cpu_to_node(gcwq->cpu),
+						      "kworker/%u:%d", gcwq->cpu, id);
 	else
 		worker->task = kthread_create(worker_thread, worker,
 					      "kworker/u:%d", id);
@@ -3775,8 +3785,10 @@ static int __init init_workqueues(void)
 	system_nrt_wq = alloc_workqueue("events_nrt", WQ_NON_REENTRANT, 0);
 	system_unbound_wq = alloc_workqueue("events_unbound", WQ_UNBOUND,
 					    WQ_UNBOUND_MAX_ACTIVE);
+	system_freezable_wq = alloc_workqueue("events_freezable",
+					      WQ_FREEZABLE, 0);
 	BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq ||
-	       !system_unbound_wq);
+	       !system_unbound_wq || !system_freezable_wq);
 	return 0;
 }
 early_initcall(init_workqueues);
diff --git a/lib/Kconfig b/lib/Kconfig
index 0ee67e0..3a55a43 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -201,6 +201,10 @@ config DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
        bool "Disable obsolete cpumask functions" if DEBUG_PER_CPU_MAPS
        depends on EXPERIMENTAL && BROKEN
 
+config CPU_RMAP
+	bool
+	depends on SMP
+
 #
 # Netlink attribute parsing support is select'ed if needed
 #
@@ -217,6 +221,13 @@ config LRU_CACHE
 	tristate
 
 config AVERAGE
-	bool
+	bool "Averaging functions"
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require averaging functions, but a module built outside
+	  the kernel tree does. Such modules that use library averaging
+	  functions require Y here.
+
+	  If unsure, say N.
 
 endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 2b97418..df9234c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -9,6 +9,17 @@ config PRINTK_TIME
 	  operations.  This is useful for identifying long delays
 	  in kernel startup.
 
+config DEFAULT_MESSAGE_LOGLEVEL
+	int "Default message log level (1-7)"
+	range 1 7
+	default "4"
+	help
+	  Default log level for printk statements with no specified priority.
+
+	  This was hard-coded to KERN_WARNING since at least 2.6.10 but folks
+	  that are auditing their logs closely may want to set it to a lower
+	  priority.
+
 config ENABLE_WARN_DEPRECATED
 	bool "Enable __deprecated logic"
 	default y
@@ -102,11 +113,6 @@ config HEADERS_CHECK
 
 config DEBUG_SECTION_MISMATCH
 	bool "Enable full Section mismatch analysis"
-	depends on UNDEFINED || (BLACKFIN)
-	default y
-	# This option is on purpose disabled for now.
-	# It will be enabled when we are down to a reasonable number
-	# of section mismatch warnings (< 10 for an allyesconfig build)
 	help
 	  The section mismatch analysis checks if there are illegal
 	  references from one section to another section.
@@ -176,6 +182,23 @@ config HARDLOCKUP_DETECTOR
 	def_bool LOCKUP_DETECTOR && PERF_EVENTS && HAVE_PERF_EVENTS_NMI && \
 		 !ARCH_HAS_NMI_WATCHDOG
 
+config BOOTPARAM_HARDLOCKUP_PANIC
+	bool "Panic (Reboot) On Hard Lockups"
+	depends on LOCKUP_DETECTOR
+	help
+	  Say Y here to enable the kernel to panic on "hard lockups",
+	  which are bugs that cause the kernel to loop in kernel
+	  mode with interrupts disabled for more than 60 seconds.
+
+	  Say N if unsure.
+
+config BOOTPARAM_HARDLOCKUP_PANIC_VALUE
+	int
+	depends on LOCKUP_DETECTOR
+	range 0 1
+	default 0 if !BOOTPARAM_HARDLOCKUP_PANIC
+	default 1 if BOOTPARAM_HARDLOCKUP_PANIC
+
 config BOOTPARAM_SOFTLOCKUP_PANIC
 	bool "Panic (Reboot) On Soft Lockups"
 	depends on LOCKUP_DETECTOR
@@ -470,15 +493,6 @@ config DEBUG_MUTEXES
 	 This feature allows mutex semantics violations to be detected and
 	 reported.
 
-config BKL
-	bool "Big Kernel Lock" if (SMP || PREEMPT)
-	default y
-	help
-	  This is the traditional lock that is used in old code instead
-	  of proper locking. All drivers that use the BKL should depend
-	  on this symbol.
-	  Say Y here unless you are working on removing the BKL.
-
 config DEBUG_LOCK_ALLOC
 	bool "Lock debugging: detect incorrect freeing of live locks"
 	depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
@@ -1236,3 +1250,6 @@ source "samples/Kconfig"
 source "lib/Kconfig.kgdb"
 
 source "lib/Kconfig.kmemcheck"
+
+config TEST_KSTRTOX
+	tristate "Test kstrto*() family of functions at runtime"
diff --git a/lib/Makefile b/lib/Makefile
index cbb774f..8c9de02 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -22,6 +22,8 @@ lib-y	+= kobject.o kref.o klist.o
 obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
 	 bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
 	 string_helpers.o gcd.o lcm.o list_sort.o uuid.o flex_array.o
+obj-y += kstrtox.o
+obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
@@ -43,7 +45,6 @@ obj-$(CONFIG_GENERIC_FIND_LAST_BIT) += find_last_bit.o
 CFLAGS_hweight.o = $(subst $(quote),,$(CONFIG_ARCH_HWEIGHT_CFLAGS))
 obj-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 
-obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
 obj-$(CONFIG_BTREE) += btree.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 obj-$(CONFIG_DEBUG_LIST) += list_debug.o
@@ -110,6 +111,8 @@ obj-$(CONFIG_ATOMIC64_SELFTEST) += atomic64_test.o
 
 obj-$(CONFIG_AVERAGE) += average.o
 
+obj-$(CONFIG_CPU_RMAP) += cpu_rmap.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/cpu_rmap.c b/lib/cpu_rmap.c
new file mode 100644
index 0000000..987acfa
--- /dev/null
+++ b/lib/cpu_rmap.c
@@ -0,0 +1,269 @@
+/*
+ * cpu_rmap.c: CPU affinity reverse-map support
+ * Copyright 2011 Solarflare Communications 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, incorporated herein by reference.
+ */
+
+#include <linux/cpu_rmap.h>
+#ifdef CONFIG_GENERIC_HARDIRQS
+#include <linux/interrupt.h>
+#endif
+#include <linux/module.h>
+
+/*
+ * These functions maintain a mapping from CPUs to some ordered set of
+ * objects with CPU affinities.  This can be seen as a reverse-map of
+ * CPU affinity.  However, we do not assume that the object affinities
+ * cover all CPUs in the system.  For those CPUs not directly covered
+ * by object affinities, we attempt to find a nearest object based on
+ * CPU topology.
+ */
+
+/**
+ * alloc_cpu_rmap - allocate CPU affinity reverse-map
+ * @size: Number of objects to be mapped
+ * @flags: Allocation flags e.g. %GFP_KERNEL
+ */
+struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags)
+{
+	struct cpu_rmap *rmap;
+	unsigned int cpu;
+	size_t obj_offset;
+
+	/* This is a silly number of objects, and we use u16 indices. */
+	if (size > 0xffff)
+		return NULL;
+
+	/* Offset of object pointer array from base structure */
+	obj_offset = ALIGN(offsetof(struct cpu_rmap, near[nr_cpu_ids]),
+			   sizeof(void *));
+
+	rmap = kzalloc(obj_offset + size * sizeof(rmap->obj[0]), flags);
+	if (!rmap)
+		return NULL;
+
+	rmap->obj = (void **)((char *)rmap + obj_offset);
+
+	/* Initially assign CPUs to objects on a rota, since we have
+	 * no idea where the objects are.  Use infinite distance, so
+	 * any object with known distance is preferable.  Include the
+	 * CPUs that are not present/online, since we definitely want
+	 * any newly-hotplugged CPUs to have some object assigned.
+	 */
+	for_each_possible_cpu(cpu) {
+		rmap->near[cpu].index = cpu % size;
+		rmap->near[cpu].dist = CPU_RMAP_DIST_INF;
+	}
+
+	rmap->size = size;
+	return rmap;
+}
+EXPORT_SYMBOL(alloc_cpu_rmap);
+
+/* Reevaluate nearest object for given CPU, comparing with the given
+ * neighbours at the given distance.
+ */
+static bool cpu_rmap_copy_neigh(struct cpu_rmap *rmap, unsigned int cpu,
+				const struct cpumask *mask, u16 dist)
+{
+	int neigh;
+
+	for_each_cpu(neigh, mask) {
+		if (rmap->near[cpu].dist > dist &&
+		    rmap->near[neigh].dist <= dist) {
+			rmap->near[cpu].index = rmap->near[neigh].index;
+			rmap->near[cpu].dist = dist;
+			return true;
+		}
+	}
+	return false;
+}
+
+#ifdef DEBUG
+static void debug_print_rmap(const struct cpu_rmap *rmap, const char *prefix)
+{
+	unsigned index;
+	unsigned int cpu;
+
+	pr_info("cpu_rmap %p, %s:\n", rmap, prefix);
+
+	for_each_possible_cpu(cpu) {
+		index = rmap->near[cpu].index;
+		pr_info("cpu %d -> obj %u (distance %u)\n",
+			cpu, index, rmap->near[cpu].dist);
+	}
+}
+#else
+static inline void
+debug_print_rmap(const struct cpu_rmap *rmap, const char *prefix)
+{
+}
+#endif
+
+/**
+ * cpu_rmap_add - add object to a rmap
+ * @rmap: CPU rmap allocated with alloc_cpu_rmap()
+ * @obj: Object to add to rmap
+ *
+ * Return index of object.
+ */
+int cpu_rmap_add(struct cpu_rmap *rmap, void *obj)
+{
+	u16 index;
+
+	BUG_ON(rmap->used >= rmap->size);
+	index = rmap->used++;
+	rmap->obj[index] = obj;
+	return index;
+}
+EXPORT_SYMBOL(cpu_rmap_add);
+
+/**
+ * cpu_rmap_update - update CPU rmap following a change of object affinity
+ * @rmap: CPU rmap to update
+ * @index: Index of object whose affinity changed
+ * @affinity: New CPU affinity of object
+ */
+int cpu_rmap_update(struct cpu_rmap *rmap, u16 index,
+		    const struct cpumask *affinity)
+{
+	cpumask_var_t update_mask;
+	unsigned int cpu;
+
+	if (unlikely(!zalloc_cpumask_var(&update_mask, GFP_KERNEL)))
+		return -ENOMEM;
+
+	/* Invalidate distance for all CPUs for which this used to be
+	 * the nearest object.  Mark those CPUs for update.
+	 */
+	for_each_online_cpu(cpu) {
+		if (rmap->near[cpu].index == index) {
+			rmap->near[cpu].dist = CPU_RMAP_DIST_INF;
+			cpumask_set_cpu(cpu, update_mask);
+		}
+	}
+
+	debug_print_rmap(rmap, "after invalidating old distances");
+
+	/* Set distance to 0 for all CPUs in the new affinity mask.
+	 * Mark all CPUs within their NUMA nodes for update.
+	 */
+	for_each_cpu(cpu, affinity) {
+		rmap->near[cpu].index = index;
+		rmap->near[cpu].dist = 0;
+		cpumask_or(update_mask, update_mask,
+			   cpumask_of_node(cpu_to_node(cpu)));
+	}
+
+	debug_print_rmap(rmap, "after updating neighbours");
+
+	/* Update distances based on topology */
+	for_each_cpu(cpu, update_mask) {
+		if (cpu_rmap_copy_neigh(rmap, cpu,
+					topology_thread_cpumask(cpu), 1))
+			continue;
+		if (cpu_rmap_copy_neigh(rmap, cpu,
+					topology_core_cpumask(cpu), 2))
+			continue;
+		if (cpu_rmap_copy_neigh(rmap, cpu,
+					cpumask_of_node(cpu_to_node(cpu)), 3))
+			continue;
+		/* We could continue into NUMA node distances, but for now
+		 * we give up.
+		 */
+	}
+
+	debug_print_rmap(rmap, "after copying neighbours");
+
+	free_cpumask_var(update_mask);
+	return 0;
+}
+EXPORT_SYMBOL(cpu_rmap_update);
+
+#ifdef CONFIG_GENERIC_HARDIRQS
+
+/* Glue between IRQ affinity notifiers and CPU rmaps */
+
+struct irq_glue {
+	struct irq_affinity_notify notify;
+	struct cpu_rmap *rmap;
+	u16 index;
+};
+
+/**
+ * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs
+ * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL
+ *
+ * Must be called in process context, before freeing the IRQs, and
+ * without holding any locks required by global workqueue items.
+ */
+void free_irq_cpu_rmap(struct cpu_rmap *rmap)
+{
+	struct irq_glue *glue;
+	u16 index;
+
+	if (!rmap)
+		return;
+
+	for (index = 0; index < rmap->used; index++) {
+		glue = rmap->obj[index];
+		irq_set_affinity_notifier(glue->notify.irq, NULL);
+	}
+	irq_run_affinity_notifiers();
+
+	kfree(rmap);
+}
+EXPORT_SYMBOL(free_irq_cpu_rmap);
+
+static void
+irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask)
+{
+	struct irq_glue *glue =
+		container_of(notify, struct irq_glue, notify);
+	int rc;
+
+	rc = cpu_rmap_update(glue->rmap, glue->index, mask);
+	if (rc)
+		pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc);
+}
+
+static void irq_cpu_rmap_release(struct kref *ref)
+{
+	struct irq_glue *glue =
+		container_of(ref, struct irq_glue, notify.kref);
+	kfree(glue);
+}
+
+/**
+ * irq_cpu_rmap_add - add an IRQ to a CPU affinity reverse-map
+ * @rmap: The reverse-map
+ * @irq: The IRQ number
+ *
+ * This adds an IRQ affinity notifier that will update the reverse-map
+ * automatically.
+ *
+ * Must be called in process context, after the IRQ is allocated but
+ * before it is bound with request_irq().
+ */
+int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq)
+{
+	struct irq_glue *glue = kzalloc(sizeof(*glue), GFP_KERNEL);
+	int rc;
+
+	if (!glue)
+		return -ENOMEM;
+	glue->notify.notify = irq_cpu_rmap_notify;
+	glue->notify.release = irq_cpu_rmap_release;
+	glue->rmap = rmap;
+	glue->index = cpu_rmap_add(rmap, glue);
+	rc = irq_set_affinity_notifier(irq, &glue->notify);
+	if (rc)
+		kfree(glue);
+	return rc;
+}
+EXPORT_SYMBOL(irq_cpu_rmap_add);
+
+#endif /* CONFIG_GENERIC_HARDIRQS */
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index deebcc5..9d86e45 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -249,14 +249,17 @@ static struct debug_bucket *get_bucket(unsigned long addr)
 
 static void debug_print_object(struct debug_obj *obj, char *msg)
 {
+	struct debug_obj_descr *descr = obj->descr;
 	static int limit;
 
-	if (limit < 5 && obj->descr != descr_test) {
+	if (limit < 5 && descr != descr_test) {
+		void *hint = descr->debug_hint ?
+			descr->debug_hint(obj->object) : NULL;
 		limit++;
 		WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "
-				 "object type: %s\n",
+				 "object type: %s hint: %pS\n",
 			msg, obj_states[obj->state], obj->astate,
-			obj->descr->name);
+			descr->name, hint);
 	}
 	debug_objects_warnings++;
 }
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index b335acb..75ca78f 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -7,6 +7,7 @@
  * Copyright (C) 2008 Jason Baron <jbaron@redhat.com>
  * By Greg Banks <gnb@melbourne.sgi.com>
  * Copyright (c) 2008 Silicon Graphics Inc.  All Rights Reserved.
+ * Copyright (C) 2011 Bart Van Assche.  All Rights Reserved.
  */
 
 #include <linux/kernel.h>
@@ -27,6 +28,8 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/jump_label.h>
+#include <linux/hardirq.h>
+#include <linux/sched.h>
 
 extern struct _ddebug __start___verbose[];
 extern struct _ddebug __stop___verbose[];
@@ -63,15 +66,25 @@ static inline const char *basename(const char *path)
 	return tail ? tail+1 : path;
 }
 
+static struct { unsigned flag:8; char opt_char; } opt_array[] = {
+	{ _DPRINTK_FLAGS_PRINT, 'p' },
+	{ _DPRINTK_FLAGS_INCL_MODNAME, 'm' },
+	{ _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' },
+	{ _DPRINTK_FLAGS_INCL_LINENO, 'l' },
+	{ _DPRINTK_FLAGS_INCL_TID, 't' },
+};
+
 /* format a string into buf[] which describes the _ddebug's flags */
 static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
 				    size_t maxlen)
 {
 	char *p = buf;
+	int i;
 
 	BUG_ON(maxlen < 4);
-	if (dp->flags & _DPRINTK_FLAGS_PRINT)
-		*p++ = 'p';
+	for (i = 0; i < ARRAY_SIZE(opt_array); ++i)
+		if (dp->flags & opt_array[i].flag)
+			*p++ = opt_array[i].opt_char;
 	if (p == buf)
 		*p++ = '-';
 	*p = '\0';
@@ -343,7 +356,7 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
 			       unsigned int *maskp)
 {
 	unsigned flags = 0;
-	int op = '=';
+	int op = '=', i;
 
 	switch (*str) {
 	case '+':
@@ -358,13 +371,14 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp,
 		printk(KERN_INFO "%s: op='%c'\n", __func__, op);
 
 	for ( ; *str ; ++str) {
-		switch (*str) {
-		case 'p':
-			flags |= _DPRINTK_FLAGS_PRINT;
-			break;
-		default:
-			return -EINVAL;
+		for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
+			if (*str == opt_array[i].opt_char) {
+				flags |= opt_array[i].flag;
+				break;
+			}
 		}
+		if (i < 0)
+			return -EINVAL;
 	}
 	if (flags == 0)
 		return -EINVAL;
@@ -413,6 +427,35 @@ static int ddebug_exec_query(char *query_string)
 	return 0;
 }
 
+int __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
+{
+	va_list args;
+	int res;
+
+	BUG_ON(!descriptor);
+	BUG_ON(!fmt);
+
+	va_start(args, fmt);
+	res = printk(KERN_DEBUG);
+	if (descriptor->flags & _DPRINTK_FLAGS_INCL_TID) {
+		if (in_interrupt())
+			res += printk(KERN_CONT "<intr> ");
+		else
+			res += printk(KERN_CONT "[%d] ", task_pid_vnr(current));
+	}
+	if (descriptor->flags & _DPRINTK_FLAGS_INCL_MODNAME)
+		res += printk(KERN_CONT "%s:", descriptor->modname);
+	if (descriptor->flags & _DPRINTK_FLAGS_INCL_FUNCNAME)
+		res += printk(KERN_CONT "%s:", descriptor->function);
+	if (descriptor->flags & _DPRINTK_FLAGS_INCL_LINENO)
+		res += printk(KERN_CONT "%d ", descriptor->lineno);
+	res += vprintk(fmt, args);
+	va_end(args);
+
+	return res;
+}
+EXPORT_SYMBOL(__dynamic_pr_debug);
+
 static __initdata char ddebug_setup_string[1024];
 static __init int ddebug_setup_query(char *str)
 {
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
deleted file mode 100644
index b135d04..0000000
--- a/lib/kernel_lock.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * lib/kernel_lock.c
- *
- * This is the traditional BKL - big kernel lock. Largely
- * relegated to obsolescence, but used by various less
- * important (or lazy) subsystems.
- */
-#include <linux/module.h>
-#include <linux/kallsyms.h>
-#include <linux/semaphore.h>
-#include <linux/smp_lock.h>
-
-#define CREATE_TRACE_POINTS
-#include <trace/events/bkl.h>
-
-/*
- * The 'big kernel lock'
- *
- * This spinlock is taken and released recursively by lock_kernel()
- * and unlock_kernel().  It is transparently dropped and reacquired
- * over schedule().  It is used to protect legacy code that hasn't
- * been migrated to a proper locking design yet.
- *
- * Don't use in new code.
- */
-static  __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(kernel_flag);
-
-
-/*
- * Acquire/release the underlying lock from the scheduler.
- *
- * This is called with preemption disabled, and should
- * return an error value if it cannot get the lock and
- * TIF_NEED_RESCHED gets set.
- *
- * If it successfully gets the lock, it should increment
- * the preemption count like any spinlock does.
- *
- * (This works on UP too - do_raw_spin_trylock will never
- * return false in that case)
- */
-int __lockfunc __reacquire_kernel_lock(void)
-{
-	while (!do_raw_spin_trylock(&kernel_flag)) {
-		if (need_resched())
-			return -EAGAIN;
-		cpu_relax();
-	}
-	preempt_disable();
-	return 0;
-}
-
-void __lockfunc __release_kernel_lock(void)
-{
-	do_raw_spin_unlock(&kernel_flag);
-	preempt_enable_no_resched();
-}
-
-/*
- * These are the BKL spinlocks - we try to be polite about preemption.
- * If SMP is not on (ie UP preemption), this all goes away because the
- * do_raw_spin_trylock() will always succeed.
- */
-#ifdef CONFIG_PREEMPT
-static inline void __lock_kernel(void)
-{
-	preempt_disable();
-	if (unlikely(!do_raw_spin_trylock(&kernel_flag))) {
-		/*
-		 * If preemption was disabled even before this
-		 * was called, there's nothing we can be polite
-		 * about - just spin.
-		 */
-		if (preempt_count() > 1) {
-			do_raw_spin_lock(&kernel_flag);
-			return;
-		}
-
-		/*
-		 * Otherwise, let's wait for the kernel lock
-		 * with preemption enabled..
-		 */
-		do {
-			preempt_enable();
-			while (raw_spin_is_locked(&kernel_flag))
-				cpu_relax();
-			preempt_disable();
-		} while (!do_raw_spin_trylock(&kernel_flag));
-	}
-}
-
-#else
-
-/*
- * Non-preemption case - just get the spinlock
- */
-static inline void __lock_kernel(void)
-{
-	do_raw_spin_lock(&kernel_flag);
-}
-#endif
-
-static inline void __unlock_kernel(void)
-{
-	/*
-	 * the BKL is not covered by lockdep, so we open-code the
-	 * unlocking sequence (and thus avoid the dep-chain ops):
-	 */
-	do_raw_spin_unlock(&kernel_flag);
-	preempt_enable();
-}
-
-/*
- * Getting the big kernel lock.
- *
- * This cannot happen asynchronously, so we only need to
- * worry about other CPU's.
- */
-void __lockfunc _lock_kernel(const char *func, const char *file, int line)
-{
-	int depth = current->lock_depth + 1;
-
-	trace_lock_kernel(func, file, line);
-
-	if (likely(!depth)) {
-		might_sleep();
-		__lock_kernel();
-	}
-	current->lock_depth = depth;
-}
-
-void __lockfunc _unlock_kernel(const char *func, const char *file, int line)
-{
-	BUG_ON(current->lock_depth < 0);
-	if (likely(--current->lock_depth < 0))
-		__unlock_kernel();
-
-	trace_unlock_kernel(func, file, line);
-}
-
-EXPORT_SYMBOL(_lock_kernel);
-EXPORT_SYMBOL(_unlock_kernel);
-
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
new file mode 100644
index 0000000..05672e8
--- /dev/null
+++ b/lib/kstrtox.c
@@ -0,0 +1,227 @@
+/*
+ * Convert integer string representation to an integer.
+ * If an integer doesn't fit into specified type, -E is returned.
+ *
+ * Integer starts with optional sign.
+ * kstrtou*() functions do not accept sign "-".
+ *
+ * Radix 0 means autodetection: leading "0x" implies radix 16,
+ * leading "0" implies radix 8, otherwise radix is 10.
+ * Autodetection hints work after optional sign, but not before.
+ *
+ * If -E is returned, result is not touched.
+ */
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/types.h>
+
+static inline char _tolower(const char c)
+{
+	return c | 0x20;
+}
+
+static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+	unsigned long long acc;
+	int ok;
+
+	if (base == 0) {
+		if (s[0] == '0') {
+			if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
+				base = 16;
+			else
+				base = 8;
+		} else
+			base = 10;
+	}
+	if (base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
+		s += 2;
+
+	acc = 0;
+	ok = 0;
+	while (*s) {
+		unsigned int val;
+
+		if ('0' <= *s && *s <= '9')
+			val = *s - '0';
+		else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
+			val = _tolower(*s) - 'a' + 10;
+		else if (*s == '\n') {
+			if (*(s + 1) == '\0')
+				break;
+			else
+				return -EINVAL;
+		} else
+			return -EINVAL;
+
+		if (val >= base)
+			return -EINVAL;
+		if (acc > div_u64(ULLONG_MAX - val, base))
+			return -ERANGE;
+		acc = acc * base + val;
+		ok = 1;
+
+		s++;
+	}
+	if (!ok)
+		return -EINVAL;
+	*res = acc;
+	return 0;
+}
+
+int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+	if (s[0] == '+')
+		s++;
+	return _kstrtoull(s, base, res);
+}
+EXPORT_SYMBOL(kstrtoull);
+
+int kstrtoll(const char *s, unsigned int base, long long *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	if (s[0] == '-') {
+		rv = _kstrtoull(s + 1, base, &tmp);
+		if (rv < 0)
+			return rv;
+		if ((long long)(-tmp) >= 0)
+			return -ERANGE;
+		*res = -tmp;
+	} else {
+		rv = kstrtoull(s, base, &tmp);
+		if (rv < 0)
+			return rv;
+		if ((long long)tmp < 0)
+			return -ERANGE;
+		*res = tmp;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(kstrtoll);
+
+/* Internal, do not use. */
+int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(unsigned long)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(_kstrtoul);
+
+/* Internal, do not use. */
+int _kstrtol(const char *s, unsigned int base, long *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(long)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(_kstrtol);
+
+int kstrtouint(const char *s, unsigned int base, unsigned int *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(unsigned int)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtouint);
+
+int kstrtoint(const char *s, unsigned int base, int *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(int)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtoint);
+
+int kstrtou16(const char *s, unsigned int base, u16 *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(u16)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtou16);
+
+int kstrtos16(const char *s, unsigned int base, s16 *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(s16)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtos16);
+
+int kstrtou8(const char *s, unsigned int base, u8 *res)
+{
+	unsigned long long tmp;
+	int rv;
+
+	rv = kstrtoull(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (unsigned long long)(u8)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtou8);
+
+int kstrtos8(const char *s, unsigned int base, s8 *res)
+{
+	long long tmp;
+	int rv;
+
+	rv = kstrtoll(s, base, &tmp);
+	if (rv < 0)
+		return rv;
+	if (tmp != (long long)(s8)tmp)
+		return -ERANGE;
+	*res = tmp;
+	return 0;
+}
+EXPORT_SYMBOL(kstrtos8);
diff --git a/lib/plist.c b/lib/plist.c
index 1471988..0ae7e64 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -28,6 +28,8 @@
 
 #ifdef CONFIG_DEBUG_PI_LIST
 
+static struct plist_head test_head;
+
 static void plist_check_prev_next(struct list_head *t, struct list_head *p,
 				  struct list_head *n)
 {
@@ -54,12 +56,13 @@ static void plist_check_list(struct list_head *top)
 
 static void plist_check_head(struct plist_head *head)
 {
-	WARN_ON(!head->rawlock && !head->spinlock);
+	WARN_ON(head != &test_head && !head->rawlock && !head->spinlock);
 	if (head->rawlock)
 		WARN_ON_SMP(!raw_spin_is_locked(head->rawlock));
 	if (head->spinlock)
 		WARN_ON_SMP(!spin_is_locked(head->spinlock));
-	plist_check_list(&head->prio_list);
+	if (!plist_head_empty(head))
+		plist_check_list(&plist_first(head)->prio_list);
 	plist_check_list(&head->node_list);
 }
 
@@ -75,25 +78,33 @@ static void plist_check_head(struct plist_head *head)
  */
 void plist_add(struct plist_node *node, struct plist_head *head)
 {
-	struct plist_node *iter;
+	struct plist_node *first, *iter, *prev = NULL;
+	struct list_head *node_next = &head->node_list;
 
 	plist_check_head(head);
 	WARN_ON(!plist_node_empty(node));
+	WARN_ON(!list_empty(&node->prio_list));
+
+	if (plist_head_empty(head))
+		goto ins_node;
 
-	list_for_each_entry(iter, &head->prio_list, plist.prio_list) {
-		if (node->prio < iter->prio)
-			goto lt_prio;
-		else if (node->prio == iter->prio) {
-			iter = list_entry(iter->plist.prio_list.next,
-					struct plist_node, plist.prio_list);
-			goto eq_prio;
+	first = iter = plist_first(head);
+
+	do {
+		if (node->prio < iter->prio) {
+			node_next = &iter->node_list;
+			break;
 		}
-	}
 
-lt_prio:
-	list_add_tail(&node->plist.prio_list, &iter->plist.prio_list);
-eq_prio:
-	list_add_tail(&node->plist.node_list, &iter->plist.node_list);
+		prev = iter;
+		iter = list_entry(iter->prio_list.next,
+				struct plist_node, prio_list);
+	} while (iter != first);
+
+	if (!prev || prev->prio != node->prio)
+		list_add_tail(&node->prio_list, &iter->prio_list);
+ins_node:
+	list_add_tail(&node->node_list, node_next);
 
 	plist_check_head(head);
 }
@@ -108,14 +119,98 @@ void plist_del(struct plist_node *node, struct plist_head *head)
 {
 	plist_check_head(head);
 
-	if (!list_empty(&node->plist.prio_list)) {
-		struct plist_node *next = plist_first(&node->plist);
+	if (!list_empty(&node->prio_list)) {
+		if (node->node_list.next != &head->node_list) {
+			struct plist_node *next;
+
+			next = list_entry(node->node_list.next,
+					struct plist_node, node_list);
 
-		list_move_tail(&next->plist.prio_list, &node->plist.prio_list);
-		list_del_init(&node->plist.prio_list);
+			/* add the next plist_node into prio_list */
+			if (list_empty(&next->prio_list))
+				list_add(&next->prio_list, &node->prio_list);
+		}
+		list_del_init(&node->prio_list);
 	}
 
-	list_del_init(&node->plist.node_list);
+	list_del_init(&node->node_list);
 
 	plist_check_head(head);
 }
+
+#ifdef CONFIG_DEBUG_PI_LIST
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+static struct plist_node __initdata test_node[241];
+
+static void __init plist_test_check(int nr_expect)
+{
+	struct plist_node *first, *prio_pos, *node_pos;
+
+	if (plist_head_empty(&test_head)) {
+		BUG_ON(nr_expect != 0);
+		return;
+	}
+
+	prio_pos = first = plist_first(&test_head);
+	plist_for_each(node_pos, &test_head) {
+		if (nr_expect-- < 0)
+			break;
+		if (node_pos == first)
+			continue;
+		if (node_pos->prio == prio_pos->prio) {
+			BUG_ON(!list_empty(&node_pos->prio_list));
+			continue;
+		}
+
+		BUG_ON(prio_pos->prio > node_pos->prio);
+		BUG_ON(prio_pos->prio_list.next != &node_pos->prio_list);
+		prio_pos = node_pos;
+	}
+
+	BUG_ON(nr_expect != 0);
+	BUG_ON(prio_pos->prio_list.next != &first->prio_list);
+}
+
+static int  __init plist_test(void)
+{
+	int nr_expect = 0, i, loop;
+	unsigned int r = local_clock();
+
+	printk(KERN_INFO "start plist test\n");
+	plist_head_init(&test_head, NULL);
+	for (i = 0; i < ARRAY_SIZE(test_node); i++)
+		plist_node_init(test_node + i, 0);
+
+	for (loop = 0; loop < 1000; loop++) {
+		r = r * 193939 % 47629;
+		i = r % ARRAY_SIZE(test_node);
+		if (plist_node_empty(test_node + i)) {
+			r = r * 193939 % 47629;
+			test_node[i].prio = r % 99;
+			plist_add(test_node + i, &test_head);
+			nr_expect++;
+		} else {
+			plist_del(test_node + i, &test_head);
+			nr_expect--;
+		}
+		plist_test_check(nr_expect);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(test_node); i++) {
+		if (plist_node_empty(test_node + i))
+			continue;
+		plist_del(test_node + i, &test_head);
+		nr_expect--;
+		plist_test_check(nr_expect);
+	}
+
+	printk(KERN_INFO "end plist test\n");
+	return 0;
+}
+
+module_init(plist_test);
+
+#endif
diff --git a/lib/rwsem.c b/lib/rwsem.c
index f236d7c..aa7c305 100644
--- a/lib/rwsem.c
+++ b/lib/rwsem.c
@@ -222,8 +222,7 @@ rwsem_down_failed_common(struct rw_semaphore *sem,
 /*
  * wait for the read lock to be granted
  */
-asmregparm struct rw_semaphore __sched *
-rwsem_down_read_failed(struct rw_semaphore *sem)
+struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
 {
 	return rwsem_down_failed_common(sem, RWSEM_WAITING_FOR_READ,
 					-RWSEM_ACTIVE_READ_BIAS);
@@ -232,8 +231,7 @@ rwsem_down_read_failed(struct rw_semaphore *sem)
 /*
  * wait for the write lock to be granted
  */
-asmregparm struct rw_semaphore __sched *
-rwsem_down_write_failed(struct rw_semaphore *sem)
+struct rw_semaphore __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
 {
 	return rwsem_down_failed_common(sem, RWSEM_WAITING_FOR_WRITE,
 					-RWSEM_ACTIVE_WRITE_BIAS);
@@ -243,7 +241,7 @@ rwsem_down_write_failed(struct rw_semaphore *sem)
  * handle waking up a waiter on the semaphore
  * - up_read/up_write has decremented the active part of count if we come here
  */
-asmregparm struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
+struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
 {
 	unsigned long flags;
 
@@ -263,7 +261,7 @@ asmregparm struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
  * - caller incremented waiting part of count and discovered it still negative
  * - just wake up any readers at the front of the queue
  */
-asmregparm struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
+struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem)
 {
 	unsigned long flags;
 
diff --git a/lib/show_mem.c b/lib/show_mem.c
index fdc77c8..d8d602b 100644
--- a/lib/show_mem.c
+++ b/lib/show_mem.c
@@ -9,14 +9,14 @@
 #include <linux/nmi.h>
 #include <linux/quicklist.h>
 
-void show_mem(void)
+void __show_mem(unsigned int filter)
 {
 	pg_data_t *pgdat;
 	unsigned long total = 0, reserved = 0, shared = 0,
 		nonshared = 0, highmem = 0;
 
 	printk("Mem-Info:\n");
-	show_free_areas();
+	__show_free_areas(filter);
 
 	for_each_online_pgdat(pgdat) {
 		unsigned long i, flags;
@@ -61,3 +61,8 @@ void show_mem(void)
 		quicklist_total_size());
 #endif
 }
+
+void show_mem(void)
+{
+	__show_mem(0);
+}
diff --git a/lib/test-kstrtox.c b/lib/test-kstrtox.c
new file mode 100644
index 0000000..325c2f9
--- /dev/null
+++ b/lib/test-kstrtox.c
@@ -0,0 +1,739 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#define for_each_test(i, test)	\
+	for (i = 0; i < sizeof(test) / sizeof(test[0]); i++)
+
+struct test_fail {
+	const char *str;
+	unsigned int base;
+};
+
+#define DEFINE_TEST_FAIL(test)	\
+	const struct test_fail test[] __initdata
+
+#define DECLARE_TEST_OK(type, test_type)	\
+	test_type {				\
+		const char *str;		\
+		unsigned int base;		\
+		type expected_res;		\
+	}
+
+#define DEFINE_TEST_OK(type, test)	\
+	const type test[] __initdata
+
+#define TEST_FAIL(fn, type, fmt, test)					\
+{									\
+	unsigned int i;							\
+									\
+	for_each_test(i, test) {					\
+		const struct test_fail *t = &test[i];			\
+		type tmp;						\
+		int rv;							\
+									\
+		tmp = 0;						\
+		rv = fn(t->str, t->base, &tmp);				\
+		if (rv >= 0) {						\
+			WARN(1, "str '%s', base %u, expected -E, got %d/" fmt "\n",	\
+				t->str, t->base, rv, tmp);		\
+			continue;					\
+		}							\
+	}								\
+}
+
+#define TEST_OK(fn, type, fmt, test)					\
+{									\
+	unsigned int i;							\
+									\
+	for_each_test(i, test) {					\
+		const typeof(test[0]) *t = &test[i];			\
+		type res;						\
+		int rv;							\
+									\
+		rv = fn(t->str, t->base, &res);				\
+		if (rv != 0) {						\
+			WARN(1, "str '%s', base %u, expected 0/" fmt ", got %d\n",	\
+				t->str, t->base, t->expected_res, rv);	\
+			continue;					\
+		}							\
+		if (res != t->expected_res) {				\
+			WARN(1, "str '%s', base %u, expected " fmt ", got " fmt "\n",	\
+				t->str, t->base, t->expected_res, res);	\
+			continue;					\
+		}							\
+	}								\
+}
+
+static void __init test_kstrtoull_ok(void)
+{
+	DECLARE_TEST_OK(unsigned long long, struct test_ull);
+	static DEFINE_TEST_OK(struct test_ull, test_ull_ok) = {
+		{"0",	10,	0ULL},
+		{"1",	10,	1ULL},
+		{"127",	10,	127ULL},
+		{"128",	10,	128ULL},
+		{"129",	10,	129ULL},
+		{"255",	10,	255ULL},
+		{"256",	10,	256ULL},
+		{"257",	10,	257ULL},
+		{"32767",	10,	32767ULL},
+		{"32768",	10,	32768ULL},
+		{"32769",	10,	32769ULL},
+		{"65535",	10,	65535ULL},
+		{"65536",	10,	65536ULL},
+		{"65537",	10,	65537ULL},
+		{"2147483647",	10,	2147483647ULL},
+		{"2147483648",	10,	2147483648ULL},
+		{"2147483649",	10,	2147483649ULL},
+		{"4294967295",	10,	4294967295ULL},
+		{"4294967296",	10,	4294967296ULL},
+		{"4294967297",	10,	4294967297ULL},
+		{"9223372036854775807",	10,	9223372036854775807ULL},
+		{"9223372036854775808",	10,	9223372036854775808ULL},
+		{"9223372036854775809",	10,	9223372036854775809ULL},
+		{"18446744073709551614",	10,	18446744073709551614ULL},
+		{"18446744073709551615",	10,	18446744073709551615ULL},
+
+		{"00",		8,	00ULL},
+		{"01",		8,	01ULL},
+		{"0177",	8,	0177ULL},
+		{"0200",	8,	0200ULL},
+		{"0201",	8,	0201ULL},
+		{"0377",	8,	0377ULL},
+		{"0400",	8,	0400ULL},
+		{"0401",	8,	0401ULL},
+		{"077777",	8,	077777ULL},
+		{"0100000",	8,	0100000ULL},
+		{"0100001",	8,	0100001ULL},
+		{"0177777",	8,	0177777ULL},
+		{"0200000",	8,	0200000ULL},
+		{"0200001",	8,	0200001ULL},
+		{"017777777777",	8,	017777777777ULL},
+		{"020000000000",	8,	020000000000ULL},
+		{"020000000001",	8,	020000000001ULL},
+		{"037777777777",	8,	037777777777ULL},
+		{"040000000000",	8,	040000000000ULL},
+		{"040000000001",	8,	040000000001ULL},
+		{"0777777777777777777777",	8,	0777777777777777777777ULL},
+		{"01000000000000000000000",	8,	01000000000000000000000ULL},
+		{"01000000000000000000001",	8,	01000000000000000000001ULL},
+		{"01777777777777777777776",	8,	01777777777777777777776ULL},
+		{"01777777777777777777777",	8,	01777777777777777777777ULL},
+
+		{"0x0",		16,	0x0ULL},
+		{"0x1",		16,	0x1ULL},
+		{"0x7f",	16,	0x7fULL},
+		{"0x80",	16,	0x80ULL},
+		{"0x81",	16,	0x81ULL},
+		{"0xff",	16,	0xffULL},
+		{"0x100",	16,	0x100ULL},
+		{"0x101",	16,	0x101ULL},
+		{"0x7fff",	16,	0x7fffULL},
+		{"0x8000",	16,	0x8000ULL},
+		{"0x8001",	16,	0x8001ULL},
+		{"0xffff",	16,	0xffffULL},
+		{"0x10000",	16,	0x10000ULL},
+		{"0x10001",	16,	0x10001ULL},
+		{"0x7fffffff",	16,	0x7fffffffULL},
+		{"0x80000000",	16,	0x80000000ULL},
+		{"0x80000001",	16,	0x80000001ULL},
+		{"0xffffffff",	16,	0xffffffffULL},
+		{"0x100000000",	16,	0x100000000ULL},
+		{"0x100000001",	16,	0x100000001ULL},
+		{"0x7fffffffffffffff",	16,	0x7fffffffffffffffULL},
+		{"0x8000000000000000",	16,	0x8000000000000000ULL},
+		{"0x8000000000000001",	16,	0x8000000000000001ULL},
+		{"0xfffffffffffffffe",	16,	0xfffffffffffffffeULL},
+		{"0xffffffffffffffff",	16,	0xffffffffffffffffULL},
+
+		{"0\n",	0,	0ULL},
+	};
+	TEST_OK(kstrtoull, unsigned long long, "%llu", test_ull_ok);
+}
+
+static void __init test_kstrtoull_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_ull_fail) = {
+		{"",	0},
+		{"",	8},
+		{"",	10},
+		{"",	16},
+		{"\n",	0},
+		{"\n",	8},
+		{"\n",	10},
+		{"\n",	16},
+		{"\n0",	0},
+		{"\n0",	8},
+		{"\n0",	10},
+		{"\n0",	16},
+		{"+",	0},
+		{"+",	8},
+		{"+",	10},
+		{"+",	16},
+		{"-",	0},
+		{"-",	8},
+		{"-",	10},
+		{"-",	16},
+		{"0x",	0},
+		{"0x",	16},
+		{"0X",	0},
+		{"0X",	16},
+		{"0 ",	0},
+		{"1+",	0},
+		{"1-",	0},
+		{" 2",	0},
+		/* base autodetection */
+		{"0x0z",	0},
+		{"0z",		0},
+		{"a",		0},
+		/* digit >= base */
+		{"2",	2},
+		{"8",	8},
+		{"a",	10},
+		{"A",	10},
+		{"g",	16},
+		{"G",	16},
+		/* overflow */
+		{"10000000000000000000000000000000000000000000000000000000000000000",	2},
+		{"2000000000000000000000",	8},
+		{"18446744073709551616",	10},
+		{"10000000000000000",	16},
+		/* negative */
+		{"-0", 0},
+		{"-0", 8},
+		{"-0", 10},
+		{"-0", 16},
+		{"-1", 0},
+		{"-1", 8},
+		{"-1", 10},
+		{"-1", 16},
+		/* sign is first character if any */
+		{"-+1", 0},
+		{"-+1", 8},
+		{"-+1", 10},
+		{"-+1", 16},
+		/* nothing after \n */
+		{"0\n0", 0},
+		{"0\n0", 8},
+		{"0\n0", 10},
+		{"0\n0", 16},
+		{"0\n+", 0},
+		{"0\n+", 8},
+		{"0\n+", 10},
+		{"0\n+", 16},
+		{"0\n-", 0},
+		{"0\n-", 8},
+		{"0\n-", 10},
+		{"0\n-", 16},
+		{"0\n ", 0},
+		{"0\n ", 8},
+		{"0\n ", 10},
+		{"0\n ", 16},
+	};
+	TEST_FAIL(kstrtoull, unsigned long long, "%llu", test_ull_fail);
+}
+
+static void __init test_kstrtoll_ok(void)
+{
+	DECLARE_TEST_OK(long long, struct test_ll);
+	static DEFINE_TEST_OK(struct test_ll, test_ll_ok) = {
+		{"0",	10,	0LL},
+		{"1",	10,	1LL},
+		{"127",	10,	127LL},
+		{"128",	10,	128LL},
+		{"129",	10,	129LL},
+		{"255",	10,	255LL},
+		{"256",	10,	256LL},
+		{"257",	10,	257LL},
+		{"32767",	10,	32767LL},
+		{"32768",	10,	32768LL},
+		{"32769",	10,	32769LL},
+		{"65535",	10,	65535LL},
+		{"65536",	10,	65536LL},
+		{"65537",	10,	65537LL},
+		{"2147483647",	10,	2147483647LL},
+		{"2147483648",	10,	2147483648LL},
+		{"2147483649",	10,	2147483649LL},
+		{"4294967295",	10,	4294967295LL},
+		{"4294967296",	10,	4294967296LL},
+		{"4294967297",	10,	4294967297LL},
+		{"9223372036854775807",	10,	9223372036854775807LL},
+
+		{"-1",	10,	-1LL},
+		{"-2",	10,	-2LL},
+		{"-9223372036854775808",	10,	LLONG_MIN},
+	};
+	TEST_OK(kstrtoll, long long, "%lld", test_ll_ok);
+}
+
+static void __init test_kstrtoll_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_ll_fail) = {
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"-9223372036854775809",	10},
+		{"-18446744073709551614",	10},
+		{"-18446744073709551615",	10},
+		/* negative zero isn't an integer in Linux */
+		{"-0",	0},
+		{"-0",	8},
+		{"-0",	10},
+		{"-0",	16},
+		/* sign is first character if any */
+		{"-+1", 0},
+		{"-+1", 8},
+		{"-+1", 10},
+		{"-+1", 16},
+	};
+	TEST_FAIL(kstrtoll, long long, "%lld", test_ll_fail);
+}
+
+static void __init test_kstrtou64_ok(void)
+{
+	DECLARE_TEST_OK(u64, struct test_u64);
+	static DEFINE_TEST_OK(struct test_u64, test_u64_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+		{"2147483648",	10,	2147483648},
+		{"2147483649",	10,	2147483649},
+		{"4294967294",	10,	4294967294},
+		{"4294967295",	10,	4294967295},
+		{"4294967296",	10,	4294967296},
+		{"4294967297",	10,	4294967297},
+		{"9223372036854775806",	10,	9223372036854775806ULL},
+		{"9223372036854775807",	10,	9223372036854775807ULL},
+		{"9223372036854775808",	10,	9223372036854775808ULL},
+		{"9223372036854775809",	10,	9223372036854775809ULL},
+		{"18446744073709551614",	10,	18446744073709551614ULL},
+		{"18446744073709551615",	10,	18446744073709551615ULL},
+	};
+	TEST_OK(kstrtou64, u64, "%llu", test_u64_ok);
+}
+
+static void __init test_kstrtou64_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u64_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou64, u64, "%llu", test_u64_fail);
+}
+
+static void __init test_kstrtos64_ok(void)
+{
+	DECLARE_TEST_OK(s64, struct test_s64);
+	static DEFINE_TEST_OK(struct test_s64, test_s64_ok) = {
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+		{"2147483648",	10,	2147483648},
+		{"2147483649",	10,	2147483649},
+		{"4294967294",	10,	4294967294},
+		{"4294967295",	10,	4294967295},
+		{"4294967296",	10,	4294967296},
+		{"4294967297",	10,	4294967297},
+		{"9223372036854775806",	10,	9223372036854775806LL},
+		{"9223372036854775807",	10,	9223372036854775807LL},
+	};
+	TEST_OK(kstrtos64, s64, "%lld", test_s64_ok);
+}
+
+static void __init test_kstrtos64_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s64_fail) = {
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos64, s64, "%lld", test_s64_fail);
+}
+
+static void __init test_kstrtou32_ok(void)
+{
+	DECLARE_TEST_OK(u32, struct test_u32);
+	static DEFINE_TEST_OK(struct test_u32, test_u32_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+		{"2147483648",	10,	2147483648},
+		{"2147483649",	10,	2147483649},
+		{"4294967294",	10,	4294967294},
+		{"4294967295",	10,	4294967295},
+	};
+	TEST_OK(kstrtou32, u32, "%u", test_u32_ok);
+}
+
+static void __init test_kstrtou32_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u32_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou32, u32, "%u", test_u32_fail);
+}
+
+static void __init test_kstrtos32_ok(void)
+{
+	DECLARE_TEST_OK(s32, struct test_s32);
+	static DEFINE_TEST_OK(struct test_s32, test_s32_ok) = {
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+		{"65536",	10,	65536},
+		{"65537",	10,	65537},
+		{"2147483646",	10,	2147483646},
+		{"2147483647",	10,	2147483647},
+	};
+	TEST_OK(kstrtos32, s32, "%d", test_s32_ok);
+}
+
+static void __init test_kstrtos32_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s32_fail) = {
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos32, s32, "%d", test_s32_fail);
+}
+
+static void __init test_kstrtou16_ok(void)
+{
+	DECLARE_TEST_OK(u16, struct test_u16);
+	static DEFINE_TEST_OK(struct test_u16, test_u16_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+		{"32768",	10,	32768},
+		{"32769",	10,	32769},
+		{"65534",	10,	65534},
+		{"65535",	10,	65535},
+	};
+	TEST_OK(kstrtou16, u16, "%hu", test_u16_ok);
+}
+
+static void __init test_kstrtou16_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u16_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou16, u16, "%hu", test_u16_fail);
+}
+
+static void __init test_kstrtos16_ok(void)
+{
+	DECLARE_TEST_OK(s16, struct test_s16);
+	static DEFINE_TEST_OK(struct test_s16, test_s16_ok) = {
+		{"-130",	10,	-130},
+		{"-129",	10,	-129},
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+		{"256",	10,	256},
+		{"257",	10,	257},
+		{"32766",	10,	32766},
+		{"32767",	10,	32767},
+	};
+	TEST_OK(kstrtos16, s16, "%hd", test_s16_ok);
+}
+
+static void __init test_kstrtos16_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s16_fail) = {
+		{"32768",	10},
+		{"32769",	10},
+		{"65534",	10},
+		{"65535",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos16, s16, "%hd", test_s16_fail);
+}
+
+static void __init test_kstrtou8_ok(void)
+{
+	DECLARE_TEST_OK(u8, struct test_u8);
+	static DEFINE_TEST_OK(struct test_u8, test_u8_ok) = {
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+		{"128",	10,	128},
+		{"129",	10,	129},
+		{"254",	10,	254},
+		{"255",	10,	255},
+	};
+	TEST_OK(kstrtou8, u8, "%hhu", test_u8_ok);
+}
+
+static void __init test_kstrtou8_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_u8_fail) = {
+		{"-2",	10},
+		{"-1",	10},
+		{"256",	10},
+		{"257",	10},
+		{"32766",	10},
+		{"32767",	10},
+		{"32768",	10},
+		{"32769",	10},
+		{"65534",	10},
+		{"65535",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtou8, u8, "%hhu", test_u8_fail);
+}
+
+static void __init test_kstrtos8_ok(void)
+{
+	DECLARE_TEST_OK(s8, struct test_s8);
+	static DEFINE_TEST_OK(struct test_s8, test_s8_ok) = {
+		{"-128",	10,	-128},
+		{"-127",	10,	-127},
+		{"-1",	10,	-1},
+		{"0",	10,	0},
+		{"1",	10,	1},
+		{"126",	10,	126},
+		{"127",	10,	127},
+	};
+	TEST_OK(kstrtos8, s8, "%hhd", test_s8_ok);
+}
+
+static void __init test_kstrtos8_fail(void)
+{
+	static DEFINE_TEST_FAIL(test_s8_fail) = {
+		{"-130",	10},
+		{"-129",	10},
+		{"128",	10},
+		{"129",	10},
+		{"254",	10},
+		{"255",	10},
+		{"256",	10},
+		{"257",	10},
+		{"32766",	10},
+		{"32767",	10},
+		{"32768",	10},
+		{"32769",	10},
+		{"65534",	10},
+		{"65535",	10},
+		{"65536",	10},
+		{"65537",	10},
+		{"2147483646",	10},
+		{"2147483647",	10},
+		{"2147483648",	10},
+		{"2147483649",	10},
+		{"4294967294",	10},
+		{"4294967295",	10},
+		{"4294967296",	10},
+		{"4294967297",	10},
+		{"9223372036854775806",	10},
+		{"9223372036854775807",	10},
+		{"9223372036854775808",	10},
+		{"9223372036854775809",	10},
+		{"18446744073709551614",	10},
+		{"18446744073709551615",	10},
+		{"18446744073709551616",	10},
+		{"18446744073709551617",	10},
+	};
+	TEST_FAIL(kstrtos8, s8, "%hhd", test_s8_fail);
+}
+
+static int __init test_kstrtox_init(void)
+{
+	test_kstrtoull_ok();
+	test_kstrtoull_fail();
+	test_kstrtoll_ok();
+	test_kstrtoll_fail();
+
+	test_kstrtou64_ok();
+	test_kstrtou64_fail();
+	test_kstrtos64_ok();
+	test_kstrtos64_fail();
+
+	test_kstrtou32_ok();
+	test_kstrtou32_fail();
+	test_kstrtos32_ok();
+	test_kstrtos32_fail();
+
+	test_kstrtou16_ok();
+	test_kstrtou16_fail();
+	test_kstrtos16_ok();
+	test_kstrtos16_fail();
+
+	test_kstrtou8_ok();
+	test_kstrtou8_fail();
+	test_kstrtos8_ok();
+	test_kstrtos8_fail();
+	return -EINVAL;
+}
+module_init(test_kstrtox_init);
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d3023df..02bcdd5 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -120,147 +120,6 @@ long long simple_strtoll(const char *cp, char **endp, unsigned int base)
 }
 EXPORT_SYMBOL(simple_strtoll);
 
-/**
- * strict_strtoul - convert a string to an unsigned long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtoul converts a string to an unsigned long only if the
- * string is really an unsigned long string, any string containing
- * any invalid char at the tail will be rejected and -EINVAL is returned,
- * only a newline char at the tail is acceptible because people generally
- * change a module parameter in the following way:
- *
- * 	echo 1024 > /sys/module/e1000/parameters/copybreak
- *
- * echo will append a newline to the tail.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- *
- * simple_strtoul just ignores the successive invalid characters and
- * return the converted value of prefix part of the string.
- */
-int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
-{
-	char *tail;
-	unsigned long val;
-
-	*res = 0;
-	if (!*cp)
-		return -EINVAL;
-
-	val = simple_strtoul(cp, &tail, base);
-	if (tail == cp)
-		return -EINVAL;
-
-	if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) {
-		*res = val;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(strict_strtoul);
-
-/**
- * strict_strtol - convert a string to a long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtol is similiar to strict_strtoul, but it allows the first
- * character of a string is '-'.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- */
-int strict_strtol(const char *cp, unsigned int base, long *res)
-{
-	int ret;
-	if (*cp == '-') {
-		ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
-		if (!ret)
-			*res = -(*res);
-	} else {
-		ret = strict_strtoul(cp, base, (unsigned long *)res);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(strict_strtol);
-
-/**
- * strict_strtoull - convert a string to an unsigned long long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtoull converts a string to an unsigned long long only if the
- * string is really an unsigned long long string, any string containing
- * any invalid char at the tail will be rejected and -EINVAL is returned,
- * only a newline char at the tail is acceptible because people generally
- * change a module parameter in the following way:
- *
- * 	echo 1024 > /sys/module/e1000/parameters/copybreak
- *
- * echo will append a newline to the tail of the string.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- *
- * simple_strtoull just ignores the successive invalid characters and
- * return the converted value of prefix part of the string.
- */
-int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
-{
-	char *tail;
-	unsigned long long val;
-
-	*res = 0;
-	if (!*cp)
-		return -EINVAL;
-
-	val = simple_strtoull(cp, &tail, base);
-	if (tail == cp)
-		return -EINVAL;
-	if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) {
-		*res = val;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-EXPORT_SYMBOL(strict_strtoull);
-
-/**
- * strict_strtoll - convert a string to a long long strictly
- * @cp: The string to be converted
- * @base: The number base to use
- * @res: The converted result value
- *
- * strict_strtoll is similiar to strict_strtoull, but it allows the first
- * character of a string is '-'.
- *
- * It returns 0 if conversion is successful and *res is set to the converted
- * value, otherwise it returns -EINVAL and *res is set to 0.
- */
-int strict_strtoll(const char *cp, unsigned int base, long long *res)
-{
-	int ret;
-	if (*cp == '-') {
-		ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
-		if (!ret)
-			*res = -(*res);
-	} else {
-		ret = strict_strtoull(cp, base, (unsigned long long *)res);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(strict_strtoll);
-
 static noinline_for_stack
 int skip_atoi(const char **s)
 {
@@ -991,7 +850,7 @@ static noinline_for_stack
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 	      struct printf_spec spec)
 {
-	if (!ptr) {
+	if (!ptr && *fmt != 'K') {
 		/*
 		 * Print (null) with the same width as a pointer so it makes
 		 * tabular output look nice.
@@ -1047,16 +906,12 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 			if (spec.field_width == -1)
 				spec.field_width = 2 * sizeof(void *);
 			return string(buf, end, "pK-error", spec);
-		} else if ((kptr_restrict == 0) ||
-			 (kptr_restrict == 1 &&
-			  has_capability_noaudit(current, CAP_SYSLOG)))
-			break;
-
-		if (spec.field_width == -1) {
-			spec.field_width = 2 * sizeof(void *);
-			spec.flags |= ZEROPAD;
 		}
-		return number(buf, end, 0, spec);
+		if (!((kptr_restrict == 0) ||
+		      (kptr_restrict == 1 &&
+		       has_capability_noaudit(current, CAP_SYSLOG))))
+			ptr = NULL;
+		break;
 	}
 	spec.flags |= SMALL;
 	if (spec.field_width == -1) {
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
index 46a31e5..d63381e 100644
--- a/lib/zlib_deflate/deflate.c
+++ b/lib/zlib_deflate/deflate.c
@@ -176,6 +176,7 @@ int zlib_deflateInit2(
     deflate_state *s;
     int noheader = 0;
     deflate_workspace *mem;
+    char *next;
 
     ush *overlay;
     /* We overlay pending_buf and d_buf+l_buf. This works since the average
@@ -199,6 +200,21 @@ int zlib_deflateInit2(
 	strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
         return Z_STREAM_ERROR;
     }
+
+    /*
+     * Direct the workspace's pointers to the chunks that were allocated
+     * along with the deflate_workspace struct.
+     */
+    next = (char *) mem;
+    next += sizeof(*mem);
+    mem->window_memory = (Byte *) next;
+    next += zlib_deflate_window_memsize(windowBits);
+    mem->prev_memory = (Pos *) next;
+    next += zlib_deflate_prev_memsize(windowBits);
+    mem->head_memory = (Pos *) next;
+    next += zlib_deflate_head_memsize(memLevel);
+    mem->overlay_memory = next;
+
     s = (deflate_state *) &(mem->deflate_memory);
     strm->state = (struct internal_state *)s;
     s->strm = strm;
@@ -1247,7 +1263,18 @@ static block_state deflate_slow(
     return flush == Z_FINISH ? finish_done : block_done;
 }
 
-int zlib_deflate_workspacesize(void)
+int zlib_deflate_workspacesize(int windowBits, int memLevel)
 {
-    return sizeof(deflate_workspace);
+    if (windowBits < 0) /* undocumented feature: suppress zlib header */
+        windowBits = -windowBits;
+
+    /* Since the return value is typically passed to vmalloc() unchecked... */
+    BUG_ON(memLevel < 1 || memLevel > MAX_MEM_LEVEL || windowBits < 9 ||
+							windowBits > 15);
+
+    return sizeof(deflate_workspace)
+        + zlib_deflate_window_memsize(windowBits)
+        + zlib_deflate_prev_memsize(windowBits)
+        + zlib_deflate_head_memsize(memLevel)
+        + zlib_deflate_overlay_memsize(memLevel);
 }
diff --git a/lib/zlib_deflate/defutil.h b/lib/zlib_deflate/defutil.h
index 6b15a90..b640b64 100644
--- a/lib/zlib_deflate/defutil.h
+++ b/lib/zlib_deflate/defutil.h
@@ -241,12 +241,21 @@ typedef struct deflate_state {
 typedef struct deflate_workspace {
     /* State memory for the deflator */
     deflate_state deflate_memory;
-    Byte window_memory[2 * (1 << MAX_WBITS)];
-    Pos prev_memory[1 << MAX_WBITS];
-    Pos head_memory[1 << (MAX_MEM_LEVEL + 7)];
-    char overlay_memory[(1 << (MAX_MEM_LEVEL + 6)) * (sizeof(ush)+2)];
+    Byte *window_memory;
+    Pos *prev_memory;
+    Pos *head_memory;
+    char *overlay_memory;
 } deflate_workspace;
 
+#define zlib_deflate_window_memsize(windowBits) \
+	(2 * (1 << (windowBits)) * sizeof(Byte))
+#define zlib_deflate_prev_memsize(windowBits) \
+	((1 << (windowBits)) * sizeof(Pos))
+#define zlib_deflate_head_memsize(memLevel) \
+	((1 << ((memLevel)+7)) * sizeof(Pos))
+#define zlib_deflate_overlay_memsize(memLevel) \
+	((1 << ((memLevel)+6)) * (sizeof(ush)+2))
+
 /* Output a byte on the stream.
  * IN assertion: there is enough room in pending_buf.
  */
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug
index af7cfb4..8b1a477 100644
--- a/mm/Kconfig.debug
+++ b/mm/Kconfig.debug
@@ -1,27 +1,24 @@
 config DEBUG_PAGEALLOC
 	bool "Debug page memory allocations"
-	depends on DEBUG_KERNEL && ARCH_SUPPORTS_DEBUG_PAGEALLOC
-	depends on !HIBERNATION || !PPC && !SPARC
+	depends on DEBUG_KERNEL
+	depends on !HIBERNATION || ARCH_SUPPORTS_DEBUG_PAGEALLOC && !PPC && !SPARC
 	depends on !KMEMCHECK
+	select PAGE_POISONING if !ARCH_SUPPORTS_DEBUG_PAGEALLOC
 	---help---
 	  Unmap pages from the kernel linear mapping after free_pages().
 	  This results in a large slowdown, but helps to find certain types
 	  of memory corruption.
 
+	  For architectures which don't enable ARCH_SUPPORTS_DEBUG_PAGEALLOC,
+	  fill the pages with poison patterns after free_pages() and verify
+	  the patterns before alloc_pages().  Additionally,
+	  this option cannot be enabled in combination with hibernation as
+	  that would result in incorrect warnings of memory corruption after
+	  a resume because free pages are not saved to the suspend image.
+
 config WANT_PAGE_DEBUG_FLAGS
 	bool
 
 config PAGE_POISONING
-	bool "Debug page memory allocations"
-	depends on DEBUG_KERNEL && !ARCH_SUPPORTS_DEBUG_PAGEALLOC
-	depends on !HIBERNATION
-	select DEBUG_PAGEALLOC
+	bool
 	select WANT_PAGE_DEBUG_FLAGS
-	---help---
-	   Fill the pages with poison patterns after free_pages() and verify
-	   the patterns before alloc_pages(). This results in a large slowdown,
-	   but helps to find certain types of memory corruption.
-
-	   This option cannot be enabled in combination with hibernation as
-	   that would result in incorrect warnings of memory corruption after
-	   a resume because free pages are not saved to the suspend image.
diff --git a/mm/Makefile b/mm/Makefile
index 2b1b575..42a8326 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -7,7 +7,7 @@ mmu-$(CONFIG_MMU)	:= fremap.o highmem.o madvise.o memory.o mincore.o \
 			   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
 			   vmalloc.o pagewalk.o pgtable-generic.o
 
-obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
+obj-y			:= filemap.o mempool.o oom_kill.o fadvise.o \
 			   maccess.o page_alloc.o page-writeback.o \
 			   readahead.o swap.o truncate.o vmscan.o shmem.o \
 			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
@@ -15,6 +15,12 @@ obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
 			   $(mmu-y)
 obj-y += init-mm.o
 
+ifdef CONFIG_NO_BOOTMEM
+	obj-y		+= nobootmem.o
+else
+	obj-y		+= bootmem.o
+endif
+
 obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o
 
 obj-$(CONFIG_BOUNCE)	+= bounce.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 13b0caa..07aeb89 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -23,6 +23,13 @@
 
 #include "internal.h"
 
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+struct pglist_data __refdata contig_page_data = {
+	.bdata = &bootmem_node_data[0]
+};
+EXPORT_SYMBOL(contig_page_data);
+#endif
+
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
@@ -35,7 +42,6 @@ unsigned long max_pfn;
 unsigned long saved_max_pfn;
 #endif
 
-#ifndef CONFIG_NO_BOOTMEM
 bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;
 
 static struct list_head bdata_list __initdata = LIST_HEAD_INIT(bdata_list);
@@ -146,7 +152,7 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages)
 	min_low_pfn = start;
 	return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);
 }
-#endif
+
 /*
  * free_bootmem_late - free bootmem pages directly to page allocator
  * @addr: starting address of the range
@@ -171,53 +177,6 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)
 	}
 }
 
-#ifdef CONFIG_NO_BOOTMEM
-static void __init __free_pages_memory(unsigned long start, unsigned long end)
-{
-	int i;
-	unsigned long start_aligned, end_aligned;
-	int order = ilog2(BITS_PER_LONG);
-
-	start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
-	end_aligned = end & ~(BITS_PER_LONG - 1);
-
-	if (end_aligned <= start_aligned) {
-		for (i = start; i < end; i++)
-			__free_pages_bootmem(pfn_to_page(i), 0);
-
-		return;
-	}
-
-	for (i = start; i < start_aligned; i++)
-		__free_pages_bootmem(pfn_to_page(i), 0);
-
-	for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG)
-		__free_pages_bootmem(pfn_to_page(i), order);
-
-	for (i = end_aligned; i < end; i++)
-		__free_pages_bootmem(pfn_to_page(i), 0);
-}
-
-unsigned long __init free_all_memory_core_early(int nodeid)
-{
-	int i;
-	u64 start, end;
-	unsigned long count = 0;
-	struct range *range = NULL;
-	int nr_range;
-
-	nr_range = get_free_all_memory_range(&range, nodeid);
-
-	for (i = 0; i < nr_range; i++) {
-		start = range[i].start;
-		end = range[i].end;
-		count += end - start;
-		__free_pages_memory(start, end);
-	}
-
-	return count;
-}
-#else
 static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 {
 	int aligned;
@@ -278,7 +237,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 
 	return count;
 }
-#endif
 
 /**
  * free_all_bootmem_node - release a node's free pages to the buddy allocator
@@ -289,12 +247,7 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
 unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
 {
 	register_page_bootmem_info_node(pgdat);
-#ifdef CONFIG_NO_BOOTMEM
-	/* free_all_memory_core_early(MAX_NUMNODES) will be called later */
-	return 0;
-#else
 	return free_all_bootmem_core(pgdat->bdata);
-#endif
 }
 
 /**
@@ -304,16 +257,6 @@ unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
  */
 unsigned long __init free_all_bootmem(void)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	/*
-	 * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id
-	 *  because in some case like Node0 doesnt have RAM installed
-	 *  low ram will be on Node1
-	 * Use MAX_NUMNODES will make sure all ranges in early_node_map[]
-	 *  will be used instead of only Node0 related
-	 */
-	return free_all_memory_core_early(MAX_NUMNODES);
-#else
 	unsigned long total_pages = 0;
 	bootmem_data_t *bdata;
 
@@ -321,10 +264,8 @@ unsigned long __init free_all_bootmem(void)
 		total_pages += free_all_bootmem_core(bdata);
 
 	return total_pages;
-#endif
 }
 
-#ifndef CONFIG_NO_BOOTMEM
 static void __init __free(bootmem_data_t *bdata,
 			unsigned long sidx, unsigned long eidx)
 {
@@ -419,7 +360,6 @@ static int __init mark_bootmem(unsigned long start, unsigned long end,
 	}
 	BUG();
 }
-#endif
 
 /**
  * free_bootmem_node - mark a page range as usable
@@ -434,10 +374,6 @@ static int __init mark_bootmem(unsigned long start, unsigned long end,
 void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 			      unsigned long size)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	kmemleak_free_part(__va(physaddr), size);
-	memblock_x86_free_range(physaddr, physaddr + size);
-#else
 	unsigned long start, end;
 
 	kmemleak_free_part(__va(physaddr), size);
@@ -446,7 +382,6 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 	end = PFN_DOWN(physaddr + size);
 
 	mark_bootmem_node(pgdat->bdata, start, end, 0, 0);
-#endif
 }
 
 /**
@@ -460,10 +395,6 @@ void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
  */
 void __init free_bootmem(unsigned long addr, unsigned long size)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	kmemleak_free_part(__va(addr), size);
-	memblock_x86_free_range(addr, addr + size);
-#else
 	unsigned long start, end;
 
 	kmemleak_free_part(__va(addr), size);
@@ -472,7 +403,6 @@ void __init free_bootmem(unsigned long addr, unsigned long size)
 	end = PFN_DOWN(addr + size);
 
 	mark_bootmem(start, end, 0, 0);
-#endif
 }
 
 /**
@@ -489,17 +419,12 @@ void __init free_bootmem(unsigned long addr, unsigned long size)
 int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 				 unsigned long size, int flags)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	panic("no bootmem");
-	return 0;
-#else
 	unsigned long start, end;
 
 	start = PFN_DOWN(physaddr);
 	end = PFN_UP(physaddr + size);
 
 	return mark_bootmem_node(pgdat->bdata, start, end, 1, flags);
-#endif
 }
 
 /**
@@ -515,20 +440,14 @@ int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
 int __init reserve_bootmem(unsigned long addr, unsigned long size,
 			    int flags)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	panic("no bootmem");
-	return 0;
-#else
 	unsigned long start, end;
 
 	start = PFN_DOWN(addr);
 	end = PFN_UP(addr + size);
 
 	return mark_bootmem(start, end, 1, flags);
-#endif
 }
 
-#ifndef CONFIG_NO_BOOTMEM
 int __weak __init reserve_bootmem_generic(unsigned long phys, unsigned long len,
 				   int flags)
 {
@@ -685,33 +604,12 @@ static void * __init alloc_arch_preferred_bootmem(bootmem_data_t *bdata,
 #endif
 	return NULL;
 }
-#endif
 
 static void * __init ___alloc_bootmem_nopanic(unsigned long size,
 					unsigned long align,
 					unsigned long goal,
 					unsigned long limit)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	void *ptr;
-
-	if (WARN_ON_ONCE(slab_is_available()))
-		return kzalloc(size, GFP_NOWAIT);
-
-restart:
-
-	ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, goal, limit);
-
-	if (ptr)
-		return ptr;
-
-	if (goal != 0) {
-		goal = 0;
-		goto restart;
-	}
-
-	return NULL;
-#else
 	bootmem_data_t *bdata;
 	void *region;
 
@@ -737,7 +635,6 @@ restart:
 	}
 
 	return NULL;
-#endif
 }
 
 /**
@@ -758,10 +655,6 @@ void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
 {
 	unsigned long limit = 0;
 
-#ifdef CONFIG_NO_BOOTMEM
-	limit = -1UL;
-#endif
-
 	return ___alloc_bootmem_nopanic(size, align, goal, limit);
 }
 
@@ -798,14 +691,9 @@ void * __init __alloc_bootmem(unsigned long size, unsigned long align,
 {
 	unsigned long limit = 0;
 
-#ifdef CONFIG_NO_BOOTMEM
-	limit = -1UL;
-#endif
-
 	return ___alloc_bootmem(size, align, goal, limit);
 }
 
-#ifndef CONFIG_NO_BOOTMEM
 static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
 				unsigned long size, unsigned long align,
 				unsigned long goal, unsigned long limit)
@@ -822,7 +710,6 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
 
 	return ___alloc_bootmem(size, align, goal, limit);
 }
-#endif
 
 /**
  * __alloc_bootmem_node - allocate boot memory from a specific node
@@ -842,24 +729,10 @@ static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,
 void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
 				   unsigned long align, unsigned long goal)
 {
-	void *ptr;
-
 	if (WARN_ON_ONCE(slab_is_available()))
 		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
-#ifdef CONFIG_NO_BOOTMEM
-	ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
-					 goal, -1ULL);
-	if (ptr)
-		return ptr;
-
-	ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align,
-					 goal, -1ULL);
-#else
-	ptr = ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0);
-#endif
-
-	return ptr;
+	return  ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0);
 }
 
 void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
@@ -880,13 +753,8 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
 		unsigned long new_goal;
 
 		new_goal = MAX_DMA32_PFN << PAGE_SHIFT;
-#ifdef CONFIG_NO_BOOTMEM
-		ptr =  __alloc_memory_core_early(pgdat->node_id, size, align,
-						 new_goal, -1ULL);
-#else
 		ptr = alloc_bootmem_core(pgdat->bdata, size, align,
 						 new_goal, 0);
-#endif
 		if (ptr)
 			return ptr;
 	}
@@ -907,16 +775,6 @@ void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
 void * __init alloc_bootmem_section(unsigned long size,
 				    unsigned long section_nr)
 {
-#ifdef CONFIG_NO_BOOTMEM
-	unsigned long pfn, goal, limit;
-
-	pfn = section_nr_to_pfn(section_nr);
-	goal = pfn << PAGE_SHIFT;
-	limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
-
-	return __alloc_memory_core_early(early_pfn_to_nid(pfn), size,
-					 SMP_CACHE_BYTES, goal, limit);
-#else
 	bootmem_data_t *bdata;
 	unsigned long pfn, goal, limit;
 
@@ -926,7 +784,6 @@ void * __init alloc_bootmem_section(unsigned long size,
 	bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
 
 	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
-#endif
 }
 #endif
 
@@ -938,16 +795,11 @@ void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
 	if (WARN_ON_ONCE(slab_is_available()))
 		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
-#ifdef CONFIG_NO_BOOTMEM
-	ptr =  __alloc_memory_core_early(pgdat->node_id, size, align,
-						 goal, -1ULL);
-#else
 	ptr = alloc_arch_preferred_bootmem(pgdat->bdata, size, align, goal, 0);
 	if (ptr)
 		return ptr;
 
 	ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);
-#endif
 	if (ptr)
 		return ptr;
 
@@ -995,21 +847,9 @@ void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
 void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
 				       unsigned long align, unsigned long goal)
 {
-	void *ptr;
-
 	if (WARN_ON_ONCE(slab_is_available()))
 		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
 
-#ifdef CONFIG_NO_BOOTMEM
-	ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
+	return ___alloc_bootmem_node(pgdat->bdata, size, align,
 				goal, ARCH_LOW_ADDRESS_LIMIT);
-	if (ptr)
-		return ptr;
-	ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align,
-				goal, ARCH_LOW_ADDRESS_LIMIT);
-#else
-	ptr = ___alloc_bootmem_node(pgdat->bdata, size, align,
-				goal, ARCH_LOW_ADDRESS_LIMIT);
-#endif
-	return ptr;
 }
diff --git a/mm/compaction.c b/mm/compaction.c
index 8be430b..021a296 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -42,8 +42,6 @@ struct compact_control {
 	unsigned int order;		/* order a direct compactor needs */
 	int migratetype;		/* MOVABLE, RECLAIMABLE etc */
 	struct zone *zone;
-
-	int compact_mode;
 };
 
 static unsigned long release_freepages(struct list_head *freelist)
@@ -155,7 +153,6 @@ static void isolate_freepages(struct zone *zone,
 	 * pages on cc->migratepages. We stop searching if the migrate
 	 * and free page scanners meet or enough free pages are isolated.
 	 */
-	spin_lock_irqsave(&zone->lock, flags);
 	for (; pfn > low_pfn && cc->nr_migratepages > nr_freepages;
 					pfn -= pageblock_nr_pages) {
 		unsigned long isolated;
@@ -178,9 +175,19 @@ static void isolate_freepages(struct zone *zone,
 		if (!suitable_migration_target(page))
 			continue;
 
-		/* Found a block suitable for isolating free pages from */
-		isolated = isolate_freepages_block(zone, pfn, freelist);
-		nr_freepages += isolated;
+		/*
+		 * Found a block suitable for isolating free pages from. Now
+		 * we disabled interrupts, double check things are ok and
+		 * isolate the pages. This is to minimise the time IRQs
+		 * are disabled
+		 */
+		isolated = 0;
+		spin_lock_irqsave(&zone->lock, flags);
+		if (suitable_migration_target(page)) {
+			isolated = isolate_freepages_block(zone, pfn, freelist);
+			nr_freepages += isolated;
+		}
+		spin_unlock_irqrestore(&zone->lock, flags);
 
 		/*
 		 * Record the highest PFN we isolated pages from. When next
@@ -190,7 +197,6 @@ static void isolate_freepages(struct zone *zone,
 		if (isolated)
 			high_pfn = max(high_pfn, pfn);
 	}
-	spin_unlock_irqrestore(&zone->lock, flags);
 
 	/* split_free_page does not map the pages */
 	list_for_each_entry(page, freelist, lru) {
@@ -271,9 +277,27 @@ static unsigned long isolate_migratepages(struct zone *zone,
 	}
 
 	/* Time to isolate some pages for migration */
+	cond_resched();
 	spin_lock_irq(&zone->lru_lock);
 	for (; low_pfn < end_pfn; low_pfn++) {
 		struct page *page;
+		bool locked = true;
+
+		/* give a chance to irqs before checking need_resched() */
+		if (!((low_pfn+1) % SWAP_CLUSTER_MAX)) {
+			spin_unlock_irq(&zone->lru_lock);
+			locked = false;
+		}
+		if (need_resched() || spin_is_contended(&zone->lru_lock)) {
+			if (locked)
+				spin_unlock_irq(&zone->lru_lock);
+			cond_resched();
+			spin_lock_irq(&zone->lru_lock);
+			if (fatal_signal_pending(current))
+				break;
+		} else if (!locked)
+			spin_lock_irq(&zone->lru_lock);
+
 		if (!pfn_valid_within(low_pfn))
 			continue;
 		nr_scanned++;
@@ -397,10 +421,7 @@ static int compact_finished(struct zone *zone,
 		return COMPACT_COMPLETE;
 
 	/* Compaction run is not finished if the watermark is not met */
-	if (cc->compact_mode != COMPACT_MODE_KSWAPD)
-		watermark = low_wmark_pages(zone);
-	else
-		watermark = high_wmark_pages(zone);
+	watermark = low_wmark_pages(zone);
 	watermark += (1 << cc->order);
 
 	if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0))
@@ -413,15 +434,6 @@ static int compact_finished(struct zone *zone,
 	if (cc->order == -1)
 		return COMPACT_CONTINUE;
 
-	/*
-	 * Generating only one page of the right order is not enough
-	 * for kswapd, we must continue until we're above the high
-	 * watermark as a pool for high order GFP_ATOMIC allocations
-	 * too.
-	 */
-	if (cc->compact_mode == COMPACT_MODE_KSWAPD)
-		return COMPACT_CONTINUE;
-
 	/* Direct compactor: Is a suitable page free? */
 	for (order = cc->order; order < MAX_ORDER; order++) {
 		/* Job done if page is free of the right migratetype */
@@ -508,12 +520,13 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 
 	while ((ret = compact_finished(zone, cc)) == COMPACT_CONTINUE) {
 		unsigned long nr_migrate, nr_remaining;
+		int err;
 
 		if (!isolate_migratepages(zone, cc))
 			continue;
 
 		nr_migrate = cc->nr_migratepages;
-		migrate_pages(&cc->migratepages, compaction_alloc,
+		err = migrate_pages(&cc->migratepages, compaction_alloc,
 				(unsigned long)cc, false,
 				cc->sync);
 		update_nr_listpages(cc);
@@ -527,7 +540,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 						nr_remaining);
 
 		/* Release LRU pages not migrated */
-		if (!list_empty(&cc->migratepages)) {
+		if (err) {
 			putback_lru_pages(&cc->migratepages);
 			cc->nr_migratepages = 0;
 		}
@@ -543,8 +556,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 
 unsigned long compact_zone_order(struct zone *zone,
 				 int order, gfp_t gfp_mask,
-				 bool sync,
-				 int compact_mode)
+				 bool sync)
 {
 	struct compact_control cc = {
 		.nr_freepages = 0,
@@ -553,7 +565,6 @@ unsigned long compact_zone_order(struct zone *zone,
 		.migratetype = allocflags_to_migratetype(gfp_mask),
 		.zone = zone,
 		.sync = sync,
-		.compact_mode = compact_mode,
 	};
 	INIT_LIST_HEAD(&cc.freepages);
 	INIT_LIST_HEAD(&cc.migratepages);
@@ -599,8 +610,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist,
 								nodemask) {
 		int status;
 
-		status = compact_zone_order(zone, order, gfp_mask, sync,
-					    COMPACT_MODE_DIRECT_RECLAIM);
+		status = compact_zone_order(zone, order, gfp_mask, sync);
 		rc = max(status, rc);
 
 		/* If a normal allocation would succeed, stop compacting */
@@ -631,7 +641,6 @@ static int compact_node(int nid)
 			.nr_freepages = 0,
 			.nr_migratepages = 0,
 			.order = -1,
-			.compact_mode = COMPACT_MODE_DIRECT_RECLAIM,
 		};
 
 		zone = &pgdat->node_zones[zoneid];
diff --git a/mm/filemap.c b/mm/filemap.c
index 83a45d3..f807afd 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -108,11 +108,11 @@
  */
 
 /*
- * Remove a page from the page cache and free it. Caller has to make
+ * Delete a page from the page cache and free it. Caller has to make
  * sure the page is locked and that nobody else uses it - or that usage
  * is safe.  The caller must hold the mapping's tree_lock.
  */
-void __remove_from_page_cache(struct page *page)
+void __delete_from_page_cache(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 
@@ -137,7 +137,15 @@ void __remove_from_page_cache(struct page *page)
 	}
 }
 
-void remove_from_page_cache(struct page *page)
+/**
+ * delete_from_page_cache - delete page from page cache
+ * @page: the page which the kernel is trying to remove from page cache
+ *
+ * This must be called only on pages that have been verified to be in the page
+ * cache and locked.  It will never put the page into the free list, the caller
+ * has a reference on the page.
+ */
+void delete_from_page_cache(struct page *page)
 {
 	struct address_space *mapping = page->mapping;
 	void (*freepage)(struct page *);
@@ -146,14 +154,15 @@ void remove_from_page_cache(struct page *page)
 
 	freepage = mapping->a_ops->freepage;
 	spin_lock_irq(&mapping->tree_lock);
-	__remove_from_page_cache(page);
+	__delete_from_page_cache(page);
 	spin_unlock_irq(&mapping->tree_lock);
 	mem_cgroup_uncharge_cache_page(page);
 
 	if (freepage)
 		freepage(page);
+	page_cache_release(page);
 }
-EXPORT_SYMBOL(remove_from_page_cache);
+EXPORT_SYMBOL(delete_from_page_cache);
 
 static int sync_page(void *word)
 {
@@ -387,6 +396,76 @@ int filemap_write_and_wait_range(struct address_space *mapping,
 EXPORT_SYMBOL(filemap_write_and_wait_range);
 
 /**
+ * replace_page_cache_page - replace a pagecache page with a new one
+ * @old:	page to be replaced
+ * @new:	page to replace with
+ * @gfp_mask:	allocation mode
+ *
+ * This function replaces a page in the pagecache with a new one.  On
+ * success it acquires the pagecache reference for the new page and
+ * drops it for the old page.  Both the old and new pages must be
+ * locked.  This function does not add the new page to the LRU, the
+ * caller must do that.
+ *
+ * The remove + add is atomic.  The only way this function can fail is
+ * memory allocation failure.
+ */
+int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
+{
+	int error;
+	struct mem_cgroup *memcg = NULL;
+
+	VM_BUG_ON(!PageLocked(old));
+	VM_BUG_ON(!PageLocked(new));
+	VM_BUG_ON(new->mapping);
+
+	/*
+	 * This is not page migration, but prepare_migration and
+	 * end_migration does enough work for charge replacement.
+	 *
+	 * In the longer term we probably want a specialized function
+	 * for moving the charge from old to new in a more efficient
+	 * manner.
+	 */
+	error = mem_cgroup_prepare_migration(old, new, &memcg, gfp_mask);
+	if (error)
+		return error;
+
+	error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
+	if (!error) {
+		struct address_space *mapping = old->mapping;
+		void (*freepage)(struct page *);
+
+		pgoff_t offset = old->index;
+		freepage = mapping->a_ops->freepage;
+
+		page_cache_get(new);
+		new->mapping = mapping;
+		new->index = offset;
+
+		spin_lock_irq(&mapping->tree_lock);
+		__delete_from_page_cache(old);
+		error = radix_tree_insert(&mapping->page_tree, offset, new);
+		BUG_ON(error);
+		mapping->nrpages++;
+		__inc_zone_page_state(new, NR_FILE_PAGES);
+		if (PageSwapBacked(new))
+			__inc_zone_page_state(new, NR_SHMEM);
+		spin_unlock_irq(&mapping->tree_lock);
+		radix_tree_preload_end();
+		if (freepage)
+			freepage(old);
+		page_cache_release(old);
+		mem_cgroup_end_migration(memcg, old, new, true);
+	} else {
+		mem_cgroup_end_migration(memcg, old, new, false);
+	}
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(replace_page_cache_page);
+
+/**
  * add_to_page_cache_locked - add a locked page to the pagecache
  * @page:	page to add
  * @mapping:	the page's address_space
@@ -621,8 +700,10 @@ int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
 		__lock_page(page);
 		return 1;
 	} else {
-		up_read(&mm->mmap_sem);
-		wait_on_page_locked(page);
+		if (!(flags & FAULT_FLAG_RETRY_NOWAIT)) {
+			up_read(&mm->mmap_sem);
+			wait_on_page_locked(page);
+		}
 		return 0;
 	}
 }
@@ -782,9 +863,13 @@ repeat:
 		page = radix_tree_deref_slot((void **)pages[i]);
 		if (unlikely(!page))
 			continue;
+
+		/*
+		 * This can only trigger when the entry at index 0 moves out
+		 * of or back to the root: none yet gotten, safe to restart.
+		 */
 		if (radix_tree_deref_retry(page)) {
-			if (ret)
-				start = pages[ret-1]->index;
+			WARN_ON(start | i);
 			goto restart;
 		}
 
@@ -800,6 +885,13 @@ repeat:
 		pages[ret] = page;
 		ret++;
 	}
+
+	/*
+	 * If all entries were removed before we could secure them,
+	 * try again, because callers stop trying once 0 is returned.
+	 */
+	if (unlikely(!ret && nr_found))
+		goto restart;
 	rcu_read_unlock();
 	return ret;
 }
@@ -834,6 +926,11 @@ repeat:
 		page = radix_tree_deref_slot((void **)pages[i]);
 		if (unlikely(!page))
 			continue;
+
+		/*
+		 * This can only trigger when the entry at index 0 moves out
+		 * of or back to the root: none yet gotten, safe to restart.
+		 */
 		if (radix_tree_deref_retry(page))
 			goto restart;
 
@@ -894,6 +991,11 @@ repeat:
 		page = radix_tree_deref_slot((void **)pages[i]);
 		if (unlikely(!page))
 			continue;
+
+		/*
+		 * This can only trigger when the entry at index 0 moves out
+		 * of or back to the root: none yet gotten, safe to restart.
+		 */
 		if (radix_tree_deref_retry(page))
 			goto restart;
 
@@ -909,6 +1011,13 @@ repeat:
 		pages[ret] = page;
 		ret++;
 	}
+
+	/*
+	 * If all entries were removed before we could secure them,
+	 * try again, because callers stop trying once 0 is returned.
+	 */
+	if (unlikely(!ret && nr_found))
+		goto restart;
 	rcu_read_unlock();
 
 	if (ret)
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 113e35c..0a619e0 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -643,23 +643,24 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
 	return ret;
 }
 
-static inline gfp_t alloc_hugepage_gfpmask(int defrag)
+static inline gfp_t alloc_hugepage_gfpmask(int defrag, gfp_t extra_gfp)
 {
-	return GFP_TRANSHUGE & ~(defrag ? 0 : __GFP_WAIT);
+	return (GFP_TRANSHUGE & ~(defrag ? 0 : __GFP_WAIT)) | extra_gfp;
 }
 
 static inline struct page *alloc_hugepage_vma(int defrag,
 					      struct vm_area_struct *vma,
-					      unsigned long haddr, int nd)
+					      unsigned long haddr, int nd,
+					      gfp_t extra_gfp)
 {
-	return alloc_pages_vma(alloc_hugepage_gfpmask(defrag),
+	return alloc_pages_vma(alloc_hugepage_gfpmask(defrag, extra_gfp),
 			       HPAGE_PMD_ORDER, vma, haddr, nd);
 }
 
 #ifndef CONFIG_NUMA
 static inline struct page *alloc_hugepage(int defrag)
 {
-	return alloc_pages(alloc_hugepage_gfpmask(defrag),
+	return alloc_pages(alloc_hugepage_gfpmask(defrag, 0),
 			   HPAGE_PMD_ORDER);
 }
 #endif
@@ -678,7 +679,7 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
 		if (unlikely(khugepaged_enter(vma)))
 			return VM_FAULT_OOM;
 		page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
-					  vma, haddr, numa_node_id());
+					  vma, haddr, numa_node_id(), 0);
 		if (unlikely(!page))
 			goto out;
 		if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) {
@@ -799,7 +800,8 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm,
 	}
 
 	for (i = 0; i < HPAGE_PMD_NR; i++) {
-		pages[i] = alloc_page_vma_node(GFP_HIGHUSER_MOVABLE,
+		pages[i] = alloc_page_vma_node(GFP_HIGHUSER_MOVABLE |
+					       __GFP_OTHER_NODE,
 					       vma, address, page_to_nid(page));
 		if (unlikely(!pages[i] ||
 			     mem_cgroup_newpage_charge(pages[i], mm,
@@ -902,7 +904,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
 	if (transparent_hugepage_enabled(vma) &&
 	    !transparent_hugepage_debug_cow())
 		new_page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
-					      vma, haddr, numa_node_id());
+					      vma, haddr, numa_node_id(), 0);
 	else
 		new_page = NULL;
 
@@ -1779,7 +1781,7 @@ static void collapse_huge_page(struct mm_struct *mm,
 	 * scalability.
 	 */
 	new_page = alloc_hugepage_vma(khugepaged_defrag(), vma, address,
-				      node);
+				      node, __GFP_OTHER_NODE);
 	if (unlikely(!new_page)) {
 		up_read(&mm->mmap_sem);
 		*hpage = ERR_PTR(-ENOMEM);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index bb0b7c1..06de5aa 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1872,8 +1872,7 @@ static int hugetlb_sysctl_handler_common(bool obey_mempolicy,
 	unsigned long tmp;
 	int ret;
 
-	if (!write)
-		tmp = h->max_huge_pages;
+	tmp = h->max_huge_pages;
 
 	if (write && h->order >= MAX_ORDER)
 		return -EINVAL;
@@ -1938,8 +1937,7 @@ int hugetlb_overcommit_handler(struct ctl_table *table, int write,
 	unsigned long tmp;
 	int ret;
 
-	if (!write)
-		tmp = h->nr_overcommit_huge_pages;
+	tmp = h->nr_overcommit_huge_pages;
 
 	if (write && h->order >= MAX_ORDER)
 		return -EINVAL;
diff --git a/mm/internal.h b/mm/internal.h
index 6948820..3438dd4 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -245,11 +245,6 @@ static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
 }
 #endif /* CONFIG_SPARSEMEM */
 
-int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-		     unsigned long start, int len, unsigned int foll_flags,
-		     struct page **pages, struct vm_area_struct **vmas,
-		     int *nonblocking);
-
 #define ZONE_RECLAIM_NOSCAN	-2
 #define ZONE_RECLAIM_FULL	-1
 #define ZONE_RECLAIM_SOME	0
diff --git a/mm/ksm.c b/mm/ksm.c
index c2b2a94..1bbe785 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -301,20 +301,6 @@ static inline int in_stable_tree(struct rmap_item *rmap_item)
 	return rmap_item->address & STABLE_FLAG;
 }
 
-static void hold_anon_vma(struct rmap_item *rmap_item,
-			  struct anon_vma *anon_vma)
-{
-	rmap_item->anon_vma = anon_vma;
-	get_anon_vma(anon_vma);
-}
-
-static void ksm_drop_anon_vma(struct rmap_item *rmap_item)
-{
-	struct anon_vma *anon_vma = rmap_item->anon_vma;
-
-	drop_anon_vma(anon_vma);
-}
-
 /*
  * ksmd, and unmerge_and_remove_all_rmap_items(), must not touch an mm's
  * page tables after it has passed through ksm_exit() - which, if necessary,
@@ -397,7 +383,7 @@ static void break_cow(struct rmap_item *rmap_item)
 	 * It is not an accident that whenever we want to break COW
 	 * to undo, we also need to drop a reference to the anon_vma.
 	 */
-	ksm_drop_anon_vma(rmap_item);
+	put_anon_vma(rmap_item->anon_vma);
 
 	down_read(&mm->mmap_sem);
 	if (ksm_test_exit(mm))
@@ -466,7 +452,7 @@ static void remove_node_from_stable_tree(struct stable_node *stable_node)
 			ksm_pages_sharing--;
 		else
 			ksm_pages_shared--;
-		ksm_drop_anon_vma(rmap_item);
+		put_anon_vma(rmap_item->anon_vma);
 		rmap_item->address &= PAGE_MASK;
 		cond_resched();
 	}
@@ -554,7 +540,7 @@ static void remove_rmap_item_from_tree(struct rmap_item *rmap_item)
 		else
 			ksm_pages_shared--;
 
-		ksm_drop_anon_vma(rmap_item);
+		put_anon_vma(rmap_item->anon_vma);
 		rmap_item->address &= PAGE_MASK;
 
 	} else if (rmap_item->address & UNSTABLE_FLAG) {
@@ -949,7 +935,8 @@ static int try_to_merge_with_ksm_page(struct rmap_item *rmap_item,
 		goto out;
 
 	/* Must get reference to anon_vma while still holding mmap_sem */
-	hold_anon_vma(rmap_item, vma->anon_vma);
+	rmap_item->anon_vma = vma->anon_vma;
+	get_anon_vma(vma->anon_vma);
 out:
 	up_read(&mm->mmap_sem);
 	return err;
diff --git a/mm/memblock.c b/mm/memblock.c
index 4618fda..a0562d1 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -58,28 +58,6 @@ static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, p
 	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
 }
 
-static long __init_memblock memblock_addrs_adjacent(phys_addr_t base1, phys_addr_t size1,
-			       phys_addr_t base2, phys_addr_t size2)
-{
-	if (base2 == base1 + size1)
-		return 1;
-	else if (base1 == base2 + size2)
-		return -1;
-
-	return 0;
-}
-
-static long __init_memblock memblock_regions_adjacent(struct memblock_type *type,
-				 unsigned long r1, unsigned long r2)
-{
-	phys_addr_t base1 = type->regions[r1].base;
-	phys_addr_t size1 = type->regions[r1].size;
-	phys_addr_t base2 = type->regions[r2].base;
-	phys_addr_t size2 = type->regions[r2].size;
-
-	return memblock_addrs_adjacent(base1, size1, base2, size2);
-}
-
 long __init_memblock memblock_overlaps_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
 {
 	unsigned long i;
@@ -206,14 +184,13 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u
 		type->regions[i].size = type->regions[i + 1].size;
 	}
 	type->cnt--;
-}
 
-/* Assumption: base addr of region 1 < base addr of region 2 */
-static void __init_memblock memblock_coalesce_regions(struct memblock_type *type,
-		unsigned long r1, unsigned long r2)
-{
-	type->regions[r1].size += type->regions[r2].size;
-	memblock_remove_region(type, r2);
+	/* Special case for empty arrays */
+	if (type->cnt == 0) {
+		type->cnt = 1;
+		type->regions[0].base = 0;
+		type->regions[0].size = 0;
+	}
 }
 
 /* Defined below but needed now */
@@ -276,7 +253,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type)
 		return 0;
 
 	/* Add the new reserved region now. Should not fail ! */
-	BUG_ON(memblock_add_region(&memblock.reserved, addr, new_size) < 0);
+	BUG_ON(memblock_add_region(&memblock.reserved, addr, new_size));
 
 	/* If the array wasn't our static init one, then free it. We only do
 	 * that before SLAB is available as later on, we don't know whether
@@ -296,58 +273,99 @@ extern int __init_memblock __weak memblock_memory_can_coalesce(phys_addr_t addr1
 	return 1;
 }
 
-static long __init_memblock memblock_add_region(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
+static long __init_memblock memblock_add_region(struct memblock_type *type,
+						phys_addr_t base, phys_addr_t size)
 {
-	unsigned long coalesced = 0;
-	long adjacent, i;
-
-	if ((type->cnt == 1) && (type->regions[0].size == 0)) {
-		type->regions[0].base = base;
-		type->regions[0].size = size;
-		return 0;
-	}
+	phys_addr_t end = base + size;
+	int i, slot = -1;
 
-	/* First try and coalesce this MEMBLOCK with another. */
+	/* First try and coalesce this MEMBLOCK with others */
 	for (i = 0; i < type->cnt; i++) {
-		phys_addr_t rgnbase = type->regions[i].base;
-		phys_addr_t rgnsize = type->regions[i].size;
+		struct memblock_region *rgn = &type->regions[i];
+		phys_addr_t rend = rgn->base + rgn->size;
+
+		/* Exit if there's no possible hits */
+		if (rgn->base > end || rgn->size == 0)
+			break;
 
-		if ((rgnbase == base) && (rgnsize == size))
-			/* Already have this region, so we're done */
+		/* Check if we are fully enclosed within an existing
+		 * block
+		 */
+		if (rgn->base <= base && rend >= end)
 			return 0;
 
-		adjacent = memblock_addrs_adjacent(base, size, rgnbase, rgnsize);
-		/* Check if arch allows coalescing */
-		if (adjacent != 0 && type == &memblock.memory &&
-		    !memblock_memory_can_coalesce(base, size, rgnbase, rgnsize))
-			break;
-		if (adjacent > 0) {
-			type->regions[i].base -= size;
-			type->regions[i].size += size;
-			coalesced++;
-			break;
-		} else if (adjacent < 0) {
-			type->regions[i].size += size;
-			coalesced++;
-			break;
+		/* Check if we overlap or are adjacent with the bottom
+		 * of a block.
+		 */
+		if (base < rgn->base && end >= rgn->base) {
+			/* If we can't coalesce, create a new block */
+			if (!memblock_memory_can_coalesce(base, size,
+							  rgn->base,
+							  rgn->size)) {
+				/* Overlap & can't coalesce are mutually
+				 * exclusive, if you do that, be prepared
+				 * for trouble
+				 */
+				WARN_ON(end != rgn->base);
+				goto new_block;
+			}
+			/* We extend the bottom of the block down to our
+			 * base
+			 */
+			rgn->base = base;
+			rgn->size = rend - base;
+
+			/* Return if we have nothing else to allocate
+			 * (fully coalesced)
+			 */
+			if (rend >= end)
+				return 0;
+
+			/* We continue processing from the end of the
+			 * coalesced block.
+			 */
+			base = rend;
+			size = end - base;
+		}
+
+		/* Now check if we overlap or are adjacent with the
+		 * top of a block
+		 */
+		if (base <= rend && end >= rend) {
+			/* If we can't coalesce, create a new block */
+			if (!memblock_memory_can_coalesce(rgn->base,
+							  rgn->size,
+							  base, size)) {
+				/* Overlap & can't coalesce are mutually
+				 * exclusive, if you do that, be prepared
+				 * for trouble
+				 */
+				WARN_ON(rend != base);
+				goto new_block;
+			}
+			/* We adjust our base down to enclose the
+			 * original block and destroy it. It will be
+			 * part of our new allocation. Since we've
+			 * freed an entry, we know we won't fail
+			 * to allocate one later, so we won't risk
+			 * losing the original block allocation.
+			 */
+			size += (base - rgn->base);
+			base = rgn->base;
+			memblock_remove_region(type, i--);
 		}
 	}
 
-	/* If we plugged a hole, we may want to also coalesce with the
-	 * next region
+	/* If the array is empty, special case, replace the fake
+	 * filler region and return
 	 */
-	if ((i < type->cnt - 1) && memblock_regions_adjacent(type, i, i+1) &&
-	    ((type != &memblock.memory || memblock_memory_can_coalesce(type->regions[i].base,
-							     type->regions[i].size,
-							     type->regions[i+1].base,
-							     type->regions[i+1].size)))) {
-		memblock_coalesce_regions(type, i, i+1);
-		coalesced++;
+	if ((type->cnt == 1) && (type->regions[0].size == 0)) {
+		type->regions[0].base = base;
+		type->regions[0].size = size;
+		return 0;
 	}
 
-	if (coalesced)
-		return coalesced;
-
+ new_block:
 	/* If we are out of space, we fail. It's too late to resize the array
 	 * but then this shouldn't have happened in the first place.
 	 */
@@ -362,13 +380,14 @@ static long __init_memblock memblock_add_region(struct memblock_type *type, phys
 		} else {
 			type->regions[i+1].base = base;
 			type->regions[i+1].size = size;
+			slot = i + 1;
 			break;
 		}
 	}
-
 	if (base < type->regions[0].base) {
 		type->regions[0].base = base;
 		type->regions[0].size = size;
+		slot = 0;
 	}
 	type->cnt++;
 
@@ -376,7 +395,8 @@ static long __init_memblock memblock_add_region(struct memblock_type *type, phys
 	 * our allocation and return an error
 	 */
 	if (type->cnt == type->max && memblock_double_array(type)) {
-		type->cnt--;
+		BUG_ON(slot < 0);
+		memblock_remove_region(type, slot);
 		return -1;
 	}
 
@@ -389,52 +409,55 @@ long __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
 
 }
 
-static long __init_memblock __memblock_remove(struct memblock_type *type, phys_addr_t base, phys_addr_t size)
+static long __init_memblock __memblock_remove(struct memblock_type *type,
+					      phys_addr_t base, phys_addr_t size)
 {
-	phys_addr_t rgnbegin, rgnend;
 	phys_addr_t end = base + size;
 	int i;
 
-	rgnbegin = rgnend = 0; /* supress gcc warnings */
-
-	/* Find the region where (base, size) belongs to */
-	for (i=0; i < type->cnt; i++) {
-		rgnbegin = type->regions[i].base;
-		rgnend = rgnbegin + type->regions[i].size;
+	/* Walk through the array for collisions */
+	for (i = 0; i < type->cnt; i++) {
+		struct memblock_region *rgn = &type->regions[i];
+		phys_addr_t rend = rgn->base + rgn->size;
 
-		if ((rgnbegin <= base) && (end <= rgnend))
+		/* Nothing more to do, exit */
+		if (rgn->base > end || rgn->size == 0)
 			break;
-	}
 
-	/* Didn't find the region */
-	if (i == type->cnt)
-		return -1;
+		/* If we fully enclose the block, drop it */
+		if (base <= rgn->base && end >= rend) {
+			memblock_remove_region(type, i--);
+			continue;
+		}
 
-	/* Check to see if we are removing entire region */
-	if ((rgnbegin == base) && (rgnend == end)) {
-		memblock_remove_region(type, i);
-		return 0;
-	}
+		/* If we are fully enclosed within a block
+		 * then we need to split it and we are done
+		 */
+		if (base > rgn->base && end < rend) {
+			rgn->size = base - rgn->base;
+			if (!memblock_add_region(type, end, rend - end))
+				return 0;
+			/* Failure to split is bad, we at least
+			 * restore the block before erroring
+			 */
+			rgn->size = rend - rgn->base;
+			WARN_ON(1);
+			return -1;
+		}
 
-	/* Check to see if region is matching at the front */
-	if (rgnbegin == base) {
-		type->regions[i].base = end;
-		type->regions[i].size -= size;
-		return 0;
-	}
+		/* Check if we need to trim the bottom of a block */
+		if (rgn->base < end && rend > end) {
+			rgn->size -= end - rgn->base;
+			rgn->base = end;
+			break;
+		}
 
-	/* Check to see if the region is matching at the end */
-	if (rgnend == end) {
-		type->regions[i].size -= size;
-		return 0;
-	}
+		/* And check if we need to trim the top of a block */
+		if (base < rend)
+			rgn->size -= rend - base;
 
-	/*
-	 * We need to split the entry -  adjust the current one to the
-	 * beginging of the hole and add the region after hole.
-	 */
-	type->regions[i].size = base - type->regions[i].base;
-	return memblock_add_region(type, end, rgnend - end);
+	}
+	return 0;
 }
 
 long __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
@@ -467,7 +490,7 @@ phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, ph
 
 	found = memblock_find_base(size, align, 0, max_addr);
 	if (found != MEMBLOCK_ERROR &&
-	    memblock_add_region(&memblock.reserved, found, size) >= 0)
+	    !memblock_add_region(&memblock.reserved, found, size))
 		return found;
 
 	return 0;
@@ -548,7 +571,7 @@ static phys_addr_t __init memblock_alloc_nid_region(struct memblock_region *mp,
 		if (this_nid == nid) {
 			phys_addr_t ret = memblock_find_region(start, this_end, size, align);
 			if (ret != MEMBLOCK_ERROR &&
-			    memblock_add_region(&memblock.reserved, ret, size) >= 0)
+			    !memblock_add_region(&memblock.reserved, ret, size))
 				return ret;
 		}
 		start = this_end;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index da53a25..e1ee6ad 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -829,6 +829,32 @@ void mem_cgroup_del_lru(struct page *page)
 	mem_cgroup_del_lru_list(page, page_lru(page));
 }
 
+/*
+ * Writeback is about to end against a page which has been marked for immediate
+ * reclaim.  If it still appears to be reclaimable, move it to the tail of the
+ * inactive list.
+ */
+void mem_cgroup_rotate_reclaimable_page(struct page *page)
+{
+	struct mem_cgroup_per_zone *mz;
+	struct page_cgroup *pc;
+	enum lru_list lru = page_lru(page);
+
+	if (mem_cgroup_disabled())
+		return;
+
+	pc = lookup_page_cgroup(page);
+	/* unused or root page is not rotated. */
+	if (!PageCgroupUsed(pc))
+		return;
+	/* Ensure pc->mem_cgroup is visible after reading PCG_USED. */
+	smp_rmb();
+	if (mem_cgroup_is_root(pc->mem_cgroup))
+		return;
+	mz = page_cgroup_zoneinfo(pc);
+	list_move_tail(&pc->lru, &mz->lists[lru]);
+}
+
 void mem_cgroup_rotate_lru_list(struct page *page, enum lru_list lru)
 {
 	struct mem_cgroup_per_zone *mz;
@@ -2883,7 +2909,7 @@ static inline int mem_cgroup_move_swap_account(swp_entry_t entry,
  * page belongs to.
  */
 int mem_cgroup_prepare_migration(struct page *page,
-	struct page *newpage, struct mem_cgroup **ptr)
+	struct page *newpage, struct mem_cgroup **ptr, gfp_t gfp_mask)
 {
 	struct page_cgroup *pc;
 	struct mem_cgroup *mem = NULL;
@@ -2940,7 +2966,7 @@ int mem_cgroup_prepare_migration(struct page *page,
 		return 0;
 
 	*ptr = mem;
-	ret = __mem_cgroup_try_charge(NULL, GFP_KERNEL, ptr, false, PAGE_SIZE);
+	ret = __mem_cgroup_try_charge(NULL, gfp_mask, ptr, false, PAGE_SIZE);
 	css_put(&mem->css);/* drop extra refcnt */
 	if (ret || *ptr == NULL) {
 		if (PageAnon(page)) {
@@ -4737,7 +4763,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
 	pte_t *pte;
 	spinlock_t *ptl;
 
-	VM_BUG_ON(pmd_trans_huge(*pmd));
+	split_huge_page_pmd(walk->mm, pmd);
+
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE)
 		if (is_target_pte_for_mc(vma, addr, *pte, NULL))
@@ -4899,8 +4926,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
 	pte_t *pte;
 	spinlock_t *ptl;
 
+	split_huge_page_pmd(walk->mm, pmd);
 retry:
-	VM_BUG_ON(pmd_trans_huge(*pmd));
 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
 	for (; addr != end; addr += PAGE_SIZE) {
 		pte_t ptent = *(pte++);
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 0207c2f..e0af336 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1130,7 +1130,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags)
 
 	/*
 	 * Now take care of user space mappings.
-	 * Abort on fail: __remove_from_page_cache() assumes unmapped page.
+	 * Abort on fail: __delete_from_page_cache() assumes unmapped page.
 	 */
 	if (hwpoison_user_mappings(p, pfn, trapno) != SWAP_SUCCESS) {
 		printk(KERN_ERR "MCE %#lx: cannot unmap page, give up\n", pfn);
@@ -1487,35 +1487,3 @@ done:
 	/* keep elevated page count for bad page */
 	return ret;
 }
-
-/*
- * The caller must hold current->mm->mmap_sem in read mode.
- */
-int is_hwpoison_address(unsigned long addr)
-{
-	pgd_t *pgdp;
-	pud_t pud, *pudp;
-	pmd_t pmd, *pmdp;
-	pte_t pte, *ptep;
-	swp_entry_t entry;
-
-	pgdp = pgd_offset(current->mm, addr);
-	if (!pgd_present(*pgdp))
-		return 0;
-	pudp = pud_offset(pgdp, addr);
-	pud = *pudp;
-	if (!pud_present(pud) || pud_large(pud))
-		return 0;
-	pmdp = pmd_offset(pudp, addr);
-	pmd = *pmdp;
-	if (!pmd_present(pmd) || pmd_large(pmd))
-		return 0;
-	ptep = pte_offset_map(pmdp, addr);
-	pte = *ptep;
-	pte_unmap(ptep);
-	if (!is_swap_pte(pte))
-		return 0;
-	entry = pte_to_swp_entry(pte);
-	return is_hwpoison_entry(entry);
-}
-EXPORT_SYMBOL_GPL(is_hwpoison_address);
diff --git a/mm/memory.c b/mm/memory.c
index 5823698..615be51 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1410,6 +1410,55 @@ no_page_table:
 	return page;
 }
 
+/**
+ * __get_user_pages() - pin user pages in memory
+ * @tsk:	task_struct of target task
+ * @mm:		mm_struct of target mm
+ * @start:	starting user address
+ * @nr_pages:	number of pages from start to pin
+ * @gup_flags:	flags modifying pin behaviour
+ * @pages:	array that receives pointers to the pages pinned.
+ *		Should be at least nr_pages long. Or NULL, if caller
+ *		only intends to ensure the pages are faulted in.
+ * @vmas:	array of pointers to vmas corresponding to each page.
+ *		Or NULL if the caller does not require them.
+ * @nonblocking: whether waiting for disk IO or mmap_sem contention
+ *
+ * Returns number of pages pinned. This may be fewer than the number
+ * requested. If nr_pages is 0 or negative, returns 0. If no pages
+ * were pinned, returns -errno. Each page returned must be released
+ * with a put_page() call when it is finished with. vmas will only
+ * remain valid while mmap_sem is held.
+ *
+ * Must be called with mmap_sem held for read or write.
+ *
+ * __get_user_pages walks a process's page tables and takes a reference to
+ * each struct page that each user address corresponds to at a given
+ * instant. That is, it takes the page that would be accessed if a user
+ * thread accesses the given user virtual address at that instant.
+ *
+ * This does not guarantee that the page exists in the user mappings when
+ * __get_user_pages returns, and there may even be a completely different
+ * page there in some cases (eg. if mmapped pagecache has been invalidated
+ * and subsequently re faulted). However it does guarantee that the page
+ * won't be freed completely. And mostly callers simply care that the page
+ * contains data that was valid *at some point in time*. Typically, an IO
+ * or similar operation cannot guarantee anything stronger anyway because
+ * locks can't be held over the syscall boundary.
+ *
+ * If @gup_flags & FOLL_WRITE == 0, the page must not be written to. If
+ * the page is written to, set_page_dirty (or set_page_dirty_lock, as
+ * appropriate) must be called after the page is finished with, and
+ * before put_page is called.
+ *
+ * If @nonblocking != NULL, __get_user_pages will not wait for disk IO
+ * or mmap_sem contention, and if waiting is needed to pin all pages,
+ * *@nonblocking will be set to 0.
+ *
+ * In most cases, get_user_pages or get_user_pages_fast should be used
+ * instead of __get_user_pages. __get_user_pages should be used only if
+ * you need some special @gup_flags.
+ */
 int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 		     unsigned long start, int nr_pages, unsigned int gup_flags,
 		     struct page **pages, struct vm_area_struct **vmas,
@@ -1520,6 +1569,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 					fault_flags |= FAULT_FLAG_WRITE;
 				if (nonblocking)
 					fault_flags |= FAULT_FLAG_ALLOW_RETRY;
+				if (foll_flags & FOLL_NOWAIT)
+					fault_flags |= (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_RETRY_NOWAIT);
 
 				ret = handle_mm_fault(mm, vma, start,
 							fault_flags);
@@ -1527,9 +1578,16 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 				if (ret & VM_FAULT_ERROR) {
 					if (ret & VM_FAULT_OOM)
 						return i ? i : -ENOMEM;
-					if (ret &
-					    (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE|
-					     VM_FAULT_SIGBUS))
+					if (ret & (VM_FAULT_HWPOISON |
+						   VM_FAULT_HWPOISON_LARGE)) {
+						if (i)
+							return i;
+						else if (gup_flags & FOLL_HWPOISON)
+							return -EHWPOISON;
+						else
+							return -EFAULT;
+					}
+					if (ret & VM_FAULT_SIGBUS)
 						return i ? i : -EFAULT;
 					BUG();
 				}
@@ -1539,7 +1597,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 					tsk->min_flt++;
 
 				if (ret & VM_FAULT_RETRY) {
-					*nonblocking = 0;
+					if (nonblocking)
+						*nonblocking = 0;
 					return i;
 				}
 
@@ -1578,6 +1637,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 	} while (nr_pages);
 	return i;
 }
+EXPORT_SYMBOL(__get_user_pages);
 
 /**
  * get_user_pages() - pin user pages in memory
@@ -2115,10 +2175,10 @@ EXPORT_SYMBOL_GPL(apply_to_page_range);
  * handle_pte_fault chooses page fault handler according to an entry
  * which was read non-atomically.  Before making any commitment, on
  * those architectures or configurations (e.g. i386 with PAE) which
- * might give a mix of unmatched parts, do_swap_page and do_file_page
+ * might give a mix of unmatched parts, do_swap_page and do_nonlinear_fault
  * must check under lock before unmapping the pte and proceeding
  * (but do_wp_page is only called after already making such a check;
- * and do_anonymous_page and do_no_page can safely check later on).
+ * and do_anonymous_page can safely check later on).
  */
 static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd,
 				pte_t *page_table, pte_t orig_pte)
@@ -2314,7 +2374,7 @@ reuse:
 		 * bit after it clear all dirty ptes, but before a racing
 		 * do_wp_page installs a dirty pte.
 		 *
-		 * do_no_page is protected similarly.
+		 * __do_fault is protected similarly.
 		 */
 		if (!page_mkwrite) {
 			wait_on_page_locked(dirty_page);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index b53ec99..959a8b8 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -993,7 +993,7 @@ int do_migrate_pages(struct mm_struct *mm,
 	 * most recent <s, d> pair that moved (s != d).  If we find a pair
 	 * that not only moved, but what's better, moved to an empty slot
 	 * (d is not set in tmp), then we break out then, with that pair.
-	 * Otherwise when we finish scannng from_tmp, we at least have the
+	 * Otherwise when we finish scanning from_tmp, we at least have the
 	 * most recent <s, d> pair that moved.  If we get all the way through
 	 * the scan of tmp without finding any node that moved, much less
 	 * moved to an empty node, then there is nothing left worth migrating.
@@ -1979,8 +1979,7 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b)
 	case MPOL_INTERLEAVE:
 		return nodes_equal(a->v.nodes, b->v.nodes);
 	case MPOL_PREFERRED:
-		return a->v.preferred_node == b->v.preferred_node &&
-			a->flags == b->flags;
+		return a->v.preferred_node == b->v.preferred_node;
 	default:
 		BUG();
 		return 0;
diff --git a/mm/migrate.c b/mm/migrate.c
index 352de555..89e5c3f 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -564,7 +564,7 @@ static int fallback_migrate_page(struct address_space *mapping,
  *  == 0 - success
  */
 static int move_to_new_page(struct page *newpage, struct page *page,
-						int remap_swapcache)
+					int remap_swapcache, bool sync)
 {
 	struct address_space *mapping;
 	int rc;
@@ -586,18 +586,28 @@ static int move_to_new_page(struct page *newpage, struct page *page,
 	mapping = page_mapping(page);
 	if (!mapping)
 		rc = migrate_page(mapping, newpage, page);
-	else if (mapping->a_ops->migratepage)
+	else {
 		/*
-		 * Most pages have a mapping and most filesystems
-		 * should provide a migration function. Anonymous
-		 * pages are part of swap space which also has its
-		 * own migration function. This is the most common
-		 * path for page migration.
+		 * Do not writeback pages if !sync and migratepage is
+		 * not pointing to migrate_page() which is nonblocking
+		 * (swapcache/tmpfs uses migratepage = migrate_page).
 		 */
-		rc = mapping->a_ops->migratepage(mapping,
-						newpage, page);
-	else
-		rc = fallback_migrate_page(mapping, newpage, page);
+		if (PageDirty(page) && !sync &&
+		    mapping->a_ops->migratepage != migrate_page)
+			rc = -EBUSY;
+		else if (mapping->a_ops->migratepage)
+			/*
+			 * Most pages have a mapping and most filesystems
+			 * should provide a migration function. Anonymous
+			 * pages are part of swap space which also has its
+			 * own migration function. This is the most common
+			 * path for page migration.
+			 */
+			rc = mapping->a_ops->migratepage(mapping,
+							newpage, page);
+		else
+			rc = fallback_migrate_page(mapping, newpage, page);
+	}
 
 	if (rc) {
 		newpage->mapping = NULL;
@@ -641,7 +651,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
 	rc = -EAGAIN;
 
 	if (!trylock_page(page)) {
-		if (!force)
+		if (!force || !sync)
 			goto move_newpage;
 
 		/*
@@ -678,7 +688,7 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
 	}
 
 	/* charge against new page */
-	charge = mem_cgroup_prepare_migration(page, newpage, &mem);
+	charge = mem_cgroup_prepare_migration(page, newpage, &mem, GFP_KERNEL);
 	if (charge == -ENOMEM) {
 		rc = -ENOMEM;
 		goto unlock;
@@ -686,7 +696,15 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
 	BUG_ON(charge);
 
 	if (PageWriteback(page)) {
-		if (!force || !sync)
+		/*
+		 * For !sync, there is no point retrying as the retry loop
+		 * is expected to be too short for PageWriteback to be cleared
+		 */
+		if (!sync) {
+			rc = -EBUSY;
+			goto uncharge;
+		}
+		if (!force)
 			goto uncharge;
 		wait_on_page_writeback(page);
 	}
@@ -757,14 +775,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
 
 skip_unmap:
 	if (!page_mapped(page))
-		rc = move_to_new_page(newpage, page, remap_swapcache);
+		rc = move_to_new_page(newpage, page, remap_swapcache, sync);
 
 	if (rc && remap_swapcache)
 		remove_migration_ptes(page, page);
 
 	/* Drop an anon_vma reference if we took one */
 	if (anon_vma)
-		drop_anon_vma(anon_vma);
+		put_anon_vma(anon_vma);
 
 uncharge:
 	if (!charge)
@@ -850,13 +868,13 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
 	try_to_unmap(hpage, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
 
 	if (!page_mapped(hpage))
-		rc = move_to_new_page(new_hpage, hpage, 1);
+		rc = move_to_new_page(new_hpage, hpage, 1, sync);
 
 	if (rc)
 		remove_migration_ptes(hpage, hpage);
 
 	if (anon_vma)
-		drop_anon_vma(anon_vma);
+		put_anon_vma(anon_vma);
 out:
 	unlock_page(hpage);
 
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
new file mode 100644
index 0000000..e2bdb07
--- /dev/null
+++ b/mm/nobootmem.c
@@ -0,0 +1,435 @@
+/*
+ *  bootmem - A boot-time physical memory allocator and configurator
+ *
+ *  Copyright (C) 1999 Ingo Molnar
+ *                1999 Kanoj Sarcar, SGI
+ *                2008 Johannes Weiner
+ *
+ * Access to this subsystem has to be serialized externally (which is true
+ * for the boot process anyway).
+ */
+#include <linux/init.h>
+#include <linux/pfn.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/kmemleak.h>
+#include <linux/range.h>
+#include <linux/memblock.h>
+
+#include <asm/bug.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+
+#include "internal.h"
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+struct pglist_data __refdata contig_page_data;
+EXPORT_SYMBOL(contig_page_data);
+#endif
+
+unsigned long max_low_pfn;
+unsigned long min_low_pfn;
+unsigned long max_pfn;
+
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * If we have booted due to a crash, max_pfn will be a very low value. We need
+ * to know the amount of memory that the previous kernel used.
+ */
+unsigned long saved_max_pfn;
+#endif
+
+static void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
+					u64 goal, u64 limit)
+{
+	void *ptr;
+	u64 addr;
+
+	if (limit > memblock.current_limit)
+		limit = memblock.current_limit;
+
+	addr = find_memory_core_early(nid, size, align, goal, limit);
+
+	if (addr == MEMBLOCK_ERROR)
+		return NULL;
+
+	ptr = phys_to_virt(addr);
+	memset(ptr, 0, size);
+	memblock_x86_reserve_range(addr, addr + size, "BOOTMEM");
+	/*
+	 * The min_count is set to 0 so that bootmem allocated blocks
+	 * are never reported as leaks.
+	 */
+	kmemleak_alloc(ptr, size, 0, 0);
+	return ptr;
+}
+
+/*
+ * free_bootmem_late - free bootmem pages directly to page allocator
+ * @addr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * This is only useful when the bootmem allocator has already been torn
+ * down, but we are still initializing the system.  Pages are given directly
+ * to the page allocator, no bootmem metadata is updated because it is gone.
+ */
+void __init free_bootmem_late(unsigned long addr, unsigned long size)
+{
+	unsigned long cursor, end;
+
+	kmemleak_free_part(__va(addr), size);
+
+	cursor = PFN_UP(addr);
+	end = PFN_DOWN(addr + size);
+
+	for (; cursor < end; cursor++) {
+		__free_pages_bootmem(pfn_to_page(cursor), 0);
+		totalram_pages++;
+	}
+}
+
+static void __init __free_pages_memory(unsigned long start, unsigned long end)
+{
+	int i;
+	unsigned long start_aligned, end_aligned;
+	int order = ilog2(BITS_PER_LONG);
+
+	start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
+	end_aligned = end & ~(BITS_PER_LONG - 1);
+
+	if (end_aligned <= start_aligned) {
+		for (i = start; i < end; i++)
+			__free_pages_bootmem(pfn_to_page(i), 0);
+
+		return;
+	}
+
+	for (i = start; i < start_aligned; i++)
+		__free_pages_bootmem(pfn_to_page(i), 0);
+
+	for (i = start_aligned; i < end_aligned; i += BITS_PER_LONG)
+		__free_pages_bootmem(pfn_to_page(i), order);
+
+	for (i = end_aligned; i < end; i++)
+		__free_pages_bootmem(pfn_to_page(i), 0);
+}
+
+unsigned long __init free_all_memory_core_early(int nodeid)
+{
+	int i;
+	u64 start, end;
+	unsigned long count = 0;
+	struct range *range = NULL;
+	int nr_range;
+
+	nr_range = get_free_all_memory_range(&range, nodeid);
+
+	for (i = 0; i < nr_range; i++) {
+		start = range[i].start;
+		end = range[i].end;
+		count += end - start;
+		__free_pages_memory(start, end);
+	}
+
+	return count;
+}
+
+/**
+ * free_all_bootmem_node - release a node's free pages to the buddy allocator
+ * @pgdat: node to be released
+ *
+ * Returns the number of pages actually released.
+ */
+unsigned long __init free_all_bootmem_node(pg_data_t *pgdat)
+{
+	register_page_bootmem_info_node(pgdat);
+
+	/* free_all_memory_core_early(MAX_NUMNODES) will be called later */
+	return 0;
+}
+
+/**
+ * free_all_bootmem - release free pages to the buddy allocator
+ *
+ * Returns the number of pages actually released.
+ */
+unsigned long __init free_all_bootmem(void)
+{
+	/*
+	 * We need to use MAX_NUMNODES instead of NODE_DATA(0)->node_id
+	 *  because in some case like Node0 doesnt have RAM installed
+	 *  low ram will be on Node1
+	 * Use MAX_NUMNODES will make sure all ranges in early_node_map[]
+	 *  will be used instead of only Node0 related
+	 */
+	return free_all_memory_core_early(MAX_NUMNODES);
+}
+
+/**
+ * free_bootmem_node - mark a page range as usable
+ * @pgdat: node the range resides on
+ * @physaddr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * Partial pages will be considered reserved and left as they are.
+ *
+ * The range must reside completely on the specified node.
+ */
+void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
+			      unsigned long size)
+{
+	kmemleak_free_part(__va(physaddr), size);
+	memblock_x86_free_range(physaddr, physaddr + size);
+}
+
+/**
+ * free_bootmem - mark a page range as usable
+ * @addr: starting address of the range
+ * @size: size of the range in bytes
+ *
+ * Partial pages will be considered reserved and left as they are.
+ *
+ * The range must be contiguous but may span node boundaries.
+ */
+void __init free_bootmem(unsigned long addr, unsigned long size)
+{
+	kmemleak_free_part(__va(addr), size);
+	memblock_x86_free_range(addr, addr + size);
+}
+
+static void * __init ___alloc_bootmem_nopanic(unsigned long size,
+					unsigned long align,
+					unsigned long goal,
+					unsigned long limit)
+{
+	void *ptr;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc(size, GFP_NOWAIT);
+
+restart:
+
+	ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, goal, limit);
+
+	if (ptr)
+		return ptr;
+
+	if (goal != 0) {
+		goal = 0;
+		goto restart;
+	}
+
+	return NULL;
+}
+
+/**
+ * __alloc_bootmem_nopanic - allocate boot memory without panicking
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * Returns NULL on failure.
+ */
+void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,
+					unsigned long goal)
+{
+	unsigned long limit = -1UL;
+
+	return ___alloc_bootmem_nopanic(size, align, goal, limit);
+}
+
+static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,
+					unsigned long goal, unsigned long limit)
+{
+	void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit);
+
+	if (mem)
+		return mem;
+	/*
+	 * Whoops, we cannot satisfy the allocation request.
+	 */
+	printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);
+	panic("Out of memory");
+	return NULL;
+}
+
+/**
+ * __alloc_bootmem - allocate boot memory
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem(unsigned long size, unsigned long align,
+			      unsigned long goal)
+{
+	unsigned long limit = -1UL;
+
+	return ___alloc_bootmem(size, align, goal, limit);
+}
+
+/**
+ * __alloc_bootmem_node - allocate boot memory from a specific node
+ * @pgdat: node to allocate from
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may fall back to any node in the system if the specified node
+ * can not hold the requested memory.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,
+				   unsigned long align, unsigned long goal)
+{
+	void *ptr;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+
+	ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
+					 goal, -1ULL);
+	if (ptr)
+		return ptr;
+
+	return __alloc_memory_core_early(MAX_NUMNODES, size, align,
+					 goal, -1ULL);
+}
+
+void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
+				   unsigned long align, unsigned long goal)
+{
+#ifdef MAX_DMA32_PFN
+	unsigned long end_pfn;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+
+	/* update goal according ...MAX_DMA32_PFN */
+	end_pfn = pgdat->node_start_pfn + pgdat->node_spanned_pages;
+
+	if (end_pfn > MAX_DMA32_PFN + (128 >> (20 - PAGE_SHIFT)) &&
+	    (goal >> PAGE_SHIFT) < MAX_DMA32_PFN) {
+		void *ptr;
+		unsigned long new_goal;
+
+		new_goal = MAX_DMA32_PFN << PAGE_SHIFT;
+		ptr =  __alloc_memory_core_early(pgdat->node_id, size, align,
+						 new_goal, -1ULL);
+		if (ptr)
+			return ptr;
+	}
+#endif
+
+	return __alloc_bootmem_node(pgdat, size, align, goal);
+
+}
+
+#ifdef CONFIG_SPARSEMEM
+/**
+ * alloc_bootmem_section - allocate boot memory from a specific section
+ * @size: size of the request in bytes
+ * @section_nr: sparse map section to allocate from
+ *
+ * Return NULL on failure.
+ */
+void * __init alloc_bootmem_section(unsigned long size,
+				    unsigned long section_nr)
+{
+	unsigned long pfn, goal, limit;
+
+	pfn = section_nr_to_pfn(section_nr);
+	goal = pfn << PAGE_SHIFT;
+	limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
+
+	return __alloc_memory_core_early(early_pfn_to_nid(pfn), size,
+					 SMP_CACHE_BYTES, goal, limit);
+}
+#endif
+
+void * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,
+				   unsigned long align, unsigned long goal)
+{
+	void *ptr;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+
+	ptr =  __alloc_memory_core_early(pgdat->node_id, size, align,
+						 goal, -1ULL);
+	if (ptr)
+		return ptr;
+
+	return __alloc_bootmem_nopanic(size, align, goal);
+}
+
+#ifndef ARCH_LOW_ADDRESS_LIMIT
+#define ARCH_LOW_ADDRESS_LIMIT	0xffffffffUL
+#endif
+
+/**
+ * __alloc_bootmem_low - allocate low boot memory
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may happen on any node in the system.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,
+				  unsigned long goal)
+{
+	return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);
+}
+
+/**
+ * __alloc_bootmem_low_node - allocate low boot memory from a specific node
+ * @pgdat: node to allocate from
+ * @size: size of the request in bytes
+ * @align: alignment of the region
+ * @goal: preferred starting address of the region
+ *
+ * The goal is dropped if it can not be satisfied and the allocation will
+ * fall back to memory below @goal.
+ *
+ * Allocation may fall back to any node in the system if the specified node
+ * can not hold the requested memory.
+ *
+ * The function panics if the request can not be satisfied.
+ */
+void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,
+				       unsigned long align, unsigned long goal)
+{
+	void *ptr;
+
+	if (WARN_ON_ONCE(slab_is_available()))
+		return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+
+	ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
+				goal, ARCH_LOW_ADDRESS_LIMIT);
+	if (ptr)
+		return ptr;
+
+	return  __alloc_memory_core_early(MAX_NUMNODES, size, align,
+				goal, ARCH_LOW_ADDRESS_LIMIT);
+}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 7dcca55..3100bc5 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -31,6 +31,7 @@
 #include <linux/memcontrol.h>
 #include <linux/mempolicy.h>
 #include <linux/security.h>
+#include <linux/ptrace.h>
 
 int sysctl_panic_on_oom;
 int sysctl_oom_kill_allocating_task;
@@ -292,13 +293,15 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
 		unsigned long totalpages, struct mem_cgroup *mem,
 		const nodemask_t *nodemask)
 {
-	struct task_struct *p;
+	struct task_struct *g, *p;
 	struct task_struct *chosen = NULL;
 	*ppoints = 0;
 
-	for_each_process(p) {
+	do_each_thread(g, p) {
 		unsigned int points;
 
+		if (!p->mm)
+			continue;
 		if (oom_unkillable_task(p, mem, nodemask))
 			continue;
 
@@ -314,22 +317,29 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
 		if (test_tsk_thread_flag(p, TIF_MEMDIE))
 			return ERR_PTR(-1UL);
 
-		/*
-		 * This is in the process of releasing memory so wait for it
-		 * to finish before killing some other task by mistake.
-		 *
-		 * However, if p is the current task, we allow the 'kill' to
-		 * go ahead if it is exiting: this will simply set TIF_MEMDIE,
-		 * which will allow it to gain access to memory reserves in
-		 * the process of exiting and releasing its resources.
-		 * Otherwise we could get an easy OOM deadlock.
-		 */
-		if (thread_group_empty(p) && (p->flags & PF_EXITING) && p->mm) {
-			if (p != current)
-				return ERR_PTR(-1UL);
-
-			chosen = p;
-			*ppoints = 1000;
+		if (p->flags & PF_EXITING) {
+			/*
+			 * If p is the current task and is in the process of
+			 * releasing memory, we allow the "kill" to set
+			 * TIF_MEMDIE, which will allow it to gain access to
+			 * memory reserves.  Otherwise, it may stall forever.
+			 *
+			 * The loop isn't broken here, however, in case other
+			 * threads are found to have already been oom killed.
+			 */
+			if (p == current) {
+				chosen = p;
+				*ppoints = 1000;
+			} else {
+				/*
+				 * If this task is not being ptraced on exit,
+				 * then wait for it to finish before killing
+				 * some other task unnecessarily.
+				 */
+				if (!(task_ptrace(p->group_leader) &
+							PT_TRACE_EXIT))
+					return ERR_PTR(-1UL);
+			}
 		}
 
 		points = oom_badness(p, mem, nodemask, totalpages);
@@ -337,7 +347,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
 			chosen = p;
 			*ppoints = points;
 		}
-	}
+	} while_each_thread(g, p);
 
 	return chosen;
 }
@@ -396,7 +406,7 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 	task_unlock(current);
 	dump_stack();
 	mem_cgroup_print_oom_info(mem, p);
-	show_mem();
+	__show_mem(SHOW_MEM_FILTER_NODES);
 	if (sysctl_oom_dump_tasks)
 		dump_tasks(mem, nodemask);
 }
@@ -491,6 +501,8 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
 		list_for_each_entry(child, &t->children, sibling) {
 			unsigned int child_points;
 
+			if (child->mm == p->mm)
+				continue;
 			/*
 			 * oom_badness() returns 0 if the thread is unkillable
 			 */
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 2cb01f6..632b464 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -927,7 +927,7 @@ retry:
 				break;
 			}
 
-			done_index = page->index + 1;
+			done_index = page->index;
 
 			lock_page(page);
 
@@ -977,6 +977,7 @@ continue_unlock:
 					 * not be suitable for data integrity
 					 * writeout).
 					 */
+					done_index = page->index + 1;
 					done = 1;
 					break;
 				}
@@ -1211,6 +1212,17 @@ int set_page_dirty(struct page *page)
 
 	if (likely(mapping)) {
 		int (*spd)(struct page *) = mapping->a_ops->set_page_dirty;
+		/*
+		 * readahead/lru_deactivate_page could remain
+		 * PG_readahead/PG_reclaim due to race with end_page_writeback
+		 * About readahead, if the page is written, the flags would be
+		 * reset. So no problem.
+		 * About lru_deactivate_page, if the page is redirty, the flag
+		 * will be reset. So no problem. but if the page is used by readahead
+		 * it will confuse readahead and make it restart the size rampup
+		 * process. But it's a trivial problem.
+		 */
+		ClearPageReclaim(page);
 #ifdef CONFIG_BLOCK
 		if (!spd)
 			spd = __set_page_dirty_buffers;
@@ -1266,7 +1278,6 @@ int clear_page_dirty_for_io(struct page *page)
 
 	BUG_ON(!PageLocked(page));
 
-	ClearPageReclaim(page);
 	if (mapping && mapping_cap_account_dirty(mapping)) {
 		/*
 		 * Yes, Virginia, this is indeed insane.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index cdef1d4..3a58221 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -286,7 +286,7 @@ static void bad_page(struct page *page)
 
 	/* Don't complain about poisoned pages */
 	if (PageHWPoison(page)) {
-		__ClearPageBuddy(page);
+		reset_page_mapcount(page); /* remove PageBuddy */
 		return;
 	}
 
@@ -317,7 +317,7 @@ static void bad_page(struct page *page)
 	dump_stack();
 out:
 	/* Leave bad fields for debug, except PageBuddy could make trouble */
-	__ClearPageBuddy(page);
+	reset_page_mapcount(page); /* remove PageBuddy */
 	add_taint(TAINT_BAD_PAGE);
 }
 
@@ -614,6 +614,10 @@ static void free_pcppages_bulk(struct zone *zone, int count,
 			list = &pcp->lists[migratetype];
 		} while (list_empty(list));
 
+		/* This is the only non-empty list. Free them all. */
+		if (batch_free == MIGRATE_PCPTYPES)
+			batch_free = to_free;
+
 		do {
 			page = list_entry(list->prev, struct page, lru);
 			/* must delete as __free_one_page list manipulates */
@@ -863,9 +867,8 @@ static int move_freepages(struct zone *zone,
 		}
 
 		order = page_order(page);
-		list_del(&page->lru);
-		list_add(&page->lru,
-			&zone->free_area[order].free_list[migratetype]);
+		list_move(&page->lru,
+			  &zone->free_area[order].free_list[migratetype]);
 		page += 1 << order;
 		pages_moved += 1 << order;
 	}
@@ -1333,7 +1336,7 @@ again:
 	}
 
 	__count_zone_vm_events(PGALLOC, zone, 1 << order);
-	zone_statistics(preferred_zone, zone);
+	zone_statistics(preferred_zone, zone, gfp_flags);
 	local_irq_restore(flags);
 
 	VM_BUG_ON(bad_range(zone, page));
@@ -1714,6 +1717,20 @@ try_next_zone:
 	return page;
 }
 
+/*
+ * Large machines with many possible nodes should not always dump per-node
+ * meminfo in irq context.
+ */
+static inline bool should_suppress_show_mem(void)
+{
+	bool ret = false;
+
+#if NODES_SHIFT > 8
+	ret = in_interrupt();
+#endif
+	return ret;
+}
+
 static inline int
 should_alloc_retry(gfp_t gfp_mask, unsigned int order,
 				unsigned long pages_reclaimed)
@@ -2085,7 +2102,7 @@ rebalance:
 					sync_migration);
 	if (page)
 		goto got_pg;
-	sync_migration = true;
+	sync_migration = !(gfp_mask & __GFP_NO_KSWAPD);
 
 	/* Try direct reclaim and then allocating */
 	page = __alloc_pages_direct_reclaim(gfp_mask, order,
@@ -2157,11 +2174,25 @@ rebalance:
 
 nopage:
 	if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit()) {
-		printk(KERN_WARNING "%s: page allocation failure."
-			" order:%d, mode:0x%x\n",
+		unsigned int filter = SHOW_MEM_FILTER_NODES;
+
+		/*
+		 * This documents exceptions given to allocations in certain
+		 * contexts that are allowed to allocate outside current's set
+		 * of allowed nodes.
+		 */
+		if (!(gfp_mask & __GFP_NOMEMALLOC))
+			if (test_thread_flag(TIF_MEMDIE) ||
+			    (current->flags & (PF_MEMALLOC | PF_EXITING)))
+				filter &= ~SHOW_MEM_FILTER_NODES;
+		if (in_interrupt() || !wait)
+			filter &= ~SHOW_MEM_FILTER_NODES;
+
+		pr_warning("%s: page allocation failure. order:%d, mode:0x%x\n",
 			current->comm, order, gfp_mask);
 		dump_stack();
-		show_mem();
+		if (!should_suppress_show_mem())
+			__show_mem(filter);
 	}
 	return page;
 got_pg:
@@ -2411,19 +2442,42 @@ void si_meminfo_node(struct sysinfo *val, int nid)
 }
 #endif
 
+/*
+ * Determine whether the zone's node should be displayed or not, depending on
+ * whether SHOW_MEM_FILTER_NODES was passed to __show_free_areas().
+ */
+static bool skip_free_areas_zone(unsigned int flags, const struct zone *zone)
+{
+	bool ret = false;
+
+	if (!(flags & SHOW_MEM_FILTER_NODES))
+		goto out;
+
+	get_mems_allowed();
+	ret = !node_isset(zone->zone_pgdat->node_id,
+				cpuset_current_mems_allowed);
+	put_mems_allowed();
+out:
+	return ret;
+}
+
 #define K(x) ((x) << (PAGE_SHIFT-10))
 
 /*
  * Show free area list (used inside shift_scroll-lock stuff)
  * We also calculate the percentage fragmentation. We do this by counting the
  * memory on each free list with the exception of the first item on the list.
+ * Suppresses nodes that are not allowed by current's cpuset if
+ * SHOW_MEM_FILTER_NODES is passed.
  */
-void show_free_areas(void)
+void __show_free_areas(unsigned int filter)
 {
 	int cpu;
 	struct zone *zone;
 
 	for_each_populated_zone(zone) {
+		if (skip_free_areas_zone(filter, zone))
+			continue;
 		show_node(zone);
 		printk("%s per-cpu:\n", zone->name);
 
@@ -2465,6 +2519,8 @@ void show_free_areas(void)
 	for_each_populated_zone(zone) {
 		int i;
 
+		if (skip_free_areas_zone(filter, zone))
+			continue;
 		show_node(zone);
 		printk("%s"
 			" free:%lukB"
@@ -2532,6 +2588,8 @@ void show_free_areas(void)
 	for_each_populated_zone(zone) {
  		unsigned long nr[MAX_ORDER], flags, order, total = 0;
 
+		if (skip_free_areas_zone(filter, zone))
+			continue;
 		show_node(zone);
 		printk("%s: ", zone->name);
 
@@ -2551,6 +2609,11 @@ void show_free_areas(void)
 	show_swap_cache_info();
 }
 
+void show_free_areas(void)
+{
+	__show_free_areas(0);
+}
+
 static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref)
 {
 	zoneref->zone = zone;
@@ -3699,13 +3762,45 @@ void __init free_bootmem_with_active_regions(int nid,
 }
 
 #ifdef CONFIG_HAVE_MEMBLOCK
+/*
+ * Basic iterator support. Return the last range of PFNs for a node
+ * Note: nid == MAX_NUMNODES returns last region regardless of node
+ */
+static int __meminit last_active_region_index_in_nid(int nid)
+{
+	int i;
+
+	for (i = nr_nodemap_entries - 1; i >= 0; i--)
+		if (nid == MAX_NUMNODES || early_node_map[i].nid == nid)
+			return i;
+
+	return -1;
+}
+
+/*
+ * Basic iterator support. Return the previous active range of PFNs for a node
+ * Note: nid == MAX_NUMNODES returns next region regardless of node
+ */
+static int __meminit previous_active_region_index_in_nid(int index, int nid)
+{
+	for (index = index - 1; index >= 0; index--)
+		if (nid == MAX_NUMNODES || early_node_map[index].nid == nid)
+			return index;
+
+	return -1;
+}
+
+#define for_each_active_range_index_in_nid_reverse(i, nid) \
+	for (i = last_active_region_index_in_nid(nid); i != -1; \
+				i = previous_active_region_index_in_nid(i, nid))
+
 u64 __init find_memory_core_early(int nid, u64 size, u64 align,
 					u64 goal, u64 limit)
 {
 	int i;
 
 	/* Need to go over early_node_map to find out good range for node */
-	for_each_active_range_index_in_nid(i, nid) {
+	for_each_active_range_index_in_nid_reverse(i, nid) {
 		u64 addr;
 		u64 ei_start, ei_last;
 		u64 final_start, final_end;
@@ -3748,34 +3843,6 @@ int __init add_from_early_node_map(struct range *range, int az,
 	return nr_range;
 }
 
-#ifdef CONFIG_NO_BOOTMEM
-void * __init __alloc_memory_core_early(int nid, u64 size, u64 align,
-					u64 goal, u64 limit)
-{
-	void *ptr;
-	u64 addr;
-
-	if (limit > memblock.current_limit)
-		limit = memblock.current_limit;
-
-	addr = find_memory_core_early(nid, size, align, goal, limit);
-
-	if (addr == MEMBLOCK_ERROR)
-		return NULL;
-
-	ptr = phys_to_virt(addr);
-	memset(ptr, 0, size);
-	memblock_x86_reserve_range(addr, addr + size, "BOOTMEM");
-	/*
-	 * The min_count is set to 0 so that bootmem allocated blocks
-	 * are never reported as leaks.
-	 */
-	kmemleak_alloc(ptr, size, 0, 0);
-	return ptr;
-}
-#endif
-
-
 void __init work_with_active_regions(int nid, work_fn_t work_fn, void *data)
 {
 	int i;
@@ -4809,15 +4876,6 @@ void __init set_dma_reserve(unsigned long new_dma_reserve)
 	dma_reserve = new_dma_reserve;
 }
 
-#ifndef CONFIG_NEED_MULTIPLE_NODES
-struct pglist_data __refdata contig_page_data = {
-#ifndef CONFIG_NO_BOOTMEM
- .bdata = &bootmem_node_data[0]
-#endif
- };
-EXPORT_SYMBOL(contig_page_data);
-#endif
-
 void __init free_area_init(unsigned long *zones_size)
 {
 	free_area_init_node(0, zones_size,
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index 5bffada..59a3cd4 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -243,12 +243,7 @@ static int __meminit page_cgroup_callback(struct notifier_block *self,
 		break;
 	}
 
-	if (ret)
-		ret = notifier_from_errno(ret);
-	else
-		ret = NOTIFY_OK;
-
-	return ret;
+	return notifier_from_errno(ret);
 }
 
 #endif
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index 7cfa6ae..c3450d5 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -33,19 +33,35 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
 
 	pmd = pmd_offset(pud, addr);
 	do {
+again:
 		next = pmd_addr_end(addr, end);
-		split_huge_page_pmd(walk->mm, pmd);
-		if (pmd_none_or_clear_bad(pmd)) {
+		if (pmd_none(*pmd)) {
 			if (walk->pte_hole)
 				err = walk->pte_hole(addr, next, walk);
 			if (err)
 				break;
 			continue;
 		}
+		/*
+		 * This implies that each ->pmd_entry() handler
+		 * needs to know about pmd_trans_huge() pmds
+		 */
 		if (walk->pmd_entry)
 			err = walk->pmd_entry(pmd, addr, next, walk);
-		if (!err && walk->pte_entry)
-			err = walk_pte_range(pmd, addr, next, walk);
+		if (err)
+			break;
+
+		/*
+		 * Check this here so we only break down trans_huge
+		 * pages when we _need_ to
+		 */
+		if (!walk->pte_entry)
+			continue;
+
+		split_huge_page_pmd(walk->mm, pmd);
+		if (pmd_none_or_clear_bad(pmd))
+			goto again;
+		err = walk_pte_range(pmd, addr, next, walk);
 		if (err)
 			break;
 	} while (pmd++, addr = next, addr != end);
diff --git a/mm/rmap.c b/mm/rmap.c
index 941bf82..4a8e99a 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -67,11 +67,24 @@ static struct kmem_cache *anon_vma_chain_cachep;
 
 static inline struct anon_vma *anon_vma_alloc(void)
 {
-	return kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
+	struct anon_vma *anon_vma;
+
+	anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
+	if (anon_vma) {
+		atomic_set(&anon_vma->refcount, 1);
+		/*
+		 * Initialise the anon_vma root to point to itself. If called
+		 * from fork, the root will be reset to the parents anon_vma.
+		 */
+		anon_vma->root = anon_vma;
+	}
+
+	return anon_vma;
 }
 
-void anon_vma_free(struct anon_vma *anon_vma)
+static inline void anon_vma_free(struct anon_vma *anon_vma)
 {
+	VM_BUG_ON(atomic_read(&anon_vma->refcount));
 	kmem_cache_free(anon_vma_cachep, anon_vma);
 }
 
@@ -133,11 +146,6 @@ int anon_vma_prepare(struct vm_area_struct *vma)
 			if (unlikely(!anon_vma))
 				goto out_enomem_free_avc;
 			allocated = anon_vma;
-			/*
-			 * This VMA had no anon_vma yet.  This anon_vma is
-			 * the root of any anon_vma tree that might form.
-			 */
-			anon_vma->root = anon_vma;
 		}
 
 		anon_vma_lock(anon_vma);
@@ -156,7 +164,7 @@ int anon_vma_prepare(struct vm_area_struct *vma)
 		anon_vma_unlock(anon_vma);
 
 		if (unlikely(allocated))
-			anon_vma_free(allocated);
+			put_anon_vma(allocated);
 		if (unlikely(avc))
 			anon_vma_chain_free(avc);
 	}
@@ -241,9 +249,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
 	 */
 	anon_vma->root = pvma->anon_vma->root;
 	/*
-	 * With KSM refcounts, an anon_vma can stay around longer than the
-	 * process it belongs to.  The root anon_vma needs to be pinned
-	 * until this anon_vma is freed, because the lock lives in the root.
+	 * With refcounts, an anon_vma can stay around longer than the
+	 * process it belongs to. The root anon_vma needs to be pinned until
+	 * this anon_vma is freed, because the lock lives in the root.
 	 */
 	get_anon_vma(anon_vma->root);
 	/* Mark this anon_vma as the one where our new (COWed) pages go. */
@@ -253,7 +261,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
 	return 0;
 
  out_error_free_anon_vma:
-	anon_vma_free(anon_vma);
+	put_anon_vma(anon_vma);
  out_error:
 	unlink_anon_vmas(vma);
 	return -ENOMEM;
@@ -272,15 +280,11 @@ static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain)
 	list_del(&anon_vma_chain->same_anon_vma);
 
 	/* We must garbage collect the anon_vma if it's empty */
-	empty = list_empty(&anon_vma->head) && !anonvma_external_refcount(anon_vma);
+	empty = list_empty(&anon_vma->head);
 	anon_vma_unlock(anon_vma);
 
-	if (empty) {
-		/* We no longer need the root anon_vma */
-		if (anon_vma->root != anon_vma)
-			drop_anon_vma(anon_vma->root);
-		anon_vma_free(anon_vma);
-	}
+	if (empty)
+		put_anon_vma(anon_vma);
 }
 
 void unlink_anon_vmas(struct vm_area_struct *vma)
@@ -303,7 +307,7 @@ static void anon_vma_ctor(void *data)
 	struct anon_vma *anon_vma = data;
 
 	spin_lock_init(&anon_vma->lock);
-	anonvma_external_refcount_init(anon_vma);
+	atomic_set(&anon_vma->refcount, 0);
 	INIT_LIST_HEAD(&anon_vma->head);
 }
 
@@ -1486,41 +1490,15 @@ int try_to_munlock(struct page *page)
 		return try_to_unmap_file(page, TTU_MUNLOCK);
 }
 
-#if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
-/*
- * Drop an anon_vma refcount, freeing the anon_vma and anon_vma->root
- * if necessary.  Be careful to do all the tests under the lock.  Once
- * we know we are the last user, nobody else can get a reference and we
- * can do the freeing without the lock.
- */
-void drop_anon_vma(struct anon_vma *anon_vma)
+void __put_anon_vma(struct anon_vma *anon_vma)
 {
-	BUG_ON(atomic_read(&anon_vma->external_refcount) <= 0);
-	if (atomic_dec_and_lock(&anon_vma->external_refcount, &anon_vma->root->lock)) {
-		struct anon_vma *root = anon_vma->root;
-		int empty = list_empty(&anon_vma->head);
-		int last_root_user = 0;
-		int root_empty = 0;
+	struct anon_vma *root = anon_vma->root;
 
-		/*
-		 * The refcount on a non-root anon_vma got dropped.  Drop
-		 * the refcount on the root and check if we need to free it.
-		 */
-		if (empty && anon_vma != root) {
-			BUG_ON(atomic_read(&root->external_refcount) <= 0);
-			last_root_user = atomic_dec_and_test(&root->external_refcount);
-			root_empty = list_empty(&root->head);
-		}
-		anon_vma_unlock(anon_vma);
+	if (root != anon_vma && atomic_dec_and_test(&root->refcount))
+		anon_vma_free(root);
 
-		if (empty) {
-			anon_vma_free(anon_vma);
-			if (root_empty && last_root_user)
-				anon_vma_free(root);
-		}
-	}
+	anon_vma_free(anon_vma);
 }
-#endif
 
 #ifdef CONFIG_MIGRATION
 /*
diff --git a/mm/shmem.c b/mm/shmem.c
index 5ee67c9..91ce9a1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -779,7 +779,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
 			 * If truncating down to a partial page, then
 			 * if that page is already allocated, hold it
 			 * in memory until the truncation is over, so
-			 * truncate_partial_page cannnot miss it were
+			 * truncate_partial_page cannot miss it were
 			 * it assigned to swap.
 			 */
 			if (newsize & (PAGE_CACHE_SIZE-1)) {
@@ -1081,7 +1081,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 	shmem_recalc_inode(inode);
 
 	if (swap.val && add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
-		remove_from_page_cache(page);
+		delete_from_page_cache(page);
 		shmem_swp_set(info, entry, swap.val);
 		shmem_swp_unmap(entry);
 		if (list_empty(&info->swaplist))
@@ -1091,7 +1091,6 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
 		spin_unlock(&info->lock);
 		swap_shmem_alloc(swap);
 		BUG_ON(page_mapped(page));
-		page_cache_release(page);	/* pagecache ref */
 		swap_writepage(page, wbc);
 		if (inode) {
 			mutex_lock(&shmem_swaplist_mutex);
@@ -1843,8 +1842,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 
 	inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
 	if (inode) {
-		error = security_inode_init_security(inode, dir, NULL, NULL,
-						     NULL);
+		error = security_inode_init_security(inode, dir,
+						     &dentry->d_name, NULL,
+						     NULL, NULL);
 		if (error) {
 			if (error != -EOPNOTSUPP) {
 				iput(inode);
@@ -1983,8 +1983,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 	if (!inode)
 		return -ENOSPC;
 
-	error = security_inode_init_security(inode, dir, NULL, NULL,
-					     NULL);
+	error = security_inode_init_security(inode, dir, &dentry->d_name, NULL,
+					     NULL, NULL);
 	if (error) {
 		if (error != -EOPNOTSUPP) {
 			iput(inode);
@@ -2144,8 +2144,10 @@ static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len,
 {
 	struct inode *inode = dentry->d_inode;
 
-	if (*len < 3)
+	if (*len < 3) {
+		*len = 3;
 		return 255;
+	}
 
 	if (inode_unhashed(inode)) {
 		/* Unfortunately insert_inode_hash is not idempotent,
@@ -2791,5 +2793,6 @@ int shmem_zero_setup(struct vm_area_struct *vma)
 		fput(vma->vm_file);
 	vma->vm_file = file;
 	vma->vm_ops = &shmem_vm_ops;
+	vma->vm_flags |= VM_CAN_NONLINEAR;
 	return 0;
 }
diff --git a/mm/slab.c b/mm/slab.c
index 37961d1..568803f 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -191,22 +191,6 @@ typedef unsigned int kmem_bufctl_t;
 #define	SLAB_LIMIT	(((kmem_bufctl_t)(~0U))-3)
 
 /*
- * struct slab
- *
- * Manages the objs in a slab. Placed either at the beginning of mem allocated
- * for a slab, or allocated from an general cache.
- * Slabs are chained into three list: fully used, partial, fully free slabs.
- */
-struct slab {
-	struct list_head list;
-	unsigned long colouroff;
-	void *s_mem;		/* including colour offset */
-	unsigned int inuse;	/* num of objs active in slab */
-	kmem_bufctl_t free;
-	unsigned short nodeid;
-};
-
-/*
  * struct slab_rcu
  *
  * slab_destroy on a SLAB_DESTROY_BY_RCU cache uses this structure to
@@ -219,8 +203,6 @@ struct slab {
  *
  * rcu_read_lock before reading the address, then rcu_read_unlock after
  * taking the spinlock within the structure expected at that address.
- *
- * We assume struct slab_rcu can overlay struct slab when destroying.
  */
 struct slab_rcu {
 	struct rcu_head head;
@@ -229,6 +211,27 @@ struct slab_rcu {
 };
 
 /*
+ * struct slab
+ *
+ * Manages the objs in a slab. Placed either at the beginning of mem allocated
+ * for a slab, or allocated from an general cache.
+ * Slabs are chained into three list: fully used, partial, fully free slabs.
+ */
+struct slab {
+	union {
+		struct {
+			struct list_head list;
+			unsigned long colouroff;
+			void *s_mem;		/* including colour offset */
+			unsigned int inuse;	/* num of objs active in slab */
+			kmem_bufctl_t free;
+			unsigned short nodeid;
+		};
+		struct slab_rcu __slab_cover_slab_rcu;
+	};
+};
+
+/*
  * struct array_cache
  *
  * Purpose:
@@ -1387,7 +1390,7 @@ static int __meminit slab_memory_callback(struct notifier_block *self,
 		break;
 	}
 out:
-	return ret ? notifier_from_errno(ret) : NOTIFY_OK;
+	return notifier_from_errno(ret);
 }
 #endif /* CONFIG_NUMA && CONFIG_MEMORY_HOTPLUG */
 
@@ -2147,8 +2150,6 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp)
  *
  * @name must be valid until the cache is destroyed. This implies that
  * the module calling this has to destroy the cache before getting unloaded.
- * Note that kmem_cache_name() is not guaranteed to return the same pointer,
- * therefore applications must manage it themselves.
  *
  * The flags are
  *
@@ -2288,8 +2289,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 	if (ralign < align) {
 		ralign = align;
 	}
-	/* disable debug if not aligning with REDZONE_ALIGN */
-	if (ralign & (__alignof__(unsigned long long) - 1))
+	/* disable debug if necessary */
+	if (ralign > __alignof__(unsigned long long))
 		flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
 	/*
 	 * 4) Store it.
@@ -2315,8 +2316,8 @@ kmem_cache_create (const char *name, size_t size, size_t align,
 	 */
 	if (flags & SLAB_RED_ZONE) {
 		/* add space for red zone words */
-		cachep->obj_offset += align;
-		size += align + sizeof(unsigned long long);
+		cachep->obj_offset += sizeof(unsigned long long);
+		size += 2 * sizeof(unsigned long long);
 	}
 	if (flags & SLAB_STORE_USER) {
 		/* user store requires one word storage behind the end of
@@ -3840,12 +3841,6 @@ unsigned int kmem_cache_size(struct kmem_cache *cachep)
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
-const char *kmem_cache_name(struct kmem_cache *cachep)
-{
-	return cachep->name;
-}
-EXPORT_SYMBOL_GPL(kmem_cache_name);
-
 /*
  * This initializes kmem_list3 or resizes various caches for all nodes.
  */
diff --git a/mm/slob.c b/mm/slob.c
index 3588eaa..46e0aee 100644
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -666,12 +666,6 @@ unsigned int kmem_cache_size(struct kmem_cache *c)
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
-const char *kmem_cache_name(struct kmem_cache *c)
-{
-	return c->name;
-}
-EXPORT_SYMBOL(kmem_cache_name);
-
 int kmem_cache_shrink(struct kmem_cache *d)
 {
 	return 0;
diff --git a/mm/slub.c b/mm/slub.c
index e15aa7f..93de30d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -217,7 +217,7 @@ static inline void sysfs_slab_remove(struct kmem_cache *s)
 
 #endif
 
-static inline void stat(struct kmem_cache *s, enum stat_item si)
+static inline void stat(const struct kmem_cache *s, enum stat_item si)
 {
 #ifdef CONFIG_SLUB_STATS
 	__this_cpu_inc(s->cpu_slab->stat[si]);
@@ -281,11 +281,40 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr)
 	return (p - addr) / s->size;
 }
 
+static inline size_t slab_ksize(const struct kmem_cache *s)
+{
+#ifdef CONFIG_SLUB_DEBUG
+	/*
+	 * Debugging requires use of the padding between object
+	 * and whatever may come after it.
+	 */
+	if (s->flags & (SLAB_RED_ZONE | SLAB_POISON))
+		return s->objsize;
+
+#endif
+	/*
+	 * If we have the need to store the freelist pointer
+	 * back there or track user information then we can
+	 * only use the space before that information.
+	 */
+	if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
+		return s->inuse;
+	/*
+	 * Else we can use all the padding etc for the allocation
+	 */
+	return s->size;
+}
+
+static inline int order_objects(int order, unsigned long size, int reserved)
+{
+	return ((PAGE_SIZE << order) - reserved) / size;
+}
+
 static inline struct kmem_cache_order_objects oo_make(int order,
-						unsigned long size)
+		unsigned long size, int reserved)
 {
 	struct kmem_cache_order_objects x = {
-		(order << OO_SHIFT) + (PAGE_SIZE << order) / size
+		(order << OO_SHIFT) + order_objects(order, size, reserved)
 	};
 
 	return x;
@@ -617,7 +646,7 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
 		return 1;
 
 	start = page_address(page);
-	length = (PAGE_SIZE << compound_order(page));
+	length = (PAGE_SIZE << compound_order(page)) - s->reserved;
 	end = start + length;
 	remainder = length % s->size;
 	if (!remainder)
@@ -698,7 +727,7 @@ static int check_slab(struct kmem_cache *s, struct page *page)
 		return 0;
 	}
 
-	maxobj = (PAGE_SIZE << compound_order(page)) / s->size;
+	maxobj = order_objects(compound_order(page), s->size, s->reserved);
 	if (page->objects > maxobj) {
 		slab_err(s, page, "objects %u > max %u",
 			s->name, page->objects, maxobj);
@@ -748,7 +777,7 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
 		nr++;
 	}
 
-	max_objects = (PAGE_SIZE << compound_order(page)) / s->size;
+	max_objects = order_objects(compound_order(page), s->size, s->reserved);
 	if (max_objects > MAX_OBJS_PER_PAGE)
 		max_objects = MAX_OBJS_PER_PAGE;
 
@@ -800,21 +829,31 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags)
 static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object)
 {
 	flags &= gfp_allowed_mask;
-	kmemcheck_slab_alloc(s, flags, object, s->objsize);
+	kmemcheck_slab_alloc(s, flags, object, slab_ksize(s));
 	kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, flags);
 }
 
 static inline void slab_free_hook(struct kmem_cache *s, void *x)
 {
 	kmemleak_free_recursive(x, s->flags);
-}
 
-static inline void slab_free_hook_irq(struct kmem_cache *s, void *object)
-{
-	kmemcheck_slab_free(s, object, s->objsize);
-	debug_check_no_locks_freed(object, s->objsize);
-	if (!(s->flags & SLAB_DEBUG_OBJECTS))
-		debug_check_no_obj_freed(object, s->objsize);
+	/*
+	 * Trouble is that we may no longer disable interupts in the fast path
+	 * So in order to make the debug calls that expect irqs to be
+	 * disabled we need to disable interrupts temporarily.
+	 */
+#if defined(CONFIG_KMEMCHECK) || defined(CONFIG_LOCKDEP)
+	{
+		unsigned long flags;
+
+		local_irq_save(flags);
+		kmemcheck_slab_free(s, x, s->objsize);
+		debug_check_no_locks_freed(x, s->objsize);
+		if (!(s->flags & SLAB_DEBUG_OBJECTS))
+			debug_check_no_obj_freed(x, s->objsize);
+		local_irq_restore(flags);
+	}
+#endif
 }
 
 /*
@@ -1101,9 +1140,6 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
 
 static inline void slab_free_hook(struct kmem_cache *s, void *x) {}
 
-static inline void slab_free_hook_irq(struct kmem_cache *s,
-		void *object) {}
-
 #endif /* CONFIG_SLUB_DEBUG */
 
 /*
@@ -1249,21 +1285,38 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
 	__free_pages(page, order);
 }
 
+#define need_reserve_slab_rcu						\
+	(sizeof(((struct page *)NULL)->lru) < sizeof(struct rcu_head))
+
 static void rcu_free_slab(struct rcu_head *h)
 {
 	struct page *page;
 
-	page = container_of((struct list_head *)h, struct page, lru);
+	if (need_reserve_slab_rcu)
+		page = virt_to_head_page(h);
+	else
+		page = container_of((struct list_head *)h, struct page, lru);
+
 	__free_slab(page->slab, page);
 }
 
 static void free_slab(struct kmem_cache *s, struct page *page)
 {
 	if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) {
-		/*
-		 * RCU free overloads the RCU head over the LRU
-		 */
-		struct rcu_head *head = (void *)&page->lru;
+		struct rcu_head *head;
+
+		if (need_reserve_slab_rcu) {
+			int order = compound_order(page);
+			int offset = (PAGE_SIZE << order) - s->reserved;
+
+			VM_BUG_ON(s->reserved != sizeof(*head));
+			head = page_address(page) + offset;
+		} else {
+			/*
+			 * RCU free overloads the RCU head over the LRU
+			 */
+			head = (void *)&page->lru;
+		}
 
 		call_rcu(head, rcu_free_slab);
 	} else
@@ -1487,6 +1540,78 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
 	}
 }
 
+#ifdef CONFIG_CMPXCHG_LOCAL
+#ifdef CONFIG_PREEMPT
+/*
+ * Calculate the next globally unique transaction for disambiguiation
+ * during cmpxchg. The transactions start with the cpu number and are then
+ * incremented by CONFIG_NR_CPUS.
+ */
+#define TID_STEP  roundup_pow_of_two(CONFIG_NR_CPUS)
+#else
+/*
+ * No preemption supported therefore also no need to check for
+ * different cpus.
+ */
+#define TID_STEP 1
+#endif
+
+static inline unsigned long next_tid(unsigned long tid)
+{
+	return tid + TID_STEP;
+}
+
+static inline unsigned int tid_to_cpu(unsigned long tid)
+{
+	return tid % TID_STEP;
+}
+
+static inline unsigned long tid_to_event(unsigned long tid)
+{
+	return tid / TID_STEP;
+}
+
+static inline unsigned int init_tid(int cpu)
+{
+	return cpu;
+}
+
+static inline void note_cmpxchg_failure(const char *n,
+		const struct kmem_cache *s, unsigned long tid)
+{
+#ifdef SLUB_DEBUG_CMPXCHG
+	unsigned long actual_tid = __this_cpu_read(s->cpu_slab->tid);
+
+	printk(KERN_INFO "%s %s: cmpxchg redo ", n, s->name);
+
+#ifdef CONFIG_PREEMPT
+	if (tid_to_cpu(tid) != tid_to_cpu(actual_tid))
+		printk("due to cpu change %d -> %d\n",
+			tid_to_cpu(tid), tid_to_cpu(actual_tid));
+	else
+#endif
+	if (tid_to_event(tid) != tid_to_event(actual_tid))
+		printk("due to cpu running other code. Event %ld->%ld\n",
+			tid_to_event(tid), tid_to_event(actual_tid));
+	else
+		printk("for unknown reason: actual=%lx was=%lx target=%lx\n",
+			actual_tid, tid, next_tid(tid));
+#endif
+	stat(s, CMPXCHG_DOUBLE_CPU_FAIL);
+}
+
+#endif
+
+void init_kmem_cache_cpus(struct kmem_cache *s)
+{
+#if defined(CONFIG_CMPXCHG_LOCAL) && defined(CONFIG_PREEMPT)
+	int cpu;
+
+	for_each_possible_cpu(cpu)
+		per_cpu_ptr(s->cpu_slab, cpu)->tid = init_tid(cpu);
+#endif
+
+}
 /*
  * Remove the cpu slab
  */
@@ -1518,6 +1643,9 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
 		page->inuse--;
 	}
 	c->page = NULL;
+#ifdef CONFIG_CMPXCHG_LOCAL
+	c->tid = next_tid(c->tid);
+#endif
 	unfreeze_slab(s, page, tail);
 }
 
@@ -1652,6 +1780,19 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
 {
 	void **object;
 	struct page *new;
+#ifdef CONFIG_CMPXCHG_LOCAL
+	unsigned long flags;
+
+	local_irq_save(flags);
+#ifdef CONFIG_PREEMPT
+	/*
+	 * We may have been preempted and rescheduled on a different
+	 * cpu before disabling interrupts. Need to reload cpu area
+	 * pointer.
+	 */
+	c = this_cpu_ptr(s->cpu_slab);
+#endif
+#endif
 
 	/* We handle __GFP_ZERO in the caller */
 	gfpflags &= ~__GFP_ZERO;
@@ -1678,6 +1819,10 @@ load_freelist:
 	c->node = page_to_nid(c->page);
 unlock_out:
 	slab_unlock(c->page);
+#ifdef CONFIG_CMPXCHG_LOCAL
+	c->tid = next_tid(c->tid);
+	local_irq_restore(flags);
+#endif
 	stat(s, ALLOC_SLOWPATH);
 	return object;
 
@@ -1713,6 +1858,9 @@ new_slab:
 	}
 	if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit())
 		slab_out_of_memory(s, gfpflags, node);
+#ifdef CONFIG_CMPXCHG_LOCAL
+	local_irq_restore(flags);
+#endif
 	return NULL;
 debug:
 	if (!alloc_debug_processing(s, c->page, object, addr))
@@ -1739,23 +1887,76 @@ static __always_inline void *slab_alloc(struct kmem_cache *s,
 {
 	void **object;
 	struct kmem_cache_cpu *c;
+#ifdef CONFIG_CMPXCHG_LOCAL
+	unsigned long tid;
+#else
 	unsigned long flags;
+#endif
 
 	if (slab_pre_alloc_hook(s, gfpflags))
 		return NULL;
 
+#ifndef CONFIG_CMPXCHG_LOCAL
 	local_irq_save(flags);
+#else
+redo:
+#endif
+
+	/*
+	 * Must read kmem_cache cpu data via this cpu ptr. Preemption is
+	 * enabled. We may switch back and forth between cpus while
+	 * reading from one cpu area. That does not matter as long
+	 * as we end up on the original cpu again when doing the cmpxchg.
+	 */
 	c = __this_cpu_ptr(s->cpu_slab);
+
+#ifdef CONFIG_CMPXCHG_LOCAL
+	/*
+	 * The transaction ids are globally unique per cpu and per operation on
+	 * a per cpu queue. Thus they can be guarantee that the cmpxchg_double
+	 * occurs on the right processor and that there was no operation on the
+	 * linked list in between.
+	 */
+	tid = c->tid;
+	barrier();
+#endif
+
 	object = c->freelist;
 	if (unlikely(!object || !node_match(c, node)))
 
 		object = __slab_alloc(s, gfpflags, node, addr, c);
 
 	else {
+#ifdef CONFIG_CMPXCHG_LOCAL
+		/*
+		 * The cmpxchg will only match if there was no additonal
+		 * operation and if we are on the right processor.
+		 *
+		 * The cmpxchg does the following atomically (without lock semantics!)
+		 * 1. Relocate first pointer to the current per cpu area.
+		 * 2. Verify that tid and freelist have not been changed
+		 * 3. If they were not changed replace tid and freelist
+		 *
+		 * Since this is without lock semantics the protection is only against
+		 * code executing on this cpu *not* from access by other cpus.
+		 */
+		if (unlikely(!this_cpu_cmpxchg_double(
+				s->cpu_slab->freelist, s->cpu_slab->tid,
+				object, tid,
+				get_freepointer(s, object), next_tid(tid)))) {
+
+			note_cmpxchg_failure("slab_alloc", s, tid);
+			goto redo;
+		}
+#else
 		c->freelist = get_freepointer(s, object);
+#endif
 		stat(s, ALLOC_FASTPATH);
 	}
+
+#ifndef CONFIG_CMPXCHG_LOCAL
 	local_irq_restore(flags);
+#endif
 
 	if (unlikely(gfpflags & __GFP_ZERO) && object)
 		memset(object, 0, s->objsize);
@@ -1833,9 +2034,13 @@ static void __slab_free(struct kmem_cache *s, struct page *page,
 {
 	void *prior;
 	void **object = (void *)x;
+#ifdef CONFIG_CMPXCHG_LOCAL
+	unsigned long flags;
 
-	stat(s, FREE_SLOWPATH);
+	local_irq_save(flags);
+#endif
 	slab_lock(page);
+	stat(s, FREE_SLOWPATH);
 
 	if (kmem_cache_debug(s))
 		goto debug;
@@ -1865,6 +2070,9 @@ checks_ok:
 
 out_unlock:
 	slab_unlock(page);
+#ifdef CONFIG_CMPXCHG_LOCAL
+	local_irq_restore(flags);
+#endif
 	return;
 
 slab_empty:
@@ -1876,6 +2084,9 @@ slab_empty:
 		stat(s, FREE_REMOVE_PARTIAL);
 	}
 	slab_unlock(page);
+#ifdef CONFIG_CMPXCHG_LOCAL
+	local_irq_restore(flags);
+#endif
 	stat(s, FREE_SLAB);
 	discard_slab(s, page);
 	return;
@@ -1902,23 +2113,56 @@ static __always_inline void slab_free(struct kmem_cache *s,
 {
 	void **object = (void *)x;
 	struct kmem_cache_cpu *c;
+#ifdef CONFIG_CMPXCHG_LOCAL
+	unsigned long tid;
+#else
 	unsigned long flags;
+#endif
 
 	slab_free_hook(s, x);
 
+#ifndef CONFIG_CMPXCHG_LOCAL
 	local_irq_save(flags);
+
+#else
+redo:
+#endif
+
+	/*
+	 * Determine the currently cpus per cpu slab.
+	 * The cpu may change afterward. However that does not matter since
+	 * data is retrieved via this pointer. If we are on the same cpu
+	 * during the cmpxchg then the free will succedd.
+	 */
 	c = __this_cpu_ptr(s->cpu_slab);
 
-	slab_free_hook_irq(s, x);
+#ifdef CONFIG_CMPXCHG_LOCAL
+	tid = c->tid;
+	barrier();
+#endif
 
 	if (likely(page == c->page && c->node != NUMA_NO_NODE)) {
 		set_freepointer(s, object, c->freelist);
+
+#ifdef CONFIG_CMPXCHG_LOCAL
+		if (unlikely(!this_cpu_cmpxchg_double(
+				s->cpu_slab->freelist, s->cpu_slab->tid,
+				c->freelist, tid,
+				object, next_tid(tid)))) {
+
+			note_cmpxchg_failure("slab_free", s, tid);
+			goto redo;
+		}
+#else
 		c->freelist = object;
+#endif
 		stat(s, FREE_FASTPATH);
 	} else
 		__slab_free(s, page, x, addr);
 
+#ifndef CONFIG_CMPXCHG_LOCAL
 	local_irq_restore(flags);
+#endif
 }
 
 void kmem_cache_free(struct kmem_cache *s, void *x)
@@ -1988,13 +2232,13 @@ static int slub_nomerge;
  * the smallest order which will fit the object.
  */
 static inline int slab_order(int size, int min_objects,
-				int max_order, int fract_leftover)
+				int max_order, int fract_leftover, int reserved)
 {
 	int order;
 	int rem;
 	int min_order = slub_min_order;
 
-	if ((PAGE_SIZE << min_order) / size > MAX_OBJS_PER_PAGE)
+	if (order_objects(min_order, size, reserved) > MAX_OBJS_PER_PAGE)
 		return get_order(size * MAX_OBJS_PER_PAGE) - 1;
 
 	for (order = max(min_order,
@@ -2003,10 +2247,10 @@ static inline int slab_order(int size, int min_objects,
 
 		unsigned long slab_size = PAGE_SIZE << order;
 
-		if (slab_size < min_objects * size)
+		if (slab_size < min_objects * size + reserved)
 			continue;
 
-		rem = slab_size % size;
+		rem = (slab_size - reserved) % size;
 
 		if (rem <= slab_size / fract_leftover)
 			break;
@@ -2016,7 +2260,7 @@ static inline int slab_order(int size, int min_objects,
 	return order;
 }
 
-static inline int calculate_order(int size)
+static inline int calculate_order(int size, int reserved)
 {
 	int order;
 	int min_objects;
@@ -2034,14 +2278,14 @@ static inline int calculate_order(int size)
 	min_objects = slub_min_objects;
 	if (!min_objects)
 		min_objects = 4 * (fls(nr_cpu_ids) + 1);
-	max_objects = (PAGE_SIZE << slub_max_order)/size;
+	max_objects = order_objects(slub_max_order, size, reserved);
 	min_objects = min(min_objects, max_objects);
 
 	while (min_objects > 1) {
 		fraction = 16;
 		while (fraction >= 4) {
 			order = slab_order(size, min_objects,
-						slub_max_order, fraction);
+					slub_max_order, fraction, reserved);
 			if (order <= slub_max_order)
 				return order;
 			fraction /= 2;
@@ -2053,14 +2297,14 @@ static inline int calculate_order(int size)
 	 * We were unable to place multiple objects in a slab. Now
 	 * lets see if we can place a single object there.
 	 */
-	order = slab_order(size, 1, slub_max_order, 1);
+	order = slab_order(size, 1, slub_max_order, 1, reserved);
 	if (order <= slub_max_order)
 		return order;
 
 	/*
 	 * Doh this slab cannot be placed using slub_max_order.
 	 */
-	order = slab_order(size, 1, MAX_ORDER, 1);
+	order = slab_order(size, 1, MAX_ORDER, 1, reserved);
 	if (order < MAX_ORDER)
 		return order;
 	return -ENOSYS;
@@ -2110,9 +2354,23 @@ 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));
 
+#ifdef CONFIG_CMPXCHG_LOCAL
+	/*
+	 * Must align to double word boundary for the double cmpxchg instructions
+	 * to work.
+	 */
+	s->cpu_slab = __alloc_percpu(sizeof(struct kmem_cache_cpu), 2 * sizeof(void *));
+#else
+	/* Regular alignment is sufficient */
 	s->cpu_slab = alloc_percpu(struct kmem_cache_cpu);
+#endif
+
+	if (!s->cpu_slab)
+		return 0;
 
-	return s->cpu_slab != NULL;
+	init_kmem_cache_cpus(s);
+
+	return 1;
 }
 
 static struct kmem_cache *kmem_cache_node;
@@ -2311,7 +2569,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
 	if (forced_order >= 0)
 		order = forced_order;
 	else
-		order = calculate_order(size);
+		order = calculate_order(size, s->reserved);
 
 	if (order < 0)
 		return 0;
@@ -2329,8 +2587,8 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
 	/*
 	 * Determine the number of objects per slab
 	 */
-	s->oo = oo_make(order, size);
-	s->min = oo_make(get_order(size), size);
+	s->oo = oo_make(order, size, s->reserved);
+	s->min = oo_make(get_order(size), size, s->reserved);
 	if (oo_objects(s->oo) > oo_objects(s->max))
 		s->max = s->oo;
 
@@ -2349,6 +2607,10 @@ static int kmem_cache_open(struct kmem_cache *s,
 	s->objsize = size;
 	s->align = align;
 	s->flags = kmem_cache_flags(size, flags, name, ctor);
+	s->reserved = 0;
+
+	if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU))
+		s->reserved = sizeof(struct rcu_head);
 
 	if (!calculate_sizes(s, -1))
 		goto error;
@@ -2399,12 +2661,6 @@ unsigned int kmem_cache_size(struct kmem_cache *s)
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
-const char *kmem_cache_name(struct kmem_cache *s)
-{
-	return s->name;
-}
-EXPORT_SYMBOL(kmem_cache_name);
-
 static void list_slab_objects(struct kmem_cache *s, struct page *page,
 							const char *text)
 {
@@ -2696,7 +2952,6 @@ EXPORT_SYMBOL(__kmalloc_node);
 size_t ksize(const void *object)
 {
 	struct page *page;
-	struct kmem_cache *s;
 
 	if (unlikely(object == ZERO_SIZE_PTR))
 		return 0;
@@ -2707,28 +2962,8 @@ size_t ksize(const void *object)
 		WARN_ON(!PageCompound(page));
 		return PAGE_SIZE << compound_order(page);
 	}
-	s = page->slab;
-
-#ifdef CONFIG_SLUB_DEBUG
-	/*
-	 * Debugging requires use of the padding between object
-	 * and whatever may come after it.
-	 */
-	if (s->flags & (SLAB_RED_ZONE | SLAB_POISON))
-		return s->objsize;
 
-#endif
-	/*
-	 * If we have the need to store the freelist pointer
-	 * back there or track user information then we can
-	 * only use the space before that information.
-	 */
-	if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
-		return s->inuse;
-	/*
-	 * Else we can use all the padding etc for the allocation
-	 */
-	return s->size;
+	return slab_ksize(page->slab);
 }
 EXPORT_SYMBOL(ksize);
 
@@ -4017,6 +4252,12 @@ static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
 }
 SLAB_ATTR_RO(destroy_by_rcu);
 
+static ssize_t reserved_show(struct kmem_cache *s, char *buf)
+{
+	return sprintf(buf, "%d\n", s->reserved);
+}
+SLAB_ATTR_RO(reserved);
+
 #ifdef CONFIG_SLUB_DEBUG
 static ssize_t slabs_show(struct kmem_cache *s, char *buf)
 {
@@ -4303,6 +4544,7 @@ static struct attribute *slab_attrs[] = {
 	&reclaim_account_attr.attr,
 	&destroy_by_rcu_attr.attr,
 	&shrink_attr.attr,
+	&reserved_attr.attr,
 #ifdef CONFIG_SLUB_DEBUG
 	&total_objects_attr.attr,
 	&slabs_attr.attr,
diff --git a/mm/swap.c b/mm/swap.c
index c02f936..a448db3 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -39,6 +39,7 @@ int page_cluster;
 
 static DEFINE_PER_CPU(struct pagevec[NR_LRU_LISTS], lru_add_pvecs);
 static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs);
+static DEFINE_PER_CPU(struct pagevec, lru_deactivate_pvecs);
 
 /*
  * This path almost never happens for VM activity - pages are normally
@@ -178,15 +179,13 @@ void put_pages_list(struct list_head *pages)
 }
 EXPORT_SYMBOL(put_pages_list);
 
-/*
- * pagevec_move_tail() must be called with IRQ disabled.
- * Otherwise this may cause nasty races.
- */
-static void pagevec_move_tail(struct pagevec *pvec)
+static void pagevec_lru_move_fn(struct pagevec *pvec,
+				void (*move_fn)(struct page *page, void *arg),
+				void *arg)
 {
 	int i;
-	int pgmoved = 0;
 	struct zone *zone = NULL;
+	unsigned long flags = 0;
 
 	for (i = 0; i < pagevec_count(pvec); i++) {
 		struct page *page = pvec->pages[i];
@@ -194,29 +193,50 @@ static void pagevec_move_tail(struct pagevec *pvec)
 
 		if (pagezone != zone) {
 			if (zone)
-				spin_unlock(&zone->lru_lock);
+				spin_unlock_irqrestore(&zone->lru_lock, flags);
 			zone = pagezone;
-			spin_lock(&zone->lru_lock);
-		}
-		if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
-			int lru = page_lru_base_type(page);
-			list_move_tail(&page->lru, &zone->lru[lru].list);
-			pgmoved++;
+			spin_lock_irqsave(&zone->lru_lock, flags);
 		}
+
+		(*move_fn)(page, arg);
 	}
 	if (zone)
-		spin_unlock(&zone->lru_lock);
-	__count_vm_events(PGROTATED, pgmoved);
+		spin_unlock_irqrestore(&zone->lru_lock, flags);
 	release_pages(pvec->pages, pvec->nr, pvec->cold);
 	pagevec_reinit(pvec);
 }
 
+static void pagevec_move_tail_fn(struct page *page, void *arg)
+{
+	int *pgmoved = arg;
+	struct zone *zone = page_zone(page);
+
+	if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
+		enum lru_list lru = page_lru_base_type(page);
+		list_move_tail(&page->lru, &zone->lru[lru].list);
+		mem_cgroup_rotate_reclaimable_page(page);
+		(*pgmoved)++;
+	}
+}
+
+/*
+ * pagevec_move_tail() must be called with IRQ disabled.
+ * Otherwise this may cause nasty races.
+ */
+static void pagevec_move_tail(struct pagevec *pvec)
+{
+	int pgmoved = 0;
+
+	pagevec_lru_move_fn(pvec, pagevec_move_tail_fn, &pgmoved);
+	__count_vm_events(PGROTATED, pgmoved);
+}
+
 /*
  * Writeback is about to end against a page which has been marked for immediate
  * reclaim.  If it still appears to be reclaimable, move it to the tail of the
  * inactive list.
  */
-void  rotate_reclaimable_page(struct page *page)
+void rotate_reclaimable_page(struct page *page)
 {
 	if (!PageLocked(page) && !PageDirty(page) && !PageActive(page) &&
 	    !PageUnevictable(page) && PageLRU(page)) {
@@ -347,6 +367,71 @@ void add_page_to_unevictable_list(struct page *page)
 }
 
 /*
+ * If the page can not be invalidated, it is moved to the
+ * inactive list to speed up its reclaim.  It is moved to the
+ * head of the list, rather than the tail, to give the flusher
+ * threads some time to write it out, as this is much more
+ * effective than the single-page writeout from reclaim.
+ *
+ * If the page isn't page_mapped and dirty/writeback, the page
+ * could reclaim asap using PG_reclaim.
+ *
+ * 1. active, mapped page -> none
+ * 2. active, dirty/writeback page -> inactive, head, PG_reclaim
+ * 3. inactive, mapped page -> none
+ * 4. inactive, dirty/writeback page -> inactive, head, PG_reclaim
+ * 5. inactive, clean -> inactive, tail
+ * 6. Others -> none
+ *
+ * In 4, why it moves inactive's head, the VM expects the page would
+ * be write it out by flusher threads as this is much more effective
+ * than the single-page writeout from reclaim.
+ */
+static void lru_deactivate_fn(struct page *page, void *arg)
+{
+	int lru, file;
+	bool active;
+	struct zone *zone = page_zone(page);
+
+	if (!PageLRU(page))
+		return;
+
+	/* Some processes are using the page */
+	if (page_mapped(page))
+		return;
+
+	active = PageActive(page);
+
+	file = page_is_file_cache(page);
+	lru = page_lru_base_type(page);
+	del_page_from_lru_list(zone, page, lru + active);
+	ClearPageActive(page);
+	ClearPageReferenced(page);
+	add_page_to_lru_list(zone, page, lru);
+
+	if (PageWriteback(page) || PageDirty(page)) {
+		/*
+		 * PG_reclaim could be raced with end_page_writeback
+		 * It can make readahead confusing.  But race window
+		 * is _really_ small and  it's non-critical problem.
+		 */
+		SetPageReclaim(page);
+	} else {
+		/*
+		 * The page's writeback ends up during pagevec
+		 * We moves tha page into tail of inactive.
+		 */
+		list_move_tail(&page->lru, &zone->lru[lru].list);
+		mem_cgroup_rotate_reclaimable_page(page);
+		__count_vm_event(PGROTATED);
+	}
+
+	if (active)
+		__count_vm_event(PGDEACTIVATE);
+	update_page_reclaim_stat(zone, page, file, 0);
+}
+
+/*
  * Drain pages out of the cpu's pagevecs.
  * Either "cpu" is the current CPU, and preemption has already been
  * disabled; or "cpu" is being hot-unplugged, and is already dead.
@@ -372,6 +457,29 @@ static void drain_cpu_pagevecs(int cpu)
 		pagevec_move_tail(pvec);
 		local_irq_restore(flags);
 	}
+
+	pvec = &per_cpu(lru_deactivate_pvecs, cpu);
+	if (pagevec_count(pvec))
+		pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL);
+}
+
+/**
+ * deactivate_page - forcefully deactivate a page
+ * @page: page to deactivate
+ *
+ * This function hints the VM that @page is a good reclaim candidate,
+ * for example if its invalidation fails due to the page being dirty
+ * or under writeback.
+ */
+void deactivate_page(struct page *page)
+{
+	if (likely(get_page_unless_zero(page))) {
+		struct pagevec *pvec = &get_cpu_var(lru_deactivate_pvecs);
+
+		if (!pagevec_add(pvec, page))
+			pagevec_lru_move_fn(pvec, lru_deactivate_fn, NULL);
+		put_cpu_var(lru_deactivate_pvecs);
+	}
 }
 
 void lru_add_drain(void)
@@ -516,44 +624,33 @@ void lru_add_page_tail(struct zone* zone,
 	}
 }
 
+static void ____pagevec_lru_add_fn(struct page *page, void *arg)
+{
+	enum lru_list lru = (enum lru_list)arg;
+	struct zone *zone = page_zone(page);
+	int file = is_file_lru(lru);
+	int active = is_active_lru(lru);
+
+	VM_BUG_ON(PageActive(page));
+	VM_BUG_ON(PageUnevictable(page));
+	VM_BUG_ON(PageLRU(page));
+
+	SetPageLRU(page);
+	if (active)
+		SetPageActive(page);
+	update_page_reclaim_stat(zone, page, file, active);
+	add_page_to_lru_list(zone, page, lru);
+}
+
 /*
  * Add the passed pages to the LRU, then drop the caller's refcount
  * on them.  Reinitialises the caller's pagevec.
  */
 void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru)
 {
-	int i;
-	struct zone *zone = NULL;
-
 	VM_BUG_ON(is_unevictable_lru(lru));
 
-	for (i = 0; i < pagevec_count(pvec); i++) {
-		struct page *page = pvec->pages[i];
-		struct zone *pagezone = page_zone(page);
-		int file;
-		int active;
-
-		if (pagezone != zone) {
-			if (zone)
-				spin_unlock_irq(&zone->lru_lock);
-			zone = pagezone;
-			spin_lock_irq(&zone->lru_lock);
-		}
-		VM_BUG_ON(PageActive(page));
-		VM_BUG_ON(PageUnevictable(page));
-		VM_BUG_ON(PageLRU(page));
-		SetPageLRU(page);
-		active = is_active_lru(lru);
-		file = is_file_lru(lru);
-		if (active)
-			SetPageActive(page);
-		update_page_reclaim_stat(zone, page, file, active);
-		add_page_to_lru_list(zone, page, lru);
-	}
-	if (zone)
-		spin_unlock_irq(&zone->lru_lock);
-	release_pages(pvec->pages, pvec->nr, pvec->cold);
-	pagevec_reinit(pvec);
+	pagevec_lru_move_fn(pvec, ____pagevec_lru_add_fn, (void *)lru);
 }
 
 EXPORT_SYMBOL(____pagevec_lru_add);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 0341c57..71b42ec 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -212,8 +212,8 @@ static int wait_for_discard(void *word)
 #define SWAPFILE_CLUSTER	256
 #define LATENCY_LIMIT		256
 
-static inline unsigned long scan_swap_map(struct swap_info_struct *si,
-					  unsigned char usage)
+static unsigned long scan_swap_map(struct swap_info_struct *si,
+				   unsigned char usage)
 {
 	unsigned long offset;
 	unsigned long scan_base;
@@ -1550,6 +1550,36 @@ bad_bmap:
 	goto out;
 }
 
+static void enable_swap_info(struct swap_info_struct *p, int prio,
+				unsigned char *swap_map)
+{
+	int i, prev;
+
+	spin_lock(&swap_lock);
+	if (prio >= 0)
+		p->prio = prio;
+	else
+		p->prio = --least_priority;
+	p->swap_map = swap_map;
+	p->flags |= SWP_WRITEOK;
+	nr_swap_pages += p->pages;
+	total_swap_pages += p->pages;
+
+	/* insert swap space into swap_list: */
+	prev = -1;
+	for (i = swap_list.head; i >= 0; i = swap_info[i]->next) {
+		if (p->prio >= swap_info[i]->prio)
+			break;
+		prev = i;
+	}
+	p->next = i;
+	if (prev < 0)
+		swap_list.head = swap_list.next = p->type;
+	else
+		swap_info[prev]->next = p->type;
+	spin_unlock(&swap_lock);
+}
+
 SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 {
 	struct swap_info_struct *p = NULL;
@@ -1621,25 +1651,14 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 	current->flags &= ~PF_OOM_ORIGIN;
 
 	if (err) {
+		/*
+		 * reading p->prio and p->swap_map outside the lock is
+		 * safe here because only sys_swapon and sys_swapoff
+		 * change them, and there can be no other sys_swapon or
+		 * sys_swapoff for this swap_info_struct at this point.
+		 */
 		/* re-insert swap space back into swap_list */
-		spin_lock(&swap_lock);
-		if (p->prio < 0)
-			p->prio = --least_priority;
-		prev = -1;
-		for (i = swap_list.head; i >= 0; i = swap_info[i]->next) {
-			if (p->prio >= swap_info[i]->prio)
-				break;
-			prev = i;
-		}
-		p->next = i;
-		if (prev < 0)
-			swap_list.head = swap_list.next = type;
-		else
-			swap_info[prev]->next = type;
-		nr_swap_pages += p->pages;
-		total_swap_pages += p->pages;
-		p->flags |= SWP_WRITEOK;
-		spin_unlock(&swap_lock);
+		enable_swap_info(p, p->prio, p->swap_map);
 		goto out_dput;
 	}
 
@@ -1844,49 +1863,24 @@ static int __init max_swapfiles_check(void)
 late_initcall(max_swapfiles_check);
 #endif
 
-/*
- * Written 01/25/92 by Simmule Turner, heavily changed by Linus.
- *
- * The swapon system call
- */
-SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
+static struct swap_info_struct *alloc_swap_info(void)
 {
 	struct swap_info_struct *p;
-	char *name = NULL;
-	struct block_device *bdev = NULL;
-	struct file *swap_file = NULL;
-	struct address_space *mapping;
 	unsigned int type;
-	int i, prev;
-	int error;
-	union swap_header *swap_header;
-	unsigned int nr_good_pages;
-	int nr_extents = 0;
-	sector_t span;
-	unsigned long maxpages;
-	unsigned long swapfilepages;
-	unsigned char *swap_map = NULL;
-	struct page *page = NULL;
-	struct inode *inode = NULL;
-	int did_down = 0;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 
 	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (!p)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
 	spin_lock(&swap_lock);
 	for (type = 0; type < nr_swapfiles; type++) {
 		if (!(swap_info[type]->flags & SWP_USED))
 			break;
 	}
-	error = -EPERM;
 	if (type >= MAX_SWAPFILES) {
 		spin_unlock(&swap_lock);
 		kfree(p);
-		goto out;
+		return ERR_PTR(-EPERM);
 	}
 	if (type >= nr_swapfiles) {
 		p->type = type;
@@ -1911,81 +1905,49 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	p->next = -1;
 	spin_unlock(&swap_lock);
 
-	name = getname(specialfile);
-	error = PTR_ERR(name);
-	if (IS_ERR(name)) {
-		name = NULL;
-		goto bad_swap_2;
-	}
-	swap_file = filp_open(name, O_RDWR|O_LARGEFILE, 0);
-	error = PTR_ERR(swap_file);
-	if (IS_ERR(swap_file)) {
-		swap_file = NULL;
-		goto bad_swap_2;
-	}
-
-	p->swap_file = swap_file;
-	mapping = swap_file->f_mapping;
-	inode = mapping->host;
-
-	error = -EBUSY;
-	for (i = 0; i < nr_swapfiles; i++) {
-		struct swap_info_struct *q = swap_info[i];
+	return p;
+}
 
-		if (i == type || !q->swap_file)
-			continue;
-		if (mapping == q->swap_file->f_mapping)
-			goto bad_swap;
-	}
+static int claim_swapfile(struct swap_info_struct *p, struct inode *inode)
+{
+	int error;
 
-	error = -EINVAL;
 	if (S_ISBLK(inode->i_mode)) {
-		bdev = bdgrab(I_BDEV(inode));
-		error = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL,
+		p->bdev = bdgrab(I_BDEV(inode));
+		error = blkdev_get(p->bdev,
+				   FMODE_READ | FMODE_WRITE | FMODE_EXCL,
 				   sys_swapon);
 		if (error < 0) {
-			bdev = NULL;
-			error = -EINVAL;
-			goto bad_swap;
+			p->bdev = NULL;
+			return -EINVAL;
 		}
-		p->old_block_size = block_size(bdev);
-		error = set_blocksize(bdev, PAGE_SIZE);
+		p->old_block_size = block_size(p->bdev);
+		error = set_blocksize(p->bdev, PAGE_SIZE);
 		if (error < 0)
-			goto bad_swap;
-		p->bdev = bdev;
+			return error;
 		p->flags |= SWP_BLKDEV;
 	} else if (S_ISREG(inode->i_mode)) {
 		p->bdev = inode->i_sb->s_bdev;
 		mutex_lock(&inode->i_mutex);
-		did_down = 1;
-		if (IS_SWAPFILE(inode)) {
-			error = -EBUSY;
-			goto bad_swap;
-		}
-	} else {
-		goto bad_swap;
-	}
+		if (IS_SWAPFILE(inode))
+			return -EBUSY;
+	} else
+		return -EINVAL;
 
-	swapfilepages = i_size_read(inode) >> PAGE_SHIFT;
+	return 0;
+}
 
-	/*
-	 * Read the swap header.
-	 */
-	if (!mapping->a_ops->readpage) {
-		error = -EINVAL;
-		goto bad_swap;
-	}
-	page = read_mapping_page(mapping, 0, swap_file);
-	if (IS_ERR(page)) {
-		error = PTR_ERR(page);
-		goto bad_swap;
-	}
-	swap_header = kmap(page);
+static unsigned long read_swap_header(struct swap_info_struct *p,
+					union swap_header *swap_header,
+					struct inode *inode)
+{
+	int i;
+	unsigned long maxpages;
+	unsigned long swapfilepages;
 
 	if (memcmp("SWAPSPACE2", swap_header->magic.magic, 10)) {
 		printk(KERN_ERR "Unable to find swap-space signature\n");
-		error = -EINVAL;
-		goto bad_swap;
+		return 0;
 	}
 
 	/* swap partition endianess hack... */
@@ -2001,8 +1963,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 		printk(KERN_WARNING
 		       "Unable to handle swap header version %d\n",
 		       swap_header->info.version);
-		error = -EINVAL;
-		goto bad_swap;
+		return 0;
 	}
 
 	p->lowest_bit  = 1;
@@ -2033,61 +1994,155 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	}
 	p->highest_bit = maxpages - 1;
 
-	error = -EINVAL;
 	if (!maxpages)
-		goto bad_swap;
+		return 0;
+	swapfilepages = i_size_read(inode) >> PAGE_SHIFT;
 	if (swapfilepages && maxpages > swapfilepages) {
 		printk(KERN_WARNING
 		       "Swap area shorter than signature indicates\n");
-		goto bad_swap;
+		return 0;
 	}
 	if (swap_header->info.nr_badpages && S_ISREG(inode->i_mode))
-		goto bad_swap;
+		return 0;
 	if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)
-		goto bad_swap;
+		return 0;
 
-	/* OK, set up the swap map and apply the bad block list */
-	swap_map = vmalloc(maxpages);
-	if (!swap_map) {
-		error = -ENOMEM;
-		goto bad_swap;
-	}
+	return maxpages;
+}
+
+static int setup_swap_map_and_extents(struct swap_info_struct *p,
+					union swap_header *swap_header,
+					unsigned char *swap_map,
+					unsigned long maxpages,
+					sector_t *span)
+{
+	int i;
+	unsigned int nr_good_pages;
+	int nr_extents;
 
-	memset(swap_map, 0, maxpages);
 	nr_good_pages = maxpages - 1;	/* omit header page */
 
 	for (i = 0; i < swap_header->info.nr_badpages; i++) {
 		unsigned int page_nr = swap_header->info.badpages[i];
-		if (page_nr == 0 || page_nr > swap_header->info.last_page) {
-			error = -EINVAL;
-			goto bad_swap;
-		}
+		if (page_nr == 0 || page_nr > swap_header->info.last_page)
+			return -EINVAL;
 		if (page_nr < maxpages) {
 			swap_map[page_nr] = SWAP_MAP_BAD;
 			nr_good_pages--;
 		}
 	}
 
-	error = swap_cgroup_swapon(type, maxpages);
-	if (error)
-		goto bad_swap;
-
 	if (nr_good_pages) {
 		swap_map[0] = SWAP_MAP_BAD;
 		p->max = maxpages;
 		p->pages = nr_good_pages;
-		nr_extents = setup_swap_extents(p, &span);
-		if (nr_extents < 0) {
-			error = nr_extents;
-			goto bad_swap;
-		}
+		nr_extents = setup_swap_extents(p, span);
+		if (nr_extents < 0)
+			return nr_extents;
 		nr_good_pages = p->pages;
 	}
 	if (!nr_good_pages) {
 		printk(KERN_WARNING "Empty swap-file\n");
+		return -EINVAL;
+	}
+
+	return nr_extents;
+}
+
+SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
+{
+	struct swap_info_struct *p;
+	char *name;
+	struct file *swap_file = NULL;
+	struct address_space *mapping;
+	int i;
+	int prio;
+	int error;
+	union swap_header *swap_header;
+	int nr_extents;
+	sector_t span;
+	unsigned long maxpages;
+	unsigned char *swap_map = NULL;
+	struct page *page = NULL;
+	struct inode *inode = NULL;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	p = alloc_swap_info();
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	name = getname(specialfile);
+	if (IS_ERR(name)) {
+		error = PTR_ERR(name);
+		name = NULL;
+		goto bad_swap;
+	}
+	swap_file = filp_open(name, O_RDWR|O_LARGEFILE, 0);
+	if (IS_ERR(swap_file)) {
+		error = PTR_ERR(swap_file);
+		swap_file = NULL;
+		goto bad_swap;
+	}
+
+	p->swap_file = swap_file;
+	mapping = swap_file->f_mapping;
+
+	for (i = 0; i < nr_swapfiles; i++) {
+		struct swap_info_struct *q = swap_info[i];
+
+		if (q == p || !q->swap_file)
+			continue;
+		if (mapping == q->swap_file->f_mapping) {
+			error = -EBUSY;
+			goto bad_swap;
+		}
+	}
+
+	inode = mapping->host;
+	/* If S_ISREG(inode->i_mode) will do mutex_lock(&inode->i_mutex); */
+	error = claim_swapfile(p, inode);
+	if (unlikely(error))
+		goto bad_swap;
+
+	/*
+	 * Read the swap header.
+	 */
+	if (!mapping->a_ops->readpage) {
 		error = -EINVAL;
 		goto bad_swap;
 	}
+	page = read_mapping_page(mapping, 0, swap_file);
+	if (IS_ERR(page)) {
+		error = PTR_ERR(page);
+		goto bad_swap;
+	}
+	swap_header = kmap(page);
+
+	maxpages = read_swap_header(p, swap_header, inode);
+	if (unlikely(!maxpages)) {
+		error = -EINVAL;
+		goto bad_swap;
+	}
+
+	/* OK, set up the swap map and apply the bad block list */
+	swap_map = vzalloc(maxpages);
+	if (!swap_map) {
+		error = -ENOMEM;
+		goto bad_swap;
+	}
+
+	error = swap_cgroup_swapon(p->type, maxpages);
+	if (error)
+		goto bad_swap;
+
+	nr_extents = setup_swap_map_and_extents(p, swap_header, swap_map,
+		maxpages, &span);
+	if (unlikely(nr_extents < 0)) {
+		error = nr_extents;
+		goto bad_swap;
+	}
 
 	if (p->bdev) {
 		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
@@ -2099,58 +2154,46 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 	}
 
 	mutex_lock(&swapon_mutex);
-	spin_lock(&swap_lock);
+	prio = -1;
 	if (swap_flags & SWAP_FLAG_PREFER)
-		p->prio =
+		prio =
 		  (swap_flags & SWAP_FLAG_PRIO_MASK) >> SWAP_FLAG_PRIO_SHIFT;
-	else
-		p->prio = --least_priority;
-	p->swap_map = swap_map;
-	p->flags |= SWP_WRITEOK;
-	nr_swap_pages += nr_good_pages;
-	total_swap_pages += nr_good_pages;
+	enable_swap_info(p, prio, swap_map);
 
 	printk(KERN_INFO "Adding %uk swap on %s.  "
 			"Priority:%d extents:%d across:%lluk %s%s\n",
-		nr_good_pages<<(PAGE_SHIFT-10), name, p->prio,
+		p->pages<<(PAGE_SHIFT-10), name, p->prio,
 		nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
 		(p->flags & SWP_SOLIDSTATE) ? "SS" : "",
 		(p->flags & SWP_DISCARDABLE) ? "D" : "");
 
-	/* insert swap space into swap_list: */
-	prev = -1;
-	for (i = swap_list.head; i >= 0; i = swap_info[i]->next) {
-		if (p->prio >= swap_info[i]->prio)
-			break;
-		prev = i;
-	}
-	p->next = i;
-	if (prev < 0)
-		swap_list.head = swap_list.next = type;
-	else
-		swap_info[prev]->next = type;
-	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
 	atomic_inc(&proc_poll_event);
 	wake_up_interruptible(&proc_poll_wait);
 
+	if (S_ISREG(inode->i_mode))
+		inode->i_flags |= S_SWAPFILE;
 	error = 0;
 	goto out;
 bad_swap:
-	if (bdev) {
-		set_blocksize(bdev, p->old_block_size);
-		blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
+	if (inode && S_ISBLK(inode->i_mode) && p->bdev) {
+		set_blocksize(p->bdev, p->old_block_size);
+		blkdev_put(p->bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL);
 	}
 	destroy_swap_extents(p);
-	swap_cgroup_swapoff(type);
-bad_swap_2:
+	swap_cgroup_swapoff(p->type);
 	spin_lock(&swap_lock);
 	p->swap_file = NULL;
 	p->flags = 0;
 	spin_unlock(&swap_lock);
 	vfree(swap_map);
-	if (swap_file)
+	if (swap_file) {
+		if (inode && S_ISREG(inode->i_mode)) {
+			mutex_unlock(&inode->i_mutex);
+			inode = NULL;
+		}
 		filp_close(swap_file, NULL);
+	}
 out:
 	if (page && !IS_ERR(page)) {
 		kunmap(page);
@@ -2158,11 +2201,8 @@ out:
 	}
 	if (name)
 		putname(name);
-	if (did_down) {
-		if (!error)
-			inode->i_flags |= S_SWAPFILE;
+	if (inode && S_ISREG(inode->i_mode))
 		mutex_unlock(&inode->i_mutex);
-	}
 	return error;
 }
 
diff --git a/mm/truncate.c b/mm/truncate.c
index d64296b..a956675 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -106,9 +106,8 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
 	cancel_dirty_page(page, PAGE_CACHE_SIZE);
 
 	clear_page_mlock(page);
-	remove_from_page_cache(page);
 	ClearPageMappedToDisk(page);
-	page_cache_release(page);	/* pagecache ref */
+	delete_from_page_cache(page);
 	return 0;
 }
 
@@ -322,11 +321,12 @@ EXPORT_SYMBOL(truncate_inode_pages);
  * pagetables.
  */
 unsigned long invalidate_mapping_pages(struct address_space *mapping,
-				       pgoff_t start, pgoff_t end)
+		pgoff_t start, pgoff_t end)
 {
 	struct pagevec pvec;
 	pgoff_t next = start;
-	unsigned long ret = 0;
+	unsigned long ret;
+	unsigned long count = 0;
 	int i;
 
 	pagevec_init(&pvec, 0);
@@ -353,9 +353,15 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
 			if (lock_failed)
 				continue;
 
-			ret += invalidate_inode_page(page);
-
+			ret = invalidate_inode_page(page);
 			unlock_page(page);
+			/*
+			 * Invalidation is a hint that the page is no longer
+			 * of interest and try to speed up its reclaim.
+			 */
+			if (!ret)
+				deactivate_page(page);
+			count += ret;
 			if (next > end)
 				break;
 		}
@@ -363,7 +369,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
 		mem_cgroup_uncharge_end();
 		cond_resched();
 	}
-	return ret;
+	return count;
 }
 EXPORT_SYMBOL(invalidate_mapping_pages);
 
@@ -389,7 +395,7 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
 
 	clear_page_mlock(page);
 	BUG_ON(page_has_private(page));
-	__remove_from_page_cache(page);
+	__delete_from_page_cache(page);
 	spin_unlock_irq(&mapping->tree_lock);
 	mem_cgroup_uncharge_cache_page(page);
 
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f9b1667..5d60302 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -261,8 +261,15 @@ struct vmap_area {
 };
 
 static DEFINE_SPINLOCK(vmap_area_lock);
-static struct rb_root vmap_area_root = RB_ROOT;
 static LIST_HEAD(vmap_area_list);
+static struct rb_root vmap_area_root = RB_ROOT;
+
+/* The vmap cache globals are protected by vmap_area_lock */
+static struct rb_node *free_vmap_cache;
+static unsigned long cached_hole_size;
+static unsigned long cached_vstart;
+static unsigned long cached_align;
+
 static unsigned long vmap_area_pcpu_hole;
 
 static struct vmap_area *__find_vmap_area(unsigned long addr)
@@ -331,9 +338,11 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 	struct rb_node *n;
 	unsigned long addr;
 	int purged = 0;
+	struct vmap_area *first;
 
 	BUG_ON(!size);
 	BUG_ON(size & ~PAGE_MASK);
+	BUG_ON(!is_power_of_2(align));
 
 	va = kmalloc_node(sizeof(struct vmap_area),
 			gfp_mask & GFP_RECLAIM_MASK, node);
@@ -341,79 +350,106 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
 		return ERR_PTR(-ENOMEM);
 
 retry:
-	addr = ALIGN(vstart, align);
-
 	spin_lock(&vmap_area_lock);
-	if (addr + size - 1 < addr)
-		goto overflow;
+	/*
+	 * Invalidate cache if we have more permissive parameters.
+	 * cached_hole_size notes the largest hole noticed _below_
+	 * the vmap_area cached in free_vmap_cache: if size fits
+	 * into that hole, we want to scan from vstart to reuse
+	 * the hole instead of allocating above free_vmap_cache.
+	 * Note that __free_vmap_area may update free_vmap_cache
+	 * without updating cached_hole_size or cached_align.
+	 */
+	if (!free_vmap_cache ||
+			size < cached_hole_size ||
+			vstart < cached_vstart ||
+			align < cached_align) {
+nocache:
+		cached_hole_size = 0;
+		free_vmap_cache = NULL;
+	}
+	/* record if we encounter less permissive parameters */
+	cached_vstart = vstart;
+	cached_align = align;
+
+	/* find starting point for our search */
+	if (free_vmap_cache) {
+		first = rb_entry(free_vmap_cache, struct vmap_area, rb_node);
+		addr = ALIGN(first->va_end + PAGE_SIZE, align);
+		if (addr < vstart)
+			goto nocache;
+		if (addr + size - 1 < addr)
+			goto overflow;
+
+	} else {
+		addr = ALIGN(vstart, align);
+		if (addr + size - 1 < addr)
+			goto overflow;
 
-	/* XXX: could have a last_hole cache */
-	n = vmap_area_root.rb_node;
-	if (n) {
-		struct vmap_area *first = NULL;
+		n = vmap_area_root.rb_node;
+		first = NULL;
 
-		do {
+		while (n) {
 			struct vmap_area *tmp;
 			tmp = rb_entry(n, struct vmap_area, rb_node);
 			if (tmp->va_end >= addr) {
-				if (!first && tmp->va_start < addr + size)
-					first = tmp;
-				n = n->rb_left;
-			} else {
 				first = tmp;
+				if (tmp->va_start <= addr)
+					break;
+				n = n->rb_left;
+			} else
 				n = n->rb_right;
-			}
-		} while (n);
+		}
 
 		if (!first)
 			goto found;
-
-		if (first->va_end < addr) {
-			n = rb_next(&first->rb_node);
-			if (n)
-				first = rb_entry(n, struct vmap_area, rb_node);
-			else
-				goto found;
-		}
-
-		while (addr + size > first->va_start && addr + size <= vend) {
-			addr = ALIGN(first->va_end + PAGE_SIZE, align);
-			if (addr + size - 1 < addr)
-				goto overflow;
-
-			n = rb_next(&first->rb_node);
-			if (n)
-				first = rb_entry(n, struct vmap_area, rb_node);
-			else
-				goto found;
-		}
 	}
-found:
-	if (addr + size > vend) {
-overflow:
-		spin_unlock(&vmap_area_lock);
-		if (!purged) {
-			purge_vmap_area_lazy();
-			purged = 1;
-			goto retry;
-		}
-		if (printk_ratelimit())
-			printk(KERN_WARNING
-				"vmap allocation for size %lu failed: "
-				"use vmalloc=<size> to increase size.\n", size);
-		kfree(va);
-		return ERR_PTR(-EBUSY);
+
+	/* from the starting point, walk areas until a suitable hole is found */
+	while (addr + size >= first->va_start && addr + size <= vend) {
+		if (addr + cached_hole_size < first->va_start)
+			cached_hole_size = first->va_start - addr;
+		addr = ALIGN(first->va_end + PAGE_SIZE, align);
+		if (addr + size - 1 < addr)
+			goto overflow;
+
+		n = rb_next(&first->rb_node);
+		if (n)
+			first = rb_entry(n, struct vmap_area, rb_node);
+		else
+			goto found;
 	}
 
-	BUG_ON(addr & (align-1));
+found:
+	if (addr + size > vend)
+		goto overflow;
 
 	va->va_start = addr;
 	va->va_end = addr + size;
 	va->flags = 0;
 	__insert_vmap_area(va);
+	free_vmap_cache = &va->rb_node;
 	spin_unlock(&vmap_area_lock);
 
+	BUG_ON(va->va_start & (align-1));
+	BUG_ON(va->va_start < vstart);
+	BUG_ON(va->va_end > vend);
+
 	return va;
+
+overflow:
+	spin_unlock(&vmap_area_lock);
+	if (!purged) {
+		purge_vmap_area_lazy();
+		purged = 1;
+		goto retry;
+	}
+	if (printk_ratelimit())
+		printk(KERN_WARNING
+			"vmap allocation for size %lu failed: "
+			"use vmalloc=<size> to increase size.\n", size);
+	kfree(va);
+	return ERR_PTR(-EBUSY);
 }
 
 static void rcu_free_va(struct rcu_head *head)
@@ -426,6 +462,22 @@ static void rcu_free_va(struct rcu_head *head)
 static void __free_vmap_area(struct vmap_area *va)
 {
 	BUG_ON(RB_EMPTY_NODE(&va->rb_node));
+
+	if (free_vmap_cache) {
+		if (va->va_end < cached_vstart) {
+			free_vmap_cache = NULL;
+		} else {
+			struct vmap_area *cache;
+			cache = rb_entry(free_vmap_cache, struct vmap_area, rb_node);
+			if (va->va_start <= cache->va_start) {
+				free_vmap_cache = rb_prev(&va->rb_node);
+				/*
+				 * We don't try to update cached_hole_size or
+				 * cached_align, but it won't go very wrong.
+				 */
+			}
+		}
+	}
 	rb_erase(&va->rb_node, &vmap_area_root);
 	RB_CLEAR_NODE(&va->rb_node);
 	list_del_rcu(&va->list);
@@ -1951,8 +2003,6 @@ finished:
  *	should know vmalloc() area is valid and can use memcpy().
  *	This is for routines which have to access vmalloc area without
  *	any informaion, as /dev/kmem.
- *
- *	The caller should guarantee KM_USER1 is not used.
  */
 
 long vwrite(char *buf, char *addr, unsigned long count)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 6771ea7..060e4c1 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -514,7 +514,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page)
 
 		freepage = mapping->a_ops->freepage;
 
-		__remove_from_page_cache(page);
+		__delete_from_page_cache(page);
 		spin_unlock_irq(&mapping->tree_lock);
 		mem_cgroup_uncharge_cache_page(page);
 
@@ -2397,9 +2397,9 @@ loop_again:
 		 * cause too much scanning of the lower zones.
 		 */
 		for (i = 0; i <= end_zone; i++) {
-			int compaction;
 			struct zone *zone = pgdat->node_zones + i;
 			int nr_slab;
+			unsigned long balance_gap;
 
 			if (!populated_zone(zone))
 				continue;
@@ -2416,11 +2416,20 @@ loop_again:
 			mem_cgroup_soft_limit_reclaim(zone, order, sc.gfp_mask);
 
 			/*
-			 * We put equal pressure on every zone, unless one
-			 * zone has way too many pages free already.
+			 * We put equal pressure on every zone, unless
+			 * one zone has way too many pages free
+			 * already. The "too many pages" is defined
+			 * as the high wmark plus a "gap" where the
+			 * gap is either the low watermark or 1%
+			 * of the zone, whichever is smaller.
 			 */
+			balance_gap = min(low_wmark_pages(zone),
+				(zone->present_pages +
+					KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
+				KSWAPD_ZONE_BALANCE_GAP_RATIO);
 			if (!zone_watermark_ok_safe(zone, order,
-					8*high_wmark_pages(zone), end_zone, 0))
+					high_wmark_pages(zone) + balance_gap,
+					end_zone, 0))
 				shrink_zone(priority, zone, &sc);
 			reclaim_state->reclaimed_slab = 0;
 			nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
@@ -2428,24 +2437,9 @@ loop_again:
 			sc.nr_reclaimed += reclaim_state->reclaimed_slab;
 			total_scanned += sc.nr_scanned;
 
-			compaction = 0;
-			if (order &&
-			    zone_watermark_ok(zone, 0,
-					       high_wmark_pages(zone),
-					      end_zone, 0) &&
-			    !zone_watermark_ok(zone, order,
-					       high_wmark_pages(zone),
-					       end_zone, 0)) {
-				compact_zone_order(zone,
-						   order,
-						   sc.gfp_mask, false,
-						   COMPACT_MODE_KSWAPD);
-				compaction = 1;
-			}
-
 			if (zone->all_unreclaimable)
 				continue;
-			if (!compaction && nr_slab == 0 &&
+			if (nr_slab == 0 &&
 			    !zone_reclaimable(zone))
 				zone->all_unreclaimable = 1;
 			/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 0c3b504..772b39b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -500,8 +500,12 @@ void refresh_cpu_vm_stats(int cpu)
  * z 	    = the zone from which the allocation occurred.
  *
  * Must be called with interrupts disabled.
+ *
+ * When __GFP_OTHER_NODE is set assume the node of the preferred
+ * zone is the local node. This is useful for daemons who allocate
+ * memory on behalf of other processes.
  */
-void zone_statistics(struct zone *preferred_zone, struct zone *z)
+void zone_statistics(struct zone *preferred_zone, struct zone *z, gfp_t flags)
 {
 	if (z->zone_pgdat == preferred_zone->zone_pgdat) {
 		__inc_zone_state(z, NUMA_HIT);
@@ -509,7 +513,8 @@ void zone_statistics(struct zone *preferred_zone, struct zone *z)
 		__inc_zone_state(z, NUMA_MISS);
 		__inc_zone_state(preferred_zone, NUMA_FOREIGN);
 	}
-	if (z->node == numa_node_id())
+	if (z->node == ((flags & __GFP_OTHER_NODE) ?
+			preferred_zone->node : numa_node_id()))
 		__inc_zone_state(z, NUMA_LOCAL);
 	else
 		__inc_zone_state(z, NUMA_OTHER);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 6e64f7c..7850412 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -327,7 +327,7 @@ static void vlan_sync_address(struct net_device *dev,
 static void vlan_transfer_features(struct net_device *dev,
 				   struct net_device *vlandev)
 {
-	unsigned long old_features = vlandev->features;
+	u32 old_features = vlandev->features;
 
 	vlandev->features &= ~dev->vlan_features;
 	vlandev->features |= dev->features & dev->vlan_features;
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index be73753..e34ea9e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -625,6 +625,19 @@ static int vlan_dev_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
 		rc = ops->ndo_fcoe_get_wwn(real_dev, wwn, type);
 	return rc;
 }
+
+static int vlan_dev_fcoe_ddp_target(struct net_device *dev, u16 xid,
+				    struct scatterlist *sgl, unsigned int sgc)
+{
+	struct net_device *real_dev = vlan_dev_info(dev)->real_dev;
+	const struct net_device_ops *ops = real_dev->netdev_ops;
+	int rc = 0;
+
+	if (ops->ndo_fcoe_ddp_target)
+		rc = ops->ndo_fcoe_ddp_target(real_dev, xid, sgl, sgc);
+
+	return rc;
+}
 #endif
 
 static void vlan_dev_change_rx_flags(struct net_device *dev, int change)
@@ -707,6 +720,7 @@ static int vlan_dev_init(struct net_device *dev)
 	dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
 #endif
 
+	dev->needed_headroom = real_dev->needed_headroom;
 	if (real_dev->features & NETIF_F_HW_VLAN_TX) {
 		dev->header_ops      = real_dev->header_ops;
 		dev->hard_header_len = real_dev->hard_header_len;
@@ -858,6 +872,7 @@ static const struct net_device_ops vlan_netdev_ops = {
 	.ndo_fcoe_enable	= vlan_dev_fcoe_enable,
 	.ndo_fcoe_disable	= vlan_dev_fcoe_disable,
 	.ndo_fcoe_get_wwn	= vlan_dev_fcoe_get_wwn,
+	.ndo_fcoe_ddp_target	= vlan_dev_fcoe_ddp_target,
 #endif
 };
 
diff --git a/net/9p/Makefile b/net/9p/Makefile
index 198a640..a0874cc 100644
--- a/net/9p/Makefile
+++ b/net/9p/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_NET_9P_RDMA) += 9pnet_rdma.o
 	util.o \
 	protocol.o \
 	trans_fd.o \
+	trans_common.o \
 
 9pnet_virtio-objs := \
 	trans_virtio.o \
diff --git a/net/9p/client.c b/net/9p/client.c
index a848bca..2ccbf04 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -223,16 +223,29 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 
 	req = &c->reqs[row][col];
 	if (!req->tc) {
-		req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL);
+		req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS);
 		if (!req->wq) {
 			printk(KERN_ERR "Couldn't grow tag array\n");
 			return ERR_PTR(-ENOMEM);
 		}
 		init_waitqueue_head(req->wq);
-		req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
-								GFP_KERNEL);
-		req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
-								GFP_KERNEL);
+		if ((c->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
+				P9_TRANS_PREF_PAYLOAD_SEP) {
+			int alloc_msize = min(c->msize, 4096);
+			req->tc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
+					  GFP_NOFS);
+			req->tc->capacity = alloc_msize;
+			req->rc = kmalloc(sizeof(struct p9_fcall)+alloc_msize,
+					  GFP_NOFS);
+			req->rc->capacity = alloc_msize;
+		} else {
+			req->tc = kmalloc(sizeof(struct p9_fcall)+c->msize,
+					  GFP_NOFS);
+			req->tc->capacity = c->msize;
+			req->rc = kmalloc(sizeof(struct p9_fcall)+c->msize,
+					  GFP_NOFS);
+			req->rc->capacity = c->msize;
+		}
 		if ((!req->tc) || (!req->rc)) {
 			printk(KERN_ERR "Couldn't grow tag array\n");
 			kfree(req->tc);
@@ -243,9 +256,7 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag)
 			return ERR_PTR(-ENOMEM);
 		}
 		req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall);
-		req->tc->capacity = c->msize;
 		req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall);
-		req->rc->capacity = c->msize;
 	}
 
 	p9pdu_reset(req->tc);
@@ -443,6 +454,7 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
 {
 	int8_t type;
 	int err;
+	int ecode;
 
 	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
 	if (err) {
@@ -450,36 +462,53 @@ static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
 		return err;
 	}
 
-	if (type == P9_RERROR || type == P9_RLERROR) {
-		int ecode;
-
-		if (!p9_is_proto_dotl(c)) {
-			char *ename;
+	if (type != P9_RERROR && type != P9_RLERROR)
+		return 0;
 
-			err = p9pdu_readf(req->rc, c->proto_version, "s?d",
-								&ename, &ecode);
-			if (err)
-				goto out_err;
+	if (!p9_is_proto_dotl(c)) {
+		char *ename;
+
+		if (req->tc->pbuf_size) {
+			/* Handle user buffers */
+			size_t len = req->rc->size - req->rc->offset;
+			if (req->tc->pubuf) {
+				/* User Buffer */
+				err = copy_from_user(
+					&req->rc->sdata[req->rc->offset],
+					req->tc->pubuf, len);
+				if (err) {
+					err = -EFAULT;
+					goto out_err;
+				}
+			} else {
+				/* Kernel Buffer */
+				memmove(&req->rc->sdata[req->rc->offset],
+						req->tc->pkbuf, len);
+			}
+		}
+		err = p9pdu_readf(req->rc, c->proto_version, "s?d",
+				&ename, &ecode);
+		if (err)
+			goto out_err;
 
-			if (p9_is_proto_dotu(c))
-				err = -ecode;
+		if (p9_is_proto_dotu(c))
+			err = -ecode;
 
-			if (!err || !IS_ERR_VALUE(err)) {
-				err = p9_errstr2errno(ename, strlen(ename));
+		if (!err || !IS_ERR_VALUE(err)) {
+			err = p9_errstr2errno(ename, strlen(ename));
 
-				P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);
+			P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode,
+					ename);
 
-				kfree(ename);
-			}
-		} else {
-			err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
-			err = -ecode;
-
-			P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
+			kfree(ename);
 		}
+	} else {
+		err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode);
+		err = -ecode;
+
+		P9_DPRINTK(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode);
+	}
 
-	} else
-		err = 0;
 
 	return err;
 
@@ -1191,6 +1220,27 @@ error:
 }
 EXPORT_SYMBOL(p9_client_fsync);
 
+int p9_client_sync_fs(struct p9_fid *fid)
+{
+	int err = 0;
+	struct p9_req_t *req;
+	struct p9_client *clnt;
+
+	P9_DPRINTK(P9_DEBUG_9P, ">>> TSYNC_FS fid %d\n", fid->fid);
+
+	clnt = fid->clnt;
+	req = p9_client_rpc(clnt, P9_TSYNCFS, "d", fid->fid);
+	if (IS_ERR(req)) {
+		err = PTR_ERR(req);
+		goto error;
+	}
+	P9_DPRINTK(P9_DEBUG_9P, "<<< RSYNCFS fid %d\n", fid->fid);
+	p9_free_req(clnt, req);
+error:
+	return err;
+}
+EXPORT_SYMBOL(p9_client_sync_fs);
+
 int p9_client_clunk(struct p9_fid *fid)
 {
 	int err;
@@ -1270,7 +1320,15 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 	if (count < rsize)
 		rsize = count;
 
-	req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
+	/* Don't bother zerocopy form small IO (< 1024) */
+	if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
+			P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) {
+		req = p9_client_rpc(clnt, P9_TREAD, "dqE", fid->fid, offset,
+				rsize, data, udata);
+	} else {
+		req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset,
+				rsize);
+	}
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto error;
@@ -1284,13 +1342,15 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
 
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
 
-	if (data) {
-		memmove(data, dataptr, count);
-	} else {
-		err = copy_to_user(udata, dataptr, count);
-		if (err) {
-			err = -EFAULT;
-			goto free_and_error;
+	if (!req->tc->pbuf_size) {
+		if (data) {
+			memmove(data, dataptr, count);
+		} else {
+			err = copy_to_user(udata, dataptr, count);
+			if (err) {
+				err = -EFAULT;
+				goto free_and_error;
+			}
 		}
 	}
 	p9_free_req(clnt, req);
@@ -1323,12 +1383,21 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
 
 	if (count < rsize)
 		rsize = count;
-	if (data)
-		req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
-								rsize, data);
-	else
-		req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
-								rsize, udata);
+
+	/* Don't bother zerocopy form small IO (< 1024) */
+	if (((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
+				P9_TRANS_PREF_PAYLOAD_SEP) && (rsize > 1024)) {
+		req = p9_client_rpc(clnt, P9_TWRITE, "dqE", fid->fid, offset,
+				rsize, data, udata);
+	} else {
+
+		if (data)
+			req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid,
+					offset, rsize, data);
+		else
+			req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid,
+					offset, rsize, udata);
+	}
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto error;
@@ -1716,7 +1785,14 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
 	if (count < rsize)
 		rsize = count;
 
-	req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize);
+	if ((clnt->trans_mod->pref & P9_TRANS_PREF_PAYLOAD_MASK) ==
+			P9_TRANS_PREF_PAYLOAD_SEP) {
+		req = p9_client_rpc(clnt, P9_TREADDIR, "dqF", fid->fid,
+				offset, rsize, data);
+	} else {
+		req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid,
+				offset, rsize);
+	}
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto error;
@@ -1730,7 +1806,7 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
 
 	P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
 
-	if (data)
+	if (!req->tc->pbuf_size && data)
 		memmove(data, dataptr, count);
 
 	p9_free_req(clnt, req);
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 1e308f2..8a4084f 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -114,6 +114,26 @@ pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
 	return size - len;
 }
 
+static size_t
+pdu_write_urw(struct p9_fcall *pdu, const char *kdata, const char __user *udata,
+		size_t size)
+{
+	BUG_ON(pdu->size > P9_IOHDRSZ);
+	pdu->pubuf = (char __user *)udata;
+	pdu->pkbuf = (char *)kdata;
+	pdu->pbuf_size = size;
+	return 0;
+}
+
+static size_t
+pdu_write_readdir(struct p9_fcall *pdu, const char *kdata, size_t size)
+{
+	BUG_ON(pdu->size > P9_READDIRHDRSZ);
+	pdu->pkbuf = (char *)kdata;
+	pdu->pbuf_size = size;
+	return 0;
+}
+
 /*
 	b - int8_t
 	w - int16_t
@@ -185,7 +205,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
 				if (errcode)
 					break;
 
-				*sptr = kmalloc(len + 1, GFP_KERNEL);
+				*sptr = kmalloc(len + 1, GFP_NOFS);
 				if (*sptr == NULL) {
 					errcode = -EFAULT;
 					break;
@@ -253,7 +273,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
 				if (!errcode) {
 					*wnames =
 					    kmalloc(sizeof(char *) * *nwname,
-						    GFP_KERNEL);
+						    GFP_NOFS);
 					if (!*wnames)
 						errcode = -ENOMEM;
 				}
@@ -297,7 +317,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
 					*wqids =
 					    kmalloc(*nwqid *
 						    sizeof(struct p9_qid),
-						    GFP_KERNEL);
+						    GFP_NOFS);
 					if (*wqids == NULL)
 						errcode = -ENOMEM;
 				}
@@ -445,6 +465,25 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
 					errcode = -EFAULT;
 			}
 			break;
+		case 'E':{
+				 int32_t cnt = va_arg(ap, int32_t);
+				 const char *k = va_arg(ap, const void *);
+				 const char *u = va_arg(ap, const void *);
+				 errcode = p9pdu_writef(pdu, proto_version, "d",
+						 cnt);
+				 if (!errcode && pdu_write_urw(pdu, k, u, cnt))
+					errcode = -EFAULT;
+			 }
+			 break;
+		case 'F':{
+				 int32_t cnt = va_arg(ap, int32_t);
+				 const char *k = va_arg(ap, const void *);
+				 errcode = p9pdu_writef(pdu, proto_version, "d",
+						 cnt);
+				 if (!errcode && pdu_write_readdir(pdu, k, cnt))
+					errcode = -EFAULT;
+			 }
+			 break;
 		case 'U':{
 				int32_t count = va_arg(ap, int32_t);
 				const char __user *udata =
@@ -579,6 +618,7 @@ EXPORT_SYMBOL(p9stat_read);
 
 int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
 {
+	pdu->id = type;
 	return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
 }
 
@@ -606,6 +646,10 @@ void p9pdu_reset(struct p9_fcall *pdu)
 {
 	pdu->offset = 0;
 	pdu->size = 0;
+	pdu->private = NULL;
+	pdu->pubuf = NULL;
+	pdu->pkbuf = NULL;
+	pdu->pbuf_size = 0;
 }
 
 int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c
new file mode 100644
index 0000000..9172ab7
--- /dev/null
+++ b/net/9p/trans_common.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright IBM Corporation, 2010
+ * Author Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <net/9p/9p.h>
+#include <net/9p/client.h>
+#include <linux/scatterlist.h>
+#include "trans_common.h"
+
+/**
+ *  p9_release_req_pages - Release pages after the transaction.
+ *  @*private: PDU's private page of struct trans_rpage_info
+ */
+void
+p9_release_req_pages(struct trans_rpage_info *rpinfo)
+{
+	int i = 0;
+
+	while (rpinfo->rp_data[i] && rpinfo->rp_nr_pages--) {
+		put_page(rpinfo->rp_data[i]);
+		i++;
+	}
+}
+EXPORT_SYMBOL(p9_release_req_pages);
+
+/**
+ * p9_nr_pages - Return number of pages needed to accomodate the payload.
+ */
+int
+p9_nr_pages(struct p9_req_t *req)
+{
+	unsigned long start_page, end_page;
+	start_page =  (unsigned long)req->tc->pubuf >> PAGE_SHIFT;
+	end_page = ((unsigned long)req->tc->pubuf + req->tc->pbuf_size +
+			PAGE_SIZE - 1) >> PAGE_SHIFT;
+	return end_page - start_page;
+}
+EXPORT_SYMBOL(p9_nr_pages);
+
+/**
+ * payload_gup - Translates user buffer into kernel pages and
+ * pins them either for read/write through get_user_pages_fast().
+ * @req: Request to be sent to server.
+ * @pdata_off: data offset into the first page after translation (gup).
+ * @pdata_len: Total length of the IO. gup may not return requested # of pages.
+ * @nr_pages: number of pages to accomodate the payload
+ * @rw: Indicates if the pages are for read or write.
+ */
+int
+p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len,
+		int nr_pages, u8 rw)
+{
+	uint32_t first_page_bytes = 0;
+	uint32_t pdata_mapped_pages;
+	struct trans_rpage_info  *rpinfo;
+
+	*pdata_off = (size_t)req->tc->pubuf & (PAGE_SIZE-1);
+
+	if (*pdata_off)
+		first_page_bytes = min(((size_t)PAGE_SIZE - *pdata_off),
+				       req->tc->pbuf_size);
+
+	rpinfo = req->tc->private;
+	pdata_mapped_pages = get_user_pages_fast((unsigned long)req->tc->pubuf,
+			nr_pages, rw, &rpinfo->rp_data[0]);
+
+	if (pdata_mapped_pages < 0) {
+		printk(KERN_ERR "get_user_pages_fast failed:%d udata:%p"
+				"nr_pages:%d\n", pdata_mapped_pages,
+				req->tc->pubuf, nr_pages);
+		pdata_mapped_pages = 0;
+		return -EIO;
+	}
+	rpinfo->rp_nr_pages = pdata_mapped_pages;
+	if (*pdata_off) {
+		*pdata_len = first_page_bytes;
+		*pdata_len += min((req->tc->pbuf_size - *pdata_len),
+				((size_t)pdata_mapped_pages - 1) << PAGE_SHIFT);
+	} else {
+		*pdata_len = min(req->tc->pbuf_size,
+				(size_t)pdata_mapped_pages << PAGE_SHIFT);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(p9_payload_gup);
diff --git a/net/9p/trans_common.h b/net/9p/trans_common.h
new file mode 100644
index 0000000..7630922
--- /dev/null
+++ b/net/9p/trans_common.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright IBM Corporation, 2010
+ * Author Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+/* TRUE if it is user context */
+#define P9_IS_USER_CONTEXT (!segment_eq(get_fs(), KERNEL_DS))
+
+/**
+ * struct trans_rpage_info - To store mapped page information in PDU.
+ * @rp_alloc:Set if this structure is allocd, not a reuse unused space in pdu.
+ * @rp_nr_pages: Number of mapped pages
+ * @rp_data: Array of page pointers
+ */
+struct trans_rpage_info {
+	u8 rp_alloc;
+	int rp_nr_pages;
+	struct page *rp_data[0];
+};
+
+void p9_release_req_pages(struct trans_rpage_info *);
+int p9_payload_gup(struct p9_req_t *, size_t *, int *, int, u8);
+int p9_nr_pages(struct p9_req_t *);
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 078eb16..aa5672b 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -153,10 +153,11 @@ struct p9_conn {
 	unsigned long wsched;
 };
 
+static void p9_poll_workfn(struct work_struct *work);
+
 static DEFINE_SPINLOCK(p9_poll_lock);
 static LIST_HEAD(p9_poll_pending_list);
-static struct workqueue_struct *p9_mux_wq;
-static struct task_struct *p9_poll_task;
+static DECLARE_WORK(p9_poll_work, p9_poll_workfn);
 
 static void p9_mux_poll_stop(struct p9_conn *m)
 {
@@ -349,7 +350,7 @@ static void p9_read_work(struct work_struct *work)
 
 		if (m->req->rc == NULL) {
 			m->req->rc = kmalloc(sizeof(struct p9_fcall) +
-						m->client->msize, GFP_KERNEL);
+						m->client->msize, GFP_NOFS);
 			if (!m->req->rc) {
 				m->req = NULL;
 				err = -ENOMEM;
@@ -384,7 +385,7 @@ static void p9_read_work(struct work_struct *work)
 
 		if (n & POLLIN) {
 			P9_DPRINTK(P9_DEBUG_TRANS, "sched read work %p\n", m);
-			queue_work(p9_mux_wq, &m->rq);
+			schedule_work(&m->rq);
 		} else
 			clear_bit(Rworksched, &m->wsched);
 	} else
@@ -497,7 +498,7 @@ static void p9_write_work(struct work_struct *work)
 
 		if (n & POLLOUT) {
 			P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m);
-			queue_work(p9_mux_wq, &m->wq);
+			schedule_work(&m->wq);
 		} else
 			clear_bit(Wworksched, &m->wsched);
 	} else
@@ -516,15 +517,14 @@ static int p9_pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
 		container_of(wait, struct p9_poll_wait, wait);
 	struct p9_conn *m = pwait->conn;
 	unsigned long flags;
-	DECLARE_WAITQUEUE(dummy_wait, p9_poll_task);
 
 	spin_lock_irqsave(&p9_poll_lock, flags);
 	if (list_empty(&m->poll_pending_link))
 		list_add_tail(&m->poll_pending_link, &p9_poll_pending_list);
 	spin_unlock_irqrestore(&p9_poll_lock, flags);
 
-	/* perform the default wake up operation */
-	return default_wake_function(&dummy_wait, mode, sync, key);
+	schedule_work(&p9_poll_work);
+	return 1;
 }
 
 /**
@@ -629,7 +629,7 @@ static void p9_poll_mux(struct p9_conn *m)
 		P9_DPRINTK(P9_DEBUG_TRANS, "mux %p can read\n", m);
 		if (!test_and_set_bit(Rworksched, &m->wsched)) {
 			P9_DPRINTK(P9_DEBUG_TRANS, "sched read work %p\n", m);
-			queue_work(p9_mux_wq, &m->rq);
+			schedule_work(&m->rq);
 		}
 	}
 
@@ -639,7 +639,7 @@ static void p9_poll_mux(struct p9_conn *m)
 		if ((m->wsize || !list_empty(&m->unsent_req_list)) &&
 		    !test_and_set_bit(Wworksched, &m->wsched)) {
 			P9_DPRINTK(P9_DEBUG_TRANS, "sched write work %p\n", m);
-			queue_work(p9_mux_wq, &m->wq);
+			schedule_work(&m->wq);
 		}
 	}
 }
@@ -677,7 +677,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
 		n = p9_fd_poll(m->client, NULL);
 
 	if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched))
-		queue_work(p9_mux_wq, &m->wq);
+		schedule_work(&m->wq);
 
 	return 0;
 }
@@ -1047,12 +1047,12 @@ static struct p9_trans_module p9_fd_trans = {
  *
  */
 
-static int p9_poll_proc(void *a)
+static void p9_poll_workfn(struct work_struct *work)
 {
 	unsigned long flags;
 
 	P9_DPRINTK(P9_DEBUG_TRANS, "start %p\n", current);
- repeat:
+
 	spin_lock_irqsave(&p9_poll_lock, flags);
 	while (!list_empty(&p9_poll_pending_list)) {
 		struct p9_conn *conn = list_first_entry(&p9_poll_pending_list,
@@ -1067,35 +1067,11 @@ static int p9_poll_proc(void *a)
 	}
 	spin_unlock_irqrestore(&p9_poll_lock, flags);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	if (list_empty(&p9_poll_pending_list)) {
-		P9_DPRINTK(P9_DEBUG_TRANS, "sleeping...\n");
-		schedule();
-	}
-	__set_current_state(TASK_RUNNING);
-
-	if (!kthread_should_stop())
-		goto repeat;
-
 	P9_DPRINTK(P9_DEBUG_TRANS, "finish\n");
-	return 0;
 }
 
 int p9_trans_fd_init(void)
 {
-	p9_mux_wq = create_workqueue("v9fs");
-	if (!p9_mux_wq) {
-		printk(KERN_WARNING "v9fs: mux: creating workqueue failed\n");
-		return -ENOMEM;
-	}
-
-	p9_poll_task = kthread_run(p9_poll_proc, NULL, "v9fs-poll");
-	if (IS_ERR(p9_poll_task)) {
-		destroy_workqueue(p9_mux_wq);
-		printk(KERN_WARNING "v9fs: mux: creating poll task failed\n");
-		return PTR_ERR(p9_poll_task);
-	}
-
 	v9fs_register_trans(&p9_tcp_trans);
 	v9fs_register_trans(&p9_unix_trans);
 	v9fs_register_trans(&p9_fd_trans);
@@ -1105,10 +1081,8 @@ int p9_trans_fd_init(void)
 
 void p9_trans_fd_exit(void)
 {
-	kthread_stop(p9_poll_task);
+	flush_work_sync(&p9_poll_work);
 	v9fs_unregister_trans(&p9_tcp_trans);
 	v9fs_unregister_trans(&p9_unix_trans);
 	v9fs_unregister_trans(&p9_fd_trans);
-
-	destroy_workqueue(p9_mux_wq);
 }
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c
index 17c5ba7..150e0c4 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -59,7 +59,6 @@
 						 * safely advertise a maxsize
 						 * of 64k */
 
-#define P9_RDMA_MAX_SGE (P9_RDMA_MAXSIZE >> PAGE_SHIFT)
 /**
  * struct p9_trans_rdma - RDMA transport instance
  *
@@ -425,7 +424,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
 	struct p9_rdma_context *rpl_context = NULL;
 
 	/* Allocate an fcall for the reply */
-	rpl_context = kmalloc(sizeof *rpl_context, GFP_KERNEL);
+	rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS);
 	if (!rpl_context) {
 		err = -ENOMEM;
 		goto err_close;
@@ -438,7 +437,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
 	 */
 	if (!req->rc) {
 		req->rc = kmalloc(sizeof(struct p9_fcall)+client->msize,
-								GFP_KERNEL);
+				  GFP_NOFS);
 		if (req->rc) {
 			req->rc->sdata = (char *) req->rc +
 						sizeof(struct p9_fcall);
@@ -469,7 +468,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
 	req->rc = NULL;
 
 	/* Post the request */
-	c = kmalloc(sizeof *c, GFP_KERNEL);
+	c = kmalloc(sizeof *c, GFP_NOFS);
 	if (!c) {
 		err = -ENOMEM;
 		goto err_free1;
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index c8f3f72..e8f046b 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -43,13 +43,17 @@
 #include <net/9p/client.h>
 #include <net/9p/transport.h>
 #include <linux/scatterlist.h>
+#include <linux/swap.h>
 #include <linux/virtio.h>
 #include <linux/virtio_9p.h>
+#include "trans_common.h"
 
 #define VIRTQUEUE_NUM	128
 
 /* a single mutex to manage channel initialization and attachment */
 static DEFINE_MUTEX(virtio_9p_lock);
+static DECLARE_WAIT_QUEUE_HEAD(vp_wq);
+static atomic_t vp_pinned = ATOMIC_INIT(0);
 
 /**
  * struct virtio_chan - per-instance transport information
@@ -77,7 +81,10 @@ struct virtio_chan {
 	struct virtqueue *vq;
 	int ring_bufs_avail;
 	wait_queue_head_t *vc_wq;
-
+	/* This is global limit. Since we don't have a global structure,
+	 * will be placing it in each channel.
+	 */
+	int p9_max_pages;
 	/* Scatterlist: can be too big for stack. */
 	struct scatterlist sg[VIRTQUEUE_NUM];
 
@@ -140,26 +147,36 @@ static void req_done(struct virtqueue *vq)
 
 	P9_DPRINTK(P9_DEBUG_TRANS, ": request done\n");
 
-	do {
+	while (1) {
 		spin_lock_irqsave(&chan->lock, flags);
 		rc = virtqueue_get_buf(chan->vq, &len);
 
-		if (rc != NULL) {
-			if (!chan->ring_bufs_avail) {
-				chan->ring_bufs_avail = 1;
-				wake_up(chan->vc_wq);
-			}
-			spin_unlock_irqrestore(&chan->lock, flags);
-			P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
-			P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n",
-					rc->tag);
-			req = p9_tag_lookup(chan->client, rc->tag);
-			req->status = REQ_STATUS_RCVD;
-			p9_client_cb(chan->client, req);
-		} else {
+		if (rc == NULL) {
 			spin_unlock_irqrestore(&chan->lock, flags);
+			break;
+		}
+
+		chan->ring_bufs_avail = 1;
+		spin_unlock_irqrestore(&chan->lock, flags);
+		/* Wakeup if anyone waiting for VirtIO ring space. */
+		wake_up(chan->vc_wq);
+		P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
+		P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
+		req = p9_tag_lookup(chan->client, rc->tag);
+		if (req->tc->private) {
+			struct trans_rpage_info *rp = req->tc->private;
+			int p = rp->rp_nr_pages;
+			/*Release pages */
+			p9_release_req_pages(rp);
+			atomic_sub(p, &vp_pinned);
+			wake_up(&vp_wq);
+			if (rp->rp_alloc)
+				kfree(rp);
+			req->tc->private = NULL;
 		}
-	} while (rc != NULL);
+		req->status = REQ_STATUS_RCVD;
+		p9_client_cb(chan->client, req);
+	}
 }
 
 /**
@@ -203,6 +220,38 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
 }
 
 /**
+ * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer,
+ * this takes a list of pages.
+ * @sg: scatter/gather list to pack into
+ * @start: which segment of the sg_list to start at
+ * @pdata_off: Offset into the first page
+ * @**pdata: a list of pages to add into sg.
+ * @count: amount of data to pack into the scatter/gather list
+ */
+static int
+pack_sg_list_p(struct scatterlist *sg, int start, int limit, size_t pdata_off,
+		struct page **pdata, int count)
+{
+	int s;
+	int i = 0;
+	int index = start;
+
+	if (pdata_off) {
+		s = min((int)(PAGE_SIZE - pdata_off), count);
+		sg_set_page(&sg[index++], pdata[i++], s, pdata_off);
+		count -= s;
+	}
+
+	while (count) {
+		BUG_ON(index > limit);
+		s = min((int)PAGE_SIZE, count);
+		sg_set_page(&sg[index++], pdata[i++], s, 0);
+		count -= s;
+	}
+	return index-start;
+}
+
+/**
  * p9_virtio_request - issue a request
  * @client: client instance issuing the request
  * @req: request to be issued
@@ -212,22 +261,107 @@ static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req)
 static int
 p9_virtio_request(struct p9_client *client, struct p9_req_t *req)
 {
-	int in, out;
+	int in, out, inp, outp;
 	struct virtio_chan *chan = client->trans;
 	char *rdata = (char *)req->rc+sizeof(struct p9_fcall);
 	unsigned long flags;
-	int err;
+	size_t pdata_off = 0;
+	struct trans_rpage_info *rpinfo = NULL;
+	int err, pdata_len = 0;
 
 	P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: virtio request\n");
 
-req_retry:
 	req->status = REQ_STATUS_SENT;
 
+	if (req->tc->pbuf_size && (req->tc->pubuf && P9_IS_USER_CONTEXT)) {
+		int nr_pages = p9_nr_pages(req);
+		int rpinfo_size = sizeof(struct trans_rpage_info) +
+			sizeof(struct page *) * nr_pages;
+
+		if (atomic_read(&vp_pinned) >= chan->p9_max_pages) {
+			err = wait_event_interruptible(vp_wq,
+				atomic_read(&vp_pinned) < chan->p9_max_pages);
+			if (err  == -ERESTARTSYS)
+				return err;
+			P9_DPRINTK(P9_DEBUG_TRANS, "9p: May gup pages now.\n");
+		}
+
+		if (rpinfo_size <= (req->tc->capacity - req->tc->size)) {
+			/* We can use sdata */
+			req->tc->private = req->tc->sdata + req->tc->size;
+			rpinfo = (struct trans_rpage_info *)req->tc->private;
+			rpinfo->rp_alloc = 0;
+		} else {
+			req->tc->private = kmalloc(rpinfo_size, GFP_NOFS);
+			if (!req->tc->private) {
+				P9_DPRINTK(P9_DEBUG_TRANS, "9p debug: "
+					"private kmalloc returned NULL");
+				return -ENOMEM;
+			}
+			rpinfo = (struct trans_rpage_info *)req->tc->private;
+			rpinfo->rp_alloc = 1;
+		}
+
+		err = p9_payload_gup(req, &pdata_off, &pdata_len, nr_pages,
+				req->tc->id == P9_TREAD ? 1 : 0);
+		if (err < 0) {
+			if (rpinfo->rp_alloc)
+				kfree(rpinfo);
+			return err;
+		} else {
+			atomic_add(rpinfo->rp_nr_pages, &vp_pinned);
+		}
+	}
+
+req_retry_pinned:
 	spin_lock_irqsave(&chan->lock, flags);
+
+	/* Handle out VirtIO ring buffers */
 	out = pack_sg_list(chan->sg, 0, VIRTQUEUE_NUM, req->tc->sdata,
-								req->tc->size);
-	in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM-out, rdata,
-								client->msize);
+			req->tc->size);
+
+	if (req->tc->pbuf_size && (req->tc->id == P9_TWRITE)) {
+		/* We have additional write payload buffer to take care */
+		if (req->tc->pubuf && P9_IS_USER_CONTEXT) {
+			outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
+					pdata_off, rpinfo->rp_data, pdata_len);
+		} else {
+			char *pbuf = req->tc->pubuf ? req->tc->pubuf :
+								req->tc->pkbuf;
+			outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf,
+					req->tc->pbuf_size);
+		}
+		out += outp;
+	}
+
+	/* Handle in VirtIO ring buffers */
+	if (req->tc->pbuf_size &&
+		((req->tc->id == P9_TREAD) || (req->tc->id == P9_TREADDIR))) {
+		/*
+		 * Take care of additional Read payload.
+		 * 11 is the read/write header = PDU Header(7) + IO Size (4).
+		 * Arrange in such a way that server places header in the
+		 * alloced memory and payload onto the user buffer.
+		 */
+		inp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata, 11);
+		/*
+		 * Running executables in the filesystem may result in
+		 * a read request with kernel buffer as opposed to user buffer.
+		 */
+		if (req->tc->pubuf && P9_IS_USER_CONTEXT) {
+			in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM,
+					pdata_off, rpinfo->rp_data, pdata_len);
+		} else {
+			char *pbuf = req->tc->pubuf ? req->tc->pubuf :
+								req->tc->pkbuf;
+			in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM,
+					pbuf, req->tc->pbuf_size);
+		}
+		in += inp;
+	} else {
+		in = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, rdata,
+				client->msize);
+	}
 
 	err = virtqueue_add_buf(chan->vq, chan->sg, out, in, req->tc);
 	if (err < 0) {
@@ -240,12 +374,14 @@ req_retry:
 				return err;
 
 			P9_DPRINTK(P9_DEBUG_TRANS, "9p:Retry virtio request\n");
-			goto req_retry;
+			goto req_retry_pinned;
 		} else {
 			spin_unlock_irqrestore(&chan->lock, flags);
 			P9_DPRINTK(P9_DEBUG_TRANS,
 					"9p debug: "
 					"virtio rpc add_buf returned failure");
+			if (rpinfo && rpinfo->rp_alloc)
+				kfree(rpinfo);
 			return -EIO;
 		}
 	}
@@ -335,6 +471,8 @@ static int p9_virtio_probe(struct virtio_device *vdev)
 	}
 	init_waitqueue_head(chan->vc_wq);
 	chan->ring_bufs_avail = 1;
+	/* Ceiling limit to avoid denial of service attacks */
+	chan->p9_max_pages = nr_free_buffer_pages()/4;
 
 	mutex_lock(&virtio_9p_lock);
 	list_add_tail(&chan->chan_list, &virtio_chan_list);
@@ -448,6 +586,7 @@ static struct p9_trans_module p9_virtio_trans = {
 	.request = p9_virtio_request,
 	.cancel = p9_virtio_cancel,
 	.maxsize = PAGE_SIZE*16,
+	.pref = P9_TRANS_PREF_PAYLOAD_SEP,
 	.def = 0,
 	.owner = THIS_MODULE,
 };
diff --git a/net/9p/util.c b/net/9p/util.c
index e048701..b84619b 100644
--- a/net/9p/util.c
+++ b/net/9p/util.c
@@ -92,7 +92,7 @@ int p9_idpool_get(struct p9_idpool *p)
 	unsigned long flags;
 
 retry:
-	if (idr_pre_get(&p->pool, GFP_KERNEL) == 0)
+	if (idr_pre_get(&p->pool, GFP_NOFS) == 0)
 		return 0;
 
 	spin_lock_irqsave(&p->lock, flags);
diff --git a/net/Kconfig b/net/Kconfig
index 7284062..79cabf1 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -221,6 +221,12 @@ config RPS
 	depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS
 	default y
 
+config RFS_ACCEL
+	boolean
+	depends on RPS && GENERIC_HARDIRQS
+	select CPU_RMAP
+	default y
+
 config XPS
 	boolean
 	depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index c410b93..206e771 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -54,7 +54,6 @@
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/if_arp.h>
-#include <linux/smp_lock.h>
 #include <linux/termios.h>	/* For TIOCOUTQ/INQ */
 #include <linux/compat.h>
 #include <linux/slab.h>
@@ -1052,13 +1051,16 @@ static int atalk_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
 
-	lock_kernel();
+	sock_hold(sk);
+	lock_sock(sk);
 	if (sk) {
 		sock_orphan(sk);
 		sock->sk = NULL;
 		atalk_destroy_socket(sk);
 	}
-	unlock_kernel();
+	release_sock(sk);
+	sock_put(sk);
+
 	return 0;
 }
 
@@ -1143,7 +1145,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	if (addr->sat_family != AF_APPLETALK)
 		return -EAFNOSUPPORT;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
 		struct atalk_addr *ap = atalk_find_primary();
 
@@ -1179,7 +1181,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	sock_reset_flag(sk, SOCK_ZAPPED);
 	err = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -1215,7 +1217,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 #endif
 	}
 
-	lock_kernel();
+	lock_sock(sk);
 	err = -EBUSY;
 	if (sock_flag(sk, SOCK_ZAPPED))
 		if (atalk_autobind(sk) < 0)
@@ -1233,7 +1235,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 	sk->sk_state = TCP_ESTABLISHED;
 	err = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -1249,7 +1251,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
 	struct atalk_sock *at = at_sk(sk);
 	int err;
 
-	lock_kernel();
+	lock_sock(sk);
 	err = -ENOBUFS;
 	if (sock_flag(sk, SOCK_ZAPPED))
 		if (atalk_autobind(sk) < 0)
@@ -1277,17 +1279,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
 	memcpy(uaddr, &sat, sizeof(sat));
 
 out:
-	unlock_kernel();
-	return err;
-}
-
-static unsigned int atalk_poll(struct file *file, struct socket *sock,
-			   poll_table *wait)
-{
-	int err;
-	lock_kernel();
-	err = datagram_poll(file, sock, wait);
-	unlock_kernel();
+	release_sock(sk);
 	return err;
 }
 
@@ -1596,7 +1588,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	if (len > DDP_MAXSZ)
 		return -EMSGSIZE;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (usat) {
 		err = -EBUSY;
 		if (sock_flag(sk, SOCK_ZAPPED))
@@ -1651,7 +1643,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 			sk, size, dev->name);
 
 	size += dev->hard_header_len;
+	release_sock(sk);
 	skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
+	lock_sock(sk);
 	if (!skb)
 		goto out;
 
@@ -1738,7 +1732,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
 
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err ? : len;
 }
 
@@ -1753,9 +1747,10 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	int err = 0;
 	struct sk_buff *skb;
 
-	lock_kernel();
 	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 						flags & MSG_DONTWAIT, &err);
+	lock_sock(sk);
+
 	if (!skb)
 		goto out;
 
@@ -1787,7 +1782,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 	skb_free_datagram(sk, skb);	/* Free the datagram. */
 
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return err ? : copied;
 }
 
@@ -1887,7 +1882,7 @@ static const struct proto_ops atalk_dgram_ops = {
 	.socketpair	= sock_no_socketpair,
 	.accept		= sock_no_accept,
 	.getname	= atalk_getname,
-	.poll		= atalk_poll,
+	.poll		= datagram_poll,
 	.ioctl		= atalk_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= atalk_compat_ioctl,
diff --git a/net/atm/clip.c b/net/atm/clip.c
index d257da5..1d4be60 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -502,8 +502,6 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
 	struct atmarp_entry *entry;
 	int error;
 	struct clip_vcc *clip_vcc;
-	struct flowi fl = { .fl4_dst = ip,
-			    .fl4_tos = 1 };
 	struct rtable *rt;
 
 	if (vcc->push != clip_push) {
@@ -520,9 +518,9 @@ static int clip_setentry(struct atm_vcc *vcc, __be32 ip)
 		unlink_clip_vcc(clip_vcc);
 		return 0;
 	}
-	error = ip_route_output_key(&init_net, &rt, &fl);
-	if (error)
-		return error;
+	rt = ip_route_output(&init_net, ip, 0, 1, 0);
+	if (IS_ERR(rt))
+		return PTR_ERR(rt);
 	neigh = __neigh_lookup(&clip_tbl, &ip, rt->dst.dev, 1);
 	ip_rt_put(rt);
 	if (!neigh)
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index d936aec..2de93d0 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+# Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
 #
 # Marek Lindner, Simon Wunderlich
 #
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c
index 3850a3e..af45d6b 100644
--- a/net/batman-adv/aggregation.c
+++ b/net/batman-adv/aggregation.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -35,7 +35,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
 			       int packet_len,
 			       unsigned long send_time,
 			       bool directlink,
-			       struct batman_if *if_incoming,
+			       struct hard_iface *if_incoming,
 			       struct forw_packet *forw_packet)
 {
 	struct batman_packet *batman_packet =
@@ -99,7 +99,7 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
 /* create a new aggregated packet and add this packet to it */
 static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
 				  unsigned long send_time, bool direct_link,
-				  struct batman_if *if_incoming,
+				  struct hard_iface *if_incoming,
 				  int own_packet)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
@@ -188,7 +188,7 @@ static void aggregate(struct forw_packet *forw_packet_aggr,
 
 void add_bat_packet_to_list(struct bat_priv *bat_priv,
 			    unsigned char *packet_buff, int packet_len,
-			    struct batman_if *if_incoming, char own_packet,
+			    struct hard_iface *if_incoming, char own_packet,
 			    unsigned long send_time)
 {
 	/**
@@ -247,7 +247,7 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
 
 /* unpack the aggregated packets and process them one by one */
 void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
-			     int packet_len, struct batman_if *if_incoming)
+			     int packet_len, struct hard_iface *if_incoming)
 {
 	struct batman_packet *batman_packet;
 	int buff_pos = 0;
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h
index 71a91b3..0622042 100644
--- a/net/batman-adv/aggregation.h
+++ b/net/batman-adv/aggregation.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -35,9 +35,9 @@ static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna)
 
 void add_bat_packet_to_list(struct bat_priv *bat_priv,
 			    unsigned char *packet_buff, int packet_len,
-			    struct batman_if *if_incoming, char own_packet,
+			    struct hard_iface *if_incoming, char own_packet,
 			    unsigned long send_time);
 void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
-			     int packet_len, struct batman_if *if_incoming);
+			     int packet_len, struct hard_iface *if_incoming);
 
 #endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c
index 0ae81d0..0e9d435 100644
--- a/net/batman-adv/bat_debugfs.c
+++ b/net/batman-adv/bat_debugfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2010-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -52,7 +52,6 @@ static void emit_log_char(struct debug_log *debug_log, char c)
 
 static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
 {
-	int printed_len;
 	va_list args;
 	static char debug_log_buf[256];
 	char *p;
@@ -62,8 +61,7 @@ static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
 
 	spin_lock_bh(&debug_log->lock);
 	va_start(args, fmt);
-	printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf),
-				 fmt, args);
+	vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt, args);
 	va_end(args);
 
 	for (p = debug_log_buf; *p != 0; p++)
diff --git a/net/batman-adv/bat_debugfs.h b/net/batman-adv/bat_debugfs.h
index 72df532..bc9cda3 100644
--- a/net/batman-adv/bat_debugfs.h
+++ b/net/batman-adv/bat_debugfs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2010-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c
index cd7bb51..e449bf6 100644
--- a/net/batman-adv/bat_sysfs.c
+++ b/net/batman-adv/bat_sysfs.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2010-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -441,16 +441,16 @@ static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
 			       char *buff)
 {
 	struct net_device *net_dev = kobj_to_netdev(kobj);
-	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
 	ssize_t length;
 
-	if (!batman_if)
+	if (!hard_iface)
 		return 0;
 
-	length = sprintf(buff, "%s\n", batman_if->if_status == IF_NOT_IN_USE ?
-			 "none" : batman_if->soft_iface->name);
+	length = sprintf(buff, "%s\n", hard_iface->if_status == IF_NOT_IN_USE ?
+			 "none" : hard_iface->soft_iface->name);
 
-	kref_put(&batman_if->refcount, hardif_free_ref);
+	hardif_free_ref(hard_iface);
 
 	return length;
 }
@@ -459,11 +459,11 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
 				char *buff, size_t count)
 {
 	struct net_device *net_dev = kobj_to_netdev(kobj);
-	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
 	int status_tmp = -1;
-	int ret;
+	int ret = count;
 
-	if (!batman_if)
+	if (!hard_iface)
 		return count;
 
 	if (buff[count - 1] == '\n')
@@ -472,7 +472,7 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
 	if (strlen(buff) >= IFNAMSIZ) {
 		pr_err("Invalid parameter for 'mesh_iface' setting received: "
 		       "interface name too long '%s'\n", buff);
-		kref_put(&batman_if->refcount, hardif_free_ref);
+		hardif_free_ref(hard_iface);
 		return -EINVAL;
 	}
 
@@ -481,30 +481,31 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
 	else
 		status_tmp = IF_I_WANT_YOU;
 
-	if ((batman_if->if_status == status_tmp) || ((batman_if->soft_iface) &&
-	    (strncmp(batman_if->soft_iface->name, buff, IFNAMSIZ) == 0))) {
-		kref_put(&batman_if->refcount, hardif_free_ref);
-		return count;
-	}
+	if (hard_iface->if_status == status_tmp)
+		goto out;
+
+	if ((hard_iface->soft_iface) &&
+	    (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0))
+		goto out;
 
 	if (status_tmp == IF_NOT_IN_USE) {
 		rtnl_lock();
-		hardif_disable_interface(batman_if);
+		hardif_disable_interface(hard_iface);
 		rtnl_unlock();
-		kref_put(&batman_if->refcount, hardif_free_ref);
-		return count;
+		goto out;
 	}
 
 	/* if the interface already is in use */
-	if (batman_if->if_status != IF_NOT_IN_USE) {
+	if (hard_iface->if_status != IF_NOT_IN_USE) {
 		rtnl_lock();
-		hardif_disable_interface(batman_if);
+		hardif_disable_interface(hard_iface);
 		rtnl_unlock();
 	}
 
-	ret = hardif_enable_interface(batman_if, buff);
-	kref_put(&batman_if->refcount, hardif_free_ref);
+	ret = hardif_enable_interface(hard_iface, buff);
 
+out:
+	hardif_free_ref(hard_iface);
 	return ret;
 }
 
@@ -512,13 +513,13 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
 				 char *buff)
 {
 	struct net_device *net_dev = kobj_to_netdev(kobj);
-	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
 	ssize_t length;
 
-	if (!batman_if)
+	if (!hard_iface)
 		return 0;
 
-	switch (batman_if->if_status) {
+	switch (hard_iface->if_status) {
 	case IF_TO_BE_REMOVED:
 		length = sprintf(buff, "disabling\n");
 		break;
@@ -537,7 +538,7 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
 		break;
 	}
 
-	kref_put(&batman_if->refcount, hardif_free_ref);
+	hardif_free_ref(hard_iface);
 
 	return length;
 }
diff --git a/net/batman-adv/bat_sysfs.h b/net/batman-adv/bat_sysfs.h
index 7f186c0..02f1fa7 100644
--- a/net/batman-adv/bat_sysfs.h
+++ b/net/batman-adv/bat_sysfs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2010-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c
index bbcd8f7..ad2ca92 100644
--- a/net/batman-adv/bitarray.c
+++ b/net/batman-adv/bitarray.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2006-2011 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
diff --git a/net/batman-adv/bitarray.h b/net/batman-adv/bitarray.h
index ac54017..769c246 100644
--- a/net/batman-adv/bitarray.h
+++ b/net/batman-adv/bitarray.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2006-2011 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 0065ffb..3cc4355 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2009-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -28,58 +28,75 @@
 #include <linux/udp.h>
 #include <linux/if_vlan.h>
 
-static void gw_node_free_ref(struct kref *refcount)
+static void gw_node_free_rcu(struct rcu_head *rcu)
 {
 	struct gw_node *gw_node;
 
-	gw_node = container_of(refcount, struct gw_node, refcount);
+	gw_node = container_of(rcu, struct gw_node, rcu);
 	kfree(gw_node);
 }
 
-static void gw_node_free_rcu(struct rcu_head *rcu)
+static void gw_node_free_ref(struct gw_node *gw_node)
 {
-	struct gw_node *gw_node;
-
-	gw_node = container_of(rcu, struct gw_node, rcu);
-	kref_put(&gw_node->refcount, gw_node_free_ref);
+	if (atomic_dec_and_test(&gw_node->refcount))
+		call_rcu(&gw_node->rcu, gw_node_free_rcu);
 }
 
 void *gw_get_selected(struct bat_priv *bat_priv)
 {
-	struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
+	struct gw_node *curr_gateway_tmp;
+	struct orig_node *orig_node = NULL;
 
+	rcu_read_lock();
+	curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
 	if (!curr_gateway_tmp)
-		return NULL;
+		goto out;
+
+	orig_node = curr_gateway_tmp->orig_node;
+	if (!orig_node)
+		goto out;
 
-	return curr_gateway_tmp->orig_node;
+	if (!atomic_inc_not_zero(&orig_node->refcount))
+		orig_node = NULL;
+
+out:
+	rcu_read_unlock();
+	return orig_node;
 }
 
 void gw_deselect(struct bat_priv *bat_priv)
 {
-	struct gw_node *gw_node = bat_priv->curr_gw;
+	struct gw_node *gw_node;
 
-	bat_priv->curr_gw = NULL;
+	spin_lock_bh(&bat_priv->gw_list_lock);
+	gw_node = rcu_dereference(bat_priv->curr_gw);
+	rcu_assign_pointer(bat_priv->curr_gw, NULL);
+	spin_unlock_bh(&bat_priv->gw_list_lock);
 
 	if (gw_node)
-		kref_put(&gw_node->refcount, gw_node_free_ref);
+		gw_node_free_ref(gw_node);
 }
 
-static struct gw_node *gw_select(struct bat_priv *bat_priv,
-			  struct gw_node *new_gw_node)
+static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node)
 {
-	struct gw_node *curr_gw_node = bat_priv->curr_gw;
+	struct gw_node *curr_gw_node;
 
-	if (new_gw_node)
-		kref_get(&new_gw_node->refcount);
+	if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount))
+		new_gw_node = NULL;
+
+	spin_lock_bh(&bat_priv->gw_list_lock);
+	curr_gw_node = rcu_dereference(bat_priv->curr_gw);
+	rcu_assign_pointer(bat_priv->curr_gw, new_gw_node);
+	spin_unlock_bh(&bat_priv->gw_list_lock);
 
-	bat_priv->curr_gw = new_gw_node;
-	return curr_gw_node;
+	if (curr_gw_node)
+		gw_node_free_ref(curr_gw_node);
 }
 
 void gw_election(struct bat_priv *bat_priv)
 {
 	struct hlist_node *node;
-	struct gw_node *gw_node, *curr_gw_tmp = NULL, *old_gw_node = NULL;
+	struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL;
 	uint8_t max_tq = 0;
 	uint32_t max_gw_factor = 0, tmp_gw_factor = 0;
 	int down, up;
@@ -93,19 +110,23 @@ void gw_election(struct bat_priv *bat_priv)
 	if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT)
 		return;
 
-	if (bat_priv->curr_gw)
+	rcu_read_lock();
+	curr_gw = rcu_dereference(bat_priv->curr_gw);
+	if (curr_gw) {
+		rcu_read_unlock();
 		return;
+	}
 
-	rcu_read_lock();
 	if (hlist_empty(&bat_priv->gw_list)) {
-		rcu_read_unlock();
 
-		if (bat_priv->curr_gw) {
+		if (curr_gw) {
+			rcu_read_unlock();
 			bat_dbg(DBG_BATMAN, bat_priv,
 				"Removing selected gateway - "
 				"no gateway in range\n");
 			gw_deselect(bat_priv);
-		}
+		} else
+			rcu_read_unlock();
 
 		return;
 	}
@@ -154,12 +175,12 @@ void gw_election(struct bat_priv *bat_priv)
 			max_gw_factor = tmp_gw_factor;
 	}
 
-	if (bat_priv->curr_gw != curr_gw_tmp) {
-		if ((bat_priv->curr_gw) && (!curr_gw_tmp))
+	if (curr_gw != curr_gw_tmp) {
+		if ((curr_gw) && (!curr_gw_tmp))
 			bat_dbg(DBG_BATMAN, bat_priv,
 				"Removing selected gateway - "
 				"no gateway in range\n");
-		else if ((!bat_priv->curr_gw) && (curr_gw_tmp))
+		else if ((!curr_gw) && (curr_gw_tmp))
 			bat_dbg(DBG_BATMAN, bat_priv,
 				"Adding route to gateway %pM "
 				"(gw_flags: %i, tq: %i)\n",
@@ -174,43 +195,43 @@ void gw_election(struct bat_priv *bat_priv)
 				curr_gw_tmp->orig_node->gw_flags,
 				curr_gw_tmp->orig_node->router->tq_avg);
 
-		old_gw_node = gw_select(bat_priv, curr_gw_tmp);
+		gw_select(bat_priv, curr_gw_tmp);
 	}
 
 	rcu_read_unlock();
-
-	/* the kfree() has to be outside of the rcu lock */
-	if (old_gw_node)
-		kref_put(&old_gw_node->refcount, gw_node_free_ref);
 }
 
 void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
 {
-	struct gw_node *curr_gateway_tmp = bat_priv->curr_gw;
+	struct gw_node *curr_gateway_tmp;
 	uint8_t gw_tq_avg, orig_tq_avg;
 
+	rcu_read_lock();
+	curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw);
 	if (!curr_gateway_tmp)
-		return;
+		goto out_rcu;
 
 	if (!curr_gateway_tmp->orig_node)
-		goto deselect;
+		goto deselect_rcu;
 
 	if (!curr_gateway_tmp->orig_node->router)
-		goto deselect;
+		goto deselect_rcu;
 
 	/* this node already is the gateway */
 	if (curr_gateway_tmp->orig_node == orig_node)
-		return;
+		goto out_rcu;
 
 	if (!orig_node->router)
-		return;
+		goto out_rcu;
 
 	gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg;
+	rcu_read_unlock();
+
 	orig_tq_avg = orig_node->router->tq_avg;
 
 	/* the TQ value has to be better */
 	if (orig_tq_avg < gw_tq_avg)
-		return;
+		goto out;
 
 	/**
 	 * if the routing class is greater than 3 the value tells us how much
@@ -218,15 +239,23 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
 	 **/
 	if ((atomic_read(&bat_priv->gw_sel_class) > 3) &&
 	    (orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw_sel_class)))
-		return;
+		goto out;
 
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Restarting gateway selection: better gateway found (tq curr: "
 		"%i, tq new: %i)\n",
 		gw_tq_avg, orig_tq_avg);
+	goto deselect;
 
+out_rcu:
+	rcu_read_unlock();
+	goto out;
+deselect_rcu:
+	rcu_read_unlock();
 deselect:
 	gw_deselect(bat_priv);
+out:
+	return;
 }
 
 static void gw_node_add(struct bat_priv *bat_priv,
@@ -242,7 +271,7 @@ static void gw_node_add(struct bat_priv *bat_priv,
 	memset(gw_node, 0, sizeof(struct gw_node));
 	INIT_HLIST_NODE(&gw_node->list);
 	gw_node->orig_node = orig_node;
-	kref_init(&gw_node->refcount);
+	atomic_set(&gw_node->refcount, 1);
 
 	spin_lock_bh(&bat_priv->gw_list_lock);
 	hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list);
@@ -283,7 +312,7 @@ void gw_node_update(struct bat_priv *bat_priv,
 				"Gateway %pM removed from gateway list\n",
 				orig_node->orig);
 
-			if (gw_node == bat_priv->curr_gw) {
+			if (gw_node == rcu_dereference(bat_priv->curr_gw)) {
 				rcu_read_unlock();
 				gw_deselect(bat_priv);
 				return;
@@ -321,11 +350,11 @@ void gw_node_purge(struct bat_priv *bat_priv)
 		    atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)
 			continue;
 
-		if (bat_priv->curr_gw == gw_node)
+		if (rcu_dereference(bat_priv->curr_gw) == gw_node)
 			gw_deselect(bat_priv);
 
 		hlist_del_rcu(&gw_node->list);
-		call_rcu(&gw_node->rcu, gw_node_free_rcu);
+		gw_node_free_ref(gw_node);
 	}
 
 
@@ -335,12 +364,16 @@ void gw_node_purge(struct bat_priv *bat_priv)
 static int _write_buffer_text(struct bat_priv *bat_priv,
 			      struct seq_file *seq, struct gw_node *gw_node)
 {
-	int down, up;
+	struct gw_node *curr_gw;
+	int down, up, ret;
 
 	gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up);
 
-	return seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
-		       (bat_priv->curr_gw == gw_node ? "=>" : "  "),
+	rcu_read_lock();
+	curr_gw = rcu_dereference(bat_priv->curr_gw);
+
+	ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n",
+		       (curr_gw == gw_node ? "=>" : "  "),
 		       gw_node->orig_node->orig,
 		       gw_node->orig_node->router->tq_avg,
 		       gw_node->orig_node->router->addr,
@@ -350,6 +383,9 @@ static int _write_buffer_text(struct bat_priv *bat_priv,
 		       (down > 2048 ? "MBit" : "KBit"),
 		       (up > 2048 ? up / 1024 : up),
 		       (up > 2048 ? "MBit" : "KBit"));
+
+	rcu_read_unlock();
+	return ret;
 }
 
 int gw_client_seq_print_text(struct seq_file *seq, void *offset)
@@ -470,8 +506,12 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)
 	if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)
 		return -1;
 
-	if (!bat_priv->curr_gw)
+	rcu_read_lock();
+	if (!rcu_dereference(bat_priv->curr_gw)) {
+		rcu_read_unlock();
 		return 0;
+	}
+	rcu_read_unlock();
 
 	return 1;
 }
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h
index 4585e65..2aa4391 100644
--- a/net/batman-adv/gateway_client.h
+++ b/net/batman-adv/gateway_client.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2009-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index b962982..50d3a59 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2009-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/gateway_common.h b/net/batman-adv/gateway_common.h
index 5e728d0..55e527a 100644
--- a/net/batman-adv/gateway_common.h
+++ b/net/batman-adv/gateway_common.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2009-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 4f95777..b3058e4 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -31,36 +31,40 @@
 
 #include <linux/if_arp.h>
 
-/* protect update critical side of if_list - but not the content */
-static DEFINE_SPINLOCK(if_list_lock);
+/* protect update critical side of hardif_list - but not the content */
+static DEFINE_SPINLOCK(hardif_list_lock);
 
-static void hardif_free_rcu(struct rcu_head *rcu)
+
+static int batman_skb_recv(struct sk_buff *skb,
+			   struct net_device *dev,
+			   struct packet_type *ptype,
+			   struct net_device *orig_dev);
+
+void hardif_free_rcu(struct rcu_head *rcu)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 
-	batman_if = container_of(rcu, struct batman_if, rcu);
-	dev_put(batman_if->net_dev);
-	kref_put(&batman_if->refcount, hardif_free_ref);
+	hard_iface = container_of(rcu, struct hard_iface, rcu);
+	dev_put(hard_iface->net_dev);
+	kfree(hard_iface);
 }
 
-struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
+struct hard_iface *hardif_get_by_netdev(struct net_device *net_dev)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if (batman_if->net_dev == net_dev)
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if (hard_iface->net_dev == net_dev &&
+		    atomic_inc_not_zero(&hard_iface->refcount))
 			goto out;
 	}
 
-	batman_if = NULL;
+	hard_iface = NULL;
 
 out:
-	if (batman_if)
-		kref_get(&batman_if->refcount);
-
 	rcu_read_unlock();
-	return batman_if;
+	return hard_iface;
 }
 
 static int is_valid_iface(struct net_device *net_dev)
@@ -75,13 +79,8 @@ static int is_valid_iface(struct net_device *net_dev)
 		return 0;
 
 	/* no batman over batman */
-#ifdef HAVE_NET_DEVICE_OPS
-	if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
-		return 0;
-#else
-	if (net_dev->hard_start_xmit == interface_tx)
+	if (softif_is_valid(net_dev))
 		return 0;
-#endif
 
 	/* Device is being bridged */
 	/* if (net_dev->priv_flags & IFF_BRIDGE_PORT)
@@ -90,27 +89,25 @@ static int is_valid_iface(struct net_device *net_dev)
 	return 1;
 }
 
-static struct batman_if *get_active_batman_if(struct net_device *soft_iface)
+static struct hard_iface *hardif_get_active(struct net_device *soft_iface)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if (batman_if->soft_iface != soft_iface)
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if (hard_iface->soft_iface != soft_iface)
 			continue;
 
-		if (batman_if->if_status == IF_ACTIVE)
+		if (hard_iface->if_status == IF_ACTIVE &&
+		    atomic_inc_not_zero(&hard_iface->refcount))
 			goto out;
 	}
 
-	batman_if = NULL;
+	hard_iface = NULL;
 
 out:
-	if (batman_if)
-		kref_get(&batman_if->refcount);
-
 	rcu_read_unlock();
-	return batman_if;
+	return hard_iface;
 }
 
 static void update_primary_addr(struct bat_priv *bat_priv)
@@ -126,24 +123,24 @@ static void update_primary_addr(struct bat_priv *bat_priv)
 }
 
 static void set_primary_if(struct bat_priv *bat_priv,
-			   struct batman_if *batman_if)
+			   struct hard_iface *hard_iface)
 {
 	struct batman_packet *batman_packet;
-	struct batman_if *old_if;
+	struct hard_iface *old_if;
 
-	if (batman_if)
-		kref_get(&batman_if->refcount);
+	if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount))
+		hard_iface = NULL;
 
 	old_if = bat_priv->primary_if;
-	bat_priv->primary_if = batman_if;
+	bat_priv->primary_if = hard_iface;
 
 	if (old_if)
-		kref_put(&old_if->refcount, hardif_free_ref);
+		hardif_free_ref(old_if);
 
 	if (!bat_priv->primary_if)
 		return;
 
-	batman_packet = (struct batman_packet *)(batman_if->packet_buff);
+	batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
 	batman_packet->flags = PRIMARIES_FIRST_HOP;
 	batman_packet->ttl = TTL;
 
@@ -156,42 +153,42 @@ static void set_primary_if(struct bat_priv *bat_priv,
 	atomic_set(&bat_priv->hna_local_changed, 1);
 }
 
-static bool hardif_is_iface_up(struct batman_if *batman_if)
+static bool hardif_is_iface_up(struct hard_iface *hard_iface)
 {
-	if (batman_if->net_dev->flags & IFF_UP)
+	if (hard_iface->net_dev->flags & IFF_UP)
 		return true;
 
 	return false;
 }
 
-static void update_mac_addresses(struct batman_if *batman_if)
+static void update_mac_addresses(struct hard_iface *hard_iface)
 {
-	memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
-	       batman_if->net_dev->dev_addr, ETH_ALEN);
-	memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
-	       batman_if->net_dev->dev_addr, ETH_ALEN);
+	memcpy(((struct batman_packet *)(hard_iface->packet_buff))->orig,
+	       hard_iface->net_dev->dev_addr, ETH_ALEN);
+	memcpy(((struct batman_packet *)(hard_iface->packet_buff))->prev_sender,
+	       hard_iface->net_dev->dev_addr, ETH_ALEN);
 }
 
 static void check_known_mac_addr(struct net_device *net_dev)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if ((batman_if->if_status != IF_ACTIVE) &&
-		    (batman_if->if_status != IF_TO_BE_ACTIVATED))
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if ((hard_iface->if_status != IF_ACTIVE) &&
+		    (hard_iface->if_status != IF_TO_BE_ACTIVATED))
 			continue;
 
-		if (batman_if->net_dev == net_dev)
+		if (hard_iface->net_dev == net_dev)
 			continue;
 
-		if (!compare_orig(batman_if->net_dev->dev_addr,
-				  net_dev->dev_addr))
+		if (!compare_eth(hard_iface->net_dev->dev_addr,
+				 net_dev->dev_addr))
 			continue;
 
 		pr_warning("The newly added mac address (%pM) already exists "
 			   "on: %s\n", net_dev->dev_addr,
-			   batman_if->net_dev->name);
+			   hard_iface->net_dev->name);
 		pr_warning("It is strongly recommended to keep mac addresses "
 			   "unique to avoid problems!\n");
 	}
@@ -201,7 +198,7 @@ static void check_known_mac_addr(struct net_device *net_dev)
 int hardif_min_mtu(struct net_device *soft_iface)
 {
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	/* allow big frames if all devices are capable to do so
 	 * (have MTU > 1500 + BAT_HEADER_LEN) */
 	int min_mtu = ETH_DATA_LEN;
@@ -210,15 +207,15 @@ int hardif_min_mtu(struct net_device *soft_iface)
 		goto out;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if ((batman_if->if_status != IF_ACTIVE) &&
-		    (batman_if->if_status != IF_TO_BE_ACTIVATED))
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if ((hard_iface->if_status != IF_ACTIVE) &&
+		    (hard_iface->if_status != IF_TO_BE_ACTIVATED))
 			continue;
 
-		if (batman_if->soft_iface != soft_iface)
+		if (hard_iface->soft_iface != soft_iface)
 			continue;
 
-		min_mtu = min_t(int, batman_if->net_dev->mtu - BAT_HEADER_LEN,
+		min_mtu = min_t(int, hard_iface->net_dev->mtu - BAT_HEADER_LEN,
 				min_mtu);
 	}
 	rcu_read_unlock();
@@ -236,77 +233,95 @@ void update_min_mtu(struct net_device *soft_iface)
 		soft_iface->mtu = min_mtu;
 }
 
-static void hardif_activate_interface(struct batman_if *batman_if)
+static void hardif_activate_interface(struct hard_iface *hard_iface)
 {
 	struct bat_priv *bat_priv;
 
-	if (batman_if->if_status != IF_INACTIVE)
+	if (hard_iface->if_status != IF_INACTIVE)
 		return;
 
-	bat_priv = netdev_priv(batman_if->soft_iface);
+	bat_priv = netdev_priv(hard_iface->soft_iface);
 
-	update_mac_addresses(batman_if);
-	batman_if->if_status = IF_TO_BE_ACTIVATED;
+	update_mac_addresses(hard_iface);
+	hard_iface->if_status = IF_TO_BE_ACTIVATED;
 
 	/**
 	 * the first active interface becomes our primary interface or
 	 * the next active interface after the old primay interface was removed
 	 */
 	if (!bat_priv->primary_if)
-		set_primary_if(bat_priv, batman_if);
+		set_primary_if(bat_priv, hard_iface);
 
-	bat_info(batman_if->soft_iface, "Interface activated: %s\n",
-		 batman_if->net_dev->name);
+	bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
+		 hard_iface->net_dev->name);
 
-	update_min_mtu(batman_if->soft_iface);
+	update_min_mtu(hard_iface->soft_iface);
 	return;
 }
 
-static void hardif_deactivate_interface(struct batman_if *batman_if)
+static void hardif_deactivate_interface(struct hard_iface *hard_iface)
 {
-	if ((batman_if->if_status != IF_ACTIVE) &&
-	   (batman_if->if_status != IF_TO_BE_ACTIVATED))
+	if ((hard_iface->if_status != IF_ACTIVE) &&
+	    (hard_iface->if_status != IF_TO_BE_ACTIVATED))
 		return;
 
-	batman_if->if_status = IF_INACTIVE;
+	hard_iface->if_status = IF_INACTIVE;
 
-	bat_info(batman_if->soft_iface, "Interface deactivated: %s\n",
-		 batman_if->net_dev->name);
+	bat_info(hard_iface->soft_iface, "Interface deactivated: %s\n",
+		 hard_iface->net_dev->name);
 
-	update_min_mtu(batman_if->soft_iface);
+	update_min_mtu(hard_iface->soft_iface);
 }
 
-int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
+int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
 {
 	struct bat_priv *bat_priv;
 	struct batman_packet *batman_packet;
+	struct net_device *soft_iface;
+	int ret;
 
-	if (batman_if->if_status != IF_NOT_IN_USE)
+	if (hard_iface->if_status != IF_NOT_IN_USE)
 		goto out;
 
-	batman_if->soft_iface = dev_get_by_name(&init_net, iface_name);
+	if (!atomic_inc_not_zero(&hard_iface->refcount))
+		goto out;
 
-	if (!batman_if->soft_iface) {
-		batman_if->soft_iface = softif_create(iface_name);
+	soft_iface = dev_get_by_name(&init_net, iface_name);
 
-		if (!batman_if->soft_iface)
+	if (!soft_iface) {
+		soft_iface = softif_create(iface_name);
+
+		if (!soft_iface) {
+			ret = -ENOMEM;
 			goto err;
+		}
 
 		/* dev_get_by_name() increases the reference counter for us */
-		dev_hold(batman_if->soft_iface);
+		dev_hold(soft_iface);
+	}
+
+	if (!softif_is_valid(soft_iface)) {
+		pr_err("Can't create batman mesh interface %s: "
+		       "already exists as regular interface\n",
+		       soft_iface->name);
+		dev_put(soft_iface);
+		ret = -EINVAL;
+		goto err;
 	}
 
-	bat_priv = netdev_priv(batman_if->soft_iface);
-	batman_if->packet_len = BAT_PACKET_LEN;
-	batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
+	hard_iface->soft_iface = soft_iface;
+	bat_priv = netdev_priv(hard_iface->soft_iface);
+	hard_iface->packet_len = BAT_PACKET_LEN;
+	hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
 
-	if (!batman_if->packet_buff) {
-		bat_err(batman_if->soft_iface, "Can't add interface packet "
-			"(%s): out of memory\n", batman_if->net_dev->name);
+	if (!hard_iface->packet_buff) {
+		bat_err(hard_iface->soft_iface, "Can't add interface packet "
+			"(%s): out of memory\n", hard_iface->net_dev->name);
+		ret = -ENOMEM;
 		goto err;
 	}
 
-	batman_packet = (struct batman_packet *)(batman_if->packet_buff);
+	batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
 	batman_packet->packet_type = BAT_PACKET;
 	batman_packet->version = COMPAT_VERSION;
 	batman_packet->flags = 0;
@@ -314,107 +329,107 @@ int hardif_enable_interface(struct batman_if *batman_if, char *iface_name)
 	batman_packet->tq = TQ_MAX_VALUE;
 	batman_packet->num_hna = 0;
 
-	batman_if->if_num = bat_priv->num_ifaces;
+	hard_iface->if_num = bat_priv->num_ifaces;
 	bat_priv->num_ifaces++;
-	batman_if->if_status = IF_INACTIVE;
-	orig_hash_add_if(batman_if, bat_priv->num_ifaces);
+	hard_iface->if_status = IF_INACTIVE;
+	orig_hash_add_if(hard_iface, bat_priv->num_ifaces);
 
-	batman_if->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN);
-	batman_if->batman_adv_ptype.func = batman_skb_recv;
-	batman_if->batman_adv_ptype.dev = batman_if->net_dev;
-	kref_get(&batman_if->refcount);
-	dev_add_pack(&batman_if->batman_adv_ptype);
+	hard_iface->batman_adv_ptype.type = __constant_htons(ETH_P_BATMAN);
+	hard_iface->batman_adv_ptype.func = batman_skb_recv;
+	hard_iface->batman_adv_ptype.dev = hard_iface->net_dev;
+	dev_add_pack(&hard_iface->batman_adv_ptype);
 
-	atomic_set(&batman_if->seqno, 1);
-	atomic_set(&batman_if->frag_seqno, 1);
-	bat_info(batman_if->soft_iface, "Adding interface: %s\n",
-		 batman_if->net_dev->name);
+	atomic_set(&hard_iface->seqno, 1);
+	atomic_set(&hard_iface->frag_seqno, 1);
+	bat_info(hard_iface->soft_iface, "Adding interface: %s\n",
+		 hard_iface->net_dev->name);
 
-	if (atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu <
+	if (atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu <
 		ETH_DATA_LEN + BAT_HEADER_LEN)
-		bat_info(batman_if->soft_iface,
+		bat_info(hard_iface->soft_iface,
 			"The MTU of interface %s is too small (%i) to handle "
 			"the transport of batman-adv packets. Packets going "
 			"over this interface will be fragmented on layer2 "
 			"which could impact the performance. Setting the MTU "
 			"to %zi would solve the problem.\n",
-			batman_if->net_dev->name, batman_if->net_dev->mtu,
+			hard_iface->net_dev->name, hard_iface->net_dev->mtu,
 			ETH_DATA_LEN + BAT_HEADER_LEN);
 
-	if (!atomic_read(&bat_priv->fragmentation) && batman_if->net_dev->mtu <
+	if (!atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu <
 		ETH_DATA_LEN + BAT_HEADER_LEN)
-		bat_info(batman_if->soft_iface,
+		bat_info(hard_iface->soft_iface,
 			"The MTU of interface %s is too small (%i) to handle "
 			"the transport of batman-adv packets. If you experience"
 			" problems getting traffic through try increasing the "
 			"MTU to %zi.\n",
-			batman_if->net_dev->name, batman_if->net_dev->mtu,
+			hard_iface->net_dev->name, hard_iface->net_dev->mtu,
 			ETH_DATA_LEN + BAT_HEADER_LEN);
 
-	if (hardif_is_iface_up(batman_if))
-		hardif_activate_interface(batman_if);
+	if (hardif_is_iface_up(hard_iface))
+		hardif_activate_interface(hard_iface);
 	else
-		bat_err(batman_if->soft_iface, "Not using interface %s "
+		bat_err(hard_iface->soft_iface, "Not using interface %s "
 			"(retrying later): interface not active\n",
-			batman_if->net_dev->name);
+			hard_iface->net_dev->name);
 
 	/* begin scheduling originator messages on that interface */
-	schedule_own_packet(batman_if);
+	schedule_own_packet(hard_iface);
 
 out:
 	return 0;
 
 err:
-	return -ENOMEM;
+	hardif_free_ref(hard_iface);
+	return ret;
 }
 
-void hardif_disable_interface(struct batman_if *batman_if)
+void hardif_disable_interface(struct hard_iface *hard_iface)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 
-	if (batman_if->if_status == IF_ACTIVE)
-		hardif_deactivate_interface(batman_if);
+	if (hard_iface->if_status == IF_ACTIVE)
+		hardif_deactivate_interface(hard_iface);
 
-	if (batman_if->if_status != IF_INACTIVE)
+	if (hard_iface->if_status != IF_INACTIVE)
 		return;
 
-	bat_info(batman_if->soft_iface, "Removing interface: %s\n",
-		 batman_if->net_dev->name);
-	dev_remove_pack(&batman_if->batman_adv_ptype);
-	kref_put(&batman_if->refcount, hardif_free_ref);
+	bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
+		 hard_iface->net_dev->name);
+	dev_remove_pack(&hard_iface->batman_adv_ptype);
 
 	bat_priv->num_ifaces--;
-	orig_hash_del_if(batman_if, bat_priv->num_ifaces);
+	orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
 
-	if (batman_if == bat_priv->primary_if) {
-		struct batman_if *new_if;
+	if (hard_iface == bat_priv->primary_if) {
+		struct hard_iface *new_if;
 
-		new_if = get_active_batman_if(batman_if->soft_iface);
+		new_if = hardif_get_active(hard_iface->soft_iface);
 		set_primary_if(bat_priv, new_if);
 
 		if (new_if)
-			kref_put(&new_if->refcount, hardif_free_ref);
+			hardif_free_ref(new_if);
 	}
 
-	kfree(batman_if->packet_buff);
-	batman_if->packet_buff = NULL;
-	batman_if->if_status = IF_NOT_IN_USE;
+	kfree(hard_iface->packet_buff);
+	hard_iface->packet_buff = NULL;
+	hard_iface->if_status = IF_NOT_IN_USE;
 
-	/* delete all references to this batman_if */
+	/* delete all references to this hard_iface */
 	purge_orig_ref(bat_priv);
-	purge_outstanding_packets(bat_priv, batman_if);
-	dev_put(batman_if->soft_iface);
+	purge_outstanding_packets(bat_priv, hard_iface);
+	dev_put(hard_iface->soft_iface);
 
 	/* nobody uses this interface anymore */
 	if (!bat_priv->num_ifaces)
-		softif_destroy(batman_if->soft_iface);
+		softif_destroy(hard_iface->soft_iface);
 
-	batman_if->soft_iface = NULL;
+	hard_iface->soft_iface = NULL;
+	hardif_free_ref(hard_iface);
 }
 
-static struct batman_if *hardif_add_interface(struct net_device *net_dev)
+static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	int ret;
 
 	ret = is_valid_iface(net_dev);
@@ -423,73 +438,73 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
 
 	dev_hold(net_dev);
 
-	batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
-	if (!batman_if) {
+	hard_iface = kmalloc(sizeof(struct hard_iface), GFP_ATOMIC);
+	if (!hard_iface) {
 		pr_err("Can't add interface (%s): out of memory\n",
 		       net_dev->name);
 		goto release_dev;
 	}
 
-	ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev);
+	ret = sysfs_add_hardif(&hard_iface->hardif_obj, net_dev);
 	if (ret)
 		goto free_if;
 
-	batman_if->if_num = -1;
-	batman_if->net_dev = net_dev;
-	batman_if->soft_iface = NULL;
-	batman_if->if_status = IF_NOT_IN_USE;
-	INIT_LIST_HEAD(&batman_if->list);
-	kref_init(&batman_if->refcount);
+	hard_iface->if_num = -1;
+	hard_iface->net_dev = net_dev;
+	hard_iface->soft_iface = NULL;
+	hard_iface->if_status = IF_NOT_IN_USE;
+	INIT_LIST_HEAD(&hard_iface->list);
+	/* extra reference for return */
+	atomic_set(&hard_iface->refcount, 2);
 
-	check_known_mac_addr(batman_if->net_dev);
+	check_known_mac_addr(hard_iface->net_dev);
 
-	spin_lock(&if_list_lock);
-	list_add_tail_rcu(&batman_if->list, &if_list);
-	spin_unlock(&if_list_lock);
+	spin_lock(&hardif_list_lock);
+	list_add_tail_rcu(&hard_iface->list, &hardif_list);
+	spin_unlock(&hardif_list_lock);
 
-	/* extra reference for return */
-	kref_get(&batman_if->refcount);
-	return batman_if;
+	return hard_iface;
 
 free_if:
-	kfree(batman_if);
+	kfree(hard_iface);
 release_dev:
 	dev_put(net_dev);
 out:
 	return NULL;
 }
 
-static void hardif_remove_interface(struct batman_if *batman_if)
+static void hardif_remove_interface(struct hard_iface *hard_iface)
 {
 	/* first deactivate interface */
-	if (batman_if->if_status != IF_NOT_IN_USE)
-		hardif_disable_interface(batman_if);
+	if (hard_iface->if_status != IF_NOT_IN_USE)
+		hardif_disable_interface(hard_iface);
 
-	if (batman_if->if_status != IF_NOT_IN_USE)
+	if (hard_iface->if_status != IF_NOT_IN_USE)
 		return;
 
-	batman_if->if_status = IF_TO_BE_REMOVED;
-	sysfs_del_hardif(&batman_if->hardif_obj);
-	call_rcu(&batman_if->rcu, hardif_free_rcu);
+	hard_iface->if_status = IF_TO_BE_REMOVED;
+	sysfs_del_hardif(&hard_iface->hardif_obj);
+	hardif_free_ref(hard_iface);
 }
 
 void hardif_remove_interfaces(void)
 {
-	struct batman_if *batman_if, *batman_if_tmp;
+	struct hard_iface *hard_iface, *hard_iface_tmp;
 	struct list_head if_queue;
 
 	INIT_LIST_HEAD(&if_queue);
 
-	spin_lock(&if_list_lock);
-	list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list) {
-		list_del_rcu(&batman_if->list);
-		list_add_tail(&batman_if->list, &if_queue);
+	spin_lock(&hardif_list_lock);
+	list_for_each_entry_safe(hard_iface, hard_iface_tmp,
+				 &hardif_list, list) {
+		list_del_rcu(&hard_iface->list);
+		list_add_tail(&hard_iface->list, &if_queue);
 	}
-	spin_unlock(&if_list_lock);
+	spin_unlock(&hardif_list_lock);
 
 	rtnl_lock();
-	list_for_each_entry_safe(batman_if, batman_if_tmp, &if_queue, list) {
-		hardif_remove_interface(batman_if);
+	list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) {
+		hardif_remove_interface(hard_iface);
 	}
 	rtnl_unlock();
 }
@@ -498,43 +513,43 @@ static int hard_if_event(struct notifier_block *this,
 			 unsigned long event, void *ptr)
 {
 	struct net_device *net_dev = (struct net_device *)ptr;
-	struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
+	struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
 	struct bat_priv *bat_priv;
 
-	if (!batman_if && event == NETDEV_REGISTER)
-		batman_if = hardif_add_interface(net_dev);
+	if (!hard_iface && event == NETDEV_REGISTER)
+		hard_iface = hardif_add_interface(net_dev);
 
-	if (!batman_if)
+	if (!hard_iface)
 		goto out;
 
 	switch (event) {
 	case NETDEV_UP:
-		hardif_activate_interface(batman_if);
+		hardif_activate_interface(hard_iface);
 		break;
 	case NETDEV_GOING_DOWN:
 	case NETDEV_DOWN:
-		hardif_deactivate_interface(batman_if);
+		hardif_deactivate_interface(hard_iface);
 		break;
 	case NETDEV_UNREGISTER:
-		spin_lock(&if_list_lock);
-		list_del_rcu(&batman_if->list);
-		spin_unlock(&if_list_lock);
+		spin_lock(&hardif_list_lock);
+		list_del_rcu(&hard_iface->list);
+		spin_unlock(&hardif_list_lock);
 
-		hardif_remove_interface(batman_if);
+		hardif_remove_interface(hard_iface);
 		break;
 	case NETDEV_CHANGEMTU:
-		if (batman_if->soft_iface)
-			update_min_mtu(batman_if->soft_iface);
+		if (hard_iface->soft_iface)
+			update_min_mtu(hard_iface->soft_iface);
 		break;
 	case NETDEV_CHANGEADDR:
-		if (batman_if->if_status == IF_NOT_IN_USE)
+		if (hard_iface->if_status == IF_NOT_IN_USE)
 			goto hardif_put;
 
-		check_known_mac_addr(batman_if->net_dev);
-		update_mac_addresses(batman_if);
+		check_known_mac_addr(hard_iface->net_dev);
+		update_mac_addresses(hard_iface);
 
-		bat_priv = netdev_priv(batman_if->soft_iface);
-		if (batman_if == bat_priv->primary_if)
+		bat_priv = netdev_priv(hard_iface->soft_iface);
+		if (hard_iface == bat_priv->primary_if)
 			update_primary_addr(bat_priv);
 		break;
 	default:
@@ -542,22 +557,23 @@ static int hard_if_event(struct notifier_block *this,
 	};
 
 hardif_put:
-	kref_put(&batman_if->refcount, hardif_free_ref);
+	hardif_free_ref(hard_iface);
 out:
 	return NOTIFY_DONE;
 }
 
 /* receive a packet with the batman ethertype coming on a hard
  * interface */
-int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
-	struct packet_type *ptype, struct net_device *orig_dev)
+static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
+			   struct packet_type *ptype,
+			   struct net_device *orig_dev)
 {
 	struct bat_priv *bat_priv;
 	struct batman_packet *batman_packet;
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	int ret;
 
-	batman_if = container_of(ptype, struct batman_if, batman_adv_ptype);
+	hard_iface = container_of(ptype, struct hard_iface, batman_adv_ptype);
 	skb = skb_share_check(skb, GFP_ATOMIC);
 
 	/* skb was released by skb_share_check() */
@@ -573,16 +589,16 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 				|| !skb_mac_header(skb)))
 		goto err_free;
 
-	if (!batman_if->soft_iface)
+	if (!hard_iface->soft_iface)
 		goto err_free;
 
-	bat_priv = netdev_priv(batman_if->soft_iface);
+	bat_priv = netdev_priv(hard_iface->soft_iface);
 
 	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
 		goto err_free;
 
 	/* discard frames on not active interfaces */
-	if (batman_if->if_status != IF_ACTIVE)
+	if (hard_iface->if_status != IF_ACTIVE)
 		goto err_free;
 
 	batman_packet = (struct batman_packet *)skb->data;
@@ -600,32 +616,32 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 	switch (batman_packet->packet_type) {
 		/* batman originator packet */
 	case BAT_PACKET:
-		ret = recv_bat_packet(skb, batman_if);
+		ret = recv_bat_packet(skb, hard_iface);
 		break;
 
 		/* batman icmp packet */
 	case BAT_ICMP:
-		ret = recv_icmp_packet(skb, batman_if);
+		ret = recv_icmp_packet(skb, hard_iface);
 		break;
 
 		/* unicast packet */
 	case BAT_UNICAST:
-		ret = recv_unicast_packet(skb, batman_if);
+		ret = recv_unicast_packet(skb, hard_iface);
 		break;
 
 		/* fragmented unicast packet */
 	case BAT_UNICAST_FRAG:
-		ret = recv_ucast_frag_packet(skb, batman_if);
+		ret = recv_ucast_frag_packet(skb, hard_iface);
 		break;
 
 		/* broadcast packet */
 	case BAT_BCAST:
-		ret = recv_bcast_packet(skb, batman_if);
+		ret = recv_bcast_packet(skb, hard_iface);
 		break;
 
 		/* vis packet */
 	case BAT_VIS:
-		ret = recv_vis_packet(skb, batman_if);
+		ret = recv_vis_packet(skb, hard_iface);
 		break;
 	default:
 		ret = NET_RX_DROP;
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 30ec3b8..a9ddf36 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -31,23 +31,18 @@
 
 extern struct notifier_block hard_if_notifier;
 
-struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev);
-int hardif_enable_interface(struct batman_if *batman_if, char *iface_name);
-void hardif_disable_interface(struct batman_if *batman_if);
+struct hard_iface *hardif_get_by_netdev(struct net_device *net_dev);
+int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name);
+void hardif_disable_interface(struct hard_iface *hard_iface);
 void hardif_remove_interfaces(void);
-int batman_skb_recv(struct sk_buff *skb,
-				struct net_device *dev,
-				struct packet_type *ptype,
-				struct net_device *orig_dev);
 int hardif_min_mtu(struct net_device *soft_iface);
 void update_min_mtu(struct net_device *soft_iface);
+void hardif_free_rcu(struct rcu_head *rcu);
 
-static inline void hardif_free_ref(struct kref *refcount)
+static inline void hardif_free_ref(struct hard_iface *hard_iface)
 {
-	struct batman_if *batman_if;
-
-	batman_if = container_of(refcount, struct batman_if, refcount);
-	kfree(batman_if);
+	if (atomic_dec_and_test(&hard_iface->refcount))
+		call_rcu(&hard_iface->rcu, hardif_free_rcu);
 }
 
 #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c
index 26e623e..c5213d8 100644
--- a/net/batman-adv/hash.c
+++ b/net/batman-adv/hash.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2006-2011 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
@@ -27,13 +27,16 @@ static void hash_init(struct hashtable_t *hash)
 {
 	int i;
 
-	for (i = 0 ; i < hash->size; i++)
+	for (i = 0 ; i < hash->size; i++) {
 		INIT_HLIST_HEAD(&hash->table[i]);
+		spin_lock_init(&hash->list_locks[i]);
+	}
 }
 
 /* free only the hashtable and the hash itself. */
 void hash_destroy(struct hashtable_t *hash)
 {
+	kfree(hash->list_locks);
 	kfree(hash->table);
 	kfree(hash);
 }
@@ -43,20 +46,25 @@ struct hashtable_t *hash_new(int size)
 {
 	struct hashtable_t *hash;
 
-	hash = kmalloc(sizeof(struct hashtable_t) , GFP_ATOMIC);
-
+	hash = kmalloc(sizeof(struct hashtable_t), GFP_ATOMIC);
 	if (!hash)
 		return NULL;
 
-	hash->size = size;
 	hash->table = kmalloc(sizeof(struct element_t *) * size, GFP_ATOMIC);
+	if (!hash->table)
+		goto free_hash;
 
-	if (!hash->table) {
-		kfree(hash);
-		return NULL;
-	}
+	hash->list_locks = kmalloc(sizeof(spinlock_t) * size, GFP_ATOMIC);
+	if (!hash->list_locks)
+		goto free_table;
 
+	hash->size = size;
 	hash_init(hash);
-
 	return hash;
+
+free_table:
+	kfree(hash->table);
+free_hash:
+	kfree(hash);
+	return NULL;
 }
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h
index 09216ad..434822b 100644
--- a/net/batman-adv/hash.h
+++ b/net/batman-adv/hash.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2006-2011 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
@@ -28,32 +28,23 @@
  * compare 2 element datas for their keys,
  * return 0 if same and not 0 if not
  * same */
-typedef int (*hashdata_compare_cb)(void *, void *);
+typedef int (*hashdata_compare_cb)(struct hlist_node *, void *);
 
 /* the hashfunction, should return an index
  * based on the key in the data of the first
  * argument and the size the second */
 typedef int (*hashdata_choose_cb)(void *, int);
-typedef void (*hashdata_free_cb)(void *, void *);
-
-struct element_t {
-	void *data;		/* pointer to the data */
-	struct hlist_node hlist;	/* bucket list pointer */
-};
+typedef void (*hashdata_free_cb)(struct hlist_node *, void *);
 
 struct hashtable_t {
-	struct hlist_head *table;   /* the hashtable itself, with the buckets */
+	struct hlist_head *table;   /* the hashtable itself with the buckets */
+	spinlock_t *list_locks;     /* spinlock for each hash list entry */
 	int size;		    /* size of hashtable */
 };
 
 /* allocates and clears the hash */
 struct hashtable_t *hash_new(int size);
 
-/* remove element if you already found the element you want to delete and don't
- * need the overhead to find it again with hash_remove().  But usually, you
- * don't want to use this function, as it fiddles with hash-internals. */
-void *hash_remove_element(struct hashtable_t *hash, struct element_t *elem);
-
 /* free only the hashtable and the hash itself. */
 void hash_destroy(struct hashtable_t *hash);
 
@@ -64,21 +55,22 @@ static inline void hash_delete(struct hashtable_t *hash,
 			       hashdata_free_cb free_cb, void *arg)
 {
 	struct hlist_head *head;
-	struct hlist_node *walk, *safe;
-	struct element_t *bucket;
+	struct hlist_node *node, *node_tmp;
+	spinlock_t *list_lock; /* spinlock to protect write access */
 	int i;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
 
-		hlist_for_each_safe(walk, safe, head) {
-			bucket = hlist_entry(walk, struct element_t, hlist);
-			if (free_cb)
-				free_cb(bucket->data, arg);
+		spin_lock_bh(list_lock);
+		hlist_for_each_safe(node, node_tmp, head) {
+			hlist_del_rcu(node);
 
-			hlist_del(walk);
-			kfree(bucket);
+			if (free_cb)
+				free_cb(node, arg);
 		}
+		spin_unlock_bh(list_lock);
 	}
 
 	hash_destroy(hash);
@@ -87,35 +79,41 @@ static inline void hash_delete(struct hashtable_t *hash,
 /* adds data to the hashtable. returns 0 on success, -1 on error */
 static inline int hash_add(struct hashtable_t *hash,
 			   hashdata_compare_cb compare,
-			   hashdata_choose_cb choose, void *data)
+			   hashdata_choose_cb choose,
+			   void *data, struct hlist_node *data_node)
 {
 	int index;
 	struct hlist_head *head;
-	struct hlist_node *walk, *safe;
-	struct element_t *bucket;
+	struct hlist_node *node;
+	spinlock_t *list_lock; /* spinlock to protect write access */
 
 	if (!hash)
-		return -1;
+		goto err;
 
 	index = choose(data, hash->size);
 	head = &hash->table[index];
+	list_lock = &hash->list_locks[index];
+
+	rcu_read_lock();
+	__hlist_for_each_rcu(node, head) {
+		if (!compare(node, data))
+			continue;
 
-	hlist_for_each_safe(walk, safe, head) {
-		bucket = hlist_entry(walk, struct element_t, hlist);
-		if (compare(bucket->data, data))
-			return -1;
+		goto err_unlock;
 	}
+	rcu_read_unlock();
 
 	/* no duplicate found in list, add new element */
-	bucket = kmalloc(sizeof(struct element_t), GFP_ATOMIC);
-
-	if (!bucket)
-		return -1;
-
-	bucket->data = data;
-	hlist_add_head(&bucket->hlist, head);
+	spin_lock_bh(list_lock);
+	hlist_add_head_rcu(data_node, head);
+	spin_unlock_bh(list_lock);
 
 	return 0;
+
+err_unlock:
+	rcu_read_unlock();
+err:
+	return -1;
 }
 
 /* removes data from hash, if found. returns pointer do data on success, so you
@@ -127,50 +125,25 @@ static inline void *hash_remove(struct hashtable_t *hash,
 				hashdata_choose_cb choose, void *data)
 {
 	size_t index;
-	struct hlist_node *walk;
-	struct element_t *bucket;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	void *data_save;
+	void *data_save = NULL;
 
 	index = choose(data, hash->size);
 	head = &hash->table[index];
 
-	hlist_for_each_entry(bucket, walk, head, hlist) {
-		if (compare(bucket->data, data)) {
-			data_save = bucket->data;
-			hlist_del(walk);
-			kfree(bucket);
-			return data_save;
-		}
-	}
-
-	return NULL;
-}
-
-/* finds data, based on the key in keydata. returns the found data on success,
- * or NULL on error */
-static inline void *hash_find(struct hashtable_t *hash,
-			      hashdata_compare_cb compare,
-			      hashdata_choose_cb choose, void *keydata)
-{
-	int index;
-	struct hlist_head *head;
-	struct hlist_node *walk;
-	struct element_t *bucket;
-
-	if (!hash)
-		return NULL;
-
-	index = choose(keydata , hash->size);
-	head = &hash->table[index];
+	spin_lock_bh(&hash->list_locks[index]);
+	hlist_for_each(node, head) {
+		if (!compare(node, data))
+			continue;
 
-	hlist_for_each(walk, head) {
-		bucket = hlist_entry(walk, struct element_t, hlist);
-		if (compare(bucket->data, keydata))
-			return bucket->data;
+		data_save = node;
+		hlist_del_rcu(node);
+		break;
 	}
+	spin_unlock_bh(&hash->list_locks[index]);
 
-	return NULL;
+	return data_save;
 }
 
 #endif /* _NET_BATMAN_ADV_HASH_H_ */
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c
index ecf6d7f..34ce56c 100644
--- a/net/batman-adv/icmp_socket.c
+++ b/net/batman-adv/icmp_socket.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -24,7 +24,6 @@
 #include <linux/slab.h>
 #include "icmp_socket.h"
 #include "send.h"
-#include "types.h"
 #include "hash.h"
 #include "originator.h"
 #include "hard-interface.h"
@@ -157,10 +156,9 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
 	struct sk_buff *skb;
 	struct icmp_packet_rr *icmp_packet;
 
-	struct orig_node *orig_node;
-	struct batman_if *batman_if;
+	struct orig_node *orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
 	size_t packet_len = sizeof(struct icmp_packet);
-	uint8_t dstaddr[ETH_ALEN];
 
 	if (len < sizeof(struct icmp_packet)) {
 		bat_dbg(DBG_BATMAN, bat_priv,
@@ -220,47 +218,52 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
 	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
 		goto dst_unreach;
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
-						   compare_orig, choose_orig,
-						   icmp_packet->dst));
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
 
 	if (!orig_node)
 		goto unlock;
 
-	if (!orig_node->router)
+	neigh_node = orig_node->router;
+
+	if (!neigh_node)
 		goto unlock;
 
-	batman_if = orig_node->router->if_incoming;
-	memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+		neigh_node = NULL;
+		goto unlock;
+	}
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	rcu_read_unlock();
 
-	if (!batman_if)
+	if (!neigh_node->if_incoming)
 		goto dst_unreach;
 
-	if (batman_if->if_status != IF_ACTIVE)
+	if (neigh_node->if_incoming->if_status != IF_ACTIVE)
 		goto dst_unreach;
 
 	memcpy(icmp_packet->orig,
 	       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
 
 	if (packet_len == sizeof(struct icmp_packet_rr))
-		memcpy(icmp_packet->rr, batman_if->net_dev->dev_addr, ETH_ALEN);
-
-
-	send_skb_packet(skb, batman_if, dstaddr);
+		memcpy(icmp_packet->rr,
+		       neigh_node->if_incoming->net_dev->dev_addr, ETH_ALEN);
 
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
 	goto out;
 
 unlock:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	rcu_read_unlock();
 dst_unreach:
 	icmp_packet->msg_type = DESTINATION_UNREACHABLE;
 	bat_socket_add_packet(socket_client, icmp_packet, packet_len);
 free_skb:
 	kfree_skb(skb);
 out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
 	return len;
 }
 
diff --git a/net/batman-adv/icmp_socket.h b/net/batman-adv/icmp_socket.h
index bf9b348..462b190 100644
--- a/net/batman-adv/icmp_socket.h
+++ b/net/batman-adv/icmp_socket.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -22,8 +22,6 @@
 #ifndef _NET_BATMAN_ADV_ICMP_SOCKET_H_
 #define _NET_BATMAN_ADV_ICMP_SOCKET_H_
 
-#include "types.h"
-
 #define ICMP_SOCKET "socket"
 
 void bat_socket_init(void);
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b827f6a..709b33b 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -30,11 +30,10 @@
 #include "translation-table.h"
 #include "hard-interface.h"
 #include "gateway_client.h"
-#include "types.h"
 #include "vis.h"
 #include "hash.h"
 
-struct list_head if_list;
+struct list_head hardif_list;
 
 unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
@@ -42,7 +41,7 @@ struct workqueue_struct *bat_event_workqueue;
 
 static int __init batman_init(void)
 {
-	INIT_LIST_HEAD(&if_list);
+	INIT_LIST_HEAD(&hardif_list);
 
 	/* the name should not be longer than 10 chars - see
 	 * http://lwn.net/Articles/23634/ */
@@ -80,7 +79,6 @@ int mesh_init(struct net_device *soft_iface)
 {
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
 
-	spin_lock_init(&bat_priv->orig_hash_lock);
 	spin_lock_init(&bat_priv->forw_bat_list_lock);
 	spin_lock_init(&bat_priv->forw_bcast_list_lock);
 	spin_lock_init(&bat_priv->hna_lhash_lock);
@@ -155,14 +153,14 @@ void dec_module_count(void)
 
 int is_my_mac(uint8_t *addr)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if (batman_if->if_status != IF_ACTIVE)
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if (hard_iface->if_status != IF_ACTIVE)
 			continue;
 
-		if (compare_orig(batman_if->net_dev->dev_addr, addr)) {
+		if (compare_eth(hard_iface->net_dev->dev_addr, addr)) {
 			rcu_read_unlock();
 			return 1;
 		}
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index 65106fb..dc24869 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -22,9 +22,6 @@
 #ifndef _NET_BATMAN_ADV_MAIN_H_
 #define _NET_BATMAN_ADV_MAIN_H_
 
-/* Kernel Programming */
-#define LINUX
-
 #define DRIVER_AUTHOR "Marek Lindner <lindner_marek@yahoo.de>, " \
 		      "Simon Wunderlich <siwu@hrz.tu-chemnitz.de>"
 #define DRIVER_DESC   "B.A.T.M.A.N. advanced"
@@ -54,7 +51,6 @@
 
 #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE)
 
-#define PACKBUFF_SIZE 2000
 #define LOG_BUF_LEN 8192	  /* has to be a power of 2 */
 
 #define VIS_INTERVAL 5000	/* 5 seconds */
@@ -96,15 +92,11 @@
 #define DBG_ROUTES 2	/* route or hna added / changed / deleted */
 #define DBG_ALL 3
 
-#define LOG_BUF_LEN 8192          /* has to be a power of 2 */
-
 
 /*
  *  Vis
  */
 
-/* #define VIS_SUBCLUSTERS_DISABLED */
-
 /*
  * Kernel headers
  */
@@ -130,7 +122,7 @@
 #define REVISION_VERSION_STR " "REVISION_VERSION
 #endif
 
-extern struct list_head if_list;
+extern struct list_head hardif_list;
 
 extern unsigned char broadcast_addr[];
 extern struct workqueue_struct *bat_event_workqueue;
@@ -158,13 +150,6 @@ static inline void bat_dbg(char type __always_unused,
 }
 #endif
 
-#define bat_warning(net_dev, fmt, arg...)				\
-	do {								\
-		struct net_device *_netdev = (net_dev);                 \
-		struct bat_priv *_batpriv = netdev_priv(_netdev);       \
-		bat_dbg(DBG_ALL, _batpriv, fmt, ## arg);		\
-		pr_warning("%s: " fmt, _netdev->name, ## arg);		\
-	} while (0)
 #define bat_info(net_dev, fmt, arg...)					\
 	do {								\
 		struct net_device *_netdev = (net_dev);                 \
@@ -180,4 +165,14 @@ static inline void bat_dbg(char type __always_unused,
 		pr_err("%s: " fmt, _netdev->name, ## arg);		\
 	} while (0)
 
+/**
+ * returns 1 if they are the same ethernet addr
+ *
+ * note: can't use compare_ether_addr() as it requires aligned memory
+ */
+static inline int compare_eth(void *data1, void *data2)
+{
+	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
 #endif /* _NET_BATMAN_ADV_MAIN_H_ */
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 6b7fb6b..0b91330 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2009-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -44,24 +44,36 @@ int originator_init(struct bat_priv *bat_priv)
 	if (bat_priv->orig_hash)
 		return 1;
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
 	bat_priv->orig_hash = hash_new(1024);
 
 	if (!bat_priv->orig_hash)
 		goto err;
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
 	start_purge_timer(bat_priv);
 	return 1;
 
 err:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
 	return 0;
 }
 
-struct neigh_node *
-create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
-		uint8_t *neigh, struct batman_if *if_incoming)
+static void neigh_node_free_rcu(struct rcu_head *rcu)
+{
+	struct neigh_node *neigh_node;
+
+	neigh_node = container_of(rcu, struct neigh_node, rcu);
+	kfree(neigh_node);
+}
+
+void neigh_node_free_ref(struct neigh_node *neigh_node)
+{
+	if (atomic_dec_and_test(&neigh_node->refcount))
+		call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
+}
+
+struct neigh_node *create_neighbor(struct orig_node *orig_node,
+				   struct orig_node *orig_neigh_node,
+				   uint8_t *neigh,
+				   struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	struct neigh_node *neigh_node;
@@ -73,50 +85,94 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
 	if (!neigh_node)
 		return NULL;
 
-	INIT_LIST_HEAD(&neigh_node->list);
+	INIT_HLIST_NODE(&neigh_node->list);
+	INIT_LIST_HEAD(&neigh_node->bonding_list);
 
 	memcpy(neigh_node->addr, neigh, ETH_ALEN);
 	neigh_node->orig_node = orig_neigh_node;
 	neigh_node->if_incoming = if_incoming;
 
-	list_add_tail(&neigh_node->list, &orig_node->neigh_list);
+	/* extra reference for return */
+	atomic_set(&neigh_node->refcount, 2);
+
+	spin_lock_bh(&orig_node->neigh_list_lock);
+	hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
+	spin_unlock_bh(&orig_node->neigh_list_lock);
 	return neigh_node;
 }
 
-static void free_orig_node(void *data, void *arg)
+static void orig_node_free_rcu(struct rcu_head *rcu)
 {
-	struct list_head *list_pos, *list_pos_tmp;
-	struct neigh_node *neigh_node;
-	struct orig_node *orig_node = (struct orig_node *)data;
-	struct bat_priv *bat_priv = (struct bat_priv *)arg;
+	struct hlist_node *node, *node_tmp;
+	struct neigh_node *neigh_node, *tmp_neigh_node;
+	struct orig_node *orig_node;
 
-	/* for all neighbors towards this originator ... */
-	list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
-		neigh_node = list_entry(list_pos, struct neigh_node, list);
+	orig_node = container_of(rcu, struct orig_node, rcu);
+
+	spin_lock_bh(&orig_node->neigh_list_lock);
+
+	/* for all bonding members ... */
+	list_for_each_entry_safe(neigh_node, tmp_neigh_node,
+				 &orig_node->bond_list, bonding_list) {
+		list_del_rcu(&neigh_node->bonding_list);
+		neigh_node_free_ref(neigh_node);
+	}
 
-		list_del(list_pos);
-		kfree(neigh_node);
+	/* for all neighbors towards this originator ... */
+	hlist_for_each_entry_safe(neigh_node, node, node_tmp,
+				  &orig_node->neigh_list, list) {
+		hlist_del_rcu(&neigh_node->list);
+		neigh_node_free_ref(neigh_node);
 	}
 
+	spin_unlock_bh(&orig_node->neigh_list_lock);
+
 	frag_list_free(&orig_node->frag_list);
-	hna_global_del_orig(bat_priv, orig_node, "originator timed out");
+	hna_global_del_orig(orig_node->bat_priv, orig_node,
+			    "originator timed out");
 
 	kfree(orig_node->bcast_own);
 	kfree(orig_node->bcast_own_sum);
 	kfree(orig_node);
 }
 
+void orig_node_free_ref(struct orig_node *orig_node)
+{
+	if (atomic_dec_and_test(&orig_node->refcount))
+		call_rcu(&orig_node->rcu, orig_node_free_rcu);
+}
+
 void originator_free(struct bat_priv *bat_priv)
 {
-	if (!bat_priv->orig_hash)
+	struct hashtable_t *hash = bat_priv->orig_hash;
+	struct hlist_node *node, *node_tmp;
+	struct hlist_head *head;
+	spinlock_t *list_lock; /* spinlock to protect write access */
+	struct orig_node *orig_node;
+	int i;
+
+	if (!hash)
 		return;
 
 	cancel_delayed_work_sync(&bat_priv->orig_work);
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	hash_delete(bat_priv->orig_hash, free_orig_node, bat_priv);
 	bat_priv->orig_hash = NULL;
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+
+	for (i = 0; i < hash->size; i++) {
+		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
+
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(orig_node, node, node_tmp,
+					  head, hash_entry) {
+
+			hlist_del_rcu(node);
+			orig_node_free_ref(orig_node);
+		}
+		spin_unlock_bh(list_lock);
+	}
+
+	hash_destroy(hash);
 }
 
 /* this function finds or creates an originator entry for the given
@@ -127,10 +183,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
 	int size;
 	int hash_added;
 
-	orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
-						   compare_orig, choose_orig,
-						   addr));
-
+	orig_node = orig_hash_find(bat_priv, addr);
 	if (orig_node)
 		return orig_node;
 
@@ -141,8 +194,16 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
 	if (!orig_node)
 		return NULL;
 
-	INIT_LIST_HEAD(&orig_node->neigh_list);
+	INIT_HLIST_HEAD(&orig_node->neigh_list);
+	INIT_LIST_HEAD(&orig_node->bond_list);
+	spin_lock_init(&orig_node->ogm_cnt_lock);
+	spin_lock_init(&orig_node->bcast_seqno_lock);
+	spin_lock_init(&orig_node->neigh_list_lock);
+
+	/* extra reference for return */
+	atomic_set(&orig_node->refcount, 2);
 
+	orig_node->bat_priv = bat_priv;
 	memcpy(orig_node->orig, addr, ETH_ALEN);
 	orig_node->router = NULL;
 	orig_node->hna_buff = NULL;
@@ -151,6 +212,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
 	orig_node->batman_seqno_reset = jiffies - 1
 					- msecs_to_jiffies(RESET_PROTECTION_MS);
 
+	atomic_set(&orig_node->bond_candidates, 0);
+
 	size = bat_priv->num_ifaces * sizeof(unsigned long) * NUM_WORDS;
 
 	orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
@@ -166,8 +229,8 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr)
 	if (!orig_node->bcast_own_sum)
 		goto free_bcast_own;
 
-	hash_added = hash_add(bat_priv->orig_hash, compare_orig, choose_orig,
-			      orig_node);
+	hash_added = hash_add(bat_priv->orig_hash, compare_orig,
+			      choose_orig, orig_node, &orig_node->hash_entry);
 	if (hash_added < 0)
 		goto free_bcast_own_sum;
 
@@ -185,23 +248,30 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
 				 struct orig_node *orig_node,
 				 struct neigh_node **best_neigh_node)
 {
-	struct list_head *list_pos, *list_pos_tmp;
+	struct hlist_node *node, *node_tmp;
 	struct neigh_node *neigh_node;
 	bool neigh_purged = false;
 
 	*best_neigh_node = NULL;
 
+	spin_lock_bh(&orig_node->neigh_list_lock);
+
 	/* for all neighbors towards this originator ... */
-	list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
-		neigh_node = list_entry(list_pos, struct neigh_node, list);
+	hlist_for_each_entry_safe(neigh_node, node, node_tmp,
+				  &orig_node->neigh_list, list) {
 
 		if ((time_after(jiffies,
 			neigh_node->last_valid + PURGE_TIMEOUT * HZ)) ||
 		    (neigh_node->if_incoming->if_status == IF_INACTIVE) ||
+		    (neigh_node->if_incoming->if_status == IF_NOT_IN_USE) ||
 		    (neigh_node->if_incoming->if_status == IF_TO_BE_REMOVED)) {
 
-			if (neigh_node->if_incoming->if_status ==
-							IF_TO_BE_REMOVED)
+			if ((neigh_node->if_incoming->if_status ==
+								IF_INACTIVE) ||
+			    (neigh_node->if_incoming->if_status ==
+							IF_NOT_IN_USE) ||
+			    (neigh_node->if_incoming->if_status ==
+							IF_TO_BE_REMOVED))
 				bat_dbg(DBG_BATMAN, bat_priv,
 					"neighbor purge: originator %pM, "
 					"neighbor: %pM, iface: %s\n",
@@ -215,14 +285,18 @@ static bool purge_orig_neighbors(struct bat_priv *bat_priv,
 					(neigh_node->last_valid / HZ));
 
 			neigh_purged = true;
-			list_del(list_pos);
-			kfree(neigh_node);
+
+			hlist_del_rcu(&neigh_node->list);
+			bonding_candidate_del(orig_node, neigh_node);
+			neigh_node_free_ref(neigh_node);
 		} else {
 			if ((!*best_neigh_node) ||
 			    (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
 				*best_neigh_node = neigh_node;
 		}
 	}
+
+	spin_unlock_bh(&orig_node->neigh_list_lock);
 	return neigh_purged;
 }
 
@@ -245,9 +319,6 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
 				      best_neigh_node,
 				      orig_node->hna_buff,
 				      orig_node->hna_buff_len);
-			/* update bonding candidates, we could have lost
-			 * some candidates. */
-			update_bonding_candidates(bat_priv, orig_node);
 		}
 	}
 
@@ -257,40 +328,38 @@ static bool purge_orig_node(struct bat_priv *bat_priv,
 static void _purge_orig(struct bat_priv *bat_priv)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk, *safe;
+	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
-	struct element_t *bucket;
+	spinlock_t *list_lock; /* spinlock to protect write access */
 	struct orig_node *orig_node;
 	int i;
 
 	if (!hash)
 		return;
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-
 	/* for all origins... */
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
+		list_lock = &hash->list_locks[i];
 
-		hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) {
-			orig_node = bucket->data;
-
+		spin_lock_bh(list_lock);
+		hlist_for_each_entry_safe(orig_node, node, node_tmp,
+					  head, hash_entry) {
 			if (purge_orig_node(bat_priv, orig_node)) {
 				if (orig_node->gw_flags)
 					gw_node_delete(bat_priv, orig_node);
-				hlist_del(walk);
-				kfree(bucket);
-				free_orig_node(orig_node, bat_priv);
+				hlist_del_rcu(node);
+				orig_node_free_ref(orig_node);
+				continue;
 			}
 
 			if (time_after(jiffies, orig_node->last_frag_packet +
 						msecs_to_jiffies(FRAG_TIMEOUT)))
 				frag_list_free(&orig_node->frag_list);
 		}
+		spin_unlock_bh(list_lock);
 	}
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
-
 	gw_node_purge(bat_priv);
 	gw_election(bat_priv);
 
@@ -318,9 +387,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 	struct net_device *net_dev = (struct net_device *)seq->private;
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct orig_node *orig_node;
 	struct neigh_node *neigh_node;
 	int batman_count = 0;
@@ -348,14 +416,11 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 		   "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
 		   "outgoingIF", "Potential nexthops");
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
-
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
 			if (!orig_node->router)
 				continue;
 
@@ -374,8 +439,8 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 				   neigh_node->addr,
 				   neigh_node->if_incoming->net_dev->name);
 
-			list_for_each_entry(neigh_node, &orig_node->neigh_list,
-					    list) {
+			hlist_for_each_entry_rcu(neigh_node, node_tmp,
+						 &orig_node->neigh_list, list) {
 				seq_printf(seq, " %pM (%3i)", neigh_node->addr,
 						neigh_node->tq_avg);
 			}
@@ -383,10 +448,9 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
 			seq_printf(seq, "\n");
 			batman_count++;
 		}
+		rcu_read_unlock();
 	}
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
-
 	if ((batman_count == 0))
 		seq_printf(seq, "No batman nodes in range ...\n");
 
@@ -423,36 +487,36 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
 	return 0;
 }
 
-int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
+int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct orig_node *orig_node;
-	int i;
+	int i, ret;
 
 	/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
 	 * if_num */
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+			spin_lock_bh(&orig_node->ogm_cnt_lock);
+			ret = orig_node_add_if(orig_node, max_if_num);
+			spin_unlock_bh(&orig_node->ogm_cnt_lock);
 
-			if (orig_node_add_if(orig_node, max_if_num) == -1)
+			if (ret == -1)
 				goto err;
 		}
+		rcu_read_unlock();
 	}
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
 	return 0;
 
 err:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	rcu_read_unlock();
 	return -ENOMEM;
 }
 
@@ -508,57 +572,55 @@ free_own_sum:
 	return 0;
 }
 
-int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
+int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
-	struct batman_if *batman_if_tmp;
+	struct hard_iface *hard_iface_tmp;
 	struct orig_node *orig_node;
 	int i, ret;
 
 	/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
 	 * if_num */
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
-
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+			spin_lock_bh(&orig_node->ogm_cnt_lock);
 			ret = orig_node_del_if(orig_node, max_if_num,
-					batman_if->if_num);
+					hard_iface->if_num);
+			spin_unlock_bh(&orig_node->ogm_cnt_lock);
 
 			if (ret == -1)
 				goto err;
 		}
+		rcu_read_unlock();
 	}
 
 	/* renumber remaining batman interfaces _inside_ of orig_hash_lock */
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if_tmp, &if_list, list) {
-		if (batman_if_tmp->if_status == IF_NOT_IN_USE)
+	list_for_each_entry_rcu(hard_iface_tmp, &hardif_list, list) {
+		if (hard_iface_tmp->if_status == IF_NOT_IN_USE)
 			continue;
 
-		if (batman_if == batman_if_tmp)
+		if (hard_iface == hard_iface_tmp)
 			continue;
 
-		if (batman_if->soft_iface != batman_if_tmp->soft_iface)
+		if (hard_iface->soft_iface != hard_iface_tmp->soft_iface)
 			continue;
 
-		if (batman_if_tmp->if_num > batman_if->if_num)
-			batman_if_tmp->if_num--;
+		if (hard_iface_tmp->if_num > hard_iface->if_num)
+			hard_iface_tmp->if_num--;
 	}
 	rcu_read_unlock();
 
-	batman_if->if_num = -1;
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	hard_iface->if_num = -1;
 	return 0;
 
 err:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	rcu_read_unlock();
 	return -ENOMEM;
 }
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index d474ceb..5cc0110 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -22,21 +22,28 @@
 #ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
 #define _NET_BATMAN_ADV_ORIGINATOR_H_
 
+#include "hash.h"
+
 int originator_init(struct bat_priv *bat_priv);
 void originator_free(struct bat_priv *bat_priv);
 void purge_orig_ref(struct bat_priv *bat_priv);
+void orig_node_free_ref(struct orig_node *orig_node);
 struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
-struct neigh_node *
-create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
-		uint8_t *neigh, struct batman_if *if_incoming);
+struct neigh_node *create_neighbor(struct orig_node *orig_node,
+				   struct orig_node *orig_neigh_node,
+				   uint8_t *neigh,
+				   struct hard_iface *if_incoming);
+void neigh_node_free_ref(struct neigh_node *neigh_node);
 int orig_seq_print_text(struct seq_file *seq, void *offset);
-int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
-int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
+int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num);
+int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num);
 
 
 /* returns 1 if they are the same originator */
-static inline int compare_orig(void *data1, void *data2)
+static inline int compare_orig(struct hlist_node *node, void *data2)
 {
+	void *data1 = container_of(node, struct orig_node, hash_entry);
+
 	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
 }
 
@@ -61,4 +68,35 @@ static inline int choose_orig(void *data, int32_t size)
 	return hash % size;
 }
 
+static inline struct orig_node *orig_hash_find(struct bat_priv *bat_priv,
+					       void *data)
+{
+	struct hashtable_t *hash = bat_priv->orig_hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct orig_node *orig_node, *orig_node_tmp = NULL;
+	int index;
+
+	if (!hash)
+		return NULL;
+
+	index = choose_orig(data, hash->size);
+	head = &hash->table[index];
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+		if (!compare_eth(orig_node, data))
+			continue;
+
+		if (!atomic_inc_not_zero(&orig_node->refcount))
+			continue;
+
+		orig_node_tmp = orig_node;
+		break;
+	}
+	rcu_read_unlock();
+
+	return orig_node_tmp;
+}
+
 #endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h
index 2284e81..e757187 100644
--- a/net/batman-adv/packet.h
+++ b/net/batman-adv/packet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -50,6 +50,7 @@
 
 /* fragmentation defines */
 #define UNI_FRAG_HEAD 0x01
+#define UNI_FRAG_LARGETAIL 0x02
 
 struct batman_packet {
 	uint8_t  packet_type;
diff --git a/net/batman-adv/ring_buffer.c b/net/batman-adv/ring_buffer.c
index defd37c..5bb6a61 100644
--- a/net/batman-adv/ring_buffer.c
+++ b/net/batman-adv/ring_buffer.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/ring_buffer.h b/net/batman-adv/ring_buffer.h
index 6b0cb9a..0395b27 100644
--- a/net/batman-adv/ring_buffer.h
+++ b/net/batman-adv/ring_buffer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 8828edd..c172f5d 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -28,7 +28,6 @@
 #include "icmp_socket.h"
 #include "translation-table.h"
 #include "originator.h"
-#include "types.h"
 #include "ring_buffer.h"
 #include "vis.h"
 #include "aggregation.h"
@@ -36,35 +35,33 @@
 #include "gateway_client.h"
 #include "unicast.h"
 
-void slide_own_bcast_window(struct batman_if *batman_if)
+void slide_own_bcast_window(struct hard_iface *hard_iface)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct orig_node *orig_node;
 	unsigned long *word;
 	int i;
 	size_t word_index;
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
-			word_index = batman_if->if_num * NUM_WORDS;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+			spin_lock_bh(&orig_node->ogm_cnt_lock);
+			word_index = hard_iface->if_num * NUM_WORDS;
 			word = &(orig_node->bcast_own[word_index]);
 
 			bit_get_packet(bat_priv, word, 1, 0);
-			orig_node->bcast_own_sum[batman_if->if_num] =
+			orig_node->bcast_own_sum[hard_iface->if_num] =
 				bit_packet_count(word);
+			spin_unlock_bh(&orig_node->ogm_cnt_lock);
 		}
+		rcu_read_unlock();
 	}
-
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
 }
 
 static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node,
@@ -90,6 +87,8 @@ static void update_route(struct bat_priv *bat_priv,
 			 struct neigh_node *neigh_node,
 			 unsigned char *hna_buff, int hna_buff_len)
 {
+	struct neigh_node *neigh_node_tmp;
+
 	/* route deleted */
 	if ((orig_node->router) && (!neigh_node)) {
 
@@ -116,7 +115,12 @@ static void update_route(struct bat_priv *bat_priv,
 			orig_node->router->addr);
 	}
 
+	if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
+		neigh_node = NULL;
+	neigh_node_tmp = orig_node->router;
 	orig_node->router = neigh_node;
+	if (neigh_node_tmp)
+		neigh_node_free_ref(neigh_node_tmp);
 }
 
 
@@ -139,73 +143,93 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
 static int is_bidirectional_neigh(struct orig_node *orig_node,
 				struct orig_node *orig_neigh_node,
 				struct batman_packet *batman_packet,
-				struct batman_if *if_incoming)
+				struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
-	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
+	struct neigh_node *neigh_node = NULL, *tmp_neigh_node;
+	struct hlist_node *node;
 	unsigned char total_count;
+	uint8_t orig_eq_count, neigh_rq_count, tq_own;
+	int tq_asym_penalty, ret = 0;
 
 	if (orig_node == orig_neigh_node) {
-		list_for_each_entry(tmp_neigh_node,
-				    &orig_node->neigh_list,
-				    list) {
-
-			if (compare_orig(tmp_neigh_node->addr,
-					 orig_neigh_node->orig) &&
-			    (tmp_neigh_node->if_incoming == if_incoming))
-				neigh_node = tmp_neigh_node;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(tmp_neigh_node, node,
+					 &orig_node->neigh_list, list) {
+
+			if (!compare_eth(tmp_neigh_node->addr,
+					 orig_neigh_node->orig))
+				continue;
+
+			if (tmp_neigh_node->if_incoming != if_incoming)
+				continue;
+
+			if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+				continue;
+
+			neigh_node = tmp_neigh_node;
 		}
+		rcu_read_unlock();
 
 		if (!neigh_node)
 			neigh_node = create_neighbor(orig_node,
 						     orig_neigh_node,
 						     orig_neigh_node->orig,
 						     if_incoming);
-		/* create_neighbor failed, return 0 */
 		if (!neigh_node)
-			return 0;
+			goto out;
 
 		neigh_node->last_valid = jiffies;
 	} else {
 		/* find packet count of corresponding one hop neighbor */
-		list_for_each_entry(tmp_neigh_node,
-				    &orig_neigh_node->neigh_list, list) {
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(tmp_neigh_node, node,
+					 &orig_neigh_node->neigh_list, list) {
 
-			if (compare_orig(tmp_neigh_node->addr,
-					 orig_neigh_node->orig) &&
-			    (tmp_neigh_node->if_incoming == if_incoming))
-				neigh_node = tmp_neigh_node;
+			if (!compare_eth(tmp_neigh_node->addr,
+					 orig_neigh_node->orig))
+				continue;
+
+			if (tmp_neigh_node->if_incoming != if_incoming)
+				continue;
+
+			if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+				continue;
+
+			neigh_node = tmp_neigh_node;
 		}
+		rcu_read_unlock();
 
 		if (!neigh_node)
 			neigh_node = create_neighbor(orig_neigh_node,
 						     orig_neigh_node,
 						     orig_neigh_node->orig,
 						     if_incoming);
-		/* create_neighbor failed, return 0 */
 		if (!neigh_node)
-			return 0;
+			goto out;
 	}
 
 	orig_node->last_valid = jiffies;
 
+	spin_lock_bh(&orig_node->ogm_cnt_lock);
+	orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num];
+	neigh_rq_count = neigh_node->real_packet_count;
+	spin_unlock_bh(&orig_node->ogm_cnt_lock);
+
 	/* pay attention to not get a value bigger than 100 % */
-	total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] >
-		       neigh_node->real_packet_count ?
-		       neigh_node->real_packet_count :
-		       orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
+	total_count = (orig_eq_count > neigh_rq_count ?
+		       neigh_rq_count : orig_eq_count);
 
 	/* if we have too few packets (too less data) we set tq_own to zero */
 	/* if we receive too few packets it is not considered bidirectional */
 	if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
-	    (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
-		orig_neigh_node->tq_own = 0;
+	    (neigh_rq_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
+		tq_own = 0;
 	else
 		/* neigh_node->real_packet_count is never zero as we
 		 * only purge old information when getting new
 		 * information */
-		orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) /
-			neigh_node->real_packet_count;
+		tq_own = (TQ_MAX_VALUE * total_count) /	neigh_rq_count;
 
 	/*
 	 * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
@@ -213,20 +237,16 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
 	 * punishes asymmetric links more.  This will give a value
 	 * between 0 and TQ_MAX_VALUE
 	 */
-	orig_neigh_node->tq_asym_penalty =
-		TQ_MAX_VALUE -
-		(TQ_MAX_VALUE *
-		 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
-		 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
-		 (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
-		(TQ_LOCAL_WINDOW_SIZE *
-		 TQ_LOCAL_WINDOW_SIZE *
-		 TQ_LOCAL_WINDOW_SIZE);
-
-	batman_packet->tq = ((batman_packet->tq *
-			      orig_neigh_node->tq_own *
-			      orig_neigh_node->tq_asym_penalty) /
-			     (TQ_MAX_VALUE * TQ_MAX_VALUE));
+	tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
+				(TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
+				(TQ_LOCAL_WINDOW_SIZE - neigh_rq_count) *
+				(TQ_LOCAL_WINDOW_SIZE - neigh_rq_count)) /
+					(TQ_LOCAL_WINDOW_SIZE *
+					 TQ_LOCAL_WINDOW_SIZE *
+					 TQ_LOCAL_WINDOW_SIZE);
+
+	batman_packet->tq = ((batman_packet->tq * tq_own * tq_asym_penalty) /
+						(TQ_MAX_VALUE * TQ_MAX_VALUE));
 
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"bidirectional: "
@@ -234,34 +254,141 @@ static int is_bidirectional_neigh(struct orig_node *orig_node,
 		"real recv = %2i, local tq: %3i, asym_penalty: %3i, "
 		"total tq: %3i\n",
 		orig_node->orig, orig_neigh_node->orig, total_count,
-		neigh_node->real_packet_count, orig_neigh_node->tq_own,
-		orig_neigh_node->tq_asym_penalty, batman_packet->tq);
+		neigh_rq_count, tq_own,	tq_asym_penalty, batman_packet->tq);
 
 	/* if link has the minimum required transmission quality
 	 * consider it bidirectional */
 	if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
-		return 1;
+		ret = 1;
 
-	return 0;
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	return ret;
+}
+
+/* caller must hold the neigh_list_lock */
+void bonding_candidate_del(struct orig_node *orig_node,
+			   struct neigh_node *neigh_node)
+{
+	/* this neighbor is not part of our candidate list */
+	if (list_empty(&neigh_node->bonding_list))
+		goto out;
+
+	list_del_rcu(&neigh_node->bonding_list);
+	INIT_LIST_HEAD(&neigh_node->bonding_list);
+	neigh_node_free_ref(neigh_node);
+	atomic_dec(&orig_node->bond_candidates);
+
+out:
+	return;
+}
+
+static void bonding_candidate_add(struct orig_node *orig_node,
+				  struct neigh_node *neigh_node)
+{
+	struct hlist_node *node;
+	struct neigh_node *tmp_neigh_node;
+	uint8_t best_tq, interference_candidate = 0;
+
+	spin_lock_bh(&orig_node->neigh_list_lock);
+
+	/* only consider if it has the same primary address ...  */
+	if (!compare_eth(orig_node->orig,
+			 neigh_node->orig_node->primary_addr))
+		goto candidate_del;
+
+	if (!orig_node->router)
+		goto candidate_del;
+
+	best_tq = orig_node->router->tq_avg;
+
+	/* ... and is good enough to be considered */
+	if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
+		goto candidate_del;
+
+	/**
+	 * check if we have another candidate with the same mac address or
+	 * interface. If we do, we won't select this candidate because of
+	 * possible interference.
+	 */
+	hlist_for_each_entry_rcu(tmp_neigh_node, node,
+				 &orig_node->neigh_list, list) {
+
+		if (tmp_neigh_node == neigh_node)
+			continue;
+
+		/* we only care if the other candidate is even
+		* considered as candidate. */
+		if (list_empty(&tmp_neigh_node->bonding_list))
+			continue;
+
+		if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) ||
+		    (compare_eth(neigh_node->addr, tmp_neigh_node->addr))) {
+			interference_candidate = 1;
+			break;
+		}
+	}
+
+	/* don't care further if it is an interference candidate */
+	if (interference_candidate)
+		goto candidate_del;
+
+	/* this neighbor already is part of our candidate list */
+	if (!list_empty(&neigh_node->bonding_list))
+		goto out;
+
+	if (!atomic_inc_not_zero(&neigh_node->refcount))
+		goto out;
+
+	list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list);
+	atomic_inc(&orig_node->bond_candidates);
+	goto out;
+
+candidate_del:
+	bonding_candidate_del(orig_node, neigh_node);
+
+out:
+	spin_unlock_bh(&orig_node->neigh_list_lock);
+	return;
+}
+
+/* copy primary address for bonding */
+static void bonding_save_primary(struct orig_node *orig_node,
+				 struct orig_node *orig_neigh_node,
+				 struct batman_packet *batman_packet)
+{
+	if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
+		return;
+
+	memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
 }
 
 static void update_orig(struct bat_priv *bat_priv,
 			struct orig_node *orig_node,
 			struct ethhdr *ethhdr,
 			struct batman_packet *batman_packet,
-			struct batman_if *if_incoming,
+			struct hard_iface *if_incoming,
 			unsigned char *hna_buff, int hna_buff_len,
 			char is_duplicate)
 {
 	struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
+	struct orig_node *orig_node_tmp;
+	struct hlist_node *node;
 	int tmp_hna_buff_len;
+	uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
 
 	bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
 		"Searching and updating originator entry of received packet\n");
 
-	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
-		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
-		    (tmp_neigh_node->if_incoming == if_incoming)) {
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(tmp_neigh_node, node,
+				 &orig_node->neigh_list, list) {
+		if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
+		    (tmp_neigh_node->if_incoming == if_incoming) &&
+		     atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
+			if (neigh_node)
+				neigh_node_free_ref(neigh_node);
 			neigh_node = tmp_neigh_node;
 			continue;
 		}
@@ -280,16 +407,20 @@ static void update_orig(struct bat_priv *bat_priv,
 
 		orig_tmp = get_orig_node(bat_priv, ethhdr->h_source);
 		if (!orig_tmp)
-			return;
+			goto unlock;
 
 		neigh_node = create_neighbor(orig_node, orig_tmp,
 					     ethhdr->h_source, if_incoming);
+
+		orig_node_free_ref(orig_tmp);
 		if (!neigh_node)
-			return;
+			goto unlock;
 	} else
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Updating existing last-hop neighbor of originator\n");
 
+	rcu_read_unlock();
+
 	orig_node->flags = batman_packet->flags;
 	neigh_node->last_valid = jiffies;
 
@@ -303,6 +434,8 @@ static void update_orig(struct bat_priv *bat_priv,
 		neigh_node->last_ttl = batman_packet->ttl;
 	}
 
+	bonding_candidate_add(orig_node, neigh_node);
+
 	tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ?
 			    batman_packet->num_hna * ETH_ALEN : hna_buff_len);
 
@@ -319,10 +452,22 @@ static void update_orig(struct bat_priv *bat_priv,
 	/* if the TQ is the same and the link not more symetric we
 	 * won't consider it either */
 	if ((orig_node->router) &&
-	     ((neigh_node->tq_avg == orig_node->router->tq_avg) &&
-	     (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num]
-	      >= neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
-		goto update_hna;
+	     (neigh_node->tq_avg == orig_node->router->tq_avg)) {
+		orig_node_tmp = orig_node->router->orig_node;
+		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
+		bcast_own_sum_orig =
+			orig_node_tmp->bcast_own_sum[if_incoming->if_num];
+		spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
+
+		orig_node_tmp = neigh_node->orig_node;
+		spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
+		bcast_own_sum_neigh =
+			orig_node_tmp->bcast_own_sum[if_incoming->if_num];
+		spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
+
+		if (bcast_own_sum_orig >= bcast_own_sum_neigh)
+			goto update_hna;
+	}
 
 	update_routes(bat_priv, orig_node, neigh_node,
 		      hna_buff, tmp_hna_buff_len);
@@ -343,6 +488,14 @@ update_gw:
 	    (atomic_read(&bat_priv->gw_mode) == GW_MODE_CLIENT) &&
 	    (atomic_read(&bat_priv->gw_sel_class) > 2))
 		gw_check_election(bat_priv, orig_node);
+
+	goto out;
+
+unlock:
+	rcu_read_unlock();
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
 }
 
 /* checks whether the host restarted and is in the protection time.
@@ -380,34 +533,38 @@ static int window_protected(struct bat_priv *bat_priv,
  */
 static char count_real_packets(struct ethhdr *ethhdr,
 			       struct batman_packet *batman_packet,
-			       struct batman_if *if_incoming)
+			       struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	struct orig_node *orig_node;
 	struct neigh_node *tmp_neigh_node;
+	struct hlist_node *node;
 	char is_duplicate = 0;
 	int32_t seq_diff;
 	int need_update = 0;
-	int set_mark;
+	int set_mark, ret = -1;
 
 	orig_node = get_orig_node(bat_priv, batman_packet->orig);
 	if (!orig_node)
 		return 0;
 
+	spin_lock_bh(&orig_node->ogm_cnt_lock);
 	seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
 
 	/* signalize caller that the packet is to be dropped. */
 	if (window_protected(bat_priv, seq_diff,
 			     &orig_node->batman_seqno_reset))
-		return -1;
+		goto out;
 
-	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(tmp_neigh_node, node,
+				 &orig_node->neigh_list, list) {
 
 		is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
 					       orig_node->last_real_seqno,
 					       batman_packet->seqno);
 
-		if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
+		if (compare_eth(tmp_neigh_node->addr, ethhdr->h_source) &&
 		    (tmp_neigh_node->if_incoming == if_incoming))
 			set_mark = 1;
 		else
@@ -421,6 +578,7 @@ static char count_real_packets(struct ethhdr *ethhdr,
 		tmp_neigh_node->real_packet_count =
 			bit_packet_count(tmp_neigh_node->real_bits);
 	}
+	rcu_read_unlock();
 
 	if (need_update) {
 		bat_dbg(DBG_BATMAN, bat_priv,
@@ -429,123 +587,21 @@ static char count_real_packets(struct ethhdr *ethhdr,
 		orig_node->last_real_seqno = batman_packet->seqno;
 	}
 
-	return is_duplicate;
-}
-
-/* copy primary address for bonding */
-static void mark_bonding_address(struct bat_priv *bat_priv,
-				 struct orig_node *orig_node,
-				 struct orig_node *orig_neigh_node,
-				 struct batman_packet *batman_packet)
+	ret = is_duplicate;
 
-{
-	if (batman_packet->flags & PRIMARIES_FIRST_HOP)
-		memcpy(orig_neigh_node->primary_addr,
-		       orig_node->orig, ETH_ALEN);
-
-	return;
-}
-
-/* mark possible bond.candidates in the neighbor list */
-void update_bonding_candidates(struct bat_priv *bat_priv,
-			       struct orig_node *orig_node)
-{
-	int candidates;
-	int interference_candidate;
-	int best_tq;
-	struct neigh_node *tmp_neigh_node, *tmp_neigh_node2;
-	struct neigh_node *first_candidate, *last_candidate;
-
-	/* update the candidates for this originator */
-	if (!orig_node->router) {
-		orig_node->bond.candidates = 0;
-		return;
-	}
-
-	best_tq = orig_node->router->tq_avg;
-
-	/* update bond.candidates */
-
-	candidates = 0;
-
-	/* mark other nodes which also received "PRIMARIES FIRST HOP" packets
-	 * as "bonding partner" */
-
-	/* first, zero the list */
-	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
-		tmp_neigh_node->next_bond_candidate = NULL;
-	}
-
-	first_candidate = NULL;
-	last_candidate = NULL;
-	list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
-
-		/* only consider if it has the same primary address ...  */
-		if (memcmp(orig_node->orig,
-				tmp_neigh_node->orig_node->primary_addr,
-				ETH_ALEN) != 0)
-			continue;
-
-		/* ... and is good enough to be considered */
-		if (tmp_neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
-			continue;
-
-		/* check if we have another candidate with the same
-		 * mac address or interface. If we do, we won't
-		 * select this candidate because of possible interference. */
-
-		interference_candidate = 0;
-		list_for_each_entry(tmp_neigh_node2,
-				&orig_node->neigh_list, list) {
-
-			if (tmp_neigh_node2 == tmp_neigh_node)
-				continue;
-
-			/* we only care if the other candidate is even
-			 * considered as candidate. */
-			if (!tmp_neigh_node2->next_bond_candidate)
-				continue;
-
-
-			if ((tmp_neigh_node->if_incoming ==
-				tmp_neigh_node2->if_incoming)
-				|| (memcmp(tmp_neigh_node->addr,
-				tmp_neigh_node2->addr, ETH_ALEN) == 0)) {
-
-				interference_candidate = 1;
-				break;
-			}
-		}
-		/* don't care further if it is an interference candidate */
-		if (interference_candidate)
-			continue;
-
-		if (!first_candidate) {
-			first_candidate = tmp_neigh_node;
-			tmp_neigh_node->next_bond_candidate = first_candidate;
-		} else
-			tmp_neigh_node->next_bond_candidate = last_candidate;
-
-		last_candidate = tmp_neigh_node;
-
-		candidates++;
-	}
-
-	if (candidates > 0) {
-		first_candidate->next_bond_candidate = last_candidate;
-		orig_node->bond.selected = first_candidate;
-	}
-
-	orig_node->bond.candidates = candidates;
+out:
+	spin_unlock_bh(&orig_node->ogm_cnt_lock);
+	orig_node_free_ref(orig_node);
+	return ret;
 }
 
 void receive_bat_packet(struct ethhdr *ethhdr,
-				struct batman_packet *batman_packet,
-				unsigned char *hna_buff, int hna_buff_len,
-				struct batman_if *if_incoming)
+			struct batman_packet *batman_packet,
+			unsigned char *hna_buff, int hna_buff_len,
+			struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	struct orig_node *orig_neigh_node, *orig_node;
 	char has_directlink_flag;
 	char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
@@ -573,8 +629,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 
 	has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
 
-	is_single_hop_neigh = (compare_orig(ethhdr->h_source,
-					    batman_packet->orig) ? 1 : 0);
+	is_single_hop_neigh = (compare_eth(ethhdr->h_source,
+					   batman_packet->orig) ? 1 : 0);
 
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Received BATMAN packet via NB: %pM, IF: %s [%pM] "
@@ -587,26 +643,26 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 		has_directlink_flag);
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if (batman_if->if_status != IF_ACTIVE)
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if (hard_iface->if_status != IF_ACTIVE)
 			continue;
 
-		if (batman_if->soft_iface != if_incoming->soft_iface)
+		if (hard_iface->soft_iface != if_incoming->soft_iface)
 			continue;
 
-		if (compare_orig(ethhdr->h_source,
-				 batman_if->net_dev->dev_addr))
+		if (compare_eth(ethhdr->h_source,
+				hard_iface->net_dev->dev_addr))
 			is_my_addr = 1;
 
-		if (compare_orig(batman_packet->orig,
-				 batman_if->net_dev->dev_addr))
+		if (compare_eth(batman_packet->orig,
+				hard_iface->net_dev->dev_addr))
 			is_my_orig = 1;
 
-		if (compare_orig(batman_packet->prev_sender,
-				 batman_if->net_dev->dev_addr))
+		if (compare_eth(batman_packet->prev_sender,
+				hard_iface->net_dev->dev_addr))
 			is_my_oldorig = 1;
 
-		if (compare_orig(ethhdr->h_source, broadcast_addr))
+		if (compare_eth(ethhdr->h_source, broadcast_addr))
 			is_broadcast = 1;
 	}
 	rcu_read_unlock();
@@ -638,7 +694,6 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 		int offset;
 
 		orig_neigh_node = get_orig_node(bat_priv, ethhdr->h_source);
-
 		if (!orig_neigh_node)
 			return;
 
@@ -647,18 +702,22 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 		/* if received seqno equals last send seqno save new
 		 * seqno for bidirectional check */
 		if (has_directlink_flag &&
-		    compare_orig(if_incoming->net_dev->dev_addr,
-				 batman_packet->orig) &&
+		    compare_eth(if_incoming->net_dev->dev_addr,
+				batman_packet->orig) &&
 		    (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
 			offset = if_incoming->if_num * NUM_WORDS;
+
+			spin_lock_bh(&orig_neigh_node->ogm_cnt_lock);
 			word = &(orig_neigh_node->bcast_own[offset]);
 			bit_mark(word, 0);
 			orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
 				bit_packet_count(word);
+			spin_unlock_bh(&orig_neigh_node->ogm_cnt_lock);
 		}
 
 		bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
 			"originator packet from myself (via neighbor)\n");
+		orig_node_free_ref(orig_neigh_node);
 		return;
 	}
 
@@ -679,27 +738,27 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: packet within seqno protection time "
 			"(sender: %pM)\n", ethhdr->h_source);
-		return;
+		goto out;
 	}
 
 	if (batman_packet->tq == 0) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: originator packet with tq equal 0\n");
-		return;
+		goto out;
 	}
 
 	/* avoid temporary routing loops */
 	if ((orig_node->router) &&
 	    (orig_node->router->orig_node->router) &&
-	    (compare_orig(orig_node->router->addr,
-			  batman_packet->prev_sender)) &&
-	    !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
-	    (compare_orig(orig_node->router->addr,
-			  orig_node->router->orig_node->router->addr))) {
+	    (compare_eth(orig_node->router->addr,
+			 batman_packet->prev_sender)) &&
+	    !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) &&
+	    (compare_eth(orig_node->router->addr,
+			 orig_node->router->orig_node->router->addr))) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: ignoring all rebroadcast packets that "
 			"may make me loop (sender: %pM)\n", ethhdr->h_source);
-		return;
+		goto out;
 	}
 
 	/* if sender is a direct neighbor the sender mac equals
@@ -708,19 +767,21 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 			   orig_node :
 			   get_orig_node(bat_priv, ethhdr->h_source));
 	if (!orig_neigh_node)
-		return;
+		goto out;
 
 	/* drop packet if sender is not a direct neighbor and if we
 	 * don't route towards it */
 	if (!is_single_hop_neigh && (!orig_neigh_node->router)) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: OGM via unknown neighbor!\n");
-		return;
+		goto out_neigh;
 	}
 
 	is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
 						batman_packet, if_incoming);
 
+	bonding_save_primary(orig_node, orig_neigh_node, batman_packet);
+
 	/* update ranking if it is not a duplicate or has the same
 	 * seqno and similar ttl as the non-duplicate */
 	if (is_bidirectional &&
@@ -730,10 +791,6 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 		update_orig(bat_priv, orig_node, ethhdr, batman_packet,
 			    if_incoming, hna_buff, hna_buff_len, is_duplicate);
 
-	mark_bonding_address(bat_priv, orig_node,
-			     orig_neigh_node, batman_packet);
-	update_bonding_candidates(bat_priv, orig_node);
-
 	/* is single hop (direct) neighbor */
 	if (is_single_hop_neigh) {
 
@@ -743,31 +800,36 @@ void receive_bat_packet(struct ethhdr *ethhdr,
 
 		bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
 			"rebroadcast neighbor packet with direct link flag\n");
-		return;
+		goto out_neigh;
 	}
 
 	/* multihop originator */
 	if (!is_bidirectional) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: not received via bidirectional link\n");
-		return;
+		goto out_neigh;
 	}
 
 	if (is_duplicate) {
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"Drop packet: duplicate packet received\n");
-		return;
+		goto out_neigh;
 	}
 
 	bat_dbg(DBG_BATMAN, bat_priv,
 		"Forwarding packet: rebroadcast originator packet\n");
 	schedule_forward_packet(orig_node, ethhdr, batman_packet,
 				0, hna_buff_len, if_incoming);
+
+out_neigh:
+	if ((orig_neigh_node) && (!is_single_hop_neigh))
+		orig_node_free_ref(orig_neigh_node);
+out:
+	orig_node_free_ref(orig_node);
 }
 
-int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
+int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
 	struct ethhdr *ethhdr;
 
 	/* drop packet if it has not necessary minimum size */
@@ -794,12 +856,10 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
 
 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
 	receive_aggr_bat_packet(ethhdr,
 				skb->data,
 				skb_headlen(skb),
-				batman_if);
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+				hard_iface);
 
 	kfree_skb(skb);
 	return NET_RX_SUCCESS;
@@ -808,135 +868,144 @@ int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
 static int recv_my_icmp_packet(struct bat_priv *bat_priv,
 			       struct sk_buff *skb, size_t icmp_len)
 {
-	struct orig_node *orig_node;
+	struct orig_node *orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
 	struct icmp_packet_rr *icmp_packet;
-	struct ethhdr *ethhdr;
-	struct batman_if *batman_if;
-	int ret;
-	uint8_t dstaddr[ETH_ALEN];
+	int ret = NET_RX_DROP;
 
 	icmp_packet = (struct icmp_packet_rr *)skb->data;
-	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
 	/* add data to device queue */
 	if (icmp_packet->msg_type != ECHO_REQUEST) {
 		bat_socket_receive_packet(icmp_packet, icmp_len);
-		return NET_RX_DROP;
+		goto out;
 	}
 
 	if (!bat_priv->primary_if)
-		return NET_RX_DROP;
+		goto out;
 
 	/* answer echo request (ping) */
 	/* get routing information */
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
-						   compare_orig, choose_orig,
-						   icmp_packet->orig));
-	ret = NET_RX_DROP;
-
-	if ((orig_node) && (orig_node->router)) {
-
-		/* don't lock while sending the packets ... we therefore
-		 * copy the required data before sending */
-		batman_if = orig_node->router->if_incoming;
-		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
-
-		/* create a copy of the skb, if needed, to modify it. */
-		if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
-			return NET_RX_DROP;
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
 
-		icmp_packet = (struct icmp_packet_rr *)skb->data;
-		ethhdr = (struct ethhdr *)skb_mac_header(skb);
+	if (!orig_node)
+		goto unlock;
 
-		memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
-		memcpy(icmp_packet->orig,
-		       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
-		icmp_packet->msg_type = ECHO_REPLY;
-		icmp_packet->ttl = TTL;
+	neigh_node = orig_node->router;
 
-		send_skb_packet(skb, batman_if, dstaddr);
-		ret = NET_RX_SUCCESS;
+	if (!neigh_node)
+		goto unlock;
 
-	} else
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
+	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+		neigh_node = NULL;
+		goto unlock;
+	}
+
+	rcu_read_unlock();
+
+	/* create a copy of the skb, if needed, to modify it. */
+	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
+		goto out;
+
+	icmp_packet = (struct icmp_packet_rr *)skb->data;
+
+	memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+	memcpy(icmp_packet->orig,
+		bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+	icmp_packet->msg_type = ECHO_REPLY;
+	icmp_packet->ttl = TTL;
 
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = NET_RX_SUCCESS;
+	goto out;
+
+unlock:
+	rcu_read_unlock();
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
 	return ret;
 }
 
 static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv,
-				  struct sk_buff *skb, size_t icmp_len)
+				  struct sk_buff *skb)
 {
-	struct orig_node *orig_node;
+	struct orig_node *orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
 	struct icmp_packet *icmp_packet;
-	struct ethhdr *ethhdr;
-	struct batman_if *batman_if;
-	int ret;
-	uint8_t dstaddr[ETH_ALEN];
+	int ret = NET_RX_DROP;
 
 	icmp_packet = (struct icmp_packet *)skb->data;
-	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
 	/* send TTL exceeded if packet is an echo request (traceroute) */
 	if (icmp_packet->msg_type != ECHO_REQUEST) {
 		pr_debug("Warning - can't forward icmp packet from %pM to "
 			 "%pM: ttl exceeded\n", icmp_packet->orig,
 			 icmp_packet->dst);
-		return NET_RX_DROP;
+		goto out;
 	}
 
 	if (!bat_priv->primary_if)
-		return NET_RX_DROP;
+		goto out;
 
 	/* get routing information */
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)
-		     hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
-			       icmp_packet->orig));
-	ret = NET_RX_DROP;
-
-	if ((orig_node) && (orig_node->router)) {
-
-		/* don't lock while sending the packets ... we therefore
-		 * copy the required data before sending */
-		batman_if = orig_node->router->if_incoming;
-		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
-
-		/* create a copy of the skb, if needed, to modify it. */
-		if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
-			return NET_RX_DROP;
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, icmp_packet->orig);
 
-		icmp_packet = (struct icmp_packet *) skb->data;
-		ethhdr = (struct ethhdr *)skb_mac_header(skb);
+	if (!orig_node)
+		goto unlock;
 
-		memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
-		memcpy(icmp_packet->orig,
-		       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
-		icmp_packet->msg_type = TTL_EXCEEDED;
-		icmp_packet->ttl = TTL;
+	neigh_node = orig_node->router;
 
-		send_skb_packet(skb, batman_if, dstaddr);
-		ret = NET_RX_SUCCESS;
+	if (!neigh_node)
+		goto unlock;
 
-	} else
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
+	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+		neigh_node = NULL;
+		goto unlock;
+	}
 
+	rcu_read_unlock();
+
+	/* create a copy of the skb, if needed, to modify it. */
+	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
+		goto out;
+
+	icmp_packet = (struct icmp_packet *)skb->data;
+
+	memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+	memcpy(icmp_packet->orig,
+		bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
+	icmp_packet->msg_type = TTL_EXCEEDED;
+	icmp_packet->ttl = TTL;
+
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = NET_RX_SUCCESS;
+	goto out;
+
+unlock:
+	rcu_read_unlock();
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
 	return ret;
 }
 
 
-int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
+int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct icmp_packet_rr *icmp_packet;
 	struct ethhdr *ethhdr;
-	struct orig_node *orig_node;
-	struct batman_if *batman_if;
+	struct orig_node *orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
 	int hdr_size = sizeof(struct icmp_packet);
-	int ret;
-	uint8_t dstaddr[ETH_ALEN];
+	int ret = NET_RX_DROP;
 
 	/**
 	 * we truncate all incoming icmp packets if they don't match our size
@@ -946,21 +1015,21 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
 
 	/* drop packet if it has not necessary minimum size */
 	if (unlikely(!pskb_may_pull(skb, hdr_size)))
-		return NET_RX_DROP;
+		goto out;
 
 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
 	/* packet with unicast indication but broadcast recipient */
 	if (is_broadcast_ether_addr(ethhdr->h_dest))
-		return NET_RX_DROP;
+		goto out;
 
 	/* packet with broadcast sender address */
 	if (is_broadcast_ether_addr(ethhdr->h_source))
-		return NET_RX_DROP;
+		goto out;
 
 	/* not for me */
 	if (!is_my_mac(ethhdr->h_dest))
-		return NET_RX_DROP;
+		goto out;
 
 	icmp_packet = (struct icmp_packet_rr *)skb->data;
 
@@ -978,53 +1047,61 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if)
 
 	/* TTL exceeded */
 	if (icmp_packet->ttl < 2)
-		return recv_icmp_ttl_exceeded(bat_priv, skb, hdr_size);
-
-	ret = NET_RX_DROP;
+		return recv_icmp_ttl_exceeded(bat_priv, skb);
 
 	/* get routing information */
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)
-		     hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
-			       icmp_packet->dst));
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, icmp_packet->dst);
 
-	if ((orig_node) && (orig_node->router)) {
+	if (!orig_node)
+		goto unlock;
 
-		/* don't lock while sending the packets ... we therefore
-		 * copy the required data before sending */
-		batman_if = orig_node->router->if_incoming;
-		memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
+	neigh_node = orig_node->router;
 
-		/* create a copy of the skb, if needed, to modify it. */
-		if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
-			return NET_RX_DROP;
+	if (!neigh_node)
+		goto unlock;
 
-		icmp_packet = (struct icmp_packet_rr *)skb->data;
-		ethhdr = (struct ethhdr *)skb_mac_header(skb);
+	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+		neigh_node = NULL;
+		goto unlock;
+	}
 
-		/* decrement ttl */
-		icmp_packet->ttl--;
+	rcu_read_unlock();
 
-		/* route it */
-		send_skb_packet(skb, batman_if, dstaddr);
-		ret = NET_RX_SUCCESS;
+	/* create a copy of the skb, if needed, to modify it. */
+	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
+		goto out;
 
-	} else
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
+	icmp_packet = (struct icmp_packet_rr *)skb->data;
+
+	/* decrement ttl */
+	icmp_packet->ttl--;
 
+	/* route it */
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = NET_RX_SUCCESS;
+	goto out;
+
+unlock:
+	rcu_read_unlock();
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
 	return ret;
 }
 
 /* find a suitable router for this originator, and use
- * bonding if possible. */
+ * bonding if possible. increases the found neighbors
+ * refcount.*/
 struct neigh_node *find_router(struct bat_priv *bat_priv,
 			       struct orig_node *orig_node,
-			       struct batman_if *recv_if)
+			       struct hard_iface *recv_if)
 {
 	struct orig_node *primary_orig_node;
 	struct orig_node *router_orig;
-	struct neigh_node *router, *first_candidate, *best_router;
+	struct neigh_node *router, *first_candidate, *tmp_neigh_node;
 	static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
 	int bonding_enabled;
 
@@ -1036,78 +1113,128 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
 
 	/* without bonding, the first node should
 	 * always choose the default router. */
-
 	bonding_enabled = atomic_read(&bat_priv->bonding);
 
-	if ((!recv_if) && (!bonding_enabled))
-		return orig_node->router;
-
+	rcu_read_lock();
+	/* select default router to output */
+	router = orig_node->router;
 	router_orig = orig_node->router->orig_node;
+	if (!router_orig || !atomic_inc_not_zero(&router->refcount)) {
+		rcu_read_unlock();
+		return NULL;
+	}
+
+	if ((!recv_if) && (!bonding_enabled))
+		goto return_router;
 
 	/* if we have something in the primary_addr, we can search
 	 * for a potential bonding candidate. */
-	if (memcmp(router_orig->primary_addr, zero_mac, ETH_ALEN) == 0)
-		return orig_node->router;
+	if (compare_eth(router_orig->primary_addr, zero_mac))
+		goto return_router;
 
 	/* find the orig_node which has the primary interface. might
 	 * even be the same as our router_orig in many cases */
 
-	if (memcmp(router_orig->primary_addr,
-				router_orig->orig, ETH_ALEN) == 0) {
+	if (compare_eth(router_orig->primary_addr, router_orig->orig)) {
 		primary_orig_node = router_orig;
 	} else {
-		primary_orig_node = hash_find(bat_priv->orig_hash, compare_orig,
-					       choose_orig,
-					       router_orig->primary_addr);
-
+		primary_orig_node = orig_hash_find(bat_priv,
+						   router_orig->primary_addr);
 		if (!primary_orig_node)
-			return orig_node->router;
+			goto return_router;
+
+		orig_node_free_ref(primary_orig_node);
 	}
 
 	/* with less than 2 candidates, we can't do any
 	 * bonding and prefer the original router. */
-
-	if (primary_orig_node->bond.candidates < 2)
-		return orig_node->router;
+	if (atomic_read(&primary_orig_node->bond_candidates) < 2)
+		goto return_router;
 
 
 	/* all nodes between should choose a candidate which
 	 * is is not on the interface where the packet came
 	 * in. */
-	first_candidate = primary_orig_node->bond.selected;
-	router = first_candidate;
+
+	neigh_node_free_ref(router);
+	first_candidate = NULL;
+	router = NULL;
 
 	if (bonding_enabled) {
 		/* in the bonding case, send the packets in a round
 		 * robin fashion over the remaining interfaces. */
-		do {
+
+		list_for_each_entry_rcu(tmp_neigh_node,
+				&primary_orig_node->bond_list, bonding_list) {
+			if (!first_candidate)
+				first_candidate = tmp_neigh_node;
 			/* recv_if == NULL on the first node. */
-			if (router->if_incoming != recv_if)
+			if (tmp_neigh_node->if_incoming != recv_if &&
+			    atomic_inc_not_zero(&tmp_neigh_node->refcount)) {
+				router = tmp_neigh_node;
 				break;
+			}
+		}
+
+		/* use the first candidate if nothing was found. */
+		if (!router && first_candidate &&
+		    atomic_inc_not_zero(&first_candidate->refcount))
+			router = first_candidate;
 
-			router = router->next_bond_candidate;
-		} while (router != first_candidate);
+		if (!router) {
+			rcu_read_unlock();
+			return NULL;
+		}
 
-		primary_orig_node->bond.selected = router->next_bond_candidate;
+		/* selected should point to the next element
+		 * after the current router */
+		spin_lock_bh(&primary_orig_node->neigh_list_lock);
+		/* this is a list_move(), which unfortunately
+		 * does not exist as rcu version */
+		list_del_rcu(&primary_orig_node->bond_list);
+		list_add_rcu(&primary_orig_node->bond_list,
+				&router->bonding_list);
+		spin_unlock_bh(&primary_orig_node->neigh_list_lock);
 
 	} else {
 		/* if bonding is disabled, use the best of the
 		 * remaining candidates which are not using
 		 * this interface. */
-		best_router = first_candidate;
+		list_for_each_entry_rcu(tmp_neigh_node,
+			&primary_orig_node->bond_list, bonding_list) {
+			if (!first_candidate)
+				first_candidate = tmp_neigh_node;
 
-		do {
 			/* recv_if == NULL on the first node. */
-			if ((router->if_incoming != recv_if) &&
-				(router->tq_avg > best_router->tq_avg))
-					best_router = router;
+			if (tmp_neigh_node->if_incoming == recv_if)
+				continue;
 
-			router = router->next_bond_candidate;
-		} while (router != first_candidate);
+			if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+				continue;
 
-		router = best_router;
-	}
+			/* if we don't have a router yet
+			 * or this one is better, choose it. */
+			if ((!router) ||
+			    (tmp_neigh_node->tq_avg > router->tq_avg)) {
+				/* decrement refcount of
+				 * previously selected router */
+				if (router)
+					neigh_node_free_ref(router);
+
+				router = tmp_neigh_node;
+				atomic_inc_not_zero(&router->refcount);
+			}
+
+			neigh_node_free_ref(tmp_neigh_node);
+		}
 
+		/* use the first candidate if nothing was found. */
+		if (!router && first_candidate &&
+		    atomic_inc_not_zero(&first_candidate->refcount))
+			router = first_candidate;
+	}
+return_router:
+	rcu_read_unlock();
 	return router;
 }
 
@@ -1136,17 +1263,14 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
 	return 0;
 }
 
-int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
-			 int hdr_size)
+int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
-	struct orig_node *orig_node;
-	struct neigh_node *router;
-	struct batman_if *batman_if;
-	uint8_t dstaddr[ETH_ALEN];
+	struct orig_node *orig_node = NULL;
+	struct neigh_node *neigh_node = NULL;
 	struct unicast_packet *unicast_packet;
 	struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb);
-	int ret;
+	int ret = NET_RX_DROP;
 	struct sk_buff *new_skb;
 
 	unicast_packet = (struct unicast_packet *)skb->data;
@@ -1156,53 +1280,51 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
 		pr_debug("Warning - can't forward unicast packet from %pM to "
 			 "%pM: ttl exceeded\n", ethhdr->h_source,
 			 unicast_packet->dest);
-		return NET_RX_DROP;
+		goto out;
 	}
 
 	/* get routing information */
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)
-		     hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
-			       unicast_packet->dest));
-
-	router = find_router(bat_priv, orig_node, recv_if);
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, unicast_packet->dest);
 
-	if (!router) {
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
-		return NET_RX_DROP;
-	}
+	if (!orig_node)
+		goto unlock;
 
-	/* don't lock while sending the packets ... we therefore
-	 * copy the required data before sending */
+	rcu_read_unlock();
 
-	batman_if = router->if_incoming;
-	memcpy(dstaddr, router->addr, ETH_ALEN);
+	/* find_router() increases neigh_nodes refcount if found. */
+	neigh_node = find_router(bat_priv, orig_node, recv_if);
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	if (!neigh_node)
+		goto out;
 
 	/* create a copy of the skb, if needed, to modify it. */
 	if (skb_cow(skb, sizeof(struct ethhdr)) < 0)
-		return NET_RX_DROP;
+		goto out;
 
 	unicast_packet = (struct unicast_packet *)skb->data;
 
 	if (unicast_packet->packet_type == BAT_UNICAST &&
 	    atomic_read(&bat_priv->fragmentation) &&
-	    skb->len > batman_if->net_dev->mtu)
-		return frag_send_skb(skb, bat_priv, batman_if,
-				     dstaddr);
+	    skb->len > neigh_node->if_incoming->net_dev->mtu) {
+		ret = frag_send_skb(skb, bat_priv,
+				    neigh_node->if_incoming, neigh_node->addr);
+		goto out;
+	}
 
 	if (unicast_packet->packet_type == BAT_UNICAST_FRAG &&
-	    2 * skb->len - hdr_size <= batman_if->net_dev->mtu) {
+	    frag_can_reassemble(skb, neigh_node->if_incoming->net_dev->mtu)) {
 
 		ret = frag_reassemble_skb(skb, bat_priv, &new_skb);
 
 		if (ret == NET_RX_DROP)
-			return NET_RX_DROP;
+			goto out;
 
 		/* packet was buffered for late merge */
-		if (!new_skb)
-			return NET_RX_SUCCESS;
+		if (!new_skb) {
+			ret = NET_RX_SUCCESS;
+			goto out;
+		}
 
 		skb = new_skb;
 		unicast_packet = (struct unicast_packet *)skb->data;
@@ -1212,12 +1334,21 @@ int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
 	unicast_packet->ttl--;
 
 	/* route it */
-	send_skb_packet(skb, batman_if, dstaddr);
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = NET_RX_SUCCESS;
+	goto out;
 
-	return NET_RX_SUCCESS;
+unlock:
+	rcu_read_unlock();
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+	return ret;
 }
 
-int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
+int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct unicast_packet *unicast_packet;
 	int hdr_size = sizeof(struct unicast_packet);
@@ -1233,10 +1364,10 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
 		return NET_RX_SUCCESS;
 	}
 
-	return route_unicast_packet(skb, recv_if, hdr_size);
+	return route_unicast_packet(skb, recv_if);
 }
 
-int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
+int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
 	struct unicast_frag_packet *unicast_packet;
@@ -1266,89 +1397,96 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
 		return NET_RX_SUCCESS;
 	}
 
-	return route_unicast_packet(skb, recv_if, hdr_size);
+	return route_unicast_packet(skb, recv_if);
 }
 
 
-int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
+int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
-	struct orig_node *orig_node;
+	struct orig_node *orig_node = NULL;
 	struct bcast_packet *bcast_packet;
 	struct ethhdr *ethhdr;
 	int hdr_size = sizeof(struct bcast_packet);
+	int ret = NET_RX_DROP;
 	int32_t seq_diff;
 
 	/* drop packet if it has not necessary minimum size */
 	if (unlikely(!pskb_may_pull(skb, hdr_size)))
-		return NET_RX_DROP;
+		goto out;
 
 	ethhdr = (struct ethhdr *)skb_mac_header(skb);
 
 	/* packet with broadcast indication but unicast recipient */
 	if (!is_broadcast_ether_addr(ethhdr->h_dest))
-		return NET_RX_DROP;
+		goto out;
 
 	/* packet with broadcast sender address */
 	if (is_broadcast_ether_addr(ethhdr->h_source))
-		return NET_RX_DROP;
+		goto out;
 
 	/* ignore broadcasts sent by myself */
 	if (is_my_mac(ethhdr->h_source))
-		return NET_RX_DROP;
+		goto out;
 
 	bcast_packet = (struct bcast_packet *)skb->data;
 
 	/* ignore broadcasts originated by myself */
 	if (is_my_mac(bcast_packet->orig))
-		return NET_RX_DROP;
+		goto out;
 
 	if (bcast_packet->ttl < 2)
-		return NET_RX_DROP;
+		goto out;
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)
-		     hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
-			       bcast_packet->orig));
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, bcast_packet->orig);
 
-	if (!orig_node) {
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
-		return NET_RX_DROP;
-	}
+	if (!orig_node)
+		goto rcu_unlock;
+
+	rcu_read_unlock();
+
+	spin_lock_bh(&orig_node->bcast_seqno_lock);
 
 	/* check whether the packet is a duplicate */
-	if (get_bit_status(orig_node->bcast_bits,
-			   orig_node->last_bcast_seqno,
-			   ntohl(bcast_packet->seqno))) {
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
-		return NET_RX_DROP;
-	}
+	if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno,
+			   ntohl(bcast_packet->seqno)))
+		goto spin_unlock;
 
 	seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
 
 	/* check whether the packet is old and the host just restarted. */
 	if (window_protected(bat_priv, seq_diff,
-			     &orig_node->bcast_seqno_reset)) {
-		spin_unlock_bh(&bat_priv->orig_hash_lock);
-		return NET_RX_DROP;
-	}
+			     &orig_node->bcast_seqno_reset))
+		goto spin_unlock;
 
 	/* mark broadcast in flood history, update window position
 	 * if required. */
 	if (bit_get_packet(bat_priv, orig_node->bcast_bits, seq_diff, 1))
 		orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	spin_unlock_bh(&orig_node->bcast_seqno_lock);
+
 	/* rebroadcast packet */
 	add_bcast_packet_to_list(bat_priv, skb);
 
 	/* broadcast for me */
 	interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
+	ret = NET_RX_SUCCESS;
+	goto out;
 
-	return NET_RX_SUCCESS;
+rcu_unlock:
+	rcu_read_unlock();
+	goto out;
+spin_unlock:
+	spin_unlock_bh(&orig_node->bcast_seqno_lock);
+out:
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+	return ret;
 }
 
-int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if)
+int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
 	struct vis_packet *vis_packet;
 	struct ethhdr *ethhdr;
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h
index f108f23..b5a064c 100644
--- a/net/batman-adv/routing.h
+++ b/net/batman-adv/routing.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -22,27 +22,25 @@
 #ifndef _NET_BATMAN_ADV_ROUTING_H_
 #define _NET_BATMAN_ADV_ROUTING_H_
 
-#include "types.h"
-
-void slide_own_bcast_window(struct batman_if *batman_if);
+void slide_own_bcast_window(struct hard_iface *hard_iface);
 void receive_bat_packet(struct ethhdr *ethhdr,
 				struct batman_packet *batman_packet,
 				unsigned char *hna_buff, int hna_buff_len,
-				struct batman_if *if_incoming);
+				struct hard_iface *if_incoming);
 void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
 		   struct neigh_node *neigh_node, unsigned char *hna_buff,
 		   int hna_buff_len);
-int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
-			 int hdr_size);
-int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if);
-int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if);
-int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if);
-int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if);
-int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if);
-int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if);
+int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 struct neigh_node *find_router(struct bat_priv *bat_priv,
-		struct orig_node *orig_node, struct batman_if *recv_if);
-void update_bonding_candidates(struct bat_priv *bat_priv,
-			       struct orig_node *orig_node);
+			       struct orig_node *orig_node,
+			       struct hard_iface *recv_if);
+void bonding_candidate_del(struct orig_node *orig_node,
+			   struct neigh_node *neigh_node);
 
 #endif /* _NET_BATMAN_ADV_ROUTING_H_ */
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index b89b9f7..d49e54d 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -25,7 +25,6 @@
 #include "translation-table.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
-#include "types.h"
 #include "vis.h"
 #include "aggregation.h"
 #include "gateway_common.h"
@@ -49,7 +48,7 @@ static unsigned long own_send_time(struct bat_priv *bat_priv)
 }
 
 /* when do we schedule a forwarded packet to be sent */
-static unsigned long forward_send_time(struct bat_priv *bat_priv)
+static unsigned long forward_send_time(void)
 {
 	return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
 }
@@ -57,20 +56,20 @@ static unsigned long forward_send_time(struct bat_priv *bat_priv)
 /* send out an already prepared packet to the given address via the
  * specified batman interface */
 int send_skb_packet(struct sk_buff *skb,
-				struct batman_if *batman_if,
+				struct hard_iface *hard_iface,
 				uint8_t *dst_addr)
 {
 	struct ethhdr *ethhdr;
 
-	if (batman_if->if_status != IF_ACTIVE)
+	if (hard_iface->if_status != IF_ACTIVE)
 		goto send_skb_err;
 
-	if (unlikely(!batman_if->net_dev))
+	if (unlikely(!hard_iface->net_dev))
 		goto send_skb_err;
 
-	if (!(batman_if->net_dev->flags & IFF_UP)) {
+	if (!(hard_iface->net_dev->flags & IFF_UP)) {
 		pr_warning("Interface %s is not up - can't send packet via "
-			   "that interface!\n", batman_if->net_dev->name);
+			   "that interface!\n", hard_iface->net_dev->name);
 		goto send_skb_err;
 	}
 
@@ -81,7 +80,7 @@ int send_skb_packet(struct sk_buff *skb,
 	skb_reset_mac_header(skb);
 
 	ethhdr = (struct ethhdr *) skb_mac_header(skb);
-	memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN);
+	memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN);
 	memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
 	ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
 
@@ -89,7 +88,7 @@ int send_skb_packet(struct sk_buff *skb,
 	skb->priority = TC_PRIO_CONTROL;
 	skb->protocol = __constant_htons(ETH_P_BATMAN);
 
-	skb->dev = batman_if->net_dev;
+	skb->dev = hard_iface->net_dev;
 
 	/* dev_queue_xmit() returns a negative result on error.	 However on
 	 * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
@@ -103,16 +102,16 @@ send_skb_err:
 
 /* Send a packet to a given interface */
 static void send_packet_to_if(struct forw_packet *forw_packet,
-			      struct batman_if *batman_if)
+			      struct hard_iface *hard_iface)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	char *fwd_str;
 	uint8_t packet_num;
 	int16_t buff_pos;
 	struct batman_packet *batman_packet;
 	struct sk_buff *skb;
 
-	if (batman_if->if_status != IF_ACTIVE)
+	if (hard_iface->if_status != IF_ACTIVE)
 		return;
 
 	packet_num = 0;
@@ -127,7 +126,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
 		/* we might have aggregated direct link packets with an
 		 * ordinary base packet */
 		if ((forw_packet->direct_link_flags & (1 << packet_num)) &&
-		    (forw_packet->if_incoming == batman_if))
+		    (forw_packet->if_incoming == hard_iface))
 			batman_packet->flags |= DIRECTLINK;
 		else
 			batman_packet->flags &= ~DIRECTLINK;
@@ -143,7 +142,8 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
 			batman_packet->tq, batman_packet->ttl,
 			(batman_packet->flags & DIRECTLINK ?
 			 "on" : "off"),
-			batman_if->net_dev->name, batman_if->net_dev->dev_addr);
+			hard_iface->net_dev->name,
+			hard_iface->net_dev->dev_addr);
 
 		buff_pos += sizeof(struct batman_packet) +
 			(batman_packet->num_hna * ETH_ALEN);
@@ -155,13 +155,13 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
 	/* create clone because function is called more than once */
 	skb = skb_clone(forw_packet->skb, GFP_ATOMIC);
 	if (skb)
-		send_skb_packet(skb, batman_if, broadcast_addr);
+		send_skb_packet(skb, hard_iface, broadcast_addr);
 }
 
 /* send a batman packet */
 static void send_packet(struct forw_packet *forw_packet)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	struct net_device *soft_iface;
 	struct bat_priv *bat_priv;
 	struct batman_packet *batman_packet =
@@ -205,17 +205,17 @@ static void send_packet(struct forw_packet *forw_packet)
 
 	/* broadcast on every interface */
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if (batman_if->soft_iface != soft_iface)
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if (hard_iface->soft_iface != soft_iface)
 			continue;
 
-		send_packet_to_if(forw_packet, batman_if);
+		send_packet_to_if(forw_packet, hard_iface);
 	}
 	rcu_read_unlock();
 }
 
 static void rebuild_batman_packet(struct bat_priv *bat_priv,
-				  struct batman_if *batman_if)
+				  struct hard_iface *hard_iface)
 {
 	int new_len;
 	unsigned char *new_buff;
@@ -227,7 +227,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv,
 
 	/* keep old buffer if kmalloc should fail */
 	if (new_buff) {
-		memcpy(new_buff, batman_if->packet_buff,
+		memcpy(new_buff, hard_iface->packet_buff,
 		       sizeof(struct batman_packet));
 		batman_packet = (struct batman_packet *)new_buff;
 
@@ -235,21 +235,21 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv,
 				new_buff + sizeof(struct batman_packet),
 				new_len - sizeof(struct batman_packet));
 
-		kfree(batman_if->packet_buff);
-		batman_if->packet_buff = new_buff;
-		batman_if->packet_len = new_len;
+		kfree(hard_iface->packet_buff);
+		hard_iface->packet_buff = new_buff;
+		hard_iface->packet_len = new_len;
 	}
 }
 
-void schedule_own_packet(struct batman_if *batman_if)
+void schedule_own_packet(struct hard_iface *hard_iface)
 {
-	struct bat_priv *bat_priv = netdev_priv(batman_if->soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
 	unsigned long send_time;
 	struct batman_packet *batman_packet;
 	int vis_server;
 
-	if ((batman_if->if_status == IF_NOT_IN_USE) ||
-	    (batman_if->if_status == IF_TO_BE_REMOVED))
+	if ((hard_iface->if_status == IF_NOT_IN_USE) ||
+	    (hard_iface->if_status == IF_TO_BE_REMOVED))
 		return;
 
 	vis_server = atomic_read(&bat_priv->vis_mode);
@@ -261,51 +261,51 @@ void schedule_own_packet(struct batman_if *batman_if)
 	 * outdated packets (especially uninitialized mac addresses) in the
 	 * packet queue
 	 */
-	if (batman_if->if_status == IF_TO_BE_ACTIVATED)
-		batman_if->if_status = IF_ACTIVE;
+	if (hard_iface->if_status == IF_TO_BE_ACTIVATED)
+		hard_iface->if_status = IF_ACTIVE;
 
 	/* if local hna has changed and interface is a primary interface */
 	if ((atomic_read(&bat_priv->hna_local_changed)) &&
-	    (batman_if == bat_priv->primary_if))
-		rebuild_batman_packet(bat_priv, batman_if);
+	    (hard_iface == bat_priv->primary_if))
+		rebuild_batman_packet(bat_priv, hard_iface);
 
 	/**
 	 * NOTE: packet_buff might just have been re-allocated in
 	 * rebuild_batman_packet()
 	 */
-	batman_packet = (struct batman_packet *)batman_if->packet_buff;
+	batman_packet = (struct batman_packet *)hard_iface->packet_buff;
 
 	/* change sequence number to network order */
 	batman_packet->seqno =
-		htonl((uint32_t)atomic_read(&batman_if->seqno));
+		htonl((uint32_t)atomic_read(&hard_iface->seqno));
 
 	if (vis_server == VIS_TYPE_SERVER_SYNC)
 		batman_packet->flags |= VIS_SERVER;
 	else
 		batman_packet->flags &= ~VIS_SERVER;
 
-	if ((batman_if == bat_priv->primary_if) &&
+	if ((hard_iface == bat_priv->primary_if) &&
 	    (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER))
 		batman_packet->gw_flags =
 				(uint8_t)atomic_read(&bat_priv->gw_bandwidth);
 	else
 		batman_packet->gw_flags = 0;
 
-	atomic_inc(&batman_if->seqno);
+	atomic_inc(&hard_iface->seqno);
 
-	slide_own_bcast_window(batman_if);
+	slide_own_bcast_window(hard_iface);
 	send_time = own_send_time(bat_priv);
 	add_bat_packet_to_list(bat_priv,
-			       batman_if->packet_buff,
-			       batman_if->packet_len,
-			       batman_if, 1, send_time);
+			       hard_iface->packet_buff,
+			       hard_iface->packet_len,
+			       hard_iface, 1, send_time);
 }
 
 void schedule_forward_packet(struct orig_node *orig_node,
 			     struct ethhdr *ethhdr,
 			     struct batman_packet *batman_packet,
 			     uint8_t directlink, int hna_buff_len,
-			     struct batman_if *if_incoming)
+			     struct hard_iface *if_incoming)
 {
 	struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface);
 	unsigned char in_tq, in_ttl, tq_avg = 0;
@@ -327,7 +327,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
 	if ((orig_node->router) && (orig_node->router->tq_avg != 0)) {
 
 		/* rebroadcast ogm of best ranking neighbor as is */
-		if (!compare_orig(orig_node->router->addr, ethhdr->h_source)) {
+		if (!compare_eth(orig_node->router->addr, ethhdr->h_source)) {
 			batman_packet->tq = orig_node->router->tq_avg;
 
 			if (orig_node->router->last_ttl)
@@ -356,7 +356,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
 	else
 		batman_packet->flags &= ~DIRECTLINK;
 
-	send_time = forward_send_time(bat_priv);
+	send_time = forward_send_time();
 	add_bat_packet_to_list(bat_priv,
 			       (unsigned char *)batman_packet,
 			       sizeof(struct batman_packet) + hna_buff_len,
@@ -444,7 +444,7 @@ out:
 
 static void send_outstanding_bcast_packet(struct work_struct *work)
 {
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	struct delayed_work *delayed_work =
 		container_of(work, struct delayed_work, work);
 	struct forw_packet *forw_packet =
@@ -462,14 +462,14 @@ static void send_outstanding_bcast_packet(struct work_struct *work)
 
 	/* rebroadcast packet */
 	rcu_read_lock();
-	list_for_each_entry_rcu(batman_if, &if_list, list) {
-		if (batman_if->soft_iface != soft_iface)
+	list_for_each_entry_rcu(hard_iface, &hardif_list, list) {
+		if (hard_iface->soft_iface != soft_iface)
 			continue;
 
 		/* send a copy of the saved skb */
 		skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
 		if (skb1)
-			send_skb_packet(skb1, batman_if, broadcast_addr);
+			send_skb_packet(skb1, hard_iface, broadcast_addr);
 	}
 	rcu_read_unlock();
 
@@ -522,15 +522,15 @@ out:
 }
 
 void purge_outstanding_packets(struct bat_priv *bat_priv,
-			       struct batman_if *batman_if)
+			       struct hard_iface *hard_iface)
 {
 	struct forw_packet *forw_packet;
 	struct hlist_node *tmp_node, *safe_tmp_node;
 
-	if (batman_if)
+	if (hard_iface)
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"purge_outstanding_packets(): %s\n",
-			batman_if->net_dev->name);
+			hard_iface->net_dev->name);
 	else
 		bat_dbg(DBG_BATMAN, bat_priv,
 			"purge_outstanding_packets()\n");
@@ -544,8 +544,8 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
 		 * if purge_outstanding_packets() was called with an argmument
 		 * we delete only packets belonging to the given interface
 		 */
-		if ((batman_if) &&
-		    (forw_packet->if_incoming != batman_if))
+		if ((hard_iface) &&
+		    (forw_packet->if_incoming != hard_iface))
 			continue;
 
 		spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
@@ -568,8 +568,8 @@ void purge_outstanding_packets(struct bat_priv *bat_priv,
 		 * if purge_outstanding_packets() was called with an argmument
 		 * we delete only packets belonging to the given interface
 		 */
-		if ((batman_if) &&
-		    (forw_packet->if_incoming != batman_if))
+		if ((hard_iface) &&
+		    (forw_packet->if_incoming != hard_iface))
 			continue;
 
 		spin_unlock_bh(&bat_priv->forw_bat_list_lock);
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h
index c4cefa8..7b2ff19 100644
--- a/net/batman-adv/send.h
+++ b/net/batman-adv/send.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -22,20 +22,18 @@
 #ifndef _NET_BATMAN_ADV_SEND_H_
 #define _NET_BATMAN_ADV_SEND_H_
 
-#include "types.h"
-
 int send_skb_packet(struct sk_buff *skb,
-				struct batman_if *batman_if,
+				struct hard_iface *hard_iface,
 				uint8_t *dst_addr);
-void schedule_own_packet(struct batman_if *batman_if);
+void schedule_own_packet(struct hard_iface *hard_iface);
 void schedule_forward_packet(struct orig_node *orig_node,
 			     struct ethhdr *ethhdr,
 			     struct batman_packet *batman_packet,
 			     uint8_t directlink, int hna_buff_len,
-			     struct batman_if *if_outgoing);
+			     struct hard_iface *if_outgoing);
 int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb);
 void send_outstanding_bat_packet(struct work_struct *work);
 void purge_outstanding_packets(struct bat_priv *bat_priv,
-			       struct batman_if *batman_if);
+			       struct hard_iface *hard_iface);
 
 #endif /* _NET_BATMAN_ADV_SEND_H_ */
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index e89ede1..9ed2614 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -26,18 +26,15 @@
 #include "send.h"
 #include "bat_debugfs.h"
 #include "translation-table.h"
-#include "types.h"
 #include "hash.h"
 #include "gateway_common.h"
 #include "gateway_client.h"
-#include "send.h"
 #include "bat_sysfs.h"
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
 #include "unicast.h"
-#include "routing.h"
 
 
 static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
@@ -79,20 +76,18 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len)
 	return 0;
 }
 
-static void softif_neigh_free_ref(struct kref *refcount)
+static void softif_neigh_free_rcu(struct rcu_head *rcu)
 {
 	struct softif_neigh *softif_neigh;
 
-	softif_neigh = container_of(refcount, struct softif_neigh, refcount);
+	softif_neigh = container_of(rcu, struct softif_neigh, rcu);
 	kfree(softif_neigh);
 }
 
-static void softif_neigh_free_rcu(struct rcu_head *rcu)
+static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
 {
-	struct softif_neigh *softif_neigh;
-
-	softif_neigh = container_of(rcu, struct softif_neigh, rcu);
-	kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
+	if (atomic_dec_and_test(&softif_neigh->refcount))
+		call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
 }
 
 void softif_neigh_purge(struct bat_priv *bat_priv)
@@ -119,11 +114,10 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
 				 softif_neigh->addr, softif_neigh->vid);
 			softif_neigh_tmp = bat_priv->softif_neigh;
 			bat_priv->softif_neigh = NULL;
-			kref_put(&softif_neigh_tmp->refcount,
-				 softif_neigh_free_ref);
+			softif_neigh_free_ref(softif_neigh_tmp);
 		}
 
-		call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
+		softif_neigh_free_ref(softif_neigh);
 	}
 
 	spin_unlock_bh(&bat_priv->softif_neigh_lock);
@@ -138,14 +132,17 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(softif_neigh, node,
 				 &bat_priv->softif_neigh_list, list) {
-		if (memcmp(softif_neigh->addr, addr, ETH_ALEN) != 0)
+		if (!compare_eth(softif_neigh->addr, addr))
 			continue;
 
 		if (softif_neigh->vid != vid)
 			continue;
 
+		if (!atomic_inc_not_zero(&softif_neigh->refcount))
+			continue;
+
 		softif_neigh->last_seen = jiffies;
-		goto found;
+		goto out;
 	}
 
 	softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
@@ -155,15 +152,14 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
 	memcpy(softif_neigh->addr, addr, ETH_ALEN);
 	softif_neigh->vid = vid;
 	softif_neigh->last_seen = jiffies;
-	kref_init(&softif_neigh->refcount);
+	/* initialize with 2 - caller decrements counter by one */
+	atomic_set(&softif_neigh->refcount, 2);
 
 	INIT_HLIST_NODE(&softif_neigh->list);
 	spin_lock_bh(&bat_priv->softif_neigh_lock);
 	hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
 	spin_unlock_bh(&bat_priv->softif_neigh_lock);
 
-found:
-	kref_get(&softif_neigh->refcount);
 out:
 	rcu_read_unlock();
 	return softif_neigh;
@@ -175,8 +171,6 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	struct softif_neigh *softif_neigh;
 	struct hlist_node *node;
-	size_t buf_size, pos;
-	char *buff;
 
 	if (!bat_priv->primary_if) {
 		return seq_printf(seq, "BATMAN mesh %s disabled - "
@@ -186,33 +180,15 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
 
 	seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
 
-	buf_size = 1;
-	/* Estimate length for: "   xx:xx:xx:xx:xx:xx\n" */
 	rcu_read_lock();
 	hlist_for_each_entry_rcu(softif_neigh, node,
 				 &bat_priv->softif_neigh_list, list)
-		buf_size += 30;
-	rcu_read_unlock();
-
-	buff = kmalloc(buf_size, GFP_ATOMIC);
-	if (!buff)
-		return -ENOMEM;
-
-	buff[0] = '\0';
-	pos = 0;
-
-	rcu_read_lock();
-	hlist_for_each_entry_rcu(softif_neigh, node,
-				 &bat_priv->softif_neigh_list, list) {
-		pos += snprintf(buff + pos, 31, "%s %pM (vid: %d)\n",
+		seq_printf(seq, "%s %pM (vid: %d)\n",
 				bat_priv->softif_neigh == softif_neigh
 				? "=>" : "  ", softif_neigh->addr,
 				softif_neigh->vid);
-	}
 	rcu_read_unlock();
 
-	seq_printf(seq, "%s", buff);
-	kfree(buff);
 	return 0;
 }
 
@@ -267,7 +243,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
 			 softif_neigh->addr, softif_neigh->vid);
 		softif_neigh_tmp = bat_priv->softif_neigh;
 		bat_priv->softif_neigh = softif_neigh;
-		kref_put(&softif_neigh_tmp->refcount, softif_neigh_free_ref);
+		softif_neigh_free_ref(softif_neigh_tmp);
 		/* we need to hold the additional reference */
 		goto err;
 	}
@@ -285,7 +261,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
 	}
 
 out:
-	kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
+	softif_neigh_free_ref(softif_neigh);
 err:
 	kfree_skb(skb);
 	return;
@@ -438,7 +414,7 @@ end:
 }
 
 void interface_rx(struct net_device *soft_iface,
-		  struct sk_buff *skb, struct batman_if *recv_if,
+		  struct sk_buff *skb, struct hard_iface *recv_if,
 		  int hdr_size)
 {
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
@@ -486,7 +462,7 @@ void interface_rx(struct net_device *soft_iface,
 
 		memcpy(unicast_packet->dest,
 		       bat_priv->softif_neigh->addr, ETH_ALEN);
-		ret = route_unicast_packet(skb, recv_if, hdr_size);
+		ret = route_unicast_packet(skb, recv_if);
 		if (ret == NET_RX_DROP)
 			goto dropped;
 
@@ -646,6 +622,19 @@ void softif_destroy(struct net_device *soft_iface)
 	unregister_netdevice(soft_iface);
 }
 
+int softif_is_valid(struct net_device *net_dev)
+{
+#ifdef HAVE_NET_DEVICE_OPS
+	if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
+		return 1;
+#else
+	if (net_dev->hard_start_xmit == interface_tx)
+		return 1;
+#endif
+
+	return 0;
+}
+
 /* ethtool */
 static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h
index 02b7733..4789b6f 100644
--- a/net/batman-adv/soft-interface.h
+++ b/net/batman-adv/soft-interface.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner
  *
@@ -27,9 +27,10 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset);
 void softif_neigh_purge(struct bat_priv *bat_priv);
 int interface_tx(struct sk_buff *skb, struct net_device *soft_iface);
 void interface_rx(struct net_device *soft_iface,
-		  struct sk_buff *skb, struct batman_if *recv_if,
+		  struct sk_buff *skb, struct hard_iface *recv_if,
 		  int hdr_size);
 struct net_device *softif_create(char *name);
 void softif_destroy(struct net_device *soft_iface);
+int softif_is_valid(struct net_device *net_dev);
 
 #endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index a633b5a4..8d15b48 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -22,7 +22,6 @@
 #include "main.h"
 #include "translation-table.h"
 #include "soft-interface.h"
-#include "types.h"
 #include "hash.h"
 #include "originator.h"
 
@@ -31,12 +30,85 @@ static void _hna_global_del_orig(struct bat_priv *bat_priv,
 				 struct hna_global_entry *hna_global_entry,
 				 char *message);
 
+/* returns 1 if they are the same mac addr */
+static int compare_lhna(struct hlist_node *node, void *data2)
+{
+	void *data1 = container_of(node, struct hna_local_entry, hash_entry);
+
+	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
+/* returns 1 if they are the same mac addr */
+static int compare_ghna(struct hlist_node *node, void *data2)
+{
+	void *data1 = container_of(node, struct hna_global_entry, hash_entry);
+
+	return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
+}
+
 static void hna_local_start_timer(struct bat_priv *bat_priv)
 {
 	INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge);
 	queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ);
 }
 
+static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv,
+						   void *data)
+{
+	struct hashtable_t *hash = bat_priv->hna_local_hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct hna_local_entry *hna_local_entry, *hna_local_entry_tmp = NULL;
+	int index;
+
+	if (!hash)
+		return NULL;
+
+	index = choose_orig(data, hash->size);
+	head = &hash->table[index];
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(hna_local_entry, node, head, hash_entry) {
+		if (!compare_eth(hna_local_entry, data))
+			continue;
+
+		hna_local_entry_tmp = hna_local_entry;
+		break;
+	}
+	rcu_read_unlock();
+
+	return hna_local_entry_tmp;
+}
+
+static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv,
+						     void *data)
+{
+	struct hashtable_t *hash = bat_priv->hna_global_hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct hna_global_entry *hna_global_entry;
+	struct hna_global_entry *hna_global_entry_tmp = NULL;
+	int index;
+
+	if (!hash)
+		return NULL;
+
+	index = choose_orig(data, hash->size);
+	head = &hash->table[index];
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(hna_global_entry, node, head, hash_entry) {
+		if (!compare_eth(hna_global_entry, data))
+			continue;
+
+		hna_global_entry_tmp = hna_global_entry;
+		break;
+	}
+	rcu_read_unlock();
+
+	return hna_global_entry_tmp;
+}
+
 int hna_local_init(struct bat_priv *bat_priv)
 {
 	if (bat_priv->hna_local_hash)
@@ -61,10 +133,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
 	int required_bytes;
 
 	spin_lock_bh(&bat_priv->hna_lhash_lock);
-	hna_local_entry =
-		((struct hna_local_entry *)hash_find(bat_priv->hna_local_hash,
-						     compare_orig, choose_orig,
-						     addr));
+	hna_local_entry = hna_local_hash_find(bat_priv, addr);
 	spin_unlock_bh(&bat_priv->hna_lhash_lock);
 
 	if (hna_local_entry) {
@@ -100,15 +169,15 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
 	hna_local_entry->last_seen = jiffies;
 
 	/* the batman interface mac address should never be purged */
-	if (compare_orig(addr, soft_iface->dev_addr))
+	if (compare_eth(addr, soft_iface->dev_addr))
 		hna_local_entry->never_purge = 1;
 	else
 		hna_local_entry->never_purge = 0;
 
 	spin_lock_bh(&bat_priv->hna_lhash_lock);
 
-	hash_add(bat_priv->hna_local_hash, compare_orig, choose_orig,
-		 hna_local_entry);
+	hash_add(bat_priv->hna_local_hash, compare_lhna, choose_orig,
+		 hna_local_entry, &hna_local_entry->hash_entry);
 	bat_priv->num_local_hna++;
 	atomic_set(&bat_priv->hna_local_changed, 1);
 
@@ -117,9 +186,7 @@ void hna_local_add(struct net_device *soft_iface, uint8_t *addr)
 	/* remove address from global hash if present */
 	spin_lock_bh(&bat_priv->hna_ghash_lock);
 
-	hna_global_entry = ((struct hna_global_entry *)
-				hash_find(bat_priv->hna_global_hash,
-					  compare_orig, choose_orig, addr));
+	hna_global_entry = hna_global_hash_find(bat_priv, addr);
 
 	if (hna_global_entry)
 		_hna_global_del_orig(bat_priv, hna_global_entry,
@@ -133,28 +200,27 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv,
 {
 	struct hashtable_t *hash = bat_priv->hna_local_hash;
 	struct hna_local_entry *hna_local_entry;
-	struct element_t *bucket;
-	int i;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	int count = 0;
+	int i, count = 0;
 
 	spin_lock_bh(&bat_priv->hna_lhash_lock);
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(hna_local_entry, node,
+					 head, hash_entry) {
 			if (buff_len < (count + 1) * ETH_ALEN)
 				break;
 
-			hna_local_entry = bucket->data;
 			memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr,
 			       ETH_ALEN);
 
 			count++;
 		}
+		rcu_read_unlock();
 	}
 
 	/* if we did not get all new local hnas see you next time  ;-) */
@@ -171,12 +237,11 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	struct hashtable_t *hash = bat_priv->hna_local_hash;
 	struct hna_local_entry *hna_local_entry;
-	int i;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	size_t buf_size, pos;
 	char *buff;
+	int i;
 
 	if (!bat_priv->primary_if) {
 		return seq_printf(seq, "BATMAN mesh %s disabled - "
@@ -195,8 +260,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each(walk, head)
+		rcu_read_lock();
+		__hlist_for_each_rcu(node, head)
 			buf_size += 21;
+		rcu_read_unlock();
 	}
 
 	buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -204,18 +271,20 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
 		spin_unlock_bh(&bat_priv->hna_lhash_lock);
 		return -ENOMEM;
 	}
+
 	buff[0] = '\0';
 	pos = 0;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			hna_local_entry = bucket->data;
-
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(hna_local_entry, node,
+					 head, hash_entry) {
 			pos += snprintf(buff + pos, 22, " * %pM\n",
 					hna_local_entry->addr);
 		}
+		rcu_read_unlock();
 	}
 
 	spin_unlock_bh(&bat_priv->hna_lhash_lock);
@@ -225,9 +294,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
-static void _hna_local_del(void *data, void *arg)
+static void _hna_local_del(struct hlist_node *node, void *arg)
 {
 	struct bat_priv *bat_priv = (struct bat_priv *)arg;
+	void *data = container_of(node, struct hna_local_entry, hash_entry);
 
 	kfree(data);
 	bat_priv->num_local_hna--;
@@ -241,9 +311,9 @@ static void hna_local_del(struct bat_priv *bat_priv,
 	bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
 		hna_local_entry->addr, message);
 
-	hash_remove(bat_priv->hna_local_hash, compare_orig, choose_orig,
+	hash_remove(bat_priv->hna_local_hash, compare_lhna, choose_orig,
 		    hna_local_entry->addr);
-	_hna_local_del(hna_local_entry, bat_priv);
+	_hna_local_del(&hna_local_entry->hash_entry, bat_priv);
 }
 
 void hna_local_remove(struct bat_priv *bat_priv,
@@ -253,9 +323,7 @@ void hna_local_remove(struct bat_priv *bat_priv,
 
 	spin_lock_bh(&bat_priv->hna_lhash_lock);
 
-	hna_local_entry = (struct hna_local_entry *)
-		hash_find(bat_priv->hna_local_hash, compare_orig, choose_orig,
-			  addr);
+	hna_local_entry = hna_local_hash_find(bat_priv, addr);
 
 	if (hna_local_entry)
 		hna_local_del(bat_priv, hna_local_entry, message);
@@ -271,27 +339,29 @@ static void hna_local_purge(struct work_struct *work)
 		container_of(delayed_work, struct bat_priv, hna_work);
 	struct hashtable_t *hash = bat_priv->hna_local_hash;
 	struct hna_local_entry *hna_local_entry;
-	int i;
-	struct hlist_node *walk, *safe;
+	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	unsigned long timeout;
+	int i;
 
 	spin_lock_bh(&bat_priv->hna_lhash_lock);
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) {
-			hna_local_entry = bucket->data;
+		hlist_for_each_entry_safe(hna_local_entry, node, node_tmp,
+					  head, hash_entry) {
+			if (hna_local_entry->never_purge)
+				continue;
 
 			timeout = hna_local_entry->last_seen;
 			timeout += LOCAL_HNA_TIMEOUT * HZ;
 
-			if ((!hna_local_entry->never_purge) &&
-			    time_after(jiffies, timeout))
-				hna_local_del(bat_priv, hna_local_entry,
-					"address timed out");
+			if (time_before(jiffies, timeout))
+				continue;
+
+			hna_local_del(bat_priv, hna_local_entry,
+				      "address timed out");
 		}
 	}
 
@@ -335,9 +405,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
 		spin_lock_bh(&bat_priv->hna_ghash_lock);
 
 		hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
-		hna_global_entry = (struct hna_global_entry *)
-			hash_find(bat_priv->hna_global_hash, compare_orig,
-				  choose_orig, hna_ptr);
+		hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr);
 
 		if (!hna_global_entry) {
 			spin_unlock_bh(&bat_priv->hna_ghash_lock);
@@ -357,8 +425,9 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
 				hna_global_entry->addr, orig_node->orig);
 
 			spin_lock_bh(&bat_priv->hna_ghash_lock);
-			hash_add(bat_priv->hna_global_hash, compare_orig,
-				 choose_orig, hna_global_entry);
+			hash_add(bat_priv->hna_global_hash, compare_ghna,
+				 choose_orig, hna_global_entry,
+				 &hna_global_entry->hash_entry);
 
 		}
 
@@ -369,9 +438,7 @@ void hna_global_add_orig(struct bat_priv *bat_priv,
 		spin_lock_bh(&bat_priv->hna_lhash_lock);
 
 		hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN);
-		hna_local_entry = (struct hna_local_entry *)
-			hash_find(bat_priv->hna_local_hash, compare_orig,
-				  choose_orig, hna_ptr);
+		hna_local_entry = hna_local_hash_find(bat_priv, hna_ptr);
 
 		if (hna_local_entry)
 			hna_local_del(bat_priv, hna_local_entry,
@@ -401,12 +468,11 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
 	struct bat_priv *bat_priv = netdev_priv(net_dev);
 	struct hashtable_t *hash = bat_priv->hna_global_hash;
 	struct hna_global_entry *hna_global_entry;
-	int i;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	size_t buf_size, pos;
 	char *buff;
+	int i;
 
 	if (!bat_priv->primary_if) {
 		return seq_printf(seq, "BATMAN mesh %s disabled - "
@@ -424,8 +490,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each(walk, head)
+		rcu_read_lock();
+		__hlist_for_each_rcu(node, head)
 			buf_size += 43;
+		rcu_read_unlock();
 	}
 
 	buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -439,14 +507,15 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset)
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			hna_global_entry = bucket->data;
-
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(hna_global_entry, node,
+					 head, hash_entry) {
 			pos += snprintf(buff + pos, 44,
 					" * %pM via %pM\n",
 					hna_global_entry->addr,
 					hna_global_entry->orig_node->orig);
 		}
+		rcu_read_unlock();
 	}
 
 	spin_unlock_bh(&bat_priv->hna_ghash_lock);
@@ -465,7 +534,7 @@ static void _hna_global_del_orig(struct bat_priv *bat_priv,
 		hna_global_entry->addr, hna_global_entry->orig_node->orig,
 		message);
 
-	hash_remove(bat_priv->hna_global_hash, compare_orig, choose_orig,
+	hash_remove(bat_priv->hna_global_hash, compare_ghna, choose_orig,
 		    hna_global_entry->addr);
 	kfree(hna_global_entry);
 }
@@ -484,9 +553,7 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
 
 	while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) {
 		hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN);
-		hna_global_entry = (struct hna_global_entry *)
-			hash_find(bat_priv->hna_global_hash, compare_orig,
-				  choose_orig, hna_ptr);
+		hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr);
 
 		if ((hna_global_entry) &&
 		    (hna_global_entry->orig_node == orig_node))
@@ -503,8 +570,10 @@ void hna_global_del_orig(struct bat_priv *bat_priv,
 	orig_node->hna_buff = NULL;
 }
 
-static void hna_global_del(void *data, void *arg)
+static void hna_global_del(struct hlist_node *node, void *arg)
 {
+	void *data = container_of(node, struct hna_global_entry, hash_entry);
+
 	kfree(data);
 }
 
@@ -520,15 +589,20 @@ void hna_global_free(struct bat_priv *bat_priv)
 struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
 {
 	struct hna_global_entry *hna_global_entry;
+	struct orig_node *orig_node = NULL;
 
 	spin_lock_bh(&bat_priv->hna_ghash_lock);
-	hna_global_entry = (struct hna_global_entry *)
-				hash_find(bat_priv->hna_global_hash,
-					  compare_orig, choose_orig, addr);
-	spin_unlock_bh(&bat_priv->hna_ghash_lock);
+	hna_global_entry = hna_global_hash_find(bat_priv, addr);
 
 	if (!hna_global_entry)
-		return NULL;
+		goto out;
 
-	return hna_global_entry->orig_node;
+	if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount))
+		goto out;
+
+	orig_node = hna_global_entry->orig_node;
+
+out:
+	spin_unlock_bh(&bat_priv->hna_ghash_lock);
+	return orig_node;
 }
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 10c4c5c..f19931c 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -22,8 +22,6 @@
 #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
 #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
 
-#include "types.h"
-
 int hna_local_init(struct bat_priv *bat_priv);
 void hna_local_add(struct net_device *soft_iface, uint8_t *addr);
 void hna_local_remove(struct bat_priv *bat_priv,
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index bf3f6f5..83445cf 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -33,7 +33,7 @@
 	 sizeof(struct bcast_packet))))
 
 
-struct batman_if {
+struct hard_iface {
 	struct list_head list;
 	int16_t if_num;
 	char if_status;
@@ -43,7 +43,7 @@ struct batman_if {
 	unsigned char *packet_buff;
 	int packet_len;
 	struct kobject *hardif_obj;
-	struct kref refcount;
+	atomic_t refcount;
 	struct packet_type batman_adv_ptype;
 	struct net_device *soft_iface;
 	struct rcu_head rcu;
@@ -70,8 +70,6 @@ struct orig_node {
 	struct neigh_node *router;
 	unsigned long *bcast_own;
 	uint8_t *bcast_own_sum;
-	uint8_t tq_own;
-	int tq_asym_penalty;
 	unsigned long last_valid;
 	unsigned long bcast_seqno_reset;
 	unsigned long batman_seqno_reset;
@@ -83,20 +81,28 @@ struct orig_node {
 	uint8_t last_ttl;
 	unsigned long bcast_bits[NUM_WORDS];
 	uint32_t last_bcast_seqno;
-	struct list_head neigh_list;
+	struct hlist_head neigh_list;
 	struct list_head frag_list;
+	spinlock_t neigh_list_lock; /* protects neighbor list */
+	atomic_t refcount;
+	struct rcu_head rcu;
+	struct hlist_node hash_entry;
+	struct bat_priv *bat_priv;
 	unsigned long last_frag_packet;
-	struct {
-		uint8_t candidates;
-		struct neigh_node *selected;
-	} bond;
+	spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum,
+				  * neigh_node->real_bits,
+				  * neigh_node->real_packet_count */
+	spinlock_t bcast_seqno_lock; /* protects bcast_bits,
+				      *	 last_bcast_seqno */
+	atomic_t bond_candidates;
+	struct list_head bond_list;
 };
 
 struct gw_node {
 	struct hlist_node list;
 	struct orig_node *orig_node;
 	unsigned long deleted;
-	struct kref refcount;
+	atomic_t refcount;
 	struct rcu_head rcu;
 };
 
@@ -105,18 +111,20 @@ struct gw_node {
  *	@last_valid: when last packet via this neighbor was received
  */
 struct neigh_node {
-	struct list_head list;
+	struct hlist_node list;
 	uint8_t addr[ETH_ALEN];
 	uint8_t real_packet_count;
 	uint8_t tq_recv[TQ_GLOBAL_WINDOW_SIZE];
 	uint8_t tq_index;
 	uint8_t tq_avg;
 	uint8_t last_ttl;
-	struct neigh_node *next_bond_candidate;
+	struct list_head bonding_list;
 	unsigned long last_valid;
 	unsigned long real_bits[NUM_WORDS];
+	atomic_t refcount;
+	struct rcu_head rcu;
 	struct orig_node *orig_node;
-	struct batman_if *if_incoming;
+	struct hard_iface *if_incoming;
 };
 
 
@@ -140,7 +148,7 @@ struct bat_priv {
 	struct hlist_head softif_neigh_list;
 	struct softif_neigh *softif_neigh;
 	struct debug_log *debug_log;
-	struct batman_if *primary_if;
+	struct hard_iface *primary_if;
 	struct kobject *mesh_obj;
 	struct dentry *debug_dir;
 	struct hlist_head forw_bat_list;
@@ -151,12 +159,11 @@ struct bat_priv {
 	struct hashtable_t *hna_local_hash;
 	struct hashtable_t *hna_global_hash;
 	struct hashtable_t *vis_hash;
-	spinlock_t orig_hash_lock; /* protects orig_hash */
 	spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
 	spinlock_t forw_bcast_list_lock; /* protects  */
 	spinlock_t hna_lhash_lock; /* protects hna_local_hash */
 	spinlock_t hna_ghash_lock; /* protects hna_global_hash */
-	spinlock_t gw_list_lock; /* protects gw_list */
+	spinlock_t gw_list_lock; /* protects gw_list and curr_gw */
 	spinlock_t vis_hash_lock; /* protects vis_hash */
 	spinlock_t vis_list_lock; /* protects vis_info::recv_list */
 	spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */
@@ -165,7 +172,7 @@ struct bat_priv {
 	struct delayed_work hna_work;
 	struct delayed_work orig_work;
 	struct delayed_work vis_work;
-	struct gw_node *curr_gw;
+	struct gw_node __rcu *curr_gw;  /* rcu protected pointer */
 	struct vis_info *my_vis_info;
 };
 
@@ -188,11 +195,13 @@ struct hna_local_entry {
 	uint8_t addr[ETH_ALEN];
 	unsigned long last_seen;
 	char never_purge;
+	struct hlist_node hash_entry;
 };
 
 struct hna_global_entry {
 	uint8_t addr[ETH_ALEN];
 	struct orig_node *orig_node;
+	struct hlist_node hash_entry;
 };
 
 /**
@@ -208,7 +217,7 @@ struct forw_packet {
 	uint32_t direct_link_flags;
 	uint8_t num_packets;
 	struct delayed_work delayed_work;
-	struct batman_if *if_incoming;
+	struct hard_iface *if_incoming;
 };
 
 /* While scanning for vis-entries of a particular vis-originator
@@ -242,6 +251,7 @@ struct vis_info {
 			     * from.  we should not reply to them. */
 	struct list_head send_list;
 	struct kref refcount;
+	struct hlist_node hash_entry;
 	struct bat_priv *bat_priv;
 	/* this packet might be part of the vis send queue. */
 	struct sk_buff *skb_packet;
@@ -264,7 +274,7 @@ struct softif_neigh {
 	uint8_t addr[ETH_ALEN];
 	unsigned long last_seen;
 	short vid;
-	struct kref refcount;
+	atomic_t refcount;
 	struct rcu_head rcu;
 };
 
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index d1a6113..19f84bd 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2010-2011 B.A.T.M.A.N. contributors:
  *
  * Andreas Langer
  *
@@ -39,8 +39,8 @@ static struct sk_buff *frag_merge_packet(struct list_head *head,
 		(struct unicast_frag_packet *)skb->data;
 	struct sk_buff *tmp_skb;
 	struct unicast_packet *unicast_packet;
-	int hdr_len = sizeof(struct unicast_packet),
-	    uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
+	int hdr_len = sizeof(struct unicast_packet);
+	int uni_diff = sizeof(struct unicast_frag_packet) - hdr_len;
 
 	/* set skb to the first part and tmp_skb to the second part */
 	if (up->flags & UNI_FRAG_HEAD) {
@@ -183,15 +183,10 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 		(struct unicast_frag_packet *)skb->data;
 
 	*new_skb = NULL;
-	spin_lock_bh(&bat_priv->orig_hash_lock);
-	orig_node = ((struct orig_node *)
-		    hash_find(bat_priv->orig_hash, compare_orig, choose_orig,
-			      unicast_packet->orig));
 
-	if (!orig_node) {
-		pr_debug("couldn't find originator in orig_hash\n");
+	orig_node = orig_hash_find(bat_priv, unicast_packet->orig);
+	if (!orig_node)
 		goto out;
-	}
 
 	orig_node->last_frag_packet = jiffies;
 
@@ -215,21 +210,24 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 	/* if not, merge failed */
 	if (*new_skb)
 		ret = NET_RX_SUCCESS;
-out:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
 
+out:
+	if (orig_node)
+		orig_node_free_ref(orig_node);
 	return ret;
 }
 
 int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
-		  struct batman_if *batman_if, uint8_t dstaddr[])
+		  struct hard_iface *hard_iface, uint8_t dstaddr[])
 {
 	struct unicast_packet tmp_uc, *unicast_packet;
 	struct sk_buff *frag_skb;
 	struct unicast_frag_packet *frag1, *frag2;
 	int uc_hdr_len = sizeof(struct unicast_packet);
 	int ucf_hdr_len = sizeof(struct unicast_frag_packet);
-	int data_len = skb->len;
+	int data_len = skb->len - uc_hdr_len;
+	int large_tail = 0;
+	uint16_t seqno;
 
 	if (!bat_priv->primary_if)
 		goto dropped;
@@ -237,10 +235,11 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 	frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len);
 	if (!frag_skb)
 		goto dropped;
+	skb_reserve(frag_skb, ucf_hdr_len);
 
 	unicast_packet = (struct unicast_packet *) skb->data;
 	memcpy(&tmp_uc, unicast_packet, uc_hdr_len);
-	skb_split(skb, frag_skb, data_len / 2);
+	skb_split(skb, frag_skb, data_len / 2 + uc_hdr_len);
 
 	if (my_skb_head_push(skb, ucf_hdr_len - uc_hdr_len) < 0 ||
 	    my_skb_head_push(frag_skb, ucf_hdr_len) < 0)
@@ -258,16 +257,18 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 	memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
 	memcpy(frag2, frag1, sizeof(struct unicast_frag_packet));
 
-	frag1->flags |= UNI_FRAG_HEAD;
-	frag2->flags &= ~UNI_FRAG_HEAD;
+	if (data_len & 1)
+		large_tail = UNI_FRAG_LARGETAIL;
+
+	frag1->flags = UNI_FRAG_HEAD | large_tail;
+	frag2->flags = large_tail;
 
-	frag1->seqno = htons((uint16_t)atomic_inc_return(
-			     &batman_if->frag_seqno));
-	frag2->seqno = htons((uint16_t)atomic_inc_return(
-			     &batman_if->frag_seqno));
+	seqno = atomic_add_return(2, &hard_iface->frag_seqno);
+	frag1->seqno = htons(seqno - 1);
+	frag2->seqno = htons(seqno);
 
-	send_skb_packet(skb, batman_if, dstaddr);
-	send_skb_packet(frag_skb, batman_if, dstaddr);
+	send_skb_packet(skb, hard_iface, dstaddr);
+	send_skb_packet(frag_skb, hard_iface, dstaddr);
 	return NET_RX_SUCCESS;
 
 drop_frag:
@@ -282,44 +283,36 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
 	struct unicast_packet *unicast_packet;
 	struct orig_node *orig_node;
-	struct batman_if *batman_if;
-	struct neigh_node *router;
+	struct neigh_node *neigh_node;
 	int data_len = skb->len;
-	uint8_t dstaddr[6];
-
-	spin_lock_bh(&bat_priv->orig_hash_lock);
+	int ret = 1;
 
 	/* get routing information */
-	if (is_multicast_ether_addr(ethhdr->h_dest))
+	if (is_multicast_ether_addr(ethhdr->h_dest)) {
 		orig_node = (struct orig_node *)gw_get_selected(bat_priv);
-	else
-		orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
-							   compare_orig,
-							   choose_orig,
-							   ethhdr->h_dest));
-
-	/* check for hna host */
-	if (!orig_node)
-		orig_node = transtable_search(bat_priv, ethhdr->h_dest);
-
-	router = find_router(bat_priv, orig_node, NULL);
-
-	if (!router)
-		goto unlock;
+		if (orig_node)
+			goto find_router;
+	}
 
-	/* don't lock while sending the packets ... we therefore
-		* copy the required data before sending */
+	/* check for hna host - increases orig_node refcount */
+	orig_node = transtable_search(bat_priv, ethhdr->h_dest);
 
-	batman_if = router->if_incoming;
-	memcpy(dstaddr, router->addr, ETH_ALEN);
+find_router:
+	/**
+	 * find_router():
+	 *  - if orig_node is NULL it returns NULL
+	 *  - increases neigh_nodes refcount if found.
+	 */
+	neigh_node = find_router(bat_priv, orig_node, NULL);
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	if (!neigh_node)
+		goto out;
 
-	if (batman_if->if_status != IF_ACTIVE)
-		goto dropped;
+	if (neigh_node->if_incoming->if_status != IF_ACTIVE)
+		goto out;
 
 	if (my_skb_head_push(skb, sizeof(struct unicast_packet)) < 0)
-		goto dropped;
+		goto out;
 
 	unicast_packet = (struct unicast_packet *)skb->data;
 
@@ -333,18 +326,24 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
 
 	if (atomic_read(&bat_priv->fragmentation) &&
 	    data_len + sizeof(struct unicast_packet) >
-	    batman_if->net_dev->mtu) {
+				neigh_node->if_incoming->net_dev->mtu) {
 		/* send frag skb decreases ttl */
 		unicast_packet->ttl++;
-		return frag_send_skb(skb, bat_priv, batman_if,
-				     dstaddr);
+		ret = frag_send_skb(skb, bat_priv,
+				    neigh_node->if_incoming, neigh_node->addr);
+		goto out;
 	}
-	send_skb_packet(skb, batman_if, dstaddr);
-	return 0;
 
-unlock:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
-dropped:
-	kfree_skb(skb);
-	return 1;
+	send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+	ret = 0;
+	goto out;
+
+out:
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+	if (ret == 1)
+		kfree_skb(skb);
+	return ret;
 }
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h
index e32b786..16ad7a9 100644
--- a/net/batman-adv/unicast.h
+++ b/net/batman-adv/unicast.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2010-2011 B.A.T.M.A.N. contributors:
  *
  * Andreas Langer
  *
@@ -22,6 +22,8 @@
 #ifndef _NET_BATMAN_ADV_UNICAST_H_
 #define _NET_BATMAN_ADV_UNICAST_H_
 
+#include "packet.h"
+
 #define FRAG_TIMEOUT 10000	/* purge frag list entrys after time in ms */
 #define FRAG_BUFFER_SIZE 6	/* number of list elements in buffer */
 
@@ -30,6 +32,27 @@ int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
 void frag_list_free(struct list_head *head);
 int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv);
 int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv,
-		  struct batman_if *batman_if, uint8_t dstaddr[]);
+		  struct hard_iface *hard_iface, uint8_t dstaddr[]);
+
+static inline int frag_can_reassemble(struct sk_buff *skb, int mtu)
+{
+	struct unicast_frag_packet *unicast_packet;
+	int uneven_correction = 0;
+	unsigned int merged_size;
+
+	unicast_packet = (struct unicast_frag_packet *)skb->data;
+
+	if (unicast_packet->flags & UNI_FRAG_LARGETAIL) {
+		if (unicast_packet->flags & UNI_FRAG_HEAD)
+			uneven_correction = 1;
+		else
+			uneven_correction = -1;
+	}
+
+	merged_size = (skb->len - sizeof(struct unicast_frag_packet)) * 2;
+	merged_size += sizeof(struct unicast_packet) + uneven_correction;
+
+	return merged_size <= mtu;
+}
 
 #endif /* _NET_BATMAN_ADV_UNICAST_H_ */
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index de1022c..f90212f 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2008-2011 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich
  *
@@ -68,15 +68,16 @@ static void free_info(struct kref *ref)
 }
 
 /* Compare two vis packets, used by the hashing algorithm */
-static int vis_info_cmp(void *data1, void *data2)
+static int vis_info_cmp(struct hlist_node *node, void *data2)
 {
 	struct vis_info *d1, *d2;
 	struct vis_packet *p1, *p2;
-	d1 = data1;
+
+	d1 = container_of(node, struct vis_info, hash_entry);
 	d2 = data2;
 	p1 = (struct vis_packet *)d1->skb_packet->data;
 	p2 = (struct vis_packet *)d2->skb_packet->data;
-	return compare_orig(p1->vis_orig, p2->vis_orig);
+	return compare_eth(p1->vis_orig, p2->vis_orig);
 }
 
 /* hash function to choose an entry in a hash table of given size */
@@ -104,6 +105,34 @@ static int vis_info_choose(void *data, int size)
 	return hash % size;
 }
 
+static struct vis_info *vis_hash_find(struct bat_priv *bat_priv,
+				      void *data)
+{
+	struct hashtable_t *hash = bat_priv->vis_hash;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct vis_info *vis_info, *vis_info_tmp = NULL;
+	int index;
+
+	if (!hash)
+		return NULL;
+
+	index = vis_info_choose(data, hash->size);
+	head = &hash->table[index];
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(vis_info, node, head, hash_entry) {
+		if (!vis_info_cmp(node, data))
+			continue;
+
+		vis_info_tmp = vis_info;
+		break;
+	}
+	rcu_read_unlock();
+
+	return vis_info_tmp;
+}
+
 /* insert interface to the list of interfaces of one originator, if it
  * does not already exist in the list */
 static void vis_data_insert_interface(const uint8_t *interface,
@@ -114,7 +143,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
 	struct hlist_node *pos;
 
 	hlist_for_each_entry(entry, pos, if_list, list) {
-		if (compare_orig(entry->addr, (void *)interface))
+		if (compare_eth(entry->addr, (void *)interface))
 			return;
 	}
 
@@ -166,7 +195,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
 	/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
 	if (primary && entry->quality == 0)
 		return sprintf(buff, "HNA %pM, ", entry->dest);
-	else if (compare_orig(entry->src, src))
+	else if (compare_eth(entry->src, src))
 		return sprintf(buff, "TQ %pM %d, ", entry->dest,
 			       entry->quality);
 
@@ -175,9 +204,8 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
 
 int vis_seq_print_text(struct seq_file *seq, void *offset)
 {
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct vis_info *info;
 	struct vis_packet *packet;
 	struct vis_info_entry *entries;
@@ -203,8 +231,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			info = bucket->data;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(info, node, head, hash_entry) {
 			packet = (struct vis_packet *)info->skb_packet->data;
 			entries = (struct vis_info_entry *)
 				((char *)packet + sizeof(struct vis_packet));
@@ -213,7 +241,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 				if (entries[j].quality == 0)
 					continue;
 				compare =
-				 compare_orig(entries[j].src, packet->vis_orig);
+				 compare_eth(entries[j].src, packet->vis_orig);
 				vis_data_insert_interface(entries[j].src,
 							  &vis_if_list,
 							  compare);
@@ -223,7 +251,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 				buf_size += 18 + 26 * packet->entries;
 
 				/* add primary/secondary records */
-				if (compare_orig(entry->addr, packet->vis_orig))
+				if (compare_eth(entry->addr, packet->vis_orig))
 					buf_size +=
 					  vis_data_count_prim_sec(&vis_if_list);
 
@@ -236,6 +264,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 				kfree(entry);
 			}
 		}
+		rcu_read_unlock();
 	}
 
 	buff = kmalloc(buf_size, GFP_ATOMIC);
@@ -249,8 +278,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			info = bucket->data;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(info, node, head, hash_entry) {
 			packet = (struct vis_packet *)info->skb_packet->data;
 			entries = (struct vis_info_entry *)
 				((char *)packet + sizeof(struct vis_packet));
@@ -259,7 +288,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 				if (entries[j].quality == 0)
 					continue;
 				compare =
-				 compare_orig(entries[j].src, packet->vis_orig);
+				 compare_eth(entries[j].src, packet->vis_orig);
 				vis_data_insert_interface(entries[j].src,
 							  &vis_if_list,
 							  compare);
@@ -277,7 +306,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 							entry->primary);
 
 				/* add primary/secondary records */
-				if (compare_orig(entry->addr, packet->vis_orig))
+				if (compare_eth(entry->addr, packet->vis_orig))
 					buff_pos +=
 					 vis_data_read_prim_sec(buff + buff_pos,
 								&vis_if_list);
@@ -291,6 +320,7 @@ int vis_seq_print_text(struct seq_file *seq, void *offset)
 				kfree(entry);
 			}
 		}
+		rcu_read_unlock();
 	}
 
 	spin_unlock_bh(&bat_priv->vis_hash_lock);
@@ -345,7 +375,7 @@ static int recv_list_is_in(struct bat_priv *bat_priv,
 
 	spin_lock_bh(&bat_priv->vis_list_lock);
 	list_for_each_entry(entry, recv_list, list) {
-		if (memcmp(entry->mac, mac, ETH_ALEN) == 0) {
+		if (compare_eth(entry->mac, mac)) {
 			spin_unlock_bh(&bat_priv->vis_list_lock);
 			return 1;
 		}
@@ -381,8 +411,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 						     sizeof(struct vis_packet));
 
 	memcpy(search_packet->vis_orig, vis_packet->vis_orig, ETH_ALEN);
-	old_info = hash_find(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
-			     &search_elem);
+	old_info = vis_hash_find(bat_priv, &search_elem);
 	kfree_skb(search_elem.skb_packet);
 
 	if (old_info) {
@@ -442,7 +471,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv,
 
 	/* try to add it */
 	hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
-			      info);
+			      info, &info->hash_entry);
 	if (hash_added < 0) {
 		/* did not work (for some reason) */
 		kref_put(&info->refcount, free_info);
@@ -529,9 +558,8 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
 				struct vis_info *info)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct orig_node *orig_node;
 	struct vis_packet *packet;
 	int best_tq = -1, i;
@@ -541,16 +569,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv,
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
 			if ((orig_node) && (orig_node->router) &&
-			(orig_node->flags & VIS_SERVER) &&
-			(orig_node->router->tq_avg > best_tq)) {
+			    (orig_node->flags & VIS_SERVER) &&
+			    (orig_node->router->tq_avg > best_tq)) {
 				best_tq = orig_node->router->tq_avg;
 				memcpy(packet->target_orig, orig_node->orig,
 				       ETH_ALEN);
 			}
 		}
+		rcu_read_unlock();
 	}
 
 	return best_tq;
@@ -573,9 +602,8 @@ static bool vis_packet_full(struct vis_info *info)
 static int generate_vis_packet(struct bat_priv *bat_priv)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct orig_node *orig_node;
 	struct neigh_node *neigh_node;
 	struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info;
@@ -587,7 +615,6 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 	info->first_seen = jiffies;
 	packet->vis_type = atomic_read(&bat_priv->vis_mode);
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
 	memcpy(packet->target_orig, broadcast_addr, ETH_ALEN);
 	packet->ttl = TTL;
 	packet->seqno = htonl(ntohl(packet->seqno) + 1);
@@ -597,23 +624,21 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 	if (packet->vis_type == VIS_TYPE_CLIENT_UPDATE) {
 		best_tq = find_best_vis_server(bat_priv, info);
 
-		if (best_tq < 0) {
-			spin_unlock_bh(&bat_priv->orig_hash_lock);
+		if (best_tq < 0)
 			return -1;
-		}
 	}
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
 			neigh_node = orig_node->router;
 
 			if (!neigh_node)
 				continue;
 
-			if (!compare_orig(neigh_node->addr, orig_node->orig))
+			if (!compare_eth(neigh_node->addr, orig_node->orig))
 				continue;
 
 			if (neigh_node->if_incoming->if_status != IF_ACTIVE)
@@ -632,23 +657,19 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 			entry->quality = neigh_node->tq_avg;
 			packet->entries++;
 
-			if (vis_packet_full(info)) {
-				spin_unlock_bh(&bat_priv->orig_hash_lock);
-				return 0;
-			}
+			if (vis_packet_full(info))
+				goto unlock;
 		}
+		rcu_read_unlock();
 	}
 
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
-
 	hash = bat_priv->hna_local_hash;
 
 	spin_lock_bh(&bat_priv->hna_lhash_lock);
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			hna_local_entry = bucket->data;
+		hlist_for_each_entry(hna_local_entry, node, head, hash_entry) {
 			entry = (struct vis_info_entry *)
 					skb_put(info->skb_packet,
 						sizeof(*entry));
@@ -666,6 +687,10 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
 
 	spin_unlock_bh(&bat_priv->hna_lhash_lock);
 	return 0;
+
+unlock:
+	rcu_read_unlock();
+	return 0;
 }
 
 /* free old vis packets. Must be called with this vis_hash_lock
@@ -674,25 +699,22 @@ static void purge_vis_packets(struct bat_priv *bat_priv)
 {
 	int i;
 	struct hashtable_t *hash = bat_priv->vis_hash;
-	struct hlist_node *walk, *safe;
+	struct hlist_node *node, *node_tmp;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct vis_info *info;
 
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry_safe(bucket, walk, safe, head, hlist) {
-			info = bucket->data;
-
+		hlist_for_each_entry_safe(info, node, node_tmp,
+					  head, hash_entry) {
 			/* never purge own data. */
 			if (info == bat_priv->my_vis_info)
 				continue;
 
 			if (time_after(jiffies,
 				       info->first_seen + VIS_TIMEOUT * HZ)) {
-				hlist_del(walk);
-				kfree(bucket);
+				hlist_del(node);
 				send_list_del(info);
 				kref_put(&info->refcount, free_info);
 			}
@@ -704,27 +726,24 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
 				 struct vis_info *info)
 {
 	struct hashtable_t *hash = bat_priv->orig_hash;
-	struct hlist_node *walk;
+	struct hlist_node *node;
 	struct hlist_head *head;
-	struct element_t *bucket;
 	struct orig_node *orig_node;
 	struct vis_packet *packet;
 	struct sk_buff *skb;
-	struct batman_if *batman_if;
+	struct hard_iface *hard_iface;
 	uint8_t dstaddr[ETH_ALEN];
 	int i;
 
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
 	packet = (struct vis_packet *)info->skb_packet->data;
 
 	/* send to all routers in range. */
 	for (i = 0; i < hash->size; i++) {
 		head = &hash->table[i];
 
-		hlist_for_each_entry(bucket, walk, head, hlist) {
-			orig_node = bucket->data;
-
+		rcu_read_lock();
+		hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
 			/* if it's a vis server and reachable, send it. */
 			if ((!orig_node) || (!orig_node->router))
 				continue;
@@ -737,54 +756,61 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv,
 				continue;
 
 			memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
-			batman_if = orig_node->router->if_incoming;
+			hard_iface = orig_node->router->if_incoming;
 			memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
-			spin_unlock_bh(&bat_priv->orig_hash_lock);
 
 			skb = skb_clone(info->skb_packet, GFP_ATOMIC);
 			if (skb)
-				send_skb_packet(skb, batman_if, dstaddr);
+				send_skb_packet(skb, hard_iface, dstaddr);
 
-			spin_lock_bh(&bat_priv->orig_hash_lock);
 		}
-
+		rcu_read_unlock();
 	}
-
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
 }
 
 static void unicast_vis_packet(struct bat_priv *bat_priv,
 			       struct vis_info *info)
 {
 	struct orig_node *orig_node;
+	struct neigh_node *neigh_node = NULL;
 	struct sk_buff *skb;
 	struct vis_packet *packet;
-	struct batman_if *batman_if;
-	uint8_t dstaddr[ETH_ALEN];
 
-	spin_lock_bh(&bat_priv->orig_hash_lock);
 	packet = (struct vis_packet *)info->skb_packet->data;
-	orig_node = ((struct orig_node *)hash_find(bat_priv->orig_hash,
-						   compare_orig, choose_orig,
-						   packet->target_orig));
 
-	if ((!orig_node) || (!orig_node->router))
-		goto out;
+	rcu_read_lock();
+	orig_node = orig_hash_find(bat_priv, packet->target_orig);
 
-	/* don't lock while sending the packets ... we therefore
-	 * copy the required data before sending */
-	batman_if = orig_node->router->if_incoming;
-	memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	if (!orig_node)
+		goto unlock;
+
+	neigh_node = orig_node->router;
+
+	if (!neigh_node)
+		goto unlock;
+
+	if (!atomic_inc_not_zero(&neigh_node->refcount)) {
+		neigh_node = NULL;
+		goto unlock;
+	}
+
+	rcu_read_unlock();
 
 	skb = skb_clone(info->skb_packet, GFP_ATOMIC);
 	if (skb)
-		send_skb_packet(skb, batman_if, dstaddr);
+		send_skb_packet(skb, neigh_node->if_incoming,
+				neigh_node->addr);
 
-	return;
+	goto out;
 
+unlock:
+	rcu_read_unlock();
 out:
-	spin_unlock_bh(&bat_priv->orig_hash_lock);
+	if (neigh_node)
+		neigh_node_free_ref(neigh_node);
+	if (orig_node)
+		orig_node_free_ref(orig_node);
+	return;
 }
 
 /* only send one vis packet. called from send_vis_packets() */
@@ -896,7 +922,8 @@ int vis_init(struct bat_priv *bat_priv)
 	INIT_LIST_HEAD(&bat_priv->vis_send_list);
 
 	hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose,
-			      bat_priv->my_vis_info);
+			      bat_priv->my_vis_info,
+			      &bat_priv->my_vis_info->hash_entry);
 	if (hash_added < 0) {
 		pr_err("Can't add own vis packet into hash\n");
 		/* not in hash, need to remove it manually. */
@@ -918,10 +945,11 @@ err:
 }
 
 /* Decrease the reference count on a hash item info */
-static void free_info_ref(void *data, void *arg)
+static void free_info_ref(struct hlist_node *node, void *arg)
 {
-	struct vis_info *info = data;
+	struct vis_info *info;
 
+	info = container_of(node, struct vis_info, hash_entry);
 	send_list_del(info);
 	kref_put(&info->refcount, free_info);
 }
diff --git a/net/batman-adv/vis.h b/net/batman-adv/vis.h
index 2c3b330..31b820d 100644
--- a/net/batman-adv/vis.h
+++ b/net/batman-adv/vis.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2008-2011 B.A.T.M.A.N. contributors:
  *
  * Simon Wunderlich, Marek Lindner
  *
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index ed37168..6ae5ec5 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -27,31 +27,27 @@ menuconfig BT
 	  compile it as module (bluetooth).
 
 	  To use Linux Bluetooth subsystem, you will need several user-space
-	  utilities like hciconfig and hcid.  These utilities and updates to
-	  Bluetooth kernel modules are provided in the BlueZ packages.
-	  For more information, see <http://www.bluez.org/>.
+	  utilities like hciconfig and bluetoothd.  These utilities and updates
+	  to Bluetooth kernel modules are provided in the BlueZ packages.  For
+	  more information, see <http://www.bluez.org/>.
+
+if BT != n
 
 config BT_L2CAP
-	tristate "L2CAP protocol support"
-	depends on BT
+	bool "L2CAP protocol support"
 	select CRC16
 	help
 	  L2CAP (Logical Link Control and Adaptation Protocol) provides
 	  connection oriented and connection-less data transport.  L2CAP
 	  support is required for most Bluetooth applications.
 
-	  Say Y here to compile L2CAP support into the kernel or say M to
-	  compile it as module (l2cap).
-
 config BT_SCO
-	tristate "SCO links support"
-	depends on BT
+	bool "SCO links support"
 	help
 	  SCO link provides voice transport over Bluetooth.  SCO support is
 	  required for voice applications like Headset and Audio.
 
-	  Say Y here to compile SCO support into the kernel or say M to
-	  compile it as module (sco).
+endif
 
 source "net/bluetooth/rfcomm/Kconfig"
 
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index 250f954..f04fe9a 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -3,11 +3,11 @@
 #
 
 obj-$(CONFIG_BT)	+= bluetooth.o
-obj-$(CONFIG_BT_L2CAP)	+= l2cap.o
-obj-$(CONFIG_BT_SCO)	+= sco.o
 obj-$(CONFIG_BT_RFCOMM)	+= rfcomm/
 obj-$(CONFIG_BT_BNEP)	+= bnep/
 obj-$(CONFIG_BT_CMTP)	+= cmtp/
 obj-$(CONFIG_BT_HIDP)	+= hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
+bluetooth-$(CONFIG_BT_L2CAP)	+= l2cap_core.o l2cap_sock.o
+bluetooth-$(CONFIG_BT_SCO)	+= sco.o
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index c4cf3f5..8add9b4 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -40,7 +40,7 @@
 
 #include <net/bluetooth/bluetooth.h>
 
-#define VERSION "2.15"
+#define VERSION "2.16"
 
 /* Bluetooth sockets */
 #define BT_MAX_PROTO	8
@@ -199,14 +199,15 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
 
 	BT_DBG("parent %p", parent);
 
+	local_bh_disable();
 	list_for_each_safe(p, n, &bt_sk(parent)->accept_q) {
 		sk = (struct sock *) list_entry(p, struct bt_sock, accept_q);
 
-		lock_sock(sk);
+		bh_lock_sock(sk);
 
 		/* FIXME: Is this check still needed */
 		if (sk->sk_state == BT_CLOSED) {
-			release_sock(sk);
+			bh_unlock_sock(sk);
 			bt_accept_unlink(sk);
 			continue;
 		}
@@ -216,12 +217,16 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock)
 			bt_accept_unlink(sk);
 			if (newsock)
 				sock_graft(sk, newsock);
-			release_sock(sk);
+
+			bh_unlock_sock(sk);
+			local_bh_enable();
 			return sk;
 		}
 
-		release_sock(sk);
+		bh_unlock_sock(sk);
 	}
+	local_bh_enable();
+
 	return NULL;
 }
 EXPORT_SYMBOL(bt_accept_dequeue);
@@ -240,7 +245,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
 	if (flags & (MSG_OOB))
 		return -EOPNOTSUPP;
 
-	if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) {
+	skb = skb_recv_datagram(sk, flags, noblock, &err);
+	if (!skb) {
 		if (sk->sk_shutdown & RCV_SHUTDOWN)
 			return 0;
 		return err;
@@ -323,7 +329,8 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 			if (copied >= target)
 				break;
 
-			if ((err = sock_error(sk)) != 0)
+			err = sock_error(sk);
+			if (err)
 				break;
 			if (sk->sk_shutdown & RCV_SHUTDOWN)
 				break;
@@ -390,7 +397,7 @@ static inline unsigned int bt_accept_poll(struct sock *parent)
 	return 0;
 }
 
-unsigned int bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait)
+unsigned int bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait)
 {
 	struct sock *sk = sock->sk;
 	unsigned int mask = 0;
@@ -538,13 +545,39 @@ static int __init bt_init(void)
 
 	BT_INFO("HCI device and connection manager initialized");
 
-	hci_sock_init();
+	err = hci_sock_init();
+	if (err < 0)
+		goto error;
+
+	err = l2cap_init();
+	if (err < 0)
+		goto sock_err;
+
+	err = sco_init();
+	if (err < 0) {
+		l2cap_exit();
+		goto sock_err;
+	}
 
 	return 0;
+
+sock_err:
+	hci_sock_cleanup();
+
+error:
+	sock_unregister(PF_BLUETOOTH);
+	bt_sysfs_cleanup();
+
+	return err;
 }
 
 static void __exit bt_exit(void)
 {
+
+	sco_exit();
+
+	l2cap_exit();
+
 	hci_sock_cleanup();
 
 	sock_unregister(PF_BLUETOOTH);
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 5868597..03d4d12 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -708,8 +708,6 @@ static int __init bnep_init(void)
 {
 	char flt[50] = "";
 
-	l2cap_load();
-
 #ifdef CONFIG_BT_BNEP_PROTO_FILTER
 	strcat(flt, "protocol ");
 #endif
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
index 2862f53..d935da7 100644
--- a/net/bluetooth/bnep/sock.c
+++ b/net/bluetooth/bnep/sock.c
@@ -88,6 +88,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
 			sockfd_put(nsock);
 			return -EBADFD;
 		}
+		ca.device[sizeof(ca.device)-1] = 0;
 
 		err = bnep_add_connection(&ca, nsock);
 		if (!err) {
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c
index 3487cfe..67cff810 100644
--- a/net/bluetooth/cmtp/capi.c
+++ b/net/bluetooth/cmtp/capi.c
@@ -155,7 +155,8 @@ static void cmtp_send_interopmsg(struct cmtp_session *session,
 
 	BT_DBG("session %p subcmd 0x%02x appl %d msgnum %d", session, subcmd, appl, msgnum);
 
-	if (!(skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC))) {
+	skb = alloc_skb(CAPI_MSG_BASELEN + 6 + len, GFP_ATOMIC);
+	if (!skb) {
 		BT_ERR("Can't allocate memory for interoperability packet");
 		return;
 	}
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c
index 8e5f292..964ea91 100644
--- a/net/bluetooth/cmtp/core.c
+++ b/net/bluetooth/cmtp/core.c
@@ -115,7 +115,8 @@ static inline void cmtp_add_msgpart(struct cmtp_session *session, int id, const
 
 	size = (skb) ? skb->len + count : count;
 
-	if (!(nskb = alloc_skb(size, GFP_ATOMIC))) {
+	nskb = alloc_skb(size, GFP_ATOMIC);
+	if (!nskb) {
 		BT_ERR("Can't allocate memory for CAPI message");
 		return;
 	}
@@ -216,7 +217,8 @@ static void cmtp_process_transmit(struct cmtp_session *session)
 
 	BT_DBG("session %p", session);
 
-	if (!(nskb = alloc_skb(session->mtu, GFP_ATOMIC))) {
+	nskb = alloc_skb(session->mtu, GFP_ATOMIC);
+	if (!nskb) {
 		BT_ERR("Can't allocate memory for new frame");
 		return;
 	}
@@ -224,7 +226,8 @@ static void cmtp_process_transmit(struct cmtp_session *session)
 	while ((skb = skb_dequeue(&session->transmit))) {
 		struct cmtp_scb *scb = (void *) skb->cb;
 
-		if ((tail = (session->mtu - nskb->len)) < 5) {
+		tail = session->mtu - nskb->len;
+		if (tail < 5) {
 			cmtp_send_frame(session, nskb->data, nskb->len);
 			skb_trim(nskb, 0);
 			tail = session->mtu;
@@ -466,8 +469,6 @@ int cmtp_get_conninfo(struct cmtp_conninfo *ci)
 
 static int __init cmtp_init(void)
 {
-	l2cap_load();
-
 	BT_INFO("CMTP (CAPI Emulation) ver %s", VERSION);
 
 	cmtp_init_sockets();
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 99cd8d9..7a6f56b 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -45,6 +45,33 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
+static void hci_le_connect(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct hci_cp_le_create_conn cp;
+
+	conn->state = BT_CONNECT;
+	conn->out = 1;
+	conn->link_mode |= HCI_LM_MASTER;
+
+	memset(&cp, 0, sizeof(cp));
+	cp.scan_interval = cpu_to_le16(0x0004);
+	cp.scan_window = cpu_to_le16(0x0004);
+	bacpy(&cp.peer_addr, &conn->dst);
+	cp.conn_interval_min = cpu_to_le16(0x0008);
+	cp.conn_interval_max = cpu_to_le16(0x0100);
+	cp.supervision_timeout = cpu_to_le16(0x0064);
+	cp.min_ce_len = cpu_to_le16(0x0001);
+	cp.max_ce_len = cpu_to_le16(0x0001);
+
+	hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+}
+
+static void hci_le_connect_cancel(struct hci_conn *conn)
+{
+	hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
+}
+
 void hci_acl_connect(struct hci_conn *conn)
 {
 	struct hci_dev *hdev = conn->hdev;
@@ -156,6 +183,26 @@ void hci_setup_sync(struct hci_conn *conn, __u16 handle)
 	hci_send_cmd(hdev, HCI_OP_SETUP_SYNC_CONN, sizeof(cp), &cp);
 }
 
+void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
+					u16 latency, u16 to_multiplier)
+{
+	struct hci_cp_le_conn_update cp;
+	struct hci_dev *hdev = conn->hdev;
+
+	memset(&cp, 0, sizeof(cp));
+
+	cp.handle		= cpu_to_le16(conn->handle);
+	cp.conn_interval_min	= cpu_to_le16(min);
+	cp.conn_interval_max	= cpu_to_le16(max);
+	cp.conn_latency		= cpu_to_le16(latency);
+	cp.supervision_timeout	= cpu_to_le16(to_multiplier);
+	cp.min_ce_len		= cpu_to_le16(0x0001);
+	cp.max_ce_len		= cpu_to_le16(0x0001);
+
+	hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_conn_update);
+
 /* Device _must_ be locked */
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 {
@@ -193,8 +240,12 @@ static void hci_conn_timeout(unsigned long arg)
 	switch (conn->state) {
 	case BT_CONNECT:
 	case BT_CONNECT2:
-		if (conn->type == ACL_LINK && conn->out)
-			hci_acl_connect_cancel(conn);
+		if (conn->out) {
+			if (conn->type == ACL_LINK)
+				hci_acl_connect_cancel(conn);
+			else if (conn->type == LE_LINK)
+				hci_le_connect_cancel(conn);
+		}
 		break;
 	case BT_CONFIG:
 	case BT_CONNECTED:
@@ -234,6 +285,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
 	conn->mode  = HCI_CM_ACTIVE;
 	conn->state = BT_OPEN;
 	conn->auth_type = HCI_AT_GENERAL_BONDING;
+	conn->io_capability = hdev->io_capability;
+	conn->remote_auth = 0xff;
 
 	conn->power_save = 1;
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
@@ -295,6 +348,11 @@ int hci_conn_del(struct hci_conn *conn)
 
 		/* Unacked frames */
 		hdev->acl_cnt += conn->sent;
+	} else if (conn->type == LE_LINK) {
+		if (hdev->le_pkts)
+			hdev->le_cnt += conn->sent;
+		else
+			hdev->acl_cnt += conn->sent;
 	} else {
 		struct hci_conn *acl = conn->link;
 		if (acl) {
@@ -360,15 +418,31 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src)
 }
 EXPORT_SYMBOL(hci_get_route);
 
-/* Create SCO or ACL connection.
+/* Create SCO, ACL or LE connection.
  * Device _must_ be locked */
 struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type)
 {
 	struct hci_conn *acl;
 	struct hci_conn *sco;
+	struct hci_conn *le;
 
 	BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
+	if (type == LE_LINK) {
+		le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+		if (le)
+			return ERR_PTR(-EBUSY);
+		le = hci_conn_add(hdev, LE_LINK, dst);
+		if (!le)
+			return ERR_PTR(-ENOMEM);
+		if (le->state == BT_OPEN)
+			hci_le_connect(le);
+
+		hci_conn_hold(le);
+
+		return le;
+	}
+
 	acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
 	if (!acl) {
 		acl = hci_conn_add(hdev, ACL_LINK, dst);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9c4541b..b372fb8 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -41,6 +41,7 @@
 #include <linux/interrupt.h>
 #include <linux/notifier.h>
 #include <linux/rfkill.h>
+#include <linux/timer.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -50,6 +51,8 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
+#define AUTO_OFF_TIMEOUT 2000
+
 static void hci_cmd_task(unsigned long arg);
 static void hci_rx_task(unsigned long arg);
 static void hci_tx_task(unsigned long arg);
@@ -95,11 +98,10 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result)
 {
 	BT_DBG("%s command 0x%04x result 0x%2.2x", hdev->name, cmd, result);
 
-	/* If the request has set req_last_cmd (typical for multi-HCI
-	 * command requests) check if the completed command matches
-	 * this, and if not just return. Single HCI command requests
-	 * typically leave req_last_cmd as 0 */
-	if (hdev->req_last_cmd && cmd != hdev->req_last_cmd)
+	/* 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)
 		return;
 
 	if (hdev->req_status == HCI_REQ_PEND) {
@@ -122,7 +124,7 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
 
 /* 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)
+					unsigned long opt, __u32 timeout)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int err = 0;
@@ -156,7 +158,7 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev,
 		break;
 	}
 
-	hdev->req_last_cmd = hdev->req_status = hdev->req_result = 0;
+	hdev->req_status = hdev->req_result = 0;
 
 	BT_DBG("%s end: err %d", hdev->name, err);
 
@@ -164,7 +166,7 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev,
 }
 
 static inline int hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, unsigned long opt),
-				unsigned long opt, __u32 timeout)
+					unsigned long opt, __u32 timeout)
 {
 	int ret;
 
@@ -189,6 +191,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
 
 static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
 {
+	struct hci_cp_delete_stored_link_key cp;
 	struct sk_buff *skb;
 	__le16 param;
 	__u8 flt_type;
@@ -252,15 +255,21 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
 	flt_type = HCI_FLT_CLEAR_ALL;
 	hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
 
-	/* Page timeout ~20 secs */
-	param = cpu_to_le16(0x8000);
-	hci_send_cmd(hdev, HCI_OP_WRITE_PG_TIMEOUT, 2, &param);
-
 	/* Connection accept timeout ~20 secs */
 	param = cpu_to_le16(0x7d00);
 	hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, &param);
 
-	hdev->req_last_cmd = HCI_OP_WRITE_CA_TIMEOUT;
+	bacpy(&cp.bdaddr, BDADDR_ANY);
+	cp.delete_all = 1;
+	hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
+}
+
+static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
+{
+	BT_DBG("%s", hdev->name);
+
+	/* Read LE buffer size */
+	hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
 }
 
 static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
@@ -429,7 +438,8 @@ int hci_inquiry(void __user *arg)
 	if (copy_from_user(&ir, ptr, sizeof(ir)))
 		return -EFAULT;
 
-	if (!(hdev = hci_dev_get(ir.dev_id)))
+	hdev = hci_dev_get(ir.dev_id);
+	if (!hdev)
 		return -ENODEV;
 
 	hci_dev_lock_bh(hdev);
@@ -455,7 +465,7 @@ int hci_inquiry(void __user *arg)
 	/* cache_dump can't sleep. Therefore we allocate temp buffer and then
 	 * copy it to the user space.
 	 */
-	buf = kmalloc(sizeof(struct inquiry_info) *max_rsp, GFP_KERNEL);
+	buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL);
 	if (!buf) {
 		err = -ENOMEM;
 		goto done;
@@ -489,7 +499,8 @@ int hci_dev_open(__u16 dev)
 	struct hci_dev *hdev;
 	int ret = 0;
 
-	if (!(hdev = hci_dev_get(dev)))
+	hdev = hci_dev_get(dev);
+	if (!hdev)
 		return -ENODEV;
 
 	BT_DBG("%s %p", hdev->name, hdev);
@@ -521,11 +532,15 @@ int hci_dev_open(__u16 dev)
 	if (!test_bit(HCI_RAW, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		set_bit(HCI_INIT, &hdev->flags);
+		hdev->init_last_cmd = 0;
 
-		//__hci_request(hdev, hci_reset_req, 0, HZ);
 		ret = __hci_request(hdev, hci_init_req, 0,
 					msecs_to_jiffies(HCI_INIT_TIMEOUT));
 
+		if (lmp_le_capable(hdev))
+			ret = __hci_request(hdev, hci_le_init_req, 0,
+					msecs_to_jiffies(HCI_INIT_TIMEOUT));
+
 		clear_bit(HCI_INIT, &hdev->flags);
 	}
 
@@ -533,6 +548,8 @@ int hci_dev_open(__u16 dev)
 		hci_dev_hold(hdev);
 		set_bit(HCI_UP, &hdev->flags);
 		hci_notify(hdev, HCI_DEV_UP);
+		if (!test_bit(HCI_SETUP, &hdev->flags))
+			mgmt_powered(hdev->id, 1);
 	} else {
 		/* Init failed, cleanup */
 		tasklet_kill(&hdev->rx_task);
@@ -606,6 +623,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
 	/* Drop last sent command */
 	if (hdev->sent_cmd) {
+		del_timer_sync(&hdev->cmd_timer);
 		kfree_skb(hdev->sent_cmd);
 		hdev->sent_cmd = NULL;
 	}
@@ -614,6 +632,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 	 * and no tasks are scheduled. */
 	hdev->close(hdev);
 
+	mgmt_powered(hdev->id, 0);
+
 	/* Clear flags */
 	hdev->flags = 0;
 
@@ -664,7 +684,7 @@ int hci_dev_reset(__u16 dev)
 		hdev->flush(hdev);
 
 	atomic_set(&hdev->cmd_cnt, 1);
-	hdev->acl_cnt = 0; hdev->sco_cnt = 0;
+	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,
@@ -793,9 +813,17 @@ int hci_get_dev_list(void __user *arg)
 	read_lock_bh(&hci_dev_list_lock);
 	list_for_each(p, &hci_dev_list) {
 		struct hci_dev *hdev;
+
 		hdev = list_entry(p, struct hci_dev, list);
+
+		hci_del_off_timer(hdev);
+
+		if (!test_bit(HCI_MGMT, &hdev->flags))
+			set_bit(HCI_PAIRABLE, &hdev->flags);
+
 		(dr + n)->dev_id  = hdev->id;
 		(dr + n)->dev_opt = hdev->flags;
+
 		if (++n >= dev_num)
 			break;
 	}
@@ -823,6 +851,11 @@ int hci_get_dev_info(void __user *arg)
 	if (!hdev)
 		return -ENODEV;
 
+	hci_del_off_timer(hdev);
+
+	if (!test_bit(HCI_MGMT, &hdev->flags))
+		set_bit(HCI_PAIRABLE, &hdev->flags);
+
 	strcpy(di.name, hdev->name);
 	di.bdaddr   = hdev->bdaddr;
 	di.type     = (hdev->bus & 0x0f) | (hdev->dev_type << 4);
@@ -891,6 +924,159 @@ void hci_free_dev(struct hci_dev *hdev)
 }
 EXPORT_SYMBOL(hci_free_dev);
 
+static void hci_power_on(struct work_struct *work)
+{
+	struct hci_dev *hdev = container_of(work, struct hci_dev, power_on);
+
+	BT_DBG("%s", hdev->name);
+
+	if (hci_dev_open(hdev->id) < 0)
+		return;
+
+	if (test_bit(HCI_AUTO_OFF, &hdev->flags))
+		mod_timer(&hdev->off_timer,
+				jiffies + msecs_to_jiffies(AUTO_OFF_TIMEOUT));
+
+	if (test_and_clear_bit(HCI_SETUP, &hdev->flags))
+		mgmt_index_added(hdev->id);
+}
+
+static void hci_power_off(struct work_struct *work)
+{
+	struct hci_dev *hdev = container_of(work, struct hci_dev, power_off);
+
+	BT_DBG("%s", hdev->name);
+
+	hci_dev_close(hdev->id);
+}
+
+static void hci_auto_off(unsigned long data)
+{
+	struct hci_dev *hdev = (struct hci_dev *) data;
+
+	BT_DBG("%s", hdev->name);
+
+	clear_bit(HCI_AUTO_OFF, &hdev->flags);
+
+	queue_work(hdev->workqueue, &hdev->power_off);
+}
+
+void hci_del_off_timer(struct hci_dev *hdev)
+{
+	BT_DBG("%s", hdev->name);
+
+	clear_bit(HCI_AUTO_OFF, &hdev->flags);
+	del_timer(&hdev->off_timer);
+}
+
+int hci_uuids_clear(struct hci_dev *hdev)
+{
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &hdev->uuids) {
+		struct bt_uuid *uuid;
+
+		uuid = list_entry(p, struct bt_uuid, list);
+
+		list_del(p);
+		kfree(uuid);
+	}
+
+	return 0;
+}
+
+int hci_link_keys_clear(struct hci_dev *hdev)
+{
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &hdev->link_keys) {
+		struct link_key *key;
+
+		key = list_entry(p, struct link_key, list);
+
+		list_del(p);
+		kfree(key);
+	}
+
+	return 0;
+}
+
+struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct list_head *p;
+
+	list_for_each(p, &hdev->link_keys) {
+		struct link_key *k;
+
+		k = list_entry(p, struct link_key, list);
+
+		if (bacmp(bdaddr, &k->bdaddr) == 0)
+			return k;
+	}
+
+	return NULL;
+}
+
+int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
+						u8 *val, u8 type, u8 pin_len)
+{
+	struct link_key *key, *old_key;
+	u8 old_key_type;
+
+	old_key = hci_find_link_key(hdev, bdaddr);
+	if (old_key) {
+		old_key_type = old_key->type;
+		key = old_key;
+	} else {
+		old_key_type = 0xff;
+		key = kzalloc(sizeof(*key), GFP_ATOMIC);
+		if (!key)
+			return -ENOMEM;
+		list_add(&key->list, &hdev->link_keys);
+	}
+
+	BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type);
+
+	bacpy(&key->bdaddr, bdaddr);
+	memcpy(key->val, val, 16);
+	key->type = type;
+	key->pin_len = pin_len;
+
+	if (new_key)
+		mgmt_new_key(hdev->id, key, old_key_type);
+
+	if (type == 0x06)
+		key->type = old_key_type;
+
+	return 0;
+}
+
+int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+	struct link_key *key;
+
+	key = hci_find_link_key(hdev, bdaddr);
+	if (!key)
+		return -ENOENT;
+
+	BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
+
+	list_del(&key->list);
+	kfree(key);
+
+	return 0;
+}
+
+/* HCI command timer function */
+static void hci_cmd_timer(unsigned long arg)
+{
+	struct hci_dev *hdev = (void *) arg;
+
+	BT_ERR("%s command tx timeout", hdev->name);
+	atomic_set(&hdev->cmd_cnt, 1);
+	tasklet_schedule(&hdev->cmd_task);
+}
+
 /* Register HCI device */
 int hci_register_dev(struct hci_dev *hdev)
 {
@@ -923,6 +1109,7 @@ int hci_register_dev(struct hci_dev *hdev)
 	hdev->pkt_type  = (HCI_DM1 | HCI_DH1 | HCI_HV1);
 	hdev->esco_type = (ESCO_HV1);
 	hdev->link_mode = (HCI_LM_ACCEPT);
+	hdev->io_capability = 0x03; /* No Input No Output */
 
 	hdev->idle_timeout = 0;
 	hdev->sniff_max_interval = 800;
@@ -936,6 +1123,8 @@ int hci_register_dev(struct hci_dev *hdev)
 	skb_queue_head_init(&hdev->cmd_q);
 	skb_queue_head_init(&hdev->raw_q);
 
+	setup_timer(&hdev->cmd_timer, hci_cmd_timer, (unsigned long) hdev);
+
 	for (i = 0; i < NUM_REASSEMBLY; i++)
 		hdev->reassembly[i] = NULL;
 
@@ -948,6 +1137,14 @@ int hci_register_dev(struct hci_dev *hdev)
 
 	INIT_LIST_HEAD(&hdev->blacklist);
 
+	INIT_LIST_HEAD(&hdev->uuids);
+
+	INIT_LIST_HEAD(&hdev->link_keys);
+
+	INIT_WORK(&hdev->power_on, hci_power_on);
+	INIT_WORK(&hdev->power_off, hci_power_off);
+	setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
+
 	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
 
 	atomic_set(&hdev->promisc, 0);
@@ -969,7 +1166,10 @@ int hci_register_dev(struct hci_dev *hdev)
 		}
 	}
 
-	mgmt_index_added(hdev->id);
+	set_bit(HCI_AUTO_OFF, &hdev->flags);
+	set_bit(HCI_SETUP, &hdev->flags);
+	queue_work(hdev->workqueue, &hdev->power_on);
+
 	hci_notify(hdev, HCI_DEV_REG);
 
 	return id;
@@ -999,7 +1199,10 @@ int hci_unregister_dev(struct hci_dev *hdev)
 	for (i = 0; i < NUM_REASSEMBLY; i++)
 		kfree_skb(hdev->reassembly[i]);
 
-	mgmt_index_removed(hdev->id);
+	if (!test_bit(HCI_INIT, &hdev->flags) &&
+					!test_bit(HCI_SETUP, &hdev->flags))
+		mgmt_index_removed(hdev->id);
+
 	hci_notify(hdev, HCI_DEV_UNREG);
 
 	if (hdev->rfkill) {
@@ -1009,10 +1212,14 @@ int hci_unregister_dev(struct hci_dev *hdev)
 
 	hci_unregister_sysfs(hdev);
 
+	hci_del_off_timer(hdev);
+
 	destroy_workqueue(hdev->workqueue);
 
 	hci_dev_lock_bh(hdev);
 	hci_blacklist_clear(hdev);
+	hci_uuids_clear(hdev);
+	hci_link_keys_clear(hdev);
 	hci_dev_unlock_bh(hdev);
 
 	__hci_dev_put(hdev);
@@ -1313,7 +1520,7 @@ static int hci_send_frame(struct sk_buff *skb)
 		/* Time stamp */
 		__net_timestamp(skb);
 
-		hci_send_to_sock(hdev, skb);
+		hci_send_to_sock(hdev, skb, NULL);
 	}
 
 	/* Get rid of skb owner, prior to sending to the driver. */
@@ -1349,6 +1556,9 @@ 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;
+
 	skb_queue_tail(&hdev->cmd_q, skb);
 	tasklet_schedule(&hdev->cmd_task);
 
@@ -1395,7 +1605,7 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
 
 	skb->dev = (void *) hdev;
 	bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
-	hci_add_acl_hdr(skb, conn->handle, flags | ACL_START);
+	hci_add_acl_hdr(skb, conn->handle, flags);
 
 	list = skb_shinfo(skb)->frag_list;
 	if (!list) {
@@ -1413,12 +1623,15 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
 		spin_lock_bh(&conn->data_q.lock);
 
 		__skb_queue_tail(&conn->data_q, skb);
+
+		flags &= ~ACL_START;
+		flags |= ACL_CONT;
 		do {
 			skb = list; list = list->next;
 
 			skb->dev = (void *) hdev;
 			bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
-			hci_add_acl_hdr(skb, conn->handle, flags | ACL_CONT);
+			hci_add_acl_hdr(skb, conn->handle, flags);
 
 			BT_DBG("%s frag %p len %d", hdev->name, skb, skb->len);
 
@@ -1486,8 +1699,25 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
 	}
 
 	if (conn) {
-		int cnt = (type == ACL_LINK ? hdev->acl_cnt : hdev->sco_cnt);
-		int q = cnt / num;
+		int cnt, q;
+
+		switch (conn->type) {
+		case ACL_LINK:
+			cnt = hdev->acl_cnt;
+			break;
+		case SCO_LINK:
+		case ESCO_LINK:
+			cnt = hdev->sco_cnt;
+			break;
+		case LE_LINK:
+			cnt = hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
+			break;
+		default:
+			cnt = 0;
+			BT_ERR("Unknown link type");
+		}
+
+		q = cnt / num;
 		*quote = q ? q : 1;
 	} else
 		*quote = 0;
@@ -1496,19 +1726,19 @@ static inline struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type, int
 	return conn;
 }
 
-static inline void hci_acl_tx_to(struct hci_dev *hdev)
+static inline void hci_link_tx_to(struct hci_dev *hdev, __u8 type)
 {
 	struct hci_conn_hash *h = &hdev->conn_hash;
 	struct list_head *p;
 	struct hci_conn  *c;
 
-	BT_ERR("%s ACL tx timeout", hdev->name);
+	BT_ERR("%s link tx timeout", hdev->name);
 
 	/* Kill stalled connections */
 	list_for_each(p, &h->list) {
 		c = list_entry(p, struct hci_conn, list);
-		if (c->type == ACL_LINK && c->sent) {
-			BT_ERR("%s killing stalled ACL connection %s",
+		if (c->type == type && c->sent) {
+			BT_ERR("%s killing stalled connection %s",
 				hdev->name, batostr(&c->dst));
 			hci_acl_disconn(c, 0x13);
 		}
@@ -1527,7 +1757,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
 		/* ACL tx timeout must be longer than maximum
 		 * link supervision timeout (40.9 seconds) */
 		if (!hdev->acl_cnt && time_after(jiffies, hdev->acl_last_tx + HZ * 45))
-			hci_acl_tx_to(hdev);
+			hci_link_tx_to(hdev, ACL_LINK);
 	}
 
 	while (hdev->acl_cnt && (conn = hci_low_sent(hdev, ACL_LINK, &quote))) {
@@ -1586,6 +1816,40 @@ static inline void hci_sched_esco(struct hci_dev *hdev)
 	}
 }
 
+static inline void hci_sched_le(struct hci_dev *hdev)
+{
+	struct hci_conn *conn;
+	struct sk_buff *skb;
+	int quote, cnt;
+
+	BT_DBG("%s", hdev->name);
+
+	if (!test_bit(HCI_RAW, &hdev->flags)) {
+		/* LE tx timeout must be longer than maximum
+		 * link supervision timeout (40.9 seconds) */
+		if (!hdev->le_cnt && hdev->le_pkts &&
+				time_after(jiffies, hdev->le_last_tx + HZ * 45))
+			hci_link_tx_to(hdev, LE_LINK);
+	}
+
+	cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
+	while (cnt && (conn = hci_low_sent(hdev, LE_LINK, &quote))) {
+		while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
+			BT_DBG("skb %p len %d", skb, skb->len);
+
+			hci_send_frame(skb);
+			hdev->le_last_tx = jiffies;
+
+			cnt--;
+			conn->sent++;
+		}
+	}
+	if (hdev->le_pkts)
+		hdev->le_cnt = cnt;
+	else
+		hdev->acl_cnt = cnt;
+}
+
 static void hci_tx_task(unsigned long arg)
 {
 	struct hci_dev *hdev = (struct hci_dev *) arg;
@@ -1593,7 +1857,8 @@ static void hci_tx_task(unsigned long arg)
 
 	read_lock(&hci_task_lock);
 
-	BT_DBG("%s acl %d sco %d", hdev->name, hdev->acl_cnt, hdev->sco_cnt);
+	BT_DBG("%s acl %d sco %d le %d", hdev->name, hdev->acl_cnt,
+		hdev->sco_cnt, hdev->le_cnt);
 
 	/* Schedule queues and send stuff to HCI driver */
 
@@ -1603,6 +1868,8 @@ static void hci_tx_task(unsigned long arg)
 
 	hci_sched_esco(hdev);
 
+	hci_sched_le(hdev);
+
 	/* Send next queued raw (unknown type) packet */
 	while ((skb = skb_dequeue(&hdev->raw_q)))
 		hci_send_frame(skb);
@@ -1700,7 +1967,7 @@ static void hci_rx_task(unsigned long arg)
 	while ((skb = skb_dequeue(&hdev->rx_q))) {
 		if (atomic_read(&hdev->promisc)) {
 			/* Send copy to the sockets */
-			hci_send_to_sock(hdev, skb);
+			hci_send_to_sock(hdev, skb, NULL);
 		}
 
 		if (test_bit(HCI_RAW, &hdev->flags)) {
@@ -1750,20 +2017,20 @@ static void hci_cmd_task(unsigned long arg)
 
 	BT_DBG("%s cmd %d", hdev->name, atomic_read(&hdev->cmd_cnt));
 
-	if (!atomic_read(&hdev->cmd_cnt) && time_after(jiffies, hdev->cmd_last_tx + HZ)) {
-		BT_ERR("%s command tx timeout", hdev->name);
-		atomic_set(&hdev->cmd_cnt, 1);
-	}
-
 	/* Send queued commands */
-	if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) {
+	if (atomic_read(&hdev->cmd_cnt)) {
+		skb = skb_dequeue(&hdev->cmd_q);
+		if (!skb)
+			return;
+
 		kfree_skb(hdev->sent_cmd);
 
 		hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC);
 		if (hdev->sent_cmd) {
 			atomic_dec(&hdev->cmd_cnt);
 			hci_send_frame(skb);
-			hdev->cmd_last_tx = jiffies;
+			mod_timer(&hdev->cmd_timer,
+				  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));
 		} else {
 			skb_queue_head(&hdev->cmd_q, skb);
 			tasklet_schedule(&hdev->cmd_task);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index a290854..3fbfa50 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -274,15 +274,24 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
 
 	if (!status) {
 		__u8 param = *((__u8 *) sent);
+		int old_pscan, old_iscan;
 
-		clear_bit(HCI_PSCAN, &hdev->flags);
-		clear_bit(HCI_ISCAN, &hdev->flags);
+		old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
+		old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
 
-		if (param & SCAN_INQUIRY)
+		if (param & SCAN_INQUIRY) {
 			set_bit(HCI_ISCAN, &hdev->flags);
+			if (!old_iscan)
+				mgmt_discoverable(hdev->id, 1);
+		} else if (old_iscan)
+			mgmt_discoverable(hdev->id, 0);
 
-		if (param & SCAN_PAGE)
+		if (param & SCAN_PAGE) {
 			set_bit(HCI_PSCAN, &hdev->flags);
+			if (!old_pscan)
+				mgmt_connectable(hdev->id, 1);
+		} else if (old_pscan)
+			mgmt_connectable(hdev->id, 0);
 	}
 
 	hci_req_complete(hdev, HCI_OP_WRITE_SCAN_ENABLE, status);
@@ -415,6 +424,115 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
 	hdev->ssp_mode = *((__u8 *) sent);
 }
 
+static u8 hci_get_inquiry_mode(struct hci_dev *hdev)
+{
+	if (hdev->features[6] & LMP_EXT_INQ)
+		return 2;
+
+	if (hdev->features[3] & LMP_RSSI_INQ)
+		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 };
+
+	/* Events for 1.2 and newer controllers */
+	if (hdev->lmp_ver > 1) {
+		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 (hdev->features[3] & LMP_RSSI_INQ)
+		events[4] |= 0x04; /* Inquiry Result with RSSI */
+
+	if (hdev->features[5] & LMP_SNIFF_SUBR)
+		events[5] |= 0x20; /* Sniff Subrating */
+
+	if (hdev->features[5] & LMP_PAUSE_ENC)
+		events[5] |= 0x80; /* Encryption Key Refresh Complete */
+
+	if (hdev->features[6] & LMP_EXT_INQ)
+		events[5] |= 0x40; /* Extended Inquiry Result */
+
+	if (hdev->features[6] & LMP_NO_FLUSH)
+		events[7] |= 0x01; /* Enhanced Flush Complete */
+
+	if (hdev->features[7] & LMP_LSTO)
+		events[6] |= 0x80; /* Link Supervision Timeout Changed */
+
+	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
+		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 (hdev->features[4] & LMP_LE)
+		events[7] |= 0x20;	/* LE Meta-Event */
+
+	hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
+}
+
+static void hci_setup(struct hci_dev *hdev)
+{
+	hci_setup_event_mask(hdev);
+
+	if (hdev->lmp_ver > 1)
+		hci_send_cmd(hdev, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
+
+	if (hdev->features[6] & LMP_SIMPLE_PAIR) {
+		u8 mode = 0x01;
+		hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
+	}
+
+	if (hdev->features[3] & LMP_RSSI_INQ)
+		hci_setup_inquiry_mode(hdev);
+
+	if (hdev->features[7] & LMP_INQ_TX_PWR)
+		hci_send_cmd(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 0, NULL);
+}
+
 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;
@@ -426,11 +544,34 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
 
 	hdev->hci_ver = rp->hci_ver;
 	hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
+	hdev->lmp_ver = rp->lmp_ver;
 	hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
+	hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
 
 	BT_DBG("%s manufacturer %d hci ver %d:%d", hdev->name,
 					hdev->manufacturer,
 					hdev->hci_ver, hdev->hci_rev);
+
+	if (test_bit(HCI_INIT, &hdev->flags))
+		hci_setup(hdev);
+}
+
+static void hci_setup_link_policy(struct hci_dev *hdev)
+{
+	u16 link_policy = 0;
+
+	if (hdev->features[0] & LMP_RSWITCH)
+		link_policy |= HCI_LP_RSWITCH;
+	if (hdev->features[0] & LMP_HOLD)
+		link_policy |= HCI_LP_HOLD;
+	if (hdev->features[0] & LMP_SNIFF)
+		link_policy |= HCI_LP_SNIFF;
+	if (hdev->features[1] & LMP_PARK)
+		link_policy |= HCI_LP_PARK;
+
+	link_policy = cpu_to_le16(link_policy);
+	hci_send_cmd(hdev, HCI_OP_WRITE_DEF_LINK_POLICY,
+					sizeof(link_policy), &link_policy);
 }
 
 static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb)
@@ -440,9 +581,15 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb
 	BT_DBG("%s status 0x%x", hdev->name, rp->status);
 
 	if (rp->status)
-		return;
+		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);
 }
 
 static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb)
@@ -548,6 +695,130 @@ static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb)
 	hci_req_complete(hdev, HCI_OP_WRITE_CA_TIMEOUT, 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%x", 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%x", 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%x", 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)
+{
+	__u8 status = *((__u8 *) skb->data);
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	hci_req_complete(hdev, HCI_OP_READ_INQ_RSP_TX_POWER, 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%x", 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)
+{
+	struct hci_rp_pin_code_reply *rp = (void *) skb->data;
+	struct hci_cp_pin_code_reply *cp;
+	struct hci_conn *conn;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_pin_code_reply_complete(hdev->id, &rp->bdaddr, rp->status);
+
+	if (rp->status != 0)
+		return;
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
+	if (!cp)
+		return;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+	if (conn)
+		conn->pin_length = cp->pin_len;
+}
+
+static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_pin_code_neg_reply_complete(hdev->id, &rp->bdaddr,
+								rp->status);
+}
+static void hci_cc_le_read_buffer_size(struct hci_dev *hdev,
+				       struct sk_buff *skb)
+{
+	struct hci_rp_le_read_buffer_size *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (rp->status)
+		return;
+
+	hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
+	hdev->le_pkts = rp->le_max_pkt;
+
+	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_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_user_confirm_reply_complete(hdev->id, &rp->bdaddr,
+								rp->status);
+}
+
+static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
+							struct sk_buff *skb)
+{
+	struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
+
+	BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_user_confirm_neg_reply_complete(hdev->id, &rp->bdaddr,
+								rp->status);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
 	BT_DBG("%s status 0x%x", hdev->name, status);
@@ -622,11 +893,14 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
 	hci_dev_lock(hdev);
 
 	acl = hci_conn_hash_lookup_handle(hdev, handle);
-	if (acl && (sco = acl->link)) {
-		sco->state = BT_CLOSED;
+	if (acl) {
+		sco = acl->link;
+		if (sco) {
+			sco->state = BT_CLOSED;
 
-		hci_proto_connect_cfm(sco, status);
-		hci_conn_del(sco);
+			hci_proto_connect_cfm(sco, status);
+			hci_conn_del(sco);
+		}
 	}
 
 	hci_dev_unlock(hdev);
@@ -687,7 +961,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
 }
 
 static int hci_outgoing_auth_needed(struct hci_dev *hdev,
-						struct hci_conn *conn)
+							struct hci_conn *conn)
 {
 	if (conn->state != BT_CONFIG || !conn->out)
 		return 0;
@@ -808,11 +1082,14 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
 	hci_dev_lock(hdev);
 
 	acl = hci_conn_hash_lookup_handle(hdev, handle);
-	if (acl && (sco = acl->link)) {
-		sco->state = BT_CLOSED;
+	if (acl) {
+		sco = acl->link;
+		if (sco) {
+			sco->state = BT_CLOSED;
 
-		hci_proto_connect_cfm(sco, status);
-		hci_conn_del(sco);
+			hci_proto_connect_cfm(sco, status);
+			hci_conn_del(sco);
+		}
 	}
 
 	hci_dev_unlock(hdev);
@@ -872,6 +1149,43 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
 	hci_dev_unlock(hdev);
 }
 
+static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
+{
+	struct hci_cp_le_create_conn *cp;
+	struct hci_conn *conn;
+
+	BT_DBG("%s status 0x%x", hdev->name, status);
+
+	cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
+	if (!cp)
+		return;
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr);
+
+	BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr),
+		conn);
+
+	if (status) {
+		if (conn && conn->state == BT_CONNECT) {
+			conn->state = BT_CLOSED;
+			hci_proto_connect_cfm(conn, status);
+			hci_conn_del(conn);
+		}
+	} else {
+		if (!conn) {
+			conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
+			if (conn)
+				conn->out = 1;
+			else
+				BT_ERR("No memory for new connection");
+		}
+	}
+
+	hci_dev_unlock(hdev);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	__u8 status = *((__u8 *) skb->data);
@@ -942,6 +1256,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 			conn->state = BT_CONFIG;
 			hci_conn_hold(conn);
 			conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+			mgmt_connected(hdev->id, &ev->bdaddr);
 		} else
 			conn->state = BT_CONNECTED;
 
@@ -970,8 +1285,11 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE,
 							sizeof(cp), &cp);
 		}
-	} else
+	} else {
 		conn->state = BT_CLOSED;
+		if (conn->type == ACL_LINK)
+			mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status);
+	}
 
 	if (conn->type == ACL_LINK)
 		hci_sco_setup(conn, ev->status);
@@ -998,7 +1316,8 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
 
 	mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type);
 
-	if ((mask & HCI_LM_ACCEPT) && !hci_blacklist_lookup(hdev, &ev->bdaddr)) {
+	if ((mask & HCI_LM_ACCEPT) &&
+			!hci_blacklist_lookup(hdev, &ev->bdaddr)) {
 		/* Connection accepted */
 		struct inquiry_entry *ie;
 		struct hci_conn *conn;
@@ -1068,19 +1387,26 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff
 
 	BT_DBG("%s status %d", hdev->name, ev->status);
 
-	if (ev->status)
+	if (ev->status) {
+		mgmt_disconnect_failed(hdev->id);
 		return;
+	}
 
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
-	if (conn) {
-		conn->state = BT_CLOSED;
+	if (!conn)
+		goto unlock;
 
-		hci_proto_disconn_cfm(conn, ev->reason);
-		hci_conn_del(conn);
-	}
+	conn->state = BT_CLOSED;
+
+	if (conn->type == ACL_LINK)
+		mgmt_disconnected(hdev->id, &conn->dst);
 
+	hci_proto_disconn_cfm(conn, ev->reason);
+	hci_conn_del(conn);
+
+unlock:
 	hci_dev_unlock(hdev);
 }
 
@@ -1098,8 +1424,10 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
 		if (!ev->status) {
 			conn->link_mode |= HCI_LM_AUTH;
 			conn->sec_level = conn->pending_sec_level;
-		} else
+		} else {
+			mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
 			conn->sec_level = BT_SECURITY_LOW;
+		}
 
 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
 
@@ -1393,11 +1721,54 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
 		hci_cc_write_ca_timeout(hdev, skb);
 		break;
 
+	case HCI_OP_DELETE_STORED_LINK_KEY:
+		hci_cc_delete_stored_link_key(hdev, skb);
+		break;
+
+	case HCI_OP_SET_EVENT_MASK:
+		hci_cc_set_event_mask(hdev, skb);
+		break;
+
+	case HCI_OP_WRITE_INQUIRY_MODE:
+		hci_cc_write_inquiry_mode(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;
+
+	case HCI_OP_PIN_CODE_NEG_REPLY:
+		hci_cc_pin_code_neg_reply(hdev, skb);
+		break;
+
+	case HCI_OP_LE_READ_BUFFER_SIZE:
+		hci_cc_le_read_buffer_size(hdev, skb);
+		break;
+
+	case HCI_OP_USER_CONFIRM_REPLY:
+		hci_cc_user_confirm_reply(hdev, skb);
+		break;
+
+	case HCI_OP_USER_CONFIRM_NEG_REPLY:
+		hci_cc_user_confirm_neg_reply(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
 	}
 
+	if (ev->opcode != HCI_OP_NOP)
+		del_timer(&hdev->cmd_timer);
+
 	if (ev->ncmd) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		if (!skb_queue_empty(&hdev->cmd_q))
@@ -1459,11 +1830,23 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_cs_exit_sniff_mode(hdev, ev->status);
 		break;
 
+	case HCI_OP_DISCONNECT:
+		if (ev->status != 0)
+			mgmt_disconnect_failed(hdev->id);
+		break;
+
+	case HCI_OP_LE_CREATE_CONN:
+		hci_cs_le_create_conn(hdev, ev->status);
+		break;
+
 	default:
 		BT_DBG("%s opcode 0x%x", hdev->name, opcode);
 		break;
 	}
 
+	if (ev->opcode != HCI_OP_NOP)
+		del_timer(&hdev->cmd_timer);
+
 	if (ev->ncmd) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		if (!skb_queue_empty(&hdev->cmd_q))
@@ -1529,6 +1912,16 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
 				hdev->acl_cnt += count;
 				if (hdev->acl_cnt > hdev->acl_pkts)
 					hdev->acl_cnt = hdev->acl_pkts;
+			} else if (conn->type == LE_LINK) {
+				if (hdev->le_pkts) {
+					hdev->le_cnt += count;
+					if (hdev->le_cnt > hdev->le_pkts)
+						hdev->le_cnt = hdev->le_pkts;
+				} else {
+					hdev->acl_cnt += count;
+					if (hdev->acl_cnt > hdev->acl_pkts)
+						hdev->acl_cnt = hdev->acl_pkts;
+				}
 			} else {
 				hdev->sco_cnt += count;
 				if (hdev->sco_cnt > hdev->sco_pkts)
@@ -1586,18 +1979,72 @@ static inline void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff
 		hci_conn_put(conn);
 	}
 
+	if (!test_bit(HCI_PAIRABLE, &hdev->flags))
+		hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
+					sizeof(ev->bdaddr), &ev->bdaddr);
+
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_pin_code_request(hdev->id, &ev->bdaddr);
+
 	hci_dev_unlock(hdev);
 }
 
 static inline void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
+	struct hci_ev_link_key_req *ev = (void *) skb->data;
+	struct hci_cp_link_key_reply cp;
+	struct hci_conn *conn;
+	struct link_key *key;
+
 	BT_DBG("%s", hdev->name);
+
+	if (!test_bit(HCI_LINK_KEYS, &hdev->flags))
+		return;
+
+	hci_dev_lock(hdev);
+
+	key = hci_find_link_key(hdev, &ev->bdaddr);
+	if (!key) {
+		BT_DBG("%s link key not found for %s", hdev->name,
+							batostr(&ev->bdaddr));
+		goto not_found;
+	}
+
+	BT_DBG("%s found key type %u for %s", hdev->name, key->type,
+							batostr(&ev->bdaddr));
+
+	if (!test_bit(HCI_DEBUG_KEYS, &hdev->flags) && key->type == 0x03) {
+		BT_DBG("%s ignoring debug key", hdev->name);
+		goto not_found;
+	}
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+
+	if (key->type == 0x04 && conn && conn->auth_type != 0xff &&
+						(conn->auth_type & 0x01)) {
+		BT_DBG("%s ignoring unauthenticated key", hdev->name);
+		goto not_found;
+	}
+
+	bacpy(&cp.bdaddr, &ev->bdaddr);
+	memcpy(cp.link_key, key->val, 16);
+
+	hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
+
+	hci_dev_unlock(hdev);
+
+	return;
+
+not_found:
+	hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
+	hci_dev_unlock(hdev);
 }
 
 static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_link_key_notify *ev = (void *) skb->data;
 	struct hci_conn *conn;
+	u8 pin_len = 0;
 
 	BT_DBG("%s", hdev->name);
 
@@ -1607,9 +2054,14 @@ static inline void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff
 	if (conn) {
 		hci_conn_hold(conn);
 		conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+		pin_len = conn->pin_length;
 		hci_conn_put(conn);
 	}
 
+	if (test_bit(HCI_LINK_KEYS, &hdev->flags))
+		hci_add_link_key(hdev, 1, &ev->bdaddr, ev->link_key,
+							ev->key_type, pin_len);
+
 	hci_dev_unlock(hdev);
 }
 
@@ -1683,7 +2135,8 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
 	hci_dev_lock(hdev);
 
 	if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
-		struct inquiry_info_with_rssi_and_pscan_mode *info = (void *) (skb->data + 1);
+		struct inquiry_info_with_rssi_and_pscan_mode *info;
+		info = (void *) (skb->data + 1);
 
 		for (; num_rsp; num_rsp--) {
 			bacpy(&data.bdaddr, &info->bdaddr);
@@ -1824,17 +2277,8 @@ static inline void hci_sync_conn_changed_evt(struct hci_dev *hdev, struct sk_buf
 static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
-	struct hci_conn *conn;
 
 	BT_DBG("%s status %d", hdev->name, ev->status);
-
-	hci_dev_lock(hdev);
-
-	conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
-	if (conn) {
-	}
-
-	hci_dev_unlock(hdev);
 }
 
 static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1852,12 +2296,12 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
 
 	for (; num_rsp; num_rsp--) {
 		bacpy(&data.bdaddr, &info->bdaddr);
-		data.pscan_rep_mode     = info->pscan_rep_mode;
-		data.pscan_period_mode  = info->pscan_period_mode;
-		data.pscan_mode         = 0x00;
+		data.pscan_rep_mode	= info->pscan_rep_mode;
+		data.pscan_period_mode	= info->pscan_period_mode;
+		data.pscan_mode		= 0x00;
 		memcpy(data.dev_class, info->dev_class, 3);
-		data.clock_offset       = info->clock_offset;
-		data.rssi               = info->rssi;
+		data.clock_offset	= info->clock_offset;
+		data.rssi		= info->rssi;
 		data.ssp_mode		= 0x01;
 		info++;
 		hci_inquiry_cache_update(hdev, &data);
@@ -1866,6 +2310,25 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
 	hci_dev_unlock(hdev);
 }
 
+static inline u8 hci_get_auth_req(struct hci_conn *conn)
+{
+	/* If remote requests dedicated bonding follow that lead */
+	if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) {
+		/* If both remote and local IO capabilities allow MITM
+		 * protection then require it, otherwise don't */
+		if (conn->remote_cap == 0x03 || conn->io_capability == 0x03)
+			return 0x02;
+		else
+			return 0x03;
+	}
+
+	/* If remote requests no-bonding follow that lead */
+	if (conn->remote_auth == 0x00 || conn->remote_auth == 0x01)
+		return 0x00;
+
+	return conn->auth_type;
+}
+
 static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_io_capa_request *ev = (void *) skb->data;
@@ -1876,8 +2339,73 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-	if (conn)
-		hci_conn_hold(conn);
+	if (!conn)
+		goto unlock;
+
+	hci_conn_hold(conn);
+
+	if (!test_bit(HCI_MGMT, &hdev->flags))
+		goto unlock;
+
+	if (test_bit(HCI_PAIRABLE, &hdev->flags) ||
+			(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
+		struct hci_cp_io_capability_reply cp;
+
+		bacpy(&cp.bdaddr, &ev->bdaddr);
+		cp.capability = conn->io_capability;
+		cp.oob_data = 0;
+		cp.authentication = hci_get_auth_req(conn);
+
+		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
+							sizeof(cp), &cp);
+	} else {
+		struct hci_cp_io_capability_neg_reply cp;
+
+		bacpy(&cp.bdaddr, &ev->bdaddr);
+		cp.reason = 0x16; /* Pairing not allowed */
+
+		hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
+							sizeof(cp), &cp);
+	}
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
+static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_io_capa_reply *ev = (void *) skb->data;
+	struct hci_conn *conn;
+
+	BT_DBG("%s", hdev->name);
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+	if (!conn)
+		goto unlock;
+
+	hci_conn_hold(conn);
+
+	conn->remote_cap = ev->capability;
+	conn->remote_oob = ev->oob_data;
+	conn->remote_auth = ev->authentication;
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
+static inline void hci_user_confirm_request_evt(struct hci_dev *hdev,
+							struct sk_buff *skb)
+{
+	struct hci_ev_user_confirm_req *ev = (void *) skb->data;
+
+	BT_DBG("%s", hdev->name);
+
+	hci_dev_lock(hdev);
+
+	if (test_bit(HCI_MGMT, &hdev->flags))
+		mgmt_user_confirm_request(hdev->id, &ev->bdaddr, ev->passkey);
 
 	hci_dev_unlock(hdev);
 }
@@ -1892,9 +2420,20 @@ static inline void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
-	if (conn)
-		hci_conn_put(conn);
+	if (!conn)
+		goto unlock;
+
+	/* To avoid duplicate auth_failed events to user space we check
+	 * the HCI_CONN_AUTH_PEND flag which will be set if we
+	 * initiated the authentication. A traditional auth_complete
+	 * event gets always produced as initiator and is also mapped to
+	 * the mgmt_auth_failed event */
+	if (!test_bit(HCI_CONN_AUTH_PEND, &conn->pend) && ev->status != 0)
+		mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
+
+	hci_conn_put(conn);
 
+unlock:
 	hci_dev_unlock(hdev);
 }
 
@@ -1914,6 +2453,60 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
 	hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_le_conn_complete *ev = (void *) skb->data;
+	struct hci_conn *conn;
+
+	BT_DBG("%s status %d", hdev->name, ev->status);
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
+	if (!conn) {
+		conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr);
+		if (!conn) {
+			BT_ERR("No memory for new connection");
+			hci_dev_unlock(hdev);
+			return;
+		}
+	}
+
+	if (ev->status) {
+		hci_proto_connect_cfm(conn, ev->status);
+		conn->state = BT_CLOSED;
+		hci_conn_del(conn);
+		goto unlock;
+	}
+
+	conn->handle = __le16_to_cpu(ev->handle);
+	conn->state = BT_CONNECTED;
+
+	hci_conn_hold_device(conn);
+	hci_conn_add_sysfs(conn);
+
+	hci_proto_connect_cfm(conn, ev->status);
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
+static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_ev_le_meta *le_ev = (void *) skb->data;
+
+	skb_pull(skb, sizeof(*le_ev));
+
+	switch (le_ev->subevent) {
+	case HCI_EV_LE_CONN_COMPLETE:
+		hci_le_conn_complete_evt(hdev, skb);
+		break;
+
+	default:
+		break;
+	}
+}
+
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_event_hdr *hdr = (void *) skb->data;
@@ -2042,6 +2635,14 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_io_capa_request_evt(hdev, skb);
 		break;
 
+	case HCI_EV_IO_CAPA_REPLY:
+		hci_io_capa_reply_evt(hdev, skb);
+		break;
+
+	case HCI_EV_USER_CONFIRM_REQUEST:
+		hci_user_confirm_request_evt(hdev, skb);
+		break;
+
 	case HCI_EV_SIMPLE_PAIR_COMPLETE:
 		hci_simple_pair_complete_evt(hdev, skb);
 		break;
@@ -2050,6 +2651,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
 		hci_remote_host_features_evt(hdev, skb);
 		break;
 
+	case HCI_EV_LE_META:
+		hci_le_meta_evt(hdev, skb);
+		break;
+
 	default:
 		BT_DBG("%s event 0x%x", hdev->name, event);
 		break;
@@ -2083,6 +2688,6 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
 
 	bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
 	skb->dev = (void *) hdev;
-	hci_send_to_sock(hdev, skb);
+	hci_send_to_sock(hdev, skb, NULL);
 	kfree_skb(skb);
 }
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 29827c7..295e4a8 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -85,7 +85,8 @@ static struct bt_sock_list hci_sk_list = {
 };
 
 /* Send frame to RAW socket */
-void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
+void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
+							struct sock *skip_sk)
 {
 	struct sock *sk;
 	struct hlist_node *node;
@@ -97,6 +98,9 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
 		struct hci_filter *flt;
 		struct sk_buff *nskb;
 
+		if (sk == skip_sk)
+			continue;
+
 		if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
 			continue;
 
@@ -857,7 +861,7 @@ error:
 	return err;
 }
 
-void __exit hci_sock_cleanup(void)
+void hci_sock_cleanup(void)
 {
 	if (bt_sock_unregister(BTPROTO_HCI) < 0)
 		BT_ERR("HCI socket unregistration failed");
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 5fce3d6..3c838a6 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -11,7 +11,7 @@
 
 static struct class *bt_class;
 
-struct dentry *bt_debugfs = NULL;
+struct dentry *bt_debugfs;
 EXPORT_SYMBOL_GPL(bt_debugfs);
 
 static inline char *link_typetostr(int type)
@@ -51,8 +51,8 @@ static ssize_t show_link_features(struct device *dev, struct device_attribute *a
 				conn->features[6], conn->features[7]);
 }
 
-#define LINK_ATTR(_name,_mode,_show,_store) \
-struct device_attribute link_attr_##_name = __ATTR(_name,_mode,_show,_store)
+#define LINK_ATTR(_name, _mode, _show, _store) \
+struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store)
 
 static LINK_ATTR(type, S_IRUGO, show_link_type, NULL);
 static LINK_ATTR(address, S_IRUGO, show_link_address, NULL);
@@ -461,6 +461,56 @@ static const struct file_operations blacklist_fops = {
 	.llseek		= seq_lseek,
 	.release	= single_release,
 };
+
+static void print_bt_uuid(struct seq_file *f, u8 *uuid)
+{
+	u32 data0, data4;
+	u16 data1, data2, data3, data5;
+
+	memcpy(&data0, &uuid[0], 4);
+	memcpy(&data1, &uuid[4], 2);
+	memcpy(&data2, &uuid[6], 2);
+	memcpy(&data3, &uuid[8], 2);
+	memcpy(&data4, &uuid[10], 4);
+	memcpy(&data5, &uuid[14], 2);
+
+	seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x\n",
+				ntohl(data0), ntohs(data1), ntohs(data2),
+				ntohs(data3), ntohl(data4), ntohs(data5));
+}
+
+static int uuids_show(struct seq_file *f, void *p)
+{
+	struct hci_dev *hdev = f->private;
+	struct list_head *l;
+
+	hci_dev_lock_bh(hdev);
+
+	list_for_each(l, &hdev->uuids) {
+		struct bt_uuid *uuid;
+
+		uuid = list_entry(l, struct bt_uuid, list);
+
+		print_bt_uuid(f, uuid->uuid);
+	}
+
+	hci_dev_unlock_bh(hdev);
+
+	return 0;
+}
+
+static int uuids_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, uuids_show, inode->i_private);
+}
+
+static const struct file_operations uuids_fops = {
+	.open		= uuids_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 int hci_register_sysfs(struct hci_dev *hdev)
 {
 	struct device *dev = &hdev->dev;
@@ -493,6 +543,8 @@ int hci_register_sysfs(struct hci_dev *hdev)
 	debugfs_create_file("blacklist", 0444, hdev->debugfs,
 						hdev, &blacklist_fops);
 
+	debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
+
 	return 0;
 }
 
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 29544c2..5ec1297 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -36,6 +36,7 @@
 #include <linux/file.h>
 #include <linux/init.h>
 #include <linux/wait.h>
+#include <linux/mutex.h>
 #include <net/sock.h>
 
 #include <linux/input.h>
@@ -157,7 +158,8 @@ static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
 
 	session->leds = newleds;
 
-	if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
+	skb = alloc_skb(3, GFP_ATOMIC);
+	if (!skb) {
 		BT_ERR("Can't allocate memory for new frame");
 		return -ENOMEM;
 	}
@@ -250,7 +252,8 @@ static int __hidp_send_ctrl_message(struct hidp_session *session,
 
 	BT_DBG("session %p data %p size %d", session, data, size);
 
-	if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
+	skb = alloc_skb(size + 1, GFP_ATOMIC);
+	if (!skb) {
 		BT_ERR("Can't allocate memory for new frame");
 		return -ENOMEM;
 	}
@@ -283,7 +286,8 @@ static int hidp_queue_report(struct hidp_session *session,
 
 	BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
 
-	if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
+	skb = alloc_skb(size + 1, GFP_ATOMIC);
+	if (!skb) {
 		BT_ERR("Can't allocate memory for new frame");
 		return -ENOMEM;
 	}
@@ -313,24 +317,144 @@ static int hidp_send_report(struct hidp_session *session, struct hid_report *rep
 	return hidp_queue_report(session, buf, rsize);
 }
 
+static int hidp_get_raw_report(struct hid_device *hid,
+		unsigned char report_number,
+		unsigned char *data, size_t count,
+		unsigned char report_type)
+{
+	struct hidp_session *session = hid->driver_data;
+	struct sk_buff *skb;
+	size_t len;
+	int numbered_reports = hid->report_enum[report_type].numbered;
+
+	switch (report_type) {
+	case HID_FEATURE_REPORT:
+		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
+		break;
+	case HID_INPUT_REPORT:
+		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
+		break;
+	case HID_OUTPUT_REPORT:
+		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (mutex_lock_interruptible(&session->report_mutex))
+		return -ERESTARTSYS;
+
+	/* Set up our wait, and send the report request to the device. */
+	session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
+	session->waiting_report_number = numbered_reports ? report_number : -1;
+	set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+	data[0] = report_number;
+	if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
+		goto err_eio;
+
+	/* Wait for the return of the report. The returned report
+	   gets put in session->report_return.  */
+	while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
+		int res;
+
+		res = wait_event_interruptible_timeout(session->report_queue,
+			!test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
+			5*HZ);
+		if (res == 0) {
+			/* timeout */
+			goto err_eio;
+		}
+		if (res < 0) {
+			/* signal */
+			goto err_restartsys;
+		}
+	}
+
+	skb = session->report_return;
+	if (skb) {
+		len = skb->len < count ? skb->len : count;
+		memcpy(data, skb->data, len);
+
+		kfree_skb(skb);
+		session->report_return = NULL;
+	} else {
+		/* Device returned a HANDSHAKE, indicating  protocol error. */
+		len = -EIO;
+	}
+
+	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+	mutex_unlock(&session->report_mutex);
+
+	return len;
+
+err_restartsys:
+	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+	mutex_unlock(&session->report_mutex);
+	return -ERESTARTSYS;
+err_eio:
+	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+	mutex_unlock(&session->report_mutex);
+	return -EIO;
+}
+
 static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
 		unsigned char report_type)
 {
+	struct hidp_session *session = hid->driver_data;
+	int ret;
+
 	switch (report_type) {
 	case HID_FEATURE_REPORT:
 		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
 		break;
 	case HID_OUTPUT_REPORT:
-		report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
+		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	if (mutex_lock_interruptible(&session->report_mutex))
+		return -ERESTARTSYS;
+
+	/* Set up our wait, and send the report request to the device. */
+	set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
 	if (hidp_send_ctrl_message(hid->driver_data, report_type,
-			data, count))
-		return -ENOMEM;
-	return count;
+			data, count)) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Wait for the ACK from the device. */
+	while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
+		int res;
+
+		res = wait_event_interruptible_timeout(session->report_queue,
+			!test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
+			10*HZ);
+		if (res == 0) {
+			/* timeout */
+			ret = -EIO;
+			goto err;
+		}
+		if (res < 0) {
+			/* signal */
+			ret = -ERESTARTSYS;
+			goto err;
+		}
+	}
+
+	if (!session->output_report_success) {
+		ret = -EIO;
+		goto err;
+	}
+
+	ret = count;
+
+err:
+	clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+	mutex_unlock(&session->report_mutex);
+	return ret;
 }
 
 static void hidp_idle_timeout(unsigned long arg)
@@ -357,16 +481,22 @@ static void hidp_process_handshake(struct hidp_session *session,
 					unsigned char param)
 {
 	BT_DBG("session %p param 0x%02x", session, param);
+	session->output_report_success = 0; /* default condition */
 
 	switch (param) {
 	case HIDP_HSHK_SUCCESSFUL:
 		/* FIXME: Call into SET_ GET_ handlers here */
+		session->output_report_success = 1;
 		break;
 
 	case HIDP_HSHK_NOT_READY:
 	case HIDP_HSHK_ERR_INVALID_REPORT_ID:
 	case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
 	case HIDP_HSHK_ERR_INVALID_PARAMETER:
+		if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
+			clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+			wake_up_interruptible(&session->report_queue);
+		}
 		/* FIXME: Call into SET_ GET_ handlers here */
 		break;
 
@@ -385,6 +515,12 @@ static void hidp_process_handshake(struct hidp_session *session,
 			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
 		break;
 	}
+
+	/* Wake up the waiting thread. */
+	if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
+		clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
+		wake_up_interruptible(&session->report_queue);
+	}
 }
 
 static void hidp_process_hid_control(struct hidp_session *session,
@@ -403,9 +539,11 @@ static void hidp_process_hid_control(struct hidp_session *session,
 	}
 }
 
-static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
+/* Returns true if the passed-in skb should be freed by the caller. */
+static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
 				unsigned char param)
 {
+	int done_with_skb = 1;
 	BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
 
 	switch (param) {
@@ -417,7 +555,6 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
 
 		if (session->hid)
 			hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
-
 		break;
 
 	case HIDP_DATA_RTYPE_OTHER:
@@ -429,12 +566,27 @@ static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
 		__hidp_send_ctrl_message(session,
 			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
 	}
+
+	if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
+				param == session->waiting_report_type) {
+		if (session->waiting_report_number < 0 ||
+		    session->waiting_report_number == skb->data[0]) {
+			/* hidp_get_raw_report() is waiting on this report. */
+			session->report_return = skb;
+			done_with_skb = 0;
+			clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
+			wake_up_interruptible(&session->report_queue);
+		}
+	}
+
+	return done_with_skb;
 }
 
 static void hidp_recv_ctrl_frame(struct hidp_session *session,
 					struct sk_buff *skb)
 {
 	unsigned char hdr, type, param;
+	int free_skb = 1;
 
 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
 
@@ -454,7 +606,7 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
 		break;
 
 	case HIDP_TRANS_DATA:
-		hidp_process_data(session, skb, param);
+		free_skb = hidp_process_data(session, skb, param);
 		break;
 
 	default:
@@ -463,7 +615,8 @@ static void hidp_recv_ctrl_frame(struct hidp_session *session,
 		break;
 	}
 
-	kfree_skb(skb);
+	if (free_skb)
+		kfree_skb(skb);
 }
 
 static void hidp_recv_intr_frame(struct hidp_session *session,
@@ -563,6 +716,8 @@ static int hidp_session(void *arg)
 	init_waitqueue_entry(&intr_wait, current);
 	add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
 	add_wait_queue(sk_sleep(intr_sk), &intr_wait);
+	session->waiting_for_startup = 0;
+	wake_up_interruptible(&session->startup_queue);
 	while (!atomic_read(&session->terminate)) {
 		set_current_state(TASK_INTERRUPTIBLE);
 
@@ -754,6 +909,8 @@ static struct hid_ll_driver hidp_hid_driver = {
 	.hidinput_input_event = hidp_hidinput_event,
 };
 
+/* This function sets up the hid device. It does not add it
+   to the HID system. That is done in hidp_add_connection(). */
 static int hidp_setup_hid(struct hidp_session *session,
 				struct hidp_connadd_req *req)
 {
@@ -793,18 +950,11 @@ static int hidp_setup_hid(struct hidp_session *session,
 	hid->dev.parent = hidp_get_device(session);
 	hid->ll_driver = &hidp_hid_driver;
 
+	hid->hid_get_raw_report = hidp_get_raw_report;
 	hid->hid_output_raw_report = hidp_output_raw_report;
 
-	err = hid_add_device(hid);
-	if (err < 0)
-		goto failed;
-
 	return 0;
 
-failed:
-	hid_destroy_device(hid);
-	session->hid = NULL;
-
 fault:
 	kfree(session->rd_data);
 	session->rd_data = NULL;
@@ -853,6 +1003,10 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 	skb_queue_head_init(&session->ctrl_transmit);
 	skb_queue_head_init(&session->intr_transmit);
 
+	mutex_init(&session->report_mutex);
+	init_waitqueue_head(&session->report_queue);
+	init_waitqueue_head(&session->startup_queue);
+	session->waiting_for_startup = 1;
 	session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
 	session->idle_to = req->idle_to;
 
@@ -875,6 +1029,14 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 	err = kernel_thread(hidp_session, session, CLONE_KERNEL);
 	if (err < 0)
 		goto unlink;
+	while (session->waiting_for_startup) {
+		wait_event_interruptible(session->startup_queue,
+			!session->waiting_for_startup);
+	}
+
+	err = hid_add_device(session->hid);
+	if (err < 0)
+		goto err_add_device;
 
 	if (session->input) {
 		hidp_send_ctrl_message(session,
@@ -888,6 +1050,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
 	up_write(&hidp_session_sem);
 	return 0;
 
+err_add_device:
+	hid_destroy_device(session->hid);
+	session->hid = NULL;
+	atomic_inc(&session->terminate);
+	hidp_schedule(session);
+
 unlink:
 	hidp_del_timer(session);
 
@@ -1016,8 +1184,6 @@ static int __init hidp_init(void)
 {
 	int ret;
 
-	l2cap_load();
-
 	BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
 
 	ret = hid_register_driver(&hidp_driver);
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index 8d934a1..13de5fa 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -80,6 +80,8 @@
 #define HIDP_VIRTUAL_CABLE_UNPLUG	0
 #define HIDP_BOOT_PROTOCOL_MODE		1
 #define HIDP_BLUETOOTH_VENDOR_ID	9
+#define	HIDP_WAITING_FOR_RETURN		10
+#define HIDP_WAITING_FOR_SEND_ACK	11
 
 struct hidp_connadd_req {
 	int   ctrl_sock;	// Connected control socket
@@ -154,9 +156,22 @@ struct hidp_session {
 	struct sk_buff_head ctrl_transmit;
 	struct sk_buff_head intr_transmit;
 
+	/* Used in hidp_get_raw_report() */
+	int waiting_report_type; /* HIDP_DATA_RTYPE_* */
+	int waiting_report_number; /* -1 for not numbered */
+	struct mutex report_mutex;
+	struct sk_buff *report_return;
+	wait_queue_head_t report_queue;
+
+	/* Used in hidp_output_raw_report() */
+	int output_report_success; /* boolean */
+
 	/* Report descriptor */
 	__u8 *rd_data;
 	uint rd_size;
+
+	wait_queue_head_t startup_queue;
+	int waiting_for_startup;
 };
 
 static inline void hidp_schedule(struct hidp_session *session)
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
deleted file mode 100644
index 675614e..0000000
--- a/net/bluetooth/l2cap.c
+++ /dev/null
@@ -1,4930 +0,0 @@
-/*
-   BlueZ - Bluetooth protocol stack for Linux
-   Copyright (C) 2000-2001 Qualcomm Incorporated
-   Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
-   Copyright (C) 2010 Google Inc.
-
-   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation;
-
-   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
-   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
-   SOFTWARE IS DISCLAIMED.
-*/
-
-/* Bluetooth L2CAP core and sockets. */
-
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/socket.h>
-#include <linux/skbuff.h>
-#include <linux/list.h>
-#include <linux/device.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/crc16.h>
-#include <net/sock.h>
-
-#include <asm/system.h>
-#include <asm/unaligned.h>
-
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-#include <net/bluetooth/l2cap.h>
-
-#define VERSION "2.15"
-
-static int disable_ertm;
-
-static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
-static u8 l2cap_fixed_chan[8] = { 0x02, };
-
-static const struct proto_ops l2cap_sock_ops;
-
-static struct workqueue_struct *_busy_wq;
-
-static struct bt_sock_list l2cap_sk_list = {
-	.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
-};
-
-static void l2cap_busy_work(struct work_struct *work);
-
-static void __l2cap_sock_close(struct sock *sk, int reason);
-static void l2cap_sock_close(struct sock *sk);
-static void l2cap_sock_kill(struct sock *sk);
-
-static int l2cap_build_conf_req(struct sock *sk, void *data);
-static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
-				u8 code, u8 ident, u16 dlen, void *data);
-
-static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
-
-/* ---- L2CAP timers ---- */
-static void l2cap_sock_set_timer(struct sock *sk, long timeout)
-{
-	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
-	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
-}
-
-static void l2cap_sock_clear_timer(struct sock *sk)
-{
-	BT_DBG("sock %p state %d", sk, sk->sk_state);
-	sk_stop_timer(sk, &sk->sk_timer);
-}
-
-static void l2cap_sock_timeout(unsigned long arg)
-{
-	struct sock *sk = (struct sock *) arg;
-	int reason;
-
-	BT_DBG("sock %p state %d", sk, sk->sk_state);
-
-	bh_lock_sock(sk);
-
-	if (sock_owned_by_user(sk)) {
-		/* sk is owned by user. Try again later */
-		l2cap_sock_set_timer(sk, HZ / 5);
-		bh_unlock_sock(sk);
-		sock_put(sk);
-		return;
-	}
-
-	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
-		reason = ECONNREFUSED;
-	else if (sk->sk_state == BT_CONNECT &&
-				l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
-		reason = ECONNREFUSED;
-	else
-		reason = ETIMEDOUT;
-
-	__l2cap_sock_close(sk, reason);
-
-	bh_unlock_sock(sk);
-
-	l2cap_sock_kill(sk);
-	sock_put(sk);
-}
-
-/* ---- L2CAP channels ---- */
-static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
-{
-	struct sock *s;
-	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
-		if (l2cap_pi(s)->dcid == cid)
-			break;
-	}
-	return s;
-}
-
-static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
-{
-	struct sock *s;
-	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
-		if (l2cap_pi(s)->scid == cid)
-			break;
-	}
-	return s;
-}
-
-/* Find channel with given SCID.
- * Returns locked socket */
-static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
-{
-	struct sock *s;
-	read_lock(&l->lock);
-	s = __l2cap_get_chan_by_scid(l, cid);
-	if (s)
-		bh_lock_sock(s);
-	read_unlock(&l->lock);
-	return s;
-}
-
-static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
-{
-	struct sock *s;
-	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
-		if (l2cap_pi(s)->ident == ident)
-			break;
-	}
-	return s;
-}
-
-static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
-{
-	struct sock *s;
-	read_lock(&l->lock);
-	s = __l2cap_get_chan_by_ident(l, ident);
-	if (s)
-		bh_lock_sock(s);
-	read_unlock(&l->lock);
-	return s;
-}
-
-static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
-{
-	u16 cid = L2CAP_CID_DYN_START;
-
-	for (; cid < L2CAP_CID_DYN_END; cid++) {
-		if (!__l2cap_get_chan_by_scid(l, cid))
-			return cid;
-	}
-
-	return 0;
-}
-
-static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
-{
-	sock_hold(sk);
-
-	if (l->head)
-		l2cap_pi(l->head)->prev_c = sk;
-
-	l2cap_pi(sk)->next_c = l->head;
-	l2cap_pi(sk)->prev_c = NULL;
-	l->head = sk;
-}
-
-static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
-{
-	struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
-
-	write_lock_bh(&l->lock);
-	if (sk == l->head)
-		l->head = next;
-
-	if (next)
-		l2cap_pi(next)->prev_c = prev;
-	if (prev)
-		l2cap_pi(prev)->next_c = next;
-	write_unlock_bh(&l->lock);
-
-	__sock_put(sk);
-}
-
-static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-
-	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
-			l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
-
-	conn->disc_reason = 0x13;
-
-	l2cap_pi(sk)->conn = conn;
-
-	if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
-		/* Alloc CID for connection-oriented socket */
-		l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
-	} else if (sk->sk_type == SOCK_DGRAM) {
-		/* Connectionless socket */
-		l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
-		l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
-		l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
-	} else {
-		/* Raw socket can send/recv signalling messages only */
-		l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
-		l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
-		l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
-	}
-
-	__l2cap_chan_link(l, sk);
-
-	if (parent)
-		bt_accept_enqueue(parent, sk);
-}
-
-/* Delete channel.
- * Must be called on the locked socket. */
-static void l2cap_chan_del(struct sock *sk, int err)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sock *parent = bt_sk(sk)->parent;
-
-	l2cap_sock_clear_timer(sk);
-
-	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
-
-	if (conn) {
-		/* Unlink from channel list */
-		l2cap_chan_unlink(&conn->chan_list, sk);
-		l2cap_pi(sk)->conn = NULL;
-		hci_conn_put(conn->hcon);
-	}
-
-	sk->sk_state = BT_CLOSED;
-	sock_set_flag(sk, SOCK_ZAPPED);
-
-	if (err)
-		sk->sk_err = err;
-
-	if (parent) {
-		bt_accept_unlink(sk);
-		parent->sk_data_ready(parent, 0);
-	} else
-		sk->sk_state_change(sk);
-
-	skb_queue_purge(TX_QUEUE(sk));
-
-	if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
-		struct srej_list *l, *tmp;
-
-		del_timer(&l2cap_pi(sk)->retrans_timer);
-		del_timer(&l2cap_pi(sk)->monitor_timer);
-		del_timer(&l2cap_pi(sk)->ack_timer);
-
-		skb_queue_purge(SREJ_QUEUE(sk));
-		skb_queue_purge(BUSY_QUEUE(sk));
-
-		list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
-			list_del(&l->list);
-			kfree(l);
-		}
-	}
-}
-
-static inline u8 l2cap_get_auth_type(struct sock *sk)
-{
-	if (sk->sk_type == SOCK_RAW) {
-		switch (l2cap_pi(sk)->sec_level) {
-		case BT_SECURITY_HIGH:
-			return HCI_AT_DEDICATED_BONDING_MITM;
-		case BT_SECURITY_MEDIUM:
-			return HCI_AT_DEDICATED_BONDING;
-		default:
-			return HCI_AT_NO_BONDING;
-		}
-	} else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
-		if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
-
-		if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
-			return HCI_AT_NO_BONDING_MITM;
-		else
-			return HCI_AT_NO_BONDING;
-	} else {
-		switch (l2cap_pi(sk)->sec_level) {
-		case BT_SECURITY_HIGH:
-			return HCI_AT_GENERAL_BONDING_MITM;
-		case BT_SECURITY_MEDIUM:
-			return HCI_AT_GENERAL_BONDING;
-		default:
-			return HCI_AT_NO_BONDING;
-		}
-	}
-}
-
-/* Service level security */
-static inline int l2cap_check_security(struct sock *sk)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	__u8 auth_type;
-
-	auth_type = l2cap_get_auth_type(sk);
-
-	return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
-								auth_type);
-}
-
-static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
-{
-	u8 id;
-
-	/* Get next available identificator.
-	 *    1 - 128 are used by kernel.
-	 *  129 - 199 are reserved.
-	 *  200 - 254 are used by utilities like l2ping, etc.
-	 */
-
-	spin_lock_bh(&conn->lock);
-
-	if (++conn->tx_ident > 128)
-		conn->tx_ident = 1;
-
-	id = conn->tx_ident;
-
-	spin_unlock_bh(&conn->lock);
-
-	return id;
-}
-
-static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
-{
-	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
-
-	BT_DBG("code 0x%2.2x", code);
-
-	if (!skb)
-		return;
-
-	hci_send_acl(conn->hcon, skb, 0);
-}
-
-static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
-{
-	struct sk_buff *skb;
-	struct l2cap_hdr *lh;
-	struct l2cap_conn *conn = pi->conn;
-	struct sock *sk = (struct sock *)pi;
-	int count, hlen = L2CAP_HDR_SIZE + 2;
-
-	if (sk->sk_state != BT_CONNECTED)
-		return;
-
-	if (pi->fcs == L2CAP_FCS_CRC16)
-		hlen += 2;
-
-	BT_DBG("pi %p, control 0x%2.2x", pi, control);
-
-	count = min_t(unsigned int, conn->mtu, hlen);
-	control |= L2CAP_CTRL_FRAME_TYPE;
-
-	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
-		control |= L2CAP_CTRL_FINAL;
-		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-	}
-
-	if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
-		control |= L2CAP_CTRL_POLL;
-		pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
-	}
-
-	skb = bt_skb_alloc(count, GFP_ATOMIC);
-	if (!skb)
-		return;
-
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
-	lh->cid = cpu_to_le16(pi->dcid);
-	put_unaligned_le16(control, skb_put(skb, 2));
-
-	if (pi->fcs == L2CAP_FCS_CRC16) {
-		u16 fcs = crc16(0, (u8 *)lh, count - 2);
-		put_unaligned_le16(fcs, skb_put(skb, 2));
-	}
-
-	hci_send_acl(pi->conn->hcon, skb, 0);
-}
-
-static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
-{
-	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
-		control |= L2CAP_SUPER_RCV_NOT_READY;
-		pi->conn_state |= L2CAP_CONN_RNR_SENT;
-	} else
-		control |= L2CAP_SUPER_RCV_READY;
-
-	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-
-	l2cap_send_sframe(pi, control);
-}
-
-static inline int __l2cap_no_conn_pending(struct sock *sk)
-{
-	return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
-}
-
-static void l2cap_do_start(struct sock *sk)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-
-	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
-		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
-			return;
-
-		if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
-			struct l2cap_conn_req req;
-			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-			req.psm  = l2cap_pi(sk)->psm;
-
-			l2cap_pi(sk)->ident = l2cap_get_ident(conn);
-			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
-
-			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_REQ, sizeof(req), &req);
-		}
-	} else {
-		struct l2cap_info_req req;
-		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
-
-		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
-		conn->info_ident = l2cap_get_ident(conn);
-
-		mod_timer(&conn->info_timer, jiffies +
-					msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
-
-		l2cap_send_cmd(conn, conn->info_ident,
-					L2CAP_INFO_REQ, sizeof(req), &req);
-	}
-}
-
-static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
-{
-	u32 local_feat_mask = l2cap_feat_mask;
-	if (!disable_ertm)
-		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
-
-	switch (mode) {
-	case L2CAP_MODE_ERTM:
-		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
-	case L2CAP_MODE_STREAMING:
-		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
-	default:
-		return 0x00;
-	}
-}
-
-static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
-{
-	struct l2cap_disconn_req req;
-
-	if (!conn)
-		return;
-
-	skb_queue_purge(TX_QUEUE(sk));
-
-	if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
-		del_timer(&l2cap_pi(sk)->retrans_timer);
-		del_timer(&l2cap_pi(sk)->monitor_timer);
-		del_timer(&l2cap_pi(sk)->ack_timer);
-	}
-
-	req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-	l2cap_send_cmd(conn, l2cap_get_ident(conn),
-			L2CAP_DISCONN_REQ, sizeof(req), &req);
-
-	sk->sk_state = BT_DISCONN;
-	sk->sk_err = err;
-}
-
-/* ---- L2CAP connections ---- */
-static void l2cap_conn_start(struct l2cap_conn *conn)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-	struct sock_del_list del, *tmp1, *tmp2;
-	struct sock *sk;
-
-	BT_DBG("conn %p", conn);
-
-	INIT_LIST_HEAD(&del.list);
-
-	read_lock(&l->lock);
-
-	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
-		bh_lock_sock(sk);
-
-		if (sk->sk_type != SOCK_SEQPACKET &&
-				sk->sk_type != SOCK_STREAM) {
-			bh_unlock_sock(sk);
-			continue;
-		}
-
-		if (sk->sk_state == BT_CONNECT) {
-			struct l2cap_conn_req req;
-
-			if (!l2cap_check_security(sk) ||
-					!__l2cap_no_conn_pending(sk)) {
-				bh_unlock_sock(sk);
-				continue;
-			}
-
-			if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
-					conn->feat_mask)
-					&& l2cap_pi(sk)->conf_state &
-					L2CAP_CONF_STATE2_DEVICE) {
-				tmp1 = kzalloc(sizeof(struct sock_del_list),
-						GFP_ATOMIC);
-				tmp1->sk = sk;
-				list_add_tail(&tmp1->list, &del.list);
-				bh_unlock_sock(sk);
-				continue;
-			}
-
-			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-			req.psm  = l2cap_pi(sk)->psm;
-
-			l2cap_pi(sk)->ident = l2cap_get_ident(conn);
-			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
-
-			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-				L2CAP_CONN_REQ, sizeof(req), &req);
-
-		} else if (sk->sk_state == BT_CONNECT2) {
-			struct l2cap_conn_rsp rsp;
-			char buf[128];
-			rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
-			rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
-
-			if (l2cap_check_security(sk)) {
-				if (bt_sk(sk)->defer_setup) {
-					struct sock *parent = bt_sk(sk)->parent;
-					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
-					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
-					parent->sk_data_ready(parent, 0);
-
-				} else {
-					sk->sk_state = BT_CONFIG;
-					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
-					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-				}
-			} else {
-				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
-				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
-			}
-
-			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-
-			if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
-					rsp.result != L2CAP_CR_SUCCESS) {
-				bh_unlock_sock(sk);
-				continue;
-			}
-
-			l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-						l2cap_build_conf_req(sk, buf), buf);
-			l2cap_pi(sk)->num_conf_req++;
-		}
-
-		bh_unlock_sock(sk);
-	}
-
-	read_unlock(&l->lock);
-
-	list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
-		bh_lock_sock(tmp1->sk);
-		__l2cap_sock_close(tmp1->sk, ECONNRESET);
-		bh_unlock_sock(tmp1->sk);
-		list_del(&tmp1->list);
-		kfree(tmp1);
-	}
-}
-
-static void l2cap_conn_ready(struct l2cap_conn *conn)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-	struct sock *sk;
-
-	BT_DBG("conn %p", conn);
-
-	read_lock(&l->lock);
-
-	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
-		bh_lock_sock(sk);
-
-		if (sk->sk_type != SOCK_SEQPACKET &&
-				sk->sk_type != SOCK_STREAM) {
-			l2cap_sock_clear_timer(sk);
-			sk->sk_state = BT_CONNECTED;
-			sk->sk_state_change(sk);
-		} else if (sk->sk_state == BT_CONNECT)
-			l2cap_do_start(sk);
-
-		bh_unlock_sock(sk);
-	}
-
-	read_unlock(&l->lock);
-}
-
-/* Notify sockets that we cannot guaranty reliability anymore */
-static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-	struct sock *sk;
-
-	BT_DBG("conn %p", conn);
-
-	read_lock(&l->lock);
-
-	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
-		if (l2cap_pi(sk)->force_reliable)
-			sk->sk_err = err;
-	}
-
-	read_unlock(&l->lock);
-}
-
-static void l2cap_info_timeout(unsigned long arg)
-{
-	struct l2cap_conn *conn = (void *) arg;
-
-	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
-	conn->info_ident = 0;
-
-	l2cap_conn_start(conn);
-}
-
-static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
-{
-	struct l2cap_conn *conn = hcon->l2cap_data;
-
-	if (conn || status)
-		return conn;
-
-	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
-	if (!conn)
-		return NULL;
-
-	hcon->l2cap_data = conn;
-	conn->hcon = hcon;
-
-	BT_DBG("hcon %p conn %p", hcon, conn);
-
-	conn->mtu = hcon->hdev->acl_mtu;
-	conn->src = &hcon->hdev->bdaddr;
-	conn->dst = &hcon->dst;
-
-	conn->feat_mask = 0;
-
-	spin_lock_init(&conn->lock);
-	rwlock_init(&conn->chan_list.lock);
-
-	setup_timer(&conn->info_timer, l2cap_info_timeout,
-						(unsigned long) conn);
-
-	conn->disc_reason = 0x13;
-
-	return conn;
-}
-
-static void l2cap_conn_del(struct hci_conn *hcon, int err)
-{
-	struct l2cap_conn *conn = hcon->l2cap_data;
-	struct sock *sk;
-
-	if (!conn)
-		return;
-
-	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
-
-	kfree_skb(conn->rx_skb);
-
-	/* Kill channels */
-	while ((sk = conn->chan_list.head)) {
-		bh_lock_sock(sk);
-		l2cap_chan_del(sk, err);
-		bh_unlock_sock(sk);
-		l2cap_sock_kill(sk);
-	}
-
-	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
-		del_timer_sync(&conn->info_timer);
-
-	hcon->l2cap_data = NULL;
-	kfree(conn);
-}
-
-static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-	write_lock_bh(&l->lock);
-	__l2cap_chan_add(conn, sk, parent);
-	write_unlock_bh(&l->lock);
-}
-
-/* ---- Socket interface ---- */
-static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
-{
-	struct sock *sk;
-	struct hlist_node *node;
-	sk_for_each(sk, node, &l2cap_sk_list.head)
-		if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
-			goto found;
-	sk = NULL;
-found:
-	return sk;
-}
-
-/* Find socket with psm and source bdaddr.
- * Returns closest match.
- */
-static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
-{
-	struct sock *sk = NULL, *sk1 = NULL;
-	struct hlist_node *node;
-
-	read_lock(&l2cap_sk_list.lock);
-
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		if (state && sk->sk_state != state)
-			continue;
-
-		if (l2cap_pi(sk)->psm == psm) {
-			/* Exact match. */
-			if (!bacmp(&bt_sk(sk)->src, src))
-				break;
-
-			/* Closest match */
-			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
-				sk1 = sk;
-		}
-	}
-
-	read_unlock(&l2cap_sk_list.lock);
-
-	return node ? sk : sk1;
-}
-
-static void l2cap_sock_destruct(struct sock *sk)
-{
-	BT_DBG("sk %p", sk);
-
-	skb_queue_purge(&sk->sk_receive_queue);
-	skb_queue_purge(&sk->sk_write_queue);
-}
-
-static void l2cap_sock_cleanup_listen(struct sock *parent)
-{
-	struct sock *sk;
-
-	BT_DBG("parent %p", parent);
-
-	/* Close not yet accepted channels */
-	while ((sk = bt_accept_dequeue(parent, NULL)))
-		l2cap_sock_close(sk);
-
-	parent->sk_state = BT_CLOSED;
-	sock_set_flag(parent, SOCK_ZAPPED);
-}
-
-/* Kill socket (only if zapped and orphan)
- * Must be called on unlocked socket.
- */
-static void l2cap_sock_kill(struct sock *sk)
-{
-	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
-		return;
-
-	BT_DBG("sk %p state %d", sk, sk->sk_state);
-
-	/* Kill poor orphan */
-	bt_sock_unlink(&l2cap_sk_list, sk);
-	sock_set_flag(sk, SOCK_DEAD);
-	sock_put(sk);
-}
-
-static void __l2cap_sock_close(struct sock *sk, int reason)
-{
-	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
-
-	switch (sk->sk_state) {
-	case BT_LISTEN:
-		l2cap_sock_cleanup_listen(sk);
-		break;
-
-	case BT_CONNECTED:
-	case BT_CONFIG:
-		if (sk->sk_type == SOCK_SEQPACKET ||
-				sk->sk_type == SOCK_STREAM) {
-			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-
-			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-			l2cap_send_disconn_req(conn, sk, reason);
-		} else
-			l2cap_chan_del(sk, reason);
-		break;
-
-	case BT_CONNECT2:
-		if (sk->sk_type == SOCK_SEQPACKET ||
-				sk->sk_type == SOCK_STREAM) {
-			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-			struct l2cap_conn_rsp rsp;
-			__u16 result;
-
-			if (bt_sk(sk)->defer_setup)
-				result = L2CAP_CR_SEC_BLOCK;
-			else
-				result = L2CAP_CR_BAD_PSM;
-			sk->sk_state = BT_DISCONN;
-
-			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
-			rsp.result = cpu_to_le16(result);
-			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-		} else
-			l2cap_chan_del(sk, reason);
-		break;
-
-	case BT_CONNECT:
-	case BT_DISCONN:
-		l2cap_chan_del(sk, reason);
-		break;
-
-	default:
-		sock_set_flag(sk, SOCK_ZAPPED);
-		break;
-	}
-}
-
-/* Must be called on unlocked socket. */
-static void l2cap_sock_close(struct sock *sk)
-{
-	l2cap_sock_clear_timer(sk);
-	lock_sock(sk);
-	__l2cap_sock_close(sk, ECONNRESET);
-	release_sock(sk);
-	l2cap_sock_kill(sk);
-}
-
-static void l2cap_sock_init(struct sock *sk, struct sock *parent)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p", sk);
-
-	if (parent) {
-		sk->sk_type = parent->sk_type;
-		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
-
-		pi->imtu = l2cap_pi(parent)->imtu;
-		pi->omtu = l2cap_pi(parent)->omtu;
-		pi->conf_state = l2cap_pi(parent)->conf_state;
-		pi->mode = l2cap_pi(parent)->mode;
-		pi->fcs  = l2cap_pi(parent)->fcs;
-		pi->max_tx = l2cap_pi(parent)->max_tx;
-		pi->tx_win = l2cap_pi(parent)->tx_win;
-		pi->sec_level = l2cap_pi(parent)->sec_level;
-		pi->role_switch = l2cap_pi(parent)->role_switch;
-		pi->force_reliable = l2cap_pi(parent)->force_reliable;
-	} else {
-		pi->imtu = L2CAP_DEFAULT_MTU;
-		pi->omtu = 0;
-		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
-			pi->mode = L2CAP_MODE_ERTM;
-			pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
-		} else {
-			pi->mode = L2CAP_MODE_BASIC;
-		}
-		pi->max_tx = L2CAP_DEFAULT_MAX_TX;
-		pi->fcs  = L2CAP_FCS_CRC16;
-		pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
-		pi->sec_level = BT_SECURITY_LOW;
-		pi->role_switch = 0;
-		pi->force_reliable = 0;
-	}
-
-	/* Default config options */
-	pi->conf_len = 0;
-	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
-	skb_queue_head_init(TX_QUEUE(sk));
-	skb_queue_head_init(SREJ_QUEUE(sk));
-	skb_queue_head_init(BUSY_QUEUE(sk));
-	INIT_LIST_HEAD(SREJ_LIST(sk));
-}
-
-static struct proto l2cap_proto = {
-	.name		= "L2CAP",
-	.owner		= THIS_MODULE,
-	.obj_size	= sizeof(struct l2cap_pinfo)
-};
-
-static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
-{
-	struct sock *sk;
-
-	sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
-	if (!sk)
-		return NULL;
-
-	sock_init_data(sock, sk);
-	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
-
-	sk->sk_destruct = l2cap_sock_destruct;
-	sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
-
-	sock_reset_flag(sk, SOCK_ZAPPED);
-
-	sk->sk_protocol = proto;
-	sk->sk_state = BT_OPEN;
-
-	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
-
-	bt_sock_link(&l2cap_sk_list, sk);
-	return sk;
-}
-
-static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
-			     int kern)
-{
-	struct sock *sk;
-
-	BT_DBG("sock %p", sock);
-
-	sock->state = SS_UNCONNECTED;
-
-	if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
-			sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
-		return -ESOCKTNOSUPPORT;
-
-	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
-		return -EPERM;
-
-	sock->ops = &l2cap_sock_ops;
-
-	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
-	if (!sk)
-		return -ENOMEM;
-
-	l2cap_sock_init(sk, NULL);
-	return 0;
-}
-
-static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_l2 la;
-	int len, err = 0;
-
-	BT_DBG("sk %p", sk);
-
-	if (!addr || addr->sa_family != AF_BLUETOOTH)
-		return -EINVAL;
-
-	memset(&la, 0, sizeof(la));
-	len = min_t(unsigned int, sizeof(la), alen);
-	memcpy(&la, addr, len);
-
-	if (la.l2_cid)
-		return -EINVAL;
-
-	lock_sock(sk);
-
-	if (sk->sk_state != BT_OPEN) {
-		err = -EBADFD;
-		goto done;
-	}
-
-	if (la.l2_psm) {
-		__u16 psm = __le16_to_cpu(la.l2_psm);
-
-		/* PSM must be odd and lsb of upper byte must be 0 */
-		if ((psm & 0x0101) != 0x0001) {
-			err = -EINVAL;
-			goto done;
-		}
-
-		/* Restrict usage of well-known PSMs */
-		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
-			err = -EACCES;
-			goto done;
-		}
-	}
-
-	write_lock_bh(&l2cap_sk_list.lock);
-
-	if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
-		err = -EADDRINUSE;
-	} else {
-		/* Save source address */
-		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
-		l2cap_pi(sk)->psm   = la.l2_psm;
-		l2cap_pi(sk)->sport = la.l2_psm;
-		sk->sk_state = BT_BOUND;
-
-		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
-					__le16_to_cpu(la.l2_psm) == 0x0003)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
-	}
-
-	write_unlock_bh(&l2cap_sk_list.lock);
-
-done:
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_do_connect(struct sock *sk)
-{
-	bdaddr_t *src = &bt_sk(sk)->src;
-	bdaddr_t *dst = &bt_sk(sk)->dst;
-	struct l2cap_conn *conn;
-	struct hci_conn *hcon;
-	struct hci_dev *hdev;
-	__u8 auth_type;
-	int err;
-
-	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
-							l2cap_pi(sk)->psm);
-
-	hdev = hci_get_route(dst, src);
-	if (!hdev)
-		return -EHOSTUNREACH;
-
-	hci_dev_lock_bh(hdev);
-
-	err = -ENOMEM;
-
-	auth_type = l2cap_get_auth_type(sk);
-
-	hcon = hci_connect(hdev, ACL_LINK, dst,
-					l2cap_pi(sk)->sec_level, auth_type);
-	if (!hcon)
-		goto done;
-
-	conn = l2cap_conn_add(hcon, 0);
-	if (!conn) {
-		hci_conn_put(hcon);
-		goto done;
-	}
-
-	err = 0;
-
-	/* Update source addr of the socket */
-	bacpy(src, conn->src);
-
-	l2cap_chan_add(conn, sk, NULL);
-
-	sk->sk_state = BT_CONNECT;
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-
-	if (hcon->state == BT_CONNECTED) {
-		if (sk->sk_type != SOCK_SEQPACKET &&
-				sk->sk_type != SOCK_STREAM) {
-			l2cap_sock_clear_timer(sk);
-			if (l2cap_check_security(sk))
-				sk->sk_state = BT_CONNECTED;
-		} else
-			l2cap_do_start(sk);
-	}
-
-done:
-	hci_dev_unlock_bh(hdev);
-	hci_dev_put(hdev);
-	return err;
-}
-
-static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_l2 la;
-	int len, err = 0;
-
-	BT_DBG("sk %p", sk);
-
-	if (!addr || alen < sizeof(addr->sa_family) ||
-	    addr->sa_family != AF_BLUETOOTH)
-		return -EINVAL;
-
-	memset(&la, 0, sizeof(la));
-	len = min_t(unsigned int, sizeof(la), alen);
-	memcpy(&la, addr, len);
-
-	if (la.l2_cid)
-		return -EINVAL;
-
-	lock_sock(sk);
-
-	if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
-			&& !la.l2_psm) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	switch (l2cap_pi(sk)->mode) {
-	case L2CAP_MODE_BASIC:
-		break;
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		if (!disable_ertm)
-			break;
-		/* fall through */
-	default:
-		err = -ENOTSUPP;
-		goto done;
-	}
-
-	switch (sk->sk_state) {
-	case BT_CONNECT:
-	case BT_CONNECT2:
-	case BT_CONFIG:
-		/* Already connecting */
-		goto wait;
-
-	case BT_CONNECTED:
-		/* Already connected */
-		err = -EISCONN;
-		goto done;
-
-	case BT_OPEN:
-	case BT_BOUND:
-		/* Can connect */
-		break;
-
-	default:
-		err = -EBADFD;
-		goto done;
-	}
-
-	/* PSM must be odd and lsb of upper byte must be 0 */
-	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
-		sk->sk_type != SOCK_RAW) {
-		err = -EINVAL;
-		goto done;
-	}
-
-	/* Set destination address and psm */
-	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
-	l2cap_pi(sk)->psm = la.l2_psm;
-
-	err = l2cap_do_connect(sk);
-	if (err)
-		goto done;
-
-wait:
-	err = bt_sock_wait_state(sk, BT_CONNECTED,
-			sock_sndtimeo(sk, flags & O_NONBLOCK));
-done:
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_listen(struct socket *sock, int backlog)
-{
-	struct sock *sk = sock->sk;
-	int err = 0;
-
-	BT_DBG("sk %p backlog %d", sk, backlog);
-
-	lock_sock(sk);
-
-	if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
-			|| sk->sk_state != BT_BOUND) {
-		err = -EBADFD;
-		goto done;
-	}
-
-	switch (l2cap_pi(sk)->mode) {
-	case L2CAP_MODE_BASIC:
-		break;
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		if (!disable_ertm)
-			break;
-		/* fall through */
-	default:
-		err = -ENOTSUPP;
-		goto done;
-	}
-
-	if (!l2cap_pi(sk)->psm) {
-		bdaddr_t *src = &bt_sk(sk)->src;
-		u16 psm;
-
-		err = -EINVAL;
-
-		write_lock_bh(&l2cap_sk_list.lock);
-
-		for (psm = 0x1001; psm < 0x1100; psm += 2)
-			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
-				l2cap_pi(sk)->psm   = cpu_to_le16(psm);
-				l2cap_pi(sk)->sport = cpu_to_le16(psm);
-				err = 0;
-				break;
-			}
-
-		write_unlock_bh(&l2cap_sk_list.lock);
-
-		if (err < 0)
-			goto done;
-	}
-
-	sk->sk_max_ack_backlog = backlog;
-	sk->sk_ack_backlog = 0;
-	sk->sk_state = BT_LISTEN;
-
-done:
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct sock *sk = sock->sk, *nsk;
-	long timeo;
-	int err = 0;
-
-	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
-
-	if (sk->sk_state != BT_LISTEN) {
-		err = -EBADFD;
-		goto done;
-	}
-
-	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
-
-	BT_DBG("sk %p timeo %ld", sk, timeo);
-
-	/* Wait for an incoming connection. (wake-one). */
-	add_wait_queue_exclusive(sk_sleep(sk), &wait);
-	while (!(nsk = bt_accept_dequeue(sk, newsock))) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!timeo) {
-			err = -EAGAIN;
-			break;
-		}
-
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
-
-		if (sk->sk_state != BT_LISTEN) {
-			err = -EBADFD;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			err = sock_intr_errno(timeo);
-			break;
-		}
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-
-	if (err)
-		goto done;
-
-	newsock->state = SS_CONNECTED;
-
-	BT_DBG("new socket %p", nsk);
-
-done:
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
-{
-	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
-	struct sock *sk = sock->sk;
-
-	BT_DBG("sock %p, sk %p", sock, sk);
-
-	addr->sa_family = AF_BLUETOOTH;
-	*len = sizeof(struct sockaddr_l2);
-
-	if (peer) {
-		la->l2_psm = l2cap_pi(sk)->psm;
-		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
-		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	} else {
-		la->l2_psm = l2cap_pi(sk)->sport;
-		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
-		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
-	}
-
-	return 0;
-}
-
-static int __l2cap_wait_ack(struct sock *sk)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int err = 0;
-	int timeo = HZ/5;
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (!timeo)
-			timeo = HZ/5;
-
-		if (signal_pending(current)) {
-			err = sock_intr_errno(timeo);
-			break;
-		}
-
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-
-		err = sock_error(sk);
-		if (err)
-			break;
-	}
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-	return err;
-}
-
-static void l2cap_monitor_timeout(unsigned long arg)
-{
-	struct sock *sk = (void *) arg;
-
-	BT_DBG("sk %p", sk);
-
-	bh_lock_sock(sk);
-	if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
-		l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
-		bh_unlock_sock(sk);
-		return;
-	}
-
-	l2cap_pi(sk)->retry_count++;
-	__mod_monitor_timer();
-
-	l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
-	bh_unlock_sock(sk);
-}
-
-static void l2cap_retrans_timeout(unsigned long arg)
-{
-	struct sock *sk = (void *) arg;
-
-	BT_DBG("sk %p", sk);
-
-	bh_lock_sock(sk);
-	l2cap_pi(sk)->retry_count = 1;
-	__mod_monitor_timer();
-
-	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
-
-	l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
-	bh_unlock_sock(sk);
-}
-
-static void l2cap_drop_acked_frames(struct sock *sk)
-{
-	struct sk_buff *skb;
-
-	while ((skb = skb_peek(TX_QUEUE(sk))) &&
-			l2cap_pi(sk)->unacked_frames) {
-		if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
-			break;
-
-		skb = skb_dequeue(TX_QUEUE(sk));
-		kfree_skb(skb);
-
-		l2cap_pi(sk)->unacked_frames--;
-	}
-
-	if (!l2cap_pi(sk)->unacked_frames)
-		del_timer(&l2cap_pi(sk)->retrans_timer);
-}
-
-static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
-
-	hci_send_acl(pi->conn->hcon, skb, 0);
-}
-
-static void l2cap_streaming_send(struct sock *sk)
-{
-	struct sk_buff *skb;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u16 control, fcs;
-
-	while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
-		control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
-		control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
-		put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
-
-		if (pi->fcs == L2CAP_FCS_CRC16) {
-			fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
-			put_unaligned_le16(fcs, skb->data + skb->len - 2);
-		}
-
-		l2cap_do_send(sk, skb);
-
-		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
-	}
-}
-
-static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *skb, *tx_skb;
-	u16 control, fcs;
-
-	skb = skb_peek(TX_QUEUE(sk));
-	if (!skb)
-		return;
-
-	do {
-		if (bt_cb(skb)->tx_seq == tx_seq)
-			break;
-
-		if (skb_queue_is_last(TX_QUEUE(sk), skb))
-			return;
-
-	} while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
-
-	if (pi->remote_max_tx &&
-			bt_cb(skb)->retries == pi->remote_max_tx) {
-		l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
-		return;
-	}
-
-	tx_skb = skb_clone(skb, GFP_ATOMIC);
-	bt_cb(skb)->retries++;
-	control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
-
-	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
-		control |= L2CAP_CTRL_FINAL;
-		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-	}
-
-	control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
-			| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
-
-	put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
-
-	if (pi->fcs == L2CAP_FCS_CRC16) {
-		fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
-		put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
-	}
-
-	l2cap_do_send(sk, tx_skb);
-}
-
-static int l2cap_ertm_send(struct sock *sk)
-{
-	struct sk_buff *skb, *tx_skb;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u16 control, fcs;
-	int nsent = 0;
-
-	if (sk->sk_state != BT_CONNECTED)
-		return -ENOTCONN;
-
-	while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
-
-		if (pi->remote_max_tx &&
-				bt_cb(skb)->retries == pi->remote_max_tx) {
-			l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
-			break;
-		}
-
-		tx_skb = skb_clone(skb, GFP_ATOMIC);
-
-		bt_cb(skb)->retries++;
-
-		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
-		control &= L2CAP_CTRL_SAR;
-
-		if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
-			control |= L2CAP_CTRL_FINAL;
-			pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-		}
-		control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
-				| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
-		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
-
-
-		if (pi->fcs == L2CAP_FCS_CRC16) {
-			fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
-			put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
-		}
-
-		l2cap_do_send(sk, tx_skb);
-
-		__mod_retrans_timer();
-
-		bt_cb(skb)->tx_seq = pi->next_tx_seq;
-		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
-
-		pi->unacked_frames++;
-		pi->frames_sent++;
-
-		if (skb_queue_is_last(TX_QUEUE(sk), skb))
-			sk->sk_send_head = NULL;
-		else
-			sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
-
-		nsent++;
-	}
-
-	return nsent;
-}
-
-static int l2cap_retransmit_frames(struct sock *sk)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	int ret;
-
-	if (!skb_queue_empty(TX_QUEUE(sk)))
-		sk->sk_send_head = TX_QUEUE(sk)->next;
-
-	pi->next_tx_seq = pi->expected_ack_seq;
-	ret = l2cap_ertm_send(sk);
-	return ret;
-}
-
-static void l2cap_send_ack(struct l2cap_pinfo *pi)
-{
-	struct sock *sk = (struct sock *)pi;
-	u16 control = 0;
-
-	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-
-	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
-		control |= L2CAP_SUPER_RCV_NOT_READY;
-		pi->conn_state |= L2CAP_CONN_RNR_SENT;
-		l2cap_send_sframe(pi, control);
-		return;
-	}
-
-	if (l2cap_ertm_send(sk) > 0)
-		return;
-
-	control |= L2CAP_SUPER_RCV_READY;
-	l2cap_send_sframe(pi, control);
-}
-
-static void l2cap_send_srejtail(struct sock *sk)
-{
-	struct srej_list *tail;
-	u16 control;
-
-	control = L2CAP_SUPER_SELECT_REJECT;
-	control |= L2CAP_CTRL_FINAL;
-
-	tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
-	control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-
-	l2cap_send_sframe(l2cap_pi(sk), control);
-}
-
-static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff **frag;
-	int err, sent = 0;
-
-	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
-		return -EFAULT;
-
-	sent += count;
-	len  -= count;
-
-	/* Continuation fragments (no L2CAP header) */
-	frag = &skb_shinfo(skb)->frag_list;
-	while (len) {
-		count = min_t(unsigned int, conn->mtu, len);
-
-		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
-		if (!*frag)
-			return err;
-		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
-			return -EFAULT;
-
-		sent += count;
-		len  -= count;
-
-		frag = &(*frag)->next;
-	}
-
-	return sent;
-}
-
-static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb;
-	int err, count, hlen = L2CAP_HDR_SIZE + 2;
-	struct l2cap_hdr *lh;
-
-	BT_DBG("sk %p len %d", sk, (int)len);
-
-	count = min_t(unsigned int, (conn->mtu - hlen), len);
-	skb = bt_skb_send_alloc(sk, count + hlen,
-			msg->msg_flags & MSG_DONTWAIT, &err);
-	if (!skb)
-		return ERR_PTR(err);
-
-	/* Create L2CAP header */
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
-	put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
-
-	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
-	if (unlikely(err < 0)) {
-		kfree_skb(skb);
-		return ERR_PTR(err);
-	}
-	return skb;
-}
-
-static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb;
-	int err, count, hlen = L2CAP_HDR_SIZE;
-	struct l2cap_hdr *lh;
-
-	BT_DBG("sk %p len %d", sk, (int)len);
-
-	count = min_t(unsigned int, (conn->mtu - hlen), len);
-	skb = bt_skb_send_alloc(sk, count + hlen,
-			msg->msg_flags & MSG_DONTWAIT, &err);
-	if (!skb)
-		return ERR_PTR(err);
-
-	/* Create L2CAP header */
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
-
-	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
-	if (unlikely(err < 0)) {
-		kfree_skb(skb);
-		return ERR_PTR(err);
-	}
-	return skb;
-}
-
-static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
-{
-	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-	struct sk_buff *skb;
-	int err, count, hlen = L2CAP_HDR_SIZE + 2;
-	struct l2cap_hdr *lh;
-
-	BT_DBG("sk %p len %d", sk, (int)len);
-
-	if (!conn)
-		return ERR_PTR(-ENOTCONN);
-
-	if (sdulen)
-		hlen += 2;
-
-	if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
-		hlen += 2;
-
-	count = min_t(unsigned int, (conn->mtu - hlen), len);
-	skb = bt_skb_send_alloc(sk, count + hlen,
-			msg->msg_flags & MSG_DONTWAIT, &err);
-	if (!skb)
-		return ERR_PTR(err);
-
-	/* Create L2CAP header */
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
-	put_unaligned_le16(control, skb_put(skb, 2));
-	if (sdulen)
-		put_unaligned_le16(sdulen, skb_put(skb, 2));
-
-	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
-	if (unlikely(err < 0)) {
-		kfree_skb(skb);
-		return ERR_PTR(err);
-	}
-
-	if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
-		put_unaligned_le16(0, skb_put(skb, 2));
-
-	bt_cb(skb)->retries = 0;
-	return skb;
-}
-
-static inline int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *skb;
-	struct sk_buff_head sar_queue;
-	u16 control;
-	size_t size = 0;
-
-	skb_queue_head_init(&sar_queue);
-	control = L2CAP_SDU_START;
-	skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
-	if (IS_ERR(skb))
-		return PTR_ERR(skb);
-
-	__skb_queue_tail(&sar_queue, skb);
-	len -= pi->remote_mps;
-	size += pi->remote_mps;
-
-	while (len > 0) {
-		size_t buflen;
-
-		if (len > pi->remote_mps) {
-			control = L2CAP_SDU_CONTINUE;
-			buflen = pi->remote_mps;
-		} else {
-			control = L2CAP_SDU_END;
-			buflen = len;
-		}
-
-		skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
-		if (IS_ERR(skb)) {
-			skb_queue_purge(&sar_queue);
-			return PTR_ERR(skb);
-		}
-
-		__skb_queue_tail(&sar_queue, skb);
-		len -= buflen;
-		size += buflen;
-	}
-	skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
-	if (sk->sk_send_head == NULL)
-		sk->sk_send_head = sar_queue.next;
-
-	return size;
-}
-
-static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
-{
-	struct sock *sk = sock->sk;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *skb;
-	u16 control;
-	int err;
-
-	BT_DBG("sock %p, sk %p", sock, sk);
-
-	err = sock_error(sk);
-	if (err)
-		return err;
-
-	if (msg->msg_flags & MSG_OOB)
-		return -EOPNOTSUPP;
-
-	lock_sock(sk);
-
-	if (sk->sk_state != BT_CONNECTED) {
-		err = -ENOTCONN;
-		goto done;
-	}
-
-	/* Connectionless channel */
-	if (sk->sk_type == SOCK_DGRAM) {
-		skb = l2cap_create_connless_pdu(sk, msg, len);
-		if (IS_ERR(skb)) {
-			err = PTR_ERR(skb);
-		} else {
-			l2cap_do_send(sk, skb);
-			err = len;
-		}
-		goto done;
-	}
-
-	switch (pi->mode) {
-	case L2CAP_MODE_BASIC:
-		/* Check outgoing MTU */
-		if (len > pi->omtu) {
-			err = -EMSGSIZE;
-			goto done;
-		}
-
-		/* Create a basic PDU */
-		skb = l2cap_create_basic_pdu(sk, msg, len);
-		if (IS_ERR(skb)) {
-			err = PTR_ERR(skb);
-			goto done;
-		}
-
-		l2cap_do_send(sk, skb);
-		err = len;
-		break;
-
-	case L2CAP_MODE_ERTM:
-	case L2CAP_MODE_STREAMING:
-		/* Entire SDU fits into one PDU */
-		if (len <= pi->remote_mps) {
-			control = L2CAP_SDU_UNSEGMENTED;
-			skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
-			if (IS_ERR(skb)) {
-				err = PTR_ERR(skb);
-				goto done;
-			}
-			__skb_queue_tail(TX_QUEUE(sk), skb);
-
-			if (sk->sk_send_head == NULL)
-				sk->sk_send_head = skb;
-
-		} else {
-		/* Segment SDU into multiples PDUs */
-			err = l2cap_sar_segment_sdu(sk, msg, len);
-			if (err < 0)
-				goto done;
-		}
-
-		if (pi->mode == L2CAP_MODE_STREAMING) {
-			l2cap_streaming_send(sk);
-		} else {
-			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-					(pi->conn_state & L2CAP_CONN_WAIT_F)) {
-				err = len;
-				break;
-			}
-			err = l2cap_ertm_send(sk);
-		}
-
-		if (err >= 0)
-			err = len;
-		break;
-
-	default:
-		BT_DBG("bad state %1.1x", pi->mode);
-		err = -EBADFD;
-	}
-
-done:
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
-{
-	struct sock *sk = sock->sk;
-
-	lock_sock(sk);
-
-	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
-		struct l2cap_conn_rsp rsp;
-		struct l2cap_conn *conn = l2cap_pi(sk)->conn;
-		u8 buf[128];
-
-		sk->sk_state = BT_CONFIG;
-
-		rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-		rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
-		rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
-		rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-		l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-
-		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
-			release_sock(sk);
-			return 0;
-		}
-
-		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-				l2cap_build_conf_req(sk, buf), buf);
-		l2cap_pi(sk)->num_conf_req++;
-
-		release_sock(sk);
-		return 0;
-	}
-
-	release_sock(sk);
-
-	if (sock->type == SOCK_STREAM)
-		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
-
-	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
-}
-
-static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
-{
-	struct sock *sk = sock->sk;
-	struct l2cap_options opts;
-	int len, err = 0;
-	u32 opt;
-
-	BT_DBG("sk %p", sk);
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case L2CAP_OPTIONS:
-		if (sk->sk_state == BT_CONNECTED) {
-			err = -EINVAL;
-			break;
-		}
-
-		opts.imtu     = l2cap_pi(sk)->imtu;
-		opts.omtu     = l2cap_pi(sk)->omtu;
-		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
-		opts.fcs      = l2cap_pi(sk)->fcs;
-		opts.max_tx   = l2cap_pi(sk)->max_tx;
-		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
-
-		len = min_t(unsigned int, sizeof(opts), optlen);
-		if (copy_from_user((char *) &opts, optval, len)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
-			err = -EINVAL;
-			break;
-		}
-
-		l2cap_pi(sk)->mode = opts.mode;
-		switch (l2cap_pi(sk)->mode) {
-		case L2CAP_MODE_BASIC:
-			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
-			break;
-		case L2CAP_MODE_ERTM:
-		case L2CAP_MODE_STREAMING:
-			if (!disable_ertm)
-				break;
-			/* fall through */
-		default:
-			err = -EINVAL;
-			break;
-		}
-
-		l2cap_pi(sk)->imtu = opts.imtu;
-		l2cap_pi(sk)->omtu = opts.omtu;
-		l2cap_pi(sk)->fcs  = opts.fcs;
-		l2cap_pi(sk)->max_tx = opts.max_tx;
-		l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
-		break;
-
-	case L2CAP_LM:
-		if (get_user(opt, (u32 __user *) optval)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (opt & L2CAP_LM_AUTH)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
-		if (opt & L2CAP_LM_ENCRYPT)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
-		if (opt & L2CAP_LM_SECURE)
-			l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
-
-		l2cap_pi(sk)->role_switch    = (opt & L2CAP_LM_MASTER);
-		l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
-{
-	struct sock *sk = sock->sk;
-	struct bt_security sec;
-	int len, err = 0;
-	u32 opt;
-
-	BT_DBG("sk %p", sk);
-
-	if (level == SOL_L2CAP)
-		return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
-
-	if (level != SOL_BLUETOOTH)
-		return -ENOPROTOOPT;
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case BT_SECURITY:
-		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-				&& sk->sk_type != SOCK_RAW) {
-			err = -EINVAL;
-			break;
-		}
-
-		sec.level = BT_SECURITY_LOW;
-
-		len = min_t(unsigned int, sizeof(sec), optlen);
-		if (copy_from_user((char *) &sec, optval, len)) {
-			err = -EFAULT;
-			break;
-		}
-
-		if (sec.level < BT_SECURITY_LOW ||
-					sec.level > BT_SECURITY_HIGH) {
-			err = -EINVAL;
-			break;
-		}
-
-		l2cap_pi(sk)->sec_level = sec.level;
-		break;
-
-	case BT_DEFER_SETUP:
-		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
-			err = -EINVAL;
-			break;
-		}
-
-		if (get_user(opt, (u32 __user *) optval)) {
-			err = -EFAULT;
-			break;
-		}
-
-		bt_sk(sk)->defer_setup = opt;
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
-{
-	struct sock *sk = sock->sk;
-	struct l2cap_options opts;
-	struct l2cap_conninfo cinfo;
-	int len, err = 0;
-	u32 opt;
-
-	BT_DBG("sk %p", sk);
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case L2CAP_OPTIONS:
-		opts.imtu     = l2cap_pi(sk)->imtu;
-		opts.omtu     = l2cap_pi(sk)->omtu;
-		opts.flush_to = l2cap_pi(sk)->flush_to;
-		opts.mode     = l2cap_pi(sk)->mode;
-		opts.fcs      = l2cap_pi(sk)->fcs;
-		opts.max_tx   = l2cap_pi(sk)->max_tx;
-		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
-
-		len = min_t(unsigned int, len, sizeof(opts));
-		if (copy_to_user(optval, (char *) &opts, len))
-			err = -EFAULT;
-
-		break;
-
-	case L2CAP_LM:
-		switch (l2cap_pi(sk)->sec_level) {
-		case BT_SECURITY_LOW:
-			opt = L2CAP_LM_AUTH;
-			break;
-		case BT_SECURITY_MEDIUM:
-			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
-			break;
-		case BT_SECURITY_HIGH:
-			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
-							L2CAP_LM_SECURE;
-			break;
-		default:
-			opt = 0;
-			break;
-		}
-
-		if (l2cap_pi(sk)->role_switch)
-			opt |= L2CAP_LM_MASTER;
-
-		if (l2cap_pi(sk)->force_reliable)
-			opt |= L2CAP_LM_RELIABLE;
-
-		if (put_user(opt, (u32 __user *) optval))
-			err = -EFAULT;
-		break;
-
-	case L2CAP_CONNINFO:
-		if (sk->sk_state != BT_CONNECTED &&
-					!(sk->sk_state == BT_CONNECT2 &&
-						bt_sk(sk)->defer_setup)) {
-			err = -ENOTCONN;
-			break;
-		}
-
-		cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
-		memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
-
-		len = min_t(unsigned int, len, sizeof(cinfo));
-		if (copy_to_user(optval, (char *) &cinfo, len))
-			err = -EFAULT;
-
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
-{
-	struct sock *sk = sock->sk;
-	struct bt_security sec;
-	int len, err = 0;
-
-	BT_DBG("sk %p", sk);
-
-	if (level == SOL_L2CAP)
-		return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
-
-	if (level != SOL_BLUETOOTH)
-		return -ENOPROTOOPT;
-
-	if (get_user(len, optlen))
-		return -EFAULT;
-
-	lock_sock(sk);
-
-	switch (optname) {
-	case BT_SECURITY:
-		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-				&& sk->sk_type != SOCK_RAW) {
-			err = -EINVAL;
-			break;
-		}
-
-		sec.level = l2cap_pi(sk)->sec_level;
-
-		len = min_t(unsigned int, len, sizeof(sec));
-		if (copy_to_user(optval, (char *) &sec, len))
-			err = -EFAULT;
-
-		break;
-
-	case BT_DEFER_SETUP:
-		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
-			err = -EINVAL;
-			break;
-		}
-
-		if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
-			err = -EFAULT;
-
-		break;
-
-	default:
-		err = -ENOPROTOOPT;
-		break;
-	}
-
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_shutdown(struct socket *sock, int how)
-{
-	struct sock *sk = sock->sk;
-	int err = 0;
-
-	BT_DBG("sock %p, sk %p", sock, sk);
-
-	if (!sk)
-		return 0;
-
-	lock_sock(sk);
-	if (!sk->sk_shutdown) {
-		if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
-			err = __l2cap_wait_ack(sk);
-
-		sk->sk_shutdown = SHUTDOWN_MASK;
-		l2cap_sock_clear_timer(sk);
-		__l2cap_sock_close(sk, 0);
-
-		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
-			err = bt_sock_wait_state(sk, BT_CLOSED,
-							sk->sk_lingertime);
-	}
-
-	if (!err && sk->sk_err)
-		err = -sk->sk_err;
-
-	release_sock(sk);
-	return err;
-}
-
-static int l2cap_sock_release(struct socket *sock)
-{
-	struct sock *sk = sock->sk;
-	int err;
-
-	BT_DBG("sock %p, sk %p", sock, sk);
-
-	if (!sk)
-		return 0;
-
-	err = l2cap_sock_shutdown(sock, 2);
-
-	sock_orphan(sk);
-	l2cap_sock_kill(sk);
-	return err;
-}
-
-static void l2cap_chan_ready(struct sock *sk)
-{
-	struct sock *parent = bt_sk(sk)->parent;
-
-	BT_DBG("sk %p, parent %p", sk, parent);
-
-	l2cap_pi(sk)->conf_state = 0;
-	l2cap_sock_clear_timer(sk);
-
-	if (!parent) {
-		/* Outgoing channel.
-		 * Wake up socket sleeping on connect.
-		 */
-		sk->sk_state = BT_CONNECTED;
-		sk->sk_state_change(sk);
-	} else {
-		/* Incoming channel.
-		 * Wake up socket sleeping on accept.
-		 */
-		parent->sk_data_ready(parent, 0);
-	}
-}
-
-/* Copy frame to all raw sockets on that connection */
-static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
-{
-	struct l2cap_chan_list *l = &conn->chan_list;
-	struct sk_buff *nskb;
-	struct sock *sk;
-
-	BT_DBG("conn %p", conn);
-
-	read_lock(&l->lock);
-	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
-		if (sk->sk_type != SOCK_RAW)
-			continue;
-
-		/* Don't send frame to the socket it came from */
-		if (skb->sk == sk)
-			continue;
-		nskb = skb_clone(skb, GFP_ATOMIC);
-		if (!nskb)
-			continue;
-
-		if (sock_queue_rcv_skb(sk, nskb))
-			kfree_skb(nskb);
-	}
-	read_unlock(&l->lock);
-}
-
-/* ---- L2CAP signalling commands ---- */
-static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
-				u8 code, u8 ident, u16 dlen, void *data)
-{
-	struct sk_buff *skb, **frag;
-	struct l2cap_cmd_hdr *cmd;
-	struct l2cap_hdr *lh;
-	int len, count;
-
-	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
-			conn, code, ident, dlen);
-
-	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
-	count = min_t(unsigned int, conn->mtu, len);
-
-	skb = bt_skb_alloc(count, GFP_ATOMIC);
-	if (!skb)
-		return NULL;
-
-	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
-	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
-	lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
-
-	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
-	cmd->code  = code;
-	cmd->ident = ident;
-	cmd->len   = cpu_to_le16(dlen);
-
-	if (dlen) {
-		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
-		memcpy(skb_put(skb, count), data, count);
-		data += count;
-	}
-
-	len -= skb->len;
-
-	/* Continuation fragments (no L2CAP header) */
-	frag = &skb_shinfo(skb)->frag_list;
-	while (len) {
-		count = min_t(unsigned int, conn->mtu, len);
-
-		*frag = bt_skb_alloc(count, GFP_ATOMIC);
-		if (!*frag)
-			goto fail;
-
-		memcpy(skb_put(*frag, count), data, count);
-
-		len  -= count;
-		data += count;
-
-		frag = &(*frag)->next;
-	}
-
-	return skb;
-
-fail:
-	kfree_skb(skb);
-	return NULL;
-}
-
-static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
-{
-	struct l2cap_conf_opt *opt = *ptr;
-	int len;
-
-	len = L2CAP_CONF_OPT_SIZE + opt->len;
-	*ptr += len;
-
-	*type = opt->type;
-	*olen = opt->len;
-
-	switch (opt->len) {
-	case 1:
-		*val = *((u8 *) opt->val);
-		break;
-
-	case 2:
-		*val = get_unaligned_le16(opt->val);
-		break;
-
-	case 4:
-		*val = get_unaligned_le32(opt->val);
-		break;
-
-	default:
-		*val = (unsigned long) opt->val;
-		break;
-	}
-
-	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
-	return len;
-}
-
-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
-{
-	struct l2cap_conf_opt *opt = *ptr;
-
-	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
-
-	opt->type = type;
-	opt->len  = len;
-
-	switch (len) {
-	case 1:
-		*((u8 *) opt->val)  = val;
-		break;
-
-	case 2:
-		put_unaligned_le16(val, opt->val);
-		break;
-
-	case 4:
-		put_unaligned_le32(val, opt->val);
-		break;
-
-	default:
-		memcpy(opt->val, (void *) val, len);
-		break;
-	}
-
-	*ptr += L2CAP_CONF_OPT_SIZE + len;
-}
-
-static void l2cap_ack_timeout(unsigned long arg)
-{
-	struct sock *sk = (void *) arg;
-
-	bh_lock_sock(sk);
-	l2cap_send_ack(l2cap_pi(sk));
-	bh_unlock_sock(sk);
-}
-
-static inline void l2cap_ertm_init(struct sock *sk)
-{
-	l2cap_pi(sk)->expected_ack_seq = 0;
-	l2cap_pi(sk)->unacked_frames = 0;
-	l2cap_pi(sk)->buffer_seq = 0;
-	l2cap_pi(sk)->num_acked = 0;
-	l2cap_pi(sk)->frames_sent = 0;
-
-	setup_timer(&l2cap_pi(sk)->retrans_timer,
-			l2cap_retrans_timeout, (unsigned long) sk);
-	setup_timer(&l2cap_pi(sk)->monitor_timer,
-			l2cap_monitor_timeout, (unsigned long) sk);
-	setup_timer(&l2cap_pi(sk)->ack_timer,
-			l2cap_ack_timeout, (unsigned long) sk);
-
-	__skb_queue_head_init(SREJ_QUEUE(sk));
-	__skb_queue_head_init(BUSY_QUEUE(sk));
-
-	INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
-
-	sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
-}
-
-static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
-{
-	switch (mode) {
-	case L2CAP_MODE_STREAMING:
-	case L2CAP_MODE_ERTM:
-		if (l2cap_mode_supported(mode, remote_feat_mask))
-			return mode;
-		/* fall through */
-	default:
-		return L2CAP_MODE_BASIC;
-	}
-}
-
-static int l2cap_build_conf_req(struct sock *sk, void *data)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct l2cap_conf_req *req = data;
-	struct l2cap_conf_rfc rfc = { .mode = pi->mode };
-	void *ptr = req->data;
-
-	BT_DBG("sk %p", sk);
-
-	if (pi->num_conf_req || pi->num_conf_rsp)
-		goto done;
-
-	switch (pi->mode) {
-	case L2CAP_MODE_STREAMING:
-	case L2CAP_MODE_ERTM:
-		if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
-			break;
-
-		/* fall through */
-	default:
-		pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
-		break;
-	}
-
-done:
-	switch (pi->mode) {
-	case L2CAP_MODE_BASIC:
-		if (pi->imtu != L2CAP_DEFAULT_MTU)
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
-
-		if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
-				!(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
-			break;
-
-		rfc.mode            = L2CAP_MODE_BASIC;
-		rfc.txwin_size      = 0;
-		rfc.max_transmit    = 0;
-		rfc.retrans_timeout = 0;
-		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = 0;
-
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-							(unsigned long) &rfc);
-		break;
-
-	case L2CAP_MODE_ERTM:
-		rfc.mode            = L2CAP_MODE_ERTM;
-		rfc.txwin_size      = pi->tx_win;
-		rfc.max_transmit    = pi->max_tx;
-		rfc.retrans_timeout = 0;
-		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
-		if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
-			rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
-
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-							(unsigned long) &rfc);
-
-		if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
-			break;
-
-		if (pi->fcs == L2CAP_FCS_NONE ||
-				pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
-			pi->fcs = L2CAP_FCS_NONE;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
-		}
-		break;
-
-	case L2CAP_MODE_STREAMING:
-		rfc.mode            = L2CAP_MODE_STREAMING;
-		rfc.txwin_size      = 0;
-		rfc.max_transmit    = 0;
-		rfc.retrans_timeout = 0;
-		rfc.monitor_timeout = 0;
-		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
-		if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
-			rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
-
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-							(unsigned long) &rfc);
-
-		if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
-			break;
-
-		if (pi->fcs == L2CAP_FCS_NONE ||
-				pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
-			pi->fcs = L2CAP_FCS_NONE;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
-		}
-		break;
-	}
-
-	/* FIXME: Need actual value of the flush timeout */
-	//if (flush_to != L2CAP_DEFAULT_FLUSH_TO)
-	//   l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, pi->flush_to);
-
-	req->dcid  = cpu_to_le16(pi->dcid);
-	req->flags = cpu_to_le16(0);
-
-	return ptr - data;
-}
-
-static int l2cap_parse_conf_req(struct sock *sk, void *data)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct l2cap_conf_rsp *rsp = data;
-	void *ptr = rsp->data;
-	void *req = pi->conf_req;
-	int len = pi->conf_len;
-	int type, hint, olen;
-	unsigned long val;
-	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
-	u16 mtu = L2CAP_DEFAULT_MTU;
-	u16 result = L2CAP_CONF_SUCCESS;
-
-	BT_DBG("sk %p", sk);
-
-	while (len >= L2CAP_CONF_OPT_SIZE) {
-		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
-
-		hint  = type & L2CAP_CONF_HINT;
-		type &= L2CAP_CONF_MASK;
-
-		switch (type) {
-		case L2CAP_CONF_MTU:
-			mtu = val;
-			break;
-
-		case L2CAP_CONF_FLUSH_TO:
-			pi->flush_to = val;
-			break;
-
-		case L2CAP_CONF_QOS:
-			break;
-
-		case L2CAP_CONF_RFC:
-			if (olen == sizeof(rfc))
-				memcpy(&rfc, (void *) val, olen);
-			break;
-
-		case L2CAP_CONF_FCS:
-			if (val == L2CAP_FCS_NONE)
-				pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
-
-			break;
-
-		default:
-			if (hint)
-				break;
-
-			result = L2CAP_CONF_UNKNOWN;
-			*((u8 *) ptr++) = type;
-			break;
-		}
-	}
-
-	if (pi->num_conf_rsp || pi->num_conf_req > 1)
-		goto done;
-
-	switch (pi->mode) {
-	case L2CAP_MODE_STREAMING:
-	case L2CAP_MODE_ERTM:
-		if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
-			pi->mode = l2cap_select_mode(rfc.mode,
-					pi->conn->feat_mask);
-			break;
-		}
-
-		if (pi->mode != rfc.mode)
-			return -ECONNREFUSED;
-
-		break;
-	}
-
-done:
-	if (pi->mode != rfc.mode) {
-		result = L2CAP_CONF_UNACCEPT;
-		rfc.mode = pi->mode;
-
-		if (pi->num_conf_rsp == 1)
-			return -ECONNREFUSED;
-
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-					sizeof(rfc), (unsigned long) &rfc);
-	}
-
-
-	if (result == L2CAP_CONF_SUCCESS) {
-		/* Configure output options and let the other side know
-		 * which ones we don't like. */
-
-		if (mtu < L2CAP_DEFAULT_MIN_MTU)
-			result = L2CAP_CONF_UNACCEPT;
-		else {
-			pi->omtu = mtu;
-			pi->conf_state |= L2CAP_CONF_MTU_DONE;
-		}
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
-
-		switch (rfc.mode) {
-		case L2CAP_MODE_BASIC:
-			pi->fcs = L2CAP_FCS_NONE;
-			pi->conf_state |= L2CAP_CONF_MODE_DONE;
-			break;
-
-		case L2CAP_MODE_ERTM:
-			pi->remote_tx_win = rfc.txwin_size;
-			pi->remote_max_tx = rfc.max_transmit;
-
-			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
-				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
-
-			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
-
-			rfc.retrans_timeout =
-				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
-			rfc.monitor_timeout =
-				le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
-
-			pi->conf_state |= L2CAP_CONF_MODE_DONE;
-
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-					sizeof(rfc), (unsigned long) &rfc);
-
-			break;
-
-		case L2CAP_MODE_STREAMING:
-			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
-				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
-
-			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
-
-			pi->conf_state |= L2CAP_CONF_MODE_DONE;
-
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-					sizeof(rfc), (unsigned long) &rfc);
-
-			break;
-
-		default:
-			result = L2CAP_CONF_UNACCEPT;
-
-			memset(&rfc, 0, sizeof(rfc));
-			rfc.mode = pi->mode;
-		}
-
-		if (result == L2CAP_CONF_SUCCESS)
-			pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
-	}
-	rsp->scid   = cpu_to_le16(pi->dcid);
-	rsp->result = cpu_to_le16(result);
-	rsp->flags  = cpu_to_le16(0x0000);
-
-	return ptr - data;
-}
-
-static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct l2cap_conf_req *req = data;
-	void *ptr = req->data;
-	int type, olen;
-	unsigned long val;
-	struct l2cap_conf_rfc rfc;
-
-	BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
-
-	while (len >= L2CAP_CONF_OPT_SIZE) {
-		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
-
-		switch (type) {
-		case L2CAP_CONF_MTU:
-			if (val < L2CAP_DEFAULT_MIN_MTU) {
-				*result = L2CAP_CONF_UNACCEPT;
-				pi->imtu = L2CAP_DEFAULT_MIN_MTU;
-			} else
-				pi->imtu = val;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
-			break;
-
-		case L2CAP_CONF_FLUSH_TO:
-			pi->flush_to = val;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
-							2, pi->flush_to);
-			break;
-
-		case L2CAP_CONF_RFC:
-			if (olen == sizeof(rfc))
-				memcpy(&rfc, (void *)val, olen);
-
-			if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
-							rfc.mode != pi->mode)
-				return -ECONNREFUSED;
-
-			pi->fcs = 0;
-
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-					sizeof(rfc), (unsigned long) &rfc);
-			break;
-		}
-	}
-
-	if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
-		return -ECONNREFUSED;
-
-	pi->mode = rfc.mode;
-
-	if (*result == L2CAP_CONF_SUCCESS) {
-		switch (rfc.mode) {
-		case L2CAP_MODE_ERTM:
-			pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
-			pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
-			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
-			break;
-		case L2CAP_MODE_STREAMING:
-			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
-		}
-	}
-
-	req->dcid   = cpu_to_le16(pi->dcid);
-	req->flags  = cpu_to_le16(0x0000);
-
-	return ptr - data;
-}
-
-static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
-{
-	struct l2cap_conf_rsp *rsp = data;
-	void *ptr = rsp->data;
-
-	BT_DBG("sk %p", sk);
-
-	rsp->scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-	rsp->result = cpu_to_le16(result);
-	rsp->flags  = cpu_to_le16(flags);
-
-	return ptr - data;
-}
-
-static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	int type, olen;
-	unsigned long val;
-	struct l2cap_conf_rfc rfc;
-
-	BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
-
-	if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
-		return;
-
-	while (len >= L2CAP_CONF_OPT_SIZE) {
-		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
-
-		switch (type) {
-		case L2CAP_CONF_RFC:
-			if (olen == sizeof(rfc))
-				memcpy(&rfc, (void *)val, olen);
-			goto done;
-		}
-	}
-
-done:
-	switch (rfc.mode) {
-	case L2CAP_MODE_ERTM:
-		pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
-		pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
-		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
-		break;
-	case L2CAP_MODE_STREAMING:
-		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
-	}
-}
-
-static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
-
-	if (rej->reason != 0x0000)
-		return 0;
-
-	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
-					cmd->ident == conn->info_ident) {
-		del_timer(&conn->info_timer);
-
-		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
-		conn->info_ident = 0;
-
-		l2cap_conn_start(conn);
-	}
-
-	return 0;
-}
-
-static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_chan_list *list = &conn->chan_list;
-	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
-	struct l2cap_conn_rsp rsp;
-	struct sock *parent, *sk = NULL;
-	int result, status = L2CAP_CS_NO_INFO;
-
-	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
-	__le16 psm = req->psm;
-
-	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
-
-	/* Check if we have socket listening on psm */
-	parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
-	if (!parent) {
-		result = L2CAP_CR_BAD_PSM;
-		goto sendresp;
-	}
-
-	bh_lock_sock(parent);
-
-	/* Check if the ACL is secure enough (if not SDP) */
-	if (psm != cpu_to_le16(0x0001) &&
-				!hci_conn_check_link_mode(conn->hcon)) {
-		conn->disc_reason = 0x05;
-		result = L2CAP_CR_SEC_BLOCK;
-		goto response;
-	}
-
-	result = L2CAP_CR_NO_MEM;
-
-	/* Check for backlog size */
-	if (sk_acceptq_is_full(parent)) {
-		BT_DBG("backlog full %d", parent->sk_ack_backlog);
-		goto response;
-	}
-
-	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-	if (!sk)
-		goto response;
-
-	write_lock_bh(&list->lock);
-
-	/* Check if we already have channel with that dcid */
-	if (__l2cap_get_chan_by_dcid(list, scid)) {
-		write_unlock_bh(&list->lock);
-		sock_set_flag(sk, SOCK_ZAPPED);
-		l2cap_sock_kill(sk);
-		goto response;
-	}
-
-	hci_conn_hold(conn->hcon);
-
-	l2cap_sock_init(sk, parent);
-	bacpy(&bt_sk(sk)->src, conn->src);
-	bacpy(&bt_sk(sk)->dst, conn->dst);
-	l2cap_pi(sk)->psm  = psm;
-	l2cap_pi(sk)->dcid = scid;
-
-	__l2cap_chan_add(conn, sk, parent);
-	dcid = l2cap_pi(sk)->scid;
-
-	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-
-	l2cap_pi(sk)->ident = cmd->ident;
-
-	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
-		if (l2cap_check_security(sk)) {
-			if (bt_sk(sk)->defer_setup) {
-				sk->sk_state = BT_CONNECT2;
-				result = L2CAP_CR_PEND;
-				status = L2CAP_CS_AUTHOR_PEND;
-				parent->sk_data_ready(parent, 0);
-			} else {
-				sk->sk_state = BT_CONFIG;
-				result = L2CAP_CR_SUCCESS;
-				status = L2CAP_CS_NO_INFO;
-			}
-		} else {
-			sk->sk_state = BT_CONNECT2;
-			result = L2CAP_CR_PEND;
-			status = L2CAP_CS_AUTHEN_PEND;
-		}
-	} else {
-		sk->sk_state = BT_CONNECT2;
-		result = L2CAP_CR_PEND;
-		status = L2CAP_CS_NO_INFO;
-	}
-
-	write_unlock_bh(&list->lock);
-
-response:
-	bh_unlock_sock(parent);
-
-sendresp:
-	rsp.scid   = cpu_to_le16(scid);
-	rsp.dcid   = cpu_to_le16(dcid);
-	rsp.result = cpu_to_le16(result);
-	rsp.status = cpu_to_le16(status);
-	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-
-	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
-		struct l2cap_info_req info;
-		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
-
-		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
-		conn->info_ident = l2cap_get_ident(conn);
-
-		mod_timer(&conn->info_timer, jiffies +
-					msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
-
-		l2cap_send_cmd(conn, conn->info_ident,
-					L2CAP_INFO_REQ, sizeof(info), &info);
-	}
-
-	if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
-				result == L2CAP_CR_SUCCESS) {
-		u8 buf[128];
-		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-					l2cap_build_conf_req(sk, buf), buf);
-		l2cap_pi(sk)->num_conf_req++;
-	}
-
-	return 0;
-}
-
-static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
-	u16 scid, dcid, result, status;
-	struct sock *sk;
-	u8 req[128];
-
-	scid   = __le16_to_cpu(rsp->scid);
-	dcid   = __le16_to_cpu(rsp->dcid);
-	result = __le16_to_cpu(rsp->result);
-	status = __le16_to_cpu(rsp->status);
-
-	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
-
-	if (scid) {
-		sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
-		if (!sk)
-			return -EFAULT;
-	} else {
-		sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
-		if (!sk)
-			return -EFAULT;
-	}
-
-	switch (result) {
-	case L2CAP_CR_SUCCESS:
-		sk->sk_state = BT_CONFIG;
-		l2cap_pi(sk)->ident = 0;
-		l2cap_pi(sk)->dcid = dcid;
-		l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
-
-		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
-			break;
-
-		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-					l2cap_build_conf_req(sk, req), req);
-		l2cap_pi(sk)->num_conf_req++;
-		break;
-
-	case L2CAP_CR_PEND:
-		l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
-		break;
-
-	default:
-		/* don't delete l2cap channel if sk is owned by user */
-		if (sock_owned_by_user(sk)) {
-			sk->sk_state = BT_DISCONN;
-			l2cap_sock_clear_timer(sk);
-			l2cap_sock_set_timer(sk, HZ / 5);
-			break;
-		}
-
-		l2cap_chan_del(sk, ECONNREFUSED);
-		break;
-	}
-
-	bh_unlock_sock(sk);
-	return 0;
-}
-
-static inline void set_default_fcs(struct l2cap_pinfo *pi)
-{
-	/* FCS is enabled only in ERTM or streaming mode, if one or both
-	 * sides request it.
-	 */
-	if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
-		pi->fcs = L2CAP_FCS_NONE;
-	else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
-		pi->fcs = L2CAP_FCS_CRC16;
-}
-
-static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
-{
-	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
-	u16 dcid, flags;
-	u8 rsp[64];
-	struct sock *sk;
-	int len;
-
-	dcid  = __le16_to_cpu(req->dcid);
-	flags = __le16_to_cpu(req->flags);
-
-	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
-
-	sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
-	if (!sk)
-		return -ENOENT;
-
-	if (sk->sk_state != BT_CONFIG) {
-		struct l2cap_cmd_rej rej;
-
-		rej.reason = cpu_to_le16(0x0002);
-		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
-				sizeof(rej), &rej);
-		goto unlock;
-	}
-
-	/* Reject if config buffer is too small. */
-	len = cmd_len - sizeof(*req);
-	if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
-		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-				l2cap_build_conf_rsp(sk, rsp,
-					L2CAP_CONF_REJECT, flags), rsp);
-		goto unlock;
-	}
-
-	/* Store config. */
-	memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
-	l2cap_pi(sk)->conf_len += len;
-
-	if (flags & 0x0001) {
-		/* Incomplete config. Send empty response. */
-		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
-				l2cap_build_conf_rsp(sk, rsp,
-					L2CAP_CONF_SUCCESS, 0x0001), rsp);
-		goto unlock;
-	}
-
-	/* Complete config. */
-	len = l2cap_parse_conf_req(sk, rsp);
-	if (len < 0) {
-		l2cap_send_disconn_req(conn, sk, ECONNRESET);
-		goto unlock;
-	}
-
-	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
-	l2cap_pi(sk)->num_conf_rsp++;
-
-	/* Reset config buffer. */
-	l2cap_pi(sk)->conf_len = 0;
-
-	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
-		goto unlock;
-
-	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
-		set_default_fcs(l2cap_pi(sk));
-
-		sk->sk_state = BT_CONNECTED;
-
-		l2cap_pi(sk)->next_tx_seq = 0;
-		l2cap_pi(sk)->expected_tx_seq = 0;
-		__skb_queue_head_init(TX_QUEUE(sk));
-		if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
-			l2cap_ertm_init(sk);
-
-		l2cap_chan_ready(sk);
-		goto unlock;
-	}
-
-	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
-		u8 buf[64];
-		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
-		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-					l2cap_build_conf_req(sk, buf), buf);
-		l2cap_pi(sk)->num_conf_req++;
-	}
-
-unlock:
-	bh_unlock_sock(sk);
-	return 0;
-}
-
-static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
-	u16 scid, flags, result;
-	struct sock *sk;
-	int len = cmd->len - sizeof(*rsp);
-
-	scid   = __le16_to_cpu(rsp->scid);
-	flags  = __le16_to_cpu(rsp->flags);
-	result = __le16_to_cpu(rsp->result);
-
-	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
-			scid, flags, result);
-
-	sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
-	if (!sk)
-		return 0;
-
-	switch (result) {
-	case L2CAP_CONF_SUCCESS:
-		l2cap_conf_rfc_get(sk, rsp->data, len);
-		break;
-
-	case L2CAP_CONF_UNACCEPT:
-		if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
-			char req[64];
-
-			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
-				l2cap_send_disconn_req(conn, sk, ECONNRESET);
-				goto done;
-			}
-
-			/* throw out any old stored conf requests */
-			result = L2CAP_CONF_SUCCESS;
-			len = l2cap_parse_conf_rsp(sk, rsp->data,
-							len, req, &result);
-			if (len < 0) {
-				l2cap_send_disconn_req(conn, sk, ECONNRESET);
-				goto done;
-			}
-
-			l2cap_send_cmd(conn, l2cap_get_ident(conn),
-						L2CAP_CONF_REQ, len, req);
-			l2cap_pi(sk)->num_conf_req++;
-			if (result != L2CAP_CONF_SUCCESS)
-				goto done;
-			break;
-		}
-
-	default:
-		sk->sk_err = ECONNRESET;
-		l2cap_sock_set_timer(sk, HZ * 5);
-		l2cap_send_disconn_req(conn, sk, ECONNRESET);
-		goto done;
-	}
-
-	if (flags & 0x01)
-		goto done;
-
-	l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
-
-	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
-		set_default_fcs(l2cap_pi(sk));
-
-		sk->sk_state = BT_CONNECTED;
-		l2cap_pi(sk)->next_tx_seq = 0;
-		l2cap_pi(sk)->expected_tx_seq = 0;
-		__skb_queue_head_init(TX_QUEUE(sk));
-		if (l2cap_pi(sk)->mode ==  L2CAP_MODE_ERTM)
-			l2cap_ertm_init(sk);
-
-		l2cap_chan_ready(sk);
-	}
-
-done:
-	bh_unlock_sock(sk);
-	return 0;
-}
-
-static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
-	struct l2cap_disconn_rsp rsp;
-	u16 dcid, scid;
-	struct sock *sk;
-
-	scid = __le16_to_cpu(req->scid);
-	dcid = __le16_to_cpu(req->dcid);
-
-	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
-
-	sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
-	if (!sk)
-		return 0;
-
-	rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
-	rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
-	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
-
-	sk->sk_shutdown = SHUTDOWN_MASK;
-
-	/* don't delete l2cap channel if sk is owned by user */
-	if (sock_owned_by_user(sk)) {
-		sk->sk_state = BT_DISCONN;
-		l2cap_sock_clear_timer(sk);
-		l2cap_sock_set_timer(sk, HZ / 5);
-		bh_unlock_sock(sk);
-		return 0;
-	}
-
-	l2cap_chan_del(sk, ECONNRESET);
-	bh_unlock_sock(sk);
-
-	l2cap_sock_kill(sk);
-	return 0;
-}
-
-static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
-	u16 dcid, scid;
-	struct sock *sk;
-
-	scid = __le16_to_cpu(rsp->scid);
-	dcid = __le16_to_cpu(rsp->dcid);
-
-	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
-
-	sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
-	if (!sk)
-		return 0;
-
-	/* don't delete l2cap channel if sk is owned by user */
-	if (sock_owned_by_user(sk)) {
-		sk->sk_state = BT_DISCONN;
-		l2cap_sock_clear_timer(sk);
-		l2cap_sock_set_timer(sk, HZ / 5);
-		bh_unlock_sock(sk);
-		return 0;
-	}
-
-	l2cap_chan_del(sk, 0);
-	bh_unlock_sock(sk);
-
-	l2cap_sock_kill(sk);
-	return 0;
-}
-
-static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
-	u16 type;
-
-	type = __le16_to_cpu(req->type);
-
-	BT_DBG("type 0x%4.4x", type);
-
-	if (type == L2CAP_IT_FEAT_MASK) {
-		u8 buf[8];
-		u32 feat_mask = l2cap_feat_mask;
-		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
-		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
-		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
-		if (!disable_ertm)
-			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
-							 | L2CAP_FEAT_FCS;
-		put_unaligned_le32(feat_mask, rsp->data);
-		l2cap_send_cmd(conn, cmd->ident,
-					L2CAP_INFO_RSP, sizeof(buf), buf);
-	} else if (type == L2CAP_IT_FIXED_CHAN) {
-		u8 buf[12];
-		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
-		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
-		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
-		memcpy(buf + 4, l2cap_fixed_chan, 8);
-		l2cap_send_cmd(conn, cmd->ident,
-					L2CAP_INFO_RSP, sizeof(buf), buf);
-	} else {
-		struct l2cap_info_rsp rsp;
-		rsp.type   = cpu_to_le16(type);
-		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
-		l2cap_send_cmd(conn, cmd->ident,
-					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
-	}
-
-	return 0;
-}
-
-static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
-{
-	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
-	u16 type, result;
-
-	type   = __le16_to_cpu(rsp->type);
-	result = __le16_to_cpu(rsp->result);
-
-	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
-
-	del_timer(&conn->info_timer);
-
-	if (result != L2CAP_IR_SUCCESS) {
-		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
-		conn->info_ident = 0;
-
-		l2cap_conn_start(conn);
-
-		return 0;
-	}
-
-	if (type == L2CAP_IT_FEAT_MASK) {
-		conn->feat_mask = get_unaligned_le32(rsp->data);
-
-		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
-			struct l2cap_info_req req;
-			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
-
-			conn->info_ident = l2cap_get_ident(conn);
-
-			l2cap_send_cmd(conn, conn->info_ident,
-					L2CAP_INFO_REQ, sizeof(req), &req);
-		} else {
-			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
-			conn->info_ident = 0;
-
-			l2cap_conn_start(conn);
-		}
-	} else if (type == L2CAP_IT_FIXED_CHAN) {
-		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
-		conn->info_ident = 0;
-
-		l2cap_conn_start(conn);
-	}
-
-	return 0;
-}
-
-static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
-{
-	u8 *data = skb->data;
-	int len = skb->len;
-	struct l2cap_cmd_hdr cmd;
-	int err = 0;
-
-	l2cap_raw_recv(conn, skb);
-
-	while (len >= L2CAP_CMD_HDR_SIZE) {
-		u16 cmd_len;
-		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
-		data += L2CAP_CMD_HDR_SIZE;
-		len  -= L2CAP_CMD_HDR_SIZE;
-
-		cmd_len = le16_to_cpu(cmd.len);
-
-		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
-
-		if (cmd_len > len || !cmd.ident) {
-			BT_DBG("corrupted command");
-			break;
-		}
-
-		switch (cmd.code) {
-		case L2CAP_COMMAND_REJ:
-			l2cap_command_rej(conn, &cmd, data);
-			break;
-
-		case L2CAP_CONN_REQ:
-			err = l2cap_connect_req(conn, &cmd, data);
-			break;
-
-		case L2CAP_CONN_RSP:
-			err = l2cap_connect_rsp(conn, &cmd, data);
-			break;
-
-		case L2CAP_CONF_REQ:
-			err = l2cap_config_req(conn, &cmd, cmd_len, data);
-			break;
-
-		case L2CAP_CONF_RSP:
-			err = l2cap_config_rsp(conn, &cmd, data);
-			break;
-
-		case L2CAP_DISCONN_REQ:
-			err = l2cap_disconnect_req(conn, &cmd, data);
-			break;
-
-		case L2CAP_DISCONN_RSP:
-			err = l2cap_disconnect_rsp(conn, &cmd, data);
-			break;
-
-		case L2CAP_ECHO_REQ:
-			l2cap_send_cmd(conn, cmd.ident, L2CAP_ECHO_RSP, cmd_len, data);
-			break;
-
-		case L2CAP_ECHO_RSP:
-			break;
-
-		case L2CAP_INFO_REQ:
-			err = l2cap_information_req(conn, &cmd, data);
-			break;
-
-		case L2CAP_INFO_RSP:
-			err = l2cap_information_rsp(conn, &cmd, data);
-			break;
-
-		default:
-			BT_ERR("Unknown signaling command 0x%2.2x", cmd.code);
-			err = -EINVAL;
-			break;
-		}
-
-		if (err) {
-			struct l2cap_cmd_rej rej;
-			BT_DBG("error %d", err);
-
-			/* FIXME: Map err to a valid reason */
-			rej.reason = cpu_to_le16(0);
-			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
-		}
-
-		data += cmd_len;
-		len  -= cmd_len;
-	}
-
-	kfree_skb(skb);
-}
-
-static int l2cap_check_fcs(struct l2cap_pinfo *pi,  struct sk_buff *skb)
-{
-	u16 our_fcs, rcv_fcs;
-	int hdr_size = L2CAP_HDR_SIZE + 2;
-
-	if (pi->fcs == L2CAP_FCS_CRC16) {
-		skb_trim(skb, skb->len - 2);
-		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
-		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
-
-		if (our_fcs != rcv_fcs)
-			return -EBADMSG;
-	}
-	return 0;
-}
-
-static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u16 control = 0;
-
-	pi->frames_sent = 0;
-
-	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-
-	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
-		control |= L2CAP_SUPER_RCV_NOT_READY;
-		l2cap_send_sframe(pi, control);
-		pi->conn_state |= L2CAP_CONN_RNR_SENT;
-	}
-
-	if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
-		l2cap_retransmit_frames(sk);
-
-	l2cap_ertm_send(sk);
-
-	if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
-			pi->frames_sent == 0) {
-		control |= L2CAP_SUPER_RCV_READY;
-		l2cap_send_sframe(pi, control);
-	}
-}
-
-static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
-{
-	struct sk_buff *next_skb;
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	int tx_seq_offset, next_tx_seq_offset;
-
-	bt_cb(skb)->tx_seq = tx_seq;
-	bt_cb(skb)->sar = sar;
-
-	next_skb = skb_peek(SREJ_QUEUE(sk));
-	if (!next_skb) {
-		__skb_queue_tail(SREJ_QUEUE(sk), skb);
-		return 0;
-	}
-
-	tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
-	if (tx_seq_offset < 0)
-		tx_seq_offset += 64;
-
-	do {
-		if (bt_cb(next_skb)->tx_seq == tx_seq)
-			return -EINVAL;
-
-		next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
-						pi->buffer_seq) % 64;
-		if (next_tx_seq_offset < 0)
-			next_tx_seq_offset += 64;
-
-		if (next_tx_seq_offset > tx_seq_offset) {
-			__skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
-			return 0;
-		}
-
-		if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
-			break;
-
-	} while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
-
-	__skb_queue_tail(SREJ_QUEUE(sk), skb);
-
-	return 0;
-}
-
-static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *_skb;
-	int err;
-
-	switch (control & L2CAP_CTRL_SAR) {
-	case L2CAP_SDU_UNSEGMENTED:
-		if (pi->conn_state & L2CAP_CONN_SAR_SDU)
-			goto drop;
-
-		err = sock_queue_rcv_skb(sk, skb);
-		if (!err)
-			return err;
-
-		break;
-
-	case L2CAP_SDU_START:
-		if (pi->conn_state & L2CAP_CONN_SAR_SDU)
-			goto drop;
-
-		pi->sdu_len = get_unaligned_le16(skb->data);
-
-		if (pi->sdu_len > pi->imtu)
-			goto disconnect;
-
-		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
-		if (!pi->sdu)
-			return -ENOMEM;
-
-		/* pull sdu_len bytes only after alloc, because of Local Busy
-		 * condition we have to be sure that this will be executed
-		 * only once, i.e., when alloc does not fail */
-		skb_pull(skb, 2);
-
-		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-
-		pi->conn_state |= L2CAP_CONN_SAR_SDU;
-		pi->partial_sdu_len = skb->len;
-		break;
-
-	case L2CAP_SDU_CONTINUE:
-		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
-			goto disconnect;
-
-		if (!pi->sdu)
-			goto disconnect;
-
-		pi->partial_sdu_len += skb->len;
-		if (pi->partial_sdu_len > pi->sdu_len)
-			goto drop;
-
-		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-
-		break;
-
-	case L2CAP_SDU_END:
-		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
-			goto disconnect;
-
-		if (!pi->sdu)
-			goto disconnect;
-
-		if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
-			pi->partial_sdu_len += skb->len;
-
-			if (pi->partial_sdu_len > pi->imtu)
-				goto drop;
-
-			if (pi->partial_sdu_len != pi->sdu_len)
-				goto drop;
-
-			memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-		}
-
-		_skb = skb_clone(pi->sdu, GFP_ATOMIC);
-		if (!_skb) {
-			pi->conn_state |= L2CAP_CONN_SAR_RETRY;
-			return -ENOMEM;
-		}
-
-		err = sock_queue_rcv_skb(sk, _skb);
-		if (err < 0) {
-			kfree_skb(_skb);
-			pi->conn_state |= L2CAP_CONN_SAR_RETRY;
-			return err;
-		}
-
-		pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
-		pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
-
-		kfree_skb(pi->sdu);
-		break;
-	}
-
-	kfree_skb(skb);
-	return 0;
-
-drop:
-	kfree_skb(pi->sdu);
-	pi->sdu = NULL;
-
-disconnect:
-	l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
-	kfree_skb(skb);
-	return 0;
-}
-
-static int l2cap_try_push_rx_skb(struct sock *sk)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *skb;
-	u16 control;
-	int err;
-
-	while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
-		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
-		err = l2cap_ertm_reassembly_sdu(sk, skb, control);
-		if (err < 0) {
-			skb_queue_head(BUSY_QUEUE(sk), skb);
-			return -EBUSY;
-		}
-
-		pi->buffer_seq = (pi->buffer_seq + 1) % 64;
-	}
-
-	if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
-		goto done;
-
-	control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-	control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
-	l2cap_send_sframe(pi, control);
-	l2cap_pi(sk)->retry_count = 1;
-
-	del_timer(&pi->retrans_timer);
-	__mod_monitor_timer();
-
-	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
-
-done:
-	pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
-	pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
-
-	BT_DBG("sk %p, Exit local busy", sk);
-
-	return 0;
-}
-
-static void l2cap_busy_work(struct work_struct *work)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	struct l2cap_pinfo *pi =
-		container_of(work, struct l2cap_pinfo, busy_work);
-	struct sock *sk = (struct sock *)pi;
-	int n_tries = 0, timeo = HZ/5, err;
-	struct sk_buff *skb;
-
-	lock_sock(sk);
-
-	add_wait_queue(sk_sleep(sk), &wait);
-	while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
-			err = -EBUSY;
-			l2cap_send_disconn_req(pi->conn, sk, EBUSY);
-			break;
-		}
-
-		if (!timeo)
-			timeo = HZ/5;
-
-		if (signal_pending(current)) {
-			err = sock_intr_errno(timeo);
-			break;
-		}
-
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-
-		err = sock_error(sk);
-		if (err)
-			break;
-
-		if (l2cap_try_push_rx_skb(sk) == 0)
-			break;
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(sk_sleep(sk), &wait);
-
-	release_sock(sk);
-}
-
-static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	int sctrl, err;
-
-	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
-		bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
-		__skb_queue_tail(BUSY_QUEUE(sk), skb);
-		return l2cap_try_push_rx_skb(sk);
-
-
-	}
-
-	err = l2cap_ertm_reassembly_sdu(sk, skb, control);
-	if (err >= 0) {
-		pi->buffer_seq = (pi->buffer_seq + 1) % 64;
-		return err;
-	}
-
-	/* Busy Condition */
-	BT_DBG("sk %p, Enter local busy", sk);
-
-	pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
-	bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
-	__skb_queue_tail(BUSY_QUEUE(sk), skb);
-
-	sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-	sctrl |= L2CAP_SUPER_RCV_NOT_READY;
-	l2cap_send_sframe(pi, sctrl);
-
-	pi->conn_state |= L2CAP_CONN_RNR_SENT;
-
-	del_timer(&pi->ack_timer);
-
-	queue_work(_busy_wq, &pi->busy_work);
-
-	return err;
-}
-
-static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct sk_buff *_skb;
-	int err = -EINVAL;
-
-	/*
-	 * TODO: We have to notify the userland if some data is lost with the
-	 * Streaming Mode.
-	 */
-
-	switch (control & L2CAP_CTRL_SAR) {
-	case L2CAP_SDU_UNSEGMENTED:
-		if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
-			kfree_skb(pi->sdu);
-			break;
-		}
-
-		err = sock_queue_rcv_skb(sk, skb);
-		if (!err)
-			return 0;
-
-		break;
-
-	case L2CAP_SDU_START:
-		if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
-			kfree_skb(pi->sdu);
-			break;
-		}
-
-		pi->sdu_len = get_unaligned_le16(skb->data);
-		skb_pull(skb, 2);
-
-		if (pi->sdu_len > pi->imtu) {
-			err = -EMSGSIZE;
-			break;
-		}
-
-		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
-		if (!pi->sdu) {
-			err = -ENOMEM;
-			break;
-		}
-
-		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-
-		pi->conn_state |= L2CAP_CONN_SAR_SDU;
-		pi->partial_sdu_len = skb->len;
-		err = 0;
-		break;
-
-	case L2CAP_SDU_CONTINUE:
-		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
-			break;
-
-		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-
-		pi->partial_sdu_len += skb->len;
-		if (pi->partial_sdu_len > pi->sdu_len)
-			kfree_skb(pi->sdu);
-		else
-			err = 0;
-
-		break;
-
-	case L2CAP_SDU_END:
-		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
-			break;
-
-		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
-
-		pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
-		pi->partial_sdu_len += skb->len;
-
-		if (pi->partial_sdu_len > pi->imtu)
-			goto drop;
-
-		if (pi->partial_sdu_len == pi->sdu_len) {
-			_skb = skb_clone(pi->sdu, GFP_ATOMIC);
-			err = sock_queue_rcv_skb(sk, _skb);
-			if (err < 0)
-				kfree_skb(_skb);
-		}
-		err = 0;
-
-drop:
-		kfree_skb(pi->sdu);
-		break;
-	}
-
-	kfree_skb(skb);
-	return err;
-}
-
-static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
-{
-	struct sk_buff *skb;
-	u16 control;
-
-	while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
-		if (bt_cb(skb)->tx_seq != tx_seq)
-			break;
-
-		skb = skb_dequeue(SREJ_QUEUE(sk));
-		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
-		l2cap_ertm_reassembly_sdu(sk, skb, control);
-		l2cap_pi(sk)->buffer_seq_srej =
-			(l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
-		tx_seq = (tx_seq + 1) % 64;
-	}
-}
-
-static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct srej_list *l, *tmp;
-	u16 control;
-
-	list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
-		if (l->tx_seq == tx_seq) {
-			list_del(&l->list);
-			kfree(l);
-			return;
-		}
-		control = L2CAP_SUPER_SELECT_REJECT;
-		control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-		l2cap_send_sframe(pi, control);
-		list_del(&l->list);
-		list_add_tail(&l->list, SREJ_LIST(sk));
-	}
-}
-
-static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	struct srej_list *new;
-	u16 control;
-
-	while (tx_seq != pi->expected_tx_seq) {
-		control = L2CAP_SUPER_SELECT_REJECT;
-		control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
-		l2cap_send_sframe(pi, control);
-
-		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
-		new->tx_seq = pi->expected_tx_seq;
-		pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-		list_add_tail(&new->list, SREJ_LIST(sk));
-	}
-	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-}
-
-static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 tx_seq = __get_txseq(rx_control);
-	u8 req_seq = __get_reqseq(rx_control);
-	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
-	int tx_seq_offset, expected_tx_seq_offset;
-	int num_to_ack = (pi->tx_win/6) + 1;
-	int err = 0;
-
-	BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
-								rx_control);
-
-	if (L2CAP_CTRL_FINAL & rx_control &&
-			l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
-		del_timer(&pi->monitor_timer);
-		if (pi->unacked_frames > 0)
-			__mod_retrans_timer();
-		pi->conn_state &= ~L2CAP_CONN_WAIT_F;
-	}
-
-	pi->expected_ack_seq = req_seq;
-	l2cap_drop_acked_frames(sk);
-
-	if (tx_seq == pi->expected_tx_seq)
-		goto expected;
-
-	tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
-	if (tx_seq_offset < 0)
-		tx_seq_offset += 64;
-
-	/* invalid tx_seq */
-	if (tx_seq_offset >= pi->tx_win) {
-		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
-		goto drop;
-	}
-
-	if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
-		goto drop;
-
-	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
-		struct srej_list *first;
-
-		first = list_first_entry(SREJ_LIST(sk),
-				struct srej_list, list);
-		if (tx_seq == first->tx_seq) {
-			l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
-			l2cap_check_srej_gap(sk, tx_seq);
-
-			list_del(&first->list);
-			kfree(first);
-
-			if (list_empty(SREJ_LIST(sk))) {
-				pi->buffer_seq = pi->buffer_seq_srej;
-				pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
-				l2cap_send_ack(pi);
-				BT_DBG("sk %p, Exit SREJ_SENT", sk);
-			}
-		} else {
-			struct srej_list *l;
-
-			/* duplicated tx_seq */
-			if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
-				goto drop;
-
-			list_for_each_entry(l, SREJ_LIST(sk), list) {
-				if (l->tx_seq == tx_seq) {
-					l2cap_resend_srejframe(sk, tx_seq);
-					return 0;
-				}
-			}
-			l2cap_send_srejframe(sk, tx_seq);
-		}
-	} else {
-		expected_tx_seq_offset =
-			(pi->expected_tx_seq - pi->buffer_seq) % 64;
-		if (expected_tx_seq_offset < 0)
-			expected_tx_seq_offset += 64;
-
-		/* duplicated tx_seq */
-		if (tx_seq_offset < expected_tx_seq_offset)
-			goto drop;
-
-		pi->conn_state |= L2CAP_CONN_SREJ_SENT;
-
-		BT_DBG("sk %p, Enter SREJ", sk);
-
-		INIT_LIST_HEAD(SREJ_LIST(sk));
-		pi->buffer_seq_srej = pi->buffer_seq;
-
-		__skb_queue_head_init(SREJ_QUEUE(sk));
-		__skb_queue_head_init(BUSY_QUEUE(sk));
-		l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
-
-		pi->conn_state |= L2CAP_CONN_SEND_PBIT;
-
-		l2cap_send_srejframe(sk, tx_seq);
-
-		del_timer(&pi->ack_timer);
-	}
-	return 0;
-
-expected:
-	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-
-	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
-		bt_cb(skb)->tx_seq = tx_seq;
-		bt_cb(skb)->sar = sar;
-		__skb_queue_tail(SREJ_QUEUE(sk), skb);
-		return 0;
-	}
-
-	err = l2cap_push_rx_skb(sk, skb, rx_control);
-	if (err < 0)
-		return 0;
-
-	if (rx_control & L2CAP_CTRL_FINAL) {
-		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
-		else
-			l2cap_retransmit_frames(sk);
-	}
-
-	__mod_ack_timer();
-
-	pi->num_acked = (pi->num_acked + 1) % num_to_ack;
-	if (pi->num_acked == num_to_ack - 1)
-		l2cap_send_ack(pi);
-
-	return 0;
-
-drop:
-	kfree_skb(skb);
-	return 0;
-}
-
-static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
-						rx_control);
-
-	pi->expected_ack_seq = __get_reqseq(rx_control);
-	l2cap_drop_acked_frames(sk);
-
-	if (rx_control & L2CAP_CTRL_POLL) {
-		pi->conn_state |= L2CAP_CONN_SEND_FBIT;
-		if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
-			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-					(pi->unacked_frames > 0))
-				__mod_retrans_timer();
-
-			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-			l2cap_send_srejtail(sk);
-		} else {
-			l2cap_send_i_or_rr_or_rnr(sk);
-		}
-
-	} else if (rx_control & L2CAP_CTRL_FINAL) {
-		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
-		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
-		else
-			l2cap_retransmit_frames(sk);
-
-	} else {
-		if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-				(pi->unacked_frames > 0))
-			__mod_retrans_timer();
-
-		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-		if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
-			l2cap_send_ack(pi);
-		else
-			l2cap_ertm_send(sk);
-	}
-}
-
-static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 tx_seq = __get_reqseq(rx_control);
-
-	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
-
-	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
-	pi->expected_ack_seq = tx_seq;
-	l2cap_drop_acked_frames(sk);
-
-	if (rx_control & L2CAP_CTRL_FINAL) {
-		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
-			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
-		else
-			l2cap_retransmit_frames(sk);
-	} else {
-		l2cap_retransmit_frames(sk);
-
-		if (pi->conn_state & L2CAP_CONN_WAIT_F)
-			pi->conn_state |= L2CAP_CONN_REJ_ACT;
-	}
-}
-static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 tx_seq = __get_reqseq(rx_control);
-
-	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
-
-	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-
-	if (rx_control & L2CAP_CTRL_POLL) {
-		pi->expected_ack_seq = tx_seq;
-		l2cap_drop_acked_frames(sk);
-
-		pi->conn_state |= L2CAP_CONN_SEND_FBIT;
-		l2cap_retransmit_one_frame(sk, tx_seq);
-
-		l2cap_ertm_send(sk);
-
-		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-			pi->srej_save_reqseq = tx_seq;
-			pi->conn_state |= L2CAP_CONN_SREJ_ACT;
-		}
-	} else if (rx_control & L2CAP_CTRL_FINAL) {
-		if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
-				pi->srej_save_reqseq == tx_seq)
-			pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
-		else
-			l2cap_retransmit_one_frame(sk, tx_seq);
-	} else {
-		l2cap_retransmit_one_frame(sk, tx_seq);
-		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
-			pi->srej_save_reqseq = tx_seq;
-			pi->conn_state |= L2CAP_CONN_SREJ_ACT;
-		}
-	}
-}
-
-static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u8 tx_seq = __get_reqseq(rx_control);
-
-	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
-
-	pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
-	pi->expected_ack_seq = tx_seq;
-	l2cap_drop_acked_frames(sk);
-
-	if (rx_control & L2CAP_CTRL_POLL)
-		pi->conn_state |= L2CAP_CONN_SEND_FBIT;
-
-	if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
-		del_timer(&pi->retrans_timer);
-		if (rx_control & L2CAP_CTRL_POLL)
-			l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
-		return;
-	}
-
-	if (rx_control & L2CAP_CTRL_POLL)
-		l2cap_send_srejtail(sk);
-	else
-		l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
-}
-
-static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
-{
-	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
-
-	if (L2CAP_CTRL_FINAL & rx_control &&
-			l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
-		del_timer(&l2cap_pi(sk)->monitor_timer);
-		if (l2cap_pi(sk)->unacked_frames > 0)
-			__mod_retrans_timer();
-		l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
-	}
-
-	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
-	case L2CAP_SUPER_RCV_READY:
-		l2cap_data_channel_rrframe(sk, rx_control);
-		break;
-
-	case L2CAP_SUPER_REJECT:
-		l2cap_data_channel_rejframe(sk, rx_control);
-		break;
-
-	case L2CAP_SUPER_SELECT_REJECT:
-		l2cap_data_channel_srejframe(sk, rx_control);
-		break;
-
-	case L2CAP_SUPER_RCV_NOT_READY:
-		l2cap_data_channel_rnrframe(sk, rx_control);
-		break;
-	}
-
-	kfree_skb(skb);
-	return 0;
-}
-
-static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
-{
-	struct l2cap_pinfo *pi = l2cap_pi(sk);
-	u16 control;
-	u8 req_seq;
-	int len, next_tx_seq_offset, req_seq_offset;
-
-	control = get_unaligned_le16(skb->data);
-	skb_pull(skb, 2);
-	len = skb->len;
-
-	/*
-	 * We can just drop the corrupted I-frame here.
-	 * Receiver will miss it and start proper recovery
-	 * procedures and ask retransmission.
-	 */
-	if (l2cap_check_fcs(pi, skb))
-		goto drop;
-
-	if (__is_sar_start(control) && __is_iframe(control))
-		len -= 2;
-
-	if (pi->fcs == L2CAP_FCS_CRC16)
-		len -= 2;
-
-	if (len > pi->mps) {
-		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
-		goto drop;
-	}
-
-	req_seq = __get_reqseq(control);
-	req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
-	if (req_seq_offset < 0)
-		req_seq_offset += 64;
-
-	next_tx_seq_offset =
-		(pi->next_tx_seq - pi->expected_ack_seq) % 64;
-	if (next_tx_seq_offset < 0)
-		next_tx_seq_offset += 64;
-
-	/* check for invalid req-seq */
-	if (req_seq_offset > next_tx_seq_offset) {
-		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
-		goto drop;
-	}
-
-	if (__is_iframe(control)) {
-		if (len < 0) {
-			l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
-			goto drop;
-		}
-
-		l2cap_data_channel_iframe(sk, control, skb);
-	} else {
-		if (len != 0) {
-			BT_ERR("%d", len);
-			l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
-			goto drop;
-		}
-
-		l2cap_data_channel_sframe(sk, control, skb);
-	}
-
-	return 0;
-
-drop:
-	kfree_skb(skb);
-	return 0;
-}
-
-static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
-{
-	struct sock *sk;
-	struct l2cap_pinfo *pi;
-	u16 control;
-	u8 tx_seq;
-	int len;
-
-	sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
-	if (!sk) {
-		BT_DBG("unknown cid 0x%4.4x", cid);
-		goto drop;
-	}
-
-	pi = l2cap_pi(sk);
-
-	BT_DBG("sk %p, len %d", sk, skb->len);
-
-	if (sk->sk_state != BT_CONNECTED)
-		goto drop;
-
-	switch (pi->mode) {
-	case L2CAP_MODE_BASIC:
-		/* If socket recv buffers overflows we drop data here
-		 * which is *bad* because L2CAP has to be reliable.
-		 * But we don't have any other choice. L2CAP doesn't
-		 * provide flow control mechanism. */
-
-		if (pi->imtu < skb->len)
-			goto drop;
-
-		if (!sock_queue_rcv_skb(sk, skb))
-			goto done;
-		break;
-
-	case L2CAP_MODE_ERTM:
-		if (!sock_owned_by_user(sk)) {
-			l2cap_ertm_data_rcv(sk, skb);
-		} else {
-			if (sk_add_backlog(sk, skb))
-				goto drop;
-		}
-
-		goto done;
-
-	case L2CAP_MODE_STREAMING:
-		control = get_unaligned_le16(skb->data);
-		skb_pull(skb, 2);
-		len = skb->len;
-
-		if (l2cap_check_fcs(pi, skb))
-			goto drop;
-
-		if (__is_sar_start(control))
-			len -= 2;
-
-		if (pi->fcs == L2CAP_FCS_CRC16)
-			len -= 2;
-
-		if (len > pi->mps || len < 0 || __is_sframe(control))
-			goto drop;
-
-		tx_seq = __get_txseq(control);
-
-		if (pi->expected_tx_seq == tx_seq)
-			pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
-		else
-			pi->expected_tx_seq = (tx_seq + 1) % 64;
-
-		l2cap_streaming_reassembly_sdu(sk, skb, control);
-
-		goto done;
-
-	default:
-		BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
-		break;
-	}
-
-drop:
-	kfree_skb(skb);
-
-done:
-	if (sk)
-		bh_unlock_sock(sk);
-
-	return 0;
-}
-
-static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
-{
-	struct sock *sk;
-
-	sk = l2cap_get_sock_by_psm(0, psm, conn->src);
-	if (!sk)
-		goto drop;
-
-	bh_lock_sock(sk);
-
-	BT_DBG("sk %p, len %d", sk, skb->len);
-
-	if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
-		goto drop;
-
-	if (l2cap_pi(sk)->imtu < skb->len)
-		goto drop;
-
-	if (!sock_queue_rcv_skb(sk, skb))
-		goto done;
-
-drop:
-	kfree_skb(skb);
-
-done:
-	if (sk)
-		bh_unlock_sock(sk);
-	return 0;
-}
-
-static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
-{
-	struct l2cap_hdr *lh = (void *) skb->data;
-	u16 cid, len;
-	__le16 psm;
-
-	skb_pull(skb, L2CAP_HDR_SIZE);
-	cid = __le16_to_cpu(lh->cid);
-	len = __le16_to_cpu(lh->len);
-
-	if (len != skb->len) {
-		kfree_skb(skb);
-		return;
-	}
-
-	BT_DBG("len %d, cid 0x%4.4x", len, cid);
-
-	switch (cid) {
-	case L2CAP_CID_SIGNALING:
-		l2cap_sig_channel(conn, skb);
-		break;
-
-	case L2CAP_CID_CONN_LESS:
-		psm = get_unaligned_le16(skb->data);
-		skb_pull(skb, 2);
-		l2cap_conless_channel(conn, psm, skb);
-		break;
-
-	default:
-		l2cap_data_channel(conn, cid, skb);
-		break;
-	}
-}
-
-/* ---- L2CAP interface with lower layer (HCI) ---- */
-
-static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
-{
-	int exact = 0, lm1 = 0, lm2 = 0;
-	register struct sock *sk;
-	struct hlist_node *node;
-
-	if (type != ACL_LINK)
-		return -EINVAL;
-
-	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
-
-	/* Find listening sockets and check their link_mode */
-	read_lock(&l2cap_sk_list.lock);
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		if (sk->sk_state != BT_LISTEN)
-			continue;
-
-		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
-			lm1 |= HCI_LM_ACCEPT;
-			if (l2cap_pi(sk)->role_switch)
-				lm1 |= HCI_LM_MASTER;
-			exact++;
-		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
-			lm2 |= HCI_LM_ACCEPT;
-			if (l2cap_pi(sk)->role_switch)
-				lm2 |= HCI_LM_MASTER;
-		}
-	}
-	read_unlock(&l2cap_sk_list.lock);
-
-	return exact ? lm1 : lm2;
-}
-
-static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
-{
-	struct l2cap_conn *conn;
-
-	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
-
-	if (hcon->type != ACL_LINK)
-		return -EINVAL;
-
-	if (!status) {
-		conn = l2cap_conn_add(hcon, status);
-		if (conn)
-			l2cap_conn_ready(conn);
-	} else
-		l2cap_conn_del(hcon, bt_err(status));
-
-	return 0;
-}
-
-static int l2cap_disconn_ind(struct hci_conn *hcon)
-{
-	struct l2cap_conn *conn = hcon->l2cap_data;
-
-	BT_DBG("hcon %p", hcon);
-
-	if (hcon->type != ACL_LINK || !conn)
-		return 0x13;
-
-	return conn->disc_reason;
-}
-
-static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
-{
-	BT_DBG("hcon %p reason %d", hcon, reason);
-
-	if (hcon->type != ACL_LINK)
-		return -EINVAL;
-
-	l2cap_conn_del(hcon, bt_err(reason));
-
-	return 0;
-}
-
-static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
-{
-	if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
-		return;
-
-	if (encrypt == 0x00) {
-		if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
-			l2cap_sock_clear_timer(sk);
-			l2cap_sock_set_timer(sk, HZ * 5);
-		} else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
-			__l2cap_sock_close(sk, ECONNREFUSED);
-	} else {
-		if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
-			l2cap_sock_clear_timer(sk);
-	}
-}
-
-static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
-{
-	struct l2cap_chan_list *l;
-	struct l2cap_conn *conn = hcon->l2cap_data;
-	struct sock *sk;
-
-	if (!conn)
-		return 0;
-
-	l = &conn->chan_list;
-
-	BT_DBG("conn %p", conn);
-
-	read_lock(&l->lock);
-
-	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
-		bh_lock_sock(sk);
-
-		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
-			bh_unlock_sock(sk);
-			continue;
-		}
-
-		if (!status && (sk->sk_state == BT_CONNECTED ||
-						sk->sk_state == BT_CONFIG)) {
-			l2cap_check_encryption(sk, encrypt);
-			bh_unlock_sock(sk);
-			continue;
-		}
-
-		if (sk->sk_state == BT_CONNECT) {
-			if (!status) {
-				struct l2cap_conn_req req;
-				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
-				req.psm  = l2cap_pi(sk)->psm;
-
-				l2cap_pi(sk)->ident = l2cap_get_ident(conn);
-				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
-
-				l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_REQ, sizeof(req), &req);
-			} else {
-				l2cap_sock_clear_timer(sk);
-				l2cap_sock_set_timer(sk, HZ / 10);
-			}
-		} else if (sk->sk_state == BT_CONNECT2) {
-			struct l2cap_conn_rsp rsp;
-			__u16 result;
-
-			if (!status) {
-				sk->sk_state = BT_CONFIG;
-				result = L2CAP_CR_SUCCESS;
-			} else {
-				sk->sk_state = BT_DISCONN;
-				l2cap_sock_set_timer(sk, HZ / 10);
-				result = L2CAP_CR_SEC_BLOCK;
-			}
-
-			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
-			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
-			rsp.result = cpu_to_le16(result);
-			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
-					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
-		}
-
-		bh_unlock_sock(sk);
-	}
-
-	read_unlock(&l->lock);
-
-	return 0;
-}
-
-static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
-{
-	struct l2cap_conn *conn = hcon->l2cap_data;
-
-	if (!conn && !(conn = l2cap_conn_add(hcon, 0)))
-		goto drop;
-
-	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
-
-	if (flags & ACL_START) {
-		struct l2cap_hdr *hdr;
-		struct sock *sk;
-		u16 cid;
-		int len;
-
-		if (conn->rx_len) {
-			BT_ERR("Unexpected start frame (len %d)", skb->len);
-			kfree_skb(conn->rx_skb);
-			conn->rx_skb = NULL;
-			conn->rx_len = 0;
-			l2cap_conn_unreliable(conn, ECOMM);
-		}
-
-		/* Start fragment always begin with Basic L2CAP header */
-		if (skb->len < L2CAP_HDR_SIZE) {
-			BT_ERR("Frame is too short (len %d)", skb->len);
-			l2cap_conn_unreliable(conn, ECOMM);
-			goto drop;
-		}
-
-		hdr = (struct l2cap_hdr *) skb->data;
-		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
-		cid = __le16_to_cpu(hdr->cid);
-
-		if (len == skb->len) {
-			/* Complete frame received */
-			l2cap_recv_frame(conn, skb);
-			return 0;
-		}
-
-		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
-
-		if (skb->len > len) {
-			BT_ERR("Frame is too long (len %d, expected len %d)",
-				skb->len, len);
-			l2cap_conn_unreliable(conn, ECOMM);
-			goto drop;
-		}
-
-		sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
-
-		if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
-			BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
-					len, l2cap_pi(sk)->imtu);
-			bh_unlock_sock(sk);
-			l2cap_conn_unreliable(conn, ECOMM);
-			goto drop;
-		}
-
-		if (sk)
-			bh_unlock_sock(sk);
-
-		/* Allocate skb for the complete frame (with header) */
-		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
-		if (!conn->rx_skb)
-			goto drop;
-
-		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
-								skb->len);
-		conn->rx_len = len - skb->len;
-	} else {
-		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
-
-		if (!conn->rx_len) {
-			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
-			l2cap_conn_unreliable(conn, ECOMM);
-			goto drop;
-		}
-
-		if (skb->len > conn->rx_len) {
-			BT_ERR("Fragment is too long (len %d, expected %d)",
-					skb->len, conn->rx_len);
-			kfree_skb(conn->rx_skb);
-			conn->rx_skb = NULL;
-			conn->rx_len = 0;
-			l2cap_conn_unreliable(conn, ECOMM);
-			goto drop;
-		}
-
-		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
-								skb->len);
-		conn->rx_len -= skb->len;
-
-		if (!conn->rx_len) {
-			/* Complete frame received */
-			l2cap_recv_frame(conn, conn->rx_skb);
-			conn->rx_skb = NULL;
-		}
-	}
-
-drop:
-	kfree_skb(skb);
-	return 0;
-}
-
-static int l2cap_debugfs_show(struct seq_file *f, void *p)
-{
-	struct sock *sk;
-	struct hlist_node *node;
-
-	read_lock_bh(&l2cap_sk_list.lock);
-
-	sk_for_each(sk, node, &l2cap_sk_list.head) {
-		struct l2cap_pinfo *pi = l2cap_pi(sk);
-
-		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
-					batostr(&bt_sk(sk)->src),
-					batostr(&bt_sk(sk)->dst),
-					sk->sk_state, __le16_to_cpu(pi->psm),
-					pi->scid, pi->dcid,
-					pi->imtu, pi->omtu, pi->sec_level);
-	}
-
-	read_unlock_bh(&l2cap_sk_list.lock);
-
-	return 0;
-}
-
-static int l2cap_debugfs_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, l2cap_debugfs_show, inode->i_private);
-}
-
-static const struct file_operations l2cap_debugfs_fops = {
-	.open		= l2cap_debugfs_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static struct dentry *l2cap_debugfs;
-
-static const struct proto_ops l2cap_sock_ops = {
-	.family		= PF_BLUETOOTH,
-	.owner		= THIS_MODULE,
-	.release	= l2cap_sock_release,
-	.bind		= l2cap_sock_bind,
-	.connect	= l2cap_sock_connect,
-	.listen		= l2cap_sock_listen,
-	.accept		= l2cap_sock_accept,
-	.getname	= l2cap_sock_getname,
-	.sendmsg	= l2cap_sock_sendmsg,
-	.recvmsg	= l2cap_sock_recvmsg,
-	.poll		= bt_sock_poll,
-	.ioctl		= bt_sock_ioctl,
-	.mmap		= sock_no_mmap,
-	.socketpair	= sock_no_socketpair,
-	.shutdown	= l2cap_sock_shutdown,
-	.setsockopt	= l2cap_sock_setsockopt,
-	.getsockopt	= l2cap_sock_getsockopt
-};
-
-static const struct net_proto_family l2cap_sock_family_ops = {
-	.family	= PF_BLUETOOTH,
-	.owner	= THIS_MODULE,
-	.create	= l2cap_sock_create,
-};
-
-static struct hci_proto l2cap_hci_proto = {
-	.name		= "L2CAP",
-	.id		= HCI_PROTO_L2CAP,
-	.connect_ind	= l2cap_connect_ind,
-	.connect_cfm	= l2cap_connect_cfm,
-	.disconn_ind	= l2cap_disconn_ind,
-	.disconn_cfm	= l2cap_disconn_cfm,
-	.security_cfm	= l2cap_security_cfm,
-	.recv_acldata	= l2cap_recv_acldata
-};
-
-static int __init l2cap_init(void)
-{
-	int err;
-
-	err = proto_register(&l2cap_proto, 0);
-	if (err < 0)
-		return err;
-
-	_busy_wq = create_singlethread_workqueue("l2cap");
-	if (!_busy_wq) {
-		proto_unregister(&l2cap_proto);
-		return -ENOMEM;
-	}
-
-	err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
-	if (err < 0) {
-		BT_ERR("L2CAP socket registration failed");
-		goto error;
-	}
-
-	err = hci_register_proto(&l2cap_hci_proto);
-	if (err < 0) {
-		BT_ERR("L2CAP protocol registration failed");
-		bt_sock_unregister(BTPROTO_L2CAP);
-		goto error;
-	}
-
-	if (bt_debugfs) {
-		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
-					bt_debugfs, NULL, &l2cap_debugfs_fops);
-		if (!l2cap_debugfs)
-			BT_ERR("Failed to create L2CAP debug file");
-	}
-
-	BT_INFO("L2CAP ver %s", VERSION);
-	BT_INFO("L2CAP socket layer initialized");
-
-	return 0;
-
-error:
-	destroy_workqueue(_busy_wq);
-	proto_unregister(&l2cap_proto);
-	return err;
-}
-
-static void __exit l2cap_exit(void)
-{
-	debugfs_remove(l2cap_debugfs);
-
-	flush_workqueue(_busy_wq);
-	destroy_workqueue(_busy_wq);
-
-	if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
-		BT_ERR("L2CAP socket unregistration failed");
-
-	if (hci_unregister_proto(&l2cap_hci_proto) < 0)
-		BT_ERR("L2CAP protocol unregistration failed");
-
-	proto_unregister(&l2cap_proto);
-}
-
-void l2cap_load(void)
-{
-	/* Dummy function to trigger automatic L2CAP module loading by
-	 * other modules that use L2CAP sockets but don't use any other
-	 * symbols from it. */
-}
-EXPORT_SYMBOL(l2cap_load);
-
-module_init(l2cap_init);
-module_exit(l2cap_exit);
-
-module_param(disable_ertm, bool, 0644);
-MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
-
-MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
-MODULE_DESCRIPTION("Bluetooth L2CAP ver " VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("bt-proto-0");
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
new file mode 100644
index 0000000..c9f9cec
--- /dev/null
+++ b/net/bluetooth/l2cap_core.c
@@ -0,0 +1,4059 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2000-2001 Qualcomm Incorporated
+   Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
+   Copyright (C) 2010 Google Inc.
+
+   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
+/* Bluetooth L2CAP core. */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/fcntl.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/socket.h>
+#include <linux/skbuff.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/crc16.h>
+#include <net/sock.h>
+
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+
+int disable_ertm;
+
+static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
+static u8 l2cap_fixed_chan[8] = { 0x02, };
+
+static struct workqueue_struct *_busy_wq;
+
+struct bt_sock_list l2cap_sk_list = {
+	.lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock)
+};
+
+static void l2cap_busy_work(struct work_struct *work);
+
+static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
+				u8 code, u8 ident, u16 dlen, void *data);
+
+static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
+
+/* ---- L2CAP channels ---- */
+static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
+{
+	struct sock *s;
+	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
+		if (l2cap_pi(s)->dcid == cid)
+			break;
+	}
+	return s;
+}
+
+static struct sock *__l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
+{
+	struct sock *s;
+	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
+		if (l2cap_pi(s)->scid == cid)
+			break;
+	}
+	return s;
+}
+
+/* Find channel with given SCID.
+ * Returns locked socket */
+static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 cid)
+{
+	struct sock *s;
+	read_lock(&l->lock);
+	s = __l2cap_get_chan_by_scid(l, cid);
+	if (s)
+		bh_lock_sock(s);
+	read_unlock(&l->lock);
+	return s;
+}
+
+static struct sock *__l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
+{
+	struct sock *s;
+	for (s = l->head; s; s = l2cap_pi(s)->next_c) {
+		if (l2cap_pi(s)->ident == ident)
+			break;
+	}
+	return s;
+}
+
+static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ident)
+{
+	struct sock *s;
+	read_lock(&l->lock);
+	s = __l2cap_get_chan_by_ident(l, ident);
+	if (s)
+		bh_lock_sock(s);
+	read_unlock(&l->lock);
+	return s;
+}
+
+static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
+{
+	u16 cid = L2CAP_CID_DYN_START;
+
+	for (; cid < L2CAP_CID_DYN_END; cid++) {
+		if (!__l2cap_get_chan_by_scid(l, cid))
+			return cid;
+	}
+
+	return 0;
+}
+
+static inline void __l2cap_chan_link(struct l2cap_chan_list *l, struct sock *sk)
+{
+	sock_hold(sk);
+
+	if (l->head)
+		l2cap_pi(l->head)->prev_c = sk;
+
+	l2cap_pi(sk)->next_c = l->head;
+	l2cap_pi(sk)->prev_c = NULL;
+	l->head = sk;
+}
+
+static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
+{
+	struct sock *next = l2cap_pi(sk)->next_c, *prev = l2cap_pi(sk)->prev_c;
+
+	write_lock_bh(&l->lock);
+	if (sk == l->head)
+		l->head = next;
+
+	if (next)
+		l2cap_pi(next)->prev_c = prev;
+	if (prev)
+		l2cap_pi(prev)->next_c = next;
+	write_unlock_bh(&l->lock);
+
+	__sock_put(sk);
+}
+
+static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+
+	BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
+			l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
+
+	conn->disc_reason = 0x13;
+
+	l2cap_pi(sk)->conn = conn;
+
+	if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
+		if (conn->hcon->type == LE_LINK) {
+			/* LE connection */
+			l2cap_pi(sk)->omtu = L2CAP_LE_DEFAULT_MTU;
+			l2cap_pi(sk)->scid = L2CAP_CID_LE_DATA;
+			l2cap_pi(sk)->dcid = L2CAP_CID_LE_DATA;
+		} else {
+			/* Alloc CID for connection-oriented socket */
+			l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
+			l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+		}
+	} else if (sk->sk_type == SOCK_DGRAM) {
+		/* Connectionless socket */
+		l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
+		l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
+		l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+	} else {
+		/* Raw socket can send/recv signalling messages only */
+		l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
+		l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
+		l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
+	}
+
+	__l2cap_chan_link(l, sk);
+
+	if (parent)
+		bt_accept_enqueue(parent, sk);
+}
+
+/* Delete channel.
+ * Must be called on the locked socket. */
+void l2cap_chan_del(struct sock *sk, int err)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sock *parent = bt_sk(sk)->parent;
+
+	l2cap_sock_clear_timer(sk);
+
+	BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
+
+	if (conn) {
+		/* Unlink from channel list */
+		l2cap_chan_unlink(&conn->chan_list, sk);
+		l2cap_pi(sk)->conn = NULL;
+		hci_conn_put(conn->hcon);
+	}
+
+	sk->sk_state = BT_CLOSED;
+	sock_set_flag(sk, SOCK_ZAPPED);
+
+	if (err)
+		sk->sk_err = err;
+
+	if (parent) {
+		bt_accept_unlink(sk);
+		parent->sk_data_ready(parent, 0);
+	} else
+		sk->sk_state_change(sk);
+
+	skb_queue_purge(TX_QUEUE(sk));
+
+	if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+		struct srej_list *l, *tmp;
+
+		del_timer(&l2cap_pi(sk)->retrans_timer);
+		del_timer(&l2cap_pi(sk)->monitor_timer);
+		del_timer(&l2cap_pi(sk)->ack_timer);
+
+		skb_queue_purge(SREJ_QUEUE(sk));
+		skb_queue_purge(BUSY_QUEUE(sk));
+
+		list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
+			list_del(&l->list);
+			kfree(l);
+		}
+	}
+}
+
+static inline u8 l2cap_get_auth_type(struct sock *sk)
+{
+	if (sk->sk_type == SOCK_RAW) {
+		switch (l2cap_pi(sk)->sec_level) {
+		case BT_SECURITY_HIGH:
+			return HCI_AT_DEDICATED_BONDING_MITM;
+		case BT_SECURITY_MEDIUM:
+			return HCI_AT_DEDICATED_BONDING;
+		default:
+			return HCI_AT_NO_BONDING;
+		}
+	} else if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001)) {
+		if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+
+		if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+			return HCI_AT_NO_BONDING_MITM;
+		else
+			return HCI_AT_NO_BONDING;
+	} else {
+		switch (l2cap_pi(sk)->sec_level) {
+		case BT_SECURITY_HIGH:
+			return HCI_AT_GENERAL_BONDING_MITM;
+		case BT_SECURITY_MEDIUM:
+			return HCI_AT_GENERAL_BONDING;
+		default:
+			return HCI_AT_NO_BONDING;
+		}
+	}
+}
+
+/* Service level security */
+static inline int l2cap_check_security(struct sock *sk)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	__u8 auth_type;
+
+	auth_type = l2cap_get_auth_type(sk);
+
+	return hci_conn_security(conn->hcon, l2cap_pi(sk)->sec_level,
+								auth_type);
+}
+
+u8 l2cap_get_ident(struct l2cap_conn *conn)
+{
+	u8 id;
+
+	/* Get next available identificator.
+	 *    1 - 128 are used by kernel.
+	 *  129 - 199 are reserved.
+	 *  200 - 254 are used by utilities like l2ping, etc.
+	 */
+
+	spin_lock_bh(&conn->lock);
+
+	if (++conn->tx_ident > 128)
+		conn->tx_ident = 1;
+
+	id = conn->tx_ident;
+
+	spin_unlock_bh(&conn->lock);
+
+	return id;
+}
+
+void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+{
+	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
+	u8 flags;
+
+	BT_DBG("code 0x%2.2x", code);
+
+	if (!skb)
+		return;
+
+	if (lmp_no_flush_capable(conn->hcon->hdev))
+		flags = ACL_START_NO_FLUSH;
+	else
+		flags = ACL_START;
+
+	hci_send_acl(conn->hcon, skb, flags);
+}
+
+static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
+{
+	struct sk_buff *skb;
+	struct l2cap_hdr *lh;
+	struct l2cap_conn *conn = pi->conn;
+	struct sock *sk = (struct sock *)pi;
+	int count, hlen = L2CAP_HDR_SIZE + 2;
+	u8 flags;
+
+	if (sk->sk_state != BT_CONNECTED)
+		return;
+
+	if (pi->fcs == L2CAP_FCS_CRC16)
+		hlen += 2;
+
+	BT_DBG("pi %p, control 0x%2.2x", pi, control);
+
+	count = min_t(unsigned int, conn->mtu, hlen);
+	control |= L2CAP_CTRL_FRAME_TYPE;
+
+	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+		control |= L2CAP_CTRL_FINAL;
+		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+	}
+
+	if (pi->conn_state & L2CAP_CONN_SEND_PBIT) {
+		control |= L2CAP_CTRL_POLL;
+		pi->conn_state &= ~L2CAP_CONN_SEND_PBIT;
+	}
+
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(pi->dcid);
+	put_unaligned_le16(control, skb_put(skb, 2));
+
+	if (pi->fcs == L2CAP_FCS_CRC16) {
+		u16 fcs = crc16(0, (u8 *)lh, count - 2);
+		put_unaligned_le16(fcs, skb_put(skb, 2));
+	}
+
+	if (lmp_no_flush_capable(conn->hcon->hdev))
+		flags = ACL_START_NO_FLUSH;
+	else
+		flags = ACL_START;
+
+	hci_send_acl(pi->conn->hcon, skb, flags);
+}
+
+static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
+{
+	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+		control |= L2CAP_SUPER_RCV_NOT_READY;
+		pi->conn_state |= L2CAP_CONN_RNR_SENT;
+	} else
+		control |= L2CAP_SUPER_RCV_READY;
+
+	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	l2cap_send_sframe(pi, control);
+}
+
+static inline int __l2cap_no_conn_pending(struct sock *sk)
+{
+	return !(l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND);
+}
+
+static void l2cap_do_start(struct sock *sk)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+
+	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) {
+		if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE))
+			return;
+
+		if (l2cap_check_security(sk) && __l2cap_no_conn_pending(sk)) {
+			struct l2cap_conn_req req;
+			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+			req.psm  = l2cap_pi(sk)->psm;
+
+			l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+
+			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_REQ, sizeof(req), &req);
+		}
+	} else {
+		struct l2cap_info_req req;
+		req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+
+		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
+		conn->info_ident = l2cap_get_ident(conn);
+
+		mod_timer(&conn->info_timer, jiffies +
+					msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
+
+		l2cap_send_cmd(conn, conn->info_ident,
+					L2CAP_INFO_REQ, sizeof(req), &req);
+	}
+}
+
+static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
+{
+	u32 local_feat_mask = l2cap_feat_mask;
+	if (!disable_ertm)
+		local_feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING;
+
+	switch (mode) {
+	case L2CAP_MODE_ERTM:
+		return L2CAP_FEAT_ERTM & feat_mask & local_feat_mask;
+	case L2CAP_MODE_STREAMING:
+		return L2CAP_FEAT_STREAMING & feat_mask & local_feat_mask;
+	default:
+		return 0x00;
+	}
+}
+
+void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err)
+{
+	struct l2cap_disconn_req req;
+
+	if (!conn)
+		return;
+
+	skb_queue_purge(TX_QUEUE(sk));
+
+	if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM) {
+		del_timer(&l2cap_pi(sk)->retrans_timer);
+		del_timer(&l2cap_pi(sk)->monitor_timer);
+		del_timer(&l2cap_pi(sk)->ack_timer);
+	}
+
+	req.dcid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+	l2cap_send_cmd(conn, l2cap_get_ident(conn),
+			L2CAP_DISCONN_REQ, sizeof(req), &req);
+
+	sk->sk_state = BT_DISCONN;
+	sk->sk_err = err;
+}
+
+/* ---- L2CAP connections ---- */
+static void l2cap_conn_start(struct l2cap_conn *conn)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+	struct sock_del_list del, *tmp1, *tmp2;
+	struct sock *sk;
+
+	BT_DBG("conn %p", conn);
+
+	INIT_LIST_HEAD(&del.list);
+
+	read_lock(&l->lock);
+
+	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+		bh_lock_sock(sk);
+
+		if (sk->sk_type != SOCK_SEQPACKET &&
+				sk->sk_type != SOCK_STREAM) {
+			bh_unlock_sock(sk);
+			continue;
+		}
+
+		if (sk->sk_state == BT_CONNECT) {
+			struct l2cap_conn_req req;
+
+			if (!l2cap_check_security(sk) ||
+					!__l2cap_no_conn_pending(sk)) {
+				bh_unlock_sock(sk);
+				continue;
+			}
+
+			if (!l2cap_mode_supported(l2cap_pi(sk)->mode,
+					conn->feat_mask)
+					&& l2cap_pi(sk)->conf_state &
+					L2CAP_CONF_STATE2_DEVICE) {
+				tmp1 = kzalloc(sizeof(struct sock_del_list),
+						GFP_ATOMIC);
+				tmp1->sk = sk;
+				list_add_tail(&tmp1->list, &del.list);
+				bh_unlock_sock(sk);
+				continue;
+			}
+
+			req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+			req.psm  = l2cap_pi(sk)->psm;
+
+			l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+			l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+
+			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+				L2CAP_CONN_REQ, sizeof(req), &req);
+
+		} else if (sk->sk_state == BT_CONNECT2) {
+			struct l2cap_conn_rsp rsp;
+			char buf[128];
+			rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
+			rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+
+			if (l2cap_check_security(sk)) {
+				if (bt_sk(sk)->defer_setup) {
+					struct sock *parent = bt_sk(sk)->parent;
+					rsp.result = cpu_to_le16(L2CAP_CR_PEND);
+					rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
+					parent->sk_data_ready(parent, 0);
+
+				} else {
+					sk->sk_state = BT_CONFIG;
+					rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+					rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+				}
+			} else {
+				rsp.result = cpu_to_le16(L2CAP_CR_PEND);
+				rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
+			}
+
+			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+			if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT ||
+					rsp.result != L2CAP_CR_SUCCESS) {
+				bh_unlock_sock(sk);
+				continue;
+			}
+
+			l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+						l2cap_build_conf_req(sk, buf), buf);
+			l2cap_pi(sk)->num_conf_req++;
+		}
+
+		bh_unlock_sock(sk);
+	}
+
+	read_unlock(&l->lock);
+
+	list_for_each_entry_safe(tmp1, tmp2, &del.list, list) {
+		bh_lock_sock(tmp1->sk);
+		__l2cap_sock_close(tmp1->sk, ECONNRESET);
+		bh_unlock_sock(tmp1->sk);
+		list_del(&tmp1->list);
+		kfree(tmp1);
+	}
+}
+
+/* Find socket with cid and source bdaddr.
+ * Returns closest match, locked.
+ */
+static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src)
+{
+	struct sock *s, *sk = NULL, *sk1 = NULL;
+	struct hlist_node *node;
+
+	read_lock(&l2cap_sk_list.lock);
+
+	sk_for_each(sk, node, &l2cap_sk_list.head) {
+		if (state && sk->sk_state != state)
+			continue;
+
+		if (l2cap_pi(sk)->scid == cid) {
+			/* Exact match. */
+			if (!bacmp(&bt_sk(sk)->src, src))
+				break;
+
+			/* Closest match */
+			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
+				sk1 = sk;
+		}
+	}
+	s = node ? sk : sk1;
+	if (s)
+		bh_lock_sock(s);
+	read_unlock(&l2cap_sk_list.lock);
+
+	return s;
+}
+
+static void l2cap_le_conn_ready(struct l2cap_conn *conn)
+{
+	struct l2cap_chan_list *list = &conn->chan_list;
+	struct sock *parent, *uninitialized_var(sk);
+
+	BT_DBG("");
+
+	/* Check if we have socket listening on cid */
+	parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA,
+							conn->src);
+	if (!parent)
+		return;
+
+	/* Check for backlog size */
+	if (sk_acceptq_is_full(parent)) {
+		BT_DBG("backlog full %d", parent->sk_ack_backlog);
+		goto clean;
+	}
+
+	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
+	if (!sk)
+		goto clean;
+
+	write_lock_bh(&list->lock);
+
+	hci_conn_hold(conn->hcon);
+
+	l2cap_sock_init(sk, parent);
+	bacpy(&bt_sk(sk)->src, conn->src);
+	bacpy(&bt_sk(sk)->dst, conn->dst);
+
+	__l2cap_chan_add(conn, sk, parent);
+
+	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
+	sk->sk_state = BT_CONNECTED;
+	parent->sk_data_ready(parent, 0);
+
+	write_unlock_bh(&list->lock);
+
+clean:
+	bh_unlock_sock(parent);
+}
+
+static void l2cap_conn_ready(struct l2cap_conn *conn)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+	struct sock *sk;
+
+	BT_DBG("conn %p", conn);
+
+	if (!conn->hcon->out && conn->hcon->type == LE_LINK)
+		l2cap_le_conn_ready(conn);
+
+	read_lock(&l->lock);
+
+	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+		bh_lock_sock(sk);
+
+		if (conn->hcon->type == LE_LINK) {
+			l2cap_sock_clear_timer(sk);
+			sk->sk_state = BT_CONNECTED;
+			sk->sk_state_change(sk);
+		}
+
+		if (sk->sk_type != SOCK_SEQPACKET &&
+				sk->sk_type != SOCK_STREAM) {
+			l2cap_sock_clear_timer(sk);
+			sk->sk_state = BT_CONNECTED;
+			sk->sk_state_change(sk);
+		} else if (sk->sk_state == BT_CONNECT)
+			l2cap_do_start(sk);
+
+		bh_unlock_sock(sk);
+	}
+
+	read_unlock(&l->lock);
+}
+
+/* Notify sockets that we cannot guaranty reliability anymore */
+static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+	struct sock *sk;
+
+	BT_DBG("conn %p", conn);
+
+	read_lock(&l->lock);
+
+	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+		if (l2cap_pi(sk)->force_reliable)
+			sk->sk_err = err;
+	}
+
+	read_unlock(&l->lock);
+}
+
+static void l2cap_info_timeout(unsigned long arg)
+{
+	struct l2cap_conn *conn = (void *) arg;
+
+	conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+	conn->info_ident = 0;
+
+	l2cap_conn_start(conn);
+}
+
+static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
+{
+	struct l2cap_conn *conn = hcon->l2cap_data;
+
+	if (conn || status)
+		return conn;
+
+	conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC);
+	if (!conn)
+		return NULL;
+
+	hcon->l2cap_data = conn;
+	conn->hcon = hcon;
+
+	BT_DBG("hcon %p conn %p", hcon, conn);
+
+	if (hcon->hdev->le_mtu && hcon->type == LE_LINK)
+		conn->mtu = hcon->hdev->le_mtu;
+	else
+		conn->mtu = hcon->hdev->acl_mtu;
+
+	conn->src = &hcon->hdev->bdaddr;
+	conn->dst = &hcon->dst;
+
+	conn->feat_mask = 0;
+
+	spin_lock_init(&conn->lock);
+	rwlock_init(&conn->chan_list.lock);
+
+	if (hcon->type != LE_LINK)
+		setup_timer(&conn->info_timer, l2cap_info_timeout,
+						(unsigned long) conn);
+
+	conn->disc_reason = 0x13;
+
+	return conn;
+}
+
+static void l2cap_conn_del(struct hci_conn *hcon, int err)
+{
+	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct sock *sk;
+
+	if (!conn)
+		return;
+
+	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
+
+	kfree_skb(conn->rx_skb);
+
+	/* Kill channels */
+	while ((sk = conn->chan_list.head)) {
+		bh_lock_sock(sk);
+		l2cap_chan_del(sk, err);
+		bh_unlock_sock(sk);
+		l2cap_sock_kill(sk);
+	}
+
+	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
+		del_timer_sync(&conn->info_timer);
+
+	hcon->l2cap_data = NULL;
+	kfree(conn);
+}
+
+static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+	write_lock_bh(&l->lock);
+	__l2cap_chan_add(conn, sk, parent);
+	write_unlock_bh(&l->lock);
+}
+
+/* ---- Socket interface ---- */
+
+/* Find socket with psm and source bdaddr.
+ * Returns closest match.
+ */
+static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
+{
+	struct sock *sk = NULL, *sk1 = NULL;
+	struct hlist_node *node;
+
+	read_lock(&l2cap_sk_list.lock);
+
+	sk_for_each(sk, node, &l2cap_sk_list.head) {
+		if (state && sk->sk_state != state)
+			continue;
+
+		if (l2cap_pi(sk)->psm == psm) {
+			/* Exact match. */
+			if (!bacmp(&bt_sk(sk)->src, src))
+				break;
+
+			/* Closest match */
+			if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY))
+				sk1 = sk;
+		}
+	}
+
+	read_unlock(&l2cap_sk_list.lock);
+
+	return node ? sk : sk1;
+}
+
+int l2cap_do_connect(struct sock *sk)
+{
+	bdaddr_t *src = &bt_sk(sk)->src;
+	bdaddr_t *dst = &bt_sk(sk)->dst;
+	struct l2cap_conn *conn;
+	struct hci_conn *hcon;
+	struct hci_dev *hdev;
+	__u8 auth_type;
+	int err;
+
+	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
+							l2cap_pi(sk)->psm);
+
+	hdev = hci_get_route(dst, src);
+	if (!hdev)
+		return -EHOSTUNREACH;
+
+	hci_dev_lock_bh(hdev);
+
+	auth_type = l2cap_get_auth_type(sk);
+
+	if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
+		hcon = hci_connect(hdev, LE_LINK, dst,
+					l2cap_pi(sk)->sec_level, auth_type);
+	else
+		hcon = hci_connect(hdev, ACL_LINK, dst,
+					l2cap_pi(sk)->sec_level, auth_type);
+
+	if (IS_ERR(hcon)) {
+		err = PTR_ERR(hcon);
+		goto done;
+	}
+
+	conn = l2cap_conn_add(hcon, 0);
+	if (!conn) {
+		hci_conn_put(hcon);
+		err = -ENOMEM;
+		goto done;
+	}
+
+	/* Update source addr of the socket */
+	bacpy(src, conn->src);
+
+	l2cap_chan_add(conn, sk, NULL);
+
+	sk->sk_state = BT_CONNECT;
+	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
+	if (hcon->state == BT_CONNECTED) {
+		if (sk->sk_type != SOCK_SEQPACKET &&
+				sk->sk_type != SOCK_STREAM) {
+			l2cap_sock_clear_timer(sk);
+			if (l2cap_check_security(sk))
+				sk->sk_state = BT_CONNECTED;
+		} else
+			l2cap_do_start(sk);
+	}
+
+	err = 0;
+
+done:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+	return err;
+}
+
+int __l2cap_wait_ack(struct sock *sk)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int err = 0;
+	int timeo = HZ/5;
+
+	add_wait_queue(sk_sleep(sk), &wait);
+	while ((l2cap_pi(sk)->unacked_frames > 0 && l2cap_pi(sk)->conn)) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (!timeo)
+			timeo = HZ/5;
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+
+		err = sock_error(sk);
+		if (err)
+			break;
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+	return err;
+}
+
+static void l2cap_monitor_timeout(unsigned long arg)
+{
+	struct sock *sk = (void *) arg;
+
+	BT_DBG("sk %p", sk);
+
+	bh_lock_sock(sk);
+	if (l2cap_pi(sk)->retry_count >= l2cap_pi(sk)->remote_max_tx) {
+		l2cap_send_disconn_req(l2cap_pi(sk)->conn, sk, ECONNABORTED);
+		bh_unlock_sock(sk);
+		return;
+	}
+
+	l2cap_pi(sk)->retry_count++;
+	__mod_monitor_timer();
+
+	l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
+	bh_unlock_sock(sk);
+}
+
+static void l2cap_retrans_timeout(unsigned long arg)
+{
+	struct sock *sk = (void *) arg;
+
+	BT_DBG("sk %p", sk);
+
+	bh_lock_sock(sk);
+	l2cap_pi(sk)->retry_count = 1;
+	__mod_monitor_timer();
+
+	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+
+	l2cap_send_rr_or_rnr(l2cap_pi(sk), L2CAP_CTRL_POLL);
+	bh_unlock_sock(sk);
+}
+
+static void l2cap_drop_acked_frames(struct sock *sk)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_peek(TX_QUEUE(sk))) &&
+			l2cap_pi(sk)->unacked_frames) {
+		if (bt_cb(skb)->tx_seq == l2cap_pi(sk)->expected_ack_seq)
+			break;
+
+		skb = skb_dequeue(TX_QUEUE(sk));
+		kfree_skb(skb);
+
+		l2cap_pi(sk)->unacked_frames--;
+	}
+
+	if (!l2cap_pi(sk)->unacked_frames)
+		del_timer(&l2cap_pi(sk)->retrans_timer);
+}
+
+void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct hci_conn *hcon = pi->conn->hcon;
+	u16 flags;
+
+	BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
+
+	if (!pi->flushable && lmp_no_flush_capable(hcon->hdev))
+		flags = ACL_START_NO_FLUSH;
+	else
+		flags = ACL_START;
+
+	hci_send_acl(hcon, skb, flags);
+}
+
+void l2cap_streaming_send(struct sock *sk)
+{
+	struct sk_buff *skb;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control, fcs;
+
+	while ((skb = skb_dequeue(TX_QUEUE(sk)))) {
+		control = get_unaligned_le16(skb->data + L2CAP_HDR_SIZE);
+		control |= pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT;
+		put_unaligned_le16(control, skb->data + L2CAP_HDR_SIZE);
+
+		if (pi->fcs == L2CAP_FCS_CRC16) {
+			fcs = crc16(0, (u8 *)skb->data, skb->len - 2);
+			put_unaligned_le16(fcs, skb->data + skb->len - 2);
+		}
+
+		l2cap_do_send(sk, skb);
+
+		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
+	}
+}
+
+static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *skb, *tx_skb;
+	u16 control, fcs;
+
+	skb = skb_peek(TX_QUEUE(sk));
+	if (!skb)
+		return;
+
+	do {
+		if (bt_cb(skb)->tx_seq == tx_seq)
+			break;
+
+		if (skb_queue_is_last(TX_QUEUE(sk), skb))
+			return;
+
+	} while ((skb = skb_queue_next(TX_QUEUE(sk), skb)));
+
+	if (pi->remote_max_tx &&
+			bt_cb(skb)->retries == pi->remote_max_tx) {
+		l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
+		return;
+	}
+
+	tx_skb = skb_clone(skb, GFP_ATOMIC);
+	bt_cb(skb)->retries++;
+	control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+
+	if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+		control |= L2CAP_CTRL_FINAL;
+		pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+	}
+
+	control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+			| (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+
+	put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
+
+	if (pi->fcs == L2CAP_FCS_CRC16) {
+		fcs = crc16(0, (u8 *)tx_skb->data, tx_skb->len - 2);
+		put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
+	}
+
+	l2cap_do_send(sk, tx_skb);
+}
+
+int l2cap_ertm_send(struct sock *sk)
+{
+	struct sk_buff *skb, *tx_skb;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control, fcs;
+	int nsent = 0;
+
+	if (sk->sk_state != BT_CONNECTED)
+		return -ENOTCONN;
+
+	while ((skb = sk->sk_send_head) && (!l2cap_tx_window_full(sk))) {
+
+		if (pi->remote_max_tx &&
+				bt_cb(skb)->retries == pi->remote_max_tx) {
+			l2cap_send_disconn_req(pi->conn, sk, ECONNABORTED);
+			break;
+		}
+
+		tx_skb = skb_clone(skb, GFP_ATOMIC);
+
+		bt_cb(skb)->retries++;
+
+		control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+		control &= L2CAP_CTRL_SAR;
+
+		if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
+			control |= L2CAP_CTRL_FINAL;
+			pi->conn_state &= ~L2CAP_CONN_SEND_FBIT;
+		}
+		control |= (pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
+				| (pi->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
+		put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
+
+
+		if (pi->fcs == L2CAP_FCS_CRC16) {
+			fcs = crc16(0, (u8 *)skb->data, tx_skb->len - 2);
+			put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
+		}
+
+		l2cap_do_send(sk, tx_skb);
+
+		__mod_retrans_timer();
+
+		bt_cb(skb)->tx_seq = pi->next_tx_seq;
+		pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
+
+		pi->unacked_frames++;
+		pi->frames_sent++;
+
+		if (skb_queue_is_last(TX_QUEUE(sk), skb))
+			sk->sk_send_head = NULL;
+		else
+			sk->sk_send_head = skb_queue_next(TX_QUEUE(sk), skb);
+
+		nsent++;
+	}
+
+	return nsent;
+}
+
+static int l2cap_retransmit_frames(struct sock *sk)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int ret;
+
+	if (!skb_queue_empty(TX_QUEUE(sk)))
+		sk->sk_send_head = TX_QUEUE(sk)->next;
+
+	pi->next_tx_seq = pi->expected_ack_seq;
+	ret = l2cap_ertm_send(sk);
+	return ret;
+}
+
+static void l2cap_send_ack(struct l2cap_pinfo *pi)
+{
+	struct sock *sk = (struct sock *)pi;
+	u16 control = 0;
+
+	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+		control |= L2CAP_SUPER_RCV_NOT_READY;
+		pi->conn_state |= L2CAP_CONN_RNR_SENT;
+		l2cap_send_sframe(pi, control);
+		return;
+	}
+
+	if (l2cap_ertm_send(sk) > 0)
+		return;
+
+	control |= L2CAP_SUPER_RCV_READY;
+	l2cap_send_sframe(pi, control);
+}
+
+static void l2cap_send_srejtail(struct sock *sk)
+{
+	struct srej_list *tail;
+	u16 control;
+
+	control = L2CAP_SUPER_SELECT_REJECT;
+	control |= L2CAP_CTRL_FINAL;
+
+	tail = list_entry(SREJ_LIST(sk)->prev, struct srej_list, list);
+	control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	l2cap_send_sframe(l2cap_pi(sk), control);
+}
+
+static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff **frag;
+	int err, sent = 0;
+
+	if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count))
+		return -EFAULT;
+
+	sent += count;
+	len  -= count;
+
+	/* Continuation fragments (no L2CAP header) */
+	frag = &skb_shinfo(skb)->frag_list;
+	while (len) {
+		count = min_t(unsigned int, conn->mtu, len);
+
+		*frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err);
+		if (!*frag)
+			return err;
+		if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count))
+			return -EFAULT;
+
+		sent += count;
+		len  -= count;
+
+		frag = &(*frag)->next;
+	}
+
+	return sent;
+}
+
+struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb;
+	int err, count, hlen = L2CAP_HDR_SIZE + 2;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, (int)len);
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+	skb = bt_skb_send_alloc(sk, count + hlen,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return ERR_PTR(err);
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+	put_unaligned_le16(l2cap_pi(sk)->psm, skb_put(skb, 2));
+
+	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
+	if (unlikely(err < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(err);
+	}
+	return skb;
+}
+
+struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb;
+	int err, count, hlen = L2CAP_HDR_SIZE;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, (int)len);
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+	skb = bt_skb_send_alloc(sk, count + hlen,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return ERR_PTR(err);
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+
+	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
+	if (unlikely(err < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(err);
+	}
+	return skb;
+}
+
+struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg, size_t len, u16 control, u16 sdulen)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+	struct sk_buff *skb;
+	int err, count, hlen = L2CAP_HDR_SIZE + 2;
+	struct l2cap_hdr *lh;
+
+	BT_DBG("sk %p len %d", sk, (int)len);
+
+	if (!conn)
+		return ERR_PTR(-ENOTCONN);
+
+	if (sdulen)
+		hlen += 2;
+
+	if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
+		hlen += 2;
+
+	count = min_t(unsigned int, (conn->mtu - hlen), len);
+	skb = bt_skb_send_alloc(sk, count + hlen,
+			msg->msg_flags & MSG_DONTWAIT, &err);
+	if (!skb)
+		return ERR_PTR(err);
+
+	/* Create L2CAP header */
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	lh->len = cpu_to_le16(len + (hlen - L2CAP_HDR_SIZE));
+	put_unaligned_le16(control, skb_put(skb, 2));
+	if (sdulen)
+		put_unaligned_le16(sdulen, skb_put(skb, 2));
+
+	err = l2cap_skbuff_fromiovec(sk, msg, len, count, skb);
+	if (unlikely(err < 0)) {
+		kfree_skb(skb);
+		return ERR_PTR(err);
+	}
+
+	if (l2cap_pi(sk)->fcs == L2CAP_FCS_CRC16)
+		put_unaligned_le16(0, skb_put(skb, 2));
+
+	bt_cb(skb)->retries = 0;
+	return skb;
+}
+
+int l2cap_sar_segment_sdu(struct sock *sk, struct msghdr *msg, size_t len)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *skb;
+	struct sk_buff_head sar_queue;
+	u16 control;
+	size_t size = 0;
+
+	skb_queue_head_init(&sar_queue);
+	control = L2CAP_SDU_START;
+	skb = l2cap_create_iframe_pdu(sk, msg, pi->remote_mps, control, len);
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	__skb_queue_tail(&sar_queue, skb);
+	len -= pi->remote_mps;
+	size += pi->remote_mps;
+
+	while (len > 0) {
+		size_t buflen;
+
+		if (len > pi->remote_mps) {
+			control = L2CAP_SDU_CONTINUE;
+			buflen = pi->remote_mps;
+		} else {
+			control = L2CAP_SDU_END;
+			buflen = len;
+		}
+
+		skb = l2cap_create_iframe_pdu(sk, msg, buflen, control, 0);
+		if (IS_ERR(skb)) {
+			skb_queue_purge(&sar_queue);
+			return PTR_ERR(skb);
+		}
+
+		__skb_queue_tail(&sar_queue, skb);
+		len -= buflen;
+		size += buflen;
+	}
+	skb_queue_splice_tail(&sar_queue, TX_QUEUE(sk));
+	if (sk->sk_send_head == NULL)
+		sk->sk_send_head = sar_queue.next;
+
+	return size;
+}
+
+static void l2cap_chan_ready(struct sock *sk)
+{
+	struct sock *parent = bt_sk(sk)->parent;
+
+	BT_DBG("sk %p, parent %p", sk, parent);
+
+	l2cap_pi(sk)->conf_state = 0;
+	l2cap_sock_clear_timer(sk);
+
+	if (!parent) {
+		/* Outgoing channel.
+		 * Wake up socket sleeping on connect.
+		 */
+		sk->sk_state = BT_CONNECTED;
+		sk->sk_state_change(sk);
+	} else {
+		/* Incoming channel.
+		 * Wake up socket sleeping on accept.
+		 */
+		parent->sk_data_ready(parent, 0);
+	}
+}
+
+/* Copy frame to all raw sockets on that connection */
+static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct l2cap_chan_list *l = &conn->chan_list;
+	struct sk_buff *nskb;
+	struct sock *sk;
+
+	BT_DBG("conn %p", conn);
+
+	read_lock(&l->lock);
+	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+		if (sk->sk_type != SOCK_RAW)
+			continue;
+
+		/* Don't send frame to the socket it came from */
+		if (skb->sk == sk)
+			continue;
+		nskb = skb_clone(skb, GFP_ATOMIC);
+		if (!nskb)
+			continue;
+
+		if (sock_queue_rcv_skb(sk, nskb))
+			kfree_skb(nskb);
+	}
+	read_unlock(&l->lock);
+}
+
+/* ---- L2CAP signalling commands ---- */
+static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
+				u8 code, u8 ident, u16 dlen, void *data)
+{
+	struct sk_buff *skb, **frag;
+	struct l2cap_cmd_hdr *cmd;
+	struct l2cap_hdr *lh;
+	int len, count;
+
+	BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
+			conn, code, ident, dlen);
+
+	len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
+	count = min_t(unsigned int, conn->mtu, len);
+
+	skb = bt_skb_alloc(count, GFP_ATOMIC);
+	if (!skb)
+		return NULL;
+
+	lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+	lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
+
+	if (conn->hcon->type == LE_LINK)
+		lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING);
+	else
+		lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
+
+	cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
+	cmd->code  = code;
+	cmd->ident = ident;
+	cmd->len   = cpu_to_le16(dlen);
+
+	if (dlen) {
+		count -= L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE;
+		memcpy(skb_put(skb, count), data, count);
+		data += count;
+	}
+
+	len -= skb->len;
+
+	/* Continuation fragments (no L2CAP header) */
+	frag = &skb_shinfo(skb)->frag_list;
+	while (len) {
+		count = min_t(unsigned int, conn->mtu, len);
+
+		*frag = bt_skb_alloc(count, GFP_ATOMIC);
+		if (!*frag)
+			goto fail;
+
+		memcpy(skb_put(*frag, count), data, count);
+
+		len  -= count;
+		data += count;
+
+		frag = &(*frag)->next;
+	}
+
+	return skb;
+
+fail:
+	kfree_skb(skb);
+	return NULL;
+}
+
+static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val)
+{
+	struct l2cap_conf_opt *opt = *ptr;
+	int len;
+
+	len = L2CAP_CONF_OPT_SIZE + opt->len;
+	*ptr += len;
+
+	*type = opt->type;
+	*olen = opt->len;
+
+	switch (opt->len) {
+	case 1:
+		*val = *((u8 *) opt->val);
+		break;
+
+	case 2:
+		*val = get_unaligned_le16(opt->val);
+		break;
+
+	case 4:
+		*val = get_unaligned_le32(opt->val);
+		break;
+
+	default:
+		*val = (unsigned long) opt->val;
+		break;
+	}
+
+	BT_DBG("type 0x%2.2x len %d val 0x%lx", *type, opt->len, *val);
+	return len;
+}
+
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
+{
+	struct l2cap_conf_opt *opt = *ptr;
+
+	BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
+
+	opt->type = type;
+	opt->len  = len;
+
+	switch (len) {
+	case 1:
+		*((u8 *) opt->val)  = val;
+		break;
+
+	case 2:
+		put_unaligned_le16(val, opt->val);
+		break;
+
+	case 4:
+		put_unaligned_le32(val, opt->val);
+		break;
+
+	default:
+		memcpy(opt->val, (void *) val, len);
+		break;
+	}
+
+	*ptr += L2CAP_CONF_OPT_SIZE + len;
+}
+
+static void l2cap_ack_timeout(unsigned long arg)
+{
+	struct sock *sk = (void *) arg;
+
+	bh_lock_sock(sk);
+	l2cap_send_ack(l2cap_pi(sk));
+	bh_unlock_sock(sk);
+}
+
+static inline void l2cap_ertm_init(struct sock *sk)
+{
+	l2cap_pi(sk)->expected_ack_seq = 0;
+	l2cap_pi(sk)->unacked_frames = 0;
+	l2cap_pi(sk)->buffer_seq = 0;
+	l2cap_pi(sk)->num_acked = 0;
+	l2cap_pi(sk)->frames_sent = 0;
+
+	setup_timer(&l2cap_pi(sk)->retrans_timer,
+			l2cap_retrans_timeout, (unsigned long) sk);
+	setup_timer(&l2cap_pi(sk)->monitor_timer,
+			l2cap_monitor_timeout, (unsigned long) sk);
+	setup_timer(&l2cap_pi(sk)->ack_timer,
+			l2cap_ack_timeout, (unsigned long) sk);
+
+	__skb_queue_head_init(SREJ_QUEUE(sk));
+	__skb_queue_head_init(BUSY_QUEUE(sk));
+
+	INIT_WORK(&l2cap_pi(sk)->busy_work, l2cap_busy_work);
+
+	sk->sk_backlog_rcv = l2cap_ertm_data_rcv;
+}
+
+static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
+{
+	switch (mode) {
+	case L2CAP_MODE_STREAMING:
+	case L2CAP_MODE_ERTM:
+		if (l2cap_mode_supported(mode, remote_feat_mask))
+			return mode;
+		/* fall through */
+	default:
+		return L2CAP_MODE_BASIC;
+	}
+}
+
+int l2cap_build_conf_req(struct sock *sk, void *data)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_conf_req *req = data;
+	struct l2cap_conf_rfc rfc = { .mode = pi->mode };
+	void *ptr = req->data;
+
+	BT_DBG("sk %p", sk);
+
+	if (pi->num_conf_req || pi->num_conf_rsp)
+		goto done;
+
+	switch (pi->mode) {
+	case L2CAP_MODE_STREAMING:
+	case L2CAP_MODE_ERTM:
+		if (pi->conf_state & L2CAP_CONF_STATE2_DEVICE)
+			break;
+
+		/* fall through */
+	default:
+		pi->mode = l2cap_select_mode(rfc.mode, pi->conn->feat_mask);
+		break;
+	}
+
+done:
+	if (pi->imtu != L2CAP_DEFAULT_MTU)
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+
+	switch (pi->mode) {
+	case L2CAP_MODE_BASIC:
+		if (!(pi->conn->feat_mask & L2CAP_FEAT_ERTM) &&
+				!(pi->conn->feat_mask & L2CAP_FEAT_STREAMING))
+			break;
+
+		rfc.mode            = L2CAP_MODE_BASIC;
+		rfc.txwin_size      = 0;
+		rfc.max_transmit    = 0;
+		rfc.retrans_timeout = 0;
+		rfc.monitor_timeout = 0;
+		rfc.max_pdu_size    = 0;
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+							(unsigned long) &rfc);
+		break;
+
+	case L2CAP_MODE_ERTM:
+		rfc.mode            = L2CAP_MODE_ERTM;
+		rfc.txwin_size      = pi->tx_win;
+		rfc.max_transmit    = pi->max_tx;
+		rfc.retrans_timeout = 0;
+		rfc.monitor_timeout = 0;
+		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+		if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
+			rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+							(unsigned long) &rfc);
+
+		if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
+			break;
+
+		if (pi->fcs == L2CAP_FCS_NONE ||
+				pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+			pi->fcs = L2CAP_FCS_NONE;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+		}
+		break;
+
+	case L2CAP_MODE_STREAMING:
+		rfc.mode            = L2CAP_MODE_STREAMING;
+		rfc.txwin_size      = 0;
+		rfc.max_transmit    = 0;
+		rfc.retrans_timeout = 0;
+		rfc.monitor_timeout = 0;
+		rfc.max_pdu_size    = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+		if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->conn->mtu - 10)
+			rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
+							(unsigned long) &rfc);
+
+		if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
+			break;
+
+		if (pi->fcs == L2CAP_FCS_NONE ||
+				pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+			pi->fcs = L2CAP_FCS_NONE;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+		}
+		break;
+	}
+
+	req->dcid  = cpu_to_le16(pi->dcid);
+	req->flags = cpu_to_le16(0);
+
+	return ptr - data;
+}
+
+static int l2cap_parse_conf_req(struct sock *sk, void *data)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_conf_rsp *rsp = data;
+	void *ptr = rsp->data;
+	void *req = pi->conf_req;
+	int len = pi->conf_len;
+	int type, hint, olen;
+	unsigned long val;
+	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
+	u16 mtu = L2CAP_DEFAULT_MTU;
+	u16 result = L2CAP_CONF_SUCCESS;
+
+	BT_DBG("sk %p", sk);
+
+	while (len >= L2CAP_CONF_OPT_SIZE) {
+		len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
+
+		hint  = type & L2CAP_CONF_HINT;
+		type &= L2CAP_CONF_MASK;
+
+		switch (type) {
+		case L2CAP_CONF_MTU:
+			mtu = val;
+			break;
+
+		case L2CAP_CONF_FLUSH_TO:
+			pi->flush_to = val;
+			break;
+
+		case L2CAP_CONF_QOS:
+			break;
+
+		case L2CAP_CONF_RFC:
+			if (olen == sizeof(rfc))
+				memcpy(&rfc, (void *) val, olen);
+			break;
+
+		case L2CAP_CONF_FCS:
+			if (val == L2CAP_FCS_NONE)
+				pi->conf_state |= L2CAP_CONF_NO_FCS_RECV;
+
+			break;
+
+		default:
+			if (hint)
+				break;
+
+			result = L2CAP_CONF_UNKNOWN;
+			*((u8 *) ptr++) = type;
+			break;
+		}
+	}
+
+	if (pi->num_conf_rsp || pi->num_conf_req > 1)
+		goto done;
+
+	switch (pi->mode) {
+	case L2CAP_MODE_STREAMING:
+	case L2CAP_MODE_ERTM:
+		if (!(pi->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
+			pi->mode = l2cap_select_mode(rfc.mode,
+					pi->conn->feat_mask);
+			break;
+		}
+
+		if (pi->mode != rfc.mode)
+			return -ECONNREFUSED;
+
+		break;
+	}
+
+done:
+	if (pi->mode != rfc.mode) {
+		result = L2CAP_CONF_UNACCEPT;
+		rfc.mode = pi->mode;
+
+		if (pi->num_conf_rsp == 1)
+			return -ECONNREFUSED;
+
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+	}
+
+
+	if (result == L2CAP_CONF_SUCCESS) {
+		/* Configure output options and let the other side know
+		 * which ones we don't like. */
+
+		if (mtu < L2CAP_DEFAULT_MIN_MTU)
+			result = L2CAP_CONF_UNACCEPT;
+		else {
+			pi->omtu = mtu;
+			pi->conf_state |= L2CAP_CONF_MTU_DONE;
+		}
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+
+		switch (rfc.mode) {
+		case L2CAP_MODE_BASIC:
+			pi->fcs = L2CAP_FCS_NONE;
+			pi->conf_state |= L2CAP_CONF_MODE_DONE;
+			break;
+
+		case L2CAP_MODE_ERTM:
+			pi->remote_tx_win = rfc.txwin_size;
+			pi->remote_max_tx = rfc.max_transmit;
+
+			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
+				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+
+			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
+
+			rfc.retrans_timeout =
+				le16_to_cpu(L2CAP_DEFAULT_RETRANS_TO);
+			rfc.monitor_timeout =
+				le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
+
+			pi->conf_state |= L2CAP_CONF_MODE_DONE;
+
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+
+			break;
+
+		case L2CAP_MODE_STREAMING:
+			if (le16_to_cpu(rfc.max_pdu_size) > pi->conn->mtu - 10)
+				rfc.max_pdu_size = cpu_to_le16(pi->conn->mtu - 10);
+
+			pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
+
+			pi->conf_state |= L2CAP_CONF_MODE_DONE;
+
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+
+			break;
+
+		default:
+			result = L2CAP_CONF_UNACCEPT;
+
+			memset(&rfc, 0, sizeof(rfc));
+			rfc.mode = pi->mode;
+		}
+
+		if (result == L2CAP_CONF_SUCCESS)
+			pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+	}
+	rsp->scid   = cpu_to_le16(pi->dcid);
+	rsp->result = cpu_to_le16(result);
+	rsp->flags  = cpu_to_le16(0x0000);
+
+	return ptr - data;
+}
+
+static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct l2cap_conf_req *req = data;
+	void *ptr = req->data;
+	int type, olen;
+	unsigned long val;
+	struct l2cap_conf_rfc rfc;
+
+	BT_DBG("sk %p, rsp %p, len %d, req %p", sk, rsp, len, data);
+
+	while (len >= L2CAP_CONF_OPT_SIZE) {
+		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
+
+		switch (type) {
+		case L2CAP_CONF_MTU:
+			if (val < L2CAP_DEFAULT_MIN_MTU) {
+				*result = L2CAP_CONF_UNACCEPT;
+				pi->imtu = L2CAP_DEFAULT_MIN_MTU;
+			} else
+				pi->imtu = val;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+			break;
+
+		case L2CAP_CONF_FLUSH_TO:
+			pi->flush_to = val;
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
+							2, pi->flush_to);
+			break;
+
+		case L2CAP_CONF_RFC:
+			if (olen == sizeof(rfc))
+				memcpy(&rfc, (void *)val, olen);
+
+			if ((pi->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
+							rfc.mode != pi->mode)
+				return -ECONNREFUSED;
+
+			pi->fcs = 0;
+
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+					sizeof(rfc), (unsigned long) &rfc);
+			break;
+		}
+	}
+
+	if (pi->mode == L2CAP_MODE_BASIC && pi->mode != rfc.mode)
+		return -ECONNREFUSED;
+
+	pi->mode = rfc.mode;
+
+	if (*result == L2CAP_CONF_SUCCESS) {
+		switch (rfc.mode) {
+		case L2CAP_MODE_ERTM:
+			pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+			pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
+			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
+			break;
+		case L2CAP_MODE_STREAMING:
+			pi->mps    = le16_to_cpu(rfc.max_pdu_size);
+		}
+	}
+
+	req->dcid   = cpu_to_le16(pi->dcid);
+	req->flags  = cpu_to_le16(0x0000);
+
+	return ptr - data;
+}
+
+static int l2cap_build_conf_rsp(struct sock *sk, void *data, u16 result, u16 flags)
+{
+	struct l2cap_conf_rsp *rsp = data;
+	void *ptr = rsp->data;
+
+	BT_DBG("sk %p", sk);
+
+	rsp->scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+	rsp->result = cpu_to_le16(result);
+	rsp->flags  = cpu_to_le16(flags);
+
+	return ptr - data;
+}
+
+static void l2cap_conf_rfc_get(struct sock *sk, void *rsp, int len)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int type, olen;
+	unsigned long val;
+	struct l2cap_conf_rfc rfc;
+
+	BT_DBG("sk %p, rsp %p, len %d", sk, rsp, len);
+
+	if ((pi->mode != L2CAP_MODE_ERTM) && (pi->mode != L2CAP_MODE_STREAMING))
+		return;
+
+	while (len >= L2CAP_CONF_OPT_SIZE) {
+		len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
+
+		switch (type) {
+		case L2CAP_CONF_RFC:
+			if (olen == sizeof(rfc))
+				memcpy(&rfc, (void *)val, olen);
+			goto done;
+		}
+	}
+
+done:
+	switch (rfc.mode) {
+	case L2CAP_MODE_ERTM:
+		pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+		pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
+		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
+		break;
+	case L2CAP_MODE_STREAMING:
+		pi->mps    = le16_to_cpu(rfc.max_pdu_size);
+	}
+}
+
+static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_cmd_rej *rej = (struct l2cap_cmd_rej *) data;
+
+	if (rej->reason != 0x0000)
+		return 0;
+
+	if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) &&
+					cmd->ident == conn->info_ident) {
+		del_timer(&conn->info_timer);
+
+		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+		conn->info_ident = 0;
+
+		l2cap_conn_start(conn);
+	}
+
+	return 0;
+}
+
+static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_chan_list *list = &conn->chan_list;
+	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
+	struct l2cap_conn_rsp rsp;
+	struct sock *parent, *sk = NULL;
+	int result, status = L2CAP_CS_NO_INFO;
+
+	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
+	__le16 psm = req->psm;
+
+	BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
+
+	/* Check if we have socket listening on psm */
+	parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src);
+	if (!parent) {
+		result = L2CAP_CR_BAD_PSM;
+		goto sendresp;
+	}
+
+	bh_lock_sock(parent);
+
+	/* Check if the ACL is secure enough (if not SDP) */
+	if (psm != cpu_to_le16(0x0001) &&
+				!hci_conn_check_link_mode(conn->hcon)) {
+		conn->disc_reason = 0x05;
+		result = L2CAP_CR_SEC_BLOCK;
+		goto response;
+	}
+
+	result = L2CAP_CR_NO_MEM;
+
+	/* Check for backlog size */
+	if (sk_acceptq_is_full(parent)) {
+		BT_DBG("backlog full %d", parent->sk_ack_backlog);
+		goto response;
+	}
+
+	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
+	if (!sk)
+		goto response;
+
+	write_lock_bh(&list->lock);
+
+	/* Check if we already have channel with that dcid */
+	if (__l2cap_get_chan_by_dcid(list, scid)) {
+		write_unlock_bh(&list->lock);
+		sock_set_flag(sk, SOCK_ZAPPED);
+		l2cap_sock_kill(sk);
+		goto response;
+	}
+
+	hci_conn_hold(conn->hcon);
+
+	l2cap_sock_init(sk, parent);
+	bacpy(&bt_sk(sk)->src, conn->src);
+	bacpy(&bt_sk(sk)->dst, conn->dst);
+	l2cap_pi(sk)->psm  = psm;
+	l2cap_pi(sk)->dcid = scid;
+
+	__l2cap_chan_add(conn, sk, parent);
+	dcid = l2cap_pi(sk)->scid;
+
+	l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
+	l2cap_pi(sk)->ident = cmd->ident;
+
+	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
+		if (l2cap_check_security(sk)) {
+			if (bt_sk(sk)->defer_setup) {
+				sk->sk_state = BT_CONNECT2;
+				result = L2CAP_CR_PEND;
+				status = L2CAP_CS_AUTHOR_PEND;
+				parent->sk_data_ready(parent, 0);
+			} else {
+				sk->sk_state = BT_CONFIG;
+				result = L2CAP_CR_SUCCESS;
+				status = L2CAP_CS_NO_INFO;
+			}
+		} else {
+			sk->sk_state = BT_CONNECT2;
+			result = L2CAP_CR_PEND;
+			status = L2CAP_CS_AUTHEN_PEND;
+		}
+	} else {
+		sk->sk_state = BT_CONNECT2;
+		result = L2CAP_CR_PEND;
+		status = L2CAP_CS_NO_INFO;
+	}
+
+	write_unlock_bh(&list->lock);
+
+response:
+	bh_unlock_sock(parent);
+
+sendresp:
+	rsp.scid   = cpu_to_le16(scid);
+	rsp.dcid   = cpu_to_le16(dcid);
+	rsp.result = cpu_to_le16(result);
+	rsp.status = cpu_to_le16(status);
+	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+	if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
+		struct l2cap_info_req info;
+		info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+
+		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT;
+		conn->info_ident = l2cap_get_ident(conn);
+
+		mod_timer(&conn->info_timer, jiffies +
+					msecs_to_jiffies(L2CAP_INFO_TIMEOUT));
+
+		l2cap_send_cmd(conn, conn->info_ident,
+					L2CAP_INFO_REQ, sizeof(info), &info);
+	}
+
+	if (sk && !(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) &&
+				result == L2CAP_CR_SUCCESS) {
+		u8 buf[128];
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+					l2cap_build_conf_req(sk, buf), buf);
+		l2cap_pi(sk)->num_conf_req++;
+	}
+
+	return 0;
+}
+
+static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
+	u16 scid, dcid, result, status;
+	struct sock *sk;
+	u8 req[128];
+
+	scid   = __le16_to_cpu(rsp->scid);
+	dcid   = __le16_to_cpu(rsp->dcid);
+	result = __le16_to_cpu(rsp->result);
+	status = __le16_to_cpu(rsp->status);
+
+	BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
+
+	if (scid) {
+		sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
+		if (!sk)
+			return -EFAULT;
+	} else {
+		sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
+		if (!sk)
+			return -EFAULT;
+	}
+
+	switch (result) {
+	case L2CAP_CR_SUCCESS:
+		sk->sk_state = BT_CONFIG;
+		l2cap_pi(sk)->ident = 0;
+		l2cap_pi(sk)->dcid = dcid;
+		l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
+
+		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)
+			break;
+
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+					l2cap_build_conf_req(sk, req), req);
+		l2cap_pi(sk)->num_conf_req++;
+		break;
+
+	case L2CAP_CR_PEND:
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+		break;
+
+	default:
+		/* don't delete l2cap channel if sk is owned by user */
+		if (sock_owned_by_user(sk)) {
+			sk->sk_state = BT_DISCONN;
+			l2cap_sock_clear_timer(sk);
+			l2cap_sock_set_timer(sk, HZ / 5);
+			break;
+		}
+
+		l2cap_chan_del(sk, ECONNREFUSED);
+		break;
+	}
+
+	bh_unlock_sock(sk);
+	return 0;
+}
+
+static inline void set_default_fcs(struct l2cap_pinfo *pi)
+{
+	/* FCS is enabled only in ERTM or streaming mode, if one or both
+	 * sides request it.
+	 */
+	if (pi->mode != L2CAP_MODE_ERTM && pi->mode != L2CAP_MODE_STREAMING)
+		pi->fcs = L2CAP_FCS_NONE;
+	else if (!(pi->conf_state & L2CAP_CONF_NO_FCS_RECV))
+		pi->fcs = L2CAP_FCS_CRC16;
+}
+
+static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
+{
+	struct l2cap_conf_req *req = (struct l2cap_conf_req *) data;
+	u16 dcid, flags;
+	u8 rsp[64];
+	struct sock *sk;
+	int len;
+
+	dcid  = __le16_to_cpu(req->dcid);
+	flags = __le16_to_cpu(req->flags);
+
+	BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
+
+	sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
+	if (!sk)
+		return -ENOENT;
+
+	if (sk->sk_state != BT_CONFIG) {
+		struct l2cap_cmd_rej rej;
+
+		rej.reason = cpu_to_le16(0x0002);
+		l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
+				sizeof(rej), &rej);
+		goto unlock;
+	}
+
+	/* Reject if config buffer is too small. */
+	len = cmd_len - sizeof(*req);
+	if (l2cap_pi(sk)->conf_len + len > sizeof(l2cap_pi(sk)->conf_req)) {
+		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
+				l2cap_build_conf_rsp(sk, rsp,
+					L2CAP_CONF_REJECT, flags), rsp);
+		goto unlock;
+	}
+
+	/* Store config. */
+	memcpy(l2cap_pi(sk)->conf_req + l2cap_pi(sk)->conf_len, req->data, len);
+	l2cap_pi(sk)->conf_len += len;
+
+	if (flags & 0x0001) {
+		/* Incomplete config. Send empty response. */
+		l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
+				l2cap_build_conf_rsp(sk, rsp,
+					L2CAP_CONF_SUCCESS, 0x0001), rsp);
+		goto unlock;
+	}
+
+	/* Complete config. */
+	len = l2cap_parse_conf_req(sk, rsp);
+	if (len < 0) {
+		l2cap_send_disconn_req(conn, sk, ECONNRESET);
+		goto unlock;
+	}
+
+	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, len, rsp);
+	l2cap_pi(sk)->num_conf_rsp++;
+
+	/* Reset config buffer. */
+	l2cap_pi(sk)->conf_len = 0;
+
+	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE))
+		goto unlock;
+
+	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) {
+		set_default_fcs(l2cap_pi(sk));
+
+		sk->sk_state = BT_CONNECTED;
+
+		l2cap_pi(sk)->next_tx_seq = 0;
+		l2cap_pi(sk)->expected_tx_seq = 0;
+		__skb_queue_head_init(TX_QUEUE(sk));
+		if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+			l2cap_ertm_init(sk);
+
+		l2cap_chan_ready(sk);
+		goto unlock;
+	}
+
+	if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) {
+		u8 buf[64];
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+					l2cap_build_conf_req(sk, buf), buf);
+		l2cap_pi(sk)->num_conf_req++;
+	}
+
+unlock:
+	bh_unlock_sock(sk);
+	return 0;
+}
+
+static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
+	u16 scid, flags, result;
+	struct sock *sk;
+	int len = cmd->len - sizeof(*rsp);
+
+	scid   = __le16_to_cpu(rsp->scid);
+	flags  = __le16_to_cpu(rsp->flags);
+	result = __le16_to_cpu(rsp->result);
+
+	BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
+			scid, flags, result);
+
+	sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
+	if (!sk)
+		return 0;
+
+	switch (result) {
+	case L2CAP_CONF_SUCCESS:
+		l2cap_conf_rfc_get(sk, rsp->data, len);
+		break;
+
+	case L2CAP_CONF_UNACCEPT:
+		if (l2cap_pi(sk)->num_conf_rsp <= L2CAP_CONF_MAX_CONF_RSP) {
+			char req[64];
+
+			if (len > sizeof(req) - sizeof(struct l2cap_conf_req)) {
+				l2cap_send_disconn_req(conn, sk, ECONNRESET);
+				goto done;
+			}
+
+			/* throw out any old stored conf requests */
+			result = L2CAP_CONF_SUCCESS;
+			len = l2cap_parse_conf_rsp(sk, rsp->data,
+							len, req, &result);
+			if (len < 0) {
+				l2cap_send_disconn_req(conn, sk, ECONNRESET);
+				goto done;
+			}
+
+			l2cap_send_cmd(conn, l2cap_get_ident(conn),
+						L2CAP_CONF_REQ, len, req);
+			l2cap_pi(sk)->num_conf_req++;
+			if (result != L2CAP_CONF_SUCCESS)
+				goto done;
+			break;
+		}
+
+	default:
+		sk->sk_err = ECONNRESET;
+		l2cap_sock_set_timer(sk, HZ * 5);
+		l2cap_send_disconn_req(conn, sk, ECONNRESET);
+		goto done;
+	}
+
+	if (flags & 0x01)
+		goto done;
+
+	l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE;
+
+	if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) {
+		set_default_fcs(l2cap_pi(sk));
+
+		sk->sk_state = BT_CONNECTED;
+		l2cap_pi(sk)->next_tx_seq = 0;
+		l2cap_pi(sk)->expected_tx_seq = 0;
+		__skb_queue_head_init(TX_QUEUE(sk));
+		if (l2cap_pi(sk)->mode ==  L2CAP_MODE_ERTM)
+			l2cap_ertm_init(sk);
+
+		l2cap_chan_ready(sk);
+	}
+
+done:
+	bh_unlock_sock(sk);
+	return 0;
+}
+
+static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
+	struct l2cap_disconn_rsp rsp;
+	u16 dcid, scid;
+	struct sock *sk;
+
+	scid = __le16_to_cpu(req->scid);
+	dcid = __le16_to_cpu(req->dcid);
+
+	BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
+
+	sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
+	if (!sk)
+		return 0;
+
+	rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
+	rsp.scid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
+
+	sk->sk_shutdown = SHUTDOWN_MASK;
+
+	/* don't delete l2cap channel if sk is owned by user */
+	if (sock_owned_by_user(sk)) {
+		sk->sk_state = BT_DISCONN;
+		l2cap_sock_clear_timer(sk);
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		return 0;
+	}
+
+	l2cap_chan_del(sk, ECONNRESET);
+	bh_unlock_sock(sk);
+
+	l2cap_sock_kill(sk);
+	return 0;
+}
+
+static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
+	u16 dcid, scid;
+	struct sock *sk;
+
+	scid = __le16_to_cpu(rsp->scid);
+	dcid = __le16_to_cpu(rsp->dcid);
+
+	BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
+
+	sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
+	if (!sk)
+		return 0;
+
+	/* don't delete l2cap channel if sk is owned by user */
+	if (sock_owned_by_user(sk)) {
+		sk->sk_state = BT_DISCONN;
+		l2cap_sock_clear_timer(sk);
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		return 0;
+	}
+
+	l2cap_chan_del(sk, 0);
+	bh_unlock_sock(sk);
+
+	l2cap_sock_kill(sk);
+	return 0;
+}
+
+static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_info_req *req = (struct l2cap_info_req *) data;
+	u16 type;
+
+	type = __le16_to_cpu(req->type);
+
+	BT_DBG("type 0x%4.4x", type);
+
+	if (type == L2CAP_IT_FEAT_MASK) {
+		u8 buf[8];
+		u32 feat_mask = l2cap_feat_mask;
+		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
+		rsp->type   = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
+		if (!disable_ertm)
+			feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
+							 | L2CAP_FEAT_FCS;
+		put_unaligned_le32(feat_mask, rsp->data);
+		l2cap_send_cmd(conn, cmd->ident,
+					L2CAP_INFO_RSP, sizeof(buf), buf);
+	} else if (type == L2CAP_IT_FIXED_CHAN) {
+		u8 buf[12];
+		struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
+		rsp->type   = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
+		rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
+		memcpy(buf + 4, l2cap_fixed_chan, 8);
+		l2cap_send_cmd(conn, cmd->ident,
+					L2CAP_INFO_RSP, sizeof(buf), buf);
+	} else {
+		struct l2cap_info_rsp rsp;
+		rsp.type   = cpu_to_le16(type);
+		rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP);
+		l2cap_send_cmd(conn, cmd->ident,
+					L2CAP_INFO_RSP, sizeof(rsp), &rsp);
+	}
+
+	return 0;
+}
+
+static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
+	u16 type, result;
+
+	type   = __le16_to_cpu(rsp->type);
+	result = __le16_to_cpu(rsp->result);
+
+	BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
+
+	del_timer(&conn->info_timer);
+
+	if (result != L2CAP_IR_SUCCESS) {
+		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+		conn->info_ident = 0;
+
+		l2cap_conn_start(conn);
+
+		return 0;
+	}
+
+	if (type == L2CAP_IT_FEAT_MASK) {
+		conn->feat_mask = get_unaligned_le32(rsp->data);
+
+		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
+			struct l2cap_info_req req;
+			req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
+
+			conn->info_ident = l2cap_get_ident(conn);
+
+			l2cap_send_cmd(conn, conn->info_ident,
+					L2CAP_INFO_REQ, sizeof(req), &req);
+		} else {
+			conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+			conn->info_ident = 0;
+
+			l2cap_conn_start(conn);
+		}
+	} else if (type == L2CAP_IT_FIXED_CHAN) {
+		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
+		conn->info_ident = 0;
+
+		l2cap_conn_start(conn);
+	}
+
+	return 0;
+}
+
+static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency,
+							u16 to_multiplier)
+{
+	u16 max_latency;
+
+	if (min > max || min < 6 || max > 3200)
+		return -EINVAL;
+
+	if (to_multiplier < 10 || to_multiplier > 3200)
+		return -EINVAL;
+
+	if (max >= to_multiplier * 8)
+		return -EINVAL;
+
+	max_latency = (to_multiplier * 8 / max) - 1;
+	if (latency > 499 || latency > max_latency)
+		return -EINVAL;
+
+	return 0;
+}
+
+static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
+					struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	struct hci_conn *hcon = conn->hcon;
+	struct l2cap_conn_param_update_req *req;
+	struct l2cap_conn_param_update_rsp rsp;
+	u16 min, max, latency, to_multiplier, cmd_len;
+	int err;
+
+	if (!(hcon->link_mode & HCI_LM_MASTER))
+		return -EINVAL;
+
+	cmd_len = __le16_to_cpu(cmd->len);
+	if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
+		return -EPROTO;
+
+	req = (struct l2cap_conn_param_update_req *) data;
+	min		= __le16_to_cpu(req->min);
+	max		= __le16_to_cpu(req->max);
+	latency		= __le16_to_cpu(req->latency);
+	to_multiplier	= __le16_to_cpu(req->to_multiplier);
+
+	BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
+						min, max, latency, to_multiplier);
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	err = l2cap_check_conn_param(min, max, latency, to_multiplier);
+	if (err)
+		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
+	else
+		rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+
+	l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
+							sizeof(rsp), &rsp);
+
+	if (!err)
+		hci_le_conn_update(hcon, min, max, latency, to_multiplier);
+
+	return 0;
+}
+
+static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
+			struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
+{
+	int err = 0;
+
+	switch (cmd->code) {
+	case L2CAP_COMMAND_REJ:
+		l2cap_command_rej(conn, cmd, data);
+		break;
+
+	case L2CAP_CONN_REQ:
+		err = l2cap_connect_req(conn, cmd, data);
+		break;
+
+	case L2CAP_CONN_RSP:
+		err = l2cap_connect_rsp(conn, cmd, data);
+		break;
+
+	case L2CAP_CONF_REQ:
+		err = l2cap_config_req(conn, cmd, cmd_len, data);
+		break;
+
+	case L2CAP_CONF_RSP:
+		err = l2cap_config_rsp(conn, cmd, data);
+		break;
+
+	case L2CAP_DISCONN_REQ:
+		err = l2cap_disconnect_req(conn, cmd, data);
+		break;
+
+	case L2CAP_DISCONN_RSP:
+		err = l2cap_disconnect_rsp(conn, cmd, data);
+		break;
+
+	case L2CAP_ECHO_REQ:
+		l2cap_send_cmd(conn, cmd->ident, L2CAP_ECHO_RSP, cmd_len, data);
+		break;
+
+	case L2CAP_ECHO_RSP:
+		break;
+
+	case L2CAP_INFO_REQ:
+		err = l2cap_information_req(conn, cmd, data);
+		break;
+
+	case L2CAP_INFO_RSP:
+		err = l2cap_information_rsp(conn, cmd, data);
+		break;
+
+	default:
+		BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
+		err = -EINVAL;
+		break;
+	}
+
+	return err;
+}
+
+static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
+					struct l2cap_cmd_hdr *cmd, u8 *data)
+{
+	switch (cmd->code) {
+	case L2CAP_COMMAND_REJ:
+		return 0;
+
+	case L2CAP_CONN_PARAM_UPDATE_REQ:
+		return l2cap_conn_param_update_req(conn, cmd, data);
+
+	case L2CAP_CONN_PARAM_UPDATE_RSP:
+		return 0;
+
+	default:
+		BT_ERR("Unknown LE signaling command 0x%2.2x", cmd->code);
+		return -EINVAL;
+	}
+}
+
+static inline void l2cap_sig_channel(struct l2cap_conn *conn,
+							struct sk_buff *skb)
+{
+	u8 *data = skb->data;
+	int len = skb->len;
+	struct l2cap_cmd_hdr cmd;
+	int err;
+
+	l2cap_raw_recv(conn, skb);
+
+	while (len >= L2CAP_CMD_HDR_SIZE) {
+		u16 cmd_len;
+		memcpy(&cmd, data, L2CAP_CMD_HDR_SIZE);
+		data += L2CAP_CMD_HDR_SIZE;
+		len  -= L2CAP_CMD_HDR_SIZE;
+
+		cmd_len = le16_to_cpu(cmd.len);
+
+		BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident);
+
+		if (cmd_len > len || !cmd.ident) {
+			BT_DBG("corrupted command");
+			break;
+		}
+
+		if (conn->hcon->type == LE_LINK)
+			err = l2cap_le_sig_cmd(conn, &cmd, data);
+		else
+			err = l2cap_bredr_sig_cmd(conn, &cmd, cmd_len, data);
+
+		if (err) {
+			struct l2cap_cmd_rej rej;
+			BT_DBG("error %d", err);
+
+			/* FIXME: Map err to a valid reason */
+			rej.reason = cpu_to_le16(0);
+			l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
+		}
+
+		data += cmd_len;
+		len  -= cmd_len;
+	}
+
+	kfree_skb(skb);
+}
+
+static int l2cap_check_fcs(struct l2cap_pinfo *pi,  struct sk_buff *skb)
+{
+	u16 our_fcs, rcv_fcs;
+	int hdr_size = L2CAP_HDR_SIZE + 2;
+
+	if (pi->fcs == L2CAP_FCS_CRC16) {
+		skb_trim(skb, skb->len - 2);
+		rcv_fcs = get_unaligned_le16(skb->data + skb->len);
+		our_fcs = crc16(0, skb->data - hdr_size, skb->len + hdr_size);
+
+		if (our_fcs != rcv_fcs)
+			return -EBADMSG;
+	}
+	return 0;
+}
+
+static inline void l2cap_send_i_or_rr_or_rnr(struct sock *sk)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control = 0;
+
+	pi->frames_sent = 0;
+
+	control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+
+	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+		control |= L2CAP_SUPER_RCV_NOT_READY;
+		l2cap_send_sframe(pi, control);
+		pi->conn_state |= L2CAP_CONN_RNR_SENT;
+	}
+
+	if (pi->conn_state & L2CAP_CONN_REMOTE_BUSY)
+		l2cap_retransmit_frames(sk);
+
+	l2cap_ertm_send(sk);
+
+	if (!(pi->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
+			pi->frames_sent == 0) {
+		control |= L2CAP_SUPER_RCV_READY;
+		l2cap_send_sframe(pi, control);
+	}
+}
+
+static int l2cap_add_to_srej_queue(struct sock *sk, struct sk_buff *skb, u8 tx_seq, u8 sar)
+{
+	struct sk_buff *next_skb;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int tx_seq_offset, next_tx_seq_offset;
+
+	bt_cb(skb)->tx_seq = tx_seq;
+	bt_cb(skb)->sar = sar;
+
+	next_skb = skb_peek(SREJ_QUEUE(sk));
+	if (!next_skb) {
+		__skb_queue_tail(SREJ_QUEUE(sk), skb);
+		return 0;
+	}
+
+	tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+	if (tx_seq_offset < 0)
+		tx_seq_offset += 64;
+
+	do {
+		if (bt_cb(next_skb)->tx_seq == tx_seq)
+			return -EINVAL;
+
+		next_tx_seq_offset = (bt_cb(next_skb)->tx_seq -
+						pi->buffer_seq) % 64;
+		if (next_tx_seq_offset < 0)
+			next_tx_seq_offset += 64;
+
+		if (next_tx_seq_offset > tx_seq_offset) {
+			__skb_queue_before(SREJ_QUEUE(sk), next_skb, skb);
+			return 0;
+		}
+
+		if (skb_queue_is_last(SREJ_QUEUE(sk), next_skb))
+			break;
+
+	} while ((next_skb = skb_queue_next(SREJ_QUEUE(sk), next_skb)));
+
+	__skb_queue_tail(SREJ_QUEUE(sk), skb);
+
+	return 0;
+}
+
+static int l2cap_ertm_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *_skb;
+	int err;
+
+	switch (control & L2CAP_CTRL_SAR) {
+	case L2CAP_SDU_UNSEGMENTED:
+		if (pi->conn_state & L2CAP_CONN_SAR_SDU)
+			goto drop;
+
+		err = sock_queue_rcv_skb(sk, skb);
+		if (!err)
+			return err;
+
+		break;
+
+	case L2CAP_SDU_START:
+		if (pi->conn_state & L2CAP_CONN_SAR_SDU)
+			goto drop;
+
+		pi->sdu_len = get_unaligned_le16(skb->data);
+
+		if (pi->sdu_len > pi->imtu)
+			goto disconnect;
+
+		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
+		if (!pi->sdu)
+			return -ENOMEM;
+
+		/* pull sdu_len bytes only after alloc, because of Local Busy
+		 * condition we have to be sure that this will be executed
+		 * only once, i.e., when alloc does not fail */
+		skb_pull(skb, 2);
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->conn_state |= L2CAP_CONN_SAR_SDU;
+		pi->partial_sdu_len = skb->len;
+		break;
+
+	case L2CAP_SDU_CONTINUE:
+		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+			goto disconnect;
+
+		if (!pi->sdu)
+			goto disconnect;
+
+		pi->partial_sdu_len += skb->len;
+		if (pi->partial_sdu_len > pi->sdu_len)
+			goto drop;
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		break;
+
+	case L2CAP_SDU_END:
+		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+			goto disconnect;
+
+		if (!pi->sdu)
+			goto disconnect;
+
+		if (!(pi->conn_state & L2CAP_CONN_SAR_RETRY)) {
+			pi->partial_sdu_len += skb->len;
+
+			if (pi->partial_sdu_len > pi->imtu)
+				goto drop;
+
+			if (pi->partial_sdu_len != pi->sdu_len)
+				goto drop;
+
+			memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+		}
+
+		_skb = skb_clone(pi->sdu, GFP_ATOMIC);
+		if (!_skb) {
+			pi->conn_state |= L2CAP_CONN_SAR_RETRY;
+			return -ENOMEM;
+		}
+
+		err = sock_queue_rcv_skb(sk, _skb);
+		if (err < 0) {
+			kfree_skb(_skb);
+			pi->conn_state |= L2CAP_CONN_SAR_RETRY;
+			return err;
+		}
+
+		pi->conn_state &= ~L2CAP_CONN_SAR_RETRY;
+		pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
+
+		kfree_skb(pi->sdu);
+		break;
+	}
+
+	kfree_skb(skb);
+	return 0;
+
+drop:
+	kfree_skb(pi->sdu);
+	pi->sdu = NULL;
+
+disconnect:
+	l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+	kfree_skb(skb);
+	return 0;
+}
+
+static int l2cap_try_push_rx_skb(struct sock *sk)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *skb;
+	u16 control;
+	int err;
+
+	while ((skb = skb_dequeue(BUSY_QUEUE(sk)))) {
+		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
+		err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+		if (err < 0) {
+			skb_queue_head(BUSY_QUEUE(sk), skb);
+			return -EBUSY;
+		}
+
+		pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+	}
+
+	if (!(pi->conn_state & L2CAP_CONN_RNR_SENT))
+		goto done;
+
+	control = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	control |= L2CAP_SUPER_RCV_READY | L2CAP_CTRL_POLL;
+	l2cap_send_sframe(pi, control);
+	l2cap_pi(sk)->retry_count = 1;
+
+	del_timer(&pi->retrans_timer);
+	__mod_monitor_timer();
+
+	l2cap_pi(sk)->conn_state |= L2CAP_CONN_WAIT_F;
+
+done:
+	pi->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
+	pi->conn_state &= ~L2CAP_CONN_RNR_SENT;
+
+	BT_DBG("sk %p, Exit local busy", sk);
+
+	return 0;
+}
+
+static void l2cap_busy_work(struct work_struct *work)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct l2cap_pinfo *pi =
+		container_of(work, struct l2cap_pinfo, busy_work);
+	struct sock *sk = (struct sock *)pi;
+	int n_tries = 0, timeo = HZ/5, err;
+	struct sk_buff *skb;
+
+	lock_sock(sk);
+
+	add_wait_queue(sk_sleep(sk), &wait);
+	while ((skb = skb_peek(BUSY_QUEUE(sk)))) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (n_tries++ > L2CAP_LOCAL_BUSY_TRIES) {
+			err = -EBUSY;
+			l2cap_send_disconn_req(pi->conn, sk, EBUSY);
+			break;
+		}
+
+		if (!timeo)
+			timeo = HZ/5;
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+
+		err = sock_error(sk);
+		if (err)
+			break;
+
+		if (l2cap_try_push_rx_skb(sk) == 0)
+			break;
+	}
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+
+	release_sock(sk);
+}
+
+static int l2cap_push_rx_skb(struct sock *sk, struct sk_buff *skb, u16 control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	int sctrl, err;
+
+	if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+		bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
+		__skb_queue_tail(BUSY_QUEUE(sk), skb);
+		return l2cap_try_push_rx_skb(sk);
+
+
+	}
+
+	err = l2cap_ertm_reassembly_sdu(sk, skb, control);
+	if (err >= 0) {
+		pi->buffer_seq = (pi->buffer_seq + 1) % 64;
+		return err;
+	}
+
+	/* Busy Condition */
+	BT_DBG("sk %p, Enter local busy", sk);
+
+	pi->conn_state |= L2CAP_CONN_LOCAL_BUSY;
+	bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
+	__skb_queue_tail(BUSY_QUEUE(sk), skb);
+
+	sctrl = pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+	sctrl |= L2CAP_SUPER_RCV_NOT_READY;
+	l2cap_send_sframe(pi, sctrl);
+
+	pi->conn_state |= L2CAP_CONN_RNR_SENT;
+
+	del_timer(&pi->ack_timer);
+
+	queue_work(_busy_wq, &pi->busy_work);
+
+	return err;
+}
+
+static int l2cap_streaming_reassembly_sdu(struct sock *sk, struct sk_buff *skb, u16 control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *_skb;
+	int err = -EINVAL;
+
+	/*
+	 * TODO: We have to notify the userland if some data is lost with the
+	 * Streaming Mode.
+	 */
+
+	switch (control & L2CAP_CTRL_SAR) {
+	case L2CAP_SDU_UNSEGMENTED:
+		if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
+			kfree_skb(pi->sdu);
+			break;
+		}
+
+		err = sock_queue_rcv_skb(sk, skb);
+		if (!err)
+			return 0;
+
+		break;
+
+	case L2CAP_SDU_START:
+		if (pi->conn_state & L2CAP_CONN_SAR_SDU) {
+			kfree_skb(pi->sdu);
+			break;
+		}
+
+		pi->sdu_len = get_unaligned_le16(skb->data);
+		skb_pull(skb, 2);
+
+		if (pi->sdu_len > pi->imtu) {
+			err = -EMSGSIZE;
+			break;
+		}
+
+		pi->sdu = bt_skb_alloc(pi->sdu_len, GFP_ATOMIC);
+		if (!pi->sdu) {
+			err = -ENOMEM;
+			break;
+		}
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->conn_state |= L2CAP_CONN_SAR_SDU;
+		pi->partial_sdu_len = skb->len;
+		err = 0;
+		break;
+
+	case L2CAP_SDU_CONTINUE:
+		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+			break;
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->partial_sdu_len += skb->len;
+		if (pi->partial_sdu_len > pi->sdu_len)
+			kfree_skb(pi->sdu);
+		else
+			err = 0;
+
+		break;
+
+	case L2CAP_SDU_END:
+		if (!(pi->conn_state & L2CAP_CONN_SAR_SDU))
+			break;
+
+		memcpy(skb_put(pi->sdu, skb->len), skb->data, skb->len);
+
+		pi->conn_state &= ~L2CAP_CONN_SAR_SDU;
+		pi->partial_sdu_len += skb->len;
+
+		if (pi->partial_sdu_len > pi->imtu)
+			goto drop;
+
+		if (pi->partial_sdu_len == pi->sdu_len) {
+			_skb = skb_clone(pi->sdu, GFP_ATOMIC);
+			err = sock_queue_rcv_skb(sk, _skb);
+			if (err < 0)
+				kfree_skb(_skb);
+		}
+		err = 0;
+
+drop:
+		kfree_skb(pi->sdu);
+		break;
+	}
+
+	kfree_skb(skb);
+	return err;
+}
+
+static void l2cap_check_srej_gap(struct sock *sk, u8 tx_seq)
+{
+	struct sk_buff *skb;
+	u16 control;
+
+	while ((skb = skb_peek(SREJ_QUEUE(sk)))) {
+		if (bt_cb(skb)->tx_seq != tx_seq)
+			break;
+
+		skb = skb_dequeue(SREJ_QUEUE(sk));
+		control = bt_cb(skb)->sar << L2CAP_CTRL_SAR_SHIFT;
+		l2cap_ertm_reassembly_sdu(sk, skb, control);
+		l2cap_pi(sk)->buffer_seq_srej =
+			(l2cap_pi(sk)->buffer_seq_srej + 1) % 64;
+		tx_seq = (tx_seq + 1) % 64;
+	}
+}
+
+static void l2cap_resend_srejframe(struct sock *sk, u8 tx_seq)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct srej_list *l, *tmp;
+	u16 control;
+
+	list_for_each_entry_safe(l, tmp, SREJ_LIST(sk), list) {
+		if (l->tx_seq == tx_seq) {
+			list_del(&l->list);
+			kfree(l);
+			return;
+		}
+		control = L2CAP_SUPER_SELECT_REJECT;
+		control |= l->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+		l2cap_send_sframe(pi, control);
+		list_del(&l->list);
+		list_add_tail(&l->list, SREJ_LIST(sk));
+	}
+}
+
+static void l2cap_send_srejframe(struct sock *sk, u8 tx_seq)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct srej_list *new;
+	u16 control;
+
+	while (tx_seq != pi->expected_tx_seq) {
+		control = L2CAP_SUPER_SELECT_REJECT;
+		control |= pi->expected_tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
+		l2cap_send_sframe(pi, control);
+
+		new = kzalloc(sizeof(struct srej_list), GFP_ATOMIC);
+		new->tx_seq = pi->expected_tx_seq;
+		pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+		list_add_tail(&new->list, SREJ_LIST(sk));
+	}
+	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+}
+
+static inline int l2cap_data_channel_iframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_txseq(rx_control);
+	u8 req_seq = __get_reqseq(rx_control);
+	u8 sar = rx_control >> L2CAP_CTRL_SAR_SHIFT;
+	int tx_seq_offset, expected_tx_seq_offset;
+	int num_to_ack = (pi->tx_win/6) + 1;
+	int err = 0;
+
+	BT_DBG("sk %p len %d tx_seq %d rx_control 0x%4.4x", sk, skb->len, tx_seq,
+								rx_control);
+
+	if (L2CAP_CTRL_FINAL & rx_control &&
+			l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
+		del_timer(&pi->monitor_timer);
+		if (pi->unacked_frames > 0)
+			__mod_retrans_timer();
+		pi->conn_state &= ~L2CAP_CONN_WAIT_F;
+	}
+
+	pi->expected_ack_seq = req_seq;
+	l2cap_drop_acked_frames(sk);
+
+	if (tx_seq == pi->expected_tx_seq)
+		goto expected;
+
+	tx_seq_offset = (tx_seq - pi->buffer_seq) % 64;
+	if (tx_seq_offset < 0)
+		tx_seq_offset += 64;
+
+	/* invalid tx_seq */
+	if (tx_seq_offset >= pi->tx_win) {
+		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+		goto drop;
+	}
+
+	if (pi->conn_state == L2CAP_CONN_LOCAL_BUSY)
+		goto drop;
+
+	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
+		struct srej_list *first;
+
+		first = list_first_entry(SREJ_LIST(sk),
+				struct srej_list, list);
+		if (tx_seq == first->tx_seq) {
+			l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
+			l2cap_check_srej_gap(sk, tx_seq);
+
+			list_del(&first->list);
+			kfree(first);
+
+			if (list_empty(SREJ_LIST(sk))) {
+				pi->buffer_seq = pi->buffer_seq_srej;
+				pi->conn_state &= ~L2CAP_CONN_SREJ_SENT;
+				l2cap_send_ack(pi);
+				BT_DBG("sk %p, Exit SREJ_SENT", sk);
+			}
+		} else {
+			struct srej_list *l;
+
+			/* duplicated tx_seq */
+			if (l2cap_add_to_srej_queue(sk, skb, tx_seq, sar) < 0)
+				goto drop;
+
+			list_for_each_entry(l, SREJ_LIST(sk), list) {
+				if (l->tx_seq == tx_seq) {
+					l2cap_resend_srejframe(sk, tx_seq);
+					return 0;
+				}
+			}
+			l2cap_send_srejframe(sk, tx_seq);
+		}
+	} else {
+		expected_tx_seq_offset =
+			(pi->expected_tx_seq - pi->buffer_seq) % 64;
+		if (expected_tx_seq_offset < 0)
+			expected_tx_seq_offset += 64;
+
+		/* duplicated tx_seq */
+		if (tx_seq_offset < expected_tx_seq_offset)
+			goto drop;
+
+		pi->conn_state |= L2CAP_CONN_SREJ_SENT;
+
+		BT_DBG("sk %p, Enter SREJ", sk);
+
+		INIT_LIST_HEAD(SREJ_LIST(sk));
+		pi->buffer_seq_srej = pi->buffer_seq;
+
+		__skb_queue_head_init(SREJ_QUEUE(sk));
+		__skb_queue_head_init(BUSY_QUEUE(sk));
+		l2cap_add_to_srej_queue(sk, skb, tx_seq, sar);
+
+		pi->conn_state |= L2CAP_CONN_SEND_PBIT;
+
+		l2cap_send_srejframe(sk, tx_seq);
+
+		del_timer(&pi->ack_timer);
+	}
+	return 0;
+
+expected:
+	pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+
+	if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
+		bt_cb(skb)->tx_seq = tx_seq;
+		bt_cb(skb)->sar = sar;
+		__skb_queue_tail(SREJ_QUEUE(sk), skb);
+		return 0;
+	}
+
+	err = l2cap_push_rx_skb(sk, skb, rx_control);
+	if (err < 0)
+		return 0;
+
+	if (rx_control & L2CAP_CTRL_FINAL) {
+		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
+			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+		else
+			l2cap_retransmit_frames(sk);
+	}
+
+	__mod_ack_timer();
+
+	pi->num_acked = (pi->num_acked + 1) % num_to_ack;
+	if (pi->num_acked == num_to_ack - 1)
+		l2cap_send_ack(pi);
+
+	return 0;
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+
+static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+
+	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, __get_reqseq(rx_control),
+						rx_control);
+
+	pi->expected_ack_seq = __get_reqseq(rx_control);
+	l2cap_drop_acked_frames(sk);
+
+	if (rx_control & L2CAP_CTRL_POLL) {
+		pi->conn_state |= L2CAP_CONN_SEND_FBIT;
+		if (pi->conn_state & L2CAP_CONN_SREJ_SENT) {
+			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+					(pi->unacked_frames > 0))
+				__mod_retrans_timer();
+
+			pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+			l2cap_send_srejtail(sk);
+		} else {
+			l2cap_send_i_or_rr_or_rnr(sk);
+		}
+
+	} else if (rx_control & L2CAP_CTRL_FINAL) {
+		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+
+		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
+			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+		else
+			l2cap_retransmit_frames(sk);
+
+	} else {
+		if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+				(pi->unacked_frames > 0))
+			__mod_retrans_timer();
+
+		pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+		if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
+			l2cap_send_ack(pi);
+		else
+			l2cap_ertm_send(sk);
+	}
+}
+
+static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
+
+	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+
+	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+
+	pi->expected_ack_seq = tx_seq;
+	l2cap_drop_acked_frames(sk);
+
+	if (rx_control & L2CAP_CTRL_FINAL) {
+		if (pi->conn_state & L2CAP_CONN_REJ_ACT)
+			pi->conn_state &= ~L2CAP_CONN_REJ_ACT;
+		else
+			l2cap_retransmit_frames(sk);
+	} else {
+		l2cap_retransmit_frames(sk);
+
+		if (pi->conn_state & L2CAP_CONN_WAIT_F)
+			pi->conn_state |= L2CAP_CONN_REJ_ACT;
+	}
+}
+static inline void l2cap_data_channel_srejframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
+
+	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+
+	pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+
+	if (rx_control & L2CAP_CTRL_POLL) {
+		pi->expected_ack_seq = tx_seq;
+		l2cap_drop_acked_frames(sk);
+
+		pi->conn_state |= L2CAP_CONN_SEND_FBIT;
+		l2cap_retransmit_one_frame(sk, tx_seq);
+
+		l2cap_ertm_send(sk);
+
+		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
+			pi->srej_save_reqseq = tx_seq;
+			pi->conn_state |= L2CAP_CONN_SREJ_ACT;
+		}
+	} else if (rx_control & L2CAP_CTRL_FINAL) {
+		if ((pi->conn_state & L2CAP_CONN_SREJ_ACT) &&
+				pi->srej_save_reqseq == tx_seq)
+			pi->conn_state &= ~L2CAP_CONN_SREJ_ACT;
+		else
+			l2cap_retransmit_one_frame(sk, tx_seq);
+	} else {
+		l2cap_retransmit_one_frame(sk, tx_seq);
+		if (pi->conn_state & L2CAP_CONN_WAIT_F) {
+			pi->srej_save_reqseq = tx_seq;
+			pi->conn_state |= L2CAP_CONN_SREJ_ACT;
+		}
+	}
+}
+
+static inline void l2cap_data_channel_rnrframe(struct sock *sk, u16 rx_control)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u8 tx_seq = __get_reqseq(rx_control);
+
+	BT_DBG("sk %p, req_seq %d ctrl 0x%4.4x", sk, tx_seq, rx_control);
+
+	pi->conn_state |= L2CAP_CONN_REMOTE_BUSY;
+	pi->expected_ack_seq = tx_seq;
+	l2cap_drop_acked_frames(sk);
+
+	if (rx_control & L2CAP_CTRL_POLL)
+		pi->conn_state |= L2CAP_CONN_SEND_FBIT;
+
+	if (!(pi->conn_state & L2CAP_CONN_SREJ_SENT)) {
+		del_timer(&pi->retrans_timer);
+		if (rx_control & L2CAP_CTRL_POLL)
+			l2cap_send_rr_or_rnr(pi, L2CAP_CTRL_FINAL);
+		return;
+	}
+
+	if (rx_control & L2CAP_CTRL_POLL)
+		l2cap_send_srejtail(sk);
+	else
+		l2cap_send_sframe(pi, L2CAP_SUPER_RCV_READY);
+}
+
+static inline int l2cap_data_channel_sframe(struct sock *sk, u16 rx_control, struct sk_buff *skb)
+{
+	BT_DBG("sk %p rx_control 0x%4.4x len %d", sk, rx_control, skb->len);
+
+	if (L2CAP_CTRL_FINAL & rx_control &&
+			l2cap_pi(sk)->conn_state & L2CAP_CONN_WAIT_F) {
+		del_timer(&l2cap_pi(sk)->monitor_timer);
+		if (l2cap_pi(sk)->unacked_frames > 0)
+			__mod_retrans_timer();
+		l2cap_pi(sk)->conn_state &= ~L2CAP_CONN_WAIT_F;
+	}
+
+	switch (rx_control & L2CAP_CTRL_SUPERVISE) {
+	case L2CAP_SUPER_RCV_READY:
+		l2cap_data_channel_rrframe(sk, rx_control);
+		break;
+
+	case L2CAP_SUPER_REJECT:
+		l2cap_data_channel_rejframe(sk, rx_control);
+		break;
+
+	case L2CAP_SUPER_SELECT_REJECT:
+		l2cap_data_channel_srejframe(sk, rx_control);
+		break;
+
+	case L2CAP_SUPER_RCV_NOT_READY:
+		l2cap_data_channel_rnrframe(sk, rx_control);
+		break;
+	}
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	u16 control;
+	u8 req_seq;
+	int len, next_tx_seq_offset, req_seq_offset;
+
+	control = get_unaligned_le16(skb->data);
+	skb_pull(skb, 2);
+	len = skb->len;
+
+	/*
+	 * We can just drop the corrupted I-frame here.
+	 * Receiver will miss it and start proper recovery
+	 * procedures and ask retransmission.
+	 */
+	if (l2cap_check_fcs(pi, skb))
+		goto drop;
+
+	if (__is_sar_start(control) && __is_iframe(control))
+		len -= 2;
+
+	if (pi->fcs == L2CAP_FCS_CRC16)
+		len -= 2;
+
+	if (len > pi->mps) {
+		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+		goto drop;
+	}
+
+	req_seq = __get_reqseq(control);
+	req_seq_offset = (req_seq - pi->expected_ack_seq) % 64;
+	if (req_seq_offset < 0)
+		req_seq_offset += 64;
+
+	next_tx_seq_offset =
+		(pi->next_tx_seq - pi->expected_ack_seq) % 64;
+	if (next_tx_seq_offset < 0)
+		next_tx_seq_offset += 64;
+
+	/* check for invalid req-seq */
+	if (req_seq_offset > next_tx_seq_offset) {
+		l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+		goto drop;
+	}
+
+	if (__is_iframe(control)) {
+		if (len < 0) {
+			l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+			goto drop;
+		}
+
+		l2cap_data_channel_iframe(sk, control, skb);
+	} else {
+		if (len != 0) {
+			BT_ERR("%d", len);
+			l2cap_send_disconn_req(pi->conn, sk, ECONNRESET);
+			goto drop;
+		}
+
+		l2cap_data_channel_sframe(sk, control, skb);
+	}
+
+	return 0;
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+
+static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb)
+{
+	struct sock *sk;
+	struct l2cap_pinfo *pi;
+	u16 control;
+	u8 tx_seq;
+	int len;
+
+	sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
+	if (!sk) {
+		BT_DBG("unknown cid 0x%4.4x", cid);
+		goto drop;
+	}
+
+	pi = l2cap_pi(sk);
+
+	BT_DBG("sk %p, len %d", sk, skb->len);
+
+	if (sk->sk_state != BT_CONNECTED)
+		goto drop;
+
+	switch (pi->mode) {
+	case L2CAP_MODE_BASIC:
+		/* If socket recv buffers overflows we drop data here
+		 * which is *bad* because L2CAP has to be reliable.
+		 * But we don't have any other choice. L2CAP doesn't
+		 * provide flow control mechanism. */
+
+		if (pi->imtu < skb->len)
+			goto drop;
+
+		if (!sock_queue_rcv_skb(sk, skb))
+			goto done;
+		break;
+
+	case L2CAP_MODE_ERTM:
+		if (!sock_owned_by_user(sk)) {
+			l2cap_ertm_data_rcv(sk, skb);
+		} else {
+			if (sk_add_backlog(sk, skb))
+				goto drop;
+		}
+
+		goto done;
+
+	case L2CAP_MODE_STREAMING:
+		control = get_unaligned_le16(skb->data);
+		skb_pull(skb, 2);
+		len = skb->len;
+
+		if (l2cap_check_fcs(pi, skb))
+			goto drop;
+
+		if (__is_sar_start(control))
+			len -= 2;
+
+		if (pi->fcs == L2CAP_FCS_CRC16)
+			len -= 2;
+
+		if (len > pi->mps || len < 0 || __is_sframe(control))
+			goto drop;
+
+		tx_seq = __get_txseq(control);
+
+		if (pi->expected_tx_seq == tx_seq)
+			pi->expected_tx_seq = (pi->expected_tx_seq + 1) % 64;
+		else
+			pi->expected_tx_seq = (tx_seq + 1) % 64;
+
+		l2cap_streaming_reassembly_sdu(sk, skb, control);
+
+		goto done;
+
+	default:
+		BT_DBG("sk %p: bad mode 0x%2.2x", sk, pi->mode);
+		break;
+	}
+
+drop:
+	kfree_skb(skb);
+
+done:
+	if (sk)
+		bh_unlock_sock(sk);
+
+	return 0;
+}
+
+static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb)
+{
+	struct sock *sk;
+
+	sk = l2cap_get_sock_by_psm(0, psm, conn->src);
+	if (!sk)
+		goto drop;
+
+	bh_lock_sock(sk);
+
+	BT_DBG("sk %p, len %d", sk, skb->len);
+
+	if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+		goto drop;
+
+	if (l2cap_pi(sk)->imtu < skb->len)
+		goto drop;
+
+	if (!sock_queue_rcv_skb(sk, skb))
+		goto done;
+
+drop:
+	kfree_skb(skb);
+
+done:
+	if (sk)
+		bh_unlock_sock(sk);
+	return 0;
+}
+
+static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+	struct l2cap_hdr *lh = (void *) skb->data;
+	u16 cid, len;
+	__le16 psm;
+
+	skb_pull(skb, L2CAP_HDR_SIZE);
+	cid = __le16_to_cpu(lh->cid);
+	len = __le16_to_cpu(lh->len);
+
+	if (len != skb->len) {
+		kfree_skb(skb);
+		return;
+	}
+
+	BT_DBG("len %d, cid 0x%4.4x", len, cid);
+
+	switch (cid) {
+	case L2CAP_CID_LE_SIGNALING:
+	case L2CAP_CID_SIGNALING:
+		l2cap_sig_channel(conn, skb);
+		break;
+
+	case L2CAP_CID_CONN_LESS:
+		psm = get_unaligned_le16(skb->data);
+		skb_pull(skb, 2);
+		l2cap_conless_channel(conn, psm, skb);
+		break;
+
+	default:
+		l2cap_data_channel(conn, cid, skb);
+		break;
+	}
+}
+
+/* ---- L2CAP interface with lower layer (HCI) ---- */
+
+static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
+{
+	int exact = 0, lm1 = 0, lm2 = 0;
+	register struct sock *sk;
+	struct hlist_node *node;
+
+	if (type != ACL_LINK)
+		return -EINVAL;
+
+	BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
+
+	/* Find listening sockets and check their link_mode */
+	read_lock(&l2cap_sk_list.lock);
+	sk_for_each(sk, node, &l2cap_sk_list.head) {
+		if (sk->sk_state != BT_LISTEN)
+			continue;
+
+		if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
+			lm1 |= HCI_LM_ACCEPT;
+			if (l2cap_pi(sk)->role_switch)
+				lm1 |= HCI_LM_MASTER;
+			exact++;
+		} else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) {
+			lm2 |= HCI_LM_ACCEPT;
+			if (l2cap_pi(sk)->role_switch)
+				lm2 |= HCI_LM_MASTER;
+		}
+	}
+	read_unlock(&l2cap_sk_list.lock);
+
+	return exact ? lm1 : lm2;
+}
+
+static int l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
+{
+	struct l2cap_conn *conn;
+
+	BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
+
+	if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
+		return -EINVAL;
+
+	if (!status) {
+		conn = l2cap_conn_add(hcon, status);
+		if (conn)
+			l2cap_conn_ready(conn);
+	} else
+		l2cap_conn_del(hcon, bt_err(status));
+
+	return 0;
+}
+
+static int l2cap_disconn_ind(struct hci_conn *hcon)
+{
+	struct l2cap_conn *conn = hcon->l2cap_data;
+
+	BT_DBG("hcon %p", hcon);
+
+	if (hcon->type != ACL_LINK || !conn)
+		return 0x13;
+
+	return conn->disc_reason;
+}
+
+static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
+{
+	BT_DBG("hcon %p reason %d", hcon, reason);
+
+	if (!(hcon->type == ACL_LINK || hcon->type == LE_LINK))
+		return -EINVAL;
+
+	l2cap_conn_del(hcon, bt_err(reason));
+
+	return 0;
+}
+
+static inline void l2cap_check_encryption(struct sock *sk, u8 encrypt)
+{
+	if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
+		return;
+
+	if (encrypt == 0x00) {
+		if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM) {
+			l2cap_sock_clear_timer(sk);
+			l2cap_sock_set_timer(sk, HZ * 5);
+		} else if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
+			__l2cap_sock_close(sk, ECONNREFUSED);
+	} else {
+		if (l2cap_pi(sk)->sec_level == BT_SECURITY_MEDIUM)
+			l2cap_sock_clear_timer(sk);
+	}
+}
+
+static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
+{
+	struct l2cap_chan_list *l;
+	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct sock *sk;
+
+	if (!conn)
+		return 0;
+
+	l = &conn->chan_list;
+
+	BT_DBG("conn %p", conn);
+
+	read_lock(&l->lock);
+
+	for (sk = l->head; sk; sk = l2cap_pi(sk)->next_c) {
+		bh_lock_sock(sk);
+
+		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_CONNECT_PEND) {
+			bh_unlock_sock(sk);
+			continue;
+		}
+
+		if (!status && (sk->sk_state == BT_CONNECTED ||
+						sk->sk_state == BT_CONFIG)) {
+			l2cap_check_encryption(sk, encrypt);
+			bh_unlock_sock(sk);
+			continue;
+		}
+
+		if (sk->sk_state == BT_CONNECT) {
+			if (!status) {
+				struct l2cap_conn_req req;
+				req.scid = cpu_to_le16(l2cap_pi(sk)->scid);
+				req.psm  = l2cap_pi(sk)->psm;
+
+				l2cap_pi(sk)->ident = l2cap_get_ident(conn);
+				l2cap_pi(sk)->conf_state |= L2CAP_CONF_CONNECT_PEND;
+
+				l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_REQ, sizeof(req), &req);
+			} else {
+				l2cap_sock_clear_timer(sk);
+				l2cap_sock_set_timer(sk, HZ / 10);
+			}
+		} else if (sk->sk_state == BT_CONNECT2) {
+			struct l2cap_conn_rsp rsp;
+			__u16 result;
+
+			if (!status) {
+				sk->sk_state = BT_CONFIG;
+				result = L2CAP_CR_SUCCESS;
+			} else {
+				sk->sk_state = BT_DISCONN;
+				l2cap_sock_set_timer(sk, HZ / 10);
+				result = L2CAP_CR_SEC_BLOCK;
+			}
+
+			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+			rsp.result = cpu_to_le16(result);
+			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+		}
+
+		bh_unlock_sock(sk);
+	}
+
+	read_unlock(&l->lock);
+
+	return 0;
+}
+
+static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
+{
+	struct l2cap_conn *conn = hcon->l2cap_data;
+
+	if (!conn)
+		conn = l2cap_conn_add(hcon, 0);
+
+	if (!conn)
+		goto drop;
+
+	BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags);
+
+	if (!(flags & ACL_CONT)) {
+		struct l2cap_hdr *hdr;
+		struct sock *sk;
+		u16 cid;
+		int len;
+
+		if (conn->rx_len) {
+			BT_ERR("Unexpected start frame (len %d)", skb->len);
+			kfree_skb(conn->rx_skb);
+			conn->rx_skb = NULL;
+			conn->rx_len = 0;
+			l2cap_conn_unreliable(conn, ECOMM);
+		}
+
+		/* Start fragment always begin with Basic L2CAP header */
+		if (skb->len < L2CAP_HDR_SIZE) {
+			BT_ERR("Frame is too short (len %d)", skb->len);
+			l2cap_conn_unreliable(conn, ECOMM);
+			goto drop;
+		}
+
+		hdr = (struct l2cap_hdr *) skb->data;
+		len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE;
+		cid = __le16_to_cpu(hdr->cid);
+
+		if (len == skb->len) {
+			/* Complete frame received */
+			l2cap_recv_frame(conn, skb);
+			return 0;
+		}
+
+		BT_DBG("Start: total len %d, frag len %d", len, skb->len);
+
+		if (skb->len > len) {
+			BT_ERR("Frame is too long (len %d, expected len %d)",
+				skb->len, len);
+			l2cap_conn_unreliable(conn, ECOMM);
+			goto drop;
+		}
+
+		sk = l2cap_get_chan_by_scid(&conn->chan_list, cid);
+
+		if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) {
+			BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)",
+					len, l2cap_pi(sk)->imtu);
+			bh_unlock_sock(sk);
+			l2cap_conn_unreliable(conn, ECOMM);
+			goto drop;
+		}
+
+		if (sk)
+			bh_unlock_sock(sk);
+
+		/* Allocate skb for the complete frame (with header) */
+		conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
+		if (!conn->rx_skb)
+			goto drop;
+
+		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
+								skb->len);
+		conn->rx_len = len - skb->len;
+	} else {
+		BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len);
+
+		if (!conn->rx_len) {
+			BT_ERR("Unexpected continuation frame (len %d)", skb->len);
+			l2cap_conn_unreliable(conn, ECOMM);
+			goto drop;
+		}
+
+		if (skb->len > conn->rx_len) {
+			BT_ERR("Fragment is too long (len %d, expected %d)",
+					skb->len, conn->rx_len);
+			kfree_skb(conn->rx_skb);
+			conn->rx_skb = NULL;
+			conn->rx_len = 0;
+			l2cap_conn_unreliable(conn, ECOMM);
+			goto drop;
+		}
+
+		skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
+								skb->len);
+		conn->rx_len -= skb->len;
+
+		if (!conn->rx_len) {
+			/* Complete frame received */
+			l2cap_recv_frame(conn, conn->rx_skb);
+			conn->rx_skb = NULL;
+		}
+	}
+
+drop:
+	kfree_skb(skb);
+	return 0;
+}
+
+static int l2cap_debugfs_show(struct seq_file *f, void *p)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+
+	read_lock_bh(&l2cap_sk_list.lock);
+
+	sk_for_each(sk, node, &l2cap_sk_list.head) {
+		struct l2cap_pinfo *pi = l2cap_pi(sk);
+
+		seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
+					batostr(&bt_sk(sk)->src),
+					batostr(&bt_sk(sk)->dst),
+					sk->sk_state, __le16_to_cpu(pi->psm),
+					pi->scid, pi->dcid,
+					pi->imtu, pi->omtu, pi->sec_level,
+					pi->mode);
+	}
+
+	read_unlock_bh(&l2cap_sk_list.lock);
+
+	return 0;
+}
+
+static int l2cap_debugfs_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, l2cap_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations l2cap_debugfs_fops = {
+	.open		= l2cap_debugfs_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static struct dentry *l2cap_debugfs;
+
+static struct hci_proto l2cap_hci_proto = {
+	.name		= "L2CAP",
+	.id		= HCI_PROTO_L2CAP,
+	.connect_ind	= l2cap_connect_ind,
+	.connect_cfm	= l2cap_connect_cfm,
+	.disconn_ind	= l2cap_disconn_ind,
+	.disconn_cfm	= l2cap_disconn_cfm,
+	.security_cfm	= l2cap_security_cfm,
+	.recv_acldata	= l2cap_recv_acldata
+};
+
+int __init l2cap_init(void)
+{
+	int err;
+
+	err = l2cap_init_sockets();
+	if (err < 0)
+		return err;
+
+	_busy_wq = create_singlethread_workqueue("l2cap");
+	if (!_busy_wq) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	err = hci_register_proto(&l2cap_hci_proto);
+	if (err < 0) {
+		BT_ERR("L2CAP protocol registration failed");
+		bt_sock_unregister(BTPROTO_L2CAP);
+		goto error;
+	}
+
+	if (bt_debugfs) {
+		l2cap_debugfs = debugfs_create_file("l2cap", 0444,
+					bt_debugfs, NULL, &l2cap_debugfs_fops);
+		if (!l2cap_debugfs)
+			BT_ERR("Failed to create L2CAP debug file");
+	}
+
+	return 0;
+
+error:
+	destroy_workqueue(_busy_wq);
+	l2cap_cleanup_sockets();
+	return err;
+}
+
+void l2cap_exit(void)
+{
+	debugfs_remove(l2cap_debugfs);
+
+	flush_workqueue(_busy_wq);
+	destroy_workqueue(_busy_wq);
+
+	if (hci_unregister_proto(&l2cap_hci_proto) < 0)
+		BT_ERR("L2CAP protocol unregistration failed");
+
+	l2cap_cleanup_sockets();
+}
+
+module_param(disable_ertm, bool, 0644);
+MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
new file mode 100644
index 0000000..fc85e7a
--- /dev/null
+++ b/net/bluetooth/l2cap_sock.c
@@ -0,0 +1,1156 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2000-2001 Qualcomm Incorporated
+   Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
+   Copyright (C) 2010 Google Inc.
+
+   Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
+/* Bluetooth L2CAP sockets. */
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+
+/* ---- L2CAP timers ---- */
+static void l2cap_sock_timeout(unsigned long arg)
+{
+	struct sock *sk = (struct sock *) arg;
+	int reason;
+
+	BT_DBG("sock %p state %d", sk, sk->sk_state);
+
+	bh_lock_sock(sk);
+
+	if (sock_owned_by_user(sk)) {
+		/* sk is owned by user. Try again later */
+		l2cap_sock_set_timer(sk, HZ / 5);
+		bh_unlock_sock(sk);
+		sock_put(sk);
+		return;
+	}
+
+	if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
+		reason = ECONNREFUSED;
+	else if (sk->sk_state == BT_CONNECT &&
+				l2cap_pi(sk)->sec_level != BT_SECURITY_SDP)
+		reason = ECONNREFUSED;
+	else
+		reason = ETIMEDOUT;
+
+	__l2cap_sock_close(sk, reason);
+
+	bh_unlock_sock(sk);
+
+	l2cap_sock_kill(sk);
+	sock_put(sk);
+}
+
+void l2cap_sock_set_timer(struct sock *sk, long timeout)
+{
+	BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
+	sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
+}
+
+void l2cap_sock_clear_timer(struct sock *sk)
+{
+	BT_DBG("sock %p state %d", sk, sk->sk_state);
+	sk_stop_timer(sk, &sk->sk_timer);
+}
+
+static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+	sk_for_each(sk, node, &l2cap_sk_list.head)
+		if (l2cap_pi(sk)->sport == psm && !bacmp(&bt_sk(sk)->src, src))
+			goto found;
+	sk = NULL;
+found:
+	return sk;
+}
+
+static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_l2 la;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	if (!addr || addr->sa_family != AF_BLUETOOTH)
+		return -EINVAL;
+
+	memset(&la, 0, sizeof(la));
+	len = min_t(unsigned int, sizeof(la), alen);
+	memcpy(&la, addr, len);
+
+	if (la.l2_cid && la.l2_psm)
+		return -EINVAL;
+
+	lock_sock(sk);
+
+	if (sk->sk_state != BT_OPEN) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	if (la.l2_psm) {
+		__u16 psm = __le16_to_cpu(la.l2_psm);
+
+		/* PSM must be odd and lsb of upper byte must be 0 */
+		if ((psm & 0x0101) != 0x0001) {
+			err = -EINVAL;
+			goto done;
+		}
+
+		/* Restrict usage of well-known PSMs */
+		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
+			err = -EACCES;
+			goto done;
+		}
+	}
+
+	write_lock_bh(&l2cap_sk_list.lock);
+
+	if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
+		err = -EADDRINUSE;
+	} else {
+		/* Save source address */
+		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+		l2cap_pi(sk)->psm   = la.l2_psm;
+		l2cap_pi(sk)->sport = la.l2_psm;
+		sk->sk_state = BT_BOUND;
+
+		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
+					__le16_to_cpu(la.l2_psm) == 0x0003)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
+	}
+
+	if (la.l2_cid)
+		l2cap_pi(sk)->scid = la.l2_cid;
+
+	write_unlock_bh(&l2cap_sk_list.lock);
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_l2 la;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	if (!addr || alen < sizeof(addr->sa_family) ||
+	    addr->sa_family != AF_BLUETOOTH)
+		return -EINVAL;
+
+	memset(&la, 0, sizeof(la));
+	len = min_t(unsigned int, sizeof(la), alen);
+	memcpy(&la, addr, len);
+
+	if (la.l2_cid && la.l2_psm)
+		return -EINVAL;
+
+	lock_sock(sk);
+
+	if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
+			&& !(la.l2_psm || la.l2_cid)) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		if (!disable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
+	switch (sk->sk_state) {
+	case BT_CONNECT:
+	case BT_CONNECT2:
+	case BT_CONFIG:
+		/* Already connecting */
+		goto wait;
+
+	case BT_CONNECTED:
+		/* Already connected */
+		err = -EISCONN;
+		goto done;
+
+	case BT_OPEN:
+	case BT_BOUND:
+		/* Can connect */
+		break;
+
+	default:
+		err = -EBADFD;
+		goto done;
+	}
+
+	/* PSM must be odd and lsb of upper byte must be 0 */
+	if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
+				sk->sk_type != SOCK_RAW && !la.l2_cid) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	/* Set destination address and psm */
+	bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
+	l2cap_pi(sk)->psm = la.l2_psm;
+	l2cap_pi(sk)->dcid = la.l2_cid;
+
+	err = l2cap_do_connect(sk);
+	if (err)
+		goto done;
+
+wait:
+	err = bt_sock_wait_state(sk, BT_CONNECTED,
+			sock_sndtimeo(sk, flags & O_NONBLOCK));
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_listen(struct socket *sock, int backlog)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+
+	BT_DBG("sk %p backlog %d", sk, backlog);
+
+	lock_sock(sk);
+
+	if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM)
+			|| sk->sk_state != BT_BOUND) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	switch (l2cap_pi(sk)->mode) {
+	case L2CAP_MODE_BASIC:
+		break;
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		if (!disable_ertm)
+			break;
+		/* fall through */
+	default:
+		err = -ENOTSUPP;
+		goto done;
+	}
+
+	if (!l2cap_pi(sk)->psm && !l2cap_pi(sk)->dcid) {
+		bdaddr_t *src = &bt_sk(sk)->src;
+		u16 psm;
+
+		err = -EINVAL;
+
+		write_lock_bh(&l2cap_sk_list.lock);
+
+		for (psm = 0x1001; psm < 0x1100; psm += 2)
+			if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
+				l2cap_pi(sk)->psm   = cpu_to_le16(psm);
+				l2cap_pi(sk)->sport = cpu_to_le16(psm);
+				err = 0;
+				break;
+			}
+
+		write_unlock_bh(&l2cap_sk_list.lock);
+
+		if (err < 0)
+			goto done;
+	}
+
+	sk->sk_max_ack_backlog = backlog;
+	sk->sk_ack_backlog = 0;
+	sk->sk_state = BT_LISTEN;
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct sock *sk = sock->sk, *nsk;
+	long timeo;
+	int err = 0;
+
+	lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+
+	if (sk->sk_state != BT_LISTEN) {
+		err = -EBADFD;
+		goto done;
+	}
+
+	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
+	BT_DBG("sk %p timeo %ld", sk, timeo);
+
+	/* Wait for an incoming connection. (wake-one). */
+	add_wait_queue_exclusive(sk_sleep(sk), &wait);
+	while (!(nsk = bt_accept_dequeue(sk, newsock))) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!timeo) {
+			err = -EAGAIN;
+			break;
+		}
+
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
+
+		if (sk->sk_state != BT_LISTEN) {
+			err = -EBADFD;
+			break;
+		}
+
+		if (signal_pending(current)) {
+			err = sock_intr_errno(timeo);
+			break;
+		}
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(sk_sleep(sk), &wait);
+
+	if (err)
+		goto done;
+
+	newsock->state = SS_CONNECTED;
+
+	BT_DBG("new socket %p", nsk);
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer)
+{
+	struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr;
+	struct sock *sk = sock->sk;
+
+	BT_DBG("sock %p, sk %p", sock, sk);
+
+	addr->sa_family = AF_BLUETOOTH;
+	*len = sizeof(struct sockaddr_l2);
+
+	if (peer) {
+		la->l2_psm = l2cap_pi(sk)->psm;
+		bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
+		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
+	} else {
+		la->l2_psm = l2cap_pi(sk)->sport;
+		bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
+		la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
+	}
+
+	return 0;
+}
+
+static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct l2cap_options opts;
+	struct l2cap_conninfo cinfo;
+	int len, err = 0;
+	u32 opt;
+
+	BT_DBG("sk %p", sk);
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case L2CAP_OPTIONS:
+		memset(&opts, 0, sizeof(opts));
+		opts.imtu     = l2cap_pi(sk)->imtu;
+		opts.omtu     = l2cap_pi(sk)->omtu;
+		opts.flush_to = l2cap_pi(sk)->flush_to;
+		opts.mode     = l2cap_pi(sk)->mode;
+		opts.fcs      = l2cap_pi(sk)->fcs;
+		opts.max_tx   = l2cap_pi(sk)->max_tx;
+		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+
+		len = min_t(unsigned int, len, sizeof(opts));
+		if (copy_to_user(optval, (char *) &opts, len))
+			err = -EFAULT;
+
+		break;
+
+	case L2CAP_LM:
+		switch (l2cap_pi(sk)->sec_level) {
+		case BT_SECURITY_LOW:
+			opt = L2CAP_LM_AUTH;
+			break;
+		case BT_SECURITY_MEDIUM:
+			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
+			break;
+		case BT_SECURITY_HIGH:
+			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
+							L2CAP_LM_SECURE;
+			break;
+		default:
+			opt = 0;
+			break;
+		}
+
+		if (l2cap_pi(sk)->role_switch)
+			opt |= L2CAP_LM_MASTER;
+
+		if (l2cap_pi(sk)->force_reliable)
+			opt |= L2CAP_LM_RELIABLE;
+
+		if (put_user(opt, (u32 __user *) optval))
+			err = -EFAULT;
+		break;
+
+	case L2CAP_CONNINFO:
+		if (sk->sk_state != BT_CONNECTED &&
+					!(sk->sk_state == BT_CONNECT2 &&
+						bt_sk(sk)->defer_setup)) {
+			err = -ENOTCONN;
+			break;
+		}
+
+		cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
+		memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);
+
+		len = min_t(unsigned int, len, sizeof(cinfo));
+		if (copy_to_user(optval, (char *) &cinfo, len))
+			err = -EFAULT;
+
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
+{
+	struct sock *sk = sock->sk;
+	struct bt_security sec;
+	int len, err = 0;
+
+	BT_DBG("sk %p", sk);
+
+	if (level == SOL_L2CAP)
+		return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);
+
+	if (level != SOL_BLUETOOTH)
+		return -ENOPROTOOPT;
+
+	if (get_user(len, optlen))
+		return -EFAULT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case BT_SECURITY:
+		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+				&& sk->sk_type != SOCK_RAW) {
+			err = -EINVAL;
+			break;
+		}
+
+		sec.level = l2cap_pi(sk)->sec_level;
+
+		len = min_t(unsigned int, len, sizeof(sec));
+		if (copy_to_user(optval, (char *) &sec, len))
+			err = -EFAULT;
+
+		break;
+
+	case BT_DEFER_SETUP:
+		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
+	case BT_FLUSHABLE:
+		if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
+			err = -EFAULT;
+
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct l2cap_options opts;
+	int len, err = 0;
+	u32 opt;
+
+	BT_DBG("sk %p", sk);
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case L2CAP_OPTIONS:
+		if (sk->sk_state == BT_CONNECTED) {
+			err = -EINVAL;
+			break;
+		}
+
+		opts.imtu     = l2cap_pi(sk)->imtu;
+		opts.omtu     = l2cap_pi(sk)->omtu;
+		opts.flush_to = l2cap_pi(sk)->flush_to;
+		opts.mode     = l2cap_pi(sk)->mode;
+		opts.fcs      = l2cap_pi(sk)->fcs;
+		opts.max_tx   = l2cap_pi(sk)->max_tx;
+		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;
+
+		len = min_t(unsigned int, sizeof(opts), optlen);
+		if (copy_from_user((char *) &opts, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opts.txwin_size > L2CAP_DEFAULT_TX_WINDOW) {
+			err = -EINVAL;
+			break;
+		}
+
+		l2cap_pi(sk)->mode = opts.mode;
+		switch (l2cap_pi(sk)->mode) {
+		case L2CAP_MODE_BASIC:
+			l2cap_pi(sk)->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+			break;
+		case L2CAP_MODE_ERTM:
+		case L2CAP_MODE_STREAMING:
+			if (!disable_ertm)
+				break;
+			/* fall through */
+		default:
+			err = -EINVAL;
+			break;
+		}
+
+		l2cap_pi(sk)->imtu = opts.imtu;
+		l2cap_pi(sk)->omtu = opts.omtu;
+		l2cap_pi(sk)->fcs  = opts.fcs;
+		l2cap_pi(sk)->max_tx = opts.max_tx;
+		l2cap_pi(sk)->tx_win = (__u8)opts.txwin_size;
+		break;
+
+	case L2CAP_LM:
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt & L2CAP_LM_AUTH)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_LOW;
+		if (opt & L2CAP_LM_ENCRYPT)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_MEDIUM;
+		if (opt & L2CAP_LM_SECURE)
+			l2cap_pi(sk)->sec_level = BT_SECURITY_HIGH;
+
+		l2cap_pi(sk)->role_switch    = (opt & L2CAP_LM_MASTER);
+		l2cap_pi(sk)->force_reliable = (opt & L2CAP_LM_RELIABLE);
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen)
+{
+	struct sock *sk = sock->sk;
+	struct bt_security sec;
+	int len, err = 0;
+	u32 opt;
+
+	BT_DBG("sk %p", sk);
+
+	if (level == SOL_L2CAP)
+		return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
+
+	if (level != SOL_BLUETOOTH)
+		return -ENOPROTOOPT;
+
+	lock_sock(sk);
+
+	switch (optname) {
+	case BT_SECURITY:
+		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+				&& sk->sk_type != SOCK_RAW) {
+			err = -EINVAL;
+			break;
+		}
+
+		sec.level = BT_SECURITY_LOW;
+
+		len = min_t(unsigned int, sizeof(sec), optlen);
+		if (copy_from_user((char *) &sec, optval, len)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (sec.level < BT_SECURITY_LOW ||
+					sec.level > BT_SECURITY_HIGH) {
+			err = -EINVAL;
+			break;
+		}
+
+		l2cap_pi(sk)->sec_level = sec.level;
+		break;
+
+	case BT_DEFER_SETUP:
+		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		bt_sk(sk)->defer_setup = opt;
+		break;
+
+	case BT_FLUSHABLE:
+		if (get_user(opt, (u32 __user *) optval)) {
+			err = -EFAULT;
+			break;
+		}
+
+		if (opt > BT_FLUSHABLE_ON) {
+			err = -EINVAL;
+			break;
+		}
+
+		if (opt == BT_FLUSHABLE_OFF) {
+			struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+			/* proceed futher only when we have l2cap_conn and
+			   No Flush support in the LM */
+			if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) {
+				err = -EINVAL;
+				break;
+			}
+		}
+
+		l2cap_pi(sk)->flushable = opt;
+		break;
+
+	default:
+		err = -ENOPROTOOPT;
+		break;
+	}
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len)
+{
+	struct sock *sk = sock->sk;
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+	struct sk_buff *skb;
+	u16 control;
+	int err;
+
+	BT_DBG("sock %p, sk %p", sock, sk);
+
+	err = sock_error(sk);
+	if (err)
+		return err;
+
+	if (msg->msg_flags & MSG_OOB)
+		return -EOPNOTSUPP;
+
+	lock_sock(sk);
+
+	if (sk->sk_state != BT_CONNECTED) {
+		err = -ENOTCONN;
+		goto done;
+	}
+
+	/* Connectionless channel */
+	if (sk->sk_type == SOCK_DGRAM) {
+		skb = l2cap_create_connless_pdu(sk, msg, len);
+		if (IS_ERR(skb)) {
+			err = PTR_ERR(skb);
+		} else {
+			l2cap_do_send(sk, skb);
+			err = len;
+		}
+		goto done;
+	}
+
+	switch (pi->mode) {
+	case L2CAP_MODE_BASIC:
+		/* Check outgoing MTU */
+		if (len > pi->omtu) {
+			err = -EMSGSIZE;
+			goto done;
+		}
+
+		/* Create a basic PDU */
+		skb = l2cap_create_basic_pdu(sk, msg, len);
+		if (IS_ERR(skb)) {
+			err = PTR_ERR(skb);
+			goto done;
+		}
+
+		l2cap_do_send(sk, skb);
+		err = len;
+		break;
+
+	case L2CAP_MODE_ERTM:
+	case L2CAP_MODE_STREAMING:
+		/* Entire SDU fits into one PDU */
+		if (len <= pi->remote_mps) {
+			control = L2CAP_SDU_UNSEGMENTED;
+			skb = l2cap_create_iframe_pdu(sk, msg, len, control, 0);
+			if (IS_ERR(skb)) {
+				err = PTR_ERR(skb);
+				goto done;
+			}
+			__skb_queue_tail(TX_QUEUE(sk), skb);
+
+			if (sk->sk_send_head == NULL)
+				sk->sk_send_head = skb;
+
+		} else {
+		/* Segment SDU into multiples PDUs */
+			err = l2cap_sar_segment_sdu(sk, msg, len);
+			if (err < 0)
+				goto done;
+		}
+
+		if (pi->mode == L2CAP_MODE_STREAMING) {
+			l2cap_streaming_send(sk);
+		} else {
+			if ((pi->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+					(pi->conn_state & L2CAP_CONN_WAIT_F)) {
+				err = len;
+				break;
+			}
+			err = l2cap_ertm_send(sk);
+		}
+
+		if (err >= 0)
+			err = len;
+		break;
+
+	default:
+		BT_DBG("bad state %1.1x", pi->mode);
+		err = -EBADFD;
+	}
+
+done:
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags)
+{
+	struct sock *sk = sock->sk;
+
+	lock_sock(sk);
+
+	if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) {
+		struct l2cap_conn_rsp rsp;
+		struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+		u8 buf[128];
+
+		sk->sk_state = BT_CONFIG;
+
+		rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+		rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+		rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+		rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+		l2cap_send_cmd(l2cap_pi(sk)->conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+
+		if (l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT) {
+			release_sock(sk);
+			return 0;
+		}
+
+		l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
+		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
+				l2cap_build_conf_req(sk, buf), buf);
+		l2cap_pi(sk)->num_conf_req++;
+
+		release_sock(sk);
+		return 0;
+	}
+
+	release_sock(sk);
+
+	if (sock->type == SOCK_STREAM)
+		return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags);
+
+	return bt_sock_recvmsg(iocb, sock, msg, len, flags);
+}
+
+/* Kill socket (only if zapped and orphan)
+ * Must be called on unlocked socket.
+ */
+void l2cap_sock_kill(struct sock *sk)
+{
+	if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
+		return;
+
+	BT_DBG("sk %p state %d", sk, sk->sk_state);
+
+	/* Kill poor orphan */
+	bt_sock_unlink(&l2cap_sk_list, sk);
+	sock_set_flag(sk, SOCK_DEAD);
+	sock_put(sk);
+}
+
+/* Must be called on unlocked socket. */
+static void l2cap_sock_close(struct sock *sk)
+{
+	l2cap_sock_clear_timer(sk);
+	lock_sock(sk);
+	__l2cap_sock_close(sk, ECONNRESET);
+	release_sock(sk);
+	l2cap_sock_kill(sk);
+}
+
+static void l2cap_sock_cleanup_listen(struct sock *parent)
+{
+	struct sock *sk;
+
+	BT_DBG("parent %p", parent);
+
+	/* Close not yet accepted channels */
+	while ((sk = bt_accept_dequeue(parent, NULL)))
+		l2cap_sock_close(sk);
+
+	parent->sk_state = BT_CLOSED;
+	sock_set_flag(parent, SOCK_ZAPPED);
+}
+
+void __l2cap_sock_close(struct sock *sk, int reason)
+{
+	struct l2cap_conn *conn = l2cap_pi(sk)->conn;
+
+	BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
+
+	switch (sk->sk_state) {
+	case BT_LISTEN:
+		l2cap_sock_cleanup_listen(sk);
+		break;
+
+	case BT_CONNECTED:
+	case BT_CONFIG:
+		if ((sk->sk_type == SOCK_SEQPACKET ||
+					sk->sk_type == SOCK_STREAM) &&
+					conn->hcon->type == ACL_LINK) {
+			l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+			l2cap_send_disconn_req(conn, sk, reason);
+		} else
+			l2cap_chan_del(sk, reason);
+		break;
+
+	case BT_CONNECT2:
+		if ((sk->sk_type == SOCK_SEQPACKET ||
+					sk->sk_type == SOCK_STREAM) &&
+					conn->hcon->type == ACL_LINK) {
+			struct l2cap_conn_rsp rsp;
+			__u16 result;
+
+			if (bt_sk(sk)->defer_setup)
+				result = L2CAP_CR_SEC_BLOCK;
+			else
+				result = L2CAP_CR_BAD_PSM;
+
+			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
+			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
+			rsp.result = cpu_to_le16(result);
+			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
+					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
+		} else
+			l2cap_chan_del(sk, reason);
+		break;
+
+	case BT_CONNECT:
+	case BT_DISCONN:
+		l2cap_chan_del(sk, reason);
+		break;
+
+	default:
+		sock_set_flag(sk, SOCK_ZAPPED);
+		break;
+	}
+}
+
+static int l2cap_sock_shutdown(struct socket *sock, int how)
+{
+	struct sock *sk = sock->sk;
+	int err = 0;
+
+	BT_DBG("sock %p, sk %p", sock, sk);
+
+	if (!sk)
+		return 0;
+
+	lock_sock(sk);
+	if (!sk->sk_shutdown) {
+		if (l2cap_pi(sk)->mode == L2CAP_MODE_ERTM)
+			err = __l2cap_wait_ack(sk);
+
+		sk->sk_shutdown = SHUTDOWN_MASK;
+		l2cap_sock_clear_timer(sk);
+		__l2cap_sock_close(sk, 0);
+
+		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
+			err = bt_sock_wait_state(sk, BT_CLOSED,
+							sk->sk_lingertime);
+	}
+
+	if (!err && sk->sk_err)
+		err = -sk->sk_err;
+
+	release_sock(sk);
+	return err;
+}
+
+static int l2cap_sock_release(struct socket *sock)
+{
+	struct sock *sk = sock->sk;
+	int err;
+
+	BT_DBG("sock %p, sk %p", sock, sk);
+
+	if (!sk)
+		return 0;
+
+	err = l2cap_sock_shutdown(sock, 2);
+
+	sock_orphan(sk);
+	l2cap_sock_kill(sk);
+	return err;
+}
+
+static void l2cap_sock_destruct(struct sock *sk)
+{
+	BT_DBG("sk %p", sk);
+
+	skb_queue_purge(&sk->sk_receive_queue);
+	skb_queue_purge(&sk->sk_write_queue);
+}
+
+void l2cap_sock_init(struct sock *sk, struct sock *parent)
+{
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
+
+	BT_DBG("sk %p", sk);
+
+	if (parent) {
+		sk->sk_type = parent->sk_type;
+		bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
+
+		pi->imtu = l2cap_pi(parent)->imtu;
+		pi->omtu = l2cap_pi(parent)->omtu;
+		pi->conf_state = l2cap_pi(parent)->conf_state;
+		pi->mode = l2cap_pi(parent)->mode;
+		pi->fcs  = l2cap_pi(parent)->fcs;
+		pi->max_tx = l2cap_pi(parent)->max_tx;
+		pi->tx_win = l2cap_pi(parent)->tx_win;
+		pi->sec_level = l2cap_pi(parent)->sec_level;
+		pi->role_switch = l2cap_pi(parent)->role_switch;
+		pi->force_reliable = l2cap_pi(parent)->force_reliable;
+		pi->flushable = l2cap_pi(parent)->flushable;
+	} else {
+		pi->imtu = L2CAP_DEFAULT_MTU;
+		pi->omtu = 0;
+		if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
+			pi->mode = L2CAP_MODE_ERTM;
+			pi->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+		} else {
+			pi->mode = L2CAP_MODE_BASIC;
+		}
+		pi->max_tx = L2CAP_DEFAULT_MAX_TX;
+		pi->fcs  = L2CAP_FCS_CRC16;
+		pi->tx_win = L2CAP_DEFAULT_TX_WINDOW;
+		pi->sec_level = BT_SECURITY_LOW;
+		pi->role_switch = 0;
+		pi->force_reliable = 0;
+		pi->flushable = BT_FLUSHABLE_OFF;
+	}
+
+	/* Default config options */
+	pi->conf_len = 0;
+	pi->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+	skb_queue_head_init(TX_QUEUE(sk));
+	skb_queue_head_init(SREJ_QUEUE(sk));
+	skb_queue_head_init(BUSY_QUEUE(sk));
+	INIT_LIST_HEAD(SREJ_LIST(sk));
+}
+
+static struct proto l2cap_proto = {
+	.name		= "L2CAP",
+	.owner		= THIS_MODULE,
+	.obj_size	= sizeof(struct l2cap_pinfo)
+};
+
+struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+{
+	struct sock *sk;
+
+	sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
+	if (!sk)
+		return NULL;
+
+	sock_init_data(sock, sk);
+	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);
+
+	sk->sk_destruct = l2cap_sock_destruct;
+	sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT);
+
+	sock_reset_flag(sk, SOCK_ZAPPED);
+
+	sk->sk_protocol = proto;
+	sk->sk_state = BT_OPEN;
+
+	setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
+
+	bt_sock_link(&l2cap_sk_list, sk);
+	return sk;
+}
+
+static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
+			     int kern)
+{
+	struct sock *sk;
+
+	BT_DBG("sock %p", sock);
+
+	sock->state = SS_UNCONNECTED;
+
+	if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM &&
+			sock->type != SOCK_DGRAM && sock->type != SOCK_RAW)
+		return -ESOCKTNOSUPPORT;
+
+	if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
+		return -EPERM;
+
+	sock->ops = &l2cap_sock_ops;
+
+	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC);
+	if (!sk)
+		return -ENOMEM;
+
+	l2cap_sock_init(sk, NULL);
+	return 0;
+}
+
+const struct proto_ops l2cap_sock_ops = {
+	.family		= PF_BLUETOOTH,
+	.owner		= THIS_MODULE,
+	.release	= l2cap_sock_release,
+	.bind		= l2cap_sock_bind,
+	.connect	= l2cap_sock_connect,
+	.listen		= l2cap_sock_listen,
+	.accept		= l2cap_sock_accept,
+	.getname	= l2cap_sock_getname,
+	.sendmsg	= l2cap_sock_sendmsg,
+	.recvmsg	= l2cap_sock_recvmsg,
+	.poll		= bt_sock_poll,
+	.ioctl		= bt_sock_ioctl,
+	.mmap		= sock_no_mmap,
+	.socketpair	= sock_no_socketpair,
+	.shutdown	= l2cap_sock_shutdown,
+	.setsockopt	= l2cap_sock_setsockopt,
+	.getsockopt	= l2cap_sock_getsockopt
+};
+
+static const struct net_proto_family l2cap_sock_family_ops = {
+	.family	= PF_BLUETOOTH,
+	.owner	= THIS_MODULE,
+	.create	= l2cap_sock_create,
+};
+
+int __init l2cap_init_sockets(void)
+{
+	int err;
+
+	err = proto_register(&l2cap_proto, 0);
+	if (err < 0)
+		return err;
+
+	err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
+	if (err < 0)
+		goto error;
+
+	BT_INFO("L2CAP socket layer initialized");
+
+	return 0;
+
+error:
+	BT_ERR("L2CAP socket registration failed");
+	proto_unregister(&l2cap_proto);
+	return err;
+}
+
+void l2cap_cleanup_sockets(void)
+{
+	if (bt_sock_unregister(BTPROTO_L2CAP) < 0)
+		BT_ERR("L2CAP socket unregistration failed");
+
+	proto_unregister(&l2cap_proto);
+}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index f827fd9..0054c74 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -22,7 +22,7 @@
 
 /* Bluetooth HCI Management interface */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
@@ -32,13 +32,24 @@
 #define MGMT_VERSION	0
 #define MGMT_REVISION	1
 
-static int cmd_status(struct sock *sk, u16 cmd, u8 status)
+struct pending_cmd {
+	struct list_head list;
+	__u16 opcode;
+	int index;
+	void *cmd;
+	struct sock *sk;
+	void *user_data;
+};
+
+LIST_HEAD(cmd_list);
+
+static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
 {
 	struct sk_buff *skb;
 	struct mgmt_hdr *hdr;
 	struct mgmt_ev_cmd_status *ev;
 
-	BT_DBG("sock %p", sk);
+	BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
 
 	skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_ATOMIC);
 	if (!skb)
@@ -47,6 +58,7 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status)
 	hdr = (void *) skb_put(skb, sizeof(*hdr));
 
 	hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
+	hdr->index = cpu_to_le16(index);
 	hdr->len = cpu_to_le16(sizeof(*ev));
 
 	ev = (void *) skb_put(skb, sizeof(*ev));
@@ -59,29 +71,30 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status)
 	return 0;
 }
 
-static int read_version(struct sock *sk)
+static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp,
+								size_t rp_len)
 {
 	struct sk_buff *skb;
 	struct mgmt_hdr *hdr;
 	struct mgmt_ev_cmd_complete *ev;
-	struct mgmt_rp_read_version *rp;
 
 	BT_DBG("sock %p", sk);
 
-	skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC);
+	skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_ATOMIC);
 	if (!skb)
 		return -ENOMEM;
 
 	hdr = (void *) skb_put(skb, sizeof(*hdr));
+
 	hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
-	hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp));
+	hdr->index = cpu_to_le16(index);
+	hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
 
-	ev = (void *) skb_put(skb, sizeof(*ev));
-	put_unaligned_le16(MGMT_OP_READ_VERSION, &ev->opcode);
+	ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
+	put_unaligned_le16(cmd, &ev->opcode);
 
-	rp = (void *) skb_put(skb, sizeof(*rp));
-	rp->version = MGMT_VERSION;
-	put_unaligned_le16(MGMT_REVISION, &rp->revision);
+	if (rp)
+		memcpy(ev->data, rp, rp_len);
 
 	if (sock_queue_rcv_skb(sk, skb) < 0)
 		kfree_skb(skb);
@@ -89,16 +102,26 @@ static int read_version(struct sock *sk)
 	return 0;
 }
 
+static int read_version(struct sock *sk)
+{
+	struct mgmt_rp_read_version rp;
+
+	BT_DBG("sock %p", sk);
+
+	rp.version = MGMT_VERSION;
+	put_unaligned_le16(MGMT_REVISION, &rp.revision);
+
+	return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp,
+								sizeof(rp));
+}
+
 static int read_index_list(struct sock *sk)
 {
-	struct sk_buff *skb;
-	struct mgmt_hdr *hdr;
-	struct mgmt_ev_cmd_complete *ev;
 	struct mgmt_rp_read_index_list *rp;
 	struct list_head *p;
-	size_t body_len;
+	size_t rp_len;
 	u16 count;
-	int i;
+	int i, err;
 
 	BT_DBG("sock %p", sk);
 
@@ -109,164 +132,340 @@ static int read_index_list(struct sock *sk)
 		count++;
 	}
 
-	body_len = sizeof(*ev) + sizeof(*rp) + (2 * count);
-	skb = alloc_skb(sizeof(*hdr) + body_len, GFP_ATOMIC);
-	if (!skb)
+	rp_len = sizeof(*rp) + (2 * count);
+	rp = kmalloc(rp_len, GFP_ATOMIC);
+	if (!rp) {
+		read_unlock(&hci_dev_list_lock);
 		return -ENOMEM;
+	}
 
-	hdr = (void *) skb_put(skb, sizeof(*hdr));
-	hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
-	hdr->len = cpu_to_le16(body_len);
-
-	ev = (void *) skb_put(skb, sizeof(*ev));
-	put_unaligned_le16(MGMT_OP_READ_INDEX_LIST, &ev->opcode);
-
-	rp = (void *) skb_put(skb, sizeof(*rp) + (2 * count));
 	put_unaligned_le16(count, &rp->num_controllers);
 
 	i = 0;
 	list_for_each(p, &hci_dev_list) {
 		struct hci_dev *d = list_entry(p, struct hci_dev, list);
+
+		hci_del_off_timer(d);
+
+		set_bit(HCI_MGMT, &d->flags);
+
+		if (test_bit(HCI_SETUP, &d->flags))
+			continue;
+
 		put_unaligned_le16(d->id, &rp->index[i++]);
 		BT_DBG("Added hci%u", d->id);
 	}
 
 	read_unlock(&hci_dev_list_lock);
 
-	if (sock_queue_rcv_skb(sk, skb) < 0)
-		kfree_skb(skb);
+	err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp,
+									rp_len);
 
-	return 0;
+	kfree(rp);
+
+	return err;
 }
 
-static int read_controller_info(struct sock *sk, unsigned char *data, u16 len)
+static int read_controller_info(struct sock *sk, u16 index)
 {
-	struct sk_buff *skb;
-	struct mgmt_hdr *hdr;
-	struct mgmt_ev_cmd_complete *ev;
-	struct mgmt_rp_read_info *rp;
-	struct mgmt_cp_read_info *cp;
+	struct mgmt_rp_read_info rp;
 	struct hci_dev *hdev;
-	u16 dev_id;
 
-	BT_DBG("sock %p", sk);
+	BT_DBG("sock %p hci%u", sk, index);
 
-	if (len != 2)
-		return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL);
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV);
 
-	skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + sizeof(*rp), GFP_ATOMIC);
-	if (!skb)
-		return -ENOMEM;
+	hci_del_off_timer(hdev);
 
-	hdr = (void *) skb_put(skb, sizeof(*hdr));
-	hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
-	hdr->len = cpu_to_le16(sizeof(*ev) + sizeof(*rp));
+	hci_dev_lock_bh(hdev);
 
-	ev = (void *) skb_put(skb, sizeof(*ev));
-	put_unaligned_le16(MGMT_OP_READ_INFO, &ev->opcode);
+	set_bit(HCI_MGMT, &hdev->flags);
 
-	rp = (void *) skb_put(skb, sizeof(*rp));
+	rp.type = hdev->dev_type;
 
-	cp = (void *) data;
-	dev_id = get_unaligned_le16(&cp->index);
+	rp.powered = test_bit(HCI_UP, &hdev->flags);
+	rp.connectable = test_bit(HCI_PSCAN, &hdev->flags);
+	rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags);
+	rp.pairable = test_bit(HCI_PSCAN, &hdev->flags);
+
+	if (test_bit(HCI_AUTH, &hdev->flags))
+		rp.sec_mode = 3;
+	else if (hdev->ssp_mode > 0)
+		rp.sec_mode = 4;
+	else
+		rp.sec_mode = 2;
 
-	BT_DBG("request for hci%u", dev_id);
+	bacpy(&rp.bdaddr, &hdev->bdaddr);
+	memcpy(rp.features, hdev->features, 8);
+	memcpy(rp.dev_class, hdev->dev_class, 3);
+	put_unaligned_le16(hdev->manufacturer, &rp.manufacturer);
+	rp.hci_ver = hdev->hci_ver;
+	put_unaligned_le16(hdev->hci_rev, &rp.hci_rev);
 
-	hdev = hci_dev_get(dev_id);
-	if (!hdev) {
-		kfree_skb(skb);
-		return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV);
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
+}
+
+static void mgmt_pending_free(struct pending_cmd *cmd)
+{
+	sock_put(cmd->sk);
+	kfree(cmd->cmd);
+	kfree(cmd);
+}
+
+static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
+						u16 index, void *data, u16 len)
+{
+	struct pending_cmd *cmd;
+
+	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
+	if (!cmd)
+		return NULL;
+
+	cmd->opcode = opcode;
+	cmd->index = index;
+
+	cmd->cmd = kmalloc(len, GFP_ATOMIC);
+	if (!cmd->cmd) {
+		kfree(cmd);
+		return NULL;
+	}
+
+	memcpy(cmd->cmd, data, len);
+
+	cmd->sk = sk;
+	sock_hold(sk);
+
+	list_add(&cmd->list, &cmd_list);
+
+	return cmd;
+}
+
+static void mgmt_pending_foreach(u16 opcode, int index,
+				void (*cb)(struct pending_cmd *cmd, void *data),
+				void *data)
+{
+	struct list_head *p, *n;
+
+	list_for_each_safe(p, n, &cmd_list) {
+		struct pending_cmd *cmd;
+
+		cmd = list_entry(p, struct pending_cmd, list);
+
+		if (cmd->opcode != opcode)
+			continue;
+
+		if (index >= 0 && cmd->index != index)
+			continue;
+
+		cb(cmd, data);
+	}
+}
+
+static struct pending_cmd *mgmt_pending_find(u16 opcode, int index)
+{
+	struct list_head *p;
+
+	list_for_each(p, &cmd_list) {
+		struct pending_cmd *cmd;
+
+		cmd = list_entry(p, struct pending_cmd, list);
+
+		if (cmd->opcode != opcode)
+			continue;
+
+		if (index >= 0 && cmd->index != index)
+			continue;
+
+		return cmd;
 	}
 
+	return NULL;
+}
+
+static void mgmt_pending_remove(struct pending_cmd *cmd)
+{
+	list_del(&cmd->list);
+	mgmt_pending_free(cmd);
+}
+
+static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct mgmt_mode *cp;
+	struct hci_dev *hdev;
+	struct pending_cmd *cmd;
+	int err, up;
+
+	cp = (void *) data;
+
+	BT_DBG("request for hci%u", index);
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
+
 	hci_dev_lock_bh(hdev);
 
-	put_unaligned_le16(hdev->id, &rp->index);
-	rp->type = hdev->dev_type;
+	up = test_bit(HCI_UP, &hdev->flags);
+	if ((cp->val && up) || (!cp->val && !up)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY);
+		goto failed;
+	}
 
-	rp->powered = test_bit(HCI_UP, &hdev->flags);
-	rp->discoverable = test_bit(HCI_ISCAN, &hdev->flags);
-	rp->pairable = test_bit(HCI_PSCAN, &hdev->flags);
+	if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY);
+		goto failed;
+	}
 
-	if (test_bit(HCI_AUTH, &hdev->flags))
-		rp->sec_mode = 3;
-	else if (hdev->ssp_mode > 0)
-		rp->sec_mode = 4;
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	if (cp->val)
+		queue_work(hdev->workqueue, &hdev->power_on);
 	else
-		rp->sec_mode = 2;
+		queue_work(hdev->workqueue, &hdev->power_off);
 
-	bacpy(&rp->bdaddr, &hdev->bdaddr);
-	memcpy(rp->features, hdev->features, 8);
-	memcpy(rp->dev_class, hdev->dev_class, 3);
-	put_unaligned_le16(hdev->manufacturer, &rp->manufacturer);
-	rp->hci_ver = hdev->hci_ver;
-	put_unaligned_le16(hdev->hci_rev, &rp->hci_rev);
+	err = 0;
 
+failed:
 	hci_dev_unlock_bh(hdev);
 	hci_dev_put(hdev);
+	return err;
+}
 
-	if (sock_queue_rcv_skb(sk, skb) < 0)
-		kfree_skb(skb);
+static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
+{
+	struct mgmt_mode *cp;
+	struct hci_dev *hdev;
+	struct pending_cmd *cmd;
+	u8 scan;
+	int err;
 
-	return 0;
+	cp = (void *) data;
+
+	BT_DBG("request for hci%u", index);
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
+		goto failed;
+	}
+
+	if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
+			mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY);
+		goto failed;
+	}
+
+	if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
+					test_bit(HCI_PSCAN, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	scan = SCAN_PAGE;
+
+	if (cp->val)
+		scan |= SCAN_INQUIRY;
+
+	err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
 }
 
-int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
+static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
 {
-	unsigned char *buf;
-	struct mgmt_hdr *hdr;
-	u16 opcode, len;
+	struct mgmt_mode *cp;
+	struct hci_dev *hdev;
+	struct pending_cmd *cmd;
+	u8 scan;
 	int err;
 
-	BT_DBG("got %zu bytes", msglen);
+	cp = (void *) data;
 
-	if (msglen < sizeof(*hdr))
-		return -EINVAL;
+	BT_DBG("request for hci%u", index);
 
-	buf = kmalloc(msglen, GFP_ATOMIC);
-	if (!buf)
-		return -ENOMEM;
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
 
-	if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
-		err = -EFAULT;
-		goto done;
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
+		goto failed;
 	}
 
-	hdr = (struct mgmt_hdr *) buf;
-	opcode = get_unaligned_le16(&hdr->opcode);
-	len = get_unaligned_le16(&hdr->len);
+	if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
+			mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY);
+		goto failed;
+	}
 
-	if (len != msglen - sizeof(*hdr)) {
-		err = -EINVAL;
-		goto done;
+	if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY);
+		goto failed;
 	}
 
-	switch (opcode) {
-	case MGMT_OP_READ_VERSION:
-		err = read_version(sk);
-		break;
-	case MGMT_OP_READ_INDEX_LIST:
-		err = read_index_list(sk);
-		break;
-	case MGMT_OP_READ_INFO:
-		err = read_controller_info(sk, buf + sizeof(*hdr), len);
-		break;
-	default:
-		BT_DBG("Unknown op %u", opcode);
-		err = cmd_status(sk, opcode, 0x01);
-		break;
+	cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
 	}
 
+	if (cp->val)
+		scan = SCAN_PAGE;
+	else
+		scan = 0;
+
+	err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 	if (err < 0)
-		goto done;
+		mgmt_pending_remove(cmd);
 
-	err = msglen;
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
 
-done:
-	kfree(buf);
 	return err;
 }
 
-static int mgmt_event(u16 event, void *data, u16 data_len)
+static int mgmt_event(u16 event, u16 index, void *data, u16 data_len,
+							struct sock *skip_sk)
 {
 	struct sk_buff *skb;
 	struct mgmt_hdr *hdr;
@@ -279,30 +478,1168 @@ static int mgmt_event(u16 event, void *data, u16 data_len)
 
 	hdr = (void *) skb_put(skb, sizeof(*hdr));
 	hdr->opcode = cpu_to_le16(event);
+	hdr->index = cpu_to_le16(index);
 	hdr->len = cpu_to_le16(data_len);
 
-	memcpy(skb_put(skb, data_len), data, data_len);
+	if (data)
+		memcpy(skb_put(skb, data_len), data, data_len);
 
-	hci_send_to_sock(NULL, skb);
+	hci_send_to_sock(NULL, skb, skip_sk);
 	kfree_skb(skb);
 
 	return 0;
 }
 
-int mgmt_index_added(u16 index)
+static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
 {
-	struct mgmt_ev_index_added ev;
+	struct mgmt_mode rp;
 
-	put_unaligned_le16(index, &ev.index);
+	rp.val = val;
 
-	return mgmt_event(MGMT_EV_INDEX_ADDED, &ev, sizeof(ev));
+	return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
 }
 
-int mgmt_index_removed(u16 index)
+static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
+{
+	struct mgmt_mode *cp, ev;
+	struct hci_dev *hdev;
+	int err;
+
+	cp = (void *) data;
+
+	BT_DBG("request for hci%u", index);
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (cp->val)
+		set_bit(HCI_PAIRABLE, &hdev->flags);
+	else
+		clear_bit(HCI_PAIRABLE, &hdev->flags);
+
+	err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val);
+	if (err < 0)
+		goto failed;
+
+	ev.val = cp->val;
+
+	err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static u8 get_service_classes(struct hci_dev *hdev)
+{
+	struct list_head *p;
+	u8 val = 0;
+
+	list_for_each(p, &hdev->uuids) {
+		struct bt_uuid *uuid = list_entry(p, struct bt_uuid, list);
+
+		val |= uuid->svc_hint;
+	}
+
+	return val;
+}
+
+static int update_class(struct hci_dev *hdev)
+{
+	u8 cod[3];
+
+	BT_DBG("%s", hdev->name);
+
+	if (test_bit(HCI_SERVICE_CACHE, &hdev->flags))
+		return 0;
+
+	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;
+
+	return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
+}
+
+static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct mgmt_cp_add_uuid *cp;
+	struct hci_dev *hdev;
+	struct bt_uuid *uuid;
+	int err;
+
+	cp = (void *) data;
+
+	BT_DBG("request for hci%u", index);
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	uuid = kmalloc(sizeof(*uuid), GFP_ATOMIC);
+	if (!uuid) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	memcpy(uuid->uuid, cp->uuid, 16);
+	uuid->svc_hint = cp->svc_hint;
+
+	list_add(&uuid->list, &hdev->uuids);
+
+	err = update_class(hdev);
+	if (err < 0)
+		goto failed;
+
+	err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct list_head *p, *n;
+	struct mgmt_cp_remove_uuid *cp;
+	struct hci_dev *hdev;
+	u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	int err, found;
+
+	cp = (void *) data;
+
+	BT_DBG("request for hci%u", index);
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
+		err = hci_uuids_clear(hdev);
+		goto unlock;
+	}
+
+	found = 0;
+
+	list_for_each_safe(p, n, &hdev->uuids) {
+		struct bt_uuid *match = list_entry(p, struct bt_uuid, list);
+
+		if (memcmp(match->uuid, cp->uuid, 16) != 0)
+			continue;
+
+		list_del(&match->list);
+		found++;
+	}
+
+	if (found == 0) {
+		err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT);
+		goto unlock;
+	}
+
+	err = update_class(hdev);
+	if (err < 0)
+		goto unlock;
+
+	err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
+
+unlock:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_set_dev_class *cp;
+	int err;
+
+	cp = (void *) data;
+
+	BT_DBG("request for hci%u", index);
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	hdev->major_class = cp->major;
+	hdev->minor_class = cp->minor;
+
+	err = update_class(hdev);
+
+	if (err == 0)
+		err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
+
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int set_service_cache(struct sock *sk, u16 index,  unsigned char *data,
+									u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_set_service_cache *cp;
+	int err;
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	BT_DBG("hci%u enable %d", index, cp->enable);
+
+	if (cp->enable) {
+		set_bit(HCI_SERVICE_CACHE, &hdev->flags);
+		err = 0;
+	} else {
+		clear_bit(HCI_SERVICE_CACHE, &hdev->flags);
+		err = update_class(hdev);
+	}
+
+	if (err == 0)
+		err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
+									0);
+
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_load_keys *cp;
+	u16 key_count, expected_len;
+	int i;
+
+	cp = (void *) data;
+
+	if (len < sizeof(*cp))
+		return -EINVAL;
+
+	key_count = get_unaligned_le16(&cp->key_count);
+
+	expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
+	if (expected_len != len) {
+		BT_ERR("load_keys: expected %u bytes, got %u bytes",
+							len, expected_len);
+		return -EINVAL;
+	}
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV);
+
+	BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
+								key_count);
+
+	hci_dev_lock_bh(hdev);
+
+	hci_link_keys_clear(hdev);
+
+	set_bit(HCI_LINK_KEYS, &hdev->flags);
+
+	if (cp->debug_keys)
+		set_bit(HCI_DEBUG_KEYS, &hdev->flags);
+	else
+		clear_bit(HCI_DEBUG_KEYS, &hdev->flags);
+
+	for (i = 0; i < key_count; i++) {
+		struct mgmt_key_info *key = &cp->keys[i];
+
+		hci_add_link_key(hdev, 0, &key->bdaddr, key->val, key->type,
+								key->pin_len);
+	}
+
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return 0;
+}
+
+static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_remove_key *cp;
+	struct hci_conn *conn;
+	int err;
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	err = hci_remove_link_key(hdev, &cp->bdaddr);
+	if (err < 0) {
+		err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err);
+		goto unlock;
+	}
+
+	err = 0;
+
+	if (!test_bit(HCI_UP, &hdev->flags) || !cp->disconnect)
+		goto unlock;
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+	if (conn) {
+		struct hci_cp_disconnect dc;
+
+		put_unaligned_le16(conn->handle, &dc.handle);
+		dc.reason = 0x13; /* Remote User Terminated Connection */
+		err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
+	}
+
+unlock:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_disconnect *cp;
+	struct hci_cp_disconnect dc;
+	struct pending_cmd *cmd;
+	struct hci_conn *conn;
+	int err;
+
+	BT_DBG("");
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
+		goto failed;
+	}
+
+	if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) {
+		err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
+		goto failed;
+	}
+
+	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+	if (!conn) {
+		err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	put_unaligned_le16(conn->handle, &dc.handle);
+	dc.reason = 0x13; /* Remote User Terminated Connection */
+
+	err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int get_connections(struct sock *sk, u16 index)
+{
+	struct mgmt_rp_get_connections *rp;
+	struct hci_dev *hdev;
+	struct list_head *p;
+	size_t rp_len;
+	u16 count;
+	int i, err;
+
+	BT_DBG("");
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	count = 0;
+	list_for_each(p, &hdev->conn_hash.list) {
+		count++;
+	}
+
+	rp_len = sizeof(*rp) + (count * sizeof(bdaddr_t));
+	rp = kmalloc(rp_len, GFP_ATOMIC);
+	if (!rp) {
+		err = -ENOMEM;
+		goto unlock;
+	}
+
+	put_unaligned_le16(count, &rp->conn_count);
+
+	read_lock(&hci_dev_list_lock);
+
+	i = 0;
+	list_for_each(p, &hdev->conn_hash.list) {
+		struct hci_conn *c = list_entry(p, struct hci_conn, list);
+
+		bacpy(&rp->conn[i++], &c->dst);
+	}
+
+	read_unlock(&hci_dev_list_lock);
+
+	err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
+
+unlock:
+	kfree(rp);
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+	return err;
+}
+
+static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_pin_code_reply *cp;
+	struct hci_cp_pin_code_reply reply;
+	struct pending_cmd *cmd;
+	int err;
+
+	BT_DBG("");
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	bacpy(&reply.bdaddr, &cp->bdaddr);
+	reply.pin_len = cp->pin_len;
+	memcpy(reply.pin_code, cp->pin_code, 16);
+
+	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_pin_code_neg_reply *cp;
+	struct pending_cmd *cmd;
+	int err;
+
+	BT_DBG("");
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+									EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+									ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+								ENETDOWN);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
+								data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
+								&cp->bdaddr);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
+									u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_set_io_capability *cp;
+
+	BT_DBG("");
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	hdev->io_capability = cp->io_capability;
+
+	BT_DBG("%s IO capability set to 0x%02x", hdev->name,
+							hdev->io_capability);
+
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
+}
+
+static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
+{
+	struct hci_dev *hdev = conn->hdev;
+	struct list_head *p;
+
+	list_for_each(p, &cmd_list) {
+		struct pending_cmd *cmd;
+
+		cmd = list_entry(p, struct pending_cmd, list);
+
+		if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
+			continue;
+
+		if (cmd->index != hdev->id)
+			continue;
+
+		if (cmd->user_data != conn)
+			continue;
+
+		return cmd;
+	}
+
+	return NULL;
+}
+
+static void pairing_complete(struct pending_cmd *cmd, u8 status)
+{
+	struct mgmt_rp_pair_device rp;
+	struct hci_conn *conn = cmd->user_data;
+
+	bacpy(&rp.bdaddr, &conn->dst);
+	rp.status = status;
+
+	cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
+
+	/* So we don't get further callbacks for this connection */
+	conn->connect_cfm_cb = NULL;
+	conn->security_cfm_cb = NULL;
+	conn->disconn_cfm_cb = NULL;
+
+	hci_conn_put(conn);
+
+	mgmt_pending_remove(cmd);
+}
+
+static void pairing_complete_cb(struct hci_conn *conn, u8 status)
+{
+	struct pending_cmd *cmd;
+
+	BT_DBG("status %u", status);
+
+	cmd = find_pairing(conn);
+	if (!cmd) {
+		BT_DBG("Unable to find a pending command");
+		return;
+	}
+
+	pairing_complete(cmd, status);
+}
+
+static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
+{
+	struct hci_dev *hdev;
+	struct mgmt_cp_pair_device *cp;
+	struct pending_cmd *cmd;
+	u8 sec_level, auth_type;
+	struct hci_conn *conn;
+	int err;
+
+	BT_DBG("");
+
+	cp = (void *) data;
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
+
+	hci_dev_lock_bh(hdev);
+
+	if (cp->io_cap == 0x03) {
+		sec_level = BT_SECURITY_MEDIUM;
+		auth_type = HCI_AT_DEDICATED_BONDING;
+	} else {
+		sec_level = BT_SECURITY_HIGH;
+		auth_type = HCI_AT_DEDICATED_BONDING_MITM;
+	}
+
+	conn = hci_connect(hdev, ACL_LINK, &cp->bdaddr, sec_level, auth_type);
+	if (IS_ERR(conn)) {
+		err = PTR_ERR(conn);
+		goto unlock;
+	}
+
+	if (conn->connect_cfm_cb) {
+		hci_conn_put(conn);
+		err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
+		goto unlock;
+	}
+
+	cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		hci_conn_put(conn);
+		goto unlock;
+	}
+
+	conn->connect_cfm_cb = pairing_complete_cb;
+	conn->security_cfm_cb = pairing_complete_cb;
+	conn->disconn_cfm_cb = pairing_complete_cb;
+	conn->io_capability = cp->io_cap;
+	cmd->user_data = conn;
+
+	if (conn->state == BT_CONNECTED &&
+				hci_conn_security(conn, sec_level, auth_type))
+		pairing_complete(cmd, 0);
+
+	err = 0;
+
+unlock:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
+							u16 len, int success)
+{
+	struct mgmt_cp_user_confirm_reply *cp = (void *) data;
+	u16 mgmt_op, hci_op;
+	struct pending_cmd *cmd;
+	struct hci_dev *hdev;
+	int err;
+
+	BT_DBG("");
+
+	if (success) {
+		mgmt_op = MGMT_OP_USER_CONFIRM_REPLY;
+		hci_op = HCI_OP_USER_CONFIRM_REPLY;
+	} else {
+		mgmt_op = MGMT_OP_USER_CONFIRM_NEG_REPLY;
+		hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
+	}
+
+	if (len != sizeof(*cp))
+		return cmd_status(sk, index, mgmt_op, EINVAL);
+
+	hdev = hci_dev_get(index);
+	if (!hdev)
+		return cmd_status(sk, index, mgmt_op, ENODEV);
+
+	if (!test_bit(HCI_UP, &hdev->flags)) {
+		err = cmd_status(sk, index, mgmt_op, ENETDOWN);
+		goto failed;
+	}
+
+	cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
+	if (!cmd) {
+		err = -ENOMEM;
+		goto failed;
+	}
+
+	err = hci_send_cmd(hdev, hci_op, sizeof(cp->bdaddr), &cp->bdaddr);
+	if (err < 0)
+		mgmt_pending_remove(cmd);
+
+failed:
+	hci_dev_unlock_bh(hdev);
+	hci_dev_put(hdev);
+
+	return err;
+}
+
+int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
+{
+	unsigned char *buf;
+	struct mgmt_hdr *hdr;
+	u16 opcode, index, len;
+	int err;
+
+	BT_DBG("got %zu bytes", msglen);
+
+	if (msglen < sizeof(*hdr))
+		return -EINVAL;
+
+	buf = kmalloc(msglen, GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
+		err = -EFAULT;
+		goto done;
+	}
+
+	hdr = (struct mgmt_hdr *) buf;
+	opcode = get_unaligned_le16(&hdr->opcode);
+	index = get_unaligned_le16(&hdr->index);
+	len = get_unaligned_le16(&hdr->len);
+
+	if (len != msglen - sizeof(*hdr)) {
+		err = -EINVAL;
+		goto done;
+	}
+
+	switch (opcode) {
+	case MGMT_OP_READ_VERSION:
+		err = read_version(sk);
+		break;
+	case MGMT_OP_READ_INDEX_LIST:
+		err = read_index_list(sk);
+		break;
+	case MGMT_OP_READ_INFO:
+		err = read_controller_info(sk, index);
+		break;
+	case MGMT_OP_SET_POWERED:
+		err = set_powered(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_SET_DISCOVERABLE:
+		err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_SET_CONNECTABLE:
+		err = set_connectable(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_SET_PAIRABLE:
+		err = set_pairable(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_ADD_UUID:
+		err = add_uuid(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_REMOVE_UUID:
+		err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_SET_DEV_CLASS:
+		err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_SET_SERVICE_CACHE:
+		err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_LOAD_KEYS:
+		err = load_keys(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_REMOVE_KEY:
+		err = remove_key(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_DISCONNECT:
+		err = disconnect(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_GET_CONNECTIONS:
+		err = get_connections(sk, index);
+		break;
+	case MGMT_OP_PIN_CODE_REPLY:
+		err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_PIN_CODE_NEG_REPLY:
+		err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_SET_IO_CAPABILITY:
+		err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_PAIR_DEVICE:
+		err = pair_device(sk, index, buf + sizeof(*hdr), len);
+		break;
+	case MGMT_OP_USER_CONFIRM_REPLY:
+		err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1);
+		break;
+	case MGMT_OP_USER_CONFIRM_NEG_REPLY:
+		err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0);
+		break;
+	default:
+		BT_DBG("Unknown op %u", opcode);
+		err = cmd_status(sk, index, opcode, 0x01);
+		break;
+	}
+
+	if (err < 0)
+		goto done;
+
+	err = msglen;
+
+done:
+	kfree(buf);
+	return err;
+}
+
+int mgmt_index_added(u16 index)
+{
+	return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
+}
+
+int mgmt_index_removed(u16 index)
+{
+	return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
+}
+
+struct cmd_lookup {
+	u8 val;
+	struct sock *sk;
+};
+
+static void mode_rsp(struct pending_cmd *cmd, void *data)
+{
+	struct mgmt_mode *cp = cmd->cmd;
+	struct cmd_lookup *match = data;
+
+	if (cp->val != match->val)
+		return;
+
+	send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val);
+
+	list_del(&cmd->list);
+
+	if (match->sk == NULL) {
+		match->sk = cmd->sk;
+		sock_hold(match->sk);
+	}
+
+	mgmt_pending_free(cmd);
+}
+
+int mgmt_powered(u16 index, u8 powered)
+{
+	struct mgmt_mode ev;
+	struct cmd_lookup match = { powered, NULL };
+	int ret;
+
+	mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
+
+	ev.val = powered;
+
+	ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
+
+	if (match.sk)
+		sock_put(match.sk);
+
+	return ret;
+}
+
+int mgmt_discoverable(u16 index, u8 discoverable)
+{
+	struct mgmt_mode ev;
+	struct cmd_lookup match = { discoverable, NULL };
+	int ret;
+
+	mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index, mode_rsp, &match);
+
+	ev.val = discoverable;
+
+	ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
+								match.sk);
+
+	if (match.sk)
+		sock_put(match.sk);
+
+	return ret;
+}
+
+int mgmt_connectable(u16 index, u8 connectable)
+{
+	struct mgmt_mode ev;
+	struct cmd_lookup match = { connectable, NULL };
+	int ret;
+
+	mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
+
+	ev.val = connectable;
+
+	ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
+
+	if (match.sk)
+		sock_put(match.sk);
+
+	return ret;
+}
+
+int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type)
+{
+	struct mgmt_ev_new_key ev;
+
+	memset(&ev, 0, sizeof(ev));
+
+	bacpy(&ev.key.bdaddr, &key->bdaddr);
+	ev.key.type = key->type;
+	memcpy(ev.key.val, key->val, 16);
+	ev.key.pin_len = key->pin_len;
+	ev.old_key_type = old_key_type;
+
+	return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
+}
+
+int mgmt_connected(u16 index, bdaddr_t *bdaddr)
+{
+	struct mgmt_ev_connected ev;
+
+	bacpy(&ev.bdaddr, bdaddr);
+
+	return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
+}
+
+static void disconnect_rsp(struct pending_cmd *cmd, void *data)
+{
+	struct mgmt_cp_disconnect *cp = cmd->cmd;
+	struct sock **sk = data;
+	struct mgmt_rp_disconnect rp;
+
+	bacpy(&rp.bdaddr, &cp->bdaddr);
+
+	cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
+
+	*sk = cmd->sk;
+	sock_hold(*sk);
+
+	mgmt_pending_remove(cmd);
+}
+
+int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
+{
+	struct mgmt_ev_disconnected ev;
+	struct sock *sk = NULL;
+	int err;
+
+	mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
+
+	bacpy(&ev.bdaddr, bdaddr);
+
+	err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
+
+	if (sk)
+		sock_put(sk);
+
+	return err;
+}
+
+int mgmt_disconnect_failed(u16 index)
+{
+	struct pending_cmd *cmd;
+	int err;
+
+	cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, index);
+	if (!cmd)
+		return -ENOENT;
+
+	err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
+
+	mgmt_pending_remove(cmd);
+
+	return err;
+}
+
+int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
+{
+	struct mgmt_ev_connect_failed ev;
+
+	bacpy(&ev.bdaddr, bdaddr);
+	ev.status = status;
+
+	return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
+}
+
+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
+{
+	struct mgmt_ev_pin_code_request ev;
+
+	bacpy(&ev.bdaddr, bdaddr);
+
+	return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
+									NULL);
+}
+
+int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
+{
+	struct pending_cmd *cmd;
+	struct mgmt_rp_pin_code_reply rp;
+	int err;
+
+	cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, index);
+	if (!cmd)
+		return -ENOENT;
+
+	bacpy(&rp.bdaddr, bdaddr);
+	rp.status = status;
+
+	err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
+								sizeof(rp));
+
+	mgmt_pending_remove(cmd);
+
+	return err;
+}
+
+int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
+{
+	struct pending_cmd *cmd;
+	struct mgmt_rp_pin_code_reply rp;
+	int err;
+
+	cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, index);
+	if (!cmd)
+		return -ENOENT;
+
+	bacpy(&rp.bdaddr, bdaddr);
+	rp.status = status;
+
+	err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
+								sizeof(rp));
+
+	mgmt_pending_remove(cmd);
+
+	return err;
+}
+
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value)
+{
+	struct mgmt_ev_user_confirm_request ev;
+
+	BT_DBG("hci%u", index);
+
+	bacpy(&ev.bdaddr, bdaddr);
+	put_unaligned_le32(value, &ev.value);
+
+	return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
+									NULL);
+}
+
+static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
+								u8 opcode)
+{
+	struct pending_cmd *cmd;
+	struct mgmt_rp_user_confirm_reply rp;
+	int err;
+
+	cmd = mgmt_pending_find(opcode, index);
+	if (!cmd)
+		return -ENOENT;
+
+	bacpy(&rp.bdaddr, bdaddr);
+	rp.status = status;
+	err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
+
+	mgmt_pending_remove(cmd);
+
+	return err;
+}
+
+int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
+{
+	return confirm_reply_complete(index, bdaddr, status,
+						MGMT_OP_USER_CONFIRM_REPLY);
+}
+
+int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
+{
+	return confirm_reply_complete(index, bdaddr, status,
+					MGMT_OP_USER_CONFIRM_NEG_REPLY);
+}
+
+int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
 {
-	struct mgmt_ev_index_added ev;
+	struct mgmt_ev_auth_failed ev;
 
-	put_unaligned_le16(index, &ev.index);
+	bacpy(&ev.bdaddr, bdaddr);
+	ev.status = status;
 
-	return mgmt_event(MGMT_EV_INDEX_REMOVED, &ev, sizeof(ev));
+	return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
 }
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 6b83776..c997393 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2154,8 +2154,6 @@ static int __init rfcomm_init(void)
 {
 	int err;
 
-	l2cap_load();
-
 	hci_register_cb(&rfcomm_cb);
 
 	rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index d7b9af4..c258796 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -832,7 +832,7 @@ static int rfcomm_tty_write_room(struct tty_struct *tty)
 	return room;
 }
 
-static int rfcomm_tty_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
+static int rfcomm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 {
 	BT_DBG("tty %p cmd 0x%02x", tty, cmd);
 
@@ -1091,7 +1091,7 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
 	}
 }
 
-static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
+static int rfcomm_tty_tiocmget(struct tty_struct *tty)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
 
@@ -1100,7 +1100,7 @@ static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp)
 	return dev->modem_status;
 }
 
-static int rfcomm_tty_tiocmset(struct tty_struct *tty, struct file *filp, unsigned int set, unsigned int clear)
+static int rfcomm_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
 {
 	struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data;
 	struct rfcomm_dlc *dlc = dev->dlc;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 960c6d1..42fdffd 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -50,8 +50,6 @@
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/sco.h>
 
-#define VERSION "0.6"
-
 static int disable_esco;
 
 static const struct proto_ops sco_sock_ops;
@@ -192,20 +190,21 @@ static int sco_connect(struct sock *sk)
 
 	hci_dev_lock_bh(hdev);
 
-	err = -ENOMEM;
-
 	if (lmp_esco_capable(hdev) && !disable_esco)
 		type = ESCO_LINK;
 	else
 		type = SCO_LINK;
 
 	hcon = hci_connect(hdev, type, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING);
-	if (!hcon)
+	if (IS_ERR(hcon)) {
+		err = PTR_ERR(hcon);
 		goto done;
+	}
 
 	conn = sco_conn_add(hcon, 0);
 	if (!conn) {
 		hci_conn_put(hcon);
+		err = -ENOMEM;
 		goto done;
 	}
 
@@ -703,6 +702,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
 			break;
 		}
 
+		memset(&cinfo, 0, sizeof(cinfo));
 		cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
 		memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
 
@@ -1023,7 +1023,7 @@ static struct hci_proto sco_hci_proto = {
 	.recv_scodata	= sco_recv_scodata
 };
 
-static int __init sco_init(void)
+int __init sco_init(void)
 {
 	int err;
 
@@ -1051,7 +1051,6 @@ static int __init sco_init(void)
 			BT_ERR("Failed to create SCO debug file");
 	}
 
-	BT_INFO("SCO (Voice Link) ver %s", VERSION);
 	BT_INFO("SCO socket layer initialized");
 
 	return 0;
@@ -1061,7 +1060,7 @@ error:
 	return err;
 }
 
-static void __exit sco_exit(void)
+void __exit sco_exit(void)
 {
 	debugfs_remove(sco_debugfs);
 
@@ -1074,14 +1073,5 @@ static void __exit sco_exit(void)
 	proto_unregister(&sco_proto);
 }
 
-module_init(sco_init);
-module_exit(sco_exit);
-
 module_param(disable_esco, bool, 0644);
 MODULE_PARM_DESC(disable_esco, "Disable eSCO connection creation");
-
-MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
-MODULE_DESCRIPTION("Bluetooth SCO ver " VERSION);
-MODULE_VERSION(VERSION);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("bt-proto-2");
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 5564435..21e5901 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -78,6 +78,8 @@ static int br_dev_open(struct net_device *dev)
 {
 	struct net_bridge *br = netdev_priv(dev);
 
+	netif_carrier_off(dev);
+
 	br_features_recompute(br);
 	netif_start_queue(dev);
 	br_stp_enable_bridge(br);
@@ -94,6 +96,8 @@ static int br_dev_stop(struct net_device *dev)
 {
 	struct net_bridge *br = netdev_priv(dev);
 
+	netif_carrier_off(dev);
+
 	br_stp_disable_bridge(br);
 	br_multicast_stop(br);
 
@@ -297,6 +301,21 @@ void br_netpoll_disable(struct net_bridge_port *p)
 
 #endif
 
+static int br_add_slave(struct net_device *dev, struct net_device *slave_dev)
+
+{
+	struct net_bridge *br = netdev_priv(dev);
+
+	return br_add_if(br, slave_dev);
+}
+
+static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
+{
+	struct net_bridge *br = netdev_priv(dev);
+
+	return br_del_if(br, slave_dev);
+}
+
 static const struct ethtool_ops br_ethtool_ops = {
 	.get_drvinfo    = br_getinfo,
 	.get_link	= ethtool_op_get_link,
@@ -326,6 +345,8 @@ static const struct net_device_ops br_netdev_ops = {
 	.ndo_netpoll_cleanup	 = br_netpoll_cleanup,
 	.ndo_poll_controller	 = br_poll_controller,
 #endif
+	.ndo_add_slave		 = br_add_slave,
+	.ndo_del_slave		 = br_del_slave,
 };
 
 static void br_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index d9d1e2b..dce8f00 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -148,6 +148,8 @@ static void del_nbp(struct net_bridge_port *p)
 
 	netdev_rx_handler_unregister(dev);
 
+	netdev_set_master(dev, NULL);
+
 	br_multicast_del_port(p);
 
 	kobject_uevent(&p->kobj, KOBJ_REMOVE);
@@ -365,7 +367,7 @@ int br_min_mtu(const struct net_bridge *br)
 void br_features_recompute(struct net_bridge *br)
 {
 	struct net_bridge_port *p;
-	unsigned long features, mask;
+	u32 features, mask;
 
 	features = mask = br->feature_mask;
 	if (list_empty(&br->port_list))
@@ -379,7 +381,7 @@ void br_features_recompute(struct net_bridge *br)
 	}
 
 done:
-	br->dev->features = netdev_fix_features(features, NULL);
+	br->dev->features = netdev_fix_features(br->dev, features);
 }
 
 /* called with RTNL */
@@ -429,10 +431,14 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (br_netpoll_info(br) && ((err = br_netpoll_enable(p))))
 		goto err3;
 
-	err = netdev_rx_handler_register(dev, br_handle_frame, p);
+	err = netdev_set_master(dev, br->dev);
 	if (err)
 		goto err3;
 
+	err = netdev_rx_handler_register(dev, br_handle_frame, p);
+	if (err)
+		goto err4;
+
 	dev->priv_flags |= IFF_BRIDGE_PORT;
 
 	dev_disable_lro(dev);
@@ -455,6 +461,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	kobject_uevent(&p->kobj, KOBJ_ADD);
 
 	return 0;
+
+err4:
+	netdev_set_master(dev, NULL);
 err3:
 	sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 88e4aa9..e216079 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -139,21 +139,22 @@ static inline int is_link_local(const unsigned char *dest)
  * Return NULL if skb is handled
  * note: already called with rcu_read_lock
  */
-struct sk_buff *br_handle_frame(struct sk_buff *skb)
+rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
 {
 	struct net_bridge_port *p;
+	struct sk_buff *skb = *pskb;
 	const unsigned char *dest = eth_hdr(skb)->h_dest;
 	br_should_route_hook_t *rhook;
 
 	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
-		return skb;
+		return RX_HANDLER_PASS;
 
 	if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
 		goto drop;
 
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (!skb)
-		return NULL;
+		return RX_HANDLER_CONSUMED;
 
 	p = br_port_get_rcu(skb->dev);
 
@@ -167,10 +168,12 @@ struct sk_buff *br_handle_frame(struct sk_buff *skb)
 			goto forward;
 
 		if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
-			    NULL, br_handle_local_finish))
-			return NULL;	/* frame consumed by filter */
-		else
-			return skb;	/* continue processing */
+			    NULL, br_handle_local_finish)) {
+			return RX_HANDLER_CONSUMED; /* consumed by filter */
+		} else {
+			*pskb = skb;
+			return RX_HANDLER_PASS;	/* continue processing */
+		}
 	}
 
 forward:
@@ -178,8 +181,10 @@ forward:
 	case BR_STATE_FORWARDING:
 		rhook = rcu_dereference(br_should_route_hook);
 		if (rhook) {
-			if ((*rhook)(skb))
-				return skb;
+			if ((*rhook)(skb)) {
+				*pskb = skb;
+				return RX_HANDLER_PASS;
+			}
 			dest = eth_hdr(skb)->h_dest;
 		}
 		/* fall through */
@@ -194,5 +199,5 @@ forward:
 drop:
 		kfree_skb(skb);
 	}
-	return NULL;
+	return RX_HANDLER_CONSUMED;
 }
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 4b5b66d..008ff6c 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -412,10 +412,6 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
 	nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;
 	if (dnat_took_place(skb)) {
 		if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) {
-			struct flowi fl = {
-				.fl4_dst = iph->daddr,
-				.fl4_tos = RT_TOS(iph->tos),
-			};
 			struct in_device *in_dev = __in_dev_get_rcu(dev);
 
 			/* If err equals -EHOSTUNREACH the error is due to a
@@ -428,14 +424,16 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
 			if (err != -EHOSTUNREACH || !in_dev || IN_DEV_FORWARD(in_dev))
 				goto free_skb;
 
-			if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+			rt = ip_route_output(dev_net(dev), iph->daddr, 0,
+					     RT_TOS(iph->tos), 0);
+			if (!IS_ERR(rt)) {
 				/* - Bridged-and-DNAT'ed traffic doesn't
 				 *   require ip_forwarding. */
-				if (((struct dst_entry *)rt)->dev == dev) {
-					skb_dst_set(skb, (struct dst_entry *)rt);
+				if (rt->dst.dev == dev) {
+					skb_dst_set(skb, &rt->dst);
 					goto bridged_dnat;
 				}
-				dst_release((struct dst_entry *)rt);
+				ip_rt_put(rt);
 			}
 free_skb:
 			kfree_skb(skb);
@@ -741,6 +739,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff *skb,
 		nf_bridge->mask |= BRNF_PKT_TYPE;
 	}
 
+	if (br_parse_ip_options(skb))
+		return NF_DROP;
+
 	/* The physdev module checks on this */
 	nf_bridge->mask |= BRNF_BRIDGED;
 	nf_bridge->physoutdev = skb->dev;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 4e1b620..19e2f46 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -182,7 +182,7 @@ struct net_bridge
 	struct br_cpu_netstats __percpu *stats;
 	spinlock_t			hash_lock;
 	struct hlist_head		hash[BR_HASH_SIZE];
-	unsigned long			feature_mask;
+	u32				feature_mask;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct rtable 			fake_rtable;
 	bool				nf_call_iptables;
@@ -379,7 +379,7 @@ extern void br_features_recompute(struct net_bridge *br);
 
 /* br_input.c */
 extern int br_handle_frame_finish(struct sk_buff *skb);
-extern struct sk_buff *br_handle_frame(struct sk_buff *skb);
+extern rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
 
 /* br_ioctl.c */
 extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index 57186d8..7370d14 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -375,12 +375,12 @@ static void br_make_forwarding(struct net_bridge_port *p)
 	if (p->state != BR_STATE_BLOCKING)
 		return;
 
-	if (br->forward_delay == 0) {
+	if (br->stp_enabled == BR_NO_STP || br->forward_delay == 0) {
 		p->state = BR_STATE_FORWARDING;
 		br_topology_change_detection(br);
 		del_timer(&p->forward_delay_timer);
 	}
-	else if (p->br->stp_enabled == BR_KERNEL_STP)
+	else if (br->stp_enabled == BR_KERNEL_STP)
 		p->state = BR_STATE_LISTENING;
 	else
 		p->state = BR_STATE_LEARNING;
@@ -397,28 +397,37 @@ static void br_make_forwarding(struct net_bridge_port *p)
 void br_port_state_selection(struct net_bridge *br)
 {
 	struct net_bridge_port *p;
+	unsigned int liveports = 0;
 
 	/* Don't change port states if userspace is handling STP */
 	if (br->stp_enabled == BR_USER_STP)
 		return;
 
 	list_for_each_entry(p, &br->port_list, list) {
-		if (p->state != BR_STATE_DISABLED) {
-			if (p->port_no == br->root_port) {
-				p->config_pending = 0;
-				p->topology_change_ack = 0;
-				br_make_forwarding(p);
-			} else if (br_is_designated_port(p)) {
-				del_timer(&p->message_age_timer);
-				br_make_forwarding(p);
-			} else {
-				p->config_pending = 0;
-				p->topology_change_ack = 0;
-				br_make_blocking(p);
-			}
+		if (p->state == BR_STATE_DISABLED)
+			continue;
+
+		if (p->port_no == br->root_port) {
+			p->config_pending = 0;
+			p->topology_change_ack = 0;
+			br_make_forwarding(p);
+		} else if (br_is_designated_port(p)) {
+			del_timer(&p->message_age_timer);
+			br_make_forwarding(p);
+		} else {
+			p->config_pending = 0;
+			p->topology_change_ack = 0;
+			br_make_blocking(p);
 		}
 
+		if (p->state == BR_STATE_FORWARDING)
+			++liveports;
 	}
+
+	if (liveports == 0)
+		netif_carrier_off(br->dev);
+	else
+		netif_carrier_on(br->dev);
 }
 
 /* called under bridge lock */
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 7b22456..3e96514 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -94,6 +94,7 @@ static void br_forward_delay_timer_expired(unsigned long arg)
 		p->state = BR_STATE_FORWARDING;
 		if (br_is_designated_for_some_port(br))
 			br_topology_change_detection(br);
+		netif_carrier_on(br->dev);
 	}
 	br_log_state(p);
 	spin_unlock(&br->lock);
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c
index 50a46af..2ed0056 100644
--- a/net/bridge/netfilter/ebt_ip6.c
+++ b/net/bridge/netfilter/ebt_ip6.c
@@ -22,9 +22,15 @@
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_bridge/ebt_ip6.h>
 
-struct tcpudphdr {
-	__be16 src;
-	__be16 dst;
+union pkthdr {
+	struct {
+		__be16 src;
+		__be16 dst;
+	} tcpudphdr;
+	struct {
+		u8 type;
+		u8 code;
+	} icmphdr;
 };
 
 static bool
@@ -33,8 +39,8 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct ebt_ip6_info *info = par->matchinfo;
 	const struct ipv6hdr *ih6;
 	struct ipv6hdr _ip6h;
-	const struct tcpudphdr *pptr;
-	struct tcpudphdr _ports;
+	const union pkthdr *pptr;
+	union pkthdr _pkthdr;
 
 	ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h);
 	if (ih6 == NULL)
@@ -56,26 +62,34 @@ ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par)
 			return false;
 		if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO))
 			return false;
-		if (!(info->bitmask & EBT_IP6_DPORT) &&
-		    !(info->bitmask & EBT_IP6_SPORT))
+		if (!(info->bitmask & ( EBT_IP6_DPORT |
+					EBT_IP6_SPORT | EBT_IP6_ICMP6)))
 			return true;
-		pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports),
-					  &_ports);
+
+		/* min icmpv6 headersize is 4, so sizeof(_pkthdr) is ok. */
+		pptr = skb_header_pointer(skb, offset_ph, sizeof(_pkthdr),
+					  &_pkthdr);
 		if (pptr == NULL)
 			return false;
 		if (info->bitmask & EBT_IP6_DPORT) {
-			u32 dst = ntohs(pptr->dst);
+			u16 dst = ntohs(pptr->tcpudphdr.dst);
 			if (FWINV(dst < info->dport[0] ||
 				  dst > info->dport[1], EBT_IP6_DPORT))
 				return false;
 		}
 		if (info->bitmask & EBT_IP6_SPORT) {
-			u32 src = ntohs(pptr->src);
+			u16 src = ntohs(pptr->tcpudphdr.src);
 			if (FWINV(src < info->sport[0] ||
 				  src > info->sport[1], EBT_IP6_SPORT))
 			return false;
 		}
-		return true;
+		if ((info->bitmask & EBT_IP6_ICMP6) &&
+		     FWINV(pptr->icmphdr.type < info->icmpv6_type[0] ||
+			   pptr->icmphdr.type > info->icmpv6_type[1] ||
+			   pptr->icmphdr.code < info->icmpv6_code[0] ||
+			   pptr->icmphdr.code > info->icmpv6_code[1],
+							EBT_IP6_ICMP6))
+			return false;
 	}
 	return true;
 }
@@ -103,6 +117,14 @@ static int ebt_ip6_mt_check(const struct xt_mtchk_param *par)
 		return -EINVAL;
 	if (info->bitmask & EBT_IP6_SPORT && info->sport[0] > info->sport[1])
 		return -EINVAL;
+	if (info->bitmask & EBT_IP6_ICMP6) {
+		if ((info->invflags & EBT_IP6_PROTO) ||
+		     info->protocol != IPPROTO_ICMPV6)
+			return -EINVAL;
+		if (info->icmpv6_type[0] > info->icmpv6_type[1] ||
+		    info->icmpv6_code[0] > info->icmpv6_code[1])
+			return -EINVAL;
+	}
 	return 0;
 }
 
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 16df053..893669c 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1107,6 +1107,8 @@ static int do_replace(struct net *net, const void __user *user,
 	if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
 		return -ENOMEM;
 
+	tmp.name[sizeof(tmp.name) - 1] = 0;
+
 	countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
 	newinfo = vmalloc(sizeof(*newinfo) + countersize);
 	if (!newinfo)
@@ -1764,6 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info,
 
 	newinfo->entries_size = size;
 
+	xt_compat_init_offsets(AF_INET, info->nentries);
 	return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
 							entries, newinfo);
 }
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index c665de7..f1f98d9 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -23,10 +23,8 @@
 #include <asm/atomic.h>
 
 #define MAX_PHY_LAYERS 7
-#define PHY_NAME_LEN 20
 
 #define container_obj(layr) container_of(layr, struct cfcnfg, layer)
-#define RFM_FRAGMENT_SIZE 4030
 
 /* Information about CAIF physical interfaces held by Config Module in order
  * to manage physical interfaces
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c
index d3ed264..27dab26 100644
--- a/net/caif/cfdgml.c
+++ b/net/caif/cfdgml.c
@@ -18,7 +18,6 @@
 #define DGM_CMD_BIT  0x80
 #define DGM_FLOW_OFF 0x81
 #define DGM_FLOW_ON  0x80
-#define DGM_CTRL_PKT_SIZE 1
 #define DGM_MTU 1500
 
 static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt);
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c
index 9297f7d..8303fe3 100644
--- a/net/caif/cfserl.c
+++ b/net/caif/cfserl.c
@@ -25,7 +25,6 @@ struct cfserl {
 	spinlock_t sync;
 	bool usestx;
 };
-#define STXLEN(layr) (layr->usestx ? 1 : 0)
 
 static int cfserl_receive(struct cflayer *layr, struct cfpkt *pkt);
 static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt);
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c
index efad410..315c0d6 100644
--- a/net/caif/cfutill.c
+++ b/net/caif/cfutill.c
@@ -20,7 +20,7 @@
 #define UTIL_REMOTE_SHUTDOWN 0x82
 #define UTIL_FLOW_OFF 0x81
 #define UTIL_FLOW_ON  0x80
-#define UTIL_CTRL_PKT_SIZE 1
+
 static int cfutill_receive(struct cflayer *layr, struct cfpkt *pkt);
 static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt);
 
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c
index 3b425b1..c3b1dec 100644
--- a/net/caif/cfveil.c
+++ b/net/caif/cfveil.c
@@ -17,7 +17,7 @@
 #define VEI_FLOW_OFF 0x81
 #define VEI_FLOW_ON  0x80
 #define VEI_SET_PIN  0x82
-#define VEI_CTRL_PKT_SIZE 1
+
 #define container_obj(layr) container_of(layr, struct cfsrvl, layer)
 
 static int cfvei_receive(struct cflayer *layr, struct cfpkt *pkt);
diff --git a/net/ceph/armor.c b/net/ceph/armor.c
index eb2a666..1fc1ee1 100644
--- a/net/ceph/armor.c
+++ b/net/ceph/armor.c
@@ -78,8 +78,10 @@ int ceph_unarmor(char *dst, const char *src, const char *end)
 	while (src < end) {
 		int a, b, c, d;
 
-		if (src < end && src[0] == '\n')
+		if (src[0] == '\n') {
 			src++;
+			continue;
+		}
 		if (src + 4 > end)
 			return -EINVAL;
 		a = decode_bits(src[0]);
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index f3e4a13..95f96ab 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -62,6 +62,7 @@ const char *ceph_msg_type_name(int type)
 	case CEPH_MSG_OSD_MAP: return "osd_map";
 	case CEPH_MSG_OSD_OP: return "osd_op";
 	case CEPH_MSG_OSD_OPREPLY: return "osd_opreply";
+	case CEPH_MSG_WATCH_NOTIFY: return "watch_notify";
 	default: return "unknown";
 	}
 }
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 3e20a12..02212ed 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -22,10 +22,15 @@
 #define OSD_OPREPLY_FRONT_LEN	512
 
 static const struct ceph_connection_operations osd_con_ops;
-static int __kick_requests(struct ceph_osd_client *osdc,
-			  struct ceph_osd *kickosd);
 
-static void kick_requests(struct ceph_osd_client *osdc, struct ceph_osd *osd);
+static void send_queued(struct ceph_osd_client *osdc);
+static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd);
+static void __register_request(struct ceph_osd_client *osdc,
+			       struct ceph_osd_request *req);
+static void __unregister_linger_request(struct ceph_osd_client *osdc,
+					struct ceph_osd_request *req);
+static int __send_request(struct ceph_osd_client *osdc,
+			  struct ceph_osd_request *req);
 
 static int op_needs_trail(int op)
 {
@@ -34,6 +39,7 @@ static int op_needs_trail(int op)
 	case CEPH_OSD_OP_SETXATTR:
 	case CEPH_OSD_OP_CMPXATTR:
 	case CEPH_OSD_OP_CALL:
+	case CEPH_OSD_OP_NOTIFY:
 		return 1;
 	default:
 		return 0;
@@ -209,6 +215,8 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
 	init_completion(&req->r_completion);
 	init_completion(&req->r_safe_completion);
 	INIT_LIST_HEAD(&req->r_unsafe_item);
+	INIT_LIST_HEAD(&req->r_linger_item);
+	INIT_LIST_HEAD(&req->r_linger_osd);
 	req->r_flags = flags;
 
 	WARN_ON((flags & (CEPH_OSD_FLAG_READ|CEPH_OSD_FLAG_WRITE)) == 0);
@@ -315,6 +323,24 @@ static void osd_req_encode_op(struct ceph_osd_request *req,
 		break;
 	case CEPH_OSD_OP_STARTSYNC:
 		break;
+	case CEPH_OSD_OP_NOTIFY:
+		{
+			__le32 prot_ver = cpu_to_le32(src->watch.prot_ver);
+			__le32 timeout = cpu_to_le32(src->watch.timeout);
+
+			BUG_ON(!req->r_trail);
+
+			ceph_pagelist_append(req->r_trail,
+						&prot_ver, sizeof(prot_ver));
+			ceph_pagelist_append(req->r_trail,
+						&timeout, sizeof(timeout));
+		}
+	case CEPH_OSD_OP_NOTIFY_ACK:
+	case CEPH_OSD_OP_WATCH:
+		dst->watch.cookie = cpu_to_le64(src->watch.cookie);
+		dst->watch.ver = cpu_to_le64(src->watch.ver);
+		dst->watch.flag = src->watch.flag;
+		break;
 	default:
 		pr_err("unrecognized osd opcode %d\n", dst->op);
 		WARN_ON(1);
@@ -529,6 +555,45 @@ __lookup_request_ge(struct ceph_osd_client *osdc,
 	return NULL;
 }
 
+/*
+ * Resubmit requests pending on the given osd.
+ */
+static void __kick_osd_requests(struct ceph_osd_client *osdc,
+				struct ceph_osd *osd)
+{
+	struct ceph_osd_request *req, *nreq;
+	int err;
+
+	dout("__kick_osd_requests osd%d\n", osd->o_osd);
+	err = __reset_osd(osdc, osd);
+	if (err == -EAGAIN)
+		return;
+
+	list_for_each_entry(req, &osd->o_requests, r_osd_item) {
+		list_move(&req->r_req_lru_item, &osdc->req_unsent);
+		dout("requeued %p tid %llu osd%d\n", req, req->r_tid,
+		     osd->o_osd);
+		if (!req->r_linger)
+			req->r_flags |= CEPH_OSD_FLAG_RETRY;
+	}
+
+	list_for_each_entry_safe(req, nreq, &osd->o_linger_requests,
+				 r_linger_osd) {
+		__unregister_linger_request(osdc, req);
+		__register_request(osdc, req);
+		list_move(&req->r_req_lru_item, &osdc->req_unsent);
+		dout("requeued lingering %p tid %llu osd%d\n", req, req->r_tid,
+		     osd->o_osd);
+	}
+}
+
+static void kick_osd_requests(struct ceph_osd_client *osdc,
+			      struct ceph_osd *kickosd)
+{
+	mutex_lock(&osdc->request_mutex);
+	__kick_osd_requests(osdc, kickosd);
+	mutex_unlock(&osdc->request_mutex);
+}
 
 /*
  * If the osd connection drops, we need to resubmit all requests.
@@ -543,7 +608,8 @@ static void osd_reset(struct ceph_connection *con)
 	dout("osd_reset osd%d\n", osd->o_osd);
 	osdc = osd->o_osdc;
 	down_read(&osdc->map_sem);
-	kick_requests(osdc, osd);
+	kick_osd_requests(osdc, osd);
+	send_queued(osdc);
 	up_read(&osdc->map_sem);
 }
 
@@ -561,6 +627,7 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc)
 	atomic_set(&osd->o_ref, 1);
 	osd->o_osdc = osdc;
 	INIT_LIST_HEAD(&osd->o_requests);
+	INIT_LIST_HEAD(&osd->o_linger_requests);
 	INIT_LIST_HEAD(&osd->o_osd_lru);
 	osd->o_incarnation = 1;
 
@@ -650,7 +717,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd)
 	int ret = 0;
 
 	dout("__reset_osd %p osd%d\n", osd, osd->o_osd);
-	if (list_empty(&osd->o_requests)) {
+	if (list_empty(&osd->o_requests) &&
+	    list_empty(&osd->o_linger_requests)) {
 		__remove_osd(osdc, osd);
 	} else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd],
 			  &osd->o_con.peer_addr,
@@ -723,10 +791,9 @@ static void __cancel_osd_timeout(struct ceph_osd_client *osdc)
  * Register request, assign tid.  If this is the first request, set up
  * the timeout event.
  */
-static void register_request(struct ceph_osd_client *osdc,
-			     struct ceph_osd_request *req)
+static void __register_request(struct ceph_osd_client *osdc,
+			       struct ceph_osd_request *req)
 {
-	mutex_lock(&osdc->request_mutex);
 	req->r_tid = ++osdc->last_tid;
 	req->r_request->hdr.tid = cpu_to_le64(req->r_tid);
 	INIT_LIST_HEAD(&req->r_req_lru_item);
@@ -740,6 +807,13 @@ static void register_request(struct ceph_osd_client *osdc,
 		dout(" first request, scheduling timeout\n");
 		__schedule_osd_timeout(osdc);
 	}
+}
+
+static void register_request(struct ceph_osd_client *osdc,
+			     struct ceph_osd_request *req)
+{
+	mutex_lock(&osdc->request_mutex);
+	__register_request(osdc, req);
 	mutex_unlock(&osdc->request_mutex);
 }
 
@@ -758,9 +832,14 @@ static void __unregister_request(struct ceph_osd_client *osdc,
 		ceph_con_revoke(&req->r_osd->o_con, req->r_request);
 
 		list_del_init(&req->r_osd_item);
-		if (list_empty(&req->r_osd->o_requests))
+		if (list_empty(&req->r_osd->o_requests) &&
+		    list_empty(&req->r_osd->o_linger_requests)) {
+			dout("moving osd to %p lru\n", req->r_osd);
 			__move_osd_to_lru(osdc, req->r_osd);
-		req->r_osd = NULL;
+		}
+		if (list_empty(&req->r_osd_item) &&
+		    list_empty(&req->r_linger_item))
+			req->r_osd = NULL;
 	}
 
 	ceph_osdc_put_request(req);
@@ -781,20 +860,72 @@ static void __cancel_request(struct ceph_osd_request *req)
 		ceph_con_revoke(&req->r_osd->o_con, req->r_request);
 		req->r_sent = 0;
 	}
-	list_del_init(&req->r_req_lru_item);
 }
 
+static void __register_linger_request(struct ceph_osd_client *osdc,
+				    struct ceph_osd_request *req)
+{
+	dout("__register_linger_request %p\n", req);
+	list_add_tail(&req->r_linger_item, &osdc->req_linger);
+	list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests);
+}
+
+static void __unregister_linger_request(struct ceph_osd_client *osdc,
+					struct ceph_osd_request *req)
+{
+	dout("__unregister_linger_request %p\n", req);
+	if (req->r_osd) {
+		list_del_init(&req->r_linger_item);
+		list_del_init(&req->r_linger_osd);
+
+		if (list_empty(&req->r_osd->o_requests) &&
+		    list_empty(&req->r_osd->o_linger_requests)) {
+			dout("moving osd to %p lru\n", req->r_osd);
+			__move_osd_to_lru(osdc, req->r_osd);
+		}
+		req->r_osd = NULL;
+	}
+}
+
+void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc,
+					 struct ceph_osd_request *req)
+{
+	mutex_lock(&osdc->request_mutex);
+	if (req->r_linger) {
+		__unregister_linger_request(osdc, req);
+		ceph_osdc_put_request(req);
+	}
+	mutex_unlock(&osdc->request_mutex);
+}
+EXPORT_SYMBOL(ceph_osdc_unregister_linger_request);
+
+void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc,
+				  struct ceph_osd_request *req)
+{
+	if (!req->r_linger) {
+		dout("set_request_linger %p\n", req);
+		req->r_linger = 1;
+		/*
+		 * caller is now responsible for calling
+		 * unregister_linger_request
+		 */
+		ceph_osdc_get_request(req);
+	}
+}
+EXPORT_SYMBOL(ceph_osdc_set_request_linger);
+
 /*
  * Pick an osd (the first 'up' osd in the pg), allocate the osd struct
  * (as needed), and set the request r_osd appropriately.  If there is
- * no up osd, set r_osd to NULL.
+ * no up osd, set r_osd to NULL.  Move the request to the appropiate list
+ * (unsent, homeless) or leave on in-flight lru.
  *
  * Return 0 if unchanged, 1 if changed, or negative on error.
  *
  * Caller should hold map_sem for read and request_mutex.
  */
-static int __map_osds(struct ceph_osd_client *osdc,
-		      struct ceph_osd_request *req)
+static int __map_request(struct ceph_osd_client *osdc,
+			 struct ceph_osd_request *req)
 {
 	struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base;
 	struct ceph_pg pgid;
@@ -802,11 +933,13 @@ static int __map_osds(struct ceph_osd_client *osdc,
 	int o = -1, num = 0;
 	int err;
 
-	dout("map_osds %p tid %lld\n", req, req->r_tid);
+	dout("map_request %p tid %lld\n", req, req->r_tid);
 	err = ceph_calc_object_layout(&reqhead->layout, req->r_oid,
 				      &req->r_file_layout, osdc->osdmap);
-	if (err)
+	if (err) {
+		list_move(&req->r_req_lru_item, &osdc->req_notarget);
 		return err;
+	}
 	pgid = reqhead->layout.ol_pgid;
 	req->r_pgid = pgid;
 
@@ -823,7 +956,7 @@ static int __map_osds(struct ceph_osd_client *osdc,
 	    (req->r_osd == NULL && o == -1))
 		return 0;  /* no change */
 
-	dout("map_osds tid %llu pgid %d.%x osd%d (was osd%d)\n",
+	dout("map_request tid %llu pgid %d.%x osd%d (was osd%d)\n",
 	     req->r_tid, le32_to_cpu(pgid.pool), le16_to_cpu(pgid.ps), o,
 	     req->r_osd ? req->r_osd->o_osd : -1);
 
@@ -841,10 +974,12 @@ static int __map_osds(struct ceph_osd_client *osdc,
 	if (!req->r_osd && o >= 0) {
 		err = -ENOMEM;
 		req->r_osd = create_osd(osdc);
-		if (!req->r_osd)
+		if (!req->r_osd) {
+			list_move(&req->r_req_lru_item, &osdc->req_notarget);
 			goto out;
+		}
 
-		dout("map_osds osd %p is osd%d\n", req->r_osd, o);
+		dout("map_request osd %p is osd%d\n", req->r_osd, o);
 		req->r_osd->o_osd = o;
 		req->r_osd->o_con.peer_name.num = cpu_to_le64(o);
 		__insert_osd(osdc, req->r_osd);
@@ -855,6 +990,9 @@ static int __map_osds(struct ceph_osd_client *osdc,
 	if (req->r_osd) {
 		__remove_osd_from_lru(req->r_osd);
 		list_add(&req->r_osd_item, &req->r_osd->o_requests);
+		list_move(&req->r_req_lru_item, &osdc->req_unsent);
+	} else {
+		list_move(&req->r_req_lru_item, &osdc->req_notarget);
 	}
 	err = 1;   /* osd or pg changed */
 
@@ -869,16 +1007,6 @@ static int __send_request(struct ceph_osd_client *osdc,
 			  struct ceph_osd_request *req)
 {
 	struct ceph_osd_request_head *reqhead;
-	int err;
-
-	err = __map_osds(osdc, req);
-	if (err < 0)
-		return err;
-	if (req->r_osd == NULL) {
-		dout("send_request %p no up osds in pg\n", req);
-		ceph_monc_request_next_osdmap(&osdc->client->monc);
-		return 0;
-	}
 
 	dout("send_request %p tid %llu to osd%d flags %d\n",
 	     req, req->r_tid, req->r_osd->o_osd, req->r_flags);
@@ -898,6 +1026,21 @@ static int __send_request(struct ceph_osd_client *osdc,
 }
 
 /*
+ * Send any requests in the queue (req_unsent).
+ */
+static void send_queued(struct ceph_osd_client *osdc)
+{
+	struct ceph_osd_request *req, *tmp;
+
+	dout("send_queued\n");
+	mutex_lock(&osdc->request_mutex);
+	list_for_each_entry_safe(req, tmp, &osdc->req_unsent, r_req_lru_item) {
+		__send_request(osdc, req);
+	}
+	mutex_unlock(&osdc->request_mutex);
+}
+
+/*
  * Timeout callback, called every N seconds when 1 or more osd
  * requests has been active for more than N seconds.  When this
  * happens, we ping all OSDs with requests who have timed out to
@@ -916,30 +1059,13 @@ static void handle_timeout(struct work_struct *work)
 	unsigned long keepalive =
 		osdc->client->options->osd_keepalive_timeout * HZ;
 	unsigned long last_stamp = 0;
-	struct rb_node *p;
 	struct list_head slow_osds;
-
 	dout("timeout\n");
 	down_read(&osdc->map_sem);
 
 	ceph_monc_request_next_osdmap(&osdc->client->monc);
 
 	mutex_lock(&osdc->request_mutex);
-	for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
-		req = rb_entry(p, struct ceph_osd_request, r_node);
-
-		if (req->r_resend) {
-			int err;
-
-			dout("osdc resending prev failed %lld\n", req->r_tid);
-			err = __send_request(osdc, req);
-			if (err)
-				dout("osdc failed again on %lld\n", req->r_tid);
-			else
-				req->r_resend = false;
-			continue;
-		}
-	}
 
 	/*
 	 * reset osds that appear to be _really_ unresponsive.  this
@@ -963,7 +1089,7 @@ static void handle_timeout(struct work_struct *work)
 		BUG_ON(!osd);
 		pr_warning(" tid %llu timed out on osd%d, will reset osd\n",
 			   req->r_tid, osd->o_osd);
-		__kick_requests(osdc, osd);
+		__kick_osd_requests(osdc, osd);
 	}
 
 	/*
@@ -991,7 +1117,7 @@ static void handle_timeout(struct work_struct *work)
 
 	__schedule_osd_timeout(osdc);
 	mutex_unlock(&osdc->request_mutex);
-
+	send_queued(osdc);
 	up_read(&osdc->map_sem);
 }
 
@@ -1035,7 +1161,6 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
 	    numops * sizeof(struct ceph_osd_op))
 		goto bad;
 	dout("handle_reply %p tid %llu result %d\n", msg, tid, (int)result);
-
 	/* lookup */
 	mutex_lock(&osdc->request_mutex);
 	req = __lookup_request(osdc, tid);
@@ -1079,6 +1204,9 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
 
 	dout("handle_reply tid %llu flags %d\n", tid, flags);
 
+	if (req->r_linger && (flags & CEPH_OSD_FLAG_ONDISK))
+		__register_linger_request(osdc, req);
+
 	/* either this is a read, or we got the safe response */
 	if (result < 0 ||
 	    (flags & CEPH_OSD_FLAG_ONDISK) ||
@@ -1099,6 +1227,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg,
 	}
 
 done:
+	dout("req=%p req->r_linger=%d\n", req, req->r_linger);
 	ceph_osdc_put_request(req);
 	return;
 
@@ -1109,108 +1238,83 @@ bad:
 	ceph_msg_dump(msg);
 }
 
-
-static int __kick_requests(struct ceph_osd_client *osdc,
-			  struct ceph_osd *kickosd)
+static void reset_changed_osds(struct ceph_osd_client *osdc)
 {
-	struct ceph_osd_request *req;
 	struct rb_node *p, *n;
-	int needmap = 0;
-	int err;
 
-	dout("kick_requests osd%d\n", kickosd ? kickosd->o_osd : -1);
-	if (kickosd) {
-		err = __reset_osd(osdc, kickosd);
-		if (err == -EAGAIN)
-			return 1;
-	} else {
-		for (p = rb_first(&osdc->osds); p; p = n) {
-			struct ceph_osd *osd =
-				rb_entry(p, struct ceph_osd, o_node);
-
-			n = rb_next(p);
-			if (!ceph_osd_is_up(osdc->osdmap, osd->o_osd) ||
-			    memcmp(&osd->o_con.peer_addr,
-				   ceph_osd_addr(osdc->osdmap,
-						 osd->o_osd),
-				   sizeof(struct ceph_entity_addr)) != 0)
-				__reset_osd(osdc, osd);
-		}
+	for (p = rb_first(&osdc->osds); p; p = n) {
+		struct ceph_osd *osd = rb_entry(p, struct ceph_osd, o_node);
+
+		n = rb_next(p);
+		if (!ceph_osd_is_up(osdc->osdmap, osd->o_osd) ||
+		    memcmp(&osd->o_con.peer_addr,
+			   ceph_osd_addr(osdc->osdmap,
+					 osd->o_osd),
+			   sizeof(struct ceph_entity_addr)) != 0)
+			__reset_osd(osdc, osd);
 	}
+}
+
+/*
+ * Requeue requests whose mapping to an OSD has changed.  If requests map to
+ * no osd, request a new map.
+ *
+ * Caller should hold map_sem for read and request_mutex.
+ */
+static void kick_requests(struct ceph_osd_client *osdc)
+{
+	struct ceph_osd_request *req, *nreq;
+	struct rb_node *p;
+	int needmap = 0;
+	int err;
 
+	dout("kick_requests\n");
+	mutex_lock(&osdc->request_mutex);
 	for (p = rb_first(&osdc->requests); p; p = rb_next(p)) {
 		req = rb_entry(p, struct ceph_osd_request, r_node);
-
-		if (req->r_resend) {
-			dout(" r_resend set on tid %llu\n", req->r_tid);
-			__cancel_request(req);
-			goto kick;
-		}
-		if (req->r_osd && kickosd == req->r_osd) {
-			__cancel_request(req);
-			goto kick;
+		err = __map_request(osdc, req);
+		if (err < 0)
+			continue;  /* error */
+		if (req->r_osd == NULL) {
+			dout("%p tid %llu maps to no osd\n", req, req->r_tid);
+			needmap++;  /* request a newer map */
+		} else if (err > 0) {
+			dout("%p tid %llu requeued on osd%d\n", req, req->r_tid,
+			     req->r_osd ? req->r_osd->o_osd : -1);
+			if (!req->r_linger)
+				req->r_flags |= CEPH_OSD_FLAG_RETRY;
 		}
+	}
+
+	list_for_each_entry_safe(req, nreq, &osdc->req_linger,
+				 r_linger_item) {
+		dout("linger req=%p req->r_osd=%p\n", req, req->r_osd);
 
-		err = __map_osds(osdc, req);
+		err = __map_request(osdc, req);
 		if (err == 0)
-			continue;  /* no change */
-		if (err < 0) {
-			/*
-			 * FIXME: really, we should set the request
-			 * error and fail if this isn't a 'nofail'
-			 * request, but that's a fair bit more
-			 * complicated to do.  So retry!
-			 */
-			dout(" setting r_resend on %llu\n", req->r_tid);
-			req->r_resend = true;
-			continue;
-		}
+			continue;  /* no change and no osd was specified */
+		if (err < 0)
+			continue;  /* hrm! */
 		if (req->r_osd == NULL) {
 			dout("tid %llu maps to no valid osd\n", req->r_tid);
 			needmap++;  /* request a newer map */
 			continue;
 		}
 
-kick:
-		dout("kicking %p tid %llu osd%d\n", req, req->r_tid,
+		dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid,
 		     req->r_osd ? req->r_osd->o_osd : -1);
-		req->r_flags |= CEPH_OSD_FLAG_RETRY;
-		err = __send_request(osdc, req);
-		if (err) {
-			dout(" setting r_resend on %llu\n", req->r_tid);
-			req->r_resend = true;
-		}
+		__unregister_linger_request(osdc, req);
+		__register_request(osdc, req);
 	}
-
-	return needmap;
-}
-
-/*
- * Resubmit osd requests whose osd or osd address has changed.  Request
- * a new osd map if osds are down, or we are otherwise unable to determine
- * how to direct a request.
- *
- * Close connections to down osds.
- *
- * If @who is specified, resubmit requests for that specific osd.
- *
- * Caller should hold map_sem for read and request_mutex.
- */
-static void kick_requests(struct ceph_osd_client *osdc,
-			  struct ceph_osd *kickosd)
-{
-	int needmap;
-
-	mutex_lock(&osdc->request_mutex);
-	needmap = __kick_requests(osdc, kickosd);
 	mutex_unlock(&osdc->request_mutex);
 
 	if (needmap) {
 		dout("%d requests for down osds, need new map\n", needmap);
 		ceph_monc_request_next_osdmap(&osdc->client->monc);
 	}
-
 }
+
+
 /*
  * Process updated osd map.
  *
@@ -1263,6 +1367,8 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
 				ceph_osdmap_destroy(osdc->osdmap);
 				osdc->osdmap = newmap;
 			}
+			kick_requests(osdc);
+			reset_changed_osds(osdc);
 		} else {
 			dout("ignoring incremental map %u len %d\n",
 			     epoch, maplen);
@@ -1300,6 +1406,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
 			osdc->osdmap = newmap;
 			if (oldmap)
 				ceph_osdmap_destroy(oldmap);
+			kick_requests(osdc);
 		}
 		p += maplen;
 		nr_maps--;
@@ -1308,8 +1415,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg)
 done:
 	downgrade_write(&osdc->map_sem);
 	ceph_monc_got_osdmap(&osdc->client->monc, osdc->osdmap->epoch);
-	if (newmap)
-		kick_requests(osdc, NULL);
+	send_queued(osdc);
 	up_read(&osdc->map_sem);
 	wake_up_all(&osdc->client->auth_wq);
 	return;
@@ -1322,6 +1428,223 @@ bad:
 }
 
 /*
+ * watch/notify callback event infrastructure
+ *
+ * These callbacks are used both for watch and notify operations.
+ */
+static void __release_event(struct kref *kref)
+{
+	struct ceph_osd_event *event =
+		container_of(kref, struct ceph_osd_event, kref);
+
+	dout("__release_event %p\n", event);
+	kfree(event);
+}
+
+static void get_event(struct ceph_osd_event *event)
+{
+	kref_get(&event->kref);
+}
+
+void ceph_osdc_put_event(struct ceph_osd_event *event)
+{
+	kref_put(&event->kref, __release_event);
+}
+EXPORT_SYMBOL(ceph_osdc_put_event);
+
+static void __insert_event(struct ceph_osd_client *osdc,
+			     struct ceph_osd_event *new)
+{
+	struct rb_node **p = &osdc->event_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_osd_event *event = NULL;
+
+	while (*p) {
+		parent = *p;
+		event = rb_entry(parent, struct ceph_osd_event, node);
+		if (new->cookie < event->cookie)
+			p = &(*p)->rb_left;
+		else if (new->cookie > event->cookie)
+			p = &(*p)->rb_right;
+		else
+			BUG();
+	}
+
+	rb_link_node(&new->node, parent, p);
+	rb_insert_color(&new->node, &osdc->event_tree);
+}
+
+static struct ceph_osd_event *__find_event(struct ceph_osd_client *osdc,
+					        u64 cookie)
+{
+	struct rb_node **p = &osdc->event_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct ceph_osd_event *event = NULL;
+
+	while (*p) {
+		parent = *p;
+		event = rb_entry(parent, struct ceph_osd_event, node);
+		if (cookie < event->cookie)
+			p = &(*p)->rb_left;
+		else if (cookie > event->cookie)
+			p = &(*p)->rb_right;
+		else
+			return event;
+	}
+	return NULL;
+}
+
+static void __remove_event(struct ceph_osd_event *event)
+{
+	struct ceph_osd_client *osdc = event->osdc;
+
+	if (!RB_EMPTY_NODE(&event->node)) {
+		dout("__remove_event removed %p\n", event);
+		rb_erase(&event->node, &osdc->event_tree);
+		ceph_osdc_put_event(event);
+	} else {
+		dout("__remove_event didn't remove %p\n", event);
+	}
+}
+
+int ceph_osdc_create_event(struct ceph_osd_client *osdc,
+			   void (*event_cb)(u64, u64, u8, void *),
+			   int one_shot, void *data,
+			   struct ceph_osd_event **pevent)
+{
+	struct ceph_osd_event *event;
+
+	event = kmalloc(sizeof(*event), GFP_NOIO);
+	if (!event)
+		return -ENOMEM;
+
+	dout("create_event %p\n", event);
+	event->cb = event_cb;
+	event->one_shot = one_shot;
+	event->data = data;
+	event->osdc = osdc;
+	INIT_LIST_HEAD(&event->osd_node);
+	kref_init(&event->kref);   /* one ref for us */
+	kref_get(&event->kref);    /* one ref for the caller */
+	init_completion(&event->completion);
+
+	spin_lock(&osdc->event_lock);
+	event->cookie = ++osdc->event_count;
+	__insert_event(osdc, event);
+	spin_unlock(&osdc->event_lock);
+
+	*pevent = event;
+	return 0;
+}
+EXPORT_SYMBOL(ceph_osdc_create_event);
+
+void ceph_osdc_cancel_event(struct ceph_osd_event *event)
+{
+	struct ceph_osd_client *osdc = event->osdc;
+
+	dout("cancel_event %p\n", event);
+	spin_lock(&osdc->event_lock);
+	__remove_event(event);
+	spin_unlock(&osdc->event_lock);
+	ceph_osdc_put_event(event); /* caller's */
+}
+EXPORT_SYMBOL(ceph_osdc_cancel_event);
+
+
+static void do_event_work(struct work_struct *work)
+{
+	struct ceph_osd_event_work *event_work =
+		container_of(work, struct ceph_osd_event_work, work);
+	struct ceph_osd_event *event = event_work->event;
+	u64 ver = event_work->ver;
+	u64 notify_id = event_work->notify_id;
+	u8 opcode = event_work->opcode;
+
+	dout("do_event_work completing %p\n", event);
+	event->cb(ver, notify_id, opcode, event->data);
+	complete(&event->completion);
+	dout("do_event_work completed %p\n", event);
+	ceph_osdc_put_event(event);
+	kfree(event_work);
+}
+
+
+/*
+ * Process osd watch notifications
+ */
+void handle_watch_notify(struct ceph_osd_client *osdc, struct ceph_msg *msg)
+{
+	void *p, *end;
+	u8 proto_ver;
+	u64 cookie, ver, notify_id;
+	u8 opcode;
+	struct ceph_osd_event *event;
+	struct ceph_osd_event_work *event_work;
+
+	p = msg->front.iov_base;
+	end = p + msg->front.iov_len;
+
+	ceph_decode_8_safe(&p, end, proto_ver, bad);
+	ceph_decode_8_safe(&p, end, opcode, bad);
+	ceph_decode_64_safe(&p, end, cookie, bad);
+	ceph_decode_64_safe(&p, end, ver, bad);
+	ceph_decode_64_safe(&p, end, notify_id, bad);
+
+	spin_lock(&osdc->event_lock);
+	event = __find_event(osdc, cookie);
+	if (event) {
+		get_event(event);
+		if (event->one_shot)
+			__remove_event(event);
+	}
+	spin_unlock(&osdc->event_lock);
+	dout("handle_watch_notify cookie %lld ver %lld event %p\n",
+	     cookie, ver, event);
+	if (event) {
+		event_work = kmalloc(sizeof(*event_work), GFP_NOIO);
+		INIT_WORK(&event_work->work, do_event_work);
+		if (!event_work) {
+			dout("ERROR: could not allocate event_work\n");
+			goto done_err;
+		}
+		event_work->event = event;
+		event_work->ver = ver;
+		event_work->notify_id = notify_id;
+		event_work->opcode = opcode;
+		if (!queue_work(osdc->notify_wq, &event_work->work)) {
+			dout("WARNING: failed to queue notify event work\n");
+			goto done_err;
+		}
+	}
+
+	return;
+
+done_err:
+	complete(&event->completion);
+	ceph_osdc_put_event(event);
+	return;
+
+bad:
+	pr_err("osdc handle_watch_notify corrupt msg\n");
+	return;
+}
+
+int ceph_osdc_wait_event(struct ceph_osd_event *event, unsigned long timeout)
+{
+	int err;
+
+	dout("wait_event %p\n", event);
+	err = wait_for_completion_interruptible_timeout(&event->completion,
+							timeout * HZ);
+	ceph_osdc_put_event(event);
+	if (err > 0)
+		err = 0;
+	dout("wait_event %p returns %d\n", event, err);
+	return err;
+}
+EXPORT_SYMBOL(ceph_osdc_wait_event);
+
+/*
  * Register request, send initial attempt.
  */
 int ceph_osdc_start_request(struct ceph_osd_client *osdc,
@@ -1347,15 +1670,22 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc,
 	 * the request still han't been touched yet.
 	 */
 	if (req->r_sent == 0) {
-		rc = __send_request(osdc, req);
-		if (rc) {
-			if (nofail) {
-				dout("osdc_start_request failed send, "
-				     " marking %lld\n", req->r_tid);
-				req->r_resend = true;
-				rc = 0;
-			} else {
-				__unregister_request(osdc, req);
+		rc = __map_request(osdc, req);
+		if (rc < 0)
+			return rc;
+		if (req->r_osd == NULL) {
+			dout("send_request %p no up osds in pg\n", req);
+			ceph_monc_request_next_osdmap(&osdc->client->monc);
+		} else {
+			rc = __send_request(osdc, req);
+			if (rc) {
+				if (nofail) {
+					dout("osdc_start_request failed send, "
+					     " will retry %lld\n", req->r_tid);
+					rc = 0;
+				} else {
+					__unregister_request(osdc, req);
+				}
 			}
 		}
 	}
@@ -1441,9 +1771,15 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
 	INIT_LIST_HEAD(&osdc->osd_lru);
 	osdc->requests = RB_ROOT;
 	INIT_LIST_HEAD(&osdc->req_lru);
+	INIT_LIST_HEAD(&osdc->req_unsent);
+	INIT_LIST_HEAD(&osdc->req_notarget);
+	INIT_LIST_HEAD(&osdc->req_linger);
 	osdc->num_requests = 0;
 	INIT_DELAYED_WORK(&osdc->timeout_work, handle_timeout);
 	INIT_DELAYED_WORK(&osdc->osds_timeout_work, handle_osds_timeout);
+	spin_lock_init(&osdc->event_lock);
+	osdc->event_tree = RB_ROOT;
+	osdc->event_count = 0;
 
 	schedule_delayed_work(&osdc->osds_timeout_work,
 	   round_jiffies_relative(osdc->client->options->osd_idle_ttl * HZ));
@@ -1463,6 +1799,13 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
 				"osd_op_reply");
 	if (err < 0)
 		goto out_msgpool;
+
+	osdc->notify_wq = create_singlethread_workqueue("ceph-watch-notify");
+	if (IS_ERR(osdc->notify_wq)) {
+		err = PTR_ERR(osdc->notify_wq);
+		osdc->notify_wq = NULL;
+		goto out_msgpool;
+	}
 	return 0;
 
 out_msgpool:
@@ -1476,6 +1819,8 @@ EXPORT_SYMBOL(ceph_osdc_init);
 
 void ceph_osdc_stop(struct ceph_osd_client *osdc)
 {
+	flush_workqueue(osdc->notify_wq);
+	destroy_workqueue(osdc->notify_wq);
 	cancel_delayed_work_sync(&osdc->timeout_work);
 	cancel_delayed_work_sync(&osdc->osds_timeout_work);
 	if (osdc->osdmap) {
@@ -1483,6 +1828,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
 		osdc->osdmap = NULL;
 	}
 	remove_old_osds(osdc, 1);
+	WARN_ON(!RB_EMPTY_ROOT(&osdc->osds));
 	mempool_destroy(osdc->req_mempool);
 	ceph_msgpool_destroy(&osdc->msgpool_op);
 	ceph_msgpool_destroy(&osdc->msgpool_op_reply);
@@ -1591,6 +1937,9 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg)
 	case CEPH_MSG_OSD_OPREPLY:
 		handle_reply(osdc, msg, con);
 		break;
+	case CEPH_MSG_WATCH_NOTIFY:
+		handle_watch_notify(osdc, msg);
+		break;
 
 	default:
 		pr_err("received unknown message type %d %s\n", type,
@@ -1684,6 +2033,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con,
 
 	switch (type) {
 	case CEPH_MSG_OSD_MAP:
+	case CEPH_MSG_WATCH_NOTIFY:
 		return ceph_msg_new(type, front, GFP_NOFS);
 	case CEPH_MSG_OSD_OPREPLY:
 		return get_reply(con, hdr, skip);
diff --git a/net/core/dev.c b/net/core/dev.c
index 6561021..0b88eba 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -132,6 +132,7 @@
 #include <trace/events/skb.h>
 #include <linux/pci.h>
 #include <linux/inetdevice.h>
+#include <linux/cpu_rmap.h>
 
 #include "net-sysfs.h"
 
@@ -1297,7 +1298,7 @@ static int __dev_close(struct net_device *dev)
 	return retval;
 }
 
-int dev_close_many(struct list_head *head)
+static int dev_close_many(struct list_head *head)
 {
 	struct net_device *dev, *tmp;
 	LIST_HEAD(tmp_list);
@@ -1605,6 +1606,48 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 	rcu_read_unlock();
 }
 
+/* netif_setup_tc - Handle tc mappings on real_num_tx_queues change
+ * @dev: Network device
+ * @txq: number of queues available
+ *
+ * If real_num_tx_queues is changed the tc mappings may no longer be
+ * valid. To resolve this verify the tc mapping remains valid and if
+ * not NULL the mapping. With no priorities mapping to this
+ * offset/count pair it will no longer be used. In the worst case TC0
+ * is invalid nothing can be done so disable priority mappings. If is
+ * expected that drivers will fix this mapping if they can before
+ * calling netif_set_real_num_tx_queues.
+ */
+static void netif_setup_tc(struct net_device *dev, unsigned int txq)
+{
+	int i;
+	struct netdev_tc_txq *tc = &dev->tc_to_txq[0];
+
+	/* If TC0 is invalidated disable TC mapping */
+	if (tc->offset + tc->count > txq) {
+		pr_warning("Number of in use tx queues changed "
+			   "invalidating tc mappings. Priority "
+			   "traffic classification disabled!\n");
+		dev->num_tc = 0;
+		return;
+	}
+
+	/* Invalidated prio to tc mappings set to TC0 */
+	for (i = 1; i < TC_BITMASK + 1; i++) {
+		int q = netdev_get_prio_tc_map(dev, i);
+
+		tc = &dev->tc_to_txq[q];
+		if (tc->offset + tc->count > txq) {
+			pr_warning("Number of in use tx queues "
+				   "changed. Priority %i to tc "
+				   "mapping %i is no longer valid "
+				   "setting map to 0\n",
+				   i, q);
+			netdev_set_prio_tc_map(dev, i, 0);
+		}
+	}
+}
+
 /*
  * Routine to help set real_num_tx_queues. To avoid skbs mapped to queues
  * greater then real_num_tx_queues stale skbs on the qdisc must be flushed.
@@ -1616,7 +1659,8 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
 	if (txq < 1 || txq > dev->num_tx_queues)
 		return -EINVAL;
 
-	if (dev->reg_state == NETREG_REGISTERED) {
+	if (dev->reg_state == NETREG_REGISTERED ||
+	    dev->reg_state == NETREG_UNREGISTERING) {
 		ASSERT_RTNL();
 
 		rc = netdev_queue_update_kobjects(dev, dev->real_num_tx_queues,
@@ -1624,6 +1668,9 @@ int netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
 		if (rc)
 			return rc;
 
+		if (dev->num_tc)
+			netif_setup_tc(dev, txq);
+
 		if (txq < dev->real_num_tx_queues)
 			qdisc_reset_all_tx_gt(dev, txq);
 	}
@@ -1823,7 +1870,7 @@ EXPORT_SYMBOL(skb_checksum_help);
  *	It may return NULL if the skb requires no segmentation.  This is
  *	only possible when GSO is used for verifying header integrity.
  */
-struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
+struct sk_buff *skb_gso_segment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 	struct packet_type *ptype;
@@ -2011,7 +2058,7 @@ static bool can_checksum_protocol(unsigned long features, __be16 protocol)
 		 protocol == htons(ETH_P_FCOE)));
 }
 
-static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features)
+static u32 harmonize_features(struct sk_buff *skb, __be16 protocol, u32 features)
 {
 	if (!can_checksum_protocol(features, protocol)) {
 		features &= ~NETIF_F_ALL_CSUM;
@@ -2023,10 +2070,10 @@ static int harmonize_features(struct sk_buff *skb, __be16 protocol, int features
 	return features;
 }
 
-int netif_skb_features(struct sk_buff *skb)
+u32 netif_skb_features(struct sk_buff *skb)
 {
 	__be16 protocol = skb->protocol;
-	int features = skb->dev->features;
+	u32 features = skb->dev->features;
 
 	if (protocol == htons(ETH_P_8021Q)) {
 		struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
@@ -2071,7 +2118,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 	int rc = NETDEV_TX_OK;
 
 	if (likely(!skb->next)) {
-		int features;
+		u32 features;
 
 		/*
 		 * If device doesnt need skb->dst, release it right now while
@@ -2173,6 +2220,8 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
 		  unsigned int num_tx_queues)
 {
 	u32 hash;
+	u16 qoffset = 0;
+	u16 qcount = num_tx_queues;
 
 	if (skb_rx_queue_recorded(skb)) {
 		hash = skb_get_rx_queue(skb);
@@ -2181,13 +2230,19 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb,
 		return hash;
 	}
 
+	if (dev->num_tc) {
+		u8 tc = netdev_get_prio_tc_map(dev, skb->priority);
+		qoffset = dev->tc_to_txq[tc].offset;
+		qcount = dev->tc_to_txq[tc].count;
+	}
+
 	if (skb->sk && skb->sk->sk_hash)
 		hash = skb->sk->sk_hash;
 	else
 		hash = (__force u16) skb->protocol ^ skb->rxhash;
 	hash = jhash_1word(hash, hashrnd);
 
-	return (u16) (((u64) hash * num_tx_queues) >> 32);
+	return (u16) (((u64) hash * qcount) >> 32) + qoffset;
 }
 EXPORT_SYMBOL(__skb_tx_hash);
 
@@ -2284,15 +2339,18 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 				 struct netdev_queue *txq)
 {
 	spinlock_t *root_lock = qdisc_lock(q);
-	bool contended = qdisc_is_running(q);
+	bool contended;
 	int rc;
 
+	qdisc_skb_cb(skb)->pkt_len = skb->len;
+	qdisc_calculate_pkt_len(skb, q);
 	/*
 	 * Heuristic to force contended enqueues to serialize on a
 	 * separate lock before trying to get qdisc main lock.
 	 * This permits __QDISC_STATE_RUNNING owner to get the lock more often
 	 * and dequeue packets faster.
 	 */
+	contended = qdisc_is_running(q);
 	if (unlikely(contended))
 		spin_lock(&q->busylock);
 
@@ -2310,7 +2368,6 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 		if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
 			skb_dst_force(skb);
 
-		qdisc_skb_cb(skb)->pkt_len = skb->len;
 		qdisc_bstats_update(q, skb);
 
 		if (sch_direct_xmit(skb, q, dev, txq, root_lock)) {
@@ -2325,7 +2382,7 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 		rc = NET_XMIT_SUCCESS;
 	} else {
 		skb_dst_force(skb);
-		rc = qdisc_enqueue_root(skb, q);
+		rc = q->enqueue(skb, q) & NET_XMIT_MASK;
 		if (qdisc_run_begin(q)) {
 			if (unlikely(contended)) {
 				spin_unlock(&q->busylock);
@@ -2544,6 +2601,54 @@ EXPORT_SYMBOL(__skb_get_rxhash);
 struct rps_sock_flow_table __rcu *rps_sock_flow_table __read_mostly;
 EXPORT_SYMBOL(rps_sock_flow_table);
 
+static struct rps_dev_flow *
+set_rps_cpu(struct net_device *dev, struct sk_buff *skb,
+	    struct rps_dev_flow *rflow, u16 next_cpu)
+{
+	u16 tcpu;
+
+	tcpu = rflow->cpu = next_cpu;
+	if (tcpu != RPS_NO_CPU) {
+#ifdef CONFIG_RFS_ACCEL
+		struct netdev_rx_queue *rxqueue;
+		struct rps_dev_flow_table *flow_table;
+		struct rps_dev_flow *old_rflow;
+		u32 flow_id;
+		u16 rxq_index;
+		int rc;
+
+		/* Should we steer this flow to a different hardware queue? */
+		if (!skb_rx_queue_recorded(skb) || !dev->rx_cpu_rmap ||
+		    !(dev->features & NETIF_F_NTUPLE))
+			goto out;
+		rxq_index = cpu_rmap_lookup_index(dev->rx_cpu_rmap, next_cpu);
+		if (rxq_index == skb_get_rx_queue(skb))
+			goto out;
+
+		rxqueue = dev->_rx + rxq_index;
+		flow_table = rcu_dereference(rxqueue->rps_flow_table);
+		if (!flow_table)
+			goto out;
+		flow_id = skb->rxhash & flow_table->mask;
+		rc = dev->netdev_ops->ndo_rx_flow_steer(dev, skb,
+							rxq_index, flow_id);
+		if (rc < 0)
+			goto out;
+		old_rflow = rflow;
+		rflow = &flow_table->flows[flow_id];
+		rflow->cpu = next_cpu;
+		rflow->filter = rc;
+		if (old_rflow->filter == rflow->filter)
+			old_rflow->filter = RPS_NO_FILTER;
+	out:
+#endif
+		rflow->last_qtail =
+			per_cpu(softnet_data, tcpu).input_queue_head;
+	}
+
+	return rflow;
+}
+
 /*
  * get_rps_cpu is called from netif_receive_skb and returns the target
  * CPU from the RPS map of the receiving queue for a given skb.
@@ -2615,12 +2720,9 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
 		if (unlikely(tcpu != next_cpu) &&
 		    (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
 		     ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
-		      rflow->last_qtail)) >= 0)) {
-			tcpu = rflow->cpu = next_cpu;
-			if (tcpu != RPS_NO_CPU)
-				rflow->last_qtail = per_cpu(softnet_data,
-				    tcpu).input_queue_head;
-		}
+		      rflow->last_qtail)) >= 0))
+			rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
+
 		if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
 			*rflowp = rflow;
 			cpu = tcpu;
@@ -2641,6 +2743,46 @@ done:
 	return cpu;
 }
 
+#ifdef CONFIG_RFS_ACCEL
+
+/**
+ * rps_may_expire_flow - check whether an RFS hardware filter may be removed
+ * @dev: Device on which the filter was set
+ * @rxq_index: RX queue index
+ * @flow_id: Flow ID passed to ndo_rx_flow_steer()
+ * @filter_id: Filter ID returned by ndo_rx_flow_steer()
+ *
+ * Drivers that implement ndo_rx_flow_steer() should periodically call
+ * this function for each installed filter and remove the filters for
+ * which it returns %true.
+ */
+bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index,
+			 u32 flow_id, u16 filter_id)
+{
+	struct netdev_rx_queue *rxqueue = dev->_rx + rxq_index;
+	struct rps_dev_flow_table *flow_table;
+	struct rps_dev_flow *rflow;
+	bool expire = true;
+	int cpu;
+
+	rcu_read_lock();
+	flow_table = rcu_dereference(rxqueue->rps_flow_table);
+	if (flow_table && flow_id <= flow_table->mask) {
+		rflow = &flow_table->flows[flow_id];
+		cpu = ACCESS_ONCE(rflow->cpu);
+		if (rflow->filter == filter_id && cpu != RPS_NO_CPU &&
+		    ((int)(per_cpu(softnet_data, cpu).input_queue_head -
+			   rflow->last_qtail) <
+		     (int)(10 * flow_table->mask)))
+			expire = false;
+	}
+	rcu_read_unlock();
+	return expire;
+}
+EXPORT_SYMBOL(rps_may_expire_flow);
+
+#endif /* CONFIG_RFS_ACCEL */
+
 /* Called from hardirq (IPI) context */
 static void rps_trigger_softirq(void *data)
 {
@@ -2928,6 +3070,8 @@ out:
  *	on a failure.
  *
  *	The caller must hold the rtnl_mutex.
+ *
+ *	For a general description of rx_handler, see enum rx_handler_result.
  */
 int netdev_rx_handler_register(struct net_device *dev,
 			       rx_handler_func_t *rx_handler,
@@ -2962,64 +3106,32 @@ void netdev_rx_handler_unregister(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
 
-static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
-					      struct net_device *master)
+static void vlan_on_bond_hook(struct sk_buff *skb)
 {
-	if (skb->pkt_type == PACKET_HOST) {
-		u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
-
-		memcpy(dest, master->dev_addr, ETH_ALEN);
-	}
-}
-
-/* On bonding slaves other than the currently active slave, suppress
- * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
- * ARP on active-backup slaves with arp_validate enabled.
- */
-int __skb_bond_should_drop(struct sk_buff *skb, struct net_device *master)
-{
-	struct net_device *dev = skb->dev;
-
-	if (master->priv_flags & IFF_MASTER_ARPMON)
-		dev->last_rx = jiffies;
-
-	if ((master->priv_flags & IFF_MASTER_ALB) &&
-	    (master->priv_flags & IFF_BRIDGE_PORT)) {
-		/* Do address unmangle. The local destination address
-		 * will be always the one master has. Provides the right
-		 * functionality in a bridge.
-		 */
-		skb_bond_set_mac_by_master(skb, master);
-	}
-
-	if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
-		if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
-		    skb->protocol == __cpu_to_be16(ETH_P_ARP))
-			return 0;
-
-		if (master->priv_flags & IFF_MASTER_ALB) {
-			if (skb->pkt_type != PACKET_BROADCAST &&
-			    skb->pkt_type != PACKET_MULTICAST)
-				return 0;
-		}
-		if (master->priv_flags & IFF_MASTER_8023AD &&
-		    skb->protocol == __cpu_to_be16(ETH_P_SLOW))
-			return 0;
+	/*
+	 * Make sure ARP frames received on VLAN interfaces stacked on
+	 * bonding interfaces still make their way to any base bonding
+	 * device that may have registered for a specific ptype.
+	 */
+	if (skb->dev->priv_flags & IFF_802_1Q_VLAN &&
+	    vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING &&
+	    skb->protocol == htons(ETH_P_ARP)) {
+		struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 
-		return 1;
+		if (!skb2)
+			return;
+		skb2->dev = vlan_dev_real_dev(skb->dev);
+		netif_rx(skb2);
 	}
-	return 0;
 }
-EXPORT_SYMBOL(__skb_bond_should_drop);
 
 static int __netif_receive_skb(struct sk_buff *skb)
 {
 	struct packet_type *ptype, *pt_prev;
 	rx_handler_func_t *rx_handler;
 	struct net_device *orig_dev;
-	struct net_device *master;
-	struct net_device *null_or_orig;
-	struct net_device *orig_or_bond;
+	struct net_device *null_or_dev;
+	bool deliver_exact = false;
 	int ret = NET_RX_DROP;
 	__be16 type;
 
@@ -3034,28 +3146,8 @@ static int __netif_receive_skb(struct sk_buff *skb)
 
 	if (!skb->skb_iif)
 		skb->skb_iif = skb->dev->ifindex;
-
-	/*
-	 * bonding note: skbs received on inactive slaves should only
-	 * be delivered to pkt handlers that are exact matches.  Also
-	 * the deliver_no_wcard flag will be set.  If packet handlers
-	 * are sensitive to duplicate packets these skbs will need to
-	 * be dropped at the handler.
-	 */
-	null_or_orig = NULL;
 	orig_dev = skb->dev;
-	master = ACCESS_ONCE(orig_dev->master);
-	if (skb->deliver_no_wcard)
-		null_or_orig = orig_dev;
-	else if (master) {
-		if (skb_bond_should_drop(skb, master)) {
-			skb->deliver_no_wcard = 1;
-			null_or_orig = orig_dev; /* deliver only exact match */
-		} else
-			skb->dev = master;
-	}
 
-	__this_cpu_inc(softnet_data.processed);
 	skb_reset_network_header(skb);
 	skb_reset_transport_header(skb);
 	skb->mac_len = skb->network_header - skb->mac_header;
@@ -3064,6 +3156,10 @@ static int __netif_receive_skb(struct sk_buff *skb)
 
 	rcu_read_lock();
 
+another_round:
+
+	__this_cpu_inc(softnet_data.processed);
+
 #ifdef CONFIG_NET_CLS_ACT
 	if (skb->tc_verd & TC_NCLS) {
 		skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
@@ -3072,8 +3168,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
 #endif
 
 	list_for_each_entry_rcu(ptype, &ptype_all, list) {
-		if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
-		    ptype->dev == orig_dev) {
+		if (!ptype->dev || ptype->dev == skb->dev) {
 			if (pt_prev)
 				ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = ptype;
@@ -3087,16 +3182,24 @@ static int __netif_receive_skb(struct sk_buff *skb)
 ncls:
 #endif
 
-	/* Handle special case of bridge or macvlan */
 	rx_handler = rcu_dereference(skb->dev->rx_handler);
 	if (rx_handler) {
 		if (pt_prev) {
 			ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = NULL;
 		}
-		skb = rx_handler(skb);
-		if (!skb)
+		switch (rx_handler(&skb)) {
+		case RX_HANDLER_CONSUMED:
 			goto out;
+		case RX_HANDLER_ANOTHER:
+			goto another_round;
+		case RX_HANDLER_EXACT:
+			deliver_exact = true;
+		case RX_HANDLER_PASS:
+			break;
+		default:
+			BUG();
+		}
 	}
 
 	if (vlan_tx_tag_present(skb)) {
@@ -3111,24 +3214,17 @@ ncls:
 			goto out;
 	}
 
-	/*
-	 * Make sure frames received on VLAN interfaces stacked on
-	 * bonding interfaces still make their way to any base bonding
-	 * device that may have registered for a specific ptype.  The
-	 * handler may have to adjust skb->dev and orig_dev.
-	 */
-	orig_or_bond = orig_dev;
-	if ((skb->dev->priv_flags & IFF_802_1Q_VLAN) &&
-	    (vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING)) {
-		orig_or_bond = vlan_dev_real_dev(skb->dev);
-	}
+	vlan_on_bond_hook(skb);
+
+	/* deliver only exact match when indicated */
+	null_or_dev = deliver_exact ? skb->dev : NULL;
 
 	type = skb->protocol;
 	list_for_each_entry_rcu(ptype,
 			&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
-		if (ptype->type == type && (ptype->dev == null_or_orig ||
-		     ptype->dev == skb->dev || ptype->dev == orig_dev ||
-		     ptype->dev == orig_or_bond)) {
+		if (ptype->type == type &&
+		    (ptype->dev == null_or_dev || ptype->dev == skb->dev ||
+		     ptype->dev == orig_dev)) {
 			if (pt_prev)
 				ret = deliver_skb(skb, pt_prev, orig_dev);
 			pt_prev = ptype;
@@ -3925,12 +4021,15 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos)
 
 void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct net_device *dev = (v == SEQ_START_TOKEN) ?
-				  first_net_device(seq_file_net(seq)) :
-				  next_net_device((struct net_device *)v);
+	struct net_device *dev = v;
+
+	if (v == SEQ_START_TOKEN)
+		dev = first_net_device_rcu(seq_file_net(seq));
+	else
+		dev = next_net_device_rcu(dev);
 
 	++*pos;
-	return rcu_dereference(dev);
+	return dev;
 }
 
 void dev_seq_stop(struct seq_file *seq, void *v)
@@ -4214,15 +4313,14 @@ static int __init dev_proc_init(void)
 
 
 /**
- *	netdev_set_master	-	set up master/slave pair
+ *	netdev_set_master	-	set up master pointer
  *	@slave: slave device
  *	@master: new master device
  *
  *	Changes the master device of the slave. Pass %NULL to break the
  *	bonding. The caller must hold the RTNL semaphore. On a failure
  *	a negative errno code is returned. On success the reference counts
- *	are adjusted, %RTM_NEWLINK is sent to the routing socket and the
- *	function returns zero.
+ *	are adjusted and the function returns zero.
  */
 int netdev_set_master(struct net_device *slave, struct net_device *master)
 {
@@ -4242,6 +4340,29 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
 		synchronize_net();
 		dev_put(old);
 	}
+	return 0;
+}
+EXPORT_SYMBOL(netdev_set_master);
+
+/**
+ *	netdev_set_bond_master	-	set up bonding master/slave pair
+ *	@slave: slave device
+ *	@master: new master device
+ *
+ *	Changes the master device of the slave. Pass %NULL to break the
+ *	bonding. The caller must hold the RTNL semaphore. On a failure
+ *	a negative errno code is returned. On success %RTM_NEWLINK is sent
+ *	to the routing socket and the function returns zero.
+ */
+int netdev_set_bond_master(struct net_device *slave, struct net_device *master)
+{
+	int err;
+
+	ASSERT_RTNL();
+
+	err = netdev_set_master(slave, master);
+	if (err)
+		return err;
 	if (master)
 		slave->flags |= IFF_SLAVE;
 	else
@@ -4250,7 +4371,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master)
 	rtmsg_ifinfo(RTM_NEWLINK, slave, IFF_SLAVE);
 	return 0;
 }
-EXPORT_SYMBOL(netdev_set_master);
+EXPORT_SYMBOL(netdev_set_bond_master);
 
 static void dev_change_rx_flags(struct net_device *dev, int flags)
 {
@@ -4587,6 +4708,17 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
 EXPORT_SYMBOL(dev_set_mtu);
 
 /**
+ *	dev_set_group - Change group this device belongs to
+ *	@dev: device
+ *	@new_group: group this device should belong to
+ */
+void dev_set_group(struct net_device *dev, int new_group)
+{
+	dev->group = new_group;
+}
+EXPORT_SYMBOL(dev_set_group);
+
+/**
  *	dev_set_mac_address - Change Media Access Control Address
  *	@dev: device
  *	@sa: new address
@@ -5077,41 +5209,55 @@ static void rollback_registered(struct net_device *dev)
 	list_del(&single);
 }
 
-unsigned long netdev_fix_features(unsigned long features, const char *name)
+u32 netdev_fix_features(struct net_device *dev, u32 features)
 {
+	/* Fix illegal checksum combinations */
+	if ((features & NETIF_F_HW_CSUM) &&
+	    (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+		netdev_info(dev, "mixed HW and IP checksum settings.\n");
+		features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
+	}
+
+	if ((features & NETIF_F_NO_CSUM) &&
+	    (features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
+		netdev_info(dev, "mixed no checksumming and other settings.\n");
+		features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+	}
+
 	/* Fix illegal SG+CSUM combinations. */
 	if ((features & NETIF_F_SG) &&
 	    !(features & NETIF_F_ALL_CSUM)) {
-		if (name)
-			printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no "
-			       "checksum feature.\n", name);
+		netdev_info(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_TSO) && !(features & NETIF_F_SG)) {
-		if (name)
-			printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no "
-			       "SG feature.\n", name);
+		netdev_info(dev, "Dropping NETIF_F_TSO since no SG feature.\n");
 		features &= ~NETIF_F_TSO;
 	}
 
+	/* Software GSO depends on SG. */
+	if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) {
+		netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
+		features &= ~NETIF_F_GSO;
+	}
+
+	/* UFO needs SG and checksumming */
 	if (features & NETIF_F_UFO) {
 		/* maybe split UFO into V4 and V6? */
 		if (!((features & NETIF_F_GEN_CSUM) ||
 		    (features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
 			    == (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-			if (name)
-				printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
-				       "since no checksum offload features.\n",
-				       name);
+			netdev_info(dev,
+				"Dropping NETIF_F_UFO since no checksum offload features.\n");
 			features &= ~NETIF_F_UFO;
 		}
 
 		if (!(features & NETIF_F_SG)) {
-			if (name)
-				printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
-				       "since no NETIF_F_SG feature.\n", name);
+			netdev_info(dev,
+				"Dropping NETIF_F_UFO since no NETIF_F_SG feature.\n");
 			features &= ~NETIF_F_UFO;
 		}
 	}
@@ -5120,6 +5266,37 @@ unsigned long netdev_fix_features(unsigned long features, const char *name)
 }
 EXPORT_SYMBOL(netdev_fix_features);
 
+void netdev_update_features(struct net_device *dev)
+{
+	u32 features;
+	int err = 0;
+
+	features = netdev_get_wanted_features(dev);
+
+	if (dev->netdev_ops->ndo_fix_features)
+		features = dev->netdev_ops->ndo_fix_features(dev, features);
+
+	/* driver might be less strict about feature dependencies */
+	features = netdev_fix_features(dev, features);
+
+	if (dev->features == features)
+		return;
+
+	netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
+		dev->features, features);
+
+	if (dev->netdev_ops->ndo_set_features)
+		err = dev->netdev_ops->ndo_set_features(dev, features);
+
+	if (!err)
+		dev->features = features;
+	else if (err < 0)
+		netdev_err(dev,
+			"set_features() failed (%d); wanted 0x%08x, left 0x%08x\n",
+			err, features, dev->features);
+}
+EXPORT_SYMBOL(netdev_update_features);
+
 /**
  *	netif_stacked_transfer_operstate -	transfer operstate
  *	@rootdev: the root or lower level device to transfer state from
@@ -5254,27 +5431,19 @@ int register_netdevice(struct net_device *dev)
 	if (dev->iflink == -1)
 		dev->iflink = dev->ifindex;
 
-	/* Fix illegal checksum combinations */
-	if ((dev->features & NETIF_F_HW_CSUM) &&
-	    (dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-		printk(KERN_NOTICE "%s: mixed HW and IP checksum settings.\n",
-		       dev->name);
-		dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM);
-	}
+	/* Transfer changeable features to wanted_features and enable
+	 * software offloads (GSO and GRO).
+	 */
+	dev->hw_features |= NETIF_F_SOFT_FEATURES;
+	dev->features |= NETIF_F_SOFT_FEATURES;
+	dev->wanted_features = dev->features & dev->hw_features;
 
-	if ((dev->features & NETIF_F_NO_CSUM) &&
-	    (dev->features & (NETIF_F_HW_CSUM|NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))) {
-		printk(KERN_NOTICE "%s: mixed no checksumming and other settings.\n",
-		       dev->name);
-		dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
+	/* Avoid warning from netdev_fix_features() for GSO without SG */
+	if (!(dev->wanted_features & NETIF_F_SG)) {
+		dev->wanted_features &= ~NETIF_F_GSO;
+		dev->features &= ~NETIF_F_GSO;
 	}
 
-	dev->features = netdev_fix_features(dev->features, dev->name);
-
-	/* Enable software GSO if SG is supported. */
-	if (dev->features & NETIF_F_SG)
-		dev->features |= NETIF_F_GSO;
-
 	/* Enable GRO and NETIF_F_HIGHDMA for vlans by default,
 	 * vlan_dev_init() will do the dev->features check, so these features
 	 * are enabled only if supported by underlying device.
@@ -5291,6 +5460,8 @@ int register_netdevice(struct net_device *dev)
 		goto err_uninit;
 	dev->reg_state = NETREG_REGISTERED;
 
+	netdev_update_features(dev);
+
 	/*
 	 *	Default initial state at registry is that the
 	 *	device is present.
@@ -5695,6 +5866,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
 #endif
 
 	strcpy(dev->name, name);
+	dev->group = INIT_NETDEV_GROUP;
 	return dev;
 
 free_all:
@@ -6009,8 +6181,7 @@ static int dev_cpu_callback(struct notifier_block *nfb,
  *	@one to the master device with current feature set @all.  Will not
  *	enable anything that is off in @mask. Returns the new feature set.
  */
-unsigned long netdev_increment_features(unsigned long all, unsigned long one,
-					unsigned long mask)
+u32 netdev_increment_features(u32 all, u32 one, u32 mask)
 {
 	/* If device needs checksumming, downgrade to it. */
 	if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 133fd22..7b39f3e 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -357,8 +357,8 @@ EXPORT_SYMBOL(dev_addr_add_multiple);
 /**
  *	dev_addr_del_multiple - Delete device addresses by another device
  *	@to_dev: device where the addresses will be deleted
- *	@from_dev: device by which addresses the addresses will be deleted
- *	@addr_type: address type - 0 means type will used from from_dev
+ *	@from_dev: device supplying the addresses to be deleted
+ *	@addr_type: address type - 0 means type will be used from from_dev
  *
  *	Deletes addresses in to device by the list of addresses in from device.
  *
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 36e603c..706502f 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -350,7 +350,7 @@ static int __init init_net_drop_monitor(void)
 	struct per_cpu_dm_data *data;
 	int cpu, rc;
 
-	printk(KERN_INFO "Initalizing network drop monitor service\n");
+	printk(KERN_INFO "Initializing network drop monitor service\n");
 
 	if (sizeof(void *) > 8) {
 		printk(KERN_ERR "Unable to store program counters on this arch, Drop monitor failed\n");
diff --git a/net/core/dst.c b/net/core/dst.c
index b99c7c7..91104d3 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -164,7 +164,9 @@ int dst_discard(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(dst_discard);
 
-void *dst_alloc(struct dst_ops *ops)
+const u32 dst_default_metrics[RTAX_MAX];
+
+void *dst_alloc(struct dst_ops *ops, int initial_ref)
 {
 	struct dst_entry *dst;
 
@@ -175,11 +177,12 @@ void *dst_alloc(struct dst_ops *ops)
 	dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC);
 	if (!dst)
 		return NULL;
-	atomic_set(&dst->__refcnt, 0);
+	atomic_set(&dst->__refcnt, initial_ref);
 	dst->ops = ops;
 	dst->lastuse = jiffies;
 	dst->path = dst;
 	dst->input = dst->output = dst_discard;
+	dst_init_metrics(dst, dst_default_metrics, true);
 #if RT_CACHE_DEBUG >= 2
 	atomic_inc(&dst_total);
 #endif
@@ -282,6 +285,42 @@ void dst_release(struct dst_entry *dst)
 }
 EXPORT_SYMBOL(dst_release);
 
+u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old)
+{
+	u32 *p = kmalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC);
+
+	if (p) {
+		u32 *old_p = __DST_METRICS_PTR(old);
+		unsigned long prev, new;
+
+		memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
+
+		new = (unsigned long) p;
+		prev = cmpxchg(&dst->_metrics, old, new);
+
+		if (prev != old) {
+			kfree(p);
+			p = __DST_METRICS_PTR(prev);
+			if (prev & DST_METRICS_READ_ONLY)
+				p = NULL;
+		}
+	}
+	return p;
+}
+EXPORT_SYMBOL(dst_cow_metrics_generic);
+
+/* Caller asserts that dst_metrics_read_only(dst) is false.  */
+void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
+{
+	unsigned long prev, new;
+
+	new = (unsigned long) dst_default_metrics;
+	prev = cmpxchg(&dst->_metrics, old, new);
+	if (prev == old)
+		kfree(__DST_METRICS_PTR(old));
+}
+EXPORT_SYMBOL(__dst_destroy_metrics_generic);
+
 /**
  * skb_dst_set_noref - sets skb dst, without a reference
  * @skb: buffer
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index ff23029..a1086fb 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -34,12 +34,6 @@ u32 ethtool_op_get_link(struct net_device *dev)
 }
 EXPORT_SYMBOL(ethtool_op_get_link);
 
-u32 ethtool_op_get_rx_csum(struct net_device *dev)
-{
-	return (dev->features & NETIF_F_ALL_CSUM) != 0;
-}
-EXPORT_SYMBOL(ethtool_op_get_rx_csum);
-
 u32 ethtool_op_get_tx_csum(struct net_device *dev)
 {
 	return (dev->features & NETIF_F_ALL_CSUM) != 0;
@@ -55,6 +49,7 @@ int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 
 	return 0;
 }
+EXPORT_SYMBOL(ethtool_op_set_tx_csum);
 
 int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
 {
@@ -171,6 +166,381 @@ EXPORT_SYMBOL(ethtool_ntuple_flush);
 
 /* Handlers for each ethtool command */
 
+#define ETHTOOL_DEV_FEATURE_WORDS	1
+
+static void ethtool_get_features_compat(struct net_device *dev,
+	struct ethtool_get_features_block *features)
+{
+	if (!dev->ethtool_ops)
+		return;
+
+	/* getting RX checksum */
+	if (dev->ethtool_ops->get_rx_csum)
+		if (dev->ethtool_ops->get_rx_csum(dev))
+			features[0].active |= NETIF_F_RXCSUM;
+
+	/* mark legacy-changeable features */
+	if (dev->ethtool_ops->set_sg)
+		features[0].available |= NETIF_F_SG;
+	if (dev->ethtool_ops->set_tx_csum)
+		features[0].available |= NETIF_F_ALL_CSUM;
+	if (dev->ethtool_ops->set_tso)
+		features[0].available |= NETIF_F_ALL_TSO;
+	if (dev->ethtool_ops->set_rx_csum)
+		features[0].available |= NETIF_F_RXCSUM;
+	if (dev->ethtool_ops->set_flags)
+		features[0].available |= flags_dup_features;
+}
+
+static int ethtool_set_feature_compat(struct net_device *dev,
+	int (*legacy_set)(struct net_device *, u32),
+	struct ethtool_set_features_block *features, u32 mask)
+{
+	u32 do_set;
+
+	if (!legacy_set)
+		return 0;
+
+	if (!(features[0].valid & mask))
+		return 0;
+
+	features[0].valid &= ~mask;
+
+	do_set = !!(features[0].requested & mask);
+
+	if (legacy_set(dev, do_set) < 0)
+		netdev_info(dev,
+			"Legacy feature change (%s) failed for 0x%08x\n",
+			do_set ? "set" : "clear", mask);
+
+	return 1;
+}
+
+static int ethtool_set_features_compat(struct net_device *dev,
+	struct ethtool_set_features_block *features)
+{
+	int compat;
+
+	if (!dev->ethtool_ops)
+		return 0;
+
+	compat  = ethtool_set_feature_compat(dev, dev->ethtool_ops->set_sg,
+		features, NETIF_F_SG);
+	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tx_csum,
+		features, NETIF_F_ALL_CSUM);
+	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_tso,
+		features, NETIF_F_ALL_TSO);
+	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_rx_csum,
+		features, NETIF_F_RXCSUM);
+	compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_flags,
+		features, flags_dup_features);
+
+	return compat;
+}
+
+static int ethtool_get_features(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_gfeatures cmd = {
+		.cmd = ETHTOOL_GFEATURES,
+		.size = ETHTOOL_DEV_FEATURE_WORDS,
+	};
+	struct ethtool_get_features_block features[ETHTOOL_DEV_FEATURE_WORDS] = {
+		{
+			.available = dev->hw_features,
+			.requested = dev->wanted_features,
+			.active = dev->features,
+			.never_changed = NETIF_F_NEVER_CHANGE,
+		},
+	};
+	u32 __user *sizeaddr;
+	u32 copy_size;
+
+	ethtool_get_features_compat(dev, features);
+
+	sizeaddr = useraddr + offsetof(struct ethtool_gfeatures, size);
+	if (get_user(copy_size, sizeaddr))
+		return -EFAULT;
+
+	if (copy_size > ETHTOOL_DEV_FEATURE_WORDS)
+		copy_size = ETHTOOL_DEV_FEATURE_WORDS;
+
+	if (copy_to_user(useraddr, &cmd, sizeof(cmd)))
+		return -EFAULT;
+	useraddr += sizeof(cmd);
+	if (copy_to_user(useraddr, features, copy_size * sizeof(*features)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int ethtool_set_features(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_sfeatures cmd;
+	struct ethtool_set_features_block features[ETHTOOL_DEV_FEATURE_WORDS];
+	int ret = 0;
+
+	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
+		return -EFAULT;
+	useraddr += sizeof(cmd);
+
+	if (cmd.size != ETHTOOL_DEV_FEATURE_WORDS)
+		return -EINVAL;
+
+	if (copy_from_user(features, useraddr, sizeof(features)))
+		return -EFAULT;
+
+	if (features[0].valid & ~NETIF_F_ETHTOOL_BITS)
+		return -EINVAL;
+
+	if (ethtool_set_features_compat(dev, features))
+		ret |= ETHTOOL_F_COMPAT;
+
+	if (features[0].valid & ~dev->hw_features) {
+		features[0].valid &= dev->hw_features;
+		ret |= ETHTOOL_F_UNSUPPORTED;
+	}
+
+	dev->wanted_features &= ~features[0].valid;
+	dev->wanted_features |= features[0].valid & features[0].requested;
+	netdev_update_features(dev);
+
+	if ((dev->wanted_features ^ dev->features) & features[0].valid)
+		ret |= ETHTOOL_F_WISH;
+
+	return ret;
+}
+
+static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GSTRING_LEN] = {
+	/* NETIF_F_SG */              "tx-scatter-gather",
+	/* NETIF_F_IP_CSUM */         "tx-checksum-ipv4",
+	/* NETIF_F_NO_CSUM */         "tx-checksum-unneeded",
+	/* NETIF_F_HW_CSUM */         "tx-checksum-ip-generic",
+	/* NETIF_F_IPV6_CSUM */       "tx_checksum-ipv6",
+	/* NETIF_F_HIGHDMA */         "highdma",
+	/* NETIF_F_FRAGLIST */        "tx-scatter-gather-fraglist",
+	/* NETIF_F_HW_VLAN_TX */      "tx-vlan-hw-insert",
+
+	/* NETIF_F_HW_VLAN_RX */      "rx-vlan-hw-parse",
+	/* NETIF_F_HW_VLAN_FILTER */  "rx-vlan-filter",
+	/* NETIF_F_VLAN_CHALLENGED */ "vlan-challenged",
+	/* NETIF_F_GSO */             "tx-generic-segmentation",
+	/* NETIF_F_LLTX */            "tx-lockless",
+	/* NETIF_F_NETNS_LOCAL */     "netns-local",
+	/* NETIF_F_GRO */             "rx-gro",
+	/* NETIF_F_LRO */             "rx-lro",
+
+	/* NETIF_F_TSO */             "tx-tcp-segmentation",
+	/* NETIF_F_UFO */             "tx-udp-fragmentation",
+	/* NETIF_F_GSO_ROBUST */      "tx-gso-robust",
+	/* NETIF_F_TSO_ECN */         "tx-tcp-ecn-segmentation",
+	/* NETIF_F_TSO6 */            "tx-tcp6-segmentation",
+	/* NETIF_F_FSO */             "tx-fcoe-segmentation",
+	"",
+	"",
+
+	/* NETIF_F_FCOE_CRC */        "tx-checksum-fcoe-crc",
+	/* NETIF_F_SCTP_CSUM */       "tx-checksum-sctp",
+	/* NETIF_F_FCOE_MTU */        "fcoe-mtu",
+	/* NETIF_F_NTUPLE */          "rx-ntuple-filter",
+	/* NETIF_F_RXHASH */          "rx-hashing",
+	/* NETIF_F_RXCSUM */          "rx-checksum",
+	"",
+	"",
+};
+
+static int __ethtool_get_sset_count(struct net_device *dev, int sset)
+{
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+
+	if (sset == ETH_SS_FEATURES)
+		return ARRAY_SIZE(netdev_features_strings);
+
+	if (ops && ops->get_sset_count && ops->get_strings)
+		return ops->get_sset_count(dev, sset);
+	else
+		return -EOPNOTSUPP;
+}
+
+static void __ethtool_get_strings(struct net_device *dev,
+	u32 stringset, u8 *data)
+{
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+
+	if (stringset == ETH_SS_FEATURES)
+		memcpy(data, netdev_features_strings,
+			sizeof(netdev_features_strings));
+	else
+		/* ops->get_strings is valid because checked earlier */
+		ops->get_strings(dev, stringset, data);
+}
+
+static u32 ethtool_get_feature_mask(u32 eth_cmd)
+{
+	/* feature masks of legacy discrete ethtool ops */
+
+	switch (eth_cmd) {
+	case ETHTOOL_GTXCSUM:
+	case ETHTOOL_STXCSUM:
+		return NETIF_F_ALL_CSUM | NETIF_F_SCTP_CSUM;
+	case ETHTOOL_GRXCSUM:
+	case ETHTOOL_SRXCSUM:
+		return NETIF_F_RXCSUM;
+	case ETHTOOL_GSG:
+	case ETHTOOL_SSG:
+		return NETIF_F_SG;
+	case ETHTOOL_GTSO:
+	case ETHTOOL_STSO:
+		return NETIF_F_ALL_TSO;
+	case ETHTOOL_GUFO:
+	case ETHTOOL_SUFO:
+		return NETIF_F_UFO;
+	case ETHTOOL_GGSO:
+	case ETHTOOL_SGSO:
+		return NETIF_F_GSO;
+	case ETHTOOL_GGRO:
+	case ETHTOOL_SGRO:
+		return NETIF_F_GRO;
+	default:
+		BUG();
+	}
+}
+
+static void *__ethtool_get_one_feature_actor(struct net_device *dev, u32 ethcmd)
+{
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+
+	if (!ops)
+		return NULL;
+
+	switch (ethcmd) {
+	case ETHTOOL_GTXCSUM:
+		return ops->get_tx_csum;
+	case ETHTOOL_GRXCSUM:
+		return ops->get_rx_csum;
+	case ETHTOOL_SSG:
+		return ops->get_sg;
+	case ETHTOOL_STSO:
+		return ops->get_tso;
+	case ETHTOOL_SUFO:
+		return ops->get_ufo;
+	default:
+		return NULL;
+	}
+}
+
+static u32 __ethtool_get_rx_csum_oldbug(struct net_device *dev)
+{
+	return !!(dev->features & NETIF_F_ALL_CSUM);
+}
+
+static int ethtool_get_one_feature(struct net_device *dev,
+	char __user *useraddr, u32 ethcmd)
+{
+	u32 mask = ethtool_get_feature_mask(ethcmd);
+	struct ethtool_value edata = {
+		.cmd = ethcmd,
+		.data = !!(dev->features & mask),
+	};
+
+	/* compatibility with discrete get_ ops */
+	if (!(dev->hw_features & mask)) {
+		u32 (*actor)(struct net_device *);
+
+		actor = __ethtool_get_one_feature_actor(dev, ethcmd);
+
+		/* bug compatibility with old get_rx_csum */
+		if (ethcmd == ETHTOOL_GRXCSUM && !actor)
+			actor = __ethtool_get_rx_csum_oldbug;
+
+		if (actor)
+			edata.data = actor(dev);
+	}
+
+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
+		return -EFAULT;
+	return 0;
+}
+
+static int __ethtool_set_tx_csum(struct net_device *dev, u32 data);
+static int __ethtool_set_rx_csum(struct net_device *dev, u32 data);
+static int __ethtool_set_sg(struct net_device *dev, u32 data);
+static int __ethtool_set_tso(struct net_device *dev, u32 data);
+static int __ethtool_set_ufo(struct net_device *dev, u32 data);
+
+static int ethtool_set_one_feature(struct net_device *dev,
+	void __user *useraddr, u32 ethcmd)
+{
+	struct ethtool_value edata;
+	u32 mask;
+
+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
+		return -EFAULT;
+
+	mask = ethtool_get_feature_mask(ethcmd);
+	mask &= dev->hw_features;
+	if (mask) {
+		if (edata.data)
+			dev->wanted_features |= mask;
+		else
+			dev->wanted_features &= ~mask;
+
+		netdev_update_features(dev);
+		return 0;
+	}
+
+	/* Driver is not converted to ndo_fix_features or does not
+	 * support changing this offload. In the latter case it won't
+	 * have corresponding ethtool_ops field set.
+	 *
+	 * Following part is to be removed after all drivers advertise
+	 * their changeable features in netdev->hw_features and stop
+	 * using discrete offload setting ops.
+	 */
+
+	switch (ethcmd) {
+	case ETHTOOL_STXCSUM:
+		return __ethtool_set_tx_csum(dev, edata.data);
+	case ETHTOOL_SRXCSUM:
+		return __ethtool_set_rx_csum(dev, edata.data);
+	case ETHTOOL_SSG:
+		return __ethtool_set_sg(dev, edata.data);
+	case ETHTOOL_STSO:
+		return __ethtool_set_tso(dev, edata.data);
+	case ETHTOOL_SUFO:
+		return __ethtool_set_ufo(dev, edata.data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int __ethtool_set_flags(struct net_device *dev, u32 data)
+{
+	u32 changed;
+
+	if (data & ~flags_dup_features)
+		return -EINVAL;
+
+	/* legacy set_flags() op */
+	if (dev->ethtool_ops->set_flags) {
+		if (unlikely(dev->hw_features & flags_dup_features))
+			netdev_warn(dev,
+				"driver BUG: mixed hw_features and set_flags()\n");
+		return dev->ethtool_ops->set_flags(dev, data);
+	}
+
+	/* allow changing only bits set in hw_features */
+	changed = (data ^ dev->wanted_features) & flags_dup_features;
+	if (changed & ~dev->hw_features)
+		return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP;
+
+	dev->wanted_features =
+		(dev->wanted_features & ~changed) | data;
+
+	netdev_update_features(dev);
+
+	return 0;
+}
+
 static int ethtool_get_settings(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
@@ -251,14 +621,10 @@ static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev,
 						    void __user *useraddr)
 {
 	struct ethtool_sset_info info;
-	const struct ethtool_ops *ops = dev->ethtool_ops;
 	u64 sset_mask;
 	int i, idx = 0, n_bits = 0, ret, rc;
 	u32 *info_buf = NULL;
 
-	if (!ops->get_sset_count)
-		return -EOPNOTSUPP;
-
 	if (copy_from_user(&info, useraddr, sizeof(info)))
 		return -EFAULT;
 
@@ -285,7 +651,7 @@ static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev,
 		if (!(sset_mask & (1ULL << i)))
 			continue;
 
-		rc = ops->get_sset_count(dev, i);
+		rc = __ethtool_get_sset_count(dev, i);
 		if (rc >= 0) {
 			info.sset_mask |= (1ULL << i);
 			info_buf[idx++] = rc;
@@ -1091,6 +1457,12 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data)
 {
 	int err;
 
+	if (!dev->ethtool_ops->set_sg)
+		return -EOPNOTSUPP;
+
+	if (data && !(dev->features & NETIF_F_ALL_CSUM))
+		return -EINVAL;
+
 	if (!data && dev->ethtool_ops->set_tso) {
 		err = dev->ethtool_ops->set_tso(dev, 0);
 		if (err)
@@ -1105,145 +1477,55 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data)
 	return dev->ethtool_ops->set_sg(dev, data);
 }
 
-static int ethtool_set_tx_csum(struct net_device *dev, char __user *useraddr)
+static int __ethtool_set_tx_csum(struct net_device *dev, u32 data)
 {
-	struct ethtool_value edata;
 	int err;
 
 	if (!dev->ethtool_ops->set_tx_csum)
 		return -EOPNOTSUPP;
 
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	if (!edata.data && dev->ethtool_ops->set_sg) {
+	if (!data && dev->ethtool_ops->set_sg) {
 		err = __ethtool_set_sg(dev, 0);
 		if (err)
 			return err;
 	}
 
-	return dev->ethtool_ops->set_tx_csum(dev, edata.data);
+	return dev->ethtool_ops->set_tx_csum(dev, data);
 }
-EXPORT_SYMBOL(ethtool_op_set_tx_csum);
 
-static int ethtool_set_rx_csum(struct net_device *dev, char __user *useraddr)
+static int __ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
-	struct ethtool_value edata;
-
 	if (!dev->ethtool_ops->set_rx_csum)
 		return -EOPNOTSUPP;
 
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	if (!edata.data && dev->ethtool_ops->set_sg)
+	if (!data)
 		dev->features &= ~NETIF_F_GRO;
 
-	return dev->ethtool_ops->set_rx_csum(dev, edata.data);
-}
-
-static int ethtool_set_sg(struct net_device *dev, char __user *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (!dev->ethtool_ops->set_sg)
-		return -EOPNOTSUPP;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	if (edata.data &&
-	    !(dev->features & NETIF_F_ALL_CSUM))
-		return -EINVAL;
-
-	return __ethtool_set_sg(dev, edata.data);
+	return dev->ethtool_ops->set_rx_csum(dev, data);
 }
 
-static int ethtool_set_tso(struct net_device *dev, char __user *useraddr)
+static int __ethtool_set_tso(struct net_device *dev, u32 data)
 {
-	struct ethtool_value edata;
-
 	if (!dev->ethtool_ops->set_tso)
 		return -EOPNOTSUPP;
 
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	if (edata.data && !(dev->features & NETIF_F_SG))
+	if (data && !(dev->features & NETIF_F_SG))
 		return -EINVAL;
 
-	return dev->ethtool_ops->set_tso(dev, edata.data);
+	return dev->ethtool_ops->set_tso(dev, data);
 }
 
-static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
+static int __ethtool_set_ufo(struct net_device *dev, u32 data)
 {
-	struct ethtool_value edata;
-
 	if (!dev->ethtool_ops->set_ufo)
 		return -EOPNOTSUPP;
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-	if (edata.data && !(dev->features & NETIF_F_SG))
+	if (data && !(dev->features & NETIF_F_SG))
 		return -EINVAL;
-	if (edata.data && !((dev->features & NETIF_F_GEN_CSUM) ||
+	if (data && !((dev->features & NETIF_F_GEN_CSUM) ||
 		(dev->features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
 			== (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM)))
 		return -EINVAL;
-	return dev->ethtool_ops->set_ufo(dev, edata.data);
-}
-
-static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GGSO };
-
-	edata.data = dev->features & NETIF_F_GSO;
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-	if (edata.data)
-		dev->features |= NETIF_F_GSO;
-	else
-		dev->features &= ~NETIF_F_GSO;
-	return 0;
-}
-
-static int ethtool_get_gro(struct net_device *dev, char __user *useraddr)
-{
-	struct ethtool_value edata = { ETHTOOL_GGRO };
-
-	edata.data = dev->features & NETIF_F_GRO;
-	if (copy_to_user(useraddr, &edata, sizeof(edata)))
-		return -EFAULT;
-	return 0;
-}
-
-static int ethtool_set_gro(struct net_device *dev, char __user *useraddr)
-{
-	struct ethtool_value edata;
-
-	if (copy_from_user(&edata, useraddr, sizeof(edata)))
-		return -EFAULT;
-
-	if (edata.data) {
-		u32 rxcsum = dev->ethtool_ops->get_rx_csum ?
-				dev->ethtool_ops->get_rx_csum(dev) :
-				ethtool_op_get_rx_csum(dev);
-
-		if (!rxcsum)
-			return -EINVAL;
-		dev->features |= NETIF_F_GRO;
-	} else
-		dev->features &= ~NETIF_F_GRO;
-
-	return 0;
+	return dev->ethtool_ops->set_ufo(dev, data);
 }
 
 static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
@@ -1287,17 +1569,13 @@ static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
 {
 	struct ethtool_gstrings gstrings;
-	const struct ethtool_ops *ops = dev->ethtool_ops;
 	u8 *data;
 	int ret;
 
-	if (!ops->get_strings || !ops->get_sset_count)
-		return -EOPNOTSUPP;
-
 	if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
 		return -EFAULT;
 
-	ret = ops->get_sset_count(dev, gstrings.string_set);
+	ret = __ethtool_get_sset_count(dev, gstrings.string_set);
 	if (ret < 0)
 		return ret;
 
@@ -1307,7 +1585,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
 	if (!data)
 		return -ENOMEM;
 
-	ops->get_strings(dev, gstrings.string_set, data);
+	__ethtool_get_strings(dev, gstrings.string_set, data);
 
 	ret = -EFAULT;
 	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
@@ -1317,7 +1595,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
 		goto out;
 	ret = 0;
 
- out:
+out:
 	kfree(data);
 	return ret;
 }
@@ -1458,7 +1736,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	void __user *useraddr = ifr->ifr_data;
 	u32 ethcmd;
 	int rc;
-	unsigned long old_features;
+	u32 old_features;
 
 	if (!dev || !netif_device_present(dev))
 		return -ENODEV;
@@ -1500,6 +1778,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GRXCLSRLCNT:
 	case ETHTOOL_GRXCLSRULE:
 	case ETHTOOL_GRXCLSRLALL:
+	case ETHTOOL_GFEATURES:
 		break;
 	default:
 		if (!capable(CAP_NET_ADMIN))
@@ -1570,42 +1849,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_SPAUSEPARAM:
 		rc = ethtool_set_pauseparam(dev, useraddr);
 		break;
-	case ETHTOOL_GRXCSUM:
-		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_rx_csum ?
-					dev->ethtool_ops->get_rx_csum :
-					ethtool_op_get_rx_csum));
-		break;
-	case ETHTOOL_SRXCSUM:
-		rc = ethtool_set_rx_csum(dev, useraddr);
-		break;
-	case ETHTOOL_GTXCSUM:
-		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_tx_csum ?
-					dev->ethtool_ops->get_tx_csum :
-					ethtool_op_get_tx_csum));
-		break;
-	case ETHTOOL_STXCSUM:
-		rc = ethtool_set_tx_csum(dev, useraddr);
-		break;
-	case ETHTOOL_GSG:
-		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_sg ?
-					dev->ethtool_ops->get_sg :
-					ethtool_op_get_sg));
-		break;
-	case ETHTOOL_SSG:
-		rc = ethtool_set_sg(dev, useraddr);
-		break;
-	case ETHTOOL_GTSO:
-		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_tso ?
-					dev->ethtool_ops->get_tso :
-					ethtool_op_get_tso));
-		break;
-	case ETHTOOL_STSO:
-		rc = ethtool_set_tso(dev, useraddr);
-		break;
 	case ETHTOOL_TEST:
 		rc = ethtool_self_test(dev, useraddr);
 		break;
@@ -1621,21 +1864,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GPERMADDR:
 		rc = ethtool_get_perm_addr(dev, useraddr);
 		break;
-	case ETHTOOL_GUFO:
-		rc = ethtool_get_value(dev, useraddr, ethcmd,
-				       (dev->ethtool_ops->get_ufo ?
-					dev->ethtool_ops->get_ufo :
-					ethtool_op_get_ufo));
-		break;
-	case ETHTOOL_SUFO:
-		rc = ethtool_set_ufo(dev, useraddr);
-		break;
-	case ETHTOOL_GGSO:
-		rc = ethtool_get_gso(dev, useraddr);
-		break;
-	case ETHTOOL_SGSO:
-		rc = ethtool_set_gso(dev, useraddr);
-		break;
 	case ETHTOOL_GFLAGS:
 		rc = ethtool_get_value(dev, useraddr, ethcmd,
 				       (dev->ethtool_ops->get_flags ?
@@ -1643,8 +1871,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 					ethtool_op_get_flags));
 		break;
 	case ETHTOOL_SFLAGS:
-		rc = ethtool_set_value(dev, useraddr,
-				       dev->ethtool_ops->set_flags);
+		rc = ethtool_set_value(dev, useraddr, __ethtool_set_flags);
 		break;
 	case ETHTOOL_GPFLAGS:
 		rc = ethtool_get_value(dev, useraddr, ethcmd,
@@ -1666,12 +1893,6 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_SRXCLSRLINS:
 		rc = ethtool_set_rxnfc(dev, ethcmd, useraddr);
 		break;
-	case ETHTOOL_GGRO:
-		rc = ethtool_get_gro(dev, useraddr);
-		break;
-	case ETHTOOL_SGRO:
-		rc = ethtool_set_gro(dev, useraddr);
-		break;
 	case ETHTOOL_FLASHDEV:
 		rc = ethtool_flash_device(dev, useraddr);
 		break;
@@ -1693,6 +1914,30 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_SRXFHINDIR:
 		rc = ethtool_set_rxfh_indir(dev, useraddr);
 		break;
+	case ETHTOOL_GFEATURES:
+		rc = ethtool_get_features(dev, useraddr);
+		break;
+	case ETHTOOL_SFEATURES:
+		rc = ethtool_set_features(dev, useraddr);
+		break;
+	case ETHTOOL_GTXCSUM:
+	case ETHTOOL_GRXCSUM:
+	case ETHTOOL_GSG:
+	case ETHTOOL_GTSO:
+	case ETHTOOL_GUFO:
+	case ETHTOOL_GGSO:
+	case ETHTOOL_GGRO:
+		rc = ethtool_get_one_feature(dev, useraddr, ethcmd);
+		break;
+	case ETHTOOL_STXCSUM:
+	case ETHTOOL_SRXCSUM:
+	case ETHTOOL_SSG:
+	case ETHTOOL_STSO:
+	case ETHTOOL_SUFO:
+	case ETHTOOL_SGSO:
+	case ETHTOOL_SGRO:
+		rc = ethtool_set_one_feature(dev, useraddr, ethcmd);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index a20e5d3..8248ebb 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -181,13 +181,13 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
 {
 	int ret = 0;
 
-	if (rule->iifindex && (rule->iifindex != fl->iif))
+	if (rule->iifindex && (rule->iifindex != fl->flowi_iif))
 		goto out;
 
-	if (rule->oifindex && (rule->oifindex != fl->oif))
+	if (rule->oifindex && (rule->oifindex != fl->flowi_oif))
 		goto out;
 
-	if ((rule->mark ^ fl->mark) & rule->mark_mask)
+	if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)
 		goto out;
 
 	ret = ops->match(rule, fl, flags);
diff --git a/net/core/filter.c b/net/core/filter.c
index afc5837..232b187 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -142,14 +142,14 @@ int sk_filter(struct sock *sk, struct sk_buff *skb)
 	if (err)
 		return err;
 
-	rcu_read_lock_bh();
-	filter = rcu_dereference_bh(sk->sk_filter);
+	rcu_read_lock();
+	filter = rcu_dereference(sk->sk_filter);
 	if (filter) {
 		unsigned int pkt_len = sk_run_filter(skb, filter->insns);
 
 		err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
 	}
-	rcu_read_unlock_bh();
+	rcu_read_unlock();
 
 	return err;
 }
diff --git a/net/core/flow.c b/net/core/flow.c
index 127c8a7..990703b 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -172,9 +172,9 @@ static void flow_new_hash_rnd(struct flow_cache *fc,
 
 static u32 flow_hash_code(struct flow_cache *fc,
 			  struct flow_cache_percpu *fcp,
-			  struct flowi *key)
+			  const struct flowi *key)
 {
-	u32 *k = (u32 *) key;
+	const u32 *k = (const u32 *) key;
 
 	return jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd)
 		& (flow_cache_hash_size(fc) - 1);
@@ -186,17 +186,17 @@ typedef unsigned long flow_compare_t;
  * important assumptions that we can here, such as alignment and
  * constant size.
  */
-static int flow_key_compare(struct flowi *key1, struct flowi *key2)
+static int flow_key_compare(const struct flowi *key1, const struct flowi *key2)
 {
-	flow_compare_t *k1, *k1_lim, *k2;
+	const flow_compare_t *k1, *k1_lim, *k2;
 	const int n_elem = sizeof(struct flowi) / sizeof(flow_compare_t);
 
 	BUILD_BUG_ON(sizeof(struct flowi) % sizeof(flow_compare_t));
 
-	k1 = (flow_compare_t *) key1;
+	k1 = (const flow_compare_t *) key1;
 	k1_lim = k1 + n_elem;
 
-	k2 = (flow_compare_t *) key2;
+	k2 = (const flow_compare_t *) key2;
 
 	do {
 		if (*k1++ != *k2++)
@@ -207,7 +207,7 @@ static int flow_key_compare(struct flowi *key1, struct flowi *key2)
 }
 
 struct flow_cache_object *
-flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
+flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
 		  flow_resolve_t resolver, void *ctx)
 {
 	struct flow_cache *fc = &flow_cache_global;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 60a9029..799f06e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -316,7 +316,7 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
 {
 	size_t size = entries * sizeof(struct neighbour *);
 	struct neigh_hash_table *ret;
-	struct neighbour **buckets;
+	struct neighbour __rcu **buckets;
 
 	ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
 	if (!ret)
@@ -324,14 +324,14 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int entries)
 	if (size <= PAGE_SIZE)
 		buckets = kzalloc(size, GFP_ATOMIC);
 	else
-		buckets = (struct neighbour **)
+		buckets = (struct neighbour __rcu **)
 			  __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
 					   get_order(size));
 	if (!buckets) {
 		kfree(ret);
 		return NULL;
 	}
-	rcu_assign_pointer(ret->hash_buckets, buckets);
+	ret->hash_buckets = buckets;
 	ret->hash_mask = entries - 1;
 	get_random_bytes(&ret->hash_rnd, sizeof(ret->hash_rnd));
 	return ret;
@@ -343,7 +343,7 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
 						    struct neigh_hash_table,
 						    rcu);
 	size_t size = (nht->hash_mask + 1) * sizeof(struct neighbour *);
-	struct neighbour **buckets = nht->hash_buckets;
+	struct neighbour __rcu **buckets = nht->hash_buckets;
 
 	if (size <= PAGE_SIZE)
 		kfree(buckets);
@@ -1540,7 +1540,7 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl)
 		panic("cannot create neighbour proc dir entry");
 #endif
 
-	tbl->nht = neigh_hash_alloc(8);
+	RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(8));
 
 	phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
 	tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
@@ -1602,7 +1602,8 @@ int neigh_table_clear(struct neigh_table *tbl)
 	}
 	write_unlock(&neigh_tbl_lock);
 
-	call_rcu(&tbl->nht->rcu, neigh_hash_free_rcu);
+	call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
+		 neigh_hash_free_rcu);
 	tbl->nht = NULL;
 
 	kfree(tbl->phash_buckets);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index e23c01b..5ceb257 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -99,7 +99,7 @@ NETDEVICE_SHOW(addr_assign_type, fmt_dec);
 NETDEVICE_SHOW(addr_len, fmt_dec);
 NETDEVICE_SHOW(iflink, fmt_dec);
 NETDEVICE_SHOW(ifindex, fmt_dec);
-NETDEVICE_SHOW(features, fmt_long_hex);
+NETDEVICE_SHOW(features, fmt_hex);
 NETDEVICE_SHOW(type, fmt_dec);
 NETDEVICE_SHOW(link_mode, fmt_dec);
 
@@ -295,6 +295,20 @@ static ssize_t show_ifalias(struct device *dev,
 	return ret;
 }
 
+NETDEVICE_SHOW(group, fmt_dec);
+
+static int change_group(struct net_device *net, unsigned long new_group)
+{
+	dev_set_group(net, (int) new_group);
+	return 0;
+}
+
+static ssize_t store_group(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t len)
+{
+	return netdev_store(dev, attr, buf, len, change_group);
+}
+
 static struct device_attribute net_class_attributes[] = {
 	__ATTR(addr_assign_type, S_IRUGO, show_addr_assign_type, NULL),
 	__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
@@ -316,6 +330,7 @@ static struct device_attribute net_class_attributes[] = {
 	__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
 	__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
 	       store_tx_queue_len),
+	__ATTR(netdev_group, S_IRUGO | S_IWUSR, show_group, store_group),
 	{}
 };
 
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 02dc2cb..06be243 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -193,6 +193,17 @@ void netpoll_poll_dev(struct net_device *dev)
 
 	poll_napi(dev);
 
+	if (dev->priv_flags & IFF_SLAVE) {
+		if (dev->npinfo) {
+			struct net_device *bond_dev = dev->master;
+			struct sk_buff *skb;
+			while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) {
+				skb->dev = bond_dev;
+				skb_queue_tail(&bond_dev->npinfo->arp_tx, skb);
+			}
+		}
+	}
+
 	service_arp_queue(dev->npinfo);
 
 	zap_completion_queue();
@@ -313,9 +324,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
 		     tries > 0; --tries) {
 			if (__netif_tx_trylock(txq)) {
 				if (!netif_tx_queue_stopped(txq)) {
-					dev->priv_flags |= IFF_IN_NETPOLL;
 					status = ops->ndo_start_xmit(skb, dev);
-					dev->priv_flags &= ~IFF_IN_NETPOLL;
 					if (status == NETDEV_TX_OK)
 						txq_trans_update(txq);
 				}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index b5bada9..aeeece7 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -251,6 +251,7 @@ struct pktgen_dev {
 	int max_pkt_size;	/* = ETH_ZLEN; */
 	int pkt_overhead;	/* overhead for MPLS, VLANs, IPSEC etc */
 	int nfrags;
+	struct page *page;
 	u64 delay;		/* nano-seconds */
 
 	__u64 count;		/* Default No packets to send */
@@ -1134,6 +1135,10 @@ static ssize_t pktgen_if_write(struct file *file,
 		if (node_possible(value)) {
 			pkt_dev->node = value;
 			sprintf(pg_result, "OK: node=%d", pkt_dev->node);
+			if (pkt_dev->page) {
+				put_page(pkt_dev->page);
+				pkt_dev->page = NULL;
+			}
 		}
 		else
 			sprintf(pg_result, "ERROR: node not possible");
@@ -2605,6 +2610,89 @@ static inline __be16 build_tci(unsigned int id, unsigned int cfi,
 	return htons(id | (cfi << 12) | (prio << 13));
 }
 
+static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb,
+				int datalen)
+{
+	struct timeval timestamp;
+	struct pktgen_hdr *pgh;
+
+	pgh = (struct pktgen_hdr *)skb_put(skb, sizeof(*pgh));
+	datalen -= sizeof(*pgh);
+
+	if (pkt_dev->nfrags <= 0) {
+		memset(skb_put(skb, datalen), 0, datalen);
+	} else {
+		int frags = pkt_dev->nfrags;
+		int i, len;
+
+
+		if (frags > MAX_SKB_FRAGS)
+			frags = MAX_SKB_FRAGS;
+		len = datalen - frags * PAGE_SIZE;
+		if (len > 0) {
+			memset(skb_put(skb, len), 0, len);
+			datalen = frags * PAGE_SIZE;
+		}
+
+		i = 0;
+		while (datalen > 0) {
+			if (unlikely(!pkt_dev->page)) {
+				int node = numa_node_id();
+
+				if (pkt_dev->node >= 0 && (pkt_dev->flags & F_NODE))
+					node = pkt_dev->node;
+				pkt_dev->page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
+				if (!pkt_dev->page)
+					break;
+			}
+			skb_shinfo(skb)->frags[i].page = pkt_dev->page;
+			get_page(pkt_dev->page);
+			skb_shinfo(skb)->frags[i].page_offset = 0;
+			skb_shinfo(skb)->frags[i].size =
+			    (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
+			datalen -= skb_shinfo(skb)->frags[i].size;
+			skb->len += skb_shinfo(skb)->frags[i].size;
+			skb->data_len += skb_shinfo(skb)->frags[i].size;
+			i++;
+			skb_shinfo(skb)->nr_frags = i;
+		}
+
+		while (i < frags) {
+			int rem;
+
+			if (i == 0)
+				break;
+
+			rem = skb_shinfo(skb)->frags[i - 1].size / 2;
+			if (rem == 0)
+				break;
+
+			skb_shinfo(skb)->frags[i - 1].size -= rem;
+
+			skb_shinfo(skb)->frags[i] =
+			    skb_shinfo(skb)->frags[i - 1];
+			get_page(skb_shinfo(skb)->frags[i].page);
+			skb_shinfo(skb)->frags[i].page =
+			    skb_shinfo(skb)->frags[i - 1].page;
+			skb_shinfo(skb)->frags[i].page_offset +=
+			    skb_shinfo(skb)->frags[i - 1].size;
+			skb_shinfo(skb)->frags[i].size = rem;
+			i++;
+			skb_shinfo(skb)->nr_frags = i;
+		}
+	}
+
+	/* Stamp the time, and sequence number,
+	 * convert them to network byte order
+	 */
+	pgh->pgh_magic = htonl(PKTGEN_MAGIC);
+	pgh->seq_num = htonl(pkt_dev->seq_num);
+
+	do_gettimeofday(&timestamp);
+	pgh->tv_sec = htonl(timestamp.tv_sec);
+	pgh->tv_usec = htonl(timestamp.tv_usec);
+}
+
 static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 					struct pktgen_dev *pkt_dev)
 {
@@ -2613,7 +2701,6 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 	struct udphdr *udph;
 	int datalen, iplen;
 	struct iphdr *iph;
-	struct pktgen_hdr *pgh = NULL;
 	__be16 protocol = htons(ETH_P_IP);
 	__be32 *mpls;
 	__be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
@@ -2729,76 +2816,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
 			   pkt_dev->pkt_overhead);
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
-
-	if (pkt_dev->nfrags <= 0) {
-		pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
-		memset(pgh + 1, 0, datalen - sizeof(struct pktgen_hdr));
-	} else {
-		int frags = pkt_dev->nfrags;
-		int i, len;
-
-		pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
-
-		if (frags > MAX_SKB_FRAGS)
-			frags = MAX_SKB_FRAGS;
-		if (datalen > frags * PAGE_SIZE) {
-			len = datalen - frags * PAGE_SIZE;
-			memset(skb_put(skb, len), 0, len);
-			datalen = frags * PAGE_SIZE;
-		}
-
-		i = 0;
-		while (datalen > 0) {
-			struct page *page = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
-			skb_shinfo(skb)->frags[i].page = page;
-			skb_shinfo(skb)->frags[i].page_offset = 0;
-			skb_shinfo(skb)->frags[i].size =
-			    (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
-			datalen -= skb_shinfo(skb)->frags[i].size;
-			skb->len += skb_shinfo(skb)->frags[i].size;
-			skb->data_len += skb_shinfo(skb)->frags[i].size;
-			i++;
-			skb_shinfo(skb)->nr_frags = i;
-		}
-
-		while (i < frags) {
-			int rem;
-
-			if (i == 0)
-				break;
-
-			rem = skb_shinfo(skb)->frags[i - 1].size / 2;
-			if (rem == 0)
-				break;
-
-			skb_shinfo(skb)->frags[i - 1].size -= rem;
-
-			skb_shinfo(skb)->frags[i] =
-			    skb_shinfo(skb)->frags[i - 1];
-			get_page(skb_shinfo(skb)->frags[i].page);
-			skb_shinfo(skb)->frags[i].page =
-			    skb_shinfo(skb)->frags[i - 1].page;
-			skb_shinfo(skb)->frags[i].page_offset +=
-			    skb_shinfo(skb)->frags[i - 1].size;
-			skb_shinfo(skb)->frags[i].size = rem;
-			i++;
-			skb_shinfo(skb)->nr_frags = i;
-		}
-	}
-
-	/* Stamp the time, and sequence number,
-	 * convert them to network byte order
-	 */
-	if (pgh) {
-		struct timeval timestamp;
-
-		pgh->pgh_magic = htonl(PKTGEN_MAGIC);
-		pgh->seq_num = htonl(pkt_dev->seq_num);
-
-		do_gettimeofday(&timestamp);
-		pgh->tv_sec = htonl(timestamp.tv_sec);
-		pgh->tv_usec = htonl(timestamp.tv_usec);
-	}
+	pktgen_finalize_skb(pkt_dev, skb, datalen);
 
 #ifdef CONFIG_XFRM
 	if (!process_ipsec(pkt_dev, skb, protocol))
@@ -2980,7 +2998,6 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 	struct udphdr *udph;
 	int datalen;
 	struct ipv6hdr *iph;
-	struct pktgen_hdr *pgh = NULL;
 	__be16 protocol = htons(ETH_P_IPV6);
 	__be32 *mpls;
 	__be16 *vlan_tci = NULL;                 /* Encapsulates priority and VLAN ID */
@@ -3083,75 +3100,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
 	skb->dev = odev;
 	skb->pkt_type = PACKET_HOST;
 
-	if (pkt_dev->nfrags <= 0)
-		pgh = (struct pktgen_hdr *)skb_put(skb, datalen);
-	else {
-		int frags = pkt_dev->nfrags;
-		int i;
-
-		pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8);
-
-		if (frags > MAX_SKB_FRAGS)
-			frags = MAX_SKB_FRAGS;
-		if (datalen > frags * PAGE_SIZE) {
-			skb_put(skb, datalen - frags * PAGE_SIZE);
-			datalen = frags * PAGE_SIZE;
-		}
-
-		i = 0;
-		while (datalen > 0) {
-			struct page *page = alloc_pages(GFP_KERNEL, 0);
-			skb_shinfo(skb)->frags[i].page = page;
-			skb_shinfo(skb)->frags[i].page_offset = 0;
-			skb_shinfo(skb)->frags[i].size =
-			    (datalen < PAGE_SIZE ? datalen : PAGE_SIZE);
-			datalen -= skb_shinfo(skb)->frags[i].size;
-			skb->len += skb_shinfo(skb)->frags[i].size;
-			skb->data_len += skb_shinfo(skb)->frags[i].size;
-			i++;
-			skb_shinfo(skb)->nr_frags = i;
-		}
-
-		while (i < frags) {
-			int rem;
-
-			if (i == 0)
-				break;
-
-			rem = skb_shinfo(skb)->frags[i - 1].size / 2;
-			if (rem == 0)
-				break;
-
-			skb_shinfo(skb)->frags[i - 1].size -= rem;
-
-			skb_shinfo(skb)->frags[i] =
-			    skb_shinfo(skb)->frags[i - 1];
-			get_page(skb_shinfo(skb)->frags[i].page);
-			skb_shinfo(skb)->frags[i].page =
-			    skb_shinfo(skb)->frags[i - 1].page;
-			skb_shinfo(skb)->frags[i].page_offset +=
-			    skb_shinfo(skb)->frags[i - 1].size;
-			skb_shinfo(skb)->frags[i].size = rem;
-			i++;
-			skb_shinfo(skb)->nr_frags = i;
-		}
-	}
-
-	/* Stamp the time, and sequence number,
-	 * convert them to network byte order
-	 * should we update cloned packets too ?
-	 */
-	if (pgh) {
-		struct timeval timestamp;
-
-		pgh->pgh_magic = htonl(PKTGEN_MAGIC);
-		pgh->seq_num = htonl(pkt_dev->seq_num);
-
-		do_gettimeofday(&timestamp);
-		pgh->tv_sec = htonl(timestamp.tv_sec);
-		pgh->tv_usec = htonl(timestamp.tv_usec);
-	}
-	/* pkt_dev->seq_num++; FF: you really mean this? */
+	pktgen_finalize_skb(pkt_dev, skb, datalen);
 
 	return skb;
 }
@@ -3812,7 +3761,10 @@ static int __init pktgen_create_thread(int cpu)
 	list_add_tail(&t->th_list, &pktgen_threads);
 	init_completion(&t->start_done);
 
-	p = kthread_create(pktgen_thread_worker, t, "kpktgend_%d", cpu);
+	p = kthread_create_on_node(pktgen_thread_worker,
+				   t,
+				   cpu_to_node(cpu),
+				   "kpktgend_%d", cpu);
 	if (IS_ERR(p)) {
 		pr_err("kernel_thread() failed for cpu %d\n", t->cpu);
 		list_del(&t->th_list);
@@ -3884,6 +3836,8 @@ static int pktgen_remove_device(struct pktgen_thread *t,
 	free_SAs(pkt_dev);
 #endif
 	vfree(pkt_dev->flows);
+	if (pkt_dev->page)
+		put_page(pkt_dev->page);
 	kfree(pkt_dev);
 	return 0;
 }
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2d65c6b..49f7ea5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -868,6 +868,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 		   netif_running(dev) ? dev->operstate : IF_OPER_DOWN);
 	NLA_PUT_U8(skb, IFLA_LINKMODE, dev->link_mode);
 	NLA_PUT_U32(skb, IFLA_MTU, dev->mtu);
+	NLA_PUT_U32(skb, IFLA_GROUP, dev->group);
 
 	if (dev->ifindex != dev->iflink)
 		NLA_PUT_U32(skb, IFLA_LINK, dev->iflink);
@@ -1035,6 +1036,7 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 	[IFLA_MAP]		= { .len = sizeof(struct rtnl_link_ifmap) },
 	[IFLA_MTU]		= { .type = NLA_U32 },
 	[IFLA_LINK]		= { .type = NLA_U32 },
+	[IFLA_MASTER]		= { .type = NLA_U32 },
 	[IFLA_TXQLEN]		= { .type = NLA_U32 },
 	[IFLA_WEIGHT]		= { .type = NLA_U32 },
 	[IFLA_OPERSTATE]	= { .type = NLA_U8 },
@@ -1177,6 +1179,41 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr *attr)
 	return err;
 }
 
+static int do_set_master(struct net_device *dev, int ifindex)
+{
+	struct net_device *master_dev;
+	const struct net_device_ops *ops;
+	int err;
+
+	if (dev->master) {
+		if (dev->master->ifindex == ifindex)
+			return 0;
+		ops = dev->master->netdev_ops;
+		if (ops->ndo_del_slave) {
+			err = ops->ndo_del_slave(dev->master, dev);
+			if (err)
+				return err;
+		} else {
+			return -EOPNOTSUPP;
+		}
+	}
+
+	if (ifindex) {
+		master_dev = __dev_get_by_index(dev_net(dev), ifindex);
+		if (!master_dev)
+			return -EINVAL;
+		ops = master_dev->netdev_ops;
+		if (ops->ndo_add_slave) {
+			err = ops->ndo_add_slave(master_dev, dev);
+			if (err)
+				return err;
+		} else {
+			return -EOPNOTSUPP;
+		}
+	}
+	return 0;
+}
+
 static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		      struct nlattr **tb, char *ifname, int modified)
 {
@@ -1264,6 +1301,11 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		modified = 1;
 	}
 
+	if (tb[IFLA_GROUP]) {
+		dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
+		modified = 1;
+	}
+
 	/*
 	 * Interface selected by interface index but interface
 	 * name provided implies that a name change has been
@@ -1295,6 +1337,13 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 			goto errout;
 	}
 
+	if (tb[IFLA_MASTER]) {
+		err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
+		if (err)
+			goto errout;
+		modified = 1;
+	}
+
 	if (tb[IFLA_TXQLEN])
 		dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
 
@@ -1541,6 +1590,8 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
 		set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
 	if (tb[IFLA_LINKMODE])
 		dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+	if (tb[IFLA_GROUP])
+		dev_set_group(dev, nla_get_u32(tb[IFLA_GROUP]));
 
 	return dev;
 
@@ -1551,6 +1602,24 @@ err:
 }
 EXPORT_SYMBOL(rtnl_create_link);
 
+static int rtnl_group_changelink(struct net *net, int group,
+		struct ifinfomsg *ifm,
+		struct nlattr **tb)
+{
+	struct net_device *dev;
+	int err;
+
+	for_each_netdev(net, dev) {
+		if (dev->group == group) {
+			err = do_setlink(dev, ifm, tb, NULL, 0);
+			if (err < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
 static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
@@ -1578,10 +1647,12 @@ replay:
 	ifm = nlmsg_data(nlh);
 	if (ifm->ifi_index > 0)
 		dev = __dev_get_by_index(net, ifm->ifi_index);
-	else if (ifname[0])
-		dev = __dev_get_by_name(net, ifname);
-	else
-		dev = NULL;
+	else {
+		if (ifname[0])
+			dev = __dev_get_by_name(net, ifname);
+		else
+			dev = NULL;
+	}
 
 	err = validate_linkmsg(dev, tb);
 	if (err < 0)
@@ -1645,8 +1716,13 @@ replay:
 			return do_setlink(dev, ifm, tb, ifname, modified);
 		}
 
-		if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+		if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
+			if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
+				return rtnl_group_changelink(net,
+						nla_get_u32(tb[IFLA_GROUP]),
+						ifm, tb);
 			return -ENODEV;
+		}
 
 		if (ifm->ifi_index)
 			return -EOPNOTSUPP;
diff --git a/net/core/scm.c b/net/core/scm.c
index bbe4544..4c1ef02 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -95,7 +95,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
 		int fd = fdp[i];
 		struct file *file;
 
-		if (fd < 0 || !(file = fget(fd)))
+		if (fd < 0 || !(file = fget_raw(fd)))
 			return -EBADF;
 		*fpp++ = file;
 		fpl->count++;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index d883dcc..801dd08 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -523,7 +523,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	new->ip_summed		= old->ip_summed;
 	skb_copy_queue_mapping(new, old);
 	new->priority		= old->priority;
-	new->deliver_no_wcard	= old->deliver_no_wcard;
 #if defined(CONFIG_IP_VS) || defined(CONFIG_IP_VS_MODULE)
 	new->ipvs_property	= old->ipvs_property;
 #endif
@@ -2434,8 +2433,6 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 			return -ENOMEM;
 
 		/* initialize the next frag */
-		sk->sk_sndmsg_page = page;
-		sk->sk_sndmsg_off = 0;
 		skb_fill_page_desc(skb, frg_cnt, page, 0, 0);
 		skb->truesize += PAGE_SIZE;
 		atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc);
@@ -2455,7 +2452,6 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb,
 			return -EFAULT;
 
 		/* copy was successful so update the size parameters */
-		sk->sk_sndmsg_off += copy;
 		frag->size += copy;
 		skb->len += copy;
 		skb->data_len += copy;
@@ -2498,7 +2494,7 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum);
  *	a pointer to the first in a list of new skbs for the segments.
  *	In case of error it returns ERR_PTR(err).
  */
-struct sk_buff *skb_segment(struct sk_buff *skb, int features)
+struct sk_buff *skb_segment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = NULL;
 	struct sk_buff *tail = NULL;
@@ -2508,7 +2504,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features)
 	unsigned int offset = doffset;
 	unsigned int headroom;
 	unsigned int len;
-	int sg = features & NETIF_F_SG;
+	int sg = !!(features & NETIF_F_SG);
 	int nfrags = skb_shinfo(skb)->nr_frags;
 	int err = -ENOMEM;
 	int i = 0;
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index c44348a..3609eac 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Intel Corporation.
+ * Copyright (c) 2008-2011, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -1224,6 +1224,59 @@ err:
 	return err;
 }
 
+static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
+				int app_nested_type, int app_info_type,
+				int app_entry_type)
+{
+	struct dcb_peer_app_info info;
+	struct dcb_app *table = NULL;
+	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+	u16 app_count;
+	int err;
+
+
+	/**
+	 * retrieve the peer app configuration form the driver. If the driver
+	 * handlers fail exit without doing anything
+	 */
+	err = ops->peer_getappinfo(netdev, &info, &app_count);
+	if (!err && app_count) {
+		table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
+		if (!table)
+			return -ENOMEM;
+
+		err = ops->peer_getapptable(netdev, table);
+	}
+
+	if (!err) {
+		u16 i;
+		struct nlattr *app;
+
+		/**
+		 * build the message, from here on the only possible failure
+		 * is due to the skb size
+		 */
+		err = -EMSGSIZE;
+
+		app = nla_nest_start(skb, app_nested_type);
+		if (!app)
+			goto nla_put_failure;
+
+		if (app_info_type)
+			NLA_PUT(skb, app_info_type, sizeof(info), &info);
+
+		for (i = 0; i < app_count; i++)
+			NLA_PUT(skb, app_entry_type, sizeof(struct dcb_app),
+				&table[i]);
+
+		nla_nest_end(skb, app);
+	}
+	err = 0;
+
+nla_put_failure:
+	kfree(table);
+	return err;
+}
 
 /* Handle IEEE 802.1Qaz GET commands. */
 static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
@@ -1288,6 +1341,30 @@ static int dcbnl_ieee_get(struct net_device *netdev, struct nlattr **tb,
 	spin_unlock(&dcb_lock);
 	nla_nest_end(skb, app);
 
+	/* get peer info if available */
+	if (ops->ieee_peer_getets) {
+		struct ieee_ets ets;
+		err = ops->ieee_peer_getets(netdev, &ets);
+		if (!err)
+			NLA_PUT(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets);
+	}
+
+	if (ops->ieee_peer_getpfc) {
+		struct ieee_pfc pfc;
+		err = ops->ieee_peer_getpfc(netdev, &pfc);
+		if (!err)
+			NLA_PUT(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc);
+	}
+
+	if (ops->peer_getappinfo && ops->peer_getapptable) {
+		err = dcbnl_build_peer_app(netdev, skb,
+					   DCB_ATTR_IEEE_PEER_APP,
+					   DCB_ATTR_IEEE_APP_UNSPEC,
+					   DCB_ATTR_IEEE_APP);
+		if (err)
+			goto nla_put_failure;
+	}
+
 	nla_nest_end(skb, ieee);
 	nlmsg_end(skb, nlh);
 
@@ -1441,6 +1518,71 @@ err:
 	return ret;
 }
 
+/* Handle CEE DCBX GET commands. */
+static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
+			 u32 pid, u32 seq, u16 flags)
+{
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct dcbmsg *dcb;
+	struct nlattr *cee;
+	const struct dcbnl_rtnl_ops *ops = netdev->dcbnl_ops;
+	int err;
+
+	if (!ops)
+		return -EOPNOTSUPP;
+
+	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	nlh = NLMSG_NEW(skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags);
+
+	dcb = NLMSG_DATA(nlh);
+	dcb->dcb_family = AF_UNSPEC;
+	dcb->cmd = DCB_CMD_CEE_GET;
+
+	NLA_PUT_STRING(skb, DCB_ATTR_IFNAME, netdev->name);
+
+	cee = nla_nest_start(skb, DCB_ATTR_CEE);
+	if (!cee)
+		goto nla_put_failure;
+
+	/* get peer info if available */
+	if (ops->cee_peer_getpg) {
+		struct cee_pg pg;
+		err = ops->cee_peer_getpg(netdev, &pg);
+		if (!err)
+			NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg);
+	}
+
+	if (ops->cee_peer_getpfc) {
+		struct cee_pfc pfc;
+		err = ops->cee_peer_getpfc(netdev, &pfc);
+		if (!err)
+			NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc);
+	}
+
+	if (ops->peer_getappinfo && ops->peer_getapptable) {
+		err = dcbnl_build_peer_app(netdev, skb,
+					   DCB_ATTR_CEE_PEER_APP_TABLE,
+					   DCB_ATTR_CEE_PEER_APP_INFO,
+					   DCB_ATTR_CEE_PEER_APP);
+		if (err)
+			goto nla_put_failure;
+	}
+
+	nla_nest_end(skb, cee);
+	nlmsg_end(skb, nlh);
+
+	return rtnl_unicast(skb, &init_net, pid);
+nla_put_failure:
+	nlmsg_cancel(skb, nlh);
+nlmsg_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
 static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
 	struct net *net = sock_net(skb->sk);
@@ -1570,6 +1712,10 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 		ret = dcbnl_setfeatcfg(netdev, tb, pid, nlh->nlmsg_seq,
 				       nlh->nlmsg_flags);
 		goto out;
+	case DCB_CMD_CEE_GET:
+		ret = dcbnl_cee_get(netdev, tb, pid, nlh->nlmsg_seq,
+				    nlh->nlmsg_flags);
+		goto out;
 	default:
 		goto errout;
 	}
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index e96d5e8..fadecd2 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -583,6 +583,15 @@ done:
 	dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
 }
 
+/*
+ * Convert RFC 3390 larger initial window into an equivalent number of packets.
+ * This is based on the numbers specified in RFC 5681, 3.1.
+ */
+static inline u32 rfc3390_bytes_to_packets(const u32 smss)
+{
+	return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
+}
+
 static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
 {
 	struct ccid2_hc_tx_sock *hc = ccid_priv(ccid);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 45a434f..ae451c6 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -43,9 +43,9 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	struct inet_sock *inet = inet_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);
 	const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
+	__be16 orig_sport, orig_dport;
 	struct rtable *rt;
 	__be32 daddr, nexthop;
-	int tmp;
 	int err;
 
 	dp->dccps_role = DCCP_ROLE_CLIENT;
@@ -63,12 +63,14 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 		nexthop = inet->opt->faddr;
 	}
 
-	tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr,
-			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
-			       IPPROTO_DCCP,
-			       inet->inet_sport, usin->sin_port, sk, 1);
-	if (tmp < 0)
-		return tmp;
+	orig_sport = inet->inet_sport;
+	orig_dport = usin->sin_port;
+	rt = ip_route_connect(nexthop, inet->inet_saddr,
+			      RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+			      IPPROTO_DCCP,
+			      orig_sport, orig_dport, sk, true);
+	if (IS_ERR(rt))
+		return PTR_ERR(rt);
 
 	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
 		ip_rt_put(rt);
@@ -99,11 +101,13 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	if (err != 0)
 		goto failure;
 
-	err = ip_route_newports(&rt, IPPROTO_DCCP, inet->inet_sport,
-				inet->inet_dport, sk);
-	if (err != 0)
+	rt = ip_route_newports(rt, IPPROTO_DCCP,
+			       orig_sport, orig_dport,
+			       inet->inet_sport, inet->inet_dport, sk);
+	if (IS_ERR(rt)) {
+		rt = NULL;
 		goto failure;
-
+	}
 	/* OK, now commit destination to socket.  */
 	sk_setup_caps(sk, &rt->dst);
 
@@ -461,17 +465,19 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
 					   struct sk_buff *skb)
 {
 	struct rtable *rt;
-	struct flowi fl = { .oif = skb_rtable(skb)->rt_iif,
-			    .fl4_dst = ip_hdr(skb)->saddr,
-			    .fl4_src = ip_hdr(skb)->daddr,
-			    .fl4_tos = RT_CONN_FLAGS(sk),
-			    .proto = sk->sk_protocol,
-			    .fl_ip_sport = dccp_hdr(skb)->dccph_dport,
-			    .fl_ip_dport = dccp_hdr(skb)->dccph_sport
-			  };
-
-	security_skb_classify_flow(skb, &fl);
-	if (ip_route_output_flow(net, &rt, &fl, sk, 0)) {
+	struct flowi4 fl4 = {
+		.flowi4_oif = skb_rtable(skb)->rt_iif,
+		.daddr = ip_hdr(skb)->saddr,
+		.saddr = ip_hdr(skb)->daddr,
+		.flowi4_tos = RT_CONN_FLAGS(sk),
+		.flowi4_proto = sk->sk_protocol,
+		.fl4_sport = dccp_hdr(skb)->dccph_dport,
+		.fl4_dport = dccp_hdr(skb)->dccph_sport,
+	};
+
+	security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
+	rt = ip_route_output_flow(net, &fl4, sk);
+	if (IS_ERR(rt)) {
 		IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
 		return NULL;
 	}
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index dca711d..de1b7e3 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -147,30 +147,24 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 		dst = __sk_dst_check(sk, np->dst_cookie);
 		if (dst == NULL) {
 			struct inet_sock *inet = inet_sk(sk);
-			struct flowi fl;
+			struct flowi6 fl6;
 
 			/* BUGGG_FUTURE: Again, it is not clear how
 			   to handle rthdr case. Ignore this complexity
 			   for now.
 			 */
-			memset(&fl, 0, sizeof(fl));
-			fl.proto = IPPROTO_DCCP;
-			ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-			ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-			fl.oif = sk->sk_bound_dev_if;
-			fl.fl_ip_dport = inet->inet_dport;
-			fl.fl_ip_sport = inet->inet_sport;
-			security_sk_classify_flow(sk, &fl);
-
-			err = ip6_dst_lookup(sk, &dst, &fl);
-			if (err) {
-				sk->sk_err_soft = -err;
-				goto out;
-			}
-
-			err = xfrm_lookup(net, &dst, &fl, sk, 0);
-			if (err < 0) {
-				sk->sk_err_soft = -err;
+			memset(&fl6, 0, sizeof(fl6));
+			fl6.flowi6_proto = IPPROTO_DCCP;
+			ipv6_addr_copy(&fl6.daddr, &np->daddr);
+			ipv6_addr_copy(&fl6.saddr, &np->saddr);
+			fl6.flowi6_oif = sk->sk_bound_dev_if;
+			fl6.fl6_dport = inet->inet_dport;
+			fl6.fl6_sport = inet->inet_sport;
+			security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
+
+			dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false);
+			if (IS_ERR(dst)) {
+				sk->sk_err_soft = -PTR_ERR(dst);
 				goto out;
 			}
 		} else
@@ -249,34 +243,30 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 	struct sk_buff *skb;
 	struct ipv6_txoptions *opt = NULL;
 	struct in6_addr *final_p, final;
-	struct flowi fl;
+	struct flowi6 fl6;
 	int err = -1;
 	struct dst_entry *dst;
 
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = IPPROTO_DCCP;
-	ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-	ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
-	fl.fl6_flowlabel = 0;
-	fl.oif = ireq6->iif;
-	fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-	fl.fl_ip_sport = inet_rsk(req)->loc_port;
-	security_req_classify_flow(req, &fl);
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = IPPROTO_DCCP;
+	ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
+	ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr);
+	fl6.flowlabel = 0;
+	fl6.flowi6_oif = ireq6->iif;
+	fl6.fl6_dport = inet_rsk(req)->rmt_port;
+	fl6.fl6_sport = inet_rsk(req)->loc_port;
+	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
 	opt = np->opt;
 
-	final_p = fl6_update_dst(&fl, opt, &final);
+	final_p = fl6_update_dst(&fl6, opt, &final);
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
-		goto done;
-
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0);
-	if (err < 0)
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
+		dst = NULL;
 		goto done;
+	}
 
 	skb = dccp_make_response(sk, dst, req);
 	if (skb != NULL) {
@@ -285,8 +275,8 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req,
 		dh->dccph_checksum = dccp_v6_csum_finish(skb,
 							 &ireq6->loc_addr,
 							 &ireq6->rmt_addr);
-		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		err = ip6_xmit(sk, skb, &fl, opt);
+		ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
+		err = ip6_xmit(sk, skb, &fl6, opt);
 		err = net_xmit_eval(err);
 	}
 
@@ -308,7 +298,7 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
 {
 	struct ipv6hdr *rxip6h;
 	struct sk_buff *skb;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct net *net = dev_net(skb_dst(rxskb)->dev);
 	struct sock *ctl_sk = net->dccp.v6_ctl_sk;
 	struct dst_entry *dst;
@@ -327,25 +317,24 @@ static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb)
 	dccp_hdr(skb)->dccph_checksum = dccp_v6_csum_finish(skb, &rxip6h->saddr,
 							    &rxip6h->daddr);
 
-	memset(&fl, 0, sizeof(fl));
-	ipv6_addr_copy(&fl.fl6_dst, &rxip6h->saddr);
-	ipv6_addr_copy(&fl.fl6_src, &rxip6h->daddr);
+	memset(&fl6, 0, sizeof(fl6));
+	ipv6_addr_copy(&fl6.daddr, &rxip6h->saddr);
+	ipv6_addr_copy(&fl6.saddr, &rxip6h->daddr);
 
-	fl.proto = IPPROTO_DCCP;
-	fl.oif = inet6_iif(rxskb);
-	fl.fl_ip_dport = dccp_hdr(skb)->dccph_dport;
-	fl.fl_ip_sport = dccp_hdr(skb)->dccph_sport;
-	security_skb_classify_flow(rxskb, &fl);
+	fl6.flowi6_proto = IPPROTO_DCCP;
+	fl6.flowi6_oif = inet6_iif(rxskb);
+	fl6.fl6_dport = dccp_hdr(skb)->dccph_dport;
+	fl6.fl6_sport = dccp_hdr(skb)->dccph_sport;
+	security_skb_classify_flow(rxskb, flowi6_to_flowi(&fl6));
 
 	/* sk = NULL, but it is safe for now. RST socket required. */
-	if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) {
-		if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) {
-			skb_dst_set(skb, dst);
-			ip6_xmit(ctl_sk, skb, &fl, NULL);
-			DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
-			DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
-			return;
-		}
+	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
+	if (!IS_ERR(dst)) {
+		skb_dst_set(skb, dst);
+		ip6_xmit(ctl_sk, skb, &fl6, NULL);
+		DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
+		DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
+		return;
 	}
 
 	kfree_skb(skb);
@@ -484,7 +473,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
 	struct inet6_request_sock *ireq6 = inet6_rsk(req);
 	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
 	struct inet_sock *newinet;
-	struct dccp_sock *newdp;
 	struct dccp6_sock *newdp6;
 	struct sock *newsk;
 	struct ipv6_txoptions *opt;
@@ -498,7 +486,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
 			return NULL;
 
 		newdp6 = (struct dccp6_sock *)newsk;
-		newdp = dccp_sk(newsk);
 		newinet = inet_sk(newsk);
 		newinet->pinet6 = &newdp6->inet6;
 		newnp = inet6_sk(newsk);
@@ -540,25 +527,20 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
 
 	if (dst == NULL) {
 		struct in6_addr *final_p, final;
-		struct flowi fl;
-
-		memset(&fl, 0, sizeof(fl));
-		fl.proto = IPPROTO_DCCP;
-		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		final_p = fl6_update_dst(&fl, opt, &final);
-		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
-		fl.oif = sk->sk_bound_dev_if;
-		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-		fl.fl_ip_sport = inet_rsk(req)->loc_port;
-		security_sk_classify_flow(sk, &fl);
-
-		if (ip6_dst_lookup(sk, &dst, &fl))
-			goto out;
-
-		if (final_p)
-			ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-		if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
+		struct flowi6 fl6;
+
+		memset(&fl6, 0, sizeof(fl6));
+		fl6.flowi6_proto = IPPROTO_DCCP;
+		ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
+		final_p = fl6_update_dst(&fl6, opt, &final);
+		ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr);
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
+		fl6.fl6_dport = inet_rsk(req)->rmt_port;
+		fl6.fl6_sport = inet_rsk(req)->loc_port;
+		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
+
+		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+		if (IS_ERR(dst))
 			goto out;
 	}
 
@@ -578,7 +560,6 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
 	newdp6 = (struct dccp6_sock *)newsk;
 	newinet = inet_sk(newsk);
 	newinet->pinet6 = &newdp6->inet6;
-	newdp = dccp_sk(newsk);
 	newnp = inet6_sk(newsk);
 
 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
@@ -878,7 +859,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct dccp_sock *dp = dccp_sk(sk);
 	struct in6_addr *saddr = NULL, *final_p, final;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 	int addr_type;
 	int err;
@@ -891,14 +872,14 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	if (usin->sin6_family != AF_INET6)
 		return -EAFNOSUPPORT;
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 
 	if (np->sndflow) {
-		fl.fl6_flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
-		IP6_ECN_flow_init(fl.fl6_flowlabel);
-		if (fl.fl6_flowlabel & IPV6_FLOWLABEL_MASK) {
+		fl6.flowlabel = usin->sin6_flowinfo & IPV6_FLOWINFO_MASK;
+		IP6_ECN_flow_init(fl6.flowlabel);
+		if (fl6.flowlabel & IPV6_FLOWLABEL_MASK) {
 			struct ip6_flowlabel *flowlabel;
-			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 			if (flowlabel == NULL)
 				return -EINVAL;
 			ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
@@ -935,7 +916,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	}
 
 	ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
-	np->flow_label = fl.fl6_flowlabel;
+	np->flow_label = fl6.flowlabel;
 
 	/*
 	 * DCCP over IPv4
@@ -972,33 +953,24 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	if (!ipv6_addr_any(&np->rcv_saddr))
 		saddr = &np->rcv_saddr;
 
-	fl.proto = IPPROTO_DCCP;
-	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-	ipv6_addr_copy(&fl.fl6_src, saddr ? saddr : &np->saddr);
-	fl.oif = sk->sk_bound_dev_if;
-	fl.fl_ip_dport = usin->sin6_port;
-	fl.fl_ip_sport = inet->inet_sport;
-	security_sk_classify_flow(sk, &fl);
+	fl6.flowi6_proto = IPPROTO_DCCP;
+	ipv6_addr_copy(&fl6.daddr, &np->daddr);
+	ipv6_addr_copy(&fl6.saddr, saddr ? saddr : &np->saddr);
+	fl6.flowi6_oif = sk->sk_bound_dev_if;
+	fl6.fl6_dport = usin->sin6_port;
+	fl6.fl6_sport = inet->inet_sport;
+	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	final_p = fl6_update_dst(&fl, np->opt, &final);
+	final_p = fl6_update_dst(&fl6, np->opt, &final);
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
 		goto failure;
-
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
-	if (err < 0) {
-		if (err == -EREMOTE)
-			err = ip6_dst_blackhole(sk, &dst, &fl);
-		if (err < 0)
-			goto failure;
 	}
 
 	if (saddr == NULL) {
-		saddr = &fl.fl6_src;
+		saddr = &fl6.saddr;
 		ipv6_addr_copy(&np->rcv_saddr, saddr);
 	}
 
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 2af15b1..ea3b6ee 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -908,7 +908,7 @@ static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen,
 	struct socket *sock = sk->sk_socket;
 	struct dn_scp *scp = DN_SK(sk);
 	int err = -EISCONN;
-	struct flowi fl;
+	struct flowidn fld;
 
 	if (sock->state == SS_CONNECTED)
 		goto out;
@@ -947,13 +947,13 @@ static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen,
 	memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn));
 
 	err = -EHOSTUNREACH;
-	memset(&fl, 0, sizeof(fl));
-	fl.oif = sk->sk_bound_dev_if;
-	fl.fld_dst = dn_saddr2dn(&scp->peer);
-	fl.fld_src = dn_saddr2dn(&scp->addr);
-	dn_sk_ports_copy(&fl, scp);
-	fl.proto = DNPROTO_NSP;
-	if (dn_route_output_sock(&sk->sk_dst_cache, &fl, sk, flags) < 0)
+	memset(&fld, 0, sizeof(fld));
+	fld.flowidn_oif = sk->sk_bound_dev_if;
+	fld.daddr = dn_saddr2dn(&scp->peer);
+	fld.saddr = dn_saddr2dn(&scp->addr);
+	dn_sk_ports_copy(&fld, scp);
+	fld.flowidn_proto = DNPROTO_NSP;
+	if (dn_route_output_sock(&sk->sk_dst_cache, &fld, sk, flags) < 0)
 		goto out;
 	sk->sk_route_caps = sk->sk_dst_cache->dev->features;
 	sock->state = SS_CONNECTING;
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index 0ef0a81..1c74ed3 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -201,7 +201,7 @@ static int dn_fib_check_nh(const struct rtmsg *r, struct dn_fib_info *fi, struct
 	int err;
 
 	if (nh->nh_gw) {
-		struct flowi fl;
+		struct flowidn fld;
 		struct dn_fib_res res;
 
 		if (nh->nh_flags&RTNH_F_ONLINK) {
@@ -221,15 +221,15 @@ static int dn_fib_check_nh(const struct rtmsg *r, struct dn_fib_info *fi, struct
 			return 0;
 		}
 
-		memset(&fl, 0, sizeof(fl));
-		fl.fld_dst = nh->nh_gw;
-		fl.oif = nh->nh_oif;
-		fl.fld_scope = r->rtm_scope + 1;
+		memset(&fld, 0, sizeof(fld));
+		fld.daddr = nh->nh_gw;
+		fld.flowidn_oif = nh->nh_oif;
+		fld.flowidn_scope = r->rtm_scope + 1;
 
-		if (fl.fld_scope < RT_SCOPE_LINK)
-			fl.fld_scope = RT_SCOPE_LINK;
+		if (fld.flowidn_scope < RT_SCOPE_LINK)
+			fld.flowidn_scope = RT_SCOPE_LINK;
 
-		if ((err = dn_fib_lookup(&fl, &res)) != 0)
+		if ((err = dn_fib_lookup(&fld, &res)) != 0)
 			return err;
 
 		err = -EINVAL;
@@ -404,7 +404,7 @@ failure:
 	return NULL;
 }
 
-int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *fl, struct dn_fib_res *res)
+int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn *fld, struct dn_fib_res *res)
 {
 	int err = dn_fib_props[type].error;
 
@@ -424,7 +424,8 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *
 				for_nexthops(fi) {
 					if (nh->nh_flags & RTNH_F_DEAD)
 						continue;
-					if (!fl->oif || fl->oif == nh->nh_oif)
+					if (!fld->flowidn_oif ||
+					    fld->flowidn_oif == nh->nh_oif)
 						break;
 				}
 				if (nhsel < fi->fib_nhs) {
@@ -445,7 +446,7 @@ int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *
 	return err;
 }
 
-void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res)
+void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res)
 {
 	struct dn_fib_info *fi = res->fi;
 	int w;
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index 2ef1152..bd78836 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -78,7 +78,7 @@ static void dn_nsp_send(struct sk_buff *skb)
 	struct sock *sk = skb->sk;
 	struct dn_scp *scp = DN_SK(sk);
 	struct dst_entry *dst;
-	struct flowi fl;
+	struct flowidn fld;
 
 	skb_reset_transport_header(skb);
 	scp->stamp = jiffies;
@@ -91,13 +91,13 @@ try_again:
 		return;
 	}
 
-	memset(&fl, 0, sizeof(fl));
-	fl.oif = sk->sk_bound_dev_if;
-	fl.fld_src = dn_saddr2dn(&scp->addr);
-	fl.fld_dst = dn_saddr2dn(&scp->peer);
-	dn_sk_ports_copy(&fl, scp);
-	fl.proto = DNPROTO_NSP;
-	if (dn_route_output_sock(&sk->sk_dst_cache, &fl, sk, 0) == 0) {
+	memset(&fld, 0, sizeof(fld));
+	fld.flowidn_oif = sk->sk_bound_dev_if;
+	fld.saddr = dn_saddr2dn(&scp->addr);
+	fld.daddr = dn_saddr2dn(&scp->peer);
+	dn_sk_ports_copy(&fld, scp);
+	fld.flowidn_proto = DNPROTO_NSP;
+	if (dn_route_output_sock(&sk->sk_dst_cache, &fld, sk, 0) == 0) {
 		dst = sk_dst_get(sk);
 		sk->sk_route_caps = dst->dev->features;
 		goto try_again;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 5e63636..9f09d4f 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -112,6 +112,7 @@ static int dn_dst_gc(struct dst_ops *ops);
 static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
 static unsigned int dn_dst_default_advmss(const struct dst_entry *dst);
 static unsigned int dn_dst_default_mtu(const struct dst_entry *dst);
+static void dn_dst_destroy(struct dst_entry *);
 static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 static void dn_dst_link_failure(struct sk_buff *);
 static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
@@ -133,11 +134,18 @@ static struct dst_ops dn_dst_ops = {
 	.check =		dn_dst_check,
 	.default_advmss =	dn_dst_default_advmss,
 	.default_mtu =		dn_dst_default_mtu,
+	.cow_metrics =		dst_cow_metrics_generic,
+	.destroy =		dn_dst_destroy,
 	.negative_advice =	dn_dst_negative_advice,
 	.link_failure =		dn_dst_link_failure,
 	.update_pmtu =		dn_dst_update_pmtu,
 };
 
+static void dn_dst_destroy(struct dst_entry *dst)
+{
+	dst_destroy_metrics_generic(dst);
+}
+
 static __inline__ unsigned dn_hash(__le16 src, __le16 dst)
 {
 	__u16 tmp = (__u16 __force)(src ^ dst);
@@ -274,14 +282,14 @@ static void dn_dst_link_failure(struct sk_buff *skb)
 {
 }
 
-static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+static inline int compare_keys(struct flowidn *fl1, struct flowidn *fl2)
 {
-	return ((fl1->fld_dst ^ fl2->fld_dst) |
-		(fl1->fld_src ^ fl2->fld_src) |
-		(fl1->mark ^ fl2->mark) |
-		(fl1->fld_scope ^ fl2->fld_scope) |
-		(fl1->oif ^ fl2->oif) |
-		(fl1->iif ^ fl2->iif)) == 0;
+	return ((fl1->daddr ^ fl2->daddr) |
+		(fl1->saddr ^ fl2->saddr) |
+		(fl1->flowidn_mark ^ fl2->flowidn_mark) |
+		(fl1->flowidn_scope ^ fl2->flowidn_scope) |
+		(fl1->flowidn_oif ^ fl2->flowidn_oif) |
+		(fl1->flowidn_iif ^ fl2->flowidn_iif)) == 0;
 }
 
 static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route **rp)
@@ -295,7 +303,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route *
 	spin_lock_bh(&dn_rt_hash_table[hash].lock);
 	while ((rth = rcu_dereference_protected(*rthp,
 						lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) {
-		if (compare_keys(&rth->fl, &rt->fl)) {
+		if (compare_keys(&rth->fld, &rt->fld)) {
 			/* Put it first */
 			*rthp = rth->dst.dn_next;
 			rcu_assign_pointer(rth->dst.dn_next,
@@ -814,14 +822,14 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
 {
 	struct dn_fib_info *fi = res->fi;
 	struct net_device *dev = rt->dst.dev;
+	unsigned int mss_metric;
 	struct neighbour *n;
-	unsigned int metric;
 
 	if (fi) {
 		if (DN_FIB_RES_GW(*res) &&
 		    DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
 			rt->rt_gateway = DN_FIB_RES_GW(*res);
-		dst_import_metrics(&rt->dst, fi->fib_metrics);
+		dst_init_metrics(&rt->dst, fi->fib_metrics, true);
 	}
 	rt->rt_type = res->type;
 
@@ -834,10 +842,10 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
 
 	if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
 		dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu);
-	metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS);
-	if (metric) {
+	mss_metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS);
+	if (mss_metric) {
 		unsigned int mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst));
-		if (metric > mss)
+		if (mss_metric > mss)
 			dst_metric_set(&rt->dst, RTAX_ADVMSS, mss);
 	}
 	return 0;
@@ -895,14 +903,16 @@ static inline __le16 dn_fib_rules_map_destination(__le16 daddr, struct dn_fib_re
 	return (daddr&~mask)|res->fi->fib_nh->nh_gw;
 }
 
-static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *oldflp, int try_hard)
+static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *oldflp, int try_hard)
 {
-	struct flowi fl = { .fld_dst = oldflp->fld_dst,
-			    .fld_src = oldflp->fld_src,
-			    .fld_scope = RT_SCOPE_UNIVERSE,
-			    .mark = oldflp->mark,
-			    .iif = init_net.loopback_dev->ifindex,
-			    .oif = oldflp->oif };
+	struct flowidn fld = {
+		.daddr = oldflp->daddr,
+		.saddr = oldflp->saddr,
+		.flowidn_scope = RT_SCOPE_UNIVERSE,
+		.flowidn_mark = oldflp->flowidn_mark,
+		.flowidn_iif = init_net.loopback_dev->ifindex,
+		.flowidn_oif = oldflp->flowidn_oif,
+	};
 	struct dn_route *rt = NULL;
 	struct net_device *dev_out = NULL, *dev;
 	struct neighbour *neigh = NULL;
@@ -916,13 +926,14 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
 	if (decnet_debug_level & 16)
 		printk(KERN_DEBUG
 		       "dn_route_output_slow: dst=%04x src=%04x mark=%d"
-		       " iif=%d oif=%d\n", le16_to_cpu(oldflp->fld_dst),
-		       le16_to_cpu(oldflp->fld_src),
-		       oldflp->mark, init_net.loopback_dev->ifindex, oldflp->oif);
+		       " iif=%d oif=%d\n", le16_to_cpu(oldflp->daddr),
+		       le16_to_cpu(oldflp->saddr),
+		       oldflp->flowidn_mark, init_net.loopback_dev->ifindex,
+		       oldflp->flowidn_oif);
 
 	/* If we have an output interface, verify its a DECnet device */
-	if (oldflp->oif) {
-		dev_out = dev_get_by_index(&init_net, oldflp->oif);
+	if (oldflp->flowidn_oif) {
+		dev_out = dev_get_by_index(&init_net, oldflp->flowidn_oif);
 		err = -ENODEV;
 		if (dev_out && dev_out->dn_ptr == NULL) {
 			dev_put(dev_out);
@@ -933,11 +944,11 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
 	}
 
 	/* If we have a source address, verify that its a local address */
-	if (oldflp->fld_src) {
+	if (oldflp->saddr) {
 		err = -EADDRNOTAVAIL;
 
 		if (dev_out) {
-			if (dn_dev_islocal(dev_out, oldflp->fld_src))
+			if (dn_dev_islocal(dev_out, oldflp->saddr))
 				goto source_ok;
 			dev_put(dev_out);
 			goto out;
@@ -946,11 +957,11 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old
 		for_each_netdev_rcu(&init_net, dev) {
 			if (!dev->dn_ptr)
 				continue;
-			if (!dn_dev_islocal(dev, oldflp->fld_src))
+			if (!dn_dev_islocal(dev, oldflp->saddr))
 				continue;
 			if ((dev->flags & IFF_LOOPBACK) &&
-			    oldflp->fld_dst &&
-			    !dn_dev_islocal(dev, oldflp->fld_dst))
+			    oldflp->daddr &&
+			    !dn_dev_islocal(dev, oldflp->daddr))
 				continue;
 
 			dev_out = dev;
@@ -965,22 +976,22 @@ source_ok:
 	}
 
 	/* No destination? Assume its local */
-	if (!fl.fld_dst) {
-		fl.fld_dst = fl.fld_src;
+	if (!fld.daddr) {
+		fld.daddr = fld.saddr;
 
 		err = -EADDRNOTAVAIL;
 		if (dev_out)
 			dev_put(dev_out);
 		dev_out = init_net.loopback_dev;
 		dev_hold(dev_out);
-		if (!fl.fld_dst) {
-			fl.fld_dst =
-			fl.fld_src = dnet_select_source(dev_out, 0,
+		if (!fld.daddr) {
+			fld.daddr =
+			fld.saddr = dnet_select_source(dev_out, 0,
 						       RT_SCOPE_HOST);
-			if (!fl.fld_dst)
+			if (!fld.daddr)
 				goto out;
 		}
-		fl.oif = init_net.loopback_dev->ifindex;
+		fld.flowidn_oif = init_net.loopback_dev->ifindex;
 		res.type = RTN_LOCAL;
 		goto make_route;
 	}
@@ -989,8 +1000,8 @@ source_ok:
 		printk(KERN_DEBUG
 		       "dn_route_output_slow: initial checks complete."
 		       " dst=%o4x src=%04x oif=%d try_hard=%d\n",
-		       le16_to_cpu(fl.fld_dst), le16_to_cpu(fl.fld_src),
-		       fl.oif, try_hard);
+		       le16_to_cpu(fld.daddr), le16_to_cpu(fld.saddr),
+		       fld.flowidn_oif, try_hard);
 
 	/*
 	 * N.B. If the kernel is compiled without router support then
@@ -998,7 +1009,7 @@ source_ok:
 	 * will always be executed.
 	 */
 	err = -ESRCH;
-	if (try_hard || (err = dn_fib_lookup(&fl, &res)) != 0) {
+	if (try_hard || (err = dn_fib_lookup(&fld, &res)) != 0) {
 		struct dn_dev *dn_db;
 		if (err != -ESRCH)
 			goto out;
@@ -1013,19 +1024,19 @@ source_ok:
 		 * here
 		 */
 		if (!try_hard) {
-			neigh = neigh_lookup_nodev(&dn_neigh_table, &init_net, &fl.fld_dst);
+			neigh = neigh_lookup_nodev(&dn_neigh_table, &init_net, &fld.daddr);
 			if (neigh) {
-				if ((oldflp->oif &&
-				    (neigh->dev->ifindex != oldflp->oif)) ||
-				    (oldflp->fld_src &&
+				if ((oldflp->flowidn_oif &&
+				    (neigh->dev->ifindex != oldflp->flowidn_oif)) ||
+				    (oldflp->saddr &&
 				    (!dn_dev_islocal(neigh->dev,
-						      oldflp->fld_src)))) {
+						     oldflp->saddr)))) {
 					neigh_release(neigh);
 					neigh = NULL;
 				} else {
 					if (dev_out)
 						dev_put(dev_out);
-					if (dn_dev_islocal(neigh->dev, fl.fld_dst)) {
+					if (dn_dev_islocal(neigh->dev, fld.daddr)) {
 						dev_out = init_net.loopback_dev;
 						res.type = RTN_LOCAL;
 					} else {
@@ -1045,7 +1056,7 @@ source_ok:
 			goto out;
 		dn_db = rcu_dereference_raw(dev_out->dn_ptr);
 		/* Possible improvement - check all devices for local addr */
-		if (dn_dev_islocal(dev_out, fl.fld_dst)) {
+		if (dn_dev_islocal(dev_out, fld.daddr)) {
 			dev_put(dev_out);
 			dev_out = init_net.loopback_dev;
 			dev_hold(dev_out);
@@ -1061,16 +1072,16 @@ select_source:
 		if (neigh)
 			gateway = ((struct dn_neigh *)neigh)->addr;
 		if (gateway == 0)
-			gateway = fl.fld_dst;
-		if (fl.fld_src == 0) {
-			fl.fld_src = dnet_select_source(dev_out, gateway,
-							 res.type == RTN_LOCAL ?
-							 RT_SCOPE_HOST :
-							 RT_SCOPE_LINK);
-			if (fl.fld_src == 0 && res.type != RTN_LOCAL)
+			gateway = fld.daddr;
+		if (fld.saddr == 0) {
+			fld.saddr = dnet_select_source(dev_out, gateway,
+						       res.type == RTN_LOCAL ?
+						       RT_SCOPE_HOST :
+						       RT_SCOPE_LINK);
+			if (fld.saddr == 0 && res.type != RTN_LOCAL)
 				goto e_addr;
 		}
-		fl.oif = dev_out->ifindex;
+		fld.flowidn_oif = dev_out->ifindex;
 		goto make_route;
 	}
 	free_res = 1;
@@ -1079,61 +1090,61 @@ select_source:
 		goto e_inval;
 
 	if (res.type == RTN_LOCAL) {
-		if (!fl.fld_src)
-			fl.fld_src = fl.fld_dst;
+		if (!fld.saddr)
+			fld.saddr = fld.daddr;
 		if (dev_out)
 			dev_put(dev_out);
 		dev_out = init_net.loopback_dev;
 		dev_hold(dev_out);
-		fl.oif = dev_out->ifindex;
+		fld.flowidn_oif = dev_out->ifindex;
 		if (res.fi)
 			dn_fib_info_put(res.fi);
 		res.fi = NULL;
 		goto make_route;
 	}
 
-	if (res.fi->fib_nhs > 1 && fl.oif == 0)
-		dn_fib_select_multipath(&fl, &res);
+	if (res.fi->fib_nhs > 1 && fld.flowidn_oif == 0)
+		dn_fib_select_multipath(&fld, &res);
 
 	/*
 	 * We could add some logic to deal with default routes here and
 	 * get rid of some of the special casing above.
 	 */
 
-	if (!fl.fld_src)
-		fl.fld_src = DN_FIB_RES_PREFSRC(res);
+	if (!fld.saddr)
+		fld.saddr = DN_FIB_RES_PREFSRC(res);
 
 	if (dev_out)
 		dev_put(dev_out);
 	dev_out = DN_FIB_RES_DEV(res);
 	dev_hold(dev_out);
-	fl.oif = dev_out->ifindex;
+	fld.flowidn_oif = dev_out->ifindex;
 	gateway = DN_FIB_RES_GW(res);
 
 make_route:
 	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
-	rt = dst_alloc(&dn_dst_ops);
+	rt = dst_alloc(&dn_dst_ops, 0);
 	if (rt == NULL)
 		goto e_nobufs;
 
 	atomic_set(&rt->dst.__refcnt, 1);
 	rt->dst.flags   = DST_HOST;
 
-	rt->fl.fld_src    = oldflp->fld_src;
-	rt->fl.fld_dst    = oldflp->fld_dst;
-	rt->fl.oif        = oldflp->oif;
-	rt->fl.iif        = 0;
-	rt->fl.mark       = oldflp->mark;
+	rt->fld.saddr        = oldflp->saddr;
+	rt->fld.daddr        = oldflp->daddr;
+	rt->fld.flowidn_oif  = oldflp->flowidn_oif;
+	rt->fld.flowidn_iif  = 0;
+	rt->fld.flowidn_mark = oldflp->flowidn_mark;
 
-	rt->rt_saddr      = fl.fld_src;
-	rt->rt_daddr      = fl.fld_dst;
-	rt->rt_gateway    = gateway ? gateway : fl.fld_dst;
-	rt->rt_local_src  = fl.fld_src;
+	rt->rt_saddr      = fld.saddr;
+	rt->rt_daddr      = fld.daddr;
+	rt->rt_gateway    = gateway ? gateway : fld.daddr;
+	rt->rt_local_src  = fld.saddr;
 
-	rt->rt_dst_map    = fl.fld_dst;
-	rt->rt_src_map    = fl.fld_src;
+	rt->rt_dst_map    = fld.daddr;
+	rt->rt_src_map    = fld.saddr;
 
 	rt->dst.dev = dev_out;
 	dev_hold(dev_out);
@@ -1151,7 +1162,7 @@ make_route:
 	if (err)
 		goto e_neighbour;
 
-	hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst);
+	hash = dn_hash(rt->fld.saddr, rt->fld.daddr);
 	dn_insert_route(rt, hash, (struct dn_route **)pprt);
 
 done:
@@ -1182,20 +1193,20 @@ e_neighbour:
 /*
  * N.B. The flags may be moved into the flowi at some future stage.
  */
-static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *flp, int flags)
+static int __dn_route_output_key(struct dst_entry **pprt, const struct flowidn *flp, int flags)
 {
-	unsigned hash = dn_hash(flp->fld_src, flp->fld_dst);
+	unsigned hash = dn_hash(flp->saddr, flp->daddr);
 	struct dn_route *rt = NULL;
 
 	if (!(flags & MSG_TRYHARD)) {
 		rcu_read_lock_bh();
 		for (rt = rcu_dereference_bh(dn_rt_hash_table[hash].chain); rt;
 			rt = rcu_dereference_bh(rt->dst.dn_next)) {
-			if ((flp->fld_dst == rt->fl.fld_dst) &&
-			    (flp->fld_src == rt->fl.fld_src) &&
-			    (flp->mark == rt->fl.mark) &&
+			if ((flp->daddr == rt->fld.daddr) &&
+			    (flp->saddr == rt->fld.saddr) &&
+			    (flp->flowidn_mark == rt->fld.flowidn_mark) &&
 			    dn_is_output_route(rt) &&
-			    (rt->fl.oif == flp->oif)) {
+			    (rt->fld.flowidn_oif == flp->flowidn_oif)) {
 				dst_use(&rt->dst, jiffies);
 				rcu_read_unlock_bh();
 				*pprt = &rt->dst;
@@ -1208,25 +1219,36 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl
 	return dn_route_output_slow(pprt, flp, flags);
 }
 
-static int dn_route_output_key(struct dst_entry **pprt, struct flowi *flp, int flags)
+static int dn_route_output_key(struct dst_entry **pprt, struct flowidn *flp, int flags)
 {
 	int err;
 
 	err = __dn_route_output_key(pprt, flp, flags);
-	if (err == 0 && flp->proto) {
-		err = xfrm_lookup(&init_net, pprt, flp, NULL, 0);
+	if (err == 0 && flp->flowidn_proto) {
+		*pprt = xfrm_lookup(&init_net, *pprt,
+				    flowidn_to_flowi(flp), NULL, 0);
+		if (IS_ERR(*pprt)) {
+			err = PTR_ERR(*pprt);
+			*pprt = NULL;
+		}
 	}
 	return err;
 }
 
-int dn_route_output_sock(struct dst_entry **pprt, struct flowi *fl, struct sock *sk, int flags)
+int dn_route_output_sock(struct dst_entry **pprt, struct flowidn *fl, struct sock *sk, int flags)
 {
 	int err;
 
 	err = __dn_route_output_key(pprt, fl, flags & MSG_TRYHARD);
-	if (err == 0 && fl->proto) {
-		err = xfrm_lookup(&init_net, pprt, fl, sk,
-				 (flags & MSG_DONTWAIT) ? 0 : XFRM_LOOKUP_WAIT);
+	if (err == 0 && fl->flowidn_proto) {
+		if (!(flags & MSG_DONTWAIT))
+			fl->flowidn_flags |= FLOWI_FLAG_CAN_SLEEP;
+		*pprt = xfrm_lookup(&init_net, *pprt,
+				    flowidn_to_flowi(fl), sk, 0);
+		if (IS_ERR(*pprt)) {
+			err = PTR_ERR(*pprt);
+			*pprt = NULL;
+		}
 	}
 	return err;
 }
@@ -1243,11 +1265,13 @@ static int dn_route_input_slow(struct sk_buff *skb)
 	int flags = 0;
 	__le16 gateway = 0;
 	__le16 local_src = 0;
-	struct flowi fl = { .fld_dst = cb->dst,
-			    .fld_src = cb->src,
-			    .fld_scope = RT_SCOPE_UNIVERSE,
-			    .mark = skb->mark,
-			    .iif = skb->dev->ifindex };
+	struct flowidn fld = {
+		.daddr = cb->dst,
+		.saddr = cb->src,
+		.flowidn_scope = RT_SCOPE_UNIVERSE,
+		.flowidn_mark = skb->mark,
+		.flowidn_iif = skb->dev->ifindex,
+	};
 	struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE };
 	int err = -EINVAL;
 	int free_res = 0;
@@ -1258,7 +1282,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
 		goto out;
 
 	/* Zero source addresses are not allowed */
-	if (fl.fld_src == 0)
+	if (fld.saddr == 0)
 		goto out;
 
 	/*
@@ -1272,7 +1296,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
 	if (dn_dev_islocal(in_dev, cb->src))
 		goto out;
 
-	err = dn_fib_lookup(&fl, &res);
+	err = dn_fib_lookup(&fld, &res);
 	if (err) {
 		if (err != -ESRCH)
 			goto out;
@@ -1284,7 +1308,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
 
 		res.type = RTN_LOCAL;
 	} else {
-		__le16 src_map = fl.fld_src;
+		__le16 src_map = fld.saddr;
 		free_res = 1;
 
 		out_dev = DN_FIB_RES_DEV(res);
@@ -1297,22 +1321,22 @@ static int dn_route_input_slow(struct sk_buff *skb)
 		dev_hold(out_dev);
 
 		if (res.r)
-			src_map = fl.fld_src; /* no NAT support for now */
+			src_map = fld.saddr; /* no NAT support for now */
 
 		gateway = DN_FIB_RES_GW(res);
 		if (res.type == RTN_NAT) {
-			fl.fld_dst = dn_fib_rules_map_destination(fl.fld_dst, &res);
+			fld.daddr = dn_fib_rules_map_destination(fld.daddr, &res);
 			dn_fib_res_put(&res);
 			free_res = 0;
-			if (dn_fib_lookup(&fl, &res))
+			if (dn_fib_lookup(&fld, &res))
 				goto e_inval;
 			free_res = 1;
 			if (res.type != RTN_UNICAST)
 				goto e_inval;
 			flags |= RTCF_DNAT;
-			gateway = fl.fld_dst;
+			gateway = fld.daddr;
 		}
-		fl.fld_src = src_map;
+		fld.saddr = src_map;
 	}
 
 	switch(res.type) {
@@ -1326,8 +1350,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
 		if (dn_db->parms.forwarding == 0)
 			goto e_inval;
 
-		if (res.fi->fib_nhs > 1 && fl.oif == 0)
-			dn_fib_select_multipath(&fl, &res);
+		if (res.fi->fib_nhs > 1 && fld.flowidn_oif == 0)
+			dn_fib_select_multipath(&fld, &res);
 
 		/*
 		 * Check for out_dev == in_dev. We use the RTCF_DOREDIRECT
@@ -1345,8 +1369,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
 		break;
 	case RTN_LOCAL:
 		flags |= RTCF_LOCAL;
-		fl.fld_src = cb->dst;
-		fl.fld_dst = cb->src;
+		fld.saddr = cb->dst;
+		fld.daddr = cb->src;
 
 		/* Routing tables gave us a gateway */
 		if (gateway)
@@ -1375,25 +1399,25 @@ static int dn_route_input_slow(struct sk_buff *skb)
 	}
 
 make_route:
-	rt = dst_alloc(&dn_dst_ops);
+	rt = dst_alloc(&dn_dst_ops, 0);
 	if (rt == NULL)
 		goto e_nobufs;
 
-	rt->rt_saddr      = fl.fld_src;
-	rt->rt_daddr      = fl.fld_dst;
-	rt->rt_gateway    = fl.fld_dst;
+	rt->rt_saddr      = fld.saddr;
+	rt->rt_daddr      = fld.daddr;
+	rt->rt_gateway    = fld.daddr;
 	if (gateway)
 		rt->rt_gateway = gateway;
 	rt->rt_local_src  = local_src ? local_src : rt->rt_saddr;
 
-	rt->rt_dst_map    = fl.fld_dst;
-	rt->rt_src_map    = fl.fld_src;
+	rt->rt_dst_map    = fld.daddr;
+	rt->rt_src_map    = fld.saddr;
 
-	rt->fl.fld_src    = cb->src;
-	rt->fl.fld_dst    = cb->dst;
-	rt->fl.oif        = 0;
-	rt->fl.iif        = in_dev->ifindex;
-	rt->fl.mark       = fl.mark;
+	rt->fld.saddr        = cb->src;
+	rt->fld.daddr        = cb->dst;
+	rt->fld.flowidn_oif  = 0;
+	rt->fld.flowidn_iif  = in_dev->ifindex;
+	rt->fld.flowidn_mark = fld.flowidn_mark;
 
 	rt->dst.flags = DST_HOST;
 	rt->dst.neighbour = neigh;
@@ -1423,7 +1447,7 @@ make_route:
 	if (err)
 		goto e_neighbour;
 
-	hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst);
+	hash = dn_hash(rt->fld.saddr, rt->fld.daddr);
 	dn_insert_route(rt, hash, &rt);
 	skb_dst_set(skb, &rt->dst);
 
@@ -1463,11 +1487,11 @@ static int dn_route_input(struct sk_buff *skb)
 	rcu_read_lock();
 	for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL;
 	    rt = rcu_dereference(rt->dst.dn_next)) {
-		if ((rt->fl.fld_src == cb->src) &&
-		    (rt->fl.fld_dst == cb->dst) &&
-		    (rt->fl.oif == 0) &&
-		    (rt->fl.mark == skb->mark) &&
-		    (rt->fl.iif == cb->iif)) {
+		if ((rt->fld.saddr == cb->src) &&
+		    (rt->fld.daddr == cb->dst) &&
+		    (rt->fld.flowidn_oif == 0) &&
+		    (rt->fld.flowidn_mark == skb->mark) &&
+		    (rt->fld.flowidn_iif == cb->iif)) {
 			dst_use(&rt->dst, jiffies);
 			rcu_read_unlock();
 			skb_dst_set(skb, (struct dst_entry *)rt);
@@ -1503,9 +1527,9 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
 	if (rt->rt_flags & RTCF_NOTIFY)
 		r->rtm_flags |= RTM_F_NOTIFY;
 	RTA_PUT(skb, RTA_DST, 2, &rt->rt_daddr);
-	if (rt->fl.fld_src) {
+	if (rt->fld.saddr) {
 		r->rtm_src_len = 16;
-		RTA_PUT(skb, RTA_SRC, 2, &rt->fl.fld_src);
+		RTA_PUT(skb, RTA_SRC, 2, &rt->fld.saddr);
 	}
 	if (rt->dst.dev)
 		RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->dst.dev->ifindex);
@@ -1524,7 +1548,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
 			       rt->dst.error) < 0)
 		goto rtattr_failure;
 	if (dn_is_input_route(rt))
-		RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif);
+		RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fld.flowidn_iif);
 
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	return skb->len;
@@ -1547,13 +1571,13 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
 	struct dn_skb_cb *cb;
 	int err;
 	struct sk_buff *skb;
-	struct flowi fl;
+	struct flowidn fld;
 
 	if (!net_eq(net, &init_net))
 		return -EINVAL;
 
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = DNPROTO_NSP;
+	memset(&fld, 0, sizeof(fld));
+	fld.flowidn_proto = DNPROTO_NSP;
 
 	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
 	if (skb == NULL)
@@ -1562,15 +1586,15 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
 	cb = DN_SKB_CB(skb);
 
 	if (rta[RTA_SRC-1])
-		memcpy(&fl.fld_src, RTA_DATA(rta[RTA_SRC-1]), 2);
+		memcpy(&fld.saddr, RTA_DATA(rta[RTA_SRC-1]), 2);
 	if (rta[RTA_DST-1])
-		memcpy(&fl.fld_dst, RTA_DATA(rta[RTA_DST-1]), 2);
+		memcpy(&fld.daddr, RTA_DATA(rta[RTA_DST-1]), 2);
 	if (rta[RTA_IIF-1])
-		memcpy(&fl.iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
+		memcpy(&fld.flowidn_iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
 
-	if (fl.iif) {
+	if (fld.flowidn_iif) {
 		struct net_device *dev;
-		if ((dev = dev_get_by_index(&init_net, fl.iif)) == NULL) {
+		if ((dev = dev_get_by_index(&init_net, fld.flowidn_iif)) == NULL) {
 			kfree_skb(skb);
 			return -ENODEV;
 		}
@@ -1581,8 +1605,8 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
 		}
 		skb->protocol = htons(ETH_P_DNA_RT);
 		skb->dev = dev;
-		cb->src = fl.fld_src;
-		cb->dst = fl.fld_dst;
+		cb->src = fld.saddr;
+		cb->dst = fld.daddr;
 		local_bh_disable();
 		err = dn_route_input(skb);
 		local_bh_enable();
@@ -1594,8 +1618,8 @@ static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void
 		int oif = 0;
 		if (rta[RTA_OIF - 1])
 			memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
-		fl.oif = oif;
-		err = dn_route_output_key((struct dst_entry **)&rt, &fl, 0);
+		fld.flowidn_oif = oif;
+		err = dn_route_output_key((struct dst_entry **)&rt, &fld, 0);
 	}
 
 	if (skb->dev)
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 6eb91df..f0efb0c 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -49,14 +49,15 @@ struct dn_fib_rule
 };
 
 
-int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
+int dn_fib_lookup(struct flowidn *flp, struct dn_fib_res *res)
 {
 	struct fib_lookup_arg arg = {
 		.result = res,
 	};
 	int err;
 
-	err = fib_rules_lookup(dn_fib_rules_ops, flp, 0, &arg);
+	err = fib_rules_lookup(dn_fib_rules_ops,
+			       flowidn_to_flowi(flp), 0, &arg);
 	res->r = arg.rule;
 
 	return err;
@@ -65,6 +66,7 @@ int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
 static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
 			      int flags, struct fib_lookup_arg *arg)
 {
+	struct flowidn *fld = &flp->u.dn;
 	int err = -EAGAIN;
 	struct dn_fib_table *tbl;
 
@@ -90,7 +92,7 @@ static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
 	if (tbl == NULL)
 		goto errout;
 
-	err = tbl->lookup(tbl, flp, (struct dn_fib_res *)arg->result);
+	err = tbl->lookup(tbl, fld, (struct dn_fib_res *)arg->result);
 	if (err > 0)
 		err = -EAGAIN;
 errout:
@@ -104,8 +106,9 @@ static const struct nla_policy dn_fib_rule_policy[FRA_MAX+1] = {
 static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
 	struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
-	__le16 daddr = fl->fld_dst;
-	__le16 saddr = fl->fld_src;
+	struct flowidn *fld = &fl->u.dn;
+	__le16 daddr = fld->daddr;
+	__le16 saddr = fld->saddr;
 
 	if (((saddr ^ r->src) & r->srcmask) ||
 	    ((daddr ^ r->dst) & r->dstmask))
@@ -175,7 +178,7 @@ static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
 
 unsigned dnet_addr_type(__le16 addr)
 {
-	struct flowi fl = { .fld_dst = addr };
+	struct flowidn fld = { .daddr = addr };
 	struct dn_fib_res res;
 	unsigned ret = RTN_UNICAST;
 	struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
@@ -183,7 +186,7 @@ unsigned dnet_addr_type(__le16 addr)
 	res.r = NULL;
 
 	if (tb) {
-		if (!tb->lookup(tb, &fl, &res)) {
+		if (!tb->lookup(tb, &fld, &res)) {
 			ret = res.type;
 			dn_fib_res_put(&res);
 		}
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index f2abd37..99d8d3a 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -59,7 +59,6 @@ struct dn_hash
 };
 
 #define dz_key_0(key)		((key).datum = 0)
-#define dz_prefix(key,dz)	((key).datum)
 
 #define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
 	for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
@@ -765,7 +764,7 @@ static int dn_fib_table_flush(struct dn_fib_table *tb)
 	return found;
 }
 
-static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowi *flp, struct dn_fib_res *res)
+static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowidn *flp, struct dn_fib_res *res)
 {
 	int err;
 	struct dn_zone *dz;
@@ -774,7 +773,7 @@ static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowi *flp,
 	read_lock(&dn_fib_tables_lock);
 	for(dz = t->dh_zone_list; dz; dz = dz->dz_next) {
 		struct dn_fib_node *f;
-		dn_fib_key_t k = dz_key(flp->fld_dst, dz);
+		dn_fib_key_t k = dz_key(flp->daddr, dz);
 
 		for(f = dz_chain(k, dz); f; f = f->fn_next) {
 			if (!dn_key_eq(k, f->fn_key)) {
@@ -789,7 +788,7 @@ static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowi *flp,
 			if (f->fn_state&DN_S_ZOMBIE)
 				continue;
 
-			if (f->fn_scope < flp->fld_scope)
+			if (f->fn_scope < flp->flowidn_scope)
 				continue;
 
 			err = dn_fib_semantic_match(f->fn_type, DN_FIB_INFO(f), flp, res);
diff --git a/net/dsa/mv88e6060.c b/net/dsa/mv88e6060.c
index 83277f4..8f4ff5a 100644
--- a/net/dsa/mv88e6060.c
+++ b/net/dsa/mv88e6060.c
@@ -18,7 +18,7 @@
 
 static int reg_read(struct dsa_switch *ds, int addr, int reg)
 {
-	return mdiobus_read(ds->master_mii_bus, addr, reg);
+	return mdiobus_read(ds->master_mii_bus, ds->pd->sw_addr + addr, reg);
 }
 
 #define REG_READ(addr, reg)					\
@@ -34,7 +34,8 @@ static int reg_read(struct dsa_switch *ds, int addr, int reg)
 
 static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
 {
-	return mdiobus_write(ds->master_mii_bus, addr, reg, val);
+	return mdiobus_write(ds->master_mii_bus, ds->pd->sw_addr + addr,
+			     reg, val);
 }
 
 #define REG_WRITE(addr, reg, val)				\
@@ -50,7 +51,7 @@ static char *mv88e6060_probe(struct mii_bus *bus, int sw_addr)
 {
 	int ret;
 
-	ret = mdiobus_read(bus, REG_PORT(0), 0x03);
+	ret = mdiobus_read(bus, sw_addr + REG_PORT(0), 0x03);
 	if (ret >= 0) {
 		ret &= 0xfff0;
 		if (ret == 0x0600)
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
index 0c28263..116d3fd 100644
--- a/net/econet/af_econet.c
+++ b/net/econet/af_econet.c
@@ -435,10 +435,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
 		udpdest.sin_addr.s_addr = htonl(network | addr.station);
 	}
 
+	memset(&ah, 0, sizeof(ah));
 	ah.port = port;
 	ah.cb = cb & 0x7f;
 	ah.code = 2;		/* magic */
-	ah.pad = 0;
 
 	/* tack our header on the front of the iovec */
 	size = sizeof(struct aunhdr);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index a5a1050..cbb505b 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -55,45 +55,9 @@ config IP_ADVANCED_ROUTER
 
 	  If unsure, say N here.
 
-choice
-	prompt "Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure)"
-	depends on IP_ADVANCED_ROUTER
-	default ASK_IP_FIB_HASH
-
-config ASK_IP_FIB_HASH
-	bool "FIB_HASH"
-	---help---
-	  Current FIB is very proven and good enough for most users.
-
-config IP_FIB_TRIE
-	bool "FIB_TRIE"
-	---help---
-	  Use new experimental LC-trie as FIB lookup algorithm.
-	  This improves lookup performance if you have a large
-	  number of routes.
-
-	  LC-trie is a longest matching prefix lookup algorithm which
-	  performs better than FIB_HASH for large routing tables.
-	  But, it consumes more memory and is more complex.
-
-	  LC-trie is described in:
-
-	  IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
-	  IEEE Journal on Selected Areas in Communications, 17(6):1083-1092,
-	  June 1999
-
-	  An experimental study of compression methods for dynamic tries
-	  Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
-	  <http://www.csc.kth.se/~snilsson/software/dyntrie2/>
-
-endchoice
-
-config IP_FIB_HASH
-	def_bool ASK_IP_FIB_HASH || !IP_ADVANCED_ROUTER
-
 config IP_FIB_TRIE_STATS
 	bool "FIB TRIE statistics"
-	depends on IP_FIB_TRIE
+	depends on IP_ADVANCED_ROUTER
 	---help---
 	  Keep track of statistics on structure of FIB TRIE table.
 	  Useful for testing and measuring TRIE performance.
@@ -140,6 +104,9 @@ config IP_ROUTE_VERBOSE
 	  handled by the klogd daemon which is responsible for kernel messages
 	  ("man klogd").
 
+config IP_ROUTE_CLASSID
+	bool
+
 config IP_PNP
 	bool "IP: kernel level autoconfiguration"
 	help
@@ -657,4 +624,3 @@ config TCP_MD5SIG
 	  on the Internet.
 
 	  If unsure, say N.
-
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 4978d22..0dc772d 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -10,12 +10,10 @@ obj-y     := route.o inetpeer.o protocol.o \
 	     tcp_minisocks.o tcp_cong.o \
 	     datagram.o raw.o udp.o udplite.o \
 	     arp.o icmp.o devinet.o af_inet.o  igmp.o \
-	     fib_frontend.o fib_semantics.o \
+	     fib_frontend.o fib_semantics.o fib_trie.o \
 	     inet_fragment.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
-obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
-obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 45b89d7..807d83c 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1101,23 +1101,20 @@ int sysctl_ip_dynaddr __read_mostly;
 static int inet_sk_reselect_saddr(struct sock *sk)
 {
 	struct inet_sock *inet = inet_sk(sk);
-	int err;
-	struct rtable *rt;
 	__be32 old_saddr = inet->inet_saddr;
-	__be32 new_saddr;
 	__be32 daddr = inet->inet_daddr;
+	struct rtable *rt;
+	__be32 new_saddr;
 
 	if (inet->opt && inet->opt->srr)
 		daddr = inet->opt->faddr;
 
 	/* Query new route. */
-	err = ip_route_connect(&rt, daddr, 0,
-			       RT_CONN_FLAGS(sk),
-			       sk->sk_bound_dev_if,
-			       sk->sk_protocol,
-			       inet->inet_sport, inet->inet_dport, sk, 0);
-	if (err)
-		return err;
+	rt = ip_route_connect(daddr, 0, RT_CONN_FLAGS(sk),
+			      sk->sk_bound_dev_if, sk->sk_protocol,
+			      inet->inet_sport, inet->inet_dport, sk, false);
+	if (IS_ERR(rt))
+		return PTR_ERR(rt);
 
 	sk_setup_caps(sk, &rt->dst);
 
@@ -1160,25 +1157,16 @@ int inet_sk_rebuild_header(struct sock *sk)
 	daddr = inet->inet_daddr;
 	if (inet->opt && inet->opt->srr)
 		daddr = inet->opt->faddr;
-{
-	struct flowi fl = {
-		.oif = sk->sk_bound_dev_if,
-		.mark = sk->sk_mark,
-		.fl4_dst = daddr,
-		.fl4_src = inet->inet_saddr,
-		.fl4_tos = RT_CONN_FLAGS(sk),
-		.proto = sk->sk_protocol,
-		.flags = inet_sk_flowi_flags(sk),
-		.fl_ip_sport = inet->inet_sport,
-		.fl_ip_dport = inet->inet_dport,
-	};
-
-	security_sk_classify_flow(sk, &fl);
-	err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0);
-}
-	if (!err)
+	rt = ip_route_output_ports(sock_net(sk), sk, daddr, inet->inet_saddr,
+				   inet->inet_dport, inet->inet_sport,
+				   sk->sk_protocol, RT_CONN_FLAGS(sk),
+				   sk->sk_bound_dev_if);
+	if (!IS_ERR(rt)) {
+		err = 0;
 		sk_setup_caps(sk, &rt->dst);
-	else {
+	} else {
+		err = PTR_ERR(rt);
+
 		/* Routing failed... */
 		sk->sk_route_caps = 0;
 		/*
@@ -1231,7 +1219,7 @@ out:
 	return err;
 }
 
-static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
+static struct sk_buff *inet_gso_segment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct iphdr *iph;
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 86961be..4286fd3 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -201,11 +201,14 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
 	top_iph->ttl = 0;
 	top_iph->check = 0;
 
-	ah->hdrlen  = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
+	if (x->props.flags & XFRM_STATE_ALIGN4)
+		ah->hdrlen  = (XFRM_ALIGN4(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
+	else
+		ah->hdrlen  = (XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len) >> 2) - 2;
 
 	ah->reserved = 0;
 	ah->spi = x->id.spi;
-	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
+	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg, 0, skb->len);
@@ -299,9 +302,15 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 	nexthdr = ah->nexthdr;
 	ah_hlen = (ah->hdrlen + 2) << 2;
 
-	if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
-	    ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len))
-		goto out;
+	if (x->props.flags & XFRM_STATE_ALIGN4) {
+		if (ah_hlen != XFRM_ALIGN4(sizeof(*ah) + ahp->icv_full_len) &&
+		    ah_hlen != XFRM_ALIGN4(sizeof(*ah) + ahp->icv_trunc_len))
+			goto out;
+	} else {
+		if (ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_full_len) &&
+		    ah_hlen != XFRM_ALIGN8(sizeof(*ah) + ahp->icv_trunc_len))
+			goto out;
+	}
 
 	if (!pskb_may_pull(skb, ah_hlen))
 		goto out;
@@ -450,8 +459,12 @@ static int ah_init_state(struct xfrm_state *x)
 
 	BUG_ON(ahp->icv_trunc_len > MAX_AH_AUTH_LEN);
 
-	x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
-					  ahp->icv_trunc_len);
+	if (x->props.flags & XFRM_STATE_ALIGN4)
+		x->props.header_len = XFRM_ALIGN4(sizeof(struct ip_auth_hdr) +
+						  ahp->icv_trunc_len);
+	else
+		x->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +
+						  ahp->icv_trunc_len);
 	if (x->props.mode == XFRM_MODE_TUNNEL)
 		x->props.header_len += sizeof(struct iphdr);
 	x->data = ahp;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 7927589..090d273 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -433,14 +433,13 @@ static int arp_ignore(struct in_device *in_dev, __be32 sip, __be32 tip)
 
 static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
 {
-	struct flowi fl = { .fl4_dst = sip,
-			    .fl4_src = tip };
 	struct rtable *rt;
 	int flag = 0;
 	/*unsigned long now; */
 	struct net *net = dev_net(dev);
 
-	if (ip_route_output_key(net, &rt, &fl) < 0)
+	rt = ip_route_output(net, sip, tip, 0, 0);
+	if (IS_ERR(rt))
 		return 1;
 	if (rt->dst.dev != dev) {
 		NET_INC_STATS_BH(net, LINUX_MIB_ARPFILTER);
@@ -1061,12 +1060,10 @@ static int arp_req_set(struct net *net, struct arpreq *r,
 	if (r->arp_flags & ATF_PERM)
 		r->arp_flags |= ATF_COM;
 	if (dev == NULL) {
-		struct flowi fl = { .fl4_dst = ip,
-				    .fl4_tos = RTO_ONLINK };
-		struct rtable *rt;
-		err = ip_route_output_key(net, &rt, &fl);
-		if (err != 0)
-			return err;
+		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
+
+		if (IS_ERR(rt))
+			return PTR_ERR(rt);
 		dev = rt->dst.dev;
 		ip_rt_put(rt);
 		if (!dev)
@@ -1177,7 +1174,6 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r,
 static int arp_req_delete(struct net *net, struct arpreq *r,
 			  struct net_device *dev)
 {
-	int err;
 	__be32 ip;
 
 	if (r->arp_flags & ATF_PUBL)
@@ -1185,12 +1181,9 @@ static int arp_req_delete(struct net *net, struct arpreq *r,
 
 	ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr;
 	if (dev == NULL) {
-		struct flowi fl = { .fl4_dst = ip,
-				    .fl4_tos = RTO_ONLINK };
-		struct rtable *rt;
-		err = ip_route_output_key(net, &rt, &fl);
-		if (err != 0)
-			return err;
+		struct rtable *rt = ip_route_output(net, ip, 0, RTO_ONLINK, 0);
+		if (IS_ERR(rt))
+			return PTR_ERR(rt);
 		dev = rt->dst.dev;
 		ip_rt_put(rt);
 		if (!dev)
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 174be6c..85bd24c 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -46,11 +46,12 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 		if (!saddr)
 			saddr = inet->mc_addr;
 	}
-	err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
-			       RT_CONN_FLAGS(sk), oif,
-			       sk->sk_protocol,
-			       inet->inet_sport, usin->sin_port, sk, 1);
-	if (err) {
+	rt = ip_route_connect(usin->sin_addr.s_addr, saddr,
+			      RT_CONN_FLAGS(sk), oif,
+			      sk->sk_protocol,
+			      inet->inet_sport, usin->sin_port, sk, true);
+	if (IS_ERR(rt)) {
+		err = PTR_ERR(rt);
 		if (err == -ENETUNREACH)
 			IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
 		return err;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 036652c..6d85800d 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -51,6 +51,7 @@
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
 #include <linux/slab.h>
+#include <linux/hash.h>
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -92,6 +93,71 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = {
 	[IFA_LABEL]     	= { .type = NLA_STRING, .len = IFNAMSIZ - 1 },
 };
 
+/* inet_addr_hash's shifting is dependent upon this IN4_ADDR_HSIZE
+ * value.  So if you change this define, make appropriate changes to
+ * inet_addr_hash as well.
+ */
+#define IN4_ADDR_HSIZE	256
+static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE];
+static DEFINE_SPINLOCK(inet_addr_hash_lock);
+
+static inline unsigned int inet_addr_hash(struct net *net, __be32 addr)
+{
+	u32 val = (__force u32) addr ^ hash_ptr(net, 8);
+
+	return ((val ^ (val >> 8) ^ (val >> 16) ^ (val >> 24)) &
+		(IN4_ADDR_HSIZE - 1));
+}
+
+static void inet_hash_insert(struct net *net, struct in_ifaddr *ifa)
+{
+	unsigned int hash = inet_addr_hash(net, ifa->ifa_local);
+
+	spin_lock(&inet_addr_hash_lock);
+	hlist_add_head_rcu(&ifa->hash, &inet_addr_lst[hash]);
+	spin_unlock(&inet_addr_hash_lock);
+}
+
+static void inet_hash_remove(struct in_ifaddr *ifa)
+{
+	spin_lock(&inet_addr_hash_lock);
+	hlist_del_init_rcu(&ifa->hash);
+	spin_unlock(&inet_addr_hash_lock);
+}
+
+/**
+ * __ip_dev_find - find the first device with a given source address.
+ * @net: the net namespace
+ * @addr: the source address
+ * @devref: if true, take a reference on the found device
+ *
+ * If a caller uses devref=false, it should be protected by RCU, or RTNL
+ */
+struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
+{
+	unsigned int hash = inet_addr_hash(net, addr);
+	struct net_device *result = NULL;
+	struct in_ifaddr *ifa;
+	struct hlist_node *node;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(ifa, node, &inet_addr_lst[hash], hash) {
+		struct net_device *dev = ifa->ifa_dev->dev;
+
+		if (!net_eq(dev_net(dev), net))
+			continue;
+		if (ifa->ifa_local == addr) {
+			result = dev;
+			break;
+		}
+	}
+	if (result && devref)
+		dev_hold(result);
+	rcu_read_unlock();
+	return result;
+}
+EXPORT_SYMBOL(__ip_dev_find);
+
 static void rtmsg_ifa(int event, struct in_ifaddr *, struct nlmsghdr *, u32);
 
 static BLOCKING_NOTIFIER_HEAD(inetaddr_chain);
@@ -265,6 +331,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
 			}
 
 			if (!do_promote) {
+				inet_hash_remove(ifa);
 				*ifap1 = ifa->ifa_next;
 
 				rtmsg_ifa(RTM_DELADDR, ifa, nlh, pid);
@@ -281,6 +348,7 @@ static void __inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
 	/* 2. Unlink it */
 
 	*ifap = ifa1->ifa_next;
+	inet_hash_remove(ifa1);
 
 	/* 3. Announce address deletion */
 
@@ -368,6 +436,8 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
 	ifa->ifa_next = *ifap;
 	*ifap = ifa;
 
+	inet_hash_insert(dev_net(in_dev->dev), ifa);
+
 	/* Send message first, then call notifier.
 	   Notifier will trigger FIB update, so that
 	   listeners of netlink will know about new ifaddr */
@@ -521,6 +591,7 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh)
 	if (tb[IFA_ADDRESS] == NULL)
 		tb[IFA_ADDRESS] = tb[IFA_LOCAL];
 
+	INIT_HLIST_NODE(&ifa->hash);
 	ifa->ifa_prefixlen = ifm->ifa_prefixlen;
 	ifa->ifa_mask = inet_make_mask(ifm->ifa_prefixlen);
 	ifa->ifa_flags = ifm->ifa_flags;
@@ -728,6 +799,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 		if (!ifa) {
 			ret = -ENOBUFS;
 			ifa = inet_alloc_ifa();
+			INIT_HLIST_NODE(&ifa->hash);
 			if (!ifa)
 				break;
 			if (colon)
@@ -1084,6 +1156,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
 			struct in_ifaddr *ifa = inet_alloc_ifa();
 
 			if (ifa) {
+				INIT_HLIST_NODE(&ifa->hash);
 				ifa->ifa_local =
 				  ifa->ifa_address = htonl(INADDR_LOOPBACK);
 				ifa->ifa_prefixlen = 8;
@@ -1720,6 +1793,11 @@ static struct rtnl_af_ops inet_af_ops = {
 
 void __init devinet_init(void)
 {
+	int i;
+
+	for (i = 0; i < IN4_ADDR_HSIZE; i++)
+		INIT_HLIST_HEAD(&inet_addr_lst[i]);
+
 	register_pernet_subsys(&devinet_ops);
 
 	register_gifconf(PF_INET, inet_gifconf);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index e42a905..03f994b 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -33,11 +33,14 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
  *
  * TODO: Use spare space in skb for this where possible.
  */
-static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen)
 {
 	unsigned int len;
 
-	len = crypto_aead_ivsize(aead);
+	len = seqhilen;
+
+	len += crypto_aead_ivsize(aead);
+
 	if (len) {
 		len += crypto_aead_alignmask(aead) &
 		       ~(crypto_tfm_ctx_alignment() - 1);
@@ -52,10 +55,15 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
 	return kmalloc(len, GFP_ATOMIC);
 }
 
-static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
+static inline __be32 *esp_tmp_seqhi(void *tmp)
+{
+	return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
+}
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
 {
 	return crypto_aead_ivsize(aead) ?
-	       PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
+	       PTR_ALIGN((u8 *)tmp + seqhilen,
+			 crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
 }
 
 static inline struct aead_givcrypt_request *esp_tmp_givreq(
@@ -122,6 +130,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 	int plen;
 	int tfclen;
 	int nfrags;
+	int assoclen;
+	int sglists;
+	int seqhilen;
+	__be32 *seqhi;
 
 	/* skb is pure payload to encrypt */
 
@@ -151,14 +163,25 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 		goto error;
 	nfrags = err;
 
-	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	assoclen = sizeof(*esph);
+	sglists = 1;
+	seqhilen = 0;
+
+	if (x->props.flags & XFRM_STATE_ESN) {
+		sglists += 2;
+		seqhilen += sizeof(__be32);
+		assoclen += seqhilen;
+	}
+
+	tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
 	if (!tmp)
 		goto error;
 
-	iv = esp_tmp_iv(aead, tmp);
+	seqhi = esp_tmp_seqhi(tmp);
+	iv = esp_tmp_iv(aead, tmp, seqhilen);
 	req = esp_tmp_givreq(aead, iv);
 	asg = esp_givreq_sg(aead, req);
-	sg = asg + 1;
+	sg = asg + sglists;
 
 	/* Fill padding... */
 	tail = skb_tail_pointer(trailer);
@@ -215,19 +238,27 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 	}
 
 	esph->spi = x->id.spi;
-	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
+	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg,
 		     esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
 		     clen + alen);
-	sg_init_one(asg, esph, sizeof(*esph));
+
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		sg_init_table(asg, 3);
+		sg_set_buf(asg, &esph->spi, sizeof(__be32));
+		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
+		sg_set_buf(asg + 1, seqhi, seqhilen);
+		sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32));
+	} else
+		sg_init_one(asg, esph, sizeof(*esph));
 
 	aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
 	aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
-	aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
+	aead_givcrypt_set_assoc(req, asg, assoclen);
 	aead_givcrypt_set_giv(req, esph->enc_data,
-			      XFRM_SKB_CB(skb)->seq.output);
+			      XFRM_SKB_CB(skb)->seq.output.low);
 
 	ESP_SKB_CB(skb)->tmp = tmp;
 	err = crypto_aead_givencrypt(req);
@@ -346,6 +377,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 	struct sk_buff *trailer;
 	int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
 	int nfrags;
+	int assoclen;
+	int sglists;
+	int seqhilen;
+	__be32 *seqhi;
 	void *tmp;
 	u8 *iv;
 	struct scatterlist *sg;
@@ -362,16 +397,27 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 		goto out;
 	nfrags = err;
 
+	assoclen = sizeof(*esph);
+	sglists = 1;
+	seqhilen = 0;
+
+	if (x->props.flags & XFRM_STATE_ESN) {
+		sglists += 2;
+		seqhilen += sizeof(__be32);
+		assoclen += seqhilen;
+	}
+
 	err = -ENOMEM;
-	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
 	if (!tmp)
 		goto out;
 
 	ESP_SKB_CB(skb)->tmp = tmp;
-	iv = esp_tmp_iv(aead, tmp);
+	seqhi = esp_tmp_seqhi(tmp);
+	iv = esp_tmp_iv(aead, tmp, seqhilen);
 	req = esp_tmp_req(aead, iv);
 	asg = esp_req_sg(aead, req);
-	sg = asg + 1;
+	sg = asg + sglists;
 
 	skb->ip_summed = CHECKSUM_NONE;
 
@@ -382,11 +428,19 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
-	sg_init_one(asg, esph, sizeof(*esph));
+
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		sg_init_table(asg, 3);
+		sg_set_buf(asg, &esph->spi, sizeof(__be32));
+		*seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
+		sg_set_buf(asg + 1, seqhi, seqhilen);
+		sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32));
+	} else
+		sg_init_one(asg, esph, sizeof(*esph));
 
 	aead_request_set_callback(req, 0, esp_input_done, skb);
 	aead_request_set_crypt(req, sg, sg, elen, iv);
-	aead_request_set_assoc(req, asg, sizeof(*esph));
+	aead_request_set_assoc(req, asg, assoclen);
 
 	err = crypto_aead_decrypt(req);
 	if (err == -EINPROGRESS)
@@ -500,10 +554,20 @@ static int esp_init_authenc(struct xfrm_state *x)
 		goto error;
 
 	err = -ENAMETOOLONG;
-	if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
-		     x->aalg ? x->aalg->alg_name : "digest_null",
-		     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
-		goto error;
+
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
+			     "authencesn(%s,%s)",
+			     x->aalg ? x->aalg->alg_name : "digest_null",
+			     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+			goto error;
+	} else {
+		if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
+			     "authenc(%s,%s)",
+			     x->aalg ? x->aalg->alg_name : "digest_null",
+			     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+			goto error;
+	}
 
 	aead = crypto_alloc_aead(authenc_name, 0, 0);
 	err = PTR_ERR(aead);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 1d2cdd4..a373a25 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -51,11 +51,11 @@ static int __net_init fib4_rules_init(struct net *net)
 {
 	struct fib_table *local_table, *main_table;
 
-	local_table = fib_hash_table(RT_TABLE_LOCAL);
+	local_table = fib_trie_table(RT_TABLE_LOCAL);
 	if (local_table == NULL)
 		return -ENOMEM;
 
-	main_table  = fib_hash_table(RT_TABLE_MAIN);
+	main_table  = fib_trie_table(RT_TABLE_MAIN);
 	if (main_table == NULL)
 		goto fail;
 
@@ -82,7 +82,7 @@ struct fib_table *fib_new_table(struct net *net, u32 id)
 	if (tb)
 		return tb;
 
-	tb = fib_hash_table(id);
+	tb = fib_trie_table(id);
 	if (!tb)
 		return NULL;
 	h = id & (FIB_TABLE_HASHSZ - 1);
@@ -114,21 +114,6 @@ struct fib_table *fib_get_table(struct net *net, u32 id)
 }
 #endif /* CONFIG_IP_MULTIPLE_TABLES */
 
-void fib_select_default(struct net *net,
-			const struct flowi *flp, struct fib_result *res)
-{
-	struct fib_table *tb;
-	int table = RT_TABLE_MAIN;
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-	if (res->r == NULL || res->r->action != FR_ACT_TO_TBL)
-		return;
-	table = res->r->table;
-#endif
-	tb = fib_get_table(net, table);
-	if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
-		fib_table_select_default(tb, flp, res);
-}
-
 static void fib_flush(struct net *net)
 {
 	int flushed = 0;
@@ -147,46 +132,6 @@ static void fib_flush(struct net *net)
 		rt_cache_flush(net, -1);
 }
 
-/**
- * __ip_dev_find - find the first device with a given source address.
- * @net: the net namespace
- * @addr: the source address
- * @devref: if true, take a reference on the found device
- *
- * If a caller uses devref=false, it should be protected by RCU, or RTNL
- */
-struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
-{
-	struct flowi fl = {
-		.fl4_dst = addr,
-	};
-	struct fib_result res = { 0 };
-	struct net_device *dev = NULL;
-	struct fib_table *local_table;
-
-#ifdef CONFIG_IP_MULTIPLE_TABLES
-	res.r = NULL;
-#endif
-
-	rcu_read_lock();
-	local_table = fib_get_table(net, RT_TABLE_LOCAL);
-	if (!local_table ||
-	    fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {
-		rcu_read_unlock();
-		return NULL;
-	}
-	if (res.type != RTN_LOCAL)
-		goto out;
-	dev = FIB_RES_DEV(res);
-
-	if (dev && devref)
-		dev_hold(dev);
-out:
-	rcu_read_unlock();
-	return dev;
-}
-EXPORT_SYMBOL(__ip_dev_find);
-
 /*
  * Find address type as if only "dev" was present in the system. If
  * on_dev is NULL then all interfaces are taken into consideration.
@@ -195,7 +140,7 @@ static inline unsigned __inet_dev_addr_type(struct net *net,
 					    const struct net_device *dev,
 					    __be32 addr)
 {
-	struct flowi		fl = { .fl4_dst = addr };
+	struct flowi4		fl4 = { .daddr = addr };
 	struct fib_result	res;
 	unsigned ret = RTN_BROADCAST;
 	struct fib_table *local_table;
@@ -213,7 +158,7 @@ static inline unsigned __inet_dev_addr_type(struct net *net,
 	if (local_table) {
 		ret = RTN_UNICAST;
 		rcu_read_lock();
-		if (!fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {
+		if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
 			if (!dev || dev == res.fi->fib_dev)
 				ret = res.type;
 		}
@@ -248,19 +193,21 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 			u32 *itag, u32 mark)
 {
 	struct in_device *in_dev;
-	struct flowi fl = {
-		.fl4_dst = src,
-		.fl4_src = dst,
-		.fl4_tos = tos,
-		.mark = mark,
-		.iif = oif
-	};
+	struct flowi4 fl4;
 	struct fib_result res;
 	int no_addr, rpf, accept_local;
 	bool dev_match;
 	int ret;
 	struct net *net;
 
+	fl4.flowi4_oif = 0;
+	fl4.flowi4_iif = oif;
+	fl4.flowi4_mark = mark;
+	fl4.daddr = src;
+	fl4.saddr = dst;
+	fl4.flowi4_tos = tos;
+	fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+
 	no_addr = rpf = accept_local = 0;
 	in_dev = __in_dev_get_rcu(dev);
 	if (in_dev) {
@@ -268,14 +215,14 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 		rpf = IN_DEV_RPFILTER(in_dev);
 		accept_local = IN_DEV_ACCEPT_LOCAL(in_dev);
 		if (mark && !IN_DEV_SRC_VMARK(in_dev))
-			fl.mark = 0;
+			fl4.flowi4_mark = 0;
 	}
 
 	if (in_dev == NULL)
 		goto e_inval;
 
 	net = dev_net(dev);
-	if (fib_lookup(net, &fl, &res))
+	if (fib_lookup(net, &fl4, &res))
 		goto last_resort;
 	if (res.type != RTN_UNICAST) {
 		if (res.type != RTN_LOCAL || !accept_local)
@@ -306,10 +253,10 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
 		goto last_resort;
 	if (rpf == 1)
 		goto e_rpf;
-	fl.oif = dev->ifindex;
+	fl4.flowi4_oif = dev->ifindex;
 
 	ret = 0;
-	if (fib_lookup(net, &fl, &res) == 0) {
+	if (fib_lookup(net, &fl4, &res) == 0) {
 		if (res.type == RTN_UNICAST) {
 			*spec_dst = FIB_RES_PREFSRC(res);
 			ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
@@ -849,11 +796,11 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 {
 
 	struct fib_result       res;
-	struct flowi            fl = {
-		.mark = frn->fl_mark,
-		.fl4_dst = frn->fl_addr,
-		.fl4_tos = frn->fl_tos,
-		.fl4_scope = frn->fl_scope,
+	struct flowi4           fl4 = {
+		.flowi4_mark = frn->fl_mark,
+		.daddr = frn->fl_addr,
+		.flowi4_tos = frn->fl_tos,
+		.flowi4_scope = frn->fl_scope,
 	};
 
 #ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -866,7 +813,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 
 		frn->tb_id = tb->tb_id;
 		rcu_read_lock();
-		frn->err = fib_table_lookup(tb, &fl, &res, FIB_LOOKUP_NOREF);
+		frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
 
 		if (!frn->err) {
 			frn->prefixlen = res.prefixlen;
@@ -945,10 +892,12 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 		fib_sync_up(dev);
 #endif
+		fib_update_nh_saddrs(dev);
 		rt_cache_flush(dev_net(dev), -1);
 		break;
 	case NETDEV_DOWN:
 		fib_del_ifaddr(ifa);
+		fib_update_nh_saddrs(dev);
 		if (ifa->ifa_dev->ifa_list == NULL) {
 			/* Last address was deleted from this interface.
 			 * Disable IP.
@@ -1101,5 +1050,5 @@ void __init ip_fib_init(void)
 	register_netdevice_notifier(&fib_netdev_notifier);
 	register_inetaddr_notifier(&fib_inetaddr_notifier);
 
-	fib_hash_init();
+	fib_trie_init();
 }
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
deleted file mode 100644
index b3acb04..0000000
--- a/net/ipv4/fib_hash.c
+++ /dev/null
@@ -1,1133 +0,0 @@
-/*
- * INET		An implementation of the TCP/IP protocol suite for the LINUX
- *		operating system.  INET is implemented using the  BSD Socket
- *		interface as the means of communication with the user level.
- *
- *		IPv4 FIB: lookup engine and maintenance routines.
- *
- * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the 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 <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/errno.h>
-#include <linux/in.h>
-#include <linux/inet.h>
-#include <linux/inetdevice.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/proc_fs.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <net/net_namespace.h>
-#include <net/ip.h>
-#include <net/protocol.h>
-#include <net/route.h>
-#include <net/tcp.h>
-#include <net/sock.h>
-#include <net/ip_fib.h>
-
-#include "fib_lookup.h"
-
-static struct kmem_cache *fn_hash_kmem __read_mostly;
-static struct kmem_cache *fn_alias_kmem __read_mostly;
-
-struct fib_node {
-	struct hlist_node	fn_hash;
-	struct list_head	fn_alias;
-	__be32			fn_key;
-	struct fib_alias        fn_embedded_alias;
-};
-
-#define EMBEDDED_HASH_SIZE (L1_CACHE_BYTES / sizeof(struct hlist_head))
-
-struct fn_zone {
-	struct fn_zone __rcu	*fz_next;	/* Next not empty zone	*/
-	struct hlist_head __rcu	*fz_hash;	/* Hash table pointer	*/
-	seqlock_t		fz_lock;
-	u32			fz_hashmask;	/* (fz_divisor - 1)	*/
-
-	u8			fz_order;	/* Zone order (0..32)	*/
-	u8			fz_revorder;	/* 32 - fz_order	*/
-	__be32			fz_mask;	/* inet_make_mask(order) */
-#define FZ_MASK(fz)		((fz)->fz_mask)
-
-	struct hlist_head	fz_embedded_hash[EMBEDDED_HASH_SIZE];
-
-	int			fz_nent;	/* Number of entries	*/
-	int			fz_divisor;	/* Hash size (mask+1)	*/
-};
-
-struct fn_hash {
-	struct fn_zone		*fn_zones[33];
-	struct fn_zone __rcu	*fn_zone_list;
-};
-
-static inline u32 fn_hash(__be32 key, struct fn_zone *fz)
-{
-	u32 h = ntohl(key) >> fz->fz_revorder;
-	h ^= (h>>20);
-	h ^= (h>>10);
-	h ^= (h>>5);
-	h &= fz->fz_hashmask;
-	return h;
-}
-
-static inline __be32 fz_key(__be32 dst, struct fn_zone *fz)
-{
-	return dst & FZ_MASK(fz);
-}
-
-static unsigned int fib_hash_genid;
-
-#define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
-
-static struct hlist_head *fz_hash_alloc(int divisor)
-{
-	unsigned long size = divisor * sizeof(struct hlist_head);
-
-	if (size <= PAGE_SIZE)
-		return kzalloc(size, GFP_KERNEL);
-
-	return (struct hlist_head *)
-		__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(size));
-}
-
-/* The fib hash lock must be held when this is called. */
-static inline void fn_rebuild_zone(struct fn_zone *fz,
-				   struct hlist_head *old_ht,
-				   int old_divisor)
-{
-	int i;
-
-	for (i = 0; i < old_divisor; i++) {
-		struct hlist_node *node, *n;
-		struct fib_node *f;
-
-		hlist_for_each_entry_safe(f, node, n, &old_ht[i], fn_hash) {
-			struct hlist_head *new_head;
-
-			hlist_del_rcu(&f->fn_hash);
-
-			new_head = rcu_dereference_protected(fz->fz_hash, 1) +
-				   fn_hash(f->fn_key, fz);
-			hlist_add_head_rcu(&f->fn_hash, new_head);
-		}
-	}
-}
-
-static void fz_hash_free(struct hlist_head *hash, int divisor)
-{
-	unsigned long size = divisor * sizeof(struct hlist_head);
-
-	if (size <= PAGE_SIZE)
-		kfree(hash);
-	else
-		free_pages((unsigned long)hash, get_order(size));
-}
-
-static void fn_rehash_zone(struct fn_zone *fz)
-{
-	struct hlist_head *ht, *old_ht;
-	int old_divisor, new_divisor;
-	u32 new_hashmask;
-
-	new_divisor = old_divisor = fz->fz_divisor;
-
-	switch (old_divisor) {
-	case EMBEDDED_HASH_SIZE:
-		new_divisor *= EMBEDDED_HASH_SIZE;
-		break;
-	case EMBEDDED_HASH_SIZE*EMBEDDED_HASH_SIZE:
-		new_divisor *= (EMBEDDED_HASH_SIZE/2);
-		break;
-	default:
-		if ((old_divisor << 1) > FZ_MAX_DIVISOR) {
-			printk(KERN_CRIT "route.c: bad divisor %d!\n", old_divisor);
-			return;
-		}
-		new_divisor = (old_divisor << 1);
-		break;
-	}
-
-	new_hashmask = (new_divisor - 1);
-
-#if RT_CACHE_DEBUG >= 2
-	printk(KERN_DEBUG "fn_rehash_zone: hash for zone %d grows from %d\n",
-	       fz->fz_order, old_divisor);
-#endif
-
-	ht = fz_hash_alloc(new_divisor);
-
-	if (ht)	{
-		struct fn_zone nfz;
-
-		memcpy(&nfz, fz, sizeof(nfz));
-
-		write_seqlock_bh(&fz->fz_lock);
-		old_ht = rcu_dereference_protected(fz->fz_hash, 1);
-		RCU_INIT_POINTER(nfz.fz_hash, ht);
-		nfz.fz_hashmask = new_hashmask;
-		nfz.fz_divisor = new_divisor;
-		fn_rebuild_zone(&nfz, old_ht, old_divisor);
-		fib_hash_genid++;
-		rcu_assign_pointer(fz->fz_hash, ht);
-		fz->fz_hashmask = new_hashmask;
-		fz->fz_divisor = new_divisor;
-		write_sequnlock_bh(&fz->fz_lock);
-
-		if (old_ht != fz->fz_embedded_hash) {
-			synchronize_rcu();
-			fz_hash_free(old_ht, old_divisor);
-		}
-	}
-}
-
-static void fn_free_node_rcu(struct rcu_head *head)
-{
-	struct fib_node *f = container_of(head, struct fib_node, fn_embedded_alias.rcu);
-
-	kmem_cache_free(fn_hash_kmem, f);
-}
-
-static inline void fn_free_node(struct fib_node *f)
-{
-	call_rcu(&f->fn_embedded_alias.rcu, fn_free_node_rcu);
-}
-
-static void fn_free_alias_rcu(struct rcu_head *head)
-{
-	struct fib_alias *fa = container_of(head, struct fib_alias, rcu);
-
-	kmem_cache_free(fn_alias_kmem, fa);
-}
-
-static inline void fn_free_alias(struct fib_alias *fa, struct fib_node *f)
-{
-	fib_release_info(fa->fa_info);
-	if (fa == &f->fn_embedded_alias)
-		fa->fa_info = NULL;
-	else
-		call_rcu(&fa->rcu, fn_free_alias_rcu);
-}
-
-static struct fn_zone *
-fn_new_zone(struct fn_hash *table, int z)
-{
-	int i;
-	struct fn_zone *fz = kzalloc(sizeof(struct fn_zone), GFP_KERNEL);
-	if (!fz)
-		return NULL;
-
-	seqlock_init(&fz->fz_lock);
-	fz->fz_divisor = z ? EMBEDDED_HASH_SIZE : 1;
-	fz->fz_hashmask = fz->fz_divisor - 1;
-	RCU_INIT_POINTER(fz->fz_hash, fz->fz_embedded_hash);
-	fz->fz_order = z;
-	fz->fz_revorder = 32 - z;
-	fz->fz_mask = inet_make_mask(z);
-
-	/* Find the first not empty zone with more specific mask */
-	for (i = z + 1; i <= 32; i++)
-		if (table->fn_zones[i])
-			break;
-	if (i > 32) {
-		/* No more specific masks, we are the first. */
-		rcu_assign_pointer(fz->fz_next,
-				   rtnl_dereference(table->fn_zone_list));
-		rcu_assign_pointer(table->fn_zone_list, fz);
-	} else {
-		rcu_assign_pointer(fz->fz_next,
-				   rtnl_dereference(table->fn_zones[i]->fz_next));
-		rcu_assign_pointer(table->fn_zones[i]->fz_next, fz);
-	}
-	table->fn_zones[z] = fz;
-	fib_hash_genid++;
-	return fz;
-}
-
-int fib_table_lookup(struct fib_table *tb,
-		     const struct flowi *flp, struct fib_result *res,
-		     int fib_flags)
-{
-	int err;
-	struct fn_zone *fz;
-	struct fn_hash *t = (struct fn_hash *)tb->tb_data;
-
-	rcu_read_lock();
-	for (fz = rcu_dereference(t->fn_zone_list);
-	     fz != NULL;
-	     fz = rcu_dereference(fz->fz_next)) {
-		struct hlist_head *head;
-		struct hlist_node *node;
-		struct fib_node *f;
-		__be32 k;
-		unsigned int seq;
-
-		do {
-			seq = read_seqbegin(&fz->fz_lock);
-			k = fz_key(flp->fl4_dst, fz);
-
-			head = rcu_dereference(fz->fz_hash) + fn_hash(k, fz);
-			hlist_for_each_entry_rcu(f, node, head, fn_hash) {
-				if (f->fn_key != k)
-					continue;
-
-				err = fib_semantic_match(&f->fn_alias,
-						 flp, res,
-						 fz->fz_order, fib_flags);
-				if (err <= 0)
-					goto out;
-			}
-		} while (read_seqretry(&fz->fz_lock, seq));
-	}
-	err = 1;
-out:
-	rcu_read_unlock();
-	return err;
-}
-
-void fib_table_select_default(struct fib_table *tb,
-			      const struct flowi *flp, struct fib_result *res)
-{
-	int order, last_idx;
-	struct hlist_node *node;
-	struct fib_node *f;
-	struct fib_info *fi = NULL;
-	struct fib_info *last_resort;
-	struct fn_hash *t = (struct fn_hash *)tb->tb_data;
-	struct fn_zone *fz = t->fn_zones[0];
-	struct hlist_head *head;
-
-	if (fz == NULL)
-		return;
-
-	last_idx = -1;
-	last_resort = NULL;
-	order = -1;
-
-	rcu_read_lock();
-	head = rcu_dereference(fz->fz_hash);
-	hlist_for_each_entry_rcu(f, node, head, fn_hash) {
-		struct fib_alias *fa;
-
-		list_for_each_entry_rcu(fa, &f->fn_alias, fa_list) {
-			struct fib_info *next_fi = fa->fa_info;
-
-			if (fa->fa_scope != res->scope ||
-			    fa->fa_type != RTN_UNICAST)
-				continue;
-
-			if (next_fi->fib_priority > res->fi->fib_priority)
-				break;
-			if (!next_fi->fib_nh[0].nh_gw ||
-			    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
-				continue;
-
-			fib_alias_accessed(fa);
-
-			if (fi == NULL) {
-				if (next_fi != res->fi)
-					break;
-			} else if (!fib_detect_death(fi, order, &last_resort,
-						&last_idx, tb->tb_default)) {
-				fib_result_assign(res, fi);
-				tb->tb_default = order;
-				goto out;
-			}
-			fi = next_fi;
-			order++;
-		}
-	}
-
-	if (order <= 0 || fi == NULL) {
-		tb->tb_default = -1;
-		goto out;
-	}
-
-	if (!fib_detect_death(fi, order, &last_resort, &last_idx,
-				tb->tb_default)) {
-		fib_result_assign(res, fi);
-		tb->tb_default = order;
-		goto out;
-	}
-
-	if (last_idx >= 0)
-		fib_result_assign(res, last_resort);
-	tb->tb_default = last_idx;
-out:
-	rcu_read_unlock();
-}
-
-/* Insert node F to FZ. */
-static inline void fib_insert_node(struct fn_zone *fz, struct fib_node *f)
-{
-	struct hlist_head *head = rtnl_dereference(fz->fz_hash) + fn_hash(f->fn_key, fz);
-
-	hlist_add_head_rcu(&f->fn_hash, head);
-}
-
-/* Return the node in FZ matching KEY. */
-static struct fib_node *fib_find_node(struct fn_zone *fz, __be32 key)
-{
-	struct hlist_head *head = rtnl_dereference(fz->fz_hash) + fn_hash(key, fz);
-	struct hlist_node *node;
-	struct fib_node *f;
-
-	hlist_for_each_entry_rcu(f, node, head, fn_hash) {
-		if (f->fn_key == key)
-			return f;
-	}
-
-	return NULL;
-}
-
-
-static struct fib_alias *fib_fast_alloc(struct fib_node *f)
-{
-	struct fib_alias *fa = &f->fn_embedded_alias;
-
-	if (fa->fa_info != NULL)
-		fa = kmem_cache_alloc(fn_alias_kmem, GFP_KERNEL);
-	return fa;
-}
-
-/* Caller must hold RTNL. */
-int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
-{
-	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
-	struct fib_node *new_f = NULL;
-	struct fib_node *f;
-	struct fib_alias *fa, *new_fa;
-	struct fn_zone *fz;
-	struct fib_info *fi;
-	u8 tos = cfg->fc_tos;
-	__be32 key;
-	int err;
-
-	if (cfg->fc_dst_len > 32)
-		return -EINVAL;
-
-	fz = table->fn_zones[cfg->fc_dst_len];
-	if (!fz && !(fz = fn_new_zone(table, cfg->fc_dst_len)))
-		return -ENOBUFS;
-
-	key = 0;
-	if (cfg->fc_dst) {
-		if (cfg->fc_dst & ~FZ_MASK(fz))
-			return -EINVAL;
-		key = fz_key(cfg->fc_dst, fz);
-	}
-
-	fi = fib_create_info(cfg);
-	if (IS_ERR(fi))
-		return PTR_ERR(fi);
-
-	if (fz->fz_nent > (fz->fz_divisor<<1) &&
-	    fz->fz_divisor < FZ_MAX_DIVISOR &&
-	    (cfg->fc_dst_len == 32 ||
-	     (1 << cfg->fc_dst_len) > fz->fz_divisor))
-		fn_rehash_zone(fz);
-
-	f = fib_find_node(fz, key);
-
-	if (!f)
-		fa = NULL;
-	else
-		fa = fib_find_alias(&f->fn_alias, tos, fi->fib_priority);
-
-	/* Now fa, if non-NULL, points to the first fib alias
-	 * with the same keys [prefix,tos,priority], if such key already
-	 * exists or to the node before which we will insert new one.
-	 *
-	 * If fa is NULL, we will need to allocate a new one and
-	 * insert to the head of f.
-	 *
-	 * If f is NULL, no fib node matched the destination key
-	 * and we need to allocate a new one of those as well.
-	 */
-
-	if (fa && fa->fa_tos == tos &&
-	    fa->fa_info->fib_priority == fi->fib_priority) {
-		struct fib_alias *fa_first, *fa_match;
-
-		err = -EEXIST;
-		if (cfg->fc_nlflags & NLM_F_EXCL)
-			goto out;
-
-		/* We have 2 goals:
-		 * 1. Find exact match for type, scope, fib_info to avoid
-		 * duplicate routes
-		 * 2. Find next 'fa' (or head), NLM_F_APPEND inserts before it
-		 */
-		fa_match = NULL;
-		fa_first = fa;
-		fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
-		list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
-			if (fa->fa_tos != tos)
-				break;
-			if (fa->fa_info->fib_priority != fi->fib_priority)
-				break;
-			if (fa->fa_type == cfg->fc_type &&
-			    fa->fa_scope == cfg->fc_scope &&
-			    fa->fa_info == fi) {
-				fa_match = fa;
-				break;
-			}
-		}
-
-		if (cfg->fc_nlflags & NLM_F_REPLACE) {
-			u8 state;
-
-			fa = fa_first;
-			if (fa_match) {
-				if (fa == fa_match)
-					err = 0;
-				goto out;
-			}
-			err = -ENOBUFS;
-			new_fa = fib_fast_alloc(f);
-			if (new_fa == NULL)
-				goto out;
-
-			new_fa->fa_tos = fa->fa_tos;
-			new_fa->fa_info = fi;
-			new_fa->fa_type = cfg->fc_type;
-			new_fa->fa_scope = cfg->fc_scope;
-			state = fa->fa_state;
-			new_fa->fa_state = state & ~FA_S_ACCESSED;
-			fib_hash_genid++;
-			list_replace_rcu(&fa->fa_list, &new_fa->fa_list);
-
-			fn_free_alias(fa, f);
-			if (state & FA_S_ACCESSED)
-				rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
-			rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len,
-				  tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
-			return 0;
-		}
-
-		/* Error if we find a perfect match which
-		 * uses the same scope, type, and nexthop
-		 * information.
-		 */
-		if (fa_match)
-			goto out;
-
-		if (!(cfg->fc_nlflags & NLM_F_APPEND))
-			fa = fa_first;
-	}
-
-	err = -ENOENT;
-	if (!(cfg->fc_nlflags & NLM_F_CREATE))
-		goto out;
-
-	err = -ENOBUFS;
-
-	if (!f) {
-		new_f = kmem_cache_zalloc(fn_hash_kmem, GFP_KERNEL);
-		if (new_f == NULL)
-			goto out;
-
-		INIT_HLIST_NODE(&new_f->fn_hash);
-		INIT_LIST_HEAD(&new_f->fn_alias);
-		new_f->fn_key = key;
-		f = new_f;
-	}
-
-	new_fa = fib_fast_alloc(f);
-	if (new_fa == NULL)
-		goto out;
-
-	new_fa->fa_info = fi;
-	new_fa->fa_tos = tos;
-	new_fa->fa_type = cfg->fc_type;
-	new_fa->fa_scope = cfg->fc_scope;
-	new_fa->fa_state = 0;
-
-	/*
-	 * Insert new entry to the list.
-	 */
-
-	if (new_f)
-		fib_insert_node(fz, new_f);
-	list_add_tail_rcu(&new_fa->fa_list,
-		 (fa ? &fa->fa_list : &f->fn_alias));
-	fib_hash_genid++;
-
-	if (new_f)
-		fz->fz_nent++;
-	rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
-
-	rtmsg_fib(RTM_NEWROUTE, key, new_fa, cfg->fc_dst_len, tb->tb_id,
-		  &cfg->fc_nlinfo, 0);
-	return 0;
-
-out:
-	if (new_f)
-		kmem_cache_free(fn_hash_kmem, new_f);
-	fib_release_info(fi);
-	return err;
-}
-
-int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
-{
-	struct fn_hash *table = (struct fn_hash *)tb->tb_data;
-	struct fib_node *f;
-	struct fib_alias *fa, *fa_to_delete;
-	struct fn_zone *fz;
-	__be32 key;
-
-	if (cfg->fc_dst_len > 32)
-		return -EINVAL;
-
-	if ((fz  = table->fn_zones[cfg->fc_dst_len]) == NULL)
-		return -ESRCH;
-
-	key = 0;
-	if (cfg->fc_dst) {
-		if (cfg->fc_dst & ~FZ_MASK(fz))
-			return -EINVAL;
-		key = fz_key(cfg->fc_dst, fz);
-	}
-
-	f = fib_find_node(fz, key);
-
-	if (!f)
-		fa = NULL;
-	else
-		fa = fib_find_alias(&f->fn_alias, cfg->fc_tos, 0);
-	if (!fa)
-		return -ESRCH;
-
-	fa_to_delete = NULL;
-	fa = list_entry(fa->fa_list.prev, struct fib_alias, fa_list);
-	list_for_each_entry_continue(fa, &f->fn_alias, fa_list) {
-		struct fib_info *fi = fa->fa_info;
-
-		if (fa->fa_tos != cfg->fc_tos)
-			break;
-
-		if ((!cfg->fc_type ||
-		     fa->fa_type == cfg->fc_type) &&
-		    (cfg->fc_scope == RT_SCOPE_NOWHERE ||
-		     fa->fa_scope == cfg->fc_scope) &&
-		    (!cfg->fc_protocol ||
-		     fi->fib_protocol == cfg->fc_protocol) &&
-		    fib_nh_match(cfg, fi) == 0) {
-			fa_to_delete = fa;
-			break;
-		}
-	}
-
-	if (fa_to_delete) {
-		int kill_fn;
-
-		fa = fa_to_delete;
-		rtmsg_fib(RTM_DELROUTE, key, fa, cfg->fc_dst_len,
-			  tb->tb_id, &cfg->fc_nlinfo, 0);
-
-		kill_fn = 0;
-		list_del_rcu(&fa->fa_list);
-		if (list_empty(&f->fn_alias)) {
-			hlist_del_rcu(&f->fn_hash);
-			kill_fn = 1;
-		}
-		fib_hash_genid++;
-
-		if (fa->fa_state & FA_S_ACCESSED)
-			rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
-		fn_free_alias(fa, f);
-		if (kill_fn) {
-			fn_free_node(f);
-			fz->fz_nent--;
-		}
-
-		return 0;
-	}
-	return -ESRCH;
-}
-
-static int fn_flush_list(struct fn_zone *fz, int idx)
-{
-	struct hlist_head *head = rtnl_dereference(fz->fz_hash) + idx;
-	struct hlist_node *node, *n;
-	struct fib_node *f;
-	int found = 0;
-
-	hlist_for_each_entry_safe(f, node, n, head, fn_hash) {
-		struct fib_alias *fa, *fa_node;
-		int kill_f;
-
-		kill_f = 0;
-		list_for_each_entry_safe(fa, fa_node, &f->fn_alias, fa_list) {
-			struct fib_info *fi = fa->fa_info;
-
-			if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
-				list_del_rcu(&fa->fa_list);
-				if (list_empty(&f->fn_alias)) {
-					hlist_del_rcu(&f->fn_hash);
-					kill_f = 1;
-				}
-				fib_hash_genid++;
-
-				fn_free_alias(fa, f);
-				found++;
-			}
-		}
-		if (kill_f) {
-			fn_free_node(f);
-			fz->fz_nent--;
-		}
-	}
-	return found;
-}
-
-/* caller must hold RTNL. */
-int fib_table_flush(struct fib_table *tb)
-{
-	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
-	struct fn_zone *fz;
-	int found = 0;
-
-	for (fz = rtnl_dereference(table->fn_zone_list);
-	     fz != NULL;
-	     fz = rtnl_dereference(fz->fz_next)) {
-		int i;
-
-		for (i = fz->fz_divisor - 1; i >= 0; i--)
-			found += fn_flush_list(fz, i);
-	}
-	return found;
-}
-
-void fib_free_table(struct fib_table *tb)
-{
-	struct fn_hash *table = (struct fn_hash *) tb->tb_data;
-	struct fn_zone *fz, *next;
-
-	next = table->fn_zone_list;
-	while (next != NULL) {
-		fz = next;
-		next = fz->fz_next;
-
-		if (fz->fz_hash != fz->fz_embedded_hash)
-			fz_hash_free(fz->fz_hash, fz->fz_divisor);
-
-		kfree(fz);
-	}
-
-	kfree(tb);
-}
-
-static inline int
-fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
-		     struct fib_table *tb,
-		     struct fn_zone *fz,
-		     struct hlist_head *head)
-{
-	struct hlist_node *node;
-	struct fib_node *f;
-	int i, s_i;
-
-	s_i = cb->args[4];
-	i = 0;
-	hlist_for_each_entry_rcu(f, node, head, fn_hash) {
-		struct fib_alias *fa;
-
-		list_for_each_entry_rcu(fa, &f->fn_alias, fa_list) {
-			if (i < s_i)
-				goto next;
-
-			if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
-					  cb->nlh->nlmsg_seq,
-					  RTM_NEWROUTE,
-					  tb->tb_id,
-					  fa->fa_type,
-					  fa->fa_scope,
-					  f->fn_key,
-					  fz->fz_order,
-					  fa->fa_tos,
-					  fa->fa_info,
-					  NLM_F_MULTI) < 0) {
-				cb->args[4] = i;
-				return -1;
-			}
-next:
-			i++;
-		}
-	}
-	cb->args[4] = i;
-	return skb->len;
-}
-
-static inline int
-fn_hash_dump_zone(struct sk_buff *skb, struct netlink_callback *cb,
-		   struct fib_table *tb,
-		   struct fn_zone *fz)
-{
-	int h, s_h;
-	struct hlist_head *head = rcu_dereference(fz->fz_hash);
-
-	if (head == NULL)
-		return skb->len;
-	s_h = cb->args[3];
-	for (h = s_h; h < fz->fz_divisor; h++) {
-		if (hlist_empty(head + h))
-			continue;
-		if (fn_hash_dump_bucket(skb, cb, tb, fz, head + h) < 0) {
-			cb->args[3] = h;
-			return -1;
-		}
-		memset(&cb->args[4], 0,
-		       sizeof(cb->args) - 4*sizeof(cb->args[0]));
-	}
-	cb->args[3] = h;
-	return skb->len;
-}
-
-int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
-		   struct netlink_callback *cb)
-{
-	int m = 0, s_m;
-	struct fn_zone *fz;
-	struct fn_hash *table = (struct fn_hash *)tb->tb_data;
-
-	s_m = cb->args[2];
-	rcu_read_lock();
-	for (fz = rcu_dereference(table->fn_zone_list);
-	     fz != NULL;
-	     fz = rcu_dereference(fz->fz_next), m++) {
-		if (m < s_m)
-			continue;
-		if (fn_hash_dump_zone(skb, cb, tb, fz) < 0) {
-			cb->args[2] = m;
-			rcu_read_unlock();
-			return -1;
-		}
-		memset(&cb->args[3], 0,
-		       sizeof(cb->args) - 3*sizeof(cb->args[0]));
-	}
-	rcu_read_unlock();
-	cb->args[2] = m;
-	return skb->len;
-}
-
-void __init fib_hash_init(void)
-{
-	fn_hash_kmem = kmem_cache_create("ip_fib_hash", sizeof(struct fib_node),
-					 0, SLAB_PANIC, NULL);
-
-	fn_alias_kmem = kmem_cache_create("ip_fib_alias", sizeof(struct fib_alias),
-					  0, SLAB_PANIC, NULL);
-
-}
-
-struct fib_table *fib_hash_table(u32 id)
-{
-	struct fib_table *tb;
-
-	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct fn_hash),
-		     GFP_KERNEL);
-	if (tb == NULL)
-		return NULL;
-
-	tb->tb_id = id;
-	tb->tb_default = -1;
-
-	memset(tb->tb_data, 0, sizeof(struct fn_hash));
-	return tb;
-}
-
-/* ------------------------------------------------------------------------ */
-#ifdef CONFIG_PROC_FS
-
-struct fib_iter_state {
-	struct seq_net_private p;
-	struct fn_zone	*zone;
-	int		bucket;
-	struct hlist_head *hash_head;
-	struct fib_node *fn;
-	struct fib_alias *fa;
-	loff_t pos;
-	unsigned int genid;
-	int valid;
-};
-
-static struct fib_alias *fib_get_first(struct seq_file *seq)
-{
-	struct fib_iter_state *iter = seq->private;
-	struct fib_table *main_table;
-	struct fn_hash *table;
-
-	main_table = fib_get_table(seq_file_net(seq), RT_TABLE_MAIN);
-	table = (struct fn_hash *)main_table->tb_data;
-
-	iter->bucket    = 0;
-	iter->hash_head = NULL;
-	iter->fn        = NULL;
-	iter->fa        = NULL;
-	iter->pos	= 0;
-	iter->genid	= fib_hash_genid;
-	iter->valid	= 1;
-
-	for (iter->zone = rcu_dereference(table->fn_zone_list);
-	     iter->zone != NULL;
-	     iter->zone = rcu_dereference(iter->zone->fz_next)) {
-		int maxslot;
-
-		if (!iter->zone->fz_nent)
-			continue;
-
-		iter->hash_head = rcu_dereference(iter->zone->fz_hash);
-		maxslot = iter->zone->fz_divisor;
-
-		for (iter->bucket = 0; iter->bucket < maxslot;
-		     ++iter->bucket, ++iter->hash_head) {
-			struct hlist_node *node;
-			struct fib_node *fn;
-
-			hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
-				struct fib_alias *fa;
-
-				list_for_each_entry(fa, &fn->fn_alias, fa_list) {
-					iter->fn = fn;
-					iter->fa = fa;
-					goto out;
-				}
-			}
-		}
-	}
-out:
-	return iter->fa;
-}
-
-static struct fib_alias *fib_get_next(struct seq_file *seq)
-{
-	struct fib_iter_state *iter = seq->private;
-	struct fib_node *fn;
-	struct fib_alias *fa;
-
-	/* Advance FA, if any. */
-	fn = iter->fn;
-	fa = iter->fa;
-	if (fa) {
-		BUG_ON(!fn);
-		list_for_each_entry_continue(fa, &fn->fn_alias, fa_list) {
-			iter->fa = fa;
-			goto out;
-		}
-	}
-
-	fa = iter->fa = NULL;
-
-	/* Advance FN. */
-	if (fn) {
-		struct hlist_node *node = &fn->fn_hash;
-		hlist_for_each_entry_continue(fn, node, fn_hash) {
-			iter->fn = fn;
-
-			list_for_each_entry(fa, &fn->fn_alias, fa_list) {
-				iter->fa = fa;
-				goto out;
-			}
-		}
-	}
-
-	fn = iter->fn = NULL;
-
-	/* Advance hash chain. */
-	if (!iter->zone)
-		goto out;
-
-	for (;;) {
-		struct hlist_node *node;
-		int maxslot;
-
-		maxslot = iter->zone->fz_divisor;
-
-		while (++iter->bucket < maxslot) {
-			iter->hash_head++;
-
-			hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
-				list_for_each_entry(fa, &fn->fn_alias, fa_list) {
-					iter->fn = fn;
-					iter->fa = fa;
-					goto out;
-				}
-			}
-		}
-
-		iter->zone = rcu_dereference(iter->zone->fz_next);
-
-		if (!iter->zone)
-			goto out;
-
-		iter->bucket = 0;
-		iter->hash_head = rcu_dereference(iter->zone->fz_hash);
-
-		hlist_for_each_entry(fn, node, iter->hash_head, fn_hash) {
-			list_for_each_entry(fa, &fn->fn_alias, fa_list) {
-				iter->fn = fn;
-				iter->fa = fa;
-				goto out;
-			}
-		}
-	}
-out:
-	iter->pos++;
-	return fa;
-}
-
-static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
-{
-	struct fib_iter_state *iter = seq->private;
-	struct fib_alias *fa;
-
-	if (iter->valid && pos >= iter->pos && iter->genid == fib_hash_genid) {
-		fa   = iter->fa;
-		pos -= iter->pos;
-	} else
-		fa = fib_get_first(seq);
-
-	if (fa)
-		while (pos && (fa = fib_get_next(seq)))
-			--pos;
-	return pos ? NULL : fa;
-}
-
-static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(RCU)
-{
-	void *v = NULL;
-
-	rcu_read_lock();
-	if (fib_get_table(seq_file_net(seq), RT_TABLE_MAIN))
-		v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-	return v;
-}
-
-static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	++*pos;
-	return v == SEQ_START_TOKEN ? fib_get_first(seq) : fib_get_next(seq);
-}
-
-static void fib_seq_stop(struct seq_file *seq, void *v)
-	__releases(RCU)
-{
-	rcu_read_unlock();
-}
-
-static unsigned fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
-{
-	static const unsigned type2flags[RTN_MAX + 1] = {
-		[7] = RTF_REJECT,
-		[8] = RTF_REJECT,
-	};
-	unsigned flags = type2flags[type];
-
-	if (fi && fi->fib_nh->nh_gw)
-		flags |= RTF_GATEWAY;
-	if (mask == htonl(0xFFFFFFFF))
-		flags |= RTF_HOST;
-	flags |= RTF_UP;
-	return flags;
-}
-
-/*
- *	This outputs /proc/net/route.
- *
- *	It always works in backward compatibility mode.
- *	The format of the file is not supposed to be changed.
- */
-static int fib_seq_show(struct seq_file *seq, void *v)
-{
-	struct fib_iter_state *iter;
-	int len;
-	__be32 prefix, mask;
-	unsigned flags;
-	struct fib_node *f;
-	struct fib_alias *fa;
-	struct fib_info *fi;
-
-	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
-			   "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU"
-			   "\tWindow\tIRTT");
-		goto out;
-	}
-
-	iter	= seq->private;
-	f	= iter->fn;
-	fa	= iter->fa;
-	fi	= fa->fa_info;
-	prefix	= f->fn_key;
-	mask	= FZ_MASK(iter->zone);
-	flags	= fib_flag_trans(fa->fa_type, mask, fi);
-	if (fi)
-		seq_printf(seq,
-			 "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
-			 fi->fib_dev ? fi->fib_dev->name : "*", prefix,
-			 fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
-			 mask, (fi->fib_advmss ? fi->fib_advmss + 40 : 0),
-			 fi->fib_window,
-			 fi->fib_rtt >> 3, &len);
-	else
-		seq_printf(seq,
-			 "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u%n",
-			 prefix, 0, flags, 0, 0, 0, mask, 0, 0, 0, &len);
-
-	seq_printf(seq, "%*s\n", 127 - len, "");
-out:
-	return 0;
-}
-
-static const struct seq_operations fib_seq_ops = {
-	.start  = fib_seq_start,
-	.next   = fib_seq_next,
-	.stop   = fib_seq_stop,
-	.show   = fib_seq_show,
-};
-
-static int fib_seq_open(struct inode *inode, struct file *file)
-{
-	return seq_open_net(inode, file, &fib_seq_ops,
-			    sizeof(struct fib_iter_state));
-}
-
-static const struct file_operations fib_seq_fops = {
-	.owner		= THIS_MODULE,
-	.open           = fib_seq_open,
-	.read           = seq_read,
-	.llseek         = seq_lseek,
-	.release	= seq_release_net,
-};
-
-int __net_init fib_proc_init(struct net *net)
-{
-	if (!proc_net_fops_create(net, "route", S_IRUGO, &fib_seq_fops))
-		return -ENOMEM;
-	return 0;
-}
-
-void __net_exit fib_proc_exit(struct net *net)
-{
-	proc_net_remove(net, "route");
-}
-#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index c079cc0..4ec3238 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -25,9 +25,6 @@ static inline void fib_alias_accessed(struct fib_alias *fa)
 }
 
 /* Exported by fib_semantics.c */
-extern int fib_semantic_match(struct list_head *head,
-			      const struct flowi *flp,
-			      struct fib_result *res, int prefixlen, int fib_flags);
 extern void fib_release_info(struct fib_info *);
 extern struct fib_info *fib_create_info(struct fib_config *cfg);
 extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
@@ -51,4 +48,11 @@ static inline void fib_result_assign(struct fib_result *res,
 	res->fi = fi;
 }
 
+struct fib_prop {
+	int	error;
+	u8	scope;
+};
+
+extern const struct fib_prop fib_props[RTN_MAX + 1];
+
 #endif /* _FIB_LOOKUP_H */
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 7981a24..a53bb1b 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -41,19 +41,19 @@ struct fib4_rule {
 	__be32			srcmask;
 	__be32			dst;
 	__be32			dstmask;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	u32			tclassid;
 #endif
 };
 
-#ifdef CONFIG_NET_CLS_ROUTE
-u32 fib_rules_tclass(struct fib_result *res)
+#ifdef CONFIG_IP_ROUTE_CLASSID
+u32 fib_rules_tclass(const struct fib_result *res)
 {
 	return res->r ? ((struct fib4_rule *) res->r)->tclassid : 0;
 }
 #endif
 
-int fib_lookup(struct net *net, struct flowi *flp, struct fib_result *res)
+int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res)
 {
 	struct fib_lookup_arg arg = {
 		.result = res,
@@ -61,7 +61,7 @@ int fib_lookup(struct net *net, struct flowi *flp, struct fib_result *res)
 	};
 	int err;
 
-	err = fib_rules_lookup(net->ipv4.rules_ops, flp, 0, &arg);
+	err = fib_rules_lookup(net->ipv4.rules_ops, flowi4_to_flowi(flp), 0, &arg);
 	res->r = arg.rule;
 
 	return err;
@@ -95,7 +95,7 @@ static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
 	if (!tbl)
 		goto errout;
 
-	err = fib_table_lookup(tbl, flp, (struct fib_result *) arg->result, arg->flags);
+	err = fib_table_lookup(tbl, &flp->u.ip4, (struct fib_result *) arg->result, arg->flags);
 	if (err > 0)
 		err = -EAGAIN;
 errout:
@@ -106,14 +106,15 @@ errout:
 static int fib4_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
 	struct fib4_rule *r = (struct fib4_rule *) rule;
-	__be32 daddr = fl->fl4_dst;
-	__be32 saddr = fl->fl4_src;
+	struct flowi4 *fl4 = &fl->u.ip4;
+	__be32 daddr = fl4->daddr;
+	__be32 saddr = fl4->saddr;
 
 	if (((saddr ^ r->src) & r->srcmask) ||
 	    ((daddr ^ r->dst) & r->dstmask))
 		return 0;
 
-	if (r->tos && (r->tos != fl->fl4_tos))
+	if (r->tos && (r->tos != fl4->flowi4_tos))
 		return 0;
 
 	return 1;
@@ -165,7 +166,7 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
 	if (frh->dst_len)
 		rule4->dst = nla_get_be32(tb[FRA_DST]);
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	if (tb[FRA_FLOW])
 		rule4->tclassid = nla_get_u32(tb[FRA_FLOW]);
 #endif
@@ -195,7 +196,7 @@ static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
 	if (frh->tos && (rule4->tos != frh->tos))
 		return 0;
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	if (tb[FRA_FLOW] && (rule4->tclassid != nla_get_u32(tb[FRA_FLOW])))
 		return 0;
 #endif
@@ -224,7 +225,7 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
 	if (rule4->src_len)
 		NLA_PUT_BE32(skb, FRA_SRC, rule4->src);
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	if (rule4->tclassid)
 		NLA_PUT_U32(skb, FRA_FLOW, rule4->tclassid);
 #endif
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 12d3dc3..622ac4c 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -49,7 +49,7 @@
 static DEFINE_SPINLOCK(fib_info_lock);
 static struct hlist_head *fib_info_hash;
 static struct hlist_head *fib_info_laddrhash;
-static unsigned int fib_hash_size;
+static unsigned int fib_info_hash_size;
 static unsigned int fib_info_cnt;
 
 #define DEVINDEX_HASHBITS 8
@@ -90,11 +90,7 @@ static DEFINE_SPINLOCK(fib_multipath_lock);
 #define endfor_nexthops(fi) }
 
 
-static const struct
-{
-	int	error;
-	u8	scope;
-} fib_props[RTN_MAX + 1] = {
+const struct fib_prop fib_props[RTN_MAX + 1] = {
 	[RTN_UNSPEC] = {
 		.error	= 0,
 		.scope	= RT_SCOPE_NOWHERE,
@@ -152,6 +148,8 @@ static void free_fib_info_rcu(struct rcu_head *head)
 {
 	struct fib_info *fi = container_of(head, struct fib_info, rcu);
 
+	if (fi->fib_metrics != (u32 *) dst_default_metrics)
+		kfree(fi->fib_metrics);
 	kfree(fi);
 }
 
@@ -200,7 +198,7 @@ static inline int nh_comp(const struct fib_info *fi, const struct fib_info *ofi)
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 		    nh->nh_weight != onh->nh_weight ||
 #endif
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 		    nh->nh_tclassid != onh->nh_tclassid ||
 #endif
 		    ((nh->nh_flags ^ onh->nh_flags) & ~RTNH_F_DEAD))
@@ -221,7 +219,7 @@ static inline unsigned int fib_devindex_hashfn(unsigned int val)
 
 static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
 {
-	unsigned int mask = (fib_hash_size - 1);
+	unsigned int mask = (fib_info_hash_size - 1);
 	unsigned int val = fi->fib_nhs;
 
 	val ^= fi->fib_protocol;
@@ -422,7 +420,7 @@ static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
 
 			nla = nla_find(attrs, attrlen, RTA_GATEWAY);
 			nexthop_nh->nh_gw = nla ? nla_get_be32(nla) : 0;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 			nla = nla_find(attrs, attrlen, RTA_FLOW);
 			nexthop_nh->nh_tclassid = nla ? nla_get_u32(nla) : 0;
 #endif
@@ -476,7 +474,7 @@ int fib_nh_match(struct fib_config *cfg, struct fib_info *fi)
 			nla = nla_find(attrs, attrlen, RTA_GATEWAY);
 			if (nla && nla_get_be32(nla) != nh->nh_gw)
 				return 1;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 			nla = nla_find(attrs, attrlen, RTA_FLOW);
 			if (nla && nla_get_u32(nla) != nh->nh_tclassid)
 				return 1;
@@ -562,16 +560,16 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 		}
 		rcu_read_lock();
 		{
-			struct flowi fl = {
-				.fl4_dst = nh->nh_gw,
-				.fl4_scope = cfg->fc_scope + 1,
-				.oif = nh->nh_oif,
+			struct flowi4 fl4 = {
+				.daddr = nh->nh_gw,
+				.flowi4_scope = cfg->fc_scope + 1,
+				.flowi4_oif = nh->nh_oif,
 			};
 
 			/* It is not necessary, but requires a bit of thinking */
-			if (fl.fl4_scope < RT_SCOPE_LINK)
-				fl.fl4_scope = RT_SCOPE_LINK;
-			err = fib_lookup(net, &fl, &res);
+			if (fl4.flowi4_scope < RT_SCOPE_LINK)
+				fl4.flowi4_scope = RT_SCOPE_LINK;
+			err = fib_lookup(net, &fl4, &res);
 			if (err) {
 				rcu_read_unlock();
 				return err;
@@ -613,14 +611,14 @@ out:
 
 static inline unsigned int fib_laddr_hashfn(__be32 val)
 {
-	unsigned int mask = (fib_hash_size - 1);
+	unsigned int mask = (fib_info_hash_size - 1);
 
 	return ((__force u32)val ^
 		((__force u32)val >> 7) ^
 		((__force u32)val >> 14)) & mask;
 }
 
-static struct hlist_head *fib_hash_alloc(int bytes)
+static struct hlist_head *fib_info_hash_alloc(int bytes)
 {
 	if (bytes <= PAGE_SIZE)
 		return kzalloc(bytes, GFP_KERNEL);
@@ -630,7 +628,7 @@ static struct hlist_head *fib_hash_alloc(int bytes)
 					 get_order(bytes));
 }
 
-static void fib_hash_free(struct hlist_head *hash, int bytes)
+static void fib_info_hash_free(struct hlist_head *hash, int bytes)
 {
 	if (!hash)
 		return;
@@ -641,18 +639,18 @@ static void fib_hash_free(struct hlist_head *hash, int bytes)
 		free_pages((unsigned long) hash, get_order(bytes));
 }
 
-static void fib_hash_move(struct hlist_head *new_info_hash,
-			  struct hlist_head *new_laddrhash,
-			  unsigned int new_size)
+static void fib_info_hash_move(struct hlist_head *new_info_hash,
+			       struct hlist_head *new_laddrhash,
+			       unsigned int new_size)
 {
 	struct hlist_head *old_info_hash, *old_laddrhash;
-	unsigned int old_size = fib_hash_size;
+	unsigned int old_size = fib_info_hash_size;
 	unsigned int i, bytes;
 
 	spin_lock_bh(&fib_info_lock);
 	old_info_hash = fib_info_hash;
 	old_laddrhash = fib_info_laddrhash;
-	fib_hash_size = new_size;
+	fib_info_hash_size = new_size;
 
 	for (i = 0; i < old_size; i++) {
 		struct hlist_head *head = &fib_info_hash[i];
@@ -693,8 +691,8 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
 	spin_unlock_bh(&fib_info_lock);
 
 	bytes = old_size * sizeof(struct hlist_head *);
-	fib_hash_free(old_info_hash, bytes);
-	fib_hash_free(old_laddrhash, bytes);
+	fib_info_hash_free(old_info_hash, bytes);
+	fib_info_hash_free(old_laddrhash, bytes);
 }
 
 struct fib_info *fib_create_info(struct fib_config *cfg)
@@ -705,6 +703,9 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 	int nhs = 1;
 	struct net *net = cfg->fc_nlinfo.nl_net;
 
+	if (cfg->fc_type > RTN_MAX)
+		goto err_inval;
+
 	/* Fast check to catch the most weird cases */
 	if (fib_props[cfg->fc_type].scope > cfg->fc_scope)
 		goto err_inval;
@@ -718,8 +719,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 #endif
 
 	err = -ENOBUFS;
-	if (fib_info_cnt >= fib_hash_size) {
-		unsigned int new_size = fib_hash_size << 1;
+	if (fib_info_cnt >= fib_info_hash_size) {
+		unsigned int new_size = fib_info_hash_size << 1;
 		struct hlist_head *new_info_hash;
 		struct hlist_head *new_laddrhash;
 		unsigned int bytes;
@@ -727,21 +728,27 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 		if (!new_size)
 			new_size = 1;
 		bytes = new_size * sizeof(struct hlist_head *);
-		new_info_hash = fib_hash_alloc(bytes);
-		new_laddrhash = fib_hash_alloc(bytes);
+		new_info_hash = fib_info_hash_alloc(bytes);
+		new_laddrhash = fib_info_hash_alloc(bytes);
 		if (!new_info_hash || !new_laddrhash) {
-			fib_hash_free(new_info_hash, bytes);
-			fib_hash_free(new_laddrhash, bytes);
+			fib_info_hash_free(new_info_hash, bytes);
+			fib_info_hash_free(new_laddrhash, bytes);
 		} else
-			fib_hash_move(new_info_hash, new_laddrhash, new_size);
+			fib_info_hash_move(new_info_hash, new_laddrhash, new_size);
 
-		if (!fib_hash_size)
+		if (!fib_info_hash_size)
 			goto failure;
 	}
 
 	fi = kzalloc(sizeof(*fi)+nhs*sizeof(struct fib_nh), GFP_KERNEL);
 	if (fi == NULL)
 		goto failure;
+	if (cfg->fc_mx) {
+		fi->fib_metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
+		if (!fi->fib_metrics)
+			goto failure;
+	} else
+		fi->fib_metrics = (u32 *) dst_default_metrics;
 	fib_info_cnt++;
 
 	fi->fib_net = hold_net(net);
@@ -779,7 +786,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 			goto err_inval;
 		if (cfg->fc_gw && fi->fib_nh->nh_gw != cfg->fc_gw)
 			goto err_inval;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 		if (cfg->fc_flow && fi->fib_nh->nh_tclassid != cfg->fc_flow)
 			goto err_inval;
 #endif
@@ -792,7 +799,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 		nh->nh_oif = cfg->fc_oif;
 		nh->nh_gw = cfg->fc_gw;
 		nh->nh_flags = cfg->fc_flags;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 		nh->nh_tclassid = cfg->fc_flow;
 #endif
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
@@ -804,6 +811,17 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 		if (cfg->fc_gw || cfg->fc_oif || cfg->fc_mp)
 			goto err_inval;
 		goto link_it;
+	} else {
+		switch (cfg->fc_type) {
+		case RTN_UNICAST:
+		case RTN_LOCAL:
+		case RTN_BROADCAST:
+		case RTN_ANYCAST:
+		case RTN_MULTICAST:
+			break;
+		default:
+			goto err_inval;
+		}
 	}
 
 	if (cfg->fc_scope > RT_SCOPE_HOST)
@@ -835,6 +853,13 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 				goto err_inval;
 	}
 
+	change_nexthops(fi) {
+		nexthop_nh->nh_cfg_scope = cfg->fc_scope;
+		nexthop_nh->nh_saddr = inet_select_addr(nexthop_nh->nh_dev,
+							nexthop_nh->nh_gw,
+							nexthop_nh->nh_cfg_scope);
+	} endfor_nexthops(fi)
+
 link_it:
 	ofi = fib_find_info(fi);
 	if (ofi) {
@@ -880,84 +905,6 @@ failure:
 	return ERR_PTR(err);
 }
 
-/* Note! fib_semantic_match intentionally uses  RCU list functions. */
-int fib_semantic_match(struct list_head *head, const struct flowi *flp,
-		       struct fib_result *res, int prefixlen, int fib_flags)
-{
-	struct fib_alias *fa;
-	int nh_sel = 0;
-
-	list_for_each_entry_rcu(fa, head, fa_list) {
-		int err;
-
-		if (fa->fa_tos &&
-		    fa->fa_tos != flp->fl4_tos)
-			continue;
-
-		if (fa->fa_scope < flp->fl4_scope)
-			continue;
-
-		fib_alias_accessed(fa);
-
-		err = fib_props[fa->fa_type].error;
-		if (err == 0) {
-			struct fib_info *fi = fa->fa_info;
-
-			if (fi->fib_flags & RTNH_F_DEAD)
-				continue;
-
-			switch (fa->fa_type) {
-			case RTN_UNICAST:
-			case RTN_LOCAL:
-			case RTN_BROADCAST:
-			case RTN_ANYCAST:
-			case RTN_MULTICAST:
-				for_nexthops(fi) {
-					if (nh->nh_flags & RTNH_F_DEAD)
-						continue;
-					if (!flp->oif || flp->oif == nh->nh_oif)
-						break;
-				}
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-				if (nhsel < fi->fib_nhs) {
-					nh_sel = nhsel;
-					goto out_fill_res;
-				}
-#else
-				if (nhsel < 1)
-					goto out_fill_res;
-#endif
-				endfor_nexthops(fi);
-				continue;
-
-			default:
-				pr_warning("fib_semantic_match bad type %#x\n",
-					   fa->fa_type);
-				return -EINVAL;
-			}
-		}
-		return err;
-	}
-	return 1;
-
-out_fill_res:
-	res->prefixlen = prefixlen;
-	res->nh_sel = nh_sel;
-	res->type = fa->fa_type;
-	res->scope = fa->fa_scope;
-	res->fi = fa->fa_info;
-	if (!(fib_flags & FIB_LOOKUP_NOREF))
-		atomic_inc(&res->fi->fib_clntref);
-	return 0;
-}
-
-/* Find appropriate source address to this destination */
-
-__be32 __fib_res_prefsrc(struct fib_result *res)
-{
-	return inet_select_addr(FIB_RES_DEV(*res), FIB_RES_GW(*res), res->scope);
-}
-
 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 		  u32 tb_id, u8 type, u8 scope, __be32 dst, int dst_len, u8 tos,
 		  struct fib_info *fi, unsigned int flags)
@@ -1002,7 +949,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 
 		if (fi->fib_nh->nh_oif)
 			NLA_PUT_U32(skb, RTA_OIF, fi->fib_nh->nh_oif);
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 		if (fi->fib_nh[0].nh_tclassid)
 			NLA_PUT_U32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid);
 #endif
@@ -1027,7 +974,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 
 			if (nh->nh_gw)
 				NLA_PUT_BE32(skb, RTA_GATEWAY, nh->nh_gw);
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 			if (nh->nh_tclassid)
 				NLA_PUT_U32(skb, RTA_FLOW, nh->nh_tclassid);
 #endif
@@ -1125,6 +1072,80 @@ int fib_sync_down_dev(struct net_device *dev, int force)
 	return ret;
 }
 
+/* Must be invoked inside of an RCU protected region.  */
+void fib_select_default(struct fib_result *res)
+{
+	struct fib_info *fi = NULL, *last_resort = NULL;
+	struct list_head *fa_head = res->fa_head;
+	struct fib_table *tb = res->table;
+	int order = -1, last_idx = -1;
+	struct fib_alias *fa;
+
+	list_for_each_entry_rcu(fa, fa_head, fa_list) {
+		struct fib_info *next_fi = fa->fa_info;
+
+		if (fa->fa_scope != res->scope ||
+		    fa->fa_type != RTN_UNICAST)
+			continue;
+
+		if (next_fi->fib_priority > res->fi->fib_priority)
+			break;
+		if (!next_fi->fib_nh[0].nh_gw ||
+		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+			continue;
+
+		fib_alias_accessed(fa);
+
+		if (fi == NULL) {
+			if (next_fi != res->fi)
+				break;
+		} else if (!fib_detect_death(fi, order, &last_resort,
+					     &last_idx, tb->tb_default)) {
+			fib_result_assign(res, fi);
+			tb->tb_default = order;
+			goto out;
+		}
+		fi = next_fi;
+		order++;
+	}
+
+	if (order <= 0 || fi == NULL) {
+		tb->tb_default = -1;
+		goto out;
+	}
+
+	if (!fib_detect_death(fi, order, &last_resort, &last_idx,
+				tb->tb_default)) {
+		fib_result_assign(res, fi);
+		tb->tb_default = order;
+		goto out;
+	}
+
+	if (last_idx >= 0)
+		fib_result_assign(res, last_resort);
+	tb->tb_default = last_idx;
+out:
+	return;
+}
+
+void fib_update_nh_saddrs(struct net_device *dev)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct fib_nh *nh;
+	unsigned int hash;
+
+	hash = fib_devindex_hashfn(dev->ifindex);
+	head = &fib_info_devhash[hash];
+	hlist_for_each_entry(nh, node, head, nh_hash) {
+		if (nh->nh_dev != dev)
+			continue;
+		nh->nh_saddr = inet_select_addr(nh->nh_dev,
+						nh->nh_gw,
+						nh->nh_cfg_scope);
+	}
+}
+
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
 /*
@@ -1189,7 +1210,7 @@ int fib_sync_up(struct net_device *dev)
  * The algorithm is suboptimal, but it provides really
  * fair weighted route distribution.
  */
-void fib_select_multipath(const struct flowi *flp, struct fib_result *res)
+void fib_select_multipath(struct fib_result *res)
 {
 	struct fib_info *fi = res->fi;
 	int w;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 0f28034..3d28a35 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -95,7 +95,7 @@ typedef unsigned int t_key;
 #define IS_TNODE(n) (!(n->parent & T_LEAF))
 #define IS_LEAF(n) (n->parent & T_LEAF)
 
-struct node {
+struct rt_trie_node {
 	unsigned long parent;
 	t_key key;
 };
@@ -126,7 +126,7 @@ struct tnode {
 		struct work_struct work;
 		struct tnode *tnode_free;
 	};
-	struct node *child[0];
+	struct rt_trie_node *child[0];
 };
 
 #ifdef CONFIG_IP_FIB_TRIE_STATS
@@ -151,16 +151,16 @@ struct trie_stat {
 };
 
 struct trie {
-	struct node *trie;
+	struct rt_trie_node *trie;
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 	struct trie_use_stats stats;
 #endif
 };
 
-static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
-static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
+static void put_child(struct trie *t, struct tnode *tn, int i, struct rt_trie_node *n);
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
 				  int wasfull);
-static struct node *resize(struct trie *t, struct tnode *tn);
+static struct rt_trie_node *resize(struct trie *t, struct tnode *tn);
 static struct tnode *inflate(struct trie *t, struct tnode *tn);
 static struct tnode *halve(struct trie *t, struct tnode *tn);
 /* tnodes to free after resize(); protected by RTNL */
@@ -177,12 +177,12 @@ static const int sync_pages = 128;
 static struct kmem_cache *fn_alias_kmem __read_mostly;
 static struct kmem_cache *trie_leaf_kmem __read_mostly;
 
-static inline struct tnode *node_parent(struct node *node)
+static inline struct tnode *node_parent(struct rt_trie_node *node)
 {
 	return (struct tnode *)(node->parent & ~NODE_TYPE_MASK);
 }
 
-static inline struct tnode *node_parent_rcu(struct node *node)
+static inline struct tnode *node_parent_rcu(struct rt_trie_node *node)
 {
 	struct tnode *ret = node_parent(node);
 
@@ -192,22 +192,22 @@ static inline struct tnode *node_parent_rcu(struct node *node)
 /* Same as rcu_assign_pointer
  * but that macro() assumes that value is a pointer.
  */
-static inline void node_set_parent(struct node *node, struct tnode *ptr)
+static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr)
 {
 	smp_wmb();
 	node->parent = (unsigned long)ptr | NODE_TYPE(node);
 }
 
-static inline struct node *tnode_get_child(struct tnode *tn, unsigned int i)
+static inline struct rt_trie_node *tnode_get_child(struct tnode *tn, unsigned int i)
 {
 	BUG_ON(i >= 1U << tn->bits);
 
 	return tn->child[i];
 }
 
-static inline struct node *tnode_get_child_rcu(struct tnode *tn, unsigned int i)
+static inline struct rt_trie_node *tnode_get_child_rcu(struct tnode *tn, unsigned int i)
 {
-	struct node *ret = tnode_get_child(tn, i);
+	struct rt_trie_node *ret = tnode_get_child(tn, i);
 
 	return rcu_dereference_rtnl(ret);
 }
@@ -217,12 +217,12 @@ static inline int tnode_child_length(const struct tnode *tn)
 	return 1 << tn->bits;
 }
 
-static inline t_key mask_pfx(t_key k, unsigned short l)
+static inline t_key mask_pfx(t_key k, unsigned int l)
 {
 	return (l == 0) ? 0 : k >> (KEYLENGTH-l) << (KEYLENGTH-l);
 }
 
-static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
+static inline t_key tkey_extract_bits(t_key a, unsigned int offset, unsigned int bits)
 {
 	if (offset < KEYLENGTH)
 		return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
@@ -378,7 +378,7 @@ static void __tnode_free_rcu(struct rcu_head *head)
 {
 	struct tnode *tn = container_of(head, struct tnode, rcu);
 	size_t size = sizeof(struct tnode) +
-		      (sizeof(struct node *) << tn->bits);
+		      (sizeof(struct rt_trie_node *) << tn->bits);
 
 	if (size <= PAGE_SIZE)
 		kfree(tn);
@@ -402,7 +402,7 @@ static void tnode_free_safe(struct tnode *tn)
 	tn->tnode_free = tnode_free_head;
 	tnode_free_head = tn;
 	tnode_free_size += sizeof(struct tnode) +
-			   (sizeof(struct node *) << tn->bits);
+			   (sizeof(struct rt_trie_node *) << tn->bits);
 }
 
 static void tnode_free_flush(void)
@@ -443,7 +443,7 @@ static struct leaf_info *leaf_info_new(int plen)
 
 static struct tnode *tnode_new(t_key key, int pos, int bits)
 {
-	size_t sz = sizeof(struct tnode) + (sizeof(struct node *) << bits);
+	size_t sz = sizeof(struct tnode) + (sizeof(struct rt_trie_node *) << bits);
 	struct tnode *tn = tnode_alloc(sz);
 
 	if (tn) {
@@ -456,7 +456,7 @@ static struct tnode *tnode_new(t_key key, int pos, int bits)
 	}
 
 	pr_debug("AT %p s=%zu %zu\n", tn, sizeof(struct tnode),
-		 sizeof(struct node) << bits);
+		 sizeof(struct rt_trie_node) << bits);
 	return tn;
 }
 
@@ -465,7 +465,7 @@ static struct tnode *tnode_new(t_key key, int pos, int bits)
  * and no bits are skipped. See discussion in dyntree paper p. 6
  */
 
-static inline int tnode_full(const struct tnode *tn, const struct node *n)
+static inline int tnode_full(const struct tnode *tn, const struct rt_trie_node *n)
 {
 	if (n == NULL || IS_LEAF(n))
 		return 0;
@@ -474,7 +474,7 @@ static inline int tnode_full(const struct tnode *tn, const struct node *n)
 }
 
 static inline void put_child(struct trie *t, struct tnode *tn, int i,
-			     struct node *n)
+			     struct rt_trie_node *n)
 {
 	tnode_put_child_reorg(tn, i, n, -1);
 }
@@ -484,10 +484,10 @@ static inline void put_child(struct trie *t, struct tnode *tn, int i,
   * Update the value of full_children and empty_children.
   */
 
-static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n,
 				  int wasfull)
 {
-	struct node *chi = tn->child[i];
+	struct rt_trie_node *chi = tn->child[i];
 	int isfull;
 
 	BUG_ON(i >= 1<<tn->bits);
@@ -515,7 +515,7 @@ static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n,
 }
 
 #define MAX_WORK 10
-static struct node *resize(struct trie *t, struct tnode *tn)
+static struct rt_trie_node *resize(struct trie *t, struct tnode *tn)
 {
 	int i;
 	struct tnode *old_tn;
@@ -605,7 +605,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
 
 	/* Keep root node larger  */
 
-	if (!node_parent((struct node *)tn)) {
+	if (!node_parent((struct rt_trie_node *)tn)) {
 		inflate_threshold_use = inflate_threshold_root;
 		halve_threshold_use = halve_threshold_root;
 	} else {
@@ -635,7 +635,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
 
 	/* Return if at least one inflate is run */
 	if (max_work != MAX_WORK)
-		return (struct node *) tn;
+		return (struct rt_trie_node *) tn;
 
 	/*
 	 * Halve as long as the number of empty children in this
@@ -663,7 +663,7 @@ static struct node *resize(struct trie *t, struct tnode *tn)
 	if (tn->empty_children == tnode_child_length(tn) - 1) {
 one_child:
 		for (i = 0; i < tnode_child_length(tn); i++) {
-			struct node *n;
+			struct rt_trie_node *n;
 
 			n = tn->child[i];
 			if (!n)
@@ -676,7 +676,7 @@ one_child:
 			return n;
 		}
 	}
-	return (struct node *) tn;
+	return (struct rt_trie_node *) tn;
 }
 
 static struct tnode *inflate(struct trie *t, struct tnode *tn)
@@ -723,14 +723,14 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn)
 				goto nomem;
 			}
 
-			put_child(t, tn, 2*i, (struct node *) left);
-			put_child(t, tn, 2*i+1, (struct node *) right);
+			put_child(t, tn, 2*i, (struct rt_trie_node *) left);
+			put_child(t, tn, 2*i+1, (struct rt_trie_node *) right);
 		}
 	}
 
 	for (i = 0; i < olen; i++) {
 		struct tnode *inode;
-		struct node *node = tnode_get_child(oldtnode, i);
+		struct rt_trie_node *node = tnode_get_child(oldtnode, i);
 		struct tnode *left, *right;
 		int size, j;
 
@@ -825,7 +825,7 @@ nomem:
 static struct tnode *halve(struct trie *t, struct tnode *tn)
 {
 	struct tnode *oldtnode = tn;
-	struct node *left, *right;
+	struct rt_trie_node *left, *right;
 	int i;
 	int olen = tnode_child_length(tn);
 
@@ -856,7 +856,7 @@ static struct tnode *halve(struct trie *t, struct tnode *tn)
 			if (!newn)
 				goto nomem;
 
-			put_child(t, tn, i/2, (struct node *)newn);
+			put_child(t, tn, i/2, (struct rt_trie_node *)newn);
 		}
 
 	}
@@ -958,7 +958,7 @@ fib_find_node(struct trie *t, u32 key)
 {
 	int pos;
 	struct tnode *tn;
-	struct node *n;
+	struct rt_trie_node *n;
 
 	pos = 0;
 	n = rcu_dereference_rtnl(t->trie);
@@ -993,17 +993,17 @@ static void trie_rebalance(struct trie *t, struct tnode *tn)
 
 	key = tn->key;
 
-	while (tn != NULL && (tp = node_parent((struct node *)tn)) != NULL) {
+	while (tn != NULL && (tp = node_parent((struct rt_trie_node *)tn)) != NULL) {
 		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
 		wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
 		tn = (struct tnode *) resize(t, (struct tnode *)tn);
 
 		tnode_put_child_reorg((struct tnode *)tp, cindex,
-				      (struct node *)tn, wasfull);
+				      (struct rt_trie_node *)tn, wasfull);
 
-		tp = node_parent((struct node *) tn);
+		tp = node_parent((struct rt_trie_node *) tn);
 		if (!tp)
-			rcu_assign_pointer(t->trie, (struct node *)tn);
+			rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
 
 		tnode_free_flush();
 		if (!tp)
@@ -1015,7 +1015,7 @@ static void trie_rebalance(struct trie *t, struct tnode *tn)
 	if (IS_TNODE(tn))
 		tn = (struct tnode *)resize(t, (struct tnode *)tn);
 
-	rcu_assign_pointer(t->trie, (struct node *)tn);
+	rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
 	tnode_free_flush();
 }
 
@@ -1025,7 +1025,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
 {
 	int pos, newpos;
 	struct tnode *tp = NULL, *tn = NULL;
-	struct node *n;
+	struct rt_trie_node *n;
 	struct leaf *l;
 	int missbit;
 	struct list_head *fa_head = NULL;
@@ -1111,10 +1111,10 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
 	if (t->trie && n == NULL) {
 		/* Case 2: n is NULL, and will just insert a new leaf */
 
-		node_set_parent((struct node *)l, tp);
+		node_set_parent((struct rt_trie_node *)l, tp);
 
 		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
-		put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
+		put_child(t, (struct tnode *)tp, cindex, (struct rt_trie_node *)l);
 	} else {
 		/* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
 		/*
@@ -1141,18 +1141,18 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen)
 			return NULL;
 		}
 
-		node_set_parent((struct node *)tn, tp);
+		node_set_parent((struct rt_trie_node *)tn, tp);
 
 		missbit = tkey_extract_bits(key, newpos, 1);
-		put_child(t, tn, missbit, (struct node *)l);
+		put_child(t, tn, missbit, (struct rt_trie_node *)l);
 		put_child(t, tn, 1-missbit, n);
 
 		if (tp) {
 			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
 			put_child(t, (struct tnode *)tp, cindex,
-				  (struct node *)tn);
+				  (struct rt_trie_node *)tn);
 		} else {
-			rcu_assign_pointer(t->trie, (struct node *)tn);
+			rcu_assign_pointer(t->trie, (struct rt_trie_node *)tn);
 			tp = tn;
 		}
 	}
@@ -1340,8 +1340,8 @@ err:
 }
 
 /* should be called with rcu_read_lock */
-static int check_leaf(struct trie *t, struct leaf *l,
-		      t_key key,  const struct flowi *flp,
+static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
+		      t_key key,  const struct flowi4 *flp,
 		      struct fib_result *res, int fib_flags)
 {
 	struct leaf_info *li;
@@ -1349,40 +1349,75 @@ static int check_leaf(struct trie *t, struct leaf *l,
 	struct hlist_node *node;
 
 	hlist_for_each_entry_rcu(li, node, hhead, hlist) {
-		int err;
+		struct fib_alias *fa;
 		int plen = li->plen;
 		__be32 mask = inet_make_mask(plen);
 
 		if (l->key != (key & ntohl(mask)))
 			continue;
 
-		err = fib_semantic_match(&li->falh, flp, res, plen, fib_flags);
+		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
+			struct fib_info *fi = fa->fa_info;
+			int nhsel, err;
 
+			if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
+				continue;
+			if (fa->fa_scope < flp->flowi4_scope)
+				continue;
+			fib_alias_accessed(fa);
+			err = fib_props[fa->fa_type].error;
+			if (err) {
 #ifdef CONFIG_IP_FIB_TRIE_STATS
-		if (err <= 0)
-			t->stats.semantic_match_passed++;
-		else
-			t->stats.semantic_match_miss++;
+				t->stats.semantic_match_miss++;
+#endif
+				return 1;
+			}
+			if (fi->fib_flags & RTNH_F_DEAD)
+				continue;
+			for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
+				const struct fib_nh *nh = &fi->fib_nh[nhsel];
+
+				if (nh->nh_flags & RTNH_F_DEAD)
+					continue;
+				if (flp->flowi4_oif && flp->flowi4_oif != nh->nh_oif)
+					continue;
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+				t->stats.semantic_match_passed++;
+#endif
+				res->prefixlen = plen;
+				res->nh_sel = nhsel;
+				res->type = fa->fa_type;
+				res->scope = fa->fa_scope;
+				res->fi = fi;
+				res->table = tb;
+				res->fa_head = &li->falh;
+				if (!(fib_flags & FIB_LOOKUP_NOREF))
+					atomic_inc(&res->fi->fib_clntref);
+				return 0;
+			}
+		}
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+		t->stats.semantic_match_miss++;
 #endif
-		if (err <= 0)
-			return err;
 	}
 
 	return 1;
 }
 
-int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
+int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 		     struct fib_result *res, int fib_flags)
 {
 	struct trie *t = (struct trie *) tb->tb_data;
 	int ret;
-	struct node *n;
+	struct rt_trie_node *n;
 	struct tnode *pn;
-	int pos, bits;
-	t_key key = ntohl(flp->fl4_dst);
-	int chopped_off;
+	unsigned int pos, bits;
+	t_key key = ntohl(flp->daddr);
+	unsigned int chopped_off;
 	t_key cindex = 0;
-	int current_prefix_length = KEYLENGTH;
+	unsigned int current_prefix_length = KEYLENGTH;
 	struct tnode *cn;
 	t_key pref_mismatch;
 
@@ -1398,7 +1433,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
 
 	/* Just a leaf? */
 	if (IS_LEAF(n)) {
-		ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags);
+		ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
 		goto found;
 	}
 
@@ -1423,7 +1458,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi *flp,
 		}
 
 		if (IS_LEAF(n)) {
-			ret = check_leaf(t, (struct leaf *)n, key, flp, res, fib_flags);
+			ret = check_leaf(tb, t, (struct leaf *)n, key, flp, res, fib_flags);
 			if (ret > 0)
 				goto backtrace;
 			goto found;
@@ -1541,7 +1576,7 @@ backtrace:
 		if (chopped_off <= pn->bits) {
 			cindex &= ~(1 << (chopped_off-1));
 		} else {
-			struct tnode *parent = node_parent_rcu((struct node *) pn);
+			struct tnode *parent = node_parent_rcu((struct rt_trie_node *) pn);
 			if (!parent)
 				goto failed;
 
@@ -1568,7 +1603,7 @@ found:
  */
 static void trie_leaf_remove(struct trie *t, struct leaf *l)
 {
-	struct tnode *tp = node_parent((struct node *) l);
+	struct tnode *tp = node_parent((struct rt_trie_node *) l);
 
 	pr_debug("entering trie_leaf_remove(%p)\n", l);
 
@@ -1706,7 +1741,7 @@ static int trie_flush_leaf(struct leaf *l)
  * Scan for the next right leaf starting at node p->child[idx]
  * Since we have back pointer, no recursion necessary.
  */
-static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
+static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c)
 {
 	do {
 		t_key idx;
@@ -1732,7 +1767,7 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
 		}
 
 		/* Node empty, walk back up to parent */
-		c = (struct node *) p;
+		c = (struct rt_trie_node *) p;
 	} while ((p = node_parent_rcu(c)) != NULL);
 
 	return NULL; /* Root of trie */
@@ -1753,7 +1788,7 @@ static struct leaf *trie_firstleaf(struct trie *t)
 
 static struct leaf *trie_nextleaf(struct leaf *l)
 {
-	struct node *c = (struct node *) l;
+	struct rt_trie_node *c = (struct rt_trie_node *) l;
 	struct tnode *p = node_parent_rcu(c);
 
 	if (!p)
@@ -1802,80 +1837,6 @@ void fib_free_table(struct fib_table *tb)
 	kfree(tb);
 }
 
-void fib_table_select_default(struct fib_table *tb,
-			      const struct flowi *flp,
-			      struct fib_result *res)
-{
-	struct trie *t = (struct trie *) tb->tb_data;
-	int order, last_idx;
-	struct fib_info *fi = NULL;
-	struct fib_info *last_resort;
-	struct fib_alias *fa = NULL;
-	struct list_head *fa_head;
-	struct leaf *l;
-
-	last_idx = -1;
-	last_resort = NULL;
-	order = -1;
-
-	rcu_read_lock();
-
-	l = fib_find_node(t, 0);
-	if (!l)
-		goto out;
-
-	fa_head = get_fa_head(l, 0);
-	if (!fa_head)
-		goto out;
-
-	if (list_empty(fa_head))
-		goto out;
-
-	list_for_each_entry_rcu(fa, fa_head, fa_list) {
-		struct fib_info *next_fi = fa->fa_info;
-
-		if (fa->fa_scope != res->scope ||
-		    fa->fa_type != RTN_UNICAST)
-			continue;
-
-		if (next_fi->fib_priority > res->fi->fib_priority)
-			break;
-		if (!next_fi->fib_nh[0].nh_gw ||
-		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
-			continue;
-
-		fib_alias_accessed(fa);
-
-		if (fi == NULL) {
-			if (next_fi != res->fi)
-				break;
-		} else if (!fib_detect_death(fi, order, &last_resort,
-					     &last_idx, tb->tb_default)) {
-			fib_result_assign(res, fi);
-			tb->tb_default = order;
-			goto out;
-		}
-		fi = next_fi;
-		order++;
-	}
-	if (order <= 0 || fi == NULL) {
-		tb->tb_default = -1;
-		goto out;
-	}
-
-	if (!fib_detect_death(fi, order, &last_resort, &last_idx,
-				tb->tb_default)) {
-		fib_result_assign(res, fi);
-		tb->tb_default = order;
-		goto out;
-	}
-	if (last_idx >= 0)
-		fib_result_assign(res, last_resort);
-	tb->tb_default = last_idx;
-out:
-	rcu_read_unlock();
-}
-
 static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
 			   struct fib_table *tb,
 			   struct sk_buff *skb, struct netlink_callback *cb)
@@ -1990,7 +1951,7 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
 	return skb->len;
 }
 
-void __init fib_hash_init(void)
+void __init fib_trie_init(void)
 {
 	fn_alias_kmem = kmem_cache_create("ip_fib_alias",
 					  sizeof(struct fib_alias),
@@ -2003,8 +1964,7 @@ void __init fib_hash_init(void)
 }
 
 
-/* Fix more generic FIB names for init later */
-struct fib_table *fib_hash_table(u32 id)
+struct fib_table *fib_trie_table(u32 id)
 {
 	struct fib_table *tb;
 	struct trie *t;
@@ -2036,7 +1996,7 @@ struct fib_trie_iter {
 	unsigned int depth;
 };
 
-static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
+static struct rt_trie_node *fib_trie_get_next(struct fib_trie_iter *iter)
 {
 	struct tnode *tn = iter->tnode;
 	unsigned int cindex = iter->index;
@@ -2050,7 +2010,7 @@ static struct node *fib_trie_get_next(struct fib_trie_iter *iter)
 		 iter->tnode, iter->index, iter->depth);
 rescan:
 	while (cindex < (1<<tn->bits)) {
-		struct node *n = tnode_get_child_rcu(tn, cindex);
+		struct rt_trie_node *n = tnode_get_child_rcu(tn, cindex);
 
 		if (n) {
 			if (IS_LEAF(n)) {
@@ -2069,7 +2029,7 @@ rescan:
 	}
 
 	/* Current node exhausted, pop back up */
-	p = node_parent_rcu((struct node *)tn);
+	p = node_parent_rcu((struct rt_trie_node *)tn);
 	if (p) {
 		cindex = tkey_extract_bits(tn->key, p->pos, p->bits)+1;
 		tn = p;
@@ -2081,10 +2041,10 @@ rescan:
 	return NULL;
 }
 
-static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
+static struct rt_trie_node *fib_trie_get_first(struct fib_trie_iter *iter,
 				       struct trie *t)
 {
-	struct node *n;
+	struct rt_trie_node *n;
 
 	if (!t)
 		return NULL;
@@ -2108,7 +2068,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
 
 static void trie_collect_stats(struct trie *t, struct trie_stat *s)
 {
-	struct node *n;
+	struct rt_trie_node *n;
 	struct fib_trie_iter iter;
 
 	memset(s, 0, sizeof(*s));
@@ -2181,7 +2141,7 @@ static void trie_show_stats(struct seq_file *seq, struct trie_stat *stat)
 	seq_putc(seq, '\n');
 	seq_printf(seq, "\tPointers: %u\n", pointers);
 
-	bytes += sizeof(struct node *) * pointers;
+	bytes += sizeof(struct rt_trie_node *) * pointers;
 	seq_printf(seq, "Null ptrs: %u\n", stat->nullpointers);
 	seq_printf(seq, "Total size: %u  kB\n", (bytes + 1023) / 1024);
 }
@@ -2262,7 +2222,7 @@ static const struct file_operations fib_triestat_fops = {
 	.release = single_release_net,
 };
 
-static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
+static struct rt_trie_node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
 {
 	struct fib_trie_iter *iter = seq->private;
 	struct net *net = seq_file_net(seq);
@@ -2275,7 +2235,7 @@ static struct node *fib_trie_get_idx(struct seq_file *seq, loff_t pos)
 		struct fib_table *tb;
 
 		hlist_for_each_entry_rcu(tb, node, head, tb_hlist) {
-			struct node *n;
+			struct rt_trie_node *n;
 
 			for (n = fib_trie_get_first(iter,
 						    (struct trie *) tb->tb_data);
@@ -2304,7 +2264,7 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 	struct fib_table *tb = iter->tb;
 	struct hlist_node *tb_node;
 	unsigned int h;
-	struct node *n;
+	struct rt_trie_node *n;
 
 	++*pos;
 	/* next node in same table */
@@ -2390,7 +2350,7 @@ static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
 static int fib_trie_seq_show(struct seq_file *seq, void *v)
 {
 	const struct fib_trie_iter *iter = seq->private;
-	struct node *n = v;
+	struct rt_trie_node *n = v;
 
 	if (!node_parent_rcu(n))
 		fib_table_print(seq, iter->tb);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 4aa1b7f..a91dc16 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -233,48 +233,11 @@ static inline void icmp_xmit_unlock(struct sock *sk)
  *	Send an ICMP frame.
  */
 
-/*
- *	Check transmit rate limitation for given message.
- *	The rate information is held in the destination cache now.
- *	This function is generic and could be used for other purposes
- *	too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.
- *
- *	Note that the same dst_entry fields are modified by functions in
- *	route.c too, but these work for packet destinations while xrlim_allow
- *	works for icmp destinations. This means the rate limiting information
- *	for one "ip object" is shared - and these ICMPs are twice limited:
- *	by source and by destination.
- *
- *	RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate
- *			  SHOULD allow setting of rate limits
- *
- * 	Shared between ICMPv4 and ICMPv6.
- */
-#define XRLIM_BURST_FACTOR 6
-int xrlim_allow(struct dst_entry *dst, int timeout)
-{
-	unsigned long now, token = dst->rate_tokens;
-	int rc = 0;
-
-	now = jiffies;
-	token += now - dst->rate_last;
-	dst->rate_last = now;
-	if (token > XRLIM_BURST_FACTOR * timeout)
-		token = XRLIM_BURST_FACTOR * timeout;
-	if (token >= timeout) {
-		token -= timeout;
-		rc = 1;
-	}
-	dst->rate_tokens = token;
-	return rc;
-}
-EXPORT_SYMBOL(xrlim_allow);
-
-static inline int icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
+static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
 		int type, int code)
 {
 	struct dst_entry *dst = &rt->dst;
-	int rc = 1;
+	bool rc = true;
 
 	if (type > NR_ICMP_TYPES)
 		goto out;
@@ -288,8 +251,12 @@ static inline int icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
 		goto out;
 
 	/* Limit if icmp type is enabled in ratemask. */
-	if ((1 << type) & net->ipv4.sysctl_icmp_ratemask)
-		rc = xrlim_allow(dst, net->ipv4.sysctl_icmp_ratelimit);
+	if ((1 << type) & net->ipv4.sysctl_icmp_ratemask) {
+		if (!rt->peer)
+			rt_bind_peer(rt, 1);
+		rc = inet_peer_xrlim_allow(rt->peer,
+					   net->ipv4.sysctl_icmp_ratelimit);
+	}
 out:
 	return rc;
 }
@@ -386,12 +353,15 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 			daddr = icmp_param->replyopts.faddr;
 	}
 	{
-		struct flowi fl = { .fl4_dst= daddr,
-				    .fl4_src = rt->rt_spec_dst,
-				    .fl4_tos = RT_TOS(ip_hdr(skb)->tos),
-				    .proto = IPPROTO_ICMP };
-		security_skb_classify_flow(skb, &fl);
-		if (ip_route_output_key(net, &rt, &fl))
+		struct flowi4 fl4 = {
+			.daddr = daddr,
+			.saddr = rt->rt_spec_dst,
+			.flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
+			.flowi4_proto = IPPROTO_ICMP,
+		};
+		security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
+		rt = ip_route_output_key(net, &fl4);
+		if (IS_ERR(rt))
 			goto out_unlock;
 	}
 	if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
@@ -402,6 +372,97 @@ out_unlock:
 	icmp_xmit_unlock(sk);
 }
 
+static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in,
+					struct iphdr *iph,
+					__be32 saddr, u8 tos,
+					int type, int code,
+					struct icmp_bxm *param)
+{
+	struct flowi4 fl4 = {
+		.daddr = (param->replyopts.srr ?
+			  param->replyopts.faddr : iph->saddr),
+		.saddr = saddr,
+		.flowi4_tos = RT_TOS(tos),
+		.flowi4_proto = IPPROTO_ICMP,
+		.fl4_icmp_type = type,
+		.fl4_icmp_code = code,
+	};
+	struct rtable *rt, *rt2;
+	int err;
+
+	security_skb_classify_flow(skb_in, flowi4_to_flowi(&fl4));
+	rt = __ip_route_output_key(net, &fl4);
+	if (IS_ERR(rt))
+		return rt;
+
+	/* No need to clone since we're just using its address. */
+	rt2 = rt;
+
+	if (!fl4.saddr)
+		fl4.saddr = rt->rt_src;
+
+	rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
+					   flowi4_to_flowi(&fl4), NULL, 0);
+	if (!IS_ERR(rt)) {
+		if (rt != rt2)
+			return rt;
+	} else if (PTR_ERR(rt) == -EPERM) {
+		rt = NULL;
+	} else
+		return rt;
+
+	err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4), AF_INET);
+	if (err)
+		goto relookup_failed;
+
+	if (inet_addr_type(net, fl4.saddr) == RTN_LOCAL) {
+		rt2 = __ip_route_output_key(net, &fl4);
+		if (IS_ERR(rt2))
+			err = PTR_ERR(rt2);
+	} else {
+		struct flowi4 fl4_2 = {};
+		unsigned long orefdst;
+
+		fl4_2.daddr = fl4.saddr;
+		rt2 = ip_route_output_key(net, &fl4_2);
+		if (IS_ERR(rt2)) {
+			err = PTR_ERR(rt2);
+			goto relookup_failed;
+		}
+		/* Ugh! */
+		orefdst = skb_in->_skb_refdst; /* save old refdst */
+		err = ip_route_input(skb_in, fl4.daddr, fl4.saddr,
+				     RT_TOS(tos), rt2->dst.dev);
+
+		dst_release(&rt2->dst);
+		rt2 = skb_rtable(skb_in);
+		skb_in->_skb_refdst = orefdst; /* restore old refdst */
+	}
+
+	if (err)
+		goto relookup_failed;
+
+	rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst,
+					    flowi4_to_flowi(&fl4), NULL,
+					    XFRM_LOOKUP_ICMP);
+	if (!IS_ERR(rt2)) {
+		dst_release(&rt->dst);
+		rt = rt2;
+	} else if (PTR_ERR(rt2) == -EPERM) {
+		if (rt)
+			dst_release(&rt->dst);
+		return rt2;
+	} else {
+		err = PTR_ERR(rt2);
+		goto relookup_failed;
+	}
+	return rt;
+
+relookup_failed:
+	if (rt)
+		return rt;
+	return ERR_PTR(err);
+}
 
 /*
  *	Send an ICMP message in response to a situation
@@ -507,7 +568,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 		rcu_read_lock();
 		if (rt_is_input_route(rt) &&
 		    net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
-			dev = dev_get_by_index_rcu(net, rt->fl.iif);
+			dev = dev_get_by_index_rcu(net, rt->rt_iif);
 
 		if (dev)
 			saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK);
@@ -539,86 +600,11 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
 	ipc.opt = &icmp_param.replyopts;
 	ipc.tx_flags = 0;
 
-	{
-		struct flowi fl = {
-			.fl4_dst = icmp_param.replyopts.srr ?
-				   icmp_param.replyopts.faddr : iph->saddr,
-			.fl4_src = saddr,
-			.fl4_tos = RT_TOS(tos),
-			.proto = IPPROTO_ICMP,
-			.fl_icmp_type = type,
-			.fl_icmp_code = code,
-		};
-		int err;
-		struct rtable *rt2;
-
-		security_skb_classify_flow(skb_in, &fl);
-		if (__ip_route_output_key(net, &rt, &fl))
-			goto out_unlock;
-
-		/* No need to clone since we're just using its address. */
-		rt2 = rt;
-
-		if (!fl.nl_u.ip4_u.saddr)
-			fl.nl_u.ip4_u.saddr = rt->rt_src;
-
-		err = xfrm_lookup(net, (struct dst_entry **)&rt, &fl, NULL, 0);
-		switch (err) {
-		case 0:
-			if (rt != rt2)
-				goto route_done;
-			break;
-		case -EPERM:
-			rt = NULL;
-			break;
-		default:
-			goto out_unlock;
-		}
-
-		if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
-			goto relookup_failed;
-
-		if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
-			err = __ip_route_output_key(net, &rt2, &fl);
-		else {
-			struct flowi fl2 = {};
-			unsigned long orefdst;
-
-			fl2.fl4_dst = fl.fl4_src;
-			if (ip_route_output_key(net, &rt2, &fl2))
-				goto relookup_failed;
-
-			/* Ugh! */
-			orefdst = skb_in->_skb_refdst; /* save old refdst */
-			err = ip_route_input(skb_in, fl.fl4_dst, fl.fl4_src,
-					     RT_TOS(tos), rt2->dst.dev);
-
-			dst_release(&rt2->dst);
-			rt2 = skb_rtable(skb_in);
-			skb_in->_skb_refdst = orefdst; /* restore old refdst */
-		}
-
-		if (err)
-			goto relookup_failed;
-
-		err = xfrm_lookup(net, (struct dst_entry **)&rt2, &fl, NULL,
-				  XFRM_LOOKUP_ICMP);
-		switch (err) {
-		case 0:
-			dst_release(&rt->dst);
-			rt = rt2;
-			break;
-		case -EPERM:
-			goto ende;
-		default:
-relookup_failed:
-			if (!rt)
-				goto out_unlock;
-			break;
-		}
-	}
+	rt = icmp_route_lookup(net, skb_in, iph, saddr, tos,
+			       type, code, &icmp_param);
+	if (IS_ERR(rt))
+		goto out_unlock;
 
-route_done:
 	if (!icmpv4_xrlim_allow(net, rt, type, code))
 		goto ende;
 
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index e0e77e2..1fd3d9c 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -321,14 +321,12 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
 	}
 	igmp_skb_size(skb) = size;
 
-	{
-		struct flowi fl = { .oif = dev->ifindex,
-				    .fl4_dst = IGMPV3_ALL_MCR,
-				    .proto = IPPROTO_IGMP };
-		if (ip_route_output_key(net, &rt, &fl)) {
-			kfree_skb(skb);
-			return NULL;
-		}
+	rt = ip_route_output_ports(net, NULL, IGMPV3_ALL_MCR, 0,
+				   0, 0,
+				   IPPROTO_IGMP, 0, dev->ifindex);
+	if (IS_ERR(rt)) {
+		kfree_skb(skb);
+		return NULL;
 	}
 	if (rt->rt_src == 0) {
 		kfree_skb(skb);
@@ -666,13 +664,12 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc,
 	else
 		dst = group;
 
-	{
-		struct flowi fl = { .oif = dev->ifindex,
-				    .fl4_dst = dst,
-				    .proto = IPPROTO_IGMP };
-		if (ip_route_output_key(net, &rt, &fl))
-			return -1;
-	}
+	rt = ip_route_output_ports(net, NULL, dst, 0,
+				   0, 0,
+				   IPPROTO_IGMP, 0, dev->ifindex);
+	if (IS_ERR(rt))
+		return -1;
+
 	if (rt->rt_src == 0) {
 		ip_rt_put(rt);
 		return -1;
@@ -1439,8 +1436,6 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
 /* RTNL is locked */
 static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
 {
-	struct flowi fl = { .fl4_dst = imr->imr_multiaddr.s_addr };
-	struct rtable *rt;
 	struct net_device *dev = NULL;
 	struct in_device *idev = NULL;
 
@@ -1454,9 +1449,14 @@ static struct in_device *ip_mc_find_dev(struct net *net, struct ip_mreqn *imr)
 			return NULL;
 	}
 
-	if (!dev && !ip_route_output_key(net, &rt, &fl)) {
-		dev = rt->dst.dev;
-		ip_rt_put(rt);
+	if (!dev) {
+		struct rtable *rt = ip_route_output(net,
+						    imr->imr_multiaddr.s_addr,
+						    0, 0, 0);
+		if (!IS_ERR(rt)) {
+			dev = rt->dst.dev;
+			ip_rt_put(rt);
+		}
 	}
 	if (dev) {
 		imr->imr_ifindex = dev->ifindex;
@@ -2329,13 +2329,13 @@ void ip_mc_drop_socket(struct sock *sk)
 	rtnl_unlock();
 }
 
-int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
+/* called with rcu_read_lock() */
+int ip_check_mc_rcu(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
 {
 	struct ip_mc_list *im;
 	struct ip_sf_list *psf;
 	int rv = 0;
 
-	rcu_read_lock();
 	for_each_pmc_rcu(in_dev, im) {
 		if (im->multiaddr == mc_addr)
 			break;
@@ -2357,7 +2357,6 @@ int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 p
 		} else
 			rv = 1; /* unspecified source; tentatively allow */
 	}
-	rcu_read_unlock();
 	return rv;
 }
 
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 97e5fb7..6c0b7f4 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -356,20 +356,23 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
 	struct rtable *rt;
 	const struct inet_request_sock *ireq = inet_rsk(req);
 	struct ip_options *opt = inet_rsk(req)->opt;
-	struct flowi fl = { .oif = sk->sk_bound_dev_if,
-			    .mark = sk->sk_mark,
-			    .fl4_dst = ((opt && opt->srr) ?
-					  opt->faddr : ireq->rmt_addr),
-			    .fl4_src = ireq->loc_addr,
-			    .fl4_tos = RT_CONN_FLAGS(sk),
-			    .proto = sk->sk_protocol,
-			    .flags = inet_sk_flowi_flags(sk),
-			    .fl_ip_sport = inet_sk(sk)->inet_sport,
-			    .fl_ip_dport = ireq->rmt_port };
+	struct flowi4 fl4 = {
+		.flowi4_oif = sk->sk_bound_dev_if,
+		.flowi4_mark = sk->sk_mark,
+		.daddr = ((opt && opt->srr) ?
+			  opt->faddr : ireq->rmt_addr),
+		.saddr = ireq->loc_addr,
+		.flowi4_tos = RT_CONN_FLAGS(sk),
+		.flowi4_proto = sk->sk_protocol,
+		.flowi4_flags = inet_sk_flowi_flags(sk),
+		.fl4_sport = inet_sk(sk)->inet_sport,
+		.fl4_dport = ireq->rmt_port,
+	};
 	struct net *net = sock_net(sk);
 
-	security_req_classify_flow(req, &fl);
-	if (ip_route_output_flow(net, &rt, &fl, sk, 0))
+	security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+	rt = ip_route_output_flow(net, &fl4, sk);
+	if (IS_ERR(rt))
 		goto no_route;
 	if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)
 		goto route_err;
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index a96e656..dd1b20e 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -81,19 +81,19 @@ static const struct inet_peer peer_fake_node = {
 
 struct inet_peer_base {
 	struct inet_peer __rcu *root;
-	spinlock_t	lock;
+	seqlock_t	lock;
 	int		total;
 };
 
 static struct inet_peer_base v4_peers = {
 	.root		= peer_avl_empty_rcu,
-	.lock		= __SPIN_LOCK_UNLOCKED(v4_peers.lock),
+	.lock		= __SEQLOCK_UNLOCKED(v4_peers.lock),
 	.total		= 0,
 };
 
 static struct inet_peer_base v6_peers = {
 	.root		= peer_avl_empty_rcu,
-	.lock		= __SPIN_LOCK_UNLOCKED(v6_peers.lock),
+	.lock		= __SEQLOCK_UNLOCKED(v6_peers.lock),
 	.total		= 0,
 };
 
@@ -167,9 +167,9 @@ static int addr_compare(const struct inetpeer_addr *a,
 	int i, n = (a->family == AF_INET ? 1 : 4);
 
 	for (i = 0; i < n; i++) {
-		if (a->a6[i] == b->a6[i])
+		if (a->addr.a6[i] == b->addr.a6[i])
 			continue;
-		if (a->a6[i] < b->a6[i])
+		if (a->addr.a6[i] < b->addr.a6[i])
 			return -1;
 		return 1;
 	}
@@ -177,6 +177,9 @@ static int addr_compare(const struct inetpeer_addr *a,
 	return 0;
 }
 
+#define rcu_deref_locked(X, BASE)				\
+	rcu_dereference_protected(X, lockdep_is_held(&(BASE)->lock.lock))
+
 /*
  * Called with local BH disabled and the pool lock held.
  */
@@ -187,8 +190,7 @@ static int addr_compare(const struct inetpeer_addr *a,
 								\
 	stackptr = _stack;					\
 	*stackptr++ = &_base->root;				\
-	for (u = rcu_dereference_protected(_base->root,		\
-			lockdep_is_held(&_base->lock));		\
+	for (u = rcu_deref_locked(_base->root, _base);		\
 	     u != peer_avl_empty; ) {				\
 		int cmp = addr_compare(_daddr, &u->daddr);	\
 		if (cmp == 0)					\
@@ -198,23 +200,22 @@ static int addr_compare(const struct inetpeer_addr *a,
 		else						\
 			v = &u->avl_right;			\
 		*stackptr++ = v;				\
-		u = rcu_dereference_protected(*v,		\
-			lockdep_is_held(&_base->lock));		\
+		u = rcu_deref_locked(*v, _base);		\
 	}							\
 	u;							\
 })
 
 /*
- * Called with rcu_read_lock_bh()
+ * Called with rcu_read_lock()
  * Because we hold no lock against a writer, its quite possible we fall
  * in an endless loop.
  * But every pointer we follow is guaranteed to be valid thanks to RCU.
  * We exit from this function if number of links exceeds PEER_MAXDEPTH
  */
-static struct inet_peer *lookup_rcu_bh(const struct inetpeer_addr *daddr,
-				       struct inet_peer_base *base)
+static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
+				    struct inet_peer_base *base)
 {
-	struct inet_peer *u = rcu_dereference_bh(base->root);
+	struct inet_peer *u = rcu_dereference(base->root);
 	int count = 0;
 
 	while (u != peer_avl_empty) {
@@ -230,9 +231,9 @@ static struct inet_peer *lookup_rcu_bh(const struct inetpeer_addr *daddr,
 			return u;
 		}
 		if (cmp == -1)
-			u = rcu_dereference_bh(u->avl_left);
+			u = rcu_dereference(u->avl_left);
 		else
-			u = rcu_dereference_bh(u->avl_right);
+			u = rcu_dereference(u->avl_right);
 		if (unlikely(++count == PEER_MAXDEPTH))
 			break;
 	}
@@ -246,13 +247,11 @@ static struct inet_peer *lookup_rcu_bh(const struct inetpeer_addr *daddr,
 	struct inet_peer __rcu **v;				\
 	*stackptr++ = &start->avl_left;				\
 	v = &start->avl_left;					\
-	for (u = rcu_dereference_protected(*v,			\
-			lockdep_is_held(&base->lock));		\
+	for (u = rcu_deref_locked(*v, base);			\
 	     u->avl_right != peer_avl_empty_rcu; ) {		\
 		v = &u->avl_right;				\
 		*stackptr++ = v;				\
-		u = rcu_dereference_protected(*v,		\
-			lockdep_is_held(&base->lock));		\
+		u = rcu_deref_locked(*v, base);			\
 	}							\
 	u;							\
 })
@@ -271,21 +270,16 @@ static void peer_avl_rebalance(struct inet_peer __rcu **stack[],
 
 	while (stackend > stack) {
 		nodep = *--stackend;
-		node = rcu_dereference_protected(*nodep,
-				lockdep_is_held(&base->lock));
-		l = rcu_dereference_protected(node->avl_left,
-				lockdep_is_held(&base->lock));
-		r = rcu_dereference_protected(node->avl_right,
-				lockdep_is_held(&base->lock));
+		node = rcu_deref_locked(*nodep, base);
+		l = rcu_deref_locked(node->avl_left, base);
+		r = rcu_deref_locked(node->avl_right, base);
 		lh = node_height(l);
 		rh = node_height(r);
 		if (lh > rh + 1) { /* l: RH+2 */
 			struct inet_peer *ll, *lr, *lrl, *lrr;
 			int lrh;
-			ll = rcu_dereference_protected(l->avl_left,
-				lockdep_is_held(&base->lock));
-			lr = rcu_dereference_protected(l->avl_right,
-				lockdep_is_held(&base->lock));
+			ll = rcu_deref_locked(l->avl_left, base);
+			lr = rcu_deref_locked(l->avl_right, base);
 			lrh = node_height(lr);
 			if (lrh <= node_height(ll)) {	/* ll: RH+1 */
 				RCU_INIT_POINTER(node->avl_left, lr);	/* lr: RH or RH+1 */
@@ -296,10 +290,8 @@ static void peer_avl_rebalance(struct inet_peer __rcu **stack[],
 				l->avl_height = node->avl_height + 1;
 				RCU_INIT_POINTER(*nodep, l);
 			} else { /* ll: RH, lr: RH+1 */
-				lrl = rcu_dereference_protected(lr->avl_left,
-					lockdep_is_held(&base->lock));	/* lrl: RH or RH-1 */
-				lrr = rcu_dereference_protected(lr->avl_right,
-					lockdep_is_held(&base->lock));	/* lrr: RH or RH-1 */
+				lrl = rcu_deref_locked(lr->avl_left, base);/* lrl: RH or RH-1 */
+				lrr = rcu_deref_locked(lr->avl_right, base);/* lrr: RH or RH-1 */
 				RCU_INIT_POINTER(node->avl_left, lrr);	/* lrr: RH or RH-1 */
 				RCU_INIT_POINTER(node->avl_right, r);	/* r: RH */
 				node->avl_height = rh + 1; /* node: RH+1 */
@@ -314,10 +306,8 @@ static void peer_avl_rebalance(struct inet_peer __rcu **stack[],
 		} else if (rh > lh + 1) { /* r: LH+2 */
 			struct inet_peer *rr, *rl, *rlr, *rll;
 			int rlh;
-			rr = rcu_dereference_protected(r->avl_right,
-				lockdep_is_held(&base->lock));
-			rl = rcu_dereference_protected(r->avl_left,
-				lockdep_is_held(&base->lock));
+			rr = rcu_deref_locked(r->avl_right, base);
+			rl = rcu_deref_locked(r->avl_left, base);
 			rlh = node_height(rl);
 			if (rlh <= node_height(rr)) {	/* rr: LH+1 */
 				RCU_INIT_POINTER(node->avl_right, rl);	/* rl: LH or LH+1 */
@@ -328,10 +318,8 @@ static void peer_avl_rebalance(struct inet_peer __rcu **stack[],
 				r->avl_height = node->avl_height + 1;
 				RCU_INIT_POINTER(*nodep, r);
 			} else { /* rr: RH, rl: RH+1 */
-				rlr = rcu_dereference_protected(rl->avl_right,
-					lockdep_is_held(&base->lock));	/* rlr: LH or LH-1 */
-				rll = rcu_dereference_protected(rl->avl_left,
-					lockdep_is_held(&base->lock));	/* rll: LH or LH-1 */
+				rlr = rcu_deref_locked(rl->avl_right, base);/* rlr: LH or LH-1 */
+				rll = rcu_deref_locked(rl->avl_left, base);/* rll: LH or LH-1 */
 				RCU_INIT_POINTER(node->avl_right, rll);	/* rll: LH or LH-1 */
 				RCU_INIT_POINTER(node->avl_left, l);	/* l: LH */
 				node->avl_height = lh + 1; /* node: LH+1 */
@@ -372,7 +360,7 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
 
 	do_free = 0;
 
-	spin_lock_bh(&base->lock);
+	write_seqlock_bh(&base->lock);
 	/* Check the reference counter.  It was artificially incremented by 1
 	 * in cleanup() function to prevent sudden disappearing.  If we can
 	 * atomically (because of lockless readers) take this last reference,
@@ -392,8 +380,7 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
 			/* look for a node to insert instead of p */
 			struct inet_peer *t;
 			t = lookup_rightempty(p, base);
-			BUG_ON(rcu_dereference_protected(*stackptr[-1],
-					lockdep_is_held(&base->lock)) != t);
+			BUG_ON(rcu_deref_locked(*stackptr[-1], base) != t);
 			**--stackptr = t->avl_left;
 			/* t is removed, t->daddr > x->daddr for any
 			 * x in p->avl_left subtree.
@@ -409,10 +396,10 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
 		base->total--;
 		do_free = 1;
 	}
-	spin_unlock_bh(&base->lock);
+	write_sequnlock_bh(&base->lock);
 
 	if (do_free)
-		call_rcu_bh(&p->rcu, inetpeer_free_rcu);
+		call_rcu(&p->rcu, inetpeer_free_rcu);
 	else
 		/* The node is used again.  Decrease the reference counter
 		 * back.  The loop "cleanup -> unlink_from_unused
@@ -477,13 +464,17 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
 	struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr;
 	struct inet_peer_base *base = family_to_base(daddr->family);
 	struct inet_peer *p;
+	unsigned int sequence;
+	int invalidated;
 
 	/* Look up for the address quickly, lockless.
 	 * Because of a concurrent writer, we might not find an existing entry.
 	 */
-	rcu_read_lock_bh();
-	p = lookup_rcu_bh(daddr, base);
-	rcu_read_unlock_bh();
+	rcu_read_lock();
+	sequence = read_seqbegin(&base->lock);
+	p = lookup_rcu(daddr, base);
+	invalidated = read_seqretry(&base->lock, sequence);
+	rcu_read_unlock();
 
 	if (p) {
 		/* The existing node has been found.
@@ -493,14 +484,18 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
 		return p;
 	}
 
+	/* If no writer did a change during our lookup, we can return early. */
+	if (!create && !invalidated)
+		return NULL;
+
 	/* retry an exact lookup, taking the lock before.
 	 * At least, nodes should be hot in our cache.
 	 */
-	spin_lock_bh(&base->lock);
+	write_seqlock_bh(&base->lock);
 	p = lookup(daddr, stack, base);
 	if (p != peer_avl_empty) {
 		atomic_inc(&p->refcnt);
-		spin_unlock_bh(&base->lock);
+		write_sequnlock_bh(&base->lock);
 		/* Remove the entry from unused list if it was there. */
 		unlink_from_unused(p);
 		return p;
@@ -510,8 +505,14 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
 		p->daddr = *daddr;
 		atomic_set(&p->refcnt, 1);
 		atomic_set(&p->rid, 0);
-		atomic_set(&p->ip_id_count, secure_ip_id(daddr->a4));
+		atomic_set(&p->ip_id_count, secure_ip_id(daddr->addr.a4));
 		p->tcp_ts_stamp = 0;
+		p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
+		p->rate_tokens = 0;
+		p->rate_last = 0;
+		p->pmtu_expires = 0;
+		p->pmtu_orig = 0;
+		memset(&p->redirect_learned, 0, sizeof(p->redirect_learned));
 		INIT_LIST_HEAD(&p->unused);
 
 
@@ -519,7 +520,7 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
 		link_to_pool(p, base);
 		base->total++;
 	}
-	spin_unlock_bh(&base->lock);
+	write_sequnlock_bh(&base->lock);
 
 	if (base->total >= inet_peer_threshold)
 		/* Remove one less-recently-used entry. */
@@ -579,3 +580,44 @@ void inet_putpeer(struct inet_peer *p)
 	local_bh_enable();
 }
 EXPORT_SYMBOL_GPL(inet_putpeer);
+
+/*
+ *	Check transmit rate limitation for given message.
+ *	The rate information is held in the inet_peer entries now.
+ *	This function is generic and could be used for other purposes
+ *	too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.
+ *
+ *	Note that the same inet_peer fields are modified by functions in
+ *	route.c too, but these work for packet destinations while xrlim_allow
+ *	works for icmp destinations. This means the rate limiting information
+ *	for one "ip object" is shared - and these ICMPs are twice limited:
+ *	by source and by destination.
+ *
+ *	RFC 1812: 4.3.2.8 SHOULD be able to limit error message rate
+ *			  SHOULD allow setting of rate limits
+ *
+ * 	Shared between ICMPv4 and ICMPv6.
+ */
+#define XRLIM_BURST_FACTOR 6
+bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout)
+{
+	unsigned long now, token;
+	bool rc = false;
+
+	if (!peer)
+		return true;
+
+	token = peer->rate_tokens;
+	now = jiffies;
+	token += now - peer->rate_last;
+	peer->rate_last = now;
+	if (token > XRLIM_BURST_FACTOR * timeout)
+		token = XRLIM_BURST_FACTOR * timeout;
+	if (token >= timeout) {
+		token -= timeout;
+		rc = true;
+	}
+	peer->rate_tokens = token;
+	return rc;
+}
+EXPORT_SYMBOL(inet_peer_xrlim_allow);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index d1d0e2c..da5941f 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -769,19 +769,12 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 			tos = ipv6_get_dsfield((struct ipv6hdr *)old_iph);
 	}
 
-	{
-		struct flowi fl = {
-			.oif = tunnel->parms.link,
-			.fl4_dst = dst,
-			.fl4_src = tiph->saddr,
-			.fl4_tos = RT_TOS(tos),
-			.proto = IPPROTO_GRE,
-			.fl_gre_key = tunnel->parms.o_key
-		};
-		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
-			dev->stats.tx_carrier_errors++;
-			goto tx_error;
-		}
+	rt = ip_route_output_gre(dev_net(dev), 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;
 
@@ -945,17 +938,13 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev)
 	/* Guess output device to choose reasonable mtu and needed_headroom */
 
 	if (iph->daddr) {
-		struct flowi fl = {
-			.oif = tunnel->parms.link,
-			.fl4_dst = iph->daddr,
-			.fl4_src = iph->saddr,
-			.fl4_tos = RT_TOS(iph->tos),
-			.proto = IPPROTO_GRE,
-			.fl_gre_key = tunnel->parms.o_key
-		};
-		struct rtable *rt;
-
-		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+		struct rtable *rt = ip_route_output_gre(dev_net(dev),
+							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);
 		}
@@ -1207,17 +1196,14 @@ static int ipgre_open(struct net_device *dev)
 	struct ip_tunnel *t = netdev_priv(dev);
 
 	if (ipv4_is_multicast(t->parms.iph.daddr)) {
-		struct flowi fl = {
-			.oif = t->parms.link,
-			.fl4_dst = t->parms.iph.daddr,
-			.fl4_src = t->parms.iph.saddr,
-			.fl4_tos = RT_TOS(t->parms.iph.tos),
-			.proto = IPPROTO_GRE,
-			.fl_gre_key = t->parms.o_key
-		};
-		struct rtable *rt;
-
-		if (ip_route_output_key(dev_net(dev), &rt, &fl))
+		struct rtable *rt = ip_route_output_gre(dev_net(dev),
+							t->parms.iph.daddr,
+							t->parms.iph.saddr,
+							t->parms.o_key,
+							RT_TOS(t->parms.iph.tos),
+							t->parms.link);
+
+		if (IS_ERR(rt))
 			return -EADDRNOTAVAIL;
 		dev = rt->dst.dev;
 		ip_rt_put(rt);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index d859bcc..d7b2b09 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -340,7 +340,7 @@ static int ip_rcv_finish(struct sk_buff *skb)
 		}
 	}
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	if (unlikely(skb_dst(skb)->tclassid)) {
 		struct ip_rt_acct *st = this_cpu_ptr(ip_rt_acct);
 		u32 idx = skb_dst(skb)->tclassid;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 04c7b3b..67f241b 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -339,25 +339,19 @@ int ip_queue_xmit(struct sk_buff *skb)
 		if(opt && opt->srr)
 			daddr = opt->faddr;
 
-		{
-			struct flowi fl = { .oif = sk->sk_bound_dev_if,
-					    .mark = sk->sk_mark,
-					    .fl4_dst = daddr,
-					    .fl4_src = inet->inet_saddr,
-					    .fl4_tos = RT_CONN_FLAGS(sk),
-					    .proto = sk->sk_protocol,
-					    .flags = inet_sk_flowi_flags(sk),
-					    .fl_ip_sport = inet->inet_sport,
-					    .fl_ip_dport = inet->inet_dport };
-
-			/* If this fails, retransmit mechanism of transport layer will
-			 * keep trying until route appears or the connection times
-			 * itself out.
-			 */
-			security_sk_classify_flow(sk, &fl);
-			if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0))
-				goto no_route;
-		}
+		/* If this fails, retransmit mechanism of transport layer will
+		 * keep trying until route appears or the connection times
+		 * itself out.
+		 */
+		rt = ip_route_output_ports(sock_net(sk), sk,
+					   daddr, inet->inet_saddr,
+					   inet->inet_dport,
+					   inet->inet_sport,
+					   sk->sk_protocol,
+					   RT_CONN_FLAGS(sk),
+					   sk->sk_bound_dev_if);
+		if (IS_ERR(rt))
+			goto no_route;
 		sk_setup_caps(sk, &rt->dst);
 	}
 	skb_dst_set_noref(skb, &rt->dst);
@@ -733,6 +727,7 @@ csum_page(struct page *page, int offset, int copy)
 }
 
 static inline int ip_ufo_append_data(struct sock *sk,
+			struct sk_buff_head *queue,
 			int getfrag(void *from, char *to, int offset, int len,
 			       int odd, struct sk_buff *skb),
 			void *from, int length, int hh_len, int fragheaderlen,
@@ -745,7 +740,7 @@ static inline int ip_ufo_append_data(struct sock *sk,
 	 * device, so create one single skb packet containing complete
 	 * udp datagram
 	 */
-	if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) {
+	if ((skb = skb_peek_tail(queue)) == NULL) {
 		skb = sock_alloc_send_skb(sk,
 			hh_len + fragheaderlen + transhdrlen + 20,
 			(flags & MSG_DONTWAIT), &err);
@@ -767,40 +762,28 @@ static inline int ip_ufo_append_data(struct sock *sk,
 
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
-		sk->sk_sndmsg_off = 0;
 
 		/* specify the length of each IP datagram fragment */
 		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
 		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
-		__skb_queue_tail(&sk->sk_write_queue, skb);
+		__skb_queue_tail(queue, skb);
 	}
 
 	return skb_append_datato_frags(sk, skb, getfrag, from,
 				       (length - transhdrlen));
 }
 
-/*
- *	ip_append_data() and ip_append_page() can make one large IP datagram
- *	from many pieces of data. Each pieces will be holded on the socket
- *	until ip_push_pending_frames() is called. Each piece can be a page
- *	or non-page data.
- *
- *	Not only UDP, other transport protocols - e.g. raw sockets - can use
- *	this interface potentially.
- *
- *	LATER: length must be adjusted by pad at tail, when it is required.
- */
-int ip_append_data(struct sock *sk,
-		   int getfrag(void *from, char *to, int offset, int len,
-			       int odd, struct sk_buff *skb),
-		   void *from, int length, int transhdrlen,
-		   struct ipcm_cookie *ipc, struct rtable **rtp,
-		   unsigned int flags)
+static int __ip_append_data(struct sock *sk, struct sk_buff_head *queue,
+			    struct inet_cork *cork,
+			    int getfrag(void *from, char *to, int offset,
+					int len, int odd, struct sk_buff *skb),
+			    void *from, int length, int transhdrlen,
+			    unsigned int flags)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct sk_buff *skb;
 
-	struct ip_options *opt = NULL;
+	struct ip_options *opt = cork->opt;
 	int hh_len;
 	int exthdrlen;
 	int mtu;
@@ -809,58 +792,19 @@ int ip_append_data(struct sock *sk,
 	int offset = 0;
 	unsigned int maxfraglen, fragheaderlen;
 	int csummode = CHECKSUM_NONE;
-	struct rtable *rt;
+	struct rtable *rt = (struct rtable *)cork->dst;
 
-	if (flags&MSG_PROBE)
-		return 0;
-
-	if (skb_queue_empty(&sk->sk_write_queue)) {
-		/*
-		 * setup for corking.
-		 */
-		opt = ipc->opt;
-		if (opt) {
-			if (inet->cork.opt == NULL) {
-				inet->cork.opt = kmalloc(sizeof(struct ip_options) + 40, sk->sk_allocation);
-				if (unlikely(inet->cork.opt == NULL))
-					return -ENOBUFS;
-			}
-			memcpy(inet->cork.opt, opt, sizeof(struct ip_options)+opt->optlen);
-			inet->cork.flags |= IPCORK_OPT;
-			inet->cork.addr = ipc->addr;
-		}
-		rt = *rtp;
-		if (unlikely(!rt))
-			return -EFAULT;
-		/*
-		 * We steal reference to this route, caller should not release it
-		 */
-		*rtp = NULL;
-		inet->cork.fragsize = mtu = inet->pmtudisc == IP_PMTUDISC_PROBE ?
-					    rt->dst.dev->mtu :
-					    dst_mtu(rt->dst.path);
-		inet->cork.dst = &rt->dst;
-		inet->cork.length = 0;
-		sk->sk_sndmsg_page = NULL;
-		sk->sk_sndmsg_off = 0;
-		exthdrlen = rt->dst.header_len;
-		length += exthdrlen;
-		transhdrlen += exthdrlen;
-	} else {
-		rt = (struct rtable *)inet->cork.dst;
-		if (inet->cork.flags & IPCORK_OPT)
-			opt = inet->cork.opt;
+	exthdrlen = transhdrlen ? rt->dst.header_len : 0;
+	length += exthdrlen;
+	transhdrlen += exthdrlen;
+	mtu = cork->fragsize;
 
-		transhdrlen = 0;
-		exthdrlen = 0;
-		mtu = inet->cork.fragsize;
-	}
 	hh_len = LL_RESERVED_SPACE(rt->dst.dev);
 
 	fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0);
 	maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen;
 
-	if (inet->cork.length + length > 0xFFFF - fragheaderlen) {
+	if (cork->length + length > 0xFFFF - fragheaderlen) {
 		ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport,
 			       mtu-exthdrlen);
 		return -EMSGSIZE;
@@ -876,15 +820,15 @@ int ip_append_data(struct sock *sk,
 	    !exthdrlen)
 		csummode = CHECKSUM_PARTIAL;
 
-	skb = skb_peek_tail(&sk->sk_write_queue);
+	skb = skb_peek_tail(queue);
 
-	inet->cork.length += length;
+	cork->length += length;
 	if (((length > mtu) || (skb && skb_is_gso(skb))) &&
 	    (sk->sk_protocol == IPPROTO_UDP) &&
 	    (rt->dst.dev->features & NETIF_F_UFO)) {
-		err = ip_ufo_append_data(sk, getfrag, from, length, hh_len,
-					 fragheaderlen, transhdrlen, mtu,
-					 flags);
+		err = ip_ufo_append_data(sk, queue, getfrag, from, length,
+					 hh_len, fragheaderlen, transhdrlen,
+					 mtu, flags);
 		if (err)
 			goto error;
 		return 0;
@@ -961,7 +905,7 @@ alloc_new_skb:
 				else
 					/* only the initial fragment is
 					   time stamped */
-					ipc->tx_flags = 0;
+					cork->tx_flags = 0;
 			}
 			if (skb == NULL)
 				goto error;
@@ -972,7 +916,7 @@ alloc_new_skb:
 			skb->ip_summed = csummode;
 			skb->csum = 0;
 			skb_reserve(skb, hh_len);
-			skb_shinfo(skb)->tx_flags = ipc->tx_flags;
+			skb_shinfo(skb)->tx_flags = cork->tx_flags;
 
 			/*
 			 *	Find where to start putting bytes.
@@ -1009,7 +953,7 @@ alloc_new_skb:
 			/*
 			 * Put the packet on the pending queue.
 			 */
-			__skb_queue_tail(&sk->sk_write_queue, skb);
+			__skb_queue_tail(queue, skb);
 			continue;
 		}
 
@@ -1029,8 +973,8 @@ alloc_new_skb:
 		} else {
 			int i = skb_shinfo(skb)->nr_frags;
 			skb_frag_t *frag = &skb_shinfo(skb)->frags[i-1];
-			struct page *page = sk->sk_sndmsg_page;
-			int off = sk->sk_sndmsg_off;
+			struct page *page = cork->page;
+			int off = cork->off;
 			unsigned int left;
 
 			if (page && (left = PAGE_SIZE - off) > 0) {
@@ -1042,7 +986,7 @@ alloc_new_skb:
 						goto error;
 					}
 					get_page(page);
-					skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0);
+					skb_fill_page_desc(skb, i, page, off, 0);
 					frag = &skb_shinfo(skb)->frags[i];
 				}
 			} else if (i < MAX_SKB_FRAGS) {
@@ -1053,8 +997,8 @@ alloc_new_skb:
 					err = -ENOMEM;
 					goto error;
 				}
-				sk->sk_sndmsg_page = page;
-				sk->sk_sndmsg_off = 0;
+				cork->page = page;
+				cork->off = 0;
 
 				skb_fill_page_desc(skb, i, page, 0, 0);
 				frag = &skb_shinfo(skb)->frags[i];
@@ -1066,7 +1010,7 @@ alloc_new_skb:
 				err = -EFAULT;
 				goto error;
 			}
-			sk->sk_sndmsg_off += copy;
+			cork->off += copy;
 			frag->size += copy;
 			skb->len += copy;
 			skb->data_len += copy;
@@ -1080,11 +1024,87 @@ alloc_new_skb:
 	return 0;
 
 error:
-	inet->cork.length -= length;
+	cork->length -= length;
 	IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS);
 	return err;
 }
 
+static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
+			 struct ipcm_cookie *ipc, struct rtable **rtp)
+{
+	struct inet_sock *inet = inet_sk(sk);
+	struct ip_options *opt;
+	struct rtable *rt;
+
+	/*
+	 * setup for corking.
+	 */
+	opt = ipc->opt;
+	if (opt) {
+		if (cork->opt == NULL) {
+			cork->opt = kmalloc(sizeof(struct ip_options) + 40,
+					    sk->sk_allocation);
+			if (unlikely(cork->opt == NULL))
+				return -ENOBUFS;
+		}
+		memcpy(cork->opt, opt, sizeof(struct ip_options) + opt->optlen);
+		cork->flags |= IPCORK_OPT;
+		cork->addr = ipc->addr;
+	}
+	rt = *rtp;
+	if (unlikely(!rt))
+		return -EFAULT;
+	/*
+	 * We steal reference to this route, caller should not release it
+	 */
+	*rtp = NULL;
+	cork->fragsize = inet->pmtudisc == IP_PMTUDISC_PROBE ?
+			 rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+	cork->dst = &rt->dst;
+	cork->length = 0;
+	cork->tx_flags = ipc->tx_flags;
+	cork->page = NULL;
+	cork->off = 0;
+
+	return 0;
+}
+
+/*
+ *	ip_append_data() and ip_append_page() can make one large IP datagram
+ *	from many pieces of data. Each pieces will be holded on the socket
+ *	until ip_push_pending_frames() is called. Each piece can be a page
+ *	or non-page data.
+ *
+ *	Not only UDP, other transport protocols - e.g. raw sockets - can use
+ *	this interface potentially.
+ *
+ *	LATER: length must be adjusted by pad at tail, when it is required.
+ */
+int ip_append_data(struct sock *sk,
+		   int getfrag(void *from, char *to, int offset, int len,
+			       int odd, struct sk_buff *skb),
+		   void *from, int length, int transhdrlen,
+		   struct ipcm_cookie *ipc, struct rtable **rtp,
+		   unsigned int flags)
+{
+	struct inet_sock *inet = inet_sk(sk);
+	int err;
+
+	if (flags&MSG_PROBE)
+		return 0;
+
+	if (skb_queue_empty(&sk->sk_write_queue)) {
+		err = ip_setup_cork(sk, &inet->cork, ipc, rtp);
+		if (err)
+			return err;
+	} else {
+		transhdrlen = 0;
+	}
+
+	return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork, getfrag,
+				from, length, transhdrlen, flags);
+}
+
 ssize_t	ip_append_page(struct sock *sk, struct page *page,
 		       int offset, size_t size, int flags)
 {
@@ -1228,40 +1248,41 @@ error:
 	return err;
 }
 
-static void ip_cork_release(struct inet_sock *inet)
+static void ip_cork_release(struct inet_cork *cork)
 {
-	inet->cork.flags &= ~IPCORK_OPT;
-	kfree(inet->cork.opt);
-	inet->cork.opt = NULL;
-	dst_release(inet->cork.dst);
-	inet->cork.dst = NULL;
+	cork->flags &= ~IPCORK_OPT;
+	kfree(cork->opt);
+	cork->opt = NULL;
+	dst_release(cork->dst);
+	cork->dst = NULL;
 }
 
 /*
  *	Combined all pending IP fragments on the socket as one IP datagram
  *	and push them out.
  */
-int ip_push_pending_frames(struct sock *sk)
+struct sk_buff *__ip_make_skb(struct sock *sk,
+			      struct sk_buff_head *queue,
+			      struct inet_cork *cork)
 {
 	struct sk_buff *skb, *tmp_skb;
 	struct sk_buff **tail_skb;
 	struct inet_sock *inet = inet_sk(sk);
 	struct net *net = sock_net(sk);
 	struct ip_options *opt = NULL;
-	struct rtable *rt = (struct rtable *)inet->cork.dst;
+	struct rtable *rt = (struct rtable *)cork->dst;
 	struct iphdr *iph;
 	__be16 df = 0;
 	__u8 ttl;
-	int err = 0;
 
-	if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL)
+	if ((skb = __skb_dequeue(queue)) == NULL)
 		goto out;
 	tail_skb = &(skb_shinfo(skb)->frag_list);
 
 	/* move skb->data to ip header from ext header */
 	if (skb->data < skb_network_header(skb))
 		__skb_pull(skb, skb_network_offset(skb));
-	while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) {
+	while ((tmp_skb = __skb_dequeue(queue)) != NULL) {
 		__skb_pull(tmp_skb, skb_network_header_len(skb));
 		*tail_skb = tmp_skb;
 		tail_skb = &(tmp_skb->next);
@@ -1287,8 +1308,8 @@ int ip_push_pending_frames(struct sock *sk)
 	     ip_dont_fragment(sk, &rt->dst)))
 		df = htons(IP_DF);
 
-	if (inet->cork.flags & IPCORK_OPT)
-		opt = inet->cork.opt;
+	if (cork->flags & IPCORK_OPT)
+		opt = cork->opt;
 
 	if (rt->rt_type == RTN_MULTICAST)
 		ttl = inet->mc_ttl;
@@ -1300,7 +1321,7 @@ int ip_push_pending_frames(struct sock *sk)
 	iph->ihl = 5;
 	if (opt) {
 		iph->ihl += opt->optlen>>2;
-		ip_options_build(skb, opt, inet->cork.addr, rt, 0);
+		ip_options_build(skb, opt, cork->addr, rt, 0);
 	}
 	iph->tos = inet->tos;
 	iph->frag_off = df;
@@ -1316,44 +1337,95 @@ int ip_push_pending_frames(struct sock *sk)
 	 * Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec
 	 * on dst refcount
 	 */
-	inet->cork.dst = NULL;
+	cork->dst = NULL;
 	skb_dst_set(skb, &rt->dst);
 
 	if (iph->protocol == IPPROTO_ICMP)
 		icmp_out_count(net, ((struct icmphdr *)
 			skb_transport_header(skb))->type);
 
-	/* Netfilter gets whole the not fragmented skb. */
+	ip_cork_release(cork);
+out:
+	return skb;
+}
+
+int ip_send_skb(struct sk_buff *skb)
+{
+	struct net *net = sock_net(skb->sk);
+	int err;
+
 	err = ip_local_out(skb);
 	if (err) {
 		if (err > 0)
 			err = net_xmit_errno(err);
 		if (err)
-			goto error;
+			IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
 	}
 
-out:
-	ip_cork_release(inet);
 	return err;
+}
 
-error:
-	IP_INC_STATS(net, IPSTATS_MIB_OUTDISCARDS);
-	goto out;
+int ip_push_pending_frames(struct sock *sk)
+{
+	struct sk_buff *skb;
+
+	skb = ip_finish_skb(sk);
+	if (!skb)
+		return 0;
+
+	/* Netfilter gets whole the not fragmented skb. */
+	return ip_send_skb(skb);
 }
 
 /*
  *	Throw away all pending data on the socket.
  */
-void ip_flush_pending_frames(struct sock *sk)
+static void __ip_flush_pending_frames(struct sock *sk,
+				      struct sk_buff_head *queue,
+				      struct inet_cork *cork)
 {
 	struct sk_buff *skb;
 
-	while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)
+	while ((skb = __skb_dequeue_tail(queue)) != NULL)
 		kfree_skb(skb);
 
-	ip_cork_release(inet_sk(sk));
+	ip_cork_release(cork);
+}
+
+void ip_flush_pending_frames(struct sock *sk)
+{
+	__ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork);
 }
 
+struct sk_buff *ip_make_skb(struct sock *sk,
+			    int getfrag(void *from, char *to, int offset,
+					int len, int odd, struct sk_buff *skb),
+			    void *from, int length, int transhdrlen,
+			    struct ipcm_cookie *ipc, struct rtable **rtp,
+			    unsigned int flags)
+{
+	struct inet_cork cork = {};
+	struct sk_buff_head queue;
+	int err;
+
+	if (flags & MSG_PROBE)
+		return NULL;
+
+	__skb_queue_head_init(&queue);
+
+	err = ip_setup_cork(sk, &cork, ipc, rtp);
+	if (err)
+		return ERR_PTR(err);
+
+	err = __ip_append_data(sk, &queue, &cork, getfrag,
+			       from, length, transhdrlen, flags);
+	if (err) {
+		__ip_flush_pending_frames(sk, &queue, &cork);
+		return ERR_PTR(err);
+	}
+
+	return __ip_make_skb(sk, &queue, &cork);
+}
 
 /*
  *	Fetch data from kernel space and fill in checksum if needed.
@@ -1402,16 +1474,19 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
 	}
 
 	{
-		struct flowi fl = { .oif = arg->bound_dev_if,
-				    .fl4_dst = daddr,
-				    .fl4_src = rt->rt_spec_dst,
-				    .fl4_tos = RT_TOS(ip_hdr(skb)->tos),
-				    .fl_ip_sport = tcp_hdr(skb)->dest,
-				    .fl_ip_dport = tcp_hdr(skb)->source,
-				    .proto = sk->sk_protocol,
-				    .flags = ip_reply_arg_flowi_flags(arg) };
-		security_skb_classify_flow(skb, &fl);
-		if (ip_route_output_key(sock_net(sk), &rt, &fl))
+		struct flowi4 fl4 = {
+			.flowi4_oif = arg->bound_dev_if,
+			.daddr = daddr,
+			.saddr = rt->rt_spec_dst,
+			.flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
+			.fl4_sport = tcp_hdr(skb)->dest,
+			.fl4_dport = tcp_hdr(skb)->source,
+			.flowi4_proto = sk->sk_protocol,
+			.flowi4_flags = ip_reply_arg_flowi_flags(arg),
+		};
+		security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
+		rt = ip_route_output_key(sock_net(sk), &fl4);
+		if (IS_ERR(rt))
 			return;
 	}
 
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index a5f58e7..bfc17c5 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -460,19 +460,14 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 			goto tx_error_icmp;
 	}
 
-	{
-		struct flowi fl = {
-			.oif = tunnel->parms.link,
-			.fl4_dst = dst,
-			.fl4_src= tiph->saddr,
-			.fl4_tos = RT_TOS(tos),
-			.proto = IPPROTO_IPIP
-		};
-
-		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
-			dev->stats.tx_carrier_errors++;
-			goto tx_error_icmp;
-		}
+	rt = ip_route_output_ports(dev_net(dev), 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;
 
@@ -583,16 +578,14 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
 	iph = &tunnel->parms.iph;
 
 	if (iph->daddr) {
-		struct flowi fl = {
-			.oif = tunnel->parms.link,
-			.fl4_dst = iph->daddr,
-			.fl4_src = iph->saddr,
-			.fl4_tos = RT_TOS(iph->tos),
-			.proto = IPPROTO_IPIP
-		};
-		struct rtable *rt;
-
-		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+		struct rtable *rt = ip_route_output_ports(dev_net(dev), 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);
 		}
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 8b65a12..1f62eae 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -148,14 +148,15 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
 	return NULL;
 }
 
-static int ipmr_fib_lookup(struct net *net, struct flowi *flp,
+static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
 			   struct mr_table **mrt)
 {
 	struct ipmr_result res;
 	struct fib_lookup_arg arg = { .result = &res, };
 	int err;
 
-	err = fib_rules_lookup(net->ipv4.mr_rules_ops, flp, 0, &arg);
+	err = fib_rules_lookup(net->ipv4.mr_rules_ops,
+			       flowi4_to_flowi(flp4), 0, &arg);
 	if (err < 0)
 		return err;
 	*mrt = res.mrt;
@@ -283,7 +284,7 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
 	return net->ipv4.mrt;
 }
 
-static int ipmr_fib_lookup(struct net *net, struct flowi *flp,
+static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
 			   struct mr_table **mrt)
 {
 	*mrt = net->ipv4.mrt;
@@ -435,14 +436,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net *net = dev_net(dev);
 	struct mr_table *mrt;
-	struct flowi fl = {
-		.oif		= dev->ifindex,
-		.iif		= skb->skb_iif,
-		.mark		= skb->mark,
+	struct flowi4 fl4 = {
+		.flowi4_oif	= dev->ifindex,
+		.flowi4_iif	= skb->skb_iif,
+		.flowi4_mark	= skb->mark,
 	};
 	int err;
 
-	err = ipmr_fib_lookup(net, &fl, &mrt);
+	err = ipmr_fib_lookup(net, &fl4, &mrt);
 	if (err < 0) {
 		kfree_skb(skb);
 		return err;
@@ -1611,26 +1612,20 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt,
 #endif
 
 	if (vif->flags & VIFF_TUNNEL) {
-		struct flowi fl = {
-			.oif = vif->link,
-			.fl4_dst = vif->remote,
-			.fl4_src = vif->local,
-			.fl4_tos = RT_TOS(iph->tos),
-			.proto = IPPROTO_IPIP
-		};
-
-		if (ip_route_output_key(net, &rt, &fl))
+		rt = ip_route_output_ports(net, NULL,
+					   vif->remote, vif->local,
+					   0, 0,
+					   IPPROTO_IPIP,
+					   RT_TOS(iph->tos), vif->link);
+		if (IS_ERR(rt))
 			goto out_free;
 		encap = sizeof(struct iphdr);
 	} else {
-		struct flowi fl = {
-			.oif = vif->link,
-			.fl4_dst = iph->daddr,
-			.fl4_tos = RT_TOS(iph->tos),
-			.proto = IPPROTO_IPIP
-		};
-
-		if (ip_route_output_key(net, &rt, &fl))
+		rt = ip_route_output_ports(net, NULL, iph->daddr, 0,
+					   0, 0,
+					   IPPROTO_IPIP,
+					   RT_TOS(iph->tos), vif->link);
+		if (IS_ERR(rt))
 			goto out_free;
 	}
 
@@ -1793,6 +1788,24 @@ dont_forward:
 	return 0;
 }
 
+static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct rtable *rt)
+{
+	struct flowi4 fl4 = {
+		.daddr = rt->rt_key_dst,
+		.saddr = rt->rt_key_src,
+		.flowi4_tos = rt->rt_tos,
+		.flowi4_oif = rt->rt_oif,
+		.flowi4_iif = rt->rt_iif,
+		.flowi4_mark = rt->rt_mark,
+	};
+	struct mr_table *mrt;
+	int err;
+
+	err = ipmr_fib_lookup(net, &fl4, &mrt);
+	if (err)
+		return ERR_PTR(err);
+	return mrt;
+}
 
 /*
  *	Multicast packets for forwarding arrive here
@@ -1805,7 +1818,6 @@ int ip_mr_input(struct sk_buff *skb)
 	struct net *net = dev_net(skb->dev);
 	int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL;
 	struct mr_table *mrt;
-	int err;
 
 	/* Packet is looped back after forward, it should not be
 	 * forwarded second time, but still can be delivered locally.
@@ -1813,12 +1825,11 @@ int ip_mr_input(struct sk_buff *skb)
 	if (IPCB(skb)->flags & IPSKB_FORWARDED)
 		goto dont_forward;
 
-	err = ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt);
-	if (err < 0) {
+	mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb));
+	if (IS_ERR(mrt)) {
 		kfree_skb(skb);
-		return err;
+		return PTR_ERR(mrt);
 	}
-
 	if (!local) {
 		if (IPCB(skb)->opt.router_alert) {
 			if (ip_call_ra_chain(skb))
@@ -1946,9 +1957,9 @@ int pim_rcv_v1(struct sk_buff *skb)
 
 	pim = igmp_hdr(skb);
 
-	if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0)
+	mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb));
+	if (IS_ERR(mrt))
 		goto drop;
-
 	if (!mrt->mroute_do_pim ||
 	    pim->group != PIM_V1_VERSION || pim->code != PIM_V1_REGISTER)
 		goto drop;
@@ -1978,9 +1989,9 @@ static int pim_rcv(struct sk_buff *skb)
 	     csum_fold(skb_checksum(skb, 0, skb->len, 0))))
 		goto drop;
 
-	if (ipmr_fib_lookup(net, &skb_rtable(skb)->fl, &mrt) < 0)
+	mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb));
+	if (IS_ERR(mrt))
 		goto drop;
-
 	if (__pim_rcv(mrt, skb, sizeof(*pim))) {
 drop:
 		kfree_skb(skb);
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 994a1f2..f3c0b54 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -16,7 +16,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
 	struct net *net = dev_net(skb_dst(skb)->dev);
 	const struct iphdr *iph = ip_hdr(skb);
 	struct rtable *rt;
-	struct flowi fl = {};
+	struct flowi4 fl4 = {};
 	unsigned long orefdst;
 	unsigned int hh_len;
 	unsigned int type;
@@ -31,14 +31,15 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
 	 * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook.
 	 */
 	if (addr_type == RTN_LOCAL) {
-		fl.fl4_dst = iph->daddr;
+		fl4.daddr = iph->daddr;
 		if (type == RTN_LOCAL)
-			fl.fl4_src = iph->saddr;
-		fl.fl4_tos = RT_TOS(iph->tos);
-		fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
-		fl.mark = skb->mark;
-		fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
-		if (ip_route_output_key(net, &rt, &fl) != 0)
+			fl4.saddr = iph->saddr;
+		fl4.flowi4_tos = RT_TOS(iph->tos);
+		fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+		fl4.flowi4_mark = skb->mark;
+		fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
+		rt = ip_route_output_key(net, &fl4);
+		if (IS_ERR(rt))
 			return -1;
 
 		/* Drop old route. */
@@ -47,8 +48,9 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
 	} else {
 		/* non-local src, find valid iif to satisfy
 		 * rp-filter when calling ip_route_input. */
-		fl.fl4_dst = iph->saddr;
-		if (ip_route_output_key(net, &rt, &fl) != 0)
+		fl4.daddr = iph->saddr;
+		rt = ip_route_output_key(net, &fl4);
+		if (IS_ERR(rt))
 			return -1;
 
 		orefdst = skb->_skb_refdst;
@@ -66,10 +68,11 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
 
 #ifdef CONFIG_XFRM
 	if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
-	    xfrm_decode_session(skb, &fl, AF_INET) == 0) {
+	    xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) {
 		struct dst_entry *dst = skb_dst(skb);
 		skb_dst_set(skb, NULL);
-		if (xfrm_lookup(net, &dst, &fl, skb->sk, 0))
+		dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0);
+		if (IS_ERR(dst))
 			return -1;
 		skb_dst_set(skb, dst);
 	}
@@ -102,7 +105,8 @@ int ip_xfrm_me_harder(struct sk_buff *skb)
 		dst = ((struct xfrm_dst *)dst)->route;
 	dst_hold(dst);
 
-	if (xfrm_lookup(dev_net(dst->dev), &dst, &fl, skb->sk, 0) < 0)
+	dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
+	if (IS_ERR(dst))
 		return -1;
 
 	skb_dst_drop(skb);
@@ -219,7 +223,11 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
 
 static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
 {
-	return ip_route_output_key(&init_net, (struct rtable **)dst, fl);
+	struct rtable *rt = ip_route_output_key(&init_net, &fl->u.ip4);
+	if (IS_ERR(rt))
+		return PTR_ERR(rt);
+	*dst = &rt->dst;
+	return 0;
 }
 
 static const struct nf_afinfo nf_ip_afinfo = {
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index babd1a2..1dfc18a 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -64,16 +64,6 @@ config IP_NF_IPTABLES
 if IP_NF_IPTABLES
 
 # The matches.
-config IP_NF_MATCH_ADDRTYPE
-	tristate '"addrtype" address type match support'
-	depends on NETFILTER_ADVANCED
-	help
-	  This option allows you to match what routing thinks of an address,
-	  eg. UNICAST, LOCAL, BROADCAST, ...
-
-	  If you want to compile it as a module, say M here and read
-	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
-
 config IP_NF_MATCH_AH
 	tristate '"ah" match support'
 	depends on NETFILTER_ADVANCED
@@ -206,8 +196,9 @@ config IP_NF_TARGET_REDIRECT
 
 config NF_NAT_SNMP_BASIC
 	tristate "Basic SNMP-ALG support"
-	depends on NF_NAT
+	depends on NF_CONNTRACK_SNMP && NF_NAT
 	depends on NETFILTER_ADVANCED
+	default NF_NAT && NF_CONNTRACK_SNMP
 	---help---
 
 	  This module implements an Application Layer Gateway (ALG) for
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 19eb59d..dca2082 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -48,7 +48,6 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
 
 # matches
-obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
 
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e855fff..4b5d457 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -866,6 +866,7 @@ static int compat_table_info(const struct xt_table_info *info,
 	memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
 	newinfo->initial_entries = 0;
 	loc_cpu_entry = info->entries[raw_smp_processor_id()];
+	xt_compat_init_offsets(NFPROTO_ARP, info->number);
 	xt_entry_foreach(iter, loc_cpu_entry, info->size) {
 		ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
 		if (ret != 0)
@@ -1065,6 +1066,7 @@ static int do_replace(struct net *net, const void __user *user,
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1333,6 +1335,7 @@ static int translate_compat_table(const char *name,
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(NFPROTO_ARP);
+	xt_compat_init_offsets(NFPROTO_ARP, number);
 	/* Walk through entries, checking offsets. */
 	xt_entry_foreach(iter0, entry0, total_size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
@@ -1486,6 +1489,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1738,6 +1742,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
 							 rev.revision, 1, &ret),
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 652efea..ffcea0d 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -387,7 +387,7 @@ ipt_do_table(struct sk_buff *skb,
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
-				if (*stackptr == 0) {
+				if (*stackptr <= origptr) {
 					e = get_entry(table_base,
 					    private->underflow[hook]);
 					pr_debug("Underflow (this is normal) "
@@ -427,10 +427,10 @@ ipt_do_table(struct sk_buff *skb,
 			/* Verdict */
 			break;
 	} while (!acpar.hotdrop);
-	xt_info_rdunlock_bh();
 	pr_debug("Exiting %s; resetting sp from %u to %u\n",
 		 __func__, *stackptr, origptr);
 	*stackptr = origptr;
+	xt_info_rdunlock_bh();
 #ifdef DEBUG_ALLOW_ALL
 	return NF_ACCEPT;
 #else
@@ -1063,6 +1063,7 @@ static int compat_table_info(const struct xt_table_info *info,
 	memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
 	newinfo->initial_entries = 0;
 	loc_cpu_entry = info->entries[raw_smp_processor_id()];
+	xt_compat_init_offsets(AF_INET, info->number);
 	xt_entry_foreach(iter, loc_cpu_entry, info->size) {
 		ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
 		if (ret != 0)
@@ -1261,6 +1262,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1664,6 +1666,7 @@ translate_compat_table(struct net *net,
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(AF_INET);
+	xt_compat_init_offsets(AF_INET, number);
 	/* Walk through entries, checking offsets. */
 	xt_entry_foreach(iter0, entry0, total_size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
@@ -1805,6 +1808,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -2034,6 +2038,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		if (cmd == IPT_SO_GET_REVISION_TARGET)
 			target = 1;
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 1e26a48..d609ac3 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -300,13 +300,8 @@ clusterip_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	 * that the ->target() function isn't called after ->destroy() */
 
 	ct = nf_ct_get(skb, &ctinfo);
-	if (ct == NULL) {
-		pr_info("no conntrack!\n");
-			/* FIXME: need to drop invalid ones, since replies
-			 * to outgoing connections of other nodes will be
-			 * marked as INVALID */
+	if (ct == NULL)
 		return NF_DROP;
-	}
 
 	/* special case: ICMP error handling. conntrack distinguishes between
 	 * error messages (RELATED) and information requests (see below) */
@@ -669,8 +664,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
 	char buffer[PROC_WRITELEN+1];
 	unsigned long nodenum;
 
-	if (copy_from_user(buffer, input, PROC_WRITELEN))
+	if (size > PROC_WRITELEN)
+		return -EIO;
+	if (copy_from_user(buffer, input, size))
 		return -EFAULT;
+	buffer[size] = 0;
 
 	if (*buffer == '+') {
 		nodenum = simple_strtoul(buffer+1, NULL, 10);
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 72ffc8f..d76d6c9 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -442,8 +442,7 @@ ipt_log_packet(u_int8_t pf,
 	}
 #endif
 
-	/* MAC logging for input path only. */
-	if (in && !out)
+	if (in != NULL)
 		dump_mac_header(m, loginfo, skb);
 
 	dump_packet(m, loginfo, skb, 0);
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c
deleted file mode 100644
index db8bff0..0000000
--- a/net/ipv4/netfilter/ipt_addrtype.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *  iptables module to match inet_addr_type() of an ip.
- *
- *  Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
- *  (C) 2007 Laszlo Attila Toth <panther@balabit.hu>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ip.h>
-#include <net/route.h>
-
-#include <linux/netfilter_ipv4/ipt_addrtype.h>
-#include <linux/netfilter/x_tables.h>
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
-MODULE_DESCRIPTION("Xtables: address type match for IPv4");
-
-static inline bool match_type(struct net *net, const struct net_device *dev,
-			      __be32 addr, u_int16_t mask)
-{
-	return !!(mask & (1 << inet_dev_addr_type(net, dev, addr)));
-}
-
-static bool
-addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
-{
-	struct net *net = dev_net(par->in ? par->in : par->out);
-	const struct ipt_addrtype_info *info = par->matchinfo;
-	const struct iphdr *iph = ip_hdr(skb);
-	bool ret = true;
-
-	if (info->source)
-		ret &= match_type(net, NULL, iph->saddr, info->source) ^
-		       info->invert_source;
-	if (info->dest)
-		ret &= match_type(net, NULL, iph->daddr, info->dest) ^
-		       info->invert_dest;
-
-	return ret;
-}
-
-static bool
-addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
-{
-	struct net *net = dev_net(par->in ? par->in : par->out);
-	const struct ipt_addrtype_info_v1 *info = par->matchinfo;
-	const struct iphdr *iph = ip_hdr(skb);
-	const struct net_device *dev = NULL;
-	bool ret = true;
-
-	if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN)
-		dev = par->in;
-	else if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT)
-		dev = par->out;
-
-	if (info->source)
-		ret &= match_type(net, dev, iph->saddr, info->source) ^
-		       (info->flags & IPT_ADDRTYPE_INVERT_SOURCE);
-	if (ret && info->dest)
-		ret &= match_type(net, dev, iph->daddr, info->dest) ^
-		       !!(info->flags & IPT_ADDRTYPE_INVERT_DEST);
-	return ret;
-}
-
-static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
-{
-	struct ipt_addrtype_info_v1 *info = par->matchinfo;
-
-	if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN &&
-	    info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
-		pr_info("both incoming and outgoing "
-			"interface limitation cannot be selected\n");
-		return -EINVAL;
-	}
-
-	if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
-	    (1 << NF_INET_LOCAL_IN)) &&
-	    info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
-		pr_info("output interface limitation "
-			"not valid in PREROUTING and INPUT\n");
-		return -EINVAL;
-	}
-
-	if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
-	    (1 << NF_INET_LOCAL_OUT)) &&
-	    info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
-		pr_info("input interface limitation "
-			"not valid in POSTROUTING and OUTPUT\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct xt_match addrtype_mt_reg[] __read_mostly = {
-	{
-		.name		= "addrtype",
-		.family		= NFPROTO_IPV4,
-		.match		= addrtype_mt_v0,
-		.matchsize	= sizeof(struct ipt_addrtype_info),
-		.me		= THIS_MODULE
-	},
-	{
-		.name		= "addrtype",
-		.family		= NFPROTO_IPV4,
-		.revision	= 1,
-		.match		= addrtype_mt_v1,
-		.checkentry	= addrtype_mt_checkentry_v1,
-		.matchsize	= sizeof(struct ipt_addrtype_info_v1),
-		.me		= THIS_MODULE
-	}
-};
-
-static int __init addrtype_mt_init(void)
-{
-	return xt_register_matches(addrtype_mt_reg,
-				   ARRAY_SIZE(addrtype_mt_reg));
-}
-
-static void __exit addrtype_mt_exit(void)
-{
-	xt_unregister_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
-}
-
-module_init(addrtype_mt_init);
-module_exit(addrtype_mt_exit);
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 294a2a3..aef5d1f 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -60,7 +60,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct net_device *out)
 	ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, NULL, out,
 			   dev_net(out)->ipv4.iptable_mangle);
 	/* Reroute for ANY change. */
-	if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
+	if (ret != NF_DROP && ret != NF_STOLEN) {
 		iph = ip_hdr(skb);
 
 		if (iph->saddr != saddr ||
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
index 63f60fc..5585980 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c
@@ -20,6 +20,7 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_acct.h>
+#include <linux/rculist_nulls.h>
 
 struct ct_iter_state {
 	struct seq_net_private p;
@@ -35,7 +36,8 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
 	for (st->bucket = 0;
 	     st->bucket < net->ct.htable_size;
 	     st->bucket++) {
-		n = rcu_dereference(net->ct.hash[st->bucket].first);
+		n = rcu_dereference(
+			hlist_nulls_first_rcu(&net->ct.hash[st->bucket]));
 		if (!is_a_nulls(n))
 			return n;
 	}
@@ -48,13 +50,14 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
 	struct net *net = seq_file_net(seq);
 	struct ct_iter_state *st = seq->private;
 
-	head = rcu_dereference(head->next);
+	head = rcu_dereference(hlist_nulls_next_rcu(head));
 	while (is_a_nulls(head)) {
 		if (likely(get_nulls_value(head) == st->bucket)) {
 			if (++st->bucket >= net->ct.htable_size)
 				return NULL;
 		}
-		head = rcu_dereference(net->ct.hash[st->bucket].first);
+		head = rcu_dereference(
+			hlist_nulls_first_rcu(&net->ct.hash[st->bucket]));
 	}
 	return head;
 }
@@ -217,7 +220,8 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 	struct hlist_node *n;
 
 	for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
-		n = rcu_dereference(net->ct.expect_hash[st->bucket].first);
+		n = rcu_dereference(
+			hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
 		if (n)
 			return n;
 	}
@@ -230,11 +234,12 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
 	struct net *net = seq_file_net(seq);
 	struct ct_expect_iter_state *st = seq->private;
 
-	head = rcu_dereference(head->next);
+	head = rcu_dereference(hlist_next_rcu(head));
 	while (head == NULL) {
 		if (++st->bucket >= nf_ct_expect_hsize)
 			return NULL;
-		head = rcu_dereference(net->ct.expect_hash[st->bucket].first);
+		head = rcu_dereference(
+			hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
 	}
 	return head;
 }
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/ipv4/netfilter/nf_nat_amanda.c
index 0f23b3f..703f366f 100644
--- a/net/ipv4/netfilter/nf_nat_amanda.c
+++ b/net/ipv4/netfilter/nf_nat_amanda.c
@@ -44,13 +44,13 @@ static unsigned int help(struct sk_buff *skb,
 
 	/* Try to get same port: if not, try to change it. */
 	for (port = ntohs(exp->saved_proto.tcp.port); port != 0; port++) {
-		int ret;
+		int res;
 
 		exp->tuple.dst.u.tcp.port = htons(port);
-		ret = nf_ct_expect_related(exp);
-		if (ret == 0)
+		res = nf_ct_expect_related(exp);
+		if (res == 0)
 			break;
-		else if (ret != -EBUSY) {
+		else if (res != -EBUSY) {
 			port = 0;
 			break;
 		}
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index c04787c..21bcf47 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -221,7 +221,14 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
 	   manips not an issue.  */
 	if (maniptype == IP_NAT_MANIP_SRC &&
 	    !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
-		if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) {
+		/* try the original tuple first */
+		if (in_range(orig_tuple, range)) {
+			if (!nf_nat_used_tuple(orig_tuple, ct)) {
+				*tuple = *orig_tuple;
+				return;
+			}
+		} else if (find_appropriate_src(net, zone, orig_tuple, tuple,
+			   range)) {
 			pr_debug("get_unique_tuple: Found current src map\n");
 			if (!nf_nat_used_tuple(tuple, ct))
 				return;
@@ -266,7 +273,6 @@ nf_nat_setup_info(struct nf_conn *ct,
 	struct net *net = nf_ct_net(ct);
 	struct nf_conntrack_tuple curr_tuple, new_tuple;
 	struct nf_conn_nat *nat;
-	int have_to_hash = !(ct->status & IPS_NAT_DONE_MASK);
 
 	/* nat helper or nfctnetlink also setup binding */
 	nat = nfct_nat(ct);
@@ -306,8 +312,7 @@ nf_nat_setup_info(struct nf_conn *ct,
 			ct->status |= IPS_DST_NAT;
 	}
 
-	/* Place in source hash if this is the first time. */
-	if (have_to_hash) {
+	if (maniptype == IP_NAT_MANIP_SRC) {
 		unsigned int srchash;
 
 		srchash = hash_by_src(net, nf_ct_zone(ct),
@@ -323,9 +328,9 @@ nf_nat_setup_info(struct nf_conn *ct,
 
 	/* It's done. */
 	if (maniptype == IP_NAT_MANIP_DST)
-		set_bit(IPS_DST_NAT_DONE_BIT, &ct->status);
+		ct->status |= IPS_DST_NAT_DONE;
 	else
-		set_bit(IPS_SRC_NAT_DONE_BIT, &ct->status);
+		ct->status |= IPS_SRC_NAT_DONE;
 
 	return NF_ACCEPT;
 }
@@ -502,7 +507,10 @@ int nf_nat_protocol_register(const struct nf_nat_protocol *proto)
 	int ret = 0;
 
 	spin_lock_bh(&nf_nat_lock);
-	if (nf_nat_protos[proto->protonum] != &nf_nat_unknown_protocol) {
+	if (rcu_dereference_protected(
+			nf_nat_protos[proto->protonum],
+			lockdep_is_held(&nf_nat_lock)
+			) != &nf_nat_unknown_protocol) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -532,7 +540,7 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
 	if (nat == NULL || nat->ct == NULL)
 		return;
 
-	NF_CT_ASSERT(nat->ct->status & IPS_NAT_DONE_MASK);
+	NF_CT_ASSERT(nat->ct->status & IPS_SRC_NAT_DONE);
 
 	spin_lock_bh(&nf_nat_lock);
 	hlist_del_rcu(&nat->bysource);
@@ -545,11 +553,10 @@ static void nf_nat_move_storage(void *new, void *old)
 	struct nf_conn_nat *old_nat = old;
 	struct nf_conn *ct = old_nat->ct;
 
-	if (!ct || !(ct->status & IPS_NAT_DONE_MASK))
+	if (!ct || !(ct->status & IPS_SRC_NAT_DONE))
 		return;
 
 	spin_lock_bh(&nf_nat_lock);
-	new_nat->ct = ct;
 	hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource);
 	spin_unlock_bh(&nf_nat_lock);
 }
@@ -679,8 +686,7 @@ static int __net_init nf_nat_net_init(struct net *net)
 {
 	/* Leave them the same for the moment. */
 	net->ipv4.nat_htable_size = net->ct.htable_size;
-	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&net->ipv4.nat_htable_size,
-						       &net->ipv4.nat_vmalloced, 0);
+	net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&net->ipv4.nat_htable_size, 0);
 	if (!net->ipv4.nat_bysource)
 		return -ENOMEM;
 	return 0;
@@ -702,8 +708,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
 {
 	nf_ct_iterate_cleanup(net, &clean_nat, NULL);
 	synchronize_rcu();
-	nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_vmalloced,
-			     net->ipv4.nat_htable_size);
+	nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_htable_size);
 }
 
 static struct pernet_operations nf_nat_net_ops = {
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index ee5f419..8812a02 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -54,6 +54,7 @@
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_nat_helper.h>
+#include <linux/netfilter/nf_conntrack_snmp.h>
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
@@ -1310,9 +1311,9 @@ static int __init nf_nat_snmp_basic_init(void)
 {
 	int ret = 0;
 
-	ret = nf_conntrack_helper_register(&snmp_helper);
-	if (ret < 0)
-		return ret;
+	BUG_ON(nf_nat_snmp_hook != NULL);
+	rcu_assign_pointer(nf_nat_snmp_hook, help);
+
 	ret = nf_conntrack_helper_register(&snmp_trap_helper);
 	if (ret < 0) {
 		nf_conntrack_helper_unregister(&snmp_helper);
@@ -1323,7 +1324,7 @@ static int __init nf_nat_snmp_basic_init(void)
 
 static void __exit nf_nat_snmp_basic_fini(void)
 {
-	nf_conntrack_helper_unregister(&snmp_helper);
+	rcu_assign_pointer(nf_nat_snmp_hook, NULL);
 	nf_conntrack_helper_unregister(&snmp_trap_helper);
 }
 
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 95481fe..7317bdf 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -31,6 +31,7 @@
 #ifdef CONFIG_XFRM
 static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 {
+	struct flowi4 *fl4 = &fl->u.ip4;
 	const struct nf_conn *ct;
 	const struct nf_conntrack_tuple *t;
 	enum ip_conntrack_info ctinfo;
@@ -49,25 +50,25 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
 		statusbit = IPS_SRC_NAT;
 
 	if (ct->status & statusbit) {
-		fl->fl4_dst = t->dst.u3.ip;
+		fl4->daddr = t->dst.u3.ip;
 		if (t->dst.protonum == IPPROTO_TCP ||
 		    t->dst.protonum == IPPROTO_UDP ||
 		    t->dst.protonum == IPPROTO_UDPLITE ||
 		    t->dst.protonum == IPPROTO_DCCP ||
 		    t->dst.protonum == IPPROTO_SCTP)
-			fl->fl_ip_dport = t->dst.u.tcp.port;
+			fl4->fl4_dport = t->dst.u.tcp.port;
 	}
 
 	statusbit ^= IPS_NAT_MASK;
 
 	if (ct->status & statusbit) {
-		fl->fl4_src = t->src.u3.ip;
+		fl4->saddr = t->src.u3.ip;
 		if (t->dst.protonum == IPPROTO_TCP ||
 		    t->dst.protonum == IPPROTO_UDP ||
 		    t->dst.protonum == IPPROTO_UDPLITE ||
 		    t->dst.protonum == IPPROTO_DCCP ||
 		    t->dst.protonum == IPPROTO_SCTP)
-			fl->fl_ip_sport = t->src.u.tcp.port;
+			fl4->fl4_sport = t->src.u.tcp.port;
 	}
 }
 #endif
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 6390ba2..e837ffd 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -402,7 +402,7 @@ error:
 	return err;
 }
 
-static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+static int raw_probe_proto_opt(struct flowi4 *fl4, struct msghdr *msg)
 {
 	struct iovec *iov;
 	u8 __user *type = NULL;
@@ -418,7 +418,7 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
 		if (!iov)
 			continue;
 
-		switch (fl->proto) {
+		switch (fl4->flowi4_proto) {
 		case IPPROTO_ICMP:
 			/* check if one-byte field is readable or not. */
 			if (iov->iov_base && iov->iov_len < 1)
@@ -433,8 +433,8 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
 				code = iov->iov_base;
 
 			if (type && code) {
-				if (get_user(fl->fl_icmp_type, type) ||
-				    get_user(fl->fl_icmp_code, code))
+				if (get_user(fl4->fl4_icmp_type, type) ||
+				    get_user(fl4->fl4_icmp_code, code))
 					return -EFAULT;
 				probed = 1;
 			}
@@ -548,25 +548,30 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	}
 
 	{
-		struct flowi fl = { .oif = ipc.oif,
-				    .mark = sk->sk_mark,
-				    .fl4_dst = daddr,
-				    .fl4_src = saddr,
-				    .fl4_tos = tos,
-				    .proto = inet->hdrincl ? IPPROTO_RAW :
-							     sk->sk_protocol,
-				  };
+		struct flowi4 fl4 = {
+			.flowi4_oif = ipc.oif,
+			.flowi4_mark = sk->sk_mark,
+			.daddr = daddr,
+			.saddr = saddr,
+			.flowi4_tos = tos,
+			.flowi4_proto = (inet->hdrincl ?
+					 IPPROTO_RAW :
+					 sk->sk_protocol),
+			.flowi4_flags = FLOWI_FLAG_CAN_SLEEP,
+		};
 		if (!inet->hdrincl) {
-			err = raw_probe_proto_opt(&fl, msg);
+			err = raw_probe_proto_opt(&fl4, msg);
 			if (err)
 				goto done;
 		}
 
-		security_sk_classify_flow(sk, &fl);
-		err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 1);
+		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+		rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
+		if (IS_ERR(rt)) {
+			err = PTR_ERR(rt);
+			goto done;
+		}
 	}
-	if (err)
-		goto done;
 
 	err = -EACCES;
 	if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST))
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6ed6603..870b518 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -109,8 +109,8 @@
 #include <linux/sysctl.h>
 #endif
 
-#define RT_FL_TOS(oldflp) \
-    ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
+#define RT_FL_TOS(oldflp4) \
+    ((u32)(oldflp4->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
 
 #define IP_MAX_MTU	0xFFF0
 
@@ -131,9 +131,6 @@ static int ip_rt_min_pmtu __read_mostly		= 512 + 20 + 20;
 static int ip_rt_min_advmss __read_mostly	= 256;
 static int rt_chain_length_max __read_mostly	= 20;
 
-static struct delayed_work expires_work;
-static unsigned long expires_ljiffies;
-
 /*
  *	Interface to generic destination cache.
  */
@@ -152,6 +149,41 @@ static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 {
 }
 
+static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old)
+{
+	struct rtable *rt = (struct rtable *) dst;
+	struct inet_peer *peer;
+	u32 *p = NULL;
+
+	if (!rt->peer)
+		rt_bind_peer(rt, 1);
+
+	peer = rt->peer;
+	if (peer) {
+		u32 *old_p = __DST_METRICS_PTR(old);
+		unsigned long prev, new;
+
+		p = peer->metrics;
+		if (inet_metrics_new(peer))
+			memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
+
+		new = (unsigned long) p;
+		prev = cmpxchg(&dst->_metrics, old, new);
+
+		if (prev != old) {
+			p = __DST_METRICS_PTR(prev);
+			if (prev & DST_METRICS_READ_ONLY)
+				p = NULL;
+		} else {
+			if (rt->fi) {
+				fib_info_put(rt->fi);
+				rt->fi = NULL;
+			}
+		}
+	}
+	return p;
+}
+
 static struct dst_ops ipv4_dst_ops = {
 	.family =		AF_INET,
 	.protocol =		cpu_to_be16(ETH_P_IP),
@@ -159,6 +191,7 @@ static struct dst_ops ipv4_dst_ops = {
 	.check =		ipv4_dst_check,
 	.default_advmss =	ipv4_default_advmss,
 	.default_mtu =		ipv4_default_mtu,
+	.cow_metrics =		ipv4_cow_metrics,
 	.destroy =		ipv4_dst_destroy,
 	.ifdown =		ipv4_dst_ifdown,
 	.negative_advice =	ipv4_negative_advice,
@@ -171,7 +204,7 @@ static struct dst_ops ipv4_dst_ops = {
 
 const __u8 ip_tos2prio[16] = {
 	TC_PRIO_BESTEFFORT,
-	ECN_OR_COST(FILLER),
+	ECN_OR_COST(BESTEFFORT),
 	TC_PRIO_BESTEFFORT,
 	ECN_OR_COST(BESTEFFORT),
 	TC_PRIO_BULK,
@@ -391,7 +424,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
 			dst_metric(&r->dst, RTAX_WINDOW),
 			(int)((dst_metric(&r->dst, RTAX_RTT) >> 3) +
 			      dst_metric(&r->dst, RTAX_RTTVAR)),
-			r->fl.fl4_tos,
+			r->rt_tos,
 			r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1,
 			r->dst.hh ? (r->dst.hh->hh_output ==
 				       dev_queue_xmit) : 0,
@@ -514,7 +547,7 @@ static const struct file_operations rt_cpu_seq_fops = {
 	.release = seq_release,
 };
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 static int rt_acct_proc_show(struct seq_file *m, void *v)
 {
 	struct ip_rt_acct *dst, *src;
@@ -567,14 +600,14 @@ static int __net_init ip_rt_do_proc_init(struct net *net)
 	if (!pde)
 		goto err2;
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	pde = proc_create("rt_acct", 0, net->proc_net, &rt_acct_proc_fops);
 	if (!pde)
 		goto err3;
 #endif
 	return 0;
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 err3:
 	remove_proc_entry("rt_cache", net->proc_net_stat);
 #endif
@@ -588,7 +621,7 @@ static void __net_exit ip_rt_do_proc_exit(struct net *net)
 {
 	remove_proc_entry("rt_cache", net->proc_net_stat);
 	remove_proc_entry("rt_cache", net->proc_net);
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	remove_proc_entry("rt_acct", net->proc_net);
 #endif
 }
@@ -632,7 +665,7 @@ static inline int rt_fast_clean(struct rtable *rth)
 static inline int rt_valuable(struct rtable *rth)
 {
 	return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
-		rth->dst.expires;
+		(rth->peer && rth->peer->pmtu_expires);
 }
 
 static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
@@ -643,13 +676,7 @@ static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long t
 	if (atomic_read(&rth->dst.__refcnt))
 		goto out;
 
-	ret = 1;
-	if (rth->dst.expires &&
-	    time_after_eq(jiffies, rth->dst.expires))
-		goto out;
-
 	age = jiffies - rth->dst.lastuse;
-	ret = 0;
 	if ((age <= tmo1 && !rt_fast_clean(rth)) ||
 	    (age <= tmo2 && rt_valuable(rth)))
 		goto out;
@@ -684,22 +711,22 @@ static inline bool rt_caching(const struct net *net)
 		net->ipv4.sysctl_rt_cache_rebuild_count;
 }
 
-static inline bool compare_hash_inputs(const struct flowi *fl1,
-					const struct flowi *fl2)
+static inline bool compare_hash_inputs(const struct rtable *rt1,
+				       const struct rtable *rt2)
 {
-	return ((((__force u32)fl1->fl4_dst ^ (__force u32)fl2->fl4_dst) |
-		((__force u32)fl1->fl4_src ^ (__force u32)fl2->fl4_src) |
-		(fl1->iif ^ fl2->iif)) == 0);
+	return ((((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) |
+		((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
+		(rt1->rt_iif ^ rt2->rt_iif)) == 0);
 }
 
-static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
+static inline int compare_keys(struct rtable *rt1, struct rtable *rt2)
 {
-	return (((__force u32)fl1->fl4_dst ^ (__force u32)fl2->fl4_dst) |
-		((__force u32)fl1->fl4_src ^ (__force u32)fl2->fl4_src) |
-		(fl1->mark ^ fl2->mark) |
-		(*(u16 *)&fl1->fl4_tos ^ *(u16 *)&fl2->fl4_tos) |
-		(fl1->oif ^ fl2->oif) |
-		(fl1->iif ^ fl2->iif)) == 0;
+	return (((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) |
+		((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) |
+		(rt1->rt_mark ^ rt2->rt_mark) |
+		(rt1->rt_tos ^ rt2->rt_tos) |
+		(rt1->rt_oif ^ rt2->rt_oif) |
+		(rt1->rt_iif ^ rt2->rt_iif)) == 0;
 }
 
 static inline int compare_netns(struct rtable *rt1, struct rtable *rt2)
@@ -786,104 +813,13 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth)
 	const struct rtable *aux = head;
 
 	while (aux != rth) {
-		if (compare_hash_inputs(&aux->fl, &rth->fl))
+		if (compare_hash_inputs(aux, rth))
 			return 0;
 		aux = rcu_dereference_protected(aux->dst.rt_next, 1);
 	}
 	return ONE;
 }
 
-static void rt_check_expire(void)
-{
-	static unsigned int rover;
-	unsigned int i = rover, goal;
-	struct rtable *rth;
-	struct rtable __rcu **rthp;
-	unsigned long samples = 0;
-	unsigned long sum = 0, sum2 = 0;
-	unsigned long delta;
-	u64 mult;
-
-	delta = jiffies - expires_ljiffies;
-	expires_ljiffies = jiffies;
-	mult = ((u64)delta) << rt_hash_log;
-	if (ip_rt_gc_timeout > 1)
-		do_div(mult, ip_rt_gc_timeout);
-	goal = (unsigned int)mult;
-	if (goal > rt_hash_mask)
-		goal = rt_hash_mask + 1;
-	for (; goal > 0; goal--) {
-		unsigned long tmo = ip_rt_gc_timeout;
-		unsigned long length;
-
-		i = (i + 1) & rt_hash_mask;
-		rthp = &rt_hash_table[i].chain;
-
-		if (need_resched())
-			cond_resched();
-
-		samples++;
-
-		if (rcu_dereference_raw(*rthp) == NULL)
-			continue;
-		length = 0;
-		spin_lock_bh(rt_hash_lock_addr(i));
-		while ((rth = rcu_dereference_protected(*rthp,
-					lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) {
-			prefetch(rth->dst.rt_next);
-			if (rt_is_expired(rth)) {
-				*rthp = rth->dst.rt_next;
-				rt_free(rth);
-				continue;
-			}
-			if (rth->dst.expires) {
-				/* Entry is expired even if it is in use */
-				if (time_before_eq(jiffies, rth->dst.expires)) {
-nofree:
-					tmo >>= 1;
-					rthp = &rth->dst.rt_next;
-					/*
-					 * We only count entries on
-					 * a chain with equal hash inputs once
-					 * so that entries for different QOS
-					 * levels, and other non-hash input
-					 * attributes don't unfairly skew
-					 * the length computation
-					 */
-					length += has_noalias(rt_hash_table[i].chain, rth);
-					continue;
-				}
-			} else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout))
-				goto nofree;
-
-			/* Cleanup aged off entries. */
-			*rthp = rth->dst.rt_next;
-			rt_free(rth);
-		}
-		spin_unlock_bh(rt_hash_lock_addr(i));
-		sum += length;
-		sum2 += length*length;
-	}
-	if (samples) {
-		unsigned long avg = sum / samples;
-		unsigned long sd = int_sqrt(sum2 / samples - avg*avg);
-		rt_chain_length_max = max_t(unsigned long,
-					ip_rt_gc_elasticity,
-					(avg + 4*sd) >> FRACT_BITS);
-	}
-	rover = i;
-}
-
-/*
- * rt_worker_func() is run in process context.
- * we call rt_check_expire() to scan part of the hash table
- */
-static void rt_worker_func(struct work_struct *work)
-{
-	rt_check_expire();
-	schedule_delayed_work(&expires_work, ip_rt_gc_interval);
-}
-
 /*
  * Pertubation of rt_genid by a small quantity [1..256]
  * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
@@ -1078,8 +1014,8 @@ static int slow_chain_length(const struct rtable *head)
 	return length >> FRACT_BITS;
 }
 
-static int rt_intern_hash(unsigned hash, struct rtable *rt,
-			  struct rtable **rp, struct sk_buff *skb, int ifindex)
+static struct rtable *rt_intern_hash(unsigned hash, struct rtable *rt,
+				     struct sk_buff *skb, int ifindex)
 {
 	struct rtable	*rth, *cand;
 	struct rtable __rcu **rthp, **candp;
@@ -1120,7 +1056,7 @@ restart:
 					printk(KERN_WARNING
 					    "Neighbour table failure & not caching routes.\n");
 				ip_rt_put(rt);
-				return err;
+				return ERR_PTR(err);
 			}
 		}
 
@@ -1137,7 +1073,7 @@ restart:
 			rt_free(rth);
 			continue;
 		}
-		if (compare_keys(&rth->fl, &rt->fl) && compare_netns(rth, rt)) {
+		if (compare_keys(rth, rt) && compare_netns(rth, rt)) {
 			/* Put it first */
 			*rthp = rth->dst.rt_next;
 			/*
@@ -1157,11 +1093,9 @@ restart:
 			spin_unlock_bh(rt_hash_lock_addr(hash));
 
 			rt_drop(rt);
-			if (rp)
-				*rp = rth;
-			else
+			if (skb)
 				skb_dst_set(skb, &rth->dst);
-			return 0;
+			return rth;
 		}
 
 		if (!atomic_read(&rth->dst.__refcnt)) {
@@ -1202,7 +1136,7 @@ restart:
 			rt_emergency_hash_rebuild(net);
 			spin_unlock_bh(rt_hash_lock_addr(hash));
 
-			hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
+			hash = rt_hash(rt->rt_key_dst, rt->rt_key_src,
 					ifindex, rt_genid(net));
 			goto restart;
 		}
@@ -1218,7 +1152,7 @@ restart:
 
 			if (err != -ENOBUFS) {
 				rt_drop(rt);
-				return err;
+				return ERR_PTR(err);
 			}
 
 			/* Neighbour tables are full and nothing
@@ -1239,7 +1173,7 @@ restart:
 			if (net_ratelimit())
 				printk(KERN_WARNING "ipv4: Neighbour table overflow.\n");
 			rt_drop(rt);
-			return -ENOBUFS;
+			return ERR_PTR(-ENOBUFS);
 		}
 	}
 
@@ -1265,11 +1199,16 @@ restart:
 	spin_unlock_bh(rt_hash_lock_addr(hash));
 
 skip_hashing:
-	if (rp)
-		*rp = rt;
-	else
+	if (skb)
 		skb_dst_set(skb, &rt->dst);
-	return 0;
+	return rt;
+}
+
+static atomic_t __rt_peer_genid = ATOMIC_INIT(0);
+
+static u32 rt_peer_genid(void)
+{
+	return atomic_read(&__rt_peer_genid);
 }
 
 void rt_bind_peer(struct rtable *rt, int create)
@@ -1280,6 +1219,8 @@ void rt_bind_peer(struct rtable *rt, int create)
 
 	if (peer && cmpxchg(&rt->peer, NULL, peer) != NULL)
 		inet_putpeer(peer);
+	else
+		rt->rt_peer_genid = rt_peer_genid();
 }
 
 /*
@@ -1349,13 +1290,8 @@ static void rt_del(unsigned hash, struct rtable *rt)
 void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
 		    __be32 saddr, struct net_device *dev)
 {
-	int i, k;
 	struct in_device *in_dev = __in_dev_get_rcu(dev);
-	struct rtable *rth;
-	struct rtable __rcu **rthp;
-	__be32  skeys[2] = { saddr, 0 };
-	int  ikeys[2] = { dev->ifindex, 0 };
-	struct netevent_redirect netevent;
+	struct inet_peer *peer;
 	struct net *net;
 
 	if (!in_dev)
@@ -1367,9 +1303,6 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
 	    ipv4_is_zeronet(new_gw))
 		goto reject_redirect;
 
-	if (!rt_caching(net))
-		goto reject_redirect;
-
 	if (!IN_DEV_SHARED_MEDIA(in_dev)) {
 		if (!inet_addr_onlink(in_dev, new_gw, old_gw))
 			goto reject_redirect;
@@ -1380,91 +1313,13 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
 			goto reject_redirect;
 	}
 
-	for (i = 0; i < 2; i++) {
-		for (k = 0; k < 2; k++) {
-			unsigned hash = rt_hash(daddr, skeys[i], ikeys[k],
-						rt_genid(net));
-
-			rthp = &rt_hash_table[hash].chain;
-
-			while ((rth = rcu_dereference(*rthp)) != NULL) {
-				struct rtable *rt;
-
-				if (rth->fl.fl4_dst != daddr ||
-				    rth->fl.fl4_src != skeys[i] ||
-				    rth->fl.oif != ikeys[k] ||
-				    rt_is_input_route(rth) ||
-				    rt_is_expired(rth) ||
-				    !net_eq(dev_net(rth->dst.dev), net)) {
-					rthp = &rth->dst.rt_next;
-					continue;
-				}
-
-				if (rth->rt_dst != daddr ||
-				    rth->rt_src != saddr ||
-				    rth->dst.error ||
-				    rth->rt_gateway != old_gw ||
-				    rth->dst.dev != dev)
-					break;
-
-				dst_hold(&rth->dst);
-
-				rt = dst_alloc(&ipv4_dst_ops);
-				if (rt == NULL) {
-					ip_rt_put(rth);
-					return;
-				}
-
-				/* Copy all the information. */
-				*rt = *rth;
-				rt->dst.__use		= 1;
-				atomic_set(&rt->dst.__refcnt, 1);
-				rt->dst.child		= NULL;
-				if (rt->dst.dev)
-					dev_hold(rt->dst.dev);
-				rt->dst.obsolete	= -1;
-				rt->dst.lastuse	= jiffies;
-				rt->dst.path		= &rt->dst;
-				rt->dst.neighbour	= NULL;
-				rt->dst.hh		= NULL;
-#ifdef CONFIG_XFRM
-				rt->dst.xfrm		= NULL;
-#endif
-				rt->rt_genid		= rt_genid(net);
-				rt->rt_flags		|= RTCF_REDIRECTED;
-
-				/* Gateway is different ... */
-				rt->rt_gateway		= new_gw;
-
-				/* Redirect received -> path was valid */
-				dst_confirm(&rth->dst);
-
-				if (rt->peer)
-					atomic_inc(&rt->peer->refcnt);
-
-				if (arp_bind_neighbour(&rt->dst) ||
-				    !(rt->dst.neighbour->nud_state &
-					    NUD_VALID)) {
-					if (rt->dst.neighbour)
-						neigh_event_send(rt->dst.neighbour, NULL);
-					ip_rt_put(rth);
-					rt_drop(rt);
-					goto do_next;
-				}
+	peer = inet_getpeer_v4(daddr, 1);
+	if (peer) {
+		peer->redirect_learned.a4 = new_gw;
 
-				netevent.old = &rth->dst;
-				netevent.new = &rt->dst;
-				call_netevent_notifiers(NETEVENT_REDIRECT,
-							&netevent);
+		inet_putpeer(peer);
 
-				rt_del(hash, rth);
-				if (!rt_intern_hash(hash, rt, &rt, NULL, rt->fl.oif))
-					ip_rt_put(rt);
-				goto do_next;
-			}
-		do_next:
-			;
-		}
+		atomic_inc(&__rt_peer_genid);
 	}
 	return;
 
@@ -1488,18 +1343,24 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 		if (dst->obsolete > 0) {
 			ip_rt_put(rt);
 			ret = NULL;
-		} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
-			   (rt->dst.expires &&
-			    time_after_eq(jiffies, rt->dst.expires))) {
-			unsigned hash = rt_hash(rt->fl.fl4_dst, rt->fl.fl4_src,
-						rt->fl.oif,
+		} else if (rt->rt_flags & RTCF_REDIRECTED) {
+			unsigned hash = rt_hash(rt->rt_key_dst, rt->rt_key_src,
+						rt->rt_oif,
 						rt_genid(dev_net(dst->dev)));
 #if RT_CACHE_DEBUG >= 1
 			printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n",
-				&rt->rt_dst, rt->fl.fl4_tos);
+				&rt->rt_dst, rt->rt_tos);
 #endif
 			rt_del(hash, rt);
 			ret = NULL;
+		} else if (rt->peer &&
+			   rt->peer->pmtu_expires &&
+			   time_after_eq(jiffies, rt->peer->pmtu_expires)) {
+			unsigned long orig = rt->peer->pmtu_expires;
+
+			if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig)
+				dst_metric_set(dst, RTAX_MTU,
+					       rt->peer->pmtu_orig);
 		}
 	}
 	return ret;
@@ -1525,6 +1386,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 {
 	struct rtable *rt = skb_rtable(skb);
 	struct in_device *in_dev;
+	struct inet_peer *peer;
 	int log_martians;
 
 	rcu_read_lock();
@@ -1536,33 +1398,41 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 	log_martians = IN_DEV_LOG_MARTIANS(in_dev);
 	rcu_read_unlock();
 
+	if (!rt->peer)
+		rt_bind_peer(rt, 1);
+	peer = rt->peer;
+	if (!peer) {
+		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
+		return;
+	}
+
 	/* No redirected packets during ip_rt_redirect_silence;
 	 * reset the algorithm.
 	 */
-	if (time_after(jiffies, rt->dst.rate_last + ip_rt_redirect_silence))
-		rt->dst.rate_tokens = 0;
+	if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence))
+		peer->rate_tokens = 0;
 
 	/* Too many ignored redirects; do not send anything
 	 * set dst.rate_last to the last seen redirected packet.
 	 */
-	if (rt->dst.rate_tokens >= ip_rt_redirect_number) {
-		rt->dst.rate_last = jiffies;
+	if (peer->rate_tokens >= ip_rt_redirect_number) {
+		peer->rate_last = jiffies;
 		return;
 	}
 
 	/* Check for load limit; set rate_last to the latest sent
 	 * redirect.
 	 */
-	if (rt->dst.rate_tokens == 0 ||
+	if (peer->rate_tokens == 0 ||
 	    time_after(jiffies,
-		       (rt->dst.rate_last +
-			(ip_rt_redirect_load << rt->dst.rate_tokens)))) {
+		       (peer->rate_last +
+			(ip_rt_redirect_load << peer->rate_tokens)))) {
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
-		rt->dst.rate_last = jiffies;
-		++rt->dst.rate_tokens;
+		peer->rate_last = jiffies;
+		++peer->rate_tokens;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 		if (log_martians &&
-		    rt->dst.rate_tokens == ip_rt_redirect_number &&
+		    peer->rate_tokens == ip_rt_redirect_number &&
 		    net_ratelimit())
 			printk(KERN_WARNING "host %pI4/if%d ignores redirects for %pI4 to %pI4.\n",
 				&rt->rt_src, rt->rt_iif,
@@ -1574,7 +1444,9 @@ void ip_rt_send_redirect(struct sk_buff *skb)
 static int ip_error(struct sk_buff *skb)
 {
 	struct rtable *rt = skb_rtable(skb);
+	struct inet_peer *peer;
 	unsigned long now;
+	bool send;
 	int code;
 
 	switch (rt->dst.error) {
@@ -1594,15 +1466,24 @@ static int ip_error(struct sk_buff *skb)
 			break;
 	}
 
-	now = jiffies;
-	rt->dst.rate_tokens += now - rt->dst.rate_last;
-	if (rt->dst.rate_tokens > ip_rt_error_burst)
-		rt->dst.rate_tokens = ip_rt_error_burst;
-	rt->dst.rate_last = now;
-	if (rt->dst.rate_tokens >= ip_rt_error_cost) {
-		rt->dst.rate_tokens -= ip_rt_error_cost;
-		icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
+	if (!rt->peer)
+		rt_bind_peer(rt, 1);
+	peer = rt->peer;
+
+	send = true;
+	if (peer) {
+		now = jiffies;
+		peer->rate_tokens += now - peer->rate_last;
+		if (peer->rate_tokens > ip_rt_error_burst)
+			peer->rate_tokens = ip_rt_error_burst;
+		peer->rate_last = now;
+		if (peer->rate_tokens >= ip_rt_error_cost)
+			peer->rate_tokens -= ip_rt_error_cost;
+		else
+			send = false;
 	}
+	if (send)
+		icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
 
 out:	kfree_skb(skb);
 	return 0;
@@ -1630,88 +1511,142 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
 				 unsigned short new_mtu,
 				 struct net_device *dev)
 {
-	int i, k;
 	unsigned short old_mtu = ntohs(iph->tot_len);
-	struct rtable *rth;
-	int  ikeys[2] = { dev->ifindex, 0 };
-	__be32  skeys[2] = { iph->saddr, 0, };
-	__be32  daddr = iph->daddr;
 	unsigned short est_mtu = 0;
+	struct inet_peer *peer;
 
-	for (k = 0; k < 2; k++) {
-		for (i = 0; i < 2; i++) {
-			unsigned hash = rt_hash(daddr, skeys[i], ikeys[k],
-						rt_genid(net));
-
-			rcu_read_lock();
-			for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
-			     rth = rcu_dereference(rth->dst.rt_next)) {
-				unsigned short mtu = new_mtu;
-
-				if (rth->fl.fl4_dst != daddr ||
-				    rth->fl.fl4_src != skeys[i] ||
-				    rth->rt_dst != daddr ||
-				    rth->rt_src != iph->saddr ||
-				    rth->fl.oif != ikeys[k] ||
-				    rt_is_input_route(rth) ||
-				    dst_metric_locked(&rth->dst, RTAX_MTU) ||
-				    !net_eq(dev_net(rth->dst.dev), net) ||
-				    rt_is_expired(rth))
-					continue;
+	peer = inet_getpeer_v4(iph->daddr, 1);
+	if (peer) {
+		unsigned short mtu = new_mtu;
 
-				if (new_mtu < 68 || new_mtu >= old_mtu) {
+		if (new_mtu < 68 || new_mtu >= old_mtu) {
+			/* BSD 4.2 derived systems incorrectly adjust
+			 * tot_len by the IP header length, and report
+			 * a zero MTU in the ICMP message.
+			 */
+			if (mtu == 0 &&
+			    old_mtu >= 68 + (iph->ihl << 2))
+				old_mtu -= iph->ihl << 2;
+			mtu = guess_mtu(old_mtu);
+		}
 
-					/* BSD 4.2 compatibility hack :-( */
-					if (mtu == 0 &&
-					    old_mtu >= dst_mtu(&rth->dst) &&
-					    old_mtu >= 68 + (iph->ihl << 2))
-						old_mtu -= iph->ihl << 2;
+		if (mtu < ip_rt_min_pmtu)
+			mtu = ip_rt_min_pmtu;
+		if (!peer->pmtu_expires || mtu < peer->pmtu_learned) {
+			unsigned long pmtu_expires;
 
-					mtu = guess_mtu(old_mtu);
-				}
-				if (mtu <= dst_mtu(&rth->dst)) {
-					if (mtu < dst_mtu(&rth->dst)) {
-						dst_confirm(&rth->dst);
-						if (mtu < ip_rt_min_pmtu) {
-							u32 lock = dst_metric(&rth->dst,
-									      RTAX_LOCK);
-							mtu = ip_rt_min_pmtu;
-							lock |= (1 << RTAX_MTU);
-							dst_metric_set(&rth->dst, RTAX_LOCK,
-								       lock);
-						}
-						dst_metric_set(&rth->dst, RTAX_MTU, mtu);
-						dst_set_expires(&rth->dst,
-							ip_rt_mtu_expires);
-					}
-					est_mtu = mtu;
-				}
-			}
-			rcu_read_unlock();
+			pmtu_expires = jiffies + ip_rt_mtu_expires;
+			if (!pmtu_expires)
+				pmtu_expires = 1UL;
+
+			est_mtu = mtu;
+			peer->pmtu_learned = mtu;
+			peer->pmtu_expires = pmtu_expires;
 		}
+
+		inet_putpeer(peer);
+
+		atomic_inc(&__rt_peer_genid);
 	}
 	return est_mtu ? : new_mtu;
 }
 
+static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer)
+{
+	unsigned long expires = peer->pmtu_expires;
+
+	if (time_before(jiffies, expires)) {
+		u32 orig_dst_mtu = dst_mtu(dst);
+		if (peer->pmtu_learned < orig_dst_mtu) {
+			if (!peer->pmtu_orig)
+				peer->pmtu_orig = dst_metric_raw(dst, RTAX_MTU);
+			dst_metric_set(dst, RTAX_MTU, peer->pmtu_learned);
+		}
+	} else if (cmpxchg(&peer->pmtu_expires, expires, 0) == expires)
+		dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig);
+}
+
 static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
-	if (dst_mtu(dst) > mtu && mtu >= 68 &&
-	    !(dst_metric_locked(dst, RTAX_MTU))) {
-		if (mtu < ip_rt_min_pmtu) {
-			u32 lock = dst_metric(dst, RTAX_LOCK);
+	struct rtable *rt = (struct rtable *) dst;
+	struct inet_peer *peer;
+
+	dst_confirm(dst);
+
+	if (!rt->peer)
+		rt_bind_peer(rt, 1);
+	peer = rt->peer;
+	if (peer) {
+		if (mtu < ip_rt_min_pmtu)
 			mtu = ip_rt_min_pmtu;
-			dst_metric_set(dst, RTAX_LOCK, lock | (1 << RTAX_MTU));
+		if (!peer->pmtu_expires || mtu < peer->pmtu_learned) {
+			unsigned long pmtu_expires;
+
+			pmtu_expires = jiffies + ip_rt_mtu_expires;
+			if (!pmtu_expires)
+				pmtu_expires = 1UL;
+
+			peer->pmtu_learned = mtu;
+			peer->pmtu_expires = pmtu_expires;
+
+			atomic_inc(&__rt_peer_genid);
+			rt->rt_peer_genid = rt_peer_genid();
 		}
-		dst_metric_set(dst, RTAX_MTU, mtu);
-		dst_set_expires(dst, ip_rt_mtu_expires);
-		call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
+		check_peer_pmtu(dst, peer);
+
+		inet_putpeer(peer);
+	}
+}
+
+static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
+{
+	struct rtable *rt = (struct rtable *) dst;
+	__be32 orig_gw = rt->rt_gateway;
+
+	dst_confirm(&rt->dst);
+
+	neigh_release(rt->dst.neighbour);
+	rt->dst.neighbour = NULL;
+
+	rt->rt_gateway = peer->redirect_learned.a4;
+	if (arp_bind_neighbour(&rt->dst) ||
+	    !(rt->dst.neighbour->nud_state & NUD_VALID)) {
+		if (rt->dst.neighbour)
+			neigh_event_send(rt->dst.neighbour, NULL);
+		rt->rt_gateway = orig_gw;
+		return -EAGAIN;
+	} else {
+		rt->rt_flags |= RTCF_REDIRECTED;
+		call_netevent_notifiers(NETEVENT_NEIGH_UPDATE,
+					rt->dst.neighbour);
 	}
+	return 0;
 }
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
-	if (rt_is_expired((struct rtable *)dst))
+	struct rtable *rt = (struct rtable *) dst;
+
+	if (rt_is_expired(rt))
 		return NULL;
+	if (rt->rt_peer_genid != rt_peer_genid()) {
+		struct inet_peer *peer;
+
+		if (!rt->peer)
+			rt_bind_peer(rt, 0);
+
+		peer = rt->peer;
+		if (peer && peer->pmtu_expires)
+			check_peer_pmtu(dst, peer);
+
+		if (peer && peer->redirect_learned.a4 &&
+		    peer->redirect_learned.a4 != rt->rt_gateway) {
+			if (check_peer_redir(dst, peer))
+				return NULL;
+		}
+
+		rt->rt_peer_genid = rt_peer_genid();
+	}
 	return dst;
 }
 
@@ -1720,6 +1655,10 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
 	struct rtable *rt = (struct rtable *) dst;
 	struct inet_peer *peer = rt->peer;
 
+	if (rt->fi) {
+		fib_info_put(rt->fi);
+		rt->fi = NULL;
+	}
 	if (peer) {
 		rt->peer = NULL;
 		inet_putpeer(peer);
@@ -1734,8 +1673,14 @@ static void ipv4_link_failure(struct sk_buff *skb)
 	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
 
 	rt = skb_rtable(skb);
-	if (rt)
-		dst_set_expires(&rt->dst, 0);
+	if (rt &&
+	    rt->peer &&
+	    rt->peer->pmtu_expires) {
+		unsigned long orig = rt->peer->pmtu_expires;
+
+		if (cmpxchg(&rt->peer->pmtu_expires, orig, 0) == orig)
+			dst_metric_set(&rt->dst, RTAX_MTU, rt->peer->pmtu_orig);
+	}
 }
 
 static int ip_rt_bug(struct sk_buff *skb)
@@ -1764,8 +1709,17 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
 	if (rt_is_output_route(rt))
 		src = rt->rt_src;
 	else {
+		struct flowi4 fl4 = {
+			.daddr = rt->rt_key_dst,
+			.saddr = rt->rt_key_src,
+			.flowi4_tos = rt->rt_tos,
+			.flowi4_oif = rt->rt_oif,
+			.flowi4_iif = rt->rt_iif,
+			.flowi4_mark = rt->rt_mark,
+		};
+
 		rcu_read_lock();
-		if (fib_lookup(dev_net(rt->dst.dev), &rt->fl, &res) == 0)
+		if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0)
 			src = FIB_RES_PREFSRC(res);
 		else
 			src = inet_select_addr(rt->dst.dev, rt->rt_gateway,
@@ -1775,7 +1729,7 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt)
 	memcpy(addr, &src, 4);
 }
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 static void set_class_tag(struct rtable *rt, u32 tag)
 {
 	if (!(rt->dst.tclassid & 0xFFFF))
@@ -1815,17 +1769,54 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst)
 	return mtu;
 }
 
-static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
+static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4,
+			    struct fib_info *fi)
+{
+	struct inet_peer *peer;
+	int create = 0;
+
+	/* If a peer entry exists for this destination, we must hook
+	 * it up in order to get at cached metrics.
+	 */
+	if (oldflp4 && (oldflp4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS))
+		create = 1;
+
+	rt->peer = peer = inet_getpeer_v4(rt->rt_dst, create);
+	if (peer) {
+		rt->rt_peer_genid = rt_peer_genid();
+		if (inet_metrics_new(peer))
+			memcpy(peer->metrics, fi->fib_metrics,
+			       sizeof(u32) * RTAX_MAX);
+		dst_init_metrics(&rt->dst, peer->metrics, false);
+
+		if (peer->pmtu_expires)
+			check_peer_pmtu(&rt->dst, peer);
+		if (peer->redirect_learned.a4 &&
+		    peer->redirect_learned.a4 != rt->rt_gateway) {
+			rt->rt_gateway = peer->redirect_learned.a4;
+			rt->rt_flags |= RTCF_REDIRECTED;
+		}
+	} else {
+		if (fi->fib_metrics != (u32 *) dst_default_metrics) {
+			rt->fi = fi;
+			atomic_inc(&fi->fib_clntref);
+		}
+		dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+	}
+}
+
+static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4,
+			   const struct fib_result *res,
+			   struct fib_info *fi, u16 type, u32 itag)
 {
 	struct dst_entry *dst = &rt->dst;
-	struct fib_info *fi = res->fi;
 
 	if (fi) {
 		if (FIB_RES_GW(*res) &&
 		    FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
 			rt->rt_gateway = FIB_RES_GW(*res);
-		dst_import_metrics(dst, fi->fib_metrics);
-#ifdef CONFIG_NET_CLS_ROUTE
+		rt_init_metrics(rt, oldflp4, fi);
+#ifdef CONFIG_IP_ROUTE_CLASSID
 		dst->tclassid = FIB_RES_NH(*res).nh_tclassid;
 #endif
 	}
@@ -1835,13 +1826,26 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
 	if (dst_metric_raw(dst, RTAX_ADVMSS) > 65535 - 40)
 		dst_metric_set(dst, RTAX_ADVMSS, 65535 - 40);
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	set_class_tag(rt, fib_rules_tclass(res));
 #endif
 	set_class_tag(rt, itag);
 #endif
-	rt->rt_type = res->type;
+	rt->rt_type = type;
+}
+
+static struct rtable *rt_dst_alloc(bool nopolicy, bool noxfrm)
+{
+	struct rtable *rt = dst_alloc(&ipv4_dst_ops, 1);
+	if (rt) {
+		rt->dst.obsolete = -1;
+
+		rt->dst.flags = DST_HOST |
+			(nopolicy ? DST_NOPOLICY : 0) |
+			(noxfrm ? DST_NOXFRM : 0);
+	}
+	return rt;
 }
 
 /* called in rcu_read_lock() section */
@@ -1874,31 +1878,25 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 		if (err < 0)
 			goto e_err;
 	}
-	rth = dst_alloc(&ipv4_dst_ops);
+	rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false);
 	if (!rth)
 		goto e_nobufs;
 
 	rth->dst.output = ip_rt_bug;
-	rth->dst.obsolete = -1;
 
-	atomic_set(&rth->dst.__refcnt, 1);
-	rth->dst.flags= DST_HOST;
-	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-		rth->dst.flags |= DST_NOPOLICY;
-	rth->fl.fl4_dst	= daddr;
+	rth->rt_key_dst	= daddr;
 	rth->rt_dst	= daddr;
-	rth->fl.fl4_tos	= tos;
-	rth->fl.mark    = skb->mark;
-	rth->fl.fl4_src	= saddr;
+	rth->rt_tos	= tos;
+	rth->rt_mark    = skb->mark;
+	rth->rt_key_src	= saddr;
 	rth->rt_src	= saddr;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	rth->dst.tclassid = itag;
 #endif
-	rth->rt_iif	=
-	rth->fl.iif	= dev->ifindex;
+	rth->rt_iif	= dev->ifindex;
 	rth->dst.dev	= init_net.loopback_dev;
 	dev_hold(rth->dst.dev);
-	rth->fl.oif	= 0;
+	rth->rt_oif	= 0;
 	rth->rt_gateway	= daddr;
 	rth->rt_spec_dst= spec_dst;
 	rth->rt_genid	= rt_genid(dev_net(dev));
@@ -1916,7 +1914,10 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	RT_CACHE_STAT_INC(in_slow_mc);
 
 	hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
-	return rt_intern_hash(hash, rth, NULL, skb, dev->ifindex);
+	rth = rt_intern_hash(hash, rth, skb, dev->ifindex);
+	err = 0;
+	if (IS_ERR(rth))
+		err = PTR_ERR(rth);
 
 e_nobufs:
 	return -ENOBUFS;
@@ -1959,7 +1960,7 @@ static void ip_handle_martian_source(struct net_device *dev,
 
 /* called in rcu_read_lock() section */
 static int __mkroute_input(struct sk_buff *skb,
-			   struct fib_result *res,
+			   const struct fib_result *res,
 			   struct in_device *in_dev,
 			   __be32 daddr, __be32 saddr, u32 tos,
 			   struct rtable **result)
@@ -2013,39 +2014,31 @@ static int __mkroute_input(struct sk_buff *skb,
 		}
 	}
 
-
-	rth = dst_alloc(&ipv4_dst_ops);
+	rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY),
+			   IN_DEV_CONF_GET(out_dev, NOXFRM));
 	if (!rth) {
 		err = -ENOBUFS;
 		goto cleanup;
 	}
 
-	atomic_set(&rth->dst.__refcnt, 1);
-	rth->dst.flags= DST_HOST;
-	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-		rth->dst.flags |= DST_NOPOLICY;
-	if (IN_DEV_CONF_GET(out_dev, NOXFRM))
-		rth->dst.flags |= DST_NOXFRM;
-	rth->fl.fl4_dst	= daddr;
+	rth->rt_key_dst	= daddr;
 	rth->rt_dst	= daddr;
-	rth->fl.fl4_tos	= tos;
-	rth->fl.mark    = skb->mark;
-	rth->fl.fl4_src	= saddr;
+	rth->rt_tos	= tos;
+	rth->rt_mark    = skb->mark;
+	rth->rt_key_src	= saddr;
 	rth->rt_src	= saddr;
 	rth->rt_gateway	= daddr;
-	rth->rt_iif 	=
-		rth->fl.iif	= in_dev->dev->ifindex;
+	rth->rt_iif 	= in_dev->dev->ifindex;
 	rth->dst.dev	= (out_dev)->dev;
 	dev_hold(rth->dst.dev);
-	rth->fl.oif 	= 0;
+	rth->rt_oif 	= 0;
 	rth->rt_spec_dst= spec_dst;
 
-	rth->dst.obsolete = -1;
 	rth->dst.input = ip_forward;
 	rth->dst.output = ip_output;
 	rth->rt_genid = rt_genid(dev_net(rth->dst.dev));
 
-	rt_set_nexthop(rth, res, itag);
+	rt_set_nexthop(rth, NULL, res, res->fi, res->type, itag);
 
 	rth->rt_flags = flags;
 
@@ -2057,7 +2050,7 @@ static int __mkroute_input(struct sk_buff *skb,
 
 static int ip_mkroute_input(struct sk_buff *skb,
 			    struct fib_result *res,
-			    const struct flowi *fl,
+			    const struct flowi4 *fl4,
 			    struct in_device *in_dev,
 			    __be32 daddr, __be32 saddr, u32 tos)
 {
@@ -2066,8 +2059,8 @@ static int ip_mkroute_input(struct sk_buff *skb,
 	unsigned hash;
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res->fi && res->fi->fib_nhs > 1 && fl->oif == 0)
-		fib_select_multipath(fl, res);
+	if (res->fi && res->fi->fib_nhs > 1)
+		fib_select_multipath(res);
 #endif
 
 	/* create a routing cache entry */
@@ -2076,9 +2069,12 @@ static int ip_mkroute_input(struct sk_buff *skb,
 		return err;
 
 	/* put it into the cache */
-	hash = rt_hash(daddr, saddr, fl->iif,
+	hash = rt_hash(daddr, saddr, fl4->flowi4_iif,
 		       rt_genid(dev_net(rth->dst.dev)));
-	return rt_intern_hash(hash, rth, NULL, skb, fl->iif);
+	rth = rt_intern_hash(hash, rth, skb, fl4->flowi4_iif);
+	if (IS_ERR(rth))
+		return PTR_ERR(rth);
+	return 0;
 }
 
 /*
@@ -2097,12 +2093,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 {
 	struct fib_result res;
 	struct in_device *in_dev = __in_dev_get_rcu(dev);
-	struct flowi fl = { .fl4_dst	= daddr,
-			    .fl4_src	= saddr,
-			    .fl4_tos	= tos,
-			    .fl4_scope	= RT_SCOPE_UNIVERSE,
-			    .mark = skb->mark,
-			    .iif = dev->ifindex };
+	struct flowi4	fl4;
 	unsigned	flags = 0;
 	u32		itag = 0;
 	struct rtable * rth;
@@ -2139,7 +2130,14 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	/*
 	 *	Now we are ready to route packet.
 	 */
-	err = fib_lookup(net, &fl, &res);
+	fl4.flowi4_oif = 0;
+	fl4.flowi4_iif = dev->ifindex;
+	fl4.flowi4_mark = skb->mark;
+	fl4.flowi4_tos = tos;
+	fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+	fl4.daddr = daddr;
+	fl4.saddr = saddr;
+	err = fib_lookup(net, &fl4, &res);
 	if (err != 0) {
 		if (!IN_DEV_FORWARD(in_dev))
 			goto e_hostunreach;
@@ -2168,7 +2166,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	if (res.type != RTN_UNICAST)
 		goto martian_destination;
 
-	err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
+	err = ip_mkroute_input(skb, &res, &fl4, in_dev, daddr, saddr, tos);
 out:	return err;
 
 brd_input:
@@ -2190,29 +2188,23 @@ brd_input:
 	RT_CACHE_STAT_INC(in_brd);
 
 local_input:
-	rth = dst_alloc(&ipv4_dst_ops);
+	rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false);
 	if (!rth)
 		goto e_nobufs;
 
 	rth->dst.output= ip_rt_bug;
-	rth->dst.obsolete = -1;
 	rth->rt_genid = rt_genid(net);
 
-	atomic_set(&rth->dst.__refcnt, 1);
-	rth->dst.flags= DST_HOST;
-	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-		rth->dst.flags |= DST_NOPOLICY;
-	rth->fl.fl4_dst	= daddr;
+	rth->rt_key_dst	= daddr;
 	rth->rt_dst	= daddr;
-	rth->fl.fl4_tos	= tos;
-	rth->fl.mark    = skb->mark;
-	rth->fl.fl4_src	= saddr;
+	rth->rt_tos	= tos;
+	rth->rt_mark    = skb->mark;
+	rth->rt_key_src	= saddr;
 	rth->rt_src	= saddr;
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	rth->dst.tclassid = itag;
 #endif
-	rth->rt_iif	=
-	rth->fl.iif	= dev->ifindex;
+	rth->rt_iif	= dev->ifindex;
 	rth->dst.dev	= net->loopback_dev;
 	dev_hold(rth->dst.dev);
 	rth->rt_gateway	= daddr;
@@ -2225,8 +2217,11 @@ local_input:
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
 	rth->rt_type	= res.type;
-	hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
-	err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
+	hash = rt_hash(daddr, saddr, fl4.flowi4_iif, rt_genid(net));
+	rth = rt_intern_hash(hash, rth, skb, fl4.flowi4_iif);
+	err = 0;
+	if (IS_ERR(rth))
+		err = PTR_ERR(rth);
 	goto out;
 
 no_route:
@@ -2288,12 +2283,12 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 	for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
 	     rth = rcu_dereference(rth->dst.rt_next)) {
-		if ((((__force u32)rth->fl.fl4_dst ^ (__force u32)daddr) |
-		     ((__force u32)rth->fl.fl4_src ^ (__force u32)saddr) |
-		     (rth->fl.iif ^ iif) |
-		     rth->fl.oif |
-		     (rth->fl.fl4_tos ^ tos)) == 0 &&
-		    rth->fl.mark == skb->mark &&
+		if ((((__force u32)rth->rt_key_dst ^ (__force u32)daddr) |
+		     ((__force u32)rth->rt_key_src ^ (__force u32)saddr) |
+		     (rth->rt_iif ^ iif) |
+		     rth->rt_oif |
+		     (rth->rt_tos ^ tos)) == 0 &&
+		    rth->rt_mark == skb->mark &&
 		    net_eq(dev_net(rth->dst.dev), net) &&
 		    !rt_is_expired(rth)) {
 			if (noref) {
@@ -2326,8 +2321,8 @@ skip_cache:
 		struct in_device *in_dev = __in_dev_get_rcu(dev);
 
 		if (in_dev) {
-			int our = ip_check_mc(in_dev, daddr, saddr,
-					      ip_hdr(skb)->protocol);
+			int our = ip_check_mc_rcu(in_dev, daddr, saddr,
+						  ip_hdr(skb)->protocol);
 			if (our
 #ifdef CONFIG_IP_MROUTE
 				||
@@ -2351,98 +2346,91 @@ skip_cache:
 EXPORT_SYMBOL(ip_route_input_common);
 
 /* called with rcu_read_lock() */
-static int __mkroute_output(struct rtable **result,
-			    struct fib_result *res,
-			    const struct flowi *fl,
-			    const struct flowi *oldflp,
-			    struct net_device *dev_out,
-			    unsigned flags)
+static struct rtable *__mkroute_output(const struct fib_result *res,
+				       const struct flowi4 *fl4,
+				       const struct flowi4 *oldflp4,
+				       struct net_device *dev_out,
+				       unsigned int flags)
 {
-	struct rtable *rth;
+	struct fib_info *fi = res->fi;
+	u32 tos = RT_FL_TOS(oldflp4);
 	struct in_device *in_dev;
-	u32 tos = RT_FL_TOS(oldflp);
+	u16 type = res->type;
+	struct rtable *rth;
 
-	if (ipv4_is_loopback(fl->fl4_src) && !(dev_out->flags & IFF_LOOPBACK))
-		return -EINVAL;
+	if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK))
+		return ERR_PTR(-EINVAL);
 
-	if (ipv4_is_lbcast(fl->fl4_dst))
-		res->type = RTN_BROADCAST;
-	else if (ipv4_is_multicast(fl->fl4_dst))
-		res->type = RTN_MULTICAST;
-	else if (ipv4_is_zeronet(fl->fl4_dst))
-		return -EINVAL;
+	if (ipv4_is_lbcast(fl4->daddr))
+		type = RTN_BROADCAST;
+	else if (ipv4_is_multicast(fl4->daddr))
+		type = RTN_MULTICAST;
+	else if (ipv4_is_zeronet(fl4->daddr))
+		return ERR_PTR(-EINVAL);
 
 	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
 	in_dev = __in_dev_get_rcu(dev_out);
 	if (!in_dev)
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 
-	if (res->type == RTN_BROADCAST) {
+	if (type == RTN_BROADCAST) {
 		flags |= RTCF_BROADCAST | RTCF_LOCAL;
-		res->fi = NULL;
-	} else if (res->type == RTN_MULTICAST) {
+		fi = NULL;
+	} else if (type == RTN_MULTICAST) {
 		flags |= RTCF_MULTICAST | RTCF_LOCAL;
-		if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src,
-				 oldflp->proto))
+		if (!ip_check_mc_rcu(in_dev, oldflp4->daddr, oldflp4->saddr,
+				     oldflp4->flowi4_proto))
 			flags &= ~RTCF_LOCAL;
 		/* If multicast route do not exist use
 		 * default one, but do not gateway in this case.
 		 * Yes, it is hack.
 		 */
-		if (res->fi && res->prefixlen < 4)
-			res->fi = NULL;
+		if (fi && res->prefixlen < 4)
+			fi = NULL;
 	}
 
-
-	rth = dst_alloc(&ipv4_dst_ops);
+	rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY),
+			   IN_DEV_CONF_GET(in_dev, NOXFRM));
 	if (!rth)
-		return -ENOBUFS;
-
-	atomic_set(&rth->dst.__refcnt, 1);
-	rth->dst.flags= DST_HOST;
-	if (IN_DEV_CONF_GET(in_dev, NOXFRM))
-		rth->dst.flags |= DST_NOXFRM;
-	if (IN_DEV_CONF_GET(in_dev, NOPOLICY))
-		rth->dst.flags |= DST_NOPOLICY;
-
-	rth->fl.fl4_dst	= oldflp->fl4_dst;
-	rth->fl.fl4_tos	= tos;
-	rth->fl.fl4_src	= oldflp->fl4_src;
-	rth->fl.oif	= oldflp->oif;
-	rth->fl.mark    = oldflp->mark;
-	rth->rt_dst	= fl->fl4_dst;
-	rth->rt_src	= fl->fl4_src;
-	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;
+		return ERR_PTR(-ENOBUFS);
+
+	rth->rt_key_dst	= oldflp4->daddr;
+	rth->rt_tos	= tos;
+	rth->rt_key_src	= oldflp4->saddr;
+	rth->rt_oif	= oldflp4->flowi4_oif;
+	rth->rt_mark    = oldflp4->flowi4_mark;
+	rth->rt_dst	= fl4->daddr;
+	rth->rt_src	= fl4->saddr;
+	rth->rt_iif	= 0;
 	/* get references to the devices that are to be hold by the routing
 	   cache entry */
 	rth->dst.dev	= dev_out;
 	dev_hold(dev_out);
-	rth->rt_gateway = fl->fl4_dst;
-	rth->rt_spec_dst= fl->fl4_src;
+	rth->rt_gateway = fl4->daddr;
+	rth->rt_spec_dst= fl4->saddr;
 
 	rth->dst.output=ip_output;
-	rth->dst.obsolete = -1;
 	rth->rt_genid = rt_genid(dev_net(dev_out));
 
 	RT_CACHE_STAT_INC(out_slow_tot);
 
 	if (flags & RTCF_LOCAL) {
 		rth->dst.input = ip_local_deliver;
-		rth->rt_spec_dst = fl->fl4_dst;
+		rth->rt_spec_dst = fl4->daddr;
 	}
 	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
-		rth->rt_spec_dst = fl->fl4_src;
+		rth->rt_spec_dst = fl4->saddr;
 		if (flags & RTCF_LOCAL &&
 		    !(dev_out->flags & IFF_LOOPBACK)) {
 			rth->dst.output = ip_mc_output;
 			RT_CACHE_STAT_INC(out_slow_mc);
 		}
 #ifdef CONFIG_IP_MROUTE
-		if (res->type == RTN_MULTICAST) {
+		if (type == RTN_MULTICAST) {
 			if (IN_DEV_MFORWARD(in_dev) &&
-			    !ipv4_is_local_multicast(oldflp->fl4_dst)) {
+			    !ipv4_is_local_multicast(oldflp4->daddr)) {
 				rth->dst.input = ip_mr_input;
 				rth->dst.output = ip_mc_output;
 			}
@@ -2450,31 +2438,10 @@ static int __mkroute_output(struct rtable **result,
 #endif
 	}
 
-	rt_set_nexthop(rth, res, 0);
+	rt_set_nexthop(rth, oldflp4, res, fi, type, 0);
 
 	rth->rt_flags = flags;
-	*result = rth;
-	return 0;
-}
-
-/* called with rcu_read_lock() */
-static int ip_mkroute_output(struct rtable **rp,
-			     struct fib_result *res,
-			     const struct flowi *fl,
-			     const struct flowi *oldflp,
-			     struct net_device *dev_out,
-			     unsigned flags)
-{
-	struct rtable *rth = NULL;
-	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
-	unsigned hash;
-	if (err == 0) {
-		hash = rt_hash(oldflp->fl4_dst, oldflp->fl4_src, oldflp->oif,
-			       rt_genid(dev_net(dev_out)));
-		err = rt_intern_hash(hash, rth, rp, NULL, oldflp->oif);
-	}
-
-	return err;
+	return rth;
 }
 
 /*
@@ -2482,34 +2449,36 @@ static int ip_mkroute_output(struct rtable **rp,
  * called with rcu_read_lock();
  */
 
-static int ip_route_output_slow(struct net *net, struct rtable **rp,
-				const struct flowi *oldflp)
-{
-	u32 tos	= RT_FL_TOS(oldflp);
-	struct flowi fl = { .fl4_dst = oldflp->fl4_dst,
-			    .fl4_src = oldflp->fl4_src,
-			    .fl4_tos = tos & IPTOS_RT_MASK,
-			    .fl4_scope = ((tos & RTO_ONLINK) ?
-					  RT_SCOPE_LINK : RT_SCOPE_UNIVERSE),
-			    .mark = oldflp->mark,
-			    .iif = net->loopback_dev->ifindex,
-			    .oif = oldflp->oif };
+static struct rtable *ip_route_output_slow(struct net *net,
+					   const struct flowi4 *oldflp4)
+{
+	u32 tos	= RT_FL_TOS(oldflp4);
+	struct flowi4 fl4;
 	struct fib_result res;
 	unsigned int flags = 0;
 	struct net_device *dev_out = NULL;
-	int err;
-
+	struct rtable *rth;
 
 	res.fi		= NULL;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	res.r		= NULL;
 #endif
 
-	if (oldflp->fl4_src) {
-		err = -EINVAL;
-		if (ipv4_is_multicast(oldflp->fl4_src) ||
-		    ipv4_is_lbcast(oldflp->fl4_src) ||
-		    ipv4_is_zeronet(oldflp->fl4_src))
+	fl4.flowi4_oif = oldflp4->flowi4_oif;
+	fl4.flowi4_iif = net->loopback_dev->ifindex;
+	fl4.flowi4_mark = oldflp4->flowi4_mark;
+	fl4.daddr = oldflp4->daddr;
+	fl4.saddr = oldflp4->saddr;
+	fl4.flowi4_tos = tos & IPTOS_RT_MASK;
+	fl4.flowi4_scope = ((tos & RTO_ONLINK) ?
+			RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
+
+	rcu_read_lock();
+	if (oldflp4->saddr) {
+		rth = ERR_PTR(-EINVAL);
+		if (ipv4_is_multicast(oldflp4->saddr) ||
+		    ipv4_is_lbcast(oldflp4->saddr) ||
+		    ipv4_is_zeronet(oldflp4->saddr))
 			goto out;
 
 		/* I removed check for oif == dev_out->oif here.
@@ -2520,11 +2489,11 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
 		      of another iface. --ANK
 		 */
 
-		if (oldflp->oif == 0 &&
-		    (ipv4_is_multicast(oldflp->fl4_dst) ||
-		     ipv4_is_lbcast(oldflp->fl4_dst))) {
+		if (oldflp4->flowi4_oif == 0 &&
+		    (ipv4_is_multicast(oldflp4->daddr) ||
+		     ipv4_is_lbcast(oldflp4->daddr))) {
 			/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
-			dev_out = __ip_dev_find(net, oldflp->fl4_src, false);
+			dev_out = __ip_dev_find(net, oldflp4->saddr, false);
 			if (dev_out == NULL)
 				goto out;
 
@@ -2543,60 +2512,60 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
 			   Luckily, this hack is good workaround.
 			 */
 
-			fl.oif = dev_out->ifindex;
+			fl4.flowi4_oif = dev_out->ifindex;
 			goto make_route;
 		}
 
-		if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) {
+		if (!(oldflp4->flowi4_flags & FLOWI_FLAG_ANYSRC)) {
 			/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
-			if (!__ip_dev_find(net, oldflp->fl4_src, false))
+			if (!__ip_dev_find(net, oldflp4->saddr, false))
 				goto out;
 		}
 	}
 
 
-	if (oldflp->oif) {
-		dev_out = dev_get_by_index_rcu(net, oldflp->oif);
-		err = -ENODEV;
+	if (oldflp4->flowi4_oif) {
+		dev_out = dev_get_by_index_rcu(net, oldflp4->flowi4_oif);
+		rth = ERR_PTR(-ENODEV);
 		if (dev_out == NULL)
 			goto out;
 
 		/* RACE: Check return value of inet_select_addr instead. */
 		if (!(dev_out->flags & IFF_UP) || !__in_dev_get_rcu(dev_out)) {
-			err = -ENETUNREACH;
+			rth = ERR_PTR(-ENETUNREACH);
 			goto out;
 		}
-		if (ipv4_is_local_multicast(oldflp->fl4_dst) ||
-		    ipv4_is_lbcast(oldflp->fl4_dst)) {
-			if (!fl.fl4_src)
-				fl.fl4_src = inet_select_addr(dev_out, 0,
-							      RT_SCOPE_LINK);
+		if (ipv4_is_local_multicast(oldflp4->daddr) ||
+		    ipv4_is_lbcast(oldflp4->daddr)) {
+			if (!fl4.saddr)
+				fl4.saddr = inet_select_addr(dev_out, 0,
+							     RT_SCOPE_LINK);
 			goto make_route;
 		}
-		if (!fl.fl4_src) {
-			if (ipv4_is_multicast(oldflp->fl4_dst))
-				fl.fl4_src = inet_select_addr(dev_out, 0,
-							      fl.fl4_scope);
-			else if (!oldflp->fl4_dst)
-				fl.fl4_src = inet_select_addr(dev_out, 0,
-							      RT_SCOPE_HOST);
+		if (!fl4.saddr) {
+			if (ipv4_is_multicast(oldflp4->daddr))
+				fl4.saddr = inet_select_addr(dev_out, 0,
+							     fl4.flowi4_scope);
+			else if (!oldflp4->daddr)
+				fl4.saddr = inet_select_addr(dev_out, 0,
+							     RT_SCOPE_HOST);
 		}
 	}
 
-	if (!fl.fl4_dst) {
-		fl.fl4_dst = fl.fl4_src;
-		if (!fl.fl4_dst)
-			fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK);
+	if (!fl4.daddr) {
+		fl4.daddr = fl4.saddr;
+		if (!fl4.daddr)
+			fl4.daddr = fl4.saddr = htonl(INADDR_LOOPBACK);
 		dev_out = net->loopback_dev;
-		fl.oif = net->loopback_dev->ifindex;
+		fl4.flowi4_oif = net->loopback_dev->ifindex;
 		res.type = RTN_LOCAL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
 	}
 
-	if (fib_lookup(net, &fl, &res)) {
+	if (fib_lookup(net, &fl4, &res)) {
 		res.fi = NULL;
-		if (oldflp->oif) {
+		if (oldflp4->flowi4_oif) {
 			/* Apparently, routing tables are wrong. Assume,
 			   that the destination is on link.
 
@@ -2615,90 +2584,93 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
 			   likely IPv6, but we do not.
 			 */
 
-			if (fl.fl4_src == 0)
-				fl.fl4_src = inet_select_addr(dev_out, 0,
-							      RT_SCOPE_LINK);
+			if (fl4.saddr == 0)
+				fl4.saddr = inet_select_addr(dev_out, 0,
+							     RT_SCOPE_LINK);
 			res.type = RTN_UNICAST;
 			goto make_route;
 		}
-		err = -ENETUNREACH;
+		rth = ERR_PTR(-ENETUNREACH);
 		goto out;
 	}
 
 	if (res.type == RTN_LOCAL) {
-		if (!fl.fl4_src) {
+		if (!fl4.saddr) {
 			if (res.fi->fib_prefsrc)
-				fl.fl4_src = res.fi->fib_prefsrc;
+				fl4.saddr = res.fi->fib_prefsrc;
 			else
-				fl.fl4_src = fl.fl4_dst;
+				fl4.saddr = fl4.daddr;
 		}
 		dev_out = net->loopback_dev;
-		fl.oif = dev_out->ifindex;
+		fl4.flowi4_oif = dev_out->ifindex;
 		res.fi = NULL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
 	}
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res.fi->fib_nhs > 1 && fl.oif == 0)
-		fib_select_multipath(&fl, &res);
+	if (res.fi->fib_nhs > 1 && fl4.flowi4_oif == 0)
+		fib_select_multipath(&res);
 	else
 #endif
-	if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif)
-		fib_select_default(net, &fl, &res);
+	if (!res.prefixlen && res.type == RTN_UNICAST && !fl4.flowi4_oif)
+		fib_select_default(&res);
 
-	if (!fl.fl4_src)
-		fl.fl4_src = FIB_RES_PREFSRC(res);
+	if (!fl4.saddr)
+		fl4.saddr = FIB_RES_PREFSRC(res);
 
 	dev_out = FIB_RES_DEV(res);
-	fl.oif = dev_out->ifindex;
+	fl4.flowi4_oif = dev_out->ifindex;
 
 
 make_route:
-	err = ip_mkroute_output(rp, &res, &fl, oldflp, dev_out, flags);
+	rth = __mkroute_output(&res, &fl4, oldflp4, dev_out, flags);
+	if (!IS_ERR(rth)) {
+		unsigned int hash;
 
-out:	return err;
+		hash = rt_hash(oldflp4->daddr, oldflp4->saddr, oldflp4->flowi4_oif,
+			       rt_genid(dev_net(dev_out)));
+		rth = rt_intern_hash(hash, rth, NULL, oldflp4->flowi4_oif);
+	}
+
+out:
+	rcu_read_unlock();
+	return rth;
 }
 
-int __ip_route_output_key(struct net *net, struct rtable **rp,
-			  const struct flowi *flp)
+struct rtable *__ip_route_output_key(struct net *net, const struct flowi4 *flp4)
 {
-	unsigned int hash;
-	int res;
 	struct rtable *rth;
+	unsigned int hash;
 
 	if (!rt_caching(net))
 		goto slow_output;
 
-	hash = rt_hash(flp->fl4_dst, flp->fl4_src, flp->oif, rt_genid(net));
+	hash = rt_hash(flp4->daddr, flp4->saddr, flp4->flowi4_oif, rt_genid(net));
 
 	rcu_read_lock_bh();
 	for (rth = rcu_dereference_bh(rt_hash_table[hash].chain); rth;
 		rth = rcu_dereference_bh(rth->dst.rt_next)) {
-		if (rth->fl.fl4_dst == flp->fl4_dst &&
-		    rth->fl.fl4_src == flp->fl4_src &&
+		if (rth->rt_key_dst == flp4->daddr &&
+		    rth->rt_key_src == flp4->saddr &&
 		    rt_is_output_route(rth) &&
-		    rth->fl.oif == flp->oif &&
-		    rth->fl.mark == flp->mark &&
-		    !((rth->fl.fl4_tos ^ flp->fl4_tos) &
+		    rth->rt_oif == flp4->flowi4_oif &&
+		    rth->rt_mark == flp4->flowi4_mark &&
+		    !((rth->rt_tos ^ flp4->flowi4_tos) &
 			    (IPTOS_RT_MASK | RTO_ONLINK)) &&
 		    net_eq(dev_net(rth->dst.dev), net) &&
 		    !rt_is_expired(rth)) {
 			dst_use(&rth->dst, jiffies);
 			RT_CACHE_STAT_INC(out_hit);
 			rcu_read_unlock_bh();
-			*rp = rth;
-			return 0;
+			return rth;
 		}
 		RT_CACHE_STAT_INC(out_hlist_search);
 	}
 	rcu_read_unlock_bh();
 
 slow_output:
-	rcu_read_lock();
-	res = ip_route_output_slow(net, rp, flp);
-	rcu_read_unlock();
-	return res;
+	return ip_route_output_slow(net, flp4);
 }
 EXPORT_SYMBOL_GPL(__ip_route_output_key);
 
@@ -2726,17 +2698,14 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
 	.update_pmtu		=	ipv4_rt_blackhole_update_pmtu,
 };
 
-
-static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi *flp)
+struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
 {
-	struct rtable *ort = *rp;
-	struct rtable *rt = (struct rtable *)
-		dst_alloc(&ipv4_dst_blackhole_ops);
+	struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, 1);
+	struct rtable *ort = (struct rtable *) dst_orig;
 
 	if (rt) {
 		struct dst_entry *new = &rt->dst;
 
-		atomic_set(&new->__refcnt, 1);
 		new->__use = 1;
 		new->input = dst_discard;
 		new->output = dst_discard;
@@ -2746,7 +2715,12 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
 		if (new->dev)
 			dev_hold(new->dev);
 
-		rt->fl = ort->fl;
+		rt->rt_key_dst = ort->rt_key_dst;
+		rt->rt_key_src = ort->rt_key_src;
+		rt->rt_tos = ort->rt_tos;
+		rt->rt_iif = ort->rt_iif;
+		rt->rt_oif = ort->rt_oif;
+		rt->rt_mark = ort->rt_mark;
 
 		rt->rt_genid = rt_genid(net);
 		rt->rt_flags = ort->rt_flags;
@@ -2759,46 +2733,40 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi
 		rt->peer = ort->peer;
 		if (rt->peer)
 			atomic_inc(&rt->peer->refcnt);
+		rt->fi = ort->fi;
+		if (rt->fi)
+			atomic_inc(&rt->fi->fib_clntref);
 
 		dst_free(new);
 	}
 
-	dst_release(&(*rp)->dst);
-	*rp = rt;
-	return rt ? 0 : -ENOMEM;
+	dst_release(dst_orig);
+
+	return rt ? &rt->dst : ERR_PTR(-ENOMEM);
 }
 
-int ip_route_output_flow(struct net *net, struct rtable **rp, struct flowi *flp,
-			 struct sock *sk, int flags)
+struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
+				    struct sock *sk)
 {
-	int err;
+	struct rtable *rt = __ip_route_output_key(net, flp4);
 
-	if ((err = __ip_route_output_key(net, rp, flp)) != 0)
-		return err;
+	if (IS_ERR(rt))
+		return rt;
 
-	if (flp->proto) {
-		if (!flp->fl4_src)
-			flp->fl4_src = (*rp)->rt_src;
-		if (!flp->fl4_dst)
-			flp->fl4_dst = (*rp)->rt_dst;
-		err = __xfrm_lookup(net, (struct dst_entry **)rp, flp, sk,
-				    flags ? XFRM_LOOKUP_WAIT : 0);
-		if (err == -EREMOTE)
-			err = ipv4_dst_blackhole(net, rp, flp);
-
-		return err;
+	if (flp4->flowi4_proto) {
+		if (!flp4->saddr)
+			flp4->saddr = rt->rt_src;
+		if (!flp4->daddr)
+			flp4->daddr = rt->rt_dst;
+		rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
+						   flowi4_to_flowi(flp4),
+						   sk, 0);
 	}
 
-	return 0;
+	return rt;
 }
 EXPORT_SYMBOL_GPL(ip_route_output_flow);
 
-int ip_route_output_key(struct net *net, struct rtable **rp, struct flowi *flp)
-{
-	return ip_route_output_flow(net, rp, flp, NULL, 0);
-}
-EXPORT_SYMBOL(ip_route_output_key);
-
 static int rt_fill_info(struct net *net,
 			struct sk_buff *skb, u32 pid, u32 seq, int event,
 			int nowait, unsigned int flags)
@@ -2817,7 +2785,7 @@ static int rt_fill_info(struct net *net,
 	r->rtm_family	 = AF_INET;
 	r->rtm_dst_len	= 32;
 	r->rtm_src_len	= 0;
-	r->rtm_tos	= rt->fl.fl4_tos;
+	r->rtm_tos	= rt->rt_tos;
 	r->rtm_table	= RT_TABLE_MAIN;
 	NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN);
 	r->rtm_type	= rt->rt_type;
@@ -2829,19 +2797,19 @@ static int rt_fill_info(struct net *net,
 
 	NLA_PUT_BE32(skb, RTA_DST, rt->rt_dst);
 
-	if (rt->fl.fl4_src) {
+	if (rt->rt_key_src) {
 		r->rtm_src_len = 32;
-		NLA_PUT_BE32(skb, RTA_SRC, rt->fl.fl4_src);
+		NLA_PUT_BE32(skb, RTA_SRC, rt->rt_key_src);
 	}
 	if (rt->dst.dev)
 		NLA_PUT_U32(skb, RTA_OIF, rt->dst.dev->ifindex);
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	if (rt->dst.tclassid)
 		NLA_PUT_U32(skb, RTA_FLOW, rt->dst.tclassid);
 #endif
 	if (rt_is_input_route(rt))
 		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_spec_dst);
-	else if (rt->rt_src != rt->fl.fl4_src)
+	else if (rt->rt_src != rt->rt_key_src)
 		NLA_PUT_BE32(skb, RTA_PREFSRC, rt->rt_src);
 
 	if (rt->rt_dst != rt->rt_gateway)
@@ -2850,11 +2818,12 @@ static int rt_fill_info(struct net *net,
 	if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
 		goto nla_put_failure;
 
-	if (rt->fl.mark)
-		NLA_PUT_BE32(skb, RTA_MARK, rt->fl.mark);
+	if (rt->rt_mark)
+		NLA_PUT_BE32(skb, RTA_MARK, rt->rt_mark);
 
 	error = rt->dst.error;
-	expires = rt->dst.expires ? rt->dst.expires - jiffies : 0;
+	expires = (rt->peer && rt->peer->pmtu_expires) ?
+		rt->peer->pmtu_expires - jiffies : 0;
 	if (rt->peer) {
 		inet_peer_refcheck(rt->peer);
 		id = atomic_read(&rt->peer->ip_id_count) & 0xffff;
@@ -2884,7 +2853,7 @@ static int rt_fill_info(struct net *net,
 			}
 		} else
 #endif
-			NLA_PUT_U32(skb, RTA_IIF, rt->fl.iif);
+			NLA_PUT_U32(skb, RTA_IIF, rt->rt_iif);
 	}
 
 	if (rtnl_put_cacheinfo(skb, &rt->dst, id, ts, tsage,
@@ -2958,14 +2927,18 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 		if (err == 0 && rt->dst.error)
 			err = -rt->dst.error;
 	} else {
-		struct flowi fl = {
-			.fl4_dst = dst,
-			.fl4_src = src,
-			.fl4_tos = rtm->rtm_tos,
-			.oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
-			.mark = mark,
+		struct flowi4 fl4 = {
+			.daddr = dst,
+			.saddr = src,
+			.flowi4_tos = rtm->rtm_tos,
+			.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0,
+			.flowi4_mark = mark,
 		};
-		err = ip_route_output_key(net, &rt, &fl);
+		rt = ip_route_output_key(net, &fl4);
+
+		err = 0;
+		if (IS_ERR(rt))
+			err = PTR_ERR(rt);
 	}
 
 	if (err)
@@ -3256,9 +3229,9 @@ static __net_initdata struct pernet_operations rt_genid_ops = {
 };
 
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 struct ip_rt_acct __percpu *ip_rt_acct __read_mostly;
-#endif /* CONFIG_NET_CLS_ROUTE */
+#endif /* CONFIG_IP_ROUTE_CLASSID */
 
 static __initdata unsigned long rhash_entries;
 static int __init set_rhash_entries(char *str)
@@ -3274,7 +3247,7 @@ int __init ip_rt_init(void)
 {
 	int rc = 0;
 
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	ip_rt_acct = __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(struct ip_rt_acct));
 	if (!ip_rt_acct)
 		panic("IP: failed to allocate ip_rt_acct\n");
@@ -3311,14 +3284,6 @@ int __init ip_rt_init(void)
 	devinet_init();
 	ip_fib_init();
 
-	/* All the timers, started at system startup tend
-	   to synchronize. Perturb it a bit.
-	 */
-	INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func);
-	expires_ljiffies = jiffies;
-	schedule_delayed_work(&expires_work,
-		net_random() % ip_rt_gc_interval + ip_rt_gc_interval);
-
 	if (ip_rt_proc_init())
 		printk(KERN_ERR "Unable to create route proc files\n");
 #ifdef CONFIG_XFRM
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 4751920..8b44c6d 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -345,17 +345,20 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 	 * no easy way to do this.
 	 */
 	{
-		struct flowi fl = { .mark = sk->sk_mark,
-				    .fl4_dst = ((opt && opt->srr) ?
-						opt->faddr : ireq->rmt_addr),
-				    .fl4_src = ireq->loc_addr,
-				    .fl4_tos = RT_CONN_FLAGS(sk),
-				    .proto = IPPROTO_TCP,
-				    .flags = inet_sk_flowi_flags(sk),
-				    .fl_ip_sport = th->dest,
-				    .fl_ip_dport = th->source };
-		security_req_classify_flow(req, &fl);
-		if (ip_route_output_key(sock_net(sk), &rt, &fl)) {
+		struct flowi4 fl4 = {
+			.flowi4_mark = sk->sk_mark,
+			.daddr = ((opt && opt->srr) ?
+				  opt->faddr : ireq->rmt_addr),
+			.saddr = ireq->loc_addr,
+			.flowi4_tos = RT_CONN_FLAGS(sk),
+			.flowi4_proto = IPPROTO_TCP,
+			.flowi4_flags = inet_sk_flowi_flags(sk),
+			.fl4_sport = th->dest,
+			.fl4_dport = th->source,
+		};
+		security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+		rt = ip_route_output_key(sock_net(sk), &fl4);
+		if (IS_ERR(rt)) {
 			reqsk_free(req);
 			goto out;
 		}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 6c11eec..b22d450 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -505,6 +505,15 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 		else
 			answ = tp->write_seq - tp->snd_una;
 		break;
+	case SIOCOUTQNSD:
+		if (sk->sk_state == TCP_LISTEN)
+			return -EINVAL;
+
+		if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
+			answ = 0;
+		else
+			answ = tp->write_seq - tp->snd_nxt;
+		break;
 	default:
 		return -ENOIOCTLCMD;
 	}
@@ -873,9 +882,7 @@ int tcp_sendpage(struct sock *sk, struct page *page, int offset,
 					flags);
 
 	lock_sock(sk);
-	TCP_CHECK_TIMER(sk);
 	res = do_tcp_sendpages(sk, &page, offset, size, flags);
-	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
 	return res;
 }
@@ -916,7 +923,6 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	long timeo;
 
 	lock_sock(sk);
-	TCP_CHECK_TIMER(sk);
 
 	flags = msg->msg_flags;
 	timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
@@ -1104,7 +1110,6 @@ wait_for_memory:
 out:
 	if (copied)
 		tcp_push(sk, flags, mss_now, tp->nonagle);
-	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
 	return copied;
 
@@ -1123,7 +1128,6 @@ do_error:
 		goto out;
 out_err:
 	err = sk_stream_error(sk, flags, err);
-	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
 	return err;
 }
@@ -1415,8 +1419,6 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
 	lock_sock(sk);
 
-	TCP_CHECK_TIMER(sk);
-
 	err = -ENOTCONN;
 	if (sk->sk_state == TCP_LISTEN)
 		goto out;
@@ -1767,12 +1769,10 @@ skip_copy:
 	/* Clean up data we have read: This will do ACK frames. */
 	tcp_cleanup_rbuf(sk, copied);
 
-	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
 	return copied;
 
 out:
-	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
 	return err;
 
@@ -2653,7 +2653,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
 EXPORT_SYMBOL(compat_tcp_getsockopt);
 #endif
 
-struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
+struct sk_buff *tcp_tso_segment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct tcphdr *th;
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 3b53fd1..6187eb4 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -209,7 +209,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt)
 }
 
 
-static struct tcp_congestion_ops bictcp = {
+static struct tcp_congestion_ops bictcp __read_mostly = {
 	.init		= bictcp_init,
 	.ssthresh	= bictcp_recalc_ssthresh,
 	.cong_avoid	= bictcp_cong_avoid,
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 71d5f2f..34340c9 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -39,7 +39,7 @@
 
 /* Number of delay samples for detecting the increase of delay */
 #define HYSTART_MIN_SAMPLES	8
-#define HYSTART_DELAY_MIN	(2U<<3)
+#define HYSTART_DELAY_MIN	(4U<<3)
 #define HYSTART_DELAY_MAX	(16U<<3)
 #define HYSTART_DELAY_THRESH(x)	clamp(x, HYSTART_DELAY_MIN, HYSTART_DELAY_MAX)
 
@@ -52,6 +52,7 @@ static int tcp_friendliness __read_mostly = 1;
 static int hystart __read_mostly = 1;
 static int hystart_detect __read_mostly = HYSTART_ACK_TRAIN | HYSTART_DELAY;
 static int hystart_low_window __read_mostly = 16;
+static int hystart_ack_delta __read_mostly = 2;
 
 static u32 cube_rtt_scale __read_mostly;
 static u32 beta_scale __read_mostly;
@@ -75,6 +76,8 @@ MODULE_PARM_DESC(hystart_detect, "hyrbrid slow start detection mechanisms"
 		 " 1: packet-train 2: delay 3: both packet-train and delay");
 module_param(hystart_low_window, int, 0644);
 MODULE_PARM_DESC(hystart_low_window, "lower bound cwnd for hybrid slow start");
+module_param(hystart_ack_delta, int, 0644);
+MODULE_PARM_DESC(hystart_ack_delta, "spacing between ack's indicating train (msecs)");
 
 /* BIC TCP Parameters */
 struct bictcp {
@@ -85,7 +88,7 @@ struct bictcp {
 	u32	last_time;	/* time when updated last_cwnd */
 	u32	bic_origin_point;/* origin point of bic function */
 	u32	bic_K;		/* time to origin point from the beginning of the current epoch */
-	u32	delay_min;	/* min delay */
+	u32	delay_min;	/* min delay (msec << 3) */
 	u32	epoch_start;	/* beginning of an epoch */
 	u32	ack_cnt;	/* number of acks */
 	u32	tcp_cwnd;	/* estimated tcp cwnd */
@@ -95,7 +98,7 @@ struct bictcp {
 	u8	found;		/* the exit point is found? */
 	u32	round_start;	/* beginning of each round */
 	u32	end_seq;	/* end_seq of the round */
-	u32	last_jiffies;	/* last time when the ACK spacing is close */
+	u32	last_ack;	/* last time when the ACK spacing is close */
 	u32	curr_rtt;	/* the minimum rtt of current round */
 };
 
@@ -116,12 +119,21 @@ static inline void bictcp_reset(struct bictcp *ca)
 	ca->found = 0;
 }
 
+static inline u32 bictcp_clock(void)
+{
+#if HZ < 1000
+	return ktime_to_ms(ktime_get_real());
+#else
+	return jiffies_to_msecs(jiffies);
+#endif
+}
+
 static inline void bictcp_hystart_reset(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct bictcp *ca = inet_csk_ca(sk);
 
-	ca->round_start = ca->last_jiffies = jiffies;
+	ca->round_start = ca->last_ack = bictcp_clock();
 	ca->end_seq = tp->snd_nxt;
 	ca->curr_rtt = 0;
 	ca->sample_cnt = 0;
@@ -236,8 +248,8 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 	 */
 
 	/* change the unit from HZ to bictcp_HZ */
-	t = ((tcp_time_stamp + (ca->delay_min>>3) - ca->epoch_start)
-	     << BICTCP_HZ) / HZ;
+	t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3)
+	      - ca->epoch_start) << BICTCP_HZ) / HZ;
 
 	if (t < ca->bic_K)		/* t - K */
 		offs = ca->bic_K - t;
@@ -258,6 +270,13 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
 		ca->cnt = 100 * cwnd;              /* very small increment*/
 	}
 
+	/*
+	 * The initial growth of cubic function may be too conservative
+	 * when the available bandwidth is still unknown.
+	 */
+	if (ca->loss_cwnd == 0 && ca->cnt > 20)
+		ca->cnt = 20;	/* increase cwnd 5% per RTT */
+
 	/* TCP Friendly */
 	if (tcp_friendliness) {
 		u32 scale = beta_scale;
@@ -339,12 +358,12 @@ static void hystart_update(struct sock *sk, u32 delay)
 	struct bictcp *ca = inet_csk_ca(sk);
 
 	if (!(ca->found & hystart_detect)) {
-		u32 curr_jiffies = jiffies;
+		u32 now = bictcp_clock();
 
 		/* first detection parameter - ack-train detection */
-		if (curr_jiffies - ca->last_jiffies <= msecs_to_jiffies(2)) {
-			ca->last_jiffies = curr_jiffies;
-			if (curr_jiffies - ca->round_start >= ca->delay_min>>4)
+		if ((s32)(now - ca->last_ack) <= hystart_ack_delta) {
+			ca->last_ack = now;
+			if ((s32)(now - ca->round_start) > ca->delay_min >> 4)
 				ca->found |= HYSTART_ACK_TRAIN;
 		}
 
@@ -391,7 +410,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
 	if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ)
 		return;
 
-	delay = usecs_to_jiffies(rtt_us) << 3;
+	delay = (rtt_us << 3) / USEC_PER_MSEC;
 	if (delay == 0)
 		delay = 1;
 
@@ -405,7 +424,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
 		hystart_update(sk, delay);
 }
 
-static struct tcp_congestion_ops cubictcp = {
+static struct tcp_congestion_ops cubictcp __read_mostly = {
 	.init		= bictcp_init,
 	.ssthresh	= bictcp_recalc_ssthresh,
 	.cong_avoid	= bictcp_cong_avoid,
@@ -447,6 +466,10 @@ static int __init cubictcp_register(void)
 	/* divide by bic_scale and by constant Srtt (100ms) */
 	do_div(cube_factor, bic_scale * 10);
 
+	/* hystart needs ms clock resolution */
+	if (hystart && HZ < 1000)
+		cubictcp.flags |= TCP_CONG_RTT_STAMP;
+
 	return tcp_register_congestion_control(&cubictcp);
 }
 
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index 8b6caaf..30f27f6 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -158,7 +158,7 @@ static u32 hstcp_ssthresh(struct sock *sk)
 }
 
 
-static struct tcp_congestion_ops tcp_highspeed = {
+static struct tcp_congestion_ops tcp_highspeed __read_mostly = {
 	.init		= hstcp_init,
 	.ssthresh	= hstcp_ssthresh,
 	.cong_avoid	= hstcp_cong_avoid,
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 7c94a49..c1a8175 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -284,7 +284,7 @@ static void htcp_state(struct sock *sk, u8 new_state)
 	}
 }
 
-static struct tcp_congestion_ops htcp = {
+static struct tcp_congestion_ops htcp __read_mostly = {
 	.init		= htcp_init,
 	.ssthresh	= htcp_recalc_ssthresh,
 	.cong_avoid	= htcp_cong_avoid,
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index 377bc93..fe3ecf4 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -162,7 +162,7 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
 	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
 }
 
-static struct tcp_congestion_ops tcp_hybla = {
+static struct tcp_congestion_ops tcp_hybla __read_mostly = {
 	.init		= hybla_init,
 	.ssthresh	= tcp_reno_ssthresh,
 	.min_cwnd	= tcp_reno_min_cwnd,
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c
index 00ca688..813b43a 100644
--- a/net/ipv4/tcp_illinois.c
+++ b/net/ipv4/tcp_illinois.c
@@ -322,7 +322,7 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
 	}
 }
 
-static struct tcp_congestion_ops tcp_illinois = {
+static struct tcp_congestion_ops tcp_illinois __read_mostly = {
 	.flags		= TCP_CONG_RTT_STAMP,
 	.init		= tcp_illinois_init,
 	.ssthresh	= tcp_illinois_ssthresh,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 65f6c04..da782e7 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -817,7 +817,7 @@ __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst)
 	__u32 cwnd = (dst ? dst_metric(dst, RTAX_INITCWND) : 0);
 
 	if (!cwnd)
-		cwnd = rfc3390_bytes_to_packets(tp->mss_cache);
+		cwnd = TCP_INIT_CWND;
 	return min_t(__u32, cwnd, tp->snd_cwnd_clamp);
 }
 
@@ -3350,7 +3350,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
 						 net_invalid_timestamp()))
 					rtt_us = ktime_us_delta(ktime_get_real(),
 								last_ackt);
-				else if (ca_seq_rtt > 0)
+				else if (ca_seq_rtt >= 0)
 					rtt_us = jiffies_to_usecs(ca_seq_rtt);
 			}
 
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 02f583b..f7e6c2c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -149,9 +149,9 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	struct inet_sock *inet = inet_sk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
+	__be16 orig_sport, orig_dport;
 	struct rtable *rt;
 	__be32 daddr, nexthop;
-	int tmp;
 	int err;
 
 	if (addr_len < sizeof(struct sockaddr_in))
@@ -167,14 +167,17 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 		nexthop = inet->opt->faddr;
 	}
 
-	tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr,
-			       RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
-			       IPPROTO_TCP,
-			       inet->inet_sport, usin->sin_port, sk, 1);
-	if (tmp < 0) {
-		if (tmp == -ENETUNREACH)
+	orig_sport = inet->inet_sport;
+	orig_dport = usin->sin_port;
+	rt = ip_route_connect(nexthop, inet->inet_saddr,
+			      RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
+			      IPPROTO_TCP,
+			      orig_sport, orig_dport, sk, true);
+	if (IS_ERR(rt)) {
+		err = PTR_ERR(rt);
+		if (err == -ENETUNREACH)
 			IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
-		return tmp;
+		return err;
 	}
 
 	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
@@ -233,11 +236,14 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	if (err)
 		goto failure;
 
-	err = ip_route_newports(&rt, IPPROTO_TCP,
-				inet->inet_sport, inet->inet_dport, sk);
-	if (err)
+	rt = ip_route_newports(rt, IPPROTO_TCP,
+			       orig_sport, orig_dport,
+			       inet->inet_sport, inet->inet_dport, sk);
+	if (IS_ERR(rt)) {
+		err = PTR_ERR(rt);
+		rt = NULL;
 		goto failure;
-
+	}
 	/* OK, now commit destination to socket.  */
 	sk->sk_gso_type = SKB_GSO_TCPV4;
 	sk_setup_caps(sk, &rt->dst);
@@ -1341,7 +1347,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 		    tcp_death_row.sysctl_tw_recycle &&
 		    (dst = inet_csk_route_req(sk, req)) != NULL &&
 		    (peer = rt_get_peer((struct rtable *)dst)) != NULL &&
-		    peer->daddr.a4 == saddr) {
+		    peer->daddr.addr.a4 == saddr) {
 			inet_peer_refcheck(peer);
 			if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
 			    (s32)(peer->tcp_ts - req->ts_recent) >
@@ -1556,12 +1562,10 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 
 	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
 		sock_rps_save_rxhash(sk, skb->rxhash);
-		TCP_CHECK_TIMER(sk);
 		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
 			rsk = sk;
 			goto reset;
 		}
-		TCP_CHECK_TIMER(sk);
 		return 0;
 	}
 
@@ -1583,13 +1587,10 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
 	} else
 		sock_rps_save_rxhash(sk, skb->rxhash);
 
-
-	TCP_CHECK_TIMER(sk);
 	if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) {
 		rsk = sk;
 		goto reset;
 	}
-	TCP_CHECK_TIMER(sk);
 	return 0;
 
 reset:
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index de87037..656d431 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -313,7 +313,7 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, s32 rtt_us)
 	lp->last_drop = tcp_time_stamp;
 }
 
-static struct tcp_congestion_ops tcp_lp = {
+static struct tcp_congestion_ops tcp_lp __read_mostly = {
 	.flags = TCP_CONG_RTT_STAMP,
 	.init = tcp_lp_init,
 	.ssthresh = tcp_reno_ssthresh,
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
index a765137..8ce55b8 100644
--- a/net/ipv4/tcp_scalable.c
+++ b/net/ipv4/tcp_scalable.c
@@ -35,7 +35,7 @@ static u32 tcp_scalable_ssthresh(struct sock *sk)
 }
 
 
-static struct tcp_congestion_ops tcp_scalable = {
+static struct tcp_congestion_ops tcp_scalable __read_mostly = {
 	.ssthresh	= tcp_scalable_ssthresh,
 	.cong_avoid	= tcp_scalable_cong_avoid,
 	.min_cwnd	= tcp_reno_min_cwnd,
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 74a6aa0..ecd44b0 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -259,7 +259,6 @@ static void tcp_delack_timer(unsigned long data)
 		tcp_send_ack(sk);
 		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKS);
 	}
-	TCP_CHECK_TIMER(sk);
 
 out:
 	if (tcp_memory_pressure)
@@ -481,7 +480,6 @@ static void tcp_write_timer(unsigned long data)
 		tcp_probe_timer(sk);
 		break;
 	}
-	TCP_CHECK_TIMER(sk);
 
 out:
 	sk_mem_reclaim(sk);
@@ -589,7 +587,6 @@ static void tcp_keepalive_timer (unsigned long data)
 		elapsed = keepalive_time_when(tp) - elapsed;
 	}
 
-	TCP_CHECK_TIMER(sk);
 	sk_mem_reclaim(sk);
 
 resched:
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index c6743ee..80fa2bf 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -304,7 +304,7 @@ void tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(tcp_vegas_get_info);
 
-static struct tcp_congestion_ops tcp_vegas = {
+static struct tcp_congestion_ops tcp_vegas __read_mostly = {
 	.flags		= TCP_CONG_RTT_STAMP,
 	.init		= tcp_vegas_init,
 	.ssthresh	= tcp_reno_ssthresh,
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
index 38bc0b5..ac43cd7 100644
--- a/net/ipv4/tcp_veno.c
+++ b/net/ipv4/tcp_veno.c
@@ -201,7 +201,7 @@ static u32 tcp_veno_ssthresh(struct sock *sk)
 		return max(tp->snd_cwnd >> 1U, 2U);
 }
 
-static struct tcp_congestion_ops tcp_veno = {
+static struct tcp_congestion_ops tcp_veno __read_mostly = {
 	.flags		= TCP_CONG_RTT_STAMP,
 	.init		= tcp_veno_init,
 	.ssthresh	= tcp_veno_ssthresh,
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index a534dda..1b91bf4 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -272,7 +272,7 @@ static void tcp_westwood_info(struct sock *sk, u32 ext,
 }
 
 
-static struct tcp_congestion_ops tcp_westwood = {
+static struct tcp_congestion_ops tcp_westwood __read_mostly = {
 	.init		= tcp_westwood_init,
 	.ssthresh	= tcp_reno_ssthresh,
 	.cong_avoid	= tcp_reno_cong_avoid,
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c
index a0f2403..dc7f431 100644
--- a/net/ipv4/tcp_yeah.c
+++ b/net/ipv4/tcp_yeah.c
@@ -225,7 +225,7 @@ static u32 tcp_yeah_ssthresh(struct sock *sk) {
 	return tp->snd_cwnd - reduction;
 }
 
-static struct tcp_congestion_ops tcp_yeah = {
+static struct tcp_congestion_ops tcp_yeah __read_mostly = {
 	.flags		= TCP_CONG_RTT_STAMP,
 	.init		= tcp_yeah_init,
 	.ssthresh	= tcp_yeah_ssthresh,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8157b17..588f47a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -663,75 +663,72 @@ void udp_flush_pending_frames(struct sock *sk)
 EXPORT_SYMBOL(udp_flush_pending_frames);
 
 /**
- * 	udp4_hwcsum_outgoing  -  handle outgoing HW checksumming
- * 	@sk: 	socket we are sending on
+ * 	udp4_hwcsum  -  handle outgoing HW checksumming
  * 	@skb: 	sk_buff containing the filled-in UDP header
  * 	        (checksum field must be zeroed out)
+ *	@src:	source IP address
+ *	@dst:	destination IP address
  */
-static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb,
-				 __be32 src, __be32 dst, int len)
+static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
 {
-	unsigned int offset;
 	struct udphdr *uh = udp_hdr(skb);
+	struct sk_buff *frags = skb_shinfo(skb)->frag_list;
+	int offset = skb_transport_offset(skb);
+	int len = skb->len - offset;
+	int hlen = len;
 	__wsum csum = 0;
 
-	if (skb_queue_len(&sk->sk_write_queue) == 1) {
+	if (!frags) {
 		/*
 		 * Only one fragment on the socket.
 		 */
 		skb->csum_start = skb_transport_header(skb) - skb->head;
 		skb->csum_offset = offsetof(struct udphdr, check);
-		uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0);
+		uh->check = ~csum_tcpudp_magic(src, dst, len,
+					       IPPROTO_UDP, 0);
 	} else {
 		/*
 		 * HW-checksum won't work as there are two or more
 		 * fragments on the socket so that all csums of sk_buffs
 		 * should be together
 		 */
-		offset = skb_transport_offset(skb);
-		skb->csum = skb_checksum(skb, offset, skb->len - offset, 0);
+		do {
+			csum = csum_add(csum, frags->csum);
+			hlen -= frags->len;
+		} while ((frags = frags->next));
 
+		csum = skb_checksum(skb, offset, hlen, csum);
 		skb->ip_summed = CHECKSUM_NONE;
 
-		skb_queue_walk(&sk->sk_write_queue, skb) {
-			csum = csum_add(csum, skb->csum);
-		}
-
 		uh->check = csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, csum);
 		if (uh->check == 0)
 			uh->check = CSUM_MANGLED_0;
 	}
 }
 
-/*
- * Push out all pending data as one UDP datagram. Socket is locked.
- */
-static int udp_push_pending_frames(struct sock *sk)
+static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport)
 {
-	struct udp_sock  *up = udp_sk(sk);
+	struct sock *sk = skb->sk;
 	struct inet_sock *inet = inet_sk(sk);
-	struct flowi *fl = &inet->cork.fl;
-	struct sk_buff *skb;
 	struct udphdr *uh;
+	struct rtable *rt = (struct rtable *)skb_dst(skb);
 	int err = 0;
 	int is_udplite = IS_UDPLITE(sk);
+	int offset = skb_transport_offset(skb);
+	int len = skb->len - offset;
 	__wsum csum = 0;
 
-	/* Grab the skbuff where UDP header space exists. */
-	if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
-		goto out;
-
 	/*
 	 * Create a UDP header
 	 */
 	uh = udp_hdr(skb);
-	uh->source = fl->fl_ip_sport;
-	uh->dest = fl->fl_ip_dport;
-	uh->len = htons(up->len);
+	uh->source = inet->inet_sport;
+	uh->dest = dport;
+	uh->len = htons(len);
 	uh->check = 0;
 
 	if (is_udplite)  				 /*     UDP-Lite      */
-		csum  = udplite_csum_outgoing(sk, skb);
+		csum = udplite_csum(skb);
 
 	else if (sk->sk_no_check == UDP_CSUM_NOXMIT) {   /* UDP csum disabled */
 
@@ -740,20 +737,20 @@ static int udp_push_pending_frames(struct sock *sk)
 
 	} else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
 
-		udp4_hwcsum_outgoing(sk, skb, fl->fl4_src, fl->fl4_dst, up->len);
+		udp4_hwcsum(skb, rt->rt_src, daddr);
 		goto send;
 
-	} else						 /*   `normal' UDP    */
-		csum = udp_csum_outgoing(sk, skb);
+	} else
+		csum = udp_csum(skb);
 
 	/* add protocol-dependent pseudo-header */
-	uh->check = csum_tcpudp_magic(fl->fl4_src, fl->fl4_dst, up->len,
+	uh->check = csum_tcpudp_magic(rt->rt_src, daddr, len,
 				      sk->sk_protocol, csum);
 	if (uh->check == 0)
 		uh->check = CSUM_MANGLED_0;
 
 send:
-	err = ip_push_pending_frames(sk);
+	err = ip_send_skb(skb);
 	if (err) {
 		if (err == -ENOBUFS && !inet->recverr) {
 			UDP_INC_STATS_USER(sock_net(sk),
@@ -763,6 +760,26 @@ send:
 	} else
 		UDP_INC_STATS_USER(sock_net(sk),
 				   UDP_MIB_OUTDATAGRAMS, is_udplite);
+	return err;
+}
+
+/*
+ * Push out all pending data as one UDP datagram. Socket is locked.
+ */
+static int udp_push_pending_frames(struct sock *sk)
+{
+	struct udp_sock  *up = udp_sk(sk);
+	struct inet_sock *inet = inet_sk(sk);
+	struct flowi4 *fl4 = &inet->cork.fl.u.ip4;
+	struct sk_buff *skb;
+	int err = 0;
+
+	skb = ip_finish_skb(sk);
+	if (!skb)
+		goto out;
+
+	err = udp_send_skb(skb, fl4->daddr, fl4->fl4_dport);
+
 out:
 	up->len = 0;
 	up->pending = 0;
@@ -774,6 +791,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct udp_sock *up = udp_sk(sk);
+	struct flowi4 *fl4;
 	int ulen = len;
 	struct ipcm_cookie ipc;
 	struct rtable *rt = NULL;
@@ -785,6 +803,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	int err, is_udplite = IS_UDPLITE(sk);
 	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
 	int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
+	struct sk_buff *skb;
 
 	if (len > 0xFFFF)
 		return -EMSGSIZE;
@@ -799,6 +818,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 	ipc.opt = NULL;
 	ipc.tx_flags = 0;
 
+	getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
+
 	if (up->pending) {
 		/*
 		 * There are pending frames.
@@ -888,20 +909,25 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 		rt = (struct rtable *)sk_dst_check(sk, 0);
 
 	if (rt == NULL) {
-		struct flowi fl = { .oif = ipc.oif,
-				    .mark = sk->sk_mark,
-				    .fl4_dst = faddr,
-				    .fl4_src = saddr,
-				    .fl4_tos = tos,
-				    .proto = sk->sk_protocol,
-				    .flags = inet_sk_flowi_flags(sk),
-				    .fl_ip_sport = inet->inet_sport,
-				    .fl_ip_dport = dport };
+		struct flowi4 fl4 = {
+			.flowi4_oif = ipc.oif,
+			.flowi4_mark = sk->sk_mark,
+			.daddr = faddr,
+			.saddr = saddr,
+			.flowi4_tos = tos,
+			.flowi4_proto = sk->sk_protocol,
+			.flowi4_flags = (inet_sk_flowi_flags(sk) |
+					 FLOWI_FLAG_CAN_SLEEP),
+			.fl4_sport = inet->inet_sport,
+			.fl4_dport = dport,
+		};
 		struct net *net = sock_net(sk);
 
-		security_sk_classify_flow(sk, &fl);
-		err = ip_route_output_flow(net, &rt, &fl, sk, 1);
-		if (err) {
+		security_sk_classify_flow(sk, flowi4_to_flowi(&fl4));
+		rt = ip_route_output_flow(net, &fl4, sk);
+		if (IS_ERR(rt)) {
+			err = PTR_ERR(rt);
+			rt = NULL;
 			if (err == -ENETUNREACH)
 				IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
 			goto out;
@@ -923,6 +949,17 @@ back_from_confirm:
 	if (!ipc.addr)
 		daddr = ipc.addr = rt->rt_dst;
 
+	/* Lockless fast path for the non-corking case. */
+	if (!corkreq) {
+		skb = ip_make_skb(sk, getfrag, msg->msg_iov, ulen,
+				  sizeof(struct udphdr), &ipc, &rt,
+				  msg->msg_flags);
+		err = PTR_ERR(skb);
+		if (skb && !IS_ERR(skb))
+			err = udp_send_skb(skb, daddr, dport);
+		goto out;
+	}
+
 	lock_sock(sk);
 	if (unlikely(up->pending)) {
 		/* The socket is already corked while preparing it. */
@@ -936,15 +973,15 @@ back_from_confirm:
 	/*
 	 *	Now cork the socket to pend data.
 	 */
-	inet->cork.fl.fl4_dst = daddr;
-	inet->cork.fl.fl_ip_dport = dport;
-	inet->cork.fl.fl4_src = saddr;
-	inet->cork.fl.fl_ip_sport = inet->inet_sport;
+	fl4 = &inet->cork.fl.u.ip4;
+	fl4->daddr = daddr;
+	fl4->saddr = saddr;
+	fl4->fl4_dport = dport;
+	fl4->fl4_sport = inet->inet_sport;
 	up->pending = AF_INET;
 
 do_append_data:
 	up->len += ulen;
-	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
 	err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
 			sizeof(struct udphdr), &ipc, &rt,
 			corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags);
@@ -2199,7 +2236,7 @@ int udp4_ufo_send_check(struct sk_buff *skb)
 	return 0;
 }
 
-struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, int features)
+struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index b057d40..13e0e7f 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -19,25 +19,23 @@
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
 
 static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos,
-					  xfrm_address_t *saddr,
-					  xfrm_address_t *daddr)
+					  const xfrm_address_t *saddr,
+					  const xfrm_address_t *daddr)
 {
-	struct flowi fl = {
-		.fl4_dst = daddr->a4,
-		.fl4_tos = tos,
+	struct flowi4 fl4 = {
+		.daddr = daddr->a4,
+		.flowi4_tos = tos,
 	};
-	struct dst_entry *dst;
 	struct rtable *rt;
-	int err;
 
 	if (saddr)
-		fl.fl4_src = saddr->a4;
+		fl4.saddr = saddr->a4;
+
+	rt = __ip_route_output_key(net, &fl4);
+	if (!IS_ERR(rt))
+		return &rt->dst;
 
-	err = __ip_route_output_key(net, &rt, &fl);
-	dst = &rt->dst;
-	if (err)
-		dst = ERR_PTR(err);
-	return dst;
+	return ERR_CAST(rt);
 }
 
 static int xfrm4_get_saddr(struct net *net,
@@ -56,9 +54,9 @@ static int xfrm4_get_saddr(struct net *net,
 	return 0;
 }
 
-static int xfrm4_get_tos(struct flowi *fl)
+static int xfrm4_get_tos(const struct flowi *fl)
 {
-	return IPTOS_RT_MASK & fl->fl4_tos; /* Strip ECN bits */
+	return IPTOS_RT_MASK & fl->u.ip4.flowi4_tos; /* Strip ECN bits */
 }
 
 static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
@@ -68,11 +66,17 @@ static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
 }
 
 static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
-			  struct flowi *fl)
+			  const struct flowi *fl)
 {
 	struct rtable *rt = (struct rtable *)xdst->route;
+	const struct flowi4 *fl4 = &fl->u.ip4;
 
-	xdst->u.rt.fl = *fl;
+	rt->rt_key_dst = fl4->daddr;
+	rt->rt_key_src = fl4->saddr;
+	rt->rt_tos = fl4->flowi4_tos;
+	rt->rt_iif = fl4->flowi4_iif;
+	rt->rt_oif = fl4->flowi4_oif;
+	rt->rt_mark = fl4->flowi4_mark;
 
 	xdst->u.dst.dev = dev;
 	dev_hold(dev);
@@ -99,9 +103,10 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 {
 	struct iphdr *iph = ip_hdr(skb);
 	u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
+	struct flowi4 *fl4 = &fl->u.ip4;
 
-	memset(fl, 0, sizeof(struct flowi));
-	fl->mark = skb->mark;
+	memset(fl4, 0, sizeof(struct flowi4));
+	fl4->flowi4_mark = skb->mark;
 
 	if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) {
 		switch (iph->protocol) {
@@ -114,8 +119,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 			    pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				__be16 *ports = (__be16 *)xprth;
 
-				fl->fl_ip_sport = ports[!!reverse];
-				fl->fl_ip_dport = ports[!reverse];
+				fl4->fl4_sport = ports[!!reverse];
+				fl4->fl4_dport = ports[!reverse];
 			}
 			break;
 
@@ -123,8 +128,8 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 			if (pskb_may_pull(skb, xprth + 2 - skb->data)) {
 				u8 *icmp = xprth;
 
-				fl->fl_icmp_type = icmp[0];
-				fl->fl_icmp_code = icmp[1];
+				fl4->fl4_icmp_type = icmp[0];
+				fl4->fl4_icmp_code = icmp[1];
 			}
 			break;
 
@@ -132,7 +137,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				__be32 *ehdr = (__be32 *)xprth;
 
-				fl->fl_ipsec_spi = ehdr[0];
+				fl4->fl4_ipsec_spi = ehdr[0];
 			}
 			break;
 
@@ -140,7 +145,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 			if (pskb_may_pull(skb, xprth + 8 - skb->data)) {
 				__be32 *ah_hdr = (__be32*)xprth;
 
-				fl->fl_ipsec_spi = ah_hdr[1];
+				fl4->fl4_ipsec_spi = ah_hdr[1];
 			}
 			break;
 
@@ -148,7 +153,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 			if (pskb_may_pull(skb, xprth + 4 - skb->data)) {
 				__be16 *ipcomp_hdr = (__be16 *)xprth;
 
-				fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
+				fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
 			}
 			break;
 
@@ -160,20 +165,20 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
 				if (greflags[0] & GRE_KEY) {
 					if (greflags[0] & GRE_CSUM)
 						gre_hdr++;
-					fl->fl_gre_key = gre_hdr[1];
+					fl4->fl4_gre_key = gre_hdr[1];
 				}
 			}
 			break;
 
 		default:
-			fl->fl_ipsec_spi = 0;
+			fl4->fl4_ipsec_spi = 0;
 			break;
 		}
 	}
-	fl->proto = iph->protocol;
-	fl->fl4_dst = reverse ? iph->saddr : iph->daddr;
-	fl->fl4_src = reverse ? iph->daddr : iph->saddr;
-	fl->fl4_tos = iph->tos;
+	fl4->flowi4_proto = iph->protocol;
+	fl4->daddr = reverse ? iph->saddr : iph->daddr;
+	fl4->saddr = reverse ? iph->daddr : iph->saddr;
+	fl4->flowi4_tos = iph->tos;
 }
 
 static inline int xfrm4_garbage_collect(struct dst_ops *ops)
@@ -196,8 +201,11 @@ static void xfrm4_dst_destroy(struct dst_entry *dst)
 {
 	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
 
+	dst_destroy_metrics_generic(dst);
+
 	if (likely(xdst->u.rt.peer))
 		inet_putpeer(xdst->u.rt.peer);
+
 	xfrm_dst_destroy(xdst);
 }
 
@@ -215,6 +223,7 @@ static struct dst_ops xfrm4_dst_ops = {
 	.protocol =		cpu_to_be16(ETH_P_IP),
 	.gc =			xfrm4_garbage_collect,
 	.update_pmtu =		xfrm4_update_pmtu,
+	.cow_metrics =		dst_cow_metrics_generic,
 	.destroy =		xfrm4_dst_destroy,
 	.ifdown =		xfrm4_dst_ifdown,
 	.local_out =		__ip_local_out,
@@ -230,6 +239,7 @@ static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
 	.get_tos =		xfrm4_get_tos,
 	.init_path =		xfrm4_init_path,
 	.fill_dst =		xfrm4_fill_dst,
+	.blackhole_route =	ipv4_blackhole_route,
 };
 
 #ifdef CONFIG_SYSCTL
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 4794762..1717c64 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -21,24 +21,26 @@ static int xfrm4_init_flags(struct xfrm_state *x)
 }
 
 static void
-__xfrm4_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
+__xfrm4_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
 {
-	sel->daddr.a4 = fl->fl4_dst;
-	sel->saddr.a4 = fl->fl4_src;
-	sel->dport = xfrm_flowi_dport(fl);
+	const struct flowi4 *fl4 = &fl->u.ip4;
+
+	sel->daddr.a4 = fl4->daddr;
+	sel->saddr.a4 = fl4->saddr;
+	sel->dport = xfrm_flowi_dport(fl, &fl4->uli);
 	sel->dport_mask = htons(0xffff);
-	sel->sport = xfrm_flowi_sport(fl);
+	sel->sport = xfrm_flowi_sport(fl, &fl4->uli);
 	sel->sport_mask = htons(0xffff);
 	sel->family = AF_INET;
 	sel->prefixlen_d = 32;
 	sel->prefixlen_s = 32;
-	sel->proto = fl->proto;
-	sel->ifindex = fl->oif;
+	sel->proto = fl4->flowi4_proto;
+	sel->ifindex = fl4->flowi4_oif;
 }
 
 static void
-xfrm4_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
-		   xfrm_address_t *daddr, xfrm_address_t *saddr)
+xfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl,
+		   const xfrm_address_t *daddr, const xfrm_address_t *saddr)
 {
 	x->id = tmpl->id;
 	if (x->id.daddr.a4 == 0)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index fd6782e..3daaf3c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -718,12 +718,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
 	struct inet6_ifaddr *ifa, *ifn;
 	struct inet6_dev *idev = ifp->idev;
 	int state;
-	int hash;
 	int deleted = 0, onlink = 0;
 	unsigned long expires = jiffies;
 
-	hash = ipv6_addr_hash(&ifp->addr);
-
 	spin_lock_bh(&ifp->state_lock);
 	state = ifp->state;
 	ifp->state = INET6_IFADDR_STATE_DEAD;
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 978e80e..4b13d5d 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -644,41 +644,34 @@ EXPORT_SYMBOL(inet6_unregister_protosw);
 
 int inet6_sk_rebuild_header(struct sock *sk)
 {
-	int err;
-	struct dst_entry *dst;
 	struct ipv6_pinfo *np = inet6_sk(sk);
+	struct dst_entry *dst;
 
 	dst = __sk_dst_check(sk, np->dst_cookie);
 
 	if (dst == NULL) {
 		struct inet_sock *inet = inet_sk(sk);
 		struct in6_addr *final_p, final;
-		struct flowi fl;
-
-		memset(&fl, 0, sizeof(fl));
-		fl.proto = sk->sk_protocol;
-		ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-		fl.fl6_flowlabel = np->flow_label;
-		fl.oif = sk->sk_bound_dev_if;
-		fl.mark = sk->sk_mark;
-		fl.fl_ip_dport = inet->inet_dport;
-		fl.fl_ip_sport = inet->inet_sport;
-		security_sk_classify_flow(sk, &fl);
-
-		final_p = fl6_update_dst(&fl, np->opt, &final);
-
-		err = ip6_dst_lookup(sk, &dst, &fl);
-		if (err) {
+		struct flowi6 fl6;
+
+		memset(&fl6, 0, sizeof(fl6));
+		fl6.flowi6_proto = sk->sk_protocol;
+		ipv6_addr_copy(&fl6.daddr, &np->daddr);
+		ipv6_addr_copy(&fl6.saddr, &np->saddr);
+		fl6.flowlabel = np->flow_label;
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
+		fl6.flowi6_mark = sk->sk_mark;
+		fl6.fl6_dport = inet->inet_dport;
+		fl6.fl6_sport = inet->inet_sport;
+		security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
+
+		final_p = fl6_update_dst(&fl6, np->opt, &final);
+
+		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+		if (IS_ERR(dst)) {
 			sk->sk_route_caps = 0;
-			return err;
-		}
-		if (final_p)
-			ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-		if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) {
-			sk->sk_err_soft = -err;
-			return err;
+			sk->sk_err_soft = -PTR_ERR(dst);
+			return PTR_ERR(dst);
 		}
 
 		__ip6_dst_store(sk, dst, NULL, NULL);
@@ -772,7 +765,7 @@ out:
 	return err;
 }
 
-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, int features)
+static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	struct ipv6hdr *ipv6h;
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 1aba54a..2195ae6 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -409,7 +409,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
 
 	ah->reserved = 0;
 	ah->spi = x->id.spi;
-	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
+	ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg, 0, skb->len);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 320bdb8..1656033 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -40,7 +40,7 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	struct ipv6_pinfo      	*np = inet6_sk(sk);
 	struct in6_addr		*daddr, *final_p, final;
 	struct dst_entry	*dst;
-	struct flowi		fl;
+	struct flowi6		fl6;
 	struct ip6_flowlabel	*flowlabel = NULL;
 	struct ipv6_txoptions   *opt;
 	int			addr_type;
@@ -59,11 +59,11 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 	if (usin->sin6_family != AF_INET6)
 		return -EAFNOSUPPORT;
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 	if (np->sndflow) {
-		fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-		if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
-			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+		fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+		if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
+			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 			if (flowlabel == NULL)
 				return -EINVAL;
 			ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
@@ -137,7 +137,7 @@ ipv4_connected:
 	}
 
 	ipv6_addr_copy(&np->daddr, daddr);
-	np->flow_label = fl.fl6_flowlabel;
+	np->flow_label = fl6.flowlabel;
 
 	inet->inet_dport = usin->sin6_port;
 
@@ -146,53 +146,46 @@ ipv4_connected:
 	 *	destination cache for it.
 	 */
 
-	fl.proto = sk->sk_protocol;
-	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-	ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-	fl.oif = sk->sk_bound_dev_if;
-	fl.mark = sk->sk_mark;
-	fl.fl_ip_dport = inet->inet_dport;
-	fl.fl_ip_sport = inet->inet_sport;
+	fl6.flowi6_proto = sk->sk_protocol;
+	ipv6_addr_copy(&fl6.daddr, &np->daddr);
+	ipv6_addr_copy(&fl6.saddr, &np->saddr);
+	fl6.flowi6_oif = sk->sk_bound_dev_if;
+	fl6.flowi6_mark = sk->sk_mark;
+	fl6.fl6_dport = inet->inet_dport;
+	fl6.fl6_sport = inet->inet_sport;
 
-	if (!fl.oif && (addr_type&IPV6_ADDR_MULTICAST))
-		fl.oif = np->mcast_oif;
+	if (!fl6.flowi6_oif && (addr_type&IPV6_ADDR_MULTICAST))
+		fl6.flowi6_oif = np->mcast_oif;
 
-	security_sk_classify_flow(sk, &fl);
+	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
 	opt = flowlabel ? flowlabel->opt : np->opt;
-	final_p = fl6_update_dst(&fl, opt, &final);
+	final_p = fl6_update_dst(&fl6, opt, &final);
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+	err = 0;
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
 		goto out;
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
-	if (err < 0) {
-		if (err == -EREMOTE)
-			err = ip6_dst_blackhole(sk, &dst, &fl);
-		if (err < 0)
-			goto out;
 	}
 
 	/* source address lookup done in ip6_dst_lookup */
 
 	if (ipv6_addr_any(&np->saddr))
-		ipv6_addr_copy(&np->saddr, &fl.fl6_src);
+		ipv6_addr_copy(&np->saddr, &fl6.saddr);
 
 	if (ipv6_addr_any(&np->rcv_saddr)) {
-		ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
+		ipv6_addr_copy(&np->rcv_saddr, &fl6.saddr);
 		inet->inet_rcv_saddr = LOOPBACK4_IPV6;
 		if (sk->sk_prot->rehash)
 			sk->sk_prot->rehash(sk);
 	}
 
 	ip6_dst_store(sk, dst,
-		      ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
+		      ipv6_addr_equal(&fl6.daddr, &np->daddr) ?
 		      &np->daddr : NULL,
 #ifdef CONFIG_IPV6_SUBTREES
-		      ipv6_addr_equal(&fl.fl6_src, &np->saddr) ?
+		      ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
 		      &np->saddr :
 #endif
 		      NULL);
@@ -238,7 +231,7 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
 		kfree_skb(skb);
 }
 
-void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
+void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sock_exterr_skb *serr;
@@ -257,7 +250,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
 	skb_put(skb, sizeof(struct ipv6hdr));
 	skb_reset_network_header(skb);
 	iph = ipv6_hdr(skb);
-	ipv6_addr_copy(&iph->daddr, &fl->fl6_dst);
+	ipv6_addr_copy(&iph->daddr, &fl6->daddr);
 
 	serr = SKB_EXT_ERR(skb);
 	serr->ee.ee_errno = err;
@@ -268,7 +261,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
 	serr->ee.ee_info = info;
 	serr->ee.ee_data = 0;
 	serr->addr_offset = (u8 *)&iph->daddr - skb_network_header(skb);
-	serr->port = fl->fl_ip_dport;
+	serr->port = fl6->fl6_dport;
 
 	__skb_pull(skb, skb_tail_pointer(skb) - skb->data);
 	skb_reset_transport_header(skb);
@@ -277,7 +270,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
 		kfree_skb(skb);
 }
 
-void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu)
+void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct ipv6hdr *iph;
@@ -294,7 +287,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu)
 	skb_put(skb, sizeof(struct ipv6hdr));
 	skb_reset_network_header(skb);
 	iph = ipv6_hdr(skb);
-	ipv6_addr_copy(&iph->daddr, &fl->fl6_dst);
+	ipv6_addr_copy(&iph->daddr, &fl6->daddr);
 
 	mtu_info = IP6CBMTU(skb);
 	if (!mtu_info) {
@@ -306,7 +299,7 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi *fl, u32 mtu)
 	mtu_info->ip6m_addr.sin6_family = AF_INET6;
 	mtu_info->ip6m_addr.sin6_port = 0;
 	mtu_info->ip6m_addr.sin6_flowinfo = 0;
-	mtu_info->ip6m_addr.sin6_scope_id = fl->oif;
+	mtu_info->ip6m_addr.sin6_scope_id = fl6->flowi6_oif;
 	ipv6_addr_copy(&mtu_info->ip6m_addr.sin6_addr, &ipv6_hdr(skb)->daddr);
 
 	__skb_pull(skb, skb_tail_pointer(skb) - skb->data);
@@ -600,7 +593,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
 }
 
 int datagram_send_ctl(struct net *net,
-		      struct msghdr *msg, struct flowi *fl,
+		      struct msghdr *msg, struct flowi6 *fl6,
 		      struct ipv6_txoptions *opt,
 		      int *hlimit, int *tclass, int *dontfrag)
 {
@@ -636,16 +629,17 @@ int datagram_send_ctl(struct net *net,
 			src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
 
 			if (src_info->ipi6_ifindex) {
-				if (fl->oif && src_info->ipi6_ifindex != fl->oif)
+				if (fl6->flowi6_oif &&
+				    src_info->ipi6_ifindex != fl6->flowi6_oif)
 					return -EINVAL;
-				fl->oif = src_info->ipi6_ifindex;
+				fl6->flowi6_oif = src_info->ipi6_ifindex;
 			}
 
 			addr_type = __ipv6_addr_type(&src_info->ipi6_addr);
 
 			rcu_read_lock();
-			if (fl->oif) {
-				dev = dev_get_by_index_rcu(net, fl->oif);
+			if (fl6->flowi6_oif) {
+				dev = dev_get_by_index_rcu(net, fl6->flowi6_oif);
 				if (!dev) {
 					rcu_read_unlock();
 					return -ENODEV;
@@ -661,7 +655,7 @@ int datagram_send_ctl(struct net *net,
 						   strict ? dev : NULL, 0))
 					err = -EINVAL;
 				else
-					ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr);
+					ipv6_addr_copy(&fl6->saddr, &src_info->ipi6_addr);
 			}
 
 			rcu_read_unlock();
@@ -678,13 +672,13 @@ int datagram_send_ctl(struct net *net,
 				goto exit_f;
 			}
 
-			if (fl->fl6_flowlabel&IPV6_FLOWINFO_MASK) {
-				if ((fl->fl6_flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) {
+			if (fl6->flowlabel&IPV6_FLOWINFO_MASK) {
+				if ((fl6->flowlabel^*(__be32 *)CMSG_DATA(cmsg))&~IPV6_FLOWINFO_MASK) {
 					err = -EINVAL;
 					goto exit_f;
 				}
 			}
-			fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg);
+			fl6->flowlabel = IPV6_FLOWINFO_MASK & *(__be32 *)CMSG_DATA(cmsg);
 			break;
 
 		case IPV6_2292HOPOPTS:
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 1b5c982..5aa8ec8 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -54,16 +54,20 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);
 /*
  * Allocate an AEAD request structure with extra space for SG and IV.
  *
- * For alignment considerations the IV is placed at the front, followed
- * by the request and finally the SG list.
+ * For alignment considerations the upper 32 bits of the sequence number are
+ * placed at the front, if present. Followed by the IV, the request and finally
+ * the SG list.
  *
  * TODO: Use spare space in skb for this where possible.
  */
-static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqihlen)
 {
 	unsigned int len;
 
-	len = crypto_aead_ivsize(aead);
+	len = seqihlen;
+
+	len += crypto_aead_ivsize(aead);
+
 	if (len) {
 		len += crypto_aead_alignmask(aead) &
 		       ~(crypto_tfm_ctx_alignment() - 1);
@@ -78,10 +82,16 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
 	return kmalloc(len, GFP_ATOMIC);
 }
 
-static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
+static inline __be32 *esp_tmp_seqhi(void *tmp)
+{
+	return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
+}
+
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
 {
 	return crypto_aead_ivsize(aead) ?
-	       PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
+	       PTR_ALIGN((u8 *)tmp + seqhilen,
+			 crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
 }
 
 static inline struct aead_givcrypt_request *esp_tmp_givreq(
@@ -145,8 +155,12 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 	int plen;
 	int tfclen;
 	int nfrags;
+	int assoclen;
+	int sglists;
+	int seqhilen;
 	u8 *iv;
 	u8 *tail;
+	__be32 *seqhi;
 	struct esp_data *esp = x->data;
 
 	/* skb is pure payload to encrypt */
@@ -175,14 +189,25 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 		goto error;
 	nfrags = err;
 
-	tmp = esp_alloc_tmp(aead, nfrags + 1);
+	assoclen = sizeof(*esph);
+	sglists = 1;
+	seqhilen = 0;
+
+	if (x->props.flags & XFRM_STATE_ESN) {
+		sglists += 2;
+		seqhilen += sizeof(__be32);
+		assoclen += seqhilen;
+	}
+
+	tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
 	if (!tmp)
 		goto error;
 
-	iv = esp_tmp_iv(aead, tmp);
+	seqhi = esp_tmp_seqhi(tmp);
+	iv = esp_tmp_iv(aead, tmp, seqhilen);
 	req = esp_tmp_givreq(aead, iv);
 	asg = esp_givreq_sg(aead, req);
-	sg = asg + 1;
+	sg = asg + sglists;
 
 	/* Fill padding... */
 	tail = skb_tail_pointer(trailer);
@@ -204,19 +229,27 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 	*skb_mac_header(skb) = IPPROTO_ESP;
 
 	esph->spi = x->id.spi;
-	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
+	esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low);
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg,
 		     esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
 		     clen + alen);
-	sg_init_one(asg, esph, sizeof(*esph));
+
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		sg_init_table(asg, 3);
+		sg_set_buf(asg, &esph->spi, sizeof(__be32));
+		*seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
+		sg_set_buf(asg + 1, seqhi, seqhilen);
+		sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32));
+	} else
+		sg_init_one(asg, esph, sizeof(*esph));
 
 	aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
 	aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
-	aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
+	aead_givcrypt_set_assoc(req, asg, assoclen);
 	aead_givcrypt_set_giv(req, esph->enc_data,
-			      XFRM_SKB_CB(skb)->seq.output);
+			      XFRM_SKB_CB(skb)->seq.output.low);
 
 	ESP_SKB_CB(skb)->tmp = tmp;
 	err = crypto_aead_givencrypt(req);
@@ -292,8 +325,12 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 	struct sk_buff *trailer;
 	int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
 	int nfrags;
+	int assoclen;
+	int sglists;
+	int seqhilen;
 	int ret = 0;
 	void *tmp;
+	__be32 *seqhi;
 	u8 *iv;
 	struct scatterlist *sg;
 	struct scatterlist *asg;
@@ -314,12 +351,24 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 	}
 
 	ret = -ENOMEM;
-	tmp = esp_alloc_tmp(aead, nfrags + 1);
+
+	assoclen = sizeof(*esph);
+	sglists = 1;
+	seqhilen = 0;
+
+	if (x->props.flags & XFRM_STATE_ESN) {
+		sglists += 2;
+		seqhilen += sizeof(__be32);
+		assoclen += seqhilen;
+	}
+
+	tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
 	if (!tmp)
 		goto out;
 
 	ESP_SKB_CB(skb)->tmp = tmp;
-	iv = esp_tmp_iv(aead, tmp);
+	seqhi = esp_tmp_seqhi(tmp);
+	iv = esp_tmp_iv(aead, tmp, seqhilen);
 	req = esp_tmp_req(aead, iv);
 	asg = esp_req_sg(aead, req);
 	sg = asg + 1;
@@ -333,11 +382,19 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 
 	sg_init_table(sg, nfrags);
 	skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
-	sg_init_one(asg, esph, sizeof(*esph));
+
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		sg_init_table(asg, 3);
+		sg_set_buf(asg, &esph->spi, sizeof(__be32));
+		*seqhi = XFRM_SKB_CB(skb)->seq.input.hi;
+		sg_set_buf(asg + 1, seqhi, seqhilen);
+		sg_set_buf(asg + 2, &esph->seq_no, sizeof(__be32));
+	} else
+		sg_init_one(asg, esph, sizeof(*esph));
 
 	aead_request_set_callback(req, 0, esp_input_done, skb);
 	aead_request_set_crypt(req, sg, sg, elen, iv);
-	aead_request_set_assoc(req, asg, sizeof(*esph));
+	aead_request_set_assoc(req, asg, assoclen);
 
 	ret = crypto_aead_decrypt(req);
 	if (ret == -EINPROGRESS)
@@ -443,10 +500,20 @@ static int esp_init_authenc(struct xfrm_state *x)
 		goto error;
 
 	err = -ENAMETOOLONG;
-	if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
-		     x->aalg ? x->aalg->alg_name : "digest_null",
-		     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
-		goto error;
+
+	if ((x->props.flags & XFRM_STATE_ESN)) {
+		if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
+			     "authencesn(%s,%s)",
+			     x->aalg ? x->aalg->alg_name : "digest_null",
+			     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+			goto error;
+	} else {
+		if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
+			     "authenc(%s,%s)",
+			     x->aalg ? x->aalg->alg_name : "digest_null",
+			     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
+			goto error;
+	}
 
 	aead = crypto_alloc_aead(authenc_name, 0, 0);
 	err = PTR_ERR(aead);
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 262f105..79a485e 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -876,22 +876,22 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
  * fl6_update_dst - update flowi destination address with info given
  *                  by srcrt option, if any.
  *
- * @fl: flowi for which fl6_dst is to be updated
+ * @fl6: flowi6 for which daddr is to be updated
  * @opt: struct ipv6_txoptions in which to look for srcrt opt
- * @orig: copy of original fl6_dst address if modified
+ * @orig: copy of original daddr address if modified
  *
  * Returns NULL if no txoptions or no srcrt, otherwise returns orig
- * and initial value of fl->fl6_dst set in orig
+ * and initial value of fl6->daddr set in orig
  */
-struct in6_addr *fl6_update_dst(struct flowi *fl,
+struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
 				const struct ipv6_txoptions *opt,
 				struct in6_addr *orig)
 {
 	if (!opt || !opt->srcrt)
 		return NULL;
 
-	ipv6_addr_copy(orig, &fl->fl6_dst);
-	ipv6_addr_copy(&fl->fl6_dst, ((struct rt0_hdr *)opt->srcrt)->addr);
+	ipv6_addr_copy(orig, &fl6->daddr);
+	ipv6_addr_copy(&fl6->daddr, ((struct rt0_hdr *)opt->srcrt)->addr);
 	return orig;
 }
 
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index d829874..34d244d 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -29,7 +29,7 @@ struct fib6_rule
 	u8			tclass;
 };
 
-struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
+struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 				   int flags, pol_lookup_t lookup)
 {
 	struct fib_lookup_arg arg = {
@@ -37,7 +37,8 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
 		.flags = FIB_LOOKUP_NOREF,
 	};
 
-	fib_rules_lookup(net->ipv6.fib6_rules_ops, fl, flags, &arg);
+	fib_rules_lookup(net->ipv6.fib6_rules_ops,
+			 flowi6_to_flowi(fl6), flags, &arg);
 
 	if (arg.result)
 		return arg.result;
@@ -49,6 +50,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
 static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
 			    int flags, struct fib_lookup_arg *arg)
 {
+	struct flowi6 *flp6 = &flp->u.ip6;
 	struct rt6_info *rt = NULL;
 	struct fib6_table *table;
 	struct net *net = rule->fr_net;
@@ -71,7 +73,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
 
 	table = fib6_get_table(net, rule->table);
 	if (table)
-		rt = lookup(net, table, flp, flags);
+		rt = lookup(net, table, flp6, flags);
 
 	if (rt != net->ipv6.ip6_null_entry) {
 		struct fib6_rule *r = (struct fib6_rule *)rule;
@@ -86,14 +88,14 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
 
 			if (ipv6_dev_get_saddr(net,
 					       ip6_dst_idev(&rt->dst)->dev,
-					       &flp->fl6_dst,
+					       &flp6->daddr,
 					       rt6_flags2srcprefs(flags),
 					       &saddr))
 				goto again;
 			if (!ipv6_prefix_equal(&saddr, &r->src.addr,
 					       r->src.plen))
 				goto again;
-			ipv6_addr_copy(&flp->fl6_src, &saddr);
+			ipv6_addr_copy(&flp6->saddr, &saddr);
 		}
 		goto out;
 	}
@@ -113,9 +115,10 @@ out:
 static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 {
 	struct fib6_rule *r = (struct fib6_rule *) rule;
+	struct flowi6 *fl6 = &fl->u.ip6;
 
 	if (r->dst.plen &&
-	    !ipv6_prefix_equal(&fl->fl6_dst, &r->dst.addr, r->dst.plen))
+	    !ipv6_prefix_equal(&fl6->daddr, &r->dst.addr, r->dst.plen))
 		return 0;
 
 	/*
@@ -125,14 +128,14 @@ static int fib6_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
 	 */
 	if (r->src.plen) {
 		if (flags & RT6_LOOKUP_F_HAS_SADDR) {
-			if (!ipv6_prefix_equal(&fl->fl6_src, &r->src.addr,
+			if (!ipv6_prefix_equal(&fl6->saddr, &r->src.addr,
 					       r->src.plen))
 				return 0;
 		} else if (!(r->common.flags & FIB_RULE_FIND_SADDR))
 			return 0;
 	}
 
-	if (r->tclass && r->tclass != ((ntohl(fl->fl6_flowlabel) >> 20) & 0xff))
+	if (r->tclass && r->tclass != ((ntohl(fl6->flowlabel) >> 20) & 0xff))
 		return 0;
 
 	return 1;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 03e62f9..83cb4f9 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -157,32 +157,32 @@ static int is_ineligible(struct sk_buff *skb)
 /*
  * Check the ICMP output rate limit
  */
-static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type,
-				     struct flowi *fl)
+static inline bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
+				      struct flowi6 *fl6)
 {
 	struct dst_entry *dst;
 	struct net *net = sock_net(sk);
-	int res = 0;
+	bool res = false;
 
 	/* Informational messages are not limited. */
 	if (type & ICMPV6_INFOMSG_MASK)
-		return 1;
+		return true;
 
 	/* Do not limit pmtu discovery, it would break it. */
 	if (type == ICMPV6_PKT_TOOBIG)
-		return 1;
+		return true;
 
 	/*
 	 * Look up the output route.
 	 * XXX: perhaps the expire for routing entries cloned by
 	 * this lookup should be more aggressive (not longer than timeout).
 	 */
-	dst = ip6_route_output(net, sk, fl);
+	dst = ip6_route_output(net, sk, fl6);
 	if (dst->error) {
 		IP6_INC_STATS(net, ip6_dst_idev(dst),
 			      IPSTATS_MIB_OUTNOROUTES);
 	} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
-		res = 1;
+		res = true;
 	} else {
 		struct rt6_info *rt = (struct rt6_info *)dst;
 		int tmo = net->ipv6.sysctl.icmpv6_time;
@@ -191,7 +191,9 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, u8 type,
 		if (rt->rt6i_dst.plen < 128)
 			tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
 
-		res = xrlim_allow(dst, tmo);
+		if (!rt->rt6i_peer)
+			rt6_bind_peer(rt, 1);
+		res = inet_peer_xrlim_allow(rt->rt6i_peer, tmo);
 	}
 	dst_release(dst);
 	return res;
@@ -215,7 +217,7 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset)
 	return (*op & 0xC0) == 0x80;
 }
 
-static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct icmp6hdr *thdr, int len)
+static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len)
 {
 	struct sk_buff *skb;
 	struct icmp6hdr *icmp6h;
@@ -231,9 +233,9 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
 	if (skb_queue_len(&sk->sk_write_queue) == 1) {
 		skb->csum = csum_partial(icmp6h,
 					sizeof(struct icmp6hdr), skb->csum);
-		icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
-						      &fl->fl6_dst,
-						      len, fl->proto,
+		icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr,
+						      &fl6->daddr,
+						      len, fl6->flowi6_proto,
 						      skb->csum);
 	} else {
 		__wsum tmp_csum = 0;
@@ -244,9 +246,9 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
 
 		tmp_csum = csum_partial(icmp6h,
 					sizeof(struct icmp6hdr), tmp_csum);
-		icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
-						      &fl->fl6_dst,
-						      len, fl->proto,
+		icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr,
+						      &fl6->daddr,
+						      len, fl6->flowi6_proto,
 						      tmp_csum);
 	}
 	ip6_push_pending_frames(sk);
@@ -298,6 +300,68 @@ static void mip6_addr_swap(struct sk_buff *skb)
 static inline void mip6_addr_swap(struct sk_buff *skb) {}
 #endif
 
+static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb,
+					     struct sock *sk, struct flowi6 *fl6)
+{
+	struct dst_entry *dst, *dst2;
+	struct flowi6 fl2;
+	int err;
+
+	err = ip6_dst_lookup(sk, &dst, fl6);
+	if (err)
+		return ERR_PTR(err);
+
+	/*
+	 * We won't send icmp if the destination is known
+	 * anycast.
+	 */
+	if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) {
+		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n");
+		dst_release(dst);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* No need to clone since we're just using its address. */
+	dst2 = dst;
+
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), sk, 0);
+	if (!IS_ERR(dst)) {
+		if (dst != dst2)
+			return dst;
+	} else {
+		if (PTR_ERR(dst) == -EPERM)
+			dst = NULL;
+		else
+			return dst;
+	}
+
+	err = xfrm_decode_session_reverse(skb, flowi6_to_flowi(&fl2), AF_INET6);
+	if (err)
+		goto relookup_failed;
+
+	err = ip6_dst_lookup(sk, &dst2, &fl2);
+	if (err)
+		goto relookup_failed;
+
+	dst2 = xfrm_lookup(net, dst2, flowi6_to_flowi(&fl2), sk, XFRM_LOOKUP_ICMP);
+	if (!IS_ERR(dst2)) {
+		dst_release(dst);
+		dst = dst2;
+	} else {
+		err = PTR_ERR(dst2);
+		if (err == -EPERM) {
+			dst_release(dst);
+			return dst2;
+		} else
+			goto relookup_failed;
+	}
+
+relookup_failed:
+	if (dst)
+		return dst;
+	return ERR_PTR(err);
+}
+
 /*
  *	Send an ICMP message in response to a packet in error
  */
@@ -310,10 +374,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
 	struct ipv6_pinfo *np;
 	struct in6_addr *saddr = NULL;
 	struct dst_entry *dst;
-	struct dst_entry *dst2;
 	struct icmp6hdr tmp_hdr;
-	struct flowi fl;
-	struct flowi fl2;
+	struct flowi6 fl6;
 	struct icmpv6_msg msg;
 	int iif = 0;
 	int addr_type = 0;
@@ -380,22 +442,22 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
 
 	mip6_addr_swap(skb);
 
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = IPPROTO_ICMPV6;
-	ipv6_addr_copy(&fl.fl6_dst, &hdr->saddr);
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = IPPROTO_ICMPV6;
+	ipv6_addr_copy(&fl6.daddr, &hdr->saddr);
 	if (saddr)
-		ipv6_addr_copy(&fl.fl6_src, saddr);
-	fl.oif = iif;
-	fl.fl_icmp_type = type;
-	fl.fl_icmp_code = code;
-	security_skb_classify_flow(skb, &fl);
+		ipv6_addr_copy(&fl6.saddr, saddr);
+	fl6.flowi6_oif = iif;
+	fl6.fl6_icmp_type = type;
+	fl6.fl6_icmp_code = code;
+	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	sk = icmpv6_xmit_lock(net);
 	if (sk == NULL)
 		return;
 	np = inet6_sk(sk);
 
-	if (!icmpv6_xrlim_allow(sk, type, &fl))
+	if (!icmpv6_xrlim_allow(sk, type, &fl6))
 		goto out;
 
 	tmp_hdr.icmp6_type = type;
@@ -403,61 +465,14 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
 	tmp_hdr.icmp6_cksum = 0;
 	tmp_hdr.icmp6_pointer = htonl(info);
 
-	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
-		fl.oif = np->mcast_oif;
+	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
+		fl6.flowi6_oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = icmpv6_route_lookup(net, skb, sk, &fl6);
+	if (IS_ERR(dst))
 		goto out;
 
-	/*
-	 * We won't send icmp if the destination is known
-	 * anycast.
-	 */
-	if (((struct rt6_info *)dst)->rt6i_flags & RTF_ANYCAST) {
-		LIMIT_NETDEBUG(KERN_DEBUG "icmpv6_send: acast source\n");
-		goto out_dst_release;
-	}
-
-	/* No need to clone since we're just using its address. */
-	dst2 = dst;
-
-	err = xfrm_lookup(net, &dst, &fl, sk, 0);
-	switch (err) {
-	case 0:
-		if (dst != dst2)
-			goto route_done;
-		break;
-	case -EPERM:
-		dst = NULL;
-		break;
-	default:
-		goto out;
-	}
-
-	if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
-		goto relookup_failed;
-
-	if (ip6_dst_lookup(sk, &dst2, &fl2))
-		goto relookup_failed;
-
-	err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP);
-	switch (err) {
-	case 0:
-		dst_release(dst);
-		dst = dst2;
-		break;
-	case -EPERM:
-		goto out_dst_release;
-	default:
-relookup_failed:
-		if (!dst)
-			goto out;
-		break;
-	}
-
-route_done:
-	if (ipv6_addr_is_multicast(&fl.fl6_dst))
+	if (ipv6_addr_is_multicast(&fl6.daddr))
 		hlimit = np->mcast_hops;
 	else
 		hlimit = np->hop_limit;
@@ -480,14 +495,14 @@ route_done:
 	err = ip6_append_data(sk, icmpv6_getfrag, &msg,
 			      len + sizeof(struct icmp6hdr),
 			      sizeof(struct icmp6hdr), hlimit,
-			      np->tclass, NULL, &fl, (struct rt6_info*)dst,
+			      np->tclass, NULL, &fl6, (struct rt6_info*)dst,
 			      MSG_DONTWAIT, np->dontfrag);
 	if (err) {
 		ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS);
 		ip6_flush_pending_frames(sk);
 		goto out_put;
 	}
-	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));
+	err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr));
 
 out_put:
 	if (likely(idev != NULL))
@@ -509,7 +524,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 	struct in6_addr *saddr = NULL;
 	struct icmp6hdr *icmph = icmp6_hdr(skb);
 	struct icmp6hdr tmp_hdr;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct icmpv6_msg msg;
 	struct dst_entry *dst;
 	int err = 0;
@@ -523,30 +538,31 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 	memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
 	tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
 
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = IPPROTO_ICMPV6;
-	ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = IPPROTO_ICMPV6;
+	ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr);
 	if (saddr)
-		ipv6_addr_copy(&fl.fl6_src, saddr);
-	fl.oif = skb->dev->ifindex;
-	fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
-	security_skb_classify_flow(skb, &fl);
+		ipv6_addr_copy(&fl6.saddr, saddr);
+	fl6.flowi6_oif = skb->dev->ifindex;
+	fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
+	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	sk = icmpv6_xmit_lock(net);
 	if (sk == NULL)
 		return;
 	np = inet6_sk(sk);
 
-	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
-		fl.oif = np->mcast_oif;
+	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
+		fl6.flowi6_oif = np->mcast_oif;
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
+	err = ip6_dst_lookup(sk, &dst, &fl6);
 	if (err)
 		goto out;
-	if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0)
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0);
+	if (IS_ERR(dst))
 		goto out;
 
-	if (ipv6_addr_is_multicast(&fl.fl6_dst))
+	if (ipv6_addr_is_multicast(&fl6.daddr))
 		hlimit = np->mcast_hops;
 	else
 		hlimit = np->hop_limit;
@@ -560,7 +576,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 	msg.type = ICMPV6_ECHO_REPLY;
 
 	err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
-				sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
+				sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl6,
 				(struct rt6_info*)dst, MSG_DONTWAIT,
 				np->dontfrag);
 
@@ -569,7 +585,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 		ip6_flush_pending_frames(sk);
 		goto out_put;
 	}
-	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
+	err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr));
 
 out_put:
 	if (likely(idev != NULL))
@@ -768,20 +784,20 @@ drop_no_count:
 	return 0;
 }
 
-void icmpv6_flow_init(struct sock *sk, struct flowi *fl,
+void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6,
 		      u8 type,
 		      const struct in6_addr *saddr,
 		      const struct in6_addr *daddr,
 		      int oif)
 {
-	memset(fl, 0, sizeof(*fl));
-	ipv6_addr_copy(&fl->fl6_src, saddr);
-	ipv6_addr_copy(&fl->fl6_dst, daddr);
-	fl->proto	 	= IPPROTO_ICMPV6;
-	fl->fl_icmp_type	= type;
-	fl->fl_icmp_code	= 0;
-	fl->oif			= oif;
-	security_sk_classify_flow(sk, fl);
+	memset(fl6, 0, sizeof(*fl6));
+	ipv6_addr_copy(&fl6->saddr, saddr);
+	ipv6_addr_copy(&fl6->daddr, daddr);
+	fl6->flowi6_proto 	= IPPROTO_ICMPV6;
+	fl6->fl6_icmp_type	= type;
+	fl6->fl6_icmp_code	= 0;
+	fl6->flowi6_oif		= oif;
+	security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
 }
 
 /*
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index d144e62..1660546 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -61,26 +61,21 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk,
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct in6_addr *final_p, final;
 	struct dst_entry *dst;
-	struct flowi fl;
-
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = IPPROTO_TCP;
-	ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-	final_p = fl6_update_dst(&fl, np->opt, &final);
-	ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
-	fl.oif = sk->sk_bound_dev_if;
-	fl.mark = sk->sk_mark;
-	fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-	fl.fl_ip_sport = inet_rsk(req)->loc_port;
-	security_req_classify_flow(req, &fl);
-
-	if (ip6_dst_lookup(sk, &dst, &fl))
-		return NULL;
-
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
+	struct flowi6 fl6;
+
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = IPPROTO_TCP;
+	ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
+	final_p = fl6_update_dst(&fl6, np->opt, &final);
+	ipv6_addr_copy(&fl6.saddr, &treq->loc_addr);
+	fl6.flowi6_oif = sk->sk_bound_dev_if;
+	fl6.flowi6_mark = sk->sk_mark;
+	fl6.fl6_dport = inet_rsk(req)->rmt_port;
+	fl6.fl6_sport = inet_rsk(req)->loc_port;
+	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
+
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+	if (IS_ERR(dst))
 		return NULL;
 
 	return dst;
@@ -213,42 +208,34 @@ int inet6_csk_xmit(struct sk_buff *skb)
 	struct sock *sk = skb->sk;
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 	struct in6_addr *final_p, final;
 
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = sk->sk_protocol;
-	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-	ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-	fl.fl6_flowlabel = np->flow_label;
-	IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
-	fl.oif = sk->sk_bound_dev_if;
-	fl.mark = sk->sk_mark;
-	fl.fl_ip_sport = inet->inet_sport;
-	fl.fl_ip_dport = inet->inet_dport;
-	security_sk_classify_flow(sk, &fl);
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = sk->sk_protocol;
+	ipv6_addr_copy(&fl6.daddr, &np->daddr);
+	ipv6_addr_copy(&fl6.saddr, &np->saddr);
+	fl6.flowlabel = np->flow_label;
+	IP6_ECN_flow_xmit(sk, fl6.flowlabel);
+	fl6.flowi6_oif = sk->sk_bound_dev_if;
+	fl6.flowi6_mark = sk->sk_mark;
+	fl6.fl6_sport = inet->inet_sport;
+	fl6.fl6_dport = inet->inet_dport;
+	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	final_p = fl6_update_dst(&fl, np->opt, &final);
+	final_p = fl6_update_dst(&fl6, np->opt, &final);
 
 	dst = __inet6_csk_dst_check(sk, np->dst_cookie);
 
 	if (dst == NULL) {
-		int err = ip6_dst_lookup(sk, &dst, &fl);
-
-		if (err) {
-			sk->sk_err_soft = -err;
-			kfree_skb(skb);
-			return err;
-		}
-
-		if (final_p)
-			ipv6_addr_copy(&fl.fl6_dst, final_p);
+		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
 
-		if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0) {
+		if (IS_ERR(dst)) {
+			sk->sk_err_soft = -PTR_ERR(dst);
 			sk->sk_route_caps = 0;
 			kfree_skb(skb);
-			return err;
+			return PTR_ERR(dst);
 		}
 
 		__inet6_csk_dst_store(sk, dst, NULL, NULL);
@@ -257,9 +244,9 @@ int inet6_csk_xmit(struct sk_buff *skb)
 	skb_dst_set(skb, dst_clone(dst));
 
 	/* Restore final destination back after routing done */
-	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
+	ipv6_addr_copy(&fl6.daddr, &np->daddr);
 
-	return ip6_xmit(sk, skb, &fl, np->opt);
+	return ip6_xmit(sk, skb, &fl6, np->opt);
 }
 
 EXPORT_SYMBOL_GPL(inet6_csk_xmit);
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 633a6c2..b531972 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -124,7 +124,7 @@ out:
 }
 EXPORT_SYMBOL(__inet6_lookup_established);
 
-static int inline compute_score(struct sock *sk, struct net *net,
+static inline int compute_score(struct sock *sk, struct net *net,
 				const unsigned short hnum,
 				const struct in6_addr *daddr,
 				const int dif)
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index de38211..7548905 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -260,10 +260,10 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id)
 	  return net->ipv6.fib6_main_tbl;
 }
 
-struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi *fl,
+struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
 				   int flags, pol_lookup_t lookup)
 {
-	return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl, flags);
+	return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
 }
 
 static void __net_init fib6_tables_init(struct net *net)
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1365468..f3caf1b 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -342,7 +342,7 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
 
 	if (olen > 0) {
 		struct msghdr msg;
-		struct flowi flowi;
+		struct flowi6 flowi6;
 		int junk;
 
 		err = -ENOMEM;
@@ -358,9 +358,9 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval,
 
 		msg.msg_controllen = olen;
 		msg.msg_control = (void*)(fl->opt+1);
-		flowi.oif = 0;
+		memset(&flowi6, 0, sizeof(flowi6));
 
-		err = datagram_send_ctl(net, &msg, &flowi, fl->opt, &junk,
+		err = datagram_send_ctl(net, &msg, &flowi6, fl->opt, &junk,
 					&junk, &junk);
 		if (err)
 			goto done;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 5f8d242..1820887 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -174,15 +174,15 @@ int ip6_output(struct sk_buff *skb)
  *	xmit an sk_buff (used by TCP, SCTP and DCCP)
  */
 
-int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
+int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6,
 	     struct ipv6_txoptions *opt)
 {
 	struct net *net = sock_net(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
-	struct in6_addr *first_hop = &fl->fl6_dst;
+	struct in6_addr *first_hop = &fl6->daddr;
 	struct dst_entry *dst = skb_dst(skb);
 	struct ipv6hdr *hdr;
-	u8  proto = fl->proto;
+	u8  proto = fl6->flowi6_proto;
 	int seg_len = skb->len;
 	int hlimit = -1;
 	int tclass = 0;
@@ -230,13 +230,13 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
 	if (hlimit < 0)
 		hlimit = ip6_dst_hoplimit(dst);
 
-	*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel;
+	*(__be32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl6->flowlabel;
 
 	hdr->payload_len = htons(seg_len);
 	hdr->nexthdr = proto;
 	hdr->hop_limit = hlimit;
 
-	ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
+	ipv6_addr_copy(&hdr->saddr, &fl6->saddr);
 	ipv6_addr_copy(&hdr->daddr, first_hop);
 
 	skb->priority = sk->sk_priority;
@@ -274,13 +274,10 @@ int ip6_nd_hdr(struct sock *sk, struct sk_buff *skb, struct net_device *dev,
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct ipv6hdr *hdr;
-	int totlen;
 
 	skb->protocol = htons(ETH_P_IPV6);
 	skb->dev = dev;
 
-	totlen = len + sizeof(struct ipv6hdr);
-
 	skb_reset_network_header(skb);
 	skb_put(skb, sizeof(struct ipv6hdr));
 	hdr = ipv6_hdr(skb);
@@ -479,10 +476,13 @@ int ip6_forward(struct sk_buff *skb)
 		else
 			target = &hdr->daddr;
 
+		if (!rt->rt6i_peer)
+			rt6_bind_peer(rt, 1);
+
 		/* Limit redirects both by destination (here)
 		   and by source (inside ndisc_send_redirect)
 		 */
-		if (xrlim_allow(dst, 1*HZ))
+		if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
 			ndisc_send_redirect(skb, n, target);
 	} else {
 		int addrtype = ipv6_addr_type(&hdr->saddr);
@@ -879,7 +879,7 @@ static inline int ip6_rt_check(struct rt6key *rt_key,
 
 static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
 					  struct dst_entry *dst,
-					  struct flowi *fl)
+					  struct flowi6 *fl6)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct rt6_info *rt = (struct rt6_info *)dst;
@@ -904,11 +904,11 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk,
 	 *    sockets.
 	 * 2. oif also should be the same.
 	 */
-	if (ip6_rt_check(&rt->rt6i_dst, &fl->fl6_dst, np->daddr_cache) ||
+	if (ip6_rt_check(&rt->rt6i_dst, &fl6->daddr, np->daddr_cache) ||
 #ifdef CONFIG_IPV6_SUBTREES
-	    ip6_rt_check(&rt->rt6i_src, &fl->fl6_src, np->saddr_cache) ||
+	    ip6_rt_check(&rt->rt6i_src, &fl6->saddr, np->saddr_cache) ||
 #endif
-	    (fl->oif && fl->oif != dst->dev->ifindex)) {
+	    (fl6->flowi6_oif && fl6->flowi6_oif != dst->dev->ifindex)) {
 		dst_release(dst);
 		dst = NULL;
 	}
@@ -918,22 +918,22 @@ out:
 }
 
 static int ip6_dst_lookup_tail(struct sock *sk,
-			       struct dst_entry **dst, struct flowi *fl)
+			       struct dst_entry **dst, struct flowi6 *fl6)
 {
 	int err;
 	struct net *net = sock_net(sk);
 
 	if (*dst == NULL)
-		*dst = ip6_route_output(net, sk, fl);
+		*dst = ip6_route_output(net, sk, fl6);
 
 	if ((err = (*dst)->error))
 		goto out_err_release;
 
-	if (ipv6_addr_any(&fl->fl6_src)) {
+	if (ipv6_addr_any(&fl6->saddr)) {
 		err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev,
-					 &fl->fl6_dst,
+					 &fl6->daddr,
 					 sk ? inet6_sk(sk)->srcprefs : 0,
-					 &fl->fl6_src);
+					 &fl6->saddr);
 		if (err)
 			goto out_err_release;
 	}
@@ -949,10 +949,10 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 	 */
 	if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
 		struct inet6_ifaddr *ifp;
-		struct flowi fl_gw;
+		struct flowi6 fl_gw6;
 		int redirect;
 
-		ifp = ipv6_get_ifaddr(net, &fl->fl6_src,
+		ifp = ipv6_get_ifaddr(net, &fl6->saddr,
 				      (*dst)->dev, 1);
 
 		redirect = (ifp && ifp->flags & IFA_F_OPTIMISTIC);
@@ -965,9 +965,9 @@ static int ip6_dst_lookup_tail(struct sock *sk,
 			 * default router instead
 			 */
 			dst_release(*dst);
-			memcpy(&fl_gw, fl, sizeof(struct flowi));
-			memset(&fl_gw.fl6_dst, 0, sizeof(struct in6_addr));
-			*dst = ip6_route_output(net, sk, &fl_gw);
+			memcpy(&fl_gw6, fl6, sizeof(struct flowi6));
+			memset(&fl_gw6.daddr, 0, sizeof(struct in6_addr));
+			*dst = ip6_route_output(net, sk, &fl_gw6);
 			if ((err = (*dst)->error))
 				goto out_err_release;
 		}
@@ -988,43 +988,85 @@ out_err_release:
  *	ip6_dst_lookup - perform route lookup on flow
  *	@sk: socket which provides route info
  *	@dst: pointer to dst_entry * for result
- *	@fl: flow to lookup
+ *	@fl6: flow to lookup
  *
  *	This function performs a route lookup on the given flow.
  *
  *	It returns zero on success, or a standard errno code on error.
  */
-int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl6)
 {
 	*dst = NULL;
-	return ip6_dst_lookup_tail(sk, dst, fl);
+	return ip6_dst_lookup_tail(sk, dst, fl6);
 }
 EXPORT_SYMBOL_GPL(ip6_dst_lookup);
 
 /**
- *	ip6_sk_dst_lookup - perform socket cached route lookup on flow
+ *	ip6_dst_lookup_flow - perform route lookup on flow with ipsec
+ *	@sk: socket which provides route info
+ *	@fl6: flow to lookup
+ *	@final_dst: final destination address for ipsec lookup
+ *	@can_sleep: we are in a sleepable context
+ *
+ *	This function performs a route lookup on the given flow.
+ *
+ *	It returns a valid dst pointer on success, or a pointer encoded
+ *	error code.
+ */
+struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
+				      const struct in6_addr *final_dst,
+				      bool can_sleep)
+{
+	struct dst_entry *dst = NULL;
+	int err;
+
+	err = ip6_dst_lookup_tail(sk, &dst, fl6);
+	if (err)
+		return ERR_PTR(err);
+	if (final_dst)
+		ipv6_addr_copy(&fl6->daddr, final_dst);
+	if (can_sleep)
+		fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP;
+
+	return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+}
+EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
+
+/**
+ *	ip6_sk_dst_lookup_flow - perform socket cached route lookup on flow
  *	@sk: socket which provides the dst cache and route info
- *	@dst: pointer to dst_entry * for result
- *	@fl: flow to lookup
+ *	@fl6: flow to lookup
+ *	@final_dst: final destination address for ipsec lookup
+ *	@can_sleep: we are in a sleepable context
  *
  *	This function performs a route lookup on the given flow with the
  *	possibility of using the cached route in the socket if it is valid.
  *	It will take the socket dst lock when operating on the dst cache.
  *	As a result, this function can only be used in process context.
  *
- *	It returns zero on success, or a standard errno code on error.
+ *	It returns a valid dst pointer on success, or a pointer encoded
+ *	error code.
  */
-int ip6_sk_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
+					 const struct in6_addr *final_dst,
+					 bool can_sleep)
 {
-	*dst = NULL;
-	if (sk) {
-		*dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
-		*dst = ip6_sk_dst_check(sk, *dst, fl);
-	}
+	struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
+	int err;
+
+	dst = ip6_sk_dst_check(sk, dst, fl6);
+
+	err = ip6_dst_lookup_tail(sk, &dst, fl6);
+	if (err)
+		return ERR_PTR(err);
+	if (final_dst)
+		ipv6_addr_copy(&fl6->daddr, final_dst);
+	if (can_sleep)
+		fl6->flowi6_flags |= FLOWI_FLAG_CAN_SLEEP;
 
-	return ip6_dst_lookup_tail(sk, dst, fl);
+	return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
 }
-EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup);
+EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
 
 static inline int ip6_ufo_append_data(struct sock *sk,
 			int getfrag(void *from, char *to, int offset, int len,
@@ -1061,7 +1103,6 @@ static inline int ip6_ufo_append_data(struct sock *sk,
 
 		skb->ip_summed = CHECKSUM_PARTIAL;
 		skb->csum = 0;
-		sk->sk_sndmsg_off = 0;
 	}
 
 	err = skb_append_datato_frags(sk,skb, getfrag, from,
@@ -1104,7 +1145,7 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
 int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	int offset, int len, int odd, struct sk_buff *skb),
 	void *from, int length, int transhdrlen,
-	int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl,
+	int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi6 *fl6,
 	struct rt6_info *rt, unsigned int flags, int dontfrag)
 {
 	struct inet_sock *inet = inet_sk(sk);
@@ -1118,6 +1159,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	int err;
 	int offset = 0;
 	int csummode = CHECKSUM_NONE;
+	__u8 tx_flags = 0;
 
 	if (flags&MSG_PROBE)
 		return 0;
@@ -1161,7 +1203,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 		}
 		dst_hold(&rt->dst);
 		inet->cork.dst = &rt->dst;
-		inet->cork.fl = *fl;
+		inet->cork.fl.u.ip6 = *fl6;
 		np->cork.hop_limit = hlimit;
 		np->cork.tclass = tclass;
 		mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
@@ -1182,7 +1224,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 		transhdrlen += exthdrlen;
 	} else {
 		rt = (struct rt6_info *)inet->cork.dst;
-		fl = &inet->cork.fl;
+		fl6 = &inet->cork.fl.u.ip6;
 		opt = np->cork.opt;
 		transhdrlen = 0;
 		exthdrlen = 0;
@@ -1197,11 +1239,18 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 
 	if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
 		if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
-			ipv6_local_error(sk, EMSGSIZE, fl, mtu-exthdrlen);
+			ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
 			return -EMSGSIZE;
 		}
 	}
 
+	/* For UDP, check if TX timestamp is enabled */
+	if (sk->sk_type == SOCK_DGRAM) {
+		err = sock_tx_timestamp(sk, &tx_flags);
+		if (err)
+			goto error;
+	}
+
 	/*
 	 * Let's try using as much space as possible.
 	 * Use MTU if total length of the message fits into the MTU.
@@ -1222,7 +1271,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
 	if (length > mtu) {
 		int proto = sk->sk_protocol;
 		if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
-			ipv6_local_rxpmtu(sk, fl, mtu-exthdrlen);
+			ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen);
 			return -EMSGSIZE;
 		}
 
@@ -1306,6 +1355,12 @@ alloc_new_skb:
 							   sk->sk_allocation);
 				if (unlikely(skb == NULL))
 					err = -ENOBUFS;
+				else {
+					/* Only the initial fragment
+					 * is time stamped.
+					 */
+					tx_flags = 0;
+				}
 			}
 			if (skb == NULL)
 				goto error;
@@ -1317,6 +1372,9 @@ alloc_new_skb:
 			/* reserve for fragmentation */
 			skb_reserve(skb, hh_len+sizeof(struct frag_hdr));
 
+			if (sk->sk_type == SOCK_DGRAM)
+				skb_shinfo(skb)->tx_flags = tx_flags;
+
 			/*
 			 *	Find where to start putting bytes
 			 */
@@ -1458,8 +1516,8 @@ int ip6_push_pending_frames(struct sock *sk)
 	struct ipv6hdr *hdr;
 	struct ipv6_txoptions *opt = np->cork.opt;
 	struct rt6_info *rt = (struct rt6_info *)inet->cork.dst;
-	struct flowi *fl = &inet->cork.fl;
-	unsigned char proto = fl->proto;
+	struct flowi6 *fl6 = &inet->cork.fl.u.ip6;
+	unsigned char proto = fl6->flowi6_proto;
 	int err = 0;
 
 	if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL)
@@ -1484,7 +1542,7 @@ int ip6_push_pending_frames(struct sock *sk)
 	if (np->pmtudisc < IPV6_PMTUDISC_DO)
 		skb->local_df = 1;
 
-	ipv6_addr_copy(final_dst, &fl->fl6_dst);
+	ipv6_addr_copy(final_dst, &fl6->daddr);
 	__skb_pull(skb, skb_network_header_len(skb));
 	if (opt && opt->opt_flen)
 		ipv6_push_frag_opts(skb, opt, &proto);
@@ -1495,12 +1553,12 @@ int ip6_push_pending_frames(struct sock *sk)
 	skb_reset_network_header(skb);
 	hdr = ipv6_hdr(skb);
 
-	*(__be32*)hdr = fl->fl6_flowlabel |
+	*(__be32*)hdr = fl6->flowlabel |
 		     htonl(0x60000000 | ((int)np->cork.tclass << 20));
 
 	hdr->hop_limit = np->cork.hop_limit;
 	hdr->nexthdr = proto;
-	ipv6_addr_copy(&hdr->saddr, &fl->fl6_src);
+	ipv6_addr_copy(&hdr->saddr, &fl6->saddr);
 	ipv6_addr_copy(&hdr->daddr, final_dst);
 
 	skb->priority = sk->sk_priority;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index e528a42..c1b1bd3 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -536,7 +536,6 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	int err;
 	struct sk_buff *skb2;
 	struct iphdr *eiph;
-	struct flowi fl;
 	struct rtable *rt;
 
 	err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code,
@@ -578,11 +577,11 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	eiph = ip_hdr(skb2);
 
 	/* Try to guess incoming interface */
-	memset(&fl, 0, sizeof(fl));
-	fl.fl4_dst = eiph->saddr;
-	fl.fl4_tos = RT_TOS(eiph->tos);
-	fl.proto = IPPROTO_IPIP;
-	if (ip_route_output_key(dev_net(skb->dev), &rt, &fl))
+	rt = ip_route_output_ports(dev_net(skb->dev), NULL,
+				   eiph->saddr, 0,
+				   0, 0,
+				   IPPROTO_IPIP, RT_TOS(eiph->tos), 0);
+	if (IS_ERR(rt))
 		goto out;
 
 	skb2->dev = rt->dst.dev;
@@ -591,15 +590,18 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	if (rt->rt_flags & RTCF_LOCAL) {
 		ip_rt_put(rt);
 		rt = NULL;
-		fl.fl4_dst = eiph->daddr;
-		fl.fl4_src = eiph->saddr;
-		fl.fl4_tos = eiph->tos;
-		if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) ||
+		rt = ip_route_output_ports(dev_net(skb->dev), NULL,
+					   eiph->daddr, eiph->saddr,
+					   0, 0,
+					   IPPROTO_IPIP,
+					   RT_TOS(eiph->tos), 0);
+		if (IS_ERR(rt) ||
 		    rt->dst.dev->type != ARPHRD_TUNNEL) {
-			ip_rt_put(rt);
+			if (!IS_ERR(rt))
+				ip_rt_put(rt);
 			goto out;
 		}
-		skb_dst_set(skb2, (struct dst_entry *)rt);
+		skb_dst_set(skb2, &rt->dst);
 	} else {
 		ip_rt_put(rt);
 		if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos,
@@ -882,7 +884,7 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t)
 static int ip6_tnl_xmit2(struct sk_buff *skb,
 			 struct net_device *dev,
 			 __u8 dsfield,
-			 struct flowi *fl,
+			 struct flowi6 *fl6,
 			 int encap_limit,
 			 __u32 *pmtu)
 {
@@ -902,10 +904,16 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 	if ((dst = ip6_tnl_dst_check(t)) != NULL)
 		dst_hold(dst);
 	else {
-		dst = ip6_route_output(net, NULL, fl);
+		dst = ip6_route_output(net, NULL, fl6);
 
-		if (dst->error || xfrm_lookup(net, &dst, fl, NULL, 0) < 0)
+		if (dst->error)
 			goto tx_err_link_failure;
+		dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0);
+		if (IS_ERR(dst)) {
+			err = PTR_ERR(dst);
+			dst = NULL;
+			goto tx_err_link_failure;
+		}
 	}
 
 	tdev = dst->dev;
@@ -955,7 +963,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 
 	skb->transport_header = skb->network_header;
 
-	proto = fl->proto;
+	proto = fl6->flowi6_proto;
 	if (encap_limit >= 0) {
 		init_tel_txopt(&opt, encap_limit);
 		ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL);
@@ -963,13 +971,13 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
 	skb_push(skb, sizeof(struct ipv6hdr));
 	skb_reset_network_header(skb);
 	ipv6h = ipv6_hdr(skb);
-	*(__be32*)ipv6h = fl->fl6_flowlabel | htonl(0x60000000);
+	*(__be32*)ipv6h = fl6->flowlabel | htonl(0x60000000);
 	dsfield = INET_ECN_encapsulate(0, dsfield);
 	ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield);
 	ipv6h->hop_limit = t->parms.hop_limit;
 	ipv6h->nexthdr = proto;
-	ipv6_addr_copy(&ipv6h->saddr, &fl->fl6_src);
-	ipv6_addr_copy(&ipv6h->daddr, &fl->fl6_dst);
+	ipv6_addr_copy(&ipv6h->saddr, &fl6->saddr);
+	ipv6_addr_copy(&ipv6h->daddr, &fl6->daddr);
 	nf_reset(skb);
 	pkt_len = skb->len;
 	err = ip6_local_out(skb);
@@ -999,7 +1007,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct ip6_tnl *t = netdev_priv(dev);
 	struct iphdr  *iph = ip_hdr(skb);
 	int encap_limit = -1;
-	struct flowi fl;
+	struct flowi6 fl6;
 	__u8 dsfield;
 	__u32 mtu;
 	int err;
@@ -1011,16 +1019,16 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
 		encap_limit = t->parms.encap_limit;
 
-	memcpy(&fl, &t->fl, sizeof (fl));
-	fl.proto = IPPROTO_IPIP;
+	memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
+	fl6.flowi6_proto = IPPROTO_IPIP;
 
 	dsfield = ipv4_get_dsfield(iph);
 
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
-		fl.fl6_flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
+		fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
 					  & IPV6_TCLASS_MASK;
 
-	err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu);
+	err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		/* XXX: send ICMP error even if DF is not set. */
 		if (err == -EMSGSIZE)
@@ -1039,7 +1047,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 	int encap_limit = -1;
 	__u16 offset;
-	struct flowi fl;
+	struct flowi6 fl6;
 	__u8 dsfield;
 	__u32 mtu;
 	int err;
@@ -1061,16 +1069,16 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
 	} else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
 		encap_limit = t->parms.encap_limit;
 
-	memcpy(&fl, &t->fl, sizeof (fl));
-	fl.proto = IPPROTO_IPV6;
+	memcpy(&fl6, &t->fl.u.ip6, sizeof (fl6));
+	fl6.flowi6_proto = IPPROTO_IPV6;
 
 	dsfield = ipv6_get_dsfield(ipv6h);
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS))
-		fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
+		fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
 	if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL))
-		fl.fl6_flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
+		fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK);
 
-	err = ip6_tnl_xmit2(skb, dev, dsfield, &fl, encap_limit, &mtu);
+	err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu);
 	if (err != 0) {
 		if (err == -EMSGSIZE)
 			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
@@ -1133,21 +1141,21 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
 {
 	struct net_device *dev = t->dev;
 	struct ip6_tnl_parm *p = &t->parms;
-	struct flowi *fl = &t->fl;
+	struct flowi6 *fl6 = &t->fl.u.ip6;
 
 	memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr));
 	memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr));
 
 	/* Set up flowi template */
-	ipv6_addr_copy(&fl->fl6_src, &p->laddr);
-	ipv6_addr_copy(&fl->fl6_dst, &p->raddr);
-	fl->oif = p->link;
-	fl->fl6_flowlabel = 0;
+	ipv6_addr_copy(&fl6->saddr, &p->laddr);
+	ipv6_addr_copy(&fl6->daddr, &p->raddr);
+	fl6->flowi6_oif = p->link;
+	fl6->flowlabel = 0;
 
 	if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS))
-		fl->fl6_flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
+		fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo;
 	if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL))
-		fl->fl6_flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo;
+		fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo;
 
 	ip6_tnl_set_cap(t);
 
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 0e1d53b..7ff0343 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -135,14 +135,15 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
 	return NULL;
 }
 
-static int ip6mr_fib_lookup(struct net *net, struct flowi *flp,
+static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
 			    struct mr6_table **mrt)
 {
 	struct ip6mr_result res;
 	struct fib_lookup_arg arg = { .result = &res, };
 	int err;
 
-	err = fib_rules_lookup(net->ipv6.mr6_rules_ops, flp, 0, &arg);
+	err = fib_rules_lookup(net->ipv6.mr6_rules_ops,
+			       flowi6_to_flowi(flp6), 0, &arg);
 	if (err < 0)
 		return err;
 	*mrt = res.mrt;
@@ -270,7 +271,7 @@ static struct mr6_table *ip6mr_get_table(struct net *net, u32 id)
 	return net->ipv6.mrt6;
 }
 
-static int ip6mr_fib_lookup(struct net *net, struct flowi *flp,
+static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
 			    struct mr6_table **mrt)
 {
 	*mrt = net->ipv6.mrt6;
@@ -617,9 +618,9 @@ static int pim6_rcv(struct sk_buff *skb)
 	struct net_device  *reg_dev = NULL;
 	struct net *net = dev_net(skb->dev);
 	struct mr6_table *mrt;
-	struct flowi fl = {
-		.iif	= skb->dev->ifindex,
-		.mark	= skb->mark,
+	struct flowi6 fl6 = {
+		.flowi6_iif	= skb->dev->ifindex,
+		.flowi6_mark	= skb->mark,
 	};
 	int reg_vif_num;
 
@@ -644,7 +645,7 @@ static int pim6_rcv(struct sk_buff *skb)
 	    ntohs(encap->payload_len) + sizeof(*pim) > skb->len)
 		goto drop;
 
-	if (ip6mr_fib_lookup(net, &fl, &mrt) < 0)
+	if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
 		goto drop;
 	reg_vif_num = mrt->mroute_reg_vif_num;
 
@@ -687,14 +688,14 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
 {
 	struct net *net = dev_net(dev);
 	struct mr6_table *mrt;
-	struct flowi fl = {
-		.oif		= dev->ifindex,
-		.iif		= skb->skb_iif,
-		.mark		= skb->mark,
+	struct flowi6 fl6 = {
+		.flowi6_oif	= dev->ifindex,
+		.flowi6_iif	= skb->skb_iif,
+		.flowi6_mark	= skb->mark,
 	};
 	int err;
 
-	err = ip6mr_fib_lookup(net, &fl, &mrt);
+	err = ip6mr_fib_lookup(net, &fl6, &mrt);
 	if (err < 0)
 		return err;
 
@@ -1039,7 +1040,6 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt,
 
 	while((skb = __skb_dequeue(&uc->mfc_un.unres.unresolved))) {
 		if (ipv6_hdr(skb)->version == 0) {
-			int err;
 			struct nlmsghdr *nlh = (struct nlmsghdr *)skb_pull(skb, sizeof(struct ipv6hdr));
 
 			if (__ip6mr_fill_mroute(mrt, skb, c, NLMSG_DATA(nlh)) > 0) {
@@ -1050,7 +1050,7 @@ static void ip6mr_cache_resolve(struct net *net, struct mr6_table *mrt,
 				skb_trim(skb, nlh->nlmsg_len);
 				((struct nlmsgerr *)NLMSG_DATA(nlh))->error = -EMSGSIZE;
 			}
-			err = rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
+			rtnl_unicast(skb, net, NETLINK_CB(skb).pid);
 		} else
 			ip6_mr_forward(net, mrt, skb, c);
 	}
@@ -1548,13 +1548,13 @@ int ip6mr_sk_done(struct sock *sk)
 struct sock *mroute6_socket(struct net *net, struct sk_buff *skb)
 {
 	struct mr6_table *mrt;
-	struct flowi fl = {
-		.iif	= skb->skb_iif,
-		.oif	= skb->dev->ifindex,
-		.mark	= skb->mark,
+	struct flowi6 fl6 = {
+		.flowi6_iif	= skb->skb_iif,
+		.flowi6_oif	= skb->dev->ifindex,
+		.flowi6_mark	= skb->mark,
 	};
 
-	if (ip6mr_fib_lookup(net, &fl, &mrt) < 0)
+	if (ip6mr_fib_lookup(net, &fl6, &mrt) < 0)
 		return NULL;
 
 	return mrt->mroute6_sk;
@@ -1898,7 +1898,7 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt,
 	struct mif_device *vif = &mrt->vif6_table[vifi];
 	struct net_device *dev;
 	struct dst_entry *dst;
-	struct flowi fl;
+	struct flowi6 fl6;
 
 	if (vif->dev == NULL)
 		goto out_free;
@@ -1916,12 +1916,12 @@ static int ip6mr_forward2(struct net *net, struct mr6_table *mrt,
 
 	ipv6h = ipv6_hdr(skb);
 
-	fl = (struct flowi) {
-		.oif = vif->link,
-		.fl6_dst = ipv6h->daddr,
+	fl6 = (struct flowi6) {
+		.flowi6_oif = vif->link,
+		.daddr = ipv6h->daddr,
 	};
 
-	dst = ip6_route_output(net, NULL, &fl);
+	dst = ip6_route_output(net, NULL, &fl6);
 	if (!dst)
 		goto out_free;
 
@@ -2044,13 +2044,13 @@ int ip6_mr_input(struct sk_buff *skb)
 	struct mfc6_cache *cache;
 	struct net *net = dev_net(skb->dev);
 	struct mr6_table *mrt;
-	struct flowi fl = {
-		.iif	= skb->dev->ifindex,
-		.mark	= skb->mark,
+	struct flowi6 fl6 = {
+		.flowi6_iif	= skb->dev->ifindex,
+		.flowi6_mark	= skb->mark,
 	};
 	int err;
 
-	err = ip6mr_fib_lookup(net, &fl, &mrt);
+	err = ip6mr_fib_lookup(net, &fl6, &mrt);
 	if (err < 0)
 		return err;
 
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index d1770e0..9cb191e 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -444,12 +444,12 @@ sticky_done:
 	{
 		struct ipv6_txoptions *opt = NULL;
 		struct msghdr msg;
-		struct flowi fl;
+		struct flowi6 fl6;
 		int junk;
 
-		fl.fl6_flowlabel = 0;
-		fl.oif = sk->sk_bound_dev_if;
-		fl.mark = sk->sk_mark;
+		memset(&fl6, 0, sizeof(fl6));
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
+		fl6.flowi6_mark = sk->sk_mark;
 
 		if (optlen == 0)
 			goto update;
@@ -475,7 +475,7 @@ sticky_done:
 		msg.msg_controllen = optlen;
 		msg.msg_control = (void*)(opt+1);
 
-		retv = datagram_send_ctl(net, &msg, &fl, opt, &junk, &junk,
+		retv = datagram_send_ctl(net, &msg, &fl6, opt, &junk, &junk,
 					 &junk);
 		if (retv)
 			goto done;
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 49f986d..76b8937 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -319,7 +319,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
 {
 	struct in6_addr *source, *group;
 	struct ipv6_mc_socklist *pmc;
-	struct net_device *dev;
 	struct inet6_dev *idev;
 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
 	struct ip6_sf_socklist *psl;
@@ -341,7 +340,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
 		rcu_read_unlock();
 		return -ENODEV;
 	}
-	dev = idev->dev;
 
 	err = -EADDRNOTAVAIL;
 
@@ -455,7 +453,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
 {
 	struct in6_addr *group;
 	struct ipv6_mc_socklist *pmc;
-	struct net_device *dev;
 	struct inet6_dev *idev;
 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
 	struct ip6_sf_socklist *newpsl, *psl;
@@ -478,7 +475,6 @@ int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf)
 		rcu_read_unlock();
 		return -ENODEV;
 	}
-	dev = idev->dev;
 
 	err = 0;
 
@@ -549,7 +545,6 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
 	struct in6_addr *group;
 	struct ipv6_mc_socklist *pmc;
 	struct inet6_dev *idev;
-	struct net_device *dev;
 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
 	struct ip6_sf_socklist *psl;
 	struct net *net = sock_net(sk);
@@ -566,7 +561,6 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
 		rcu_read_unlock();
 		return -ENODEV;
 	}
-	dev = idev->dev;
 
 	err = -EADDRNOTAVAIL;
 	/*
@@ -1402,7 +1396,7 @@ static void mld_sendpack(struct sk_buff *skb)
 	struct inet6_dev *idev;
 	struct net *net = dev_net(skb->dev);
 	int err;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 
 	rcu_read_lock();
@@ -1425,11 +1419,16 @@ static void mld_sendpack(struct sk_buff *skb)
 		goto err_out;
 	}
 
-	icmpv6_flow_init(net->ipv6.igmp_sk, &fl, ICMPV6_MLD2_REPORT,
+	icmpv6_flow_init(net->ipv6.igmp_sk, &fl6, ICMPV6_MLD2_REPORT,
 			 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
 			 skb->dev->ifindex);
 
-	err = xfrm_lookup(net, &dst, &fl, NULL, 0);
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+	err = 0;
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
+		dst = NULL;
+	}
 	skb_dst_set(skb, dst);
 	if (err)
 		goto err_out;
@@ -1732,7 +1731,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 	u8 ra[8] = { IPPROTO_ICMPV6, 0,
 		     IPV6_TLV_ROUTERALERT, 2, 0, 0,
 		     IPV6_TLV_PADN, 0 };
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 
 	if (type == ICMPV6_MGM_REDUCTION)
@@ -1792,13 +1791,15 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 		goto err_out;
 	}
 
-	icmpv6_flow_init(sk, &fl, type,
+	icmpv6_flow_init(sk, &fl6, type,
 			 &ipv6_hdr(skb)->saddr, &ipv6_hdr(skb)->daddr,
 			 skb->dev->ifindex);
 
-	err = xfrm_lookup(net, &dst, &fl, NULL, 0);
-	if (err)
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
 		goto err_out;
+	}
 
 	skb_dst_set(skb, dst);
 	err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, skb->dev,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index d6e9599..9b21048 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -203,18 +203,20 @@ static inline int mip6_report_rl_allow(struct timeval *stamp,
 	return allow;
 }
 
-static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct flowi *fl)
+static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb,
+			       const struct flowi *fl)
 {
 	struct net *net = xs_net(x);
 	struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
+	const struct flowi6 *fl6 = &fl->u.ip6;
 	struct ipv6_destopt_hao *hao = NULL;
 	struct xfrm_selector sel;
 	int offset;
 	struct timeval stamp;
 	int err = 0;
 
-	if (unlikely(fl->proto == IPPROTO_MH &&
-		     fl->fl_mh_type <= IP6_MH_TYPE_MAX))
+	if (unlikely(fl6->flowi6_proto == IPPROTO_MH &&
+		     fl6->fl6_mh_type <= IP6_MH_TYPE_MAX))
 		goto out;
 
 	if (likely(opt->dsthao)) {
@@ -239,14 +241,14 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct
 	       sizeof(sel.saddr));
 	sel.prefixlen_s = 128;
 	sel.family = AF_INET6;
-	sel.proto = fl->proto;
-	sel.dport = xfrm_flowi_dport(fl);
+	sel.proto = fl6->flowi6_proto;
+	sel.dport = xfrm_flowi_dport(fl, &fl6->uli);
 	if (sel.dport)
 		sel.dport_mask = htons(~0);
-	sel.sport = xfrm_flowi_sport(fl);
+	sel.sport = xfrm_flowi_sport(fl, &fl6->uli);
 	if (sel.sport)
 		sel.sport_mask = htons(~0);
-	sel.ifindex = fl->oif;
+	sel.ifindex = fl6->flowi6_oif;
 
 	err = km_report(net, IPPROTO_DSTOPTS, &sel,
 			(hao ? (xfrm_address_t *)&hao->addr : NULL));
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 2342545..0e49c9d 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -511,7 +511,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 		    const struct in6_addr *saddr,
 		    struct icmp6hdr *icmp6h)
 {
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 	struct net *net = dev_net(dev);
 	struct sock *sk = net->ipv6.ndisc_sk;
@@ -521,7 +521,7 @@ void ndisc_send_skb(struct sk_buff *skb,
 
 	type = icmp6h->icmp6_type;
 
-	icmpv6_flow_init(sk, &fl, type, saddr, daddr, dev->ifindex);
+	icmpv6_flow_init(sk, &fl6, type, saddr, daddr, dev->ifindex);
 
 	dst = icmp6_dst_alloc(dev, neigh, daddr);
 	if (!dst) {
@@ -529,8 +529,8 @@ void ndisc_send_skb(struct sk_buff *skb,
 		return;
 	}
 
-	err = xfrm_lookup(net, &dst, &fl, NULL, 0);
-	if (err < 0) {
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+	if (IS_ERR(dst)) {
 		kfree_skb(skb);
 		return;
 	}
@@ -1515,7 +1515,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 	struct rt6_info *rt;
 	struct dst_entry *dst;
 	struct inet6_dev *idev;
-	struct flowi fl;
+	struct flowi6 fl6;
 	u8 *opt;
 	int rd_len;
 	int err;
@@ -1535,15 +1535,15 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 		return;
 	}
 
-	icmpv6_flow_init(sk, &fl, NDISC_REDIRECT,
+	icmpv6_flow_init(sk, &fl6, NDISC_REDIRECT,
 			 &saddr_buf, &ipv6_hdr(skb)->saddr, dev->ifindex);
 
-	dst = ip6_route_output(net, NULL, &fl);
+	dst = ip6_route_output(net, NULL, &fl6);
 	if (dst == NULL)
 		return;
 
-	err = xfrm_lookup(net, &dst, &fl, NULL, 0);
-	if (err)
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+	if (IS_ERR(dst))
 		return;
 
 	rt = (struct rt6_info *) dst;
@@ -1553,7 +1553,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 			   "ICMPv6 Redirect: destination is not a neighbour.\n");
 		goto release;
 	}
-	if (!xrlim_allow(dst, 1*HZ))
+	if (!rt->rt6i_peer)
+		rt6_bind_peer(rt, 1);
+	if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
 		goto release;
 
 	if (dev->addr_len) {
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index 35915e8..39aaca2 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -15,14 +15,14 @@ int ip6_route_me_harder(struct sk_buff *skb)
 	struct net *net = dev_net(skb_dst(skb)->dev);
 	struct ipv6hdr *iph = ipv6_hdr(skb);
 	struct dst_entry *dst;
-	struct flowi fl = {
-		.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
-		.mark = skb->mark,
-		.fl6_dst = iph->daddr,
-		.fl6_src = iph->saddr,
+	struct flowi6 fl6 = {
+		.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
+		.flowi6_mark = skb->mark,
+		.daddr = iph->daddr,
+		.saddr = iph->saddr,
 	};
 
-	dst = ip6_route_output(net, skb->sk, &fl);
+	dst = ip6_route_output(net, skb->sk, &fl6);
 	if (dst->error) {
 		IP6_INC_STATS(net, ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
 		LIMIT_NETDEBUG(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
@@ -37,9 +37,10 @@ int ip6_route_me_harder(struct sk_buff *skb)
 
 #ifdef CONFIG_XFRM
 	if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
-	    xfrm_decode_session(skb, &fl, AF_INET6) == 0) {
+	    xfrm_decode_session(skb, flowi6_to_flowi(&fl6), AF_INET6) == 0) {
 		skb_dst_set(skb, NULL);
-		if (xfrm_lookup(net, &dst, &fl, skb->sk, 0))
+		dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), skb->sk, 0);
+		if (IS_ERR(dst))
 			return -1;
 		skb_dst_set(skb, dst);
 	}
@@ -91,7 +92,7 @@ static int nf_ip6_reroute(struct sk_buff *skb,
 
 static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl)
 {
-	*dst = ip6_route_output(&init_net, NULL, fl);
+	*dst = ip6_route_output(&init_net, NULL, &fl->u.ip6);
 	return (*dst)->error;
 }
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 7d227c6..0b2af9b 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -410,7 +410,7 @@ ip6t_do_table(struct sk_buff *skb,
 					verdict = (unsigned)(-v) - 1;
 					break;
 				}
-				if (*stackptr == 0)
+				if (*stackptr <= origptr)
 					e = get_entry(table_base,
 					    private->underflow[hook]);
 				else
@@ -441,8 +441,8 @@ ip6t_do_table(struct sk_buff *skb,
 			break;
 	} while (!acpar.hotdrop);
 
-	xt_info_rdunlock_bh();
 	*stackptr = origptr;
+	xt_info_rdunlock_bh();
 
 #ifdef DEBUG_ALLOW_ALL
 	return NF_ACCEPT;
@@ -1076,6 +1076,7 @@ static int compat_table_info(const struct xt_table_info *info,
 	memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
 	newinfo->initial_entries = 0;
 	loc_cpu_entry = info->entries[raw_smp_processor_id()];
+	xt_compat_init_offsets(AF_INET6, info->number);
 	xt_entry_foreach(iter, loc_cpu_entry, info->size) {
 		ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
 		if (ret != 0)
@@ -1274,6 +1275,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
 	/* overflow check */
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -1679,6 +1681,7 @@ translate_compat_table(struct net *net,
 	duprintf("translate_compat_table: size %u\n", info->size);
 	j = 0;
 	xt_compat_lock(AF_INET6);
+	xt_compat_init_offsets(AF_INET6, number);
 	/* Walk through entries, checking offsets. */
 	xt_entry_foreach(iter0, entry0, total_size) {
 		ret = check_compat_entry_size_and_hooks(iter0, info, &size,
@@ -1820,6 +1823,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
 		return -ENOMEM;
 	if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
 		return -ENOMEM;
+	tmp.name[sizeof(tmp.name)-1] = 0;
 
 	newinfo = xt_alloc_table_info(tmp.size);
 	if (!newinfo)
@@ -2049,6 +2053,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 			ret = -EFAULT;
 			break;
 		}
+		rev.name[sizeof(rev.name)-1] = 0;
 
 		if (cmd == IP6T_SO_GET_REVISION_TARGET)
 			target = 1;
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index de33803..e6af8d7 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -452,8 +452,7 @@ ip6t_log_packet(u_int8_t pf,
 	       in ? in->name : "",
 	       out ? out->name : "");
 
-	/* MAC logging for input path only. */
-	if (in && !out)
+	if (in != NULL)
 		dump_mac_header(m, loginfo, skb);
 
 	dump_packet(m, loginfo, skb, skb_network_offset(skb), 1);
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c
index bf998fe..28e7448 100644
--- a/net/ipv6/netfilter/ip6t_REJECT.c
+++ b/net/ipv6/netfilter/ip6t_REJECT.c
@@ -47,7 +47,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
 	struct ipv6hdr *ip6h;
 	struct dst_entry *dst = NULL;
 	u8 proto;
-	struct flowi fl;
+	struct flowi6 fl6;
 
 	if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
 	    (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
@@ -89,19 +89,20 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
 		return;
 	}
 
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = IPPROTO_TCP;
-	ipv6_addr_copy(&fl.fl6_src, &oip6h->daddr);
-	ipv6_addr_copy(&fl.fl6_dst, &oip6h->saddr);
-	fl.fl_ip_sport = otcph.dest;
-	fl.fl_ip_dport = otcph.source;
-	security_skb_classify_flow(oldskb, &fl);
-	dst = ip6_route_output(net, NULL, &fl);
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = IPPROTO_TCP;
+	ipv6_addr_copy(&fl6.saddr, &oip6h->daddr);
+	ipv6_addr_copy(&fl6.daddr, &oip6h->saddr);
+	fl6.fl6_sport = otcph.dest;
+	fl6.fl6_dport = otcph.source;
+	security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
+	dst = ip6_route_output(net, NULL, &fl6);
 	if (dst == NULL || dst->error) {
 		dst_release(dst);
 		return;
 	}
-	if (xfrm_lookup(net, &dst, &fl, NULL, 0))
+	dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+	if (IS_ERR(dst))
 		return;
 
 	hh_len = (dst->dev->hard_header_len + 15)&~15;
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 79d43aa..0857272 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -45,6 +45,7 @@
 #include <linux/netfilter_ipv6.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 
 
 struct nf_ct_frag6_skb_cb
@@ -73,7 +74,7 @@ static struct inet_frags nf_frags;
 static struct netns_frags nf_init_frags;
 
 #ifdef CONFIG_SYSCTL
-struct ctl_table nf_ct_frag6_sysctl_table[] = {
+static struct ctl_table nf_ct_frag6_sysctl_table[] = {
 	{
 		.procname	= "nf_conntrack_frag6_timeout",
 		.data		= &nf_init_frags.timeout,
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index c5b0915..4a1c3b4 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -124,18 +124,18 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
 }
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-static int (*mh_filter)(struct sock *sock, struct sk_buff *skb);
+typedef int mh_filter_t(struct sock *sock, struct sk_buff *skb);
 
-int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
-					   struct sk_buff *skb))
+static mh_filter_t __rcu *mh_filter __read_mostly;
+
+int rawv6_mh_filter_register(mh_filter_t filter)
 {
 	rcu_assign_pointer(mh_filter, filter);
 	return 0;
 }
 EXPORT_SYMBOL(rawv6_mh_filter_register);
 
-int rawv6_mh_filter_unregister(int (*filter)(struct sock *sock,
-					     struct sk_buff *skb))
+int rawv6_mh_filter_unregister(mh_filter_t filter)
 {
 	rcu_assign_pointer(mh_filter, NULL);
 	synchronize_rcu();
@@ -193,10 +193,10 @@ static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
 			 * policy is placed in rawv6_rcv() because it is
 			 * required for each socket.
 			 */
-			int (*filter)(struct sock *sock, struct sk_buff *skb);
+			mh_filter_t *filter;
 
 			filter = rcu_dereference(mh_filter);
-			filtered = filter ? filter(sk, skb) : 0;
+			filtered = filter ? (*filter)(sk, skb) : 0;
 			break;
 		}
 #endif
@@ -524,7 +524,7 @@ csum_copy_err:
 	goto out;
 }
 
-static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
+static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
 				     struct raw6_sock *rp)
 {
 	struct sk_buff *skb;
@@ -586,11 +586,10 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl,
 	if (unlikely(csum))
 		tmp_csum = csum_sub(tmp_csum, csum_unfold(csum));
 
-	csum = csum_ipv6_magic(&fl->fl6_src,
-				   &fl->fl6_dst,
-				   total_len, fl->proto, tmp_csum);
+	csum = csum_ipv6_magic(&fl6->saddr, &fl6->daddr,
+			       total_len, fl6->flowi6_proto, tmp_csum);
 
-	if (csum == 0 && fl->proto == IPPROTO_UDP)
+	if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP)
 		csum = CSUM_MANGLED_0;
 
 	if (skb_store_bits(skb, offset, &csum, 2))
@@ -603,7 +602,7 @@ out:
 }
 
 static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
-			struct flowi *fl, struct dst_entry **dstp,
+			struct flowi6 *fl6, struct dst_entry **dstp,
 			unsigned int flags)
 {
 	struct ipv6_pinfo *np = inet6_sk(sk);
@@ -613,7 +612,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
 	struct rt6_info *rt = (struct rt6_info *)*dstp;
 
 	if (length > rt->dst.dev->mtu) {
-		ipv6_local_error(sk, EMSGSIZE, fl, rt->dst.dev->mtu);
+		ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
 		return -EMSGSIZE;
 	}
 	if (flags&MSG_PROBE)
@@ -662,7 +661,7 @@ error:
 	return err;
 }
 
-static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
+static int rawv6_probe_proto_opt(struct flowi6 *fl6, struct msghdr *msg)
 {
 	struct iovec *iov;
 	u8 __user *type = NULL;
@@ -679,7 +678,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
 		if (!iov)
 			continue;
 
-		switch (fl->proto) {
+		switch (fl6->flowi6_proto) {
 		case IPPROTO_ICMPV6:
 			/* check if one-byte field is readable or not. */
 			if (iov->iov_base && iov->iov_len < 1)
@@ -694,8 +693,8 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
 				code = iov->iov_base;
 
 			if (type && code) {
-				if (get_user(fl->fl_icmp_type, type) ||
-				    get_user(fl->fl_icmp_code, code))
+				if (get_user(fl6->fl6_icmp_type, type) ||
+				    get_user(fl6->fl6_icmp_code, code))
 					return -EFAULT;
 				probed = 1;
 			}
@@ -706,7 +705,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
 			/* check if type field is readable or not. */
 			if (iov->iov_len > 2 - len) {
 				u8 __user *p = iov->iov_base;
-				if (get_user(fl->fl_mh_type, &p[2 - len]))
+				if (get_user(fl6->fl6_mh_type, &p[2 - len]))
 					return -EFAULT;
 				probed = 1;
 			} else
@@ -735,7 +734,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
 	struct dst_entry *dst = NULL;
-	struct flowi fl;
+	struct flowi6 fl6;
 	int addr_len = msg->msg_namelen;
 	int hlimit = -1;
 	int tclass = -1;
@@ -756,9 +755,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	/*
 	 *	Get and verify the address.
 	 */
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 
-	fl.mark = sk->sk_mark;
+	fl6.flowi6_mark = sk->sk_mark;
 
 	if (sin6) {
 		if (addr_len < SIN6_LEN_RFC2133)
@@ -780,9 +779,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 
 		daddr = &sin6->sin6_addr;
 		if (np->sndflow) {
-			fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-			if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
-				flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+			fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+			if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
+				flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 				if (flowlabel == NULL)
 					return -EINVAL;
 				daddr = &flowlabel->dst;
@@ -800,32 +799,32 @@ 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)
-			fl.oif = sin6->sin6_scope_id;
+			fl6.flowi6_oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
 
 		proto = inet->inet_num;
 		daddr = &np->daddr;
-		fl.fl6_flowlabel = np->flow_label;
+		fl6.flowlabel = np->flow_label;
 	}
 
-	if (fl.oif == 0)
-		fl.oif = sk->sk_bound_dev_if;
+	if (fl6.flowi6_oif == 0)
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
 
 	if (msg->msg_controllen) {
 		opt = &opt_space;
 		memset(opt, 0, sizeof(struct ipv6_txoptions));
 		opt->tot_len = sizeof(struct ipv6_txoptions);
 
-		err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit,
+		err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit,
 					&tclass, &dontfrag);
 		if (err < 0) {
 			fl6_sock_release(flowlabel);
 			return err;
 		}
-		if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
-			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+		if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
+			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 			if (flowlabel == NULL)
 				return -EINVAL;
 		}
@@ -838,40 +837,31 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 		opt = fl6_merge_options(&opt_space, flowlabel, opt);
 	opt = ipv6_fixup_options(&opt_space, opt);
 
-	fl.proto = proto;
-	err = rawv6_probe_proto_opt(&fl, msg);
+	fl6.flowi6_proto = proto;
+	err = rawv6_probe_proto_opt(&fl6, msg);
 	if (err)
 		goto out;
 
 	if (!ipv6_addr_any(daddr))
-		ipv6_addr_copy(&fl.fl6_dst, daddr);
+		ipv6_addr_copy(&fl6.daddr, daddr);
 	else
-		fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
-	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
-		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
+		fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+	if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
+		ipv6_addr_copy(&fl6.saddr, &np->saddr);
 
-	final_p = fl6_update_dst(&fl, opt, &final);
+	final_p = fl6_update_dst(&fl6, opt, &final);
 
-	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
-		fl.oif = np->mcast_oif;
-	security_sk_classify_flow(sk, &fl);
+	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
+		fl6.flowi6_oif = np->mcast_oif;
+	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
 		goto out;
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
-	if (err < 0) {
-		if (err == -EREMOTE)
-			err = ip6_dst_blackhole(sk, &dst, &fl);
-		if (err < 0)
-			goto out;
 	}
-
 	if (hlimit < 0) {
-		if (ipv6_addr_is_multicast(&fl.fl6_dst))
+		if (ipv6_addr_is_multicast(&fl6.daddr))
 			hlimit = np->mcast_hops;
 		else
 			hlimit = np->hop_limit;
@@ -890,17 +880,17 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 
 back_from_confirm:
 	if (inet->hdrincl)
-		err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, &dst, msg->msg_flags);
+		err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl6, &dst, msg->msg_flags);
 	else {
 		lock_sock(sk);
 		err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov,
-			len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst,
+			len, 0, hlimit, tclass, opt, &fl6, (struct rt6_info*)dst,
 			msg->msg_flags, dontfrag);
 
 		if (err)
 			ip6_flush_pending_frames(sk);
 		else if (!(msg->msg_flags & MSG_MORE))
-			err = rawv6_push_pending_frames(sk, &fl, rp);
+			err = rawv6_push_pending_frames(sk, &fl6, rp);
 		release_sock(sk);
 	}
 done:
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e7db701..6814c87 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -97,6 +97,36 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
 					   struct in6_addr *gwaddr, int ifindex);
 #endif
 
+static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
+{
+	struct rt6_info *rt = (struct rt6_info *) dst;
+	struct inet_peer *peer;
+	u32 *p = NULL;
+
+	if (!rt->rt6i_peer)
+		rt6_bind_peer(rt, 1);
+
+	peer = rt->rt6i_peer;
+	if (peer) {
+		u32 *old_p = __DST_METRICS_PTR(old);
+		unsigned long prev, new;
+
+		p = peer->metrics;
+		if (inet_metrics_new(peer))
+			memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
+
+		new = (unsigned long) p;
+		prev = cmpxchg(&dst->_metrics, old, new);
+
+		if (prev != old) {
+			p = __DST_METRICS_PTR(prev);
+			if (prev & DST_METRICS_READ_ONLY)
+				p = NULL;
+		}
+	}
+	return p;
+}
+
 static struct dst_ops ip6_dst_ops_template = {
 	.family			=	AF_INET6,
 	.protocol		=	cpu_to_be16(ETH_P_IPV6),
@@ -105,6 +135,7 @@ static struct dst_ops ip6_dst_ops_template = {
 	.check			=	ip6_dst_check,
 	.default_advmss		=	ip6_default_advmss,
 	.default_mtu		=	ip6_default_mtu,
+	.cow_metrics		=	ipv6_cow_metrics,
 	.destroy		=	ip6_dst_destroy,
 	.ifdown			=	ip6_dst_ifdown,
 	.negative_advice	=	ip6_negative_advice,
@@ -132,6 +163,10 @@ static struct dst_ops ip6_dst_blackhole_ops = {
 	.update_pmtu		=	ip6_rt_blackhole_update_pmtu,
 };
 
+static const u32 ip6_template_metrics[RTAX_MAX] = {
+	[RTAX_HOPLIMIT - 1] = 255,
+};
+
 static struct rt6_info ip6_null_entry_template = {
 	.dst = {
 		.__refcnt	= ATOMIC_INIT(1),
@@ -187,7 +222,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
 /* allocate dst with ip6_dst_ops */
 static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops)
 {
-	return (struct rt6_info *)dst_alloc(ops);
+	return (struct rt6_info *)dst_alloc(ops, 0);
 }
 
 static void ip6_dst_destroy(struct dst_entry *dst)
@@ -206,6 +241,13 @@ static void ip6_dst_destroy(struct dst_entry *dst)
 	}
 }
 
+static atomic_t __rt6_peer_genid = ATOMIC_INIT(0);
+
+static u32 rt6_peer_genid(void)
+{
+	return atomic_read(&__rt6_peer_genid);
+}
+
 void rt6_bind_peer(struct rt6_info *rt, int create)
 {
 	struct inet_peer *peer;
@@ -213,6 +255,8 @@ void rt6_bind_peer(struct rt6_info *rt, int create)
 	peer = inet_getpeer_v6(&rt->rt6i_dst.addr, create);
 	if (peer && cmpxchg(&rt->rt6i_peer, NULL, peer) != NULL)
 		inet_putpeer(peer);
+	else
+		rt->rt6i_peer_genid = rt6_peer_genid();
 }
 
 static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
@@ -555,17 +599,17 @@ do { \
 
 static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 					     struct fib6_table *table,
-					     struct flowi *fl, int flags)
+					     struct flowi6 *fl6, int flags)
 {
 	struct fib6_node *fn;
 	struct rt6_info *rt;
 
 	read_lock_bh(&table->tb6_lock);
-	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
+	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 restart:
 	rt = fn->leaf;
-	rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
-	BACKTRACK(net, &fl->fl6_src);
+	rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+	BACKTRACK(net, &fl6->saddr);
 out:
 	dst_use(&rt->dst, jiffies);
 	read_unlock_bh(&table->tb6_lock);
@@ -576,19 +620,19 @@ out:
 struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
 			    const struct in6_addr *saddr, int oif, int strict)
 {
-	struct flowi fl = {
-		.oif = oif,
-		.fl6_dst = *daddr,
+	struct flowi6 fl6 = {
+		.flowi6_oif = oif,
+		.daddr = *daddr,
 	};
 	struct dst_entry *dst;
 	int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
 
 	if (saddr) {
-		memcpy(&fl.fl6_src, saddr, sizeof(*saddr));
+		memcpy(&fl6.saddr, saddr, sizeof(*saddr));
 		flags |= RT6_LOOKUP_F_HAS_SADDR;
 	}
 
-	dst = fib6_rule_lookup(net, &fl, flags, ip6_pol_route_lookup);
+	dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup);
 	if (dst->error == 0)
 		return (struct rt6_info *) dst;
 
@@ -709,7 +753,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *d
 }
 
 static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
-				      struct flowi *fl, int flags)
+				      struct flowi6 *fl6, int flags)
 {
 	struct fib6_node *fn;
 	struct rt6_info *rt, *nrt;
@@ -724,12 +768,12 @@ relookup:
 	read_lock_bh(&table->tb6_lock);
 
 restart_2:
-	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
+	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 
 restart:
 	rt = rt6_select(fn, oif, strict | reachable);
 
-	BACKTRACK(net, &fl->fl6_src);
+	BACKTRACK(net, &fl6->saddr);
 	if (rt == net->ipv6.ip6_null_entry ||
 	    rt->rt6i_flags & RTF_CACHE)
 		goto out;
@@ -738,9 +782,9 @@ restart:
 	read_unlock_bh(&table->tb6_lock);
 
 	if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
-		nrt = rt6_alloc_cow(rt, &fl->fl6_dst, &fl->fl6_src);
+		nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
 	else if (!(rt->dst.flags & DST_HOST))
-		nrt = rt6_alloc_clone(rt, &fl->fl6_dst);
+		nrt = rt6_alloc_clone(rt, &fl6->daddr);
 	else
 		goto out2;
 
@@ -779,9 +823,9 @@ out2:
 }
 
 static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
-					    struct flowi *fl, int flags)
+					    struct flowi6 *fl6, int flags)
 {
-	return ip6_pol_route(net, table, fl->iif, fl, flags);
+	return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
 }
 
 void ip6_route_input(struct sk_buff *skb)
@@ -789,56 +833,54 @@ void ip6_route_input(struct sk_buff *skb)
 	struct ipv6hdr *iph = ipv6_hdr(skb);
 	struct net *net = dev_net(skb->dev);
 	int flags = RT6_LOOKUP_F_HAS_SADDR;
-	struct flowi fl = {
-		.iif = skb->dev->ifindex,
-		.fl6_dst = iph->daddr,
-		.fl6_src = iph->saddr,
-		.fl6_flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
-		.mark = skb->mark,
-		.proto = iph->nexthdr,
+	struct flowi6 fl6 = {
+		.flowi6_iif = skb->dev->ifindex,
+		.daddr = iph->daddr,
+		.saddr = iph->saddr,
+		.flowlabel = (* (__be32 *) iph)&IPV6_FLOWINFO_MASK,
+		.flowi6_mark = skb->mark,
+		.flowi6_proto = iph->nexthdr,
 	};
 
 	if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG)
 		flags |= RT6_LOOKUP_F_IFACE;
 
-	skb_dst_set(skb, fib6_rule_lookup(net, &fl, flags, ip6_pol_route_input));
+	skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input));
 }
 
 static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
-					     struct flowi *fl, int flags)
+					     struct flowi6 *fl6, int flags)
 {
-	return ip6_pol_route(net, table, fl->oif, fl, flags);
+	return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
 }
 
 struct dst_entry * ip6_route_output(struct net *net, struct sock *sk,
-				    struct flowi *fl)
+				    struct flowi6 *fl6)
 {
 	int flags = 0;
 
-	if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl->fl6_dst))
+	if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
 		flags |= RT6_LOOKUP_F_IFACE;
 
-	if (!ipv6_addr_any(&fl->fl6_src))
+	if (!ipv6_addr_any(&fl6->saddr))
 		flags |= RT6_LOOKUP_F_HAS_SADDR;
 	else if (sk)
 		flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
 
-	return fib6_rule_lookup(net, fl, flags, ip6_pol_route_output);
+	return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
 }
 
 EXPORT_SYMBOL(ip6_route_output);
 
-int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl)
+struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
 {
-	struct rt6_info *ort = (struct rt6_info *) *dstp;
-	struct rt6_info *rt = (struct rt6_info *)
-		dst_alloc(&ip6_dst_blackhole_ops);
+	struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1);
+	struct rt6_info *ort = (struct rt6_info *) dst_orig;
 	struct dst_entry *new = NULL;
 
 	if (rt) {
 		new = &rt->dst;
 
-		atomic_set(&new->__refcnt, 1);
 		new->__use = 1;
 		new->input = dst_discard;
 		new->output = dst_discard;
@@ -864,11 +906,9 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl
 		dst_free(new);
 	}
 
-	dst_release(*dstp);
-	*dstp = new;
-	return new ? 0 : -ENOMEM;
+	dst_release(dst_orig);
+	return new ? new : ERR_PTR(-ENOMEM);
 }
-EXPORT_SYMBOL_GPL(ip6_dst_blackhole);
 
 /*
  *	Destination cache support functions
@@ -880,9 +920,14 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
 	rt = (struct rt6_info *) dst;
 
-	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
+	if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
+		if (rt->rt6i_peer_genid != rt6_peer_genid()) {
+			if (!rt->rt6i_peer)
+				rt6_bind_peer(rt, 0);
+			rt->rt6i_peer_genid = rt6_peer_genid();
+		}
 		return dst;
-
+	}
 	return NULL;
 }
 
@@ -933,7 +978,6 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 			dst_metric_set(dst, RTAX_FEATURES, features);
 		}
 		dst_metric_set(dst, RTAX_MTU, mtu);
-		call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst);
 	}
 }
 
@@ -1030,11 +1074,9 @@ out:
 
 int icmp6_dst_gc(void)
 {
-	struct dst_entry *dst, *next, **pprev;
+	struct dst_entry *dst, **pprev;
 	int more = 0;
 
-	next = NULL;
-
 	spin_lock_bh(&icmp6_dst_lock);
 	pprev = &icmp6_dst_gc_list;
 
@@ -1402,16 +1444,16 @@ static int ip6_route_del(struct fib6_config *cfg)
  *	Handle redirects
  */
 struct ip6rd_flowi {
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct in6_addr gateway;
 };
 
 static struct rt6_info *__ip6_route_redirect(struct net *net,
 					     struct fib6_table *table,
-					     struct flowi *fl,
+					     struct flowi6 *fl6,
 					     int flags)
 {
-	struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl;
+	struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
 	struct rt6_info *rt;
 	struct fib6_node *fn;
 
@@ -1427,7 +1469,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
 	 */
 
 	read_lock_bh(&table->tb6_lock);
-	fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
+	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 restart:
 	for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
 		/*
@@ -1442,7 +1484,7 @@ restart:
 			continue;
 		if (!(rt->rt6i_flags & RTF_GATEWAY))
 			continue;
-		if (fl->oif != rt->rt6i_dev->ifindex)
+		if (fl6->flowi6_oif != rt->rt6i_dev->ifindex)
 			continue;
 		if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
 			continue;
@@ -1451,7 +1493,7 @@ restart:
 
 	if (!rt)
 		rt = net->ipv6.ip6_null_entry;
-	BACKTRACK(net, &fl->fl6_src);
+	BACKTRACK(net, &fl6->saddr);
 out:
 	dst_hold(&rt->dst);
 
@@ -1468,10 +1510,10 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
 	int flags = RT6_LOOKUP_F_HAS_SADDR;
 	struct net *net = dev_net(dev);
 	struct ip6rd_flowi rdfl = {
-		.fl = {
-			.oif = dev->ifindex,
-			.fl6_dst = *dest,
-			.fl6_src = *src,
+		.fl6 = {
+			.flowi6_oif = dev->ifindex,
+			.daddr = *dest,
+			.saddr = *src,
 		},
 	};
 
@@ -1480,7 +1522,7 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest,
 	if (rt6_need_strict(dest))
 		flags |= RT6_LOOKUP_F_IFACE;
 
-	return (struct rt6_info *)fib6_rule_lookup(net, (struct flowi *)&rdfl,
+	return (struct rt6_info *)fib6_rule_lookup(net, &rdfl.fl6,
 						   flags, __ip6_route_redirect);
 }
 
@@ -1982,12 +2024,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
 	if (IS_ERR(neigh)) {
 		dst_free(&rt->dst);
 
-		/* We are casting this because that is the return
-		 * value type.  But an errno encoded pointer is the
-		 * same regardless of the underlying pointer type,
-		 * and that's what we are returning.  So this is OK.
-		 */
-		return (struct rt6_info *) neigh;
+		return ERR_CAST(neigh);
 	}
 	rt->rt6i_nexthop = neigh;
 
@@ -2348,7 +2385,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 	struct rt6_info *rt;
 	struct sk_buff *skb;
 	struct rtmsg *rtm;
-	struct flowi fl;
+	struct flowi6 fl6;
 	int err, iif = 0;
 
 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
@@ -2356,27 +2393,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 		goto errout;
 
 	err = -EINVAL;
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 
 	if (tb[RTA_SRC]) {
 		if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
 			goto errout;
 
-		ipv6_addr_copy(&fl.fl6_src, nla_data(tb[RTA_SRC]));
+		ipv6_addr_copy(&fl6.saddr, nla_data(tb[RTA_SRC]));
 	}
 
 	if (tb[RTA_DST]) {
 		if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
 			goto errout;
 
-		ipv6_addr_copy(&fl.fl6_dst, nla_data(tb[RTA_DST]));
+		ipv6_addr_copy(&fl6.daddr, nla_data(tb[RTA_DST]));
 	}
 
 	if (tb[RTA_IIF])
 		iif = nla_get_u32(tb[RTA_IIF]);
 
 	if (tb[RTA_OIF])
-		fl.oif = nla_get_u32(tb[RTA_OIF]);
+		fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]);
 
 	if (iif) {
 		struct net_device *dev;
@@ -2399,10 +2436,10 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 	skb_reset_mac_header(skb);
 	skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
 
-	rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl);
+	rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6);
 	skb_dst_set(skb, &rt->dst);
 
-	err = rt6_fill_node(net, skb, rt, &fl.fl6_dst, &fl.fl6_src, iif,
+	err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
 			    RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
 			    nlh->nlmsg_seq, 0, 0, 0);
 	if (err < 0) {
@@ -2689,7 +2726,8 @@ static int __net_init ip6_route_net_init(struct net *net)
 	net->ipv6.ip6_null_entry->dst.path =
 		(struct dst_entry *)net->ipv6.ip6_null_entry;
 	net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
-	dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255);
+	dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
+			 ip6_template_metrics, true);
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
 	net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
@@ -2700,7 +2738,8 @@ static int __net_init ip6_route_net_init(struct net *net)
 	net->ipv6.ip6_prohibit_entry->dst.path =
 		(struct dst_entry *)net->ipv6.ip6_prohibit_entry;
 	net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
-	dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255);
+	dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
+			 ip6_template_metrics, true);
 
 	net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
 					       sizeof(*net->ipv6.ip6_blk_hole_entry),
@@ -2710,7 +2749,8 @@ static int __net_init ip6_route_net_init(struct net *net)
 	net->ipv6.ip6_blk_hole_entry->dst.path =
 		(struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
 	net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
-	dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255);
+	dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
+			 ip6_template_metrics, true);
 #endif
 
 	net->ipv6.sysctl.flush_delay = 0;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index d2c16e1..43b3337 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -412,7 +412,7 @@ static void prl_list_destroy_rcu(struct rcu_head *head)
 
 	p = container_of(head, struct ip_tunnel_prl_entry, rcu_head);
 	do {
-		n = p->next;
+		n = rcu_dereference_protected(p->next, 1);
 		kfree(p);
 		p = n;
 	} while (p);
@@ -421,15 +421,17 @@ static void prl_list_destroy_rcu(struct rcu_head *head)
 static int
 ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
 {
-	struct ip_tunnel_prl_entry *x, **p;
+	struct ip_tunnel_prl_entry *x;
+	struct ip_tunnel_prl_entry __rcu **p;
 	int err = 0;
 
 	ASSERT_RTNL();
 
 	if (a && a->addr != htonl(INADDR_ANY)) {
-		for (p = &t->prl; *p; p = &(*p)->next) {
-			if ((*p)->addr == a->addr) {
-				x = *p;
+		for (p = &t->prl;
+		     (x = rtnl_dereference(*p)) != NULL;
+		     p = &x->next) {
+			if (x->addr == a->addr) {
 				*p = x->next;
 				call_rcu(&x->rcu_head, prl_entry_destroy_rcu);
 				t->prl_count--;
@@ -438,9 +440,9 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
 		}
 		err = -ENXIO;
 	} else {
-		if (t->prl) {
+		x = rtnl_dereference(t->prl);
+		if (x) {
 			t->prl_count = 0;
-			x = t->prl;
 			call_rcu(&x->rcu_head, prl_list_destroy_rcu);
 			t->prl = NULL;
 		}
@@ -730,16 +732,14 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
 		dst = addr6->s6_addr32[3];
 	}
 
-	{
-		struct flowi fl = { .fl4_dst = dst,
-				    .fl4_src = tiph->saddr,
-				    .fl4_tos = RT_TOS(tos),
-				    .oif = tunnel->parms.link,
-				    .proto = IPPROTO_IPV6 };
-		if (ip_route_output_key(dev_net(dev), &rt, &fl)) {
-			dev->stats.tx_carrier_errors++;
-			goto tx_error_icmp;
-		}
+	rt = ip_route_output_ports(dev_net(dev), NULL,
+				   dst, tiph->saddr,
+				   0, 0,
+				   IPPROTO_IPV6, RT_TOS(tos),
+				   tunnel->parms.link);
+	if (IS_ERR(rt)) {
+		dev->stats.tx_carrier_errors++;
+		goto tx_error_icmp;
 	}
 	if (rt->rt_type != RTN_UNICAST) {
 		ip_rt_put(rt);
@@ -855,13 +855,14 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
 	iph = &tunnel->parms.iph;
 
 	if (iph->daddr) {
-		struct flowi fl = { .fl4_dst = iph->daddr,
-				    .fl4_src = iph->saddr,
-				    .fl4_tos = RT_TOS(iph->tos),
-				    .oif = tunnel->parms.link,
-				    .proto = IPPROTO_IPV6 };
-		struct rtable *rt;
-		if (!ip_route_output_key(dev_net(dev), &rt, &fl)) {
+		struct rtable *rt = ip_route_output_ports(dev_net(dev), NULL,
+							  iph->daddr, iph->saddr,
+							  0, 0,
+							  IPPROTO_IPV6,
+							  RT_TOS(iph->tos),
+							  tunnel->parms.link);
+
+		if (!IS_ERR(rt)) {
 			tdev = rt->dst.dev;
 			ip_rt_put(rt);
 		}
@@ -1179,7 +1180,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
 	if (!dev->tstats)
 		return -ENOMEM;
 	dev_hold(dev);
-	sitn->tunnels_wc[0]	= tunnel;
+	rcu_assign_pointer(sitn->tunnels_wc[0], tunnel);
 	return 0;
 }
 
@@ -1196,11 +1197,12 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea
 	for (prio = 1; prio < 4; prio++) {
 		int h;
 		for (h = 0; h < HASH_SIZE; h++) {
-			struct ip_tunnel *t = sitn->tunnels[prio][h];
+			struct ip_tunnel *t;
 
+			t = rtnl_dereference(sitn->tunnels[prio][h]);
 			while (t != NULL) {
 				unregister_netdevice_queue(t->dev, head);
-				t = t->next;
+				t = rtnl_dereference(t->next);
 			}
 		}
 	}
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 09fd34f..352c260 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -232,23 +232,20 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 	 */
 	{
 		struct in6_addr *final_p, final;
-		struct flowi fl;
-		memset(&fl, 0, sizeof(fl));
-		fl.proto = IPPROTO_TCP;
-		ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr);
-		final_p = fl6_update_dst(&fl, np->opt, &final);
-		ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
-		fl.oif = sk->sk_bound_dev_if;
-		fl.mark = sk->sk_mark;
-		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-		fl.fl_ip_sport = inet_sk(sk)->inet_sport;
-		security_req_classify_flow(req, &fl);
-		if (ip6_dst_lookup(sk, &dst, &fl))
-			goto out_free;
-
-		if (final_p)
-			ipv6_addr_copy(&fl.fl6_dst, final_p);
-		if ((xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
+		struct flowi6 fl6;
+		memset(&fl6, 0, sizeof(fl6));
+		fl6.flowi6_proto = IPPROTO_TCP;
+		ipv6_addr_copy(&fl6.daddr, &ireq6->rmt_addr);
+		final_p = fl6_update_dst(&fl6, np->opt, &final);
+		ipv6_addr_copy(&fl6.saddr, &ireq6->loc_addr);
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
+		fl6.flowi6_mark = sk->sk_mark;
+		fl6.fl6_dport = inet_rsk(req)->rmt_port;
+		fl6.fl6_sport = inet_sk(sk)->inet_sport;
+		security_req_classify_flow(req, flowi6_to_flowi(&fl6));
+
+		dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+		if (IS_ERR(dst))
 			goto out_free;
 	}
 
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c
index 7cb65ef..6dcf5e7 100644
--- a/net/ipv6/sysctl_net_ipv6.c
+++ b/net/ipv6/sysctl_net_ipv6.c
@@ -17,6 +17,16 @@
 
 static struct ctl_table empty[1];
 
+static ctl_table ipv6_static_skeleton[] = {
+	{
+		.procname	= "neigh",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= empty,
+	},
+	{ }
+};
+
 static ctl_table ipv6_table_template[] = {
 	{
 		.procname	= "route",
@@ -37,12 +47,6 @@ static ctl_table ipv6_table_template[] = {
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
-	{
-		.procname	= "neigh",
-		.maxlen		= 0,
-		.mode		= 0555,
-		.child		= empty,
-	},
 	{ }
 };
 
@@ -160,7 +164,7 @@ static struct ctl_table_header *ip6_base;
 
 int ipv6_static_sysctl_register(void)
 {
-	ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty);
+	ip6_base = register_sysctl_paths(net_ipv6_ctl_path, ipv6_static_skeleton);
 	if (ip6_base == NULL)
 		return -ENOMEM;
 	return 0;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 20aa95e..2b0c186 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -131,7 +131,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct in6_addr *saddr = NULL, *final_p, final;
 	struct rt6_info *rt;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 	int addr_type;
 	int err;
@@ -142,14 +142,14 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	if (usin->sin6_family != AF_INET6)
 		return -EAFNOSUPPORT;
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 
 	if (np->sndflow) {
-		fl.fl6_flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-		IP6_ECN_flow_init(fl.fl6_flowlabel);
-		if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
+		fl6.flowlabel = usin->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+		IP6_ECN_flow_init(fl6.flowlabel);
+		if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
 			struct ip6_flowlabel *flowlabel;
-			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 			if (flowlabel == NULL)
 				return -EINVAL;
 			ipv6_addr_copy(&usin->sin6_addr, &flowlabel->dst);
@@ -195,7 +195,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	}
 
 	ipv6_addr_copy(&np->daddr, &usin->sin6_addr);
-	np->flow_label = fl.fl6_flowlabel;
+	np->flow_label = fl6.flowlabel;
 
 	/*
 	 *	TCP over IPv4
@@ -242,35 +242,27 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
 	if (!ipv6_addr_any(&np->rcv_saddr))
 		saddr = &np->rcv_saddr;
 
-	fl.proto = IPPROTO_TCP;
-	ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-	ipv6_addr_copy(&fl.fl6_src,
+	fl6.flowi6_proto = IPPROTO_TCP;
+	ipv6_addr_copy(&fl6.daddr, &np->daddr);
+	ipv6_addr_copy(&fl6.saddr,
 		       (saddr ? saddr : &np->saddr));
-	fl.oif = sk->sk_bound_dev_if;
-	fl.mark = sk->sk_mark;
-	fl.fl_ip_dport = usin->sin6_port;
-	fl.fl_ip_sport = inet->inet_sport;
+	fl6.flowi6_oif = sk->sk_bound_dev_if;
+	fl6.flowi6_mark = sk->sk_mark;
+	fl6.fl6_dport = usin->sin6_port;
+	fl6.fl6_sport = inet->inet_sport;
 
-	final_p = fl6_update_dst(&fl, np->opt, &final);
+	final_p = fl6_update_dst(&fl6, np->opt, &final);
 
-	security_sk_classify_flow(sk, &fl);
+	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, true);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
 		goto failure;
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
-	if (err < 0) {
-		if (err == -EREMOTE)
-			err = ip6_dst_blackhole(sk, &dst, &fl);
-		if (err < 0)
-			goto failure;
 	}
 
 	if (saddr == NULL) {
-		saddr = &fl.fl6_src;
+		saddr = &fl6.saddr;
 		ipv6_addr_copy(&np->rcv_saddr, saddr);
 	}
 
@@ -385,7 +377,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 	np = inet6_sk(sk);
 
 	if (type == ICMPV6_PKT_TOOBIG) {
-		struct dst_entry *dst = NULL;
+		struct dst_entry *dst;
 
 		if (sock_owned_by_user(sk))
 			goto out;
@@ -397,29 +389,25 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
 		if (dst == NULL) {
 			struct inet_sock *inet = inet_sk(sk);
-			struct flowi fl;
+			struct flowi6 fl6;
 
 			/* BUGGG_FUTURE: Again, it is not clear how
 			   to handle rthdr case. Ignore this complexity
 			   for now.
 			 */
-			memset(&fl, 0, sizeof(fl));
-			fl.proto = IPPROTO_TCP;
-			ipv6_addr_copy(&fl.fl6_dst, &np->daddr);
-			ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-			fl.oif = sk->sk_bound_dev_if;
-			fl.mark = sk->sk_mark;
-			fl.fl_ip_dport = inet->inet_dport;
-			fl.fl_ip_sport = inet->inet_sport;
-			security_skb_classify_flow(skb, &fl);
-
-			if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
-				sk->sk_err_soft = -err;
-				goto out;
-			}
-
-			if ((err = xfrm_lookup(net, &dst, &fl, sk, 0)) < 0) {
-				sk->sk_err_soft = -err;
+			memset(&fl6, 0, sizeof(fl6));
+			fl6.flowi6_proto = IPPROTO_TCP;
+			ipv6_addr_copy(&fl6.daddr, &np->daddr);
+			ipv6_addr_copy(&fl6.saddr, &np->saddr);
+			fl6.flowi6_oif = sk->sk_bound_dev_if;
+			fl6.flowi6_mark = sk->sk_mark;
+			fl6.fl6_dport = inet->inet_dport;
+			fl6.fl6_sport = inet->inet_sport;
+			security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
+
+			dst = ip6_dst_lookup_flow(sk, &fl6, NULL, false);
+			if (IS_ERR(dst)) {
+				sk->sk_err_soft = -PTR_ERR(dst);
 				goto out;
 			}
 
@@ -494,38 +482,36 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 	struct sk_buff * skb;
 	struct ipv6_txoptions *opt = NULL;
 	struct in6_addr * final_p, final;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
-	int err = -1;
-
-	memset(&fl, 0, sizeof(fl));
-	fl.proto = IPPROTO_TCP;
-	ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-	ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
-	fl.fl6_flowlabel = 0;
-	fl.oif = treq->iif;
-	fl.mark = sk->sk_mark;
-	fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-	fl.fl_ip_sport = inet_rsk(req)->loc_port;
-	security_req_classify_flow(req, &fl);
+	int err;
+
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_proto = IPPROTO_TCP;
+	ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
+	ipv6_addr_copy(&fl6.saddr, &treq->loc_addr);
+	fl6.flowlabel = 0;
+	fl6.flowi6_oif = treq->iif;
+	fl6.flowi6_mark = sk->sk_mark;
+	fl6.fl6_dport = inet_rsk(req)->rmt_port;
+	fl6.fl6_sport = inet_rsk(req)->loc_port;
+	security_req_classify_flow(req, flowi6_to_flowi(&fl6));
 
 	opt = np->opt;
-	final_p = fl6_update_dst(&fl, opt, &final);
+	final_p = fl6_update_dst(&fl6, opt, &final);
 
-	err = ip6_dst_lookup(sk, &dst, &fl);
-	if (err)
-		goto done;
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-	if ((err = xfrm_lookup(sock_net(sk), &dst, &fl, sk, 0)) < 0)
+	dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
 		goto done;
-
+	}
 	skb = tcp_make_synack(sk, dst, req, rvp);
+	err = -ENOMEM;
 	if (skb) {
 		__tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
 
-		ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
-		err = ip6_xmit(sk, skb, &fl, opt);
+		ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr);
+		err = ip6_xmit(sk, skb, &fl6, opt);
 		err = net_xmit_eval(err);
 	}
 
@@ -1006,7 +992,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 {
 	struct tcphdr *th = tcp_hdr(skb), *t1;
 	struct sk_buff *buff;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct net *net = dev_net(skb_dst(skb)->dev);
 	struct sock *ctl_sk = net->ipv6.tcp_sk;
 	unsigned int tot_len = sizeof(struct tcphdr);
@@ -1060,34 +1046,33 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
 	}
 #endif
 
-	memset(&fl, 0, sizeof(fl));
-	ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
-	ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
+	memset(&fl6, 0, sizeof(fl6));
+	ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->saddr);
+	ipv6_addr_copy(&fl6.saddr, &ipv6_hdr(skb)->daddr);
 
 	buff->ip_summed = CHECKSUM_PARTIAL;
 	buff->csum = 0;
 
-	__tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst);
+	__tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr);
 
-	fl.proto = IPPROTO_TCP;
-	fl.oif = inet6_iif(skb);
-	fl.fl_ip_dport = t1->dest;
-	fl.fl_ip_sport = t1->source;
-	security_skb_classify_flow(skb, &fl);
+	fl6.flowi6_proto = IPPROTO_TCP;
+	fl6.flowi6_oif = inet6_iif(skb);
+	fl6.fl6_dport = t1->dest;
+	fl6.fl6_sport = t1->source;
+	security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
 
 	/* Pass a socket to ip6_dst_lookup either it is for RST
 	 * Underlying function will use this to retrieve the network
 	 * namespace
 	 */
-	if (!ip6_dst_lookup(ctl_sk, &dst, &fl)) {
-		if (xfrm_lookup(net, &dst, &fl, NULL, 0) >= 0) {
-			skb_dst_set(buff, dst);
-			ip6_xmit(ctl_sk, buff, &fl, NULL);
-			TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
-			if (rst)
-				TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
-			return;
-		}
+	dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false);
+	if (!IS_ERR(dst)) {
+		skb_dst_set(buff, dst);
+		ip6_xmit(ctl_sk, buff, &fl6, NULL);
+		TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS);
+		if (rst)
+			TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS);
+		return;
 	}
 
 	kfree_skb(buff);
@@ -1323,7 +1308,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 		    tcp_death_row.sysctl_tw_recycle &&
 		    (dst = inet6_csk_route_req(sk, req)) != NULL &&
 		    (peer = rt6_get_peer((struct rt6_info *)dst)) != NULL &&
-		    ipv6_addr_equal((struct in6_addr *)peer->daddr.a6,
+		    ipv6_addr_equal((struct in6_addr *)peer->daddr.addr.a6,
 				    &treq->rmt_addr)) {
 			inet_peer_refcheck(peer);
 			if ((u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL &&
@@ -1636,10 +1621,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 		opt_skb = skb_clone(skb, GFP_ATOMIC);
 
 	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
-		TCP_CHECK_TIMER(sk);
 		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
 			goto reset;
-		TCP_CHECK_TIMER(sk);
 		if (opt_skb)
 			goto ipv6_pktoptions;
 		return 0;
@@ -1667,10 +1650,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
 		}
 	}
 
-	TCP_CHECK_TIMER(sk);
 	if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len))
 		goto reset;
-	TCP_CHECK_TIMER(sk);
 	if (opt_skb)
 		goto ipv6_pktoptions;
 	return 0;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9a009c6..d7037c0 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -886,7 +886,7 @@ static int udp_v6_push_pending_frames(struct sock *sk)
 	struct udphdr *uh;
 	struct udp_sock  *up = udp_sk(sk);
 	struct inet_sock *inet = inet_sk(sk);
-	struct flowi *fl = &inet->cork.fl;
+	struct flowi6 *fl6 = &inet->cork.fl.u.ip6;
 	int err = 0;
 	int is_udplite = IS_UDPLITE(sk);
 	__wsum csum = 0;
@@ -899,23 +899,23 @@ static int udp_v6_push_pending_frames(struct sock *sk)
 	 * Create a UDP header
 	 */
 	uh = udp_hdr(skb);
-	uh->source = fl->fl_ip_sport;
-	uh->dest = fl->fl_ip_dport;
+	uh->source = fl6->fl6_sport;
+	uh->dest = fl6->fl6_dport;
 	uh->len = htons(up->len);
 	uh->check = 0;
 
 	if (is_udplite)
 		csum = udplite_csum_outgoing(sk, skb);
 	else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */
-		udp6_hwcsum_outgoing(sk, skb, &fl->fl6_src, &fl->fl6_dst,
+		udp6_hwcsum_outgoing(sk, skb, &fl6->saddr, &fl6->daddr,
 				     up->len);
 		goto send;
 	} else
 		csum = udp_csum_outgoing(sk, skb);
 
 	/* add protocol-dependent pseudo-header */
-	uh->check = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst,
-				    up->len, fl->proto, csum   );
+	uh->check = csum_ipv6_magic(&fl6->saddr, &fl6->daddr,
+				    up->len, fl6->flowi6_proto, csum);
 	if (uh->check == 0)
 		uh->check = CSUM_MANGLED_0;
 
@@ -947,7 +947,7 @@ int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
 	struct in6_addr *daddr, *final_p, final;
 	struct ipv6_txoptions *opt = NULL;
 	struct ip6_flowlabel *flowlabel = NULL;
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 	int addr_len = msg->msg_namelen;
 	int ulen = len;
@@ -1030,19 +1030,19 @@ do_udp_sendmsg:
 	}
 	ulen += sizeof(struct udphdr);
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 
 	if (sin6) {
 		if (sin6->sin6_port == 0)
 			return -EINVAL;
 
-		fl.fl_ip_dport = sin6->sin6_port;
+		fl6.fl6_dport = sin6->sin6_port;
 		daddr = &sin6->sin6_addr;
 
 		if (np->sndflow) {
-			fl.fl6_flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
-			if (fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) {
-				flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+			fl6.flowlabel = sin6->sin6_flowinfo&IPV6_FLOWINFO_MASK;
+			if (fl6.flowlabel&IPV6_FLOWLABEL_MASK) {
+				flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 				if (flowlabel == NULL)
 					return -EINVAL;
 				daddr = &flowlabel->dst;
@@ -1060,38 +1060,38 @@ do_udp_sendmsg:
 		if (addr_len >= sizeof(struct sockaddr_in6) &&
 		    sin6->sin6_scope_id &&
 		    ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL)
-			fl.oif = sin6->sin6_scope_id;
+			fl6.flowi6_oif = sin6->sin6_scope_id;
 	} else {
 		if (sk->sk_state != TCP_ESTABLISHED)
 			return -EDESTADDRREQ;
 
-		fl.fl_ip_dport = inet->inet_dport;
+		fl6.fl6_dport = inet->inet_dport;
 		daddr = &np->daddr;
-		fl.fl6_flowlabel = np->flow_label;
+		fl6.flowlabel = np->flow_label;
 		connected = 1;
 	}
 
-	if (!fl.oif)
-		fl.oif = sk->sk_bound_dev_if;
+	if (!fl6.flowi6_oif)
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
 
-	if (!fl.oif)
-		fl.oif = np->sticky_pktinfo.ipi6_ifindex;
+	if (!fl6.flowi6_oif)
+		fl6.flowi6_oif = np->sticky_pktinfo.ipi6_ifindex;
 
-	fl.mark = sk->sk_mark;
+	fl6.flowi6_mark = sk->sk_mark;
 
 	if (msg->msg_controllen) {
 		opt = &opt_space;
 		memset(opt, 0, sizeof(struct ipv6_txoptions));
 		opt->tot_len = sizeof(*opt);
 
-		err = datagram_send_ctl(sock_net(sk), msg, &fl, opt, &hlimit,
+		err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit,
 					&tclass, &dontfrag);
 		if (err < 0) {
 			fl6_sock_release(flowlabel);
 			return err;
 		}
-		if ((fl.fl6_flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
-			flowlabel = fl6_sock_lookup(sk, fl.fl6_flowlabel);
+		if ((fl6.flowlabel&IPV6_FLOWLABEL_MASK) && !flowlabel) {
+			flowlabel = fl6_sock_lookup(sk, fl6.flowlabel);
 			if (flowlabel == NULL)
 				return -EINVAL;
 		}
@@ -1105,42 +1105,35 @@ do_udp_sendmsg:
 		opt = fl6_merge_options(&opt_space, flowlabel, opt);
 	opt = ipv6_fixup_options(&opt_space, opt);
 
-	fl.proto = sk->sk_protocol;
+	fl6.flowi6_proto = sk->sk_protocol;
 	if (!ipv6_addr_any(daddr))
-		ipv6_addr_copy(&fl.fl6_dst, daddr);
+		ipv6_addr_copy(&fl6.daddr, daddr);
 	else
-		fl.fl6_dst.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
-	if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
-		ipv6_addr_copy(&fl.fl6_src, &np->saddr);
-	fl.fl_ip_sport = inet->inet_sport;
+		fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+	if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
+		ipv6_addr_copy(&fl6.saddr, &np->saddr);
+	fl6.fl6_sport = inet->inet_sport;
 
-	final_p = fl6_update_dst(&fl, opt, &final);
+	final_p = fl6_update_dst(&fl6, opt, &final);
 	if (final_p)
 		connected = 0;
 
-	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst)) {
-		fl.oif = np->mcast_oif;
+	if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) {
+		fl6.flowi6_oif = np->mcast_oif;
 		connected = 0;
 	}
 
-	security_sk_classify_flow(sk, &fl);
+	security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 
-	err = ip6_sk_dst_lookup(sk, &dst, &fl);
-	if (err)
+	dst = ip6_sk_dst_lookup_flow(sk, &fl6, final_p, true);
+	if (IS_ERR(dst)) {
+		err = PTR_ERR(dst);
+		dst = NULL;
 		goto out;
-	if (final_p)
-		ipv6_addr_copy(&fl.fl6_dst, final_p);
-
-	err = __xfrm_lookup(sock_net(sk), &dst, &fl, sk, XFRM_LOOKUP_WAIT);
-	if (err < 0) {
-		if (err == -EREMOTE)
-			err = ip6_dst_blackhole(sk, &dst, &fl);
-		if (err < 0)
-			goto out;
 	}
 
 	if (hlimit < 0) {
-		if (ipv6_addr_is_multicast(&fl.fl6_dst))
+		if (ipv6_addr_is_multicast(&fl6.daddr))
 			hlimit = np->mcast_hops;
 		else
 			hlimit = np->hop_limit;
@@ -1175,7 +1168,7 @@ do_append_data:
 	up->len += ulen;
 	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
 	err = ip6_append_data(sk, getfrag, msg->msg_iov, ulen,
-		sizeof(struct udphdr), hlimit, tclass, opt, &fl,
+		sizeof(struct udphdr), hlimit, tclass, opt, &fl6,
 		(struct rt6_info*)dst,
 		corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags, dontfrag);
 	if (err)
@@ -1188,10 +1181,10 @@ do_append_data:
 	if (dst) {
 		if (connected) {
 			ip6_dst_store(sk, dst,
-				      ipv6_addr_equal(&fl.fl6_dst, &np->daddr) ?
+				      ipv6_addr_equal(&fl6.daddr, &np->daddr) ?
 				      &np->daddr : NULL,
 #ifdef CONFIG_IPV6_SUBTREES
-				      ipv6_addr_equal(&fl.fl6_src, &np->saddr) ?
+				      ipv6_addr_equal(&fl6.saddr, &np->saddr) ?
 				      &np->saddr :
 #endif
 				      NULL);
@@ -1299,7 +1292,7 @@ static int udp6_ufo_send_check(struct sk_buff *skb)
 	return 0;
 }
 
-static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, int features)
+static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
 {
 	struct sk_buff *segs = ERR_PTR(-EINVAL);
 	unsigned int mss;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index da87428..05e34c8 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -27,18 +27,19 @@
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
 static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos,
-					  xfrm_address_t *saddr,
-					  xfrm_address_t *daddr)
+					  const xfrm_address_t *saddr,
+					  const xfrm_address_t *daddr)
 {
-	struct flowi fl = {};
+	struct flowi6 fl6;
 	struct dst_entry *dst;
 	int err;
 
-	memcpy(&fl.fl6_dst, daddr, sizeof(fl.fl6_dst));
+	memset(&fl6, 0, sizeof(fl6));
+	memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
 	if (saddr)
-		memcpy(&fl.fl6_src, saddr, sizeof(fl.fl6_src));
+		memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
 
-	dst = ip6_route_output(net, NULL, &fl);
+	dst = ip6_route_output(net, NULL, &fl6);
 
 	err = dst->error;
 	if (dst->error) {
@@ -67,7 +68,7 @@ static int xfrm6_get_saddr(struct net *net,
 	return 0;
 }
 
-static int xfrm6_get_tos(struct flowi *fl)
+static int xfrm6_get_tos(const struct flowi *fl)
 {
 	return 0;
 }
@@ -87,7 +88,7 @@ static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst,
 }
 
 static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
-			  struct flowi *fl)
+			  const struct flowi *fl)
 {
 	struct rt6_info *rt = (struct rt6_info*)xdst->route;
 
@@ -120,6 +121,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
 static inline void
 _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 {
+	struct flowi6 *fl6 = &fl->u.ip6;
 	int onlyproto = 0;
 	u16 offset = skb_network_header_len(skb);
 	struct ipv6hdr *hdr = ipv6_hdr(skb);
@@ -127,11 +129,11 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 	const unsigned char *nh = skb_network_header(skb);
 	u8 nexthdr = nh[IP6CB(skb)->nhoff];
 
-	memset(fl, 0, sizeof(struct flowi));
-	fl->mark = skb->mark;
+	memset(fl6, 0, sizeof(struct flowi6));
+	fl6->flowi6_mark = skb->mark;
 
-	ipv6_addr_copy(&fl->fl6_dst, reverse ? &hdr->saddr : &hdr->daddr);
-	ipv6_addr_copy(&fl->fl6_src, reverse ? &hdr->daddr : &hdr->saddr);
+	ipv6_addr_copy(&fl6->daddr, reverse ? &hdr->saddr : &hdr->daddr);
+	ipv6_addr_copy(&fl6->saddr, reverse ? &hdr->daddr : &hdr->saddr);
 
 	while (nh + offset + 1 < skb->data ||
 	       pskb_may_pull(skb, nh + offset + 1 - skb->data)) {
@@ -158,20 +160,20 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 			     pskb_may_pull(skb, nh + offset + 4 - skb->data))) {
 				__be16 *ports = (__be16 *)exthdr;
 
-				fl->fl_ip_sport = ports[!!reverse];
-				fl->fl_ip_dport = ports[!reverse];
+				fl6->fl6_sport = ports[!!reverse];
+				fl6->fl6_dport = ports[!reverse];
 			}
-			fl->proto = nexthdr;
+			fl6->flowi6_proto = nexthdr;
 			return;
 
 		case IPPROTO_ICMPV6:
 			if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) {
 				u8 *icmp = (u8 *)exthdr;
 
-				fl->fl_icmp_type = icmp[0];
-				fl->fl_icmp_code = icmp[1];
+				fl6->fl6_icmp_type = icmp[0];
+				fl6->fl6_icmp_code = icmp[1];
 			}
-			fl->proto = nexthdr;
+			fl6->flowi6_proto = nexthdr;
 			return;
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
@@ -180,9 +182,9 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 				struct ip6_mh *mh;
 				mh = (struct ip6_mh *)exthdr;
 
-				fl->fl_mh_type = mh->ip6mh_type;
+				fl6->fl6_mh_type = mh->ip6mh_type;
 			}
-			fl->proto = nexthdr;
+			fl6->flowi6_proto = nexthdr;
 			return;
 #endif
 
@@ -191,8 +193,8 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
 		case IPPROTO_ESP:
 		case IPPROTO_COMP:
 		default:
-			fl->fl_ipsec_spi = 0;
-			fl->proto = nexthdr;
+			fl6->fl6_ipsec_spi = 0;
+			fl6->flowi6_proto = nexthdr;
 			return;
 		}
 	}
@@ -220,6 +222,7 @@ static void xfrm6_dst_destroy(struct dst_entry *dst)
 
 	if (likely(xdst->u.rt6.rt6i_idev))
 		in6_dev_put(xdst->u.rt6.rt6i_idev);
+	dst_destroy_metrics_generic(dst);
 	if (likely(xdst->u.rt6.rt6i_peer))
 		inet_putpeer(xdst->u.rt6.rt6i_peer);
 	xfrm_dst_destroy(xdst);
@@ -257,6 +260,7 @@ static struct dst_ops xfrm6_dst_ops = {
 	.protocol =		cpu_to_be16(ETH_P_IPV6),
 	.gc =			xfrm6_garbage_collect,
 	.update_pmtu =		xfrm6_update_pmtu,
+	.cow_metrics =		dst_cow_metrics_generic,
 	.destroy =		xfrm6_dst_destroy,
 	.ifdown =		xfrm6_dst_ifdown,
 	.local_out =		__ip6_local_out,
@@ -272,6 +276,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
 	.get_tos =		xfrm6_get_tos,
 	.init_path =		xfrm6_init_path,
 	.fill_dst =		xfrm6_fill_dst,
+	.blackhole_route =	ip6_blackhole_route,
 };
 
 static int __init xfrm6_policy_init(void)
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index a67575d..afe941e 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -20,26 +20,28 @@
 #include <net/addrconf.h>
 
 static void
-__xfrm6_init_tempsel(struct xfrm_selector *sel, struct flowi *fl)
+__xfrm6_init_tempsel(struct xfrm_selector *sel, const struct flowi *fl)
 {
+	const struct flowi6 *fl6 = &fl->u.ip6;
+
 	/* Initialize temporary selector matching only
 	 * to current session. */
-	ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl->fl6_dst);
-	ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl->fl6_src);
-	sel->dport = xfrm_flowi_dport(fl);
+	ipv6_addr_copy((struct in6_addr *)&sel->daddr, &fl6->daddr);
+	ipv6_addr_copy((struct in6_addr *)&sel->saddr, &fl6->saddr);
+	sel->dport = xfrm_flowi_dport(fl, &fl6->uli);
 	sel->dport_mask = htons(0xffff);
-	sel->sport = xfrm_flowi_sport(fl);
+	sel->sport = xfrm_flowi_sport(fl, &fl6->uli);
 	sel->sport_mask = htons(0xffff);
 	sel->family = AF_INET6;
 	sel->prefixlen_d = 128;
 	sel->prefixlen_s = 128;
-	sel->proto = fl->proto;
-	sel->ifindex = fl->oif;
+	sel->proto = fl6->flowi6_proto;
+	sel->ifindex = fl6->flowi6_oif;
 }
 
 static void
-xfrm6_init_temprop(struct xfrm_state *x, struct xfrm_tmpl *tmpl,
-		   xfrm_address_t *daddr, xfrm_address_t *saddr)
+xfrm6_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl,
+		   const xfrm_address_t *daddr, const xfrm_address_t *saddr)
 {
 	x->id = tmpl->id;
 	if (ipv6_addr_any((struct in6_addr*)&x->id.daddr))
diff --git a/net/ipx/Kconfig b/net/ipx/Kconfig
index 02549cb..e9ad006 100644
--- a/net/ipx/Kconfig
+++ b/net/ipx/Kconfig
@@ -3,7 +3,6 @@
 #
 config IPX
 	tristate "The IPX protocol"
-	depends on BKL # should be fixable
 	select LLC
 	---help---
 	  This is support for the Novell networking protocol, IPX, commonly
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index da3d21c..9680226 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -42,7 +42,6 @@
 #include <linux/uio.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
-#include <linux/smp_lock.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/string.h>
@@ -149,7 +148,6 @@ static void ipx_destroy_socket(struct sock *sk)
 	ipx_remove_socket(sk);
 	skb_queue_purge(&sk->sk_receive_queue);
 	sk_refcnt_debug_dec(sk);
-	sock_put(sk);
 }
 
 /*
@@ -1299,7 +1297,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
 	int opt;
 	int rc = -EINVAL;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (optlen != sizeof(int))
 		goto out;
 
@@ -1314,7 +1312,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
 	ipx_sk(sk)->type = opt;
 	rc = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 }
 
@@ -1326,7 +1324,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
 	int len;
 	int rc = -ENOPROTOOPT;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (!(level == SOL_IPX && optname == IPX_TYPE))
 		goto out;
 
@@ -1347,7 +1345,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
 
 	rc = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 }
 
@@ -1396,7 +1394,7 @@ static int ipx_release(struct socket *sock)
 	if (!sk)
 		goto out;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_state_change(sk);
 
@@ -1404,7 +1402,8 @@ static int ipx_release(struct socket *sock)
 	sock->sk = NULL;
 	sk_refcnt_debug_release(sk);
 	ipx_destroy_socket(sk);
-	unlock_kernel();
+	release_sock(sk);
+	sock_put(sk);
 out:
 	return 0;
 }
@@ -1530,11 +1529,12 @@ out:
 
 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
+	struct sock *sk = sock->sk;
 	int rc;
 
-	lock_kernel();
+	lock_sock(sk);
 	rc = __ipx_bind(sock, uaddr, addr_len);
-	unlock_kernel();
+	release_sock(sk);
 
 	return rc;
 }
@@ -1551,7 +1551,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 	sk->sk_state	= TCP_CLOSE;
 	sock->state 	= SS_UNCONNECTED;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (addr_len != sizeof(*addr))
 		goto out;
 	addr = (struct sockaddr_ipx *)uaddr;
@@ -1598,7 +1598,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
 		ipxrtr_put(rt);
 	rc = 0;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 }
 
@@ -1614,7 +1614,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
 	*uaddr_len = sizeof(struct sockaddr_ipx);
 
-	lock_kernel();
+	lock_sock(sk);
 	if (peer) {
 		rc = -ENOTCONN;
 		if (sk->sk_state != TCP_ESTABLISHED)
@@ -1649,19 +1649,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
 	rc = 0;
 out:
-	unlock_kernel();
-	return rc;
-}
-
-static unsigned int ipx_datagram_poll(struct file *file, struct socket *sock,
-			   poll_table *wait)
-{
-	int rc;
-
-	lock_kernel();
-	rc = datagram_poll(file, sock, wait);
-	unlock_kernel();
-
+	release_sock(sk);
 	return rc;
 }
 
@@ -1736,7 +1724,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
 	int rc = -EINVAL;
 	int flags = msg->msg_flags;
 
-	lock_kernel();
+	lock_sock(sk);
 	/* Socket gets bound below anyway */
 /*	if (sk->sk_zapped)
 		return -EIO; */	/* Socket not bound */
@@ -1788,7 +1776,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
 	if (rc >= 0)
 		rc = len;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 }
 
@@ -1803,7 +1791,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 	struct sk_buff *skb;
 	int copied, rc;
 
-	lock_kernel();
+	lock_sock(sk);
 	/* put the autobinding in */
 	if (!ipxs->port) {
 		struct sockaddr_ipx uaddr;
@@ -1862,7 +1850,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 out_free:
 	skb_free_datagram(sk, skb);
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 }
 
@@ -1874,7 +1862,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 	struct sock *sk = sock->sk;
 	void __user *argp = (void __user *)arg;
 
-	lock_kernel();
+	lock_sock(sk);
 	switch (cmd) {
 	case TIOCOUTQ:
 		amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1937,7 +1925,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 		rc = -ENOIOCTLCMD;
 		break;
 	}
-	unlock_kernel();
+	release_sock(sk);
 
 	return rc;
 }
@@ -1984,7 +1972,7 @@ static const struct proto_ops ipx_dgram_ops = {
 	.socketpair	= sock_no_socketpair,
 	.accept		= sock_no_accept,
 	.getname	= ipx_getname,
-	.poll		= ipx_datagram_poll,
+	.poll		= datagram_poll,
 	.ioctl		= ipx_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= ipx_compat_ioctl,
diff --git a/net/irda/ircomm/ircomm_tty_ioctl.c b/net/irda/ircomm/ircomm_tty_ioctl.c
index 24cb3aa..77c5e64 100644
--- a/net/irda/ircomm/ircomm_tty_ioctl.c
+++ b/net/irda/ircomm/ircomm_tty_ioctl.c
@@ -189,12 +189,12 @@ void ircomm_tty_set_termios(struct tty_struct *tty,
 }
 
 /*
- * Function ircomm_tty_tiocmget (tty, file)
+ * Function ircomm_tty_tiocmget (tty)
  *
  *
  *
  */
-int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
+int ircomm_tty_tiocmget(struct tty_struct *tty)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 	unsigned int result;
@@ -214,12 +214,12 @@ int ircomm_tty_tiocmget(struct tty_struct *tty, struct file *file)
 }
 
 /*
- * Function ircomm_tty_tiocmset (tty, file, set, clear)
+ * Function ircomm_tty_tiocmset (tty, set, clear)
  *
  *
  *
  */
-int ircomm_tty_tiocmset(struct tty_struct *tty, struct file *file,
+int ircomm_tty_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
@@ -365,12 +365,12 @@ static int ircomm_tty_set_serial_info(struct ircomm_tty_cb *self,
 }
 
 /*
- * Function ircomm_tty_ioctl (tty, file, cmd, arg)
+ * Function ircomm_tty_ioctl (tty, cmd, arg)
  *
  *
  *
  */
-int ircomm_tty_ioctl(struct tty_struct *tty, struct file *file,
+int ircomm_tty_ioctl(struct tty_struct *tty,
 		     unsigned int cmd, unsigned long arg)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index d87c22d..7db86ff 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -70,7 +70,7 @@ static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
 	return (struct pfkey_sock *)sk;
 }
 
-static int pfkey_can_dump(struct sock *sk)
+static int pfkey_can_dump(const struct sock *sk)
 {
 	if (3 * atomic_read(&sk->sk_rmem_alloc) <= 2 * sk->sk_rcvbuf)
 		return 1;
@@ -303,12 +303,13 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
 	return rc;
 }
 
-static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig)
+static inline void pfkey_hdr_dup(struct sadb_msg *new,
+				 const struct sadb_msg *orig)
 {
 	*new = *orig;
 }
 
-static int pfkey_error(struct sadb_msg *orig, int err, struct sock *sk)
+static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
 {
 	struct sk_buff *skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
 	struct sadb_msg *hdr;
@@ -369,13 +370,13 @@ static u8 sadb_ext_min_len[] = {
 };
 
 /* Verify sadb_address_{len,prefixlen} against sa_family.  */
-static int verify_address_len(void *p)
+static int verify_address_len(const void *p)
 {
-	struct sadb_address *sp = p;
-	struct sockaddr *addr = (struct sockaddr *)(sp + 1);
-	struct sockaddr_in *sin;
+	const struct sadb_address *sp = p;
+	const struct sockaddr *addr = (const struct sockaddr *)(sp + 1);
+	const struct sockaddr_in *sin;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-	struct sockaddr_in6 *sin6;
+	const struct sockaddr_in6 *sin6;
 #endif
 	int len;
 
@@ -411,16 +412,16 @@ static int verify_address_len(void *p)
 	return 0;
 }
 
-static inline int pfkey_sec_ctx_len(struct sadb_x_sec_ctx *sec_ctx)
+static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx)
 {
 	return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) +
 			    sec_ctx->sadb_x_ctx_len,
 			    sizeof(uint64_t));
 }
 
-static inline int verify_sec_ctx_len(void *p)
+static inline int verify_sec_ctx_len(const void *p)
 {
-	struct sadb_x_sec_ctx *sec_ctx = (struct sadb_x_sec_ctx *)p;
+	const struct sadb_x_sec_ctx *sec_ctx = p;
 	int len = sec_ctx->sadb_x_ctx_len;
 
 	if (len > PAGE_SIZE)
@@ -434,7 +435,7 @@ static inline int verify_sec_ctx_len(void *p)
 	return 0;
 }
 
-static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(struct sadb_x_sec_ctx *sec_ctx)
+static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(const struct sadb_x_sec_ctx *sec_ctx)
 {
 	struct xfrm_user_sec_ctx *uctx = NULL;
 	int ctx_size = sec_ctx->sadb_x_ctx_len;
@@ -455,16 +456,16 @@ static inline struct xfrm_user_sec_ctx *pfkey_sadb2xfrm_user_sec_ctx(struct sadb
 	return uctx;
 }
 
-static int present_and_same_family(struct sadb_address *src,
-				   struct sadb_address *dst)
+static int present_and_same_family(const struct sadb_address *src,
+				   const struct sadb_address *dst)
 {
-	struct sockaddr *s_addr, *d_addr;
+	const struct sockaddr *s_addr, *d_addr;
 
 	if (!src || !dst)
 		return 0;
 
-	s_addr = (struct sockaddr *)(src + 1);
-	d_addr = (struct sockaddr *)(dst + 1);
+	s_addr = (const struct sockaddr *)(src + 1);
+	d_addr = (const struct sockaddr *)(dst + 1);
 	if (s_addr->sa_family != d_addr->sa_family)
 		return 0;
 	if (s_addr->sa_family != AF_INET
@@ -477,15 +478,15 @@ static int present_and_same_family(struct sadb_address *src,
 	return 1;
 }
 
-static int parse_exthdrs(struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void **ext_hdrs)
 {
-	char *p = (char *) hdr;
+	const char *p = (char *) hdr;
 	int len = skb->len;
 
 	len -= sizeof(*hdr);
 	p += sizeof(*hdr);
 	while (len > 0) {
-		struct sadb_ext *ehdr = (struct sadb_ext *) p;
+		const struct sadb_ext *ehdr = (const struct sadb_ext *) p;
 		uint16_t ext_type;
 		int ext_len;
 
@@ -514,7 +515,7 @@ static int parse_exthdrs(struct sk_buff *skb, struct sadb_msg *hdr, void **ext_h
 				if (verify_sec_ctx_len(p))
 					return -EINVAL;
 			}
-			ext_hdrs[ext_type-1] = p;
+			ext_hdrs[ext_type-1] = (void *) p;
 		}
 		p   += ext_len;
 		len -= ext_len;
@@ -606,21 +607,21 @@ int pfkey_sockaddr_extract(const struct sockaddr *sa, xfrm_address_t *xaddr)
 }
 
 static
-int pfkey_sadb_addr2xfrm_addr(struct sadb_address *addr, xfrm_address_t *xaddr)
+int pfkey_sadb_addr2xfrm_addr(const struct sadb_address *addr, xfrm_address_t *xaddr)
 {
 	return pfkey_sockaddr_extract((struct sockaddr *)(addr + 1),
 				      xaddr);
 }
 
-static struct  xfrm_state *pfkey_xfrm_state_lookup(struct net *net, struct sadb_msg *hdr, void **ext_hdrs)
+static struct  xfrm_state *pfkey_xfrm_state_lookup(struct net *net, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
-	struct sadb_sa *sa;
-	struct sadb_address *addr;
+	const struct sadb_sa *sa;
+	const struct sadb_address *addr;
 	uint16_t proto;
 	unsigned short family;
 	xfrm_address_t *xaddr;
 
-	sa = (struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
+	sa = (const struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
 	if (sa == NULL)
 		return NULL;
 
@@ -629,18 +630,18 @@ static struct  xfrm_state *pfkey_xfrm_state_lookup(struct net *net, struct sadb_
 		return NULL;
 
 	/* sadb_address_len should be checked by caller */
-	addr = (struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1];
+	addr = (const struct sadb_address *) ext_hdrs[SADB_EXT_ADDRESS_DST-1];
 	if (addr == NULL)
 		return NULL;
 
-	family = ((struct sockaddr *)(addr + 1))->sa_family;
+	family = ((const struct sockaddr *)(addr + 1))->sa_family;
 	switch (family) {
 	case AF_INET:
-		xaddr = (xfrm_address_t *)&((struct sockaddr_in *)(addr + 1))->sin_addr;
+		xaddr = (xfrm_address_t *)&((const struct sockaddr_in *)(addr + 1))->sin_addr;
 		break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 	case AF_INET6:
-		xaddr = (xfrm_address_t *)&((struct sockaddr_in6 *)(addr + 1))->sin6_addr;
+		xaddr = (xfrm_address_t *)&((const struct sockaddr_in6 *)(addr + 1))->sin6_addr;
 		break;
 #endif
 	default:
@@ -690,9 +691,9 @@ static inline int pfkey_mode_to_xfrm(int mode)
 	}
 }
 
-static unsigned int pfkey_sockaddr_fill(xfrm_address_t *xaddr, __be16 port,
-				       struct sockaddr *sa,
-				       unsigned short family)
+static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port,
+					struct sockaddr *sa,
+					unsigned short family)
 {
 	switch (family) {
 	case AF_INET:
@@ -720,7 +721,7 @@ static unsigned int pfkey_sockaddr_fill(xfrm_address_t *xaddr, __be16 port,
 	return 0;
 }
 
-static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
+static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x,
 					      int add_keys, int hsc)
 {
 	struct sk_buff *skb;
@@ -1010,7 +1011,7 @@ static struct sk_buff *__pfkey_xfrm_state2msg(struct xfrm_state *x,
 }
 
 
-static inline struct sk_buff *pfkey_xfrm_state2msg(struct xfrm_state *x)
+static inline struct sk_buff *pfkey_xfrm_state2msg(const struct xfrm_state *x)
 {
 	struct sk_buff *skb;
 
@@ -1019,26 +1020,26 @@ static inline struct sk_buff *pfkey_xfrm_state2msg(struct xfrm_state *x)
 	return skb;
 }
 
-static inline struct sk_buff *pfkey_xfrm_state2msg_expire(struct xfrm_state *x,
+static inline struct sk_buff *pfkey_xfrm_state2msg_expire(const struct xfrm_state *x,
 							  int hsc)
 {
 	return __pfkey_xfrm_state2msg(x, 0, hsc);
 }
 
 static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
-						struct sadb_msg *hdr,
-						void **ext_hdrs)
+						const struct sadb_msg *hdr,
+						void * const *ext_hdrs)
 {
 	struct xfrm_state *x;
-	struct sadb_lifetime *lifetime;
-	struct sadb_sa *sa;
-	struct sadb_key *key;
-	struct sadb_x_sec_ctx *sec_ctx;
+	const struct sadb_lifetime *lifetime;
+	const struct sadb_sa *sa;
+	const struct sadb_key *key;
+	const struct sadb_x_sec_ctx *sec_ctx;
 	uint16_t proto;
 	int err;
 
 
-	sa = (struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
+	sa = (const struct sadb_sa *) ext_hdrs[SADB_EXT_SA-1];
 	if (!sa ||
 	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]))
@@ -1077,7 +1078,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 	     sa->sadb_sa_encrypt > SADB_X_CALG_MAX) ||
 	    sa->sadb_sa_encrypt > SADB_EALG_MAX)
 		return ERR_PTR(-EINVAL);
-	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
+	key = (const struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
 	if (key != NULL &&
 	    sa->sadb_sa_auth != SADB_X_AALG_NULL &&
 	    ((key->sadb_key_bits+7) / 8 == 0 ||
@@ -1104,14 +1105,14 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
 		x->props.flags |= XFRM_STATE_NOPMTUDISC;
 
-	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
+	lifetime = (const struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
 	if (lifetime != NULL) {
 		x->lft.hard_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
 		x->lft.hard_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
 		x->lft.hard_add_expires_seconds = lifetime->sadb_lifetime_addtime;
 		x->lft.hard_use_expires_seconds = lifetime->sadb_lifetime_usetime;
 	}
-	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_SOFT-1];
+	lifetime = (const struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_SOFT-1];
 	if (lifetime != NULL) {
 		x->lft.soft_packet_limit = _KEY2X(lifetime->sadb_lifetime_allocations);
 		x->lft.soft_byte_limit = _KEY2X(lifetime->sadb_lifetime_bytes);
@@ -1119,7 +1120,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 		x->lft.soft_use_expires_seconds = lifetime->sadb_lifetime_usetime;
 	}
 
-	sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
+	sec_ctx = (const struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
 	if (sec_ctx != NULL) {
 		struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
 
@@ -1133,7 +1134,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 			goto out;
 	}
 
-	key = (struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
+	key = (const struct sadb_key*) ext_hdrs[SADB_EXT_KEY_AUTH-1];
 	if (sa->sadb_sa_auth) {
 		int keysize = 0;
 		struct xfrm_algo_desc *a = xfrm_aalg_get_byid(sa->sadb_sa_auth);
@@ -1202,7 +1203,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 				  &x->id.daddr);
 
 	if (ext_hdrs[SADB_X_EXT_SA2-1]) {
-		struct sadb_x_sa2 *sa2 = (void*)ext_hdrs[SADB_X_EXT_SA2-1];
+		const struct sadb_x_sa2 *sa2 = ext_hdrs[SADB_X_EXT_SA2-1];
 		int mode = pfkey_mode_to_xfrm(sa2->sadb_x_sa2_mode);
 		if (mode < 0) {
 			err = -EINVAL;
@@ -1213,7 +1214,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 	}
 
 	if (ext_hdrs[SADB_EXT_ADDRESS_PROXY-1]) {
-		struct sadb_address *addr = ext_hdrs[SADB_EXT_ADDRESS_PROXY-1];
+		const struct sadb_address *addr = ext_hdrs[SADB_EXT_ADDRESS_PROXY-1];
 
 		/* Nobody uses this, but we try. */
 		x->sel.family = pfkey_sadb_addr2xfrm_addr(addr, &x->sel.saddr);
@@ -1224,7 +1225,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 		x->sel.family = x->props.family;
 
 	if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) {
-		struct sadb_x_nat_t_type* n_type;
+		const struct sadb_x_nat_t_type* n_type;
 		struct xfrm_encap_tmpl *natt;
 
 		x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
@@ -1236,12 +1237,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
 		natt->encap_type = n_type->sadb_x_nat_t_type_type;
 
 		if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) {
-			struct sadb_x_nat_t_port* n_port =
+			const struct sadb_x_nat_t_port *n_port =
 				ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1];
 			natt->encap_sport = n_port->sadb_x_nat_t_port_port;
 		}
 		if (ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1]) {
-			struct sadb_x_nat_t_port* n_port =
+			const struct sadb_x_nat_t_port *n_port =
 				ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1];
 			natt->encap_dport = n_port->sadb_x_nat_t_port_port;
 		}
@@ -1261,12 +1262,12 @@ out:
 	return ERR_PTR(err);
 }
 
-static int pfkey_reserved(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_reserved(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	return -EOPNOTSUPP;
 }
 
-static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	struct sk_buff *resp_skb;
@@ -1365,7 +1366,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
 	return 0;
 }
 
-static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	struct xfrm_state *x;
@@ -1429,7 +1430,7 @@ static inline int event2keytype(int event)
 }
 
 /* ADD/UPD/DEL */
-static int key_notify_sa(struct xfrm_state *x, struct km_event *c)
+static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
 {
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
@@ -1453,7 +1454,7 @@ static int key_notify_sa(struct xfrm_state *x, struct km_event *c)
 	return 0;
 }
 
-static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_add(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	struct xfrm_state *x;
@@ -1492,7 +1493,7 @@ out:
 	return err;
 }
 
-static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_delete(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	struct xfrm_state *x;
@@ -1534,7 +1535,7 @@ out:
 	return err;
 }
 
-static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	__u8 proto;
@@ -1570,7 +1571,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
 	return 0;
 }
 
-static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig,
+static struct sk_buff *compose_sadb_supported(const struct sadb_msg *orig,
 					      gfp_t allocation)
 {
 	struct sk_buff *skb;
@@ -1642,7 +1643,7 @@ out_put_algs:
 	return skb;
 }
 
-static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct pfkey_sock *pfk = pfkey_sk(sk);
 	struct sk_buff *supp_skb;
@@ -1671,7 +1672,7 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg
 	return 0;
 }
 
-static int unicast_flush_resp(struct sock *sk, struct sadb_msg *ihdr)
+static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
 {
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
@@ -1688,7 +1689,7 @@ static int unicast_flush_resp(struct sock *sk, struct sadb_msg *ihdr)
 	return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
 }
 
-static int key_notify_sa_flush(struct km_event *c)
+static int key_notify_sa_flush(const struct km_event *c)
 {
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
@@ -1710,7 +1711,7 @@ static int key_notify_sa_flush(struct km_event *c)
 	return 0;
 }
 
-static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	unsigned proto;
@@ -1784,7 +1785,7 @@ static void pfkey_dump_sa_done(struct pfkey_sock *pfk)
 	xfrm_state_walk_done(&pfk->dump.u.state);
 }
 
-static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	u8 proto;
 	struct pfkey_sock *pfk = pfkey_sk(sk);
@@ -1805,19 +1806,29 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr
 	return pfkey_do_dump(pfk);
 }
 
-static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct pfkey_sock *pfk = pfkey_sk(sk);
 	int satype = hdr->sadb_msg_satype;
+	bool reset_errno = false;
 
 	if (hdr->sadb_msg_len == (sizeof(*hdr) / sizeof(uint64_t))) {
-		/* XXX we mangle packet... */
-		hdr->sadb_msg_errno = 0;
+		reset_errno = true;
 		if (satype != 0 && satype != 1)
 			return -EINVAL;
 		pfk->promisc = satype;
 	}
-	pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
+	if (reset_errno && skb_cloned(skb))
+		skb = skb_copy(skb, GFP_KERNEL);
+	else
+		skb = skb_clone(skb, GFP_KERNEL);
+
+	if (reset_errno && skb) {
+		struct sadb_msg *new_hdr = (struct sadb_msg *) skb->data;
+		new_hdr->sadb_msg_errno = 0;
+	}
+
+	pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
 	return 0;
 }
 
@@ -1921,7 +1932,7 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
 	return 0;
 }
 
-static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp)
+static inline int pfkey_xfrm_policy2sec_ctx_size(const struct xfrm_policy *xp)
 {
   struct xfrm_sec_ctx *xfrm_ctx = xp->security;
 
@@ -1933,9 +1944,9 @@ static inline int pfkey_xfrm_policy2sec_ctx_size(struct xfrm_policy *xp)
 	return 0;
 }
 
-static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
+static int pfkey_xfrm_policy2msg_size(const struct xfrm_policy *xp)
 {
-	struct xfrm_tmpl *t;
+	const struct xfrm_tmpl *t;
 	int sockaddr_size = pfkey_sockaddr_size(xp->family);
 	int socklen = 0;
 	int i;
@@ -1955,7 +1966,7 @@ static int pfkey_xfrm_policy2msg_size(struct xfrm_policy *xp)
 		pfkey_xfrm_policy2sec_ctx_size(xp);
 }
 
-static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
+static struct sk_buff * pfkey_xfrm_policy2msg_prep(const struct xfrm_policy *xp)
 {
 	struct sk_buff *skb;
 	int size;
@@ -1969,7 +1980,7 @@ static struct sk_buff * pfkey_xfrm_policy2msg_prep(struct xfrm_policy *xp)
 	return skb;
 }
 
-static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, int dir)
+static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy *xp, int dir)
 {
 	struct sadb_msg *hdr;
 	struct sadb_address *addr;
@@ -2065,8 +2076,8 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
 	pol->sadb_x_policy_priority = xp->priority;
 
 	for (i=0; i<xp->xfrm_nr; i++) {
+		const struct xfrm_tmpl *t = xp->xfrm_vec + i;
 		struct sadb_x_ipsecrequest *rq;
-		struct xfrm_tmpl *t = xp->xfrm_vec + i;
 		int req_size;
 		int mode;
 
@@ -2123,7 +2134,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, in
 	return 0;
 }
 
-static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c)
 {
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
@@ -2152,7 +2163,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c
 
 }
 
-static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	int err = 0;
@@ -2273,7 +2284,7 @@ out:
 	return err;
 }
 
-static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	int err;
@@ -2350,7 +2361,7 @@ out:
 	return err;
 }
 
-static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir)
+static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struct sadb_msg *hdr, int dir)
 {
 	int err;
 	struct sk_buff *out_skb;
@@ -2458,7 +2469,7 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
 }
 
 static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
-			 struct sadb_msg *hdr, void **ext_hdrs)
+			 const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	int i, len, ret, err = -EINVAL;
 	u8 dir;
@@ -2549,14 +2560,14 @@ static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
 }
 #else
 static int pfkey_migrate(struct sock *sk, struct sk_buff *skb,
-			 struct sadb_msg *hdr, void **ext_hdrs)
+			 const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	return -ENOPROTOOPT;
 }
 #endif
 
 
-static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	unsigned int dir;
@@ -2644,7 +2655,7 @@ static void pfkey_dump_sp_done(struct pfkey_sock *pfk)
 	xfrm_policy_walk_done(&pfk->dump.u.policy);
 }
 
-static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct pfkey_sock *pfk = pfkey_sk(sk);
 
@@ -2660,7 +2671,7 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
 	return pfkey_do_dump(pfk);
 }
 
-static int key_notify_policy_flush(struct km_event *c)
+static int key_notify_policy_flush(const struct km_event *c)
 {
 	struct sk_buff *skb_out;
 	struct sadb_msg *hdr;
@@ -2680,7 +2691,7 @@ static int key_notify_policy_flush(struct km_event *c)
 
 }
 
-static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs)
 {
 	struct net *net = sock_net(sk);
 	struct km_event c;
@@ -2709,7 +2720,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
 }
 
 typedef int (*pfkey_handler)(struct sock *sk, struct sk_buff *skb,
-			     struct sadb_msg *hdr, void **ext_hdrs);
+			     const struct sadb_msg *hdr, void * const *ext_hdrs);
 static pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
 	[SADB_RESERVED]		= pfkey_reserved,
 	[SADB_GETSPI]		= pfkey_getspi,
@@ -2736,7 +2747,7 @@ static pfkey_handler pfkey_funcs[SADB_MAX + 1] = {
 	[SADB_X_MIGRATE]	= pfkey_migrate,
 };
 
-static int pfkey_process(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr)
+static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr)
 {
 	void *ext_hdrs[SADB_EXT_MAX];
 	int err;
@@ -2781,7 +2792,8 @@ static struct sadb_msg *pfkey_get_base_msg(struct sk_buff *skb, int *errp)
 	return hdr;
 }
 
-static inline int aalg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
+static inline int aalg_tmpl_set(const struct xfrm_tmpl *t,
+				const struct xfrm_algo_desc *d)
 {
 	unsigned int id = d->desc.sadb_alg_id;
 
@@ -2791,7 +2803,8 @@ static inline int aalg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
 	return (t->aalgos >> id) & 1;
 }
 
-static inline int ealg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
+static inline int ealg_tmpl_set(const struct xfrm_tmpl *t,
+				const struct xfrm_algo_desc *d)
 {
 	unsigned int id = d->desc.sadb_alg_id;
 
@@ -2801,12 +2814,12 @@ static inline int ealg_tmpl_set(struct xfrm_tmpl *t, struct xfrm_algo_desc *d)
 	return (t->ealgos >> id) & 1;
 }
 
-static int count_ah_combs(struct xfrm_tmpl *t)
+static int count_ah_combs(const struct xfrm_tmpl *t)
 {
 	int i, sz = 0;
 
 	for (i = 0; ; i++) {
-		struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
+		const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
 		if (!aalg)
 			break;
 		if (aalg_tmpl_set(t, aalg) && aalg->available)
@@ -2815,12 +2828,12 @@ static int count_ah_combs(struct xfrm_tmpl *t)
 	return sz + sizeof(struct sadb_prop);
 }
 
-static int count_esp_combs(struct xfrm_tmpl *t)
+static int count_esp_combs(const struct xfrm_tmpl *t)
 {
 	int i, k, sz = 0;
 
 	for (i = 0; ; i++) {
-		struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
+		const struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
 		if (!ealg)
 			break;
 
@@ -2828,7 +2841,7 @@ static int count_esp_combs(struct xfrm_tmpl *t)
 			continue;
 
 		for (k = 1; ; k++) {
-			struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
+			const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
 			if (!aalg)
 				break;
 
@@ -2839,7 +2852,7 @@ static int count_esp_combs(struct xfrm_tmpl *t)
 	return sz + sizeof(struct sadb_prop);
 }
 
-static void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
+static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
 {
 	struct sadb_prop *p;
 	int i;
@@ -2851,7 +2864,7 @@ static void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
 	memset(p->sadb_prop_reserved, 0, sizeof(p->sadb_prop_reserved));
 
 	for (i = 0; ; i++) {
-		struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
+		const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(i);
 		if (!aalg)
 			break;
 
@@ -2871,7 +2884,7 @@ static void dump_ah_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
 	}
 }
 
-static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
+static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
 {
 	struct sadb_prop *p;
 	int i, k;
@@ -2883,7 +2896,7 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
 	memset(p->sadb_prop_reserved, 0, sizeof(p->sadb_prop_reserved));
 
 	for (i=0; ; i++) {
-		struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
+		const struct xfrm_algo_desc *ealg = xfrm_ealg_get_byidx(i);
 		if (!ealg)
 			break;
 
@@ -2892,7 +2905,7 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
 
 		for (k = 1; ; k++) {
 			struct sadb_comb *c;
-			struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
+			const struct xfrm_algo_desc *aalg = xfrm_aalg_get_byidx(k);
 			if (!aalg)
 				break;
 			if (!(aalg_tmpl_set(t, aalg) && aalg->available))
@@ -2914,12 +2927,12 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
 	}
 }
 
-static int key_notify_policy_expire(struct xfrm_policy *xp, struct km_event *c)
+static int key_notify_policy_expire(struct xfrm_policy *xp, const struct km_event *c)
 {
 	return 0;
 }
 
-static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c)
+static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
 {
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
@@ -2949,7 +2962,7 @@ static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c)
 	return 0;
 }
 
-static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
+static int pfkey_send_notify(struct xfrm_state *x, const struct km_event *c)
 {
 	struct net *net = x ? xs_net(x) : c->net;
 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
@@ -2976,7 +2989,7 @@ static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
 	return 0;
 }
 
-static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
 {
 	if (xp && xp->type != XFRM_POLICY_TYPE_MAIN)
 		return 0;
@@ -3318,7 +3331,7 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
 
 #ifdef CONFIG_NET_KEY_MIGRATE
 static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
-			    struct xfrm_selector *sel)
+			    const struct xfrm_selector *sel)
 {
 	struct sadb_address *addr;
 	addr = (struct sadb_address *)skb_put(skb, sizeof(struct sadb_address) + sasize);
@@ -3348,7 +3361,7 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
 }
 
 
-static int set_sadb_kmaddress(struct sk_buff *skb, struct xfrm_kmaddress *k)
+static int set_sadb_kmaddress(struct sk_buff *skb, const struct xfrm_kmaddress *k)
 {
 	struct sadb_x_kmaddress *kma;
 	u8 *sa;
@@ -3376,7 +3389,7 @@ static int set_sadb_kmaddress(struct sk_buff *skb, struct xfrm_kmaddress *k)
 static int set_ipsecrequest(struct sk_buff *skb,
 			    uint8_t proto, uint8_t mode, int level,
 			    uint32_t reqid, uint8_t family,
-			    xfrm_address_t *src, xfrm_address_t *dst)
+			    const xfrm_address_t *src, const xfrm_address_t *dst)
 {
 	struct sadb_x_ipsecrequest *rq;
 	u8 *sa;
@@ -3404,9 +3417,9 @@ static int set_ipsecrequest(struct sk_buff *skb,
 #endif
 
 #ifdef CONFIG_NET_KEY_MIGRATE
-static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
-			      struct xfrm_migrate *m, int num_bundles,
-			      struct xfrm_kmaddress *k)
+static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+			      const struct xfrm_migrate *m, int num_bundles,
+			      const struct xfrm_kmaddress *k)
 {
 	int i;
 	int sasize_sel;
@@ -3415,7 +3428,7 @@ static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
 	struct sk_buff *skb;
 	struct sadb_msg *hdr;
 	struct sadb_x_policy *pol;
-	struct xfrm_migrate *mp;
+	const struct xfrm_migrate *mp;
 
 	if (type != XFRM_POLICY_TYPE_MAIN)
 		return 0;
@@ -3513,9 +3526,9 @@ err:
 	return -EINVAL;
 }
 #else
-static int pfkey_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
-			      struct xfrm_migrate *m, int num_bundles,
-			      struct xfrm_kmaddress *k)
+static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+			      const struct xfrm_migrate *m, int num_bundles,
+			      const struct xfrm_kmaddress *k)
 {
 	return -ENOPROTOOPT;
 }
@@ -3655,6 +3668,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v)
 }
 
 static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
+	__acquires(rcu)
 {
 	struct net *net = seq_file_net(f);
 	struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
@@ -3672,6 +3686,7 @@ static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
 }
 
 static void pfkey_seq_stop(struct seq_file *f, void *v)
+	__releases(rcu)
 {
 	rcu_read_unlock();
 }
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 8d9ce0a..a8193f5 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -283,7 +283,7 @@ static __net_init int l2tp_eth_init_net(struct net *net)
 	return 0;
 }
 
-static __net_initdata struct pernet_operations l2tp_eth_net_ops = {
+static struct pernet_operations l2tp_eth_net_ops = {
 	.init = l2tp_eth_init_net,
 	.id   = &l2tp_eth_net_id,
 	.size = sizeof(struct l2tp_eth_net),
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 110efb7..fce9bd3 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -320,11 +320,12 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
 	if (ipv4_is_multicast(lsa->l2tp_addr.s_addr))
 		goto out;
 
-	rc = ip_route_connect(&rt, lsa->l2tp_addr.s_addr, saddr,
+	rt = ip_route_connect(lsa->l2tp_addr.s_addr, saddr,
 			      RT_CONN_FLAGS(sk), oif,
 			      IPPROTO_L2TP,
-			      0, 0, sk, 1);
-	if (rc) {
+			      0, 0, sk, true);
+	if (IS_ERR(rt)) {
+		rc = PTR_ERR(rt);
 		if (rc == -ENETUNREACH)
 			IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES);
 		goto out;
@@ -474,24 +475,17 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
 		if (opt && opt->srr)
 			daddr = opt->faddr;
 
-		{
-			struct flowi fl = { .oif = sk->sk_bound_dev_if,
-					    .fl4_dst = daddr,
-					    .fl4_src = inet->inet_saddr,
-					    .fl4_tos = RT_CONN_FLAGS(sk),
-					    .proto = sk->sk_protocol,
-					    .flags = inet_sk_flowi_flags(sk),
-					    .fl_ip_sport = inet->inet_sport,
-					    .fl_ip_dport = inet->inet_dport };
-
-			/* If this fails, retransmit mechanism of transport layer will
-			 * keep trying until route appears or the connection times
-			 * itself out.
-			 */
-			security_sk_classify_flow(sk, &fl);
-			if (ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0))
-				goto no_route;
-		}
+		/* If this fails, retransmit mechanism of transport layer will
+		 * keep trying until route appears or the connection times
+		 * itself out.
+		 */
+		rt = ip_route_output_ports(sock_net(sk), sk,
+					   daddr, inet->inet_saddr,
+					   inet->inet_dport, inet->inet_sport,
+					   sk->sk_protocol, RT_CONN_FLAGS(sk),
+					   sk->sk_bound_dev_if);
+		if (IS_ERR(rt))
+			goto no_route;
 		sk_setup_caps(sk, &rt->dst);
 	}
 	skb_dst_set(skb, dst_clone(&rt->dst));
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index f996874..058f1e9 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -181,25 +181,26 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
 	 * LLC functionality
 	 */
 	rcv = rcu_dereference(sap->rcv_func);
-	if (rcv) {
-		struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
-		if (cskb)
-			rcv(cskb, dev, pt, orig_dev);
-	}
 	dest = llc_pdu_type(skb);
-	if (unlikely(!dest || !llc_type_handlers[dest - 1]))
-		goto drop_put;
-	llc_type_handlers[dest - 1](sap, skb);
-out_put:
+	if (unlikely(!dest || !llc_type_handlers[dest - 1])) {
+		if (rcv)
+			rcv(skb, dev, pt, orig_dev);
+		else
+			kfree_skb(skb);
+	} else {
+		if (rcv) {
+			struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
+			if (cskb)
+				rcv(cskb, dev, pt, orig_dev);
+		}
+		llc_type_handlers[dest - 1](sap, skb);
+	}
 	llc_sap_put(sap);
 out:
 	return 0;
 drop:
 	kfree_skb(skb);
 	goto out;
-drop_put:
-	kfree_skb(skb);
-	goto out_put;
 handle_station:
 	if (!llc_station_handler)
 		goto drop;
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index c766056..513f85c 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -17,7 +17,7 @@ comment "CFG80211 needs to be enabled for MAC80211"
 if MAC80211 != n
 
 config MAC80211_HAS_RC
-	def_bool n
+	bool
 
 config MAC80211_RC_PID
 	bool "PID controller based rate control algorithm" if EXPERT
@@ -78,7 +78,7 @@ config MAC80211_RC_DEFAULT
 endif
 
 comment "Some wireless drivers require a rate control algorithm"
-	depends on MAC80211_HAS_RC=n
+	depends on MAC80211 && MAC80211_HAS_RC=n
 
 config MAC80211_MESH
 	bool "Enable mac80211 mesh networking (pre-802.11s) support"
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 227ca82..0c9d0c0 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -76,7 +76,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
 	if (drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_STOP,
-			     &sta->sta, tid, NULL))
+			     &sta->sta, tid, NULL, 0))
 		printk(KERN_DEBUG "HW problem - can not stop rx "
 				"aggregation for tid %d\n", tid);
 
@@ -232,6 +232,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 	if (buf_size == 0)
 		buf_size = IEEE80211_MAX_AMPDU_BUF;
 
+	/* make sure the size doesn't exceed the maximum supported by the hw */
+	if (buf_size > local->hw.max_rx_aggregation_subframes)
+		buf_size = local->hw.max_rx_aggregation_subframes;
 
 	/* examine state machine */
 	mutex_lock(&sta->ampdu_mlme.mtx);
@@ -287,7 +290,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
 	}
 
 	ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
-			       &sta->sta, tid, &start_seq_num);
+			       &sta->sta, tid, &start_seq_num, 0);
 #ifdef CONFIG_MAC80211_HT_DEBUG
 	printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 9cc472c..63d852c 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -190,7 +190,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 
 	ret = drv_ampdu_action(local, sta->sdata,
 			       IEEE80211_AMPDU_TX_STOP,
-			       &sta->sta, tid, NULL);
+			       &sta->sta, tid, NULL, 0);
 
 	/* HW shall not deny going back to legacy */
 	if (WARN_ON(ret)) {
@@ -311,7 +311,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
 	start_seq_num = sta->tid_seq[tid] >> 4;
 
 	ret = drv_ampdu_action(local, sdata, IEEE80211_AMPDU_TX_START,
-			       &sta->sta, tid, &start_seq_num);
+			       &sta->sta, tid, &start_seq_num, 0);
 	if (ret) {
 #ifdef CONFIG_MAC80211_HT_DEBUG
 		printk(KERN_DEBUG "BA request denied - HW unavailable for"
@@ -342,7 +342,8 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
 	/* send AddBA request */
 	ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
 				     tid_tx->dialog_token, start_seq_num,
-				     0x40, tid_tx->timeout);
+				     local->hw.max_tx_aggregation_subframes,
+				     tid_tx->timeout);
 }
 
 int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
@@ -487,7 +488,8 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
 
 	drv_ampdu_action(local, sta->sdata,
 			 IEEE80211_AMPDU_TX_OPERATIONAL,
-			 &sta->sta, tid, NULL);
+			 &sta->sta, tid, NULL,
+			 sta->ampdu_mlme.tid_tx[tid]->buf_size);
 
 	/*
 	 * synchronize with TX path, while splicing the TX path
@@ -742,9 +744,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 {
 	struct tid_ampdu_tx *tid_tx;
 	u16 capab, tid;
+	u8 buf_size;
 
 	capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
 	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
+	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;
 
 	mutex_lock(&sta->ampdu_mlme.mtx);
 
@@ -767,12 +771,23 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
 
 	if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
 			== WLAN_STATUS_SUCCESS) {
+		/*
+		 * IEEE 802.11-2007 7.3.1.14:
+		 * In an ADDBA Response frame, when the Status Code field
+		 * is set to 0, the Buffer Size subfield is set to a value
+		 * of at least 1.
+		 */
+		if (!buf_size)
+			goto out;
+
 		if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED,
 				     &tid_tx->state)) {
 			/* ignore duplicate response */
 			goto out;
 		}
 
+		tid_tx->buf_size = buf_size;
+
 		if (test_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))
 			ieee80211_agg_tx_operational(local, sta, tid);
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9cd73b1..3342135 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -316,6 +316,17 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
 	return 0;
 }
 
+static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
+{
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		rate->legacy = sband->bitrates[idx].bitrate;
+	} else
+		rate->mcs = idx;
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -330,6 +341,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 			STATION_INFO_TX_RETRIES |
 			STATION_INFO_TX_FAILED |
 			STATION_INFO_TX_BITRATE |
+			STATION_INFO_RX_BITRATE |
 			STATION_INFO_RX_DROP_MISC;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
@@ -355,15 +367,16 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
 	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
 		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+	rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx);
 
-	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
-		struct ieee80211_supported_band *sband;
-		sband = sta->local->hw.wiphy->bands[
-				sta->local->hw.conf.channel->band];
-		sinfo->txrate.legacy =
-			sband->bitrates[sta->last_tx_rate.idx].bitrate;
-	} else
-		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+	sinfo->rxrate.flags = 0;
+	if (sta->last_rx_rate_flag & RX_FLAG_HT)
+		sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
+		sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
+		sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+	rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx);
 
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
@@ -821,6 +834,10 @@ static int ieee80211_change_station(struct wiphy *wiphy,
 
 	rcu_read_unlock();
 
+	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+	    params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))
+		ieee80211_recalc_ps(local, -1);
+
 	return 0;
 }
 
@@ -1215,6 +1232,9 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
 {
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_sub_if_data *sdata = NULL;
+	struct ieee80211_channel *old_oper;
+	enum nl80211_channel_type old_oper_type;
+	enum nl80211_channel_type old_vif_oper_type= NL80211_CHAN_NO_HT;
 
 	if (netdev)
 		sdata = IEEE80211_DEV_TO_SUB_IF(netdev);
@@ -1232,13 +1252,23 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
 		break;
 	}
 
-	local->oper_channel = chan;
+	if (sdata)
+		old_vif_oper_type = sdata->vif.bss_conf.channel_type;
+	old_oper_type = local->_oper_channel_type;
 
 	if (!ieee80211_set_channel_type(local, sdata, channel_type))
 		return -EBUSY;
 
-	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
-	if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR)
+	old_oper = local->oper_channel;
+	local->oper_channel = chan;
+
+	/* Update driver if changes were actually made. */
+	if ((old_oper != local->oper_channel) ||
+	    (old_oper_type != local->_oper_channel_type))
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+	if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) &&
+	    old_vif_oper_type != sdata->vif.bss_conf.channel_type)
 		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
 
 	return 0;
@@ -1274,8 +1304,11 @@ static int ieee80211_scan(struct wiphy *wiphy,
 	case NL80211_IFTYPE_P2P_GO:
 		if (sdata->local->ops->hw_scan)
 			break;
-		/* FIXME: implement NoA while scanning in software */
-		return -EOPNOTSUPP;
+		/*
+		 * FIXME: implement NoA while scanning in software,
+		 * for now fall through to allow scanning only when
+		 * beaconing hasn't been configured yet
+		 */
 	case NL80211_IFTYPE_AP:
 		if (sdata->u.ap.beacon)
 			return -EOPNOTSUPP;
@@ -1784,6 +1817,33 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 
 	*cookie = (unsigned long) skb;
 
+	if (is_offchan && local->ops->offchannel_tx) {
+		int ret;
+
+		IEEE80211_SKB_CB(skb)->band = chan->band;
+
+		mutex_lock(&local->mtx);
+
+		if (local->hw_offchan_tx_cookie) {
+			mutex_unlock(&local->mtx);
+			return -EBUSY;
+		}
+
+		/* TODO: bitrate control, TX processing? */
+		ret = drv_offchannel_tx(local, skb, chan, channel_type, wait);
+
+		if (ret == 0)
+			local->hw_offchan_tx_cookie = *cookie;
+		mutex_unlock(&local->mtx);
+
+		/*
+		 * Allow driver to return 1 to indicate it wants to have the
+		 * frame transmitted with a remain_on_channel + regular TX.
+		 */
+		if (ret != 1)
+			return ret;
+	}
+
 	if (is_offchan && local->ops->remain_on_channel) {
 		unsigned int duration;
 		int ret;
@@ -1847,6 +1907,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 
 	wk->type = IEEE80211_WORK_OFFCHANNEL_TX;
 	wk->chan = chan;
+	wk->chan_type = channel_type;
 	wk->sdata = sdata;
 	wk->done = ieee80211_offchan_tx_done;
 	wk->offchan_tx.frame = skb;
@@ -1869,6 +1930,18 @@ static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
 
 	mutex_lock(&local->mtx);
 
+	if (local->ops->offchannel_tx_cancel_wait &&
+	    local->hw_offchan_tx_cookie == cookie) {
+		ret = drv_offchannel_tx_cancel_wait(local);
+
+		if (!ret)
+			local->hw_offchan_tx_cookie = 0;
+
+		mutex_unlock(&local->mtx);
+
+		return ret;
+	}
+
 	if (local->ops->cancel_remain_on_channel) {
 		cookie ^= 2;
 		ret = ieee80211_cancel_remain_on_channel_hw(local, cookie);
@@ -1939,6 +2012,21 @@ static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
 	return drv_get_antenna(local, tx_ant, rx_ant);
 }
 
+static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	return drv_set_ringparam(local, tx, rx);
+}
+
+static void ieee80211_get_ringparam(struct wiphy *wiphy,
+				    u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+	struct ieee80211_local *local = wiphy_priv(wiphy);
+
+	drv_get_ringparam(local, tx, tx_max, rx, rx_max);
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -1996,4 +2084,6 @@ struct cfg80211_ops mac80211_config_ops = {
 	.mgmt_frame_register = ieee80211_mgmt_frame_register,
 	.set_antenna = ieee80211_set_antenna,
 	.get_antenna = ieee80211_get_antenna,
+	.set_ringparam = ieee80211_set_ringparam,
+	.get_ringparam = ieee80211_get_ringparam,
 };
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5b24740..889c3e9 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -77,6 +77,9 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local,
 		switch (tmp->vif.bss_conf.channel_type) {
 		case NL80211_CHAN_NO_HT:
 		case NL80211_CHAN_HT20:
+			if (superchan > tmp->vif.bss_conf.channel_type)
+				break;
+
 			superchan = tmp->vif.bss_conf.channel_type;
 			break;
 		case NL80211_CHAN_HT40PLUS:
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 1f02e59..51f0d78 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -60,6 +60,10 @@ static const struct file_operations name## _ops = {			\
 	debugfs_create_file(#name, mode, phyd, local, &name## _ops);
 
 
+DEBUGFS_READONLY_FILE(user_power, "%d",
+		      local->user_power_level);
+DEBUGFS_READONLY_FILE(power, "%d",
+		      local->hw.conf.power_level);
 DEBUGFS_READONLY_FILE(frequency, "%d",
 		      local->hw.conf.channel->center_freq);
 DEBUGFS_READONLY_FILE(total_ps_buffered, "%d",
@@ -391,6 +395,8 @@ void debugfs_hw_add(struct ieee80211_local *local)
 	DEBUGFS_ADD(uapsd_queues);
 	DEBUGFS_ADD(uapsd_max_sp_len);
 	DEBUGFS_ADD(channel_type);
+	DEBUGFS_ADD(user_power);
+	DEBUGFS_ADD(power);
 
 	statsd = debugfs_create_dir("statistics", phyd);
 
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 2dabdf7..dacace6 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -36,7 +36,7 @@ static ssize_t ieee80211_if_read(
 		ret = (*format)(sdata, buf, sizeof(buf));
 	read_unlock(&dev_base_lock);
 
-	if (ret != -EINVAL)
+	if (ret >= 0)
 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
 
 	return ret;
@@ -81,6 +81,8 @@ static ssize_t ieee80211_if_fmt_##name(					\
 		IEEE80211_IF_FMT(name, field, "%d\n")
 #define IEEE80211_IF_FMT_HEX(name, field)				\
 		IEEE80211_IF_FMT(name, field, "%#x\n")
+#define IEEE80211_IF_FMT_LHEX(name, field)				\
+		IEEE80211_IF_FMT(name, field, "%#lx\n")
 #define IEEE80211_IF_FMT_SIZE(name, field)				\
 		IEEE80211_IF_FMT(name, field, "%zd\n")
 
@@ -145,6 +147,9 @@ IEEE80211_IF_FILE(rc_rateidx_mask_2ghz, rc_rateidx_mask[IEEE80211_BAND_2GHZ],
 		  HEX);
 IEEE80211_IF_FILE(rc_rateidx_mask_5ghz, rc_rateidx_mask[IEEE80211_BAND_5GHZ],
 		  HEX);
+IEEE80211_IF_FILE(flags, flags, HEX);
+IEEE80211_IF_FILE(state, state, LHEX);
+IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC);
 
 /* STA attributes */
 IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
@@ -216,6 +221,104 @@ static ssize_t ieee80211_if_parse_smps(struct ieee80211_sub_if_data *sdata,
 
 __IEEE80211_IF_FILE_W(smps);
 
+static ssize_t ieee80211_if_fmt_tkip_mic_test(
+	const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
+{
+	return -EOPNOTSUPP;
+}
+
+static int hwaddr_aton(const char *txt, u8 *addr)
+{
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		int a, b;
+
+		a = hex_to_bin(*txt++);
+		if (a < 0)
+			return -1;
+		b = hex_to_bin(*txt++);
+		if (b < 0)
+			return -1;
+		*addr++ = (a << 4) | b;
+		if (i < 5 && *txt++ != ':')
+			return -1;
+	}
+
+	return 0;
+}
+
+static ssize_t ieee80211_if_parse_tkip_mic_test(
+	struct ieee80211_sub_if_data *sdata, const char *buf, int buflen)
+{
+	struct ieee80211_local *local = sdata->local;
+	u8 addr[ETH_ALEN];
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+	__le16 fc;
+
+	/*
+	 * Assume colon-delimited MAC address with possible white space
+	 * following.
+	 */
+	if (buflen < 3 * ETH_ALEN - 1)
+		return -EINVAL;
+	if (hwaddr_aton(buf, addr) < 0)
+		return -EINVAL;
+
+	if (!ieee80211_sdata_running(sdata))
+		return -ENOTCONN;
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24 + 100);
+	if (!skb)
+		return -ENOMEM;
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	hdr = (struct ieee80211_hdr *) skb_put(skb, 24);
+	memset(hdr, 0, 24);
+	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
+
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_AP:
+		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
+		/* DA BSSID SA */
+		memcpy(hdr->addr1, addr, ETH_ALEN);
+		memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
+		memcpy(hdr->addr3, sdata->vif.addr, ETH_ALEN);
+		break;
+	case NL80211_IFTYPE_STATION:
+		fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
+		/* BSSID SA DA */
+		if (sdata->vif.bss_conf.bssid == NULL) {
+			dev_kfree_skb(skb);
+			return -ENOTCONN;
+		}
+		memcpy(hdr->addr1, sdata->vif.bss_conf.bssid, ETH_ALEN);
+		memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
+		memcpy(hdr->addr3, addr, ETH_ALEN);
+		break;
+	default:
+		dev_kfree_skb(skb);
+		return -EOPNOTSUPP;
+	}
+	hdr->frame_control = fc;
+
+	/*
+	 * Add some length to the test frame to make it look bit more valid.
+	 * The exact contents does not matter since the recipient is required
+	 * to drop this because of the Michael MIC failure.
+	 */
+	memset(skb_put(skb, 50), 0, 50);
+
+	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_TKIP_MIC_FAILURE;
+
+	ieee80211_tx_skb(sdata, skb);
+
+	return buflen;
+}
+
+__IEEE80211_IF_FILE_W(tkip_mic_test);
+
 /* AP attributes */
 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
@@ -283,6 +386,9 @@ IEEE80211_IF_FILE(dot11MeshHWMPRootMode,
 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 {
 	DEBUGFS_ADD(drop_unencrypted);
+	DEBUGFS_ADD(flags);
+	DEBUGFS_ADD(state);
+	DEBUGFS_ADD(channel_type);
 	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
 	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 
@@ -291,22 +397,30 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 	DEBUGFS_ADD(last_beacon);
 	DEBUGFS_ADD(ave_beacon);
 	DEBUGFS_ADD_MODE(smps, 0600);
+	DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
 }
 
 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 {
 	DEBUGFS_ADD(drop_unencrypted);
+	DEBUGFS_ADD(flags);
+	DEBUGFS_ADD(state);
+	DEBUGFS_ADD(channel_type);
 	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
 	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 
 	DEBUGFS_ADD(num_sta_ps);
 	DEBUGFS_ADD(dtim_count);
 	DEBUGFS_ADD(num_buffered_multicast);
+	DEBUGFS_ADD_MODE(tkip_mic_test, 0200);
 }
 
 static void add_wds_files(struct ieee80211_sub_if_data *sdata)
 {
 	DEBUGFS_ADD(drop_unencrypted);
+	DEBUGFS_ADD(flags);
+	DEBUGFS_ADD(state);
+	DEBUGFS_ADD(channel_type);
 	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
 	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 
@@ -316,12 +430,18 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
 {
 	DEBUGFS_ADD(drop_unencrypted);
+	DEBUGFS_ADD(flags);
+	DEBUGFS_ADD(state);
+	DEBUGFS_ADD(channel_type);
 	DEBUGFS_ADD(rc_rateidx_mask_2ghz);
 	DEBUGFS_ADD(rc_rateidx_mask_5ghz);
 }
 
 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
 {
+	DEBUGFS_ADD(flags);
+	DEBUGFS_ADD(state);
+	DEBUGFS_ADD(channel_type);
 }
 
 #ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 98d5899..9c0d62b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -5,9 +5,9 @@
 #include "ieee80211_i.h"
 #include "driver-trace.h"
 
-static inline int drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
+static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb)
 {
-	return local->ops->tx(&local->hw, skb);
+	local->ops->tx(&local->hw, skb);
 }
 
 static inline int drv_start(struct ieee80211_local *local)
@@ -382,17 +382,17 @@ static inline int drv_ampdu_action(struct ieee80211_local *local,
 				   struct ieee80211_sub_if_data *sdata,
 				   enum ieee80211_ampdu_mlme_action action,
 				   struct ieee80211_sta *sta, u16 tid,
-				   u16 *ssn)
+				   u16 *ssn, u8 buf_size)
 {
 	int ret = -EOPNOTSUPP;
 
 	might_sleep();
 
-	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn);
+	trace_drv_ampdu_action(local, sdata, action, sta, tid, ssn, buf_size);
 
 	if (local->ops->ampdu_action)
 		ret = local->ops->ampdu_action(&local->hw, &sdata->vif, action,
-					       sta, tid, ssn);
+					       sta, tid, ssn, buf_size);
 
 	trace_drv_return_int(local, ret);
 
@@ -495,4 +495,61 @@ static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local)
 	return ret;
 }
 
+static inline int drv_offchannel_tx(struct ieee80211_local *local,
+				    struct sk_buff *skb,
+				    struct ieee80211_channel *chan,
+				    enum nl80211_channel_type channel_type,
+				    unsigned int wait)
+{
+	int ret;
+
+	might_sleep();
+
+	trace_drv_offchannel_tx(local, skb, chan, channel_type, wait);
+	ret = local->ops->offchannel_tx(&local->hw, skb, chan,
+					channel_type, wait);
+	trace_drv_return_int(local, ret);
+
+	return ret;
+}
+
+static inline int drv_offchannel_tx_cancel_wait(struct ieee80211_local *local)
+{
+	int ret;
+
+	might_sleep();
+
+	trace_drv_offchannel_tx_cancel_wait(local);
+	ret = local->ops->offchannel_tx_cancel_wait(&local->hw);
+	trace_drv_return_int(local, ret);
+
+	return ret;
+}
+
+static inline int drv_set_ringparam(struct ieee80211_local *local,
+				    u32 tx, u32 rx)
+{
+	int ret = -ENOTSUPP;
+
+	might_sleep();
+
+	trace_drv_set_ringparam(local, tx, rx);
+	if (local->ops->set_ringparam)
+		ret = local->ops->set_ringparam(&local->hw, tx, rx);
+	trace_drv_return_int(local, ret);
+
+	return ret;
+}
+
+static inline void drv_get_ringparam(struct ieee80211_local *local,
+				     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+	might_sleep();
+
+	trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max);
+	if (local->ops->get_ringparam)
+		local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max);
+	trace_drv_return_void(local);
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 49c8421..45aab80 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -9,6 +9,11 @@
 #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
 
 #undef TRACE_SYSTEM
@@ -38,7 +43,7 @@ static inline void trace_ ## name(proto) {}
  * Tracing for driver callbacks.
  */
 
-TRACE_EVENT(drv_return_void,
+DECLARE_EVENT_CLASS(local_only_evt,
 	TP_PROTO(struct ieee80211_local *local),
 	TP_ARGS(local),
 	TP_STRUCT__entry(
@@ -50,6 +55,11 @@ TRACE_EVENT(drv_return_void,
 	TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG)
 );
 
+DEFINE_EVENT(local_only_evt, drv_return_void,
+	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
+);
+
 TRACE_EVENT(drv_return_int,
 	TP_PROTO(struct ieee80211_local *local, int ret),
 	TP_ARGS(local, ret),
@@ -78,40 +88,14 @@ TRACE_EVENT(drv_return_u64,
 	TP_printk(LOCAL_PR_FMT " - %llu", LOCAL_PR_ARG, __entry->ret)
 );
 
-TRACE_EVENT(drv_start,
+DEFINE_EVENT(local_only_evt, drv_start,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
-TRACE_EVENT(drv_stop,
+DEFINE_EVENT(local_only_evt, drv_stop,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
 TRACE_EVENT(drv_add_interface,
@@ -439,40 +423,14 @@ TRACE_EVENT(drv_hw_scan,
 	)
 );
 
-TRACE_EVENT(drv_sw_scan_start,
+DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
-TRACE_EVENT(drv_sw_scan_complete,
+DEFINE_EVENT(local_only_evt, drv_sw_scan_complete,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
 TRACE_EVENT(drv_get_stats,
@@ -702,23 +660,9 @@ TRACE_EVENT(drv_conf_tx,
 	)
 );
 
-TRACE_EVENT(drv_get_tsf,
+DEFINE_EVENT(local_only_evt, drv_get_tsf,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT,
-		LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
 TRACE_EVENT(drv_set_tsf,
@@ -742,41 +686,14 @@ TRACE_EVENT(drv_set_tsf,
 	)
 );
 
-TRACE_EVENT(drv_reset_tsf,
+DEFINE_EVENT(local_only_evt, drv_reset_tsf,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
-TRACE_EVENT(drv_tx_last_beacon,
+DEFINE_EVENT(local_only_evt, drv_tx_last_beacon,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT,
-		LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
 TRACE_EVENT(drv_ampdu_action,
@@ -784,9 +701,9 @@ TRACE_EVENT(drv_ampdu_action,
 		 struct ieee80211_sub_if_data *sdata,
 		 enum ieee80211_ampdu_mlme_action action,
 		 struct ieee80211_sta *sta, u16 tid,
-		 u16 *ssn),
+		 u16 *ssn, u8 buf_size),
 
-	TP_ARGS(local, sdata, action, sta, tid, ssn),
+	TP_ARGS(local, sdata, action, sta, tid, ssn, buf_size),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
@@ -794,6 +711,7 @@ TRACE_EVENT(drv_ampdu_action,
 		__field(u32, action)
 		__field(u16, tid)
 		__field(u16, ssn)
+		__field(u8, buf_size)
 		VIF_ENTRY
 	),
 
@@ -804,11 +722,13 @@ TRACE_EVENT(drv_ampdu_action,
 		__entry->action = action;
 		__entry->tid = tid;
 		__entry->ssn = ssn ? *ssn : 0;
+		__entry->buf_size = buf_size;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d",
-		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid
+		LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d buf:%d",
+		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action,
+		__entry->tid, __entry->buf_size
 	)
 );
 
@@ -959,24 +879,96 @@ TRACE_EVENT(drv_remain_on_channel,
 	)
 );
 
-TRACE_EVENT(drv_cancel_remain_on_channel,
+DEFINE_EVENT(local_only_evt, drv_cancel_remain_on_channel,
 	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
+);
 
-	TP_ARGS(local),
+TRACE_EVENT(drv_offchannel_tx,
+	TP_PROTO(struct ieee80211_local *local, struct sk_buff *skb,
+		 struct ieee80211_channel *chan,
+		 enum nl80211_channel_type channel_type,
+		 unsigned int wait),
+
+	TP_ARGS(local, skb, chan, channel_type, wait),
 
 	TP_STRUCT__entry(
 		LOCAL_ENTRY
+		__field(int, center_freq)
+		__field(int, channel_type)
+		__field(unsigned int, wait)
 	),
 
 	TP_fast_assign(
 		LOCAL_ASSIGN;
+		__entry->center_freq = chan->center_freq;
+		__entry->channel_type = channel_type;
+		__entry->wait = wait;
 	),
 
 	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
+		LOCAL_PR_FMT " freq:%dMHz, wait:%dms",
+		LOCAL_PR_ARG, __entry->center_freq, __entry->wait
+	)
+);
+
+TRACE_EVENT(drv_set_ringparam,
+	TP_PROTO(struct ieee80211_local *local, u32 tx, u32 rx),
+
+	TP_ARGS(local, tx, rx),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(u32, tx)
+		__field(u32, rx)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->tx = tx;
+		__entry->rx = rx;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " tx:%d rx %d",
+		LOCAL_PR_ARG, __entry->tx, __entry->rx
+	)
+);
+
+TRACE_EVENT(drv_get_ringparam,
+	TP_PROTO(struct ieee80211_local *local, u32 *tx, u32 *tx_max,
+		 u32 *rx, u32 *rx_max),
+
+	TP_ARGS(local, tx, tx_max, rx, rx_max),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(u32, tx)
+		__field(u32, tx_max)
+		__field(u32, rx)
+		__field(u32, rx_max)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->tx = *tx;
+		__entry->tx_max = *tx_max;
+		__entry->rx = *rx;
+		__entry->rx_max = *rx_max;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " tx:%d tx_max %d rx %d rx_max %d",
+		LOCAL_PR_ARG,
+		__entry->tx, __entry->tx_max, __entry->rx, __entry->rx_max
 	)
 );
 
+DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,
+	TP_PROTO(struct ieee80211_local *local),
+	TP_ARGS(local)
+);
+
 /*
  * Tracing for API calls that drivers call.
  */
@@ -1069,23 +1061,9 @@ TRACE_EVENT(api_stop_tx_ba_cb,
 	)
 );
 
-TRACE_EVENT(api_restart_hw,
+DEFINE_EVENT(local_only_evt, api_restart_hw,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT,
-		LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
 TRACE_EVENT(api_beacon_loss,
@@ -1214,40 +1192,14 @@ TRACE_EVENT(api_chswitch_done,
 	)
 );
 
-TRACE_EVENT(api_ready_on_channel,
+DEFINE_EVENT(local_only_evt, api_ready_on_channel,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
-TRACE_EVENT(api_remain_on_channel_expired,
+DEFINE_EVENT(local_only_evt, api_remain_on_channel_expired,
 	TP_PROTO(struct ieee80211_local *local),
-
-	TP_ARGS(local),
-
-	TP_STRUCT__entry(
-		LOCAL_ENTRY
-	),
-
-	TP_fast_assign(
-		LOCAL_ASSIGN;
-	),
-
-	TP_printk(
-		LOCAL_PR_FMT, LOCAL_PR_ARG
-	)
+	TP_ARGS(local)
 );
 
 /*
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 75d679d..b9e4b9b 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -66,6 +66,9 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
 	/* own MCS TX capabilities */
 	tx_mcs_set_cap = sband->ht_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;
+
 	/* can we TX with MCS rates? */
 	if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED))
 		return;
@@ -79,7 +82,7 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
 		max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS;
 
 	/*
-	 * 802.11n D5.0 20.3.5 / 20.6 says:
+	 * 802.11n-2009 20.3.5 / 20.6 says:
 	 * - indices 0 to 7 and 32 are single spatial stream
 	 * - 8 to 31 are multiple spatial streams using equal modulation
 	 *   [8..15 for two streams, 16..23 for three and 24..31 for four]
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 53c7077..3e81af1 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -31,7 +31,6 @@
 #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ)
 
 #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
-#define IEEE80211_IBSS_MERGE_DELAY 0x400000
 #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
 
 #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
@@ -270,7 +269,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 	enum ieee80211_band band = rx_status->band;
 
 	if (elems->ds_params && elems->ds_params_len == 1)
-		freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
+		freq = ieee80211_channel_to_frequency(elems->ds_params[0],
+						      band);
 	else
 		freq = rx_status->freq;
 
@@ -354,7 +354,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 	if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0)
 		goto put_bss;
 
-	if (rx_status->flag & RX_FLAG_TSFT) {
+	if (rx_status->flag & RX_FLAG_MACTIME_MPDU) {
 		/*
 		 * For correct IBSS merging we need mactime; since mactime is
 		 * defined as the time the first data symbol of the frame hits
@@ -396,10 +396,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 	       jiffies);
 #endif
 
-	/* give slow hardware some time to do the TSF sync */
-	if (rx_timestamp < IEEE80211_IBSS_MERGE_DELAY)
-		goto put_bss;
-
 	if (beacon_timestamp > rx_timestamp) {
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
 		printk(KERN_DEBUG "%s: beacon TSF higher than "
@@ -663,12 +659,13 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
 }
 
 static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
-					struct ieee80211_mgmt *mgmt,
-					size_t len)
+					struct sk_buff *req)
 {
+	struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(req);
+	struct ieee80211_mgmt *mgmt = (void *)req->data;
 	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 	struct ieee80211_local *local = sdata->local;
-	int tx_last_beacon;
+	int tx_last_beacon, len = req->len;
 	struct sk_buff *skb;
 	struct ieee80211_mgmt *resp;
 	u8 *pos, *end;
@@ -688,7 +685,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
 	       mgmt->bssid, tx_last_beacon);
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
 
-	if (!tx_last_beacon)
+	if (!tx_last_beacon && !(rx_status->rx_flags & IEEE80211_RX_RA_MATCH))
 		return;
 
 	if (memcmp(mgmt->bssid, ifibss->bssid, ETH_ALEN) != 0 &&
@@ -785,7 +782,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
 	switch (fc & IEEE80211_FCTL_STYPE) {
 	case IEEE80211_STYPE_PROBE_REQ:
-		ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len);
+		ieee80211_rx_mgmt_probe_req(sdata, skb);
 		break;
 	case IEEE80211_STYPE_PROBE_RESP:
 		ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 533fd32..a404017 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -225,6 +225,7 @@ struct ieee80211_if_ap {
 	struct sk_buff_head ps_bc_buf;
 	atomic_t num_sta_ps; /* number of stations in PS mode */
 	int dtim_count;
+	bool dtim_bc_mc;
 };
 
 struct ieee80211_if_wds {
@@ -654,8 +655,6 @@ struct tpt_led_trigger {
  *	well be on the operating channel
  * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
  *	determine if we are on the operating channel or not
- * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
- *	gets only set in conjunction with SCAN_SW_SCANNING
  * @SCAN_COMPLETED: Set for our scan work function when the driver reported
  *	that the scan completed.
  * @SCAN_ABORTED: Set for our scan work function when the driver reported
@@ -664,7 +663,6 @@ struct tpt_led_trigger {
 enum {
 	SCAN_SW_SCANNING,
 	SCAN_HW_SCANNING,
-	SCAN_OFF_CHANNEL,
 	SCAN_COMPLETED,
 	SCAN_ABORTED,
 };
@@ -959,6 +957,7 @@ struct ieee80211_local {
 	unsigned int hw_roc_duration;
 	u32 hw_roc_cookie;
 	bool hw_roc_for_tx;
+	unsigned long hw_offchan_tx_cookie;
 
 	/* dummy netdev for use w/ NAPI */
 	struct net_device napi_dev;
@@ -1068,8 +1067,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 void ieee80211_configure_filter(struct ieee80211_local *local);
 u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata);
 
-extern bool ieee80211_disable_40mhz_24ghz;
-
 /* STA code */
 void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata);
 int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@ -1147,10 +1144,14 @@ void ieee80211_rx_bss_put(struct ieee80211_local *local,
 			  struct ieee80211_bss *bss);
 
 /* off-channel helpers */
-void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
-void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
+bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
+void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
+					bool tell_ap);
+void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
+				    bool offchannel_ps_enable);
 void ieee80211_offchannel_return(struct ieee80211_local *local,
-				 bool enable_beaconing);
+				 bool enable_beaconing,
+				 bool offchannel_ps_disable);
 void ieee80211_hw_roc_setup(struct ieee80211_local *local);
 
 /* interface handling */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7a10a8d..4054399 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -382,6 +382,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 	struct sk_buff *skb, *tmp;
 	u32 hw_reconf_flags = 0;
 	int i;
+	enum nl80211_channel_type orig_ct;
 
 	if (local->scan_sdata == sdata)
 		ieee80211_scan_cancel(local);
@@ -542,8 +543,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 		hw_reconf_flags = 0;
 	}
 
+	/* Re-calculate channel-type, in case there are multiple vifs
+	 * on different channel types.
+	 */
+	orig_ct = local->_oper_channel_type;
+	ieee80211_set_channel_type(local, NULL, NL80211_CHAN_NO_HT);
+
 	/* do after stop to avoid reconfiguring when we stop anyway */
-	if (hw_reconf_flags)
+	if (hw_reconf_flags || (orig_ct != local->_oper_channel_type))
 		ieee80211_hw_config(local, hw_reconf_flags);
 
 	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 8106aa1..4ddbe27 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -21,7 +21,6 @@
 
 #define WEP_IV_LEN		4
 #define WEP_ICV_LEN		4
-#define ALG_TKIP_KEY_LEN	32
 #define ALG_CCMP_KEY_LEN	16
 #define CCMP_HDR_LEN		8
 #define CCMP_MIC_LEN		8
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a46ff06..562d298 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -34,7 +34,7 @@
 #include "debugfs.h"
 
 
-bool ieee80211_disable_40mhz_24ghz;
+static bool ieee80211_disable_40mhz_24ghz;
 module_param(ieee80211_disable_40mhz_24ghz, bool, 0644);
 MODULE_PARM_DESC(ieee80211_disable_40mhz_24ghz,
 		 "Disable 40MHz support in the 2.4GHz band");
@@ -98,6 +98,47 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
 	ieee80211_configure_filter(local);
 }
 
+/*
+ * Returns true if we are logically configured to be on
+ * the operating channel AND the hardware-conf is currently
+ * configured on the operating channel.  Compares channel-type
+ * as well.
+ */
+bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
+{
+	struct ieee80211_channel *chan, *scan_chan;
+	enum nl80211_channel_type channel_type;
+
+	/* This logic needs to match logic in ieee80211_hw_config */
+	if (local->scan_channel) {
+		chan = local->scan_channel;
+		/* If scanning on oper channel, use whatever channel-type
+		 * is currently in use.
+		 */
+		if (chan == local->oper_channel)
+			channel_type = local->_oper_channel_type;
+		else
+			channel_type = NL80211_CHAN_NO_HT;
+	} else if (local->tmp_channel) {
+		chan = scan_chan = local->tmp_channel;
+		channel_type = local->tmp_channel_type;
+	} else {
+		chan = local->oper_channel;
+		channel_type = local->_oper_channel_type;
+	}
+
+	if (chan != local->oper_channel ||
+	    channel_type != local->_oper_channel_type)
+		return false;
+
+	/* Check current hardware-config against oper_channel. */
+	if ((local->oper_channel != local->hw.conf.channel) ||
+	    (local->_oper_channel_type != local->hw.conf.channel_type))
+		return false;
+
+	return true;
+}
+
 int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 {
 	struct ieee80211_channel *chan, *scan_chan;
@@ -110,21 +151,33 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 
 	scan_chan = local->scan_channel;
 
+	/* If this off-channel logic ever changes,  ieee80211_on_oper_channel
+	 * may need to change as well.
+	 */
 	offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 	if (scan_chan) {
 		chan = scan_chan;
-		channel_type = NL80211_CHAN_NO_HT;
-		local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
-	} else if (local->tmp_channel &&
-		   local->oper_channel != local->tmp_channel) {
+		/* If scanning on oper channel, use whatever channel-type
+		 * is currently in use.
+		 */
+		if (chan == local->oper_channel)
+			channel_type = local->_oper_channel_type;
+		else
+			channel_type = NL80211_CHAN_NO_HT;
+	} else if (local->tmp_channel) {
 		chan = scan_chan = local->tmp_channel;
 		channel_type = local->tmp_channel_type;
-		local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
 	} else {
 		chan = local->oper_channel;
 		channel_type = local->_oper_channel_type;
-		local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
 	}
+
+	if (chan != local->oper_channel ||
+	    channel_type != local->_oper_channel_type)
+		local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+	else
+		local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
+
 	offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
 
 	if (offchannel_flag || chan != local->hw.conf.channel ||
@@ -146,7 +199,8 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
 		changed |= IEEE80211_CONF_CHANGE_SMPS;
 	}
 
-	if (scan_chan)
+	if ((local->scanning & SCAN_SW_SCANNING) ||
+	    (local->scanning & SCAN_HW_SCANNING))
 		power = chan->max_power;
 	else
 		power = local->power_constr_level ?
@@ -231,7 +285,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
 
 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
 		if (local->quiescing || !ieee80211_sdata_running(sdata) ||
-		    test_bit(SCAN_SW_SCANNING, &local->scanning)) {
+		    test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
 			sdata->vif.bss_conf.enable_beacon = false;
 		} else {
 			/*
@@ -326,6 +380,9 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
 
 	trace_api_restart_hw(local);
 
+	wiphy_info(hw->wiphy,
+		   "Hardware restart was requested\n");
+
 	/* use this reason, ieee80211_reconfig will unblock it */
 	ieee80211_stop_queues_by_reason(hw,
 		IEEE80211_QUEUE_STOP_REASON_SUSPEND);
@@ -554,6 +611,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 	local->hw.queues = 1;
 	local->hw.max_rates = 1;
 	local->hw.max_report_rates = 0;
+	local->hw.max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF;
 	local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
 	local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
 	local->user_power_level = -1;
@@ -668,6 +726,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 		}
 		channels += sband->n_channels;
 
+		/*
+		 * Since ieee80211_disable_40mhz_24ghz is global, we can
+		 * modify the sband's ht data even if the driver uses a
+		 * global structure for that.
+		 */
+		if (ieee80211_disable_40mhz_24ghz &&
+		    band == IEEE80211_BAND_2GHZ &&
+		    sband->ht_cap.ht_supported) {
+			sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+			sband->ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_40;
+		}
+
 		if (max_bitrates < sband->n_bitrates)
 			max_bitrates = sband->n_bitrates;
 		supp_ht = supp_ht || sband->ht_cap.ht_supported;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index ca3af46..2a57cc0 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
 			       &elems);
 
 	if (elems.ds_params && elems.ds_params_len == 1)
-		freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
+		freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
 	else
 		freq = rx_status->freq;
 
@@ -645,7 +645,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
 	if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
 		mesh_mpath_table_grow();
 
-	if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
+	if (test_and_clear_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags))
 		mesh_mpp_table_grow();
 
 	if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index c9ceb4d..64d92d5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -28,8 +28,15 @@
 #include "rate.h"
 #include "led.h"
 
-#define IEEE80211_MAX_NULLFUNC_TRIES 2
-#define IEEE80211_MAX_PROBE_TRIES 5
+static int max_nullfunc_tries = 2;
+module_param(max_nullfunc_tries, int, 0644);
+MODULE_PARM_DESC(max_nullfunc_tries,
+		 "Maximum nullfunc tx tries before disconnecting (reason 4).");
+
+static int max_probe_tries = 5;
+module_param(max_probe_tries, int, 0644);
+MODULE_PARM_DESC(max_probe_tries,
+		 "Maximum probe tries before disconnecting (reason 4).");
 
 /*
  * Beacon loss timeout is calculated as N frames times the
@@ -51,7 +58,11 @@
  * a probe request because of beacon loss or for
  * checking the connection still works.
  */
-#define IEEE80211_PROBE_WAIT		(HZ / 2)
+static int probe_wait_ms = 500;
+module_param(probe_wait_ms, int, 0644);
+MODULE_PARM_DESC(probe_wait_ms,
+		 "Maximum time(ms) to wait for probe response"
+		 " before disconnecting (reason 4).");
 
 /*
  * Weight given to the latest Beacon frame when calculating average signal
@@ -134,6 +145,9 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+	if (unlikely(!sdata->u.mgd.associated))
+		return;
+
 	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
 		return;
 
@@ -161,6 +175,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
 	struct ieee80211_supported_band *sband;
 	struct sta_info *sta;
 	u32 changed = 0;
+	int hti_cfreq;
 	u16 ht_opmode;
 	bool enable_ht = true;
 	enum nl80211_channel_type prev_chantype;
@@ -174,10 +189,27 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
 	if (!sband->ht_cap.ht_supported)
 		enable_ht = false;
 
-	/* check that channel matches the right operating channel */
-	if (local->hw.conf.channel->center_freq !=
-	    ieee80211_channel_to_frequency(hti->control_chan))
-		enable_ht = false;
+	if (enable_ht) {
+		hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan,
+							   sband->band);
+		/* check that channel matches the right operating channel */
+		if (local->hw.conf.channel->center_freq != hti_cfreq) {
+			/* Some APs mess this up, evidently.
+			 * Netgear WNDR3700 sometimes reports 4 higher than
+			 * the actual channel, for instance.
+			 */
+			printk(KERN_DEBUG
+			       "%s: Wrong control channel in association"
+			       " response: configured center-freq: %d"
+			       " hti-cfreq: %d  hti->control_chan: %d"
+			       " band: %d.  Disabling HT.\n",
+			       sdata->name,
+			       local->hw.conf.channel->center_freq,
+			       hti_cfreq, hti->control_chan,
+			       sband->band);
+			enable_ht = false;
+		}
+	}
 
 	if (enable_ht) {
 		channel_type = NL80211_CHAN_HT20;
@@ -429,7 +461,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
 		container_of((void *)bss, struct cfg80211_bss, priv);
 	struct ieee80211_channel *new_ch;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-	int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
+	int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
+						      cbss->channel->band);
 
 	ASSERT_MGD_MTX(ifmgd);
 
@@ -580,6 +613,37 @@ static void ieee80211_change_ps(struct ieee80211_local *local)
 	}
 }
 
+static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_if_managed *mgd = &sdata->u.mgd;
+	struct sta_info *sta = NULL;
+	u32 sta_flags = 0;
+
+	if (!mgd->powersave)
+		return false;
+
+	if (!mgd->associated)
+		return false;
+
+	if (!mgd->associated->beacon_ies)
+		return false;
+
+	if (mgd->flags & (IEEE80211_STA_BEACON_POLL |
+			  IEEE80211_STA_CONNECTION_POLL))
+		return false;
+
+	rcu_read_lock();
+	sta = sta_info_get(sdata, mgd->bssid);
+	if (sta)
+		sta_flags = get_sta_flags(sta);
+	rcu_read_unlock();
+
+	if (!(sta_flags & WLAN_STA_AUTHORIZED))
+		return false;
+
+	return true;
+}
+
 /* need to hold RTNL or interface lock */
 void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 {
@@ -600,17 +664,21 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (!ieee80211_sdata_running(sdata))
 			continue;
+		if (sdata->vif.type == NL80211_IFTYPE_AP) {
+			/* If an AP vif is found, then disable PS
+			 * by setting the count to zero thereby setting
+			 * ps_sdata to NULL.
+			 */
+			count = 0;
+			break;
+		}
 		if (sdata->vif.type != NL80211_IFTYPE_STATION)
 			continue;
 		found = sdata;
 		count++;
 	}
 
-	if (count == 1 && found->u.mgd.powersave &&
-	    found->u.mgd.associated &&
-	    found->u.mgd.associated->beacon_ies &&
-	    !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
-				    IEEE80211_STA_CONNECTION_POLL))) {
+	if (count == 1 && ieee80211_powersave_allowed(found)) {
 		struct ieee80211_conf *conf = &local->hw.conf;
 		s32 beaconint_us;
 
@@ -700,9 +768,19 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		return;
 
 	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
-	    (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)))
+	    (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
+		netif_tx_stop_all_queues(sdata->dev);
+		/*
+		 * Flush all the frames queued in the driver before
+		 * going to power save
+		 */
+		drv_flush(local, false);
 		ieee80211_send_nullfunc(local, sdata, 1);
 
+		/* Flush once again to get the tx status of nullfunc frame */
+		drv_flush(local, false);
+	}
+
 	if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
 	      (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) ||
 	    (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
@@ -710,6 +788,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
 		local->hw.conf.flags |= IEEE80211_CONF_PS;
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
+
+	netif_tx_start_all_queues(sdata->dev);
 }
 
 void ieee80211_dynamic_ps_timer(unsigned long data)
@@ -1033,12 +1113,6 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
 	if (is_multicast_ether_addr(hdr->addr1))
 		return;
 
-	/*
-	 * In case we receive frames after disassociation.
-	 */
-	if (!sdata->u.mgd.associated)
-		return;
-
 	ieee80211_sta_reset_conn_monitor(sdata);
 }
 
@@ -1095,7 +1169,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	const u8 *ssid;
 	u8 *dst = ifmgd->associated->bssid;
-	u8 unicast_limit = max(1, IEEE80211_MAX_PROBE_TRIES - 3);
+	u8 unicast_limit = max(1, max_probe_tries - 3);
 
 	/*
 	 * Try sending broadcast probe requests for the last three
@@ -1121,7 +1195,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
 	}
 
 	ifmgd->probe_send_count++;
-	ifmgd->probe_timeout = jiffies + IEEE80211_PROBE_WAIT;
+	ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
 	run_again(ifmgd, ifmgd->probe_timeout);
 }
 
@@ -1222,7 +1296,8 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
 
 	memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
 
-	printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
+	printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n",
+	       sdata->name, bssid);
 
 	ieee80211_set_disassoc(sdata, true, true);
 	mutex_unlock(&ifmgd->mtx);
@@ -1525,7 +1600,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
 	}
 
 	if (elems->ds_params && elems->ds_params_len == 1)
-		freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
+		freq = ieee80211_channel_to_frequency(elems->ds_params[0],
+						      rx_status->band);
 	else
 		freq = rx_status->freq;
 
@@ -1966,9 +2042,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 		memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN);
 
 		if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
-			max_tries = IEEE80211_MAX_NULLFUNC_TRIES;
+			max_tries = max_nullfunc_tries;
 		else
-			max_tries = IEEE80211_MAX_PROBE_TRIES;
+			max_tries = max_probe_tries;
 
 		/* ACK received for nullfunc probing frame */
 		if (!ifmgd->probe_send_count)
@@ -1978,9 +2054,9 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 				wiphy_debug(local->hw.wiphy,
 					    "%s: No ack for nullfunc frame to"
-					    " AP %pM, try %d\n",
+					    " AP %pM, try %d/%i\n",
 					    sdata->name, bssid,
-					    ifmgd->probe_send_count);
+					    ifmgd->probe_send_count, max_tries);
 #endif
 				ieee80211_mgd_probe_ap_send(sdata);
 			} else {
@@ -2000,17 +2076,17 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 				    "%s: Failed to send nullfunc to AP %pM"
 				    " after %dms, disconnecting.\n",
 				    sdata->name,
-				    bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
+				    bssid, probe_wait_ms);
 #endif
 			ieee80211_sta_connection_lost(sdata, bssid);
 		} else if (ifmgd->probe_send_count < max_tries) {
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
 			wiphy_debug(local->hw.wiphy,
 				    "%s: No probe response from AP %pM"
-				    " after %dms, try %d\n",
+				    " after %dms, try %d/%i\n",
 				    sdata->name,
-				    bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ,
-				    ifmgd->probe_send_count);
+				    bssid, probe_wait_ms,
+				    ifmgd->probe_send_count, max_tries);
 #endif
 			ieee80211_mgd_probe_ap_send(sdata);
 		} else {
@@ -2022,7 +2098,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 				    "%s: No probe response from AP %pM"
 				    " after %dms, disconnecting.\n",
 				    sdata->name,
-				    bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
+				    bssid, probe_wait_ms);
 
 			ieee80211_sta_connection_lost(sdata, bssid);
 		}
@@ -2260,6 +2336,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
 	else
 		wk->type = IEEE80211_WORK_DIRECT_PROBE;
 	wk->chan = req->bss->channel;
+	wk->chan_type = NL80211_CHAN_NO_HT;
 	wk->sdata = sdata;
 	wk->done = ieee80211_probe_auth_done;
 
@@ -2409,6 +2486,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 		memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN);
 
 	wk->chan = req->bss->channel;
+	wk->chan_type = NL80211_CHAN_NO_HT;
 	wk->sdata = sdata;
 	wk->done = ieee80211_assoc_done;
 	if (!bss->dtim_period &&
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index b4e5267..13427b1 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -17,10 +17,14 @@
 #include "driver-trace.h"
 
 /*
- * inform AP that we will go to sleep so that it will buffer the frames
- * while we scan
+ * Tell our hardware to disable PS.
+ * Optionally inform AP that we will go to sleep so that it will buffer
+ * the frames while we are doing off-channel work.  This is optional
+ * because we *may* be doing work on-operating channel, and want our
+ * hardware unconditionally awake, but still let the AP send us normal frames.
  */
-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
+static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
+					   bool tell_ap)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -41,8 +45,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	}
 
-	if (!(local->offchannel_ps_enabled) ||
-	    !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
+	if (tell_ap && (!local->offchannel_ps_enabled ||
+			!(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)))
 		/*
 		 * If power save was enabled, no need to send a nullfunc
 		 * frame because AP knows that we are sleeping. But if the
@@ -77,6 +81,9 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
 		 * we are sleeping, let's just enable power save mode in
 		 * hardware.
 		 */
+		/* TODO:  Only set hardware if CONF_PS changed?
+		 * TODO:  Should we set offchannel_ps_enabled to false?
+		 */
 		local->hw.conf.flags |= IEEE80211_CONF_PS;
 		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
 	} else if (local->hw.conf.dynamic_ps_timeout > 0) {
@@ -95,63 +102,61 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
 	ieee80211_sta_reset_conn_monitor(sdata);
 }
 
-void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
+void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
+				    bool offchannel_ps_enable)
 {
 	struct ieee80211_sub_if_data *sdata;
 
+	/*
+	 * notify the AP about us leaving the channel and stop all
+	 * STA interfaces.
+	 */
 	mutex_lock(&local->iflist_mtx);
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (!ieee80211_sdata_running(sdata))
 			continue;
 
-		/* disable beaconing */
+		if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
+			set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
+
+		/* Check to see if we should disable beaconing. */
 		if (sdata->vif.type == NL80211_IFTYPE_AP ||
 		    sdata->vif.type == NL80211_IFTYPE_ADHOC ||
 		    sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
 			ieee80211_bss_info_change_notify(
 				sdata, BSS_CHANGED_BEACON_ENABLED);
 
-		/*
-		 * only handle non-STA interfaces here, STA interfaces
-		 * are handled in ieee80211_offchannel_stop_station(),
-		 * e.g., from the background scan state machine.
-		 *
-		 * In addition, do not stop monitor interface to allow it to be
-		 * used from user space controlled off-channel operations.
-		 */
-		if (sdata->vif.type != NL80211_IFTYPE_STATION &&
-		    sdata->vif.type != NL80211_IFTYPE_MONITOR) {
-			set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
+		if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
 			netif_tx_stop_all_queues(sdata->dev);
+			if (offchannel_ps_enable &&
+			    (sdata->vif.type == NL80211_IFTYPE_STATION) &&
+			    sdata->u.mgd.associated)
+				ieee80211_offchannel_ps_enable(sdata, true);
 		}
 	}
 	mutex_unlock(&local->iflist_mtx);
 }
 
-void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
+void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
+					bool tell_ap)
 {
 	struct ieee80211_sub_if_data *sdata;
 
-	/*
-	 * notify the AP about us leaving the channel and stop all STA interfaces
-	 */
 	mutex_lock(&local->iflist_mtx);
 	list_for_each_entry(sdata, &local->interfaces, list) {
 		if (!ieee80211_sdata_running(sdata))
 			continue;
 
-		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
-			set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
-			netif_tx_stop_all_queues(sdata->dev);
-			if (sdata->u.mgd.associated)
-				ieee80211_offchannel_ps_enable(sdata);
-		}
+		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+		    sdata->u.mgd.associated)
+			ieee80211_offchannel_ps_enable(sdata, tell_ap);
 	}
 	mutex_unlock(&local->iflist_mtx);
 }
 
 void ieee80211_offchannel_return(struct ieee80211_local *local,
-				 bool enable_beaconing)
+				 bool enable_beaconing,
+				 bool offchannel_ps_disable)
 {
 	struct ieee80211_sub_if_data *sdata;
 
@@ -161,7 +166,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
 			continue;
 
 		/* Tell AP we're back */
-		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+		if (offchannel_ps_disable &&
+		    sdata->vif.type == NL80211_IFTYPE_STATION) {
 			if (sdata->u.mgd.associated)
 				ieee80211_offchannel_ps_disable(sdata);
 		}
@@ -181,7 +187,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
 			netif_tx_wake_all_queues(sdata->dev);
 		}
 
-		/* re-enable beaconing */
+		/* Check to see if we should re-enable beaconing */
 		if (enable_beaconing &&
 		    (sdata->vif.type == NL80211_IFTYPE_AP ||
 		     sdata->vif.type == NL80211_IFTYPE_ADHOC ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index 165a451..8212a8b 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -415,10 +415,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
 		mi->sample_count--;
 	}
 
-	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
+	if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
 		mi->sample_packets += info->status.ampdu_len;
-		minstrel_next_sample_idx(mi);
-	}
 
 	for (i = 0; !last; i++) {
 		last = (i == IEEE80211_TX_MAX_RATES - 1) ||
@@ -519,9 +517,7 @@ minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
 		rate->count = mr->retry_count;
 
 	rate->flags = IEEE80211_TX_RC_MCS | group->flags;
-	if (txrc->short_preamble)
-		rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
-	if (txrc->rts || rtscts)
+	if (rtscts)
 		rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
 	rate->idx = index % MCS_GROUP_RATES + (group->streams - 1) * MCS_GROUP_RATES;
 }
@@ -553,13 +549,14 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 	sample_idx = sample_table[mg->column][mg->index];
 	mr = &mg->rates[sample_idx];
 	sample_idx += mi->sample_group * MCS_GROUP_RATES;
+	minstrel_next_sample_idx(mi);
 
 	/*
 	 * When not using MRR, 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)))
-		goto next;
+		return -1;
 
 	/*
 	 * Make sure that lower rates get sampled only occasionally,
@@ -568,17 +565,13 @@ minstrel_get_sample_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
 	if (minstrel_get_duration(sample_idx) >
 	    minstrel_get_duration(mi->max_tp_rate)) {
 		if (mr->sample_skipped < 20)
-			goto next;
+			return -1;
 
 		if (mi->sample_slow++ > 2)
-			goto next;
+			return -1;
 	}
 
 	return sample_idx;
-
-next:
-	minstrel_next_sample_idx(mi);
-	return -1;
 }
 
 static void
@@ -605,19 +598,46 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
 		sample = true;
 		minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
 			txrc, true, false);
-		minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
-			txrc, false, false);
 		info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 	} else {
 		minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
 			txrc, false, false);
-		minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
-			txrc, false, true);
 	}
-	minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, !sample);
 
-	ar[3].count = 0;
-	ar[3].idx = -1;
+	if (mp->hw->max_rates >= 3) {
+		/*
+		 * At least 3 tx rates supported, use
+		 * sample_rate -> max_tp_rate -> max_prob_rate for sampling and
+		 * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
+		 */
+		if (sample_idx >= 0)
+			minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
+				txrc, false, false);
+		else
+			minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
+				txrc, false, true);
+
+		minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
+				     txrc, false, !sample);
+
+		ar[3].count = 0;
+		ar[3].idx = -1;
+	} else if (mp->hw->max_rates == 2) {
+		/*
+		 * Only 2 tx rates supported, use
+		 * sample_rate -> max_prob_rate for sampling and
+		 * max_tp_rate -> max_prob_rate by default.
+		 */
+		minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
+				     txrc, false, !sample);
+
+		ar[2].count = 0;
+		ar[2].idx = -1;
+	} else {
+		/* Not using MRR, only use the first rate */
+		ar[1].count = 0;
+		ar[1].idx = -1;
+	}
 
 	mi->total_packets++;
 
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h
index 1a873f0..6510f8e 100644
--- a/net/mac80211/rc80211_pid.h
+++ b/net/mac80211/rc80211_pid.h
@@ -24,9 +24,6 @@
 /* Fixed point arithmetic shifting amount. */
 #define RC_PID_ARITH_SHIFT		8
 
-/* Fixed point arithmetic factor. */
-#define RC_PID_ARITH_FACTOR		(1 << RC_PID_ARITH_SHIFT)
-
 /* Proportional PID component coefficient. */
 #define RC_PID_COEFF_P			15
 /* Integral PID component coefficient. */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index a6701ed..5c1930b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -77,7 +77,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
 	/* always present fields */
 	len = sizeof(struct ieee80211_radiotap_header) + 9;
 
-	if (status->flag & RX_FLAG_TSFT)
+	if (status->flag & RX_FLAG_MACTIME_MPDU)
 		len += 8;
 	if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
 		len += 1;
@@ -85,6 +85,9 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
 	if (len & 1) /* padding for RX_FLAGS if necessary */
 		len++;
 
+	if (status->flag & RX_FLAG_HT) /* HT info */
+		len += 3;
+
 	return len;
 }
 
@@ -120,7 +123,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 	/* the order of the following fields is important */
 
 	/* IEEE80211_RADIOTAP_TSFT */
-	if (status->flag & RX_FLAG_TSFT) {
+	if (status->flag & RX_FLAG_MACTIME_MPDU) {
 		put_unaligned_le64(status->mactime, pos);
 		rthdr->it_present |=
 			cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
@@ -139,11 +142,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 	/* IEEE80211_RADIOTAP_RATE */
 	if (status->flag & RX_FLAG_HT) {
 		/*
-		 * TODO: add following information into radiotap header once
-		 * suitable fields are defined for it:
-		 * - MCS index (status->rate_idx)
-		 * - HT40 (status->flag & RX_FLAG_40MHZ)
-		 * - short-GI (status->flag & RX_FLAG_SHORT_GI)
+		 * MCS information is a separate field in radiotap,
+		 * added below.
 		 */
 		*pos = 0;
 	} else {
@@ -193,6 +193,20 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 		rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
 	put_unaligned_le16(rx_flags, pos);
 	pos += 2;
+
+	if (status->flag & RX_FLAG_HT) {
+		rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
+		*pos++ = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
+			 IEEE80211_RADIOTAP_MCS_HAVE_GI |
+			 IEEE80211_RADIOTAP_MCS_HAVE_BW;
+		*pos = 0;
+		if (status->flag & RX_FLAG_SHORT_GI)
+			*pos |= IEEE80211_RADIOTAP_MCS_SGI;
+		if (status->flag & RX_FLAG_40MHZ)
+			*pos |= IEEE80211_RADIOTAP_MCS_BW_40;
+		pos++;
+		*pos++ = status->rate_idx;
+	}
 }
 
 /*
@@ -392,16 +406,10 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
 	if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN)))
 		return RX_CONTINUE;
 
-	if (test_bit(SCAN_HW_SCANNING, &local->scanning))
+	if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+	    test_bit(SCAN_SW_SCANNING, &local->scanning))
 		return ieee80211_scan_rx(rx->sdata, skb);
 
-	if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
-		/* drop all the other packets during a software scan anyway */
-		if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
-			dev_kfree_skb(skb);
-		return RX_QUEUED;
-	}
-
 	/* scanning finished during invoking of handlers */
 	I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
 	return RX_DROP_UNUSABLE;
@@ -798,7 +806,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 				rx->local->dot11FrameDuplicateCount++;
 				rx->sta->num_duplicates++;
 			}
-			return RX_DROP_MONITOR;
+			return RX_DROP_UNUSABLE;
 		} else
 			rx->sta->last_seq_ctrl[rx->queue] = hdr->seq_ctrl;
 	}
@@ -824,18 +832,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 		      ieee80211_is_pspoll(hdr->frame_control)) &&
 		     rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
 		     rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
-		     (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
-		if ((!ieee80211_has_fromds(hdr->frame_control) &&
-		     !ieee80211_has_tods(hdr->frame_control) &&
-		     ieee80211_is_data(hdr->frame_control)) ||
-		    !(status->rx_flags & IEEE80211_RX_RA_MATCH)) {
-			/* Drop IBSS frames and frames for other hosts
-			 * silently. */
-			return RX_DROP_MONITOR;
-		}
-
+		     (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC))))
 		return RX_DROP_MONITOR;
-	}
 
 	return RX_CONTINUE;
 }
@@ -1088,7 +1086,8 @@ static void ap_sta_ps_start(struct sta_info *sta)
 
 	atomic_inc(&sdata->bss->num_sta_ps);
 	set_sta_flags(sta, WLAN_STA_PS_STA);
-	drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
+	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
+		drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
 	printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
 	       sdata->name, sta->sta.addr, sta->sta.aid);
@@ -1117,6 +1116,27 @@ static void ap_sta_ps_end(struct sta_info *sta)
 	ieee80211_sta_ps_deliver_wakeup(sta);
 }
 
+int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
+{
+	struct sta_info *sta_inf = container_of(sta, struct sta_info, sta);
+	bool in_ps;
+
+	WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
+
+	/* Don't let the same PS state be set twice */
+	in_ps = test_sta_flags(sta_inf, WLAN_STA_PS_STA);
+	if ((start && in_ps) || (!start && !in_ps))
+		return -EINVAL;
+
+	if (start)
+		ap_sta_ps_start(sta_inf);
+	else
+		ap_sta_ps_end(sta_inf);
+
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_sta_ps_transition);
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1136,14 +1156,23 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) {
 			sta->last_rx = jiffies;
+			if (ieee80211_is_data(hdr->frame_control)) {
+				sta->last_rx_rate_idx = status->rate_idx;
+				sta->last_rx_rate_flag = status->flag;
+			}
+		}
 	} else if (!is_multicast_ether_addr(hdr->addr1)) {
 		/*
 		 * Mesh beacons will update last_rx when if they are found to
 		 * match the current local configuration when processed.
 		 */
 		sta->last_rx = jiffies;
+		if (ieee80211_is_data(hdr->frame_control)) {
+			sta->last_rx_rate_idx = status->rate_idx;
+			sta->last_rx_rate_flag = status->flag;
+		}
 	}
 
 	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
@@ -1161,7 +1190,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	 * Change STA power saving mode only at the end of a frame
 	 * exchange sequence.
 	 */
-	if (!ieee80211_has_morefrags(hdr->frame_control) &&
+	if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) &&
+	    !ieee80211_has_morefrags(hdr->frame_control) &&
 	    !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
 	    (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
 	     rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
@@ -1556,17 +1586,36 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+	bool check_port_control = false;
+	struct ethhdr *ehdr;
+	int ret;
 
 	if (ieee80211_has_a4(hdr->frame_control) &&
 	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
 		return -1;
 
+	if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+	    !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) {
+
+		if (!sdata->u.mgd.use_4addr)
+			return -1;
+		else
+			check_port_control = true;
+	}
+
 	if (is_multicast_ether_addr(hdr->addr1) &&
-	    ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) ||
-	     (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
+	    sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)
 		return -1;
 
-	return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
+	ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
+	if (ret < 0 || !check_port_control)
+		return ret;
+
+	ehdr = (struct ethhdr *) rx->skb->data;
+	if (ehdr->h_proto != rx->sdata->control_port_protocol)
+		return -1;
+
+	return 0;
 }
 
 /*
@@ -1893,7 +1942,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 	dev->stats.rx_bytes += rx->skb->len;
 
 	if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 &&
-	    !is_multicast_ether_addr(((struct ethhdr *)rx->skb->data)->h_dest)) {
+	    !is_multicast_ether_addr(
+		    ((struct ethhdr *)rx->skb->data)->h_dest) &&
+	    (!local->scanning &&
+	     !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) {
 			mod_timer(&local->dynamic_ps_timer, jiffies +
 			 msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 	}
@@ -2590,7 +2642,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
 			return 0;
 		if (!multicast &&
 		    compare_ether_addr(sdata->vif.addr, hdr->addr1) != 0) {
-			if (!(sdata->dev->flags & IFF_PROMISC))
+			if (!(sdata->dev->flags & IFF_PROMISC) ||
+			    sdata->u.mgd.use_4addr)
 				return 0;
 			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		}
@@ -2639,7 +2692,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
 				return 0;
 		} else if (!ieee80211_bssid_match(bssid,
 					sdata->vif.addr)) {
-			if (!(status->rx_flags & IEEE80211_RX_IN_SCAN))
+			if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
+			    !ieee80211_is_beacon(hdr->frame_control))
 				return 0;
 			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
 		}
@@ -2692,7 +2746,7 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
 		if (!skb) {
 			if (net_ratelimit())
 				wiphy_debug(local->hw.wiphy,
-					"failed to copy multicast frame for %s\n",
+					"failed to copy skb for %s\n",
 					sdata->name);
 			return true;
 		}
@@ -2730,7 +2784,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 		local->dot11ReceivedFragmentCount++;
 
 	if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-		     test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
+		     test_bit(SCAN_SW_SCANNING, &local->scanning)))
 		status->rx_flags |= IEEE80211_RX_IN_SCAN;
 
 	if (ieee80211_is_mgmt(fc))
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index fb274db..489b6ad 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -196,7 +196,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 	ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
 
 	if (elems.ds_params && elems.ds_params_len == 1)
-		freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
+		freq = ieee80211_channel_to_frequency(elems.ds_params[0],
+						      rx_status->band);
 	else
 		freq = rx_status->freq;
 
@@ -211,6 +212,14 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 	if (bss)
 		ieee80211_rx_bss_put(sdata->local, bss);
 
+	/* If we are on-operating-channel, and this packet is for the
+	 * current channel, pass the pkt on up the stack so that
+	 * the rest of the stack can make use of it.
+	 */
+	if (ieee80211_cfg_on_oper_channel(sdata->local)
+	    && (channel == sdata->local->oper_channel))
+		return RX_CONTINUE;
+
 	dev_kfree_skb(skb);
 	return RX_QUEUED;
 }
@@ -249,10 +258,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
 	return true;
 }
 
-static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
+static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 				       bool was_hw_scan)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
+	bool on_oper_chan;
+	bool enable_beacons = false;
 
 	lockdep_assert_held(&local->mtx);
 
@@ -266,12 +277,12 @@ static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 		aborted = true;
 
 	if (WARN_ON(!local->scan_req))
-		return false;
+		return;
 
 	if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
 		int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
 		if (rc == 0)
-			return false;
+			return;
 	}
 
 	kfree(local->hw_scan_req);
@@ -285,24 +296,28 @@ static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
 	local->scanning = 0;
 	local->scan_channel = NULL;
 
-	return true;
-}
+	on_oper_chan = ieee80211_cfg_on_oper_channel(local);
 
-static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
-					      bool was_hw_scan)
-{
-	struct ieee80211_local *local = hw_to_local(hw);
+	if (was_hw_scan || !on_oper_chan)
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+	else
+		/* Set power back to normal operating levels. */
+		ieee80211_hw_config(local, 0);
 
-	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 	if (!was_hw_scan) {
+		bool on_oper_chan2;
 		ieee80211_configure_filter(local);
 		drv_sw_scan_complete(local);
-		ieee80211_offchannel_return(local, true);
+		on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
+		/* We should always be on-channel at this point. */
+		WARN_ON(!on_oper_chan2);
+		if (on_oper_chan2 && (on_oper_chan != on_oper_chan2))
+			enable_beacons = true;
+
+		ieee80211_offchannel_return(local, enable_beacons, true);
 	}
 
-	mutex_lock(&local->mtx);
 	ieee80211_recalc_idle(local);
-	mutex_unlock(&local->mtx);
 
 	ieee80211_mlme_notify_scan_completed(local);
 	ieee80211_ibss_notify_scan_completed(local);
@@ -340,16 +355,21 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
 	 */
 	drv_sw_scan_start(local);
 
-	ieee80211_offchannel_stop_beaconing(local);
-
 	local->leave_oper_channel_time = 0;
 	local->next_scan_state = SCAN_DECISION;
 	local->scan_channel_idx = 0;
 
-	drv_flush(local, false);
+	/* We always want to use off-channel PS, even if we
+	 * are not really leaving oper-channel.  Don't
+	 * tell the AP though, as long as we are on-channel.
+	 */
+	ieee80211_offchannel_enable_all_ps(local, false);
 
 	ieee80211_configure_filter(local);
 
+	/* We need to set power level at maximum rate for scanning. */
+	ieee80211_hw_config(local, 0);
+
 	ieee80211_queue_delayed_work(&local->hw,
 				     &local->scan_work,
 				     IEEE80211_CHANNEL_TIME);
@@ -486,7 +506,20 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
 	}
 	mutex_unlock(&local->iflist_mtx);
 
-	if (local->scan_channel) {
+	next_chan = local->scan_req->channels[local->scan_channel_idx];
+
+	if (ieee80211_cfg_on_oper_channel(local)) {
+		/* We're currently on operating channel. */
+		if (next_chan == local->oper_channel)
+			/* We don't need to move off of operating channel. */
+			local->next_scan_state = SCAN_SET_CHANNEL;
+		else
+			/*
+			 * We do need to leave operating channel, as next
+			 * scan is somewhere else.
+			 */
+			local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
+	} else {
 		/*
 		 * we're currently scanning a different channel, let's
 		 * see if we can scan another channel without interfering
@@ -502,7 +535,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
 		 *
 		 * Otherwise switch back to the operating channel.
 		 */
-		next_chan = local->scan_req->channels[local->scan_channel_idx];
 
 		bad_latency = time_after(jiffies +
 				ieee80211_scan_get_channel_time(next_chan),
@@ -520,12 +552,6 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
 			local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
 		else
 			local->next_scan_state = SCAN_SET_CHANNEL;
-	} else {
-		/*
-		 * we're on the operating channel currently, let's
-		 * leave that channel now to scan another one
-		 */
-		local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
 	}
 
 	*next_delay = 0;
@@ -534,9 +560,10 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
 static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
 						    unsigned long *next_delay)
 {
-	ieee80211_offchannel_stop_station(local);
-
-	__set_bit(SCAN_OFF_CHANNEL, &local->scanning);
+	/* PS will already be in off-channel mode,
+	 * we do that once at the beginning of scanning.
+	 */
+	ieee80211_offchannel_stop_vifs(local, false);
 
 	/*
 	 * What if the nullfunc frames didn't arrive?
@@ -559,15 +586,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
 {
 	/* switch back to the operating channel */
 	local->scan_channel = NULL;
-	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+	if (!ieee80211_cfg_on_oper_channel(local))
+		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
 	/*
-	 * Only re-enable station mode interface now; beaconing will be
-	 * re-enabled once the full scan has been completed.
+	 * Re-enable vifs and beaconing.  Leave PS
+	 * in off-channel state..will put that back
+	 * on-channel at the end of scanning.
 	 */
-	ieee80211_offchannel_return(local, false);
-
-	__clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
+	ieee80211_offchannel_return(local, true, false);
 
 	*next_delay = HZ / 5;
 	local->next_scan_state = SCAN_DECISION;
@@ -583,8 +610,11 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
 	chan = local->scan_req->channels[local->scan_channel_idx];
 
 	local->scan_channel = chan;
-	if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
-		skip = 1;
+
+	/* Only call hw-config if we really need to change channels. */
+	if (chan != local->hw.conf.channel)
+		if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
+			skip = 1;
 
 	/* advance state machine to next channel/band */
 	local->scan_channel_idx++;
@@ -642,12 +672,14 @@ void ieee80211_scan_work(struct work_struct *work)
 {
 	struct ieee80211_local *local =
 		container_of(work, struct ieee80211_local, scan_work.work);
-	struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+	struct ieee80211_sub_if_data *sdata;
 	unsigned long next_delay = 0;
-	bool aborted, hw_scan, finish;
+	bool aborted, hw_scan;
 
 	mutex_lock(&local->mtx);
 
+	sdata = local->scan_sdata;
+
 	if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
 		aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
 		goto out_complete;
@@ -711,17 +743,11 @@ void ieee80211_scan_work(struct work_struct *work)
 	} while (next_delay == 0);
 
 	ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
-	mutex_unlock(&local->mtx);
-	return;
+	goto out;
 
 out_complete:
 	hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
-	finish = __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
-	mutex_unlock(&local->mtx);
-	if (finish)
-		__ieee80211_scan_completed_finish(&local->hw, hw_scan);
-	return;
-
+	__ieee80211_scan_completed(&local->hw, aborted, hw_scan);
 out:
 	mutex_unlock(&local->mtx);
 }
@@ -791,7 +817,6 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
 void ieee80211_scan_cancel(struct ieee80211_local *local)
 {
 	bool abortscan;
-	bool finish = false;
 
 	/*
 	 * We are only canceling software scan, or deferred scan that was not
@@ -811,14 +836,17 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
 
 	mutex_lock(&local->mtx);
 	abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
-	if (abortscan)
-		finish = __ieee80211_scan_completed(&local->hw, true, false);
-	mutex_unlock(&local->mtx);
-
 	if (abortscan) {
-		/* The scan is canceled, but stop work from being pending */
-		cancel_delayed_work_sync(&local->scan_work);
+		/*
+		 * The scan is canceled, but stop work from being pending.
+		 *
+		 * If the work is currently running, it must be blocked on
+		 * the mutex, but we'll set scan_sdata = NULL and it'll
+		 * simply exit once it acquires the mutex.
+		 */
+		cancel_delayed_work(&local->scan_work);
+		/* and clean up */
+		__ieee80211_scan_completed(&local->hw, true, false);
 	}
-	if (finish)
-		__ieee80211_scan_completed_finish(&local->hw, false);
+	mutex_unlock(&local->mtx);
 }
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index c426504..5a11078 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -899,7 +899,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
 	struct ieee80211_local *local = sdata->local;
 	int sent, buffered;
 
-	drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
+	if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
+		drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
 
 	if (!skb_queue_empty(&sta->ps_tx_buf))
 		sta_info_clear_tim_bit(sta);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index bbdd2a8..5768114 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -82,6 +82,7 @@ enum ieee80211_sta_info_flags {
  * @state: session state (see above)
  * @stop_initiator: initiator of a session stop
  * @tx_stop: TX DelBA frame when stopping
+ * @buf_size: reorder buffer size at receiver
  *
  * This structure's lifetime is managed by RCU, assignments to
  * the array holding it must hold the aggregation mutex.
@@ -101,6 +102,7 @@ struct tid_ampdu_tx {
 	u8 dialog_token;
 	u8 stop_initiator;
 	bool tx_stop;
+	u8 buf_size;
 };
 
 /**
@@ -207,6 +209,8 @@ enum plink_state {
  * @rate_ctrl_priv: rate control private per-STA pointer
  * @last_tx_rate: rate used for last transmit, to report to userspace as
  *	"the" transmit rate
+ * @last_rx_rate_idx: rx status rate index of the last data packet
+ * @last_rx_rate_flag: rx status flag of the last data packet
  * @lock: used for locking all fields that require locking, see comments
  *	in the header file.
  * @flaglock: spinlock for flags accesses
@@ -309,6 +313,8 @@ struct sta_info {
 	unsigned long tx_bytes;
 	unsigned long tx_fragments;
 	struct ieee80211_tx_rate last_tx_rate;
+	int last_rx_rate_idx;
+	int last_rx_rate_flag;
 	u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
 
 	/*
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 071ac95..b936dd2 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -98,6 +98,10 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
 	 *  (b) always process RX events before TX status events if ordering
 	 *      can be unknown, for example with different interrupt status
 	 *	bits.
+	 *  (c) if PS mode transitions are manual (i.e. the flag
+	 *      %IEEE80211_HW_AP_LINK_PS is set), always process PS state
+	 *      changes before calling TX status events if ordering can be
+	 *	unknown.
 	 */
 	if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
 	    skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
@@ -314,8 +318,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 		if (info->flags & IEEE80211_TX_STAT_ACK) {
 			local->ps_sdata->u.mgd.flags |=
 					IEEE80211_STA_NULLFUNC_ACKED;
-			ieee80211_queue_work(&local->hw,
-					&local->dynamic_ps_enable_work);
 		} else
 			mod_timer(&local->dynamic_ps_timer, jiffies +
 					msecs_to_jiffies(10));
@@ -339,6 +341,10 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
 			cookie = local->hw_roc_cookie ^ 2;
 			local->hw_roc_skb_for_status = NULL;
 		}
+
+		if (cookie == local->hw_offchan_tx_cookie)
+			local->hw_offchan_tx_cookie = 0;
+
 		cfg80211_mgmt_tx_status(
 			skb->dev, cookie, skb->data, skb->len,
 			!!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b0beaa5..ce4596e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -33,10 +33,6 @@
 #include "wme.h"
 #include "rate.h"
 
-#define IEEE80211_TX_OK		0
-#define IEEE80211_TX_AGAIN	1
-#define IEEE80211_TX_PENDING	2
-
 /* misc utils */
 
 static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
@@ -173,7 +169,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr,
 	return cpu_to_le16(dur);
 }
 
-static int inline is_ieee80211_device(struct ieee80211_local *local,
+static inline int is_ieee80211_device(struct ieee80211_local *local,
 				      struct net_device *dev)
 {
 	return local == wdev_priv(dev->ieee80211_ptr);
@@ -236,6 +232,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_QUEUE_STOP_REASON_PS);
+		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
 		ieee80211_queue_work(&local->hw,
 				     &local->dynamic_ps_disable_work);
 	}
@@ -257,7 +254,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
 	if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
 		return TX_CONTINUE;
 
-	if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
+	if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
+	    test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
 	    !ieee80211_is_probe_req(hdr->frame_control) &&
 	    !ieee80211_is_nullfunc(hdr->frame_control))
 		/*
@@ -1283,16 +1281,17 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
 	return TX_CONTINUE;
 }
 
-static int __ieee80211_tx(struct ieee80211_local *local,
-			  struct sk_buff **skbp,
-			  struct sta_info *sta,
-			  bool txpending)
+/*
+ * Returns false if the frame couldn't be transmitted but was queued instead.
+ */
+static bool __ieee80211_tx(struct ieee80211_local *local, struct sk_buff **skbp,
+			   struct sta_info *sta, bool txpending)
 {
 	struct sk_buff *skb = *skbp, *next;
 	struct ieee80211_tx_info *info;
 	struct ieee80211_sub_if_data *sdata;
 	unsigned long flags;
-	int ret, len;
+	int len;
 	bool fragm = false;
 
 	while (skb) {
@@ -1300,13 +1299,37 @@ static int __ieee80211_tx(struct ieee80211_local *local,
 		__le16 fc;
 
 		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-		ret = IEEE80211_TX_OK;
 		if (local->queue_stop_reasons[q] ||
-		    (!txpending && !skb_queue_empty(&local->pending[q])))
-			ret = IEEE80211_TX_PENDING;
+		    (!txpending && !skb_queue_empty(&local->pending[q]))) {
+			/*
+			 * Since queue is stopped, queue up frames for later
+			 * transmission from the tx-pending tasklet when the
+			 * queue is woken again.
+			 */
+
+			do {
+				next = skb->next;
+				skb->next = NULL;
+				/*
+				 * NB: If txpending is true, next must already
+				 * be NULL since we must've gone through this
+				 * loop before already; therefore we can just
+				 * queue the frame to the head without worrying
+				 * about reordering of fragments.
+				 */
+				if (unlikely(txpending))
+					__skb_queue_head(&local->pending[q],
+							 skb);
+				else
+					__skb_queue_tail(&local->pending[q],
+							 skb);
+			} while ((skb = next));
+
+			spin_unlock_irqrestore(&local->queue_stop_reason_lock,
+					       flags);
+			return false;
+		}
 		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
-		if (ret != IEEE80211_TX_OK)
-			return ret;
 
 		info = IEEE80211_SKB_CB(skb);
 
@@ -1341,15 +1364,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
 			info->control.sta = NULL;
 
 		fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
-		ret = drv_tx(local, skb);
-		if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) {
-			dev_kfree_skb(skb);
-			ret = NETDEV_TX_OK;
-		}
-		if (ret != NETDEV_TX_OK) {
-			info->control.vif = &sdata->vif;
-			return IEEE80211_TX_AGAIN;
-		}
+		drv_tx(local, skb);
 
 		ieee80211_tpt_led_trig_tx(local, fc, len);
 		*skbp = skb = next;
@@ -1357,7 +1372,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
 		fragm = true;
 	}
 
-	return IEEE80211_TX_OK;
+	return true;
 }
 
 /*
@@ -1394,7 +1409,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 	/* handlers after fragment must be aware of tx info fragmentation! */
 	CALL_TXH(ieee80211_tx_h_stats);
 	CALL_TXH(ieee80211_tx_h_encrypt);
-	CALL_TXH(ieee80211_tx_h_calculate_duration);
+	if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
+		CALL_TXH(ieee80211_tx_h_calculate_duration);
 #undef CALL_TXH
 
  txh_done:
@@ -1416,23 +1432,24 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
 	return 0;
 }
 
-static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
+/*
+ * Returns false if the frame couldn't be transmitted but was queued instead.
+ */
+static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
 			 struct sk_buff *skb, bool txpending)
 {
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_tx_data tx;
 	ieee80211_tx_result res_prepare;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct sk_buff *next;
-	unsigned long flags;
-	int ret, retries;
 	u16 queue;
+	bool result = true;
 
 	queue = skb_get_queue_mapping(skb);
 
 	if (unlikely(skb->len < 10)) {
 		dev_kfree_skb(skb);
-		return;
+		return true;
 	}
 
 	rcu_read_lock();
@@ -1442,85 +1459,19 @@ static void ieee80211_tx(struct ieee80211_sub_if_data *sdata,
 
 	if (unlikely(res_prepare == TX_DROP)) {
 		dev_kfree_skb(skb);
-		rcu_read_unlock();
-		return;
+		goto out;
 	} else if (unlikely(res_prepare == TX_QUEUED)) {
-		rcu_read_unlock();
-		return;
+		goto out;
 	}
 
 	tx.channel = local->hw.conf.channel;
 	info->band = tx.channel->band;
 
-	if (invoke_tx_handlers(&tx))
-		goto out;
-
-	retries = 0;
- retry:
-	ret = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
-	switch (ret) {
-	case IEEE80211_TX_OK:
-		break;
-	case IEEE80211_TX_AGAIN:
-		/*
-		 * Since there are no fragmented frames on A-MPDU
-		 * queues, there's no reason for a driver to reject
-		 * a frame there, warn and drop it.
-		 */
-		if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
-			goto drop;
-		/* fall through */
-	case IEEE80211_TX_PENDING:
-		skb = tx.skb;
-
-		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
-
-		if (local->queue_stop_reasons[queue] ||
-		    !skb_queue_empty(&local->pending[queue])) {
-			/*
-			 * if queue is stopped, queue up frames for later
-			 * transmission from the tasklet
-			 */
-			do {
-				next = skb->next;
-				skb->next = NULL;
-				if (unlikely(txpending))
-					__skb_queue_head(&local->pending[queue],
-							 skb);
-				else
-					__skb_queue_tail(&local->pending[queue],
-							 skb);
-			} while ((skb = next));
-
-			spin_unlock_irqrestore(&local->queue_stop_reason_lock,
-					       flags);
-		} else {
-			/*
-			 * otherwise retry, but this is a race condition or
-			 * a driver bug (which we warn about if it persists)
-			 */
-			spin_unlock_irqrestore(&local->queue_stop_reason_lock,
-					       flags);
-
-			retries++;
-			if (WARN(retries > 10, "tx refused but queue active\n"))
-				goto drop;
-			goto retry;
-		}
-	}
+	if (!invoke_tx_handlers(&tx))
+		result = __ieee80211_tx(local, &tx.skb, tx.sta, txpending);
  out:
 	rcu_read_unlock();
-	return;
-
- drop:
-	rcu_read_unlock();
-
-	skb = tx.skb;
-	while (skb) {
-		next = skb->next;
-		dev_kfree_skb(skb);
-		skb = next;
-	}
+	return result;
 }
 
 /* device xmit handlers */
@@ -1750,7 +1701,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	__le16 fc;
 	struct ieee80211_hdr hdr;
 	struct ieee80211s_hdr mesh_hdr __maybe_unused;
-	struct mesh_path *mppath = NULL;
+	struct mesh_path __maybe_unused *mppath = NULL;
 	const u8 *encaps_data;
 	int encaps_len, skip_header_bytes;
 	int nh_pos, h_pos;
@@ -1815,19 +1766,19 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 			mppath = mpp_path_lookup(skb->data, sdata);
 
 		/*
-		 * Do not use address extension, if it is a packet from
-		 * the same interface and the destination is not being
-		 * proxied by any other mest point.
+		 * Use address extension if it is a packet from
+		 * another interface or if we know the destination
+		 * is being proxied by a portal (i.e. portal address
+		 * differs from proxied address)
 		 */
 		if (compare_ether_addr(sdata->vif.addr,
 				       skb->data + ETH_ALEN) == 0 &&
-		    (!mppath || !compare_ether_addr(mppath->mpp, skb->data))) {
+		    !(mppath && compare_ether_addr(mppath->mpp, skb->data))) {
 			hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
 					skb->data, skb->data + ETH_ALEN);
 			meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
 					sdata, NULL, NULL);
 		} else {
-			/* packet from other interface */
 			int is_mesh_mcast = 1;
 			const u8 *mesh_da;
 
@@ -2067,6 +2018,11 @@ void ieee80211_clear_tx_pending(struct ieee80211_local *local)
 		skb_queue_purge(&local->pending[i]);
 }
 
+/*
+ * Returns false if the frame couldn't be transmitted but was queued instead,
+ * which in this case means re-queued -- take as an indication to stop sending
+ * more pending frames.
+ */
 static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
 				     struct sk_buff *skb)
 {
@@ -2074,20 +2030,17 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
 	struct ieee80211_sub_if_data *sdata;
 	struct sta_info *sta;
 	struct ieee80211_hdr *hdr;
-	int ret;
-	bool result = true;
+	bool result;
 
 	sdata = vif_to_sdata(info->control.vif);
 
 	if (info->flags & IEEE80211_TX_INTFL_NEED_TXPROCESSING) {
-		ieee80211_tx(sdata, skb, true);
+		result = ieee80211_tx(sdata, skb, true);
 	} else {
 		hdr = (struct ieee80211_hdr *)skb->data;
 		sta = sta_info_get(sdata, hdr->addr1);
 
-		ret = __ieee80211_tx(local, &skb, sta, true);
-		if (ret != IEEE80211_TX_OK)
-			result = false;
+		result = __ieee80211_tx(local, &skb, sta, true);
 	}
 
 	return result;
@@ -2129,8 +2082,6 @@ void ieee80211_tx_pending(unsigned long data)
 						flags);
 
 			txok = ieee80211_tx_pending_skb(local, skb);
-			if (!txok)
-				__skb_queue_head(&local->pending[i], skb);
 			spin_lock_irqsave(&local->queue_stop_reason_lock,
 					  flags);
 			if (!txok)
@@ -2178,6 +2129,8 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
 	if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf))
 		aid0 = 1;
 
+	bss->dtim_bc_mc = aid0 == 1;
+
 	if (have_bits) {
 		/* Find largest even number N1 so that bits numbered 1 through
 		 * (N1 x 8) - 1 in the bitmap are 0 and number N2 so that bits
@@ -2241,7 +2194,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
 		ap = &sdata->u.ap;
 		beacon = rcu_dereference(ap->beacon);
-		if (ap && beacon) {
+		if (beacon) {
 			/*
 			 * headroom, head length,
 			 * tail length and maximum TIM length
@@ -2302,6 +2255,11 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 		struct ieee80211_mgmt *mgmt;
 		u8 *pos;
 
+#ifdef CONFIG_MAC80211_MESH
+		if (!sdata->u.mesh.mesh_id_len)
+			goto out;
+#endif
+
 		/* headroom, head length, tail length and maximum TIM length */
 		skb = dev_alloc_skb(local->tx_headroom + 400 +
 				sdata->u.mesh.vendor_ie_len);
@@ -2543,7 +2501,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
 	if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head)
 		goto out;
 
-	if (bss->dtim_count != 0)
+	if (bss->dtim_count != 0 || !bss->dtim_bc_mc)
 		goto out; /* send buffered bc/mc only after DTIM beacon */
 
 	while (1) {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d036597..556647a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -986,12 +986,6 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 		u16 cap = sband->ht_cap.cap;
 		__le16 tmp;
 
-		if (ieee80211_disable_40mhz_24ghz &&
-		    sband->band == IEEE80211_BAND_2GHZ) {
-			cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-			cap &= ~IEEE80211_HT_CAP_SGI_40;
-		}
-
 		*pos++ = WLAN_EID_HT_CAPABILITY;
 		*pos++ = sizeof(struct ieee80211_ht_cap);
 		memset(pos, 0, sizeof(struct ieee80211_ht_cap));
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 36305e0..e73c8ca 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -30,7 +30,6 @@
 #define IEEE80211_AUTH_MAX_TRIES 3
 #define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
 #define IEEE80211_ASSOC_MAX_TRIES 3
-#define IEEE80211_MAX_PROBE_TRIES 5
 
 enum work_action {
 	WORK_ACT_MISMATCH,
@@ -126,12 +125,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
 
 	/* determine capability flags */
 
-	if (ieee80211_disable_40mhz_24ghz &&
-	    sband->band == IEEE80211_BAND_2GHZ) {
-		cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
-		cap &= ~IEEE80211_HT_CAP_SGI_40;
-	}
-
 	switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
 	case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
 		if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
@@ -874,6 +867,44 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
 	kfree_skb(skb);
 }
 
+static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
+				       enum nl80211_channel_type oper_ct)
+{
+	switch (wk_ct) {
+	case NL80211_CHAN_NO_HT:
+		return true;
+	case NL80211_CHAN_HT20:
+		if (oper_ct != NL80211_CHAN_NO_HT)
+			return true;
+		return false;
+	case NL80211_CHAN_HT40MINUS:
+	case NL80211_CHAN_HT40PLUS:
+		return (wk_ct == oper_ct);
+	}
+	WARN_ON(1); /* shouldn't get here */
+	return false;
+}
+
+static enum nl80211_channel_type
+ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
+		  enum nl80211_channel_type oper_ct)
+{
+	switch (wk_ct) {
+	case NL80211_CHAN_NO_HT:
+		return oper_ct;
+	case NL80211_CHAN_HT20:
+		if (oper_ct != NL80211_CHAN_NO_HT)
+			return oper_ct;
+		return wk_ct;
+	case NL80211_CHAN_HT40MINUS:
+	case NL80211_CHAN_HT40PLUS:
+		return wk_ct;
+	}
+	WARN_ON(1); /* shouldn't get here */
+	return wk_ct;
+}
+
+
 static void ieee80211_work_timer(unsigned long data)
 {
 	struct ieee80211_local *local = (void *) data;
@@ -924,18 +955,52 @@ static void ieee80211_work_work(struct work_struct *work)
 		}
 
 		if (!started && !local->tmp_channel) {
+			bool on_oper_chan;
+			bool tmp_chan_changed = false;
+			bool on_oper_chan2;
+			enum nl80211_channel_type wk_ct;
+			on_oper_chan = ieee80211_cfg_on_oper_channel(local);
+
+			/* Work with existing channel type if possible. */
+			wk_ct = wk->chan_type;
+			if (wk->chan == local->hw.conf.channel)
+				wk_ct = ieee80211_calc_ct(wk->chan_type,
+						local->hw.conf.channel_type);
+
+			if (local->tmp_channel)
+				if ((local->tmp_channel != wk->chan) ||
+				    (local->tmp_channel_type != wk_ct))
+					tmp_chan_changed = true;
+
+			local->tmp_channel = wk->chan;
+			local->tmp_channel_type = wk_ct;
 			/*
-			 * TODO: could optimize this by leaving the
-			 *	 station vifs in awake mode if they
-			 *	 happen to be on the same channel as
-			 *	 the requested channel
+			 * Leave the station vifs in awake mode if they
+			 * happen to be on the same channel as
+			 * the requested channel.
 			 */
-			ieee80211_offchannel_stop_beaconing(local);
-			ieee80211_offchannel_stop_station(local);
+			on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
+			if (on_oper_chan != on_oper_chan2) {
+				if (on_oper_chan2) {
+					/* going off oper channel, PS too */
+					ieee80211_offchannel_stop_vifs(local,
+								       true);
+					ieee80211_hw_config(local, 0);
+				} else {
+					/* going on channel, but leave PS
+					 * off-channel. */
+					ieee80211_hw_config(local, 0);
+					ieee80211_offchannel_return(local,
+								    true,
+								    false);
+				}
+			} else if (tmp_chan_changed)
+				/* Still off-channel, but on some other
+				 * channel, so update hardware.
+				 * PS should already be off-channel.
+				 */
+				ieee80211_hw_config(local, 0);
 
-			local->tmp_channel = wk->chan;
-			local->tmp_channel_type = wk->chan_type;
-			ieee80211_hw_config(local, 0);
 			started = true;
 			wk->timeout = jiffies;
 		}
@@ -1005,15 +1070,34 @@ static void ieee80211_work_work(struct work_struct *work)
 			continue;
 		if (wk->chan != local->tmp_channel)
 			continue;
-		if (wk->chan_type != local->tmp_channel_type)
+		if (ieee80211_work_ct_coexists(wk->chan_type,
+					       local->tmp_channel_type))
 			continue;
 		remain_off_channel = true;
 	}
 
 	if (!remain_off_channel && local->tmp_channel) {
+		bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
 		local->tmp_channel = NULL;
-		ieee80211_hw_config(local, 0);
-		ieee80211_offchannel_return(local, true);
+		/* If tmp_channel wasn't operating channel, then
+		 * we need to go back on-channel.
+		 * NOTE:  If we can ever be here while scannning,
+		 * or if the hw_config() channel config logic changes,
+		 * then we may need to do a more thorough check to see if
+		 * we still need to do a hardware config.  Currently,
+		 * we cannot be here while scanning, however.
+		 */
+		if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
+			ieee80211_hw_config(local, 0);
+
+		/* At the least, we need to disable offchannel_ps,
+		 * so just go ahead and run the entire offchannel
+		 * return logic here.  We *could* skip enabling
+		 * beaconing if we were already on-oper-channel
+		 * as a future optimization.
+		 */
+		ieee80211_offchannel_return(local, true, true);
+
 		/* give connection some time to breathe */
 		run_again(local, jiffies + HZ/2);
 	}
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index bee230d..f1765de 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -26,13 +26,12 @@
 ieee80211_tx_result
 ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 {
-	u8 *data, *key, *mic, key_offset;
+	u8 *data, *key, *mic;
 	size_t data_len;
 	unsigned int hdrlen;
 	struct ieee80211_hdr *hdr;
 	struct sk_buff *skb = tx->skb;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	int authenticator;
 	int tail;
 
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -47,6 +46,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 	data = skb->data + hdrlen;
 	data_len = skb->len - hdrlen;
 
+	if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE)) {
+		/* Need to use software crypto for the test */
+		info->control.hw_key = NULL;
+	}
+
 	if (info->control.hw_key &&
 	    !(tx->flags & IEEE80211_TX_FRAGMENTED) &&
 	    !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
@@ -62,17 +66,11 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 		    skb_headroom(skb) < TKIP_IV_LEN))
 		return TX_DROP;
 
-#if 0
-	authenticator = fc & IEEE80211_FCTL_FROMDS; /* FIX */
-#else
-	authenticator = 1;
-#endif
-	key_offset = authenticator ?
-		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY :
-		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
-	key = &tx->key->conf.key[key_offset];
+	key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
 	mic = skb_put(skb, MICHAEL_MIC_LEN);
 	michael_mic(key, hdr, data, data_len, mic);
+	if (unlikely(info->flags & IEEE80211_TX_INTFL_TKIP_MIC_FAILURE))
+		mic[0]++;
 
 	return TX_CONTINUE;
 }
@@ -81,14 +79,13 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
 ieee80211_rx_result
 ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
 {
-	u8 *data, *key = NULL, key_offset;
+	u8 *data, *key = NULL;
 	size_t data_len;
 	unsigned int hdrlen;
 	u8 mic[MICHAEL_MIC_LEN];
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	int authenticator = 1, wpa_test = 0;
 
 	/* No way to verify the MIC if the hardware stripped it */
 	if (status->flag & RX_FLAG_MMIC_STRIPPED)
@@ -106,17 +103,9 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
 	data = skb->data + hdrlen;
 	data_len = skb->len - hdrlen - MICHAEL_MIC_LEN;
 
-#if 0
-	authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */
-#else
-	authenticator = 1;
-#endif
-	key_offset = authenticator ?
-		NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY :
-		NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
-	key = &rx->key->conf.key[key_offset];
+	key = &rx->key->conf.key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY];
 	michael_mic(key, hdr, data, data_len, mic);
-	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) {
+	if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0) {
 		if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
 			return RX_DROP_UNUSABLE;
 
@@ -208,7 +197,7 @@ ieee80211_rx_result
 ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 {
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
-	int hdrlen, res, hwaccel = 0, wpa_test = 0;
+	int hdrlen, res, hwaccel = 0;
 	struct ieee80211_key *key = rx->key;
 	struct sk_buff *skb = rx->skb;
 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
@@ -235,7 +224,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 					  hdr->addr1, hwaccel, rx->queue,
 					  &rx->tkip_iv32,
 					  &rx->tkip_iv16);
-	if (res != TKIP_DECRYPT_OK || wpa_test)
+	if (res != TKIP_DECRYPT_OK)
 		return RX_DROP_UNUSABLE;
 
 	/* Trim ICV */
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 1534f2b..c3f988a 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -85,6 +85,17 @@ config NF_CONNTRACK_EVENTS
 
 	  If unsure, say `N'.
 
+config NF_CONNTRACK_TIMESTAMP
+	bool  'Connection tracking timestamping'
+	depends on NETFILTER_ADVANCED
+	help
+	  This option enables support for connection tracking timestamping.
+	  This allows you to store the flow start-time and to obtain
+	  the flow-stop time (once it has been destroyed) via Connection
+	  tracking events.
+
+	  If unsure, say `N'.
+
 config NF_CT_PROTO_DCCP
 	tristate 'DCCP protocol connection tracking support (EXPERIMENTAL)'
 	depends on EXPERIMENTAL
@@ -185,9 +196,13 @@ config NF_CONNTRACK_IRC
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NF_CONNTRACK_BROADCAST
+	tristate
+
 config NF_CONNTRACK_NETBIOS_NS
 	tristate "NetBIOS name service protocol support"
 	depends on NETFILTER_ADVANCED
+	select NF_CONNTRACK_BROADCAST
 	help
 	  NetBIOS name service requests are sent as broadcast messages from an
 	  unprivileged port and responded to with unicast messages to the
@@ -204,6 +219,21 @@ config NF_CONNTRACK_NETBIOS_NS
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NF_CONNTRACK_SNMP
+	tristate "SNMP service protocol support"
+	depends on NETFILTER_ADVANCED
+	select NF_CONNTRACK_BROADCAST
+	help
+	  SNMP service requests are sent as broadcast messages from an
+	  unprivileged port and responded to with unicast messages to the
+	  same port. This make them hard to firewall properly because connection
+	  tracking doesn't deal with broadcasts. This helper tracks locally
+	  originating SNMP service requests and the corresponding
+	  responses. It relies on correct IP address configuration, specifically
+	  netmask and broadcast address.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NF_CONNTRACK_PPTP
 	tristate "PPtP protocol support"
 	depends on NETFILTER_ADVANCED
@@ -322,10 +352,32 @@ config NETFILTER_XT_CONNMARK
 	ctmark), similarly to the packet mark (nfmark). Using this
 	target and match, you can set and match on this mark.
 
+config NETFILTER_XT_SET
+	tristate 'set target and match support'
+	depends on IP_SET
+	depends on NETFILTER_ADVANCED
+	help
+	  This option adds the "SET" target and "set" match.
+
+	  Using this target and match, you can add/delete and match
+	  elements in the sets created by ipset(8).
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 # alphabetically ordered list of targets
 
 comment "Xtables targets"
 
+config NETFILTER_XT_TARGET_AUDIT
+	tristate "AUDIT target support"
+	depends on AUDIT
+	depends on NETFILTER_ADVANCED
+	---help---
+	  This option adds a 'AUDIT' target, which can be used to create
+	  audit records for packets dropped/accepted.
+
+	  To compileit as a module, choose M here. If unsure, say N.
+
 config NETFILTER_XT_TARGET_CHECKSUM
 	tristate "CHECKSUM target support"
 	depends on IP_NF_MANGLE || IP6_NF_MANGLE
@@ -477,6 +529,7 @@ config NETFILTER_XT_TARGET_NFLOG
 config NETFILTER_XT_TARGET_NFQUEUE
 	tristate '"NFQUEUE" target Support'
 	depends on NETFILTER_ADVANCED
+	select NETFILTER_NETLINK_QUEUE
 	help
 	  This target replaced the old obsolete QUEUE target.
 
@@ -596,6 +649,17 @@ config NETFILTER_XT_TARGET_TCPOPTSTRIP
 
 comment "Xtables matches"
 
+config NETFILTER_XT_MATCH_ADDRTYPE
+	tristate '"addrtype" address type match support'
+	depends on NETFILTER_ADVANCED
+	depends on (IPV6 || IPV6=n)
+	---help---
+	  This option allows you to match what routing thinks of an address,
+	  eg. UNICAST, LOCAL, BROADCAST, ...
+
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_MATCH_CLUSTER
 	tristate '"cluster" match support'
 	depends on NF_CONNTRACK
@@ -685,6 +749,15 @@ config NETFILTER_XT_MATCH_DCCP
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/kbuild/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_MATCH_DEVGROUP
+	tristate '"devgroup" match support'
+	depends on NETFILTER_ADVANCED
+	help
+	  This options adds a `devgroup' match, which allows to match on the
+	  device group a network device is assigned to.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_DSCP
 	tristate '"dscp" and "tos" match support'
 	depends on NETFILTER_ADVANCED
@@ -886,7 +959,7 @@ config NETFILTER_XT_MATCH_RATEEST
 config NETFILTER_XT_MATCH_REALM
 	tristate  '"realm" match support'
 	depends on NETFILTER_ADVANCED
-	select NET_CLS_ROUTE
+	select IP_ROUTE_CLASSID
 	help
 	  This option adds a `realm' match, which allows you to use the realm
 	  key from the routing subsystem inside iptables.
@@ -1011,4 +1084,6 @@ endif # NETFILTER_XTABLES
 
 endmenu
 
+source "net/netfilter/ipset/Kconfig"
+
 source "net/netfilter/ipvs/Kconfig"
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 441050f..1a02853 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -1,6 +1,7 @@
 netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
 
 nf_conntrack-y	:= nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o
+nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o
 nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
 
 obj-$(CONFIG_NETFILTER) = netfilter.o
@@ -28,7 +29,9 @@ obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
 obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
 obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o
 obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o
+obj-$(CONFIG_NF_CONNTRACK_BROADCAST) += nf_conntrack_broadcast.o
 obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o
+obj-$(CONFIG_NF_CONNTRACK_SNMP) += nf_conntrack_snmp.o
 obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o
 obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
@@ -43,8 +46,10 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 # combos
 obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o
 obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o
+obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o
 
 # targets
+obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CHECKSUM) += xt_CHECKSUM.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
@@ -65,6 +70,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_IDLETIMER) += xt_IDLETIMER.o
 
 # matches
+obj-$(CONFIG_NETFILTER_XT_MATCH_ADDRTYPE) += xt_addrtype.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CLUSTER) += xt_cluster.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
@@ -72,6 +78,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_CONNLIMIT) += xt_connlimit.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_DEVGROUP) += xt_devgroup.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o
@@ -101,5 +108,8 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o
 
+# ipset
+obj-$(CONFIG_IP_SET) += ipset/
+
 # IPVS
 obj-$(CONFIG_IP_VS) += ipvs/
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 4aa614b..899b71c 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -176,13 +176,21 @@ next_hook:
 		ret = 1;
 	} else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {
 		kfree_skb(skb);
-		ret = -(verdict >> NF_VERDICT_BITS);
+		ret = NF_DROP_GETERR(verdict);
 		if (ret == 0)
 			ret = -EPERM;
 	} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
-		if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
-			      verdict >> NF_VERDICT_BITS))
-			goto next_hook;
+		ret = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
+			       verdict >> NF_VERDICT_QBITS);
+		if (ret < 0) {
+			if (ret == -ECANCELED)
+				goto next_hook;
+			if (ret == -ESRCH &&
+			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
+				goto next_hook;
+			kfree_skb(skb);
+		}
+		ret = 0;
 	}
 	rcu_read_unlock();
 	return ret;
@@ -215,7 +223,7 @@ EXPORT_SYMBOL(skb_make_writable);
 /* This does not belong here, but locally generated errors need it if connection
    tracking in use: without this, connection may not be in hash table, and hence
    manufactured ICMP or RST packets will not be associated with it. */
-void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
+void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu __read_mostly;
 EXPORT_SYMBOL(ip_ct_attach);
 
 void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
@@ -232,7 +240,7 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(nf_ct_attach);
 
-void (*nf_ct_destroy)(struct nf_conntrack *);
+void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
 EXPORT_SYMBOL(nf_ct_destroy);
 
 void nf_conntrack_destroy(struct nf_conntrack *nfct)
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig
new file mode 100644
index 0000000..2c5b348
--- /dev/null
+++ b/net/netfilter/ipset/Kconfig
@@ -0,0 +1,122 @@
+menuconfig IP_SET
+	tristate "IP set support"
+	depends on INET && NETFILTER
+	depends on NETFILTER_NETLINK
+	help
+	  This option adds IP set support to the kernel.
+	  In order to define and use the sets, you need the userspace utility
+	  ipset(8). You can use the sets in netfilter via the "set" match
+	  and "SET" target.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+if IP_SET
+
+config IP_SET_MAX
+	int "Maximum number of IP sets"
+	default 256
+	range 2 65534
+	depends on IP_SET
+	help
+	  You can define here default value of the maximum number 
+	  of IP sets for the kernel.
+
+	  The value can be overriden by the 'max_sets' module
+	  parameter of the 'ip_set' module.
+
+config IP_SET_BITMAP_IP
+	tristate "bitmap:ip set support"
+	depends on IP_SET
+	help
+	  This option adds the bitmap:ip set type support, by which one
+	  can store IPv4 addresses (or network addresse) from a range.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_BITMAP_IPMAC
+	tristate "bitmap:ip,mac set support"
+	depends on IP_SET
+	help
+	  This option adds the bitmap:ip,mac set type support, by which one
+	  can store IPv4 address and (source) MAC address pairs from a range.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_BITMAP_PORT
+	tristate "bitmap:port set support"
+	depends on IP_SET
+	help
+	  This option adds the bitmap:port set type support, by which one
+	  can store TCP/UDP port numbers from a range.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_HASH_IP
+	tristate "hash:ip set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:ip set type support, by which one
+	  can store arbitrary IPv4 or IPv6 addresses (or network addresses)
+	  in a set.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_HASH_IPPORT
+	tristate "hash:ip,port set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:ip,port set type support, by which one
+	  can store IPv4/IPv6 address and protocol/port pairs.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_HASH_IPPORTIP
+	tristate "hash:ip,port,ip set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:ip,port,ip set type support, by which
+	  one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv6
+	  address triples in a set.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_HASH_IPPORTNET
+	tristate "hash:ip,port,net set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:ip,port,net set type support, by which
+	  one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv6
+	  network address/prefix triples in a set.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_HASH_NET
+	tristate "hash:net set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:net set type support, by which
+	  one can store IPv4/IPv6 network address/prefix elements in a set.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_HASH_NETPORT
+	tristate "hash:net,port set support"
+	depends on IP_SET
+	help
+	  This option adds the hash:net,port set type support, by which
+	  one can store IPv4/IPv6 network address/prefix and
+	  protocol/port pairs as elements in a set.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config IP_SET_LIST_SET
+	tristate "list:set set support"
+	depends on IP_SET
+	help
+	  This option adds the list:set set type support. In this
+	  kind of set one can store the name of other sets and it forms
+	  an ordered union of the member sets.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+endif # IP_SET
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile
new file mode 100644
index 0000000..5adbdab
--- /dev/null
+++ b/net/netfilter/ipset/Makefile
@@ -0,0 +1,24 @@
+#
+# Makefile for the ipset modules
+#
+
+ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o
+
+# ipset core
+obj-$(CONFIG_IP_SET) += ip_set.o
+
+# bitmap types
+obj-$(CONFIG_IP_SET_BITMAP_IP) += ip_set_bitmap_ip.o
+obj-$(CONFIG_IP_SET_BITMAP_IPMAC) += ip_set_bitmap_ipmac.o
+obj-$(CONFIG_IP_SET_BITMAP_PORT) += ip_set_bitmap_port.o
+
+# hash types
+obj-$(CONFIG_IP_SET_HASH_IP) += ip_set_hash_ip.o
+obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o
+obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o
+obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
+obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
+obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
+
+# list types
+obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
new file mode 100644
index 0000000..bca9699
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -0,0 +1,587 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ *                         Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the bitmap:ip type */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/netlink.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <net/netlink.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_bitmap.h>
+#define IP_SET_BITMAP_TIMEOUT
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("bitmap:ip type of IP sets");
+MODULE_ALIAS("ip_set_bitmap:ip");
+
+/* Type structure */
+struct bitmap_ip {
+	void *members;		/* the set members */
+	u32 first_ip;		/* host byte order, included in range */
+	u32 last_ip;		/* host byte order, included in range */
+	u32 elements;		/* number of max elements in the set */
+	u32 hosts;		/* number of hosts in a subnet */
+	size_t memsize;		/* members size */
+	u8 netmask;		/* subnet netmask */
+	u32 timeout;		/* timeout parameter */
+	struct timer_list gc;	/* garbage collection */
+};
+
+/* Base variant */
+
+static inline u32
+ip_to_id(const struct bitmap_ip *m, u32 ip)
+{
+	return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts;
+}
+
+static int
+bitmap_ip_test(struct ip_set *set, void *value, u32 timeout)
+{
+	const struct bitmap_ip *map = set->data;
+	u16 id = *(u16 *)value;
+
+	return !!test_bit(id, map->members);
+}
+
+static int
+bitmap_ip_add(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ip *map = set->data;
+	u16 id = *(u16 *)value;
+
+	if (test_and_set_bit(id, map->members))
+		return -IPSET_ERR_EXIST;
+
+	return 0;
+}
+
+static int
+bitmap_ip_del(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ip *map = set->data;
+	u16 id = *(u16 *)value;
+
+	if (!test_and_clear_bit(id, map->members))
+		return -IPSET_ERR_EXIST;
+
+	return 0;
+}
+
+static int
+bitmap_ip_list(const struct ip_set *set,
+	       struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct bitmap_ip *map = set->data;
+	struct nlattr *atd, *nested;
+	u32 id, first = cb->args[2];
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	for (; cb->args[2] < map->elements; cb->args[2]++) {
+		id = cb->args[2];
+		if (!test_bit(id, map->members))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, atd);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
+				htonl(map->first_ip + id * map->hosts));
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, atd);
+	if (unlikely(id == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+/* Timeout variant */
+
+static int
+bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout)
+{
+	const struct bitmap_ip *map = set->data;
+	const unsigned long *members = map->members;
+	u16 id = *(u16 *)value;
+
+	return ip_set_timeout_test(members[id]);
+}
+
+static int
+bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ip *map = set->data;
+	unsigned long *members = map->members;
+	u16 id = *(u16 *)value;
+
+	if (ip_set_timeout_test(members[id]))
+		return -IPSET_ERR_EXIST;
+
+	members[id] = ip_set_timeout_set(timeout);
+
+	return 0;
+}
+
+static int
+bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ip *map = set->data;
+	unsigned long *members = map->members;
+	u16 id = *(u16 *)value;
+	int ret = -IPSET_ERR_EXIST;
+
+	if (ip_set_timeout_test(members[id]))
+		ret = 0;
+
+	members[id] = IPSET_ELEM_UNSET;
+	return ret;
+}
+
+static int
+bitmap_ip_tlist(const struct ip_set *set,
+		struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct bitmap_ip *map = set->data;
+	struct nlattr *adt, *nested;
+	u32 id, first = cb->args[2];
+	const unsigned long *members = map->members;
+
+	adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!adt)
+		return -EMSGSIZE;
+	for (; cb->args[2] < map->elements; cb->args[2]++) {
+		id = cb->args[2];
+		if (!ip_set_timeout_test(members[id]))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, adt);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
+				htonl(map->first_ip + id * map->hosts));
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+			      htonl(ip_set_timeout_get(members[id])));
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, adt);
+
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, adt);
+	if (unlikely(id == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+static int
+bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
+	       enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	struct bitmap_ip *map = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	u32 ip;
+
+	ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	ip = ip_to_id(map, ip);
+
+	return adtfn(set, &ip, map->timeout);
+}
+
+static int
+bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
+	       enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	struct bitmap_ip *map = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	u32 timeout = map->timeout;
+	u32 ip, ip_to, id;
+	int ret = 0;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
+	if (ret)
+		return ret;
+
+	if (ip < map->first_ip || ip > map->last_ip)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(map->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST) {
+		id = ip_to_id(map, ip);
+		return adtfn(set, &id, timeout);
+	}
+
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip > ip_to) {
+			swap(ip, ip_to);
+			if (ip < map->first_ip)
+				return -IPSET_ERR_BITMAP_RANGE;
+		}
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr > 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		ip &= ip_set_hostmask(cidr);
+		ip_to = ip | ~ip_set_hostmask(cidr);
+	} else
+		ip_to = ip;
+
+	if (ip_to > map->last_ip)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	for (; !before(ip_to, ip); ip += map->hosts) {
+		id = ip_to_id(map, ip);
+		ret = adtfn(set, &id, timeout);;
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+static void
+bitmap_ip_destroy(struct ip_set *set)
+{
+	struct bitmap_ip *map = set->data;
+
+	if (with_timeout(map->timeout))
+		del_timer_sync(&map->gc);
+
+	ip_set_free(map->members);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void
+bitmap_ip_flush(struct ip_set *set)
+{
+	struct bitmap_ip *map = set->data;
+
+	memset(map->members, 0, map->memsize);
+}
+
+static int
+bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
+{
+	const struct bitmap_ip *map = set->data;
+	struct nlattr *nested;
+
+	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+	if (!nested)
+		goto nla_put_failure;
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
+	if (map->netmask != 32)
+		NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
+	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
+		      htonl(atomic_read(&set->ref) - 1));
+	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
+		      htonl(sizeof(*map) + map->memsize));
+	if (with_timeout(map->timeout))
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
+	ipset_nest_end(skb, nested);
+
+	return 0;
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static bool
+bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct bitmap_ip *x = a->data;
+	const struct bitmap_ip *y = b->data;
+
+	return x->first_ip == y->first_ip &&
+	       x->last_ip == y->last_ip &&
+	       x->netmask == y->netmask &&
+	       x->timeout == y->timeout;
+}
+
+static const struct ip_set_type_variant bitmap_ip = {
+	.kadt	= bitmap_ip_kadt,
+	.uadt	= bitmap_ip_uadt,
+	.adt	= {
+		[IPSET_ADD] = bitmap_ip_add,
+		[IPSET_DEL] = bitmap_ip_del,
+		[IPSET_TEST] = bitmap_ip_test,
+	},
+	.destroy = bitmap_ip_destroy,
+	.flush	= bitmap_ip_flush,
+	.head	= bitmap_ip_head,
+	.list	= bitmap_ip_list,
+	.same_set = bitmap_ip_same_set,
+};
+
+static const struct ip_set_type_variant bitmap_tip = {
+	.kadt	= bitmap_ip_kadt,
+	.uadt	= bitmap_ip_uadt,
+	.adt	= {
+		[IPSET_ADD] = bitmap_ip_tadd,
+		[IPSET_DEL] = bitmap_ip_tdel,
+		[IPSET_TEST] = bitmap_ip_ttest,
+	},
+	.destroy = bitmap_ip_destroy,
+	.flush	= bitmap_ip_flush,
+	.head	= bitmap_ip_head,
+	.list	= bitmap_ip_tlist,
+	.same_set = bitmap_ip_same_set,
+};
+
+static void
+bitmap_ip_gc(unsigned long ul_set)
+{
+	struct ip_set *set = (struct ip_set *) ul_set;
+	struct bitmap_ip *map = set->data;
+	unsigned long *table = map->members;
+	u32 id;
+
+	/* We run parallel with other readers (test element)
+	 * but adding/deleting new entries is locked out */
+	read_lock_bh(&set->lock);
+	for (id = 0; id < map->elements; id++)
+		if (ip_set_timeout_expired(table[id]))
+			table[id] = IPSET_ELEM_UNSET;
+	read_unlock_bh(&set->lock);
+
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+static void
+bitmap_ip_gc_init(struct ip_set *set)
+{
+	struct bitmap_ip *map = set->data;
+
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = bitmap_ip_gc;
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+/* Create bitmap:ip type of sets */
+
+static bool
+init_map_ip(struct ip_set *set, struct bitmap_ip *map,
+	    u32 first_ip, u32 last_ip,
+	    u32 elements, u32 hosts, u8 netmask)
+{
+	map->members = ip_set_alloc(map->memsize);
+	if (!map->members)
+		return false;
+	map->first_ip = first_ip;
+	map->last_ip = last_ip;
+	map->elements = elements;
+	map->hosts = hosts;
+	map->netmask = netmask;
+	map->timeout = IPSET_NO_TIMEOUT;
+
+	set->data = map;
+	set->family = AF_INET;
+
+	return true;
+}
+
+static int
+bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	struct bitmap_ip *map;
+	u32 first_ip, last_ip, hosts, elements;
+	u8 netmask = 32;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
+		if (ret)
+			return ret;
+		if (first_ip > last_ip) {
+			u32 tmp = first_ip;
+
+			first_ip = last_ip;
+			last_ip = tmp;
+		}
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr >= 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		last_ip = first_ip | ~ip_set_hostmask(cidr);
+	} else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_NETMASK]) {
+		netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
+
+		if (netmask > 32)
+			return -IPSET_ERR_INVALID_NETMASK;
+
+		first_ip &= ip_set_hostmask(netmask);
+		last_ip |= ~ip_set_hostmask(netmask);
+	}
+
+	if (netmask == 32) {
+		hosts = 1;
+		elements = last_ip - first_ip + 1;
+	} else {
+		u8 mask_bits;
+		u32 mask;
+
+		mask = range_to_mask(first_ip, last_ip, &mask_bits);
+
+		if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
+		    netmask <= mask_bits)
+			return -IPSET_ERR_BITMAP_RANGE;
+
+		pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
+		hosts = 2 << (32 - netmask - 1);
+		elements = 2 << (netmask - mask_bits - 1);
+	}
+	if (elements > IPSET_BITMAP_MAX_RANGE + 1)
+		return -IPSET_ERR_BITMAP_RANGE_SIZE;
+
+	pr_debug("hosts %u, elements %u\n", hosts, elements);
+
+	map = kzalloc(sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		map->memsize = elements * sizeof(unsigned long);
+
+		if (!init_map_ip(set, map, first_ip, last_ip,
+				 elements, hosts, netmask)) {
+			kfree(map);
+			return -ENOMEM;
+		}
+
+		map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+		set->variant = &bitmap_tip;
+
+		bitmap_ip_gc_init(set);
+	} else {
+		map->memsize = bitmap_bytes(0, elements - 1);
+
+		if (!init_map_ip(set, map, first_ip, last_ip,
+				 elements, hosts, netmask)) {
+			kfree(map);
+			return -ENOMEM;
+		}
+
+		set->variant = &bitmap_ip;
+	}
+	return 0;
+}
+
+static struct ip_set_type bitmap_ip_type __read_mostly = {
+	.name		= "bitmap:ip",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP,
+	.dimension	= IPSET_DIM_ONE,
+	.family		= AF_INET,
+	.revision	= 0,
+	.create		= bitmap_ip_create,
+	.create_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_NETMASK]	= { .type = NLA_U8  },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+bitmap_ip_init(void)
+{
+	return ip_set_type_register(&bitmap_ip_type);
+}
+
+static void __exit
+bitmap_ip_fini(void)
+{
+	ip_set_type_unregister(&bitmap_ip_type);
+}
+
+module_init(bitmap_ip_init);
+module_exit(bitmap_ip_fini);
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
new file mode 100644
index 0000000..5e79017
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -0,0 +1,652 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ *                         Patrick Schaaf <bof@bof.de>
+ *			   Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/if_ether.h>
+#include <linux/netlink.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_bitmap.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
+MODULE_ALIAS("ip_set_bitmap:ip,mac");
+
+enum {
+	MAC_EMPTY,		/* element is not set */
+	MAC_FILLED,		/* element is set with MAC */
+	MAC_UNSET,		/* element is set, without MAC */
+};
+
+/* Type structure */
+struct bitmap_ipmac {
+	void *members;		/* the set members */
+	u32 first_ip;		/* host byte order, included in range */
+	u32 last_ip;		/* host byte order, included in range */
+	u32 timeout;		/* timeout value */
+	struct timer_list gc;	/* garbage collector */
+	size_t dsize;		/* size of element */
+};
+
+/* ADT structure for generic function args */
+struct ipmac {
+	u32 id;			/* id in array */
+	unsigned char *ether;	/* ethernet address */
+};
+
+/* Member element without and with timeout */
+
+struct ipmac_elem {
+	unsigned char ether[ETH_ALEN];
+	unsigned char match;
+} __attribute__ ((aligned));
+
+struct ipmac_telem {
+	unsigned char ether[ETH_ALEN];
+	unsigned char match;
+	unsigned long timeout;
+} __attribute__ ((aligned));
+
+static inline void *
+bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
+{
+	return (void *)((char *)map->members + id * map->dsize);
+}
+
+static inline bool
+bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
+{
+	const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
+
+	return ip_set_timeout_test(elem->timeout);
+}
+
+static inline bool
+bitmap_expired(const struct bitmap_ipmac *map, u32 id)
+{
+	const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
+
+	return ip_set_timeout_expired(elem->timeout);
+}
+
+static inline int
+bitmap_ipmac_exist(const struct ipmac_telem *elem)
+{
+	return elem->match == MAC_UNSET ||
+	       (elem->match == MAC_FILLED &&
+		!ip_set_timeout_expired(elem->timeout));
+}
+
+/* Base variant */
+
+static int
+bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
+{
+	const struct bitmap_ipmac *map = set->data;
+	const struct ipmac *data = value;
+	const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
+
+	switch (elem->match) {
+	case MAC_UNSET:
+		/* Trigger kernel to fill out the ethernet address */
+		return -EAGAIN;
+	case MAC_FILLED:
+		return data->ether == NULL ||
+		       compare_ether_addr(data->ether, elem->ether) == 0;
+	}
+	return 0;
+}
+
+static int
+bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ipmac *map = set->data;
+	const struct ipmac *data = value;
+	struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
+
+	switch (elem->match) {
+	case MAC_UNSET:
+		if (!data->ether)
+			/* Already added without ethernet address */
+			return -IPSET_ERR_EXIST;
+		/* Fill the MAC address */
+		memcpy(elem->ether, data->ether, ETH_ALEN);
+		elem->match = MAC_FILLED;
+		break;
+	case MAC_FILLED:
+		return -IPSET_ERR_EXIST;
+	case MAC_EMPTY:
+		if (data->ether) {
+			memcpy(elem->ether, data->ether, ETH_ALEN);
+			elem->match = MAC_FILLED;
+		} else
+			elem->match = MAC_UNSET;
+	}
+
+	return 0;
+}
+
+static int
+bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ipmac *map = set->data;
+	const struct ipmac *data = value;
+	struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
+
+	if (elem->match == MAC_EMPTY)
+		return -IPSET_ERR_EXIST;
+
+	elem->match = MAC_EMPTY;
+
+	return 0;
+}
+
+static int
+bitmap_ipmac_list(const struct ip_set *set,
+		  struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct bitmap_ipmac *map = set->data;
+	const struct ipmac_elem *elem;
+	struct nlattr *atd, *nested;
+	u32 id, first = cb->args[2];
+	u32 last = map->last_ip - map->first_ip;
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	for (; cb->args[2] <= last; cb->args[2]++) {
+		id = cb->args[2];
+		elem = bitmap_ipmac_elem(map, id);
+		if (elem->match == MAC_EMPTY)
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, atd);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
+				htonl(map->first_ip + id));
+		if (elem->match == MAC_FILLED)
+			NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
+				elem->ether);
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, atd);
+	if (unlikely(id == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+/* Timeout variant */
+
+static int
+bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
+{
+	const struct bitmap_ipmac *map = set->data;
+	const struct ipmac *data = value;
+	const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
+
+	switch (elem->match) {
+	case MAC_UNSET:
+		/* Trigger kernel to fill out the ethernet address */
+		return -EAGAIN;
+	case MAC_FILLED:
+		return (data->ether == NULL ||
+			compare_ether_addr(data->ether, elem->ether) == 0) &&
+		       !bitmap_expired(map, data->id);
+	}
+	return 0;
+}
+
+static int
+bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ipmac *map = set->data;
+	const struct ipmac *data = value;
+	struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
+
+	switch (elem->match) {
+	case MAC_UNSET:
+		if (!data->ether)
+			/* Already added without ethernet address */
+			return -IPSET_ERR_EXIST;
+		/* Fill the MAC address and activate the timer */
+		memcpy(elem->ether, data->ether, ETH_ALEN);
+		elem->match = MAC_FILLED;
+		if (timeout == map->timeout)
+			/* Timeout was not specified, get stored one */
+			timeout = elem->timeout;
+		elem->timeout = ip_set_timeout_set(timeout);
+		break;
+	case MAC_FILLED:
+		if (!bitmap_expired(map, data->id))
+			return -IPSET_ERR_EXIST;
+		/* Fall through */
+	case MAC_EMPTY:
+		if (data->ether) {
+			memcpy(elem->ether, data->ether, ETH_ALEN);
+			elem->match = MAC_FILLED;
+		} else
+			elem->match = MAC_UNSET;
+		/* If MAC is unset yet, we store plain timeout value
+		 * because the timer is not activated yet
+		 * and we can reuse it later when MAC is filled out,
+		 * possibly by the kernel */
+		elem->timeout = data->ether ? ip_set_timeout_set(timeout)
+					    : timeout;
+		break;
+	}
+
+	return 0;
+}
+
+static int
+bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_ipmac *map = set->data;
+	const struct ipmac *data = value;
+	struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
+
+	if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
+		return -IPSET_ERR_EXIST;
+
+	elem->match = MAC_EMPTY;
+
+	return 0;
+}
+
+static int
+bitmap_ipmac_tlist(const struct ip_set *set,
+		   struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct bitmap_ipmac *map = set->data;
+	const struct ipmac_telem *elem;
+	struct nlattr *atd, *nested;
+	u32 id, first = cb->args[2];
+	u32 timeout, last = map->last_ip - map->first_ip;
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	for (; cb->args[2] <= last; cb->args[2]++) {
+		id = cb->args[2];
+		elem = bitmap_ipmac_elem(map, id);
+		if (!bitmap_ipmac_exist(elem))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, atd);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
+				htonl(map->first_ip + id));
+		if (elem->match == MAC_FILLED)
+			NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
+				elem->ether);
+		timeout = elem->match == MAC_UNSET ? elem->timeout
+				: ip_set_timeout_get(elem->timeout);
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, atd);
+	return -EMSGSIZE;
+}
+
+static int
+bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
+		  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	struct bitmap_ipmac *map = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct ipmac data;
+
+	data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
+	if (data.id < map->first_ip || data.id > map->last_ip)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	/* Backward compatibility: we don't check the second flag */
+	if (skb_mac_header(skb) < skb->head ||
+	    (skb_mac_header(skb) + ETH_HLEN) > skb->data)
+		return -EINVAL;
+
+	data.id -= map->first_ip;
+	data.ether = eth_hdr(skb)->h_source;
+
+	return adtfn(set, &data, map->timeout);
+}
+
+static int
+bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
+		  enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct bitmap_ipmac *map = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct ipmac data;
+	u32 timeout = map->timeout;
+	int ret = 0;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id);
+	if (ret)
+		return ret;
+
+	if (data.id < map->first_ip || data.id > map->last_ip)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	if (tb[IPSET_ATTR_ETHER])
+		data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
+	else
+		data.ether = NULL;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(map->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	data.id -= map->first_ip;
+
+	ret = adtfn(set, &data, timeout);
+
+	return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+static void
+bitmap_ipmac_destroy(struct ip_set *set)
+{
+	struct bitmap_ipmac *map = set->data;
+
+	if (with_timeout(map->timeout))
+		del_timer_sync(&map->gc);
+
+	ip_set_free(map->members);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void
+bitmap_ipmac_flush(struct ip_set *set)
+{
+	struct bitmap_ipmac *map = set->data;
+
+	memset(map->members, 0,
+	       (map->last_ip - map->first_ip + 1) * map->dsize);
+}
+
+static int
+bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
+{
+	const struct bitmap_ipmac *map = set->data;
+	struct nlattr *nested;
+
+	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+	if (!nested)
+		goto nla_put_failure;
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
+	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
+		      htonl(atomic_read(&set->ref) - 1));
+	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
+		      htonl(sizeof(*map)
+			    + (map->last_ip - map->first_ip + 1) * map->dsize));
+	if (with_timeout(map->timeout))
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
+	ipset_nest_end(skb, nested);
+
+	return 0;
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static bool
+bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct bitmap_ipmac *x = a->data;
+	const struct bitmap_ipmac *y = b->data;
+
+	return x->first_ip == y->first_ip &&
+	       x->last_ip == y->last_ip &&
+	       x->timeout == y->timeout;
+}
+
+static const struct ip_set_type_variant bitmap_ipmac = {
+	.kadt	= bitmap_ipmac_kadt,
+	.uadt	= bitmap_ipmac_uadt,
+	.adt	= {
+		[IPSET_ADD] = bitmap_ipmac_add,
+		[IPSET_DEL] = bitmap_ipmac_del,
+		[IPSET_TEST] = bitmap_ipmac_test,
+	},
+	.destroy = bitmap_ipmac_destroy,
+	.flush	= bitmap_ipmac_flush,
+	.head	= bitmap_ipmac_head,
+	.list	= bitmap_ipmac_list,
+	.same_set = bitmap_ipmac_same_set,
+};
+
+static const struct ip_set_type_variant bitmap_tipmac = {
+	.kadt	= bitmap_ipmac_kadt,
+	.uadt	= bitmap_ipmac_uadt,
+	.adt	= {
+		[IPSET_ADD] = bitmap_ipmac_tadd,
+		[IPSET_DEL] = bitmap_ipmac_tdel,
+		[IPSET_TEST] = bitmap_ipmac_ttest,
+	},
+	.destroy = bitmap_ipmac_destroy,
+	.flush	= bitmap_ipmac_flush,
+	.head	= bitmap_ipmac_head,
+	.list	= bitmap_ipmac_tlist,
+	.same_set = bitmap_ipmac_same_set,
+};
+
+static void
+bitmap_ipmac_gc(unsigned long ul_set)
+{
+	struct ip_set *set = (struct ip_set *) ul_set;
+	struct bitmap_ipmac *map = set->data;
+	struct ipmac_telem *elem;
+	u32 id, last = map->last_ip - map->first_ip;
+
+	/* We run parallel with other readers (test element)
+	 * but adding/deleting new entries is locked out */
+	read_lock_bh(&set->lock);
+	for (id = 0; id <= last; id++) {
+		elem = bitmap_ipmac_elem(map, id);
+		if (elem->match == MAC_FILLED &&
+		    ip_set_timeout_expired(elem->timeout))
+			elem->match = MAC_EMPTY;
+	}
+	read_unlock_bh(&set->lock);
+
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+static void
+bitmap_ipmac_gc_init(struct ip_set *set)
+{
+	struct bitmap_ipmac *map = set->data;
+
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = bitmap_ipmac_gc;
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+/* Create bitmap:ip,mac type of sets */
+
+static bool
+init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
+	       u32 first_ip, u32 last_ip)
+{
+	map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize);
+	if (!map->members)
+		return false;
+	map->first_ip = first_ip;
+	map->last_ip = last_ip;
+	map->timeout = IPSET_NO_TIMEOUT;
+
+	set->data = map;
+	set->family = AF_INET;
+
+	return true;
+}
+
+static int
+bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
+		    u32 flags)
+{
+	u32 first_ip, last_ip, elements;
+	struct bitmap_ipmac *map;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
+		if (ret)
+			return ret;
+		if (first_ip > last_ip) {
+			u32 tmp = first_ip;
+
+			first_ip = last_ip;
+			last_ip = tmp;
+		}
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr >= 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		last_ip = first_ip | ~ip_set_hostmask(cidr);
+	} else
+		return -IPSET_ERR_PROTOCOL;
+
+	elements = last_ip - first_ip + 1;
+
+	if (elements > IPSET_BITMAP_MAX_RANGE + 1)
+		return -IPSET_ERR_BITMAP_RANGE_SIZE;
+
+	map = kzalloc(sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		map->dsize = sizeof(struct ipmac_telem);
+
+		if (!init_map_ipmac(set, map, first_ip, last_ip)) {
+			kfree(map);
+			return -ENOMEM;
+		}
+
+		map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = &bitmap_tipmac;
+
+		bitmap_ipmac_gc_init(set);
+	} else {
+		map->dsize = sizeof(struct ipmac_elem);
+
+		if (!init_map_ipmac(set, map, first_ip, last_ip)) {
+			kfree(map);
+			return -ENOMEM;
+		}
+		set->variant = &bitmap_ipmac;
+
+	}
+	return 0;
+}
+
+static struct ip_set_type bitmap_ipmac_type = {
+	.name		= "bitmap:ip,mac",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP | IPSET_TYPE_MAC,
+	.dimension	= IPSET_DIM_TWO,
+	.family		= AF_INET,
+	.revision	= 0,
+	.create		= bitmap_ipmac_create,
+	.create_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_ETHER]	= { .type = NLA_BINARY, .len  = ETH_ALEN },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+bitmap_ipmac_init(void)
+{
+	return ip_set_type_register(&bitmap_ipmac_type);
+}
+
+static void __exit
+bitmap_ipmac_fini(void)
+{
+	ip_set_type_unregister(&bitmap_ipmac_type);
+}
+
+module_init(bitmap_ipmac_init);
+module_exit(bitmap_ipmac_fini);
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
new file mode 100644
index 0000000..165f09b
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -0,0 +1,515 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the bitmap:port type */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/netlink.h>
+#include <linux/jiffies.h>
+#include <linux/timer.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_bitmap.h>
+#include <linux/netfilter/ipset/ip_set_getport.h>
+#define IP_SET_BITMAP_TIMEOUT
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("bitmap:port type of IP sets");
+MODULE_ALIAS("ip_set_bitmap:port");
+
+/* Type structure */
+struct bitmap_port {
+	void *members;		/* the set members */
+	u16 first_port;		/* host byte order, included in range */
+	u16 last_port;		/* host byte order, included in range */
+	size_t memsize;		/* members size */
+	u32 timeout;		/* timeout parameter */
+	struct timer_list gc;	/* garbage collection */
+};
+
+/* Base variant */
+
+static int
+bitmap_port_test(struct ip_set *set, void *value, u32 timeout)
+{
+	const struct bitmap_port *map = set->data;
+	u16 id = *(u16 *)value;
+
+	return !!test_bit(id, map->members);
+}
+
+static int
+bitmap_port_add(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_port *map = set->data;
+	u16 id = *(u16 *)value;
+
+	if (test_and_set_bit(id, map->members))
+		return -IPSET_ERR_EXIST;
+
+	return 0;
+}
+
+static int
+bitmap_port_del(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_port *map = set->data;
+	u16 id = *(u16 *)value;
+
+	if (!test_and_clear_bit(id, map->members))
+		return -IPSET_ERR_EXIST;
+
+	return 0;
+}
+
+static int
+bitmap_port_list(const struct ip_set *set,
+		 struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct bitmap_port *map = set->data;
+	struct nlattr *atd, *nested;
+	u16 id, first = cb->args[2];
+	u16 last = map->last_port - map->first_port;
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	for (; cb->args[2] <= last; cb->args[2]++) {
+		id = cb->args[2];
+		if (!test_bit(id, map->members))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, atd);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
+			      htons(map->first_port + id));
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, atd);
+	if (unlikely(id == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+/* Timeout variant */
+
+static int
+bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout)
+{
+	const struct bitmap_port *map = set->data;
+	const unsigned long *members = map->members;
+	u16 id = *(u16 *)value;
+
+	return ip_set_timeout_test(members[id]);
+}
+
+static int
+bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_port *map = set->data;
+	unsigned long *members = map->members;
+	u16 id = *(u16 *)value;
+
+	if (ip_set_timeout_test(members[id]))
+		return -IPSET_ERR_EXIST;
+
+	members[id] = ip_set_timeout_set(timeout);
+
+	return 0;
+}
+
+static int
+bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout)
+{
+	struct bitmap_port *map = set->data;
+	unsigned long *members = map->members;
+	u16 id = *(u16 *)value;
+	int ret = -IPSET_ERR_EXIST;
+
+	if (ip_set_timeout_test(members[id]))
+		ret = 0;
+
+	members[id] = IPSET_ELEM_UNSET;
+	return ret;
+}
+
+static int
+bitmap_port_tlist(const struct ip_set *set,
+		  struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct bitmap_port *map = set->data;
+	struct nlattr *adt, *nested;
+	u16 id, first = cb->args[2];
+	u16 last = map->last_port - map->first_port;
+	const unsigned long *members = map->members;
+
+	adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!adt)
+		return -EMSGSIZE;
+	for (; cb->args[2] <= last; cb->args[2]++) {
+		id = cb->args[2];
+		if (!ip_set_timeout_test(members[id]))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (id == first) {
+				nla_nest_cancel(skb, adt);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
+			      htons(map->first_port + id));
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+			      htonl(ip_set_timeout_get(members[id])));
+		ipset_nest_end(skb, nested);
+	}
+	ipset_nest_end(skb, adt);
+
+	/* Set listing finished */
+	cb->args[2] = 0;
+
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, adt);
+	if (unlikely(id == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+static int
+bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
+		 enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	struct bitmap_port *map = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	__be16 __port;
+	u16 port = 0;
+
+	if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port))
+		return -EINVAL;
+
+	port = ntohs(__port);
+
+	if (port < map->first_port || port > map->last_port)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	port -= map->first_port;
+
+	return adtfn(set, &port, map->timeout);
+}
+
+static int
+bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
+		 enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	struct bitmap_port *map = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	u32 timeout = map->timeout;
+	u32 port;	/* wraparound */
+	u16 id, port_to;
+	int ret = 0;
+
+	if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
+	if (port < map->first_port || port > map->last_port)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(map->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST) {
+		id = port - map->first_port;
+		return adtfn(set, &id, timeout);
+	}
+
+	if (tb[IPSET_ATTR_PORT_TO]) {
+		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+		if (port > port_to) {
+			swap(port, port_to);
+			if (port < map->first_port)
+				return -IPSET_ERR_BITMAP_RANGE;
+		}
+	} else
+		port_to = port;
+
+	if (port_to > map->last_port)
+		return -IPSET_ERR_BITMAP_RANGE;
+
+	for (; port <= port_to; port++) {
+		id = port - map->first_port;
+		ret = adtfn(set, &id, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+static void
+bitmap_port_destroy(struct ip_set *set)
+{
+	struct bitmap_port *map = set->data;
+
+	if (with_timeout(map->timeout))
+		del_timer_sync(&map->gc);
+
+	ip_set_free(map->members);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static void
+bitmap_port_flush(struct ip_set *set)
+{
+	struct bitmap_port *map = set->data;
+
+	memset(map->members, 0, map->memsize);
+}
+
+static int
+bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
+{
+	const struct bitmap_port *map = set->data;
+	struct nlattr *nested;
+
+	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+	if (!nested)
+		goto nla_put_failure;
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
+	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
+		      htonl(atomic_read(&set->ref) - 1));
+	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
+		      htonl(sizeof(*map) + map->memsize));
+	if (with_timeout(map->timeout))
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
+	ipset_nest_end(skb, nested);
+
+	return 0;
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static bool
+bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct bitmap_port *x = a->data;
+	const struct bitmap_port *y = b->data;
+
+	return x->first_port == y->first_port &&
+	       x->last_port == y->last_port &&
+	       x->timeout == y->timeout;
+}
+
+static const struct ip_set_type_variant bitmap_port = {
+	.kadt	= bitmap_port_kadt,
+	.uadt	= bitmap_port_uadt,
+	.adt	= {
+		[IPSET_ADD] = bitmap_port_add,
+		[IPSET_DEL] = bitmap_port_del,
+		[IPSET_TEST] = bitmap_port_test,
+	},
+	.destroy = bitmap_port_destroy,
+	.flush	= bitmap_port_flush,
+	.head	= bitmap_port_head,
+	.list	= bitmap_port_list,
+	.same_set = bitmap_port_same_set,
+};
+
+static const struct ip_set_type_variant bitmap_tport = {
+	.kadt	= bitmap_port_kadt,
+	.uadt	= bitmap_port_uadt,
+	.adt	= {
+		[IPSET_ADD] = bitmap_port_tadd,
+		[IPSET_DEL] = bitmap_port_tdel,
+		[IPSET_TEST] = bitmap_port_ttest,
+	},
+	.destroy = bitmap_port_destroy,
+	.flush	= bitmap_port_flush,
+	.head	= bitmap_port_head,
+	.list	= bitmap_port_tlist,
+	.same_set = bitmap_port_same_set,
+};
+
+static void
+bitmap_port_gc(unsigned long ul_set)
+{
+	struct ip_set *set = (struct ip_set *) ul_set;
+	struct bitmap_port *map = set->data;
+	unsigned long *table = map->members;
+	u32 id;	/* wraparound */
+	u16 last = map->last_port - map->first_port;
+
+	/* We run parallel with other readers (test element)
+	 * but adding/deleting new entries is locked out */
+	read_lock_bh(&set->lock);
+	for (id = 0; id <= last; id++)
+		if (ip_set_timeout_expired(table[id]))
+			table[id] = IPSET_ELEM_UNSET;
+	read_unlock_bh(&set->lock);
+
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+static void
+bitmap_port_gc_init(struct ip_set *set)
+{
+	struct bitmap_port *map = set->data;
+
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = bitmap_port_gc;
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+/* Create bitmap:ip type of sets */
+
+static bool
+init_map_port(struct ip_set *set, struct bitmap_port *map,
+	      u16 first_port, u16 last_port)
+{
+	map->members = ip_set_alloc(map->memsize);
+	if (!map->members)
+		return false;
+	map->first_port = first_port;
+	map->last_port = last_port;
+	map->timeout = IPSET_NO_TIMEOUT;
+
+	set->data = map;
+	set->family = AF_UNSPEC;
+
+	return true;
+}
+
+static int
+bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
+		 u32 flags)
+{
+	struct bitmap_port *map;
+	u16 first_port, last_port;
+
+	if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
+	last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+	if (first_port > last_port) {
+		u16 tmp = first_port;
+
+		first_port = last_port;
+		last_port = tmp;
+	}
+
+	map = kzalloc(sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		map->memsize = (last_port - first_port + 1)
+			       * sizeof(unsigned long);
+
+		if (!init_map_port(set, map, first_port, last_port)) {
+			kfree(map);
+			return -ENOMEM;
+		}
+
+		map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+		set->variant = &bitmap_tport;
+
+		bitmap_port_gc_init(set);
+	} else {
+		map->memsize = bitmap_bytes(0, last_port - first_port);
+		pr_debug("memsize: %zu\n", map->memsize);
+		if (!init_map_port(set, map, first_port, last_port)) {
+			kfree(map);
+			return -ENOMEM;
+		}
+
+		set->variant = &bitmap_port;
+	}
+	return 0;
+}
+
+static struct ip_set_type bitmap_port_type = {
+	.name		= "bitmap:port",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_PORT,
+	.dimension	= IPSET_DIM_ONE,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= bitmap_port_create,
+	.create_policy	= {
+		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+bitmap_port_init(void)
+{
+	return ip_set_type_register(&bitmap_port_type);
+}
+
+static void __exit
+bitmap_port_fini(void)
+{
+	ip_set_type_unregister(&bitmap_port_type);
+}
+
+module_init(bitmap_port_init);
+module_exit(bitmap_port_fini);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
new file mode 100644
index 0000000..d6b4823
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -0,0 +1,1683 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ *                         Patrick Schaaf <bof@bof.de>
+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module for IP set management */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/netlink.h>
+#include <linux/rculist.h>
+#include <linux/version.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/ipset/ip_set.h>
+
+static LIST_HEAD(ip_set_type_list);		/* all registered set types */
+static DEFINE_MUTEX(ip_set_type_mutex);		/* protects ip_set_type_list */
+
+static struct ip_set **ip_set_list;		/* all individual sets */
+static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
+
+#define STREQ(a, b)	(strncmp(a, b, IPSET_MAXNAMELEN) == 0)
+
+static unsigned int max_sets;
+
+module_param(max_sets, int, 0600);
+MODULE_PARM_DESC(max_sets, "maximal number of sets");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("core IP set support");
+MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
+
+/*
+ * The set types are implemented in modules and registered set types
+ * can be found in ip_set_type_list. Adding/deleting types is
+ * serialized by ip_set_type_mutex.
+ */
+
+static inline void
+ip_set_type_lock(void)
+{
+	mutex_lock(&ip_set_type_mutex);
+}
+
+static inline void
+ip_set_type_unlock(void)
+{
+	mutex_unlock(&ip_set_type_mutex);
+}
+
+/* Register and deregister settype */
+
+static struct ip_set_type *
+find_set_type(const char *name, u8 family, u8 revision)
+{
+	struct ip_set_type *type;
+
+	list_for_each_entry_rcu(type, &ip_set_type_list, list)
+		if (STREQ(type->name, name) &&
+		    (type->family == family || type->family == AF_UNSPEC) &&
+		    type->revision == revision)
+			return type;
+	return NULL;
+}
+
+/* Unlock, try to load a set type module and lock again */
+static int
+try_to_load_type(const char *name)
+{
+	nfnl_unlock();
+	pr_debug("try to load ip_set_%s\n", name);
+	if (request_module("ip_set_%s", name) < 0) {
+		pr_warning("Can't find ip_set type %s\n", name);
+		nfnl_lock();
+		return -IPSET_ERR_FIND_TYPE;
+	}
+	nfnl_lock();
+	return -EAGAIN;
+}
+
+/* Find a set type and reference it */
+static int
+find_set_type_get(const char *name, u8 family, u8 revision,
+		  struct ip_set_type **found)
+{
+	struct ip_set_type *type;
+	int err;
+
+	rcu_read_lock();
+	*found = find_set_type(name, family, revision);
+	if (*found) {
+		err = !try_module_get((*found)->me) ? -EFAULT : 0;
+		goto unlock;
+	}
+	/* Make sure the type is loaded but we don't support the revision */
+	list_for_each_entry_rcu(type, &ip_set_type_list, list)
+		if (STREQ(type->name, name)) {
+			err = -IPSET_ERR_FIND_TYPE;
+			goto unlock;
+		}
+	rcu_read_unlock();
+
+	return try_to_load_type(name);
+
+unlock:
+	rcu_read_unlock();
+	return err;
+}
+
+/* Find a given set type by name and family.
+ * If we succeeded, the supported minimal and maximum revisions are
+ * filled out.
+ */
+static int
+find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
+{
+	struct ip_set_type *type;
+	bool found = false;
+
+	*min = 255; *max = 0;
+	rcu_read_lock();
+	list_for_each_entry_rcu(type, &ip_set_type_list, list)
+		if (STREQ(type->name, name) &&
+		    (type->family == family || type->family == AF_UNSPEC)) {
+			found = true;
+			if (type->revision < *min)
+				*min = type->revision;
+			if (type->revision > *max)
+				*max = type->revision;
+		}
+	rcu_read_unlock();
+	if (found)
+		return 0;
+
+	return try_to_load_type(name);
+}
+
+#define family_name(f)	((f) == AF_INET ? "inet" : \
+			 (f) == AF_INET6 ? "inet6" : "any")
+
+/* Register a set type structure. The type is identified by
+ * the unique triple of name, family and revision.
+ */
+int
+ip_set_type_register(struct ip_set_type *type)
+{
+	int ret = 0;
+
+	if (type->protocol != IPSET_PROTOCOL) {
+		pr_warning("ip_set type %s, family %s, revision %u uses "
+			   "wrong protocol version %u (want %u)\n",
+			   type->name, family_name(type->family),
+			   type->revision, type->protocol, IPSET_PROTOCOL);
+		return -EINVAL;
+	}
+
+	ip_set_type_lock();
+	if (find_set_type(type->name, type->family, type->revision)) {
+		/* Duplicate! */
+		pr_warning("ip_set type %s, family %s, revision %u "
+			   "already registered!\n", type->name,
+			   family_name(type->family), type->revision);
+		ret = -EINVAL;
+		goto unlock;
+	}
+	list_add_rcu(&type->list, &ip_set_type_list);
+	pr_debug("type %s, family %s, revision %u registered.\n",
+		 type->name, family_name(type->family), type->revision);
+unlock:
+	ip_set_type_unlock();
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ip_set_type_register);
+
+/* Unregister a set type. There's a small race with ip_set_create */
+void
+ip_set_type_unregister(struct ip_set_type *type)
+{
+	ip_set_type_lock();
+	if (!find_set_type(type->name, type->family, type->revision)) {
+		pr_warning("ip_set type %s, family %s, revision %u "
+			   "not registered\n", type->name,
+			   family_name(type->family), type->revision);
+		goto unlock;
+	}
+	list_del_rcu(&type->list);
+	pr_debug("type %s, family %s, revision %u unregistered.\n",
+		 type->name, family_name(type->family), type->revision);
+unlock:
+	ip_set_type_unlock();
+
+	synchronize_rcu();
+}
+EXPORT_SYMBOL_GPL(ip_set_type_unregister);
+
+/* Utility functions */
+void *
+ip_set_alloc(size_t size)
+{
+	void *members = NULL;
+
+	if (size < KMALLOC_MAX_SIZE)
+		members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+
+	if (members) {
+		pr_debug("%p: allocated with kmalloc\n", members);
+		return members;
+	}
+
+	members = vzalloc(size);
+	if (!members)
+		return NULL;
+	pr_debug("%p: allocated with vmalloc\n", members);
+
+	return members;
+}
+EXPORT_SYMBOL_GPL(ip_set_alloc);
+
+void
+ip_set_free(void *members)
+{
+	pr_debug("%p: free with %s\n", members,
+		 is_vmalloc_addr(members) ? "vfree" : "kfree");
+	if (is_vmalloc_addr(members))
+		vfree(members);
+	else
+		kfree(members);
+}
+EXPORT_SYMBOL_GPL(ip_set_free);
+
+static inline bool
+flag_nested(const struct nlattr *nla)
+{
+	return nla->nla_type & NLA_F_NESTED;
+}
+
+static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
+	[IPSET_ATTR_IPADDR_IPV4]	= { .type = NLA_U32 },
+	[IPSET_ATTR_IPADDR_IPV6]	= { .type = NLA_BINARY,
+					    .len = sizeof(struct in6_addr) },
+};
+
+int
+ip_set_get_ipaddr4(struct nlattr *nla,  __be32 *ipaddr)
+{
+	struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
+
+	if (unlikely(!flag_nested(nla)))
+		return -IPSET_ERR_PROTOCOL;
+	if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
+		return -IPSET_ERR_PROTOCOL;
+	if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
+		return -IPSET_ERR_PROTOCOL;
+
+	*ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
+
+int
+ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
+{
+	struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
+
+	if (unlikely(!flag_nested(nla)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
+		return -IPSET_ERR_PROTOCOL;
+	if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
+		return -IPSET_ERR_PROTOCOL;
+
+	memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
+		sizeof(struct in6_addr));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
+
+/*
+ * Creating/destroying/renaming/swapping affect the existence and
+ * the properties of a set. All of these can be executed from userspace
+ * only and serialized by the nfnl mutex indirectly from nfnetlink.
+ *
+ * Sets are identified by their index in ip_set_list and the index
+ * is used by the external references (set/SET netfilter modules).
+ *
+ * The set behind an index may change by swapping only, from userspace.
+ */
+
+static inline void
+__ip_set_get(ip_set_id_t index)
+{
+	atomic_inc(&ip_set_list[index]->ref);
+}
+
+static inline void
+__ip_set_put(ip_set_id_t index)
+{
+	atomic_dec(&ip_set_list[index]->ref);
+}
+
+/*
+ * Add, del and test set entries from kernel.
+ *
+ * The set behind the index must exist and must be referenced
+ * so it can't be destroyed (or changed) under our foot.
+ */
+
+int
+ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
+	    u8 family, u8 dim, u8 flags)
+{
+	struct ip_set *set = ip_set_list[index];
+	int ret = 0;
+
+	BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
+	pr_debug("set %s, index %u\n", set->name, index);
+
+	if (dim < set->type->dimension ||
+	    !(family == set->family || set->family == AF_UNSPEC))
+		return 0;
+
+	read_lock_bh(&set->lock);
+	ret = set->variant->kadt(set, skb, IPSET_TEST, family, dim, flags);
+	read_unlock_bh(&set->lock);
+
+	if (ret == -EAGAIN) {
+		/* Type requests element to be completed */
+		pr_debug("element must be competed, ADD is triggered\n");
+		write_lock_bh(&set->lock);
+		set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
+		write_unlock_bh(&set->lock);
+		ret = 1;
+	}
+
+	/* Convert error codes to nomatch */
+	return (ret < 0 ? 0 : ret);
+}
+EXPORT_SYMBOL_GPL(ip_set_test);
+
+int
+ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
+	   u8 family, u8 dim, u8 flags)
+{
+	struct ip_set *set = ip_set_list[index];
+	int ret;
+
+	BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
+	pr_debug("set %s, index %u\n", set->name, index);
+
+	if (dim < set->type->dimension ||
+	    !(family == set->family || set->family == AF_UNSPEC))
+		return 0;
+
+	write_lock_bh(&set->lock);
+	ret = set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags);
+	write_unlock_bh(&set->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ip_set_add);
+
+int
+ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
+	   u8 family, u8 dim, u8 flags)
+{
+	struct ip_set *set = ip_set_list[index];
+	int ret = 0;
+
+	BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
+	pr_debug("set %s, index %u\n", set->name, index);
+
+	if (dim < set->type->dimension ||
+	    !(family == set->family || set->family == AF_UNSPEC))
+		return 0;
+
+	write_lock_bh(&set->lock);
+	ret = set->variant->kadt(set, skb, IPSET_DEL, family, dim, flags);
+	write_unlock_bh(&set->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ip_set_del);
+
+/*
+ * Find set by name, reference it once. The reference makes sure the
+ * thing pointed to, does not go away under our feet.
+ *
+ * The nfnl mutex must already be activated.
+ */
+ip_set_id_t
+ip_set_get_byname(const char *name, struct ip_set **set)
+{
+	ip_set_id_t i, index = IPSET_INVALID_ID;
+	struct ip_set *s;
+
+	for (i = 0; i < ip_set_max; i++) {
+		s = ip_set_list[i];
+		if (s != NULL && STREQ(s->name, name)) {
+			__ip_set_get(i);
+			index = i;
+			*set = s;
+		}
+	}
+
+	return index;
+}
+EXPORT_SYMBOL_GPL(ip_set_get_byname);
+
+/*
+ * If the given set pointer points to a valid set, decrement
+ * reference count by 1. The caller shall not assume the index
+ * to be valid, after calling this function.
+ *
+ * The nfnl mutex must already be activated.
+ */
+void
+ip_set_put_byindex(ip_set_id_t index)
+{
+	if (ip_set_list[index] != NULL) {
+		BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
+		__ip_set_put(index);
+	}
+}
+EXPORT_SYMBOL_GPL(ip_set_put_byindex);
+
+/*
+ * Get the name of a set behind a set index.
+ * We assume the set is referenced, so it does exist and
+ * can't be destroyed. The set cannot be renamed due to
+ * the referencing either.
+ *
+ * The nfnl mutex must already be activated.
+ */
+const char *
+ip_set_name_byindex(ip_set_id_t index)
+{
+	const struct ip_set *set = ip_set_list[index];
+
+	BUG_ON(set == NULL);
+	BUG_ON(atomic_read(&set->ref) == 0);
+
+	/* Referenced, so it's safe */
+	return set->name;
+}
+EXPORT_SYMBOL_GPL(ip_set_name_byindex);
+
+/*
+ * Routines to call by external subsystems, which do not
+ * call nfnl_lock for us.
+ */
+
+/*
+ * Find set by name, reference it once. The reference makes sure the
+ * thing pointed to, does not go away under our feet.
+ *
+ * The nfnl mutex is used in the function.
+ */
+ip_set_id_t
+ip_set_nfnl_get(const char *name)
+{
+	struct ip_set *s;
+	ip_set_id_t index;
+
+	nfnl_lock();
+	index = ip_set_get_byname(name, &s);
+	nfnl_unlock();
+
+	return index;
+}
+EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
+
+/*
+ * Find set by index, reference it once. The reference makes sure the
+ * thing pointed to, does not go away under our feet.
+ *
+ * The nfnl mutex is used in the function.
+ */
+ip_set_id_t
+ip_set_nfnl_get_byindex(ip_set_id_t index)
+{
+	if (index > ip_set_max)
+		return IPSET_INVALID_ID;
+
+	nfnl_lock();
+	if (ip_set_list[index])
+		__ip_set_get(index);
+	else
+		index = IPSET_INVALID_ID;
+	nfnl_unlock();
+
+	return index;
+}
+EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
+
+/*
+ * If the given set pointer points to a valid set, decrement
+ * reference count by 1. The caller shall not assume the index
+ * to be valid, after calling this function.
+ *
+ * The nfnl mutex is used in the function.
+ */
+void
+ip_set_nfnl_put(ip_set_id_t index)
+{
+	nfnl_lock();
+	if (ip_set_list[index] != NULL) {
+		BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
+		__ip_set_put(index);
+	}
+	nfnl_unlock();
+}
+EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
+
+/*
+ * Communication protocol with userspace over netlink.
+ *
+ * We already locked by nfnl_lock.
+ */
+
+static inline bool
+protocol_failed(const struct nlattr * const tb[])
+{
+	return !tb[IPSET_ATTR_PROTOCOL] ||
+	       nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
+}
+
+static inline u32
+flag_exist(const struct nlmsghdr *nlh)
+{
+	return nlh->nlmsg_flags & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
+}
+
+static struct nlmsghdr *
+start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
+	  enum ipset_cmd cmd)
+{
+	struct nlmsghdr *nlh;
+	struct nfgenmsg *nfmsg;
+
+	nlh = nlmsg_put(skb, pid, seq, cmd | (NFNL_SUBSYS_IPSET << 8),
+			sizeof(*nfmsg), flags);
+	if (nlh == NULL)
+		return NULL;
+
+	nfmsg = nlmsg_data(nlh);
+	nfmsg->nfgen_family = AF_INET;
+	nfmsg->version = NFNETLINK_V0;
+	nfmsg->res_id = 0;
+
+	return nlh;
+}
+
+/* Create a set */
+
+static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
+	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
+	[IPSET_ATTR_SETNAME]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1 },
+	[IPSET_ATTR_TYPENAME]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1},
+	[IPSET_ATTR_REVISION]	= { .type = NLA_U8 },
+	[IPSET_ATTR_FAMILY]	= { .type = NLA_U8 },
+	[IPSET_ATTR_DATA]	= { .type = NLA_NESTED },
+};
+
+static ip_set_id_t
+find_set_id(const char *name)
+{
+	ip_set_id_t i, index = IPSET_INVALID_ID;
+	const struct ip_set *set;
+
+	for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) {
+		set = ip_set_list[i];
+		if (set != NULL && STREQ(set->name, name))
+			index = i;
+	}
+	return index;
+}
+
+static inline struct ip_set *
+find_set(const char *name)
+{
+	ip_set_id_t index = find_set_id(name);
+
+	return index == IPSET_INVALID_ID ? NULL : ip_set_list[index];
+}
+
+static int
+find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
+{
+	ip_set_id_t i;
+
+	*index = IPSET_INVALID_ID;
+	for (i = 0;  i < ip_set_max; i++) {
+		if (ip_set_list[i] == NULL) {
+			if (*index == IPSET_INVALID_ID)
+				*index = i;
+		} else if (STREQ(name, ip_set_list[i]->name)) {
+			/* Name clash */
+			*set = ip_set_list[i];
+			return -EEXIST;
+		}
+	}
+	if (*index == IPSET_INVALID_ID)
+		/* No free slot remained */
+		return -IPSET_ERR_MAX_SETS;
+	return 0;
+}
+
+static int
+ip_set_create(struct sock *ctnl, struct sk_buff *skb,
+	      const struct nlmsghdr *nlh,
+	      const struct nlattr * const attr[])
+{
+	struct ip_set *set, *clash = NULL;
+	ip_set_id_t index = IPSET_INVALID_ID;
+	struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {};
+	const char *name, *typename;
+	u8 family, revision;
+	u32 flags = flag_exist(nlh);
+	int ret = 0;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL ||
+		     attr[IPSET_ATTR_TYPENAME] == NULL ||
+		     attr[IPSET_ATTR_REVISION] == NULL ||
+		     attr[IPSET_ATTR_FAMILY] == NULL ||
+		     (attr[IPSET_ATTR_DATA] != NULL &&
+		      !flag_nested(attr[IPSET_ATTR_DATA]))))
+		return -IPSET_ERR_PROTOCOL;
+
+	name = nla_data(attr[IPSET_ATTR_SETNAME]);
+	typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
+	family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
+	revision = nla_get_u8(attr[IPSET_ATTR_REVISION]);
+	pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
+		 name, typename, family_name(family), revision);
+
+	/*
+	 * First, and without any locks, allocate and initialize
+	 * a normal base set structure.
+	 */
+	set = kzalloc(sizeof(struct ip_set), GFP_KERNEL);
+	if (!set)
+		return -ENOMEM;
+	rwlock_init(&set->lock);
+	strlcpy(set->name, name, IPSET_MAXNAMELEN);
+	atomic_set(&set->ref, 0);
+	set->family = family;
+
+	/*
+	 * Next, check that we know the type, and take
+	 * a reference on the type, to make sure it stays available
+	 * while constructing our new set.
+	 *
+	 * After referencing the type, we try to create the type
+	 * specific part of the set without holding any locks.
+	 */
+	ret = find_set_type_get(typename, family, revision, &(set->type));
+	if (ret)
+		goto out;
+
+	/*
+	 * Without holding any locks, create private part.
+	 */
+	if (attr[IPSET_ATTR_DATA] &&
+	    nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
+			     set->type->create_policy)) {
+	    	ret = -IPSET_ERR_PROTOCOL;
+	    	goto put_out;
+	}
+
+	ret = set->type->create(set, tb, flags);
+	if (ret != 0)
+		goto put_out;
+
+	/* BTW, ret==0 here. */
+
+	/*
+	 * Here, we have a valid, constructed set and we are protected
+	 * by nfnl_lock. Find the first free index in ip_set_list and
+	 * check clashing.
+	 */
+	if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
+		/* If this is the same set and requested, ignore error */
+		if (ret == -EEXIST &&
+		    (flags & IPSET_FLAG_EXIST) &&
+		    STREQ(set->type->name, clash->type->name) &&
+		    set->type->family == clash->type->family &&
+		    set->type->revision == clash->type->revision &&
+		    set->variant->same_set(set, clash))
+			ret = 0;
+		goto cleanup;
+	}
+
+	/*
+	 * Finally! Add our shiny new set to the list, and be done.
+	 */
+	pr_debug("create: '%s' created with index %u!\n", set->name, index);
+	ip_set_list[index] = set;
+
+	return ret;
+
+cleanup:
+	set->variant->destroy(set);
+put_out:
+	module_put(set->type->me);
+out:
+	kfree(set);
+	return ret;
+}
+
+/* Destroy sets */
+
+static const struct nla_policy
+ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
+	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
+	[IPSET_ATTR_SETNAME]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1 },
+};
+
+static void
+ip_set_destroy_set(ip_set_id_t index)
+{
+	struct ip_set *set = ip_set_list[index];
+
+	pr_debug("set: %s\n",  set->name);
+	ip_set_list[index] = NULL;
+
+	/* Must call it without holding any lock */
+	set->variant->destroy(set);
+	module_put(set->type->me);
+	kfree(set);
+}
+
+static int
+ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
+	       const struct nlmsghdr *nlh,
+	       const struct nlattr * const attr[])
+{
+	ip_set_id_t i;
+
+	if (unlikely(protocol_failed(attr)))
+		return -IPSET_ERR_PROTOCOL;
+
+	/* References are protected by the nfnl mutex */
+	if (!attr[IPSET_ATTR_SETNAME]) {
+		for (i = 0; i < ip_set_max; i++) {
+			if (ip_set_list[i] != NULL &&
+			    (atomic_read(&ip_set_list[i]->ref)))
+				return -IPSET_ERR_BUSY;
+		}
+		for (i = 0; i < ip_set_max; i++) {
+			if (ip_set_list[i] != NULL)
+				ip_set_destroy_set(i);
+		}
+	} else {
+		i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
+		if (i == IPSET_INVALID_ID)
+			return -ENOENT;
+		else if (atomic_read(&ip_set_list[i]->ref))
+			return -IPSET_ERR_BUSY;
+
+		ip_set_destroy_set(i);
+	}
+	return 0;
+}
+
+/* Flush sets */
+
+static void
+ip_set_flush_set(struct ip_set *set)
+{
+	pr_debug("set: %s\n",  set->name);
+
+	write_lock_bh(&set->lock);
+	set->variant->flush(set);
+	write_unlock_bh(&set->lock);
+}
+
+static int
+ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
+	     const struct nlmsghdr *nlh,
+	     const struct nlattr * const attr[])
+{
+	ip_set_id_t i;
+
+	if (unlikely(protocol_failed(attr)))
+		return -EPROTO;
+
+	if (!attr[IPSET_ATTR_SETNAME]) {
+		for (i = 0; i < ip_set_max; i++)
+			if (ip_set_list[i] != NULL)
+				ip_set_flush_set(ip_set_list[i]);
+	} else {
+		i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
+		if (i == IPSET_INVALID_ID)
+			return -ENOENT;
+
+		ip_set_flush_set(ip_set_list[i]);
+	}
+
+	return 0;
+}
+
+/* Rename a set */
+
+static const struct nla_policy
+ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
+	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
+	[IPSET_ATTR_SETNAME]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1 },
+	[IPSET_ATTR_SETNAME2]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1 },
+};
+
+static int
+ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
+	      const struct nlmsghdr *nlh,
+	      const struct nlattr * const attr[])
+{
+	struct ip_set *set;
+	const char *name2;
+	ip_set_id_t i;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL ||
+		     attr[IPSET_ATTR_SETNAME2] == NULL))
+		return -IPSET_ERR_PROTOCOL;
+
+	set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+	if (set == NULL)
+		return -ENOENT;
+	if (atomic_read(&set->ref) != 0)
+		return -IPSET_ERR_REFERENCED;
+
+	name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
+	for (i = 0; i < ip_set_max; i++) {
+		if (ip_set_list[i] != NULL &&
+		    STREQ(ip_set_list[i]->name, name2))
+			return -IPSET_ERR_EXIST_SETNAME2;
+	}
+	strncpy(set->name, name2, IPSET_MAXNAMELEN);
+
+	return 0;
+}
+
+/* Swap two sets so that name/index points to the other.
+ * References and set names are also swapped.
+ *
+ * We are protected by the nfnl mutex and references are
+ * manipulated only by holding the mutex. The kernel interfaces
+ * do not hold the mutex but the pointer settings are atomic
+ * so the ip_set_list always contains valid pointers to the sets.
+ */
+
+static int
+ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
+	    const struct nlmsghdr *nlh,
+	    const struct nlattr * const attr[])
+{
+	struct ip_set *from, *to;
+	ip_set_id_t from_id, to_id;
+	char from_name[IPSET_MAXNAMELEN];
+	u32 from_ref;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL ||
+		     attr[IPSET_ATTR_SETNAME2] == NULL))
+		return -IPSET_ERR_PROTOCOL;
+
+	from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
+	if (from_id == IPSET_INVALID_ID)
+		return -ENOENT;
+
+	to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
+	if (to_id == IPSET_INVALID_ID)
+		return -IPSET_ERR_EXIST_SETNAME2;
+
+	from = ip_set_list[from_id];
+	to = ip_set_list[to_id];
+
+	/* Features must not change.
+	 * Not an artifical restriction anymore, as we must prevent
+	 * possible loops created by swapping in setlist type of sets. */
+	if (!(from->type->features == to->type->features &&
+	      from->type->family == to->type->family))
+		return -IPSET_ERR_TYPE_MISMATCH;
+
+	/* No magic here: ref munging protected by the nfnl_lock */
+	strncpy(from_name, from->name, IPSET_MAXNAMELEN);
+	from_ref = atomic_read(&from->ref);
+
+	strncpy(from->name, to->name, IPSET_MAXNAMELEN);
+	atomic_set(&from->ref, atomic_read(&to->ref));
+	strncpy(to->name, from_name, IPSET_MAXNAMELEN);
+	atomic_set(&to->ref, from_ref);
+
+	ip_set_list[from_id] = to;
+	ip_set_list[to_id] = from;
+
+	return 0;
+}
+
+/* List/save set data */
+
+#define DUMP_INIT	0L
+#define DUMP_ALL	1L
+#define DUMP_ONE	2L
+#define DUMP_LAST	3L
+
+static int
+ip_set_dump_done(struct netlink_callback *cb)
+{
+	if (cb->args[2]) {
+		pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
+		__ip_set_put((ip_set_id_t) cb->args[1]);
+	}
+	return 0;
+}
+
+static inline void
+dump_attrs(struct nlmsghdr *nlh)
+{
+	const struct nlattr *attr;
+	int rem;
+
+	pr_debug("dump nlmsg\n");
+	nlmsg_for_each_attr(attr, nlh, sizeof(struct nfgenmsg), rem) {
+		pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len);
+	}
+}
+
+static int
+dump_init(struct netlink_callback *cb)
+{
+	struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
+	int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+	struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
+	struct nlattr *attr = (void *)nlh + min_len;
+	ip_set_id_t index;
+
+	/* Second pass, so parser can't fail */
+	nla_parse(cda, IPSET_ATTR_CMD_MAX,
+		  attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
+
+	/* cb->args[0] : dump single set/all sets
+	 *         [1] : set index
+	 *         [..]: type specific
+	 */
+
+	if (!cda[IPSET_ATTR_SETNAME]) {
+		cb->args[0] = DUMP_ALL;
+		return 0;
+	}
+
+	index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
+	if (index == IPSET_INVALID_ID)
+		return -ENOENT;
+
+	cb->args[0] = DUMP_ONE;
+	cb->args[1] = index;
+	return 0;
+}
+
+static int
+ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	ip_set_id_t index = IPSET_INVALID_ID, max;
+	struct ip_set *set = NULL;
+	struct nlmsghdr *nlh = NULL;
+	unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
+	int ret = 0;
+
+	if (cb->args[0] == DUMP_INIT) {
+		ret = dump_init(cb);
+		if (ret < 0) {
+			nlh = nlmsg_hdr(cb->skb);
+			/* We have to create and send the error message
+			 * manually :-( */
+			if (nlh->nlmsg_flags & NLM_F_ACK)
+				netlink_ack(cb->skb, nlh, ret);
+			return ret;
+		}
+	}
+
+	if (cb->args[1] >= ip_set_max)
+		goto out;
+
+	pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
+	max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
+	for (; cb->args[1] < max; cb->args[1]++) {
+		index = (ip_set_id_t) cb->args[1];
+		set = ip_set_list[index];
+		if (set == NULL) {
+			if (cb->args[0] == DUMP_ONE) {
+				ret = -ENOENT;
+				goto out;
+			}
+			continue;
+		}
+		/* When dumping all sets, we must dump "sorted"
+		 * so that lists (unions of sets) are dumped last.
+		 */
+		if (cb->args[0] != DUMP_ONE &&
+		    !((cb->args[0] == DUMP_ALL) ^
+		      (set->type->features & IPSET_DUMP_LAST)))
+			continue;
+		pr_debug("List set: %s\n", set->name);
+		if (!cb->args[2]) {
+			/* Start listing: make sure set won't be destroyed */
+			pr_debug("reference set\n");
+			__ip_set_get(index);
+		}
+		nlh = start_msg(skb, NETLINK_CB(cb->skb).pid,
+				cb->nlh->nlmsg_seq, flags,
+				IPSET_CMD_LIST);
+		if (!nlh) {
+			ret = -EMSGSIZE;
+			goto release_refcount;
+		}
+		NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
+		NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
+		switch (cb->args[2]) {
+		case 0:
+			/* Core header data */
+			NLA_PUT_STRING(skb, IPSET_ATTR_TYPENAME,
+				       set->type->name);
+			NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
+				   set->family);
+			NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
+				   set->type->revision);
+			ret = set->variant->head(set, skb);
+			if (ret < 0)
+				goto release_refcount;
+			/* Fall through and add elements */
+		default:
+			read_lock_bh(&set->lock);
+			ret = set->variant->list(set, skb, cb);
+			read_unlock_bh(&set->lock);
+			if (!cb->args[2]) {
+				/* Set is done, proceed with next one */
+				if (cb->args[0] == DUMP_ONE)
+					cb->args[1] = IPSET_INVALID_ID;
+				else
+					cb->args[1]++;
+			}
+			goto release_refcount;
+		}
+	}
+	goto out;
+
+nla_put_failure:
+	ret = -EFAULT;
+release_refcount:
+	/* If there was an error or set is done, release set */
+	if (ret || !cb->args[2]) {
+		pr_debug("release set %s\n", ip_set_list[index]->name);
+		__ip_set_put(index);
+	}
+
+	/* If we dump all sets, continue with dumping last ones */
+	if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2])
+		cb->args[0] = DUMP_LAST;
+
+out:
+	if (nlh) {
+		nlmsg_end(skb, nlh);
+		pr_debug("nlmsg_len: %u\n", nlh->nlmsg_len);
+		dump_attrs(nlh);
+	}
+
+	return ret < 0 ? ret : skb->len;
+}
+
+static int
+ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
+	    const struct nlmsghdr *nlh,
+	    const struct nlattr * const attr[])
+{
+	if (unlikely(protocol_failed(attr)))
+		return -IPSET_ERR_PROTOCOL;
+
+	return netlink_dump_start(ctnl, skb, nlh,
+				  ip_set_dump_start,
+				  ip_set_dump_done);
+}
+
+/* Add, del and test */
+
+static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
+	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
+	[IPSET_ATTR_SETNAME]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1 },
+	[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	[IPSET_ATTR_DATA]	= { .type = NLA_NESTED },
+	[IPSET_ATTR_ADT]	= { .type = NLA_NESTED },
+};
+
+static int
+call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
+	struct nlattr *tb[], enum ipset_adt adt,
+	u32 flags, bool use_lineno)
+{
+	int ret, retried = 0;
+	u32 lineno = 0;
+	bool eexist = flags & IPSET_FLAG_EXIST;
+
+	do {
+		write_lock_bh(&set->lock);
+		ret = set->variant->uadt(set, tb, adt, &lineno, flags);
+		write_unlock_bh(&set->lock);
+	} while (ret == -EAGAIN &&
+		 set->variant->resize &&
+		 (ret = set->variant->resize(set, retried++)) == 0);
+
+	if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
+		return 0;
+	if (lineno && use_lineno) {
+		/* Error in restore/batch mode: send back lineno */
+		struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
+		struct sk_buff *skb2;
+		struct nlmsgerr *errmsg;
+		size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
+		int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
+		struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
+		struct nlattr *cmdattr;
+		u32 *errline;
+
+		skb2 = nlmsg_new(payload, GFP_KERNEL);
+		if (skb2 == NULL)
+			return -ENOMEM;
+		rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid,
+				  nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
+		errmsg = nlmsg_data(rep);
+		errmsg->error = ret;
+		memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
+		cmdattr = (void *)&errmsg->msg + min_len;
+
+		nla_parse(cda, IPSET_ATTR_CMD_MAX,
+			  cmdattr, nlh->nlmsg_len - min_len,
+			  ip_set_adt_policy);
+
+		errline = nla_data(cda[IPSET_ATTR_LINENO]);
+
+		*errline = lineno;
+
+		netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+		/* Signal netlink not to send its ACK/errmsg.  */
+		return -EINTR;
+	}
+
+	return ret;
+}
+
+static int
+ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
+	    const struct nlmsghdr *nlh,
+	    const struct nlattr * const attr[])
+{
+	struct ip_set *set;
+	struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
+	const struct nlattr *nla;
+	u32 flags = flag_exist(nlh);
+	bool use_lineno;
+	int ret = 0;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL ||
+		     !((attr[IPSET_ATTR_DATA] != NULL) ^
+		       (attr[IPSET_ATTR_ADT] != NULL)) ||
+		     (attr[IPSET_ATTR_DATA] != NULL &&
+		      !flag_nested(attr[IPSET_ATTR_DATA])) ||
+		     (attr[IPSET_ATTR_ADT] != NULL &&
+		      (!flag_nested(attr[IPSET_ATTR_ADT]) ||
+		       attr[IPSET_ATTR_LINENO] == NULL))))
+		return -IPSET_ERR_PROTOCOL;
+
+	set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+	if (set == NULL)
+		return -ENOENT;
+
+	use_lineno = !!attr[IPSET_ATTR_LINENO];
+	if (attr[IPSET_ATTR_DATA]) {
+		if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
+				     attr[IPSET_ATTR_DATA],
+				     set->type->adt_policy))
+			return -IPSET_ERR_PROTOCOL;
+		ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags,
+			      use_lineno);
+	} else {
+		int nla_rem;
+
+		nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
+			memset(tb, 0, sizeof(tb));
+			if (nla_type(nla) != IPSET_ATTR_DATA ||
+			    !flag_nested(nla) ||
+			    nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
+					     set->type->adt_policy))
+				return -IPSET_ERR_PROTOCOL;
+			ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
+				      flags, use_lineno);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return ret;
+}
+
+static int
+ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
+	    const struct nlmsghdr *nlh,
+	    const struct nlattr * const attr[])
+{
+	struct ip_set *set;
+	struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
+	const struct nlattr *nla;
+	u32 flags = flag_exist(nlh);
+	bool use_lineno;
+	int ret = 0;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL ||
+		     !((attr[IPSET_ATTR_DATA] != NULL) ^
+		       (attr[IPSET_ATTR_ADT] != NULL)) ||
+		     (attr[IPSET_ATTR_DATA] != NULL &&
+		      !flag_nested(attr[IPSET_ATTR_DATA])) ||
+		     (attr[IPSET_ATTR_ADT] != NULL &&
+		      (!flag_nested(attr[IPSET_ATTR_ADT]) ||
+		       attr[IPSET_ATTR_LINENO] == NULL))))
+		return -IPSET_ERR_PROTOCOL;
+
+	set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+	if (set == NULL)
+		return -ENOENT;
+
+	use_lineno = !!attr[IPSET_ATTR_LINENO];
+	if (attr[IPSET_ATTR_DATA]) {
+		if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
+				     attr[IPSET_ATTR_DATA],
+				     set->type->adt_policy))
+			return -IPSET_ERR_PROTOCOL;
+		ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags,
+			      use_lineno);
+	} else {
+		int nla_rem;
+
+		nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
+			memset(tb, 0, sizeof(*tb));
+			if (nla_type(nla) != IPSET_ATTR_DATA ||
+			    !flag_nested(nla) ||
+			    nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
+					     set->type->adt_policy))
+				return -IPSET_ERR_PROTOCOL;
+			ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
+				      flags, use_lineno);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return ret;
+}
+
+static int
+ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
+	     const struct nlmsghdr *nlh,
+	     const struct nlattr * const attr[])
+{
+	struct ip_set *set;
+	struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
+	int ret = 0;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL ||
+		     attr[IPSET_ATTR_DATA] == NULL ||
+		     !flag_nested(attr[IPSET_ATTR_DATA])))
+		return -IPSET_ERR_PROTOCOL;
+
+	set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+	if (set == NULL)
+		return -ENOENT;
+
+	if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
+			     set->type->adt_policy))
+		return -IPSET_ERR_PROTOCOL;
+
+	read_lock_bh(&set->lock);
+	ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
+	read_unlock_bh(&set->lock);
+	/* Userspace can't trigger element to be re-added */
+	if (ret == -EAGAIN)
+		ret = 1;
+
+	return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST;
+}
+
+/* Get headed data of a set */
+
+static int
+ip_set_header(struct sock *ctnl, struct sk_buff *skb,
+	      const struct nlmsghdr *nlh,
+	      const struct nlattr * const attr[])
+{
+	const struct ip_set *set;
+	struct sk_buff *skb2;
+	struct nlmsghdr *nlh2;
+	ip_set_id_t index;
+	int ret = 0;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_SETNAME] == NULL))
+		return -IPSET_ERR_PROTOCOL;
+
+	index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
+	if (index == IPSET_INVALID_ID)
+		return -ENOENT;
+	set = ip_set_list[index];
+
+	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (skb2 == NULL)
+		return -ENOMEM;
+
+	nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
+			 IPSET_CMD_HEADER);
+	if (!nlh2)
+		goto nlmsg_failure;
+	NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
+	NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
+	NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
+	NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
+	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision);
+	nlmsg_end(skb2, nlh2);
+
+	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+
+nla_put_failure:
+	nlmsg_cancel(skb2, nlh2);
+nlmsg_failure:
+	kfree_skb(skb2);
+	return -EMSGSIZE;
+}
+
+/* Get type data */
+
+static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
+	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
+	[IPSET_ATTR_TYPENAME]	= { .type = NLA_NUL_STRING,
+				    .len = IPSET_MAXNAMELEN - 1 },
+	[IPSET_ATTR_FAMILY]	= { .type = NLA_U8 },
+};
+
+static int
+ip_set_type(struct sock *ctnl, struct sk_buff *skb,
+	    const struct nlmsghdr *nlh,
+	    const struct nlattr * const attr[])
+{
+	struct sk_buff *skb2;
+	struct nlmsghdr *nlh2;
+	u8 family, min, max;
+	const char *typename;
+	int ret = 0;
+
+	if (unlikely(protocol_failed(attr) ||
+		     attr[IPSET_ATTR_TYPENAME] == NULL ||
+		     attr[IPSET_ATTR_FAMILY] == NULL))
+		return -IPSET_ERR_PROTOCOL;
+
+	family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
+	typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
+	ret = find_set_type_minmax(typename, family, &min, &max);
+	if (ret)
+		return ret;
+
+	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (skb2 == NULL)
+		return -ENOMEM;
+
+	nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
+			 IPSET_CMD_TYPE);
+	if (!nlh2)
+		goto nlmsg_failure;
+	NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
+	NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, typename);
+	NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, family);
+	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, max);
+	NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min);
+	nlmsg_end(skb2, nlh2);
+
+	pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
+	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+
+nla_put_failure:
+	nlmsg_cancel(skb2, nlh2);
+nlmsg_failure:
+	kfree_skb(skb2);
+	return -EMSGSIZE;
+}
+
+/* Get protocol version */
+
+static const struct nla_policy
+ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
+	[IPSET_ATTR_PROTOCOL]	= { .type = NLA_U8 },
+};
+
+static int
+ip_set_protocol(struct sock *ctnl, struct sk_buff *skb,
+		const struct nlmsghdr *nlh,
+		const struct nlattr * const attr[])
+{
+	struct sk_buff *skb2;
+	struct nlmsghdr *nlh2;
+	int ret = 0;
+
+	if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
+		return -IPSET_ERR_PROTOCOL;
+
+	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (skb2 == NULL)
+		return -ENOMEM;
+
+	nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
+			 IPSET_CMD_PROTOCOL);
+	if (!nlh2)
+		goto nlmsg_failure;
+	NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
+	nlmsg_end(skb2, nlh2);
+
+	ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+
+nla_put_failure:
+	nlmsg_cancel(skb2, nlh2);
+nlmsg_failure:
+	kfree_skb(skb2);
+	return -EMSGSIZE;
+}
+
+static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
+	[IPSET_CMD_CREATE]	= {
+		.call		= ip_set_create,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_create_policy,
+	},
+	[IPSET_CMD_DESTROY]	= {
+		.call		= ip_set_destroy,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname_policy,
+	},
+	[IPSET_CMD_FLUSH]	= {
+		.call		= ip_set_flush,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname_policy,
+	},
+	[IPSET_CMD_RENAME]	= {
+		.call		= ip_set_rename,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname2_policy,
+	},
+	[IPSET_CMD_SWAP]	= {
+		.call		= ip_set_swap,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname2_policy,
+	},
+	[IPSET_CMD_LIST]	= {
+		.call		= ip_set_dump,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname_policy,
+	},
+	[IPSET_CMD_SAVE]	= {
+		.call		= ip_set_dump,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname_policy,
+	},
+	[IPSET_CMD_ADD]	= {
+		.call		= ip_set_uadd,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_adt_policy,
+	},
+	[IPSET_CMD_DEL]	= {
+		.call		= ip_set_udel,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_adt_policy,
+	},
+	[IPSET_CMD_TEST]	= {
+		.call		= ip_set_utest,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_adt_policy,
+	},
+	[IPSET_CMD_HEADER]	= {
+		.call		= ip_set_header,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_setname_policy,
+	},
+	[IPSET_CMD_TYPE]	= {
+		.call		= ip_set_type,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_type_policy,
+	},
+	[IPSET_CMD_PROTOCOL]	= {
+		.call		= ip_set_protocol,
+		.attr_count	= IPSET_ATTR_CMD_MAX,
+		.policy		= ip_set_protocol_policy,
+	},
+};
+
+static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = {
+	.name		= "ip_set",
+	.subsys_id	= NFNL_SUBSYS_IPSET,
+	.cb_count	= IPSET_MSG_MAX,
+	.cb		= ip_set_netlink_subsys_cb,
+};
+
+/* Interface to iptables/ip6tables */
+
+static int
+ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
+{
+	unsigned *op;
+	void *data;
+	int copylen = *len, ret = 0;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+	if (optval != SO_IP_SET)
+		return -EBADF;
+	if (*len < sizeof(unsigned))
+		return -EINVAL;
+
+	data = vmalloc(*len);
+	if (!data)
+		return -ENOMEM;
+	if (copy_from_user(data, user, *len) != 0) {
+		ret = -EFAULT;
+		goto done;
+	}
+	op = (unsigned *) data;
+
+	if (*op < IP_SET_OP_VERSION) {
+		/* Check the version at the beginning of operations */
+		struct ip_set_req_version *req_version = data;
+		if (req_version->version != IPSET_PROTOCOL) {
+			ret = -EPROTO;
+			goto done;
+		}
+	}
+
+	switch (*op) {
+	case IP_SET_OP_VERSION: {
+		struct ip_set_req_version *req_version = data;
+
+		if (*len != sizeof(struct ip_set_req_version)) {
+			ret = -EINVAL;
+			goto done;
+		}
+
+		req_version->version = IPSET_PROTOCOL;
+		ret = copy_to_user(user, req_version,
+				   sizeof(struct ip_set_req_version));
+		goto done;
+	}
+	case IP_SET_OP_GET_BYNAME: {
+		struct ip_set_req_get_set *req_get = data;
+
+		if (*len != sizeof(struct ip_set_req_get_set)) {
+			ret = -EINVAL;
+			goto done;
+		}
+		req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
+		nfnl_lock();
+		req_get->set.index = find_set_id(req_get->set.name);
+		nfnl_unlock();
+		goto copy;
+	}
+	case IP_SET_OP_GET_BYINDEX: {
+		struct ip_set_req_get_set *req_get = data;
+
+		if (*len != sizeof(struct ip_set_req_get_set) ||
+		    req_get->set.index >= ip_set_max) {
+			ret = -EINVAL;
+			goto done;
+		}
+		nfnl_lock();
+		strncpy(req_get->set.name,
+			ip_set_list[req_get->set.index]
+				? ip_set_list[req_get->set.index]->name : "",
+			IPSET_MAXNAMELEN);
+		nfnl_unlock();
+		goto copy;
+	}
+	default:
+		ret = -EBADMSG;
+		goto done;
+	}	/* end of switch(op) */
+
+copy:
+	ret = copy_to_user(user, data, copylen);
+
+done:
+	vfree(data);
+	if (ret > 0)
+		ret = 0;
+	return ret;
+}
+
+static struct nf_sockopt_ops so_set __read_mostly = {
+	.pf		= PF_INET,
+	.get_optmin	= SO_IP_SET,
+	.get_optmax	= SO_IP_SET + 1,
+	.get		= &ip_set_sockfn_get,
+	.owner		= THIS_MODULE,
+};
+
+static int __init
+ip_set_init(void)
+{
+	int ret;
+
+	if (max_sets)
+		ip_set_max = max_sets;
+	if (ip_set_max >= IPSET_INVALID_ID)
+		ip_set_max = IPSET_INVALID_ID - 1;
+
+	ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
+			      GFP_KERNEL);
+	if (!ip_set_list) {
+		pr_err("ip_set: Unable to create ip_set_list\n");
+		return -ENOMEM;
+	}
+
+	ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
+	if (ret != 0) {
+		pr_err("ip_set: cannot register with nfnetlink.\n");
+		kfree(ip_set_list);
+		return ret;
+	}
+	ret = nf_register_sockopt(&so_set);
+	if (ret != 0) {
+		pr_err("SO_SET registry failed: %d\n", ret);
+		nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
+		kfree(ip_set_list);
+		return ret;
+	}
+
+	pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
+	return 0;
+}
+
+static void __exit
+ip_set_fini(void)
+{
+	/* There can't be any existing set */
+	nf_unregister_sockopt(&so_set);
+	nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
+	kfree(ip_set_list);
+	pr_debug("these are the famous last words\n");
+}
+
+module_init(ip_set_init);
+module_exit(ip_set_fini);
diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c
new file mode 100644
index 0000000..8d52272
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_getport.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Get Layer-4 data from the packets */
+
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+#include <linux/netfilter/ipset/ip_set_getport.h>
+
+/* We must handle non-linear skbs */
+static bool
+get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
+	 bool src, __be16 *port, u8 *proto)
+{
+	switch (protocol) {
+	case IPPROTO_TCP: {
+		struct tcphdr _tcph;
+		const struct tcphdr *th;
+
+		th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
+		if (th == NULL)
+			/* No choice either */
+			return false;
+
+		*port = src ? th->source : th->dest;
+		break;
+	}
+	case IPPROTO_UDP: {
+		struct udphdr _udph;
+		const struct udphdr *uh;
+
+		uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
+		if (uh == NULL)
+			/* No choice either */
+			return false;
+
+		*port = src ? uh->source : uh->dest;
+		break;
+	}
+	case IPPROTO_ICMP: {
+		struct icmphdr _ich;
+		const struct icmphdr *ic;
+
+		ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
+		if (ic == NULL)
+			return false;
+
+		*port = (__force __be16)htons((ic->type << 8) | ic->code);
+		break;
+	}
+	case IPPROTO_ICMPV6: {
+		struct icmp6hdr _ich;
+		const struct icmp6hdr *ic;
+
+		ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
+		if (ic == NULL)
+			return false;
+
+		*port = (__force __be16)
+			htons((ic->icmp6_type << 8) | ic->icmp6_code);
+		break;
+	}
+	default:
+		break;
+	}
+	*proto = protocol;
+
+	return true;
+}
+
+bool
+ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
+		    __be16 *port, u8 *proto)
+{
+	const struct iphdr *iph = ip_hdr(skb);
+	unsigned int protooff = ip_hdrlen(skb);
+	int protocol = iph->protocol;
+
+	/* See comments at tcp_match in ip_tables.c */
+	if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
+		return false;
+
+	return get_port(skb, protocol, protooff, src, port, proto);
+}
+EXPORT_SYMBOL_GPL(ip_set_get_ip4_port);
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+bool
+ip_set_get_ip6_port(const struct sk_buff *skb, bool src,
+		    __be16 *port, u8 *proto)
+{
+	int protoff;
+	u8 nexthdr;
+
+	nexthdr = ipv6_hdr(skb)->nexthdr;
+	protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
+	if (protoff < 0)
+		return false;
+
+	return get_port(skb, nexthdr, protoff, src, port, proto);
+}
+EXPORT_SYMBOL_GPL(ip_set_get_ip6_port);
+#endif
+
+bool
+ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port)
+{
+	bool ret;
+	u8 proto;
+
+	switch (pf) {
+	case AF_INET:
+		ret = ip_set_get_ip4_port(skb, src, port, &proto);
+		break;
+	case AF_INET6:
+		ret = ip_set_get_ip6_port(skb, src, port, &proto);
+		break;
+	default:
+		return false;
+	}
+	if (!ret)
+		return ret;
+	switch (proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+		return true;
+	default:
+		return false;
+	}
+}
+EXPORT_SYMBOL_GPL(ip_set_get_ip_port);
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
new file mode 100644
index 0000000..43bcce2
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -0,0 +1,464 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the hash:ip type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:ip type of IP sets");
+MODULE_ALIAS("ip_set_hash:ip");
+
+/* Type specific function prefix */
+#define TYPE		hash_ip
+
+static bool
+hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_ip4_same_set	hash_ip_same_set
+#define hash_ip6_same_set	hash_ip_same_set
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_ip4_elem {
+	__be32 ip;
+};
+
+/* Member elements with timeout support */
+struct hash_ip4_telem {
+	__be32 ip;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
+		    const struct hash_ip4_elem *ip2)
+{
+	return ip1->ip == ip2->ip;
+}
+
+static inline bool
+hash_ip4_data_isnull(const struct hash_ip4_elem *elem)
+{
+	return elem->ip == 0;
+}
+
+static inline void
+hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
+{
+	dst->ip = src->ip;
+}
+
+/* Zero valued IP addresses cannot be stored */
+static inline void
+hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
+{
+	elem->ip = 0;
+}
+
+static inline bool
+hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data)
+{
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
+{
+	const struct hash_ip4_telem *tdata =
+		(const struct hash_ip4_telem *)data;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define IP_SET_HASH_WITH_NETMASK
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
+	      enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	__be32 ip;
+
+	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
+	ip &= ip_set_netmask(h->netmask);
+	if (ip == 0)
+		return -EINVAL;
+
+	return adtfn(set, &ip, h->timeout);
+}
+
+static int
+hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
+	      enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	u32 ip, ip_to, hosts, timeout = h->timeout;
+	__be32 nip;
+	int ret = 0;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
+	if (ret)
+		return ret;
+
+	ip &= ip_set_hostmask(h->netmask);
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST) {
+		nip = htonl(ip);
+		if (nip == 0)
+			return -IPSET_ERR_HASH_ELEM;
+		return adtfn(set, &nip, timeout);
+	}
+
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip > ip_to)
+			swap(ip, ip_to);
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr > 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		ip &= ip_set_hostmask(cidr);
+		ip_to = ip | ~ip_set_hostmask(cidr);
+	} else
+		ip_to = ip;
+
+	hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
+
+	for (; !before(ip_to, ip); ip += hosts) {
+		nip = htonl(ip);
+		if (nip == 0)
+			return -IPSET_ERR_HASH_ELEM;
+		ret = adtfn(set, &nip, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+static bool
+hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout &&
+	       x->netmask == y->netmask;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_ip6_elem {
+	union nf_inet_addr ip;
+};
+
+struct hash_ip6_telem {
+	union nf_inet_addr ip;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
+		    const struct hash_ip6_elem *ip2)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
+}
+
+static inline bool
+hash_ip6_data_isnull(const struct hash_ip6_elem *elem)
+{
+	return ipv6_addr_any(&elem->ip.in6);
+}
+
+static inline void
+hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
+{
+	ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
+}
+
+static inline void
+hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
+{
+	ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0);
+}
+
+static inline void
+ip6_netmask(union nf_inet_addr *ip, u8 prefix)
+{
+	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
+	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
+	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
+	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
+}
+
+static bool
+hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
+{
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
+{
+	const struct hash_ip6_telem *e =
+		(const struct hash_ip6_telem *)data;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
+	      enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	union nf_inet_addr ip;
+
+	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6);
+	ip6_netmask(&ip, h->netmask);
+	if (ipv6_addr_any(&ip.in6))
+		return -EINVAL;
+
+	return adtfn(set, &ip, h->timeout);
+}
+
+static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
+	[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+	[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+};
+
+static int
+hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
+	      enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	union nf_inet_addr ip;
+	u32 timeout = h->timeout;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     tb[IPSET_ATTR_IP_TO] ||
+		     tb[IPSET_ATTR_CIDR]))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip);
+	if (ret)
+		return ret;
+
+	ip6_netmask(&ip, h->netmask);
+	if (ipv6_addr_any(&ip.in6))
+		return -IPSET_ERR_HASH_ELEM;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	ret = adtfn(set, &ip, timeout);
+
+	return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	u8 netmask, hbits;
+	struct ip_set_hash *h;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+	netmask = set->family == AF_INET ? 32 : 128;
+	pr_debug("Create set %s with family %s\n",
+		 set->name, set->family == AF_INET ? "inet" : "inet6");
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	if (tb[IPSET_ATTR_NETMASK]) {
+		netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
+
+		if ((set->family == AF_INET && netmask > 32) ||
+		    (set->family == AF_INET6 && netmask > 128) ||
+		    netmask == 0)
+			return -IPSET_ERR_INVALID_NETMASK;
+	}
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	h->netmask = netmask;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_ip4_tvariant : &hash_ip6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_ip4_gc_init(set);
+		else
+			hash_ip6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_ip4_variant : &hash_ip6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_ip_type __read_mostly = {
+	.name		= "hash:ip",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP,
+	.dimension	= IPSET_DIM_ONE,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= hash_ip_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_NETMASK]	= { .type = NLA_U8  },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_ip_init(void)
+{
+	return ip_set_type_register(&hash_ip_type);
+}
+
+static void __exit
+hash_ip_fini(void)
+{
+	ip_set_type_unregister(&hash_ip_type);
+}
+
+module_init(hash_ip_init);
+module_exit(hash_ip_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
new file mode 100644
index 0000000..b921414
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -0,0 +1,530 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the hash:ip,port type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_getport.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:ip,port type of IP sets");
+MODULE_ALIAS("ip_set_hash:ip,port");
+
+/* Type specific function prefix */
+#define TYPE		hash_ipport
+
+static bool
+hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_ipport4_same_set	hash_ipport_same_set
+#define hash_ipport6_same_set	hash_ipport_same_set
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_ipport4_elem {
+	__be32 ip;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+};
+
+/* Member elements with timeout support */
+struct hash_ipport4_telem {
+	__be32 ip;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
+			const struct hash_ipport4_elem *ip2)
+{
+	return ip1->ip == ip2->ip &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto;
+}
+
+static inline bool
+hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
+		       const struct hash_ipport4_elem *src)
+{
+	dst->ip = src->ip;
+	dst->port = src->port;
+	dst->proto = src->proto;
+}
+
+static inline void
+hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static bool
+hash_ipport4_data_list(struct sk_buff *skb,
+		       const struct hash_ipport4_elem *data)
+{
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ipport4_data_tlist(struct sk_buff *skb,
+			const struct hash_ipport4_elem *data)
+{
+	const struct hash_ipport4_telem *tdata =
+		(const struct hash_ipport4_telem *)data;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
+		  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipport4_elem data = { };
+
+	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
+		  enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipport4_elem data = { };
+	u32 ip, ip_to, p, port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMP))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST ||
+	    !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
+	      tb[IPSET_ATTR_PORT_TO])) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	ip = ntohl(data.ip);
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip > ip_to)
+			swap(ip, ip_to);
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr > 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		ip &= ip_set_hostmask(cidr);
+		ip_to = ip | ~ip_set_hostmask(cidr);
+	} else
+		ip_to = ip;
+
+	port_to = port = ntohs(data.port);
+	if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
+		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+		if (port > port_to)
+			swap(port, port_to);
+	}
+
+	for (; !before(ip_to, ip); ip++)
+		for (p = port; p <= port_to; p++) {
+			data.ip = htonl(ip);
+			data.port = htons(p);
+			ret = adtfn(set, &data, timeout);
+
+			if (ret && !ip_set_eexist(ret, flags))
+				return ret;
+			else
+				ret = 0;
+		}
+	return ret;
+}
+
+static bool
+hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_ipport6_elem {
+	union nf_inet_addr ip;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+};
+
+struct hash_ipport6_telem {
+	union nf_inet_addr ip;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
+			const struct hash_ipport6_elem *ip2)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto;
+}
+
+static inline bool
+hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
+		       const struct hash_ipport6_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static bool
+hash_ipport6_data_list(struct sk_buff *skb,
+		       const struct hash_ipport6_elem *data)
+{
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ipport6_data_tlist(struct sk_buff *skb,
+			const struct hash_ipport6_elem *data)
+{
+	const struct hash_ipport6_telem *e =
+		(const struct hash_ipport6_telem *)data;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
+		  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipport6_elem data = { };
+
+	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
+		  enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipport6_elem data = { };
+	u32 port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     tb[IPSET_ATTR_IP_TO] ||
+		     tb[IPSET_ATTR_CIDR]))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMPV6))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	port = ntohs(data.port);
+	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+	if (port > port_to)
+		swap(port, port_to);
+
+	for (; port <= port_to; port++) {
+		data.port = htons(port);
+		ret = adtfn(set, &data, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	struct ip_set_hash *h;
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	u8 hbits;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_ipport4_gc_init(set);
+		else
+			hash_ipport6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_ipport4_variant : &hash_ipport6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_ipport_type __read_mostly = {
+	.name		= "hash:ip,port",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT,
+	.dimension	= IPSET_DIM_TWO,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= hash_ipport_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_ipport_init(void)
+{
+	return ip_set_type_register(&hash_ipport_type);
+}
+
+static void __exit
+hash_ipport_fini(void)
+{
+	ip_set_type_unregister(&hash_ipport_type);
+}
+
+module_init(hash_ipport_init);
+module_exit(hash_ipport_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
new file mode 100644
index 0000000..4642872
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -0,0 +1,548 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_getport.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
+MODULE_ALIAS("ip_set_hash:ip,port,ip");
+
+/* Type specific function prefix */
+#define TYPE		hash_ipportip
+
+static bool
+hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_ipportip4_same_set	hash_ipportip_same_set
+#define hash_ipportip6_same_set	hash_ipportip_same_set
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_ipportip4_elem {
+	__be32 ip;
+	__be32 ip2;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+};
+
+/* Member elements with timeout support */
+struct hash_ipportip4_telem {
+	__be32 ip;
+	__be32 ip2;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
+			  const struct hash_ipportip4_elem *ip2)
+{
+	return ip1->ip == ip2->ip &&
+	       ip1->ip2 == ip2->ip2 &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto;
+}
+
+static inline bool
+hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
+			 const struct hash_ipportip4_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static bool
+hash_ipportip4_data_list(struct sk_buff *skb,
+		       const struct hash_ipportip4_elem *data)
+{
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ipportip4_data_tlist(struct sk_buff *skb,
+			const struct hash_ipportip4_elem *data)
+{
+	const struct hash_ipportip4_telem *tdata =
+		(const struct hash_ipportip4_telem *)data;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
+		    enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportip4_elem data = { };
+
+	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
+		    enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportip4_elem data = { };
+	u32 ip, ip_to, p, port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMP))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST ||
+	    !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
+	      tb[IPSET_ATTR_PORT_TO])) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	ip = ntohl(data.ip);
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip > ip_to)
+			swap(ip, ip_to);
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr > 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		ip &= ip_set_hostmask(cidr);
+		ip_to = ip | ~ip_set_hostmask(cidr);
+	} else
+		ip_to = ip;
+
+	port_to = port = ntohs(data.port);
+	if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
+		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+		if (port > port_to)
+			swap(port, port_to);
+	}
+
+	for (; !before(ip_to, ip); ip++)
+		for (p = port; p <= port_to; p++) {
+			data.ip = htonl(ip);
+			data.port = htons(p);
+			ret = adtfn(set, &data, timeout);
+
+			if (ret && !ip_set_eexist(ret, flags))
+				return ret;
+			else
+				ret = 0;
+		}
+	return ret;
+}
+
+static bool
+hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_ipportip6_elem {
+	union nf_inet_addr ip;
+	union nf_inet_addr ip2;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+};
+
+struct hash_ipportip6_telem {
+	union nf_inet_addr ip;
+	union nf_inet_addr ip2;
+	__be16 port;
+	u8 proto;
+	u8 padding;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
+			  const struct hash_ipportip6_elem *ip2)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+	       ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto;
+}
+
+static inline bool
+hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
+			 const struct hash_ipportip6_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static bool
+hash_ipportip6_data_list(struct sk_buff *skb,
+			 const struct hash_ipportip6_elem *data)
+{
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ipportip6_data_tlist(struct sk_buff *skb,
+			  const struct hash_ipportip6_elem *data)
+{
+	const struct hash_ipportip6_telem *e =
+		(const struct hash_ipportip6_telem *)data;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
+		    enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportip6_elem data = { };
+
+	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
+		    enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportip6_elem data = { };
+	u32 port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     tb[IPSET_ATTR_IP_TO] ||
+		     tb[IPSET_ATTR_CIDR]))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMPV6))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	port = ntohs(data.port);
+	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+	if (port > port_to)
+		swap(port, port_to);
+
+	for (; port <= port_to; port++) {
+		data.port = htons(port);
+		ret = adtfn(set, &data, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	struct ip_set_hash *h;
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	u8 hbits;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	h = kzalloc(sizeof(*h), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_ipportip4_gc_init(set);
+		else
+			hash_ipportip6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_ipportip4_variant : &hash_ipportip6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_ipportip_type __read_mostly = {
+	.name		= "hash:ip,port,ip",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
+	.dimension	= IPSET_DIM_THREE,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= hash_ipportip_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP2]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_ipportip_init(void)
+{
+	return ip_set_type_register(&hash_ipportip_type);
+}
+
+static void __exit
+hash_ipportip_fini(void)
+{
+	ip_set_type_unregister(&hash_ipportip_type);
+}
+
+module_init(hash_ipportip_init);
+module_exit(hash_ipportip_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
new file mode 100644
index 0000000..2cb84a5
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -0,0 +1,614 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the hash:ip,port,net type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+#include <net/tcp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_getport.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
+MODULE_ALIAS("ip_set_hash:ip,port,net");
+
+/* Type specific function prefix */
+#define TYPE		hash_ipportnet
+
+static bool
+hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_ipportnet4_same_set	hash_ipportnet_same_set
+#define hash_ipportnet6_same_set	hash_ipportnet_same_set
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_ipportnet4_elem {
+	__be32 ip;
+	__be32 ip2;
+	__be16 port;
+	u8 cidr;
+	u8 proto;
+};
+
+/* Member elements with timeout support */
+struct hash_ipportnet4_telem {
+	__be32 ip;
+	__be32 ip2;
+	__be16 port;
+	u8 cidr;
+	u8 proto;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
+			   const struct hash_ipportnet4_elem *ip2)
+{
+	return ip1->ip == ip2->ip &&
+	       ip1->ip2 == ip2->ip2 &&
+	       ip1->cidr == ip2->cidr &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto;
+}
+
+static inline bool
+hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
+			  const struct hash_ipportnet4_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
+{
+	elem->ip2 &= ip_set_netmask(cidr);
+	elem->cidr = cidr;
+}
+
+static inline void
+hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static bool
+hash_ipportnet4_data_list(struct sk_buff *skb,
+			  const struct hash_ipportnet4_elem *data)
+{
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ipportnet4_data_tlist(struct sk_buff *skb,
+			   const struct hash_ipportnet4_elem *data)
+{
+	const struct hash_ipportnet4_telem *tdata =
+		(const struct hash_ipportnet4_telem *)data;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define IP_SET_HASH_WITH_PROTO
+#define IP_SET_HASH_WITH_NETS
+
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
+		     enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportnet4_elem data =
+		{ .cidr = h->nets[0].cidr || HOST_MASK };
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
+	data.ip2 &= ip_set_netmask(data.cidr);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
+		     enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
+	u32 ip, ip_to, p, port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR2])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
+
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+
+	data.ip2 &= ip_set_netmask(data.cidr);
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMP))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST ||
+	    !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
+	      tb[IPSET_ATTR_PORT_TO])) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	ip = ntohl(data.ip);
+	if (tb[IPSET_ATTR_IP_TO]) {
+		ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
+		if (ret)
+			return ret;
+		if (ip > ip_to)
+			swap(ip, ip_to);
+	} else if (tb[IPSET_ATTR_CIDR]) {
+		u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+		if (cidr > 32)
+			return -IPSET_ERR_INVALID_CIDR;
+		ip &= ip_set_hostmask(cidr);
+		ip_to = ip | ~ip_set_hostmask(cidr);
+	} else
+		ip_to = ip;
+
+	port_to = port = ntohs(data.port);
+	if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
+		port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+		if (port > port_to)
+			swap(port, port_to);
+	}
+
+	for (; !before(ip_to, ip); ip++)
+		for (p = port; p <= port_to; p++) {
+			data.ip = htonl(ip);
+			data.port = htons(p);
+			ret = adtfn(set, &data, timeout);
+
+			if (ret && !ip_set_eexist(ret, flags))
+				return ret;
+			else
+				ret = 0;
+		}
+	return ret;
+}
+
+static bool
+hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_ipportnet6_elem {
+	union nf_inet_addr ip;
+	union nf_inet_addr ip2;
+	__be16 port;
+	u8 cidr;
+	u8 proto;
+};
+
+struct hash_ipportnet6_telem {
+	union nf_inet_addr ip;
+	union nf_inet_addr ip2;
+	__be16 port;
+	u8 cidr;
+	u8 proto;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
+			   const struct hash_ipportnet6_elem *ip2)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+	       ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
+	       ip1->cidr == ip2->cidr &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto;
+}
+
+static inline bool
+hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
+			  const struct hash_ipportnet6_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static inline void
+ip6_netmask(union nf_inet_addr *ip, u8 prefix)
+{
+	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
+	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
+	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
+	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
+}
+
+static inline void
+hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
+{
+	ip6_netmask(&elem->ip2, cidr);
+	elem->cidr = cidr;
+}
+
+static bool
+hash_ipportnet6_data_list(struct sk_buff *skb,
+			  const struct hash_ipportnet6_elem *data)
+{
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_ipportnet6_data_tlist(struct sk_buff *skb,
+			   const struct hash_ipportnet6_elem *data)
+{
+	const struct hash_ipportnet6_telem *e =
+		(const struct hash_ipportnet6_telem *)data;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
+		     enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportnet6_elem data =
+		{ .cidr = h->nets[0].cidr || HOST_MASK };
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
+	ip6_netmask(&data.ip2, data.cidr);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
+		     enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
+	u32 port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     tb[IPSET_ATTR_IP_TO] ||
+		     tb[IPSET_ATTR_CIDR]))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR2])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
+
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+
+	ip6_netmask(&data.ip2, data.cidr);
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMPV6))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	port = ntohs(data.port);
+	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+	if (port > port_to)
+		swap(port, port_to);
+
+	for (; port <= port_to; port++) {
+		data.port = htons(port);
+		ret = adtfn(set, &data, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	struct ip_set_hash *h;
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	u8 hbits;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	h = kzalloc(sizeof(*h)
+		    + sizeof(struct ip_set_hash_nets)
+		      * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_ipportnet4_tvariant
+			: &hash_ipportnet6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_ipportnet4_gc_init(set);
+		else
+			hash_ipportnet6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_ipportnet_type __read_mostly = {
+	.name		= "hash:ip,port,net",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
+	.dimension	= IPSET_DIM_THREE,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= hash_ipportnet_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP_TO]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_IP2]	= { .type = NLA_NESTED },
+		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_CIDR2]	= { .type = NLA_U8 },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_ipportnet_init(void)
+{
+	return ip_set_type_register(&hash_ipportnet_type);
+}
+
+static void __exit
+hash_ipportnet_fini(void)
+{
+	ip_set_type_unregister(&hash_ipportnet_type);
+}
+
+module_init(hash_ipportnet_init);
+module_exit(hash_ipportnet_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
new file mode 100644
index 0000000..c4db202
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -0,0 +1,458 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the hash:net type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:net type of IP sets");
+MODULE_ALIAS("ip_set_hash:net");
+
+/* Type specific function prefix */
+#define TYPE		hash_net
+
+static bool
+hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_net4_same_set	hash_net_same_set
+#define hash_net6_same_set	hash_net_same_set
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_net4_elem {
+	__be32 ip;
+	u16 padding0;
+	u8 padding1;
+	u8 cidr;
+};
+
+/* Member elements with timeout support */
+struct hash_net4_telem {
+	__be32 ip;
+	u16 padding0;
+	u8 padding1;
+	u8 cidr;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_net4_data_equal(const struct hash_net4_elem *ip1,
+		    const struct hash_net4_elem *ip2)
+{
+	return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
+}
+
+static inline bool
+hash_net4_data_isnull(const struct hash_net4_elem *elem)
+{
+	return elem->cidr == 0;
+}
+
+static inline void
+hash_net4_data_copy(struct hash_net4_elem *dst,
+		    const struct hash_net4_elem *src)
+{
+	dst->ip = src->ip;
+	dst->cidr = src->cidr;
+}
+
+static inline void
+hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
+{
+	elem->ip &= ip_set_netmask(cidr);
+	elem->cidr = cidr;
+}
+
+/* Zero CIDR values cannot be stored */
+static inline void
+hash_net4_data_zero_out(struct hash_net4_elem *elem)
+{
+	elem->cidr = 0;
+}
+
+static bool
+hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
+{
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
+{
+	const struct hash_net4_telem *tdata =
+		(const struct hash_net4_telem *)data;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define IP_SET_HASH_WITH_NETS
+
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
+	       enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_net4_elem data = { .cidr = h->nets[0].cidr || HOST_MASK };
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	data.ip &= ip_set_netmask(data.cidr);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
+	       enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_net4_elem data = { .cidr = HOST_MASK };
+	u32 timeout = h->timeout;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+
+	data.ip &= ip_set_netmask(data.cidr);
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	ret = adtfn(set, &data, timeout);
+
+	return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+static bool
+hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_net6_elem {
+	union nf_inet_addr ip;
+	u16 padding0;
+	u8 padding1;
+	u8 cidr;
+};
+
+struct hash_net6_telem {
+	union nf_inet_addr ip;
+	u16 padding0;
+	u8 padding1;
+	u8 cidr;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_net6_data_equal(const struct hash_net6_elem *ip1,
+		     const struct hash_net6_elem *ip2)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+	       ip1->cidr == ip2->cidr;
+}
+
+static inline bool
+hash_net6_data_isnull(const struct hash_net6_elem *elem)
+{
+	return elem->cidr == 0;
+}
+
+static inline void
+hash_net6_data_copy(struct hash_net6_elem *dst,
+		    const struct hash_net6_elem *src)
+{
+	ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
+	dst->cidr = src->cidr;
+}
+
+static inline void
+hash_net6_data_zero_out(struct hash_net6_elem *elem)
+{
+	elem->cidr = 0;
+}
+
+static inline void
+ip6_netmask(union nf_inet_addr *ip, u8 prefix)
+{
+	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
+	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
+	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
+	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
+}
+
+static inline void
+hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
+{
+	ip6_netmask(&elem->ip, cidr);
+	elem->cidr = cidr;
+}
+
+static bool
+hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
+{
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
+{
+	const struct hash_net6_telem *e =
+		(const struct hash_net6_telem *)data;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
+	       enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_net6_elem data = { .cidr = h->nets[0].cidr || HOST_MASK };
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6_netmask(&data.ip, data.cidr);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
+	       enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_net6_elem data = { .cidr = HOST_MASK };
+	u32 timeout = h->timeout;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+
+	ip6_netmask(&data.ip, data.cidr);
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	ret = adtfn(set, &data, timeout);
+
+	return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	struct ip_set_hash *h;
+	u8 hbits;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	h = kzalloc(sizeof(*h)
+		    + sizeof(struct ip_set_hash_nets)
+		      * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_net4_tvariant : &hash_net6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_net4_gc_init(set);
+		else
+			hash_net6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_net4_variant : &hash_net6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_net_type __read_mostly = {
+	.name		= "hash:net",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP,
+	.dimension	= IPSET_DIM_ONE,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= hash_net_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_net_init(void)
+{
+	return ip_set_type_register(&hash_net_type);
+}
+
+static void __exit
+hash_net_fini(void)
+{
+	ip_set_type_unregister(&hash_net_type);
+}
+
+module_init(hash_net_init);
+module_exit(hash_net_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
new file mode 100644
index 0000000..8598676
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -0,0 +1,564 @@
+/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the hash:net,port type */
+
+#include <linux/jhash.h>
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <linux/random.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+#include <net/netlink.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter/ipset/pfxlen.h>
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_getport.h>
+#include <linux/netfilter/ipset/ip_set_hash.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("hash:net,port type of IP sets");
+MODULE_ALIAS("ip_set_hash:net,port");
+
+/* Type specific function prefix */
+#define TYPE		hash_netport
+
+static bool
+hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
+
+#define hash_netport4_same_set	hash_netport_same_set
+#define hash_netport6_same_set	hash_netport_same_set
+
+/* The type variant functions: IPv4 */
+
+/* Member elements without timeout */
+struct hash_netport4_elem {
+	__be32 ip;
+	__be16 port;
+	u8 proto;
+	u8 cidr;
+};
+
+/* Member elements with timeout support */
+struct hash_netport4_telem {
+	__be32 ip;
+	__be16 port;
+	u8 proto;
+	u8 cidr;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
+			 const struct hash_netport4_elem *ip2)
+{
+	return ip1->ip == ip2->ip &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto &&
+	       ip1->cidr == ip2->cidr;
+}
+
+static inline bool
+hash_netport4_data_isnull(const struct hash_netport4_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_netport4_data_copy(struct hash_netport4_elem *dst,
+			const struct hash_netport4_elem *src)
+{
+	dst->ip = src->ip;
+	dst->port = src->port;
+	dst->proto = src->proto;
+	dst->cidr = src->cidr;
+}
+
+static inline void
+hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
+{
+	elem->ip &= ip_set_netmask(cidr);
+	elem->cidr = cidr;
+}
+
+static inline void
+hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static bool
+hash_netport4_data_list(struct sk_buff *skb,
+			const struct hash_netport4_elem *data)
+{
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_netport4_data_tlist(struct sk_buff *skb,
+			 const struct hash_netport4_elem *data)
+{
+	const struct hash_netport4_telem *tdata =
+		(const struct hash_netport4_telem *)data;
+
+	NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(tdata->timeout)));
+
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#define IP_SET_HASH_WITH_PROTO
+#define IP_SET_HASH_WITH_NETS
+
+#define PF		4
+#define HOST_MASK	32
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
+		   enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netport4_elem data = {
+		.cidr = h->nets[0].cidr || HOST_MASK };
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
+	data.ip &= ip_set_netmask(data.cidr);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
+		   enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netport4_elem data = { .cidr = HOST_MASK };
+	u32 port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+	data.ip &= ip_set_netmask(data.cidr);
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMP))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	port = ntohs(data.port);
+	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+	if (port > port_to)
+		swap(port, port_to);
+
+	for (; port <= port_to; port++) {
+		data.port = htons(port);
+		ret = adtfn(set, &data, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+static bool
+hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct ip_set_hash *x = a->data;
+	const struct ip_set_hash *y = b->data;
+
+	/* Resizing changes htable_bits, so we ignore it */
+	return x->maxelem == y->maxelem &&
+	       x->timeout == y->timeout;
+}
+
+/* The type variant functions: IPv6 */
+
+struct hash_netport6_elem {
+	union nf_inet_addr ip;
+	__be16 port;
+	u8 proto;
+	u8 cidr;
+};
+
+struct hash_netport6_telem {
+	union nf_inet_addr ip;
+	__be16 port;
+	u8 proto;
+	u8 cidr;
+	unsigned long timeout;
+};
+
+static inline bool
+hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
+			 const struct hash_netport6_elem *ip2)
+{
+	return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
+	       ip1->port == ip2->port &&
+	       ip1->proto == ip2->proto &&
+	       ip1->cidr == ip2->cidr;
+}
+
+static inline bool
+hash_netport6_data_isnull(const struct hash_netport6_elem *elem)
+{
+	return elem->proto == 0;
+}
+
+static inline void
+hash_netport6_data_copy(struct hash_netport6_elem *dst,
+			const struct hash_netport6_elem *src)
+{
+	memcpy(dst, src, sizeof(*dst));
+}
+
+static inline void
+hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
+{
+	elem->proto = 0;
+}
+
+static inline void
+ip6_netmask(union nf_inet_addr *ip, u8 prefix)
+{
+	ip->ip6[0] &= ip_set_netmask6(prefix)[0];
+	ip->ip6[1] &= ip_set_netmask6(prefix)[1];
+	ip->ip6[2] &= ip_set_netmask6(prefix)[2];
+	ip->ip6[3] &= ip_set_netmask6(prefix)[3];
+}
+
+static inline void
+hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
+{
+	ip6_netmask(&elem->ip, cidr);
+	elem->cidr = cidr;
+}
+
+static bool
+hash_netport6_data_list(struct sk_buff *skb,
+			const struct hash_netport6_elem *data)
+{
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+static bool
+hash_netport6_data_tlist(struct sk_buff *skb,
+			 const struct hash_netport6_elem *data)
+{
+	const struct hash_netport6_telem *e =
+		(const struct hash_netport6_telem *)data;
+
+	NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
+	NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
+	NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
+	NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
+	NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+		      htonl(ip_set_timeout_get(e->timeout)));
+	return 0;
+
+nla_put_failure:
+	return 1;
+}
+
+#undef PF
+#undef HOST_MASK
+
+#define PF		6
+#define HOST_MASK	128
+#include <linux/netfilter/ipset/ip_set_ahash.h>
+
+static int
+hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
+		   enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netport6_elem data = {
+		.cidr = h->nets[0].cidr || HOST_MASK };
+
+	if (data.cidr == 0)
+		return -EINVAL;
+	if (adt == IPSET_TEST)
+		data.cidr = HOST_MASK;
+
+	if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
+				 &data.port, &data.proto))
+		return -EINVAL;
+
+	ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
+	ip6_netmask(&data.ip, data.cidr);
+
+	return adtfn(set, &data, h->timeout);
+}
+
+static int
+hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
+		   enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	const struct ip_set_hash *h = set->data;
+	ipset_adtfn adtfn = set->variant->adt[adt];
+	struct hash_netport6_elem data = { .cidr = HOST_MASK };
+	u32 port, port_to;
+	u32 timeout = h->timeout;
+	bool with_ports = false;
+	int ret;
+
+	if (unlikely(!tb[IPSET_ATTR_IP] ||
+		     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
+	if (ret)
+		return ret;
+
+	if (tb[IPSET_ATTR_CIDR])
+		data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
+	if (!data.cidr)
+		return -IPSET_ERR_INVALID_CIDR;
+	ip6_netmask(&data.ip, data.cidr);
+
+	if (tb[IPSET_ATTR_PORT])
+		data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
+	else
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_PROTO]) {
+		data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
+		with_ports = ip_set_proto_with_ports(data.proto);
+
+		if (data.proto == 0)
+			return -IPSET_ERR_INVALID_PROTO;
+	} else
+		return -IPSET_ERR_MISSING_PROTO;
+
+	if (!(with_ports || data.proto == IPPROTO_ICMPV6))
+		data.port = 0;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout(h->timeout))
+			return -IPSET_ERR_TIMEOUT;
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
+		ret = adtfn(set, &data, timeout);
+		return ip_set_eexist(ret, flags) ? 0 : ret;
+	}
+
+	port = ntohs(data.port);
+	port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
+	if (port > port_to)
+		swap(port, port_to);
+
+	for (; port <= port_to; port++) {
+		data.port = htons(port);
+		ret = adtfn(set, &data, timeout);
+
+		if (ret && !ip_set_eexist(ret, flags))
+			return ret;
+		else
+			ret = 0;
+	}
+	return ret;
+}
+
+/* Create hash:ip type of sets */
+
+static int
+hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	struct ip_set_hash *h;
+	u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
+	u8 hbits;
+
+	if (!(set->family == AF_INET || set->family == AF_INET6))
+		return -IPSET_ERR_INVALID_FAMILY;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_HASHSIZE]) {
+		hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
+		if (hashsize < IPSET_MIMINAL_HASHSIZE)
+			hashsize = IPSET_MIMINAL_HASHSIZE;
+	}
+
+	if (tb[IPSET_ATTR_MAXELEM])
+		maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
+
+	h = kzalloc(sizeof(*h)
+		    + sizeof(struct ip_set_hash_nets)
+		      * (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
+	if (!h)
+		return -ENOMEM;
+
+	h->maxelem = maxelem;
+	get_random_bytes(&h->initval, sizeof(h->initval));
+	h->timeout = IPSET_NO_TIMEOUT;
+
+	hbits = htable_bits(hashsize);
+	h->table = ip_set_alloc(
+			sizeof(struct htable)
+			+ jhash_size(hbits) * sizeof(struct hbucket));
+	if (!h->table) {
+		kfree(h);
+		return -ENOMEM;
+	}
+	h->table->htable_bits = hbits;
+
+	set->data = h;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+
+		set->variant = set->family == AF_INET
+			? &hash_netport4_tvariant : &hash_netport6_tvariant;
+
+		if (set->family == AF_INET)
+			hash_netport4_gc_init(set);
+		else
+			hash_netport6_gc_init(set);
+	} else {
+		set->variant = set->family == AF_INET
+			? &hash_netport4_variant : &hash_netport6_variant;
+	}
+
+	pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
+		 set->name, jhash_size(h->table->htable_bits),
+		 h->table->htable_bits, h->maxelem, set->data, h->table);
+
+	return 0;
+}
+
+static struct ip_set_type hash_netport_type __read_mostly = {
+	.name		= "hash:net,port",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_IP | IPSET_TYPE_PORT,
+	.dimension	= IPSET_DIM_TWO,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= hash_netport_create,
+	.create_policy	= {
+		[IPSET_ATTR_HASHSIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_MAXELEM]	= { .type = NLA_U32 },
+		[IPSET_ATTR_PROBES]	= { .type = NLA_U8 },
+		[IPSET_ATTR_RESIZE]	= { .type = NLA_U8  },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_IP]		= { .type = NLA_NESTED },
+		[IPSET_ATTR_PORT]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PORT_TO]	= { .type = NLA_U16 },
+		[IPSET_ATTR_PROTO]	= { .type = NLA_U8 },
+		[IPSET_ATTR_CIDR]	= { .type = NLA_U8 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+hash_netport_init(void)
+{
+	return ip_set_type_register(&hash_netport_type);
+}
+
+static void __exit
+hash_netport_fini(void)
+{
+	ip_set_type_unregister(&hash_netport_type);
+}
+
+module_init(hash_netport_init);
+module_exit(hash_netport_fini);
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
new file mode 100644
index 0000000..a47c329
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -0,0 +1,584 @@
+/* Copyright (C) 2008-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module implementing an IP set type: the list:set type */
+
+#include <linux/module.h>
+#include <linux/ip.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+
+#include <linux/netfilter/ipset/ip_set.h>
+#include <linux/netfilter/ipset/ip_set_timeout.h>
+#include <linux/netfilter/ipset/ip_set_list.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("list:set type of IP sets");
+MODULE_ALIAS("ip_set_list:set");
+
+/* Member elements without and with timeout */
+struct set_elem {
+	ip_set_id_t id;
+};
+
+struct set_telem {
+	ip_set_id_t id;
+	unsigned long timeout;
+};
+
+/* Type structure */
+struct list_set {
+	size_t dsize;		/* element size */
+	u32 size;		/* size of set list array */
+	u32 timeout;		/* timeout value */
+	struct timer_list gc;	/* garbage collection */
+	struct set_elem members[0]; /* the set members */
+};
+
+static inline struct set_elem *
+list_set_elem(const struct list_set *map, u32 id)
+{
+	return (struct set_elem *)((char *)map->members + id * map->dsize);
+}
+
+static inline bool
+list_set_timeout(const struct list_set *map, u32 id)
+{
+	const struct set_telem *elem =
+		(const struct set_telem *) list_set_elem(map, id);
+
+	return ip_set_timeout_test(elem->timeout);
+}
+
+static inline bool
+list_set_expired(const struct list_set *map, u32 id)
+{
+	const struct set_telem *elem =
+		(const struct set_telem *) list_set_elem(map, id);
+
+	return ip_set_timeout_expired(elem->timeout);
+}
+
+static inline int
+list_set_exist(const struct set_telem *elem)
+{
+	return elem->id != IPSET_INVALID_ID &&
+	       !ip_set_timeout_expired(elem->timeout);
+}
+
+/* Set list without and with timeout */
+
+static int
+list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
+	      enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
+{
+	struct list_set *map = set->data;
+	struct set_elem *elem;
+	u32 i;
+	int ret;
+
+	for (i = 0; i < map->size; i++) {
+		elem = list_set_elem(map, i);
+		if (elem->id == IPSET_INVALID_ID)
+			return 0;
+		if (with_timeout(map->timeout) && list_set_expired(map, i))
+			continue;
+		switch (adt) {
+		case IPSET_TEST:
+			ret = ip_set_test(elem->id, skb, pf, dim, flags);
+			if (ret > 0)
+				return ret;
+			break;
+		case IPSET_ADD:
+			ret = ip_set_add(elem->id, skb, pf, dim, flags);
+			if (ret == 0)
+				return ret;
+			break;
+		case IPSET_DEL:
+			ret = ip_set_del(elem->id, skb, pf, dim, flags);
+			if (ret == 0)
+				return ret;
+			break;
+		default:
+			break;
+		}
+	}
+	return -EINVAL;
+}
+
+static bool
+next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
+{
+	const struct set_elem *elem;
+
+	if (i + 1 < map->size) {
+		elem = list_set_elem(map, i + 1);
+		return !!(elem->id == id &&
+			  !(with_timeout(map->timeout) &&
+			    list_set_expired(map, i + 1)));
+	}
+
+	return 0;
+}
+
+static void
+list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
+{
+	struct set_elem *e;
+
+	for (; i < map->size; i++) {
+		e = list_set_elem(map, i);
+		swap(e->id, id);
+		if (e->id == IPSET_INVALID_ID)
+			break;
+	}
+}
+
+static void
+list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
+	       unsigned long timeout)
+{
+	struct set_telem *e;
+
+	for (; i < map->size; i++) {
+		e = (struct set_telem *)list_set_elem(map, i);
+		swap(e->id, id);
+		if (e->id == IPSET_INVALID_ID)
+			break;
+		swap(e->timeout, timeout);
+	}
+}
+
+static int
+list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
+	     unsigned long timeout)
+{
+	const struct set_elem *e = list_set_elem(map, i);
+
+	if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
+		/* Last element replaced: e.g. add new,before,last */
+		ip_set_put_byindex(e->id);
+	if (with_timeout(map->timeout))
+		list_elem_tadd(map, i, id, timeout);
+	else
+		list_elem_add(map, i, id);
+
+	return 0;
+}
+
+static int
+list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
+{
+	struct set_elem *a = list_set_elem(map, i), *b;
+
+	ip_set_put_byindex(id);
+
+	for (; i < map->size - 1; i++) {
+		b = list_set_elem(map, i + 1);
+		a->id = b->id;
+		if (with_timeout(map->timeout))
+			((struct set_telem *)a)->timeout =
+				((struct set_telem *)b)->timeout;
+		a = b;
+		if (a->id == IPSET_INVALID_ID)
+			break;
+	}
+	/* Last element */
+	a->id = IPSET_INVALID_ID;
+	return 0;
+}
+
+static int
+list_set_uadt(struct ip_set *set, struct nlattr *tb[],
+	      enum ipset_adt adt, u32 *lineno, u32 flags)
+{
+	struct list_set *map = set->data;
+	bool with_timeout = with_timeout(map->timeout);
+	int before = 0;
+	u32 timeout = map->timeout;
+	ip_set_id_t id, refid = IPSET_INVALID_ID;
+	const struct set_elem *elem;
+	struct ip_set *s;
+	u32 i;
+	int ret = 0;
+
+	if (unlikely(!tb[IPSET_ATTR_NAME] ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_LINENO])
+		*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
+
+	id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
+	if (id == IPSET_INVALID_ID)
+		return -IPSET_ERR_NAME;
+	/* "Loop detection" */
+	if (s->type->features & IPSET_TYPE_NAME) {
+		ret = -IPSET_ERR_LOOP;
+		goto finish;
+	}
+
+	if (tb[IPSET_ATTR_CADT_FLAGS]) {
+		u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
+		before = f & IPSET_FLAG_BEFORE;
+	}
+
+	if (before && !tb[IPSET_ATTR_NAMEREF]) {
+		ret = -IPSET_ERR_BEFORE;
+		goto finish;
+	}
+
+	if (tb[IPSET_ATTR_NAMEREF]) {
+		refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]),
+					  &s);
+		if (refid == IPSET_INVALID_ID) {
+			ret = -IPSET_ERR_NAMEREF;
+			goto finish;
+		}
+		if (!before)
+			before = -1;
+	}
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!with_timeout) {
+			ret = -IPSET_ERR_TIMEOUT;
+			goto finish;
+		}
+		timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
+	}
+
+	switch (adt) {
+	case IPSET_TEST:
+		for (i = 0; i < map->size && !ret; i++) {
+			elem = list_set_elem(map, i);
+			if (elem->id == IPSET_INVALID_ID ||
+			    (before != 0 && i + 1 >= map->size))
+				break;
+			else if (with_timeout && list_set_expired(map, i))
+				continue;
+			else if (before > 0 && elem->id == id)
+				ret = next_id_eq(map, i, refid);
+			else if (before < 0 && elem->id == refid)
+				ret = next_id_eq(map, i, id);
+			else if (before == 0 && elem->id == id)
+				ret = 1;
+		}
+		break;
+	case IPSET_ADD:
+		for (i = 0; i < map->size && !ret; i++) {
+			elem = list_set_elem(map, i);
+			if (elem->id == id &&
+			    !(with_timeout && list_set_expired(map, i)))
+				ret = -IPSET_ERR_EXIST;
+		}
+		if (ret == -IPSET_ERR_EXIST)
+			break;
+		ret = -IPSET_ERR_LIST_FULL;
+		for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
+			elem = list_set_elem(map, i);
+			if (elem->id == IPSET_INVALID_ID)
+				ret = before != 0 ? -IPSET_ERR_REF_EXIST
+					: list_set_add(map, i, id, timeout);
+			else if (elem->id != refid)
+				continue;
+			else if (with_timeout && list_set_expired(map, i))
+				ret = -IPSET_ERR_REF_EXIST;
+			else if (before)
+				ret = list_set_add(map, i, id, timeout);
+			else if (i + 1 < map->size)
+				ret = list_set_add(map, i + 1, id, timeout);
+		}
+		break;
+	case IPSET_DEL:
+		ret = -IPSET_ERR_EXIST;
+		for (i = 0; i < map->size && ret == -IPSET_ERR_EXIST; i++) {
+			elem = list_set_elem(map, i);
+			if (elem->id == IPSET_INVALID_ID) {
+				ret = before != 0 ? -IPSET_ERR_REF_EXIST
+						  : -IPSET_ERR_EXIST;
+				break;
+			} else if (with_timeout && list_set_expired(map, i))
+				continue;
+			else if (elem->id == id &&
+				 (before == 0 ||
+				  (before > 0 &&
+				   next_id_eq(map, i, refid))))
+				ret = list_set_del(map, id, i);
+			else if (before < 0 &&
+				 elem->id == refid &&
+				 next_id_eq(map, i, id))
+				ret = list_set_del(map, id, i + 1);
+		}
+		break;
+	default:
+		break;
+	}
+
+finish:
+	if (refid != IPSET_INVALID_ID)
+		ip_set_put_byindex(refid);
+	if (adt != IPSET_ADD || ret)
+		ip_set_put_byindex(id);
+
+	return ip_set_eexist(ret, flags) ? 0 : ret;
+}
+
+static void
+list_set_flush(struct ip_set *set)
+{
+	struct list_set *map = set->data;
+	struct set_elem *elem;
+	u32 i;
+
+	for (i = 0; i < map->size; i++) {
+		elem = list_set_elem(map, i);
+		if (elem->id != IPSET_INVALID_ID) {
+			ip_set_put_byindex(elem->id);
+			elem->id = IPSET_INVALID_ID;
+		}
+	}
+}
+
+static void
+list_set_destroy(struct ip_set *set)
+{
+	struct list_set *map = set->data;
+
+	if (with_timeout(map->timeout))
+		del_timer_sync(&map->gc);
+	list_set_flush(set);
+	kfree(map);
+
+	set->data = NULL;
+}
+
+static int
+list_set_head(struct ip_set *set, struct sk_buff *skb)
+{
+	const struct list_set *map = set->data;
+	struct nlattr *nested;
+
+	nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+	if (!nested)
+		goto nla_put_failure;
+	NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
+	if (with_timeout(map->timeout))
+		NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
+	NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
+		      htonl(atomic_read(&set->ref) - 1));
+	NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
+		      htonl(sizeof(*map) + map->size * map->dsize));
+	ipset_nest_end(skb, nested);
+
+	return 0;
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int
+list_set_list(const struct ip_set *set,
+	      struct sk_buff *skb, struct netlink_callback *cb)
+{
+	const struct list_set *map = set->data;
+	struct nlattr *atd, *nested;
+	u32 i, first = cb->args[2];
+	const struct set_elem *e;
+
+	atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
+	if (!atd)
+		return -EMSGSIZE;
+	for (; cb->args[2] < map->size; cb->args[2]++) {
+		i = cb->args[2];
+		e = list_set_elem(map, i);
+		if (e->id == IPSET_INVALID_ID)
+			goto finish;
+		if (with_timeout(map->timeout) && list_set_expired(map, i))
+			continue;
+		nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
+		if (!nested) {
+			if (i == first) {
+				nla_nest_cancel(skb, atd);
+				return -EMSGSIZE;
+			} else
+				goto nla_put_failure;
+		}
+		NLA_PUT_STRING(skb, IPSET_ATTR_NAME,
+			       ip_set_name_byindex(e->id));
+		if (with_timeout(map->timeout)) {
+			const struct set_telem *te =
+				(const struct set_telem *) e;
+			NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
+				      htonl(ip_set_timeout_get(te->timeout)));
+		}
+		ipset_nest_end(skb, nested);
+	}
+finish:
+	ipset_nest_end(skb, atd);
+	/* Set listing finished */
+	cb->args[2] = 0;
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nested);
+	ipset_nest_end(skb, atd);
+	if (unlikely(i == first)) {
+		cb->args[2] = 0;
+		return -EMSGSIZE;
+	}
+	return 0;
+}
+
+static bool
+list_set_same_set(const struct ip_set *a, const struct ip_set *b)
+{
+	const struct list_set *x = a->data;
+	const struct list_set *y = b->data;
+
+	return x->size == y->size &&
+	       x->timeout == y->timeout;
+}
+
+static const struct ip_set_type_variant list_set = {
+	.kadt	= list_set_kadt,
+	.uadt	= list_set_uadt,
+	.destroy = list_set_destroy,
+	.flush	= list_set_flush,
+	.head	= list_set_head,
+	.list	= list_set_list,
+	.same_set = list_set_same_set,
+};
+
+static void
+list_set_gc(unsigned long ul_set)
+{
+	struct ip_set *set = (struct ip_set *) ul_set;
+	struct list_set *map = set->data;
+	struct set_telem *e;
+	u32 i;
+
+	/* We run parallel with other readers (test element)
+	 * but adding/deleting new entries is locked out */
+	read_lock_bh(&set->lock);
+	for (i = map->size - 1; i >= 0; i--) {
+		e = (struct set_telem *) list_set_elem(map, i);
+		if (e->id != IPSET_INVALID_ID &&
+		    list_set_expired(map, i))
+			list_set_del(map, e->id, i);
+	}
+	read_unlock_bh(&set->lock);
+
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+static void
+list_set_gc_init(struct ip_set *set)
+{
+	struct list_set *map = set->data;
+
+	init_timer(&map->gc);
+	map->gc.data = (unsigned long) set;
+	map->gc.function = list_set_gc;
+	map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
+	add_timer(&map->gc);
+}
+
+/* Create list:set type of sets */
+
+static bool
+init_list_set(struct ip_set *set, u32 size, size_t dsize,
+	      unsigned long timeout)
+{
+	struct list_set *map;
+	struct set_elem *e;
+	u32 i;
+
+	map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL);
+	if (!map)
+		return false;
+
+	map->size = size;
+	map->dsize = dsize;
+	map->timeout = timeout;
+	set->data = map;
+
+	for (i = 0; i < size; i++) {
+		e = list_set_elem(map, i);
+		e->id = IPSET_INVALID_ID;
+	}
+
+	return true;
+}
+
+static int
+list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
+{
+	u32 size = IP_SET_LIST_DEFAULT_SIZE;
+
+	if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
+		     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
+		return -IPSET_ERR_PROTOCOL;
+
+	if (tb[IPSET_ATTR_SIZE])
+		size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
+	if (size < IP_SET_LIST_MIN_SIZE)
+		size = IP_SET_LIST_MIN_SIZE;
+
+	if (tb[IPSET_ATTR_TIMEOUT]) {
+		if (!init_list_set(set, size, sizeof(struct set_telem),
+				   ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT])))
+			return -ENOMEM;
+
+		list_set_gc_init(set);
+	} else {
+		if (!init_list_set(set, size, sizeof(struct set_elem),
+				   IPSET_NO_TIMEOUT))
+			return -ENOMEM;
+	}
+	set->variant = &list_set;
+	return 0;
+}
+
+static struct ip_set_type list_set_type __read_mostly = {
+	.name		= "list:set",
+	.protocol	= IPSET_PROTOCOL,
+	.features	= IPSET_TYPE_NAME | IPSET_DUMP_LAST,
+	.dimension	= IPSET_DIM_ONE,
+	.family		= AF_UNSPEC,
+	.revision	= 0,
+	.create		= list_set_create,
+	.create_policy	= {
+		[IPSET_ATTR_SIZE]	= { .type = NLA_U32 },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+	},
+	.adt_policy	= {
+		[IPSET_ATTR_NAME]	= { .type = NLA_STRING,
+					    .len = IPSET_MAXNAMELEN },
+		[IPSET_ATTR_NAMEREF]	= { .type = NLA_STRING,
+					    .len = IPSET_MAXNAMELEN },
+		[IPSET_ATTR_TIMEOUT]	= { .type = NLA_U32 },
+		[IPSET_ATTR_LINENO]	= { .type = NLA_U32 },
+		[IPSET_ATTR_CADT_FLAGS]	= { .type = NLA_U32 },
+	},
+	.me		= THIS_MODULE,
+};
+
+static int __init
+list_set_init(void)
+{
+	return ip_set_type_register(&list_set_type);
+}
+
+static void __exit
+list_set_fini(void)
+{
+	ip_set_type_unregister(&list_set_type);
+}
+
+module_init(list_set_init);
+module_exit(list_set_fini);
diff --git a/net/netfilter/ipset/pfxlen.c b/net/netfilter/ipset/pfxlen.c
new file mode 100644
index 0000000..23f8c81
--- /dev/null
+++ b/net/netfilter/ipset/pfxlen.c
@@ -0,0 +1,291 @@
+#include <linux/netfilter/ipset/pfxlen.h>
+
+/*
+ * Prefixlen maps for fast conversions, by Jan Engelhardt.
+ */
+
+#define E(a, b, c, d) \
+	{.ip6 = { \
+		__constant_htonl(a), __constant_htonl(b), \
+		__constant_htonl(c), __constant_htonl(d), \
+	} }
+
+/*
+ * This table works for both IPv4 and IPv6;
+ * just use prefixlen_netmask_map[prefixlength].ip.
+ */
+const union nf_inet_addr ip_set_netmask_map[] = {
+	E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
+};
+EXPORT_SYMBOL_GPL(ip_set_netmask_map);
+
+#undef  E
+#define E(a, b, c, d) 						\
+	{.ip6 = { (__force __be32) a, (__force __be32) b,	\
+		  (__force __be32) c, (__force __be32) d,	\
+	} }
+
+/*
+ * This table works for both IPv4 and IPv6;
+ * just use prefixlen_hostmask_map[prefixlength].ip.
+ */
+const union nf_inet_addr ip_set_hostmask_map[] = {
+	E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
+	E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
+};
+EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
index a475ede..2dc6de1 100644
--- a/net/netfilter/ipvs/ip_vs_app.c
+++ b/net/netfilter/ipvs/ip_vs_app.c
@@ -43,11 +43,8 @@ EXPORT_SYMBOL(register_ip_vs_app);
 EXPORT_SYMBOL(unregister_ip_vs_app);
 EXPORT_SYMBOL(register_ip_vs_app_inc);
 
-/* ipvs application list head */
-static LIST_HEAD(ip_vs_app_list);
 static DEFINE_MUTEX(__ip_vs_app_mutex);
 
-
 /*
  *	Get an ip_vs_app object
  */
@@ -67,7 +64,8 @@ static inline void ip_vs_app_put(struct ip_vs_app *app)
  *	Allocate/initialize app incarnation and register it in proto apps.
  */
 static int
-ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port)
+ip_vs_app_inc_new(struct net *net, struct ip_vs_app *app, __u16 proto,
+		  __u16 port)
 {
 	struct ip_vs_protocol *pp;
 	struct ip_vs_app *inc;
@@ -98,7 +96,7 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port)
 		}
 	}
 
-	ret = pp->register_app(inc);
+	ret = pp->register_app(net, inc);
 	if (ret)
 		goto out;
 
@@ -119,7 +117,7 @@ ip_vs_app_inc_new(struct ip_vs_app *app, __u16 proto, __u16 port)
  *	Release app incarnation
  */
 static void
-ip_vs_app_inc_release(struct ip_vs_app *inc)
+ip_vs_app_inc_release(struct net *net, struct ip_vs_app *inc)
 {
 	struct ip_vs_protocol *pp;
 
@@ -127,7 +125,7 @@ ip_vs_app_inc_release(struct ip_vs_app *inc)
 		return;
 
 	if (pp->unregister_app)
-		pp->unregister_app(inc);
+		pp->unregister_app(net, inc);
 
 	IP_VS_DBG(9, "%s App %s:%u unregistered\n",
 		  pp->name, inc->name, ntohs(inc->port));
@@ -168,13 +166,14 @@ void ip_vs_app_inc_put(struct ip_vs_app *inc)
  *	Register an application incarnation in protocol applications
  */
 int
-register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port)
+register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto,
+		       __u16 port)
 {
 	int result;
 
 	mutex_lock(&__ip_vs_app_mutex);
 
-	result = ip_vs_app_inc_new(app, proto, port);
+	result = ip_vs_app_inc_new(net, app, proto, port);
 
 	mutex_unlock(&__ip_vs_app_mutex);
 
@@ -185,14 +184,15 @@ register_ip_vs_app_inc(struct ip_vs_app *app, __u16 proto, __u16 port)
 /*
  *	ip_vs_app registration routine
  */
-int register_ip_vs_app(struct ip_vs_app *app)
+int register_ip_vs_app(struct net *net, struct ip_vs_app *app)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	/* increase the module use count */
 	ip_vs_use_count_inc();
 
 	mutex_lock(&__ip_vs_app_mutex);
 
-	list_add(&app->a_list, &ip_vs_app_list);
+	list_add(&app->a_list, &ipvs->app_list);
 
 	mutex_unlock(&__ip_vs_app_mutex);
 
@@ -204,14 +204,14 @@ int register_ip_vs_app(struct ip_vs_app *app)
  *	ip_vs_app unregistration routine
  *	We are sure there are no app incarnations attached to services
  */
-void unregister_ip_vs_app(struct ip_vs_app *app)
+void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app)
 {
 	struct ip_vs_app *inc, *nxt;
 
 	mutex_lock(&__ip_vs_app_mutex);
 
 	list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) {
-		ip_vs_app_inc_release(inc);
+		ip_vs_app_inc_release(net, inc);
 	}
 
 	list_del(&app->a_list);
@@ -226,7 +226,8 @@ void unregister_ip_vs_app(struct ip_vs_app *app)
 /*
  *	Bind ip_vs_conn to its ip_vs_app (called by cp constructor)
  */
-int ip_vs_bind_app(struct ip_vs_conn *cp, struct ip_vs_protocol *pp)
+int ip_vs_bind_app(struct ip_vs_conn *cp,
+		   struct ip_vs_protocol *pp)
 {
 	return pp->app_conn_bind(cp);
 }
@@ -481,11 +482,11 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)
  *	/proc/net/ip_vs_app entry function
  */
 
-static struct ip_vs_app *ip_vs_app_idx(loff_t pos)
+static struct ip_vs_app *ip_vs_app_idx(struct netns_ipvs *ipvs, loff_t pos)
 {
 	struct ip_vs_app *app, *inc;
 
-	list_for_each_entry(app, &ip_vs_app_list, a_list) {
+	list_for_each_entry(app, &ipvs->app_list, a_list) {
 		list_for_each_entry(inc, &app->incs_list, a_list) {
 			if (pos-- == 0)
 				return inc;
@@ -497,19 +498,24 @@ static struct ip_vs_app *ip_vs_app_idx(loff_t pos)
 
 static void *ip_vs_app_seq_start(struct seq_file *seq, loff_t *pos)
 {
+	struct net *net = seq_file_net(seq);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
 	mutex_lock(&__ip_vs_app_mutex);
 
-	return *pos ? ip_vs_app_idx(*pos - 1) : SEQ_START_TOKEN;
+	return *pos ? ip_vs_app_idx(ipvs, *pos - 1) : SEQ_START_TOKEN;
 }
 
 static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct ip_vs_app *inc, *app;
 	struct list_head *e;
+	struct net *net = seq_file_net(seq);
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
 	++*pos;
 	if (v == SEQ_START_TOKEN)
-		return ip_vs_app_idx(0);
+		return ip_vs_app_idx(ipvs, 0);
 
 	inc = v;
 	app = inc->app;
@@ -518,7 +524,7 @@ static void *ip_vs_app_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 		return list_entry(e, struct ip_vs_app, a_list);
 
 	/* go on to next application */
-	for (e = app->a_list.next; e != &ip_vs_app_list; e = e->next) {
+	for (e = app->a_list.next; e != &ipvs->app_list; e = e->next) {
 		app = list_entry(e, struct ip_vs_app, a_list);
 		list_for_each_entry(inc, &app->incs_list, a_list) {
 			return inc;
@@ -557,7 +563,8 @@ static const struct seq_operations ip_vs_app_seq_ops = {
 
 static int ip_vs_app_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ip_vs_app_seq_ops);
+	return seq_open_net(inode, file, &ip_vs_app_seq_ops,
+			    sizeof(struct seq_net_private));
 }
 
 static const struct file_operations ip_vs_app_fops = {
@@ -569,15 +576,35 @@ static const struct file_operations ip_vs_app_fops = {
 };
 #endif
 
-int __init ip_vs_app_init(void)
+static int __net_init __ip_vs_app_init(struct net *net)
 {
-	/* we will replace it with proc_net_ipvs_create() soon */
-	proc_net_fops_create(&init_net, "ip_vs_app", 0, &ip_vs_app_fops);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	INIT_LIST_HEAD(&ipvs->app_list);
+	proc_net_fops_create(net, "ip_vs_app", 0, &ip_vs_app_fops);
 	return 0;
 }
 
+static void __net_exit __ip_vs_app_cleanup(struct net *net)
+{
+	proc_net_remove(net, "ip_vs_app");
+}
+
+static struct pernet_operations ip_vs_app_ops = {
+	.init = __ip_vs_app_init,
+	.exit = __ip_vs_app_cleanup,
+};
+
+int __init ip_vs_app_init(void)
+{
+	int rv;
+
+	rv = register_pernet_subsys(&ip_vs_app_ops);
+	return rv;
+}
+
 
 void ip_vs_app_cleanup(void)
 {
-	proc_net_remove(&init_net, "ip_vs_app");
+	unregister_pernet_subsys(&ip_vs_app_ops);
 }
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index e9adecd..f289306 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -48,35 +48,32 @@
 /*
  * Connection hash size. Default is what was selected at compile time.
 */
-int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
+static int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
 module_param_named(conn_tab_bits, ip_vs_conn_tab_bits, int, 0444);
 MODULE_PARM_DESC(conn_tab_bits, "Set connections' hash size");
 
 /* size and mask values */
-int ip_vs_conn_tab_size;
-int ip_vs_conn_tab_mask;
+int ip_vs_conn_tab_size __read_mostly;
+static int ip_vs_conn_tab_mask __read_mostly;
 
 /*
  *  Connection hash table: for input and output packets lookups of IPVS
  */
-static struct list_head *ip_vs_conn_tab;
+static struct hlist_head *ip_vs_conn_tab __read_mostly;
 
 /*  SLAB cache for IPVS connections */
 static struct kmem_cache *ip_vs_conn_cachep __read_mostly;
 
-/*  counter for current IPVS connections */
-static atomic_t ip_vs_conn_count = ATOMIC_INIT(0);
-
 /*  counter for no client port connections */
 static atomic_t ip_vs_conn_no_cport_cnt = ATOMIC_INIT(0);
 
 /* random value for IPVS connection hash */
-static unsigned int ip_vs_conn_rnd;
+static unsigned int ip_vs_conn_rnd __read_mostly;
 
 /*
  *  Fine locking granularity for big connection hash table
  */
-#define CT_LOCKARRAY_BITS  4
+#define CT_LOCKARRAY_BITS  5
 #define CT_LOCKARRAY_SIZE  (1<<CT_LOCKARRAY_BITS)
 #define CT_LOCKARRAY_MASK  (CT_LOCKARRAY_SIZE-1)
 
@@ -133,19 +130,19 @@ static inline void ct_write_unlock_bh(unsigned key)
 /*
  *	Returns hash value for IPVS connection entry
  */
-static unsigned int ip_vs_conn_hashkey(int af, unsigned proto,
+static unsigned int ip_vs_conn_hashkey(struct net *net, int af, unsigned proto,
 				       const union nf_inet_addr *addr,
 				       __be16 port)
 {
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6)
-		return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
-				    (__force u32)port, proto, ip_vs_conn_rnd)
-			& ip_vs_conn_tab_mask;
+		return (jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
+				    (__force u32)port, proto, ip_vs_conn_rnd) ^
+			((size_t)net>>8)) & ip_vs_conn_tab_mask;
 #endif
-	return jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
-			    ip_vs_conn_rnd)
-		& ip_vs_conn_tab_mask;
+	return (jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
+			    ip_vs_conn_rnd) ^
+		((size_t)net>>8)) & ip_vs_conn_tab_mask;
 }
 
 static unsigned int ip_vs_conn_hashkey_param(const struct ip_vs_conn_param *p,
@@ -166,18 +163,18 @@ static unsigned int ip_vs_conn_hashkey_param(const struct ip_vs_conn_param *p,
 		port = p->vport;
 	}
 
-	return ip_vs_conn_hashkey(p->af, p->protocol, addr, port);
+	return ip_vs_conn_hashkey(p->net, p->af, p->protocol, addr, port);
 }
 
 static unsigned int ip_vs_conn_hashkey_conn(const struct ip_vs_conn *cp)
 {
 	struct ip_vs_conn_param p;
 
-	ip_vs_conn_fill_param(cp->af, cp->protocol, &cp->caddr, cp->cport,
-			      NULL, 0, &p);
+	ip_vs_conn_fill_param(ip_vs_conn_net(cp), cp->af, cp->protocol,
+			      &cp->caddr, cp->cport, NULL, 0, &p);
 
-	if (cp->dest && cp->dest->svc->pe) {
-		p.pe = cp->dest->svc->pe;
+	if (cp->pe) {
+		p.pe = cp->pe;
 		p.pe_data = cp->pe_data;
 		p.pe_data_len = cp->pe_data_len;
 	}
@@ -186,7 +183,7 @@ static unsigned int ip_vs_conn_hashkey_conn(const struct ip_vs_conn *cp)
 }
 
 /*
- *	Hashes ip_vs_conn in ip_vs_conn_tab by proto,addr,port.
+ *	Hashes ip_vs_conn in ip_vs_conn_tab by netns,proto,addr,port.
  *	returns bool success.
  */
 static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
@@ -204,7 +201,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
 	spin_lock(&cp->lock);
 
 	if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
-		list_add(&cp->c_list, &ip_vs_conn_tab[hash]);
+		hlist_add_head(&cp->c_list, &ip_vs_conn_tab[hash]);
 		cp->flags |= IP_VS_CONN_F_HASHED;
 		atomic_inc(&cp->refcnt);
 		ret = 1;
@@ -237,7 +234,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
 	spin_lock(&cp->lock);
 
 	if (cp->flags & IP_VS_CONN_F_HASHED) {
-		list_del(&cp->c_list);
+		hlist_del(&cp->c_list);
 		cp->flags &= ~IP_VS_CONN_F_HASHED;
 		atomic_dec(&cp->refcnt);
 		ret = 1;
@@ -262,18 +259,20 @@ __ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
+	struct hlist_node *n;
 
 	hash = ip_vs_conn_hashkey_param(p, false);
 
 	ct_read_lock(hash);
 
-	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
+	hlist_for_each_entry(cp, n, &ip_vs_conn_tab[hash], c_list) {
 		if (cp->af == p->af &&
+		    p->cport == cp->cport && p->vport == cp->vport &&
 		    ip_vs_addr_equal(p->af, p->caddr, &cp->caddr) &&
 		    ip_vs_addr_equal(p->af, p->vaddr, &cp->vaddr) &&
-		    p->cport == cp->cport && p->vport == cp->vport &&
 		    ((!p->cport) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) &&
-		    p->protocol == cp->protocol) {
+		    p->protocol == cp->protocol &&
+		    ip_vs_conn_net_eq(cp, p->net)) {
 			/* HIT */
 			atomic_inc(&cp->refcnt);
 			ct_read_unlock(hash);
@@ -313,23 +312,23 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
 			    struct ip_vs_conn_param *p)
 {
 	__be16 _ports[2], *pptr;
+	struct net *net = skb_net(skb);
 
 	pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
 	if (pptr == NULL)
 		return 1;
 
 	if (likely(!inverse))
-		ip_vs_conn_fill_param(af, iph->protocol, &iph->saddr, pptr[0],
-				      &iph->daddr, pptr[1], p);
+		ip_vs_conn_fill_param(net, af, iph->protocol, &iph->saddr,
+				      pptr[0], &iph->daddr, pptr[1], p);
 	else
-		ip_vs_conn_fill_param(af, iph->protocol, &iph->daddr, pptr[1],
-				      &iph->saddr, pptr[0], p);
+		ip_vs_conn_fill_param(net, af, iph->protocol, &iph->daddr,
+				      pptr[1], &iph->saddr, pptr[0], p);
 	return 0;
 }
 
 struct ip_vs_conn *
 ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
-			struct ip_vs_protocol *pp,
 			const struct ip_vs_iphdr *iph,
 			unsigned int proto_off, int inverse)
 {
@@ -347,14 +346,17 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp;
+	struct hlist_node *n;
 
 	hash = ip_vs_conn_hashkey_param(p, false);
 
 	ct_read_lock(hash);
 
-	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
+	hlist_for_each_entry(cp, n, &ip_vs_conn_tab[hash], c_list) {
+		if (!ip_vs_conn_net_eq(cp, p->net))
+			continue;
 		if (p->pe_data && p->pe->ct_match) {
-			if (p->pe->ct_match(p, cp))
+			if (p->pe == cp->pe && p->pe->ct_match(p, cp))
 				goto out;
 			continue;
 		}
@@ -394,6 +396,7 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
 {
 	unsigned hash;
 	struct ip_vs_conn *cp, *ret=NULL;
+	struct hlist_node *n;
 
 	/*
 	 *	Check for "full" addressed entries
@@ -402,12 +405,13 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
 
 	ct_read_lock(hash);
 
-	list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
+	hlist_for_each_entry(cp, n, &ip_vs_conn_tab[hash], c_list) {
 		if (cp->af == p->af &&
+		    p->vport == cp->cport && p->cport == cp->dport &&
 		    ip_vs_addr_equal(p->af, p->vaddr, &cp->caddr) &&
 		    ip_vs_addr_equal(p->af, p->caddr, &cp->daddr) &&
-		    p->vport == cp->cport && p->cport == cp->dport &&
-		    p->protocol == cp->protocol) {
+		    p->protocol == cp->protocol &&
+		    ip_vs_conn_net_eq(cp, p->net)) {
 			/* HIT */
 			atomic_inc(&cp->refcnt);
 			ret = cp;
@@ -428,7 +432,6 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
 
 struct ip_vs_conn *
 ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
-			 struct ip_vs_protocol *pp,
 			 const struct ip_vs_iphdr *iph,
 			 unsigned int proto_off, int inverse)
 {
@@ -611,9 +614,9 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
 	struct ip_vs_dest *dest;
 
 	if ((cp) && (!cp->dest)) {
-		dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport,
-				       &cp->vaddr, cp->vport,
-				       cp->protocol);
+		dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, &cp->daddr,
+				       cp->dport, &cp->vaddr, cp->vport,
+				       cp->protocol, cp->fwmark);
 		ip_vs_bind_dest(cp, dest);
 		return dest;
 	} else
@@ -677,6 +680,16 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
 	atomic_dec(&dest->refcnt);
 }
 
+static int expire_quiescent_template(struct netns_ipvs *ipvs,
+				     struct ip_vs_dest *dest)
+{
+#ifdef CONFIG_SYSCTL
+	return ipvs->sysctl_expire_quiescent_template &&
+		(atomic_read(&dest->weight) == 0);
+#else
+	return 0;
+#endif
+}
 
 /*
  *	Checking if the destination of a connection template is available.
@@ -686,14 +699,14 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
 int ip_vs_check_template(struct ip_vs_conn *ct)
 {
 	struct ip_vs_dest *dest = ct->dest;
+	struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(ct));
 
 	/*
 	 * Checking the dest server status.
 	 */
 	if ((dest == NULL) ||
 	    !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
-	    (sysctl_ip_vs_expire_quiescent_template &&
-	     (atomic_read(&dest->weight) == 0))) {
+	    expire_quiescent_template(ipvs, dest)) {
 		IP_VS_DBG_BUF(9, "check_template: dest not available for "
 			      "protocol %s s:%s:%d v:%s:%d "
 			      "-> d:%s:%d\n",
@@ -730,6 +743,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
 static void ip_vs_conn_expire(unsigned long data)
 {
 	struct ip_vs_conn *cp = (struct ip_vs_conn *)data;
+	struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
 
 	cp->timeout = 60*HZ;
 
@@ -765,13 +779,14 @@ static void ip_vs_conn_expire(unsigned long data)
 		if (cp->flags & IP_VS_CONN_F_NFCT)
 			ip_vs_conn_drop_conntrack(cp);
 
+		ip_vs_pe_put(cp->pe);
 		kfree(cp->pe_data);
 		if (unlikely(cp->app != NULL))
 			ip_vs_unbind_app(cp);
 		ip_vs_unbind_dest(cp);
 		if (cp->flags & IP_VS_CONN_F_NO_CPORT)
 			atomic_dec(&ip_vs_conn_no_cport_cnt);
-		atomic_dec(&ip_vs_conn_count);
+		atomic_dec(&ipvs->conn_count);
 
 		kmem_cache_free(ip_vs_conn_cachep, cp);
 		return;
@@ -802,10 +817,12 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
 struct ip_vs_conn *
 ip_vs_conn_new(const struct ip_vs_conn_param *p,
 	       const union nf_inet_addr *daddr, __be16 dport, unsigned flags,
-	       struct ip_vs_dest *dest)
+	       struct ip_vs_dest *dest, __u32 fwmark)
 {
 	struct ip_vs_conn *cp;
-	struct ip_vs_protocol *pp = ip_vs_proto_get(p->protocol);
+	struct netns_ipvs *ipvs = net_ipvs(p->net);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(p->net,
+							   p->protocol);
 
 	cp = kmem_cache_zalloc(ip_vs_conn_cachep, GFP_ATOMIC);
 	if (cp == NULL) {
@@ -813,8 +830,9 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
 		return NULL;
 	}
 
-	INIT_LIST_HEAD(&cp->c_list);
+	INIT_HLIST_NODE(&cp->c_list);
 	setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
+	ip_vs_conn_net_set(cp, p->net);
 	cp->af		   = p->af;
 	cp->protocol	   = p->protocol;
 	ip_vs_addr_copy(p->af, &cp->caddr, p->caddr);
@@ -826,7 +844,10 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
 			&cp->daddr, daddr);
 	cp->dport          = dport;
 	cp->flags	   = flags;
-	if (flags & IP_VS_CONN_F_TEMPLATE && p->pe_data) {
+	cp->fwmark         = fwmark;
+	if (flags & IP_VS_CONN_F_TEMPLATE && p->pe) {
+		ip_vs_pe_get(p->pe);
+		cp->pe = p->pe;
 		cp->pe_data = p->pe_data;
 		cp->pe_data_len = p->pe_data_len;
 	}
@@ -842,7 +863,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
 	atomic_set(&cp->n_control, 0);
 	atomic_set(&cp->in_pkts, 0);
 
-	atomic_inc(&ip_vs_conn_count);
+	atomic_inc(&ipvs->conn_count);
 	if (flags & IP_VS_CONN_F_NO_CPORT)
 		atomic_inc(&ip_vs_conn_no_cport_cnt);
 
@@ -861,8 +882,8 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
 #endif
 		ip_vs_bind_xmit(cp);
 
-	if (unlikely(pp && atomic_read(&pp->appcnt)))
-		ip_vs_bind_app(cp, pp);
+	if (unlikely(pd && atomic_read(&pd->appcnt)))
+		ip_vs_bind_app(cp, pd->pp);
 
 	/*
 	 * Allow conntrack to be preserved. By default, conntrack
@@ -871,7 +892,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
 	 * IP_VS_CONN_F_ONE_PACKET too.
 	 */
 
-	if (ip_vs_conntrack_enabled())
+	if (ip_vs_conntrack_enabled(ipvs))
 		cp->flags |= IP_VS_CONN_F_NFCT;
 
 	/* Hash it in the ip_vs_conn_tab finally */
@@ -884,18 +905,24 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
  *	/proc/net/ip_vs_conn entries
  */
 #ifdef CONFIG_PROC_FS
+struct ip_vs_iter_state {
+	struct seq_net_private	p;
+	struct hlist_head	*l;
+};
 
 static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
 {
 	int idx;
 	struct ip_vs_conn *cp;
+	struct ip_vs_iter_state *iter = seq->private;
+	struct hlist_node *n;
 
 	for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
 		ct_read_lock_bh(idx);
-		list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
+		hlist_for_each_entry(cp, n, &ip_vs_conn_tab[idx], c_list) {
 			if (pos-- == 0) {
-				seq->private = &ip_vs_conn_tab[idx];
-			return cp;
+				iter->l = &ip_vs_conn_tab[idx];
+				return cp;
 			}
 		}
 		ct_read_unlock_bh(idx);
@@ -906,14 +933,18 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
 
 static void *ip_vs_conn_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	seq->private = NULL;
+	struct ip_vs_iter_state *iter = seq->private;
+
+	iter->l = NULL;
 	return *pos ? ip_vs_conn_array(seq, *pos - 1) :SEQ_START_TOKEN;
 }
 
 static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct ip_vs_conn *cp = v;
-	struct list_head *e, *l = seq->private;
+	struct ip_vs_iter_state *iter = seq->private;
+	struct hlist_node *e;
+	struct hlist_head *l = iter->l;
 	int idx;
 
 	++*pos;
@@ -921,27 +952,28 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 		return ip_vs_conn_array(seq, 0);
 
 	/* more on same hash chain? */
-	if ((e = cp->c_list.next) != l)
-		return list_entry(e, struct ip_vs_conn, c_list);
+	if ((e = cp->c_list.next))
+		return hlist_entry(e, struct ip_vs_conn, c_list);
 
 	idx = l - ip_vs_conn_tab;
 	ct_read_unlock_bh(idx);
 
 	while (++idx < ip_vs_conn_tab_size) {
 		ct_read_lock_bh(idx);
-		list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
-			seq->private = &ip_vs_conn_tab[idx];
+		hlist_for_each_entry(cp, e, &ip_vs_conn_tab[idx], c_list) {
+			iter->l = &ip_vs_conn_tab[idx];
 			return cp;
 		}
 		ct_read_unlock_bh(idx);
 	}
-	seq->private = NULL;
+	iter->l = NULL;
 	return NULL;
 }
 
 static void ip_vs_conn_seq_stop(struct seq_file *seq, void *v)
 {
-	struct list_head *l = seq->private;
+	struct ip_vs_iter_state *iter = seq->private;
+	struct hlist_head *l = iter->l;
 
 	if (l)
 		ct_read_unlock_bh(l - ip_vs_conn_tab);
@@ -955,18 +987,19 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
    "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Expires PEName PEData\n");
 	else {
 		const struct ip_vs_conn *cp = v;
+		struct net *net = seq_file_net(seq);
 		char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3];
 		size_t len = 0;
 
-		if (cp->dest && cp->pe_data &&
-		    cp->dest->svc->pe->show_pe_data) {
+		if (!ip_vs_conn_net_eq(cp, net))
+			return 0;
+		if (cp->pe_data) {
 			pe_data[0] = ' ';
-			len = strlen(cp->dest->svc->pe->name);
-			memcpy(pe_data + 1, cp->dest->svc->pe->name, len);
+			len = strlen(cp->pe->name);
+			memcpy(pe_data + 1, cp->pe->name, len);
 			pe_data[len + 1] = ' ';
 			len += 2;
-			len += cp->dest->svc->pe->show_pe_data(cp,
-							       pe_data + len);
+			len += cp->pe->show_pe_data(cp, pe_data + len);
 		}
 		pe_data[len] = '\0';
 
@@ -1004,7 +1037,8 @@ static const struct seq_operations ip_vs_conn_seq_ops = {
 
 static int ip_vs_conn_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ip_vs_conn_seq_ops);
+	return seq_open_net(inode, file, &ip_vs_conn_seq_ops,
+			    sizeof(struct ip_vs_iter_state));
 }
 
 static const struct file_operations ip_vs_conn_fops = {
@@ -1031,6 +1065,10 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
    "Pro FromIP   FPrt ToIP     TPrt DestIP   DPrt State       Origin Expires\n");
 	else {
 		const struct ip_vs_conn *cp = v;
+		struct net *net = seq_file_net(seq);
+
+		if (!ip_vs_conn_net_eq(cp, net))
+			return 0;
 
 #ifdef CONFIG_IP_VS_IPV6
 		if (cp->af == AF_INET6)
@@ -1067,7 +1105,8 @@ static const struct seq_operations ip_vs_conn_sync_seq_ops = {
 
 static int ip_vs_conn_sync_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ip_vs_conn_sync_seq_ops);
+	return seq_open_net(inode, file, &ip_vs_conn_sync_seq_ops,
+			    sizeof(struct ip_vs_iter_state));
 }
 
 static const struct file_operations ip_vs_conn_sync_fops = {
@@ -1113,7 +1152,7 @@ static inline int todrop_entry(struct ip_vs_conn *cp)
 }
 
 /* Called from keventd and must protect itself from softirqs */
-void ip_vs_random_dropentry(void)
+void ip_vs_random_dropentry(struct net *net)
 {
 	int idx;
 	struct ip_vs_conn *cp;
@@ -1123,17 +1162,19 @@ void ip_vs_random_dropentry(void)
 	 */
 	for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) {
 		unsigned hash = net_random() & ip_vs_conn_tab_mask;
+		struct hlist_node *n;
 
 		/*
 		 *  Lock is actually needed in this loop.
 		 */
 		ct_write_lock_bh(hash);
 
-		list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) {
+		hlist_for_each_entry(cp, n, &ip_vs_conn_tab[hash], c_list) {
 			if (cp->flags & IP_VS_CONN_F_TEMPLATE)
 				/* connection template */
 				continue;
-
+			if (!ip_vs_conn_net_eq(cp, net))
+				continue;
 			if (cp->protocol == IPPROTO_TCP) {
 				switch(cp->state) {
 				case IP_VS_TCP_S_SYN_RECV:
@@ -1168,20 +1209,24 @@ void ip_vs_random_dropentry(void)
 /*
  *      Flush all the connection entries in the ip_vs_conn_tab
  */
-static void ip_vs_conn_flush(void)
+static void ip_vs_conn_flush(struct net *net)
 {
 	int idx;
 	struct ip_vs_conn *cp;
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
-  flush_again:
+flush_again:
 	for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
+		struct hlist_node *n;
+
 		/*
 		 *  Lock is actually needed in this loop.
 		 */
 		ct_write_lock_bh(idx);
 
-		list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
-
+		hlist_for_each_entry(cp, n, &ip_vs_conn_tab[idx], c_list) {
+			if (!ip_vs_conn_net_eq(cp, net))
+				continue;
 			IP_VS_DBG(4, "del connection\n");
 			ip_vs_conn_expire_now(cp);
 			if (cp->control) {
@@ -1194,16 +1239,41 @@ static void ip_vs_conn_flush(void)
 
 	/* the counter may be not NULL, because maybe some conn entries
 	   are run by slow timer handler or unhashed but still referred */
-	if (atomic_read(&ip_vs_conn_count) != 0) {
+	if (atomic_read(&ipvs->conn_count) != 0) {
 		schedule();
 		goto flush_again;
 	}
 }
+/*
+ * per netns init and exit
+ */
+int __net_init __ip_vs_conn_init(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	atomic_set(&ipvs->conn_count, 0);
 
+	proc_net_fops_create(net, "ip_vs_conn", 0, &ip_vs_conn_fops);
+	proc_net_fops_create(net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
+	return 0;
+}
+
+static void __net_exit __ip_vs_conn_cleanup(struct net *net)
+{
+	/* flush all the connection entries first */
+	ip_vs_conn_flush(net);
+	proc_net_remove(net, "ip_vs_conn");
+	proc_net_remove(net, "ip_vs_conn_sync");
+}
+static struct pernet_operations ipvs_conn_ops = {
+	.init = __ip_vs_conn_init,
+	.exit = __ip_vs_conn_cleanup,
+};
 
 int __init ip_vs_conn_init(void)
 {
 	int idx;
+	int retc;
 
 	/* Compute size and mask */
 	ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
@@ -1212,8 +1282,7 @@ int __init ip_vs_conn_init(void)
 	/*
 	 * Allocate the connection hash table and initialize its list heads
 	 */
-	ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size *
-				 sizeof(struct list_head));
+	ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size * sizeof(*ip_vs_conn_tab));
 	if (!ip_vs_conn_tab)
 		return -ENOMEM;
 
@@ -1233,32 +1302,25 @@ int __init ip_vs_conn_init(void)
 	IP_VS_DBG(0, "Each connection entry needs %Zd bytes at least\n",
 		  sizeof(struct ip_vs_conn));
 
-	for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
-		INIT_LIST_HEAD(&ip_vs_conn_tab[idx]);
-	}
+	for (idx = 0; idx < ip_vs_conn_tab_size; idx++)
+		INIT_HLIST_HEAD(&ip_vs_conn_tab[idx]);
 
 	for (idx = 0; idx < CT_LOCKARRAY_SIZE; idx++)  {
 		rwlock_init(&__ip_vs_conntbl_lock_array[idx].l);
 	}
 
-	proc_net_fops_create(&init_net, "ip_vs_conn", 0, &ip_vs_conn_fops);
-	proc_net_fops_create(&init_net, "ip_vs_conn_sync", 0, &ip_vs_conn_sync_fops);
+	retc = register_pernet_subsys(&ipvs_conn_ops);
 
 	/* calculate the random value for connection hash */
 	get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd));
 
-	return 0;
+	return retc;
 }
 
-
 void ip_vs_conn_cleanup(void)
 {
-	/* flush all the connection entries first */
-	ip_vs_conn_flush();
-
+	unregister_pernet_subsys(&ipvs_conn_ops);
 	/* Release the empty cache */
 	kmem_cache_destroy(ip_vs_conn_cachep);
-	proc_net_remove(&init_net, "ip_vs_conn");
-	proc_net_remove(&init_net, "ip_vs_conn_sync");
 	vfree(ip_vs_conn_tab);
 }
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index b4e51e9..07accf6 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -41,6 +41,7 @@
 #include <net/icmp.h>                   /* for icmp_send */
 #include <net/route.h>
 #include <net/ip6_checksum.h>
+#include <net/netns/generic.h>		/* net_generic() */
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
@@ -68,6 +69,12 @@ 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
+/* netns cnt used for uniqueness */
+static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);
 
 /* ID used in ICMP lookups */
 #define icmp_id(icmph)          (((icmph)->un).echo.id)
@@ -108,21 +115,28 @@ static inline void
 ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
 {
 	struct ip_vs_dest *dest = cp->dest;
+	struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
+
 	if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
-		spin_lock(&dest->stats.lock);
-		dest->stats.ustats.inpkts++;
-		dest->stats.ustats.inbytes += skb->len;
-		spin_unlock(&dest->stats.lock);
-
-		spin_lock(&dest->svc->stats.lock);
-		dest->svc->stats.ustats.inpkts++;
-		dest->svc->stats.ustats.inbytes += skb->len;
-		spin_unlock(&dest->svc->stats.lock);
-
-		spin_lock(&ip_vs_stats.lock);
-		ip_vs_stats.ustats.inpkts++;
-		ip_vs_stats.ustats.inbytes += skb->len;
-		spin_unlock(&ip_vs_stats.lock);
+		struct ip_vs_cpu_stats *s;
+
+		s = this_cpu_ptr(dest->stats.cpustats);
+		s->ustats.inpkts++;
+		u64_stats_update_begin(&s->syncp);
+		s->ustats.inbytes += skb->len;
+		u64_stats_update_end(&s->syncp);
+
+		s = this_cpu_ptr(dest->svc->stats.cpustats);
+		s->ustats.inpkts++;
+		u64_stats_update_begin(&s->syncp);
+		s->ustats.inbytes += skb->len;
+		u64_stats_update_end(&s->syncp);
+
+		s = this_cpu_ptr(ipvs->tot_stats.cpustats);
+		s->ustats.inpkts++;
+		u64_stats_update_begin(&s->syncp);
+		s->ustats.inbytes += skb->len;
+		u64_stats_update_end(&s->syncp);
 	}
 }
 
@@ -131,21 +145,28 @@ static inline void
 ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
 {
 	struct ip_vs_dest *dest = cp->dest;
+	struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
+
 	if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
-		spin_lock(&dest->stats.lock);
-		dest->stats.ustats.outpkts++;
-		dest->stats.ustats.outbytes += skb->len;
-		spin_unlock(&dest->stats.lock);
-
-		spin_lock(&dest->svc->stats.lock);
-		dest->svc->stats.ustats.outpkts++;
-		dest->svc->stats.ustats.outbytes += skb->len;
-		spin_unlock(&dest->svc->stats.lock);
-
-		spin_lock(&ip_vs_stats.lock);
-		ip_vs_stats.ustats.outpkts++;
-		ip_vs_stats.ustats.outbytes += skb->len;
-		spin_unlock(&ip_vs_stats.lock);
+		struct ip_vs_cpu_stats *s;
+
+		s = this_cpu_ptr(dest->stats.cpustats);
+		s->ustats.outpkts++;
+		u64_stats_update_begin(&s->syncp);
+		s->ustats.outbytes += skb->len;
+		u64_stats_update_end(&s->syncp);
+
+		s = this_cpu_ptr(dest->svc->stats.cpustats);
+		s->ustats.outpkts++;
+		u64_stats_update_begin(&s->syncp);
+		s->ustats.outbytes += skb->len;
+		u64_stats_update_end(&s->syncp);
+
+		s = this_cpu_ptr(ipvs->tot_stats.cpustats);
+		s->ustats.outpkts++;
+		u64_stats_update_begin(&s->syncp);
+		s->ustats.outbytes += skb->len;
+		u64_stats_update_end(&s->syncp);
 	}
 }
 
@@ -153,41 +174,44 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
 static inline void
 ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)
 {
-	spin_lock(&cp->dest->stats.lock);
-	cp->dest->stats.ustats.conns++;
-	spin_unlock(&cp->dest->stats.lock);
+	struct netns_ipvs *ipvs = net_ipvs(svc->net);
+	struct ip_vs_cpu_stats *s;
+
+	s = this_cpu_ptr(cp->dest->stats.cpustats);
+	s->ustats.conns++;
 
-	spin_lock(&svc->stats.lock);
-	svc->stats.ustats.conns++;
-	spin_unlock(&svc->stats.lock);
+	s = this_cpu_ptr(svc->stats.cpustats);
+	s->ustats.conns++;
 
-	spin_lock(&ip_vs_stats.lock);
-	ip_vs_stats.ustats.conns++;
-	spin_unlock(&ip_vs_stats.lock);
+	s = this_cpu_ptr(ipvs->tot_stats.cpustats);
+	s->ustats.conns++;
 }
 
 
 static inline int
 ip_vs_set_state(struct ip_vs_conn *cp, int direction,
 		const struct sk_buff *skb,
-		struct ip_vs_protocol *pp)
+		struct ip_vs_proto_data *pd)
 {
-	if (unlikely(!pp->state_transition))
+	if (unlikely(!pd->pp->state_transition))
 		return 0;
-	return pp->state_transition(cp, direction, skb, pp);
+	return pd->pp->state_transition(cp, direction, skb, pd);
 }
 
-static inline void
+static inline int
 ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
 			      struct sk_buff *skb, int protocol,
 			      const union nf_inet_addr *caddr, __be16 cport,
 			      const union nf_inet_addr *vaddr, __be16 vport,
 			      struct ip_vs_conn_param *p)
 {
-	ip_vs_conn_fill_param(svc->af, protocol, caddr, cport, vaddr, vport, p);
+	ip_vs_conn_fill_param(svc->net, svc->af, protocol, caddr, cport, vaddr,
+			      vport, p);
 	p->pe = svc->pe;
 	if (p->pe && p->pe->fill_param)
-		p->pe->fill_param(p, skb);
+		return p->pe->fill_param(p, skb);
+
+	return 0;
 }
 
 /*
@@ -200,7 +224,7 @@ ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
 static struct ip_vs_conn *
 ip_vs_sched_persist(struct ip_vs_service *svc,
 		    struct sk_buff *skb,
-		    __be16 ports[2])
+		    __be16 src_port, __be16 dst_port, int *ignored)
 {
 	struct ip_vs_conn *cp = NULL;
 	struct ip_vs_iphdr iph;
@@ -224,8 +248,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 
 	IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
 		      "mnet %s\n",
-		      IP_VS_DBG_ADDR(svc->af, &iph.saddr), ntohs(ports[0]),
-		      IP_VS_DBG_ADDR(svc->af, &iph.daddr), ntohs(ports[1]),
+		      IP_VS_DBG_ADDR(svc->af, &iph.saddr), ntohs(src_port),
+		      IP_VS_DBG_ADDR(svc->af, &iph.daddr), ntohs(dst_port),
 		      IP_VS_DBG_ADDR(svc->af, &snet));
 
 	/*
@@ -247,14 +271,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 		const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
 		__be16 vport = 0;
 
-		if (ports[1] == svc->port) {
+		if (dst_port == svc->port) {
 			/* non-FTP template:
 			 * <protocol, caddr, 0, vaddr, vport, daddr, dport>
 			 * FTP template:
 			 * <protocol, caddr, 0, vaddr, 0, daddr, 0>
 			 */
 			if (svc->port != FTPPORT)
-				vport = ports[1];
+				vport = dst_port;
 		} else {
 			/* Note: persistent fwmark-based services and
 			 * persistent port zero service are handled here.
@@ -268,24 +292,31 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 				vaddr = &fwmark;
 			}
 		}
-		ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0,
-					      vaddr, vport, &param);
+		/* return *ignored = -1 so NF_DROP can be used */
+		if (ip_vs_conn_fill_param_persist(svc, skb, protocol, &snet, 0,
+						  vaddr, vport, &param) < 0) {
+			*ignored = -1;
+			return NULL;
+		}
 	}
 
 	/* Check if a template already exists */
 	ct = ip_vs_ct_in_get(&param);
 	if (!ct || !ip_vs_check_template(ct)) {
-		/* No template found or the dest of the connection
+		/*
+		 * No template found or the dest of the connection
 		 * template is not available.
+		 * return *ignored=0 i.e. ICMP and NF_DROP
 		 */
 		dest = svc->scheduler->schedule(svc, skb);
 		if (!dest) {
 			IP_VS_DBG(1, "p-schedule: no dest found.\n");
 			kfree(param.pe_data);
+			*ignored = 0;
 			return NULL;
 		}
 
-		if (ports[1] == svc->port && svc->port != FTPPORT)
+		if (dst_port == svc->port && svc->port != FTPPORT)
 			dport = dest->port;
 
 		/* Create a template
@@ -293,9 +324,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 		 * and thus param.pe_data will be destroyed
 		 * when the template expires */
 		ct = ip_vs_conn_new(&param, &dest->addr, dport,
-				    IP_VS_CONN_F_TEMPLATE, dest);
+				    IP_VS_CONN_F_TEMPLATE, dest, skb->mark);
 		if (ct == NULL) {
 			kfree(param.pe_data);
+			*ignored = -1;
 			return NULL;
 		}
 
@@ -306,7 +338,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 		kfree(param.pe_data);
 	}
 
-	dport = ports[1];
+	dport = dst_port;
 	if (dport == svc->port && dest->port)
 		dport = dest->port;
 
@@ -317,11 +349,13 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
 	/*
 	 *    Create a new connection according to the template
 	 */
-	ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr, ports[0],
-			      &iph.daddr, ports[1], &param);
-	cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest);
+	ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol, &iph.saddr,
+			      src_port, &iph.daddr, dst_port, &param);
+
+	cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest, skb->mark);
 	if (cp == NULL) {
 		ip_vs_conn_put(ct);
+		*ignored = -1;
 		return NULL;
 	}
 
@@ -341,11 +375,27 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
  *  It selects a server according to the virtual service, and
  *  creates a connection entry.
  *  Protocols supported: TCP, UDP
+ *
+ *  Usage of *ignored
+ *
+ * 1 :   protocol tried to schedule (eg. on SYN), found svc but the
+ *       svc/scheduler decides that this packet should be accepted with
+ *       NF_ACCEPT because it must not be scheduled.
+ *
+ * 0 :   scheduler can not find destination, so try bypass or
+ *       return ICMP and then NF_DROP (ip_vs_leave).
+ *
+ * -1 :  scheduler tried to schedule but fatal error occurred, eg.
+ *       ip_vs_conn_new failure (ENOMEM) or ip_vs_sip_fill_param
+ *       failure such as missing Call-ID, ENOMEM on skb_linearize
+ *       or pe_data. In this case we should return NF_DROP without
+ *       any attempts to send ICMP with ip_vs_leave.
  */
 struct ip_vs_conn *
 ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
-	       struct ip_vs_protocol *pp, int *ignored)
+	       struct ip_vs_proto_data *pd, int *ignored)
 {
+	struct ip_vs_protocol *pp = pd->pp;
 	struct ip_vs_conn *cp = NULL;
 	struct ip_vs_iphdr iph;
 	struct ip_vs_dest *dest;
@@ -371,12 +421,10 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 	}
 
 	/*
-	 * Do not schedule replies from local real server. It is risky
-	 * for fwmark services but mostly for persistent services.
+	 *    Do not schedule replies from local real server.
 	 */
 	if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
-	    (svc->flags & IP_VS_SVC_F_PERSISTENT || svc->fwmark) &&
-	    (cp = pp->conn_in_get(svc->af, skb, pp, &iph, iph.len, 1))) {
+	    (cp = pp->conn_in_get(svc->af, skb, &iph, iph.len, 1))) {
 		IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
 			      "Not scheduling reply for existing connection");
 		__ip_vs_conn_put(cp);
@@ -386,10 +434,10 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 	/*
 	 *    Persistent service
 	 */
-	if (svc->flags & IP_VS_SVC_F_PERSISTENT) {
-		*ignored = 0;
-		return ip_vs_sched_persist(svc, skb, pptr);
-	}
+	if (svc->flags & IP_VS_SVC_F_PERSISTENT)
+		return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored);
+
+	*ignored = 0;
 
 	/*
 	 *    Non-persistent service
@@ -402,8 +450,6 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 		return NULL;
 	}
 
-	*ignored = 0;
-
 	dest = svc->scheduler->schedule(svc, skb);
 	if (dest == NULL) {
 		IP_VS_DBG(1, "Schedule: no dest found.\n");
@@ -419,13 +465,17 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
 	 */
 	{
 		struct ip_vs_conn_param p;
-		ip_vs_conn_fill_param(svc->af, iph.protocol, &iph.saddr,
-				      pptr[0], &iph.daddr, pptr[1], &p);
+
+		ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
+				      &iph.saddr, pptr[0], &iph.daddr, pptr[1],
+				      &p);
 		cp = ip_vs_conn_new(&p, &dest->addr,
 				    dest->port ? dest->port : pptr[1],
-				    flags, dest);
-		if (!cp)
+				    flags, dest, skb->mark);
+		if (!cp) {
+			*ignored = -1;
 			return NULL;
+		}
 	}
 
 	IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
@@ -447,11 +497,16 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
  *  no destination is available for a new connection.
  */
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
-		struct ip_vs_protocol *pp)
+		struct ip_vs_proto_data *pd)
 {
 	__be16 _ports[2], *pptr;
 	struct ip_vs_iphdr iph;
+#ifdef CONFIG_SYSCTL
+	struct net *net;
+	struct netns_ipvs *ipvs;
 	int unicast;
+#endif
+
 	ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
 
 	pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
@@ -460,17 +515,21 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		return NF_DROP;
 	}
 
+#ifdef CONFIG_SYSCTL
+	net = skb_net(skb);
+
 #ifdef CONFIG_IP_VS_IPV6
 	if (svc->af == AF_INET6)
 		unicast = ipv6_addr_type(&iph.daddr.in6) & IPV6_ADDR_UNICAST;
 	else
 #endif
-		unicast = (inet_addr_type(&init_net, iph.daddr.ip) == RTN_UNICAST);
+		unicast = (inet_addr_type(net, iph.daddr.ip) == RTN_UNICAST);
 
 	/* if it is fwmark-based service, the cache_bypass sysctl is up
 	   and the destination is a non-local unicast, then create
 	   a cache_bypass connection entry */
-	if (sysctl_ip_vs_cache_bypass && svc->fwmark && unicast) {
+	ipvs = net_ipvs(net);
+	if (ipvs->sysctl_cache_bypass && svc->fwmark && unicast) {
 		int ret, cs;
 		struct ip_vs_conn *cp;
 		unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
@@ -484,12 +543,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
 		{
 			struct ip_vs_conn_param p;
-			ip_vs_conn_fill_param(svc->af, iph.protocol,
+			ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
 					      &iph.saddr, pptr[0],
 					      &iph.daddr, pptr[1], &p);
 			cp = ip_vs_conn_new(&p, &daddr, 0,
 					    IP_VS_CONN_F_BYPASS | flags,
-					    NULL);
+					    NULL, skb->mark);
 			if (!cp)
 				return NF_DROP;
 		}
@@ -498,16 +557,17 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 		ip_vs_in_stats(cp, skb);
 
 		/* set state */
-		cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
+		cs = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
 
 		/* transmit the first SYN packet */
-		ret = cp->packet_xmit(skb, cp, pp);
+		ret = cp->packet_xmit(skb, cp, pd->pp);
 		/* do not touch skb anymore */
 
 		atomic_inc(&cp->in_pkts);
 		ip_vs_conn_put(cp);
 		return ret;
 	}
+#endif
 
 	/*
 	 * When the virtual ftp service is presented, packets destined
@@ -544,6 +604,33 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 	return NF_DROP;
 }
 
+#ifdef CONFIG_SYSCTL
+
+static int sysctl_snat_reroute(struct sk_buff *skb)
+{
+	struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
+	return ipvs->sysctl_snat_reroute;
+}
+
+static int sysctl_nat_icmp_send(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	return ipvs->sysctl_nat_icmp_send;
+}
+
+static int sysctl_expire_nodest_conn(struct netns_ipvs *ipvs)
+{
+	return ipvs->sysctl_expire_nodest_conn;
+}
+
+#else
+
+static int sysctl_snat_reroute(struct sk_buff *skb) { return 0; }
+static int sysctl_nat_icmp_send(struct net *net) { return 0; }
+static int sysctl_expire_nodest_conn(struct netns_ipvs *ipvs) { return 0; }
+
+#endif
+
 __sum16 ip_vs_checksum_complete(struct sk_buff *skb, int offset)
 {
 	return csum_fold(skb_checksum(skb, offset, skb->len - offset, 0));
@@ -576,6 +663,22 @@ static inline int ip_vs_gather_frags_v6(struct sk_buff *skb, u_int32_t user)
 }
 #endif
 
+static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
+{
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6) {
+		if (sysctl_snat_reroute(skb) && ip6_route_me_harder(skb) != 0)
+			return 1;
+	} else
+#endif
+		if ((sysctl_snat_reroute(skb) ||
+		     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
+		    ip_route_me_harder(skb, RTN_LOCAL) != 0)
+			return 1;
+
+	return 0;
+}
+
 /*
  * Packet has been made sufficiently writable in caller
  * - inout: 1=in->out, 0=out->in
@@ -674,7 +777,7 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
 #endif
 
 /* Handle relevant response ICMP messages - forward to the right
- * destination host. Used for NAT and local client.
+ * destination host.
  */
 static int handle_response_icmp(int af, struct sk_buff *skb,
 				union nf_inet_addr *snet,
@@ -710,16 +813,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
 #endif
 		ip_vs_nat_icmp(skb, pp, cp, 1);
 
-#ifdef CONFIG_IP_VS_IPV6
-	if (af == AF_INET6) {
-		if (sysctl_ip_vs_snat_reroute && ip6_route_me_harder(skb) != 0)
-			goto out;
-	} else
-#endif
-		if ((sysctl_ip_vs_snat_reroute ||
-		     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
-		    ip_route_me_harder(skb, RTN_LOCAL) != 0)
-			goto out;
+	if (ip_vs_route_me_harder(af, skb))
+		goto out;
 
 	/* do the statistics and put it back */
 	ip_vs_out_stats(cp, skb);
@@ -808,7 +903,7 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
 
 	ip_vs_fill_iphdr(AF_INET, cih, &ciph);
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1);
+	cp = pp->conn_out_get(AF_INET, skb, &ciph, offset, 1);
 	if (!cp)
 		return NF_ACCEPT;
 
@@ -885,7 +980,7 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
 
 	ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_out_get(AF_INET6, skb, pp, &ciph, offset, 1);
+	cp = pp->conn_out_get(AF_INET6, skb, &ciph, offset, 1);
 	if (!cp)
 		return NF_ACCEPT;
 
@@ -921,12 +1016,13 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
 }
 
 /* Handle response packets: rewrite addresses and send away...
- * Used for NAT and local client.
  */
 static unsigned int
-handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 		struct ip_vs_conn *cp, int ihl)
 {
+	struct ip_vs_protocol *pp = pd->pp;
+
 	IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
 
 	if (!skb_make_writable(skb, ihl))
@@ -961,21 +1057,13 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 	 * if it came from this machine itself.  So re-compute
 	 * the routing information.
 	 */
-#ifdef CONFIG_IP_VS_IPV6
-	if (af == AF_INET6) {
-		if (sysctl_ip_vs_snat_reroute && ip6_route_me_harder(skb) != 0)
-			goto drop;
-	} else
-#endif
-		if ((sysctl_ip_vs_snat_reroute ||
-		     skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
-		    ip_route_me_harder(skb, RTN_LOCAL) != 0)
-			goto drop;
+	if (ip_vs_route_me_harder(af, skb))
+		goto drop;
 
 	IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
 
 	ip_vs_out_stats(cp, skb);
-	ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
+	ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd);
 	skb->ipvs_property = 1;
 	if (!(cp->flags & IP_VS_CONN_F_NFCT))
 		ip_vs_notrack(skb);
@@ -999,8 +1087,10 @@ drop:
 static unsigned int
 ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 {
+	struct net *net = NULL;
 	struct ip_vs_iphdr iph;
 	struct ip_vs_protocol *pp;
+	struct ip_vs_proto_data *pd;
 	struct ip_vs_conn *cp;
 
 	EnterFunction(11);
@@ -1022,6 +1112,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 	if (unlikely(!skb_dst(skb)))
 		return NF_ACCEPT;
 
+	net = skb_net(skb);
 	ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 #ifdef CONFIG_IP_VS_IPV6
 	if (af == AF_INET6) {
@@ -1045,9 +1136,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 			ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 		}
 
-	pp = ip_vs_proto_get(iph.protocol);
-	if (unlikely(!pp))
+	pd = ip_vs_proto_data_get(net, iph.protocol);
+	if (unlikely(!pd))
 		return NF_ACCEPT;
+	pp = pd->pp;
 
 	/* reassemble IP fragments */
 #ifdef CONFIG_IP_VS_IPV6
@@ -1073,11 +1165,11 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 	/*
 	 * Check if the packet belongs to an existing entry
 	 */
-	cp = pp->conn_out_get(af, skb, pp, &iph, iph.len, 0);
+	cp = pp->conn_out_get(af, skb, &iph, iph.len, 0);
 
 	if (likely(cp))
-		return handle_response(af, skb, pp, cp, iph.len);
-	if (sysctl_ip_vs_nat_icmp_send &&
+		return handle_response(af, skb, pd, cp, iph.len);
+	if (sysctl_nat_icmp_send(net) &&
 	    (pp->protocol == IPPROTO_TCP ||
 	     pp->protocol == IPPROTO_UDP ||
 	     pp->protocol == IPPROTO_SCTP)) {
@@ -1087,7 +1179,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 					  sizeof(_ports), _ports);
 		if (pptr == NULL)
 			return NF_ACCEPT;	/* Not for me */
-		if (ip_vs_lookup_real_service(af, iph.protocol,
+		if (ip_vs_lookup_real_service(net, af, iph.protocol,
 					      &iph.saddr,
 					      pptr[0])) {
 			/*
@@ -1202,14 +1294,15 @@ ip_vs_local_reply6(unsigned int hooknum, struct sk_buff *skb,
 static int
 ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 {
+	struct net *net = NULL;
 	struct iphdr *iph;
 	struct icmphdr	_icmph, *ic;
 	struct iphdr	_ciph, *cih;	/* The ip header contained within the ICMP */
 	struct ip_vs_iphdr ciph;
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp;
+	struct ip_vs_proto_data *pd;
 	unsigned int offset, ihl, verdict;
-	union nf_inet_addr snet;
 
 	*related = 1;
 
@@ -1249,9 +1342,11 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 	if (cih == NULL)
 		return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-	pp = ip_vs_proto_get(cih->protocol);
-	if (!pp)
+	net = skb_net(skb);
+	pd = ip_vs_proto_data_get(net, cih->protocol);
+	if (!pd)
 		return NF_ACCEPT;
+	pp = pd->pp;
 
 	/* Is the embedded protocol header present? */
 	if (unlikely(cih->frag_off & htons(IP_OFFSET) &&
@@ -1265,18 +1360,9 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 
 	ip_vs_fill_iphdr(AF_INET, cih, &ciph);
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_in_get(AF_INET, skb, pp, &ciph, offset, 1);
-	if (!cp) {
-		/* The packet could also belong to a local client */
-		cp = pp->conn_out_get(AF_INET, skb, pp, &ciph, offset, 1);
-		if (cp) {
-			snet.ip = iph->saddr;
-			return handle_response_icmp(AF_INET, skb, &snet,
-						    cih->protocol, cp, pp,
-						    offset, ihl);
-		}
+	cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, 1);
+	if (!cp)
 		return NF_ACCEPT;
-	}
 
 	verdict = NF_DROP;
 
@@ -1312,6 +1398,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
 static int
 ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
 {
+	struct net *net = NULL;
 	struct ipv6hdr *iph;
 	struct icmp6hdr	_icmph, *ic;
 	struct ipv6hdr	_ciph, *cih;	/* The ip header contained
@@ -1319,8 +1406,8 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
 	struct ip_vs_iphdr ciph;
 	struct ip_vs_conn *cp;
 	struct ip_vs_protocol *pp;
+	struct ip_vs_proto_data *pd;
 	unsigned int offset, verdict;
-	union nf_inet_addr snet;
 	struct rt6_info *rt;
 
 	*related = 1;
@@ -1361,9 +1448,11 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
 	if (cih == NULL)
 		return NF_ACCEPT; /* The packet looks wrong, ignore */
 
-	pp = ip_vs_proto_get(cih->nexthdr);
-	if (!pp)
+	net = skb_net(skb);
+	pd = ip_vs_proto_data_get(net, cih->nexthdr);
+	if (!pd)
 		return NF_ACCEPT;
+	pp = pd->pp;
 
 	/* Is the embedded protocol header present? */
 	/* TODO: we don't support fragmentation at the moment anyways */
@@ -1377,19 +1466,9 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
 
 	ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
 	/* The embedded headers contain source and dest in reverse order */
-	cp = pp->conn_in_get(AF_INET6, skb, pp, &ciph, offset, 1);
-	if (!cp) {
-		/* The packet could also belong to a local client */
-		cp = pp->conn_out_get(AF_INET6, skb, pp, &ciph, offset, 1);
-		if (cp) {
-			ipv6_addr_copy(&snet.in6, &iph->saddr);
-			return handle_response_icmp(AF_INET6, skb, &snet,
-						    cih->nexthdr,
-						    cp, pp, offset,
-						    sizeof(struct ipv6hdr));
-		}
+	cp = pp->conn_in_get(AF_INET6, skb, &ciph, offset, 1);
+	if (!cp)
 		return NF_ACCEPT;
-	}
 
 	verdict = NF_DROP;
 
@@ -1423,10 +1502,13 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
 static unsigned int
 ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 {
+	struct net *net;
 	struct ip_vs_iphdr iph;
 	struct ip_vs_protocol *pp;
+	struct ip_vs_proto_data *pd;
 	struct ip_vs_conn *cp;
 	int ret, restart, pkts;
+	struct netns_ipvs *ipvs;
 
 	/* Already marked as IPVS request or reply? */
 	if (skb->ipvs_property)
@@ -1480,20 +1562,21 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 			ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
 		}
 
+	net = skb_net(skb);
 	/* Protocol supported? */
-	pp = ip_vs_proto_get(iph.protocol);
-	if (unlikely(!pp))
+	pd = ip_vs_proto_data_get(net, iph.protocol);
+	if (unlikely(!pd))
 		return NF_ACCEPT;
-
+	pp = pd->pp;
 	/*
 	 * Check if the packet belongs to an existing connection entry
 	 */
-	cp = pp->conn_in_get(af, skb, pp, &iph, iph.len, 0);
+	cp = pp->conn_in_get(af, skb, &iph, iph.len, 0);
 
 	if (unlikely(!cp)) {
 		int v;
 
-		if (!pp->conn_schedule(af, skb, pp, &v, &cp))
+		if (!pp->conn_schedule(af, skb, pd, &v, &cp))
 			return v;
 	}
 
@@ -1505,12 +1588,13 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 	}
 
 	IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
-
+	net = skb_net(skb);
+	ipvs = net_ipvs(net);
 	/* Check the server status */
 	if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
 		/* the destination server is not available */
 
-		if (sysctl_ip_vs_expire_nodest_conn) {
+		if (sysctl_expire_nodest_conn(ipvs)) {
 			/* try to expire the connection immediately */
 			ip_vs_conn_expire_now(cp);
 		}
@@ -1521,7 +1605,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 	}
 
 	ip_vs_in_stats(cp, skb);
-	restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
+	restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
 	if (cp->packet_xmit)
 		ret = cp->packet_xmit(skb, cp, pp);
 		/* do not touch skb anymore */
@@ -1535,35 +1619,41 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 	 *
 	 * Sync connection if it is about to close to
 	 * encorage the standby servers to update the connections timeout
+	 *
+	 * For ONE_PKT let ip_vs_sync_conn() do the filter work.
 	 */
-	pkts = atomic_add_return(1, &cp->in_pkts);
-	if (af == AF_INET && (ip_vs_sync_state & IP_VS_STATE_MASTER) &&
+
+	if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
+		pkts = sysctl_sync_threshold(ipvs);
+	else
+		pkts = atomic_add_return(1, &cp->in_pkts);
+
+	if ((ipvs->sync_state & IP_VS_STATE_MASTER) &&
 	    cp->protocol == IPPROTO_SCTP) {
 		if ((cp->state == IP_VS_SCTP_S_ESTABLISHED &&
-			(pkts % sysctl_ip_vs_sync_threshold[1]
-			 == sysctl_ip_vs_sync_threshold[0])) ||
+			(pkts % sysctl_sync_period(ipvs)
+			 == sysctl_sync_threshold(ipvs))) ||
 				(cp->old_state != cp->state &&
 				 ((cp->state == IP_VS_SCTP_S_CLOSED) ||
 				  (cp->state == IP_VS_SCTP_S_SHUT_ACK_CLI) ||
 				  (cp->state == IP_VS_SCTP_S_SHUT_ACK_SER)))) {
-			ip_vs_sync_conn(cp);
+			ip_vs_sync_conn(net, cp);
 			goto out;
 		}
 	}
 
 	/* Keep this block last: TCP and others with pp->num_states <= 1 */
-	else if (af == AF_INET &&
-	    (ip_vs_sync_state & IP_VS_STATE_MASTER) &&
+	else if ((ipvs->sync_state & IP_VS_STATE_MASTER) &&
 	    (((cp->protocol != IPPROTO_TCP ||
 	       cp->state == IP_VS_TCP_S_ESTABLISHED) &&
-	      (pkts % sysctl_ip_vs_sync_threshold[1]
-	       == sysctl_ip_vs_sync_threshold[0])) ||
+	      (pkts % sysctl_sync_period(ipvs)
+	       == sysctl_sync_threshold(ipvs))) ||
 	     ((cp->protocol == IPPROTO_TCP) && (cp->old_state != cp->state) &&
 	      ((cp->state == IP_VS_TCP_S_FIN_WAIT) ||
 	       (cp->state == IP_VS_TCP_S_CLOSE) ||
 	       (cp->state == IP_VS_TCP_S_CLOSE_WAIT) ||
 	       (cp->state == IP_VS_TCP_S_TIME_WAIT)))))
-		ip_vs_sync_conn(cp);
+		ip_vs_sync_conn(net, cp);
 out:
 	cp->old_state = cp->state;
 
@@ -1782,7 +1872,39 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
 	},
 #endif
 };
+/*
+ *	Initialize IP Virtual Server netns mem.
+ */
+static int __net_init __ip_vs_init(struct net *net)
+{
+	struct netns_ipvs *ipvs;
+
+	ipvs = net_generic(net, ip_vs_net_id);
+	if (ipvs == NULL) {
+		pr_err("%s(): no memory.\n", __func__);
+		return -ENOMEM;
+	}
+	ipvs->net = net;
+	/* Counters used for creating unique names */
+	ipvs->gen = atomic_read(&ipvs_netns_cnt);
+	atomic_inc(&ipvs_netns_cnt);
+	net->ipvs = ipvs;
+	printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
+			 sizeof(struct netns_ipvs), ipvs->gen);
+	return 0;
+}
 
+static void __net_exit __ip_vs_cleanup(struct net *net)
+{
+	IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen);
+}
+
+static struct pernet_operations ipvs_core_ops = {
+	.init = __ip_vs_init,
+	.exit = __ip_vs_cleanup,
+	.id   = &ip_vs_net_id,
+	.size = sizeof(struct netns_ipvs),
+};
 
 /*
  *	Initialize IP Virtual Server
@@ -1791,8 +1913,11 @@ static int __init ip_vs_init(void)
 {
 	int ret;
 
-	ip_vs_estimator_init();
+	ret = register_pernet_subsys(&ipvs_core_ops);	/* Alloc ip_vs struct */
+	if (ret < 0)
+		return ret;
 
+	ip_vs_estimator_init();
 	ret = ip_vs_control_init();
 	if (ret < 0) {
 		pr_err("can't setup control.\n");
@@ -1813,15 +1938,23 @@ static int __init ip_vs_init(void)
 		goto cleanup_app;
 	}
 
+	ret = ip_vs_sync_init();
+	if (ret < 0) {
+		pr_err("can't setup sync data.\n");
+		goto cleanup_conn;
+	}
+
 	ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
 	if (ret < 0) {
 		pr_err("can't register hooks.\n");
-		goto cleanup_conn;
+		goto cleanup_sync;
 	}
 
 	pr_info("ipvs loaded.\n");
 	return ret;
 
+cleanup_sync:
+	ip_vs_sync_cleanup();
   cleanup_conn:
 	ip_vs_conn_cleanup();
   cleanup_app:
@@ -1831,17 +1964,20 @@ static int __init ip_vs_init(void)
 	ip_vs_control_cleanup();
   cleanup_estimator:
 	ip_vs_estimator_cleanup();
+	unregister_pernet_subsys(&ipvs_core_ops);	/* free ip_vs struct */
 	return ret;
 }
 
 static void __exit ip_vs_cleanup(void)
 {
 	nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
+	ip_vs_sync_cleanup();
 	ip_vs_conn_cleanup();
 	ip_vs_app_cleanup();
 	ip_vs_protocol_cleanup();
 	ip_vs_control_cleanup();
 	ip_vs_estimator_cleanup();
+	unregister_pernet_subsys(&ipvs_core_ops);	/* free ip_vs struct */
 	pr_info("ipvs unloaded.\n");
 }
 
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index ba98e13..33733c8 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -38,6 +38,7 @@
 #include <linux/mutex.h>
 
 #include <net/net_namespace.h>
+#include <linux/nsproxy.h>
 #include <net/ip.h>
 #ifdef CONFIG_IP_VS_IPV6
 #include <net/ipv6.h>
@@ -57,42 +58,7 @@ static DEFINE_MUTEX(__ip_vs_mutex);
 /* lock for service table */
 static DEFINE_RWLOCK(__ip_vs_svc_lock);
 
-/* lock for table with the real services */
-static DEFINE_RWLOCK(__ip_vs_rs_lock);
-
-/* lock for state and timeout tables */
-static DEFINE_SPINLOCK(ip_vs_securetcp_lock);
-
-/* lock for drop entry handling */
-static DEFINE_SPINLOCK(__ip_vs_dropentry_lock);
-
-/* lock for drop packet handling */
-static DEFINE_SPINLOCK(__ip_vs_droppacket_lock);
-
-/* 1/rate drop and drop-entry variables */
-int ip_vs_drop_rate = 0;
-int ip_vs_drop_counter = 0;
-static atomic_t ip_vs_dropentry = ATOMIC_INIT(0);
-
-/* number of virtual services */
-static int ip_vs_num_services = 0;
-
 /* sysctl variables */
-static int sysctl_ip_vs_drop_entry = 0;
-static int sysctl_ip_vs_drop_packet = 0;
-static int sysctl_ip_vs_secure_tcp = 0;
-static int sysctl_ip_vs_amemthresh = 1024;
-static int sysctl_ip_vs_am_droprate = 10;
-int sysctl_ip_vs_cache_bypass = 0;
-int sysctl_ip_vs_expire_nodest_conn = 0;
-int sysctl_ip_vs_expire_quiescent_template = 0;
-int sysctl_ip_vs_sync_threshold[2] = { 3, 50 };
-int sysctl_ip_vs_nat_icmp_send = 0;
-#ifdef CONFIG_IP_VS_NFCT
-int sysctl_ip_vs_conntrack;
-#endif
-int sysctl_ip_vs_snat_reroute = 1;
-
 
 #ifdef CONFIG_IP_VS_DEBUG
 static int sysctl_ip_vs_debug_level = 0;
@@ -105,27 +71,28 @@ int ip_vs_get_debug_level(void)
 
 #ifdef CONFIG_IP_VS_IPV6
 /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */
-static int __ip_vs_addr_is_local_v6(const struct in6_addr *addr)
+static int __ip_vs_addr_is_local_v6(struct net *net,
+				    const struct in6_addr *addr)
 {
 	struct rt6_info *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.fl6_dst = *addr,
-		.fl6_src = { .s6_addr32 = {0, 0, 0, 0} },
+	struct flowi6 fl6 = {
+		.daddr = *addr,
 	};
 
-	rt = (struct rt6_info *)ip6_route_output(&init_net, NULL, &fl);
+	rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
 	if (rt && rt->rt6i_dev && (rt->rt6i_dev->flags & IFF_LOOPBACK))
-			return 1;
+		return 1;
 
 	return 0;
 }
 #endif
+
+#ifdef CONFIG_SYSCTL
 /*
  *	update_defense_level is called from keventd and from sysctl,
  *	so it needs to protect itself from softirqs
  */
-static void update_defense_level(void)
+static void update_defense_level(struct netns_ipvs *ipvs)
 {
 	struct sysinfo i;
 	static int old_secure_tcp = 0;
@@ -141,73 +108,73 @@ static void update_defense_level(void)
 	/* si_swapinfo(&i); */
 	/* availmem = availmem - (i.totalswap - i.freeswap); */
 
-	nomem = (availmem < sysctl_ip_vs_amemthresh);
+	nomem = (availmem < ipvs->sysctl_amemthresh);
 
 	local_bh_disable();
 
 	/* drop_entry */
-	spin_lock(&__ip_vs_dropentry_lock);
-	switch (sysctl_ip_vs_drop_entry) {
+	spin_lock(&ipvs->dropentry_lock);
+	switch (ipvs->sysctl_drop_entry) {
 	case 0:
-		atomic_set(&ip_vs_dropentry, 0);
+		atomic_set(&ipvs->dropentry, 0);
 		break;
 	case 1:
 		if (nomem) {
-			atomic_set(&ip_vs_dropentry, 1);
-			sysctl_ip_vs_drop_entry = 2;
+			atomic_set(&ipvs->dropentry, 1);
+			ipvs->sysctl_drop_entry = 2;
 		} else {
-			atomic_set(&ip_vs_dropentry, 0);
+			atomic_set(&ipvs->dropentry, 0);
 		}
 		break;
 	case 2:
 		if (nomem) {
-			atomic_set(&ip_vs_dropentry, 1);
+			atomic_set(&ipvs->dropentry, 1);
 		} else {
-			atomic_set(&ip_vs_dropentry, 0);
-			sysctl_ip_vs_drop_entry = 1;
+			atomic_set(&ipvs->dropentry, 0);
+			ipvs->sysctl_drop_entry = 1;
 		};
 		break;
 	case 3:
-		atomic_set(&ip_vs_dropentry, 1);
+		atomic_set(&ipvs->dropentry, 1);
 		break;
 	}
-	spin_unlock(&__ip_vs_dropentry_lock);
+	spin_unlock(&ipvs->dropentry_lock);
 
 	/* drop_packet */
-	spin_lock(&__ip_vs_droppacket_lock);
-	switch (sysctl_ip_vs_drop_packet) {
+	spin_lock(&ipvs->droppacket_lock);
+	switch (ipvs->sysctl_drop_packet) {
 	case 0:
-		ip_vs_drop_rate = 0;
+		ipvs->drop_rate = 0;
 		break;
 	case 1:
 		if (nomem) {
-			ip_vs_drop_rate = ip_vs_drop_counter
-				= sysctl_ip_vs_amemthresh /
-				(sysctl_ip_vs_amemthresh-availmem);
-			sysctl_ip_vs_drop_packet = 2;
+			ipvs->drop_rate = ipvs->drop_counter
+				= ipvs->sysctl_amemthresh /
+				(ipvs->sysctl_amemthresh-availmem);
+			ipvs->sysctl_drop_packet = 2;
 		} else {
-			ip_vs_drop_rate = 0;
+			ipvs->drop_rate = 0;
 		}
 		break;
 	case 2:
 		if (nomem) {
-			ip_vs_drop_rate = ip_vs_drop_counter
-				= sysctl_ip_vs_amemthresh /
-				(sysctl_ip_vs_amemthresh-availmem);
+			ipvs->drop_rate = ipvs->drop_counter
+				= ipvs->sysctl_amemthresh /
+				(ipvs->sysctl_amemthresh-availmem);
 		} else {
-			ip_vs_drop_rate = 0;
-			sysctl_ip_vs_drop_packet = 1;
+			ipvs->drop_rate = 0;
+			ipvs->sysctl_drop_packet = 1;
 		}
 		break;
 	case 3:
-		ip_vs_drop_rate = sysctl_ip_vs_am_droprate;
+		ipvs->drop_rate = ipvs->sysctl_am_droprate;
 		break;
 	}
-	spin_unlock(&__ip_vs_droppacket_lock);
+	spin_unlock(&ipvs->droppacket_lock);
 
 	/* secure_tcp */
-	spin_lock(&ip_vs_securetcp_lock);
-	switch (sysctl_ip_vs_secure_tcp) {
+	spin_lock(&ipvs->securetcp_lock);
+	switch (ipvs->sysctl_secure_tcp) {
 	case 0:
 		if (old_secure_tcp >= 2)
 			to_change = 0;
@@ -216,7 +183,7 @@ static void update_defense_level(void)
 		if (nomem) {
 			if (old_secure_tcp < 2)
 				to_change = 1;
-			sysctl_ip_vs_secure_tcp = 2;
+			ipvs->sysctl_secure_tcp = 2;
 		} else {
 			if (old_secure_tcp >= 2)
 				to_change = 0;
@@ -229,7 +196,7 @@ static void update_defense_level(void)
 		} else {
 			if (old_secure_tcp >= 2)
 				to_change = 0;
-			sysctl_ip_vs_secure_tcp = 1;
+			ipvs->sysctl_secure_tcp = 1;
 		}
 		break;
 	case 3:
@@ -237,10 +204,11 @@ static void update_defense_level(void)
 			to_change = 1;
 		break;
 	}
-	old_secure_tcp = sysctl_ip_vs_secure_tcp;
+	old_secure_tcp = ipvs->sysctl_secure_tcp;
 	if (to_change >= 0)
-		ip_vs_protocol_timeout_change(sysctl_ip_vs_secure_tcp>1);
-	spin_unlock(&ip_vs_securetcp_lock);
+		ip_vs_protocol_timeout_change(ipvs,
+					      ipvs->sysctl_secure_tcp > 1);
+	spin_unlock(&ipvs->securetcp_lock);
 
 	local_bh_enable();
 }
@@ -250,17 +218,18 @@ static void update_defense_level(void)
  *	Timer for checking the defense
  */
 #define DEFENSE_TIMER_PERIOD	1*HZ
-static void defense_work_handler(struct work_struct *work);
-static DECLARE_DELAYED_WORK(defense_work, defense_work_handler);
 
 static void defense_work_handler(struct work_struct *work)
 {
-	update_defense_level();
-	if (atomic_read(&ip_vs_dropentry))
-		ip_vs_random_dropentry();
+	struct netns_ipvs *ipvs =
+		container_of(work, struct netns_ipvs, defense_work.work);
 
-	schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
+	update_defense_level(ipvs);
+	if (atomic_read(&ipvs->dropentry))
+		ip_vs_random_dropentry(ipvs->net);
+	schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD);
 }
+#endif
 
 int
 ip_vs_use_count_inc(void)
@@ -287,33 +256,13 @@ static struct list_head ip_vs_svc_table[IP_VS_SVC_TAB_SIZE];
 /* the service table hashed by fwmark */
 static struct list_head ip_vs_svc_fwm_table[IP_VS_SVC_TAB_SIZE];
 
-/*
- *	Hash table: for real service lookups
- */
-#define IP_VS_RTAB_BITS 4
-#define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
-#define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1)
-
-static struct list_head ip_vs_rtable[IP_VS_RTAB_SIZE];
-
-/*
- *	Trash for destinations
- */
-static LIST_HEAD(ip_vs_dest_trash);
-
-/*
- *	FTP & NULL virtual service counters
- */
-static atomic_t ip_vs_ftpsvc_counter = ATOMIC_INIT(0);
-static atomic_t ip_vs_nullsvc_counter = ATOMIC_INIT(0);
-
 
 /*
  *	Returns hash value for virtual service
  */
-static __inline__ unsigned
-ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
-		  __be16 port)
+static inline unsigned
+ip_vs_svc_hashkey(struct net *net, int af, unsigned proto,
+		  const union nf_inet_addr *addr, __be16 port)
 {
 	register unsigned porth = ntohs(port);
 	__be32 addr_fold = addr->ip;
@@ -323,6 +272,7 @@ ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
 		addr_fold = addr->ip6[0]^addr->ip6[1]^
 			    addr->ip6[2]^addr->ip6[3];
 #endif
+	addr_fold ^= ((size_t)net>>8);
 
 	return (proto^ntohl(addr_fold)^(porth>>IP_VS_SVC_TAB_BITS)^porth)
 		& IP_VS_SVC_TAB_MASK;
@@ -331,13 +281,13 @@ ip_vs_svc_hashkey(int af, unsigned proto, const union nf_inet_addr *addr,
 /*
  *	Returns hash value of fwmark for virtual service lookup
  */
-static __inline__ unsigned ip_vs_svc_fwm_hashkey(__u32 fwmark)
+static inline unsigned ip_vs_svc_fwm_hashkey(struct net *net, __u32 fwmark)
 {
-	return fwmark & IP_VS_SVC_TAB_MASK;
+	return (((size_t)net>>8) ^ fwmark) & IP_VS_SVC_TAB_MASK;
 }
 
 /*
- *	Hashes a service in the ip_vs_svc_table by <proto,addr,port>
+ *	Hashes a service in the ip_vs_svc_table by <netns,proto,addr,port>
  *	or in the ip_vs_svc_fwm_table by fwmark.
  *	Should be called with locked tables.
  */
@@ -353,16 +303,16 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
 
 	if (svc->fwmark == 0) {
 		/*
-		 *  Hash it by <protocol,addr,port> in ip_vs_svc_table
+		 *  Hash it by <netns,protocol,addr,port> in ip_vs_svc_table
 		 */
-		hash = ip_vs_svc_hashkey(svc->af, svc->protocol, &svc->addr,
-					 svc->port);
+		hash = ip_vs_svc_hashkey(svc->net, svc->af, svc->protocol,
+					 &svc->addr, svc->port);
 		list_add(&svc->s_list, &ip_vs_svc_table[hash]);
 	} else {
 		/*
-		 *  Hash it by fwmark in ip_vs_svc_fwm_table
+		 *  Hash it by fwmark in svc_fwm_table
 		 */
-		hash = ip_vs_svc_fwm_hashkey(svc->fwmark);
+		hash = ip_vs_svc_fwm_hashkey(svc->net, svc->fwmark);
 		list_add(&svc->f_list, &ip_vs_svc_fwm_table[hash]);
 	}
 
@@ -374,7 +324,7 @@ static int ip_vs_svc_hash(struct ip_vs_service *svc)
 
 
 /*
- *	Unhashes a service from ip_vs_svc_table/ip_vs_svc_fwm_table.
+ *	Unhashes a service from svc_table / svc_fwm_table.
  *	Should be called with locked tables.
  */
 static int ip_vs_svc_unhash(struct ip_vs_service *svc)
@@ -386,10 +336,10 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
 	}
 
 	if (svc->fwmark == 0) {
-		/* Remove it from the ip_vs_svc_table table */
+		/* Remove it from the svc_table table */
 		list_del(&svc->s_list);
 	} else {
-		/* Remove it from the ip_vs_svc_fwm_table table */
+		/* Remove it from the svc_fwm_table table */
 		list_del(&svc->f_list);
 	}
 
@@ -400,23 +350,24 @@ static int ip_vs_svc_unhash(struct ip_vs_service *svc)
 
 
 /*
- *	Get service by {proto,addr,port} in the service table.
+ *	Get service by {netns, proto,addr,port} in the service table.
  */
 static inline struct ip_vs_service *
-__ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr,
-		    __be16 vport)
+__ip_vs_service_find(struct net *net, int af, __u16 protocol,
+		     const union nf_inet_addr *vaddr, __be16 vport)
 {
 	unsigned hash;
 	struct ip_vs_service *svc;
 
 	/* Check for "full" addressed entries */
-	hash = ip_vs_svc_hashkey(af, protocol, vaddr, vport);
+	hash = ip_vs_svc_hashkey(net, af, protocol, vaddr, vport);
 
 	list_for_each_entry(svc, &ip_vs_svc_table[hash], s_list){
 		if ((svc->af == af)
 		    && ip_vs_addr_equal(af, &svc->addr, vaddr)
 		    && (svc->port == vport)
-		    && (svc->protocol == protocol)) {
+		    && (svc->protocol == protocol)
+		    && net_eq(svc->net, net)) {
 			/* HIT */
 			return svc;
 		}
@@ -430,16 +381,17 @@ __ip_vs_service_find(int af, __u16 protocol, const union nf_inet_addr *vaddr,
  *	Get service by {fwmark} in the service table.
  */
 static inline struct ip_vs_service *
-__ip_vs_svc_fwm_find(int af, __u32 fwmark)
+__ip_vs_svc_fwm_find(struct net *net, int af, __u32 fwmark)
 {
 	unsigned hash;
 	struct ip_vs_service *svc;
 
 	/* Check for fwmark addressed entries */
-	hash = ip_vs_svc_fwm_hashkey(fwmark);
+	hash = ip_vs_svc_fwm_hashkey(net, fwmark);
 
 	list_for_each_entry(svc, &ip_vs_svc_fwm_table[hash], f_list) {
-		if (svc->fwmark == fwmark && svc->af == af) {
+		if (svc->fwmark == fwmark && svc->af == af
+		    && net_eq(svc->net, net)) {
 			/* HIT */
 			return svc;
 		}
@@ -449,42 +401,46 @@ __ip_vs_svc_fwm_find(int af, __u32 fwmark)
 }
 
 struct ip_vs_service *
-ip_vs_service_get(int af, __u32 fwmark, __u16 protocol,
+ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
 		  const union nf_inet_addr *vaddr, __be16 vport)
 {
 	struct ip_vs_service *svc;
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
 	read_lock(&__ip_vs_svc_lock);
 
 	/*
 	 *	Check the table hashed by fwmark first
 	 */
-	if (fwmark && (svc = __ip_vs_svc_fwm_find(af, fwmark)))
-		goto out;
+	if (fwmark) {
+		svc = __ip_vs_svc_fwm_find(net, af, fwmark);
+		if (svc)
+			goto out;
+	}
 
 	/*
 	 *	Check the table hashed by <protocol,addr,port>
 	 *	for "full" addressed entries
 	 */
-	svc = __ip_vs_service_find(af, protocol, vaddr, vport);
+	svc = __ip_vs_service_find(net, af, protocol, vaddr, vport);
 
 	if (svc == NULL
 	    && protocol == IPPROTO_TCP
-	    && atomic_read(&ip_vs_ftpsvc_counter)
+	    && atomic_read(&ipvs->ftpsvc_counter)
 	    && (vport == FTPDATA || ntohs(vport) >= PROT_SOCK)) {
 		/*
 		 * Check if ftp service entry exists, the packet
 		 * might belong to FTP data connections.
 		 */
-		svc = __ip_vs_service_find(af, protocol, vaddr, FTPPORT);
+		svc = __ip_vs_service_find(net, af, protocol, vaddr, FTPPORT);
 	}
 
 	if (svc == NULL
-	    && atomic_read(&ip_vs_nullsvc_counter)) {
+	    && atomic_read(&ipvs->nullsvc_counter)) {
 		/*
 		 * Check if the catch-all port (port zero) exists
 		 */
-		svc = __ip_vs_service_find(af, protocol, vaddr, 0);
+		svc = __ip_vs_service_find(net, af, protocol, vaddr, 0);
 	}
 
   out:
@@ -519,6 +475,7 @@ __ip_vs_unbind_svc(struct ip_vs_dest *dest)
 			      svc->fwmark,
 			      IP_VS_DBG_ADDR(svc->af, &svc->addr),
 			      ntohs(svc->port), atomic_read(&svc->usecnt));
+		free_percpu(svc->stats.cpustats);
 		kfree(svc);
 	}
 }
@@ -545,10 +502,10 @@ static inline unsigned ip_vs_rs_hashkey(int af,
 }
 
 /*
- *	Hashes ip_vs_dest in ip_vs_rtable by <proto,addr,port>.
+ *	Hashes ip_vs_dest in rs_table by <proto,addr,port>.
  *	should be called with locked tables.
  */
-static int ip_vs_rs_hash(struct ip_vs_dest *dest)
+static int ip_vs_rs_hash(struct netns_ipvs *ipvs, struct ip_vs_dest *dest)
 {
 	unsigned hash;
 
@@ -562,19 +519,19 @@ static int ip_vs_rs_hash(struct ip_vs_dest *dest)
 	 */
 	hash = ip_vs_rs_hashkey(dest->af, &dest->addr, dest->port);
 
-	list_add(&dest->d_list, &ip_vs_rtable[hash]);
+	list_add(&dest->d_list, &ipvs->rs_table[hash]);
 
 	return 1;
 }
 
 /*
- *	UNhashes ip_vs_dest from ip_vs_rtable.
+ *	UNhashes ip_vs_dest from rs_table.
  *	should be called with locked tables.
  */
 static int ip_vs_rs_unhash(struct ip_vs_dest *dest)
 {
 	/*
-	 * Remove it from the ip_vs_rtable table.
+	 * Remove it from the rs_table table.
 	 */
 	if (!list_empty(&dest->d_list)) {
 		list_del(&dest->d_list);
@@ -588,10 +545,11 @@ static int ip_vs_rs_unhash(struct ip_vs_dest *dest)
  *	Lookup real service by <proto,addr,port> in the real service table.
  */
 struct ip_vs_dest *
-ip_vs_lookup_real_service(int af, __u16 protocol,
+ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
 			  const union nf_inet_addr *daddr,
 			  __be16 dport)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	unsigned hash;
 	struct ip_vs_dest *dest;
 
@@ -601,19 +559,19 @@ ip_vs_lookup_real_service(int af, __u16 protocol,
 	 */
 	hash = ip_vs_rs_hashkey(af, daddr, dport);
 
-	read_lock(&__ip_vs_rs_lock);
-	list_for_each_entry(dest, &ip_vs_rtable[hash], d_list) {
+	read_lock(&ipvs->rs_lock);
+	list_for_each_entry(dest, &ipvs->rs_table[hash], d_list) {
 		if ((dest->af == af)
 		    && ip_vs_addr_equal(af, &dest->addr, daddr)
 		    && (dest->port == dport)
 		    && ((dest->protocol == protocol) ||
 			dest->vfwmark)) {
 			/* HIT */
-			read_unlock(&__ip_vs_rs_lock);
+			read_unlock(&ipvs->rs_lock);
 			return dest;
 		}
 	}
-	read_unlock(&__ip_vs_rs_lock);
+	read_unlock(&ipvs->rs_lock);
 
 	return NULL;
 }
@@ -652,15 +610,16 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
  * ip_vs_lookup_real_service() looked promissing, but
  * seems not working as expected.
  */
-struct ip_vs_dest *ip_vs_find_dest(int af, const union nf_inet_addr *daddr,
+struct ip_vs_dest *ip_vs_find_dest(struct net  *net, int af,
+				   const union nf_inet_addr *daddr,
 				   __be16 dport,
 				   const union nf_inet_addr *vaddr,
-				   __be16 vport, __u16 protocol)
+				   __be16 vport, __u16 protocol, __u32 fwmark)
 {
 	struct ip_vs_dest *dest;
 	struct ip_vs_service *svc;
 
-	svc = ip_vs_service_get(af, 0, protocol, vaddr, vport);
+	svc = ip_vs_service_get(net, af, fwmark, protocol, vaddr, vport);
 	if (!svc)
 		return NULL;
 	dest = ip_vs_lookup_dest(svc, daddr, dport);
@@ -685,11 +644,12 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
 		     __be16 dport)
 {
 	struct ip_vs_dest *dest, *nxt;
+	struct netns_ipvs *ipvs = net_ipvs(svc->net);
 
 	/*
 	 * Find the destination in trash
 	 */
-	list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) {
+	list_for_each_entry_safe(dest, nxt, &ipvs->dest_trash, n_list) {
 		IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, "
 			      "dest->refcnt=%d\n",
 			      dest->vfwmark,
@@ -720,6 +680,7 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
 			list_del(&dest->n_list);
 			ip_vs_dst_reset(dest);
 			__ip_vs_unbind_svc(dest);
+			free_percpu(dest->stats.cpustats);
 			kfree(dest);
 		}
 	}
@@ -737,25 +698,53 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
  *  are expired, and the refcnt of each destination in the trash must
  *  be 1, so we simply release them here.
  */
-static void ip_vs_trash_cleanup(void)
+static void ip_vs_trash_cleanup(struct net *net)
 {
 	struct ip_vs_dest *dest, *nxt;
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
-	list_for_each_entry_safe(dest, nxt, &ip_vs_dest_trash, n_list) {
+	list_for_each_entry_safe(dest, nxt, &ipvs->dest_trash, n_list) {
 		list_del(&dest->n_list);
 		ip_vs_dst_reset(dest);
 		__ip_vs_unbind_svc(dest);
+		free_percpu(dest->stats.cpustats);
 		kfree(dest);
 	}
 }
 
+static void
+ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src)
+{
+#define IP_VS_SHOW_STATS_COUNTER(c) dst->c = src->ustats.c - src->ustats0.c
+
+	spin_lock_bh(&src->lock);
+
+	IP_VS_SHOW_STATS_COUNTER(conns);
+	IP_VS_SHOW_STATS_COUNTER(inpkts);
+	IP_VS_SHOW_STATS_COUNTER(outpkts);
+	IP_VS_SHOW_STATS_COUNTER(inbytes);
+	IP_VS_SHOW_STATS_COUNTER(outbytes);
+
+	ip_vs_read_estimator(dst, src);
+
+	spin_unlock_bh(&src->lock);
+}
 
 static void
 ip_vs_zero_stats(struct ip_vs_stats *stats)
 {
 	spin_lock_bh(&stats->lock);
 
-	memset(&stats->ustats, 0, sizeof(stats->ustats));
+	/* get current counters as zero point, rates are zeroed */
+
+#define IP_VS_ZERO_STATS_COUNTER(c) stats->ustats0.c = stats->ustats.c
+
+	IP_VS_ZERO_STATS_COUNTER(conns);
+	IP_VS_ZERO_STATS_COUNTER(inpkts);
+	IP_VS_ZERO_STATS_COUNTER(outpkts);
+	IP_VS_ZERO_STATS_COUNTER(inbytes);
+	IP_VS_ZERO_STATS_COUNTER(outbytes);
+
 	ip_vs_zero_estimator(stats);
 
 	spin_unlock_bh(&stats->lock);
@@ -768,6 +757,7 @@ static void
 __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
 		    struct ip_vs_dest_user_kern *udest, int add)
 {
+	struct netns_ipvs *ipvs = net_ipvs(svc->net);
 	int conn_flags;
 
 	/* set the weight and the flags */
@@ -780,12 +770,12 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
 		conn_flags |= IP_VS_CONN_F_NOOUTPUT;
 	} else {
 		/*
-		 *    Put the real service in ip_vs_rtable if not present.
+		 *    Put the real service in rs_table if not present.
 		 *    For now only for NAT!
 		 */
-		write_lock_bh(&__ip_vs_rs_lock);
-		ip_vs_rs_hash(dest);
-		write_unlock_bh(&__ip_vs_rs_lock);
+		write_lock_bh(&ipvs->rs_lock);
+		ip_vs_rs_hash(ipvs, dest);
+		write_unlock_bh(&ipvs->rs_lock);
 	}
 	atomic_set(&dest->conn_flags, conn_flags);
 
@@ -813,7 +803,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
 	spin_unlock_bh(&dest->dst_lock);
 
 	if (add)
-		ip_vs_new_estimator(&dest->stats);
+		ip_vs_start_estimator(svc->net, &dest->stats);
 
 	write_lock_bh(&__ip_vs_svc_lock);
 
@@ -850,12 +840,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 		atype = ipv6_addr_type(&udest->addr.in6);
 		if ((!(atype & IPV6_ADDR_UNICAST) ||
 			atype & IPV6_ADDR_LINKLOCAL) &&
-			!__ip_vs_addr_is_local_v6(&udest->addr.in6))
+			!__ip_vs_addr_is_local_v6(svc->net, &udest->addr.in6))
 			return -EINVAL;
 	} else
 #endif
 	{
-		atype = inet_addr_type(&init_net, udest->addr.ip);
+		atype = inet_addr_type(svc->net, udest->addr.ip);
 		if (atype != RTN_LOCAL && atype != RTN_UNICAST)
 			return -EINVAL;
 	}
@@ -865,6 +855,11 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 		pr_err("%s(): no memory.\n", __func__);
 		return -ENOMEM;
 	}
+	dest->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats);
+	if (!dest->stats.cpustats) {
+		pr_err("%s() alloc_percpu failed\n", __func__);
+		goto err_alloc;
+	}
 
 	dest->af = svc->af;
 	dest->protocol = svc->protocol;
@@ -888,6 +883,10 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 
 	LeaveFunction(2);
 	return 0;
+
+err_alloc:
+	kfree(dest);
+	return -ENOMEM;
 }
 
 
@@ -1006,16 +1005,18 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
 /*
  *	Delete a destination (must be already unlinked from the service)
  */
-static void __ip_vs_del_dest(struct ip_vs_dest *dest)
+static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest)
 {
-	ip_vs_kill_estimator(&dest->stats);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	ip_vs_stop_estimator(net, &dest->stats);
 
 	/*
 	 *  Remove it from the d-linked list with the real services.
 	 */
-	write_lock_bh(&__ip_vs_rs_lock);
+	write_lock_bh(&ipvs->rs_lock);
 	ip_vs_rs_unhash(dest);
-	write_unlock_bh(&__ip_vs_rs_lock);
+	write_unlock_bh(&ipvs->rs_lock);
 
 	/*
 	 *  Decrease the refcnt of the dest, and free the dest
@@ -1034,6 +1035,7 @@ static void __ip_vs_del_dest(struct ip_vs_dest *dest)
 		   and only one user context can update virtual service at a
 		   time, so the operation here is OK */
 		atomic_dec(&dest->svc->refcnt);
+		free_percpu(dest->stats.cpustats);
 		kfree(dest);
 	} else {
 		IP_VS_DBG_BUF(3, "Moving dest %s:%u into trash, "
@@ -1041,7 +1043,7 @@ static void __ip_vs_del_dest(struct ip_vs_dest *dest)
 			      IP_VS_DBG_ADDR(dest->af, &dest->addr),
 			      ntohs(dest->port),
 			      atomic_read(&dest->refcnt));
-		list_add(&dest->n_list, &ip_vs_dest_trash);
+		list_add(&dest->n_list, &ipvs->dest_trash);
 		atomic_inc(&dest->refcnt);
 	}
 }
@@ -1105,7 +1107,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
 	/*
 	 *	Delete the destination
 	 */
-	__ip_vs_del_dest(dest);
+	__ip_vs_del_dest(svc->net, dest);
 
 	LeaveFunction(2);
 
@@ -1117,13 +1119,14 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
  *	Add a service into the service hash table
  */
 static int
-ip_vs_add_service(struct ip_vs_service_user_kern *u,
+ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
 		  struct ip_vs_service **svc_p)
 {
 	int ret = 0;
 	struct ip_vs_scheduler *sched = NULL;
 	struct ip_vs_pe *pe = NULL;
 	struct ip_vs_service *svc = NULL;
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
 	/* increase the module use count */
 	ip_vs_use_count_inc();
@@ -1137,7 +1140,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
 	}
 
 	if (u->pe_name && *u->pe_name) {
-		pe = ip_vs_pe_get(u->pe_name);
+		pe = ip_vs_pe_getbyname(u->pe_name);
 		if (pe == NULL) {
 			pr_info("persistence engine module ip_vs_pe_%s "
 				"not found\n", u->pe_name);
@@ -1159,6 +1162,11 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
 		ret = -ENOMEM;
 		goto out_err;
 	}
+	svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats);
+	if (!svc->stats.cpustats) {
+		pr_err("%s() alloc_percpu failed\n", __func__);
+		goto out_err;
+	}
 
 	/* I'm the first user of the service */
 	atomic_set(&svc->usecnt, 0);
@@ -1172,6 +1180,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
 	svc->flags = u->flags;
 	svc->timeout = u->timeout * HZ;
 	svc->netmask = u->netmask;
+	svc->net = net;
 
 	INIT_LIST_HEAD(&svc->destinations);
 	rwlock_init(&svc->sched_lock);
@@ -1189,15 +1198,15 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
 
 	/* Update the virtual service counters */
 	if (svc->port == FTPPORT)
-		atomic_inc(&ip_vs_ftpsvc_counter);
+		atomic_inc(&ipvs->ftpsvc_counter);
 	else if (svc->port == 0)
-		atomic_inc(&ip_vs_nullsvc_counter);
+		atomic_inc(&ipvs->nullsvc_counter);
 
-	ip_vs_new_estimator(&svc->stats);
+	ip_vs_start_estimator(net, &svc->stats);
 
 	/* Count only IPv4 services for old get/setsockopt interface */
 	if (svc->af == AF_INET)
-		ip_vs_num_services++;
+		ipvs->num_services++;
 
 	/* Hash the service into the service table */
 	write_lock_bh(&__ip_vs_svc_lock);
@@ -1207,6 +1216,7 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
 	*svc_p = svc;
 	return 0;
 
+
  out_err:
 	if (svc != NULL) {
 		ip_vs_unbind_scheduler(svc);
@@ -1215,6 +1225,8 @@ ip_vs_add_service(struct ip_vs_service_user_kern *u,
 			ip_vs_app_inc_put(svc->inc);
 			local_bh_enable();
 		}
+		if (svc->stats.cpustats)
+			free_percpu(svc->stats.cpustats);
 		kfree(svc);
 	}
 	ip_vs_scheduler_put(sched);
@@ -1248,7 +1260,7 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
 	old_sched = sched;
 
 	if (u->pe_name && *u->pe_name) {
-		pe = ip_vs_pe_get(u->pe_name);
+		pe = ip_vs_pe_getbyname(u->pe_name);
 		if (pe == NULL) {
 			pr_info("persistence engine module ip_vs_pe_%s "
 				"not found\n", u->pe_name);
@@ -1334,14 +1346,15 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
 	struct ip_vs_dest *dest, *nxt;
 	struct ip_vs_scheduler *old_sched;
 	struct ip_vs_pe *old_pe;
+	struct netns_ipvs *ipvs = net_ipvs(svc->net);
 
 	pr_info("%s: enter\n", __func__);
 
 	/* Count only IPv4 services for old get/setsockopt interface */
 	if (svc->af == AF_INET)
-		ip_vs_num_services--;
+		ipvs->num_services--;
 
-	ip_vs_kill_estimator(&svc->stats);
+	ip_vs_stop_estimator(svc->net, &svc->stats);
 
 	/* Unbind scheduler */
 	old_sched = svc->scheduler;
@@ -1364,16 +1377,16 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
 	 */
 	list_for_each_entry_safe(dest, nxt, &svc->destinations, n_list) {
 		__ip_vs_unlink_dest(svc, dest, 0);
-		__ip_vs_del_dest(dest);
+		__ip_vs_del_dest(svc->net, dest);
 	}
 
 	/*
 	 *    Update the virtual service counters
 	 */
 	if (svc->port == FTPPORT)
-		atomic_dec(&ip_vs_ftpsvc_counter);
+		atomic_dec(&ipvs->ftpsvc_counter);
 	else if (svc->port == 0)
-		atomic_dec(&ip_vs_nullsvc_counter);
+		atomic_dec(&ipvs->nullsvc_counter);
 
 	/*
 	 *    Free the service if nobody refers to it
@@ -1383,6 +1396,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc)
 			      svc->fwmark,
 			      IP_VS_DBG_ADDR(svc->af, &svc->addr),
 			      ntohs(svc->port), atomic_read(&svc->usecnt));
+		free_percpu(svc->stats.cpustats);
 		kfree(svc);
 	}
 
@@ -1428,17 +1442,19 @@ static int ip_vs_del_service(struct ip_vs_service *svc)
 /*
  *	Flush all the virtual services
  */
-static int ip_vs_flush(void)
+static int ip_vs_flush(struct net *net)
 {
 	int idx;
 	struct ip_vs_service *svc, *nxt;
 
 	/*
-	 * Flush the service table hashed by <protocol,addr,port>
+	 * Flush the service table hashed by <netns,protocol,addr,port>
 	 */
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
-		list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx], s_list) {
-			ip_vs_unlink_service(svc);
+		list_for_each_entry_safe(svc, nxt, &ip_vs_svc_table[idx],
+					 s_list) {
+			if (net_eq(svc->net, net))
+				ip_vs_unlink_service(svc);
 		}
 	}
 
@@ -1448,7 +1464,8 @@ static int ip_vs_flush(void)
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry_safe(svc, nxt,
 					 &ip_vs_svc_fwm_table[idx], f_list) {
-			ip_vs_unlink_service(svc);
+			if (net_eq(svc->net, net))
+				ip_vs_unlink_service(svc);
 		}
 	}
 
@@ -1472,32 +1489,35 @@ static int ip_vs_zero_service(struct ip_vs_service *svc)
 	return 0;
 }
 
-static int ip_vs_zero_all(void)
+static int ip_vs_zero_all(struct net *net)
 {
 	int idx;
 	struct ip_vs_service *svc;
 
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
-			ip_vs_zero_service(svc);
+			if (net_eq(svc->net, net))
+				ip_vs_zero_service(svc);
 		}
 	}
 
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
-			ip_vs_zero_service(svc);
+			if (net_eq(svc->net, net))
+				ip_vs_zero_service(svc);
 		}
 	}
 
-	ip_vs_zero_stats(&ip_vs_stats);
+	ip_vs_zero_stats(&net_ipvs(net)->tot_stats);
 	return 0;
 }
 
-
+#ifdef CONFIG_SYSCTL
 static int
 proc_do_defense_mode(ctl_table *table, int write,
 		     void __user *buffer, size_t *lenp, loff_t *ppos)
 {
+	struct net *net = current->nsproxy->net_ns;
 	int *valp = table->data;
 	int val = *valp;
 	int rc;
@@ -1508,13 +1528,12 @@ proc_do_defense_mode(ctl_table *table, int write,
 			/* Restore the correct value */
 			*valp = val;
 		} else {
-			update_defense_level();
+			update_defense_level(net_ipvs(net));
 		}
 	}
 	return rc;
 }
 
-
 static int
 proc_do_sync_threshold(ctl_table *table, int write,
 		       void __user *buffer, size_t *lenp, loff_t *ppos)
@@ -1534,45 +1553,54 @@ proc_do_sync_threshold(ctl_table *table, int write,
 	return rc;
 }
 
+static int
+proc_do_sync_mode(ctl_table *table, int write,
+		     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	int *valp = table->data;
+	int val = *valp;
+	int rc;
+
+	rc = proc_dointvec(table, write, buffer, lenp, ppos);
+	if (write && (*valp != val)) {
+		if ((*valp < 0) || (*valp > 1)) {
+			/* Restore the correct value */
+			*valp = val;
+		} else {
+			struct net *net = current->nsproxy->net_ns;
+			ip_vs_sync_switch_mode(net, val);
+		}
+	}
+	return rc;
+}
 
 /*
  *	IPVS sysctl table (under the /proc/sys/net/ipv4/vs/)
+ *	Do not change order or insert new entries without
+ *	align with netns init in __ip_vs_control_init()
  */
 
 static struct ctl_table vs_vars[] = {
 	{
 		.procname	= "amemthresh",
-		.data		= &sysctl_ip_vs_amemthresh,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-#ifdef CONFIG_IP_VS_DEBUG
-	{
-		.procname	= "debug_level",
-		.data		= &sysctl_ip_vs_debug_level,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
-#endif
 	{
 		.procname	= "am_droprate",
-		.data		= &sysctl_ip_vs_am_droprate,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
 	{
 		.procname	= "drop_entry",
-		.data		= &sysctl_ip_vs_drop_entry,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_do_defense_mode,
 	},
 	{
 		.procname	= "drop_packet",
-		.data		= &sysctl_ip_vs_drop_packet,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_do_defense_mode,
@@ -1580,7 +1608,6 @@ static struct ctl_table vs_vars[] = {
 #ifdef CONFIG_IP_VS_NFCT
 	{
 		.procname	= "conntrack",
-		.data		= &sysctl_ip_vs_conntrack,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
@@ -1588,18 +1615,62 @@ static struct ctl_table vs_vars[] = {
 #endif
 	{
 		.procname	= "secure_tcp",
-		.data		= &sysctl_ip_vs_secure_tcp,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_do_defense_mode,
 	},
 	{
 		.procname	= "snat_reroute",
-		.data		= &sysctl_ip_vs_snat_reroute,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec,
 	},
+	{
+		.procname	= "sync_version",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_do_sync_mode,
+	},
+	{
+		.procname	= "cache_bypass",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "expire_nodest_conn",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "expire_quiescent_template",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{
+		.procname	= "sync_threshold",
+		.maxlen		=
+			sizeof(((struct netns_ipvs *)0)->sysctl_sync_threshold),
+		.mode		= 0644,
+		.proc_handler	= proc_do_sync_threshold,
+	},
+	{
+		.procname	= "nat_icmp_send",
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+#ifdef CONFIG_IP_VS_DEBUG
+	{
+		.procname	= "debug_level",
+		.data		= &sysctl_ip_vs_debug_level,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+#endif
 #if 0
 	{
 		.procname	= "timeout_established",
@@ -1686,41 +1757,6 @@ static struct ctl_table vs_vars[] = {
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 #endif
-	{
-		.procname	= "cache_bypass",
-		.data		= &sysctl_ip_vs_cache_bypass,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-	{
-		.procname	= "expire_nodest_conn",
-		.data		= &sysctl_ip_vs_expire_nodest_conn,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-	{
-		.procname	= "expire_quiescent_template",
-		.data		= &sysctl_ip_vs_expire_quiescent_template,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-	{
-		.procname	= "sync_threshold",
-		.data		= &sysctl_ip_vs_sync_threshold,
-		.maxlen		= sizeof(sysctl_ip_vs_sync_threshold),
-		.mode		= 0644,
-		.proc_handler	= proc_do_sync_threshold,
-	},
-	{
-		.procname	= "nat_icmp_send",
-		.data		= &sysctl_ip_vs_nat_icmp_send,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
 	{ }
 };
 
@@ -1731,12 +1767,12 @@ const struct ctl_path net_vs_ctl_path[] = {
 	{ }
 };
 EXPORT_SYMBOL_GPL(net_vs_ctl_path);
-
-static struct ctl_table_header * sysctl_header;
+#endif
 
 #ifdef CONFIG_PROC_FS
 
 struct ip_vs_iter {
+	struct seq_net_private p;  /* Do not move this, netns depends upon it*/
 	struct list_head *table;
 	int bucket;
 };
@@ -1763,6 +1799,7 @@ static inline const char *ip_vs_fwd_name(unsigned flags)
 /* Get the Nth entry in the two lists */
 static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
 {
+	struct net *net = seq_file_net(seq);
 	struct ip_vs_iter *iter = seq->private;
 	int idx;
 	struct ip_vs_service *svc;
@@ -1770,7 +1807,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
 	/* look in hash by protocol */
 	for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
-			if (pos-- == 0){
+			if (net_eq(svc->net, net) && pos-- == 0) {
 				iter->table = ip_vs_svc_table;
 				iter->bucket = idx;
 				return svc;
@@ -1781,7 +1818,7 @@ static struct ip_vs_service *ip_vs_info_array(struct seq_file *seq, loff_t pos)
 	/* keep looking in fwmark */
 	for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
-			if (pos-- == 0) {
+			if (net_eq(svc->net, net) && pos-- == 0) {
 				iter->table = ip_vs_svc_fwm_table;
 				iter->bucket = idx;
 				return svc;
@@ -1935,7 +1972,7 @@ static const struct seq_operations ip_vs_info_seq_ops = {
 
 static int ip_vs_info_open(struct inode *inode, struct file *file)
 {
-	return seq_open_private(file, &ip_vs_info_seq_ops,
+	return seq_open_net(inode, file, &ip_vs_info_seq_ops,
 			sizeof(struct ip_vs_iter));
 }
 
@@ -1949,13 +1986,11 @@ static const struct file_operations ip_vs_info_fops = {
 
 #endif
 
-struct ip_vs_stats ip_vs_stats = {
-	.lock = __SPIN_LOCK_UNLOCKED(ip_vs_stats.lock),
-};
-
 #ifdef CONFIG_PROC_FS
 static int ip_vs_stats_show(struct seq_file *seq, void *v)
 {
+	struct net *net = seq_file_single_net(seq);
+	struct ip_vs_stats_user show;
 
 /*               01234567 01234567 01234567 0123456701234567 0123456701234567 */
 	seq_puts(seq,
@@ -1963,29 +1998,25 @@ static int ip_vs_stats_show(struct seq_file *seq, void *v)
 	seq_printf(seq,
 		   "   Conns  Packets  Packets            Bytes            Bytes\n");
 
-	spin_lock_bh(&ip_vs_stats.lock);
-	seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", ip_vs_stats.ustats.conns,
-		   ip_vs_stats.ustats.inpkts, ip_vs_stats.ustats.outpkts,
-		   (unsigned long long) ip_vs_stats.ustats.inbytes,
-		   (unsigned long long) ip_vs_stats.ustats.outbytes);
+	ip_vs_copy_stats(&show, &net_ipvs(net)->tot_stats);
+	seq_printf(seq, "%8X %8X %8X %16LX %16LX\n\n", show.conns,
+		   show.inpkts, show.outpkts,
+		   (unsigned long long) show.inbytes,
+		   (unsigned long long) show.outbytes);
 
 /*                 01234567 01234567 01234567 0123456701234567 0123456701234567 */
 	seq_puts(seq,
 		   " Conns/s   Pkts/s   Pkts/s          Bytes/s          Bytes/s\n");
-	seq_printf(seq,"%8X %8X %8X %16X %16X\n",
-			ip_vs_stats.ustats.cps,
-			ip_vs_stats.ustats.inpps,
-			ip_vs_stats.ustats.outpps,
-			ip_vs_stats.ustats.inbps,
-			ip_vs_stats.ustats.outbps);
-	spin_unlock_bh(&ip_vs_stats.lock);
+	seq_printf(seq, "%8X %8X %8X %16X %16X\n",
+			show.cps, show.inpps, show.outpps,
+			show.inbps, show.outbps);
 
 	return 0;
 }
 
 static int ip_vs_stats_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, ip_vs_stats_show, NULL);
+	return single_open_net(inode, file, ip_vs_stats_show);
 }
 
 static const struct file_operations ip_vs_stats_fops = {
@@ -1996,13 +2027,85 @@ static const struct file_operations ip_vs_stats_fops = {
 	.release = single_release,
 };
 
+static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v)
+{
+	struct net *net = seq_file_single_net(seq);
+	struct ip_vs_stats *tot_stats = &net_ipvs(net)->tot_stats;
+	struct ip_vs_cpu_stats *cpustats = tot_stats->cpustats;
+	struct ip_vs_stats_user rates;
+	int i;
+
+/*               01234567 01234567 01234567 0123456701234567 0123456701234567 */
+	seq_puts(seq,
+		 "       Total Incoming Outgoing         Incoming         Outgoing\n");
+	seq_printf(seq,
+		   "CPU    Conns  Packets  Packets            Bytes            Bytes\n");
+
+	for_each_possible_cpu(i) {
+		struct ip_vs_cpu_stats *u = per_cpu_ptr(cpustats, i);
+		unsigned int start;
+		__u64 inbytes, outbytes;
+
+		do {
+			start = u64_stats_fetch_begin_bh(&u->syncp);
+			inbytes = u->ustats.inbytes;
+			outbytes = u->ustats.outbytes;
+		} while (u64_stats_fetch_retry_bh(&u->syncp, start));
+
+		seq_printf(seq, "%3X %8X %8X %8X %16LX %16LX\n",
+			   i, u->ustats.conns, u->ustats.inpkts,
+			   u->ustats.outpkts, (__u64)inbytes,
+			   (__u64)outbytes);
+	}
+
+	spin_lock_bh(&tot_stats->lock);
+
+	seq_printf(seq, "  ~ %8X %8X %8X %16LX %16LX\n\n",
+		   tot_stats->ustats.conns, tot_stats->ustats.inpkts,
+		   tot_stats->ustats.outpkts,
+		   (unsigned long long) tot_stats->ustats.inbytes,
+		   (unsigned long long) tot_stats->ustats.outbytes);
+
+	ip_vs_read_estimator(&rates, tot_stats);
+
+	spin_unlock_bh(&tot_stats->lock);
+
+/*                 01234567 01234567 01234567 0123456701234567 0123456701234567 */
+	seq_puts(seq,
+		   "     Conns/s   Pkts/s   Pkts/s          Bytes/s          Bytes/s\n");
+	seq_printf(seq, "    %8X %8X %8X %16X %16X\n",
+			rates.cps,
+			rates.inpps,
+			rates.outpps,
+			rates.inbps,
+			rates.outbps);
+
+	return 0;
+}
+
+static int ip_vs_stats_percpu_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open_net(inode, file, ip_vs_stats_percpu_show);
+}
+
+static const struct file_operations ip_vs_stats_percpu_fops = {
+	.owner = THIS_MODULE,
+	.open = ip_vs_stats_percpu_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 #endif
 
 /*
  *	Set timeout values for tcp tcpfin udp in the timeout_table.
  */
-static int ip_vs_set_timeout(struct ip_vs_timeout_user *u)
+static int ip_vs_set_timeout(struct net *net, struct ip_vs_timeout_user *u)
 {
+#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
+	struct ip_vs_proto_data *pd;
+#endif
+
 	IP_VS_DBG(2, "Setting timeout tcp:%d tcpfin:%d udp:%d\n",
 		  u->tcp_timeout,
 		  u->tcp_fin_timeout,
@@ -2010,19 +2113,22 @@ static int ip_vs_set_timeout(struct ip_vs_timeout_user *u)
 
 #ifdef CONFIG_IP_VS_PROTO_TCP
 	if (u->tcp_timeout) {
-		ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_ESTABLISHED]
+		pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+		pd->timeout_table[IP_VS_TCP_S_ESTABLISHED]
 			= u->tcp_timeout * HZ;
 	}
 
 	if (u->tcp_fin_timeout) {
-		ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_FIN_WAIT]
+		pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+		pd->timeout_table[IP_VS_TCP_S_FIN_WAIT]
 			= u->tcp_fin_timeout * HZ;
 	}
 #endif
 
 #ifdef CONFIG_IP_VS_PROTO_UDP
 	if (u->udp_timeout) {
-		ip_vs_protocol_udp.timeout_table[IP_VS_UDP_S_NORMAL]
+		pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
+		pd->timeout_table[IP_VS_UDP_S_NORMAL]
 			= u->udp_timeout * HZ;
 	}
 #endif
@@ -2087,6 +2193,7 @@ static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
 static int
 do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 {
+	struct net *net = sock_net(sk);
 	int ret;
 	unsigned char arg[MAX_ARG_LEN];
 	struct ip_vs_service_user *usvc_compat;
@@ -2121,19 +2228,20 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
 	if (cmd == IP_VS_SO_SET_FLUSH) {
 		/* Flush the virtual service */
-		ret = ip_vs_flush();
+		ret = ip_vs_flush(net);
 		goto out_unlock;
 	} else if (cmd == IP_VS_SO_SET_TIMEOUT) {
 		/* Set timeout values for (tcp tcpfin udp) */
-		ret = ip_vs_set_timeout((struct ip_vs_timeout_user *)arg);
+		ret = ip_vs_set_timeout(net, (struct ip_vs_timeout_user *)arg);
 		goto out_unlock;
 	} else if (cmd == IP_VS_SO_SET_STARTDAEMON) {
 		struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
-		ret = start_sync_thread(dm->state, dm->mcast_ifn, dm->syncid);
+		ret = start_sync_thread(net, dm->state, dm->mcast_ifn,
+					dm->syncid);
 		goto out_unlock;
 	} else if (cmd == IP_VS_SO_SET_STOPDAEMON) {
 		struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
-		ret = stop_sync_thread(dm->state);
+		ret = stop_sync_thread(net, dm->state);
 		goto out_unlock;
 	}
 
@@ -2148,7 +2256,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 	if (cmd == IP_VS_SO_SET_ZERO) {
 		/* if no service address is set, zero counters in all */
 		if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) {
-			ret = ip_vs_zero_all();
+			ret = ip_vs_zero_all(net);
 			goto out_unlock;
 		}
 	}
@@ -2165,10 +2273,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
 	/* Lookup the exact service by <protocol, addr, port> or fwmark */
 	if (usvc.fwmark == 0)
-		svc = __ip_vs_service_find(usvc.af, usvc.protocol,
+		svc = __ip_vs_service_find(net, usvc.af, usvc.protocol,
 					   &usvc.addr, usvc.port);
 	else
-		svc = __ip_vs_svc_fwm_find(usvc.af, usvc.fwmark);
+		svc = __ip_vs_svc_fwm_find(net, usvc.af, usvc.fwmark);
 
 	if (cmd != IP_VS_SO_SET_ADD
 	    && (svc == NULL || svc->protocol != usvc.protocol)) {
@@ -2181,7 +2289,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 		if (svc != NULL)
 			ret = -EEXIST;
 		else
-			ret = ip_vs_add_service(&usvc, &svc);
+			ret = ip_vs_add_service(net, &usvc, &svc);
 		break;
 	case IP_VS_SO_SET_EDIT:
 		ret = ip_vs_edit_service(svc, &usvc);
@@ -2218,14 +2326,6 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
 
 static void
-ip_vs_copy_stats(struct ip_vs_stats_user *dst, struct ip_vs_stats *src)
-{
-	spin_lock_bh(&src->lock);
-	memcpy(dst, &src->ustats, sizeof(*dst));
-	spin_unlock_bh(&src->lock);
-}
-
-static void
 ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
 {
 	dst->protocol = src->protocol;
@@ -2241,7 +2341,8 @@ ip_vs_copy_service(struct ip_vs_service_entry *dst, struct ip_vs_service *src)
 }
 
 static inline int
-__ip_vs_get_service_entries(const struct ip_vs_get_services *get,
+__ip_vs_get_service_entries(struct net *net,
+			    const struct ip_vs_get_services *get,
 			    struct ip_vs_get_services __user *uptr)
 {
 	int idx, count=0;
@@ -2252,7 +2353,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
 	for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
 			/* Only expose IPv4 entries to old interface */
-			if (svc->af != AF_INET)
+			if (svc->af != AF_INET || !net_eq(svc->net, net))
 				continue;
 
 			if (count >= get->num_services)
@@ -2271,7 +2372,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
 	for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
 		list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
 			/* Only expose IPv4 entries to old interface */
-			if (svc->af != AF_INET)
+			if (svc->af != AF_INET || !net_eq(svc->net, net))
 				continue;
 
 			if (count >= get->num_services)
@@ -2291,7 +2392,7 @@ __ip_vs_get_service_entries(const struct ip_vs_get_services *get,
 }
 
 static inline int
-__ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
+__ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
 			 struct ip_vs_get_dests __user *uptr)
 {
 	struct ip_vs_service *svc;
@@ -2299,9 +2400,9 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
 	int ret = 0;
 
 	if (get->fwmark)
-		svc = __ip_vs_svc_fwm_find(AF_INET, get->fwmark);
+		svc = __ip_vs_svc_fwm_find(net, AF_INET, get->fwmark);
 	else
-		svc = __ip_vs_service_find(AF_INET, get->protocol, &addr,
+		svc = __ip_vs_service_find(net, AF_INET, get->protocol, &addr,
 					   get->port);
 
 	if (svc) {
@@ -2336,17 +2437,21 @@ __ip_vs_get_dest_entries(const struct ip_vs_get_dests *get,
 }
 
 static inline void
-__ip_vs_get_timeouts(struct ip_vs_timeout_user *u)
+__ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
 {
+#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP)
+	struct ip_vs_proto_data *pd;
+#endif
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
-	u->tcp_timeout =
-		ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
-	u->tcp_fin_timeout =
-		ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_FIN_WAIT] / HZ;
+	pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+	u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
+	u->tcp_fin_timeout = pd->timeout_table[IP_VS_TCP_S_FIN_WAIT] / HZ;
 #endif
 #ifdef CONFIG_IP_VS_PROTO_UDP
+	pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
 	u->udp_timeout =
-		ip_vs_protocol_udp.timeout_table[IP_VS_UDP_S_NORMAL] / HZ;
+			pd->timeout_table[IP_VS_UDP_S_NORMAL] / HZ;
 #endif
 }
 
@@ -2375,7 +2480,10 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 	unsigned char arg[128];
 	int ret = 0;
 	unsigned int copylen;
+	struct net *net = sock_net(sk);
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
+	BUG_ON(!net);
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
@@ -2418,7 +2526,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 		struct ip_vs_getinfo info;
 		info.version = IP_VS_VERSION_CODE;
 		info.size = ip_vs_conn_tab_size;
-		info.num_services = ip_vs_num_services;
+		info.num_services = ipvs->num_services;
 		if (copy_to_user(user, &info, sizeof(info)) != 0)
 			ret = -EFAULT;
 	}
@@ -2437,7 +2545,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 			ret = -EINVAL;
 			goto out;
 		}
-		ret = __ip_vs_get_service_entries(get, user);
+		ret = __ip_vs_get_service_entries(net, get, user);
 	}
 	break;
 
@@ -2450,10 +2558,11 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 		entry = (struct ip_vs_service_entry *)arg;
 		addr.ip = entry->addr;
 		if (entry->fwmark)
-			svc = __ip_vs_svc_fwm_find(AF_INET, entry->fwmark);
+			svc = __ip_vs_svc_fwm_find(net, AF_INET, entry->fwmark);
 		else
-			svc = __ip_vs_service_find(AF_INET, entry->protocol,
-						   &addr, entry->port);
+			svc = __ip_vs_service_find(net, AF_INET,
+						   entry->protocol, &addr,
+						   entry->port);
 		if (svc) {
 			ip_vs_copy_service(entry, svc);
 			if (copy_to_user(user, entry, sizeof(*entry)) != 0)
@@ -2476,7 +2585,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 			ret = -EINVAL;
 			goto out;
 		}
-		ret = __ip_vs_get_dest_entries(get, user);
+		ret = __ip_vs_get_dest_entries(net, get, user);
 	}
 	break;
 
@@ -2484,7 +2593,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 	{
 		struct ip_vs_timeout_user t;
 
-		__ip_vs_get_timeouts(&t);
+		__ip_vs_get_timeouts(net, &t);
 		if (copy_to_user(user, &t, sizeof(t)) != 0)
 			ret = -EFAULT;
 	}
@@ -2495,15 +2604,17 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 		struct ip_vs_daemon_user d[2];
 
 		memset(&d, 0, sizeof(d));
-		if (ip_vs_sync_state & IP_VS_STATE_MASTER) {
+		if (ipvs->sync_state & IP_VS_STATE_MASTER) {
 			d[0].state = IP_VS_STATE_MASTER;
-			strlcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn, sizeof(d[0].mcast_ifn));
-			d[0].syncid = ip_vs_master_syncid;
+			strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,
+				sizeof(d[0].mcast_ifn));
+			d[0].syncid = ipvs->master_syncid;
 		}
-		if (ip_vs_sync_state & IP_VS_STATE_BACKUP) {
+		if (ipvs->sync_state & IP_VS_STATE_BACKUP) {
 			d[1].state = IP_VS_STATE_BACKUP;
-			strlcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn, sizeof(d[1].mcast_ifn));
-			d[1].syncid = ip_vs_backup_syncid;
+			strlcpy(d[1].mcast_ifn, ipvs->backup_mcast_ifn,
+				sizeof(d[1].mcast_ifn));
+			d[1].syncid = ipvs->backup_syncid;
 		}
 		if (copy_to_user(user, &d, sizeof(d)) != 0)
 			ret = -EFAULT;
@@ -2542,6 +2653,7 @@ static struct genl_family ip_vs_genl_family = {
 	.name		= IPVS_GENL_NAME,
 	.version	= IPVS_GENL_VERSION,
 	.maxattr	= IPVS_CMD_MAX,
+	.netnsok        = true,         /* Make ipvsadm to work on netns */
 };
 
 /* Policy used for first-level command attributes */
@@ -2599,31 +2711,29 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = {
 static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
 				 struct ip_vs_stats *stats)
 {
+	struct ip_vs_stats_user ustats;
 	struct nlattr *nl_stats = nla_nest_start(skb, container_type);
 	if (!nl_stats)
 		return -EMSGSIZE;
 
-	spin_lock_bh(&stats->lock);
-
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_CONNS, stats->ustats.conns);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPKTS, stats->ustats.inpkts);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPKTS, stats->ustats.outpkts);
-	NLA_PUT_U64(skb, IPVS_STATS_ATTR_INBYTES, stats->ustats.inbytes);
-	NLA_PUT_U64(skb, IPVS_STATS_ATTR_OUTBYTES, stats->ustats.outbytes);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_CPS, stats->ustats.cps);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPPS, stats->ustats.inpps);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPPS, stats->ustats.outpps);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_INBPS, stats->ustats.inbps);
-	NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTBPS, stats->ustats.outbps);
+	ip_vs_copy_stats(&ustats, stats);
 
-	spin_unlock_bh(&stats->lock);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_CONNS, ustats.conns);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPKTS, ustats.inpkts);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPKTS, ustats.outpkts);
+	NLA_PUT_U64(skb, IPVS_STATS_ATTR_INBYTES, ustats.inbytes);
+	NLA_PUT_U64(skb, IPVS_STATS_ATTR_OUTBYTES, ustats.outbytes);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_CPS, ustats.cps);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_INPPS, ustats.inpps);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTPPS, ustats.outpps);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_INBPS, ustats.inbps);
+	NLA_PUT_U32(skb, IPVS_STATS_ATTR_OUTBPS, ustats.outbps);
 
 	nla_nest_end(skb, nl_stats);
 
 	return 0;
 
 nla_put_failure:
-	spin_unlock_bh(&stats->lock);
 	nla_nest_cancel(skb, nl_stats);
 	return -EMSGSIZE;
 }
@@ -2696,11 +2806,12 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
 	int idx = 0, i;
 	int start = cb->args[0];
 	struct ip_vs_service *svc;
+	struct net *net = skb_sknet(skb);
 
 	mutex_lock(&__ip_vs_mutex);
 	for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) {
 		list_for_each_entry(svc, &ip_vs_svc_table[i], s_list) {
-			if (++idx <= start)
+			if (++idx <= start || !net_eq(svc->net, net))
 				continue;
 			if (ip_vs_genl_dump_service(skb, svc, cb) < 0) {
 				idx--;
@@ -2711,7 +2822,7 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
 
 	for (i = 0; i < IP_VS_SVC_TAB_SIZE; i++) {
 		list_for_each_entry(svc, &ip_vs_svc_fwm_table[i], f_list) {
-			if (++idx <= start)
+			if (++idx <= start || !net_eq(svc->net, net))
 				continue;
 			if (ip_vs_genl_dump_service(skb, svc, cb) < 0) {
 				idx--;
@@ -2727,7 +2838,8 @@ nla_put_failure:
 	return skb->len;
 }
 
-static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
+static int ip_vs_genl_parse_service(struct net *net,
+				    struct ip_vs_service_user_kern *usvc,
 				    struct nlattr *nla, int full_entry,
 				    struct ip_vs_service **ret_svc)
 {
@@ -2770,9 +2882,9 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
 	}
 
 	if (usvc->fwmark)
-		svc = __ip_vs_svc_fwm_find(usvc->af, usvc->fwmark);
+		svc = __ip_vs_svc_fwm_find(net, usvc->af, usvc->fwmark);
 	else
-		svc = __ip_vs_service_find(usvc->af, usvc->protocol,
+		svc = __ip_vs_service_find(net, usvc->af, usvc->protocol,
 					   &usvc->addr, usvc->port);
 	*ret_svc = svc;
 
@@ -2809,13 +2921,14 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
 	return 0;
 }
 
-static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla)
+static struct ip_vs_service *ip_vs_genl_find_service(struct net *net,
+						     struct nlattr *nla)
 {
 	struct ip_vs_service_user_kern usvc;
 	struct ip_vs_service *svc;
 	int ret;
 
-	ret = ip_vs_genl_parse_service(&usvc, nla, 0, &svc);
+	ret = ip_vs_genl_parse_service(net, &usvc, nla, 0, &svc);
 	return ret ? ERR_PTR(ret) : svc;
 }
 
@@ -2883,6 +2996,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
 	struct ip_vs_service *svc;
 	struct ip_vs_dest *dest;
 	struct nlattr *attrs[IPVS_CMD_ATTR_MAX + 1];
+	struct net *net = skb_sknet(skb);
 
 	mutex_lock(&__ip_vs_mutex);
 
@@ -2891,7 +3005,8 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
 			IPVS_CMD_ATTR_MAX, ip_vs_cmd_policy))
 		goto out_err;
 
-	svc = ip_vs_genl_find_service(attrs[IPVS_CMD_ATTR_SERVICE]);
+
+	svc = ip_vs_genl_find_service(net, attrs[IPVS_CMD_ATTR_SERVICE]);
 	if (IS_ERR(svc) || svc == NULL)
 		goto out_err;
 
@@ -3005,20 +3120,23 @@ nla_put_failure:
 static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
 				   struct netlink_callback *cb)
 {
+	struct net *net = skb_net(skb);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
 	mutex_lock(&__ip_vs_mutex);
-	if ((ip_vs_sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {
+	if ((ipvs->sync_state & IP_VS_STATE_MASTER) && !cb->args[0]) {
 		if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_MASTER,
-					   ip_vs_master_mcast_ifn,
-					   ip_vs_master_syncid, cb) < 0)
+					   ipvs->master_mcast_ifn,
+					   ipvs->master_syncid, cb) < 0)
 			goto nla_put_failure;
 
 		cb->args[0] = 1;
 	}
 
-	if ((ip_vs_sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) {
+	if ((ipvs->sync_state & IP_VS_STATE_BACKUP) && !cb->args[1]) {
 		if (ip_vs_genl_dump_daemon(skb, IP_VS_STATE_BACKUP,
-					   ip_vs_backup_mcast_ifn,
-					   ip_vs_backup_syncid, cb) < 0)
+					   ipvs->backup_mcast_ifn,
+					   ipvs->backup_syncid, cb) < 0)
 			goto nla_put_failure;
 
 		cb->args[1] = 1;
@@ -3030,31 +3148,33 @@ nla_put_failure:
 	return skb->len;
 }
 
-static int ip_vs_genl_new_daemon(struct nlattr **attrs)
+static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs)
 {
 	if (!(attrs[IPVS_DAEMON_ATTR_STATE] &&
 	      attrs[IPVS_DAEMON_ATTR_MCAST_IFN] &&
 	      attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
 		return -EINVAL;
 
-	return start_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]),
+	return start_sync_thread(net,
+				 nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]),
 				 nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
 				 nla_get_u32(attrs[IPVS_DAEMON_ATTR_SYNC_ID]));
 }
 
-static int ip_vs_genl_del_daemon(struct nlattr **attrs)
+static int ip_vs_genl_del_daemon(struct net *net, struct nlattr **attrs)
 {
 	if (!attrs[IPVS_DAEMON_ATTR_STATE])
 		return -EINVAL;
 
-	return stop_sync_thread(nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
+	return stop_sync_thread(net,
+				nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]));
 }
 
-static int ip_vs_genl_set_config(struct nlattr **attrs)
+static int ip_vs_genl_set_config(struct net *net, struct nlattr **attrs)
 {
 	struct ip_vs_timeout_user t;
 
-	__ip_vs_get_timeouts(&t);
+	__ip_vs_get_timeouts(net, &t);
 
 	if (attrs[IPVS_CMD_ATTR_TIMEOUT_TCP])
 		t.tcp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_TCP]);
@@ -3066,7 +3186,7 @@ static int ip_vs_genl_set_config(struct nlattr **attrs)
 	if (attrs[IPVS_CMD_ATTR_TIMEOUT_UDP])
 		t.udp_timeout = nla_get_u32(attrs[IPVS_CMD_ATTR_TIMEOUT_UDP]);
 
-	return ip_vs_set_timeout(&t);
+	return ip_vs_set_timeout(net, &t);
 }
 
 static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
@@ -3076,16 +3196,20 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
 	struct ip_vs_dest_user_kern udest;
 	int ret = 0, cmd;
 	int need_full_svc = 0, need_full_dest = 0;
+	struct net *net;
+	struct netns_ipvs *ipvs;
 
+	net = skb_sknet(skb);
+	ipvs = net_ipvs(net);
 	cmd = info->genlhdr->cmd;
 
 	mutex_lock(&__ip_vs_mutex);
 
 	if (cmd == IPVS_CMD_FLUSH) {
-		ret = ip_vs_flush();
+		ret = ip_vs_flush(net);
 		goto out;
 	} else if (cmd == IPVS_CMD_SET_CONFIG) {
-		ret = ip_vs_genl_set_config(info->attrs);
+		ret = ip_vs_genl_set_config(net, info->attrs);
 		goto out;
 	} else if (cmd == IPVS_CMD_NEW_DAEMON ||
 		   cmd == IPVS_CMD_DEL_DAEMON) {
@@ -3101,13 +3225,13 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
 		}
 
 		if (cmd == IPVS_CMD_NEW_DAEMON)
-			ret = ip_vs_genl_new_daemon(daemon_attrs);
+			ret = ip_vs_genl_new_daemon(net, daemon_attrs);
 		else
-			ret = ip_vs_genl_del_daemon(daemon_attrs);
+			ret = ip_vs_genl_del_daemon(net, daemon_attrs);
 		goto out;
 	} else if (cmd == IPVS_CMD_ZERO &&
 		   !info->attrs[IPVS_CMD_ATTR_SERVICE]) {
-		ret = ip_vs_zero_all();
+		ret = ip_vs_zero_all(net);
 		goto out;
 	}
 
@@ -3117,7 +3241,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
 	if (cmd == IPVS_CMD_NEW_SERVICE || cmd == IPVS_CMD_SET_SERVICE)
 		need_full_svc = 1;
 
-	ret = ip_vs_genl_parse_service(&usvc,
+	ret = ip_vs_genl_parse_service(net, &usvc,
 				       info->attrs[IPVS_CMD_ATTR_SERVICE],
 				       need_full_svc, &svc);
 	if (ret)
@@ -3147,7 +3271,7 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
 	switch (cmd) {
 	case IPVS_CMD_NEW_SERVICE:
 		if (svc == NULL)
-			ret = ip_vs_add_service(&usvc, &svc);
+			ret = ip_vs_add_service(net, &usvc, &svc);
 		else
 			ret = -EEXIST;
 		break;
@@ -3185,7 +3309,11 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
 	struct sk_buff *msg;
 	void *reply;
 	int ret, cmd, reply_cmd;
+	struct net *net;
+	struct netns_ipvs *ipvs;
 
+	net = skb_sknet(skb);
+	ipvs = net_ipvs(net);
 	cmd = info->genlhdr->cmd;
 
 	if (cmd == IPVS_CMD_GET_SERVICE)
@@ -3214,7 +3342,8 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
 	{
 		struct ip_vs_service *svc;
 
-		svc = ip_vs_genl_find_service(info->attrs[IPVS_CMD_ATTR_SERVICE]);
+		svc = ip_vs_genl_find_service(net,
+					      info->attrs[IPVS_CMD_ATTR_SERVICE]);
 		if (IS_ERR(svc)) {
 			ret = PTR_ERR(svc);
 			goto out_err;
@@ -3234,7 +3363,7 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
 	{
 		struct ip_vs_timeout_user t;
 
-		__ip_vs_get_timeouts(&t);
+		__ip_vs_get_timeouts(net, &t);
 #ifdef CONFIG_IP_VS_PROTO_TCP
 		NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP, t.tcp_timeout);
 		NLA_PUT_U32(msg, IPVS_CMD_ATTR_TIMEOUT_TCP_FIN,
@@ -3380,62 +3509,189 @@ static void ip_vs_genl_unregister(void)
 
 /* End of Generic Netlink interface definitions */
 
+/*
+ * per netns intit/exit func.
+ */
+#ifdef CONFIG_SYSCTL
+int __net_init __ip_vs_control_init_sysctl(struct net *net)
+{
+	int idx;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ctl_table *tbl;
+
+	atomic_set(&ipvs->dropentry, 0);
+	spin_lock_init(&ipvs->dropentry_lock);
+	spin_lock_init(&ipvs->droppacket_lock);
+	spin_lock_init(&ipvs->securetcp_lock);
+
+	if (!net_eq(net, &init_net)) {
+		tbl = kmemdup(vs_vars, sizeof(vs_vars), GFP_KERNEL);
+		if (tbl == NULL)
+			return -ENOMEM;
+	} else
+		tbl = vs_vars;
+	/* Initialize sysctl defaults */
+	idx = 0;
+	ipvs->sysctl_amemthresh = 1024;
+	tbl[idx++].data = &ipvs->sysctl_amemthresh;
+	ipvs->sysctl_am_droprate = 10;
+	tbl[idx++].data = &ipvs->sysctl_am_droprate;
+	tbl[idx++].data = &ipvs->sysctl_drop_entry;
+	tbl[idx++].data = &ipvs->sysctl_drop_packet;
+#ifdef CONFIG_IP_VS_NFCT
+	tbl[idx++].data = &ipvs->sysctl_conntrack;
+#endif
+	tbl[idx++].data = &ipvs->sysctl_secure_tcp;
+	ipvs->sysctl_snat_reroute = 1;
+	tbl[idx++].data = &ipvs->sysctl_snat_reroute;
+	ipvs->sysctl_sync_ver = 1;
+	tbl[idx++].data = &ipvs->sysctl_sync_ver;
+	tbl[idx++].data = &ipvs->sysctl_cache_bypass;
+	tbl[idx++].data = &ipvs->sysctl_expire_nodest_conn;
+	tbl[idx++].data = &ipvs->sysctl_expire_quiescent_template;
+	ipvs->sysctl_sync_threshold[0] = DEFAULT_SYNC_THRESHOLD;
+	ipvs->sysctl_sync_threshold[1] = DEFAULT_SYNC_PERIOD;
+	tbl[idx].data = &ipvs->sysctl_sync_threshold;
+	tbl[idx++].maxlen = sizeof(ipvs->sysctl_sync_threshold);
+	tbl[idx++].data = &ipvs->sysctl_nat_icmp_send;
+
+
+	ipvs->sysctl_hdr = register_net_sysctl_table(net, net_vs_ctl_path,
+						     tbl);
+	if (ipvs->sysctl_hdr == NULL) {
+		if (!net_eq(net, &init_net))
+			kfree(tbl);
+		return -ENOMEM;
+	}
+	ip_vs_start_estimator(net, &ipvs->tot_stats);
+	ipvs->sysctl_tbl = tbl;
+	/* Schedule defense work */
+	INIT_DELAYED_WORK(&ipvs->defense_work, defense_work_handler);
+	schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD);
+
+	return 0;
+}
+
+void __net_init __ip_vs_control_cleanup_sysctl(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	cancel_delayed_work_sync(&ipvs->defense_work);
+	cancel_work_sync(&ipvs->defense_work.work);
+	unregister_net_sysctl_table(ipvs->sysctl_hdr);
+}
+
+#else
+
+int __net_init __ip_vs_control_init_sysctl(struct net *net) { return 0; }
+void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { }
+
+#endif
+
+int __net_init __ip_vs_control_init(struct net *net)
+{
+	int idx;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	ipvs->rs_lock = __RW_LOCK_UNLOCKED(ipvs->rs_lock);
+
+	/* Initialize rs_table */
+	for (idx = 0; idx < IP_VS_RTAB_SIZE; idx++)
+		INIT_LIST_HEAD(&ipvs->rs_table[idx]);
+
+	INIT_LIST_HEAD(&ipvs->dest_trash);
+	atomic_set(&ipvs->ftpsvc_counter, 0);
+	atomic_set(&ipvs->nullsvc_counter, 0);
+
+	/* procfs stats */
+	ipvs->tot_stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats);
+	if (!ipvs->tot_stats.cpustats) {
+		pr_err("%s(): alloc_percpu.\n", __func__);
+		return -ENOMEM;
+	}
+	spin_lock_init(&ipvs->tot_stats.lock);
+
+	proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops);
+	proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops);
+	proc_net_fops_create(net, "ip_vs_stats_percpu", 0,
+			     &ip_vs_stats_percpu_fops);
+
+	if (__ip_vs_control_init_sysctl(net))
+		goto err;
+
+	return 0;
+
+err:
+	free_percpu(ipvs->tot_stats.cpustats);
+	return -ENOMEM;
+}
+
+static void __net_exit __ip_vs_control_cleanup(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	ip_vs_trash_cleanup(net);
+	ip_vs_stop_estimator(net, &ipvs->tot_stats);
+	__ip_vs_control_cleanup_sysctl(net);
+	proc_net_remove(net, "ip_vs_stats_percpu");
+	proc_net_remove(net, "ip_vs_stats");
+	proc_net_remove(net, "ip_vs");
+	free_percpu(ipvs->tot_stats.cpustats);
+}
+
+static struct pernet_operations ipvs_control_ops = {
+	.init = __ip_vs_control_init,
+	.exit = __ip_vs_control_cleanup,
+};
 
 int __init ip_vs_control_init(void)
 {
-	int ret;
 	int idx;
+	int ret;
 
 	EnterFunction(2);
 
-	/* Initialize ip_vs_svc_table, ip_vs_svc_fwm_table, ip_vs_rtable */
+	/* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
 	for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++)  {
 		INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
 		INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
 	}
-	for(idx = 0; idx < IP_VS_RTAB_SIZE; idx++)  {
-		INIT_LIST_HEAD(&ip_vs_rtable[idx]);
+
+	ret = register_pernet_subsys(&ipvs_control_ops);
+	if (ret) {
+		pr_err("cannot register namespace.\n");
+		goto err;
 	}
-	smp_wmb();
+
+	smp_wmb();	/* Do we really need it now ? */
 
 	ret = nf_register_sockopt(&ip_vs_sockopts);
 	if (ret) {
 		pr_err("cannot register sockopt.\n");
-		return ret;
+		goto err_net;
 	}
 
 	ret = ip_vs_genl_register();
 	if (ret) {
 		pr_err("cannot register Generic Netlink interface.\n");
 		nf_unregister_sockopt(&ip_vs_sockopts);
-		return ret;
+		goto err_net;
 	}
 
-	proc_net_fops_create(&init_net, "ip_vs", 0, &ip_vs_info_fops);
-	proc_net_fops_create(&init_net, "ip_vs_stats",0, &ip_vs_stats_fops);
-
-	sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars);
-
-	ip_vs_new_estimator(&ip_vs_stats);
-
-	/* Hook the defense timer */
-	schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
-
 	LeaveFunction(2);
 	return 0;
+
+err_net:
+	unregister_pernet_subsys(&ipvs_control_ops);
+err:
+	return ret;
 }
 
 
 void ip_vs_control_cleanup(void)
 {
 	EnterFunction(2);
-	ip_vs_trash_cleanup();
-	cancel_delayed_work_sync(&defense_work);
-	cancel_work_sync(&defense_work.work);
-	ip_vs_kill_estimator(&ip_vs_stats);
-	unregister_sysctl_table(sysctl_header);
-	proc_net_remove(&init_net, "ip_vs_stats");
-	proc_net_remove(&init_net, "ip_vs");
+	unregister_pernet_subsys(&ipvs_control_ops);
 	ip_vs_genl_unregister();
 	nf_unregister_sockopt(&ip_vs_sockopts);
 	LeaveFunction(2);
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c
index ff28801..8c8766c 100644
--- a/net/netfilter/ipvs/ip_vs_est.c
+++ b/net/netfilter/ipvs/ip_vs_est.c
@@ -8,8 +8,12 @@
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Changes:
- *
+ * Changes:     Hans Schillstrom <hans.schillstrom@ericsson.com>
+ *              Network name space (netns) aware.
+ *              Global data moved to netns i.e struct netns_ipvs
+ *              Affected data: est_list and est_lock.
+ *              estimation_timer() runs with timer per netns.
+ *              get_stats()) do the per cpu summing.
  */
 
 #define KMSG_COMPONENT "IPVS"
@@ -48,11 +52,42 @@
  */
 
 
-static void estimation_timer(unsigned long arg);
+/*
+ * 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)
+{
+	int i;
+
+	for_each_possible_cpu(i) {
+		struct ip_vs_cpu_stats *s = per_cpu_ptr(stats, i);
+		unsigned int start;
+		__u64 inbytes, outbytes;
+		if (i) {
+			sum->conns += s->ustats.conns;
+			sum->inpkts += s->ustats.inpkts;
+			sum->outpkts += s->ustats.outpkts;
+			do {
+				start = u64_stats_fetch_begin(&s->syncp);
+				inbytes = s->ustats.inbytes;
+				outbytes = s->ustats.outbytes;
+			} while (u64_stats_fetch_retry(&s->syncp, start));
+			sum->inbytes += inbytes;
+			sum->outbytes += outbytes;
+		} else {
+			sum->conns = s->ustats.conns;
+			sum->inpkts = s->ustats.inpkts;
+			sum->outpkts = s->ustats.outpkts;
+			do {
+				start = u64_stats_fetch_begin(&s->syncp);
+				sum->inbytes = s->ustats.inbytes;
+				sum->outbytes = s->ustats.outbytes;
+			} while (u64_stats_fetch_retry(&s->syncp, start));
+		}
+	}
+}
 
-static LIST_HEAD(est_list);
-static DEFINE_SPINLOCK(est_lock);
-static DEFINE_TIMER(est_timer, estimation_timer, 0, 0);
 
 static void estimation_timer(unsigned long arg)
 {
@@ -62,12 +97,16 @@ static void estimation_timer(unsigned long arg)
 	u32 n_inpkts, n_outpkts;
 	u64 n_inbytes, n_outbytes;
 	u32 rate;
+	struct net *net = (struct net *)arg;
+	struct netns_ipvs *ipvs;
 
-	spin_lock(&est_lock);
-	list_for_each_entry(e, &est_list, list) {
+	ipvs = net_ipvs(net);
+	spin_lock(&ipvs->est_lock);
+	list_for_each_entry(e, &ipvs->est_list, list) {
 		s = container_of(e, struct ip_vs_stats, est);
 
 		spin_lock(&s->lock);
+		ip_vs_read_cpu_stats(&s->ustats, s->cpustats);
 		n_conns = s->ustats.conns;
 		n_inpkts = s->ustats.inpkts;
 		n_outpkts = s->ustats.outpkts;
@@ -75,81 +114,64 @@ static void estimation_timer(unsigned long arg)
 		n_outbytes = s->ustats.outbytes;
 
 		/* scaled by 2^10, but divided 2 seconds */
-		rate = (n_conns - e->last_conns)<<9;
+		rate = (n_conns - e->last_conns) << 9;
 		e->last_conns = n_conns;
-		e->cps += ((long)rate - (long)e->cps)>>2;
-		s->ustats.cps = (e->cps+0x1FF)>>10;
+		e->cps += ((long)rate - (long)e->cps) >> 2;
 
-		rate = (n_inpkts - e->last_inpkts)<<9;
+		rate = (n_inpkts - e->last_inpkts) << 9;
 		e->last_inpkts = n_inpkts;
-		e->inpps += ((long)rate - (long)e->inpps)>>2;
-		s->ustats.inpps = (e->inpps+0x1FF)>>10;
+		e->inpps += ((long)rate - (long)e->inpps) >> 2;
 
-		rate = (n_outpkts - e->last_outpkts)<<9;
+		rate = (n_outpkts - e->last_outpkts) << 9;
 		e->last_outpkts = n_outpkts;
-		e->outpps += ((long)rate - (long)e->outpps)>>2;
-		s->ustats.outpps = (e->outpps+0x1FF)>>10;
+		e->outpps += ((long)rate - (long)e->outpps) >> 2;
 
-		rate = (n_inbytes - e->last_inbytes)<<4;
+		rate = (n_inbytes - e->last_inbytes) << 4;
 		e->last_inbytes = n_inbytes;
-		e->inbps += ((long)rate - (long)e->inbps)>>2;
-		s->ustats.inbps = (e->inbps+0xF)>>5;
+		e->inbps += ((long)rate - (long)e->inbps) >> 2;
 
-		rate = (n_outbytes - e->last_outbytes)<<4;
+		rate = (n_outbytes - e->last_outbytes) << 4;
 		e->last_outbytes = n_outbytes;
-		e->outbps += ((long)rate - (long)e->outbps)>>2;
-		s->ustats.outbps = (e->outbps+0xF)>>5;
+		e->outbps += ((long)rate - (long)e->outbps) >> 2;
 		spin_unlock(&s->lock);
 	}
-	spin_unlock(&est_lock);
-	mod_timer(&est_timer, jiffies + 2*HZ);
+	spin_unlock(&ipvs->est_lock);
+	mod_timer(&ipvs->est_timer, jiffies + 2*HZ);
 }
 
-void ip_vs_new_estimator(struct ip_vs_stats *stats)
+void ip_vs_start_estimator(struct net *net, struct ip_vs_stats *stats)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	struct ip_vs_estimator *est = &stats->est;
 
 	INIT_LIST_HEAD(&est->list);
 
-	est->last_conns = stats->ustats.conns;
-	est->cps = stats->ustats.cps<<10;
-
-	est->last_inpkts = stats->ustats.inpkts;
-	est->inpps = stats->ustats.inpps<<10;
-
-	est->last_outpkts = stats->ustats.outpkts;
-	est->outpps = stats->ustats.outpps<<10;
-
-	est->last_inbytes = stats->ustats.inbytes;
-	est->inbps = stats->ustats.inbps<<5;
-
-	est->last_outbytes = stats->ustats.outbytes;
-	est->outbps = stats->ustats.outbps<<5;
-
-	spin_lock_bh(&est_lock);
-	list_add(&est->list, &est_list);
-	spin_unlock_bh(&est_lock);
+	spin_lock_bh(&ipvs->est_lock);
+	list_add(&est->list, &ipvs->est_list);
+	spin_unlock_bh(&ipvs->est_lock);
 }
 
-void ip_vs_kill_estimator(struct ip_vs_stats *stats)
+void ip_vs_stop_estimator(struct net *net, struct ip_vs_stats *stats)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	struct ip_vs_estimator *est = &stats->est;
 
-	spin_lock_bh(&est_lock);
+	spin_lock_bh(&ipvs->est_lock);
 	list_del(&est->list);
-	spin_unlock_bh(&est_lock);
+	spin_unlock_bh(&ipvs->est_lock);
 }
 
 void ip_vs_zero_estimator(struct ip_vs_stats *stats)
 {
 	struct ip_vs_estimator *est = &stats->est;
-
-	/* set counters zero, caller must hold the stats->lock lock */
-	est->last_inbytes = 0;
-	est->last_outbytes = 0;
-	est->last_conns = 0;
-	est->last_inpkts = 0;
-	est->last_outpkts = 0;
+	struct ip_vs_stats_user *u = &stats->ustats;
+
+	/* reset counters, caller must hold the stats->lock lock */
+	est->last_inbytes = u->inbytes;
+	est->last_outbytes = u->outbytes;
+	est->last_conns = u->conns;
+	est->last_inpkts = u->inpkts;
+	est->last_outpkts = u->outpkts;
 	est->cps = 0;
 	est->inpps = 0;
 	est->outpps = 0;
@@ -157,13 +179,48 @@ void ip_vs_zero_estimator(struct ip_vs_stats *stats)
 	est->outbps = 0;
 }
 
-int __init ip_vs_estimator_init(void)
+/* Get decoded rates */
+void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
+			  struct ip_vs_stats *stats)
 {
-	mod_timer(&est_timer, jiffies + 2 * HZ);
+	struct ip_vs_estimator *e = &stats->est;
+
+	dst->cps = (e->cps + 0x1FF) >> 10;
+	dst->inpps = (e->inpps + 0x1FF) >> 10;
+	dst->outpps = (e->outpps + 0x1FF) >> 10;
+	dst->inbps = (e->inbps + 0xF) >> 5;
+	dst->outbps = (e->outbps + 0xF) >> 5;
+}
+
+static int __net_init __ip_vs_estimator_init(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	INIT_LIST_HEAD(&ipvs->est_list);
+	spin_lock_init(&ipvs->est_lock);
+	setup_timer(&ipvs->est_timer, estimation_timer, (unsigned long)net);
+	mod_timer(&ipvs->est_timer, jiffies + 2 * HZ);
 	return 0;
 }
 
+static void __net_exit __ip_vs_estimator_exit(struct net *net)
+{
+	del_timer_sync(&net_ipvs(net)->est_timer);
+}
+static struct pernet_operations ip_vs_app_ops = {
+	.init = __ip_vs_estimator_init,
+	.exit = __ip_vs_estimator_exit,
+};
+
+int __init ip_vs_estimator_init(void)
+{
+	int rv;
+
+	rv = register_pernet_subsys(&ip_vs_app_ops);
+	return rv;
+}
+
 void ip_vs_estimator_cleanup(void)
 {
-	del_timer_sync(&est_timer);
+	unregister_pernet_subsys(&ip_vs_app_ops);
 }
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 7545500..6b5dd6d 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -157,6 +157,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
 	int ret = 0;
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn *ct;
+	struct net *net;
 
 #ifdef CONFIG_IP_VS_IPV6
 	/* This application helper doesn't work with IPv6 yet,
@@ -197,18 +198,20 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
 		 */
 		{
 			struct ip_vs_conn_param p;
-			ip_vs_conn_fill_param(AF_INET, iph->protocol,
-					      &from, port, &cp->caddr, 0, &p);
+			ip_vs_conn_fill_param(ip_vs_conn_net(cp), AF_INET,
+					      iph->protocol, &from, port,
+					      &cp->caddr, 0, &p);
 			n_cp = ip_vs_conn_out_get(&p);
 		}
 		if (!n_cp) {
 			struct ip_vs_conn_param p;
-			ip_vs_conn_fill_param(AF_INET, IPPROTO_TCP, &cp->caddr,
+			ip_vs_conn_fill_param(ip_vs_conn_net(cp),
+					      AF_INET, IPPROTO_TCP, &cp->caddr,
 					      0, &cp->vaddr, port, &p);
 			n_cp = ip_vs_conn_new(&p, &from, port,
 					      IP_VS_CONN_F_NO_CPORT |
 					      IP_VS_CONN_F_NFCT,
-					      cp->dest);
+					      cp->dest, skb->mark);
 			if (!n_cp)
 				return 0;
 
@@ -257,8 +260,9 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
 		 * would be adjusted twice.
 		 */
 
+		net = skb_net(skb);
 		cp->app_data = NULL;
-		ip_vs_tcp_conn_listen(n_cp);
+		ip_vs_tcp_conn_listen(net, n_cp);
 		ip_vs_conn_put(n_cp);
 		return ret;
 	}
@@ -287,6 +291,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
 	union nf_inet_addr to;
 	__be16 port;
 	struct ip_vs_conn *n_cp;
+	struct net *net;
 
 #ifdef CONFIG_IP_VS_IPV6
 	/* This application helper doesn't work with IPv6 yet,
@@ -358,14 +363,15 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
 
 	{
 		struct ip_vs_conn_param p;
-		ip_vs_conn_fill_param(AF_INET, iph->protocol, &to, port,
-				      &cp->vaddr, htons(ntohs(cp->vport)-1),
-				      &p);
+		ip_vs_conn_fill_param(ip_vs_conn_net(cp), AF_INET,
+				      iph->protocol, &to, port, &cp->vaddr,
+				      htons(ntohs(cp->vport)-1), &p);
 		n_cp = ip_vs_conn_in_get(&p);
 		if (!n_cp) {
 			n_cp = ip_vs_conn_new(&p, &cp->daddr,
 					      htons(ntohs(cp->dport)-1),
-					      IP_VS_CONN_F_NFCT, cp->dest);
+					      IP_VS_CONN_F_NFCT, cp->dest,
+					      skb->mark);
 			if (!n_cp)
 				return 0;
 
@@ -377,7 +383,8 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
 	/*
 	 *	Move tunnel to listen state
 	 */
-	ip_vs_tcp_conn_listen(n_cp);
+	net = skb_net(skb);
+	ip_vs_tcp_conn_listen(net, n_cp);
 	ip_vs_conn_put(n_cp);
 
 	return 1;
@@ -398,23 +405,22 @@ static struct ip_vs_app ip_vs_ftp = {
 	.pkt_in =	ip_vs_ftp_in,
 };
 
-
 /*
- *	ip_vs_ftp initialization
+ *	per netns ip_vs_ftp initialization
  */
-static int __init ip_vs_ftp_init(void)
+static int __net_init __ip_vs_ftp_init(struct net *net)
 {
 	int i, ret;
 	struct ip_vs_app *app = &ip_vs_ftp;
 
-	ret = register_ip_vs_app(app);
+	ret = register_ip_vs_app(net, app);
 	if (ret)
 		return ret;
 
 	for (i=0; i<IP_VS_APP_MAX_PORTS; i++) {
 		if (!ports[i])
 			continue;
-		ret = register_ip_vs_app_inc(app, app->protocol, ports[i]);
+		ret = register_ip_vs_app_inc(net, app, app->protocol, ports[i]);
 		if (ret)
 			break;
 		pr_info("%s: loaded support on port[%d] = %d\n",
@@ -422,18 +428,39 @@ static int __init ip_vs_ftp_init(void)
 	}
 
 	if (ret)
-		unregister_ip_vs_app(app);
+		unregister_ip_vs_app(net, app);
 
 	return ret;
 }
+/*
+ *	netns exit
+ */
+static void __ip_vs_ftp_exit(struct net *net)
+{
+	struct ip_vs_app *app = &ip_vs_ftp;
+
+	unregister_ip_vs_app(net, app);
+}
+
+static struct pernet_operations ip_vs_ftp_ops = {
+	.init = __ip_vs_ftp_init,
+	.exit = __ip_vs_ftp_exit,
+};
 
+int __init ip_vs_ftp_init(void)
+{
+	int rv;
+
+	rv = register_pernet_subsys(&ip_vs_ftp_ops);
+	return rv;
+}
 
 /*
  *	ip_vs_ftp finish.
  */
 static void __exit ip_vs_ftp_exit(void)
 {
-	unregister_ip_vs_app(&ip_vs_ftp);
+	unregister_pernet_subsys(&ip_vs_ftp_ops);
 }
 
 
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 9323f89..f276df9 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -63,6 +63,8 @@
 #define CHECK_EXPIRE_INTERVAL   (60*HZ)
 #define ENTRY_TIMEOUT           (6*60*HZ)
 
+#define DEFAULT_EXPIRATION	(24*60*60*HZ)
+
 /*
  *    It is for full expiration check.
  *    When there is no partial expiration check (garbage collection)
@@ -70,7 +72,6 @@
  *    entries that haven't been touched for a day.
  */
 #define COUNT_FOR_FULL_EXPIRATION   30
-static int sysctl_ip_vs_lblc_expiration = 24*60*60*HZ;
 
 
 /*
@@ -113,19 +114,18 @@ struct ip_vs_lblc_table {
 /*
  *      IPVS LBLC sysctl table
  */
-
+#ifdef CONFIG_SYSCTL
 static ctl_table vs_vars_table[] = {
 	{
 		.procname	= "lblc_expiration",
-		.data		= &sysctl_ip_vs_lblc_expiration,
+		.data		= NULL,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{ }
 };
-
-static struct ctl_table_header * sysctl_header;
+#endif
 
 static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en)
 {
@@ -241,6 +241,15 @@ static void ip_vs_lblc_flush(struct ip_vs_lblc_table *tbl)
 	}
 }
 
+static int sysctl_lblc_expiration(struct ip_vs_service *svc)
+{
+#ifdef CONFIG_SYSCTL
+	struct netns_ipvs *ipvs = net_ipvs(svc->net);
+	return ipvs->sysctl_lblc_expiration;
+#else
+	return DEFAULT_EXPIRATION;
+#endif
+}
 
 static inline void ip_vs_lblc_full_check(struct ip_vs_service *svc)
 {
@@ -255,7 +264,8 @@ static inline void ip_vs_lblc_full_check(struct ip_vs_service *svc)
 		write_lock(&svc->sched_lock);
 		list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) {
 			if (time_before(now,
-					en->lastuse + sysctl_ip_vs_lblc_expiration))
+					en->lastuse +
+					sysctl_lblc_expiration(svc)))
 				continue;
 
 			ip_vs_lblc_free(en);
@@ -390,12 +400,7 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
 	int loh, doh;
 
 	/*
-	 * We think the overhead of processing active connections is fifty
-	 * times higher than that of inactive connections in average. (This
-	 * fifty times might not be accurate, we will change it later.) We
-	 * use the following formula to estimate the overhead:
-	 *                dest->activeconns*50 + dest->inactconns
-	 * and the load:
+	 * We use the following formula to estimate the load:
 	 *                (dest overhead) / dest->weight
 	 *
 	 * Remember -- no floats in kernel mode!!!
@@ -411,8 +416,7 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
 			continue;
 		if (atomic_read(&dest->weight) > 0) {
 			least = dest;
-			loh = atomic_read(&least->activeconns) * 50
-				+ atomic_read(&least->inactconns);
+			loh = ip_vs_dest_conn_overhead(least);
 			goto nextstage;
 		}
 	}
@@ -426,8 +430,7 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
 		if (dest->flags & IP_VS_DEST_F_OVERLOAD)
 			continue;
 
-		doh = atomic_read(&dest->activeconns) * 50
-			+ atomic_read(&dest->inactconns);
+		doh = ip_vs_dest_conn_overhead(dest);
 		if (loh * atomic_read(&dest->weight) >
 		    doh * atomic_read(&least->weight)) {
 			least = dest;
@@ -511,7 +514,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	/* No cache entry or it is invalid, time to schedule */
 	dest = __ip_vs_lblc_schedule(svc);
 	if (!dest) {
-		IP_VS_ERR_RL("LBLC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
@@ -543,23 +546,77 @@ static struct ip_vs_scheduler ip_vs_lblc_scheduler =
 	.schedule =		ip_vs_lblc_schedule,
 };
 
+/*
+ *  per netns init.
+ */
+#ifdef CONFIG_SYSCTL
+static int __net_init __ip_vs_lblc_init(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	if (!net_eq(net, &init_net)) {
+		ipvs->lblc_ctl_table = kmemdup(vs_vars_table,
+						sizeof(vs_vars_table),
+						GFP_KERNEL);
+		if (ipvs->lblc_ctl_table == NULL)
+			return -ENOMEM;
+	} else
+		ipvs->lblc_ctl_table = vs_vars_table;
+	ipvs->sysctl_lblc_expiration = DEFAULT_EXPIRATION;
+	ipvs->lblc_ctl_table[0].data = &ipvs->sysctl_lblc_expiration;
+
+	ipvs->lblc_ctl_header =
+		register_net_sysctl_table(net, net_vs_ctl_path,
+					  ipvs->lblc_ctl_table);
+	if (!ipvs->lblc_ctl_header) {
+		if (!net_eq(net, &init_net))
+			kfree(ipvs->lblc_ctl_table);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void __net_exit __ip_vs_lblc_exit(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	unregister_net_sysctl_table(ipvs->lblc_ctl_header);
+
+	if (!net_eq(net, &init_net))
+		kfree(ipvs->lblc_ctl_table);
+}
+
+#else
+
+static int __net_init __ip_vs_lblc_init(struct net *net) { return 0; }
+static void __net_exit __ip_vs_lblc_exit(struct net *net) { }
+
+#endif
+
+static struct pernet_operations ip_vs_lblc_ops = {
+	.init = __ip_vs_lblc_init,
+	.exit = __ip_vs_lblc_exit,
+};
 
 static int __init ip_vs_lblc_init(void)
 {
 	int ret;
 
-	sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table);
+	ret = register_pernet_subsys(&ip_vs_lblc_ops);
+	if (ret)
+		return ret;
+
 	ret = register_ip_vs_scheduler(&ip_vs_lblc_scheduler);
 	if (ret)
-		unregister_sysctl_table(sysctl_header);
+		unregister_pernet_subsys(&ip_vs_lblc_ops);
 	return ret;
 }
 
-
 static void __exit ip_vs_lblc_cleanup(void)
 {
-	unregister_sysctl_table(sysctl_header);
 	unregister_ip_vs_scheduler(&ip_vs_lblc_scheduler);
+	unregister_pernet_subsys(&ip_vs_lblc_ops);
 }
 
 
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index dbeed8e..cb1c991 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -63,6 +63,8 @@
 #define CHECK_EXPIRE_INTERVAL   (60*HZ)
 #define ENTRY_TIMEOUT           (6*60*HZ)
 
+#define DEFAULT_EXPIRATION	(24*60*60*HZ)
+
 /*
  *    It is for full expiration check.
  *    When there is no partial expiration check (garbage collection)
@@ -70,8 +72,6 @@
  *    entries that haven't been touched for a day.
  */
 #define COUNT_FOR_FULL_EXPIRATION   30
-static int sysctl_ip_vs_lblcr_expiration = 24*60*60*HZ;
-
 
 /*
  *     for IPVS lblcr entry hash table
@@ -180,8 +180,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
 
 		if ((atomic_read(&least->weight) > 0)
 		    && (least->flags & IP_VS_DEST_F_AVAILABLE)) {
-			loh = atomic_read(&least->activeconns) * 50
-				+ atomic_read(&least->inactconns);
+			loh = ip_vs_dest_conn_overhead(least);
 			goto nextstage;
 		}
 	}
@@ -194,8 +193,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
 		if (dest->flags & IP_VS_DEST_F_OVERLOAD)
 			continue;
 
-		doh = atomic_read(&dest->activeconns) * 50
-			+ atomic_read(&dest->inactconns);
+		doh = ip_vs_dest_conn_overhead(dest);
 		if ((loh * atomic_read(&dest->weight) >
 		     doh * atomic_read(&least->weight))
 		    && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
@@ -230,8 +228,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
 	list_for_each_entry(e, &set->list, list) {
 		most = e->dest;
 		if (atomic_read(&most->weight) > 0) {
-			moh = atomic_read(&most->activeconns) * 50
-				+ atomic_read(&most->inactconns);
+			moh = ip_vs_dest_conn_overhead(most);
 			goto nextstage;
 		}
 	}
@@ -241,8 +238,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
   nextstage:
 	list_for_each_entry(e, &set->list, list) {
 		dest = e->dest;
-		doh = atomic_read(&dest->activeconns) * 50
-			+ atomic_read(&dest->inactconns);
+		doh = ip_vs_dest_conn_overhead(dest);
 		/* moh/mw < doh/dw ==> moh*dw < doh*mw, where mw,dw>0 */
 		if ((moh * atomic_read(&dest->weight) <
 		     doh * atomic_read(&most->weight))
@@ -289,6 +285,7 @@ struct ip_vs_lblcr_table {
 };
 
 
+#ifdef CONFIG_SYSCTL
 /*
  *      IPVS LBLCR sysctl table
  */
@@ -296,15 +293,14 @@ struct ip_vs_lblcr_table {
 static ctl_table vs_vars_table[] = {
 	{
 		.procname	= "lblcr_expiration",
-		.data		= &sysctl_ip_vs_lblcr_expiration,
+		.data		= NULL,
 		.maxlen		= sizeof(int),
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec_jiffies,
 	},
 	{ }
 };
-
-static struct ctl_table_header * sysctl_header;
+#endif
 
 static inline void ip_vs_lblcr_free(struct ip_vs_lblcr_entry *en)
 {
@@ -418,6 +414,15 @@ static void ip_vs_lblcr_flush(struct ip_vs_lblcr_table *tbl)
 	}
 }
 
+static int sysctl_lblcr_expiration(struct ip_vs_service *svc)
+{
+#ifdef CONFIG_SYSCTL
+	struct netns_ipvs *ipvs = net_ipvs(svc->net);
+	return ipvs->sysctl_lblcr_expiration;
+#else
+	return DEFAULT_EXPIRATION;
+#endif
+}
 
 static inline void ip_vs_lblcr_full_check(struct ip_vs_service *svc)
 {
@@ -431,8 +436,8 @@ static inline void ip_vs_lblcr_full_check(struct ip_vs_service *svc)
 
 		write_lock(&svc->sched_lock);
 		list_for_each_entry_safe(en, nxt, &tbl->bucket[j], list) {
-			if (time_after(en->lastuse+sysctl_ip_vs_lblcr_expiration,
-				       now))
+			if (time_after(en->lastuse +
+				       sysctl_lblcr_expiration(svc), now))
 				continue;
 
 			ip_vs_lblcr_free(en);
@@ -566,12 +571,7 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
 	int loh, doh;
 
 	/*
-	 * We think the overhead of processing active connections is fifty
-	 * times higher than that of inactive connections in average. (This
-	 * fifty times might not be accurate, we will change it later.) We
-	 * use the following formula to estimate the overhead:
-	 *                dest->activeconns*50 + dest->inactconns
-	 * and the load:
+	 * We use the following formula to estimate the load:
 	 *                (dest overhead) / dest->weight
 	 *
 	 * Remember -- no floats in kernel mode!!!
@@ -588,8 +588,7 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
 
 		if (atomic_read(&dest->weight) > 0) {
 			least = dest;
-			loh = atomic_read(&least->activeconns) * 50
-				+ atomic_read(&least->inactconns);
+			loh = ip_vs_dest_conn_overhead(least);
 			goto nextstage;
 		}
 	}
@@ -603,8 +602,7 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
 		if (dest->flags & IP_VS_DEST_F_OVERLOAD)
 			continue;
 
-		doh = atomic_read(&dest->activeconns) * 50
-			+ atomic_read(&dest->inactconns);
+		doh = ip_vs_dest_conn_overhead(dest);
 		if (loh * atomic_read(&dest->weight) >
 		    doh * atomic_read(&least->weight)) {
 			least = dest;
@@ -675,7 +673,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		/* More than one destination + enough time passed by, cleanup */
 		if (atomic_read(&en->set.size) > 1 &&
 				time_after(jiffies, en->set.lastmod +
-				sysctl_ip_vs_lblcr_expiration)) {
+				sysctl_lblcr_expiration(svc))) {
 			struct ip_vs_dest *m;
 
 			write_lock(&en->set.lock);
@@ -694,7 +692,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		/* The cache entry is invalid, time to schedule */
 		dest = __ip_vs_lblcr_schedule(svc);
 		if (!dest) {
-			IP_VS_ERR_RL("LBLCR: no destination available\n");
+			ip_vs_scheduler_err(svc, "no destination available");
 			read_unlock(&svc->sched_lock);
 			return NULL;
 		}
@@ -744,23 +742,77 @@ static struct ip_vs_scheduler ip_vs_lblcr_scheduler =
 	.schedule =		ip_vs_lblcr_schedule,
 };
 
+/*
+ *  per netns init.
+ */
+#ifdef CONFIG_SYSCTL
+static int __net_init __ip_vs_lblcr_init(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	if (!net_eq(net, &init_net)) {
+		ipvs->lblcr_ctl_table = kmemdup(vs_vars_table,
+						sizeof(vs_vars_table),
+						GFP_KERNEL);
+		if (ipvs->lblcr_ctl_table == NULL)
+			return -ENOMEM;
+	} else
+		ipvs->lblcr_ctl_table = vs_vars_table;
+	ipvs->sysctl_lblcr_expiration = DEFAULT_EXPIRATION;
+	ipvs->lblcr_ctl_table[0].data = &ipvs->sysctl_lblcr_expiration;
+
+	ipvs->lblcr_ctl_header =
+		register_net_sysctl_table(net, net_vs_ctl_path,
+					  ipvs->lblcr_ctl_table);
+	if (!ipvs->lblcr_ctl_header) {
+		if (!net_eq(net, &init_net))
+			kfree(ipvs->lblcr_ctl_table);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void __net_exit __ip_vs_lblcr_exit(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	unregister_net_sysctl_table(ipvs->lblcr_ctl_header);
+
+	if (!net_eq(net, &init_net))
+		kfree(ipvs->lblcr_ctl_table);
+}
+
+#else
+
+static int __net_init __ip_vs_lblcr_init(struct net *net) { return 0; }
+static void __net_exit __ip_vs_lblcr_exit(struct net *net) { }
+
+#endif
+
+static struct pernet_operations ip_vs_lblcr_ops = {
+	.init = __ip_vs_lblcr_init,
+	.exit = __ip_vs_lblcr_exit,
+};
 
 static int __init ip_vs_lblcr_init(void)
 {
 	int ret;
 
-	sysctl_header = register_sysctl_paths(net_vs_ctl_path, vs_vars_table);
+	ret = register_pernet_subsys(&ip_vs_lblcr_ops);
+	if (ret)
+		return ret;
+
 	ret = register_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
 	if (ret)
-		unregister_sysctl_table(sysctl_header);
+		unregister_pernet_subsys(&ip_vs_lblcr_ops);
 	return ret;
 }
 
-
 static void __exit ip_vs_lblcr_cleanup(void)
 {
-	unregister_sysctl_table(sysctl_header);
 	unregister_ip_vs_scheduler(&ip_vs_lblcr_scheduler);
+	unregister_pernet_subsys(&ip_vs_lblcr_ops);
 }
 
 
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
index 4f69db1..f391819 100644
--- a/net/netfilter/ipvs/ip_vs_lc.c
+++ b/net/netfilter/ipvs/ip_vs_lc.c
@@ -22,22 +22,6 @@
 
 #include <net/ip_vs.h>
 
-
-static inline unsigned int
-ip_vs_lc_dest_overhead(struct ip_vs_dest *dest)
-{
-	/*
-	 * We think the overhead of processing active connections is 256
-	 * times higher than that of inactive connections in average. (This
-	 * 256 times might not be accurate, we will change it later) We
-	 * use the following formula to estimate the overhead now:
-	 *		  dest->activeconns*256 + dest->inactconns
-	 */
-	return (atomic_read(&dest->activeconns) << 8) +
-		atomic_read(&dest->inactconns);
-}
-
-
 /*
  *	Least Connection scheduling
  */
@@ -62,7 +46,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
 		    atomic_read(&dest->weight) == 0)
 			continue;
-		doh = ip_vs_lc_dest_overhead(dest);
+		doh = ip_vs_dest_conn_overhead(dest);
 		if (!least || doh < loh) {
 			least = dest;
 			loh = doh;
@@ -70,7 +54,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	}
 
 	if (!least)
-		IP_VS_ERR_RL("LC: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 	else
 		IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
 			      "inactconns %d\n",
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
index 4680647..f454c80 100644
--- a/net/netfilter/ipvs/ip_vs_nfct.c
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -141,6 +141,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
 	struct nf_conntrack_tuple *orig, new_reply;
 	struct ip_vs_conn *cp;
 	struct ip_vs_conn_param p;
+	struct net *net = nf_ct_net(ct);
 
 	if (exp->tuple.src.l3num != PF_INET)
 		return;
@@ -155,7 +156,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
 
 	/* RS->CLIENT */
 	orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
-	ip_vs_conn_fill_param(exp->tuple.src.l3num, orig->dst.protonum,
+	ip_vs_conn_fill_param(net, exp->tuple.src.l3num, orig->dst.protonum,
 			      &orig->src.u3, orig->src.u.tcp.port,
 			      &orig->dst.u3, orig->dst.u.tcp.port, &p);
 	cp = ip_vs_conn_out_get(&p);
@@ -268,7 +269,8 @@ void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
 		" for conn " FMT_CONN "\n",
 		__func__, ARG_TUPLE(&tuple), ARG_CONN(cp));
 
-	h = nf_conntrack_find_get(&init_net, NF_CT_DEFAULT_ZONE, &tuple);
+	h = nf_conntrack_find_get(ip_vs_conn_net(cp), NF_CT_DEFAULT_ZONE,
+				  &tuple);
 	if (h) {
 		ct = nf_ct_tuplehash_to_ctrack(h);
 		/* Show what happens instead of calling nf_ct_kill() */
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
index c413e18..984d9c1 100644
--- a/net/netfilter/ipvs/ip_vs_nq.c
+++ b/net/netfilter/ipvs/ip_vs_nq.c
@@ -99,7 +99,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	}
 
 	if (!least) {
-		IP_VS_ERR_RL("NQ: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
diff --git a/net/netfilter/ipvs/ip_vs_pe.c b/net/netfilter/ipvs/ip_vs_pe.c
index 3414af7..5cf859c 100644
--- a/net/netfilter/ipvs/ip_vs_pe.c
+++ b/net/netfilter/ipvs/ip_vs_pe.c
@@ -29,12 +29,11 @@ void ip_vs_unbind_pe(struct ip_vs_service *svc)
 }
 
 /* Get pe in the pe list by name */
-static struct ip_vs_pe *
-ip_vs_pe_getbyname(const char *pe_name)
+struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
 {
 	struct ip_vs_pe *pe;
 
-	IP_VS_DBG(2, "%s(): pe_name \"%s\"\n", __func__,
+	IP_VS_DBG(10, "%s(): pe_name \"%s\"\n", __func__,
 		  pe_name);
 
 	spin_lock_bh(&ip_vs_pe_lock);
@@ -60,28 +59,22 @@ ip_vs_pe_getbyname(const char *pe_name)
 }
 
 /* Lookup pe and try to load it if it doesn't exist */
-struct ip_vs_pe *ip_vs_pe_get(const char *name)
+struct ip_vs_pe *ip_vs_pe_getbyname(const char *name)
 {
 	struct ip_vs_pe *pe;
 
 	/* Search for the pe by name */
-	pe = ip_vs_pe_getbyname(name);
+	pe = __ip_vs_pe_getbyname(name);
 
 	/* If pe not found, load the module and search again */
 	if (!pe) {
 		request_module("ip_vs_pe_%s", name);
-		pe = ip_vs_pe_getbyname(name);
+		pe = __ip_vs_pe_getbyname(name);
 	}
 
 	return pe;
 }
 
-void ip_vs_pe_put(struct ip_vs_pe *pe)
-{
-	if (pe && pe->module)
-		module_put(pe->module);
-}
-
 /* Register a pe in the pe list */
 int register_ip_vs_pe(struct ip_vs_pe *pe)
 {
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
index b8b4e96..13d607a 100644
--- a/net/netfilter/ipvs/ip_vs_pe_sip.c
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -71,6 +71,7 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
 	struct ip_vs_iphdr iph;
 	unsigned int dataoff, datalen, matchoff, matchlen;
 	const char *dptr;
+	int retc;
 
 	ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);
 
@@ -83,20 +84,21 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
 	if (dataoff >= skb->len)
 		return -EINVAL;
 
+	if ((retc=skb_linearize(skb)) < 0)
+		return retc;
 	dptr = skb->data + dataoff;
 	datalen = skb->len - dataoff;
 
 	if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen))
 		return -EINVAL;
 
-	p->pe_data = kmalloc(matchlen, GFP_ATOMIC);
-	if (!p->pe_data)
-		return -ENOMEM;
-
 	/* N.B: pe_data is only set on success,
 	 * this allows fallback to the default persistence logic on failure
 	 */
-	memcpy(p->pe_data, dptr + matchoff, matchlen);
+	p->pe_data = kmemdup(dptr + matchoff, matchlen, GFP_ATOMIC);
+	if (!p->pe_data)
+		return -ENOMEM;
+
 	p->pe_data_len = matchlen;
 
 	return 0;
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index c539983..17484a4 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -60,6 +60,35 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp)
 	return 0;
 }
 
+#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
+    defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
+    defined(CONFIG_IP_VS_PROTO_ESP)
+/*
+ *	register an ipvs protocols netns related data
+ */
+static int
+register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	unsigned hash = IP_VS_PROTO_HASH(pp->protocol);
+	struct ip_vs_proto_data *pd =
+			kzalloc(sizeof(struct ip_vs_proto_data), GFP_ATOMIC);
+
+	if (!pd) {
+		pr_err("%s(): no memory.\n", __func__);
+		return -ENOMEM;
+	}
+	pd->pp = pp;	/* For speed issues */
+	pd->next = ipvs->proto_data_table[hash];
+	ipvs->proto_data_table[hash] = pd;
+	atomic_set(&pd->appcnt, 0);	/* Init app counter */
+
+	if (pp->init_netns != NULL)
+		pp->init_netns(net, pd);
+
+	return 0;
+}
+#endif
 
 /*
  *	unregister an ipvs protocol
@@ -82,6 +111,29 @@ static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp)
 	return -ESRCH;
 }
 
+/*
+ *	unregister an ipvs protocols netns data
+ */
+static int
+unregister_ip_vs_proto_netns(struct net *net, struct ip_vs_proto_data *pd)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data **pd_p;
+	unsigned hash = IP_VS_PROTO_HASH(pd->pp->protocol);
+
+	pd_p = &ipvs->proto_data_table[hash];
+	for (; *pd_p; pd_p = &(*pd_p)->next) {
+		if (*pd_p == pd) {
+			*pd_p = pd->next;
+			if (pd->pp->exit_netns != NULL)
+				pd->pp->exit_netns(net, pd);
+			kfree(pd);
+			return 0;
+		}
+	}
+
+	return -ESRCH;
+}
 
 /*
  *	get ip_vs_protocol object by its proto.
@@ -100,19 +152,44 @@ struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto)
 }
 EXPORT_SYMBOL(ip_vs_proto_get);
 
+/*
+ *	get ip_vs_protocol object data by netns and proto
+ */
+struct ip_vs_proto_data *
+__ipvs_proto_data_get(struct netns_ipvs *ipvs, unsigned short proto)
+{
+	struct ip_vs_proto_data *pd;
+	unsigned hash = IP_VS_PROTO_HASH(proto);
+
+	for (pd = ipvs->proto_data_table[hash]; pd; pd = pd->next) {
+		if (pd->pp->protocol == proto)
+			return pd;
+	}
+
+	return NULL;
+}
+
+struct ip_vs_proto_data *
+ip_vs_proto_data_get(struct net *net, unsigned short proto)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	return __ipvs_proto_data_get(ipvs, proto);
+}
+EXPORT_SYMBOL(ip_vs_proto_data_get);
 
 /*
  *	Propagate event for state change to all protocols
  */
-void ip_vs_protocol_timeout_change(int flags)
+void ip_vs_protocol_timeout_change(struct netns_ipvs *ipvs, int flags)
 {
-	struct ip_vs_protocol *pp;
+	struct ip_vs_proto_data *pd;
 	int i;
 
 	for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
-		for (pp = ip_vs_proto_table[i]; pp; pp = pp->next) {
-			if (pp->timeout_change)
-				pp->timeout_change(pp, flags);
+		for (pd = ipvs->proto_data_table[i]; pd; pd = pd->next) {
+			if (pd->pp->timeout_change)
+				pd->pp->timeout_change(pd, flags);
 		}
 	}
 }
@@ -236,6 +313,46 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp,
 		ip_vs_tcpudp_debug_packet_v4(pp, skb, offset, msg);
 }
 
+/*
+ * per network name-space init
+ */
+static int __net_init __ip_vs_protocol_init(struct net *net)
+{
+#ifdef CONFIG_IP_VS_PROTO_TCP
+	register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
+#endif
+#ifdef CONFIG_IP_VS_PROTO_UDP
+	register_ip_vs_proto_netns(net, &ip_vs_protocol_udp);
+#endif
+#ifdef CONFIG_IP_VS_PROTO_SCTP
+	register_ip_vs_proto_netns(net, &ip_vs_protocol_sctp);
+#endif
+#ifdef CONFIG_IP_VS_PROTO_AH
+	register_ip_vs_proto_netns(net, &ip_vs_protocol_ah);
+#endif
+#ifdef CONFIG_IP_VS_PROTO_ESP
+	register_ip_vs_proto_netns(net, &ip_vs_protocol_esp);
+#endif
+	return 0;
+}
+
+static void __net_exit __ip_vs_protocol_cleanup(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data *pd;
+	int i;
+
+	/* unregister all the ipvs proto data for this netns */
+	for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
+		while ((pd = ipvs->proto_data_table[i]) != NULL)
+			unregister_ip_vs_proto_netns(net, pd);
+	}
+}
+
+static struct pernet_operations ipvs_proto_ops = {
+	.init = __ip_vs_protocol_init,
+	.exit = __ip_vs_protocol_cleanup,
+};
 
 int __init ip_vs_protocol_init(void)
 {
@@ -265,6 +382,7 @@ int __init ip_vs_protocol_init(void)
 	REGISTER_PROTOCOL(&ip_vs_protocol_esp);
 #endif
 	pr_info("Registered protocols (%s)\n", &protocols[2]);
+	return register_pernet_subsys(&ipvs_proto_ops);
 
 	return 0;
 }
@@ -275,6 +393,7 @@ void ip_vs_protocol_cleanup(void)
 	struct ip_vs_protocol *pp;
 	int i;
 
+	unregister_pernet_subsys(&ipvs_proto_ops);
 	/* unregister all the ipvs protocols */
 	for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) {
 		while ((pp = ip_vs_proto_table[i]) != NULL)
diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
index 3a04611..5b8eb8b 100644
--- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
@@ -41,28 +41,30 @@ struct isakmp_hdr {
 #define PORT_ISAKMP	500
 
 static void
-ah_esp_conn_fill_param_proto(int af, const struct ip_vs_iphdr *iph,
-			     int inverse, struct ip_vs_conn_param *p)
+ah_esp_conn_fill_param_proto(struct net *net, int af,
+			     const struct ip_vs_iphdr *iph, int inverse,
+			     struct ip_vs_conn_param *p)
 {
 	if (likely(!inverse))
-		ip_vs_conn_fill_param(af, IPPROTO_UDP,
+		ip_vs_conn_fill_param(net, af, IPPROTO_UDP,
 				      &iph->saddr, htons(PORT_ISAKMP),
 				      &iph->daddr, htons(PORT_ISAKMP), p);
 	else
-		ip_vs_conn_fill_param(af, IPPROTO_UDP,
+		ip_vs_conn_fill_param(net, af, IPPROTO_UDP,
 				      &iph->daddr, htons(PORT_ISAKMP),
 				      &iph->saddr, htons(PORT_ISAKMP), p);
 }
 
 static struct ip_vs_conn *
-ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
+ah_esp_conn_in_get(int af, const struct sk_buff *skb,
 		   const struct ip_vs_iphdr *iph, unsigned int proto_off,
 		   int inverse)
 {
 	struct ip_vs_conn *cp;
 	struct ip_vs_conn_param p;
+	struct net *net = skb_net(skb);
 
-	ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
+	ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p);
 	cp = ip_vs_conn_in_get(&p);
 	if (!cp) {
 		/*
@@ -72,7 +74,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
 		IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet "
 			      "%s%s %s->%s\n",
 			      inverse ? "ICMP+" : "",
-			      pp->name,
+			      ip_vs_proto_get(iph->protocol)->name,
 			      IP_VS_DBG_ADDR(af, &iph->saddr),
 			      IP_VS_DBG_ADDR(af, &iph->daddr));
 	}
@@ -83,21 +85,21 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
 
 static struct ip_vs_conn *
 ah_esp_conn_out_get(int af, const struct sk_buff *skb,
-		    struct ip_vs_protocol *pp,
 		    const struct ip_vs_iphdr *iph,
 		    unsigned int proto_off,
 		    int inverse)
 {
 	struct ip_vs_conn *cp;
 	struct ip_vs_conn_param p;
+	struct net *net = skb_net(skb);
 
-	ah_esp_conn_fill_param_proto(af, iph, inverse, &p);
+	ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p);
 	cp = ip_vs_conn_out_get(&p);
 	if (!cp) {
 		IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
 			      "%s%s %s->%s\n",
 			      inverse ? "ICMP+" : "",
-			      pp->name,
+			      ip_vs_proto_get(iph->protocol)->name,
 			      IP_VS_DBG_ADDR(af, &iph->saddr),
 			      IP_VS_DBG_ADDR(af, &iph->daddr));
 	}
@@ -107,7 +109,7 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
 
 
 static int
-ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 		     int *verdict, struct ip_vs_conn **cpp)
 {
 	/*
@@ -117,26 +119,14 @@ ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 	return 0;
 }
 
-static void ah_esp_init(struct ip_vs_protocol *pp)
-{
-	/* nothing to do now */
-}
-
-
-static void ah_esp_exit(struct ip_vs_protocol *pp)
-{
-	/* nothing to do now */
-}
-
-
 #ifdef CONFIG_IP_VS_PROTO_AH
 struct ip_vs_protocol ip_vs_protocol_ah = {
 	.name =			"AH",
 	.protocol =		IPPROTO_AH,
 	.num_states =		1,
 	.dont_defrag =		1,
-	.init =			ah_esp_init,
-	.exit =			ah_esp_exit,
+	.init =			NULL,
+	.exit =			NULL,
 	.conn_schedule =	ah_esp_conn_schedule,
 	.conn_in_get =		ah_esp_conn_in_get,
 	.conn_out_get =		ah_esp_conn_out_get,
@@ -149,7 +139,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = {
 	.app_conn_bind =	NULL,
 	.debug_packet =		ip_vs_tcpudp_debug_packet,
 	.timeout_change =	NULL,		/* ISAKMP */
-	.set_state_timeout =	NULL,
 };
 #endif
 
@@ -159,8 +148,8 @@ struct ip_vs_protocol ip_vs_protocol_esp = {
 	.protocol =		IPPROTO_ESP,
 	.num_states =		1,
 	.dont_defrag =		1,
-	.init =			ah_esp_init,
-	.exit =			ah_esp_exit,
+	.init =			NULL,
+	.exit =			NULL,
 	.conn_schedule =	ah_esp_conn_schedule,
 	.conn_in_get =		ah_esp_conn_in_get,
 	.conn_out_get =		ah_esp_conn_out_get,
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 1ea96bc..b027ccc 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -9,9 +9,10 @@
 #include <net/ip_vs.h>
 
 static int
-sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 		   int *verdict, struct ip_vs_conn **cpp)
 {
+	struct net *net;
 	struct ip_vs_service *svc;
 	sctp_chunkhdr_t _schunkh, *sch;
 	sctp_sctphdr_t *sh, _sctph;
@@ -27,13 +28,13 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 				 sizeof(_schunkh), &_schunkh);
 	if (sch == NULL)
 		return 0;
-
+	net = skb_net(skb);
 	if ((sch->type == SCTP_CID_INIT) &&
-	    (svc = ip_vs_service_get(af, skb->mark, iph.protocol,
+	    (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
 				     &iph.daddr, sh->dest))) {
 		int ignored;
 
-		if (ip_vs_todrop()) {
+		if (ip_vs_todrop(net_ipvs(net))) {
 			/*
 			 * It seems that we are very loaded.
 			 * We have to drop this packet :(
@@ -46,14 +47,19 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 * Let the virtual server select a real server for the
 		 * incoming connection, and create a connection entry.
 		 */
-		*cpp = ip_vs_schedule(svc, skb, pp, &ignored);
-		if (!*cpp && !ignored) {
-			*verdict = ip_vs_leave(svc, skb, pp);
+		*cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+		if (!*cpp && ignored <= 0) {
+			if (!ignored)
+				*verdict = ip_vs_leave(svc, skb, pd);
+			else {
+				ip_vs_service_put(svc);
+				*verdict = NF_DROP;
+			}
 			return 0;
 		}
 		ip_vs_service_put(svc);
 	}
-
+	/* NF_ACCEPT */
 	return 1;
 }
 
@@ -856,7 +862,7 @@ static struct ipvs_sctp_nextstate
 /*
  *      Timeout table[state]
  */
-static int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = {
+static const int sctp_timeouts[IP_VS_SCTP_S_LAST + 1] = {
 	[IP_VS_SCTP_S_NONE]         =     2 * HZ,
 	[IP_VS_SCTP_S_INIT_CLI]     =     1 * 60 * HZ,
 	[IP_VS_SCTP_S_INIT_SER]     =     1 * 60 * HZ,
@@ -900,20 +906,8 @@ static const char *sctp_state_name(int state)
 	return "?";
 }
 
-static void sctp_timeout_change(struct ip_vs_protocol *pp, int flags)
-{
-}
-
-static int
-sctp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
-{
-
-return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_SCTP_S_LAST,
-				sctp_state_name_table, sname, to);
-}
-
 static inline int
-set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
+set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
 		int direction, const struct sk_buff *skb)
 {
 	sctp_chunkhdr_t _sctpch, *sch;
@@ -971,7 +965,7 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
 
 		IP_VS_DBG_BUF(8, "%s %s  %s:%d->"
 				"%s:%d state: %s->%s conn->refcnt:%d\n",
-				pp->name,
+				pd->pp->name,
 				((direction == IP_VS_DIR_OUTPUT) ?
 				 "output " : "input "),
 				IP_VS_DBG_ADDR(cp->af, &cp->daddr),
@@ -995,75 +989,73 @@ set_sctp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
 			}
 		}
 	}
+	if (likely(pd))
+		cp->timeout = pd->timeout_table[cp->state = next_state];
+	else	/* What to do ? */
+		cp->timeout = sctp_timeouts[cp->state = next_state];
 
-	 cp->timeout = pp->timeout_table[cp->state = next_state];
-
-	 return 1;
+	return 1;
 }
 
 static int
 sctp_state_transition(struct ip_vs_conn *cp, int direction,
-		const struct sk_buff *skb, struct ip_vs_protocol *pp)
+		const struct sk_buff *skb, struct ip_vs_proto_data *pd)
 {
 	int ret = 0;
 
 	spin_lock(&cp->lock);
-	ret = set_sctp_state(pp, cp, direction, skb);
+	ret = set_sctp_state(pd, cp, direction, skb);
 	spin_unlock(&cp->lock);
 
 	return ret;
 }
 
-/*
- *      Hash table for SCTP application incarnations
- */
-#define SCTP_APP_TAB_BITS        4
-#define SCTP_APP_TAB_SIZE        (1 << SCTP_APP_TAB_BITS)
-#define SCTP_APP_TAB_MASK        (SCTP_APP_TAB_SIZE - 1)
-
-static struct list_head sctp_apps[SCTP_APP_TAB_SIZE];
-static DEFINE_SPINLOCK(sctp_app_lock);
-
 static inline __u16 sctp_app_hashkey(__be16 port)
 {
 	return (((__force u16)port >> SCTP_APP_TAB_BITS) ^ (__force u16)port)
 		& SCTP_APP_TAB_MASK;
 }
 
-static int sctp_register_app(struct ip_vs_app *inc)
+static int sctp_register_app(struct net *net, struct ip_vs_app *inc)
 {
 	struct ip_vs_app *i;
 	__u16 hash;
 	__be16 port = inc->port;
 	int ret = 0;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_SCTP);
 
 	hash = sctp_app_hashkey(port);
 
-	spin_lock_bh(&sctp_app_lock);
-	list_for_each_entry(i, &sctp_apps[hash], p_list) {
+	spin_lock_bh(&ipvs->sctp_app_lock);
+	list_for_each_entry(i, &ipvs->sctp_apps[hash], p_list) {
 		if (i->port == port) {
 			ret = -EEXIST;
 			goto out;
 		}
 	}
-	list_add(&inc->p_list, &sctp_apps[hash]);
-	atomic_inc(&ip_vs_protocol_sctp.appcnt);
+	list_add(&inc->p_list, &ipvs->sctp_apps[hash]);
+	atomic_inc(&pd->appcnt);
 out:
-	spin_unlock_bh(&sctp_app_lock);
+	spin_unlock_bh(&ipvs->sctp_app_lock);
 
 	return ret;
 }
 
-static void sctp_unregister_app(struct ip_vs_app *inc)
+static void sctp_unregister_app(struct net *net, struct ip_vs_app *inc)
 {
-	spin_lock_bh(&sctp_app_lock);
-	atomic_dec(&ip_vs_protocol_sctp.appcnt);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_SCTP);
+
+	spin_lock_bh(&ipvs->sctp_app_lock);
+	atomic_dec(&pd->appcnt);
 	list_del(&inc->p_list);
-	spin_unlock_bh(&sctp_app_lock);
+	spin_unlock_bh(&ipvs->sctp_app_lock);
 }
 
 static int sctp_app_conn_bind(struct ip_vs_conn *cp)
 {
+	struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
 	int hash;
 	struct ip_vs_app *inc;
 	int result = 0;
@@ -1074,12 +1066,12 @@ static int sctp_app_conn_bind(struct ip_vs_conn *cp)
 	/* Lookup application incarnations and bind the right one */
 	hash = sctp_app_hashkey(cp->vport);
 
-	spin_lock(&sctp_app_lock);
-	list_for_each_entry(inc, &sctp_apps[hash], p_list) {
+	spin_lock(&ipvs->sctp_app_lock);
+	list_for_each_entry(inc, &ipvs->sctp_apps[hash], p_list) {
 		if (inc->port == cp->vport) {
 			if (unlikely(!ip_vs_app_inc_get(inc)))
 				break;
-			spin_unlock(&sctp_app_lock);
+			spin_unlock(&ipvs->sctp_app_lock);
 
 			IP_VS_DBG_BUF(9, "%s: Binding conn %s:%u->"
 					"%s:%u to app %s on port %u\n",
@@ -1095,43 +1087,50 @@ static int sctp_app_conn_bind(struct ip_vs_conn *cp)
 			goto out;
 		}
 	}
-	spin_unlock(&sctp_app_lock);
+	spin_unlock(&ipvs->sctp_app_lock);
 out:
 	return result;
 }
 
-static void ip_vs_sctp_init(struct ip_vs_protocol *pp)
+/* ---------------------------------------------
+ *   timeouts is netns related now.
+ * ---------------------------------------------
+ */
+static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
 {
-	IP_VS_INIT_HASH_TABLE(sctp_apps);
-	pp->timeout_table = sctp_timeouts;
-}
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
+	ip_vs_init_hash_table(ipvs->sctp_apps, SCTP_APP_TAB_SIZE);
+	spin_lock_init(&ipvs->sctp_app_lock);
+	pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts,
+							sizeof(sctp_timeouts));
+}
 
-static void ip_vs_sctp_exit(struct ip_vs_protocol *pp)
+static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd)
 {
-
+	kfree(pd->timeout_table);
 }
 
 struct ip_vs_protocol ip_vs_protocol_sctp = {
-	.name = "SCTP",
-	.protocol = IPPROTO_SCTP,
-	.num_states = IP_VS_SCTP_S_LAST,
-	.dont_defrag = 0,
-	.appcnt = ATOMIC_INIT(0),
-	.init = ip_vs_sctp_init,
-	.exit = ip_vs_sctp_exit,
-	.register_app = sctp_register_app,
+	.name		= "SCTP",
+	.protocol	= IPPROTO_SCTP,
+	.num_states	= IP_VS_SCTP_S_LAST,
+	.dont_defrag	= 0,
+	.init		= NULL,
+	.exit		= NULL,
+	.init_netns	= __ip_vs_sctp_init,
+	.exit_netns	= __ip_vs_sctp_exit,
+	.register_app	= sctp_register_app,
 	.unregister_app = sctp_unregister_app,
-	.conn_schedule = sctp_conn_schedule,
-	.conn_in_get = ip_vs_conn_in_get_proto,
-	.conn_out_get = ip_vs_conn_out_get_proto,
-	.snat_handler = sctp_snat_handler,
-	.dnat_handler = sctp_dnat_handler,
-	.csum_check = sctp_csum_check,
-	.state_name = sctp_state_name,
+	.conn_schedule	= sctp_conn_schedule,
+	.conn_in_get	= ip_vs_conn_in_get_proto,
+	.conn_out_get	= ip_vs_conn_out_get_proto,
+	.snat_handler	= sctp_snat_handler,
+	.dnat_handler	= sctp_dnat_handler,
+	.csum_check	= sctp_csum_check,
+	.state_name	= sctp_state_name,
 	.state_transition = sctp_state_transition,
-	.app_conn_bind = sctp_app_conn_bind,
-	.debug_packet = ip_vs_tcpudp_debug_packet,
-	.timeout_change = sctp_timeout_change,
-	.set_state_timeout = sctp_set_state_timeout,
+	.app_conn_bind	= sctp_app_conn_bind,
+	.debug_packet	= ip_vs_tcpudp_debug_packet,
+	.timeout_change	= NULL,
 };
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index f6c5200..c0cc341 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -9,8 +9,12 @@
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Changes:
+ * Changes:     Hans Schillstrom <hans.schillstrom@ericsson.com>
  *
+ *              Network name space (netns) aware.
+ *              Global data moved to netns i.e struct netns_ipvs
+ *              tcp_timeouts table has copy per netns in a hash table per
+ *              protocol ip_vs_proto_data and is handled by netns
  */
 
 #define KMSG_COMPONENT "IPVS"
@@ -28,9 +32,10 @@
 #include <net/ip_vs.h>
 
 static int
-tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 		  int *verdict, struct ip_vs_conn **cpp)
 {
+	struct net *net;
 	struct ip_vs_service *svc;
 	struct tcphdr _tcph, *th;
 	struct ip_vs_iphdr iph;
@@ -42,14 +47,14 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 		*verdict = NF_DROP;
 		return 0;
 	}
-
+	net = skb_net(skb);
 	/* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
 	if (th->syn &&
-	    (svc = ip_vs_service_get(af, skb->mark, iph.protocol, &iph.daddr,
-				     th->dest))) {
+	    (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
+				     &iph.daddr, th->dest))) {
 		int ignored;
 
-		if (ip_vs_todrop()) {
+		if (ip_vs_todrop(net_ipvs(net))) {
 			/*
 			 * It seems that we are very loaded.
 			 * We have to drop this packet :(
@@ -63,13 +68,19 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 * Let the virtual server select a real server for the
 		 * incoming connection, and create a connection entry.
 		 */
-		*cpp = ip_vs_schedule(svc, skb, pp, &ignored);
-		if (!*cpp && !ignored) {
-			*verdict = ip_vs_leave(svc, skb, pp);
+		*cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+		if (!*cpp && ignored <= 0) {
+			if (!ignored)
+				*verdict = ip_vs_leave(svc, skb, pd);
+			else {
+				ip_vs_service_put(svc);
+				*verdict = NF_DROP;
+			}
 			return 0;
 		}
 		ip_vs_service_put(svc);
 	}
+	/* NF_ACCEPT */
 	return 1;
 }
 
@@ -338,7 +349,7 @@ static const int tcp_state_off[IP_VS_DIR_LAST] = {
 /*
  *	Timeout table[state]
  */
-static int tcp_timeouts[IP_VS_TCP_S_LAST+1] = {
+static const int tcp_timeouts[IP_VS_TCP_S_LAST+1] = {
 	[IP_VS_TCP_S_NONE]		=	2*HZ,
 	[IP_VS_TCP_S_ESTABLISHED]	=	15*60*HZ,
 	[IP_VS_TCP_S_SYN_SENT]		=	2*60*HZ,
@@ -437,10 +448,7 @@ static struct tcp_states_t tcp_states_dos [] = {
 /*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sCL }},
 };
 
-static struct tcp_states_t *tcp_state_table = tcp_states;
-
-
-static void tcp_timeout_change(struct ip_vs_protocol *pp, int flags)
+static void tcp_timeout_change(struct ip_vs_proto_data *pd, int flags)
 {
 	int on = (flags & 1);		/* secure_tcp */
 
@@ -450,14 +458,7 @@ static void tcp_timeout_change(struct ip_vs_protocol *pp, int flags)
 	** for most if not for all of the applications. Something
 	** like "capabilities" (flags) for each object.
 	*/
-	tcp_state_table = (on? tcp_states_dos : tcp_states);
-}
-
-static int
-tcp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
-{
-	return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_TCP_S_LAST,
-				       tcp_state_name_table, sname, to);
+	pd->tcp_state_table = (on ? tcp_states_dos : tcp_states);
 }
 
 static inline int tcp_state_idx(struct tcphdr *th)
@@ -474,7 +475,7 @@ static inline int tcp_state_idx(struct tcphdr *th)
 }
 
 static inline void
-set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
+set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
 	      int direction, struct tcphdr *th)
 {
 	int state_idx;
@@ -497,7 +498,8 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
 		goto tcp_state_out;
 	}
 
-	new_state = tcp_state_table[state_off+state_idx].next_state[cp->state];
+	new_state =
+		pd->tcp_state_table[state_off+state_idx].next_state[cp->state];
 
   tcp_state_out:
 	if (new_state != cp->state) {
@@ -505,7 +507,7 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
 
 		IP_VS_DBG_BUF(8, "%s %s [%c%c%c%c] %s:%d->"
 			      "%s:%d state: %s->%s conn->refcnt:%d\n",
-			      pp->name,
+			      pd->pp->name,
 			      ((state_off == TCP_DIR_OUTPUT) ?
 			       "output " : "input "),
 			      th->syn ? 'S' : '.',
@@ -535,17 +537,19 @@ set_tcp_state(struct ip_vs_protocol *pp, struct ip_vs_conn *cp,
 		}
 	}
 
-	cp->timeout = pp->timeout_table[cp->state = new_state];
+	if (likely(pd))
+		cp->timeout = pd->timeout_table[cp->state = new_state];
+	else	/* What to do ? */
+		cp->timeout = tcp_timeouts[cp->state = new_state];
 }
 
-
 /*
  *	Handle state transitions
  */
 static int
 tcp_state_transition(struct ip_vs_conn *cp, int direction,
 		     const struct sk_buff *skb,
-		     struct ip_vs_protocol *pp)
+		     struct ip_vs_proto_data *pd)
 {
 	struct tcphdr _tcph, *th;
 
@@ -560,23 +564,12 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction,
 		return 0;
 
 	spin_lock(&cp->lock);
-	set_tcp_state(pp, cp, direction, th);
+	set_tcp_state(pd, cp, direction, th);
 	spin_unlock(&cp->lock);
 
 	return 1;
 }
 
-
-/*
- *	Hash table for TCP application incarnations
- */
-#define	TCP_APP_TAB_BITS	4
-#define	TCP_APP_TAB_SIZE	(1 << TCP_APP_TAB_BITS)
-#define	TCP_APP_TAB_MASK	(TCP_APP_TAB_SIZE - 1)
-
-static struct list_head tcp_apps[TCP_APP_TAB_SIZE];
-static DEFINE_SPINLOCK(tcp_app_lock);
-
 static inline __u16 tcp_app_hashkey(__be16 port)
 {
 	return (((__force u16)port >> TCP_APP_TAB_BITS) ^ (__force u16)port)
@@ -584,44 +577,50 @@ static inline __u16 tcp_app_hashkey(__be16 port)
 }
 
 
-static int tcp_register_app(struct ip_vs_app *inc)
+static int tcp_register_app(struct net *net, struct ip_vs_app *inc)
 {
 	struct ip_vs_app *i;
 	__u16 hash;
 	__be16 port = inc->port;
 	int ret = 0;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
 
 	hash = tcp_app_hashkey(port);
 
-	spin_lock_bh(&tcp_app_lock);
-	list_for_each_entry(i, &tcp_apps[hash], p_list) {
+	spin_lock_bh(&ipvs->tcp_app_lock);
+	list_for_each_entry(i, &ipvs->tcp_apps[hash], p_list) {
 		if (i->port == port) {
 			ret = -EEXIST;
 			goto out;
 		}
 	}
-	list_add(&inc->p_list, &tcp_apps[hash]);
-	atomic_inc(&ip_vs_protocol_tcp.appcnt);
+	list_add(&inc->p_list, &ipvs->tcp_apps[hash]);
+	atomic_inc(&pd->appcnt);
 
   out:
-	spin_unlock_bh(&tcp_app_lock);
+	spin_unlock_bh(&ipvs->tcp_app_lock);
 	return ret;
 }
 
 
 static void
-tcp_unregister_app(struct ip_vs_app *inc)
+tcp_unregister_app(struct net *net, struct ip_vs_app *inc)
 {
-	spin_lock_bh(&tcp_app_lock);
-	atomic_dec(&ip_vs_protocol_tcp.appcnt);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+
+	spin_lock_bh(&ipvs->tcp_app_lock);
+	atomic_dec(&pd->appcnt);
 	list_del(&inc->p_list);
-	spin_unlock_bh(&tcp_app_lock);
+	spin_unlock_bh(&ipvs->tcp_app_lock);
 }
 
 
 static int
 tcp_app_conn_bind(struct ip_vs_conn *cp)
 {
+	struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
 	int hash;
 	struct ip_vs_app *inc;
 	int result = 0;
@@ -633,12 +632,12 @@ tcp_app_conn_bind(struct ip_vs_conn *cp)
 	/* Lookup application incarnations and bind the right one */
 	hash = tcp_app_hashkey(cp->vport);
 
-	spin_lock(&tcp_app_lock);
-	list_for_each_entry(inc, &tcp_apps[hash], p_list) {
+	spin_lock(&ipvs->tcp_app_lock);
+	list_for_each_entry(inc, &ipvs->tcp_apps[hash], p_list) {
 		if (inc->port == cp->vport) {
 			if (unlikely(!ip_vs_app_inc_get(inc)))
 				break;
-			spin_unlock(&tcp_app_lock);
+			spin_unlock(&ipvs->tcp_app_lock);
 
 			IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->"
 				      "%s:%u to app %s on port %u\n",
@@ -655,7 +654,7 @@ tcp_app_conn_bind(struct ip_vs_conn *cp)
 			goto out;
 		}
 	}
-	spin_unlock(&tcp_app_lock);
+	spin_unlock(&ipvs->tcp_app_lock);
 
   out:
 	return result;
@@ -665,24 +664,35 @@ tcp_app_conn_bind(struct ip_vs_conn *cp)
 /*
  *	Set LISTEN timeout. (ip_vs_conn_put will setup timer)
  */
-void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp)
+void ip_vs_tcp_conn_listen(struct net *net, struct ip_vs_conn *cp)
 {
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
+
 	spin_lock(&cp->lock);
 	cp->state = IP_VS_TCP_S_LISTEN;
-	cp->timeout = ip_vs_protocol_tcp.timeout_table[IP_VS_TCP_S_LISTEN];
+	cp->timeout = (pd ? pd->timeout_table[IP_VS_TCP_S_LISTEN]
+			   : tcp_timeouts[IP_VS_TCP_S_LISTEN]);
 	spin_unlock(&cp->lock);
 }
 
-
-static void ip_vs_tcp_init(struct ip_vs_protocol *pp)
+/* ---------------------------------------------
+ *   timeouts is netns related now.
+ * ---------------------------------------------
+ */
+static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
 {
-	IP_VS_INIT_HASH_TABLE(tcp_apps);
-	pp->timeout_table = tcp_timeouts;
-}
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
+	ip_vs_init_hash_table(ipvs->tcp_apps, TCP_APP_TAB_SIZE);
+	spin_lock_init(&ipvs->tcp_app_lock);
+	pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts,
+							sizeof(tcp_timeouts));
+	pd->tcp_state_table =  tcp_states;
+}
 
-static void ip_vs_tcp_exit(struct ip_vs_protocol *pp)
+static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)
 {
+	kfree(pd->timeout_table);
 }
 
 
@@ -691,9 +701,10 @@ struct ip_vs_protocol ip_vs_protocol_tcp = {
 	.protocol =		IPPROTO_TCP,
 	.num_states =		IP_VS_TCP_S_LAST,
 	.dont_defrag =		0,
-	.appcnt =		ATOMIC_INIT(0),
-	.init =			ip_vs_tcp_init,
-	.exit =			ip_vs_tcp_exit,
+	.init =			NULL,
+	.exit =			NULL,
+	.init_netns =		__ip_vs_tcp_init,
+	.exit_netns =		__ip_vs_tcp_exit,
 	.register_app =		tcp_register_app,
 	.unregister_app =	tcp_unregister_app,
 	.conn_schedule =	tcp_conn_schedule,
@@ -707,5 +718,4 @@ struct ip_vs_protocol ip_vs_protocol_tcp = {
 	.app_conn_bind =	tcp_app_conn_bind,
 	.debug_packet =		ip_vs_tcpudp_debug_packet,
 	.timeout_change =	tcp_timeout_change,
-	.set_state_timeout =	tcp_set_state_timeout,
 };
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index 9d106a0..f1282cb 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -9,7 +9,8 @@
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Changes:
+ * Changes:     Hans Schillstrom <hans.schillstrom@ericsson.com>
+ *              Network name space (netns) aware.
  *
  */
 
@@ -28,9 +29,10 @@
 #include <net/ip6_checksum.h>
 
 static int
-udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
+udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 		  int *verdict, struct ip_vs_conn **cpp)
 {
+	struct net *net;
 	struct ip_vs_service *svc;
 	struct udphdr _udph, *uh;
 	struct ip_vs_iphdr iph;
@@ -42,13 +44,13 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 		*verdict = NF_DROP;
 		return 0;
 	}
-
-	svc = ip_vs_service_get(af, skb->mark, iph.protocol,
+	net = skb_net(skb);
+	svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
 				&iph.daddr, uh->dest);
 	if (svc) {
 		int ignored;
 
-		if (ip_vs_todrop()) {
+		if (ip_vs_todrop(net_ipvs(net))) {
 			/*
 			 * It seems that we are very loaded.
 			 * We have to drop this packet :(
@@ -62,13 +64,19 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 		 * Let the virtual server select a real server for the
 		 * incoming connection, and create a connection entry.
 		 */
-		*cpp = ip_vs_schedule(svc, skb, pp, &ignored);
-		if (!*cpp && !ignored) {
-			*verdict = ip_vs_leave(svc, skb, pp);
+		*cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+		if (!*cpp && ignored <= 0) {
+			if (!ignored)
+				*verdict = ip_vs_leave(svc, skb, pd);
+			else {
+				ip_vs_service_put(svc);
+				*verdict = NF_DROP;
+			}
 			return 0;
 		}
 		ip_vs_service_put(svc);
 	}
+	/* NF_ACCEPT */
 	return 1;
 }
 
@@ -338,19 +346,6 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
 	return 1;
 }
 
-
-/*
- *	Note: the caller guarantees that only one of register_app,
- *	unregister_app or app_conn_bind is called each time.
- */
-
-#define	UDP_APP_TAB_BITS	4
-#define	UDP_APP_TAB_SIZE	(1 << UDP_APP_TAB_BITS)
-#define	UDP_APP_TAB_MASK	(UDP_APP_TAB_SIZE - 1)
-
-static struct list_head udp_apps[UDP_APP_TAB_SIZE];
-static DEFINE_SPINLOCK(udp_app_lock);
-
 static inline __u16 udp_app_hashkey(__be16 port)
 {
 	return (((__force u16)port >> UDP_APP_TAB_BITS) ^ (__force u16)port)
@@ -358,44 +353,50 @@ static inline __u16 udp_app_hashkey(__be16 port)
 }
 
 
-static int udp_register_app(struct ip_vs_app *inc)
+static int udp_register_app(struct net *net, struct ip_vs_app *inc)
 {
 	struct ip_vs_app *i;
 	__u16 hash;
 	__be16 port = inc->port;
 	int ret = 0;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
 
 	hash = udp_app_hashkey(port);
 
 
-	spin_lock_bh(&udp_app_lock);
-	list_for_each_entry(i, &udp_apps[hash], p_list) {
+	spin_lock_bh(&ipvs->udp_app_lock);
+	list_for_each_entry(i, &ipvs->udp_apps[hash], p_list) {
 		if (i->port == port) {
 			ret = -EEXIST;
 			goto out;
 		}
 	}
-	list_add(&inc->p_list, &udp_apps[hash]);
-	atomic_inc(&ip_vs_protocol_udp.appcnt);
+	list_add(&inc->p_list, &ipvs->udp_apps[hash]);
+	atomic_inc(&pd->appcnt);
 
   out:
-	spin_unlock_bh(&udp_app_lock);
+	spin_unlock_bh(&ipvs->udp_app_lock);
 	return ret;
 }
 
 
 static void
-udp_unregister_app(struct ip_vs_app *inc)
+udp_unregister_app(struct net *net, struct ip_vs_app *inc)
 {
-	spin_lock_bh(&udp_app_lock);
-	atomic_dec(&ip_vs_protocol_udp.appcnt);
+	struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	spin_lock_bh(&ipvs->udp_app_lock);
+	atomic_dec(&pd->appcnt);
 	list_del(&inc->p_list);
-	spin_unlock_bh(&udp_app_lock);
+	spin_unlock_bh(&ipvs->udp_app_lock);
 }
 
 
 static int udp_app_conn_bind(struct ip_vs_conn *cp)
 {
+	struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
 	int hash;
 	struct ip_vs_app *inc;
 	int result = 0;
@@ -407,12 +408,12 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
 	/* Lookup application incarnations and bind the right one */
 	hash = udp_app_hashkey(cp->vport);
 
-	spin_lock(&udp_app_lock);
-	list_for_each_entry(inc, &udp_apps[hash], p_list) {
+	spin_lock(&ipvs->udp_app_lock);
+	list_for_each_entry(inc, &ipvs->udp_apps[hash], p_list) {
 		if (inc->port == cp->vport) {
 			if (unlikely(!ip_vs_app_inc_get(inc)))
 				break;
-			spin_unlock(&udp_app_lock);
+			spin_unlock(&ipvs->udp_app_lock);
 
 			IP_VS_DBG_BUF(9, "%s(): Binding conn %s:%u->"
 				      "%s:%u to app %s on port %u\n",
@@ -429,14 +430,14 @@ static int udp_app_conn_bind(struct ip_vs_conn *cp)
 			goto out;
 		}
 	}
-	spin_unlock(&udp_app_lock);
+	spin_unlock(&ipvs->udp_app_lock);
 
   out:
 	return result;
 }
 
 
-static int udp_timeouts[IP_VS_UDP_S_LAST+1] = {
+static const int udp_timeouts[IP_VS_UDP_S_LAST+1] = {
 	[IP_VS_UDP_S_NORMAL]		=	5*60*HZ,
 	[IP_VS_UDP_S_LAST]		=	2*HZ,
 };
@@ -446,14 +447,6 @@ static const char *const udp_state_name_table[IP_VS_UDP_S_LAST+1] = {
 	[IP_VS_UDP_S_LAST]		=	"BUG!",
 };
 
-
-static int
-udp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
-{
-	return ip_vs_set_state_timeout(pp->timeout_table, IP_VS_UDP_S_LAST,
-				       udp_state_name_table, sname, to);
-}
-
 static const char * udp_state_name(int state)
 {
 	if (state >= IP_VS_UDP_S_LAST)
@@ -464,20 +457,30 @@ static const char * udp_state_name(int state)
 static int
 udp_state_transition(struct ip_vs_conn *cp, int direction,
 		     const struct sk_buff *skb,
-		     struct ip_vs_protocol *pp)
+		     struct ip_vs_proto_data *pd)
 {
-	cp->timeout = pp->timeout_table[IP_VS_UDP_S_NORMAL];
+	if (unlikely(!pd)) {
+		pr_err("UDP no ns data\n");
+		return 0;
+	}
+
+	cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
 	return 1;
 }
 
-static void udp_init(struct ip_vs_protocol *pp)
+static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
 {
-	IP_VS_INIT_HASH_TABLE(udp_apps);
-	pp->timeout_table = udp_timeouts;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	ip_vs_init_hash_table(ipvs->udp_apps, UDP_APP_TAB_SIZE);
+	spin_lock_init(&ipvs->udp_app_lock);
+	pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
+							sizeof(udp_timeouts));
 }
 
-static void udp_exit(struct ip_vs_protocol *pp)
+static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
 {
+	kfree(pd->timeout_table);
 }
 
 
@@ -486,8 +489,10 @@ struct ip_vs_protocol ip_vs_protocol_udp = {
 	.protocol =		IPPROTO_UDP,
 	.num_states =		IP_VS_UDP_S_LAST,
 	.dont_defrag =		0,
-	.init =			udp_init,
-	.exit =			udp_exit,
+	.init =			NULL,
+	.exit =			NULL,
+	.init_netns =		__udp_init,
+	.exit_netns =		__udp_exit,
 	.conn_schedule =	udp_conn_schedule,
 	.conn_in_get =		ip_vs_conn_in_get_proto,
 	.conn_out_get =		ip_vs_conn_out_get_proto,
@@ -501,5 +506,4 @@ struct ip_vs_protocol ip_vs_protocol_udp = {
 	.app_conn_bind =	udp_app_conn_bind,
 	.debug_packet =		ip_vs_tcpudp_debug_packet,
 	.timeout_change =	NULL,
-	.set_state_timeout =	udp_set_state_timeout,
 };
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
index e210f37..c49b388 100644
--- a/net/netfilter/ipvs/ip_vs_rr.c
+++ b/net/netfilter/ipvs/ip_vs_rr.c
@@ -72,7 +72,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		q = q->next;
 	} while (q != p);
 	write_unlock(&svc->sched_lock);
-	IP_VS_ERR_RL("RR: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
   out:
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index 076ebe0..08dbdd5 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -29,6 +29,7 @@
 
 #include <net/ip_vs.h>
 
+EXPORT_SYMBOL(ip_vs_scheduler_err);
 /*
  *  IPVS scheduler list
  */
@@ -146,6 +147,30 @@ void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler)
 		module_put(scheduler->module);
 }
 
+/*
+ * Common error output helper for schedulers
+ */
+
+void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
+{
+	if (svc->fwmark) {
+		IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
+			     svc->scheduler->name, svc->fwmark,
+			     svc->fwmark, msg);
+#ifdef CONFIG_IP_VS_IPV6
+	} else if (svc->af == AF_INET6) {
+		IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+			     svc->scheduler->name,
+			     ip_vs_proto_name(svc->protocol),
+			     &svc->addr.in6, ntohs(svc->port), msg);
+#endif
+	} else {
+		IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
+			     svc->scheduler->name,
+			     ip_vs_proto_name(svc->protocol),
+			     &svc->addr.ip, ntohs(svc->port), msg);
+	}
+}
 
 /*
  *  Register a scheduler in the scheduler list
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
index 1ab75a9..89ead24 100644
--- a/net/netfilter/ipvs/ip_vs_sed.c
+++ b/net/netfilter/ipvs/ip_vs_sed.c
@@ -87,7 +87,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("SED: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index e6cc174..b5e2556 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -223,7 +223,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	    || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
 	    || atomic_read(&dest->weight) <= 0
 	    || is_overloaded(dest)) {
-		IP_VS_ERR_RL("SH: no destination available\n");
+		ip_vs_scheduler_err(svc, "no destination available");
 		return NULL;
 	}
 
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index ab85aed..3e7961e 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -5,6 +5,18 @@
  *              high-performance and highly available server based on a
  *              cluster of servers.
  *
+ * Version 1,   is capable of handling both version 0 and 1 messages.
+ *              Version 0 is the plain old format.
+ *              Note Version 0 receivers will just drop Ver 1 messages.
+ *              Version 1 is capable of handle IPv6, Persistence data,
+ *              time-outs, and firewall marks.
+ *              In ver.1 "ip_vs_sync_conn_options" will be sent in netw. order.
+ *              Ver. 0 can be turned on by sysctl -w net.ipv4.vs.sync_version=0
+ *
+ * Definitions  Message: is a complete datagram
+ *              Sync_conn: is a part of a Message
+ *              Param Data is an option to a Sync_conn.
+ *
  * Authors:     Wensong Zhang <wensong@linuxvirtualserver.org>
  *
  * ip_vs_sync:  sync connection info from master load balancer to backups
@@ -15,6 +27,8 @@
  *	Alexandre Cassen	:	Added SyncID support for incoming sync
  *					messages filtering.
  *	Justin Ossevoort	:	Fix endian problem on sync message size.
+ *	Hans Schillstrom	:	Added Version 1: i.e. IPv6,
+ *					Persistence support, fwmark and time-out.
  */
 
 #define KMSG_COMPONENT "IPVS"
@@ -35,6 +49,8 @@
 #include <linux/wait.h>
 #include <linux/kernel.h>
 
+#include <asm/unaligned.h>		/* Used for ntoh_seq and hton_seq */
+
 #include <net/ip.h>
 #include <net/sock.h>
 
@@ -43,11 +59,13 @@
 #define IP_VS_SYNC_GROUP 0xe0000051    /* multicast addr - 224.0.0.81 */
 #define IP_VS_SYNC_PORT  8848          /* multicast port */
 
+#define SYNC_PROTO_VER  1		/* Protocol version in header */
 
 /*
  *	IPVS sync connection entry
+ *	Version 0, i.e. original version.
  */
-struct ip_vs_sync_conn {
+struct ip_vs_sync_conn_v0 {
 	__u8			reserved;
 
 	/* Protocol, addresses and port numbers */
@@ -71,41 +89,159 @@ struct ip_vs_sync_conn_options {
 	struct ip_vs_seq        out_seq;        /* outgoing seq. struct */
 };
 
+/*
+     Sync Connection format (sync_conn)
+
+       0                   1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |    Type       |    Protocol   | Ver.  |        Size           |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                             Flags                             |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |            State              |         cport                 |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |            vport              |         dport                 |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                             fwmark                            |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                             timeout  (in sec.)                |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                              ...                              |
+      |                        IP-Addresses  (v4 or v6)               |
+      |                              ...                              |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  Optional Parameters.
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      | Param. Type    | Param. Length |   Param. data                |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
+      |                              ...                              |
+      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                               | Param Type    | Param. Length |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                           Param  data                         |
+      |         Last Param data should be padded for 32 bit alignment |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+*/
+
+/*
+ *  Type 0, IPv4 sync connection format
+ */
+struct ip_vs_sync_v4 {
+	__u8			type;
+	__u8			protocol;	/* Which protocol (TCP/UDP) */
+	__be16			ver_size;	/* Version msb 4 bits */
+	/* Flags and state transition */
+	__be32			flags;		/* status flags */
+	__be16			state;		/* state info 	*/
+	/* Protocol, addresses and port numbers */
+	__be16			cport;
+	__be16			vport;
+	__be16			dport;
+	__be32			fwmark;		/* Firewall mark from skb */
+	__be32			timeout;	/* cp timeout */
+	__be32			caddr;		/* client address */
+	__be32			vaddr;		/* virtual address */
+	__be32			daddr;		/* destination address */
+	/* The sequence options start here */
+	/* PE data padded to 32bit alignment after seq. options */
+};
+/*
+ * Type 2 messages IPv6
+ */
+struct ip_vs_sync_v6 {
+	__u8			type;
+	__u8			protocol;	/* Which protocol (TCP/UDP) */
+	__be16			ver_size;	/* Version msb 4 bits */
+	/* Flags and state transition */
+	__be32			flags;		/* status flags */
+	__be16			state;		/* state info 	*/
+	/* Protocol, addresses and port numbers */
+	__be16			cport;
+	__be16			vport;
+	__be16			dport;
+	__be32			fwmark;		/* Firewall mark from skb */
+	__be32			timeout;	/* cp timeout */
+	struct in6_addr		caddr;		/* client address */
+	struct in6_addr		vaddr;		/* virtual address */
+	struct in6_addr		daddr;		/* destination address */
+	/* The sequence options start here */
+	/* PE data padded to 32bit alignment after seq. options */
+};
+
+union ip_vs_sync_conn {
+	struct ip_vs_sync_v4	v4;
+	struct ip_vs_sync_v6	v6;
+};
+
+/* Bits in Type field in above */
+#define STYPE_INET6		0
+#define STYPE_F_INET6		(1 << STYPE_INET6)
+
+#define SVER_SHIFT		12		/* Shift to get version */
+#define SVER_MASK		0x0fff		/* Mask to strip version */
+
+#define IPVS_OPT_SEQ_DATA	1
+#define IPVS_OPT_PE_DATA	2
+#define IPVS_OPT_PE_NAME	3
+#define IPVS_OPT_PARAM		7
+
+#define IPVS_OPT_F_SEQ_DATA	(1 << (IPVS_OPT_SEQ_DATA-1))
+#define IPVS_OPT_F_PE_DATA	(1 << (IPVS_OPT_PE_DATA-1))
+#define IPVS_OPT_F_PE_NAME	(1 << (IPVS_OPT_PE_NAME-1))
+#define IPVS_OPT_F_PARAM	(1 << (IPVS_OPT_PARAM-1))
+
 struct ip_vs_sync_thread_data {
+	struct net *net;
 	struct socket *sock;
 	char *buf;
 };
 
-#define SIMPLE_CONN_SIZE  (sizeof(struct ip_vs_sync_conn))
+/* Version 0 definition of packet sizes */
+#define SIMPLE_CONN_SIZE  (sizeof(struct ip_vs_sync_conn_v0))
 #define FULL_CONN_SIZE  \
-(sizeof(struct ip_vs_sync_conn) + sizeof(struct ip_vs_sync_conn_options))
+(sizeof(struct ip_vs_sync_conn_v0) + sizeof(struct ip_vs_sync_conn_options))
 
 
 /*
-  The master mulitcasts messages to the backup load balancers in the
-  following format.
+  The master mulitcasts messages (Datagrams) to the backup load balancers
+  in the following format.
+
+ Version 1:
+  Note, first byte should be Zero, so ver 0 receivers will drop the packet.
 
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-      |  Count Conns  |    SyncID     |            Size               |
+      |      0        |    SyncID     |            Size               |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |  Count Conns  |    Version    |    Reserved, set to Zero      |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       |                    IPVS Sync Connection (1)                   |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                            .                                  |
-      |                            .                                  |
+      ~                            .                                  ~
       |                            .                                  |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       |                    IPVS Sync Connection (n)                   |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Version 0 Header
+       0                   1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |  Count Conns  |    SyncID     |            Size               |
+      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+      |                    IPVS Sync Connection (1)                   |
 */
 
 #define SYNC_MESG_HEADER_LEN	4
 #define MAX_CONNS_PER_SYNCBUFF	255 /* nr_conns in ip_vs_sync_mesg is 8 bit */
 
-struct ip_vs_sync_mesg {
+/* Version 0 header */
+struct ip_vs_sync_mesg_v0 {
 	__u8                    nr_conns;
 	__u8                    syncid;
 	__u16                   size;
@@ -113,9 +249,16 @@ struct ip_vs_sync_mesg {
 	/* ip_vs_sync_conn entries start here */
 };
 
-/* the maximum length of sync (sending/receiving) message */
-static int sync_send_mesg_maxlen;
-static int sync_recv_mesg_maxlen;
+/* Version 1 header */
+struct ip_vs_sync_mesg {
+	__u8			reserved;	/* must be zero */
+	__u8			syncid;
+	__u16			size;
+	__u8			nr_conns;
+	__s8			version;	/* SYNC_PROTO_VER  */
+	__u16			spare;
+	/* ip_vs_sync_conn entries start here */
+};
 
 struct ip_vs_sync_buff {
 	struct list_head        list;
@@ -127,28 +270,6 @@ struct ip_vs_sync_buff {
 	unsigned char           *end;
 };
 
-
-/* the sync_buff list head and the lock */
-static LIST_HEAD(ip_vs_sync_queue);
-static DEFINE_SPINLOCK(ip_vs_sync_lock);
-
-/* current sync_buff for accepting new conn entries */
-static struct ip_vs_sync_buff   *curr_sb = NULL;
-static DEFINE_SPINLOCK(curr_sb_lock);
-
-/* ipvs sync daemon state */
-volatile int ip_vs_sync_state = IP_VS_STATE_NONE;
-volatile int ip_vs_master_syncid = 0;
-volatile int ip_vs_backup_syncid = 0;
-
-/* multicast interface name */
-char ip_vs_master_mcast_ifn[IP_VS_IFNAME_MAXLEN];
-char ip_vs_backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
-
-/* sync daemon tasks */
-static struct task_struct *sync_master_thread;
-static struct task_struct *sync_backup_thread;
-
 /* multicast addr */
 static struct sockaddr_in mcast_addr = {
 	.sin_family		= AF_INET,
@@ -156,41 +277,71 @@ static struct sockaddr_in mcast_addr = {
 	.sin_addr.s_addr	= cpu_to_be32(IP_VS_SYNC_GROUP),
 };
 
+/*
+ * Copy of struct ip_vs_seq
+ * From unaligned network order to aligned host order
+ */
+static void ntoh_seq(struct ip_vs_seq *no, struct ip_vs_seq *ho)
+{
+	ho->init_seq       = get_unaligned_be32(&no->init_seq);
+	ho->delta          = get_unaligned_be32(&no->delta);
+	ho->previous_delta = get_unaligned_be32(&no->previous_delta);
+}
+
+/*
+ * Copy of struct ip_vs_seq
+ * From Aligned host order to unaligned network order
+ */
+static void hton_seq(struct ip_vs_seq *ho, struct ip_vs_seq *no)
+{
+	put_unaligned_be32(ho->init_seq, &no->init_seq);
+	put_unaligned_be32(ho->delta, &no->delta);
+	put_unaligned_be32(ho->previous_delta, &no->previous_delta);
+}
 
-static inline struct ip_vs_sync_buff *sb_dequeue(void)
+static inline struct ip_vs_sync_buff *sb_dequeue(struct netns_ipvs *ipvs)
 {
 	struct ip_vs_sync_buff *sb;
 
-	spin_lock_bh(&ip_vs_sync_lock);
-	if (list_empty(&ip_vs_sync_queue)) {
+	spin_lock_bh(&ipvs->sync_lock);
+	if (list_empty(&ipvs->sync_queue)) {
 		sb = NULL;
 	} else {
-		sb = list_entry(ip_vs_sync_queue.next,
+		sb = list_entry(ipvs->sync_queue.next,
 				struct ip_vs_sync_buff,
 				list);
 		list_del(&sb->list);
 	}
-	spin_unlock_bh(&ip_vs_sync_lock);
+	spin_unlock_bh(&ipvs->sync_lock);
 
 	return sb;
 }
 
-static inline struct ip_vs_sync_buff * ip_vs_sync_buff_create(void)
+/*
+ * Create a new sync buffer for Version 1 proto.
+ */
+static inline struct ip_vs_sync_buff *
+ip_vs_sync_buff_create(struct netns_ipvs *ipvs)
 {
 	struct ip_vs_sync_buff *sb;
 
 	if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC)))
 		return NULL;
 
-	if (!(sb->mesg=kmalloc(sync_send_mesg_maxlen, GFP_ATOMIC))) {
+	sb->mesg = kmalloc(ipvs->send_mesg_maxlen, GFP_ATOMIC);
+	if (!sb->mesg) {
 		kfree(sb);
 		return NULL;
 	}
+	sb->mesg->reserved = 0;  /* old nr_conns i.e. must be zeo now */
+	sb->mesg->version = SYNC_PROTO_VER;
+	sb->mesg->syncid = ipvs->master_syncid;
+	sb->mesg->size = sizeof(struct ip_vs_sync_mesg);
 	sb->mesg->nr_conns = 0;
-	sb->mesg->syncid = ip_vs_master_syncid;
-	sb->mesg->size = 4;
-	sb->head = (unsigned char *)sb->mesg + 4;
-	sb->end = (unsigned char *)sb->mesg + sync_send_mesg_maxlen;
+	sb->mesg->spare = 0;
+	sb->head = (unsigned char *)sb->mesg + sizeof(struct ip_vs_sync_mesg);
+	sb->end = (unsigned char *)sb->mesg + ipvs->send_mesg_maxlen;
+
 	sb->firstuse = jiffies;
 	return sb;
 }
@@ -201,14 +352,16 @@ static inline void ip_vs_sync_buff_release(struct ip_vs_sync_buff *sb)
 	kfree(sb);
 }
 
-static inline void sb_queue_tail(struct ip_vs_sync_buff *sb)
+static inline void sb_queue_tail(struct netns_ipvs *ipvs)
 {
-	spin_lock(&ip_vs_sync_lock);
-	if (ip_vs_sync_state & IP_VS_STATE_MASTER)
-		list_add_tail(&sb->list, &ip_vs_sync_queue);
+	struct ip_vs_sync_buff *sb = ipvs->sync_buff;
+
+	spin_lock(&ipvs->sync_lock);
+	if (ipvs->sync_state & IP_VS_STATE_MASTER)
+		list_add_tail(&sb->list, &ipvs->sync_queue);
 	else
 		ip_vs_sync_buff_release(sb);
-	spin_unlock(&ip_vs_sync_lock);
+	spin_unlock(&ipvs->sync_lock);
 }
 
 /*
@@ -216,36 +369,101 @@ static inline void sb_queue_tail(struct ip_vs_sync_buff *sb)
  *	than the specified time or the specified time is zero.
  */
 static inline struct ip_vs_sync_buff *
-get_curr_sync_buff(unsigned long time)
+get_curr_sync_buff(struct netns_ipvs *ipvs, unsigned long time)
 {
 	struct ip_vs_sync_buff *sb;
 
-	spin_lock_bh(&curr_sb_lock);
-	if (curr_sb && (time == 0 ||
-			time_before(jiffies - curr_sb->firstuse, time))) {
-		sb = curr_sb;
-		curr_sb = NULL;
+	spin_lock_bh(&ipvs->sync_buff_lock);
+	if (ipvs->sync_buff &&
+	    time_after_eq(jiffies - ipvs->sync_buff->firstuse, time)) {
+		sb = ipvs->sync_buff;
+		ipvs->sync_buff = NULL;
 	} else
 		sb = NULL;
-	spin_unlock_bh(&curr_sb_lock);
+	spin_unlock_bh(&ipvs->sync_buff_lock);
 	return sb;
 }
 
+/*
+ * Switch mode from sending version 0 or 1
+ *  - must handle sync_buf
+ */
+void ip_vs_sync_switch_mode(struct net *net, int mode)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	if (!(ipvs->sync_state & IP_VS_STATE_MASTER))
+		return;
+	if (mode == sysctl_sync_ver(ipvs) || !ipvs->sync_buff)
+		return;
+
+	spin_lock_bh(&ipvs->sync_buff_lock);
+	/* Buffer empty ? then let buf_create do the job  */
+	if (ipvs->sync_buff->mesg->size <=  sizeof(struct ip_vs_sync_mesg)) {
+		kfree(ipvs->sync_buff);
+		ipvs->sync_buff = NULL;
+	} else {
+		spin_lock_bh(&ipvs->sync_lock);
+		if (ipvs->sync_state & IP_VS_STATE_MASTER)
+			list_add_tail(&ipvs->sync_buff->list,
+				      &ipvs->sync_queue);
+		else
+			ip_vs_sync_buff_release(ipvs->sync_buff);
+		spin_unlock_bh(&ipvs->sync_lock);
+	}
+	spin_unlock_bh(&ipvs->sync_buff_lock);
+}
 
 /*
+ * Create a new sync buffer for Version 0 proto.
+ */
+static inline struct ip_vs_sync_buff *
+ip_vs_sync_buff_create_v0(struct netns_ipvs *ipvs)
+{
+	struct ip_vs_sync_buff *sb;
+	struct ip_vs_sync_mesg_v0 *mesg;
+
+	if (!(sb=kmalloc(sizeof(struct ip_vs_sync_buff), GFP_ATOMIC)))
+		return NULL;
+
+	sb->mesg = kmalloc(ipvs->send_mesg_maxlen, GFP_ATOMIC);
+	if (!sb->mesg) {
+		kfree(sb);
+		return NULL;
+	}
+	mesg = (struct ip_vs_sync_mesg_v0 *)sb->mesg;
+	mesg->nr_conns = 0;
+	mesg->syncid = ipvs->master_syncid;
+	mesg->size = sizeof(struct ip_vs_sync_mesg_v0);
+	sb->head = (unsigned char *)mesg + sizeof(struct ip_vs_sync_mesg_v0);
+	sb->end = (unsigned char *)mesg + ipvs->send_mesg_maxlen;
+	sb->firstuse = jiffies;
+	return sb;
+}
+
+/*
+ *      Version 0 , could be switched in by sys_ctl.
  *      Add an ip_vs_conn information into the current sync_buff.
- *      Called by ip_vs_in.
  */
-void ip_vs_sync_conn(struct ip_vs_conn *cp)
+void ip_vs_sync_conn_v0(struct net *net, struct ip_vs_conn *cp)
 {
-	struct ip_vs_sync_mesg *m;
-	struct ip_vs_sync_conn *s;
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_sync_mesg_v0 *m;
+	struct ip_vs_sync_conn_v0 *s;
 	int len;
 
-	spin_lock(&curr_sb_lock);
-	if (!curr_sb) {
-		if (!(curr_sb=ip_vs_sync_buff_create())) {
-			spin_unlock(&curr_sb_lock);
+	if (unlikely(cp->af != AF_INET))
+		return;
+	/* Do not sync ONE PACKET */
+	if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
+		return;
+
+	spin_lock(&ipvs->sync_buff_lock);
+	if (!ipvs->sync_buff) {
+		ipvs->sync_buff =
+			ip_vs_sync_buff_create_v0(ipvs);
+		if (!ipvs->sync_buff) {
+			spin_unlock(&ipvs->sync_buff_lock);
 			pr_err("ip_vs_sync_buff_create failed.\n");
 			return;
 		}
@@ -253,10 +471,11 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp)
 
 	len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE :
 		SIMPLE_CONN_SIZE;
-	m = curr_sb->mesg;
-	s = (struct ip_vs_sync_conn *)curr_sb->head;
+	m = (struct ip_vs_sync_mesg_v0 *)ipvs->sync_buff->mesg;
+	s = (struct ip_vs_sync_conn_v0 *)ipvs->sync_buff->head;
 
 	/* copy members */
+	s->reserved = 0;
 	s->protocol = cp->protocol;
 	s->cport = cp->cport;
 	s->vport = cp->vport;
@@ -274,83 +493,365 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp)
 
 	m->nr_conns++;
 	m->size += len;
-	curr_sb->head += len;
+	ipvs->sync_buff->head += len;
 
 	/* check if there is a space for next one */
-	if (curr_sb->head+FULL_CONN_SIZE > curr_sb->end) {
-		sb_queue_tail(curr_sb);
-		curr_sb = NULL;
+	if (ipvs->sync_buff->head + FULL_CONN_SIZE > ipvs->sync_buff->end) {
+		sb_queue_tail(ipvs);
+		ipvs->sync_buff = NULL;
 	}
-	spin_unlock(&curr_sb_lock);
+	spin_unlock(&ipvs->sync_buff_lock);
 
 	/* synchronize its controller if it has */
 	if (cp->control)
-		ip_vs_sync_conn(cp->control);
+		ip_vs_sync_conn(net, cp->control);
+}
+
+/*
+ *      Add an ip_vs_conn information into the current sync_buff.
+ *      Called by ip_vs_in.
+ *      Sending Version 1 messages
+ */
+void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_sync_mesg *m;
+	union ip_vs_sync_conn *s;
+	__u8 *p;
+	unsigned int len, pe_name_len, pad;
+
+	/* Handle old version of the protocol */
+	if (sysctl_sync_ver(ipvs) == 0) {
+		ip_vs_sync_conn_v0(net, cp);
+		return;
+	}
+	/* Do not sync ONE PACKET */
+	if (cp->flags & IP_VS_CONN_F_ONE_PACKET)
+		goto control;
+sloop:
+	/* Sanity checks */
+	pe_name_len = 0;
+	if (cp->pe_data_len) {
+		if (!cp->pe_data || !cp->dest) {
+			IP_VS_ERR_RL("SYNC, connection pe_data invalid\n");
+			return;
+		}
+		pe_name_len = strnlen(cp->pe->name, IP_VS_PENAME_MAXLEN);
+	}
+
+	spin_lock(&ipvs->sync_buff_lock);
+
+#ifdef CONFIG_IP_VS_IPV6
+	if (cp->af == AF_INET6)
+		len = sizeof(struct ip_vs_sync_v6);
+	else
+#endif
+		len = sizeof(struct ip_vs_sync_v4);
+
+	if (cp->flags & IP_VS_CONN_F_SEQ_MASK)
+		len += sizeof(struct ip_vs_sync_conn_options) + 2;
+
+	if (cp->pe_data_len)
+		len += cp->pe_data_len + 2;	/* + Param hdr field */
+	if (pe_name_len)
+		len += pe_name_len + 2;
+
+	/* check if there is a space for this one  */
+	pad = 0;
+	if (ipvs->sync_buff) {
+		pad = (4 - (size_t)ipvs->sync_buff->head) & 3;
+		if (ipvs->sync_buff->head + len + pad > ipvs->sync_buff->end) {
+			sb_queue_tail(ipvs);
+			ipvs->sync_buff = NULL;
+			pad = 0;
+		}
+	}
+
+	if (!ipvs->sync_buff) {
+		ipvs->sync_buff = ip_vs_sync_buff_create(ipvs);
+		if (!ipvs->sync_buff) {
+			spin_unlock(&ipvs->sync_buff_lock);
+			pr_err("ip_vs_sync_buff_create failed.\n");
+			return;
+		}
+	}
+
+	m = ipvs->sync_buff->mesg;
+	p = ipvs->sync_buff->head;
+	ipvs->sync_buff->head += pad + len;
+	m->size += pad + len;
+	/* Add ev. padding from prev. sync_conn */
+	while (pad--)
+		*(p++) = 0;
+
+	s = (union ip_vs_sync_conn *)p;
+
+	/* Set message type  & copy members */
+	s->v4.type = (cp->af == AF_INET6 ? STYPE_F_INET6 : 0);
+	s->v4.ver_size = htons(len & SVER_MASK);	/* Version 0 */
+	s->v4.flags = htonl(cp->flags & ~IP_VS_CONN_F_HASHED);
+	s->v4.state = htons(cp->state);
+	s->v4.protocol = cp->protocol;
+	s->v4.cport = cp->cport;
+	s->v4.vport = cp->vport;
+	s->v4.dport = cp->dport;
+	s->v4.fwmark = htonl(cp->fwmark);
+	s->v4.timeout = htonl(cp->timeout / HZ);
+	m->nr_conns++;
+
+#ifdef CONFIG_IP_VS_IPV6
+	if (cp->af == AF_INET6) {
+		p += sizeof(struct ip_vs_sync_v6);
+		ipv6_addr_copy(&s->v6.caddr, &cp->caddr.in6);
+		ipv6_addr_copy(&s->v6.vaddr, &cp->vaddr.in6);
+		ipv6_addr_copy(&s->v6.daddr, &cp->daddr.in6);
+	} else
+#endif
+	{
+		p += sizeof(struct ip_vs_sync_v4);	/* options ptr */
+		s->v4.caddr = cp->caddr.ip;
+		s->v4.vaddr = cp->vaddr.ip;
+		s->v4.daddr = cp->daddr.ip;
+	}
+	if (cp->flags & IP_VS_CONN_F_SEQ_MASK) {
+		*(p++) = IPVS_OPT_SEQ_DATA;
+		*(p++) = sizeof(struct ip_vs_sync_conn_options);
+		hton_seq((struct ip_vs_seq *)p, &cp->in_seq);
+		p += sizeof(struct ip_vs_seq);
+		hton_seq((struct ip_vs_seq *)p, &cp->out_seq);
+		p += sizeof(struct ip_vs_seq);
+	}
+	/* Handle pe data */
+	if (cp->pe_data_len && cp->pe_data) {
+		*(p++) = IPVS_OPT_PE_DATA;
+		*(p++) = cp->pe_data_len;
+		memcpy(p, cp->pe_data, cp->pe_data_len);
+		p += cp->pe_data_len;
+		if (pe_name_len) {
+			/* Add PE_NAME */
+			*(p++) = IPVS_OPT_PE_NAME;
+			*(p++) = pe_name_len;
+			memcpy(p, cp->pe->name, pe_name_len);
+			p += pe_name_len;
+		}
+	}
+
+	spin_unlock(&ipvs->sync_buff_lock);
+
+control:
+	/* synchronize its controller if it has */
+	cp = cp->control;
+	if (!cp)
+		return;
+	/*
+	 * Reduce sync rate for templates
+	 * i.e only increment in_pkts for Templates.
+	 */
+	if (cp->flags & IP_VS_CONN_F_TEMPLATE) {
+		int pkts = atomic_add_return(1, &cp->in_pkts);
+
+		if (pkts % sysctl_sync_period(ipvs) != 1)
+			return;
+	}
+	goto sloop;
 }
 
+/*
+ *  fill_param used by version 1
+ */
 static inline int
-ip_vs_conn_fill_param_sync(int af, int protocol,
-			   const union nf_inet_addr *caddr, __be16 cport,
-			   const union nf_inet_addr *vaddr, __be16 vport,
-			   struct ip_vs_conn_param *p)
+ip_vs_conn_fill_param_sync(struct net *net, int af, union ip_vs_sync_conn *sc,
+			   struct ip_vs_conn_param *p,
+			   __u8 *pe_data, unsigned int pe_data_len,
+			   __u8 *pe_name, unsigned int pe_name_len)
 {
-	/* XXX: Need to take into account persistence engine */
-	ip_vs_conn_fill_param(af, protocol, caddr, cport, vaddr, vport, p);
+#ifdef CONFIG_IP_VS_IPV6
+	if (af == AF_INET6)
+		ip_vs_conn_fill_param(net, af, sc->v6.protocol,
+				      (const union nf_inet_addr *)&sc->v6.caddr,
+				      sc->v6.cport,
+				      (const union nf_inet_addr *)&sc->v6.vaddr,
+				      sc->v6.vport, p);
+	else
+#endif
+		ip_vs_conn_fill_param(net, af, sc->v4.protocol,
+				      (const union nf_inet_addr *)&sc->v4.caddr,
+				      sc->v4.cport,
+				      (const union nf_inet_addr *)&sc->v4.vaddr,
+				      sc->v4.vport, p);
+	/* Handle pe data */
+	if (pe_data_len) {
+		if (pe_name_len) {
+			char buff[IP_VS_PENAME_MAXLEN+1];
+
+			memcpy(buff, pe_name, pe_name_len);
+			buff[pe_name_len]=0;
+			p->pe = __ip_vs_pe_getbyname(buff);
+			if (!p->pe) {
+				IP_VS_DBG(3, "BACKUP, no %s engine found/loaded\n",
+					     buff);
+				return 1;
+			}
+		} else {
+			IP_VS_ERR_RL("BACKUP, Invalid PE parameters\n");
+			return 1;
+		}
+
+		p->pe_data = kmemdup(pe_data, pe_data_len, GFP_ATOMIC);
+		if (!p->pe_data) {
+			if (p->pe->module)
+				module_put(p->pe->module);
+			return -ENOMEM;
+		}
+		p->pe_data_len = pe_data_len;
+	}
 	return 0;
 }
 
 /*
- *      Process received multicast message and create the corresponding
- *      ip_vs_conn entries.
+ *  Connection Add / Update.
+ *  Common for version 0 and 1 reception of backup sync_conns.
+ *  Param: ...
+ *         timeout is in sec.
  */
-static void ip_vs_process_message(const char *buffer, const size_t buflen)
+static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
+			    unsigned int flags, unsigned int state,
+			    unsigned int protocol, unsigned int type,
+			    const union nf_inet_addr *daddr, __be16 dport,
+			    unsigned long timeout, __u32 fwmark,
+			    struct ip_vs_sync_conn_options *opt)
 {
-	struct ip_vs_sync_mesg *m = (struct ip_vs_sync_mesg *)buffer;
-	struct ip_vs_sync_conn *s;
-	struct ip_vs_sync_conn_options *opt;
-	struct ip_vs_conn *cp;
-	struct ip_vs_protocol *pp;
 	struct ip_vs_dest *dest;
-	struct ip_vs_conn_param param;
-	char *p;
-	int i;
+	struct ip_vs_conn *cp;
+	struct netns_ipvs *ipvs = net_ipvs(net);
 
-	if (buflen < sizeof(struct ip_vs_sync_mesg)) {
-		IP_VS_ERR_RL("sync message header too short\n");
-		return;
-	}
+	if (!(flags & IP_VS_CONN_F_TEMPLATE))
+		cp = ip_vs_conn_in_get(param);
+	else
+		cp = ip_vs_ct_in_get(param);
 
-	/* Convert size back to host byte order */
-	m->size = ntohs(m->size);
+	if (cp && param->pe_data) 	/* Free pe_data */
+		kfree(param->pe_data);
+	if (!cp) {
+		/*
+		 * Find the appropriate destination for the connection.
+		 * If it is not found the connection will remain unbound
+		 * but still handled.
+		 */
+		dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr,
+				       param->vport, protocol, fwmark);
 
-	if (buflen != m->size) {
-		IP_VS_ERR_RL("bogus sync message size\n");
-		return;
+		/*  Set the approprite ativity flag */
+		if (protocol == IPPROTO_TCP) {
+			if (state != IP_VS_TCP_S_ESTABLISHED)
+				flags |= IP_VS_CONN_F_INACTIVE;
+			else
+				flags &= ~IP_VS_CONN_F_INACTIVE;
+		} else if (protocol == IPPROTO_SCTP) {
+			if (state != IP_VS_SCTP_S_ESTABLISHED)
+				flags |= IP_VS_CONN_F_INACTIVE;
+			else
+				flags &= ~IP_VS_CONN_F_INACTIVE;
+		}
+		cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark);
+		if (dest)
+			atomic_dec(&dest->refcnt);
+		if (!cp) {
+			if (param->pe_data)
+				kfree(param->pe_data);
+			IP_VS_DBG(2, "BACKUP, add new conn. failed\n");
+			return;
+		}
+	} else if (!cp->dest) {
+		dest = ip_vs_try_bind_dest(cp);
+		if (dest)
+			atomic_dec(&dest->refcnt);
+	} else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) &&
+		(cp->state != state)) {
+		/* update active/inactive flag for the connection */
+		dest = cp->dest;
+		if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
+			(state != IP_VS_TCP_S_ESTABLISHED)) {
+			atomic_dec(&dest->activeconns);
+			atomic_inc(&dest->inactconns);
+			cp->flags |= IP_VS_CONN_F_INACTIVE;
+		} else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
+			(state == IP_VS_TCP_S_ESTABLISHED)) {
+			atomic_inc(&dest->activeconns);
+			atomic_dec(&dest->inactconns);
+			cp->flags &= ~IP_VS_CONN_F_INACTIVE;
+		}
+	} else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) &&
+		(cp->state != state)) {
+		dest = cp->dest;
+		if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
+		(state != IP_VS_SCTP_S_ESTABLISHED)) {
+			atomic_dec(&dest->activeconns);
+			atomic_inc(&dest->inactconns);
+			cp->flags &= ~IP_VS_CONN_F_INACTIVE;
+		}
 	}
 
-	/* SyncID sanity check */
-	if (ip_vs_backup_syncid != 0 && m->syncid != ip_vs_backup_syncid) {
-		IP_VS_DBG(7, "Ignoring incoming msg with syncid = %d\n",
-			  m->syncid);
-		return;
+	if (opt)
+		memcpy(&cp->in_seq, opt, sizeof(*opt));
+	atomic_set(&cp->in_pkts, sysctl_sync_threshold(ipvs));
+	cp->state = state;
+	cp->old_state = cp->state;
+	/*
+	 * For Ver 0 messages style
+	 *  - Not possible to recover the right timeout for templates
+	 *  - can not find the right fwmark
+	 *    virtual service. If needed, we can do it for
+	 *    non-fwmark persistent services.
+	 * Ver 1 messages style.
+	 *  - No problem.
+	 */
+	if (timeout) {
+		if (timeout > MAX_SCHEDULE_TIMEOUT / HZ)
+			timeout = MAX_SCHEDULE_TIMEOUT / HZ;
+		cp->timeout = timeout*HZ;
+	} else {
+		struct ip_vs_proto_data *pd;
+
+		pd = ip_vs_proto_data_get(net, protocol);
+		if (!(flags & IP_VS_CONN_F_TEMPLATE) && pd && pd->timeout_table)
+			cp->timeout = pd->timeout_table[state];
+		else
+			cp->timeout = (3*60*HZ);
 	}
+	ip_vs_conn_put(cp);
+}
 
-	p = (char *)buffer + sizeof(struct ip_vs_sync_mesg);
+/*
+ *  Process received multicast message for Version 0
+ */
+static void ip_vs_process_message_v0(struct net *net, const char *buffer,
+				     const size_t buflen)
+{
+	struct ip_vs_sync_mesg_v0 *m = (struct ip_vs_sync_mesg_v0 *)buffer;
+	struct ip_vs_sync_conn_v0 *s;
+	struct ip_vs_sync_conn_options *opt;
+	struct ip_vs_protocol *pp;
+	struct ip_vs_conn_param param;
+	char *p;
+	int i;
+
+	p = (char *)buffer + sizeof(struct ip_vs_sync_mesg_v0);
 	for (i=0; i<m->nr_conns; i++) {
 		unsigned flags, state;
 
 		if (p + SIMPLE_CONN_SIZE > buffer+buflen) {
-			IP_VS_ERR_RL("bogus conn in sync message\n");
+			IP_VS_ERR_RL("BACKUP v0, bogus conn\n");
 			return;
 		}
-		s = (struct ip_vs_sync_conn *) p;
+		s = (struct ip_vs_sync_conn_v0 *) p;
 		flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC;
 		flags &= ~IP_VS_CONN_F_HASHED;
 		if (flags & IP_VS_CONN_F_SEQ_MASK) {
 			opt = (struct ip_vs_sync_conn_options *)&s[1];
 			p += FULL_CONN_SIZE;
 			if (p > buffer+buflen) {
-				IP_VS_ERR_RL("bogus conn options in sync message\n");
+				IP_VS_ERR_RL("BACKUP v0, Dropping buffer bogus conn options\n");
 				return;
 			}
 		} else {
@@ -362,118 +863,286 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
 		if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
 			pp = ip_vs_proto_get(s->protocol);
 			if (!pp) {
-				IP_VS_ERR_RL("Unsupported protocol %u in sync msg\n",
+				IP_VS_DBG(2, "BACKUP v0, Unsupported protocol %u\n",
 					s->protocol);
 				continue;
 			}
 			if (state >= pp->num_states) {
-				IP_VS_DBG(2, "Invalid %s state %u in sync msg\n",
+				IP_VS_DBG(2, "BACKUP v0, Invalid %s state %u\n",
 					pp->name, state);
 				continue;
 			}
 		} else {
 			/* protocol in templates is not used for state/timeout */
-			pp = NULL;
 			if (state > 0) {
-				IP_VS_DBG(2, "Invalid template state %u in sync msg\n",
+				IP_VS_DBG(2, "BACKUP v0, Invalid template state %u\n",
 					state);
 				state = 0;
 			}
 		}
 
-		{
-			if (ip_vs_conn_fill_param_sync(AF_INET, s->protocol,
-					      (union nf_inet_addr *)&s->caddr,
-					      s->cport,
-					      (union nf_inet_addr *)&s->vaddr,
-					      s->vport, &param)) {
-				pr_err("ip_vs_conn_fill_param_sync failed");
-				return;
+		ip_vs_conn_fill_param(net, AF_INET, s->protocol,
+				      (const union nf_inet_addr *)&s->caddr,
+				      s->cport,
+				      (const union nf_inet_addr *)&s->vaddr,
+				      s->vport, &param);
+
+		/* Send timeout as Zero */
+		ip_vs_proc_conn(net, &param, flags, state, s->protocol, AF_INET,
+				(union nf_inet_addr *)&s->daddr, s->dport,
+				0, 0, opt);
+	}
+}
+
+/*
+ * Handle options
+ */
+static inline int ip_vs_proc_seqopt(__u8 *p, unsigned int plen,
+				    __u32 *opt_flags,
+				    struct ip_vs_sync_conn_options *opt)
+{
+	struct ip_vs_sync_conn_options *topt;
+
+	topt = (struct ip_vs_sync_conn_options *)p;
+
+	if (plen != sizeof(struct ip_vs_sync_conn_options)) {
+		IP_VS_DBG(2, "BACKUP, bogus conn options length\n");
+		return -EINVAL;
+	}
+	if (*opt_flags & IPVS_OPT_F_SEQ_DATA) {
+		IP_VS_DBG(2, "BACKUP, conn options found twice\n");
+		return -EINVAL;
+	}
+	ntoh_seq(&topt->in_seq, &opt->in_seq);
+	ntoh_seq(&topt->out_seq, &opt->out_seq);
+	*opt_flags |= IPVS_OPT_F_SEQ_DATA;
+	return 0;
+}
+
+static int ip_vs_proc_str(__u8 *p, unsigned int plen, unsigned int *data_len,
+			  __u8 **data, unsigned int maxlen,
+			  __u32 *opt_flags, __u32 flag)
+{
+	if (plen > maxlen) {
+		IP_VS_DBG(2, "BACKUP, bogus par.data len > %d\n", maxlen);
+		return -EINVAL;
+	}
+	if (*opt_flags & flag) {
+		IP_VS_DBG(2, "BACKUP, Par.data found twice 0x%x\n", flag);
+		return -EINVAL;
+	}
+	*data_len = plen;
+	*data = p;
+	*opt_flags |= flag;
+	return 0;
+}
+/*
+ *   Process a Version 1 sync. connection
+ */
+static inline int ip_vs_proc_sync_conn(struct net *net, __u8 *p, __u8 *msg_end)
+{
+	struct ip_vs_sync_conn_options opt;
+	union  ip_vs_sync_conn *s;
+	struct ip_vs_protocol *pp;
+	struct ip_vs_conn_param param;
+	__u32 flags;
+	unsigned int af, state, pe_data_len=0, pe_name_len=0;
+	__u8 *pe_data=NULL, *pe_name=NULL;
+	__u32 opt_flags=0;
+	int retc=0;
+
+	s = (union ip_vs_sync_conn *) p;
+
+	if (s->v6.type & STYPE_F_INET6) {
+#ifdef CONFIG_IP_VS_IPV6
+		af = AF_INET6;
+		p += sizeof(struct ip_vs_sync_v6);
+#else
+		IP_VS_DBG(3,"BACKUP, IPv6 msg received, and IPVS is not compiled for IPv6\n");
+		retc = 10;
+		goto out;
+#endif
+	} else if (!s->v4.type) {
+		af = AF_INET;
+		p += sizeof(struct ip_vs_sync_v4);
+	} else {
+		return -10;
+	}
+	if (p > msg_end)
+		return -20;
+
+	/* Process optional params check Type & Len. */
+	while (p < msg_end) {
+		int ptype;
+		int plen;
+
+		if (p+2 > msg_end)
+			return -30;
+		ptype = *(p++);
+		plen  = *(p++);
+
+		if (!plen || ((p + plen) > msg_end))
+			return -40;
+		/* Handle seq option  p = param data */
+		switch (ptype & ~IPVS_OPT_F_PARAM) {
+		case IPVS_OPT_SEQ_DATA:
+			if (ip_vs_proc_seqopt(p, plen, &opt_flags, &opt))
+				return -50;
+			break;
+
+		case IPVS_OPT_PE_DATA:
+			if (ip_vs_proc_str(p, plen, &pe_data_len, &pe_data,
+					   IP_VS_PEDATA_MAXLEN, &opt_flags,
+					   IPVS_OPT_F_PE_DATA))
+				return -60;
+			break;
+
+		case IPVS_OPT_PE_NAME:
+			if (ip_vs_proc_str(p, plen,&pe_name_len, &pe_name,
+					   IP_VS_PENAME_MAXLEN, &opt_flags,
+					   IPVS_OPT_F_PE_NAME))
+				return -70;
+			break;
+
+		default:
+			/* Param data mandatory ? */
+			if (!(ptype & IPVS_OPT_F_PARAM)) {
+				IP_VS_DBG(3, "BACKUP, Unknown mandatory param %d found\n",
+					  ptype & ~IPVS_OPT_F_PARAM);
+				retc = 20;
+				goto out;
 			}
-			if (!(flags & IP_VS_CONN_F_TEMPLATE))
-				cp = ip_vs_conn_in_get(&param);
-			else
-				cp = ip_vs_ct_in_get(&param);
 		}
-		if (!cp) {
-			/*
-			 * Find the appropriate destination for the connection.
-			 * If it is not found the connection will remain unbound
-			 * but still handled.
-			 */
-			dest = ip_vs_find_dest(AF_INET,
-					       (union nf_inet_addr *)&s->daddr,
-					       s->dport,
-					       (union nf_inet_addr *)&s->vaddr,
-					       s->vport,
-					       s->protocol);
-			/*  Set the approprite ativity flag */
-			if (s->protocol == IPPROTO_TCP) {
-				if (state != IP_VS_TCP_S_ESTABLISHED)
-					flags |= IP_VS_CONN_F_INACTIVE;
-				else
-					flags &= ~IP_VS_CONN_F_INACTIVE;
-			} else if (s->protocol == IPPROTO_SCTP) {
-				if (state != IP_VS_SCTP_S_ESTABLISHED)
-					flags |= IP_VS_CONN_F_INACTIVE;
-				else
-					flags &= ~IP_VS_CONN_F_INACTIVE;
+		p += plen;  /* Next option */
+	}
+
+	/* Get flags and Mask off unsupported */
+	flags  = ntohl(s->v4.flags) & IP_VS_CONN_F_BACKUP_MASK;
+	flags |= IP_VS_CONN_F_SYNC;
+	state = ntohs(s->v4.state);
+
+	if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
+		pp = ip_vs_proto_get(s->v4.protocol);
+		if (!pp) {
+			IP_VS_DBG(3,"BACKUP, Unsupported protocol %u\n",
+				s->v4.protocol);
+			retc = 30;
+			goto out;
+		}
+		if (state >= pp->num_states) {
+			IP_VS_DBG(3, "BACKUP, Invalid %s state %u\n",
+				pp->name, state);
+			retc = 40;
+			goto out;
+		}
+	} else {
+		/* protocol in templates is not used for state/timeout */
+		if (state > 0) {
+			IP_VS_DBG(3, "BACKUP, Invalid template state %u\n",
+				state);
+			state = 0;
+		}
+	}
+	if (ip_vs_conn_fill_param_sync(net, af, s, &param, pe_data,
+				       pe_data_len, pe_name, pe_name_len)) {
+		retc = 50;
+		goto out;
+	}
+	/* If only IPv4, just silent skip IPv6 */
+	if (af == AF_INET)
+		ip_vs_proc_conn(net, &param, flags, state, s->v4.protocol, af,
+				(union nf_inet_addr *)&s->v4.daddr, s->v4.dport,
+				ntohl(s->v4.timeout), ntohl(s->v4.fwmark),
+				(opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL)
+				);
+#ifdef CONFIG_IP_VS_IPV6
+	else
+		ip_vs_proc_conn(net, &param, flags, state, s->v6.protocol, af,
+				(union nf_inet_addr *)&s->v6.daddr, s->v6.dport,
+				ntohl(s->v6.timeout), ntohl(s->v6.fwmark),
+				(opt_flags & IPVS_OPT_F_SEQ_DATA ? &opt : NULL)
+				);
+#endif
+	return 0;
+	/* Error exit */
+out:
+	IP_VS_DBG(2, "BACKUP, Single msg dropped err:%d\n", retc);
+	return retc;
+
+}
+/*
+ *      Process received multicast message and create the corresponding
+ *      ip_vs_conn entries.
+ *      Handles Version 0 & 1
+ */
+static void ip_vs_process_message(struct net *net, __u8 *buffer,
+				  const size_t buflen)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+	struct ip_vs_sync_mesg *m2 = (struct ip_vs_sync_mesg *)buffer;
+	__u8 *p, *msg_end;
+	int i, nr_conns;
+
+	if (buflen < sizeof(struct ip_vs_sync_mesg_v0)) {
+		IP_VS_DBG(2, "BACKUP, message header too short\n");
+		return;
+	}
+	/* Convert size back to host byte order */
+	m2->size = ntohs(m2->size);
+
+	if (buflen != m2->size) {
+		IP_VS_DBG(2, "BACKUP, bogus message size\n");
+		return;
+	}
+	/* SyncID sanity check */
+	if (ipvs->backup_syncid != 0 && m2->syncid != ipvs->backup_syncid) {
+		IP_VS_DBG(7, "BACKUP, Ignoring syncid = %d\n", m2->syncid);
+		return;
+	}
+	/* Handle version 1  message */
+	if ((m2->version == SYNC_PROTO_VER) && (m2->reserved == 0)
+	    && (m2->spare == 0)) {
+
+		msg_end = buffer + sizeof(struct ip_vs_sync_mesg);
+		nr_conns = m2->nr_conns;
+
+		for (i=0; i<nr_conns; i++) {
+			union ip_vs_sync_conn *s;
+			unsigned size;
+			int retc;
+
+			p = msg_end;
+			if (p + sizeof(s->v4) > buffer+buflen) {
+				IP_VS_ERR_RL("BACKUP, Dropping buffer, to small\n");
+				return;
 			}
-			cp = ip_vs_conn_new(&param,
-					    (union nf_inet_addr *)&s->daddr,
-					    s->dport, flags, dest);
-			if (dest)
-				atomic_dec(&dest->refcnt);
-			if (!cp) {
-				pr_err("ip_vs_conn_new failed\n");
+			s = (union ip_vs_sync_conn *)p;
+			size = ntohs(s->v4.ver_size) & SVER_MASK;
+			msg_end = p + size;
+			/* Basic sanity checks */
+			if (msg_end  > buffer+buflen) {
+				IP_VS_ERR_RL("BACKUP, Dropping buffer, msg > buffer\n");
 				return;
 			}
-		} else if (!cp->dest) {
-			dest = ip_vs_try_bind_dest(cp);
-			if (dest)
-				atomic_dec(&dest->refcnt);
-		} else if ((cp->dest) && (cp->protocol == IPPROTO_TCP) &&
-			   (cp->state != state)) {
-			/* update active/inactive flag for the connection */
-			dest = cp->dest;
-			if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
-				(state != IP_VS_TCP_S_ESTABLISHED)) {
-				atomic_dec(&dest->activeconns);
-				atomic_inc(&dest->inactconns);
-				cp->flags |= IP_VS_CONN_F_INACTIVE;
-			} else if ((cp->flags & IP_VS_CONN_F_INACTIVE) &&
-				(state == IP_VS_TCP_S_ESTABLISHED)) {
-				atomic_inc(&dest->activeconns);
-				atomic_dec(&dest->inactconns);
-				cp->flags &= ~IP_VS_CONN_F_INACTIVE;
+			if (ntohs(s->v4.ver_size) >> SVER_SHIFT) {
+				IP_VS_ERR_RL("BACKUP, Dropping buffer, Unknown version %d\n",
+					      ntohs(s->v4.ver_size) >> SVER_SHIFT);
+				return;
 			}
-		} else if ((cp->dest) && (cp->protocol == IPPROTO_SCTP) &&
-			   (cp->state != state)) {
-			dest = cp->dest;
-			if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
-			     (state != IP_VS_SCTP_S_ESTABLISHED)) {
-			    atomic_dec(&dest->activeconns);
-			    atomic_inc(&dest->inactconns);
-			    cp->flags &= ~IP_VS_CONN_F_INACTIVE;
+			/* Process a single sync_conn */
+			retc = ip_vs_proc_sync_conn(net, p, msg_end);
+			if (retc < 0) {
+				IP_VS_ERR_RL("BACKUP, Dropping buffer, Err: %d in decoding\n",
+					     retc);
+				return;
 			}
+			/* Make sure we have 32 bit alignment */
+			msg_end = p + ((size + 3) & ~3);
 		}
-
-		if (opt)
-			memcpy(&cp->in_seq, opt, sizeof(*opt));
-		atomic_set(&cp->in_pkts, sysctl_ip_vs_sync_threshold[0]);
-		cp->state = state;
-		cp->old_state = cp->state;
-		/*
-		 * We can not recover the right timeout for templates
-		 * in all cases, we can not find the right fwmark
-		 * virtual service. If needed, we can do it for
-		 * non-fwmark persistent services.
-		 */
-		if (!(flags & IP_VS_CONN_F_TEMPLATE) && pp->timeout_table)
-			cp->timeout = pp->timeout_table[state];
-		else
-			cp->timeout = (3*60*HZ);
-		ip_vs_conn_put(cp);
+	} else {
+		/* Old type of message */
+		ip_vs_process_message_v0(net, buffer, buflen);
+		return;
 	}
 }
 
@@ -511,8 +1180,10 @@ static int set_mcast_if(struct sock *sk, char *ifname)
 {
 	struct net_device *dev;
 	struct inet_sock *inet = inet_sk(sk);
+	struct net *net = sock_net(sk);
 
-	if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
+	dev = __dev_get_by_name(net, ifname);
+	if (!dev)
 		return -ENODEV;
 
 	if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
@@ -531,30 +1202,33 @@ static int set_mcast_if(struct sock *sk, char *ifname)
  *	Set the maximum length of sync message according to the
  *	specified interface's MTU.
  */
-static int set_sync_mesg_maxlen(int sync_state)
+static int set_sync_mesg_maxlen(struct net *net, int sync_state)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	struct net_device *dev;
 	int num;
 
 	if (sync_state == IP_VS_STATE_MASTER) {
-		if ((dev = __dev_get_by_name(&init_net, ip_vs_master_mcast_ifn)) == NULL)
+		dev = __dev_get_by_name(net, ipvs->master_mcast_ifn);
+		if (!dev)
 			return -ENODEV;
 
 		num = (dev->mtu - sizeof(struct iphdr) -
 		       sizeof(struct udphdr) -
 		       SYNC_MESG_HEADER_LEN - 20) / SIMPLE_CONN_SIZE;
-		sync_send_mesg_maxlen = SYNC_MESG_HEADER_LEN +
+		ipvs->send_mesg_maxlen = SYNC_MESG_HEADER_LEN +
 			SIMPLE_CONN_SIZE * min(num, MAX_CONNS_PER_SYNCBUFF);
 		IP_VS_DBG(7, "setting the maximum length of sync sending "
-			  "message %d.\n", sync_send_mesg_maxlen);
+			  "message %d.\n", ipvs->send_mesg_maxlen);
 	} else if (sync_state == IP_VS_STATE_BACKUP) {
-		if ((dev = __dev_get_by_name(&init_net, ip_vs_backup_mcast_ifn)) == NULL)
+		dev = __dev_get_by_name(net, ipvs->backup_mcast_ifn);
+		if (!dev)
 			return -ENODEV;
 
-		sync_recv_mesg_maxlen = dev->mtu -
+		ipvs->recv_mesg_maxlen = dev->mtu -
 			sizeof(struct iphdr) - sizeof(struct udphdr);
 		IP_VS_DBG(7, "setting the maximum length of sync receiving "
-			  "message %d.\n", sync_recv_mesg_maxlen);
+			  "message %d.\n", ipvs->recv_mesg_maxlen);
 	}
 
 	return 0;
@@ -569,6 +1243,7 @@ static int set_sync_mesg_maxlen(int sync_state)
 static int
 join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
 {
+	struct net *net = sock_net(sk);
 	struct ip_mreqn mreq;
 	struct net_device *dev;
 	int ret;
@@ -576,7 +1251,8 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
 	memset(&mreq, 0, sizeof(mreq));
 	memcpy(&mreq.imr_multiaddr, addr, sizeof(struct in_addr));
 
-	if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
+	dev = __dev_get_by_name(net, ifname);
+	if (!dev)
 		return -ENODEV;
 	if (sk->sk_bound_dev_if && dev->ifindex != sk->sk_bound_dev_if)
 		return -EINVAL;
@@ -593,11 +1269,13 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
 
 static int bind_mcastif_addr(struct socket *sock, char *ifname)
 {
+	struct net *net = sock_net(sock->sk);
 	struct net_device *dev;
 	__be32 addr;
 	struct sockaddr_in sin;
 
-	if ((dev = __dev_get_by_name(&init_net, ifname)) == NULL)
+	dev = __dev_get_by_name(net, ifname);
+	if (!dev)
 		return -ENODEV;
 
 	addr = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE);
@@ -619,19 +1297,20 @@ static int bind_mcastif_addr(struct socket *sock, char *ifname)
 /*
  *      Set up sending multicast socket over UDP
  */
-static struct socket * make_send_sock(void)
+static struct socket *make_send_sock(struct net *net)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	struct socket *sock;
 	int result;
 
 	/* First create a socket */
-	result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+	result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
 	if (result < 0) {
 		pr_err("Error during creation of socket; terminating\n");
 		return ERR_PTR(result);
 	}
 
-	result = set_mcast_if(sock->sk, ip_vs_master_mcast_ifn);
+	result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn);
 	if (result < 0) {
 		pr_err("Error setting outbound mcast interface\n");
 		goto error;
@@ -640,7 +1319,7 @@ static struct socket * make_send_sock(void)
 	set_mcast_loop(sock->sk, 0);
 	set_mcast_ttl(sock->sk, 1);
 
-	result = bind_mcastif_addr(sock, ip_vs_master_mcast_ifn);
+	result = bind_mcastif_addr(sock, ipvs->master_mcast_ifn);
 	if (result < 0) {
 		pr_err("Error binding address of the mcast interface\n");
 		goto error;
@@ -664,13 +1343,14 @@ static struct socket * make_send_sock(void)
 /*
  *      Set up receiving multicast socket over UDP
  */
-static struct socket * make_receive_sock(void)
+static struct socket *make_receive_sock(struct net *net)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	struct socket *sock;
 	int result;
 
 	/* First create a socket */
-	result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
+	result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1);
 	if (result < 0) {
 		pr_err("Error during creation of socket; terminating\n");
 		return ERR_PTR(result);
@@ -689,7 +1369,7 @@ static struct socket * make_receive_sock(void)
 	/* join the multicast group */
 	result = join_mcast_group(sock->sk,
 			(struct in_addr *) &mcast_addr.sin_addr,
-			ip_vs_backup_mcast_ifn);
+			ipvs->backup_mcast_ifn);
 	if (result < 0) {
 		pr_err("Error joining to the multicast group\n");
 		goto error;
@@ -760,20 +1440,21 @@ ip_vs_receive(struct socket *sock, char *buffer, const size_t buflen)
 static int sync_thread_master(void *data)
 {
 	struct ip_vs_sync_thread_data *tinfo = data;
+	struct netns_ipvs *ipvs = net_ipvs(tinfo->net);
 	struct ip_vs_sync_buff *sb;
 
 	pr_info("sync thread started: state = MASTER, mcast_ifn = %s, "
 		"syncid = %d\n",
-		ip_vs_master_mcast_ifn, ip_vs_master_syncid);
+		ipvs->master_mcast_ifn, ipvs->master_syncid);
 
 	while (!kthread_should_stop()) {
-		while ((sb = sb_dequeue())) {
+		while ((sb = sb_dequeue(ipvs))) {
 			ip_vs_send_sync_msg(tinfo->sock, sb->mesg);
 			ip_vs_sync_buff_release(sb);
 		}
 
-		/* check if entries stay in curr_sb for 2 seconds */
-		sb = get_curr_sync_buff(2 * HZ);
+		/* check if entries stay in ipvs->sync_buff for 2 seconds */
+		sb = get_curr_sync_buff(ipvs, 2 * HZ);
 		if (sb) {
 			ip_vs_send_sync_msg(tinfo->sock, sb->mesg);
 			ip_vs_sync_buff_release(sb);
@@ -783,14 +1464,13 @@ static int sync_thread_master(void *data)
 	}
 
 	/* clean up the sync_buff queue */
-	while ((sb=sb_dequeue())) {
+	while ((sb = sb_dequeue(ipvs)))
 		ip_vs_sync_buff_release(sb);
-	}
 
 	/* clean up the current sync_buff */
-	if ((sb = get_curr_sync_buff(0))) {
+	sb = get_curr_sync_buff(ipvs, 0);
+	if (sb)
 		ip_vs_sync_buff_release(sb);
-	}
 
 	/* release the sending multicast socket */
 	sock_release(tinfo->sock);
@@ -803,11 +1483,12 @@ static int sync_thread_master(void *data)
 static int sync_thread_backup(void *data)
 {
 	struct ip_vs_sync_thread_data *tinfo = data;
+	struct netns_ipvs *ipvs = net_ipvs(tinfo->net);
 	int len;
 
 	pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, "
 		"syncid = %d\n",
-		ip_vs_backup_mcast_ifn, ip_vs_backup_syncid);
+		ipvs->backup_mcast_ifn, ipvs->backup_syncid);
 
 	while (!kthread_should_stop()) {
 		wait_event_interruptible(*sk_sleep(tinfo->sock->sk),
@@ -817,7 +1498,7 @@ static int sync_thread_backup(void *data)
 		/* do we have data now? */
 		while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) {
 			len = ip_vs_receive(tinfo->sock, tinfo->buf,
-					sync_recv_mesg_maxlen);
+					ipvs->recv_mesg_maxlen);
 			if (len <= 0) {
 				pr_err("receiving message error\n");
 				break;
@@ -826,7 +1507,7 @@ static int sync_thread_backup(void *data)
 			/* disable bottom half, because it accesses the data
 			   shared by softirq while getting/creating conns */
 			local_bh_disable();
-			ip_vs_process_message(tinfo->buf, len);
+			ip_vs_process_message(tinfo->net, tinfo->buf, len);
 			local_bh_enable();
 		}
 	}
@@ -840,41 +1521,42 @@ static int sync_thread_backup(void *data)
 }
 
 
-int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
+int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid)
 {
 	struct ip_vs_sync_thread_data *tinfo;
 	struct task_struct **realtask, *task;
 	struct socket *sock;
+	struct netns_ipvs *ipvs = net_ipvs(net);
 	char *name, *buf = NULL;
 	int (*threadfn)(void *data);
 	int result = -ENOMEM;
 
 	IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
 	IP_VS_DBG(7, "Each ip_vs_sync_conn entry needs %Zd bytes\n",
-		  sizeof(struct ip_vs_sync_conn));
+		  sizeof(struct ip_vs_sync_conn_v0));
 
 	if (state == IP_VS_STATE_MASTER) {
-		if (sync_master_thread)
+		if (ipvs->master_thread)
 			return -EEXIST;
 
-		strlcpy(ip_vs_master_mcast_ifn, mcast_ifn,
-			sizeof(ip_vs_master_mcast_ifn));
-		ip_vs_master_syncid = syncid;
-		realtask = &sync_master_thread;
-		name = "ipvs_syncmaster";
+		strlcpy(ipvs->master_mcast_ifn, mcast_ifn,
+			sizeof(ipvs->master_mcast_ifn));
+		ipvs->master_syncid = syncid;
+		realtask = &ipvs->master_thread;
+		name = "ipvs_master:%d";
 		threadfn = sync_thread_master;
-		sock = make_send_sock();
+		sock = make_send_sock(net);
 	} else if (state == IP_VS_STATE_BACKUP) {
-		if (sync_backup_thread)
+		if (ipvs->backup_thread)
 			return -EEXIST;
 
-		strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn,
-			sizeof(ip_vs_backup_mcast_ifn));
-		ip_vs_backup_syncid = syncid;
-		realtask = &sync_backup_thread;
-		name = "ipvs_syncbackup";
+		strlcpy(ipvs->backup_mcast_ifn, mcast_ifn,
+			sizeof(ipvs->backup_mcast_ifn));
+		ipvs->backup_syncid = syncid;
+		realtask = &ipvs->backup_thread;
+		name = "ipvs_backup:%d";
 		threadfn = sync_thread_backup;
-		sock = make_receive_sock();
+		sock = make_receive_sock(net);
 	} else {
 		return -EINVAL;
 	}
@@ -884,9 +1566,9 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
 		goto out;
 	}
 
-	set_sync_mesg_maxlen(state);
+	set_sync_mesg_maxlen(net, state);
 	if (state == IP_VS_STATE_BACKUP) {
-		buf = kmalloc(sync_recv_mesg_maxlen, GFP_KERNEL);
+		buf = kmalloc(ipvs->recv_mesg_maxlen, GFP_KERNEL);
 		if (!buf)
 			goto outsocket;
 	}
@@ -895,10 +1577,11 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
 	if (!tinfo)
 		goto outbuf;
 
+	tinfo->net = net;
 	tinfo->sock = sock;
 	tinfo->buf = buf;
 
-	task = kthread_run(threadfn, tinfo, name);
+	task = kthread_run(threadfn, tinfo, name, ipvs->gen);
 	if (IS_ERR(task)) {
 		result = PTR_ERR(task);
 		goto outtinfo;
@@ -906,7 +1589,7 @@ int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
 
 	/* mark as active */
 	*realtask = task;
-	ip_vs_sync_state |= state;
+	ipvs->sync_state |= state;
 
 	/* increase the module use count */
 	ip_vs_use_count_inc();
@@ -924,16 +1607,18 @@ out:
 }
 
 
-int stop_sync_thread(int state)
+int stop_sync_thread(struct net *net, int state)
 {
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
 	IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current));
 
 	if (state == IP_VS_STATE_MASTER) {
-		if (!sync_master_thread)
+		if (!ipvs->master_thread)
 			return -ESRCH;
 
 		pr_info("stopping master sync thread %d ...\n",
-			task_pid_nr(sync_master_thread));
+			task_pid_nr(ipvs->master_thread));
 
 		/*
 		 * The lock synchronizes with sb_queue_tail(), so that we don't
@@ -941,21 +1626,21 @@ int stop_sync_thread(int state)
 		 * progress of stopping the master sync daemon.
 		 */
 
-		spin_lock_bh(&ip_vs_sync_lock);
-		ip_vs_sync_state &= ~IP_VS_STATE_MASTER;
-		spin_unlock_bh(&ip_vs_sync_lock);
-		kthread_stop(sync_master_thread);
-		sync_master_thread = NULL;
+		spin_lock_bh(&ipvs->sync_lock);
+		ipvs->sync_state &= ~IP_VS_STATE_MASTER;
+		spin_unlock_bh(&ipvs->sync_lock);
+		kthread_stop(ipvs->master_thread);
+		ipvs->master_thread = NULL;
 	} else if (state == IP_VS_STATE_BACKUP) {
-		if (!sync_backup_thread)
+		if (!ipvs->backup_thread)
 			return -ESRCH;
 
 		pr_info("stopping backup sync thread %d ...\n",
-			task_pid_nr(sync_backup_thread));
+			task_pid_nr(ipvs->backup_thread));
 
-		ip_vs_sync_state &= ~IP_VS_STATE_BACKUP;
-		kthread_stop(sync_backup_thread);
-		sync_backup_thread = NULL;
+		ipvs->sync_state &= ~IP_VS_STATE_BACKUP;
+		kthread_stop(ipvs->backup_thread);
+		ipvs->backup_thread = NULL;
 	} else {
 		return -EINVAL;
 	}
@@ -965,3 +1650,42 @@ int stop_sync_thread(int state)
 
 	return 0;
 }
+
+/*
+ * Initialize data struct for each netns
+ */
+static int __net_init __ip_vs_sync_init(struct net *net)
+{
+	struct netns_ipvs *ipvs = net_ipvs(net);
+
+	INIT_LIST_HEAD(&ipvs->sync_queue);
+	spin_lock_init(&ipvs->sync_lock);
+	spin_lock_init(&ipvs->sync_buff_lock);
+
+	ipvs->sync_mcast_addr.sin_family = AF_INET;
+	ipvs->sync_mcast_addr.sin_port = cpu_to_be16(IP_VS_SYNC_PORT);
+	ipvs->sync_mcast_addr.sin_addr.s_addr = cpu_to_be32(IP_VS_SYNC_GROUP);
+	return 0;
+}
+
+static void __ip_vs_sync_cleanup(struct net *net)
+{
+	stop_sync_thread(net, IP_VS_STATE_MASTER);
+	stop_sync_thread(net, IP_VS_STATE_BACKUP);
+}
+
+static struct pernet_operations ipvs_sync_ops = {
+	.init = __ip_vs_sync_init,
+	.exit = __ip_vs_sync_cleanup,
+};
+
+
+int __init ip_vs_sync_init(void)
+{
+	return register_pernet_subsys(&ipvs_sync_ops);
+}
+
+void ip_vs_sync_cleanup(void)
+{
+	unregister_pernet_subsys(&ipvs_sync_ops);
+}
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
index bbddfdb..bc1bfc4 100644
--- a/net/netfilter/ipvs/ip_vs_wlc.c
+++ b/net/netfilter/ipvs/ip_vs_wlc.c
@@ -27,22 +27,6 @@
 
 #include <net/ip_vs.h>
 
-
-static inline unsigned int
-ip_vs_wlc_dest_overhead(struct ip_vs_dest *dest)
-{
-	/*
-	 * We think the overhead of processing active connections is 256
-	 * times higher than that of inactive connections in average. (This
-	 * 256 times might not be accurate, we will change it later) We
-	 * use the following formula to estimate the overhead now:
-	 *		  dest->activeconns*256 + dest->inactconns
-	 */
-	return (atomic_read(&dest->activeconns) << 8) +
-		atomic_read(&dest->inactconns);
-}
-
-
 /*
  *	Weighted Least Connection scheduling
  */
@@ -71,11 +55,11 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 		if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
 		    atomic_read(&dest->weight) > 0) {
 			least = dest;
-			loh = ip_vs_wlc_dest_overhead(least);
+			loh = ip_vs_dest_conn_overhead(least);
 			goto nextstage;
 		}
 	}
-	IP_VS_ERR_RL("WLC: no destination available\n");
+	ip_vs_scheduler_err(svc, "no destination available");
 	return NULL;
 
 	/*
@@ -85,7 +69,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 	list_for_each_entry_continue(dest, &svc->destinations, n_list) {
 		if (dest->flags & IP_VS_DEST_F_OVERLOAD)
 			continue;
-		doh = ip_vs_wlc_dest_overhead(dest);
+		doh = ip_vs_dest_conn_overhead(dest);
 		if (loh * atomic_read(&dest->weight) >
 		    doh * atomic_read(&least->weight)) {
 			least = dest;
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
index 30db633..1ef41f5 100644
--- a/net/netfilter/ipvs/ip_vs_wrr.c
+++ b/net/netfilter/ipvs/ip_vs_wrr.c
@@ -147,8 +147,9 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 
 			if (mark->cl == mark->cl->next) {
 				/* no dest entry */
-				IP_VS_ERR_RL("WRR: no destination available: "
-					     "no destinations present\n");
+				ip_vs_scheduler_err(svc,
+					"no destination available: "
+					"no destinations present");
 				dest = NULL;
 				goto out;
 			}
@@ -162,8 +163,8 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
-					IP_VS_ERR_RL("WRR: no destination "
-						     "available\n");
+					ip_vs_scheduler_err(svc,
+						"no destination available");
 					dest = NULL;
 					goto out;
 				}
@@ -185,8 +186,9 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
 			/* back to the start, and no dest is found.
 			   It is only possible when all dests are OVERLOADED */
 			dest = NULL;
-			IP_VS_ERR_RL("WRR: no destination available: "
-				     "all destinations are overloaded\n");
+			ip_vs_scheduler_err(svc,
+				"no destination available: "
+				"all destinations are overloaded");
 			goto out;
 		}
 	}
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 5325a3f..6132b21 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -43,6 +43,13 @@
 
 #include <net/ip_vs.h>
 
+enum {
+	IP_VS_RT_MODE_LOCAL	= 1, /* Allow local dest */
+	IP_VS_RT_MODE_NON_LOCAL	= 2, /* Allow non-local dest */
+	IP_VS_RT_MODE_RDR	= 4, /* Allow redirect from remote daddr to
+				      * local
+				      */
+};
 
 /*
  *      Destination cache to speed up outgoing route lookup
@@ -77,11 +84,7 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos)
 	return dst;
 }
 
-/*
- * Get route to destination or remote server
- * rt_mode: flags, &1=Allow local dest, &2=Allow non-local dest,
- *	    &4=Allow redirect from remote daddr to local
- */
+/* Get route to destination or remote server */
 static struct rtable *
 __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
 		   __be32 daddr, u32 rtos, int rt_mode)
@@ -95,12 +98,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
 		spin_lock(&dest->dst_lock);
 		if (!(rt = (struct rtable *)
 		      __ip_vs_dst_check(dest, rtos))) {
-			struct flowi fl = {
-				.fl4_dst = dest->addr.ip,
-				.fl4_tos = rtos,
-			};
-
-			if (ip_route_output_key(net, &rt, &fl)) {
+			rt = ip_route_output(net, dest->addr.ip, 0, rtos, 0);
+			if (IS_ERR(rt)) {
 				spin_unlock(&dest->dst_lock);
 				IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
 					     &dest->addr.ip);
@@ -113,12 +112,8 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
 		}
 		spin_unlock(&dest->dst_lock);
 	} else {
-		struct flowi fl = {
-			.fl4_dst = daddr,
-			.fl4_tos = rtos,
-		};
-
-		if (ip_route_output_key(net, &rt, &fl)) {
+		rt = ip_route_output(net, daddr, 0, rtos, 0);
+		if (IS_ERR(rt)) {
 			IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n",
 				     &daddr);
 			return NULL;
@@ -126,15 +121,16 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
 	}
 
 	local = rt->rt_flags & RTCF_LOCAL;
-	if (!((local ? 1 : 2) & rt_mode)) {
+	if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) &
+	      rt_mode)) {
 		IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI4\n",
 			     (rt->rt_flags & RTCF_LOCAL) ?
 			     "local":"non-local", &rt->rt_dst);
 		ip_rt_put(rt);
 		return NULL;
 	}
-	if (local && !(rt_mode & 4) && !((ort = skb_rtable(skb)) &&
-					 ort->rt_flags & RTCF_LOCAL)) {
+	if (local && !(rt_mode & IP_VS_RT_MODE_RDR) &&
+	    !((ort = skb_rtable(skb)) && ort->rt_flags & RTCF_LOCAL)) {
 		IP_VS_DBG_RL("Redirect from non-local address %pI4 to local "
 			     "requires NAT method, dest: %pI4\n",
 			     &ip_hdr(skb)->daddr, &rt->rt_dst);
@@ -169,15 +165,15 @@ __ip_vs_reroute_locally(struct sk_buff *skb)
 			return 0;
 		refdst_drop(orefdst);
 	} else {
-		struct flowi fl = {
-			.fl4_dst = iph->daddr,
-			.fl4_src = iph->saddr,
-			.fl4_tos = RT_TOS(iph->tos),
-			.mark = skb->mark,
+		struct flowi4 fl4 = {
+			.daddr = iph->daddr,
+			.saddr = iph->saddr,
+			.flowi4_tos = RT_TOS(iph->tos),
+			.flowi4_mark = skb->mark,
 		};
-		struct rtable *rt;
 
-		if (ip_route_output_key(net, &rt, &fl))
+		rt = ip_route_output_key(net, &fl4);
+		if (IS_ERR(rt))
 			return 0;
 		if (!(rt->rt_flags & RTCF_LOCAL)) {
 			ip_rt_put(rt);
@@ -202,22 +198,27 @@ __ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr,
 			struct in6_addr *ret_saddr, int do_xfrm)
 {
 	struct dst_entry *dst;
-	struct flowi fl = {
-		.fl6_dst = *daddr,
+	struct flowi6 fl6 = {
+		.daddr = *daddr,
 	};
 
-	dst = ip6_route_output(net, NULL, &fl);
+	dst = ip6_route_output(net, NULL, &fl6);
 	if (dst->error)
 		goto out_err;
 	if (!ret_saddr)
 		return dst;
-	if (ipv6_addr_any(&fl.fl6_src) &&
+	if (ipv6_addr_any(&fl6.saddr) &&
 	    ipv6_dev_get_saddr(net, ip6_dst_idev(dst)->dev,
-			       &fl.fl6_dst, 0, &fl.fl6_src) < 0)
-		goto out_err;
-	if (do_xfrm && xfrm_lookup(net, &dst, &fl, NULL, 0) < 0)
+			       &fl6.daddr, 0, &fl6.saddr) < 0)
 		goto out_err;
-	ipv6_addr_copy(ret_saddr, &fl.fl6_src);
+	if (do_xfrm) {
+		dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
+		if (IS_ERR(dst)) {
+			dst = NULL;
+			goto out_err;
+		}
+	}
+	ipv6_addr_copy(ret_saddr, &fl6.saddr);
 	return dst;
 
 out_err:
@@ -384,13 +385,14 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	EnterFunction(10);
 
-	if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr,
-				      RT_TOS(iph->tos), 2)))
+	if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr, RT_TOS(iph->tos),
+				      IP_VS_RT_MODE_NON_LOCAL)))
 		goto tx_error_icmp;
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) {
+	if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF)) &&
+	    !skb_is_gso(skb)) {
 		ip_rt_put(rt);
 		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
@@ -443,7 +445,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if (skb->len > mtu) {
+	if (skb->len > mtu && !skb_is_gso(skb)) {
 		if (!skb->dev) {
 			struct net *net = dev_net(skb_dst(skb)->dev);
 
@@ -512,7 +514,10 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	}
 
 	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
-				      RT_TOS(iph->tos), 1|2|4)))
+				      RT_TOS(iph->tos),
+				      IP_VS_RT_MODE_LOCAL |
+					IP_VS_RT_MODE_NON_LOCAL |
+					IP_VS_RT_MODE_RDR)))
 		goto tx_error_icmp;
 	local = rt->rt_flags & RTCF_LOCAL;
 	/*
@@ -543,7 +548,8 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF))) {
+	if ((skb->len > mtu) && (iph->frag_off & htons(IP_DF)) &&
+	    !skb_is_gso(skb)) {
 		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
 		IP_VS_DBG_RL_PKT(0, AF_INET, pp, skb, 0,
 				 "ip_vs_nat_xmit(): frag needed for");
@@ -658,7 +664,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if (skb->len > mtu) {
+	if (skb->len > mtu && !skb_is_gso(skb)) {
 		if (!skb->dev) {
 			struct net *net = dev_net(skb_dst(skb)->dev);
 
@@ -754,7 +760,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	EnterFunction(10);
 
 	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
-				      RT_TOS(tos), 1|2)))
+				      RT_TOS(tos), IP_VS_RT_MODE_LOCAL |
+						   IP_VS_RT_MODE_NON_LOCAL)))
 		goto tx_error_icmp;
 	if (rt->rt_flags & RTCF_LOCAL) {
 		ip_rt_put(rt);
@@ -773,8 +780,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	df |= (old_iph->frag_off & htons(IP_DF));
 
-	if ((old_iph->frag_off & htons(IP_DF))
-	    && mtu < ntohs(old_iph->tot_len)) {
+	if ((old_iph->frag_off & htons(IP_DF) &&
+	    mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb))) {
 		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
 		goto tx_error_put;
@@ -886,7 +893,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 	if (skb_dst(skb))
 		skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu);
 
-	if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr)) {
+	if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr) &&
+	    !skb_is_gso(skb)) {
 		if (!skb->dev) {
 			struct net *net = dev_net(skb_dst(skb)->dev);
 
@@ -982,7 +990,9 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	EnterFunction(10);
 
 	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
-				      RT_TOS(iph->tos), 1|2)))
+				      RT_TOS(iph->tos),
+				      IP_VS_RT_MODE_LOCAL |
+					IP_VS_RT_MODE_NON_LOCAL)))
 		goto tx_error_icmp;
 	if (rt->rt_flags & RTCF_LOCAL) {
 		ip_rt_put(rt);
@@ -991,7 +1001,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if ((iph->frag_off & htons(IP_DF)) && skb->len > mtu) {
+	if ((iph->frag_off & htons(IP_DF)) && skb->len > mtu &&
+	    !skb_is_gso(skb)) {
 		icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu));
 		ip_rt_put(rt);
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
@@ -1125,7 +1136,10 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 	 */
 
 	if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip,
-				      RT_TOS(ip_hdr(skb)->tos), 1|2|4)))
+				      RT_TOS(ip_hdr(skb)->tos),
+				      IP_VS_RT_MODE_LOCAL |
+					IP_VS_RT_MODE_NON_LOCAL |
+					IP_VS_RT_MODE_RDR)))
 		goto tx_error_icmp;
 	local = rt->rt_flags & RTCF_LOCAL;
 
@@ -1158,7 +1172,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF))) {
+	if ((skb->len > mtu) && (ip_hdr(skb)->frag_off & htons(IP_DF)) &&
+	    !skb_is_gso(skb)) {
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
 		IP_VS_DBG_RL("%s(): frag needed\n", __func__);
 		goto tx_error_put;
@@ -1272,7 +1287,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
 	/* MTU checking */
 	mtu = dst_mtu(&rt->dst);
-	if (skb->len > mtu) {
+	if (skb->len > mtu && !skb_is_gso(skb)) {
 		if (!skb->dev) {
 			struct net *net = dev_net(skb_dst(skb)->dev);
 
diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c
new file mode 100644
index 0000000..4e99cca
--- /dev/null
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -0,0 +1,82 @@
+/*
+ *      broadcast connection tracking helper
+ *
+ *      (c) 2005 Patrick McHardy <kaber@trash.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/module.h>
+#include <linux/ip.h>
+#include <net/route.h>
+#include <linux/inetdevice.h>
+#include <linux/skbuff.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+int nf_conntrack_broadcast_help(struct sk_buff *skb,
+				unsigned int protoff,
+				struct nf_conn *ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned int timeout)
+{
+	struct nf_conntrack_expect *exp;
+	struct iphdr *iph = ip_hdr(skb);
+	struct rtable *rt = skb_rtable(skb);
+	struct in_device *in_dev;
+	struct nf_conn_help *help = nfct_help(ct);
+	__be32 mask = 0;
+
+	/* we're only interested in locally generated packets */
+	if (skb->sk == NULL)
+		goto out;
+	if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
+		goto out;
+	if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
+		goto out;
+
+	rcu_read_lock();
+	in_dev = __in_dev_get_rcu(rt->dst.dev);
+	if (in_dev != NULL) {
+		for_primary_ifa(in_dev) {
+			if (ifa->ifa_broadcast == iph->daddr) {
+				mask = ifa->ifa_mask;
+				break;
+			}
+		} endfor_ifa(in_dev);
+	}
+	rcu_read_unlock();
+
+	if (mask == 0)
+		goto out;
+
+	exp = nf_ct_expect_alloc(ct);
+	if (exp == NULL)
+		goto out;
+
+	exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+	exp->tuple.src.u.udp.port = help->helper->tuple.src.u.udp.port;
+
+	exp->mask.src.u3.ip       = mask;
+	exp->mask.src.u.udp.port  = htons(0xFFFF);
+
+	exp->expectfn             = NULL;
+	exp->flags                = NF_CT_EXPECT_PERMANENT;
+	exp->class		  = NF_CT_EXPECT_CLASS_DEFAULT;
+	exp->helper               = NULL;
+
+	nf_ct_expect_related(exp);
+	nf_ct_expect_put(exp);
+
+	nf_ct_refresh(ct, skb, timeout * HZ);
+out:
+	return NF_ACCEPT;
+}
+EXPORT_SYMBOL_GPL(nf_conntrack_broadcast_help);
+
+MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 84f4fcc..941286c 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -43,6 +43,7 @@
 #include <net/netfilter/nf_conntrack_acct.h>
 #include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_conntrack_zones.h>
+#include <net/netfilter/nf_conntrack_timestamp.h>
 #include <net/netfilter/nf_nat.h>
 #include <net/netfilter/nf_nat_core.h>
 
@@ -282,6 +283,11 @@ EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
 static void death_by_timeout(unsigned long ul_conntrack)
 {
 	struct nf_conn *ct = (void *)ul_conntrack;
+	struct nf_conn_tstamp *tstamp;
+
+	tstamp = nf_conn_tstamp_find(ct);
+	if (tstamp && tstamp->stop == 0)
+		tstamp->stop = ktime_to_ns(ktime_get_real());
 
 	if (!test_bit(IPS_DYING_BIT, &ct->status) &&
 	    unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
@@ -419,6 +425,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 	struct nf_conntrack_tuple_hash *h;
 	struct nf_conn *ct;
 	struct nf_conn_help *help;
+	struct nf_conn_tstamp *tstamp;
 	struct hlist_nulls_node *n;
 	enum ip_conntrack_info ctinfo;
 	struct net *net;
@@ -486,8 +493,16 @@ __nf_conntrack_confirm(struct sk_buff *skb)
 	ct->timeout.expires += jiffies;
 	add_timer(&ct->timeout);
 	atomic_inc(&ct->ct_general.use);
-	set_bit(IPS_CONFIRMED_BIT, &ct->status);
+	ct->status |= IPS_CONFIRMED;
+
+	/* set conntrack timestamp, if enabled. */
+	tstamp = nf_conn_tstamp_find(ct);
+	if (tstamp) {
+		if (skb->tstamp.tv64 == 0)
+			__net_timestamp((struct sk_buff *)skb);
 
+		tstamp->start = ktime_to_ns(skb->tstamp);
+	}
 	/* Since the lookup is lockless, hash insertion must be done after
 	 * starting the timer and setting the CONFIRMED bit. The RCU barriers
 	 * guarantee that no other CPU can find the conntrack before the above
@@ -655,7 +670,8 @@ __nf_conntrack_alloc(struct net *net, u16 zone,
 	 * and ct->tuplehash[IP_CT_DIR_REPLY].hnnode.next unchanged.
 	 */
 	memset(&ct->tuplehash[IP_CT_DIR_MAX], 0,
-	       sizeof(*ct) - offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX]));
+	       offsetof(struct nf_conn, proto) -
+	       offsetof(struct nf_conn, tuplehash[IP_CT_DIR_MAX]));
 	spin_lock_init(&ct->lock);
 	ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *orig;
 	ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode.pprev = NULL;
@@ -745,6 +761,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
 	}
 
 	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
+	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
 
 	ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL;
 	nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0,
@@ -1192,6 +1209,11 @@ struct __nf_ct_flush_report {
 static int kill_report(struct nf_conn *i, void *data)
 {
 	struct __nf_ct_flush_report *fr = (struct __nf_ct_flush_report *)data;
+	struct nf_conn_tstamp *tstamp;
+
+	tstamp = nf_conn_tstamp_find(i);
+	if (tstamp && tstamp->stop == 0)
+		tstamp->stop = ktime_to_ns(ktime_get_real());
 
 	/* If we fail to deliver the event, death_by_timeout() will retry */
 	if (nf_conntrack_event_report(IPCT_DESTROY, i,
@@ -1208,9 +1230,9 @@ static int kill_all(struct nf_conn *i, void *data)
 	return 1;
 }
 
-void nf_ct_free_hashtable(void *hash, int vmalloced, unsigned int size)
+void nf_ct_free_hashtable(void *hash, unsigned int size)
 {
-	if (vmalloced)
+	if (is_vmalloc_addr(hash))
 		vfree(hash);
 	else
 		free_pages((unsigned long)hash,
@@ -1277,9 +1299,9 @@ static void nf_conntrack_cleanup_net(struct net *net)
 		goto i_see_dead_people;
 	}
 
-	nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
-			     net->ct.htable_size);
+	nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
 	nf_conntrack_ecache_fini(net);
+	nf_conntrack_tstamp_fini(net);
 	nf_conntrack_acct_fini(net);
 	nf_conntrack_expect_fini(net);
 	kmem_cache_destroy(net->ct.nf_conntrack_cachep);
@@ -1307,21 +1329,18 @@ void nf_conntrack_cleanup(struct net *net)
 	}
 }
 
-void *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced, int nulls)
+void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
 {
 	struct hlist_nulls_head *hash;
 	unsigned int nr_slots, i;
 	size_t sz;
 
-	*vmalloced = 0;
-
 	BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head));
 	nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head));
 	sz = nr_slots * sizeof(struct hlist_nulls_head);
 	hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
 					get_order(sz));
 	if (!hash) {
-		*vmalloced = 1;
 		printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
 		hash = __vmalloc(sz, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
 				 PAGE_KERNEL);
@@ -1337,7 +1356,7 @@ EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
 
 int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 {
-	int i, bucket, vmalloced, old_vmalloced;
+	int i, bucket;
 	unsigned int hashsize, old_size;
 	struct hlist_nulls_head *hash, *old_hash;
 	struct nf_conntrack_tuple_hash *h;
@@ -1354,7 +1373,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 	if (!hashsize)
 		return -EINVAL;
 
-	hash = nf_ct_alloc_hashtable(&hashsize, &vmalloced, 1);
+	hash = nf_ct_alloc_hashtable(&hashsize, 1);
 	if (!hash)
 		return -ENOMEM;
 
@@ -1376,15 +1395,13 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 		}
 	}
 	old_size = init_net.ct.htable_size;
-	old_vmalloced = init_net.ct.hash_vmalloc;
 	old_hash = init_net.ct.hash;
 
 	init_net.ct.htable_size = nf_conntrack_htable_size = hashsize;
-	init_net.ct.hash_vmalloc = vmalloced;
 	init_net.ct.hash = hash;
 	spin_unlock_bh(&nf_conntrack_lock);
 
-	nf_ct_free_hashtable(old_hash, old_vmalloced, old_size);
+	nf_ct_free_hashtable(old_hash, old_size);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize);
@@ -1497,8 +1514,7 @@ static int nf_conntrack_init_net(struct net *net)
 	}
 
 	net->ct.htable_size = nf_conntrack_htable_size;
-	net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size,
-					     &net->ct.hash_vmalloc, 1);
+	net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size, 1);
 	if (!net->ct.hash) {
 		ret = -ENOMEM;
 		printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
@@ -1510,6 +1526,9 @@ static int nf_conntrack_init_net(struct net *net)
 	ret = nf_conntrack_acct_init(net);
 	if (ret < 0)
 		goto err_acct;
+	ret = nf_conntrack_tstamp_init(net);
+	if (ret < 0)
+		goto err_tstamp;
 	ret = nf_conntrack_ecache_init(net);
 	if (ret < 0)
 		goto err_ecache;
@@ -1517,12 +1536,13 @@ static int nf_conntrack_init_net(struct net *net)
 	return 0;
 
 err_ecache:
+	nf_conntrack_tstamp_fini(net);
+err_tstamp:
 	nf_conntrack_acct_fini(net);
 err_acct:
 	nf_conntrack_expect_fini(net);
 err_expect:
-	nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
-			     net->ct.htable_size);
+	nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
 err_hash:
 	kmem_cache_destroy(net->ct.nf_conntrack_cachep);
 err_cache:
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index a20fb0b..cd1e8e0 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -319,7 +319,8 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 	const struct nf_conntrack_expect_policy *p;
 	unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
 
-	atomic_inc(&exp->use);
+	/* two references : one for hash insert, one for the timer */
+	atomic_add(2, &exp->use);
 
 	if (master_help) {
 		hlist_add_head(&exp->lnode, &master_help->expectations);
@@ -333,12 +334,14 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
 	setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
 		    (unsigned long)exp);
 	if (master_help) {
-		p = &master_help->helper->expect_policy[exp->class];
+		p = &rcu_dereference_protected(
+				master_help->helper,
+				lockdep_is_held(&nf_conntrack_lock)
+				)->expect_policy[exp->class];
 		exp->timeout.expires = jiffies + p->timeout * HZ;
 	}
 	add_timer(&exp->timeout);
 
-	atomic_inc(&exp->use);
 	NF_CT_STAT_INC(net, expect_create);
 }
 
@@ -369,7 +372,10 @@ static inline int refresh_timer(struct nf_conntrack_expect *i)
 	if (!del_timer(&i->timeout))
 		return 0;
 
-	p = &master_help->helper->expect_policy[i->class];
+	p = &rcu_dereference_protected(
+		master_help->helper,
+		lockdep_is_held(&nf_conntrack_lock)
+		)->expect_policy[i->class];
 	i->timeout.expires = jiffies + p->timeout * HZ;
 	add_timer(&i->timeout);
 	return 1;
@@ -407,7 +413,10 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
 	}
 	/* Will be over limit? */
 	if (master_help) {
-		p = &master_help->helper->expect_policy[expect->class];
+		p = &rcu_dereference_protected(
+			master_help->helper,
+			lockdep_is_held(&nf_conntrack_lock)
+			)->expect_policy[expect->class];
 		if (p->max_expected &&
 		    master_help->expecting[expect->class] >= p->max_expected) {
 			evict_oldest_expect(master, expect);
@@ -478,7 +487,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
 	struct hlist_node *n;
 
 	for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
-		n = rcu_dereference(net->ct.expect_hash[st->bucket].first);
+		n = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
 		if (n)
 			return n;
 	}
@@ -491,11 +500,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
 	struct net *net = seq_file_net(seq);
 	struct ct_expect_iter_state *st = seq->private;
 
-	head = rcu_dereference(head->next);
+	head = rcu_dereference(hlist_next_rcu(head));
 	while (head == NULL) {
 		if (++st->bucket >= nf_ct_expect_hsize)
 			return NULL;
-		head = rcu_dereference(net->ct.expect_hash[st->bucket].first);
+		head = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
 	}
 	return head;
 }
@@ -630,8 +639,7 @@ int nf_conntrack_expect_init(struct net *net)
 	}
 
 	net->ct.expect_count = 0;
-	net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
-						  &net->ct.expect_vmalloc, 0);
+	net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 0);
 	if (net->ct.expect_hash == NULL)
 		goto err1;
 
@@ -653,8 +661,7 @@ err3:
 	if (net_eq(net, &init_net))
 		kmem_cache_destroy(nf_ct_expect_cachep);
 err2:
-	nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
-			     nf_ct_expect_hsize);
+	nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
 err1:
 	return err;
 }
@@ -666,6 +673,5 @@ void nf_conntrack_expect_fini(struct net *net)
 		rcu_barrier(); /* Wait for call_rcu() before destroy */
 		kmem_cache_destroy(nf_ct_expect_cachep);
 	}
-	nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
-			     nf_ct_expect_hsize);
+	nf_ct_free_hashtable(net->ct.expect_hash, nf_ct_expect_hsize);
 }
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index bd82450..80a23ed 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -140,15 +140,16 @@ static void update_alloc_size(struct nf_ct_ext_type *type)
 	/* This assumes that extended areas in conntrack for the types
 	   whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */
 	for (i = min; i <= max; i++) {
-		t1 = nf_ct_ext_types[i];
+		t1 = rcu_dereference_protected(nf_ct_ext_types[i],
+				lockdep_is_held(&nf_ct_ext_type_mutex));
 		if (!t1)
 			continue;
 
-		t1->alloc_size = sizeof(struct nf_ct_ext)
-				 + ALIGN(sizeof(struct nf_ct_ext), t1->align)
-				 + t1->len;
+		t1->alloc_size = ALIGN(sizeof(struct nf_ct_ext), t1->align) +
+				 t1->len;
 		for (j = 0; j < NF_CT_EXT_NUM; j++) {
-			t2 = nf_ct_ext_types[j];
+			t2 = rcu_dereference_protected(nf_ct_ext_types[j],
+				lockdep_is_held(&nf_ct_ext_type_mutex));
 			if (t2 == NULL || t2 == t1 ||
 			    (t2->flags & NF_CT_EXT_F_PREALLOC) == 0)
 				continue;
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index b969025..533a183 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -714,7 +714,6 @@ static int callforward_do_filter(const union nf_inet_addr *src,
 				 u_int8_t family)
 {
 	const struct nf_afinfo *afinfo;
-	struct flowi fl1, fl2;
 	int ret = 0;
 
 	/* rcu_read_lock()ed by nf_hook_slow() */
@@ -722,17 +721,20 @@ static int callforward_do_filter(const union nf_inet_addr *src,
 	if (!afinfo)
 		return 0;
 
-	memset(&fl1, 0, sizeof(fl1));
-	memset(&fl2, 0, sizeof(fl2));
-
 	switch (family) {
 	case AF_INET: {
+		struct flowi4 fl1, fl2;
 		struct rtable *rt1, *rt2;
 
-		fl1.fl4_dst = src->ip;
-		fl2.fl4_dst = dst->ip;
-		if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) {
-			if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) {
+		memset(&fl1, 0, sizeof(fl1));
+		fl1.daddr = src->ip;
+
+		memset(&fl2, 0, sizeof(fl2));
+		fl2.daddr = dst->ip;
+		if (!afinfo->route((struct dst_entry **)&rt1,
+				   flowi4_to_flowi(&fl1))) {
+			if (!afinfo->route((struct dst_entry **)&rt2,
+					   flowi4_to_flowi(&fl2))) {
 				if (rt1->rt_gateway == rt2->rt_gateway &&
 				    rt1->dst.dev  == rt2->dst.dev)
 					ret = 1;
@@ -745,12 +747,18 @@ static int callforward_do_filter(const union nf_inet_addr *src,
 #if defined(CONFIG_NF_CONNTRACK_IPV6) || \
     defined(CONFIG_NF_CONNTRACK_IPV6_MODULE)
 	case AF_INET6: {
+		struct flowi6 fl1, fl2;
 		struct rt6_info *rt1, *rt2;
 
-		memcpy(&fl1.fl6_dst, src, sizeof(fl1.fl6_dst));
-		memcpy(&fl2.fl6_dst, dst, sizeof(fl2.fl6_dst));
-		if (!afinfo->route((struct dst_entry **)&rt1, &fl1)) {
-			if (!afinfo->route((struct dst_entry **)&rt2, &fl2)) {
+		memset(&fl1, 0, sizeof(fl1));
+		ipv6_addr_copy(&fl1.daddr, &src->in6);
+
+		memset(&fl2, 0, sizeof(fl2));
+		ipv6_addr_copy(&fl2.daddr, &dst->in6);
+		if (!afinfo->route((struct dst_entry **)&rt1,
+				   flowi6_to_flowi(&fl1))) {
+			if (!afinfo->route((struct dst_entry **)&rt2,
+					   flowi6_to_flowi(&fl2))) {
 				if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
 					    sizeof(rt1->rt6i_gateway)) &&
 				    rt1->dst.dev == rt2->dst.dev)
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 59e1a4c..1bdfea3 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -33,7 +33,6 @@ static DEFINE_MUTEX(nf_ct_helper_mutex);
 static struct hlist_head *nf_ct_helper_hash __read_mostly;
 static unsigned int nf_ct_helper_hsize __read_mostly;
 static unsigned int nf_ct_helper_count __read_mostly;
-static int nf_ct_helper_vmalloc;
 
 
 /* Stupid hash, but collision free for the default registrations of the
@@ -158,7 +157,10 @@ static inline int unhelp(struct nf_conntrack_tuple_hash *i,
 	struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i);
 	struct nf_conn_help *help = nfct_help(ct);
 
-	if (help && help->helper == me) {
+	if (help && rcu_dereference_protected(
+			help->helper,
+			lockdep_is_held(&nf_conntrack_lock)
+			) == me) {
 		nf_conntrack_event(IPCT_HELPER, ct);
 		rcu_assign_pointer(help->helper, NULL);
 	}
@@ -210,7 +212,10 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me,
 		hlist_for_each_entry_safe(exp, n, next,
 					  &net->ct.expect_hash[i], hnode) {
 			struct nf_conn_help *help = nfct_help(exp->master);
-			if ((help->helper == me || exp->helper == me) &&
+			if ((rcu_dereference_protected(
+					help->helper,
+					lockdep_is_held(&nf_conntrack_lock)
+					) == me || exp->helper == me) &&
 			    del_timer(&exp->timeout)) {
 				nf_ct_unlink_expect(exp);
 				nf_ct_expect_put(exp);
@@ -261,8 +266,7 @@ int nf_conntrack_helper_init(void)
 	int err;
 
 	nf_ct_helper_hsize = 1; /* gets rounded up to use one page */
-	nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize,
-						  &nf_ct_helper_vmalloc, 0);
+	nf_ct_helper_hash = nf_ct_alloc_hashtable(&nf_ct_helper_hsize, 0);
 	if (!nf_ct_helper_hash)
 		return -ENOMEM;
 
@@ -273,14 +277,12 @@ int nf_conntrack_helper_init(void)
 	return 0;
 
 err1:
-	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
-			     nf_ct_helper_hsize);
+	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
 	return err;
 }
 
 void nf_conntrack_helper_fini(void)
 {
 	nf_ct_extend_unregister(&helper_extend);
-	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_vmalloc,
-			     nf_ct_helper_hsize);
+	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
 }
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index aadde01..4c8f30a 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -18,14 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/if_addr.h>
 #include <linux/in.h>
-#include <linux/ip.h>
-#include <linux/netfilter.h>
-#include <net/route.h>
 
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
@@ -40,75 +33,26 @@ MODULE_ALIAS("ip_conntrack_netbios_ns");
 MODULE_ALIAS_NFCT_HELPER("netbios_ns");
 
 static unsigned int timeout __read_mostly = 3;
-module_param(timeout, uint, 0400);
+module_param(timeout, uint, S_IRUSR);
 MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
 
-static int help(struct sk_buff *skb, unsigned int protoff,
-		struct nf_conn *ct, enum ip_conntrack_info ctinfo)
-{
-	struct nf_conntrack_expect *exp;
-	struct iphdr *iph = ip_hdr(skb);
-	struct rtable *rt = skb_rtable(skb);
-	struct in_device *in_dev;
-	__be32 mask = 0;
-
-	/* we're only interested in locally generated packets */
-	if (skb->sk == NULL)
-		goto out;
-	if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
-		goto out;
-	if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
-		goto out;
-
-	rcu_read_lock();
-	in_dev = __in_dev_get_rcu(rt->dst.dev);
-	if (in_dev != NULL) {
-		for_primary_ifa(in_dev) {
-			if (ifa->ifa_broadcast == iph->daddr) {
-				mask = ifa->ifa_mask;
-				break;
-			}
-		} endfor_ifa(in_dev);
-	}
-	rcu_read_unlock();
-
-	if (mask == 0)
-		goto out;
-
-	exp = nf_ct_expect_alloc(ct);
-	if (exp == NULL)
-		goto out;
-
-	exp->tuple                = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
-	exp->tuple.src.u.udp.port = htons(NMBD_PORT);
-
-	exp->mask.src.u3.ip       = mask;
-	exp->mask.src.u.udp.port  = htons(0xFFFF);
-
-	exp->expectfn             = NULL;
-	exp->flags                = NF_CT_EXPECT_PERMANENT;
-	exp->class		  = NF_CT_EXPECT_CLASS_DEFAULT;
-	exp->helper               = NULL;
-
-	nf_ct_expect_related(exp);
-	nf_ct_expect_put(exp);
-
-	nf_ct_refresh(ct, skb, timeout * HZ);
-out:
-	return NF_ACCEPT;
-}
-
 static struct nf_conntrack_expect_policy exp_policy = {
 	.max_expected	= 1,
 };
 
+static int netbios_ns_help(struct sk_buff *skb, unsigned int protoff,
+		   struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+	return nf_conntrack_broadcast_help(skb, protoff, ct, ctinfo, timeout);
+}
+
 static struct nf_conntrack_helper helper __read_mostly = {
 	.name			= "netbios-ns",
-	.tuple.src.l3num	= AF_INET,
+	.tuple.src.l3num	= NFPROTO_IPV4,
 	.tuple.src.u.udp.port	= cpu_to_be16(NMBD_PORT),
 	.tuple.dst.protonum	= IPPROTO_UDP,
 	.me			= THIS_MODULE,
-	.help			= help,
+	.help			= netbios_ns_help,
 	.expect_policy		= &exp_policy,
 };
 
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index eead9db..30bf8a1 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -42,6 +42,7 @@
 #include <net/netfilter/nf_conntrack_tuple.h>
 #include <net/netfilter/nf_conntrack_acct.h>
 #include <net/netfilter/nf_conntrack_zones.h>
+#include <net/netfilter/nf_conntrack_timestamp.h>
 #ifdef CONFIG_NF_NAT_NEEDED
 #include <net/netfilter/nf_nat_core.h>
 #include <net/netfilter/nf_nat_protocol.h>
@@ -230,6 +231,33 @@ nla_put_failure:
 	return -1;
 }
 
+static int
+ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct)
+{
+	struct nlattr *nest_count;
+	const struct nf_conn_tstamp *tstamp;
+
+	tstamp = nf_conn_tstamp_find(ct);
+	if (!tstamp)
+		return 0;
+
+	nest_count = nla_nest_start(skb, CTA_TIMESTAMP | NLA_F_NESTED);
+	if (!nest_count)
+		goto nla_put_failure;
+
+	NLA_PUT_BE64(skb, CTA_TIMESTAMP_START, cpu_to_be64(tstamp->start));
+	if (tstamp->stop != 0) {
+		NLA_PUT_BE64(skb, CTA_TIMESTAMP_STOP,
+			     cpu_to_be64(tstamp->stop));
+	}
+	nla_nest_end(skb, nest_count);
+
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+
 #ifdef CONFIG_NF_CONNTRACK_MARK
 static inline int
 ctnetlink_dump_mark(struct sk_buff *skb, const struct nf_conn *ct)
@@ -404,6 +432,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
 	    ctnetlink_dump_timeout(skb, ct) < 0 ||
 	    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
 	    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
+	    ctnetlink_dump_timestamp(skb, ct) < 0 ||
 	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_mark(skb, ct) < 0 ||
@@ -471,6 +500,18 @@ ctnetlink_secctx_size(const struct nf_conn *ct)
 }
 
 static inline size_t
+ctnetlink_timestamp_size(const struct nf_conn *ct)
+{
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+	if (!nf_ct_ext_exist(ct, NF_CT_EXT_TSTAMP))
+		return 0;
+	return nla_total_size(0) + 2 * nla_total_size(sizeof(uint64_t));
+#else
+	return 0;
+#endif
+}
+
+static inline size_t
 ctnetlink_nlmsg_size(const struct nf_conn *ct)
 {
 	return NLMSG_ALIGN(sizeof(struct nfgenmsg))
@@ -481,6 +522,7 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct)
 	       + nla_total_size(sizeof(u_int32_t)) /* CTA_ID */
 	       + nla_total_size(sizeof(u_int32_t)) /* CTA_STATUS */
 	       + ctnetlink_counters_size(ct)
+	       + ctnetlink_timestamp_size(ct)
 	       + nla_total_size(sizeof(u_int32_t)) /* CTA_TIMEOUT */
 	       + nla_total_size(0) /* CTA_PROTOINFO */
 	       + nla_total_size(0) /* CTA_HELP */
@@ -571,7 +613,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
 
 	if (events & (1 << IPCT_DESTROY)) {
 		if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
-		    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0)
+		    ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 ||
+		    ctnetlink_dump_timestamp(skb, ct) < 0)
 			goto nla_put_failure;
 	} else {
 		if (ctnetlink_dump_timeout(skb, ct) < 0)
@@ -761,7 +804,7 @@ static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
 static int
 ctnetlink_parse_tuple(const struct nlattr * const cda[],
 		      struct nf_conntrack_tuple *tuple,
-		      enum ctattr_tuple type, u_int8_t l3num)
+		      enum ctattr_type type, u_int8_t l3num)
 {
 	struct nlattr *tb[CTA_TUPLE_MAX+1];
 	int err;
@@ -1358,6 +1401,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
 	}
 
 	nf_ct_acct_ext_add(ct, GFP_ATOMIC);
+	nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
 	nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
 	/* we must add conntrack extensions before confirmation. */
 	ct->status |= IPS_CONFIRMED;
@@ -1376,6 +1420,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone,
 	}
 #endif
 
+	memset(&ct->proto, 0, sizeof(ct->proto));
 	if (cda[CTA_PROTOINFO]) {
 		err = ctnetlink_change_protoinfo(ct, cda);
 		if (err < 0)
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index dc7bb74..5701c8d 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -166,6 +166,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto
 int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
 {
 	int ret = 0;
+	struct nf_conntrack_l3proto *old;
 
 	if (proto->l3proto >= AF_MAX)
 		return -EBUSY;
@@ -174,7 +175,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
 		return -EINVAL;
 
 	mutex_lock(&nf_ct_proto_mutex);
-	if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) {
+	old = rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
+					lockdep_is_held(&nf_ct_proto_mutex));
+	if (old != &nf_conntrack_l3proto_generic) {
 		ret = -EBUSY;
 		goto out_unlock;
 	}
@@ -201,7 +204,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
 	BUG_ON(proto->l3proto >= AF_MAX);
 
 	mutex_lock(&nf_ct_proto_mutex);
-	BUG_ON(nf_ct_l3protos[proto->l3proto] != proto);
+	BUG_ON(rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
+					 lockdep_is_held(&nf_ct_proto_mutex)
+					 ) != proto);
 	rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
 			   &nf_conntrack_l3proto_generic);
 	nf_ct_l3proto_unregister_sysctl(proto);
@@ -279,7 +284,7 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
 	mutex_lock(&nf_ct_proto_mutex);
 	if (!nf_ct_protos[l4proto->l3proto]) {
 		/* l3proto may be loaded latter. */
-		struct nf_conntrack_l4proto **proto_array;
+		struct nf_conntrack_l4proto __rcu **proto_array;
 		int i;
 
 		proto_array = kmalloc(MAX_NF_CT_PROTO *
@@ -291,7 +296,7 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
 		}
 
 		for (i = 0; i < MAX_NF_CT_PROTO; i++)
-			proto_array[i] = &nf_conntrack_l4proto_generic;
+			RCU_INIT_POINTER(proto_array[i], &nf_conntrack_l4proto_generic);
 
 		/* Before making proto_array visible to lockless readers,
 		 * we must make sure its content is committed to memory.
@@ -299,8 +304,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
 		smp_wmb();
 
 		nf_ct_protos[l4proto->l3proto] = proto_array;
-	} else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] !=
-					&nf_conntrack_l4proto_generic) {
+	} else if (rcu_dereference_protected(
+			nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
+			lockdep_is_held(&nf_ct_proto_mutex)
+			) != &nf_conntrack_l4proto_generic) {
 		ret = -EBUSY;
 		goto out_unlock;
 	}
@@ -331,7 +338,10 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
 	BUG_ON(l4proto->l3proto >= PF_MAX);
 
 	mutex_lock(&nf_ct_proto_mutex);
-	BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto);
+	BUG_ON(rcu_dereference_protected(
+			nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
+			lockdep_is_held(&nf_ct_proto_mutex)
+			) != l4proto);
 	rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
 			   &nf_conntrack_l4proto_generic);
 	nf_ct_l4proto_unregister_sysctl(l4proto);
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index 5292560..9ae57c5 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -452,6 +452,9 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
 	ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
 	ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
 	ct->proto.dccp.state = CT_DCCP_NONE;
+	ct->proto.dccp.last_pkt = DCCP_PKT_REQUEST;
+	ct->proto.dccp.last_dir = IP_CT_DIR_ORIGINAL;
+	ct->proto.dccp.handshake_seq = 0;
 	return true;
 
 out_invalid:
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index c6049c2..6f4ee70 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -413,6 +413,7 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
 	    test_bit(SCTP_CID_COOKIE_ACK, map))
 		return false;
 
+	memset(&ct->proto.sctp, 0, sizeof(ct->proto.sctp));
 	new_state = SCTP_CONNTRACK_MAX;
 	for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
 		/* Don't need lock here: this conntrack not in circulation yet */
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 3fb2b73..37bf943 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -227,11 +227,11 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
  *	sCL -> sIV
  */
 /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2	*/
-/*synack*/ { sIV, sSR, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sSR },
+/*synack*/ { sIV, sSR, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR },
 /*
  *	sSS -> sSR	Standard open.
  *	sS2 -> sSR	Simultaneous open
- *	sSR -> sSR	Retransmitted SYN/ACK.
+ *	sSR -> sIG	Retransmitted SYN/ACK, ignore it.
  *	sES -> sIG	Late retransmitted SYN/ACK?
  *	sFW -> sIG	Might be SYN/ACK answering ignored SYN
  *	sCW -> sIG
@@ -1066,9 +1066,7 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 	BUG_ON(th == NULL);
 
 	/* Don't need lock here: this conntrack not in circulation yet */
-	new_state
-		= tcp_conntracks[0][get_conntrack_index(th)]
-		[TCP_CONNTRACK_NONE];
+	new_state = tcp_conntracks[0][get_conntrack_index(th)][TCP_CONNTRACK_NONE];
 
 	/* Invalid: delete conntrack */
 	if (new_state >= TCP_CONNTRACK_MAX) {
@@ -1077,6 +1075,7 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 	}
 
 	if (new_state == TCP_CONNTRACK_SYN_SENT) {
+		memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp));
 		/* SYN packet */
 		ct->proto.tcp.seen[0].td_end =
 			segment_seq_plus_len(ntohl(th->seq), skb->len,
@@ -1088,11 +1087,11 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 			ct->proto.tcp.seen[0].td_end;
 
 		tcp_options(skb, dataoff, th, &ct->proto.tcp.seen[0]);
-		ct->proto.tcp.seen[1].flags = 0;
 	} else if (nf_ct_tcp_loose == 0) {
 		/* Don't try to pick up connections. */
 		return false;
 	} else {
+		memset(&ct->proto.tcp, 0, sizeof(ct->proto.tcp));
 		/*
 		 * We are in the middle of a connection,
 		 * its history is lost for us.
@@ -1107,7 +1106,6 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 		ct->proto.tcp.seen[0].td_maxend =
 			ct->proto.tcp.seen[0].td_end +
 			ct->proto.tcp.seen[0].td_maxwin;
-		ct->proto.tcp.seen[0].td_scale = 0;
 
 		/* We assume SACK and liberal window checking to handle
 		 * window scaling */
@@ -1116,13 +1114,7 @@ static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
 					      IP_CT_TCP_FLAG_BE_LIBERAL;
 	}
 
-	ct->proto.tcp.seen[1].td_end = 0;
-	ct->proto.tcp.seen[1].td_maxend = 0;
-	ct->proto.tcp.seen[1].td_maxwin = 0;
-	ct->proto.tcp.seen[1].td_scale = 0;
-
 	/* tcp_packet will set them */
-	ct->proto.tcp.state = TCP_CONNTRACK_NONE;
 	ct->proto.tcp.last_index = TCP_NONE_SET;
 
 	pr_debug("tcp_new: sender end=%u maxend=%u maxwin=%u scale=%i "
diff --git a/net/netfilter/nf_conntrack_snmp.c b/net/netfilter/nf_conntrack_snmp.c
new file mode 100644
index 0000000..6e545e2
--- /dev/null
+++ b/net/netfilter/nf_conntrack_snmp.c
@@ -0,0 +1,77 @@
+/*
+ *      SNMP service broadcast connection tracking helper
+ *
+ *      (c) 2011 Jiri Olsa <jolsa@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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/in.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_helper.h>
+#include <net/netfilter/nf_conntrack_expect.h>
+
+#define SNMP_PORT	161
+
+MODULE_AUTHOR("Jiri Olsa <jolsa@redhat.com>");
+MODULE_DESCRIPTION("SNMP service broadcast connection tracking helper");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_NFCT_HELPER("snmp");
+
+static unsigned int timeout __read_mostly = 30;
+module_param(timeout, uint, S_IRUSR);
+MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
+
+int (*nf_nat_snmp_hook)(struct sk_buff *skb,
+			unsigned int protoff,
+			struct nf_conn *ct,
+			enum ip_conntrack_info ctinfo);
+EXPORT_SYMBOL_GPL(nf_nat_snmp_hook);
+
+static int snmp_conntrack_help(struct sk_buff *skb, unsigned int protoff,
+		struct nf_conn *ct, enum ip_conntrack_info ctinfo)
+{
+	typeof(nf_nat_snmp_hook) nf_nat_snmp;
+
+	nf_conntrack_broadcast_help(skb, protoff, ct, ctinfo, timeout);
+
+	nf_nat_snmp = rcu_dereference(nf_nat_snmp_hook);
+	if (nf_nat_snmp && ct->status & IPS_NAT_MASK)
+		return nf_nat_snmp(skb, protoff, ct, ctinfo);
+
+	return NF_ACCEPT;
+}
+
+static struct nf_conntrack_expect_policy exp_policy = {
+	.max_expected	= 1,
+};
+
+static struct nf_conntrack_helper helper __read_mostly = {
+	.name			= "snmp",
+	.tuple.src.l3num	= NFPROTO_IPV4,
+	.tuple.src.u.udp.port	= cpu_to_be16(SNMP_PORT),
+	.tuple.dst.protonum	= IPPROTO_UDP,
+	.me			= THIS_MODULE,
+	.help			= snmp_conntrack_help,
+	.expect_policy		= &exp_policy,
+};
+
+static int __init nf_conntrack_snmp_init(void)
+{
+	exp_policy.timeout = timeout;
+	return nf_conntrack_helper_register(&helper);
+}
+
+static void __exit nf_conntrack_snmp_fini(void)
+{
+	nf_conntrack_helper_unregister(&helper);
+}
+
+module_init(nf_conntrack_snmp_init);
+module_exit(nf_conntrack_snmp_fini);
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index b4d7f0f..0ae1428 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -29,6 +29,8 @@
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_acct.h>
 #include <net/netfilter/nf_conntrack_zones.h>
+#include <net/netfilter/nf_conntrack_timestamp.h>
+#include <linux/rculist_nulls.h>
 
 MODULE_LICENSE("GPL");
 
@@ -45,6 +47,7 @@ EXPORT_SYMBOL_GPL(print_tuple);
 struct ct_iter_state {
 	struct seq_net_private p;
 	unsigned int bucket;
+	u_int64_t time_now;
 };
 
 static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
@@ -56,7 +59,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
 	for (st->bucket = 0;
 	     st->bucket < net->ct.htable_size;
 	     st->bucket++) {
-		n = rcu_dereference(net->ct.hash[st->bucket].first);
+		n = rcu_dereference(hlist_nulls_first_rcu(&net->ct.hash[st->bucket]));
 		if (!is_a_nulls(n))
 			return n;
 	}
@@ -69,13 +72,15 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
 	struct net *net = seq_file_net(seq);
 	struct ct_iter_state *st = seq->private;
 
-	head = rcu_dereference(head->next);
+	head = rcu_dereference(hlist_nulls_next_rcu(head));
 	while (is_a_nulls(head)) {
 		if (likely(get_nulls_value(head) == st->bucket)) {
 			if (++st->bucket >= net->ct.htable_size)
 				return NULL;
 		}
-		head = rcu_dereference(net->ct.hash[st->bucket].first);
+		head = rcu_dereference(
+				hlist_nulls_first_rcu(
+					&net->ct.hash[st->bucket]));
 	}
 	return head;
 }
@@ -93,6 +98,9 @@ static struct hlist_nulls_node *ct_get_idx(struct seq_file *seq, loff_t pos)
 static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
 	__acquires(RCU)
 {
+	struct ct_iter_state *st = seq->private;
+
+	st->time_now = ktime_to_ns(ktime_get_real());
 	rcu_read_lock();
 	return ct_get_idx(seq, *pos);
 }
@@ -132,6 +140,34 @@ static inline int ct_show_secctx(struct seq_file *s, const struct nf_conn *ct)
 }
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
+static int ct_show_delta_time(struct seq_file *s, const struct nf_conn *ct)
+{
+	struct ct_iter_state *st = s->private;
+	struct nf_conn_tstamp *tstamp;
+	s64 delta_time;
+
+	tstamp = nf_conn_tstamp_find(ct);
+	if (tstamp) {
+		delta_time = st->time_now - tstamp->start;
+		if (delta_time > 0)
+			delta_time = div_s64(delta_time, NSEC_PER_SEC);
+		else
+			delta_time = 0;
+
+		return seq_printf(s, "delta-time=%llu ",
+				  (unsigned long long)delta_time);
+	}
+	return 0;
+}
+#else
+static inline int
+ct_show_delta_time(struct seq_file *s, const struct nf_conn *ct)
+{
+	return 0;
+}
+#endif
+
 /* return 0 on success, 1 in case of error */
 static int ct_seq_show(struct seq_file *s, void *v)
 {
@@ -200,6 +236,9 @@ static int ct_seq_show(struct seq_file *s, void *v)
 		goto release;
 #endif
 
+	if (ct_show_delta_time(s, ct))
+		goto release;
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
 		goto release;
 
diff --git a/net/netfilter/nf_conntrack_timestamp.c b/net/netfilter/nf_conntrack_timestamp.c
new file mode 100644
index 0000000..af7dd31
--- /dev/null
+++ b/net/netfilter/nf_conntrack_timestamp.c
@@ -0,0 +1,120 @@
+/*
+ * (C) 2010 Pablo Neira Ayuso <pablo@netfilter.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 (or any later at your option).
+ */
+
+#include <linux/netfilter.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+
+#include <net/netfilter/nf_conntrack.h>
+#include <net/netfilter/nf_conntrack_extend.h>
+#include <net/netfilter/nf_conntrack_timestamp.h>
+
+static int nf_ct_tstamp __read_mostly;
+
+module_param_named(tstamp, nf_ct_tstamp, bool, 0644);
+MODULE_PARM_DESC(tstamp, "Enable connection tracking flow timestamping.");
+
+#ifdef CONFIG_SYSCTL
+static struct ctl_table tstamp_sysctl_table[] = {
+	{
+		.procname	= "nf_conntrack_timestamp",
+		.data		= &init_net.ct.sysctl_tstamp,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
+	{}
+};
+#endif /* CONFIG_SYSCTL */
+
+static struct nf_ct_ext_type tstamp_extend __read_mostly = {
+	.len	= sizeof(struct nf_conn_tstamp),
+	.align	= __alignof__(struct nf_conn_tstamp),
+	.id	= NF_CT_EXT_TSTAMP,
+};
+
+#ifdef CONFIG_SYSCTL
+static int nf_conntrack_tstamp_init_sysctl(struct net *net)
+{
+	struct ctl_table *table;
+
+	table = kmemdup(tstamp_sysctl_table, sizeof(tstamp_sysctl_table),
+			GFP_KERNEL);
+	if (!table)
+		goto out;
+
+	table[0].data = &net->ct.sysctl_tstamp;
+
+	net->ct.tstamp_sysctl_header = register_net_sysctl_table(net,
+			nf_net_netfilter_sysctl_path, table);
+	if (!net->ct.tstamp_sysctl_header) {
+		printk(KERN_ERR "nf_ct_tstamp: can't register to sysctl.\n");
+		goto out_register;
+	}
+	return 0;
+
+out_register:
+	kfree(table);
+out:
+	return -ENOMEM;
+}
+
+static void nf_conntrack_tstamp_fini_sysctl(struct net *net)
+{
+	struct ctl_table *table;
+
+	table = net->ct.tstamp_sysctl_header->ctl_table_arg;
+	unregister_net_sysctl_table(net->ct.tstamp_sysctl_header);
+	kfree(table);
+}
+#else
+static int nf_conntrack_tstamp_init_sysctl(struct net *net)
+{
+	return 0;
+}
+
+static void nf_conntrack_tstamp_fini_sysctl(struct net *net)
+{
+}
+#endif
+
+int nf_conntrack_tstamp_init(struct net *net)
+{
+	int ret;
+
+	net->ct.sysctl_tstamp = nf_ct_tstamp;
+
+	if (net_eq(net, &init_net)) {
+		ret = nf_ct_extend_register(&tstamp_extend);
+		if (ret < 0) {
+			printk(KERN_ERR "nf_ct_tstamp: Unable to register "
+					"extension\n");
+			goto out_extend_register;
+		}
+	}
+
+	ret = nf_conntrack_tstamp_init_sysctl(net);
+	if (ret < 0)
+		goto out_sysctl;
+
+	return 0;
+
+out_sysctl:
+	if (net_eq(net, &init_net))
+		nf_ct_extend_unregister(&tstamp_extend);
+out_extend_register:
+	return ret;
+}
+
+void nf_conntrack_tstamp_fini(struct net *net)
+{
+	nf_conntrack_tstamp_fini_sysctl(net);
+	if (net_eq(net, &init_net))
+		nf_ct_extend_unregister(&tstamp_extend);
+}
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 9181699..20714ed 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -165,7 +165,8 @@ static int seq_show(struct seq_file *s, void *v)
 	struct nf_logger *t;
 	int ret;
 
-	logger = nf_loggers[*pos];
+	logger = rcu_dereference_protected(nf_loggers[*pos],
+					   lockdep_is_held(&nf_log_mutex));
 
 	if (!logger)
 		ret = seq_printf(s, "%2lld NONE (", *pos);
@@ -253,7 +254,8 @@ static int nf_log_proc_dostring(ctl_table *table, int write,
 		mutex_unlock(&nf_log_mutex);
 	} else {
 		mutex_lock(&nf_log_mutex);
-		logger = nf_loggers[tindex];
+		logger = rcu_dereference_protected(nf_loggers[tindex],
+						   lockdep_is_held(&nf_log_mutex));
 		if (!logger)
 			table->data = "NONE";
 		else
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 74aebed..5ab22e2 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -27,14 +27,17 @@ static DEFINE_MUTEX(queue_handler_mutex);
 int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
 {
 	int ret;
+	const struct nf_queue_handler *old;
 
 	if (pf >= ARRAY_SIZE(queue_handler))
 		return -EINVAL;
 
 	mutex_lock(&queue_handler_mutex);
-	if (queue_handler[pf] == qh)
+	old = rcu_dereference_protected(queue_handler[pf],
+					lockdep_is_held(&queue_handler_mutex));
+	if (old == qh)
 		ret = -EEXIST;
-	else if (queue_handler[pf])
+	else if (old)
 		ret = -EBUSY;
 	else {
 		rcu_assign_pointer(queue_handler[pf], qh);
@@ -49,11 +52,15 @@ EXPORT_SYMBOL(nf_register_queue_handler);
 /* The caller must flush their queue before this */
 int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
 {
+	const struct nf_queue_handler *old;
+
 	if (pf >= ARRAY_SIZE(queue_handler))
 		return -EINVAL;
 
 	mutex_lock(&queue_handler_mutex);
-	if (queue_handler[pf] && queue_handler[pf] != qh) {
+	old = rcu_dereference_protected(queue_handler[pf],
+					lockdep_is_held(&queue_handler_mutex));
+	if (old && old != qh) {
 		mutex_unlock(&queue_handler_mutex);
 		return -EINVAL;
 	}
@@ -73,7 +80,10 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
 
 	mutex_lock(&queue_handler_mutex);
 	for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++)  {
-		if (queue_handler[pf] == qh)
+		if (rcu_dereference_protected(
+				queue_handler[pf],
+				lockdep_is_held(&queue_handler_mutex)
+				) == qh)
 			rcu_assign_pointer(queue_handler[pf], NULL);
 	}
 	mutex_unlock(&queue_handler_mutex);
@@ -115,7 +125,7 @@ static int __nf_queue(struct sk_buff *skb,
 		      int (*okfn)(struct sk_buff *),
 		      unsigned int queuenum)
 {
-	int status;
+	int status = -ENOENT;
 	struct nf_queue_entry *entry = NULL;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct net_device *physindev;
@@ -128,16 +138,20 @@ static int __nf_queue(struct sk_buff *skb,
 	rcu_read_lock();
 
 	qh = rcu_dereference(queue_handler[pf]);
-	if (!qh)
+	if (!qh) {
+		status = -ESRCH;
 		goto err_unlock;
+	}
 
 	afinfo = nf_get_afinfo(pf);
 	if (!afinfo)
 		goto err_unlock;
 
 	entry = kmalloc(sizeof(*entry) + afinfo->route_key_size, GFP_ATOMIC);
-	if (!entry)
+	if (!entry) {
+		status = -ENOMEM;
 		goto err_unlock;
+	}
 
 	*entry = (struct nf_queue_entry) {
 		.skb	= skb,
@@ -151,11 +165,9 @@ static int __nf_queue(struct sk_buff *skb,
 
 	/* If it's going away, ignore hook. */
 	if (!try_module_get(entry->elem->owner)) {
-		rcu_read_unlock();
-		kfree(entry);
-		return 0;
+		status = -ECANCELED;
+		goto err_unlock;
 	}
-
 	/* Bump dev refs so they don't vanish while packet is out */
 	if (indev)
 		dev_hold(indev);
@@ -182,14 +194,13 @@ static int __nf_queue(struct sk_buff *skb,
 		goto err;
 	}
 
-	return 1;
+	return 0;
 
 err_unlock:
 	rcu_read_unlock();
 err:
-	kfree_skb(skb);
 	kfree(entry);
-	return 1;
+	return status;
 }
 
 int nf_queue(struct sk_buff *skb,
@@ -201,6 +212,8 @@ int nf_queue(struct sk_buff *skb,
 	     unsigned int queuenum)
 {
 	struct sk_buff *segs;
+	int err;
+	unsigned int queued;
 
 	if (!skb_is_gso(skb))
 		return __nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
@@ -216,20 +229,35 @@ int nf_queue(struct sk_buff *skb,
 	}
 
 	segs = skb_gso_segment(skb, 0);
-	kfree_skb(skb);
+	/* Does not use PTR_ERR to limit the number of error codes that can be
+	 * returned by nf_queue.  For instance, callers rely on -ECANCELED to mean
+	 * 'ignore this hook'.
+	 */
 	if (IS_ERR(segs))
-		return 1;
+		return -EINVAL;
 
+	queued = 0;
+	err = 0;
 	do {
 		struct sk_buff *nskb = segs->next;
 
 		segs->next = NULL;
-		if (!__nf_queue(segs, elem, pf, hook, indev, outdev, okfn,
-				queuenum))
+		if (err == 0)
+			err = __nf_queue(segs, elem, pf, hook, indev,
+					   outdev, okfn, queuenum);
+		if (err == 0)
+			queued++;
+		else
 			kfree_skb(segs);
 		segs = nskb;
 	} while (segs);
-	return 1;
+
+	/* also free orig skb if only some segments were queued */
+	if (unlikely(err && queued))
+		err = 0;
+	if (err == 0)
+		kfree_skb(skb);
+	return err;
 }
 
 void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
@@ -237,6 +265,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 	struct sk_buff *skb = entry->skb;
 	struct list_head *elem = &entry->elem->list;
 	const struct nf_afinfo *afinfo;
+	int err;
 
 	rcu_read_lock();
 
@@ -270,10 +299,17 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
 		local_bh_enable();
 		break;
 	case NF_QUEUE:
-		if (!__nf_queue(skb, elem, entry->pf, entry->hook,
-				entry->indev, entry->outdev, entry->okfn,
-				verdict >> NF_VERDICT_BITS))
-			goto next_hook;
+		err = __nf_queue(skb, elem, entry->pf, entry->hook,
+				 entry->indev, entry->outdev, entry->okfn,
+				 verdict >> NF_VERDICT_QBITS);
+		if (err < 0) {
+			if (err == -ECANCELED)
+				goto next_hook;
+			if (err == -ESRCH &&
+			   (verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))
+				goto next_hook;
+			kfree_skb(skb);
+		}
 		break;
 	case NF_STOLEN:
 	default:
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 6a1572b..985e9b7 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -376,7 +376,6 @@ __build_packet_message(struct nfulnl_instance *inst,
 			unsigned int hooknum,
 			const struct net_device *indev,
 			const struct net_device *outdev,
-			const struct nf_loginfo *li,
 			const char *prefix, unsigned int plen)
 {
 	struct nfulnl_msg_packet_hdr pmsg;
@@ -652,7 +651,7 @@ nfulnl_log_packet(u_int8_t pf,
 	inst->qlen++;
 
 	__build_packet_message(inst, skb, data_len, pf,
-				hooknum, in, out, li, prefix, plen);
+				hooknum, in, out, prefix, plen);
 
 	if (inst->qlen >= qthreshold)
 		__nfulnl_flush(inst);
@@ -874,19 +873,19 @@ static struct hlist_node *get_first(struct iter_state *st)
 
 	for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
 		if (!hlist_empty(&instance_table[st->bucket]))
-			return rcu_dereference_bh(instance_table[st->bucket].first);
+			return rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
 	}
 	return NULL;
 }
 
 static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h)
 {
-	h = rcu_dereference_bh(h->next);
+	h = rcu_dereference_bh(hlist_next_rcu(h));
 	while (!h) {
 		if (++st->bucket >= INSTANCE_BUCKETS)
 			return NULL;
 
-		h = rcu_dereference_bh(instance_table[st->bucket].first);
+		h = rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
 	}
 	return h;
 }
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 68e67d1..b83123f 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -387,25 +387,31 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 {
 	struct sk_buff *nskb;
 	struct nfqnl_instance *queue;
-	int err;
+	int err = -ENOBUFS;
 
 	/* rcu_read_lock()ed by nf_hook_slow() */
 	queue = instance_lookup(queuenum);
-	if (!queue)
+	if (!queue) {
+		err = -ESRCH;
 		goto err_out;
+	}
 
-	if (queue->copy_mode == NFQNL_COPY_NONE)
+	if (queue->copy_mode == NFQNL_COPY_NONE) {
+		err = -EINVAL;
 		goto err_out;
+	}
 
 	nskb = nfqnl_build_packet_message(queue, entry);
-	if (nskb == NULL)
+	if (nskb == NULL) {
+		err = -ENOMEM;
 		goto err_out;
-
+	}
 	spin_lock_bh(&queue->lock);
 
-	if (!queue->peer_pid)
+	if (!queue->peer_pid) {
+		err = -EINVAL;
 		goto err_out_free_nskb;
-
+	}
 	if (queue->queue_total >= queue->queue_maxlen) {
 		queue->queue_dropped++;
 		if (net_ratelimit())
@@ -432,7 +438,7 @@ err_out_free_nskb:
 err_out_unlock:
 	spin_unlock_bh(&queue->lock);
 err_out:
-	return -1;
+	return err;
 }
 
 static int
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index c942376..a9adf4c 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/audit.h>
 #include <net/net_namespace.h>
 
 #include <linux/netfilter/x_tables.h>
@@ -38,9 +39,8 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
 #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
 
 struct compat_delta {
-	struct compat_delta *next;
-	unsigned int offset;
-	int delta;
+	unsigned int offset; /* offset in kernel */
+	int delta; /* delta in 32bit user land */
 };
 
 struct xt_af {
@@ -49,7 +49,9 @@ struct xt_af {
 	struct list_head target;
 #ifdef CONFIG_COMPAT
 	struct mutex compat_mutex;
-	struct compat_delta *compat_offsets;
+	struct compat_delta *compat_tab;
+	unsigned int number; /* number of slots in compat_tab[] */
+	unsigned int cur; /* number of used slots in compat_tab[] */
 #endif
 };
 
@@ -181,14 +183,14 @@ EXPORT_SYMBOL(xt_unregister_matches);
 /*
  * These are weird, but module loading must not be done with mutex
  * held (since they will register), and we have to have a single
- * function to use try_then_request_module().
+ * function to use.
  */
 
 /* Find match, grabs ref.  Returns ERR_PTR() on error. */
 struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
 {
 	struct xt_match *m;
-	int err = 0;
+	int err = -ENOENT;
 
 	if (mutex_lock_interruptible(&xt[af].mutex) != 0)
 		return ERR_PTR(-EINTR);
@@ -219,9 +221,13 @@ xt_request_find_match(uint8_t nfproto, const char *name, uint8_t revision)
 {
 	struct xt_match *match;
 
-	match = try_then_request_module(xt_find_match(nfproto, name, revision),
-					"%st_%s", xt_prefix[nfproto], name);
-	return (match != NULL) ? match : ERR_PTR(-ENOENT);
+	match = xt_find_match(nfproto, name, revision);
+	if (IS_ERR(match)) {
+		request_module("%st_%s", xt_prefix[nfproto], name);
+		match = xt_find_match(nfproto, name, revision);
+	}
+
+	return match;
 }
 EXPORT_SYMBOL_GPL(xt_request_find_match);
 
@@ -229,7 +235,7 @@ EXPORT_SYMBOL_GPL(xt_request_find_match);
 struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
 {
 	struct xt_target *t;
-	int err = 0;
+	int err = -ENOENT;
 
 	if (mutex_lock_interruptible(&xt[af].mutex) != 0)
 		return ERR_PTR(-EINTR);
@@ -259,9 +265,13 @@ struct xt_target *xt_request_find_target(u8 af, const char *name, u8 revision)
 {
 	struct xt_target *target;
 
-	target = try_then_request_module(xt_find_target(af, name, revision),
-					 "%st_%s", xt_prefix[af], name);
-	return (target != NULL) ? target : ERR_PTR(-ENOENT);
+	target = xt_find_target(af, name, revision);
+	if (IS_ERR(target)) {
+		request_module("%st_%s", xt_prefix[af], name);
+		target = xt_find_target(af, name, revision);
+	}
+
+	return target;
 }
 EXPORT_SYMBOL_GPL(xt_request_find_target);
 
@@ -414,54 +424,67 @@ int xt_check_match(struct xt_mtchk_param *par,
 EXPORT_SYMBOL_GPL(xt_check_match);
 
 #ifdef CONFIG_COMPAT
-int xt_compat_add_offset(u_int8_t af, unsigned int offset, short delta)
+int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
 {
-	struct compat_delta *tmp;
+	struct xt_af *xp = &xt[af];
 
-	tmp = kmalloc(sizeof(struct compat_delta), GFP_KERNEL);
-	if (!tmp)
-		return -ENOMEM;
+	if (!xp->compat_tab) {
+		if (!xp->number)
+			return -EINVAL;
+		xp->compat_tab = vmalloc(sizeof(struct compat_delta) * xp->number);
+		if (!xp->compat_tab)
+			return -ENOMEM;
+		xp->cur = 0;
+	}
 
-	tmp->offset = offset;
-	tmp->delta = delta;
+	if (xp->cur >= xp->number)
+		return -EINVAL;
 
-	if (xt[af].compat_offsets) {
-		tmp->next = xt[af].compat_offsets->next;
-		xt[af].compat_offsets->next = tmp;
-	} else {
-		xt[af].compat_offsets = tmp;
-		tmp->next = NULL;
-	}
+	if (xp->cur)
+		delta += xp->compat_tab[xp->cur - 1].delta;
+	xp->compat_tab[xp->cur].offset = offset;
+	xp->compat_tab[xp->cur].delta = delta;
+	xp->cur++;
 	return 0;
 }
 EXPORT_SYMBOL_GPL(xt_compat_add_offset);
 
 void xt_compat_flush_offsets(u_int8_t af)
 {
-	struct compat_delta *tmp, *next;
-
-	if (xt[af].compat_offsets) {
-		for (tmp = xt[af].compat_offsets; tmp; tmp = next) {
-			next = tmp->next;
-			kfree(tmp);
-		}
-		xt[af].compat_offsets = NULL;
+	if (xt[af].compat_tab) {
+		vfree(xt[af].compat_tab);
+		xt[af].compat_tab = NULL;
+		xt[af].number = 0;
 	}
 }
 EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
 
 int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
 {
-	struct compat_delta *tmp;
-	int delta;
-
-	for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
-		if (tmp->offset < offset)
-			delta += tmp->delta;
-	return delta;
+	struct compat_delta *tmp = xt[af].compat_tab;
+	int mid, left = 0, right = xt[af].cur - 1;
+
+	while (left <= right) {
+		mid = (left + right) >> 1;
+		if (offset > tmp[mid].offset)
+			left = mid + 1;
+		else if (offset < tmp[mid].offset)
+			right = mid - 1;
+		else
+			return mid ? tmp[mid - 1].delta : 0;
+	}
+	WARN_ON_ONCE(1);
+	return 0;
 }
 EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
 
+void xt_compat_init_offsets(u_int8_t af, unsigned int number)
+{
+	xt[af].number = number;
+	xt[af].cur = 0;
+}
+EXPORT_SYMBOL(xt_compat_init_offsets);
+
 int xt_compat_match_offset(const struct xt_match *match)
 {
 	u_int16_t csize = match->compatsize ? : match->matchsize;
@@ -820,6 +843,21 @@ xt_replace_table(struct xt_table *table,
 	 */
 	local_bh_enable();
 
+#ifdef CONFIG_AUDIT
+	if (audit_enabled) {
+		struct audit_buffer *ab;
+
+		ab = audit_log_start(current->audit_context, GFP_KERNEL,
+				     AUDIT_NETFILTER_CFG);
+		if (ab) {
+			audit_log_format(ab, "table=%s family=%u entries=%u",
+					 table->name, table->af,
+					 private->number);
+			audit_log_end(ab);
+		}
+	}
+#endif
+
 	return private;
 }
 EXPORT_SYMBOL_GPL(xt_replace_table);
@@ -1338,7 +1376,7 @@ static int __init xt_init(void)
 		mutex_init(&xt[i].mutex);
 #ifdef CONFIG_COMPAT
 		mutex_init(&xt[i].compat_mutex);
-		xt[i].compat_offsets = NULL;
+		xt[i].compat_tab = NULL;
 #endif
 		INIT_LIST_HEAD(&xt[i].target);
 		INIT_LIST_HEAD(&xt[i].match);
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
new file mode 100644
index 0000000..363a99e
--- /dev/null
+++ b/net/netfilter/xt_AUDIT.c
@@ -0,0 +1,222 @@
+/*
+ * Creates audit record for dropped/accepted packets
+ *
+ * (C) 2010-2011 Thomas Graf <tgraf@redhat.com>
+ * (C) 2010-2011 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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/audit.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/if_arp.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_AUDIT.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <net/ipv6.h>
+#include <net/ip.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Graf <tgraf@redhat.com>");
+MODULE_DESCRIPTION("Xtables: creates audit records for dropped/accepted packets");
+MODULE_ALIAS("ipt_AUDIT");
+MODULE_ALIAS("ip6t_AUDIT");
+MODULE_ALIAS("ebt_AUDIT");
+MODULE_ALIAS("arpt_AUDIT");
+
+static void audit_proto(struct audit_buffer *ab, struct sk_buff *skb,
+			unsigned int proto, unsigned int offset)
+{
+	switch (proto) {
+	case IPPROTO_TCP:
+	case IPPROTO_UDP:
+	case IPPROTO_UDPLITE: {
+		const __be16 *pptr;
+		__be16 _ports[2];
+
+		pptr = skb_header_pointer(skb, offset, sizeof(_ports), _ports);
+		if (pptr == NULL) {
+			audit_log_format(ab, " truncated=1");
+			return;
+		}
+
+		audit_log_format(ab, " sport=%hu dport=%hu",
+				 ntohs(pptr[0]), ntohs(pptr[1]));
+		}
+		break;
+
+	case IPPROTO_ICMP:
+	case IPPROTO_ICMPV6: {
+		const u8 *iptr;
+		u8 _ih[2];
+
+		iptr = skb_header_pointer(skb, offset, sizeof(_ih), &_ih);
+		if (iptr == NULL) {
+			audit_log_format(ab, " truncated=1");
+			return;
+		}
+
+		audit_log_format(ab, " icmptype=%hhu icmpcode=%hhu",
+				 iptr[0], iptr[1]);
+
+		}
+		break;
+	}
+}
+
+static void audit_ip4(struct audit_buffer *ab, struct sk_buff *skb)
+{
+	struct iphdr _iph;
+	const struct iphdr *ih;
+
+	ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+	if (!ih) {
+		audit_log_format(ab, " truncated=1");
+		return;
+	}
+
+	audit_log_format(ab, " saddr=%pI4 daddr=%pI4 ipid=%hu proto=%hhu",
+		&ih->saddr, &ih->daddr, ntohs(ih->id), ih->protocol);
+
+	if (ntohs(ih->frag_off) & IP_OFFSET) {
+		audit_log_format(ab, " frag=1");
+		return;
+	}
+
+	audit_proto(ab, skb, ih->protocol, ih->ihl * 4);
+}
+
+static void audit_ip6(struct audit_buffer *ab, struct sk_buff *skb)
+{
+	struct ipv6hdr _ip6h;
+	const struct ipv6hdr *ih;
+	u8 nexthdr;
+	int offset;
+
+	ih = skb_header_pointer(skb, skb_network_offset(skb), sizeof(_ip6h), &_ip6h);
+	if (!ih) {
+		audit_log_format(ab, " truncated=1");
+		return;
+	}
+
+	nexthdr = ih->nexthdr;
+	offset = ipv6_skip_exthdr(skb, skb_network_offset(skb) + sizeof(_ip6h),
+				  &nexthdr);
+
+	audit_log_format(ab, " saddr=%pI6c daddr=%pI6c proto=%hhu",
+			 &ih->saddr, &ih->daddr, nexthdr);
+
+	if (offset)
+		audit_proto(ab, skb, nexthdr, offset);
+}
+
+static unsigned int
+audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_audit_info *info = par->targinfo;
+	struct audit_buffer *ab;
+
+	ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
+	if (ab == NULL)
+		goto errout;
+
+	audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s",
+			 info->type, par->hooknum, skb->len,
+			 par->in ? par->in->name : "?",
+			 par->out ? par->out->name : "?");
+
+	if (skb->mark)
+		audit_log_format(ab, " mark=%#x", skb->mark);
+
+	if (skb->dev && skb->dev->type == ARPHRD_ETHER) {
+		audit_log_format(ab, " smac=%pM dmac=%pM macproto=0x%04x",
+				 eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+				 ntohs(eth_hdr(skb)->h_proto));
+
+		if (par->family == NFPROTO_BRIDGE) {
+			switch (eth_hdr(skb)->h_proto) {
+			case __constant_htons(ETH_P_IP):
+				audit_ip4(ab, skb);
+				break;
+
+			case __constant_htons(ETH_P_IPV6):
+				audit_ip6(ab, skb);
+				break;
+			}
+		}
+	}
+
+	switch (par->family) {
+	case NFPROTO_IPV4:
+		audit_ip4(ab, skb);
+		break;
+
+	case NFPROTO_IPV6:
+		audit_ip6(ab, skb);
+		break;
+	}
+
+	audit_log_end(ab);
+
+errout:
+	return XT_CONTINUE;
+}
+
+static unsigned int
+audit_tg_ebt(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	audit_tg(skb, par);
+	return EBT_CONTINUE;
+}
+
+static int audit_tg_check(const struct xt_tgchk_param *par)
+{
+	const struct xt_audit_info *info = par->targinfo;
+
+	if (info->type > XT_AUDIT_TYPE_MAX) {
+		pr_info("Audit type out of range (valid range: 0..%hhu)\n",
+			XT_AUDIT_TYPE_MAX);
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+static struct xt_target audit_tg_reg[] __read_mostly = {
+	{
+		.name		= "AUDIT",
+		.family		= NFPROTO_UNSPEC,
+		.target		= audit_tg,
+		.targetsize	= sizeof(struct xt_audit_info),
+		.checkentry	= audit_tg_check,
+		.me		= THIS_MODULE,
+	},
+	{
+		.name		= "AUDIT",
+		.family		= NFPROTO_BRIDGE,
+		.target		= audit_tg_ebt,
+		.targetsize	= sizeof(struct xt_audit_info),
+		.checkentry	= audit_tg_check,
+		.me		= THIS_MODULE,
+	},
+};
+
+static int __init audit_tg_init(void)
+{
+	return xt_register_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg));
+}
+
+static void __exit audit_tg_exit(void)
+{
+	xt_unregister_targets(audit_tg_reg, ARRAY_SIZE(audit_tg_reg));
+}
+
+module_init(audit_tg_init);
+module_exit(audit_tg_exit);
diff --git a/net/netfilter/xt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c
index c2c0e4a..af9c4da 100644
--- a/net/netfilter/xt_CLASSIFY.c
+++ b/net/netfilter/xt_CLASSIFY.c
@@ -19,12 +19,14 @@
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter/xt_CLASSIFY.h>
+#include <linux/netfilter_arp.h>
 
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Xtables: Qdisc classification");
 MODULE_ALIAS("ipt_CLASSIFY");
 MODULE_ALIAS("ip6t_CLASSIFY");
+MODULE_ALIAS("arpt_CLASSIFY");
 
 static unsigned int
 classify_tg(struct sk_buff *skb, const struct xt_action_param *par)
@@ -35,26 +37,36 @@ classify_tg(struct sk_buff *skb, const struct xt_action_param *par)
 	return XT_CONTINUE;
 }
 
-static struct xt_target classify_tg_reg __read_mostly = {
-	.name       = "CLASSIFY",
-	.revision   = 0,
-	.family     = NFPROTO_UNSPEC,
-	.table      = "mangle",
-	.hooks      = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
-		      (1 << NF_INET_POST_ROUTING),
-	.target     = classify_tg,
-	.targetsize = sizeof(struct xt_classify_target_info),
-	.me         = THIS_MODULE,
+static struct xt_target classify_tg_reg[] __read_mostly = {
+	{
+		.name       = "CLASSIFY",
+		.revision   = 0,
+		.family     = NFPROTO_UNSPEC,
+		.hooks      = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
+		              (1 << NF_INET_POST_ROUTING),
+		.target     = classify_tg,
+		.targetsize = sizeof(struct xt_classify_target_info),
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "CLASSIFY",
+		.revision   = 0,
+		.family     = NFPROTO_ARP,
+		.hooks      = (1 << NF_ARP_OUT) | (1 << NF_ARP_FORWARD),
+		.target     = classify_tg,
+		.targetsize = sizeof(struct xt_classify_target_info),
+		.me         = THIS_MODULE,
+	},
 };
 
 static int __init classify_tg_init(void)
 {
-	return xt_register_target(&classify_tg_reg);
+	return xt_register_targets(classify_tg_reg, ARRAY_SIZE(classify_tg_reg));
 }
 
 static void __exit classify_tg_exit(void)
 {
-	xt_unregister_target(&classify_tg_reg);
+	xt_unregister_targets(classify_tg_reg, ARRAY_SIZE(classify_tg_reg));
 }
 
 module_init(classify_tg_init);
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
index be1f22e..3bdd443 100644
--- a/net/netfilter/xt_IDLETIMER.c
+++ b/net/netfilter/xt_IDLETIMER.c
@@ -313,3 +313,5 @@ MODULE_AUTHOR("Timo Teras <ext-timo.teras@nokia.com>");
 MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
 MODULE_DESCRIPTION("Xtables: idle time monitor");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("ipt_IDLETIMER");
+MODULE_ALIAS("ip6t_IDLETIMER");
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c
index a414050..993de2b 100644
--- a/net/netfilter/xt_LED.c
+++ b/net/netfilter/xt_LED.c
@@ -31,6 +31,8 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Adam Nielsen <a.nielsen@shikadi.net>");
 MODULE_DESCRIPTION("Xtables: trigger LED devices on packet match");
+MODULE_ALIAS("ipt_LED");
+MODULE_ALIAS("ip6t_LED");
 
 static LIST_HEAD(xt_led_triggers);
 static DEFINE_MUTEX(xt_led_mutex);
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index 039cce1..d4f4b5d 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -72,18 +72,31 @@ nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
 
 	if (info->queues_total > 1) {
 		if (par->family == NFPROTO_IPV4)
-			queue = hash_v4(skb) % info->queues_total + queue;
+			queue = (((u64) hash_v4(skb) * info->queues_total) >>
+				 32) + queue;
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
 		else if (par->family == NFPROTO_IPV6)
-			queue = hash_v6(skb) % info->queues_total + queue;
+			queue = (((u64) hash_v6(skb) * info->queues_total) >>
+				 32) + queue;
 #endif
 	}
 	return NF_QUEUE_NR(queue);
 }
 
-static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
+static unsigned int
+nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
 {
-	const struct xt_NFQ_info_v1 *info = par->targinfo;
+	const struct xt_NFQ_info_v2 *info = par->targinfo;
+	unsigned int ret = nfqueue_tg_v1(skb, par);
+
+	if (info->bypass)
+		ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
+	return ret;
+}
+
+static int nfqueue_tg_check(const struct xt_tgchk_param *par)
+{
+	const struct xt_NFQ_info_v2 *info = par->targinfo;
 	u32 maxid;
 
 	if (unlikely(!rnd_inited)) {
@@ -100,6 +113,8 @@ static int nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
 		       info->queues_total, maxid);
 		return -ERANGE;
 	}
+	if (par->target->revision == 2 && info->bypass > 1)
+		return -EINVAL;
 	return 0;
 }
 
@@ -115,11 +130,20 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = {
 		.name		= "NFQUEUE",
 		.revision	= 1,
 		.family		= NFPROTO_UNSPEC,
-		.checkentry	= nfqueue_tg_v1_check,
+		.checkentry	= nfqueue_tg_check,
 		.target		= nfqueue_tg_v1,
 		.targetsize	= sizeof(struct xt_NFQ_info_v1),
 		.me		= THIS_MODULE,
 	},
+	{
+		.name		= "NFQUEUE",
+		.revision	= 2,
+		.family		= NFPROTO_UNSPEC,
+		.checkentry	= nfqueue_tg_check,
+		.target		= nfqueue_tg_v2,
+		.targetsize	= sizeof(struct xt_NFQ_info_v2),
+		.me		= THIS_MODULE,
+	},
 };
 
 static int __init nfqueue_tg_init(void)
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index eb81c38..6e6b46c 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -148,16 +148,21 @@ tcpmss_mangle_packet(struct sk_buff *skb,
 static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
 				    unsigned int family)
 {
-	struct flowi fl = {};
+	struct flowi fl;
 	const struct nf_afinfo *ai;
 	struct rtable *rt = NULL;
 	u_int32_t mtu     = ~0U;
 
-	if (family == PF_INET)
-		fl.fl4_dst = ip_hdr(skb)->saddr;
-	else
-		fl.fl6_dst = ipv6_hdr(skb)->saddr;
+	if (family == PF_INET) {
+		struct flowi4 *fl4 = &fl.u.ip4;
+		memset(fl4, 0, sizeof(*fl4));
+		fl4->daddr = ip_hdr(skb)->saddr;
+	} else {
+		struct flowi6 *fl6 = &fl.u.ip6;
 
+		memset(fl6, 0, sizeof(*fl6));
+		ipv6_addr_copy(&fl6->daddr, &ipv6_hdr(skb)->saddr);
+	}
 	rcu_read_lock();
 	ai = nf_get_afinfo(family);
 	if (ai != NULL)
diff --git a/net/netfilter/xt_TEE.c b/net/netfilter/xt_TEE.c
index 5128a6c..5f054a0 100644
--- a/net/netfilter/xt_TEE.c
+++ b/net/netfilter/xt_TEE.c
@@ -62,18 +62,19 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
 	const struct iphdr *iph = ip_hdr(skb);
 	struct net *net = pick_net(skb);
 	struct rtable *rt;
-	struct flowi fl;
+	struct flowi4 fl4;
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl4, 0, sizeof(fl4));
 	if (info->priv) {
 		if (info->priv->oif == -1)
 			return false;
-		fl.oif = info->priv->oif;
+		fl4.flowi4_oif = info->priv->oif;
 	}
-	fl.fl4_dst = info->gw.ip;
-	fl.fl4_tos = RT_TOS(iph->tos);
-	fl.fl4_scope = RT_SCOPE_UNIVERSE;
-	if (ip_route_output_key(net, &rt, &fl) != 0)
+	fl4.daddr = info->gw.ip;
+	fl4.flowi4_tos = RT_TOS(iph->tos);
+	fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+	rt = ip_route_output_key(net, &fl4);
+	if (IS_ERR(rt))
 		return false;
 
 	skb_dst_drop(skb);
@@ -142,18 +143,18 @@ tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info)
 	const struct ipv6hdr *iph = ipv6_hdr(skb);
 	struct net *net = pick_net(skb);
 	struct dst_entry *dst;
-	struct flowi fl;
+	struct flowi6 fl6;
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 	if (info->priv) {
 		if (info->priv->oif == -1)
 			return false;
-		fl.oif = info->priv->oif;
+		fl6.flowi6_oif = info->priv->oif;
 	}
-	fl.fl6_dst = info->gw.in6;
-	fl.fl6_flowlabel = ((iph->flow_lbl[0] & 0xF) << 16) |
+	fl6.daddr = info->gw.in6;
+	fl6.flowlabel = ((iph->flow_lbl[0] & 0xF) << 16) |
 			   (iph->flow_lbl[1] << 8) | iph->flow_lbl[2];
-	dst = ip6_route_output(net, NULL, &fl);
+	dst = ip6_route_output(net, NULL, &fl6);
 	if (dst == NULL)
 		return false;
 
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c
new file mode 100644
index 0000000..2220b85
--- /dev/null
+++ b/net/netfilter/xt_addrtype.c
@@ -0,0 +1,229 @@
+/*
+ *  iptables module to match inet_addr_type() of an ip.
+ *
+ *  Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
+ *  (C) 2007 Laszlo Attila Toth <panther@balabit.hu>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <net/route.h>
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+#include <net/ipv6.h>
+#include <net/ip6_route.h>
+#include <net/ip6_fib.h>
+#endif
+
+#include <linux/netfilter/xt_addrtype.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("Xtables: address type match");
+MODULE_ALIAS("ipt_addrtype");
+MODULE_ALIAS("ip6t_addrtype");
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt)
+{
+	u32 ret;
+
+	if (!rt)
+		return XT_ADDRTYPE_UNREACHABLE;
+
+	if (rt->rt6i_flags & RTF_REJECT)
+		ret = XT_ADDRTYPE_UNREACHABLE;
+	else
+		ret = 0;
+
+	if (rt->rt6i_flags & RTF_LOCAL)
+		ret |= XT_ADDRTYPE_LOCAL;
+	if (rt->rt6i_flags & RTF_ANYCAST)
+		ret |= XT_ADDRTYPE_ANYCAST;
+	return ret;
+}
+
+static bool match_type6(struct net *net, const struct net_device *dev,
+				const struct in6_addr *addr, u16 mask)
+{
+	int addr_type = ipv6_addr_type(addr);
+
+	if ((mask & XT_ADDRTYPE_MULTICAST) &&
+	    !(addr_type & IPV6_ADDR_MULTICAST))
+		return false;
+	if ((mask & XT_ADDRTYPE_UNICAST) && !(addr_type & IPV6_ADDR_UNICAST))
+		return false;
+	if ((mask & XT_ADDRTYPE_UNSPEC) && addr_type != IPV6_ADDR_ANY)
+		return false;
+
+	if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST |
+	     XT_ADDRTYPE_UNREACHABLE) & mask) {
+		struct rt6_info *rt;
+		u32 type;
+		int ifindex = dev ? dev->ifindex : 0;
+
+		rt = rt6_lookup(net, addr, NULL, ifindex, !!dev);
+
+		type = xt_addrtype_rt6_to_type(rt);
+
+		dst_release(&rt->dst);
+		return !!(mask & type);
+	}
+	return true;
+}
+
+static bool
+addrtype_mt6(struct net *net, const struct net_device *dev,
+	const struct sk_buff *skb, const struct xt_addrtype_info_v1 *info)
+{
+	const struct ipv6hdr *iph = ipv6_hdr(skb);
+	bool ret = true;
+
+	if (info->source)
+		ret &= match_type6(net, dev, &iph->saddr, info->source) ^
+		       (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
+	if (ret && info->dest)
+		ret &= match_type6(net, dev, &iph->daddr, info->dest) ^
+		       !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
+	return ret;
+}
+#endif
+
+static inline bool match_type(struct net *net, const struct net_device *dev,
+			      __be32 addr, u_int16_t mask)
+{
+	return !!(mask & (1 << inet_dev_addr_type(net, dev, addr)));
+}
+
+static bool
+addrtype_mt_v0(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	struct net *net = dev_net(par->in ? par->in : par->out);
+	const struct xt_addrtype_info *info = par->matchinfo;
+	const struct iphdr *iph = ip_hdr(skb);
+	bool ret = true;
+
+	if (info->source)
+		ret &= match_type(net, NULL, iph->saddr, info->source) ^
+		       info->invert_source;
+	if (info->dest)
+		ret &= match_type(net, NULL, iph->daddr, info->dest) ^
+		       info->invert_dest;
+
+	return ret;
+}
+
+static bool
+addrtype_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	struct net *net = dev_net(par->in ? par->in : par->out);
+	const struct xt_addrtype_info_v1 *info = par->matchinfo;
+	const struct iphdr *iph;
+	const struct net_device *dev = NULL;
+	bool ret = true;
+
+	if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN)
+		dev = par->in;
+	else if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT)
+		dev = par->out;
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+	if (par->family == NFPROTO_IPV6)
+		return addrtype_mt6(net, dev, skb, info);
+#endif
+	iph = ip_hdr(skb);
+	if (info->source)
+		ret &= match_type(net, dev, iph->saddr, info->source) ^
+		       (info->flags & XT_ADDRTYPE_INVERT_SOURCE);
+	if (ret && info->dest)
+		ret &= match_type(net, dev, iph->daddr, info->dest) ^
+		       !!(info->flags & XT_ADDRTYPE_INVERT_DEST);
+	return ret;
+}
+
+static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param *par)
+{
+	struct xt_addrtype_info_v1 *info = par->matchinfo;
+
+	if (info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN &&
+	    info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
+		pr_info("both incoming and outgoing "
+			"interface limitation cannot be selected\n");
+		return -EINVAL;
+	}
+
+	if (par->hook_mask & ((1 << NF_INET_PRE_ROUTING) |
+	    (1 << NF_INET_LOCAL_IN)) &&
+	    info->flags & XT_ADDRTYPE_LIMIT_IFACE_OUT) {
+		pr_info("output interface limitation "
+			"not valid in PREROUTING and INPUT\n");
+		return -EINVAL;
+	}
+
+	if (par->hook_mask & ((1 << NF_INET_POST_ROUTING) |
+	    (1 << NF_INET_LOCAL_OUT)) &&
+	    info->flags & XT_ADDRTYPE_LIMIT_IFACE_IN) {
+		pr_info("input interface limitation "
+			"not valid in POSTROUTING and OUTPUT\n");
+		return -EINVAL;
+	}
+
+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
+	if (par->family == NFPROTO_IPV6) {
+		if ((info->source | info->dest) & XT_ADDRTYPE_BLACKHOLE) {
+			pr_err("ipv6 BLACKHOLE matching not supported\n");
+			return -EINVAL;
+		}
+		if ((info->source | info->dest) >= XT_ADDRTYPE_PROHIBIT) {
+			pr_err("ipv6 PROHIBT (THROW, NAT ..) matching not supported\n");
+			return -EINVAL;
+		}
+		if ((info->source | info->dest) & XT_ADDRTYPE_BROADCAST) {
+			pr_err("ipv6 does not support BROADCAST matching\n");
+			return -EINVAL;
+		}
+	}
+#endif
+	return 0;
+}
+
+static struct xt_match addrtype_mt_reg[] __read_mostly = {
+	{
+		.name		= "addrtype",
+		.family		= NFPROTO_IPV4,
+		.match		= addrtype_mt_v0,
+		.matchsize	= sizeof(struct xt_addrtype_info),
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "addrtype",
+		.family		= NFPROTO_UNSPEC,
+		.revision	= 1,
+		.match		= addrtype_mt_v1,
+		.checkentry	= addrtype_mt_checkentry_v1,
+		.matchsize	= sizeof(struct xt_addrtype_info_v1),
+		.me		= THIS_MODULE
+	}
+};
+
+static int __init addrtype_mt_init(void)
+{
+	return xt_register_matches(addrtype_mt_reg,
+				   ARRAY_SIZE(addrtype_mt_reg));
+}
+
+static void __exit addrtype_mt_exit(void)
+{
+	xt_unregister_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
+}
+
+module_init(addrtype_mt_init);
+module_exit(addrtype_mt_exit);
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 5c5b6b9..c6d5a83 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -33,17 +33,17 @@
 
 /* we will save the tuples of all connections we care about */
 struct xt_connlimit_conn {
-	struct list_head list;
-	struct nf_conntrack_tuple tuple;
+	struct hlist_node		node;
+	struct nf_conntrack_tuple	tuple;
+	union nf_inet_addr		addr;
 };
 
 struct xt_connlimit_data {
-	struct list_head iphash[256];
-	spinlock_t lock;
+	struct hlist_head	iphash[256];
+	spinlock_t		lock;
 };
 
 static u_int32_t connlimit_rnd __read_mostly;
-static bool connlimit_rnd_inited __read_mostly;
 
 static inline unsigned int connlimit_iphash(__be32 addr)
 {
@@ -101,9 +101,9 @@ static int count_them(struct net *net,
 {
 	const struct nf_conntrack_tuple_hash *found;
 	struct xt_connlimit_conn *conn;
-	struct xt_connlimit_conn *tmp;
+	struct hlist_node *pos, *n;
 	struct nf_conn *found_ct;
-	struct list_head *hash;
+	struct hlist_head *hash;
 	bool addit = true;
 	int matches = 0;
 
@@ -115,7 +115,7 @@ static int count_them(struct net *net,
 	rcu_read_lock();
 
 	/* check the saved connections */
-	list_for_each_entry_safe(conn, tmp, hash, list) {
+	hlist_for_each_entry_safe(conn, pos, n, hash, node) {
 		found    = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE,
 						 &conn->tuple);
 		found_ct = NULL;
@@ -135,7 +135,7 @@ static int count_them(struct net *net,
 
 		if (found == NULL) {
 			/* this one is gone */
-			list_del(&conn->list);
+			hlist_del(&conn->node);
 			kfree(conn);
 			continue;
 		}
@@ -146,12 +146,12 @@ static int count_them(struct net *net,
 			 * closed already -> ditch it
 			 */
 			nf_ct_put(found_ct);
-			list_del(&conn->list);
+			hlist_del(&conn->node);
 			kfree(conn);
 			continue;
 		}
 
-		if (same_source_net(addr, mask, &conn->tuple.src.u3, family))
+		if (same_source_net(addr, mask, &conn->addr, family))
 			/* same source network -> be counted! */
 			++matches;
 		nf_ct_put(found_ct);
@@ -161,11 +161,12 @@ static int count_them(struct net *net,
 
 	if (addit) {
 		/* save the new connection in our list */
-		conn = kzalloc(sizeof(*conn), GFP_ATOMIC);
+		conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
 		if (conn == NULL)
 			return -ENOMEM;
 		conn->tuple = *tuple;
-		list_add(&conn->list, hash);
+		conn->addr = *addr;
+		hlist_add_head(&conn->node, hash);
 		++matches;
 	}
 
@@ -186,17 +187,19 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	ct = nf_ct_get(skb, &ctinfo);
 	if (ct != NULL)
-		tuple_ptr = &ct->tuplehash[0].tuple;
+		tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
 	else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
 				    par->family, &tuple))
 		goto hotdrop;
 
 	if (par->family == NFPROTO_IPV6) {
 		const struct ipv6hdr *iph = ipv6_hdr(skb);
-		memcpy(&addr.ip6, &iph->saddr, sizeof(iph->saddr));
+		memcpy(&addr.ip6, (info->flags & XT_CONNLIMIT_DADDR) ?
+		       &iph->daddr : &iph->saddr, sizeof(addr.ip6));
 	} else {
 		const struct iphdr *iph = ip_hdr(skb);
-		addr.ip = iph->saddr;
+		addr.ip = (info->flags & XT_CONNLIMIT_DADDR) ?
+			  iph->daddr : iph->saddr;
 	}
 
 	spin_lock_bh(&info->data->lock);
@@ -204,13 +207,12 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	                         &info->mask, par->family);
 	spin_unlock_bh(&info->data->lock);
 
-	if (connections < 0) {
+	if (connections < 0)
 		/* kmalloc failed, drop it entirely */
-		par->hotdrop = true;
-		return false;
-	}
+		goto hotdrop;
 
-	return (connections > info->limit) ^ info->inverse;
+	return (connections > info->limit) ^
+	       !!(info->flags & XT_CONNLIMIT_INVERT);
 
  hotdrop:
 	par->hotdrop = true;
@@ -223,9 +225,13 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
 	unsigned int i;
 	int ret;
 
-	if (unlikely(!connlimit_rnd_inited)) {
-		get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
-		connlimit_rnd_inited = true;
+	if (unlikely(!connlimit_rnd)) {
+		u_int32_t rand;
+
+		do {
+			get_random_bytes(&rand, sizeof(rand));
+		} while (!rand);
+		cmpxchg(&connlimit_rnd, 0, rand);
 	}
 	ret = nf_ct_l3proto_try_module_get(par->family);
 	if (ret < 0) {
@@ -243,7 +249,7 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par)
 
 	spin_lock_init(&info->data->lock);
 	for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i)
-		INIT_LIST_HEAD(&info->data->iphash[i]);
+		INIT_HLIST_HEAD(&info->data->iphash[i]);
 
 	return 0;
 }
@@ -252,15 +258,15 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
 {
 	const struct xt_connlimit_info *info = par->matchinfo;
 	struct xt_connlimit_conn *conn;
-	struct xt_connlimit_conn *tmp;
-	struct list_head *hash = info->data->iphash;
+	struct hlist_node *pos, *n;
+	struct hlist_head *hash = info->data->iphash;
 	unsigned int i;
 
 	nf_ct_l3proto_module_put(par->family);
 
 	for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) {
-		list_for_each_entry_safe(conn, tmp, &hash[i], list) {
-			list_del(&conn->list);
+		hlist_for_each_entry_safe(conn, pos, n, &hash[i], node) {
+			hlist_del(&conn->node);
 			kfree(conn);
 		}
 	}
@@ -268,25 +274,38 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
 	kfree(info->data);
 }
 
-static struct xt_match connlimit_mt_reg __read_mostly = {
-	.name       = "connlimit",
-	.revision   = 0,
-	.family     = NFPROTO_UNSPEC,
-	.checkentry = connlimit_mt_check,
-	.match      = connlimit_mt,
-	.matchsize  = sizeof(struct xt_connlimit_info),
-	.destroy    = connlimit_mt_destroy,
-	.me         = THIS_MODULE,
+static struct xt_match connlimit_mt_reg[] __read_mostly = {
+	{
+		.name       = "connlimit",
+		.revision   = 0,
+		.family     = NFPROTO_UNSPEC,
+		.checkentry = connlimit_mt_check,
+		.match      = connlimit_mt,
+		.matchsize  = sizeof(struct xt_connlimit_info),
+		.destroy    = connlimit_mt_destroy,
+		.me         = THIS_MODULE,
+	},
+	{
+		.name       = "connlimit",
+		.revision   = 1,
+		.family     = NFPROTO_UNSPEC,
+		.checkentry = connlimit_mt_check,
+		.match      = connlimit_mt,
+		.matchsize  = sizeof(struct xt_connlimit_info),
+		.destroy    = connlimit_mt_destroy,
+		.me         = THIS_MODULE,
+	},
 };
 
 static int __init connlimit_mt_init(void)
 {
-	return xt_register_match(&connlimit_mt_reg);
+	return xt_register_matches(connlimit_mt_reg,
+	       ARRAY_SIZE(connlimit_mt_reg));
 }
 
 static void __exit connlimit_mt_exit(void)
 {
-	xt_unregister_match(&connlimit_mt_reg);
+	xt_unregister_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
 }
 
 module_init(connlimit_mt_init);
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index e536710..2c0086a 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -112,6 +112,54 @@ ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info,
 	return true;
 }
 
+static inline bool
+port_match(u16 min, u16 max, u16 port, bool invert)
+{
+	return (port >= min && port <= max) ^ invert;
+}
+
+static inline bool
+ct_proto_port_check_v3(const struct xt_conntrack_mtinfo3 *info,
+		       const struct nf_conn *ct)
+{
+	const struct nf_conntrack_tuple *tuple;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
+	if ((info->match_flags & XT_CONNTRACK_PROTO) &&
+	    (nf_ct_protonum(ct) == info->l4proto) ^
+	    !(info->invert_flags & XT_CONNTRACK_PROTO))
+		return false;
+
+	/* Shortcut to match all recognized protocols by using ->src.all. */
+	if ((info->match_flags & XT_CONNTRACK_ORIGSRC_PORT) &&
+	    !port_match(info->origsrc_port, info->origsrc_port_high,
+			ntohs(tuple->src.u.all),
+			info->invert_flags & XT_CONNTRACK_ORIGSRC_PORT))
+		return false;
+
+	if ((info->match_flags & XT_CONNTRACK_ORIGDST_PORT) &&
+	    !port_match(info->origdst_port, info->origdst_port_high,
+			ntohs(tuple->dst.u.all),
+			info->invert_flags & XT_CONNTRACK_ORIGDST_PORT))
+		return false;
+
+	tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
+
+	if ((info->match_flags & XT_CONNTRACK_REPLSRC_PORT) &&
+	    !port_match(info->replsrc_port, info->replsrc_port_high,
+			ntohs(tuple->src.u.all),
+			info->invert_flags & XT_CONNTRACK_REPLSRC_PORT))
+		return false;
+
+	if ((info->match_flags & XT_CONNTRACK_REPLDST_PORT) &&
+	    !port_match(info->repldst_port, info->repldst_port_high,
+			ntohs(tuple->dst.u.all),
+			info->invert_flags & XT_CONNTRACK_REPLDST_PORT))
+		return false;
+
+	return true;
+}
+
 static bool
 conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par,
              u16 state_mask, u16 status_mask)
@@ -170,8 +218,13 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par,
 		    !(info->invert_flags & XT_CONNTRACK_REPLDST))
 			return false;
 
-	if (!ct_proto_port_check(info, ct))
-		return false;
+	if (par->match->revision != 3) {
+		if (!ct_proto_port_check(info, ct))
+			return false;
+	} else {
+		if (!ct_proto_port_check_v3(par->matchinfo, ct))
+			return false;
+	}
 
 	if ((info->match_flags & XT_CONNTRACK_STATUS) &&
 	    (!!(status_mask & ct->status) ^
@@ -207,10 +260,23 @@ conntrack_mt_v2(const struct sk_buff *skb, struct xt_action_param *par)
 	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
 }
 
+static bool
+conntrack_mt_v3(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_conntrack_mtinfo3 *info = par->matchinfo;
+
+	return conntrack_mt(skb, par, info->state_mask, info->status_mask);
+}
+
 static int conntrack_mt_check(const struct xt_mtchk_param *par)
 {
 	int ret;
 
+	if (strcmp(par->table, "raw") == 0) {
+		pr_info("state is undetermined at the time of raw table\n");
+		return -EINVAL;
+	}
+
 	ret = nf_ct_l3proto_try_module_get(par->family);
 	if (ret < 0)
 		pr_info("cannot load conntrack support for proto=%u\n",
@@ -244,6 +310,16 @@ static struct xt_match conntrack_mt_reg[] __read_mostly = {
 		.destroy    = conntrack_mt_destroy,
 		.me         = THIS_MODULE,
 	},
+	{
+		.name       = "conntrack",
+		.revision   = 3,
+		.family     = NFPROTO_UNSPEC,
+		.matchsize  = sizeof(struct xt_conntrack_mtinfo3),
+		.match      = conntrack_mt_v3,
+		.checkentry = conntrack_mt_check,
+		.destroy    = conntrack_mt_destroy,
+		.me         = THIS_MODULE,
+	},
 };
 
 static int __init conntrack_mt_init(void)
diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
index b39db8a..c7a2e54 100644
--- a/net/netfilter/xt_cpu.c
+++ b/net/netfilter/xt_cpu.c
@@ -22,6 +22,8 @@
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Eric Dumazet <eric.dumazet@gmail.com>");
 MODULE_DESCRIPTION("Xtables: CPU match");
+MODULE_ALIAS("ipt_cpu");
+MODULE_ALIAS("ip6t_cpu");
 
 static int cpu_mt_check(const struct xt_mtchk_param *par)
 {
diff --git a/net/netfilter/xt_devgroup.c b/net/netfilter/xt_devgroup.c
new file mode 100644
index 0000000..d9202cd
--- /dev/null
+++ b/net/netfilter/xt_devgroup.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Patrick McHardy <kaber@trash.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/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <linux/netfilter/xt_devgroup.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Xtables: Device group match");
+MODULE_ALIAS("ipt_devgroup");
+MODULE_ALIAS("ip6t_devgroup");
+
+static bool devgroup_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_devgroup_info *info = par->matchinfo;
+
+	if (info->flags & XT_DEVGROUP_MATCH_SRC &&
+	    (((info->src_group ^ par->in->group) & info->src_mask ? 1 : 0) ^
+	     ((info->flags & XT_DEVGROUP_INVERT_SRC) ? 1 : 0)))
+		return false;
+
+	if (info->flags & XT_DEVGROUP_MATCH_DST &&
+	    (((info->dst_group ^ par->out->group) & info->dst_mask ? 1 : 0) ^
+	     ((info->flags & XT_DEVGROUP_INVERT_DST) ? 1 : 0)))
+		return false;
+
+	return true;
+}
+
+static int devgroup_mt_checkentry(const struct xt_mtchk_param *par)
+{
+	const struct xt_devgroup_info *info = par->matchinfo;
+
+	if (info->flags & ~(XT_DEVGROUP_MATCH_SRC | XT_DEVGROUP_INVERT_SRC |
+			    XT_DEVGROUP_MATCH_DST | XT_DEVGROUP_INVERT_DST))
+		return -EINVAL;
+
+	if (info->flags & XT_DEVGROUP_MATCH_SRC &&
+	    par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) |
+			       (1 << NF_INET_LOCAL_IN) |
+			       (1 << NF_INET_FORWARD)))
+		return -EINVAL;
+
+	if (info->flags & XT_DEVGROUP_MATCH_DST &&
+	    par->hook_mask & ~((1 << NF_INET_FORWARD) |
+			       (1 << NF_INET_LOCAL_OUT) |
+			       (1 << NF_INET_POST_ROUTING)))
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct xt_match devgroup_mt_reg __read_mostly = {
+	.name		= "devgroup",
+	.match		= devgroup_mt,
+	.checkentry	= devgroup_mt_checkentry,
+	.matchsize	= sizeof(struct xt_devgroup_info),
+	.family		= NFPROTO_UNSPEC,
+	.me		= THIS_MODULE
+};
+
+static int __init devgroup_mt_init(void)
+{
+	return xt_register_match(&devgroup_mt_reg);
+}
+
+static void __exit devgroup_mt_exit(void)
+{
+	xt_unregister_match(&devgroup_mt_reg);
+}
+
+module_init(devgroup_mt_init);
+module_exit(devgroup_mt_exit);
diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c
index 73c33a4..b46626c 100644
--- a/net/netfilter/xt_iprange.c
+++ b/net/netfilter/xt_iprange.c
@@ -31,7 +31,7 @@ iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par)
 			pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n",
 			         &iph->saddr,
 			         (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
-			         &info->src_max.ip,
+			         &info->src_min.ip,
 			         &info->src_max.ip);
 			return false;
 		}
@@ -76,15 +76,27 @@ iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 		m  = iprange_ipv6_lt(&iph->saddr, &info->src_min.in6);
 		m |= iprange_ipv6_lt(&info->src_max.in6, &iph->saddr);
 		m ^= !!(info->flags & IPRANGE_SRC_INV);
-		if (m)
+		if (m) {
+			pr_debug("src IP %pI6 NOT in range %s%pI6-%pI6\n",
+				 &iph->saddr,
+				 (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
+				 &info->src_min.in6,
+				 &info->src_max.in6);
 			return false;
+		}
 	}
 	if (info->flags & IPRANGE_DST) {
 		m  = iprange_ipv6_lt(&iph->daddr, &info->dst_min.in6);
 		m |= iprange_ipv6_lt(&info->dst_max.in6, &iph->daddr);
 		m ^= !!(info->flags & IPRANGE_DST_INV);
-		if (m)
+		if (m) {
+			pr_debug("dst IP %pI6 NOT in range %s%pI6-%pI6\n",
+				 &iph->daddr,
+				 (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
+				 &info->dst_min.in6,
+				 &info->dst_max.in6);
 			return false;
+		}
 	}
 	return true;
 }
diff --git a/net/netfilter/xt_ipvs.c b/net/netfilter/xt_ipvs.c
index 9127a3d..bb10b07 100644
--- a/net/netfilter/xt_ipvs.c
+++ b/net/netfilter/xt_ipvs.c
@@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	/*
 	 * Check if the packet belongs to an existing entry
 	 */
-	cp = pp->conn_out_get(family, skb, pp, &iph, iph.len, 1 /* inverse */);
+	cp = pp->conn_out_get(family, skb, &iph, iph.len, 1 /* inverse */);
 	if (unlikely(cp == NULL)) {
 		match = false;
 		goto out;
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
new file mode 100644
index 0000000..061d48c
--- /dev/null
+++ b/net/netfilter/xt_set.c
@@ -0,0 +1,359 @@
+/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
+ *                         Patrick Schaaf <bof@bof.de>
+ *                         Martin Josefsson <gandalf@wlug.westbo.se>
+ * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* Kernel module which implements the set match and SET target
+ * for netfilter/iptables. */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/version.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_set.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
+MODULE_DESCRIPTION("Xtables: IP set match and target module");
+MODULE_ALIAS("xt_SET");
+MODULE_ALIAS("ipt_set");
+MODULE_ALIAS("ip6t_set");
+MODULE_ALIAS("ipt_SET");
+MODULE_ALIAS("ip6t_SET");
+
+static inline int
+match_set(ip_set_id_t index, const struct sk_buff *skb,
+	  u8 pf, u8 dim, u8 flags, int inv)
+{
+	if (ip_set_test(index, skb, pf, dim, flags))
+		inv = !inv;
+	return inv;
+}
+
+/* Revision 0 interface: backward compatible with netfilter/iptables */
+
+static bool
+set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_set_info_match_v0 *info = par->matchinfo;
+
+	return match_set(info->match_set.index, skb, par->family,
+			 info->match_set.u.compat.dim,
+			 info->match_set.u.compat.flags,
+			 info->match_set.u.compat.flags & IPSET_INV_MATCH);
+}
+
+static void
+compat_flags(struct xt_set_info_v0 *info)
+{
+	u_int8_t i;
+
+	/* Fill out compatibility data according to enum ip_set_kopt */
+	info->u.compat.dim = IPSET_DIM_ZERO;
+	if (info->u.flags[0] & IPSET_MATCH_INV)
+		info->u.compat.flags |= IPSET_INV_MATCH;
+	for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) {
+		info->u.compat.dim++;
+		if (info->u.flags[i] & IPSET_SRC)
+			info->u.compat.flags |= (1<<info->u.compat.dim);
+	}
+}
+
+static int
+set_match_v0_checkentry(const struct xt_mtchk_param *par)
+{
+	struct xt_set_info_match_v0 *info = par->matchinfo;
+	ip_set_id_t index;
+
+	index = ip_set_nfnl_get_byindex(info->match_set.index);
+
+	if (index == IPSET_INVALID_ID) {
+		pr_warning("Cannot find set indentified by id %u to match\n",
+			   info->match_set.index);
+		return -ENOENT;
+	}
+	if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
+		pr_warning("Protocol error: set match dimension "
+			   "is over the limit!\n");
+		return -ERANGE;
+	}
+
+	/* Fill out compatibility data */
+	compat_flags(&info->match_set);
+
+	return 0;
+}
+
+static void
+set_match_v0_destroy(const struct xt_mtdtor_param *par)
+{
+	struct xt_set_info_match_v0 *info = par->matchinfo;
+
+	ip_set_nfnl_put(info->match_set.index);
+}
+
+static unsigned int
+set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_set_info_target_v0 *info = par->targinfo;
+
+	if (info->add_set.index != IPSET_INVALID_ID)
+		ip_set_add(info->add_set.index, skb, par->family,
+			   info->add_set.u.compat.dim,
+			   info->add_set.u.compat.flags);
+	if (info->del_set.index != IPSET_INVALID_ID)
+		ip_set_del(info->del_set.index, skb, par->family,
+			   info->del_set.u.compat.dim,
+			   info->del_set.u.compat.flags);
+
+	return XT_CONTINUE;
+}
+
+static int
+set_target_v0_checkentry(const struct xt_tgchk_param *par)
+{
+	struct xt_set_info_target_v0 *info = par->targinfo;
+	ip_set_id_t index;
+
+	if (info->add_set.index != IPSET_INVALID_ID) {
+		index = ip_set_nfnl_get_byindex(info->add_set.index);
+		if (index == IPSET_INVALID_ID) {
+			pr_warning("Cannot find add_set index %u as target\n",
+				   info->add_set.index);
+			return -ENOENT;
+		}
+	}
+
+	if (info->del_set.index != IPSET_INVALID_ID) {
+		index = ip_set_nfnl_get_byindex(info->del_set.index);
+		if (index == IPSET_INVALID_ID) {
+			pr_warning("Cannot find del_set index %u as target\n",
+				   info->del_set.index);
+			return -ENOENT;
+		}
+	}
+	if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 ||
+	    info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
+		pr_warning("Protocol error: SET target dimension "
+			   "is over the limit!\n");
+		return -ERANGE;
+	}
+
+	/* Fill out compatibility data */
+	compat_flags(&info->add_set);
+	compat_flags(&info->del_set);
+
+	return 0;
+}
+
+static void
+set_target_v0_destroy(const struct xt_tgdtor_param *par)
+{
+	const struct xt_set_info_target_v0 *info = par->targinfo;
+
+	if (info->add_set.index != IPSET_INVALID_ID)
+		ip_set_nfnl_put(info->add_set.index);
+	if (info->del_set.index != IPSET_INVALID_ID)
+		ip_set_nfnl_put(info->del_set.index);
+}
+
+/* Revision 1: current interface to netfilter/iptables */
+
+static bool
+set_match(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_set_info_match *info = par->matchinfo;
+
+	return match_set(info->match_set.index, skb, par->family,
+			 info->match_set.dim,
+			 info->match_set.flags,
+			 info->match_set.flags & IPSET_INV_MATCH);
+}
+
+static int
+set_match_checkentry(const struct xt_mtchk_param *par)
+{
+	struct xt_set_info_match *info = par->matchinfo;
+	ip_set_id_t index;
+
+	index = ip_set_nfnl_get_byindex(info->match_set.index);
+
+	if (index == IPSET_INVALID_ID) {
+		pr_warning("Cannot find set indentified by id %u to match\n",
+			   info->match_set.index);
+		return -ENOENT;
+	}
+	if (info->match_set.dim > IPSET_DIM_MAX) {
+		pr_warning("Protocol error: set match dimension "
+			   "is over the limit!\n");
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+static void
+set_match_destroy(const struct xt_mtdtor_param *par)
+{
+	struct xt_set_info_match *info = par->matchinfo;
+
+	ip_set_nfnl_put(info->match_set.index);
+}
+
+static unsigned int
+set_target(struct sk_buff *skb, const struct xt_action_param *par)
+{
+	const struct xt_set_info_target *info = par->targinfo;
+
+	if (info->add_set.index != IPSET_INVALID_ID)
+		ip_set_add(info->add_set.index,
+			   skb, par->family,
+			   info->add_set.dim,
+			   info->add_set.flags);
+	if (info->del_set.index != IPSET_INVALID_ID)
+		ip_set_del(info->del_set.index,
+			   skb, par->family,
+			   info->add_set.dim,
+			   info->del_set.flags);
+
+	return XT_CONTINUE;
+}
+
+static int
+set_target_checkentry(const struct xt_tgchk_param *par)
+{
+	const struct xt_set_info_target *info = par->targinfo;
+	ip_set_id_t index;
+
+	if (info->add_set.index != IPSET_INVALID_ID) {
+		index = ip_set_nfnl_get_byindex(info->add_set.index);
+		if (index == IPSET_INVALID_ID) {
+			pr_warning("Cannot find add_set index %u as target\n",
+				   info->add_set.index);
+			return -ENOENT;
+		}
+	}
+
+	if (info->del_set.index != IPSET_INVALID_ID) {
+		index = ip_set_nfnl_get_byindex(info->del_set.index);
+		if (index == IPSET_INVALID_ID) {
+			pr_warning("Cannot find del_set index %u as target\n",
+				   info->del_set.index);
+			return -ENOENT;
+		}
+	}
+	if (info->add_set.dim > IPSET_DIM_MAX ||
+	    info->del_set.flags > IPSET_DIM_MAX) {
+		pr_warning("Protocol error: SET target dimension "
+			   "is over the limit!\n");
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+static void
+set_target_destroy(const struct xt_tgdtor_param *par)
+{
+	const struct xt_set_info_target *info = par->targinfo;
+
+	if (info->add_set.index != IPSET_INVALID_ID)
+		ip_set_nfnl_put(info->add_set.index);
+	if (info->del_set.index != IPSET_INVALID_ID)
+		ip_set_nfnl_put(info->del_set.index);
+}
+
+static struct xt_match set_matches[] __read_mostly = {
+	{
+		.name		= "set",
+		.family		= NFPROTO_IPV4,
+		.revision	= 0,
+		.match		= set_match_v0,
+		.matchsize	= sizeof(struct xt_set_info_match_v0),
+		.checkentry	= set_match_v0_checkentry,
+		.destroy	= set_match_v0_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "set",
+		.family		= NFPROTO_IPV4,
+		.revision	= 1,
+		.match		= set_match,
+		.matchsize	= sizeof(struct xt_set_info_match),
+		.checkentry	= set_match_checkentry,
+		.destroy	= set_match_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "set",
+		.family		= NFPROTO_IPV6,
+		.revision	= 1,
+		.match		= set_match,
+		.matchsize	= sizeof(struct xt_set_info_match),
+		.checkentry	= set_match_checkentry,
+		.destroy	= set_match_destroy,
+		.me		= THIS_MODULE
+	},
+};
+
+static struct xt_target set_targets[] __read_mostly = {
+	{
+		.name		= "SET",
+		.revision	= 0,
+		.family		= NFPROTO_IPV4,
+		.target		= set_target_v0,
+		.targetsize	= sizeof(struct xt_set_info_target_v0),
+		.checkentry	= set_target_v0_checkentry,
+		.destroy	= set_target_v0_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "SET",
+		.revision	= 1,
+		.family		= NFPROTO_IPV4,
+		.target		= set_target,
+		.targetsize	= sizeof(struct xt_set_info_target),
+		.checkentry	= set_target_checkentry,
+		.destroy	= set_target_destroy,
+		.me		= THIS_MODULE
+	},
+	{
+		.name		= "SET",
+		.revision	= 1,
+		.family		= NFPROTO_IPV6,
+		.target		= set_target,
+		.targetsize	= sizeof(struct xt_set_info_target),
+		.checkentry	= set_target_checkentry,
+		.destroy	= set_target_destroy,
+		.me		= THIS_MODULE
+	},
+};
+
+static int __init xt_set_init(void)
+{
+	int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
+
+	if (!ret) {
+		ret = xt_register_targets(set_targets,
+					  ARRAY_SIZE(set_targets));
+		if (ret)
+			xt_unregister_matches(set_matches,
+					      ARRAY_SIZE(set_matches));
+	}
+	return ret;
+}
+
+static void __exit xt_set_fini(void)
+{
+	xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
+	xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
+}
+
+module_init(xt_set_init);
+module_exit(xt_set_fini);
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index 6caef8b..f4fc4c9 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -49,9 +49,9 @@
 static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
 					    struct netlbl_audit *audit_info)
 {
-	audit_info->secid = NETLINK_CB(skb).sid;
-	audit_info->loginuid = NETLINK_CB(skb).loginuid;
-	audit_info->sessionid = NETLINK_CB(skb).sessionid;
+	security_task_getsecid(current, &audit_info->secid);
+	audit_info->loginuid = audit_get_loginuid(current);
+	audit_info->sessionid = audit_get_sessionid(current);
 }
 
 /* NetLabel NETLINK I/O functions */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1f92459..c8f35b5 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1362,17 +1362,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
 
 	NETLINK_CB(skb).pid	= nlk->pid;
 	NETLINK_CB(skb).dst_group = dst_group;
-	NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
-	NETLINK_CB(skb).sessionid = audit_get_sessionid(current);
-	security_task_getsecid(current, &(NETLINK_CB(skb).sid));
 	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
 
-	/* What can I do? Netlink is asynchronous, so that
-	   we will have to save current capabilities to
-	   check them, when this message will be delivered
-	   to corresponding kernel module.   --ANK (980802)
-	 */
-
 	err = -EFAULT;
 	if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
 		kfree_skb(skb);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 91cb1d7..b5362e9 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -164,7 +164,6 @@ struct packet_mreq_max {
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req,
 		int closing, int tx_ring);
 
-#define PGV_FROM_VMALLOC 1
 struct pgv {
 	char *buffer;
 };
@@ -466,7 +465,7 @@ retry:
 	 */
 
 	err = -EMSGSIZE;
-	if (len > dev->mtu + dev->hard_header_len)
+	if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN)
 		goto out_unlock;
 
 	if (!skb) {
@@ -497,6 +496,19 @@ retry:
 		goto retry;
 	}
 
+	if (len > (dev->mtu + dev->hard_header_len)) {
+		/* Earlier code assumed this would be a VLAN pkt,
+		 * double-check this now that we have the actual
+		 * packet in hand.
+		 */
+		struct ethhdr *ehdr;
+		skb_reset_mac_header(skb);
+		ehdr = eth_hdr(skb);
+		if (ehdr->h_proto != htons(ETH_P_8021Q)) {
+			err = -EMSGSIZE;
+			goto out_unlock;
+		}
+	}
 
 	skb->protocol = proto;
 	skb->dev = dev;
@@ -523,11 +535,11 @@ static inline unsigned int run_filter(const struct sk_buff *skb,
 {
 	struct sk_filter *filter;
 
-	rcu_read_lock_bh();
-	filter = rcu_dereference_bh(sk->sk_filter);
+	rcu_read_lock();
+	filter = rcu_dereference(sk->sk_filter);
 	if (filter != NULL)
 		res = sk_run_filter(skb, filter->insns);
-	rcu_read_unlock_bh();
+	rcu_read_unlock();
 
 	return res;
 }
@@ -954,7 +966,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 
 static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 {
-	struct socket *sock;
 	struct sk_buff *skb;
 	struct net_device *dev;
 	__be16 proto;
@@ -966,8 +977,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 	int len_sum = 0;
 	int status = 0;
 
-	sock = po->sk.sk_socket;
-
 	mutex_lock(&po->pg_vec_lock);
 
 	err = -EBUSY;
@@ -1200,7 +1209,7 @@ static int packet_snd(struct socket *sock,
 	}
 
 	err = -EMSGSIZE;
-	if (!gso_type && (len > dev->mtu+reserve))
+	if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN))
 		goto out_unlock;
 
 	err = -ENOBUFS;
@@ -1225,6 +1234,20 @@ static int packet_snd(struct socket *sock,
 	if (err < 0)
 		goto out_free;
 
+	if (!gso_type && (len > dev->mtu + reserve)) {
+		/* Earlier code assumed this would be a VLAN pkt,
+		 * double-check this now that we have the actual
+		 * packet in hand.
+		 */
+		struct ethhdr *ehdr;
+		skb_reset_mac_header(skb);
+		ehdr = eth_hdr(skb);
+		if (ehdr->h_proto != htons(ETH_P_8021Q)) {
+			err = -EMSGSIZE;
+			goto out_free;
+		}
+	}
+
 	skb->protocol = proto;
 	skb->dev = dev;
 	skb->priority = sk->sk_priority;
diff --git a/net/phonet/Kconfig b/net/phonet/Kconfig
index 0d9b8a2..6ec7d55 100644
--- a/net/phonet/Kconfig
+++ b/net/phonet/Kconfig
@@ -14,15 +14,3 @@ config PHONET
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called phonet. If unsure, say N.
-
-config PHONET_PIPECTRLR
-	bool "Phonet Pipe Controller (EXPERIMENTAL)"
-	depends on PHONET && EXPERIMENTAL
-	default N
-	help
-	  The Pipe Controller implementation in Phonet stack to support Pipe
-	  data with Nokia Slim modems like WG2.5 used on ST-Ericsson U8500
-	  platform.
-
-	  This option is incompatible with older Nokia modems.
-	  Say N here unless you really know what you are doing.
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c
index 1072b2c..c6fffd9 100644
--- a/net/phonet/af_phonet.c
+++ b/net/phonet/af_phonet.c
@@ -110,6 +110,7 @@ static int pn_socket_create(struct net *net, struct socket *sock, int protocol,
 	sk->sk_protocol = protocol;
 	pn = pn_sk(sk);
 	pn->sobject = 0;
+	pn->dobject = 0;
 	pn->resource = 0;
 	sk->sk_prot->init(sk);
 	err = 0;
@@ -194,11 +195,7 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
 	if (skb->pkt_type == PACKET_LOOPBACK) {
 		skb_reset_mac_header(skb);
 		skb_orphan(skb);
-		if (irq)
-			netif_rx(skb);
-		else
-			netif_rx_ni(skb);
-		err = 0;
+		err = (irq ? netif_rx(skb) : netif_rx_ni(skb)) ? -ENOBUFS : 0;
 	} else {
 		err = dev_hard_header(skb, dev, ntohs(skb->protocol),
 					NULL, NULL, skb->len);
@@ -207,6 +204,8 @@ static int pn_send(struct sk_buff *skb, struct net_device *dev,
 			goto drop;
 		}
 		err = dev_queue_xmit(skb);
+		if (unlikely(err > 0))
+			err = net_xmit_errno(err);
 	}
 
 	return err;
@@ -242,8 +241,18 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb,
 	struct net_device *dev;
 	struct pn_sock *pn = pn_sk(sk);
 	int err;
-	u16 src;
-	u8 daddr = pn_sockaddr_get_addr(target), saddr = PN_NO_ADDR;
+	u16 src, dst;
+	u8 daddr, saddr, res;
+
+	src = pn->sobject;
+	if (target != NULL) {
+		dst = pn_sockaddr_get_object(target);
+		res = pn_sockaddr_get_resource(target);
+	} else {
+		dst = pn->dobject;
+		res = pn->resource;
+	}
+	daddr = pn_addr(dst);
 
 	err = -EHOSTUNREACH;
 	if (sk->sk_bound_dev_if)
@@ -251,10 +260,9 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb,
 	else if (phonet_address_lookup(net, daddr) == 0) {
 		dev = phonet_device_get(net);
 		skb->pkt_type = PACKET_LOOPBACK;
-	} else if (pn_sockaddr_get_object(target) == 0) {
+	} else if (dst == 0) {
 		/* Resource routing (small race until phonet_rcv()) */
-		struct sock *sk = pn_find_sock_by_res(net,
-							target->spn_resource);
+		struct sock *sk = pn_find_sock_by_res(net, res);
 		if (sk)	{
 			sock_put(sk);
 			dev = phonet_device_get(net);
@@ -271,12 +279,10 @@ int pn_skb_send(struct sock *sk, struct sk_buff *skb,
 	if (saddr == PN_NO_ADDR)
 		goto drop;
 
-	src = pn->sobject;
 	if (!pn_addr(src))
 		src = pn_object(saddr, pn_obj(src));
 
-	err = pn_send(skb, dev, pn_sockaddr_get_object(target),
-			src, pn_sockaddr_get_resource(target), 0);
+	err = pn_send(skb, dev, dst, src, res, 0);
 	dev_put(dev);
 	return err;
 
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 3e60f2e..f17fd84 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -42,7 +42,7 @@
  * TCP_ESTABLISHED	connected pipe in enabled state
  *
  * pep_sock locking:
- *  - sk_state, ackq, hlist: sock lock needed
+ *  - sk_state, hlist: sock lock needed
  *  - listener: read only
  *  - pipe_handle: read only
  */
@@ -50,11 +50,6 @@
 #define CREDITS_MAX	10
 #define CREDITS_THR	7
 
-static const struct sockaddr_pn pipe_srv = {
-	.spn_family = AF_PHONET,
-	.spn_resource = 0xD9, /* pipe service */
-};
-
 #define pep_sb_size(s) (((s) + 5) & ~3) /* 2-bytes head, 32-bits aligned */
 
 /* Get the next TLV sub-block. */
@@ -82,236 +77,95 @@ static unsigned char *pep_get_sb(struct sk_buff *skb, u8 *ptype, u8 *plen,
 	return data;
 }
 
-static int pep_reply(struct sock *sk, struct sk_buff *oskb,
-			u8 code, const void *data, int len, gfp_t priority)
+static struct sk_buff *pep_alloc_skb(struct sock *sk, const void *payload,
+					int len, gfp_t priority)
 {
-	const struct pnpipehdr *oph = pnp_hdr(oskb);
-	struct pnpipehdr *ph;
-	struct sk_buff *skb;
-
-	skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
+	struct sk_buff *skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
 	if (!skb)
-		return -ENOMEM;
+		return NULL;
 	skb_set_owner_w(skb, sk);
 
 	skb_reserve(skb, MAX_PNPIPE_HEADER);
 	__skb_put(skb, len);
-	skb_copy_to_linear_data(skb, data, len);
-	__skb_push(skb, sizeof(*ph));
+	skb_copy_to_linear_data(skb, payload, len);
+	__skb_push(skb, sizeof(struct pnpipehdr));
 	skb_reset_transport_header(skb);
-	ph = pnp_hdr(skb);
-	ph->utid = oph->utid;
-	ph->message_id = oph->message_id + 1; /* REQ -> RESP */
-	ph->pipe_handle = oph->pipe_handle;
-	ph->error_code = code;
-
-	return pn_skb_send(sk, skb, &pipe_srv);
-}
-
-#define PAD 0x00
-
-#ifdef CONFIG_PHONET_PIPECTRLR
-static u8 pipe_negotiate_fc(u8 *host_fc, u8 *remote_fc, int len)
-{
-	int i, j;
-	u8 base_fc, final_fc;
-
-	for (i = 0; i < len; i++) {
-		base_fc = host_fc[i];
-		for (j = 0; j < len; j++) {
-			if (remote_fc[j] == base_fc) {
-				final_fc = base_fc;
-				goto done;
-			}
-		}
-	}
-	return -EINVAL;
-
-done:
-	return final_fc;
-
-}
-
-static int pipe_get_flow_info(struct sock *sk, struct sk_buff *skb,
-		u8 *pref_rx_fc, u8 *req_tx_fc)
-{
-	struct pnpipehdr *hdr;
-	u8 n_sb;
-
-	if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
-		return -EINVAL;
-
-	hdr = pnp_hdr(skb);
-	n_sb = hdr->data[4];
-
-	__skb_pull(skb, sizeof(*hdr) + 4);
-	while (n_sb > 0) {
-		u8 type, buf[3], len = sizeof(buf);
-		u8 *data = pep_get_sb(skb, &type, &len, buf);
-
-		if (data == NULL)
-			return -EINVAL;
-
-		switch (type) {
-		case PN_PIPE_SB_REQUIRED_FC_TX:
-			if (len < 3 || (data[2] | data[3] | data[4]) > 3)
-				break;
-			req_tx_fc[0] = data[2];
-			req_tx_fc[1] = data[3];
-			req_tx_fc[2] = data[4];
-			break;
-
-		case PN_PIPE_SB_PREFERRED_FC_RX:
-			if (len < 3 || (data[2] | data[3] | data[4]) > 3)
-				break;
-			pref_rx_fc[0] = data[2];
-			pref_rx_fc[1] = data[3];
-			pref_rx_fc[2] = data[4];
-			break;
-
-		}
-		n_sb--;
-	}
-	return 0;
+	return skb;
 }
 
-static int pipe_handler_send_req(struct sock *sk, u8 utid,
-		u8 msg_id, gfp_t priority)
+static int pep_reply(struct sock *sk, struct sk_buff *oskb, u8 code,
+			const void *data, int len, gfp_t priority)
 {
-	int len;
+	const struct pnpipehdr *oph = pnp_hdr(oskb);
 	struct pnpipehdr *ph;
 	struct sk_buff *skb;
-	struct pep_sock *pn = pep_sk(sk);
-
-	static const u8 data[4] = {
-		PAD, PAD, PAD, PAD,
-	};
+	struct sockaddr_pn peer;
 
-	switch (msg_id) {
-	case PNS_PEP_CONNECT_REQ:
-		len = sizeof(data);
-		break;
-
-	case PNS_PEP_DISCONNECT_REQ:
-	case PNS_PEP_ENABLE_REQ:
-	case PNS_PEP_DISABLE_REQ:
-		len = 0;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
+	skb = pep_alloc_skb(sk, data, len, priority);
 	if (!skb)
 		return -ENOMEM;
-	skb_set_owner_w(skb, sk);
 
-	skb_reserve(skb, MAX_PNPIPE_HEADER);
-	if (len) {
-		__skb_put(skb, len);
-		skb_copy_to_linear_data(skb, data, len);
-	}
-	__skb_push(skb, sizeof(*ph));
-	skb_reset_transport_header(skb);
 	ph = pnp_hdr(skb);
-	ph->utid = utid;
-	ph->message_id = msg_id;
-	ph->pipe_handle = pn->pipe_handle;
-	ph->error_code = PN_PIPE_NO_ERROR;
+	ph->utid = oph->utid;
+	ph->message_id = oph->message_id + 1; /* REQ -> RESP */
+	ph->pipe_handle = oph->pipe_handle;
+	ph->error_code = code;
 
-	return pn_skb_send(sk, skb, &pn->remote_pep);
+	pn_skb_get_src_sockaddr(oskb, &peer);
+	return pn_skb_send(sk, skb, &peer);
 }
 
-static int pipe_handler_send_created_ind(struct sock *sk,
-		u8 utid, u8 msg_id)
+static int pep_indicate(struct sock *sk, u8 id, u8 code,
+			const void *data, int len, gfp_t priority)
 {
-	int err_code;
+	struct pep_sock *pn = pep_sk(sk);
 	struct pnpipehdr *ph;
 	struct sk_buff *skb;
 
-	struct pep_sock *pn = pep_sk(sk);
-	static u8 data[4] = {
-		0x03, 0x04,
-	};
-	data[2] = pn->tx_fc;
-	data[3] = pn->rx_fc;
-
-	/*
-	 * actually, below is number of sub-blocks and not error code.
-	 * Pipe_created_ind message format does not have any
-	 * error code field. However, the Phonet stack will always send
-	 * an error code as part of pnpipehdr. So, use that err_code to
-	 * specify the number of sub-blocks.
-	 */
-	err_code = 0x01;
-
-	skb = alloc_skb(MAX_PNPIPE_HEADER + sizeof(data), GFP_ATOMIC);
+	skb = pep_alloc_skb(sk, data, len, priority);
 	if (!skb)
 		return -ENOMEM;
-	skb_set_owner_w(skb, sk);
 
-	skb_reserve(skb, MAX_PNPIPE_HEADER);
-	__skb_put(skb, sizeof(data));
-	skb_copy_to_linear_data(skb, data, sizeof(data));
-	__skb_push(skb, sizeof(*ph));
-	skb_reset_transport_header(skb);
 	ph = pnp_hdr(skb);
-	ph->utid = utid;
-	ph->message_id = msg_id;
+	ph->utid = 0;
+	ph->message_id = id;
 	ph->pipe_handle = pn->pipe_handle;
-	ph->error_code = err_code;
-
-	return pn_skb_send(sk, skb, &pn->remote_pep);
+	ph->data[0] = code;
+	return pn_skb_send(sk, skb, NULL);
 }
 
-static int pipe_handler_send_ind(struct sock *sk, u8 utid, u8 msg_id)
+#define PAD 0x00
+
+static int pipe_handler_request(struct sock *sk, u8 id, u8 code,
+				const void *data, int len)
 {
-	int err_code;
+	struct pep_sock *pn = pep_sk(sk);
 	struct pnpipehdr *ph;
 	struct sk_buff *skb;
-	struct pep_sock *pn = pep_sk(sk);
-
-	/*
-	 * actually, below is a filler.
-	 * Pipe_enabled/disabled_ind message format does not have any
-	 * error code field. However, the Phonet stack will always send
-	 * an error code as part of pnpipehdr. So, use that err_code to
-	 * specify the filler value.
-	 */
-	err_code = 0x0;
 
-	skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
+	skb = pep_alloc_skb(sk, data, len, GFP_KERNEL);
 	if (!skb)
 		return -ENOMEM;
-	skb_set_owner_w(skb, sk);
 
-	skb_reserve(skb, MAX_PNPIPE_HEADER);
-	__skb_push(skb, sizeof(*ph));
-	skb_reset_transport_header(skb);
 	ph = pnp_hdr(skb);
-	ph->utid = utid;
-	ph->message_id = msg_id;
+	ph->utid = id; /* whatever */
+	ph->message_id = id;
 	ph->pipe_handle = pn->pipe_handle;
-	ph->error_code = err_code;
-
-	return pn_skb_send(sk, skb, &pn->remote_pep);
+	ph->data[0] = code;
+	return pn_skb_send(sk, skb, NULL);
 }
 
-static int pipe_handler_enable_pipe(struct sock *sk, int enable)
+static int pipe_handler_send_created_ind(struct sock *sk)
 {
-	int utid, req;
-
-	if (enable) {
-		utid = PNS_PIPE_ENABLE_UTID;
-		req = PNS_PEP_ENABLE_REQ;
-	} else {
-		utid = PNS_PIPE_DISABLE_UTID;
-		req = PNS_PEP_DISABLE_REQ;
-	}
-	return pipe_handler_send_req(sk, utid, req, GFP_ATOMIC);
+	struct pep_sock *pn = pep_sk(sk);
+	u8 data[4] = {
+		PN_PIPE_SB_NEGOTIATED_FC, pep_sb_size(2),
+		pn->tx_fc, pn->rx_fc,
+	};
+
+	return pep_indicate(sk, PNS_PIPE_CREATED_IND, 1 /* sub-blocks */,
+				data, 4, GFP_ATOMIC);
 }
-#endif
 
 static int pep_accept_conn(struct sock *sk, struct sk_buff *skb)
 {
@@ -334,11 +188,12 @@ static int pep_accept_conn(struct sock *sk, struct sk_buff *skb)
 				GFP_KERNEL);
 }
 
-static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code)
+static int pep_reject_conn(struct sock *sk, struct sk_buff *skb, u8 code,
+				gfp_t priority)
 {
 	static const u8 data[4] = { PAD, PAD, PAD, 0 /* sub-blocks */ };
 	WARN_ON(code == PN_PIPE_NO_ERROR);
-	return pep_reply(sk, skb, code, data, sizeof(data), GFP_ATOMIC);
+	return pep_reply(sk, skb, code, data, sizeof(data), priority);
 }
 
 /* Control requests are not sent by the pipe service and have a specific
@@ -350,23 +205,21 @@ static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
 	struct sk_buff *skb;
 	struct pnpipehdr *ph;
 	struct sockaddr_pn dst;
+	u8 data[4] = {
+		oph->data[0], /* PEP type */
+		code, /* error code, at an unusual offset */
+		PAD, PAD,
+	};
 
-	skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority);
+	skb = pep_alloc_skb(sk, data, 4, priority);
 	if (!skb)
 		return -ENOMEM;
-	skb_set_owner_w(skb, sk);
-
-	skb_reserve(skb, MAX_PHONET_HEADER);
-	ph = (struct pnpipehdr *)skb_put(skb, sizeof(*ph) + 4);
 
+	ph = pnp_hdr(skb);
 	ph->utid = oph->utid;
 	ph->message_id = PNS_PEP_CTRL_RESP;
 	ph->pipe_handle = oph->pipe_handle;
 	ph->data[0] = oph->data[1]; /* CTRL id */
-	ph->data[1] = oph->data[0]; /* PEP type */
-	ph->data[2] = code; /* error code, at an usual offset */
-	ph->data[3] = PAD;
-	ph->data[4] = PAD;
 
 	pn_skb_get_src_sockaddr(oskb, &dst);
 	return pn_skb_send(sk, skb, &dst);
@@ -374,38 +227,15 @@ static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
 
 static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority)
 {
-	struct pep_sock *pn = pep_sk(sk);
-	struct pnpipehdr *ph;
-	struct sk_buff *skb;
+	u8 data[4] = { type, PAD, PAD, status };
 
-	skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority);
-	if (!skb)
-		return -ENOMEM;
-	skb_set_owner_w(skb, sk);
-
-	skb_reserve(skb, MAX_PNPIPE_HEADER + 4);
-	__skb_push(skb, sizeof(*ph) + 4);
-	skb_reset_transport_header(skb);
-	ph = pnp_hdr(skb);
-	ph->utid = 0;
-	ph->message_id = PNS_PEP_STATUS_IND;
-	ph->pipe_handle = pn->pipe_handle;
-	ph->pep_type = PN_PEP_TYPE_COMMON;
-	ph->data[1] = type;
-	ph->data[2] = PAD;
-	ph->data[3] = PAD;
-	ph->data[4] = status;
-
-#ifdef CONFIG_PHONET_PIPECTRLR
-	return pn_skb_send(sk, skb, &pn->remote_pep);
-#else
-	return pn_skb_send(sk, skb, &pipe_srv);
-#endif
+	return pep_indicate(sk, PNS_PEP_STATUS_IND, PN_PEP_TYPE_COMMON,
+				data, 4, priority);
 }
 
 /* Send our RX flow control information to the sender.
  * Socket must be locked. */
-static void pipe_grant_credits(struct sock *sk)
+static void pipe_grant_credits(struct sock *sk, gfp_t priority)
 {
 	struct pep_sock *pn = pep_sk(sk);
 
@@ -415,16 +245,16 @@ static void pipe_grant_credits(struct sock *sk)
 	case PN_LEGACY_FLOW_CONTROL: /* TODO */
 		break;
 	case PN_ONE_CREDIT_FLOW_CONTROL:
-		pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL,
-				PEP_IND_READY, GFP_ATOMIC);
-		pn->rx_credits = 1;
+		if (pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL,
+					PEP_IND_READY, priority) == 0)
+			pn->rx_credits = 1;
 		break;
 	case PN_MULTI_CREDIT_FLOW_CONTROL:
 		if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX)
 			break;
 		if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS,
 					CREDITS_MAX - pn->rx_credits,
-					GFP_ATOMIC) == 0)
+					priority) == 0)
 			pn->rx_credits = CREDITS_MAX;
 		break;
 	}
@@ -522,7 +352,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
 
 	switch (hdr->message_id) {
 	case PNS_PEP_CONNECT_REQ:
-		pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE);
+		pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE, GFP_ATOMIC);
 		break;
 
 	case PNS_PEP_DISCONNECT_REQ:
@@ -532,35 +362,11 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
 			sk->sk_state_change(sk);
 		break;
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNS_PEP_DISCONNECT_RESP:
-		pn->pipe_state = PIPE_IDLE;
-		sk->sk_state = TCP_CLOSE;
-		break;
-#endif
-
 	case PNS_PEP_ENABLE_REQ:
 		/* Wait for PNS_PIPE_(ENABLED|REDIRECTED)_IND */
 		pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
 		break;
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNS_PEP_ENABLE_RESP:
-		pn->pipe_state = PIPE_ENABLED;
-		pipe_handler_send_ind(sk, PNS_PIPE_ENABLED_IND_UTID,
-				PNS_PIPE_ENABLED_IND);
-
-		if (!pn_flow_safe(pn->tx_fc)) {
-			atomic_set(&pn->tx_credits, 1);
-			sk->sk_write_space(sk);
-		}
-		if (sk->sk_state == TCP_ESTABLISHED)
-			break; /* Nothing to do */
-		sk->sk_state = TCP_ESTABLISHED;
-		pipe_grant_credits(sk);
-		break;
-#endif
-
 	case PNS_PEP_RESET_REQ:
 		switch (hdr->state_after_reset) {
 		case PN_PIPE_DISABLE:
@@ -579,17 +385,6 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
 		pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
 		break;
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNS_PEP_DISABLE_RESP:
-		pn->pipe_state = PIPE_DISABLED;
-		atomic_set(&pn->tx_credits, 0);
-		pipe_handler_send_ind(sk, PNS_PIPE_DISABLED_IND_UTID,
-				PNS_PIPE_DISABLED_IND);
-		sk->sk_state = TCP_SYN_RECV;
-		pn->rx_credits = 0;
-		break;
-#endif
-
 	case PNS_PEP_CTRL_REQ:
 		if (skb_queue_len(&pn->ctrlreq_queue) >= PNPIPE_CTRLREQ_MAX) {
 			atomic_inc(&sk->sk_drops);
@@ -607,7 +402,8 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
 		if (!pn_flow_safe(pn->rx_fc)) {
 			err = sock_queue_rcv_skb(sk, skb);
 			if (!err)
-				return 0;
+				return NET_RX_SUCCESS;
+			err = -ENOBUFS;
 			break;
 		}
 
@@ -645,7 +441,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
 		if (sk->sk_state == TCP_ESTABLISHED)
 			break; /* Nothing to do */
 		sk->sk_state = TCP_ESTABLISHED;
-		pipe_grant_credits(sk);
+		pipe_grant_credits(sk, GFP_ATOMIC);
 		break;
 
 	case PNS_PIPE_DISABLED_IND:
@@ -660,7 +456,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
 	}
 out:
 	kfree_skb(skb);
-	return err;
+	return (err == -ENOBUFS) ? NET_RX_DROP : NET_RX_SUCCESS;
 
 queue:
 	skb->dev = NULL;
@@ -669,7 +465,7 @@ queue:
 	skb_queue_tail(queue, skb);
 	if (!sock_flag(sk, SOCK_DEAD))
 		sk->sk_data_ready(sk, err);
-	return 0;
+	return NET_RX_SUCCESS;
 }
 
 /* Destroy connected sock. */
@@ -681,133 +477,126 @@ static void pipe_destruct(struct sock *sk)
 	skb_queue_purge(&pn->ctrlreq_queue);
 }
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
+static u8 pipe_negotiate_fc(const u8 *fcs, unsigned n)
 {
-	struct pep_sock *pn = pep_sk(sk);
-	u8 host_pref_rx_fc[3] = {3, 2, 1}, host_req_tx_fc[3] = {3, 2, 1};
-	u8 remote_pref_rx_fc[3], remote_req_tx_fc[3];
-	u8 negotiated_rx_fc, negotiated_tx_fc;
-	int ret;
-
-	pipe_get_flow_info(sk, skb, remote_pref_rx_fc,
-			remote_req_tx_fc);
-	negotiated_tx_fc = pipe_negotiate_fc(remote_req_tx_fc,
-			host_pref_rx_fc,
-			sizeof(host_pref_rx_fc));
-	negotiated_rx_fc = pipe_negotiate_fc(host_req_tx_fc,
-			remote_pref_rx_fc,
-			sizeof(host_pref_rx_fc));
-
-	pn->pipe_state = PIPE_DISABLED;
-	sk->sk_state = TCP_SYN_RECV;
-	sk->sk_backlog_rcv = pipe_do_rcv;
-	sk->sk_destruct = pipe_destruct;
-	pn->rx_credits = 0;
-	pn->rx_fc = negotiated_rx_fc;
-	pn->tx_fc = negotiated_tx_fc;
-	sk->sk_state_change(sk);
+	unsigned i;
+	u8 final_fc = PN_NO_FLOW_CONTROL;
 
-	ret = pipe_handler_send_created_ind(sk,
-			PNS_PIPE_CREATED_IND_UTID,
-			PNS_PIPE_CREATED_IND
-			);
+	for (i = 0; i < n; i++) {
+		u8 fc = fcs[i];
 
-	return ret;
+		if (fc > final_fc && fc < PN_MAX_FLOW_CONTROL)
+			final_fc = fc;
+	}
+	return final_fc;
 }
-#endif
 
-static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
+static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
 {
-	struct sock *newsk;
-	struct pep_sock *newpn, *pn = pep_sk(sk);
+	struct pep_sock *pn = pep_sk(sk);
 	struct pnpipehdr *hdr;
-	struct sockaddr_pn dst;
-	u16 peer_type;
-	u8 pipe_handle, enabled, n_sb;
-	u8 aligned = 0;
+	u8 n_sb;
 
 	if (!pskb_pull(skb, sizeof(*hdr) + 4))
 		return -EINVAL;
 
 	hdr = pnp_hdr(skb);
-	pipe_handle = hdr->pipe_handle;
-	switch (hdr->state_after_connect) {
-	case PN_PIPE_DISABLE:
-		enabled = 0;
-		break;
-	case PN_PIPE_ENABLE:
-		enabled = 1;
-		break;
-	default:
-		pep_reject_conn(sk, skb, PN_PIPE_ERR_INVALID_PARAM);
-		return -EINVAL;
-	}
-	peer_type = hdr->other_pep_type << 8;
-
-	if (unlikely(sk->sk_state != TCP_LISTEN) || sk_acceptq_is_full(sk)) {
-		pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE);
-		return -ENOBUFS;
-	}
+	if (hdr->error_code != PN_PIPE_NO_ERROR)
+		return -ECONNREFUSED;
 
-	/* Parse sub-blocks (options) */
+	/* Parse sub-blocks */
 	n_sb = hdr->data[4];
 	while (n_sb > 0) {
-		u8 type, buf[1], len = sizeof(buf);
+		u8 type, buf[6], len = sizeof(buf);
 		const u8 *data = pep_get_sb(skb, &type, &len, buf);
 
 		if (data == NULL)
 			return -EINVAL;
+
 		switch (type) {
-		case PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE:
-			if (len < 1)
-				return -EINVAL;
-			peer_type = (peer_type & 0xff00) | data[0];
+		case PN_PIPE_SB_REQUIRED_FC_TX:
+			if (len < 2 || len < data[0])
+				break;
+			pn->tx_fc = pipe_negotiate_fc(data + 2, len - 2);
 			break;
-		case PN_PIPE_SB_ALIGNED_DATA:
-			aligned = data[0] != 0;
+
+		case PN_PIPE_SB_PREFERRED_FC_RX:
+			if (len < 2 || len < data[0])
+				break;
+			pn->rx_fc = pipe_negotiate_fc(data + 2, len - 2);
 			break;
+
 		}
 		n_sb--;
 	}
 
-	skb = skb_clone(skb, GFP_ATOMIC);
-	if (!skb)
-		return -ENOMEM;
+	return pipe_handler_send_created_ind(sk);
+}
 
-	/* Create a new to-be-accepted sock */
-	newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_ATOMIC, sk->sk_prot);
-	if (!newsk) {
-		kfree_skb(skb);
-		return -ENOMEM;
-	}
-	sock_init_data(NULL, newsk);
-	newsk->sk_state = TCP_SYN_RECV;
-	newsk->sk_backlog_rcv = pipe_do_rcv;
-	newsk->sk_protocol = sk->sk_protocol;
-	newsk->sk_destruct = pipe_destruct;
+/* Queue an skb to an actively connected sock.
+ * Socket lock must be held. */
+static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb)
+{
+	struct pep_sock *pn = pep_sk(sk);
+	struct pnpipehdr *hdr = pnp_hdr(skb);
+	int err = NET_RX_SUCCESS;
 
-	newpn = pep_sk(newsk);
-	pn_skb_get_dst_sockaddr(skb, &dst);
-	newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst);
-	newpn->pn_sk.resource = pn->pn_sk.resource;
-	skb_queue_head_init(&newpn->ctrlreq_queue);
-	newpn->pipe_handle = pipe_handle;
-	atomic_set(&newpn->tx_credits, 0);
-	newpn->peer_type = peer_type;
-	newpn->rx_credits = 0;
-	newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
-	newpn->init_enable = enabled;
-	newpn->aligned = aligned;
+	switch (hdr->message_id) {
+	case PNS_PIPE_ALIGNED_DATA:
+		__skb_pull(skb, 1);
+		/* fall through */
+	case PNS_PIPE_DATA:
+		__skb_pull(skb, 3); /* Pipe data header */
+		if (!pn_flow_safe(pn->rx_fc)) {
+			err = sock_queue_rcv_skb(sk, skb);
+			if (!err)
+				return NET_RX_SUCCESS;
+			err = NET_RX_DROP;
+			break;
+		}
 
-	BUG_ON(!skb_queue_empty(&newsk->sk_receive_queue));
-	skb_queue_head(&newsk->sk_receive_queue, skb);
-	if (!sock_flag(sk, SOCK_DEAD))
-		sk->sk_data_ready(sk, 0);
+		if (pn->rx_credits == 0) {
+			atomic_inc(&sk->sk_drops);
+			err = NET_RX_DROP;
+			break;
+		}
+		pn->rx_credits--;
+		skb->dev = NULL;
+		skb_set_owner_r(skb, sk);
+		err = skb->len;
+		skb_queue_tail(&sk->sk_receive_queue, skb);
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_data_ready(sk, err);
+		return NET_RX_SUCCESS;
 
-	sk_acceptq_added(sk);
-	sk_add_node(newsk, &pn->ackq);
-	return 0;
+	case PNS_PEP_CONNECT_RESP:
+		if (sk->sk_state != TCP_SYN_SENT)
+			break;
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_state_change(sk);
+		if (pep_connresp_rcv(sk, skb)) {
+			sk->sk_state = TCP_CLOSE_WAIT;
+			break;
+		}
+
+		sk->sk_state = TCP_ESTABLISHED;
+		if (!pn_flow_safe(pn->tx_fc)) {
+			atomic_set(&pn->tx_credits, 1);
+			sk->sk_write_space(sk);
+		}
+		pipe_grant_credits(sk, GFP_ATOMIC);
+		break;
+
+	case PNS_PEP_DISCONNECT_RESP:
+		/* sock should already be dead, nothing to do */
+		break;
+
+	case PNS_PEP_STATUS_IND:
+		pipe_rcv_status(sk, skb);
+		break;
+	}
+	kfree_skb(skb);
+	return err;
 }
 
 /* Listening sock must be locked */
@@ -847,7 +636,6 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
 	struct sock *sknode;
 	struct pnpipehdr *hdr;
 	struct sockaddr_pn dst;
-	int err = NET_RX_SUCCESS;
 	u8 pipe_handle;
 
 	if (!pskb_may_pull(skb, sizeof(*hdr)))
@@ -865,26 +653,18 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
 	if (sknode)
 		return sk_receive_skb(sknode, skb, 1);
 
-	/* Look for a pipe handle pending accept */
-	sknode = pep_find_pipe(&pn->ackq, &dst, pipe_handle);
-	if (sknode) {
-		sock_put(sknode);
-		if (net_ratelimit())
-			printk(KERN_WARNING"Phonet unconnected PEP ignored");
-		err = NET_RX_DROP;
-		goto drop;
-	}
-
 	switch (hdr->message_id) {
 	case PNS_PEP_CONNECT_REQ:
-		err = pep_connreq_rcv(sk, skb);
-		break;
-
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNS_PEP_CONNECT_RESP:
-		err = pep_connresp_rcv(sk, skb);
-		break;
-#endif
+		if (sk->sk_state != TCP_LISTEN || sk_acceptq_is_full(sk)) {
+			pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE,
+					GFP_ATOMIC);
+			break;
+		}
+		skb_queue_head(&sk->sk_receive_queue, skb);
+		sk_acceptq_added(sk);
+		if (!sock_flag(sk, SOCK_DEAD))
+			sk->sk_data_ready(sk, 0);
+		return NET_RX_SUCCESS;
 
 	case PNS_PEP_DISCONNECT_REQ:
 		pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
@@ -898,12 +678,17 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb)
 	case PNS_PEP_ENABLE_REQ:
 	case PNS_PEP_DISABLE_REQ:
 		/* invalid handle is not even allowed here! */
+		break;
+
 	default:
-		err = NET_RX_DROP;
+		if ((1 << sk->sk_state)
+				& ~(TCPF_CLOSE|TCPF_LISTEN|TCPF_CLOSE_WAIT))
+			/* actively connected socket */
+			return pipe_handler_do_rcv(sk, skb);
 	}
 drop:
 	kfree_skb(skb);
-	return err;
+	return NET_RX_SUCCESS;
 }
 
 static int pipe_do_remove(struct sock *sk)
@@ -912,20 +697,16 @@ static int pipe_do_remove(struct sock *sk)
 	struct pnpipehdr *ph;
 	struct sk_buff *skb;
 
-	skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_KERNEL);
+	skb = pep_alloc_skb(sk, NULL, 0, GFP_KERNEL);
 	if (!skb)
 		return -ENOMEM;
 
-	skb_reserve(skb, MAX_PNPIPE_HEADER);
-	__skb_push(skb, sizeof(*ph));
-	skb_reset_transport_header(skb);
 	ph = pnp_hdr(skb);
 	ph->utid = 0;
 	ph->message_id = PNS_PIPE_REMOVE_REQ;
 	ph->pipe_handle = pn->pipe_handle;
 	ph->data[0] = PAD;
-
-	return pn_skb_send(sk, skb, &pipe_srv);
+	return pn_skb_send(sk, skb, NULL);
 }
 
 /* associated socket ceases to exist */
@@ -938,29 +719,15 @@ static void pep_sock_close(struct sock *sk, long timeout)
 	sk_common_release(sk);
 
 	lock_sock(sk);
-	if (sk->sk_state == TCP_LISTEN) {
-		/* Destroy the listen queue */
-		struct sock *sknode;
-		struct hlist_node *p, *n;
-
-		sk_for_each_safe(sknode, p, n, &pn->ackq)
-			sk_del_node_init(sknode);
-		sk->sk_state = TCP_CLOSE;
-	} else if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED))
-		/* Forcefully remove dangling Phonet pipe */
-		pipe_do_remove(sk);
-
-#ifdef CONFIG_PHONET_PIPECTRLR
-	if (pn->pipe_state != PIPE_IDLE) {
-		/* send pep disconnect request */
-		pipe_handler_send_req(sk,
-				PNS_PEP_DISCONNECT_UTID, PNS_PEP_DISCONNECT_REQ,
-				GFP_KERNEL);
-
-		pn->pipe_state = PIPE_IDLE;
-		sk->sk_state = TCP_CLOSE;
+	if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED)) {
+		if (sk->sk_backlog_rcv == pipe_do_rcv)
+			/* Forcefully remove dangling Phonet pipe */
+			pipe_do_remove(sk);
+		else
+			pipe_handler_request(sk, PNS_PEP_DISCONNECT_REQ, PAD,
+						NULL, 0);
 	}
-#endif
+	sk->sk_state = TCP_CLOSE;
 
 	ifindex = pn->ifindex;
 	pn->ifindex = 0;
@@ -971,86 +738,141 @@ static void pep_sock_close(struct sock *sk, long timeout)
 	sock_put(sk);
 }
 
-static int pep_wait_connreq(struct sock *sk, int noblock)
+static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)
 {
-	struct task_struct *tsk = current;
-	struct pep_sock *pn = pep_sk(sk);
-	long timeo = sock_rcvtimeo(sk, noblock);
-
-	for (;;) {
-		DEFINE_WAIT(wait);
+	struct pep_sock *pn = pep_sk(sk), *newpn;
+	struct sock *newsk = NULL;
+	struct sk_buff *skb;
+	struct pnpipehdr *hdr;
+	struct sockaddr_pn dst, src;
+	int err;
+	u16 peer_type;
+	u8 pipe_handle, enabled, n_sb;
+	u8 aligned = 0;
 
-		if (sk->sk_state != TCP_LISTEN)
-			return -EINVAL;
-		if (!hlist_empty(&pn->ackq))
-			break;
-		if (!timeo)
-			return -EWOULDBLOCK;
-		if (signal_pending(tsk))
-			return sock_intr_errno(timeo);
+	skb = skb_recv_datagram(sk, 0, flags & O_NONBLOCK, errp);
+	if (!skb)
+		return NULL;
 
-		prepare_to_wait_exclusive(sk_sleep(sk), &wait,
-						TASK_INTERRUPTIBLE);
-		release_sock(sk);
-		timeo = schedule_timeout(timeo);
-		lock_sock(sk);
-		finish_wait(sk_sleep(sk), &wait);
+	lock_sock(sk);
+	if (sk->sk_state != TCP_LISTEN) {
+		err = -EINVAL;
+		goto drop;
 	}
+	sk_acceptq_removed(sk);
 
-	return 0;
-}
+	err = -EPROTO;
+	if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
+		goto drop;
 
-static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp)
-{
-	struct pep_sock *pn = pep_sk(sk);
-	struct sock *newsk = NULL;
-	struct sk_buff *oskb;
-	int err;
+	hdr = pnp_hdr(skb);
+	pipe_handle = hdr->pipe_handle;
+	switch (hdr->state_after_connect) {
+	case PN_PIPE_DISABLE:
+		enabled = 0;
+		break;
+	case PN_PIPE_ENABLE:
+		enabled = 1;
+		break;
+	default:
+		pep_reject_conn(sk, skb, PN_PIPE_ERR_INVALID_PARAM,
+				GFP_KERNEL);
+		goto drop;
+	}
+	peer_type = hdr->other_pep_type << 8;
 
-	lock_sock(sk);
-	err = pep_wait_connreq(sk, flags & O_NONBLOCK);
-	if (err)
-		goto out;
+	/* Parse sub-blocks (options) */
+	n_sb = hdr->data[4];
+	while (n_sb > 0) {
+		u8 type, buf[1], len = sizeof(buf);
+		const u8 *data = pep_get_sb(skb, &type, &len, buf);
 
-	newsk = __sk_head(&pn->ackq);
+		if (data == NULL)
+			goto drop;
+		switch (type) {
+		case PN_PIPE_SB_CONNECT_REQ_PEP_SUB_TYPE:
+			if (len < 1)
+				goto drop;
+			peer_type = (peer_type & 0xff00) | data[0];
+			break;
+		case PN_PIPE_SB_ALIGNED_DATA:
+			aligned = data[0] != 0;
+			break;
+		}
+		n_sb--;
+	}
 
-	oskb = skb_dequeue(&newsk->sk_receive_queue);
-	err = pep_accept_conn(newsk, oskb);
-	if (err) {
-		skb_queue_head(&newsk->sk_receive_queue, oskb);
+	/* Check for duplicate pipe handle */
+	newsk = pep_find_pipe(&pn->hlist, &dst, pipe_handle);
+	if (unlikely(newsk)) {
+		__sock_put(newsk);
 		newsk = NULL;
-		goto out;
+		pep_reject_conn(sk, skb, PN_PIPE_ERR_PEP_IN_USE, GFP_KERNEL);
+		goto drop;
+	}
+
+	/* Create a new to-be-accepted sock */
+	newsk = sk_alloc(sock_net(sk), PF_PHONET, GFP_KERNEL, sk->sk_prot);
+	if (!newsk) {
+		pep_reject_conn(sk, skb, PN_PIPE_ERR_OVERLOAD, GFP_KERNEL);
+		err = -ENOBUFS;
+		goto drop;
 	}
-	kfree_skb(oskb);
 
+	sock_init_data(NULL, newsk);
+	newsk->sk_state = TCP_SYN_RECV;
+	newsk->sk_backlog_rcv = pipe_do_rcv;
+	newsk->sk_protocol = sk->sk_protocol;
+	newsk->sk_destruct = pipe_destruct;
+
+	newpn = pep_sk(newsk);
+	pn_skb_get_dst_sockaddr(skb, &dst);
+	pn_skb_get_src_sockaddr(skb, &src);
+	newpn->pn_sk.sobject = pn_sockaddr_get_object(&dst);
+	newpn->pn_sk.dobject = pn_sockaddr_get_object(&src);
+	newpn->pn_sk.resource = pn_sockaddr_get_resource(&dst);
 	sock_hold(sk);
-	pep_sk(newsk)->listener = sk;
+	newpn->listener = sk;
+	skb_queue_head_init(&newpn->ctrlreq_queue);
+	newpn->pipe_handle = pipe_handle;
+	atomic_set(&newpn->tx_credits, 0);
+	newpn->ifindex = 0;
+	newpn->peer_type = peer_type;
+	newpn->rx_credits = 0;
+	newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
+	newpn->init_enable = enabled;
+	newpn->aligned = aligned;
 
-	sock_hold(newsk);
-	sk_del_node_init(newsk);
-	sk_acceptq_removed(sk);
+	err = pep_accept_conn(newsk, skb);
+	if (err) {
+		sock_put(newsk);
+		newsk = NULL;
+		goto drop;
+	}
 	sk_add_node(newsk, &pn->hlist);
-	__sock_put(newsk);
-
-out:
+drop:
 	release_sock(sk);
+	kfree_skb(skb);
 	*errp = err;
 	return newsk;
 }
 
-#ifdef CONFIG_PHONET_PIPECTRLR
 static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len)
 {
 	struct pep_sock *pn = pep_sk(sk);
-	struct sockaddr_pn *spn =  (struct sockaddr_pn *)addr;
-
-	memcpy(&pn->remote_pep, spn, sizeof(struct sockaddr_pn));
+	int err;
+	u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD };
 
-	return pipe_handler_send_req(sk,
-			PNS_PEP_CONNECT_UTID, PNS_PEP_CONNECT_REQ,
-			GFP_ATOMIC);
+	pn->pipe_handle = 1; /* anything but INVALID_HANDLE */
+	err = pipe_handler_request(sk, PNS_PEP_CONNECT_REQ,
+					PN_PIPE_ENABLE, data, 4);
+	if (err) {
+		pn->pipe_handle = PN_PIPE_INVALID_HANDLE;
+		return err;
+	}
+	sk->sk_state = TCP_SYN_SENT;
+	return 0;
 }
-#endif
 
 static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
@@ -1081,10 +903,18 @@ static int pep_init(struct sock *sk)
 {
 	struct pep_sock *pn = pep_sk(sk);
 
-	INIT_HLIST_HEAD(&pn->ackq);
+	sk->sk_destruct = pipe_destruct;
 	INIT_HLIST_HEAD(&pn->hlist);
+	pn->listener = NULL;
 	skb_queue_head_init(&pn->ctrlreq_queue);
+	atomic_set(&pn->tx_credits, 0);
+	pn->ifindex = 0;
+	pn->peer_type = 0;
 	pn->pipe_handle = PN_PIPE_INVALID_HANDLE;
+	pn->rx_credits = 0;
+	pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL;
+	pn->init_enable = 1;
+	pn->aligned = 0;
 	return 0;
 }
 
@@ -1103,18 +933,6 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
 
 	lock_sock(sk);
 	switch (optname) {
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNPIPE_PIPE_HANDLE:
-		if (val) {
-			if (pn->pipe_state > PIPE_IDLE) {
-				err = -EFAULT;
-				break;
-			}
-			pn->pipe_handle = val;
-			break;
-		}
-#endif
-
 	case PNPIPE_ENCAP:
 		if (val && val != PNPIPE_ENCAP_IP) {
 			err = -EINVAL;
@@ -1141,16 +959,6 @@ static int pep_setsockopt(struct sock *sk, int level, int optname,
 		}
 		goto out_norel;
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNPIPE_ENABLE:
-		if (pn->pipe_state <= PIPE_IDLE) {
-			err = -ENOTCONN;
-			break;
-		}
-		err = pipe_handler_enable_pipe(sk, val);
-		break;
-#endif
-
 	default:
 		err = -ENOPROTOOPT;
 	}
@@ -1180,13 +988,11 @@ static int pep_getsockopt(struct sock *sk, int level, int optname,
 		val = pn->ifindex;
 		break;
 
-#ifdef CONFIG_PHONET_PIPECTRLR
-	case PNPIPE_ENABLE:
-		if (pn->pipe_state <= PIPE_IDLE)
-			return -ENOTCONN;
-		val = pn->pipe_state != PIPE_DISABLED;
+	case PNPIPE_HANDLE:
+		val = pn->pipe_handle;
+		if (val == PN_PIPE_INVALID_HANDLE)
+			return -EINVAL;
 		break;
-#endif
 
 	default:
 		return -ENOPROTOOPT;
@@ -1222,11 +1028,7 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
 	} else
 		ph->message_id = PNS_PIPE_DATA;
 	ph->pipe_handle = pn->pipe_handle;
-#ifdef CONFIG_PHONET_PIPECTRLR
-	err = pn_skb_send(sk, skb, &pn->remote_pep);
-#else
-	err = pn_skb_send(sk, skb, &pipe_srv);
-#endif
+	err = pn_skb_send(sk, skb, NULL);
 
 	if (err && pn_flow_safe(pn->tx_fc))
 		atomic_inc(&pn->tx_credits);
@@ -1253,7 +1055,7 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
 	if (!skb)
 		return err;
 
-	skb_reserve(skb, MAX_PHONET_HEADER + 3);
+	skb_reserve(skb, MAX_PHONET_HEADER + 3 + pn->aligned);
 	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 	if (err < 0)
 		goto outfree;
@@ -1355,7 +1157,7 @@ struct sk_buff *pep_read(struct sock *sk)
 	struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
 
 	if (sk->sk_state == TCP_ESTABLISHED)
-		pipe_grant_credits(sk);
+		pipe_grant_credits(sk, GFP_ATOMIC);
 	return skb;
 }
 
@@ -1400,7 +1202,7 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,
 	}
 
 	if (sk->sk_state == TCP_ESTABLISHED)
-		pipe_grant_credits(sk);
+		pipe_grant_credits(sk, GFP_KERNEL);
 	release_sock(sk);
 copy:
 	msg->msg_flags |= MSG_EOR;
@@ -1424,9 +1226,9 @@ static void pep_sock_unhash(struct sock *sk)
 
 	lock_sock(sk);
 
-#ifndef CONFIG_PHONET_PIPECTRLR
-	if ((1 << sk->sk_state) & ~(TCPF_CLOSE|TCPF_LISTEN)) {
+	if (pn->listener != NULL) {
 		skparent = pn->listener;
+		pn->listener = NULL;
 		release_sock(sk);
 
 		pn = pep_sk(skparent);
@@ -1434,7 +1236,7 @@ static void pep_sock_unhash(struct sock *sk)
 		sk_del_node_init(sk);
 		sk = skparent;
 	}
-#endif
+
 	/* Unhash a listening sock only when it is closed
 	 * and all of its active connected pipes are closed. */
 	if (hlist_empty(&pn->hlist))
@@ -1448,9 +1250,7 @@ static void pep_sock_unhash(struct sock *sk)
 static struct proto pep_proto = {
 	.close		= pep_sock_close,
 	.accept		= pep_sock_accept,
-#ifdef CONFIG_PHONET_PIPECTRLR
 	.connect	= pep_sock_connect,
-#endif
 	.ioctl		= pep_ioctl,
 	.init		= pep_init,
 	.setsockopt	= pep_setsockopt,
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index 25f746d..b1adafa 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -225,15 +225,18 @@ static int pn_socket_autobind(struct socket *sock)
 	return 0; /* socket was already bound */
 }
 
-#ifdef CONFIG_PHONET_PIPECTRLR
 static int pn_socket_connect(struct socket *sock, struct sockaddr *addr,
 		int len, int flags)
 {
 	struct sock *sk = sock->sk;
+	struct pn_sock *pn = pn_sk(sk);
 	struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
-	long timeo;
+	struct task_struct *tsk = current;
+	long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 	int err;
 
+	if (pn_socket_autobind(sock))
+		return -ENOBUFS;
 	if (len < sizeof(struct sockaddr_pn))
 		return -EINVAL;
 	if (spn->spn_family != AF_PHONET)
@@ -243,82 +246,61 @@ static int pn_socket_connect(struct socket *sock, struct sockaddr *addr,
 
 	switch (sock->state) {
 	case SS_UNCONNECTED:
-		sk->sk_state = TCP_CLOSE;
-		break;
-	case SS_CONNECTING:
-		switch (sk->sk_state) {
-		case TCP_SYN_RECV:
-			sock->state = SS_CONNECTED;
+		if (sk->sk_state != TCP_CLOSE) {
 			err = -EISCONN;
 			goto out;
-		case TCP_CLOSE:
-			err = -EALREADY;
-			if (flags & O_NONBLOCK)
-				goto out;
-			goto wait_connect;
 		}
 		break;
-	case SS_CONNECTED:
-		switch (sk->sk_state) {
-		case TCP_SYN_RECV:
-			err = -EISCONN;
-			goto out;
-		case TCP_CLOSE:
-			sock->state = SS_UNCONNECTED;
-			break;
-		}
-		break;
-	case SS_DISCONNECTING:
-	case SS_FREE:
-		break;
+	case SS_CONNECTING:
+		err = -EALREADY;
+		goto out;
+	default:
+		err = -EISCONN;
+		goto out;
 	}
-	sk->sk_state = TCP_CLOSE;
-	sk_stream_kill_queues(sk);
 
+	pn->dobject = pn_sockaddr_get_object(spn);
+	pn->resource = pn_sockaddr_get_resource(spn);
 	sock->state = SS_CONNECTING;
+
 	err = sk->sk_prot->connect(sk, addr, len);
-	if (err < 0) {
+	if (err) {
 		sock->state = SS_UNCONNECTED;
-		sk->sk_state = TCP_CLOSE;
+		pn->dobject = 0;
 		goto out;
 	}
 
-	err = -EINPROGRESS;
-wait_connect:
-	if (sk->sk_state != TCP_SYN_RECV && (flags & O_NONBLOCK))
-		goto out;
-
-	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
-	release_sock(sk);
-
-	err = -ERESTARTSYS;
-	timeo = wait_event_interruptible_timeout(*sk_sleep(sk),
-			sk->sk_state != TCP_CLOSE,
-			timeo);
-
-	lock_sock(sk);
-	if (timeo < 0)
-		goto out; /* -ERESTARTSYS */
+	while (sk->sk_state == TCP_SYN_SENT) {
+		DEFINE_WAIT(wait);
 
-	err = -ETIMEDOUT;
-	if (timeo == 0 && sk->sk_state != TCP_SYN_RECV)
-		goto out;
+		if (!timeo) {
+			err = -EINPROGRESS;
+			goto out;
+		}
+		if (signal_pending(tsk)) {
+			err = sock_intr_errno(timeo);
+			goto out;
+		}
 
-	if (sk->sk_state != TCP_SYN_RECV) {
-		sock->state = SS_UNCONNECTED;
-		err = sock_error(sk);
-		if (!err)
-			err = -ECONNREFUSED;
-		goto out;
+		prepare_to_wait_exclusive(sk_sleep(sk), &wait,
+						TASK_INTERRUPTIBLE);
+		release_sock(sk);
+		timeo = schedule_timeout(timeo);
+		lock_sock(sk);
+		finish_wait(sk_sleep(sk), &wait);
 	}
-	sock->state = SS_CONNECTED;
-	err = 0;
 
+	if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED))
+		err = 0;
+	else if (sk->sk_state == TCP_CLOSE_WAIT)
+		err = -ECONNRESET;
+	else
+		err = -ECONNREFUSED;
+	sock->state = err ? SS_UNCONNECTED : SS_CONNECTED;
 out:
 	release_sock(sk);
 	return err;
 }
-#endif
 
 static int pn_socket_accept(struct socket *sock, struct socket *newsock,
 				int flags)
@@ -327,6 +309,9 @@ static int pn_socket_accept(struct socket *sock, struct socket *newsock,
 	struct sock *newsk;
 	int err;
 
+	if (unlikely(sk->sk_state != TCP_LISTEN))
+		return -EINVAL;
+
 	newsk = sk->sk_prot->accept(sk, flags, &err);
 	if (!newsk)
 		return err;
@@ -363,13 +348,8 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
 
 	poll_wait(file, sk_sleep(sk), wait);
 
-	switch (sk->sk_state) {
-	case TCP_LISTEN:
-		return hlist_empty(&pn->ackq) ? 0 : POLLIN;
-	case TCP_CLOSE:
+	if (sk->sk_state == TCP_CLOSE)
 		return POLLERR;
-	}
-
 	if (!skb_queue_empty(&sk->sk_receive_queue))
 		mask |= POLLIN | POLLRDNORM;
 	if (!skb_queue_empty(&pn->ctrlreq_queue))
@@ -428,19 +408,19 @@ static int pn_socket_listen(struct socket *sock, int backlog)
 	struct sock *sk = sock->sk;
 	int err = 0;
 
-	if (sock->state != SS_UNCONNECTED)
-		return -EINVAL;
 	if (pn_socket_autobind(sock))
 		return -ENOBUFS;
 
 	lock_sock(sk);
-	if (sk->sk_state != TCP_CLOSE) {
+	if (sock->state != SS_UNCONNECTED) {
 		err = -EINVAL;
 		goto out;
 	}
 
-	sk->sk_state = TCP_LISTEN;
-	sk->sk_ack_backlog = 0;
+	if (sk->sk_state != TCP_LISTEN) {
+		sk->sk_state = TCP_LISTEN;
+		sk->sk_ack_backlog = 0;
+	}
 	sk->sk_max_ack_backlog = backlog;
 out:
 	release_sock(sk);
@@ -488,11 +468,7 @@ const struct proto_ops phonet_stream_ops = {
 	.owner		= THIS_MODULE,
 	.release	= pn_socket_release,
 	.bind		= pn_socket_bind,
-#ifdef CONFIG_PHONET_PIPECTRLR
 	.connect	= pn_socket_connect,
-#else
-	.connect	= sock_no_connect,
-#endif
 	.socketpair	= sock_no_socketpair,
 	.accept		= pn_socket_accept,
 	.getname	= pn_socket_getname,
@@ -633,8 +609,8 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v)
 
 		seq_printf(seq, "%2d %04X:%04X:%02X %02X %08X:%08X %5d %lu "
 			"%d %p %d%n",
-			sk->sk_protocol, pn->sobject, 0, pn->resource,
-			sk->sk_state,
+			sk->sk_protocol, pn->sobject, pn->dobject,
+			pn->resource, sk->sk_state,
 			sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk),
 			sock_i_uid(sk), sock_i_ino(sk),
 			atomic_read(&sk->sk_refcnt), sk,
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 4123967..cce19f9 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -364,7 +364,6 @@ void rds_ib_exit(void)
 	rds_ib_sysctl_exit();
 	rds_ib_recv_exit();
 	rds_trans_unregister(&rds_ib_transport);
-	rds_ib_fmr_exit();
 }
 
 struct rds_transport rds_ib_transport = {
@@ -400,13 +399,9 @@ int rds_ib_init(void)
 
 	INIT_LIST_HEAD(&rds_ib_devices);
 
-	ret = rds_ib_fmr_init();
-	if (ret)
-		goto out;
-
 	ret = ib_register_client(&rds_ib_client);
 	if (ret)
-		goto out_fmr_exit;
+		goto out;
 
 	ret = rds_ib_sysctl_init();
 	if (ret)
@@ -430,8 +425,6 @@ out_sysctl:
 	rds_ib_sysctl_exit();
 out_ibreg:
 	rds_ib_unregister_client();
-out_fmr_exit:
-	rds_ib_fmr_exit();
 out:
 	return ret;
 }
diff --git a/net/rds/ib.h b/net/rds/ib.h
index e34ad03..4297d92 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -307,8 +307,6 @@ void *rds_ib_get_mr(struct scatterlist *sg, unsigned long nents,
 void rds_ib_sync_mr(void *trans_private, int dir);
 void rds_ib_free_mr(void *trans_private, int invalidate);
 void rds_ib_flush_mrs(void);
-int rds_ib_fmr_init(void);
-void rds_ib_fmr_exit(void);
 
 /* ib_recv.c */
 int rds_ib_recv_init(void);
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 18a833c..819c35a 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -38,8 +38,6 @@
 #include "ib.h"
 #include "xlist.h"
 
-static struct workqueue_struct *rds_ib_fmr_wq;
-
 static DEFINE_PER_CPU(unsigned long, clean_list_grace);
 #define CLEAN_LIST_BUSY_BIT 0
 
@@ -307,7 +305,7 @@ static struct rds_ib_mr *rds_ib_alloc_fmr(struct rds_ib_device *rds_ibdev)
 	int err = 0, iter = 0;
 
 	if (atomic_read(&pool->dirty_count) >= pool->max_items / 10)
-		queue_delayed_work(rds_ib_fmr_wq, &pool->flush_worker, 10);
+		schedule_delayed_work(&pool->flush_worker, 10);
 
 	while (1) {
 		ibmr = rds_ib_reuse_fmr(pool);
@@ -696,24 +694,6 @@ out_nolock:
 	return ret;
 }
 
-int rds_ib_fmr_init(void)
-{
-	rds_ib_fmr_wq = create_workqueue("rds_fmr_flushd");
-	if (!rds_ib_fmr_wq)
-		return -ENOMEM;
-	return 0;
-}
-
-/*
- * By the time this is called all the IB devices should have been torn down and
- * had their pools freed.  As each pool is freed its work struct is waited on,
- * so the pool flushing work queue should be idle by the time we get here.
- */
-void rds_ib_fmr_exit(void)
-{
-	destroy_workqueue(rds_ib_fmr_wq);
-}
-
 static void rds_ib_mr_pool_flush_worker(struct work_struct *work)
 {
 	struct rds_ib_mr_pool *pool = container_of(work, struct rds_ib_mr_pool, flush_worker.work);
@@ -741,7 +721,7 @@ void rds_ib_free_mr(void *trans_private, int invalidate)
 	/* If we've pinned too many pages, request a flush */
 	if (atomic_read(&pool->free_pinned) >= pool->max_free_pinned ||
 	    atomic_read(&pool->dirty_count) >= pool->max_items / 10)
-		queue_delayed_work(rds_ib_fmr_wq, &pool->flush_worker, 10);
+		schedule_delayed_work(&pool->flush_worker, 10);
 
 	if (invalidate) {
 		if (likely(!in_interrupt())) {
@@ -749,8 +729,7 @@ void rds_ib_free_mr(void *trans_private, int invalidate)
 		} else {
 			/* We get here if the user created a MR marked
 			 * as use_once and invalidate at the same time. */
-			queue_delayed_work(rds_ib_fmr_wq,
-					   &pool->flush_worker, 10);
+			schedule_delayed_work(&pool->flush_worker, 10);
 		}
 	}
 
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 9542449..da8adac 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -50,7 +50,6 @@ rdsdebug(char *fmt, ...)
 #define RDS_FRAG_SIZE	((unsigned int)(1 << RDS_FRAG_SHIFT))
 
 #define RDS_CONG_MAP_BYTES	(65536 / 8)
-#define RDS_CONG_MAP_LONGS	(RDS_CONG_MAP_BYTES / sizeof(unsigned long))
 #define RDS_CONG_MAP_PAGES	(PAGE_ALIGN(RDS_CONG_MAP_BYTES) / PAGE_SIZE)
 #define RDS_CONG_MAP_PAGE_BITS	(PAGE_SIZE * 8)
 
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index d952e7e..5ee0c62 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -803,7 +803,6 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
 
 		rose_insert_socket(sk);		/* Finish the bind */
 	}
-rose_try_next_neigh:
 	rose->dest_addr   = addr->srose_addr;
 	rose->dest_call   = addr->srose_call;
 	rose->rand        = ((long)rose & 0xFFFF) + rose->lci;
@@ -865,12 +864,6 @@ rose_try_next_neigh:
 	}
 
 	if (sk->sk_state != TCP_ESTABLISHED) {
-	/* Try next neighbour */
-		rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic, 0);
-		if (rose->neighbour)
-			goto rose_try_next_neigh;
-
-		/* No more neighbours */
 		sock->state = SS_UNCONNECTED;
 		err = sock_error(sk);	/* Always set at this point */
 		goto out_release;
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c
index b4fdaac..88a77e9 100644
--- a/net/rose/rose_route.c
+++ b/net/rose/rose_route.c
@@ -674,29 +674,34 @@ struct rose_route *rose_route_free_lci(unsigned int lci, struct rose_neigh *neig
  *	Find a neighbour or a route given a ROSE address.
  */
 struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
-	unsigned char *diagnostic, int new)
+	unsigned char *diagnostic, int route_frame)
 {
 	struct rose_neigh *res = NULL;
 	struct rose_node *node;
 	int failed = 0;
 	int i;
 
-	if (!new) spin_lock_bh(&rose_node_list_lock);
+	if (!route_frame) spin_lock_bh(&rose_node_list_lock);
 	for (node = rose_node_list; node != NULL; node = node->next) {
 		if (rosecmpm(addr, &node->address, node->mask) == 0) {
 			for (i = 0; i < node->count; i++) {
-				if (new) {
-					if (node->neighbour[i]->restarted) {
-						res = node->neighbour[i];
-						goto out;
-					}
+				if (node->neighbour[i]->restarted) {
+					res = node->neighbour[i];
+					goto out;
 				}
-				else {
+			}
+		}
+	}
+	if (!route_frame) { /* connect request */
+		for (node = rose_node_list; node != NULL; node = node->next) {
+			if (rosecmpm(addr, &node->address, node->mask) == 0) {
+				for (i = 0; i < node->count; i++) {
 					if (!rose_ftimer_running(node->neighbour[i])) {
 						res = node->neighbour[i];
+						failed = 0;
 						goto out;
-					} else
-						failed = 1;
+					}
+					failed = 1;
 				}
 			}
 		}
@@ -711,8 +716,7 @@ struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
 	}
 
 out:
-	if (!new) spin_unlock_bh(&rose_node_list_lock);
-
+	if (!route_frame) spin_unlock_bh(&rose_node_list_lock);
 	return res;
 }
 
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index d763793..43ea7de 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -25,6 +25,7 @@
 #include <keys/user-type.h>
 #include "ar-internal.h"
 
+static int rxrpc_vet_description_s(const char *);
 static int rxrpc_instantiate(struct key *, const void *, size_t);
 static int rxrpc_instantiate_s(struct key *, const void *, size_t);
 static void rxrpc_destroy(struct key *);
@@ -52,6 +53,7 @@ EXPORT_SYMBOL(key_type_rxrpc);
  */
 struct key_type key_type_rxrpc_s = {
 	.name		= "rxrpc_s",
+	.vet_description = rxrpc_vet_description_s,
 	.instantiate	= rxrpc_instantiate_s,
 	.match		= user_match,
 	.destroy	= rxrpc_destroy_s,
@@ -59,6 +61,23 @@ struct key_type key_type_rxrpc_s = {
 };
 
 /*
+ * Vet the description for an RxRPC server key
+ */
+static int rxrpc_vet_description_s(const char *desc)
+{
+	unsigned long num;
+	char *p;
+
+	num = simple_strtoul(desc, &p, 10);
+	if (*p != ':' || num > 65535)
+		return -EINVAL;
+	num = simple_strtoul(p + 1, &p, 10);
+	if (*p || num < 1 || num > 255)
+		return -EINVAL;
+	return 0;
+}
+
+/*
  * parse an RxKAD type XDR format token
  * - the caller guarantees we have at least 4 words
  */
diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c
index a53fb25..55b93dc 100644
--- a/net/rxrpc/ar-peer.c
+++ b/net/rxrpc/ar-peer.c
@@ -36,31 +36,15 @@ static void rxrpc_destroy_peer(struct work_struct *work);
 static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer)
 {
 	struct rtable *rt;
-	struct flowi fl;
-	int ret;
 
 	peer->if_mtu = 1500;
 
-	memset(&fl, 0, sizeof(fl));
-
-	switch (peer->srx.transport.family) {
-	case AF_INET:
-		fl.oif = 0;
-		fl.proto = IPPROTO_UDP,
-		fl.fl4_dst = peer->srx.transport.sin.sin_addr.s_addr;
-		fl.fl4_src = 0;
-		fl.fl4_tos = 0;
-		/* assume AFS.CM talking to AFS.FS */
-		fl.fl_ip_sport = htons(7001);
-		fl.fl_ip_dport = htons(7000);
-		break;
-	default:
-		BUG();
-	}
-
-	ret = ip_route_output_key(&init_net, &rt, &fl);
-	if (ret < 0) {
-		_leave(" [route err %d]", ret);
+	rt = ip_route_output_ports(&init_net, NULL,
+				   peer->srx.transport.sin.sin_addr.s_addr, 0,
+				   htons(7000), htons(7001),
+				   IPPROTO_UDP, 0, 0);
+	if (IS_ERR(rt)) {
+		_leave(" [route err %ld]", PTR_ERR(rt));
 		return;
 	}
 
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index f04d4a4..a7a5583 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -126,6 +126,17 @@ config NET_SCH_RED
 	  To compile this code as a module, choose M here: the
 	  module will be called sch_red.
 
+config NET_SCH_SFB
+	tristate "Stochastic Fair Blue (SFB)"
+	---help---
+	  Say Y here if you want to use the Stochastic Fair Blue (SFB)
+	  packet scheduling algorithm.
+
+	  See the top of <file:net/sched/sch_sfb.c> for more details.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called sch_sfb.
+
 config NET_SCH_SFQ
 	tristate "Stochastic Fairness Queueing (SFQ)"
 	---help---
@@ -205,6 +216,29 @@ config NET_SCH_DRR
 
 	  If unsure, say N.
 
+config NET_SCH_MQPRIO
+	tristate "Multi-queue priority scheduler (MQPRIO)"
+	help
+	  Say Y here if you want to use the Multi-queue Priority scheduler.
+	  This scheduler allows QOS to be offloaded on NICs that have support
+	  for offloading QOS schedulers.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called sch_mqprio.
+
+	  If unsure, say N.
+
+config NET_SCH_CHOKE
+	tristate "CHOose and Keep responsive flow scheduler (CHOKE)"
+	help
+	  Say Y here if you want to use the CHOKe packet scheduler (CHOose
+	  and Keep for responsive flows, CHOose and Kill for unresponsive
+	  flows). This is a variation of RED which trys to penalize flows
+	  that monopolize the queue.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called sch_choke.
+
 config NET_SCH_INGRESS
 	tristate "Ingress Qdisc"
 	depends on NET_CLS_ACT
@@ -243,7 +277,7 @@ config NET_CLS_TCINDEX
 
 config NET_CLS_ROUTE4
 	tristate "Routing decision (ROUTE)"
-	select NET_CLS_ROUTE
+	select IP_ROUTE_CLASSID
 	select NET_CLS
 	---help---
 	  If you say Y here, you will be able to classify packets
@@ -252,9 +286,6 @@ config NET_CLS_ROUTE4
 	  To compile this code as a module, choose M here: the
 	  module will be called cls_route.
 
-config NET_CLS_ROUTE
-	bool
-
 config NET_CLS_FW
 	tristate "Netfilter mark (FW)"
 	select NET_CLS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index 960f5db..2e77b8d 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_SCH_RED)	+= sch_red.o
 obj-$(CONFIG_NET_SCH_GRED)	+= sch_gred.o
 obj-$(CONFIG_NET_SCH_INGRESS)	+= sch_ingress.o 
 obj-$(CONFIG_NET_SCH_DSMARK)	+= sch_dsmark.o
+obj-$(CONFIG_NET_SCH_SFB)	+= sch_sfb.o
 obj-$(CONFIG_NET_SCH_SFQ)	+= sch_sfq.o
 obj-$(CONFIG_NET_SCH_TBF)	+= sch_tbf.o
 obj-$(CONFIG_NET_SCH_TEQL)	+= sch_teql.o
@@ -32,6 +33,9 @@ obj-$(CONFIG_NET_SCH_MULTIQ)	+= sch_multiq.o
 obj-$(CONFIG_NET_SCH_ATM)	+= sch_atm.o
 obj-$(CONFIG_NET_SCH_NETEM)	+= sch_netem.o
 obj-$(CONFIG_NET_SCH_DRR)	+= sch_drr.o
+obj-$(CONFIG_NET_SCH_MQPRIO)	+= sch_mqprio.o
+obj-$(CONFIG_NET_SCH_CHOKE)	+= sch_choke.o
+
 obj-$(CONFIG_NET_CLS_U32)	+= cls_u32.o
 obj-$(CONFIG_NET_CLS_ROUTE4)	+= cls_route.o
 obj-$(CONFIG_NET_CLS_FW)	+= cls_fw.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 23b25f8..15873e1 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -78,7 +78,7 @@ static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
 			   struct tc_action *a, struct tcf_hashinfo *hinfo)
 {
 	struct tcf_common *p;
-	int err = 0, index = -1,i = 0, s_i = 0, n_i = 0;
+	int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
 	struct nlattr *nest;
 
 	read_lock_bh(hinfo->lock);
@@ -126,7 +126,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
 {
 	struct tcf_common *p, *s_p;
 	struct nlattr *nest;
-	int i= 0, n_i = 0;
+	int i = 0, n_i = 0;
 
 	nest = nla_nest_start(skb, a->order);
 	if (nest == NULL)
@@ -138,7 +138,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a,
 		while (p != NULL) {
 			s_p = p->tcfc_next;
 			if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo))
-				 module_put(a->ops->owner);
+				module_put(a->ops->owner);
 			n_i++;
 			p = s_p;
 		}
@@ -447,7 +447,8 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 	nest = nla_nest_start(skb, TCA_OPTIONS);
 	if (nest == NULL)
 		goto nla_put_failure;
-	if ((err = tcf_action_dump_old(skb, a, bind, ref)) > 0) {
+	err = tcf_action_dump_old(skb, a, bind, ref);
+	if (err > 0) {
 		nla_nest_end(skb, nest);
 		return err;
 	}
@@ -491,7 +492,7 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
 	struct tc_action *a;
 	struct tc_action_ops *a_o;
 	char act_name[IFNAMSIZ];
-	struct nlattr *tb[TCA_ACT_MAX+1];
+	struct nlattr *tb[TCA_ACT_MAX + 1];
 	struct nlattr *kind;
 	int err;
 
@@ -549,9 +550,9 @@ struct tc_action *tcf_action_init_1(struct nlattr *nla, struct nlattr *est,
 		goto err_free;
 
 	/* module count goes up only when brand new policy is created
-	   if it exists and is only bound to in a_o->init() then
-	   ACT_P_CREATED is not returned (a zero is).
-	*/
+	 * if it exists and is only bound to in a_o->init() then
+	 * ACT_P_CREATED is not returned (a zero is).
+	 */
 	if (err != ACT_P_CREATED)
 		module_put(a_o->owner);
 	a->ops = a_o;
@@ -569,7 +570,7 @@ err_out:
 struct tc_action *tcf_action_init(struct nlattr *nla, struct nlattr *est,
 				  char *name, int ovr, int bind)
 {
-	struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
+	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
 	struct tc_action *head = NULL, *act, *act_prev = NULL;
 	int err;
 	int i;
@@ -697,7 +698,7 @@ act_get_notify(struct net *net, u32 pid, struct nlmsghdr *n,
 static struct tc_action *
 tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 pid)
 {
-	struct nlattr *tb[TCA_ACT_MAX+1];
+	struct nlattr *tb[TCA_ACT_MAX + 1];
 	struct tc_action *a;
 	int index;
 	int err;
@@ -770,7 +771,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 	struct tcamsg *t;
 	struct netlink_callback dcb;
 	struct nlattr *nest;
-	struct nlattr *tb[TCA_ACT_MAX+1];
+	struct nlattr *tb[TCA_ACT_MAX + 1];
 	struct nlattr *kind;
 	struct tc_action *a = create_a(0);
 	int err = -ENOMEM;
@@ -821,7 +822,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 	nlh->nlmsg_flags |= NLM_F_ROOT;
 	module_put(a->ops->owner);
 	kfree(a);
-	err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+	err = rtnetlink_send(skb, net, pid, RTNLGRP_TC,
+			     n->nlmsg_flags & NLM_F_ECHO);
 	if (err > 0)
 		return 0;
 
@@ -842,14 +844,14 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 	      u32 pid, int event)
 {
 	int i, ret;
-	struct nlattr *tb[TCA_ACT_MAX_PRIO+1];
+	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
 	struct tc_action *head = NULL, *act, *act_prev = NULL;
 
 	ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL);
 	if (ret < 0)
 		return ret;
 
-	if (event == RTM_DELACTION && n->nlmsg_flags&NLM_F_ROOT) {
+	if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) {
 		if (tb[1] != NULL)
 			return tca_action_flush(net, tb[1], n, pid);
 		else
@@ -892,7 +894,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 		/* now do the delete */
 		tcf_action_destroy(head, 0);
 		ret = rtnetlink_send(skb, net, pid, RTNLGRP_TC,
-				     n->nlmsg_flags&NLM_F_ECHO);
+				     n->nlmsg_flags & NLM_F_ECHO);
 		if (ret > 0)
 			return 0;
 		return ret;
@@ -936,7 +938,7 @@ static int tcf_add_notify(struct net *net, struct tc_action *a,
 	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
 	NETLINK_CB(skb).dst_group = RTNLGRP_TC;
 
-	err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, flags&NLM_F_ECHO);
+	err = rtnetlink_send(skb, net, pid, RTNLGRP_TC, flags & NLM_F_ECHO);
 	if (err > 0)
 		err = 0;
 	return err;
@@ -967,7 +969,7 @@ tcf_action_add(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
 
 	/* dump then free all the actions after update; inserted policy
 	 * stays intact
-	 * */
+	 */
 	ret = tcf_add_notify(net, act, pid, seq, RTM_NEWACTION, n->nlmsg_flags);
 	for (a = act; a; a = act) {
 		act = a->next;
@@ -993,8 +995,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 		return -EINVAL;
 	}
 
-	/* n->nlmsg_flags&NLM_F_CREATE
-	 * */
+	/* n->nlmsg_flags & NLM_F_CREATE */
 	switch (n->nlmsg_type) {
 	case RTM_NEWACTION:
 		/* we are going to assume all other flags
@@ -1003,7 +1004,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 		 * but since we want avoid ambiguity (eg when flags
 		 * is zero) then just set this
 		 */
-		if (n->nlmsg_flags&NLM_F_REPLACE)
+		if (n->nlmsg_flags & NLM_F_REPLACE)
 			ovr = 1;
 replay:
 		ret = tcf_action_add(net, tca[TCA_ACT_TAB], n, pid, ovr);
@@ -1028,7 +1029,7 @@ replay:
 static struct nlattr *
 find_dump_kind(const struct nlmsghdr *n)
 {
-	struct nlattr *tb1, *tb2[TCA_ACT_MAX+1];
+	struct nlattr *tb1, *tb2[TCA_ACT_MAX + 1];
 	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
 	struct nlattr *nla[TCAA_MAX + 1];
 	struct nlattr *kind;
@@ -1071,9 +1072,8 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
 	}
 
 	a_o = tc_lookup_action(kind);
-	if (a_o == NULL) {
+	if (a_o == NULL)
 		return 0;
-	}
 
 	memset(&a, 0, sizeof(struct tc_action));
 	a.ops = a_o;
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 83ddfc0..6cdf9ab 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -63,7 +63,7 @@ static int tcf_csum_init(struct nlattr *nla, struct nlattr *est,
 	if (nla == NULL)
 		return -EINVAL;
 
-	err = nla_parse_nested(tb, TCA_CSUM_MAX, nla,csum_policy);
+	err = nla_parse_nested(tb, TCA_CSUM_MAX, nla, csum_policy);
 	if (err < 0)
 		return err;
 
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index c2ed90a..2b4ab4b 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -50,7 +50,7 @@ static int gact_determ(struct tcf_gact *gact)
 }
 
 typedef int (*g_rand)(struct tcf_gact *gact);
-static g_rand gact_rand[MAX_RAND]= { NULL, gact_net_rand, gact_determ };
+static g_rand gact_rand[MAX_RAND] = { NULL, gact_net_rand, gact_determ };
 #endif /* CONFIG_GACT_PROB */
 
 static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
@@ -89,7 +89,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est,
 		pc = tcf_hash_create(parm->index, est, a, sizeof(*gact),
 				     bind, &gact_idx_gen, &gact_hash_info);
 		if (IS_ERR(pc))
-		    return PTR_ERR(pc);
+			return PTR_ERR(pc);
 		ret = ACT_P_CREATED;
 	} else {
 		if (!ovr) {
@@ -205,9 +205,9 @@ MODULE_LICENSE("GPL");
 static int __init gact_init_module(void)
 {
 #ifdef CONFIG_GACT_PROB
-	printk(KERN_INFO "GACT probability on\n");
+	pr_info("GACT probability on\n");
 #else
-	printk(KERN_INFO "GACT probability NOT on\n");
+	pr_info("GACT probability NOT on\n");
 #endif
 	return tcf_register_action(&act_gact_ops);
 }
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index c2a7c20..9fc211a 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -138,7 +138,7 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 		pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind,
 				     &ipt_idx_gen, &ipt_hash_info);
 		if (IS_ERR(pc))
-		    return PTR_ERR(pc);
+			return PTR_ERR(pc);
 		ret = ACT_P_CREATED;
 	} else {
 		if (!ovr) {
@@ -162,7 +162,8 @@ static int tcf_ipt_init(struct nlattr *nla, struct nlattr *est,
 	if (unlikely(!t))
 		goto err2;
 
-	if ((err = ipt_init_target(t, tname, hook)) < 0)
+	err = ipt_init_target(t, tname, hook);
+	if (err < 0)
 		goto err3;
 
 	spin_lock_bh(&ipt->tcf_lock);
@@ -212,8 +213,9 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,
 	bstats_update(&ipt->tcf_bstats, skb);
 
 	/* yes, we have to worry about both in and out dev
-	 worry later - danger - this API seems to have changed
-	 from earlier kernels */
+	 * worry later - danger - this API seems to have changed
+	 * from earlier kernels
+	 */
 	par.in       = skb->dev;
 	par.out      = NULL;
 	par.hooknum  = ipt->tcfi_hook;
@@ -253,9 +255,9 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind, int
 	struct tc_cnt c;
 
 	/* for simple targets kernel size == user size
-	** user name = target name
-	** for foolproof you need to not assume this
-	*/
+	 * user name = target name
+	 * for foolproof you need to not assume this
+	 */
 
 	t = kmemdup(ipt->tcfi_t, ipt->tcfi_t->u.user.target_size, GFP_ATOMIC);
 	if (unlikely(!t))
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index d765067..961386e 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -41,13 +41,13 @@ static struct tcf_hashinfo mirred_hash_info = {
 	.lock	=	&mirred_lock,
 };
 
-static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
+static int tcf_mirred_release(struct tcf_mirred *m, int bind)
 {
 	if (m) {
 		if (bind)
 			m->tcf_bindcnt--;
 		m->tcf_refcnt--;
-		if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
+		if (!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
 			list_del(&m->tcfm_list);
 			if (m->tcfm_dev)
 				dev_put(m->tcfm_dev);
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 178a4bd..762b027 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -69,7 +69,7 @@ static int tcf_nat_init(struct nlattr *nla, struct nlattr *est,
 		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
 				     &nat_idx_gen, &nat_hash_info);
 		if (IS_ERR(pc))
-		    return PTR_ERR(pc);
+			return PTR_ERR(pc);
 		p = to_tcf_nat(pc);
 		ret = ACT_P_CREATED;
 	} else {
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 445bef7..50c7c06 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -70,7 +70,7 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est,
 		pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind,
 				     &pedit_idx_gen, &pedit_hash_info);
 		if (IS_ERR(pc))
-		    return PTR_ERR(pc);
+			return PTR_ERR(pc);
 		p = to_pedit(pc);
 		keys = kmalloc(ksize, GFP_KERNEL);
 		if (keys == NULL) {
@@ -127,11 +127,9 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
 	int i, munged = 0;
 	unsigned int off;
 
-	if (skb_cloned(skb)) {
-		if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
-			return p->tcf_action;
-		}
-	}
+	if (skb_cloned(skb) &&
+	    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		return p->tcf_action;
 
 	off = skb_network_offset(skb);
 
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index e2f08b1..8a16307 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -22,8 +22,8 @@
 #include <net/act_api.h>
 #include <net/netlink.h>
 
-#define L2T(p,L)   qdisc_l2t((p)->tcfp_R_tab, L)
-#define L2T_P(p,L) qdisc_l2t((p)->tcfp_P_tab, L)
+#define L2T(p, L)   qdisc_l2t((p)->tcfp_R_tab, L)
+#define L2T_P(p, L) qdisc_l2t((p)->tcfp_P_tab, L)
 
 #define POL_TAB_MASK     15
 static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
@@ -37,8 +37,7 @@ static struct tcf_hashinfo police_hash_info = {
 };
 
 /* old policer structure from before tc actions */
-struct tc_police_compat
-{
+struct tc_police_compat {
 	u32			index;
 	int			action;
 	u32			limit;
@@ -139,7 +138,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
 static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
 				 struct tc_action *a, int ovr, int bind)
 {
-	unsigned h;
+	unsigned int h;
 	int ret = 0, err;
 	struct nlattr *tb[TCA_POLICE_MAX + 1];
 	struct tc_police *parm;
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 7287cff..a34a22d 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -47,7 +47,7 @@ static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result
 	/* print policy string followed by _ then packet count
 	 * Example if this was the 3rd packet and the string was "hello"
 	 * then it would look like "hello_3" (without quotes)
-	 **/
+	 */
 	pr_info("simple: %s_%d\n",
 	       (char *)d->tcfd_defdata, d->tcf_bstats.packets);
 	spin_unlock(&d->tcf_lock);
@@ -125,7 +125,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
 		pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
 				     &simp_idx_gen, &simp_hash_info);
 		if (IS_ERR(pc))
-		    return PTR_ERR(pc);
+			return PTR_ERR(pc);
 
 		d = to_defact(pc);
 		ret = alloc_defdata(d, defdata);
@@ -149,7 +149,7 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
 	return ret;
 }
 
-static inline int tcf_simp_cleanup(struct tc_action *a, int bind)
+static int tcf_simp_cleanup(struct tc_action *a, int bind)
 {
 	struct tcf_defact *d = a->priv;
 
@@ -158,8 +158,8 @@ static inline int tcf_simp_cleanup(struct tc_action *a, int bind)
 	return 0;
 }
 
-static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
-				int bind, int ref)
+static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
+			 int bind, int ref)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_defact *d = a->priv;
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 836f5fe..5f6f0c7 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -113,7 +113,7 @@ static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est,
 		pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind,
 				     &skbedit_idx_gen, &skbedit_hash_info);
 		if (IS_ERR(pc))
-		    return PTR_ERR(pc);
+			return PTR_ERR(pc);
 
 		d = to_skbedit(pc);
 		ret = ACT_P_CREATED;
@@ -144,7 +144,7 @@ static int tcf_skbedit_init(struct nlattr *nla, struct nlattr *est,
 	return ret;
 }
 
-static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind)
+static int tcf_skbedit_cleanup(struct tc_action *a, int bind)
 {
 	struct tcf_skbedit *d = a->priv;
 
@@ -153,8 +153,8 @@ static inline int tcf_skbedit_cleanup(struct tc_action *a, int bind)
 	return 0;
 }
 
-static inline int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
-				int bind, int ref)
+static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
+			    int bind, int ref)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tcf_skbedit *d = a->priv;
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 5fd0c28..bb2c523 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -85,7 +85,7 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
 	int rc = -ENOENT;
 
 	write_lock(&cls_mod_lock);
-	for (tp = &tcf_proto_base; (t=*tp) != NULL; tp = &t->next)
+	for (tp = &tcf_proto_base; (t = *tp) != NULL; tp = &t->next)
 		if (t == ops)
 			break;
 
@@ -111,7 +111,7 @@ static inline u32 tcf_auto_prio(struct tcf_proto *tp)
 	u32 first = TC_H_MAKE(0xC0000000U, 0U);
 
 	if (tp)
-		first = tp->prio-1;
+		first = tp->prio - 1;
 
 	return first;
 }
@@ -149,7 +149,8 @@ replay:
 
 	if (prio == 0) {
 		/* If no priority is given, user wants we allocated it. */
-		if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
+		if (n->nlmsg_type != RTM_NEWTFILTER ||
+		    !(n->nlmsg_flags & NLM_F_CREATE))
 			return -ENOENT;
 		prio = TC_H_MAKE(0x80000000U, 0U);
 	}
@@ -176,7 +177,8 @@ replay:
 	}
 
 	/* Is it classful? */
-	if ((cops = q->ops->cl_ops) == NULL)
+	cops = q->ops->cl_ops;
+	if (!cops)
 		return -EINVAL;
 
 	if (cops->tcf_chain == NULL)
@@ -196,10 +198,11 @@ replay:
 		goto errout;
 
 	/* Check the chain for existence of proto-tcf with this priority */
-	for (back = chain; (tp=*back) != NULL; back = &tp->next) {
+	for (back = chain; (tp = *back) != NULL; back = &tp->next) {
 		if (tp->prio >= prio) {
 			if (tp->prio == prio) {
-				if (!nprio || (tp->protocol != protocol && protocol))
+				if (!nprio ||
+				    (tp->protocol != protocol && protocol))
 					goto errout;
 			} else
 				tp = NULL;
@@ -216,7 +219,8 @@ replay:
 			goto errout;
 
 		err = -ENOENT;
-		if (n->nlmsg_type != RTM_NEWTFILTER || !(n->nlmsg_flags&NLM_F_CREATE))
+		if (n->nlmsg_type != RTM_NEWTFILTER ||
+		    !(n->nlmsg_flags & NLM_F_CREATE))
 			goto errout;
 
 
@@ -420,7 +424,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 
 	if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
 		return skb->len;
-	if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL)
+	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
 		return skb->len;
 
 	if (!tcm->tcm_parent)
@@ -429,7 +434,8 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 		q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
 	if (!q)
 		goto out;
-	if ((cops = q->ops->cl_ops) == NULL)
+	cops = q->ops->cl_ops;
+	if (!cops)
 		goto errout;
 	if (cops->tcf_chain == NULL)
 		goto errout;
@@ -444,8 +450,9 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 
 	s_t = cb->args[0];
 
-	for (tp=*chain, t=0; tp; tp = tp->next, t++) {
-		if (t < s_t) continue;
+	for (tp = *chain, t = 0; tp; tp = tp->next, t++) {
+		if (t < s_t)
+			continue;
 		if (TC_H_MAJ(tcm->tcm_info) &&
 		    TC_H_MAJ(tcm->tcm_info) != tp->prio)
 			continue;
@@ -468,10 +475,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
 		arg.skb = skb;
 		arg.cb = cb;
 		arg.w.stop = 0;
-		arg.w.skip = cb->args[1]-1;
+		arg.w.skip = cb->args[1] - 1;
 		arg.w.count = 0;
 		tp->ops->walk(tp, &arg.w);
-		cb->args[1] = arg.w.count+1;
+		cb->args[1] = arg.w.count + 1;
 		if (arg.w.stop)
 			break;
 	}
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index f23d915..8be8872 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -21,14 +21,12 @@
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
-struct basic_head
-{
+struct basic_head {
 	u32			hgenerator;
 	struct list_head	flist;
 };
 
-struct basic_filter
-{
+struct basic_filter {
 	u32			handle;
 	struct tcf_exts		exts;
 	struct tcf_ematch_tree	ematches;
@@ -92,8 +90,7 @@ static int basic_init(struct tcf_proto *tp)
 	return 0;
 }
 
-static inline void basic_delete_filter(struct tcf_proto *tp,
-				       struct basic_filter *f)
+static void basic_delete_filter(struct tcf_proto *tp, struct basic_filter *f)
 {
 	tcf_unbind_filter(tp, &f->res);
 	tcf_exts_destroy(tp, &f->exts);
@@ -135,9 +132,9 @@ static const struct nla_policy basic_policy[TCA_BASIC_MAX + 1] = {
 	[TCA_BASIC_EMATCHES]	= { .type = NLA_NESTED },
 };
 
-static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
-				  unsigned long base, struct nlattr **tb,
-				  struct nlattr *est)
+static int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
+			   unsigned long base, struct nlattr **tb,
+			   struct nlattr *est)
 {
 	int err = -EINVAL;
 	struct tcf_exts e;
@@ -203,7 +200,7 @@ static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 		} while (--i > 0 && basic_get(tp, head->hgenerator));
 
 		if (i <= 0) {
-			printk(KERN_ERR "Insufficient number of handles\n");
+			pr_err("Insufficient number of handles\n");
 			goto errout;
 		}
 
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index d49c40f..32a3351 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -56,7 +56,8 @@ static struct cgroup_subsys_state *cgrp_create(struct cgroup_subsys *ss,
 {
 	struct cgroup_cls_state *cs;
 
-	if (!(cs = kzalloc(sizeof(*cs), GFP_KERNEL)))
+	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+	if (!cs)
 		return ERR_PTR(-ENOMEM);
 
 	if (cgrp->parent)
@@ -94,8 +95,7 @@ static int cgrp_populate(struct cgroup_subsys *ss, struct cgroup *cgrp)
 	return cgroup_add_files(cgrp, ss, ss_files, ARRAY_SIZE(ss_files));
 }
 
-struct cls_cgroup_head
-{
+struct cls_cgroup_head {
 	u32			handle;
 	struct tcf_exts		exts;
 	struct tcf_ematch_tree	ematches;
@@ -166,7 +166,7 @@ static int cls_cgroup_change(struct tcf_proto *tp, unsigned long base,
 			     u32 handle, struct nlattr **tca,
 			     unsigned long *arg)
 {
-	struct nlattr *tb[TCA_CGROUP_MAX+1];
+	struct nlattr *tb[TCA_CGROUP_MAX + 1];
 	struct cls_cgroup_head *head = tp->root;
 	struct tcf_ematch_tree t;
 	struct tcf_exts e;
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 5b271a1..8ec0139 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -121,7 +121,7 @@ static u32 flow_get_proto_src(struct sk_buff *skb)
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ip_hdr(skb);
-		if (iph->frag_off & htons(IP_MF|IP_OFFSET))
+		if (iph->frag_off & htons(IP_MF | IP_OFFSET))
 			break;
 		poff = proto_ports_offset(iph->protocol);
 		if (poff >= 0 &&
@@ -163,7 +163,7 @@ static u32 flow_get_proto_dst(struct sk_buff *skb)
 		if (!pskb_network_may_pull(skb, sizeof(*iph)))
 			break;
 		iph = ip_hdr(skb);
-		if (iph->frag_off & htons(IP_MF|IP_OFFSET))
+		if (iph->frag_off & htons(IP_MF | IP_OFFSET))
 			break;
 		poff = proto_ports_offset(iph->protocol);
 		if (poff >= 0 &&
@@ -276,7 +276,7 @@ fallback:
 
 static u32 flow_get_rtclassid(const struct sk_buff *skb)
 {
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 	if (skb_dst(skb))
 		return skb_dst(skb)->tclassid;
 #endif
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 93b0a7b..26e7bc4 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -31,14 +31,12 @@
 
 #define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *))
 
-struct fw_head
-{
+struct fw_head {
 	struct fw_filter *ht[HTSIZE];
 	u32 mask;
 };
 
-struct fw_filter
-{
+struct fw_filter {
 	struct fw_filter	*next;
 	u32			id;
 	struct tcf_result	res;
@@ -53,7 +51,7 @@ static const struct tcf_ext_map fw_ext_map = {
 	.police = TCA_FW_POLICE
 };
 
-static __inline__ int fw_hash(u32 handle)
+static inline int fw_hash(u32 handle)
 {
 	if (HTSIZE == 4096)
 		return ((handle >> 24) & 0xFFF) ^
@@ -82,14 +80,14 @@ static __inline__ int fw_hash(u32 handle)
 static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
 			  struct tcf_result *res)
 {
-	struct fw_head *head = (struct fw_head*)tp->root;
+	struct fw_head *head = (struct fw_head *)tp->root;
 	struct fw_filter *f;
 	int r;
 	u32 id = skb->mark;
 
 	if (head != NULL) {
 		id &= head->mask;
-		for (f=head->ht[fw_hash(id)]; f; f=f->next) {
+		for (f = head->ht[fw_hash(id)]; f; f = f->next) {
 			if (f->id == id) {
 				*res = f->res;
 #ifdef CONFIG_NET_CLS_IND
@@ -105,7 +103,8 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
 		}
 	} else {
 		/* old method */
-		if (id && (TC_H_MAJ(id) == 0 || !(TC_H_MAJ(id^tp->q->handle)))) {
+		if (id && (TC_H_MAJ(id) == 0 ||
+			   !(TC_H_MAJ(id ^ tp->q->handle)))) {
 			res->classid = id;
 			res->class = 0;
 			return 0;
@@ -117,13 +116,13 @@ static int fw_classify(struct sk_buff *skb, struct tcf_proto *tp,
 
 static unsigned long fw_get(struct tcf_proto *tp, u32 handle)
 {
-	struct fw_head *head = (struct fw_head*)tp->root;
+	struct fw_head *head = (struct fw_head *)tp->root;
 	struct fw_filter *f;
 
 	if (head == NULL)
 		return 0;
 
-	for (f=head->ht[fw_hash(handle)]; f; f=f->next) {
+	for (f = head->ht[fw_hash(handle)]; f; f = f->next) {
 		if (f->id == handle)
 			return (unsigned long)f;
 	}
@@ -139,8 +138,7 @@ static int fw_init(struct tcf_proto *tp)
 	return 0;
 }
 
-static inline void
-fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f)
+static void fw_delete_filter(struct tcf_proto *tp, struct fw_filter *f)
 {
 	tcf_unbind_filter(tp, &f->res);
 	tcf_exts_destroy(tp, &f->exts);
@@ -156,8 +154,8 @@ static void fw_destroy(struct tcf_proto *tp)
 	if (head == NULL)
 		return;
 
-	for (h=0; h<HTSIZE; h++) {
-		while ((f=head->ht[h]) != NULL) {
+	for (h = 0; h < HTSIZE; h++) {
+		while ((f = head->ht[h]) != NULL) {
 			head->ht[h] = f->next;
 			fw_delete_filter(tp, f);
 		}
@@ -167,14 +165,14 @@ static void fw_destroy(struct tcf_proto *tp)
 
 static int fw_delete(struct tcf_proto *tp, unsigned long arg)
 {
-	struct fw_head *head = (struct fw_head*)tp->root;
-	struct fw_filter *f = (struct fw_filter*)arg;
+	struct fw_head *head = (struct fw_head *)tp->root;
+	struct fw_filter *f = (struct fw_filter *)arg;
 	struct fw_filter **fp;
 
 	if (head == NULL || f == NULL)
 		goto out;
 
-	for (fp=&head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) {
+	for (fp = &head->ht[fw_hash(f->id)]; *fp; fp = &(*fp)->next) {
 		if (*fp == f) {
 			tcf_tree_lock(tp);
 			*fp = f->next;
@@ -240,7 +238,7 @@ static int fw_change(struct tcf_proto *tp, unsigned long base,
 		     struct nlattr **tca,
 		     unsigned long *arg)
 {
-	struct fw_head *head = (struct fw_head*)tp->root;
+	struct fw_head *head = (struct fw_head *)tp->root;
 	struct fw_filter *f = (struct fw_filter *) *arg;
 	struct nlattr *opt = tca[TCA_OPTIONS];
 	struct nlattr *tb[TCA_FW_MAX + 1];
@@ -302,7 +300,7 @@ errout:
 
 static void fw_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
-	struct fw_head *head = (struct fw_head*)tp->root;
+	struct fw_head *head = (struct fw_head *)tp->root;
 	int h;
 
 	if (head == NULL)
@@ -332,7 +330,7 @@ static int fw_dump(struct tcf_proto *tp, unsigned long fh,
 		   struct sk_buff *skb, struct tcmsg *t)
 {
 	struct fw_head *head = (struct fw_head *)tp->root;
-	struct fw_filter *f = (struct fw_filter*)fh;
+	struct fw_filter *f = (struct fw_filter *)fh;
 	unsigned char *b = skb_tail_pointer(skb);
 	struct nlattr *nest;
 
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c
index 694dcd8..a9079053 100644
--- a/net/sched/cls_route.c
+++ b/net/sched/cls_route.c
@@ -23,34 +23,30 @@
 #include <net/pkt_cls.h>
 
 /*
-   1. For now we assume that route tags < 256.
-      It allows to use direct table lookups, instead of hash tables.
-   2. For now we assume that "from TAG" and "fromdev DEV" statements
-      are mutually  exclusive.
-   3. "to TAG from ANY" has higher priority, than "to ANY from XXX"
+ * 1. For now we assume that route tags < 256.
+ *    It allows to use direct table lookups, instead of hash tables.
+ * 2. For now we assume that "from TAG" and "fromdev DEV" statements
+ *    are mutually  exclusive.
+ * 3. "to TAG from ANY" has higher priority, than "to ANY from XXX"
  */
 
-struct route4_fastmap
-{
+struct route4_fastmap {
 	struct route4_filter	*filter;
 	u32			id;
 	int			iif;
 };
 
-struct route4_head
-{
+struct route4_head {
 	struct route4_fastmap	fastmap[16];
-	struct route4_bucket	*table[256+1];
+	struct route4_bucket	*table[256 + 1];
 };
 
-struct route4_bucket
-{
+struct route4_bucket {
 	/* 16 FROM buckets + 16 IIF buckets + 1 wildcard bucket */
-	struct route4_filter	*ht[16+16+1];
+	struct route4_filter	*ht[16 + 16 + 1];
 };
 
-struct route4_filter
-{
+struct route4_filter {
 	struct route4_filter	*next;
 	u32			id;
 	int			iif;
@@ -61,20 +57,20 @@ struct route4_filter
 	struct route4_bucket	*bkt;
 };
 
-#define ROUTE4_FAILURE ((struct route4_filter*)(-1L))
+#define ROUTE4_FAILURE ((struct route4_filter *)(-1L))
 
 static const struct tcf_ext_map route_ext_map = {
 	.police = TCA_ROUTE4_POLICE,
 	.action = TCA_ROUTE4_ACT
 };
 
-static __inline__ int route4_fastmap_hash(u32 id, int iif)
+static inline int route4_fastmap_hash(u32 id, int iif)
 {
-	return id&0xF;
+	return id & 0xF;
 }
 
-static inline
-void route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id)
+static void
+route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id)
 {
 	spinlock_t *root_lock = qdisc_root_sleeping_lock(q);
 
@@ -83,32 +79,33 @@ void route4_reset_fastmap(struct Qdisc *q, struct route4_head *head, u32 id)
 	spin_unlock_bh(root_lock);
 }
 
-static inline void
+static void
 route4_set_fastmap(struct route4_head *head, u32 id, int iif,
 		   struct route4_filter *f)
 {
 	int h = route4_fastmap_hash(id, iif);
+
 	head->fastmap[h].id = id;
 	head->fastmap[h].iif = iif;
 	head->fastmap[h].filter = f;
 }
 
-static __inline__ int route4_hash_to(u32 id)
+static inline int route4_hash_to(u32 id)
 {
-	return id&0xFF;
+	return id & 0xFF;
 }
 
-static __inline__ int route4_hash_from(u32 id)
+static inline int route4_hash_from(u32 id)
 {
-	return (id>>16)&0xF;
+	return (id >> 16) & 0xF;
 }
 
-static __inline__ int route4_hash_iif(int iif)
+static inline int route4_hash_iif(int iif)
 {
-	return 16 + ((iif>>16)&0xF);
+	return 16 + ((iif >> 16) & 0xF);
 }
 
-static __inline__ int route4_hash_wild(void)
+static inline int route4_hash_wild(void)
 {
 	return 32;
 }
@@ -131,21 +128,22 @@ static __inline__ int route4_hash_wild(void)
 static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
 			   struct tcf_result *res)
 {
-	struct route4_head *head = (struct route4_head*)tp->root;
+	struct route4_head *head = (struct route4_head *)tp->root;
 	struct dst_entry *dst;
 	struct route4_bucket *b;
 	struct route4_filter *f;
 	u32 id, h;
 	int iif, dont_cache = 0;
 
-	if ((dst = skb_dst(skb)) == NULL)
+	dst = skb_dst(skb);
+	if (!dst)
 		goto failure;
 
 	id = dst->tclassid;
 	if (head == NULL)
 		goto old_method;
 
-	iif = ((struct rtable*)dst)->fl.iif;
+	iif = ((struct rtable *)dst)->rt_iif;
 
 	h = route4_fastmap_hash(id, iif);
 	if (id == head->fastmap[h].id &&
@@ -161,7 +159,8 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
 	h = route4_hash_to(id);
 
 restart:
-	if ((b = head->table[h]) != NULL) {
+	b = head->table[h];
+	if (b) {
 		for (f = b->ht[route4_hash_from(id)]; f; f = f->next)
 			if (f->id == id)
 				ROUTE4_APPLY_RESULT();
@@ -197,8 +196,9 @@ old_method:
 
 static inline u32 to_hash(u32 id)
 {
-	u32 h = id&0xFF;
-	if (id&0x8000)
+	u32 h = id & 0xFF;
+
+	if (id & 0x8000)
 		h += 256;
 	return h;
 }
@@ -211,17 +211,17 @@ static inline u32 from_hash(u32 id)
 	if (!(id & 0x8000)) {
 		if (id > 255)
 			return 256;
-		return id&0xF;
+		return id & 0xF;
 	}
-	return 16 + (id&0xF);
+	return 16 + (id & 0xF);
 }
 
 static unsigned long route4_get(struct tcf_proto *tp, u32 handle)
 {
-	struct route4_head *head = (struct route4_head*)tp->root;
+	struct route4_head *head = (struct route4_head *)tp->root;
 	struct route4_bucket *b;
 	struct route4_filter *f;
-	unsigned h1, h2;
+	unsigned int h1, h2;
 
 	if (!head)
 		return 0;
@@ -230,11 +230,12 @@ static unsigned long route4_get(struct tcf_proto *tp, u32 handle)
 	if (h1 > 256)
 		return 0;
 
-	h2 = from_hash(handle>>16);
+	h2 = from_hash(handle >> 16);
 	if (h2 > 32)
 		return 0;
 
-	if ((b = head->table[h1]) != NULL) {
+	b = head->table[h1];
+	if (b) {
 		for (f = b->ht[h2]; f; f = f->next)
 			if (f->handle == handle)
 				return (unsigned long)f;
@@ -251,7 +252,7 @@ static int route4_init(struct tcf_proto *tp)
 	return 0;
 }
 
-static inline void
+static void
 route4_delete_filter(struct tcf_proto *tp, struct route4_filter *f)
 {
 	tcf_unbind_filter(tp, &f->res);
@@ -267,11 +268,12 @@ static void route4_destroy(struct tcf_proto *tp)
 	if (head == NULL)
 		return;
 
-	for (h1=0; h1<=256; h1++) {
+	for (h1 = 0; h1 <= 256; h1++) {
 		struct route4_bucket *b;
 
-		if ((b = head->table[h1]) != NULL) {
-			for (h2=0; h2<=32; h2++) {
+		b = head->table[h1];
+		if (b) {
+			for (h2 = 0; h2 <= 32; h2++) {
 				struct route4_filter *f;
 
 				while ((f = b->ht[h2]) != NULL) {
@@ -287,9 +289,9 @@ static void route4_destroy(struct tcf_proto *tp)
 
 static int route4_delete(struct tcf_proto *tp, unsigned long arg)
 {
-	struct route4_head *head = (struct route4_head*)tp->root;
-	struct route4_filter **fp, *f = (struct route4_filter*)arg;
-	unsigned h = 0;
+	struct route4_head *head = (struct route4_head *)tp->root;
+	struct route4_filter **fp, *f = (struct route4_filter *)arg;
+	unsigned int h = 0;
 	struct route4_bucket *b;
 	int i;
 
@@ -299,7 +301,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
 	h = f->handle;
 	b = f->bkt;
 
-	for (fp = &b->ht[from_hash(h>>16)]; *fp; fp = &(*fp)->next) {
+	for (fp = &b->ht[from_hash(h >> 16)]; *fp; fp = &(*fp)->next) {
 		if (*fp == f) {
 			tcf_tree_lock(tp);
 			*fp = f->next;
@@ -310,7 +312,7 @@ static int route4_delete(struct tcf_proto *tp, unsigned long arg)
 
 			/* Strip tree */
 
-			for (i=0; i<=32; i++)
+			for (i = 0; i <= 32; i++)
 				if (b->ht[i])
 					return 0;
 
@@ -380,7 +382,8 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 	}
 
 	h1 = to_hash(nhandle);
-	if ((b = head->table[h1]) == NULL) {
+	b = head->table[h1];
+	if (!b) {
 		err = -ENOBUFS;
 		b = kzalloc(sizeof(struct route4_bucket), GFP_KERNEL);
 		if (b == NULL)
@@ -391,6 +394,7 @@ static int route4_set_parms(struct tcf_proto *tp, unsigned long base,
 		tcf_tree_unlock(tp);
 	} else {
 		unsigned int h2 = from_hash(nhandle >> 16);
+
 		err = -EEXIST;
 		for (fp = b->ht[h2]; fp; fp = fp->next)
 			if (fp->handle == f->handle)
@@ -444,7 +448,8 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
 	if (err < 0)
 		return err;
 
-	if ((f = (struct route4_filter*)*arg) != NULL) {
+	f = (struct route4_filter *)*arg;
+	if (f) {
 		if (f->handle != handle && handle)
 			return -EINVAL;
 
@@ -481,7 +486,7 @@ static int route4_change(struct tcf_proto *tp, unsigned long base,
 
 reinsert:
 	h = from_hash(f->handle >> 16);
-	for (fp = &f->bkt->ht[h]; (f1=*fp) != NULL; fp = &f1->next)
+	for (fp = &f->bkt->ht[h]; (f1 = *fp) != NULL; fp = &f1->next)
 		if (f->handle < f1->handle)
 			break;
 
@@ -492,7 +497,8 @@ reinsert:
 	if (old_handle && f->handle != old_handle) {
 		th = to_hash(old_handle);
 		h = from_hash(old_handle >> 16);
-		if ((b = head->table[th]) != NULL) {
+		b = head->table[th];
+		if (b) {
 			for (fp = &b->ht[h]; *fp; fp = &(*fp)->next) {
 				if (*fp == f) {
 					*fp = f->next;
@@ -515,7 +521,7 @@ errout:
 static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
 	struct route4_head *head = tp->root;
-	unsigned h, h1;
+	unsigned int h, h1;
 
 	if (head == NULL)
 		arg->stop = 1;
@@ -549,7 +555,7 @@ static void route4_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 static int route4_dump(struct tcf_proto *tp, unsigned long fh,
 		       struct sk_buff *skb, struct tcmsg *t)
 {
-	struct route4_filter *f = (struct route4_filter*)fh;
+	struct route4_filter *f = (struct route4_filter *)fh;
 	unsigned char *b = skb_tail_pointer(skb);
 	struct nlattr *nest;
 	u32 id;
@@ -563,15 +569,15 @@ static int route4_dump(struct tcf_proto *tp, unsigned long fh,
 	if (nest == NULL)
 		goto nla_put_failure;
 
-	if (!(f->handle&0x8000)) {
-		id = f->id&0xFF;
+	if (!(f->handle & 0x8000)) {
+		id = f->id & 0xFF;
 		NLA_PUT_U32(skb, TCA_ROUTE4_TO, id);
 	}
-	if (f->handle&0x80000000) {
-		if ((f->handle>>16) != 0xFFFF)
+	if (f->handle & 0x80000000) {
+		if ((f->handle >> 16) != 0xFFFF)
 			NLA_PUT_U32(skb, TCA_ROUTE4_IIF, f->iif);
 	} else {
-		id = f->id>>16;
+		id = f->id >> 16;
 		NLA_PUT_U32(skb, TCA_ROUTE4_FROM, id);
 	}
 	if (f->res.classid)
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h
index 425a179..402c44b 100644
--- a/net/sched/cls_rsvp.h
+++ b/net/sched/cls_rsvp.h
@@ -66,28 +66,25 @@
    powerful classification engine.  */
 
 
-struct rsvp_head
-{
+struct rsvp_head {
 	u32			tmap[256/32];
 	u32			hgenerator;
 	u8			tgenerator;
 	struct rsvp_session	*ht[256];
 };
 
-struct rsvp_session
-{
+struct rsvp_session {
 	struct rsvp_session	*next;
 	__be32			dst[RSVP_DST_LEN];
 	struct tc_rsvp_gpi 	dpi;
 	u8			protocol;
 	u8			tunnelid;
 	/* 16 (src,sport) hash slots, and one wildcard source slot */
-	struct rsvp_filter	*ht[16+1];
+	struct rsvp_filter	*ht[16 + 1];
 };
 
 
-struct rsvp_filter
-{
+struct rsvp_filter {
 	struct rsvp_filter	*next;
 	__be32			src[RSVP_DST_LEN];
 	struct tc_rsvp_gpi	spi;
@@ -100,17 +97,19 @@ struct rsvp_filter
 	struct rsvp_session	*sess;
 };
 
-static __inline__ unsigned hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
+static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
 {
-	unsigned h = (__force __u32)dst[RSVP_DST_LEN-1];
+	unsigned int h = (__force __u32)dst[RSVP_DST_LEN - 1];
+
 	h ^= h>>16;
 	h ^= h>>8;
 	return (h ^ protocol ^ tunnelid) & 0xFF;
 }
 
-static __inline__ unsigned hash_src(__be32 *src)
+static inline unsigned int hash_src(__be32 *src)
 {
-	unsigned h = (__force __u32)src[RSVP_DST_LEN-1];
+	unsigned int h = (__force __u32)src[RSVP_DST_LEN-1];
+
 	h ^= h>>16;
 	h ^= h>>8;
 	h ^= h>>4;
@@ -134,10 +133,10 @@ static struct tcf_ext_map rsvp_ext_map = {
 static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
 			 struct tcf_result *res)
 {
-	struct rsvp_session **sht = ((struct rsvp_head*)tp->root)->ht;
+	struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
 	struct rsvp_session *s;
 	struct rsvp_filter *f;
-	unsigned h1, h2;
+	unsigned int h1, h2;
 	__be32 *dst, *src;
 	u8 protocol;
 	u8 tunnelid = 0;
@@ -162,13 +161,13 @@ restart:
 	src = &nhptr->saddr.s6_addr32[0];
 	dst = &nhptr->daddr.s6_addr32[0];
 	protocol = nhptr->nexthdr;
-	xprt = ((u8*)nhptr) + sizeof(struct ipv6hdr);
+	xprt = ((u8 *)nhptr) + sizeof(struct ipv6hdr);
 #else
 	src = &nhptr->saddr;
 	dst = &nhptr->daddr;
 	protocol = nhptr->protocol;
-	xprt = ((u8*)nhptr) + (nhptr->ihl<<2);
-	if (nhptr->frag_off & htons(IP_MF|IP_OFFSET))
+	xprt = ((u8 *)nhptr) + (nhptr->ihl<<2);
+	if (nhptr->frag_off & htons(IP_MF | IP_OFFSET))
 		return -1;
 #endif
 
@@ -176,10 +175,10 @@ restart:
 	h2 = hash_src(src);
 
 	for (s = sht[h1]; s; s = s->next) {
-		if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] &&
+		if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN - 1] &&
 		    protocol == s->protocol &&
 		    !(s->dpi.mask &
-		      (*(u32*)(xprt+s->dpi.offset)^s->dpi.key)) &&
+		      (*(u32 *)(xprt + s->dpi.offset) ^ s->dpi.key)) &&
 #if RSVP_DST_LEN == 4
 		    dst[0] == s->dst[0] &&
 		    dst[1] == s->dst[1] &&
@@ -188,8 +187,8 @@ restart:
 		    tunnelid == s->tunnelid) {
 
 			for (f = s->ht[h2]; f; f = f->next) {
-				if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN-1] &&
-				    !(f->spi.mask & (*(u32*)(xprt+f->spi.offset)^f->spi.key))
+				if (src[RSVP_DST_LEN-1] == f->src[RSVP_DST_LEN - 1] &&
+				    !(f->spi.mask & (*(u32 *)(xprt + f->spi.offset) ^ f->spi.key))
 #if RSVP_DST_LEN == 4
 				    &&
 				    src[0] == f->src[0] &&
@@ -205,7 +204,7 @@ matched:
 						return 0;
 
 					tunnelid = f->res.classid;
-					nhptr = (void*)(xprt + f->tunnelhdr - sizeof(*nhptr));
+					nhptr = (void *)(xprt + f->tunnelhdr - sizeof(*nhptr));
 					goto restart;
 				}
 			}
@@ -224,11 +223,11 @@ matched:
 
 static unsigned long rsvp_get(struct tcf_proto *tp, u32 handle)
 {
-	struct rsvp_session **sht = ((struct rsvp_head*)tp->root)->ht;
+	struct rsvp_session **sht = ((struct rsvp_head *)tp->root)->ht;
 	struct rsvp_session *s;
 	struct rsvp_filter *f;
-	unsigned h1 = handle&0xFF;
-	unsigned h2 = (handle>>8)&0xFF;
+	unsigned int h1 = handle & 0xFF;
+	unsigned int h2 = (handle >> 8) & 0xFF;
 
 	if (h2 > 16)
 		return 0;
@@ -258,7 +257,7 @@ static int rsvp_init(struct tcf_proto *tp)
 	return -ENOBUFS;
 }
 
-static inline void
+static void
 rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
 {
 	tcf_unbind_filter(tp, &f->res);
@@ -277,13 +276,13 @@ static void rsvp_destroy(struct tcf_proto *tp)
 
 	sht = data->ht;
 
-	for (h1=0; h1<256; h1++) {
+	for (h1 = 0; h1 < 256; h1++) {
 		struct rsvp_session *s;
 
 		while ((s = sht[h1]) != NULL) {
 			sht[h1] = s->next;
 
-			for (h2=0; h2<=16; h2++) {
+			for (h2 = 0; h2 <= 16; h2++) {
 				struct rsvp_filter *f;
 
 				while ((f = s->ht[h2]) != NULL) {
@@ -299,13 +298,13 @@ static void rsvp_destroy(struct tcf_proto *tp)
 
 static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
 {
-	struct rsvp_filter **fp, *f = (struct rsvp_filter*)arg;
-	unsigned h = f->handle;
+	struct rsvp_filter **fp, *f = (struct rsvp_filter *)arg;
+	unsigned int h = f->handle;
 	struct rsvp_session **sp;
 	struct rsvp_session *s = f->sess;
 	int i;
 
-	for (fp = &s->ht[(h>>8)&0xFF]; *fp; fp = &(*fp)->next) {
+	for (fp = &s->ht[(h >> 8) & 0xFF]; *fp; fp = &(*fp)->next) {
 		if (*fp == f) {
 			tcf_tree_lock(tp);
 			*fp = f->next;
@@ -314,12 +313,12 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
 
 			/* Strip tree */
 
-			for (i=0; i<=16; i++)
+			for (i = 0; i <= 16; i++)
 				if (s->ht[i])
 					return 0;
 
 			/* OK, session has no flows */
-			for (sp = &((struct rsvp_head*)tp->root)->ht[h&0xFF];
+			for (sp = &((struct rsvp_head *)tp->root)->ht[h & 0xFF];
 			     *sp; sp = &(*sp)->next) {
 				if (*sp == s) {
 					tcf_tree_lock(tp);
@@ -337,13 +336,14 @@ static int rsvp_delete(struct tcf_proto *tp, unsigned long arg)
 	return 0;
 }
 
-static unsigned gen_handle(struct tcf_proto *tp, unsigned salt)
+static unsigned int gen_handle(struct tcf_proto *tp, unsigned salt)
 {
 	struct rsvp_head *data = tp->root;
 	int i = 0xFFFF;
 
 	while (i-- > 0) {
 		u32 h;
+
 		if ((data->hgenerator += 0x10000) == 0)
 			data->hgenerator = 0x10000;
 		h = data->hgenerator|salt;
@@ -355,10 +355,10 @@ static unsigned gen_handle(struct tcf_proto *tp, unsigned salt)
 
 static int tunnel_bts(struct rsvp_head *data)
 {
-	int n = data->tgenerator>>5;
-	u32 b = 1<<(data->tgenerator&0x1F);
+	int n = data->tgenerator >> 5;
+	u32 b = 1 << (data->tgenerator & 0x1F);
 
-	if (data->tmap[n]&b)
+	if (data->tmap[n] & b)
 		return 0;
 	data->tmap[n] |= b;
 	return 1;
@@ -372,10 +372,10 @@ static void tunnel_recycle(struct rsvp_head *data)
 
 	memset(tmap, 0, sizeof(tmap));
 
-	for (h1=0; h1<256; h1++) {
+	for (h1 = 0; h1 < 256; h1++) {
 		struct rsvp_session *s;
 		for (s = sht[h1]; s; s = s->next) {
-			for (h2=0; h2<=16; h2++) {
+			for (h2 = 0; h2 <= 16; h2++) {
 				struct rsvp_filter *f;
 
 				for (f = s->ht[h2]; f; f = f->next) {
@@ -395,8 +395,8 @@ static u32 gen_tunnel(struct rsvp_head *data)
 {
 	int i, k;
 
-	for (k=0; k<2; k++) {
-		for (i=255; i>0; i--) {
+	for (k = 0; k < 2; k++) {
+		for (i = 255; i > 0; i--) {
 			if (++data->tgenerator == 0)
 				data->tgenerator = 1;
 			if (tunnel_bts(data))
@@ -428,7 +428,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 	struct nlattr *opt = tca[TCA_OPTIONS-1];
 	struct nlattr *tb[TCA_RSVP_MAX + 1];
 	struct tcf_exts e;
-	unsigned h1, h2;
+	unsigned int h1, h2;
 	__be32 *dst;
 	int err;
 
@@ -443,7 +443,8 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 	if (err < 0)
 		return err;
 
-	if ((f = (struct rsvp_filter*)*arg) != NULL) {
+	f = (struct rsvp_filter *)*arg;
+	if (f) {
 		/* Node exists: adjust only classid */
 
 		if (f->handle != handle && handle)
@@ -500,7 +501,7 @@ static int rsvp_change(struct tcf_proto *tp, unsigned long base,
 			goto errout;
 	}
 
-	for (sp = &data->ht[h1]; (s=*sp) != NULL; sp = &s->next) {
+	for (sp = &data->ht[h1]; (s = *sp) != NULL; sp = &s->next) {
 		if (dst[RSVP_DST_LEN-1] == s->dst[RSVP_DST_LEN-1] &&
 		    pinfo && pinfo->protocol == s->protocol &&
 		    memcmp(&pinfo->dpi, &s->dpi, sizeof(s->dpi)) == 0 &&
@@ -523,7 +524,7 @@ insert:
 			tcf_exts_change(tp, &f->exts, &e);
 
 			for (fp = &s->ht[h2]; *fp; fp = &(*fp)->next)
-				if (((*fp)->spi.mask&f->spi.mask) != f->spi.mask)
+				if (((*fp)->spi.mask & f->spi.mask) != f->spi.mask)
 					break;
 			f->next = *fp;
 			wmb();
@@ -567,7 +568,7 @@ errout2:
 static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 {
 	struct rsvp_head *head = tp->root;
-	unsigned h, h1;
+	unsigned int h, h1;
 
 	if (arg->stop)
 		return;
@@ -598,7 +599,7 @@ static void rsvp_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 		     struct sk_buff *skb, struct tcmsg *t)
 {
-	struct rsvp_filter *f = (struct rsvp_filter*)fh;
+	struct rsvp_filter *f = (struct rsvp_filter *)fh;
 	struct rsvp_session *s;
 	unsigned char *b = skb_tail_pointer(skb);
 	struct nlattr *nest;
@@ -624,7 +625,7 @@ static int rsvp_dump(struct tcf_proto *tp, unsigned long fh,
 	NLA_PUT(skb, TCA_RSVP_PINFO, sizeof(pinfo), &pinfo);
 	if (f->res.classid)
 		NLA_PUT_U32(skb, TCA_RSVP_CLASSID, f->res.classid);
-	if (((f->handle>>8)&0xFF) != 16)
+	if (((f->handle >> 8) & 0xFF) != 16)
 		NLA_PUT(skb, TCA_RSVP_SRC, sizeof(f->src), f->src);
 
 	if (tcf_exts_dump(skb, &f->exts, &rsvp_ext_map) < 0)
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c
index 20ef330..36667fa 100644
--- a/net/sched/cls_tcindex.c
+++ b/net/sched/cls_tcindex.c
@@ -249,7 +249,7 @@ tcindex_set_parms(struct tcf_proto *tp, unsigned long base, u32 handle,
 		 * of the hashing index is below the threshold.
 		 */
 		if ((cp.mask >> cp.shift) < PERFECT_HASH_THRESHOLD)
-			cp.hash = (cp.mask >> cp.shift)+1;
+			cp.hash = (cp.mask >> cp.shift) + 1;
 		else
 			cp.hash = DEFAULT_HASH_SIZE;
 	}
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index b0c2a82..3b93fc0 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -42,8 +42,7 @@
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
-struct tc_u_knode
-{
+struct tc_u_knode {
 	struct tc_u_knode	*next;
 	u32			handle;
 	struct tc_u_hnode	*ht_up;
@@ -63,19 +62,17 @@ struct tc_u_knode
 	struct tc_u32_sel	sel;
 };
 
-struct tc_u_hnode
-{
+struct tc_u_hnode {
 	struct tc_u_hnode	*next;
 	u32			handle;
 	u32			prio;
 	struct tc_u_common	*tp_c;
 	int			refcnt;
-	unsigned		divisor;
+	unsigned int		divisor;
 	struct tc_u_knode	*ht[1];
 };
 
-struct tc_u_common
-{
+struct tc_u_common {
 	struct tc_u_hnode	*hlist;
 	struct Qdisc		*q;
 	int			refcnt;
@@ -87,9 +84,11 @@ static const struct tcf_ext_map u32_ext_map = {
 	.police = TCA_U32_POLICE
 };
 
-static __inline__ unsigned u32_hash_fold(__be32 key, struct tc_u32_sel *sel, u8 fshift)
+static inline unsigned int u32_hash_fold(__be32 key,
+					 const struct tc_u32_sel *sel,
+					 u8 fshift)
 {
-	unsigned h = ntohl(key & sel->hmask)>>fshift;
+	unsigned int h = ntohl(key & sel->hmask) >> fshift;
 
 	return h;
 }
@@ -101,7 +100,7 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
 		unsigned int	  off;
 	} stack[TC_U32_MAXDEPTH];
 
-	struct tc_u_hnode *ht = (struct tc_u_hnode*)tp->root;
+	struct tc_u_hnode *ht = (struct tc_u_hnode *)tp->root;
 	unsigned int off = skb_network_offset(skb);
 	struct tc_u_knode *n;
 	int sdepth = 0;
@@ -120,7 +119,7 @@ next_knode:
 		struct tc_u32_key *key = n->sel.keys;
 
 #ifdef CONFIG_CLS_U32_PERF
-		n->pf->rcnt +=1;
+		n->pf->rcnt += 1;
 		j = 0;
 #endif
 
@@ -133,14 +132,14 @@ next_knode:
 		}
 #endif
 
-		for (i = n->sel.nkeys; i>0; i--, key++) {
+		for (i = n->sel.nkeys; i > 0; i--, key++) {
 			int toff = off + key->off + (off2 & key->offmask);
-			__be32 *data, _data;
+			__be32 *data, hdata;
 
 			if (skb_headroom(skb) + toff > INT_MAX)
 				goto out;
 
-			data = skb_header_pointer(skb, toff, 4, &_data);
+			data = skb_header_pointer(skb, toff, 4, &hdata);
 			if (!data)
 				goto out;
 			if ((*data ^ key->val) & key->mask) {
@@ -148,13 +147,13 @@ next_knode:
 				goto next_knode;
 			}
 #ifdef CONFIG_CLS_U32_PERF
-			n->pf->kcnts[j] +=1;
+			n->pf->kcnts[j] += 1;
 			j++;
 #endif
 		}
 		if (n->ht_down == NULL) {
 check_terminal:
-			if (n->sel.flags&TC_U32_TERMINAL) {
+			if (n->sel.flags & TC_U32_TERMINAL) {
 
 				*res = n->res;
 #ifdef CONFIG_NET_CLS_IND
@@ -164,7 +163,7 @@ check_terminal:
 				}
 #endif
 #ifdef CONFIG_CLS_U32_PERF
-				n->pf->rhit +=1;
+				n->pf->rhit += 1;
 #endif
 				r = tcf_exts_exec(skb, &n->exts, res);
 				if (r < 0) {
@@ -188,26 +187,26 @@ check_terminal:
 		ht = n->ht_down;
 		sel = 0;
 		if (ht->divisor) {
-			__be32 *data, _data;
+			__be32 *data, hdata;
 
 			data = skb_header_pointer(skb, off + n->sel.hoff, 4,
-						  &_data);
+						  &hdata);
 			if (!data)
 				goto out;
 			sel = ht->divisor & u32_hash_fold(*data, &n->sel,
 							  n->fshift);
 		}
-		if (!(n->sel.flags&(TC_U32_VAROFFSET|TC_U32_OFFSET|TC_U32_EAT)))
+		if (!(n->sel.flags & (TC_U32_VAROFFSET | TC_U32_OFFSET | TC_U32_EAT)))
 			goto next_ht;
 
-		if (n->sel.flags&(TC_U32_OFFSET|TC_U32_VAROFFSET)) {
+		if (n->sel.flags & (TC_U32_OFFSET | TC_U32_VAROFFSET)) {
 			off2 = n->sel.off + 3;
 			if (n->sel.flags & TC_U32_VAROFFSET) {
-				__be16 *data, _data;
+				__be16 *data, hdata;
 
 				data = skb_header_pointer(skb,
 							  off + n->sel.offoff,
-							  2, &_data);
+							  2, &hdata);
 				if (!data)
 					goto out;
 				off2 += ntohs(n->sel.offmask & *data) >>
@@ -215,7 +214,7 @@ check_terminal:
 			}
 			off2 &= ~3;
 		}
-		if (n->sel.flags&TC_U32_EAT) {
+		if (n->sel.flags & TC_U32_EAT) {
 			off += off2;
 			off2 = 0;
 		}
@@ -236,11 +235,11 @@ out:
 
 deadloop:
 	if (net_ratelimit())
-		printk(KERN_WARNING "cls_u32: dead loop\n");
+		pr_warning("cls_u32: dead loop\n");
 	return -1;
 }
 
-static __inline__ struct tc_u_hnode *
+static struct tc_u_hnode *
 u32_lookup_ht(struct tc_u_common *tp_c, u32 handle)
 {
 	struct tc_u_hnode *ht;
@@ -252,10 +251,10 @@ u32_lookup_ht(struct tc_u_common *tp_c, u32 handle)
 	return ht;
 }
 
-static __inline__ struct tc_u_knode *
+static struct tc_u_knode *
 u32_lookup_key(struct tc_u_hnode *ht, u32 handle)
 {
-	unsigned sel;
+	unsigned int sel;
 	struct tc_u_knode *n = NULL;
 
 	sel = TC_U32_HASH(handle);
@@ -300,7 +299,7 @@ static u32 gen_new_htid(struct tc_u_common *tp_c)
 	do {
 		if (++tp_c->hgenerator == 0x7FF)
 			tp_c->hgenerator = 1;
-	} while (--i>0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20));
+	} while (--i > 0 && u32_lookup_ht(tp_c, (tp_c->hgenerator|0x800)<<20));
 
 	return i > 0 ? (tp_c->hgenerator|0x800)<<20 : 0;
 }
@@ -378,9 +377,9 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode* key)
 static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
 {
 	struct tc_u_knode *n;
-	unsigned h;
+	unsigned int h;
 
-	for (h=0; h<=ht->divisor; h++) {
+	for (h = 0; h <= ht->divisor; h++) {
 		while ((n = ht->ht[h]) != NULL) {
 			ht->ht[h] = n->next;
 
@@ -446,13 +445,13 @@ static void u32_destroy(struct tcf_proto *tp)
 
 static int u32_delete(struct tcf_proto *tp, unsigned long arg)
 {
-	struct tc_u_hnode *ht = (struct tc_u_hnode*)arg;
+	struct tc_u_hnode *ht = (struct tc_u_hnode *)arg;
 
 	if (ht == NULL)
 		return 0;
 
 	if (TC_U32_KEY(ht->handle))
-		return u32_delete_key(tp, (struct tc_u_knode*)ht);
+		return u32_delete_key(tp, (struct tc_u_knode *)ht);
 
 	if (tp->root == ht)
 		return -EINVAL;
@@ -470,14 +469,14 @@ static int u32_delete(struct tcf_proto *tp, unsigned long arg)
 static u32 gen_new_kid(struct tc_u_hnode *ht, u32 handle)
 {
 	struct tc_u_knode *n;
-	unsigned i = 0x7FF;
+	unsigned int i = 0x7FF;
 
-	for (n=ht->ht[TC_U32_HASH(handle)]; n; n = n->next)
+	for (n = ht->ht[TC_U32_HASH(handle)]; n; n = n->next)
 		if (i < TC_U32_NODE(n->handle))
 			i = TC_U32_NODE(n->handle);
 	i++;
 
-	return handle|(i>0xFFF ? 0xFFF : i);
+	return handle | (i > 0xFFF ? 0xFFF : i);
 }
 
 static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
@@ -566,7 +565,8 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	if (err < 0)
 		return err;
 
-	if ((n = (struct tc_u_knode*)*arg) != NULL) {
+	n = (struct tc_u_knode *)*arg;
+	if (n) {
 		if (TC_U32_KEY(n->handle) == 0)
 			return -EINVAL;
 
@@ -574,7 +574,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 	}
 
 	if (tb[TCA_U32_DIVISOR]) {
-		unsigned divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
+		unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
 
 		if (--divisor > 0x100)
 			return -EINVAL;
@@ -585,7 +585,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle,
 			if (handle == 0)
 				return -ENOMEM;
 		}
-		ht = kzalloc(sizeof(*ht) + divisor*sizeof(void*), GFP_KERNEL);
+		ht = kzalloc(sizeof(*ht) + divisor*sizeof(void *), GFP_KERNEL);
 		if (ht == NULL)
 			return -ENOBUFS;
 		ht->tp_c = tp_c;
@@ -683,7 +683,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 	struct tc_u_common *tp_c = tp->data;
 	struct tc_u_hnode *ht;
 	struct tc_u_knode *n;
-	unsigned h;
+	unsigned int h;
 
 	if (arg->stop)
 		return;
@@ -717,7 +717,7 @@ static void u32_walk(struct tcf_proto *tp, struct tcf_walker *arg)
 static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 		     struct sk_buff *skb, struct tcmsg *t)
 {
-	struct tc_u_knode *n = (struct tc_u_knode*)fh;
+	struct tc_u_knode *n = (struct tc_u_knode *)fh;
 	struct nlattr *nest;
 
 	if (n == NULL)
@@ -730,8 +730,9 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 		goto nla_put_failure;
 
 	if (TC_U32_KEY(n->handle) == 0) {
-		struct tc_u_hnode *ht = (struct tc_u_hnode*)fh;
-		u32 divisor = ht->divisor+1;
+		struct tc_u_hnode *ht = (struct tc_u_hnode *)fh;
+		u32 divisor = ht->divisor + 1;
+
 		NLA_PUT_U32(skb, TCA_U32_DIVISOR, divisor);
 	} else {
 		NLA_PUT(skb, TCA_U32_SEL,
@@ -755,7 +756,7 @@ static int u32_dump(struct tcf_proto *tp, unsigned long fh,
 			goto nla_put_failure;
 
 #ifdef CONFIG_NET_CLS_IND
-		if(strlen(n->indev))
+		if (strlen(n->indev))
 			NLA_PUT_STRING(skb, TCA_U32_INDEV, n->indev);
 #endif
 #ifdef CONFIG_CLS_U32_PERF
diff --git a/net/sched/em_cmp.c b/net/sched/em_cmp.c
index bc45039..1c8360a 100644
--- a/net/sched/em_cmp.c
+++ b/net/sched/em_cmp.c
@@ -33,40 +33,41 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em,
 		return 0;
 
 	switch (cmp->align) {
-		case TCF_EM_ALIGN_U8:
-			val = *ptr;
-			break;
+	case TCF_EM_ALIGN_U8:
+		val = *ptr;
+		break;
 
-		case TCF_EM_ALIGN_U16:
-			val = get_unaligned_be16(ptr);
+	case TCF_EM_ALIGN_U16:
+		val = get_unaligned_be16(ptr);
 
-			if (cmp_needs_transformation(cmp))
-				val = be16_to_cpu(val);
-			break;
+		if (cmp_needs_transformation(cmp))
+			val = be16_to_cpu(val);
+		break;
 
-		case TCF_EM_ALIGN_U32:
-			/* Worth checking boundries? The branching seems
-			 * to get worse. Visit again. */
-			val = get_unaligned_be32(ptr);
+	case TCF_EM_ALIGN_U32:
+		/* Worth checking boundries? The branching seems
+		 * to get worse. Visit again.
+		 */
+		val = get_unaligned_be32(ptr);
 
-			if (cmp_needs_transformation(cmp))
-				val = be32_to_cpu(val);
-			break;
+		if (cmp_needs_transformation(cmp))
+			val = be32_to_cpu(val);
+		break;
 
-		default:
-			return 0;
+	default:
+		return 0;
 	}
 
 	if (cmp->mask)
 		val &= cmp->mask;
 
 	switch (cmp->opnd) {
-		case TCF_EM_OPND_EQ:
-			return val == cmp->val;
-		case TCF_EM_OPND_LT:
-			return val < cmp->val;
-		case TCF_EM_OPND_GT:
-			return val > cmp->val;
+	case TCF_EM_OPND_EQ:
+		return val == cmp->val;
+	case TCF_EM_OPND_LT:
+		return val < cmp->val;
+	case TCF_EM_OPND_GT:
+		return val > cmp->val;
 	}
 
 	return 0;
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index 34da5e2..a4de67e 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -73,21 +73,18 @@
 #include <net/pkt_cls.h>
 #include <net/sock.h>
 
-struct meta_obj
-{
+struct meta_obj {
 	unsigned long		value;
 	unsigned int		len;
 };
 
-struct meta_value
-{
+struct meta_value {
 	struct tcf_meta_val	hdr;
 	unsigned long		val;
 	unsigned int		len;
 };
 
-struct meta_match
-{
+struct meta_match {
 	struct meta_value	lvalue;
 	struct meta_value	rvalue;
 };
@@ -255,7 +252,7 @@ META_COLLECTOR(int_rtclassid)
 	if (unlikely(skb_dst(skb) == NULL))
 		*err = -1;
 	else
-#ifdef CONFIG_NET_CLS_ROUTE
+#ifdef CONFIG_IP_ROUTE_CLASSID
 		dst->value = skb_dst(skb)->tclassid;
 #else
 		dst->value = 0;
@@ -267,7 +264,7 @@ META_COLLECTOR(int_rtiif)
 	if (unlikely(skb_rtable(skb) == NULL))
 		*err = -1;
 	else
-		dst->value = skb_rtable(skb)->fl.iif;
+		dst->value = skb_rtable(skb)->rt_iif;
 }
 
 /**************************************************************************
@@ -404,7 +401,7 @@ META_COLLECTOR(int_sk_sndbuf)
 META_COLLECTOR(int_sk_alloc)
 {
 	SKIP_NONLOCAL(skb);
-	dst->value = skb->sk->sk_allocation;
+	dst->value = (__force int) skb->sk->sk_allocation;
 }
 
 META_COLLECTOR(int_sk_route_caps)
@@ -483,8 +480,7 @@ META_COLLECTOR(int_sk_write_pend)
  * Meta value collectors assignment table
  **************************************************************************/
 
-struct meta_ops
-{
+struct meta_ops {
 	void		(*get)(struct sk_buff *, struct tcf_pkt_info *,
 			       struct meta_value *, struct meta_obj *, int *);
 };
@@ -494,7 +490,7 @@ struct meta_ops
 
 /* Meta value operations table listing all meta value collectors and
  * assigns them to a type and meta id. */
-static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
+static struct meta_ops __meta_ops[TCF_META_TYPE_MAX + 1][TCF_META_ID_MAX + 1] = {
 	[TCF_META_TYPE_VAR] = {
 		[META_ID(DEV)]			= META_FUNC(var_dev),
 		[META_ID(SK_BOUND_IF)] 		= META_FUNC(var_sk_bound_if),
@@ -550,7 +546,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
 	}
 };
 
-static inline struct meta_ops * meta_ops(struct meta_value *val)
+static inline struct meta_ops *meta_ops(struct meta_value *val)
 {
 	return &__meta_ops[meta_type(val)][meta_id(val)];
 }
@@ -649,9 +645,8 @@ static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
 {
 	if (v->len == sizeof(unsigned long))
 		NLA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
-	else if (v->len == sizeof(u32)) {
+	else if (v->len == sizeof(u32))
 		NLA_PUT_U32(skb, tlv, v->val);
-	}
 
 	return 0;
 
@@ -663,8 +658,7 @@ nla_put_failure:
  * Type specific operations table
  **************************************************************************/
 
-struct meta_type_ops
-{
+struct meta_type_ops {
 	void	(*destroy)(struct meta_value *);
 	int	(*compare)(struct meta_obj *, struct meta_obj *);
 	int	(*change)(struct meta_value *, struct nlattr *);
@@ -672,7 +666,7 @@ struct meta_type_ops
 	int	(*dump)(struct sk_buff *, struct meta_value *, int);
 };
 
-static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = {
+static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX + 1] = {
 	[TCF_META_TYPE_VAR] = {
 		.destroy = meta_var_destroy,
 		.compare = meta_var_compare,
@@ -688,7 +682,7 @@ static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = {
 	}
 };
 
-static inline struct meta_type_ops * meta_type_ops(struct meta_value *v)
+static inline struct meta_type_ops *meta_type_ops(struct meta_value *v)
 {
 	return &__meta_type_ops[meta_type(v)];
 }
@@ -713,7 +707,7 @@ static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info,
 		return err;
 
 	if (meta_type_ops(v)->apply_extras)
-	    meta_type_ops(v)->apply_extras(v, dst);
+		meta_type_ops(v)->apply_extras(v, dst);
 
 	return 0;
 }
@@ -732,12 +726,12 @@ static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m,
 	r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value);
 
 	switch (meta->lvalue.hdr.op) {
-		case TCF_EM_OPND_EQ:
-			return !r;
-		case TCF_EM_OPND_LT:
-			return r < 0;
-		case TCF_EM_OPND_GT:
-			return r > 0;
+	case TCF_EM_OPND_EQ:
+		return !r;
+	case TCF_EM_OPND_LT:
+		return r < 0;
+	case TCF_EM_OPND_GT:
+		return r > 0;
 	}
 
 	return 0;
@@ -771,7 +765,7 @@ static inline int meta_change_data(struct meta_value *dst, struct nlattr *nla)
 
 static inline int meta_is_supported(struct meta_value *val)
 {
-	return (!meta_id(val) || meta_ops(val)->get);
+	return !meta_id(val) || meta_ops(val)->get;
 }
 
 static const struct nla_policy meta_policy[TCA_EM_META_MAX + 1] = {
diff --git a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
index 1a4176a..a3bed07 100644
--- a/net/sched/em_nbyte.c
+++ b/net/sched/em_nbyte.c
@@ -18,8 +18,7 @@
 #include <linux/tc_ematch/tc_em_nbyte.h>
 #include <net/pkt_cls.h>
 
-struct nbyte_data
-{
+struct nbyte_data {
 	struct tcf_em_nbyte	hdr;
 	char			pattern[0];
 };
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
index ea8f566..15d353d 100644
--- a/net/sched/em_text.c
+++ b/net/sched/em_text.c
@@ -19,8 +19,7 @@
 #include <linux/tc_ematch/tc_em_text.h>
 #include <net/pkt_cls.h>
 
-struct text_match
-{
+struct text_match {
 	u16			from_offset;
 	u16			to_offset;
 	u8			from_layer;
diff --git a/net/sched/em_u32.c b/net/sched/em_u32.c
index 953f147..797bdb8 100644
--- a/net/sched/em_u32.c
+++ b/net/sched/em_u32.c
@@ -35,7 +35,7 @@ static int em_u32_match(struct sk_buff *skb, struct tcf_ematch *em,
 	if (!tcf_valid_offset(skb, ptr, sizeof(u32)))
 		return 0;
 
-	return !(((*(__be32*) ptr)  ^ key->val) & key->mask);
+	return !(((*(__be32 *) ptr)  ^ key->val) & key->mask);
 }
 
 static struct tcf_ematch_ops em_u32_ops = {
diff --git a/net/sched/ematch.c b/net/sched/ematch.c
index 5e37da9..88d93eb 100644
--- a/net/sched/ematch.c
+++ b/net/sched/ematch.c
@@ -93,7 +93,7 @@
 static LIST_HEAD(ematch_ops);
 static DEFINE_RWLOCK(ematch_mod_lock);
 
-static inline struct tcf_ematch_ops * tcf_em_lookup(u16 kind)
+static struct tcf_ematch_ops *tcf_em_lookup(u16 kind)
 {
 	struct tcf_ematch_ops *e = NULL;
 
@@ -163,8 +163,8 @@ void tcf_em_unregister(struct tcf_ematch_ops *ops)
 }
 EXPORT_SYMBOL(tcf_em_unregister);
 
-static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree,
-						   int index)
+static inline struct tcf_ematch *tcf_em_get_match(struct tcf_ematch_tree *tree,
+						  int index)
 {
 	return &tree->matches[index];
 }
@@ -184,7 +184,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
 
 	if (em_hdr->kind == TCF_EM_CONTAINER) {
 		/* Special ematch called "container", carries an index
-		 * referencing an external ematch sequence. */
+		 * referencing an external ematch sequence.
+		 */
 		u32 ref;
 
 		if (data_len < sizeof(ref))
@@ -195,7 +196,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
 			goto errout;
 
 		/* We do not allow backward jumps to avoid loops and jumps
-		 * to our own position are of course illegal. */
+		 * to our own position are of course illegal.
+		 */
 		if (ref <= idx)
 			goto errout;
 
@@ -208,7 +210,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
 		 * which automatically releases the reference again, therefore
 		 * the module MUST not be given back under any circumstances
 		 * here. Be aware, the destroy function assumes that the
-		 * module is held if the ops field is non zero. */
+		 * module is held if the ops field is non zero.
+		 */
 		em->ops = tcf_em_lookup(em_hdr->kind);
 
 		if (em->ops == NULL) {
@@ -221,7 +224,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
 			if (em->ops) {
 				/* We dropped the RTNL mutex in order to
 				 * perform the module load. Tell the caller
-				 * to replay the request. */
+				 * to replay the request.
+				 */
 				module_put(em->ops->owner);
 				err = -EAGAIN;
 			}
@@ -230,7 +234,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
 		}
 
 		/* ematch module provides expected length of data, so we
-		 * can do a basic sanity check. */
+		 * can do a basic sanity check.
+		 */
 		if (em->ops->datalen && data_len < em->ops->datalen)
 			goto errout;
 
@@ -246,7 +251,8 @@ static int tcf_em_validate(struct tcf_proto *tp,
 			 * TCF_EM_SIMPLE may be specified stating that the
 			 * data only consists of a u32 integer and the module
 			 * does not expected a memory reference but rather
-			 * the value carried. */
+			 * the value carried.
+			 */
 			if (em_hdr->flags & TCF_EM_SIMPLE) {
 				if (data_len < sizeof(u32))
 					goto errout;
@@ -334,7 +340,8 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
 	 * The array of rt attributes is parsed in the order as they are
 	 * provided, their type must be incremental from 1 to n. Even
 	 * if it does not serve any real purpose, a failure of sticking
-	 * to this policy will result in parsing failure. */
+	 * to this policy will result in parsing failure.
+	 */
 	for (idx = 0; nla_ok(rt_match, list_len); idx++) {
 		err = -EINVAL;
 
@@ -359,7 +366,8 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla,
 	/* Check if the number of matches provided by userspace actually
 	 * complies with the array of matches. The number was used for
 	 * the validation of references and a mismatch could lead to
-	 * undefined references during the matching process. */
+	 * undefined references during the matching process.
+	 */
 	if (idx != tree_hdr->nmatches) {
 		err = -EINVAL;
 		goto errout_abort;
@@ -449,7 +457,7 @@ int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
 			.flags = em->flags
 		};
 
-		NLA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr);
+		NLA_PUT(skb, i + 1, sizeof(em_hdr), &em_hdr);
 
 		if (em->ops && em->ops->dump) {
 			if (em->ops->dump(skb, em) < 0)
@@ -478,6 +486,7 @@ static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em,
 			       struct tcf_pkt_info *info)
 {
 	int r = em->ops->match(skb, em, info);
+
 	return tcf_em_is_inverted(em) ? !r : r;
 }
 
@@ -527,8 +536,8 @@ pop_stack:
 
 stack_overflow:
 	if (net_ratelimit())
-		printk(KERN_WARNING "tc ematch: local stack overflow,"
-			" increase NET_EMATCH_STACK\n");
+		pr_warning("tc ematch: local stack overflow,"
+			   " increase NET_EMATCH_STACK\n");
 	return -1;
 }
 EXPORT_SYMBOL(__tcf_em_tree_match);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index b22ca2d..7490f3f 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -187,7 +187,7 @@ int unregister_qdisc(struct Qdisc_ops *qops)
 	int err = -ENOENT;
 
 	write_lock(&qdisc_mod_lock);
-	for (qp = &qdisc_base; (q=*qp)!=NULL; qp = &q->next)
+	for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next)
 		if (q == qops)
 			break;
 	if (q) {
@@ -321,7 +321,9 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab)
 	if (!tab || --tab->refcnt)
 		return;
 
-	for (rtabp = &qdisc_rtab_list; (rtab=*rtabp) != NULL; rtabp = &rtab->next) {
+	for (rtabp = &qdisc_rtab_list;
+	     (rtab = *rtabp) != NULL;
+	     rtabp = &rtab->next) {
 		if (rtab == tab) {
 			*rtabp = rtab->next;
 			kfree(rtab);
@@ -396,6 +398,11 @@ static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
 	return stab;
 }
 
+static void stab_kfree_rcu(struct rcu_head *head)
+{
+	kfree(container_of(head, struct qdisc_size_table, rcu));
+}
+
 void qdisc_put_stab(struct qdisc_size_table *tab)
 {
 	if (!tab)
@@ -405,7 +412,7 @@ void qdisc_put_stab(struct qdisc_size_table *tab)
 
 	if (--tab->refcnt == 0) {
 		list_del(&tab->list);
-		kfree(tab);
+		call_rcu_bh(&tab->rcu, stab_kfree_rcu);
 	}
 
 	spin_unlock(&qdisc_stab_lock);
@@ -428,7 +435,7 @@ nla_put_failure:
 	return -1;
 }
 
-void qdisc_calculate_pkt_len(struct sk_buff *skb, struct qdisc_size_table *stab)
+void __qdisc_calculate_pkt_len(struct sk_buff *skb, const struct qdisc_size_table *stab)
 {
 	int pkt_len, slot;
 
@@ -454,14 +461,13 @@ out:
 		pkt_len = 1;
 	qdisc_skb_cb(skb)->pkt_len = pkt_len;
 }
-EXPORT_SYMBOL(qdisc_calculate_pkt_len);
+EXPORT_SYMBOL(__qdisc_calculate_pkt_len);
 
 void qdisc_warn_nonwc(char *txt, struct Qdisc *qdisc)
 {
 	if (!(qdisc->flags & TCQ_F_WARN_NONWC)) {
-		printk(KERN_WARNING
-		       "%s: %s qdisc %X: is non-work-conserving?\n",
-		       txt, qdisc->ops->id, qdisc->handle >> 16);
+		pr_warn("%s: %s qdisc %X: is non-work-conserving?\n",
+			txt, qdisc->ops->id, qdisc->handle >> 16);
 		qdisc->flags |= TCQ_F_WARN_NONWC;
 	}
 }
@@ -472,7 +478,7 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
 	struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog,
 						 timer);
 
-	wd->qdisc->flags &= ~TCQ_F_THROTTLED;
+	qdisc_unthrottled(wd->qdisc);
 	__netif_schedule(qdisc_root(wd->qdisc));
 
 	return HRTIMER_NORESTART;
@@ -494,7 +500,7 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
 		     &qdisc_root_sleeping(wd->qdisc)->state))
 		return;
 
-	wd->qdisc->flags |= TCQ_F_THROTTLED;
+	qdisc_throttled(wd->qdisc);
 	time = ktime_set(0, 0);
 	time = ktime_add_ns(time, PSCHED_TICKS2NS(expires));
 	hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
@@ -504,7 +510,7 @@ EXPORT_SYMBOL(qdisc_watchdog_schedule);
 void qdisc_watchdog_cancel(struct qdisc_watchdog *wd)
 {
 	hrtimer_cancel(&wd->timer);
-	wd->qdisc->flags &= ~TCQ_F_THROTTLED;
+	qdisc_unthrottled(wd->qdisc);
 }
 EXPORT_SYMBOL(qdisc_watchdog_cancel);
 
@@ -625,7 +631,7 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
 			autohandle = TC_H_MAKE(0x80000000U, 0);
 	} while	(qdisc_lookup(dev, autohandle) && --i > 0);
 
-	return i>0 ? autohandle : 0;
+	return i > 0 ? autohandle : 0;
 }
 
 void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
@@ -834,7 +840,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
 				err = PTR_ERR(stab);
 				goto err_out4;
 			}
-			sch->stab = stab;
+			rcu_assign_pointer(sch->stab, stab);
 		}
 		if (tca[TCA_RATE]) {
 			spinlock_t *root_lock;
@@ -874,7 +880,7 @@ err_out4:
 	 * Any broken qdiscs that would require a ops->reset() here?
 	 * The qdisc was never in action so it shouldn't be necessary.
 	 */
-	qdisc_put_stab(sch->stab);
+	qdisc_put_stab(rtnl_dereference(sch->stab));
 	if (ops->destroy)
 		ops->destroy(sch);
 	goto err_out3;
@@ -882,7 +888,7 @@ err_out4:
 
 static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
 {
-	struct qdisc_size_table *stab = NULL;
+	struct qdisc_size_table *ostab, *stab = NULL;
 	int err = 0;
 
 	if (tca[TCA_OPTIONS]) {
@@ -899,8 +905,9 @@ static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
 			return PTR_ERR(stab);
 	}
 
-	qdisc_put_stab(sch->stab);
-	sch->stab = stab;
+	ostab = rtnl_dereference(sch->stab);
+	rcu_assign_pointer(sch->stab, stab);
+	qdisc_put_stab(ostab);
 
 	if (tca[TCA_RATE]) {
 		/* NB: ignores errors from replace_estimator
@@ -915,9 +922,8 @@ out:
 	return 0;
 }
 
-struct check_loop_arg
-{
-	struct qdisc_walker 	w;
+struct check_loop_arg {
+	struct qdisc_walker	w;
 	struct Qdisc		*p;
 	int			depth;
 };
@@ -970,7 +976,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	struct Qdisc *p = NULL;
 	int err;
 
-	if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL)
+	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
 		return -ENODEV;
 
 	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
@@ -980,12 +987,12 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	if (clid) {
 		if (clid != TC_H_ROOT) {
 			if (TC_H_MAJ(clid) != TC_H_MAJ(TC_H_INGRESS)) {
-				if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
+				p = qdisc_lookup(dev, TC_H_MAJ(clid));
+				if (!p)
 					return -ENOENT;
 				q = qdisc_leaf(p, clid);
-			} else { /* ingress */
-				if (dev_ingress_queue(dev))
-					q = dev_ingress_queue(dev)->qdisc_sleeping;
+			} else if (dev_ingress_queue(dev)) {
+				q = dev_ingress_queue(dev)->qdisc_sleeping;
 			}
 		} else {
 			q = dev->qdisc;
@@ -996,7 +1003,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 		if (tcm->tcm_handle && q->handle != tcm->tcm_handle)
 			return -EINVAL;
 	} else {
-		if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL)
+		q = qdisc_lookup(dev, tcm->tcm_handle);
+		if (!q)
 			return -ENOENT;
 	}
 
@@ -1008,7 +1016,8 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 			return -EINVAL;
 		if (q->handle == 0)
 			return -ENOENT;
-		if ((err = qdisc_graft(dev, p, skb, n, clid, NULL, q)) != 0)
+		err = qdisc_graft(dev, p, skb, n, clid, NULL, q);
+		if (err != 0)
 			return err;
 	} else {
 		qdisc_notify(net, skb, n, clid, NULL, q);
@@ -1017,7 +1026,7 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 }
 
 /*
-   Create/change qdisc.
+ * Create/change qdisc.
  */
 
 static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
@@ -1036,7 +1045,8 @@ replay:
 	clid = tcm->tcm_parent;
 	q = p = NULL;
 
-	if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL)
+	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
 		return -ENODEV;
 
 	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
@@ -1046,12 +1056,12 @@ replay:
 	if (clid) {
 		if (clid != TC_H_ROOT) {
 			if (clid != TC_H_INGRESS) {
-				if ((p = qdisc_lookup(dev, TC_H_MAJ(clid))) == NULL)
+				p = qdisc_lookup(dev, TC_H_MAJ(clid));
+				if (!p)
 					return -ENOENT;
 				q = qdisc_leaf(p, clid);
-			} else { /* ingress */
-				if (dev_ingress_queue_create(dev))
-					q = dev_ingress_queue(dev)->qdisc_sleeping;
+			} else if (dev_ingress_queue_create(dev)) {
+				q = dev_ingress_queue(dev)->qdisc_sleeping;
 			}
 		} else {
 			q = dev->qdisc;
@@ -1063,13 +1073,14 @@ replay:
 
 		if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) {
 			if (tcm->tcm_handle) {
-				if (q && !(n->nlmsg_flags&NLM_F_REPLACE))
+				if (q && !(n->nlmsg_flags & NLM_F_REPLACE))
 					return -EEXIST;
 				if (TC_H_MIN(tcm->tcm_handle))
 					return -EINVAL;
-				if ((q = qdisc_lookup(dev, tcm->tcm_handle)) == NULL)
+				q = qdisc_lookup(dev, tcm->tcm_handle);
+				if (!q)
 					goto create_n_graft;
-				if (n->nlmsg_flags&NLM_F_EXCL)
+				if (n->nlmsg_flags & NLM_F_EXCL)
 					return -EEXIST;
 				if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
 					return -EINVAL;
@@ -1079,7 +1090,7 @@ replay:
 				atomic_inc(&q->refcnt);
 				goto graft;
 			} else {
-				if (q == NULL)
+				if (!q)
 					goto create_n_graft;
 
 				/* This magic test requires explanation.
@@ -1101,9 +1112,9 @@ replay:
 				 *   For now we select create/graft, if
 				 *   user gave KIND, which does not match existing.
 				 */
-				if ((n->nlmsg_flags&NLM_F_CREATE) &&
-				    (n->nlmsg_flags&NLM_F_REPLACE) &&
-				    ((n->nlmsg_flags&NLM_F_EXCL) ||
+				if ((n->nlmsg_flags & NLM_F_CREATE) &&
+				    (n->nlmsg_flags & NLM_F_REPLACE) &&
+				    ((n->nlmsg_flags & NLM_F_EXCL) ||
 				     (tca[TCA_KIND] &&
 				      nla_strcmp(tca[TCA_KIND], q->ops->id))))
 					goto create_n_graft;
@@ -1118,7 +1129,7 @@ replay:
 	/* Change qdisc parameters */
 	if (q == NULL)
 		return -ENOENT;
-	if (n->nlmsg_flags&NLM_F_EXCL)
+	if (n->nlmsg_flags & NLM_F_EXCL)
 		return -EEXIST;
 	if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id))
 		return -EINVAL;
@@ -1128,7 +1139,7 @@ replay:
 	return err;
 
 create_n_graft:
-	if (!(n->nlmsg_flags&NLM_F_CREATE))
+	if (!(n->nlmsg_flags & NLM_F_CREATE))
 		return -ENOENT;
 	if (clid == TC_H_INGRESS) {
 		if (dev_ingress_queue(dev))
@@ -1175,6 +1186,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
 	struct nlmsghdr  *nlh;
 	unsigned char *b = skb_tail_pointer(skb);
 	struct gnet_dump d;
+	struct qdisc_size_table *stab;
 
 	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
 	tcm = NLMSG_DATA(nlh);
@@ -1190,7 +1202,8 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
 		goto nla_put_failure;
 	q->qstats.qlen = q->q.qlen;
 
-	if (q->stab && qdisc_dump_stab(skb, q->stab) < 0)
+	stab = rtnl_dereference(q->stab);
+	if (stab && qdisc_dump_stab(skb, stab) < 0)
 		goto nla_put_failure;
 
 	if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS, TCA_XSTATS,
@@ -1234,16 +1247,19 @@ static int qdisc_notify(struct net *net, struct sk_buff *oskb,
 		return -ENOBUFS;
 
 	if (old && !tc_qdisc_dump_ignore(old)) {
-		if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, RTM_DELQDISC) < 0)
+		if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq,
+				  0, RTM_DELQDISC) < 0)
 			goto err_out;
 	}
 	if (new && !tc_qdisc_dump_ignore(new)) {
-		if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
+		if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq,
+				  old ? NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
 			goto err_out;
 	}
 
 	if (skb->len)
-		return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+		return rtnetlink_send(skb, net, pid, RTNLGRP_TC,
+				      n->nlmsg_flags & NLM_F_ECHO);
 
 err_out:
 	kfree_skb(skb);
@@ -1275,7 +1291,7 @@ static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
 			q_idx++;
 			continue;
 		}
-		if (!tc_qdisc_dump_ignore(q) && 
+		if (!tc_qdisc_dump_ignore(q) &&
 		    tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).pid,
 				  cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWQDISC) <= 0)
 			goto done;
@@ -1356,7 +1372,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	u32 qid = TC_H_MAJ(clid);
 	int err;
 
-	if ((dev = __dev_get_by_index(net, tcm->tcm_ifindex)) == NULL)
+	dev = __dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
 		return -ENODEV;
 
 	err = nlmsg_parse(n, sizeof(*tcm), tca, TCA_MAX, NULL);
@@ -1391,9 +1408,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 			qid = dev->qdisc->handle;
 
 		/* Now qid is genuine qdisc handle consistent
-		   both with parent and child.
-
-		   TC_H_MAJ(pid) still may be unspecified, complete it now.
+		 * both with parent and child.
+		 *
+		 * TC_H_MAJ(pid) still may be unspecified, complete it now.
 		 */
 		if (pid)
 			pid = TC_H_MAKE(qid, pid);
@@ -1403,7 +1420,8 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 	}
 
 	/* OK. Locate qdisc */
-	if ((q = qdisc_lookup(dev, qid)) == NULL)
+	q = qdisc_lookup(dev, qid);
+	if (!q)
 		return -ENOENT;
 
 	/* An check that it supports classes */
@@ -1423,13 +1441,14 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
 
 	if (cl == 0) {
 		err = -ENOENT;
-		if (n->nlmsg_type != RTM_NEWTCLASS || !(n->nlmsg_flags&NLM_F_CREATE))
+		if (n->nlmsg_type != RTM_NEWTCLASS ||
+		    !(n->nlmsg_flags & NLM_F_CREATE))
 			goto out;
 	} else {
 		switch (n->nlmsg_type) {
 		case RTM_NEWTCLASS:
 			err = -EEXIST;
-			if (n->nlmsg_flags&NLM_F_EXCL)
+			if (n->nlmsg_flags & NLM_F_EXCL)
 				goto out;
 			break;
 		case RTM_DELTCLASS:
@@ -1521,14 +1540,14 @@ static int tclass_notify(struct net *net, struct sk_buff *oskb,
 		return -EINVAL;
 	}
 
-	return rtnetlink_send(skb, net, pid, RTNLGRP_TC, n->nlmsg_flags&NLM_F_ECHO);
+	return rtnetlink_send(skb, net, pid, RTNLGRP_TC,
+			      n->nlmsg_flags & NLM_F_ECHO);
 }
 
-struct qdisc_dump_args
-{
-	struct qdisc_walker w;
-	struct sk_buff *skb;
-	struct netlink_callback *cb;
+struct qdisc_dump_args {
+	struct qdisc_walker	w;
+	struct sk_buff		*skb;
+	struct netlink_callback	*cb;
 };
 
 static int qdisc_class_dump(struct Qdisc *q, unsigned long cl, struct qdisc_walker *arg)
@@ -1590,7 +1609,7 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
 
 static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct tcmsg *tcm = (struct tcmsg*)NLMSG_DATA(cb->nlh);
+	struct tcmsg *tcm = (struct tcmsg *)NLMSG_DATA(cb->nlh);
 	struct net *net = sock_net(skb->sk);
 	struct netdev_queue *dev_queue;
 	struct net_device *dev;
@@ -1598,7 +1617,8 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
 
 	if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm)))
 		return 0;
-	if ((dev = dev_get_by_index(net, tcm->tcm_ifindex)) == NULL)
+	dev = dev_get_by_index(net, tcm->tcm_ifindex);
+	if (!dev)
 		return 0;
 
 	s_t = cb->args[0];
@@ -1621,19 +1641,22 @@ done:
 }
 
 /* Main classifier routine: scans classifier chain attached
-   to this qdisc, (optionally) tests for protocol and asks
-   specific classifiers.
+ * to this qdisc, (optionally) tests for protocol and asks
+ * specific classifiers.
  */
 int tc_classify_compat(struct sk_buff *skb, struct tcf_proto *tp,
 		       struct tcf_result *res)
 {
 	__be16 protocol = skb->protocol;
-	int err = 0;
+	int err;
 
 	for (; tp; tp = tp->next) {
-		if ((tp->protocol == protocol ||
-		     tp->protocol == htons(ETH_P_ALL)) &&
-		    (err = tp->classify(skb, tp, res)) >= 0) {
+		if (tp->protocol != protocol &&
+		    tp->protocol != htons(ETH_P_ALL))
+			continue;
+		err = tp->classify(skb, tp, res);
+
+		if (err >= 0) {
 #ifdef CONFIG_NET_CLS_ACT
 			if (err != TC_ACT_RECLASSIFY && skb->tc_verd)
 				skb->tc_verd = SET_TC_VERD(skb->tc_verd, 0);
@@ -1649,12 +1672,12 @@ int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
 		struct tcf_result *res)
 {
 	int err = 0;
-	__be16 protocol;
 #ifdef CONFIG_NET_CLS_ACT
+	__be16 protocol;
 	struct tcf_proto *otp = tp;
 reclassify:
-#endif
 	protocol = skb->protocol;
+#endif
 
 	err = tc_classify_compat(skb, tp, res);
 #ifdef CONFIG_NET_CLS_ACT
@@ -1664,11 +1687,11 @@ reclassify:
 
 		if (verd++ >= MAX_REC_LOOP) {
 			if (net_ratelimit())
-				printk(KERN_NOTICE
-				       "%s: packet reclassify loop"
+				pr_notice("%s: packet reclassify loop"
 					  " rule prio %u protocol %02x\n",
-				       tp->q->ops->id,
-				       tp->prio & 0xffff, ntohs(tp->protocol));
+					  tp->q->ops->id,
+					  tp->prio & 0xffff,
+					  ntohs(tp->protocol));
 			return TC_ACT_SHOT;
 		}
 		skb->tc_verd = SET_TC_VERD(skb->tc_verd, verd);
@@ -1761,7 +1784,7 @@ static int __init pktsched_init(void)
 
 	err = register_pernet_subsys(&psched_net_ops);
 	if (err) {
-		printk(KERN_ERR "pktsched_init: "
+		pr_err("pktsched_init: "
 		       "cannot initialize per netns operations\n");
 		return err;
 	}
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c
index 943d733..3f08158 100644
--- a/net/sched/sch_atm.c
+++ b/net/sched/sch_atm.c
@@ -319,7 +319,7 @@ static int atm_tc_delete(struct Qdisc *sch, unsigned long arg)
 	 * creation), and one for the reference held when calling delete.
 	 */
 	if (flow->ref < 2) {
-		printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n", flow->ref);
+		pr_err("atm_tc_delete: flow->ref == %d\n", flow->ref);
 		return -EINVAL;
 	}
 	if (flow->ref > 2)
@@ -384,12 +384,12 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 			}
 		}
 		flow = NULL;
-	done:
-		;		
+done:
+		;
 	}
-	if (!flow)
+	if (!flow) {
 		flow = &p->link;
-	else {
+	} else {
 		if (flow->vcc)
 			ATM_SKB(skb)->atm_options = flow->vcc->atm_options;
 		/*@@@ looks good ... but it's not supposed to work :-) */
@@ -576,8 +576,7 @@ static void atm_tc_destroy(struct Qdisc *sch)
 
 	list_for_each_entry_safe(flow, tmp, &p->flows, list) {
 		if (flow->ref > 1)
-			printk(KERN_ERR "atm_destroy: %p->ref = %d\n", flow,
-			       flow->ref);
+			pr_err("atm_destroy: %p->ref = %d\n", flow, flow->ref);
 		atm_tc_put(sch, (unsigned long)flow);
 	}
 	tasklet_kill(&p->task);
@@ -616,9 +615,8 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl,
 	}
 	if (flow->excess)
 		NLA_PUT_U32(skb, TCA_ATM_EXCESS, flow->classid);
-	else {
+	else
 		NLA_PUT_U32(skb, TCA_ATM_EXCESS, 0);
-	}
 
 	nla_nest_end(skb, nest);
 	return skb->len;
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 5f63ec5..24d94c0 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -72,8 +72,7 @@
 struct cbq_sched_data;
 
 
-struct cbq_class
-{
+struct cbq_class {
 	struct Qdisc_class_common common;
 	struct cbq_class	*next_alive;	/* next class with backlog in this priority band */
 
@@ -139,19 +138,18 @@ struct cbq_class
 	int			refcnt;
 	int			filters;
 
-	struct cbq_class 	*defaults[TC_PRIO_MAX+1];
+	struct cbq_class	*defaults[TC_PRIO_MAX + 1];
 };
 
-struct cbq_sched_data
-{
+struct cbq_sched_data {
 	struct Qdisc_class_hash	clhash;			/* Hash table of all classes */
-	int			nclasses[TC_CBQ_MAXPRIO+1];
-	unsigned		quanta[TC_CBQ_MAXPRIO+1];
+	int			nclasses[TC_CBQ_MAXPRIO + 1];
+	unsigned int		quanta[TC_CBQ_MAXPRIO + 1];
 
 	struct cbq_class	link;
 
-	unsigned		activemask;
-	struct cbq_class	*active[TC_CBQ_MAXPRIO+1];	/* List of all classes
+	unsigned int		activemask;
+	struct cbq_class	*active[TC_CBQ_MAXPRIO + 1];	/* List of all classes
 								   with backlog */
 
 #ifdef CONFIG_NET_CLS_ACT
@@ -162,7 +160,7 @@ struct cbq_sched_data
 	int			tx_len;
 	psched_time_t		now;		/* Cached timestamp */
 	psched_time_t		now_rt;		/* Cached real time */
-	unsigned		pmask;
+	unsigned int		pmask;
 
 	struct hrtimer		delay_timer;
 	struct qdisc_watchdog	watchdog;	/* Watchdog timer,
@@ -175,9 +173,9 @@ struct cbq_sched_data
 };
 
 
-#define L2T(cl,len)	qdisc_l2t((cl)->R_tab,len)
+#define L2T(cl, len)	qdisc_l2t((cl)->R_tab, len)
 
-static __inline__ struct cbq_class *
+static inline struct cbq_class *
 cbq_class_lookup(struct cbq_sched_data *q, u32 classid)
 {
 	struct Qdisc_class_common *clc;
@@ -193,25 +191,27 @@ cbq_class_lookup(struct cbq_sched_data *q, u32 classid)
 static struct cbq_class *
 cbq_reclassify(struct sk_buff *skb, struct cbq_class *this)
 {
-	struct cbq_class *cl, *new;
+	struct cbq_class *cl;
 
-	for (cl = this->tparent; cl; cl = cl->tparent)
-		if ((new = cl->defaults[TC_PRIO_BESTEFFORT]) != NULL && new != this)
-			return new;
+	for (cl = this->tparent; cl; cl = cl->tparent) {
+		struct cbq_class *new = cl->defaults[TC_PRIO_BESTEFFORT];
 
+		if (new != NULL && new != this)
+			return new;
+	}
 	return NULL;
 }
 
 #endif
 
 /* Classify packet. The procedure is pretty complicated, but
-   it allows us to combine link sharing and priority scheduling
-   transparently.
-
-   Namely, you can put link sharing rules (f.e. route based) at root of CBQ,
-   so that it resolves to split nodes. Then packets are classified
-   by logical priority, or a more specific classifier may be attached
-   to the split node.
+ * it allows us to combine link sharing and priority scheduling
+ * transparently.
+ *
+ * Namely, you can put link sharing rules (f.e. route based) at root of CBQ,
+ * so that it resolves to split nodes. Then packets are classified
+ * by logical priority, or a more specific classifier may be attached
+ * to the split node.
  */
 
 static struct cbq_class *
@@ -227,7 +227,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 	/*
 	 *  Step 1. If skb->priority points to one of our classes, use it.
 	 */
-	if (TC_H_MAJ(prio^sch->handle) == 0 &&
+	if (TC_H_MAJ(prio ^ sch->handle) == 0 &&
 	    (cl = cbq_class_lookup(q, prio)) != NULL)
 		return cl;
 
@@ -243,10 +243,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 		    (result = tc_classify_compat(skb, head->filter_list, &res)) < 0)
 			goto fallback;
 
-		if ((cl = (void*)res.class) == NULL) {
+		cl = (void *)res.class;
+		if (!cl) {
 			if (TC_H_MAJ(res.classid))
 				cl = cbq_class_lookup(q, res.classid);
-			else if ((cl = defmap[res.classid&TC_PRIO_MAX]) == NULL)
+			else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
 				cl = defmap[TC_PRIO_BESTEFFORT];
 
 			if (cl == NULL || cl->level >= head->level)
@@ -282,7 +283,7 @@ fallback:
 	 * Step 4. No success...
 	 */
 	if (TC_H_MAJ(prio) == 0 &&
-	    !(cl = head->defaults[prio&TC_PRIO_MAX]) &&
+	    !(cl = head->defaults[prio & TC_PRIO_MAX]) &&
 	    !(cl = head->defaults[TC_PRIO_BESTEFFORT]))
 		return head;
 
@@ -290,12 +291,12 @@ fallback:
 }
 
 /*
-   A packet has just been enqueued on the empty class.
-   cbq_activate_class adds it to the tail of active class list
-   of its priority band.
+ * A packet has just been enqueued on the empty class.
+ * cbq_activate_class adds it to the tail of active class list
+ * of its priority band.
  */
 
-static __inline__ void cbq_activate_class(struct cbq_class *cl)
+static inline void cbq_activate_class(struct cbq_class *cl)
 {
 	struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
 	int prio = cl->cpriority;
@@ -314,9 +315,9 @@ static __inline__ void cbq_activate_class(struct cbq_class *cl)
 }
 
 /*
-   Unlink class from active chain.
-   Note that this same procedure is done directly in cbq_dequeue*
-   during round-robin procedure.
+ * Unlink class from active chain.
+ * Note that this same procedure is done directly in cbq_dequeue*
+ * during round-robin procedure.
  */
 
 static void cbq_deactivate_class(struct cbq_class *this)
@@ -350,7 +351,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
 {
 	int toplevel = q->toplevel;
 
-	if (toplevel > cl->level && !(cl->q->flags&TCQ_F_THROTTLED)) {
+	if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) {
 		psched_time_t now;
 		psched_tdiff_t incr;
 
@@ -363,7 +364,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)
 				q->toplevel = cl->level;
 				return;
 			}
-		} while ((cl=cl->borrow) != NULL && toplevel > cl->level);
+		} while ((cl = cl->borrow) != NULL && toplevel > cl->level);
 	}
 }
 
@@ -417,11 +418,11 @@ static void cbq_ovl_classic(struct cbq_class *cl)
 		delay += cl->offtime;
 
 		/*
-		   Class goes to sleep, so that it will have no
-		   chance to work avgidle. Let's forgive it 8)
-
-		   BTW cbq-2.0 has a crap in this
-		   place, apparently they forgot to shift it by cl->ewma_log.
+		 * Class goes to sleep, so that it will have no
+		 * chance to work avgidle. Let's forgive it 8)
+		 *
+		 * BTW cbq-2.0 has a crap in this
+		 * place, apparently they forgot to shift it by cl->ewma_log.
 		 */
 		if (cl->avgidle < 0)
 			delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log);
@@ -438,8 +439,8 @@ static void cbq_ovl_classic(struct cbq_class *cl)
 		q->wd_expires = delay;
 
 	/* Dirty work! We must schedule wakeups based on
-	   real available rate, rather than leaf rate,
-	   which may be tiny (even zero).
+	 * real available rate, rather than leaf rate,
+	 * which may be tiny (even zero).
 	 */
 	if (q->toplevel == TC_CBQ_MAXLEVEL) {
 		struct cbq_class *b;
@@ -459,7 +460,7 @@ static void cbq_ovl_classic(struct cbq_class *cl)
 }
 
 /* TC_CBQ_OVL_RCLASSIC: penalize by offtime classes in hierarchy, when
-   they go overlimit
+ * they go overlimit
  */
 
 static void cbq_ovl_rclassic(struct cbq_class *cl)
@@ -594,7 +595,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
 	struct Qdisc *sch = q->watchdog.qdisc;
 	psched_time_t now;
 	psched_tdiff_t delay = 0;
-	unsigned pmask;
+	unsigned int pmask;
 
 	now = psched_get_time();
 
@@ -623,7 +624,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
 		hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS);
 	}
 
-	sch->flags &= ~TCQ_F_THROTTLED;
+	qdisc_unthrottled(sch);
 	__netif_schedule(qdisc_root(sch));
 	return HRTIMER_NORESTART;
 }
@@ -663,15 +664,15 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
 #endif
 
 /*
-   It is mission critical procedure.
-
-   We "regenerate" toplevel cutoff, if transmitting class
-   has backlog and it is not regulated. It is not part of
-   original CBQ description, but looks more reasonable.
-   Probably, it is wrong. This question needs further investigation.
-*/
+ * It is mission critical procedure.
+ *
+ * We "regenerate" toplevel cutoff, if transmitting class
+ * has backlog and it is not regulated. It is not part of
+ * original CBQ description, but looks more reasonable.
+ * Probably, it is wrong. This question needs further investigation.
+ */
 
-static __inline__ void
+static inline void
 cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl,
 		    struct cbq_class *borrowed)
 {
@@ -682,7 +683,7 @@ cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl,
 					q->toplevel = borrowed->level;
 					return;
 				}
-			} while ((borrowed=borrowed->borrow) != NULL);
+			} while ((borrowed = borrowed->borrow) != NULL);
 		}
 #if 0
 	/* It is not necessary now. Uncommenting it
@@ -710,10 +711,10 @@ cbq_update(struct cbq_sched_data *q)
 		cl->bstats.bytes += len;
 
 		/*
-		   (now - last) is total time between packet right edges.
-		   (last_pktlen/rate) is "virtual" busy time, so that
-
-			 idle = (now - last) - last_pktlen/rate
+		 * (now - last) is total time between packet right edges.
+		 * (last_pktlen/rate) is "virtual" busy time, so that
+		 *
+		 *	idle = (now - last) - last_pktlen/rate
 		 */
 
 		idle = q->now - cl->last;
@@ -723,9 +724,9 @@ cbq_update(struct cbq_sched_data *q)
 			idle -= L2T(cl, len);
 
 		/* true_avgidle := (1-W)*true_avgidle + W*idle,
-		   where W=2^{-ewma_log}. But cl->avgidle is scaled:
-		   cl->avgidle == true_avgidle/W,
-		   hence:
+		 * where W=2^{-ewma_log}. But cl->avgidle is scaled:
+		 * cl->avgidle == true_avgidle/W,
+		 * hence:
 		 */
 			avgidle += idle - (avgidle>>cl->ewma_log);
 		}
@@ -739,22 +740,22 @@ cbq_update(struct cbq_sched_data *q)
 			cl->avgidle = avgidle;
 
 			/* Calculate expected time, when this class
-			   will be allowed to send.
-			   It will occur, when:
-			   (1-W)*true_avgidle + W*delay = 0, i.e.
-			   idle = (1/W - 1)*(-true_avgidle)
-			   or
-			   idle = (1 - W)*(-cl->avgidle);
+			 * will be allowed to send.
+			 * It will occur, when:
+			 * (1-W)*true_avgidle + W*delay = 0, i.e.
+			 * idle = (1/W - 1)*(-true_avgidle)
+			 * or
+			 * idle = (1 - W)*(-cl->avgidle);
 			 */
 			idle = (-avgidle) - ((-avgidle) >> cl->ewma_log);
 
 			/*
-			   That is not all.
-			   To maintain the rate allocated to the class,
-			   we add to undertime virtual clock,
-			   necessary to complete transmitted packet.
-			   (len/phys_bandwidth has been already passed
-			   to the moment of cbq_update)
+			 * That is not all.
+			 * To maintain the rate allocated to the class,
+			 * we add to undertime virtual clock,
+			 * necessary to complete transmitted packet.
+			 * (len/phys_bandwidth has been already passed
+			 * to the moment of cbq_update)
 			 */
 
 			idle -= L2T(&q->link, len);
@@ -776,7 +777,7 @@ cbq_update(struct cbq_sched_data *q)
 	cbq_update_toplevel(q, this, q->tx_borrowed);
 }
 
-static __inline__ struct cbq_class *
+static inline struct cbq_class *
 cbq_under_limit(struct cbq_class *cl)
 {
 	struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
@@ -792,16 +793,17 @@ cbq_under_limit(struct cbq_class *cl)
 
 	do {
 		/* It is very suspicious place. Now overlimit
-		   action is generated for not bounded classes
-		   only if link is completely congested.
-		   Though it is in agree with ancestor-only paradigm,
-		   it looks very stupid. Particularly,
-		   it means that this chunk of code will either
-		   never be called or result in strong amplification
-		   of burstiness. Dangerous, silly, and, however,
-		   no another solution exists.
+		 * action is generated for not bounded classes
+		 * only if link is completely congested.
+		 * Though it is in agree with ancestor-only paradigm,
+		 * it looks very stupid. Particularly,
+		 * it means that this chunk of code will either
+		 * never be called or result in strong amplification
+		 * of burstiness. Dangerous, silly, and, however,
+		 * no another solution exists.
 		 */
-		if ((cl = cl->borrow) == NULL) {
+		cl = cl->borrow;
+		if (!cl) {
 			this_cl->qstats.overlimits++;
 			this_cl->overlimit(this_cl);
 			return NULL;
@@ -814,7 +816,7 @@ cbq_under_limit(struct cbq_class *cl)
 	return cl;
 }
 
-static __inline__ struct sk_buff *
+static inline struct sk_buff *
 cbq_dequeue_prio(struct Qdisc *sch, int prio)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
@@ -838,7 +840,7 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio)
 
 			if (cl->deficit <= 0) {
 				/* Class exhausted its allotment per
-				   this round. Switch to the next one.
+				 * this round. Switch to the next one.
 				 */
 				deficit = 1;
 				cl->deficit += cl->quantum;
@@ -848,8 +850,8 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio)
 			skb = cl->q->dequeue(cl->q);
 
 			/* Class did not give us any skb :-(
-			   It could occur even if cl->q->q.qlen != 0
-			   f.e. if cl->q == "tbf"
+			 * It could occur even if cl->q->q.qlen != 0
+			 * f.e. if cl->q == "tbf"
 			 */
 			if (skb == NULL)
 				goto skip_class;
@@ -878,7 +880,7 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio)
 skip_class:
 			if (cl->q->q.qlen == 0 || prio != cl->cpriority) {
 				/* Class is empty or penalized.
-				   Unlink it from active chain.
+				 * Unlink it from active chain.
 				 */
 				cl_prev->next_alive = cl->next_alive;
 				cl->next_alive = NULL;
@@ -917,14 +919,14 @@ next_class:
 	return NULL;
 }
 
-static __inline__ struct sk_buff *
+static inline struct sk_buff *
 cbq_dequeue_1(struct Qdisc *sch)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
-	unsigned activemask;
+	unsigned int activemask;
 
-	activemask = q->activemask&0xFF;
+	activemask = q->activemask & 0xFF;
 	while (activemask) {
 		int prio = ffz(~activemask);
 		activemask &= ~(1<<prio);
@@ -949,11 +951,11 @@ cbq_dequeue(struct Qdisc *sch)
 	if (q->tx_class) {
 		psched_tdiff_t incr2;
 		/* Time integrator. We calculate EOS time
-		   by adding expected packet transmission time.
-		   If real time is greater, we warp artificial clock,
-		   so that:
-
-		   cbq_time = max(real_time, work);
+		 * by adding expected packet transmission time.
+		 * If real time is greater, we warp artificial clock,
+		 * so that:
+		 *
+		 * cbq_time = max(real_time, work);
 		 */
 		incr2 = L2T(&q->link, q->tx_len);
 		q->now += incr2;
@@ -971,27 +973,27 @@ cbq_dequeue(struct Qdisc *sch)
 		if (skb) {
 			qdisc_bstats_update(sch, skb);
 			sch->q.qlen--;
-			sch->flags &= ~TCQ_F_THROTTLED;
+			qdisc_unthrottled(sch);
 			return skb;
 		}
 
 		/* All the classes are overlimit.
-
-		   It is possible, if:
-
-		   1. Scheduler is empty.
-		   2. Toplevel cutoff inhibited borrowing.
-		   3. Root class is overlimit.
-
-		   Reset 2d and 3d conditions and retry.
-
-		   Note, that NS and cbq-2.0 are buggy, peeking
-		   an arbitrary class is appropriate for ancestor-only
-		   sharing, but not for toplevel algorithm.
-
-		   Our version is better, but slower, because it requires
-		   two passes, but it is unavoidable with top-level sharing.
-		*/
+		 *
+		 * It is possible, if:
+		 *
+		 * 1. Scheduler is empty.
+		 * 2. Toplevel cutoff inhibited borrowing.
+		 * 3. Root class is overlimit.
+		 *
+		 * Reset 2d and 3d conditions and retry.
+		 *
+		 * Note, that NS and cbq-2.0 are buggy, peeking
+		 * an arbitrary class is appropriate for ancestor-only
+		 * sharing, but not for toplevel algorithm.
+		 *
+		 * Our version is better, but slower, because it requires
+		 * two passes, but it is unavoidable with top-level sharing.
+		 */
 
 		if (q->toplevel == TC_CBQ_MAXLEVEL &&
 		    q->link.undertime == PSCHED_PASTPERFECT)
@@ -1002,7 +1004,8 @@ cbq_dequeue(struct Qdisc *sch)
 	}
 
 	/* No packets in scheduler or nobody wants to give them to us :-(
-	   Sigh... start watchdog timer in the last case. */
+	 * Sigh... start watchdog timer in the last case.
+	 */
 
 	if (sch->q.qlen) {
 		sch->qstats.overlimits++;
@@ -1024,13 +1027,14 @@ static void cbq_adjust_levels(struct cbq_class *this)
 		int level = 0;
 		struct cbq_class *cl;
 
-		if ((cl = this->children) != NULL) {
+		cl = this->children;
+		if (cl) {
 			do {
 				if (cl->level > level)
 					level = cl->level;
 			} while ((cl = cl->sibling) != this->children);
 		}
-		this->level = level+1;
+		this->level = level + 1;
 	} while ((this = this->tparent) != NULL);
 }
 
@@ -1046,14 +1050,15 @@ static void cbq_normalize_quanta(struct cbq_sched_data *q, int prio)
 	for (h = 0; h < q->clhash.hashsize; h++) {
 		hlist_for_each_entry(cl, n, &q->clhash.hash[h], common.hnode) {
 			/* BUGGGG... Beware! This expression suffer of
-			   arithmetic overflows!
+			 * arithmetic overflows!
 			 */
 			if (cl->priority == prio) {
 				cl->quantum = (cl->weight*cl->allot*q->nclasses[prio])/
 					q->quanta[prio];
 			}
 			if (cl->quantum <= 0 || cl->quantum>32*qdisc_dev(cl->qdisc)->mtu) {
-				printk(KERN_WARNING "CBQ: class %08x has bad quantum==%ld, repaired.\n", cl->common.classid, cl->quantum);
+				pr_warning("CBQ: class %08x has bad quantum==%ld, repaired.\n",
+					   cl->common.classid, cl->quantum);
 				cl->quantum = qdisc_dev(cl->qdisc)->mtu/2 + 1;
 			}
 		}
@@ -1064,18 +1069,18 @@ static void cbq_sync_defmap(struct cbq_class *cl)
 {
 	struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
 	struct cbq_class *split = cl->split;
-	unsigned h;
+	unsigned int h;
 	int i;
 
 	if (split == NULL)
 		return;
 
-	for (i=0; i<=TC_PRIO_MAX; i++) {
-		if (split->defaults[i] == cl && !(cl->defmap&(1<<i)))
+	for (i = 0; i <= TC_PRIO_MAX; i++) {
+		if (split->defaults[i] == cl && !(cl->defmap & (1<<i)))
 			split->defaults[i] = NULL;
 	}
 
-	for (i=0; i<=TC_PRIO_MAX; i++) {
+	for (i = 0; i <= TC_PRIO_MAX; i++) {
 		int level = split->level;
 
 		if (split->defaults[i])
@@ -1088,7 +1093,7 @@ static void cbq_sync_defmap(struct cbq_class *cl)
 			hlist_for_each_entry(c, n, &q->clhash.hash[h],
 					     common.hnode) {
 				if (c->split == split && c->level < level &&
-				    c->defmap&(1<<i)) {
+				    c->defmap & (1<<i)) {
 					split->defaults[i] = c;
 					level = c->level;
 				}
@@ -1102,7 +1107,8 @@ static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 ma
 	struct cbq_class *split = NULL;
 
 	if (splitid == 0) {
-		if ((split = cl->split) == NULL)
+		split = cl->split;
+		if (!split)
 			return;
 		splitid = split->common.classid;
 	}
@@ -1120,9 +1126,9 @@ static void cbq_change_defmap(struct cbq_class *cl, u32 splitid, u32 def, u32 ma
 		cl->defmap = 0;
 		cbq_sync_defmap(cl);
 		cl->split = split;
-		cl->defmap = def&mask;
+		cl->defmap = def & mask;
 	} else
-		cl->defmap = (cl->defmap&~mask)|(def&mask);
+		cl->defmap = (cl->defmap & ~mask) | (def & mask);
 
 	cbq_sync_defmap(cl);
 }
@@ -1135,7 +1141,7 @@ static void cbq_unlink_class(struct cbq_class *this)
 	qdisc_class_hash_remove(&q->clhash, &this->common);
 
 	if (this->tparent) {
-		clp=&this->sibling;
+		clp = &this->sibling;
 		cl = *clp;
 		do {
 			if (cl == this) {
@@ -1174,7 +1180,7 @@ static void cbq_link_class(struct cbq_class *this)
 	}
 }
 
-static unsigned int cbq_drop(struct Qdisc* sch)
+static unsigned int cbq_drop(struct Qdisc *sch)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct cbq_class *cl, *cl_head;
@@ -1182,7 +1188,8 @@ static unsigned int cbq_drop(struct Qdisc* sch)
 	unsigned int len;
 
 	for (prio = TC_CBQ_MAXPRIO; prio >= 0; prio--) {
-		if ((cl_head = q->active[prio]) == NULL)
+		cl_head = q->active[prio];
+		if (!cl_head)
 			continue;
 
 		cl = cl_head;
@@ -1199,13 +1206,13 @@ static unsigned int cbq_drop(struct Qdisc* sch)
 }
 
 static void
-cbq_reset(struct Qdisc* sch)
+cbq_reset(struct Qdisc *sch)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct cbq_class *cl;
 	struct hlist_node *n;
 	int prio;
-	unsigned h;
+	unsigned int h;
 
 	q->activemask = 0;
 	q->pmask = 0;
@@ -1237,21 +1244,21 @@ cbq_reset(struct Qdisc* sch)
 
 static int cbq_set_lss(struct cbq_class *cl, struct tc_cbq_lssopt *lss)
 {
-	if (lss->change&TCF_CBQ_LSS_FLAGS) {
-		cl->share = (lss->flags&TCF_CBQ_LSS_ISOLATED) ? NULL : cl->tparent;
-		cl->borrow = (lss->flags&TCF_CBQ_LSS_BOUNDED) ? NULL : cl->tparent;
+	if (lss->change & TCF_CBQ_LSS_FLAGS) {
+		cl->share = (lss->flags & TCF_CBQ_LSS_ISOLATED) ? NULL : cl->tparent;
+		cl->borrow = (lss->flags & TCF_CBQ_LSS_BOUNDED) ? NULL : cl->tparent;
 	}
-	if (lss->change&TCF_CBQ_LSS_EWMA)
+	if (lss->change & TCF_CBQ_LSS_EWMA)
 		cl->ewma_log = lss->ewma_log;
-	if (lss->change&TCF_CBQ_LSS_AVPKT)
+	if (lss->change & TCF_CBQ_LSS_AVPKT)
 		cl->avpkt = lss->avpkt;
-	if (lss->change&TCF_CBQ_LSS_MINIDLE)
+	if (lss->change & TCF_CBQ_LSS_MINIDLE)
 		cl->minidle = -(long)lss->minidle;
-	if (lss->change&TCF_CBQ_LSS_MAXIDLE) {
+	if (lss->change & TCF_CBQ_LSS_MAXIDLE) {
 		cl->maxidle = lss->maxidle;
 		cl->avgidle = lss->maxidle;
 	}
-	if (lss->change&TCF_CBQ_LSS_OFFTIME)
+	if (lss->change & TCF_CBQ_LSS_OFFTIME)
 		cl->offtime = lss->offtime;
 	return 0;
 }
@@ -1279,10 +1286,10 @@ static int cbq_set_wrr(struct cbq_class *cl, struct tc_cbq_wrropt *wrr)
 	if (wrr->weight)
 		cl->weight = wrr->weight;
 	if (wrr->priority) {
-		cl->priority = wrr->priority-1;
+		cl->priority = wrr->priority - 1;
 		cl->cpriority = cl->priority;
 		if (cl->priority >= cl->priority2)
-			cl->priority2 = TC_CBQ_MAXPRIO-1;
+			cl->priority2 = TC_CBQ_MAXPRIO - 1;
 	}
 
 	cbq_addprio(q, cl);
@@ -1299,10 +1306,10 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl)
 		cl->overlimit = cbq_ovl_delay;
 		break;
 	case TC_CBQ_OVL_LOWPRIO:
-		if (ovl->priority2-1 >= TC_CBQ_MAXPRIO ||
-		    ovl->priority2-1 <= cl->priority)
+		if (ovl->priority2 - 1 >= TC_CBQ_MAXPRIO ||
+		    ovl->priority2 - 1 <= cl->priority)
 			return -EINVAL;
-		cl->priority2 = ovl->priority2-1;
+		cl->priority2 = ovl->priority2 - 1;
 		cl->overlimit = cbq_ovl_lowprio;
 		break;
 	case TC_CBQ_OVL_DROP:
@@ -1381,9 +1388,9 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt)
 	if (!q->link.q)
 		q->link.q = &noop_qdisc;
 
-	q->link.priority = TC_CBQ_MAXPRIO-1;
-	q->link.priority2 = TC_CBQ_MAXPRIO-1;
-	q->link.cpriority = TC_CBQ_MAXPRIO-1;
+	q->link.priority = TC_CBQ_MAXPRIO - 1;
+	q->link.priority2 = TC_CBQ_MAXPRIO - 1;
+	q->link.cpriority = TC_CBQ_MAXPRIO - 1;
 	q->link.ovl_strategy = TC_CBQ_OVL_CLASSIC;
 	q->link.overlimit = cbq_ovl_classic;
 	q->link.allot = psched_mtu(qdisc_dev(sch));
@@ -1414,7 +1421,7 @@ put_rtab:
 	return err;
 }
 
-static __inline__ int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
+static int cbq_dump_rate(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 
@@ -1426,7 +1433,7 @@ nla_put_failure:
 	return -1;
 }
 
-static __inline__ int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl)
+static int cbq_dump_lss(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tc_cbq_lssopt opt;
@@ -1451,15 +1458,15 @@ nla_put_failure:
 	return -1;
 }
 
-static __inline__ int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
+static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tc_cbq_wrropt opt;
 
 	opt.flags = 0;
 	opt.allot = cl->allot;
-	opt.priority = cl->priority+1;
-	opt.cpriority = cl->cpriority+1;
+	opt.priority = cl->priority + 1;
+	opt.cpriority = cl->cpriority + 1;
 	opt.weight = cl->weight;
 	NLA_PUT(skb, TCA_CBQ_WRROPT, sizeof(opt), &opt);
 	return skb->len;
@@ -1469,13 +1476,13 @@ nla_put_failure:
 	return -1;
 }
 
-static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl)
+static int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tc_cbq_ovl opt;
 
 	opt.strategy = cl->ovl_strategy;
-	opt.priority2 = cl->priority2+1;
+	opt.priority2 = cl->priority2 + 1;
 	opt.pad = 0;
 	opt.penalty = cl->penalty;
 	NLA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt);
@@ -1486,7 +1493,7 @@ nla_put_failure:
 	return -1;
 }
 
-static __inline__ int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
+static int cbq_dump_fopt(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tc_cbq_fopt opt;
@@ -1505,7 +1512,7 @@ nla_put_failure:
 }
 
 #ifdef CONFIG_NET_CLS_ACT
-static __inline__ int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
+static int cbq_dump_police(struct sk_buff *skb, struct cbq_class *cl)
 {
 	unsigned char *b = skb_tail_pointer(skb);
 	struct tc_cbq_police opt;
@@ -1569,7 +1576,7 @@ static int
 cbq_dump_class(struct Qdisc *sch, unsigned long arg,
 	       struct sk_buff *skb, struct tcmsg *tcm)
 {
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 	struct nlattr *nest;
 
 	if (cl->tparent)
@@ -1597,7 +1604,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
 	struct gnet_dump *d)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 
 	cl->qstats.qlen = cl->q->q.qlen;
 	cl->xstats.avgidle = cl->avgidle;
@@ -1617,7 +1624,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
 static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 		     struct Qdisc **old)
 {
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 
 	if (new == NULL) {
 		new = qdisc_create_dflt(sch->dev_queue,
@@ -1640,10 +1647,9 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
 	return 0;
 }
 
-static struct Qdisc *
-cbq_leaf(struct Qdisc *sch, unsigned long arg)
+static struct Qdisc *cbq_leaf(struct Qdisc *sch, unsigned long arg)
 {
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 
 	return cl->q;
 }
@@ -1682,13 +1688,12 @@ static void cbq_destroy_class(struct Qdisc *sch, struct cbq_class *cl)
 		kfree(cl);
 }
 
-static void
-cbq_destroy(struct Qdisc* sch)
+static void cbq_destroy(struct Qdisc *sch)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct hlist_node *n, *next;
 	struct cbq_class *cl;
-	unsigned h;
+	unsigned int h;
 
 #ifdef CONFIG_NET_CLS_ACT
 	q->rx_class = NULL;
@@ -1712,7 +1717,7 @@ cbq_destroy(struct Qdisc* sch)
 
 static void cbq_put(struct Qdisc *sch, unsigned long arg)
 {
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 
 	if (--cl->refcnt == 0) {
 #ifdef CONFIG_NET_CLS_ACT
@@ -1735,7 +1740,7 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 {
 	int err;
 	struct cbq_sched_data *q = qdisc_priv(sch);
-	struct cbq_class *cl = (struct cbq_class*)*arg;
+	struct cbq_class *cl = (struct cbq_class *)*arg;
 	struct nlattr *opt = tca[TCA_OPTIONS];
 	struct nlattr *tb[TCA_CBQ_MAX + 1];
 	struct cbq_class *parent;
@@ -1827,13 +1832,14 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 
 	if (classid) {
 		err = -EINVAL;
-		if (TC_H_MAJ(classid^sch->handle) || cbq_class_lookup(q, classid))
+		if (TC_H_MAJ(classid ^ sch->handle) ||
+		    cbq_class_lookup(q, classid))
 			goto failure;
 	} else {
 		int i;
-		classid = TC_H_MAKE(sch->handle,0x8000);
+		classid = TC_H_MAKE(sch->handle, 0x8000);
 
-		for (i=0; i<0x8000; i++) {
+		for (i = 0; i < 0x8000; i++) {
 			if (++q->hgenerator >= 0x8000)
 				q->hgenerator = 1;
 			if (cbq_class_lookup(q, classid|q->hgenerator) == NULL)
@@ -1890,11 +1896,11 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t
 	cl->minidle = -0x7FFFFFFF;
 	cbq_set_lss(cl, nla_data(tb[TCA_CBQ_LSSOPT]));
 	cbq_set_wrr(cl, nla_data(tb[TCA_CBQ_WRROPT]));
-	if (cl->ewma_log==0)
+	if (cl->ewma_log == 0)
 		cl->ewma_log = q->link.ewma_log;
-	if (cl->maxidle==0)
+	if (cl->maxidle == 0)
 		cl->maxidle = q->link.maxidle;
-	if (cl->avpkt==0)
+	if (cl->avpkt == 0)
 		cl->avpkt = q->link.avpkt;
 	cl->overlimit = cbq_ovl_classic;
 	if (tb[TCA_CBQ_OVL_STRATEGY])
@@ -1920,7 +1926,7 @@ failure:
 static int cbq_delete(struct Qdisc *sch, unsigned long arg)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 	unsigned int qlen;
 
 	if (cl->filters || cl->children || cl == &q->link)
@@ -1978,7 +1984,7 @@ static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent,
 				     u32 classid)
 {
 	struct cbq_sched_data *q = qdisc_priv(sch);
-	struct cbq_class *p = (struct cbq_class*)parent;
+	struct cbq_class *p = (struct cbq_class *)parent;
 	struct cbq_class *cl = cbq_class_lookup(q, classid);
 
 	if (cl) {
@@ -1992,7 +1998,7 @@ static unsigned long cbq_bind_filter(struct Qdisc *sch, unsigned long parent,
 
 static void cbq_unbind_filter(struct Qdisc *sch, unsigned long arg)
 {
-	struct cbq_class *cl = (struct cbq_class*)arg;
+	struct cbq_class *cl = (struct cbq_class *)arg;
 
 	cl->filters--;
 }
@@ -2002,7 +2008,7 @@ static void cbq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 	struct cbq_sched_data *q = qdisc_priv(sch);
 	struct cbq_class *cl;
 	struct hlist_node *n;
-	unsigned h;
+	unsigned int h;
 
 	if (arg->stop)
 		return;
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
new file mode 100644
index 0000000..06afbae
--- /dev/null
+++ b/net/sched/sch_choke.c
@@ -0,0 +1,688 @@
+/*
+ * net/sched/sch_choke.c	CHOKE scheduler
+ *
+ * Copyright (c) 2011 Stephen Hemminger <shemminger@vyatta.com>
+ * Copyright (c) 2011 Eric Dumazet <eric.dumazet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/reciprocal_div.h>
+#include <linux/vmalloc.h>
+#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
+#include <net/red.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <net/ipv6.h>
+
+/*
+   CHOKe stateless AQM for fair bandwidth allocation
+   =================================================
+
+   CHOKe (CHOose and Keep for responsive flows, CHOose and Kill for
+   unresponsive flows) is a variant of RED that penalizes misbehaving flows but
+   maintains no flow state. The difference from RED is an additional step
+   during the enqueuing process. If average queue size is over the
+   low threshold (qmin), a packet is chosen at random from the queue.
+   If both the new and chosen packet are from the same flow, both
+   are dropped. Unlike RED, CHOKe is not really a "classful" qdisc because it
+   needs to access packets in queue randomly. It has a minimal class
+   interface to allow overriding the builtin flow classifier with
+   filters.
+
+   Source:
+   R. Pan, B. Prabhakar, and K. Psounis, "CHOKe, A Stateless
+   Active Queue Management Scheme for Approximating Fair Bandwidth Allocation",
+   IEEE INFOCOM, 2000.
+
+   A. Tang, J. Wang, S. Low, "Understanding CHOKe: Throughput and Spatial
+   Characteristics", IEEE/ACM Transactions on Networking, 2004
+
+ */
+
+/* Upper bound on size of sk_buff table (packets) */
+#define CHOKE_MAX_QUEUE	(128*1024 - 1)
+
+struct choke_sched_data {
+/* Parameters */
+	u32		 limit;
+	unsigned char	 flags;
+
+	struct red_parms parms;
+
+/* Variables */
+	struct tcf_proto *filter_list;
+	struct {
+		u32	prob_drop;	/* Early probability drops */
+		u32	prob_mark;	/* Early probability marks */
+		u32	forced_drop;	/* Forced drops, qavg > max_thresh */
+		u32	forced_mark;	/* Forced marks, qavg > max_thresh */
+		u32	pdrop;          /* Drops due to queue limits */
+		u32	other;          /* Drops due to drop() calls */
+		u32	matched;	/* Drops to flow match */
+	} stats;
+
+	unsigned int	 head;
+	unsigned int	 tail;
+
+	unsigned int	 tab_mask; /* size - 1 */
+
+	struct sk_buff **tab;
+};
+
+/* deliver a random number between 0 and N - 1 */
+static u32 random_N(unsigned int N)
+{
+	return reciprocal_divide(random32(), N);
+}
+
+/* number of elements in queue including holes */
+static unsigned int choke_len(const struct choke_sched_data *q)
+{
+	return (q->tail - q->head) & q->tab_mask;
+}
+
+/* Is ECN parameter configured */
+static int use_ecn(const struct choke_sched_data *q)
+{
+	return q->flags & TC_RED_ECN;
+}
+
+/* Should packets over max just be dropped (versus marked) */
+static int use_harddrop(const struct choke_sched_data *q)
+{
+	return q->flags & TC_RED_HARDDROP;
+}
+
+/* Move head pointer forward to skip over holes */
+static void choke_zap_head_holes(struct choke_sched_data *q)
+{
+	do {
+		q->head = (q->head + 1) & q->tab_mask;
+		if (q->head == q->tail)
+			break;
+	} while (q->tab[q->head] == NULL);
+}
+
+/* Move tail pointer backwards to reuse holes */
+static void choke_zap_tail_holes(struct choke_sched_data *q)
+{
+	do {
+		q->tail = (q->tail - 1) & q->tab_mask;
+		if (q->head == q->tail)
+			break;
+	} while (q->tab[q->tail] == NULL);
+}
+
+/* Drop packet from queue array by creating a "hole" */
+static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb = q->tab[idx];
+
+	q->tab[idx] = NULL;
+
+	if (idx == q->head)
+		choke_zap_head_holes(q);
+	if (idx == q->tail)
+		choke_zap_tail_holes(q);
+
+	sch->qstats.backlog -= qdisc_pkt_len(skb);
+	qdisc_drop(skb, sch);
+	qdisc_tree_decrease_qlen(sch, 1);
+	--sch->q.qlen;
+}
+
+/*
+ * Compare flow of two packets
+ *  Returns true only if source and destination address and port match.
+ *          false for special cases
+ */
+static bool choke_match_flow(struct sk_buff *skb1,
+			     struct sk_buff *skb2)
+{
+	int off1, off2, poff;
+	const u32 *ports1, *ports2;
+	u8 ip_proto;
+	__u32 hash1;
+
+	if (skb1->protocol != skb2->protocol)
+		return false;
+
+	/* Use hash value as quick check
+	 * Assumes that __skb_get_rxhash makes IP header and ports linear
+	 */
+	hash1 = skb_get_rxhash(skb1);
+	if (!hash1 || hash1 != skb_get_rxhash(skb2))
+		return false;
+
+	/* Probably match, but be sure to avoid hash collisions */
+	off1 = skb_network_offset(skb1);
+	off2 = skb_network_offset(skb2);
+
+	switch (skb1->protocol) {
+	case __constant_htons(ETH_P_IP): {
+		const struct iphdr *ip1, *ip2;
+
+		ip1 = (const struct iphdr *) (skb1->data + off1);
+		ip2 = (const struct iphdr *) (skb2->data + off2);
+
+		ip_proto = ip1->protocol;
+		if (ip_proto != ip2->protocol ||
+		    ip1->saddr != ip2->saddr || ip1->daddr != ip2->daddr)
+			return false;
+
+		if ((ip1->frag_off | ip2->frag_off) & htons(IP_MF | IP_OFFSET))
+			ip_proto = 0;
+		off1 += ip1->ihl * 4;
+		off2 += ip2->ihl * 4;
+		break;
+	}
+
+	case __constant_htons(ETH_P_IPV6): {
+		const struct ipv6hdr *ip1, *ip2;
+
+		ip1 = (const struct ipv6hdr *) (skb1->data + off1);
+		ip2 = (const struct ipv6hdr *) (skb2->data + off2);
+
+		ip_proto = ip1->nexthdr;
+		if (ip_proto != ip2->nexthdr ||
+		    ipv6_addr_cmp(&ip1->saddr, &ip2->saddr) ||
+		    ipv6_addr_cmp(&ip1->daddr, &ip2->daddr))
+			return false;
+		off1 += 40;
+		off2 += 40;
+	}
+
+	default: /* Maybe compare MAC header here? */
+		return false;
+	}
+
+	poff = proto_ports_offset(ip_proto);
+	if (poff < 0)
+		return true;
+
+	off1 += poff;
+	off2 += poff;
+
+	ports1 = (__force u32 *)(skb1->data + off1);
+	ports2 = (__force u32 *)(skb2->data + off2);
+	return *ports1 == *ports2;
+}
+
+struct choke_skb_cb {
+	u16 classid;
+};
+
+static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(skb->cb) <
+		sizeof(struct qdisc_skb_cb) + sizeof(struct choke_skb_cb));
+	return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data;
+}
+
+static inline void choke_set_classid(struct sk_buff *skb, u16 classid)
+{
+	choke_skb_cb(skb)->classid = classid;
+}
+
+static u16 choke_get_classid(const struct sk_buff *skb)
+{
+	return choke_skb_cb(skb)->classid;
+}
+
+/*
+ * Classify flow using either:
+ *  1. pre-existing classification result in skb
+ *  2. fast internal classification
+ *  3. use TC filter based classification
+ */
+static bool choke_classify(struct sk_buff *skb,
+			   struct Qdisc *sch, int *qerr)
+
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct tcf_result res;
+	int result;
+
+	result = tc_classify(skb, q->filter_list, &res);
+	if (result >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+		switch (result) {
+		case TC_ACT_STOLEN:
+		case TC_ACT_QUEUED:
+			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+		case TC_ACT_SHOT:
+			return false;
+		}
+#endif
+		choke_set_classid(skb, TC_H_MIN(res.classid));
+		return true;
+	}
+
+	return false;
+}
+
+/*
+ * Select a packet at random from queue
+ * HACK: since queue can have holes from previous deletion; retry several
+ *   times to find a random skb but then just give up and return the head
+ * Will return NULL if queue is empty (q->head == q->tail)
+ */
+static struct sk_buff *choke_peek_random(const struct choke_sched_data *q,
+					 unsigned int *pidx)
+{
+	struct sk_buff *skb;
+	int retrys = 3;
+
+	do {
+		*pidx = (q->head + random_N(choke_len(q))) & q->tab_mask;
+		skb = q->tab[*pidx];
+		if (skb)
+			return skb;
+	} while (--retrys > 0);
+
+	return q->tab[*pidx = q->head];
+}
+
+/*
+ * Compare new packet with random packet in queue
+ * returns true if matched and sets *pidx
+ */
+static bool choke_match_random(const struct choke_sched_data *q,
+			       struct sk_buff *nskb,
+			       unsigned int *pidx)
+{
+	struct sk_buff *oskb;
+
+	if (q->head == q->tail)
+		return false;
+
+	oskb = choke_peek_random(q, pidx);
+	if (q->filter_list)
+		return choke_get_classid(nskb) == choke_get_classid(oskb);
+
+	return choke_match_flow(oskb, nskb);
+}
+
+static int choke_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct red_parms *p = &q->parms;
+	int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+
+	if (q->filter_list) {
+		/* If using external classifiers, get result and record it. */
+		if (!choke_classify(skb, sch, &ret))
+			goto other_drop;	/* Packet was eaten by filter */
+	}
+
+	/* Compute average queue usage (see RED) */
+	p->qavg = red_calc_qavg(p, sch->q.qlen);
+	if (red_is_idling(p))
+		red_end_of_idle_period(p);
+
+	/* Is queue small? */
+	if (p->qavg <= p->qth_min)
+		p->qcount = -1;
+	else {
+		unsigned int idx;
+
+		/* Draw a packet at random from queue and compare flow */
+		if (choke_match_random(q, skb, &idx)) {
+			q->stats.matched++;
+			choke_drop_by_idx(sch, idx);
+			goto congestion_drop;
+		}
+
+		/* Queue is large, always mark/drop */
+		if (p->qavg > p->qth_max) {
+			p->qcount = -1;
+
+			sch->qstats.overlimits++;
+			if (use_harddrop(q) || !use_ecn(q) ||
+			    !INET_ECN_set_ce(skb)) {
+				q->stats.forced_drop++;
+				goto congestion_drop;
+			}
+
+			q->stats.forced_mark++;
+		} else if (++p->qcount) {
+			if (red_mark_probability(p, p->qavg)) {
+				p->qcount = 0;
+				p->qR = red_random(p);
+
+				sch->qstats.overlimits++;
+				if (!use_ecn(q) || !INET_ECN_set_ce(skb)) {
+					q->stats.prob_drop++;
+					goto congestion_drop;
+				}
+
+				q->stats.prob_mark++;
+			}
+		} else
+			p->qR = red_random(p);
+	}
+
+	/* Admit new packet */
+	if (sch->q.qlen < q->limit) {
+		q->tab[q->tail] = skb;
+		q->tail = (q->tail + 1) & q->tab_mask;
+		++sch->q.qlen;
+		sch->qstats.backlog += qdisc_pkt_len(skb);
+		return NET_XMIT_SUCCESS;
+	}
+
+	q->stats.pdrop++;
+	sch->qstats.drops++;
+	kfree_skb(skb);
+	return NET_XMIT_DROP;
+
+ congestion_drop:
+	qdisc_drop(skb, sch);
+	return NET_XMIT_CN;
+
+ other_drop:
+	if (ret & __NET_XMIT_BYPASS)
+		sch->qstats.drops++;
+	kfree_skb(skb);
+	return ret;
+}
+
+static struct sk_buff *choke_dequeue(struct Qdisc *sch)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct sk_buff *skb;
+
+	if (q->head == q->tail) {
+		if (!red_is_idling(&q->parms))
+			red_start_of_idle_period(&q->parms);
+		return NULL;
+	}
+
+	skb = q->tab[q->head];
+	q->tab[q->head] = NULL;
+	choke_zap_head_holes(q);
+	--sch->q.qlen;
+	sch->qstats.backlog -= qdisc_pkt_len(skb);
+	qdisc_bstats_update(sch, skb);
+
+	return skb;
+}
+
+static unsigned int choke_drop(struct Qdisc *sch)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	unsigned int len;
+
+	len = qdisc_queue_drop(sch);
+	if (len > 0)
+		q->stats.other++;
+	else {
+		if (!red_is_idling(&q->parms))
+			red_start_of_idle_period(&q->parms);
+	}
+
+	return len;
+}
+
+static void choke_reset(struct Qdisc *sch)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+
+	red_restart(&q->parms);
+}
+
+static const struct nla_policy choke_policy[TCA_CHOKE_MAX + 1] = {
+	[TCA_CHOKE_PARMS]	= { .len = sizeof(struct tc_red_qopt) },
+	[TCA_CHOKE_STAB]	= { .len = RED_STAB_SIZE },
+};
+
+
+static void choke_free(void *addr)
+{
+	if (addr) {
+		if (is_vmalloc_addr(addr))
+			vfree(addr);
+		else
+			kfree(addr);
+	}
+}
+
+static int choke_change(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct nlattr *tb[TCA_CHOKE_MAX + 1];
+	const struct tc_red_qopt *ctl;
+	int err;
+	struct sk_buff **old = NULL;
+	unsigned int mask;
+
+	if (opt == NULL)
+		return -EINVAL;
+
+	err = nla_parse_nested(tb, TCA_CHOKE_MAX, opt, choke_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[TCA_CHOKE_PARMS] == NULL ||
+	    tb[TCA_CHOKE_STAB] == NULL)
+		return -EINVAL;
+
+	ctl = nla_data(tb[TCA_CHOKE_PARMS]);
+
+	if (ctl->limit > CHOKE_MAX_QUEUE)
+		return -EINVAL;
+
+	mask = roundup_pow_of_two(ctl->limit + 1) - 1;
+	if (mask != q->tab_mask) {
+		struct sk_buff **ntab;
+
+		ntab = kcalloc(mask + 1, sizeof(struct sk_buff *), GFP_KERNEL);
+		if (!ntab)
+			ntab = vzalloc((mask + 1) * sizeof(struct sk_buff *));
+		if (!ntab)
+			return -ENOMEM;
+
+		sch_tree_lock(sch);
+		old = q->tab;
+		if (old) {
+			unsigned int oqlen = sch->q.qlen, tail = 0;
+
+			while (q->head != q->tail) {
+				struct sk_buff *skb = q->tab[q->head];
+
+				q->head = (q->head + 1) & q->tab_mask;
+				if (!skb)
+					continue;
+				if (tail < mask) {
+					ntab[tail++] = skb;
+					continue;
+				}
+				sch->qstats.backlog -= qdisc_pkt_len(skb);
+				--sch->q.qlen;
+				qdisc_drop(skb, sch);
+			}
+			qdisc_tree_decrease_qlen(sch, oqlen - sch->q.qlen);
+			q->head = 0;
+			q->tail = tail;
+		}
+
+		q->tab_mask = mask;
+		q->tab = ntab;
+	} else
+		sch_tree_lock(sch);
+
+	q->flags = ctl->flags;
+	q->limit = ctl->limit;
+
+	red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog,
+		      ctl->Plog, ctl->Scell_log,
+		      nla_data(tb[TCA_CHOKE_STAB]));
+
+	if (q->head == q->tail)
+		red_end_of_idle_period(&q->parms);
+
+	sch_tree_unlock(sch);
+	choke_free(old);
+	return 0;
+}
+
+static int choke_init(struct Qdisc *sch, struct nlattr *opt)
+{
+	return choke_change(sch, opt);
+}
+
+static int choke_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct nlattr *opts = NULL;
+	struct tc_red_qopt opt = {
+		.limit		= q->limit,
+		.flags		= q->flags,
+		.qth_min	= q->parms.qth_min >> q->parms.Wlog,
+		.qth_max	= q->parms.qth_max >> q->parms.Wlog,
+		.Wlog		= q->parms.Wlog,
+		.Plog		= q->parms.Plog,
+		.Scell_log	= q->parms.Scell_log,
+	};
+
+	opts = nla_nest_start(skb, TCA_OPTIONS);
+	if (opts == NULL)
+		goto nla_put_failure;
+
+	NLA_PUT(skb, TCA_CHOKE_PARMS, sizeof(opt), &opt);
+	return nla_nest_end(skb, opts);
+
+nla_put_failure:
+	nla_nest_cancel(skb, opts);
+	return -EMSGSIZE;
+}
+
+static int choke_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+	struct tc_choke_xstats st = {
+		.early	= q->stats.prob_drop + q->stats.forced_drop,
+		.marked	= q->stats.prob_mark + q->stats.forced_mark,
+		.pdrop	= q->stats.pdrop,
+		.other	= q->stats.other,
+		.matched = q->stats.matched,
+	};
+
+	return gnet_stats_copy_app(d, &st, sizeof(st));
+}
+
+static void choke_destroy(struct Qdisc *sch)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+
+	tcf_destroy_chain(&q->filter_list);
+	choke_free(q->tab);
+}
+
+static struct Qdisc *choke_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	return NULL;
+}
+
+static unsigned long choke_get(struct Qdisc *sch, u32 classid)
+{
+	return 0;
+}
+
+static void choke_put(struct Qdisc *q, unsigned long cl)
+{
+}
+
+static unsigned long choke_bind(struct Qdisc *sch, unsigned long parent,
+				u32 classid)
+{
+	return 0;
+}
+
+static struct tcf_proto **choke_find_tcf(struct Qdisc *sch, unsigned long cl)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+
+	if (cl)
+		return NULL;
+	return &q->filter_list;
+}
+
+static int choke_dump_class(struct Qdisc *sch, unsigned long cl,
+			  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	tcm->tcm_handle |= TC_H_MIN(cl);
+	return 0;
+}
+
+static void choke_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+	if (!arg->stop) {
+		if (arg->fn(sch, 1, arg) < 0) {
+			arg->stop = 1;
+			return;
+		}
+		arg->count++;
+	}
+}
+
+static const struct Qdisc_class_ops choke_class_ops = {
+	.leaf		=	choke_leaf,
+	.get		=	choke_get,
+	.put		=	choke_put,
+	.tcf_chain	=	choke_find_tcf,
+	.bind_tcf	=	choke_bind,
+	.unbind_tcf	=	choke_put,
+	.dump		=	choke_dump_class,
+	.walk		=	choke_walk,
+};
+
+static struct sk_buff *choke_peek_head(struct Qdisc *sch)
+{
+	struct choke_sched_data *q = qdisc_priv(sch);
+
+	return (q->head != q->tail) ? q->tab[q->head] : NULL;
+}
+
+static struct Qdisc_ops choke_qdisc_ops __read_mostly = {
+	.id		=	"choke",
+	.priv_size	=	sizeof(struct choke_sched_data),
+
+	.enqueue	=	choke_enqueue,
+	.dequeue	=	choke_dequeue,
+	.peek		=	choke_peek_head,
+	.drop		=	choke_drop,
+	.init		=	choke_init,
+	.destroy	=	choke_destroy,
+	.reset		=	choke_reset,
+	.change		=	choke_change,
+	.dump		=	choke_dump,
+	.dump_stats	=	choke_dump_stats,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init choke_module_init(void)
+{
+	return register_qdisc(&choke_qdisc_ops);
+}
+
+static void __exit choke_module_exit(void)
+{
+	unregister_qdisc(&choke_qdisc_ops);
+}
+
+module_init(choke_module_init)
+module_exit(choke_module_exit)
+
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 0f7bf3f..2c79020 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -137,10 +137,10 @@ static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
 		mask = nla_get_u8(tb[TCA_DSMARK_MASK]);
 
 	if (tb[TCA_DSMARK_VALUE])
-		p->value[*arg-1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
+		p->value[*arg - 1] = nla_get_u8(tb[TCA_DSMARK_VALUE]);
 
 	if (tb[TCA_DSMARK_MASK])
-		p->mask[*arg-1] = mask;
+		p->mask[*arg - 1] = mask;
 
 	err = 0;
 
@@ -155,8 +155,8 @@ static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
 	if (!dsmark_valid_index(p, arg))
 		return -EINVAL;
 
-	p->mask[arg-1] = 0xff;
-	p->value[arg-1] = 0;
+	p->mask[arg - 1] = 0xff;
+	p->value[arg - 1] = 0;
 
 	return 0;
 }
@@ -175,7 +175,7 @@ static void dsmark_walk(struct Qdisc *sch, struct qdisc_walker *walker)
 		if (p->mask[i] == 0xff && !p->value[i])
 			goto ignore;
 		if (walker->count >= walker->skip) {
-			if (walker->fn(sch, i+1, walker) < 0) {
+			if (walker->fn(sch, i + 1, walker) < 0) {
 				walker->stop = 1;
 				break;
 			}
@@ -304,9 +304,8 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
 		 * and don't need yet another qdisc as a bypass.
 		 */
 		if (p->mask[index] != 0xff || p->value[index])
-			printk(KERN_WARNING
-			       "dsmark_dequeue: unsupported protocol %d\n",
-			       ntohs(skb->protocol));
+			pr_warning("dsmark_dequeue: unsupported protocol %d\n",
+				   ntohs(skb->protocol));
 		break;
 	}
 
@@ -424,14 +423,14 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
 	if (!dsmark_valid_index(p, cl))
 		return -EINVAL;
 
-	tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1);
+	tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl - 1);
 	tcm->tcm_info = p->q->handle;
 
 	opts = nla_nest_start(skb, TCA_OPTIONS);
 	if (opts == NULL)
 		goto nla_put_failure;
-	NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl-1]);
-	NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl-1]);
+	NLA_PUT_U8(skb, TCA_DSMARK_MASK, p->mask[cl - 1]);
+	NLA_PUT_U8(skb, TCA_DSMARK_VALUE, p->value[cl - 1]);
 
 	return nla_nest_end(skb, opts);
 
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index d468b47..66effe2 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -19,36 +19,25 @@
 
 /* 1 band FIFO pseudo-"scheduler" */
 
-struct fifo_sched_data
+static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
-	u32 limit;
-};
-
-static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
-{
-	struct fifo_sched_data *q = qdisc_priv(sch);
-
-	if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <= q->limit))
+	if (likely(sch->qstats.backlog + qdisc_pkt_len(skb) <= sch->limit))
 		return qdisc_enqueue_tail(skb, sch);
 
 	return qdisc_reshape_fail(skb, sch);
 }
 
-static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
-	struct fifo_sched_data *q = qdisc_priv(sch);
-
-	if (likely(skb_queue_len(&sch->q) < q->limit))
+	if (likely(skb_queue_len(&sch->q) < sch->limit))
 		return qdisc_enqueue_tail(skb, sch);
 
 	return qdisc_reshape_fail(skb, sch);
 }
 
-static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
-	struct fifo_sched_data *q = qdisc_priv(sch);
-
-	if (likely(skb_queue_len(&sch->q) < q->limit))
+	if (likely(skb_queue_len(&sch->q) < sch->limit))
 		return qdisc_enqueue_tail(skb, sch);
 
 	/* queue full, remove one skb to fulfill the limit */
@@ -61,31 +50,40 @@ static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 
 static int fifo_init(struct Qdisc *sch, struct nlattr *opt)
 {
-	struct fifo_sched_data *q = qdisc_priv(sch);
+	bool bypass;
+	bool is_bfifo = sch->ops == &bfifo_qdisc_ops;
 
 	if (opt == NULL) {
 		u32 limit = qdisc_dev(sch)->tx_queue_len ? : 1;
 
-		if (sch->ops == &bfifo_qdisc_ops)
+		if (is_bfifo)
 			limit *= psched_mtu(qdisc_dev(sch));
 
-		q->limit = limit;
+		sch->limit = limit;
 	} else {
 		struct tc_fifo_qopt *ctl = nla_data(opt);
 
 		if (nla_len(opt) < sizeof(*ctl))
 			return -EINVAL;
 
-		q->limit = ctl->limit;
+		sch->limit = ctl->limit;
 	}
 
+	if (is_bfifo)
+		bypass = sch->limit >= psched_mtu(qdisc_dev(sch));
+	else
+		bypass = sch->limit >= 1;
+
+	if (bypass)
+		sch->flags |= TCQ_F_CAN_BYPASS;
+	else
+		sch->flags &= ~TCQ_F_CAN_BYPASS;
 	return 0;
 }
 
 static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
-	struct fifo_sched_data *q = qdisc_priv(sch);
-	struct tc_fifo_qopt opt = { .limit = q->limit };
+	struct tc_fifo_qopt opt = { .limit = sch->limit };
 
 	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 	return skb->len;
@@ -96,7 +94,7 @@ nla_put_failure:
 
 struct Qdisc_ops pfifo_qdisc_ops __read_mostly = {
 	.id		=	"pfifo",
-	.priv_size	=	sizeof(struct fifo_sched_data),
+	.priv_size	=	0,
 	.enqueue	=	pfifo_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
 	.peek		=	qdisc_peek_head,
@@ -111,7 +109,7 @@ EXPORT_SYMBOL(pfifo_qdisc_ops);
 
 struct Qdisc_ops bfifo_qdisc_ops __read_mostly = {
 	.id		=	"bfifo",
-	.priv_size	=	sizeof(struct fifo_sched_data),
+	.priv_size	=	0,
 	.enqueue	=	bfifo_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
 	.peek		=	qdisc_peek_head,
@@ -126,7 +124,7 @@ EXPORT_SYMBOL(bfifo_qdisc_ops);
 
 struct Qdisc_ops pfifo_head_drop_qdisc_ops __read_mostly = {
 	.id		=	"pfifo_head_drop",
-	.priv_size	=	sizeof(struct fifo_sched_data),
+	.priv_size	=	0,
 	.enqueue	=	pfifo_tail_enqueue,
 	.dequeue	=	qdisc_dequeue_head,
 	.peek		=	qdisc_peek_head,
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 1bc6980..c84b659 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -87,8 +87,8 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb,
 		 */
 		kfree_skb(skb);
 		if (net_ratelimit())
-			printk(KERN_WARNING "Dead loop on netdevice %s, "
-			       "fix it urgently!\n", dev_queue->dev->name);
+			pr_warning("Dead loop on netdevice %s, fix it urgently!\n",
+				   dev_queue->dev->name);
 		ret = qdisc_qlen(q);
 	} else {
 		/*
@@ -137,8 +137,8 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
 	} else {
 		/* Driver returned NETDEV_TX_BUSY - requeue skb */
 		if (unlikely (ret != NETDEV_TX_BUSY && net_ratelimit()))
-			printk(KERN_WARNING "BUG %s code %d qlen %d\n",
-			       dev->name, ret, q->q.qlen);
+			pr_warning("BUG %s code %d qlen %d\n",
+				   dev->name, ret, q->q.qlen);
 
 		ret = dev_requeue_skb(skb, q);
 	}
@@ -412,8 +412,9 @@ static struct Qdisc noqueue_qdisc = {
 };
 
 
-static const u8 prio2band[TC_PRIO_MAX+1] =
-	{ 1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1 };
+static const u8 prio2band[TC_PRIO_MAX + 1] = {
+	1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1
+};
 
 /* 3-band FIFO queue: old style, but should be a bit faster than
    generic prio+fifo combination.
@@ -445,7 +446,7 @@ static inline struct sk_buff_head *band2list(struct pfifo_fast_priv *priv,
 	return priv->q + band;
 }
 
-static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
+static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc)
 {
 	if (skb_queue_len(&qdisc->q) < qdisc_dev(qdisc)->tx_queue_len) {
 		int band = prio2band[skb->priority & TC_PRIO_MAX];
@@ -460,7 +461,7 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
 	return qdisc_drop(skb, qdisc);
 }
 
-static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
+static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc)
 {
 	struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
 	int band = bitmap2band[priv->bitmap];
@@ -479,7 +480,7 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
 	return NULL;
 }
 
-static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
+static struct sk_buff *pfifo_fast_peek(struct Qdisc *qdisc)
 {
 	struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
 	int band = bitmap2band[priv->bitmap];
@@ -493,7 +494,7 @@ static struct sk_buff *pfifo_fast_peek(struct Qdisc* qdisc)
 	return NULL;
 }
 
-static void pfifo_fast_reset(struct Qdisc* qdisc)
+static void pfifo_fast_reset(struct Qdisc *qdisc)
 {
 	int prio;
 	struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
@@ -510,7 +511,7 @@ static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
 {
 	struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
 
-	memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
+	memcpy(&opt.priomap, prio2band, TC_PRIO_MAX + 1);
 	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 	return skb->len;
 
@@ -526,6 +527,8 @@ static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
 	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
 		skb_queue_head_init(band2list(priv, prio));
 
+	/* Can by-pass the queue discipline */
+	qdisc->flags |= TCQ_F_CAN_BYPASS;
 	return 0;
 }
 
@@ -540,27 +543,32 @@ struct Qdisc_ops pfifo_fast_ops __read_mostly = {
 	.dump		=	pfifo_fast_dump,
 	.owner		=	THIS_MODULE,
 };
+EXPORT_SYMBOL(pfifo_fast_ops);
 
 struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 			  struct Qdisc_ops *ops)
 {
 	void *p;
 	struct Qdisc *sch;
-	unsigned int size;
+	unsigned int size = QDISC_ALIGN(sizeof(*sch)) + ops->priv_size;
 	int err = -ENOBUFS;
 
-	/* ensure that the Qdisc and the private data are 64-byte aligned */
-	size = QDISC_ALIGN(sizeof(*sch));
-	size += ops->priv_size + (QDISC_ALIGNTO - 1);
-
 	p = kzalloc_node(size, GFP_KERNEL,
 			 netdev_queue_numa_node_read(dev_queue));
 
 	if (!p)
 		goto errout;
 	sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
-	sch->padded = (char *) sch - (char *) p;
-
+	/* if we got non aligned memory, ask more and do alignment ourself */
+	if (sch != p) {
+		kfree(p);
+		p = kzalloc_node(size + QDISC_ALIGNTO - 1, GFP_KERNEL,
+				 netdev_queue_numa_node_read(dev_queue));
+		if (!p)
+			goto errout;
+		sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
+		sch->padded = (char *) sch - (char *) p;
+	}
 	INIT_LIST_HEAD(&sch->list);
 	skb_queue_head_init(&sch->q);
 	spin_lock_init(&sch->busylock);
@@ -630,7 +638,7 @@ void qdisc_destroy(struct Qdisc *qdisc)
 #ifdef CONFIG_NET_SCHED
 	qdisc_list_del(qdisc);
 
-	qdisc_put_stab(qdisc->stab);
+	qdisc_put_stab(rtnl_dereference(qdisc->stab));
 #endif
 	gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
 	if (ops->reset)
@@ -674,25 +682,21 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
 
 	return oqdisc;
 }
+EXPORT_SYMBOL(dev_graft_qdisc);
 
 static void attach_one_default_qdisc(struct net_device *dev,
 				     struct netdev_queue *dev_queue,
 				     void *_unused)
 {
-	struct Qdisc *qdisc;
+	struct Qdisc *qdisc = &noqueue_qdisc;
 
 	if (dev->tx_queue_len) {
 		qdisc = qdisc_create_dflt(dev_queue,
 					  &pfifo_fast_ops, TC_H_ROOT);
 		if (!qdisc) {
-			printk(KERN_INFO "%s: activation failed\n", dev->name);
+			netdev_info(dev, "activation failed\n");
 			return;
 		}
-
-		/* Can by-pass the queue discipline for default qdisc */
-		qdisc->flags |= TCQ_F_CAN_BYPASS;
-	} else {
-		qdisc =  &noqueue_qdisc;
 	}
 	dev_queue->qdisc_sleeping = qdisc;
 }
@@ -761,6 +765,7 @@ void dev_activate(struct net_device *dev)
 		dev_watchdog_up(dev);
 	}
 }
+EXPORT_SYMBOL(dev_activate);
 
 static void dev_deactivate_queue(struct net_device *dev,
 				 struct netdev_queue *dev_queue,
@@ -841,6 +846,7 @@ void dev_deactivate(struct net_device *dev)
 	dev_deactivate_many(&single);
 	list_del(&single);
 }
+EXPORT_SYMBOL(dev_deactivate);
 
 static void dev_init_scheduler_queue(struct net_device *dev,
 				     struct netdev_queue *dev_queue,
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 51dcc2a..b9493a0 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -32,8 +32,7 @@
 struct gred_sched_data;
 struct gred_sched;
 
-struct gred_sched_data
-{
+struct gred_sched_data {
 	u32		limit;		/* HARD maximal queue length	*/
 	u32      	DP;		/* the drop pramaters */
 	u32		bytesin;	/* bytes seen on virtualQ so far*/
@@ -50,8 +49,7 @@ enum {
 	GRED_RIO_MODE,
 };
 
-struct gred_sched
-{
+struct gred_sched {
 	struct gred_sched_data *tab[MAX_DPs];
 	unsigned long	flags;
 	u32		red_flags;
@@ -150,17 +148,18 @@ static inline int gred_use_harddrop(struct gred_sched *t)
 	return t->red_flags & TC_RED_HARDDROP;
 }
 
-static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
-	struct gred_sched_data *q=NULL;
-	struct gred_sched *t= qdisc_priv(sch);
+	struct gred_sched_data *q = NULL;
+	struct gred_sched *t = qdisc_priv(sch);
 	unsigned long qavg = 0;
 	u16 dp = tc_index_to_dp(skb);
 
-	if (dp >= t->DPs  || (q = t->tab[dp]) == NULL) {
+	if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
 		dp = t->def;
 
-		if ((q = t->tab[dp]) == NULL) {
+		q = t->tab[dp];
+		if (!q) {
 			/* Pass through packets not assigned to a DP
 			 * if no default DP has been configured. This
 			 * allows for DP flows to be left untouched.
@@ -183,7 +182,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 		for (i = 0; i < t->DPs; i++) {
 			if (t->tab[i] && t->tab[i]->prio < q->prio &&
 			    !red_is_idling(&t->tab[i]->parms))
-				qavg +=t->tab[i]->parms.qavg;
+				qavg += t->tab[i]->parms.qavg;
 		}
 
 	}
@@ -203,28 +202,28 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 		gred_store_wred_set(t, q);
 
 	switch (red_action(&q->parms, q->parms.qavg + qavg)) {
-		case RED_DONT_MARK:
-			break;
-
-		case RED_PROB_MARK:
-			sch->qstats.overlimits++;
-			if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) {
-				q->stats.prob_drop++;
-				goto congestion_drop;
-			}
-
-			q->stats.prob_mark++;
-			break;
-
-		case RED_HARD_MARK:
-			sch->qstats.overlimits++;
-			if (gred_use_harddrop(t) || !gred_use_ecn(t) ||
-			    !INET_ECN_set_ce(skb)) {
-				q->stats.forced_drop++;
-				goto congestion_drop;
-			}
-			q->stats.forced_mark++;
-			break;
+	case RED_DONT_MARK:
+		break;
+
+	case RED_PROB_MARK:
+		sch->qstats.overlimits++;
+		if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) {
+			q->stats.prob_drop++;
+			goto congestion_drop;
+		}
+
+		q->stats.prob_mark++;
+		break;
+
+	case RED_HARD_MARK:
+		sch->qstats.overlimits++;
+		if (gred_use_harddrop(t) || !gred_use_ecn(t) ||
+		    !INET_ECN_set_ce(skb)) {
+			q->stats.forced_drop++;
+			goto congestion_drop;
+		}
+		q->stats.forced_mark++;
+		break;
 	}
 
 	if (q->backlog + qdisc_pkt_len(skb) <= q->limit) {
@@ -241,7 +240,7 @@ congestion_drop:
 	return NET_XMIT_CN;
 }
 
-static struct sk_buff *gred_dequeue(struct Qdisc* sch)
+static struct sk_buff *gred_dequeue(struct Qdisc *sch)
 {
 	struct sk_buff *skb;
 	struct gred_sched *t = qdisc_priv(sch);
@@ -254,9 +253,9 @@ static struct sk_buff *gred_dequeue(struct Qdisc* sch)
 
 		if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
 			if (net_ratelimit())
-				printk(KERN_WARNING "GRED: Unable to relocate "
-				       "VQ 0x%x after dequeue, screwing up "
-				       "backlog.\n", tc_index_to_dp(skb));
+				pr_warning("GRED: Unable to relocate VQ 0x%x "
+					   "after dequeue, screwing up "
+					   "backlog.\n", tc_index_to_dp(skb));
 		} else {
 			q->backlog -= qdisc_pkt_len(skb);
 
@@ -273,7 +272,7 @@ static struct sk_buff *gred_dequeue(struct Qdisc* sch)
 	return NULL;
 }
 
-static unsigned int gred_drop(struct Qdisc* sch)
+static unsigned int gred_drop(struct Qdisc *sch)
 {
 	struct sk_buff *skb;
 	struct gred_sched *t = qdisc_priv(sch);
@@ -286,9 +285,9 @@ static unsigned int gred_drop(struct Qdisc* sch)
 
 		if (dp >= t->DPs || (q = t->tab[dp]) == NULL) {
 			if (net_ratelimit())
-				printk(KERN_WARNING "GRED: Unable to relocate "
-				       "VQ 0x%x while dropping, screwing up "
-				       "backlog.\n", tc_index_to_dp(skb));
+				pr_warning("GRED: Unable to relocate VQ 0x%x "
+					   "while dropping, screwing up "
+					   "backlog.\n", tc_index_to_dp(skb));
 		} else {
 			q->backlog -= len;
 			q->stats.other++;
@@ -308,7 +307,7 @@ static unsigned int gred_drop(struct Qdisc* sch)
 
 }
 
-static void gred_reset(struct Qdisc* sch)
+static void gred_reset(struct Qdisc *sch)
 {
 	int i;
 	struct gred_sched *t = qdisc_priv(sch);
@@ -369,8 +368,8 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct nlattr *dps)
 
 	for (i = table->DPs; i < MAX_DPs; i++) {
 		if (table->tab[i]) {
-			printk(KERN_WARNING "GRED: Warning: Destroying "
-			       "shadowed VQ 0x%x\n", i);
+			pr_warning("GRED: Warning: Destroying "
+				   "shadowed VQ 0x%x\n", i);
 			gred_destroy_vq(table->tab[i]);
 			table->tab[i] = NULL;
 		}
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index 14a799d..6488e64 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -81,8 +81,7 @@
  *   that are expensive on 32-bit architectures.
  */
 
-struct internal_sc
-{
+struct internal_sc {
 	u64	sm1;	/* scaled slope of the 1st segment */
 	u64	ism1;	/* scaled inverse-slope of the 1st segment */
 	u64	dx;	/* the x-projection of the 1st segment */
@@ -92,8 +91,7 @@ struct internal_sc
 };
 
 /* runtime service curve */
-struct runtime_sc
-{
+struct runtime_sc {
 	u64	x;	/* current starting position on x-axis */
 	u64	y;	/* current starting position on y-axis */
 	u64	sm1;	/* scaled slope of the 1st segment */
@@ -104,15 +102,13 @@ struct runtime_sc
 	u64	ism2;	/* scaled inverse-slope of the 2nd segment */
 };
 
-enum hfsc_class_flags
-{
+enum hfsc_class_flags {
 	HFSC_RSC = 0x1,
 	HFSC_FSC = 0x2,
 	HFSC_USC = 0x4
 };
 
-struct hfsc_class
-{
+struct hfsc_class {
 	struct Qdisc_class_common cl_common;
 	unsigned int	refcnt;		/* usage count */
 
@@ -140,8 +136,8 @@ struct hfsc_class
 	u64	cl_cumul;		/* cumulative work in bytes done by
 					   real-time criteria */
 
-	u64 	cl_d;			/* deadline*/
-	u64 	cl_e;			/* eligible time */
+	u64	cl_d;			/* deadline*/
+	u64	cl_e;			/* eligible time */
 	u64	cl_vt;			/* virtual time */
 	u64	cl_f;			/* time when this class will fit for
 					   link-sharing, max(myf, cfmin) */
@@ -176,8 +172,7 @@ struct hfsc_class
 	unsigned long	cl_nactive;	/* number of active children */
 };
 
-struct hfsc_sched
-{
+struct hfsc_sched {
 	u16	defcls;				/* default class id */
 	struct hfsc_class root;			/* root class */
 	struct Qdisc_class_hash clhash;		/* class hash */
@@ -693,7 +688,7 @@ init_vf(struct hfsc_class *cl, unsigned int len)
 		if (go_active) {
 			n = rb_last(&cl->cl_parent->vt_tree);
 			if (n != NULL) {
-				max_cl = rb_entry(n, struct hfsc_class,vt_node);
+				max_cl = rb_entry(n, struct hfsc_class, vt_node);
 				/*
 				 * set vt to the average of the min and max
 				 * classes.  if the parent's period didn't
@@ -1177,8 +1172,10 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 			return NULL;
 		}
 #endif
-		if ((cl = (struct hfsc_class *)res.class) == NULL) {
-			if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
+		cl = (struct hfsc_class *)res.class;
+		if (!cl) {
+			cl = hfsc_find_class(res.classid, sch);
+			if (!cl)
 				break; /* filter selected invalid classid */
 			if (cl->level >= head->level)
 				break; /* filter may only point downwards */
@@ -1316,7 +1313,7 @@ hfsc_dump_sc(struct sk_buff *skb, int attr, struct internal_sc *sc)
 	return -1;
 }
 
-static inline int
+static int
 hfsc_dump_curves(struct sk_buff *skb, struct hfsc_class *cl)
 {
 	if ((cl->cl_flags & HFSC_RSC) &&
@@ -1420,7 +1417,8 @@ hfsc_schedule_watchdog(struct Qdisc *sch)
 	struct hfsc_class *cl;
 	u64 next_time = 0;
 
-	if ((cl = eltree_get_minel(q)) != NULL)
+	cl = eltree_get_minel(q);
+	if (cl)
 		next_time = cl->cl_e;
 	if (q->root.cl_cfmin != 0) {
 		if (next_time == 0 || next_time > q->root.cl_cfmin)
@@ -1625,7 +1623,8 @@ hfsc_dequeue(struct Qdisc *sch)
 	 * find the class with the minimum deadline among
 	 * the eligible classes.
 	 */
-	if ((cl = eltree_get_mindl(q, cur_time)) != NULL) {
+	cl = eltree_get_mindl(q, cur_time);
+	if (cl) {
 		realtime = 1;
 	} else {
 		/*
@@ -1664,7 +1663,7 @@ hfsc_dequeue(struct Qdisc *sch)
 		set_passive(cl);
 	}
 
-	sch->flags &= ~TCQ_F_THROTTLED;
+	qdisc_unthrottled(sch);
 	qdisc_bstats_update(sch, skb);
 	sch->q.qlen--;
 
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index fc12fe6..e1429a8 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -99,9 +99,10 @@ struct htb_class {
 			struct rb_root feed[TC_HTB_NUMPRIO];	/* feed trees */
 			struct rb_node *ptr[TC_HTB_NUMPRIO];	/* current class ptr */
 			/* When class changes from state 1->2 and disconnects from
-			   parent's feed then we lost ptr value and start from the
-			   first child again. Here we store classid of the
-			   last valid ptr (used when ptr is NULL). */
+			 * parent's feed then we lost ptr value and start from the
+			 * first child again. Here we store classid of the
+			 * last valid ptr (used when ptr is NULL).
+			 */
 			u32 last_ptr_id[TC_HTB_NUMPRIO];
 		} inner;
 	} un;
@@ -185,7 +186,7 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
  * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull
  * then finish and return direct queue.
  */
-#define HTB_DIRECT (struct htb_class*)-1
+#define HTB_DIRECT ((struct htb_class *)-1L)
 
 static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
 				      int *qerr)
@@ -197,11 +198,13 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
 	int result;
 
 	/* allow to select class by setting skb->priority to valid classid;
-	   note that nfmark can be used too by attaching filter fw with no
-	   rules in it */
+	 * note that nfmark can be used too by attaching filter fw with no
+	 * rules in it
+	 */
 	if (skb->priority == sch->handle)
 		return HTB_DIRECT;	/* X:0 (direct flow) selected */
-	if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0)
+	cl = htb_find(skb->priority, sch);
+	if (cl && cl->level == 0)
 		return cl;
 
 	*qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
@@ -216,10 +219,12 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,
 			return NULL;
 		}
 #endif
-		if ((cl = (void *)res.class) == NULL) {
+		cl = (void *)res.class;
+		if (!cl) {
 			if (res.classid == sch->handle)
 				return HTB_DIRECT;	/* X:0 (direct flow) */
-			if ((cl = htb_find(res.classid, sch)) == NULL)
+			cl = htb_find(res.classid, sch);
+			if (!cl)
 				break;	/* filter selected invalid classid */
 		}
 		if (!cl->level)
@@ -378,7 +383,8 @@ static void htb_activate_prios(struct htb_sched *q, struct htb_class *cl)
 
 			if (p->un.inner.feed[prio].rb_node)
 				/* parent already has its feed in use so that
-				   reset bit in mask as parent is already ok */
+				 * reset bit in mask as parent is already ok
+				 */
 				mask &= ~(1 << prio);
 
 			htb_add_to_id_tree(p->un.inner.feed + prio, cl, prio);
@@ -413,8 +419,9 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
 
 			if (p->un.inner.ptr[prio] == cl->node + prio) {
 				/* we are removing child which is pointed to from
-				   parent feed - forget the pointer but remember
-				   classid */
+				 * parent feed - forget the pointer but remember
+				 * classid
+				 */
 				p->un.inner.last_ptr_id[prio] = cl->common.classid;
 				p->un.inner.ptr[prio] = NULL;
 			}
@@ -663,8 +670,9 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
 				   unsigned long start)
 {
 	/* don't run for longer than 2 jiffies; 2 is used instead of
-	   1 to simplify things when jiffy is going to be incremented
-	   too soon */
+	 * 1 to simplify things when jiffy is going to be incremented
+	 * too soon
+	 */
 	unsigned long stop_at = start + 2;
 	while (time_before(jiffies, stop_at)) {
 		struct htb_class *cl;
@@ -687,7 +695,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
 
 	/* too much load - let's continue after a break for scheduling */
 	if (!(q->warned & HTB_WARN_TOOMANYEVENTS)) {
-		printk(KERN_WARNING "htb: too many events!\n");
+		pr_warning("htb: too many events!\n");
 		q->warned |= HTB_WARN_TOOMANYEVENTS;
 	}
 
@@ -695,7 +703,8 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
 }
 
 /* Returns class->node+prio from id-tree where classe's id is >= id. NULL
-   is no such one exists. */
+ * is no such one exists.
+ */
 static struct rb_node *htb_id_find_next_upper(int prio, struct rb_node *n,
 					      u32 id)
 {
@@ -739,12 +748,14 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
 	for (i = 0; i < 65535; i++) {
 		if (!*sp->pptr && *sp->pid) {
 			/* ptr was invalidated but id is valid - try to recover
-			   the original or next ptr */
+			 * the original or next ptr
+			 */
 			*sp->pptr =
 			    htb_id_find_next_upper(prio, sp->root, *sp->pid);
 		}
 		*sp->pid = 0;	/* ptr is valid now so that remove this hint as it
-				   can become out of date quickly */
+				 * can become out of date quickly
+				 */
 		if (!*sp->pptr) {	/* we are at right end; rewind & go up */
 			*sp->pptr = sp->root;
 			while ((*sp->pptr)->rb_left)
@@ -772,7 +783,8 @@ static struct htb_class *htb_lookup_leaf(struct rb_root *tree, int prio,
 }
 
 /* dequeues packet at given priority and level; call only if
-   you are sure that there is active class at prio/level */
+ * you are sure that there is active class at prio/level
+ */
 static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
 					int level)
 {
@@ -789,9 +801,10 @@ next:
 			return NULL;
 
 		/* class can be empty - it is unlikely but can be true if leaf
-		   qdisc drops packets in enqueue routine or if someone used
-		   graft operation on the leaf since last dequeue;
-		   simply deactivate and skip such class */
+		 * qdisc drops packets in enqueue routine or if someone used
+		 * graft operation on the leaf since last dequeue;
+		 * simply deactivate and skip such class
+		 */
 		if (unlikely(cl->un.leaf.q->q.qlen == 0)) {
 			struct htb_class *next;
 			htb_deactivate(q, cl);
@@ -831,7 +844,8 @@ next:
 					  ptr[0]) + prio);
 		}
 		/* this used to be after charge_class but this constelation
-		   gives us slightly better performance */
+		 * gives us slightly better performance
+		 */
 		if (!cl->un.leaf.q->q.qlen)
 			htb_deactivate(q, cl);
 		htb_charge_class(q, cl, level, skb);
@@ -852,7 +866,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
 	if (skb != NULL) {
 ok:
 		qdisc_bstats_update(sch, skb);
-		sch->flags &= ~TCQ_F_THROTTLED;
+		qdisc_unthrottled(sch);
 		sch->q.qlen--;
 		return skb;
 	}
@@ -883,6 +897,7 @@ ok:
 		m = ~q->row_mask[level];
 		while (m != (int)(-1)) {
 			int prio = ffz(m);
+
 			m |= 1 << prio;
 			skb = htb_dequeue_tree(q, prio, level);
 			if (likely(skb != NULL))
@@ -987,13 +1002,12 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
 		return err;
 
 	if (tb[TCA_HTB_INIT] == NULL) {
-		printk(KERN_ERR "HTB: hey probably you have bad tc tool ?\n");
+		pr_err("HTB: hey probably you have bad tc tool ?\n");
 		return -EINVAL;
 	}
 	gopt = nla_data(tb[TCA_HTB_INIT]);
 	if (gopt->version != HTB_VER >> 16) {
-		printk(KERN_ERR
-		       "HTB: need tc/htb version %d (minor is %d), you have %d\n",
+		pr_err("HTB: need tc/htb version %d (minor is %d), you have %d\n",
 		       HTB_VER >> 16, HTB_VER & 0xffff, gopt->version);
 		return -EINVAL;
 	}
@@ -1206,9 +1220,10 @@ static void htb_destroy(struct Qdisc *sch)
 	cancel_work_sync(&q->work);
 	qdisc_watchdog_cancel(&q->watchdog);
 	/* This line used to be after htb_destroy_class call below
-	   and surprisingly it worked in 2.4. But it must precede it
-	   because filter need its target class alive to be able to call
-	   unbind_filter on it (without Oops). */
+	 * and surprisingly it worked in 2.4. But it must precede it
+	 * because filter need its target class alive to be able to call
+	 * unbind_filter on it (without Oops).
+	 */
 	tcf_destroy_chain(&q->filter_list);
 
 	for (i = 0; i < q->clhash.hashsize; i++) {
@@ -1342,11 +1357,12 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 
 		/* check maximal depth */
 		if (parent && parent->parent && parent->parent->level < 2) {
-			printk(KERN_ERR "htb: tree is too deep\n");
+			pr_err("htb: tree is too deep\n");
 			goto failure;
 		}
 		err = -ENOBUFS;
-		if ((cl = kzalloc(sizeof(*cl), GFP_KERNEL)) == NULL)
+		cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+		if (!cl)
 			goto failure;
 
 		err = gen_new_estimator(&cl->bstats, &cl->rate_est,
@@ -1366,8 +1382,9 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 			RB_CLEAR_NODE(&cl->node[prio]);
 
 		/* create leaf qdisc early because it uses kmalloc(GFP_KERNEL)
-		   so that can't be used inside of sch_tree_lock
-		   -- thanks to Karlis Peisenieks */
+		 * so that can't be used inside of sch_tree_lock
+		 * -- thanks to Karlis Peisenieks
+		 */
 		new_q = qdisc_create_dflt(sch->dev_queue,
 					  &pfifo_qdisc_ops, classid);
 		sch_tree_lock(sch);
@@ -1419,17 +1436,18 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 	}
 
 	/* it used to be a nasty bug here, we have to check that node
-	   is really leaf before changing cl->un.leaf ! */
+	 * is really leaf before changing cl->un.leaf !
+	 */
 	if (!cl->level) {
 		cl->quantum = rtab->rate.rate / q->rate2quantum;
 		if (!hopt->quantum && cl->quantum < 1000) {
-			printk(KERN_WARNING
+			pr_warning(
 			       "HTB: quantum of class %X is small. Consider r2q change.\n",
 			       cl->common.classid);
 			cl->quantum = 1000;
 		}
 		if (!hopt->quantum && cl->quantum > 200000) {
-			printk(KERN_WARNING
+			pr_warning(
 			       "HTB: quantum of class %X is big. Consider r2q change.\n",
 			       cl->common.classid);
 			cl->quantum = 200000;
@@ -1478,13 +1496,13 @@ static unsigned long htb_bind_filter(struct Qdisc *sch, unsigned long parent,
 	struct htb_class *cl = htb_find(classid, sch);
 
 	/*if (cl && !cl->level) return 0;
-	   The line above used to be there to prevent attaching filters to
-	   leaves. But at least tc_index filter uses this just to get class
-	   for other reasons so that we have to allow for it.
-	   ----
-	   19.6.2002 As Werner explained it is ok - bind filter is just
-	   another way to "lock" the class - unlike "get" this lock can
-	   be broken by class during destroy IIUC.
+	 * The line above used to be there to prevent attaching filters to
+	 * leaves. But at least tc_index filter uses this just to get class
+	 * for other reasons so that we have to allow for it.
+	 * ----
+	 * 19.6.2002 As Werner explained it is ok - bind filter is just
+	 * another way to "lock" the class - unlike "get" this lock can
+	 * be broken by class during destroy IIUC.
 	 */
 	if (cl)
 		cl->filter_cnt++;
diff --git a/net/sched/sch_mq.c b/net/sched/sch_mq.c
index ecc302f..ec5cbc8 100644
--- a/net/sched/sch_mq.c
+++ b/net/sched/sch_mq.c
@@ -61,7 +61,6 @@ static int mq_init(struct Qdisc *sch, struct nlattr *opt)
 						    TC_H_MIN(ntx + 1)));
 		if (qdisc == NULL)
 			goto err;
-		qdisc->flags |= TCQ_F_CAN_BYPASS;
 		priv->qdiscs[ntx] = qdisc;
 	}
 
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
new file mode 100644
index 0000000..ea17cbe
--- /dev/null
+++ b/net/sched/sch_mqprio.c
@@ -0,0 +1,418 @@
+/*
+ * net/sched/sch_mqprio.c
+ *
+ * Copyright (c) 2010 John Fastabend <john.r.fastabend@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/types.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <net/netlink.h>
+#include <net/pkt_sched.h>
+#include <net/sch_generic.h>
+
+struct mqprio_sched {
+	struct Qdisc		**qdiscs;
+	int hw_owned;
+};
+
+static void mqprio_destroy(struct Qdisc *sch)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	struct mqprio_sched *priv = qdisc_priv(sch);
+	unsigned int ntx;
+
+	if (priv->qdiscs) {
+		for (ntx = 0;
+		     ntx < dev->num_tx_queues && priv->qdiscs[ntx];
+		     ntx++)
+			qdisc_destroy(priv->qdiscs[ntx]);
+		kfree(priv->qdiscs);
+	}
+
+	if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc)
+		dev->netdev_ops->ndo_setup_tc(dev, 0);
+	else
+		netdev_set_num_tc(dev, 0);
+}
+
+static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)
+{
+	int i, j;
+
+	/* Verify num_tc is not out of max range */
+	if (qopt->num_tc > TC_MAX_QUEUE)
+		return -EINVAL;
+
+	/* Verify priority mapping uses valid tcs */
+	for (i = 0; i < TC_BITMASK + 1; i++) {
+		if (qopt->prio_tc_map[i] >= qopt->num_tc)
+			return -EINVAL;
+	}
+
+	/* net_device does not support requested operation */
+	if (qopt->hw && !dev->netdev_ops->ndo_setup_tc)
+		return -EINVAL;
+
+	/* if hw owned qcount and qoffset are taken from LLD so
+	 * no reason to verify them here
+	 */
+	if (qopt->hw)
+		return 0;
+
+	for (i = 0; i < qopt->num_tc; i++) {
+		unsigned int last = qopt->offset[i] + qopt->count[i];
+
+		/* Verify the queue count is in tx range being equal to the
+		 * real_num_tx_queues indicates the last queue is in use.
+		 */
+		if (qopt->offset[i] >= dev->real_num_tx_queues ||
+		    !qopt->count[i] ||
+		    last > dev->real_num_tx_queues)
+			return -EINVAL;
+
+		/* Verify that the offset and counts do not overlap */
+		for (j = i + 1; j < qopt->num_tc; j++) {
+			if (last > qopt->offset[j])
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	struct mqprio_sched *priv = qdisc_priv(sch);
+	struct netdev_queue *dev_queue;
+	struct Qdisc *qdisc;
+	int i, err = -EOPNOTSUPP;
+	struct tc_mqprio_qopt *qopt = NULL;
+
+	BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE);
+	BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK);
+
+	if (sch->parent != TC_H_ROOT)
+		return -EOPNOTSUPP;
+
+	if (!netif_is_multiqueue(dev))
+		return -EOPNOTSUPP;
+
+	if (nla_len(opt) < sizeof(*qopt))
+		return -EINVAL;
+
+	qopt = nla_data(opt);
+	if (mqprio_parse_opt(dev, qopt))
+		return -EINVAL;
+
+	/* pre-allocate qdisc, attachment can't fail */
+	priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]),
+			       GFP_KERNEL);
+	if (priv->qdiscs == NULL) {
+		err = -ENOMEM;
+		goto err;
+	}
+
+	for (i = 0; i < dev->num_tx_queues; i++) {
+		dev_queue = netdev_get_tx_queue(dev, i);
+		qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops,
+					  TC_H_MAKE(TC_H_MAJ(sch->handle),
+						    TC_H_MIN(i + 1)));
+		if (qdisc == NULL) {
+			err = -ENOMEM;
+			goto err;
+		}
+		priv->qdiscs[i] = qdisc;
+	}
+
+	/* If the mqprio options indicate that hardware should own
+	 * the queue mapping then run ndo_setup_tc otherwise use the
+	 * supplied and verified mapping
+	 */
+	if (qopt->hw) {
+		priv->hw_owned = 1;
+		err = dev->netdev_ops->ndo_setup_tc(dev, qopt->num_tc);
+		if (err)
+			goto err;
+	} else {
+		netdev_set_num_tc(dev, qopt->num_tc);
+		for (i = 0; i < qopt->num_tc; i++)
+			netdev_set_tc_queue(dev, i,
+					    qopt->count[i], qopt->offset[i]);
+	}
+
+	/* Always use supplied priority mappings */
+	for (i = 0; i < TC_BITMASK + 1; i++)
+		netdev_set_prio_tc_map(dev, i, qopt->prio_tc_map[i]);
+
+	sch->flags |= TCQ_F_MQROOT;
+	return 0;
+
+err:
+	mqprio_destroy(sch);
+	return err;
+}
+
+static void mqprio_attach(struct Qdisc *sch)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	struct mqprio_sched *priv = qdisc_priv(sch);
+	struct Qdisc *qdisc;
+	unsigned int ntx;
+
+	/* Attach underlying qdisc */
+	for (ntx = 0; ntx < dev->num_tx_queues; ntx++) {
+		qdisc = priv->qdiscs[ntx];
+		qdisc = dev_graft_qdisc(qdisc->dev_queue, qdisc);
+		if (qdisc)
+			qdisc_destroy(qdisc);
+	}
+	kfree(priv->qdiscs);
+	priv->qdiscs = NULL;
+}
+
+static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch,
+					     unsigned long cl)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	unsigned long ntx = cl - 1 - netdev_get_num_tc(dev);
+
+	if (ntx >= dev->num_tx_queues)
+		return NULL;
+	return netdev_get_tx_queue(dev, ntx);
+}
+
+static int mqprio_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,
+		    struct Qdisc **old)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl);
+
+	if (!dev_queue)
+		return -EINVAL;
+
+	if (dev->flags & IFF_UP)
+		dev_deactivate(dev);
+
+	*old = dev_graft_qdisc(dev_queue, new);
+
+	if (dev->flags & IFF_UP)
+		dev_activate(dev);
+
+	return 0;
+}
+
+static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	struct mqprio_sched *priv = qdisc_priv(sch);
+	unsigned char *b = skb_tail_pointer(skb);
+	struct tc_mqprio_qopt opt = { 0 };
+	struct Qdisc *qdisc;
+	unsigned int i;
+
+	sch->q.qlen = 0;
+	memset(&sch->bstats, 0, sizeof(sch->bstats));
+	memset(&sch->qstats, 0, sizeof(sch->qstats));
+
+	for (i = 0; i < dev->num_tx_queues; i++) {
+		qdisc = netdev_get_tx_queue(dev, i)->qdisc;
+		spin_lock_bh(qdisc_lock(qdisc));
+		sch->q.qlen		+= qdisc->q.qlen;
+		sch->bstats.bytes	+= qdisc->bstats.bytes;
+		sch->bstats.packets	+= qdisc->bstats.packets;
+		sch->qstats.qlen	+= qdisc->qstats.qlen;
+		sch->qstats.backlog	+= qdisc->qstats.backlog;
+		sch->qstats.drops	+= qdisc->qstats.drops;
+		sch->qstats.requeues	+= qdisc->qstats.requeues;
+		sch->qstats.overlimits	+= qdisc->qstats.overlimits;
+		spin_unlock_bh(qdisc_lock(qdisc));
+	}
+
+	opt.num_tc = netdev_get_num_tc(dev);
+	memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));
+	opt.hw = priv->hw_owned;
+
+	for (i = 0; i < netdev_get_num_tc(dev); i++) {
+		opt.count[i] = dev->tc_to_txq[i].count;
+		opt.offset[i] = dev->tc_to_txq[i].offset;
+	}
+
+	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
+
+	return skb->len;
+nla_put_failure:
+	nlmsg_trim(skb, b);
+	return -1;
+}
+
+static struct Qdisc *mqprio_leaf(struct Qdisc *sch, unsigned long cl)
+{
+	struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl);
+
+	if (!dev_queue)
+		return NULL;
+
+	return dev_queue->qdisc_sleeping;
+}
+
+static unsigned long mqprio_get(struct Qdisc *sch, u32 classid)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	unsigned int ntx = TC_H_MIN(classid);
+
+	if (ntx > dev->num_tx_queues + netdev_get_num_tc(dev))
+		return 0;
+	return ntx;
+}
+
+static void mqprio_put(struct Qdisc *sch, unsigned long cl)
+{
+}
+
+static int mqprio_dump_class(struct Qdisc *sch, unsigned long cl,
+			 struct sk_buff *skb, struct tcmsg *tcm)
+{
+	struct net_device *dev = qdisc_dev(sch);
+
+	if (cl <= netdev_get_num_tc(dev)) {
+		tcm->tcm_parent = TC_H_ROOT;
+		tcm->tcm_info = 0;
+	} else {
+		int i;
+		struct netdev_queue *dev_queue;
+
+		dev_queue = mqprio_queue_get(sch, cl);
+		tcm->tcm_parent = 0;
+		for (i = 0; i < netdev_get_num_tc(dev); i++) {
+			struct netdev_tc_txq tc = dev->tc_to_txq[i];
+			int q_idx = cl - netdev_get_num_tc(dev);
+
+			if (q_idx > tc.offset &&
+			    q_idx <= tc.offset + tc.count) {
+				tcm->tcm_parent =
+					TC_H_MAKE(TC_H_MAJ(sch->handle),
+						  TC_H_MIN(i + 1));
+				break;
+			}
+		}
+		tcm->tcm_info = dev_queue->qdisc_sleeping->handle;
+	}
+	tcm->tcm_handle |= TC_H_MIN(cl);
+	return 0;
+}
+
+static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
+				   struct gnet_dump *d)
+	__releases(d->lock)
+	__acquires(d->lock)
+{
+	struct net_device *dev = qdisc_dev(sch);
+
+	if (cl <= netdev_get_num_tc(dev)) {
+		int i;
+		struct Qdisc *qdisc;
+		struct gnet_stats_queue qstats = {0};
+		struct gnet_stats_basic_packed bstats = {0};
+		struct netdev_tc_txq tc = dev->tc_to_txq[cl - 1];
+
+		/* Drop lock here it will be reclaimed before touching
+		 * statistics this is required because the d->lock we
+		 * hold here is the look on dev_queue->qdisc_sleeping
+		 * also acquired below.
+		 */
+		spin_unlock_bh(d->lock);
+
+		for (i = tc.offset; i < tc.offset + tc.count; i++) {
+			qdisc = netdev_get_tx_queue(dev, i)->qdisc;
+			spin_lock_bh(qdisc_lock(qdisc));
+			bstats.bytes      += qdisc->bstats.bytes;
+			bstats.packets    += qdisc->bstats.packets;
+			qstats.qlen       += qdisc->qstats.qlen;
+			qstats.backlog    += qdisc->qstats.backlog;
+			qstats.drops      += qdisc->qstats.drops;
+			qstats.requeues   += qdisc->qstats.requeues;
+			qstats.overlimits += qdisc->qstats.overlimits;
+			spin_unlock_bh(qdisc_lock(qdisc));
+		}
+		/* Reclaim root sleeping lock before completing stats */
+		spin_lock_bh(d->lock);
+		if (gnet_stats_copy_basic(d, &bstats) < 0 ||
+		    gnet_stats_copy_queue(d, &qstats) < 0)
+			return -1;
+	} else {
+		struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl);
+
+		sch = dev_queue->qdisc_sleeping;
+		sch->qstats.qlen = sch->q.qlen;
+		if (gnet_stats_copy_basic(d, &sch->bstats) < 0 ||
+		    gnet_stats_copy_queue(d, &sch->qstats) < 0)
+			return -1;
+	}
+	return 0;
+}
+
+static void mqprio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
+{
+	struct net_device *dev = qdisc_dev(sch);
+	unsigned long ntx;
+
+	if (arg->stop)
+		return;
+
+	/* Walk hierarchy with a virtual class per tc */
+	arg->count = arg->skip;
+	for (ntx = arg->skip;
+	     ntx < dev->num_tx_queues + netdev_get_num_tc(dev);
+	     ntx++) {
+		if (arg->fn(sch, ntx + 1, arg) < 0) {
+			arg->stop = 1;
+			break;
+		}
+		arg->count++;
+	}
+}
+
+static const struct Qdisc_class_ops mqprio_class_ops = {
+	.graft		= mqprio_graft,
+	.leaf		= mqprio_leaf,
+	.get		= mqprio_get,
+	.put		= mqprio_put,
+	.walk		= mqprio_walk,
+	.dump		= mqprio_dump_class,
+	.dump_stats	= mqprio_dump_class_stats,
+};
+
+static struct Qdisc_ops mqprio_qdisc_ops __read_mostly = {
+	.cl_ops		= &mqprio_class_ops,
+	.id		= "mqprio",
+	.priv_size	= sizeof(struct mqprio_sched),
+	.init		= mqprio_init,
+	.destroy	= mqprio_destroy,
+	.attach		= mqprio_attach,
+	.dump		= mqprio_dump,
+	.owner		= THIS_MODULE,
+};
+
+static int __init mqprio_module_init(void)
+{
+	return register_qdisc(&mqprio_qdisc_ops);
+}
+
+static void __exit mqprio_module_exit(void)
+{
+	unregister_qdisc(&mqprio_qdisc_ops);
+}
+
+module_init(mqprio_module_init);
+module_exit(mqprio_module_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 436a2e7..edc1950 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -156,7 +156,7 @@ static unsigned int multiq_drop(struct Qdisc *sch)
 	unsigned int len;
 	struct Qdisc *qdisc;
 
-	for (band = q->bands-1; band >= 0; band--) {
+	for (band = q->bands - 1; band >= 0; band--) {
 		qdisc = q->queues[band];
 		if (qdisc->ops->drop) {
 			len = qdisc->ops->drop(qdisc);
@@ -265,7 +265,7 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
 	for (i = 0; i < q->max_bands; i++)
 		q->queues[i] = &noop_qdisc;
 
-	err = multiq_tune(sch,opt);
+	err = multiq_tune(sch, opt);
 
 	if (err)
 		kfree(q->queues);
@@ -346,7 +346,7 @@ static int multiq_dump_class(struct Qdisc *sch, unsigned long cl,
 	struct multiq_sched_data *q = qdisc_priv(sch);
 
 	tcm->tcm_handle |= TC_H_MIN(cl);
-	tcm->tcm_info = q->queues[cl-1]->handle;
+	tcm->tcm_info = q->queues[cl - 1]->handle;
 	return 0;
 }
 
@@ -378,7 +378,7 @@ static void multiq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 			arg->count++;
 			continue;
 		}
-		if (arg->fn(sch, band+1, arg) < 0) {
+		if (arg->fn(sch, band + 1, arg) < 0) {
 			arg->stop = 1;
 			break;
 		}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 6a3006b..edbbf7a 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -19,12 +19,13 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/skbuff.h>
+#include <linux/vmalloc.h>
 #include <linux/rtnetlink.h>
 
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
 
-#define VERSION "1.2"
+#define VERSION "1.3"
 
 /*	Network Emulation Queuing algorithm.
 	====================================
@@ -47,6 +48,20 @@
 	 layering other disciplines.  It does not need to do bandwidth
 	 control either since that can be handled by using token
 	 bucket or other rate control.
+
+     Correlated Loss Generator models
+
+	Added generation of correlated loss according to the
+	"Gilbert-Elliot" model, a 4-state markov model.
+
+	References:
+	[1] NetemCLG Home http://netgroup.uniroma2.it/NetemCLG
+	[2] S. Salsano, F. Ludovici, A. Ordine, "Definition of a general
+	and intuitive loss model for packet networks and its implementation
+	in the Netem module in the Linux kernel", available in [1]
+
+	Authors: Stefano Salsano <stefano.salsano at uniroma2.it
+		 Fabio Ludovici <fabio.ludovici at yahoo.it>
 */
 
 struct netem_sched_data {
@@ -73,6 +88,26 @@ struct netem_sched_data {
 		u32  size;
 		s16 table[0];
 	} *delay_dist;
+
+	enum  {
+		CLG_RANDOM,
+		CLG_4_STATES,
+		CLG_GILB_ELL,
+	} loss_model;
+
+	/* Correlated Loss Generation models */
+	struct clgstate {
+		/* state of the Markov chain */
+		u8 state;
+
+		/* 4-states and Gilbert-Elliot models */
+		u32 a1;	/* p13 for 4-states or p for GE */
+		u32 a2;	/* p31 for 4-states or r for GE */
+		u32 a3;	/* p32 for 4-states or h for GE */
+		u32 a4;	/* p14 for 4-states or 1-k for GE */
+		u32 a5; /* p23 used only in 4-states */
+	} clg;
+
 };
 
 /* Time stamp put into socket buffer control block */
@@ -115,6 +150,122 @@ static u32 get_crandom(struct crndstate *state)
 	return answer;
 }
 
+/* loss_4state - 4-state model loss generator
+ * Generates losses according to the 4-state Markov chain adopted in
+ * the GI (General and Intuitive) loss model.
+ */
+static bool loss_4state(struct netem_sched_data *q)
+{
+	struct clgstate *clg = &q->clg;
+	u32 rnd = net_random();
+
+	/*
+	 * Makes a comparision between rnd and the transition
+	 * probabilities outgoing from the current state, then decides the
+	 * next state and if the next packet has to be transmitted or lost.
+	 * The four states correspond to:
+	 *   1 => successfully transmitted packets within a gap period
+	 *   4 => isolated losses within a gap period
+	 *   3 => lost packets within a burst period
+	 *   2 => successfully transmitted packets within a burst period
+	 */
+	switch (clg->state) {
+	case 1:
+		if (rnd < clg->a4) {
+			clg->state = 4;
+			return true;
+		} else if (clg->a4 < rnd && rnd < clg->a1) {
+			clg->state = 3;
+			return true;
+		} else if (clg->a1 < rnd)
+			clg->state = 1;
+
+		break;
+	case 2:
+		if (rnd < clg->a5) {
+			clg->state = 3;
+			return true;
+		} else
+			clg->state = 2;
+
+		break;
+	case 3:
+		if (rnd < clg->a3)
+			clg->state = 2;
+		else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
+			clg->state = 1;
+			return true;
+		} else if (clg->a2 + clg->a3 < rnd) {
+			clg->state = 3;
+			return true;
+		}
+		break;
+	case 4:
+		clg->state = 1;
+		break;
+	}
+
+	return false;
+}
+
+/* loss_gilb_ell - Gilbert-Elliot model loss generator
+ * Generates losses according to the Gilbert-Elliot loss model or
+ * its special cases  (Gilbert or Simple Gilbert)
+ *
+ * Makes a comparision between random number and the transition
+ * probabilities outgoing from the current state, then decides the
+ * next state. A second random number is extracted and the comparision
+ * with the loss probability of the current state decides if the next
+ * packet will be transmitted or lost.
+ */
+static bool loss_gilb_ell(struct netem_sched_data *q)
+{
+	struct clgstate *clg = &q->clg;
+
+	switch (clg->state) {
+	case 1:
+		if (net_random() < clg->a1)
+			clg->state = 2;
+		if (net_random() < clg->a4)
+			return true;
+	case 2:
+		if (net_random() < clg->a2)
+			clg->state = 1;
+		if (clg->a3 > net_random())
+			return true;
+	}
+
+	return false;
+}
+
+static bool loss_event(struct netem_sched_data *q)
+{
+	switch (q->loss_model) {
+	case CLG_RANDOM:
+		/* Random packet drop 0 => none, ~0 => all */
+		return q->loss && q->loss >= get_crandom(&q->loss_cor);
+
+	case CLG_4_STATES:
+		/* 4state loss model algorithm (used also for GI model)
+		* Extracts a value from the markov 4 state loss generator,
+		* if it is 1 drops a packet and if needed writes the event in
+		* the kernel logs
+		*/
+		return loss_4state(q);
+
+	case CLG_GILB_ELL:
+		/* Gilbert-Elliot loss model algorithm
+		* Extracts a value from the Gilbert-Elliot loss generator,
+		* if it is 1 drops a packet and if needed writes the event in
+		* the kernel logs
+		*/
+		return loss_gilb_ell(q);
+	}
+
+	return false;	/* not reached */
+}
+
+
 /* tabledist - return a pseudo-randomly distributed value with mean mu and
  * std deviation sigma.  Uses table lookup to approximate the desired
  * distribution, and a uniformly-distributed pseudo-random source.
@@ -161,14 +312,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 	int ret;
 	int count = 1;
 
-	pr_debug("netem_enqueue skb=%p\n", skb);
-
 	/* Random duplication */
 	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
 		++count;
 
-	/* Random packet drop 0 => none, ~0 => all */
-	if (q->loss && q->loss >= get_crandom(&q->loss_cor))
+	/* Drop packet? */
+	if (loss_event(q))
 		--count;
 
 	if (count == 0) {
@@ -211,8 +360,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 	}
 
 	cb = netem_skb_cb(skb);
-	if (q->gap == 0 || 		/* not doing reordering */
-	    q->counter < q->gap || 	/* inside last reordering gap */
+	if (q->gap == 0 ||		/* not doing reordering */
+	    q->counter < q->gap ||	/* inside last reordering gap */
 	    q->reorder < get_crandom(&q->reorder_cor)) {
 		psched_time_t now;
 		psched_tdiff_t delay;
@@ -238,17 +387,18 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 		ret = NET_XMIT_SUCCESS;
 	}
 
-	if (likely(ret == NET_XMIT_SUCCESS)) {
-		sch->q.qlen++;
-	} else if (net_xmit_drop_count(ret)) {
-		sch->qstats.drops++;
+	if (ret != NET_XMIT_SUCCESS) {
+		if (net_xmit_drop_count(ret)) {
+			sch->qstats.drops++;
+			return ret;
+		}
 	}
 
-	pr_debug("netem: enqueue ret %d\n", ret);
-	return ret;
+	sch->q.qlen++;
+	return NET_XMIT_SUCCESS;
 }
 
-static unsigned int netem_drop(struct Qdisc* sch)
+static unsigned int netem_drop(struct Qdisc *sch)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
 	unsigned int len = 0;
@@ -265,7 +415,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
 	struct netem_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
 
-	if (sch->flags & TCQ_F_THROTTLED)
+	if (qdisc_is_throttled(sch))
 		return NULL;
 
 	skb = q->qdisc->ops->peek(q->qdisc);
@@ -287,9 +437,10 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
 			if (G_TC_FROM(skb->tc_verd) & AT_INGRESS)
 				skb->tstamp.tv64 = 0;
 #endif
-			pr_debug("netem_dequeue: return skb=%p\n", skb);
-			qdisc_bstats_update(sch, skb);
+
 			sch->q.qlen--;
+			qdisc_unthrottled(sch);
+			qdisc_bstats_update(sch, skb);
 			return skb;
 		}
 
@@ -308,6 +459,16 @@ static void netem_reset(struct Qdisc *sch)
 	qdisc_watchdog_cancel(&q->watchdog);
 }
 
+static void dist_free(struct disttable *d)
+{
+	if (d) {
+		if (is_vmalloc_addr(d))
+			vfree(d);
+		else
+			kfree(d);
+	}
+}
+
 /*
  * Distribution data is a variable size payload containing
  * signed 16 bit values.
@@ -315,16 +476,20 @@ static void netem_reset(struct Qdisc *sch)
 static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
 {
 	struct netem_sched_data *q = qdisc_priv(sch);
-	unsigned long n = nla_len(attr)/sizeof(__s16);
+	size_t n = nla_len(attr)/sizeof(__s16);
 	const __s16 *data = nla_data(attr);
 	spinlock_t *root_lock;
 	struct disttable *d;
 	int i;
+	size_t s;
 
-	if (n > 65536)
+	if (n > NETEM_DIST_MAX)
 		return -EINVAL;
 
-	d = kmalloc(sizeof(*d) + n*sizeof(d->table[0]), GFP_KERNEL);
+	s = sizeof(struct disttable) + n * sizeof(s16);
+	d = kmalloc(s, GFP_KERNEL);
+	if (!d)
+		d = vmalloc(s);
 	if (!d)
 		return -ENOMEM;
 
@@ -335,7 +500,7 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
 	root_lock = qdisc_root_sleeping_lock(sch);
 
 	spin_lock_bh(root_lock);
-	kfree(q->delay_dist);
+	dist_free(q->delay_dist);
 	q->delay_dist = d;
 	spin_unlock_bh(root_lock);
 	return 0;
@@ -369,10 +534,66 @@ static void get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
 	init_crandom(&q->corrupt_cor, r->correlation);
 }
 
+static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	const struct nlattr *la;
+	int rem;
+
+	nla_for_each_nested(la, attr, rem) {
+		u16 type = nla_type(la);
+
+		switch(type) {
+		case NETEM_LOSS_GI: {
+			const struct tc_netem_gimodel *gi = nla_data(la);
+
+			if (nla_len(la) != sizeof(struct tc_netem_gimodel)) {
+				pr_info("netem: incorrect gi model size\n");
+				return -EINVAL;
+			}
+
+			q->loss_model = CLG_4_STATES;
+
+			q->clg.state = 1;
+			q->clg.a1 = gi->p13;
+			q->clg.a2 = gi->p31;
+			q->clg.a3 = gi->p32;
+			q->clg.a4 = gi->p14;
+			q->clg.a5 = gi->p23;
+			break;
+		}
+
+		case NETEM_LOSS_GE: {
+			const struct tc_netem_gemodel *ge = nla_data(la);
+
+			if (nla_len(la) != sizeof(struct tc_netem_gemodel)) {
+				pr_info("netem: incorrect gi model size\n");
+				return -EINVAL;
+			}
+
+			q->loss_model = CLG_GILB_ELL;
+			q->clg.state = 1;
+			q->clg.a1 = ge->p;
+			q->clg.a2 = ge->r;
+			q->clg.a3 = ge->h;
+			q->clg.a4 = ge->k1;
+			break;
+		}
+
+		default:
+			pr_info("netem: unknown loss type %u\n", type);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
 	[TCA_NETEM_CORR]	= { .len = sizeof(struct tc_netem_corr) },
 	[TCA_NETEM_REORDER]	= { .len = sizeof(struct tc_netem_reorder) },
 	[TCA_NETEM_CORRUPT]	= { .len = sizeof(struct tc_netem_corrupt) },
+	[TCA_NETEM_LOSS]	= { .type = NLA_NESTED },
 };
 
 static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
@@ -380,11 +601,15 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
 {
 	int nested_len = nla_len(nla) - NLA_ALIGN(len);
 
-	if (nested_len < 0)
+	if (nested_len < 0) {
+		pr_info("netem: invalid attributes len %d\n", nested_len);
 		return -EINVAL;
+	}
+
 	if (nested_len >= nla_attr_size(0))
 		return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),
 				 nested_len, policy);
+
 	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
 	return 0;
 }
@@ -407,7 +632,7 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
 
 	ret = fifo_set_limit(q->qdisc, qopt->limit);
 	if (ret) {
-		pr_debug("netem: can't set fifo limit\n");
+		pr_info("netem: can't set fifo limit\n");
 		return ret;
 	}
 
@@ -440,7 +665,11 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt)
 	if (tb[TCA_NETEM_CORRUPT])
 		get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
 
-	return 0;
+	q->loss_model = CLG_RANDOM;
+	if (tb[TCA_NETEM_LOSS])
+		ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
+
+	return ret;
 }
 
 /*
@@ -535,16 +764,17 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt)
 
 	qdisc_watchdog_init(&q->watchdog, sch);
 
+	q->loss_model = CLG_RANDOM;
 	q->qdisc = qdisc_create_dflt(sch->dev_queue, &tfifo_qdisc_ops,
 				     TC_H_MAKE(sch->handle, 1));
 	if (!q->qdisc) {
-		pr_debug("netem: qdisc create failed\n");
+		pr_notice("netem: qdisc create tfifo qdisc failed\n");
 		return -ENOMEM;
 	}
 
 	ret = netem_change(sch, opt);
 	if (ret) {
-		pr_debug("netem: change failed\n");
+		pr_info("netem: change failed\n");
 		qdisc_destroy(q->qdisc);
 	}
 	return ret;
@@ -556,14 +786,61 @@ static void netem_destroy(struct Qdisc *sch)
 
 	qdisc_watchdog_cancel(&q->watchdog);
 	qdisc_destroy(q->qdisc);
-	kfree(q->delay_dist);
+	dist_free(q->delay_dist);
+}
+
+static int dump_loss_model(const struct netem_sched_data *q,
+			   struct sk_buff *skb)
+{
+	struct nlattr *nest;
+
+	nest = nla_nest_start(skb, TCA_NETEM_LOSS);
+	if (nest == NULL)
+		goto nla_put_failure;
+
+	switch (q->loss_model) {
+	case CLG_RANDOM:
+		/* legacy loss model */
+		nla_nest_cancel(skb, nest);
+		return 0;	/* no data */
+
+	case CLG_4_STATES: {
+		struct tc_netem_gimodel gi = {
+			.p13 = q->clg.a1,
+			.p31 = q->clg.a2,
+			.p32 = q->clg.a3,
+			.p14 = q->clg.a4,
+			.p23 = q->clg.a5,
+		};
+
+		NLA_PUT(skb, NETEM_LOSS_GI, sizeof(gi), &gi);
+		break;
+	}
+	case CLG_GILB_ELL: {
+		struct tc_netem_gemodel ge = {
+			.p = q->clg.a1,
+			.r = q->clg.a2,
+			.h = q->clg.a3,
+			.k1 = q->clg.a4,
+		};
+
+		NLA_PUT(skb, NETEM_LOSS_GE, sizeof(ge), &ge);
+		break;
+	}
+	}
+
+	nla_nest_end(skb, nest);
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(skb, nest);
+	return -1;
 }
 
 static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	const struct netem_sched_data *q = qdisc_priv(sch);
-	unsigned char *b = skb_tail_pointer(skb);
-	struct nlattr *nla = (struct nlattr *) b;
+	struct nlattr *nla = (struct nlattr *) skb_tail_pointer(skb);
 	struct tc_netem_qopt qopt;
 	struct tc_netem_corr cor;
 	struct tc_netem_reorder reorder;
@@ -590,17 +867,87 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
 	corrupt.correlation = q->corrupt_cor.rho;
 	NLA_PUT(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt);
 
-	nla->nla_len = skb_tail_pointer(skb) - b;
+	if (dump_loss_model(q, skb) != 0)
+		goto nla_put_failure;
 
-	return skb->len;
+	return nla_nest_end(skb, nla);
 
 nla_put_failure:
-	nlmsg_trim(skb, b);
+	nlmsg_trim(skb, nla);
 	return -1;
 }
 
+static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
+			  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+
+	if (cl != 1) 	/* only one class */
+		return -ENOENT;
+
+	tcm->tcm_handle |= TC_H_MIN(1);
+	tcm->tcm_info = q->qdisc->handle;
+
+	return 0;
+}
+
+static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+		     struct Qdisc **old)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+
+	if (new == NULL)
+		new = &noop_qdisc;
+
+	sch_tree_lock(sch);
+	*old = q->qdisc;
+	q->qdisc = new;
+	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+	qdisc_reset(*old);
+	sch_tree_unlock(sch);
+
+	return 0;
+}
+
+static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	struct netem_sched_data *q = qdisc_priv(sch);
+	return q->qdisc;
+}
+
+static unsigned long netem_get(struct Qdisc *sch, u32 classid)
+{
+	return 1;
+}
+
+static void netem_put(struct Qdisc *sch, unsigned long arg)
+{
+}
+
+static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+{
+	if (!walker->stop) {
+		if (walker->count >= walker->skip)
+			if (walker->fn(sch, 1, walker) < 0) {
+				walker->stop = 1;
+				return;
+			}
+		walker->count++;
+	}
+}
+
+static const struct Qdisc_class_ops netem_class_ops = {
+	.graft		=	netem_graft,
+	.leaf		=	netem_leaf,
+	.get		=	netem_get,
+	.put		=	netem_put,
+	.walk		=	netem_walk,
+	.dump		=	netem_dump_class,
+};
+
 static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
 	.id		=	"netem",
+	.cl_ops		=	&netem_class_ops,
 	.priv_size	=	sizeof(struct netem_sched_data),
 	.enqueue	=	netem_enqueue,
 	.dequeue	=	netem_dequeue,
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c
index fbd710d..2a318f2 100644
--- a/net/sched/sch_prio.c
+++ b/net/sched/sch_prio.c
@@ -22,8 +22,7 @@
 #include <net/pkt_sched.h>
 
 
-struct prio_sched_data
-{
+struct prio_sched_data {
 	int bands;
 	struct tcf_proto *filter_list;
 	u8  prio2band[TC_PRIO_MAX+1];
@@ -54,7 +53,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 		if (!q->filter_list || err < 0) {
 			if (TC_H_MAJ(band))
 				band = 0;
-			return q->queues[q->prio2band[band&TC_PRIO_MAX]];
+			return q->queues[q->prio2band[band & TC_PRIO_MAX]];
 		}
 		band = res.classid;
 	}
@@ -106,7 +105,7 @@ static struct sk_buff *prio_peek(struct Qdisc *sch)
 	return NULL;
 }
 
-static struct sk_buff *prio_dequeue(struct Qdisc* sch)
+static struct sk_buff *prio_dequeue(struct Qdisc *sch)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
 	int prio;
@@ -124,7 +123,7 @@ static struct sk_buff *prio_dequeue(struct Qdisc* sch)
 
 }
 
-static unsigned int prio_drop(struct Qdisc* sch)
+static unsigned int prio_drop(struct Qdisc *sch)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
 	int prio;
@@ -143,24 +142,24 @@ static unsigned int prio_drop(struct Qdisc* sch)
 
 
 static void
-prio_reset(struct Qdisc* sch)
+prio_reset(struct Qdisc *sch)
 {
 	int prio;
 	struct prio_sched_data *q = qdisc_priv(sch);
 
-	for (prio=0; prio<q->bands; prio++)
+	for (prio = 0; prio < q->bands; prio++)
 		qdisc_reset(q->queues[prio]);
 	sch->q.qlen = 0;
 }
 
 static void
-prio_destroy(struct Qdisc* sch)
+prio_destroy(struct Qdisc *sch)
 {
 	int prio;
 	struct prio_sched_data *q = qdisc_priv(sch);
 
 	tcf_destroy_chain(&q->filter_list);
-	for (prio=0; prio<q->bands; prio++)
+	for (prio = 0; prio < q->bands; prio++)
 		qdisc_destroy(q->queues[prio]);
 }
 
@@ -177,7 +176,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
 	if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2)
 		return -EINVAL;
 
-	for (i=0; i<=TC_PRIO_MAX; i++) {
+	for (i = 0; i <= TC_PRIO_MAX; i++) {
 		if (qopt->priomap[i] >= qopt->bands)
 			return -EINVAL;
 	}
@@ -186,7 +185,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
 	q->bands = qopt->bands;
 	memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
 
-	for (i=q->bands; i<TCQ_PRIO_BANDS; i++) {
+	for (i = q->bands; i < TCQ_PRIO_BANDS; i++) {
 		struct Qdisc *child = q->queues[i];
 		q->queues[i] = &noop_qdisc;
 		if (child != &noop_qdisc) {
@@ -196,9 +195,10 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt)
 	}
 	sch_tree_unlock(sch);
 
-	for (i=0; i<q->bands; i++) {
+	for (i = 0; i < q->bands; i++) {
 		if (q->queues[i] == &noop_qdisc) {
 			struct Qdisc *child, *old;
+
 			child = qdisc_create_dflt(sch->dev_queue,
 						  &pfifo_qdisc_ops,
 						  TC_H_MAKE(sch->handle, i + 1));
@@ -224,7 +224,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt)
 	struct prio_sched_data *q = qdisc_priv(sch);
 	int i;
 
-	for (i=0; i<TCQ_PRIO_BANDS; i++)
+	for (i = 0; i < TCQ_PRIO_BANDS; i++)
 		q->queues[i] = &noop_qdisc;
 
 	if (opt == NULL) {
@@ -232,7 +232,7 @@ static int prio_init(struct Qdisc *sch, struct nlattr *opt)
 	} else {
 		int err;
 
-		if ((err= prio_tune(sch, opt)) != 0)
+		if ((err = prio_tune(sch, opt)) != 0)
 			return err;
 	}
 	return 0;
@@ -245,7 +245,7 @@ static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
 	struct tc_prio_qopt opt;
 
 	opt.bands = q->bands;
-	memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX+1);
+	memcpy(&opt.priomap, q->prio2band, TC_PRIO_MAX + 1);
 
 	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 
@@ -342,7 +342,7 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 			arg->count++;
 			continue;
 		}
-		if (arg->fn(sch, prio+1, arg) < 0) {
+		if (arg->fn(sch, prio + 1, arg) < 0) {
 			arg->stop = 1;
 			break;
 		}
@@ -350,7 +350,7 @@ static void prio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 	}
 }
 
-static struct tcf_proto ** prio_find_tcf(struct Qdisc *sch, unsigned long cl)
+static struct tcf_proto **prio_find_tcf(struct Qdisc *sch, unsigned long cl)
 {
 	struct prio_sched_data *q = qdisc_priv(sch);
 
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 9f98dbd..6649463 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -36,8 +36,7 @@
 	if RED works correctly.
  */
 
-struct red_sched_data
-{
+struct red_sched_data {
 	u32			limit;		/* HARD maximal queue length */
 	unsigned char		flags;
 	struct red_parms	parms;
@@ -55,7 +54,7 @@ static inline int red_use_harddrop(struct red_sched_data *q)
 	return q->flags & TC_RED_HARDDROP;
 }
 
-static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
 	struct Qdisc *child = q->qdisc;
@@ -67,29 +66,29 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 		red_end_of_idle_period(&q->parms);
 
 	switch (red_action(&q->parms, q->parms.qavg)) {
-		case RED_DONT_MARK:
-			break;
-
-		case RED_PROB_MARK:
-			sch->qstats.overlimits++;
-			if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) {
-				q->stats.prob_drop++;
-				goto congestion_drop;
-			}
-
-			q->stats.prob_mark++;
-			break;
-
-		case RED_HARD_MARK:
-			sch->qstats.overlimits++;
-			if (red_use_harddrop(q) || !red_use_ecn(q) ||
-			    !INET_ECN_set_ce(skb)) {
-				q->stats.forced_drop++;
-				goto congestion_drop;
-			}
-
-			q->stats.forced_mark++;
-			break;
+	case RED_DONT_MARK:
+		break;
+
+	case RED_PROB_MARK:
+		sch->qstats.overlimits++;
+		if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) {
+			q->stats.prob_drop++;
+			goto congestion_drop;
+		}
+
+		q->stats.prob_mark++;
+		break;
+
+	case RED_HARD_MARK:
+		sch->qstats.overlimits++;
+		if (red_use_harddrop(q) || !red_use_ecn(q) ||
+		    !INET_ECN_set_ce(skb)) {
+			q->stats.forced_drop++;
+			goto congestion_drop;
+		}
+
+		q->stats.forced_mark++;
+		break;
 	}
 
 	ret = qdisc_enqueue(skb, child);
@@ -106,7 +105,7 @@ congestion_drop:
 	return NET_XMIT_CN;
 }
 
-static struct sk_buff * red_dequeue(struct Qdisc* sch)
+static struct sk_buff *red_dequeue(struct Qdisc *sch)
 {
 	struct sk_buff *skb;
 	struct red_sched_data *q = qdisc_priv(sch);
@@ -123,7 +122,7 @@ static struct sk_buff * red_dequeue(struct Qdisc* sch)
 	return skb;
 }
 
-static struct sk_buff * red_peek(struct Qdisc* sch)
+static struct sk_buff *red_peek(struct Qdisc *sch)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
 	struct Qdisc *child = q->qdisc;
@@ -131,7 +130,7 @@ static struct sk_buff * red_peek(struct Qdisc* sch)
 	return child->ops->peek(child);
 }
 
-static unsigned int red_drop(struct Qdisc* sch)
+static unsigned int red_drop(struct Qdisc *sch)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
 	struct Qdisc *child = q->qdisc;
@@ -150,7 +149,7 @@ static unsigned int red_drop(struct Qdisc* sch)
 	return 0;
 }
 
-static void red_reset(struct Qdisc* sch)
+static void red_reset(struct Qdisc *sch)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
 
@@ -217,7 +216,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
 	return 0;
 }
 
-static int red_init(struct Qdisc* sch, struct nlattr *opt)
+static int red_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct red_sched_data *q = qdisc_priv(sch);
 
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
new file mode 100644
index 0000000..0a833d0
--- /dev/null
+++ b/net/sched/sch_sfb.c
@@ -0,0 +1,709 @@
+/*
+ * net/sched/sch_sfb.c	  Stochastic Fair Blue
+ *
+ * Copyright (c) 2008-2011 Juliusz Chroboczek <jch@pps.jussieu.fr>
+ * Copyright (c) 2011 Eric Dumazet <eric.dumazet@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * W. Feng, D. Kandlur, D. Saha, K. Shin. Blue:
+ * A New Class of Active Queue Management Algorithms.
+ * U. Michigan CSE-TR-387-99, April 1999.
+ *
+ * http://www.thefengs.com/wuchang/blue/CSE-TR-387-99.pdf
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <linux/jhash.h>
+#include <net/ip.h>
+#include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
+
+/*
+ * SFB uses two B[l][n] : L x N arrays of bins (L levels, N bins per level)
+ * This implementation uses L = 8 and N = 16
+ * This permits us to split one 32bit hash (provided per packet by rxhash or
+ * external classifier) into 8 subhashes of 4 bits.
+ */
+#define SFB_BUCKET_SHIFT 4
+#define SFB_NUMBUCKETS	(1 << SFB_BUCKET_SHIFT) /* N bins per Level */
+#define SFB_BUCKET_MASK (SFB_NUMBUCKETS - 1)
+#define SFB_LEVELS	(32 / SFB_BUCKET_SHIFT) /* L */
+
+/* SFB algo uses a virtual queue, named "bin" */
+struct sfb_bucket {
+	u16		qlen; /* length of virtual queue */
+	u16		p_mark; /* marking probability */
+};
+
+/* We use a double buffering right before hash change
+ * (Section 4.4 of SFB reference : moving hash functions)
+ */
+struct sfb_bins {
+	u32		  perturbation; /* jhash perturbation */
+	struct sfb_bucket bins[SFB_LEVELS][SFB_NUMBUCKETS];
+};
+
+struct sfb_sched_data {
+	struct Qdisc	*qdisc;
+	struct tcf_proto *filter_list;
+	unsigned long	rehash_interval;
+	unsigned long	warmup_time;	/* double buffering warmup time in jiffies */
+	u32		max;
+	u32		bin_size;	/* maximum queue length per bin */
+	u32		increment;	/* d1 */
+	u32		decrement;	/* d2 */
+	u32		limit;		/* HARD maximal queue length */
+	u32		penalty_rate;
+	u32		penalty_burst;
+	u32		tokens_avail;
+	unsigned long	rehash_time;
+	unsigned long	token_time;
+
+	u8		slot;		/* current active bins (0 or 1) */
+	bool		double_buffering;
+	struct sfb_bins bins[2];
+
+	struct {
+		u32	earlydrop;
+		u32	penaltydrop;
+		u32	bucketdrop;
+		u32	queuedrop;
+		u32	childdrop;	/* drops in child qdisc */
+		u32	marked;		/* ECN mark */
+	} stats;
+};
+
+/*
+ * Each queued skb might be hashed on one or two bins
+ * We store in skb_cb the two hash values.
+ * (A zero value means double buffering was not used)
+ */
+struct sfb_skb_cb {
+	u32 hashes[2];
+};
+
+static inline struct sfb_skb_cb *sfb_skb_cb(const struct sk_buff *skb)
+{
+	BUILD_BUG_ON(sizeof(skb->cb) <
+		sizeof(struct qdisc_skb_cb) + sizeof(struct sfb_skb_cb));
+	return (struct sfb_skb_cb *)qdisc_skb_cb(skb)->data;
+}
+
+/*
+ * If using 'internal' SFB flow classifier, hash comes from skb rxhash
+ * If using external classifier, hash comes from the classid.
+ */
+static u32 sfb_hash(const struct sk_buff *skb, u32 slot)
+{
+	return sfb_skb_cb(skb)->hashes[slot];
+}
+
+/* Probabilities are coded as Q0.16 fixed-point values,
+ * with 0xFFFF representing 65535/65536 (almost 1.0)
+ * Addition and subtraction are saturating in [0, 65535]
+ */
+static u32 prob_plus(u32 p1, u32 p2)
+{
+	u32 res = p1 + p2;
+
+	return min_t(u32, res, SFB_MAX_PROB);
+}
+
+static u32 prob_minus(u32 p1, u32 p2)
+{
+	return p1 > p2 ? p1 - p2 : 0;
+}
+
+static void increment_one_qlen(u32 sfbhash, u32 slot, struct sfb_sched_data *q)
+{
+	int i;
+	struct sfb_bucket *b = &q->bins[slot].bins[0][0];
+
+	for (i = 0; i < SFB_LEVELS; i++) {
+		u32 hash = sfbhash & SFB_BUCKET_MASK;
+
+		sfbhash >>= SFB_BUCKET_SHIFT;
+		if (b[hash].qlen < 0xFFFF)
+			b[hash].qlen++;
+		b += SFB_NUMBUCKETS; /* next level */
+	}
+}
+
+static void increment_qlen(const struct sk_buff *skb, struct sfb_sched_data *q)
+{
+	u32 sfbhash;
+
+	sfbhash = sfb_hash(skb, 0);
+	if (sfbhash)
+		increment_one_qlen(sfbhash, 0, q);
+
+	sfbhash = sfb_hash(skb, 1);
+	if (sfbhash)
+		increment_one_qlen(sfbhash, 1, q);
+}
+
+static void decrement_one_qlen(u32 sfbhash, u32 slot,
+			       struct sfb_sched_data *q)
+{
+	int i;
+	struct sfb_bucket *b = &q->bins[slot].bins[0][0];
+
+	for (i = 0; i < SFB_LEVELS; i++) {
+		u32 hash = sfbhash & SFB_BUCKET_MASK;
+
+		sfbhash >>= SFB_BUCKET_SHIFT;
+		if (b[hash].qlen > 0)
+			b[hash].qlen--;
+		b += SFB_NUMBUCKETS; /* next level */
+	}
+}
+
+static void decrement_qlen(const struct sk_buff *skb, struct sfb_sched_data *q)
+{
+	u32 sfbhash;
+
+	sfbhash = sfb_hash(skb, 0);
+	if (sfbhash)
+		decrement_one_qlen(sfbhash, 0, q);
+
+	sfbhash = sfb_hash(skb, 1);
+	if (sfbhash)
+		decrement_one_qlen(sfbhash, 1, q);
+}
+
+static void decrement_prob(struct sfb_bucket *b, struct sfb_sched_data *q)
+{
+	b->p_mark = prob_minus(b->p_mark, q->decrement);
+}
+
+static void increment_prob(struct sfb_bucket *b, struct sfb_sched_data *q)
+{
+	b->p_mark = prob_plus(b->p_mark, q->increment);
+}
+
+static void sfb_zero_all_buckets(struct sfb_sched_data *q)
+{
+	memset(&q->bins, 0, sizeof(q->bins));
+}
+
+/*
+ * compute max qlen, max p_mark, and avg p_mark
+ */
+static u32 sfb_compute_qlen(u32 *prob_r, u32 *avgpm_r, const struct sfb_sched_data *q)
+{
+	int i;
+	u32 qlen = 0, prob = 0, totalpm = 0;
+	const struct sfb_bucket *b = &q->bins[q->slot].bins[0][0];
+
+	for (i = 0; i < SFB_LEVELS * SFB_NUMBUCKETS; i++) {
+		if (qlen < b->qlen)
+			qlen = b->qlen;
+		totalpm += b->p_mark;
+		if (prob < b->p_mark)
+			prob = b->p_mark;
+		b++;
+	}
+	*prob_r = prob;
+	*avgpm_r = totalpm / (SFB_LEVELS * SFB_NUMBUCKETS);
+	return qlen;
+}
+
+
+static void sfb_init_perturbation(u32 slot, struct sfb_sched_data *q)
+{
+	q->bins[slot].perturbation = net_random();
+}
+
+static void sfb_swap_slot(struct sfb_sched_data *q)
+{
+	sfb_init_perturbation(q->slot, q);
+	q->slot ^= 1;
+	q->double_buffering = false;
+}
+
+/* Non elastic flows are allowed to use part of the bandwidth, expressed
+ * in "penalty_rate" packets per second, with "penalty_burst" burst
+ */
+static bool sfb_rate_limit(struct sk_buff *skb, struct sfb_sched_data *q)
+{
+	if (q->penalty_rate == 0 || q->penalty_burst == 0)
+		return true;
+
+	if (q->tokens_avail < 1) {
+		unsigned long age = min(10UL * HZ, jiffies - q->token_time);
+
+		q->tokens_avail = (age * q->penalty_rate) / HZ;
+		if (q->tokens_avail > q->penalty_burst)
+			q->tokens_avail = q->penalty_burst;
+		q->token_time = jiffies;
+		if (q->tokens_avail < 1)
+			return true;
+	}
+
+	q->tokens_avail--;
+	return false;
+}
+
+static bool sfb_classify(struct sk_buff *skb, struct sfb_sched_data *q,
+			 int *qerr, u32 *salt)
+{
+	struct tcf_result res;
+	int result;
+
+	result = tc_classify(skb, q->filter_list, &res);
+	if (result >= 0) {
+#ifdef CONFIG_NET_CLS_ACT
+		switch (result) {
+		case TC_ACT_STOLEN:
+		case TC_ACT_QUEUED:
+			*qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
+		case TC_ACT_SHOT:
+			return false;
+		}
+#endif
+		*salt = TC_H_MIN(res.classid);
+		return true;
+	}
+	return false;
+}
+
+static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+
+	struct sfb_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *child = q->qdisc;
+	int i;
+	u32 p_min = ~0;
+	u32 minqlen = ~0;
+	u32 r, slot, salt, sfbhash;
+	int ret = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
+
+	if (q->rehash_interval > 0) {
+		unsigned long limit = q->rehash_time + q->rehash_interval;
+
+		if (unlikely(time_after(jiffies, limit))) {
+			sfb_swap_slot(q);
+			q->rehash_time = jiffies;
+		} else if (unlikely(!q->double_buffering && q->warmup_time > 0 &&
+				    time_after(jiffies, limit - q->warmup_time))) {
+			q->double_buffering = true;
+		}
+	}
+
+	if (q->filter_list) {
+		/* If using external classifiers, get result and record it. */
+		if (!sfb_classify(skb, q, &ret, &salt))
+			goto other_drop;
+	} else {
+		salt = skb_get_rxhash(skb);
+	}
+
+	slot = q->slot;
+
+	sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
+	if (!sfbhash)
+		sfbhash = 1;
+	sfb_skb_cb(skb)->hashes[slot] = sfbhash;
+
+	for (i = 0; i < SFB_LEVELS; i++) {
+		u32 hash = sfbhash & SFB_BUCKET_MASK;
+		struct sfb_bucket *b = &q->bins[slot].bins[i][hash];
+
+		sfbhash >>= SFB_BUCKET_SHIFT;
+		if (b->qlen == 0)
+			decrement_prob(b, q);
+		else if (b->qlen >= q->bin_size)
+			increment_prob(b, q);
+		if (minqlen > b->qlen)
+			minqlen = b->qlen;
+		if (p_min > b->p_mark)
+			p_min = b->p_mark;
+	}
+
+	slot ^= 1;
+	sfb_skb_cb(skb)->hashes[slot] = 0;
+
+	if (unlikely(minqlen >= q->max || sch->q.qlen >= q->limit)) {
+		sch->qstats.overlimits++;
+		if (minqlen >= q->max)
+			q->stats.bucketdrop++;
+		else
+			q->stats.queuedrop++;
+		goto drop;
+	}
+
+	if (unlikely(p_min >= SFB_MAX_PROB)) {
+		/* Inelastic flow */
+		if (q->double_buffering) {
+			sfbhash = jhash_1word(salt, q->bins[slot].perturbation);
+			if (!sfbhash)
+				sfbhash = 1;
+			sfb_skb_cb(skb)->hashes[slot] = sfbhash;
+
+			for (i = 0; i < SFB_LEVELS; i++) {
+				u32 hash = sfbhash & SFB_BUCKET_MASK;
+				struct sfb_bucket *b = &q->bins[slot].bins[i][hash];
+
+				sfbhash >>= SFB_BUCKET_SHIFT;
+				if (b->qlen == 0)
+					decrement_prob(b, q);
+				else if (b->qlen >= q->bin_size)
+					increment_prob(b, q);
+			}
+		}
+		if (sfb_rate_limit(skb, q)) {
+			sch->qstats.overlimits++;
+			q->stats.penaltydrop++;
+			goto drop;
+		}
+		goto enqueue;
+	}
+
+	r = net_random() & SFB_MAX_PROB;
+
+	if (unlikely(r < p_min)) {
+		if (unlikely(p_min > SFB_MAX_PROB / 2)) {
+			/* If we're marking that many packets, then either
+			 * this flow is unresponsive, or we're badly congested.
+			 * In either case, we want to start dropping packets.
+			 */
+			if (r < (p_min - SFB_MAX_PROB / 2) * 2) {
+				q->stats.earlydrop++;
+				goto drop;
+			}
+		}
+		if (INET_ECN_set_ce(skb)) {
+			q->stats.marked++;
+		} else {
+			q->stats.earlydrop++;
+			goto drop;
+		}
+	}
+
+enqueue:
+	ret = qdisc_enqueue(skb, child);
+	if (likely(ret == NET_XMIT_SUCCESS)) {
+		sch->q.qlen++;
+		increment_qlen(skb, q);
+	} else if (net_xmit_drop_count(ret)) {
+		q->stats.childdrop++;
+		sch->qstats.drops++;
+	}
+	return ret;
+
+drop:
+	qdisc_drop(skb, sch);
+	return NET_XMIT_CN;
+other_drop:
+	if (ret & __NET_XMIT_BYPASS)
+		sch->qstats.drops++;
+	kfree_skb(skb);
+	return ret;
+}
+
+static struct sk_buff *sfb_dequeue(struct Qdisc *sch)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *child = q->qdisc;
+	struct sk_buff *skb;
+
+	skb = child->dequeue(q->qdisc);
+
+	if (skb) {
+		qdisc_bstats_update(sch, skb);
+		sch->q.qlen--;
+		decrement_qlen(skb, q);
+	}
+
+	return skb;
+}
+
+static struct sk_buff *sfb_peek(struct Qdisc *sch)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *child = q->qdisc;
+
+	return child->ops->peek(child);
+}
+
+/* No sfb_drop -- impossible since the child doesn't return the dropped skb. */
+
+static void sfb_reset(struct Qdisc *sch)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+
+	qdisc_reset(q->qdisc);
+	sch->q.qlen = 0;
+	q->slot = 0;
+	q->double_buffering = false;
+	sfb_zero_all_buckets(q);
+	sfb_init_perturbation(0, q);
+}
+
+static void sfb_destroy(struct Qdisc *sch)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+
+	tcf_destroy_chain(&q->filter_list);
+	qdisc_destroy(q->qdisc);
+}
+
+static const struct nla_policy sfb_policy[TCA_SFB_MAX + 1] = {
+	[TCA_SFB_PARMS]	= { .len = sizeof(struct tc_sfb_qopt) },
+};
+
+static const struct tc_sfb_qopt sfb_default_ops = {
+	.rehash_interval = 600 * MSEC_PER_SEC,
+	.warmup_time = 60 * MSEC_PER_SEC,
+	.limit = 0,
+	.max = 25,
+	.bin_size = 20,
+	.increment = (SFB_MAX_PROB + 500) / 1000, /* 0.1 % */
+	.decrement = (SFB_MAX_PROB + 3000) / 6000,
+	.penalty_rate = 10,
+	.penalty_burst = 20,
+};
+
+static int sfb_change(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+	struct Qdisc *child;
+	struct nlattr *tb[TCA_SFB_MAX + 1];
+	const struct tc_sfb_qopt *ctl = &sfb_default_ops;
+	u32 limit;
+	int err;
+
+	if (opt) {
+		err = nla_parse_nested(tb, TCA_SFB_MAX, opt, sfb_policy);
+		if (err < 0)
+			return -EINVAL;
+
+		if (tb[TCA_SFB_PARMS] == NULL)
+			return -EINVAL;
+
+		ctl = nla_data(tb[TCA_SFB_PARMS]);
+	}
+
+	limit = ctl->limit;
+	if (limit == 0)
+		limit = max_t(u32, qdisc_dev(sch)->tx_queue_len, 1);
+
+	child = fifo_create_dflt(sch, &pfifo_qdisc_ops, limit);
+	if (IS_ERR(child))
+		return PTR_ERR(child);
+
+	sch_tree_lock(sch);
+
+	qdisc_tree_decrease_qlen(q->qdisc, q->qdisc->q.qlen);
+	qdisc_destroy(q->qdisc);
+	q->qdisc = child;
+
+	q->rehash_interval = msecs_to_jiffies(ctl->rehash_interval);
+	q->warmup_time = msecs_to_jiffies(ctl->warmup_time);
+	q->rehash_time = jiffies;
+	q->limit = limit;
+	q->increment = ctl->increment;
+	q->decrement = ctl->decrement;
+	q->max = ctl->max;
+	q->bin_size = ctl->bin_size;
+	q->penalty_rate = ctl->penalty_rate;
+	q->penalty_burst = ctl->penalty_burst;
+	q->tokens_avail = ctl->penalty_burst;
+	q->token_time = jiffies;
+
+	q->slot = 0;
+	q->double_buffering = false;
+	sfb_zero_all_buckets(q);
+	sfb_init_perturbation(0, q);
+	sfb_init_perturbation(1, q);
+
+	sch_tree_unlock(sch);
+
+	return 0;
+}
+
+static int sfb_init(struct Qdisc *sch, struct nlattr *opt)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+
+	q->qdisc = &noop_qdisc;
+	return sfb_change(sch, opt);
+}
+
+static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+	struct nlattr *opts;
+	struct tc_sfb_qopt opt = {
+		.rehash_interval = jiffies_to_msecs(q->rehash_interval),
+		.warmup_time = jiffies_to_msecs(q->warmup_time),
+		.limit = q->limit,
+		.max = q->max,
+		.bin_size = q->bin_size,
+		.increment = q->increment,
+		.decrement = q->decrement,
+		.penalty_rate = q->penalty_rate,
+		.penalty_burst = q->penalty_burst,
+	};
+
+	sch->qstats.backlog = q->qdisc->qstats.backlog;
+	opts = nla_nest_start(skb, TCA_OPTIONS);
+	NLA_PUT(skb, TCA_SFB_PARMS, sizeof(opt), &opt);
+	return nla_nest_end(skb, opts);
+
+nla_put_failure:
+	nla_nest_cancel(skb, opts);
+	return -EMSGSIZE;
+}
+
+static int sfb_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+	struct tc_sfb_xstats st = {
+		.earlydrop = q->stats.earlydrop,
+		.penaltydrop = q->stats.penaltydrop,
+		.bucketdrop = q->stats.bucketdrop,
+		.queuedrop = q->stats.queuedrop,
+		.childdrop = q->stats.childdrop,
+		.marked = q->stats.marked,
+	};
+
+	st.maxqlen = sfb_compute_qlen(&st.maxprob, &st.avgprob, q);
+
+	return gnet_stats_copy_app(d, &st, sizeof(st));
+}
+
+static int sfb_dump_class(struct Qdisc *sch, unsigned long cl,
+			  struct sk_buff *skb, struct tcmsg *tcm)
+{
+	return -ENOSYS;
+}
+
+static int sfb_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
+		     struct Qdisc **old)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+
+	if (new == NULL)
+		new = &noop_qdisc;
+
+	sch_tree_lock(sch);
+	*old = q->qdisc;
+	q->qdisc = new;
+	qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
+	qdisc_reset(*old);
+	sch_tree_unlock(sch);
+	return 0;
+}
+
+static struct Qdisc *sfb_leaf(struct Qdisc *sch, unsigned long arg)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+
+	return q->qdisc;
+}
+
+static unsigned long sfb_get(struct Qdisc *sch, u32 classid)
+{
+	return 1;
+}
+
+static void sfb_put(struct Qdisc *sch, unsigned long arg)
+{
+}
+
+static int sfb_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
+			    struct nlattr **tca, unsigned long *arg)
+{
+	return -ENOSYS;
+}
+
+static int sfb_delete(struct Qdisc *sch, unsigned long cl)
+{
+	return -ENOSYS;
+}
+
+static void sfb_walk(struct Qdisc *sch, struct qdisc_walker *walker)
+{
+	if (!walker->stop) {
+		if (walker->count >= walker->skip)
+			if (walker->fn(sch, 1, walker) < 0) {
+				walker->stop = 1;
+				return;
+			}
+		walker->count++;
+	}
+}
+
+static struct tcf_proto **sfb_find_tcf(struct Qdisc *sch, unsigned long cl)
+{
+	struct sfb_sched_data *q = qdisc_priv(sch);
+
+	if (cl)
+		return NULL;
+	return &q->filter_list;
+}
+
+static unsigned long sfb_bind(struct Qdisc *sch, unsigned long parent,
+			      u32 classid)
+{
+	return 0;
+}
+
+
+static const struct Qdisc_class_ops sfb_class_ops = {
+	.graft		=	sfb_graft,
+	.leaf		=	sfb_leaf,
+	.get		=	sfb_get,
+	.put		=	sfb_put,
+	.change		=	sfb_change_class,
+	.delete		=	sfb_delete,
+	.walk		=	sfb_walk,
+	.tcf_chain	=	sfb_find_tcf,
+	.bind_tcf	=	sfb_bind,
+	.unbind_tcf	=	sfb_put,
+	.dump		=	sfb_dump_class,
+};
+
+static struct Qdisc_ops sfb_qdisc_ops __read_mostly = {
+	.id		=	"sfb",
+	.priv_size	=	sizeof(struct sfb_sched_data),
+	.cl_ops		=	&sfb_class_ops,
+	.enqueue	=	sfb_enqueue,
+	.dequeue	=	sfb_dequeue,
+	.peek		=	sfb_peek,
+	.init		=	sfb_init,
+	.reset		=	sfb_reset,
+	.destroy	=	sfb_destroy,
+	.change		=	sfb_change,
+	.dump		=	sfb_dump,
+	.dump_stats	=	sfb_dump_stats,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init sfb_module_init(void)
+{
+	return register_qdisc(&sfb_qdisc_ops);
+}
+
+static void __exit sfb_module_exit(void)
+{
+	unregister_qdisc(&sfb_qdisc_ops);
+}
+
+module_init(sfb_module_init)
+module_exit(sfb_module_exit)
+
+MODULE_DESCRIPTION("Stochastic Fair Blue queue discipline");
+MODULE_AUTHOR("Juliusz Chroboczek");
+MODULE_AUTHOR("Eric Dumazet");
+MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index edea8ce..c2e628d 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -21,6 +21,7 @@
 #include <linux/skbuff.h>
 #include <linux/jhash.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <net/ip.h>
 #include <net/netlink.h>
 #include <net/pkt_sched.h>
@@ -76,7 +77,8 @@
 #define SFQ_DEPTH		128 /* max number of packets per flow */
 #define SFQ_SLOTS		128 /* max number of flows */
 #define SFQ_EMPTY_SLOT		255
-#define SFQ_HASH_DIVISOR	1024
+#define SFQ_DEFAULT_HASH_DIVISOR 1024
+
 /* We use 16 bits to store allot, and want to handle packets up to 64K
  * Scale allot by 8 (1<<3) so that no overflow occurs.
  */
@@ -92,8 +94,7 @@ typedef unsigned char sfq_index;
  * while following values [SFQ_SLOTS ... SFQ_SLOTS + SFQ_DEPTH - 1]
  * are 'pointers' to dep[] array
  */
-struct sfq_head
-{
+struct sfq_head {
 	sfq_index	next;
 	sfq_index	prev;
 };
@@ -108,13 +109,12 @@ struct sfq_slot {
 	short		allot; /* credit for this slot */
 };
 
-struct sfq_sched_data
-{
+struct sfq_sched_data {
 /* Parameters */
 	int		perturb_period;
-	unsigned	quantum;	/* Allotment per round: MUST BE >= MTU */
+	unsigned int	quantum;	/* Allotment per round: MUST BE >= MTU */
 	int		limit;
-
+	unsigned int	divisor;	/* number of slots in hash table */
 /* Variables */
 	struct tcf_proto *filter_list;
 	struct timer_list perturb_timer;
@@ -122,7 +122,7 @@ struct sfq_sched_data
 	sfq_index	cur_depth;	/* depth of longest slot */
 	unsigned short  scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */
 	struct sfq_slot *tail;		/* current slot in round */
-	sfq_index	ht[SFQ_HASH_DIVISOR];	/* Hash table */
+	sfq_index	*ht;		/* Hash table (divisor slots) */
 	struct sfq_slot	slots[SFQ_SLOTS];
 	struct sfq_head	dep[SFQ_DEPTH];	/* Linked list of slots, indexed by depth */
 };
@@ -137,12 +137,12 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index
 	return &q->dep[val - SFQ_SLOTS];
 }
 
-static __inline__ unsigned sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1)
+static unsigned int sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1)
 {
-	return jhash_2words(h, h1, q->perturbation) & (SFQ_HASH_DIVISOR - 1);
+	return jhash_2words(h, h1, q->perturbation) & (q->divisor - 1);
 }
 
-static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
+static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
 {
 	u32 h, h2;
 
@@ -157,13 +157,13 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
 		iph = ip_hdr(skb);
 		h = (__force u32)iph->daddr;
 		h2 = (__force u32)iph->saddr ^ iph->protocol;
-		if (iph->frag_off & htons(IP_MF|IP_OFFSET))
+		if (iph->frag_off & htons(IP_MF | IP_OFFSET))
 			break;
 		poff = proto_ports_offset(iph->protocol);
 		if (poff >= 0 &&
 		    pskb_network_may_pull(skb, iph->ihl * 4 + 4 + poff)) {
 			iph = ip_hdr(skb);
-			h2 ^= *(u32*)((void *)iph + iph->ihl * 4 + poff);
+			h2 ^= *(u32 *)((void *)iph + iph->ihl * 4 + poff);
 		}
 		break;
 	}
@@ -181,7 +181,7 @@ static unsigned sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
 		if (poff >= 0 &&
 		    pskb_network_may_pull(skb, sizeof(*iph) + 4 + poff)) {
 			iph = ipv6_hdr(skb);
-			h2 ^= *(u32*)((void *)iph + sizeof(*iph) + poff);
+			h2 ^= *(u32 *)((void *)iph + sizeof(*iph) + poff);
 		}
 		break;
 	}
@@ -203,7 +203,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
 
 	if (TC_H_MAJ(skb->priority) == sch->handle &&
 	    TC_H_MIN(skb->priority) > 0 &&
-	    TC_H_MIN(skb->priority) <= SFQ_HASH_DIVISOR)
+	    TC_H_MIN(skb->priority) <= q->divisor)
 		return TC_H_MIN(skb->priority);
 
 	if (!q->filter_list)
@@ -221,7 +221,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
 			return 0;
 		}
 #endif
-		if (TC_H_MIN(res.classid) <= SFQ_HASH_DIVISOR)
+		if (TC_H_MIN(res.classid) <= q->divisor)
 			return TC_H_MIN(res.classid);
 	}
 	return 0;
@@ -491,13 +491,18 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
 	if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
 		return -EINVAL;
 
+	if (ctl->divisor &&
+	    (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536))
+		return -EINVAL;
+
 	sch_tree_lock(sch);
 	q->quantum = ctl->quantum ? : psched_mtu(qdisc_dev(sch));
 	q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
 	q->perturb_period = ctl->perturb_period * HZ;
 	if (ctl->limit)
 		q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1);
-
+	if (ctl->divisor)
+		q->divisor = ctl->divisor;
 	qlen = sch->q.qlen;
 	while (sch->q.qlen > q->limit)
 		sfq_drop(sch);
@@ -515,15 +520,13 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
 static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct sfq_sched_data *q = qdisc_priv(sch);
+	size_t sz;
 	int i;
 
 	q->perturb_timer.function = sfq_perturbation;
 	q->perturb_timer.data = (unsigned long)sch;
 	init_timer_deferrable(&q->perturb_timer);
 
-	for (i = 0; i < SFQ_HASH_DIVISOR; i++)
-		q->ht[i] = SFQ_EMPTY_SLOT;
-
 	for (i = 0; i < SFQ_DEPTH; i++) {
 		q->dep[i].next = i + SFQ_SLOTS;
 		q->dep[i].prev = i + SFQ_SLOTS;
@@ -532,6 +535,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
 	q->limit = SFQ_DEPTH - 1;
 	q->cur_depth = 0;
 	q->tail = NULL;
+	q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
 	if (opt == NULL) {
 		q->quantum = psched_mtu(qdisc_dev(sch));
 		q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
@@ -543,10 +547,23 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
 			return err;
 	}
 
+	sz = sizeof(q->ht[0]) * q->divisor;
+	q->ht = kmalloc(sz, GFP_KERNEL);
+	if (!q->ht && sz > PAGE_SIZE)
+		q->ht = vmalloc(sz);
+	if (!q->ht)
+		return -ENOMEM;
+	for (i = 0; i < q->divisor; i++)
+		q->ht[i] = SFQ_EMPTY_SLOT;
+
 	for (i = 0; i < SFQ_SLOTS; i++) {
 		slot_queue_init(&q->slots[i]);
 		sfq_link(q, i);
 	}
+	if (q->limit >= 1)
+		sch->flags |= TCQ_F_CAN_BYPASS;
+	else
+		sch->flags &= ~TCQ_F_CAN_BYPASS;
 	return 0;
 }
 
@@ -557,6 +574,10 @@ static void sfq_destroy(struct Qdisc *sch)
 	tcf_destroy_chain(&q->filter_list);
 	q->perturb_period = 0;
 	del_timer_sync(&q->perturb_timer);
+	if (is_vmalloc_addr(q->ht))
+		vfree(q->ht);
+	else
+		kfree(q->ht);
 }
 
 static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
@@ -569,7 +590,7 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
 	opt.perturb_period = q->perturb_period / HZ;
 
 	opt.limit = q->limit;
-	opt.divisor = SFQ_HASH_DIVISOR;
+	opt.divisor = q->divisor;
 	opt.flows = q->limit;
 
 	NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
@@ -594,6 +615,8 @@ static unsigned long sfq_get(struct Qdisc *sch, u32 classid)
 static unsigned long sfq_bind(struct Qdisc *sch, unsigned long parent,
 			      u32 classid)
 {
+	/* we cannot bypass queue discipline anymore */
+	sch->flags &= ~TCQ_F_CAN_BYPASS;
 	return 0;
 }
 
@@ -647,7 +670,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
 	if (arg->stop)
 		return;
 
-	for (i = 0; i < SFQ_HASH_DIVISOR; i++) {
+	for (i = 0; i < q->divisor; i++) {
 		if (q->ht[i] == SFQ_EMPTY_SLOT ||
 		    arg->count < arg->skip) {
 			arg->count++;
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index e931658..1dcfb52 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -97,8 +97,7 @@
 	changed the limit is not effective anymore.
 */
 
-struct tbf_sched_data
-{
+struct tbf_sched_data {
 /* Parameters */
 	u32		limit;		/* Maximal length of backlog: bytes */
 	u32		buffer;		/* Token bucket depth/rate: MUST BE >= MTU/B */
@@ -115,10 +114,10 @@ struct tbf_sched_data
 	struct qdisc_watchdog watchdog;	/* Watchdog timer */
 };
 
-#define L2T(q,L)   qdisc_l2t((q)->R_tab,L)
-#define L2T_P(q,L) qdisc_l2t((q)->P_tab,L)
+#define L2T(q, L)   qdisc_l2t((q)->R_tab, L)
+#define L2T_P(q, L) qdisc_l2t((q)->P_tab, L)
 
-static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	int ret;
@@ -137,7 +136,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 	return NET_XMIT_SUCCESS;
 }
 
-static unsigned int tbf_drop(struct Qdisc* sch)
+static unsigned int tbf_drop(struct Qdisc *sch)
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	unsigned int len = 0;
@@ -149,7 +148,7 @@ static unsigned int tbf_drop(struct Qdisc* sch)
 	return len;
 }
 
-static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
+static struct sk_buff *tbf_dequeue(struct Qdisc *sch)
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
 	struct sk_buff *skb;
@@ -185,7 +184,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
 			q->tokens = toks;
 			q->ptokens = ptoks;
 			sch->q.qlen--;
-			sch->flags &= ~TCQ_F_THROTTLED;
+			qdisc_unthrottled(sch);
 			qdisc_bstats_update(sch, skb);
 			return skb;
 		}
@@ -209,7 +208,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
 	return NULL;
 }
 
-static void tbf_reset(struct Qdisc* sch)
+static void tbf_reset(struct Qdisc *sch)
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
 
@@ -227,7 +226,7 @@ static const struct nla_policy tbf_policy[TCA_TBF_MAX + 1] = {
 	[TCA_TBF_PTAB]	= { .type = NLA_BINARY, .len = TC_RTAB_SIZE },
 };
 
-static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
+static int tbf_change(struct Qdisc *sch, struct nlattr *opt)
 {
 	int err;
 	struct tbf_sched_data *q = qdisc_priv(sch);
@@ -236,7 +235,7 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
 	struct qdisc_rate_table *rtab = NULL;
 	struct qdisc_rate_table *ptab = NULL;
 	struct Qdisc *child = NULL;
-	int max_size,n;
+	int max_size, n;
 
 	err = nla_parse_nested(tb, TCA_TBF_PTAB, opt, tbf_policy);
 	if (err < 0)
@@ -259,15 +258,18 @@ static int tbf_change(struct Qdisc* sch, struct nlattr *opt)
 	}
 
 	for (n = 0; n < 256; n++)
-		if (rtab->data[n] > qopt->buffer) break;
-	max_size = (n << qopt->rate.cell_log)-1;
+		if (rtab->data[n] > qopt->buffer)
+			break;
+	max_size = (n << qopt->rate.cell_log) - 1;
 	if (ptab) {
 		int size;
 
 		for (n = 0; n < 256; n++)
-			if (ptab->data[n] > qopt->mtu) break;
-		size = (n << qopt->peakrate.cell_log)-1;
-		if (size < max_size) max_size = size;
+			if (ptab->data[n] > qopt->mtu)
+				break;
+		size = (n << qopt->peakrate.cell_log) - 1;
+		if (size < max_size)
+			max_size = size;
 	}
 	if (max_size < 0)
 		goto done;
@@ -310,7 +312,7 @@ done:
 	return err;
 }
 
-static int tbf_init(struct Qdisc* sch, struct nlattr *opt)
+static int tbf_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct tbf_sched_data *q = qdisc_priv(sch);
 
@@ -422,8 +424,7 @@ static void tbf_walk(struct Qdisc *sch, struct qdisc_walker *walker)
 	}
 }
 
-static const struct Qdisc_class_ops tbf_class_ops =
-{
+static const struct Qdisc_class_ops tbf_class_ops = {
 	.graft		=	tbf_graft,
 	.leaf		=	tbf_leaf,
 	.get		=	tbf_get,
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index d84e732..45cd300 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -53,8 +53,7 @@
       which will not break load balancing, though native slave
       traffic will have the highest priority.  */
 
-struct teql_master
-{
+struct teql_master {
 	struct Qdisc_ops qops;
 	struct net_device *dev;
 	struct Qdisc *slaves;
@@ -65,22 +64,21 @@ struct teql_master
 	unsigned long	tx_dropped;
 };
 
-struct teql_sched_data
-{
+struct teql_sched_data {
 	struct Qdisc *next;
 	struct teql_master *m;
 	struct neighbour *ncache;
 	struct sk_buff_head q;
 };
 
-#define NEXT_SLAVE(q) (((struct teql_sched_data*)qdisc_priv(q))->next)
+#define NEXT_SLAVE(q) (((struct teql_sched_data *)qdisc_priv(q))->next)
 
-#define FMASK (IFF_BROADCAST|IFF_POINTOPOINT)
+#define FMASK (IFF_BROADCAST | IFF_POINTOPOINT)
 
 /* "teql*" qdisc routines */
 
 static int
-teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+teql_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
 	struct net_device *dev = qdisc_dev(sch);
 	struct teql_sched_data *q = qdisc_priv(sch);
@@ -96,7 +94,7 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 }
 
 static struct sk_buff *
-teql_dequeue(struct Qdisc* sch)
+teql_dequeue(struct Qdisc *sch)
 {
 	struct teql_sched_data *dat = qdisc_priv(sch);
 	struct netdev_queue *dat_queue;
@@ -118,13 +116,13 @@ teql_dequeue(struct Qdisc* sch)
 }
 
 static struct sk_buff *
-teql_peek(struct Qdisc* sch)
+teql_peek(struct Qdisc *sch)
 {
 	/* teql is meant to be used as root qdisc */
 	return NULL;
 }
 
-static __inline__ void
+static inline void
 teql_neigh_release(struct neighbour *n)
 {
 	if (n)
@@ -132,7 +130,7 @@ teql_neigh_release(struct neighbour *n)
 }
 
 static void
-teql_reset(struct Qdisc* sch)
+teql_reset(struct Qdisc *sch)
 {
 	struct teql_sched_data *dat = qdisc_priv(sch);
 
@@ -142,13 +140,14 @@ teql_reset(struct Qdisc* sch)
 }
 
 static void
-teql_destroy(struct Qdisc* sch)
+teql_destroy(struct Qdisc *sch)
 {
 	struct Qdisc *q, *prev;
 	struct teql_sched_data *dat = qdisc_priv(sch);
 	struct teql_master *master = dat->m;
 
-	if ((prev = master->slaves) != NULL) {
+	prev = master->slaves;
+	if (prev) {
 		do {
 			q = NEXT_SLAVE(prev);
 			if (q == sch) {
@@ -180,7 +179,7 @@ teql_destroy(struct Qdisc* sch)
 static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
 {
 	struct net_device *dev = qdisc_dev(sch);
-	struct teql_master *m = (struct teql_master*)sch->ops;
+	struct teql_master *m = (struct teql_master *)sch->ops;
 	struct teql_sched_data *q = qdisc_priv(sch);
 
 	if (dev->hard_header_len > m->dev->hard_header_len)
@@ -291,7 +290,8 @@ restart:
 	nores = 0;
 	busy = 0;
 
-	if ((q = start) == NULL)
+	q = start;
+	if (!q)
 		goto drop;
 
 	do {
@@ -356,10 +356,10 @@ drop:
 
 static int teql_master_open(struct net_device *dev)
 {
-	struct Qdisc * q;
+	struct Qdisc *q;
 	struct teql_master *m = netdev_priv(dev);
 	int mtu = 0xFFFE;
-	unsigned flags = IFF_NOARP|IFF_MULTICAST;
+	unsigned int flags = IFF_NOARP | IFF_MULTICAST;
 
 	if (m->slaves == NULL)
 		return -EUNATCH;
@@ -427,7 +427,7 @@ static int teql_master_mtu(struct net_device *dev, int new_mtu)
 		do {
 			if (new_mtu > qdisc_dev(q)->mtu)
 				return -EINVAL;
-		} while ((q=NEXT_SLAVE(q)) != m->slaves);
+		} while ((q = NEXT_SLAVE(q)) != m->slaves);
 	}
 
 	dev->mtu = new_mtu;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 5f1fb8b..6b04287 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1089,7 +1089,6 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
 			     base.inqueue.immediate);
 	struct sctp_endpoint *ep;
 	struct sctp_chunk *chunk;
-	struct sock *sk;
 	struct sctp_inq *inqueue;
 	int state;
 	sctp_subtype_t subtype;
@@ -1097,7 +1096,6 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
 
 	/* The association should be held so we should be safe. */
 	ep = asoc->ep;
-	sk = asoc->base.sk;
 
 	inqueue = &asoc->base.inqueue;
 	sctp_association_hold(asoc);
diff --git a/net/sctp/input.c b/net/sctp/input.c
index ea21924..826661b 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -948,14 +948,11 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb,
 	union sctp_addr addr;
 	union sctp_addr *paddr = &addr;
 	struct sctphdr *sh = sctp_hdr(skb);
-	sctp_chunkhdr_t *ch;
 	union sctp_params params;
 	sctp_init_chunk_t *init;
 	struct sctp_transport *transport;
 	struct sctp_af *af;
 
-	ch = (sctp_chunkhdr_t *) skb->data;
-
 	/*
 	 * This code will NOT touch anything inside the chunk--it is
 	 * strictly READ-ONLY.
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 95e0c8e..865ce7b 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -201,40 +201,40 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
 {
 	struct sock *sk = skb->sk;
 	struct ipv6_pinfo *np = inet6_sk(sk);
-	struct flowi fl;
+	struct flowi6 fl6;
 
-	memset(&fl, 0, sizeof(fl));
+	memset(&fl6, 0, sizeof(fl6));
 
-	fl.proto = sk->sk_protocol;
+	fl6.flowi6_proto = sk->sk_protocol;
 
 	/* Fill in the dest address from the route entry passed with the skb
 	 * and the source address from the transport.
 	 */
-	ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr.v6.sin6_addr);
-	ipv6_addr_copy(&fl.fl6_src, &transport->saddr.v6.sin6_addr);
+	ipv6_addr_copy(&fl6.daddr, &transport->ipaddr.v6.sin6_addr);
+	ipv6_addr_copy(&fl6.saddr, &transport->saddr.v6.sin6_addr);
 
-	fl.fl6_flowlabel = np->flow_label;
-	IP6_ECN_flow_xmit(sk, fl.fl6_flowlabel);
-	if (ipv6_addr_type(&fl.fl6_src) & IPV6_ADDR_LINKLOCAL)
-		fl.oif = transport->saddr.v6.sin6_scope_id;
+	fl6.flowlabel = np->flow_label;
+	IP6_ECN_flow_xmit(sk, fl6.flowlabel);
+	if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL)
+		fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id;
 	else
-		fl.oif = sk->sk_bound_dev_if;
+		fl6.flowi6_oif = sk->sk_bound_dev_if;
 
 	if (np->opt && np->opt->srcrt) {
 		struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
-		ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+		ipv6_addr_copy(&fl6.daddr, rt0->addr);
 	}
 
 	SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n",
 			  __func__, skb, skb->len,
-			  &fl.fl6_src, &fl.fl6_dst);
+			  &fl6.saddr, &fl6.daddr);
 
 	SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
 
 	if (!(transport->param_flags & SPP_PMTUD_ENABLE))
 		skb->local_df = 1;
 
-	return ip6_xmit(sk, skb, &fl, np->opt);
+	return ip6_xmit(sk, skb, &fl6, np->opt);
 }
 
 /* Returns the dst cache entry for the given source and destination ip
@@ -245,22 +245,22 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
 					 union sctp_addr *saddr)
 {
 	struct dst_entry *dst;
-	struct flowi fl;
+	struct flowi6 fl6;
 
-	memset(&fl, 0, sizeof(fl));
-	ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
+	memset(&fl6, 0, sizeof(fl6));
+	ipv6_addr_copy(&fl6.daddr, &daddr->v6.sin6_addr);
 	if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		fl.oif = daddr->v6.sin6_scope_id;
+		fl6.flowi6_oif = daddr->v6.sin6_scope_id;
 
 
-	SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl.fl6_dst);
+	SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6.daddr);
 
 	if (saddr) {
-		ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr);
-		SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl.fl6_src);
+		ipv6_addr_copy(&fl6.saddr, &saddr->v6.sin6_addr);
+		SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6.saddr);
 	}
 
-	dst = ip6_route_output(&init_net, NULL, &fl);
+	dst = ip6_route_output(&init_net, NULL, &fl6);
 	if (!dst->error) {
 		struct rt6_info *rt;
 		rt = (struct rt6_info *)dst;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 8c6d379..26dc005 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -545,13 +545,11 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt,
 	struct sctp_transport *transport = pkt->transport;
 	sctp_xmit_t status;
 	struct sctp_chunk *chunk, *chunk1;
-	struct sctp_association *asoc;
 	int fast_rtx;
 	int error = 0;
 	int timer = 0;
 	int done = 0;
 
-	asoc = q->asoc;
 	lqueue = &q->retransmit;
 	fast_rtx = q->fast_rtx;
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index e58f947..152976e 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -468,32 +468,32 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
 					 union sctp_addr *saddr)
 {
 	struct rtable *rt;
-	struct flowi fl;
+	struct flowi4 fl4;
 	struct sctp_bind_addr *bp;
 	struct sctp_sockaddr_entry *laddr;
 	struct dst_entry *dst = NULL;
 	union sctp_addr dst_saddr;
 
-	memset(&fl, 0x0, sizeof(struct flowi));
-	fl.fl4_dst  = daddr->v4.sin_addr.s_addr;
-	fl.fl_ip_dport = daddr->v4.sin_port;
-	fl.proto = IPPROTO_SCTP;
+	memset(&fl4, 0x0, sizeof(struct flowi4));
+	fl4.daddr  = daddr->v4.sin_addr.s_addr;
+	fl4.fl4_dport = daddr->v4.sin_port;
+	fl4.flowi4_proto = IPPROTO_SCTP;
 	if (asoc) {
-		fl.fl4_tos = RT_CONN_FLAGS(asoc->base.sk);
-		fl.oif = asoc->base.sk->sk_bound_dev_if;
-		fl.fl_ip_sport = htons(asoc->base.bind_addr.port);
+		fl4.flowi4_tos = RT_CONN_FLAGS(asoc->base.sk);
+		fl4.flowi4_oif = asoc->base.sk->sk_bound_dev_if;
+		fl4.fl4_sport = htons(asoc->base.bind_addr.port);
 	}
 	if (saddr) {
-		fl.fl4_src = saddr->v4.sin_addr.s_addr;
-		fl.fl_ip_sport = saddr->v4.sin_port;
+		fl4.saddr = saddr->v4.sin_addr.s_addr;
+		fl4.fl4_sport = saddr->v4.sin_port;
 	}
 
 	SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ",
-			  __func__, &fl.fl4_dst, &fl.fl4_src);
+			  __func__, &fl4.daddr, &fl4.saddr);
 
-	if (!ip_route_output_key(&init_net, &rt, &fl)) {
+	rt = ip_route_output_key(&init_net, &fl4);
+	if (!IS_ERR(rt))
 		dst = &rt->dst;
-	}
 
 	/* If there is no association or if a source address is passed, no
 	 * more validation is required.
@@ -533,9 +533,10 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
 			continue;
 		if ((laddr->state == SCTP_ADDR_SRC) &&
 		    (AF_INET == laddr->a.sa.sa_family)) {
-			fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
-			fl.fl_ip_sport = laddr->a.v4.sin_port;
-			if (!ip_route_output_key(&init_net, &rt, &fl)) {
+			fl4.saddr = laddr->a.v4.sin_addr.s_addr;
+			fl4.fl4_sport = laddr->a.v4.sin_port;
+			rt = ip_route_output_key(&init_net, &fl4);
+			if (!IS_ERR(rt)) {
 				dst = &rt->dst;
 				goto out_unlock;
 			}
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index b23428f..de98665 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3375,7 +3375,6 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
 				    struct sctp_fwdtsn_skip *skiplist)
 {
 	struct sctp_chunk *retval = NULL;
-	struct sctp_fwdtsn_chunk *ftsn_chunk;
 	struct sctp_fwdtsn_hdr ftsn_hdr;
 	struct sctp_fwdtsn_skip skip;
 	size_t hint;
@@ -3388,8 +3387,6 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
 	if (!retval)
 		return NULL;
 
-	ftsn_chunk = (struct sctp_fwdtsn_chunk *)retval->subh.fwdtsn_hdr;
-
 	ftsn_hdr.new_cum_tsn = htonl(new_cum_tsn);
 	retval->subh.fwdtsn_hdr =
 		sctp_addto_chunk(retval, sizeof(ftsn_hdr), &ftsn_hdr);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 8e02550..3951a10 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2928,7 +2928,6 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
 					     unsigned int optlen)
 {
 	struct sctp_sock	*sp;
-	struct sctp_endpoint	*ep;
 	struct sctp_association	*asoc = NULL;
 	struct sctp_setpeerprim	prim;
 	struct sctp_chunk	*chunk;
@@ -2936,7 +2935,6 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
 	int 			err;
 
 	sp = sctp_sk(sk);
-	ep = sp->ep;
 
 	if (!sctp_addip_enable)
 		return -EPERM;
@@ -6102,15 +6100,16 @@ static void __sctp_write_space(struct sctp_association *asoc)
 			wake_up_interruptible(&asoc->wait);
 
 		if (sctp_writeable(sk)) {
-			if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
-				wake_up_interruptible(sk_sleep(sk));
+			wait_queue_head_t *wq = sk_sleep(sk);
+
+			if (wq && waitqueue_active(wq))
+				wake_up_interruptible(wq);
 
 			/* Note that we try to include the Async I/O support
 			 * here by modeling from the current TCP/UDP code.
 			 * We have not tested with it yet.
 			 */
-			if (sock->wq->fasync_list &&
-			    !(sk->sk_shutdown & SEND_SHUTDOWN))
+			if (!(sk->sk_shutdown & SEND_SHUTDOWN))
 				sock_wake_async(sock,
 						SOCK_WAKE_SPACE, POLL_OUT);
 		}
diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c
index 747d541..f1e40ceb 100644
--- a/net/sctp/tsnmap.c
+++ b/net/sctp/tsnmap.c
@@ -344,7 +344,7 @@ __u16 sctp_tsnmap_num_gabs(struct sctp_tsnmap *map,
 
 	/* Refresh the gap ack information. */
 	if (sctp_tsnmap_has_gap(map)) {
-		__u16 start, end;
+		__u16 start = 0, end = 0;
 		sctp_tsnmap_iter_init(map, &iter);
 		while (sctp_tsnmap_next_gap_ack(map, &iter,
 						&start,
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index c7f7e49..1767818 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -105,11 +105,8 @@ int sctp_ulpq_tail_data(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
 			gfp_t gfp)
 {
 	struct sk_buff_head temp;
-	sctp_data_chunk_t *hdr;
 	struct sctp_ulpevent *event;
 
-	hdr = (sctp_data_chunk_t *) chunk->chunk_hdr;
-
 	/* Create an event from the incoming chunk. */
 	event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp);
 	if (!event)
@@ -743,11 +740,9 @@ static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq,
 	struct sk_buff *pos, *tmp;
 	struct sctp_ulpevent *cevent;
 	struct sctp_stream *in;
-	__u16 sid, csid;
-	__u16 ssn, cssn;
+	__u16 sid, csid, cssn;
 
 	sid = event->stream;
-	ssn = event->ssn;
 	in  = &ulpq->asoc->ssnmap->in;
 
 	event_list = (struct sk_buff_head *) sctp_event2skb(event)->prev;
diff --git a/net/socket.c b/net/socket.c
index ac2219f..5212447 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -240,17 +240,19 @@ static struct kmem_cache *sock_inode_cachep __read_mostly;
 static struct inode *sock_alloc_inode(struct super_block *sb)
 {
 	struct socket_alloc *ei;
+	struct socket_wq *wq;
 
 	ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
 	if (!ei)
 		return NULL;
-	ei->socket.wq = kmalloc(sizeof(struct socket_wq), GFP_KERNEL);
-	if (!ei->socket.wq) {
+	wq = kmalloc(sizeof(*wq), GFP_KERNEL);
+	if (!wq) {
 		kmem_cache_free(sock_inode_cachep, ei);
 		return NULL;
 	}
-	init_waitqueue_head(&ei->socket.wq->wait);
-	ei->socket.wq->fasync_list = NULL;
+	init_waitqueue_head(&wq->wait);
+	wq->fasync_list = NULL;
+	RCU_INIT_POINTER(ei->socket.wq, wq);
 
 	ei->socket.state = SS_UNCONNECTED;
 	ei->socket.flags = 0;
@@ -273,9 +275,11 @@ static void wq_free_rcu(struct rcu_head *head)
 static void sock_destroy_inode(struct inode *inode)
 {
 	struct socket_alloc *ei;
+	struct socket_wq *wq;
 
 	ei = container_of(inode, struct socket_alloc, vfs_inode);
-	call_rcu(&ei->socket.wq->rcu, wq_free_rcu);
+	wq = rcu_dereference_protected(ei->socket.wq, 1);
+	call_rcu(&wq->rcu, wq_free_rcu);
 	kmem_cache_free(sock_inode_cachep, ei);
 }
 
@@ -524,7 +528,7 @@ void sock_release(struct socket *sock)
 		module_put(owner);
 	}
 
-	if (sock->wq->fasync_list)
+	if (rcu_dereference_protected(sock->wq, 1)->fasync_list)
 		printk(KERN_ERR "sock_release: fasync list not empty!\n");
 
 	percpu_sub(sockets_in_use, 1);
@@ -1108,15 +1112,16 @@ static int sock_fasync(int fd, struct file *filp, int on)
 {
 	struct socket *sock = filp->private_data;
 	struct sock *sk = sock->sk;
+	struct socket_wq *wq;
 
 	if (sk == NULL)
 		return -EINVAL;
 
 	lock_sock(sk);
+	wq = rcu_dereference_protected(sock->wq, sock_owned_by_user(sk));
+	fasync_helper(fd, filp, on, &wq->fasync_list);
 
-	fasync_helper(fd, filp, on, &sock->wq->fasync_list);
-
-	if (!sock->wq->fasync_list)
+	if (!wq->fasync_list)
 		sock_reset_flag(sk, SOCK_FASYNC);
 	else
 		sock_set_flag(sk, SOCK_FASYNC);
@@ -2583,23 +2588,123 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32)
 
 static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
 {
+	struct compat_ethtool_rxnfc __user *compat_rxnfc;
+	bool convert_in = false, convert_out = false;
+	size_t buf_size = ALIGN(sizeof(struct ifreq), 8);
+	struct ethtool_rxnfc __user *rxnfc;
 	struct ifreq __user *ifr;
+	u32 rule_cnt = 0, actual_rule_cnt;
+	u32 ethcmd;
 	u32 data;
-	void __user *datap;
+	int ret;
 
-	ifr = compat_alloc_user_space(sizeof(*ifr));
+	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+		return -EFAULT;
 
-	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
+	compat_rxnfc = compat_ptr(data);
+
+	if (get_user(ethcmd, &compat_rxnfc->cmd))
 		return -EFAULT;
 
-	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+	/* Most ethtool structures are defined without padding.
+	 * Unfortunately struct ethtool_rxnfc is an exception.
+	 */
+	switch (ethcmd) {
+	default:
+		break;
+	case ETHTOOL_GRXCLSRLALL:
+		/* Buffer size is variable */
+		if (get_user(rule_cnt, &compat_rxnfc->rule_cnt))
+			return -EFAULT;
+		if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
+			return -ENOMEM;
+		buf_size += rule_cnt * sizeof(u32);
+		/* fall through */
+	case ETHTOOL_GRXRINGS:
+	case ETHTOOL_GRXCLSRLCNT:
+	case ETHTOOL_GRXCLSRULE:
+		convert_out = true;
+		/* fall through */
+	case ETHTOOL_SRXCLSRLDEL:
+	case ETHTOOL_SRXCLSRLINS:
+		buf_size += sizeof(struct ethtool_rxnfc);
+		convert_in = true;
+		break;
+	}
+
+	ifr = compat_alloc_user_space(buf_size);
+	rxnfc = (void *)ifr + ALIGN(sizeof(struct ifreq), 8);
+
+	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
 		return -EFAULT;
 
-	datap = compat_ptr(data);
-	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
+	if (put_user(convert_in ? rxnfc : compat_ptr(data),
+		     &ifr->ifr_ifru.ifru_data))
 		return -EFAULT;
 
-	return dev_ioctl(net, SIOCETHTOOL, ifr);
+	if (convert_in) {
+		/* We expect there to be holes between fs.m_u and
+		 * fs.ring_cookie and at the end of fs, but nowhere else.
+		 */
+		BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) +
+			     sizeof(compat_rxnfc->fs.m_u) !=
+			     offsetof(struct ethtool_rxnfc, fs.m_u) +
+			     sizeof(rxnfc->fs.m_u));
+		BUILD_BUG_ON(
+			offsetof(struct compat_ethtool_rxnfc, fs.location) -
+			offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) !=
+			offsetof(struct ethtool_rxnfc, fs.location) -
+			offsetof(struct ethtool_rxnfc, fs.ring_cookie));
+
+		if (copy_in_user(rxnfc, compat_rxnfc,
+				 (void *)(&rxnfc->fs.m_u + 1) -
+				 (void *)rxnfc) ||
+		    copy_in_user(&rxnfc->fs.ring_cookie,
+				 &compat_rxnfc->fs.ring_cookie,
+				 (void *)(&rxnfc->fs.location + 1) -
+				 (void *)&rxnfc->fs.ring_cookie) ||
+		    copy_in_user(&rxnfc->rule_cnt, &compat_rxnfc->rule_cnt,
+				 sizeof(rxnfc->rule_cnt)))
+			return -EFAULT;
+	}
+
+	ret = dev_ioctl(net, SIOCETHTOOL, ifr);
+	if (ret)
+		return ret;
+
+	if (convert_out) {
+		if (copy_in_user(compat_rxnfc, rxnfc,
+				 (const void *)(&rxnfc->fs.m_u + 1) -
+				 (const void *)rxnfc) ||
+		    copy_in_user(&compat_rxnfc->fs.ring_cookie,
+				 &rxnfc->fs.ring_cookie,
+				 (const void *)(&rxnfc->fs.location + 1) -
+				 (const void *)&rxnfc->fs.ring_cookie) ||
+		    copy_in_user(&compat_rxnfc->rule_cnt, &rxnfc->rule_cnt,
+				 sizeof(rxnfc->rule_cnt)))
+			return -EFAULT;
+
+		if (ethcmd == ETHTOOL_GRXCLSRLALL) {
+			/* As an optimisation, we only copy the actual
+			 * number of rules that the underlying
+			 * function returned.  Since Mallory might
+			 * change the rule count in user memory, we
+			 * check that it is less than the rule count
+			 * originally given (as the user buffer size),
+			 * which has been range-checked.
+			 */
+			if (get_user(actual_rule_cnt, &rxnfc->rule_cnt))
+				return -EFAULT;
+			if (actual_rule_cnt < rule_cnt)
+				rule_cnt = actual_rule_cnt;
+			if (copy_in_user(&compat_rxnfc->rule_locs[0],
+					 &rxnfc->rule_locs[0],
+					 rule_cnt * sizeof(u32)))
+				return -EFAULT;
+		}
+	}
+
+	return 0;
 }
 
 static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32)
@@ -2643,7 +2748,8 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
 
 		old_fs = get_fs();
 		set_fs(KERNEL_DS);
-		err = dev_ioctl(net, cmd, &kifr);
+		err = dev_ioctl(net, cmd,
+				(struct ifreq __user __force *) &kifr);
 		set_fs(old_fs);
 
 		return err;
@@ -2752,7 +2858,7 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 
 	old_fs = get_fs();
 	set_fs(KERNEL_DS);
-	err = dev_ioctl(net, cmd, (void __user *)&ifr);
+	err = dev_ioctl(net, cmd, (void  __user __force *)&ifr);
 	set_fs(old_fs);
 
 	if (cmd == SIOCGIFMAP && !err) {
@@ -2857,7 +2963,8 @@ static int routing_ioctl(struct net *net, struct socket *sock,
 		ret |= __get_user(rtdev, &(ur4->rt_dev));
 		if (rtdev) {
 			ret |= copy_from_user(devname, compat_ptr(rtdev), 15);
-			r4.rt_dev = devname; devname[15] = 0;
+			r4.rt_dev = (char __user __force *)devname;
+			devname[15] = 0;
 		} else
 			r4.rt_dev = NULL;
 
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 45dbf15..f3914d0 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -417,7 +417,7 @@ static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg,
 		gss_msg->msg.len += len;
 	}
 	if (mech->gm_upcall_enctypes) {
-		len = sprintf(p, mech->gm_upcall_enctypes);
+		len = sprintf(p, "enctypes=%s ", mech->gm_upcall_enctypes);
 		p += len;
 		gss_msg->msg.len += len;
 	}
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index f375dec..9022f0a 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -750,7 +750,7 @@ static struct gss_api_mech gss_kerberos_mech = {
 	.gm_ops		= &gss_kerberos_ops,
 	.gm_pf_num	= ARRAY_SIZE(gss_kerberos_pfs),
 	.gm_pfs		= gss_kerberos_pfs,
-	.gm_upcall_enctypes = "enctypes=18,17,16,23,3,1,2 ",
+	.gm_upcall_enctypes = "18,17,16,23,3,1,2",
 };
 
 static int __init init_kerberos_module(void)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 57d344c..e7a96e4 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -436,7 +436,9 @@ void rpc_killall_tasks(struct rpc_clnt *clnt)
 		if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
 			rovr->tk_flags |= RPC_TASK_KILLED;
 			rpc_exit(rovr, -EIO);
-			rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr);
+			if (RPC_IS_QUEUED(rovr))
+				rpc_wake_up_queued_task(rovr->tk_waitqueue,
+							rovr);
 		}
 	}
 	spin_unlock(&clnt->cl_lock);
@@ -597,6 +599,14 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt)
 	}
 }
 
+void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt)
+{
+	rpc_task_release_client(task);
+	rpc_task_set_client(task, clnt);
+}
+EXPORT_SYMBOL_GPL(rpc_task_reset_client);
+
+
 static void
 rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg)
 {
@@ -636,12 +646,6 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
 	rpc_task_set_client(task, task_setup_data->rpc_client);
 	rpc_task_set_rpc_message(task, task_setup_data->rpc_message);
 
-	if (task->tk_status != 0) {
-		int ret = task->tk_status;
-		rpc_put_task(task);
-		return ERR_PTR(ret);
-	}
-
 	if (task->tk_action == NULL)
 		rpc_call_start(task);
 
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 59e5994..ffb6876 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -299,15 +299,8 @@ static void rpc_make_runnable(struct rpc_task *task)
 	if (rpc_test_and_set_running(task))
 		return;
 	if (RPC_IS_ASYNC(task)) {
-		int status;
-
 		INIT_WORK(&task->u.tk_work, rpc_async_schedule);
-		status = queue_work(rpciod_workqueue, &task->u.tk_work);
-		if (status < 0) {
-			printk(KERN_WARNING "RPC: failed to add task to queue: error: %d!\n", status);
-			task->tk_status = status;
-			return;
-		}
+		queue_work(rpciod_workqueue, &task->u.tk_work);
 	} else
 		wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED);
 }
@@ -637,14 +630,12 @@ static void __rpc_execute(struct rpc_task *task)
 			save_callback = task->tk_callback;
 			task->tk_callback = NULL;
 			save_callback(task);
-		}
-
-		/*
-		 * Perform the next FSM step.
-		 * tk_action may be NULL when the task has been killed
-		 * by someone else.
-		 */
-		if (!RPC_IS_QUEUED(task)) {
+		} else {
+			/*
+			 * Perform the next FSM step.
+			 * tk_action may be NULL when the task has been killed
+			 * by someone else.
+			 */
 			if (task->tk_action == NULL)
 				break;
 			task->tk_action(task);
@@ -843,12 +834,6 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data)
 	}
 
 	rpc_init_task(task, setup_data);
-	if (task->tk_status < 0) {
-		int err = task->tk_status;
-		rpc_put_task(task);
-		return ERR_PTR(err);
-	}
-
 	task->tk_flags |= flags;
 	dprintk("RPC:       allocated task %p\n", task);
 	return task;
@@ -955,7 +940,7 @@ static int rpciod_start(void)
 	 * Create the rpciod thread and wait for it to start.
 	 */
 	dprintk("RPC:       creating workqueue rpciod\n");
-	wq = alloc_workqueue("rpciod", WQ_RESCUER, 0);
+	wq = alloc_workqueue("rpciod", WQ_MEM_RECLAIM, 0);
 	rpciod_workqueue = wq;
 	return rpciod_workqueue != NULL;
 }
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index d802e94..b7d435c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -420,6 +420,7 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
 static void svc_udp_data_ready(struct sock *sk, int count)
 {
 	struct svc_sock	*svsk = (struct svc_sock *)sk->sk_user_data;
+	wait_queue_head_t *wq = sk_sleep(sk);
 
 	if (svsk) {
 		dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
@@ -428,8 +429,8 @@ static void svc_udp_data_ready(struct sock *sk, int count)
 		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
 		svc_xprt_enqueue(&svsk->sk_xprt);
 	}
-	if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
-		wake_up_interruptible(sk_sleep(sk));
+	if (wq && waitqueue_active(wq))
+		wake_up_interruptible(wq);
 }
 
 /*
@@ -438,6 +439,7 @@ static void svc_udp_data_ready(struct sock *sk, int count)
 static void svc_write_space(struct sock *sk)
 {
 	struct svc_sock	*svsk = (struct svc_sock *)(sk->sk_user_data);
+	wait_queue_head_t *wq = sk_sleep(sk);
 
 	if (svsk) {
 		dprintk("svc: socket %p(inet %p), write_space busy=%d\n",
@@ -445,10 +447,10 @@ static void svc_write_space(struct sock *sk)
 		svc_xprt_enqueue(&svsk->sk_xprt);
 	}
 
-	if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk))) {
+	if (wq && waitqueue_active(wq)) {
 		dprintk("RPC svc_write_space: someone sleeping on %p\n",
 		       svsk);
-		wake_up_interruptible(sk_sleep(sk));
+		wake_up_interruptible(wq);
 	}
 }
 
@@ -739,6 +741,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
 static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
 {
 	struct svc_sock	*svsk = (struct svc_sock *)sk->sk_user_data;
+	wait_queue_head_t *wq;
 
 	dprintk("svc: socket %p TCP (listen) state change %d\n",
 		sk, sk->sk_state);
@@ -761,8 +764,9 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
 			printk("svc: socket %p: no user data\n", sk);
 	}
 
-	if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
-		wake_up_interruptible_all(sk_sleep(sk));
+	wq = sk_sleep(sk);
+	if (wq && waitqueue_active(wq))
+		wake_up_interruptible_all(wq);
 }
 
 /*
@@ -771,6 +775,7 @@ static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused)
 static void svc_tcp_state_change(struct sock *sk)
 {
 	struct svc_sock	*svsk = (struct svc_sock *)sk->sk_user_data;
+	wait_queue_head_t *wq = sk_sleep(sk);
 
 	dprintk("svc: socket %p TCP (connected) state change %d (svsk %p)\n",
 		sk, sk->sk_state, sk->sk_user_data);
@@ -781,13 +786,14 @@ static void svc_tcp_state_change(struct sock *sk)
 		set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
 		svc_xprt_enqueue(&svsk->sk_xprt);
 	}
-	if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
-		wake_up_interruptible_all(sk_sleep(sk));
+	if (wq && waitqueue_active(wq))
+		wake_up_interruptible_all(wq);
 }
 
 static void svc_tcp_data_ready(struct sock *sk, int count)
 {
 	struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data;
+	wait_queue_head_t *wq = sk_sleep(sk);
 
 	dprintk("svc: socket %p TCP data ready (svsk %p)\n",
 		sk, sk->sk_user_data);
@@ -795,8 +801,8 @@ static void svc_tcp_data_ready(struct sock *sk, int count)
 		set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
 		svc_xprt_enqueue(&svsk->sk_xprt);
 	}
-	if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
-		wake_up_interruptible(sk_sleep(sk));
+	if (wq && waitqueue_active(wq))
+		wake_up_interruptible(wq);
 }
 
 /*
@@ -1531,6 +1537,7 @@ static void svc_sock_detach(struct svc_xprt *xprt)
 {
 	struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
 	struct sock *sk = svsk->sk_sk;
+	wait_queue_head_t *wq;
 
 	dprintk("svc: svc_sock_detach(%p)\n", svsk);
 
@@ -1539,8 +1546,9 @@ static void svc_sock_detach(struct svc_xprt *xprt)
 	sk->sk_data_ready = svsk->sk_odata;
 	sk->sk_write_space = svsk->sk_owspace;
 
-	if (sk_sleep(sk) && waitqueue_active(sk_sleep(sk)))
-		wake_up_interruptible(sk_sleep(sk));
+	wq = sk_sleep(sk);
+	if (wq && waitqueue_active(wq))
+		wake_up_interruptible(wq);
 }
 
 /*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 856274d..9494c37 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -202,10 +202,9 @@ int xprt_reserve_xprt(struct rpc_task *task)
 		goto out_sleep;
 	}
 	xprt->snd_task = task;
-	if (req) {
-		req->rq_bytes_sent = 0;
-		req->rq_ntrans++;
-	}
+	req->rq_bytes_sent = 0;
+	req->rq_ntrans++;
+
 	return 1;
 
 out_sleep:
@@ -213,7 +212,7 @@ out_sleep:
 			task->tk_pid, xprt);
 	task->tk_timeout = 0;
 	task->tk_status = -EAGAIN;
-	if (req && req->rq_ntrans)
+	if (req->rq_ntrans)
 		rpc_sleep_on(&xprt->resend, task, NULL);
 	else
 		rpc_sleep_on(&xprt->sending, task, NULL);
@@ -965,7 +964,7 @@ struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req)
 	xprt = kzalloc(size, GFP_KERNEL);
 	if (xprt == NULL)
 		goto out;
-	kref_init(&xprt->kref);
+	atomic_set(&xprt->count, 1);
 
 	xprt->max_reqs = max_req;
 	xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
@@ -1145,13 +1144,11 @@ found:
 
 /**
  * xprt_destroy - destroy an RPC transport, killing off all requests.
- * @kref: kref for the transport to destroy
+ * @xprt: transport to destroy
  *
  */
-static void xprt_destroy(struct kref *kref)
+static void xprt_destroy(struct rpc_xprt *xprt)
 {
-	struct rpc_xprt *xprt = container_of(kref, struct rpc_xprt, kref);
-
 	dprintk("RPC:       destroying transport %p\n", xprt);
 	xprt->shutdown = 1;
 	del_timer_sync(&xprt->timer);
@@ -1175,7 +1172,8 @@ static void xprt_destroy(struct kref *kref)
  */
 void xprt_put(struct rpc_xprt *xprt)
 {
-	kref_put(&xprt->kref, xprt_destroy);
+	if (atomic_dec_and_test(&xprt->count))
+		xprt_destroy(xprt);
 }
 
 /**
@@ -1185,6 +1183,7 @@ void xprt_put(struct rpc_xprt *xprt)
  */
 struct rpc_xprt *xprt_get(struct rpc_xprt *xprt)
 {
-	kref_get(&xprt->kref);
-	return xprt;
+	if (atomic_inc_not_zero(&xprt->count))
+		return xprt;
+	return NULL;
 }
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 2ac3f6e..554d081 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -87,6 +87,8 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
 	enum rpcrdma_chunktype type, struct rpcrdma_mr_seg *seg, int nsegs)
 {
 	int len, n = 0, p;
+	int page_base;
+	struct page **ppages;
 
 	if (pos == 0 && xdrbuf->head[0].iov_len) {
 		seg[n].mr_page = NULL;
@@ -95,34 +97,32 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos,
 		++n;
 	}
 
-	if (xdrbuf->page_len && (xdrbuf->pages[0] != NULL)) {
-		if (n == nsegs)
-			return 0;
-		seg[n].mr_page = xdrbuf->pages[0];
-		seg[n].mr_offset = (void *)(unsigned long) xdrbuf->page_base;
-		seg[n].mr_len = min_t(u32,
-			PAGE_SIZE - xdrbuf->page_base, xdrbuf->page_len);
-		len = xdrbuf->page_len - seg[n].mr_len;
+	len = xdrbuf->page_len;
+	ppages = xdrbuf->pages + (xdrbuf->page_base >> PAGE_SHIFT);
+	page_base = xdrbuf->page_base & ~PAGE_MASK;
+	p = 0;
+	while (len && n < nsegs) {
+		seg[n].mr_page = ppages[p];
+		seg[n].mr_offset = (void *)(unsigned long) page_base;
+		seg[n].mr_len = min_t(u32, PAGE_SIZE - page_base, len);
+		BUG_ON(seg[n].mr_len > PAGE_SIZE);
+		len -= seg[n].mr_len;
 		++n;
-		p = 1;
-		while (len > 0) {
-			if (n == nsegs)
-				return 0;
-			seg[n].mr_page = xdrbuf->pages[p];
-			seg[n].mr_offset = NULL;
-			seg[n].mr_len = min_t(u32, PAGE_SIZE, len);
-			len -= seg[n].mr_len;
-			++n;
-			++p;
-		}
+		++p;
+		page_base = 0;	/* page offset only applies to first page */
 	}
 
+	/* Message overflows the seg array */
+	if (len && n == nsegs)
+		return 0;
+
 	if (xdrbuf->tail[0].iov_len) {
 		/* the rpcrdma protocol allows us to omit any trailing
 		 * xdr pad bytes, saving the server an RDMA operation. */
 		if (xdrbuf->tail[0].iov_len < 4 && xprt_rdma_pad_optimize)
 			return n;
 		if (n == nsegs)
+			/* Tail remains, but we're out of segments */
 			return 0;
 		seg[n].mr_page = NULL;
 		seg[n].mr_offset = xdrbuf->tail[0].iov_base;
@@ -296,6 +296,8 @@ rpcrdma_inline_pullup(struct rpc_rqst *rqst, int pad)
 	int copy_len;
 	unsigned char *srcp, *destp;
 	struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);
+	int page_base;
+	struct page **ppages;
 
 	destp = rqst->rq_svec[0].iov_base;
 	curlen = rqst->rq_svec[0].iov_len;
@@ -324,28 +326,25 @@ rpcrdma_inline_pullup(struct rpc_rqst *rqst, int pad)
 			__func__, destp + copy_len, curlen);
 		rqst->rq_svec[0].iov_len += curlen;
 	}
-
 	r_xprt->rx_stats.pullup_copy_count += copy_len;
-	npages = PAGE_ALIGN(rqst->rq_snd_buf.page_base+copy_len) >> PAGE_SHIFT;
+
+	page_base = rqst->rq_snd_buf.page_base;
+	ppages = rqst->rq_snd_buf.pages + (page_base >> PAGE_SHIFT);
+	page_base &= ~PAGE_MASK;
+	npages = PAGE_ALIGN(page_base+copy_len) >> PAGE_SHIFT;
 	for (i = 0; copy_len && i < npages; i++) {
-		if (i == 0)
-			curlen = PAGE_SIZE - rqst->rq_snd_buf.page_base;
-		else
-			curlen = PAGE_SIZE;
+		curlen = PAGE_SIZE - page_base;
 		if (curlen > copy_len)
 			curlen = copy_len;
 		dprintk("RPC:       %s: page %d destp 0x%p len %d curlen %d\n",
 			__func__, i, destp, copy_len, curlen);
-		srcp = kmap_atomic(rqst->rq_snd_buf.pages[i],
-					KM_SKB_SUNRPC_DATA);
-		if (i == 0)
-			memcpy(destp, srcp+rqst->rq_snd_buf.page_base, curlen);
-		else
-			memcpy(destp, srcp, curlen);
+		srcp = kmap_atomic(ppages[i], KM_SKB_SUNRPC_DATA);
+		memcpy(destp, srcp+page_base, curlen);
 		kunmap_atomic(srcp, KM_SKB_SUNRPC_DATA);
 		rqst->rq_svec[0].iov_len += curlen;
 		destp += curlen;
 		copy_len -= curlen;
+		page_base = 0;
 	}
 	/* header now contains entire send message */
 	return pad;
@@ -606,6 +605,8 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
 {
 	int i, npages, curlen, olen;
 	char *destp;
+	struct page **ppages;
+	int page_base;
 
 	curlen = rqst->rq_rcv_buf.head[0].iov_len;
 	if (curlen > copy_len) {	/* write chunk header fixup */
@@ -624,32 +625,29 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad)
 	olen = copy_len;
 	i = 0;
 	rpcx_to_rdmax(rqst->rq_xprt)->rx_stats.fixup_copy_count += olen;
+	page_base = rqst->rq_rcv_buf.page_base;
+	ppages = rqst->rq_rcv_buf.pages + (page_base >> PAGE_SHIFT);
+	page_base &= ~PAGE_MASK;
+
 	if (copy_len && rqst->rq_rcv_buf.page_len) {
-		npages = PAGE_ALIGN(rqst->rq_rcv_buf.page_base +
+		npages = PAGE_ALIGN(page_base +
 			rqst->rq_rcv_buf.page_len) >> PAGE_SHIFT;
 		for (; i < npages; i++) {
-			if (i == 0)
-				curlen = PAGE_SIZE - rqst->rq_rcv_buf.page_base;
-			else
-				curlen = PAGE_SIZE;
+			curlen = PAGE_SIZE - page_base;
 			if (curlen > copy_len)
 				curlen = copy_len;
 			dprintk("RPC:       %s: page %d"
 				" srcp 0x%p len %d curlen %d\n",
 				__func__, i, srcp, copy_len, curlen);
-			destp = kmap_atomic(rqst->rq_rcv_buf.pages[i],
-						KM_SKB_SUNRPC_DATA);
-			if (i == 0)
-				memcpy(destp + rqst->rq_rcv_buf.page_base,
-						srcp, curlen);
-			else
-				memcpy(destp, srcp, curlen);
-			flush_dcache_page(rqst->rq_rcv_buf.pages[i]);
+			destp = kmap_atomic(ppages[i], KM_SKB_SUNRPC_DATA);
+			memcpy(destp + page_base, srcp, curlen);
+			flush_dcache_page(ppages[i]);
 			kunmap_atomic(destp, KM_SKB_SUNRPC_DATA);
 			srcp += curlen;
 			copy_len -= curlen;
 			if (copy_len == 0)
 				break;
+			page_base = 0;
 		}
 		rqst->rq_rcv_buf.page_len = olen - copy_len;
 	} else
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index 5f4c7b3..d4297dc 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -144,6 +144,7 @@ rpcrdma_cq_async_error_upcall(struct ib_event *event, void *context)
 static inline
 void rpcrdma_event_process(struct ib_wc *wc)
 {
+	struct rpcrdma_mw *frmr;
 	struct rpcrdma_rep *rep =
 			(struct rpcrdma_rep *)(unsigned long) wc->wr_id;
 
@@ -154,15 +155,23 @@ void rpcrdma_event_process(struct ib_wc *wc)
 		return;
 
 	if (IB_WC_SUCCESS != wc->status) {
-		dprintk("RPC:       %s: %s WC status %X, connection lost\n",
-			__func__, (wc->opcode & IB_WC_RECV) ? "recv" : "send",
-			 wc->status);
+		dprintk("RPC:       %s: WC opcode %d status %X, connection lost\n",
+			__func__, wc->opcode, wc->status);
 		rep->rr_len = ~0U;
-		rpcrdma_schedule_tasklet(rep);
+		if (wc->opcode != IB_WC_FAST_REG_MR && wc->opcode != IB_WC_LOCAL_INV)
+			rpcrdma_schedule_tasklet(rep);
 		return;
 	}
 
 	switch (wc->opcode) {
+	case IB_WC_FAST_REG_MR:
+		frmr = (struct rpcrdma_mw *)(unsigned long)wc->wr_id;
+		frmr->r.frmr.state = FRMR_IS_VALID;
+		break;
+	case IB_WC_LOCAL_INV:
+		frmr = (struct rpcrdma_mw *)(unsigned long)wc->wr_id;
+		frmr->r.frmr.state = FRMR_IS_INVALID;
+		break;
 	case IB_WC_RECV:
 		rep->rr_len = wc->byte_len;
 		ib_dma_sync_single_for_cpu(
@@ -1450,6 +1459,12 @@ rpcrdma_map_one(struct rpcrdma_ia *ia, struct rpcrdma_mr_seg *seg, int writing)
 		seg->mr_dma = ib_dma_map_single(ia->ri_id->device,
 				seg->mr_offset,
 				seg->mr_dmalen, seg->mr_dir);
+	if (ib_dma_mapping_error(ia->ri_id->device, seg->mr_dma)) {
+		dprintk("RPC:       %s: mr_dma %llx mr_offset %p mr_dma_len %zu\n",
+			__func__,
+			(unsigned long long)seg->mr_dma,
+			seg->mr_offset, seg->mr_dmalen);
+	}
 }
 
 static void
@@ -1469,7 +1484,8 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
 			struct rpcrdma_xprt *r_xprt)
 {
 	struct rpcrdma_mr_seg *seg1 = seg;
-	struct ib_send_wr frmr_wr, *bad_wr;
+	struct ib_send_wr invalidate_wr, frmr_wr, *bad_wr, *post_wr;
+
 	u8 key;
 	int len, pageoff;
 	int i, rc;
@@ -1484,6 +1500,7 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
 		rpcrdma_map_one(ia, seg, writing);
 		seg1->mr_chunk.rl_mw->r.frmr.fr_pgl->page_list[i] = seg->mr_dma;
 		len += seg->mr_len;
+		BUG_ON(seg->mr_len > PAGE_SIZE);
 		++seg;
 		++i;
 		/* Check for holes */
@@ -1494,26 +1511,45 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg,
 	dprintk("RPC:       %s: Using frmr %p to map %d segments\n",
 		__func__, seg1->mr_chunk.rl_mw, i);
 
+	if (unlikely(seg1->mr_chunk.rl_mw->r.frmr.state == FRMR_IS_VALID)) {
+		dprintk("RPC:       %s: frmr %x left valid, posting invalidate.\n",
+			__func__,
+			seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey);
+		/* Invalidate before using. */
+		memset(&invalidate_wr, 0, sizeof invalidate_wr);
+		invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw;
+		invalidate_wr.next = &frmr_wr;
+		invalidate_wr.opcode = IB_WR_LOCAL_INV;
+		invalidate_wr.send_flags = IB_SEND_SIGNALED;
+		invalidate_wr.ex.invalidate_rkey =
+			seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
+		DECR_CQCOUNT(&r_xprt->rx_ep);
+		post_wr = &invalidate_wr;
+	} else
+		post_wr = &frmr_wr;
+
 	/* Bump the key */
 	key = (u8)(seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey & 0x000000FF);
 	ib_update_fast_reg_key(seg1->mr_chunk.rl_mw->r.frmr.fr_mr, ++key);
 
 	/* Prepare FRMR WR */
 	memset(&frmr_wr, 0, sizeof frmr_wr);
+	frmr_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw;
 	frmr_wr.opcode = IB_WR_FAST_REG_MR;
-	frmr_wr.send_flags = 0;			/* unsignaled */
+	frmr_wr.send_flags = IB_SEND_SIGNALED;
 	frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma;
 	frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl;
 	frmr_wr.wr.fast_reg.page_list_len = i;
 	frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT;
 	frmr_wr.wr.fast_reg.length = i << PAGE_SHIFT;
+	BUG_ON(frmr_wr.wr.fast_reg.length < len);
 	frmr_wr.wr.fast_reg.access_flags = (writing ?
 				IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE :
 				IB_ACCESS_REMOTE_READ);
 	frmr_wr.wr.fast_reg.rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
 	DECR_CQCOUNT(&r_xprt->rx_ep);
 
-	rc = ib_post_send(ia->ri_id->qp, &frmr_wr, &bad_wr);
+	rc = ib_post_send(ia->ri_id->qp, post_wr, &bad_wr);
 
 	if (rc) {
 		dprintk("RPC:       %s: failed ib_post_send for register,"
@@ -1542,8 +1578,9 @@ rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg,
 		rpcrdma_unmap_one(ia, seg++);
 
 	memset(&invalidate_wr, 0, sizeof invalidate_wr);
+	invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw;
 	invalidate_wr.opcode = IB_WR_LOCAL_INV;
-	invalidate_wr.send_flags = 0;			/* unsignaled */
+	invalidate_wr.send_flags = IB_SEND_SIGNALED;
 	invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey;
 	DECR_CQCOUNT(&r_xprt->rx_ep);
 
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index c7a7eba..cae761a 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -164,6 +164,7 @@ struct rpcrdma_mr_seg {		/* chunk descriptors */
 				struct {
 					struct ib_fast_reg_page_list *fr_pgl;
 					struct ib_mr *fr_mr;
+					enum { FRMR_IS_INVALID, FRMR_IS_VALID  } state;
 				} frmr;
 			} r;
 			struct list_head mw_list;
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig
index 0436927..2c5954b 100644
--- a/net/tipc/Kconfig
+++ b/net/tipc/Kconfig
@@ -29,18 +29,6 @@ config TIPC_ADVANCED
 	  Saying Y here will open some advanced configuration for TIPC.
 	  Most users do not need to bother; if unsure, just say N.
 
-config TIPC_NODES
-	int "Maximum number of nodes in a cluster"
-	depends on TIPC_ADVANCED
-	range 8 2047
-	default "255"
-	help
-	  Specifies how many nodes can be supported in a TIPC cluster.
-	  Can range from 8 to 2047 nodes; default is 255.
-
-	  Setting this to a smaller value saves some memory;
-	  setting it to higher allows for more nodes.
-
 config TIPC_PORTS
 	int "Maximum number of ports in a node"
 	depends on TIPC_ADVANCED
diff --git a/net/tipc/addr.c b/net/tipc/addr.c
index 88463d9..a6fdab3 100644
--- a/net/tipc/addr.c
+++ b/net/tipc/addr.c
@@ -2,7 +2,7 @@
  * net/tipc/addr.c: TIPC address utility routines
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,7 +41,7 @@
  * tipc_addr_domain_valid - validates a network domain address
  *
  * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>,
- * where Z, C, and N are non-zero and do not exceed the configured limits.
+ * where Z, C, and N are non-zero.
  *
  * Returns 1 if domain address is valid, otherwise 0
  */
@@ -51,10 +51,6 @@ int tipc_addr_domain_valid(u32 addr)
 	u32 n = tipc_node(addr);
 	u32 c = tipc_cluster(addr);
 	u32 z = tipc_zone(addr);
-	u32 max_nodes = tipc_max_nodes;
-
-	if (n > max_nodes)
-		return 0;
 
 	if (n && (!z || !c))
 		return 0;
@@ -66,8 +62,7 @@ int tipc_addr_domain_valid(u32 addr)
 /**
  * tipc_addr_node_valid - validates a proposed network address for this node
  *
- * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed
- * the configured limits.
+ * Accepts <Z.C.N>, where Z, C, and N are non-zero.
  *
  * Returns 1 if address can be used, otherwise 0
  */
@@ -81,9 +76,9 @@ int tipc_in_scope(u32 domain, u32 addr)
 {
 	if (!domain || (domain == addr))
 		return 1;
-	if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */
+	if (domain == tipc_cluster_mask(addr)) /* domain <Z.C.0> */
 		return 1;
-	if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */
+	if (domain == tipc_zone_mask(addr)) /* domain <Z.0.0> */
 		return 1;
 	return 0;
 }
diff --git a/net/tipc/addr.h b/net/tipc/addr.h
index 2490fad..8971aba 100644
--- a/net/tipc/addr.h
+++ b/net/tipc/addr.h
@@ -37,6 +37,16 @@
 #ifndef _TIPC_ADDR_H
 #define _TIPC_ADDR_H
 
+static inline u32 tipc_zone_mask(u32 addr)
+{
+	return addr & 0xff000000u;
+}
+
+static inline u32 tipc_cluster_mask(u32 addr)
+{
+	return addr & 0xfffff000u;
+}
+
 static inline int in_own_cluster(u32 addr)
 {
 	return !((addr ^ tipc_own_addr) >> 12);
@@ -49,14 +59,13 @@ static inline int in_own_cluster(u32 addr)
  * after a network hop.
  */
 
-static inline int addr_domain(int sc)
+static inline u32 addr_domain(u32 sc)
 {
 	if (likely(sc == TIPC_NODE_SCOPE))
 		return tipc_own_addr;
 	if (sc == TIPC_CLUSTER_SCOPE)
-		return tipc_addr(tipc_zone(tipc_own_addr),
-				 tipc_cluster(tipc_own_addr), 0);
-	return tipc_addr(tipc_zone(tipc_own_addr), 0, 0);
+		return tipc_cluster_mask(tipc_own_addr);
+	return tipc_zone_mask(tipc_own_addr);
 }
 
 int tipc_addr_domain_valid(u32);
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 70ab5ef..7dc1dc7 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2004-2006, Ericsson AB
  * Copyright (c) 2004, Intel Corporation.
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,8 +61,8 @@
  */
 
 struct bcbearer_pair {
-	struct bearer *primary;
-	struct bearer *secondary;
+	struct tipc_bearer *primary;
+	struct tipc_bearer *secondary;
 };
 
 /**
@@ -81,7 +81,7 @@ struct bcbearer_pair {
  */
 
 struct bcbearer {
-	struct bearer bearer;
+	struct tipc_bearer bearer;
 	struct media media;
 	struct bcbearer_pair bpairs[MAX_BEARERS];
 	struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
@@ -93,6 +93,7 @@ struct bcbearer {
  * struct bclink - link used for broadcast messages
  * @link: (non-standard) broadcast link structure
  * @node: (non-standard) node structure representing b'cast link's peer node
+ * @retransmit_to: node that most recently requested a retransmit
  *
  * Handles sequence numbering, fragmentation, bundling, etc.
  */
@@ -100,6 +101,7 @@ struct bcbearer {
 struct bclink {
 	struct link link;
 	struct tipc_node node;
+	struct tipc_node *retransmit_to;
 };
 
 
@@ -184,6 +186,17 @@ static int bclink_ack_allowed(u32 n)
 
 
 /**
+ * tipc_bclink_retransmit_to - get most recent node to request retransmission
+ *
+ * Called with bc_lock locked
+ */
+
+struct tipc_node *tipc_bclink_retransmit_to(void)
+{
+	return bclink->retransmit_to;
+}
+
+/**
  * bclink_retransmit_pkt - retransmit broadcast packets
  * @after: sequence number of last packet to *not* retransmit
  * @to: sequence number of last packet to retransmit
@@ -285,6 +298,7 @@ static void bclink_send_nack(struct tipc_node *n_ptr)
 		msg = buf_msg(buf);
 		tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG,
 			 INT_H_SIZE, n_ptr->addr);
+		msg_set_non_seq(msg, 1);
 		msg_set_mc_netid(msg, tipc_net_id);
 		msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in));
 		msg_set_bcgap_after(msg, n_ptr->bclink.gap_after);
@@ -405,8 +419,6 @@ int tipc_bclink_send_msg(struct sk_buff *buf)
 	else
 		bclink_set_last_sent();
 
-	if (bcl->out_queue_size > bcl->stats.max_queue_sz)
-		bcl->stats.max_queue_sz = bcl->out_queue_size;
 	bcl->stats.queue_sz_counts++;
 	bcl->stats.accu_queue_sz += bcl->out_queue_size;
 
@@ -444,10 +456,9 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
 			tipc_node_unlock(node);
 			spin_lock_bh(&bc_lock);
 			bcl->stats.recv_nacks++;
-			bcl->owner->next = node;   /* remember requestor */
+			bclink->retransmit_to = node;
 			bclink_retransmit_pkt(msg_bcgap_after(msg),
 					      msg_bcgap_to(msg));
-			bcl->owner->next = NULL;
 			spin_unlock_bh(&bc_lock);
 		} else {
 			tipc_bclink_peek_nack(msg_destnode(msg),
@@ -574,8 +585,8 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
 	bcbearer->remains = tipc_bcast_nmap;
 
 	for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
-		struct bearer *p = bcbearer->bpairs[bp_index].primary;
-		struct bearer *s = bcbearer->bpairs[bp_index].secondary;
+		struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary;
+		struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary;
 
 		if (!p)
 			break;	/* no more bearers to try */
@@ -584,11 +595,11 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
 		if (bcbearer->remains_new.count == bcbearer->remains.count)
 			continue;	/* bearer pair doesn't add anything */
 
-		if (p->publ.blocked ||
-		    p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) {
+		if (p->blocked ||
+		    p->media->send_msg(buf, p, &p->media->bcast_addr)) {
 			/* unable to send on primary bearer */
-			if (!s || s->publ.blocked ||
-			    s->media->send_msg(buf, &s->publ,
+			if (!s || s->blocked ||
+			    s->media->send_msg(buf, s,
 					       &s->media->bcast_addr)) {
 				/* unable to send on either bearer */
 				continue;
@@ -633,7 +644,7 @@ void tipc_bcbearer_sort(void)
 	memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp));
 
 	for (b_index = 0; b_index < MAX_BEARERS; b_index++) {
-		struct bearer *b = &tipc_bearers[b_index];
+		struct tipc_bearer *b = &tipc_bearers[b_index];
 
 		if (!b->active || !b->nodes.count)
 			continue;
@@ -682,12 +693,12 @@ void tipc_bcbearer_sort(void)
 
 void tipc_bcbearer_push(void)
 {
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 
 	spin_lock_bh(&bc_lock);
 	b_ptr = &bcbearer->bearer;
-	if (b_ptr->publ.blocked) {
-		b_ptr->publ.blocked = 0;
+	if (b_ptr->blocked) {
+		b_ptr->blocked = 0;
 		tipc_bearer_lock_push(b_ptr);
 	}
 	spin_unlock_bh(&bc_lock);
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 51f8c53..500c97f 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -2,7 +2,7 @@
  * net/tipc/bcast.h: Include file for TIPC broadcast code
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -90,6 +90,7 @@ void tipc_port_list_free(struct port_list *pl_ptr);
 
 int  tipc_bclink_init(void);
 void tipc_bclink_stop(void);
+struct tipc_node *tipc_bclink_retransmit_to(void);
 void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked);
 int  tipc_bclink_send_msg(struct sk_buff *buf);
 void tipc_bclink_recv_pkt(struct sk_buff *buf);
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 837b7a4..411719f 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -2,7 +2,7 @@
  * net/tipc/bearer.c: TIPC bearer code
  *
  * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2004-2006, Wind River Systems
+ * Copyright (c) 2004-2006, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,7 @@
 static struct media media_list[MAX_MEDIA];
 static u32 media_count;
 
-struct bearer tipc_bearers[MAX_BEARERS];
+struct tipc_bearer tipc_bearers[MAX_BEARERS];
 
 /**
  * media_name_valid - validate media name
@@ -158,7 +158,6 @@ int  tipc_register_media(u32 media_type,
 	m_ptr->disable_bearer = disable;
 	m_ptr->addr2str = addr2str;
 	memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
-	m_ptr->bcast = 1;
 	strcpy(m_ptr->name, name);
 	m_ptr->priority = bearer_priority;
 	m_ptr->tolerance = link_tolerance;
@@ -278,13 +277,13 @@ static int bearer_name_validate(const char *name,
  * bearer_find - locates bearer object with matching bearer name
  */
 
-static struct bearer *bearer_find(const char *name)
+static struct tipc_bearer *bearer_find(const char *name)
 {
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	u32 i;
 
 	for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
-		if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
+		if (b_ptr->active && (!strcmp(b_ptr->name, name)))
 			return b_ptr;
 	}
 	return NULL;
@@ -294,16 +293,16 @@ static struct bearer *bearer_find(const char *name)
  * tipc_bearer_find_interface - locates bearer object with matching interface name
  */
 
-struct bearer *tipc_bearer_find_interface(const char *if_name)
+struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
 {
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	char *b_if_name;
 	u32 i;
 
 	for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 		if (!b_ptr->active)
 			continue;
-		b_if_name = strchr(b_ptr->publ.name, ':') + 1;
+		b_if_name = strchr(b_ptr->name, ':') + 1;
 		if (!strcmp(b_if_name, if_name))
 			return b_ptr;
 	}
@@ -318,7 +317,7 @@ struct sk_buff *tipc_bearer_get_names(void)
 {
 	struct sk_buff *buf;
 	struct media *m_ptr;
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	int i, j;
 
 	buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
@@ -331,8 +330,8 @@ struct sk_buff *tipc_bearer_get_names(void)
 			b_ptr = &tipc_bearers[j];
 			if (b_ptr->active && (b_ptr->media == m_ptr)) {
 				tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
-						    b_ptr->publ.name,
-						    strlen(b_ptr->publ.name) + 1);
+						    b_ptr->name,
+						    strlen(b_ptr->name) + 1);
 			}
 		}
 	}
@@ -340,14 +339,14 @@ struct sk_buff *tipc_bearer_get_names(void)
 	return buf;
 }
 
-void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest)
+void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest)
 {
 	tipc_nmap_add(&b_ptr->nodes, dest);
 	tipc_disc_update_link_req(b_ptr->link_req);
 	tipc_bcbearer_sort();
 }
 
-void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest)
+void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest)
 {
 	tipc_nmap_remove(&b_ptr->nodes, dest);
 	tipc_disc_update_link_req(b_ptr->link_req);
@@ -362,12 +361,12 @@ void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest)
  * bearer.lock must be taken before calling
  * Returns binary true(1) ore false(0)
  */
-static int bearer_push(struct bearer *b_ptr)
+static int bearer_push(struct tipc_bearer *b_ptr)
 {
 	u32 res = 0;
 	struct link *ln, *tln;
 
-	if (b_ptr->publ.blocked)
+	if (b_ptr->blocked)
 		return 0;
 
 	while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
@@ -382,13 +381,13 @@ static int bearer_push(struct bearer *b_ptr)
 	return list_empty(&b_ptr->cong_links);
 }
 
-void tipc_bearer_lock_push(struct bearer *b_ptr)
+void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
 {
 	int res;
 
-	spin_lock_bh(&b_ptr->publ.lock);
+	spin_lock_bh(&b_ptr->lock);
 	res = bearer_push(b_ptr);
-	spin_unlock_bh(&b_ptr->publ.lock);
+	spin_unlock_bh(&b_ptr->lock);
 	if (res)
 		tipc_bcbearer_push();
 }
@@ -398,16 +397,14 @@ void tipc_bearer_lock_push(struct bearer *b_ptr)
  * Interrupt enabling new requests after bearer congestion or blocking:
  * See bearer_send().
  */
-void tipc_continue(struct tipc_bearer *tb_ptr)
+void tipc_continue(struct tipc_bearer *b_ptr)
 {
-	struct bearer *b_ptr = (struct bearer *)tb_ptr;
-
-	spin_lock_bh(&b_ptr->publ.lock);
+	spin_lock_bh(&b_ptr->lock);
 	b_ptr->continue_count++;
 	if (!list_empty(&b_ptr->cong_links))
 		tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
-	b_ptr->publ.blocked = 0;
-	spin_unlock_bh(&b_ptr->publ.lock);
+	b_ptr->blocked = 0;
+	spin_unlock_bh(&b_ptr->lock);
 }
 
 /*
@@ -418,7 +415,7 @@ void tipc_continue(struct tipc_bearer *tb_ptr)
  * bearer.lock is busy
  */
 
-static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
+static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr, struct link *l_ptr)
 {
 	list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
 }
@@ -431,11 +428,11 @@ static void tipc_bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_p
  * bearer.lock is free
  */
 
-void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
+void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct link *l_ptr)
 {
-	spin_lock_bh(&b_ptr->publ.lock);
+	spin_lock_bh(&b_ptr->lock);
 	tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
-	spin_unlock_bh(&b_ptr->publ.lock);
+	spin_unlock_bh(&b_ptr->lock);
 }
 
 
@@ -444,18 +441,18 @@ void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
  * and if there is, try to resolve it before returning.
  * 'tipc_net_lock' is read_locked when this function is called
  */
-int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
+int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, struct link *l_ptr)
 {
 	int res = 1;
 
 	if (list_empty(&b_ptr->cong_links))
 		return 1;
-	spin_lock_bh(&b_ptr->publ.lock);
+	spin_lock_bh(&b_ptr->lock);
 	if (!bearer_push(b_ptr)) {
 		tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
 		res = 0;
 	}
-	spin_unlock_bh(&b_ptr->publ.lock);
+	spin_unlock_bh(&b_ptr->lock);
 	return res;
 }
 
@@ -463,9 +460,9 @@ int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
  * tipc_bearer_congested - determines if bearer is currently congested
  */
 
-int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
+int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr)
 {
-	if (unlikely(b_ptr->publ.blocked))
+	if (unlikely(b_ptr->blocked))
 		return 1;
 	if (likely(list_empty(&b_ptr->cong_links)))
 		return 0;
@@ -476,9 +473,9 @@ int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr)
  * tipc_enable_bearer - enable bearer with the given name
  */
 
-int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
+int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
 {
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	struct media *m_ptr;
 	struct bearer_name b_name;
 	char addr_string[16];
@@ -496,9 +493,9 @@ int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
 		warn("Bearer <%s> rejected, illegal name\n", name);
 		return -EINVAL;
 	}
-	if (!tipc_addr_domain_valid(bcast_scope) ||
-	    !tipc_in_scope(bcast_scope, tipc_own_addr)) {
-		warn("Bearer <%s> rejected, illegal broadcast scope\n", name);
+	if (!tipc_addr_domain_valid(disc_domain) ||
+	    !tipc_in_scope(disc_domain, tipc_own_addr)) {
+		warn("Bearer <%s> rejected, illegal discovery domain\n", name);
 		return -EINVAL;
 	}
 	if ((priority < TIPC_MIN_LINK_PRI ||
@@ -528,7 +525,7 @@ restart:
 			bearer_id = i;
 			continue;
 		}
-		if (!strcmp(name, tipc_bearers[i].publ.name)) {
+		if (!strcmp(name, tipc_bearers[i].name)) {
 			warn("Bearer <%s> rejected, already enabled\n", name);
 			goto failed;
 		}
@@ -551,8 +548,8 @@ restart:
 	}
 
 	b_ptr = &tipc_bearers[bearer_id];
-	strcpy(b_ptr->publ.name, name);
-	res = m_ptr->enable_bearer(&b_ptr->publ);
+	strcpy(b_ptr->name, name);
+	res = m_ptr->enable_bearer(b_ptr);
 	if (res) {
 		warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res);
 		goto failed;
@@ -562,18 +559,15 @@ restart:
 	b_ptr->media = m_ptr;
 	b_ptr->net_plane = bearer_id + 'A';
 	b_ptr->active = 1;
-	b_ptr->detect_scope = bcast_scope;
 	b_ptr->priority = priority;
 	INIT_LIST_HEAD(&b_ptr->cong_links);
 	INIT_LIST_HEAD(&b_ptr->links);
-	if (m_ptr->bcast) {
-		b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
-							  bcast_scope, 2);
-	}
-	spin_lock_init(&b_ptr->publ.lock);
+	b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
+						  disc_domain);
+	spin_lock_init(&b_ptr->lock);
 	write_unlock_bh(&tipc_net_lock);
 	info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
-	     name, tipc_addr_string_fill(addr_string, bcast_scope), priority);
+	     name, tipc_addr_string_fill(addr_string, disc_domain), priority);
 	return 0;
 failed:
 	write_unlock_bh(&tipc_net_lock);
@@ -587,7 +581,7 @@ failed:
 
 int tipc_block_bearer(const char *name)
 {
-	struct bearer *b_ptr = NULL;
+	struct tipc_bearer *b_ptr = NULL;
 	struct link *l_ptr;
 	struct link *temp_l_ptr;
 
@@ -600,8 +594,8 @@ int tipc_block_bearer(const char *name)
 	}
 
 	info("Blocking bearer <%s>\n", name);
-	spin_lock_bh(&b_ptr->publ.lock);
-	b_ptr->publ.blocked = 1;
+	spin_lock_bh(&b_ptr->lock);
+	b_ptr->blocked = 1;
 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
 		struct tipc_node *n_ptr = l_ptr->owner;
 
@@ -609,7 +603,7 @@ int tipc_block_bearer(const char *name)
 		tipc_link_reset(l_ptr);
 		spin_unlock_bh(&n_ptr->lock);
 	}
-	spin_unlock_bh(&b_ptr->publ.lock);
+	spin_unlock_bh(&b_ptr->lock);
 	read_unlock_bh(&tipc_net_lock);
 	return 0;
 }
@@ -620,27 +614,27 @@ int tipc_block_bearer(const char *name)
  * Note: This routine assumes caller holds tipc_net_lock.
  */
 
-static void bearer_disable(struct bearer *b_ptr)
+static void bearer_disable(struct tipc_bearer *b_ptr)
 {
 	struct link *l_ptr;
 	struct link *temp_l_ptr;
 
-	info("Disabling bearer <%s>\n", b_ptr->publ.name);
+	info("Disabling bearer <%s>\n", b_ptr->name);
 	tipc_disc_stop_link_req(b_ptr->link_req);
-	spin_lock_bh(&b_ptr->publ.lock);
+	spin_lock_bh(&b_ptr->lock);
 	b_ptr->link_req = NULL;
-	b_ptr->publ.blocked = 1;
-	b_ptr->media->disable_bearer(&b_ptr->publ);
+	b_ptr->blocked = 1;
+	b_ptr->media->disable_bearer(b_ptr);
 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
 		tipc_link_delete(l_ptr);
 	}
-	spin_unlock_bh(&b_ptr->publ.lock);
-	memset(b_ptr, 0, sizeof(struct bearer));
+	spin_unlock_bh(&b_ptr->lock);
+	memset(b_ptr, 0, sizeof(struct tipc_bearer));
 }
 
 int tipc_disable_bearer(const char *name)
 {
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	int res;
 
 	write_lock_bh(&tipc_net_lock);
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 85f451d..31d6172 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -2,7 +2,7 @@
  * net/tipc/bearer.h: Include file for TIPC bearer code
  *
  * Copyright (c) 1996-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -61,26 +61,7 @@ struct tipc_media_addr {
 	} dev_addr;
 };
 
-/**
- * struct tipc_bearer - TIPC bearer info available to media code
- * @usr_handle: pointer to additional media-specific information about bearer
- * @mtu: max packet size bearer can support
- * @blocked: non-zero if bearer is blocked
- * @lock: spinlock for controlling access to bearer
- * @addr: media-specific address associated with bearer
- * @name: bearer name (format = media:interface)
- *
- * Note: TIPC initializes "name" and "lock" fields; media code is responsible
- * for initialization all other fields when a bearer is enabled.
- */
-struct tipc_bearer {
-	void *usr_handle;
-	u32 mtu;
-	int blocked;
-	spinlock_t lock;
-	struct tipc_media_addr addr;
-	char name[TIPC_MAX_BEARER_NAME];
-};
+struct tipc_bearer;
 
 /**
  * struct media - TIPC media information available to internal users
@@ -89,7 +70,6 @@ struct tipc_bearer {
  * @disable_bearer: routine which disables a bearer
  * @addr2str: routine which converts bearer's address to string form
  * @bcast_addr: media address used in broadcasting
- * @bcast: non-zero if media supports broadcasting [currently mandatory]
  * @priority: default link (and bearer) priority
  * @tolerance: default time (in ms) before declaring link failure
  * @window: default window (in packets) before declaring link congestion
@@ -106,7 +86,6 @@ struct media {
 	char *(*addr2str)(struct tipc_media_addr *a,
 			  char *str_buf, int str_size);
 	struct tipc_media_addr bcast_addr;
-	int bcast;
 	u32 priority;
 	u32 tolerance;
 	u32 window;
@@ -115,11 +94,15 @@ struct media {
 };
 
 /**
- * struct bearer - TIPC bearer information available to internal users
- * @publ: bearer information available to privileged users
+ * struct tipc_bearer - TIPC bearer structure
+ * @usr_handle: pointer to additional media-specific information about bearer
+ * @mtu: max packet size bearer can support
+ * @blocked: non-zero if bearer is blocked
+ * @lock: spinlock for controlling access to bearer
+ * @addr: media-specific address associated with bearer
+ * @name: bearer name (format = media:interface)
  * @media: ptr to media structure associated with bearer
  * @priority: default link priority for bearer
- * @detect_scope: network address mask used during automatic link creation
  * @identity: array index of this bearer within TIPC bearer array
  * @link_req: ptr to (optional) structure making periodic link setup requests
  * @links: list of non-congested links associated with bearer
@@ -128,13 +111,20 @@ struct media {
  * @active: non-zero if bearer structure is represents a bearer
  * @net_plane: network plane ('A' through 'H') currently associated with bearer
  * @nodes: indicates which nodes in cluster can be reached through bearer
+ *
+ * Note: media-specific code is responsible for initialization of the fields
+ * indicated below when a bearer is enabled; TIPC's generic bearer code takes
+ * care of initializing all other fields.
  */
-
-struct bearer {
-	struct tipc_bearer publ;
+struct tipc_bearer {
+	void *usr_handle;			/* initalized by media */
+	u32 mtu;				/* initalized by media */
+	int blocked;				/* initalized by media */
+	struct tipc_media_addr addr;		/* initalized by media */
+	char name[TIPC_MAX_BEARER_NAME];
+	spinlock_t lock;
 	struct media *media;
 	u32 priority;
-	u32 detect_scope;
 	u32 identity;
 	struct link_req *link_req;
 	struct list_head links;
@@ -152,7 +142,7 @@ struct bearer_name {
 
 struct link;
 
-extern struct bearer tipc_bearers[];
+extern struct tipc_bearer tipc_bearers[];
 
 /*
  * TIPC routines available to supported media types
@@ -173,7 +163,7 @@ void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
 int  tipc_block_bearer(const char *name);
 void tipc_continue(struct tipc_bearer *tb_ptr);
 
-int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
+int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
 int tipc_disable_bearer(const char *name);
 
 /*
@@ -186,14 +176,14 @@ void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
 struct sk_buff *tipc_media_get_names(void);
 
 struct sk_buff *tipc_bearer_get_names(void);
-void tipc_bearer_add_dest(struct bearer *b_ptr, u32 dest);
-void tipc_bearer_remove_dest(struct bearer *b_ptr, u32 dest);
-void tipc_bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
-struct bearer *tipc_bearer_find_interface(const char *if_name);
-int tipc_bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
-int tipc_bearer_congested(struct bearer *b_ptr, struct link *l_ptr);
+void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
+void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
+void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct link *l_ptr);
+struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
+int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, struct link *l_ptr);
+int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr);
 void tipc_bearer_stop(void);
-void tipc_bearer_lock_push(struct bearer *b_ptr);
+void tipc_bearer_lock_push(struct tipc_bearer *b_ptr);
 
 
 /**
@@ -214,10 +204,11 @@ void tipc_bearer_lock_push(struct bearer *b_ptr);
  * and let TIPC's link code deal with the undelivered message.
  */
 
-static inline int tipc_bearer_send(struct bearer *b_ptr, struct sk_buff *buf,
+static inline int tipc_bearer_send(struct tipc_bearer *b_ptr,
+				   struct sk_buff *buf,
 				   struct tipc_media_addr *dest)
 {
-	return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest);
+	return !b_ptr->media->send_msg(buf, b_ptr, dest);
 }
 
 #endif	/* _TIPC_BEARER_H */
diff --git a/net/tipc/config.c b/net/tipc/config.c
index e16750d..b25a396 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -2,7 +2,7 @@
  * net/tipc/config.c: TIPC configuration management code
  *
  * Copyright (c) 2002-2006, Ericsson AB
- * Copyright (c) 2004-2007, Wind River Systems
+ * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -148,7 +148,7 @@ static struct sk_buff *cfg_enable_bearer(void)
 
 	args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area);
 	if (tipc_enable_bearer(args->name,
-			       ntohl(args->detect_scope),
+			       ntohl(args->disc_domain),
 			       ntohl(args->priority)))
 		return tipc_cfg_reply_error_string("unable to enable bearer");
 
@@ -260,25 +260,6 @@ static struct sk_buff *cfg_set_max_ports(void)
 	return tipc_cfg_reply_none();
 }
 
-static struct sk_buff *cfg_set_max_nodes(void)
-{
-	u32 value;
-
-	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
-		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
-	value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area));
-	if (value == tipc_max_nodes)
-		return tipc_cfg_reply_none();
-	if (value != delimit(value, 8, 2047))
-		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
-						   " (max nodes must be 8-2047)");
-	if (tipc_mode == TIPC_NET_MODE)
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-			" (cannot change max nodes once TIPC has joined a network)");
-	tipc_max_nodes = value;
-	return tipc_cfg_reply_none();
-}
-
 static struct sk_buff *cfg_set_netid(void)
 {
 	u32 value;
@@ -397,9 +378,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
 	case TIPC_CMD_SET_MAX_SUBSCR:
 		rep_tlv_buf = cfg_set_max_subscriptions();
 		break;
-	case TIPC_CMD_SET_MAX_NODES:
-		rep_tlv_buf = cfg_set_max_nodes();
-		break;
 	case TIPC_CMD_SET_NETID:
 		rep_tlv_buf = cfg_set_netid();
 		break;
@@ -415,9 +393,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
 	case TIPC_CMD_GET_MAX_SUBSCR:
 		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions);
 		break;
-	case TIPC_CMD_GET_MAX_NODES:
-		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_nodes);
-		break;
 	case TIPC_CMD_GET_NETID:
 		rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id);
 		break;
@@ -431,6 +406,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area
 	case TIPC_CMD_GET_MAX_SLAVES:
 	case TIPC_CMD_SET_MAX_CLUSTERS:
 	case TIPC_CMD_GET_MAX_CLUSTERS:
+	case TIPC_CMD_SET_MAX_NODES:
+	case TIPC_CMD_GET_MAX_NODES:
 		rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 							  " (obsolete command)");
 		break;
diff --git a/net/tipc/core.c b/net/tipc/core.c
index e071579..c9a73e7 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -2,7 +2,7 @@
  * net/tipc/core.c: TIPC module code
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2005-2006, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,10 +41,6 @@
 #include "config.h"
 
 
-#ifndef CONFIG_TIPC_NODES
-#define CONFIG_TIPC_NODES 255
-#endif
-
 #ifndef CONFIG_TIPC_PORTS
 #define CONFIG_TIPC_PORTS 8191
 #endif
@@ -57,7 +53,6 @@
 
 int tipc_mode = TIPC_NOT_RUNNING;
 int tipc_random;
-atomic_t tipc_user_count = ATOMIC_INIT(0);
 
 const char tipc_alphabet[] =
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.";
@@ -65,7 +60,6 @@ const char tipc_alphabet[] =
 /* configurable TIPC parameters */
 
 u32 tipc_own_addr;
-int tipc_max_nodes;
 int tipc_max_ports;
 int tipc_max_subscriptions;
 int tipc_max_publications;
@@ -193,7 +187,6 @@ static int __init tipc_init(void)
 	tipc_max_publications = 10000;
 	tipc_max_subscriptions = 2000;
 	tipc_max_ports = CONFIG_TIPC_PORTS;
-	tipc_max_nodes = CONFIG_TIPC_NODES;
 	tipc_net_id = 4711;
 
 	res = tipc_core_start();
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 9971585..436dda1 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -2,7 +2,7 @@
  * net/tipc/core.h: Include file for TIPC global declarations
  *
  * Copyright (c) 2005-2006, Ericsson AB
- * Copyright (c) 2005-2007, Wind River Systems
+ * Copyright (c) 2005-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -147,7 +147,6 @@ void tipc_msg_dbg(struct print_buf *, struct tipc_msg *, const char *);
  */
 
 extern u32 tipc_own_addr;
-extern int tipc_max_nodes;
 extern int tipc_max_ports;
 extern int tipc_max_subscriptions;
 extern int tipc_max_publications;
@@ -161,7 +160,6 @@ extern int tipc_remote_management;
 extern int tipc_mode;
 extern int tipc_random;
 extern const char tipc_alphabet[];
-extern atomic_t tipc_user_count;
 
 
 /*
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index fa026bd..491eff5 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -2,7 +2,7 @@
  * net/tipc/discover.c
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2005-2006, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
  * @timer_intv: current interval between requests (in ms)
  */
 struct link_req {
-	struct bearer *bearer;
+	struct tipc_bearer *bearer;
 	struct tipc_media_addr dest;
 	struct sk_buff *buf;
 	struct timer_list timer;
@@ -67,27 +67,24 @@ struct link_req {
 /**
  * tipc_disc_init_msg - initialize a link setup message
  * @type: message type (request or response)
- * @req_links: number of links associated with message
  * @dest_domain: network domain of node(s) which should respond to message
  * @b_ptr: ptr to bearer issuing message
  */
 
 static struct sk_buff *tipc_disc_init_msg(u32 type,
-					  u32 req_links,
 					  u32 dest_domain,
-					  struct bearer *b_ptr)
+					  struct tipc_bearer *b_ptr)
 {
-	struct sk_buff *buf = tipc_buf_acquire(DSC_H_SIZE);
+	struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE);
 	struct tipc_msg *msg;
 
 	if (buf) {
 		msg = buf_msg(buf);
-		tipc_msg_init(msg, LINK_CONFIG, type, DSC_H_SIZE, dest_domain);
+		tipc_msg_init(msg, LINK_CONFIG, type, INT_H_SIZE, dest_domain);
 		msg_set_non_seq(msg, 1);
-		msg_set_req_links(msg, req_links);
 		msg_set_dest_domain(msg, dest_domain);
 		msg_set_bc_netid(msg, tipc_net_id);
-		msg_set_media_addr(msg, &b_ptr->publ.addr);
+		msg_set_media_addr(msg, &b_ptr->addr);
 	}
 	return buf;
 }
@@ -99,7 +96,7 @@ static struct sk_buff *tipc_disc_init_msg(u32 type,
  * @media_addr: media address advertised by duplicated node
  */
 
-static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
+static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
 			    struct tipc_media_addr *media_addr)
 {
 	char node_addr_str[16];
@@ -111,7 +108,7 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
 	tipc_media_addr_printf(&pb, media_addr);
 	tipc_printbuf_validate(&pb);
 	warn("Duplicate %s using %s seen on <%s>\n",
-	     node_addr_str, media_addr_str, b_ptr->publ.name);
+	     node_addr_str, media_addr_str, b_ptr->name);
 }
 
 /**
@@ -120,19 +117,23 @@ static void disc_dupl_alert(struct bearer *b_ptr, u32 node_addr,
  * @b_ptr: bearer that message arrived on
  */
 
-void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
+void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
 {
+	struct tipc_node *n_ptr;
 	struct link *link;
-	struct tipc_media_addr media_addr;
+	struct tipc_media_addr media_addr, *addr;
+	struct sk_buff *rbuf;
 	struct tipc_msg *msg = buf_msg(buf);
 	u32 dest = msg_dest_domain(msg);
 	u32 orig = msg_prevnode(msg);
 	u32 net_id = msg_bc_netid(msg);
 	u32 type = msg_type(msg);
+	int link_fully_up;
 
 	msg_get_media_addr(msg, &media_addr);
 	buf_discard(buf);
 
+	/* Validate discovery message from requesting node */
 	if (net_id != tipc_net_id)
 		return;
 	if (!tipc_addr_domain_valid(dest))
@@ -140,63 +141,76 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr)
 	if (!tipc_addr_node_valid(orig))
 		return;
 	if (orig == tipc_own_addr) {
-		if (memcmp(&media_addr, &b_ptr->publ.addr, sizeof(media_addr)))
+		if (memcmp(&media_addr, &b_ptr->addr, sizeof(media_addr)))
 			disc_dupl_alert(b_ptr, tipc_own_addr, &media_addr);
 		return;
 	}
 	if (!tipc_in_scope(dest, tipc_own_addr))
 		return;
-	if (in_own_cluster(orig)) {
-		/* Always accept link here */
-		struct sk_buff *rbuf;
-		struct tipc_media_addr *addr;
-		struct tipc_node *n_ptr = tipc_node_find(orig);
-		int link_fully_up;
-
-		if (n_ptr == NULL) {
-			n_ptr = tipc_node_create(orig);
-			if (!n_ptr)
-				return;
-		}
-		spin_lock_bh(&n_ptr->lock);
-
-		/* Don't talk to neighbor during cleanup after last session */
+	if (!in_own_cluster(orig))
+		return;
 
-		if (n_ptr->cleanup_required) {
-			spin_unlock_bh(&n_ptr->lock);
+	/* Locate structure corresponding to requesting node */
+	n_ptr = tipc_node_find(orig);
+	if (!n_ptr) {
+		n_ptr = tipc_node_create(orig);
+		if (!n_ptr)
 			return;
-		}
+	}
+	tipc_node_lock(n_ptr);
+
+	/* Don't talk to neighbor during cleanup after last session */
+	if (n_ptr->cleanup_required) {
+		tipc_node_unlock(n_ptr);
+		return;
+	}
+
+	link = n_ptr->links[b_ptr->identity];
 
-		link = n_ptr->links[b_ptr->identity];
+	/* Create a link endpoint for this bearer, if necessary */
+	if (!link) {
+		link = tipc_link_create(n_ptr, b_ptr, &media_addr);
 		if (!link) {
-			link = tipc_link_create(b_ptr, orig, &media_addr);
-			if (!link) {
-				spin_unlock_bh(&n_ptr->lock);
-				return;
-			}
-		}
-		addr = &link->media_addr;
-		if (memcmp(addr, &media_addr, sizeof(*addr))) {
-			if (tipc_link_is_up(link) || (!link->started)) {
-				disc_dupl_alert(b_ptr, orig, &media_addr);
-				spin_unlock_bh(&n_ptr->lock);
-				return;
-			}
-			warn("Resetting link <%s>, peer interface address changed\n",
-			     link->name);
-			memcpy(addr, &media_addr, sizeof(*addr));
-			tipc_link_reset(link);
+			tipc_node_unlock(n_ptr);
+			return;
 		}
-		link_fully_up = link_working_working(link);
-		spin_unlock_bh(&n_ptr->lock);
-		if ((type == DSC_RESP_MSG) || link_fully_up)
+	}
+
+	/*
+	 * Ensure requesting node's media address is correct
+	 *
+	 * If media address doesn't match and the link is working, reject the
+	 * request (must be from a duplicate node).
+	 *
+	 * If media address doesn't match and the link is not working, accept
+	 * the new media address and reset the link to ensure it starts up
+	 * cleanly.
+	 */
+	addr = &link->media_addr;
+	if (memcmp(addr, &media_addr, sizeof(*addr))) {
+		if (tipc_link_is_up(link) || (!link->started)) {
+			disc_dupl_alert(b_ptr, orig, &media_addr);
+			tipc_node_unlock(n_ptr);
 			return;
-		rbuf = tipc_disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr);
-		if (rbuf != NULL) {
-			b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr);
+		}
+		warn("Resetting link <%s>, peer interface address changed\n",
+		     link->name);
+		memcpy(addr, &media_addr, sizeof(*addr));
+		tipc_link_reset(link);
+	}
+
+	/* Accept discovery message & send response, if necessary */
+	link_fully_up = link_working_working(link);
+
+	if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {
+		rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
+		if (rbuf) {
+			b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
 			buf_discard(rbuf);
 		}
 	}
+
+	tipc_node_unlock(n_ptr);
 }
 
 /**
@@ -249,9 +263,9 @@ void tipc_disc_update_link_req(struct link_req *req)
 
 static void disc_timeout(struct link_req *req)
 {
-	spin_lock_bh(&req->bearer->publ.lock);
+	spin_lock_bh(&req->bearer->lock);
 
-	req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest);
+	req->bearer->media->send_msg(req->buf, req->bearer, &req->dest);
 
 	if ((req->timer_intv == TIPC_LINK_REQ_SLOW) ||
 	    (req->timer_intv == TIPC_LINK_REQ_FAST)) {
@@ -266,7 +280,7 @@ static void disc_timeout(struct link_req *req)
 	}
 	k_start_timer(&req->timer, req->timer_intv);
 
-	spin_unlock_bh(&req->bearer->publ.lock);
+	spin_unlock_bh(&req->bearer->lock);
 }
 
 /**
@@ -274,15 +288,13 @@ static void disc_timeout(struct link_req *req)
  * @b_ptr: ptr to bearer issuing requests
  * @dest: destination address for request messages
  * @dest_domain: network domain of node(s) which should respond to message
- * @req_links: max number of desired links
  *
  * Returns pointer to link request structure, or NULL if unable to create.
  */
 
-struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
+struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr,
 					 const struct tipc_media_addr *dest,
-					 u32 dest_domain,
-					 u32 req_links)
+					 u32 dest_domain)
 {
 	struct link_req *req;
 
@@ -290,7 +302,7 @@ struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
 	if (!req)
 		return NULL;
 
-	req->buf = tipc_disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr);
+	req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr);
 	if (!req->buf) {
 		kfree(req);
 		return NULL;
diff --git a/net/tipc/discover.h b/net/tipc/discover.h
index d2c3cff..e48a167 100644
--- a/net/tipc/discover.h
+++ b/net/tipc/discover.h
@@ -2,7 +2,7 @@
  * net/tipc/discover.h
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,13 +39,12 @@
 
 struct link_req;
 
-struct link_req *tipc_disc_init_link_req(struct bearer *b_ptr,
+struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr,
 					 const struct tipc_media_addr *dest,
-					 u32 dest_domain,
-					 u32 req_links);
+					 u32 dest_domain);
 void tipc_disc_update_link_req(struct link_req *req);
 void tipc_disc_stop_link_req(struct link_req *req);
 
-void tipc_disc_recv_msg(struct sk_buff *buf, struct bearer *b_ptr);
+void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr);
 
 #endif
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 18702f5..43639ff 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -2,7 +2,7 @@
  * net/tipc/link.c: TIPC link code
  *
  * Copyright (c) 1996-2007, Ericsson AB
- * Copyright (c) 2004-2007, Wind River Systems
+ * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -90,7 +90,7 @@ static void link_handle_out_of_seq_msg(struct link *l_ptr,
 static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf);
 static int  link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf);
 static void link_set_supervision_props(struct link *l_ptr, u32 tolerance);
-static int  link_send_sections_long(struct port *sender,
+static int  link_send_sections_long(struct tipc_port *sender,
 				    struct iovec const *msg_sect,
 				    u32 num_sect, u32 destnode);
 static void link_check_defragm_bufs(struct link *l_ptr);
@@ -113,7 +113,7 @@ static void link_init_max_pkt(struct link *l_ptr)
 {
 	u32 max_pkt;
 
-	max_pkt = (l_ptr->b_ptr->publ.mtu & ~3);
+	max_pkt = (l_ptr->b_ptr->mtu & ~3);
 	if (max_pkt > MAX_MSG_SIZE)
 		max_pkt = MAX_MSG_SIZE;
 
@@ -246,9 +246,6 @@ static void link_timeout(struct link *l_ptr)
 	l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size;
 	l_ptr->stats.queue_sz_counts++;
 
-	if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz)
-		l_ptr->stats.max_queue_sz = l_ptr->out_queue_size;
-
 	if (l_ptr->first_out) {
 		struct tipc_msg *msg = buf_msg(l_ptr->first_out);
 		u32 length = msg_size(msg);
@@ -296,19 +293,35 @@ static void link_set_timer(struct link *l_ptr, u32 time)
 
 /**
  * tipc_link_create - create a new link
+ * @n_ptr: pointer to associated node
  * @b_ptr: pointer to associated bearer
- * @peer: network address of node at other end of link
  * @media_addr: media address to use when sending messages over link
  *
  * Returns pointer to link.
  */
 
-struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
+struct link *tipc_link_create(struct tipc_node *n_ptr,
+			      struct tipc_bearer *b_ptr,
 			      const struct tipc_media_addr *media_addr)
 {
 	struct link *l_ptr;
 	struct tipc_msg *msg;
 	char *if_name;
+	char addr_string[16];
+	u32 peer = n_ptr->addr;
+
+	if (n_ptr->link_cnt >= 2) {
+		tipc_addr_string_fill(addr_string, n_ptr->addr);
+		err("Attempt to establish third link to %s\n", addr_string);
+		return NULL;
+	}
+
+	if (n_ptr->links[b_ptr->identity]) {
+		tipc_addr_string_fill(addr_string, n_ptr->addr);
+		err("Attempt to establish second link on <%s> to %s\n",
+		    b_ptr->name, addr_string);
+		return NULL;
+	}
 
 	l_ptr = kzalloc(sizeof(*l_ptr), GFP_ATOMIC);
 	if (!l_ptr) {
@@ -317,7 +330,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
 	}
 
 	l_ptr->addr = peer;
-	if_name = strchr(b_ptr->publ.name, ':') + 1;
+	if_name = strchr(b_ptr->name, ':') + 1;
 	sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:",
 		tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
 		tipc_node(tipc_own_addr),
@@ -325,6 +338,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
 		tipc_zone(peer), tipc_cluster(peer), tipc_node(peer));
 		/* note: peer i/f is appended to link name by reset/activate */
 	memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr));
+	l_ptr->owner = n_ptr;
 	l_ptr->checkpoint = 1;
 	l_ptr->b_ptr = b_ptr;
 	link_set_supervision_props(l_ptr, b_ptr->media->tolerance);
@@ -348,11 +362,7 @@ struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
 
 	link_reset_statistics(l_ptr);
 
-	l_ptr->owner = tipc_node_attach_link(l_ptr);
-	if (!l_ptr->owner) {
-		kfree(l_ptr);
-		return NULL;
-	}
+	tipc_node_attach_link(n_ptr, l_ptr);
 
 	k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr);
 	list_add_tail(&l_ptr->link_list, &b_ptr->links);
@@ -391,7 +401,9 @@ void tipc_link_delete(struct link *l_ptr)
 
 static void link_start(struct link *l_ptr)
 {
+	tipc_node_lock(l_ptr->owner);
 	link_state_event(l_ptr, STARTING_EVT);
+	tipc_node_unlock(l_ptr->owner);
 }
 
 /**
@@ -406,7 +418,7 @@ static void link_start(struct link *l_ptr)
 
 static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	spin_lock_bh(&tipc_port_list_lock);
 	p_ptr = tipc_port_lock(origport);
@@ -415,7 +427,7 @@ static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz)
 			goto exit;
 		if (!list_empty(&p_ptr->wait_list))
 			goto exit;
-		p_ptr->publ.congested = 1;
+		p_ptr->congested = 1;
 		p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt);
 		list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports);
 		l_ptr->stats.link_congs++;
@@ -428,8 +440,8 @@ exit:
 
 void tipc_link_wakeup_ports(struct link *l_ptr, int all)
 {
-	struct port *p_ptr;
-	struct port *temp_p_ptr;
+	struct tipc_port *p_ptr;
+	struct tipc_port *temp_p_ptr;
 	int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size;
 
 	if (all)
@@ -445,11 +457,11 @@ void tipc_link_wakeup_ports(struct link *l_ptr, int all)
 		if (win <= 0)
 			break;
 		list_del_init(&p_ptr->wait_list);
-		spin_lock_bh(p_ptr->publ.lock);
-		p_ptr->publ.congested = 0;
-		p_ptr->wakeup(&p_ptr->publ);
+		spin_lock_bh(p_ptr->lock);
+		p_ptr->congested = 0;
+		p_ptr->wakeup(p_ptr);
 		win -= p_ptr->waiting_pkts;
-		spin_unlock_bh(p_ptr->publ.lock);
+		spin_unlock_bh(p_ptr->lock);
 	}
 
 exit:
@@ -549,7 +561,7 @@ void tipc_link_reset(struct link *l_ptr)
 	tipc_node_link_down(l_ptr->owner, l_ptr);
 	tipc_bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr);
 
-	if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&
+	if (was_active_link && tipc_node_active_links(l_ptr->owner) &&
 	    l_ptr->owner->permit_changeover) {
 		l_ptr->reset_checkpoint = checkpoint;
 		l_ptr->exp_msg_count = START_CHANGEOVER;
@@ -824,7 +836,10 @@ static void link_add_to_outqueue(struct link *l_ptr,
 		l_ptr->last_out = buf;
 	} else
 		l_ptr->first_out = l_ptr->last_out = buf;
+
 	l_ptr->out_queue_size++;
+	if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz)
+		l_ptr->stats.max_queue_sz = l_ptr->out_queue_size;
 }
 
 /*
@@ -867,9 +882,6 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf)
 
 	/* Packet can be queued or sent: */
 
-	if (queue_size > l_ptr->stats.max_queue_sz)
-		l_ptr->stats.max_queue_sz = queue_size;
-
 	if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) &&
 		   !link_congested(l_ptr))) {
 		link_add_to_outqueue(l_ptr, buf, msg);
@@ -1027,12 +1039,12 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode)
  * except for total message length.
  * Returns user data length or errno.
  */
-int tipc_link_send_sections_fast(struct port *sender,
+int tipc_link_send_sections_fast(struct tipc_port *sender,
 				 struct iovec const *msg_sect,
 				 const u32 num_sect,
 				 u32 destaddr)
 {
-	struct tipc_msg *hdr = &sender->publ.phdr;
+	struct tipc_msg *hdr = &sender->phdr;
 	struct link *l_ptr;
 	struct sk_buff *buf;
 	struct tipc_node *node;
@@ -1045,7 +1057,7 @@ again:
 	 * (Must not hold any locks while building message.)
 	 */
 
-	res = tipc_msg_build(hdr, msg_sect, num_sect, sender->publ.max_pkt,
+	res = tipc_msg_build(hdr, msg_sect, num_sect, sender->max_pkt,
 			!sender->user_port, &buf);
 
 	read_lock_bh(&tipc_net_lock);
@@ -1056,7 +1068,7 @@ again:
 		if (likely(l_ptr)) {
 			if (likely(buf)) {
 				res = link_send_buf_fast(l_ptr, buf,
-							 &sender->publ.max_pkt);
+							 &sender->max_pkt);
 				if (unlikely(res < 0))
 					buf_discard(buf);
 exit:
@@ -1075,7 +1087,7 @@ exit:
 			if (link_congested(l_ptr) ||
 			    !list_empty(&l_ptr->b_ptr->cong_links)) {
 				res = link_schedule_port(l_ptr,
-							 sender->publ.ref, res);
+							 sender->ref, res);
 				goto exit;
 			}
 
@@ -1084,12 +1096,12 @@ exit:
 			 * then re-try fast path or fragment the message
 			 */
 
-			sender->publ.max_pkt = l_ptr->max_pkt;
+			sender->max_pkt = l_ptr->max_pkt;
 			tipc_node_unlock(node);
 			read_unlock_bh(&tipc_net_lock);
 
 
-			if ((msg_hdr_sz(hdr) + res) <= sender->publ.max_pkt)
+			if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt)
 				goto again;
 
 			return link_send_sections_long(sender, msg_sect,
@@ -1123,14 +1135,14 @@ exit:
  *
  * Returns user data length or errno.
  */
-static int link_send_sections_long(struct port *sender,
+static int link_send_sections_long(struct tipc_port *sender,
 				   struct iovec const *msg_sect,
 				   u32 num_sect,
 				   u32 destaddr)
 {
 	struct link *l_ptr;
 	struct tipc_node *node;
-	struct tipc_msg *hdr = &sender->publ.phdr;
+	struct tipc_msg *hdr = &sender->phdr;
 	u32 dsz = msg_data_sz(hdr);
 	u32 max_pkt, fragm_sz, rest;
 	struct tipc_msg fragm_hdr;
@@ -1142,7 +1154,7 @@ static int link_send_sections_long(struct port *sender,
 
 again:
 	fragm_no = 1;
-	max_pkt = sender->publ.max_pkt - INT_H_SIZE;
+	max_pkt = sender->max_pkt - INT_H_SIZE;
 		/* leave room for tunnel header in case of link changeover */
 	fragm_sz = max_pkt - INT_H_SIZE;
 		/* leave room for fragmentation header in each fragment */
@@ -1157,7 +1169,7 @@ again:
 
 	tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
 		 INT_H_SIZE, msg_destnode(hdr));
-	msg_set_link_selector(&fragm_hdr, sender->publ.ref);
+	msg_set_link_selector(&fragm_hdr, sender->ref);
 	msg_set_size(&fragm_hdr, max_pkt);
 	msg_set_fragm_no(&fragm_hdr, 1);
 
@@ -1238,13 +1250,13 @@ error:
 	node = tipc_node_find(destaddr);
 	if (likely(node)) {
 		tipc_node_lock(node);
-		l_ptr = node->active_links[sender->publ.ref & 1];
+		l_ptr = node->active_links[sender->ref & 1];
 		if (!l_ptr) {
 			tipc_node_unlock(node);
 			goto reject;
 		}
 		if (l_ptr->max_pkt < max_pkt) {
-			sender->publ.max_pkt = l_ptr->max_pkt;
+			sender->max_pkt = l_ptr->max_pkt;
 			tipc_node_unlock(node);
 			for (; buf_chain; buf_chain = buf) {
 				buf = buf_chain->next;
@@ -1441,7 +1453,7 @@ static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
 		info("Outstanding acks: %lu\n",
 		     (unsigned long) TIPC_SKB_CB(buf)->handle);
 
-		n_ptr = l_ptr->owner->next;
+		n_ptr = tipc_bclink_retransmit_to();
 		tipc_node_lock(n_ptr);
 
 		tipc_addr_string_fill(addr_string, n_ptr->addr);
@@ -1595,11 +1607,10 @@ static int link_recv_buf_validate(struct sk_buff *buf)
  * structure (i.e. cannot be NULL), but bearer can be inactive.
  */
 
-void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr)
+void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
 {
 	read_lock_bh(&tipc_net_lock);
 	while (head) {
-		struct bearer *b_ptr = (struct bearer *)tb_ptr;
 		struct tipc_node *n_ptr;
 		struct link *l_ptr;
 		struct sk_buff *crs;
@@ -1735,10 +1746,6 @@ deliver:
 						tipc_node_unlock(n_ptr);
 						tipc_link_recv_bundle(buf);
 						continue;
-					case ROUTE_DISTRIBUTOR:
-						tipc_node_unlock(n_ptr);
-						buf_discard(buf);
-						continue;
 					case NAME_DISTRIBUTOR:
 						tipc_node_unlock(n_ptr);
 						tipc_named_recv(buf);
@@ -1765,6 +1772,10 @@ deliver:
 							goto protocol_check;
 						}
 						break;
+					default:
+						buf_discard(buf);
+						buf = NULL;
+						break;
 					}
 				}
 				tipc_node_unlock(n_ptr);
@@ -1900,6 +1911,7 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
 	struct sk_buff *buf = NULL;
 	struct tipc_msg *msg = l_ptr->pmsg;
 	u32 msg_size = sizeof(l_ptr->proto_msg);
+	int r_flag;
 
 	if (link_blocked(l_ptr))
 		return;
@@ -1950,15 +1962,14 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
 		msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1));
 		msg_set_seq_gap(msg, 0);
 		msg_set_next_sent(msg, 1);
+		msg_set_probe(msg, 0);
 		msg_set_link_tolerance(msg, l_ptr->tolerance);
 		msg_set_linkprio(msg, l_ptr->priority);
 		msg_set_max_pkt(msg, l_ptr->max_pkt_target);
 	}
 
-	if (tipc_node_has_redundant_links(l_ptr->owner))
-		msg_set_redundant_link(msg);
-	else
-		msg_clear_redundant_link(msg);
+	r_flag = (l_ptr->owner->working_links > tipc_link_is_up(l_ptr));
+	msg_set_redundant_link(msg, r_flag);
 	msg_set_linkprio(msg, l_ptr->priority);
 
 	/* Ensure sequence number will not fit : */
@@ -1978,7 +1989,6 @@ void tipc_link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg,
 		skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));
 		return;
 	}
-	msg_set_timestamp(msg, jiffies_to_msecs(jiffies));
 
 	/* Message can be sent */
 
@@ -2066,7 +2076,7 @@ static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf)
 		l_ptr->peer_bearer_id = msg_bearer_id(msg);
 
 		/* Synchronize broadcast sequence numbers */
-		if (!tipc_node_has_redundant_links(l_ptr->owner))
+		if (!tipc_node_redundant_links(l_ptr->owner))
 			l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg));
 		break;
 	case STATE_MSG:
@@ -2413,9 +2423,6 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf)
 	else
 		destaddr = msg_destnode(inmsg);
 
-	if (msg_routed(inmsg))
-		msg_set_prevnode(inmsg, tipc_own_addr);
-
 	/* Prepare reusable fragment header: */
 
 	tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT,
@@ -2618,6 +2625,9 @@ static void link_check_defragm_bufs(struct link *l_ptr)
 
 static void link_set_supervision_props(struct link *l_ptr, u32 tolerance)
 {
+	if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL))
+		return;
+
 	l_ptr->tolerance = tolerance;
 	l_ptr->continuity_interval =
 		((tolerance / 4) > 500) ? 500 : tolerance / 4;
@@ -2658,7 +2668,7 @@ void tipc_link_set_queue_limits(struct link *l_ptr, u32 window)
 static struct link *link_find_link(const char *name, struct tipc_node **node)
 {
 	struct link_name link_name_parts;
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	struct link *l_ptr;
 
 	if (!link_name_validate(name, &link_name_parts))
@@ -2961,7 +2971,7 @@ static void link_print(struct link *l_ptr, const char *str)
 
 	tipc_printf(buf, str);
 	tipc_printf(buf, "Link %x<%s>:",
-		    l_ptr->addr, l_ptr->b_ptr->publ.name);
+		    l_ptr->addr, l_ptr->b_ptr->name);
 
 #ifdef CONFIG_TIPC_DEBUG
 	if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr))
@@ -2981,9 +2991,9 @@ static void link_print(struct link *l_ptr, const char *str)
 		     != (l_ptr->out_queue_size - 1)) ||
 		    (l_ptr->last_out->next != NULL)) {
 			tipc_printf(buf, "\nSend queue inconsistency\n");
-			tipc_printf(buf, "first_out= %x ", l_ptr->first_out);
-			tipc_printf(buf, "next_out= %x ", l_ptr->next_out);
-			tipc_printf(buf, "last_out= %x ", l_ptr->last_out);
+			tipc_printf(buf, "first_out= %p ", l_ptr->first_out);
+			tipc_printf(buf, "next_out= %p ", l_ptr->next_out);
+			tipc_printf(buf, "last_out= %p ", l_ptr->last_out);
 		}
 	} else
 		tipc_printf(buf, "[]");
diff --git a/net/tipc/link.h b/net/tipc/link.h
index 70967e6..e6a30db 100644
--- a/net/tipc/link.h
+++ b/net/tipc/link.h
@@ -2,7 +2,7 @@
  * net/tipc/link.h: Include file for TIPC link code
  *
  * Copyright (c) 1995-2006, Ericsson AB
- * Copyright (c) 2004-2005, Wind River Systems
+ * Copyright (c) 2004-2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -122,7 +122,7 @@ struct link {
 	u32 checkpoint;
 	u32 peer_session;
 	u32 peer_bearer_id;
-	struct bearer *b_ptr;
+	struct tipc_bearer *b_ptr;
 	u32 tolerance;
 	u32 continuity_interval;
 	u32 abort_limit;
@@ -196,24 +196,19 @@ struct link {
 		u32 bearer_congs;
 		u32 deferred_recv;
 		u32 duplicates;
-
-		/* for statistical profiling of send queue size */
-
-		u32 max_queue_sz;
-		u32 accu_queue_sz;
-		u32 queue_sz_counts;
-
-		/* for statistical profiling of message lengths */
-
-		u32 msg_length_counts;
-		u32 msg_lengths_total;
-		u32 msg_length_profile[7];
+		u32 max_queue_sz;	/* send queue size high water mark */
+		u32 accu_queue_sz;	/* used for send queue size profiling */
+		u32 queue_sz_counts;	/* used for send queue size profiling */
+		u32 msg_length_counts;	/* used for message length profiling */
+		u32 msg_lengths_total;	/* used for message length profiling */
+		u32 msg_length_profile[7]; /* used for msg. length profiling */
 	} stats;
 };
 
-struct port;
+struct tipc_port;
 
-struct link *tipc_link_create(struct bearer *b_ptr, const u32 peer,
+struct link *tipc_link_create(struct tipc_node *n_ptr,
+			      struct tipc_bearer *b_ptr,
 			      const struct tipc_media_addr *media_addr);
 void tipc_link_delete(struct link *l_ptr);
 void tipc_link_changeover(struct link *l_ptr);
@@ -230,7 +225,7 @@ void tipc_link_reset(struct link *l_ptr);
 int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector);
 int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf);
 u32 tipc_link_get_max_pkt(u32 dest, u32 selector);
-int tipc_link_send_sections_fast(struct port *sender,
+int tipc_link_send_sections_fast(struct tipc_port *sender,
 				 struct iovec const *msg_sect,
 				 const u32 num_sect,
 				 u32 destnode);
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index bb6180c..6d92d17 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -2,7 +2,7 @@
  * net/tipc/msg.c: TIPC message header routines
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -192,8 +192,6 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 		default:
 			tipc_printf(buf, "UNKNOWN TYPE %u", msg_type(msg));
 		}
-		if (msg_routed(msg) && !msg_non_seq(msg))
-			tipc_printf(buf, "ROUT:");
 		if (msg_reroute_cnt(msg))
 			tipc_printf(buf, "REROUTED(%u):",
 				    msg_reroute_cnt(msg));
@@ -210,8 +208,6 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 		default:
 			tipc_printf(buf, "UNKNOWN:%x", msg_type(msg));
 		}
-		if (msg_routed(msg))
-			tipc_printf(buf, "ROUT:");
 		if (msg_reroute_cnt(msg))
 			tipc_printf(buf, "REROUTED(%u):",
 				    msg_reroute_cnt(msg));
@@ -232,13 +228,10 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 		default:
 			tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
 		}
-		if (msg_routed(msg))
-			tipc_printf(buf, "ROUT:");
 		if (msg_reroute_cnt(msg))
 			tipc_printf(buf, "REROUTED(%u):", msg_reroute_cnt(msg));
 		break;
 	case LINK_PROTOCOL:
-		tipc_printf(buf, "PROT:TIM(%u):", msg_timestamp(msg));
 		switch (msg_type(msg)) {
 		case STATE_MSG:
 			tipc_printf(buf, "STATE:");
@@ -275,33 +268,6 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 			tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
 		}
 		break;
-	case ROUTE_DISTRIBUTOR:
-		tipc_printf(buf, "ROUTING_MNG:");
-		switch (msg_type(msg)) {
-		case EXT_ROUTING_TABLE:
-			tipc_printf(buf, "EXT_TBL:");
-			tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
-			break;
-		case LOCAL_ROUTING_TABLE:
-			tipc_printf(buf, "LOCAL_TBL:");
-			tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
-			break;
-		case SLAVE_ROUTING_TABLE:
-			tipc_printf(buf, "DP_TBL:");
-			tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
-			break;
-		case ROUTE_ADDITION:
-			tipc_printf(buf, "ADD:");
-			tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
-			break;
-		case ROUTE_REMOVAL:
-			tipc_printf(buf, "REMOVE:");
-			tipc_printf(buf, "TO:%x:", msg_remote_node(msg));
-			break;
-		default:
-			tipc_printf(buf, "UNKNOWN TYPE:%x", msg_type(msg));
-		}
-		break;
 	case LINK_CONFIG:
 		tipc_printf(buf, "CFG:");
 		switch (msg_type(msg)) {
@@ -381,20 +347,15 @@ void tipc_msg_dbg(struct print_buf *buf, struct tipc_msg *msg, const char *str)
 			tipc_printf(buf, ":OPRT(%u):", msg_origport(msg));
 			tipc_printf(buf, ":DPRT(%u):", msg_destport(msg));
 		}
-		if (msg_routed(msg) && !msg_non_seq(msg))
-			tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg));
 	}
 	if (msg_user(msg) == NAME_DISTRIBUTOR) {
 		tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg));
 		tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg));
-		if (msg_routed(msg))
-			tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg));
 	}
 
 	if (msg_user(msg) ==  LINK_CONFIG) {
 		u32 *raw = (u32 *)msg;
 		struct tipc_media_addr *orig = (struct tipc_media_addr *)&raw[5];
-		tipc_printf(buf, ":REQL(%u):", msg_req_links(msg));
 		tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg));
 		tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg));
 		tipc_media_addr_printf(buf, orig);
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 92c4c4f..de02339 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -2,7 +2,7 @@
  * net/tipc/msg.h: Include file for TIPC message header routines
  *
  * Copyright (c) 2000-2007, Ericsson AB
- * Copyright (c) 2005-2008, Wind River Systems
+ * Copyright (c) 2005-2008, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -421,13 +421,6 @@ static inline int msg_is_dest(struct tipc_msg *m, u32 d)
 	return msg_short(m) || (msg_destnode(m) == d);
 }
 
-static inline u32 msg_routed(struct tipc_msg *m)
-{
-	if (likely(msg_short(m)))
-		return 0;
-	return (msg_destnode(m) ^ msg_orignode(m)) >> 11;
-}
-
 static inline u32 msg_nametype(struct tipc_msg *m)
 {
 	return msg_word(m, 8);
@@ -438,26 +431,6 @@ static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
 	msg_set_word(m, 8, n);
 }
 
-static inline u32 msg_transp_seqno(struct tipc_msg *m)
-{
-	return msg_word(m, 8);
-}
-
-static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
-{
-	msg_set_word(m, 8, n);
-}
-
-static inline u32 msg_timestamp(struct tipc_msg *m)
-{
-	return msg_word(m, 8);
-}
-
-static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n)
-{
-	msg_set_word(m, 8, n);
-}
-
 static inline u32 msg_nameinst(struct tipc_msg *m)
 {
 	return msg_word(m, 9);
@@ -545,7 +518,6 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
 #define  NAME_DISTRIBUTOR     11
 #define  MSG_FRAGMENTER       12
 #define  LINK_CONFIG          13
-#define  DSC_H_SIZE           40
 
 /*
  *  Connection management protocol messages
@@ -577,16 +549,6 @@ static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
 	msg_set_bits(m, 1, 16, 0x1fff, n);
 }
 
-static inline u32 msg_req_links(struct tipc_msg *m)
-{
-	return msg_bits(m, 1, 16, 0xfff);
-}
-
-static inline void msg_set_req_links(struct tipc_msg *m, u32 n)
-{
-	msg_set_bits(m, 1, 16, 0xfff, n);
-}
-
 
 /*
  * Word 2
@@ -749,14 +711,9 @@ static inline u32 msg_redundant_link(struct tipc_msg *m)
 	return msg_bits(m, 5, 12, 0x1);
 }
 
-static inline void msg_set_redundant_link(struct tipc_msg *m)
+static inline void msg_set_redundant_link(struct tipc_msg *m, u32 r)
 {
-	msg_set_bits(m, 5, 12, 0x1, 1);
-}
-
-static inline void msg_clear_redundant_link(struct tipc_msg *m)
-{
-	msg_set_bits(m, 5, 12, 0x1, 0);
+	msg_set_bits(m, 5, 12, 0x1, r);
 }
 
 
@@ -805,21 +762,6 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n)
 }
 
 /*
- * Routing table message data
- */
-
-
-static inline u32 msg_remote_node(struct tipc_msg *m)
-{
-	return msg_word(m, msg_hdr_sz(m)/4);
-}
-
-static inline void msg_set_remote_node(struct tipc_msg *m, u32 a)
-{
-	msg_set_word(m, msg_hdr_sz(m)/4, a);
-}
-
-/*
  * Segmentation message types
  */
 
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 483c226..c9fa6df 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -2,7 +2,7 @@
  * net/tipc/name_distr.c: TIPC name distribution code
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -109,11 +109,9 @@ static void named_cluster_distribute(struct sk_buff *buf)
 {
 	struct sk_buff *buf_copy;
 	struct tipc_node *n_ptr;
-	u32 n_num;
 
-	for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {
-		n_ptr = tipc_net.nodes[n_num];
-		if (n_ptr && tipc_node_has_active_links(n_ptr)) {
+	list_for_each_entry(n_ptr, &tipc_node_list, list) {
+		if (tipc_node_active_links(n_ptr)) {
 			buf_copy = skb_copy(buf, GFP_ATOMIC);
 			if (!buf_copy)
 				break;
@@ -214,17 +212,16 @@ exit:
 }
 
 /**
- * node_is_down - remove publication associated with a failed node
+ * named_purge_publ - remove publication associated with a failed node
  *
  * Invoked for each publication issued by a newly failed node.
  * Removes publication structure from name table & deletes it.
  * In rare cases the link may have come back up again when this
  * function is called, and we have two items representing the same
  * publication. Nudge this item's key to distinguish it from the other.
- * (Note: Publication's node subscription is already unsubscribed.)
  */
 
-static void node_is_down(struct publication *publ)
+static void named_purge_publ(struct publication *publ)
 {
 	struct publication *p;
 
@@ -232,6 +229,8 @@ static void node_is_down(struct publication *publ)
 	publ->key += 1222345;
 	p = tipc_nametbl_remove_publ(publ->type, publ->lower,
 				     publ->node, publ->ref, publ->key);
+	if (p)
+		tipc_nodesub_unsubscribe(&p->subscr);
 	write_unlock_bh(&tipc_nametbl_lock);
 
 	if (p != publ) {
@@ -268,7 +267,8 @@ void tipc_named_recv(struct sk_buff *buf)
 				tipc_nodesub_subscribe(&publ->subscr,
 						       msg_orignode(msg),
 						       publ,
-						       (net_ev_handler)node_is_down);
+						       (net_ev_handler)
+						       named_purge_publ);
 			}
 		} else if (msg_type(msg) == WITHDRAWAL) {
 			publ = tipc_nametbl_remove_publ(ntohl(item->type),
diff --git a/net/tipc/net.c b/net/tipc/net.c
index 9bacfd0..68b3dd6 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -2,7 +2,7 @@
  * net/tipc/net.c: TIPC network routing code
  *
  * Copyright (c) 1995-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
 #include "name_distr.h"
 #include "subscr.h"
 #include "port.h"
+#include "node.h"
 #include "config.h"
 
 /*
@@ -108,26 +109,6 @@
 */
 
 DEFINE_RWLOCK(tipc_net_lock);
-struct network tipc_net;
-
-static int net_start(void)
-{
-	tipc_net.nodes = kcalloc(tipc_max_nodes + 1,
-				 sizeof(*tipc_net.nodes), GFP_ATOMIC);
-	tipc_net.highest_node = 0;
-
-	return tipc_net.nodes ? 0 : -ENOMEM;
-}
-
-static void net_stop(void)
-{
-	u32 n_num;
-
-	for (n_num = 1; n_num <= tipc_net.highest_node; n_num++)
-		tipc_node_delete(tipc_net.nodes[n_num]);
-	kfree(tipc_net.nodes);
-	tipc_net.nodes = NULL;
-}
 
 static void net_route_named_msg(struct sk_buff *buf)
 {
@@ -217,9 +198,6 @@ int tipc_net_start(u32 addr)
 	tipc_named_reinit();
 	tipc_port_reinit();
 
-	res = net_start();
-	if (res)
-		return res;
 	res = tipc_bclink_init();
 	if (res)
 		return res;
@@ -235,14 +213,16 @@ int tipc_net_start(u32 addr)
 
 void tipc_net_stop(void)
 {
+	struct tipc_node *node, *t_node;
+
 	if (tipc_mode != TIPC_NET_MODE)
 		return;
 	write_lock_bh(&tipc_net_lock);
 	tipc_bearer_stop();
 	tipc_mode = TIPC_NODE_MODE;
 	tipc_bclink_stop();
-	net_stop();
+	list_for_each_entry_safe(node, t_node, &tipc_node_list, list)
+		tipc_node_delete(node);
 	write_unlock_bh(&tipc_net_lock);
 	info("Left network mode\n");
 }
-
diff --git a/net/tipc/net.h b/net/tipc/net.h
index 4ae59ad..9eb4b9e 100644
--- a/net/tipc/net.h
+++ b/net/tipc/net.h
@@ -2,7 +2,7 @@
  * net/tipc/net.h: Include file for TIPC network routing code
  *
  * Copyright (c) 1995-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,23 +37,6 @@
 #ifndef _TIPC_NET_H
 #define _TIPC_NET_H
 
-struct tipc_node;
-
-/**
- * struct network - TIPC network structure
- * @nodes: array of pointers to all nodes within cluster
- * @highest_node: id of highest numbered node within cluster
- * @links: number of (unicast) links to cluster
- */
-
-struct network {
-	struct tipc_node **nodes;
-	u32 highest_node;
-	u32 links;
-};
-
-
-extern struct network tipc_net;
 extern rwlock_t tipc_net_lock;
 
 void tipc_net_route_msg(struct sk_buff *buf);
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 3af53e3..2d106ef 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -2,7 +2,7 @@
  * net/tipc/node.c: TIPC node management routines
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005-2006, Wind River Systems
+ * Copyright (c) 2005-2006, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -44,9 +44,33 @@ static void node_established_contact(struct tipc_node *n_ptr);
 
 static DEFINE_SPINLOCK(node_create_lock);
 
+static struct hlist_head node_htable[NODE_HTABLE_SIZE];
+LIST_HEAD(tipc_node_list);
+static u32 tipc_num_nodes;
+
+static atomic_t tipc_num_links = ATOMIC_INIT(0);
 u32 tipc_own_tag;
 
 /**
+ * tipc_node_find - locate specified node object, if it exists
+ */
+
+struct tipc_node *tipc_node_find(u32 addr)
+{
+	struct tipc_node *node;
+	struct hlist_node *pos;
+
+	if (unlikely(!in_own_cluster(addr)))
+		return NULL;
+
+	hlist_for_each_entry(node, pos, &node_htable[tipc_hashfn(addr)], hash) {
+		if (node->addr == addr)
+			return node;
+	}
+	return NULL;
+}
+
+/**
  * tipc_node_create - create neighboring node
  *
  * Currently, this routine is called by neighbor discovery code, which holds
@@ -58,8 +82,7 @@ u32 tipc_own_tag;
 
 struct tipc_node *tipc_node_create(u32 addr)
 {
-	struct tipc_node *n_ptr;
-	u32 n_num;
+	struct tipc_node *n_ptr, *temp_node;
 
 	spin_lock_bh(&node_create_lock);
 
@@ -78,12 +101,19 @@ struct tipc_node *tipc_node_create(u32 addr)
 
 	n_ptr->addr = addr;
 	spin_lock_init(&n_ptr->lock);
+	INIT_HLIST_NODE(&n_ptr->hash);
+	INIT_LIST_HEAD(&n_ptr->list);
 	INIT_LIST_HEAD(&n_ptr->nsub);
 
-	n_num = tipc_node(addr);
-	tipc_net.nodes[n_num] = n_ptr;
-	if (n_num > tipc_net.highest_node)
-		tipc_net.highest_node = n_num;
+	hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);
+
+	list_for_each_entry(temp_node, &tipc_node_list, list) {
+		if (n_ptr->addr < temp_node->addr)
+			break;
+	}
+	list_add_tail(&n_ptr->list, &temp_node->list);
+
+	tipc_num_nodes++;
 
 	spin_unlock_bh(&node_create_lock);
 	return n_ptr;
@@ -91,18 +121,11 @@ struct tipc_node *tipc_node_create(u32 addr)
 
 void tipc_node_delete(struct tipc_node *n_ptr)
 {
-	u32 n_num;
-
-	if (!n_ptr)
-		return;
-
-	n_num = tipc_node(n_ptr->addr);
-	tipc_net.nodes[n_num] = NULL;
+	list_del(&n_ptr->list);
+	hlist_del(&n_ptr->hash);
 	kfree(n_ptr);
 
-	while (!tipc_net.nodes[tipc_net.highest_node])
-		if (--tipc_net.highest_node == 0)
-			break;
+	tipc_num_nodes--;
 }
 
 
@@ -200,54 +223,32 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr)
 		node_lost_contact(n_ptr);
 }
 
-int tipc_node_has_active_links(struct tipc_node *n_ptr)
+int tipc_node_active_links(struct tipc_node *n_ptr)
 {
 	return n_ptr->active_links[0] != NULL;
 }
 
-int tipc_node_has_redundant_links(struct tipc_node *n_ptr)
+int tipc_node_redundant_links(struct tipc_node *n_ptr)
 {
 	return n_ptr->working_links > 1;
 }
 
 int tipc_node_is_up(struct tipc_node *n_ptr)
 {
-	return tipc_node_has_active_links(n_ptr);
+	return tipc_node_active_links(n_ptr);
 }
 
-struct tipc_node *tipc_node_attach_link(struct link *l_ptr)
+void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr)
 {
-	struct tipc_node *n_ptr = tipc_node_find(l_ptr->addr);
-
-	if (!n_ptr)
-		n_ptr = tipc_node_create(l_ptr->addr);
-	if (n_ptr) {
-		u32 bearer_id = l_ptr->b_ptr->identity;
-		char addr_string[16];
-
-		if (n_ptr->link_cnt >= 2) {
-			err("Attempt to create third link to %s\n",
-			    tipc_addr_string_fill(addr_string, n_ptr->addr));
-			return NULL;
-		}
-
-		if (!n_ptr->links[bearer_id]) {
-			n_ptr->links[bearer_id] = l_ptr;
-			tipc_net.links++;
-			n_ptr->link_cnt++;
-			return n_ptr;
-		}
-		err("Attempt to establish second link on <%s> to %s\n",
-		    l_ptr->b_ptr->publ.name,
-		    tipc_addr_string_fill(addr_string, l_ptr->addr));
-	}
-	return NULL;
+	n_ptr->links[l_ptr->b_ptr->identity] = l_ptr;
+	atomic_inc(&tipc_num_links);
+	n_ptr->link_cnt++;
 }
 
 void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr)
 {
 	n_ptr->links[l_ptr->b_ptr->identity] = NULL;
-	tipc_net.links--;
+	atomic_dec(&tipc_num_links);
 	n_ptr->link_cnt--;
 }
 
@@ -327,7 +328,6 @@ static void node_cleanup_finished(unsigned long node_addr)
 
 static void node_lost_contact(struct tipc_node *n_ptr)
 {
-	struct tipc_node_subscr *ns, *tns;
 	char addr_string[16];
 	u32 i;
 
@@ -365,12 +365,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
 	}
 
 	/* Notify subscribers */
-	list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) {
-		ns->node = NULL;
-		list_del_init(&ns->nodesub_list);
-		tipc_k_signal((Handler)ns->handle_node_down,
-			      (unsigned long)ns->usr_handle);
-	}
+	tipc_nodesub_notify(n_ptr);
 
 	/* Prevent re-contact with node until all cleanup is done */
 
@@ -385,7 +380,6 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 	struct tipc_node *n_ptr;
 	struct tipc_node_info node_info;
 	u32 payload_size;
-	u32 n_num;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -396,15 +390,14 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 						   " (network address)");
 
 	read_lock_bh(&tipc_net_lock);
-	if (!tipc_net.nodes) {
+	if (!tipc_num_nodes) {
 		read_unlock_bh(&tipc_net_lock);
 		return tipc_cfg_reply_none();
 	}
 
 	/* For now, get space for all other nodes */
 
-	payload_size = TLV_SPACE(sizeof(node_info)) *
-		(tipc_net.highest_node - 1);
+	payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes;
 	if (payload_size > 32768u) {
 		read_unlock_bh(&tipc_net_lock);
 		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
@@ -418,9 +411,8 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space)
 
 	/* Add TLVs for all nodes in scope */
 
-	for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {
-		n_ptr = tipc_net.nodes[n_num];
-		if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
+	list_for_each_entry(n_ptr, &tipc_node_list, list) {
+		if (!tipc_in_scope(domain, n_ptr->addr))
 			continue;
 		node_info.addr = htonl(n_ptr->addr);
 		node_info.up = htonl(tipc_node_is_up(n_ptr));
@@ -439,7 +431,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 	struct tipc_node *n_ptr;
 	struct tipc_link_info link_info;
 	u32 payload_size;
-	u32 n_num;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR))
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
@@ -456,7 +447,8 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 
 	/* Get space for all unicast links + multicast link */
 
-	payload_size = TLV_SPACE(sizeof(link_info)) * (tipc_net.links + 1);
+	payload_size = TLV_SPACE(sizeof(link_info)) *
+		(atomic_read(&tipc_num_links) + 1);
 	if (payload_size > 32768u) {
 		read_unlock_bh(&tipc_net_lock);
 		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
@@ -470,18 +462,17 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space)
 
 	/* Add TLV for broadcast link */
 
-	link_info.dest = htonl(tipc_own_addr & 0xfffff00);
+	link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr));
 	link_info.up = htonl(1);
 	strlcpy(link_info.str, tipc_bclink_name, TIPC_MAX_LINK_NAME);
 	tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info));
 
 	/* Add TLVs for any other links in scope */
 
-	for (n_num = 1; n_num <= tipc_net.highest_node; n_num++) {
+	list_for_each_entry(n_ptr, &tipc_node_list, list) {
 		u32 i;
 
-		n_ptr = tipc_net.nodes[n_num];
-		if (!n_ptr || !tipc_in_scope(domain, n_ptr->addr))
+		if (!tipc_in_scope(domain, n_ptr->addr))
 			continue;
 		tipc_node_lock(n_ptr);
 		for (i = 0; i < MAX_BEARERS; i++) {
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 206a8ef..5c61afc 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -2,7 +2,7 @@
  * net/tipc/node.h: Include file for TIPC node management routines
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,8 @@
  * struct tipc_node - TIPC node structure
  * @addr: network address of node
  * @lock: spinlock governing access to structure
- * @next: pointer to next node in sorted list of cluster's nodes
+ * @hash: links to adjacent nodes in unsorted hash chain
+ * @list: links to adjacent nodes in sorted list of cluster's nodes
  * @nsub: list of "node down" subscriptions monitoring node
  * @active_links: pointers to active links to node
  * @links: pointers to all links to node
@@ -69,7 +70,8 @@
 struct tipc_node {
 	u32 addr;
 	spinlock_t lock;
-	struct tipc_node *next;
+	struct hlist_node hash;
+	struct list_head list;
 	struct list_head nsub;
 	struct link *active_links[2];
 	struct link *links[MAX_BEARERS];
@@ -90,27 +92,35 @@ struct tipc_node {
 	} bclink;
 };
 
+#define NODE_HTABLE_SIZE 512
+extern struct list_head tipc_node_list;
+
+/*
+ * A trivial power-of-two bitmask technique is used for speed, since this
+ * operation is done for every incoming TIPC packet. The number of hash table
+ * entries has been chosen so that no hash chain exceeds 8 nodes and will
+ * usually be much smaller (typically only a single node).
+ */
+static inline unsigned int tipc_hashfn(u32 addr)
+{
+	return addr & (NODE_HTABLE_SIZE - 1);
+}
+
 extern u32 tipc_own_tag;
 
+struct tipc_node *tipc_node_find(u32 addr);
 struct tipc_node *tipc_node_create(u32 addr);
 void tipc_node_delete(struct tipc_node *n_ptr);
-struct tipc_node *tipc_node_attach_link(struct link *l_ptr);
+void tipc_node_attach_link(struct tipc_node *n_ptr, struct link *l_ptr);
 void tipc_node_detach_link(struct tipc_node *n_ptr, struct link *l_ptr);
 void tipc_node_link_down(struct tipc_node *n_ptr, struct link *l_ptr);
 void tipc_node_link_up(struct tipc_node *n_ptr, struct link *l_ptr);
-int tipc_node_has_active_links(struct tipc_node *n_ptr);
-int tipc_node_has_redundant_links(struct tipc_node *n_ptr);
+int tipc_node_active_links(struct tipc_node *n_ptr);
+int tipc_node_redundant_links(struct tipc_node *n_ptr);
 int tipc_node_is_up(struct tipc_node *n_ptr);
 struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space);
 struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space);
 
-static inline struct tipc_node *tipc_node_find(u32 addr)
-{
-	if (likely(in_own_cluster(addr)))
-		return tipc_net.nodes[tipc_node(addr)];
-	return NULL;
-}
-
 static inline void tipc_node_lock(struct tipc_node *n_ptr)
 {
 	spin_lock_bh(&n_ptr->lock);
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index 018a553..c3c2815 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -2,7 +2,7 @@
  * net/tipc/node_subscr.c: TIPC "node down" subscription handling
  *
  * Copyright (c) 1995-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -76,3 +76,22 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub)
 	list_del_init(&node_sub->nodesub_list);
 	tipc_node_unlock(node_sub->node);
 }
+
+/**
+ * tipc_nodesub_notify - notify subscribers that a node is unreachable
+ *
+ * Note: node is locked by caller
+ */
+
+void tipc_nodesub_notify(struct tipc_node *node)
+{
+	struct tipc_node_subscr *ns;
+
+	list_for_each_entry(ns, &node->nsub, nodesub_list) {
+		if (ns->handle_node_down) {
+			tipc_k_signal((Handler)ns->handle_node_down,
+				      (unsigned long)ns->usr_handle);
+			ns->handle_node_down = NULL;
+		}
+	}
+}
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h
index 006ed73..4bc2ca0 100644
--- a/net/tipc/node_subscr.h
+++ b/net/tipc/node_subscr.h
@@ -2,7 +2,7 @@
  * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling
  *
  * Copyright (c) 1995-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -59,5 +59,6 @@ struct tipc_node_subscr {
 void tipc_nodesub_subscribe(struct tipc_node_subscr *node_sub, u32 addr,
 			    void *usr_handle, net_ev_handler handle_down);
 void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub);
+void tipc_nodesub_notify(struct tipc_node *node);
 
 #endif
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 067bab2..6ff78f9 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -2,7 +2,7 @@
  * net/tipc/port.c: TIPC port code
  *
  * Copyright (c) 1992-2007, Ericsson AB
- * Copyright (c) 2004-2008, Wind River Systems
+ * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,33 +54,19 @@ static DEFINE_SPINLOCK(queue_lock);
 
 static LIST_HEAD(ports);
 static void port_handle_node_down(unsigned long ref);
-static struct sk_buff *port_build_self_abort_msg(struct port *, u32 err);
-static struct sk_buff *port_build_peer_abort_msg(struct port *, u32 err);
+static struct sk_buff *port_build_self_abort_msg(struct tipc_port *, u32 err);
+static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *, u32 err);
 static void port_timeout(unsigned long ref);
 
 
-static u32 port_peernode(struct port *p_ptr)
+static u32 port_peernode(struct tipc_port *p_ptr)
 {
-	return msg_destnode(&p_ptr->publ.phdr);
+	return msg_destnode(&p_ptr->phdr);
 }
 
-static u32 port_peerport(struct port *p_ptr)
+static u32 port_peerport(struct tipc_port *p_ptr)
 {
-	return msg_destport(&p_ptr->publ.phdr);
-}
-
-static u32 port_out_seqno(struct port *p_ptr)
-{
-	return msg_transp_seqno(&p_ptr->publ.phdr);
-}
-
-static void port_incr_out_seqno(struct port *p_ptr)
-{
-	struct tipc_msg *m = &p_ptr->publ.phdr;
-
-	if (likely(!msg_routed(m)))
-		return;
-	msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1));
+	return msg_destport(&p_ptr->phdr);
 }
 
 /**
@@ -94,7 +80,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq,
 	struct sk_buff *buf;
 	struct sk_buff *ibuf = NULL;
 	struct port_list dports = {0, NULL, };
-	struct port *oport = tipc_port_deref(ref);
+	struct tipc_port *oport = tipc_port_deref(ref);
 	int ext_targets;
 	int res;
 
@@ -103,7 +89,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq,
 
 	/* Create multicast message */
 
-	hdr = &oport->publ.phdr;
+	hdr = &oport->phdr;
 	msg_set_type(hdr, TIPC_MCAST_MSG);
 	msg_set_nametype(hdr, seq->type);
 	msg_set_namelower(hdr, seq->lower);
@@ -211,7 +197,7 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
 			void (*wakeup)(struct tipc_port *),
 			const u32 importance)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg;
 	u32 ref;
 
@@ -220,21 +206,19 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
 		warn("Port creation failed, no memory\n");
 		return NULL;
 	}
-	ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock);
+	ref = tipc_ref_acquire(p_ptr, &p_ptr->lock);
 	if (!ref) {
 		warn("Port creation failed, reference table exhausted\n");
 		kfree(p_ptr);
 		return NULL;
 	}
 
-	p_ptr->publ.usr_handle = usr_handle;
-	p_ptr->publ.max_pkt = MAX_PKT_DEFAULT;
-	p_ptr->publ.ref = ref;
-	msg = &p_ptr->publ.phdr;
+	p_ptr->usr_handle = usr_handle;
+	p_ptr->max_pkt = MAX_PKT_DEFAULT;
+	p_ptr->ref = ref;
+	msg = &p_ptr->phdr;
 	tipc_msg_init(msg, importance, TIPC_NAMED_MSG, LONG_H_SIZE, 0);
 	msg_set_origport(msg, ref);
-	p_ptr->last_in_seqno = 41;
-	p_ptr->sent = 1;
 	INIT_LIST_HEAD(&p_ptr->wait_list);
 	INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list);
 	p_ptr->dispatcher = dispatcher;
@@ -246,12 +230,12 @@ struct tipc_port *tipc_createport_raw(void *usr_handle,
 	INIT_LIST_HEAD(&p_ptr->port_list);
 	list_add_tail(&p_ptr->port_list, &ports);
 	spin_unlock_bh(&tipc_port_list_lock);
-	return &(p_ptr->publ);
+	return p_ptr;
 }
 
 int tipc_deleteport(u32 ref)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct sk_buff *buf = NULL;
 
 	tipc_withdraw(ref, 0, NULL);
@@ -263,7 +247,7 @@ int tipc_deleteport(u32 ref)
 	tipc_port_unlock(p_ptr);
 
 	k_cancel_timer(&p_ptr->timer);
-	if (p_ptr->publ.connected) {
+	if (p_ptr->connected) {
 		buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
 		tipc_nodesub_unsubscribe(&p_ptr->subscription);
 	}
@@ -279,14 +263,14 @@ int tipc_deleteport(u32 ref)
 	return 0;
 }
 
-static int port_unreliable(struct port *p_ptr)
+static int port_unreliable(struct tipc_port *p_ptr)
 {
-	return msg_src_droppable(&p_ptr->publ.phdr);
+	return msg_src_droppable(&p_ptr->phdr);
 }
 
 int tipc_portunreliable(u32 ref, unsigned int *isunreliable)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
@@ -298,24 +282,24 @@ int tipc_portunreliable(u32 ref, unsigned int *isunreliable)
 
 int tipc_set_portunreliable(u32 ref, unsigned int isunreliable)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0));
+	msg_set_src_droppable(&p_ptr->phdr, (isunreliable != 0));
 	tipc_port_unlock(p_ptr);
 	return 0;
 }
 
-static int port_unreturnable(struct port *p_ptr)
+static int port_unreturnable(struct tipc_port *p_ptr)
 {
-	return msg_dest_droppable(&p_ptr->publ.phdr);
+	return msg_dest_droppable(&p_ptr->phdr);
 }
 
 int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
@@ -327,12 +311,12 @@ int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable)
 
 int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0));
+	msg_set_dest_droppable(&p_ptr->phdr, (isunrejectable != 0));
 	tipc_port_unlock(p_ptr);
 	return 0;
 }
@@ -345,7 +329,7 @@ int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable)
 static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
 					    u32 origport, u32 orignode,
 					    u32 usr, u32 type, u32 err,
-					    u32 seqno, u32 ack)
+					    u32 ack)
 {
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
@@ -358,7 +342,6 @@ static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode,
 		msg_set_destport(msg, destport);
 		msg_set_origport(msg, origport);
 		msg_set_orignode(msg, orignode);
-		msg_set_transp_seqno(msg, seqno);
 		msg_set_msgcnt(msg, ack);
 	}
 	return buf;
@@ -413,10 +396,10 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
 	/* send self-abort message when rejecting on a connected port */
 	if (msg_connected(msg)) {
 		struct sk_buff *abuf = NULL;
-		struct port *p_ptr = tipc_port_lock(msg_destport(msg));
+		struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
 
 		if (p_ptr) {
-			if (p_ptr->publ.connected)
+			if (p_ptr->connected)
 				abuf = port_build_self_abort_msg(p_ptr, err);
 			tipc_port_unlock(p_ptr);
 		}
@@ -429,7 +412,7 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err)
 	return data_sz;
 }
 
-int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
+int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr,
 			      struct iovec const *msg_sect, u32 num_sect,
 			      int err)
 {
@@ -446,13 +429,13 @@ int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
 
 static void port_timeout(unsigned long ref)
 {
-	struct port *p_ptr = tipc_port_lock(ref);
+	struct tipc_port *p_ptr = tipc_port_lock(ref);
 	struct sk_buff *buf = NULL;
 
 	if (!p_ptr)
 		return;
 
-	if (!p_ptr->publ.connected) {
+	if (!p_ptr->connected) {
 		tipc_port_unlock(p_ptr);
 		return;
 	}
@@ -463,14 +446,12 @@ static void port_timeout(unsigned long ref)
 	} else {
 		buf = port_build_proto_msg(port_peerport(p_ptr),
 					   port_peernode(p_ptr),
-					   p_ptr->publ.ref,
+					   p_ptr->ref,
 					   tipc_own_addr,
 					   CONN_MANAGER,
 					   CONN_PROBE,
 					   TIPC_OK,
-					   port_out_seqno(p_ptr),
 					   0);
-		port_incr_out_seqno(p_ptr);
 		p_ptr->probing_state = PROBING;
 		k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
 	}
@@ -481,7 +462,7 @@ static void port_timeout(unsigned long ref)
 
 static void port_handle_node_down(unsigned long ref)
 {
-	struct port *p_ptr = tipc_port_lock(ref);
+	struct tipc_port *p_ptr = tipc_port_lock(ref);
 	struct sk_buff *buf = NULL;
 
 	if (!p_ptr)
@@ -492,73 +473,71 @@ static void port_handle_node_down(unsigned long ref)
 }
 
 
-static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err)
+static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 err)
 {
-	u32 imp = msg_importance(&p_ptr->publ.phdr);
+	u32 imp = msg_importance(&p_ptr->phdr);
 
-	if (!p_ptr->publ.connected)
+	if (!p_ptr->connected)
 		return NULL;
 	if (imp < TIPC_CRITICAL_IMPORTANCE)
 		imp++;
-	return port_build_proto_msg(p_ptr->publ.ref,
+	return port_build_proto_msg(p_ptr->ref,
 				    tipc_own_addr,
 				    port_peerport(p_ptr),
 				    port_peernode(p_ptr),
 				    imp,
 				    TIPC_CONN_MSG,
 				    err,
-				    p_ptr->last_in_seqno + 1,
 				    0);
 }
 
 
-static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err)
+static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 err)
 {
-	u32 imp = msg_importance(&p_ptr->publ.phdr);
+	u32 imp = msg_importance(&p_ptr->phdr);
 
-	if (!p_ptr->publ.connected)
+	if (!p_ptr->connected)
 		return NULL;
 	if (imp < TIPC_CRITICAL_IMPORTANCE)
 		imp++;
 	return port_build_proto_msg(port_peerport(p_ptr),
 				    port_peernode(p_ptr),
-				    p_ptr->publ.ref,
+				    p_ptr->ref,
 				    tipc_own_addr,
 				    imp,
 				    TIPC_CONN_MSG,
 				    err,
-				    port_out_seqno(p_ptr),
 				    0);
 }
 
 void tipc_port_recv_proto_msg(struct sk_buff *buf)
 {
 	struct tipc_msg *msg = buf_msg(buf);
-	struct port *p_ptr = tipc_port_lock(msg_destport(msg));
+	struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg));
 	u32 err = TIPC_OK;
 	struct sk_buff *r_buf = NULL;
 	struct sk_buff *abort_buf = NULL;
 
 	if (!p_ptr) {
 		err = TIPC_ERR_NO_PORT;
-	} else if (p_ptr->publ.connected) {
+	} else if (p_ptr->connected) {
 		if ((port_peernode(p_ptr) != msg_orignode(msg)) ||
 		    (port_peerport(p_ptr) != msg_origport(msg))) {
 			err = TIPC_ERR_NO_PORT;
 		} else if (msg_type(msg) == CONN_ACK) {
 			int wakeup = tipc_port_congested(p_ptr) &&
-				     p_ptr->publ.congested &&
+				     p_ptr->congested &&
 				     p_ptr->wakeup;
 			p_ptr->acked += msg_msgcnt(msg);
 			if (tipc_port_congested(p_ptr))
 				goto exit;
-			p_ptr->publ.congested = 0;
+			p_ptr->congested = 0;
 			if (!wakeup)
 				goto exit;
-			p_ptr->wakeup(&p_ptr->publ);
+			p_ptr->wakeup(p_ptr);
 			goto exit;
 		}
-	} else if (p_ptr->publ.published) {
+	} else if (p_ptr->published) {
 		err = TIPC_ERR_NO_PORT;
 	}
 	if (err) {
@@ -569,7 +548,6 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
 					     TIPC_HIGH_IMPORTANCE,
 					     TIPC_CONN_MSG,
 					     err,
-					     0,
 					     0);
 		goto exit;
 	}
@@ -583,11 +561,9 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf)
 					     CONN_MANAGER,
 					     CONN_PROBE_REPLY,
 					     TIPC_OK,
-					     port_out_seqno(p_ptr),
 					     0);
 	}
 	p_ptr->probing_state = CONFIRMED;
-	port_incr_out_seqno(p_ptr);
 exit:
 	if (p_ptr)
 		tipc_port_unlock(p_ptr);
@@ -596,29 +572,29 @@ exit:
 	buf_discard(buf);
 }
 
-static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id)
+static void port_print(struct tipc_port *p_ptr, struct print_buf *buf, int full_id)
 {
 	struct publication *publ;
 
 	if (full_id)
 		tipc_printf(buf, "<%u.%u.%u:%u>:",
 			    tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr),
-			    tipc_node(tipc_own_addr), p_ptr->publ.ref);
+			    tipc_node(tipc_own_addr), p_ptr->ref);
 	else
-		tipc_printf(buf, "%-10u:", p_ptr->publ.ref);
+		tipc_printf(buf, "%-10u:", p_ptr->ref);
 
-	if (p_ptr->publ.connected) {
+	if (p_ptr->connected) {
 		u32 dport = port_peerport(p_ptr);
 		u32 destnode = port_peernode(p_ptr);
 
 		tipc_printf(buf, " connected to <%u.%u.%u:%u>",
 			    tipc_zone(destnode), tipc_cluster(destnode),
 			    tipc_node(destnode), dport);
-		if (p_ptr->publ.conn_type != 0)
+		if (p_ptr->conn_type != 0)
 			tipc_printf(buf, " via {%u,%u}",
-				    p_ptr->publ.conn_type,
-				    p_ptr->publ.conn_instance);
-	} else if (p_ptr->publ.published) {
+				    p_ptr->conn_type,
+				    p_ptr->conn_instance);
+	} else if (p_ptr->published) {
 		tipc_printf(buf, " bound to");
 		list_for_each_entry(publ, &p_ptr->publications, pport_list) {
 			if (publ->lower == publ->upper)
@@ -639,7 +615,7 @@ struct sk_buff *tipc_port_get_ports(void)
 	struct sk_buff *buf;
 	struct tlv_desc *rep_tlv;
 	struct print_buf pb;
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	int str_len;
 
 	buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY));
@@ -650,9 +626,9 @@ struct sk_buff *tipc_port_get_ports(void)
 	tipc_printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY);
 	spin_lock_bh(&tipc_port_list_lock);
 	list_for_each_entry(p_ptr, &ports, port_list) {
-		spin_lock_bh(p_ptr->publ.lock);
+		spin_lock_bh(p_ptr->lock);
 		port_print(p_ptr, &pb, 0);
-		spin_unlock_bh(p_ptr->publ.lock);
+		spin_unlock_bh(p_ptr->lock);
 	}
 	spin_unlock_bh(&tipc_port_list_lock);
 	str_len = tipc_printbuf_validate(&pb);
@@ -665,12 +641,12 @@ struct sk_buff *tipc_port_get_ports(void)
 
 void tipc_port_reinit(void)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg;
 
 	spin_lock_bh(&tipc_port_list_lock);
 	list_for_each_entry(p_ptr, &ports, port_list) {
-		msg = &p_ptr->publ.phdr;
+		msg = &p_ptr->phdr;
 		if (msg_orignode(msg) == tipc_own_addr)
 			break;
 		msg_set_prevnode(msg, tipc_own_addr);
@@ -695,7 +671,7 @@ static void port_dispatcher_sigh(void *dummy)
 	spin_unlock_bh(&queue_lock);
 
 	while (buf) {
-		struct port *p_ptr;
+		struct tipc_port *p_ptr;
 		struct user_port *up_ptr;
 		struct tipc_portid orig;
 		struct tipc_name_seq dseq;
@@ -720,8 +696,8 @@ static void port_dispatcher_sigh(void *dummy)
 		orig.node = msg_orignode(msg);
 		up_ptr = p_ptr->user_port;
 		usr_handle = up_ptr->usr_handle;
-		connected = p_ptr->publ.connected;
-		published = p_ptr->publ.published;
+		connected = p_ptr->connected;
+		published = p_ptr->published;
 
 		if (unlikely(msg_errcode(msg)))
 			goto err;
@@ -732,6 +708,7 @@ static void port_dispatcher_sigh(void *dummy)
 				tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
 				u32 peer_port = port_peerport(p_ptr);
 				u32 peer_node = port_peernode(p_ptr);
+				u32 dsz;
 
 				tipc_port_unlock(p_ptr);
 				if (unlikely(!cb))
@@ -742,13 +719,14 @@ static void port_dispatcher_sigh(void *dummy)
 				} else if ((msg_origport(msg) != peer_port) ||
 					   (msg_orignode(msg) != peer_node))
 					goto reject;
-				if (unlikely(++p_ptr->publ.conn_unacked >=
-					     TIPC_FLOW_CONTROL_WIN))
+				dsz = msg_data_sz(msg);
+				if (unlikely(dsz &&
+					     (++p_ptr->conn_unacked >=
+					      TIPC_FLOW_CONTROL_WIN)))
 					tipc_acknowledge(dref,
-							 p_ptr->publ.conn_unacked);
+							 p_ptr->conn_unacked);
 				skb_pull(buf, msg_hdr_sz(msg));
-				cb(usr_handle, dref, &buf, msg_data(msg),
-				   msg_data_sz(msg));
+				cb(usr_handle, dref, &buf, msg_data(msg), dsz);
 				break;
 			}
 		case TIPC_DIRECT_MSG:{
@@ -872,7 +850,7 @@ static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf)
 
 static void port_wakeup_sh(unsigned long ref)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct user_port *up_ptr;
 	tipc_continue_event cb = NULL;
 	void *uh = NULL;
@@ -898,14 +876,14 @@ static void port_wakeup(struct tipc_port *p_ptr)
 
 void tipc_acknowledge(u32 ref, u32 ack)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct sk_buff *buf = NULL;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return;
-	if (p_ptr->publ.connected) {
-		p_ptr->publ.conn_unacked -= ack;
+	if (p_ptr->connected) {
+		p_ptr->conn_unacked -= ack;
 		buf = port_build_proto_msg(port_peerport(p_ptr),
 					   port_peernode(p_ptr),
 					   ref,
@@ -913,7 +891,6 @@ void tipc_acknowledge(u32 ref, u32 ack)
 					   CONN_MANAGER,
 					   CONN_ACK,
 					   TIPC_OK,
-					   port_out_seqno(p_ptr),
 					   ack);
 	}
 	tipc_port_unlock(p_ptr);
@@ -936,14 +913,14 @@ int tipc_createport(void *usr_handle,
 		    u32 *portref)
 {
 	struct user_port *up_ptr;
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	up_ptr = kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
 	if (!up_ptr) {
 		warn("Port creation failed, no memory\n");
 		return -ENOMEM;
 	}
-	p_ptr = (struct port *)tipc_createport_raw(NULL, port_dispatcher,
+	p_ptr = (struct tipc_port *)tipc_createport_raw(NULL, port_dispatcher,
 						   port_wakeup, importance);
 	if (!p_ptr) {
 		kfree(up_ptr);
@@ -952,7 +929,7 @@ int tipc_createport(void *usr_handle,
 
 	p_ptr->user_port = up_ptr;
 	up_ptr->usr_handle = usr_handle;
-	up_ptr->ref = p_ptr->publ.ref;
+	up_ptr->ref = p_ptr->ref;
 	up_ptr->err_cb = error_cb;
 	up_ptr->named_err_cb = named_error_cb;
 	up_ptr->conn_err_cb = conn_error_cb;
@@ -960,26 +937,26 @@ int tipc_createport(void *usr_handle,
 	up_ptr->named_msg_cb = named_msg_cb;
 	up_ptr->conn_msg_cb = conn_msg_cb;
 	up_ptr->continue_event_cb = continue_event_cb;
-	*portref = p_ptr->publ.ref;
+	*portref = p_ptr->ref;
 	tipc_port_unlock(p_ptr);
 	return 0;
 }
 
 int tipc_portimportance(u32 ref, unsigned int *importance)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	*importance = (unsigned int)msg_importance(&p_ptr->publ.phdr);
+	*importance = (unsigned int)msg_importance(&p_ptr->phdr);
 	tipc_port_unlock(p_ptr);
 	return 0;
 }
 
 int tipc_set_portimportance(u32 ref, unsigned int imp)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 
 	if (imp > TIPC_CRITICAL_IMPORTANCE)
 		return -EINVAL;
@@ -987,7 +964,7 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	msg_set_importance(&p_ptr->publ.phdr, (u32)imp);
+	msg_set_importance(&p_ptr->phdr, (u32)imp);
 	tipc_port_unlock(p_ptr);
 	return 0;
 }
@@ -995,7 +972,7 @@ int tipc_set_portimportance(u32 ref, unsigned int imp)
 
 int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct publication *publ;
 	u32 key;
 	int res = -EINVAL;
@@ -1004,7 +981,7 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
 	if (!p_ptr)
 		return -EINVAL;
 
-	if (p_ptr->publ.connected)
+	if (p_ptr->connected)
 		goto exit;
 	if (seq->lower > seq->upper)
 		goto exit;
@@ -1016,11 +993,11 @@ int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
 		goto exit;
 	}
 	publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
-				    scope, p_ptr->publ.ref, key);
+				    scope, p_ptr->ref, key);
 	if (publ) {
 		list_add(&publ->pport_list, &p_ptr->publications);
 		p_ptr->pub_count++;
-		p_ptr->publ.published = 1;
+		p_ptr->published = 1;
 		res = 0;
 	}
 exit:
@@ -1030,7 +1007,7 @@ exit:
 
 int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct publication *publ;
 	struct publication *tpubl;
 	int res = -EINVAL;
@@ -1063,37 +1040,36 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
 		}
 	}
 	if (list_empty(&p_ptr->publications))
-		p_ptr->publ.published = 0;
+		p_ptr->published = 0;
 	tipc_port_unlock(p_ptr);
 	return res;
 }
 
 int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg;
 	int res = -EINVAL;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	if (p_ptr->publ.published || p_ptr->publ.connected)
+	if (p_ptr->published || p_ptr->connected)
 		goto exit;
 	if (!peer->ref)
 		goto exit;
 
-	msg = &p_ptr->publ.phdr;
+	msg = &p_ptr->phdr;
 	msg_set_destnode(msg, peer->node);
 	msg_set_destport(msg, peer->ref);
 	msg_set_orignode(msg, tipc_own_addr);
-	msg_set_origport(msg, p_ptr->publ.ref);
-	msg_set_transp_seqno(msg, 42);
+	msg_set_origport(msg, p_ptr->ref);
 	msg_set_type(msg, TIPC_CONN_MSG);
 	msg_set_hdr_sz(msg, SHORT_H_SIZE);
 
 	p_ptr->probing_interval = PROBING_INTERVAL;
 	p_ptr->probing_state = CONFIRMED;
-	p_ptr->publ.connected = 1;
+	p_ptr->connected = 1;
 	k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
 
 	tipc_nodesub_subscribe(&p_ptr->subscription, peer->node,
@@ -1102,7 +1078,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
 	res = 0;
 exit:
 	tipc_port_unlock(p_ptr);
-	p_ptr->publ.max_pkt = tipc_link_get_max_pkt(peer->node, ref);
+	p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
 	return res;
 }
 
@@ -1120,7 +1096,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr)
 		tp_ptr->connected = 0;
 		/* let timer expire on it's own to avoid deadlock! */
 		tipc_nodesub_unsubscribe(
-			&((struct port *)tp_ptr)->subscription);
+			&((struct tipc_port *)tp_ptr)->subscription);
 		res = 0;
 	} else {
 		res = -ENOTCONN;
@@ -1135,7 +1111,7 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr)
 
 int tipc_disconnect(u32 ref)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	int res;
 
 	p_ptr = tipc_port_lock(ref);
@@ -1151,15 +1127,15 @@ int tipc_disconnect(u32 ref)
  */
 int tipc_shutdown(u32 ref)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct sk_buff *buf = NULL;
 
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
 
-	if (p_ptr->publ.connected) {
-		u32 imp = msg_importance(&p_ptr->publ.phdr);
+	if (p_ptr->connected) {
+		u32 imp = msg_importance(&p_ptr->phdr);
 		if (imp < TIPC_CRITICAL_IMPORTANCE)
 			imp++;
 		buf = port_build_proto_msg(port_peerport(p_ptr),
@@ -1169,7 +1145,6 @@ int tipc_shutdown(u32 ref)
 					   imp,
 					   TIPC_CONN_MSG,
 					   TIPC_CONN_SHUTDOWN,
-					   port_out_seqno(p_ptr),
 					   0);
 	}
 	tipc_port_unlock(p_ptr);
@@ -1182,13 +1157,13 @@ int tipc_shutdown(u32 ref)
  *                        message for this node.
  */
 
-static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,
+static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect,
 				   struct iovec const *msg_sect)
 {
 	struct sk_buff *buf;
 	int res;
 
-	res = tipc_msg_build(&sender->publ.phdr, msg_sect, num_sect,
+	res = tipc_msg_build(&sender->phdr, msg_sect, num_sect,
 			MAX_MSG_SIZE, !sender->user_port, &buf);
 	if (likely(buf))
 		tipc_port_recv_msg(buf);
@@ -1201,15 +1176,15 @@ static int tipc_port_recv_sections(struct port *sender, unsigned int num_sect,
 
 int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	u32 destnode;
 	int res;
 
 	p_ptr = tipc_port_deref(ref);
-	if (!p_ptr || !p_ptr->publ.connected)
+	if (!p_ptr || !p_ptr->connected)
 		return -EINVAL;
 
-	p_ptr->publ.congested = 1;
+	p_ptr->congested = 1;
 	if (!tipc_port_congested(p_ptr)) {
 		destnode = port_peernode(p_ptr);
 		if (likely(destnode != tipc_own_addr))
@@ -1219,14 +1194,14 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
 			res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
 
 		if (likely(res != -ELINKCONG)) {
-			port_incr_out_seqno(p_ptr);
-			p_ptr->publ.congested = 0;
-			p_ptr->sent++;
+			p_ptr->congested = 0;
+			if (res > 0)
+				p_ptr->sent++;
 			return res;
 		}
 	}
 	if (port_unreliable(p_ptr)) {
-		p_ptr->publ.congested = 0;
+		p_ptr->congested = 0;
 		/* Just calculate msg length and return */
 		return tipc_msg_calc_data_size(msg_sect, num_sect);
 	}
@@ -1240,17 +1215,17 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect)
 int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
 	   unsigned int num_sect, struct iovec const *msg_sect)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg;
 	u32 destnode = domain;
 	u32 destport;
 	int res;
 
 	p_ptr = tipc_port_deref(ref);
-	if (!p_ptr || p_ptr->publ.connected)
+	if (!p_ptr || p_ptr->connected)
 		return -EINVAL;
 
-	msg = &p_ptr->publ.phdr;
+	msg = &p_ptr->phdr;
 	msg_set_type(msg, TIPC_NAMED_MSG);
 	msg_set_orignode(msg, tipc_own_addr);
 	msg_set_origport(msg, ref);
@@ -1263,13 +1238,17 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
 	msg_set_destport(msg, destport);
 
 	if (likely(destport)) {
-		p_ptr->sent++;
 		if (likely(destnode == tipc_own_addr))
-			return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
-		res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
-						   destnode);
-		if (likely(res != -ELINKCONG))
+			res = tipc_port_recv_sections(p_ptr, num_sect,
+						      msg_sect);
+		else
+			res = tipc_link_send_sections_fast(p_ptr, msg_sect,
+							   num_sect, destnode);
+		if (likely(res != -ELINKCONG)) {
+			if (res > 0)
+				p_ptr->sent++;
 			return res;
+		}
 		if (port_unreliable(p_ptr)) {
 			/* Just calculate msg length and return */
 			return tipc_msg_calc_data_size(msg_sect, num_sect);
@@ -1287,27 +1266,32 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain,
 int tipc_send2port(u32 ref, struct tipc_portid const *dest,
 	   unsigned int num_sect, struct iovec const *msg_sect)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg;
 	int res;
 
 	p_ptr = tipc_port_deref(ref);
-	if (!p_ptr || p_ptr->publ.connected)
+	if (!p_ptr || p_ptr->connected)
 		return -EINVAL;
 
-	msg = &p_ptr->publ.phdr;
+	msg = &p_ptr->phdr;
 	msg_set_type(msg, TIPC_DIRECT_MSG);
 	msg_set_orignode(msg, tipc_own_addr);
 	msg_set_origport(msg, ref);
 	msg_set_destnode(msg, dest->node);
 	msg_set_destport(msg, dest->ref);
 	msg_set_hdr_sz(msg, DIR_MSG_H_SIZE);
-	p_ptr->sent++;
+
 	if (dest->node == tipc_own_addr)
-		return tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
-	res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node);
-	if (likely(res != -ELINKCONG))
+		res =  tipc_port_recv_sections(p_ptr, num_sect, msg_sect);
+	else
+		res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect,
+						   dest->node);
+	if (likely(res != -ELINKCONG)) {
+		if (res > 0)
+			p_ptr->sent++;
 		return res;
+	}
 	if (port_unreliable(p_ptr)) {
 		/* Just calculate msg length and return */
 		return tipc_msg_calc_data_size(msg_sect, num_sect);
@@ -1322,15 +1306,15 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest,
 int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
 	       struct sk_buff *buf, unsigned int dsz)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg;
 	int res;
 
-	p_ptr = (struct port *)tipc_ref_deref(ref);
-	if (!p_ptr || p_ptr->publ.connected)
+	p_ptr = (struct tipc_port *)tipc_ref_deref(ref);
+	if (!p_ptr || p_ptr->connected)
 		return -EINVAL;
 
-	msg = &p_ptr->publ.phdr;
+	msg = &p_ptr->phdr;
 	msg_set_type(msg, TIPC_DIRECT_MSG);
 	msg_set_orignode(msg, tipc_own_addr);
 	msg_set_origport(msg, ref);
@@ -1343,12 +1327,16 @@ int tipc_send_buf2port(u32 ref, struct tipc_portid const *dest,
 
 	skb_push(buf, DIR_MSG_H_SIZE);
 	skb_copy_to_linear_data(buf, msg, DIR_MSG_H_SIZE);
-	p_ptr->sent++;
+
 	if (dest->node == tipc_own_addr)
-		return tipc_port_recv_msg(buf);
-	res = tipc_send_buf_fast(buf, dest->node);
-	if (likely(res != -ELINKCONG))
+		res = tipc_port_recv_msg(buf);
+	else
+		res = tipc_send_buf_fast(buf, dest->node);
+	if (likely(res != -ELINKCONG)) {
+		if (res > 0)
+			p_ptr->sent++;
 		return res;
+	}
 	if (port_unreliable(p_ptr))
 		return dsz;
 	return -ELINKCONG;
diff --git a/net/tipc/port.h b/net/tipc/port.h
index 8e84b98..87b9424 100644
--- a/net/tipc/port.h
+++ b/net/tipc/port.h
@@ -2,7 +2,7 @@
  * net/tipc/port.h: Include file for TIPC port code
  *
  * Copyright (c) 1994-2007, Ericsson AB
- * Copyright (c) 2004-2007, Wind River Systems
+ * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -95,7 +95,7 @@ struct user_port {
 };
 
 /**
- * struct tipc_port - TIPC port info available to socket API
+ * struct tipc_port - TIPC port structure
  * @usr_handle: pointer to additional user-defined information about port
  * @lock: pointer to spinlock for controlling access to port
  * @connected: non-zero if port is currently connected to a peer port
@@ -107,43 +107,33 @@ struct user_port {
  * @max_pkt: maximum packet size "hint" used when building messages sent by port
  * @ref: unique reference to port in TIPC object registry
  * @phdr: preformatted message header used when sending messages
- */
-struct tipc_port {
-	void *usr_handle;
-	spinlock_t *lock;
-	int connected;
-	u32 conn_type;
-	u32 conn_instance;
-	u32 conn_unacked;
-	int published;
-	u32 congested;
-	u32 max_pkt;
-	u32 ref;
-	struct tipc_msg phdr;
-};
-
-/**
- * struct port - TIPC port structure
- * @publ: TIPC port info available to privileged users
  * @port_list: adjacent ports in TIPC's global list of ports
  * @dispatcher: ptr to routine which handles received messages
  * @wakeup: ptr to routine to call when port is no longer congested
  * @user_port: ptr to user port associated with port (if any)
  * @wait_list: adjacent ports in list of ports waiting on link congestion
  * @waiting_pkts:
- * @sent:
- * @acked:
+ * @sent: # of non-empty messages sent by port
+ * @acked: # of non-empty message acknowledgements from connected port's peer
  * @publications: list of publications for port
  * @pub_count: total # of publications port has made during its lifetime
  * @probing_state:
  * @probing_interval:
- * @last_in_seqno:
  * @timer_ref:
  * @subscription: "node down" subscription used to terminate failed connections
  */
-
-struct port {
-	struct tipc_port publ;
+struct tipc_port {
+	void *usr_handle;
+	spinlock_t *lock;
+	int connected;
+	u32 conn_type;
+	u32 conn_instance;
+	u32 conn_unacked;
+	int published;
+	u32 congested;
+	u32 max_pkt;
+	u32 ref;
+	struct tipc_msg phdr;
 	struct list_head port_list;
 	u32 (*dispatcher)(struct tipc_port *, struct sk_buff *);
 	void (*wakeup)(struct tipc_port *);
@@ -156,7 +146,6 @@ struct port {
 	u32 pub_count;
 	u32 probing_state;
 	u32 probing_interval;
-	u32 last_in_seqno;
 	struct timer_list timer;
 	struct tipc_node_subscr subscription;
 };
@@ -230,7 +219,7 @@ int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest,
 int tipc_multicast(u32 portref, struct tipc_name_seq const *seq,
 		unsigned int section_count, struct iovec const *msg);
 
-int tipc_port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
+int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr,
 			      struct iovec const *msg_sect, u32 num_sect,
 			      int err);
 struct sk_buff *tipc_port_get_ports(void);
@@ -242,9 +231,9 @@ void tipc_port_reinit(void);
  * tipc_port_lock - lock port instance referred to and return its pointer
  */
 
-static inline struct port *tipc_port_lock(u32 ref)
+static inline struct tipc_port *tipc_port_lock(u32 ref)
 {
-	return (struct port *)tipc_ref_lock(ref);
+	return (struct tipc_port *)tipc_ref_lock(ref);
 }
 
 /**
@@ -253,27 +242,27 @@ static inline struct port *tipc_port_lock(u32 ref)
  * Can use pointer instead of tipc_ref_unlock() since port is already locked.
  */
 
-static inline void tipc_port_unlock(struct port *p_ptr)
+static inline void tipc_port_unlock(struct tipc_port *p_ptr)
 {
-	spin_unlock_bh(p_ptr->publ.lock);
+	spin_unlock_bh(p_ptr->lock);
 }
 
-static inline struct port *tipc_port_deref(u32 ref)
+static inline struct tipc_port *tipc_port_deref(u32 ref)
 {
-	return (struct port *)tipc_ref_deref(ref);
+	return (struct tipc_port *)tipc_ref_deref(ref);
 }
 
-static inline u32 tipc_peer_port(struct port *p_ptr)
+static inline u32 tipc_peer_port(struct tipc_port *p_ptr)
 {
-	return msg_destport(&p_ptr->publ.phdr);
+	return msg_destport(&p_ptr->phdr);
 }
 
-static inline u32 tipc_peer_node(struct port *p_ptr)
+static inline u32 tipc_peer_node(struct tipc_port *p_ptr)
 {
-	return msg_destnode(&p_ptr->publ.phdr);
+	return msg_destnode(&p_ptr->phdr);
 }
 
-static inline int tipc_port_congested(struct port *p_ptr)
+static inline int tipc_port_congested(struct tipc_port *p_ptr)
 {
 	return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2);
 }
@@ -284,7 +273,7 @@ static inline int tipc_port_congested(struct port *p_ptr)
 
 static inline int tipc_port_recv_msg(struct sk_buff *buf)
 {
-	struct port *p_ptr;
+	struct tipc_port *p_ptr;
 	struct tipc_msg *msg = buf_msg(buf);
 	u32 destport = msg_destport(msg);
 	u32 dsz = msg_data_sz(msg);
@@ -299,7 +288,7 @@ static inline int tipc_port_recv_msg(struct sk_buff *buf)
 	/* validate destination & pass to port, otherwise reject message */
 	p_ptr = tipc_port_lock(destport);
 	if (likely(p_ptr)) {
-		if (likely(p_ptr->publ.connected)) {
+		if (likely(p_ptr->connected)) {
 			if ((unlikely(msg_origport(msg) != tipc_peer_port(p_ptr))) ||
 			    (unlikely(msg_orignode(msg) != tipc_peer_node(p_ptr))) ||
 			    (unlikely(!msg_connected(msg)))) {
@@ -308,7 +297,7 @@ static inline int tipc_port_recv_msg(struct sk_buff *buf)
 				goto reject;
 			}
 		}
-		err = p_ptr->dispatcher(&p_ptr->publ, buf);
+		err = p_ptr->dispatcher(p_ptr, buf);
 		tipc_port_unlock(p_ptr);
 		if (likely(!err))
 			return dsz;
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 2b02a3a..29d94d5 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2,7 +2,7 @@
  * net/tipc/socket.c: TIPC socket API
  *
  * Copyright (c) 2001-2007, Ericsson AB
- * Copyright (c) 2004-2008, Wind River Systems
+ * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -58,6 +58,9 @@ struct tipc_sock {
 #define tipc_sk(sk) ((struct tipc_sock *)(sk))
 #define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
 
+#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
+			(sock->state == SS_DISCONNECTING))
+
 static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
 static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
 static void wakeupdispatch(struct tipc_port *tport);
@@ -241,7 +244,6 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
 			tipc_set_portunreliable(tp_ptr->ref, 1);
 	}
 
-	atomic_inc(&tipc_user_count);
 	return 0;
 }
 
@@ -290,7 +292,7 @@ static int release(struct socket *sock)
 		if (buf == NULL)
 			break;
 		atomic_dec(&tipc_queue_size);
-		if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf)))
+		if (TIPC_SKB_CB(buf)->handle != 0)
 			buf_discard(buf);
 		else {
 			if ((sock->state == SS_CONNECTING) ||
@@ -321,7 +323,6 @@ static int release(struct socket *sock)
 	sock_put(sk);
 	sock->sk = NULL;
 
-	atomic_dec(&tipc_user_count);
 	return res;
 }
 
@@ -495,6 +496,8 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m)
 	if (likely(dest->addr.name.name.type != TIPC_CFG_SRV))
 		return -EACCES;
 
+	if (!m->msg_iovlen || (m->msg_iov[0].iov_len < sizeof(hdr)))
+		return -EMSGSIZE;
 	if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
 		return -EFAULT;
 	if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
@@ -911,15 +914,13 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
 	struct tipc_port *tport = tipc_sk_port(sk);
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
+	long timeout;
 	unsigned int sz;
 	u32 err;
 	int res;
 
 	/* Catch invalid receive requests */
 
-	if (m->msg_iovlen != 1)
-		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
-
 	if (unlikely(!buf_len))
 		return -EINVAL;
 
@@ -930,6 +931,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
 		goto exit;
 	}
 
+	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
 	/* Look for a message in receive queue; wait if necessary */
@@ -939,17 +941,15 @@ restart:
 			res = -ENOTCONN;
 			goto exit;
 		}
-		if (flags & MSG_DONTWAIT) {
-			res = -EWOULDBLOCK;
+		if (timeout <= 0L) {
+			res = timeout ? timeout : -EWOULDBLOCK;
 			goto exit;
 		}
 		release_sock(sk);
-		res = wait_event_interruptible(*sk_sleep(sk),
-			(!skb_queue_empty(&sk->sk_receive_queue) ||
-			 (sock->state == SS_DISCONNECTING)));
+		timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
+							   tipc_rx_ready(sock),
+							   timeout);
 		lock_sock(sk);
-		if (res)
-			goto exit;
 	}
 
 	/* Look at first message in receive queue */
@@ -991,11 +991,10 @@ restart:
 			sz = buf_len;
 			m->msg_flags |= MSG_TRUNC;
 		}
-		if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg),
-					  sz))) {
-			res = -EFAULT;
+		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg),
+					      m->msg_iov, sz);
+		if (res)
 			goto exit;
-		}
 		res = sz;
 	} else {
 		if ((sock->state == SS_READY) ||
@@ -1038,19 +1037,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
 	struct tipc_port *tport = tipc_sk_port(sk);
 	struct sk_buff *buf;
 	struct tipc_msg *msg;
+	long timeout;
 	unsigned int sz;
 	int sz_to_copy, target, needed;
 	int sz_copied = 0;
-	char __user *crs = m->msg_iov->iov_base;
-	unsigned char *buf_crs;
 	u32 err;
 	int res = 0;
 
 	/* Catch invalid receive attempts */
 
-	if (m->msg_iovlen != 1)
-		return -EOPNOTSUPP;   /* Don't do multiple iovec entries yet */
-
 	if (unlikely(!buf_len))
 		return -EINVAL;
 
@@ -1063,7 +1058,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
 	}
 
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
-
+	timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
 restart:
 
 	/* Look for a message in receive queue; wait if necessary */
@@ -1073,17 +1068,15 @@ restart:
 			res = -ENOTCONN;
 			goto exit;
 		}
-		if (flags & MSG_DONTWAIT) {
-			res = -EWOULDBLOCK;
+		if (timeout <= 0L) {
+			res = timeout ? timeout : -EWOULDBLOCK;
 			goto exit;
 		}
 		release_sock(sk);
-		res = wait_event_interruptible(*sk_sleep(sk),
-			(!skb_queue_empty(&sk->sk_receive_queue) ||
-			 (sock->state == SS_DISCONNECTING)));
+		timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
+							   tipc_rx_ready(sock),
+							   timeout);
 		lock_sock(sk);
-		if (res)
-			goto exit;
 	}
 
 	/* Look at first message in receive queue */
@@ -1112,24 +1105,25 @@ restart:
 	/* Capture message data (if valid) & compute return value (always) */
 
 	if (!err) {
-		buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle);
-		sz = (unsigned char *)msg + msg_size(msg) - buf_crs;
+		u32 offset = (u32)(unsigned long)(TIPC_SKB_CB(buf)->handle);
 
+		sz -= offset;
 		needed = (buf_len - sz_copied);
 		sz_to_copy = (sz <= needed) ? sz : needed;
-		if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) {
-			res = -EFAULT;
+
+		res = skb_copy_datagram_iovec(buf, msg_hdr_sz(msg) + offset,
+					      m->msg_iov, sz_to_copy);
+		if (res)
 			goto exit;
-		}
+
 		sz_copied += sz_to_copy;
 
 		if (sz_to_copy < sz) {
 			if (!(flags & MSG_PEEK))
-				TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy;
+				TIPC_SKB_CB(buf)->handle =
+				(void *)(unsigned long)(offset + sz_to_copy);
 			goto exit;
 		}
-
-		crs += sz_to_copy;
 	} else {
 		if (sz_copied != 0)
 			goto exit; /* can't add error msg to valid data */
@@ -1256,7 +1250,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
 
 	/* Enqueue message (finally!) */
 
-	TIPC_SKB_CB(buf)->handle = msg_data(msg);
+	TIPC_SKB_CB(buf)->handle = 0;
 	atomic_inc(&tipc_queue_size);
 	__skb_queue_tail(&sk->sk_receive_queue, buf);
 
@@ -1608,7 +1602,7 @@ restart:
 		buf = __skb_dequeue(&sk->sk_receive_queue);
 		if (buf) {
 			atomic_dec(&tipc_queue_size);
-			if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) {
+			if (TIPC_SKB_CB(buf)->handle != 0) {
 				buf_discard(buf);
 				goto restart;
 			}
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index ca04479..aae9eae 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -2,7 +2,7 @@
  * net/tipc/subscr.c: TIPC network topology service
  *
  * Copyright (c) 2000-2006, Ericsson AB
- * Copyright (c) 2005-2007, Wind River Systems
+ * Copyright (c) 2005-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -160,7 +160,7 @@ void tipc_subscr_report_overlap(struct subscription *sub,
 
 static void subscr_timeout(struct subscription *sub)
 {
-	struct port *server_port;
+	struct tipc_port *server_port;
 
 	/* Validate server port reference (in case subscriber is terminating) */
 
@@ -472,8 +472,6 @@ static void subscr_named_msg_event(void *usr_handle,
 				   struct tipc_portid const *orig,
 				   struct tipc_name_seq const *dest)
 {
-	static struct iovec msg_sect = {NULL, 0};
-
 	struct subscriber *subscriber;
 	u32 server_port_ref;
 
@@ -508,7 +506,7 @@ static void subscr_named_msg_event(void *usr_handle,
 
 	/* Lock server port (& save lock address for future use) */
 
-	subscriber->lock = tipc_port_lock(subscriber->port_ref)->publ.lock;
+	subscriber->lock = tipc_port_lock(subscriber->port_ref)->lock;
 
 	/* Add subscriber to topology server's subscriber list */
 
@@ -523,7 +521,7 @@ static void subscr_named_msg_event(void *usr_handle,
 
 	/* Send an ACK- to complete connection handshaking */
 
-	tipc_send(server_port_ref, 1, &msg_sect);
+	tipc_send(server_port_ref, 0, NULL);
 
 	/* Handle optional subscription request */
 
@@ -542,7 +540,6 @@ int tipc_subscr_start(void)
 	spin_lock_init(&topsrv.lock);
 	INIT_LIST_HEAD(&topsrv.subscriber_list);
 
-	spin_lock_bh(&topsrv.lock);
 	res = tipc_createport(NULL,
 			      TIPC_CRITICAL_IMPORTANCE,
 			      NULL,
@@ -563,12 +560,10 @@ int tipc_subscr_start(void)
 		goto failed;
 	}
 
-	spin_unlock_bh(&topsrv.lock);
 	return 0;
 
 failed:
 	err("Failed to create subscription service\n");
-	spin_unlock_bh(&topsrv.lock);
 	return res;
 }
 
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 437a99e..1663e1a 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -850,7 +850,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 		 * Get the parent directory, calculate the hash for last
 		 * component.
 		 */
-		err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
+		err = kern_path_parent(sunaddr->sun_path, &nd);
 		if (err)
 			goto out_mknod_parent;
 
@@ -1124,7 +1124,7 @@ restart:
 
 	/* Latch our state.
 
-	   It is tricky place. We need to grab write lock and cannot
+	   It is tricky place. We need to grab our state lock and cannot
 	   drop lock on peer. It is dangerous because deadlock is
 	   possible. Connect to self case and simultaneous
 	   attempt to connect are eliminated by checking socket
@@ -1171,7 +1171,7 @@ restart:
 	newsk->sk_type		= sk->sk_type;
 	init_peercred(newsk);
 	newu = unix_sk(newsk);
-	newsk->sk_wq		= &newu->peer_wq;
+	RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
 	otheru = unix_sk(other);
 
 	/* copy address information from listening to new sock*/
@@ -1475,6 +1475,12 @@ restart:
 			goto out_free;
 	}
 
+	if (sk_filter(other, skb) < 0) {
+		/* Toss the packet but do not return any error to the sender */
+		err = len;
+		goto out_free;
+	}
+
 	unix_state_lock(other);
 	err = -EPERM;
 	if (!unix_may_send(sk, other))
@@ -1561,7 +1567,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
 	struct sock *other = NULL;
-	struct sockaddr_un *sunaddr = msg->msg_name;
 	int err, size;
 	struct sk_buff *skb;
 	int sent = 0;
@@ -1584,7 +1589,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
 		err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
 		goto out_err;
 	} else {
-		sunaddr = NULL;
 		err = -ENOTCONN;
 		other = unix_peer(sk);
 		if (!other)
@@ -1987,36 +1991,38 @@ static int unix_shutdown(struct socket *sock, int mode)
 
 	mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN);
 
-	if (mode) {
-		unix_state_lock(sk);
-		sk->sk_shutdown |= mode;
-		other = unix_peer(sk);
-		if (other)
-			sock_hold(other);
-		unix_state_unlock(sk);
-		sk->sk_state_change(sk);
-
-		if (other &&
-			(sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
-
-			int peer_mode = 0;
-
-			if (mode&RCV_SHUTDOWN)
-				peer_mode |= SEND_SHUTDOWN;
-			if (mode&SEND_SHUTDOWN)
-				peer_mode |= RCV_SHUTDOWN;
-			unix_state_lock(other);
-			other->sk_shutdown |= peer_mode;
-			unix_state_unlock(other);
-			other->sk_state_change(other);
-			if (peer_mode == SHUTDOWN_MASK)
-				sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
-			else if (peer_mode & RCV_SHUTDOWN)
-				sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
-		}
-		if (other)
-			sock_put(other);
+	if (!mode)
+		return 0;
+
+	unix_state_lock(sk);
+	sk->sk_shutdown |= mode;
+	other = unix_peer(sk);
+	if (other)
+		sock_hold(other);
+	unix_state_unlock(sk);
+	sk->sk_state_change(sk);
+
+	if (other &&
+		(sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) {
+
+		int peer_mode = 0;
+
+		if (mode&RCV_SHUTDOWN)
+			peer_mode |= SEND_SHUTDOWN;
+		if (mode&SEND_SHUTDOWN)
+			peer_mode |= RCV_SHUTDOWN;
+		unix_state_lock(other);
+		other->sk_shutdown |= peer_mode;
+		unix_state_unlock(other);
+		other->sk_state_change(other);
+		if (peer_mode == SHUTDOWN_MASK)
+			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP);
+		else if (peer_mode & RCV_SHUTDOWN)
+			sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN);
 	}
+	if (other)
+		sock_put(other);
+
 	return 0;
 }
 
diff --git a/net/unix/garbage.c b/net/unix/garbage.c
index f89f83b..b6f4b99 100644
--- a/net/unix/garbage.c
+++ b/net/unix/garbage.c
@@ -104,7 +104,7 @@ struct sock *unix_get_socket(struct file *filp)
 	/*
 	 *	Socket ?
 	 */
-	if (S_ISSOCK(inode->i_mode)) {
+	if (S_ISSOCK(inode->i_mode) && !(filp->f_mode & FMODE_PATH)) {
 		struct socket *sock = SOCKET_I(inode);
 		struct sock *s = sock->sk;
 
diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c
index 74944a2..788a12c 100644
--- a/net/wanrouter/wanmain.c
+++ b/net/wanrouter/wanmain.c
@@ -59,8 +59,6 @@
 #include <asm/uaccess.h>        /* copy_to/from_user */
 #include <linux/init.h>         /* __initfunc et al. */
 
-#define KMEM_SAFETYZONE 8
-
 #define DEV_TO_SLAVE(dev)	(*((struct net_device **)netdev_priv(dev)))
 
 /*
diff --git a/net/wireless/core.c b/net/wireless/core.c
index e9a5f8c..fe01de2 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -718,13 +718,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
 			wdev->ps = false;
 		/* allow mac80211 to determine the timeout */
 		wdev->ps_timeout = -1;
-		if (rdev->ops->set_power_mgmt)
-			if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
-						      wdev->ps,
-						      wdev->ps_timeout)) {
-				/* assume this means it's off */
-				wdev->ps = false;
-			}
 
 		if (!dev->ethtool_ops)
 			dev->ethtool_ops = &cfg80211_ethtool_ops;
@@ -813,6 +806,19 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
 		rdev->opencount++;
 		mutex_unlock(&rdev->devlist_mtx);
 		cfg80211_unlock_rdev(rdev);
+
+		/*
+		 * Configure power management to the driver here so that its
+		 * correctly set also after interface type changes etc.
+		 */
+		if (wdev->iftype == NL80211_IFTYPE_STATION &&
+		    rdev->ops->set_power_mgmt)
+			if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
+						      wdev->ps,
+						      wdev->ps_timeout)) {
+				/* assume this means it's off */
+				wdev->ps = false;
+			}
 		break;
 	case NETDEV_UNREGISTER:
 		/*
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c
index ca4c825..9bde4d1 100644
--- a/net/wireless/ethtool.c
+++ b/net/wireless/ethtool.c
@@ -1,5 +1,6 @@
 #include <linux/utsname.h>
 #include <net/cfg80211.h>
+#include "core.h"
 #include "ethtool.h"
 
 static void cfg80211_get_drvinfo(struct net_device *dev,
@@ -37,9 +38,41 @@ static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 	regs->len = 0;
 }
 
+static void cfg80211_get_ringparam(struct net_device *dev,
+				   struct ethtool_ringparam *rp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+
+	memset(rp, 0, sizeof(*rp));
+
+	if (rdev->ops->get_ringparam)
+		rdev->ops->get_ringparam(wdev->wiphy,
+					 &rp->tx_pending, &rp->tx_max_pending,
+					 &rp->rx_pending, &rp->rx_max_pending);
+}
+
+static int cfg80211_set_ringparam(struct net_device *dev,
+				  struct ethtool_ringparam *rp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+
+	if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
+		return -EINVAL;
+
+	if (rdev->ops->set_ringparam)
+		return rdev->ops->set_ringparam(wdev->wiphy,
+						rp->tx_pending, rp->rx_pending);
+
+	return -ENOTSUPP;
+}
+
 const struct ethtool_ops cfg80211_ethtool_ops = {
 	.get_drvinfo = cfg80211_get_drvinfo,
 	.get_regs_len = cfg80211_get_regs_len,
 	.get_regs = cfg80211_get_regs,
 	.get_link = ethtool_op_get_link,
+	.get_ringparam = cfg80211_get_ringparam,
+	.set_ringparam = cfg80211_set_ringparam,
 };
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9b62710..4ebce42 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct genl_info *info,
 	return 0;
 }
 
+static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
+				 int attr)
+{
+	struct nlattr *rate;
+	u16 bitrate;
+
+	rate = nla_nest_start(msg, attr);
+	if (!rate)
+		goto nla_put_failure;
+
+	/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
+	bitrate = cfg80211_calculate_bitrate(info);
+	if (bitrate > 0)
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
+
+	if (info->flags & RATE_INFO_FLAGS_MCS)
+		NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
+	if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+		NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+	if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
+		NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+	nla_nest_end(msg, rate);
+	return true;
+
+nla_put_failure:
+	return false;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				const u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr, *txrate;
-	u16 bitrate;
+	struct nlattr *sinfoattr;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
 			   sinfo->signal_avg);
 	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
-		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
-		if (!txrate)
+		if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
+					  NL80211_STA_INFO_TX_BITRATE))
+			goto nla_put_failure;
+	}
+	if (sinfo->filled & STATION_INFO_RX_BITRATE) {
+		if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
+					  NL80211_STA_INFO_RX_BITRATE))
 			goto nla_put_failure;
-
-		/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
-		bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
-		if (bitrate > 0)
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
-
-		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
-			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
-				    sinfo->txrate.mcs);
-		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
-			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
-		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
-			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
-
-		nla_nest_end(msg, txrate);
 	}
 	if (sinfo->filled & STATION_INFO_RX_PACKETS)
 		NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
@@ -2718,7 +2736,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 			     NL80211_CMD_GET_MESH_CONFIG);
 	if (!hdr)
-		goto nla_put_failure;
+		goto out;
 	pinfoattr = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
 	if (!pinfoattr)
 		goto nla_put_failure;
@@ -2759,6 +2777,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
 
  nla_put_failure:
 	genlmsg_cancel(msg, hdr);
+ out:
 	nlmsg_free(msg);
 	return -ENOBUFS;
 }
@@ -2954,7 +2973,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
 	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
 			     NL80211_CMD_GET_REG);
 	if (!hdr)
-		goto nla_put_failure;
+		goto put_failure;
 
 	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
 		cfg80211_regdomain->alpha2);
@@ -3001,6 +3020,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
 
 nla_put_failure:
 	genlmsg_cancel(msg, hdr);
+put_failure:
 	nlmsg_free(msg);
 	err = -EMSGSIZE;
 out:
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 37693b6..3332d5b 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -63,6 +63,10 @@ static struct regulatory_request *last_request;
 /* To trigger userspace events */
 static struct platform_device *reg_pdev;
 
+static struct device_type reg_device_type = {
+	.uevent = reg_device_uevent,
+};
+
 /*
  * Central wireless core regulatory domains, we only need two,
  * the current one and a world regulatory domain in case we have no
@@ -362,16 +366,11 @@ static inline void reg_regdb_query(const char *alpha2) {}
 
 /*
  * This lets us keep regulatory code which is updated on a regulatory
- * basis in userspace.
+ * basis in userspace. Country information is filled in by
+ * reg_device_uevent
  */
 static int call_crda(const char *alpha2)
 {
-	char country_env[9 + 2] = "COUNTRY=";
-	char *envp[] = {
-		country_env,
-		NULL
-	};
-
 	if (!is_world_regdom((char *) alpha2))
 		pr_info("Calling CRDA for country: %c%c\n",
 			alpha2[0], alpha2[1]);
@@ -381,10 +380,7 @@ static int call_crda(const char *alpha2)
 	/* query internal regulatory database (if it exists) */
 	reg_regdb_query(alpha2);
 
-	country_env[8] = alpha2[0];
-	country_env[9] = alpha2[1];
-
-	return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
+	return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
 }
 
 /* Used by nl80211 before kmalloc'ing our regulatory domain */
@@ -1801,9 +1797,9 @@ void regulatory_hint_disconnect(void)
 
 static bool freq_is_chan_12_13_14(u16 freq)
 {
-	if (freq == ieee80211_channel_to_frequency(12) ||
-	    freq == ieee80211_channel_to_frequency(13) ||
-	    freq == ieee80211_channel_to_frequency(14))
+	if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
+	    freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
+	    freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
 		return true;
 	return false;
 }
@@ -2087,6 +2083,25 @@ int set_regdom(const struct ieee80211_regdomain *rd)
 	return r;
 }
 
+#ifdef CONFIG_HOTPLUG
+int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	if (last_request && !last_request->processed) {
+		if (add_uevent_var(env, "COUNTRY=%c%c",
+				   last_request->alpha2[0],
+				   last_request->alpha2[1]))
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+#else
+int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	return -ENODEV;
+}
+#endif /* CONFIG_HOTPLUG */
+
 /* Caller must hold cfg80211_mutex */
 void reg_device_remove(struct wiphy *wiphy)
 {
@@ -2118,6 +2133,8 @@ int __init regulatory_init(void)
 	if (IS_ERR(reg_pdev))
 		return PTR_ERR(reg_pdev);
 
+	reg_pdev->dev.type = &reg_device_type;
+
 	spin_lock_init(&reg_requests_lock);
 	spin_lock_init(&reg_pending_beacons_lock);
 
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index c4695d0..b67d1c3 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -8,6 +8,7 @@ bool reg_is_valid_request(const char *alpha2);
 
 int regulatory_hint_user(const char *alpha2);
 
+int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 void reg_device_remove(struct wiphy *wiphy);
 
 int __init regulatory_init(void);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 7620ae2..6a750bc 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -29,29 +29,37 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
 }
 EXPORT_SYMBOL(ieee80211_get_response_rate);
 
-int ieee80211_channel_to_frequency(int chan)
+int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
 {
-	if (chan < 14)
-		return 2407 + chan * 5;
-
-	if (chan == 14)
-		return 2484;
-
-	/* FIXME: 802.11j 17.3.8.3.2 */
-	return (chan + 1000) * 5;
+	/* see 802.11 17.3.8.3.2 and Annex J
+	 * there are overlapping channel numbers in 5GHz and 2GHz bands */
+	if (band == IEEE80211_BAND_5GHZ) {
+		if (chan >= 182 && chan <= 196)
+			return 4000 + chan * 5;
+		else
+			return 5000 + chan * 5;
+	} else { /* IEEE80211_BAND_2GHZ */
+		if (chan == 14)
+			return 2484;
+		else if (chan < 14)
+			return 2407 + chan * 5;
+		else
+			return 0; /* not supported */
+	}
 }
 EXPORT_SYMBOL(ieee80211_channel_to_frequency);
 
 int ieee80211_frequency_to_channel(int freq)
 {
+	/* see 802.11 17.3.8.3.2 and Annex J */
 	if (freq == 2484)
 		return 14;
-
-	if (freq < 2484)
+	else if (freq < 2484)
 		return (freq - 2407) / 5;
-
-	/* FIXME: 802.11j 17.3.8.3.2 */
-	return freq/5 - 1000;
+	else if (freq >= 4910 && freq <= 4980)
+		return (freq - 4000) / 5;
+	else
+		return (freq - 5000) / 5;
 }
 EXPORT_SYMBOL(ieee80211_frequency_to_channel);
 
@@ -159,12 +167,15 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
 
 	/*
 	 * Disallow pairwise keys with non-zero index unless it's WEP
-	 * (because current deployments use pairwise WEP keys with
-	 * non-zero indizes but 802.11i clearly specifies to use zero)
+	 * or a vendor specific cipher (because current deployments use
+	 * pairwise WEP keys with non-zero indices and for vendor specific
+	 * ciphers this should be validated in the driver or hardware level
+	 * - but 802.11i clearly specifies to use zero)
 	 */
 	if (pairwise && key_idx &&
-	    params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
-	    params->cipher != WLAN_CIPHER_SUITE_WEP104)
+	    ((params->cipher == WLAN_CIPHER_SUITE_TKIP) ||
+	     (params->cipher == WLAN_CIPHER_SUITE_CCMP) ||
+	     (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC)))
 		return -EINVAL;
 
 	switch (params->cipher) {
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index d112f03..0bf169b 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -267,9 +267,12 @@ int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
 	 * -EINVAL for impossible things.
 	 */
 	if (freq->e == 0) {
+		enum ieee80211_band band = IEEE80211_BAND_2GHZ;
 		if (freq->m < 0)
 			return 0;
-		return ieee80211_channel_to_frequency(freq->m);
+		if (freq->m > 14)
+			band = IEEE80211_BAND_5GHZ;
+		return ieee80211_channel_to_frequency(freq->m, band);
 	} else {
 		int i, div = 1000000;
 		for (i = 0; i < freq->e; i++)
diff --git a/net/x25/Kconfig b/net/x25/Kconfig
index 2196e55..e6759c9 100644
--- a/net/x25/Kconfig
+++ b/net/x25/Kconfig
@@ -5,7 +5,6 @@
 config X25
 	tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
-	depends on BKL # should be fixable
 	---help---
 	  X.25 is a set of standardized network protocols, similar in scope to
 	  frame relay; the one physical line from your box to the X.25 network
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index ad96ee9..4680b1e 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -40,7 +40,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/smp_lock.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/net.h>
@@ -432,15 +431,6 @@ void x25_destroy_socket_from_timer(struct sock *sk)
 	sock_put(sk);
 }
 
-static void x25_destroy_socket(struct sock *sk)
-{
-	sock_hold(sk);
-	lock_sock(sk);
-	__x25_destroy_socket(sk);
-	release_sock(sk);
-	sock_put(sk);
-}
-
 /*
  *	Handling for system calls applied via the various interfaces to a
  *	X.25 socket object.
@@ -647,18 +637,19 @@ static int x25_release(struct socket *sock)
 	struct sock *sk = sock->sk;
 	struct x25_sock *x25;
 
-	lock_kernel();
 	if (!sk)
-		goto out;
+		return 0;
 
 	x25 = x25_sk(sk);
 
+	sock_hold(sk);
+	lock_sock(sk);
 	switch (x25->state) {
 
 		case X25_STATE_0:
 		case X25_STATE_2:
 			x25_disconnect(sk, 0, 0, 0);
-			x25_destroy_socket(sk);
+			__x25_destroy_socket(sk);
 			goto out;
 
 		case X25_STATE_1:
@@ -678,7 +669,8 @@ static int x25_release(struct socket *sock)
 
 	sock_orphan(sk);
 out:
-	unlock_kernel();
+	release_sock(sk);
+	sock_put(sk);
 	return 0;
 }
 
@@ -1085,7 +1077,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
 	size_t size;
 	int qbit = 0, rc = -EINVAL;
 
-	lock_kernel();
+	lock_sock(sk);
 	if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
 		goto out;
 
@@ -1148,7 +1140,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
 
 	size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
 
+	release_sock(sk);
 	skb = sock_alloc_send_skb(sk, size, noblock, &rc);
+	lock_sock(sk);
 	if (!skb)
 		goto out;
 	X25_SKB_CB(skb)->flags = msg->msg_flags;
@@ -1231,26 +1225,10 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
 			len++;
 	}
 
-	/*
-	 * lock_sock() is currently only used to serialize this x25_kick()
-	 * against input-driven x25_kick() calls. It currently only blocks
-	 * incoming packets for this socket and does not protect against
-	 * any other socket state changes and is not called from anywhere
-	 * else. As x25_kick() cannot block and as long as all socket
-	 * operations are BKL-wrapped, we don't need take to care about
-	 * purging the backlog queue in x25_release().
-	 *
-	 * Using lock_sock() to protect all socket operations entirely
-	 * (and making the whole x25 stack SMP aware) unfortunately would
-	 * require major changes to {send,recv}msg and skb allocation methods.
-	 * -> 2.5 ;)
-	 */
-	lock_sock(sk);
 	x25_kick(sk);
-	release_sock(sk);
 	rc = len;
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 out_kfree_skb:
 	kfree_skb(skb);
@@ -1271,7 +1249,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 	unsigned char *asmptr;
 	int rc = -ENOTCONN;
 
-	lock_kernel();
+	lock_sock(sk);
 	/*
 	 * This works for seqpacket too. The receiver has ordered the queue for
 	 * us! We do one quick check first though
@@ -1300,8 +1278,10 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 		msg->msg_flags |= MSG_OOB;
 	} else {
 		/* Now we can treat all alike */
+		release_sock(sk);
 		skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
 					flags & MSG_DONTWAIT, &rc);
+		lock_sock(sk);
 		if (!skb)
 			goto out;
 
@@ -1338,14 +1318,12 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 	msg->msg_namelen = sizeof(struct sockaddr_x25);
 
-	lock_sock(sk);
 	x25_check_rbuf(sk);
-	release_sock(sk);
 	rc = copied;
 out_free_dgram:
 	skb_free_datagram(sk, skb);
 out:
-	unlock_kernel();
+	release_sock(sk);
 	return rc;
 }
 
@@ -1581,18 +1559,18 @@ out_cud_release:
 
 		case SIOCX25CALLACCPTAPPRV: {
 			rc = -EINVAL;
-			lock_kernel();
+			lock_sock(sk);
 			if (sk->sk_state != TCP_CLOSE)
 				break;
 			clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
-			unlock_kernel();
+			release_sock(sk);
 			rc = 0;
 			break;
 		}
 
 		case SIOCX25SENDCALLACCPT:  {
 			rc = -EINVAL;
-			lock_kernel();
+			lock_sock(sk);
 			if (sk->sk_state != TCP_ESTABLISHED)
 				break;
 			/* must call accptapprv above */
@@ -1600,7 +1578,7 @@ out_cud_release:
 				break;
 			x25_write_internal(sk, X25_CALL_ACCEPTED);
 			x25->state = X25_STATE_3;
-			unlock_kernel();
+			release_sock(sk);
 			rc = 0;
 			break;
 		}
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index d00649f..0144271 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -68,8 +68,11 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
 		frontlen = skb_headroom(skb);
 
 		while (skb->len > 0) {
-			if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len,
-							noblock, &err)) == NULL){
+			release_sock(sk);
+			skbn = sock_alloc_send_skb(sk, frontlen + max_len,
+						   noblock, &err);
+			lock_sock(sk);
+			if (!skbn) {
 				if (err == -EWOULDBLOCK && noblock){
 					kfree_skb(skb);
 					return sent;
diff --git a/net/xfrm/Makefile b/net/xfrm/Makefile
index c631047..aa429ee 100644
--- a/net/xfrm/Makefile
+++ b/net/xfrm/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_XFRM) := xfrm_policy.o xfrm_state.o xfrm_hash.o \
 		      xfrm_input.o xfrm_output.o xfrm_algo.o \
-		      xfrm_sysctl.o
+		      xfrm_sysctl.o xfrm_replay.o
 obj-$(CONFIG_XFRM_STATISTICS) += xfrm_proc.o
 obj-$(CONFIG_XFRM_USER) += xfrm_user.o
 obj-$(CONFIG_XFRM_IPCOMP) += xfrm_ipcomp.o
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 8b4d6e3..58064d9 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -618,21 +618,21 @@ static int xfrm_alg_name_match(const struct xfrm_algo_desc *entry,
 			(entry->compat && !strcmp(name, entry->compat)));
 }
 
-struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe)
+struct xfrm_algo_desc *xfrm_aalg_get_byname(const char *name, int probe)
 {
 	return xfrm_find_algo(&xfrm_aalg_list, xfrm_alg_name_match, name,
 			      probe);
 }
 EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname);
 
-struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe)
+struct xfrm_algo_desc *xfrm_ealg_get_byname(const char *name, int probe)
 {
 	return xfrm_find_algo(&xfrm_ealg_list, xfrm_alg_name_match, name,
 			      probe);
 }
 EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname);
 
-struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
+struct xfrm_algo_desc *xfrm_calg_get_byname(const char *name, int probe)
 {
 	return xfrm_find_algo(&xfrm_calg_list, xfrm_alg_name_match, name,
 			      probe);
@@ -654,7 +654,7 @@ static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry,
 	       !strcmp(name, entry->name);
 }
 
-struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len, int probe)
+struct xfrm_algo_desc *xfrm_aead_get_byname(const char *name, int icv_len, int probe)
 {
 	struct xfrm_aead_name data = {
 		.name = name,
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h
index 8e69533..7199d78 100644
--- a/net/xfrm/xfrm_hash.h
+++ b/net/xfrm/xfrm_hash.h
@@ -4,29 +4,32 @@
 #include <linux/xfrm.h>
 #include <linux/socket.h>
 
-static inline unsigned int __xfrm4_addr_hash(xfrm_address_t *addr)
+static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t *addr)
 {
 	return ntohl(addr->a4);
 }
 
-static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr)
+static inline unsigned int __xfrm6_addr_hash(const xfrm_address_t *addr)
 {
 	return ntohl(addr->a6[2] ^ addr->a6[3]);
 }
 
-static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
+static inline unsigned int __xfrm4_daddr_saddr_hash(const xfrm_address_t *daddr,
+						    const xfrm_address_t *saddr)
 {
 	u32 sum = (__force u32)daddr->a4 + (__force u32)saddr->a4;
 	return ntohl((__force __be32)sum);
 }
 
-static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr)
+static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t *daddr,
+						    const xfrm_address_t *saddr)
 {
 	return ntohl(daddr->a6[2] ^ daddr->a6[3] ^
 		     saddr->a6[2] ^ saddr->a6[3]);
 }
 
-static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t *saddr,
+static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr,
+					   const xfrm_address_t *saddr,
 					   u32 reqid, unsigned short family,
 					   unsigned int hmask)
 {
@@ -42,8 +45,8 @@ static inline unsigned int __xfrm_dst_hash(xfrm_address_t *daddr, xfrm_address_t
 	return (h ^ (h >> 16)) & hmask;
 }
 
-static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr,
-				       xfrm_address_t *saddr,
+static inline unsigned __xfrm_src_hash(const xfrm_address_t *daddr,
+				       const xfrm_address_t *saddr,
 				       unsigned short family,
 				       unsigned int hmask)
 {
@@ -60,8 +63,8 @@ static inline unsigned __xfrm_src_hash(xfrm_address_t *daddr,
 }
 
 static inline unsigned int
-__xfrm_spi_hash(xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family,
-		unsigned int hmask)
+__xfrm_spi_hash(const xfrm_address_t *daddr, __be32 spi, u8 proto,
+		unsigned short family, unsigned int hmask)
 {
 	unsigned int h = (__force u32)spi ^ proto;
 	switch (family) {
@@ -80,10 +83,11 @@ static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
 	return (index ^ (index >> 8)) & hmask;
 }
 
-static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short family, unsigned int hmask)
+static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
+				      unsigned short family, unsigned int hmask)
 {
-	xfrm_address_t *daddr = &sel->daddr;
-	xfrm_address_t *saddr = &sel->saddr;
+	const xfrm_address_t *daddr = &sel->daddr;
+	const xfrm_address_t *saddr = &sel->saddr;
 	unsigned int h = 0;
 
 	switch (family) {
@@ -107,7 +111,9 @@ static inline unsigned int __sel_hash(struct xfrm_selector *sel, unsigned short
 	return h & hmask;
 }
 
-static inline unsigned int __addr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, unsigned int hmask)
+static inline unsigned int __addr_hash(const xfrm_address_t *daddr,
+				       const xfrm_address_t *saddr,
+				       unsigned short family, unsigned int hmask)
 {
 	unsigned int h = 0;
 
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 45f1c98..872065c 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -107,6 +107,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 	struct net *net = dev_net(skb->dev);
 	int err;
 	__be32 seq;
+	__be32 seq_hi;
 	struct xfrm_state *x;
 	xfrm_address_t *daddr;
 	struct xfrm_mode *inner_mode;
@@ -118,7 +119,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 	if (encap_type < 0) {
 		async = 1;
 		x = xfrm_input_state(skb);
-		seq = XFRM_SKB_CB(skb)->seq.input;
+		seq = XFRM_SKB_CB(skb)->seq.input.low;
 		goto resume;
 	}
 
@@ -172,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 			goto drop_unlock;
 		}
 
-		if (x->props.replay_window && xfrm_replay_check(x, skb, seq)) {
+		if (x->props.replay_window && x->repl->check(x, skb, seq)) {
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
 			goto drop_unlock;
 		}
@@ -184,7 +185,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 
 		spin_unlock(&x->lock);
 
-		XFRM_SKB_CB(skb)->seq.input = seq;
+		seq_hi = htonl(xfrm_replay_seqhi(x, seq));
+
+		XFRM_SKB_CB(skb)->seq.input.low = seq;
+		XFRM_SKB_CB(skb)->seq.input.hi = seq_hi;
 
 		nexthdr = x->type->input(x, skb);
 
@@ -206,8 +210,7 @@ resume:
 		/* only the first xfrm gets the encap type */
 		encap_type = 0;
 
-		if (x->props.replay_window)
-			xfrm_replay_advance(x, seq);
+		x->repl->advance(x, seq);
 
 		x->curlft.bytes += skb->len;
 		x->curlft.packets++;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 64f2ae1..1aba03f 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -67,17 +67,10 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 			goto error;
 		}
 
-		if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
-			XFRM_SKB_CB(skb)->seq.output = ++x->replay.oseq;
-			if (unlikely(x->replay.oseq == 0)) {
-				XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR);
-				x->replay.oseq--;
-				xfrm_audit_state_replay_overflow(x, skb);
-				err = -EOVERFLOW;
-				goto error;
-			}
-			if (xfrm_aevent_is_on(net))
-				xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+		err = x->repl->overflow(x, skb);
+		if (err) {
+			XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATESEQERROR);
+			goto error;
 		}
 
 		x->curlft.bytes += skb->len;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 6459588..15792d8 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -50,37 +50,40 @@ static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
 static void xfrm_init_pmtu(struct dst_entry *dst);
 static int stale_bundle(struct dst_entry *dst);
-static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
-			  struct flowi *fl, int family, int strict);
+static int xfrm_bundle_ok(struct xfrm_dst *xdst, int family);
 
 
 static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
 						int dir);
 
 static inline int
-__xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
+__xfrm4_selector_match(const struct xfrm_selector *sel, const struct flowi *fl)
 {
-	return  addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) &&
-		addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) &&
-		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
-		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
-		(fl->proto == sel->proto || !sel->proto) &&
-		(fl->oif == sel->ifindex || !sel->ifindex);
+	const struct flowi4 *fl4 = &fl->u.ip4;
+
+	return  addr_match(&fl4->daddr, &sel->daddr, sel->prefixlen_d) &&
+		addr_match(&fl4->saddr, &sel->saddr, sel->prefixlen_s) &&
+		!((xfrm_flowi_dport(fl, &fl4->uli) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl, &fl4->uli) ^ sel->sport) & sel->sport_mask) &&
+		(fl4->flowi4_proto == sel->proto || !sel->proto) &&
+		(fl4->flowi4_oif == sel->ifindex || !sel->ifindex);
 }
 
 static inline int
-__xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl)
+__xfrm6_selector_match(const struct xfrm_selector *sel, const struct flowi *fl)
 {
-	return  addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) &&
-		addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) &&
-		!((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) &&
-		!((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) &&
-		(fl->proto == sel->proto || !sel->proto) &&
-		(fl->oif == sel->ifindex || !sel->ifindex);
+	const struct flowi6 *fl6 = &fl->u.ip6;
+
+	return  addr_match(&fl6->daddr, &sel->daddr, sel->prefixlen_d) &&
+		addr_match(&fl6->saddr, &sel->saddr, sel->prefixlen_s) &&
+		!((xfrm_flowi_dport(fl, &fl6->uli) ^ sel->dport) & sel->dport_mask) &&
+		!((xfrm_flowi_sport(fl, &fl6->uli) ^ sel->sport) & sel->sport_mask) &&
+		(fl6->flowi6_proto == sel->proto || !sel->proto) &&
+		(fl6->flowi6_oif == sel->ifindex || !sel->ifindex);
 }
 
-int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
-		    unsigned short family)
+int xfrm_selector_match(const struct xfrm_selector *sel, const struct flowi *fl,
+			unsigned short family)
 {
 	switch (family) {
 	case AF_INET:
@@ -92,8 +95,8 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
 }
 
 static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos,
-						  xfrm_address_t *saddr,
-						  xfrm_address_t *daddr,
+						  const xfrm_address_t *saddr,
+						  const xfrm_address_t *daddr,
 						  int family)
 {
 	struct xfrm_policy_afinfo *afinfo;
@@ -311,7 +314,9 @@ static inline unsigned int idx_hash(struct net *net, u32 index)
 	return __idx_hash(index, net->xfrm.policy_idx_hmask);
 }
 
-static struct hlist_head *policy_hash_bysel(struct net *net, struct xfrm_selector *sel, unsigned short family, int dir)
+static struct hlist_head *policy_hash_bysel(struct net *net,
+					    const struct xfrm_selector *sel,
+					    unsigned short family, int dir)
 {
 	unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
 	unsigned int hash = __sel_hash(sel, family, hmask);
@@ -321,7 +326,10 @@ static struct hlist_head *policy_hash_bysel(struct net *net, struct xfrm_selecto
 		net->xfrm.policy_bydst[dir].table + hash);
 }
 
-static struct hlist_head *policy_hash_direct(struct net *net, xfrm_address_t *daddr, xfrm_address_t *saddr, unsigned short family, int dir)
+static struct hlist_head *policy_hash_direct(struct net *net,
+					     const xfrm_address_t *daddr,
+					     const xfrm_address_t *saddr,
+					     unsigned short family, int dir)
 {
 	unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
 	unsigned int hash = __addr_hash(daddr, saddr, family, hmask);
@@ -864,32 +872,33 @@ EXPORT_SYMBOL(xfrm_policy_walk_done);
  *
  * Returns 0 if policy found, else an -errno.
  */
-static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
+static int xfrm_policy_match(const struct xfrm_policy *pol,
+			     const struct flowi *fl,
 			     u8 type, u16 family, int dir)
 {
-	struct xfrm_selector *sel = &pol->selector;
+	const struct xfrm_selector *sel = &pol->selector;
 	int match, ret = -ESRCH;
 
 	if (pol->family != family ||
-	    (fl->mark & pol->mark.m) != pol->mark.v ||
+	    (fl->flowi_mark & pol->mark.m) != pol->mark.v ||
 	    pol->type != type)
 		return ret;
 
 	match = xfrm_selector_match(sel, fl, family);
 	if (match)
-		ret = security_xfrm_policy_lookup(pol->security, fl->secid,
+		ret = security_xfrm_policy_lookup(pol->security, fl->flowi_secid,
 						  dir);
 
 	return ret;
 }
 
 static struct xfrm_policy *xfrm_policy_lookup_bytype(struct net *net, u8 type,
-						     struct flowi *fl,
+						     const struct flowi *fl,
 						     u16 family, u8 dir)
 {
 	int err;
 	struct xfrm_policy *pol, *ret;
-	xfrm_address_t *daddr, *saddr;
+	const xfrm_address_t *daddr, *saddr;
 	struct hlist_node *entry;
 	struct hlist_head *chain;
 	u32 priority = ~0U;
@@ -941,7 +950,7 @@ fail:
 }
 
 static struct xfrm_policy *
-__xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir)
+__xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir)
 {
 #ifdef CONFIG_XFRM_SUB_POLICY
 	struct xfrm_policy *pol;
@@ -954,7 +963,7 @@ __xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir)
 }
 
 static struct flow_cache_object *
-xfrm_policy_lookup(struct net *net, struct flowi *fl, u16 family,
+xfrm_policy_lookup(struct net *net, const struct flowi *fl, u16 family,
 		   u8 dir, struct flow_cache_object *old_obj, void *ctx)
 {
 	struct xfrm_policy *pol;
@@ -990,7 +999,8 @@ static inline int policy_to_flow_dir(int dir)
 	}
 }
 
-static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl)
+static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir,
+						 const struct flowi *fl)
 {
 	struct xfrm_policy *pol;
 
@@ -1006,7 +1016,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
 				goto out;
 			}
 			err = security_xfrm_policy_lookup(pol->security,
-						      fl->secid,
+						      fl->flowi_secid,
 						      policy_to_flow_dir(dir));
 			if (!err)
 				xfrm_pol_hold(pol);
@@ -1098,7 +1108,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
 	return 0;
 }
 
-static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
+static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
 {
 	struct xfrm_policy *newp = xfrm_policy_alloc(xp_net(old), GFP_ATOMIC);
 
@@ -1157,9 +1167,8 @@ xfrm_get_saddr(struct net *net, xfrm_address_t *local, xfrm_address_t *remote,
 /* Resolve list of templates for the flow, given policy. */
 
 static int
-xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
-		      struct xfrm_state **xfrm,
-		      unsigned short family)
+xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
+		      struct xfrm_state **xfrm, unsigned short family)
 {
 	struct net *net = xp_net(policy);
 	int nx;
@@ -1214,9 +1223,8 @@ fail:
 }
 
 static int
-xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
-		  struct xfrm_state **xfrm,
-		  unsigned short family)
+xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, const struct flowi *fl,
+		  struct xfrm_state **xfrm, unsigned short family)
 {
 	struct xfrm_state *tp[XFRM_MAX_DEPTH];
 	struct xfrm_state **tpp = (npols > 1) ? tp : xfrm;
@@ -1256,7 +1264,7 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, struct flowi *fl,
  * still valid.
  */
 
-static inline int xfrm_get_tos(struct flowi *fl, int family)
+static inline int xfrm_get_tos(const struct flowi *fl, int family)
 {
 	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
 	int tos;
@@ -1340,7 +1348,7 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
 	default:
 		BUG();
 	}
-	xdst = dst_alloc(dst_ops);
+	xdst = dst_alloc(dst_ops, 0);
 	xfrm_policy_put_afinfo(afinfo);
 
 	if (likely(xdst))
@@ -1369,7 +1377,7 @@ static inline int xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst,
 }
 
 static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
-				struct flowi *fl)
+				const struct flowi *fl)
 {
 	struct xfrm_policy_afinfo *afinfo =
 		xfrm_policy_get_afinfo(xdst->u.dst.ops->family);
@@ -1392,7 +1400,7 @@ static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
 
 static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 					    struct xfrm_state **xfrm, int nx,
-					    struct flowi *fl,
+					    const struct flowi *fl,
 					    struct dst_entry *dst)
 {
 	struct net *net = xp_net(policy);
@@ -1508,7 +1516,7 @@ free_dst:
 }
 
 static int inline
-xfrm_dst_alloc_copy(void **target, void *src, int size)
+xfrm_dst_alloc_copy(void **target, const void *src, int size)
 {
 	if (!*target) {
 		*target = kmalloc(size, GFP_ATOMIC);
@@ -1520,7 +1528,7 @@ xfrm_dst_alloc_copy(void **target, void *src, int size)
 }
 
 static int inline
-xfrm_dst_update_parent(struct dst_entry *dst, struct xfrm_selector *sel)
+xfrm_dst_update_parent(struct dst_entry *dst, const struct xfrm_selector *sel)
 {
 #ifdef CONFIG_XFRM_SUB_POLICY
 	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
@@ -1532,7 +1540,7 @@ xfrm_dst_update_parent(struct dst_entry *dst, struct xfrm_selector *sel)
 }
 
 static int inline
-xfrm_dst_update_origin(struct dst_entry *dst, struct flowi *fl)
+xfrm_dst_update_origin(struct dst_entry *dst, const struct flowi *fl)
 {
 #ifdef CONFIG_XFRM_SUB_POLICY
 	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
@@ -1542,7 +1550,7 @@ xfrm_dst_update_origin(struct dst_entry *dst, struct flowi *fl)
 #endif
 }
 
-static int xfrm_expand_policies(struct flowi *fl, u16 family,
+static int xfrm_expand_policies(const struct flowi *fl, u16 family,
 				struct xfrm_policy **pols,
 				int *num_pols, int *num_xfrms)
 {
@@ -1588,7 +1596,7 @@ static int xfrm_expand_policies(struct flowi *fl, u16 family,
 
 static struct xfrm_dst *
 xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
-			       struct flowi *fl, u16 family,
+			       const struct flowi *fl, u16 family,
 			       struct dst_entry *dst_orig)
 {
 	struct net *net = xp_net(pols[0]);
@@ -1631,7 +1639,7 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
 }
 
 static struct flow_cache_object *
-xfrm_bundle_lookup(struct net *net, struct flowi *fl, u16 family, u8 dir,
+xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
 		   struct flow_cache_object *oldflo, void *ctx)
 {
 	struct dst_entry *dst_orig = (struct dst_entry *)ctx;
@@ -1730,18 +1738,36 @@ error:
 	return ERR_PTR(err);
 }
 
+static struct dst_entry *make_blackhole(struct net *net, u16 family,
+					struct dst_entry *dst_orig)
+{
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+	struct dst_entry *ret;
+
+	if (!afinfo) {
+		dst_release(dst_orig);
+		ret = ERR_PTR(-EINVAL);
+	} else {
+		ret = afinfo->blackhole_route(net, dst_orig);
+	}
+	xfrm_policy_put_afinfo(afinfo);
+
+	return ret;
+}
+
 /* Main function: finds/creates a bundle for given flow.
  *
  * At the moment we eat a raw IP route. Mostly to speed up lookups
  * on interfaces with disabled IPsec.
  */
-int __xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl,
-		  struct sock *sk, int flags)
+struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
+			      const struct flowi *fl,
+			      struct sock *sk, int flags)
 {
 	struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
 	struct flow_cache_object *flo;
 	struct xfrm_dst *xdst;
-	struct dst_entry *dst, *dst_orig = *dst_p, *route;
+	struct dst_entry *dst, *route;
 	u16 family = dst_orig->ops->family;
 	u8 dir = policy_to_flow_dir(XFRM_POLICY_OUT);
 	int i, err, num_pols, num_xfrms = 0, drop_pols = 0;
@@ -1778,6 +1804,8 @@ restart:
 				goto no_transform;
 			}
 
+			dst_hold(&xdst->u.dst);
+
 			spin_lock_bh(&xfrm_policy_sk_bundle_lock);
 			xdst->u.dst.next = xfrm_policy_sk_bundles;
 			xfrm_policy_sk_bundles = &xdst->u.dst;
@@ -1823,9 +1851,10 @@ restart:
 			dst_release(dst);
 			xfrm_pols_put(pols, drop_pols);
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
-			return -EREMOTE;
+
+			return make_blackhole(net, family, dst_orig);
 		}
-		if (flags & XFRM_LOOKUP_WAIT) {
+		if (fl->flowi_flags & FLOWI_FLAG_CAN_SLEEP) {
 			DECLARE_WAITQUEUE(wait, current);
 
 			add_wait_queue(&net->xfrm.km_waitq, &wait);
@@ -1867,47 +1896,33 @@ no_transform:
 		goto error;
 	} else if (num_xfrms > 0) {
 		/* Flow transformed */
-		*dst_p = dst;
 		dst_release(dst_orig);
 	} else {
 		/* Flow passes untransformed */
 		dst_release(dst);
+		dst = dst_orig;
 	}
 ok:
 	xfrm_pols_put(pols, drop_pols);
-	return 0;
+	return dst;
 
 nopol:
-	if (!(flags & XFRM_LOOKUP_ICMP))
+	if (!(flags & XFRM_LOOKUP_ICMP)) {
+		dst = dst_orig;
 		goto ok;
+	}
 	err = -ENOENT;
 error:
 	dst_release(dst);
 dropdst:
 	dst_release(dst_orig);
-	*dst_p = NULL;
 	xfrm_pols_put(pols, drop_pols);
-	return err;
-}
-EXPORT_SYMBOL(__xfrm_lookup);
-
-int xfrm_lookup(struct net *net, struct dst_entry **dst_p, struct flowi *fl,
-		struct sock *sk, int flags)
-{
-	int err = __xfrm_lookup(net, dst_p, fl, sk, flags);
-
-	if (err == -EREMOTE) {
-		dst_release(*dst_p);
-		*dst_p = NULL;
-		err = -EAGAIN;
-	}
-
-	return err;
+	return ERR_PTR(err);
 }
 EXPORT_SYMBOL(xfrm_lookup);
 
 static inline int
-xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl)
+xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
 {
 	struct xfrm_state *x;
 
@@ -1926,7 +1941,7 @@ xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl)
  */
 
 static inline int
-xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
+xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
 	      unsigned short family)
 {
 	if (xfrm_state_kern(x))
@@ -1949,7 +1964,7 @@ xfrm_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x,
  * Otherwise "-2 - errored_index" is returned.
  */
 static inline int
-xfrm_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int start,
+xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
 	       unsigned short family)
 {
 	int idx = start;
@@ -1981,13 +1996,13 @@ int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
 		return -EAFNOSUPPORT;
 
 	afinfo->decode_session(skb, fl, reverse);
-	err = security_xfrm_decode_session(skb, &fl->secid);
+	err = security_xfrm_decode_session(skb, &fl->flowi_secid);
 	xfrm_policy_put_afinfo(afinfo);
 	return err;
 }
 EXPORT_SYMBOL(__xfrm_decode_session);
 
-static inline int secpath_has_nontransport(struct sec_path *sp, int k, int *idxp)
+static inline int secpath_has_nontransport(const struct sec_path *sp, int k, int *idxp)
 {
 	for (; k < sp->len; k++) {
 		if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
@@ -2162,7 +2177,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 	struct net *net = dev_net(skb->dev);
 	struct flowi fl;
 	struct dst_entry *dst;
-	int res;
+	int res = 1;
 
 	if (xfrm_decode_session(skb, &fl, family) < 0) {
 		XFRM_INC_STATS(net, LINUX_MIB_XFRMFWDHDRERROR);
@@ -2170,9 +2185,12 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
 	}
 
 	skb_dst_force(skb);
-	dst = skb_dst(skb);
 
-	res = xfrm_lookup(net, &dst, &fl, NULL, 0) == 0;
+	dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0);
+	if (IS_ERR(dst)) {
+		res = 0;
+		dst = NULL;
+	}
 	skb_dst_set(skb, dst);
 	return res;
 }
@@ -2210,7 +2228,7 @@ static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie)
 
 static int stale_bundle(struct dst_entry *dst)
 {
-	return !xfrm_bundle_ok(NULL, (struct xfrm_dst *)dst, NULL, AF_UNSPEC, 0);
+	return !xfrm_bundle_ok((struct xfrm_dst *)dst, AF_UNSPEC);
 }
 
 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
@@ -2282,8 +2300,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst)
  * still valid.
  */
 
-static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
-		struct flowi *fl, int family, int strict)
+static int xfrm_bundle_ok(struct xfrm_dst *first, int family)
 {
 	struct dst_entry *dst = &first->u.dst;
 	struct xfrm_dst *last;
@@ -2292,26 +2309,12 @@ static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
 	if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) ||
 	    (dst->dev && !netif_running(dst->dev)))
 		return 0;
-#ifdef CONFIG_XFRM_SUB_POLICY
-	if (fl) {
-		if (first->origin && !flow_cache_uli_match(first->origin, fl))
-			return 0;
-		if (first->partner &&
-		    !xfrm_selector_match(first->partner, fl, family))
-			return 0;
-	}
-#endif
 
 	last = NULL;
 
 	do {
 		struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
 
-		if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
-			return 0;
-		if (fl && pol &&
-		    !security_xfrm_state_pol_flow_match(dst->xfrm, pol, fl))
-			return 0;
 		if (dst->xfrm->km.state != XFRM_STATE_VALID)
 			return 0;
 		if (xdst->xfrm_genid != dst->xfrm->genid)
@@ -2320,11 +2323,6 @@ static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
 		    xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
 			return 0;
 
-		if (strict && fl &&
-		    !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
-		    !xfrm_state_addr_flow_check(dst->xfrm, fl, family))
-			return 0;
-
 		mtu = dst_mtu(dst->child);
 		if (xdst->child_mtu_cached != mtu) {
 			last = xdst;
@@ -2735,8 +2733,8 @@ EXPORT_SYMBOL_GPL(xfrm_audit_policy_delete);
 #endif
 
 #ifdef CONFIG_XFRM_MIGRATE
-static int xfrm_migrate_selector_match(struct xfrm_selector *sel_cmp,
-				       struct xfrm_selector *sel_tgt)
+static int xfrm_migrate_selector_match(const struct xfrm_selector *sel_cmp,
+				       const struct xfrm_selector *sel_tgt)
 {
 	if (sel_cmp->proto == IPSEC_ULPROTO_ANY) {
 		if (sel_tgt->family == sel_cmp->family &&
@@ -2756,7 +2754,7 @@ static int xfrm_migrate_selector_match(struct xfrm_selector *sel_cmp,
 	return 0;
 }
 
-static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel,
+static struct xfrm_policy * xfrm_migrate_policy_find(const struct xfrm_selector *sel,
 						     u8 dir, u8 type)
 {
 	struct xfrm_policy *pol, *ret = NULL;
@@ -2792,7 +2790,7 @@ static struct xfrm_policy * xfrm_migrate_policy_find(struct xfrm_selector *sel,
 	return ret;
 }
 
-static int migrate_tmpl_match(struct xfrm_migrate *m, struct xfrm_tmpl *t)
+static int migrate_tmpl_match(const struct xfrm_migrate *m, const struct xfrm_tmpl *t)
 {
 	int match = 0;
 
@@ -2862,7 +2860,7 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
 	return 0;
 }
 
-static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate)
+static int xfrm_migrate_check(const struct xfrm_migrate *m, int num_migrate)
 {
 	int i, j;
 
@@ -2896,7 +2894,7 @@ static int xfrm_migrate_check(struct xfrm_migrate *m, int num_migrate)
 	return 0;
 }
 
-int xfrm_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
+int xfrm_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
 		 struct xfrm_migrate *m, int num_migrate,
 		 struct xfrm_kmaddress *k)
 {
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
new file mode 100644
index 0000000..2f5be5b
--- /dev/null
+++ b/net/xfrm/xfrm_replay.c
@@ -0,0 +1,534 @@
+/*
+ * xfrm_replay.c - xfrm replay detection, derived from xfrm_state.c.
+ *
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <net/xfrm.h>
+
+u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq)
+{
+	u32 seq, seq_hi, bottom;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+
+	if (!(x->props.flags & XFRM_STATE_ESN))
+		return 0;
+
+	seq = ntohl(net_seq);
+	seq_hi = replay_esn->seq_hi;
+	bottom = replay_esn->seq - replay_esn->replay_window + 1;
+
+	if (likely(replay_esn->seq >= replay_esn->replay_window - 1)) {
+		/* A. same subspace */
+		if (unlikely(seq < bottom))
+			seq_hi++;
+	} else {
+		/* B. window spans two subspaces */
+		if (unlikely(seq >= bottom))
+			seq_hi--;
+	}
+
+	return seq_hi;
+}
+
+static void xfrm_replay_notify(struct xfrm_state *x, int event)
+{
+	struct km_event c;
+	/* 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 &&
+		    (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
+		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
+			if (x->xflags & XFRM_TIME_DEFER)
+				event = XFRM_REPLAY_TIMEOUT;
+			else
+				return;
+		}
+
+		break;
+
+	case XFRM_REPLAY_TIMEOUT:
+		if (memcmp(&x->replay, &x->preplay,
+			   sizeof(struct xfrm_replay_state)) == 0) {
+			x->xflags |= XFRM_TIME_DEFER;
+			return;
+		}
+
+		break;
+	}
+
+	memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
+	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(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err = 0;
+	struct net *net = xs_net(x);
+
+	if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+		XFRM_SKB_CB(skb)->seq.output.low = ++x->replay.oseq;
+		if (unlikely(x->replay.oseq == 0)) {
+			x->replay.oseq--;
+			xfrm_audit_state_replay_overflow(x, skb);
+			err = -EOVERFLOW;
+
+			return err;
+		}
+		if (xfrm_aevent_is_on(net))
+			x->repl->notify(x, XFRM_REPLAY_UPDATE);
+	}
+
+	return err;
+}
+
+static int xfrm_replay_check(struct xfrm_state *x,
+		      struct sk_buff *skb, __be32 net_seq)
+{
+	u32 diff;
+	u32 seq = ntohl(net_seq);
+
+	if (unlikely(seq == 0))
+		goto err;
+
+	if (likely(seq > x->replay.seq))
+		return 0;
+
+	diff = x->replay.seq - seq;
+	if (diff >= min_t(unsigned int, x->props.replay_window,
+			  sizeof(x->replay.bitmap) * 8)) {
+		x->stats.replay_window++;
+		goto err;
+	}
+
+	if (x->replay.bitmap & (1U << diff)) {
+		x->stats.replay++;
+		goto err;
+	}
+	return 0;
+
+err:
+	xfrm_audit_state_replay(x, skb, net_seq);
+	return -EINVAL;
+}
+
+static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
+{
+	u32 diff;
+	u32 seq = ntohl(net_seq);
+
+	if (!x->props.replay_window)
+		return;
+
+	if (seq > x->replay.seq) {
+		diff = seq - x->replay.seq;
+		if (diff < x->props.replay_window)
+			x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
+		else
+			x->replay.bitmap = 1;
+		x->replay.seq = seq;
+	} else {
+		diff = x->replay.seq - seq;
+		x->replay.bitmap |= (1U << diff);
+	}
+
+	if (xfrm_aevent_is_on(xs_net(x)))
+		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
+static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err = 0;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+	struct net *net = xs_net(x);
+
+	if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+		XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
+		if (unlikely(replay_esn->oseq == 0)) {
+			replay_esn->oseq--;
+			xfrm_audit_state_replay_overflow(x, skb);
+			err = -EOVERFLOW;
+
+			return err;
+		}
+		if (xfrm_aevent_is_on(net))
+			x->repl->notify(x, XFRM_REPLAY_UPDATE);
+	}
+
+	return err;
+}
+
+static int xfrm_replay_check_bmp(struct xfrm_state *x,
+				 struct sk_buff *skb, __be32 net_seq)
+{
+	unsigned int bitnr, nr;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+	u32 seq = ntohl(net_seq);
+	u32 diff =  replay_esn->seq - seq;
+	u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
+	if (unlikely(seq == 0))
+		goto err;
+
+	if (likely(seq > replay_esn->seq))
+		return 0;
+
+	if (diff >= replay_esn->replay_window) {
+		x->stats.replay_window++;
+		goto err;
+	}
+
+	if (pos >= diff) {
+		bitnr = (pos - diff) % replay_esn->replay_window;
+		nr = bitnr >> 5;
+		bitnr = bitnr & 0x1F;
+		if (replay_esn->bmp[nr] & (1U << bitnr))
+			goto err_replay;
+	} else {
+		bitnr = replay_esn->replay_window - (diff - pos);
+		nr = bitnr >> 5;
+		bitnr = bitnr & 0x1F;
+		if (replay_esn->bmp[nr] & (1U << bitnr))
+			goto err_replay;
+	}
+	return 0;
+
+err_replay:
+	x->stats.replay++;
+err:
+	xfrm_audit_state_replay(x, skb, net_seq);
+	return -EINVAL;
+}
+
+static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
+{
+	unsigned int bitnr, nr, i;
+	u32 diff;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+	u32 seq = ntohl(net_seq);
+	u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
+	if (!replay_esn->replay_window)
+		return;
+
+	if (seq > replay_esn->seq) {
+		diff = seq - replay_esn->seq;
+
+		if (diff < replay_esn->replay_window) {
+			for (i = 1; i < diff; i++) {
+				bitnr = (pos + i) % replay_esn->replay_window;
+				nr = bitnr >> 5;
+				bitnr = bitnr & 0x1F;
+				replay_esn->bmp[nr] &=  ~(1U << bitnr);
+			}
+
+			bitnr = (pos + diff) % replay_esn->replay_window;
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		} else {
+			nr = replay_esn->replay_window >> 5;
+			for (i = 0; i <= nr; i++)
+				replay_esn->bmp[i] = 0;
+
+			bitnr = (pos + diff) % replay_esn->replay_window;
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		}
+
+		replay_esn->seq = seq;
+	} else {
+		diff = replay_esn->seq - seq;
+
+		if (pos >= diff) {
+			bitnr = (pos - diff) % replay_esn->replay_window;
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		} else {
+			bitnr = replay_esn->replay_window - (diff - pos);
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		}
+	}
+
+	if (xfrm_aevent_is_on(xs_net(x)))
+		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
+static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
+{
+	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 &&
+		    (replay_esn->seq - preplay_esn->seq < x->replay_maxdiff) &&
+		    (replay_esn->oseq - preplay_esn->oseq < 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;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+	struct net *net = xs_net(x);
+
+	if (x->type->flags & XFRM_TYPE_REPLAY_PROT) {
+		XFRM_SKB_CB(skb)->seq.output.low = ++replay_esn->oseq;
+		XFRM_SKB_CB(skb)->seq.output.hi = replay_esn->oseq_hi;
+
+		if (unlikely(replay_esn->oseq == 0)) {
+			XFRM_SKB_CB(skb)->seq.output.hi = ++replay_esn->oseq_hi;
+
+			if (replay_esn->oseq_hi == 0) {
+				replay_esn->oseq--;
+				replay_esn->oseq_hi--;
+				xfrm_audit_state_replay_overflow(x, skb);
+				err = -EOVERFLOW;
+
+				return err;
+			}
+		}
+		if (xfrm_aevent_is_on(net))
+			x->repl->notify(x, XFRM_REPLAY_UPDATE);
+	}
+
+	return err;
+}
+
+static int xfrm_replay_check_esn(struct xfrm_state *x,
+				 struct sk_buff *skb, __be32 net_seq)
+{
+	unsigned int bitnr, nr;
+	u32 diff;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+	u32 seq = ntohl(net_seq);
+	u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+	u32 wsize = replay_esn->replay_window;
+	u32 top = replay_esn->seq;
+	u32 bottom = top - wsize + 1;
+
+	if (unlikely(seq == 0 && replay_esn->seq_hi == 0 &&
+		     (replay_esn->seq < replay_esn->replay_window - 1)))
+		goto err;
+
+	diff = top - seq;
+
+	if (likely(top >= wsize - 1)) {
+		/* A. same subspace */
+		if (likely(seq > top) || seq < bottom)
+			return 0;
+	} else {
+		/* B. window spans two subspaces */
+		if (likely(seq > top && seq < bottom))
+			return 0;
+		if (seq >= bottom)
+			diff = ~seq + top + 1;
+	}
+
+	if (diff >= replay_esn->replay_window) {
+		x->stats.replay_window++;
+		goto err;
+	}
+
+	if (pos >= diff) {
+		bitnr = (pos - diff) % replay_esn->replay_window;
+		nr = bitnr >> 5;
+		bitnr = bitnr & 0x1F;
+		if (replay_esn->bmp[nr] & (1U << bitnr))
+			goto err_replay;
+	} else {
+		bitnr = replay_esn->replay_window - (diff - pos);
+		nr = bitnr >> 5;
+		bitnr = bitnr & 0x1F;
+		if (replay_esn->bmp[nr] & (1U << bitnr))
+			goto err_replay;
+	}
+	return 0;
+
+err_replay:
+	x->stats.replay++;
+err:
+	xfrm_audit_state_replay(x, skb, net_seq);
+	return -EINVAL;
+}
+
+static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
+{
+	unsigned int bitnr, nr, i;
+	int wrap;
+	u32 diff, pos, seq, seq_hi;
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+
+	if (!replay_esn->replay_window)
+		return;
+
+	seq = ntohl(net_seq);
+	pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+	seq_hi = xfrm_replay_seqhi(x, net_seq);
+	wrap = seq_hi - replay_esn->seq_hi;
+
+	if ((!wrap && seq > replay_esn->seq) || wrap > 0) {
+		if (likely(!wrap))
+			diff = seq - replay_esn->seq;
+		else
+			diff = ~replay_esn->seq + seq + 1;
+
+		if (diff < replay_esn->replay_window) {
+			for (i = 1; i < diff; i++) {
+				bitnr = (pos + i) % replay_esn->replay_window;
+				nr = bitnr >> 5;
+				bitnr = bitnr & 0x1F;
+				replay_esn->bmp[nr] &=  ~(1U << bitnr);
+			}
+
+			bitnr = (pos + diff) % replay_esn->replay_window;
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		} else {
+			nr = replay_esn->replay_window >> 5;
+			for (i = 0; i <= nr; i++)
+				replay_esn->bmp[i] = 0;
+
+			bitnr = (pos + diff) % replay_esn->replay_window;
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		}
+
+		replay_esn->seq = seq;
+
+		if (unlikely(wrap > 0))
+			replay_esn->seq_hi++;
+	} else {
+		diff = replay_esn->seq - seq;
+
+		if (pos >= diff) {
+			bitnr = (pos - diff) % replay_esn->replay_window;
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		} else {
+			bitnr = replay_esn->replay_window - (diff - pos);
+			nr = bitnr >> 5;
+			bitnr = bitnr & 0x1F;
+			replay_esn->bmp[nr] |= (1U << bitnr);
+		}
+	}
+
+	if (xfrm_aevent_is_on(xs_net(x)))
+		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+}
+
+static struct xfrm_replay xfrm_replay_legacy = {
+	.advance	= xfrm_replay_advance,
+	.check		= xfrm_replay_check,
+	.notify		= xfrm_replay_notify,
+	.overflow	= xfrm_replay_overflow,
+};
+
+static struct xfrm_replay xfrm_replay_bmp = {
+	.advance	= xfrm_replay_advance_bmp,
+	.check		= xfrm_replay_check_bmp,
+	.notify		= xfrm_replay_notify_bmp,
+	.overflow	= xfrm_replay_overflow_bmp,
+};
+
+static struct xfrm_replay xfrm_replay_esn = {
+	.advance	= xfrm_replay_advance_esn,
+	.check		= xfrm_replay_check_esn,
+	.notify		= xfrm_replay_notify_bmp,
+	.overflow	= xfrm_replay_overflow_esn,
+};
+
+int xfrm_init_replay(struct xfrm_state *x)
+{
+	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+
+	if (replay_esn) {
+		if (replay_esn->replay_window >
+		    replay_esn->bmp_len * sizeof(__u32))
+			return -EINVAL;
+
+	if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn)
+		x->repl = &xfrm_replay_esn;
+	else
+		x->repl = &xfrm_replay_bmp;
+	} else
+		x->repl = &xfrm_replay_legacy;
+
+	return 0;
+}
+EXPORT_SYMBOL(xfrm_init_replay);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 220ebc0..f83a3d1 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -42,16 +42,9 @@ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024;
 static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family);
 static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
 
-#ifdef CONFIG_AUDITSYSCALL
-static void xfrm_audit_state_replay(struct xfrm_state *x,
-				    struct sk_buff *skb, __be32 net_seq);
-#else
-#define xfrm_audit_state_replay(x, s, sq)	do { ; } while (0)
-#endif /* CONFIG_AUDITSYSCALL */
-
 static inline unsigned int xfrm_dst_hash(struct net *net,
-					 xfrm_address_t *daddr,
-					 xfrm_address_t *saddr,
+					 const xfrm_address_t *daddr,
+					 const xfrm_address_t *saddr,
 					 u32 reqid,
 					 unsigned short family)
 {
@@ -59,15 +52,16 @@ static inline unsigned int xfrm_dst_hash(struct net *net,
 }
 
 static inline unsigned int xfrm_src_hash(struct net *net,
-					 xfrm_address_t *daddr,
-					 xfrm_address_t *saddr,
+					 const xfrm_address_t *daddr,
+					 const xfrm_address_t *saddr,
 					 unsigned short family)
 {
 	return __xfrm_src_hash(daddr, saddr, family, net->xfrm.state_hmask);
 }
 
 static inline unsigned int
-xfrm_spi_hash(struct net *net, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
+xfrm_spi_hash(struct net *net, const xfrm_address_t *daddr,
+	      __be32 spi, u8 proto, unsigned short family)
 {
 	return __xfrm_spi_hash(daddr, spi, proto, family, net->xfrm.state_hmask);
 }
@@ -362,6 +356,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
 	kfree(x->calg);
 	kfree(x->encap);
 	kfree(x->coaddr);
+	kfree(x->replay_esn);
+	kfree(x->preplay_esn);
 	if (x->inner_mode)
 		xfrm_put_mode(x->inner_mode);
 	if (x->inner_mode_iaf)
@@ -656,9 +652,9 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si)
 EXPORT_SYMBOL(xfrm_sad_getinfo);
 
 static int
-xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl,
-		    struct xfrm_tmpl *tmpl,
-		    xfrm_address_t *daddr, xfrm_address_t *saddr,
+xfrm_init_tempstate(struct xfrm_state *x, const struct flowi *fl,
+		    const struct xfrm_tmpl *tmpl,
+		    const xfrm_address_t *daddr, const xfrm_address_t *saddr,
 		    unsigned short family)
 {
 	struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family);
@@ -677,7 +673,10 @@ xfrm_init_tempstate(struct xfrm_state *x, struct flowi *fl,
 	return 0;
 }
 
-static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi, u8 proto, unsigned short family)
+static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark,
+					      const xfrm_address_t *daddr,
+					      __be32 spi, u8 proto,
+					      unsigned short family)
 {
 	unsigned int h = xfrm_spi_hash(net, daddr, spi, proto, family);
 	struct xfrm_state *x;
@@ -699,7 +698,10 @@ static struct xfrm_state *__xfrm_state_lookup(struct net *net, u32 mark, xfrm_ad
 	return NULL;
 }
 
-static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark, xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family)
+static struct xfrm_state *__xfrm_state_lookup_byaddr(struct net *net, u32 mark,
+						     const xfrm_address_t *daddr,
+						     const xfrm_address_t *saddr,
+						     u8 proto, unsigned short family)
 {
 	unsigned int h = xfrm_src_hash(net, daddr, saddr, family);
 	struct xfrm_state *x;
@@ -746,8 +748,7 @@ static void xfrm_hash_grow_check(struct net *net, int have_hash_collision)
 }
 
 static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
-			       struct flowi *fl, unsigned short family,
-			       xfrm_address_t *daddr, xfrm_address_t *saddr,
+			       const struct flowi *fl, unsigned short family,
 			       struct xfrm_state **best, int *acq_in_progress,
 			       int *error)
 {
@@ -784,8 +785,8 @@ static void xfrm_state_look_at(struct xfrm_policy *pol, struct xfrm_state *x,
 }
 
 struct xfrm_state *
-xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
-		struct flowi *fl, struct xfrm_tmpl *tmpl,
+xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
+		const struct flowi *fl, struct xfrm_tmpl *tmpl,
 		struct xfrm_policy *pol, int *err,
 		unsigned short family)
 {
@@ -813,7 +814,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
 		    tmpl->mode == x->props.mode &&
 		    tmpl->id.proto == x->id.proto &&
 		    (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
-			xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
+			xfrm_state_look_at(pol, x, fl, encap_family,
 					   &best, &acquire_in_progress, &error);
 	}
 	if (best)
@@ -829,7 +830,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
 		    tmpl->mode == x->props.mode &&
 		    tmpl->id.proto == x->id.proto &&
 		    (tmpl->id.spi == x->id.spi || !tmpl->id.spi))
-			xfrm_state_look_at(pol, x, fl, encap_family, daddr, saddr,
+			xfrm_state_look_at(pol, x, fl, encap_family,
 					   &best, &acquire_in_progress, &error);
 	}
 
@@ -853,7 +854,7 @@ found:
 		xfrm_init_tempstate(x, fl, tmpl, daddr, saddr, family);
 		memcpy(&x->mark, &pol->mark, sizeof(x->mark));
 
-		error = security_xfrm_state_alloc_acquire(x, pol->security, fl->secid);
+		error = security_xfrm_state_alloc_acquire(x, pol->security, fl->flowi_secid);
 		if (error) {
 			x->km.state = XFRM_STATE_DEAD;
 			to_put = x;
@@ -991,7 +992,11 @@ void xfrm_state_insert(struct xfrm_state *x)
 EXPORT_SYMBOL(xfrm_state_insert);
 
 /* xfrm_state_lock is held */
-static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create)
+static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m,
+					  unsigned short family, u8 mode,
+					  u32 reqid, u8 proto,
+					  const xfrm_address_t *daddr,
+					  const xfrm_address_t *saddr, int create)
 {
 	unsigned int h = xfrm_dst_hash(net, daddr, saddr, reqid, family);
 	struct hlist_node *entry;
@@ -1369,7 +1374,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
 EXPORT_SYMBOL(xfrm_state_check_expire);
 
 struct xfrm_state *
-xfrm_state_lookup(struct net *net, u32 mark, xfrm_address_t *daddr, __be32 spi,
+xfrm_state_lookup(struct net *net, u32 mark, const xfrm_address_t *daddr, __be32 spi,
 		  u8 proto, unsigned short family)
 {
 	struct xfrm_state *x;
@@ -1383,7 +1388,7 @@ EXPORT_SYMBOL(xfrm_state_lookup);
 
 struct xfrm_state *
 xfrm_state_lookup_byaddr(struct net *net, u32 mark,
-			 xfrm_address_t *daddr, xfrm_address_t *saddr,
+			 const xfrm_address_t *daddr, const xfrm_address_t *saddr,
 			 u8 proto, unsigned short family)
 {
 	struct xfrm_state *x;
@@ -1397,7 +1402,7 @@ EXPORT_SYMBOL(xfrm_state_lookup_byaddr);
 
 struct xfrm_state *
 xfrm_find_acq(struct net *net, struct xfrm_mark *mark, u8 mode, u32 reqid, u8 proto,
-	      xfrm_address_t *daddr, xfrm_address_t *saddr,
+	      const xfrm_address_t *daddr, const xfrm_address_t *saddr,
 	      int create, unsigned short family)
 {
 	struct xfrm_state *x;
@@ -1609,54 +1614,6 @@ void xfrm_state_walk_done(struct xfrm_state_walk *walk)
 }
 EXPORT_SYMBOL(xfrm_state_walk_done);
 
-
-void xfrm_replay_notify(struct xfrm_state *x, int event)
-{
-	struct km_event c;
-	/* 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 &&
-		    (x->replay.seq - x->preplay.seq < x->replay_maxdiff) &&
-		    (x->replay.oseq - x->preplay.oseq < x->replay_maxdiff)) {
-			if (x->xflags & XFRM_TIME_DEFER)
-				event = XFRM_REPLAY_TIMEOUT;
-			else
-				return;
-		}
-
-		break;
-
-	case XFRM_REPLAY_TIMEOUT:
-		if ((x->replay.seq == x->preplay.seq) &&
-		    (x->replay.bitmap == x->preplay.bitmap) &&
-		    (x->replay.oseq == x->preplay.oseq)) {
-			x->xflags |= XFRM_TIME_DEFER;
-			return;
-		}
-
-		break;
-	}
-
-	memcpy(&x->preplay, &x->replay, sizeof(struct xfrm_replay_state));
-	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 void xfrm_replay_timer_handler(unsigned long data)
 {
 	struct xfrm_state *x = (struct xfrm_state*)data;
@@ -1665,7 +1622,7 @@ static void xfrm_replay_timer_handler(unsigned long data)
 
 	if (x->km.state == XFRM_STATE_VALID) {
 		if (xfrm_aevent_is_on(xs_net(x)))
-			xfrm_replay_notify(x, XFRM_REPLAY_TIMEOUT);
+			x->repl->notify(x, XFRM_REPLAY_TIMEOUT);
 		else
 			x->xflags |= XFRM_TIME_DEFER;
 	}
@@ -1673,61 +1630,10 @@ static void xfrm_replay_timer_handler(unsigned long data)
 	spin_unlock(&x->lock);
 }
 
-int xfrm_replay_check(struct xfrm_state *x,
-		      struct sk_buff *skb, __be32 net_seq)
-{
-	u32 diff;
-	u32 seq = ntohl(net_seq);
-
-	if (unlikely(seq == 0))
-		goto err;
-
-	if (likely(seq > x->replay.seq))
-		return 0;
-
-	diff = x->replay.seq - seq;
-	if (diff >= min_t(unsigned int, x->props.replay_window,
-			  sizeof(x->replay.bitmap) * 8)) {
-		x->stats.replay_window++;
-		goto err;
-	}
-
-	if (x->replay.bitmap & (1U << diff)) {
-		x->stats.replay++;
-		goto err;
-	}
-	return 0;
-
-err:
-	xfrm_audit_state_replay(x, skb, net_seq);
-	return -EINVAL;
-}
-
-void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
-{
-	u32 diff;
-	u32 seq = ntohl(net_seq);
-
-	if (seq > x->replay.seq) {
-		diff = seq - x->replay.seq;
-		if (diff < x->props.replay_window)
-			x->replay.bitmap = ((x->replay.bitmap) << diff) | 1;
-		else
-			x->replay.bitmap = 1;
-		x->replay.seq = seq;
-	} else {
-		diff = x->replay.seq - seq;
-		x->replay.bitmap |= (1U << diff);
-	}
-
-	if (xfrm_aevent_is_on(xs_net(x)))
-		xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
-}
-
 static LIST_HEAD(xfrm_km_list);
 static DEFINE_RWLOCK(xfrm_km_lock);
 
-void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+void km_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
 {
 	struct xfrm_mgr *km;
 
@@ -1738,7 +1644,7 @@ void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
 	read_unlock(&xfrm_km_lock);
 }
 
-void km_state_notify(struct xfrm_state *x, struct km_event *c)
+void km_state_notify(struct xfrm_state *x, const struct km_event *c)
 {
 	struct xfrm_mgr *km;
 	read_lock(&xfrm_km_lock);
@@ -1819,9 +1725,9 @@ void km_policy_expired(struct xfrm_policy *pol, int dir, int hard, u32 pid)
 EXPORT_SYMBOL(km_policy_expired);
 
 #ifdef CONFIG_XFRM_MIGRATE
-int km_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
-	       struct xfrm_migrate *m, int num_migrate,
-	       struct xfrm_kmaddress *k)
+int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+	       const struct xfrm_migrate *m, int num_migrate,
+	       const struct xfrm_kmaddress *k)
 {
 	int err = -EINVAL;
 	int ret;
@@ -2001,7 +1907,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
 	return res;
 }
 
-int xfrm_init_state(struct xfrm_state *x)
+int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
 {
 	struct xfrm_state_afinfo *afinfo;
 	struct xfrm_mode *inner_mode;
@@ -2074,12 +1980,25 @@ int xfrm_init_state(struct xfrm_state *x)
 	if (x->outer_mode == NULL)
 		goto error;
 
+	if (init_replay) {
+		err = xfrm_init_replay(x);
+		if (err)
+			goto error;
+	}
+
 	x->km.state = XFRM_STATE_VALID;
 
 error:
 	return err;
 }
 
+EXPORT_SYMBOL(__xfrm_init_state);
+
+int xfrm_init_state(struct xfrm_state *x)
+{
+	return __xfrm_init_state(x, true);
+}
+
 EXPORT_SYMBOL(xfrm_init_state);
 
 int __net_init xfrm_state_init(struct net *net)
@@ -2236,7 +2155,7 @@ void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
 }
 EXPORT_SYMBOL_GPL(xfrm_audit_state_replay_overflow);
 
-static void xfrm_audit_state_replay(struct xfrm_state *x,
+void xfrm_audit_state_replay(struct xfrm_state *x,
 			     struct sk_buff *skb, __be32 net_seq)
 {
 	struct audit_buffer *audit_buf;
@@ -2251,6 +2170,7 @@ static void xfrm_audit_state_replay(struct xfrm_state *x,
 			 spi, spi, ntohl(net_seq));
 	audit_log_end(audit_buf);
 }
+EXPORT_SYMBOL_GPL(xfrm_audit_state_replay);
 
 void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family)
 {
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 6129196..fc152d2 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -119,6 +119,19 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs)
 	return 0;
 }
 
+static inline int verify_replay(struct xfrm_usersa_info *p,
+				struct nlattr **attrs)
+{
+	struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
+
+	if (!rt)
+		return 0;
+
+	if (p->replay_window != 0)
+		return -EINVAL;
+
+	return 0;
+}
 
 static int verify_newsa_info(struct xfrm_usersa_info *p,
 			     struct nlattr **attrs)
@@ -214,6 +227,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
 		goto out;
 	if ((err = verify_sec_ctx_len(attrs)))
 		goto out;
+	if ((err = verify_replay(p, attrs)))
+		goto out;
 
 	err = -EINVAL;
 	switch (p->mode) {
@@ -234,7 +249,7 @@ out:
 }
 
 static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
-			   struct xfrm_algo_desc *(*get_byname)(char *, int),
+			   struct xfrm_algo_desc *(*get_byname)(const char *, int),
 			   struct nlattr *rta)
 {
 	struct xfrm_algo *p, *ualg;
@@ -345,6 +360,33 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
 	return 0;
 }
 
+static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn,
+				       struct xfrm_replay_state_esn **preplay_esn,
+				       struct nlattr *rta)
+{
+	struct xfrm_replay_state_esn *p, *pp, *up;
+
+	if (!rta)
+		return 0;
+
+	up = nla_data(rta);
+
+	p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+
+	pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+	if (!pp) {
+		kfree(p);
+		return -ENOMEM;
+	}
+
+	*replay_esn = p;
+	*preplay_esn = pp;
+
+	return 0;
+}
+
 static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
 {
 	int len = 0;
@@ -380,10 +422,20 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
 static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
 {
 	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
+	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
 	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
 	struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
 	struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
 
+	if (re) {
+		struct xfrm_replay_state_esn *replay_esn;
+		replay_esn = nla_data(re);
+		memcpy(x->replay_esn, replay_esn,
+		       xfrm_replay_state_esn_len(replay_esn));
+		memcpy(x->preplay_esn, replay_esn,
+		       xfrm_replay_state_esn_len(replay_esn));
+	}
+
 	if (rp) {
 		struct xfrm_replay_state *replay;
 		replay = nla_data(rp);
@@ -459,7 +511,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
 
 	xfrm_mark_get(attrs, &x->mark);
 
-	err = xfrm_init_state(x);
+	err = __xfrm_init_state(x, false);
 	if (err)
 		goto error;
 
@@ -467,16 +519,19 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
 	    security_xfrm_state_alloc(x, nla_data(attrs[XFRMA_SEC_CTX])))
 		goto error;
 
+	if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
+					       attrs[XFRMA_REPLAY_ESN_VAL])))
+		goto error;
+
 	x->km.seq = p->seq;
 	x->replay_maxdiff = net->xfrm.sysctl_aevent_rseqth;
 	/* sysctl_xfrm_aevent_etime is in 100ms units */
 	x->replay_maxage = (net->xfrm.sysctl_aevent_etime*HZ)/XFRM_AE_ETH_M;
-	x->preplay.bitmap = 0;
-	x->preplay.seq = x->replay.seq+x->replay_maxdiff;
-	x->preplay.oseq = x->replay.oseq +x->replay_maxdiff;
 
-	/* override default values from above */
+	if ((err = xfrm_init_replay(x)))
+		goto error;
 
+	/* override default values from above */
 	xfrm_update_ae_params(x, attrs);
 
 	return x;
@@ -497,9 +552,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_state *x;
 	int err;
 	struct km_event c;
-	uid_t loginuid = NETLINK_CB(skb).loginuid;
-	u32 sessionid = NETLINK_CB(skb).sessionid;
-	u32 sid = NETLINK_CB(skb).sid;
+	uid_t loginuid = audit_get_loginuid(current);
+	u32 sessionid = audit_get_sessionid(current);
+	u32 sid;
 
 	err = verify_newsa_info(p, attrs);
 	if (err)
@@ -515,6 +570,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	else
 		err = xfrm_state_update(x);
 
+	security_task_getsecid(current, &sid);
 	xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
 
 	if (err < 0) {
@@ -575,9 +631,9 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	int err = -ESRCH;
 	struct km_event c;
 	struct xfrm_usersa_id *p = nlmsg_data(nlh);
-	uid_t loginuid = NETLINK_CB(skb).loginuid;
-	u32 sessionid = NETLINK_CB(skb).sessionid;
-	u32 sid = NETLINK_CB(skb).sid;
+	uid_t loginuid = audit_get_loginuid(current);
+	u32 sessionid = audit_get_sessionid(current);
+	u32 sid;
 
 	x = xfrm_user_state_lookup(net, p, attrs, &err);
 	if (x == NULL)
@@ -602,6 +658,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	km_state_notify(x, &c);
 
 out:
+	security_task_getsecid(current, &sid);
 	xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
 	xfrm_state_put(x);
 	return err;
@@ -705,6 +762,10 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
 	if (xfrm_mark_put(skb, &x->mark))
 		goto nla_put_failure;
 
+	if (x->replay_esn)
+		NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
+			xfrm_replay_state_esn_len(x->replay_esn), x->replay_esn);
+
 	if (x->security && copy_sec_ctx(x->security, skb) < 0)
 		goto nla_put_failure;
 
@@ -1265,9 +1326,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct km_event c;
 	int err;
 	int excl;
-	uid_t loginuid = NETLINK_CB(skb).loginuid;
-	u32 sessionid = NETLINK_CB(skb).sessionid;
-	u32 sid = NETLINK_CB(skb).sid;
+	uid_t loginuid = audit_get_loginuid(current);
+	u32 sessionid = audit_get_sessionid(current);
+	u32 sid;
 
 	err = verify_newpolicy_info(p);
 	if (err)
@@ -1286,6 +1347,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	 * a type XFRM_MSG_UPDPOLICY - JHS */
 	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
 	err = xfrm_policy_insert(p->dir, xp, excl);
+	security_task_getsecid(current, &sid);
 	xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
 
 	if (err) {
@@ -1522,10 +1584,11 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 					    NETLINK_CB(skb).pid);
 		}
 	} else {
-		uid_t loginuid = NETLINK_CB(skb).loginuid;
-		u32 sessionid = NETLINK_CB(skb).sessionid;
-		u32 sid = NETLINK_CB(skb).sid;
+		uid_t loginuid = audit_get_loginuid(current);
+		u32 sessionid = audit_get_sessionid(current);
+		u32 sid;
 
+		security_task_getsecid(current, &sid);
 		xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
 					 sid);
 
@@ -1553,9 +1616,9 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_audit audit_info;
 	int err;
 
-	audit_info.loginuid = NETLINK_CB(skb).loginuid;
-	audit_info.sessionid = NETLINK_CB(skb).sessionid;
-	audit_info.secid = NETLINK_CB(skb).sid;
+	audit_info.loginuid = audit_get_loginuid(current);
+	audit_info.sessionid = audit_get_sessionid(current);
+	security_task_getsecid(current, &audit_info.secid);
 	err = xfrm_state_flush(net, p->proto, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1572,17 +1635,21 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
 	return 0;
 }
 
-static inline size_t xfrm_aevent_msgsize(void)
+static inline size_t xfrm_aevent_msgsize(struct xfrm_state *x)
 {
+	size_t replay_size = x->replay_esn ?
+			      xfrm_replay_state_esn_len(x->replay_esn) :
+			      sizeof(struct xfrm_replay_state);
+
 	return NLMSG_ALIGN(sizeof(struct xfrm_aevent_id))
-	       + nla_total_size(sizeof(struct xfrm_replay_state))
+	       + nla_total_size(replay_size)
 	       + nla_total_size(sizeof(struct xfrm_lifetime_cur))
 	       + nla_total_size(sizeof(struct xfrm_mark))
 	       + nla_total_size(4) /* XFRM_AE_RTHR */
 	       + nla_total_size(4); /* XFRM_AE_ETHR */
 }
 
-static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
+static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
 {
 	struct xfrm_aevent_id *id;
 	struct nlmsghdr *nlh;
@@ -1600,7 +1667,13 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, struct km_eve
 	id->reqid = x->props.reqid;
 	id->flags = c->data.aevent;
 
-	NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
+	if (x->replay_esn)
+		NLA_PUT(skb, XFRMA_REPLAY_ESN_VAL,
+			xfrm_replay_state_esn_len(x->replay_esn),
+			x->replay_esn);
+	else
+		NLA_PUT(skb, XFRMA_REPLAY_VAL, sizeof(x->replay), &x->replay);
+
 	NLA_PUT(skb, XFRMA_LTIME_VAL, sizeof(x->curlft), &x->curlft);
 
 	if (id->flags & XFRM_AE_RTHR)
@@ -1633,16 +1706,16 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_aevent_id *p = nlmsg_data(nlh);
 	struct xfrm_usersa_id *id = &p->sa_id;
 
-	r_skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
-	if (r_skb == NULL)
-		return -ENOMEM;
-
 	mark = xfrm_mark_get(attrs, &m);
 
 	x = xfrm_state_lookup(net, mark, &id->daddr, id->spi, id->proto, id->family);
-	if (x == NULL) {
-		kfree_skb(r_skb);
+	if (x == NULL)
 		return -ESRCH;
+
+	r_skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
+	if (r_skb == NULL) {
+		xfrm_state_put(x);
+		return -ENOMEM;
 	}
 
 	/*
@@ -1674,9 +1747,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct xfrm_mark m;
 	struct xfrm_aevent_id *p = nlmsg_data(nlh);
 	struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
+	struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
 	struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
 
-	if (!lt && !rp)
+	if (!lt && !rp && !re)
 		return err;
 
 	/* pedantic mode - thou shalt sayeth replaceth */
@@ -1720,9 +1794,9 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (err)
 		return err;
 
-	audit_info.loginuid = NETLINK_CB(skb).loginuid;
-	audit_info.sessionid = NETLINK_CB(skb).sessionid;
-	audit_info.secid = NETLINK_CB(skb).sid;
+	audit_info.loginuid = audit_get_loginuid(current);
+	audit_info.sessionid = audit_get_sessionid(current);
+	security_task_getsecid(current, &audit_info.secid);
 	err = xfrm_policy_flush(net, type, &audit_info);
 	if (err) {
 		if (err == -ESRCH) /* empty table */
@@ -1789,9 +1863,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 	err = 0;
 	if (up->hard) {
-		uid_t loginuid = NETLINK_CB(skb).loginuid;
-		uid_t sessionid = NETLINK_CB(skb).sessionid;
-		u32 sid = NETLINK_CB(skb).sid;
+		uid_t loginuid = audit_get_loginuid(current);
+		u32 sessionid = audit_get_sessionid(current);
+		u32 sid;
+
+		security_task_getsecid(current, &sid);
 		xfrm_policy_delete(xp, p->dir);
 		xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
 
@@ -1830,9 +1906,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
 	km_state_expired(x, ue->hard, current->pid);
 
 	if (ue->hard) {
-		uid_t loginuid = NETLINK_CB(skb).loginuid;
-		uid_t sessionid = NETLINK_CB(skb).sessionid;
-		u32 sid = NETLINK_CB(skb).sid;
+		uid_t loginuid = audit_get_loginuid(current);
+		u32 sessionid = audit_get_sessionid(current);
+		u32 sid;
+
+		security_task_getsecid(current, &sid);
 		__xfrm_state_delete(x);
 		xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
 	}
@@ -1986,7 +2064,7 @@ static int xfrm_do_migrate(struct sk_buff *skb, struct nlmsghdr *nlh,
 #endif
 
 #ifdef CONFIG_XFRM_MIGRATE
-static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb)
+static int copy_to_user_migrate(const struct xfrm_migrate *m, struct sk_buff *skb)
 {
 	struct xfrm_user_migrate um;
 
@@ -2004,7 +2082,7 @@ static int copy_to_user_migrate(struct xfrm_migrate *m, struct sk_buff *skb)
 	return nla_put(skb, XFRMA_MIGRATE, sizeof(um), &um);
 }
 
-static int copy_to_user_kmaddress(struct xfrm_kmaddress *k, struct sk_buff *skb)
+static int copy_to_user_kmaddress(const struct xfrm_kmaddress *k, struct sk_buff *skb)
 {
 	struct xfrm_user_kmaddress uk;
 
@@ -2025,11 +2103,11 @@ static inline size_t xfrm_migrate_msgsize(int num_migrate, int with_kma)
 	      + userpolicy_type_attrsize();
 }
 
-static int build_migrate(struct sk_buff *skb, struct xfrm_migrate *m,
-			 int num_migrate, struct xfrm_kmaddress *k,
-			 struct xfrm_selector *sel, u8 dir, u8 type)
+static int build_migrate(struct sk_buff *skb, const struct xfrm_migrate *m,
+			 int num_migrate, const struct xfrm_kmaddress *k,
+			 const struct xfrm_selector *sel, u8 dir, u8 type)
 {
-	struct xfrm_migrate *mp;
+	const struct xfrm_migrate *mp;
 	struct xfrm_userpolicy_id *pol_id;
 	struct nlmsghdr *nlh;
 	int i;
@@ -2061,9 +2139,9 @@ nlmsg_failure:
 	return -EMSGSIZE;
 }
 
-static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
-			     struct xfrm_migrate *m, int num_migrate,
-			     struct xfrm_kmaddress *k)
+static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+			     const struct xfrm_migrate *m, int num_migrate,
+			     const struct xfrm_kmaddress *k)
 {
 	struct net *net = &init_net;
 	struct sk_buff *skb;
@@ -2079,9 +2157,9 @@ static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MIGRATE, GFP_ATOMIC);
 }
 #else
-static int xfrm_send_migrate(struct xfrm_selector *sel, u8 dir, u8 type,
-			     struct xfrm_migrate *m, int num_migrate,
-			     struct xfrm_kmaddress *k)
+static int xfrm_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
+			     const struct xfrm_migrate *m, int num_migrate,
+			     const struct xfrm_kmaddress *k)
 {
 	return -ENOPROTOOPT;
 }
@@ -2137,6 +2215,7 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
 	[XFRMA_KMADDRESS]	= { .len = sizeof(struct xfrm_user_kmaddress) },
 	[XFRMA_MARK]		= { .len = sizeof(struct xfrm_mark) },
 	[XFRMA_TFCPAD]		= { .type = NLA_U32 },
+	[XFRMA_REPLAY_ESN_VAL]	= { .len = sizeof(struct xfrm_replay_state_esn) },
 };
 
 static struct xfrm_link {
@@ -2220,7 +2299,7 @@ static inline size_t xfrm_expire_msgsize(void)
 	       + nla_total_size(sizeof(struct xfrm_mark));
 }
 
-static int build_expire(struct sk_buff *skb, struct xfrm_state *x, struct km_event *c)
+static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
 {
 	struct xfrm_user_expire *ue;
 	struct nlmsghdr *nlh;
@@ -2242,7 +2321,7 @@ nla_put_failure:
 	return -EMSGSIZE;
 }
 
-static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
+static int xfrm_exp_state_notify(struct xfrm_state *x, const struct km_event *c)
 {
 	struct net *net = xs_net(x);
 	struct sk_buff *skb;
@@ -2259,12 +2338,12 @@ static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
-static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c)
+static int xfrm_aevent_state_notify(struct xfrm_state *x, const struct km_event *c)
 {
 	struct net *net = xs_net(x);
 	struct sk_buff *skb;
 
-	skb = nlmsg_new(xfrm_aevent_msgsize(), GFP_ATOMIC);
+	skb = nlmsg_new(xfrm_aevent_msgsize(x), GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
 
@@ -2274,7 +2353,7 @@ static int xfrm_aevent_state_notify(struct xfrm_state *x, struct km_event *c)
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_AEVENTS, GFP_ATOMIC);
 }
 
-static int xfrm_notify_sa_flush(struct km_event *c)
+static int xfrm_notify_sa_flush(const struct km_event *c)
 {
 	struct net *net = c->net;
 	struct xfrm_usersa_flush *p;
@@ -2318,6 +2397,8 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
 		l += nla_total_size(sizeof(*x->encap));
 	if (x->tfcpad)
 		l += nla_total_size(sizeof(x->tfcpad));
+	if (x->replay_esn)
+		l += nla_total_size(xfrm_replay_state_esn_len(x->replay_esn));
 	if (x->security)
 		l += nla_total_size(sizeof(struct xfrm_user_sec_ctx) +
 				    x->security->ctx_len);
@@ -2330,7 +2411,7 @@ static inline size_t xfrm_sa_len(struct xfrm_state *x)
 	return l;
 }
 
-static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
+static int xfrm_notify_sa(struct xfrm_state *x, const struct km_event *c)
 {
 	struct net *net = xs_net(x);
 	struct xfrm_usersa_info *p;
@@ -2387,7 +2468,7 @@ nla_put_failure:
 	return -1;
 }
 
-static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
+static int xfrm_send_state_notify(struct xfrm_state *x, const struct km_event *c)
 {
 
 	switch (c->event) {
@@ -2546,7 +2627,7 @@ static inline size_t xfrm_polexpire_msgsize(struct xfrm_policy *xp)
 }
 
 static int build_polexpire(struct sk_buff *skb, struct xfrm_policy *xp,
-			   int dir, struct km_event *c)
+			   int dir, const struct km_event *c)
 {
 	struct xfrm_user_polexpire *upe;
 	struct nlmsghdr *nlh;
@@ -2576,7 +2657,7 @@ nlmsg_failure:
 	return -EMSGSIZE;
 }
 
-static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
 {
 	struct net *net = xp_net(xp);
 	struct sk_buff *skb;
@@ -2591,7 +2672,7 @@ static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_eve
 	return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_EXPIRE, GFP_ATOMIC);
 }
 
-static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, const struct km_event *c)
 {
 	struct net *net = xp_net(xp);
 	struct xfrm_userpolicy_info *p;
@@ -2656,7 +2737,7 @@ nlmsg_failure:
 	return -1;
 }
 
-static int xfrm_notify_policy_flush(struct km_event *c)
+static int xfrm_notify_policy_flush(const struct km_event *c)
 {
 	struct net *net = c->net;
 	struct nlmsghdr *nlh;
@@ -2681,7 +2762,7 @@ nlmsg_failure:
 	return -1;
 }
 
-static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, const struct km_event *c)
 {
 
 	switch (c->event) {
diff --git a/scripts/Makefile b/scripts/Makefile
index 2e08810..fcea261 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -18,6 +18,11 @@ always		:= $(hostprogs-y) $(hostprogs-m)
 # The following hostprogs-y programs are only build on demand
 hostprogs-y += unifdef
 
+# This target is used internally to avoid "is up to date" messages
+PHONY += build_unifdef
+build_unifdef: scripts/unifdef FORCE
+	@:
+
 subdir-$(CONFIG_MODVERSIONS) += genksyms
 subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 4eb99ab..d5f925a 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -49,6 +49,40 @@ ifeq ($(KBUILD_NOPEDANTIC),)
                 $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use EXTRA_CFLAGS)
         endif
 endif
+
+#
+# make W=1 settings
+#
+# $(call cc-option... ) handles gcc -W.. options which
+# are not supported by all versions of the compiler
+ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS
+KBUILD_EXTRA_WARNINGS := -Wextra
+KBUILD_EXTRA_WARNINGS += -Wunused -Wno-unused-parameter
+KBUILD_EXTRA_WARNINGS += -Waggregate-return
+KBUILD_EXTRA_WARNINGS += -Wbad-function-cast
+KBUILD_EXTRA_WARNINGS += -Wcast-qual
+KBUILD_EXTRA_WARNINGS += -Wcast-align
+KBUILD_EXTRA_WARNINGS += -Wconversion
+KBUILD_EXTRA_WARNINGS += -Wdisabled-optimization
+KBUILD_EXTRA_WARNINGS += -Wlogical-op
+KBUILD_EXTRA_WARNINGS += -Wmissing-declarations
+KBUILD_EXTRA_WARNINGS += -Wmissing-format-attribute
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wmissing-include-dirs,)
+KBUILD_EXTRA_WARNINGS += -Wmissing-prototypes
+KBUILD_EXTRA_WARNINGS += -Wnested-externs
+KBUILD_EXTRA_WARNINGS += -Wold-style-definition
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Woverlength-strings,)
+KBUILD_EXTRA_WARNINGS += -Wpacked
+KBUILD_EXTRA_WARNINGS += -Wpacked-bitfield-compat
+KBUILD_EXTRA_WARNINGS += -Wpadded
+KBUILD_EXTRA_WARNINGS += -Wpointer-arith
+KBUILD_EXTRA_WARNINGS += -Wredundant-decls
+KBUILD_EXTRA_WARNINGS += -Wshadow
+KBUILD_EXTRA_WARNINGS += -Wswitch-default
+KBUILD_EXTRA_WARNINGS += $(call cc-option, -Wvla,)
+KBUILD_CFLAGS += $(KBUILD_EXTRA_WARNINGS)
+endif
+
 include scripts/Makefile.lib
 
 ifdef host-progs
@@ -403,7 +437,6 @@ ifneq ($(cmd_files),)
   include $(cmd_files)
 endif
 
-
 # Declare the contents of the .PHONY variable as phony.  We keep that
 # information in a variable se we can use it in if_changed and friends.
 
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index 6501a50..6129020 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -17,7 +17,9 @@ def getsizes(file):
     sym = {}
     for l in os.popen("nm --size-sort " + file).readlines():
         size, type, name = l[:-1].split()
-        if type in "tTdDbB":
+        if type in "tTdDbBrR":
+            # strip generated symbols
+            if name[:6] == "__mod_": continue
             # function names begin with '.' on 64-bit powerpc
             if "." in name[1:]: name = "static." + name.split(".")[0]
             sym[name] = sym.get(name, 0) + int(size, 16)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4c0383d..8f9e394 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2654,11 +2654,6 @@ sub process {
 			WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
 		}
 
-# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
-		if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
-			ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
-		}
-
 # warn about #if 0
 		if ($line =~ /^.\s*\#\s*if\s+0\b/) {
 			CHK("if this code is redundant consider removing it\n" .
@@ -2809,9 +2804,9 @@ sub process {
 			WARN("consider using a completion\n" . $herecurr);
 
 		}
-# recommend strict_strto* over simple_strto*
+# recommend kstrto* over simple_strto*
 		if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
-			WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
+			WARN("consider using kstrto* in preference to simple_$1\n" . $herecurr);
 		}
 # check for __initcall(), use device_initcall() explicitly please
 		if ($line =~ /^.\s*__initcall\s*\(/) {
@@ -2907,6 +2902,11 @@ sub process {
 		    $line =~ /DEVICE_ATTR.*S_IWUGO/ ) {
 			WARN("Exporting world writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr);
 		}
+
+		# Check for memset with swapped arguments
+		if ($line =~ /memset.*\,(\ |)(0x|)0(\ |0|)\);/) {
+			ERROR("memset size is 3rd argument, not the second.\n" . $herecurr);
+		}
 	}
 
 	# If we have no input at all, then there is nothing to report on
@@ -2949,6 +2949,7 @@ sub process {
 		if ($rpt_cleaners) {
 			print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
 			print "      scripts/cleanfile\n\n";
+			$rpt_cleaners = 0;
 		}
 	}
 
diff --git a/scripts/extract-ikconfig b/scripts/extract-ikconfig
index 1512c0a..e186242 100755
--- a/scripts/extract-ikconfig
+++ b/scripts/extract-ikconfig
@@ -56,10 +56,11 @@ trap "rm -f $tmp1 $tmp2" 0
 dump_config "$img"
 
 # That didn't work, so retry after decompression.
-try_decompress '\037\213\010' xy  gunzip
-try_decompress 'BZh'          xy  bunzip2
-try_decompress '\135\0\0\0'   xxx unlzma
-try_decompress '\211\114\132' xy  'lzop -d'
+try_decompress '\037\213\010' xy    gunzip
+try_decompress '\3757zXZ\000' abcde unxz
+try_decompress 'BZh'          xy    bunzip2
+try_decompress '\135\0\0\0'   xxx   unlzma
+try_decompress '\211\114\132' xy    'lzop -d'
 
 # Bail out:
 echo "$me: Cannot find kernel config." >&2
diff --git a/scripts/genksyms/Makefile b/scripts/genksyms/Makefile
index e420fe4..13d03cf 100644
--- a/scripts/genksyms/Makefile
+++ b/scripts/genksyms/Makefile
@@ -28,9 +28,9 @@ $(obj)/keywords.c: $(obj)/keywords.gperf FORCE
 # flex
 
 quiet_cmd_lex.c = FLEX    $@
-      cmd_lex.c = flex -o$@ -d $< $(obj)/parse.h
+      cmd_lex.c = flex -o$@ -d $<
 
-$(obj)/lex.c: $(obj)/lex.l $(obj)/parse.h $(obj)/keywords.c FORCE
+$(obj)/lex.c: $(obj)/lex.l $(obj)/keywords.c FORCE
 	$(call if_changed,lex.c)
 	cp $@ $@_shipped
 
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index f99115e..f9e7553 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -53,12 +53,22 @@ static int nsyms;
 static struct symbol *expansion_trail;
 static struct symbol *visited_symbols;
 
-static const char *const symbol_type_name[] = {
-	"normal", "typedef", "enum", "struct", "union"
+static const struct {
+	int n;
+	const char *name;
+} symbol_types[] = {
+	[SYM_NORMAL]     = { 0, NULL},
+	[SYM_TYPEDEF]    = {'t', "typedef"},
+	[SYM_ENUM]       = {'e', "enum"},
+	[SYM_STRUCT]     = {'s', "struct"},
+	[SYM_UNION]      = {'u', "union"},
+	[SYM_ENUM_CONST] = {'E', "enum constant"},
 };
 
 static int equal_list(struct string_list *a, struct string_list *b);
 static void print_list(FILE * f, struct string_list *list);
+static struct string_list *concat_list(struct string_list *start, ...);
+static struct string_list *mk_node(const char *string);
 static void print_location(void);
 static void print_type_name(enum symbol_type type, const char *name);
 
@@ -140,14 +150,20 @@ static unsigned long crc32(const char *s)
 
 static enum symbol_type map_to_ns(enum symbol_type t)
 {
-	if (t == SYM_TYPEDEF)
-		t = SYM_NORMAL;
-	else if (t == SYM_UNION)
-		t = SYM_STRUCT;
+	switch (t) {
+	case SYM_ENUM_CONST:
+	case SYM_NORMAL:
+	case SYM_TYPEDEF:
+		return SYM_NORMAL;
+	case SYM_ENUM:
+	case SYM_STRUCT:
+	case SYM_UNION:
+		return SYM_STRUCT;
+	}
 	return t;
 }
 
-struct symbol *find_symbol(const char *name, enum symbol_type ns)
+struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact)
 {
 	unsigned long h = crc32(name) % HASH_BUCKETS;
 	struct symbol *sym;
@@ -158,6 +174,8 @@ struct symbol *find_symbol(const char *name, enum symbol_type ns)
 		    sym->is_declared)
 			break;
 
+	if (exact && sym && sym->type != ns)
+		return NULL;
 	return sym;
 }
 
@@ -180,10 +198,47 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
 			    struct string_list *defn, int is_extern,
 			    int is_reference)
 {
-	unsigned long h = crc32(name) % HASH_BUCKETS;
+	unsigned long h;
 	struct symbol *sym;
 	enum symbol_status status = STATUS_UNCHANGED;
+	/* The parser adds symbols in the order their declaration completes,
+	 * so it is safe to store the value of the previous enum constant in
+	 * a static variable.
+	 */
+	static int enum_counter;
+	static struct string_list *last_enum_expr;
+
+	if (type == SYM_ENUM_CONST) {
+		if (defn) {
+			free_list(last_enum_expr, NULL);
+			last_enum_expr = copy_list_range(defn, NULL);
+			enum_counter = 1;
+		} else {
+			struct string_list *expr;
+			char buf[20];
+
+			snprintf(buf, sizeof(buf), "%d", enum_counter++);
+			if (last_enum_expr) {
+				expr = copy_list_range(last_enum_expr, NULL);
+				defn = concat_list(mk_node("("),
+						   expr,
+						   mk_node(")"),
+						   mk_node("+"),
+						   mk_node(buf), NULL);
+			} else {
+				defn = mk_node(buf);
+			}
+		}
+	} else if (type == SYM_ENUM) {
+		free_list(last_enum_expr, NULL);
+		last_enum_expr = NULL;
+		enum_counter = 0;
+		if (!name)
+			/* Anonymous enum definition, nothing more to do */
+			return NULL;
+	}
 
+	h = crc32(name) % HASH_BUCKETS;
 	for (sym = symtab[h]; sym; sym = sym->hash_next) {
 		if (map_to_ns(sym->type) == map_to_ns(type) &&
 		    strcmp(name, sym->name) == 0) {
@@ -247,8 +302,12 @@ static struct symbol *__add_symbol(const char *name, enum symbol_type type,
 	sym->is_override = 0;
 
 	if (flag_debug) {
-		fprintf(debugfile, "Defn for %s %s == <",
-			symbol_type_name[type], name);
+		if (symbol_types[type].name)
+			fprintf(debugfile, "Defn for %s %s == <",
+				symbol_types[type].name, name);
+		else
+			fprintf(debugfile, "Defn for type%d %s == <",
+				type, name);
 		if (is_extern)
 			fputs("extern ", debugfile);
 		print_list(debugfile, defn);
@@ -288,6 +347,35 @@ void free_list(struct string_list *s, struct string_list *e)
 	}
 }
 
+static struct string_list *mk_node(const char *string)
+{
+	struct string_list *newnode;
+
+	newnode = xmalloc(sizeof(*newnode));
+	newnode->string = xstrdup(string);
+	newnode->tag = SYM_NORMAL;
+	newnode->next = NULL;
+
+	return newnode;
+}
+
+static struct string_list *concat_list(struct string_list *start, ...)
+{
+	va_list ap;
+	struct string_list *n, *n2;
+
+	if (!start)
+		return NULL;
+	for (va_start(ap, start); (n = va_arg(ap, struct string_list *));) {
+		for (n2 = n; n2->next; n2 = n2->next)
+			;
+		n2->next = start;
+		start = n;
+	}
+	va_end(ap);
+	return start;
+}
+
 struct string_list *copy_node(struct string_list *node)
 {
 	struct string_list *newnode;
@@ -299,6 +387,22 @@ struct string_list *copy_node(struct string_list *node)
 	return newnode;
 }
 
+struct string_list *copy_list_range(struct string_list *start,
+				    struct string_list *end)
+{
+	struct string_list *res, *n;
+
+	if (start == end)
+		return NULL;
+	n = res = copy_node(start);
+	for (start = start->next; start != end; start = start->next) {
+		n->next = copy_node(start);
+		n = n->next;
+	}
+	n->next = NULL;
+	return res;
+}
+
 static int equal_list(struct string_list *a, struct string_list *b)
 {
 	while (a && b) {
@@ -346,8 +450,8 @@ static struct string_list *read_node(FILE *f)
 	if (node.string[1] == '#') {
 		int n;
 
-		for (n = 0; n < ARRAY_SIZE(symbol_type_name); n++) {
-			if (node.string[0] == symbol_type_name[n][0]) {
+		for (n = 0; n < ARRAY_SIZE(symbol_types); n++) {
+			if (node.string[0] == symbol_types[n].n) {
 				node.tag = n;
 				node.string += 2;
 				return copy_node(&node);
@@ -397,8 +501,8 @@ static void read_reference(FILE *f)
 
 static void print_node(FILE * f, struct string_list *list)
 {
-	if (list->tag != SYM_NORMAL) {
-		putc(symbol_type_name[list->tag][0], f);
+	if (symbol_types[list->tag].n) {
+		putc(symbol_types[list->tag].n, f);
 		putc('#', f);
 	}
 	fputs(list->string, f);
@@ -468,8 +572,9 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 			crc = partial_crc32_one(' ', crc);
 			break;
 
+		case SYM_ENUM_CONST:
 		case SYM_TYPEDEF:
-			subsym = find_symbol(cur->string, cur->tag);
+			subsym = find_symbol(cur->string, cur->tag, 0);
 			/* FIXME: Bad reference files can segfault here. */
 			if (subsym->expansion_trail) {
 				if (flag_dump_defs)
@@ -486,55 +591,30 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 		case SYM_STRUCT:
 		case SYM_UNION:
 		case SYM_ENUM:
-			subsym = find_symbol(cur->string, cur->tag);
+			subsym = find_symbol(cur->string, cur->tag, 0);
 			if (!subsym) {
-				struct string_list *n, *t = NULL;
+				struct string_list *n;
 
 				error_with_pos("expand undefined %s %s",
-					       symbol_type_name[cur->tag],
+					       symbol_types[cur->tag].name,
 					       cur->string);
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup(symbol_type_name[cur->tag]);
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup(cur->string);
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup("{");
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup("UNKNOWN");
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
-				n = xmalloc(sizeof(*n));
-				n->string = xstrdup("}");
-				n->tag = SYM_NORMAL;
-				n->next = t;
-				t = n;
-
+				n = concat_list(mk_node
+						(symbol_types[cur->tag].name),
+						mk_node(cur->string),
+						mk_node("{"),
+						mk_node("UNKNOWN"),
+						mk_node("}"), NULL);
 				subsym =
 				    add_symbol(cur->string, cur->tag, n, 0);
 			}
 			if (subsym->expansion_trail) {
 				if (flag_dump_defs) {
 					fprintf(debugfile, "%s %s ",
-						symbol_type_name[cur->tag],
+						symbol_types[cur->tag].name,
 						cur->string);
 				}
 
-				crc = partial_crc32(symbol_type_name[cur->tag],
+				crc = partial_crc32(symbol_types[cur->tag].name,
 						    crc);
 				crc = partial_crc32_one(' ', crc);
 				crc = partial_crc32(cur->string, crc);
@@ -565,7 +645,7 @@ void export_symbol(const char *name)
 {
 	struct symbol *sym;
 
-	sym = find_symbol(name, SYM_NORMAL);
+	sym = find_symbol(name, SYM_NORMAL, 0);
 	if (!sym)
 		error_with_pos("export undefined symbol %s", name);
 	else {
@@ -624,8 +704,8 @@ static void print_location(void)
 
 static void print_type_name(enum symbol_type type, const char *name)
 {
-	if (type != SYM_NORMAL)
-		fprintf(stderr, "%s %s", symbol_type_name[type], name);
+	if (symbol_types[type].name)
+		fprintf(stderr, "%s %s", symbol_types[type].name, name);
 	else
 		fprintf(stderr, "%s", name);
 }
@@ -771,8 +851,8 @@ int main(int argc, char **argv)
 
 			if (sym->is_override)
 				fputs("override ", dumpfile);
-			if (sym->type != SYM_NORMAL) {
-				putc(symbol_type_name[sym->type][0], dumpfile);
+			if (symbol_types[sym->type].n) {
+				putc(symbol_types[sym->type].n, dumpfile);
 				putc('#', dumpfile);
 			}
 			fputs(sym->name, dumpfile);
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
index 25c4d40..7ec52ae 100644
--- a/scripts/genksyms/genksyms.h
+++ b/scripts/genksyms/genksyms.h
@@ -26,7 +26,8 @@
 #include <stdio.h>
 
 enum symbol_type {
-	SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION
+	SYM_NORMAL, SYM_TYPEDEF, SYM_ENUM, SYM_STRUCT, SYM_UNION,
+	SYM_ENUM_CONST
 };
 
 enum symbol_status {
@@ -58,7 +59,7 @@ typedef struct string_list **yystype;
 extern int cur_line;
 extern char *cur_filename;
 
-struct symbol *find_symbol(const char *name, enum symbol_type ns);
+struct symbol *find_symbol(const char *name, enum symbol_type ns, int exact);
 struct symbol *add_symbol(const char *name, enum symbol_type type,
 			  struct string_list *defn, int is_extern);
 void export_symbol(const char *);
@@ -66,6 +67,8 @@ void export_symbol(const char *);
 void free_node(struct string_list *list);
 void free_list(struct string_list *s, struct string_list *e);
 struct string_list *copy_node(struct string_list *);
+struct string_list *copy_list_range(struct string_list *start,
+				    struct string_list *end);
 
 int yylex(void);
 int yyparse(void);
diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped
index 2ac23bc..af49390 100644
--- a/scripts/genksyms/lex.c_shipped
+++ b/scripts/genksyms/lex.c_shipped
@@ -79,6 +79,7 @@ typedef int flex_int32_t;
 typedef unsigned char flex_uint8_t; 
 typedef unsigned short int flex_uint16_t;
 typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
 
 /* Limits of integral types. */
 #ifndef INT8_MIN
@@ -109,8 +110,6 @@ typedef unsigned int flex_uint32_t;
 #define UINT32_MAX             (4294967295U)
 #endif
 
-#endif /* ! C99 */
-
 #endif /* ! FLEXINT_H */
 
 /* %endif */
@@ -456,16 +455,16 @@ struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static yyconst flex_int16_t yy_accept[76] =
+static yyconst flex_int16_t yy_accept[73] =
     {   0,
-        0,    0,    0,    0,   14,   12,    4,    3,   12,    7,
-       12,   12,    7,   12,   12,   12,   12,   12,    9,    9,
-       12,   12,   12,    4,    0,    5,    0,    7,    0,    6,
-        0,    0,    0,    0,    0,    0,    2,    8,   10,   10,
-        9,    0,    0,    9,    9,    0,    9,    0,    0,   11,
-        0,    0,    0,   10,    0,   10,    9,    9,    0,    0,
-        0,    0,    0,    0,    0,   10,   10,    0,    0,    0,
-        0,    0,    0,    1,    0
+        0,    0,   14,   12,    4,    3,   12,    7,   12,   12,
+       12,   12,   12,    9,    9,   12,   12,    7,   12,   12,
+        4,    0,    5,    0,    7,    8,    0,    6,    0,    0,
+       10,   10,    9,    0,    0,    9,    9,    0,    9,    0,
+        0,    0,    0,    2,    0,    0,   11,    0,   10,    0,
+       10,    9,    9,    0,    0,    0,   10,   10,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        1,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -507,108 +506,104 @@ static yyconst flex_int32_t yy_meta[29] =
         8,    7,    3,    3,    3,    1,    3,    1
     } ;
 
-static yyconst flex_int16_t yy_base[88] =
+static yyconst flex_int16_t yy_base[85] =
     {   0,
-        0,  147,   21,  140,  145,  284,   39,  284,   26,    0,
-       32,  126,   40,   44,  115,   35,   36,   46,   50,   53,
-       39,   61,   54,   79,   65,  284,    0,    0,   66,  284,
-        0,  119,   79,   75,  123,  104,  284,  284,  107,    0,
-       79,   73,   76,   76,   66,    0,    0,   85,   86,  284,
-      133,   83,   91,  284,   99,  147,  284,  114,  122,   70,
-      107,  141,  172,  151,  135,  181,  284,  137,  114,  157,
-      149,   48,   45,  284,  284,  208,  214,  222,  230,  238,
-      246,  250,  255,  256,  261,  267,  275
+        0,  145,  150,  266,   27,  266,   25,    0,  131,   23,
+       23,   16,   23,   39,   31,   25,   39,   60,   22,   65,
+       57,   43,  266,    0,    0,  266,   61,  266,    0,  128,
+       74,    0,  113,   59,   62,  113,   52,    0,    0,   72,
+       66,  110,  100,  266,   73,   74,  266,   70,  266,   90,
+      103,  266,   84,  129,  108,  113,  143,  266,  107,   66,
+      118,  137,  168,  120,   80,   91,  145,  143,   83,   41,
+      266,  266,  190,  196,  204,  212,  220,  228,  232,  237,
+      238,  243,  249,  257
     } ;
 
-static yyconst flex_int16_t yy_def[88] =
+static yyconst flex_int16_t yy_def[85] =
     {   0,
-       75,    1,    1,    3,   75,   75,   75,   75,   76,   77,
-       78,   75,   77,   79,   75,   75,   75,   75,   75,   19,
-       75,   75,   75,   75,   76,   75,   80,   77,   78,   75,
-       81,   75,   76,   78,   79,   79,   75,   75,   75,   39,
-       19,   82,   83,   75,   75,   84,   20,   76,   78,   75,
-       79,   51,   85,   75,   75,   75,   75,   84,   79,   51,
-       79,   79,   79,   51,   75,   75,   75,   86,   79,   63,
-       86,   87,   87,   75,    0,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75
+       72,    1,   72,   72,   72,   72,   73,   74,   72,   72,
+       75,   72,   72,   72,   14,   72,   72,   74,   72,   76,
+       72,   73,   72,   77,   74,   72,   75,   72,   78,   72,
+       72,   31,   14,   79,   80,   72,   72,   81,   15,   73,
+       75,   76,   76,   72,   73,   75,   72,   82,   72,   72,
+       72,   72,   81,   76,   54,   72,   72,   72,   76,   54,
+       76,   76,   76,   54,   83,   76,   63,   83,   84,   84,
+       72,    0,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
     } ;
 
-static yyconst flex_int16_t yy_nxt[313] =
+static yyconst flex_int16_t yy_nxt[295] =
     {   0,
-        6,    7,    8,    7,    9,    6,   10,    6,    6,   11,
-        6,    6,   12,    6,    6,    6,    6,    6,    6,   10,
-       10,   10,   13,   10,   10,    6,   10,    6,   15,   16,
-       26,   15,   17,   18,   19,   20,   20,   21,   15,   22,
-       24,   30,   24,   38,   33,   36,   37,   74,   23,   34,
-       74,   27,   38,   38,   38,   38,   38,   31,   32,   39,
-       39,   39,   40,   41,   41,   42,   47,   47,   47,   26,
-       43,   38,   44,   45,   46,   30,   44,   75,   38,   38,
-       24,   38,   24,   26,   30,   40,   55,   55,   57,   26,
-       27,   31,   57,   43,   35,   30,   64,   64,   64,   57,
-
-       31,   65,   65,   75,   27,   36,   37,   35,   59,   37,
-       27,   31,   56,   56,   56,   59,   37,   51,   52,   52,
-       39,   39,   39,   59,   37,   37,   68,   53,   54,   54,
-       69,   50,   38,   54,   59,   37,   44,   45,   32,   37,
-       44,   35,   59,   37,   75,   14,   60,   60,   66,   66,
-       66,   37,   14,   72,   75,   61,   62,   63,   59,   61,
-       56,   56,   56,   69,   64,   64,   64,   69,   67,   67,
-       75,   75,   75,   67,   37,   35,   75,   75,   75,   61,
-       62,   75,   75,   61,   75,   70,   70,   70,   75,   75,
-       75,   70,   70,   70,   66,   66,   66,   75,   75,   75,
-
-       75,   75,   54,   54,   75,   75,   75,   54,   25,   25,
-       25,   25,   25,   25,   25,   25,   28,   75,   75,   28,
-       28,   28,   29,   29,   29,   29,   29,   29,   29,   29,
-       35,   35,   35,   35,   35,   35,   35,   35,   48,   75,
-       48,   48,   48,   48,   48,   48,   49,   75,   49,   49,
-       49,   49,   49,   49,   42,   42,   75,   42,   56,   75,
-       56,   58,   58,   58,   66,   75,   66,   71,   71,   71,
-       71,   71,   71,   71,   71,   73,   73,   73,   73,   73,
-       73,   73,   73,    5,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75
+        4,    5,    6,    5,    7,    4,    8,    9,   10,   11,
+        9,   12,   13,   14,   15,   15,   16,    9,   17,    8,
+        8,    8,   18,    8,    8,    4,    8,   19,   21,   23,
+       21,   26,   28,   26,   26,   30,   31,   31,   31,   26,
+       26,   26,   26,   71,   39,   39,   39,   23,   29,   26,
+       24,   32,   33,   33,   34,   72,   26,   26,   21,   35,
+       21,   36,   37,   38,   40,   36,   43,   44,   24,   41,
+       28,   32,   50,   50,   52,   28,   23,   23,   52,   35,
+       56,   56,   44,   28,   42,   71,   29,   31,   31,   31,
+       42,   29,   59,   44,   48,   49,   49,   24,   24,   29,
+
+       49,   43,   44,   51,   51,   51,   36,   37,   59,   44,
+       36,   65,   44,   54,   55,   55,   51,   51,   51,   59,
+       44,   64,   64,   64,   58,   58,   57,   57,   57,   58,
+       59,   44,   42,   64,   64,   64,   52,   72,   59,   44,
+       47,   66,   60,   60,   42,   44,   59,   69,   26,   72,
+       20,   61,   62,   63,   72,   61,   57,   57,   57,   66,
+       72,   72,   72,   66,   49,   49,   72,   61,   62,   49,
+       44,   61,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   67,   67,   67,   72,   72,   72,   67,   67,   67,
+       22,   22,   22,   22,   22,   22,   22,   22,   25,   72,
+
+       72,   25,   25,   25,   27,   27,   27,   27,   27,   27,
+       27,   27,   42,   42,   42,   42,   42,   42,   42,   42,
+       45,   72,   45,   45,   45,   45,   45,   45,   46,   72,
+       46,   46,   46,   46,   46,   46,   34,   34,   72,   34,
+       51,   72,   51,   53,   53,   53,   57,   72,   57,   68,
+       68,   68,   68,   68,   68,   68,   68,   70,   70,   70,
+       70,   70,   70,   70,   70,    3,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
     } ;
 
-static yyconst flex_int16_t yy_chk[313] =
+static yyconst flex_int16_t yy_chk[295] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
-        9,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        7,   11,    7,   16,   13,   14,   14,   73,    3,   13,
-       72,    9,   16,   17,   17,   21,   21,   11,   18,   18,
-       18,   18,   19,   19,   19,   19,   20,   20,   20,   25,
-       19,   23,   19,   19,   19,   29,   19,   20,   22,   22,
-       24,   23,   24,   33,   34,   42,   43,   43,   45,   48,
-       25,   29,   45,   42,   60,   49,   52,   52,   52,   44,
-
-       34,   53,   53,   41,   33,   36,   36,   52,   61,   61,
-       48,   49,   55,   55,   55,   69,   69,   36,   36,   36,
-       39,   39,   39,   59,   59,   35,   59,   39,   39,   39,
-       61,   32,   15,   39,   51,   51,   58,   58,   12,   68,
-       58,   68,   62,   62,    5,    4,   51,   51,   65,   65,
-       65,   71,    2,   71,    0,   51,   51,   51,   70,   51,
-       56,   56,   56,   62,   64,   64,   64,   62,   56,   56,
-        0,    0,    0,   56,   63,   64,    0,    0,    0,   70,
-       70,    0,    0,   70,    0,   63,   63,   63,    0,    0,
-        0,   63,   63,   63,   66,   66,   66,    0,    0,    0,
-
-        0,    0,   66,   66,    0,    0,    0,   66,   76,   76,
-       76,   76,   76,   76,   76,   76,   77,    0,    0,   77,
-       77,   77,   78,   78,   78,   78,   78,   78,   78,   78,
-       79,   79,   79,   79,   79,   79,   79,   79,   80,    0,
-       80,   80,   80,   80,   80,   80,   81,    0,   81,   81,
-       81,   81,   81,   81,   82,   82,    0,   82,   83,    0,
-       83,   84,   84,   84,   85,    0,   85,   86,   86,   86,
-       86,   86,   86,   86,   86,   87,   87,   87,   87,   87,
-       87,   87,   87,   75,   75,   75,   75,   75,   75,   75,
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-
-       75,   75,   75,   75,   75,   75,   75,   75,   75,   75,
-       75,   75
+        1,    1,    1,    1,    1,    1,    1,    1,    5,    7,
+        5,   10,   11,   12,   12,   13,   13,   13,   13,   19,
+       10,   16,   16,   70,   15,   15,   15,   22,   11,   19,
+        7,   14,   14,   14,   14,   15,   17,   17,   21,   14,
+       21,   14,   14,   14,   18,   14,   20,   20,   22,   18,
+       27,   34,   35,   35,   37,   41,   40,   45,   37,   34,
+       48,   48,   65,   46,   65,   69,   27,   31,   31,   31,
+       60,   41,   66,   66,   31,   31,   31,   40,   45,   46,
+
+       31,   43,   43,   50,   50,   50,   53,   53,   59,   59,
+       53,   59,   42,   43,   43,   43,   51,   51,   51,   61,
+       61,   55,   55,   55,   51,   51,   56,   56,   56,   51,
+       54,   54,   55,   64,   64,   64,   36,   33,   62,   62,
+       30,   61,   54,   54,   64,   68,   67,   68,    9,    3,
+        2,   54,   54,   54,    0,   54,   57,   57,   57,   62,
+        0,    0,    0,   62,   57,   57,    0,   67,   67,   57,
+       63,   67,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,   63,   63,   63,    0,    0,    0,   63,   63,   63,
+       73,   73,   73,   73,   73,   73,   73,   73,   74,    0,
+
+        0,   74,   74,   74,   75,   75,   75,   75,   75,   75,
+       75,   75,   76,   76,   76,   76,   76,   76,   76,   76,
+       77,    0,   77,   77,   77,   77,   77,   77,   78,    0,
+       78,   78,   78,   78,   78,   78,   79,   79,    0,   79,
+       80,    0,   80,   81,   81,   81,   82,    0,   82,   83,
+       83,   83,   83,   83,   83,   83,   83,   84,   84,   84,
+       84,   84,   84,   84,   84,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72,   72,   72
+
     } ;
 
 static yy_state_type yy_last_accepting_state;
@@ -619,8 +614,8 @@ int yy_flex_debug = 1;
 
 static yyconst flex_int16_t yy_rule_linenum[13] =
     {   0,
-       71,   72,   73,   76,   79,   80,   81,   87,   88,   89,
-       91,   94
+       67,   68,   69,   72,   75,   76,   77,   83,   84,   85,
+       87,   90
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -667,15 +662,11 @@ char *yytext;
    and then we categorize those basic tokens in the second stage.  */
 #define YY_DECL		static int yylex1(void)
 
-/* Version 2 checksumming does proper tokenization; version 1 wasn't
-   quite so pedantic.  */
-
 /* We don't do multiple input files.  */
 #define YY_NO_INPUT 1
-#line 676 "scripts/genksyms/lex.c"
+#line 668 "scripts/genksyms/lex.c"
 
 #define INITIAL 0
-#define V2_TOKENS 1
 
 #ifndef YY_NO_UNISTD_H
 /* Special case for "unistd.h", since it is non-ANSI. We include it way
@@ -808,7 +799,7 @@ static int input (void );
 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
 		{ \
 		int c = '*'; \
-		size_t n; \
+		int n; \
 		for ( n = 0; n < max_size && \
 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
 			buf[n] = (char) c; \
@@ -918,12 +909,12 @@ YY_DECL
 	register int yy_act;
     
 /* %% [7.0] user's declarations go here */
-#line 67 "scripts/genksyms/lex.l"
+#line 63 "scripts/genksyms/lex.l"
 
 
 
  /* Keep track of our location in the original source files.  */
-#line 927 "scripts/genksyms/lex.c"
+#line 918 "scripts/genksyms/lex.c"
 
 	if ( !(yy_init) )
 		{
@@ -987,13 +978,13 @@ yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 76 )
+				if ( yy_current_state >= 73 )
 					yy_c = yy_meta[(unsigned int) yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
 			++yy_cp;
 			}
-		while ( yy_base[yy_current_state] != 284 );
+		while ( yy_base[yy_current_state] != 266 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1041,42 +1032,42 @@ do_action:	/* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 71 "scripts/genksyms/lex.l"
+#line 67 "scripts/genksyms/lex.l"
 return FILENAME;
 	YY_BREAK
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 72 "scripts/genksyms/lex.l"
+#line 68 "scripts/genksyms/lex.l"
 cur_line++;
 	YY_BREAK
 case 3:
 /* rule 3 can match eol */
 YY_RULE_SETUP
-#line 73 "scripts/genksyms/lex.l"
+#line 69 "scripts/genksyms/lex.l"
 cur_line++;
 	YY_BREAK
 /* Ignore all other whitespace.  */
 case 4:
 YY_RULE_SETUP
-#line 76 "scripts/genksyms/lex.l"
+#line 72 "scripts/genksyms/lex.l"
 ;
 	YY_BREAK
 case 5:
 /* rule 5 can match eol */
 YY_RULE_SETUP
-#line 79 "scripts/genksyms/lex.l"
+#line 75 "scripts/genksyms/lex.l"
 return STRING;
 	YY_BREAK
 case 6:
 /* rule 6 can match eol */
 YY_RULE_SETUP
-#line 80 "scripts/genksyms/lex.l"
+#line 76 "scripts/genksyms/lex.l"
 return CHAR;
 	YY_BREAK
 case 7:
 YY_RULE_SETUP
-#line 81 "scripts/genksyms/lex.l"
+#line 77 "scripts/genksyms/lex.l"
 return IDENT;
 	YY_BREAK
 /* The Pedant requires that the other C multi-character tokens be
@@ -1085,38 +1076,37 @@ return IDENT;
     around them properly.  */
 case 8:
 YY_RULE_SETUP
-#line 87 "scripts/genksyms/lex.l"
+#line 83 "scripts/genksyms/lex.l"
 return OTHER;
 	YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 88 "scripts/genksyms/lex.l"
+#line 84 "scripts/genksyms/lex.l"
 return INT;
 	YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 89 "scripts/genksyms/lex.l"
+#line 85 "scripts/genksyms/lex.l"
 return REAL;
 	YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 91 "scripts/genksyms/lex.l"
+#line 87 "scripts/genksyms/lex.l"
 return DOTS;
 	YY_BREAK
 /* All other tokens are single characters.  */
 case 12:
 YY_RULE_SETUP
-#line 94 "scripts/genksyms/lex.l"
+#line 90 "scripts/genksyms/lex.l"
 return yytext[0];
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 97 "scripts/genksyms/lex.l"
+#line 93 "scripts/genksyms/lex.l"
 ECHO;
 	YY_BREAK
-#line 1118 "scripts/genksyms/lex.c"
+#line 1109 "scripts/genksyms/lex.c"
 case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(V2_TOKENS):
 	yyterminate();
 
 	case YY_END_OF_BUFFER:
@@ -1429,7 +1419,7 @@ static int yy_get_next_buffer (void)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 76 )
+			if ( yy_current_state >= 73 )
 				yy_c = yy_meta[(unsigned int) yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1462,11 +1452,11 @@ static int yy_get_next_buffer (void)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 76 )
+		if ( yy_current_state >= 73 )
 			yy_c = yy_meta[(unsigned int) yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 75);
+	yy_is_jam = (yy_current_state == 72);
 
 	return yy_is_jam ? 0 : yy_current_state;
 }
@@ -2252,7 +2242,7 @@ void yyfree (void * ptr )
 
 /* %ok-for-header */
 
-#line 97 "scripts/genksyms/lex.l"
+#line 93 "scripts/genksyms/lex.l"
 
 
 
@@ -2263,12 +2253,23 @@ void yyfree (void * ptr )
 
 /* Macros to append to our phrase collection list.  */
 
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
 #define _APP(T,L)	do {						   \
 			  cur_node = next_node;				   \
 			  next_node = xmalloc(sizeof(*next_node));	   \
 			  next_node->next = cur_node;			   \
 			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-			  cur_node->tag = SYM_NORMAL;			   \
+			  cur_node->tag =				   \
+			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
 			} while (0)
 
 #define APP		_APP(yytext, yyleng)
@@ -2294,7 +2295,6 @@ yylex(void)
 
   if (lexstate == ST_NOTSTARTED)
     {
-      BEGIN(V2_TOKENS);
       next_node = xmalloc(sizeof(*next_node));
       next_node->next = NULL;
       lexstate = ST_NORMAL;
@@ -2347,8 +2347,8 @@ repeat:
 
 		  case STRUCT_KEYW:
 		  case UNION_KEYW:
-		    dont_want_brace_phrase = 3;
 		  case ENUM_KEYW:
+		    dont_want_brace_phrase = 3;
 		    suppress_type_lookup = 2;
 		    goto fini;
 
@@ -2358,8 +2358,7 @@ repeat:
 	      }
 	    if (!suppress_type_lookup)
 	      {
-		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
-		if (sym && sym->type == SYM_TYPEDEF)
+		if (find_symbol(yytext, SYM_TYPEDEF, 1))
 		  token = TYPE;
 	      }
 	  }
@@ -2478,7 +2477,20 @@ repeat:
 	  ++count;
 	  APP;
 	  goto repeat;
-	case ')': case ']': case '}':
+	case '}':
+	  /* is this the last line of an enum declaration? */
+	  if (count == 0)
+	    {
+	      /* Put back the token we just read so's we can find it again
+		 after registering the expression.  */
+	      unput(token);
+
+	      lexstate = ST_NORMAL;
+	      token = EXPRESSION_PHRASE;
+	      break;
+	    }
+	  /* FALLTHRU */
+	case ')': case ']':
 	  --count;
 	  APP;
 	  goto repeat;
@@ -2567,143 +2579,4 @@ fini:
 
   return token;
 }
-/* A Bison parser, made by GNU Bison 2.3.  */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
-
-/* As a special exception, you may create a larger work that contains
-   part or all of the Bison parser skeleton and distribute that work
-   under terms of your choice, so long as that work isn't itself a
-   parser generator using the skeleton or a modified version thereof
-   as a parser skeleton.  Alternatively, if you modify or redistribute
-   the parser skeleton itself, you may (at your option) remove this
-   special exception, which will cause the skeleton and the resulting
-   Bison output files to be licensed under the GNU General Public
-   License without this special exception.
-
-   This special exception was added by the Free Software Foundation in
-   version 2.2 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     ASM_KEYW = 258,
-     ATTRIBUTE_KEYW = 259,
-     AUTO_KEYW = 260,
-     BOOL_KEYW = 261,
-     CHAR_KEYW = 262,
-     CONST_KEYW = 263,
-     DOUBLE_KEYW = 264,
-     ENUM_KEYW = 265,
-     EXTERN_KEYW = 266,
-     EXTENSION_KEYW = 267,
-     FLOAT_KEYW = 268,
-     INLINE_KEYW = 269,
-     INT_KEYW = 270,
-     LONG_KEYW = 271,
-     REGISTER_KEYW = 272,
-     RESTRICT_KEYW = 273,
-     SHORT_KEYW = 274,
-     SIGNED_KEYW = 275,
-     STATIC_KEYW = 276,
-     STRUCT_KEYW = 277,
-     TYPEDEF_KEYW = 278,
-     UNION_KEYW = 279,
-     UNSIGNED_KEYW = 280,
-     VOID_KEYW = 281,
-     VOLATILE_KEYW = 282,
-     TYPEOF_KEYW = 283,
-     EXPORT_SYMBOL_KEYW = 284,
-     ASM_PHRASE = 285,
-     ATTRIBUTE_PHRASE = 286,
-     BRACE_PHRASE = 287,
-     BRACKET_PHRASE = 288,
-     EXPRESSION_PHRASE = 289,
-     CHAR = 290,
-     DOTS = 291,
-     IDENT = 292,
-     INT = 293,
-     REAL = 294,
-     STRING = 295,
-     TYPE = 296,
-     OTHER = 297,
-     FILENAME = 298
-   };
-#endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
 
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index fe50ff9..e4ddd49 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -55,10 +55,6 @@ CHAR			L?\'([^\\\']*\\.)*[^\\\']*\'
 
 MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
-/* Version 2 checksumming does proper tokenization; version 1 wasn't
-   quite so pedantic.  */
-%s V2_TOKENS
-
 /* We don't do multiple input files.  */
 %option noyywrap
 
@@ -84,9 +80,9 @@ MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
     recognized as tokens.  We don't actually use them since we don't
     parse expressions, but we do want whitespace to be arranged
     around them properly.  */
-<V2_TOKENS>{MC_TOKEN}			return OTHER;
-<V2_TOKENS>{INT}			return INT;
-<V2_TOKENS>{REAL}			return REAL;
+{MC_TOKEN}				return OTHER;
+{INT}					return INT;
+{REAL}					return REAL;
 
 "..."					return DOTS;
 
@@ -103,12 +99,23 @@ MC_TOKEN		([~%^&*+=|<>/-]=)|(&&)|("||")|(->)|(<<)|(>>)
 
 /* Macros to append to our phrase collection list.  */
 
+/*
+ * We mark any token, that that equals to a known enumerator, as
+ * SYM_ENUM_CONST. The parser will change this for struct and union tags later,
+ * the only problem is struct and union members:
+ *    enum e { a, b }; struct s { int a, b; }
+ * but in this case, the only effect will be, that the ABI checksums become
+ * more volatile, which is acceptable. Also, such collisions are quite rare,
+ * so far it was only observed in include/linux/telephony.h.
+ */
 #define _APP(T,L)	do {						   \
 			  cur_node = next_node;				   \
 			  next_node = xmalloc(sizeof(*next_node));	   \
 			  next_node->next = cur_node;			   \
 			  cur_node->string = memcpy(xmalloc(L+1), T, L+1); \
-			  cur_node->tag = SYM_NORMAL;			   \
+			  cur_node->tag =				   \
+			    find_symbol(cur_node->string, SYM_ENUM_CONST, 1)?\
+			    SYM_ENUM_CONST : SYM_NORMAL ;		   \
 			} while (0)
 
 #define APP		_APP(yytext, yyleng)
@@ -134,7 +141,6 @@ yylex(void)
 
   if (lexstate == ST_NOTSTARTED)
     {
-      BEGIN(V2_TOKENS);
       next_node = xmalloc(sizeof(*next_node));
       next_node->next = NULL;
       lexstate = ST_NORMAL;
@@ -187,8 +193,8 @@ repeat:
 
 		  case STRUCT_KEYW:
 		  case UNION_KEYW:
-		    dont_want_brace_phrase = 3;
 		  case ENUM_KEYW:
+		    dont_want_brace_phrase = 3;
 		    suppress_type_lookup = 2;
 		    goto fini;
 
@@ -198,8 +204,7 @@ repeat:
 	      }
 	    if (!suppress_type_lookup)
 	      {
-		struct symbol *sym = find_symbol(yytext, SYM_TYPEDEF);
-		if (sym && sym->type == SYM_TYPEDEF)
+		if (find_symbol(yytext, SYM_TYPEDEF, 1))
 		  token = TYPE;
 	      }
 	  }
@@ -318,7 +323,20 @@ repeat:
 	  ++count;
 	  APP;
 	  goto repeat;
-	case ')': case ']': case '}':
+	case '}':
+	  /* is this the last line of an enum declaration? */
+	  if (count == 0)
+	    {
+	      /* Put back the token we just read so's we can find it again
+		 after registering the expression.  */
+	      unput(token);
+
+	      lexstate = ST_NORMAL;
+	      token = EXPRESSION_PHRASE;
+	      break;
+	    }
+	  /* FALLTHRU */
+	case ')': case ']':
 	  --count;
 	  APP;
 	  goto repeat;
diff --git a/scripts/genksyms/parse.c_shipped b/scripts/genksyms/parse.c_shipped
index 809b949..1a0b860 100644
--- a/scripts/genksyms/parse.c_shipped
+++ b/scripts/genksyms/parse.c_shipped
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Skeleton implementation for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -29,7 +28,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -47,7 +46,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.3"
+#define YYBISON_VERSION "2.4.1"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -55,11 +54,75 @@
 /* Pure parsers.  */
 #define YYPURE 0
 
+/* Push parsers.  */
+#define YYPUSH 0
+
+/* Pull parsers.  */
+#define YYPULL 1
+
 /* Using locations.  */
 #define YYLSP_NEEDED 0
 
 
 
+/* Copy the first part of user declarations.  */
+
+/* Line 189 of yacc.c  */
+#line 24 "scripts/genksyms/parse.y"
+
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "genksyms.h"
+
+static int is_typedef;
+static int is_extern;
+static char *current_name;
+static struct string_list *decl_spec;
+
+static void yyerror(const char *);
+
+static inline void
+remove_node(struct string_list **p)
+{
+  struct string_list *node = *p;
+  *p = node->next;
+  free_node(node);
+}
+
+static inline void
+remove_list(struct string_list **pb, struct string_list **pe)
+{
+  struct string_list *b = *pb, *e = *pe;
+  *pb = e;
+  free_list(b, e);
+}
+
+
+
+/* Line 189 of yacc.c  */
+#line 106 "scripts/genksyms/parse.c"
+
+/* Enabling traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+
+/* Enabling verbose error messages.  */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -109,117 +172,22 @@
      FILENAME = 298
    };
 #endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
-
-
-
-/* Copy the first part of user declarations.  */
-#line 24 "scripts/genksyms/parse.y"
-
-
-#include <assert.h>
-#include <stdlib.h>
-#include "genksyms.h"
-
-static int is_typedef;
-static int is_extern;
-static char *current_name;
-static struct string_list *decl_spec;
-
-static void yyerror(const char *);
-
-static inline void
-remove_node(struct string_list **p)
-{
-  struct string_list *node = *p;
-  *p = node->next;
-  free_node(node);
-}
-
-static inline void
-remove_list(struct string_list **pb, struct string_list **pe)
-{
-  struct string_list *b = *pb, *e = *pe;
-  *pb = e;
-  free_list(b, e);
-}
-
-
-
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
 
-/* Enabling verbose error messages.  */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 
-
 /* Copy the second part of user declarations.  */
 
 
-/* Line 216 of yacc.c.  */
-#line 223 "scripts/genksyms/parse.c"
+/* Line 264 of yacc.c  */
+#line 191 "scripts/genksyms/parse.c"
 
 #ifdef short
 # undef short
@@ -294,14 +262,14 @@ typedef short int yytype_int16;
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static int
-YYID (int i)
+YYID (int yyi)
 #else
 static int
-YYID (i)
-    int i;
+YYID (yyi)
+    int yyi;
 #endif
 {
-  return i;
+  return yyi;
 }
 #endif
 
@@ -382,9 +350,9 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
 {
-  yytype_int16 yyss;
-  YYSTYPE yyvs;
-  };
+  yytype_int16 yyss_alloc;
+  YYSTYPE yyvs_alloc;
+};
 
 /* The size of the maximum gap between one aligned stack and the next.  */
 # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
@@ -418,12 +386,12 @@ union yyalloc
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack)					\
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
     do									\
       {									\
 	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack, Stack, yysize);				\
-	Stack = &yyptr->Stack;						\
+	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
+	Stack = &yyptr->Stack_alloc;					\
 	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
 	yyptr += yynewbytes / sizeof (*yyptr);				\
       }									\
@@ -434,16 +402,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   523
+#define YYLAST   532
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  53
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  46
+#define YYNNTS  49
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  126
+#define YYNRULES  132
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  178
+#define YYNSTATES  188
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -504,7 +472,8 @@ static const yytype_uint16 yyprhs[] =
      239,   242,   245,   247,   248,   250,   252,   257,   262,   265,
      269,   273,   277,   278,   280,   283,   287,   291,   292,   294,
      296,   299,   303,   306,   307,   309,   311,   315,   318,   321,
-     323,   326,   327,   330,   333,   334,   336
+     323,   326,   327,   330,   334,   339,   341,   345,   347,   351,
+     354,   355,   357
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -512,16 +481,16 @@ static const yytype_int8 yyrhs[] =
 {
       54,     0,    -1,    55,    -1,    54,    55,    -1,    -1,    56,
       57,    -1,    -1,    12,    23,    58,    60,    -1,    -1,    23,
-      59,    60,    -1,    60,    -1,    84,    -1,    96,    -1,    98,
+      59,    60,    -1,    60,    -1,    84,    -1,    99,    -1,   101,
       -1,     1,    44,    -1,     1,    45,    -1,    64,    61,    44,
       -1,    -1,    62,    -1,    63,    -1,    62,    46,    63,    -1,
-      74,    97,    95,    85,    -1,    -1,    65,    -1,    66,    -1,
+      74,   100,    95,    85,    -1,    -1,    65,    -1,    66,    -1,
       65,    66,    -1,    67,    -1,    68,    -1,     5,    -1,    17,
       -1,    21,    -1,    11,    -1,    14,    -1,    69,    -1,    73,
       -1,    28,    47,    65,    48,    49,    -1,    28,    47,    65,
       49,    -1,    22,    37,    -1,    24,    37,    -1,    10,    37,
       -1,    22,    37,    87,    -1,    24,    37,    87,    -1,    10,
-      37,    32,    -1,    10,    32,    -1,    22,    87,    -1,    24,
+      37,    96,    -1,    10,    96,    -1,    22,    87,    -1,    24,
       87,    -1,     7,    -1,    19,    -1,    15,    -1,    16,    -1,
       20,    -1,    25,    -1,    13,    -1,     9,    -1,    26,    -1,
        6,    -1,    41,    -1,    48,    71,    -1,    -1,    72,    -1,
@@ -543,26 +512,29 @@ static const yytype_int8 yyrhs[] =
       91,    44,    -1,     1,    44,    -1,    -1,    92,    -1,    93,
       -1,    92,    46,    93,    -1,    76,    95,    -1,    37,    94,
       -1,    94,    -1,    52,    34,    -1,    -1,    95,    31,    -1,
-      30,    44,    -1,    -1,    30,    -1,    29,    47,    37,    49,
-      44,    -1
+      51,    97,    45,    -1,    51,    97,    46,    45,    -1,    98,
+      -1,    97,    46,    98,    -1,    37,    -1,    37,    50,    34,
+      -1,    30,    44,    -1,    -1,    30,    -1,    29,    47,    37,
+      49,    44,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   103,   103,   104,   108,   108,   114,   114,   116,   116,
-     118,   119,   120,   121,   122,   123,   127,   141,   142,   146,
-     154,   167,   173,   174,   178,   179,   183,   189,   193,   194,
-     195,   196,   197,   201,   202,   203,   204,   208,   210,   212,
-     216,   223,   230,   239,   240,   241,   245,   246,   247,   248,
-     249,   250,   251,   252,   253,   254,   255,   259,   264,   265,
-     269,   270,   274,   274,   274,   275,   283,   284,   288,   297,
-     299,   301,   303,   305,   312,   313,   317,   318,   319,   321,
-     323,   325,   327,   332,   333,   334,   338,   339,   343,   344,
-     349,   354,   356,   360,   361,   369,   373,   375,   377,   379,
-     381,   386,   395,   396,   401,   406,   407,   411,   412,   416,
-     417,   421,   423,   428,   429,   433,   434,   438,   439,   440,
-     444,   448,   449,   453,   457,   458,   462
+       0,   104,   104,   105,   109,   109,   115,   115,   117,   117,
+     119,   120,   121,   122,   123,   124,   128,   142,   143,   147,
+     155,   168,   174,   175,   179,   180,   184,   190,   194,   195,
+     196,   197,   198,   202,   203,   204,   205,   209,   211,   213,
+     217,   224,   231,   241,   244,   245,   249,   250,   251,   252,
+     253,   254,   255,   256,   257,   258,   259,   263,   268,   269,
+     273,   274,   278,   278,   278,   279,   287,   288,   292,   301,
+     303,   305,   307,   309,   316,   317,   321,   322,   323,   325,
+     327,   329,   331,   336,   337,   338,   342,   343,   347,   348,
+     353,   358,   360,   364,   365,   373,   377,   379,   381,   383,
+     385,   390,   399,   400,   405,   410,   411,   415,   416,   420,
+     421,   425,   427,   432,   433,   437,   438,   442,   443,   444,
+     448,   452,   453,   457,   458,   462,   463,   466,   471,   479,
+     483,   484,   488
 };
 #endif
 
@@ -581,8 +553,8 @@ static const char *const yytname[] =
   "ATTRIBUTE_PHRASE", "BRACE_PHRASE", "BRACKET_PHRASE",
   "EXPRESSION_PHRASE", "CHAR", "DOTS", "IDENT", "INT", "REAL", "STRING",
   "TYPE", "OTHER", "FILENAME", "';'", "'}'", "','", "'('", "'*'", "')'",
-  "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "@1",
-  "declaration1", "@2", "@3", "simple_declaration",
+  "'='", "'{'", "':'", "$accept", "declaration_seq", "declaration", "$@1",
+  "declaration1", "$@2", "$@3", "simple_declaration",
   "init_declarator_list_opt", "init_declarator_list", "init_declarator",
   "decl_specifier_seq_opt", "decl_specifier_seq", "decl_specifier",
   "storage_class_specifier", "type_specifier", "simple_type_specifier",
@@ -596,7 +568,8 @@ static const char *const yytname[] =
   "member_specification", "member_declaration",
   "member_declarator_list_opt", "member_declarator_list",
   "member_declarator", "member_bitfield_declarator", "attribute_opt",
-  "asm_definition", "asm_phrase_opt", "export_definition", 0
+  "enum_body", "enumerator_list", "enumerator", "asm_definition",
+  "asm_phrase_opt", "export_definition", 0
 };
 #endif
 
@@ -629,7 +602,8 @@ static const yytype_uint8 yyr1[] =
       81,    82,    82,    83,    83,    83,    83,    83,    83,    83,
       83,    84,    85,    85,    86,    87,    87,    88,    88,    89,
       89,    90,    90,    91,    91,    92,    92,    93,    93,    93,
-      94,    95,    95,    96,    97,    97,    98
+      94,    95,    95,    96,    96,    97,    97,    98,    98,    99,
+     100,   100,   101
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -647,7 +621,8 @@ static const yytype_uint8 yyr2[] =
        2,     2,     1,     0,     1,     1,     4,     4,     2,     3,
        3,     3,     0,     1,     2,     3,     3,     0,     1,     1,
        2,     3,     2,     0,     1,     1,     3,     2,     2,     1,
-       2,     0,     2,     2,     0,     1,     5
+       2,     0,     2,     3,     4,     1,     3,     1,     3,     2,
+       0,     1,     5
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -659,17 +634,18 @@ static const yytype_uint8 yydefact[] =
       62,    53,     0,    31,     0,    52,    32,    48,    49,    29,
       65,    47,    50,    30,     0,     8,     0,    51,    54,    63,
        0,     0,     0,    64,    56,     5,    10,    17,    23,    24,
-      26,    27,    33,    34,    11,    12,    13,    14,    15,    43,
-      39,     6,    37,     0,    44,    22,    38,    45,     0,     0,
-     123,    68,     0,    58,     0,    18,    19,     0,   124,    67,
-      25,    42,    22,    40,     0,   113,     0,     0,   109,     9,
-      17,    41,     0,     0,     0,     0,    57,    59,    60,    16,
-       0,    66,   125,   101,   121,    71,     0,     7,   112,   106,
-      76,    77,     0,     0,     0,   121,    75,     0,   114,   115,
-     119,   105,     0,   110,   124,     0,    36,     0,    73,    72,
-      61,    20,   102,     0,    93,     0,    84,    87,    88,   118,
+      26,    27,    33,    34,    11,    12,    13,    14,    15,    39,
+       0,    43,     6,    37,     0,    44,    22,    38,    45,     0,
+       0,   129,    68,     0,    58,     0,    18,    19,     0,   130,
+      67,    25,    42,   127,     0,   125,    22,    40,     0,   113,
+       0,     0,   109,     9,    17,    41,     0,     0,     0,     0,
+      57,    59,    60,    16,     0,    66,   131,   101,   121,    71,
+       0,     0,   123,     0,     7,   112,   106,    76,    77,     0,
+       0,     0,   121,    75,     0,   114,   115,   119,   105,     0,
+     110,   130,     0,    36,     0,    73,    72,    61,    20,   102,
+       0,    93,     0,    84,    87,    88,   128,   124,   126,   118,
        0,    76,     0,   120,    74,   117,    80,     0,   111,     0,
-      35,   126,   122,     0,    21,   103,    70,    94,    56,     0,
+      35,   132,   122,     0,    21,   103,    70,    94,    56,     0,
       93,    90,    92,    69,    83,     0,    82,    81,     0,     0,
      116,   104,     0,    95,     0,    91,    98,     0,    85,    89,
       79,    78,   100,    99,     0,     0,    97,    96
@@ -678,46 +654,47 @@ static const yytype_uint8 yydefact[] =
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     1,     2,     3,    35,    72,    55,    36,    64,    65,
-      66,    75,    38,    39,    40,    41,    42,    67,    86,    87,
-      43,   114,    69,   105,   106,   125,   126,   127,   128,   151,
-     152,    44,   144,   145,    54,    76,    77,    78,   107,   108,
-     109,   110,   122,    45,    94,    46
+      -1,     1,     2,     3,    35,    76,    56,    36,    65,    66,
+      67,    79,    38,    39,    40,    41,    42,    68,    90,    91,
+      43,   121,    70,   112,   113,   132,   133,   134,   135,   161,
+     162,    44,   154,   155,    55,    80,    81,    82,   114,   115,
+     116,   117,   129,    51,    74,    75,    45,    98,    46
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -134
+#define YYPACT_NINF -135
 static const yytype_int16 yypact[] =
 {
-    -134,    16,  -134,   312,  -134,  -134,    20,  -134,  -134,  -134,
-    -134,  -134,   -18,  -134,    -3,  -134,  -134,  -134,  -134,  -134,
-    -134,  -134,  -134,  -134,   -26,  -134,   -25,  -134,  -134,  -134,
-      -7,     5,    27,  -134,  -134,  -134,  -134,    46,   482,  -134,
-    -134,  -134,  -134,  -134,  -134,  -134,  -134,  -134,  -134,  -134,
-      -8,  -134,    30,    97,  -134,   482,    30,  -134,   482,     7,
-    -134,  -134,    12,    10,    42,    55,  -134,    46,   -15,    15,
-    -134,  -134,   482,  -134,    25,    26,    47,   145,  -134,  -134,
-      46,  -134,   356,    39,    71,    77,  -134,    10,  -134,  -134,
-      46,  -134,  -134,  -134,  -134,  -134,   193,  -134,  -134,  -134,
-      75,  -134,     6,    95,    43,  -134,    28,    86,    85,  -134,
-    -134,  -134,    88,  -134,   103,    87,  -134,    91,  -134,  -134,
-    -134,  -134,   -23,    90,   401,    94,   101,   102,  -134,  -134,
-      98,  -134,   108,  -134,  -134,   109,  -134,   230,  -134,    26,
-    -134,  -134,  -134,   134,  -134,  -134,  -134,  -134,  -134,     9,
-      48,  -134,    35,  -134,  -134,   445,  -134,  -134,   125,   126,
-    -134,  -134,   128,  -134,   129,  -134,  -134,   267,  -134,  -134,
-    -134,  -134,  -134,  -134,   130,   131,  -134,  -134
+    -135,    20,  -135,   321,  -135,  -135,    30,  -135,  -135,  -135,
+    -135,  -135,   -28,  -135,     2,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,    -6,  -135,     9,  -135,  -135,  -135,
+      -5,    15,   -17,  -135,  -135,  -135,  -135,    18,   491,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,   -22,
+      31,  -135,  -135,    19,   106,  -135,   491,    19,  -135,   491,
+      50,  -135,  -135,    11,    -3,    51,    57,  -135,    18,   -14,
+      14,  -135,  -135,    48,    46,  -135,   491,  -135,    33,    32,
+      59,   154,  -135,  -135,    18,  -135,   365,    56,    60,    61,
+    -135,    -3,  -135,  -135,    18,  -135,  -135,  -135,  -135,  -135,
+     202,    74,  -135,   -23,  -135,  -135,  -135,    77,  -135,    16,
+     101,    49,  -135,    34,    92,    93,  -135,  -135,  -135,    94,
+    -135,   110,    95,  -135,    97,  -135,  -135,  -135,  -135,   -20,
+      96,   410,    99,   113,   100,  -135,  -135,  -135,  -135,  -135,
+     103,  -135,   107,  -135,  -135,   111,  -135,   239,  -135,    32,
+    -135,  -135,  -135,   123,  -135,  -135,  -135,  -135,  -135,     3,
+      52,  -135,    38,  -135,  -135,   454,  -135,  -135,   117,   128,
+    -135,  -135,   134,  -135,   135,  -135,  -135,   276,  -135,  -135,
+    -135,  -135,  -135,  -135,   137,   138,  -135,  -135
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -134,  -134,   180,  -134,  -134,  -134,  -134,   -33,  -134,  -134,
-      93,     0,   -58,   -37,  -134,  -134,  -134,   -73,  -134,  -134,
-     -54,   -32,  -134,   -81,  -134,  -133,  -134,  -134,    29,   -50,
-    -134,  -134,  -134,  -134,   -20,  -134,  -134,   110,  -134,  -134,
-      49,    96,    80,  -134,  -134,  -134
+    -135,  -135,   187,  -135,  -135,  -135,  -135,   -50,  -135,  -135,
+      98,     0,   -59,   -37,  -135,  -135,  -135,   -77,  -135,  -135,
+     -54,   -30,  -135,   -90,  -135,  -134,  -135,  -135,    24,   -58,
+    -135,  -135,  -135,  -135,   -18,  -135,  -135,   109,  -135,  -135,
+      44,    87,    84,   148,  -135,   102,  -135,  -135,  -135
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -727,116 +704,118 @@ static const yytype_int16 yypgoto[] =
 #define YYTABLE_NINF -109
 static const yytype_int16 yytable[] =
 {
-      82,    70,   104,    37,   159,    68,    57,   130,   142,    88,
-     162,    52,    56,    84,    49,    92,     4,    93,    10,    50,
-      51,   132,    79,   134,    71,    53,    53,   143,    20,   104,
-      85,   104,    73,   120,   175,    91,    81,    29,   124,    97,
-      58,    33,   -93,   131,    83,    70,   147,   101,    95,    61,
-     163,   150,    59,   102,    63,    80,   149,    63,   -93,    62,
-      63,   136,    96,   100,    47,    48,   104,   101,   166,    98,
-      99,    60,    80,   102,    63,   137,   150,   150,   103,   124,
-     131,    53,   167,    61,   101,   147,    89,    70,   117,   163,
-     102,    63,   111,    62,    63,   149,    63,   124,    74,   164,
-     165,    90,     7,     8,     9,    10,    11,    12,    13,   124,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-     118,    26,    27,    28,    29,    30,   119,   103,    33,   133,
-     138,   139,    98,    92,   -22,   141,   140,   154,    34,   146,
-     142,   -22,  -107,   153,   -22,   -22,   112,   156,   155,   -22,
-       7,     8,     9,    10,    11,    12,    13,   157,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,   161,    26,
-      27,    28,    29,    30,   170,   171,    33,   172,   173,   176,
-     177,     5,   -22,   121,   169,   135,    34,   113,   160,   -22,
-    -108,     0,   -22,   -22,   123,     0,   129,   -22,     7,     8,
-       9,    10,    11,    12,    13,     0,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,     0,    26,    27,    28,
-      29,    30,     0,     0,    33,     0,     0,     0,     0,   -86,
-       0,   158,     0,     0,    34,     7,     8,     9,    10,    11,
-      12,    13,   -86,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,     0,    26,    27,    28,    29,    30,     0,
-       0,    33,     0,     0,     0,     0,   -86,     0,   174,     0,
-       0,    34,     7,     8,     9,    10,    11,    12,    13,   -86,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-       0,    26,    27,    28,    29,    30,     0,     0,    33,     0,
-       0,     0,     0,   -86,     0,     0,     0,     0,    34,     0,
-       0,     0,     0,     6,     0,     0,   -86,     7,     8,     9,
-      10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    31,    32,    33,     0,     0,     0,     0,     0,   -22,
-       0,     0,     0,    34,     0,     0,   -22,     0,     0,   -22,
-     -22,     7,     8,     9,    10,    11,    12,    13,     0,    15,
+      86,    71,   111,    37,   172,    10,    83,    69,    58,    49,
+      92,   152,    88,   169,    73,    20,    96,   140,    97,   142,
+       4,   144,   137,    50,    29,    52,   104,    61,    33,    50,
+     153,    53,   111,    89,   111,    77,   -93,   127,    95,    85,
+     157,   131,    59,   185,   173,    54,    57,    99,    62,    71,
+     159,    64,   -93,   141,   160,    62,    84,   108,    63,    64,
+      54,   100,    60,   109,    64,    63,    64,   146,    73,   107,
+      54,   176,   111,   108,    47,    48,    84,   105,   106,   109,
+      64,   147,   160,   160,   110,   177,   141,    87,   131,   157,
+     108,   102,   103,   173,    71,    93,   109,    64,   101,   159,
+      64,   174,   175,    94,   118,   124,   131,    78,   136,   125,
+     126,     7,     8,     9,    10,    11,    12,    13,   131,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,   110,
+      26,    27,    28,    29,    30,   143,   148,    33,   105,   149,
+      96,   151,   152,   -22,   150,   156,   165,    34,   163,   164,
+     -22,  -107,   166,   -22,   -22,   119,   167,   171,   -22,     7,
+       8,     9,    10,    11,    12,    13,   180,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,   181,    26,    27,
+      28,    29,    30,   182,   183,    33,   186,   187,     5,   179,
+     120,   -22,   128,   170,   139,    34,   145,    72,   -22,  -108,
+       0,   -22,   -22,   130,     0,   138,   -22,     7,     8,     9,
+      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
+      30,     0,     0,    33,     0,     0,     0,     0,   -86,     0,
+     168,     0,     0,    34,     7,     8,     9,    10,    11,    12,
+      13,   -86,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,     0,    26,    27,    28,    29,    30,     0,     0,
+      33,     0,     0,     0,     0,   -86,     0,   184,     0,     0,
+      34,     7,     8,     9,    10,    11,    12,    13,   -86,    15,
       16,    17,    18,    19,    20,    21,    22,    23,    24,     0,
       26,    27,    28,    29,    30,     0,     0,    33,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,    34,     0,     0,
-       0,     0,     0,     0,   115,   116,     7,     8,     9,    10,
-      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
-       0,     0,    33,     0,     0,     0,     0,     0,   147,     0,
-       0,     0,   148,     0,     0,     0,     0,     0,   149,    63,
+       0,     0,   -86,     0,     0,     0,     0,    34,     0,     0,
+       0,     0,     6,     0,     0,   -86,     7,     8,     9,    10,
+      11,    12,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,    25,    26,    27,    28,    29,    30,
+      31,    32,    33,     0,     0,     0,     0,     0,   -22,     0,
+       0,     0,    34,     0,     0,   -22,     0,     0,   -22,   -22,
        7,     8,     9,    10,    11,    12,    13,     0,    15,    16,
       17,    18,    19,    20,    21,    22,    23,    24,     0,    26,
       27,    28,    29,    30,     0,     0,    33,     0,     0,     0,
-       0,   168,     0,     0,     0,     0,    34,     7,     8,     9,
-      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
-      30,     0,     0,    33,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,    34
+       0,     0,     0,     0,     0,     0,    34,     0,     0,     0,
+       0,     0,     0,   122,   123,     7,     8,     9,    10,    11,
+      12,    13,     0,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,     0,    26,    27,    28,    29,    30,     0,
+       0,    33,     0,     0,     0,     0,     0,   157,     0,     0,
+       0,   158,     0,     0,     0,     0,     0,   159,    64,     7,
+       8,     9,    10,    11,    12,    13,     0,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,     0,    26,    27,
+      28,    29,    30,     0,     0,    33,     0,     0,     0,     0,
+     178,     0,     0,     0,     0,    34,     7,     8,     9,    10,
+      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
+       0,     0,    33,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    34
 };
 
 static const yytype_int16 yycheck[] =
 {
-      58,    38,    75,     3,   137,    37,    26,     1,    31,    63,
-       1,    37,    37,     1,    32,    30,     0,    32,     8,    37,
-      23,   102,    55,   104,    32,    51,    51,    50,    18,   102,
-      62,   104,    52,    87,   167,    67,    56,    27,    96,    72,
-      47,    31,    33,    37,    37,    82,    37,    41,    33,    37,
-      41,   124,    47,    47,    48,    55,    47,    48,    49,    47,
-      48,    33,    47,    37,    44,    45,   139,    41,    33,    44,
-      45,    44,    72,    47,    48,    47,   149,   150,    52,   137,
-      37,    51,    47,    37,    41,    37,    44,   124,    49,    41,
-      47,    48,    45,    47,    48,    47,    48,   155,     1,   149,
-     150,    46,     5,     6,     7,     8,     9,    10,    11,   167,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      49,    24,    25,    26,    27,    28,    49,    52,    31,    34,
-      44,    46,    44,    30,    37,    44,    49,    36,    41,    49,
-      31,    44,    45,    49,    47,    48,     1,    49,    46,    52,
-       5,     6,     7,     8,     9,    10,    11,    49,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    34,    24,
-      25,    26,    27,    28,    49,    49,    31,    49,    49,    49,
-      49,     1,    37,    90,   155,   105,    41,    77,   139,    44,
-      45,    -1,    47,    48,     1,    -1,   100,    52,     5,     6,
-       7,     8,     9,    10,    11,    -1,    13,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    -1,    24,    25,    26,
-      27,    28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    36,
-      -1,     1,    -1,    -1,    41,     5,     6,     7,     8,     9,
-      10,    11,    49,    13,    14,    15,    16,    17,    18,    19,
-      20,    21,    22,    -1,    24,    25,    26,    27,    28,    -1,
-      -1,    31,    -1,    -1,    -1,    -1,    36,    -1,     1,    -1,
-      -1,    41,     5,     6,     7,     8,     9,    10,    11,    49,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      -1,    24,    25,    26,    27,    28,    -1,    -1,    31,    -1,
-      -1,    -1,    -1,    36,    -1,    -1,    -1,    -1,    41,    -1,
-      -1,    -1,    -1,     1,    -1,    -1,    49,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,    31,    -1,    -1,    -1,    -1,    -1,    37,
-      -1,    -1,    -1,    41,    -1,    -1,    44,    -1,    -1,    47,
-      48,     5,     6,     7,     8,     9,    10,    11,    -1,    13,
+      59,    38,    79,     3,     1,     8,    56,    37,    26,    37,
+      64,    31,     1,   147,    37,    18,    30,     1,    32,   109,
+       0,   111,    45,    51,    27,    23,    76,    44,    31,    51,
+      50,    37,   109,    63,   111,    53,    33,    91,    68,    57,
+      37,   100,    47,   177,    41,    51,    37,    33,    37,    86,
+      47,    48,    49,    37,   131,    37,    56,    41,    47,    48,
+      51,    47,    47,    47,    48,    47,    48,    33,    37,    37,
+      51,    33,   149,    41,    44,    45,    76,    44,    45,    47,
+      48,    47,   159,   160,    52,    47,    37,    37,   147,    37,
+      41,    45,    46,    41,   131,    44,    47,    48,    50,    47,
+      48,   159,   160,    46,    45,    49,   165,     1,    34,    49,
+      49,     5,     6,     7,     8,     9,    10,    11,   177,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    52,
+      24,    25,    26,    27,    28,    34,    44,    31,    44,    46,
+      30,    44,    31,    37,    49,    49,    46,    41,    49,    36,
+      44,    45,    49,    47,    48,     1,    49,    34,    52,     5,
+       6,     7,     8,     9,    10,    11,    49,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    49,    24,    25,
+      26,    27,    28,    49,    49,    31,    49,    49,     1,   165,
+      81,    37,    94,   149,   107,    41,   112,    49,    44,    45,
+      -1,    47,    48,     1,    -1,   103,    52,     5,     6,     7,
+       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
+      28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    36,    -1,
+       1,    -1,    -1,    41,     5,     6,     7,     8,     9,    10,
+      11,    49,    13,    14,    15,    16,    17,    18,    19,    20,
+      21,    22,    -1,    24,    25,    26,    27,    28,    -1,    -1,
+      31,    -1,    -1,    -1,    -1,    36,    -1,     1,    -1,    -1,
+      41,     5,     6,     7,     8,     9,    10,    11,    49,    13,
       14,    15,    16,    17,    18,    19,    20,    21,    22,    -1,
       24,    25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,
-      -1,    -1,    -1,    -1,    -1,    -1,    -1,    41,    -1,    -1,
-      -1,    -1,    -1,    -1,    48,    49,     5,     6,     7,     8,
-       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
-      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,
-      -1,    -1,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,
+      -1,    -1,    36,    -1,    -1,    -1,    -1,    41,    -1,    -1,
+      -1,    -1,     1,    -1,    -1,    49,     5,     6,     7,     8,
+       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
+      29,    30,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,
+      -1,    -1,    41,    -1,    -1,    44,    -1,    -1,    47,    48,
        5,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    -1,    24,
       25,    26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,
-      -1,    36,    -1,    -1,    -1,    -1,    41,     5,     6,     7,
-       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
-      28,    -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    41
+      -1,    -1,    -1,    -1,    -1,    -1,    41,    -1,    -1,    -1,
+      -1,    -1,    -1,    48,    49,     5,     6,     7,     8,     9,
+      10,    11,    -1,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    -1,    24,    25,    26,    27,    28,    -1,
+      -1,    31,    -1,    -1,    -1,    -1,    -1,    37,    -1,    -1,
+      -1,    41,    -1,    -1,    -1,    -1,    -1,    47,    48,     5,
+       6,     7,     8,     9,    10,    11,    -1,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    -1,    24,    25,
+      26,    27,    28,    -1,    -1,    31,    -1,    -1,    -1,    -1,
+      36,    -1,    -1,    -1,    -1,    41,     5,     6,     7,     8,
+       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
+      -1,    -1,    31,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    41
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -847,15 +826,16 @@ static const yytype_uint8 yystos[] =
        8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
       18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
       28,    29,    30,    31,    41,    57,    60,    64,    65,    66,
-      67,    68,    69,    73,    84,    96,    98,    44,    45,    32,
-      37,    23,    37,    51,    87,    59,    37,    87,    47,    47,
-      44,    37,    47,    48,    61,    62,    63,    70,    74,    75,
-      66,    32,    58,    87,     1,    64,    88,    89,    90,    60,
-      64,    87,    65,    37,     1,    74,    71,    72,    73,    44,
-      46,    74,    30,    32,    97,    33,    47,    60,    44,    45,
-      37,    41,    47,    52,    70,    76,    77,    91,    92,    93,
-      94,    45,     1,    90,    74,    48,    49,    49,    49,    49,
-      73,    63,    95,     1,    65,    78,    79,    80,    81,    94,
+      67,    68,    69,    73,    84,    99,   101,    44,    45,    37,
+      51,    96,    23,    37,    51,    87,    59,    37,    87,    47,
+      47,    44,    37,    47,    48,    61,    62,    63,    70,    74,
+      75,    66,    96,    37,    97,    98,    58,    87,     1,    64,
+      88,    89,    90,    60,    64,    87,    65,    37,     1,    74,
+      71,    72,    73,    44,    46,    74,    30,    32,   100,    33,
+      47,    50,    45,    46,    60,    44,    45,    37,    41,    47,
+      52,    70,    76,    77,    91,    92,    93,    94,    45,     1,
+      90,    74,    48,    49,    49,    49,    49,    73,    63,    95,
+       1,    65,    78,    79,    80,    81,    34,    45,    98,    94,
        1,    37,    76,    34,    76,    95,    33,    47,    44,    46,
       49,    44,    31,    50,    85,    86,    49,    37,    41,    47,
       70,    82,    83,    49,    36,    46,    49,    49,     1,    78,
@@ -1045,17 +1025,20 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
 #else
 static void
-yy_stack_print (bottom, top)
-    yytype_int16 *bottom;
-    yytype_int16 *top;
+yy_stack_print (yybottom, yytop)
+    yytype_int16 *yybottom;
+    yytype_int16 *yytop;
 #endif
 {
   YYFPRINTF (stderr, "Stack now");
-  for (; bottom <= top; ++bottom)
-    YYFPRINTF (stderr, " %d", *bottom);
+  for (; yybottom <= yytop; yybottom++)
+    {
+      int yybot = *yybottom;
+      YYFPRINTF (stderr, " %d", yybot);
+    }
   YYFPRINTF (stderr, "\n");
 }
 
@@ -1089,11 +1072,11 @@ yy_reduce_print (yyvsp, yyrule)
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
-      fprintf (stderr, "   $%d = ", yyi + 1);
+      YYFPRINTF (stderr, "   $%d = ", yyi + 1);
       yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
 		       &(yyvsp[(yyi + 1) - (yynrhs)])
 		       		       );
-      fprintf (stderr, "\n");
+      YYFPRINTF (stderr, "\n");
     }
 }
 
@@ -1373,10 +1356,8 @@ yydestruct (yymsg, yytype, yyvaluep)
 	break;
     }
 }
-
 
 /* Prevent warnings from -Wmissing-prototypes.  */
-
 #ifdef YYPARSE_PARAM
 #if defined __STDC__ || defined __cplusplus
 int yyparse (void *YYPARSE_PARAM);
@@ -1392,11 +1373,10 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 
 
-
-/* The look-ahead symbol.  */
+/* The lookahead symbol.  */
 int yychar;
 
-/* The semantic value of the look-ahead symbol.  */
+/* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
 
 /* Number of syntax errors so far.  */
@@ -1404,9 +1384,9 @@ int yynerrs;
 
 
 
-/*----------.
-| yyparse.  |
-`----------*/
+/*-------------------------.
+| yyparse or yypush_parse.  |
+`-------------------------*/
 
 #ifdef YYPARSE_PARAM
 #if (defined __STDC__ || defined __C99__FUNC__ \
@@ -1430,66 +1410,68 @@ yyparse ()
 #endif
 #endif
 {
-  
-  int yystate;
-  int yyn;
-  int yyresult;
-  /* Number of tokens to shift before error messages enabled.  */
-  int yyerrstatus;
-  /* Look-ahead token as an internal (translated) token number.  */
-  int yytoken = 0;
-#if YYERROR_VERBOSE
-  /* Buffer for error messages, and its allocated size.  */
-  char yymsgbuf[128];
-  char *yymsg = yymsgbuf;
-  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
 
-  /* Three stacks and their tools:
-     `yyss': related to states,
-     `yyvs': related to semantic values,
-     `yyls': related to locations.
 
-     Refer to the stacks thru separate pointers, to allow yyoverflow
-     to reallocate them elsewhere.  */
+    int yystate;
+    /* Number of tokens to shift before error messages enabled.  */
+    int yyerrstatus;
 
-  /* The state stack.  */
-  yytype_int16 yyssa[YYINITDEPTH];
-  yytype_int16 *yyss = yyssa;
-  yytype_int16 *yyssp;
+    /* The stacks and their tools:
+       `yyss': related to states.
+       `yyvs': related to semantic values.
 
-  /* The semantic value stack.  */
-  YYSTYPE yyvsa[YYINITDEPTH];
-  YYSTYPE *yyvs = yyvsa;
-  YYSTYPE *yyvsp;
+       Refer to the stacks thru separate pointers, to allow yyoverflow
+       to reallocate them elsewhere.  */
 
+    /* The state stack.  */
+    yytype_int16 yyssa[YYINITDEPTH];
+    yytype_int16 *yyss;
+    yytype_int16 *yyssp;
 
+    /* The semantic value stack.  */
+    YYSTYPE yyvsa[YYINITDEPTH];
+    YYSTYPE *yyvs;
+    YYSTYPE *yyvsp;
 
-#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
-
-  YYSIZE_T yystacksize = YYINITDEPTH;
+    YYSIZE_T yystacksize;
 
+  int yyn;
+  int yyresult;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yytoken;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
 
+#if YYERROR_VERBOSE
+  /* Buffer for error messages, and its allocated size.  */
+  char yymsgbuf[128];
+  char *yymsg = yymsgbuf;
+  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N)   (yyvsp -= (N), yyssp -= (N))
 
   /* The number of symbols on the RHS of the reduced rule.
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
+  yytoken = 0;
+  yyss = yyssa;
+  yyvs = yyvsa;
+  yystacksize = YYINITDEPTH;
+
   YYDPRINTF ((stderr, "Starting parse\n"));
 
   yystate = 0;
   yyerrstatus = 0;
   yynerrs = 0;
-  yychar = YYEMPTY;		/* Cause a token to be read.  */
+  yychar = YYEMPTY; /* Cause a token to be read.  */
 
   /* Initialize stack pointers.
      Waste one element of value and location stack
      so that they stay on the same level as the state stack.
      The wasted elements are never initialized.  */
-
   yyssp = yyss;
   yyvsp = yyvs;
 
@@ -1519,7 +1501,6 @@ yyparse ()
 	YYSTYPE *yyvs1 = yyvs;
 	yytype_int16 *yyss1 = yyss;
 
-
 	/* Each stack pointer address is followed by the size of the
 	   data in use in that stack, in bytes.  This used to be a
 	   conditional around just the two extra args, but that might
@@ -1527,7 +1508,6 @@ yyparse ()
 	yyoverflow (YY_("memory exhausted"),
 		    &yyss1, yysize * sizeof (*yyssp),
 		    &yyvs1, yysize * sizeof (*yyvsp),
-
 		    &yystacksize);
 
 	yyss = yyss1;
@@ -1550,9 +1530,8 @@ yyparse ()
 	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 	if (! yyptr)
 	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss);
-	YYSTACK_RELOCATE (yyvs);
-
+	YYSTACK_RELOCATE (yyss_alloc, yyss);
+	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
 	if (yyss1 != yyssa)
 	  YYSTACK_FREE (yyss1);
@@ -1563,7 +1542,6 @@ yyparse ()
       yyssp = yyss + yysize - 1;
       yyvsp = yyvs + yysize - 1;
 
-
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
 		  (unsigned long int) yystacksize));
 
@@ -1573,6 +1551,9 @@ yyparse ()
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
 
+  if (yystate == YYFINAL)
+    YYACCEPT;
+
   goto yybackup;
 
 /*-----------.
@@ -1581,16 +1562,16 @@ yyparse ()
 yybackup:
 
   /* Do appropriate processing given the current state.  Read a
-     look-ahead token if we need one and don't already have one.  */
+     lookahead token if we need one and don't already have one.  */
 
-  /* First try to decide what to do without reference to look-ahead token.  */
+  /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
   if (yyn == YYPACT_NINF)
     goto yydefault;
 
-  /* Not known => get a look-ahead token if don't already have one.  */
+  /* Not known => get a lookahead token if don't already have one.  */
 
-  /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol.  */
+  /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol.  */
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
@@ -1622,20 +1603,16 @@ yybackup:
       goto yyreduce;
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   /* Count tokens shifted since error; after three, turn off error
      status.  */
   if (yyerrstatus)
     yyerrstatus--;
 
-  /* Shift the look-ahead token.  */
+  /* Shift the lookahead token.  */
   YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
 
-  /* Discard the shifted token unless it is eof.  */
-  if (yychar != YYEOF)
-    yychar = YYEMPTY;
+  /* Discard the shifted token.  */
+  yychar = YYEMPTY;
 
   yystate = yyn;
   *++yyvsp = yylval;
@@ -1675,47 +1652,65 @@ yyreduce:
   switch (yyn)
     {
         case 4:
-#line 108 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 109 "scripts/genksyms/parse.y"
     { is_typedef = 0; is_extern = 0; current_name = NULL; decl_spec = NULL; ;}
     break;
 
   case 5:
-#line 110 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 111 "scripts/genksyms/parse.y"
     { free_list(*(yyvsp[(2) - (2)]), NULL); *(yyvsp[(2) - (2)]) = NULL; ;}
     break;
 
   case 6:
-#line 114 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 115 "scripts/genksyms/parse.y"
     { is_typedef = 1; ;}
     break;
 
   case 7:
-#line 115 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 116 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 8:
-#line 116 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 117 "scripts/genksyms/parse.y"
     { is_typedef = 1; ;}
     break;
 
   case 9:
-#line 117 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 118 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 14:
-#line 122 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 123 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 15:
-#line 123 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 124 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 16:
-#line 128 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 129 "scripts/genksyms/parse.y"
     { if (current_name) {
 		    struct string_list *decl = (*(yyvsp[(3) - (3)]))->next;
 		    (*(yyvsp[(3) - (3)]))->next = NULL;
@@ -1729,12 +1724,16 @@ yyreduce:
     break;
 
   case 17:
-#line 141 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 142 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 19:
-#line 147 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 148 "scripts/genksyms/parse.y"
     { struct string_list *decl = *(yyvsp[(1) - (1)]);
 		  *(yyvsp[(1) - (1)]) = NULL;
 		  add_symbol(current_name,
@@ -1745,7 +1744,9 @@ yyreduce:
     break;
 
   case 20:
-#line 155 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 156 "scripts/genksyms/parse.y"
     { struct string_list *decl = *(yyvsp[(3) - (3)]);
 		  *(yyvsp[(3) - (3)]) = NULL;
 		  free_list(*(yyvsp[(2) - (3)]), NULL);
@@ -1758,27 +1759,37 @@ yyreduce:
     break;
 
   case 21:
-#line 168 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 169 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]) ? (yyvsp[(4) - (4)]) : (yyvsp[(3) - (4)]) ? (yyvsp[(3) - (4)]) : (yyvsp[(2) - (4)]) ? (yyvsp[(2) - (4)]) : (yyvsp[(1) - (4)]); ;}
     break;
 
   case 22:
-#line 173 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 174 "scripts/genksyms/parse.y"
     { decl_spec = NULL; ;}
     break;
 
   case 24:
-#line 178 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 179 "scripts/genksyms/parse.y"
     { decl_spec = *(yyvsp[(1) - (1)]); ;}
     break;
 
   case 25:
-#line 179 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 180 "scripts/genksyms/parse.y"
     { decl_spec = *(yyvsp[(2) - (2)]); ;}
     break;
 
   case 26:
-#line 184 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 185 "scripts/genksyms/parse.y"
     { /* Version 2 checksumming ignores storage class, as that
 		     is really irrelevant to the linkage.  */
 		  remove_node((yyvsp[(1) - (1)]));
@@ -1787,32 +1798,44 @@ yyreduce:
     break;
 
   case 31:
-#line 196 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 197 "scripts/genksyms/parse.y"
     { is_extern = 1; (yyval) = (yyvsp[(1) - (1)]); ;}
     break;
 
   case 32:
-#line 197 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 198 "scripts/genksyms/parse.y"
     { is_extern = 0; (yyval) = (yyvsp[(1) - (1)]); ;}
     break;
 
   case 37:
-#line 209 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 210 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_STRUCT; (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 38:
-#line 211 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 212 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_UNION; (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 39:
-#line 213 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 214 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (2)])); (*(yyvsp[(2) - (2)]))->tag = SYM_ENUM; (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 40:
-#line 217 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 218 "scripts/genksyms/parse.y"
     { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
 		  r = copy_node(i); r->tag = SYM_STRUCT;
 		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
@@ -1822,7 +1845,9 @@ yyreduce:
     break;
 
   case 41:
-#line 224 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 225 "scripts/genksyms/parse.y"
     { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
 		  r = copy_node(i); r->tag = SYM_UNION;
 		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
@@ -1832,7 +1857,9 @@ yyreduce:
     break;
 
   case 42:
-#line 231 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 232 "scripts/genksyms/parse.y"
     { struct string_list *s = *(yyvsp[(3) - (3)]), *i = *(yyvsp[(2) - (3)]), *r;
 		  r = copy_node(i); r->tag = SYM_ENUM;
 		  r->next = (*(yyvsp[(1) - (3)]))->next; *(yyvsp[(3) - (3)]) = r; (*(yyvsp[(1) - (3)]))->next = NULL;
@@ -1842,42 +1869,58 @@ yyreduce:
     break;
 
   case 43:
-#line 239 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
+
+/* Line 1455 of yacc.c  */
+#line 242 "scripts/genksyms/parse.y"
+    { add_symbol(NULL, SYM_ENUM, NULL, 0); (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 44:
-#line 240 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 244 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 45:
-#line 241 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 245 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 56:
-#line 255 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 259 "scripts/genksyms/parse.y"
     { (*(yyvsp[(1) - (1)]))->tag = SYM_TYPEDEF; (yyval) = (yyvsp[(1) - (1)]); ;}
     break;
 
   case 57:
-#line 260 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 264 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 58:
-#line 264 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 268 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 61:
-#line 270 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 274 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 65:
-#line 276 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 280 "scripts/genksyms/parse.y"
     { /* restrict has no effect in prototypes so ignore it */
 		  remove_node((yyvsp[(1) - (1)]));
 		  (yyval) = (yyvsp[(1) - (1)]);
@@ -1885,12 +1928,16 @@ yyreduce:
     break;
 
   case 66:
-#line 283 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 287 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 68:
-#line 289 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 293 "scripts/genksyms/parse.y"
     { if (current_name != NULL) {
 		    error_with_pos("unexpected second declaration name");
 		    YYERROR;
@@ -1902,97 +1949,135 @@ yyreduce:
     break;
 
   case 69:
-#line 298 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 302 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 70:
-#line 300 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 304 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 71:
-#line 302 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 306 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 72:
-#line 304 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 308 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 73:
-#line 306 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 310 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 74:
-#line 312 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 316 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 78:
-#line 320 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 324 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 79:
-#line 322 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 326 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 80:
-#line 324 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 328 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 81:
-#line 326 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 330 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 82:
-#line 328 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 332 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 83:
-#line 332 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 336 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 85:
-#line 334 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 338 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 86:
-#line 338 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 342 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 89:
-#line 345 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 349 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 90:
-#line 350 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 354 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 91:
-#line 355 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 359 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 93:
-#line 360 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 364 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 94:
-#line 362 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 366 "scripts/genksyms/parse.y"
     { /* For version 2 checksums, we don't want to remember
 		     private parameter names.  */
 		  remove_node((yyvsp[(1) - (1)]));
@@ -2001,39 +2086,53 @@ yyreduce:
     break;
 
   case 95:
-#line 370 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 374 "scripts/genksyms/parse.y"
     { remove_node((yyvsp[(1) - (1)]));
 		  (yyval) = (yyvsp[(1) - (1)]);
 		;}
     break;
 
   case 96:
-#line 374 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 378 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 97:
-#line 376 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 380 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(4) - (4)]); ;}
     break;
 
   case 98:
-#line 378 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 382 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 99:
-#line 380 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 384 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 100:
-#line 382 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 386 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 101:
-#line 387 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 391 "scripts/genksyms/parse.y"
     { struct string_list *decl = *(yyvsp[(2) - (3)]);
 		  *(yyvsp[(2) - (3)]) = NULL;
 		  add_symbol(current_name, SYM_NORMAL, decl, is_extern);
@@ -2042,93 +2141,163 @@ yyreduce:
     break;
 
   case 102:
-#line 395 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 399 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 104:
-#line 402 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 406 "scripts/genksyms/parse.y"
     { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 105:
-#line 406 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 410 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 106:
-#line 407 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 411 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 107:
-#line 411 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 415 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 110:
-#line 417 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 421 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 111:
-#line 422 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 426 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 112:
-#line 424 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 428 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 113:
-#line 428 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 432 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 116:
-#line 434 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 438 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 117:
-#line 438 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 442 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); ;}
     break;
 
   case 118:
-#line 439 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 443 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 120:
-#line 444 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 448 "scripts/genksyms/parse.y"
     { (yyval) = (yyvsp[(2) - (2)]); ;}
     break;
 
   case 121:
-#line 448 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 452 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
   case 123:
-#line 453 "scripts/genksyms/parse.y"
-    { (yyval) = (yyvsp[(2) - (2)]); ;}
+
+/* Line 1455 of yacc.c  */
+#line 457 "scripts/genksyms/parse.y"
+    { (yyval) = (yyvsp[(3) - (3)]); ;}
     break;
 
   case 124:
-#line 457 "scripts/genksyms/parse.y"
+
+/* Line 1455 of yacc.c  */
+#line 458 "scripts/genksyms/parse.y"
+    { (yyval) = (yyvsp[(4) - (4)]); ;}
+    break;
+
+  case 127:
+
+/* Line 1455 of yacc.c  */
+#line 467 "scripts/genksyms/parse.y"
+    {
+			const char *name = strdup((*(yyvsp[(1) - (1)]))->string);
+			add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+		;}
+    break;
+
+  case 128:
+
+/* Line 1455 of yacc.c  */
+#line 472 "scripts/genksyms/parse.y"
+    {
+			const char *name = strdup((*(yyvsp[(1) - (3)]))->string);
+			struct string_list *expr = copy_list_range(*(yyvsp[(3) - (3)]), *(yyvsp[(2) - (3)]));
+			add_symbol(name, SYM_ENUM_CONST, expr, 0);
+		;}
+    break;
+
+  case 129:
+
+/* Line 1455 of yacc.c  */
+#line 479 "scripts/genksyms/parse.y"
+    { (yyval) = (yyvsp[(2) - (2)]); ;}
+    break;
+
+  case 130:
+
+/* Line 1455 of yacc.c  */
+#line 483 "scripts/genksyms/parse.y"
     { (yyval) = NULL; ;}
     break;
 
-  case 126:
-#line 463 "scripts/genksyms/parse.y"
+  case 132:
+
+/* Line 1455 of yacc.c  */
+#line 489 "scripts/genksyms/parse.y"
     { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); ;}
     break;
 
 
-/* Line 1267 of yacc.c.  */
-#line 2132 "scripts/genksyms/parse.c"
+
+/* Line 1455 of yacc.c  */
+#line 2301 "scripts/genksyms/parse.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2139,7 +2308,6 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-
   /* Now `shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
@@ -2204,7 +2372,7 @@ yyerrlab:
 
   if (yyerrstatus == 3)
     {
-      /* If just tried and failed to reuse look-ahead token after an
+      /* If just tried and failed to reuse lookahead token after an
 	 error, discard it.  */
 
       if (yychar <= YYEOF)
@@ -2221,7 +2389,7 @@ yyerrlab:
 	}
     }
 
-  /* Else will try to reuse look-ahead token after shifting the error
+  /* Else will try to reuse lookahead token after shifting the error
      token.  */
   goto yyerrlab1;
 
@@ -2278,9 +2446,6 @@ yyerrlab1:
       YY_STACK_PRINT (yyss, yyssp);
     }
 
-  if (yyn == YYFINAL)
-    YYACCEPT;
-
   *++yyvsp = yylval;
 
 
@@ -2305,7 +2470,7 @@ yyabortlab:
   yyresult = 1;
   goto yyreturn;
 
-#ifndef yyoverflow
+#if !defined(yyoverflow) || YYERROR_VERBOSE
 /*-------------------------------------------------.
 | yyexhaustedlab -- memory exhaustion comes here.  |
 `-------------------------------------------------*/
@@ -2316,7 +2481,7 @@ yyexhaustedlab:
 #endif
 
 yyreturn:
-  if (yychar != YYEOF && yychar != YYEMPTY)
+  if (yychar != YYEMPTY)
      yydestruct ("Cleanup: discarding lookahead",
 		 yytoken, &yylval);
   /* Do not reclaim the symbols of the rule which action triggered
@@ -2342,7 +2507,9 @@ yyreturn:
 }
 
 
-#line 467 "scripts/genksyms/parse.y"
+
+/* Line 1675 of yacc.c  */
+#line 493 "scripts/genksyms/parse.y"
 
 
 static void
diff --git a/scripts/genksyms/parse.h_shipped b/scripts/genksyms/parse.h_shipped
index c4eeec6..5175236 100644
--- a/scripts/genksyms/parse.h_shipped
+++ b/scripts/genksyms/parse.h_shipped
@@ -1,24 +1,23 @@
-/* A Bison parser, made by GNU Bison 2.3.  */
 
-/* Skeleton interface for Bison's Yacc-like parsers in C
+/* A Bison parser, made by GNU Bison 2.4.1.  */
 
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+/* Skeleton interface for Bison's Yacc-like parsers in C
+   
+      Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
+   
+   This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-
+   
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor,
-   Boston, MA 02110-1301, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* As a special exception, you may create a larger work that contains
    part or all of the Bison parser skeleton and distribute that work
@@ -29,10 +28,11 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-
+   
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
+
 /* Tokens.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
@@ -82,58 +82,16 @@
      FILENAME = 298
    };
 #endif
-/* Tokens.  */
-#define ASM_KEYW 258
-#define ATTRIBUTE_KEYW 259
-#define AUTO_KEYW 260
-#define BOOL_KEYW 261
-#define CHAR_KEYW 262
-#define CONST_KEYW 263
-#define DOUBLE_KEYW 264
-#define ENUM_KEYW 265
-#define EXTERN_KEYW 266
-#define EXTENSION_KEYW 267
-#define FLOAT_KEYW 268
-#define INLINE_KEYW 269
-#define INT_KEYW 270
-#define LONG_KEYW 271
-#define REGISTER_KEYW 272
-#define RESTRICT_KEYW 273
-#define SHORT_KEYW 274
-#define SIGNED_KEYW 275
-#define STATIC_KEYW 276
-#define STRUCT_KEYW 277
-#define TYPEDEF_KEYW 278
-#define UNION_KEYW 279
-#define UNSIGNED_KEYW 280
-#define VOID_KEYW 281
-#define VOLATILE_KEYW 282
-#define TYPEOF_KEYW 283
-#define EXPORT_SYMBOL_KEYW 284
-#define ASM_PHRASE 285
-#define ATTRIBUTE_PHRASE 286
-#define BRACE_PHRASE 287
-#define BRACKET_PHRASE 288
-#define EXPRESSION_PHRASE 289
-#define CHAR 290
-#define DOTS 291
-#define IDENT 292
-#define INT 293
-#define REAL 294
-#define STRING 295
-#define TYPE 296
-#define OTHER 297
-#define FILENAME 298
-
 
 
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef int YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
 #endif
 
 extern YYSTYPE yylval;
 
+
diff --git a/scripts/genksyms/parse.y b/scripts/genksyms/parse.y
index 09a265c..ba5c242 100644
--- a/scripts/genksyms/parse.y
+++ b/scripts/genksyms/parse.y
@@ -25,6 +25,7 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <string.h>
 #include "genksyms.h"
 
 static int is_typedef;
@@ -227,16 +228,19 @@ type_specifier:
 		  add_symbol(i->string, SYM_UNION, s, is_extern);
 		  $$ = $3;
 		}
-	| ENUM_KEYW IDENT BRACE_PHRASE
+	| ENUM_KEYW IDENT enum_body
 		{ struct string_list *s = *$3, *i = *$2, *r;
 		  r = copy_node(i); r->tag = SYM_ENUM;
 		  r->next = (*$1)->next; *$3 = r; (*$1)->next = NULL;
 		  add_symbol(i->string, SYM_ENUM, s, is_extern);
 		  $$ = $3;
 		}
-
-	/* Anonymous s/u/e definitions.  Nothing needs doing.  */
-	| ENUM_KEYW BRACE_PHRASE			{ $$ = $2; }
+	/*
+	 * Anonymous enum definition. Tell add_symbol() to restart its counter.
+	 */
+	| ENUM_KEYW enum_body
+		{ add_symbol(NULL, SYM_ENUM, NULL, 0); $$ = $2; }
+	/* Anonymous s/u definitions.  Nothing needs doing.  */
 	| STRUCT_KEYW class_body			{ $$ = $2; }
 	| UNION_KEYW class_body				{ $$ = $2; }
 	;
@@ -449,6 +453,28 @@ attribute_opt:
 	| attribute_opt ATTRIBUTE_PHRASE
 	;
 
+enum_body:
+	'{' enumerator_list '}'				{ $$ = $3; }
+	| '{' enumerator_list ',' '}'			{ $$ = $4; }
+	 ;
+
+enumerator_list:
+	enumerator
+	| enumerator_list ',' enumerator
+
+enumerator:
+	IDENT
+		{
+			const char *name = strdup((*$1)->string);
+			add_symbol(name, SYM_ENUM_CONST, NULL, 0);
+		}
+	| IDENT '=' EXPRESSION_PHRASE
+		{
+			const char *name = strdup((*$1)->string);
+			struct string_list *expr = copy_list_range(*$3, *$2);
+			add_symbol(name, SYM_ENUM_CONST, expr, 0);
+		}
+
 asm_definition:
 	ASM_PHRASE ';'					{ $$ = $2; }
 	;
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 139e0ff..d29a8d7 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -420,6 +420,14 @@ foreach my $file (@ARGV) {
 
 	open(my $patch, "< $file")
 	    or die "$P: Can't open $file: $!\n";
+
+	# We can check arbitrary information before the patch
+	# like the commit message, mail headers, etc...
+	# This allows us to match arbitrary keywords against any part
+	# of a git format-patch generated file (subject tags, etc...)
+
+	my $patch_prefix = "";			#Parsing the intro
+
 	while (<$patch>) {
 	    my $patch_line = $_;
 	    if (m/^\+\+\+\s+(\S+)/) {
@@ -428,13 +436,14 @@ foreach my $file (@ARGV) {
 		$filename =~ s@\n@@;
 		$lastfile = $filename;
 		push(@files, $filename);
+		$patch_prefix = "^[+-].*";	#Now parsing the actual patch
 	    } elsif (m/^\@\@ -(\d+),(\d+)/) {
 		if ($email_git_blame) {
 		    push(@range, "$lastfile:$1:$2");
 		}
 	    } elsif ($keywords) {
 		foreach my $line (keys %keyword_hash) {
-		    if ($patch_line =~ m/^[+-].*$keyword_hash{$line}/x) {
+		    if ($patch_line =~ m/${patch_prefix}$keyword_hash{$line}/x) {
 			push(@keyword_tvi, $line);
 		    }
 		}
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index fd81fc3..a4fe923 100644
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# Copywrite 2005-2009 - Steven Rostedt
+# Copyright 2005-2009 - Steven Rostedt
 # Licensed under the terms of the GNU GPL License version 2
 #
 #  It's simple enough to figure out how this works.
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index e8fba95..cd104af 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1248,6 +1248,19 @@ static int is_function(Elf_Sym *sym)
 		return -1;
 }
 
+static void print_section_list(const char * const list[20])
+{
+	const char *const *s = list;
+
+	while (*s) {
+		fprintf(stderr, "%s", *s);
+		s++;
+		if (*s)
+			fprintf(stderr, ", ");
+	}
+	fprintf(stderr, "\n");
+}
+
 /*
  * Print a warning about a section mismatch.
  * Try to find symbols near it so user can find it.
@@ -1304,7 +1317,6 @@ static void report_sec_mismatch(const char *modname,
 		break;
 	case DATA_TO_ANY_INIT: {
 		prl_to = sec2annotation(tosec);
-		const char *const *s = mismatch->symbol_white_list;
 		fprintf(stderr,
 		"The variable %s references\n"
 		"the %s %s%s%s\n"
@@ -1312,9 +1324,7 @@ static void report_sec_mismatch(const char *modname,
 		"variable with __init* or __refdata (see linux/init.h) "
 		"or name the variable:\n",
 		fromsym, to, prl_to, tosym, to_p);
-		while (*s)
-			fprintf(stderr, "%s, ", *s++);
-		fprintf(stderr, "\n");
+		print_section_list(mismatch->symbol_white_list);
 		free(prl_to);
 		break;
 	}
@@ -1329,7 +1339,6 @@ static void report_sec_mismatch(const char *modname,
 		break;
 	case DATA_TO_ANY_EXIT: {
 		prl_to = sec2annotation(tosec);
-		const char *const *s = mismatch->symbol_white_list;
 		fprintf(stderr,
 		"The variable %s references\n"
 		"the %s %s%s%s\n"
@@ -1337,9 +1346,7 @@ static void report_sec_mismatch(const char *modname,
 		"variable with __exit* (see linux/init.h) or "
 		"name the variable:\n",
 		fromsym, to, prl_to, tosym, to_p);
-		while (*s)
-			fprintf(stderr, "%s, ", *s++);
-		fprintf(stderr, "\n");
+		print_section_list(mismatch->symbol_white_list);
 		free(prl_to);
 		break;
 	}
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index d0b931b..a834b93 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -127,7 +127,8 @@ rm -r $(perf-tar);                                                  \
 $(if $(findstring tar-src,$@),,                                     \
 $(if $(findstring bz2,$@),bzip2,                                    \
 $(if $(findstring gz,$@),gzip,                                      \
-$(error unknown target $@)))                                       \
+$(if $(findstring xz,$@),xz,                                        \
+$(error unknown target $@))))                                       \
 	-f -9 $(perf-tar).tar)
 
 perf-%pkg: FORCE
@@ -142,7 +143,9 @@ help: FORCE
 	@echo '  tar-pkg             - Build the kernel as an uncompressed tarball'
 	@echo '  targz-pkg           - Build the kernel as a gzip compressed tarball'
 	@echo '  tarbz2-pkg          - Build the kernel as a bzip2 compressed tarball'
+	@echo '  tarxz-pkg           - Build the kernel as a xz compressed tarball'
 	@echo '  perf-tar-src-pkg    - Build $(perf-tar).tar source tarball'
 	@echo '  perf-targz-src-pkg  - Build $(perf-tar).tar.gz source tarball'
 	@echo '  perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball'
+	@echo '  perf-tarxz-src-pkg  - Build $(perf-tar).tar.xz source tarball'
 
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index 51b2aa0..83c9c04 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -35,6 +35,10 @@ case "${1}" in
 		compress="bzip2 -c9"
 		file_ext=".bz2"
 		;;
+	tarxz-pkg)
+		compress="xz -c9"
+		file_ext=".xz"
+		;;
 	*)
 		echo "Unknown tarball target \"${1}\" requested, please add it to ${0}." >&2
 		exit 1
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 038b3d1..f9f6f52 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -206,7 +206,8 @@ static uint32_t (*w2)(uint16_t);
 static int
 is_mcounted_section_name(char const *const txtname)
 {
-	return 0 == strcmp(".text",          txtname) ||
+	return 0 == strcmp(".text",           txtname) ||
+		0 == strcmp(".ref.text",      txtname) ||
 		0 == strcmp(".sched.text",    txtname) ||
 		0 == strcmp(".spinlock.text", txtname) ||
 		0 == strcmp(".irqentry.text", txtname) ||
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 1d7963f..4be0dee 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -130,6 +130,7 @@ if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {
 # Acceptable sections to record.
 my %text_sections = (
      ".text" => 1,
+     ".ref.text" => 1,
      ".sched.text" => 1,
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py
index 44423b4..8c81d76 100644
--- a/scripts/rt-tester/rt-tester.py
+++ b/scripts/rt-tester/rt-tester.py
@@ -33,8 +33,6 @@ cmd_opcodes = {
     "lockintnowait" : "6",
     "lockcont"      : "7",
     "unlock"        : "8",
-    "lockbkl"       : "9",
-    "unlockbkl"     : "10",
     "signal"        : "11",
     "resetevent"    : "98",
     "reset"         : "99",
diff --git a/scripts/rt-tester/t2-l1-2rt-sameprio.tst b/scripts/rt-tester/t2-l1-2rt-sameprio.tst
index 8821f27..3710c8b 100644
--- a/scripts/rt-tester/t2-l1-2rt-sameprio.tst
+++ b/scripts/rt-tester/t2-l1-2rt-sameprio.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	0
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t2-l1-pi.tst b/scripts/rt-tester/t2-l1-pi.tst
index cde1f18..b4cc959 100644
--- a/scripts/rt-tester/t2-l1-pi.tst
+++ b/scripts/rt-tester/t2-l1-pi.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	0
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t2-l1-signal.tst b/scripts/rt-tester/t2-l1-signal.tst
index 3ab0bfc..1b57376 100644
--- a/scripts/rt-tester/t2-l1-signal.tst
+++ b/scripts/rt-tester/t2-l1-signal.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	0
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t2-l2-2rt-deadlock.tst b/scripts/rt-tester/t2-l2-2rt-deadlock.tst
index f4b5d5d..68b1062 100644
--- a/scripts/rt-tester/t2-l2-2rt-deadlock.tst
+++ b/scripts/rt-tester/t2-l2-2rt-deadlock.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	0
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t3-l1-pi-1rt.tst b/scripts/rt-tester/t3-l1-pi-1rt.tst
index 63440ca..8e6c8b1 100644
--- a/scripts/rt-tester/t3-l1-pi-1rt.tst
+++ b/scripts/rt-tester/t3-l1-pi-1rt.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t3-l1-pi-2rt.tst b/scripts/rt-tester/t3-l1-pi-2rt.tst
index e5816fe..69c2212 100644
--- a/scripts/rt-tester/t3-l1-pi-2rt.tst
+++ b/scripts/rt-tester/t3-l1-pi-2rt.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t3-l1-pi-3rt.tst b/scripts/rt-tester/t3-l1-pi-3rt.tst
index 718b82b..9b0f1eb 100644
--- a/scripts/rt-tester/t3-l1-pi-3rt.tst
+++ b/scripts/rt-tester/t3-l1-pi-3rt.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t3-l1-pi-signal.tst b/scripts/rt-tester/t3-l1-pi-signal.tst
index c6e2135..39ec74a 100644
--- a/scripts/rt-tester/t3-l1-pi-signal.tst
+++ b/scripts/rt-tester/t3-l1-pi-signal.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t3-l1-pi-steal.tst b/scripts/rt-tester/t3-l1-pi-steal.tst
index f53749d..e03db7e 100644
--- a/scripts/rt-tester/t3-l1-pi-steal.tst
+++ b/scripts/rt-tester/t3-l1-pi-steal.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t3-l2-pi.tst b/scripts/rt-tester/t3-l2-pi.tst
index cdc3e4f..7b59100 100644
--- a/scripts/rt-tester/t3-l2-pi.tst
+++ b/scripts/rt-tester/t3-l2-pi.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t4-l2-pi-deboost.tst b/scripts/rt-tester/t4-l2-pi-deboost.tst
index baa1413..2f0e049 100644
--- a/scripts/rt-tester/t4-l2-pi-deboost.tst
+++ b/scripts/rt-tester/t4-l2-pi-deboost.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst
index e6ec0c8..04f4034 100644
--- a/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst
+++ b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst
index ca64f8b..a48a6ee 100644
--- a/scripts/rt-tester/t5-l4-pi-boost-deboost.tst
+++ b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst
@@ -19,8 +19,6 @@
 # lockintnowait	lock nr (0-7)
 # lockcont	lock nr (0-7)
 # unlock	lock nr (0-7)
-# lockbkl	lock nr (0-7)
-# unlockbkl	lock nr (0-7)
 # signal	thread to signal (0-7)
 # reset		0
 # resetevent	0
@@ -39,9 +37,6 @@
 # blocked	lock nr (0-7)
 # blockedwake	lock nr (0-7)
 # unlocked	lock nr (0-7)
-# lockedbkl	dont care
-# blockedbkl	dont care
-# unlockedbkl	dont care
 # opcodeeq	command opcode or number
 # opcodelt	number
 # opcodegt	number
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c
index 58a12c2..539855f 100644
--- a/scripts/selinux/genheaders/genheaders.c
+++ b/scripts/selinux/genheaders/genheaders.c
@@ -43,6 +43,8 @@ int main(int argc, char *argv[])
 	int i, j, k;
 	int isids_len;
 	FILE *fout;
+	const char *needle = "SOCKET";
+	char *substr;
 
 	progname = argv[0];
 
@@ -88,6 +90,24 @@ int main(int argc, char *argv[])
 		fprintf(fout, "%2d\n", i);
 	}
 	fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1);
+	fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n");
+	fprintf(fout, "{\n");
+	fprintf(fout, "\tbool sock = false;\n\n");
+	fprintf(fout, "\tswitch (kern_tclass) {\n");
+	for (i = 0; secclass_map[i].name; i++) {
+		struct security_class_mapping *map = &secclass_map[i];
+		substr = strstr(map->name, needle);
+		if (substr && strcmp(substr, needle) == 0)
+			fprintf(fout, "\tcase SECCLASS_%s:\n", map->name);
+	}
+	fprintf(fout, "\t\tsock = true;\n");
+	fprintf(fout, "\t\tbreak;\n");
+	fprintf(fout, "\tdefault:\n");
+	fprintf(fout, "\t\tbreak;\n");
+	fprintf(fout, "\t}\n\n");
+	fprintf(fout, "\treturn sock;\n");
+	fprintf(fout, "}\n");
+
 	fprintf(fout, "\n#endif\n");
 	fclose(fout);
 
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index ef8729f..4d40384 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -86,12 +86,16 @@ scm_version()
 
 	# Check for mercurial and a mercurial repo.
 	if test -d .hg && hgid=`hg id 2>/dev/null`; then
-		tag=`printf '%s' "$hgid" | cut -s -d' ' -f2`
-
-		# Do we have an untagged version?
-		if [ -z "$tag" -o "$tag" = tip ]; then
-			id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+		# Do we have an tagged version?  If so, latesttagdistance == 1
+		if [ "`hg log -r . --template '{latesttagdistance}'`" == "1" ]; then
+			id=`hg log -r . --template '{latesttag}'`
 			printf '%s%s' -hg "$id"
+		else
+			tag=`printf '%s' "$hgid" | cut -d' ' -f2`
+			if [ -z "$tag" -o "$tag" = tip ]; then
+				id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
+				printf '%s%s' -hg "$id"
+			fi
 		fi
 
 		# Are there uncommitted changes?
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 92fdc45..bd6185d 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -114,6 +114,11 @@ docscope()
 	cscope -b -f cscope.out
 }
 
+dogtags()
+{
+	all_sources | gtags -f -
+}
+
 exuberant()
 {
 	all_sources | xargs $1 -a                               \
@@ -187,6 +192,10 @@ case "$1" in
 		docscope
 		;;
 
+	"gtags")
+		dogtags
+		;;
+
 	"tags")
 		rm -f tags
 		xtags ctags
diff --git a/scripts/unifdef.c b/scripts/unifdef.c
index 44d3978..7493c0e 100644
--- a/scripts/unifdef.c
+++ b/scripts/unifdef.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>
+ * Copyright (c) 2002 - 2011 Tony Finch <dot@dotat.at>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -24,23 +24,14 @@
  */
 
 /*
+ * unifdef - remove ifdef'ed lines
+ *
  * This code was derived from software contributed to Berkeley by Dave Yost.
  * It was rewritten to support ANSI C by Tony Finch. The original version
  * of unifdef carried the 4-clause BSD copyright licence. None of its code
  * remains in this version (though some of the names remain) so it now
  * carries a more liberal licence.
  *
- * The latest version is available from http://dotat.at/prog/unifdef
- */
-
-static const char * const copyright[] = {
-    "@(#) Copyright (c) 2002 - 2009 Tony Finch <dot@dotat.at>\n",
-    "$dotat: unifdef/unifdef.c,v 1.190 2009/11/27 17:21:26 fanf2 Exp $",
-};
-
-/*
- * unifdef - remove ifdef'ed lines
- *
  *  Wishlist:
  *      provide an option which will append the name of the
  *        appropriate symbol after #else's and #endif's
@@ -48,12 +39,16 @@ static const char * const copyright[] = {
  *        #else's and #endif's to see that they match their
  *        corresponding #ifdef or #ifndef
  *
- *   The first two items above require better buffer handling, which would
- *     also make it possible to handle all "dodgy" directives correctly.
+ *   These require better buffer handling, which would also make
+ *   it possible to handle all "dodgy" directives correctly.
  */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include <ctype.h>
 #include <err.h>
+#include <errno.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -61,6 +56,12 @@ static const char * const copyright[] = {
 #include <string.h>
 #include <unistd.h>
 
+const char copyright[] =
+    "@(#) $Version: unifdef-2.5 $\n"
+    "@(#) $Author: Tony Finch (dot@dotat.at) $\n"
+    "@(#) $URL: http://dotat.at/prog/unifdef $\n"
+;
+
 /* types of input lines: */
 typedef enum {
 	LT_TRUEI,		/* a true #if with ignore flag */
@@ -153,6 +154,11 @@ static char const * const linestate_name[] = {
 #define	EDITSLOP        10
 
 /*
+ * For temporary filenames
+ */
+#define TEMPLATE        "unifdef.XXXXXX"
+
+/*
  * Globals.
  */
 
@@ -165,6 +171,7 @@ static bool             strictlogic;		/* -K: keep ambiguous #ifs */
 static bool             killconsts;		/* -k: eval constant #ifs */
 static bool             lnnum;			/* -n: add #line directives */
 static bool             symlist;		/* -s: output symbol list */
+static bool             symdepth;		/* -S: output symbol depth */
 static bool             text;			/* -t: this is a text file */
 
 static const char      *symname[MAXSYMS];	/* symbol name */
@@ -175,10 +182,18 @@ static int              nsyms;			/* number of symbols */
 static FILE            *input;			/* input file pointer */
 static const char      *filename;		/* input file name */
 static int              linenum;		/* current line number */
+static FILE            *output;			/* output file pointer */
+static const char      *ofilename;		/* output file name */
+static bool             overwriting;		/* output overwrites input */
+static char             tempname[FILENAME_MAX];	/* used when overwriting */
 
 static char             tline[MAXLINE+EDITSLOP];/* input buffer plus space */
 static char            *keyword;		/* used for editing #elif's */
 
+static const char      *newline;		/* input file format */
+static const char       newline_unix[] = "\n";
+static const char       newline_crlf[] = "\r\n";
+
 static Comment_state    incomment;		/* comment parser state */
 static Line_state       linestate;		/* #if line parser state */
 static Ifstate          ifstate[MAXDEPTH];	/* #if processor state */
@@ -189,10 +204,13 @@ static int              delcount;		/* count of deleted lines */
 static unsigned         blankcount;		/* count of blank lines */
 static unsigned         blankmax;		/* maximum recent blankcount */
 static bool             constexpr;		/* constant #if expression */
+static bool             zerosyms = true;	/* to format symdepth output */
+static bool             firstsym;		/* ditto */
 
 static int              exitstat;		/* program exit status */
 
 static void             addsym(bool, bool, char *);
+static void             closeout(void);
 static void             debug(const char *, ...);
 static void             done(void);
 static void             error(const char *);
@@ -212,6 +230,7 @@ static void             state(Ifstate);
 static int              strlcmp(const char *, const char *, size_t);
 static void             unnest(void);
 static void             usage(void);
+static void             version(void);
 
 #define endsym(c) (!isalnum((unsigned char)c) && c != '_')
 
@@ -223,7 +242,7 @@ main(int argc, char *argv[])
 {
 	int opt;
 
-	while ((opt = getopt(argc, argv, "i:D:U:I:BbcdeKklnst")) != -1)
+	while ((opt = getopt(argc, argv, "i:D:U:I:o:bBcdeKklnsStV")) != -1)
 		switch (opt) {
 		case 'i': /* treat stuff controlled by these symbols as text */
 			/*
@@ -245,16 +264,15 @@ main(int argc, char *argv[])
 		case 'U': /* undef a symbol */
 			addsym(false, false, optarg);
 			break;
-		case 'I':
-			/* no-op for compatibility with cpp */
-			break;
-		case 'B': /* compress blank lines around removed section */
-			compblank = true;
+		case 'I': /* no-op for compatibility with cpp */
 			break;
 		case 'b': /* blank deleted lines instead of omitting them */
 		case 'l': /* backwards compatibility */
 			lnblank = true;
 			break;
+		case 'B': /* compress blank lines around removed section */
+			compblank = true;
+			break;
 		case 'c': /* treat -D as -U and vice versa */
 			complement = true;
 			break;
@@ -273,12 +291,20 @@ main(int argc, char *argv[])
 		case 'n': /* add #line directive after deleted lines */
 			lnnum = true;
 			break;
+		case 'o': /* output to a file */
+			ofilename = optarg;
+			break;
 		case 's': /* only output list of symbols that control #ifs */
 			symlist = true;
 			break;
+		case 'S': /* list symbols with their nesting depth */
+			symlist = symdepth = true;
+			break;
 		case 't': /* don't parse C comments */
 			text = true;
 			break;
+		case 'V': /* print version */
+			version();
 		default:
 			usage();
 		}
@@ -290,21 +316,68 @@ main(int argc, char *argv[])
 		errx(2, "can only do one file");
 	} else if (argc == 1 && strcmp(*argv, "-") != 0) {
 		filename = *argv;
-		input = fopen(filename, "r");
+		input = fopen(filename, "rb");
 		if (input == NULL)
 			err(2, "can't open %s", filename);
 	} else {
 		filename = "[stdin]";
 		input = stdin;
 	}
+	if (ofilename == NULL) {
+		ofilename = "[stdout]";
+		output = stdout;
+	} else {
+		struct stat ist, ost;
+		if (stat(ofilename, &ost) == 0 &&
+		    fstat(fileno(input), &ist) == 0)
+			overwriting = (ist.st_dev == ost.st_dev
+				    && ist.st_ino == ost.st_ino);
+		if (overwriting) {
+			const char *dirsep;
+			int ofd;
+
+			dirsep = strrchr(ofilename, '/');
+			if (dirsep != NULL)
+				snprintf(tempname, sizeof(tempname),
+				    "%.*s/" TEMPLATE,
+				    (int)(dirsep - ofilename), ofilename);
+			else
+				snprintf(tempname, sizeof(tempname),
+				    TEMPLATE);
+			ofd = mkstemp(tempname);
+			if (ofd != -1)
+				output = fdopen(ofd, "wb+");
+			if (output == NULL)
+				err(2, "can't create temporary file");
+			fchmod(ofd, ist.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+		} else {
+			output = fopen(ofilename, "wb");
+			if (output == NULL)
+				err(2, "can't open %s", ofilename);
+		}
+	}
 	process();
 	abort(); /* bug */
 }
 
 static void
+version(void)
+{
+	const char *c = copyright;
+	for (;;) {
+		while (*++c != '$')
+			if (*c == '\0')
+				exit(0);
+		while (*++c != '$')
+			putc(*c, stderr);
+		putc('\n', stderr);
+	}
+}
+
+static void
 usage(void)
 {
-	fprintf(stderr, "usage: unifdef [-BbcdeKknst] [-Ipath]"
+	fprintf(stderr, "usage: unifdef [-bBcdeKknsStV] [-Ipath]"
 	    " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
 	exit(2);
 }
@@ -322,7 +395,8 @@ usage(void)
  * When we have processed a group that starts off with a known-false
  * #if/#elif sequence (which has therefore been deleted) followed by a
  * #elif that we don't understand and therefore must keep, we edit the
- * latter into a #if to keep the nesting correct.
+ * latter into a #if to keep the nesting correct. We use strncpy() to
+ * overwrite the 4 byte token "elif" with "if  " without a '\0' byte.
  *
  * When we find a true #elif in a group, the following block will
  * always be kept and the rest of the sequence after the next #elif or
@@ -375,11 +449,11 @@ static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); }
 static void Idrop (void) { Fdrop();  ignoreon(); }
 static void Itrue (void) { Ftrue();  ignoreon(); }
 static void Ifalse(void) { Ffalse(); ignoreon(); }
-/* edit this line */
+/* modify this line */
 static void Mpass (void) { strncpy(keyword, "if  ", 4); Pelif(); }
-static void Mtrue (void) { keywordedit("else\n");  state(IS_TRUE_MIDDLE); }
-static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); }
-static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); }
+static void Mtrue (void) { keywordedit("else");  state(IS_TRUE_MIDDLE); }
+static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); }
+static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); }
 
 static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
 /* IS_OUTSIDE */
@@ -431,13 +505,6 @@ static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
  * State machine utility functions
  */
 static void
-done(void)
-{
-	if (incomment)
-		error("EOF in comment");
-	exit(exitstat);
-}
-static void
 ignoreoff(void)
 {
 	if (depth == 0)
@@ -452,14 +519,8 @@ ignoreon(void)
 static void
 keywordedit(const char *replacement)
 {
-	size_t size = tline + sizeof(tline) - keyword;
-	char *dst = keyword;
-	const char *src = replacement;
-	if (size != 0) {
-		while ((--size != 0) && (*src != '\0'))
-			*dst++ = *src++;
-		*dst = '\0';
-	}
+	snprintf(keyword, tline + sizeof(tline) - keyword,
+	    "%s%s", replacement, newline);
 	print();
 }
 static void
@@ -494,24 +555,26 @@ flushline(bool keep)
 	if (symlist)
 		return;
 	if (keep ^ complement) {
-		bool blankline = tline[strspn(tline, " \t\n")] == '\0';
+		bool blankline = tline[strspn(tline, " \t\r\n")] == '\0';
 		if (blankline && compblank && blankcount != blankmax) {
 			delcount += 1;
 			blankcount += 1;
 		} else {
 			if (lnnum && delcount > 0)
-				printf("#line %d\n", linenum);
-			fputs(tline, stdout);
+				printf("#line %d%s", linenum, newline);
+			fputs(tline, output);
 			delcount = 0;
 			blankmax = blankcount = blankline ? blankcount + 1 : 0;
 		}
 	} else {
 		if (lnblank)
-			putc('\n', stdout);
+			fputs(newline, output);
 		exitstat = 1;
 		delcount += 1;
 		blankcount = 0;
 	}
+	if (debugging)
+		fflush(output);
 }
 
 /*
@@ -520,22 +583,55 @@ flushline(bool keep)
 static void
 process(void)
 {
-	Linetype lineval;
-
 	/* When compressing blank lines, act as if the file
 	   is preceded by a large number of blank lines. */
 	blankmax = blankcount = 1000;
 	for (;;) {
-		linenum++;
-		lineval = parseline();
+		Linetype lineval = parseline();
 		trans_table[ifstate[depth]][lineval]();
-		debug("process %s -> %s depth %d",
-		    linetype_name[lineval],
+		debug("process line %d %s -> %s depth %d",
+		    linenum, linetype_name[lineval],
 		    ifstate_name[ifstate[depth]], depth);
 	}
 }
 
 /*
+ * Flush the output and handle errors.
+ */
+static void
+closeout(void)
+{
+	if (symdepth && !zerosyms)
+		printf("\n");
+	if (fclose(output) == EOF) {
+		warn("couldn't write to %s", ofilename);
+		if (overwriting) {
+			unlink(tempname);
+			errx(2, "%s unchanged", filename);
+		} else {
+			exit(2);
+		}
+	}
+}
+
+/*
+ * Clean up and exit.
+ */
+static void
+done(void)
+{
+	if (incomment)
+		error("EOF in comment");
+	closeout();
+	if (overwriting && rename(tempname, ofilename) == -1) {
+		warn("couldn't rename temporary file");
+		unlink(tempname);
+		errx(2, "%s unchanged", ofilename);
+	}
+	exit(exitstat);
+}
+
+/*
  * Parse a line and determine its type. We keep the preprocessor line
  * parser state between calls in the global variable linestate, with
  * help from skipcomment().
@@ -549,14 +645,22 @@ parseline(void)
 	Linetype retval;
 	Comment_state wascomment;
 
+	linenum++;
 	if (fgets(tline, MAXLINE, input) == NULL)
 		return (LT_EOF);
+	if (newline == NULL) {
+		if (strrchr(tline, '\n') == strrchr(tline, '\r') + 1)
+			newline = newline_crlf;
+		else
+			newline = newline_unix;
+	}
 	retval = LT_PLAIN;
 	wascomment = incomment;
 	cp = skipcomment(tline);
 	if (linestate == LS_START) {
 		if (*cp == '#') {
 			linestate = LS_HASH;
+			firstsym = true;
 			cp = skipcomment(cp + 1);
 		} else if (*cp != '\0')
 			linestate = LS_DIRTY;
@@ -566,7 +670,8 @@ parseline(void)
 		cp = skipsym(cp);
 		kwlen = cp - keyword;
 		/* no way can we deal with a continuation inside a keyword */
-		if (strncmp(cp, "\\\n", 2) == 0)
+		if (strncmp(cp, "\\\r\n", 3) == 0 ||
+		    strncmp(cp, "\\\n", 2) == 0)
 			Eioccc();
 		if (strlcmp("ifdef", keyword, kwlen) == 0 ||
 		    strlcmp("ifndef", keyword, kwlen) == 0) {
@@ -617,9 +722,8 @@ parseline(void)
 			size_t len = cp - tline;
 			if (fgets(tline + len, MAXLINE - len, input) == NULL) {
 				/* append the missing newline */
-				tline[len+0] = '\n';
-				tline[len+1] = '\0';
-				cp++;
+				strcpy(tline + len, newline);
+				cp += strlen(newline);
 				linestate = LS_START;
 			} else {
 				linestate = LS_DIRTY;
@@ -630,7 +734,7 @@ parseline(void)
 		while (*cp != '\0')
 			cp = skipcomment(cp + 1);
 	}
-	debug("parser %s comment %s line",
+	debug("parser line %d state %s comment %s line", linenum,
 	    comment_name[incomment], linestate_name[linestate]);
 	return (retval);
 }
@@ -875,11 +979,16 @@ skipcomment(const char *cp)
 	}
 	while (*cp != '\0')
 		/* don't reset to LS_START after a line continuation */
-		if (strncmp(cp, "\\\n", 2) == 0)
+		if (strncmp(cp, "\\\r\n", 3) == 0)
+			cp += 3;
+		else if (strncmp(cp, "\\\n", 2) == 0)
 			cp += 2;
 		else switch (incomment) {
 		case NO_COMMENT:
-			if (strncmp(cp, "/\\\n", 3) == 0) {
+			if (strncmp(cp, "/\\\r\n", 4) == 0) {
+				incomment = STARTING_COMMENT;
+				cp += 4;
+			} else if (strncmp(cp, "/\\\n", 3) == 0) {
 				incomment = STARTING_COMMENT;
 				cp += 3;
 			} else if (strncmp(cp, "/*", 2) == 0) {
@@ -899,7 +1008,7 @@ skipcomment(const char *cp)
 			} else if (strncmp(cp, "\n", 1) == 0) {
 				linestate = LS_START;
 				cp += 1;
-			} else if (strchr(" \t", *cp) != NULL) {
+			} else if (strchr(" \r\t", *cp) != NULL) {
 				cp += 1;
 			} else
 				return (cp);
@@ -931,7 +1040,10 @@ skipcomment(const char *cp)
 				cp += 1;
 			continue;
 		case C_COMMENT:
-			if (strncmp(cp, "*\\\n", 3) == 0) {
+			if (strncmp(cp, "*\\\r\n", 4) == 0) {
+				incomment = FINISHING_COMMENT;
+				cp += 4;
+			} else if (strncmp(cp, "*\\\n", 3) == 0) {
 				incomment = FINISHING_COMMENT;
 				cp += 3;
 			} else if (strncmp(cp, "*/", 2) == 0) {
@@ -1015,7 +1127,13 @@ findsym(const char *str)
 	if (cp == str)
 		return (-1);
 	if (symlist) {
-		printf("%.*s\n", (int)(cp-str), str);
+		if (symdepth && firstsym)
+			printf("%s%3d", zerosyms ? "" : "\n", depth);
+		firstsym = zerosyms = false;
+		printf("%s%.*s%s",
+		    symdepth ? " " : "",
+		    (int)(cp-str), str,
+		    symdepth ? "" : "\n");
 		/* we don't care about the value of the symbol */
 		return (0);
 	}
@@ -1052,7 +1170,7 @@ addsym(bool ignorethis, bool definethis, char *sym)
 			value[symind] = val+1;
 			*val = '\0';
 		} else if (*val == '\0')
-			value[symind] = "";
+			value[symind] = "1";
 		else
 			usage();
 	} else {
@@ -1060,6 +1178,8 @@ addsym(bool ignorethis, bool definethis, char *sym)
 			usage();
 		value[symind] = NULL;
 	}
+	debug("addsym %s=%s", symname[symind],
+	    value[symind] ? value[symind] : "undef");
 }
 
 /*
@@ -1100,5 +1220,6 @@ error(const char *msg)
 	else
 		warnx("%s: %d: %s (#if line %d depth %d)",
 		    filename, linenum, msg, stifline[depth], depth);
+	closeout();
 	errx(2, "output may be truncated");
 }
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index f204869..2dafe50 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -6,19 +6,47 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
               path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
               resource.o sid.o file.o
 
-clean-files: capability_names.h af_names.h
+clean-files := capability_names.h rlim_names.h
 
+
+# Build a lower case string table of capability names
+# Transforms lines from
+#    #define CAP_DAC_OVERRIDE     1
+# to
+#    [1] = "dac_override",
 quiet_cmd_make-caps = GEN     $@
-cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
+cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ;\
+	sed $< >>$@ -r -n -e '/CAP_FS_MASK/d' \
+	-e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/[\2] = "\L\1",/p';\
+	echo "};" >> $@
+
 
+# Build a lower case string table of rlimit names.
+# Transforms lines from
+#    #define RLIMIT_STACK		3	/* max stack size */
+# to
+#    [RLIMIT_STACK] = "stack",
+#
+# and build a second integer table (with the second sed cmd), that maps
+# RLIMIT defines to the order defined in asm-generic/resource.h  Thi is
+# required by policy load to map policy ordering of RLIMITs to internal
+# ordering for architectures that redefine an RLIMIT.
+# Transforms lines from
+#    #define RLIMIT_STACK		3	/* max stack size */
+# to
+# RLIMIT_STACK, 
 quiet_cmd_make-rlim = GEN     $@
-cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
+cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ;\
+	sed $< >> $@ -r -n \
+	    -e 's/^\# ?define[ \t]+(RLIMIT_([A-Z0-9_]+)).*/[\1] = "\L\2",/p';\
+	echo "};" >> $@ ;\
+	echo "static const int rlim_map[] = {" >> $@ ;\
+	sed -r -n "s/^\# ?define[ \t]+(RLIMIT_[A-Z0-9_]+).*/\1,/p" $< >> $@ ;\
+	echo "};" >> $@
 
 $(obj)/capability.o : $(obj)/capability_names.h
 $(obj)/resource.o : $(obj)/rlim_names.h
 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
 	$(call cmd,make-caps)
-$(obj)/af_names.h : $(srctree)/include/linux/socket.h
-	$(call cmd,make-af)
 $(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
 	$(call cmd,make-rlim)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index b7106f1..d21a427 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -693,11 +693,9 @@ static struct kernel_param_ops param_ops_aalockpolicy = {
 
 static int param_set_audit(const char *val, struct kernel_param *kp);
 static int param_get_audit(char *buffer, struct kernel_param *kp);
-#define param_check_audit(name, p) __param_check(name, p, int)
 
 static int param_set_mode(const char *val, struct kernel_param *kp);
 static int param_get_mode(char *buffer, struct kernel_param *kp);
-#define param_check_mode(name, p) __param_check(name, p, int)
 
 /* Flag values, also controllable via /sys/module/apparmor/parameters
  * We define special types as we want to do additional mediation.
diff --git a/security/capability.c b/security/capability.c
index 2a5df2b..2984ea4 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -12,11 +12,6 @@
 
 #include <linux/security.h>
 
-static int cap_sysctl(ctl_table *table, int op)
-{
-	return 0;
-}
-
 static int cap_syslog(int type)
 {
 	return 0;
@@ -59,6 +54,11 @@ static int cap_sb_copy_data(char *orig, char *copy)
 	return 0;
 }
 
+static int cap_sb_remount(struct super_block *sb, void *data)
+{
+	return 0;
+}
+
 static int cap_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
 	return 0;
@@ -118,7 +118,8 @@ static void cap_inode_free_security(struct inode *inode)
 }
 
 static int cap_inode_init_security(struct inode *inode, struct inode *dir,
-				   char **name, void **value, size_t *len)
+				   const struct qstr *qstr, char **name,
+				   void **value, size_t *len)
 {
 	return -EOPNOTSUPP;
 }
@@ -760,7 +761,7 @@ static int cap_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 sk_sid, u8 dir)
 
 static int cap_xfrm_state_pol_flow_match(struct xfrm_state *x,
 					 struct xfrm_policy *xp,
-					 struct flowi *fl)
+					 const struct flowi *fl)
 {
 	return 1;
 }
@@ -880,7 +881,6 @@ void __init security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, capable);
 	set_to_cap_if_null(ops, quotactl);
 	set_to_cap_if_null(ops, quota_on);
-	set_to_cap_if_null(ops, sysctl);
 	set_to_cap_if_null(ops, syslog);
 	set_to_cap_if_null(ops, settime);
 	set_to_cap_if_null(ops, vm_enough_memory);
@@ -892,6 +892,7 @@ void __init security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, sb_alloc_security);
 	set_to_cap_if_null(ops, sb_free_security);
 	set_to_cap_if_null(ops, sb_copy_data);
+	set_to_cap_if_null(ops, sb_remount);
 	set_to_cap_if_null(ops, sb_kern_mount);
 	set_to_cap_if_null(ops, sb_show_options);
 	set_to_cap_if_null(ops, sb_statfs);
diff --git a/security/commoncap.c b/security/commoncap.c
index 64c2ed9..49c57fd 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -52,13 +52,12 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
 
 int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
 {
-	NETLINK_CB(skb).eff_cap = current_cap();
 	return 0;
 }
 
 int cap_netlink_recv(struct sk_buff *skb, int cap)
 {
-	if (!cap_raised(NETLINK_CB(skb).eff_cap, cap))
+	if (!cap_raised(current_cap(), cap))
 		return -EPERM;
 	return 0;
 }
@@ -93,7 +92,7 @@ int cap_capable(struct task_struct *tsk, const struct cred *cred, int cap,
  * Determine whether the current process may set the system clock and timezone
  * information, returning 0 if permission granted, -ve if denied.
  */
-int cap_settime(struct timespec *ts, struct timezone *tz)
+int cap_settime(const struct timespec *ts, const struct timezone *tz)
 {
 	if (!capable(CAP_SYS_TIME))
 		return -EPERM;
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index ac79032..08408bd 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -110,8 +110,7 @@ struct ima_iint_cache {
 };
 
 /* LIM API function definitions */
-int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
-		     int mask, int function);
+int ima_must_measure(struct inode *inode, int mask, int function);
 int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file);
 void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
 			   const unsigned char *filename);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index d3963de..da36d2c 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -105,20 +105,13 @@ err_out:
  * 	mask: contains the permission mask
  *	fsmagic: hex value
  *
- * Must be called with iint->mutex held.
- *
- * Return 0 to measure. Return 1 if already measured.
- * For matching a DONT_MEASURE policy, no policy, or other
- * error, return an error code.
+ * Return 0 to measure. For matching a DONT_MEASURE policy, no policy,
+ * or other error, return an error code.
 */
-int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
-		     int mask, int function)
+int ima_must_measure(struct inode *inode, int mask, int function)
 {
 	int must_measure;
 
-	if (iint && iint->flags & IMA_MEASURED)
-		return 1;
-
 	must_measure = ima_match_policy(inode, function, mask);
 	return must_measure ? 0 : -EACCES;
 }
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c
index c442e47..4ae7304 100644
--- a/security/integrity/ima/ima_iint.c
+++ b/security/integrity/ima/ima_iint.c
@@ -137,11 +137,6 @@ void ima_inode_free(struct inode *inode)
 {
 	struct ima_iint_cache *iint;
 
-	if (inode->i_readcount)
-		printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount);
-
-	inode->i_readcount = 0;
-
 	if (!IS_IMA(inode))
 		return;
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 203de97..39d66dc 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -36,67 +36,17 @@ static int __init hash_setup(char *str)
 }
 __setup("ima_hash=", hash_setup);
 
-struct ima_imbalance {
-	struct hlist_node node;
-	unsigned long fsmagic;
-};
-
-/*
- * ima_limit_imbalance - emit one imbalance message per filesystem type
- *
- * Maintain list of filesystem types that do not measure files properly.
- * Return false if unknown, true if known.
- */
-static bool ima_limit_imbalance(struct file *file)
-{
-	static DEFINE_SPINLOCK(ima_imbalance_lock);
-	static HLIST_HEAD(ima_imbalance_list);
-
-	struct super_block *sb = file->f_dentry->d_sb;
-	struct ima_imbalance *entry;
-	struct hlist_node *node;
-	bool found = false;
-
-	rcu_read_lock();
-	hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) {
-		if (entry->fsmagic == sb->s_magic) {
-			found = true;
-			break;
-		}
-	}
-	rcu_read_unlock();
-	if (found)
-		goto out;
-
-	entry = kmalloc(sizeof(*entry), GFP_NOFS);
-	if (!entry)
-		goto out;
-	entry->fsmagic = sb->s_magic;
-	spin_lock(&ima_imbalance_lock);
-	/*
-	 * we could have raced and something else might have added this fs
-	 * to the list, but we don't really care
-	 */
-	hlist_add_head_rcu(&entry->node, &ima_imbalance_list);
-	spin_unlock(&ima_imbalance_lock);
-	printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n",
-	       entry->fsmagic);
-out:
-	return found;
-}
-
 /*
- * ima_counts_get - increment file counts
+ * ima_rdwr_violation_check
  *
- * Maintain read/write counters for all files, but only
- * invalidate the PCR for measured files:
+ * Only invalidate the PCR for measured files:
  * 	- Opening a file for write when already open for read,
  *	  results in a time of measure, time of use (ToMToU) error.
  *	- Opening a file for read when already open for write,
  * 	  could result in a file measurement error.
  *
  */
-void ima_counts_get(struct file *file)
+static void ima_rdwr_violation_check(struct file *file)
 {
 	struct dentry *dentry = file->f_path.dentry;
 	struct inode *inode = dentry->d_inode;
@@ -104,32 +54,25 @@ void ima_counts_get(struct file *file)
 	int rc;
 	bool send_tomtou = false, send_writers = false;
 
-	if (!S_ISREG(inode->i_mode))
+	if (!S_ISREG(inode->i_mode) || !ima_initialized)
 		return;
 
-	spin_lock(&inode->i_lock);
-
-	if (!ima_initialized)
-		goto out;
+	mutex_lock(&inode->i_mutex);	/* file metadata: permissions, xattr */
 
 	if (mode & FMODE_WRITE) {
-		if (inode->i_readcount && IS_IMA(inode))
+		if (atomic_read(&inode->i_readcount) && IS_IMA(inode))
 			send_tomtou = true;
 		goto out;
 	}
 
-	rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK);
+	rc = ima_must_measure(inode, MAY_READ, FILE_CHECK);
 	if (rc < 0)
 		goto out;
 
 	if (atomic_read(&inode->i_writecount) > 0)
 		send_writers = true;
 out:
-	/* remember the vfs deals with i_writecount */
-	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-		inode->i_readcount++;
-
-	spin_unlock(&inode->i_lock);
+	mutex_unlock(&inode->i_mutex);
 
 	if (send_tomtou)
 		ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
@@ -139,71 +82,25 @@ out:
 				  "open_writers");
 }
 
-/*
- * Decrement ima counts
- */
-static void ima_dec_counts(struct inode *inode, struct file *file)
-{
-	mode_t mode = file->f_mode;
-
-	assert_spin_locked(&inode->i_lock);
-
-	if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
-		if (unlikely(inode->i_readcount == 0)) {
-			if (!ima_limit_imbalance(file)) {
-				printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
-				       __func__, inode->i_readcount);
-				dump_stack();
-			}
-			return;
-		}
-		inode->i_readcount--;
-	}
-}
-
 static void ima_check_last_writer(struct ima_iint_cache *iint,
 				  struct inode *inode,
 				  struct file *file)
 {
 	mode_t mode = file->f_mode;
 
-	BUG_ON(!mutex_is_locked(&iint->mutex));
-	assert_spin_locked(&inode->i_lock);
-
+	mutex_lock(&iint->mutex);
 	if (mode & FMODE_WRITE &&
 	    atomic_read(&inode->i_writecount) == 1 &&
 	    iint->version != inode->i_version)
 		iint->flags &= ~IMA_MEASURED;
-}
-
-static void ima_file_free_iint(struct ima_iint_cache *iint, struct inode *inode,
-			       struct file *file)
-{
-	mutex_lock(&iint->mutex);
-	spin_lock(&inode->i_lock);
-
-	ima_dec_counts(inode, file);
-	ima_check_last_writer(iint, inode, file);
-
-	spin_unlock(&inode->i_lock);
 	mutex_unlock(&iint->mutex);
 }
 
-static void ima_file_free_noiint(struct inode *inode, struct file *file)
-{
-	spin_lock(&inode->i_lock);
-
-	ima_dec_counts(inode, file);
-
-	spin_unlock(&inode->i_lock);
-}
-
 /**
  * ima_file_free - called on __fput()
  * @file: pointer to file structure being freed
  *
- * Flag files that changed, based on i_version;
- * and decrement the i_readcount.
+ * Flag files that changed, based on i_version
  */
 void ima_file_free(struct file *file)
 {
@@ -214,12 +111,10 @@ void ima_file_free(struct file *file)
 		return;
 
 	iint = ima_iint_find(inode);
+	if (!iint)
+		return;
 
-	if (iint)
-		ima_file_free_iint(iint, inode, file);
-	else
-		ima_file_free_noiint(inode, file);
-
+	ima_check_last_writer(iint, inode, file);
 }
 
 static int process_measurement(struct file *file, const unsigned char *filename,
@@ -232,7 +127,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
 	if (!ima_initialized || !S_ISREG(inode->i_mode))
 		return 0;
 
-	rc = ima_must_measure(NULL, inode, mask, function);
+	rc = ima_must_measure(inode, mask, function);
 	if (rc != 0)
 		return rc;
 retry:
@@ -246,7 +141,7 @@ retry:
 
 	mutex_lock(&iint->mutex);
 
-	rc = ima_must_measure(iint, inode, mask, function);
+	rc = iint->flags & IMA_MEASURED ? 1 : 0;
 	if (rc != 0)
 		goto out;
 
@@ -317,6 +212,7 @@ int ima_file_check(struct file *file, int mask)
 {
 	int rc;
 
+	ima_rdwr_violation_check(file);
 	rc = process_measurement(file, file->f_dentry->d_name.name,
 				 mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
 				 FILE_CHECK);
diff --git a/security/keys/compat.c b/security/keys/compat.c
index 07a5f35..338b510 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -12,9 +12,52 @@
 #include <linux/syscalls.h>
 #include <linux/keyctl.h>
 #include <linux/compat.h>
+#include <linux/slab.h>
 #include "internal.h"
 
 /*
+ * Instantiate a key with the specified compatibility multipart payload and
+ * link the key into the destination keyring if one is given.
+ *
+ * The caller must have the appropriate instantiation permit set for this to
+ * work (see keyctl_assume_authority).  No other permissions are required.
+ *
+ * If successful, 0 will be returned.
+ */
+long compat_keyctl_instantiate_key_iov(
+	key_serial_t id,
+	const struct compat_iovec __user *_payload_iov,
+	unsigned ioc,
+	key_serial_t ringid)
+{
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	long ret;
+
+	if (_payload_iov == 0 || ioc == 0)
+		goto no_payload;
+
+	ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
+					   ARRAY_SIZE(iovstack),
+					   iovstack, &iov);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		goto no_payload_free;
+
+	ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
+
+	if (iov != iovstack)
+		kfree(iov);
+	return ret;
+
+no_payload_free:
+	if (iov != iovstack)
+		kfree(iov);
+no_payload:
+	return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+}
+
+/*
  * The key control system call, 32-bit compatibility version for 64-bit archs
  *
  * This should only be called if the 64-bit arch uses weird pointers in 32-bit
@@ -85,6 +128,13 @@ asmlinkage long compat_sys_keyctl(u32 option,
 	case KEYCTL_SESSION_TO_PARENT:
 		return keyctl_session_to_parent();
 
+	case KEYCTL_REJECT:
+		return keyctl_reject_key(arg2, arg3, arg4, arg5);
+
+	case KEYCTL_INSTANTIATE_IOV:
+		return compat_keyctl_instantiate_key_iov(
+			arg2, compat_ptr(arg3), arg4, arg5);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/encrypted.c b/security/keys/encrypted.c
index 9e7e4ce..69907a5 100644
--- a/security/keys/encrypted.c
+++ b/security/keys/encrypted.c
@@ -765,8 +765,7 @@ static long encrypted_read(const struct key *key, char __user *buffer,
 	size_t asciiblob_len;
 	int ret;
 
-	epayload = rcu_dereference_protected(key->payload.data,
-				  rwsem_is_locked(&((struct key *)key)->sem));
+	epayload = rcu_dereference_key(key);
 
 	/* returns the hex encoded iv, encrypted-data, and hmac as ascii */
 	asciiblob_len = epayload->datablob_len + ivsize + 1
diff --git a/security/keys/internal.h b/security/keys/internal.h
index a52aa7c..07a025f 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -214,6 +214,14 @@ extern long keyctl_assume_authority(key_serial_t);
 extern long keyctl_get_security(key_serial_t keyid, char __user *buffer,
 				size_t buflen);
 extern long keyctl_session_to_parent(void);
+extern long keyctl_reject_key(key_serial_t, unsigned, unsigned, key_serial_t);
+extern long keyctl_instantiate_key_iov(key_serial_t,
+				       const struct iovec __user *,
+				       unsigned, key_serial_t);
+
+extern long keyctl_instantiate_key_common(key_serial_t,
+					  const struct iovec __user *,
+					  unsigned, size_t, key_serial_t);
 
 /*
  * Debugging key validation
diff --git a/security/keys/key.c b/security/keys/key.c
index 1c2d43d..f7f9d93 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -249,6 +249,14 @@ struct key *key_alloc(struct key_type *type, const char *desc,
 	if (!desc || !*desc)
 		goto error;
 
+	if (type->vet_description) {
+		ret = type->vet_description(desc);
+		if (ret < 0) {
+			key = ERR_PTR(ret);
+			goto error;
+		}
+	}
+
 	desclen = strlen(desc) + 1;
 	quotalen = desclen + type->def_datalen;
 
@@ -503,26 +511,29 @@ int key_instantiate_and_link(struct key *key,
 EXPORT_SYMBOL(key_instantiate_and_link);
 
 /**
- * key_negate_and_link - Negatively instantiate a key and link it into the keyring.
+ * key_reject_and_link - Negatively instantiate a key and link it into the keyring.
  * @key: The key to instantiate.
  * @timeout: The timeout on the negative key.
+ * @error: The error to return when the key is hit.
  * @keyring: Keyring to create a link in on success (or NULL).
  * @authkey: The authorisation token permitting instantiation.
  *
  * Negatively instantiate a key that's in the uninstantiated state and, if
- * successful, set its timeout and link it in to the destination keyring if one
- * is supplied.  The key and any links to the key will be automatically garbage
- * collected after the timeout expires.
+ * successful, set its timeout and stored error and link it in to the
+ * destination keyring if one is supplied.  The key and any links to the key
+ * will be automatically garbage collected after the timeout expires.
  *
  * Negative keys are used to rate limit repeated request_key() calls by causing
- * them to return -ENOKEY until the negative key expires.
+ * them to return the stored error code (typically ENOKEY) until the negative
+ * key expires.
  *
  * If successful, 0 is returned, the authorisation token is revoked and anyone
  * waiting for the key is woken up.  If the key was already instantiated,
  * -EBUSY will be returned.
  */
-int key_negate_and_link(struct key *key,
+int key_reject_and_link(struct key *key,
 			unsigned timeout,
+			unsigned error,
 			struct key *keyring,
 			struct key *authkey)
 {
@@ -548,6 +559,7 @@ int key_negate_and_link(struct key *key,
 		atomic_inc(&key->user->nikeys);
 		set_bit(KEY_FLAG_NEGATIVE, &key->flags);
 		set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
+		key->type_data.reject_error = -error;
 		now = current_kernel_time();
 		key->expiry = now.tv_sec + timeout;
 		key_schedule_gc(key->expiry + key_gc_delay);
@@ -577,8 +589,7 @@ int key_negate_and_link(struct key *key,
 
 	return ret == 0 ? link_ret : ret;
 }
-
-EXPORT_SYMBOL(key_negate_and_link);
+EXPORT_SYMBOL(key_reject_and_link);
 
 /*
  * Garbage collect keys in process context so that we don't have to disable
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 31a0fd8..427fddc 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -913,6 +913,21 @@ static int keyctl_change_reqkey_auth(struct key *key)
 }
 
 /*
+ * Copy the iovec data from userspace
+ */
+static long copy_from_user_iovec(void *buffer, const struct iovec *iov,
+				 unsigned ioc)
+{
+	for (; ioc > 0; ioc--) {
+		if (copy_from_user(buffer, iov->iov_base, iov->iov_len) != 0)
+			return -EFAULT;
+		buffer += iov->iov_len;
+		iov++;
+	}
+	return 0;
+}
+
+/*
  * Instantiate a key with the specified payload and link the key into the
  * destination keyring if one is given.
  *
@@ -921,10 +936,11 @@ static int keyctl_change_reqkey_auth(struct key *key)
  *
  * If successful, 0 will be returned.
  */
-long keyctl_instantiate_key(key_serial_t id,
-			    const void __user *_payload,
-			    size_t plen,
-			    key_serial_t ringid)
+long keyctl_instantiate_key_common(key_serial_t id,
+				   const struct iovec *payload_iov,
+				   unsigned ioc,
+				   size_t plen,
+				   key_serial_t ringid)
 {
 	const struct cred *cred = current_cred();
 	struct request_key_auth *rka;
@@ -953,7 +969,7 @@ long keyctl_instantiate_key(key_serial_t id,
 	/* pull the payload in if one was supplied */
 	payload = NULL;
 
-	if (_payload) {
+	if (payload_iov) {
 		ret = -ENOMEM;
 		payload = kmalloc(plen, GFP_KERNEL);
 		if (!payload) {
@@ -965,8 +981,8 @@ long keyctl_instantiate_key(key_serial_t id,
 				goto error;
 		}
 
-		ret = -EFAULT;
-		if (copy_from_user(payload, _payload, plen) != 0)
+		ret = copy_from_user_iovec(payload, payload_iov, ioc);
+		if (ret < 0)
 			goto error2;
 	}
 
@@ -997,6 +1013,72 @@ error:
 }
 
 /*
+ * Instantiate a key with the specified payload and link the key into the
+ * destination keyring if one is given.
+ *
+ * The caller must have the appropriate instantiation permit set for this to
+ * work (see keyctl_assume_authority).  No other permissions are required.
+ *
+ * If successful, 0 will be returned.
+ */
+long keyctl_instantiate_key(key_serial_t id,
+			    const void __user *_payload,
+			    size_t plen,
+			    key_serial_t ringid)
+{
+	if (_payload && plen) {
+		struct iovec iov[1] = {
+			[0].iov_base = (void __user *)_payload,
+			[0].iov_len  = plen
+		};
+
+		return keyctl_instantiate_key_common(id, iov, 1, plen, ringid);
+	}
+
+	return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+}
+
+/*
+ * Instantiate a key with the specified multipart payload and link the key into
+ * the destination keyring if one is given.
+ *
+ * The caller must have the appropriate instantiation permit set for this to
+ * work (see keyctl_assume_authority).  No other permissions are required.
+ *
+ * If successful, 0 will be returned.
+ */
+long keyctl_instantiate_key_iov(key_serial_t id,
+				const struct iovec __user *_payload_iov,
+				unsigned ioc,
+				key_serial_t ringid)
+{
+	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
+	long ret;
+
+	if (_payload_iov == 0 || ioc == 0)
+		goto no_payload;
+
+	ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
+				    ARRAY_SIZE(iovstack), iovstack, &iov);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		goto no_payload_free;
+
+	ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
+
+	if (iov != iovstack)
+		kfree(iov);
+	return ret;
+
+no_payload_free:
+	if (iov != iovstack)
+		kfree(iov);
+no_payload:
+	return keyctl_instantiate_key_common(id, NULL, 0, 0, ringid);
+}
+
+/*
  * Negatively instantiate the key with the given timeout (in seconds) and link
  * the key into the destination keyring if one is given.
  *
@@ -1013,12 +1095,42 @@ error:
  */
 long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 {
+	return keyctl_reject_key(id, timeout, ENOKEY, ringid);
+}
+
+/*
+ * Negatively instantiate the key with the given timeout (in seconds) and error
+ * code and link the key into the destination keyring if one is given.
+ *
+ * The caller must have the appropriate instantiation permit set for this to
+ * work (see keyctl_assume_authority).  No other permissions are required.
+ *
+ * The key and any links to the key will be automatically garbage collected
+ * after the timeout expires.
+ *
+ * Negative keys are used to rate limit repeated request_key() calls by causing
+ * them to return the specified error code until the negative key expires.
+ *
+ * If successful, 0 will be returned.
+ */
+long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
+		       key_serial_t ringid)
+{
 	const struct cred *cred = current_cred();
 	struct request_key_auth *rka;
 	struct key *instkey, *dest_keyring;
 	long ret;
 
-	kenter("%d,%u,%d", id, timeout, ringid);
+	kenter("%d,%u,%u,%d", id, timeout, error, ringid);
+
+	/* must be a valid error code and mustn't be a kernel special */
+	if (error <= 0 ||
+	    error >= MAX_ERRNO ||
+	    error == ERESTARTSYS ||
+	    error == ERESTARTNOINTR ||
+	    error == ERESTARTNOHAND ||
+	    error == ERESTART_RESTARTBLOCK)
+		return -EINVAL;
 
 	/* the appropriate instantiation authorisation key must have been
 	 * assumed before calling this */
@@ -1038,7 +1150,7 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 		goto error;
 
 	/* instantiate the key and link it into a keyring */
-	ret = key_negate_and_link(rka->target_key, timeout,
+	ret = key_reject_and_link(rka->target_key, timeout, error,
 				  dest_keyring, instkey);
 
 	key_put(dest_keyring);
@@ -1492,6 +1604,19 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
 	case KEYCTL_SESSION_TO_PARENT:
 		return keyctl_session_to_parent();
 
+	case KEYCTL_REJECT:
+		return keyctl_reject_key((key_serial_t) arg2,
+					 (unsigned) arg3,
+					 (unsigned) arg4,
+					 (key_serial_t) arg5);
+
+	case KEYCTL_INSTANTIATE_IOV:
+		return keyctl_instantiate_key_iov(
+			(key_serial_t) arg2,
+			(const struct iovec __user *) arg3,
+			(unsigned) arg4,
+			(key_serial_t) arg5);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 5620f08..cdd2f3f 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -352,7 +352,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
 			goto error_2;
 		if (key->expiry && now.tv_sec >= key->expiry)
 			goto error_2;
-		key_ref = ERR_PTR(-ENOKEY);
+		key_ref = ERR_PTR(key->type_data.reject_error);
 		if (kflags & (1 << KEY_FLAG_NEGATIVE))
 			goto error_2;
 		goto found;
@@ -401,7 +401,7 @@ descend:
 
 		/* we set a different error code if we pass a negative key */
 		if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
-			err = -ENOKEY;
+			err = key->type_data.reject_error;
 			continue;
 		}
 
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index a3dc0d4..df3c041 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -585,7 +585,7 @@ int wait_for_key_construction(struct key *key, bool intr)
 	if (ret < 0)
 		return ret;
 	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags))
-		return -ENOKEY;
+		return key->type_data.reject_error;
 	return key_validate(key);
 }
 EXPORT_SYMBOL(wait_for_key_construction);
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 83fc92e..c99b936 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -1076,8 +1076,7 @@ static long trusted_read(const struct key *key, char __user *buffer,
 	char *bufp;
 	int i;
 
-	p = rcu_dereference_protected(key->payload.data,
-			rwsem_is_locked(&((struct key *)key)->sem));
+	p = rcu_dereference_key(key);
 	if (!p)
 		return -EINVAL;
 	if (!buffer || buflen <= 0)
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 02807fb..c6ca866 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -184,8 +184,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen)
 	struct user_key_payload *upayload;
 	long ret;
 
-	upayload = rcu_dereference_protected(
-		key->payload.data, rwsem_is_locked(&((struct key *)key)->sem));
+	upayload = rcu_dereference_key(key);
 	ret = upayload->datalen;
 
 	/* we can return the data as is */
diff --git a/security/security.c b/security/security.c
index 7b7308a..9187665 100644
--- a/security/security.c
+++ b/security/security.c
@@ -181,11 +181,6 @@ int security_real_capable_noaudit(struct task_struct *tsk, int cap)
 	return ret;
 }
 
-int security_sysctl(struct ctl_table *table, int op)
-{
-	return security_ops->sysctl(table, op);
-}
-
 int security_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
 	return security_ops->quotactl(cmds, type, id, sb);
@@ -201,7 +196,7 @@ int security_syslog(int type)
 	return security_ops->syslog(type);
 }
 
-int security_settime(struct timespec *ts, struct timezone *tz)
+int security_settime(const struct timespec *ts, const struct timezone *tz)
 {
 	return security_ops->settime(ts, tz);
 }
@@ -271,6 +266,11 @@ int security_sb_copy_data(char *orig, char *copy)
 }
 EXPORT_SYMBOL(security_sb_copy_data);
 
+int security_sb_remount(struct super_block *sb, void *data)
+{
+	return security_ops->sb_remount(sb, data);
+}
+
 int security_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
 	return security_ops->sb_kern_mount(sb, flags, data);
@@ -335,11 +335,13 @@ void security_inode_free(struct inode *inode)
 }
 
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-				  char **name, void **value, size_t *len)
+				 const struct qstr *qstr, char **name,
+				 void **value, size_t *len)
 {
 	if (unlikely(IS_PRIVATE(inode)))
 		return -EOPNOTSUPP;
-	return security_ops->inode_init_security(inode, dir, name, value, len);
+	return security_ops->inode_init_security(inode, dir, qstr, name, value,
+						 len);
 }
 EXPORT_SYMBOL(security_inode_init_security);
 
@@ -359,6 +361,7 @@ int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
 		return 0;
 	return security_ops->path_mkdir(dir, dentry, mode);
 }
+EXPORT_SYMBOL(security_path_mkdir);
 
 int security_path_rmdir(struct path *dir, struct dentry *dentry)
 {
@@ -373,6 +376,7 @@ int security_path_unlink(struct path *dir, struct dentry *dentry)
 		return 0;
 	return security_ops->path_unlink(dir, dentry);
 }
+EXPORT_SYMBOL(security_path_unlink);
 
 int security_path_symlink(struct path *dir, struct dentry *dentry,
 			  const char *old_name)
@@ -399,6 +403,7 @@ int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
 	return security_ops->path_rename(old_dir, old_dentry, new_dir,
 					 new_dentry);
 }
+EXPORT_SYMBOL(security_path_rename);
 
 int security_path_truncate(struct path *path)
 {
@@ -1100,7 +1105,7 @@ void security_sk_clone(const struct sock *sk, struct sock *newsk)
 
 void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
 {
-	security_ops->sk_getsecid(sk, &fl->secid);
+	security_ops->sk_getsecid(sk, &fl->flowi_secid);
 }
 EXPORT_SYMBOL(security_sk_classify_flow);
 
@@ -1233,7 +1238,8 @@ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
 }
 
 int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
-				       struct xfrm_policy *xp, struct flowi *fl)
+				       struct xfrm_policy *xp,
+				       const struct flowi *fl)
 {
 	return security_ops->xfrm_state_pol_flow_match(x, xp, fl);
 }
@@ -1245,7 +1251,7 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
 
 void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl)
 {
-	int rc = security_ops->xfrm_decode_session(skb, &fl->secid, 0);
+	int rc = security_ops->xfrm_decode_session(skb, &fl->flowi_secid, 0);
 
 	BUG_ON(rc);
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c8d6992..6475e1f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -24,9 +24,11 @@
  */
 
 #include <linux/init.h>
+#include <linux/kd.h>
 #include <linux/kernel.h>
 #include <linux/tracehook.h>
 #include <linux/errno.h>
+#include <linux/ext2_fs.h>
 #include <linux/sched.h>
 #include <linux/security.h>
 #include <linux/xattr.h>
@@ -36,14 +38,15 @@
 #include <linux/mman.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/proc_fs.h>
 #include <linux/swap.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
+#include <linux/dcache.h>
 #include <linux/file.h>
 #include <linux/fdtable.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
-#include <linux/proc_fs.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/tty.h>
@@ -70,7 +73,6 @@
 #include <net/ipv6.h>
 #include <linux/hugetlb.h>
 #include <linux/personality.h>
-#include <linux/sysctl.h>
 #include <linux/audit.h>
 #include <linux/string.h>
 #include <linux/selinux.h>
@@ -1120,39 +1122,35 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
 }
 
 #ifdef CONFIG_PROC_FS
-static int selinux_proc_get_sid(struct proc_dir_entry *de,
+static int selinux_proc_get_sid(struct dentry *dentry,
 				u16 tclass,
 				u32 *sid)
 {
-	int buflen, rc;
-	char *buffer, *path, *end;
+	int rc;
+	char *buffer, *path;
 
 	buffer = (char *)__get_free_page(GFP_KERNEL);
 	if (!buffer)
 		return -ENOMEM;
 
-	buflen = PAGE_SIZE;
-	end = buffer+buflen;
-	*--end = '\0';
-	buflen--;
-	path = end-1;
-	*path = '/';
-	while (de && de != de->parent) {
-		buflen -= de->namelen + 1;
-		if (buflen < 0)
-			break;
-		end -= de->namelen;
-		memcpy(end, de->name, de->namelen);
-		*--end = '/';
-		path = end;
-		de = de->parent;
+	path = dentry_path_raw(dentry, buffer, PAGE_SIZE);
+	if (IS_ERR(path))
+		rc = PTR_ERR(path);
+	else {
+		/* each process gets a /proc/PID/ entry. Strip off the
+		 * PID part to get a valid selinux labeling.
+		 * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
+		while (path[1] >= '0' && path[1] <= '9') {
+			path[1] = '/';
+			path++;
+		}
+		rc = security_genfs_sid("proc", path, tclass, sid);
 	}
-	rc = security_genfs_sid("proc", path, tclass, sid);
 	free_page((unsigned long)buffer);
 	return rc;
 }
 #else
-static int selinux_proc_get_sid(struct proc_dir_entry *de,
+static int selinux_proc_get_sid(struct dentry *dentry,
 				u16 tclass,
 				u32 *sid)
 {
@@ -1300,10 +1298,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 
 		/* Try to obtain a transition SID. */
 		isec->sclass = inode_mode_to_security_class(inode->i_mode);
-		rc = security_transition_sid(isec->task_sid,
-					     sbsec->sid,
-					     isec->sclass,
-					     &sid);
+		rc = security_transition_sid(isec->task_sid, sbsec->sid,
+					     isec->sclass, NULL, &sid);
 		if (rc)
 			goto out_unlock;
 		isec->sid = sid;
@@ -1316,10 +1312,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
 		isec->sid = sbsec->sid;
 
 		if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) {
-			struct proc_inode *proci = PROC_I(inode);
-			if (proci->pde) {
+			if (opt_dentry) {
 				isec->sclass = inode_mode_to_security_class(inode->i_mode);
-				rc = selinux_proc_get_sid(proci->pde,
+				rc = selinux_proc_get_sid(opt_dentry,
 							  isec->sclass,
 							  &sid);
 				if (rc)
@@ -1578,7 +1573,7 @@ static int may_create(struct inode *dir,
 		return rc;
 
 	if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
-		rc = security_transition_sid(sid, dsec->sid, tclass, &newsid);
+		rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid);
 		if (rc)
 			return rc;
 	}
@@ -1862,82 +1857,6 @@ static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
 	return task_has_capability(tsk, cred, cap, audit);
 }
 
-static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
-{
-	int buflen, rc;
-	char *buffer, *path, *end;
-
-	rc = -ENOMEM;
-	buffer = (char *)__get_free_page(GFP_KERNEL);
-	if (!buffer)
-		goto out;
-
-	buflen = PAGE_SIZE;
-	end = buffer+buflen;
-	*--end = '\0';
-	buflen--;
-	path = end-1;
-	*path = '/';
-	while (table) {
-		const char *name = table->procname;
-		size_t namelen = strlen(name);
-		buflen -= namelen + 1;
-		if (buflen < 0)
-			goto out_free;
-		end -= namelen;
-		memcpy(end, name, namelen);
-		*--end = '/';
-		path = end;
-		table = table->parent;
-	}
-	buflen -= 4;
-	if (buflen < 0)
-		goto out_free;
-	end -= 4;
-	memcpy(end, "/sys", 4);
-	path = end;
-	rc = security_genfs_sid("proc", path, tclass, sid);
-out_free:
-	free_page((unsigned long)buffer);
-out:
-	return rc;
-}
-
-static int selinux_sysctl(ctl_table *table, int op)
-{
-	int error = 0;
-	u32 av;
-	u32 tsid, sid;
-	int rc;
-
-	sid = current_sid();
-
-	rc = selinux_sysctl_get_sid(table, (op == 0001) ?
-				    SECCLASS_DIR : SECCLASS_FILE, &tsid);
-	if (rc) {
-		/* Default to the well-defined sysctl SID. */
-		tsid = SECINITSID_SYSCTL;
-	}
-
-	/* The op values are "defined" in sysctl.c, thereby creating
-	 * a bad coupling between this module and sysctl.c */
-	if (op == 001) {
-		error = avc_has_perm(sid, tsid,
-				     SECCLASS_DIR, DIR__SEARCH, NULL);
-	} else {
-		av = 0;
-		if (op & 004)
-			av |= FILE__READ;
-		if (op & 002)
-			av |= FILE__WRITE;
-		if (av)
-			error = avc_has_perm(sid, tsid,
-					     SECCLASS_FILE, av, NULL);
-	}
-
-	return error;
-}
-
 static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
 	const struct cred *cred = current_cred();
@@ -2060,7 +1979,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
 	} else {
 		/* Check for a default transition on this program. */
 		rc = security_transition_sid(old_tsec->sid, isec->sid,
-					     SECCLASS_PROCESS, &new_tsec->sid);
+					     SECCLASS_PROCESS, NULL,
+					     &new_tsec->sid);
 		if (rc)
 			return rc;
 	}
@@ -2443,6 +2363,91 @@ out:
 	return rc;
 }
 
+static int selinux_sb_remount(struct super_block *sb, void *data)
+{
+	int rc, i, *flags;
+	struct security_mnt_opts opts;
+	char *secdata, **mount_options;
+	struct superblock_security_struct *sbsec = sb->s_security;
+
+	if (!(sbsec->flags & SE_SBINITIALIZED))
+		return 0;
+
+	if (!data)
+		return 0;
+
+	if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
+		return 0;
+
+	security_init_mnt_opts(&opts);
+	secdata = alloc_secdata();
+	if (!secdata)
+		return -ENOMEM;
+	rc = selinux_sb_copy_data(data, secdata);
+	if (rc)
+		goto out_free_secdata;
+
+	rc = selinux_parse_opts_str(secdata, &opts);
+	if (rc)
+		goto out_free_secdata;
+
+	mount_options = opts.mnt_opts;
+	flags = opts.mnt_opts_flags;
+
+	for (i = 0; i < opts.num_mnt_opts; i++) {
+		u32 sid;
+		size_t len;
+
+		if (flags[i] == SE_SBLABELSUPP)
+			continue;
+		len = strlen(mount_options[i]);
+		rc = security_context_to_sid(mount_options[i], len, &sid);
+		if (rc) {
+			printk(KERN_WARNING "SELinux: security_context_to_sid"
+			       "(%s) failed for (dev %s, type %s) errno=%d\n",
+			       mount_options[i], sb->s_id, sb->s_type->name, rc);
+			goto out_free_opts;
+		}
+		rc = -EINVAL;
+		switch (flags[i]) {
+		case FSCONTEXT_MNT:
+			if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid))
+				goto out_bad_option;
+			break;
+		case CONTEXT_MNT:
+			if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid))
+				goto out_bad_option;
+			break;
+		case ROOTCONTEXT_MNT: {
+			struct inode_security_struct *root_isec;
+			root_isec = sb->s_root->d_inode->i_security;
+
+			if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid))
+				goto out_bad_option;
+			break;
+		}
+		case DEFCONTEXT_MNT:
+			if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid))
+				goto out_bad_option;
+			break;
+		default:
+			goto out_free_opts;
+		}
+	}
+
+	rc = 0;
+out_free_opts:
+	security_free_mnt_opts(&opts);
+out_free_secdata:
+	free_secdata(secdata);
+	return rc;
+out_bad_option:
+	printk(KERN_WARNING "SELinux: unable to change security options "
+	       "during remount (dev %s, type=%s)\n", sb->s_id,
+	       sb->s_type->name);
+	goto out_free_opts;
+}
+
 static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
 {
 	const struct cred *cred = current_cred();
@@ -2509,8 +2514,8 @@ static void selinux_inode_free_security(struct inode *inode)
 }
 
 static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
-				       char **name, void **value,
-				       size_t *len)
+				       const struct qstr *qstr, char **name,
+				       void **value, size_t *len)
 {
 	const struct task_security_struct *tsec = current_security();
 	struct inode_security_struct *dsec;
@@ -2531,7 +2536,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
 	else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
 		rc = security_transition_sid(sid, dsec->sid,
 					     inode_mode_to_security_class(inode->i_mode),
-					     &newsid);
+					     qstr, &newsid);
 		if (rc) {
 			printk(KERN_WARNING "%s:  "
 			       "security_transition_sid failed, rc=%d (dev=%s "
@@ -2932,16 +2937,47 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
 			      unsigned long arg)
 {
 	const struct cred *cred = current_cred();
-	u32 av = 0;
+	int error = 0;
 
-	if (_IOC_DIR(cmd) & _IOC_WRITE)
-		av |= FILE__WRITE;
-	if (_IOC_DIR(cmd) & _IOC_READ)
-		av |= FILE__READ;
-	if (!av)
-		av = FILE__IOCTL;
+	switch (cmd) {
+	case FIONREAD:
+	/* fall through */
+	case FIBMAP:
+	/* fall through */
+	case FIGETBSZ:
+	/* fall through */
+	case EXT2_IOC_GETFLAGS:
+	/* fall through */
+	case EXT2_IOC_GETVERSION:
+		error = file_has_perm(cred, file, FILE__GETATTR);
+		break;
 
-	return file_has_perm(cred, file, av);
+	case EXT2_IOC_SETFLAGS:
+	/* fall through */
+	case EXT2_IOC_SETVERSION:
+		error = file_has_perm(cred, file, FILE__SETATTR);
+		break;
+
+	/* sys_ioctl() checks */
+	case FIONBIO:
+	/* fall through */
+	case FIOASYNC:
+		error = file_has_perm(cred, file, 0);
+		break;
+
+	case KDSKBENT:
+	case KDSKBSENT:
+		error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG,
+					    SECURITY_CAP_AUDIT);
+		break;
+
+	/* default case assumes that the command will go
+	 * to the file's ioctl() function.
+	 */
+	default:
+		error = file_has_perm(cred, file, FILE__IOCTL);
+	}
+	return error;
 }
 
 static int default_noexec;
@@ -3644,9 +3680,16 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
 
 /* socket security operations */
 
-static u32 socket_sockcreate_sid(const struct task_security_struct *tsec)
+static int socket_sockcreate_sid(const struct task_security_struct *tsec,
+				 u16 secclass, u32 *socksid)
 {
-	return tsec->sockcreate_sid ? : tsec->sid;
+	if (tsec->sockcreate_sid > SECSID_NULL) {
+		*socksid = tsec->sockcreate_sid;
+		return 0;
+	}
+
+	return security_transition_sid(tsec->sid, tsec->sid, secclass, NULL,
+				       socksid);
 }
 
 static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
@@ -3670,12 +3713,16 @@ static int selinux_socket_create(int family, int type,
 	const struct task_security_struct *tsec = current_security();
 	u32 newsid;
 	u16 secclass;
+	int rc;
 
 	if (kern)
 		return 0;
 
-	newsid = socket_sockcreate_sid(tsec);
 	secclass = socket_type_to_security_class(family, type, protocol);
+	rc = socket_sockcreate_sid(tsec, secclass, &newsid);
+	if (rc)
+		return rc;
+
 	return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL);
 }
 
@@ -3687,12 +3734,16 @@ static int selinux_socket_post_create(struct socket *sock, int family,
 	struct sk_security_struct *sksec;
 	int err = 0;
 
+	isec->sclass = socket_type_to_security_class(family, type, protocol);
+
 	if (kern)
 		isec->sid = SECINITSID_KERNEL;
-	else
-		isec->sid = socket_sockcreate_sid(tsec);
+	else {
+		err = socket_sockcreate_sid(tsec, isec->sclass, &(isec->sid));
+		if (err)
+			return err;
+	}
 
-	isec->sclass = socket_type_to_security_class(family, type, protocol);
 	isec->initialized = 1;
 
 	if (sock->sk) {
@@ -4002,7 +4053,6 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 {
 	int err = 0;
 	struct sk_security_struct *sksec = sk->sk_security;
-	u32 peer_sid;
 	u32 sk_sid = sksec->sid;
 	struct common_audit_data ad;
 	char *addrp;
@@ -4021,20 +4071,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 			return err;
 	}
 
-	if (selinux_policycap_netpeer) {
-		err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
-		if (err)
-			return err;
-		err = avc_has_perm(sk_sid, peer_sid,
-				   SECCLASS_PEER, PEER__RECV, &ad);
-		if (err)
-			selinux_netlbl_err(skb, err, 0);
-	} else {
-		err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
-		if (err)
-			return err;
-		err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
-	}
+	err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
+	if (err)
+		return err;
+	err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
 
 	return err;
 }
@@ -4306,7 +4346,7 @@ static void selinux_secmark_refcount_dec(void)
 static void selinux_req_classify_flow(const struct request_sock *req,
 				      struct flowi *fl)
 {
-	fl->secid = req->secid;
+	fl->flowi_secid = req->secid;
 }
 
 static int selinux_tun_dev_create(void)
@@ -4529,9 +4569,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 				 SECCLASS_PACKET, PACKET__SEND, &ad))
 			return NF_DROP_ERR(-ECONNREFUSED);
 
-	if (selinux_policycap_netpeer)
-		if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
-			return NF_DROP_ERR(-ECONNREFUSED);
+	if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto))
+		return NF_DROP_ERR(-ECONNREFUSED);
 
 	return NF_ACCEPT;
 }
@@ -4574,27 +4613,14 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 	 * from the sending socket, otherwise use the kernel's sid */
 	sk = skb->sk;
 	if (sk == NULL) {
-		switch (family) {
-		case PF_INET:
-			if (IPCB(skb)->flags & IPSKB_FORWARDED)
-				secmark_perm = PACKET__FORWARD_OUT;
-			else
-				secmark_perm = PACKET__SEND;
-			break;
-		case PF_INET6:
-			if (IP6CB(skb)->flags & IP6SKB_FORWARDED)
-				secmark_perm = PACKET__FORWARD_OUT;
-			else
-				secmark_perm = PACKET__SEND;
-			break;
-		default:
-			return NF_DROP_ERR(-ECONNREFUSED);
-		}
-		if (secmark_perm == PACKET__FORWARD_OUT) {
+		if (skb->skb_iif) {
+			secmark_perm = PACKET__FORWARD_OUT;
 			if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
 				return NF_DROP;
-		} else
+		} else {
+			secmark_perm = PACKET__SEND;
 			peer_sid = SECINITSID_KERNEL;
+		}
 	} else {
 		struct sk_security_struct *sksec = sk->sk_security;
 		peer_sid = sksec->sid;
@@ -4669,6 +4695,7 @@ static int selinux_netlink_recv(struct sk_buff *skb, int capability)
 {
 	int err;
 	struct common_audit_data ad;
+	u32 sid;
 
 	err = cap_netlink_recv(skb, capability);
 	if (err)
@@ -4677,8 +4704,9 @@ static int selinux_netlink_recv(struct sk_buff *skb, int capability)
 	COMMON_AUDIT_DATA_INIT(&ad, CAP);
 	ad.u.cap = capability;
 
-	return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
-			    SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
+	security_task_getsecid(current, &sid);
+	return avc_has_perm(sid, sid, SECCLASS_CAPABILITY,
+			    CAP_TO_MASK(capability), &ad);
 }
 
 static int ipc_alloc_security(struct task_struct *task,
@@ -4848,7 +4876,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
 		 * message queue this message will be stored in
 		 */
 		rc = security_transition_sid(sid, isec->sid, SECCLASS_MSG,
-					     &msec->sid);
+					     NULL, &msec->sid);
 		if (rc)
 			return rc;
 	}
@@ -5402,7 +5430,6 @@ static struct security_operations selinux_ops = {
 	.ptrace_traceme =		selinux_ptrace_traceme,
 	.capget =			selinux_capget,
 	.capset =			selinux_capset,
-	.sysctl =			selinux_sysctl,
 	.capable =			selinux_capable,
 	.quotactl =			selinux_quotactl,
 	.quota_on =			selinux_quota_on,
@@ -5420,6 +5447,7 @@ static struct security_operations selinux_ops = {
 	.sb_alloc_security =		selinux_sb_alloc_security,
 	.sb_free_security =		selinux_sb_free_security,
 	.sb_copy_data =			selinux_sb_copy_data,
+	.sb_remount =			selinux_sb_remount,
 	.sb_kern_mount =		selinux_sb_kern_mount,
 	.sb_show_options =		selinux_sb_show_options,
 	.sb_statfs =			selinux_sb_statfs,
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 7ed3663..b8c5372 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -12,6 +12,10 @@
 #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
 	    "write", "associate", "unix_read", "unix_write"
 
+/*
+ * Note: The name for any socket class should be suffixed by "socket",
+ *	 and doesn't contain more than one substr of "socket".
+ */
 struct security_class_mapping secclass_map[] = {
 	{ "security",
 	  { "compute_av", "compute_create", "compute_member",
@@ -132,8 +136,7 @@ struct security_class_mapping secclass_map[] = {
 	{ "appletalk_socket",
 	  { COMMON_SOCK_PERMS, NULL } },
 	{ "packet",
-	  { "send", "recv", "relabelto", "flow_in", "flow_out",
-	    "forward_in", "forward_out", NULL } },
+	  { "send", "recv", "relabelto", "forward_in", "forward_out", NULL } },
 	{ "key",
 	  { "view", "read", "write", "search", "link", "setattr", "create",
 	    NULL } },
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 671273e..348eb00 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -8,6 +8,7 @@
 #ifndef _SELINUX_SECURITY_H_
 #define _SELINUX_SECURITY_H_
 
+#include <linux/dcache.h>
 #include <linux/magic.h>
 #include <linux/types.h>
 #include "flask.h"
@@ -28,13 +29,14 @@
 #define POLICYDB_VERSION_POLCAP		22
 #define POLICYDB_VERSION_PERMISSIVE	23
 #define POLICYDB_VERSION_BOUNDARY	24
+#define POLICYDB_VERSION_FILENAME_TRANS	25
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
 #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
 #define POLICYDB_VERSION_MAX	CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
 #else
-#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_BOUNDARY
+#define POLICYDB_VERSION_MAX	POLICYDB_VERSION_FILENAME_TRANS
 #endif
 
 /* Mask for just the mount related flags */
@@ -106,8 +108,8 @@ void security_compute_av(u32 ssid, u32 tsid,
 void security_compute_av_user(u32 ssid, u32 tsid,
 			     u16 tclass, struct av_decision *avd);
 
-int security_transition_sid(u32 ssid, u32 tsid,
-			    u16 tclass, u32 *out_sid);
+int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
+			    const struct qstr *qstr, u32 *out_sid);
 
 int security_transition_sid_user(u32 ssid, u32 tsid,
 				 u16 tclass, u32 *out_sid);
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 13128f9..b43813c 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,7 @@ void selinux_xfrm_state_free(struct xfrm_state *x);
 int selinux_xfrm_state_delete(struct xfrm_state *x);
 int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
 int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
-			struct xfrm_policy *xp, struct flowi *fl);
+			struct xfrm_policy *xp, const struct flowi *fl);
 
 /*
  * Extract the security blob from the sock (it's actually on the socket)
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index dff0c75..63ce2f9 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -14,7 +14,7 @@
  *
  * Copyright (C) 2003 Tresys Technology, LLC
  *	This program is free software; you can redistribute it and/or modify
- *  	it under the terms of the GNU General Public License as published by
+ *	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
  *
  * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
@@ -27,16 +27,16 @@ struct avtab_key {
 	u16 source_type;	/* source type */
 	u16 target_type;	/* target type */
 	u16 target_class;	/* target object class */
-#define AVTAB_ALLOWED     1
-#define AVTAB_AUDITALLOW  2
-#define AVTAB_AUDITDENY   4
-#define AVTAB_AV         (AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
-#define AVTAB_TRANSITION 16
-#define AVTAB_MEMBER     32
-#define AVTAB_CHANGE     64
-#define AVTAB_TYPE       (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
-#define AVTAB_ENABLED_OLD    0x80000000 /* reserved for used in cond_avtab */
-#define AVTAB_ENABLED    0x8000 /* reserved for used in cond_avtab */
+#define AVTAB_ALLOWED		0x0001
+#define AVTAB_AUDITALLOW	0x0002
+#define AVTAB_AUDITDENY		0x0004
+#define AVTAB_AV		(AVTAB_ALLOWED | AVTAB_AUDITALLOW | AVTAB_AUDITDENY)
+#define AVTAB_TRANSITION	0x0010
+#define AVTAB_MEMBER		0x0020
+#define AVTAB_CHANGE		0x0040
+#define AVTAB_TYPE		(AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
+#define AVTAB_ENABLED_OLD   0x80000000 /* reserved for used in cond_avtab */
+#define AVTAB_ENABLED		0x8000 /* reserved for used in cond_avtab */
 	u16 specified;	/* what field is specified */
 };
 
@@ -86,7 +86,6 @@ void avtab_cache_destroy(void);
 
 #define MAX_AVTAB_HASH_BITS 11
 #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
-#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
 
 #endif	/* _SS_AVTAB_H_ */
 
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 1f4e93c..922f8af 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -36,7 +36,6 @@ struct ebitmap {
 };
 
 #define ebitmap_length(e) ((e)->highbit)
-#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
 
 static inline unsigned int ebitmap_start_positive(struct ebitmap *e,
 						  struct ebitmap_node **n)
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 1ef8e4e..e961742 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -512,7 +512,8 @@ int mls_compute_sid(struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
-		    struct context *newcontext)
+		    struct context *newcontext,
+		    bool sock)
 {
 	struct range_trans rtr;
 	struct mls_range *r;
@@ -531,7 +532,7 @@ int mls_compute_sid(struct context *scontext,
 			return mls_range_set(newcontext, r);
 		/* Fallthrough */
 	case AVTAB_CHANGE:
-		if (tclass == policydb.process_class)
+		if ((tclass == policydb.process_class) || (sock == true))
 			/* Use the process MLS attributes. */
 			return mls_context_cpy(newcontext, scontext);
 		else
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index cd91526..037bf9d 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -49,7 +49,8 @@ int mls_compute_sid(struct context *scontext,
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
-		    struct context *newcontext);
+		    struct context *newcontext,
+		    bool sock);
 
 int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
 			 struct context *usercon);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 5736356..e7b850a 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -123,6 +123,11 @@ static struct policydb_compat_info policydb_compat[] = {
 		.sym_num	= SYM_NUM,
 		.ocon_num	= OCON_NUM,
 	},
+	{
+		.version	= POLICYDB_VERSION_FILENAME_TRANS,
+		.sym_num	= SYM_NUM,
+		.ocon_num	= OCON_NUM,
+	},
 };
 
 static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -704,6 +709,7 @@ void policydb_destroy(struct policydb *p)
 	int i;
 	struct role_allow *ra, *lra = NULL;
 	struct role_trans *tr, *ltr = NULL;
+	struct filename_trans *ft, *nft;
 
 	for (i = 0; i < SYM_NUM; i++) {
 		cond_resched();
@@ -781,6 +787,15 @@ void policydb_destroy(struct policydb *p)
 		}
 		flex_array_free(p->type_attr_map_array);
 	}
+
+	ft = p->filename_trans;
+	while (ft) {
+		nft = ft->next;
+		kfree(ft->name);
+		kfree(ft);
+		ft = nft;
+	}
+
 	ebitmap_destroy(&p->policycaps);
 	ebitmap_destroy(&p->permissive_map);
 
@@ -1788,6 +1803,76 @@ out:
 	return rc;
 }
 
+static int filename_trans_read(struct policydb *p, void *fp)
+{
+	struct filename_trans *ft, *last;
+	u32 nel, len;
+	char *name;
+	__le32 buf[4];
+	int rc, i;
+
+	if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
+		return 0;
+
+	rc = next_entry(buf, fp, sizeof(u32));
+	if (rc)
+		goto out;
+	nel = le32_to_cpu(buf[0]);
+
+	printk(KERN_ERR "%s: nel=%d\n", __func__, nel);
+
+	last = p->filename_trans;
+	while (last && last->next)
+		last = last->next;
+
+	for (i = 0; i < nel; i++) {
+		rc = -ENOMEM;
+		ft = kzalloc(sizeof(*ft), GFP_KERNEL);
+		if (!ft)
+			goto out;
+
+		/* add it to the tail of the list */
+		if (!last)
+			p->filename_trans = ft;
+		else
+			last->next = ft;
+		last = ft;
+
+		/* length of the path component string */
+		rc = next_entry(buf, fp, sizeof(u32));
+		if (rc)
+			goto out;
+		len = le32_to_cpu(buf[0]);
+
+		rc = -ENOMEM;
+		name = kmalloc(len + 1, GFP_KERNEL);
+		if (!name)
+			goto out;
+
+		ft->name = name;
+
+		/* path component string */
+		rc = next_entry(name, fp, len);
+		if (rc)
+			goto out;
+		name[len] = 0;
+
+		printk(KERN_ERR "%s: ft=%p ft->name=%p ft->name=%s\n", __func__, ft, ft->name, ft->name);
+
+		rc = next_entry(buf, fp, sizeof(u32) * 4);
+		if (rc)
+			goto out;
+
+		ft->stype = le32_to_cpu(buf[0]);
+		ft->ttype = le32_to_cpu(buf[1]);
+		ft->tclass = le32_to_cpu(buf[2]);
+		ft->otype = le32_to_cpu(buf[3]);
+	}
+	rc = 0;
+out:
+	return rc;
+}
+
 static int genfs_read(struct policydb *p, void *fp)
 {
 	int i, j, rc;
@@ -2251,6 +2336,10 @@ int policydb_read(struct policydb *p, void *fp)
 		lra = ra;
 	}
 
+	rc = filename_trans_read(p, fp);
+	if (rc)
+		goto bad;
+
 	rc = policydb_index(p);
 	if (rc)
 		goto bad;
@@ -3025,6 +3114,43 @@ static int range_write(struct policydb *p, void *fp)
 	return 0;
 }
 
+static int filename_trans_write(struct policydb *p, void *fp)
+{
+	struct filename_trans *ft;
+	u32 len, nel = 0;
+	__le32 buf[4];
+	int rc;
+
+	for (ft = p->filename_trans; ft; ft = ft->next)
+		nel++;
+
+	buf[0] = cpu_to_le32(nel);
+	rc = put_entry(buf, sizeof(u32), 1, fp);
+	if (rc)
+		return rc;
+
+	for (ft = p->filename_trans; ft; ft = ft->next) {
+		len = strlen(ft->name);
+		buf[0] = cpu_to_le32(len);
+		rc = put_entry(buf, sizeof(u32), 1, fp);
+		if (rc)
+			return rc;
+
+		rc = put_entry(ft->name, sizeof(char), len, fp);
+		if (rc)
+			return rc;
+
+		buf[0] = ft->stype;
+		buf[1] = ft->ttype;
+		buf[2] = ft->tclass;
+		buf[3] = ft->otype;
+
+		rc = put_entry(buf, sizeof(u32), 4, fp);
+		if (rc)
+			return rc;
+	}
+	return 0;
+}
 /*
  * Write the configuration data in a policy database
  * structure to a policy database binary representation
@@ -3135,6 +3261,10 @@ int policydb_write(struct policydb *p, void *fp)
 	if (rc)
 		return rc;
 
+	rc = filename_trans_write(p, fp);
+	if (rc)
+		return rc;
+
 	rc = ocontext_write(p, info, fp);
 	if (rc)
 		return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 4e3ab9d..732ea4a 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -77,6 +77,15 @@ struct role_trans {
 	struct role_trans *next;
 };
 
+struct filename_trans {
+	struct filename_trans *next;
+	u32 stype;		/* current process */
+	u32 ttype;		/* parent dir context */
+	u16 tclass;		/* class of new object */
+	const char *name;	/* last path component */
+	u32 otype;		/* expected of new object */
+};
+
 struct role_allow {
 	u32 role;		/* current role */
 	u32 new_role;		/* new role */
@@ -217,6 +226,9 @@ struct policydb {
 	/* role transitions */
 	struct role_trans *role_tr;
 
+	/* file transitions with the last path component */
+	struct filename_trans *filename_trans;
+
 	/* bools indexed by (value - 1) */
 	struct cond_bool_datum **bool_val_to_struct;
 	/* type enforcement conditional access vectors and transitions */
@@ -302,7 +314,7 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
 	return 0;
 }
 
-static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file *fp)
+static inline int put_entry(const void *buf, size_t bytes, int num, struct policy_file *fp)
 {
 	size_t len = bytes * num;
 
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index a03cfaf..3e7544d 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass)
 	return tclass;
 }
 
+/*
+ * Get kernel value for class from its policy value
+ */
+static u16 map_class(u16 pol_value)
+{
+	u16 i;
+
+	for (i = 1; i < current_mapping_size; i++) {
+		if (current_mapping[i].value == pol_value)
+			return i;
+	}
+
+	return pol_value;
+}
+
 static void map_decision(u16 tclass, struct av_decision *avd,
 			 int allow_unknown)
 {
@@ -1343,10 +1358,27 @@ out:
 	return -EACCES;
 }
 
+static void filename_compute_type(struct policydb *p, struct context *newcontext,
+				  u32 scon, u32 tcon, u16 tclass,
+				  const struct qstr *qstr)
+{
+	struct filename_trans *ft;
+	for (ft = p->filename_trans; ft; ft = ft->next) {
+		if (ft->stype == scon &&
+		    ft->ttype == tcon &&
+		    ft->tclass == tclass &&
+		    !strcmp(ft->name, qstr->name)) {
+			newcontext->type = ft->otype;
+			return;
+		}
+	}
+}
+
 static int security_compute_sid(u32 ssid,
 				u32 tsid,
 				u16 orig_tclass,
 				u32 specified,
+				const struct qstr *qstr,
 				u32 *out_sid,
 				bool kern)
 {
@@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid,
 	struct avtab_node *node;
 	u16 tclass;
 	int rc = 0;
+	bool sock;
 
 	if (!ss_initialized) {
 		switch (orig_tclass) {
@@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid,
 
 	read_lock(&policy_rwlock);
 
-	if (kern)
+	if (kern) {
 		tclass = unmap_class(orig_tclass);
-	else
+		sock = security_is_socket_class(orig_tclass);
+	} else {
 		tclass = orig_tclass;
+		sock = security_is_socket_class(map_class(tclass));
+	}
 
 	scontext = sidtab_search(&sidtab, ssid);
 	if (!scontext) {
@@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid,
 	}
 
 	/* Set the role and type to default values. */
-	if (tclass == policydb.process_class) {
+	if ((tclass == policydb.process_class) || (sock == true)) {
 		/* Use the current role and type of process. */
 		newcontext.role = scontext->role;
 		newcontext.type = scontext->type;
@@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid,
 		newcontext.type = avdatum->data;
 	}
 
+	/* if we have a qstr this is a file trans check so check those rules */
+	if (qstr)
+		filename_compute_type(&policydb, &newcontext, scontext->type,
+				      tcontext->type, tclass, qstr);
+
 	/* Check for class-specific changes. */
 	if  (tclass == policydb.process_class) {
 		if (specified & AVTAB_TRANSITION) {
@@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid,
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
+	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+			     &newcontext, sock);
 	if (rc)
 		goto out_unlock;
 
@@ -1495,22 +1537,17 @@ out:
  * if insufficient memory is available, or %0 if the new SID was
  * computed successfully.
  */
-int security_transition_sid(u32 ssid,
-			    u32 tsid,
-			    u16 tclass,
-			    u32 *out_sid)
+int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
+			    const struct qstr *qstr, u32 *out_sid)
 {
 	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-				    out_sid, true);
+				    qstr, out_sid, true);
 }
 
-int security_transition_sid_user(u32 ssid,
-				 u32 tsid,
-				 u16 tclass,
-				 u32 *out_sid)
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
 {
 	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-				    out_sid, false);
+				    NULL, out_sid, false);
 }
 
 /**
@@ -1531,8 +1568,8 @@ int security_member_sid(u32 ssid,
 			u16 tclass,
 			u32 *out_sid)
 {
-	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid,
-				    false);
+	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL,
+				    out_sid, false);
 }
 
 /**
@@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid,
 			u16 tclass,
 			u32 *out_sid)
 {
-	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid,
-				    false);
+	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
+				    out_sid, false);
 }
 
 /* Clone the SID into the new SID table. */
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index fff78d3..68178b7 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -112,7 +112,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
  */
 
 int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp,
-			struct flowi *fl)
+			const struct flowi *fl)
 {
 	u32 state_sid;
 	int rc;
@@ -135,10 +135,10 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
 
 	state_sid = x->security->ctx_sid;
 
-	if (fl->secid != state_sid)
+	if (fl->flowi_secid != state_sid)
 		return 0;
 
-	rc = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
+	rc = avc_has_perm(fl->flowi_secid, state_sid, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__SENDTO,
 			  NULL)? 0:1;
 
@@ -208,7 +208,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
 	if (!uctx)
 		goto not_from_user;
 
-	if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX)
+	if (uctx->ctx_alg != XFRM_SC_ALG_SELINUX)
 		return -EINVAL;
 
 	str_len = uctx->ctx_len;
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 129c4eb..b449cfd 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -52,13 +52,16 @@ struct socket_smack {
 struct inode_smack {
 	char		*smk_inode;	/* label of the fso */
 	char		*smk_task;	/* label of the task */
+	char		*smk_mmap;	/* label of the mmap domain */
 	struct mutex	smk_lock;	/* initialization lock */
 	int		smk_flags;	/* smack inode flags */
 };
 
 struct task_smack {
-	char		*smk_task;	/* label used for access control */
-	char		*smk_forked;	/* label when forked */
+	char			*smk_task;	/* label for access control */
+	char			*smk_forked;	/* label when forked */
+	struct list_head	smk_rules;	/* per task access rules */
+	struct mutex		smk_rules_lock;	/* lock for the rules */
 };
 
 #define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
@@ -152,12 +155,6 @@ struct smack_known {
 #define SMACK_MAGIC	0x43415d53 /* "SMAC" */
 
 /*
- * A limit on the number of entries in the lists
- * makes some of the list administration easier.
- */
-#define SMACK_LIST_MAX	10000
-
-/*
  * CIPSO defaults.
  */
 #define SMACK_CIPSO_DOI_DEFAULT		3	/* Historical */
@@ -174,9 +171,7 @@ struct smack_known {
 /*
  * Just to make the common cases easier to deal with
  */
-#define MAY_ANY		(MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
 #define MAY_ANYREAD	(MAY_READ | MAY_EXEC)
-#define MAY_ANYWRITE	(MAY_WRITE | MAY_APPEND)
 #define MAY_READWRITE	(MAY_READ | MAY_WRITE)
 #define MAY_NOT		0
 
@@ -202,7 +197,7 @@ struct inode_smack *new_inode_smack(char *);
 /*
  * These functions are in smack_access.c
  */
-int smk_access_entry(char *, char *);
+int smk_access_entry(char *, char *, struct list_head *);
 int smk_access(char *, char *, int, struct smk_audit_info *);
 int smk_curacc(char *, u32, struct smk_audit_info *);
 int smack_to_cipso(const char *, struct smack_cipso *);
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 7ba8478..86453db 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED;
  * smk_access_entry - look up matching access rule
  * @subject_label: a pointer to the subject's Smack label
  * @object_label: a pointer to the object's Smack label
+ * @rule_list: the list of rules to search
  *
  * This function looks up the subject/object pair in the
- * access rule list and returns pointer to the matching rule if found,
- * NULL otherwise.
+ * access rule list and returns the access mode. If no
+ * entry is found returns -ENOENT.
  *
  * NOTE:
  * Even though Smack labels are usually shared on smack_list
@@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED;
  * will be on the list, so checking the pointers may be a worthwhile
  * optimization.
  */
-int smk_access_entry(char *subject_label, char *object_label)
+int smk_access_entry(char *subject_label, char *object_label,
+			struct list_head *rule_list)
 {
-	u32 may = MAY_NOT;
+	int may = -ENOENT;
 	struct smack_rule *srp;
 
-	rcu_read_lock();
-	list_for_each_entry_rcu(srp, &smack_rule_list, list) {
+	list_for_each_entry_rcu(srp, rule_list, list) {
 		if (srp->smk_subject == subject_label ||
 		    strcmp(srp->smk_subject, subject_label) == 0) {
 			if (srp->smk_object == object_label ||
@@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label)
 			}
 		}
 	}
-	rcu_read_unlock();
 
 	return may;
 }
@@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label)
 int smk_access(char *subject_label, char *object_label, int request,
 	       struct smk_audit_info *a)
 {
-	u32 may = MAY_NOT;
+	int may = MAY_NOT;
 	int rc = 0;
 
 	/*
@@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request,
 	 * Beyond here an explicit relationship is required.
 	 * If the requested access is contained in the available
 	 * access (e.g. read is included in readwrite) it's
-	 * good.
-	 */
-	may = smk_access_entry(subject_label, object_label);
-	/*
-	 * This is a bit map operation.
+	 * good. A negative response from smk_access_entry()
+	 * indicates there is no entry for this pair.
 	 */
-	if ((request & may) == request)
+	rcu_read_lock();
+	may = smk_access_entry(subject_label, object_label, &smack_rule_list);
+	rcu_read_unlock();
+
+	if (may > 0 && (request & may) == request)
 		goto out_audit;
 
 	rc = -EACCES;
@@ -212,12 +213,27 @@ out_audit:
  */
 int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
 {
+	struct task_smack *tsp = current_security();
+	char *sp = smk_of_task(tsp);
+	int may;
 	int rc;
-	char *sp = smk_of_current();
 
+	/*
+	 * Check the global rule list
+	 */
 	rc = smk_access(sp, obj_label, mode, NULL);
-	if (rc == 0)
-		goto out_audit;
+	if (rc == 0) {
+		/*
+		 * If there is an entry in the task's rule list
+		 * it can further restrict access.
+		 */
+		may = smk_access_entry(sp, obj_label, &tsp->smk_rules);
+		if (may < 0)
+			goto out_audit;
+		if ((mode & may) == mode)
+			goto out_audit;
+		rc = -EACCES;
+	}
 
 	/*
 	 * Return if a specific label has been designated as the
@@ -228,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
 		goto out_audit;
 
 	if (capable(CAP_MAC_OVERRIDE))
-		return 0;
+		rc = 0;
 
 out_audit:
 #ifdef CONFIG_AUDIT
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 533bf32..23c7a6d 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -33,6 +33,7 @@
 #include <net/cipso_ipv4.h>
 #include <linux/audit.h>
 #include <linux/magic.h>
+#include <linux/dcache.h>
 #include "smack.h"
 
 #define task_security(task)	(task_cred_xxx((task), security))
@@ -84,6 +85,56 @@ struct inode_smack *new_inode_smack(char *smack)
 	return isp;
 }
 
+/**
+ * new_task_smack - allocate a task security blob
+ * @smack: a pointer to the Smack label to use in the blob
+ *
+ * Returns the new blob or NULL if there's no memory available
+ */
+static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp)
+{
+	struct task_smack *tsp;
+
+	tsp = kzalloc(sizeof(struct task_smack), gfp);
+	if (tsp == NULL)
+		return NULL;
+
+	tsp->smk_task = task;
+	tsp->smk_forked = forked;
+	INIT_LIST_HEAD(&tsp->smk_rules);
+	mutex_init(&tsp->smk_rules_lock);
+
+	return tsp;
+}
+
+/**
+ * smk_copy_rules - copy a rule set
+ * @nhead - new rules header pointer
+ * @ohead - old rules header pointer
+ *
+ * Returns 0 on success, -ENOMEM on error
+ */
+static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
+				gfp_t gfp)
+{
+	struct smack_rule *nrp;
+	struct smack_rule *orp;
+	int rc = 0;
+
+	INIT_LIST_HEAD(nhead);
+
+	list_for_each_entry_rcu(orp, ohead, list) {
+		nrp = kzalloc(sizeof(struct smack_rule), gfp);
+		if (nrp == NULL) {
+			rc = -ENOMEM;
+			break;
+		}
+		*nrp = *orp;
+		list_add_rcu(&nrp->list, nhead);
+	}
+	return rc;
+}
+
 /*
  * LSM hooks.
  * We he, that is fun!
@@ -102,23 +153,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
 {
 	int rc;
 	struct smk_audit_info ad;
-	char *sp, *tsp;
+	char *tsp;
 
 	rc = cap_ptrace_access_check(ctp, mode);
 	if (rc != 0)
 		return rc;
 
-	sp = smk_of_current();
 	tsp = smk_of_task(task_security(ctp));
 	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
 	smk_ad_setfield_u_tsk(&ad, ctp);
 
-	/* we won't log here, because rc can be overriden */
-	rc = smk_access(sp, tsp, MAY_READWRITE, NULL);
-	if (rc != 0 && capable(CAP_MAC_OVERRIDE))
-		rc = 0;
-
-	smack_log(sp, tsp, MAY_READWRITE, rc, &ad);
+	rc = smk_curacc(tsp, MAY_READWRITE, &ad);
 	return rc;
 }
 
@@ -134,23 +179,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
 {
 	int rc;
 	struct smk_audit_info ad;
-	char *sp, *tsp;
+	char *tsp;
 
 	rc = cap_ptrace_traceme(ptp);
 	if (rc != 0)
 		return rc;
 
+	tsp = smk_of_task(task_security(ptp));
 	smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
 	smk_ad_setfield_u_tsk(&ad, ptp);
 
-	sp = smk_of_current();
-	tsp = smk_of_task(task_security(ptp));
-	/* we won't log here, because rc can be overriden */
-	rc = smk_access(tsp, sp, MAY_READWRITE, NULL);
-	if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
-		rc = 0;
-
-	smack_log(tsp, sp, MAY_READWRITE, rc, &ad);
+	rc = smk_curacc(tsp, MAY_READWRITE, &ad);
 	return rc;
 }
 
@@ -463,6 +502,7 @@ static void smack_inode_free_security(struct inode *inode)
  * smack_inode_init_security - copy out the smack from an inode
  * @inode: the inode
  * @dir: unused
+ * @qstr: unused
  * @name: where to put the attribute name
  * @value: where to put the attribute value
  * @len: where to put the length of the attribute
@@ -470,11 +510,12 @@ static void smack_inode_free_security(struct inode *inode)
  * Returns 0 if it all works out, -ENOMEM if there's no memory
  */
 static int smack_inode_init_security(struct inode *inode, struct inode *dir,
-				     char **name, void **value, size_t *len)
+				     const struct qstr *qstr, char **name,
+				     void **value, size_t *len)
 {
 	char *isp = smk_of_inode(inode);
 	char *dsp = smk_of_inode(dir);
-	u32 may;
+	int may;
 
 	if (name) {
 		*name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
@@ -483,14 +524,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
 	}
 
 	if (value) {
-		may = smk_access_entry(smk_of_current(), dsp);
+		rcu_read_lock();
+		may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list);
+		rcu_read_unlock();
 
 		/*
 		 * If the access rule allows transmutation and
 		 * the directory requests transmutation then
 		 * by all means transmute.
 		 */
-		if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir))
+		if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
+		    smk_inode_transmutable(dir))
 			isp = dsp;
 
 		*value = kstrdup(isp, GFP_KERNEL);
@@ -716,7 +760,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
 	if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
 	    strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
 	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
-	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
+	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
+	    strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
 		if (!capable(CAP_MAC_ADMIN))
 			rc = -EPERM;
 		/*
@@ -773,6 +818,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
 			isp->smk_task = nsp;
 		else
 			isp->smk_task = smack_known_invalid.smk_known;
+	} else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
+		nsp = smk_import(value, size);
+		if (nsp != NULL)
+			isp->smk_mmap = nsp;
+		else
+			isp->smk_mmap = smack_known_invalid.smk_known;
 	} else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
 		isp->smk_flags |= SMK_INODE_TRANSMUTE;
 
@@ -815,7 +866,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
 	    strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
 	    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
 	    strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
-	    strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
+	    strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
+	    strcmp(name, XATTR_NAME_SMACKMMAP)) {
 		if (!capable(CAP_MAC_ADMIN))
 			rc = -EPERM;
 	} else
@@ -829,6 +881,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
 	if (rc == 0) {
 		isp = dentry->d_inode->i_security;
 		isp->smk_task = NULL;
+		isp->smk_mmap = NULL;
 	}
 
 	return rc;
@@ -1060,6 +1113,126 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
 }
 
 /**
+ * smack_file_mmap :
+ * Check permissions for a mmap operation.  The @file may be NULL, e.g.
+ * if mapping anonymous memory.
+ * @file contains the file structure for file to map (may be NULL).
+ * @reqprot contains the protection requested by the application.
+ * @prot contains the protection that will be applied by the kernel.
+ * @flags contains the operational flags.
+ * Return 0 if permission is granted.
+ */
+static int smack_file_mmap(struct file *file,
+			   unsigned long reqprot, unsigned long prot,
+			   unsigned long flags, unsigned long addr,
+			   unsigned long addr_only)
+{
+	struct smack_rule *srp;
+	struct task_smack *tsp;
+	char *sp;
+	char *msmack;
+	char *osmack;
+	struct inode_smack *isp;
+	struct dentry *dp;
+	int may;
+	int mmay;
+	int tmay;
+	int rc;
+
+	/* do DAC check on address space usage */
+	rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
+	if (rc || addr_only)
+		return rc;
+
+	if (file == NULL || file->f_dentry == NULL)
+		return 0;
+
+	dp = file->f_dentry;
+
+	if (dp->d_inode == NULL)
+		return 0;
+
+	isp = dp->d_inode->i_security;
+	if (isp->smk_mmap == NULL)
+		return 0;
+	msmack = isp->smk_mmap;
+
+	tsp = current_security();
+	sp = smk_of_current();
+	rc = 0;
+
+	rcu_read_lock();
+	/*
+	 * For each Smack rule associated with the subject
+	 * label verify that the SMACK64MMAP also has access
+	 * to that rule's object label.
+	 *
+	 * Because neither of the labels comes
+	 * from the networking code it is sufficient
+	 * to compare pointers.
+	 */
+	list_for_each_entry_rcu(srp, &smack_rule_list, list) {
+		if (srp->smk_subject != sp)
+			continue;
+
+		osmack = srp->smk_object;
+		/*
+		 * Matching labels always allows access.
+		 */
+		if (msmack == osmack)
+			continue;
+		/*
+		 * If there is a matching local rule take
+		 * that into account as well.
+		 */
+		may = smk_access_entry(srp->smk_subject, osmack,
+					&tsp->smk_rules);
+		if (may == -ENOENT)
+			may = srp->smk_access;
+		else
+			may &= srp->smk_access;
+		/*
+		 * If may is zero the SMACK64MMAP subject can't
+		 * possibly have less access.
+		 */
+		if (may == 0)
+			continue;
+
+		/*
+		 * Fetch the global list entry.
+		 * If there isn't one a SMACK64MMAP subject
+		 * can't have as much access as current.
+		 */
+		mmay = smk_access_entry(msmack, osmack, &smack_rule_list);
+		if (mmay == -ENOENT) {
+			rc = -EACCES;
+			break;
+		}
+		/*
+		 * If there is a local entry it modifies the
+		 * potential access, too.
+		 */
+		tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules);
+		if (tmay != -ENOENT)
+			mmay &= tmay;
+
+		/*
+		 * If there is any access available to current that is
+		 * not available to a SMACK64MMAP subject
+		 * deny access.
+		 */
+		if ((may | mmay) != mmay) {
+			rc = -EACCES;
+			break;
+		}
+	}
+
+	rcu_read_unlock();
+
+	return rc;
+}
+
+/**
  * smack_file_set_fowner - set the file security blob value
  * @file: object in question
  *
@@ -1095,6 +1268,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
 	 * struct fown_struct is never outside the context of a struct file
 	 */
 	file = container_of(fown, struct file, f_owner);
+
 	/* we don't log here as rc can be overriden */
 	rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
 	if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
@@ -1145,9 +1319,14 @@ static int smack_file_receive(struct file *file)
  */
 static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 {
-	cred->security = kzalloc(sizeof(struct task_smack), gfp);
-	if (cred->security == NULL)
+	struct task_smack *tsp;
+
+	tsp = new_task_smack(NULL, NULL, gfp);
+	if (tsp == NULL)
 		return -ENOMEM;
+
+	cred->security = tsp;
+
 	return 0;
 }
 
@@ -1156,13 +1335,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
  * smack_cred_free - "free" task-level security credentials
  * @cred: the credentials in question
  *
- * Smack isn't using copies of blobs. Everyone
- * points to an immutable list. The blobs never go away.
- * There is no leak here.
  */
 static void smack_cred_free(struct cred *cred)
 {
-	kfree(cred->security);
+	struct task_smack *tsp = cred->security;
+	struct smack_rule *rp;
+	struct list_head *l;
+	struct list_head *n;
+
+	if (tsp == NULL)
+		return;
+	cred->security = NULL;
+
+	list_for_each_safe(l, n, &tsp->smk_rules) {
+		rp = list_entry(l, struct smack_rule, list);
+		list_del(&rp->list);
+		kfree(rp);
+	}
+	kfree(tsp);
 }
 
 /**
@@ -1178,13 +1368,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
 {
 	struct task_smack *old_tsp = old->security;
 	struct task_smack *new_tsp;
+	int rc;
 
-	new_tsp = kzalloc(sizeof(struct task_smack), gfp);
+	new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp);
 	if (new_tsp == NULL)
 		return -ENOMEM;
 
-	new_tsp->smk_task = old_tsp->smk_task;
-	new_tsp->smk_forked = old_tsp->smk_task;
+	rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp);
+	if (rc != 0)
+		return rc;
+
 	new->security = new_tsp;
 	return 0;
 }
@@ -1203,6 +1396,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
 
 	new_tsp->smk_task = old_tsp->smk_task;
 	new_tsp->smk_forked = old_tsp->smk_task;
+	mutex_init(&new_tsp->smk_rules_lock);
+	INIT_LIST_HEAD(&new_tsp->smk_rules);
+
+
+	/* cbs copy rule list */
 }
 
 /**
@@ -2419,6 +2617,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
 			}
 		}
 		isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
+		isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
 
 		dput(dp);
 		break;
@@ -2478,6 +2677,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
 static int smack_setprocattr(struct task_struct *p, char *name,
 			     void *value, size_t size)
 {
+	int rc;
 	struct task_smack *tsp;
 	struct task_smack *oldtsp;
 	struct cred *new;
@@ -2513,13 +2713,16 @@ static int smack_setprocattr(struct task_struct *p, char *name,
 	new = prepare_creds();
 	if (new == NULL)
 		return -ENOMEM;
-	tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL);
+
+	tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL);
 	if (tsp == NULL) {
 		kfree(new);
 		return -ENOMEM;
 	}
-	tsp->smk_task = newsmack;
-	tsp->smk_forked = oldtsp->smk_forked;
+	rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL);
+	if (rc != 0)
+		return rc;
+
 	new->security = tsp;
 	commit_creds(new);
 	return size;
@@ -3221,6 +3424,7 @@ struct security_operations smack_ops = {
 	.file_ioctl = 			smack_file_ioctl,
 	.file_lock = 			smack_file_lock,
 	.file_fcntl = 			smack_file_fcntl,
+	.file_mmap =			smack_file_mmap,
 	.file_set_fowner = 		smack_file_set_fowner,
 	.file_send_sigiotask = 		smack_file_send_sigiotask,
 	.file_receive = 		smack_file_receive,
@@ -3334,23 +3538,20 @@ static __init int smack_init(void)
 	struct cred *cred;
 	struct task_smack *tsp;
 
-	tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL);
+	if (!security_module_enable(&smack_ops))
+		return 0;
+
+	tsp = new_task_smack(smack_known_floor.smk_known,
+				smack_known_floor.smk_known, GFP_KERNEL);
 	if (tsp == NULL)
 		return -ENOMEM;
 
-	if (!security_module_enable(&smack_ops)) {
-		kfree(tsp);
-		return 0;
-	}
-
 	printk(KERN_INFO "Smack:  Initializing.\n");
 
 	/*
 	 * Set the security state for the initial task.
 	 */
 	cred = (struct cred *) current->cred;
-	tsp->smk_forked = smack_known_floor.smk_known;
-	tsp->smk_task = smack_known_floor.smk_known;
 	cred->security = tsp;
 
 	/* initialize the smack_know_list */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 362d5ed..90d1bba 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -43,6 +43,7 @@ enum smk_inos {
 	SMK_NETLBLADDR	= 8,	/* single label hosts */
 	SMK_ONLYCAP	= 9,	/* the only "capable" label */
 	SMK_LOGGING	= 10,	/* logging */
+	SMK_LOAD_SELF	= 11,	/* task specific rules */
 };
 
 /*
@@ -135,104 +136,30 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
 #define SMK_NETLBLADDRMIN	9
 #define SMK_NETLBLADDRMAX	42
 
-/*
- * Seq_file read operations for /smack/load
- */
-
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
-{
-	if (*pos == SEQ_READ_FINISHED)
-		return NULL;
-	if (list_empty(&smack_rule_list))
-		return NULL;
-	return smack_rule_list.next;
-}
-
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-	struct list_head *list = v;
-
-	if (list_is_last(list, &smack_rule_list)) {
-		*pos = SEQ_READ_FINISHED;
-		return NULL;
-	}
-	return list->next;
-}
-
-static int load_seq_show(struct seq_file *s, void *v)
-{
-	struct list_head *list = v;
-	struct smack_rule *srp =
-		 list_entry(list, struct smack_rule, list);
-
-	seq_printf(s, "%s %s", (char *)srp->smk_subject,
-		   (char *)srp->smk_object);
-
-	seq_putc(s, ' ');
-
-	if (srp->smk_access & MAY_READ)
-		seq_putc(s, 'r');
-	if (srp->smk_access & MAY_WRITE)
-		seq_putc(s, 'w');
-	if (srp->smk_access & MAY_EXEC)
-		seq_putc(s, 'x');
-	if (srp->smk_access & MAY_APPEND)
-		seq_putc(s, 'a');
-	if (srp->smk_access & MAY_TRANSMUTE)
-		seq_putc(s, 't');
-	if (srp->smk_access == 0)
-		seq_putc(s, '-');
-
-	seq_putc(s, '\n');
-
-	return 0;
-}
-
-static void load_seq_stop(struct seq_file *s, void *v)
-{
-	/* No-op */
-}
-
-static const struct seq_operations load_seq_ops = {
-	.start = load_seq_start,
-	.next  = load_seq_next,
-	.show  = load_seq_show,
-	.stop  = load_seq_stop,
-};
-
-/**
- * smk_open_load - open() for /smack/load
- * @inode: inode structure representing file
- * @file: "load" file pointer
- *
- * For reading, use load_seq_* seq_file reading operations.
- */
-static int smk_open_load(struct inode *inode, struct file *file)
-{
-	return seq_open(file, &load_seq_ops);
-}
-
 /**
  * smk_set_access - add a rule to the rule list
  * @srp: the new rule to add
+ * @rule_list: the list of rules
+ * @rule_lock: the rule list lock
  *
  * 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)
+static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
+				struct mutex *rule_lock)
 {
 	struct smack_rule *sp;
-	int ret = 0;
-	int found;
-	mutex_lock(&smack_list_lock);
+	int found = 0;
 
-	found = 0;
-	list_for_each_entry_rcu(sp, &smack_rule_list, list) {
+	mutex_lock(rule_lock);
+
+	list_for_each_entry_rcu(sp, rule_list, list) {
 		if (sp->smk_subject == srp->smk_subject &&
 		    sp->smk_object == srp->smk_object) {
 			found = 1;
@@ -241,19 +168,21 @@ static int smk_set_access(struct smack_rule *srp)
 		}
 	}
 	if (found == 0)
-		list_add_rcu(&srp->list, &smack_rule_list);
+		list_add_rcu(&srp->list, rule_list);
 
-	mutex_unlock(&smack_list_lock);
+	mutex_unlock(rule_lock);
 
-	return ret;
+	return found;
 }
 
 /**
- * smk_write_load - write() for /smack/load
+ * smk_write_load_list - write() for any /smack/load
  * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
  * @ppos: where to start - must be 0
+ * @rule_list: the list of rules to write to
+ * @rule_lock: lock for the rule list
  *
  * Get one smack access rule from above.
  * The format is exactly:
@@ -263,21 +192,19 @@ static int smk_set_access(struct smack_rule *srp)
  *
  * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
  */
-static ssize_t smk_write_load(struct file *file, const char __user *buf,
-			      size_t count, loff_t *ppos)
+static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
+				size_t count, loff_t *ppos,
+				struct list_head *rule_list,
+				struct mutex *rule_lock)
 {
 	struct smack_rule *rule;
 	char *data;
 	int rc = -EINVAL;
 
 	/*
-	 * Must have privilege.
 	 * No partial writes.
 	 * Enough data must be present.
 	 */
-	if (!capable(CAP_MAC_ADMIN))
-		return -EPERM;
-
 	if (*ppos != 0)
 		return -EINVAL;
 	/*
@@ -372,11 +299,13 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
 		goto out_free_rule;
 	}
 
-	rc = smk_set_access(rule);
-
-	if (!rc)
-		rc = count;
-	goto out;
+	rc = count;
+	/*
+	 * 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))
+		goto out;
 
 out_free_rule:
 	kfree(rule);
@@ -385,6 +314,108 @@ out:
 	return rc;
 }
 
+
+/*
+ * Seq_file read operations for /smack/load
+ */
+
+static void *load_seq_start(struct seq_file *s, loff_t *pos)
+{
+	if (*pos == SEQ_READ_FINISHED)
+		return NULL;
+	if (list_empty(&smack_rule_list))
+		return NULL;
+	return smack_rule_list.next;
+}
+
+static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct list_head *list = v;
+
+	if (list_is_last(list, &smack_rule_list)) {
+		*pos = SEQ_READ_FINISHED;
+		return NULL;
+	}
+	return list->next;
+}
+
+static int load_seq_show(struct seq_file *s, void *v)
+{
+	struct list_head *list = v;
+	struct smack_rule *srp =
+		 list_entry(list, struct smack_rule, list);
+
+	seq_printf(s, "%s %s", (char *)srp->smk_subject,
+		   (char *)srp->smk_object);
+
+	seq_putc(s, ' ');
+
+	if (srp->smk_access & MAY_READ)
+		seq_putc(s, 'r');
+	if (srp->smk_access & MAY_WRITE)
+		seq_putc(s, 'w');
+	if (srp->smk_access & MAY_EXEC)
+		seq_putc(s, 'x');
+	if (srp->smk_access & MAY_APPEND)
+		seq_putc(s, 'a');
+	if (srp->smk_access & MAY_TRANSMUTE)
+		seq_putc(s, 't');
+	if (srp->smk_access == 0)
+		seq_putc(s, '-');
+
+	seq_putc(s, '\n');
+
+	return 0;
+}
+
+static void load_seq_stop(struct seq_file *s, void *v)
+{
+	/* No-op */
+}
+
+static const struct seq_operations load_seq_ops = {
+	.start = load_seq_start,
+	.next  = load_seq_next,
+	.show  = load_seq_show,
+	.stop  = load_seq_stop,
+};
+
+/**
+ * smk_open_load - open() for /smack/load
+ * @inode: inode structure representing file
+ * @file: "load" file pointer
+ *
+ * For reading, use load_seq_* seq_file reading operations.
+ */
+static int smk_open_load(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &load_seq_ops);
+}
+
+/**
+ * smk_write_load - write() for /smack/load
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ *
+ */
+static ssize_t smk_write_load(struct file *file, const char __user *buf,
+			      size_t count, loff_t *ppos)
+{
+
+	/*
+	 * Must have privilege.
+	 * No partial writes.
+	 * Enough data must be present.
+	 */
+	if (!capable(CAP_MAC_ADMIN))
+		return -EPERM;
+
+	return smk_write_load_list(file, buf, count, ppos, &smack_rule_list,
+					&smack_list_lock);
+}
+
 static const struct file_operations smk_load_ops = {
 	.open           = smk_open_load,
 	.read		= seq_read,
@@ -1288,6 +1319,112 @@ static const struct file_operations smk_logging_ops = {
 	.write		= smk_write_logging,
 	.llseek		= default_llseek,
 };
+
+/*
+ * Seq_file read operations for /smack/load-self
+ */
+
+static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct task_smack *tsp = current_security();
+
+	if (*pos == SEQ_READ_FINISHED)
+		return NULL;
+	if (list_empty(&tsp->smk_rules))
+		return NULL;
+	return tsp->smk_rules.next;
+}
+
+static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct task_smack *tsp = current_security();
+	struct list_head *list = v;
+
+	if (list_is_last(list, &tsp->smk_rules)) {
+		*pos = SEQ_READ_FINISHED;
+		return NULL;
+	}
+	return list->next;
+}
+
+static int load_self_seq_show(struct seq_file *s, void *v)
+{
+	struct list_head *list = v;
+	struct smack_rule *srp =
+		 list_entry(list, struct smack_rule, list);
+
+	seq_printf(s, "%s %s", (char *)srp->smk_subject,
+		   (char *)srp->smk_object);
+
+	seq_putc(s, ' ');
+
+	if (srp->smk_access & MAY_READ)
+		seq_putc(s, 'r');
+	if (srp->smk_access & MAY_WRITE)
+		seq_putc(s, 'w');
+	if (srp->smk_access & MAY_EXEC)
+		seq_putc(s, 'x');
+	if (srp->smk_access & MAY_APPEND)
+		seq_putc(s, 'a');
+	if (srp->smk_access & MAY_TRANSMUTE)
+		seq_putc(s, 't');
+	if (srp->smk_access == 0)
+		seq_putc(s, '-');
+
+	seq_putc(s, '\n');
+
+	return 0;
+}
+
+static void load_self_seq_stop(struct seq_file *s, void *v)
+{
+	/* No-op */
+}
+
+static const struct seq_operations load_self_seq_ops = {
+	.start = load_self_seq_start,
+	.next  = load_self_seq_next,
+	.show  = load_self_seq_show,
+	.stop  = load_self_seq_stop,
+};
+
+
+/**
+ * smk_open_load_self - open() for /smack/load-self
+ * @inode: inode structure representing file
+ * @file: "load" file pointer
+ *
+ * For reading, use load_seq_* seq_file reading operations.
+ */
+static int smk_open_load_self(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &load_self_seq_ops);
+}
+
+/**
+ * smk_write_load_self - write() for /smack/load-self
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ *
+ */
+static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
+			      size_t count, loff_t *ppos)
+{
+	struct task_smack *tsp = current_security();
+
+	return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules,
+					&tsp->smk_rules_lock);
+}
+
+static const struct file_operations smk_load_self_ops = {
+	.open           = smk_open_load_self,
+	.read		= seq_read,
+	.llseek         = seq_lseek,
+	.write		= smk_write_load_self,
+	.release        = seq_release,
+};
 /**
  * smk_fill_super - fill the /smackfs superblock
  * @sb: the empty superblock
@@ -1304,23 +1441,26 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
 	struct inode *root_inode;
 
 	static struct tree_descr smack_files[] = {
-		[SMK_LOAD]	=
-			{"load", &smk_load_ops, S_IRUGO|S_IWUSR},
-		[SMK_CIPSO]	=
-			{"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
-		[SMK_DOI]	=
-			{"doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
-		[SMK_DIRECT]	=
-			{"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
-		[SMK_AMBIENT]	=
-			{"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
-		[SMK_NETLBLADDR] =
-			{"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
-		[SMK_ONLYCAP]	=
-			{"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
-		[SMK_LOGGING]	=
-			{"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
-		/* last one */ {""}
+		[SMK_LOAD] = {
+			"load", &smk_load_ops, S_IRUGO|S_IWUSR},
+		[SMK_CIPSO] = {
+			"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
+		[SMK_DOI] = {
+			"doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
+		[SMK_DIRECT] = {
+			"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
+		[SMK_AMBIENT] = {
+			"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
+		[SMK_NETLBLADDR] = {
+			"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
+		[SMK_ONLYCAP] = {
+			"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
+		[SMK_LOGGING] = {
+			"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
+		[SMK_LOAD_SELF] = {
+			"load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
+		/* last one */
+			{""}
 	};
 
 	rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 9d32f18..cb09f1f 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -927,7 +927,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 				 struct path *path, const int flag)
 {
 	const u8 acc_mode = ACC_MODE(flag);
-	int error = -ENOMEM;
+	int error = 0;
 	struct tomoyo_path_info buf;
 	struct tomoyo_request_info r;
 	int idx;
@@ -938,9 +938,6 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
 	buf.name = NULL;
 	r.mode = TOMOYO_CONFIG_DISABLED;
 	idx = tomoyo_read_lock();
-	if (!tomoyo_get_realpath(&buf, path))
-		goto out;
-	error = 0;
 	/*
 	 * If the filename is specified by "deny_rewrite" keyword,
 	 * we need to check "allow_rewrite" permission when the filename is not
diff --git a/sound/Kconfig b/sound/Kconfig
index fcad760..1fef141 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -97,6 +97,8 @@ source "sound/sh/Kconfig"
 # here assuming USB is defined before ALSA
 source "sound/usb/Kconfig"
 
+source "sound/firewire/Kconfig"
+
 # the following will depend on the order of config.
 # here assuming PCMCIA is defined before ALSA
 source "sound/pcmcia/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index ec467de..ce9132b 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
-	sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
+	firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
 obj-$(CONFIG_SND_AOA) += aoa/
 
 # This one must be compilable even if sound is configured out
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index 7c1fc64..d0cead3 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -210,6 +210,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 
 	if (mask & ISR_RXINTR) {
 		struct aaci_runtime *aacirun = &aaci->capture;
+		bool period_elapsed = false;
 		void *ptr;
 
 		if (!aacirun->substream || !aacirun->start) {
@@ -222,15 +223,12 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 
 		ptr = aacirun->ptr;
 		do {
-			unsigned int len = aacirun->fifosz;
+			unsigned int len = aacirun->fifo_bytes;
 			u32 val;
 
 			if (aacirun->bytes <= 0) {
 				aacirun->bytes += aacirun->period;
-				aacirun->ptr = ptr;
-				spin_unlock(&aacirun->lock);
-				snd_pcm_period_elapsed(aacirun->substream);
-				spin_lock(&aacirun->lock);
+				period_elapsed = true;
 			}
 			if (!(aacirun->cr & CR_EN))
 				break;
@@ -260,6 +258,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 		aacirun->ptr = ptr;
 
 		spin_unlock(&aacirun->lock);
+
+		if (period_elapsed)
+			snd_pcm_period_elapsed(aacirun->substream);
 	}
 
 	if (mask & ISR_URINTR) {
@@ -269,6 +270,7 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 
 	if (mask & ISR_TXINTR) {
 		struct aaci_runtime *aacirun = &aaci->playback;
+		bool period_elapsed = false;
 		void *ptr;
 
 		if (!aacirun->substream || !aacirun->start) {
@@ -281,15 +283,12 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 
 		ptr = aacirun->ptr;
 		do {
-			unsigned int len = aacirun->fifosz;
+			unsigned int len = aacirun->fifo_bytes;
 			u32 val;
 
 			if (aacirun->bytes <= 0) {
 				aacirun->bytes += aacirun->period;
-				aacirun->ptr = ptr;
-				spin_unlock(&aacirun->lock);
-				snd_pcm_period_elapsed(aacirun->substream);
-				spin_lock(&aacirun->lock);
+				period_elapsed = true;
 			}
 			if (!(aacirun->cr & CR_EN))
 				break;
@@ -319,6 +318,9 @@ static void aaci_fifo_irq(struct aaci *aaci, int channel, u32 mask)
 		aacirun->ptr = ptr;
 
 		spin_unlock(&aacirun->lock);
+
+		if (period_elapsed)
+			snd_pcm_period_elapsed(aacirun->substream);
 	}
 }
 
@@ -361,7 +363,7 @@ static struct snd_pcm_hardware aaci_hw_info = {
 
 	/* rates are setup from the AC'97 codec */
 	.channels_min		= 2,
-	.channels_max		= 6,
+	.channels_max		= 2,
 	.buffer_bytes_max	= 64 * 1024,
 	.period_bytes_min	= 256,
 	.period_bytes_max	= PAGE_SIZE,
@@ -369,12 +371,46 @@ static struct snd_pcm_hardware aaci_hw_info = {
 	.periods_max		= PAGE_SIZE / 16,
 };
 
-static int __aaci_pcm_open(struct aaci *aaci,
-			   struct snd_pcm_substream *substream,
-			   struct aaci_runtime *aacirun)
+/*
+ * We can support two and four channel audio.  Unfortunately
+ * six channel audio requires a non-standard channel ordering:
+ *   2 -> FL(3), FR(4)
+ *   4 -> FL(3), FR(4), SL(7), SR(8)
+ *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
+ *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
+ * This requires an ALSA configuration file to correct.
+ */
+static int aaci_rule_channels(struct snd_pcm_hw_params *p,
+	struct snd_pcm_hw_rule *rule)
+{
+	static unsigned int channel_list[] = { 2, 4, 6 };
+	struct aaci *aaci = rule->private;
+	unsigned int mask = 1 << 0, slots;
+
+	/* pcms[0] is the our 5.1 PCM instance. */
+	slots = aaci->ac97_bus->pcms[0].r[0].slots;
+	if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+		mask |= 1 << 1;
+		if (slots & (1 << AC97_SLOT_LFE))
+			mask |= 1 << 2;
+	}
+
+	return snd_interval_list(hw_param_interval(p, rule->var),
+				 ARRAY_SIZE(channel_list), channel_list, mask);
+}
+
+static int aaci_pcm_open(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	int ret;
+	struct aaci *aaci = substream->private_data;
+	struct aaci_runtime *aacirun;
+	int ret = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		aacirun = &aaci->playback;
+	} else {
+		aacirun = &aaci->capture;
+	}
 
 	aacirun->substream = substream;
 	runtime->private_data = aacirun;
@@ -382,27 +418,37 @@ static int __aaci_pcm_open(struct aaci *aaci,
 	runtime->hw.rates = aacirun->pcm->rates;
 	snd_pcm_limit_hw_rates(runtime);
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
-	    aacirun->pcm->r[1].slots)
-		snd_ac97_pcm_double_rate_rules(runtime);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		runtime->hw.channels_max = 6;
+
+		/* Add rule describing channel dependency. */
+		ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+					  SNDRV_PCM_HW_PARAM_CHANNELS,
+					  aaci_rule_channels, aaci,
+					  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+		if (ret)
+			return ret;
+
+		if (aacirun->pcm->r[1].slots)
+			snd_ac97_pcm_double_rate_rules(runtime);
+	}
 
 	/*
-	 * FIXME: ALSA specifies fifo_size in bytes.  If we're in normal
-	 * mode, each 32-bit word contains one sample.  If we're in
-	 * compact mode, each 32-bit word contains two samples, effectively
-	 * halving the FIFO size.  However, we don't know for sure which
-	 * we'll be using at this point.  We set this to the lower limit.
+	 * ALSA wants the byte-size of the FIFOs.  As we only support
+	 * 16-bit samples, this is twice the FIFO depth irrespective
+	 * of whether it's in compact mode or not.
 	 */
-	runtime->hw.fifo_size = aaci->fifosize * 2;
-
-	ret = request_irq(aaci->dev->irq[0], aaci_irq, IRQF_SHARED|IRQF_DISABLED,
-			  DRIVER_NAME, aaci);
-	if (ret)
-		goto out;
-
-	return 0;
+	runtime->hw.fifo_size = aaci->fifo_depth * 2;
+
+	mutex_lock(&aaci->irq_lock);
+	if (!aaci->users++) {
+		ret = request_irq(aaci->dev->irq[0], aaci_irq,
+			   IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci);
+		if (ret != 0)
+			aaci->users--;
+	}
+	mutex_unlock(&aaci->irq_lock);
 
- out:
 	return ret;
 }
 
@@ -418,7 +464,11 @@ static int aaci_pcm_close(struct snd_pcm_substream *substream)
 	WARN_ON(aacirun->cr & CR_EN);
 
 	aacirun->substream = NULL;
-	free_irq(aaci->dev->irq[0], aaci);
+
+	mutex_lock(&aaci->irq_lock);
+	if (!--aaci->users)
+		free_irq(aaci->dev->irq[0], aaci);
+	mutex_unlock(&aaci->irq_lock);
 
 	return 0;
 }
@@ -444,12 +494,21 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
 	return 0;
 }
 
+/* Channel to slot mask */
+static const u32 channels_to_slotmask[] = {
+	[2] = CR_SL3 | CR_SL4,
+	[4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
+	[6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
+};
+
 static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
-			      struct aaci_runtime *aacirun,
 			      struct snd_pcm_hw_params *params)
 {
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+	unsigned int channels = params_channels(params);
+	unsigned int rate = params_rate(params);
+	int dbl = rate > 48000;
 	int err;
-	struct aaci *aaci = substream->private_data;
 
 	aaci_pcm_hw_free(substream);
 	if (aacirun->pcm_open) {
@@ -457,22 +516,28 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
 		aacirun->pcm_open = 0;
 	}
 
+	/* channels is already limited to 2, 4, or 6 by aaci_rule_channels */
+	if (dbl && channels != 2)
+		return -EINVAL;
+
 	err = snd_pcm_lib_malloc_pages(substream,
 				       params_buffer_bytes(params));
 	if (err >= 0) {
-		unsigned int rate = params_rate(params);
-		int dbl = rate > 48000;
+		struct aaci *aaci = substream->private_data;
 
-		err = snd_ac97_pcm_open(aacirun->pcm, rate,
-					params_channels(params),
+		err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
 					aacirun->pcm->r[dbl].slots);
 
 		aacirun->pcm_open = err == 0;
 		aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
-		aacirun->fifosz = aaci->fifosize * 4;
-
-		if (aacirun->cr & CR_COMPACT)
-			aacirun->fifosz >>= 1;
+		aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
+
+		/*
+		 * fifo_bytes is the number of bytes we transfer to/from
+		 * the FIFO, including padding.  So that's x4.  As we're
+		 * in compact mode, the FIFO is half the size.
+		 */
+		aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;
 	}
 
 	return err;
@@ -483,11 +548,11 @@ static int aaci_pcm_prepare(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct aaci_runtime *aacirun = runtime->private_data;
 
+	aacirun->period	= snd_pcm_lib_period_bytes(substream);
 	aacirun->start	= runtime->dma_area;
 	aacirun->end	= aacirun->start + snd_pcm_lib_buffer_bytes(substream);
 	aacirun->ptr	= aacirun->start;
-	aacirun->period	=
-	aacirun->bytes	= frames_to_bytes(runtime, runtime->period_size);
+	aacirun->bytes	= aacirun->period;
 
 	return 0;
 }
@@ -505,89 +570,6 @@ static snd_pcm_uframes_t aaci_pcm_pointer(struct snd_pcm_substream *substream)
 /*
  * Playback specific ALSA stuff
  */
-static const u32 channels_to_txmask[] = {
-	[2] = CR_SL3 | CR_SL4,
-	[4] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8,
-	[6] = CR_SL3 | CR_SL4 | CR_SL7 | CR_SL8 | CR_SL6 | CR_SL9,
-};
-
-/*
- * We can support two and four channel audio.  Unfortunately
- * six channel audio requires a non-standard channel ordering:
- *   2 -> FL(3), FR(4)
- *   4 -> FL(3), FR(4), SL(7), SR(8)
- *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
- *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
- * This requires an ALSA configuration file to correct.
- */
-static unsigned int channel_list[] = { 2, 4, 6 };
-
-static int
-aaci_rule_channels(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *rule)
-{
-	struct aaci *aaci = rule->private;
-	unsigned int chan_mask = 1 << 0, slots;
-
-	/*
-	 * pcms[0] is the our 5.1 PCM instance.
-	 */
-	slots = aaci->ac97_bus->pcms[0].r[0].slots;
-	if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
-		chan_mask |= 1 << 1;
-		if (slots & (1 << AC97_SLOT_LFE))
-			chan_mask |= 1 << 2;
-	}
-
-	return snd_interval_list(hw_param_interval(p, rule->var),
-				 ARRAY_SIZE(channel_list), channel_list,
-				 chan_mask);
-}
-
-static int aaci_pcm_open(struct snd_pcm_substream *substream)
-{
-	struct aaci *aaci = substream->private_data;
-	int ret;
-
-	/*
-	 * Add rule describing channel dependency.
-	 */
-	ret = snd_pcm_hw_rule_add(substream->runtime, 0,
-				  SNDRV_PCM_HW_PARAM_CHANNELS,
-				  aaci_rule_channels, aaci,
-				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-	if (ret)
-		return ret;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		ret = __aaci_pcm_open(aaci, substream, &aaci->playback);
-	} else {
-		ret = __aaci_pcm_open(aaci, substream, &aaci->capture);
-	}
-	return ret;
-}
-
-static int aaci_pcm_playback_hw_params(struct snd_pcm_substream *substream,
-				       struct snd_pcm_hw_params *params)
-{
-	struct aaci_runtime *aacirun = substream->runtime->private_data;
-	unsigned int channels = params_channels(params);
-	int ret;
-
-	WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
-		!channels_to_txmask[channels]);
-
-	ret = aaci_pcm_hw_params(substream, aacirun, params);
-
-	/*
-	 * Enable FIFO, compact mode, 16 bits per sample.
-	 * FIXME: double rate slots?
-	 */
-	if (ret >= 0)
-		aacirun->cr |= channels_to_txmask[channels];
-
-	return ret;
-}
-
 static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
 {
 	u32 ie;
@@ -657,27 +639,13 @@ static struct snd_pcm_ops aaci_playback_ops = {
 	.open		= aaci_pcm_open,
 	.close		= aaci_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
-	.hw_params	= aaci_pcm_playback_hw_params,
+	.hw_params	= aaci_pcm_hw_params,
 	.hw_free	= aaci_pcm_hw_free,
 	.prepare	= aaci_pcm_prepare,
 	.trigger	= aaci_pcm_playback_trigger,
 	.pointer	= aaci_pcm_pointer,
 };
 
-static int aaci_pcm_capture_hw_params(struct snd_pcm_substream *substream,
-				      struct snd_pcm_hw_params *params)
-{
-	struct aaci_runtime *aacirun = substream->runtime->private_data;
-	int ret;
-
-	ret = aaci_pcm_hw_params(substream, aacirun, params);
-	if (ret >= 0)
-		/* Line in record: slot 3 and 4 */
-		aacirun->cr |= CR_SL3 | CR_SL4;
-
-	return ret;
-}
-
 static void aaci_pcm_capture_stop(struct aaci_runtime *aacirun)
 {
 	u32 ie;
@@ -774,7 +742,7 @@ static struct snd_pcm_ops aaci_capture_ops = {
 	.open		= aaci_pcm_open,
 	.close		= aaci_pcm_close,
 	.ioctl		= snd_pcm_lib_ioctl,
-	.hw_params	= aaci_pcm_capture_hw_params,
+	.hw_params	= aaci_pcm_hw_params,
 	.hw_free	= aaci_pcm_hw_free,
 	.prepare	= aaci_pcm_capture_prepare,
 	.trigger	= aaci_pcm_capture_trigger,
@@ -941,12 +909,13 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
 	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
 	strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
 	snprintf(card->longname, sizeof(card->longname),
-		 "%s at 0x%016llx, irq %d",
-		 card->shortname, (unsigned long long)dev->res.start,
-		 dev->irq[0]);
+		 "%s PL%03x rev%u at 0x%08llx, irq %d",
+		 card->shortname, amba_part(dev), amba_rev(dev),
+		 (unsigned long long)dev->res.start, dev->irq[0]);
 
 	aaci = card->private_data;
 	mutex_init(&aaci->ac97_sem);
+	mutex_init(&aaci->irq_lock);
 	aaci->card = card;
 	aaci->dev = dev;
 
@@ -984,6 +953,10 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
 	struct aaci_runtime *aacirun = &aaci->playback;
 	int i;
 
+	/*
+	 * Enable the channel, but don't assign it to any slots, so
+	 * it won't empty onto the AC'97 link.
+	 */
 	writel(CR_FEN | CR_SZ16 | CR_EN, aacirun->base + AACI_TXCR);
 
 	for (i = 0; !(readl(aacirun->base + AACI_SR) & SR_TXFF) && i < 4096; i++)
@@ -1002,7 +975,7 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
 	writel(aaci->maincr, aaci->base + AACI_MAINCR);
 
 	/*
-	 * If we hit 4096, we failed.  Go back to the specified
+	 * If we hit 4096 entries, we failed.  Go back to the specified
 	 * fifo depth.
 	 */
 	if (i == 4096)
@@ -1011,7 +984,8 @@ static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
 	return i;
 }
 
-static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit aaci_probe(struct amba_device *dev,
+	const struct amba_id *id)
 {
 	struct aaci *aaci;
 	int ret, i;
@@ -1067,11 +1041,12 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id)
 
 	/*
 	 * Size the FIFOs (must be multiple of 16).
+	 * This is the number of entries in the FIFO.
 	 */
-	aaci->fifosize = aaci_size_fifo(aaci);
-	if (aaci->fifosize & 15) {
-		printk(KERN_WARNING "AACI: fifosize = %d not supported\n",
-		       aaci->fifosize);
+	aaci->fifo_depth = aaci_size_fifo(aaci);
+	if (aaci->fifo_depth & 15) {
+		printk(KERN_WARNING "AACI: FIFO depth %d not supported\n",
+		       aaci->fifo_depth);
 		ret = -ENODEV;
 		goto out;
 	}
@@ -1084,8 +1059,8 @@ static int __devinit aaci_probe(struct amba_device *dev, struct amba_id *id)
 
 	ret = snd_card_register(aaci->card);
 	if (ret == 0) {
-		dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
-			 aaci->fifosize);
+		dev_info(&dev->dev, "%s\n", aaci->card->longname);
+		dev_info(&dev->dev, "FIFO %u entries\n", aaci->fifo_depth);
 		amba_set_drvdata(dev, aaci->card);
 		return ret;
 	}
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index 6a4a2ee..5791bd5 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -210,6 +210,8 @@ struct aaci_runtime {
 	u32			cr;
 	struct snd_pcm_substream	*substream;
 
+	unsigned int		period;	/* byte size of a "period" */
+
 	/*
 	 * PIO support
 	 */
@@ -217,15 +219,16 @@ struct aaci_runtime {
 	void			*end;
 	void			*ptr;
 	int			bytes;
-	unsigned int		period;
-	unsigned int		fifosz;
+	unsigned int		fifo_bytes;
 };
 
 struct aaci {
 	struct amba_device	*dev;
 	struct snd_card		*card;
 	void			__iomem *base;
-	unsigned int		fifosize;
+	unsigned int		fifo_depth;
+	unsigned int		users;
+	struct mutex		irq_lock;
 
 	/* AC'97 */
 	struct mutex		ac97_sem;
diff --git a/sound/core/control.c b/sound/core/control.c
index 9ce00ed..a08ad57 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -279,33 +279,31 @@ void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
 
 EXPORT_SYMBOL(snd_ctl_free_one);
 
-static unsigned int snd_ctl_hole_check(struct snd_card *card,
-				       unsigned int count)
+static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
+					  unsigned int count)
 {
 	struct snd_kcontrol *kctl;
 
 	list_for_each_entry(kctl, &card->controls, list) {
-		if ((kctl->id.numid <= card->last_numid &&
-		     kctl->id.numid + kctl->count > card->last_numid) ||
-		    (kctl->id.numid <= card->last_numid + count - 1 &&
-		     kctl->id.numid + kctl->count > card->last_numid + count - 1))
-		    	return card->last_numid = kctl->id.numid + kctl->count - 1;
+		if (kctl->id.numid < card->last_numid + 1 + count &&
+		    kctl->id.numid + kctl->count > card->last_numid + 1) {
+		    	card->last_numid = kctl->id.numid + kctl->count - 1;
+			return true;
+		}
 	}
-	return card->last_numid;
+	return false;
 }
 
 static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
 {
-	unsigned int last_numid, iter = 100000;
+	unsigned int iter = 100000;
 
-	last_numid = card->last_numid;
-	while (last_numid != snd_ctl_hole_check(card, count)) {
+	while (snd_ctl_remove_numid_conflict(card, count)) {
 		if (--iter == 0) {
 			/* this situation is very unlikely */
 			snd_printk(KERN_ERR "unable to allocate new control numid\n");
 			return -ENOMEM;
 		}
-		last_numid = card->last_numid;
 	}
 	return 0;
 }
@@ -466,6 +464,52 @@ error:
 }
 
 /**
+ * snd_ctl_activate_id - activate/inactivate the control of the given id
+ * @card: the card instance
+ * @id: the control id to activate/inactivate
+ * @active: non-zero to activate
+ *
+ * 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.
+ */
+int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id,
+			int active)
+{
+	struct snd_kcontrol *kctl;
+	struct snd_kcontrol_volatile *vd;
+	unsigned int index_offset;
+	int ret;
+
+	down_write(&card->controls_rwsem);
+	kctl = snd_ctl_find_id(card, id);
+	if (kctl == NULL) {
+		ret = -ENOENT;
+		goto unlock;
+	}
+	index_offset = snd_ctl_get_ioff(kctl, &kctl->id);
+	vd = &kctl->vd[index_offset];
+	ret = 0;
+	if (active) {
+		if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE))
+			goto unlock;
+		vd->access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+	} else {
+		if (vd->access & SNDRV_CTL_ELEM_ACCESS_INACTIVE)
+			goto unlock;
+		vd->access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+	}
+	ret = 1;
+ unlock:
+	up_write(&card->controls_rwsem);
+	if (ret > 0)
+		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO, id);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(snd_ctl_activate_id);
+
+/**
  * snd_ctl_rename_id - replace the id of a control on the card
  * @card: the card instance
  * @src_id: the old id
diff --git a/sound/core/device.c b/sound/core/device.c
index a67dfac0..2d1ad4b 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -225,15 +225,16 @@ int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
 {
 	struct snd_device *dev;
 	int err;
-	unsigned int range_low, range_high;
+	unsigned int range_low, range_high, type;
 
 	if (snd_BUG_ON(!card))
 		return -ENXIO;
-	range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
+	range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
 	range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
       __again:
 	list_for_each_entry(dev, &card->devices, list) {
-		if (dev->type >= range_low && dev->type <= range_high) {
+		type = (__force unsigned int)dev->type;
+		if (type >= range_low && type <= range_high) {
 			if ((err = snd_device_free(card, dev->device_data)) < 0)
 				return err;
 			goto __again;
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 9e92441..16bd9c0 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -192,7 +192,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 	dmab->bytes = 0;
 	switch (type) {
 	case SNDRV_DMA_TYPE_CONTINUOUS:
-		dmab->area = snd_malloc_pages(size, (unsigned long)device);
+		dmab->area = snd_malloc_pages(size,
+					(__force gfp_t)(unsigned long)device);
 		dmab->addr = 0;
 		break;
 #ifdef CONFIG_HAS_DMA
diff --git a/sound/core/oss/linear.c b/sound/core/oss/linear.c
index 4c1d168..13b3f6f 100644
--- a/sound/core/oss/linear.c
+++ b/sound/core/oss/linear.c
@@ -114,7 +114,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
 	return frames;
 }
 
-static void init_data(struct linear_priv *data, int src_format, int dst_format)
+static void init_data(struct linear_priv *data,
+		      snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 {
 	int src_le, dst_le, src_bytes, dst_bytes;
 
@@ -140,9 +141,9 @@ static void init_data(struct linear_priv *data, int src_format, int dst_format)
 	if (snd_pcm_format_signed(src_format) !=
 	    snd_pcm_format_signed(dst_format)) {
 		if (dst_le)
-			data->flip = cpu_to_le32(0x80000000);
+			data->flip = (__force u32)cpu_to_le32(0x80000000);
 		else
-			data->flip = cpu_to_be32(0x80000000);
+			data->flip = (__force u32)cpu_to_be32(0x80000000);
 	}
 }
 
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 822dd56..d8359cf 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -190,9 +190,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
 		return -EIO;
 	if (mixer->put_recsrc && mixer->get_recsrc) {	/* exclusive */
 		int err;
-		if ((err = mixer->get_recsrc(fmixer, &result)) < 0)
+		unsigned int index;
+		if ((err = mixer->get_recsrc(fmixer, &index)) < 0)
 			return err;
-		result = 1 << result;
+		result = 1 << index;
 	} else {
 		struct snd_mixer_oss_slot *pslot;
 		int chn;
@@ -214,6 +215,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
 	struct snd_mixer_oss *mixer = fmixer->mixer;
 	struct snd_mixer_oss_slot *pslot;
 	int chn, active;
+	unsigned int index;
 	int result = 0;
 
 	if (mixer == NULL)
@@ -222,8 +224,8 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
 		if (recsrc & ~mixer->oss_recsrc)
 			recsrc &= ~mixer->oss_recsrc;
 		mixer->put_recsrc(fmixer, ffz(~recsrc));
-		mixer->get_recsrc(fmixer, &result);
-		result = 1 << result;
+		mixer->get_recsrc(fmixer, &index);
+		result = 1 << index;
 	}
 	for (chn = 0; chn < 31; chn++) {
 		pslot = &mixer->slots[chn];
diff --git a/sound/core/oss/mulaw.c b/sound/core/oss/mulaw.c
index f7649d4..7915564 100644
--- a/sound/core/oss/mulaw.c
+++ b/sound/core/oss/mulaw.c
@@ -274,7 +274,7 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
 	return frames;
 }
 
-static void init_data(struct mulaw_priv *data, int format)
+static void init_data(struct mulaw_priv *data, snd_pcm_format_t format)
 {
 #ifdef SNDRV_LITTLE_ENDIAN
 	data->cvt_endian = snd_pcm_format_big_endian(format) > 0;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index a2e4eb3..23c34a0 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -41,6 +41,7 @@
 #include <sound/info.h>
 #include <linux/soundcard.h>
 #include <sound/initval.h>
+#include <sound/mixer_oss.h>
 
 #define OSS_ALSAEMULVER		_SIOR ('M', 249, int)
 
@@ -60,7 +61,6 @@ MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
 
-extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg);
 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
@@ -656,7 +656,7 @@ snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
 #define AFMT_AC3         0x00000400
 #define AFMT_VORBIS      0x00000800
 
-static int snd_pcm_oss_format_from(int format)
+static snd_pcm_format_t snd_pcm_oss_format_from(int format)
 {
 	switch (format) {
 	case AFMT_MU_LAW:	return SNDRV_PCM_FORMAT_MU_LAW;
@@ -680,7 +680,7 @@ static int snd_pcm_oss_format_from(int format)
 	}
 }
 
-static int snd_pcm_oss_format_to(int format)
+static int snd_pcm_oss_format_to(snd_pcm_format_t format)
 {
 	switch (format) {
 	case SNDRV_PCM_FORMAT_MU_LAW:	return AFMT_MU_LAW;
@@ -843,7 +843,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	size_t oss_frame_size;
 	int err;
 	int direct;
-	int format, sformat, n;
+	snd_pcm_format_t format, sformat;
+	int n;
 	struct snd_mask sformat_mask;
 	struct snd_mask mask;
 
@@ -868,11 +869,11 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	_snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
 	snd_mask_none(&mask);
 	if (atomic_read(&substream->mmap_count))
-		snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
+		snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
 	else {
-		snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
+		snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED);
 		if (!direct)
-			snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
+			snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
 	}
 	err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
 	if (err < 0) {
@@ -891,19 +892,22 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	else
 		sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
 
-	if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) {
-		for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) {
-			if (snd_mask_test(&sformat_mask, sformat) &&
+	if ((__force int)sformat < 0 ||
+	    !snd_mask_test(&sformat_mask, (__force int)sformat)) {
+		for (sformat = (__force snd_pcm_format_t)0;
+		     (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
+		     sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
+			if (snd_mask_test(&sformat_mask, (__force int)sformat) &&
 			    snd_pcm_oss_format_to(sformat) >= 0)
 				break;
 		}
-		if (sformat > SNDRV_PCM_FORMAT_LAST) {
+		if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) {
 			snd_printd("Cannot find a format!!!\n");
 			err = -EINVAL;
 			goto failure;
 		}
 	}
-	err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0);
+	err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0);
 	if (err < 0)
 		goto failure;
 
@@ -912,9 +916,9 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	} else {
 		_snd_pcm_hw_params_any(params);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
-				      SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
+				      (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				      snd_pcm_oss_format_from(runtime->oss.format), 0);
+				      (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
 				      runtime->oss.channels, 0);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
@@ -1185,10 +1189,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
 		if (in_kernel) {
 			mm_segment_t fs;
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
 			snd_leave_user(fs);
 		} else {
-			ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
 		}
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 			break;
@@ -1230,10 +1234,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
 		if (in_kernel) {
 			mm_segment_t fs;
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
 			snd_leave_user(fs);
 		} else {
-			ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
 		}
 		if (ret == -EPIPE) {
 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@@ -1333,7 +1337,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
 		struct snd_pcm_plugin_channel *channels;
 		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
 		if (!in_kernel) {
-			if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
+			if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes))
 				return -EFAULT;
 			buf = runtime->oss.buffer;
 		}
@@ -1429,7 +1433,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_sframes_t frames, frames1;
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
-	char __user *final_dst = (char __user *)buf;
+	char __user *final_dst = (char __force __user *)buf;
 	if (runtime->oss.plugin_first) {
 		struct snd_pcm_plugin_channel *channels;
 		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
@@ -1549,6 +1553,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
 {
 	struct snd_pcm_runtime *runtime;
 	ssize_t result = 0;
+	snd_pcm_state_t state;
 	long res;
 	wait_queue_t wait;
 
@@ -1570,9 +1575,9 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
 		result = 0;
 		set_current_state(TASK_INTERRUPTIBLE);
 		snd_pcm_stream_lock_irq(substream);
-		res = runtime->status->state;
+		state = runtime->status->state;
 		snd_pcm_stream_unlock_irq(substream);
-		if (res != SNDRV_PCM_STATE_RUNNING) {
+		if (state != SNDRV_PCM_STATE_RUNNING) {
 			set_current_state(TASK_RUNNING);
 			break;
 		}
@@ -1658,7 +1663,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
 								   size1);
 					size1 /= runtime->channels; /* frames */
 					fs = snd_enter_user();
-					snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
+					snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
 					snd_leave_user(fs);
 				}
 			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6751daa..71cc3dd 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -264,7 +264,7 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
 	return frames;
 }
 
-static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
+static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format)
 {
 	struct snd_mask formats = *mask;
 	u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
@@ -276,16 +276,16 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
 		       SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
 		       SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
 		       SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
-	snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
+	snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW);
 	
 	if (formats.bits[0] & (u32)linfmts)
 		formats.bits[0] |= (u32)linfmts;
 	if (formats.bits[1] & (u32)(linfmts >> 32))
 		formats.bits[1] |= (u32)(linfmts >> 32);
-	return snd_mask_test(&formats, format);
+	return snd_mask_test(&formats, (__force int)format);
 }
 
-static int preferred_formats[] = {
+static snd_pcm_format_t preferred_formats[] = {
 	SNDRV_PCM_FORMAT_S16_LE,
 	SNDRV_PCM_FORMAT_S16_BE,
 	SNDRV_PCM_FORMAT_U16_LE,
@@ -306,24 +306,25 @@ static int preferred_formats[] = {
 	SNDRV_PCM_FORMAT_U8
 };
 
-int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
+snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+					   struct snd_mask *format_mask)
 {
 	int i;
 
-	if (snd_mask_test(format_mask, format))
+	if (snd_mask_test(format_mask, (__force int)format))
 		return format;
-	if (! snd_pcm_plug_formats(format_mask, format))
-		return -EINVAL;
+	if (!snd_pcm_plug_formats(format_mask, format))
+		return (__force snd_pcm_format_t)-EINVAL;
 	if (snd_pcm_format_linear(format)) {
 		unsigned int width = snd_pcm_format_width(format);
 		int unsignd = snd_pcm_format_unsigned(format) > 0;
 		int big = snd_pcm_format_big_endian(format) > 0;
 		unsigned int badness, best = -1;
-		int best_format = -1;
+		snd_pcm_format_t best_format = (__force snd_pcm_format_t)-1;
 		for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
-			int f = preferred_formats[i];
+			snd_pcm_format_t f = preferred_formats[i];
 			unsigned int w;
-			if (!snd_mask_test(format_mask, f))
+			if (!snd_mask_test(format_mask, (__force int)f))
 				continue;
 			w = snd_pcm_format_width(f);
 			if (w >= width)
@@ -337,17 +338,20 @@ int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
 				best = badness;
 			}
 		}
-		return best_format >= 0 ? best_format : -EINVAL;
+		if ((__force int)best_format >= 0)
+			return best_format;
+		else
+			return (__force snd_pcm_format_t)-EINVAL;
 	} else {
 		switch (format) {
 		case SNDRV_PCM_FORMAT_MU_LAW:
 			for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
-				int format1 = preferred_formats[i];
-				if (snd_mask_test(format_mask, format1))
+				snd_pcm_format_t format1 = preferred_formats[i];
+				if (snd_mask_test(format_mask, (__force int)format1))
 					return format1;
 			}
 		default:
-			return -EINVAL;
+			return (__force snd_pcm_format_t)-EINVAL;
 		}
 	}
 }
@@ -359,7 +363,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
 	struct snd_pcm_plugin_format tmpformat;
 	struct snd_pcm_plugin_format dstformat;
 	struct snd_pcm_plugin_format srcformat;
-	int src_access, dst_access;
+	snd_pcm_access_t src_access, dst_access;
 	struct snd_pcm_plugin *plugin = NULL;
 	int err;
 	int stream = snd_pcm_plug_stream(plug);
@@ -641,7 +645,7 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
 }
 
 int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
-			 size_t samples, int format)
+			 size_t samples, snd_pcm_format_t format)
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
 	unsigned char *dst;
@@ -688,7 +692,7 @@ int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst
 
 int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
 		      const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
-		      size_t samples, int format)
+		      size_t samples, snd_pcm_format_t format)
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
 	char *src, *dst;
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index b9afab6..a5035c2 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -46,7 +46,7 @@ struct snd_pcm_plugin_channel {
 };
 
 struct snd_pcm_plugin_format {
-	int format;
+	snd_pcm_format_t format;
 	unsigned int rate;
 	unsigned int channels;
 };
@@ -58,7 +58,7 @@ struct snd_pcm_plugin {
 	struct snd_pcm_plugin_format dst_format;	/* destination format */
 	int src_width;			/* sample width in bits */
 	int dst_width;			/* sample width in bits */
-	int access;
+	snd_pcm_access_t access;
 	snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames);
 	snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames);
 	snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
@@ -125,7 +125,8 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params,
 				struct snd_pcm_hw_params *slave_params);
 
-int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask);
+snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+					   struct snd_mask *format_mask);
 
 int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
 
@@ -146,12 +147,12 @@ snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
 
 int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel,
 			 size_t dst_offset,
-			 size_t samples, int format);
+			 size_t samples, snd_pcm_format_t format);
 int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
 		      size_t src_offset,
 		      const struct snd_pcm_channel_area *dst_channel,
 		      size_t dst_offset,
-		      size_t samples, int format);
+		      size_t samples, snd_pcm_format_t format);
 
 void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
 void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);
diff --git a/sound/core/oss/route.c b/sound/core/oss/route.c
index bbe25d8..c8171f5 100644
--- a/sound/core/oss/route.c
+++ b/sound/core/oss/route.c
@@ -25,7 +25,7 @@
 #include "pcm_plugin.h"
 
 static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
-		       snd_pcm_uframes_t frames, int format)
+		       snd_pcm_uframes_t frames, snd_pcm_format_t format)
 {
 	int dst = 0;
 	for (; dst < ndsts; ++dst) {
@@ -38,7 +38,7 @@ static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
 
 static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
 			     struct snd_pcm_plugin_channel *dst_channel,
-			     snd_pcm_uframes_t frames, int format)
+			     snd_pcm_uframes_t frames, snd_pcm_format_t format)
 {
 	dst_channel->enabled = 1;
 	snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
@@ -51,7 +51,7 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
 {
 	int nsrcs, ndsts, dst;
 	struct snd_pcm_plugin_channel *dvp;
-	int format;
+	snd_pcm_format_t format;
 
 	if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
 		return -ENXIO;
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 6b4b128..ee9abb2 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -211,9 +211,9 @@ static char *snd_pcm_format_names[] = {
 
 const char *snd_pcm_format_name(snd_pcm_format_t format)
 {
-	if (format >= ARRAY_SIZE(snd_pcm_format_names))
+	if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names))
 		return "Unknown";
-	return snd_pcm_format_names[format];
+	return snd_pcm_format_names[(__force unsigned int)format];
 }
 EXPORT_SYMBOL_GPL(snd_pcm_format_name);
 
@@ -269,12 +269,12 @@ static const char *snd_pcm_stream_name(int stream)
 
 static const char *snd_pcm_access_name(snd_pcm_access_t access)
 {
-	return snd_pcm_access_names[access];
+	return snd_pcm_access_names[(__force int)access];
 }
 
 static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
 {
-	return snd_pcm_subformat_names[subformat];
+	return snd_pcm_subformat_names[(__force int)subformat];
 }
 
 static const char *snd_pcm_tstamp_mode_name(int mode)
@@ -284,7 +284,7 @@ static const char *snd_pcm_tstamp_mode_name(int mode)
 
 static const char *snd_pcm_state_name(snd_pcm_state_t state)
 {
-	return snd_pcm_state_names[state];
+	return snd_pcm_state_names[(__force int)state];
 }
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 434af3c..88f02e3 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -35,7 +35,10 @@ struct pcm_format_data {
 	unsigned char silence[8];	/* silence data to fill */
 };
 
-static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
+/* we do lots of calculations on snd_pcm_format_t; shut up sparse */
+#define INT	__force int
+
+static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
 	[SNDRV_PCM_FORMAT_S8] = {
 		.width = 8, .phys = 8, .le = -1, .signd = 1,
 		.silence = {},
@@ -215,9 +218,9 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
 int snd_pcm_format_signed(snd_pcm_format_t format)
 {
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	if ((val = pcm_formats[format].signd) < 0)
+	if ((val = pcm_formats[(INT)format].signd) < 0)
 		return -EINVAL;
 	return val;
 }
@@ -266,9 +269,9 @@ EXPORT_SYMBOL(snd_pcm_format_linear);
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
 {
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	if ((val = pcm_formats[format].le) < 0)
+	if ((val = pcm_formats[(INT)format].le) < 0)
 		return -EINVAL;
 	return val;
 }
@@ -304,9 +307,9 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian);
 int snd_pcm_format_width(snd_pcm_format_t format)
 {
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	if ((val = pcm_formats[format].width) == 0)
+	if ((val = pcm_formats[(INT)format].width) == 0)
 		return -EINVAL;
 	return val;
 }
@@ -323,9 +326,9 @@ EXPORT_SYMBOL(snd_pcm_format_width);
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
 {
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
-	if ((val = pcm_formats[format].phys) == 0)
+	if ((val = pcm_formats[(INT)format].phys) == 0)
 		return -EINVAL;
 	return val;
 }
@@ -358,11 +361,11 @@ EXPORT_SYMBOL(snd_pcm_format_size);
  */
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 {
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return NULL;
-	if (! pcm_formats[format].phys)
+	if (! pcm_formats[(INT)format].phys)
 		return NULL;
-	return pcm_formats[format].silence;
+	return pcm_formats[(INT)format].silence;
 }
 
 EXPORT_SYMBOL(snd_pcm_format_silence_64);
@@ -382,16 +385,16 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
 	int width;
 	unsigned char *dst, *pat;
 
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
 	if (samples == 0)
 		return 0;
-	width = pcm_formats[format].phys; /* physical width */
-	pat = pcm_formats[format].silence;
+	width = pcm_formats[(INT)format].phys; /* physical width */
+	pat = pcm_formats[(INT)format].silence;
 	if (! width)
 		return -EINVAL;
 	/* signed or 1 byte data */
-	if (pcm_formats[format].signd == 1 || width <= 8) {
+	if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
 		unsigned int bytes = samples * width / 8;
 		memset(data, *pat, bytes);
 		return 0;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 4be45e7..ae42b65 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -941,7 +941,7 @@ static struct action_ops snd_pcm_action_stop = {
  *
  * The state of each stream is then changed to the given state unconditionally.
  */
-int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
+int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
 {
 	return snd_pcm_action(&snd_pcm_action_stop, substream, state);
 }
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 99a485f..f2436d3 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1052,7 +1052,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
 		} else {
 #ifdef CONFIG_COMPAT
 			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
-				void *ptr = compat_ptr(event.data.raw32.d[1]);
+				void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]);
 				event.data.ext.ptr = ptr;
 			}
 #endif
@@ -2407,7 +2407,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
 	if (client == NULL)
 		return -ENXIO;
 	fs = snd_enter_user();
-	result = snd_seq_do_ioctl(client, cmd, (void __user *)arg);
+	result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg);
 	snd_leave_user(fs);
 	return result;
 }
@@ -2497,9 +2497,6 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
 }
 
 
-void snd_seq_info_pool(struct snd_info_buffer *buffer,
-		       struct snd_seq_pool *pool, char *space);
-
 /* exported to seq_info.c */
 void snd_seq_info_clients_read(struct snd_info_entry *entry, 
 			       struct snd_info_buffer *buffer)
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 7fb5543..7f50c14 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -86,7 +86,7 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
 
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		char buf[32];
-		char __user *curptr = (char __user *)event->data.ext.ptr;
+		char __user *curptr = (char __force __user *)event->data.ext.ptr;
 		while (len > 0) {
 			int size = sizeof(buf);
 			if (len < size)
@@ -157,7 +157,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		if (! in_kernel)
 			return -EINVAL;
-		if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len))
+		if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len))
 			return -EFAULT;
 		return newlen;
 	}
@@ -343,7 +343,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
 				tmp->event = src->event;
 				src = src->next;
 			} else if (is_usrptr) {
-				if (copy_from_user(&tmp->event, (char __user *)buf, size)) {
+				if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) {
 					err = -EFAULT;
 					goto __error;
 				}
diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h
index 63e9143..4a2ec77 100644
--- a/sound/core/seq/seq_memory.h
+++ b/sound/core/seq/seq_memory.h
@@ -24,6 +24,8 @@
 #include <sound/seq_kernel.h>
 #include <linux/poll.h>
 
+struct snd_info_buffer;
+
 /* container for sequencer event (internal use) */
 struct snd_seq_event_cell {
 	struct snd_seq_event event;
@@ -99,5 +101,7 @@ void snd_sequencer_memory_done(void);
 /* polling */
 int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
 
+void snd_seq_info_pool(struct snd_info_buffer *buffer,
+		       struct snd_seq_pool *pool, char *space);
 
 #endif
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 3bf7d73..e12bcd9 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -412,7 +412,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
  * initialization or termination of devices (see seq_midi.c).
  *
  * If callback_all option is set, the callback function is invoked
- * at each connnection/disconnection. 
+ * at each connection/disconnection. 
  */
 
 static int subscribe_port(struct snd_seq_client *client,
diff --git a/sound/core/timer.c b/sound/core/timer.c
index ed01632..7c1cbf0 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -186,9 +186,8 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
 		list_for_each_entry(master, &timer->open_list_head, open_list) {
 			if (slave->slave_class == master->slave_class &&
 			    slave->slave_id == master->slave_id) {
-				list_del(&slave->open_list);
-				list_add_tail(&slave->open_list,
-					      &master->slave_list_head);
+				list_move_tail(&slave->open_list,
+					       &master->slave_list_head);
 				spin_lock_irq(&slave_active_lock);
 				slave->master = master;
 				slave->timer = master->timer;
@@ -414,8 +413,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
 static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri,
 			    unsigned long sticks)
 {
-	list_del(&timeri->active_list);
-	list_add_tail(&timeri->active_list, &timer->active_list_head);
+	list_move_tail(&timeri->active_list, &timer->active_list_head);
 	if (timer->running) {
 		if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
 			goto __start_now;
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index 3b9b550..a89948a 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -18,7 +18,7 @@
  * a subset of information returned via ctl info callback
  */
 struct link_ctl_info {
-	int type;		/* value type */
+	snd_ctl_elem_type_t type; /* value type */
 	int count;		/* item count */
 	int min_val, max_val;	/* min, max values */
 };
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index 12b44b0..a0da775 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -482,8 +482,9 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
 			cable->streams[SNDRV_PCM_STREAM_CAPTURE];
 	unsigned long delta_play = 0, delta_capt = 0;
 	unsigned int running;
+	unsigned long flags;
 
-	spin_lock(&cable->lock);	
+	spin_lock_irqsave(&cable->lock, flags);
 	running = cable->running ^ cable->pause;
 	if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
 		delta_play = jiffies - dpcm_play->last_jiffies;
@@ -495,10 +496,8 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
 		dpcm_capt->last_jiffies += delta_capt;
 	}
 
-	if (delta_play == 0 && delta_capt == 0) {
-		spin_unlock(&cable->lock);
-		return running;
-	}
+	if (delta_play == 0 && delta_capt == 0)
+		goto unlock;
 		
 	if (delta_play > delta_capt) {
 		loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
@@ -510,14 +509,14 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
 		delta_capt = delta_play;
 	}
 
-	if (delta_play == 0 && delta_capt == 0) {
-		spin_unlock(&cable->lock);
-		return running;
-	}
+	if (delta_play == 0 && delta_capt == 0)
+		goto unlock;
+
 	/* note delta_capt == delta_play at this moment */
 	loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
 	loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
-	spin_unlock(&cable->lock);
+ unlock:
+	spin_unlock_irqrestore(&cable->lock, flags);
 	return running;
 }
 
diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig
new file mode 100644
index 0000000..e486f48
--- /dev/null
+++ b/sound/firewire/Kconfig
@@ -0,0 +1,25 @@
+menuconfig SND_FIREWIRE
+	bool "FireWire sound devices"
+	depends on FIREWIRE
+	default y
+	help
+	  Support for IEEE-1394/FireWire/iLink sound devices.
+
+if SND_FIREWIRE && FIREWIRE
+
+config SND_FIREWIRE_LIB
+	tristate
+	depends on SND_PCM
+
+config SND_FIREWIRE_SPEAKERS
+	tristate "FireWire speakers"
+	select SND_PCM
+	select SND_FIREWIRE_LIB
+	help
+	  Say Y here to include support for the Griffin FireWave Surround
+	  and the LaCie FireWire Speakers.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-firewire-speakers.
+
+endif # SND_FIREWIRE
diff --git a/sound/firewire/Makefile b/sound/firewire/Makefile
new file mode 100644
index 0000000..e5b1634
--- /dev/null
+++ b/sound/firewire/Makefile
@@ -0,0 +1,6 @@
+snd-firewire-lib-objs := lib.o iso-resources.o packets-buffer.o \
+			 fcp.o cmp.o amdtp.o
+snd-firewire-speakers-objs := speakers.o
+
+obj-$(CONFIG_SND_FIREWIRE_LIB) += snd-firewire-lib.o
+obj-$(CONFIG_SND_FIREWIRE_SPEAKERS) += snd-firewire-speakers.o
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
new file mode 100644
index 0000000..b18140f
--- /dev/null
+++ b/sound/firewire/amdtp.c
@@ -0,0 +1,562 @@
+/*
+ * Audio and Music Data Transmission Protocol (IEC 61883-6) streams
+ * with Common Isochronous Packet (IEC 61883-1) headers
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/firewire.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include "amdtp.h"
+
+#define TICKS_PER_CYCLE		3072
+#define CYCLES_PER_SECOND	8000
+#define TICKS_PER_SECOND	(TICKS_PER_CYCLE * CYCLES_PER_SECOND)
+
+#define TRANSFER_DELAY_TICKS	0x2e00 /* 479.17 Âľs */
+
+#define TAG_CIP			1
+
+#define CIP_EOH			(1u << 31)
+#define CIP_FMT_AM		(0x10 << 24)
+#define AMDTP_FDF_AM824		(0 << 19)
+#define AMDTP_FDF_SFC_SHIFT	16
+
+/* TODO: make these configurable */
+#define INTERRUPT_INTERVAL	16
+#define QUEUE_LENGTH		48
+
+/**
+ * amdtp_out_stream_init - initialize an AMDTP output stream structure
+ * @s: the AMDTP output stream to initialize
+ * @unit: the target of the stream
+ * @flags: the packet transmission method to use
+ */
+int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
+			  enum cip_out_flags flags)
+{
+	if (flags != CIP_NONBLOCKING)
+		return -EINVAL;
+
+	s->unit = fw_unit_get(unit);
+	s->flags = flags;
+	s->context = ERR_PTR(-1);
+	mutex_init(&s->mutex);
+	s->packet_index = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL(amdtp_out_stream_init);
+
+/**
+ * amdtp_out_stream_destroy - free stream resources
+ * @s: the AMDTP output stream to destroy
+ */
+void amdtp_out_stream_destroy(struct amdtp_out_stream *s)
+{
+	WARN_ON(!IS_ERR(s->context));
+	mutex_destroy(&s->mutex);
+	fw_unit_put(s->unit);
+}
+EXPORT_SYMBOL(amdtp_out_stream_destroy);
+
+/**
+ * amdtp_out_stream_set_rate - set the sample rate
+ * @s: the AMDTP output stream to configure
+ * @rate: the sample rate
+ *
+ * The sample rate must be set before the stream is started, and must not be
+ * changed while the stream is running.
+ */
+void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate)
+{
+	static const struct {
+		unsigned int rate;
+		unsigned int syt_interval;
+	} rate_info[] = {
+		[CIP_SFC_32000]  = {  32000,  8, },
+		[CIP_SFC_44100]  = {  44100,  8, },
+		[CIP_SFC_48000]  = {  48000,  8, },
+		[CIP_SFC_88200]  = {  88200, 16, },
+		[CIP_SFC_96000]  = {  96000, 16, },
+		[CIP_SFC_176400] = { 176400, 32, },
+		[CIP_SFC_192000] = { 192000, 32, },
+	};
+	unsigned int sfc;
+
+	if (WARN_ON(!IS_ERR(s->context)))
+		return;
+
+	for (sfc = 0; sfc < ARRAY_SIZE(rate_info); ++sfc)
+		if (rate_info[sfc].rate == rate) {
+			s->sfc = sfc;
+			s->syt_interval = rate_info[sfc].syt_interval;
+			return;
+		}
+	WARN_ON(1);
+}
+EXPORT_SYMBOL(amdtp_out_stream_set_rate);
+
+/**
+ * amdtp_out_stream_get_max_payload - get the stream's packet size
+ * @s: the AMDTP output stream
+ *
+ * This function must not be called before the stream has been configured
+ * with amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
+ * amdtp_out_stream_set_midi().
+ */
+unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s)
+{
+	static const unsigned int max_data_blocks[] = {
+		[CIP_SFC_32000]  =  4,
+		[CIP_SFC_44100]  =  6,
+		[CIP_SFC_48000]  =  6,
+		[CIP_SFC_88200]  = 12,
+		[CIP_SFC_96000]  = 12,
+		[CIP_SFC_176400] = 23,
+		[CIP_SFC_192000] = 24,
+	};
+
+	s->data_block_quadlets = s->pcm_channels;
+	s->data_block_quadlets += DIV_ROUND_UP(s->midi_ports, 8);
+
+	return 8 + max_data_blocks[s->sfc] * 4 * s->data_block_quadlets;
+}
+EXPORT_SYMBOL(amdtp_out_stream_get_max_payload);
+
+static void amdtp_write_s16(struct amdtp_out_stream *s,
+			    struct snd_pcm_substream *pcm,
+			    __be32 *buffer, unsigned int frames);
+static void amdtp_write_s32(struct amdtp_out_stream *s,
+			    struct snd_pcm_substream *pcm,
+			    __be32 *buffer, unsigned int frames);
+
+/**
+ * amdtp_out_stream_set_pcm_format - set the PCM format
+ * @s: the AMDTP output stream to configure
+ * @format: the format of the ALSA PCM device
+ *
+ * The sample format must be set before the stream is started, and must not be
+ * changed while the stream is running.
+ */
+void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
+				     snd_pcm_format_t format)
+{
+	if (WARN_ON(!IS_ERR(s->context)))
+		return;
+
+	switch (format) {
+	default:
+		WARN_ON(1);
+		/* fall through */
+	case SNDRV_PCM_FORMAT_S16:
+		s->transfer_samples = amdtp_write_s16;
+		break;
+	case SNDRV_PCM_FORMAT_S32:
+		s->transfer_samples = amdtp_write_s32;
+		break;
+	}
+}
+EXPORT_SYMBOL(amdtp_out_stream_set_pcm_format);
+
+static unsigned int calculate_data_blocks(struct amdtp_out_stream *s)
+{
+	unsigned int phase, data_blocks;
+
+	if (!cip_sfc_is_base_44100(s->sfc)) {
+		/* Sample_rate / 8000 is an integer, and precomputed. */
+		data_blocks = s->data_block_state;
+	} else {
+		phase = s->data_block_state;
+
+		/*
+		 * This calculates the number of data blocks per packet so that
+		 * 1) the overall rate is correct and exactly synchronized to
+		 *    the bus clock, and
+		 * 2) packets with a rounded-up number of blocks occur as early
+		 *    as possible in the sequence (to prevent underruns of the
+		 *    device's buffer).
+		 */
+		if (s->sfc == CIP_SFC_44100)
+			/* 6 6 5 6 5 6 5 ... */
+			data_blocks = 5 + ((phase & 1) ^
+					   (phase == 0 || phase >= 40));
+		else
+			/* 12 11 11 11 11 ... or 23 22 22 22 22 ... */
+			data_blocks = 11 * (s->sfc >> 1) + (phase == 0);
+		if (++phase >= (80 >> (s->sfc >> 1)))
+			phase = 0;
+		s->data_block_state = phase;
+	}
+
+	return data_blocks;
+}
+
+static unsigned int calculate_syt(struct amdtp_out_stream *s,
+				  unsigned int cycle)
+{
+	unsigned int syt_offset, phase, index, syt;
+
+	if (s->last_syt_offset < TICKS_PER_CYCLE) {
+		if (!cip_sfc_is_base_44100(s->sfc))
+			syt_offset = s->last_syt_offset + s->syt_offset_state;
+		else {
+		/*
+		 * The time, in ticks, of the n'th SYT_INTERVAL sample is:
+		 *   n * SYT_INTERVAL * 24576000 / sample_rate
+		 * Modulo TICKS_PER_CYCLE, the difference between successive
+		 * elements is about 1386.23.  Rounding the results of this
+		 * formula to the SYT precision results in a sequence of
+		 * differences that begins with:
+		 *   1386 1386 1387 1386 1386 1386 1387 1386 1386 1386 1387 ...
+		 * This code generates _exactly_ the same sequence.
+		 */
+			phase = s->syt_offset_state;
+			index = phase % 13;
+			syt_offset = s->last_syt_offset;
+			syt_offset += 1386 + ((index && !(index & 3)) ||
+					      phase == 146);
+			if (++phase >= 147)
+				phase = 0;
+			s->syt_offset_state = phase;
+		}
+	} else
+		syt_offset = s->last_syt_offset - TICKS_PER_CYCLE;
+	s->last_syt_offset = syt_offset;
+
+	if (syt_offset < TICKS_PER_CYCLE) {
+		syt_offset += TRANSFER_DELAY_TICKS - TICKS_PER_CYCLE;
+		syt = (cycle + syt_offset / TICKS_PER_CYCLE) << 12;
+		syt += syt_offset % TICKS_PER_CYCLE;
+
+		return syt & 0xffff;
+	} else {
+		return 0xffff; /* no info */
+	}
+}
+
+static void amdtp_write_s32(struct amdtp_out_stream *s,
+			    struct snd_pcm_substream *pcm,
+			    __be32 *buffer, unsigned int frames)
+{
+	struct snd_pcm_runtime *runtime = pcm->runtime;
+	unsigned int channels, remaining_frames, frame_step, i, c;
+	const u32 *src;
+
+	channels = s->pcm_channels;
+	src = (void *)runtime->dma_area +
+			s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+	remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
+	frame_step = s->data_block_quadlets - channels;
+
+	for (i = 0; i < frames; ++i) {
+		for (c = 0; c < channels; ++c) {
+			*buffer = cpu_to_be32((*src >> 8) | 0x40000000);
+			src++;
+			buffer++;
+		}
+		buffer += frame_step;
+		if (--remaining_frames == 0)
+			src = (void *)runtime->dma_area;
+	}
+}
+
+static void amdtp_write_s16(struct amdtp_out_stream *s,
+			    struct snd_pcm_substream *pcm,
+			    __be32 *buffer, unsigned int frames)
+{
+	struct snd_pcm_runtime *runtime = pcm->runtime;
+	unsigned int channels, remaining_frames, frame_step, i, c;
+	const u16 *src;
+
+	channels = s->pcm_channels;
+	src = (void *)runtime->dma_area +
+			s->pcm_buffer_pointer * (runtime->frame_bits / 8);
+	remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
+	frame_step = s->data_block_quadlets - channels;
+
+	for (i = 0; i < frames; ++i) {
+		for (c = 0; c < channels; ++c) {
+			*buffer = cpu_to_be32((*src << 8) | 0x40000000);
+			src++;
+			buffer++;
+		}
+		buffer += frame_step;
+		if (--remaining_frames == 0)
+			src = (void *)runtime->dma_area;
+	}
+}
+
+static void amdtp_fill_pcm_silence(struct amdtp_out_stream *s,
+				   __be32 *buffer, unsigned int frames)
+{
+	unsigned int i, c;
+
+	for (i = 0; i < frames; ++i) {
+		for (c = 0; c < s->pcm_channels; ++c)
+			buffer[c] = cpu_to_be32(0x40000000);
+		buffer += s->data_block_quadlets;
+	}
+}
+
+static void amdtp_fill_midi(struct amdtp_out_stream *s,
+			    __be32 *buffer, unsigned int frames)
+{
+	unsigned int i;
+
+	for (i = 0; i < frames; ++i)
+		buffer[s->pcm_channels + i * s->data_block_quadlets] =
+						cpu_to_be32(0x80000000);
+}
+
+static void queue_out_packet(struct amdtp_out_stream *s, unsigned int cycle)
+{
+	__be32 *buffer;
+	unsigned int index, data_blocks, syt, ptr;
+	struct snd_pcm_substream *pcm;
+	struct fw_iso_packet packet;
+	int err;
+
+	if (s->packet_index < 0)
+		return;
+	index = s->packet_index;
+
+	data_blocks = calculate_data_blocks(s);
+	syt = calculate_syt(s, cycle);
+
+	buffer = s->buffer.packets[index].buffer;
+	buffer[0] = cpu_to_be32(ACCESS_ONCE(s->source_node_id_field) |
+				(s->data_block_quadlets << 16) |
+				s->data_block_counter);
+	buffer[1] = cpu_to_be32(CIP_EOH | CIP_FMT_AM | AMDTP_FDF_AM824 |
+				(s->sfc << AMDTP_FDF_SFC_SHIFT) | syt);
+	buffer += 2;
+
+	pcm = ACCESS_ONCE(s->pcm);
+	if (pcm)
+		s->transfer_samples(s, pcm, buffer, data_blocks);
+	else
+		amdtp_fill_pcm_silence(s, buffer, data_blocks);
+	if (s->midi_ports)
+		amdtp_fill_midi(s, buffer, data_blocks);
+
+	s->data_block_counter = (s->data_block_counter + data_blocks) & 0xff;
+
+	packet.payload_length = 8 + data_blocks * 4 * s->data_block_quadlets;
+	packet.interrupt = IS_ALIGNED(index + 1, INTERRUPT_INTERVAL);
+	packet.skip = 0;
+	packet.tag = TAG_CIP;
+	packet.sy = 0;
+	packet.header_length = 0;
+
+	err = fw_iso_context_queue(s->context, &packet, &s->buffer.iso_buffer,
+				   s->buffer.packets[index].offset);
+	if (err < 0) {
+		dev_err(&s->unit->device, "queueing error: %d\n", err);
+		s->packet_index = -1;
+		amdtp_out_stream_pcm_abort(s);
+		return;
+	}
+
+	if (++index >= QUEUE_LENGTH)
+		index = 0;
+	s->packet_index = index;
+
+	if (pcm) {
+		ptr = s->pcm_buffer_pointer + data_blocks;
+		if (ptr >= pcm->runtime->buffer_size)
+			ptr -= pcm->runtime->buffer_size;
+		ACCESS_ONCE(s->pcm_buffer_pointer) = ptr;
+
+		s->pcm_period_pointer += data_blocks;
+		if (s->pcm_period_pointer >= pcm->runtime->period_size) {
+			s->pcm_period_pointer -= pcm->runtime->period_size;
+			snd_pcm_period_elapsed(pcm);
+		}
+	}
+}
+
+static void out_packet_callback(struct fw_iso_context *context, u32 cycle,
+				size_t header_length, void *header, void *data)
+{
+	struct amdtp_out_stream *s = data;
+	unsigned int i, packets = header_length / 4;
+
+	/*
+	 * Compute the cycle of the last queued packet.
+	 * (We need only the four lowest bits for the SYT, so we can ignore
+	 * that bits 0-11 must wrap around at 3072.)
+	 */
+	cycle += QUEUE_LENGTH - packets;
+
+	for (i = 0; i < packets; ++i)
+		queue_out_packet(s, ++cycle);
+}
+
+static int queue_initial_skip_packets(struct amdtp_out_stream *s)
+{
+	struct fw_iso_packet skip_packet = {
+		.skip = 1,
+	};
+	unsigned int i;
+	int err;
+
+	for (i = 0; i < QUEUE_LENGTH; ++i) {
+		skip_packet.interrupt = IS_ALIGNED(s->packet_index + 1,
+						   INTERRUPT_INTERVAL);
+		err = fw_iso_context_queue(s->context, &skip_packet, NULL, 0);
+		if (err < 0)
+			return err;
+		if (++s->packet_index >= QUEUE_LENGTH)
+			s->packet_index = 0;
+	}
+
+	return 0;
+}
+
+/**
+ * amdtp_out_stream_start - start sending packets
+ * @s: the AMDTP output stream to start
+ * @channel: the isochronous channel on the bus
+ * @speed: firewire speed code
+ *
+ * The stream cannot be started until it has been configured with
+ * amdtp_out_stream_set_hw_params(), amdtp_out_stream_set_pcm(), and
+ * amdtp_out_stream_set_midi(); and it must be started before any
+ * PCM or MIDI device can be started.
+ */
+int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed)
+{
+	static const struct {
+		unsigned int data_block;
+		unsigned int syt_offset;
+	} initial_state[] = {
+		[CIP_SFC_32000]  = {  4, 3072 },
+		[CIP_SFC_48000]  = {  6, 1024 },
+		[CIP_SFC_96000]  = { 12, 1024 },
+		[CIP_SFC_192000] = { 24, 1024 },
+		[CIP_SFC_44100]  = {  0,   67 },
+		[CIP_SFC_88200]  = {  0,   67 },
+		[CIP_SFC_176400] = {  0,   67 },
+	};
+	int err;
+
+	mutex_lock(&s->mutex);
+
+	if (WARN_ON(!IS_ERR(s->context) ||
+		    (!s->pcm_channels && !s->midi_ports))) {
+		err = -EBADFD;
+		goto err_unlock;
+	}
+
+	s->data_block_state = initial_state[s->sfc].data_block;
+	s->syt_offset_state = initial_state[s->sfc].syt_offset;
+	s->last_syt_offset = TICKS_PER_CYCLE;
+
+	err = iso_packets_buffer_init(&s->buffer, s->unit, QUEUE_LENGTH,
+				      amdtp_out_stream_get_max_payload(s),
+				      DMA_TO_DEVICE);
+	if (err < 0)
+		goto err_unlock;
+
+	s->context = fw_iso_context_create(fw_parent_device(s->unit)->card,
+					   FW_ISO_CONTEXT_TRANSMIT,
+					   channel, speed, 0,
+					   out_packet_callback, s);
+	if (IS_ERR(s->context)) {
+		err = PTR_ERR(s->context);
+		if (err == -EBUSY)
+			dev_err(&s->unit->device,
+				"no free output stream on this controller\n");
+		goto err_buffer;
+	}
+
+	amdtp_out_stream_update(s);
+
+	s->packet_index = 0;
+	s->data_block_counter = 0;
+	err = queue_initial_skip_packets(s);
+	if (err < 0)
+		goto err_context;
+
+	err = fw_iso_context_start(s->context, -1, 0, 0);
+	if (err < 0)
+		goto err_context;
+
+	mutex_unlock(&s->mutex);
+
+	return 0;
+
+err_context:
+	fw_iso_context_destroy(s->context);
+	s->context = ERR_PTR(-1);
+err_buffer:
+	iso_packets_buffer_destroy(&s->buffer, s->unit);
+err_unlock:
+	mutex_unlock(&s->mutex);
+
+	return err;
+}
+EXPORT_SYMBOL(amdtp_out_stream_start);
+
+/**
+ * amdtp_out_stream_update - update the stream after a bus reset
+ * @s: the AMDTP output stream
+ */
+void amdtp_out_stream_update(struct amdtp_out_stream *s)
+{
+	ACCESS_ONCE(s->source_node_id_field) =
+		(fw_parent_device(s->unit)->card->node_id & 0x3f) << 24;
+}
+EXPORT_SYMBOL(amdtp_out_stream_update);
+
+/**
+ * amdtp_out_stream_stop - stop sending packets
+ * @s: the AMDTP output stream to stop
+ *
+ * All PCM and MIDI devices of the stream must be stopped before the stream
+ * itself can be stopped.
+ */
+void amdtp_out_stream_stop(struct amdtp_out_stream *s)
+{
+	mutex_lock(&s->mutex);
+
+	if (IS_ERR(s->context)) {
+		mutex_unlock(&s->mutex);
+		return;
+	}
+
+	fw_iso_context_stop(s->context);
+	fw_iso_context_destroy(s->context);
+	s->context = ERR_PTR(-1);
+	iso_packets_buffer_destroy(&s->buffer, s->unit);
+
+	mutex_unlock(&s->mutex);
+}
+EXPORT_SYMBOL(amdtp_out_stream_stop);
+
+/**
+ * amdtp_out_stream_pcm_abort - abort the running PCM device
+ * @s: the AMDTP stream about to be stopped
+ *
+ * If the isochronous stream needs to be stopped asynchronously, call this
+ * function first to stop the PCM device.
+ */
+void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s)
+{
+	struct snd_pcm_substream *pcm;
+
+	pcm = ACCESS_ONCE(s->pcm);
+	if (pcm) {
+		snd_pcm_stream_lock_irq(pcm);
+		if (snd_pcm_running(pcm))
+			snd_pcm_stop(pcm, SNDRV_PCM_STATE_XRUN);
+		snd_pcm_stream_unlock_irq(pcm);
+	}
+}
+EXPORT_SYMBOL(amdtp_out_stream_pcm_abort);
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
new file mode 100644
index 0000000..537a9cb
--- /dev/null
+++ b/sound/firewire/amdtp.h
@@ -0,0 +1,169 @@
+#ifndef SOUND_FIREWIRE_AMDTP_H_INCLUDED
+#define SOUND_FIREWIRE_AMDTP_H_INCLUDED
+
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include "packets-buffer.h"
+
+/**
+ * enum cip_out_flags - describes details of the streaming protocol
+ * @CIP_NONBLOCKING: In non-blocking mode, each packet contains
+ *	sample_rate/8000 samples, with rounding up or down to adjust
+ *	for clock skew and left-over fractional samples.  This should
+ *	be used if supported by the device.
+ */
+enum cip_out_flags {
+	CIP_NONBLOCKING = 0,
+};
+
+/**
+ * enum cip_sfc - a stream's sample rate
+ */
+enum cip_sfc {
+	CIP_SFC_32000  = 0,
+	CIP_SFC_44100  = 1,
+	CIP_SFC_48000  = 2,
+	CIP_SFC_88200  = 3,
+	CIP_SFC_96000  = 4,
+	CIP_SFC_176400 = 5,
+	CIP_SFC_192000 = 6,
+};
+
+#define AMDTP_OUT_PCM_FORMAT_BITS	(SNDRV_PCM_FMTBIT_S16 | \
+					 SNDRV_PCM_FMTBIT_S32)
+
+struct fw_unit;
+struct fw_iso_context;
+struct snd_pcm_substream;
+
+struct amdtp_out_stream {
+	struct fw_unit *unit;
+	enum cip_out_flags flags;
+	struct fw_iso_context *context;
+	struct mutex mutex;
+
+	enum cip_sfc sfc;
+	unsigned int data_block_quadlets;
+	unsigned int pcm_channels;
+	unsigned int midi_ports;
+	void (*transfer_samples)(struct amdtp_out_stream *s,
+				 struct snd_pcm_substream *pcm,
+				 __be32 *buffer, unsigned int frames);
+
+	unsigned int syt_interval;
+	unsigned int source_node_id_field;
+	struct iso_packets_buffer buffer;
+
+	struct snd_pcm_substream *pcm;
+
+	int packet_index;
+	unsigned int data_block_counter;
+
+	unsigned int data_block_state;
+
+	unsigned int last_syt_offset;
+	unsigned int syt_offset_state;
+
+	unsigned int pcm_buffer_pointer;
+	unsigned int pcm_period_pointer;
+};
+
+int amdtp_out_stream_init(struct amdtp_out_stream *s, struct fw_unit *unit,
+			  enum cip_out_flags flags);
+void amdtp_out_stream_destroy(struct amdtp_out_stream *s);
+
+void amdtp_out_stream_set_rate(struct amdtp_out_stream *s, unsigned int rate);
+unsigned int amdtp_out_stream_get_max_payload(struct amdtp_out_stream *s);
+
+int amdtp_out_stream_start(struct amdtp_out_stream *s, int channel, int speed);
+void amdtp_out_stream_update(struct amdtp_out_stream *s);
+void amdtp_out_stream_stop(struct amdtp_out_stream *s);
+
+void amdtp_out_stream_set_pcm_format(struct amdtp_out_stream *s,
+				     snd_pcm_format_t format);
+void amdtp_out_stream_pcm_abort(struct amdtp_out_stream *s);
+
+/**
+ * amdtp_out_stream_set_pcm - configure format of PCM samples
+ * @s: the AMDTP output stream to be configured
+ * @pcm_channels: the number of PCM samples in each data block, to be encoded
+ *                as AM824 multi-bit linear audio
+ *
+ * This function must not be called while the stream is running.
+ */
+static inline void amdtp_out_stream_set_pcm(struct amdtp_out_stream *s,
+					    unsigned int pcm_channels)
+{
+	s->pcm_channels = pcm_channels;
+}
+
+/**
+ * amdtp_out_stream_set_midi - configure format of MIDI data
+ * @s: the AMDTP output stream to be configured
+ * @midi_ports: the number of MIDI ports (i.e., MPX-MIDI Data Channels)
+ *
+ * This function must not be called while the stream is running.
+ */
+static inline void amdtp_out_stream_set_midi(struct amdtp_out_stream *s,
+					     unsigned int midi_ports)
+{
+	s->midi_ports = midi_ports;
+}
+
+/**
+ * amdtp_out_streaming_error - check for streaming error
+ * @s: the AMDTP output stream
+ *
+ * If this function returns true, the stream's packet queue has stopped due to
+ * an asynchronous error.
+ */
+static inline bool amdtp_out_streaming_error(struct amdtp_out_stream *s)
+{
+	return s->packet_index < 0;
+}
+
+/**
+ * amdtp_out_stream_pcm_prepare - prepare PCM device for running
+ * @s: the AMDTP output stream
+ *
+ * This function should be called from the PCM device's .prepare callback.
+ */
+static inline void amdtp_out_stream_pcm_prepare(struct amdtp_out_stream *s)
+{
+	s->pcm_buffer_pointer = 0;
+	s->pcm_period_pointer = 0;
+}
+
+/**
+ * amdtp_out_stream_pcm_trigger - start/stop playback from a PCM device
+ * @s: the AMDTP output stream
+ * @pcm: the PCM device to be started, or %NULL to stop the current device
+ *
+ * Call this function on a running isochronous stream to enable the actual
+ * transmission of PCM data.  This function should be called from the PCM
+ * device's .trigger callback.
+ */
+static inline void amdtp_out_stream_pcm_trigger(struct amdtp_out_stream *s,
+						struct snd_pcm_substream *pcm)
+{
+	ACCESS_ONCE(s->pcm) = pcm;
+}
+
+/**
+ * amdtp_out_stream_pcm_pointer - get the PCM buffer position
+ * @s: the AMDTP output stream that transports the PCM data
+ *
+ * Returns the current buffer position, in frames.
+ */
+static inline unsigned long
+amdtp_out_stream_pcm_pointer(struct amdtp_out_stream *s)
+{
+	return ACCESS_ONCE(s->pcm_buffer_pointer);
+}
+
+static inline bool cip_sfc_is_base_44100(enum cip_sfc sfc)
+{
+	return sfc & 1;
+}
+
+#endif
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c
new file mode 100644
index 0000000..4a37f3a
--- /dev/null
+++ b/sound/firewire/cmp.c
@@ -0,0 +1,308 @@
+/*
+ * Connection Management Procedures (IEC 61883-1) helper functions
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include "lib.h"
+#include "iso-resources.h"
+#include "cmp.h"
+
+#define IMPR_SPEED_MASK		0xc0000000
+#define IMPR_SPEED_SHIFT	30
+#define IMPR_XSPEED_MASK	0x00000060
+#define IMPR_XSPEED_SHIFT	5
+#define IMPR_PLUGS_MASK		0x0000001f
+
+#define IPCR_ONLINE		0x80000000
+#define IPCR_BCAST_CONN		0x40000000
+#define IPCR_P2P_CONN_MASK	0x3f000000
+#define IPCR_P2P_CONN_SHIFT	24
+#define IPCR_CHANNEL_MASK	0x003f0000
+#define IPCR_CHANNEL_SHIFT	16
+
+enum bus_reset_handling {
+	ABORT_ON_BUS_RESET,
+	SUCCEED_ON_BUS_RESET,
+};
+
+static __attribute__((format(printf, 2, 3)))
+void cmp_error(struct cmp_connection *c, const char *fmt, ...)
+{
+	va_list va;
+
+	va_start(va, fmt);
+	dev_err(&c->resources.unit->device, "%cPCR%u: %pV",
+		'i', c->pcr_index, &(struct va_format){ fmt, &va });
+	va_end(va);
+}
+
+static int pcr_modify(struct cmp_connection *c,
+		      __be32 (*modify)(struct cmp_connection *c, __be32 old),
+		      int (*check)(struct cmp_connection *c, __be32 pcr),
+		      enum bus_reset_handling bus_reset_handling)
+{
+	struct fw_device *device = fw_parent_device(c->resources.unit);
+	__be32 *buffer = c->resources.buffer;
+	int generation = c->resources.generation;
+	int rcode, errors = 0;
+	__be32 old_arg;
+	int err;
+
+	buffer[0] = c->last_pcr_value;
+	for (;;) {
+		old_arg = buffer[0];
+		buffer[1] = modify(c, buffer[0]);
+
+		rcode = fw_run_transaction(
+				device->card, TCODE_LOCK_COMPARE_SWAP,
+				device->node_id, generation, device->max_speed,
+				CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index),
+				buffer, 8);
+
+		if (rcode == RCODE_COMPLETE) {
+			if (buffer[0] == old_arg) /* success? */
+				break;
+
+			if (check) {
+				err = check(c, buffer[0]);
+				if (err < 0)
+					return err;
+			}
+		} else if (rcode == RCODE_GENERATION)
+			goto bus_reset;
+		else if (rcode_is_permanent_error(rcode) || ++errors >= 3)
+			goto io_error;
+	}
+	c->last_pcr_value = buffer[1];
+
+	return 0;
+
+io_error:
+	cmp_error(c, "transaction failed: %s\n", rcode_string(rcode));
+	return -EIO;
+
+bus_reset:
+	return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0;
+}
+
+
+/**
+ * cmp_connection_init - initializes a connection manager
+ * @c: the connection manager to initialize
+ * @unit: a unit of the target device
+ * @ipcr_index: the index of the iPCR on the target device
+ */
+int cmp_connection_init(struct cmp_connection *c,
+			struct fw_unit *unit,
+			unsigned int ipcr_index)
+{
+	__be32 impr_be;
+	u32 impr;
+	int err;
+
+	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
+				 CSR_REGISTER_BASE + CSR_IMPR,
+				 &impr_be, 4);
+	if (err < 0)
+		return err;
+	impr = be32_to_cpu(impr_be);
+
+	if (ipcr_index >= (impr & IMPR_PLUGS_MASK))
+		return -EINVAL;
+
+	err = fw_iso_resources_init(&c->resources, unit);
+	if (err < 0)
+		return err;
+
+	c->connected = false;
+	mutex_init(&c->mutex);
+	c->last_pcr_value = cpu_to_be32(0x80000000);
+	c->pcr_index = ipcr_index;
+	c->max_speed = (impr & IMPR_SPEED_MASK) >> IMPR_SPEED_SHIFT;
+	if (c->max_speed == SCODE_BETA)
+		c->max_speed += (impr & IMPR_XSPEED_MASK) >> IMPR_XSPEED_SHIFT;
+
+	return 0;
+}
+EXPORT_SYMBOL(cmp_connection_init);
+
+/**
+ * cmp_connection_destroy - free connection manager resources
+ * @c: the connection manager
+ */
+void cmp_connection_destroy(struct cmp_connection *c)
+{
+	WARN_ON(c->connected);
+	mutex_destroy(&c->mutex);
+	fw_iso_resources_destroy(&c->resources);
+}
+EXPORT_SYMBOL(cmp_connection_destroy);
+
+
+static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr)
+{
+	ipcr &= ~cpu_to_be32(IPCR_BCAST_CONN |
+			     IPCR_P2P_CONN_MASK |
+			     IPCR_CHANNEL_MASK);
+	ipcr |= cpu_to_be32(1 << IPCR_P2P_CONN_SHIFT);
+	ipcr |= cpu_to_be32(c->resources.channel << IPCR_CHANNEL_SHIFT);
+
+	return ipcr;
+}
+
+static int ipcr_set_check(struct cmp_connection *c, __be32 ipcr)
+{
+	if (ipcr & cpu_to_be32(IPCR_BCAST_CONN |
+			       IPCR_P2P_CONN_MASK)) {
+		cmp_error(c, "plug is already in use\n");
+		return -EBUSY;
+	}
+	if (!(ipcr & cpu_to_be32(IPCR_ONLINE))) {
+		cmp_error(c, "plug is not on-line\n");
+		return -ECONNREFUSED;
+	}
+
+	return 0;
+}
+
+/**
+ * cmp_connection_establish - establish a connection to the target
+ * @c: the connection manager
+ * @max_payload_bytes: the amount of data (including CIP headers) per packet
+ *
+ * This function establishes a point-to-point connection from the local
+ * computer to the target by allocating isochronous resources (channel and
+ * bandwidth) and setting the target's input plug control register.  When this
+ * function succeeds, the caller is responsible for starting transmitting
+ * packets.
+ */
+int cmp_connection_establish(struct cmp_connection *c,
+			     unsigned int max_payload_bytes)
+{
+	int err;
+
+	if (WARN_ON(c->connected))
+		return -EISCONN;
+
+	c->speed = min(c->max_speed,
+		       fw_parent_device(c->resources.unit)->max_speed);
+
+	mutex_lock(&c->mutex);
+
+retry_after_bus_reset:
+	err = fw_iso_resources_allocate(&c->resources,
+					max_payload_bytes, c->speed);
+	if (err < 0)
+		goto err_mutex;
+
+	err = pcr_modify(c, ipcr_set_modify, ipcr_set_check,
+			 ABORT_ON_BUS_RESET);
+	if (err == -EAGAIN) {
+		fw_iso_resources_free(&c->resources);
+		goto retry_after_bus_reset;
+	}
+	if (err < 0)
+		goto err_resources;
+
+	c->connected = true;
+
+	mutex_unlock(&c->mutex);
+
+	return 0;
+
+err_resources:
+	fw_iso_resources_free(&c->resources);
+err_mutex:
+	mutex_unlock(&c->mutex);
+
+	return err;
+}
+EXPORT_SYMBOL(cmp_connection_establish);
+
+/**
+ * cmp_connection_update - update the connection after a bus reset
+ * @c: the connection manager
+ *
+ * This function must be called from the driver's .update handler to reestablish
+ * any connection that might have been active.
+ *
+ * Returns zero on success, or a negative error code.  On an error, the
+ * connection is broken and the caller must stop transmitting iso packets.
+ */
+int cmp_connection_update(struct cmp_connection *c)
+{
+	int err;
+
+	mutex_lock(&c->mutex);
+
+	if (!c->connected) {
+		mutex_unlock(&c->mutex);
+		return 0;
+	}
+
+	err = fw_iso_resources_update(&c->resources);
+	if (err < 0)
+		goto err_unconnect;
+
+	err = pcr_modify(c, ipcr_set_modify, ipcr_set_check,
+			 SUCCEED_ON_BUS_RESET);
+	if (err < 0)
+		goto err_resources;
+
+	mutex_unlock(&c->mutex);
+
+	return 0;
+
+err_resources:
+	fw_iso_resources_free(&c->resources);
+err_unconnect:
+	c->connected = false;
+	mutex_unlock(&c->mutex);
+
+	return err;
+}
+EXPORT_SYMBOL(cmp_connection_update);
+
+
+static __be32 ipcr_break_modify(struct cmp_connection *c, __be32 ipcr)
+{
+	return ipcr & ~cpu_to_be32(IPCR_BCAST_CONN | IPCR_P2P_CONN_MASK);
+}
+
+/**
+ * cmp_connection_break - break the connection to the target
+ * @c: the connection manager
+ *
+ * This function deactives the connection in the target's input plug control
+ * register, and frees the isochronous resources of the connection.  Before
+ * calling this function, the caller should cease transmitting packets.
+ */
+void cmp_connection_break(struct cmp_connection *c)
+{
+	int err;
+
+	mutex_lock(&c->mutex);
+
+	if (!c->connected) {
+		mutex_unlock(&c->mutex);
+		return;
+	}
+
+	err = pcr_modify(c, ipcr_break_modify, NULL, SUCCEED_ON_BUS_RESET);
+	if (err < 0)
+		cmp_error(c, "plug is still connected\n");
+
+	fw_iso_resources_free(&c->resources);
+
+	c->connected = false;
+
+	mutex_unlock(&c->mutex);
+}
+EXPORT_SYMBOL(cmp_connection_break);
diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h
new file mode 100644
index 0000000..f47de08
--- /dev/null
+++ b/sound/firewire/cmp.h
@@ -0,0 +1,41 @@
+#ifndef SOUND_FIREWIRE_CMP_H_INCLUDED
+#define SOUND_FIREWIRE_CMP_H_INCLUDED
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include "iso-resources.h"
+
+struct fw_unit;
+
+/**
+ * struct cmp_connection - manages an isochronous connection to a device
+ * @speed: the connection's actual speed
+ *
+ * This structure manages (using CMP) an isochronous stream from the local
+ * computer to a device's input plug (iPCR).
+ *
+ * There is no corresponding oPCR created on the local computer, so it is not
+ * possible to overlay connections on top of this one.
+ */
+struct cmp_connection {
+	int speed;
+	/* private: */
+	bool connected;
+	struct mutex mutex;
+	struct fw_iso_resources resources;
+	__be32 last_pcr_value;
+	unsigned int pcr_index;
+	unsigned int max_speed;
+};
+
+int cmp_connection_init(struct cmp_connection *connection,
+			struct fw_unit *unit,
+			unsigned int ipcr_index);
+void cmp_connection_destroy(struct cmp_connection *connection);
+
+int cmp_connection_establish(struct cmp_connection *connection,
+			     unsigned int max_payload);
+int cmp_connection_update(struct cmp_connection *connection);
+void cmp_connection_break(struct cmp_connection *connection);
+
+#endif
diff --git a/sound/firewire/fcp.c b/sound/firewire/fcp.c
new file mode 100644
index 0000000..ec578b5
--- /dev/null
+++ b/sound/firewire/fcp.c
@@ -0,0 +1,224 @@
+/*
+ * Function Control Protocol (IEC 61883-1) helper functions
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include "fcp.h"
+#include "lib.h"
+
+#define CTS_AVC 0x00
+
+#define ERROR_RETRIES	3
+#define ERROR_DELAY_MS	5
+#define FCP_TIMEOUT_MS	125
+
+static DEFINE_SPINLOCK(transactions_lock);
+static LIST_HEAD(transactions);
+
+enum fcp_state {
+	STATE_PENDING,
+	STATE_BUS_RESET,
+	STATE_COMPLETE,
+};
+
+struct fcp_transaction {
+	struct list_head list;
+	struct fw_unit *unit;
+	void *response_buffer;
+	unsigned int response_size;
+	unsigned int response_match_bytes;
+	enum fcp_state state;
+	wait_queue_head_t wait;
+};
+
+/**
+ * fcp_avc_transaction - send an AV/C command and wait for its response
+ * @unit: a unit on the target device
+ * @command: a buffer containing the command frame; must be DMA-able
+ * @command_size: the size of @command
+ * @response: a buffer for the response frame
+ * @response_size: the maximum size of @response
+ * @response_match_bytes: a bitmap specifying the bytes used to detect the
+ *                        correct response frame
+ *
+ * This function sends a FCP command frame to the target and waits for the
+ * corresponding response frame to be returned.
+ *
+ * Because it is possible for multiple FCP transactions to be active at the
+ * same time, the correct response frame is detected by the value of certain
+ * bytes.  These bytes must be set in @response before calling this function,
+ * and the corresponding bits must be set in @response_match_bytes.
+ *
+ * @command and @response can point to the same buffer.
+ *
+ * Asynchronous operation (INTERIM, NOTIFY) is not supported at the moment.
+ *
+ * Returns the actual size of the response frame, or a negative error code.
+ */
+int fcp_avc_transaction(struct fw_unit *unit,
+			const void *command, unsigned int command_size,
+			void *response, unsigned int response_size,
+			unsigned int response_match_bytes)
+{
+	struct fcp_transaction t;
+	int tcode, ret, tries = 0;
+
+	t.unit = unit;
+	t.response_buffer = response;
+	t.response_size = response_size;
+	t.response_match_bytes = response_match_bytes;
+	t.state = STATE_PENDING;
+	init_waitqueue_head(&t.wait);
+
+	spin_lock_irq(&transactions_lock);
+	list_add_tail(&t.list, &transactions);
+	spin_unlock_irq(&transactions_lock);
+
+	for (;;) {
+		tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST
+					  : TCODE_WRITE_BLOCK_REQUEST;
+		ret = snd_fw_transaction(t.unit, tcode,
+					 CSR_REGISTER_BASE + CSR_FCP_COMMAND,
+					 (void *)command, command_size);
+		if (ret < 0)
+			break;
+
+		wait_event_timeout(t.wait, t.state != STATE_PENDING,
+				   msecs_to_jiffies(FCP_TIMEOUT_MS));
+
+		if (t.state == STATE_COMPLETE) {
+			ret = t.response_size;
+			break;
+		} else if (t.state == STATE_BUS_RESET) {
+			msleep(ERROR_DELAY_MS);
+		} else if (++tries >= ERROR_RETRIES) {
+			dev_err(&t.unit->device, "FCP command timed out\n");
+			ret = -EIO;
+			break;
+		}
+	}
+
+	spin_lock_irq(&transactions_lock);
+	list_del(&t.list);
+	spin_unlock_irq(&transactions_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(fcp_avc_transaction);
+
+/**
+ * fcp_bus_reset - inform the target handler about a bus reset
+ * @unit: the unit that might be used by fcp_avc_transaction()
+ *
+ * This function must be called from the driver's .update handler to inform
+ * the FCP transaction handler that a bus reset has happened.  Any pending FCP
+ * transactions are retried.
+ */
+void fcp_bus_reset(struct fw_unit *unit)
+{
+	struct fcp_transaction *t;
+
+	spin_lock_irq(&transactions_lock);
+	list_for_each_entry(t, &transactions, list) {
+		if (t->unit == unit &&
+		    t->state == STATE_PENDING) {
+			t->state = STATE_BUS_RESET;
+			wake_up(&t->wait);
+		}
+	}
+	spin_unlock_irq(&transactions_lock);
+}
+EXPORT_SYMBOL(fcp_bus_reset);
+
+/* checks whether the response matches the masked bytes in response_buffer */
+static bool is_matching_response(struct fcp_transaction *transaction,
+				 const void *response, size_t length)
+{
+	const u8 *p1, *p2;
+	unsigned int mask, i;
+
+	p1 = response;
+	p2 = transaction->response_buffer;
+	mask = transaction->response_match_bytes;
+
+	for (i = 0; ; ++i) {
+		if ((mask & 1) && p1[i] != p2[i])
+			return false;
+		mask >>= 1;
+		if (!mask)
+			return true;
+		if (--length == 0)
+			return false;
+	}
+}
+
+static void fcp_response(struct fw_card *card, struct fw_request *request,
+			 int tcode, int destination, int source,
+			 int generation, unsigned long long offset,
+			 void *data, size_t length, void *callback_data)
+{
+	struct fcp_transaction *t;
+	unsigned long flags;
+
+	if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC)
+		return;
+
+	spin_lock_irqsave(&transactions_lock, flags);
+	list_for_each_entry(t, &transactions, list) {
+		struct fw_device *device = fw_parent_device(t->unit);
+		if (device->card != card ||
+		    device->generation != generation)
+			continue;
+		smp_rmb(); /* node_id vs. generation */
+		if (device->node_id != source)
+			continue;
+
+		if (t->state == STATE_PENDING &&
+		    is_matching_response(t, data, length)) {
+			t->state = STATE_COMPLETE;
+			t->response_size = min((unsigned int)length,
+					       t->response_size);
+			memcpy(t->response_buffer, data, t->response_size);
+			wake_up(&t->wait);
+		}
+	}
+	spin_unlock_irqrestore(&transactions_lock, flags);
+}
+
+static struct fw_address_handler response_register_handler = {
+	.length = 0x200,
+	.address_callback = fcp_response,
+};
+
+static int __init fcp_module_init(void)
+{
+	static const struct fw_address_region response_register_region = {
+		.start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
+		.end = CSR_REGISTER_BASE + CSR_FCP_END,
+	};
+
+	fw_core_add_address_handler(&response_register_handler,
+				    &response_register_region);
+
+	return 0;
+}
+
+static void __exit fcp_module_exit(void)
+{
+	WARN_ON(!list_empty(&transactions));
+	fw_core_remove_address_handler(&response_register_handler);
+}
+
+module_init(fcp_module_init);
+module_exit(fcp_module_exit);
diff --git a/sound/firewire/fcp.h b/sound/firewire/fcp.h
new file mode 100644
index 0000000..8659568
--- /dev/null
+++ b/sound/firewire/fcp.h
@@ -0,0 +1,12 @@
+#ifndef SOUND_FIREWIRE_FCP_H_INCLUDED
+#define SOUND_FIREWIRE_FCP_H_INCLUDED
+
+struct fw_unit;
+
+int fcp_avc_transaction(struct fw_unit *unit,
+			const void *command, unsigned int command_size,
+			void *response, unsigned int response_size,
+			unsigned int response_match_bytes);
+void fcp_bus_reset(struct fw_unit *unit);
+
+#endif
diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c
new file mode 100644
index 0000000..775dbd5
--- /dev/null
+++ b/sound/firewire/iso-resources.c
@@ -0,0 +1,232 @@
+/*
+ * isochronous resources helper functions
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "iso-resources.h"
+
+/**
+ * fw_iso_resources_init - initializes a &struct fw_iso_resources
+ * @r: the resource manager to initialize
+ * @unit: the device unit for which the resources will be needed
+ *
+ * If the device does not support all channel numbers, change @r->channels_mask
+ * after calling this function.
+ */
+int fw_iso_resources_init(struct fw_iso_resources *r, struct fw_unit *unit)
+{
+	r->buffer = kmalloc(2 * 4, GFP_KERNEL);
+	if (!r->buffer)
+		return -ENOMEM;
+
+	r->channels_mask = ~0uLL;
+	r->unit = fw_unit_get(unit);
+	mutex_init(&r->mutex);
+	r->allocated = false;
+
+	return 0;
+}
+
+/**
+ * fw_iso_resources_destroy - destroy a resource manager
+ * @r: the resource manager that is no longer needed
+ */
+void fw_iso_resources_destroy(struct fw_iso_resources *r)
+{
+	WARN_ON(r->allocated);
+	kfree(r->buffer);
+	mutex_destroy(&r->mutex);
+	fw_unit_put(r->unit);
+}
+
+static unsigned int packet_bandwidth(unsigned int max_payload_bytes, int speed)
+{
+	unsigned int bytes, s400_bytes;
+
+	/* iso packets have three header quadlets and quadlet-aligned payload */
+	bytes = 3 * 4 + ALIGN(max_payload_bytes, 4);
+
+	/* convert to bandwidth units (quadlets at S1600 = bytes at S400) */
+	if (speed <= SCODE_400)
+		s400_bytes = bytes * (1 << (SCODE_400 - speed));
+	else
+		s400_bytes = DIV_ROUND_UP(bytes, 1 << (speed - SCODE_400));
+
+	return s400_bytes;
+}
+
+static int current_bandwidth_overhead(struct fw_card *card)
+{
+	/*
+	 * Under the usual pessimistic assumption (cable length 4.5 m), the
+	 * isochronous overhead for N cables is 1.797 Âľs + N * 0.494 Âľs, or
+	 * 88.3 + N * 24.3 in bandwidth units.
+	 *
+	 * The calculation below tries to deduce N from the current gap count.
+	 * If the gap count has been optimized by measuring the actual packet
+	 * transmission time, this derived overhead should be near the actual
+	 * overhead as well.
+	 */
+	return card->gap_count < 63 ? card->gap_count * 97 / 10 + 89 : 512;
+}
+
+static int wait_isoch_resource_delay_after_bus_reset(struct fw_card *card)
+{
+	for (;;) {
+		s64 delay = (card->reset_jiffies + HZ) - get_jiffies_64();
+		if (delay <= 0)
+			return 0;
+		if (schedule_timeout_interruptible(delay) > 0)
+			return -ERESTARTSYS;
+	}
+}
+
+/**
+ * fw_iso_resources_allocate - allocate isochronous channel and bandwidth
+ * @r: the resource manager
+ * @max_payload_bytes: the amount of data (including CIP headers) per packet
+ * @speed: the speed (e.g., SCODE_400) at which the packets will be sent
+ *
+ * This function allocates one isochronous channel and enough bandwidth for the
+ * specified packet size.
+ *
+ * Returns the channel number that the caller must use for streaming, or
+ * a negative error code.  Due to potentionally long delays, this function is
+ * interruptible and can return -ERESTARTSYS.  On success, the caller is
+ * responsible for calling fw_iso_resources_update() on bus resets, and
+ * fw_iso_resources_free() when the resources are not longer needed.
+ */
+int fw_iso_resources_allocate(struct fw_iso_resources *r,
+			      unsigned int max_payload_bytes, int speed)
+{
+	struct fw_card *card = fw_parent_device(r->unit)->card;
+	int bandwidth, channel, err;
+
+	if (WARN_ON(r->allocated))
+		return -EBADFD;
+
+	r->bandwidth = packet_bandwidth(max_payload_bytes, speed);
+
+retry_after_bus_reset:
+	spin_lock_irq(&card->lock);
+	r->generation = card->generation;
+	r->bandwidth_overhead = current_bandwidth_overhead(card);
+	spin_unlock_irq(&card->lock);
+
+	err = wait_isoch_resource_delay_after_bus_reset(card);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&r->mutex);
+
+	bandwidth = r->bandwidth + r->bandwidth_overhead;
+	fw_iso_resource_manage(card, r->generation, r->channels_mask,
+			       &channel, &bandwidth, true, r->buffer);
+	if (channel == -EAGAIN) {
+		mutex_unlock(&r->mutex);
+		goto retry_after_bus_reset;
+	}
+	if (channel >= 0) {
+		r->channel = channel;
+		r->allocated = true;
+	} else {
+		if (channel == -EBUSY)
+			dev_err(&r->unit->device,
+				"isochronous resources exhausted\n");
+		else
+			dev_err(&r->unit->device,
+				"isochronous resource allocation failed\n");
+	}
+
+	mutex_unlock(&r->mutex);
+
+	return channel;
+}
+
+/**
+ * fw_iso_resources_update - update resource allocations after a bus reset
+ * @r: the resource manager
+ *
+ * This function must be called from the driver's .update handler to reallocate
+ * any resources that were allocated before the bus reset.  It is safe to call
+ * this function if no resources are currently allocated.
+ *
+ * Returns a negative error code on failure.  If this happens, the caller must
+ * stop streaming.
+ */
+int fw_iso_resources_update(struct fw_iso_resources *r)
+{
+	struct fw_card *card = fw_parent_device(r->unit)->card;
+	int bandwidth, channel;
+
+	mutex_lock(&r->mutex);
+
+	if (!r->allocated) {
+		mutex_unlock(&r->mutex);
+		return 0;
+	}
+
+	spin_lock_irq(&card->lock);
+	r->generation = card->generation;
+	r->bandwidth_overhead = current_bandwidth_overhead(card);
+	spin_unlock_irq(&card->lock);
+
+	bandwidth = r->bandwidth + r->bandwidth_overhead;
+
+	fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
+			       &channel, &bandwidth, true, r->buffer);
+	/*
+	 * When another bus reset happens, pretend that the allocation
+	 * succeeded; we will try again for the new generation later.
+	 */
+	if (channel < 0 && channel != -EAGAIN) {
+		r->allocated = false;
+		if (channel == -EBUSY)
+			dev_err(&r->unit->device,
+				"isochronous resources exhausted\n");
+		else
+			dev_err(&r->unit->device,
+				"isochronous resource allocation failed\n");
+	}
+
+	mutex_unlock(&r->mutex);
+
+	return channel;
+}
+
+/**
+ * fw_iso_resources_free - frees allocated resources
+ * @r: the resource manager
+ *
+ * This function deallocates the channel and bandwidth, if allocated.
+ */
+void fw_iso_resources_free(struct fw_iso_resources *r)
+{
+	struct fw_card *card = fw_parent_device(r->unit)->card;
+	int bandwidth, channel;
+
+	mutex_lock(&r->mutex);
+
+	if (r->allocated) {
+		bandwidth = r->bandwidth + r->bandwidth_overhead;
+		fw_iso_resource_manage(card, r->generation, 1uLL << r->channel,
+				       &channel, &bandwidth, false, r->buffer);
+		if (channel < 0)
+			dev_err(&r->unit->device,
+				"isochronous resource deallocation failed\n");
+
+		r->allocated = false;
+	}
+
+	mutex_unlock(&r->mutex);
+}
diff --git a/sound/firewire/iso-resources.h b/sound/firewire/iso-resources.h
new file mode 100644
index 0000000..3f0730e4
--- /dev/null
+++ b/sound/firewire/iso-resources.h
@@ -0,0 +1,39 @@
+#ifndef SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED
+#define SOUND_FIREWIRE_ISO_RESOURCES_H_INCLUDED
+
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+struct fw_unit;
+
+/**
+ * struct fw_iso_resources - manages channel/bandwidth allocation
+ * @channels_mask: if the device does not support all channel numbers, set this
+ *                 bit mask to something else than the default (all ones)
+ *
+ * This structure manages (de)allocation of isochronous resources (channel and
+ * bandwidth) for one isochronous stream.
+ */
+struct fw_iso_resources {
+	u64 channels_mask;
+	/* private: */
+	struct fw_unit *unit;
+	struct mutex mutex;
+	unsigned int channel;
+	unsigned int bandwidth; /* in bandwidth units, without overhead */
+	unsigned int bandwidth_overhead;
+	int generation; /* in which allocation is valid */
+	bool allocated;
+	__be32 *buffer;
+};
+
+int fw_iso_resources_init(struct fw_iso_resources *r,
+			  struct fw_unit *unit);
+void fw_iso_resources_destroy(struct fw_iso_resources *r);
+
+int fw_iso_resources_allocate(struct fw_iso_resources *r,
+			      unsigned int max_payload_bytes, int speed);
+int fw_iso_resources_update(struct fw_iso_resources *r);
+void fw_iso_resources_free(struct fw_iso_resources *r);
+
+#endif
diff --git a/sound/firewire/lib.c b/sound/firewire/lib.c
new file mode 100644
index 0000000..4750cea
--- /dev/null
+++ b/sound/firewire/lib.c
@@ -0,0 +1,85 @@
+/*
+ * miscellaneous helper functions
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/module.h>
+#include "lib.h"
+
+#define ERROR_RETRY_DELAY_MS	5
+
+/**
+ * rcode_string - convert a firewire result code to a string
+ * @rcode: the result
+ */
+const char *rcode_string(unsigned int rcode)
+{
+	static const char *const names[] = {
+		[RCODE_COMPLETE]	= "complete",
+		[RCODE_CONFLICT_ERROR]	= "conflict error",
+		[RCODE_DATA_ERROR]	= "data error",
+		[RCODE_TYPE_ERROR]	= "type error",
+		[RCODE_ADDRESS_ERROR]	= "address error",
+		[RCODE_SEND_ERROR]	= "send error",
+		[RCODE_CANCELLED]	= "cancelled",
+		[RCODE_BUSY]		= "busy",
+		[RCODE_GENERATION]	= "generation",
+		[RCODE_NO_ACK]		= "no ack",
+	};
+
+	if (rcode < ARRAY_SIZE(names) && names[rcode])
+		return names[rcode];
+	else
+		return "unknown";
+}
+EXPORT_SYMBOL(rcode_string);
+
+/**
+ * snd_fw_transaction - send a request and wait for its completion
+ * @unit: the driver's unit on the target device
+ * @tcode: the transaction code
+ * @offset: the address in the target's address space
+ * @buffer: input/output data
+ * @length: length of @buffer
+ *
+ * Submits an asynchronous request to the target device, and waits for the
+ * response.  The node ID and the current generation are derived from @unit.
+ * On a bus reset or an error, the transaction is retried a few times.
+ * Returns zero on success, or a negative error code.
+ */
+int snd_fw_transaction(struct fw_unit *unit, int tcode,
+		       u64 offset, void *buffer, size_t length)
+{
+	struct fw_device *device = fw_parent_device(unit);
+	int generation, rcode, tries = 0;
+
+	for (;;) {
+		generation = device->generation;
+		smp_rmb(); /* node_id vs. generation */
+		rcode = fw_run_transaction(device->card, tcode,
+					   device->node_id, generation,
+					   device->max_speed, offset,
+					   buffer, length);
+
+		if (rcode == RCODE_COMPLETE)
+			return 0;
+
+		if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
+			dev_err(&unit->device, "transaction failed: %s\n",
+				rcode_string(rcode));
+			return -EIO;
+		}
+
+		msleep(ERROR_RETRY_DELAY_MS);
+	}
+}
+EXPORT_SYMBOL(snd_fw_transaction);
+
+MODULE_DESCRIPTION("FireWire audio helper functions");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
new file mode 100644
index 0000000..064f3fd
--- /dev/null
+++ b/sound/firewire/lib.h
@@ -0,0 +1,19 @@
+#ifndef SOUND_FIREWIRE_LIB_H_INCLUDED
+#define SOUND_FIREWIRE_LIB_H_INCLUDED
+
+#include <linux/firewire-constants.h>
+#include <linux/types.h>
+
+struct fw_unit;
+
+int snd_fw_transaction(struct fw_unit *unit, int tcode,
+		       u64 offset, void *buffer, size_t length);
+const char *rcode_string(unsigned int rcode);
+
+/* returns true if retrying the transaction would not make sense */
+static inline bool rcode_is_permanent_error(int rcode)
+{
+	return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR;
+}
+
+#endif
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c
new file mode 100644
index 0000000..1e20e60
--- /dev/null
+++ b/sound/firewire/packets-buffer.c
@@ -0,0 +1,74 @@
+/*
+ * helpers for managing a buffer for many packets
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/firewire.h>
+#include <linux/slab.h>
+#include "packets-buffer.h"
+
+/**
+ * iso_packets_buffer_init - allocates the memory for packets
+ * @b: the buffer structure to initialize
+ * @unit: the device at the other end of the stream
+ * @count: the number of packets
+ * @packet_size: the (maximum) size of a packet, in bytes
+ * @direction: %DMA_TO_DEVICE or %DMA_FROM_DEVICE
+ */
+int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
+			    unsigned int count, unsigned int packet_size,
+			    enum dma_data_direction direction)
+{
+	unsigned int packets_per_page, pages;
+	unsigned int i, page_index, offset_in_page;
+	void *p;
+	int err;
+
+	b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL);
+	if (!b->packets) {
+		err = -ENOMEM;
+		goto error;
+	}
+
+	packet_size = L1_CACHE_ALIGN(packet_size);
+	packets_per_page = PAGE_SIZE / packet_size;
+	if (WARN_ON(!packets_per_page)) {
+		err = -EINVAL;
+		goto error;
+	}
+	pages = DIV_ROUND_UP(count, packets_per_page);
+
+	err = fw_iso_buffer_init(&b->iso_buffer, fw_parent_device(unit)->card,
+				 pages, direction);
+	if (err < 0)
+		goto err_packets;
+
+	for (i = 0; i < count; ++i) {
+		page_index = i / packets_per_page;
+		p = page_address(b->iso_buffer.pages[page_index]);
+		offset_in_page = (i % packets_per_page) * packet_size;
+		b->packets[i].buffer = p + offset_in_page;
+		b->packets[i].offset = page_index * PAGE_SIZE + offset_in_page;
+	}
+
+	return 0;
+
+err_packets:
+	kfree(b->packets);
+error:
+	return err;
+}
+
+/**
+ * iso_packets_buffer_destroy - frees packet buffer resources
+ * @b: the buffer structure to free
+ * @unit: the device at the other end of the stream
+ */
+void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
+				struct fw_unit *unit)
+{
+	fw_iso_buffer_destroy(&b->iso_buffer, fw_parent_device(unit)->card);
+	kfree(b->packets);
+}
diff --git a/sound/firewire/packets-buffer.h b/sound/firewire/packets-buffer.h
new file mode 100644
index 0000000..6513c5c
--- /dev/null
+++ b/sound/firewire/packets-buffer.h
@@ -0,0 +1,26 @@
+#ifndef SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED
+#define SOUND_FIREWIRE_PACKETS_BUFFER_H_INCLUDED
+
+#include <linux/dma-mapping.h>
+#include <linux/firewire.h>
+
+/**
+ * struct iso_packets_buffer - manages a buffer for many packets
+ * @iso_buffer: the memory containing the packets
+ * @packets: an array, with each element pointing to one packet
+ */
+struct iso_packets_buffer {
+	struct fw_iso_buffer iso_buffer;
+	struct {
+		void *buffer;
+		unsigned int offset;
+	} *packets;
+};
+
+int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
+			    unsigned int count, unsigned int packet_size,
+			    enum dma_data_direction direction);
+void iso_packets_buffer_destroy(struct iso_packets_buffer *b,
+				struct fw_unit *unit);
+
+#endif
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
new file mode 100644
index 0000000..0fce921
--- /dev/null
+++ b/sound/firewire/speakers.c
@@ -0,0 +1,858 @@
+/*
+ * OXFW970-based speakers driver
+ *
+ * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#include <linux/device.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <sound/control.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include "cmp.h"
+#include "fcp.h"
+#include "amdtp.h"
+#include "lib.h"
+
+#define OXFORD_FIRMWARE_ID_ADDRESS	(CSR_REGISTER_BASE + 0x50000)
+/* 0x970?vvvv or 0x971?vvvv, where vvvv = firmware version */
+
+#define OXFORD_HARDWARE_ID_ADDRESS	(CSR_REGISTER_BASE + 0x90020)
+#define OXFORD_HARDWARE_ID_OXFW970	0x39443841
+#define OXFORD_HARDWARE_ID_OXFW971	0x39373100
+
+#define VENDOR_GRIFFIN		0x001292
+#define VENDOR_LACIE		0x00d04b
+
+#define SPECIFIER_1394TA	0x00a02d
+#define VERSION_AVC		0x010001
+
+struct device_info {
+	const char *driver_name;
+	const char *short_name;
+	const char *long_name;
+	int (*pcm_constraints)(struct snd_pcm_runtime *runtime);
+	unsigned int mixer_channels;
+	u8 mute_fb_id;
+	u8 volume_fb_id;
+};
+
+struct fwspk {
+	struct snd_card *card;
+	struct fw_unit *unit;
+	const struct device_info *device_info;
+	struct snd_pcm_substream *pcm;
+	struct mutex mutex;
+	struct cmp_connection connection;
+	struct amdtp_out_stream stream;
+	bool stream_running;
+	bool mute;
+	s16 volume[6];
+	s16 volume_min;
+	s16 volume_max;
+};
+
+MODULE_DESCRIPTION("FireWire speakers driver");
+MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
+MODULE_LICENSE("GPL v2");
+
+static int firewave_rate_constraint(struct snd_pcm_hw_params *params,
+				    struct snd_pcm_hw_rule *rule)
+{
+	static unsigned int stereo_rates[] = { 48000, 96000 };
+	struct snd_interval *channels =
+			hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct snd_interval *rate =
+			hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+	/* two channels work only at 48/96 kHz */
+	if (snd_interval_max(channels) < 6)
+		return snd_interval_list(rate, 2, stereo_rates, 0);
+	return 0;
+}
+
+static int firewave_channels_constraint(struct snd_pcm_hw_params *params,
+					struct snd_pcm_hw_rule *rule)
+{
+	static const struct snd_interval all_channels = { .min = 6, .max = 6 };
+	struct snd_interval *rate =
+			hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels =
+			hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	/* 32/44.1 kHz work only with all six channels */
+	if (snd_interval_max(rate) < 48000)
+		return snd_interval_refine(channels, &all_channels);
+	return 0;
+}
+
+static int firewave_constraints(struct snd_pcm_runtime *runtime)
+{
+	static unsigned int channels_list[] = { 2, 6 };
+	static struct snd_pcm_hw_constraint_list channels_list_constraint = {
+		.count = 2,
+		.list = channels_list,
+	};
+	int err;
+
+	runtime->hw.rates = SNDRV_PCM_RATE_32000 |
+			    SNDRV_PCM_RATE_44100 |
+			    SNDRV_PCM_RATE_48000 |
+			    SNDRV_PCM_RATE_96000;
+	runtime->hw.channels_max = 6;
+
+	err = snd_pcm_hw_constraint_list(runtime, 0,
+					 SNDRV_PCM_HW_PARAM_CHANNELS,
+					 &channels_list_constraint);
+	if (err < 0)
+		return err;
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  firewave_rate_constraint, NULL,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (err < 0)
+		return err;
+	err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+				  firewave_channels_constraint, NULL,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int lacie_speakers_constraints(struct snd_pcm_runtime *runtime)
+{
+	runtime->hw.rates = SNDRV_PCM_RATE_32000 |
+			    SNDRV_PCM_RATE_44100 |
+			    SNDRV_PCM_RATE_48000 |
+			    SNDRV_PCM_RATE_88200 |
+			    SNDRV_PCM_RATE_96000;
+
+	return 0;
+}
+
+static int fwspk_open(struct snd_pcm_substream *substream)
+{
+	static const struct snd_pcm_hardware hardware = {
+		.info = SNDRV_PCM_INFO_MMAP |
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_BATCH |
+			SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_BLOCK_TRANSFER,
+		.formats = AMDTP_OUT_PCM_FORMAT_BITS,
+		.channels_min = 2,
+		.channels_max = 2,
+		.buffer_bytes_max = 4 * 1024 * 1024,
+		.period_bytes_min = 1,
+		.period_bytes_max = UINT_MAX,
+		.periods_min = 1,
+		.periods_max = UINT_MAX,
+	};
+	struct fwspk *fwspk = substream->private_data;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	int err;
+
+	runtime->hw = hardware;
+
+	err = fwspk->device_info->pcm_constraints(runtime);
+	if (err < 0)
+		return err;
+	err = snd_pcm_limit_hw_rates(runtime);
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_minmax(runtime,
+					   SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+					   5000, 8192000);
+	if (err < 0)
+		return err;
+
+	err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int fwspk_close(struct snd_pcm_substream *substream)
+{
+	return 0;
+}
+
+static void fwspk_stop_stream(struct fwspk *fwspk)
+{
+	if (fwspk->stream_running) {
+		amdtp_out_stream_stop(&fwspk->stream);
+		cmp_connection_break(&fwspk->connection);
+		fwspk->stream_running = false;
+	}
+}
+
+static int fwspk_set_rate(struct fwspk *fwspk, unsigned int sfc)
+{
+	u8 *buf;
+	int err;
+
+	buf = kmalloc(8, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = 0x00;		/* AV/C, CONTROL */
+	buf[1] = 0xff;		/* unit */
+	buf[2] = 0x19;		/* INPUT PLUG SIGNAL FORMAT */
+	buf[3] = 0x00;		/* plug 0 */
+	buf[4] = 0x90;		/* format: audio */
+	buf[5] = 0x00 | sfc;	/* AM824, frequency */
+	buf[6] = 0xff;		/* SYT (not used) */
+	buf[7] = 0xff;
+
+	err = fcp_avc_transaction(fwspk->unit, buf, 8, buf, 8,
+				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
+	if (err < 0)
+		goto error;
+	if (err < 6 || buf[0] != 0x09 /* ACCEPTED */) {
+		dev_err(&fwspk->unit->device, "failed to set sample rate\n");
+		err = -EIO;
+		goto error;
+	}
+
+	err = 0;
+
+error:
+	kfree(buf);
+
+	return err;
+}
+
+static int fwspk_hw_params(struct snd_pcm_substream *substream,
+			   struct snd_pcm_hw_params *hw_params)
+{
+	struct fwspk *fwspk = substream->private_data;
+	int err;
+
+	mutex_lock(&fwspk->mutex);
+	fwspk_stop_stream(fwspk);
+	mutex_unlock(&fwspk->mutex);
+
+	err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
+					       params_buffer_bytes(hw_params));
+	if (err < 0)
+		goto error;
+
+	amdtp_out_stream_set_rate(&fwspk->stream, params_rate(hw_params));
+	amdtp_out_stream_set_pcm(&fwspk->stream, params_channels(hw_params));
+
+	amdtp_out_stream_set_pcm_format(&fwspk->stream,
+					params_format(hw_params));
+
+	err = fwspk_set_rate(fwspk, fwspk->stream.sfc);
+	if (err < 0)
+		goto err_buffer;
+
+	return 0;
+
+err_buffer:
+	snd_pcm_lib_free_vmalloc_buffer(substream);
+error:
+	return err;
+}
+
+static int fwspk_hw_free(struct snd_pcm_substream *substream)
+{
+	struct fwspk *fwspk = substream->private_data;
+
+	mutex_lock(&fwspk->mutex);
+	fwspk_stop_stream(fwspk);
+	mutex_unlock(&fwspk->mutex);
+
+	return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+static int fwspk_prepare(struct snd_pcm_substream *substream)
+{
+	struct fwspk *fwspk = substream->private_data;
+	int err;
+
+	mutex_lock(&fwspk->mutex);
+
+	if (amdtp_out_streaming_error(&fwspk->stream))
+		fwspk_stop_stream(fwspk);
+
+	if (!fwspk->stream_running) {
+		err = cmp_connection_establish(&fwspk->connection,
+			amdtp_out_stream_get_max_payload(&fwspk->stream));
+		if (err < 0)
+			goto err_mutex;
+
+		err = amdtp_out_stream_start(&fwspk->stream,
+					fwspk->connection.resources.channel,
+					fwspk->connection.speed);
+		if (err < 0)
+			goto err_connection;
+
+		fwspk->stream_running = true;
+	}
+
+	mutex_unlock(&fwspk->mutex);
+
+	amdtp_out_stream_pcm_prepare(&fwspk->stream);
+
+	return 0;
+
+err_connection:
+	cmp_connection_break(&fwspk->connection);
+err_mutex:
+	mutex_unlock(&fwspk->mutex);
+
+	return err;
+}
+
+static int fwspk_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct fwspk *fwspk = substream->private_data;
+	struct snd_pcm_substream *pcm;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		pcm = substream;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		pcm = NULL;
+		break;
+	default:
+		return -EINVAL;
+	}
+	amdtp_out_stream_pcm_trigger(&fwspk->stream, pcm);
+	return 0;
+}
+
+static snd_pcm_uframes_t fwspk_pointer(struct snd_pcm_substream *substream)
+{
+	struct fwspk *fwspk = substream->private_data;
+
+	return amdtp_out_stream_pcm_pointer(&fwspk->stream);
+}
+
+static int fwspk_create_pcm(struct fwspk *fwspk)
+{
+	static struct snd_pcm_ops ops = {
+		.open      = fwspk_open,
+		.close     = fwspk_close,
+		.ioctl     = snd_pcm_lib_ioctl,
+		.hw_params = fwspk_hw_params,
+		.hw_free   = fwspk_hw_free,
+		.prepare   = fwspk_prepare,
+		.trigger   = fwspk_trigger,
+		.pointer   = fwspk_pointer,
+		.page      = snd_pcm_lib_get_vmalloc_page,
+		.mmap      = snd_pcm_lib_mmap_vmalloc,
+	};
+	struct snd_pcm *pcm;
+	int err;
+
+	err = snd_pcm_new(fwspk->card, "OXFW970", 0, 1, 0, &pcm);
+	if (err < 0)
+		return err;
+	pcm->private_data = fwspk;
+	strcpy(pcm->name, fwspk->device_info->short_name);
+	fwspk->pcm = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+	fwspk->pcm->ops = &ops;
+	return 0;
+}
+
+enum control_action { CTL_READ, CTL_WRITE };
+enum control_attribute {
+	CTL_MIN		= 0x02,
+	CTL_MAX		= 0x03,
+	CTL_CURRENT	= 0x10,
+};
+
+static int fwspk_mute_command(struct fwspk *fwspk, bool *value,
+			      enum control_action action)
+{
+	u8 *buf;
+	u8 response_ok;
+	int err;
+
+	buf = kmalloc(11, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (action == CTL_READ) {
+		buf[0] = 0x01;		/* AV/C, STATUS */
+		response_ok = 0x0c;	/*       STABLE */
+	} else {
+		buf[0] = 0x00;		/* AV/C, CONTROL */
+		response_ok = 0x09;	/*       ACCEPTED */
+	}
+	buf[1] = 0x08;			/* audio unit 0 */
+	buf[2] = 0xb8;			/* FUNCTION BLOCK */
+	buf[3] = 0x81;			/* function block type: feature */
+	buf[4] = fwspk->device_info->mute_fb_id; /* function block ID */
+	buf[5] = 0x10;			/* control attribute: current */
+	buf[6] = 0x02;			/* selector length */
+	buf[7] = 0x00;			/* audio channel number */
+	buf[8] = 0x01;			/* control selector: mute */
+	buf[9] = 0x01;			/* control data length */
+	if (action == CTL_READ)
+		buf[10] = 0xff;
+	else
+		buf[10] = *value ? 0x70 : 0x60;
+
+	err = fcp_avc_transaction(fwspk->unit, buf, 11, buf, 11, 0x3fe);
+	if (err < 0)
+		goto error;
+	if (err < 11) {
+		dev_err(&fwspk->unit->device, "short FCP response\n");
+		err = -EIO;
+		goto error;
+	}
+	if (buf[0] != response_ok) {
+		dev_err(&fwspk->unit->device, "mute command failed\n");
+		err = -EIO;
+		goto error;
+	}
+	if (action == CTL_READ)
+		*value = buf[10] == 0x70;
+
+	err = 0;
+
+error:
+	kfree(buf);
+
+	return err;
+}
+
+static int fwspk_volume_command(struct fwspk *fwspk, s16 *value,
+				unsigned int channel,
+				enum control_attribute attribute,
+				enum control_action action)
+{
+	u8 *buf;
+	u8 response_ok;
+	int err;
+
+	buf = kmalloc(12, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (action == CTL_READ) {
+		buf[0] = 0x01;		/* AV/C, STATUS */
+		response_ok = 0x0c;	/*       STABLE */
+	} else {
+		buf[0] = 0x00;		/* AV/C, CONTROL */
+		response_ok = 0x09;	/*       ACCEPTED */
+	}
+	buf[1] = 0x08;			/* audio unit 0 */
+	buf[2] = 0xb8;			/* FUNCTION BLOCK */
+	buf[3] = 0x81;			/* function block type: feature */
+	buf[4] = fwspk->device_info->volume_fb_id; /* function block ID */
+	buf[5] = attribute;		/* control attribute */
+	buf[6] = 0x02;			/* selector length */
+	buf[7] = channel;		/* audio channel number */
+	buf[8] = 0x02;			/* control selector: volume */
+	buf[9] = 0x02;			/* control data length */
+	if (action == CTL_READ) {
+		buf[10] = 0xff;
+		buf[11] = 0xff;
+	} else {
+		buf[10] = *value >> 8;
+		buf[11] = *value;
+	}
+
+	err = fcp_avc_transaction(fwspk->unit, buf, 12, buf, 12, 0x3fe);
+	if (err < 0)
+		goto error;
+	if (err < 12) {
+		dev_err(&fwspk->unit->device, "short FCP response\n");
+		err = -EIO;
+		goto error;
+	}
+	if (buf[0] != response_ok) {
+		dev_err(&fwspk->unit->device, "volume command failed\n");
+		err = -EIO;
+		goto error;
+	}
+	if (action == CTL_READ)
+		*value = (buf[10] << 8) | buf[11];
+
+	err = 0;
+
+error:
+	kfree(buf);
+
+	return err;
+}
+
+static int fwspk_mute_get(struct snd_kcontrol *control,
+			  struct snd_ctl_elem_value *value)
+{
+	struct fwspk *fwspk = control->private_data;
+
+	value->value.integer.value[0] = !fwspk->mute;
+
+	return 0;
+}
+
+static int fwspk_mute_put(struct snd_kcontrol *control,
+			  struct snd_ctl_elem_value *value)
+{
+	struct fwspk *fwspk = control->private_data;
+	bool mute;
+	int err;
+
+	mute = !value->value.integer.value[0];
+
+	if (mute == fwspk->mute)
+		return 0;
+
+	err = fwspk_mute_command(fwspk, &mute, CTL_WRITE);
+	if (err < 0)
+		return err;
+	fwspk->mute = mute;
+
+	return 1;
+}
+
+static int fwspk_volume_info(struct snd_kcontrol *control,
+			     struct snd_ctl_elem_info *info)
+{
+	struct fwspk *fwspk = control->private_data;
+
+	info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	info->count = fwspk->device_info->mixer_channels;
+	info->value.integer.min = fwspk->volume_min;
+	info->value.integer.max = fwspk->volume_max;
+
+	return 0;
+}
+
+static const u8 channel_map[6] = { 0, 1, 4, 5, 2, 3 };
+
+static int fwspk_volume_get(struct snd_kcontrol *control,
+			    struct snd_ctl_elem_value *value)
+{
+	struct fwspk *fwspk = control->private_data;
+	unsigned int i;
+
+	for (i = 0; i < fwspk->device_info->mixer_channels; ++i)
+		value->value.integer.value[channel_map[i]] = fwspk->volume[i];
+
+	return 0;
+}
+
+static int fwspk_volume_put(struct snd_kcontrol *control,
+			  struct snd_ctl_elem_value *value)
+{
+	struct fwspk *fwspk = control->private_data;
+	unsigned int i, changed_channels;
+	bool equal_values = true;
+	s16 volume;
+	int err;
+
+	for (i = 0; i < fwspk->device_info->mixer_channels; ++i) {
+		if (value->value.integer.value[i] < fwspk->volume_min ||
+		    value->value.integer.value[i] > fwspk->volume_max)
+			return -EINVAL;
+		if (value->value.integer.value[i] !=
+		    value->value.integer.value[0])
+			equal_values = false;
+	}
+
+	changed_channels = 0;
+	for (i = 0; i < fwspk->device_info->mixer_channels; ++i)
+		if (value->value.integer.value[channel_map[i]] !=
+							fwspk->volume[i])
+			changed_channels |= 1 << (i + 1);
+
+	if (equal_values && changed_channels != 0)
+		changed_channels = 1 << 0;
+
+	for (i = 0; i <= fwspk->device_info->mixer_channels; ++i) {
+		volume = value->value.integer.value[channel_map[i ? i - 1 : 0]];
+		if (changed_channels & (1 << i)) {
+			err = fwspk_volume_command(fwspk, &volume, i,
+						   CTL_CURRENT, CTL_WRITE);
+			if (err < 0)
+				return err;
+		}
+		if (i > 0)
+			fwspk->volume[i - 1] = volume;
+	}
+
+	return changed_channels != 0;
+}
+
+static int fwspk_create_mixer(struct fwspk *fwspk)
+{
+	static const struct snd_kcontrol_new controls[] = {
+		{
+			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+			.name = "PCM Playback Switch",
+			.info = snd_ctl_boolean_mono_info,
+			.get = fwspk_mute_get,
+			.put = fwspk_mute_put,
+		},
+		{
+			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+			.name = "PCM Playback Volume",
+			.info = fwspk_volume_info,
+			.get = fwspk_volume_get,
+			.put = fwspk_volume_put,
+		},
+	};
+	unsigned int i, first_ch;
+	int err;
+
+	err = fwspk_volume_command(fwspk, &fwspk->volume_min,
+				   0, CTL_MIN, CTL_READ);
+	if (err < 0)
+		return err;
+	err = fwspk_volume_command(fwspk, &fwspk->volume_max,
+				   0, CTL_MAX, CTL_READ);
+	if (err < 0)
+		return err;
+
+	err = fwspk_mute_command(fwspk, &fwspk->mute, CTL_READ);
+	if (err < 0)
+		return err;
+
+	first_ch = fwspk->device_info->mixer_channels == 1 ? 0 : 1;
+	for (i = 0; i < fwspk->device_info->mixer_channels; ++i) {
+		err = fwspk_volume_command(fwspk, &fwspk->volume[i],
+					   first_ch + i, CTL_CURRENT, CTL_READ);
+		if (err < 0)
+			return err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(controls); ++i) {
+		err = snd_ctl_add(fwspk->card,
+				  snd_ctl_new1(&controls[i], fwspk));
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+static u32 fwspk_read_firmware_version(struct fw_unit *unit)
+{
+	__be32 data;
+	int err;
+
+	err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST,
+				 OXFORD_FIRMWARE_ID_ADDRESS, &data, 4);
+	return err >= 0 ? be32_to_cpu(data) : 0;
+}
+
+static void fwspk_card_free(struct snd_card *card)
+{
+	struct fwspk *fwspk = card->private_data;
+	struct fw_device *dev = fw_parent_device(fwspk->unit);
+
+	amdtp_out_stream_destroy(&fwspk->stream);
+	cmp_connection_destroy(&fwspk->connection);
+	fw_unit_put(fwspk->unit);
+	fw_device_put(dev);
+	mutex_destroy(&fwspk->mutex);
+}
+
+static const struct device_info *__devinit fwspk_detect(struct fw_device *dev)
+{
+	static const struct device_info griffin_firewave = {
+		.driver_name = "FireWave",
+		.short_name  = "FireWave",
+		.long_name   = "Griffin FireWave Surround",
+		.pcm_constraints = firewave_constraints,
+		.mixer_channels = 6,
+		.mute_fb_id   = 0x01,
+		.volume_fb_id = 0x02,
+	};
+	static const struct device_info lacie_speakers = {
+		.driver_name = "FWSpeakers",
+		.short_name  = "FireWire Speakers",
+		.long_name   = "LaCie FireWire Speakers",
+		.pcm_constraints = lacie_speakers_constraints,
+		.mixer_channels = 1,
+		.mute_fb_id   = 0x01,
+		.volume_fb_id = 0x01,
+	};
+	struct fw_csr_iterator i;
+	int key, value;
+
+	fw_csr_iterator_init(&i, dev->config_rom);
+	while (fw_csr_iterator_next(&i, &key, &value))
+		if (key == CSR_VENDOR)
+			switch (value) {
+			case VENDOR_GRIFFIN:
+				return &griffin_firewave;
+			case VENDOR_LACIE:
+				return &lacie_speakers;
+			}
+
+	return NULL;
+}
+
+static int __devinit fwspk_probe(struct device *unit_dev)
+{
+	struct fw_unit *unit = fw_unit(unit_dev);
+	struct fw_device *fw_dev = fw_parent_device(unit);
+	struct snd_card *card;
+	struct fwspk *fwspk;
+	u32 firmware;
+	int err;
+
+	err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(*fwspk), &card);
+	if (err < 0)
+		return err;
+	snd_card_set_dev(card, unit_dev);
+
+	fwspk = card->private_data;
+	fwspk->card = card;
+	mutex_init(&fwspk->mutex);
+	fw_device_get(fw_dev);
+	fwspk->unit = fw_unit_get(unit);
+	fwspk->device_info = fwspk_detect(fw_dev);
+	if (!fwspk->device_info) {
+		err = -ENODEV;
+		goto err_unit;
+	}
+
+	err = cmp_connection_init(&fwspk->connection, unit, 0);
+	if (err < 0)
+		goto err_unit;
+
+	err = amdtp_out_stream_init(&fwspk->stream, unit, CIP_NONBLOCKING);
+	if (err < 0)
+		goto err_connection;
+
+	card->private_free = fwspk_card_free;
+
+	strcpy(card->driver, fwspk->device_info->driver_name);
+	strcpy(card->shortname, fwspk->device_info->short_name);
+	firmware = fwspk_read_firmware_version(unit);
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s (OXFW%x %04x), GUID %08x%08x at %s, S%d",
+		 fwspk->device_info->long_name,
+		 firmware >> 20, firmware & 0xffff,
+		 fw_dev->config_rom[3], fw_dev->config_rom[4],
+		 dev_name(&unit->device), 100 << fw_dev->max_speed);
+	strcpy(card->mixername, "OXFW970");
+
+	err = fwspk_create_pcm(fwspk);
+	if (err < 0)
+		goto error;
+
+	err = fwspk_create_mixer(fwspk);
+	if (err < 0)
+		goto error;
+
+	err = snd_card_register(card);
+	if (err < 0)
+		goto error;
+
+	dev_set_drvdata(unit_dev, fwspk);
+
+	return 0;
+
+err_connection:
+	cmp_connection_destroy(&fwspk->connection);
+err_unit:
+	fw_unit_put(fwspk->unit);
+	fw_device_put(fw_dev);
+	mutex_destroy(&fwspk->mutex);
+error:
+	snd_card_free(card);
+	return err;
+}
+
+static int __devexit fwspk_remove(struct device *dev)
+{
+	struct fwspk *fwspk = dev_get_drvdata(dev);
+
+	snd_card_disconnect(fwspk->card);
+
+	mutex_lock(&fwspk->mutex);
+	amdtp_out_stream_pcm_abort(&fwspk->stream);
+	fwspk_stop_stream(fwspk);
+	mutex_unlock(&fwspk->mutex);
+
+	snd_card_free_when_closed(fwspk->card);
+
+	return 0;
+}
+
+static void fwspk_bus_reset(struct fw_unit *unit)
+{
+	struct fwspk *fwspk = dev_get_drvdata(&unit->device);
+
+	fcp_bus_reset(fwspk->unit);
+
+	if (cmp_connection_update(&fwspk->connection) < 0) {
+		mutex_lock(&fwspk->mutex);
+		amdtp_out_stream_pcm_abort(&fwspk->stream);
+		fwspk_stop_stream(fwspk);
+		mutex_unlock(&fwspk->mutex);
+		return;
+	}
+
+	amdtp_out_stream_update(&fwspk->stream);
+}
+
+static const struct ieee1394_device_id fwspk_id_table[] = {
+	{
+		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
+				IEEE1394_MATCH_MODEL_ID |
+				IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_MATCH_VERSION,
+		.vendor_id    = VENDOR_GRIFFIN,
+		.model_id     = 0x00f970,
+		.specifier_id = SPECIFIER_1394TA,
+		.version      = VERSION_AVC,
+	},
+	{
+		.match_flags  = IEEE1394_MATCH_VENDOR_ID |
+				IEEE1394_MATCH_MODEL_ID |
+				IEEE1394_MATCH_SPECIFIER_ID |
+				IEEE1394_MATCH_VERSION,
+		.vendor_id    = VENDOR_LACIE,
+		.model_id     = 0x00f970,
+		.specifier_id = SPECIFIER_1394TA,
+		.version      = VERSION_AVC,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(ieee1394, fwspk_id_table);
+
+static struct fw_driver fwspk_driver = {
+	.driver   = {
+		.owner	= THIS_MODULE,
+		.name	= KBUILD_MODNAME,
+		.bus	= &fw_bus_type,
+		.probe	= fwspk_probe,
+		.remove	= __devexit_p(fwspk_remove),
+	},
+	.update   = fwspk_bus_reset,
+	.id_table = fwspk_id_table,
+};
+
+static int __init alsa_fwspk_init(void)
+{
+	return driver_register(&fwspk_driver.driver);
+}
+
+static void __exit alsa_fwspk_exit(void)
+{
+	driver_unregister(&fwspk_driver.driver);
+}
+
+module_init(alsa_fwspk_init);
+module_exit(alsa_fwspk_exit);
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index fcb14a09..7c7793a 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -526,31 +526,21 @@ bad:
 }
 
 
-/* These device names follow the official Linux device list,
- * Documentation/devices.txt.  Let us know if there are other
- * common names we should support for compatibility.
- * Only those devices not created by the generic code in sound_core.c are
- * registered here.
- */
-static const struct {
-	unsigned short minor;
-	char *name;
-	umode_t mode;
-	int *num;
-} dev_list[] = { /* list of minor devices */
-/* seems to be some confusion here -- this device is not in the device list */
-	{SND_DEV_DSP16,     "dspW",	 S_IWUGO | S_IRUSR | S_IRGRP,
-	 &num_audiodevs},
-	{SND_DEV_AUDIO,     "audio",	 S_IWUGO | S_IRUSR | S_IRGRP,
-	 &num_audiodevs},
-};
-
 static int dmabuf;
 static int dmabug;
 
 module_param(dmabuf, int, 0444);
 module_param(dmabug, int, 0444);
 
+/* additional minors for compatibility */
+struct oss_minor_dev {
+	unsigned short minor;
+	unsigned int enabled;
+} dev_list[] = {
+	{ SND_DEV_DSP16 },
+	{ SND_DEV_AUDIO },
+};
+
 static int __init oss_init(void)
 {
 	int             err;
@@ -571,18 +561,12 @@ static int __init oss_init(void)
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-		device_create(sound_class, NULL,
-			      MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
-			      "%s", dev_list[i].name);
-
-		if (!dev_list[i].num)
-			continue;
-
-		for (j = 1; j < *dev_list[i].num; j++)
-			device_create(sound_class, NULL,
-				      MKDEV(SOUND_MAJOR,
-					    dev_list[i].minor + (j*0x10)),
-				      NULL, "%s%d", dev_list[i].name, j);
+		j = 0;
+		do {
+			unsigned short minor = dev_list[i].minor + j * 0x10;
+			if (!register_sound_special(&oss_sound_fops, minor))
+				dev_list[i].enabled = (1 << j);
+		} while (++j < num_audiodevs);
 	}
 
 	if (sound_nblocks >= MAX_MEM_BLOCKS - 1)
@@ -596,11 +580,11 @@ static void __exit oss_cleanup(void)
 	int i, j;
 
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-		device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
-		if (!dev_list[i].num)
-			continue;
-		for (j = 1; j < *dev_list[i].num; j++)
-			device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
+		j = 0;
+		do {
+			if (dev_list[i].enabled & (1 << j))
+				unregister_sound_special(dev_list[i].minor);
+		} while (++j < num_audiodevs);
 	}
 	
 	unregister_sound_special(1);
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 9823d59..389cd79 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -152,10 +152,16 @@ config SND_AZT3328
 	select SND_MPU401_UART
 	select SND_PCM
 	select SND_RAWMIDI
+	select SND_AC97_CODEC
 	help
 	  Say Y here to include support for Aztech AZF3328 (PCI168)
 	  soundcards.
 
+	  Supported features: AC97-"conformant" mixer, MPU401/OPL3, analog I/O
+	  (16bit/8bit, many sample rates [<= 66.2kHz], NO hardware mixing),
+	  Digital Enhanced Game Port, 1.024MHz multimedia sequencer timer,
+	  ext. codec (I2S port), onboard amp (4W/4Ohms/ch), suspend/resume.
+
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-azt3328.
 
@@ -572,13 +578,13 @@ comment "Don't forget to add built-in firmwares for HDSP driver"
 	depends on SND_HDSP=y
 
 config SND_HDSPM
-	tristate "RME Hammerfall DSP MADI"
+	tristate "RME Hammerfall DSP MADI/RayDAT/AIO"
 	select SND_HWDEP
 	select SND_RAWMIDI
 	select SND_PCM
 	help
-	  Say Y here to include support for RME Hammerfall DSP MADI
-	  soundcards.
+	  Say Y here to include support for RME Hammerfall DSP MADI,
+	  RayDAT and AIO soundcards.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-hdspm.
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index cb62d17..7f4d619 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -71,6 +71,12 @@ static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = {
 { 0x414b4d00, 0xffffff00, "Asahi Kasei",	NULL,	NULL },
 { 0x414c4300, 0xffffff00, "Realtek",		NULL,	NULL },
 { 0x414c4700, 0xffffff00, "Realtek",		NULL,	NULL },
+/*
+ * This is an _inofficial_ Aztech Labs entry
+ * (value might differ from unknown official Aztech ID),
+ * currently used by the AC97 emulation of the almost-AC97 PCI168 card.
+ */
+{ 0x415a5400, 0xffffff00, "Aztech Labs (emulated)",	NULL,	NULL },
 { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL,	NULL },
 { 0x43525900, 0xffffff00, "Cirrus Logic",	NULL,	NULL },
 { 0x43585400, 0xffffff00, "Conexant",           NULL,	NULL },
@@ -127,6 +133,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
 { 0x414c4781, 0xffffffff, "ALC658D",		NULL,	NULL }, /* already patched */
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
 { 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
+{ 0x415a5401, 0xffffffff, "AZF3328",		patch_aztech_azf3328,	NULL },
 { 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738,	NULL },
 { 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739,	NULL },
 { 0x434d4969, 0xffffffff, "CMI9780",		patch_cm9780,	NULL },
@@ -590,9 +597,9 @@ static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol,
 	snd_ac97_page_restore(ac97, page_save);
 #ifdef CONFIG_SND_AC97_POWER_SAVE
 	/* check analog mixer power-down */
-	if ((val_mask & 0x8000) &&
+	if ((val_mask & AC97_PD_EAPD) &&
 	    (kcontrol->private_value & (1<<30))) {
-		if (val & 0x8000)
+		if (val & AC97_PD_EAPD)
 			ac97->power_up &= ~(1 << (reg>>1));
 		else
 			ac97->power_up |= 1 << (reg>>1);
@@ -1035,20 +1042,20 @@ static int snd_ac97_dev_free(struct snd_device *device)
 
 static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg)
 {
-	unsigned short val, mask = 0x8000;
+	unsigned short val, mask = AC97_MUTE_MASK_MONO;
 
 	if (! snd_ac97_valid_reg(ac97, reg))
 		return 0;
 
 	switch (reg) {
 	case AC97_MASTER_TONE:
-		return ac97->caps & 0x04 ? 1 : 0;
+		return ac97->caps & AC97_BC_BASS_TREBLE ? 1 : 0;
 	case AC97_HEADPHONE:
-		return ac97->caps & 0x10 ? 1 : 0;
+		return ac97->caps & AC97_BC_HEADPHONE ? 1 : 0;
 	case AC97_REC_GAIN_MIC:
-		return ac97->caps & 0x01 ? 1 : 0;
+		return ac97->caps & AC97_BC_DEDICATED_MIC ? 1 : 0;
 	case AC97_3D_CONTROL:
-		if (ac97->caps & 0x7c00) {
+		if (ac97->caps & AC97_BC_3D_TECH_ID_MASK) {
 			val = snd_ac97_read(ac97, reg);
 			/* if nonzero - fixed and we can't set it */
 			return val == 0;
@@ -1104,7 +1111,10 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha
 	*lo_max = *hi_max = 0;
 	for (i = 0 ; i < ARRAY_SIZE(cbit); i++) {
 		unsigned short val;
-		snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
+		snd_ac97_write(
+			ac97, reg,
+			AC97_MUTE_MASK_STEREO | cbit[i] | (cbit[i] << 8)
+		);
 		/* Do the read twice due to buffers on some ac97 codecs.
 		 * e.g. The STAC9704 returns exactly what you wrote to the register
 		 * if you read it immediately. This causes the detect routine to fail.
@@ -1139,14 +1149,14 @@ static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int
 	unsigned short val, val1;
 
 	*max = 63;
-	val = 0x8080 | (0x20 << shift);
+	val = AC97_MUTE_MASK_STEREO | (0x20 << shift);
 	snd_ac97_write(ac97, reg, val);
 	val1 = snd_ac97_read(ac97, reg);
 	if (val != val1) {
 		*max = 31;
 	}
 	/* reset volume to zero */
-	snd_ac97_write_cache(ac97, reg, 0x8080);
+	snd_ac97_write_cache(ac97, reg, AC97_MUTE_MASK_STEREO);
 }
 
 static inline int printable(unsigned int x)
@@ -1183,16 +1193,16 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg,
 	if (! snd_ac97_valid_reg(ac97, reg))
 		return 0;
 
-	mute_mask = 0x8000;
+	mute_mask = AC97_MUTE_MASK_MONO;
 	val = snd_ac97_read(ac97, reg);
 	if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {
 		/* check whether both mute bits work */
-		val1 = val | 0x8080;
+		val1 = val | AC97_MUTE_MASK_STEREO;
 		snd_ac97_write(ac97, reg, val1);
 		if (val1 == snd_ac97_read(ac97, reg))
-			mute_mask = 0x8080;
+			mute_mask = AC97_MUTE_MASK_STEREO;
 	}
-	if (mute_mask == 0x8080) {
+	if (mute_mask == AC97_MUTE_MASK_STEREO) {
 		struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
 		if (check_amix)
 			tmp.private_value |= (1 << 30);
@@ -1268,9 +1278,11 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne
 	err = snd_ctl_add(card, kctl);
 	if (err < 0)
 		return err;
-	snd_ac97_write_cache(ac97, reg,
-			     (snd_ac97_read(ac97, reg) & 0x8080) |
-			     lo_max | (hi_max << 8));
+	snd_ac97_write_cache(
+		ac97, reg,
+		(snd_ac97_read(ac97, reg) & AC97_MUTE_MASK_STEREO)
+		| lo_max | (hi_max << 8)
+	);
 	return 0;
 }
 
@@ -1332,7 +1344,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 			return err;
 	}
 
-	ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;
+	ac97->regs[AC97_CENTER_LFE_MASTER] = AC97_MUTE_MASK_STEREO;
 
 	/* build center controls */
 	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) 
@@ -1410,8 +1422,12 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 				return err;
 		set_tlv_db_scale(kctl, db_scale_4bit);
-		snd_ac97_write_cache(ac97, AC97_PC_BEEP,
-				     snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);
+		snd_ac97_write_cache(
+			ac97,
+			AC97_PC_BEEP,
+			(snd_ac97_read(ac97, AC97_PC_BEEP)
+				| AC97_MUTE_MASK_MONO | 0x001e)
+		);
 	}
 	
 	/* build Phone controls */
@@ -1545,7 +1561,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 	}
 
 	/* build Simulated Stereo Enhancement control */
-	if (ac97->caps & 0x0008) {
+	if (ac97->caps & AC97_BC_SIM_STEREO) {
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0)
 			return err;
 	}
@@ -1557,7 +1573,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 	}
 
 	/* build Loudness control */
-	if (ac97->caps & 0x0020) {
+	if (ac97->caps & AC97_BC_LOUDNESS) {
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0)
 			return err;
 	}
@@ -2542,8 +2558,8 @@ void snd_ac97_resume(struct snd_ac97 *ac97)
 			schedule_timeout_uninterruptible(1);
 		} while (time_after_eq(end_time, jiffies));
 		/* FIXME: extra delay */
-		ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000);
-		if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000)
+		ac97->bus->ops->write(ac97, AC97_MASTER, AC97_MUTE_MASK_MONO);
+		if (snd_ac97_read(ac97, AC97_MASTER) != AC97_MUTE_MASK_MONO)
 			msleep(250);
 	} else {
 		end_time = jiffies + msecs_to_jiffies(100);
@@ -2747,12 +2763,12 @@ static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 		int rshift = (kcontrol->private_value >> 12) & 0x0f;
 		unsigned short mask;
 		if (shift != rshift)
-			mask = 0x8080;
+			mask = AC97_MUTE_MASK_STEREO;
 		else
-			mask = 0x8000;
-		snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000,
+			mask = AC97_MUTE_MASK_MONO;
+		snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD,
 				     (ac97->regs[AC97_MASTER] & mask) == mask ?
-				     0x8000 : 0);
+				     AC97_PD_EAPD : 0);
 	}
 	return err;
 }
@@ -2765,7 +2781,10 @@ static int tune_mute_led(struct snd_ac97 *ac97)
 		return -ENOENT;
 	msw->put = master_mute_sw_put;
 	snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
-	snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */
+	snd_ac97_update_bits(
+		ac97, AC97_POWERDOWN,
+		AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */
+	);
 	ac97->scaps |= AC97_SCAP_EAPD_LED;
 	return 0;
 }
@@ -2780,12 +2799,12 @@ static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol,
 		int rshift = (kcontrol->private_value >> 12) & 0x0f;
 		unsigned short mask;
 		if (shift != rshift)
-			mask = 0x8080;
+			mask = AC97_MUTE_MASK_STEREO;
 		else
-			mask = 0x8000;
-		snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000,
+			mask = AC97_MUTE_MASK_MONO;
+		snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD,
 				     (ac97->regs[AC97_MASTER] & mask) == mask ?
-				     0x8000 : 0);
+				     AC97_PD_EAPD : 0);
 	}
 	return err;
 }
@@ -2801,7 +2820,10 @@ static int tune_hp_mute_led(struct snd_ac97 *ac97)
 	snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
 	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
 	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
-	snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */
+	snd_ac97_update_bits(
+		ac97, AC97_POWERDOWN,
+		AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */
+	);
 	return 0;
 }
 
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index bf47574..200c9a1 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -27,6 +27,15 @@
 #include "ac97_patch.h"
 
 /*
+ *  Forward declarations
+ */
+
+static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
+						    const char *name);
+static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
+				const unsigned int *tlv, const char **slaves);
+
+/*
  *  Chip specific initialization
  */
 
@@ -2940,6 +2949,49 @@ static int patch_alc850(struct snd_ac97 *ac97)
 	return 0;
 }
 
+static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
+{
+	struct snd_kcontrol *kctl_3d_center =
+		snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
+	struct snd_kcontrol *kctl_3d_depth =
+		snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
+
+	/*
+	 * 3D register is different from AC97 standard layout
+	 * (also do some renaming, to resemble Windows driver naming)
+	 */
+	if (kctl_3d_center) {
+		kctl_3d_center->private_value =
+			AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
+		snd_ac97_rename_vol_ctl(ac97,
+			"3D Control - Center", "3D Control - Width"
+		);
+	}
+	if (kctl_3d_depth)
+		kctl_3d_depth->private_value =
+			AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
+
+	/* Aztech Windows driver calls the
+	   equivalent control "Modem Playback", thus rename it: */
+	snd_ac97_rename_vol_ctl(ac97,
+		"Master Mono Playback", "Modem Playback"
+	);
+	snd_ac97_rename_vol_ctl(ac97,
+		"Headphone Playback", "FM Synth Playback"
+	);
+
+	return 0;
+}
+
+static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
+	.build_specific	= patch_aztech_azf3328_specific
+};
+
+static int patch_aztech_azf3328(struct snd_ac97 *ac97)
+{
+	ac97->build_ops = &patch_aztech_azf3328_ops;
+	return 0;
+}
 
 /*
  * C-Media CM97xx codecs
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index c80b0b8..0ac1f98 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -21,6 +21,7 @@
  *  would appreciate it if you grant us the right to use those modifications
  *  for any purpose including commercial applications.
  */
+
 /* >0: print Hw params, timer vars. >1: print stream write/copy sizes  */
 #define REALLY_VERBOSE_LOGGING 0
 
@@ -36,16 +37,12 @@
 #define VPRINTK2(...)
 #endif
 
-#ifndef ASI_STYLE_NAMES
-/* not sure how ALSA style name should look */
-#define ASI_STYLE_NAMES 1
-#endif
-
 #include "hpi_internal.h"
 #include "hpimsginit.h"
 #include "hpioctl.h"
 
 #include <linux/pci.h>
+#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
@@ -85,11 +82,11 @@ MODULE_PARM_DESC(enable_hpi_hwdep,
 
 /* identify driver */
 #ifdef KERNEL_ALSA_BUILD
-static char *build_info = "built using headers from kernel source";
+static char *build_info = "Built using headers from kernel source";
 module_param(build_info, charp, S_IRUGO);
 MODULE_PARM_DESC(build_info, "built using headers from kernel source");
 #else
-static char *build_info = "built within ALSA source";
+static char *build_info = "Built within ALSA source";
 module_param(build_info, charp, S_IRUGO);
 MODULE_PARM_DESC(build_info, "built within ALSA source");
 #endif
@@ -100,13 +97,14 @@ static const int mixer_dump;
 #define DEFAULT_SAMPLERATE 44100
 static int adapter_fs = DEFAULT_SAMPLERATE;
 
-static struct hpi_hsubsys *ss;	/* handle to HPI audio subsystem */
-
 /* defaults */
 #define PERIODS_MIN 2
-#define PERIOD_BYTES_MIN  2304
+#define PERIOD_BYTES_MIN  2048
 #define BUFFER_BYTES_MAX (512 * 1024)
 
+/* convert stream to character */
+#define SCHR(s) ((s == SNDRV_PCM_STREAM_PLAYBACK) ? 'P' : 'C')
+
 /*#define TIMER_MILLISECONDS 20
 #define FORCE_TIMER_JIFFIES ((TIMER_MILLISECONDS * HZ + 999)/1000)
 */
@@ -152,11 +150,12 @@ struct snd_card_asihpi_pcm {
 	struct timer_list timer;
 	unsigned int respawn_timer;
 	unsigned int hpi_buffer_attached;
-	unsigned int pcm_size;
-	unsigned int pcm_count;
+	unsigned int buffer_bytes;
+	unsigned int period_bytes;
 	unsigned int bytes_per_sec;
-	unsigned int pcm_irq_pos;	/* IRQ position */
-	unsigned int pcm_buf_pos;	/* position in buffer */
+	unsigned int pcm_buf_host_rw_ofs; /* Host R/W pos */
+	unsigned int pcm_buf_dma_ofs;	/* DMA R/W offset in buffer */
+	unsigned int pcm_buf_elapsed_dma_ofs;	/* DMA R/W offset in buffer */
 	struct snd_pcm_substream *substream;
 	u32 h_stream;
 	struct hpi_format format;
@@ -167,7 +166,6 @@ struct snd_card_asihpi_pcm {
 /* Functions to allow driver to give a buffer to HPI for busmastering */
 
 static u16 hpi_stream_host_buffer_attach(
-	struct hpi_hsubsys *hS,
 	u32 h_stream,   /* handle to outstream. */
 	u32 size_in_bytes, /* size in bytes of bus mastering buffer */
 	u32 pci_address
@@ -194,10 +192,7 @@ static u16 hpi_stream_host_buffer_attach(
 	return hr.error;
 }
 
-static u16 hpi_stream_host_buffer_detach(
-	struct hpi_hsubsys *hS,
-	u32  h_stream
-)
+static u16 hpi_stream_host_buffer_detach(u32  h_stream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -218,24 +213,23 @@ static u16 hpi_stream_host_buffer_detach(
 	return hr.error;
 }
 
-static inline u16 hpi_stream_start(struct hpi_hsubsys *hS, u32 h_stream)
+static inline u16 hpi_stream_start(u32 h_stream)
 {
 	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)
-		return hpi_outstream_start(hS, h_stream);
+		return hpi_outstream_start(h_stream);
 	else
-		return hpi_instream_start(hS, h_stream);
+		return hpi_instream_start(h_stream);
 }
 
-static inline u16 hpi_stream_stop(struct hpi_hsubsys *hS, u32 h_stream)
+static inline u16 hpi_stream_stop(u32 h_stream)
 {
 	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)
-		return hpi_outstream_stop(hS, h_stream);
+		return hpi_outstream_stop(h_stream);
 	else
-		return hpi_instream_stop(hS, h_stream);
+		return hpi_instream_stop(h_stream);
 }
 
 static inline u16 hpi_stream_get_info_ex(
-    struct hpi_hsubsys *hS,
     u32 h_stream,
     u16        *pw_state,
     u32        *pbuffer_size,
@@ -244,42 +238,43 @@ static inline u16 hpi_stream_get_info_ex(
     u32        *pauxiliary_data
 )
 {
+	u16 e;
 	if (hpi_handle_object(h_stream)  ==  HPI_OBJ_OSTREAM)
-		return hpi_outstream_get_info_ex(hS, h_stream, pw_state,
+		e = hpi_outstream_get_info_ex(h_stream, pw_state,
 					pbuffer_size, pdata_in_buffer,
 					psample_count, pauxiliary_data);
 	else
-		return hpi_instream_get_info_ex(hS, h_stream, pw_state,
+		e = hpi_instream_get_info_ex(h_stream, pw_state,
 					pbuffer_size, pdata_in_buffer,
 					psample_count, pauxiliary_data);
+	return e;
 }
 
-static inline u16 hpi_stream_group_add(struct hpi_hsubsys *hS,
+static inline u16 hpi_stream_group_add(
 					u32 h_master,
 					u32 h_stream)
 {
 	if (hpi_handle_object(h_master) ==  HPI_OBJ_OSTREAM)
-		return hpi_outstream_group_add(hS, h_master, h_stream);
+		return hpi_outstream_group_add(h_master, h_stream);
 	else
-		return hpi_instream_group_add(hS, h_master, h_stream);
+		return hpi_instream_group_add(h_master, h_stream);
 }
 
-static inline u16 hpi_stream_group_reset(struct hpi_hsubsys *hS,
-						u32 h_stream)
+static inline u16 hpi_stream_group_reset(u32 h_stream)
 {
 	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)
-		return hpi_outstream_group_reset(hS, h_stream);
+		return hpi_outstream_group_reset(h_stream);
 	else
-		return hpi_instream_group_reset(hS, h_stream);
+		return hpi_instream_group_reset(h_stream);
 }
 
-static inline u16 hpi_stream_group_get_map(struct hpi_hsubsys *hS,
+static inline u16 hpi_stream_group_get_map(
 				u32 h_stream, u32 *mo, u32 *mi)
 {
 	if (hpi_handle_object(h_stream) ==  HPI_OBJ_OSTREAM)
-		return hpi_outstream_group_get_map(hS, h_stream, mo, mi);
+		return hpi_outstream_group_get_map(h_stream, mo, mi);
 	else
-		return hpi_instream_group_get_map(hS, h_stream, mo, mi);
+		return hpi_instream_group_get_map(h_stream, mo, mi);
 }
 
 static u16 handle_error(u16 err, int line, char *filename)
@@ -299,11 +294,11 @@ static void print_hwparams(struct snd_pcm_hw_params *p)
 {
 	snd_printd("HWPARAMS \n");
 	snd_printd("samplerate %d \n", params_rate(p));
-	snd_printd("channels %d \n", params_channels(p));
-	snd_printd("format %d \n", params_format(p));
+	snd_printd("Channels %d \n", params_channels(p));
+	snd_printd("Format %d \n", params_format(p));
 	snd_printd("subformat %d \n", params_subformat(p));
-	snd_printd("buffer bytes %d \n", params_buffer_bytes(p));
-	snd_printd("period bytes %d \n", params_period_bytes(p));
+	snd_printd("Buffer bytes %d \n", params_buffer_bytes(p));
+	snd_printd("Period bytes %d \n", params_period_bytes(p));
 	snd_printd("access %d \n", params_access(p));
 	snd_printd("period_size %d \n", params_period_size(p));
 	snd_printd("periods %d \n", params_periods(p));
@@ -335,7 +330,7 @@ static snd_pcm_format_t hpi_to_alsa_formats[] = {
 	 */
 	-1
 #else
-	/* SNDRV_PCM_FORMAT_S24_3LE */	/* { HPI_FORMAT_PCM24_SIGNED        15 */
+	/* SNDRV_PCM_FORMAT_S24_3LE */ /* HPI_FORMAT_PCM24_SIGNED 15 */
 #endif
 };
 
@@ -378,20 +373,20 @@ static void snd_card_asihpi_pcm_samplerates(struct snd_card_asihpi *asihpi,
 	} else {
 		/* on cards without SRC,
 		   valid rates are determined by sampleclock */
-		err = hpi_mixer_get_control(ss, asihpi->h_mixer,
+		err = hpi_mixer_get_control(asihpi->h_mixer,
 					  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
 					  HPI_CONTROL_SAMPLECLOCK, &h_control);
 		if (err) {
 			snd_printk(KERN_ERR
-				"no local sampleclock, err %d\n", err);
+				"No local sampleclock, err %d\n", err);
 		}
 
 		for (idx = 0; idx < 100; idx++) {
-			if (hpi_sample_clock_query_local_rate(ss,
+			if (hpi_sample_clock_query_local_rate(
 				h_control, idx, &sample_rate)) {
 				if (!idx)
 					snd_printk(KERN_ERR
-						"local rate query failed\n");
+						"Local rate query failed\n");
 
 				break;
 			}
@@ -480,10 +475,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 			format, params_rate(params), 0, 0));
 
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
-		if (hpi_instream_reset(ss, dpcm->h_stream) != 0)
+		if (hpi_instream_reset(dpcm->h_stream) != 0)
 			return -EINVAL;
 
-		if (hpi_instream_set_format(ss,
+		if (hpi_instream_set_format(
 			dpcm->h_stream, &dpcm->format) != 0)
 			return -EINVAL;
 	}
@@ -491,10 +486,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 	dpcm->hpi_buffer_attached = 0;
 	if (card->support_mmap) {
 
-		err = hpi_stream_host_buffer_attach(ss, dpcm->h_stream,
+		err = hpi_stream_host_buffer_attach(dpcm->h_stream,
 			params_buffer_bytes(params),  runtime->dma_addr);
 		if (err == 0) {
-			snd_printd(KERN_INFO
+			VPRINTK1(KERN_INFO
 				"stream_host_buffer_attach succeeded %u %lu\n",
 				params_buffer_bytes(params),
 				(unsigned long)runtime->dma_addr);
@@ -505,11 +500,11 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 			return -ENOMEM;
 		}
 
-		err = hpi_stream_get_info_ex(ss, dpcm->h_stream, NULL,
+		err = hpi_stream_get_info_ex(dpcm->h_stream, NULL,
 						&dpcm->hpi_buffer_attached,
 						NULL, NULL, NULL);
 
-		snd_printd(KERN_INFO "stream_host_buffer_attach status 0x%x\n",
+		VPRINTK1(KERN_INFO "stream_host_buffer_attach status 0x%x\n",
 				dpcm->hpi_buffer_attached);
 	}
 	bytes_per_sec = params_rate(params) * params_channels(params);
@@ -520,16 +515,32 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 
 	dpcm->bytes_per_sec = bytes_per_sec;
-	dpcm->pcm_size = params_buffer_bytes(params);
-	dpcm->pcm_count = params_period_bytes(params);
-	snd_printd(KERN_INFO "pcm_size=%d, pcm_count=%d, bps=%d\n",
-			dpcm->pcm_size, dpcm->pcm_count, bytes_per_sec);
+	dpcm->buffer_bytes = params_buffer_bytes(params);
+	dpcm->period_bytes = params_period_bytes(params);
+	VPRINTK1(KERN_INFO "buffer_bytes=%d, period_bytes=%d, bps=%d\n",
+			dpcm->buffer_bytes, dpcm->period_bytes, bytes_per_sec);
 
-	dpcm->pcm_irq_pos = 0;
-	dpcm->pcm_buf_pos = 0;
 	return 0;
 }
 
+static int
+snd_card_asihpi_hw_free(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
+	if (dpcm->hpi_buffer_attached)
+		hpi_stream_host_buffer_detach(dpcm->h_stream);
+
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
+static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime)
+{
+	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
+	kfree(dpcm);
+}
+
 static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream *
 					    substream)
 {
@@ -537,9 +548,9 @@ static void snd_card_asihpi_pcm_timer_start(struct snd_pcm_substream *
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 	int expiry;
 
-	expiry = (dpcm->pcm_count * HZ / dpcm->bytes_per_sec);
-	/* wait longer the first time, for samples to propagate */
-	expiry = max(expiry, 20);
+	expiry = HZ / 200;
+	/*? (dpcm->period_bytes * HZ / dpcm->bytes_per_sec); */
+	expiry = max(expiry, 1); /* don't let it be zero! */
 	dpcm->timer.expires = jiffies + expiry;
 	dpcm->respawn_timer = 1;
 	add_timer(&dpcm->timer);
@@ -562,37 +573,44 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
 	struct snd_pcm_substream *s;
 	u16 e;
 
-	snd_printd("trigger %dstream %d\n",
-			substream->stream, substream->number);
+	VPRINTK1(KERN_INFO "%c%d trigger\n",
+			SCHR(substream->stream), substream->number);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 		snd_pcm_group_for_each_entry(s, substream) {
-			struct snd_card_asihpi_pcm *ds;
-			ds = s->runtime->private_data;
+			struct snd_pcm_runtime *runtime = s->runtime;
+			struct snd_card_asihpi_pcm *ds = runtime->private_data;
 
 			if (snd_pcm_substream_chip(s) != card)
 				continue;
 
+			/* don't link Cap and Play */
+			if (substream->stream != s->stream)
+				continue;
+
 			if ((s->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
 				(card->support_mmap)) {
 				/* How do I know how much valid data is present
-				* in buffer? Just guessing 2 periods, but if
+				* in buffer? Must be at least one period!
+				* Guessing 2 periods, but if
 				* buffer is bigger it may contain even more
 				* data??
 				*/
-				unsigned int preload = ds->pcm_count * 2;
-				VPRINTK2("preload %d\n", preload);
+				unsigned int preload = ds->period_bytes * 1;
+				VPRINTK2(KERN_INFO "%d preload x%x\n", s->number, preload);
 				hpi_handle_error(hpi_outstream_write_buf(
-						ss, ds->h_stream,
-						&s->runtime->dma_area[0],
+						ds->h_stream,
+						&runtime->dma_area[0],
 						preload,
 						&ds->format));
+				ds->pcm_buf_host_rw_ofs = preload;
 			}
 
 			if (card->support_grouping) {
-				VPRINTK1("\t_group %dstream %d\n", s->stream,
+				VPRINTK1(KERN_INFO "\t%c%d group\n",
+						SCHR(s->stream),
 						s->number);
-				e = hpi_stream_group_add(ss,
+				e = hpi_stream_group_add(
 					dpcm->h_stream,
 					ds->h_stream);
 				if (!e) {
@@ -604,10 +622,12 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
 			} else
 				break;
 		}
-		snd_printd("start\n");
+		VPRINTK1(KERN_INFO "start\n");
 		/* start the master stream */
 		snd_card_asihpi_pcm_timer_start(substream);
-		hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream));
+		if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE) ||
+			!card->support_mmap)
+			hpi_handle_error(hpi_stream_start(dpcm->h_stream));
 		break;
 
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -615,88 +635,73 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream,
 		snd_pcm_group_for_each_entry(s, substream) {
 			if (snd_pcm_substream_chip(s) != card)
 				continue;
+			/* don't link Cap and Play */
+			if (substream->stream != s->stream)
+				continue;
 
 			/*? workaround linked streams don't
 			transition to SETUP 20070706*/
 			s->runtime->status->state = SNDRV_PCM_STATE_SETUP;
 
 			if (card->support_grouping) {
-				VPRINTK1("\t_group %dstream %d\n", s->stream,
+				VPRINTK1(KERN_INFO "\t%c%d group\n",
+				SCHR(s->stream),
 					s->number);
 				snd_pcm_trigger_done(s, substream);
 			} else
 				break;
 		}
-		snd_printd("stop\n");
+		VPRINTK1(KERN_INFO "stop\n");
 
 		/* _prepare and _hwparams reset the stream */
-		hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream));
+		hpi_handle_error(hpi_stream_stop(dpcm->h_stream));
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 			hpi_handle_error(
-				hpi_outstream_reset(ss, dpcm->h_stream));
+				hpi_outstream_reset(dpcm->h_stream));
 
 		if (card->support_grouping)
-			hpi_handle_error(hpi_stream_group_reset(ss,
-						dpcm->h_stream));
+			hpi_handle_error(hpi_stream_group_reset(dpcm->h_stream));
 		break;
 
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		snd_printd("pause release\n");
-		hpi_handle_error(hpi_stream_start(ss, dpcm->h_stream));
+		VPRINTK1(KERN_INFO "pause release\n");
+		hpi_handle_error(hpi_stream_start(dpcm->h_stream));
 		snd_card_asihpi_pcm_timer_start(substream);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		snd_printd("pause\n");
+		VPRINTK1(KERN_INFO "pause\n");
 		snd_card_asihpi_pcm_timer_stop(substream);
-		hpi_handle_error(hpi_stream_stop(ss, dpcm->h_stream));
+		hpi_handle_error(hpi_stream_stop(dpcm->h_stream));
 		break;
 	default:
-		snd_printd("\tINVALID\n");
+		snd_printd(KERN_ERR "\tINVALID\n");
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
-static int
-snd_card_asihpi_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
-	if (dpcm->hpi_buffer_attached)
-		hpi_stream_host_buffer_detach(ss, dpcm->h_stream);
-
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-static void snd_card_asihpi_runtime_free(struct snd_pcm_runtime *runtime)
-{
-	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
-	kfree(dpcm);
-}
-
 /*algorithm outline
  Without linking degenerates to getting single stream pos etc
  Without mmap 2nd loop degenerates to snd_pcm_period_elapsed
 */
 /*
-buf_pos=get_buf_pos(s);
+pcm_buf_dma_ofs=get_buf_pos(s);
 for_each_linked_stream(s) {
-	buf_pos=get_buf_pos(s);
-	min_buf_pos = modulo_min(min_buf_pos, buf_pos, pcm_size)
-	new_data = min(new_data, calc_new_data(buf_pos,irq_pos)
+	pcm_buf_dma_ofs=get_buf_pos(s);
+	min_buf_pos = modulo_min(min_buf_pos, pcm_buf_dma_ofs, buffer_bytes)
+	new_data = min(new_data, calc_new_data(pcm_buf_dma_ofs,irq_pos)
 }
 timer.expires = jiffies + predict_next_period_ready(min_buf_pos);
 for_each_linked_stream(s) {
-	s->buf_pos = min_buf_pos;
-	if (new_data > pcm_count) {
+	s->pcm_buf_dma_ofs = min_buf_pos;
+	if (new_data > period_bytes) {
 		if (mmap) {
-			irq_pos = (irq_pos + pcm_count) % pcm_size;
+			irq_pos = (irq_pos + period_bytes) % buffer_bytes;
 			if (playback) {
-				write(pcm_count);
+				write(period_bytes);
 			} else {
-				read(pcm_count);
+				read(period_bytes);
 			}
 		}
 		snd_pcm_period_elapsed(s);
@@ -724,105 +729,136 @@ static inline unsigned int modulo_min(unsigned int a, unsigned int b,
 static void snd_card_asihpi_timer_function(unsigned long data)
 {
 	struct snd_card_asihpi_pcm *dpcm = (struct snd_card_asihpi_pcm *)data;
-	struct snd_card_asihpi *card = snd_pcm_substream_chip(dpcm->substream);
+	struct snd_pcm_substream *substream = dpcm->substream;
+	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
 	struct snd_pcm_runtime *runtime;
 	struct snd_pcm_substream *s;
 	unsigned int newdata = 0;
-	unsigned int buf_pos, min_buf_pos = 0;
+	unsigned int pcm_buf_dma_ofs, min_buf_pos = 0;
 	unsigned int remdata, xfercount, next_jiffies;
 	int first = 1;
+	int loops = 0;
 	u16 state;
-	u32 buffer_size, data_avail, samples_played, aux;
+	u32 buffer_size, bytes_avail, samples_played, on_card_bytes;
+
+	VPRINTK1(KERN_INFO "%c%d snd_card_asihpi_timer_function\n",
+				SCHR(substream->stream), substream->number);
 
 	/* find minimum newdata and buffer pos in group */
-	snd_pcm_group_for_each_entry(s, dpcm->substream) {
+	snd_pcm_group_for_each_entry(s, substream) {
 		struct snd_card_asihpi_pcm *ds = s->runtime->private_data;
 		runtime = s->runtime;
 
 		if (snd_pcm_substream_chip(s) != card)
 			continue;
 
-		hpi_handle_error(hpi_stream_get_info_ex(ss,
+		/* don't link Cap and Play */
+		if (substream->stream != s->stream)
+			continue;
+
+		hpi_handle_error(hpi_stream_get_info_ex(
 					ds->h_stream, &state,
-					&buffer_size, &data_avail,
-					&samples_played, &aux));
+					&buffer_size, &bytes_avail,
+					&samples_played, &on_card_bytes));
 
 		/* number of bytes in on-card buffer */
-		runtime->delay = aux;
-
-		if (state == HPI_STATE_DRAINED) {
-			snd_printd(KERN_WARNING  "outstream %d drained\n",
-					s->number);
-			snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
-			return;
-		}
+		runtime->delay = on_card_bytes;
 
 		if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-			buf_pos = frames_to_bytes(runtime, samples_played);
-		} else {
-			buf_pos = data_avail + ds->pcm_irq_pos;
-		}
+			pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail;
+			if (state == HPI_STATE_STOPPED) {
+				if ((bytes_avail == 0) &&
+				    (on_card_bytes < ds->pcm_buf_host_rw_ofs)) {
+					hpi_handle_error(hpi_stream_start(ds->h_stream));
+					VPRINTK1(KERN_INFO "P%d start\n", s->number);
+				}
+			} else if (state == HPI_STATE_DRAINED) {
+				VPRINTK1(KERN_WARNING "P%d drained\n",
+						s->number);
+				/*snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
+				continue; */
+			}
+		} else
+			pcm_buf_dma_ofs = bytes_avail + ds->pcm_buf_host_rw_ofs;
 
 		if (first) {
 			/* can't statically init min when wrap is involved */
-			min_buf_pos = buf_pos;
-			newdata = (buf_pos - ds->pcm_irq_pos) % ds->pcm_size;
+			min_buf_pos = pcm_buf_dma_ofs;
+			newdata = (pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes;
 			first = 0;
 		} else {
 			min_buf_pos =
-				modulo_min(min_buf_pos, buf_pos, UINT_MAX+1L);
+				modulo_min(min_buf_pos, pcm_buf_dma_ofs, UINT_MAX+1L);
 			newdata = min(
-				(buf_pos - ds->pcm_irq_pos) % ds->pcm_size,
+				(pcm_buf_dma_ofs - ds->pcm_buf_elapsed_dma_ofs) % ds->buffer_bytes,
 				newdata);
 		}
 
-		VPRINTK1("PB timer hw_ptr x%04lX, appl_ptr x%04lX\n",
+		VPRINTK1(KERN_INFO "PB timer hw_ptr x%04lX, appl_ptr x%04lX\n",
 			(unsigned long)frames_to_bytes(runtime,
 						runtime->status->hw_ptr),
 			(unsigned long)frames_to_bytes(runtime,
 						runtime->control->appl_ptr));
-		VPRINTK1("%d S=%d, irq=%04X, pos=x%04X, left=x%04X,"
-			" aux=x%04X space=x%04X\n", s->number,
-			state,	ds->pcm_irq_pos, buf_pos, (int)data_avail,
-			(int)aux, buffer_size-data_avail);
+
+		VPRINTK1(KERN_INFO "%d %c%d S=%d, rw=%04X, dma=x%04X, left=x%04X,"
+			" aux=x%04X space=x%04X\n",
+			loops, SCHR(s->stream),	s->number,
+			state,	ds->pcm_buf_host_rw_ofs, pcm_buf_dma_ofs, (int)bytes_avail,
+			(int)on_card_bytes, buffer_size-bytes_avail);
+		loops++;
 	}
+	pcm_buf_dma_ofs = min_buf_pos;
 
-	remdata = newdata % dpcm->pcm_count;
-	xfercount = newdata - remdata; /* a multiple of pcm_count */
-	next_jiffies = ((dpcm->pcm_count-remdata) * HZ / dpcm->bytes_per_sec)+1;
-	next_jiffies = max(next_jiffies, 2U * HZ / 1000U);
+	remdata = newdata % dpcm->period_bytes;
+	xfercount = newdata - remdata; /* a multiple of period_bytes */
+	/* come back when on_card_bytes has decreased enough to allow
+	   write to happen, or when data has been consumed to make another
+	   period
+	*/
+	if (xfercount && (on_card_bytes  > dpcm->period_bytes))
+		next_jiffies = ((on_card_bytes - dpcm->period_bytes) * HZ / dpcm->bytes_per_sec);
+	else
+		next_jiffies = ((dpcm->period_bytes - remdata) * HZ / dpcm->bytes_per_sec);
+
+	next_jiffies = max(next_jiffies, 1U);
 	dpcm->timer.expires = jiffies + next_jiffies;
-	VPRINTK1("jif %d buf pos x%04X newdata x%04X xc x%04X\n",
-			next_jiffies, min_buf_pos, newdata, xfercount);
+	VPRINTK1(KERN_INFO "jif %d buf pos x%04X newdata x%04X xfer x%04X\n",
+			next_jiffies, pcm_buf_dma_ofs, newdata, xfercount);
 
-	snd_pcm_group_for_each_entry(s, dpcm->substream) {
+	snd_pcm_group_for_each_entry(s, substream) {
 		struct snd_card_asihpi_pcm *ds = s->runtime->private_data;
-		ds->pcm_buf_pos = min_buf_pos;
 
-		if (xfercount) {
+		/* don't link Cap and Play */
+		if (substream->stream != s->stream)
+			continue;
+
+		ds->pcm_buf_dma_ofs = pcm_buf_dma_ofs;
+
+		if (xfercount && (on_card_bytes <= ds->period_bytes)) {
 			if (card->support_mmap) {
-				ds->pcm_irq_pos = ds->pcm_irq_pos + xfercount;
 				if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-					VPRINTK2("write OS%d x%04x\n",
+					VPRINTK2(KERN_INFO "P%d write x%04x\n",
 							s->number,
-							ds->pcm_count);
+							ds->period_bytes);
 					hpi_handle_error(
 						hpi_outstream_write_buf(
-							ss, ds->h_stream,
+							ds->h_stream,
 							&s->runtime->
 								dma_area[0],
 							xfercount,
 							&ds->format));
 				} else {
-					VPRINTK2("read IS%d x%04x\n",
+					VPRINTK2(KERN_INFO "C%d read x%04x\n",
 						s->number,
-						dpcm->pcm_count);
+						xfercount);
 					hpi_handle_error(
 						hpi_instream_read_buf(
-							ss, ds->h_stream,
+							ds->h_stream,
 							NULL, xfercount));
 				}
+				ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount;
 			} /* else R/W will be handled by read/write callbacks */
+			ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs;
 			snd_pcm_period_elapsed(s);
 		}
 	}
@@ -845,12 +881,12 @@ static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
-	snd_printd(KERN_INFO "playback prepare %d\n", substream->number);
-
-	hpi_handle_error(hpi_outstream_reset(ss, dpcm->h_stream));
-	dpcm->pcm_irq_pos = 0;
-	dpcm->pcm_buf_pos = 0;
+	VPRINTK1(KERN_INFO "playback prepare %d\n", substream->number);
 
+	hpi_handle_error(hpi_outstream_reset(dpcm->h_stream));
+	dpcm->pcm_buf_host_rw_ofs = 0;
+	dpcm->pcm_buf_dma_ofs = 0;
+	dpcm->pcm_buf_elapsed_dma_ofs = 0;
 	return 0;
 }
 
@@ -861,27 +897,8 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 	snd_pcm_uframes_t ptr;
 
-	u32 samples_played;
-	u16 err;
-
-	if (!snd_pcm_stream_linked(substream)) {
-		/* NOTE, can use samples played for playback position here and
-		* in timer fn because it LAGS the actual read pointer, and is a
-		* better representation of actual playout position
-		*/
-		err = hpi_outstream_get_info_ex(ss, dpcm->h_stream, NULL,
-					NULL, NULL,
-					&samples_played, NULL);
-		hpi_handle_error(err);
-
-		dpcm->pcm_buf_pos = frames_to_bytes(runtime, samples_played);
-	}
-	/* else must return most conservative value found in timer func
-	 * by looping over all streams
-	 */
-
-	ptr = bytes_to_frames(runtime, dpcm->pcm_buf_pos  % dpcm->pcm_size);
-	VPRINTK2("playback_pointer=%04ld\n", (unsigned long)ptr);
+	ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs  % dpcm->buffer_bytes);
+	/* VPRINTK2(KERN_INFO "playback_pointer=x%04lx\n", (unsigned long)ptr); */
 	return ptr;
 }
 
@@ -898,12 +915,12 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
 	/* on cards without SRC, must query at valid rate,
 	* maybe set by external sync
 	*/
-	err = hpi_mixer_get_control(ss, asihpi->h_mixer,
+	err = hpi_mixer_get_control(asihpi->h_mixer,
 				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
 				  HPI_CONTROL_SAMPLECLOCK, &h_control);
 
 	if (!err)
-		err = hpi_sample_clock_get_sample_rate(ss, h_control,
+		err = hpi_sample_clock_get_sample_rate(h_control,
 				&sample_rate);
 
 	for (format = HPI_FORMAT_PCM8_UNSIGNED;
@@ -911,7 +928,7 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
 		err = hpi_format_create(&hpi_format,
 					2, format, sample_rate, 128000, 0);
 		if (!err)
-			err = hpi_outstream_query_format(ss, h_stream,
+			err = hpi_outstream_query_format(h_stream,
 							&hpi_format);
 		if (!err && (hpi_to_alsa_formats[format] != -1))
 			pcmhw->formats |=
@@ -942,7 +959,7 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
 		return -ENOMEM;
 
 	err =
-	    hpi_outstream_open(ss, card->adapter_index,
+	    hpi_outstream_open(card->adapter_index,
 			      substream->number, &dpcm->h_stream);
 	hpi_handle_error(err);
 	if (err)
@@ -998,11 +1015,11 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
 	snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
 		card->update_interval_frames);
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-		card->update_interval_frames * 4, UINT_MAX);
+		card->update_interval_frames * 2, UINT_MAX);
 
 	snd_pcm_set_sync(substream);
 
-	snd_printd(KERN_INFO "playback open\n");
+	VPRINTK1(KERN_INFO "playback open\n");
 
 	return 0;
 }
@@ -1012,8 +1029,8 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
-	hpi_handle_error(hpi_outstream_close(ss, dpcm->h_stream));
-	snd_printd(KERN_INFO "playback close\n");
+	hpi_handle_error(hpi_outstream_close(dpcm->h_stream));
+	VPRINTK1(KERN_INFO "playback close\n");
 
 	return 0;
 }
@@ -1036,9 +1053,11 @@ static int snd_card_asihpi_playback_copy(struct snd_pcm_substream *substream,
 	VPRINTK2(KERN_DEBUG "playback copy%d %u bytes\n",
 			substream->number, len);
 
-	hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream,
+	hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream,
 				runtime->dma_area, len, &dpcm->format));
 
+	dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len;
+
 	return 0;
 }
 
@@ -1052,10 +1071,10 @@ static int snd_card_asihpi_playback_silence(struct snd_pcm_substream *
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
 	len = frames_to_bytes(runtime, count);
-	snd_printd(KERN_INFO "playback silence  %u bytes\n", len);
+	VPRINTK1(KERN_INFO "playback silence  %u bytes\n", len);
 
 	memset(runtime->dma_area, 0, len);
-	hpi_handle_error(hpi_outstream_write_buf(ss, dpcm->h_stream,
+	hpi_handle_error(hpi_outstream_write_buf(dpcm->h_stream,
 				runtime->dma_area, len, &dpcm->format));
 	return 0;
 }
@@ -1091,13 +1110,13 @@ snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
-	VPRINTK2("capture pointer %d=%d\n",
-			substream->number, dpcm->pcm_buf_pos);
-	/* NOTE Unlike playback can't use actual dwSamplesPlayed
+	VPRINTK2(KERN_INFO "capture pointer %d=%d\n",
+			substream->number, dpcm->pcm_buf_dma_ofs);
+	/* NOTE Unlike playback can't use actual samples_played
 		for the capture position, because those samples aren't yet in
 		the local buffer available for reading.
 	*/
-	return bytes_to_frames(runtime, dpcm->pcm_buf_pos % dpcm->pcm_size);
+	return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);
 }
 
 static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream,
@@ -1111,11 +1130,12 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
 
-	hpi_handle_error(hpi_instream_reset(ss, dpcm->h_stream));
-	dpcm->pcm_irq_pos = 0;
-	dpcm->pcm_buf_pos = 0;
+	hpi_handle_error(hpi_instream_reset(dpcm->h_stream));
+	dpcm->pcm_buf_host_rw_ofs = 0;
+	dpcm->pcm_buf_dma_ofs = 0;
+	dpcm->pcm_buf_elapsed_dma_ofs = 0;
 
-	snd_printd("capture prepare %d\n", substream->number);
+	VPRINTK1("Capture Prepare %d\n", substream->number);
 	return 0;
 }
 
@@ -1133,12 +1153,12 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
 
 	/* on cards without SRC, must query at valid rate,
 		maybe set by external sync */
-	err = hpi_mixer_get_control(ss, asihpi->h_mixer,
+	err = hpi_mixer_get_control(asihpi->h_mixer,
 				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
 				  HPI_CONTROL_SAMPLECLOCK, &h_control);
 
 	if (!err)
-		err = hpi_sample_clock_get_sample_rate(ss, h_control,
+		err = hpi_sample_clock_get_sample_rate(h_control,
 			&sample_rate);
 
 	for (format = HPI_FORMAT_PCM8_UNSIGNED;
@@ -1147,7 +1167,7 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
 		err = hpi_format_create(&hpi_format, 2, format,
 				sample_rate, 128000, 0);
 		if (!err)
-			err = hpi_instream_query_format(ss, h_stream,
+			err = hpi_instream_query_format(h_stream,
 					    &hpi_format);
 		if (!err)
 			pcmhw->formats |=
@@ -1178,11 +1198,11 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
 	if (dpcm == NULL)
 		return -ENOMEM;
 
-	snd_printd("hpi_instream_open adapter %d stream %d\n",
+	VPRINTK1("hpi_instream_open adapter %d stream %d\n",
 		   card->adapter_index, substream->number);
 
 	err = hpi_handle_error(
-	    hpi_instream_open(ss, card->adapter_index,
+	    hpi_instream_open(card->adapter_index,
 			     substream->number, &dpcm->h_stream));
 	if (err)
 		kfree(dpcm);
@@ -1209,6 +1229,9 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
 		snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_MMAP |
 						SNDRV_PCM_INFO_MMAP_VALID;
 
+	if (card->support_grouping)
+		snd_card_asihpi_capture.info |= SNDRV_PCM_INFO_SYNC_START;
+
 	runtime->hw = snd_card_asihpi_capture;
 
 	if (card->support_mmap)
@@ -1231,7 +1254,7 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)
 {
 	struct snd_card_asihpi_pcm *dpcm = substream->runtime->private_data;
 
-	hpi_handle_error(hpi_instream_close(ss, dpcm->h_stream));
+	hpi_handle_error(hpi_instream_close(dpcm->h_stream));
 	return 0;
 }
 
@@ -1241,18 +1264,17 @@ static int snd_card_asihpi_capture_copy(struct snd_pcm_substream *substream,
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
-	u32 data_size;
+	u32 len;
 
-	data_size = frames_to_bytes(runtime, count);
+	len = frames_to_bytes(runtime, count);
 
-	VPRINTK2("capture copy%d %d bytes\n", substream->number, data_size);
-	hpi_handle_error(hpi_instream_read_buf(ss, dpcm->h_stream,
-				runtime->dma_area, data_size));
+	VPRINTK2(KERN_INFO "capture copy%d %d bytes\n", substream->number, len);
+	hpi_handle_error(hpi_instream_read_buf(dpcm->h_stream,
+				runtime->dma_area, len));
 
-	/* Used by capture_pointer */
-	dpcm->pcm_irq_pos = dpcm->pcm_irq_pos + data_size;
+	dpcm->pcm_buf_host_rw_ofs = dpcm->pcm_buf_host_rw_ofs + len;
 
-	if (copy_to_user(dst, runtime->dma_area, data_size))
+	if (copy_to_user(dst, runtime->dma_area, len))
 		return -EFAULT;
 
 	return 0;
@@ -1287,7 +1309,7 @@ static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
 	struct snd_pcm *pcm;
 	int err;
 
-	err = snd_pcm_new(asihpi->card, "asihpi PCM", device,
+	err = snd_pcm_new(asihpi->card, "Asihpi PCM", device,
 			 asihpi->num_outstreams, asihpi->num_instreams,
 			 &pcm);
 	if (err < 0)
@@ -1307,7 +1329,7 @@ static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
 
 	pcm->private_data = asihpi;
 	pcm->info_flags = 0;
-	strcpy(pcm->name, "asihpi PCM");
+	strcpy(pcm->name, "Asihpi PCM");
 
 	/*? do we want to emulate MMAP for non-BBM cards?
 	Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */
@@ -1330,8 +1352,7 @@ struct hpi_control {
 	char name[44]; /* copied to snd_ctl_elem_id.name[44]; */
 };
 
-static char *asihpi_tuner_band_names[] =
-{
+static const char * const asihpi_tuner_band_names[] = {
 	"invalid",
 	"AM",
 	"FM mono",
@@ -1349,70 +1370,36 @@ compile_time_assert(
 		(HPI_TUNER_BAND_LAST+1)),
 	assert_tuner_band_names_size);
 
-#if ASI_STYLE_NAMES
-static char *asihpi_src_names[] =
-{
+static const char * const asihpi_src_names[] = {
 	"no source",
-	"outstream",
-	"line_in",
-	"aes_in",
-	"tuner",
+	"PCM",
+	"Line",
+	"Digital",
+	"Tuner",
 	"RF",
-	"clock",
-	"bitstr",
-	"mic",
-	"cobranet",
-	"analog_in",
-	"adapter",
+	"Clock",
+	"Bitstream",
+	"Microphone",
+	"Cobranet",
+	"Analog",
+	"Adapter",
 };
-#else
-static char *asihpi_src_names[] =
-{
-	"no source",
-	"PCM playback",
-	"line in",
-	"digital in",
-	"tuner",
-	"RF",
-	"clock",
-	"bitstream",
-	"mic",
-	"cobranet in",
-	"analog in",
-	"adapter",
-};
-#endif
 
 compile_time_assert(
 	(ARRAY_SIZE(asihpi_src_names) ==
 		(HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)),
 	assert_src_names_size);
 
-#if ASI_STYLE_NAMES
-static char *asihpi_dst_names[] =
-{
-	"no destination",
-	"instream",
-	"line_out",
-	"aes_out",
-	"RF",
-	"speaker" ,
-	"cobranet",
-	"analog_out",
-};
-#else
-static char *asihpi_dst_names[] =
-{
+static const char * const asihpi_dst_names[] = {
 	"no destination",
-	"PCM capture",
-	"line out",
-	"digital out",
+	"PCM",
+	"Line",
+	"Digital",
 	"RF",
-	"speaker",
-	"cobranet out",
-	"analog out"
+	"Speaker",
+	"Cobranet Out",
+	"Analog"
 };
-#endif
 
 compile_time_assert(
 	(ARRAY_SIZE(asihpi_dst_names) ==
@@ -1438,30 +1425,45 @@ static void asihpi_ctl_init(struct snd_kcontrol_new *snd_control,
 				struct hpi_control *hpi_ctl,
 				char *name)
 {
+	char *dir = "";
 	memset(snd_control, 0, sizeof(*snd_control));
 	snd_control->name = hpi_ctl->name;
 	snd_control->private_value = hpi_ctl->h_control;
 	snd_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
 	snd_control->index = 0;
 
+	if (hpi_ctl->dst_node_type + HPI_DESTNODE_NONE == HPI_DESTNODE_ISTREAM)
+		dir = "Capture ";  /* On or towards a PCM capture destination*/
+	else if ((hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&
+		(!hpi_ctl->dst_node_type))
+		dir = "Capture "; /* On a source node that is not PCM playback */
+	else if (hpi_ctl->src_node_type &&
+		(hpi_ctl->src_node_type + HPI_SOURCENODE_NONE != HPI_SOURCENODE_OSTREAM) &&
+		(hpi_ctl->dst_node_type))
+		dir = "Monitor Playback "; /* Between an input and an output */
+	else
+		dir = "Playback "; /* PCM Playback source, or  output node */
+
 	if (hpi_ctl->src_node_type && hpi_ctl->dst_node_type)
-		sprintf(hpi_ctl->name, "%s%d to %s%d %s",
+		sprintf(hpi_ctl->name, "%s%d %s%d %s%s",
 			asihpi_src_names[hpi_ctl->src_node_type],
 			hpi_ctl->src_node_index,
 			asihpi_dst_names[hpi_ctl->dst_node_type],
 			hpi_ctl->dst_node_index,
-			name);
+			dir, name);
 	else if (hpi_ctl->dst_node_type) {
-		sprintf(hpi_ctl->name, "%s%d %s",
+		sprintf(hpi_ctl->name, "%s %d %s%s",
 		asihpi_dst_names[hpi_ctl->dst_node_type],
 		hpi_ctl->dst_node_index,
-		name);
+		dir, name);
 	} else {
-		sprintf(hpi_ctl->name, "%s%d %s",
+		sprintf(hpi_ctl->name, "%s %d %s%s",
 		asihpi_src_names[hpi_ctl->src_node_type],
 		hpi_ctl->src_node_index,
-		name);
+		dir, name);
 	}
+	/* printk(KERN_INFO "Adding %s %d to %d ",  hpi_ctl->name,
+		hpi_ctl->wSrcNodeType, hpi_ctl->wDstNodeType); */
 }
 
 /*------------------------------------------------------------
@@ -1478,7 +1480,7 @@ static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol,
 	short max_gain_mB;
 	short step_gain_mB;
 
-	err = hpi_volume_query_range(ss, h_control,
+	err = hpi_volume_query_range(h_control,
 			&min_gain_mB, &max_gain_mB, &step_gain_mB);
 	if (err) {
 		max_gain_mB = 0;
@@ -1500,7 +1502,7 @@ static int snd_asihpi_volume_get(struct snd_kcontrol *kcontrol,
 	u32 h_control = kcontrol->private_value;
 	short an_gain_mB[HPI_MAX_CHANNELS];
 
-	hpi_handle_error(hpi_volume_get_gain(ss, h_control, an_gain_mB));
+	hpi_handle_error(hpi_volume_get_gain(h_control, an_gain_mB));
 	ucontrol->value.integer.value[0] = an_gain_mB[0] / VOL_STEP_mB;
 	ucontrol->value.integer.value[1] = an_gain_mB[1] / VOL_STEP_mB;
 
@@ -1522,7 +1524,7 @@ static int snd_asihpi_volume_put(struct snd_kcontrol *kcontrol,
 	   asihpi->mixer_volume[addr][1] != right;
 	 */
 	change = 1;
-	hpi_handle_error(hpi_volume_set_gain(ss, h_control, an_gain_mB));
+	hpi_handle_error(hpi_volume_set_gain(h_control, an_gain_mB));
 	return change;
 }
 
@@ -1534,7 +1536,7 @@ static int __devinit snd_asihpi_volume_add(struct snd_card_asihpi *asihpi,
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "volume");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Volume");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 				SNDRV_CTL_ELEM_ACCESS_TLV_READ;
 	snd_control.info = snd_asihpi_volume_info;
@@ -1558,7 +1560,7 @@ static int snd_asihpi_level_info(struct snd_kcontrol *kcontrol,
 	short step_gain_mB;
 
 	err =
-	    hpi_level_query_range(ss, h_control, &min_gain_mB,
+	    hpi_level_query_range(h_control, &min_gain_mB,
 			       &max_gain_mB, &step_gain_mB);
 	if (err) {
 		max_gain_mB = 2400;
@@ -1580,7 +1582,7 @@ static int snd_asihpi_level_get(struct snd_kcontrol *kcontrol,
 	u32 h_control = kcontrol->private_value;
 	short an_gain_mB[HPI_MAX_CHANNELS];
 
-	hpi_handle_error(hpi_level_get_gain(ss, h_control, an_gain_mB));
+	hpi_handle_error(hpi_level_get_gain(h_control, an_gain_mB));
 	ucontrol->value.integer.value[0] =
 	    an_gain_mB[0] / HPI_UNITS_PER_dB;
 	ucontrol->value.integer.value[1] =
@@ -1604,7 +1606,7 @@ static int snd_asihpi_level_put(struct snd_kcontrol *kcontrol,
 	   asihpi->mixer_level[addr][1] != right;
 	 */
 	change = 1;
-	hpi_handle_error(hpi_level_set_gain(ss, h_control, an_gain_mB));
+	hpi_handle_error(hpi_level_set_gain(h_control, an_gain_mB));
 	return change;
 }
 
@@ -1617,7 +1619,7 @@ static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
 	struct snd_kcontrol_new snd_control;
 
 	/* can't use 'volume' cos some nodes have volume as well */
-	asihpi_ctl_init(&snd_control, hpi_ctl, "level");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Level");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 				SNDRV_CTL_ELEM_ACCESS_TLV_READ;
 	snd_control.info = snd_asihpi_level_info;
@@ -1633,12 +1635,8 @@ static int __devinit snd_asihpi_level_add(struct snd_card_asihpi *asihpi,
  ------------------------------------------------------------*/
 
 /* AESEBU format */
-static char *asihpi_aesebu_format_names[] =
-{
-	"N/A",
-	"S/PDIF",
-	"AES/EBU",
-};
+static const char * const asihpi_aesebu_format_names[] = {
+	"N/A", "S/PDIF", "AES/EBU" };
 
 static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
@@ -1659,12 +1657,12 @@ static int snd_asihpi_aesebu_format_info(struct snd_kcontrol *kcontrol,
 
 static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol,
-			u16 (*func)(const struct hpi_hsubsys *, u32, u16 *))
+			u16 (*func)(u32, u16 *))
 {
 	u32 h_control = kcontrol->private_value;
 	u16 source, err;
 
-	err = func(ss, h_control, &source);
+	err = func(h_control, &source);
 
 	/* default to N/A */
 	ucontrol->value.enumerated.item[0] = 0;
@@ -1681,7 +1679,7 @@ static int snd_asihpi_aesebu_format_get(struct snd_kcontrol *kcontrol,
 
 static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol,
-			 u16 (*func)(const struct hpi_hsubsys *, u32, u16))
+			 u16 (*func)(u32, u16))
 {
 	u32 h_control = kcontrol->private_value;
 
@@ -1693,7 +1691,7 @@ static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol,
 	if (ucontrol->value.enumerated.item[0] == 2)
 		source = HPI_AESEBU_FORMAT_AESEBU;
 
-	if (func(ss, h_control, source) != 0)
+	if (func(h_control, source) != 0)
 		return -EINVAL;
 
 	return 1;
@@ -1702,13 +1700,13 @@ static int snd_asihpi_aesebu_format_put(struct snd_kcontrol *kcontrol,
 static int snd_asihpi_aesebu_rx_format_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol) {
 	return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,
-					HPI_AESEBU__receiver_get_format);
+					hpi_aesebu_receiver_get_format);
 }
 
 static int snd_asihpi_aesebu_rx_format_put(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol) {
 	return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,
-					HPI_AESEBU__receiver_set_format);
+					hpi_aesebu_receiver_set_format);
 }
 
 static int snd_asihpi_aesebu_rxstatus_info(struct snd_kcontrol *kcontrol,
@@ -1730,8 +1728,8 @@ static int snd_asihpi_aesebu_rxstatus_get(struct snd_kcontrol *kcontrol,
 	u32 h_control = kcontrol->private_value;
 	u16 status;
 
-	hpi_handle_error(HPI_AESEBU__receiver_get_error_status(
-				ss, h_control, &status));
+	hpi_handle_error(hpi_aesebu_receiver_get_error_status(
+					 h_control, &status));
 	ucontrol->value.integer.value[0] = status;
 	return 0;
 }
@@ -1742,7 +1740,7 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "format");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Format");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 	snd_control.info = snd_asihpi_aesebu_format_info;
 	snd_control.get = snd_asihpi_aesebu_rx_format_get;
@@ -1752,7 +1750,7 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
 	if (ctl_add(card, &snd_control, asihpi) < 0)
 		return -EINVAL;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "status");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Status");
 	snd_control.access =
 	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
 	snd_control.info = snd_asihpi_aesebu_rxstatus_info;
@@ -1764,13 +1762,13 @@ static int __devinit snd_asihpi_aesebu_rx_add(struct snd_card_asihpi *asihpi,
 static int snd_asihpi_aesebu_tx_format_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol) {
 	return snd_asihpi_aesebu_format_get(kcontrol, ucontrol,
-					HPI_AESEBU__transmitter_get_format);
+					hpi_aesebu_transmitter_get_format);
 }
 
 static int snd_asihpi_aesebu_tx_format_put(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol) {
 	return snd_asihpi_aesebu_format_put(kcontrol, ucontrol,
-					HPI_AESEBU__transmitter_set_format);
+					hpi_aesebu_transmitter_set_format);
 }
 
 
@@ -1780,7 +1778,7 @@ static int __devinit snd_asihpi_aesebu_tx_add(struct snd_card_asihpi *asihpi,
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "format");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Format");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 	snd_control.info = snd_asihpi_aesebu_format_info;
 	snd_control.get = snd_asihpi_aesebu_tx_format_get;
@@ -1804,7 +1802,7 @@ static int snd_asihpi_tuner_gain_info(struct snd_kcontrol *kcontrol,
 	u16 gain_range[3];
 
 	for (idx = 0; idx < 3; idx++) {
-		err = hpi_tuner_query_gain(ss, h_control,
+		err = hpi_tuner_query_gain(h_control,
 					  idx, &gain_range[idx]);
 		if (err != 0)
 			return err;
@@ -1827,7 +1825,7 @@ static int snd_asihpi_tuner_gain_get(struct snd_kcontrol *kcontrol,
 	u32 h_control = kcontrol->private_value;
 	short gain;
 
-	hpi_handle_error(hpi_tuner_get_gain(ss, h_control, &gain));
+	hpi_handle_error(hpi_tuner_get_gain(h_control, &gain));
 	ucontrol->value.integer.value[0] = gain / HPI_UNITS_PER_dB;
 
 	return 0;
@@ -1843,7 +1841,7 @@ static int snd_asihpi_tuner_gain_put(struct snd_kcontrol *kcontrol,
 	short gain;
 
 	gain = (ucontrol->value.integer.value[0]) * HPI_UNITS_PER_dB;
-	hpi_handle_error(hpi_tuner_set_gain(ss, h_control, gain));
+	hpi_handle_error(hpi_tuner_set_gain(h_control, gain));
 
 	return 1;
 }
@@ -1857,7 +1855,7 @@ static int asihpi_tuner_band_query(struct snd_kcontrol *kcontrol,
 	u32 i;
 
 	for (i = 0; i < len; i++) {
-		err = hpi_tuner_query_band(ss,
+		err = hpi_tuner_query_band(
 				h_control, i, &band_list[i]);
 		if (err != 0)
 			break;
@@ -1913,7 +1911,7 @@ static int snd_asihpi_tuner_band_get(struct snd_kcontrol *kcontrol,
 	num_bands = asihpi_tuner_band_query(kcontrol, tuner_bands,
 				HPI_TUNER_BAND_LAST);
 
-	hpi_handle_error(hpi_tuner_get_band(ss, h_control, &band));
+	hpi_handle_error(hpi_tuner_get_band(h_control, &band));
 
 	ucontrol->value.enumerated.item[0] = -1;
 	for (idx = 0; idx < HPI_TUNER_BAND_LAST; idx++)
@@ -1940,7 +1938,7 @@ static int snd_asihpi_tuner_band_put(struct snd_kcontrol *kcontrol,
 			HPI_TUNER_BAND_LAST);
 
 	band = tuner_bands[ucontrol->value.enumerated.item[0]];
-	hpi_handle_error(hpi_tuner_set_band(ss, h_control, band));
+	hpi_handle_error(hpi_tuner_set_band(h_control, band));
 
 	return 1;
 }
@@ -1965,7 +1963,7 @@ static int snd_asihpi_tuner_freq_info(struct snd_kcontrol *kcontrol,
 
 	for (band_iter = 0; band_iter < num_bands; band_iter++) {
 		for (idx = 0; idx < 3; idx++) {
-			err = hpi_tuner_query_frequency(ss, h_control,
+			err = hpi_tuner_query_frequency(h_control,
 				idx, tuner_bands[band_iter],
 				&temp_freq_range[idx]);
 			if (err != 0)
@@ -1998,7 +1996,7 @@ static int snd_asihpi_tuner_freq_get(struct snd_kcontrol *kcontrol,
 	u32 h_control = kcontrol->private_value;
 	u32 freq;
 
-	hpi_handle_error(hpi_tuner_get_frequency(ss, h_control, &freq));
+	hpi_handle_error(hpi_tuner_get_frequency(h_control, &freq));
 	ucontrol->value.integer.value[0] = freq;
 
 	return 0;
@@ -2011,7 +2009,7 @@ static int snd_asihpi_tuner_freq_put(struct snd_kcontrol *kcontrol,
 	u32 freq;
 
 	freq = ucontrol->value.integer.value[0];
-	hpi_handle_error(hpi_tuner_set_frequency(ss, h_control, freq));
+	hpi_handle_error(hpi_tuner_set_frequency(h_control, freq));
 
 	return 1;
 }
@@ -2026,8 +2024,8 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
 	snd_control.private_value = hpi_ctl->h_control;
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 
-	if (!hpi_tuner_get_gain(ss, hpi_ctl->h_control, NULL)) {
-		asihpi_ctl_init(&snd_control, hpi_ctl, "gain");
+	if (!hpi_tuner_get_gain(hpi_ctl->h_control, NULL)) {
+		asihpi_ctl_init(&snd_control, hpi_ctl, "Gain");
 		snd_control.info = snd_asihpi_tuner_gain_info;
 		snd_control.get = snd_asihpi_tuner_gain_get;
 		snd_control.put = snd_asihpi_tuner_gain_put;
@@ -2036,7 +2034,7 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
 			return -EINVAL;
 	}
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "band");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Band");
 	snd_control.info = snd_asihpi_tuner_band_info;
 	snd_control.get = snd_asihpi_tuner_band_get;
 	snd_control.put = snd_asihpi_tuner_band_put;
@@ -2044,7 +2042,7 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
 	if (ctl_add(card, &snd_control, asihpi) < 0)
 		return -EINVAL;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "freq");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Freq");
 	snd_control.info = snd_asihpi_tuner_freq_info;
 	snd_control.get = snd_asihpi_tuner_freq_get;
 	snd_control.put = snd_asihpi_tuner_freq_put;
@@ -2095,7 +2093,7 @@ static int snd_asihpi_meter_get(struct snd_kcontrol *kcontrol,
 	short an_gain_mB[HPI_MAX_CHANNELS], i;
 	u16 err;
 
-	err = hpi_meter_get_peak(ss, h_control, an_gain_mB);
+	err = hpi_meter_get_peak(h_control, an_gain_mB);
 
 	for (i = 0; i < HPI_MAX_CHANNELS; i++) {
 		if (err) {
@@ -2120,7 +2118,7 @@ static int __devinit snd_asihpi_meter_add(struct snd_card_asihpi *asihpi,
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "meter");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Meter");
 	snd_control.access =
 	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
 	snd_control.info = snd_asihpi_meter_info;
@@ -2140,7 +2138,7 @@ static int snd_card_asihpi_mux_count_sources(struct snd_kcontrol *snd_control)
 	struct hpi_control hpi_ctl;
 	int s, err;
 	for (s = 0; s < 32; s++) {
-		err = hpi_multiplexer_query_source(ss, h_control, s,
+		err = hpi_multiplexer_query_source(h_control, s,
 						  &hpi_ctl.
 						  src_node_type,
 						  &hpi_ctl.
@@ -2168,7 +2166,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
 		    uinfo->value.enumerated.items - 1;
 
 	err =
-	    hpi_multiplexer_query_source(ss, h_control,
+	    hpi_multiplexer_query_source(h_control,
 					uinfo->value.enumerated.item,
 					&src_node_type, &src_node_index);
 
@@ -2186,11 +2184,11 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol,
 	u16 src_node_type, src_node_index;
 	int s;
 
-	hpi_handle_error(hpi_multiplexer_get_source(ss, h_control,
+	hpi_handle_error(hpi_multiplexer_get_source(h_control,
 				&source_type, &source_index));
 	/* Should cache this search result! */
 	for (s = 0; s < 256; s++) {
-		if (hpi_multiplexer_query_source(ss, h_control, s,
+		if (hpi_multiplexer_query_source(h_control, s,
 					    &src_node_type, &src_node_index))
 			break;
 
@@ -2201,7 +2199,7 @@ static int snd_asihpi_mux_get(struct snd_kcontrol *kcontrol,
 		}
 	}
 	snd_printd(KERN_WARNING
-		"control %x failed to match mux source %hu %hu\n",
+		"Control %x failed to match mux source %hu %hu\n",
 		h_control, source_type, source_index);
 	ucontrol->value.enumerated.item[0] = 0;
 	return 0;
@@ -2217,12 +2215,12 @@ static int snd_asihpi_mux_put(struct snd_kcontrol *kcontrol,
 
 	change = 1;
 
-	e = hpi_multiplexer_query_source(ss, h_control,
+	e = hpi_multiplexer_query_source(h_control,
 				    ucontrol->value.enumerated.item[0],
 				    &source_type, &source_index);
 	if (!e)
 		hpi_handle_error(
-			hpi_multiplexer_set_source(ss, h_control,
+			hpi_multiplexer_set_source(h_control,
 						source_type, source_index));
 	return change;
 }
@@ -2234,11 +2232,7 @@ static int  __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
 
-#if ASI_STYLE_NAMES
-	asihpi_ctl_init(&snd_control, hpi_ctl, "multiplexer");
-#else
-	asihpi_ctl_init(&snd_control, hpi_ctl, "route");
-#endif
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Route");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 	snd_control.info = snd_asihpi_mux_info;
 	snd_control.get = snd_asihpi_mux_get;
@@ -2254,33 +2248,38 @@ static int  __devinit snd_asihpi_mux_add(struct snd_card_asihpi *asihpi,
 static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_info *uinfo)
 {
-	static char *mode_names[HPI_CHANNEL_MODE_LAST] = {
-		"normal", "swap",
-		"from_left", "from_right",
-		"to_left", "to_right"
+	static const char * const mode_names[HPI_CHANNEL_MODE_LAST + 1] = {
+		"invalid",
+		"Normal", "Swap",
+		"From Left", "From Right",
+		"To Left", "To Right"
 	};
 
 	u32 h_control = kcontrol->private_value;
 	u16 mode;
 	int i;
+	u16 mode_map[6];
+	int valid_modes = 0;
 
 	/* HPI channel mode values can be from 1 to 6
 	Some adapters only support a contiguous subset
 	*/
 	for (i = 0; i < HPI_CHANNEL_MODE_LAST; i++)
-		if (hpi_channel_mode_query_mode(
-			ss,  h_control, i, &mode))
-			break;
+		if (!hpi_channel_mode_query_mode(
+			h_control, i, &mode)) {
+			mode_map[valid_modes] = mode;
+			valid_modes++;
+			}
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = i;
+	uinfo->value.enumerated.items = valid_modes;
 
-	if (uinfo->value.enumerated.item >= i)
-		uinfo->value.enumerated.item = i - 1;
+	if (uinfo->value.enumerated.item >= valid_modes)
+		uinfo->value.enumerated.item = valid_modes - 1;
 
 	strcpy(uinfo->value.enumerated.name,
-	       mode_names[uinfo->value.enumerated.item]);
+	       mode_names[mode_map[uinfo->value.enumerated.item]]);
 
 	return 0;
 }
@@ -2291,7 +2290,7 @@ static int snd_asihpi_cmode_get(struct snd_kcontrol *kcontrol,
 	u32 h_control = kcontrol->private_value;
 	u16 mode;
 
-	if (hpi_channel_mode_get(ss, h_control, &mode))
+	if (hpi_channel_mode_get(h_control, &mode))
 		mode = 1;
 
 	ucontrol->value.enumerated.item[0] = mode - 1;
@@ -2307,7 +2306,7 @@ static int snd_asihpi_cmode_put(struct snd_kcontrol *kcontrol,
 
 	change = 1;
 
-	hpi_handle_error(hpi_channel_mode_set(ss, h_control,
+	hpi_handle_error(hpi_channel_mode_set(h_control,
 			   ucontrol->value.enumerated.item[0] + 1));
 	return change;
 }
@@ -2319,7 +2318,7 @@ static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
 	struct snd_card *card = asihpi->card;
 	struct snd_kcontrol_new snd_control;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "channel mode");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Mode");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
 	snd_control.info = snd_asihpi_cmode_info;
 	snd_control.get = snd_asihpi_cmode_get;
@@ -2331,15 +2330,12 @@ static int __devinit snd_asihpi_cmode_add(struct snd_card_asihpi *asihpi,
 /*------------------------------------------------------------
    Sampleclock source  controls
  ------------------------------------------------------------*/
-
-static char *sampleclock_sources[MAX_CLOCKSOURCES] =
-    { "N/A", "local PLL", "AES/EBU sync", "word external", "word header",
-	  "SMPTE", "AES/EBU in1", "auto", "network", "invalid",
-	  "prev module",
-	  "AES/EBU in2", "AES/EBU in3", "AES/EBU in4", "AES/EBU in5",
-	  "AES/EBU in6", "AES/EBU in7", "AES/EBU in8"};
-
-
+static char *sampleclock_sources[MAX_CLOCKSOURCES] = {
+	"N/A", "Local PLL", "Digital Sync", "Word External", "Word Header",
+	"SMPTE", "Digital1", "Auto", "Network", "Invalid",
+	"Prev Module",
+	"Digital2", "Digital3", "Digital4", "Digital5",
+	"Digital6", "Digital7", "Digital8"};
 
 static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
@@ -2371,11 +2367,11 @@ static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,
 	int i;
 
 	ucontrol->value.enumerated.item[0] = 0;
-	if (hpi_sample_clock_get_source(ss, h_control, &source))
+	if (hpi_sample_clock_get_source(h_control, &source))
 		source = 0;
 
 	if (source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
-		if (hpi_sample_clock_get_source_index(ss, h_control, &srcindex))
+		if (hpi_sample_clock_get_source_index(h_control, &srcindex))
 			srcindex = 0;
 
 	for (i = 0; i < clkcache->count; i++)
@@ -2402,11 +2398,11 @@ static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol,
 	if (item >= clkcache->count)
 		item = clkcache->count-1;
 
-	hpi_handle_error(hpi_sample_clock_set_source(ss,
+	hpi_handle_error(hpi_sample_clock_set_source(
 				h_control, clkcache->s[item].source));
 
 	if (clkcache->s[item].source == HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT)
-		hpi_handle_error(hpi_sample_clock_set_source_index(ss,
+		hpi_handle_error(hpi_sample_clock_set_source_index(
 				h_control, clkcache->s[item].index));
 	return change;
 }
@@ -2434,7 +2430,7 @@ static int snd_asihpi_clklocal_get(struct snd_kcontrol *kcontrol,
 	u32 rate;
 	u16 e;
 
-	e = hpi_sample_clock_get_local_rate(ss, h_control, &rate);
+	e = hpi_sample_clock_get_local_rate(h_control, &rate);
 	if (!e)
 		ucontrol->value.integer.value[0] = rate;
 	else
@@ -2452,7 +2448,7 @@ static int snd_asihpi_clklocal_put(struct snd_kcontrol *kcontrol,
 	   asihpi->mixer_clkrate[addr][1] != right;
 	 */
 	change = 1;
-	hpi_handle_error(hpi_sample_clock_set_local_rate(ss, h_control,
+	hpi_handle_error(hpi_sample_clock_set_local_rate(h_control,
 				      ucontrol->value.integer.value[0]));
 	return change;
 }
@@ -2476,7 +2472,7 @@ static int snd_asihpi_clkrate_get(struct snd_kcontrol *kcontrol,
 	u32 rate;
 	u16 e;
 
-	e = hpi_sample_clock_get_sample_rate(ss, h_control, &rate);
+	e = hpi_sample_clock_get_sample_rate(h_control, &rate);
 	if (!e)
 		ucontrol->value.integer.value[0] = rate;
 	else
@@ -2501,7 +2497,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 	clkcache->has_local = 0;
 
 	for (i = 0; i <= HPI_SAMPLECLOCK_SOURCE_LAST; i++) {
-		if  (hpi_sample_clock_query_source(ss, hSC,
+		if  (hpi_sample_clock_query_source(hSC,
 				i, &source))
 			break;
 		clkcache->s[i].source = source;
@@ -2515,7 +2511,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 	if (has_aes_in)
 		/* already will have picked up index 0 above */
 		for (j = 1; j < 8; j++) {
-			if (hpi_sample_clock_query_source_index(ss, hSC,
+			if (hpi_sample_clock_query_source_index(hSC,
 				j, HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT,
 				&source))
 				break;
@@ -2528,7 +2524,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 		}
 	clkcache->count = i;
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "source");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Source");
 	snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
 	snd_control.info = snd_asihpi_clksrc_info;
 	snd_control.get = snd_asihpi_clksrc_get;
@@ -2538,7 +2534,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 
 
 	if (clkcache->has_local) {
-		asihpi_ctl_init(&snd_control, hpi_ctl, "local_rate");
+		asihpi_ctl_init(&snd_control, hpi_ctl, "Localrate");
 		snd_control.access = SNDRV_CTL_ELEM_ACCESS_READWRITE ;
 		snd_control.info = snd_asihpi_clklocal_info;
 		snd_control.get = snd_asihpi_clklocal_get;
@@ -2549,7 +2545,7 @@ static int __devinit snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 			return -EINVAL;
 	}
 
-	asihpi_ctl_init(&snd_control, hpi_ctl, "rate");
+	asihpi_ctl_init(&snd_control, hpi_ctl, "Rate");
 	snd_control.access =
 	    SNDRV_CTL_ELEM_ACCESS_VOLATILE | SNDRV_CTL_ELEM_ACCESS_READ;
 	snd_control.info = snd_asihpi_clkrate_info;
@@ -2571,10 +2567,10 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 
 	if (snd_BUG_ON(!asihpi))
 		return -EINVAL;
-	strcpy(card->mixername, "asihpi mixer");
+	strcpy(card->mixername, "Asihpi Mixer");
 
 	err =
-	    hpi_mixer_open(ss, asihpi->adapter_index,
+	    hpi_mixer_open(asihpi->adapter_index,
 			  &asihpi->h_mixer);
 	hpi_handle_error(err);
 	if (err)
@@ -2585,7 +2581,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 
 	for (idx = 0; idx < 2000; idx++) {
 		err = hpi_mixer_get_control_by_index(
-				ss, asihpi->h_mixer,
+				asihpi->h_mixer,
 				idx,
 				&hpi_ctl.src_node_type,
 				&hpi_ctl.src_node_index,
@@ -2597,7 +2593,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 			if (err == HPI_ERROR_CONTROL_DISABLED) {
 				if (mixer_dump)
 					snd_printk(KERN_INFO
-						   "disabled HPI control(%d)\n",
+						   "Disabled HPI Control(%d)\n",
 						   idx);
 				continue;
 			} else
@@ -2662,7 +2658,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 		default:
 			if (mixer_dump)
 				snd_printk(KERN_INFO
-					"untranslated HPI control"
+					"Untranslated HPI Control"
 					"(%d) %d %d %d %d %d\n",
 					idx,
 					hpi_ctl.control_type,
@@ -2712,14 +2708,14 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
 		version & 0x7,
 		((version >> 13) * 100) + ((version >> 7) & 0x3f));
 
-	err = hpi_mixer_get_control(ss, asihpi->h_mixer,
+	err = hpi_mixer_get_control(asihpi->h_mixer,
 				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
 				  HPI_CONTROL_SAMPLECLOCK, &h_control);
 
 	if (!err) {
-		err = hpi_sample_clock_get_sample_rate(ss,
+		err = hpi_sample_clock_get_sample_rate(
 					h_control, &rate);
-		err += hpi_sample_clock_get_source(ss, h_control, &source);
+		err += hpi_sample_clock_get_source(h_control, &source);
 
 		if (!err)
 			snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n",
@@ -2841,15 +2837,17 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
 		if (err < 0)
 			return err;
 		snd_printk(KERN_WARNING
-			"**** WARNING **** adapter index %d->ALSA index %d\n",
+			"**** WARNING **** Adapter index %d->ALSA index %d\n",
 			hpi_card->index, card->number);
 	}
 
+	snd_card_set_dev(card, &pci_dev->dev);
+
 	asihpi = (struct snd_card_asihpi *) card->private_data;
 	asihpi->card = card;
-	asihpi->pci = hpi_card->pci;
+	asihpi->pci = pci_dev;
 	asihpi->adapter_index = hpi_card->index;
-	hpi_handle_error(hpi_adapter_get_info(ss,
+	hpi_handle_error(hpi_adapter_get_info(
 				 asihpi->adapter_index,
 				 &asihpi->num_outstreams,
 				 &asihpi->num_instreams,
@@ -2859,7 +2857,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
 	version = asihpi->version;
 	snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d "
 			"num_instreams=%d S/N=%d\n"
-			"hw version %c%d DSP code version %03d\n",
+			"Hw Version %c%d DSP code version %03d\n",
 			asihpi->type, asihpi->adapter_index,
 			asihpi->num_outstreams,
 			asihpi->num_instreams, asihpi->serial_number,
@@ -2871,33 +2869,33 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
 	if (pcm_substreams < asihpi->num_instreams)
 		pcm_substreams = asihpi->num_instreams;
 
-	err = hpi_adapter_get_property(ss, asihpi->adapter_index,
+	err = hpi_adapter_get_property(asihpi->adapter_index,
 		HPI_ADAPTER_PROPERTY_CAPS1,
 		NULL, &asihpi->support_grouping);
 	if (err)
 		asihpi->support_grouping = 0;
 
-	err = hpi_adapter_get_property(ss, asihpi->adapter_index,
+	err = hpi_adapter_get_property(asihpi->adapter_index,
 		HPI_ADAPTER_PROPERTY_CAPS2,
 		&asihpi->support_mrx, NULL);
 	if (err)
 		asihpi->support_mrx = 0;
 
-	err = hpi_adapter_get_property(ss, asihpi->adapter_index,
+	err = hpi_adapter_get_property(asihpi->adapter_index,
 		HPI_ADAPTER_PROPERTY_INTERVAL,
 		NULL, &asihpi->update_interval_frames);
 	if (err)
 		asihpi->update_interval_frames = 512;
 
-	hpi_handle_error(hpi_instream_open(ss, asihpi->adapter_index,
+	hpi_handle_error(hpi_instream_open(asihpi->adapter_index,
 			     0, &h_stream));
 
-	err = hpi_instream_host_buffer_free(ss, h_stream);
+	err = hpi_instream_host_buffer_free(h_stream);
 	asihpi->support_mmap = (!err);
 
-	hpi_handle_error(hpi_instream_close(ss, h_stream));
+	hpi_handle_error(hpi_instream_close(h_stream));
 
-	err = hpi_adapter_get_property(ss, asihpi->adapter_index,
+	err = hpi_adapter_get_property(asihpi->adapter_index,
 		HPI_ADAPTER_PROPERTY_CURCHANNELS,
 		&asihpi->in_max_chans, &asihpi->out_max_chans);
 	if (err) {
@@ -2923,13 +2921,13 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
 		goto __nodev;
 	}
 
-	err = hpi_mixer_get_control(ss, asihpi->h_mixer,
+	err = hpi_mixer_get_control(asihpi->h_mixer,
 				  HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0,
 				  HPI_CONTROL_SAMPLECLOCK, &h_control);
 
 	if (!err)
 		err = hpi_sample_clock_set_local_rate(
-			ss, h_control, adapter_fs);
+			h_control, adapter_fs);
 
 	snd_asihpi_proc_init(asihpi);
 
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h
index 23399d0..6fc025c 100644
--- a/sound/pci/asihpi/hpi.h
+++ b/sound/pci/asihpi/hpi.h
@@ -24,17 +24,10 @@
 
  The HPI is a low-level hardware abstraction layer to all
  AudioScience digital audio adapters
-*/
-/*
- You must define one operating system that the HPI is to be compiled under
- HPI_OS_WIN32_USER   32bit Windows
- HPI_OS_DSP_C6000    DSP TI C6000  (automatically set)
- HPI_OS_WDM          Windows WDM kernel driver
- HPI_OS_LINUX        Linux userspace
- HPI_OS_LINUX_KERNEL Linux kernel (automatically set)
 
 (C) Copyright AudioScience Inc. 1998-2010
-******************************************************************************/
+*/
+
 #ifndef _HPI_H_
 #define _HPI_H_
 /* HPI Version
@@ -50,20 +43,20 @@ i.e 3.05.02 is a development version
 #define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
 
 /* Use single digits for versions less that 10 to avoid octal. */
-#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 4, 1)
-#define HPI_VER_STRING "4.04.01"
+#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 6, 0)
+#define HPI_VER_STRING "4.06.00"
 
 /* Library version as documented in hpi-api-versions.txt */
 #define HPI_LIB_VER  HPI_VERSION_CONSTRUCTOR(9, 0, 0)
 
 #include <linux/types.h>
-#define HPI_EXCLUDE_DEPRECATED
+#define HPI_BUILD_EXCLUDE_DEPRECATED
+#define HPI_BUILD_KERNEL_MODE
 
 /******************************************************************************/
-/******************************************************************************/
 /********       HPI API DEFINITIONS                                       *****/
 /******************************************************************************/
-/******************************************************************************/
+
 /*******************************************/
 /**  Audio format types
 \ingroup stream
@@ -174,7 +167,6 @@ The range is +1.0 to -1.0, which corresponds to digital fullscale.
 	HPI_FORMAT_UNDEFINED = 0xffff
 };
 
-/******************************************* in/out Stream states */
 /*******************************************/
 /** Stream States
 \ingroup stream
@@ -194,7 +186,7 @@ enum HPI_STREAM_STATES {
 		cards to be ready. */
 	HPI_STATE_WAIT = 6
 };
-/******************************************* mixer source node types */
+/*******************************************/
 /** Source node types
 \ingroup mixer
 */
@@ -224,7 +216,7 @@ enum HPI_SOURCENODES {
 		/* AX6 max sourcenode types = 15 */
 };
 
-/******************************************* mixer dest node types */
+/*******************************************/
 /** Destination node types
 \ingroup mixer
 */
@@ -262,11 +254,11 @@ enum HPI_CONTROLS {
 	HPI_CONTROL_MUTE = 4,	/*mute control - not used at present. */
 	HPI_CONTROL_MULTIPLEXER = 5,	/**< multiplexer control. */
 
-	HPI_CONTROL_AESEBU_TRANSMITTER = 6,	/**< AES/EBU transmitter control. */
-	HPI_CONTROL_AESEBUTX = HPI_CONTROL_AESEBU_TRANSMITTER,
+	HPI_CONTROL_AESEBU_TRANSMITTER = 6, /**< AES/EBU transmitter control */
+	HPI_CONTROL_AESEBUTX = 6,	/* HPI_CONTROL_AESEBU_TRANSMITTER */
 
 	HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */
-	HPI_CONTROL_AESEBURX = HPI_CONTROL_AESEBU_RECEIVER,
+	HPI_CONTROL_AESEBURX = 7,	/* HPI_CONTROL_AESEBU_RECEIVER */
 
 	HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */
 	HPI_CONTROL_TUNER = 9,	/**< tuner control. */
@@ -281,7 +273,7 @@ enum HPI_CONTROLS {
 	HPI_CONTROL_SAMPLECLOCK = 17,	/**< sample clock control. */
 	HPI_CONTROL_MICROPHONE = 18,	/**< microphone control. */
 	HPI_CONTROL_PARAMETRIC_EQ = 19,	/**< parametric EQ control. */
-	HPI_CONTROL_EQUALIZER = HPI_CONTROL_PARAMETRIC_EQ,
+	HPI_CONTROL_EQUALIZER = 19,	/*HPI_CONTROL_PARAMETRIC_EQ */
 
 	HPI_CONTROL_COMPANDER = 20,	/**< compander control. */
 	HPI_CONTROL_COBRANET = 21,	/**< cobranet control. */
@@ -296,10 +288,7 @@ enum HPI_CONTROLS {
 /* WARNING types 256 or greater impact bit packing in all AX6 DSP code */
 };
 
-/* Shorthand names that match attribute names */
-
-/******************************************* ADAPTER ATTRIBUTES ****/
-
+/*******************************************/
 /** Adapter properties
 These are used in HPI_AdapterSetProperty() and HPI_AdapterGetProperty()
 \ingroup adapter
@@ -330,12 +319,21 @@ by the driver and is not passed on to the DSP at all.
 Indicates the state of the adapter's SSX2 setting. This setting is stored in
 non-volatile memory on the adapter. A typical call sequence would be to use
 HPI_ADAPTER_PROPERTY_SSX2_SETTING to set SSX2 on the adapter and then to reload
-the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during startup
-and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2 to enable
-SSX2 stream mapping within the kernel level of the driver.
+the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during
+startup and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2
+to enable SSX2 stream mapping within the kernel level of the driver.
 */
 	HPI_ADAPTER_PROPERTY_SSX2_SETTING = 4,
 
+/** Enables/disables PCI(e) IRQ.
+A setting of 0 indicates that no interrupts are being generated. A DSP boot
+this property is set to 0. Setting to a non-zero value specifies the number
+of frames of audio that should be processed between interrupts. This property
+should be set to multiple of the mixer interval as read back from the
+HPI_ADAPTER_PROPERTY_INTERVAL property.
+*/
+	HPI_ADAPTER_PROPERTY_IRQ_RATE = 5,
+
 /** Base number for readonly properties */
 	HPI_ADAPTER_PROPERTY_READONLYBASE = 256,
 
@@ -440,21 +438,30 @@ return value is true (1) or false (0). If the current adapter
 mode is MONO SSX2 is disabled, even though this property will
 return true.
 */
-	HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271
+	HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271,
+/** Readonly supports PCI(e) IRQ.
+Indicates that the adapter in it's current mode supports interrupts
+across the host bus. Note, this does not imply that interrupts are
+enabled. Instead it indicates that they can be enabled.
+*/
+	HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ = 272
 };
 
 /** Adapter mode commands
 
-Used in wQueryOrSet field of HPI_AdapterSetModeEx().
+Used in wQueryOrSet parameter of HPI_AdapterSetModeEx().
 \ingroup adapter
 */
 enum HPI_ADAPTER_MODE_CMDS {
+	/** Set the mode to the given parameter */
 	HPI_ADAPTER_MODE_SET = 0,
+	/** Return 0 or error depending whether mode is valid,
+	but don't set the mode */
 	HPI_ADAPTER_MODE_QUERY = 1
 };
 
 /** Adapter Modes
-	These are used by HPI_AdapterSetModeEx()
+ These are used by HPI_AdapterSetModeEx()
 
 \warning - more than 16 possible modes breaks
 a bitmask in the Windows WAVE DLL
@@ -629,10 +636,13 @@ enum HPI_MIXER_STORE_COMMAND {
 	HPI_MIXER_STORE_SAVE_SINGLE = 6
 };
 
-/************************************* CONTROL ATTRIBUTE VALUES ****/
+/****************************/
+/* CONTROL ATTRIBUTE VALUES */
+/****************************/
+
 /** Used by mixer plugin enable functions
 
-E.g. HPI_ParametricEQ_SetState()
+E.g. HPI_ParametricEq_SetState()
 \ingroup mixer
 */
 enum HPI_SWITCH_STATES {
@@ -641,6 +651,7 @@ enum HPI_SWITCH_STATES {
 };
 
 /* Volume control special gain values */
+
 /** volumes units are 100ths of a dB
 \ingroup volume
 */
@@ -650,6 +661,11 @@ enum HPI_SWITCH_STATES {
 */
 #define HPI_GAIN_OFF                    (-100 * HPI_UNITS_PER_dB)
 
+/** channel mask specifying all channels
+\ingroup volume
+*/
+#define HPI_BITMASK_ALL_CHANNELS        (0xFFFFFFFF)
+
 /** value returned for no signal
 \ingroup meter
 */
@@ -667,7 +683,7 @@ enum HPI_VOLUME_AUTOFADES {
 
 /** The physical encoding format of the AESEBU I/O.
 
-Used in HPI_AESEBU_Transmitter_SetFormat(), HPI_AESEBU_Receiver_SetFormat()
+Used in HPI_Aesebu_Transmitter_SetFormat(), HPI_Aesebu_Receiver_SetFormat()
 along with related Get and Query functions
 \ingroup aestx
 */
@@ -680,7 +696,7 @@ enum HPI_AESEBU_FORMATS {
 
 /** AES/EBU error status bits
 
-Returned by HPI_AESEBU_Receiver_GetErrorStatus()
+Returned by HPI_Aesebu_Receiver_GetErrorStatus()
 \ingroup aesrx
 */
 enum HPI_AESEBU_ERRORS {
@@ -767,14 +783,6 @@ enum HPI_TUNER_MODE_VALUES {
 	HPI_TUNER_MODE_RDS_RBDS = 2 /**<  RDS - RBDS mode */
 };
 
-/** Tuner Level settings
-\ingroup tuner
-*/
-enum HPI_TUNER_LEVEL {
-	HPI_TUNER_LEVEL_AVERAGE = 0,
-	HPI_TUNER_LEVEL_RAW = 1
-};
-
 /** Tuner Status Bits
 
 These bitfield values are returned by a call to HPI_Tuner_GetStatus().
@@ -783,13 +791,13 @@ Multiple fields are returned from a single call.
 */
 enum HPI_TUNER_STATUS_BITS {
 	HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001,	/**< video color is present. */
-	HPI_TUNER_VIDEO_IS_60HZ = 0x0020,	/**< 60 hz video detected. */
-	HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040,	/**< video HSYNC is missing. */
-	HPI_TUNER_VIDEO_STATUS_VALID = 0x0100,	/**< video status is valid. */
-	HPI_TUNER_PLL_LOCKED = 0x1000,		/**< the tuner's PLL is locked. */
-	HPI_TUNER_FM_STEREO = 0x2000,		/**< tuner reports back FM stereo. */
-	HPI_TUNER_DIGITAL = 0x0200,		/**< tuner reports digital programming. */
-	HPI_TUNER_MULTIPROGRAM = 0x0400		/**< tuner reports multiple programs. */
+	HPI_TUNER_VIDEO_IS_60HZ = 0x0020, /**< 60 hz video detected. */
+	HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040, /**< video HSYNC is missing. */
+	HPI_TUNER_VIDEO_STATUS_VALID = 0x0100, /**< video status is valid. */
+	HPI_TUNER_DIGITAL = 0x0200, /**< tuner reports digital programming. */
+	HPI_TUNER_MULTIPROGRAM = 0x0400, /**< tuner reports multiple programs. */
+	HPI_TUNER_PLL_LOCKED = 0x1000, /**< the tuner's PLL is locked. */
+	HPI_TUNER_FM_STEREO = 0x2000 /**< tuner reports back FM stereo. */
 };
 
 /** Channel Modes
@@ -839,7 +847,7 @@ enum HPI_SAMPLECLOCK_SOURCES {
 	HPI_SAMPLECLOCK_SOURCE_LAST = 10
 };
 
-/** Equalizer filter types. Used by HPI_ParametricEQ_SetBand()
+/** Equalizer filter types. Used by HPI_ParametricEq_SetBand()
 \ingroup parmeq
 */
 enum HPI_FILTER_TYPE {
@@ -882,7 +890,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_INVALID_OBJ = 101,
 	/** Function does not exist. */
 	HPI_ERROR_INVALID_FUNC = 102,
-	/** The specified object (adapter/Stream) does not exist. */
+	/** The specified object does not exist. */
 	HPI_ERROR_INVALID_OBJ_INDEX = 103,
 	/** Trying to access an object that has not been opened yet. */
 	HPI_ERROR_OBJ_NOT_OPEN = 104,
@@ -890,8 +898,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_OBJ_ALREADY_OPEN = 105,
 	/** PCI, ISA resource not valid. */
 	HPI_ERROR_INVALID_RESOURCE = 106,
-	/** GetInfo call from SubSysFindAdapters failed. */
-	HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO = 107,
+	/* HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO= 107 */
 	/** Default response was never updated with actual error code. */
 	HPI_ERROR_INVALID_RESPONSE = 108,
 	/** wSize field of response was not updated,
@@ -899,38 +906,44 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_PROCESSING_MESSAGE = 109,
 	/** The network did not respond in a timely manner. */
 	HPI_ERROR_NETWORK_TIMEOUT = 110,
-	/** An HPI handle is invalid (uninitialised?). */
+	/* An HPI handle is invalid (uninitialised?). */
 	HPI_ERROR_INVALID_HANDLE = 111,
 	/** A function or attribute has not been implemented yet. */
 	HPI_ERROR_UNIMPLEMENTED = 112,
-	/** There are too many clients attempting to access a network resource. */
+	/** There are too many clients attempting
+	    to access a network resource. */
 	HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113,
-	/** Response buffer passed to HPI_Message was smaller than returned response */
+	/** Response buffer passed to HPI_Message
+	    was smaller than returned response.
+	    wSpecificError field of hpi response contains the required size.
+	*/
 	HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114,
 	/** The returned response did not match the sent message */
 	HPI_ERROR_RESPONSE_MISMATCH = 115,
+	/** A control setting that should have been cached was not. */
+	HPI_ERROR_CONTROL_CACHING = 116,
+	/** A message buffer in the path to the adapter was smaller
+	    than the message size.
+	    wSpecificError field of hpi response contains the actual size.
+	*/
+	HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL = 117,
 
-	/** Too many adapters.*/
-	HPI_ERROR_TOO_MANY_ADAPTERS = 200,
+	/* HPI_ERROR_TOO_MANY_ADAPTERS= 200 */
 	/** Bad adpater. */
 	HPI_ERROR_BAD_ADAPTER = 201,
 	/** Adapter number out of range or not set properly. */
 	HPI_ERROR_BAD_ADAPTER_NUMBER = 202,
 	/** 2 adapters with the same adapter number. */
-	HPI_DUPLICATE_ADAPTER_NUMBER = 203,
-	/** DSP code failed to bootload. */
+	HPI_ERROR_DUPLICATE_ADAPTER_NUMBER = 203,
+	/** DSP code failed to bootload. (unused?) */
 	HPI_ERROR_DSP_BOOTLOAD = 204,
-	/** Adapter failed DSP code self test. */
-	HPI_ERROR_DSP_SELFTEST = 205,
 	/** Couldn't find or open the DSP code file. */
 	HPI_ERROR_DSP_FILE_NOT_FOUND = 206,
 	/** Internal DSP hardware error. */
 	HPI_ERROR_DSP_HARDWARE = 207,
-	/** Could not allocate memory in DOS. */
-	HPI_ERROR_DOS_MEMORY_ALLOC = 208,
 	/** Could not allocate memory */
 	HPI_ERROR_MEMORY_ALLOC = 208,
-	/** Failed to correctly load/config PLD .*/
+	/** Failed to correctly load/config PLD. (unused) */
 	HPI_ERROR_PLD_LOAD = 209,
 	/** Unexpected end of file, block length too big etc. */
 	HPI_ERROR_DSP_FILE_FORMAT = 210,
@@ -939,8 +952,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211,
 	/** First DSP code section header not found in DSP file. */
 	HPI_ERROR_DSP_FILE_NO_HEADER = 212,
-	/** File read operation on DSP code file failed. */
-	HPI_ERROR_DSP_FILE_READ_ERROR = 213,
+	/* HPI_ERROR_DSP_FILE_READ_ERROR= 213, */
 	/** DSP code for adapter family not found. */
 	HPI_ERROR_DSP_SECTION_NOT_FOUND = 214,
 	/** Other OS specific error opening DSP file. */
@@ -950,23 +962,21 @@ enum HPI_ERROR_CODES {
 	/** DSP code section header had size == 0. */
 	HPI_ERROR_DSP_FILE_NULL_HEADER = 217,
 
-	/** Base number for flash errors. */
-	HPI_ERROR_FLASH = 220,
+	/* HPI_ERROR_FLASH = 220, */
 
 	/** Flash has bad checksum */
-	HPI_ERROR_BAD_CHECKSUM = (HPI_ERROR_FLASH + 1),
-	HPI_ERROR_BAD_SEQUENCE = (HPI_ERROR_FLASH + 2),
-	HPI_ERROR_FLASH_ERASE = (HPI_ERROR_FLASH + 3),
-	HPI_ERROR_FLASH_PROGRAM = (HPI_ERROR_FLASH + 4),
-	HPI_ERROR_FLASH_VERIFY = (HPI_ERROR_FLASH + 5),
-	HPI_ERROR_FLASH_TYPE = (HPI_ERROR_FLASH + 6),
-	HPI_ERROR_FLASH_START = (HPI_ERROR_FLASH + 7),
+	HPI_ERROR_BAD_CHECKSUM = 221,
+	HPI_ERROR_BAD_SEQUENCE = 222,
+	HPI_ERROR_FLASH_ERASE = 223,
+	HPI_ERROR_FLASH_PROGRAM = 224,
+	HPI_ERROR_FLASH_VERIFY = 225,
+	HPI_ERROR_FLASH_TYPE = 226,
+	HPI_ERROR_FLASH_START = 227,
 
 	/** Reserved for OEMs. */
 	HPI_ERROR_RESERVED_1 = 290,
 
-	/** Stream does not exist. */
-	HPI_ERROR_INVALID_STREAM = 300,
+	/* HPI_ERROR_INVALID_STREAM = 300 use HPI_ERROR_INVALID_OBJ_INDEX */
 	/** Invalid compression format. */
 	HPI_ERROR_INVALID_FORMAT = 301,
 	/** Invalid format samplerate */
@@ -977,21 +987,19 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_INVALID_BITRATE = 304,
 	/** Invalid datasize used for stream read/write. */
 	HPI_ERROR_INVALID_DATASIZE = 305,
-	/** Stream buffer is full during stream write. */
-	HPI_ERROR_BUFFER_FULL = 306,
-	/** Stream buffer is empty during stream read. */
-	HPI_ERROR_BUFFER_EMPTY = 307,
-	/** Invalid datasize used for stream read/write. */
-	HPI_ERROR_INVALID_DATA_TRANSFER = 308,
+	/* HPI_ERROR_BUFFER_FULL = 306 use HPI_ERROR_INVALID_DATASIZE */
+	/* HPI_ERROR_BUFFER_EMPTY = 307 use HPI_ERROR_INVALID_DATASIZE */
+	/** Null data pointer used for stream read/write. */
+	HPI_ERROR_INVALID_DATA_POINTER = 308,
 	/** Packet ordering error for stream read/write. */
 	HPI_ERROR_INVALID_PACKET_ORDER = 309,
 
 	/** Object can't do requested operation in its current
-	state, eg set format, change rec mux state while recording.*/
+	    state, eg set format, change rec mux state while recording.*/
 	HPI_ERROR_INVALID_OPERATION = 310,
 
-	/** Where an SRG is shared amongst streams, an incompatible samplerate is one
-	that is different to any currently playing or recording stream. */
+	/** Where a SRG is shared amongst streams, an incompatible samplerate
+	    is one that is different to any currently active stream. */
 	HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311,
 	/** Adapter mode is illegal.*/
 	HPI_ERROR_BAD_ADAPTER_MODE = 312,
@@ -1004,6 +1012,8 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_NO_INTERADAPTER_GROUPS = 314,
 	/** Streams on different DSPs cannot be grouped. */
 	HPI_ERROR_NO_INTERDSP_GROUPS = 315,
+	/** Stream wait cancelled before threshold reached. */
+	HPI_ERROR_WAIT_CANCELLED = 316,
 
 	/** Invalid mixer node for this adapter. */
 	HPI_ERROR_INVALID_NODE = 400,
@@ -1017,6 +1027,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_CONTROL_DISABLED = 404,
 	/** I2C transaction failed due to a missing ACK. */
 	HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405,
+	HPI_ERROR_I2C_MISSING_ACK = 405,
 	/** Control is busy, or coming out of
 	reset and cannot be accessed at this time. */
 	HPI_ERROR_CONTROL_NOT_READY = 407,
@@ -1027,7 +1038,6 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_NVMEM_FAIL = 452,
 
 	/** I2C */
-	HPI_ERROR_I2C_MISSING_ACK = HPI_ERROR_CONTROL_I2C_MISSING_ACK,
 	HPI_ERROR_I2C_BAD_ADR = 460,
 
 	/** Entity errors */
@@ -1035,6 +1045,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_ENTITY_ITEM_COUNT = 471,
 	HPI_ERROR_ENTITY_TYPE_INVALID = 472,
 	HPI_ERROR_ENTITY_ROLE_INVALID = 473,
+	HPI_ERROR_ENTITY_SIZE_MISMATCH = 474,
 
 	/* AES18 specific errors were 500..507 */
 
@@ -1044,11 +1055,18 @@ enum HPI_ERROR_CODES {
 	/** hpioct32.c can't obtain mutex */
 	HPI_ERROR_MUTEX_TIMEOUT = 700,
 
-	/** errors from HPI backends have values >= this */
+	/** Backend errors used to be greater than this.
+	    \deprecated Now, all backends return only errors defined here in hpi.h
+	*/
 	HPI_ERROR_BACKEND_BASE = 900,
 
-	/** indicates a cached u16 value is invalid. */
-	HPI_ERROR_ILLEGAL_CACHE_VALUE = 0xffff
+	/** Communication with DSP failed */
+	HPI_ERROR_DSP_COMMUNICATION = 900
+		/* Note that the dsp communication error is set to this value so that
+		   it remains compatible with any software that expects such errors
+		   to be backend errors i.e. >= 900.
+		   Do not define any new error codes with values > 900.
+		 */
 };
 
 /** \defgroup maximums HPI maximum values
@@ -1075,7 +1093,7 @@ enum HPI_ERROR_CODES {
 
 /**\}*/
 
-/* ////////////////////////////////////////////////////////////////////// */
+/**************/
 /* STRUCTURES */
 #ifndef DISABLE_PRAGMA_PACK1
 #pragma pack(push, 1)
@@ -1092,7 +1110,7 @@ struct hpi_format {
 				/**< Stereo/JointStereo/Mono */
 	u16 mode_legacy;
 				/**< Legacy ancillary mode or idle bit  */
-	u16 unused;	      /**< unused */
+	u16 unused;	      /**< Unused */
 	u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
 	u16 format;   /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */
 };
@@ -1106,930 +1124,594 @@ struct hpi_anc_frame {
 */
 struct hpi_async_event {
 	u16 event_type;	/**< type of event. \sa async_event  */
-	u16 sequence;  /**< sequence number, allows lost event detection */
-	u32 state;    /**< new state */
-	u32 h_object;	 /**< handle to the object returning the event. */
+	u16 sequence; /**< Sequence number, allows lost event detection */
+	u32 state; /**< New state */
+	u32 h_object; /**< handle to the object returning the event. */
 	union {
 		struct {
 			u16 index; /**< GPIO bit index. */
 		} gpio;
 		struct {
 			u16 node_index;	/**< what node is the control on ? */
-			u16 node_type;	/**< what type of node is the control on ? */
+			u16 node_type; /**< what type of node is the control on ? */
 		} control;
 	} u;
 };
 
-/*/////////////////////////////////////////////////////////////////////////// */
-/* Public HPI Entity related definitions                                     */
-
-struct hpi_entity;
-
-enum e_entity_type {
-	entity_type_null,
-	entity_type_sequence,	/* sequence of potentially heterogeneous TLV entities */
-
-	entity_type_reference,	/* refers to a TLV entity or NULL */
-
-	entity_type_int,	/* 32 bit */
-	entity_type_float,	/* ieee754 binary 32 bit encoding */
-	entity_type_double,
-
-	entity_type_cstring,
-	entity_type_octet,
-	entity_type_ip4_address,
-	entity_type_ip6_address,
-	entity_type_mac_address,
-
-	LAST_ENTITY_TYPE
-};
-
-enum e_entity_role {
-	entity_role_null,
-	entity_role_value,
-	entity_role_classname,
-
-	entity_role_units,
-	entity_role_flags,
-	entity_role_range,
-
-	entity_role_mapping,
-	entity_role_enum,
-
-	entity_role_instance_of,
-	entity_role_depends_on,
-	entity_role_member_of_group,
-	entity_role_value_constraint,
-	entity_role_parameter_port,
-
-	entity_role_block,
-	entity_role_node_group,
-	entity_role_audio_port,
-	entity_role_clock_port,
-	LAST_ENTITY_ROLE
-};
-
 /* skip host side function declarations for
    DSP compile and documentation extraction */
 
-struct hpi_hsubsys {
-	int not_really_used;
-};
-
 #ifndef DISABLE_PRAGMA_PACK1
 #pragma pack(pop)
 #endif
 
-/*////////////////////////////////////////////////////////////////////////// */
+/*****************/
 /* HPI FUNCTIONS */
+/*****************/
 
-/*/////////////////////////// */
-/* DATA and FORMAT and STREAM */
-
+/* Stream */
 u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF,
 	u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size);
 
-/*/////////// */
-/* SUB SYSTEM */
-struct hpi_hsubsys *hpi_subsys_create(void
-	);
-
-void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys);
-
-u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys,
-	u32 *pversion);
-
-u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 *pversion_ex);
-
-u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion,
-	u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length);
-
-u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys,
-	u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length);
-
-u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys,
-	int *pn_num_adapters);
-
-u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator,
-	u32 *padapter_index, u16 *pw_adapter_type);
-
-u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass);
+/*************/
+/* SubSystem */
+/*************/
 
-u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys,
-	const char *sz_interface);
+u16 hpi_subsys_get_version_ex(u32 *pversion_ex);
 
-/*///////// */
-/* ADAPTER */
+u16 hpi_subsys_get_num_adapters(int *pn_num_adapters);
 
-u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index);
+u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index,
+	u16 *pw_adapter_type);
 
-u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index);
+/***********/
+/* Adapter */
+/***********/
 
-u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams,
-	u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type);
+u16 hpi_adapter_open(u16 adapter_index);
 
-u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 module_index, u16 *pw_num_outputs,
-	u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number,
-	u16 *pw_module_type, u32 *ph_module);
+u16 hpi_adapter_close(u16 adapter_index);
 
-u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 adapter_mode);
+u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams,
+	u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number,
+	u16 *pw_adapter_type);
 
-u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 adapter_mode, u16 query_or_set);
-
-u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 *padapter_mode);
-
-u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *assert_present, char *psz_assert,
-	u16 *pw_line_number);
-
-u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *assert_present, char *psz_assert,
-	u32 *pline_number, u16 *pw_assert_on_dsp);
-
-u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 assert_id);
-
-u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 capability, u32 key);
-
-u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index);
-
-u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 dsp_address, char *p_bytes, int *count_bytes);
-
-u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 property, u16 paramter1, u16 paramter2);
-
-u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 property, u16 *pw_paramter1,
-	u16 *pw_paramter2);
-
-u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 index, u16 what_to_enumerate,
-	u16 property_index, u32 *psetting);
-
-/*////////////// */
-/* NonVol Memory */
-u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_nv_memory, u16 *pw_size_in_bytes);
-
-u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys,
-	u32 h_nv_memory, u16 index, u16 *pw_data);
-
-u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys,
-	u32 h_nv_memory, u16 index, u16 data);
-
-/*////////////// */
-/* Digital I/O */
-u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits);
-
-u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 bit_index, u16 *pw_bit_data);
-
-u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 aw_all_bit_data[4]
-	);
+u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index,
+	u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version,
+	u32 *pserial_number, u16 *pw_module_type, u32 *ph_module);
 
-u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 bit_index, u16 bit_data);
+u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode);
 
-u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 aw_all_bit_data[4]
-	);
+u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode,
+	u16 query_or_set);
 
-/**********************/
-/* Async Event Object */
-/**********************/
-u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 *ph_async);
+u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode);
 
-u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async);
+u16 hpi_adapter_get_assert2(u16 adapter_index, u16 *p_assert_count,
+	char *psz_assert, u32 *p_param1, u32 *p_param2,
+	u32 *p_dsp_string_addr, u16 *p_processor_id);
 
-u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
-	u16 maximum_events, struct hpi_async_event *p_events,
-	u16 *pw_number_returned);
+u16 hpi_adapter_test_assert(u16 adapter_index, u16 assert_id);
 
-u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys,
-	u32 h_async, u16 *pw_count);
+u16 hpi_adapter_enable_capability(u16 adapter_index, u16 capability, u32 key);
 
-u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async,
-	u16 maximum_events, struct hpi_async_event *p_events,
-	u16 *pw_number_returned);
+u16 hpi_adapter_self_test(u16 adapter_index);
 
-/*/////////// */
-/* WATCH-DOG  */
-u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_watchdog);
+u16 hpi_adapter_debug_read(u16 adapter_index, u32 dsp_address, char *p_bytes,
+	int *count_bytes);
 
-u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog,
-	u32 time_millisec);
+u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 paramter1,
+	u16 paramter2);
 
-u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog);
+u16 hpi_adapter_get_property(u16 adapter_index, u16 property,
+	u16 *pw_paramter1, u16 *pw_paramter2);
 
-/**************/
-/* OUT STREAM */
-/**************/
-u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u16 outstream_index, u32 *ph_outstream);
+u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index,
+	u16 what_to_enumerate, u16 property_index, u32 *psetting);
+/*************/
+/* OutStream */
+/*************/
+u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index,
+	u32 *ph_outstream);
 
-u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_close(u32 h_outstream);
 
-u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play,
-	u32 *psamples_played, u32 *pauxiliary_data_to_play);
+u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state,
+	u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played,
+	u32 *pauxiliary_data_to_play);
 
-u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, const u8 *pb_write_buf, u32 bytes_to_write,
-	const struct hpi_format *p_format);
+u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_write_buf,
+	u32 bytes_to_write, const struct hpi_format *p_format);
 
-u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_start(u32 h_outstream);
 
-u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_wait_start(u32 h_outstream);
 
-u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_stop(u32 h_outstream);
 
-u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_sinegen(u32 h_outstream);
 
-u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_reset(u32 h_outstream);
 
-u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_format *p_format);
+u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format);
 
-u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_format *p_format);
+u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format);
 
-u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample);
+u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample,
+	u32 punch_out_sample);
 
-u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, short velocity);
+u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity);
 
-u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u16 mode);
+u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode);
 
-u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 *pframes_available);
+u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available);
 
-u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer,
+u16 hpi_outstream_ancillary_read(u32 h_outstream,
+	struct hpi_anc_frame *p_anc_frame_buffer,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 number_of_ancillary_frames_to_read);
 
-u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 time_scaleX10000);
+u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scaleX10000);
 
-u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 size_in_bytes);
+u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes);
 
-u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_host_buffer_free(u32 h_outstream);
 
-u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 h_stream);
+u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream);
 
-u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map);
+u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map,
+	u32 *pinstream_map);
 
-u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_group_reset(u32 h_outstream);
 
-/*////////// */
-/* IN_STREAM */
-u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u16 instream_index, u32 *ph_instream);
+/************/
+/* InStream */
+/************/
+u16 hpi_instream_open(u16 adapter_index, u16 instream_index,
+	u32 *ph_instream);
 
-u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_close(u32 h_instream);
 
-u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_format *p_format);
+u16 hpi_instream_query_format(u32 h_instream,
+	const struct hpi_format *p_format);
 
-u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_format *p_format);
+u16 hpi_instream_set_format(u32 h_instream,
+	const struct hpi_format *p_format);
 
-u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream,
-	u8 *pb_read_buf, u32 bytes_to_read);
+u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_read_buf, u32 bytes_to_read);
 
-u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_start(u32 h_instream);
 
-u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream);
+u16 hpi_instream_wait_start(u32 h_instream);
 
-u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_stop(u32 h_instream);
 
-u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_reset(u32 h_instream);
 
-u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded,
-	u32 *psamples_recorded, u32 *pauxiliary_data_recorded);
+u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size,
+	u32 *pdata_recorded, u32 *psamples_recorded,
+	u32 *pauxiliary_data_recorded);
 
-u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment,
-	u16 idle_bit);
+u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame,
+	u16 mode, u16 alignment, u16 idle_bit);
 
-u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 *pframe_space);
+u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space);
 
-u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer,
+u16 hpi_instream_ancillary_write(u32 h_instream,
+	const struct hpi_anc_frame *p_anc_frame_buffer,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 number_of_ancillary_frames_to_write);
 
-u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 size_in_bytes);
+u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes);
 
-u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream);
+u16 hpi_instream_host_buffer_free(u32 h_instream);
 
-u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 h_stream);
+u16 hpi_instream_group_add(u32 h_instream, u32 h_stream);
 
-u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 *poutstream_map, u32 *pinstream_map);
+u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map,
+	u32 *pinstream_map);
 
-u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream);
+u16 hpi_instream_group_reset(u32 h_instream);
 
 /*********/
-/* MIXER */
+/* Mixer */
 /*********/
-u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_mixer);
-
-u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer);
-
-u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
-	u16 src_node_type, u16 src_node_type_index, u16 dst_node_type,
-	u16 dst_node_type_index, u16 control_type, u32 *ph_control);
-
-u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_mixer, u16 control_index, u16 *pw_src_node_type,
-	u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index,
-	u16 *pw_control_type, u32 *ph_control);
-
-u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
-	enum HPI_MIXER_STORE_COMMAND command, u16 index);
-/*************************/
-/* mixer CONTROLS                */
-/*************************/
-/*************************/
-/* volume control                */
-/*************************/
-u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB[HPI_MAX_CHANNELS]
+u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer);
+
+u16 hpi_mixer_close(u32 h_mixer);
+
+u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type,
+	u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index,
+	u16 control_type, u32 *ph_control);
+
+u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index,
+	u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type,
+	u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control);
+
+u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command,
+	u16 index);
+/************/
+/* Controls */
+/************/
+/******************/
+/* Volume control */
+/******************/
+u16 hpi_volume_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS]
 	);
 
-u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_volume_get_gain(u32 h_control,
 	short an_gain0_01dB_out[HPI_MAX_CHANNELS]
 	);
 
+u16 hpi_volume_set_mute(u32 h_control, u32 mute);
+
+u16 hpi_volume_get_mute(u32 h_control, u32 *mute);
+
 #define hpi_volume_get_range hpi_volume_query_range
-u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB);
+u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB,
+	short *max_gain_01dB, short *step_gain_01dB);
 
-u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_volume, u32 *p_channels);
+u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels);
 
-u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_volume_auto_fade(u32 h_control,
 	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms);
 
-u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS],
-	u32 duration_ms, u16 profile);
+u16 hpi_volume_auto_fade_profile(u32 h_control,
+	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms,
+	u16 profile);
 
-/*************************/
-/* level control         */
-/*************************/
-u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB);
+/*****************/
+/* Level control */
+/*****************/
+u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB,
+	short *max_gain_01dB, short *step_gain_01dB);
 
-u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB[HPI_MAX_CHANNELS]
+u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS]
 	);
 
-u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_level_get_gain(u32 h_control,
 	short an_gain0_01dB_out[HPI_MAX_CHANNELS]
 	);
 
-/*************************/
-/* meter control                 */
-/*************************/
-u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_meter, u32 *p_channels);
+/*****************/
+/* Meter control */
+/*****************/
+u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels);
 
-u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_meter_get_peak(u32 h_control,
 	short an_peak0_01dB_out[HPI_MAX_CHANNELS]
 	);
 
-u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_peak0_01dB_out[HPI_MAX_CHANNELS]
+u16 hpi_meter_get_rms(u32 h_control, short an_peak0_01dB_out[HPI_MAX_CHANNELS]
 	);
 
-u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attack, u16 decay);
+u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay);
 
-u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attack, u16 decay);
+u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay);
 
-u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *attack, u16 *decay);
+u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *attack, u16 *decay);
 
-u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *attack, u16 *decay);
+u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *attack, u16 *decay);
 
-/*************************/
-/* channel mode control  */
-/*************************/
-u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_mode, const u32 index, u16 *pw_mode);
+/************************/
+/* ChannelMode control */
+/************************/
+u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index,
+	u16 *pw_mode);
 
-u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 mode);
+u16 hpi_channel_mode_set(u32 h_control, u16 mode);
 
-u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *mode);
+u16 hpi_channel_mode_get(u32 h_control, u16 *mode);
 
-/*************************/
-/* Tuner control                 */
-/*************************/
-u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, u16 *pw_band);
+/*****************/
+/* Tuner control */
+/*****************/
+u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band);
 
-u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 band);
+u16 hpi_tuner_set_band(u32 h_control, u16 band);
 
-u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_band);
+u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band);
 
-u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq);
+u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index,
+	const u16 band, u32 *pfreq);
 
-u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 freq_ink_hz);
+u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz);
 
-u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pw_freq_ink_hz);
+u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz);
 
-u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *pw_level);
+u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level);
 
-u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short *pw_level);
+u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level);
 
-u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, u16 *pw_gain);
+u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain);
 
-u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short gain);
+u16 hpi_tuner_set_gain(u32 h_control, short gain);
 
-u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *pn_gain);
+u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain);
 
-u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_status_mask, u16 *pw_status);
+u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status);
 
-u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 mode, u32 value);
+u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value);
 
-u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 mode, u32 *pn_value);
+u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value);
 
-u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *p_rds_data);
+u16 hpi_tuner_get_rds(u32 h_control, char *p_rds_data);
 
-u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis);
+u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index,
+	const u16 band, u32 *pdeemphasis);
 
-u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 deemphasis);
-u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pdeemphasis);
+u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis);
+u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis);
 
-u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, u32 *pbitmap_program);
+u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program);
 
-u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 program);
+u16 hpi_tuner_set_program(u32 h_control, u32 program);
 
-u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 *pprogram);
+u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram);
 
-u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_dsp_version, const u32 string_size);
+u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version,
+	const u32 string_size);
 
-u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_sdk_version, const u32 string_size);
+u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version,
+	const u32 string_size);
 
-u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pquality);
+u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality);
 
-u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pblend);
+u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend);
 
-u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, const u32 blend);
+u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend);
 
-/****************************/
-/* PADs control             */
-/****************************/
+/***************/
+/* PAD control */
+/***************/
 
-u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_string, const u32 string_length);
+u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string,
+	const u32 string_length);
 
-u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 string_length);
+u16 hpi_pad_get_artist(u32 h_control, char *psz_string,
+	const u32 string_length);
 
-u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 string_length);
+u16 hpi_pad_get_title(u32 h_control, char *psz_string,
+	const u32 string_length);
 
-u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 string_length);
+u16 hpi_pad_get_comment(u32 h_control, char *psz_string,
+	const u32 string_length);
 
-u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *ppTY);
+u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY);
 
-u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 *ppI);
+u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI);
 
-u16 HPI_PAD__get_program_type_string(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, const u32 data_type, const u32 pTY, char *psz_string,
-	const u32 string_length);
+u16 hpi_pad_get_program_type_string(u32 h_control, const u32 data_type,
+	const u32 pTY, char *psz_string, const u32 string_length);
 
 /****************************/
 /* AES/EBU Receiver control */
 /****************************/
-u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_aes_rx, const u32 index, u16 *pw_format);
+u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index,
+	u16 *pw_format);
 
-u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source);
+u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 source);
 
-u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source);
+u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_source);
 
-u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate);
+u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate);
 
-u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *pw_data);
+u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data);
 
-u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 *pw_data);
+u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index,
+	u16 *pw_data);
 
-u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_error_data);
+u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data);
 
 /*******************************/
 /* AES/EBU Transmitter control */
 /*******************************/
-u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u32 sample_rate);
+u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate);
 
-u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 data);
+u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data);
 
-u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 data);
+u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index,
+	u16 data);
 
-u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 *pw_data);
+u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index,
+	u16 *pw_data);
 
-u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_aes_tx, const u32 index, u16 *pw_format);
+u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index,
+	u16 *pw_format);
 
-u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 output_format);
+u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format);
 
-u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_output_format);
+u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format);
 
 /***********************/
-/* multiplexer control */
+/* Multiplexer control */
 /***********************/
-u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source_node_type, u16 source_node_index);
-
-u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *source_node_type, u16 *source_node_index);
+u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type,
+	u16 source_node_index);
 
-u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *source_node_type,
+u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type,
 	u16 *source_node_index);
 
+u16 hpi_multiplexer_query_source(u32 h_control, u16 index,
+	u16 *source_node_type, u16 *source_node_index);
+
 /***************/
-/* VOX control */
+/* Vox control */
 /***************/
-u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB);
+u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB);
 
-u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *an_gain0_01dB);
+u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB);
 
 /*********************/
 /* Bitstream control */
 /*********************/
-u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 edge_type);
+u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type);
 
-u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 polarity);
+u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity);
 
-u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity);
+u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity,
+	u16 *pw_data_activity);
 
 /***********************/
 /* SampleClock control */
 /***********************/
 
-u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, u16 *pw_source);
+u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index,
+	u16 *pw_source);
 
-u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source);
+u16 hpi_sample_clock_set_source(u32 h_control, u16 source);
 
-u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source);
+u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source);
 
-u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, const u32 source,
-	u16 *pw_source_index);
+u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index,
+	const u32 source, u16 *pw_source_index);
 
-u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source_index);
+u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index);
 
-u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source_index);
+u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index);
 
-u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate);
+u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate);
 
-u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, u32 *psource);
+u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index,
+	u32 *psource);
 
-u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 sample_rate);
+u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate);
 
-u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate);
+u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate);
 
-u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 enable);
+u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable);
 
-u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *penable);
+u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable);
 
-u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 lock);
+u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock);
 
-u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *plock);
+u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock);
 
 /***********************/
 /* Microphone control */
 /***********************/
-u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 on_off);
+u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off);
 
-u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_on_off);
+u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off);
 
-/*******************************
-  Parametric Equalizer control
-*******************************/
-u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_number_of_bands, u16 *pw_enabled);
+/********************************/
+/* Parametric Equalizer control */
+/********************************/
+u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands,
+	u16 *pw_enabled);
 
-u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 on_off);
+u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off);
 
-u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100,
-	short gain0_01dB);
+u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type,
+	u32 frequency_hz, short q100, short gain0_01dB);
 
-u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz,
-	short *pnQ100, short *pn_gain0_01dB);
+u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type,
+	u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB);
 
-u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, short coeffs[5]
+u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5]
 	);
 
-/*******************************
-  Compressor Expander control
-*******************************/
-
-u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 on);
-
-u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pon);
-
-u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short makeup_gain0_01dB);
-
-u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short *pn_makeup_gain0_01dB);
-
-u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u32 index, u32 attack);
-
-u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u32 index, u32 *pw_attack);
-
-u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 decay);
-
-u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 *pw_decay);
-
-u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, short threshold0_01dB);
-
-u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, short *pn_threshold0_01dB);
-
-u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 ratio100);
-
-u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 *pw_ratio100);
-
-/*******************************
-  Cobranet HMI control
-*******************************/
-u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 hmi_address, u32 byte_count, u8 *pb_data);
-
-u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data);
-
-u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pstatus, u32 *preadable_size,
-	u32 *pwriteable_size);
-
-/*Read the current IP address
-*/
-u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pi_paddress);
-
-/* Write the current IP address
-*/
-u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 i_paddress);
-
-/* Read the static IP address
-*/
-u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pi_paddress);
+/*******************************/
+/* Compressor Expander control */
+/*******************************/
 
-/* Write the static IP address
-*/
-u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 i_paddress);
+u16 hpi_compander_set_enable(u32 h_control, u32 on);
 
-/* Read the MAC address
-*/
-u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs);
+u16 hpi_compander_get_enable(u32 h_control, u32 *pon);
 
-/*******************************
-  Tone Detector control
-*******************************/
-u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	u32 *state);
+u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB);
 
-u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	u32 enable);
+u16 hpi_compander_get_makeup_gain(u32 h_control, short *pn_makeup_gain0_01dB);
 
-u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	u32 *enable);
+u16 hpi_compander_set_attack_time_constant(u32 h_control, u32 index,
+	u32 attack);
 
-u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 event_enable);
+u16 hpi_compander_get_attack_time_constant(u32 h_control, u32 index,
+	u32 *pw_attack);
 
-u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *event_enable);
+u16 hpi_compander_set_decay_time_constant(u32 h_control, u32 index,
+	u32 decay);
 
-u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int threshold);
+u16 hpi_compander_get_decay_time_constant(u32 h_control, u32 index,
+	u32 *pw_decay);
 
-u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int *threshold);
+u16 hpi_compander_set_threshold(u32 h_control, u32 index,
+	short threshold0_01dB);
 
-u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 index, u32 *frequency);
+u16 hpi_compander_get_threshold(u32 h_control, u32 index,
+	short *pn_threshold0_01dB);
 
-/*******************************
-  Silence Detector control
-*******************************/
-u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *state);
+u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100);
 
-u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 enable);
+u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *pw_ratio100);
 
-u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *enable);
+/********************/
+/* Cobranet control */
+/********************/
+u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count,
+	u8 *pb_data);
 
-u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 event_enable);
+u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count,
+	u32 *pbyte_count, u8 *pb_data);
 
-u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *event_enable);
+u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus,
+	u32 *preadable_size, u32 *pwriteable_size);
 
-u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 delay);
+u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address);
 
-u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *delay);
+u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address);
 
-u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int threshold);
+u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address);
 
-u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int *threshold);
+u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address);
 
-/*******************************
-  Universal control
-*******************************/
-u16 hpi_entity_find_next(struct hpi_entity *container_entity,
-	enum e_entity_type type, enum e_entity_role role, int recursive_flag,
-	struct hpi_entity **current_match);
+u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs,
+	u32 *p_mac_lsbs);
 
-u16 hpi_entity_copy_value_from(struct hpi_entity *entity,
-	enum e_entity_type type, size_t item_count, void *value_dst_p);
+/*************************/
+/* Tone Detector control */
+/*************************/
+u16 hpi_tone_detector_get_state(u32 hC, u32 *state);
 
-u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type,
-	size_t *items, enum e_entity_role *role, void **value);
+u16 hpi_tone_detector_set_enable(u32 hC, u32 enable);
 
-u16 hpi_entity_alloc_and_pack(const enum e_entity_type type,
-	const size_t item_count, const enum e_entity_role role, void *value,
-	struct hpi_entity **entity);
+u16 hpi_tone_detector_get_enable(u32 hC, u32 *enable);
 
-void hpi_entity_free(struct hpi_entity *entity);
+u16 hpi_tone_detector_set_event_enable(u32 hC, u32 event_enable);
 
-u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity **info);
+u16 hpi_tone_detector_get_event_enable(u32 hC, u32 *event_enable);
 
-u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity **value);
+u16 hpi_tone_detector_set_threshold(u32 hC, int threshold);
 
-u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity *value);
+u16 hpi_tone_detector_get_threshold(u32 hC, int *threshold);
 
-/*/////////// */
-/* DSP CLOCK  */
-/*/////////// */
-u16 hpi_clock_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_dsp_clock);
+u16 hpi_tone_detector_get_frequency(u32 hC, u32 index, u32 *frequency);
 
-u16 hpi_clock_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock,
-	u16 hour, u16 minute, u16 second, u16 milli_second);
+/****************************/
+/* Silence Detector control */
+/****************************/
+u16 hpi_silence_detector_get_state(u32 hC, u32 *state);
 
-u16 hpi_clock_get_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock,
-	u16 *pw_hour, u16 *pw_minute, u16 *pw_second, u16 *pw_milli_second);
+u16 hpi_silence_detector_set_enable(u32 hC, u32 enable);
 
-/*/////////// */
-/* PROFILE        */
-/*/////////// */
-u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 profile_index, u32 *ph_profile,
-	u16 *pw_max_profiles);
+u16 hpi_silence_detector_get_enable(u32 hC, u32 *enable);
 
-u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
-	u16 index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count,
-	u32 *pmax_micro_seconds, u32 *pmin_micro_seconds);
+u16 hpi_silence_detector_set_event_enable(u32 hC, u32 event_enable);
 
-u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile);
+u16 hpi_silence_detector_get_event_enable(u32 hC, u32 *event_enable);
 
-u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile);
+u16 hpi_silence_detector_set_delay(u32 hC, u32 delay);
 
-u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
-	u16 index, char *sz_profile_name, u16 profile_name_length);
+u16 hpi_silence_detector_get_delay(u32 hC, u32 *delay);
 
-u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys,
-	u32 h_profile, u32 *putilization);
+u16 hpi_silence_detector_set_threshold(u32 hC, int threshold);
 
-/*//////////////////// */
-/* UTILITY functions */
+u16 hpi_silence_detector_get_threshold(u32 hC, int *threshold);
+/*********************/
+/* Utility functions */
+/*********************/
 
 u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 	u32 sample_rate, u32 bit_rate, u32 attributes);
 
-/* Until it's verified, this function is for Windows OSs only */
-
-#endif	 /*_H_HPI_ */
-/*
-///////////////////////////////////////////////////////////////////////////////
-// See CVS for history.  Last complete set in rev 1.146
-////////////////////////////////////////////////////////////////////////////////
-*/
+#endif	 /*_HPI_H_ */
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 1b9bf93..3e3c2ef 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -43,16 +43,17 @@
 #define HPI_HIF_ERROR_MASK      0x4000
 
 /* HPI6000 specific error codes */
+#define HPI6000_ERROR_BASE 900	/* not actually used anywhere */
 
-#define HPI6000_ERROR_BASE                              900
+/* operational/messaging errors */
 #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT             901
-#define HPI6000_ERROR_MSG_RESP_SEND_MSG_ACK             902
+
 #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK             903
 #define HPI6000_ERROR_MSG_GET_ADR                       904
 #define HPI6000_ERROR_RESP_GET_ADR                      905
 #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32             906
 #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32              907
-#define HPI6000_ERROR_MSG_INVALID_DSP_INDEX             908
+
 #define HPI6000_ERROR_CONTROL_CACHE_PARAMS              909
 
 #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT            911
@@ -62,7 +63,6 @@
 #define HPI6000_ERROR_SEND_DATA_CMD                     915
 #define HPI6000_ERROR_SEND_DATA_WRITE                   916
 #define HPI6000_ERROR_SEND_DATA_IDLECMD                 917
-#define HPI6000_ERROR_SEND_DATA_VERIFY                  918
 
 #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT             921
 #define HPI6000_ERROR_GET_DATA_ACK                      922
@@ -76,9 +76,8 @@
 
 #define HPI6000_ERROR_MSG_RESP_GETRESPCMD               961
 #define HPI6000_ERROR_MSG_RESP_IDLECMD                  962
-#define HPI6000_ERROR_MSG_RESP_BLOCKVERIFY32            963
 
-/* adapter init errors */
+/* Initialisation/bootload errors */
 #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID               930
 
 /* can't access PCI2040 */
@@ -210,6 +209,8 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao,
 static short create_adapter_obj(struct hpi_adapter_obj *pao,
 	u32 *pos_error_code);
 
+static void delete_adapter_obj(struct hpi_adapter_obj *pao);
+
 /* local globals */
 
 static u16 gw_pci_read_asserts;	/* used to count PCI2040 errors */
@@ -217,17 +218,7 @@ static u16 gw_pci_write_asserts;	/* used to count PCI2040 errors */
 
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 {
-
 	switch (phm->function) {
-	case HPI_SUBSYS_OPEN:
-	case HPI_SUBSYS_CLOSE:
-	case HPI_SUBSYS_GET_INFO:
-	case HPI_SUBSYS_DRIVER_UNLOAD:
-	case HPI_SUBSYS_DRIVER_LOAD:
-	case HPI_SUBSYS_FIND_ADAPTERS:
-		/* messages that should not get here */
-		phr->error = HPI_ERROR_UNIMPLEMENTED;
-		break;
 	case HPI_SUBSYS_CREATE_ADAPTER:
 		subsys_create_adapter(phm, phr);
 		break;
@@ -243,7 +234,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 static void control_message(struct hpi_adapter_obj *pao,
 	struct hpi_message *phm, struct hpi_response *phr)
 {
-
 	switch (phm->function) {
 	case HPI_CONTROL_GET_STATE:
 		if (pao->has_control_cache) {
@@ -251,7 +241,13 @@ static void control_message(struct hpi_adapter_obj *pao,
 			err = hpi6000_update_control_cache(pao, phm);
 
 			if (err) {
-				phr->error = err;
+				if (err >= HPI_ERROR_BACKEND_BASE) {
+					phr->error =
+						HPI_ERROR_CONTROL_CACHING;
+					phr->specific_error = err;
+				} else {
+					phr->error = err;
+				}
 				break;
 			}
 
@@ -262,16 +258,15 @@ static void control_message(struct hpi_adapter_obj *pao,
 		}
 		hw_message(pao, phm, phr);
 		break;
-	case HPI_CONTROL_GET_INFO:
-		hw_message(pao, phm, phr);
-		break;
 	case HPI_CONTROL_SET_STATE:
 		hw_message(pao, phm, phr);
-		hpi_sync_control_cache(((struct hpi_hw_obj *)pao->priv)->
-			p_cache, phm, phr);
+		hpi_cmn_control_cache_sync_to_msg(((struct hpi_hw_obj *)pao->
+				priv)->p_cache, phm, phr);
 		break;
+
+	case HPI_CONTROL_GET_INFO:
 	default:
-		phr->error = HPI_ERROR_INVALID_FUNC;
+		hw_message(pao, phm, phr);
 		break;
 	}
 }
@@ -280,26 +275,12 @@ static void adapter_message(struct hpi_adapter_obj *pao,
 	struct hpi_message *phm, struct hpi_response *phr)
 {
 	switch (phm->function) {
-	case HPI_ADAPTER_GET_INFO:
-		hw_message(pao, phm, phr);
-		break;
 	case HPI_ADAPTER_GET_ASSERT:
 		adapter_get_asserts(pao, phm, phr);
 		break;
-	case HPI_ADAPTER_OPEN:
-	case HPI_ADAPTER_CLOSE:
-	case HPI_ADAPTER_TEST_ASSERT:
-	case HPI_ADAPTER_SELFTEST:
-	case HPI_ADAPTER_GET_MODE:
-	case HPI_ADAPTER_SET_MODE:
-	case HPI_ADAPTER_FIND_OBJECT:
-	case HPI_ADAPTER_GET_PROPERTY:
-	case HPI_ADAPTER_SET_PROPERTY:
-	case HPI_ADAPTER_ENUM_PROPERTY:
-		hw_message(pao, phm, phr);
-		break;
+
 	default:
-		phr->error = HPI_ERROR_INVALID_FUNC;
+		hw_message(pao, phm, phr);
 		break;
 	}
 }
@@ -311,7 +292,7 @@ static void outstream_message(struct hpi_adapter_obj *pao,
 	case HPI_OSTREAM_HOSTBUFFER_ALLOC:
 	case HPI_OSTREAM_HOSTBUFFER_FREE:
 		/* Don't let these messages go to the HW function because
-		 * they're called without allocating the spinlock.
+		 * they're called without locking the spinlock.
 		 * For the HPI6000 adapters the HW would return
 		 * HPI_ERROR_INVALID_FUNC anyway.
 		 */
@@ -331,7 +312,7 @@ static void instream_message(struct hpi_adapter_obj *pao,
 	case HPI_ISTREAM_HOSTBUFFER_ALLOC:
 	case HPI_ISTREAM_HOSTBUFFER_FREE:
 		/* Don't let these messages go to the HW function because
-		 * they're called without allocating the spinlock.
+		 * they're called without locking the spinlock.
 		 * For the HPI6000 adapters the HW would return
 		 * HPI_ERROR_INVALID_FUNC anyway.
 		 */
@@ -355,7 +336,7 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
 	/* subsytem messages get executed by every HPI. */
 	/* All other messages are ignored unless the adapter index matches */
 	/* an adapter in the HPI */
-	HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->object, phm->function);
+	/*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */
 
 	/* if Dsp has crashed then do not communicate with it any more */
 	if (phm->object != HPI_OBJ_SUBSYSTEM) {
@@ -433,21 +414,13 @@ static void subsys_create_adapter(struct hpi_message *phm,
 	struct hpi_adapter_obj ao;
 	struct hpi_adapter_obj *pao;
 	u32 os_error_code;
-	short error = 0;
+	u16 err = 0;
 	u32 dsp_index = 0;
 
 	HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");
 
 	memset(&ao, 0, sizeof(ao));
 
-	/* this HPI only creates adapters for TI/PCI2040 based devices */
-	if (phm->u.s.resource.bus_type != HPI_BUS_PCI)
-		return;
-	if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI)
-		return;
-	if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040)
-		return;
-
 	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
 	if (!ao.priv) {
 		HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
@@ -456,16 +429,19 @@ static void subsys_create_adapter(struct hpi_message *phm,
 	}
 
 	/* create the adapter object based on the resource information */
-	/*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */
 	ao.pci = *phm->u.s.resource.r.pci;
 
-	error = create_adapter_obj(&ao, &os_error_code);
-	if (!error)
-		error = hpi_add_adapter(&ao);
-	if (error) {
+	err = create_adapter_obj(&ao, &os_error_code);
+	if (err) {
+		delete_adapter_obj(&ao);
+		if (err >= HPI_ERROR_BACKEND_BASE) {
+			phr->error = HPI_ERROR_DSP_BOOTLOAD;
+			phr->specific_error = err;
+		} else {
+			phr->error = err;
+		}
+
 		phr->u.s.data = os_error_code;
-		kfree(ao.priv);
-		phr->error = error;
 		return;
 	}
 	/* need to update paParentAdapter */
@@ -473,7 +449,7 @@ static void subsys_create_adapter(struct hpi_message *phm,
 	if (!pao) {
 		/* We just added this adapter, why can't we find it!? */
 		HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
-		phr->error = 950;
+		phr->error = HPI_ERROR_BAD_ADAPTER;
 		return;
 	}
 
@@ -482,9 +458,8 @@ static void subsys_create_adapter(struct hpi_message *phm,
 		phw->ado[dsp_index].pa_parent_adapter = pao;
 	}
 
-	phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
+	phr->u.s.adapter_type = ao.adapter_type;
 	phr->u.s.adapter_index = ao.index;
-	phr->u.s.num_adapters++;
 	phr->error = 0;
 }
 
@@ -492,20 +467,13 @@ static void subsys_delete_adapter(struct hpi_message *phm,
 	struct hpi_response *phr)
 {
 	struct hpi_adapter_obj *pao = NULL;
-	struct hpi_hw_obj *phw;
 
-	pao = hpi_find_adapter(phm->adapter_index);
+	pao = hpi_find_adapter(phm->obj_index);
 	if (!pao)
 		return;
 
-	phw = (struct hpi_hw_obj *)pao->priv;
-
-	if (pao->has_control_cache)
-		hpi_free_control_cache(phw->p_cache);
-
+	delete_adapter_obj(pao);
 	hpi_delete_adapter(pao);
-	kfree(phw);
-
 	phr->error = 0;
 }
 
@@ -519,9 +487,6 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 	u32 control_cache_count = 0;
 	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
 
-	/* init error reporting */
-	pao->dsp_crashed = 0;
-
 	/* The PCI2040 has the following address map */
 	/* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
 	/* BAR1 - 32K = HPI registers on DSP */
@@ -575,36 +540,36 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 	/* get info about the adapter by asking the adapter */
 	/* send a HPI_ADAPTER_GET_INFO message */
 	{
-		struct hpi_message hM;
-		struct hpi_response hR0;	/* response from DSP 0 */
-		struct hpi_response hR1;	/* response from DSP 1 */
+		struct hpi_message hm;
+		struct hpi_response hr0;	/* response from DSP 0 */
+		struct hpi_response hr1;	/* response from DSP 1 */
 		u16 error = 0;
 
 		HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
-		memset(&hM, 0, sizeof(hM));
-		hM.type = HPI_TYPE_MESSAGE;
-		hM.size = sizeof(struct hpi_message);
-		hM.object = HPI_OBJ_ADAPTER;
-		hM.function = HPI_ADAPTER_GET_INFO;
-		hM.adapter_index = 0;
-		memset(&hR0, 0, sizeof(hR0));
-		memset(&hR1, 0, sizeof(hR1));
-		hR0.size = sizeof(hR0);
-		hR1.size = sizeof(hR1);
-
-		error = hpi6000_message_response_sequence(pao, 0, &hM, &hR0);
-		if (hR0.error) {
-			HPI_DEBUG_LOG(DEBUG, "message error %d\n", hR0.error);
-			return hR0.error;
+		memset(&hm, 0, sizeof(hm));
+		hm.type = HPI_TYPE_MESSAGE;
+		hm.size = sizeof(struct hpi_message);
+		hm.object = HPI_OBJ_ADAPTER;
+		hm.function = HPI_ADAPTER_GET_INFO;
+		hm.adapter_index = 0;
+		memset(&hr0, 0, sizeof(hr0));
+		memset(&hr1, 0, sizeof(hr1));
+		hr0.size = sizeof(hr0);
+		hr1.size = sizeof(hr1);
+
+		error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0);
+		if (hr0.error) {
+			HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error);
+			return hr0.error;
 		}
 		if (phw->num_dsp == 2) {
-			error = hpi6000_message_response_sequence(pao, 1, &hM,
-				&hR1);
+			error = hpi6000_message_response_sequence(pao, 1, &hm,
+				&hr1);
 			if (error)
 				return error;
 		}
-		pao->adapter_type = hR0.u.a.adapter_type;
-		pao->index = hR0.u.a.adapter_index;
+		pao->adapter_type = hr0.u.ax.info.adapter_type;
+		pao->index = hr0.u.ax.info.adapter_index;
 	}
 
 	memset(&phw->control_cache[0], 0,
@@ -618,22 +583,37 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 		control_cache_count =
 			hpi_read_word(&phw->ado[0],
 			HPI_HIF_ADDR(control_cache_count));
-		pao->has_control_cache = 1;
 
 		phw->p_cache =
 			hpi_alloc_control_cache(control_cache_count,
-			control_cache_size, (struct hpi_control_cache_info *)
+			control_cache_size, (unsigned char *)
 			&phw->control_cache[0]
 			);
-		if (!phw->p_cache)
-			pao->has_control_cache = 0;
-	} else
-		pao->has_control_cache = 0;
+		if (phw->p_cache)
+			pao->has_control_cache = 1;
+	}
 
 	HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n",
 		pao->adapter_type, pao->index);
 	pao->open = 0;	/* upon creation the adapter is closed */
-	return 0;
+
+	if (phw->p_cache)
+		phw->p_cache->adap_idx = pao->index;
+
+	return hpi_add_adapter(pao);
+}
+
+static void delete_adapter_obj(struct hpi_adapter_obj *pao)
+{
+	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+
+	if (pao->has_control_cache)
+		hpi_free_control_cache(phw->p_cache);
+
+	/* reset DSPs on adapter */
+	iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET);
+
+	kfree(phw);
 }
 
 /************************************************************************/
@@ -645,11 +625,13 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao,
 #ifndef HIDE_PCI_ASSERTS
 	/* if we have PCI2040 asserts then collect them */
 	if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
-		phr->u.a.serial_number =
+		phr->u.ax.assert.p1 =
 			gw_pci_read_asserts * 100 + gw_pci_write_asserts;
-		phr->u.a.adapter_index = 1;	/* assert count */
-		phr->u.a.adapter_type = -1;	/* "dsp index" */
-		strcpy(phr->u.a.sz_adapter_assert, "PCI2040 error");
+		phr->u.ax.assert.p2 = 0;
+		phr->u.ax.assert.count = 1;	/* assert count */
+		phr->u.ax.assert.dsp_index = -1;	/* "dsp index" */
+		strcpy(phr->u.ax.assert.sz_message, "PCI2040 error");
+		phr->u.ax.assert.dsp_msg_addr = 0;
 		gw_pci_read_asserts = 0;
 		gw_pci_write_asserts = 0;
 		phr->error = 0;
@@ -686,10 +668,10 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 
 	/* NOTE don't use wAdapterType in this routine. It is not setup yet */
 
-	switch (pao->pci.subsys_device_id) {
+	switch (pao->pci.pci_dev->subsystem_device) {
 	case 0x5100:
 	case 0x5110:	/* ASI5100 revB or higher with C6711D */
-	case 0x5200:	/* ASI5200 PC_ie version of ASI5100 */
+	case 0x5200:	/* ASI5200 PCIe version of ASI5100 */
 	case 0x6100:
 	case 0x6200:
 		boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
@@ -709,8 +691,9 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	 * note that bits 4..15 are read-only and so should always return zero,
 	 * even though we wrote 1 to them
 	 */
-	for (i = 0; i < 1000; i++)
-		delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+	hpios_delay_micro_seconds(1000);
+	delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+
 	if (delay != dw2040_reset) {
 		HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
 			delay);
@@ -743,8 +726,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	dw2040_reset = dw2040_reset & (~0x00000008);
 	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
 	/*delay to allow DSP to get going */
-	for (i = 0; i < 100; i++)
-		delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+	hpios_delay_micro_seconds(100);
 
 	/* loop through all DSPs, downloading DSP code */
 	for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
@@ -783,27 +765,27 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			 */
 			/* bypass PLL */
 			hpi_write_word(pdo, 0x01B7C100, 0x0000);
-			for (i = 0; i < 100; i++)
-				delay = ioread32(phw->dw2040_HPICSR +
-					HPI_RESET);
+			hpios_delay_micro_seconds(100);
 
 			/*  ** use default of PLL  x7 ** */
 			/* EMIF = 225/3=75MHz */
 			hpi_write_word(pdo, 0x01B7C120, 0x8002);
+			hpios_delay_micro_seconds(100);
+
 			/* peri = 225/2 */
 			hpi_write_word(pdo, 0x01B7C11C, 0x8001);
+			hpios_delay_micro_seconds(100);
+
 			/* cpu  = 225/1 */
 			hpi_write_word(pdo, 0x01B7C118, 0x8000);
-			/* ~200us delay */
-			for (i = 0; i < 2000; i++)
-				delay = ioread32(phw->dw2040_HPICSR +
-					HPI_RESET);
+
+			/* ~2ms delay */
+			hpios_delay_micro_seconds(2000);
+
 			/* PLL not bypassed */
 			hpi_write_word(pdo, 0x01B7C100, 0x0001);
-			/* ~200us delay */
-			for (i = 0; i < 2000; i++)
-				delay = ioread32(phw->dw2040_HPICSR +
-					HPI_RESET);
+			/* ~2ms delay */
+			hpios_delay_micro_seconds(2000);
 		}
 
 		/* test r/w to internal DSP memory
@@ -927,9 +909,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 		}
 
 		/* delay a little to allow SDRAM and DSP to "get going" */
-
-		for (i = 0; i < 1000; i++)
-			delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+		hpios_delay_micro_seconds(1000);
 
 		/* test access to SDRAM */
 		{
@@ -976,7 +956,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 
 		/* write the DSP code down into the DSPs memory */
 		/*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */
-		dsp_code.ps_dev = pao->pci.p_os_data;
+		dsp_code.ps_dev = pao->pci.pci_dev;
 
 		error = hpi_dsp_code_open(boot_load_family, &dsp_code,
 			pos_error_code);
@@ -1073,8 +1053,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 
 		/* step 3. Start code by sending interrupt */
 		iowrite32(0x00030003, pdo->prHPI_control);
-		for (i = 0; i < 10000; i++)
-			delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+		hpios_delay_micro_seconds(10000);
 
 		/* wait for a non-zero value in hostcmd -
 		 * indicating initialization is complete
@@ -1101,7 +1080,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			 * locks up with a bluescreen (NOT GPF or pagefault).
 			 */
 			else
-				hpios_delay_micro_seconds(1000);
+				hpios_delay_micro_seconds(10000);
 		}
 		if (timeout == 0)
 			return HPI6000_ERROR_INIT_NOACK;
@@ -1132,14 +1111,14 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 				mask = 0xFFFFFF00L;
 				/* ASI5100 uses AX6 code, */
 				/* but has no PLD r/w register to test */
-				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
-						subsys_device_id) ==
+				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
+						subsystem_device) ==
 					HPI_ADAPTER_FAMILY_ASI(0x5100))
 					mask = 0x00000000L;
 				/* ASI5200 uses AX6 code, */
 				/* but has no PLD r/w register to test */
-				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
-						subsys_device_id) ==
+				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
+						subsystem_device) ==
 					HPI_ADAPTER_FAMILY_ASI(0x5200))
 					mask = 0x00000000L;
 				break;
@@ -1204,7 +1183,7 @@ static u32 hpi_read_word(struct dsp_obj *pdo, u32 address)
 	u32 data = 0;
 
 	if (hpi_set_address(pdo, address))
-		return 0;	/*? no way to return error */
+		return 0;	/*? No way to return error */
 
 	/* take care of errata in revB DSP (2.0.1) */
 	data = ioread32(pdo->prHPI_data);
@@ -1340,10 +1319,6 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	u32 *p_data;
 	u16 error = 0;
 
-	/* does the DSP we are referencing exist? */
-	if (dsp_index >= phw->num_dsp)
-		return HPI6000_ERROR_MSG_INVALID_DSP_INDEX;
-
 	ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
 	if (ack & HPI_HIF_ERROR_MASK) {
 		pao->dsp_crashed++;
@@ -1351,9 +1326,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	}
 	pao->dsp_crashed = 0;
 
-	/* send the message */
-
-	/* get the address and size */
+	/* get the message address and size */
 	if (phw->message_buffer_address_on_dsp == 0) {
 		timeout = TIMEOUT;
 		do {
@@ -1368,10 +1341,9 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	} else
 		address = phw->message_buffer_address_on_dsp;
 
-	/*        dwLength = sizeof(struct hpi_message); */
 	length = phm->size;
 
-	/* send it */
+	/* send the message */
 	p_data = (u32 *)phm;
 	if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
 			(u16)length / 4))
@@ -1385,7 +1357,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	if (ack & HPI_HIF_ERROR_MASK)
 		return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
 
-	/* get the address and size */
+	/* get the response address */
 	if (phw->response_buffer_address_on_dsp == 0) {
 		timeout = TIMEOUT;
 		do {
@@ -1409,7 +1381,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	if (!timeout)
 		length = sizeof(struct hpi_response);
 
-	/* get it */
+	/* get the response */
 	p_data = (u32 *)phr;
 	if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
 			(u16)length / 4))
@@ -1805,17 +1777,11 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 	hpios_dsplock_lock(pao);
 	error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
 
-	/* maybe an error response */
-	if (error) {
-		/* something failed in the HPI/DSP interface */
-		phr->error = error;
-		/* just the header of the response is valid */
-		phr->size = sizeof(struct hpi_response_header);
+	if (error)	/* something failed in the HPI/DSP interface */
 		goto err;
-	}
 
-	if (phr->error != 0)	/* something failed in the DSP */
-		goto err;
+	if (phr->error)	/* something failed in the DSP */
+		goto out;
 
 	switch (phm->function) {
 	case HPI_OSTREAM_WRITE:
@@ -1827,21 +1793,30 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 		error = hpi6000_get_data(pao, dsp_index, phm, phr);
 		break;
 	case HPI_ADAPTER_GET_ASSERT:
-		phr->u.a.adapter_index = 0;	/* dsp 0 default */
+		phr->u.ax.assert.dsp_index = 0;	/* dsp 0 default */
 		if (num_dsp == 2) {
-			if (!phr->u.a.adapter_type) {
+			if (!phr->u.ax.assert.count) {
 				/* no assert from dsp 0, check dsp 1 */
 				error = hpi6000_message_response_sequence(pao,
 					1, phm, phr);
-				phr->u.a.adapter_index = 1;
+				phr->u.ax.assert.dsp_index = 1;
 			}
 		}
 	}
 
-	if (error)
-		phr->error = error;
-
 err:
+	if (error) {
+		if (error >= HPI_ERROR_BACKEND_BASE) {
+			phr->error = HPI_ERROR_DSP_COMMUNICATION;
+			phr->specific_error = error;
+		} else {
+			phr->error = error;
+		}
+
+		/* just the header of the response is valid */
+		phr->size = sizeof(struct hpi_response_header);
+	}
+out:
 	hpios_dsplock_unlock(pao);
 	return;
 }
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index 2672f65..620525b 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -38,27 +38,26 @@
 
 /*****************************************************************************/
 /* HPI6205 specific error codes */
-#define HPI6205_ERROR_BASE                      1000
-/*#define HPI6205_ERROR_MEM_ALLOC 1001 */
+#define HPI6205_ERROR_BASE 1000	/* not actually used anywhere */
+
+/* operational/messaging errors */
+#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT     1015
+#define HPI6205_ERROR_MSG_RESP_TIMEOUT          1016
+
+/* initialization/bootload errors */
 #define HPI6205_ERROR_6205_NO_IRQ               1002
 #define HPI6205_ERROR_6205_INIT_FAILED          1003
-/*#define HPI6205_ERROR_MISSING_DSPCODE 1004 */
-#define HPI6205_ERROR_UNKNOWN_PCI_DEVICE        1005
 #define HPI6205_ERROR_6205_REG                  1006
 #define HPI6205_ERROR_6205_DSPPAGE              1007
-#define HPI6205_ERROR_BAD_DSPINDEX              1008
 #define HPI6205_ERROR_C6713_HPIC                1009
 #define HPI6205_ERROR_C6713_HPIA                1010
 #define HPI6205_ERROR_C6713_PLL                 1011
 #define HPI6205_ERROR_DSP_INTMEM                1012
 #define HPI6205_ERROR_DSP_EXTMEM                1013
 #define HPI6205_ERROR_DSP_PLD                   1014
-#define HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT     1015
-#define HPI6205_ERROR_MSG_RESP_TIMEOUT          1016
 #define HPI6205_ERROR_6205_EEPROM               1017
 #define HPI6205_ERROR_DSP_EMIF                  1018
 
-#define hpi6205_error(dsp_index, err) (err)
 /*****************************************************************************/
 /* for C6205 PCI i/f */
 /* Host Status Register (HSR) bitfields */
@@ -128,9 +127,6 @@ struct hpi_hw_obj {
 	u32 outstream_host_buffer_size[HPI_MAX_STREAMS];
 
 	struct consistent_dma_area h_control_cache;
-	struct consistent_dma_area h_async_event_buffer;
-/*      struct hpi_control_cache_single *pControlCache; */
-	struct hpi_async_event *p_async_event_buffer;
 	struct hpi_control_cache *p_cache;
 };
 
@@ -208,8 +204,8 @@ static void instream_start(struct hpi_adapter_obj *pao,
 static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
 	u32 address);
 
-static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index,
-	u32 address, u32 data);
+static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
+	int dsp_index, u32 address, u32 data);
 
 static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao,
 	int dsp_index);
@@ -229,17 +225,7 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index);
 
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 {
-
 	switch (phm->function) {
-	case HPI_SUBSYS_OPEN:
-	case HPI_SUBSYS_CLOSE:
-	case HPI_SUBSYS_GET_INFO:
-	case HPI_SUBSYS_DRIVER_UNLOAD:
-	case HPI_SUBSYS_DRIVER_LOAD:
-	case HPI_SUBSYS_FIND_ADAPTERS:
-		/* messages that should not get here */
-		phr->error = HPI_ERROR_UNIMPLEMENTED;
-		break;
 	case HPI_SUBSYS_CREATE_ADAPTER:
 		subsys_create_adapter(phm, phr);
 		break;
@@ -257,15 +243,22 @@ static void control_message(struct hpi_adapter_obj *pao,
 {
 
 	struct hpi_hw_obj *phw = pao->priv;
+	u16 pending_cache_error = 0;
 
 	switch (phm->function) {
 	case HPI_CONTROL_GET_STATE:
 		if (pao->has_control_cache) {
-			rmb();	/* make sure we see updates DM_aed from DSP */
-			if (hpi_check_control_cache(phw->p_cache, phm, phr))
+			rmb();	/* make sure we see updates DMAed from DSP */
+			if (hpi_check_control_cache(phw->p_cache, phm, phr)) {
 				break;
+			} else if (phm->u.c.attribute == HPI_METER_PEAK) {
+				pending_cache_error =
+					HPI_ERROR_CONTROL_CACHING;
+			}
 		}
 		hw_message(pao, phm, phr);
+		if (pending_cache_error && !phr->error)
+			phr->error = pending_cache_error;
 		break;
 	case HPI_CONTROL_GET_INFO:
 		hw_message(pao, phm, phr);
@@ -273,7 +266,8 @@ static void control_message(struct hpi_adapter_obj *pao,
 	case HPI_CONTROL_SET_STATE:
 		hw_message(pao, phm, phr);
 		if (pao->has_control_cache)
-			hpi_sync_control_cache(phw->p_cache, phm, phr);
+			hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm,
+				phr);
 		break;
 	default:
 		phr->error = HPI_ERROR_INVALID_FUNC;
@@ -296,9 +290,9 @@ static void outstream_message(struct hpi_adapter_obj *pao,
 {
 
 	if (phm->obj_index >= HPI_MAX_STREAMS) {
-		phr->error = HPI_ERROR_INVALID_STREAM;
+		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
 		HPI_DEBUG_LOG(WARNING,
-			"message referencing invalid stream %d "
+			"Message referencing invalid stream %d "
 			"on adapter index %d\n", phm->obj_index,
 			phm->adapter_index);
 		return;
@@ -340,9 +334,9 @@ static void instream_message(struct hpi_adapter_obj *pao,
 {
 
 	if (phm->obj_index >= HPI_MAX_STREAMS) {
-		phr->error = HPI_ERROR_INVALID_STREAM;
+		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
 		HPI_DEBUG_LOG(WARNING,
-			"message referencing invalid stream %d "
+			"Message referencing invalid stream %d "
 			"on adapter index %d\n", phm->obj_index,
 			phm->adapter_index);
 		return;
@@ -385,8 +379,8 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
 	 * All other messages are ignored unless the adapter index matches
 	 * an adapter in the HPI
 	 */
-	HPI_DEBUG_LOG(DEBUG, "HPI obj=%d, func=%d\n", phm->object,
-		phm->function);
+	/* HPI_DEBUG_LOG(DEBUG, "HPI Obj=%d, Func=%d\n", phm->wObject,
+	   phm->wFunction); */
 
 	/* if Dsp has crashed then do not communicate with it any more */
 	if (phm->object != HPI_OBJ_SUBSYSTEM) {
@@ -411,8 +405,7 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
 
 	/* Init default response  */
 	if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
-		hpi_init_response(phr, phm->object, phm->function,
-			HPI_ERROR_PROCESSING_MESSAGE);
+		phr->error = HPI_ERROR_PROCESSING_MESSAGE;
 
 	HPI_DEBUG_LOG(VERBOSE, "start of switch\n");
 	switch (phm->type) {
@@ -423,9 +416,6 @@ void HPI_6205(struct hpi_message *phm, struct hpi_response *phr)
 			break;
 
 		case HPI_OBJ_ADAPTER:
-			phr->size =
-				sizeof(struct hpi_response_header) +
-				sizeof(struct hpi_adapter_res);
 			adapter_message(pao, phm, phr);
 			break;
 
@@ -474,14 +464,6 @@ static void subsys_create_adapter(struct hpi_message *phm,
 
 	memset(&ao, 0, sizeof(ao));
 
-	/* this HPI only creates adapters for TI/PCI devices */
-	if (phm->u.s.resource.bus_type != HPI_BUS_PCI)
-		return;
-	if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI)
-		return;
-	if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_DSP6205)
-		return;
-
 	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
 	if (!ao.priv) {
 		HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
@@ -491,18 +473,20 @@ static void subsys_create_adapter(struct hpi_message *phm,
 
 	ao.pci = *phm->u.s.resource.r.pci;
 	err = create_adapter_obj(&ao, &os_error_code);
-	if (!err)
-		err = hpi_add_adapter(&ao);
 	if (err) {
-		phr->u.s.data = os_error_code;
 		delete_adapter_obj(&ao);
-		phr->error = err;
+		if (err >= HPI_ERROR_BACKEND_BASE) {
+			phr->error = HPI_ERROR_DSP_BOOTLOAD;
+			phr->specific_error = err;
+		} else {
+			phr->error = err;
+		}
+		phr->u.s.data = os_error_code;
 		return;
 	}
 
-	phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
+	phr->u.s.adapter_type = ao.adapter_type;
 	phr->u.s.adapter_index = ao.index;
-	phr->u.s.num_adapters++;
 	phr->error = 0;
 }
 
@@ -513,7 +497,7 @@ static void subsys_delete_adapter(struct hpi_message *phm,
 	struct hpi_adapter_obj *pao;
 	struct hpi_hw_obj *phw;
 
-	pao = hpi_find_adapter(phm->adapter_index);
+	pao = hpi_find_adapter(phm->obj_index);
 	if (!pao) {
 		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
 		return;
@@ -526,6 +510,7 @@ static void subsys_delete_adapter(struct hpi_message *phm,
 	iowrite32(C6205_HDCR_WARMRESET, phw->prHDCR);
 
 	delete_adapter_obj(pao);
+	hpi_delete_adapter(pao);
 	phr->error = 0;
 }
 
@@ -538,10 +523,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 	struct hpi_hw_obj *phw = pao->priv;
 	struct bus_master_interface *interface;
 	u32 phys_addr;
-#ifndef HPI6205_NO_HSR_POLL
-	u32 time_out = HPI6205_TIMEOUT;
-	u32 temp1;
-#endif
 	int i;
 	u16 err;
 
@@ -566,7 +547,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 
 	if (hpios_locked_mem_alloc(&phw->h_locked_mem,
 			sizeof(struct bus_master_interface),
-			pao->pci.p_os_data))
+			pao->pci.pci_dev))
 		phw->p_interface_buffer = NULL;
 	else if (hpios_locked_mem_get_virt_addr(&phw->h_locked_mem,
 			(void *)&phw->p_interface_buffer))
@@ -591,49 +572,29 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 
 	/* allow boot load even if mem alloc wont work */
 	if (!phw->p_interface_buffer)
-		return hpi6205_error(0, HPI_ERROR_MEMORY_ALLOC);
+		return HPI_ERROR_MEMORY_ALLOC;
 
 	interface = phw->p_interface_buffer;
 
-#ifndef HPI6205_NO_HSR_POLL
-	/* wait for first interrupt indicating the DSP init is done */
-	time_out = HPI6205_TIMEOUT * 10;
-	temp1 = 0;
-	while (((temp1 & C6205_HSR_INTSRC) == 0) && --time_out)
-		temp1 = ioread32(phw->prHSR);
-
-	if (temp1 & C6205_HSR_INTSRC)
-		HPI_DEBUG_LOG(INFO,
-			"interrupt confirming DSP code running OK\n");
-	else {
-		HPI_DEBUG_LOG(ERROR,
-			"timed out waiting for interrupt "
-			"confirming DSP code running\n");
-		return hpi6205_error(0, HPI6205_ERROR_6205_NO_IRQ);
-	}
-
-	/* reset the interrupt */
-	iowrite32(C6205_HSR_INTSRC, phw->prHSR);
-#endif
-
 	/* make sure the DSP has started ok */
 	if (!wait_dsp_ack(phw, H620_HIF_RESET, HPI6205_TIMEOUT * 10)) {
 		HPI_DEBUG_LOG(ERROR, "timed out waiting reset state \n");
-		return hpi6205_error(0, HPI6205_ERROR_6205_INIT_FAILED);
+		return HPI6205_ERROR_6205_INIT_FAILED;
 	}
 	/* Note that *pao, *phw are zeroed after allocation,
 	 * so pointers and flags are NULL by default.
 	 * Allocate bus mastering control cache buffer and tell the DSP about it
 	 */
 	if (interface->control_cache.number_of_controls) {
-		void *p_control_cache_virtual;
+		u8 *p_control_cache_virtual;
 
 		err = hpios_locked_mem_alloc(&phw->h_control_cache,
 			interface->control_cache.size_in_bytes,
-			pao->pci.p_os_data);
+			pao->pci.pci_dev);
 		if (!err)
 			err = hpios_locked_mem_get_virt_addr(&phw->
-				h_control_cache, &p_control_cache_virtual);
+				h_control_cache,
+				(void *)&p_control_cache_virtual);
 		if (!err) {
 			memset(p_control_cache_virtual, 0,
 				interface->control_cache.size_in_bytes);
@@ -642,7 +603,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 				hpi_alloc_control_cache(interface->
 				control_cache.number_of_controls,
 				interface->control_cache.size_in_bytes,
-				(struct hpi_control_cache_info *)
 				p_control_cache_virtual);
 			if (!phw->p_cache)
 				err = HPI_ERROR_MEMORY_ALLOC;
@@ -662,78 +622,56 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
 			pao->has_control_cache = 0;
 		}
 	}
-	/* allocate bus mastering async buffer and tell the DSP about it */
-	if (interface->async_buffer.b.size) {
-		err = hpios_locked_mem_alloc(&phw->h_async_event_buffer,
-			interface->async_buffer.b.size *
-			sizeof(struct hpi_async_event), pao->pci.p_os_data);
-		if (!err)
-			err = hpios_locked_mem_get_virt_addr
-				(&phw->h_async_event_buffer, (void *)
-				&phw->p_async_event_buffer);
-		if (!err)
-			memset((void *)phw->p_async_event_buffer, 0,
-				interface->async_buffer.b.size *
-				sizeof(struct hpi_async_event));
-		if (!err) {
-			err = hpios_locked_mem_get_phys_addr
-				(&phw->h_async_event_buffer, &phys_addr);
-			interface->async_buffer.physical_address32 =
-				phys_addr;
-		}
-		if (err) {
-			if (hpios_locked_mem_valid(&phw->
-					h_async_event_buffer)) {
-				hpios_locked_mem_free
-					(&phw->h_async_event_buffer);
-				phw->p_async_event_buffer = NULL;
-			}
-		}
-	}
 	send_dsp_command(phw, H620_HIF_IDLE);
 
 	{
-		struct hpi_message hM;
-		struct hpi_response hR;
+		struct hpi_message hm;
+		struct hpi_response hr;
 		u32 max_streams;
 
 		HPI_DEBUG_LOG(VERBOSE, "init ADAPTER_GET_INFO\n");
-		memset(&hM, 0, sizeof(hM));
-		hM.type = HPI_TYPE_MESSAGE;
-		hM.size = sizeof(hM);
-		hM.object = HPI_OBJ_ADAPTER;
-		hM.function = HPI_ADAPTER_GET_INFO;
-		hM.adapter_index = 0;
-		memset(&hR, 0, sizeof(hR));
-		hR.size = sizeof(hR);
-
-		err = message_response_sequence(pao, &hM, &hR);
+		memset(&hm, 0, sizeof(hm));
+		hm.type = HPI_TYPE_MESSAGE;
+		hm.size = sizeof(hm);
+		hm.object = HPI_OBJ_ADAPTER;
+		hm.function = HPI_ADAPTER_GET_INFO;
+		hm.adapter_index = 0;
+		memset(&hr, 0, sizeof(hr));
+		hr.size = sizeof(hr);
+
+		err = message_response_sequence(pao, &hm, &hr);
 		if (err) {
 			HPI_DEBUG_LOG(ERROR, "message transport error %d\n",
 				err);
 			return err;
 		}
-		if (hR.error)
-			return hR.error;
+		if (hr.error)
+			return hr.error;
 
-		pao->adapter_type = hR.u.a.adapter_type;
-		pao->index = hR.u.a.adapter_index;
+		pao->adapter_type = hr.u.ax.info.adapter_type;
+		pao->index = hr.u.ax.info.adapter_index;
 
-		max_streams = hR.u.a.num_outstreams + hR.u.a.num_instreams;
+		max_streams =
+			hr.u.ax.info.num_outstreams +
+			hr.u.ax.info.num_instreams;
 
 		hpios_locked_mem_prepare((max_streams * 6) / 10, max_streams,
-			65536, pao->pci.p_os_data);
+			65536, pao->pci.pci_dev);
 
 		HPI_DEBUG_LOG(VERBOSE,
 			"got adapter info type %x index %d serial %d\n",
-			hR.u.a.adapter_type, hR.u.a.adapter_index,
-			hR.u.a.serial_number);
+			hr.u.ax.info.adapter_type, hr.u.ax.info.adapter_index,
+			hr.u.ax.info.serial_number);
 	}
 
 	pao->open = 0;	/* upon creation the adapter is closed */
 
+	if (phw->p_cache)
+		phw->p_cache->adap_idx = pao->index;
+
 	HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");
-	return 0;
+
+	return hpi_add_adapter(pao);
 }
 
 /** Free memory areas allocated by adapter
@@ -747,11 +685,6 @@ static void delete_adapter_obj(struct hpi_adapter_obj *pao)
 
 	phw = pao->priv;
 
-	if (hpios_locked_mem_valid(&phw->h_async_event_buffer)) {
-		hpios_locked_mem_free(&phw->h_async_event_buffer);
-		phw->p_async_event_buffer = NULL;
-	}
-
 	if (hpios_locked_mem_valid(&phw->h_control_cache)) {
 		hpios_locked_mem_free(&phw->h_control_cache);
 		hpi_free_control_cache(phw->p_cache);
@@ -776,13 +709,15 @@ static void delete_adapter_obj(struct hpi_adapter_obj *pao)
 			phw->outstream_host_buffer_size[i] = 0;
 		}
 
-	hpios_locked_mem_unprepare(pao->pci.p_os_data);
+	hpios_locked_mem_unprepare(pao->pci.pci_dev);
 
-	hpi_delete_adapter(pao);
 	kfree(phw);
 }
 
 /*****************************************************************************/
+/* Adapter functions */
+
+/*****************************************************************************/
 /* OutStream Host buffer functions */
 
 /** Allocate or attach buffer for busmastering
@@ -824,7 +759,7 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
 
 		err = hpios_locked_mem_alloc(&phw->outstream_host_buffers
 			[phm->obj_index], phm->u.d.u.buffer.buffer_size,
-			pao->pci.p_os_data);
+			pao->pci.pci_dev);
 
 		if (err) {
 			phr->error = HPI_ERROR_INVALID_DATASIZE;
@@ -861,7 +796,7 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
 		if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
 				buffer_size - 1)) {
 			HPI_DEBUG_LOG(ERROR,
-				"buffer size must be 2^N not %d\n",
+				"Buffer size must be 2^N not %d\n",
 				phm->u.d.u.buffer.buffer_size);
 			phr->error = HPI_ERROR_INVALID_DATASIZE;
 			return;
@@ -875,6 +810,7 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
 		status->dSP_index = 0;
 		status->host_index = status->dSP_index;
 		status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
+		status->auxiliary_data_available = 0;
 
 		hw_message(pao, phm, phr);
 
@@ -966,51 +902,6 @@ static void outstream_write(struct hpi_adapter_obj *pao,
 	hpi_init_response(phr, phm->object, phm->function, 0);
 	status = &interface->outstream_host_buffer_status[phm->obj_index];
 
-	if (phw->flag_outstream_just_reset[phm->obj_index]) {
-		/* First OutStremWrite() call following reset will write data to the
-		   adapter's buffers, reducing delay before stream can start. The DSP
-		   takes care of setting the stream data format using format information
-		   embedded in phm.
-		 */
-		int partial_write = 0;
-		unsigned int original_size = 0;
-
-		phw->flag_outstream_just_reset[phm->obj_index] = 0;
-
-		/* Send the first buffer to the DSP the old way. */
-		/* Limit size of first transfer - */
-		/* expect that this will not usually be triggered. */
-		if (phm->u.d.u.data.data_size > HPI6205_SIZEOF_DATA) {
-			partial_write = 1;
-			original_size = phm->u.d.u.data.data_size;
-			phm->u.d.u.data.data_size = HPI6205_SIZEOF_DATA;
-		}
-		/* write it */
-		phm->function = HPI_OSTREAM_WRITE;
-		hw_message(pao, phm, phr);
-
-		if (phr->error)
-			return;
-
-		/* update status information that the DSP would typically
-		 * update (and will update next time the DSP
-		 * buffer update task reads data from the host BBM buffer)
-		 */
-		status->auxiliary_data_available = phm->u.d.u.data.data_size;
-		status->host_index += phm->u.d.u.data.data_size;
-		status->dSP_index += phm->u.d.u.data.data_size;
-
-		/* if we did a full write, we can return from here. */
-		if (!partial_write)
-			return;
-
-		/* tweak buffer parameters and let the rest of the */
-		/* buffer land in internal BBM buffer */
-		phm->u.d.u.data.data_size =
-			original_size - HPI6205_SIZEOF_DATA;
-		phm->u.d.u.data.pb_data += HPI6205_SIZEOF_DATA;
-	}
-
 	space_available = outstream_get_space_available(status);
 	if (space_available < phm->u.d.u.data.data_size) {
 		phr->error = HPI_ERROR_INVALID_DATASIZE;
@@ -1047,6 +938,24 @@ static void outstream_write(struct hpi_adapter_obj *pao,
 		memcpy(p_bbm_data, p_app_data + l_first_write,
 			phm->u.d.u.data.data_size - l_first_write);
 	}
+
+	/*
+	 * This version relies on the DSP code triggering an OStream buffer
+	 * update immediately following a SET_FORMAT call. The host has
+	 * already written data into the BBM buffer, but the DSP won't know
+	 * about it until dwHostIndex is adjusted.
+	 */
+	if (phw->flag_outstream_just_reset[phm->obj_index]) {
+		/* Format can only change after reset. Must tell DSP. */
+		u16 function = phm->function;
+		phw->flag_outstream_just_reset[phm->obj_index] = 0;
+		phm->function = HPI_OSTREAM_SET_FORMAT;
+		hw_message(pao, phm, phr);	/* send the format to the DSP */
+		phm->function = function;
+		if (phr->error)
+			return;
+	}
+
 	status->host_index += phm->u.d.u.data.data_size;
 }
 
@@ -1132,7 +1041,7 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
 
 		err = hpios_locked_mem_alloc(&phw->instream_host_buffers[phm->
 				obj_index], phm->u.d.u.buffer.buffer_size,
-			pao->pci.p_os_data);
+			pao->pci.pci_dev);
 
 		if (err) {
 			phr->error = HPI_ERROR_INVALID_DATASIZE;
@@ -1163,7 +1072,7 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
 		if (phm->u.d.u.buffer.buffer_size & (phm->u.d.u.buffer.
 				buffer_size - 1)) {
 			HPI_DEBUG_LOG(ERROR,
-				"buffer size must be 2^N not %d\n",
+				"Buffer size must be 2^N not %d\n",
 				phm->u.d.u.buffer.buffer_size);
 			phr->error = HPI_ERROR_INVALID_DATASIZE;
 			return;
@@ -1178,8 +1087,10 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
 		status->dSP_index = 0;
 		status->host_index = status->dSP_index;
 		status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
+		status->auxiliary_data_available = 0;
 
 		hw_message(pao, phm, phr);
+
 		if (phr->error
 			&& hpios_locked_mem_valid(&phw->
 				instream_host_buffers[phm->obj_index])) {
@@ -1344,33 +1255,36 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	struct hpi_hw_obj *phw = pao->priv;
 	struct dsp_code dsp_code;
 	u16 boot_code_id[HPI6205_MAX_FILES_TO_LOAD];
-	u16 firmware_id = pao->pci.subsys_device_id;
 	u32 temp;
 	int dsp = 0, i = 0;
 	u16 err = 0;
 
 	boot_code_id[0] = HPI_ADAPTER_ASI(0x6205);
 
-	/* special cases where firmware_id != subsys ID */
-	switch (firmware_id) {
+	boot_code_id[1] = pao->pci.pci_dev->subsystem_device;
+	boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(boot_code_id[1]);
+
+	/* fix up cases where bootcode id[1] != subsys id */
+	switch (boot_code_id[1]) {
 	case HPI_ADAPTER_FAMILY_ASI(0x5000):
-		boot_code_id[0] = firmware_id;
-		firmware_id = 0;
+		boot_code_id[0] = boot_code_id[1];
+		boot_code_id[1] = 0;
 		break;
 	case HPI_ADAPTER_FAMILY_ASI(0x5300):
 	case HPI_ADAPTER_FAMILY_ASI(0x5400):
 	case HPI_ADAPTER_FAMILY_ASI(0x6300):
-		firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6400);
+		boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6400);
 		break;
 	case HPI_ADAPTER_FAMILY_ASI(0x5600):
 	case HPI_ADAPTER_FAMILY_ASI(0x6500):
-		firmware_id = HPI_ADAPTER_FAMILY_ASI(0x6600);
+		boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x6600);
 		break;
 	case HPI_ADAPTER_FAMILY_ASI(0x8800):
-		firmware_id = HPI_ADAPTER_FAMILY_ASI(0x8900);
+		boot_code_id[1] = HPI_ADAPTER_FAMILY_ASI(0x8900);
+		break;
+	default:
 		break;
 	}
-	boot_code_id[1] = firmware_id;
 
 	/* reset DSP by writing a 1 to the WARMRESET bit */
 	temp = C6205_HDCR_WARMRESET;
@@ -1381,7 +1295,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	temp = ioread32(phw->prHSR);
 	if ((temp & (C6205_HSR_CFGERR | C6205_HSR_EEREAD)) !=
 		C6205_HSR_EEREAD)
-		return hpi6205_error(0, HPI6205_ERROR_6205_EEPROM);
+		return HPI6205_ERROR_6205_EEPROM;
 	temp |= 0x04;
 	/* disable PINTA interrupt */
 	iowrite32(temp, phw->prHSR);
@@ -1389,27 +1303,27 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	/* check control register reports PCI boot mode */
 	temp = ioread32(phw->prHDCR);
 	if (!(temp & C6205_HDCR_PCIBOOT))
-		return hpi6205_error(0, HPI6205_ERROR_6205_REG);
+		return HPI6205_ERROR_6205_REG;
 
-	/* try writing a couple of numbers to the DSP page register */
+	/* try writing a few numbers to the DSP page register */
 	/* and reading them back. */
-	temp = 1;
+	temp = 3;
 	iowrite32(temp, phw->prDSPP);
 	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
-		return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
+		return HPI6205_ERROR_6205_DSPPAGE;
 	temp = 2;
 	iowrite32(temp, phw->prDSPP);
 	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
-		return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
-	temp = 3;
+		return HPI6205_ERROR_6205_DSPPAGE;
+	temp = 1;
 	iowrite32(temp, phw->prDSPP);
 	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
-		return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
+		return HPI6205_ERROR_6205_DSPPAGE;
 	/* reset DSP page to the correct number */
 	temp = 0;
 	iowrite32(temp, phw->prDSPP);
 	if ((temp | C6205_DSPP_MAP1) != ioread32(phw->prDSPP))
-		return hpi6205_error(0, HPI6205_ERROR_6205_DSPPAGE);
+		return HPI6205_ERROR_6205_DSPPAGE;
 	phw->dsp_page = 0;
 
 	/* release 6713 from reset before 6205 is bootloaded.
@@ -1455,7 +1369,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			return err;
 
 		/* write the DSP code down into the DSPs memory */
-		dsp_code.ps_dev = pao->pci.p_os_data;
+		dsp_code.ps_dev = pao->pci.pci_dev;
 		err = hpi_dsp_code_open(boot_code_id[dsp], &dsp_code,
 			pos_error_code);
 		if (err)
@@ -1484,10 +1398,8 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			if (err)
 				break;
 			for (i = 0; i < (int)length; i++) {
-				err = boot_loader_write_mem32(pao, dsp,
-					address, *pcode);
-				if (err)
-					break;
+				boot_loader_write_mem32(pao, dsp, address,
+					*pcode);
 				/* dummy read every 4 words */
 				/* for 6205 advisory 1.4.4 */
 				if (i % 4 == 0)
@@ -1561,7 +1473,7 @@ static u16 adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 		host_mailbox_address_on_dsp = 0x80000000;
 		while ((physicalPC_iaddress != physicalPC_iaddress_verify)
 			&& time_out--) {
-			err = boot_loader_write_mem32(pao, 0,
+			boot_loader_write_mem32(pao, 0,
 				host_mailbox_address_on_dsp,
 				physicalPC_iaddress);
 			physicalPC_iaddress_verify =
@@ -1631,11 +1543,10 @@ static u32 boot_loader_read_mem32(struct hpi_adapter_obj *pao, int dsp_index,
 	return data;
 }
 
-static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index,
-	u32 address, u32 data)
+static void boot_loader_write_mem32(struct hpi_adapter_obj *pao,
+	int dsp_index, u32 address, u32 data)
 {
 	struct hpi_hw_obj *phw = pao->priv;
-	u16 err = 0;
 	__iomem u32 *p_data;
 	/*      u32 dwVerifyData=0; */
 
@@ -1675,15 +1586,11 @@ static u16 boot_loader_write_mem32(struct hpi_adapter_obj *pao, int dsp_index,
 
 		/* dummy read every 4 words for 6205 advisory 1.4.4 */
 		boot_loader_read_mem32(pao, 0, 0);
-	} else
-		err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
-	return err;
+	}
 }
 
 static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 {
-	u16 err = 0;
-
 	if (dsp_index == 0) {
 		u32 setting;
 
@@ -1711,8 +1618,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 		boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
 		if (setting != boot_loader_read_mem32(pao, dsp_index,
 				0x01800008))
-			return hpi6205_error(dsp_index,
-				HPI6205_ERROR_DSP_EMIF);
+			return HPI6205_ERROR_DSP_EMIF;
 
 		/* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
 		/* which occupies D15..0. 6713 starts at 27MHz, so need */
@@ -1725,8 +1631,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 		boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
 		if (setting != boot_loader_read_mem32(pao, dsp_index,
 				0x01800004))
-			return hpi6205_error(dsp_index,
-				HPI6205_ERROR_DSP_EMIF);
+			return HPI6205_ERROR_DSP_EMIF;
 
 		/* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
 		/* which occupies D15..0. 6713 starts at 27MHz, so need */
@@ -1738,8 +1643,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 		boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
 		if (setting != boot_loader_read_mem32(pao, dsp_index,
 				0x01800010))
-			return hpi6205_error(dsp_index,
-				HPI6205_ERROR_DSP_EMIF);
+			return HPI6205_ERROR_DSP_EMIF;
 
 		/* EMIF CE3 setup - 32 bit async. */
 		/* This is the PLD on the ASI5000 cards only */
@@ -1750,8 +1654,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 		boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
 		if (setting != boot_loader_read_mem32(pao, dsp_index,
 				0x01800014))
-			return hpi6205_error(dsp_index,
-				HPI6205_ERROR_DSP_EMIF);
+			return HPI6205_ERROR_DSP_EMIF;
 
 		/* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
 		/*  need to use this else DSP code crashes? */
@@ -1775,12 +1678,9 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 		read_data =
 			0xFFF7 & boot_loader_read_mem32(pao, 0, HPICL_ADDR);
 		if (write_data != read_data) {
-			err = hpi6205_error(dsp_index,
-				HPI6205_ERROR_C6713_HPIC);
 			HPI_DEBUG_LOG(ERROR, "HPICL %x %x\n", write_data,
 				read_data);
-
-			return err;
+			return HPI6205_ERROR_C6713_HPIC;
 		}
 		/* HPIA - walking ones test */
 		write_data = 1;
@@ -1798,11 +1698,9 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 						HPIAH_ADDR))
 				<< 16);
 			if (read_data != write_data) {
-				err = hpi6205_error(dsp_index,
-					HPI6205_ERROR_C6713_HPIA);
 				HPI_DEBUG_LOG(ERROR, "HPIA %x %x\n",
 					write_data, read_data);
-				return err;
+				return HPI6205_ERROR_C6713_HPIA;
 			}
 			write_data = write_data << 1;
 		}
@@ -1847,30 +1745,81 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
 		/* PLL should not be bypassed! */
 		if ((boot_loader_read_mem32(pao, dsp_index, 0x01B7C100) & 0xF)
 			!= 0x0001) {
-			err = hpi6205_error(dsp_index,
-				HPI6205_ERROR_C6713_PLL);
-			return err;
+			return HPI6205_ERROR_C6713_PLL;
 		}
 		/* setup C67x EMIF  (note this is the only use of
 		   BAR1 via BootLoader_WriteMem32) */
 		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_GCTL,
 			0x000034A8);
+
+		/* EMIF CE0 setup - 2Mx32 Sync DRAM
+		   31..28       Wr setup
+		   27..22       Wr strobe
+		   21..20       Wr hold
+		   19..16       Rd setup
+		   15..14       -
+		   13..8        Rd strobe
+		   7..4         MTYPE   0011            Sync DRAM 32bits
+		   3            Wr hold MSB
+		   2..0         Rd hold
+		 */
 		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_CE0,
 			0x00000030);
+
+		/* EMIF SDRAM Extension
+		   0x00
+		   31-21        0000b 0000b 000b
+		   20           WR2RD = 2cycles-1  = 1b
+
+		   19-18        WR2DEAC = 3cycle-1 = 10b
+		   17           WR2WR = 2cycle-1   = 1b
+		   16-15        R2WDQM = 4cycle-1  = 11b
+		   14-12        RD2WR = 6cycles-1  = 101b
+
+		   11-10        RD2DEAC = 4cycle-1 = 11b
+		   9            RD2RD = 2cycle-1   = 1b
+		   8-7          THZP = 3cycle-1    = 10b
+		   6-5          TWR  = 2cycle-1    = 01b (tWR = 17ns)
+		   4            TRRD = 2cycle      = 0b  (tRRD = 14ns)
+		   3-1          TRAS = 5cycle-1    = 100b (Tras=42ns)
+		   1            CAS latency = 3cyc = 1b
+		   (for Micron 2M32-7 operating at 100MHz)
+		 */
 		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMEXT,
 			0x001BDF29);
+
+		/* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
+		   31           -       0b       -
+		   30           SDBSZ   1b              4 bank
+		   29..28       SDRSZ   00b             11 row address pins
+
+		   27..26       SDCSZ   01b             8 column address pins
+		   25           RFEN    1b              refersh enabled
+		   24           INIT    1b              init SDRAM!
+
+		   23..20       TRCD    0001b                   (Trcd/Tcyc)-1 = (20/10)-1 = 1
+
+		   19..16       TRP     0001b                   (Trp/Tcyc)-1 = (20/10)-1 = 1
+
+		   15..12       TRC     0110b                   (Trc/Tcyc)-1 = (70/10)-1 = 6
+
+		   11..0        -       0000b 0000b 0000b
+		 */
 		boot_loader_write_mem32(pao, dsp_index, C6713_EMIF_SDRAMCTL,
-			0x47117000);
+			0x47116000);
+
+		/* SDRAM refresh timing
+		   Need 4,096 refresh cycles every 64ms = 15.625us = 1562cycles of 100MHz = 0x61A
+		 */
 		boot_loader_write_mem32(pao, dsp_index,
 			C6713_EMIF_SDRAMTIMING, 0x00000410);
 
 		hpios_delay_micro_seconds(1000);
 	} else if (dsp_index == 2) {
 		/* DSP 2 is a C6713 */
+	}
 
-	} else
-		err = hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
-	return err;
+	return 0;
 }
 
 static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
@@ -1896,7 +1845,7 @@ static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
 				test_addr);
 			if (data != test_data) {
 				HPI_DEBUG_LOG(VERBOSE,
-					"memtest error details  "
+					"Memtest error details  "
 					"%08x %08x %08x %i\n", test_addr,
 					test_data, data, dsp_index);
 				return 1;	/* error */
@@ -1916,7 +1865,7 @@ static u16 boot_loader_test_memory(struct hpi_adapter_obj *pao, int dsp_index,
 		data = boot_loader_read_mem32(pao, dsp_index, test_addr);
 		if (data != test_data) {
 			HPI_DEBUG_LOG(VERBOSE,
-				"memtest error details  "
+				"Memtest error details  "
 				"%08x %08x %08x %i\n", test_addr, test_data,
 				data, dsp_index);
 			return 1;	/* error */
@@ -1946,8 +1895,8 @@ static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
 			/* 64K data mem */
 			err = boot_loader_test_memory(pao, dsp_index,
 				0x80000000, 0x10000);
-	} else if ((dsp_index == 1) || (dsp_index == 2)) {
-		/* DSP 1&2 are a C6713 */
+	} else if (dsp_index == 1) {
+		/* DSP 1 is a C6713 */
 		/* 192K internal mem */
 		err = boot_loader_test_memory(pao, dsp_index, 0x00000000,
 			0x30000);
@@ -1955,11 +1904,10 @@ static u16 boot_loader_test_internal_memory(struct hpi_adapter_obj *pao,
 			/* 64K internal mem / L2 cache */
 			err = boot_loader_test_memory(pao, dsp_index,
 				0x00030000, 0x10000);
-	} else
-		return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
+	}
 
 	if (err)
-		return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_INTMEM);
+		return HPI6205_ERROR_DSP_INTMEM;
 	else
 		return 0;
 }
@@ -1972,24 +1920,23 @@ static u16 boot_loader_test_external_memory(struct hpi_adapter_obj *pao,
 
 	if (dsp_index == 0) {
 		/* only test for SDRAM if an ASI5000 card */
-		if (pao->pci.subsys_device_id == 0x5000) {
+		if (pao->pci.pci_dev->subsystem_device == 0x5000) {
 			/* DSP 0 is always C6205 */
 			dRAM_start_address = 0x00400000;
 			dRAM_size = 0x200000;
 			/*dwDRAMinc=1024; */
 		} else
 			return 0;
-	} else if ((dsp_index == 1) || (dsp_index == 2)) {
+	} else if (dsp_index == 1) {
 		/* DSP 1 is a C6713 */
 		dRAM_start_address = 0x80000000;
 		dRAM_size = 0x200000;
 		/*dwDRAMinc=1024; */
-	} else
-		return hpi6205_error(dsp_index, HPI6205_ERROR_BAD_DSPINDEX);
+	}
 
 	if (boot_loader_test_memory(pao, dsp_index, dRAM_start_address,
 			dRAM_size))
-		return hpi6205_error(dsp_index, HPI6205_ERROR_DSP_EXTMEM);
+		return HPI6205_ERROR_DSP_EXTMEM;
 	return 0;
 }
 
@@ -1998,28 +1945,25 @@ static u16 boot_loader_test_pld(struct hpi_adapter_obj *pao, int dsp_index)
 	u32 data = 0;
 	if (dsp_index == 0) {
 		/* only test for DSP0 PLD on ASI5000 card */
-		if (pao->pci.subsys_device_id == 0x5000) {
+		if (pao->pci.pci_dev->subsystem_device == 0x5000) {
 			/* PLD is located at CE3=0x03000000 */
 			data = boot_loader_read_mem32(pao, dsp_index,
 				0x03000008);
 			if ((data & 0xF) != 0x5)
-				return hpi6205_error(dsp_index,
-					HPI6205_ERROR_DSP_PLD);
+				return HPI6205_ERROR_DSP_PLD;
 			data = boot_loader_read_mem32(pao, dsp_index,
 				0x0300000C);
 			if ((data & 0xF) != 0xA)
-				return hpi6205_error(dsp_index,
-					HPI6205_ERROR_DSP_PLD);
+				return HPI6205_ERROR_DSP_PLD;
 		}
 	} else if (dsp_index == 1) {
 		/* DSP 1 is a C6713 */
-		if (pao->pci.subsys_device_id == 0x8700) {
+		if (pao->pci.pci_dev->subsystem_device == 0x8700) {
 			/* PLD is located at CE1=0x90000000 */
 			data = boot_loader_read_mem32(pao, dsp_index,
 				0x90000010);
 			if ((data & 0xFF) != 0xAA)
-				return hpi6205_error(dsp_index,
-					HPI6205_ERROR_DSP_PLD);
+				return HPI6205_ERROR_DSP_PLD;
 			/* 8713 - LED on */
 			boot_loader_write_mem32(pao, dsp_index, 0x90000000,
 				0x02);
@@ -2037,14 +1981,11 @@ static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
 	struct hpi_hw_obj *phw = pao->priv;
 	u32 data_transferred = 0;
 	u16 err = 0;
-#ifndef HPI6205_NO_HSR_POLL
-	u32 time_out;
-#endif
 	u32 temp2;
 	struct bus_master_interface *interface = phw->p_interface_buffer;
 
 	if (!p_data)
-		return HPI_ERROR_INVALID_DATA_TRANSFER;
+		return HPI_ERROR_INVALID_DATA_POINTER;
 
 	data_size &= ~3L;	/* round data_size down to nearest 4 bytes */
 
@@ -2064,14 +2005,10 @@ static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
 
 		interface->transfer_size_in_bytes = this_copy;
 
-#ifdef HPI6205_NO_HSR_POLL
 		/* DSP must change this back to nOperation */
 		interface->dsp_ack = H620_HIF_IDLE;
-#endif
-
 		send_dsp_command(phw, operation);
 
-#ifdef HPI6205_NO_HSR_POLL
 		temp2 = wait_dsp_ack(phw, operation, HPI6205_TIMEOUT);
 		HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
 			HPI6205_TIMEOUT - temp2, this_copy);
@@ -2079,45 +2016,11 @@ static short hpi6205_transfer_data(struct hpi_adapter_obj *pao, u8 *p_data,
 		if (!temp2) {
 			/* timed out */
 			HPI_DEBUG_LOG(ERROR,
-				"timed out waiting for " "state %d got %d\n",
+				"Timed out waiting for " "state %d got %d\n",
 				operation, interface->dsp_ack);
 
 			break;
 		}
-#else
-		/* spin waiting on the result */
-		time_out = HPI6205_TIMEOUT;
-		temp2 = 0;
-		while ((temp2 == 0) && time_out--) {
-			/* give 16k bus mastering transfer time to happen */
-			/*(16k / 132Mbytes/s = 122usec) */
-			hpios_delay_micro_seconds(20);
-			temp2 = ioread32(phw->prHSR);
-			temp2 &= C6205_HSR_INTSRC;
-		}
-		HPI_DEBUG_LOG(DEBUG, "spun %d times for data xfer of %d\n",
-			HPI6205_TIMEOUT - time_out, this_copy);
-		if (temp2 == C6205_HSR_INTSRC) {
-			HPI_DEBUG_LOG(VERBOSE,
-				"interrupt from HIF <data> OK\n");
-			/*
-			   if(interface->dwDspAck != nOperation) {
-			   HPI_DEBUG_LOG(DEBUG("interface->dwDspAck=%d,
-			   expected %d \n",
-			   interface->dwDspAck,nOperation);
-			   }
-			 */
-		}
-/* need to handle this differently... */
-		else {
-			HPI_DEBUG_LOG(ERROR,
-				"interrupt from HIF <data> BAD\n");
-			err = HPI_ERROR_DSP_HARDWARE;
-		}
-
-		/* reset the interrupt from the DSP */
-		iowrite32(C6205_HSR_INTSRC, phw->prHSR);
-#endif
 		if (operation == H620_HIF_GET_DATA)
 			memcpy(&p_data[data_transferred],
 				(void *)&interface->u.b_data[0], this_copy);
@@ -2174,31 +2077,39 @@ static unsigned int message_count;
 static u16 message_response_sequence(struct hpi_adapter_obj *pao,
 	struct hpi_message *phm, struct hpi_response *phr)
 {
-#ifndef HPI6205_NO_HSR_POLL
-	u32 temp2;
-#endif
 	u32 time_out, time_out2;
 	struct hpi_hw_obj *phw = pao->priv;
 	struct bus_master_interface *interface = phw->p_interface_buffer;
 	u16 err = 0;
 
 	message_count++;
+	if (phm->size > sizeof(interface->u)) {
+		phr->error = HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL;
+		phr->specific_error = sizeof(interface->u);
+		phr->size = sizeof(struct hpi_response_header);
+		HPI_DEBUG_LOG(ERROR,
+			"message len %d too big for buffer %zd \n", phm->size,
+			sizeof(interface->u));
+		return 0;
+	}
+
 	/* Assume buffer of type struct bus_master_interface
 	   is allocated "noncacheable" */
 
 	if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
 		HPI_DEBUG_LOG(DEBUG, "timeout waiting for idle\n");
-		return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT);
+		return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
 	}
-	interface->u.message_buffer = *phm;
+
+	memcpy(&interface->u.message_buffer, phm, phm->size);
 	/* signal we want a response */
 	send_dsp_command(phw, H620_HIF_GET_RESP);
 
 	time_out2 = wait_dsp_ack(phw, H620_HIF_GET_RESP, HPI6205_TIMEOUT);
 
-	if (time_out2 == 0) {
+	if (!time_out2) {
 		HPI_DEBUG_LOG(ERROR,
-			"(%u) timed out waiting for " "GET_RESP state [%x]\n",
+			"(%u) Timed out waiting for " "GET_RESP state [%x]\n",
 			message_count, interface->dsp_ack);
 	} else {
 		HPI_DEBUG_LOG(VERBOSE,
@@ -2208,58 +2119,38 @@ static u16 message_response_sequence(struct hpi_adapter_obj *pao,
 	/* spin waiting on HIF interrupt flag (end of msg process) */
 	time_out = HPI6205_TIMEOUT;
 
-#ifndef HPI6205_NO_HSR_POLL
-	temp2 = 0;
-	while ((temp2 == 0) && --time_out) {
-		temp2 = ioread32(phw->prHSR);
-		temp2 &= C6205_HSR_INTSRC;
-		hpios_delay_micro_seconds(1);
-	}
-	if (temp2 == C6205_HSR_INTSRC) {
-		rmb();	/* ensure we see latest value for dsp_ack */
-		if ((interface->dsp_ack != H620_HIF_GET_RESP)) {
-			HPI_DEBUG_LOG(DEBUG,
-				"(%u)interface->dsp_ack(0x%x) != "
-				"H620_HIF_GET_RESP, t=%u\n", message_count,
-				interface->dsp_ack,
-				HPI6205_TIMEOUT - time_out);
-		} else {
-			HPI_DEBUG_LOG(VERBOSE,
-				"(%u)int with GET_RESP after %u\n",
-				message_count, HPI6205_TIMEOUT - time_out);
+	/* read the result */
+	if (time_out) {
+		if (interface->u.response_buffer.size <= phr->size)
+			memcpy(phr, &interface->u.response_buffer,
+				interface->u.response_buffer.size);
+		else {
+			HPI_DEBUG_LOG(ERROR,
+				"response len %d too big for buffer %d\n",
+				interface->u.response_buffer.size, phr->size);
+			memcpy(phr, &interface->u.response_buffer,
+				sizeof(struct hpi_response_header));
+			phr->error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
+			phr->specific_error =
+				interface->u.response_buffer.size;
+			phr->size = sizeof(struct hpi_response_header);
 		}
-
-	} else {
-		/* can we do anything else in response to the error ? */
-		HPI_DEBUG_LOG(ERROR,
-			"interrupt from HIF module BAD (function %x)\n",
-			phm->function);
 	}
-
-	/* reset the interrupt from the DSP */
-	iowrite32(C6205_HSR_INTSRC, phw->prHSR);
-#endif
-
-	/* read the result */
-	if (time_out != 0)
-		*phr = interface->u.response_buffer;
-
 	/* set interface back to idle */
 	send_dsp_command(phw, H620_HIF_IDLE);
 
-	if ((time_out == 0) || (time_out2 == 0)) {
+	if (!time_out || !time_out2) {
 		HPI_DEBUG_LOG(DEBUG, "something timed out!\n");
-		return hpi6205_error(0, HPI6205_ERROR_MSG_RESP_TIMEOUT);
+		return HPI6205_ERROR_MSG_RESP_TIMEOUT;
 	}
 	/* special case for adapter close - */
 	/* wait for the DSP to indicate it is idle */
 	if (phm->function == HPI_ADAPTER_CLOSE) {
 		if (!wait_dsp_ack(phw, H620_HIF_IDLE, HPI6205_TIMEOUT)) {
 			HPI_DEBUG_LOG(DEBUG,
-				"timeout waiting for idle "
+				"Timeout waiting for idle "
 				"(on adapter_close)\n");
-			return hpi6205_error(0,
-				HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT);
+			return HPI6205_ERROR_MSG_RESP_IDLE_TIMEOUT;
 		}
 	}
 	err = hpi_validate_response(phm, phr);
@@ -2279,7 +2170,13 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 	/* maybe an error response */
 	if (err) {
 		/* something failed in the HPI/DSP interface */
-		phr->error = err;
+		if (err >= HPI_ERROR_BACKEND_BASE) {
+			phr->error = HPI_ERROR_DSP_COMMUNICATION;
+			phr->specific_error = err;
+		} else {
+			phr->error = err;
+		}
+
 		pao->dsp_crashed++;
 
 		/* just the header of the response is valid */
diff --git a/sound/pci/asihpi/hpi6205.h b/sound/pci/asihpi/hpi6205.h
index 1adae08..df2f02c 100644
--- a/sound/pci/asihpi/hpi6205.h
+++ b/sound/pci/asihpi/hpi6205.h
@@ -25,9 +25,6 @@ Copyright AudioScience, Inc., 2003
 #ifndef _HPI6205_H_
 #define _HPI6205_H_
 
-/* transitional conditional compile shared between host and DSP */
-/* #define HPI6205_NO_HSR_POLL */
-
 #include "hpi_internal.h"
 
 /***********************************************************
@@ -78,8 +75,8 @@ struct bus_master_interface {
 	u32 dsp_ack;
 	u32 transfer_size_in_bytes;
 	union {
-		struct hpi_message message_buffer;
-		struct hpi_response response_buffer;
+		struct hpi_message_header message_buffer;
+		struct hpi_response_header response_buffer;
 		u8 b_data[HPI6205_SIZEOF_DATA];
 	} u;
 	struct controlcache_6205 control_cache;
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
index 16f502d..af678be 100644
--- a/sound/pci/asihpi/hpi_internal.h
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -28,7 +28,7 @@ HPI internal definitions
 /** maximum number of memory regions mapped to an adapter */
 #define HPI_MAX_ADAPTER_MEM_SPACES (2)
 
-/* Each OS needs its own hpios.h, or specific define as above */
+/* Each OS needs its own hpios.h */
 #include "hpios.h"
 
 /* physical memory allocation */
@@ -49,7 +49,7 @@ HpiOs_LockedMem_GetPyhsAddr() will always succed on the returned handle.
 */
 u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_locked_mem_handle,
 							   /**< memory handle */
-	u32 size, /**< size in bytes to allocate */
+	u32 size, /**< Size in bytes to allocate */
 	struct pci_dev *p_os_reference
 	/**< OS specific data required for memory allocation */
 	);
@@ -96,41 +96,6 @@ typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *);
 #define compile_time_assert(cond, msg) \
     typedef char ASSERT_##msg[(cond) ? 1 : -1]
 
-/*/////////////////////////////////////////////////////////////////////////// */
-/* Private HPI Entity related definitions                                     */
-
-#define STR_SIZE_FIELD_MAX 65535U
-#define STR_TYPE_FIELD_MAX 255U
-#define STR_ROLE_FIELD_MAX 255U
-
-struct hpi_entity_str {
-	u16 size;
-	u8 type;
-	u8 role;
-};
-
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4200)
-#endif
-
-struct hpi_entity {
-	struct hpi_entity_str header;
-#if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008))
-	/* DSP C6000 compiler v6.0.8 and lower
-	   do not support  flexible array member */
-	u8 value[];
-#else
-	/* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */
-#define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE
-	u8 value[1];
-#endif
-};
-
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
-
 /******************************************* bus types */
 enum HPI_BUSES {
 	HPI_BUS_ISAPNP = 1,
@@ -139,206 +104,155 @@ enum HPI_BUSES {
 	HPI_BUS_NET = 4
 };
 
+enum HPI_SUBSYS_OPTIONS {
+	/* 0, 256 are invalid, 1..255 reserved for global options */
+	HPI_SUBSYS_OPT_NET_ENABLE = 257,
+	HPI_SUBSYS_OPT_NET_BROADCAST = 258,
+	HPI_SUBSYS_OPT_NET_UNICAST = 259,
+	HPI_SUBSYS_OPT_NET_ADDR = 260,
+	HPI_SUBSYS_OPT_NET_MASK = 261,
+	HPI_SUBSYS_OPT_NET_ADAPTER_ADDRESS_ADD = 262
+};
+
+/** Volume flags
+*/
+enum HPI_VOLUME_FLAGS {
+	/** Set if the volume control is muted */
+	HPI_VOLUME_FLAG_MUTED = (1 << 0),
+	/** Set if the volume control has a mute function */
+	HPI_VOLUME_FLAG_HAS_MUTE = (1 << 1),
+	/** Set if volume control can do autofading */
+	HPI_VOLUME_FLAG_HAS_AUTOFADE = (1 << 2)
+		/* Note Flags >= (1<<8) are for DSP internal use only */
+};
+
 /******************************************* CONTROL ATTRIBUTES ****/
 /* (in order of control type ID */
 
 /* This allows for 255 control types, 256 unique attributes each */
-#define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
+#define HPI_CTL_ATTR(ctl, ai) ((HPI_CONTROL_##ctl << 8) + ai)
 
 /* Get the sub-index of the attribute for a control type */
-#define HPI_CTL_ATTR_INDEX(i) (i&0xff)
+#define HPI_CTL_ATTR_INDEX(i) (i & 0xff)
 
 /* Extract the control from the control attribute */
-#define HPI_CTL_ATTR_CONTROL(i) (i>>8)
-
-/* Generic control attributes.  */
-
-/** Enable a control.
-0=disable, 1=enable
-\note generic to all mixer plugins?
-*/
-#define HPI_GENERIC_ENABLE HPI_CTL_ATTR(GENERIC, 1)
+#define HPI_CTL_ATTR_CONTROL(i) (i >> 8)
 
 /** Enable event generation for a control.
 0=disable, 1=enable
 \note generic to all controls that can generate events
 */
-#define HPI_GENERIC_EVENT_ENABLE HPI_CTL_ATTR(GENERIC, 2)
-
-/* Volume Control attributes */
-#define HPI_VOLUME_GAIN                 HPI_CTL_ATTR(VOLUME, 1)
-#define HPI_VOLUME_AUTOFADE             HPI_CTL_ATTR(VOLUME, 2)
-
-/** For HPI_ControlQuery() to get the number of channels of a volume control*/
-#define HPI_VOLUME_NUM_CHANNELS         HPI_CTL_ATTR(VOLUME, 6)
-#define HPI_VOLUME_RANGE                HPI_CTL_ATTR(VOLUME, 10)
-
-/** Level Control attributes */
-#define HPI_LEVEL_GAIN                  HPI_CTL_ATTR(LEVEL, 1)
-#define HPI_LEVEL_RANGE                 HPI_CTL_ATTR(LEVEL, 10)
-
-/* Meter Control attributes */
-/** return RMS signal level */
-#define HPI_METER_RMS                   HPI_CTL_ATTR(METER, 1)
-/** return peak signal level */
-#define HPI_METER_PEAK                  HPI_CTL_ATTR(METER, 2)
-/** ballistics for ALL rms meters on adapter */
-#define HPI_METER_RMS_BALLISTICS        HPI_CTL_ATTR(METER, 3)
-/** ballistics for ALL peak meters on adapter */
-#define HPI_METER_PEAK_BALLISTICS       HPI_CTL_ATTR(METER, 4)
-
-/** For HPI_ControlQuery() to get the number of channels of a meter control*/
-#define HPI_METER_NUM_CHANNELS          HPI_CTL_ATTR(METER, 5)
-
-/* Multiplexer control attributes */
-#define HPI_MULTIPLEXER_SOURCE          HPI_CTL_ATTR(MULTIPLEXER, 1)
-#define HPI_MULTIPLEXER_QUERYSOURCE     HPI_CTL_ATTR(MULTIPLEXER, 2)
-
-/** AES/EBU transmitter control attributes */
-/** AESEBU or SPDIF */
-#define HPI_AESEBUTX_FORMAT             HPI_CTL_ATTR(AESEBUTX, 1)
-#define HPI_AESEBUTX_SAMPLERATE         HPI_CTL_ATTR(AESEBUTX, 3)
-#define HPI_AESEBUTX_CHANNELSTATUS      HPI_CTL_ATTR(AESEBUTX, 4)
-#define HPI_AESEBUTX_USERDATA           HPI_CTL_ATTR(AESEBUTX, 5)
-
-/** AES/EBU receiver control attributes */
-#define HPI_AESEBURX_FORMAT             HPI_CTL_ATTR(AESEBURX, 1)
-#define HPI_AESEBURX_ERRORSTATUS        HPI_CTL_ATTR(AESEBURX, 2)
-#define HPI_AESEBURX_SAMPLERATE         HPI_CTL_ATTR(AESEBURX, 3)
-#define HPI_AESEBURX_CHANNELSTATUS      HPI_CTL_ATTR(AESEBURX, 4)
-#define HPI_AESEBURX_USERDATA           HPI_CTL_ATTR(AESEBURX, 5)
-
-/** \defgroup tuner_defs Tuners
-\{
-*/
-/** \defgroup tuner_attrs Tuner control attributes
-\{
-*/
-#define HPI_TUNER_BAND                  HPI_CTL_ATTR(TUNER, 1)
-#define HPI_TUNER_FREQ                  HPI_CTL_ATTR(TUNER, 2)
-#define HPI_TUNER_LEVEL                 HPI_CTL_ATTR(TUNER, 3)
-#define HPI_TUNER_AUDIOMUTE             HPI_CTL_ATTR(TUNER, 4)
-/* use TUNER_STATUS instead */
-#define HPI_TUNER_VIDEO_STATUS          HPI_CTL_ATTR(TUNER, 5)
-#define HPI_TUNER_GAIN                  HPI_CTL_ATTR(TUNER, 6)
-#define HPI_TUNER_STATUS                HPI_CTL_ATTR(TUNER, 7)
-#define HPI_TUNER_MODE                  HPI_CTL_ATTR(TUNER, 8)
-/** RDS data. */
-#define HPI_TUNER_RDS                   HPI_CTL_ATTR(TUNER, 9)
-/** Audio pre-emphasis. */
-#define HPI_TUNER_DEEMPHASIS            HPI_CTL_ATTR(TUNER, 10)
-/** HD Radio tuner program control. */
-#define HPI_TUNER_PROGRAM               HPI_CTL_ATTR(TUNER, 11)
-/** HD Radio tuner digital signal quality. */
-#define HPI_TUNER_HDRADIO_SIGNAL_QUALITY        HPI_CTL_ATTR(TUNER, 12)
-/** HD Radio SDK firmware version. */
-#define HPI_TUNER_HDRADIO_SDK_VERSION   HPI_CTL_ATTR(TUNER, 13)
-/** HD Radio DSP firmware version. */
-#define HPI_TUNER_HDRADIO_DSP_VERSION   HPI_CTL_ATTR(TUNER, 14)
-/** HD Radio signal blend (force analog, or automatic). */
-#define HPI_TUNER_HDRADIO_BLEND         HPI_CTL_ATTR(TUNER, 15)
-
-/** \} */
-
-/** \defgroup pads_attrs Tuner PADs control attributes
-\{
-*/
-/** The text string containing the station/channel combination. */
-#define HPI_PAD_CHANNEL_NAME            HPI_CTL_ATTR(PAD, 1)
-/** The text string containing the artist. */
-#define HPI_PAD_ARTIST                  HPI_CTL_ATTR(PAD, 2)
-/** The text string containing the title. */
-#define HPI_PAD_TITLE                   HPI_CTL_ATTR(PAD, 3)
-/** The text string containing the comment. */
-#define HPI_PAD_COMMENT                 HPI_CTL_ATTR(PAD, 4)
-/** The integer containing the PTY code. */
-#define HPI_PAD_PROGRAM_TYPE            HPI_CTL_ATTR(PAD, 5)
-/** The integer containing the program identification. */
-#define HPI_PAD_PROGRAM_ID              HPI_CTL_ATTR(PAD, 6)
-/** The integer containing whether traffic information is supported.
-Contains either 1 or 0. */
-#define HPI_PAD_TA_SUPPORT              HPI_CTL_ATTR(PAD, 7)
-/** The integer containing whether traffic announcement is in progress.
-Contains either 1 or 0. */
-#define HPI_PAD_TA_ACTIVE               HPI_CTL_ATTR(PAD, 8)
-/** \} */
-/** \} */
-
-/* VOX control attributes */
-#define HPI_VOX_THRESHOLD               HPI_CTL_ATTR(VOX, 1)
-
-/*?? channel mode used hpi_multiplexer_source attribute == 1 */
-#define HPI_CHANNEL_MODE_MODE HPI_CTL_ATTR(CHANNEL_MODE, 1)
-
-/** \defgroup channel_modes Channel Modes
-Used for HPI_ChannelModeSet/Get()
-\{
+
+/** Unique identifiers for every control attribute
 */
-/** Left channel out = left channel in, Right channel out = right channel in. */
-#define HPI_CHANNEL_MODE_NORMAL                 1
-/** Left channel out = right channel in, Right channel out = left channel in. */
-#define HPI_CHANNEL_MODE_SWAP                   2
-/** Left channel out = left channel in, Right channel out = left channel in. */
-#define HPI_CHANNEL_MODE_LEFT_TO_STEREO         3
-/** Left channel out = right channel in, Right channel out = right channel in.*/
-#define HPI_CHANNEL_MODE_RIGHT_TO_STEREO        4
-/** Left channel out = (left channel in + right channel in)/2,
-    Right channel out = mute. */
-#define HPI_CHANNEL_MODE_STEREO_TO_LEFT         5
-/** Left channel out = mute,
-    Right channel out = (right channel in + left channel in)/2. */
-#define HPI_CHANNEL_MODE_STEREO_TO_RIGHT        6
-#define HPI_CHANNEL_MODE_LAST                   6
-/** \} */
-
-/* Bitstream control set attributes */
-#define HPI_BITSTREAM_DATA_POLARITY     HPI_CTL_ATTR(BITSTREAM, 1)
-#define HPI_BITSTREAM_CLOCK_EDGE        HPI_CTL_ATTR(BITSTREAM, 2)
-#define HPI_BITSTREAM_CLOCK_SOURCE      HPI_CTL_ATTR(BITSTREAM, 3)
+enum HPI_CONTROL_ATTRIBUTES {
+	HPI_GENERIC_ENABLE = HPI_CTL_ATTR(GENERIC, 1),
+	HPI_GENERIC_EVENT_ENABLE = HPI_CTL_ATTR(GENERIC, 2),
+
+	HPI_VOLUME_GAIN = HPI_CTL_ATTR(VOLUME, 1),
+	HPI_VOLUME_AUTOFADE = HPI_CTL_ATTR(VOLUME, 2),
+	HPI_VOLUME_MUTE = HPI_CTL_ATTR(VOLUME, 3),
+	HPI_VOLUME_GAIN_AND_FLAGS = HPI_CTL_ATTR(VOLUME, 4),
+	HPI_VOLUME_NUM_CHANNELS = HPI_CTL_ATTR(VOLUME, 6),
+	HPI_VOLUME_RANGE = HPI_CTL_ATTR(VOLUME, 10),
+
+	HPI_METER_RMS = HPI_CTL_ATTR(METER, 1),
+	HPI_METER_PEAK = HPI_CTL_ATTR(METER, 2),
+	HPI_METER_RMS_BALLISTICS = HPI_CTL_ATTR(METER, 3),
+	HPI_METER_PEAK_BALLISTICS = HPI_CTL_ATTR(METER, 4),
+	HPI_METER_NUM_CHANNELS = HPI_CTL_ATTR(METER, 5),
+
+	HPI_MULTIPLEXER_SOURCE = HPI_CTL_ATTR(MULTIPLEXER, 1),
+	HPI_MULTIPLEXER_QUERYSOURCE = HPI_CTL_ATTR(MULTIPLEXER, 2),
+
+	HPI_AESEBUTX_FORMAT = HPI_CTL_ATTR(AESEBUTX, 1),
+	HPI_AESEBUTX_SAMPLERATE = HPI_CTL_ATTR(AESEBUTX, 3),
+	HPI_AESEBUTX_CHANNELSTATUS = HPI_CTL_ATTR(AESEBUTX, 4),
+	HPI_AESEBUTX_USERDATA = HPI_CTL_ATTR(AESEBUTX, 5),
+
+	HPI_AESEBURX_FORMAT = HPI_CTL_ATTR(AESEBURX, 1),
+	HPI_AESEBURX_ERRORSTATUS = HPI_CTL_ATTR(AESEBURX, 2),
+	HPI_AESEBURX_SAMPLERATE = HPI_CTL_ATTR(AESEBURX, 3),
+	HPI_AESEBURX_CHANNELSTATUS = HPI_CTL_ATTR(AESEBURX, 4),
+	HPI_AESEBURX_USERDATA = HPI_CTL_ATTR(AESEBURX, 5),
+
+	HPI_LEVEL_GAIN = HPI_CTL_ATTR(LEVEL, 1),
+	HPI_LEVEL_RANGE = HPI_CTL_ATTR(LEVEL, 10),
+
+	HPI_TUNER_BAND = HPI_CTL_ATTR(TUNER, 1),
+	HPI_TUNER_FREQ = HPI_CTL_ATTR(TUNER, 2),
+	HPI_TUNER_LEVEL_AVG = HPI_CTL_ATTR(TUNER, 3),
+	HPI_TUNER_LEVEL_RAW = HPI_CTL_ATTR(TUNER, 4),
+	HPI_TUNER_SNR = HPI_CTL_ATTR(TUNER, 5),
+	HPI_TUNER_GAIN = HPI_CTL_ATTR(TUNER, 6),
+	HPI_TUNER_STATUS = HPI_CTL_ATTR(TUNER, 7),
+	HPI_TUNER_MODE = HPI_CTL_ATTR(TUNER, 8),
+	HPI_TUNER_RDS = HPI_CTL_ATTR(TUNER, 9),
+	HPI_TUNER_DEEMPHASIS = HPI_CTL_ATTR(TUNER, 10),
+	HPI_TUNER_PROGRAM = HPI_CTL_ATTR(TUNER, 11),
+	HPI_TUNER_HDRADIO_SIGNAL_QUALITY = HPI_CTL_ATTR(TUNER, 12),
+	HPI_TUNER_HDRADIO_SDK_VERSION = HPI_CTL_ATTR(TUNER, 13),
+	HPI_TUNER_HDRADIO_DSP_VERSION = HPI_CTL_ATTR(TUNER, 14),
+	HPI_TUNER_HDRADIO_BLEND = HPI_CTL_ATTR(TUNER, 15),
+
+	HPI_VOX_THRESHOLD = HPI_CTL_ATTR(VOX, 1),
+
+	HPI_CHANNEL_MODE_MODE = HPI_CTL_ATTR(CHANNEL_MODE, 1),
+
+	HPI_BITSTREAM_DATA_POLARITY = HPI_CTL_ATTR(BITSTREAM, 1),
+	HPI_BITSTREAM_CLOCK_EDGE = HPI_CTL_ATTR(BITSTREAM, 2),
+	HPI_BITSTREAM_CLOCK_SOURCE = HPI_CTL_ATTR(BITSTREAM, 3),
+	HPI_BITSTREAM_ACTIVITY = HPI_CTL_ATTR(BITSTREAM, 4),
+
+	HPI_SAMPLECLOCK_SOURCE = HPI_CTL_ATTR(SAMPLECLOCK, 1),
+	HPI_SAMPLECLOCK_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 2),
+	HPI_SAMPLECLOCK_SOURCE_INDEX = HPI_CTL_ATTR(SAMPLECLOCK, 3),
+	HPI_SAMPLECLOCK_LOCAL_SAMPLERATE = HPI_CTL_ATTR(SAMPLECLOCK, 4),
+	HPI_SAMPLECLOCK_AUTO = HPI_CTL_ATTR(SAMPLECLOCK, 5),
+	HPI_SAMPLECLOCK_LOCAL_LOCK = HPI_CTL_ATTR(SAMPLECLOCK, 6),
+
+	HPI_MICROPHONE_PHANTOM_POWER = HPI_CTL_ATTR(MICROPHONE, 1),
+
+	HPI_EQUALIZER_NUM_FILTERS = HPI_CTL_ATTR(EQUALIZER, 1),
+	HPI_EQUALIZER_FILTER = HPI_CTL_ATTR(EQUALIZER, 2),
+	HPI_EQUALIZER_COEFFICIENTS = HPI_CTL_ATTR(EQUALIZER, 3),
+
+	HPI_COMPANDER_PARAMS = HPI_CTL_ATTR(COMPANDER, 1),
+	HPI_COMPANDER_MAKEUPGAIN = HPI_CTL_ATTR(COMPANDER, 2),
+	HPI_COMPANDER_THRESHOLD = HPI_CTL_ATTR(COMPANDER, 3),
+	HPI_COMPANDER_RATIO = HPI_CTL_ATTR(COMPANDER, 4),
+	HPI_COMPANDER_ATTACK = HPI_CTL_ATTR(COMPANDER, 5),
+	HPI_COMPANDER_DECAY = HPI_CTL_ATTR(COMPANDER, 6),
+
+	HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1),
+	HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2),
+	HPI_COBRANET_SET_DATA = HPI_CTL_ATTR(COBRANET, 3),
+	HPI_COBRANET_GET_DATA = HPI_CTL_ATTR(COBRANET, 4),
+	HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5),
+	HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6),
+	HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7),
+
+	HPI_TONEDETECTOR_THRESHOLD = HPI_CTL_ATTR(TONEDETECTOR, 1),
+	HPI_TONEDETECTOR_STATE = HPI_CTL_ATTR(TONEDETECTOR, 2),
+	HPI_TONEDETECTOR_FREQUENCY = HPI_CTL_ATTR(TONEDETECTOR, 3),
+
+	HPI_SILENCEDETECTOR_THRESHOLD = HPI_CTL_ATTR(SILENCEDETECTOR, 1),
+	HPI_SILENCEDETECTOR_STATE = HPI_CTL_ATTR(SILENCEDETECTOR, 2),
+	HPI_SILENCEDETECTOR_DELAY = HPI_CTL_ATTR(SILENCEDETECTOR, 3),
+
+	HPI_PAD_CHANNEL_NAME = HPI_CTL_ATTR(PAD, 1),
+	HPI_PAD_ARTIST = HPI_CTL_ATTR(PAD, 2),
+	HPI_PAD_TITLE = HPI_CTL_ATTR(PAD, 3),
+	HPI_PAD_COMMENT = HPI_CTL_ATTR(PAD, 4),
+	HPI_PAD_PROGRAM_TYPE = HPI_CTL_ATTR(PAD, 5),
+	HPI_PAD_PROGRAM_ID = HPI_CTL_ATTR(PAD, 6),
+	HPI_PAD_TA_SUPPORT = HPI_CTL_ATTR(PAD, 7),
+	HPI_PAD_TA_ACTIVE = HPI_CTL_ATTR(PAD, 8)
+};
 
 #define HPI_POLARITY_POSITIVE           0
 #define HPI_POLARITY_NEGATIVE           1
 
-/* Bitstream control get attributes */
-#define HPI_BITSTREAM_ACTIVITY          1
-
-/* SampleClock control attributes */
-#define HPI_SAMPLECLOCK_SOURCE                  HPI_CTL_ATTR(SAMPLECLOCK, 1)
-#define HPI_SAMPLECLOCK_SAMPLERATE              HPI_CTL_ATTR(SAMPLECLOCK, 2)
-#define HPI_SAMPLECLOCK_SOURCE_INDEX            HPI_CTL_ATTR(SAMPLECLOCK, 3)
-#define HPI_SAMPLECLOCK_LOCAL_SAMPLERATE\
-	HPI_CTL_ATTR(SAMPLECLOCK, 4)
-#define HPI_SAMPLECLOCK_AUTO                    HPI_CTL_ATTR(SAMPLECLOCK, 5)
-#define HPI_SAMPLECLOCK_LOCAL_LOCK                      HPI_CTL_ATTR(SAMPLECLOCK, 6)
-
-/* Microphone control attributes */
-#define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1)
-
-/** Equalizer control attributes */
-/** Used to get number of filters in an EQ. (Can't set) */
-#define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1)
-/** Set/get the filter by type, freq, Q, gain */
-#define HPI_EQUALIZER_FILTER HPI_CTL_ATTR(EQUALIZER, 2)
-/** Get the biquad coefficients */
-#define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3)
-
-/* Note compander also uses HPI_GENERIC_ENABLE */
-#define HPI_COMPANDER_PARAMS     HPI_CTL_ATTR(COMPANDER, 1)
-#define HPI_COMPANDER_MAKEUPGAIN HPI_CTL_ATTR(COMPANDER, 2)
-#define HPI_COMPANDER_THRESHOLD  HPI_CTL_ATTR(COMPANDER, 3)
-#define HPI_COMPANDER_RATIO      HPI_CTL_ATTR(COMPANDER, 4)
-#define HPI_COMPANDER_ATTACK     HPI_CTL_ATTR(COMPANDER, 5)
-#define HPI_COMPANDER_DECAY      HPI_CTL_ATTR(COMPANDER, 6)
-
-/* Cobranet control attributes. */
-#define HPI_COBRANET_SET         HPI_CTL_ATTR(COBRANET, 1)
-#define HPI_COBRANET_GET         HPI_CTL_ATTR(COBRANET, 2)
-#define HPI_COBRANET_SET_DATA    HPI_CTL_ATTR(COBRANET, 3)
-#define HPI_COBRANET_GET_DATA    HPI_CTL_ATTR(COBRANET, 4)
-#define HPI_COBRANET_GET_STATUS  HPI_CTL_ATTR(COBRANET, 5)
-#define HPI_COBRANET_SEND_PACKET HPI_CTL_ATTR(COBRANET, 6)
-#define HPI_COBRANET_GET_PACKET  HPI_CTL_ATTR(COBRANET, 7)
-
 /*------------------------------------------------------------
  Cobranet Chip Bridge - copied from HMI.H
 ------------------------------------------------------------*/
@@ -395,69 +309,22 @@ Used for HPI_ChannelModeSet/Get()
 
 #define HPI_ETHERNET_UDP_PORT (44600)	/*!< UDP messaging port */
 
-/** Base network time out is set to 100 milli-seconds. */
-#define HPI_ETHERNET_TIMEOUT_MS      (100)
-
-/** \defgroup tonedet_attr Tonedetector attributes
-\{
-Used by HPI_ToneDetector_Set() and HPI_ToneDetector_Get()
-*/
-
-/** Set the threshold level of a tonedetector,
-Threshold is a -ve number in units of dB/100,
-*/
-#define HPI_TONEDETECTOR_THRESHOLD HPI_CTL_ATTR(TONEDETECTOR, 1)
-
-/** Get the current state of tonedetection
-The result is a bitmap of detected tones.  pairs of bits represent the left
-and right channels, with left channel in LSB.
-The lowest frequency detector state is in the LSB
-*/
-#define HPI_TONEDETECTOR_STATE HPI_CTL_ATTR(TONEDETECTOR, 2)
-
-/** Get the frequency of a tonedetector band.
-*/
-#define HPI_TONEDETECTOR_FREQUENCY HPI_CTL_ATTR(TONEDETECTOR, 3)
-
-/**\}*/
+/** Default network timeout in milli-seconds. */
+#define HPI_ETHERNET_TIMEOUT_MS 500
 
-/** \defgroup silencedet_attr SilenceDetector attributes
-\{
-*/
-
-/** Get the current state of tonedetection
-The result is a bitmap with 1s for silent channels. Left channel is in LSB
-*/
-#define HPI_SILENCEDETECTOR_STATE \
-  HPI_CTL_ATTR(SILENCEDETECTOR, 2)
-
-/** Set the threshold level of a SilenceDetector,
-Threshold is a -ve number in units of dB/100,
-*/
-#define HPI_SILENCEDETECTOR_THRESHOLD \
-  HPI_CTL_ATTR(SILENCEDETECTOR, 1)
-
-/** get/set the silence time before the detector triggers
-*/
-#define HPI_SILENCEDETECTOR_DELAY \
-       HPI_CTL_ATTR(SILENCEDETECTOR, 3)
-
-/**\}*/
-
-/* Locked memory buffer alloc/free phases */
-/** use one message to allocate or free physical memory */
-#define HPI_BUFFER_CMD_EXTERNAL                 0
-/** alloc physical memory */
-#define HPI_BUFFER_CMD_INTERNAL_ALLOC           1
-/** send physical memory address to adapter */
-#define HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER    2
-/** notify adapter to stop using physical buffer */
-#define HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER   3
-/** free physical buffer */
-#define HPI_BUFFER_CMD_INTERNAL_FREE            4
-
-/******************************************* CONTROLX ATTRIBUTES ****/
-/* NOTE: All controlx attributes must be unique, unlike control attributes */
+/** Locked memory buffer alloc/free phases */
+enum HPI_BUFFER_CMDS {
+	/** use one message to allocate or free physical memory */
+	HPI_BUFFER_CMD_EXTERNAL = 0,
+	/** alloc physical memory */
+	HPI_BUFFER_CMD_INTERNAL_ALLOC = 1,
+	/** send physical memory address to adapter */
+	HPI_BUFFER_CMD_INTERNAL_GRANTADAPTER = 2,
+	/** notify adapter to stop using physical buffer */
+	HPI_BUFFER_CMD_INTERNAL_REVOKEADAPTER = 3,
+	/** free physical buffer */
+	HPI_BUFFER_CMD_INTERNAL_FREE = 4
+};
 
 /*****************************************************************************/
 /*****************************************************************************/
@@ -482,6 +349,12 @@ Threshold is a -ve number in units of dB/100,
 #define HPI_USB_W2K_TAG                 0x57495341	/* "ASIW"       */
 #define HPI_USB_LINUX_TAG               0x4C495341	/* "ASIL"       */
 
+/** Invalid Adapter index
+Used in HPI messages that are not addressed to a specific adapter
+Used in DLL to indicate device not present
+*/
+#define HPI_ADAPTER_INDEX_INVALID 0xFFFF
+
 /** First 2 hex digits define the adapter family */
 #define HPI_ADAPTER_FAMILY_MASK         0xff00
 #define HPI_MODULE_FAMILY_MASK          0xfff0
@@ -490,178 +363,185 @@ Threshold is a -ve number in units of dB/100,
 #define HPI_MODULE_FAMILY_ASI(f)   (f & HPI_MODULE_FAMILY_MASK)
 #define HPI_ADAPTER_ASI(f)   (f)
 
-/******************************************* message types */
-#define HPI_TYPE_MESSAGE                        1
-#define HPI_TYPE_RESPONSE                       2
-#define HPI_TYPE_DATA                           3
-#define HPI_TYPE_SSX2BYPASS_MESSAGE             4
-
-/******************************************* object types */
-#define HPI_OBJ_SUBSYSTEM                       1
-#define HPI_OBJ_ADAPTER                         2
-#define HPI_OBJ_OSTREAM                         3
-#define HPI_OBJ_ISTREAM                         4
-#define HPI_OBJ_MIXER                           5
-#define HPI_OBJ_NODE                            6
-#define HPI_OBJ_CONTROL                         7
-#define HPI_OBJ_NVMEMORY                        8
-#define HPI_OBJ_GPIO                            9
-#define HPI_OBJ_WATCHDOG                        10
-#define HPI_OBJ_CLOCK                           11
-#define HPI_OBJ_PROFILE                         12
-#define HPI_OBJ_CONTROLEX                       13
-#define HPI_OBJ_ASYNCEVENT                      14
-
-#define HPI_OBJ_MAXINDEX                        14
-
-/******************************************* methods/functions */
-
-#define HPI_OBJ_FUNCTION_SPACING        0x100
-#define HPI_MAKE_INDEX(obj, index) (obj * HPI_OBJ_FUNCTION_SPACING + index)
+enum HPI_MESSAGE_TYPES {
+	HPI_TYPE_MESSAGE = 1,
+	HPI_TYPE_RESPONSE = 2,
+	HPI_TYPE_DATA = 3,
+	HPI_TYPE_SSX2BYPASS_MESSAGE = 4
+};
+
+enum HPI_OBJECT_TYPES {
+	HPI_OBJ_SUBSYSTEM = 1,
+	HPI_OBJ_ADAPTER = 2,
+	HPI_OBJ_OSTREAM = 3,
+	HPI_OBJ_ISTREAM = 4,
+	HPI_OBJ_MIXER = 5,
+	HPI_OBJ_NODE = 6,
+	HPI_OBJ_CONTROL = 7,
+	HPI_OBJ_NVMEMORY = 8,
+	HPI_OBJ_GPIO = 9,
+	HPI_OBJ_WATCHDOG = 10,
+	HPI_OBJ_CLOCK = 11,
+	HPI_OBJ_PROFILE = 12,
+	HPI_OBJ_CONTROLEX = 13,
+	HPI_OBJ_ASYNCEVENT = 14
+#define HPI_OBJ_MAXINDEX 14
+};
+
+#define HPI_OBJ_FUNCTION_SPACING 0x100
+#define HPI_FUNC_ID(obj, i) (HPI_OBJ_##obj * HPI_OBJ_FUNCTION_SPACING + i)
+
 #define HPI_EXTRACT_INDEX(fn) (fn & 0xff)
 
-/* SUB-SYSTEM */
-#define HPI_SUBSYS_OPEN                 HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 1)
-#define HPI_SUBSYS_GET_VERSION          HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 2)
-#define HPI_SUBSYS_GET_INFO             HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 3)
-#define HPI_SUBSYS_FIND_ADAPTERS        HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 4)
-#define HPI_SUBSYS_CREATE_ADAPTER       HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 5)
-#define HPI_SUBSYS_CLOSE                HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 6)
-#define HPI_SUBSYS_DELETE_ADAPTER       HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 7)
-#define HPI_SUBSYS_DRIVER_LOAD          HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 8)
-#define HPI_SUBSYS_DRIVER_UNLOAD        HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 9)
-#define HPI_SUBSYS_READ_PORT_8          HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 10)
-#define HPI_SUBSYS_WRITE_PORT_8         HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 11)
-#define HPI_SUBSYS_GET_NUM_ADAPTERS     HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 12)
-#define HPI_SUBSYS_GET_ADAPTER          HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 13)
-#define HPI_SUBSYS_SET_NETWORK_INTERFACE HPI_MAKE_INDEX(HPI_OBJ_SUBSYSTEM, 14)
-#define HPI_SUBSYS_FUNCTION_COUNT 14
-/* ADAPTER */
-#define HPI_ADAPTER_OPEN                HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 1)
-#define HPI_ADAPTER_CLOSE               HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 2)
-#define HPI_ADAPTER_GET_INFO            HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 3)
-#define HPI_ADAPTER_GET_ASSERT          HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 4)
-#define HPI_ADAPTER_TEST_ASSERT         HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 5)
-#define HPI_ADAPTER_SET_MODE            HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 6)
-#define HPI_ADAPTER_GET_MODE            HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 7)
-#define HPI_ADAPTER_ENABLE_CAPABILITY   HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 8)
-#define HPI_ADAPTER_SELFTEST            HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 9)
-#define HPI_ADAPTER_FIND_OBJECT         HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 10)
-#define HPI_ADAPTER_QUERY_FLASH         HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 11)
-#define HPI_ADAPTER_START_FLASH         HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 12)
-#define HPI_ADAPTER_PROGRAM_FLASH       HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 13)
-#define HPI_ADAPTER_SET_PROPERTY        HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 14)
-#define HPI_ADAPTER_GET_PROPERTY        HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 15)
-#define HPI_ADAPTER_ENUM_PROPERTY       HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 16)
-#define HPI_ADAPTER_MODULE_INFO         HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 17)
-#define HPI_ADAPTER_DEBUG_READ          HPI_MAKE_INDEX(HPI_OBJ_ADAPTER, 18)
-#define HPI_ADAPTER_FUNCTION_COUNT 18
-/* OUTPUT STREAM */
-#define HPI_OSTREAM_OPEN                HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 1)
-#define HPI_OSTREAM_CLOSE               HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 2)
-#define HPI_OSTREAM_WRITE               HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 3)
-#define HPI_OSTREAM_START               HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 4)
-#define HPI_OSTREAM_STOP                HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 5)
-#define HPI_OSTREAM_RESET               HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 6)
-#define HPI_OSTREAM_GET_INFO            HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 7)
-#define HPI_OSTREAM_QUERY_FORMAT        HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 8)
-#define HPI_OSTREAM_DATA                HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 9)
-#define HPI_OSTREAM_SET_VELOCITY        HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 10)
-#define HPI_OSTREAM_SET_PUNCHINOUT      HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 11)
-#define HPI_OSTREAM_SINEGEN             HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 12)
-#define HPI_OSTREAM_ANC_RESET           HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 13)
-#define HPI_OSTREAM_ANC_GET_INFO        HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 14)
-#define HPI_OSTREAM_ANC_READ            HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 15)
-#define HPI_OSTREAM_SET_TIMESCALE       HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 16)
-#define HPI_OSTREAM_SET_FORMAT          HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 17)
-#define HPI_OSTREAM_HOSTBUFFER_ALLOC    HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 18)
-#define HPI_OSTREAM_HOSTBUFFER_FREE     HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 19)
-#define HPI_OSTREAM_GROUP_ADD           HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 20)
-#define HPI_OSTREAM_GROUP_GETMAP        HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 21)
-#define HPI_OSTREAM_GROUP_RESET         HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 22)
-#define HPI_OSTREAM_HOSTBUFFER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 23)
-#define HPI_OSTREAM_WAIT_START          HPI_MAKE_INDEX(HPI_OBJ_OSTREAM, 24)
-#define HPI_OSTREAM_FUNCTION_COUNT              24
-/* INPUT STREAM */
-#define HPI_ISTREAM_OPEN                HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 1)
-#define HPI_ISTREAM_CLOSE               HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 2)
-#define HPI_ISTREAM_SET_FORMAT          HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 3)
-#define HPI_ISTREAM_READ                HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 4)
-#define HPI_ISTREAM_START               HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 5)
-#define HPI_ISTREAM_STOP                HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 6)
-#define HPI_ISTREAM_RESET               HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 7)
-#define HPI_ISTREAM_GET_INFO            HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 8)
-#define HPI_ISTREAM_QUERY_FORMAT        HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 9)
-#define HPI_ISTREAM_ANC_RESET           HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 10)
-#define HPI_ISTREAM_ANC_GET_INFO        HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 11)
-#define HPI_ISTREAM_ANC_WRITE           HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 12)
-#define HPI_ISTREAM_HOSTBUFFER_ALLOC    HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 13)
-#define HPI_ISTREAM_HOSTBUFFER_FREE     HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 14)
-#define HPI_ISTREAM_GROUP_ADD           HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 15)
-#define HPI_ISTREAM_GROUP_GETMAP        HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 16)
-#define HPI_ISTREAM_GROUP_RESET         HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 17)
-#define HPI_ISTREAM_HOSTBUFFER_GET_INFO HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 18)
-#define HPI_ISTREAM_WAIT_START          HPI_MAKE_INDEX(HPI_OBJ_ISTREAM, 19)
-#define HPI_ISTREAM_FUNCTION_COUNT              19
-/* MIXER */
+enum HPI_FUNCTION_IDS {
+	HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1),
+	HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2),
+	HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3),
+	HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4),
+	HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5),
+	HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6),
+	HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7),
+	HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8),
+	HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9),
+	HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10),
+	HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11),
+	HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12),
+	HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13),
+	HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14),
+	HPI_SUBSYS_OPTION_INFO = HPI_FUNC_ID(SUBSYSTEM, 15),
+	HPI_SUBSYS_OPTION_GET = HPI_FUNC_ID(SUBSYSTEM, 16),
+	HPI_SUBSYS_OPTION_SET = HPI_FUNC_ID(SUBSYSTEM, 17),
+#define HPI_SUBSYS_FUNCTION_COUNT 17
+
+	HPI_ADAPTER_OPEN = HPI_FUNC_ID(ADAPTER, 1),
+	HPI_ADAPTER_CLOSE = HPI_FUNC_ID(ADAPTER, 2),
+	HPI_ADAPTER_GET_INFO = HPI_FUNC_ID(ADAPTER, 3),
+	HPI_ADAPTER_GET_ASSERT = HPI_FUNC_ID(ADAPTER, 4),
+	HPI_ADAPTER_TEST_ASSERT = HPI_FUNC_ID(ADAPTER, 5),
+	HPI_ADAPTER_SET_MODE = HPI_FUNC_ID(ADAPTER, 6),
+	HPI_ADAPTER_GET_MODE = HPI_FUNC_ID(ADAPTER, 7),
+	HPI_ADAPTER_ENABLE_CAPABILITY = HPI_FUNC_ID(ADAPTER, 8),
+	HPI_ADAPTER_SELFTEST = HPI_FUNC_ID(ADAPTER, 9),
+	HPI_ADAPTER_FIND_OBJECT = HPI_FUNC_ID(ADAPTER, 10),
+	HPI_ADAPTER_QUERY_FLASH = HPI_FUNC_ID(ADAPTER, 11),
+	HPI_ADAPTER_START_FLASH = HPI_FUNC_ID(ADAPTER, 12),
+	HPI_ADAPTER_PROGRAM_FLASH = HPI_FUNC_ID(ADAPTER, 13),
+	HPI_ADAPTER_SET_PROPERTY = HPI_FUNC_ID(ADAPTER, 14),
+	HPI_ADAPTER_GET_PROPERTY = HPI_FUNC_ID(ADAPTER, 15),
+	HPI_ADAPTER_ENUM_PROPERTY = HPI_FUNC_ID(ADAPTER, 16),
+	HPI_ADAPTER_MODULE_INFO = HPI_FUNC_ID(ADAPTER, 17),
+	HPI_ADAPTER_DEBUG_READ = HPI_FUNC_ID(ADAPTER, 18),
+	HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19),
+	HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20),
+#define HPI_ADAPTER_FUNCTION_COUNT 20
+
+	HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1),
+	HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2),
+	HPI_OSTREAM_WRITE = HPI_FUNC_ID(OSTREAM, 3),
+	HPI_OSTREAM_START = HPI_FUNC_ID(OSTREAM, 4),
+	HPI_OSTREAM_STOP = HPI_FUNC_ID(OSTREAM, 5),
+	HPI_OSTREAM_RESET = HPI_FUNC_ID(OSTREAM, 6),
+	HPI_OSTREAM_GET_INFO = HPI_FUNC_ID(OSTREAM, 7),
+	HPI_OSTREAM_QUERY_FORMAT = HPI_FUNC_ID(OSTREAM, 8),
+	HPI_OSTREAM_DATA = HPI_FUNC_ID(OSTREAM, 9),
+	HPI_OSTREAM_SET_VELOCITY = HPI_FUNC_ID(OSTREAM, 10),
+	HPI_OSTREAM_SET_PUNCHINOUT = HPI_FUNC_ID(OSTREAM, 11),
+	HPI_OSTREAM_SINEGEN = HPI_FUNC_ID(OSTREAM, 12),
+	HPI_OSTREAM_ANC_RESET = HPI_FUNC_ID(OSTREAM, 13),
+	HPI_OSTREAM_ANC_GET_INFO = HPI_FUNC_ID(OSTREAM, 14),
+	HPI_OSTREAM_ANC_READ = HPI_FUNC_ID(OSTREAM, 15),
+	HPI_OSTREAM_SET_TIMESCALE = HPI_FUNC_ID(OSTREAM, 16),
+	HPI_OSTREAM_SET_FORMAT = HPI_FUNC_ID(OSTREAM, 17),
+	HPI_OSTREAM_HOSTBUFFER_ALLOC = HPI_FUNC_ID(OSTREAM, 18),
+	HPI_OSTREAM_HOSTBUFFER_FREE = HPI_FUNC_ID(OSTREAM, 19),
+	HPI_OSTREAM_GROUP_ADD = HPI_FUNC_ID(OSTREAM, 20),
+	HPI_OSTREAM_GROUP_GETMAP = HPI_FUNC_ID(OSTREAM, 21),
+	HPI_OSTREAM_GROUP_RESET = HPI_FUNC_ID(OSTREAM, 22),
+	HPI_OSTREAM_HOSTBUFFER_GET_INFO = HPI_FUNC_ID(OSTREAM, 23),
+	HPI_OSTREAM_WAIT_START = HPI_FUNC_ID(OSTREAM, 24),
+	HPI_OSTREAM_WAIT = HPI_FUNC_ID(OSTREAM, 25),
+#define HPI_OSTREAM_FUNCTION_COUNT 25
+
+	HPI_ISTREAM_OPEN = HPI_FUNC_ID(ISTREAM, 1),
+	HPI_ISTREAM_CLOSE = HPI_FUNC_ID(ISTREAM, 2),
+	HPI_ISTREAM_SET_FORMAT = HPI_FUNC_ID(ISTREAM, 3),
+	HPI_ISTREAM_READ = HPI_FUNC_ID(ISTREAM, 4),
+	HPI_ISTREAM_START = HPI_FUNC_ID(ISTREAM, 5),
+	HPI_ISTREAM_STOP = HPI_FUNC_ID(ISTREAM, 6),
+	HPI_ISTREAM_RESET = HPI_FUNC_ID(ISTREAM, 7),
+	HPI_ISTREAM_GET_INFO = HPI_FUNC_ID(ISTREAM, 8),
+	HPI_ISTREAM_QUERY_FORMAT = HPI_FUNC_ID(ISTREAM, 9),
+	HPI_ISTREAM_ANC_RESET = HPI_FUNC_ID(ISTREAM, 10),
+	HPI_ISTREAM_ANC_GET_INFO = HPI_FUNC_ID(ISTREAM, 11),
+	HPI_ISTREAM_ANC_WRITE = HPI_FUNC_ID(ISTREAM, 12),
+	HPI_ISTREAM_HOSTBUFFER_ALLOC = HPI_FUNC_ID(ISTREAM, 13),
+	HPI_ISTREAM_HOSTBUFFER_FREE = HPI_FUNC_ID(ISTREAM, 14),
+	HPI_ISTREAM_GROUP_ADD = HPI_FUNC_ID(ISTREAM, 15),
+	HPI_ISTREAM_GROUP_GETMAP = HPI_FUNC_ID(ISTREAM, 16),
+	HPI_ISTREAM_GROUP_RESET = HPI_FUNC_ID(ISTREAM, 17),
+	HPI_ISTREAM_HOSTBUFFER_GET_INFO = HPI_FUNC_ID(ISTREAM, 18),
+	HPI_ISTREAM_WAIT_START = HPI_FUNC_ID(ISTREAM, 19),
+	HPI_ISTREAM_WAIT = HPI_FUNC_ID(ISTREAM, 20),
+#define HPI_ISTREAM_FUNCTION_COUNT 20
+
 /* NOTE:
    GET_NODE_INFO, SET_CONNECTION, GET_CONNECTIONS are not currently used */
-#define HPI_MIXER_OPEN                  HPI_MAKE_INDEX(HPI_OBJ_MIXER, 1)
-#define HPI_MIXER_CLOSE                 HPI_MAKE_INDEX(HPI_OBJ_MIXER, 2)
-#define HPI_MIXER_GET_INFO              HPI_MAKE_INDEX(HPI_OBJ_MIXER, 3)
-#define HPI_MIXER_GET_NODE_INFO         HPI_MAKE_INDEX(HPI_OBJ_MIXER, 4)
-#define HPI_MIXER_GET_CONTROL           HPI_MAKE_INDEX(HPI_OBJ_MIXER, 5)
-#define HPI_MIXER_SET_CONNECTION        HPI_MAKE_INDEX(HPI_OBJ_MIXER, 6)
-#define HPI_MIXER_GET_CONNECTIONS       HPI_MAKE_INDEX(HPI_OBJ_MIXER, 7)
-#define HPI_MIXER_GET_CONTROL_BY_INDEX  HPI_MAKE_INDEX(HPI_OBJ_MIXER, 8)
-#define HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX  HPI_MAKE_INDEX(HPI_OBJ_MIXER, 9)
-#define HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES HPI_MAKE_INDEX(HPI_OBJ_MIXER, 10)
-#define HPI_MIXER_STORE                 HPI_MAKE_INDEX(HPI_OBJ_MIXER, 11)
-#define HPI_MIXER_FUNCTION_COUNT        11
-/* MIXER CONTROLS */
-#define HPI_CONTROL_GET_INFO            HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 1)
-#define HPI_CONTROL_GET_STATE           HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 2)
-#define HPI_CONTROL_SET_STATE           HPI_MAKE_INDEX(HPI_OBJ_CONTROL, 3)
+	HPI_MIXER_OPEN = HPI_FUNC_ID(MIXER, 1),
+	HPI_MIXER_CLOSE = HPI_FUNC_ID(MIXER, 2),
+	HPI_MIXER_GET_INFO = HPI_FUNC_ID(MIXER, 3),
+	HPI_MIXER_GET_NODE_INFO = HPI_FUNC_ID(MIXER, 4),
+	HPI_MIXER_GET_CONTROL = HPI_FUNC_ID(MIXER, 5),
+	HPI_MIXER_SET_CONNECTION = HPI_FUNC_ID(MIXER, 6),
+	HPI_MIXER_GET_CONNECTIONS = HPI_FUNC_ID(MIXER, 7),
+	HPI_MIXER_GET_CONTROL_BY_INDEX = HPI_FUNC_ID(MIXER, 8),
+	HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX = HPI_FUNC_ID(MIXER, 9),
+	HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES = HPI_FUNC_ID(MIXER, 10),
+	HPI_MIXER_STORE = HPI_FUNC_ID(MIXER, 11),
+	HPI_MIXER_GET_CACHE_INFO = HPI_FUNC_ID(MIXER, 12),
+#define HPI_MIXER_FUNCTION_COUNT 12
+
+	HPI_CONTROL_GET_INFO = HPI_FUNC_ID(CONTROL, 1),
+	HPI_CONTROL_GET_STATE = HPI_FUNC_ID(CONTROL, 2),
+	HPI_CONTROL_SET_STATE = HPI_FUNC_ID(CONTROL, 3),
 #define HPI_CONTROL_FUNCTION_COUNT 3
-/* NONVOL MEMORY */
-#define HPI_NVMEMORY_OPEN               HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 1)
-#define HPI_NVMEMORY_READ_BYTE          HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 2)
-#define HPI_NVMEMORY_WRITE_BYTE         HPI_MAKE_INDEX(HPI_OBJ_NVMEMORY, 3)
+
+	HPI_NVMEMORY_OPEN = HPI_FUNC_ID(NVMEMORY, 1),
+	HPI_NVMEMORY_READ_BYTE = HPI_FUNC_ID(NVMEMORY, 2),
+	HPI_NVMEMORY_WRITE_BYTE = HPI_FUNC_ID(NVMEMORY, 3),
 #define HPI_NVMEMORY_FUNCTION_COUNT 3
-/* GPIO */
-#define HPI_GPIO_OPEN                   HPI_MAKE_INDEX(HPI_OBJ_GPIO, 1)
-#define HPI_GPIO_READ_BIT               HPI_MAKE_INDEX(HPI_OBJ_GPIO, 2)
-#define HPI_GPIO_WRITE_BIT              HPI_MAKE_INDEX(HPI_OBJ_GPIO, 3)
-#define HPI_GPIO_READ_ALL               HPI_MAKE_INDEX(HPI_OBJ_GPIO, 4)
-#define HPI_GPIO_WRITE_STATUS           HPI_MAKE_INDEX(HPI_OBJ_GPIO, 5)
+
+	HPI_GPIO_OPEN = HPI_FUNC_ID(GPIO, 1),
+	HPI_GPIO_READ_BIT = HPI_FUNC_ID(GPIO, 2),
+	HPI_GPIO_WRITE_BIT = HPI_FUNC_ID(GPIO, 3),
+	HPI_GPIO_READ_ALL = HPI_FUNC_ID(GPIO, 4),
+	HPI_GPIO_WRITE_STATUS = HPI_FUNC_ID(GPIO, 5),
 #define HPI_GPIO_FUNCTION_COUNT 5
-/* ASYNC EVENT */
-#define HPI_ASYNCEVENT_OPEN             HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 1)
-#define HPI_ASYNCEVENT_CLOSE            HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 2)
-#define HPI_ASYNCEVENT_WAIT             HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 3)
-#define HPI_ASYNCEVENT_GETCOUNT         HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 4)
-#define HPI_ASYNCEVENT_GET              HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 5)
-#define HPI_ASYNCEVENT_SENDEVENTS       HPI_MAKE_INDEX(HPI_OBJ_ASYNCEVENT, 6)
+
+	HPI_ASYNCEVENT_OPEN = HPI_FUNC_ID(ASYNCEVENT, 1),
+	HPI_ASYNCEVENT_CLOSE = HPI_FUNC_ID(ASYNCEVENT, 2),
+	HPI_ASYNCEVENT_WAIT = HPI_FUNC_ID(ASYNCEVENT, 3),
+	HPI_ASYNCEVENT_GETCOUNT = HPI_FUNC_ID(ASYNCEVENT, 4),
+	HPI_ASYNCEVENT_GET = HPI_FUNC_ID(ASYNCEVENT, 5),
+	HPI_ASYNCEVENT_SENDEVENTS = HPI_FUNC_ID(ASYNCEVENT, 6),
 #define HPI_ASYNCEVENT_FUNCTION_COUNT 6
-/* WATCH-DOG */
-#define HPI_WATCHDOG_OPEN               HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 1)
-#define HPI_WATCHDOG_SET_TIME           HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 2)
-#define HPI_WATCHDOG_PING               HPI_MAKE_INDEX(HPI_OBJ_WATCHDOG, 3)
-/* CLOCK */
-#define HPI_CLOCK_OPEN                  HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 1)
-#define HPI_CLOCK_SET_TIME              HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 2)
-#define HPI_CLOCK_GET_TIME              HPI_MAKE_INDEX(HPI_OBJ_CLOCK, 3)
-/* PROFILE */
-#define HPI_PROFILE_OPEN_ALL            HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 1)
-#define HPI_PROFILE_START_ALL           HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 2)
-#define HPI_PROFILE_STOP_ALL            HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 3)
-#define HPI_PROFILE_GET                 HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 4)
-#define HPI_PROFILE_GET_IDLECOUNT       HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 5)
-#define HPI_PROFILE_GET_NAME            HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 6)
-#define HPI_PROFILE_GET_UTILIZATION     HPI_MAKE_INDEX(HPI_OBJ_PROFILE, 7)
+
+	HPI_WATCHDOG_OPEN = HPI_FUNC_ID(WATCHDOG, 1),
+	HPI_WATCHDOG_SET_TIME = HPI_FUNC_ID(WATCHDOG, 2),
+	HPI_WATCHDOG_PING = HPI_FUNC_ID(WATCHDOG, 3),
+
+	HPI_CLOCK_OPEN = HPI_FUNC_ID(CLOCK, 1),
+	HPI_CLOCK_SET_TIME = HPI_FUNC_ID(CLOCK, 2),
+	HPI_CLOCK_GET_TIME = HPI_FUNC_ID(CLOCK, 3),
+
+	HPI_PROFILE_OPEN_ALL = HPI_FUNC_ID(PROFILE, 1),
+	HPI_PROFILE_START_ALL = HPI_FUNC_ID(PROFILE, 2),
+	HPI_PROFILE_STOP_ALL = HPI_FUNC_ID(PROFILE, 3),
+	HPI_PROFILE_GET = HPI_FUNC_ID(PROFILE, 4),
+	HPI_PROFILE_GET_IDLECOUNT = HPI_FUNC_ID(PROFILE, 5),
+	HPI_PROFILE_GET_NAME = HPI_FUNC_ID(PROFILE, 6),
+	HPI_PROFILE_GET_UTILIZATION = HPI_FUNC_ID(PROFILE, 7)
 #define HPI_PROFILE_FUNCTION_COUNT 7
-/* ////////////////////////////////////////////////////////////////////// */
-/* PRIVATE ATTRIBUTES */
+};
 
 /* ////////////////////////////////////////////////////////////////////// */
 /* STRUCTURES */
@@ -672,18 +552,7 @@ Threshold is a -ve number in units of dB/100,
 /** PCI bus resource */
 struct hpi_pci {
 	u32 __iomem *ap_mem_base[HPI_MAX_ADAPTER_MEM_SPACES];
-	struct pci_dev *p_os_data;
-
-#ifndef HPI64BIT		/* keep structure size constant */
-	u32 padding[HPI_MAX_ADAPTER_MEM_SPACES + 1];
-#endif
-	u16 vendor_id;
-	u16 device_id;
-	u16 subsys_vendor_id;
-	u16 subsys_device_id;
-	u16 bus_number;
-	u16 device_number;
-	u32 interrupt;
+	struct pci_dev *pci_dev;
 };
 
 struct hpi_resource {
@@ -702,12 +571,10 @@ struct hpi_resource {
 /** Format info used inside struct hpi_message
     Not the same as public API struct hpi_format */
 struct hpi_msg_format {
-	u32 sample_rate;
-				/**< 11025, 32000, 44100 ... */
-	u32 bit_rate;	      /**< for MPEG */
-	u32 attributes;
-				/**< Stereo/JointStereo/Mono */
-	u16 channels;	      /**< 1,2..., (or ancillary mode or idle bit */
+	u32 sample_rate; /**< 11025, 32000, 44100 etc. */
+	u32 bit_rate; /**< for MPEG */
+	u32 attributes;	/**< stereo/joint_stereo/mono */
+	u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
 	u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see \ref HPI_FORMATS. */
 };
 
@@ -742,7 +609,7 @@ struct hpi_data_compat32 {
 struct hpi_buffer {
   /** placehoder for backward compatability (see dwBufferSize) */
 	struct hpi_msg_format reserved;
-	u32 command;	/**< HPI_BUFFER_CMD_xxx*/
+	u32 command; /**< HPI_BUFFER_CMD_xxx*/
 	u32 pci_address; /**< PCI physical address of buffer for DSP DMA */
 	u32 buffer_size; /**< must line up with data_size of HPI_DATA*/
 };
@@ -777,30 +644,25 @@ struct hpi_subsys_msg {
 
 struct hpi_subsys_res {
 	u32 version;
-	u32 data;		/* used to return extended version */
-	u16 num_adapters;	/* number of adapters */
+	u32 data;		/* extended version */
+	u16 num_adapters;
 	u16 adapter_index;
-	u16 aw_adapter_list[HPI_MAX_ADAPTERS];
-};
-
-struct hpi_adapter_msg {
-	u32 adapter_mode;	/* adapter mode */
-	u16 assert_id;		/* assert number for "test assert" call
-				   object_index for find object call
-				   query_or_set for hpi_adapter_set_mode_ex() */
-	u16 object_type;	/* for adapter find object call */
+	u16 adapter_type;
+	u16 pad16;
 };
 
 union hpi_adapterx_msg {
-	struct hpi_adapter_msg adapter;
 	struct {
-		u32 offset;
-	} query_flash;
+		u32 dsp_address;
+		u32 count_bytes;
+	} debug_read;
 	struct {
-		u32 offset;
-		u32 length;
-		u32 key;
-	} start_flash;
+		u32 adapter_mode;
+		u16 query_or_set;
+	} mode;
+	struct {
+		u16 index;
+	} module_info;
 	struct {
 		u32 checksum;
 		u16 sequence;
@@ -809,28 +671,41 @@ union hpi_adapterx_msg {
 		u16 unused;
 	} program_flash;
 	struct {
+		u16 index;
+		u16 what;
+		u16 property_index;
+	} property_enum;
+	struct {
 		u16 property;
 		u16 parameter1;
 		u16 parameter2;
 	} property_set;
 	struct {
-		u16 index;
-		u16 what;
-		u16 property_index;
-	} property_enum;
+		u32 offset;
+	} query_flash;
 	struct {
-		u16 index;
-	} module_info;
+		u32 pad32;
+		u16 key1;
+		u16 key2;
+	} restart;
 	struct {
-		u32 dsp_address;
-		u32 count_bytes;
-	} debug_read;
+		u32 offset;
+		u32 length;
+		u32 key;
+	} start_flash;
+	struct {
+		u32 pad32;
+		u16 value;
+	} test_assert;
+	struct {
+		u32 yes;
+	} irq_query;
 };
 
 struct hpi_adapter_res {
 	u32 serial_number;
 	u16 adapter_type;
-	u16 adapter_index;	/* is this needed? also used for dsp_index */
+	u16 adapter_index;
 	u16 num_instreams;
 	u16 num_outstreams;
 	u16 num_mixers;
@@ -839,12 +714,18 @@ struct hpi_adapter_res {
 };
 
 union hpi_adapterx_res {
-	struct hpi_adapter_res adapter;
+	struct hpi_adapter_res info;
 	struct {
-		u32 checksum;
-		u32 length;
-		u32 version;
-	} query_flash;
+		u32 p1;
+		u16 count;
+		u16 dsp_index;
+		u32 p2;
+		u32 dsp_msg_addr;
+		char sz_message[HPI_STRING_LEN];
+	} assert;
+	struct {
+		u32 adapter_mode;
+	} mode;
 	struct {
 		u16 sequence;
 	} program_flash;
@@ -852,6 +733,14 @@ union hpi_adapterx_res {
 		u16 parameter1;
 		u16 parameter2;
 	} property_get;
+	struct {
+		u32 checksum;
+		u32 length;
+		u32 version;
+	} query_flash;
+	struct {
+		u32 yes;
+	} irq_query;
 };
 
 struct hpi_stream_msg {
@@ -863,6 +752,7 @@ struct hpi_stream_msg {
 		u32 time_scale;
 		struct hpi_buffer buffer;
 		struct hpi_streamid stream;
+		u32 threshold_bytes;
 	} u;
 };
 
@@ -911,7 +801,7 @@ struct hpi_stream_res {
 struct hpi_mixer_msg {
 	u16 control_index;
 	u16 control_type;	/* = HPI_CONTROL_METER _VOLUME etc */
-	u16 padding1;		/* maintain alignment of subsequent fields */
+	u16 padding1;		/* Maintain alignment of subsequent fields */
 	u16 node_type1;		/* = HPI_SOURCENODE_LINEIN etc */
 	u16 node_index1;	/* = 0..N */
 	u16 node_type2;
@@ -949,6 +839,11 @@ union hpi_mixerx_res {
 		u32 p_data;	/* pointer to data array */
 		u16 more_to_do;	/* indicates if there is more to do */
 	} gcabi;
+	struct {
+		u32 total_controls;	/* count of controls in the mixer */
+		u32 cache_controls;	/* count of controls in the cac */
+		u32 cache_bytes;	/* size of cache */
+	} cache_info;
 };
 
 struct hpi_control_msg {
@@ -1000,12 +895,16 @@ union hpi_control_union_res {
 		u32 band;
 		u32 frequency;
 		u32 gain;
-		u32 level;
 		u32 deemphasis;
 		struct {
 			u32 data[2];
 			u32 bLER;
 		} rds;
+		short s_level;
+		struct {
+			u16 value;
+			u16 mask;
+		} status;
 	} tuner;
 	struct {
 		char sz_data[8];
@@ -1178,11 +1077,11 @@ struct hpi_profile_res_open {
 };
 
 struct hpi_profile_res_time {
-	u32 micro_seconds;
+	u32 total_tick_count;
 	u32 call_count;
-	u32 max_micro_seconds;
-	u32 min_micro_seconds;
-	u16 seconds;
+	u32 max_tick_count;
+	u32 ticks_per_millisecond;
+	u16 profile_interval;
 };
 
 struct hpi_profile_res_name {
@@ -1218,7 +1117,6 @@ struct hpi_message {
 	u16 obj_index;		/*  */
 	union {
 		struct hpi_subsys_msg s;
-		struct hpi_adapter_msg a;
 		union hpi_adapterx_msg ax;
 		struct hpi_stream_msg d;
 		struct hpi_mixer_msg m;
@@ -1239,7 +1137,7 @@ struct hpi_message {
 };
 
 #define HPI_MESSAGE_SIZE_BY_OBJECT { \
-	sizeof(struct hpi_message_header) ,   /* default, no object type 0 */ \
+	sizeof(struct hpi_message_header) ,   /* Default, no object type 0 */ \
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_subsys_msg),\
 	sizeof(struct hpi_message_header) + sizeof(union hpi_adapterx_msg),\
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_stream_msg),\
@@ -1256,6 +1154,11 @@ struct hpi_message {
 	sizeof(struct hpi_message_header) + sizeof(struct hpi_async_msg) \
 }
 
+/*
+Note that the wSpecificError error field should be inspected and potentially
+reported whenever HPI_ERROR_DSP_COMMUNICATION or HPI_ERROR_DSP_BOOTLOAD is
+returned in wError.
+*/
 struct hpi_response_header {
 	u16 size;
 	u8 type;		/* HPI_TYPE_RESPONSE  */
@@ -1277,7 +1180,6 @@ struct hpi_response {
 	u16 specific_error;	/* adapter specific error */
 	union {
 		struct hpi_subsys_res s;
-		struct hpi_adapter_res a;
 		union hpi_adapterx_res ax;
 		struct hpi_stream_res d;
 		struct hpi_mixer_res m;
@@ -1297,7 +1199,7 @@ struct hpi_response {
 };
 
 #define HPI_RESPONSE_SIZE_BY_OBJECT { \
-	sizeof(struct hpi_response_header) ,/* default, no object type 0 */ \
+	sizeof(struct hpi_response_header) ,/* Default, no object type 0 */ \
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_subsys_res),\
 	sizeof(struct hpi_response_header) + sizeof(union  hpi_adapterx_res),\
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_stream_res),\
@@ -1314,7 +1216,7 @@ struct hpi_response {
 	sizeof(struct hpi_response_header) + sizeof(struct hpi_async_res) \
 }
 
-/*********************** version 1 message/response *****************************/
+/*********************** version 1 message/response **************************/
 #define HPINET_ETHERNET_DATA_SIZE (1500)
 #define HPINET_IP_HDR_SIZE (20)
 #define HPINET_IP_DATA_SIZE (HPINET_ETHERNET_DATA_SIZE - HPINET_IP_HDR_SIZE)
@@ -1394,6 +1296,17 @@ struct hpi_res_adapter_program_flash {
 		sizeof(struct hpi_response_header) - sizeof(u16)];
 };
 
+struct hpi_msg_adapter_debug_read {
+	struct hpi_message_header h;
+	u32 dsp_address;
+	u32 count_bytes;
+};
+
+struct hpi_res_adapter_debug_read {
+	struct hpi_response_header h;
+	u8 bytes[256];
+};
+
 #if 1
 #define hpi_message_header_v1 hpi_message_header
 #define hpi_response_header_v1 hpi_response_header
@@ -1414,23 +1327,10 @@ struct hpi_response_header_v1 {
 };
 #endif
 
-/* STRV HPI Packet */
-struct hpi_msg_strv {
-	struct hpi_message_header h;
-	struct hpi_entity strv;
-};
-
-struct hpi_res_strv {
-	struct hpi_response_header h;
-	struct hpi_entity strv;
-};
-#define MIN_STRV_PACKET_SIZE sizeof(struct hpi_res_strv)
-
 struct hpi_msg_payload_v0 {
 	struct hpi_message_header h;
 	union {
 		struct hpi_subsys_msg s;
-		struct hpi_adapter_msg a;
 		union hpi_adapterx_msg ax;
 		struct hpi_stream_msg d;
 		struct hpi_mixer_msg m;
@@ -1451,7 +1351,6 @@ struct hpi_res_payload_v0 {
 	struct hpi_response_header h;
 	union {
 		struct hpi_subsys_res s;
-		struct hpi_adapter_res a;
 		union hpi_adapterx_res ax;
 		struct hpi_stream_res d;
 		struct hpi_mixer_res m;
@@ -1471,13 +1370,13 @@ struct hpi_res_payload_v0 {
 union hpi_message_buffer_v1 {
 	struct hpi_message m0;	/* version 0 */
 	struct hpi_message_header_v1 h;
-	unsigned char buf[HPI_MAX_PAYLOAD_SIZE];
+	u8 buf[HPI_MAX_PAYLOAD_SIZE];
 };
 
 union hpi_response_buffer_v1 {
 	struct hpi_response r0;	/* version 0 */
 	struct hpi_response_header_v1 h;
-	unsigned char buf[HPI_MAX_PAYLOAD_SIZE];
+	u8 buf[HPI_MAX_PAYLOAD_SIZE];
 };
 
 compile_time_assert((sizeof(union hpi_message_buffer_v1) <=
@@ -1499,6 +1398,11 @@ struct hpi_control_defn {
 /*////////////////////////////////////////////////////////////////////////// */
 /* declarations for control caching (internal to HPI<->DSP interaction)      */
 
+/** indicates a cached u16 value is invalid. */
+#define HPI_CACHE_INVALID_UINT16 0xFFFF
+/** indicates a cached short value is invalid. */
+#define HPI_CACHE_INVALID_SHORT -32768
+
 /** A compact representation of (part of) a controls state.
 Used for efficient transfer of the control state
 between DSP and host or across a network
@@ -1512,58 +1416,104 @@ struct hpi_control_cache_info {
 	u16 control_index;
 };
 
-struct hpi_control_cache_single {
+struct hpi_control_cache_vol {
+	struct hpi_control_cache_info i;
+	short an_log[2];
+	unsigned short flags;
+	char padding[2];
+};
+
+struct hpi_control_cache_meter {
+	struct hpi_control_cache_info i;
+	short an_log_peak[2];
+	short an_logRMS[2];
+};
+
+struct hpi_control_cache_channelmode {
+	struct hpi_control_cache_info i;
+	u16 mode;
+	char temp_padding[6];
+};
+
+struct hpi_control_cache_mux {
+	struct hpi_control_cache_info i;
+	u16 source_node_type;
+	u16 source_node_index;
+	char temp_padding[4];
+};
+
+struct hpi_control_cache_level {
 	struct hpi_control_cache_info i;
+	short an_log[2];
+	char temp_padding[4];
+};
+
+struct hpi_control_cache_tuner {
+	struct hpi_control_cache_info i;
+	u32 freq_ink_hz;
+	u16 band;
+	short s_level_avg;
+};
+
+struct hpi_control_cache_aes3rx {
+	struct hpi_control_cache_info i;
+	u32 error_status;
+	u32 format;
+};
+
+struct hpi_control_cache_aes3tx {
+	struct hpi_control_cache_info i;
+	u32 format;
+	char temp_padding[4];
+};
+
+struct hpi_control_cache_tonedetector {
+	struct hpi_control_cache_info i;
+	u16 state;
+	char temp_padding[6];
+};
+
+struct hpi_control_cache_silencedetector {
+	struct hpi_control_cache_info i;
+	u32 state;
+	char temp_padding[4];
+};
+
+struct hpi_control_cache_sampleclock {
+	struct hpi_control_cache_info i;
+	u16 source;
+	u16 source_index;
+	u32 sample_rate;
+};
+
+struct hpi_control_cache_microphone {
+	struct hpi_control_cache_info i;
+	u16 phantom_state;
+	char temp_padding[6];
+};
+
+struct hpi_control_cache_generic {
+	struct hpi_control_cache_info i;
+	u32 dw1;
+	u32 dw2;
+};
+
+struct hpi_control_cache_single {
 	union {
-		struct {	/* volume */
-			short an_log[2];
-		} v;
-		struct {	/* peak meter */
-			short an_log_peak[2];
-			short an_logRMS[2];
-		} p;
-		struct {	/* channel mode */
-			u16 mode;
-		} m;
-		struct {	/* multiplexer */
-			u16 source_node_type;
-			u16 source_node_index;
-		} x;
-		struct {	/* level/trim */
-			short an_log[2];
-		} l;
-		struct {	/* tuner - partial caching.
-				   some attributes go to the DSP. */
-			u32 freq_ink_hz;
-			u16 band;
-			u16 level;
-		} t;
-		struct {	/* AESEBU rx status */
-			u32 error_status;
-			u32 source;
-		} aes3rx;
-		struct {	/* AESEBU tx */
-			u32 format;
-		} aes3tx;
-		struct {	/* tone detector */
-			u16 state;
-		} tone;
-		struct {	/* silence detector */
-			u32 state;
-			u32 count;
-		} silence;
-		struct {	/* sample clock */
-			u16 source;
-			u16 source_index;
-			u32 sample_rate;
-		} clk;
-		struct {	/* microphone control */
-			u16 state;
-		} phantom_power;
-		struct {	/* generic control */
-			u32 dw1;
-			u32 dw2;
-		} g;
+		struct hpi_control_cache_info i;
+		struct hpi_control_cache_vol vol;
+		struct hpi_control_cache_meter meter;
+		struct hpi_control_cache_channelmode mode;
+		struct hpi_control_cache_mux mux;
+		struct hpi_control_cache_level level;
+		struct hpi_control_cache_tuner tuner;
+		struct hpi_control_cache_aes3rx aes3rx;
+		struct hpi_control_cache_aes3tx aes3tx;
+		struct hpi_control_cache_tonedetector tone;
+		struct hpi_control_cache_silencedetector silence;
+		struct hpi_control_cache_sampleclock clk;
+		struct hpi_control_cache_microphone microphone;
+		struct hpi_control_cache_generic generic;
 	} u;
 };
 
@@ -1580,8 +1530,7 @@ struct hpi_control_cache_pad {
 	u32 traffic_anouncement;
 };
 
-/*/////////////////////////////////////////////////////////////////////////// */
-/* declarations for 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */
+/* 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */
 struct hpi_fifo_buffer {
 	u32 size;
 	u32 dSP_index;
@@ -1606,25 +1555,18 @@ u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index,
 /*////////////////////////////////////////////////////////////////////////// */
 
 /* main HPI entry point */
-hpi_handler_func hpi_send_recv;
-
-/* UDP message */
-void hpi_send_recvUDP(struct hpi_message *phm, struct hpi_response *phr,
-	const unsigned int timeout);
+void hpi_send_recv(struct hpi_message *phm, struct hpi_response *phr);
 
 /* used in PnP OS/driver */
-u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys,
-	const struct hpi_resource *p_resource, u16 *pw_adapter_index);
+u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource,
+	u16 *pw_adapter_index);
 
-u16 hpi_subsys_delete_adapter(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index);
+u16 hpi_subsys_delete_adapter(u16 adapter_index);
 
-u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u8 **pp_buffer,
+u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer,
 	struct hpi_hostbuffer_status **pp_status);
 
-u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u8 **pp_buffer,
+u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer,
 	struct hpi_hostbuffer_status **pp_status);
 
 u16 hpi_adapter_restart(u16 adapter_index);
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index d67f4d3..3e9c5c2 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -26,6 +26,8 @@
 
 #include "hpi_internal.h"
 #include "hpidebug.h"
+#include "hpimsginit.h"
+
 #include "hpicmn.h"
 
 struct hpi_adapters_list {
@@ -43,14 +45,24 @@ static struct hpi_adapters_list adapters;
 **/
 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
 {
-	u16 error = 0;
+	if (phr->type != HPI_TYPE_RESPONSE) {
+		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
+		return HPI_ERROR_INVALID_RESPONSE;
+	}
 
-	if ((phr->type != HPI_TYPE_RESPONSE)
-		|| (phr->object != phm->object)
-		|| (phr->function != phm->function))
-		error = HPI_ERROR_INVALID_RESPONSE;
+	if (phr->object != phm->object) {
+		HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
+			phr->object);
+		return HPI_ERROR_INVALID_RESPONSE;
+	}
+
+	if (phr->function != phm->function) {
+		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n",
+			phr->function);
+		return HPI_ERROR_INVALID_RESPONSE;
+	}
 
-	return error;
+	return 0;
 }
 
 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
@@ -66,8 +78,18 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
 	}
 
 	if (adapters.adapter[pao->index].adapter_type) {
-		{
-			retval = HPI_DUPLICATE_ADAPTER_NUMBER;
+		int a;
+		for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
+			if (!adapters.adapter[a].adapter_type) {
+				HPI_DEBUG_LOG(WARNING,
+					"ASI%X duplicate index %d moved to %d\n",
+					pao->adapter_type, pao->index, a);
+				pao->index = a;
+				break;
+			}
+		}
+		if (a < 0) {
+			retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
 			goto unlock;
 		}
 	}
@@ -76,17 +98,22 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
 	adapters.gw_num_adapters++;
 
 unlock:
-	hpios_alistlock_un_lock(&adapters);
+	hpios_alistlock_unlock(&adapters);
 	return retval;
 }
 
 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
 {
-	memset(pao, 0, sizeof(struct hpi_adapter_obj));
+	if (!pao->adapter_type) {
+		HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
+		return;
+	}
 
 	hpios_alistlock_lock(&adapters);
-	adapters.gw_num_adapters--;	/* dec the number of adapters */
-	hpios_alistlock_un_lock(&adapters);
+	if (adapters.adapter[pao->index].adapter_type)
+		adapters.gw_num_adapters--;
+	memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
+	hpios_alistlock_unlock(&adapters);
 }
 
 /**
@@ -99,7 +126,7 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
 	struct hpi_adapter_obj *pao = NULL;
 
 	if (adapter_index >= HPI_MAX_ADAPTERS) {
-		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
+		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
 			adapter_index);
 		return NULL;
 	}
@@ -125,51 +152,34 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
 * wipe an HPI_ADAPTERS_LIST structure.
 *
 **/
-static void wipe_adapter_list(void
-	)
+static void wipe_adapter_list(void)
 {
 	memset(&adapters, 0, sizeof(adapters));
 }
 
-/**
-* SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
-* with all adapters in the given HPI_ADAPTERS_LIST.
-*
-*/
-static void subsys_get_adapters(struct hpi_response *phr)
+static void subsys_get_adapter(struct hpi_message *phm,
+	struct hpi_response *phr)
 {
-	/* fill in the response adapter array with the position */
-	/* identified by the adapter number/index of the adapters in */
-	/* this HPI */
-	/* i.e. if we have an A120 with it's jumper set to */
-	/* Adapter Number 2 then put an Adapter type A120 in the */
-	/* array in position 1 */
-	/* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */
-
-	/* input:  NONE */
-	/* output: wNumAdapters */
-	/*                 awAdapter[] */
-	/* */
-
-	short i;
-	struct hpi_adapter_obj *pao = NULL;
+	int count = phm->obj_index;
+	u16 index = 0;
 
-	HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n");
-
-	/* for each adapter, place it's type in the position of the array */
-	/* corresponding to it's adapter number */
-	for (i = 0; i < adapters.gw_num_adapters; i++) {
-		pao = &adapters.adapter[i];
-		if (phr->u.s.aw_adapter_list[pao->index] != 0) {
-			phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
-			phr->specific_error = pao->index;
-			return;
+	/* find the nCount'th nonzero adapter in array */
+	for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
+		if (adapters.adapter[index].adapter_type) {
+			if (!count)
+				break;
+			count--;
 		}
-		phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
 	}
 
-	phr->u.s.num_adapters = adapters.gw_num_adapters;
-	phr->error = 0;	/* the function completed OK; */
+	if (index < HPI_MAX_ADAPTERS) {
+		phr->u.s.adapter_index = adapters.adapter[index].index;
+		phr->u.s.adapter_type = adapters.adapter[index].adapter_type;
+	} else {
+		phr->u.s.adapter_index = 0;
+		phr->u.s.adapter_type = 0;
+		phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
+	}
 }
 
 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
@@ -178,67 +188,98 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
 	int cached = 0;
 	if (!pC)
 		return 0;
-	if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
-		&& (pC->cache_size_in_bytes)
-		) {
-		u32 *p_master_cache;
-		pC->init = 1;
-
-		p_master_cache = (u32 *)pC->p_cache;
-		HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
+
+	if (pC->init)
+		return pC->init;
+
+	if (!pC->p_cache)
+		return 0;
+
+	if (pC->control_count && pC->cache_size_in_bytes) {
+		char *p_master_cache;
+		unsigned int byte_count = 0;
+
+		p_master_cache = (char *)pC->p_cache;
+		HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
 			pC->control_count);
 		for (i = 0; i < pC->control_count; i++) {
 			struct hpi_control_cache_info *info =
 				(struct hpi_control_cache_info *)
-				p_master_cache;
+				&p_master_cache[byte_count];
+
+			if (!info->size_in32bit_words) {
+				if (!i) {
+					HPI_DEBUG_LOG(INFO,
+						"adap %d cache not ready?\n",
+						pC->adap_idx);
+					return 0;
+				}
+				/* The cache is invalid.
+				 * Minimum valid entry size is
+				 * sizeof(struct hpi_control_cache_info)
+				 */
+				HPI_DEBUG_LOG(ERROR,
+					"adap %d zero size cache entry %d\n",
+					pC->adap_idx, i);
+				break;
+			}
 
 			if (info->control_type) {
-				pC->p_info[i] = info;
+				pC->p_info[info->control_index] = info;
 				cached++;
-			} else
-				pC->p_info[i] = NULL;
+			} else	/* dummy cache entry */
+				pC->p_info[info->control_index] = NULL;
 
-			if (info->size_in32bit_words)
-				p_master_cache += info->size_in32bit_words;
-			else
-				p_master_cache +=
-					sizeof(struct
-					hpi_control_cache_single) /
-					sizeof(u32);
+			byte_count += info->size_in32bit_words * 4;
 
 			HPI_DEBUG_LOG(VERBOSE,
-				"cached %d, pinfo %p index %d type %d\n",
-				cached, pC->p_info[i], info->control_index,
-				info->control_type);
+				"cached %d, pinfo %p index %d type %d size %d\n",
+				cached, pC->p_info[info->control_index],
+				info->control_index, info->control_type,
+				info->size_in32bit_words);
+
+			/* quit loop early if whole cache has been scanned.
+			 * dwControlCount is the maximum possible entries
+			 * but some may be absent from the cache
+			 */
+			if (byte_count >= pC->cache_size_in_bytes)
+				break;
+			/* have seen last control index */
+			if (info->control_index == pC->control_count - 1)
+				break;
 		}
-		/*
-		   We didn't find anything to cache, so try again later !
-		 */
-		if (!cached)
-			pC->init = 0;
+
+		if (byte_count != pC->cache_size_in_bytes)
+			HPI_DEBUG_LOG(WARNING,
+				"adap %d bytecount %d != cache size %d\n",
+				pC->adap_idx, byte_count,
+				pC->cache_size_in_bytes);
+		else
+			HPI_DEBUG_LOG(DEBUG,
+				"adap %d cache good, bytecount == cache size = %d\n",
+				pC->adap_idx, byte_count);
+
+		pC->init = (u16)cached;
 	}
 	return pC->init;
 }
 
 /** Find a control.
 */
-static short find_control(struct hpi_message *phm,
-	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
-	u16 *pw_control_index)
+static short find_control(u16 control_index,
+	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
 {
-	*pw_control_index = phm->obj_index;
-
 	if (!control_cache_alloc_check(p_cache)) {
 		HPI_DEBUG_LOG(VERBOSE,
-			"control_cache_alloc_check() failed. adap%d ci%d\n",
-			phm->adapter_index, *pw_control_index);
+			"control_cache_alloc_check() failed %d\n",
+			control_index);
 		return 0;
 	}
 
-	*pI = p_cache->p_info[*pw_control_index];
+	*pI = p_cache->p_info[control_index];
 	if (!*pI) {
-		HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
-			phm->adapter_index, *pw_control_index);
+		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
+			control_index);
 		return 0;
 	} else {
 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
@@ -247,25 +288,6 @@ static short find_control(struct hpi_message *phm,
 	return 1;
 }
 
-/** Used by the kernel driver to figure out if a buffer needs mapping.
- */
-short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
-	struct hpi_message *phm, void **p, unsigned int *pN)
-{
-	*pN = 0;
-	*p = NULL;
-	if ((phm->function == HPI_CONTROL_GET_STATE)
-		&& (phm->object == HPI_OBJ_CONTROLEX)
-		) {
-		u16 control_index;
-		struct hpi_control_cache_info *pI;
-
-		if (!find_control(phm, p_cache, &pI, &control_index))
-			return 0;
-	}
-	return 0;
-}
-
 /* allow unified treatment of several string fields within struct */
 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
 	offsetof(struct hpi_control_cache_pad, m), \
@@ -290,13 +312,16 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 	struct hpi_message *phm, struct hpi_response *phr)
 {
 	short found = 1;
-	u16 control_index;
 	struct hpi_control_cache_info *pI;
 	struct hpi_control_cache_single *pC;
 	struct hpi_control_cache_pad *p_pad;
 
-	if (!find_control(phm, p_cache, &pI, &control_index))
+	if (!find_control(phm->obj_index, p_cache, &pI)) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"HPICMN find_control() failed for adap %d\n",
+			phm->adapter_index);
 		return 0;
+	}
 
 	phr->error = 0;
 
@@ -310,55 +335,79 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 
 	case HPI_CONTROL_METER:
 		if (phm->u.c.attribute == HPI_METER_PEAK) {
-			phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0];
-			phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1];
+			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
+			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
-			phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0];
-			phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1];
+			if (pC->u.meter.an_logRMS[0] ==
+				HPI_CACHE_INVALID_SHORT) {
+				phr->error =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
+				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
+			} else {
+				phr->u.c.an_log_value[0] =
+					pC->u.meter.an_logRMS[0];
+				phr->u.c.an_log_value[1] =
+					pC->u.meter.an_logRMS[1];
+			}
 		} else
 			found = 0;
 		break;
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
-			phr->u.c.an_log_value[0] = pC->u.v.an_log[0];
-			phr->u.c.an_log_value[1] = pC->u.v.an_log[1];
-		} else
+			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
+			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
+		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
+			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
+				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
+					phr->u.c.param1 =
+						HPI_BITMASK_ALL_CHANNELS;
+				else
+					phr->u.c.param1 = 0;
+			} else {
+				phr->error =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+				phr->u.c.param1 = 0;
+			}
+		} else {
 			found = 0;
+		}
 		break;
 	case HPI_CONTROL_MULTIPLEXER:
 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
-			phr->u.c.param1 = pC->u.x.source_node_type;
-			phr->u.c.param2 = pC->u.x.source_node_index;
+			phr->u.c.param1 = pC->u.mux.source_node_type;
+			phr->u.c.param2 = pC->u.mux.source_node_index;
 		} else {
 			found = 0;
 		}
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
-			phr->u.c.param1 = pC->u.m.mode;
+			phr->u.c.param1 = pC->u.mode.mode;
 		else
 			found = 0;
 		break;
 	case HPI_CONTROL_LEVEL:
 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
-			phr->u.c.an_log_value[0] = pC->u.l.an_log[0];
-			phr->u.c.an_log_value[1] = pC->u.l.an_log[1];
+			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
+			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
 		} else
 			found = 0;
 		break;
 	case HPI_CONTROL_TUNER:
 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
-			phr->u.c.param1 = pC->u.t.freq_ink_hz;
+			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
-			phr->u.c.param1 = pC->u.t.band;
-		else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
-			&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
-			if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
-				phr->u.c.param1 = 0;
+			phr->u.c.param1 = pC->u.tuner.band;
+		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
+			if (pC->u.tuner.s_level_avg ==
+				HPI_CACHE_INVALID_SHORT) {
+				phr->u.cu.tuner.s_level = 0;
 				phr->error =
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 			} else
-				phr->u.c.param1 = pC->u.t.level;
+				phr->u.cu.tuner.s_level =
+					pC->u.tuner.s_level_avg;
 		else
 			found = 0;
 		break;
@@ -366,7 +415,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
 			phr->u.c.param1 = pC->u.aes3rx.error_status;
 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
-			phr->u.c.param1 = pC->u.aes3rx.source;
+			phr->u.c.param1 = pC->u.aes3rx.format;
 		else
 			found = 0;
 		break;
@@ -385,13 +434,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 	case HPI_CONTROL_SILENCEDETECTOR:
 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
 			phr->u.c.param1 = pC->u.silence.state;
-			phr->u.c.param2 = pC->u.silence.count;
 		} else
 			found = 0;
 		break;
 	case HPI_CONTROL_MICROPHONE:
 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
-			phr->u.c.param1 = pC->u.phantom_power.state;
+			phr->u.c.param1 = pC->u.microphone.phantom_state;
 		else
 			found = 0;
 		break;
@@ -400,7 +448,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 			phr->u.c.param1 = pC->u.clk.source;
 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
 			if (pC->u.clk.source_index ==
-				HPI_ERROR_ILLEGAL_CACHE_VALUE) {
+				HPI_CACHE_INVALID_UINT16) {
 				phr->u.c.param1 = 0;
 				phr->error =
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
@@ -411,60 +459,63 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		else
 			found = 0;
 		break;
-	case HPI_CONTROL_PAD:
+	case HPI_CONTROL_PAD:{
+			struct hpi_control_cache_pad *p_pad;
+			p_pad = (struct hpi_control_cache_pad *)pI;
 
-		if (!(p_pad->field_valid_flags & (1 <<
-					HPI_CTL_ATTR_INDEX(phm->u.c.
-						attribute)))) {
-			phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
-			break;
-		}
-
-		if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
-			phr->u.c.param1 = p_pad->pI;
-		else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
-			phr->u.c.param1 = p_pad->pTY;
-		else {
-			unsigned int index =
-				HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1;
-			unsigned int offset = phm->u.c.param1;
-			unsigned int pad_string_len, field_size;
-			char *pad_string;
-			unsigned int tocopy;
-
-			HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n",
-				phm->u.c.attribute);
-
-			if (index > ARRAY_SIZE(pad_desc) - 1) {
+			if (!(p_pad->field_valid_flags & (1 <<
+						HPI_CTL_ATTR_INDEX(phm->u.c.
+							attribute)))) {
 				phr->error =
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 				break;
 			}
 
-			pad_string = ((char *)p_pad) + pad_desc[index].offset;
-			field_size = pad_desc[index].field_size;
-			/* Ensure null terminator */
-			pad_string[field_size - 1] = 0;
-
-			pad_string_len = strlen(pad_string) + 1;
-
-			if (offset > pad_string_len) {
-				phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
-				break;
+			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
+				phr->u.c.param1 = p_pad->pI;
+			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
+				phr->u.c.param1 = p_pad->pTY;
+			else {
+				unsigned int index =
+					HPI_CTL_ATTR_INDEX(phm->u.c.
+					attribute) - 1;
+				unsigned int offset = phm->u.c.param1;
+				unsigned int pad_string_len, field_size;
+				char *pad_string;
+				unsigned int tocopy;
+
+				if (index > ARRAY_SIZE(pad_desc) - 1) {
+					phr->error =
+						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+					break;
+				}
+
+				pad_string =
+					((char *)p_pad) +
+					pad_desc[index].offset;
+				field_size = pad_desc[index].field_size;
+				/* Ensure null terminator */
+				pad_string[field_size - 1] = 0;
+
+				pad_string_len = strlen(pad_string) + 1;
+
+				if (offset > pad_string_len) {
+					phr->error =
+						HPI_ERROR_INVALID_CONTROL_VALUE;
+					break;
+				}
+
+				tocopy = pad_string_len - offset;
+				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
+					tocopy = sizeof(phr->u.cu.chars8.
+						sz_data);
+
+				memcpy(phr->u.cu.chars8.sz_data,
+					&pad_string[offset], tocopy);
+
+				phr->u.cu.chars8.remaining_chars =
+					pad_string_len - offset - tocopy;
 			}
-
-			tocopy = pad_string_len - offset;
-			if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
-				tocopy = sizeof(phr->u.cu.chars8.sz_data);
-
-			HPI_DEBUG_LOG(VERBOSE,
-				"PADS memcpy(%d), offset %d \n", tocopy,
-				offset);
-			memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset],
-				tocopy);
-
-			phr->u.cu.chars8.remaining_chars =
-				pad_string_len - offset - tocopy;
 		}
 		break;
 	default:
@@ -472,16 +523,9 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		break;
 	}
 
-	if (found)
-		HPI_DEBUG_LOG(VERBOSE,
-			"cached adap %d, ctl %d, type %d, attr %d\n",
-			phm->adapter_index, pI->control_index,
-			pI->control_type, phm->u.c.attribute);
-	else
-		HPI_DEBUG_LOG(VERBOSE,
-			"uncached adap %d, ctl %d, ctl type %d\n",
-			phm->adapter_index, pI->control_index,
-			pI->control_type);
+	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
+		found ? "Cached" : "Uncached", phm->adapter_index,
+		pI->control_index, pI->control_type, phm->u.c.attribute);
 
 	if (found)
 		phr->size =
@@ -497,18 +541,21 @@ Only update if no error.
 Volume and Level return the limited values in the response, so use these
 Multiplexer does so use sent values
 */
-void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
+void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
 	struct hpi_message *phm, struct hpi_response *phr)
 {
-	u16 control_index;
 	struct hpi_control_cache_single *pC;
 	struct hpi_control_cache_info *pI;
 
 	if (phr->error)
 		return;
 
-	if (!find_control(phm, p_cache, &pI, &control_index))
+	if (!find_control(phm->obj_index, p_cache, &pI)) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"HPICMN find_control() failed for adap %d\n",
+			phm->adapter_index);
 		return;
+	}
 
 	/* pC is the default cached control strucure.
 	   May be cast to something else in the following switch statement.
@@ -518,31 +565,36 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
 	switch (pI->control_type) {
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
-			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
-			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
+			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
+			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
+		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
+			if (phm->u.c.param1)
+				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
+			else
+				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
 		}
 		break;
 	case HPI_CONTROL_MULTIPLEXER:
 		/* mux does not return its setting on Set command. */
 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
-			pC->u.x.source_node_type = (u16)phm->u.c.param1;
-			pC->u.x.source_node_index = (u16)phm->u.c.param2;
+			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
+			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
 		}
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
 		/* mode does not return its setting on Set command. */
 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
-			pC->u.m.mode = (u16)phm->u.c.param1;
+			pC->u.mode.mode = (u16)phm->u.c.param1;
 		break;
 	case HPI_CONTROL_LEVEL:
 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
-			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
-			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
+			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
+			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
 		}
 		break;
 	case HPI_CONTROL_MICROPHONE:
 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
-			pC->u.phantom_power.state = (u16)phm->u.c.param1;
+			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
 		break;
 	case HPI_CONTROL_AESEBU_TRANSMITTER:
 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
@@ -550,7 +602,7 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
 		break;
 	case HPI_CONTROL_AESEBU_RECEIVER:
 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
-			pC->u.aes3rx.source = phm->u.c.param1;
+			pC->u.aes3rx.format = phm->u.c.param1;
 		break;
 	case HPI_CONTROL_SAMPLECLOCK:
 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
@@ -565,59 +617,57 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
 	}
 }
 
-struct hpi_control_cache *hpi_alloc_control_cache(const u32
-	number_of_controls, const u32 size_in_bytes,
-	struct hpi_control_cache_info *pDSP_control_buffer)
+struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
+	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
 {
 	struct hpi_control_cache *p_cache =
 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
 	if (!p_cache)
 		return NULL;
+
 	p_cache->p_info =
-		kmalloc(sizeof(*p_cache->p_info) * number_of_controls,
-			GFP_KERNEL);
+		kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
 	if (!p_cache->p_info) {
 		kfree(p_cache);
 		return NULL;
 	}
+	memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
 	p_cache->cache_size_in_bytes = size_in_bytes;
-	p_cache->control_count = number_of_controls;
-	p_cache->p_cache =
-		(struct hpi_control_cache_single *)pDSP_control_buffer;
+	p_cache->control_count = control_count;
+	p_cache->p_cache = p_dsp_control_buffer;
 	p_cache->init = 0;
 	return p_cache;
 }
 
 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
 {
-	if (p_cache->init) {
+	if (p_cache) {
 		kfree(p_cache->p_info);
-		p_cache->p_info = NULL;
-		p_cache->init = 0;
 		kfree(p_cache);
 	}
 }
 
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 {
+	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
 
 	switch (phm->function) {
 	case HPI_SUBSYS_OPEN:
 	case HPI_SUBSYS_CLOSE:
 	case HPI_SUBSYS_DRIVER_UNLOAD:
-		phr->error = 0;
 		break;
 	case HPI_SUBSYS_DRIVER_LOAD:
 		wipe_adapter_list();
 		hpios_alistlock_init(&adapters);
-		phr->error = 0;
 		break;
-	case HPI_SUBSYS_GET_INFO:
-		subsys_get_adapters(phr);
+	case HPI_SUBSYS_GET_ADAPTER:
+		subsys_get_adapter(phm, phr);
+		break;
+	case HPI_SUBSYS_GET_NUM_ADAPTERS:
+		phr->u.s.num_adapters = adapters.gw_num_adapters;
 		break;
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_SUBSYS_DELETE_ADAPTER:
-		phr->error = 0;
 		break;
 	default:
 		phr->error = HPI_ERROR_INVALID_FUNC;
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h
index 6229022..590f0b6 100644
--- a/sound/pci/asihpi/hpicmn.h
+++ b/sound/pci/asihpi/hpicmn.h
@@ -33,18 +33,19 @@ struct hpi_adapter_obj {
 };
 
 struct hpi_control_cache {
-	u32 init;	     /**< indicates whether the
-				structures are initialized */
+	/** indicates whether the structures are initialized */
+	u16 init;
+	u16 adap_idx;
 	u32 control_count;
 	u32 cache_size_in_bytes;
-	struct hpi_control_cache_info
-	**p_info;		 /**< pointer to allocated memory of
-				lookup pointers. */
-	struct hpi_control_cache_single
-	*p_cache;		 /**< pointer to DSP's control cache. */
+	/** pointer to allocated memory of lookup pointers. */
+	struct hpi_control_cache_info **p_info;
+	/** pointer to DSP's control cache. */
+	u8 *p_cache;
 };
 
 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index);
+
 u16 hpi_add_adapter(struct hpi_adapter_obj *pao);
 
 void hpi_delete_adapter(struct hpi_adapter_obj *pao);
@@ -52,13 +53,10 @@ void hpi_delete_adapter(struct hpi_adapter_obj *pao);
 short hpi_check_control_cache(struct hpi_control_cache *pC,
 	struct hpi_message *phm, struct hpi_response *phr);
 struct hpi_control_cache *hpi_alloc_control_cache(const u32
-	number_of_controls, const u32 size_in_bytes,
-	struct hpi_control_cache_info
-	*pDSP_control_buffer);
+	number_of_controls, const u32 size_in_bytes, u8 *pDSP_control_buffer);
 void hpi_free_control_cache(struct hpi_control_cache *p_cache);
 
-void hpi_sync_control_cache(struct hpi_control_cache *pC,
+void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC,
 	struct hpi_message *phm, struct hpi_response *phr);
+
 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr);
-short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
-	struct hpi_message *phm, void **p, unsigned int *pN);
diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c
index 949836e..b52baf6 100644
--- a/sound/pci/asihpi/hpidebug.c
+++ b/sound/pci/asihpi/hpidebug.c
@@ -45,161 +45,14 @@ int hpi_debug_level_get(void)
 	return hpi_debug_level;
 }
 
-#ifdef HPIOS_DEBUG_PRINT
-/* implies OS has no printf-like function */
-#include <stdarg.h>
-
-void hpi_debug_printf(char *fmt, ...)
-{
-	va_list arglist;
-	char buffer[128];
-
-	va_start(arglist, fmt);
-
-	if (buffer[0])
-		HPIOS_DEBUG_PRINT(buffer);
-	va_end(arglist);
-}
-#endif
-
-struct treenode {
-	void *array;
-	unsigned int num_elements;
-};
-
-#define make_treenode_from_array(nodename, array) \
-static void *tmp_strarray_##nodename[] = array; \
-static struct treenode nodename = { \
-	&tmp_strarray_##nodename, \
-	ARRAY_SIZE(tmp_strarray_##nodename) \
-};
-
-#define get_treenode_elem(node_ptr, idx, type)  \
-	(&(*((type *)(node_ptr)->array)[idx]))
-
-make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
-
-	make_treenode_from_array(hpi_subsys_strings, HPI_SUBSYS_STRINGS)
-	make_treenode_from_array(hpi_adapter_strings, HPI_ADAPTER_STRINGS)
-	make_treenode_from_array(hpi_istream_strings, HPI_ISTREAM_STRINGS)
-	make_treenode_from_array(hpi_ostream_strings, HPI_OSTREAM_STRINGS)
-	make_treenode_from_array(hpi_mixer_strings, HPI_MIXER_STRINGS)
-	make_treenode_from_array(hpi_node_strings,
-	{
-	"NODE is invalid object"})
-
-	make_treenode_from_array(hpi_control_strings, HPI_CONTROL_STRINGS)
-	make_treenode_from_array(hpi_nvmemory_strings, HPI_OBJ_STRINGS)
-	make_treenode_from_array(hpi_digitalio_strings, HPI_DIGITALIO_STRINGS)
-	make_treenode_from_array(hpi_watchdog_strings, HPI_WATCHDOG_STRINGS)
-	make_treenode_from_array(hpi_clock_strings, HPI_CLOCK_STRINGS)
-	make_treenode_from_array(hpi_profile_strings, HPI_PROFILE_STRINGS)
-	make_treenode_from_array(hpi_asyncevent_strings, HPI_ASYNCEVENT_STRINGS)
-#define HPI_FUNCTION_STRINGS \
-{ \
-  &hpi_subsys_strings,\
-  &hpi_adapter_strings,\
-  &hpi_ostream_strings,\
-  &hpi_istream_strings,\
-  &hpi_mixer_strings,\
-  &hpi_node_strings,\
-  &hpi_control_strings,\
-  &hpi_nvmemory_strings,\
-  &hpi_digitalio_strings,\
-  &hpi_watchdog_strings,\
-  &hpi_clock_strings,\
-  &hpi_profile_strings,\
-  &hpi_control_strings, \
-  &hpi_asyncevent_strings \
-}
-	make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
-
-	compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);
-
-static char *hpi_function_string(unsigned int function)
-{
-	unsigned int object;
-	struct treenode *tmp;
-
-	object = function / HPI_OBJ_FUNCTION_SPACING;
-	function = function - object * HPI_OBJ_FUNCTION_SPACING;
-
-	if (object == 0 || object == HPI_OBJ_NODE
-		|| object > hpi_function_strings.num_elements)
-		return "invalid object";
-
-	tmp = get_treenode_elem(&hpi_function_strings, object - 1,
-		struct treenode *);
-
-	if (function == 0 || function > tmp->num_elements)
-		return "invalid function";
-
-	return get_treenode_elem(tmp, function - 1, char *);
-}
-
 void hpi_debug_message(struct hpi_message *phm, char *sz_fileline)
 {
 	if (phm) {
-		if ((phm->object <= HPI_OBJ_MAXINDEX) && phm->object) {
-			u16 index = 0;
-			u16 attrib = 0;
-			int is_control = 0;
-
-			index = phm->obj_index;
-			switch (phm->object) {
-			case HPI_OBJ_ADAPTER:
-			case HPI_OBJ_PROFILE:
-				break;
-			case HPI_OBJ_MIXER:
-				if (phm->function ==
-					HPI_MIXER_GET_CONTROL_BY_INDEX)
-					index = phm->u.m.control_index;
-				break;
-			case HPI_OBJ_OSTREAM:
-			case HPI_OBJ_ISTREAM:
-				break;
-
-			case HPI_OBJ_CONTROLEX:
-			case HPI_OBJ_CONTROL:
-				if (phm->version == 1)
-					attrib = HPI_CTL_ATTR(UNIVERSAL, 1);
-				else
-					attrib = phm->u.c.attribute;
-				is_control = 1;
-				break;
-			default:
-				break;
-			}
-
-			if (is_control && (attrib & 0xFF00)) {
-				int control_type = (attrib & 0xFF00) >> 8;
-				int attr_index = HPI_CTL_ATTR_INDEX(attrib);
-				/* note the KERN facility level
-				   is in szFileline already */
-				printk("%s adapter %d %s "
-					"ctrl_index x%04x %s %d\n",
-					sz_fileline, phm->adapter_index,
-					hpi_function_string(phm->function),
-					index,
-					get_treenode_elem
-					(&hpi_control_type_strings,
-						control_type, char *),
-					attr_index);
-
-			} else
-				printk("%s adapter %d %s "
-					"idx x%04x attr x%04x \n",
-					sz_fileline, phm->adapter_index,
-					hpi_function_string(phm->function),
-					index, attrib);
-		} else {
-			printk("adap=%d, invalid obj=%d, func=0x%x\n",
-				phm->adapter_index, phm->object,
-				phm->function);
-		}
-	} else
-		printk(KERN_ERR
-			"NULL message pointer to hpi_debug_message!\n");
+		printk(KERN_DEBUG "HPI_MSG%d,%d,%d,%d,%d\n", phm->version,
+			phm->adapter_index, phm->obj_index, phm->function,
+			phm->u.c.attribute);
+	}
+
 }
 
 void hpi_debug_data(u16 *pdata, u32 len)
diff --git a/sound/pci/asihpi/hpidebug.h b/sound/pci/asihpi/hpidebug.h
index a2f0952..940f54c 100644
--- a/sound/pci/asihpi/hpidebug.h
+++ b/sound/pci/asihpi/hpidebug.h
@@ -37,7 +37,7 @@ enum { HPI_DEBUG_LEVEL_ERROR = 0,	/* always log errors */
 #define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE
 
 /* an OS can define an extra flag string that is appended to
-   the start of each message, eg see hpios_linux.h */
+   the start of each message, eg see linux kernel hpios.h */
 
 #ifdef SOURCEFILE_NAME
 #define FILE_LINE  SOURCEFILE_NAME ":" __stringify(__LINE__) " "
@@ -45,18 +45,11 @@ enum { HPI_DEBUG_LEVEL_ERROR = 0,	/* always log errors */
 #define FILE_LINE  __FILE__ ":" __stringify(__LINE__) " "
 #endif
 
-#if defined(HPI_DEBUG) && defined(_WINDOWS)
-#define HPI_DEBUGBREAK() debug_break()
-#else
-#define HPI_DEBUGBREAK()
-#endif
-
 #define HPI_DEBUG_ASSERT(expression) \
 	do { \
-		if (!(expression)) {\
-			printk(KERN_ERR  FILE_LINE\
-				"ASSERT " __stringify(expression));\
-			HPI_DEBUGBREAK();\
+		if (!(expression)) { \
+			printk(KERN_ERR  FILE_LINE \
+				"ASSERT " __stringify(expression)); \
 		} \
 	} while (0)
 
@@ -78,28 +71,27 @@ void hpi_debug_message(struct hpi_message *phm, char *sz_fileline);
 
 void hpi_debug_data(u16 *pdata, u32 len);
 
-#define HPI_DEBUG_DATA(pdata, len)                                      \
-	do {                                                            \
+#define HPI_DEBUG_DATA(pdata, len) \
+	do { \
 		if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
 			hpi_debug_data(pdata, len); \
 	} while (0)
 
-#define HPI_DEBUG_MESSAGE(level, phm)                                   \
-	do {                                                            \
-		if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) {         \
-			hpi_debug_message(phm,HPI_DEBUG_FLAG_##level    \
-				FILE_LINE __stringify(level));\
-		}                                                       \
+#define HPI_DEBUG_MESSAGE(level, phm) \
+	do { \
+		if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \
+			hpi_debug_message(phm, HPI_DEBUG_FLAG_##level \
+				FILE_LINE __stringify(level)); \
+		} \
 	} while (0)
 
-#define HPI_DEBUG_RESPONSE(phr)                                         \
-	do {                                                            \
-		if ((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && (phr->error))\
-			HPI_DEBUG_LOG(ERROR, \
-				"HPI response - error# %d\n", \
-				phr->error); \
-		else if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
-			HPI_DEBUG_LOG(VERBOSE, "HPI response OK\n");\
+#define HPI_DEBUG_RESPONSE(phr) \
+	do { \
+		if (((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && \
+			(phr->error)) ||\
+		(hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)) \
+			printk(KERN_DEBUG "HPI_RES%d,%d,%d\n", \
+				phr->version, phr->error, phr->specific_error); \
 	} while (0)
 
 #ifndef compile_time_assert
@@ -107,279 +99,4 @@ void hpi_debug_data(u16 *pdata, u32 len);
     typedef char msg[(cond) ? 1 : -1]
 #endif
 
-	  /* check that size is exactly some number */
-#define function_count_check(sym, size) \
-    compile_time_assert((sym##_FUNCTION_COUNT) == (size),\
-	    strings_match_defs_##sym)
-
-/* These strings should be generated using a macro which defines
-   the corresponding symbol values.  */
-#define HPI_OBJ_STRINGS \
-{                               \
-  "HPI_OBJ_SUBSYSTEM",        \
-  "HPI_OBJ_ADAPTER",          \
-  "HPI_OBJ_OSTREAM",          \
-  "HPI_OBJ_ISTREAM",          \
-  "HPI_OBJ_MIXER",            \
-  "HPI_OBJ_NODE",             \
-  "HPI_OBJ_CONTROL",          \
-  "HPI_OBJ_NVMEMORY",         \
-  "HPI_OBJ_DIGITALIO",        \
-  "HPI_OBJ_WATCHDOG",         \
-  "HPI_OBJ_CLOCK",            \
-  "HPI_OBJ_PROFILE",          \
-  "HPI_OBJ_CONTROLEX"         \
-}
-
-#define HPI_SUBSYS_STRINGS      \
-{                               \
-  "HPI_SUBSYS_OPEN",          \
-  "HPI_SUBSYS_GET_VERSION",   \
-  "HPI_SUBSYS_GET_INFO",      \
-  "HPI_SUBSYS_FIND_ADAPTERS", \
-  "HPI_SUBSYS_CREATE_ADAPTER",\
-  "HPI_SUBSYS_CLOSE",         \
-  "HPI_SUBSYS_DELETE_ADAPTER", \
-  "HPI_SUBSYS_DRIVER_LOAD", \
-  "HPI_SUBSYS_DRIVER_UNLOAD", \
-  "HPI_SUBSYS_READ_PORT_8",   \
-  "HPI_SUBSYS_WRITE_PORT_8",  \
-  "HPI_SUBSYS_GET_NUM_ADAPTERS",\
-  "HPI_SUBSYS_GET_ADAPTER",   \
-  "HPI_SUBSYS_SET_NETWORK_INTERFACE"\
-}
-function_count_check(HPI_SUBSYS, 14);
-
-#define HPI_ADAPTER_STRINGS     \
-{                               \
-  "HPI_ADAPTER_OPEN",         \
-  "HPI_ADAPTER_CLOSE",        \
-  "HPI_ADAPTER_GET_INFO",     \
-  "HPI_ADAPTER_GET_ASSERT",   \
-  "HPI_ADAPTER_TEST_ASSERT",    \
-  "HPI_ADAPTER_SET_MODE",       \
-  "HPI_ADAPTER_GET_MODE",       \
-  "HPI_ADAPTER_ENABLE_CAPABILITY",\
-  "HPI_ADAPTER_SELFTEST",        \
-  "HPI_ADAPTER_FIND_OBJECT",     \
-  "HPI_ADAPTER_QUERY_FLASH",     \
-  "HPI_ADAPTER_START_FLASH",     \
-  "HPI_ADAPTER_PROGRAM_FLASH",   \
-  "HPI_ADAPTER_SET_PROPERTY",    \
-  "HPI_ADAPTER_GET_PROPERTY",    \
-  "HPI_ADAPTER_ENUM_PROPERTY",    \
-  "HPI_ADAPTER_MODULE_INFO",    \
-  "HPI_ADAPTER_DEBUG_READ"    \
-}
-
-function_count_check(HPI_ADAPTER, 18);
-
-#define HPI_OSTREAM_STRINGS     \
-{                               \
-  "HPI_OSTREAM_OPEN",         \
-  "HPI_OSTREAM_CLOSE",        \
-  "HPI_OSTREAM_WRITE",        \
-  "HPI_OSTREAM_START",        \
-  "HPI_OSTREAM_STOP",         \
-  "HPI_OSTREAM_RESET",                \
-  "HPI_OSTREAM_GET_INFO",     \
-  "HPI_OSTREAM_QUERY_FORMAT", \
-  "HPI_OSTREAM_DATA",         \
-  "HPI_OSTREAM_SET_VELOCITY", \
-  "HPI_OSTREAM_SET_PUNCHINOUT", \
-  "HPI_OSTREAM_SINEGEN",        \
-  "HPI_OSTREAM_ANC_RESET",      \
-  "HPI_OSTREAM_ANC_GET_INFO",   \
-  "HPI_OSTREAM_ANC_READ",       \
-  "HPI_OSTREAM_SET_TIMESCALE",\
-  "HPI_OSTREAM_SET_FORMAT", \
-  "HPI_OSTREAM_HOSTBUFFER_ALLOC", \
-  "HPI_OSTREAM_HOSTBUFFER_FREE", \
-  "HPI_OSTREAM_GROUP_ADD",\
-  "HPI_OSTREAM_GROUP_GETMAP", \
-  "HPI_OSTREAM_GROUP_RESET", \
-  "HPI_OSTREAM_HOSTBUFFER_GET_INFO", \
-  "HPI_OSTREAM_WAIT_START", \
-}
-function_count_check(HPI_OSTREAM, 24);
-
-#define HPI_ISTREAM_STRINGS     \
-{                               \
-  "HPI_ISTREAM_OPEN",         \
-  "HPI_ISTREAM_CLOSE",        \
-  "HPI_ISTREAM_SET_FORMAT",   \
-  "HPI_ISTREAM_READ",         \
-  "HPI_ISTREAM_START",        \
-  "HPI_ISTREAM_STOP",         \
-  "HPI_ISTREAM_RESET",        \
-  "HPI_ISTREAM_GET_INFO",     \
-  "HPI_ISTREAM_QUERY_FORMAT", \
-  "HPI_ISTREAM_ANC_RESET",      \
-  "HPI_ISTREAM_ANC_GET_INFO",   \
-  "HPI_ISTREAM_ANC_WRITE",   \
-  "HPI_ISTREAM_HOSTBUFFER_ALLOC",\
-  "HPI_ISTREAM_HOSTBUFFER_FREE", \
-  "HPI_ISTREAM_GROUP_ADD", \
-  "HPI_ISTREAM_GROUP_GETMAP", \
-  "HPI_ISTREAM_GROUP_RESET", \
-  "HPI_ISTREAM_HOSTBUFFER_GET_INFO", \
-  "HPI_ISTREAM_WAIT_START", \
-}
-function_count_check(HPI_ISTREAM, 19);
-
-#define HPI_MIXER_STRINGS       \
-{                               \
-  "HPI_MIXER_OPEN",           \
-  "HPI_MIXER_CLOSE",          \
-  "HPI_MIXER_GET_INFO",       \
-  "HPI_MIXER_GET_NODE_INFO",  \
-  "HPI_MIXER_GET_CONTROL",    \
-  "HPI_MIXER_SET_CONNECTION", \
-  "HPI_MIXER_GET_CONNECTIONS",        \
-  "HPI_MIXER_GET_CONTROL_BY_INDEX",   \
-  "HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX",     \
-  "HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES",    \
-  "HPI_MIXER_STORE",  \
-}
-function_count_check(HPI_MIXER, 11);
-
-#define HPI_CONTROL_STRINGS     \
-{                               \
-  "HPI_CONTROL_GET_INFO",     \
-  "HPI_CONTROL_GET_STATE",    \
-  "HPI_CONTROL_SET_STATE"     \
-}
-function_count_check(HPI_CONTROL, 3);
-
-#define HPI_NVMEMORY_STRINGS    \
-{                               \
-  "HPI_NVMEMORY_OPEN",        \
-  "HPI_NVMEMORY_READ_BYTE",   \
-  "HPI_NVMEMORY_WRITE_BYTE"   \
-}
-function_count_check(HPI_NVMEMORY, 3);
-
-#define HPI_DIGITALIO_STRINGS   \
-{                               \
-  "HPI_GPIO_OPEN",            \
-  "HPI_GPIO_READ_BIT",        \
-  "HPI_GPIO_WRITE_BIT",       \
-  "HPI_GPIO_READ_ALL",                \
-  "HPI_GPIO_WRITE_STATUS"\
-}
-function_count_check(HPI_GPIO, 5);
-
-#define HPI_WATCHDOG_STRINGS    \
-{                               \
-  "HPI_WATCHDOG_OPEN",        \
-  "HPI_WATCHDOG_SET_TIME",    \
-  "HPI_WATCHDOG_PING"         \
-}
-
-#define HPI_CLOCK_STRINGS       \
-{                               \
-  "HPI_CLOCK_OPEN",           \
-  "HPI_CLOCK_SET_TIME",       \
-  "HPI_CLOCK_GET_TIME"        \
-}
-
-#define HPI_PROFILE_STRINGS     \
-{                               \
-  "HPI_PROFILE_OPEN_ALL",     \
-  "HPI_PROFILE_START_ALL",    \
-  "HPI_PROFILE_STOP_ALL",     \
-  "HPI_PROFILE_GET",          \
-  "HPI_PROFILE_GET_IDLECOUNT",  \
-  "HPI_PROFILE_GET_NAME",       \
-  "HPI_PROFILE_GET_UTILIZATION" \
-}
-function_count_check(HPI_PROFILE, 7);
-
-#define HPI_ASYNCEVENT_STRINGS  \
-{                               \
-  "HPI_ASYNCEVENT_OPEN",\
-  "HPI_ASYNCEVENT_CLOSE  ",\
-  "HPI_ASYNCEVENT_WAIT",\
-  "HPI_ASYNCEVENT_GETCOUNT",\
-  "HPI_ASYNCEVENT_GET",\
-  "HPI_ASYNCEVENT_SENDEVENTS"\
-}
-function_count_check(HPI_ASYNCEVENT, 6);
-
-#define HPI_CONTROL_TYPE_STRINGS \
-{ \
-	"null control", \
-	"HPI_CONTROL_CONNECTION", \
-	"HPI_CONTROL_VOLUME", \
-	"HPI_CONTROL_METER", \
-	"HPI_CONTROL_MUTE", \
-	"HPI_CONTROL_MULTIPLEXER", \
-	"HPI_CONTROL_AESEBU_TRANSMITTER", \
-	"HPI_CONTROL_AESEBU_RECEIVER", \
-	"HPI_CONTROL_LEVEL", \
-	"HPI_CONTROL_TUNER", \
-	"HPI_CONTROL_ONOFFSWITCH", \
-	"HPI_CONTROL_VOX", \
-	"HPI_CONTROL_AES18_TRANSMITTER", \
-	"HPI_CONTROL_AES18_RECEIVER", \
-	"HPI_CONTROL_AES18_BLOCKGENERATOR", \
-	"HPI_CONTROL_CHANNEL_MODE", \
-	"HPI_CONTROL_BITSTREAM", \
-	"HPI_CONTROL_SAMPLECLOCK", \
-	"HPI_CONTROL_MICROPHONE", \
-	"HPI_CONTROL_PARAMETRIC_EQ", \
-	"HPI_CONTROL_COMPANDER", \
-	"HPI_CONTROL_COBRANET", \
-	"HPI_CONTROL_TONE_DETECT", \
-	"HPI_CONTROL_SILENCE_DETECT", \
-	"HPI_CONTROL_PAD", \
-	"HPI_CONTROL_SRC" ,\
-	"HPI_CONTROL_UNIVERSAL" \
-}
-
-compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
-	controltype_strings_match_defs);
-
-#define HPI_SOURCENODE_STRINGS \
-{ \
-	"no source", \
-	"HPI_SOURCENODE_OSTREAM", \
-	"HPI_SOURCENODE_LINEIN", \
-	"HPI_SOURCENODE_AESEBU_IN", \
-	"HPI_SOURCENODE_TUNER", \
-	"HPI_SOURCENODE_RF", \
-	"HPI_SOURCENODE_CLOCK_SOURCE", \
-	"HPI_SOURCENODE_RAW_BITSTREAM", \
-	"HPI_SOURCENODE_MICROPHONE", \
-	"HPI_SOURCENODE_COBRANET", \
-	"HPI_SOURCENODE_ANALOG", \
-	"HPI_SOURCENODE_ADAPTER" \
-}
-
-compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_NONE + 1) ==
-	(12), sourcenode_strings_match_defs);
-
-#define HPI_DESTNODE_STRINGS \
-{ \
-	"no destination", \
-	"HPI_DESTNODE_ISTREAM", \
-	"HPI_DESTNODE_LINEOUT", \
-	"HPI_DESTNODE_AESEBU_OUT", \
-	"HPI_DESTNODE_RF", \
-	"HPI_DESTNODE_SPEAKER", \
-	"HPI_DESTNODE_COBRANET", \
-	"HPI_DESTNODE_ANALOG" \
-}
-compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_NONE + 1) == (8),
-	destnode_strings_match_defs);
-
-#define HPI_CONTROL_CHANNEL_MODE_STRINGS \
-{ \
-	"XXX HPI_CHANNEL_MODE_ERROR XXX", \
-	"HPI_CHANNEL_MODE_NORMAL", \
-	"HPI_CHANNEL_MODE_SWAP", \
-	"HPI_CHANNEL_MODE_LEFT_ONLY", \
-	"HPI_CHANNEL_MODE_RIGHT_ONLY" \
-}
-
-#endif				/* _HPIDEBUG_H  */
+#endif				/* _HPIDEBUG_H_  */
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
index 9b10d9a..fb311d8 100644
--- a/sound/pci/asihpi/hpidspcd.c
+++ b/sound/pci/asihpi/hpidspcd.c
@@ -71,47 +71,50 @@ short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
 	int err;
 
 	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
-	HPI_DEBUG_LOG(INFO, "requesting firmware for %s\n", fw_name);
 
 	err = request_firmware(&ps_firmware, fw_name,
 		&ps_dsp_code->ps_dev->dev);
+
 	if (err != 0) {
-		HPI_DEBUG_LOG(ERROR, "%d, request_firmware failed for  %s\n",
-			err, fw_name);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"%d, request_firmware failed for  %s\n", err,
+			fw_name);
 		goto error1;
 	}
 	if (ps_firmware->size < sizeof(header)) {
-		HPI_DEBUG_LOG(ERROR, "header size too small %s\n", fw_name);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Header size too small %s\n", fw_name);
 		goto error2;
 	}
 	memcpy(&header, ps_firmware->data, sizeof(header));
 	if (header.adapter != adapter) {
-		HPI_DEBUG_LOG(ERROR, "adapter type incorrect %4x != %4x\n",
-			header.adapter, adapter);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Adapter type incorrect %4x != %4x\n", header.adapter,
+			adapter);
 		goto error2;
 	}
 	if (header.size != ps_firmware->size) {
-		HPI_DEBUG_LOG(ERROR, "code size wrong  %d != %ld\n",
-			header.size, (unsigned long)ps_firmware->size);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Code size wrong  %d != %ld\n", header.size,
+			(unsigned long)ps_firmware->size);
 		goto error2;
 	}
 
-	if (header.version / 10000 != HPI_VER_DECIMAL / 10000) {
-		HPI_DEBUG_LOG(ERROR,
-			"firmware major version mismatch "
-			"DSP image %d != driver %d\n", header.version,
+	if (header.version / 100 != HPI_VER_DECIMAL / 100) {
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Incompatible firmware version "
+			"DSP image %d != Driver %d\n", header.version,
 			HPI_VER_DECIMAL);
 		goto error2;
 	}
 
 	if (header.version != HPI_VER_DECIMAL) {
-		HPI_DEBUG_LOG(WARNING,
-			"version mismatch  DSP image %d != driver %d\n",
+		dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev,
+			"Firmware: release version mismatch  DSP image %d != Driver %d\n",
 			header.version, HPI_VER_DECIMAL);
-		/* goto error2;  still allow driver to load */
 	}
 
-	HPI_DEBUG_LOG(INFO, "dsp code %s opened\n", fw_name);
+	HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
 	ps_dsp_code->ps_firmware = ps_firmware;
 	ps_dsp_code->block_length = header.size / sizeof(u32);
 	ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
@@ -148,7 +151,7 @@ void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code)
 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword)
 {
 	if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length)
-		return (HPI_ERROR_DSP_FILE_FORMAT);
+		return HPI_ERROR_DSP_FILE_FORMAT;
 
 	*pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code->
 		word_count];
diff --git a/sound/pci/asihpi/hpidspcd.h b/sound/pci/asihpi/hpidspcd.h
index d7c2403..65f0ca7 100644
--- a/sound/pci/asihpi/hpidspcd.h
+++ b/sound/pci/asihpi/hpidspcd.h
@@ -87,7 +87,7 @@ void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code);
 */
 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code,
 				      /**< DSP code descriptor */
-	u32 *pword /**< where to store the read word */
+	u32 *pword /**< Where to store the read word */
 	);
 
 /** Get a block of dsp code into an internal buffer, and provide a pointer to
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index 1e92eb6..c38fc94 100644
--- a/sound/pci/asihpi/hpifunc.c
+++ b/sound/pci/asihpi/hpifunc.c
@@ -30,16 +30,25 @@ u32 hpi_indexes_to_handle(const char c_object, const u16 adapter_index,
 	return handle.w;
 }
 
-void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index,
-	u16 *pw_object_index)
+static u16 hpi_handle_indexes(const u32 h, u16 *p1, u16 *p2)
 {
 	union handle_word uhandle;
-	uhandle.w = handle;
+	if (!h)
+		return HPI_ERROR_INVALID_HANDLE;
+
+	uhandle.w = h;
+
+	*p1 = (u16)uhandle.h.adapter_index;
+	if (p2)
+		*p2 = (u16)uhandle.h.obj_index;
+
+	return 0;
+}
 
-	if (pw_adapter_index)
-		*pw_adapter_index = (u16)uhandle.h.adapter_index;
-	if (pw_object_index)
-		*pw_object_index = (u16)uhandle.h.obj_index;
+void hpi_handle_to_indexes(const u32 handle, u16 *pw_adapter_index,
+	u16 *pw_object_index)
+{
+	hpi_handle_indexes(handle, pw_adapter_index, pw_object_index);
 }
 
 char hpi_handle_object(const u32 handle)
@@ -49,22 +58,6 @@ char hpi_handle_object(const u32 handle)
 	return (char)uhandle.h.obj_type;
 }
 
-#define u32TOINDEX(h, i1) \
-do {\
-	if (h == 0) \
-		return HPI_ERROR_INVALID_OBJ; \
-	else \
-		hpi_handle_to_indexes(h, i1, NULL); \
-} while (0)
-
-#define u32TOINDEXES(h, i1, i2) \
-do {\
-	if (h == 0) \
-		return HPI_ERROR_INVALID_OBJ; \
-	else \
-		hpi_handle_to_indexes(h, i1, i2);\
-} while (0)
-
 void hpi_format_to_msg(struct hpi_msg_format *pMF,
 	const struct hpi_format *pF)
 {
@@ -94,52 +87,13 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR)
 	pSR->u.legacy_stream_info.state = pSR->u.stream_info.state;
 }
 
-static struct hpi_hsubsys gh_subsys;
-
-struct hpi_hsubsys *hpi_subsys_create(void)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-
-	memset(&gh_subsys, 0, sizeof(struct hpi_hsubsys));
-
-	{
-		hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
-			HPI_SUBSYS_OPEN);
-		hpi_send_recv(&hm, &hr);
-
-		if (hr.error == 0)
-			return &gh_subsys;
-
-	}
-	return NULL;
-}
-
-void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
-		HPI_SUBSYS_CLOSE);
-	hpi_send_recv(&hm, &hr);
-
-}
-
-u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys, u32 *pversion)
+static inline void hpi_send_recvV1(struct hpi_message_header *m,
+	struct hpi_response_header *r)
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
-
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
-		HPI_SUBSYS_GET_VERSION);
-	hpi_send_recv(&hm, &hr);
-	*pversion = hr.u.s.version;
-	return hr.error;
+	hpi_send_recv((struct hpi_message *)m, (struct hpi_response *)r);
 }
 
-u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 *pversion_ex)
+u16 hpi_subsys_get_version_ex(u32 *pversion_ex)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -151,51 +105,8 @@ u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion,
-	u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
-		HPI_SUBSYS_GET_INFO);
-
-	hpi_send_recv(&hm, &hr);
-
-	*pversion = hr.u.s.version;
-	if (list_length > HPI_MAX_ADAPTERS)
-		memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list,
-			HPI_MAX_ADAPTERS);
-	else
-		memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list, list_length);
-	*pw_num_adapters = hr.u.s.num_adapters;
-	return hr.error;
-}
-
-u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys,
-	u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
-		HPI_SUBSYS_FIND_ADAPTERS);
-
-	hpi_send_recv(&hm, &hr);
-
-	if (list_length > HPI_MAX_ADAPTERS) {
-		memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list,
-			HPI_MAX_ADAPTERS * sizeof(u16));
-		memset(&aw_adapter_list[HPI_MAX_ADAPTERS], 0,
-			(list_length - HPI_MAX_ADAPTERS) * sizeof(u16));
-	} else
-		memcpy(aw_adapter_list, &hr.u.s.aw_adapter_list,
-			list_length * sizeof(u16));
-	*pw_num_adapters = hr.u.s.num_adapters;
-
-	return hr.error;
-}
-
-u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys,
-	const struct hpi_resource *p_resource, u16 *pw_adapter_index)
+u16 hpi_subsys_create_adapter(const struct hpi_resource *p_resource,
+	u16 *pw_adapter_index)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -210,20 +121,18 @@ u16 hpi_subsys_create_adapter(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_subsys_delete_adapter(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index)
+u16 hpi_subsys_delete_adapter(u16 adapter_index)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_DELETE_ADAPTER);
-	hm.adapter_index = adapter_index;
+	hm.obj_index = adapter_index;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys,
-	int *pn_num_adapters)
+u16 hpi_subsys_get_num_adapters(int *pn_num_adapters)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -234,35 +143,22 @@ u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator,
-	u32 *padapter_index, u16 *pw_adapter_type)
+u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index,
+	u16 *pw_adapter_type)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_GET_ADAPTER);
-	hm.adapter_index = (u16)iterator;
+	hm.obj_index = (u16)iterator;
 	hpi_send_recv(&hm, &hr);
 	*padapter_index = (int)hr.u.s.adapter_index;
-	*pw_adapter_type = hr.u.s.aw_adapter_list[0];
-	return hr.error;
-}
+	*pw_adapter_type = hr.u.s.adapter_type;
 
-u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys,
-	const char *sz_interface)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
-		HPI_SUBSYS_SET_NETWORK_INTERFACE);
-	if (sz_interface == NULL)
-		return HPI_ERROR_INVALID_RESOURCE;
-	hm.u.s.resource.r.net_if = sz_interface;
-	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index)
+u16 hpi_adapter_open(u16 adapter_index)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -276,7 +172,7 @@ u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index)
 
 }
 
-u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index)
+u16 hpi_adapter_close(u16 adapter_index)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -289,15 +185,14 @@ u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index)
 	return hr.error;
 }
 
-u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 adapter_mode)
+u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode)
 {
-	return hpi_adapter_set_mode_ex(ph_subsys, adapter_index, adapter_mode,
+	return hpi_adapter_set_mode_ex(adapter_index, adapter_mode,
 		HPI_ADAPTER_MODE_SET);
 }
 
-u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 adapter_mode, u16 query_or_set)
+u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode,
+	u16 query_or_set)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -305,14 +200,13 @@ u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
 		HPI_ADAPTER_SET_MODE);
 	hm.adapter_index = adapter_index;
-	hm.u.a.adapter_mode = adapter_mode;
-	hm.u.a.assert_id = query_or_set;
+	hm.u.ax.mode.adapter_mode = adapter_mode;
+	hm.u.ax.mode.query_or_set = query_or_set;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 *padapter_mode)
+u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -321,13 +215,13 @@ u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys,
 	hm.adapter_index = adapter_index;
 	hpi_send_recv(&hm, &hr);
 	if (padapter_mode)
-		*padapter_mode = hr.u.a.serial_number;
+		*padapter_mode = hr.u.ax.mode.adapter_mode;
 	return hr.error;
 }
 
-u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams,
-	u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type)
+u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams,
+	u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number,
+	u16 *pw_adapter_type)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -337,18 +231,17 @@ u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_send_recv(&hm, &hr);
 
-	*pw_adapter_type = hr.u.a.adapter_type;
-	*pw_num_outstreams = hr.u.a.num_outstreams;
-	*pw_num_instreams = hr.u.a.num_instreams;
-	*pw_version = hr.u.a.version;
-	*pserial_number = hr.u.a.serial_number;
+	*pw_adapter_type = hr.u.ax.info.adapter_type;
+	*pw_num_outstreams = hr.u.ax.info.num_outstreams;
+	*pw_num_instreams = hr.u.ax.info.num_instreams;
+	*pw_version = hr.u.ax.info.version;
+	*pserial_number = hr.u.ax.info.serial_number;
 	return hr.error;
 }
 
-u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 module_index, u16 *pw_num_outputs,
-	u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number,
-	u16 *pw_module_type, u32 *ph_module)
+u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index,
+	u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version,
+	u32 *pserial_number, u16 *pw_module_type, u32 *ph_module)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -360,173 +253,18 @@ u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_send_recv(&hm, &hr);
 
-	*pw_module_type = hr.u.a.adapter_type;
-	*pw_num_outputs = hr.u.a.num_outstreams;
-	*pw_num_inputs = hr.u.a.num_instreams;
-	*pw_version = hr.u.a.version;
-	*pserial_number = hr.u.a.serial_number;
+	*pw_module_type = hr.u.ax.info.adapter_type;
+	*pw_num_outputs = hr.u.ax.info.num_outstreams;
+	*pw_num_inputs = hr.u.ax.info.num_instreams;
+	*pw_version = hr.u.ax.info.version;
+	*pserial_number = hr.u.ax.info.serial_number;
 	*ph_module = 0;
 
 	return hr.error;
 }
 
-u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *assert_present, char *psz_assert,
-	u16 *pw_line_number)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
-		HPI_ADAPTER_GET_ASSERT);
-	hm.adapter_index = adapter_index;
-	hpi_send_recv(&hm, &hr);
-
-	*assert_present = 0;
-
-	if (!hr.error) {
-
-		*pw_line_number = (u16)hr.u.a.serial_number;
-		if (*pw_line_number) {
-
-			int i;
-			char *src = (char *)hr.u.a.sz_adapter_assert;
-			char *dst = psz_assert;
-
-			*assert_present = 1;
-
-			for (i = 0; i < HPI_STRING_LEN; i++) {
-				char c;
-				c = *src++;
-				*dst++ = c;
-				if (c == 0)
-					break;
-			}
-
-		}
-	}
-	return hr.error;
-}
-
-u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *assert_present, char *psz_assert,
-	u32 *pline_number, u16 *pw_assert_on_dsp)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
-		HPI_ADAPTER_GET_ASSERT);
-	hm.adapter_index = adapter_index;
-
-	hpi_send_recv(&hm, &hr);
-
-	*assert_present = 0;
-
-	if (!hr.error) {
-
-		*pline_number = hr.u.a.serial_number;
-
-		*assert_present = hr.u.a.adapter_type;
-
-		*pw_assert_on_dsp = hr.u.a.adapter_index;
-
-		if (!*assert_present && *pline_number)
-
-			*assert_present = 1;
-
-		if (*assert_present) {
-
-			int i;
-			char *src = (char *)hr.u.a.sz_adapter_assert;
-			char *dst = psz_assert;
-
-			for (i = 0; i < HPI_STRING_LEN; i++) {
-				char c;
-				c = *src++;
-				*dst++ = c;
-				if (c == 0)
-					break;
-			}
-
-		} else {
-			*psz_assert = 0;
-		}
-	}
-	return hr.error;
-}
-
-u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 assert_id)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
-		HPI_ADAPTER_TEST_ASSERT);
-	hm.adapter_index = adapter_index;
-	hm.u.a.assert_id = assert_id;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 capability, u32 key)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
-		HPI_ADAPTER_ENABLE_CAPABILITY);
-	hm.adapter_index = adapter_index;
-	hm.u.a.assert_id = capability;
-	hm.u.a.adapter_mode = key;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
-		HPI_ADAPTER_SELFTEST);
-	hm.adapter_index = adapter_index;
-	hpi_send_recv(&hm, &hr);
-	return hr.error;
-}
-
-u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 dsp_address, char *p_buffer, int *count_bytes)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
-		HPI_ADAPTER_DEBUG_READ);
-
-	hr.size = sizeof(hr);
-
-	hm.adapter_index = adapter_index;
-	hm.u.ax.debug_read.dsp_address = dsp_address;
-
-	if (*count_bytes > (int)sizeof(hr.u.bytes))
-		*count_bytes = sizeof(hr.u.bytes);
-
-	hm.u.ax.debug_read.count_bytes = *count_bytes;
-
-	hpi_send_recv(&hm, &hr);
-
-	if (!hr.error) {
-		*count_bytes = hr.size - 12;
-		memcpy(p_buffer, &hr.u.bytes, *count_bytes);
-	} else
-		*count_bytes = 0;
-	return hr.error;
-}
-
-u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 property, u16 parameter1, u16 parameter2)
+u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 parameter1,
+	u16 parameter2)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -542,9 +280,8 @@ u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 property, u16 *pw_parameter1,
-	u16 *pw_parameter2)
+u16 hpi_adapter_get_property(u16 adapter_index, u16 property,
+	u16 *pw_parameter1, u16 *pw_parameter2)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -564,9 +301,8 @@ u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 index, u16 what_to_enumerate,
-	u16 property_index, u32 *psetting)
+u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index,
+	u16 what_to_enumerate, u16 property_index, u32 *psetting)
 {
 	return 0;
 }
@@ -574,7 +310,7 @@ u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 	u32 sample_rate, u32 bit_rate, u32 attributes)
 {
-	u16 error = 0;
+	u16 err = 0;
 	struct hpi_msg_format fmt;
 
 	switch (channels) {
@@ -586,8 +322,8 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 	case 16:
 		break;
 	default:
-		error = HPI_ERROR_INVALID_CHANNELS;
-		return error;
+		err = HPI_ERROR_INVALID_CHANNELS;
+		return err;
 	}
 	fmt.channels = channels;
 
@@ -610,17 +346,17 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 	case HPI_FORMAT_OEM2:
 		break;
 	default:
-		error = HPI_ERROR_INVALID_FORMAT;
-		return error;
+		err = HPI_ERROR_INVALID_FORMAT;
+		return err;
 	}
 	fmt.format = format;
 
 	if (sample_rate < 8000L) {
-		error = HPI_ERROR_INCOMPATIBLE_SAMPLERATE;
+		err = HPI_ERROR_INCOMPATIBLE_SAMPLERATE;
 		sample_rate = 8000L;
 	}
 	if (sample_rate > 200000L) {
-		error = HPI_ERROR_INCOMPATIBLE_SAMPLERATE;
+		err = HPI_ERROR_INCOMPATIBLE_SAMPLERATE;
 		sample_rate = 200000L;
 	}
 	fmt.sample_rate = sample_rate;
@@ -651,10 +387,10 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 		if ((channels == 1)
 			&& (attributes != HPI_MPEG_MODE_DEFAULT)) {
 			attributes = HPI_MPEG_MODE_DEFAULT;
-			error = HPI_ERROR_INVALID_FORMAT;
+			err = HPI_ERROR_INVALID_FORMAT;
 		} else if (attributes > HPI_MPEG_MODE_DUALCHANNEL) {
 			attributes = HPI_MPEG_MODE_DEFAULT;
-			error = HPI_ERROR_INVALID_FORMAT;
+			err = HPI_ERROR_INVALID_FORMAT;
 		}
 		fmt.attributes = attributes;
 		break;
@@ -663,7 +399,7 @@ u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 	}
 
 	hpi_msg_to_format(p_format, &fmt);
-	return error;
+	return err;
 }
 
 u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format,
@@ -712,8 +448,8 @@ u16 hpi_stream_estimate_buffer_size(struct hpi_format *p_format,
 	return 0;
 }
 
-u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u16 outstream_index, u32 *ph_outstream)
+u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index,
+	u32 *ph_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -733,38 +469,41 @@ u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
 	return hr.error;
 }
 
-u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
+u16 hpi_outstream_close(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_HOSTBUFFER_FREE);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
+
 	hpi_send_recv(&hm, &hr);
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_GROUP_RESET);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index);
 	hpi_send_recv(&hm, &hr);
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_CLOSE);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index);
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play,
-	u32 *psamples_played, u32 *pauxiliary_data_to_play)
+u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state,
+	u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played,
+	u32 *pauxiliary_data_to_play)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_GET_INFO);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
@@ -782,15 +521,15 @@ u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, const u8 *pb_data, u32 bytes_to_write,
-	const struct hpi_format *p_format)
+u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_data,
+	u32 bytes_to_write, const struct hpi_format *p_format)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_WRITE);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.pb_data = (u8 *)pb_data;
 	hm.u.d.u.data.data_size = bytes_to_write;
 
@@ -801,82 +540,85 @@ u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
+u16 hpi_outstream_start(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_START);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream)
+u16 hpi_outstream_wait_start(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_WAIT_START);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
+u16 hpi_outstream_stop(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_STOP);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream)
+u16 hpi_outstream_sinegen(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_SINEGEN);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream)
+u16 hpi_outstream_reset(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_RESET);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_format *p_format)
+u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_QUERY_FORMAT);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
 
@@ -885,15 +627,15 @@ u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_format *p_format)
+u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_SET_FORMAT);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
 
@@ -902,15 +644,15 @@ u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, short velocity)
+u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_SET_VELOCITY);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.velocity = velocity;
 
 	hpi_send_recv(&hm, &hr);
@@ -918,15 +660,16 @@ u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample)
+u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample,
+	u32 punch_out_sample)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_SET_PUNCHINOUT);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.d.u.pio.punch_in_sample = punch_in_sample;
 	hm.u.d.u.pio.punch_out_sample = punch_out_sample;
@@ -936,29 +679,29 @@ u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u16 mode)
+u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_ANC_RESET);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.format.channels = mode;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 *pframes_available)
+u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_ANC_GET_INFO);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 	if (hr.error == 0) {
 		if (pframes_available)
@@ -969,8 +712,8 @@ u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer,
+u16 hpi_outstream_ancillary_read(u32 h_outstream,
+	struct hpi_anc_frame *p_anc_frame_buffer,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 number_of_ancillary_frames_to_read)
 {
@@ -979,7 +722,8 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_ANC_READ);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer;
 	hm.u.d.u.data.data_size =
 		number_of_ancillary_frames_to_read *
@@ -987,19 +731,19 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
 	if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes)
 		hpi_send_recv(&hm, &hr);
 	else
-		hr.error = HPI_ERROR_INVALID_DATA_TRANSFER;
+		hr.error = HPI_ERROR_INVALID_DATASIZE;
 	return hr.error;
 }
 
-u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 time_scale)
+u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scale)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_SET_TIMESCALE);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.d.u.time_scale = time_scale;
 
@@ -1008,22 +752,21 @@ u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 size_in_bytes)
+u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_HOSTBUFFER_ALLOC);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.data_size = size_in_bytes;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u8 **pp_buffer,
+u16 hpi_outstream_host_buffer_get_info(u32 h_outstream, u8 **pp_buffer,
 	struct hpi_hostbuffer_status **pp_status)
 {
 	struct hpi_message hm;
@@ -1031,7 +774,8 @@ u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_HOSTBUFFER_GET_INFO);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 
 	if (hr.error == 0) {
@@ -1043,21 +787,20 @@ u16 hpi_outstream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream)
+u16 hpi_outstream_host_buffer_free(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_HOSTBUFFER_FREE);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 h_stream)
+u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -1066,22 +809,22 @@ u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_GROUP_ADD);
-	hr.error = 0;
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
+
+	if (hpi_handle_indexes(h_stream, &adapter,
+			&hm.u.d.u.stream.stream_index))
+		return HPI_ERROR_INVALID_HANDLE;
+
 	c_obj_type = hpi_handle_object(h_stream);
 	switch (c_obj_type) {
 	case HPI_OBJ_OSTREAM:
-		hm.u.d.u.stream.object_type = HPI_OBJ_OSTREAM;
-		u32TOINDEXES(h_stream, &adapter,
-			&hm.u.d.u.stream.stream_index);
-		break;
 	case HPI_OBJ_ISTREAM:
-		hm.u.d.u.stream.object_type = HPI_OBJ_ISTREAM;
-		u32TOINDEXES(h_stream, &adapter,
-			&hm.u.d.u.stream.stream_index);
+		hm.u.d.u.stream.object_type = c_obj_type;
 		break;
 	default:
-		return HPI_ERROR_INVALID_STREAM;
+		return HPI_ERROR_INVALID_OBJ;
 	}
 	if (adapter != hm.adapter_index)
 		return HPI_ERROR_NO_INTERADAPTER_GROUPS;
@@ -1090,15 +833,16 @@ u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map)
+u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map,
+	u32 *pinstream_map)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_GROUP_GETMAP);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 
 	if (poutstream_map)
@@ -1109,21 +853,20 @@ u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream)
+u16 hpi_outstream_group_reset(u32 h_outstream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_GROUP_RESET);
-	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_outstream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u16 instream_index, u32 *ph_instream)
+u16 hpi_instream_open(u16 adapter_index, u16 instream_index, u32 *ph_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -1145,38 +888,40 @@ u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
 	return hr.error;
 }
 
-u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
+u16 hpi_instream_close(u32 h_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_HOSTBUFFER_FREE);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_GROUP_RESET);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index);
 	hpi_send_recv(&hm, &hr);
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_CLOSE);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index);
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_format *p_format)
+u16 hpi_instream_query_format(u32 h_instream,
+	const struct hpi_format *p_format)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_QUERY_FORMAT);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
 
 	hpi_send_recv(&hm, &hr);
@@ -1184,15 +929,15 @@ u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_format *p_format)
+u16 hpi_instream_set_format(u32 h_instream, const struct hpi_format *p_format)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_SET_FORMAT);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_format_to_msg(&hm.u.d.u.data.format, p_format);
 
 	hpi_send_recv(&hm, &hr);
@@ -1200,15 +945,15 @@ u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream,
-	u8 *pb_data, u32 bytes_to_read)
+u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_data, u32 bytes_to_read)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_READ);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.data_size = bytes_to_read;
 	hm.u.d.u.data.pb_data = pb_data;
 
@@ -1217,72 +962,76 @@ u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream,
 	return hr.error;
 }
 
-u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
+u16 hpi_instream_start(u32 h_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_START);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream)
+u16 hpi_instream_wait_start(u32 h_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_WAIT_START);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
+u16 hpi_instream_stop(u32 h_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_STOP);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream)
+u16 hpi_instream_reset(u32 h_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_RESET);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
 	return hr.error;
 }
 
-u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded,
-	u32 *psamples_recorded, u32 *pauxiliary_data_recorded)
+u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size,
+	u32 *pdata_recorded, u32 *psamples_recorded,
+	u32 *pauxiliary_data_recorded)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_GET_INFO);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hpi_send_recv(&hm, &hr);
 
@@ -1300,15 +1049,15 @@ u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment,
-	u16 idle_bit)
+u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame,
+	u16 mode, u16 alignment, u16 idle_bit)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_ANC_RESET);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.format.attributes = bytes_per_frame;
 	hm.u.d.u.data.format.format = (mode << 8) | (alignment & 0xff);
 	hm.u.d.u.data.format.channels = idle_bit;
@@ -1316,14 +1065,14 @@ u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 *pframe_space)
+u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_ANC_GET_INFO);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 	if (pframe_space)
 		*pframe_space =
@@ -1333,8 +1082,8 @@ u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer,
+u16 hpi_instream_ancillary_write(u32 h_instream,
+	const struct hpi_anc_frame *p_anc_frame_buffer,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 number_of_ancillary_frames_to_write)
 {
@@ -1343,7 +1092,8 @@ u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_ANC_WRITE);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.pb_data = (u8 *)p_anc_frame_buffer;
 	hm.u.d.u.data.data_size =
 		number_of_ancillary_frames_to_write *
@@ -1351,12 +1101,11 @@ u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
 	if (hm.u.d.u.data.data_size <= anc_frame_buffer_size_in_bytes)
 		hpi_send_recv(&hm, &hr);
 	else
-		hr.error = HPI_ERROR_INVALID_DATA_TRANSFER;
+		hr.error = HPI_ERROR_INVALID_DATASIZE;
 	return hr.error;
 }
 
-u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 size_in_bytes)
+u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes)
 {
 
 	struct hpi_message hm;
@@ -1364,14 +1113,14 @@ u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_HOSTBUFFER_ALLOC);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.d.u.data.data_size = size_in_bytes;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u8 **pp_buffer,
+u16 hpi_instream_host_buffer_get_info(u32 h_instream, u8 **pp_buffer,
 	struct hpi_hostbuffer_status **pp_status)
 {
 	struct hpi_message hm;
@@ -1379,7 +1128,8 @@ u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_HOSTBUFFER_GET_INFO);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 
 	if (hr.error == 0) {
@@ -1391,8 +1141,7 @@ u16 hpi_instream_host_buffer_get_info(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream)
+u16 hpi_instream_host_buffer_free(u32 h_instream)
 {
 
 	struct hpi_message hm;
@@ -1400,13 +1149,13 @@ u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_HOSTBUFFER_FREE);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 h_stream)
+u16 hpi_instream_group_add(u32 h_instream, u32 h_stream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -1416,22 +1165,23 @@ u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_GROUP_ADD);
 	hr.error = 0;
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
+
+	if (hpi_handle_indexes(h_stream, &adapter,
+			&hm.u.d.u.stream.stream_index))
+		return HPI_ERROR_INVALID_HANDLE;
+
 	c_obj_type = hpi_handle_object(h_stream);
 
 	switch (c_obj_type) {
 	case HPI_OBJ_OSTREAM:
-		hm.u.d.u.stream.object_type = HPI_OBJ_OSTREAM;
-		u32TOINDEXES(h_stream, &adapter,
-			&hm.u.d.u.stream.stream_index);
-		break;
 	case HPI_OBJ_ISTREAM:
-		hm.u.d.u.stream.object_type = HPI_OBJ_ISTREAM;
-		u32TOINDEXES(h_stream, &adapter,
-			&hm.u.d.u.stream.stream_index);
+		hm.u.d.u.stream.object_type = c_obj_type;
 		break;
 	default:
-		return HPI_ERROR_INVALID_STREAM;
+		return HPI_ERROR_INVALID_OBJ;
 	}
 
 	if (adapter != hm.adapter_index)
@@ -1441,15 +1191,16 @@ u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 *poutstream_map, u32 *pinstream_map)
+u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map,
+	u32 *pinstream_map)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_HOSTBUFFER_FREE);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 
 	if (poutstream_map)
@@ -1460,21 +1211,20 @@ u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream)
+u16 hpi_instream_group_reset(u32 h_instream)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		HPI_ISTREAM_GROUP_RESET);
-	u32TOINDEXES(h_instream, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_instream, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_mixer)
+u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
@@ -1492,25 +1242,29 @@ u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
 	return hr.error;
 }
 
-u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer)
+u16 hpi_mixer_close(u32 h_mixer)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE);
-	u32TOINDEX(h_mixer, &hm.adapter_index);
+	if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL))
+		return HPI_ERROR_INVALID_HANDLE;
+
 	hpi_send_recv(&hm, &hr);
 	return hr.error;
 }
 
-u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
-	u16 src_node_type, u16 src_node_type_index, u16 dst_node_type,
-	u16 dst_node_type_index, u16 control_type, u32 *ph_control)
+u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type,
+	u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index,
+	u16 control_type, u32 *ph_control)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER,
 		HPI_MIXER_GET_CONTROL);
-	u32TOINDEX(h_mixer, &hm.adapter_index);
+	if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.m.node_type1 = src_node_type;
 	hm.u.m.node_index1 = src_node_type_index;
 	hm.u.m.node_type2 = dst_node_type;
@@ -1528,16 +1282,16 @@ u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
 	return hr.error;
 }
 
-u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_mixer, u16 control_index, u16 *pw_src_node_type,
-	u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index,
-	u16 *pw_control_type, u32 *ph_control)
+u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index,
+	u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type,
+	u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER,
 		HPI_MIXER_GET_CONTROL_BY_INDEX);
-	u32TOINDEX(h_mixer, &hm.adapter_index);
+	if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.m.control_index = control_index;
 	hpi_send_recv(&hm, &hr);
 
@@ -1562,13 +1316,14 @@ u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
-	enum HPI_MIXER_STORE_COMMAND command, u16 index)
+u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command,
+	u16 index)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_STORE);
-	u32TOINDEX(h_mixer, &hm.adapter_index);
+	if (hpi_handle_indexes(h_mixer, &hm.adapter_index, NULL))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.mx.store.command = command;
 	hm.u.mx.store.index = index;
 	hpi_send_recv(&hm, &hr);
@@ -1576,16 +1331,16 @@ u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
 }
 
 static
-u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_control, const u16 attrib, const u32 param1,
-	const u32 param2)
+u16 hpi_control_param_set(const u32 h_control, const u16 attrib,
+	const u32 param1, const u32 param2)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = attrib;
 	hm.u.c.param1 = param1;
 	hm.u.c.param2 = param2;
@@ -1601,7 +1356,8 @@ static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = attrib;
 	hm.u.c.an_log_value[0] = sv0;
 	hm.u.c.an_log_value[1] = sv1;
@@ -1610,16 +1366,16 @@ static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0,
 }
 
 static
-u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_control, const u16 attrib, u32 param1, u32 param2,
-	u32 *pparam1, u32 *pparam2)
+u16 hpi_control_param_get(const u32 h_control, const u16 attrib, u32 param1,
+	u32 param2, u32 *pparam1, u32 *pparam2)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = attrib;
 	hm.u.c.param1 = param1;
 	hm.u.c.param2 = param2;
@@ -1632,19 +1388,20 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-#define hpi_control_param1_get(s, h, a, p1) \
-		hpi_control_param_get(s, h, a, 0, 0, p1, NULL)
-#define hpi_control_param2_get(s, h, a, p1, p2) \
-		hpi_control_param_get(s, h, a, 0, 0, p1, p2)
+#define hpi_control_param1_get(h, a, p1) \
+		hpi_control_param_get(h, a, 0, 0, p1, NULL)
+#define hpi_control_param2_get(h, a, p1, p2) \
+		hpi_control_param_get(h, a, 0, 0, p1, p2)
 
-static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attrib, short *sv0, short *sv1)
+static u16 hpi_control_log_get2(u32 h_control, u16 attrib, short *sv0,
+	short *sv1)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = attrib;
 
 	hpi_send_recv(&hm, &hr);
@@ -1655,8 +1412,7 @@ static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys,
 }
 
 static
-u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_control, const u16 attrib, const u32 index,
+u16 hpi_control_query(const u32 h_control, const u16 attrib, const u32 index,
 	const u32 param, u32 *psetting)
 {
 	struct hpi_message hm;
@@ -1664,7 +1420,8 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_INFO);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.c.attribute = attrib;
 	hm.u.c.param1 = index;
@@ -1682,7 +1439,7 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
 	unsigned int sub_string_index = 0, j = 0;
 	char c = 0;
 	unsigned int n = 0;
-	u16 hE = 0;
+	u16 err = 0;
 
 	if ((string_length < 1) || (string_length > 256))
 		return HPI_ERROR_INVALID_CONTROL_VALUE;
@@ -1693,7 +1450,9 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
 
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 			HPI_CONTROL_GET_STATE);
-		u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+		if (hpi_handle_indexes(h_control, &hm.adapter_index,
+				&hm.obj_index))
+			return HPI_ERROR_INVALID_HANDLE;
 		hm.u.c.attribute = attribute;
 		hm.u.c.param1 = sub_string_index;
 		hm.u.c.param2 = 0;
@@ -1705,7 +1464,7 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
 			return HPI_ERROR_INVALID_CONTROL_VALUE;
 
 		if (hr.error) {
-			hE = hr.error;
+			err = hr.error;
 			break;
 		}
 		for (j = 0; j < 8; j++) {
@@ -1714,7 +1473,7 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
 			n++;
 			if (n >= string_length) {
 				psz_string[string_length - 1] = 0;
-				hE = HPI_ERROR_INVALID_CONTROL_VALUE;
+				err = HPI_ERROR_INVALID_CONTROL_VALUE;
 				break;
 			}
 			if (c == 0)
@@ -1730,57 +1489,52 @@ static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
 		if (c == 0)
 			break;
 	}
-	return hE;
+	return err;
 }
 
-u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_aes_rx, const u32 index, u16 *pw_format)
+u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index,
+	u16 *pw_format)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_aes_rx, HPI_AESEBURX_FORMAT,
-		index, 0, &qr);
+	err = hpi_control_query(h_aes_rx, HPI_AESEBURX_FORMAT, index, 0, &qr);
 	*pw_format = (u16)qr;
 	return err;
 }
 
-u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 format)
+u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 format)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_AESEBURX_FORMAT, format, 0);
+	return hpi_control_param_set(h_control, HPI_AESEBURX_FORMAT, format,
+		0);
 }
 
-u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_format)
+u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_format)
 {
 	u16 err;
 	u32 param;
 
-	err = hpi_control_param1_get(ph_subsys, h_control,
-		HPI_AESEBURX_FORMAT, &param);
+	err = hpi_control_param1_get(h_control, HPI_AESEBURX_FORMAT, &param);
 	if (!err && pw_format)
 		*pw_format = (u16)param;
 
 	return err;
 }
 
-u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate)
+u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_AESEBURX_SAMPLERATE, psample_rate);
+	return hpi_control_param1_get(h_control, HPI_AESEBURX_SAMPLERATE,
+		psample_rate);
 }
 
-u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *pw_data)
+u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_AESEBURX_USERDATA;
 	hm.u.c.param1 = index;
 
@@ -1791,14 +1545,15 @@ u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 *pw_data)
+u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index,
+	u16 *pw_data)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_AESEBURX_CHANNELSTATUS;
 	hm.u.c.param1 = index;
 
@@ -1809,101 +1564,93 @@ u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys
 	return hr.error;
 }
 
-u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_error_data)
+u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data)
 {
 	u32 error_data = 0;
-	u16 error = 0;
+	u16 err = 0;
 
-	error = hpi_control_param1_get(ph_subsys, h_control,
-		HPI_AESEBURX_ERRORSTATUS, &error_data);
+	err = hpi_control_param1_get(h_control, HPI_AESEBURX_ERRORSTATUS,
+		&error_data);
 	if (pw_error_data)
 		*pw_error_data = (u16)error_data;
-	return error;
+	return err;
 }
 
-u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u32 sample_rate)
+u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_AESEBUTX_SAMPLERATE, sample_rate, 0);
+	return hpi_control_param_set(h_control, HPI_AESEBUTX_SAMPLERATE,
+		sample_rate, 0);
 }
 
-u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 data)
+u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_AESEBUTX_USERDATA, index, data);
+	return hpi_control_param_set(h_control, HPI_AESEBUTX_USERDATA, index,
+		data);
 }
 
-u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 data)
+u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index,
+	u16 data)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_AESEBUTX_CHANNELSTATUS, index, data);
+	return hpi_control_param_set(h_control, HPI_AESEBUTX_CHANNELSTATUS,
+		index, data);
 }
 
-u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 *pw_data)
+u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index,
+	u16 *pw_data)
 {
 	return HPI_ERROR_INVALID_OPERATION;
 }
 
-u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_aes_tx, const u32 index, u16 *pw_format)
+u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index,
+	u16 *pw_format)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_aes_tx, HPI_AESEBUTX_FORMAT,
-		index, 0, &qr);
+	err = hpi_control_query(h_aes_tx, HPI_AESEBUTX_FORMAT, index, 0, &qr);
 	*pw_format = (u16)qr;
 	return err;
 }
 
-u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 output_format)
+u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_AESEBUTX_FORMAT, output_format, 0);
+	return hpi_control_param_set(h_control, HPI_AESEBUTX_FORMAT,
+		output_format, 0);
 }
 
-u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_output_format)
+u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format)
 {
 	u16 err;
 	u32 param;
 
-	err = hpi_control_param1_get(ph_subsys, h_control,
-		HPI_AESEBUTX_FORMAT, &param);
+	err = hpi_control_param1_get(h_control, HPI_AESEBUTX_FORMAT, &param);
 	if (!err && pw_output_format)
 		*pw_output_format = (u16)param;
 
 	return err;
 }
 
-u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 edge_type)
+u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_BITSTREAM_CLOCK_EDGE, edge_type, 0);
+	return hpi_control_param_set(h_control, HPI_BITSTREAM_CLOCK_EDGE,
+		edge_type, 0);
 }
 
-u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 polarity)
+u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_BITSTREAM_DATA_POLARITY, polarity, 0);
+	return hpi_control_param_set(h_control, HPI_BITSTREAM_DATA_POLARITY,
+		polarity, 0);
 }
 
-u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity)
+u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity,
+	u16 *pw_data_activity)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_BITSTREAM_ACTIVITY;
 	hpi_send_recv(&hm, &hr);
 	if (pw_clk_activity)
@@ -1913,45 +1660,43 @@ u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_mode, const u32 index, u16 *pw_mode)
+u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index,
+	u16 *pw_mode)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_mode, HPI_CHANNEL_MODE_MODE,
-		index, 0, &qr);
+	err = hpi_control_query(h_mode, HPI_CHANNEL_MODE_MODE, index, 0, &qr);
 	*pw_mode = (u16)qr;
 	return err;
 }
 
-u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 mode)
+u16 hpi_channel_mode_set(u32 h_control, u16 mode)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_CHANNEL_MODE_MODE, mode, 0);
+	return hpi_control_param_set(h_control, HPI_CHANNEL_MODE_MODE, mode,
+		0);
 }
 
-u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *mode)
+u16 hpi_channel_mode_get(u32 h_control, u16 *mode)
 {
 	u32 mode32 = 0;
-	u16 error = hpi_control_param1_get(ph_subsys, h_control,
+	u16 err = hpi_control_param1_get(h_control,
 		HPI_CHANNEL_MODE_MODE, &mode32);
 	if (mode)
 		*mode = (u16)mode32;
-	return error;
+	return err;
 }
 
-u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 hmi_address, u32 byte_count, u8 *pb_data)
+u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count,
+	u8 *pb_data)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.cx.u.cobranet_data.byte_count = byte_count;
 	hm.u.cx.u.cobranet_data.hmi_address = hmi_address;
@@ -1969,15 +1714,16 @@ u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data)
+u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count,
+	u32 *pbyte_count, u8 *pb_data)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.cx.u.cobranet_data.byte_count = max_byte_count;
 	hm.u.cx.u.cobranet_data.hmi_address = hmi_address;
@@ -2008,16 +1754,16 @@ u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pstatus, u32 *preadable_size,
-	u32 *pwriteable_size)
+u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus,
+	u32 *preadable_size, u32 *pwriteable_size)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.cx.attribute = HPI_COBRANET_GET_STATUS;
 
@@ -2035,177 +1781,176 @@ u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pi_paddress)
+u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address)
 {
 	u32 byte_count;
 	u32 iP;
-	u16 error;
+	u16 err;
 
-	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
+	err = hpi_cobranet_hmi_read(h_control,
 		HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count,
 		(u8 *)&iP);
 
-	*pi_paddress =
+	*pdw_ip_address =
 		((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP &
 			0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8);
 
-	if (error)
-		*pi_paddress = 0;
+	if (err)
+		*pdw_ip_address = 0;
 
-	return error;
+	return err;
 
 }
 
-u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 i_paddress)
+u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address)
 {
 	u32 iP;
-	u16 error;
+	u16 err;
 
-	iP = ((i_paddress & 0xff000000) >> 8) | ((i_paddress & 0x00ff0000) <<
-		8) | ((i_paddress & 0x0000ff00) >> 8) | ((i_paddress &
-			0x000000ff) << 8);
+	iP = ((dw_ip_address & 0xff000000) >> 8) | ((dw_ip_address &
+			0x00ff0000) << 8) | ((dw_ip_address & 0x0000ff00) >>
+		8) | ((dw_ip_address & 0x000000ff) << 8);
 
-	error = hpi_cobranet_hmi_write(ph_subsys, h_control,
+	err = hpi_cobranet_hmi_write(h_control,
 		HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, (u8 *)&iP);
 
-	return error;
+	return err;
 
 }
 
-u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pi_paddress)
+u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address)
 {
 	u32 byte_count;
 	u32 iP;
-	u16 error;
-	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
+	u16 err;
+	err = hpi_cobranet_hmi_read(h_control,
 		HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, &byte_count,
 		(u8 *)&iP);
 
-	*pi_paddress =
+	*pdw_ip_address =
 		((iP & 0xff000000) >> 8) | ((iP & 0x00ff0000) << 8) | ((iP &
 			0x0000ff00) >> 8) | ((iP & 0x000000ff) << 8);
 
-	if (error)
-		*pi_paddress = 0;
+	if (err)
+		*pdw_ip_address = 0;
 
-	return error;
+	return err;
 
 }
 
-u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 i_paddress)
+u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address)
 {
 	u32 iP;
-	u16 error;
+	u16 err;
 
-	iP = ((i_paddress & 0xff000000) >> 8) | ((i_paddress & 0x00ff0000) <<
-		8) | ((i_paddress & 0x0000ff00) >> 8) | ((i_paddress &
-			0x000000ff) << 8);
+	iP = ((dw_ip_address & 0xff000000) >> 8) | ((dw_ip_address &
+			0x00ff0000) << 8) | ((dw_ip_address & 0x0000ff00) >>
+		8) | ((dw_ip_address & 0x000000ff) << 8);
 
-	error = hpi_cobranet_hmi_write(ph_subsys, h_control,
+	err = hpi_cobranet_hmi_write(h_control,
 		HPI_COBRANET_HMI_cobra_ip_mon_staticIP, 4, (u8 *)&iP);
 
-	return error;
+	return err;
 
 }
 
-u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs)
+u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs,
+	u32 *p_mac_lsbs)
 {
 	u32 byte_count;
-	u16 error;
-	u32 mAC;
+	u16 err;
+	u32 mac;
 
-	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
+	err = hpi_cobranet_hmi_read(h_control,
 		HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count,
-		(u8 *)&mAC);
-	*pmAC_MS_bs =
-		((mAC & 0xff000000) >> 8) | ((mAC & 0x00ff0000) << 8) | ((mAC
-			& 0x0000ff00) >> 8) | ((mAC & 0x000000ff) << 8);
-	error += hpi_cobranet_hmi_read(ph_subsys, h_control,
-		HPI_COBRANET_HMI_cobra_if_phy_address + 1, 4, &byte_count,
-		(u8 *)&mAC);
-	*pmAC_LS_bs =
-		((mAC & 0xff000000) >> 8) | ((mAC & 0x00ff0000) << 8) | ((mAC
-			& 0x0000ff00) >> 8) | ((mAC & 0x000000ff) << 8);
-
-	if (error) {
-		*pmAC_MS_bs = 0;
-		*pmAC_LS_bs = 0;
+		(u8 *)&mac);
+
+	if (!err) {
+		*p_mac_msbs =
+			((mac & 0xff000000) >> 8) | ((mac & 0x00ff0000) << 8)
+			| ((mac & 0x0000ff00) >> 8) | ((mac & 0x000000ff) <<
+			8);
+
+		err = hpi_cobranet_hmi_read(h_control,
+			HPI_COBRANET_HMI_cobra_if_phy_address + 1, 4,
+			&byte_count, (u8 *)&mac);
 	}
 
-	return error;
+	if (!err) {
+		*p_mac_lsbs =
+			((mac & 0xff000000) >> 8) | ((mac & 0x00ff0000) << 8)
+			| ((mac & 0x0000ff00) >> 8) | ((mac & 0x000000ff) <<
+			8);
+	} else {
+		*p_mac_msbs = 0;
+		*p_mac_lsbs = 0;
+	}
+
+	return err;
 }
 
-u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 enable)
+u16 hpi_compander_set_enable(u32 h_control, u32 enable)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
-		enable, 0);
+	return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable,
+		0);
 }
 
-u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *enable)
+u16 hpi_compander_get_enable(u32 h_control, u32 *enable)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_GENERIC_ENABLE, enable);
+	return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable);
 }
 
-u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short makeup_gain0_01dB)
+u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB)
 {
 	return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN,
 		makeup_gain0_01dB, 0);
 }
 
-u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short *makeup_gain0_01dB)
+u16 hpi_compander_get_makeup_gain(u32 h_control, short *makeup_gain0_01dB)
 {
-	return hpi_control_log_get2(ph_subsys, h_control,
-		HPI_COMPANDER_MAKEUPGAIN, makeup_gain0_01dB, NULL);
+	return hpi_control_log_get2(h_control, HPI_COMPANDER_MAKEUPGAIN,
+		makeup_gain0_01dB, NULL);
 }
 
-u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, unsigned int index, u32 attack)
+u16 hpi_compander_set_attack_time_constant(u32 h_control, unsigned int index,
+	u32 attack)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_COMPANDER_ATTACK, attack, index);
+	return hpi_control_param_set(h_control, HPI_COMPANDER_ATTACK, attack,
+		index);
 }
 
-u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, unsigned int index, u32 *attack)
+u16 hpi_compander_get_attack_time_constant(u32 h_control, unsigned int index,
+	u32 *attack)
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_COMPANDER_ATTACK, 0, index, attack, NULL);
+	return hpi_control_param_get(h_control, HPI_COMPANDER_ATTACK, 0,
+		index, attack, NULL);
 }
 
-u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, unsigned int index, u32 decay)
+u16 hpi_compander_set_decay_time_constant(u32 h_control, unsigned int index,
+	u32 decay)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_COMPANDER_DECAY, decay, index);
+	return hpi_control_param_set(h_control, HPI_COMPANDER_DECAY, decay,
+		index);
 }
 
-u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, unsigned int index, u32 *decay)
+u16 hpi_compander_get_decay_time_constant(u32 h_control, unsigned int index,
+	u32 *decay)
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_COMPANDER_DECAY, 0, index, decay, NULL);
+	return hpi_control_param_get(h_control, HPI_COMPANDER_DECAY, 0, index,
+		decay, NULL);
 
 }
 
-u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, unsigned int index, short threshold0_01dB)
+u16 hpi_compander_set_threshold(u32 h_control, unsigned int index,
+	short threshold0_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
 	hm.u.c.param2 = index;
 	hm.u.c.an_log_value[0] = threshold0_01dB;
@@ -2215,15 +1960,16 @@ u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, unsigned int index, short *threshold0_01dB)
+u16 hpi_compander_get_threshold(u32 h_control, unsigned int index,
+	short *threshold0_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
 	hm.u.c.param2 = index;
 
@@ -2233,29 +1979,28 @@ u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 ratio100)
+u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_COMPANDER_RATIO, ratio100, index);
+	return hpi_control_param_set(h_control, HPI_COMPANDER_RATIO, ratio100,
+		index);
 }
 
-u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 *ratio100)
+u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *ratio100)
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_COMPANDER_RATIO, 0, index, ratio100, NULL);
+	return hpi_control_param_get(h_control, HPI_COMPANDER_RATIO, 0, index,
+		ratio100, NULL);
 }
 
-u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB)
+u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB,
+	short *max_gain_01dB, short *step_gain_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_LEVEL_RANGE;
 
 	hpi_send_recv(&hm, &hr);
@@ -2273,31 +2018,27 @@ u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB[HPI_MAX_CHANNELS]
+u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS]
 	)
 {
 	return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN,
 		an_gain0_01dB[0], an_gain0_01dB[1]);
 }
 
-u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB[HPI_MAX_CHANNELS]
+u16 hpi_level_get_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS]
 	)
 {
-	return hpi_control_log_get2(ph_subsys, h_control, HPI_LEVEL_GAIN,
+	return hpi_control_log_get2(h_control, HPI_LEVEL_GAIN,
 		&an_gain0_01dB[0], &an_gain0_01dB[1]);
 }
 
-u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_meter, u32 *p_channels)
+u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels)
 {
-	return hpi_control_query(ph_subsys, h_meter, HPI_METER_NUM_CHANNELS,
-		0, 0, p_channels);
+	return hpi_control_query(h_meter, HPI_METER_NUM_CHANNELS, 0, 0,
+		p_channels);
 }
 
-u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_peakdB[HPI_MAX_CHANNELS]
+u16 hpi_meter_get_peak(u32 h_control, short an_peakdB[HPI_MAX_CHANNELS]
 	)
 {
 	short i = 0;
@@ -2307,7 +2048,8 @@ u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.obj_index = hm.obj_index;
 	hm.u.c.attribute = HPI_METER_PEAK;
 
@@ -2322,8 +2064,7 @@ u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_rmsdB[HPI_MAX_CHANNELS]
+u16 hpi_meter_get_rms(u32 h_control, short an_rmsdB[HPI_MAX_CHANNELS]
 	)
 {
 	short i = 0;
@@ -2333,7 +2074,8 @@ u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_METER_RMS;
 
 	hpi_send_recv(&hm, &hr);
@@ -2348,22 +2090,20 @@ u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attack, u16 decay)
+u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_METER_RMS_BALLISTICS, attack, decay);
+	return hpi_control_param_set(h_control, HPI_METER_RMS_BALLISTICS,
+		attack, decay);
 }
 
-u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pn_attack, u16 *pn_decay)
+u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *pn_attack, u16 *pn_decay)
 {
 	u32 attack;
 	u32 decay;
 	u16 error;
 
-	error = hpi_control_param2_get(ph_subsys, h_control,
-		HPI_METER_RMS_BALLISTICS, &attack, &decay);
+	error = hpi_control_param2_get(h_control, HPI_METER_RMS_BALLISTICS,
+		&attack, &decay);
 
 	if (pn_attack)
 		*pn_attack = (unsigned short)attack;
@@ -2373,22 +2113,21 @@ u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
 	return error;
 }
 
-u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attack, u16 decay)
+u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_METER_PEAK_BALLISTICS, attack, decay);
+	return hpi_control_param_set(h_control, HPI_METER_PEAK_BALLISTICS,
+		attack, decay);
 }
 
-u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pn_attack, u16 *pn_decay)
+u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *pn_attack,
+	u16 *pn_decay)
 {
 	u32 attack;
 	u32 decay;
 	u16 error;
 
-	error = hpi_control_param2_get(ph_subsys, h_control,
-		HPI_METER_PEAK_BALLISTICS, &attack, &decay);
+	error = hpi_control_param2_get(h_control, HPI_METER_PEAK_BALLISTICS,
+		&attack, &decay);
 
 	if (pn_attack)
 		*pn_attack = (short)attack;
@@ -2398,55 +2137,53 @@ u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
 	return error;
 }
 
-u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 on_off)
+u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_MICROPHONE_PHANTOM_POWER, (u32)on_off, 0);
+	return hpi_control_param_set(h_control, HPI_MICROPHONE_PHANTOM_POWER,
+		(u32)on_off, 0);
 }
 
-u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_on_off)
+u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off)
 {
 	u16 error = 0;
 	u32 on_off = 0;
-	error = hpi_control_param1_get(ph_subsys, h_control,
+	error = hpi_control_param1_get(h_control,
 		HPI_MICROPHONE_PHANTOM_POWER, &on_off);
 	if (pw_on_off)
 		*pw_on_off = (u16)on_off;
 	return error;
 }
 
-u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source_node_type, u16 source_node_index)
+u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type,
+	u16 source_node_index)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_MULTIPLEXER_SOURCE, source_node_type, source_node_index);
+	return hpi_control_param_set(h_control, HPI_MULTIPLEXER_SOURCE,
+		source_node_type, source_node_index);
 }
 
-u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *source_node_type, u16 *source_node_index)
+u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type,
+	u16 *source_node_index)
 {
 	u32 node, index;
-	u16 error = hpi_control_param2_get(ph_subsys, h_control,
+	u16 err = hpi_control_param2_get(h_control,
 		HPI_MULTIPLEXER_SOURCE, &node,
 		&index);
 	if (source_node_type)
 		*source_node_type = (u16)node;
 	if (source_node_index)
 		*source_node_index = (u16)index;
-	return error;
+	return err;
 }
 
-u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *source_node_type,
-	u16 *source_node_index)
+u16 hpi_multiplexer_query_source(u32 h_control, u16 index,
+	u16 *source_node_type, u16 *source_node_index)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_MULTIPLEXER_QUERYSOURCE;
 	hm.u.c.param1 = index;
 
@@ -2459,15 +2196,15 @@ u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_number_of_bands, u16 *pw_on_off)
+u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands,
+	u16 *pw_on_off)
 {
 	u32 oB = 0;
 	u32 oO = 0;
 	u16 error = 0;
 
-	error = hpi_control_param2_get(ph_subsys, h_control,
-		HPI_EQUALIZER_NUM_FILTERS, &oO, &oB);
+	error = hpi_control_param2_get(h_control, HPI_EQUALIZER_NUM_FILTERS,
+		&oO, &oB);
 	if (pw_number_of_bands)
 		*pw_number_of_bands = (u16)oB;
 	if (pw_on_off)
@@ -2475,23 +2212,22 @@ u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys,
 	return error;
 }
 
-u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 on_off)
+u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_EQUALIZER_NUM_FILTERS, on_off, 0);
+	return hpi_control_param_set(h_control, HPI_EQUALIZER_NUM_FILTERS,
+		on_off, 0);
 }
 
-u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz,
-	short *pnQ100, short *pn_gain0_01dB)
+u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type,
+	u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_EQUALIZER_FILTER;
 	hm.u.c.param2 = index;
 
@@ -2509,16 +2245,16 @@ u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100,
-	short gain0_01dB)
+u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type,
+	u32 frequency_hz, short q100, short gain0_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	hm.u.c.param1 = frequency_hz;
 	hm.u.c.param2 = (index & 0xFFFFL) + ((u32)type << 16);
@@ -2531,8 +2267,7 @@ u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, short coeffs[5]
+u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5]
 	)
 {
 	struct hpi_message hm;
@@ -2540,7 +2275,8 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_EQUALIZER_COEFFICIENTS;
 	hm.u.c.param2 = index;
 
@@ -2555,444 +2291,388 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, u16 *pw_source)
+u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index,
+	u16 *pw_source)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_clock, HPI_SAMPLECLOCK_SOURCE,
-		index, 0, &qr);
+	err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_SOURCE, index, 0,
+		&qr);
 	*pw_source = (u16)qr;
 	return err;
 }
 
-u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source)
+u16 hpi_sample_clock_set_source(u32 h_control, u16 source)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_SOURCE, source, 0);
+	return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_SOURCE,
+		source, 0);
 }
 
-u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source)
+u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source)
 {
-	u16 error = 0;
+	u16 err = 0;
 	u32 source = 0;
-	error = hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_SOURCE, &source);
-	if (!error)
+	err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SOURCE,
+		&source);
+	if (!err)
 		if (pw_source)
 			*pw_source = (u16)source;
-	return error;
+	return err;
 }
 
-u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, const u32 source,
-	u16 *pw_source_index)
+u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index,
+	const u32 source, u16 *pw_source_index)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_clock,
-		HPI_SAMPLECLOCK_SOURCE_INDEX, index, source, &qr);
+	err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_SOURCE_INDEX, index,
+		source, &qr);
 	*pw_source_index = (u16)qr;
 	return err;
 }
 
-u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source_index)
+u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_SOURCE_INDEX, source_index, 0);
+	return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_SOURCE_INDEX,
+		source_index, 0);
 }
 
-u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source_index)
+u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index)
 {
-	u16 error = 0;
+	u16 err = 0;
 	u32 source_index = 0;
-	error = hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_SOURCE_INDEX, &source_index);
-	if (!error)
+	err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SOURCE_INDEX,
+		&source_index);
+	if (!err)
 		if (pw_source_index)
 			*pw_source_index = (u16)source_index;
-	return error;
+	return err;
 }
 
-u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, u32 *prate)
+u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index,
+	u32 *prate)
 {
 	u16 err;
-	err = hpi_control_query(ph_subsys, h_clock,
-		HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, index, 0, prate);
+	err = hpi_control_query(h_clock, HPI_SAMPLECLOCK_LOCAL_SAMPLERATE,
+		index, 0, prate);
 
 	return err;
 }
 
-u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 sample_rate)
+u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
+	return hpi_control_param_set(h_control,
 		HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, sample_rate, 0);
 }
 
-u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate)
+u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate)
 {
-	u16 error = 0;
+	u16 err = 0;
 	u32 sample_rate = 0;
-	error = hpi_control_param1_get(ph_subsys, h_control,
+	err = hpi_control_param1_get(h_control,
 		HPI_SAMPLECLOCK_LOCAL_SAMPLERATE, &sample_rate);
-	if (!error)
+	if (!err)
 		if (psample_rate)
 			*psample_rate = sample_rate;
-	return error;
+	return err;
 }
 
-u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate)
+u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate)
 {
-	u16 error = 0;
+	u16 err = 0;
 	u32 sample_rate = 0;
-	error = hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_SAMPLERATE, &sample_rate);
-	if (!error)
+	err = hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_SAMPLERATE,
+		&sample_rate);
+	if (!err)
 		if (psample_rate)
 			*psample_rate = sample_rate;
-	return error;
+	return err;
 }
 
-u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 enable)
+u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_AUTO, enable, 0);
+	return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_AUTO, enable,
+		0);
 }
 
-u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *penable)
+u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_AUTO, penable);
+	return hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_AUTO,
+		penable);
 }
 
-u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 lock)
+u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_LOCAL_LOCK, lock, 0);
+	return hpi_control_param_set(h_control, HPI_SAMPLECLOCK_LOCAL_LOCK,
+		lock, 0);
 }
 
-u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *plock)
+u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SAMPLECLOCK_LOCAL_LOCK, plock);
+	return hpi_control_param1_get(h_control, HPI_SAMPLECLOCK_LOCAL_LOCK,
+		plock);
 }
 
-u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 *frequency)
+u16 hpi_tone_detector_get_frequency(u32 h_control, u32 index, u32 *frequency)
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_TONEDETECTOR_FREQUENCY, index, 0, frequency, NULL);
+	return hpi_control_param_get(h_control, HPI_TONEDETECTOR_FREQUENCY,
+		index, 0, frequency, NULL);
 }
 
-u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *state)
+u16 hpi_tone_detector_get_state(u32 h_control, u32 *state)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_TONEDETECTOR_STATE, state);
+	return hpi_control_param1_get(h_control, HPI_TONEDETECTOR_STATE,
+		state);
 }
 
-u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 enable)
+u16 hpi_tone_detector_set_enable(u32 h_control, u32 enable)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
-		(u32)enable, 0);
+	return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable,
+		0);
 }
 
-u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *enable)
+u16 hpi_tone_detector_get_enable(u32 h_control, u32 *enable)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_GENERIC_ENABLE, enable);
+	return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable);
 }
 
-u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 event_enable)
+u16 hpi_tone_detector_set_event_enable(u32 h_control, u32 event_enable)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0);
+	return hpi_control_param_set(h_control, HPI_GENERIC_EVENT_ENABLE,
+		(u32)event_enable, 0);
 }
 
-u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *event_enable)
+u16 hpi_tone_detector_get_event_enable(u32 h_control, u32 *event_enable)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, event_enable);
+	return hpi_control_param1_get(h_control, HPI_GENERIC_EVENT_ENABLE,
+		event_enable);
 }
 
-u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, int threshold)
+u16 hpi_tone_detector_set_threshold(u32 h_control, int threshold)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_TONEDETECTOR_THRESHOLD, (u32)threshold, 0);
+	return hpi_control_param_set(h_control, HPI_TONEDETECTOR_THRESHOLD,
+		(u32)threshold, 0);
 }
 
-u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, int *threshold)
+u16 hpi_tone_detector_get_threshold(u32 h_control, int *threshold)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_TONEDETECTOR_THRESHOLD, (u32 *)threshold);
+	return hpi_control_param1_get(h_control, HPI_TONEDETECTOR_THRESHOLD,
+		(u32 *)threshold);
 }
 
-u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *state)
+u16 hpi_silence_detector_get_state(u32 h_control, u32 *state)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_STATE, state);
+	return hpi_control_param1_get(h_control, HPI_SILENCEDETECTOR_STATE,
+		state);
 }
 
-u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 enable)
+u16 hpi_silence_detector_set_enable(u32 h_control, u32 enable)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
-		(u32)enable, 0);
+	return hpi_control_param_set(h_control, HPI_GENERIC_ENABLE, enable,
+		0);
 }
 
-u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *enable)
+u16 hpi_silence_detector_get_enable(u32 h_control, u32 *enable)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_GENERIC_ENABLE, enable);
+	return hpi_control_param1_get(h_control, HPI_GENERIC_ENABLE, enable);
 }
 
-u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 event_enable)
+u16 hpi_silence_detector_set_event_enable(u32 h_control, u32 event_enable)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, event_enable, 0);
+	return hpi_control_param_set(h_control, HPI_GENERIC_EVENT_ENABLE,
+		event_enable, 0);
 }
 
-u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *event_enable)
+u16 hpi_silence_detector_get_event_enable(u32 h_control, u32 *event_enable)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, event_enable);
+	return hpi_control_param1_get(h_control, HPI_GENERIC_EVENT_ENABLE,
+		event_enable);
 }
 
-u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 delay)
+u16 hpi_silence_detector_set_delay(u32 h_control, u32 delay)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_DELAY, delay, 0);
+	return hpi_control_param_set(h_control, HPI_SILENCEDETECTOR_DELAY,
+		delay, 0);
 }
 
-u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *delay)
+u16 hpi_silence_detector_get_delay(u32 h_control, u32 *delay)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_DELAY, delay);
+	return hpi_control_param1_get(h_control, HPI_SILENCEDETECTOR_DELAY,
+		delay);
 }
 
-u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, int threshold)
+u16 hpi_silence_detector_set_threshold(u32 h_control, int threshold)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_THRESHOLD, threshold, 0);
+	return hpi_control_param_set(h_control, HPI_SILENCEDETECTOR_THRESHOLD,
+		threshold, 0);
 }
 
-u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, int *threshold)
+u16 hpi_silence_detector_get_threshold(u32 h_control, int *threshold)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
+	return hpi_control_param1_get(h_control,
 		HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold);
 }
 
-u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, u16 *pw_band)
+u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_BAND, index, 0,
-		&qr);
+	err = hpi_control_query(h_tuner, HPI_TUNER_BAND, index, 0, &qr);
 	*pw_band = (u16)qr;
 	return err;
 }
 
-u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 band)
+u16 hpi_tuner_set_band(u32 h_control, u16 band)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_BAND,
-		band, 0);
+	return hpi_control_param_set(h_control, HPI_TUNER_BAND, band, 0);
 }
 
-u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_band)
+u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band)
 {
 	u32 band = 0;
 	u16 error = 0;
 
-	error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_BAND,
-		&band);
+	error = hpi_control_param1_get(h_control, HPI_TUNER_BAND, &band);
 	if (pw_band)
 		*pw_band = (u16)band;
 	return error;
 }
 
-u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq)
+u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index,
+	const u16 band, u32 *pfreq)
 {
-	return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_FREQ, index,
-		band, pfreq);
+	return hpi_control_query(h_tuner, HPI_TUNER_FREQ, index, band, pfreq);
 }
 
-u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 freq_ink_hz)
+u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_FREQ,
-		freq_ink_hz, 0);
+	return hpi_control_param_set(h_control, HPI_TUNER_FREQ, freq_ink_hz,
+		0);
 }
 
-u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pw_freq_ink_hz)
+u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz)
 {
-	return hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_FREQ,
+	return hpi_control_param1_get(h_control, HPI_TUNER_FREQ,
 		pw_freq_ink_hz);
 }
 
-u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, u16 *pw_gain)
+u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain)
 {
 	u32 qr;
 	u16 err;
 
-	err = hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_BAND, index, 0,
-		&qr);
+	err = hpi_control_query(h_tuner, HPI_TUNER_BAND, index, 0, &qr);
 	*pw_gain = (u16)qr;
 	return err;
 }
 
-u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short gain)
+u16 hpi_tuner_set_gain(u32 h_control, short gain)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_GAIN,
-		gain, 0);
+	return hpi_control_param_set(h_control, HPI_TUNER_GAIN, gain, 0);
 }
 
-u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *pn_gain)
+u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain)
 {
 	u32 gain = 0;
 	u16 error = 0;
 
-	error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_GAIN,
-		&gain);
+	error = hpi_control_param1_get(h_control, HPI_TUNER_GAIN, &gain);
 	if (pn_gain)
 		*pn_gain = (u16)gain;
 	return error;
 }
 
-u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *pw_level)
+u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	hm.u.c.attribute = HPI_TUNER_LEVEL;
-	hm.u.c.param1 = HPI_TUNER_LEVEL_AVERAGE;
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
+	hm.u.cu.attribute = HPI_TUNER_LEVEL_AVG;
 	hpi_send_recv(&hm, &hr);
 	if (pw_level)
-		*pw_level = (short)hr.u.c.param1;
+		*pw_level = hr.u.cu.tuner.s_level;
 	return hr.error;
 }
 
-u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short *pw_level)
+u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	hm.u.c.attribute = HPI_TUNER_LEVEL;
-	hm.u.c.param1 = HPI_TUNER_LEVEL_RAW;
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
+	hm.u.cu.attribute = HPI_TUNER_LEVEL_RAW;
 	hpi_send_recv(&hm, &hr);
 	if (pw_level)
-		*pw_level = (short)hr.u.c.param1;
+		*pw_level = hr.u.cu.tuner.s_level;
 	return hr.error;
 }
 
-u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis)
+u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index,
+	const u16 band, u32 *pdeemphasis)
 {
-	return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_DEEMPHASIS,
-		index, band, pdeemphasis);
+	return hpi_control_query(h_tuner, HPI_TUNER_DEEMPHASIS, index, band,
+		pdeemphasis);
 }
 
-u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 deemphasis)
+u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_TUNER_DEEMPHASIS, deemphasis, 0);
+	return hpi_control_param_set(h_control, HPI_TUNER_DEEMPHASIS,
+		deemphasis, 0);
 }
 
-u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pdeemphasis)
+u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_TUNER_DEEMPHASIS, pdeemphasis);
+	return hpi_control_param1_get(h_control, HPI_TUNER_DEEMPHASIS,
+		pdeemphasis);
 }
 
-u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, u32 *pbitmap_program)
+u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program)
 {
-	return hpi_control_query(ph_subsys, h_tuner, HPI_TUNER_PROGRAM, 0, 0,
+	return hpi_control_query(h_tuner, HPI_TUNER_PROGRAM, 0, 0,
 		pbitmap_program);
 }
 
-u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 program)
+u16 hpi_tuner_set_program(u32 h_control, u32 program)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_PROGRAM,
-		program, 0);
+	return hpi_control_param_set(h_control, HPI_TUNER_PROGRAM, program,
+		0);
 }
 
-u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 *pprogram)
+u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram)
 {
-	return hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_PROGRAM,
-		pprogram);
+	return hpi_control_param1_get(h_control, HPI_TUNER_PROGRAM, pprogram);
 }
 
-u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_dsp_version, const u32 string_size)
+u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version,
+	const u32 string_size)
 {
 	return hpi_control_get_string(h_control,
 		HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size);
 }
 
-u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_sdk_version, const u32 string_size)
+u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version,
+	const u32 string_size)
 {
 	return hpi_control_get_string(h_control,
 		HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size);
 }
 
-u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_status_mask, u16 *pw_status)
+u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status)
 {
 	u32 status = 0;
 	u16 error = 0;
 
-	error = hpi_control_param1_get(ph_subsys, h_control, HPI_TUNER_STATUS,
-		&status);
+	error = hpi_control_param1_get(h_control, HPI_TUNER_STATUS, &status);
 	if (pw_status) {
 		if (!error) {
 			*pw_status_mask = (u16)(status >> 16);
@@ -3005,50 +2685,44 @@ u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return error;
 }
 
-u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 mode, u32 value)
+u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value)
 {
-	return hpi_control_param_set(ph_subsys, h_control, HPI_TUNER_MODE,
-		mode, value);
+	return hpi_control_param_set(h_control, HPI_TUNER_MODE, mode, value);
 }
 
-u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 mode, u32 *pn_value)
+u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value)
 {
-	return hpi_control_param_get(ph_subsys, h_control, HPI_TUNER_MODE,
-		mode, 0, pn_value, NULL);
+	return hpi_control_param_get(h_control, HPI_TUNER_MODE, mode, 0,
+		pn_value, NULL);
 }
 
-u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pquality)
+u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
+	return hpi_control_param1_get(h_control,
 		HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality);
 }
 
-u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pblend)
+u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_TUNER_HDRADIO_BLEND, pblend);
+	return hpi_control_param1_get(h_control, HPI_TUNER_HDRADIO_BLEND,
+		pblend);
 }
 
-u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, const u32 blend)
+u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend)
 {
-	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_TUNER_HDRADIO_BLEND, blend, 0);
+	return hpi_control_param_set(h_control, HPI_TUNER_HDRADIO_BLEND,
+		blend, 0);
 }
 
-u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *p_data)
+u16 hpi_tuner_get_rds(u32 h_control, char *p_data)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_TUNER_RDS;
 	hpi_send_recv(&hm, &hr);
 	if (p_data) {
@@ -3059,80 +2733,82 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_string, const u32 data_length)
+u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string,
+	const u32 data_length)
 {
 	return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME,
 		psz_string, data_length);
 }
 
-u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 data_length)
+u16 hpi_pad_get_artist(u32 h_control, char *psz_string, const u32 data_length)
 {
 	return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string,
 		data_length);
 }
 
-u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 data_length)
+u16 hpi_pad_get_title(u32 h_control, char *psz_string, const u32 data_length)
 {
 	return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string,
 		data_length);
 }
 
-u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 data_length)
+u16 hpi_pad_get_comment(u32 h_control, char *psz_string,
+	const u32 data_length)
 {
 	return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string,
 		data_length);
 }
 
-u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *ppTY)
+u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_PAD_PROGRAM_TYPE, ppTY);
+	return hpi_control_param1_get(h_control, HPI_PAD_PROGRAM_TYPE, ppTY);
 }
 
-u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 *ppI)
+u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI)
 {
-	return hpi_control_param1_get(ph_subsys, h_control,
-		HPI_PAD_PROGRAM_ID, ppI);
+	return hpi_control_param1_get(h_control, HPI_PAD_PROGRAM_ID, ppI);
 }
 
-u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_volume, u32 *p_channels)
+u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels)
 {
-	return hpi_control_query(ph_subsys, h_volume, HPI_VOLUME_NUM_CHANNELS,
-		0, 0, p_channels);
+	return hpi_control_query(h_volume, HPI_VOLUME_NUM_CHANNELS, 0, 0,
+		p_channels);
 }
 
-u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_log_gain[HPI_MAX_CHANNELS]
+u16 hpi_volume_set_gain(u32 h_control, short an_log_gain[HPI_MAX_CHANNELS]
 	)
 {
 	return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN,
 		an_log_gain[0], an_log_gain[1]);
 }
 
-u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_log_gain[HPI_MAX_CHANNELS]
+u16 hpi_volume_get_gain(u32 h_control, short an_log_gain[HPI_MAX_CHANNELS]
 	)
 {
-	return hpi_control_log_get2(ph_subsys, h_control, HPI_VOLUME_GAIN,
+	return hpi_control_log_get2(h_control, HPI_VOLUME_GAIN,
 		&an_log_gain[0], &an_log_gain[1]);
 }
 
-u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB)
+u16 hpi_volume_set_mute(u32 h_control, u32 mute)
+{
+	return hpi_control_param_set(h_control, HPI_VOLUME_MUTE, mute, 0);
+}
+
+u16 hpi_volume_get_mute(u32 h_control, u32 *mute)
+{
+	return hpi_control_param1_get(h_control, HPI_VOLUME_MUTE, mute);
+}
+
+u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB,
+	short *max_gain_01dB, short *step_gain_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_VOLUME_RANGE;
 
 	hpi_send_recv(&hm, &hr);
@@ -3150,16 +2826,17 @@ u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS],
-	u32 duration_ms, u16 profile)
+u16 hpi_volume_auto_fade_profile(u32 h_control,
+	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms,
+	u16 profile)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 
 	memcpy(hm.u.c.an_log_value, an_stop_gain0_01dB,
 		sizeof(short) * HPI_MAX_CHANNELS);
@@ -3173,21 +2850,21 @@ u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 }
 
-u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_volume_auto_fade(u32 h_control,
 	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms)
 {
-	return hpi_volume_auto_fade_profile(ph_subsys, h_control,
-		an_stop_gain0_01dB, duration_ms, HPI_VOLUME_AUTOFADE_LOG);
+	return hpi_volume_auto_fade_profile(h_control, an_stop_gain0_01dB,
+		duration_ms, HPI_VOLUME_AUTOFADE_LOG);
 }
 
-u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB)
+u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_VOX_THRESHOLD;
 
 	hm.u.c.an_log_value[0] = an_gain0_01dB;
@@ -3197,14 +2874,14 @@ u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	return hr.error;
 }
 
-u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *an_gain0_01dB)
+u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB)
 {
 	struct hpi_message hm;
 	struct hpi_response hr;
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index))
+		return HPI_ERROR_INVALID_HANDLE;
 	hm.u.c.attribute = HPI_VOX_THRESHOLD;
 
 	hpi_send_recv(&hm, &hr);
@@ -3213,728 +2890,3 @@ u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 
 	return hr.error;
 }
-
-static size_t strv_packet_size = MIN_STRV_PACKET_SIZE;
-
-static size_t entity_type_to_size[LAST_ENTITY_TYPE] = {
-	0,
-	sizeof(struct hpi_entity),
-	sizeof(void *),
-
-	sizeof(int),
-	sizeof(float),
-	sizeof(double),
-
-	sizeof(char),
-	sizeof(char),
-
-	4 * sizeof(char),
-	16 * sizeof(char),
-	6 * sizeof(char),
-};
-
-static inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
-{
-	return entity_ptr->header.size;
-}
-
-static inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
-{
-	return sizeof(entity_ptr->header);
-}
-
-static inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
-{
-	return hpi_entity_size(entity_ptr) -
-		hpi_entity_header_size(entity_ptr);
-}
-
-static inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
-{
-	return hpi_entity_value_size(entity_ptr) /
-		entity_type_to_size[entity_ptr->header.type];
-}
-
-static inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
-	*entity_ptr)
-{
-	return (void *)(((u8 *)entity_ptr) + hpi_entity_size(entity_ptr));
-}
-
-static inline u16 hpi_entity_check_type(const enum e_entity_type t)
-{
-	if (t >= 0 && t < STR_TYPE_FIELD_MAX)
-		return 0;
-	return HPI_ERROR_ENTITY_TYPE_INVALID;
-}
-
-static inline u16 hpi_entity_check_role(const enum e_entity_role r)
-{
-	if (r >= 0 && r < STR_ROLE_FIELD_MAX)
-		return 0;
-	return HPI_ERROR_ENTITY_ROLE_INVALID;
-}
-
-static u16 hpi_entity_get_next(struct hpi_entity *entity, int recursive_flag,
-	void *guard_p, struct hpi_entity **next)
-{
-	HPI_DEBUG_ASSERT(entity != NULL);
-	HPI_DEBUG_ASSERT(next != NULL);
-	HPI_DEBUG_ASSERT(hpi_entity_size(entity) != 0);
-
-	if (guard_p <= (void *)entity) {
-		*next = NULL;
-		return 0;
-	}
-
-	if (recursive_flag && entity->header.type == entity_type_sequence)
-		*next = (struct hpi_entity *)entity->value;
-	else
-		*next = (struct hpi_entity *)hpi_entity_ptr_to_next(entity);
-
-	if (guard_p <= (void *)*next) {
-		*next = NULL;
-		return 0;
-	}
-
-	HPI_DEBUG_ASSERT(guard_p >= (void *)hpi_entity_ptr_to_next(*next));
-	return 0;
-}
-
-u16 hpi_entity_find_next(struct hpi_entity *container_entity,
-	enum e_entity_type type, enum e_entity_role role, int recursive_flag,
-	struct hpi_entity **current_match)
-{
-	struct hpi_entity *tmp = NULL;
-	void *guard_p = NULL;
-
-	HPI_DEBUG_ASSERT(container_entity != NULL);
-	guard_p = hpi_entity_ptr_to_next(container_entity);
-
-	if (*current_match != NULL)
-		hpi_entity_get_next(*current_match, recursive_flag, guard_p,
-			&tmp);
-	else
-		hpi_entity_get_next(container_entity, 1, guard_p, &tmp);
-
-	while (tmp) {
-		u16 err;
-
-		HPI_DEBUG_ASSERT((void *)tmp >= (void *)container_entity);
-
-		if ((!type || tmp->header.type == type) && (!role
-				|| tmp->header.role == role)) {
-			*current_match = tmp;
-			return 0;
-		}
-
-		err = hpi_entity_get_next(tmp, recursive_flag, guard_p,
-			current_match);
-		if (err)
-			return err;
-
-		tmp = *current_match;
-	}
-
-	*current_match = NULL;
-	return 0;
-}
-
-void hpi_entity_free(struct hpi_entity *entity)
-{
-	kfree(entity);
-}
-
-static u16 hpi_entity_alloc_and_copy(struct hpi_entity *src,
-	struct hpi_entity **dst)
-{
-	size_t buf_size;
-	HPI_DEBUG_ASSERT(dst != NULL);
-	HPI_DEBUG_ASSERT(src != NULL);
-
-	buf_size = hpi_entity_size(src);
-	*dst = kmalloc(buf_size, GFP_KERNEL);
-	if (*dst == NULL)
-		return HPI_ERROR_MEMORY_ALLOC;
-	memcpy(*dst, src, buf_size);
-	return 0;
-}
-
-u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity **info)
-{
-	struct hpi_msg_strv hm;
-	struct hpi_res_strv *phr;
-	u16 hpi_err;
-	int remaining_attempts = 2;
-	size_t resp_packet_size = 1024;
-
-	*info = NULL;
-
-	while (remaining_attempts--) {
-		phr = kmalloc(resp_packet_size, GFP_KERNEL);
-		HPI_DEBUG_ASSERT(phr != NULL);
-
-		hpi_init_message_responseV1(&hm.h, (u16)sizeof(hm), &phr->h,
-			(u16)resp_packet_size, HPI_OBJ_CONTROL,
-			HPI_CONTROL_GET_INFO);
-		u32TOINDEXES(hC, &hm.h.adapter_index, &hm.h.obj_index);
-
-		hm.strv.header.size = sizeof(hm.strv);
-		phr->strv.header.size = resp_packet_size - sizeof(phr->h);
-
-		hpi_send_recv((struct hpi_message *)&hm.h,
-			(struct hpi_response *)&phr->h);
-		if (phr->h.error == HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL) {
-
-			HPI_DEBUG_ASSERT(phr->h.specific_error >
-				MIN_STRV_PACKET_SIZE
-				&& phr->h.specific_error < 1500);
-			resp_packet_size = phr->h.specific_error;
-		} else {
-			remaining_attempts = 0;
-			if (!phr->h.error)
-				hpi_entity_alloc_and_copy(&phr->strv, info);
-		}
-
-		hpi_err = phr->h.error;
-		kfree(phr);
-	}
-
-	return hpi_err;
-}
-
-u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity **value)
-{
-	struct hpi_msg_strv hm;
-	struct hpi_res_strv *phr;
-	u16 hpi_err;
-	int remaining_attempts = 2;
-
-	*value = NULL;
-
-	while (remaining_attempts--) {
-		phr = kmalloc(strv_packet_size, GFP_KERNEL);
-		if (!phr)
-			return HPI_ERROR_MEMORY_ALLOC;
-
-		hpi_init_message_responseV1(&hm.h, (u16)sizeof(hm), &phr->h,
-			(u16)strv_packet_size, HPI_OBJ_CONTROL,
-			HPI_CONTROL_GET_STATE);
-		u32TOINDEXES(hC, &hm.h.adapter_index, &hm.h.obj_index);
-
-		hm.strv.header.size = sizeof(hm.strv);
-		phr->strv.header.size = strv_packet_size - sizeof(phr->h);
-
-		hpi_send_recv((struct hpi_message *)&hm.h,
-			(struct hpi_response *)&phr->h);
-		if (phr->h.error == HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL) {
-
-			HPI_DEBUG_ASSERT(phr->h.specific_error >
-				MIN_STRV_PACKET_SIZE
-				&& phr->h.specific_error < 1000);
-			strv_packet_size = phr->h.specific_error;
-		} else {
-			remaining_attempts = 0;
-			if (!phr->h.error)
-				hpi_entity_alloc_and_copy(&phr->strv, value);
-		}
-
-		hpi_err = phr->h.error;
-		kfree(phr);
-	}
-
-	return hpi_err;
-}
-
-u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity *value)
-{
-	struct hpi_msg_strv *phm;
-	struct hpi_res_strv hr;
-
-	phm = kmalloc(sizeof(phm->h) + value->header.size, GFP_KERNEL);
-	HPI_DEBUG_ASSERT(phm != NULL);
-
-	hpi_init_message_responseV1(&phm->h,
-		sizeof(phm->h) + value->header.size, &hr.h, sizeof(hr),
-		HPI_OBJ_CONTROL, HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(hC, &phm->h.adapter_index, &phm->h.obj_index);
-	hr.strv.header.size = sizeof(hr.strv);
-
-	memcpy(&phm->strv, value, value->header.size);
-	hpi_send_recv((struct hpi_message *)&phm->h,
-		(struct hpi_response *)&hr.h);
-
-	return hr.h.error;
-}
-
-u16 hpi_entity_alloc_and_pack(const enum e_entity_type type,
-	const size_t item_count, const enum e_entity_role role, void *value,
-	struct hpi_entity **entity)
-{
-	size_t bytes_to_copy, total_size;
-	u16 hE = 0;
-	*entity = NULL;
-
-	hE = hpi_entity_check_type(type);
-	if (hE)
-		return hE;
-
-	HPI_DEBUG_ASSERT(role > entity_role_null && type < LAST_ENTITY_TYPE);
-
-	bytes_to_copy = entity_type_to_size[type] * item_count;
-	total_size = hpi_entity_header_size(*entity) + bytes_to_copy;
-
-	HPI_DEBUG_ASSERT(total_size >= hpi_entity_header_size(*entity)
-		&& total_size < STR_SIZE_FIELD_MAX);
-
-	*entity = kmalloc(total_size, GFP_KERNEL);
-	if (*entity == NULL)
-		return HPI_ERROR_MEMORY_ALLOC;
-	memcpy((*entity)->value, value, bytes_to_copy);
-	(*entity)->header.size =
-		hpi_entity_header_size(*entity) + bytes_to_copy;
-	(*entity)->header.type = type;
-	(*entity)->header.role = role;
-	return 0;
-}
-
-u16 hpi_entity_copy_value_from(struct hpi_entity *entity,
-	enum e_entity_type type, size_t item_count, void *value_dst_p)
-{
-	size_t bytes_to_copy;
-
-	if (entity->header.type != type)
-		return HPI_ERROR_ENTITY_TYPE_MISMATCH;
-
-	if (hpi_entity_item_count(entity) != item_count)
-		return HPI_ERROR_ENTITY_ITEM_COUNT;
-
-	bytes_to_copy = entity_type_to_size[type] * item_count;
-	memcpy(value_dst_p, entity->value, bytes_to_copy);
-	return 0;
-}
-
-u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type,
-	size_t *item_count, enum e_entity_role *role, void **value)
-{
-	u16 err = 0;
-	HPI_DEBUG_ASSERT(entity != NULL);
-
-	if (type)
-		*type = entity->header.type;
-
-	if (role)
-		*role = entity->header.role;
-
-	if (value)
-		*value = entity->value;
-
-	if (item_count != NULL) {
-		if (entity->header.type == entity_type_sequence) {
-			void *guard_p = hpi_entity_ptr_to_next(entity);
-			struct hpi_entity *next = NULL;
-			void *contents = entity->value;
-
-			*item_count = 0;
-			while (contents < guard_p) {
-				(*item_count)++;
-				err = hpi_entity_get_next(contents, 0,
-					guard_p, &next);
-				if (next == NULL || err)
-					break;
-				contents = next;
-			}
-		} else {
-			*item_count = hpi_entity_item_count(entity);
-		}
-	}
-	return err;
-}
-
-u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_OPEN);
-	hm.adapter_index = adapter_index;
-
-	hpi_send_recv(&hm, &hr);
-
-	if (hr.error == 0) {
-		*ph_gpio =
-			hpi_indexes_to_handle(HPI_OBJ_GPIO, adapter_index, 0);
-		if (pw_number_input_bits)
-			*pw_number_input_bits = hr.u.l.number_input_bits;
-		if (pw_number_output_bits)
-			*pw_number_output_bits = hr.u.l.number_output_bits;
-	} else
-		*ph_gpio = 0;
-	return hr.error;
-}
-
-u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 bit_index, u16 *pw_bit_data)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_READ_BIT);
-	u32TOINDEX(h_gpio, &hm.adapter_index);
-	hm.u.l.bit_index = bit_index;
-
-	hpi_send_recv(&hm, &hr);
-
-	*pw_bit_data = hr.u.l.bit_data[0];
-	return hr.error;
-}
-
-u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 aw_all_bit_data[4]
-	)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_READ_ALL);
-	u32TOINDEX(h_gpio, &hm.adapter_index);
-
-	hpi_send_recv(&hm, &hr);
-
-	if (aw_all_bit_data) {
-		aw_all_bit_data[0] = hr.u.l.bit_data[0];
-		aw_all_bit_data[1] = hr.u.l.bit_data[1];
-		aw_all_bit_data[2] = hr.u.l.bit_data[2];
-		aw_all_bit_data[3] = hr.u.l.bit_data[3];
-	}
-	return hr.error;
-}
-
-u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 bit_index, u16 bit_data)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO, HPI_GPIO_WRITE_BIT);
-	u32TOINDEX(h_gpio, &hm.adapter_index);
-	hm.u.l.bit_index = bit_index;
-	hm.u.l.bit_data = bit_data;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 aw_all_bit_data[4]
-	)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_GPIO,
-		HPI_GPIO_WRITE_STATUS);
-	u32TOINDEX(h_gpio, &hm.adapter_index);
-
-	hpi_send_recv(&hm, &hr);
-
-	if (aw_all_bit_data) {
-		aw_all_bit_data[0] = hr.u.l.bit_data[0];
-		aw_all_bit_data[1] = hr.u.l.bit_data[1];
-		aw_all_bit_data[2] = hr.u.l.bit_data[2];
-		aw_all_bit_data[3] = hr.u.l.bit_data[3];
-	}
-	return hr.error;
-}
-
-u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 *ph_async)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
-		HPI_ASYNCEVENT_OPEN);
-	hm.adapter_index = adapter_index;
-
-	hpi_send_recv(&hm, &hr);
-
-	if (hr.error == 0)
-
-		*ph_async =
-			hpi_indexes_to_handle(HPI_OBJ_ASYNCEVENT,
-			adapter_index, 0);
-	else
-		*ph_async = 0;
-	return hr.error;
-
-}
-
-u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
-		HPI_ASYNCEVENT_OPEN);
-	u32TOINDEX(h_async, &hm.adapter_index);
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
-	u16 maximum_events, struct hpi_async_event *p_events,
-	u16 *pw_number_returned)
-{
-
-	return 0;
-}
-
-u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys,
-	u32 h_async, u16 *pw_count)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
-		HPI_ASYNCEVENT_GETCOUNT);
-	u32TOINDEX(h_async, &hm.adapter_index);
-
-	hpi_send_recv(&hm, &hr);
-
-	if (hr.error == 0)
-		if (pw_count)
-			*pw_count = hr.u.as.u.count.count;
-
-	return hr.error;
-}
-
-u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async,
-	u16 maximum_events, struct hpi_async_event *p_events,
-	u16 *pw_number_returned)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_ASYNCEVENT,
-		HPI_ASYNCEVENT_GET);
-	u32TOINDEX(h_async, &hm.adapter_index);
-
-	hpi_send_recv(&hm, &hr);
-	if (!hr.error) {
-		memcpy(p_events, &hr.u.as.u.event,
-			sizeof(struct hpi_async_event));
-		*pw_number_returned = 1;
-	}
-
-	return hr.error;
-}
-
-u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_nv_memory, u16 *pw_size_in_bytes)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY,
-		HPI_NVMEMORY_OPEN);
-	hm.adapter_index = adapter_index;
-
-	hpi_send_recv(&hm, &hr);
-
-	if (hr.error == 0) {
-		*ph_nv_memory =
-			hpi_indexes_to_handle(HPI_OBJ_NVMEMORY, adapter_index,
-			0);
-		if (pw_size_in_bytes)
-			*pw_size_in_bytes = hr.u.n.size_in_bytes;
-	} else
-		*ph_nv_memory = 0;
-	return hr.error;
-}
-
-u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys,
-	u32 h_nv_memory, u16 index, u16 *pw_data)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY,
-		HPI_NVMEMORY_READ_BYTE);
-	u32TOINDEX(h_nv_memory, &hm.adapter_index);
-	hm.u.n.address = index;
-
-	hpi_send_recv(&hm, &hr);
-
-	*pw_data = hr.u.n.data;
-	return hr.error;
-}
-
-u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys,
-	u32 h_nv_memory, u16 index, u16 data)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_NVMEMORY,
-		HPI_NVMEMORY_WRITE_BYTE);
-	u32TOINDEX(h_nv_memory, &hm.adapter_index);
-	hm.u.n.address = index;
-	hm.u.n.data = data;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 profile_index, u32 *ph_profile,
-	u16 *pw_max_profiles)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
-		HPI_PROFILE_OPEN_ALL);
-	hm.adapter_index = adapter_index;
-	hm.obj_index = profile_index;
-	hpi_send_recv(&hm, &hr);
-
-	*pw_max_profiles = hr.u.p.u.o.max_profiles;
-	if (hr.error == 0)
-		*ph_profile =
-			hpi_indexes_to_handle(HPI_OBJ_PROFILE, adapter_index,
-			profile_index);
-	else
-		*ph_profile = 0;
-	return hr.error;
-}
-
-u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
-	u16 bin_index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count,
-	u32 *pmax_micro_seconds, u32 *pmin_micro_seconds)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE, HPI_PROFILE_GET);
-	u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
-	hm.u.p.bin_index = bin_index;
-	hpi_send_recv(&hm, &hr);
-	if (pw_seconds)
-		*pw_seconds = hr.u.p.u.t.seconds;
-	if (pmicro_seconds)
-		*pmicro_seconds = hr.u.p.u.t.micro_seconds;
-	if (pcall_count)
-		*pcall_count = hr.u.p.u.t.call_count;
-	if (pmax_micro_seconds)
-		*pmax_micro_seconds = hr.u.p.u.t.max_micro_seconds;
-	if (pmin_micro_seconds)
-		*pmin_micro_seconds = hr.u.p.u.t.min_micro_seconds;
-	return hr.error;
-}
-
-u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys,
-	u32 h_profile, u32 *putilization)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
-		HPI_PROFILE_GET_UTILIZATION);
-	u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
-	hpi_send_recv(&hm, &hr);
-	if (hr.error) {
-		if (putilization)
-			*putilization = 0;
-	} else {
-		if (putilization)
-			*putilization = hr.u.p.u.t.call_count;
-	}
-	return hr.error;
-}
-
-u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
-	u16 bin_index, char *sz_name, u16 name_length)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
-		HPI_PROFILE_GET_NAME);
-	u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
-	hm.u.p.bin_index = bin_index;
-	hpi_send_recv(&hm, &hr);
-	if (hr.error) {
-		if (sz_name)
-			strcpy(sz_name, "??");
-	} else {
-		if (sz_name)
-			memcpy(sz_name, (char *)hr.u.p.u.n.sz_name,
-				name_length);
-	}
-	return hr.error;
-}
-
-u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
-		HPI_PROFILE_START_ALL);
-	u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_PROFILE,
-		HPI_PROFILE_STOP_ALL);
-	u32TOINDEXES(h_profile, &hm.adapter_index, &hm.obj_index);
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_watchdog)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG,
-		HPI_WATCHDOG_OPEN);
-	hm.adapter_index = adapter_index;
-
-	hpi_send_recv(&hm, &hr);
-
-	if (hr.error == 0)
-		*ph_watchdog =
-			hpi_indexes_to_handle(HPI_OBJ_WATCHDOG, adapter_index,
-			0);
-	else
-		*ph_watchdog = 0;
-	return hr.error;
-}
-
-u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog,
-	u32 time_millisec)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG,
-		HPI_WATCHDOG_SET_TIME);
-	u32TOINDEX(h_watchdog, &hm.adapter_index);
-	hm.u.w.time_ms = time_millisec;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
-
-u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog)
-{
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_WATCHDOG,
-		HPI_WATCHDOG_PING);
-	u32TOINDEX(h_watchdog, &hm.adapter_index);
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
-}
diff --git a/sound/pci/asihpi/hpimsginit.c b/sound/pci/asihpi/hpimsginit.c
index 8e1d099..628376c 100644
--- a/sound/pci/asihpi/hpimsginit.c
+++ b/sound/pci/asihpi/hpimsginit.c
@@ -32,21 +32,6 @@ static u16 res_size[HPI_OBJ_MAXINDEX + 1] = HPI_RESPONSE_SIZE_BY_OBJECT;
 static u16 gwSSX2_bypass;
 
 /** \internal
-  * Used by ASIO driver to disable SSX2 for a single process
-  * \param phSubSys Pointer to HPI subsystem handle.
-  * \param wBypass New bypass setting 0 = off, nonzero = on
-  * \return Previous bypass setting.
-  */
-u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass)
-{
-	u16 old_value = gwSSX2_bypass;
-
-	gwSSX2_bypass = bypass;
-
-	return old_value;
-}
-
-/** \internal
   * initialize the HPI message structure
   */
 static void hpi_init_message(struct hpi_message *phm, u16 object,
@@ -65,7 +50,8 @@ static void hpi_init_message(struct hpi_message *phm, u16 object,
 	phm->object = object;
 	phm->function = function;
 	phm->version = 0;
-	/* Expect adapter index to be set by caller */
+	phm->adapter_index = HPI_ADAPTER_INDEX_INVALID;
+	/* Expect actual adapter index to be set by caller */
 }
 
 /** \internal
diff --git a/sound/pci/asihpi/hpimsginit.h b/sound/pci/asihpi/hpimsginit.h
index 864ad02..bfd330d 100644
--- a/sound/pci/asihpi/hpimsginit.h
+++ b/sound/pci/asihpi/hpimsginit.h
@@ -21,11 +21,15 @@
  (C) Copyright AudioScience Inc. 2007
 *******************************************************************************/
 /* Initialise response headers, or msg/response pairs.
-Note that it is valid to just init a response e.g. when a lower level is preparing
-a response to a message.
-However, when sending a message, a matching response buffer always must be prepared
+Note that it is valid to just init a response e.g. when a lower level is
+preparing a response to a message.
+However, when sending a message, a matching response buffer must always be
+prepared.
 */
 
+#ifndef _HPIMSGINIT_H_
+#define _HPIMSGINIT_H_
+
 void hpi_init_response(struct hpi_response *phr, u16 object, u16 function,
 	u16 error);
 
@@ -38,3 +42,5 @@ void hpi_init_responseV1(struct hpi_response_header *phr, u16 size,
 void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size,
 	struct hpi_response_header *phr, u16 res_size, u16 object,
 	u16 function);
+
+#endif				/* _HPIMSGINIT_H_ */
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
index f01ab96..bcbdf30 100644
--- a/sound/pci/asihpi/hpimsgx.c
+++ b/sound/pci/asihpi/hpimsgx.c
@@ -23,6 +23,7 @@ Extended Message Function With Response Cacheing
 #define SOURCEFILE_NAME "hpimsgx.c"
 #include "hpi_internal.h"
 #include "hpimsginit.h"
+#include "hpicmn.h"
 #include "hpimsgx.h"
 #include "hpidebug.h"
 
@@ -42,22 +43,24 @@ static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
 
 	for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
 		if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
-			&& asihpi_pci_tbl[i].vendor != pci_info->vendor_id)
+			&& asihpi_pci_tbl[i].vendor !=
+			pci_info->pci_dev->vendor)
 			continue;
 		if (asihpi_pci_tbl[i].device != PCI_ANY_ID
-			&& asihpi_pci_tbl[i].device != pci_info->device_id)
+			&& asihpi_pci_tbl[i].device !=
+			pci_info->pci_dev->device)
 			continue;
 		if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
 			&& asihpi_pci_tbl[i].subvendor !=
-			pci_info->subsys_vendor_id)
+			pci_info->pci_dev->subsystem_vendor)
 			continue;
 		if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
 			&& asihpi_pci_tbl[i].subdevice !=
-			pci_info->subsys_device_id)
+			pci_info->pci_dev->subsystem_device)
 			continue;
 
-		HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i,
-			asihpi_pci_tbl[i].driver_data);
+		/* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
+		   asihpi_pci_tbl[i].driver_data); */
 		return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
 	}
 
@@ -67,21 +70,12 @@ static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
 static inline void hw_entry_point(struct hpi_message *phm,
 	struct hpi_response *phr)
 {
-
-	hpi_handler_func *ep;
-
-	if (phm->adapter_index < HPI_MAX_ADAPTERS) {
-		ep = (hpi_handler_func *) hpi_entry_points[phm->
-			adapter_index];
-		if (ep) {
-			HPI_DEBUG_MESSAGE(DEBUG, phm);
-			ep(phm, phr);
-			HPI_DEBUG_RESPONSE(phr);
-			return;
-		}
-	}
-	hpi_init_response(phr, phm->object, phm->function,
-		HPI_ERROR_PROCESSING_MESSAGE);
+	if ((phm->adapter_index < HPI_MAX_ADAPTERS)
+		&& hpi_entry_points[phm->adapter_index])
+		hpi_entry_points[phm->adapter_index] (phm, phr);
+	else
+		hpi_init_response(phr, phm->object, phm->function,
+			HPI_ERROR_PROCESSING_MESSAGE);
 }
 
 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
@@ -100,6 +94,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 	void *h_owner);
 
 static void HPIMSGX__reset(u16 adapter_index);
+
 static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
 
@@ -153,8 +148,6 @@ static struct hpi_stream_response
 
 static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
 
-static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS;
-
 static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
 
 /* use these to keep track of opens from user mode apps/DLLs */
@@ -167,6 +160,11 @@ static struct asi_open_state
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 	void *h_owner)
 {
+	if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID)
+		HPI_DEBUG_LOG(WARNING,
+			"suspicious adapter index %d in subsys message 0x%x.\n",
+			phm->adapter_index, phm->function);
+
 	switch (phm->function) {
 	case HPI_SUBSYS_GET_VERSION:
 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
@@ -204,85 +202,37 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 			HPI_SUBSYS_DRIVER_UNLOAD, 0);
 		return;
 
-	case HPI_SUBSYS_GET_INFO:
-		HPI_COMMON(phm, phr);
-		break;
-
-	case HPI_SUBSYS_FIND_ADAPTERS:
-		memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
-			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
-		break;
 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
-		memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
-			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
-		phr->function = HPI_SUBSYS_GET_NUM_ADAPTERS;
-		break;
 	case HPI_SUBSYS_GET_ADAPTER:
-		{
-			int count = phm->adapter_index;
-			int index = 0;
-			hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
-				HPI_SUBSYS_GET_ADAPTER, 0);
-
-			/* This is complicated by the fact that we want to
-			 * "skip" 0's in the adapter list.
-			 * First, make sure we are pointing to a
-			 * non-zero adapter type.
-			 */
-			while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-				s.aw_adapter_list[index] == 0) {
-				index++;
-				if (index >= HPI_MAX_ADAPTERS)
-					break;
-			}
-			while (count) {
-				/* move on to the next adapter */
-				index++;
-				if (index >= HPI_MAX_ADAPTERS)
-					break;
-				while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-					s.aw_adapter_list[index] == 0) {
-					index++;
-					if (index >= HPI_MAX_ADAPTERS)
-						break;
-				}
-				count--;
-			}
+		HPI_COMMON(phm, phr);
+		break;
 
-			if (index < HPI_MAX_ADAPTERS) {
-				phr->u.s.adapter_index = (u16)index;
-				phr->u.s.aw_adapter_list[0] =
-					gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-					s.aw_adapter_list[index];
-			} else {
-				phr->u.s.adapter_index = 0;
-				phr->u.s.aw_adapter_list[0] = 0;
-				phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
-			}
-			break;
-		}
 	case HPI_SUBSYS_CREATE_ADAPTER:
 		HPIMSGX__init(phm, phr);
 		break;
+
 	case HPI_SUBSYS_DELETE_ADAPTER:
-		HPIMSGX__cleanup(phm->adapter_index, h_owner);
+		HPIMSGX__cleanup(phm->obj_index, h_owner);
 		{
 			struct hpi_message hm;
 			struct hpi_response hr;
-			/* call to HPI_ADAPTER_CLOSE */
 			hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
 				HPI_ADAPTER_CLOSE);
-			hm.adapter_index = phm->adapter_index;
+			hm.adapter_index = phm->obj_index;
 			hw_entry_point(&hm, &hr);
 		}
-		hw_entry_point(phm, phr);
-		gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
-			aw_adapter_list[phm->adapter_index]
-			= 0;
-		hpi_entry_points[phm->adapter_index] = NULL;
+		if ((phm->obj_index < HPI_MAX_ADAPTERS)
+			&& hpi_entry_points[phm->obj_index]) {
+			hpi_entry_points[phm->obj_index] (phm, phr);
+			hpi_entry_points[phm->obj_index] = NULL;
+		} else
+			phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
+
 		break;
 	default:
-		hw_entry_point(phm, phr);
+		/* Must explicitly handle every subsys message in this switch */
+		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
+			HPI_ERROR_INVALID_FUNC);
 		break;
 	}
 }
@@ -409,33 +359,7 @@ void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
 		break;
 	}
 	HPI_DEBUG_RESPONSE(phr);
-#if 1
-	if (phr->error >= HPI_ERROR_BACKEND_BASE) {
-		void *ep = NULL;
-		char *ep_name;
-
-		HPI_DEBUG_MESSAGE(ERROR, phm);
-
-		if (phm->adapter_index < HPI_MAX_ADAPTERS)
-			ep = hpi_entry_points[phm->adapter_index];
-
-		/* Don't need this? Have adapter index in debug info
-		   Know at driver load time index->backend mapping */
-		if (ep == HPI_6000)
-			ep_name = "HPI_6000";
-		else if (ep == HPI_6205)
-			ep_name = "HPI_6205";
-		else
-			ep_name = "unknown";
-
-		HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name,
-			phr->error);
-
-		if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)
-			hpi_debug_data((u16 *)phm,
-				sizeof(*phm) / sizeof(u16));
-	}
-#endif
+
 }
 
 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
@@ -484,7 +408,7 @@ static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
 	else {
 		instream_user_open[phm->adapter_index][phm->
 			obj_index].open_flag = 1;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
@@ -509,7 +433,7 @@ static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
 				sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
 		}
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 
 static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
@@ -530,7 +454,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
 		instream_user_open[phm->adapter_index][phm->
 			obj_index].h_owner = NULL;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 			HPI_ISTREAM_RESET);
@@ -556,7 +480,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 				obj_index].h_owner);
 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 
 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
@@ -581,7 +505,7 @@ static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
 	else {
 		outstream_user_open[phm->adapter_index][phm->
 			obj_index].open_flag = 1;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
@@ -606,7 +530,7 @@ static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
 				sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
 		}
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 
 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
@@ -628,7 +552,7 @@ static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
 		outstream_user_open[phm->adapter_index][phm->
 			obj_index].h_owner = NULL;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 			HPI_OSTREAM_RESET);
@@ -654,7 +578,7 @@ static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
 				obj_index].h_owner);
 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 
 static u16 adapter_prepare(u16 adapter)
@@ -683,16 +607,9 @@ static u16 adapter_prepare(u16 adapter)
 	if (hr.error)
 		return hr.error;
 
-	aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams;
-	aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams;
-	aDAPTER_INFO[adapter].type = hr.u.a.adapter_type;
-
-	gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] =
-		hr.u.a.adapter_type;
-	gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++;
-	if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS)
-		gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters =
-			HPI_MAX_ADAPTERS;
+	aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
+	aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
+	aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
 
 	/* call to HPI_OSTREAM_OPEN */
 	for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
@@ -727,7 +644,7 @@ static u16 adapter_prepare(u16 adapter)
 	memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
 		sizeof(rESP_HPI_MIXER_OPEN[0]));
 
-	return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error;
+	return 0;
 }
 
 static void HPIMSGX__reset(u16 adapter_index)
@@ -737,12 +654,6 @@ static void HPIMSGX__reset(u16 adapter_index)
 	struct hpi_response hr;
 
 	if (adapter_index == HPIMSGX_ALLADAPTERS) {
-		/* reset all responses to contain errors */
-		hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
-			HPI_SUBSYS_FIND_ADAPTERS, 0);
-		memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
-			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
-
 		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
 
 			hpi_init_response(&hr, HPI_OBJ_ADAPTER,
@@ -783,12 +694,6 @@ static void HPIMSGX__reset(u16 adapter_index)
 			rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
 				HPI_ERROR_INVALID_OBJ;
 		}
-		if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-			s.aw_adapter_list[adapter_index]) {
-			gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-				s.aw_adapter_list[adapter_index] = 0;
-			gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--;
-		}
 	}
 }
 
@@ -802,15 +707,9 @@ static u16 HPIMSGX__init(struct hpi_message *phm,
 	hpi_handler_func *entry_point_func;
 	struct hpi_response hr;
 
-	if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS)
-		return HPI_ERROR_BAD_ADAPTER_NUMBER;
-
 	/* Init response here so we can pass in previous adapter list */
 	hpi_init_response(&hr, phm->object, phm->function,
 		HPI_ERROR_INVALID_OBJ);
-	memcpy(hr.u.s.aw_adapter_list,
-		gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list,
-		sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list));
 
 	entry_point_func =
 		hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
@@ -860,7 +759,7 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
 				struct hpi_response hr;
 
 				HPI_DEBUG_LOG(DEBUG,
-					"close adapter %d ostream %d\n",
+					"Close adapter %d ostream %d\n",
 					adapter, i);
 
 				hpi_init_message_response(&hm, &hr,
@@ -884,7 +783,7 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
 				struct hpi_response hr;
 
 				HPI_DEBUG_LOG(DEBUG,
-					"close adapter %d istream %d\n",
+					"Close adapter %d istream %d\n",
 					adapter, i);
 
 				hpi_init_message_response(&hm, &hr,
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index 22dbd91..cd624f1 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -30,6 +30,7 @@ Common Linux HPI ioctl and module probe/remove functions
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <asm/uaccess.h>
+#include <linux/pci.h>
 #include <linux/stringify.h>
 
 #ifdef MODULE_FIRMWARE
@@ -45,7 +46,7 @@ MODULE_FIRMWARE("asihpi/dsp8900.bin");
 static int prealloc_stream_buf;
 module_param(prealloc_stream_buf, int, S_IRUGO);
 MODULE_PARM_DESC(prealloc_stream_buf,
-	"preallocate size for per-adapter stream buffer");
+	"Preallocate size for per-adapter stream buffer");
 
 /* Allow the debug level to be changed after module load.
  E.g.   echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel
@@ -121,8 +122,8 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
 
 	/* Read the message and response pointers from user space.  */
-	if (get_user(puhm, &phpi_ioctl_data->phm) ||
-	    get_user(puhr, &phpi_ioctl_data->phr)) {
+	if (get_user(puhm, &phpi_ioctl_data->phm)
+		|| get_user(puhr, &phpi_ioctl_data->phr)) {
 		err = -EFAULT;
 		goto out;
 	}
@@ -135,7 +136,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	if (hm->h.size > sizeof(*hm))
 		hm->h.size = sizeof(*hm);
 
-	/*printk(KERN_INFO "message size %d\n", hm->h.wSize); */
+	/* printk(KERN_INFO "message size %d\n", hm->h.wSize); */
 
 	uncopied_bytes = copy_from_user(hm, puhm, hm->h.size);
 	if (uncopied_bytes) {
@@ -155,8 +156,13 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		goto out;
 	}
 
+	if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	pa = &adapters[hm->h.adapter_index];
-	hr->h.size = 0;
+	hr->h.size = res_max_size;
 	if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
 		switch (hm->h.function) {
 		case HPI_SUBSYS_CREATE_ADAPTER:
@@ -216,7 +222,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 				 */
 				if (pa->buffer_size < size) {
 					HPI_DEBUG_LOG(DEBUG,
-						"realloc adapter %d stream "
+						"Realloc adapter %d stream "
 						"buffer from %zd to %d\n",
 						hm->h.adapter_index,
 						pa->buffer_size, size);
@@ -259,7 +265,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 				copy_from_user(pa->p_buffer, ptr, size);
 			if (uncopied_bytes)
 				HPI_DEBUG_LOG(WARNING,
-					"missed %d of %d "
+					"Missed %d of %d "
 					"bytes from user\n", uncopied_bytes,
 					size);
 		}
@@ -271,7 +277,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 				copy_to_user(ptr, pa->p_buffer, size);
 			if (uncopied_bytes)
 				HPI_DEBUG_LOG(WARNING,
-					"missed %d of %d " "bytes to user\n",
+					"Missed %d of %d " "bytes to user\n",
 					uncopied_bytes, size);
 		}
 
@@ -290,9 +296,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	if (hr->h.size > res_max_size) {
 		HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size,
 			res_max_size);
-		/*HPI_DEBUG_MESSAGE(ERROR, hm); */
-		err = -EFAULT;
-		goto out;
+		hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
+		hr->h.specific_error = hr->h.size;
+		hr->h.size = sizeof(hr->h);
 	}
 
 	uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
@@ -320,18 +326,26 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 
 	memset(&adapter, 0, sizeof(adapter));
 
-	printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n",
-		pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor,
+	dev_printk(KERN_DEBUG, &pci_dev->dev,
+		"probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor,
+		pci_dev->device, pci_dev->subsystem_vendor,
 		pci_dev->subsystem_device, pci_dev->devfn);
 
+	if (pci_enable_device(pci_dev) < 0) {
+		dev_printk(KERN_ERR, &pci_dev->dev,
+			"pci_enable_device failed, disabling device\n");
+		return -EIO;
+	}
+
+	pci_set_master(pci_dev);	/* also sets latency timer if < 16 */
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_CREATE_ADAPTER);
 	hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
 		HPI_ERROR_PROCESSING_MESSAGE);
 
-	hm.adapter_index = -1;	/* an invalid index */
+	hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
 
-	/* fill in HPI_PCI information from kernel provided information */
 	adapter.pci = pci_dev;
 
 	nm = HPI_MAX_ADAPTER_MEM_SPACES;
@@ -359,19 +373,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 		pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx];
 	}
 
-	/* could replace Pci with direct pointer to pci_dev for linux
-	   Instead wrap accessor functions for IDs etc.
-	   Would it work for windows?
-	 */
-	pci.bus_number = pci_dev->bus->number;
-	pci.vendor_id = (u16)pci_dev->vendor;
-	pci.device_id = (u16)pci_dev->device;
-	pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff);
-	pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff);
-	pci.device_number = pci_dev->devfn;
-	pci.interrupt = pci_dev->irq;
-	pci.p_os_data = pci_dev;
-
+	pci.pci_dev = pci_dev;
 	hm.u.s.resource.bus_type = HPI_BUS_PCI;
 	hm.u.s.resource.r.pci = &pci;
 
@@ -392,10 +394,10 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 	}
 
 	adapter.index = hr.u.s.adapter_index;
-	adapter.type = hr.u.s.aw_adapter_list[adapter.index];
+	adapter.type = hr.u.s.adapter_type;
 	hm.adapter_index = adapter.index;
 
-	err = hpi_adapter_open(NULL, adapter.index);
+	err = hpi_adapter_open(adapter.index);
 	if (err)
 		goto err;
 
@@ -407,8 +409,9 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 	mutex_init(&adapters[adapter.index].mutex);
 	pci_set_drvdata(pci_dev, &adapters[adapter.index]);
 
-	printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n",
-		adapter.type, adapter.index);
+	dev_printk(KERN_INFO, &pci_dev->dev,
+		"probe succeeded for ASI%04X HPI index %d\n", adapter.type,
+		adapter.index);
 
 	return 0;
 
@@ -439,7 +442,8 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_DELETE_ADAPTER);
-	hm.adapter_index = pa->index;
+	hm.obj_index = pa->index;
+	hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
 	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
 
 	/* unmap PCI memory space, mapped during device init. */
@@ -450,20 +454,18 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
 		}
 	}
 
-	if (pa->p_buffer) {
-		pa->buffer_size = 0;
+	if (pa->p_buffer)
 		vfree(pa->p_buffer);
-	}
 
 	pci_set_drvdata(pci_dev, NULL);
-	/*
-	   printk(KERN_INFO "PCI device (%04x:%04x,%04x:%04x,%04x),"
-	   " HPI index # %d, removed.\n",
-	   pci_dev->vendor, pci_dev->device,
-	   pci_dev->subsystem_vendor,
-	   pci_dev->subsystem_device, pci_dev->devfn,
-	   pa->index);
-	 */
+	if (1)
+		dev_printk(KERN_INFO, &pci_dev->dev,
+			"remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n",
+			pci_dev->vendor, pci_dev->device,
+			pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+			pci_dev->devfn, pa->index);
+
+	memset(pa, 0, sizeof(*pa));
 }
 
 void __init asihpi_init(void)
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h
index 370f39b..03273e7 100644
--- a/sound/pci/asihpi/hpios.h
+++ b/sound/pci/asihpi/hpios.h
@@ -27,9 +27,7 @@ HPI Operating System Specific macros for Linux Kernel driver
 #define HPI_OS_LINUX_KERNEL
 
 #define HPI_OS_DEFINED
-#define HPI_KERNEL_MODE
-
-#define HPI_REASSIGN_DUPLICATE_ADAPTER_IDX
+#define HPI_BUILD_KERNEL_MODE
 
 #include <linux/io.h>
 #include <asm/system.h>
@@ -135,20 +133,20 @@ static inline void cond_unlock(struct hpios_spinlock *l)
 
 #define hpios_msgxlock_init(obj)      spin_lock_init(&(obj)->lock)
 #define hpios_msgxlock_lock(obj)   cond_lock(obj)
-#define hpios_msgxlock_un_lock(obj) cond_unlock(obj)
+#define hpios_msgxlock_unlock(obj) cond_unlock(obj)
 
 #define hpios_dsplock_init(obj)       spin_lock_init(&(obj)->dsp_lock.lock)
 #define hpios_dsplock_lock(obj)    cond_lock(&(obj)->dsp_lock)
 #define hpios_dsplock_unlock(obj)  cond_unlock(&(obj)->dsp_lock)
 
 #ifdef CONFIG_SND_DEBUG
-#define HPI_DEBUG
+#define HPI_BUILD_DEBUG
 #endif
 
 #define HPI_ALIST_LOCKING
 #define hpios_alistlock_init(obj)    spin_lock_init(&((obj)->list_lock.lock))
 #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
-#define hpios_alistlock_un_lock(obj) spin_unlock(&((obj)->list_lock.lock))
+#define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock))
 
 struct hpi_adapter {
 	/* mutex prevents contention for one card
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 49d572a..3119cd9 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -522,7 +522,7 @@ static int snd_atiixp_aclink_reset(struct atiixp *chip)
 		atiixp_read(chip, CMD);
 		mdelay(1);
 		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
-		if (--timeout) {
+		if (!--timeout) {
 			snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
 			break;
 		}
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 91d7036..2f74c2f 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -498,7 +498,7 @@ static int snd_atiixp_aclink_reset(struct atiixp_modem *chip)
 		atiixp_read(chip, CMD);
 		msleep(1);
 		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
-		if (--timeout) {
+		if (!--timeout) {
 			snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n");
 			break;
 		}
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index cf46bba..ecb8f4d 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -211,7 +211,7 @@ static void vortex_adbdma_startfifo(vortex_t * vortex, int adbdma);
 //static void vortex_adbdma_stopfifo(vortex_t *vortex, int adbdma);
 static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma);
 static void vortex_adbdma_resumefifo(vortex_t * vortex, int adbdma);
-static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma);
+static inline int vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma);
 static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma);
 
 #ifndef CHIP_AU8810
@@ -219,7 +219,7 @@ static void vortex_wtdma_startfifo(vortex_t * vortex, int wtdma);
 static void vortex_wtdma_stopfifo(vortex_t * vortex, int wtdma);
 static void vortex_wtdma_pausefifo(vortex_t * vortex, int wtdma);
 static void vortex_wtdma_resumefifo(vortex_t * vortex, int wtdma);
-static int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma);
+static inline int vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma);
 #endif
 
 /* global stuff. */
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 16c0bdf..4891503 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1249,7 +1249,7 @@ static void vortex_adbdma_resetup(vortex_t *vortex, int adbdma) {
 	}
 }
 
-static int inline vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma)
+static inline int vortex_adbdma_getlinearpos(vortex_t * vortex, int adbdma)
 {
 	stream_t *dma = &vortex->dma_adb[adbdma];
 	int temp, page, delta;
@@ -1506,7 +1506,7 @@ static int vortex_wtdma_getcursubuffer(vortex_t * vortex, int wtdma)
 		 POS_SHIFT) & POS_MASK);
 }
 #endif
-static int inline vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma)
+static inline int vortex_wtdma_getlinearpos(vortex_t * vortex, int wtdma)
 {
 	stream_t *dma = &vortex->dma_wt[wtdma];
 	int temp;
diff --git a/sound/pci/au88x0/au88x0_eq.c b/sound/pci/au88x0/au88x0_eq.c
index 38602b8..278ed81 100644
--- a/sound/pci/au88x0/au88x0_eq.c
+++ b/sound/pci/au88x0/au88x0_eq.c
@@ -896,7 +896,8 @@ static int __devinit vortex_eq_init(vortex_t * vortex)
 		if ((kcontrol =
 		     snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
 			return -ENOMEM;
-		strcpy(kcontrol->id.name, EqBandLabels[i]);
+		snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
+			"%s Playback Volume", EqBandLabels[i]);
 		kcontrol->private_value = i;
 		if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
 			return err;
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 573594b..5715c4d0 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1,6 +1,5 @@
-/*
- *  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
- *  Copyright (C) 2002, 2005 - 2010 by Andreas Mohr <andi AT lisas.de>
+/*  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
+ *  Copyright (C) 2002, 2005 - 2011 by Andreas Mohr <andi AT lisas.de>
  *
  *  Framework borrowed from Bart Hartgers's als4000.c.
  *  Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
@@ -66,6 +65,13 @@
  *    addresses illegally. So far unfortunately it looks like the very flexible
  *    ALSA AC97 support is still not enough to easily compensate for such a
  *    grave layout violation despite all tweaks and quirks mechanisms it offers.
+ *    Well, not quite: now ac97 layer is much improved (bus-specific ops!),
+ *    thus I was able to implement support - it's actually working quite well.
+ *    An interesting item might be Aztech AMR 2800-W, since it's an AC97
+ *    modem card which might reveal the Aztech-specific codec ID which
+ *    we might want to pretend, too. Dito PCI168's brother, PCI368,
+ *    where the advertising datasheet says it's AC97-based and has a
+ *    Digital Enhanced Game Port.
  *  - builtin genuine OPL3 - verified to work fine, 20080506
  *  - full duplex 16bit playback/record at independent sampling rate
  *  - MPU401 (+ legacy address support, claimed by one official spec sheet)
@@ -189,6 +195,16 @@
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 #include <sound/initval.h>
+/*
+ * Config switch, to use ALSA's AC97 layer instead of old custom mixer crap.
+ * If the AC97 compatibility parts we needed to implement locally turn out
+ * to work nicely, then remove the old implementation eventually.
+ */
+#define AZF_USE_AC97_LAYER 1
+
+#ifdef AZF_USE_AC97_LAYER
+#include <sound/ac97_codec.h>
+#endif
 #include "azt3328.h"
 
 MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>");
@@ -328,6 +344,10 @@ struct snd_azf3328 {
 	/* playback, recording and I2S out codecs */
 	struct snd_azf3328_codec_data codecs[3];
 
+#ifdef AZF_USE_AC97_LAYER
+	struct snd_ac97 *ac97;
+#endif
+
 	struct snd_card *card;
 	struct snd_rawmidi *rmidi;
 
@@ -506,7 +526,7 @@ snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
 #define AZF_MUTE_BIT 0x80
 
 static bool
-snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
+snd_azf3328_mixer_mute_control(const struct snd_azf3328 *chip,
 			   unsigned reg, bool do_mute
 )
 {
@@ -521,6 +541,323 @@ snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
 	return (do_mute) ? !updated : updated;
 }
 
+static inline bool
+snd_azf3328_mixer_mute_control_master(const struct snd_azf3328 *chip,
+			   bool do_mute
+)
+{
+	return snd_azf3328_mixer_mute_control(
+		chip,
+		IDX_MIXER_PLAY_MASTER,
+		do_mute
+	);
+}
+
+static inline bool
+snd_azf3328_mixer_mute_control_pcm(const struct snd_azf3328 *chip,
+			   bool do_mute
+)
+{
+	return snd_azf3328_mixer_mute_control(
+		chip,
+		IDX_MIXER_WAVEOUT,
+		do_mute
+	);
+}
+
+static inline void
+snd_azf3328_mixer_reset(const struct snd_azf3328 *chip)
+{
+	/* reset (close) mixer:
+	 * first mute master volume, then reset
+	 */
+	snd_azf3328_mixer_mute_control_master(chip, 1);
+	snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
+}
+
+#ifdef AZF_USE_AC97_LAYER
+
+static inline void
+snd_azf3328_mixer_ac97_map_unsupported(unsigned short reg, const char *mode)
+{
+	/* need to add some more or less clever emulation? */
+	printk(KERN_WARNING
+		"azt3328: missing %s emulation for AC97 register 0x%02x!\n",
+		mode, reg);
+}
+
+/*
+ * Need to have _special_ AC97 mixer hardware register index mapper,
+ * to compensate for the issue of a rather AC97-incompatible hardware layout.
+ */
+#define AZF_REG_MASK 0x3f
+#define AZF_AC97_REG_UNSUPPORTED 0x8000
+#define AZF_AC97_REG_REAL_IO_READ 0x4000
+#define AZF_AC97_REG_REAL_IO_WRITE 0x2000
+#define AZF_AC97_REG_REAL_IO_RW \
+	(AZF_AC97_REG_REAL_IO_READ | AZF_AC97_REG_REAL_IO_WRITE)
+#define AZF_AC97_REG_EMU_IO_READ 0x0400
+#define AZF_AC97_REG_EMU_IO_WRITE 0x0200
+#define AZF_AC97_REG_EMU_IO_RW \
+	(AZF_AC97_REG_EMU_IO_READ | AZF_AC97_REG_EMU_IO_WRITE)
+static unsigned short
+snd_azf3328_mixer_ac97_map_reg_idx(unsigned short reg)
+{
+	static const struct {
+		unsigned short azf_reg;
+	} azf_reg_mapper[] = {
+		/* Especially when taking into consideration
+		 * mono/stereo-based sequence of azf vs. AC97 control series,
+		 * it's quite obvious that azf simply got rid
+		 * of the AC97_HEADPHONE control at its intended offset,
+		 * thus shifted _all_ controls by one,
+		 * and _then_ simply added it as an FMSYNTH control at the end,
+		 * to make up for the offset.
+		 * This means we'll have to translate indices here as
+		 * needed and then do some tiny AC97 patch action
+		 * (snd_ac97_rename_vol_ctl() etc.) - that's it.
+		 */
+		{ /* AC97_RESET */ IDX_MIXER_RESET
+			| AZF_AC97_REG_REAL_IO_WRITE
+			| AZF_AC97_REG_EMU_IO_READ },
+		{ /* AC97_MASTER */ IDX_MIXER_PLAY_MASTER },
+		 /* note large shift: AC97_HEADPHONE to IDX_MIXER_FMSYNTH! */
+		{ /* AC97_HEADPHONE */ IDX_MIXER_FMSYNTH },
+		{ /* AC97_MASTER_MONO */ IDX_MIXER_MODEMOUT },
+		{ /* AC97_MASTER_TONE */ IDX_MIXER_BASSTREBLE },
+		{ /* AC97_PC_BEEP */ IDX_MIXER_PCBEEP },
+		{ /* AC97_PHONE */ IDX_MIXER_MODEMIN },
+		{ /* AC97_MIC */ IDX_MIXER_MIC },
+		{ /* AC97_LINE */ IDX_MIXER_LINEIN },
+		{ /* AC97_CD */ IDX_MIXER_CDAUDIO },
+		{ /* AC97_VIDEO */ IDX_MIXER_VIDEO },
+		{ /* AC97_AUX */ IDX_MIXER_AUX },
+		{ /* AC97_PCM */ IDX_MIXER_WAVEOUT },
+		{ /* AC97_REC_SEL */ IDX_MIXER_REC_SELECT },
+		{ /* AC97_REC_GAIN */ IDX_MIXER_REC_VOLUME },
+		{ /* AC97_REC_GAIN_MIC */ AZF_AC97_REG_EMU_IO_RW },
+		{ /* AC97_GENERAL_PURPOSE */ IDX_MIXER_ADVCTL2 },
+		{ /* AC97_3D_CONTROL */ IDX_MIXER_ADVCTL1 },
+	};
+
+	unsigned short reg_azf = AZF_AC97_REG_UNSUPPORTED;
+
+	/* azf3328 supports the low-numbered and low-spec:ed range
+	   of AC97 regs only */
+	if (reg <= AC97_3D_CONTROL) {
+		unsigned short reg_idx = reg / 2;
+		reg_azf = azf_reg_mapper[reg_idx].azf_reg;
+		/* a translation-only entry means it's real read/write: */
+		if (!(reg_azf & ~AZF_REG_MASK))
+			reg_azf |= AZF_AC97_REG_REAL_IO_RW;
+	} else {
+		switch (reg) {
+		case AC97_POWERDOWN:
+			reg_azf = AZF_AC97_REG_EMU_IO_RW;
+			break;
+		case AC97_EXTENDED_ID:
+			reg_azf = AZF_AC97_REG_EMU_IO_READ;
+			break;
+		case AC97_EXTENDED_STATUS:
+			/* I don't know what the h*ll AC97 layer
+			 * would consult this _extended_ register for
+			 * given a base-AC97-advertised card,
+			 * but let's just emulate it anyway :-P
+			 */
+			reg_azf = AZF_AC97_REG_EMU_IO_RW;
+			break;
+		case AC97_VENDOR_ID1:
+		case AC97_VENDOR_ID2:
+			reg_azf = AZF_AC97_REG_EMU_IO_READ;
+			break;
+		}
+	}
+	return reg_azf;
+}
+
+static const unsigned short
+azf_emulated_ac97_caps =
+	AC97_BC_DEDICATED_MIC |
+	AC97_BC_BASS_TREBLE |
+	/* Headphone is an FM Synth control here */
+	AC97_BC_HEADPHONE |
+	/* no AC97_BC_LOUDNESS! */
+	/* mask 0x7c00 is
+	   vendor-specific 3D enhancement
+	   vendor indicator.
+	   Since there actually _is_ an
+	   entry for Aztech Labs
+	   (13), make damn sure
+	   to indicate it. */
+	(13 << 10);
+
+static const unsigned short
+azf_emulated_ac97_powerdown =
+	/* pretend everything to be active */
+		AC97_PD_ADC_STATUS |
+		AC97_PD_DAC_STATUS |
+		AC97_PD_MIXER_STATUS |
+		AC97_PD_VREF_STATUS;
+
+/*
+ * Emulated, _inofficial_ vendor ID
+ * (there might be some devices such as the MR 2800-W
+ * which could reveal the real Aztech AC97 ID).
+ * We choose to use "AZT" prefix, and then use 1 to indicate PCI168
+ * (better don't use 0x68 since there's a PCI368 as well).
+ */
+static const unsigned int
+azf_emulated_ac97_vendor_id = 0x415a5401;
+
+static unsigned short
+snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97)
+{
+	const struct snd_azf3328 *chip = ac97->private_data;
+	unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
+	unsigned short reg_val = 0;
+	bool unsupported = 0;
+
+	snd_azf3328_dbgmixer(
+		"snd_azf3328_mixer_ac97_read reg_ac97 %u\n",
+			reg_ac97
+	);
+	if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
+		unsupported = 1;
+	else {
+		if (reg_azf & AZF_AC97_REG_REAL_IO_READ)
+			reg_val = snd_azf3328_mixer_inw(chip,
+						reg_azf & AZF_REG_MASK);
+		else {
+			/*
+			 * Proceed with dummy I/O read,
+			 * to ensure compatible timing where this may matter.
+			 * (ALSA AC97 layer usually doesn't call I/O functions
+			 * due to intelligent I/O caching anyway)
+			 * Choose a mixer register that's thoroughly unrelated
+			 * to common audio (try to minimize distortion).
+			 */
+			snd_azf3328_mixer_inw(chip, IDX_MIXER_SOMETHING30H);
+		}
+
+		if (reg_azf & AZF_AC97_REG_EMU_IO_READ) {
+			switch (reg_ac97) {
+			case AC97_RESET:
+				reg_val |= azf_emulated_ac97_caps;
+				break;
+			case AC97_POWERDOWN:
+				reg_val |= azf_emulated_ac97_powerdown;
+				break;
+			case AC97_EXTENDED_ID:
+			case AC97_EXTENDED_STATUS:
+				/* AFAICS we simply can't support anything: */
+				reg_val |= 0;
+				break;
+			case AC97_VENDOR_ID1:
+				reg_val = azf_emulated_ac97_vendor_id >> 16;
+				break;
+			case AC97_VENDOR_ID2:
+				reg_val = azf_emulated_ac97_vendor_id & 0xffff;
+				break;
+			default:
+				unsupported = 1;
+				break;
+			}
+		}
+	}
+	if (unsupported)
+		snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "read");
+
+	return reg_val;
+}
+
+static void
+snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
+		     unsigned short reg_ac97, unsigned short val)
+{
+	const struct snd_azf3328 *chip = ac97->private_data;
+	unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
+	bool unsupported = 0;
+
+	snd_azf3328_dbgmixer(
+		"snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n",
+			reg_ac97, val
+	);
+	if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
+		unsupported = 1;
+	else {
+		if (reg_azf & AZF_AC97_REG_REAL_IO_WRITE)
+			snd_azf3328_mixer_outw(
+				chip,
+				reg_azf & AZF_REG_MASK,
+				val
+			);
+		else
+		if (reg_azf & AZF_AC97_REG_EMU_IO_WRITE) {
+			switch (reg_ac97) {
+			case AC97_REC_GAIN_MIC:
+			case AC97_POWERDOWN:
+			case AC97_EXTENDED_STATUS:
+				/*
+				 * Silently swallow these writes.
+				 * Since for most registers our card doesn't
+				 * actually support a comparable feature,
+				 * this is exactly what we should do here.
+				 * The AC97 layer's I/O caching probably
+				 * automatically takes care of all the rest...
+				 * (remembers written values etc.)
+				 */
+				break;
+			default:
+				unsupported = 1;
+				break;
+			}
+		}
+	}
+	if (unsupported)
+		snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write");
+}
+
+static int __devinit
+snd_azf3328_mixer_new(struct snd_azf3328 *chip)
+{
+	struct snd_ac97_bus *bus;
+	struct snd_ac97_template ac97;
+	static struct snd_ac97_bus_ops ops = {
+		.write = snd_azf3328_mixer_ac97_write,
+		.read = snd_azf3328_mixer_ac97_read,
+	};
+	int rc;
+
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.scaps = AC97_SCAP_SKIP_MODEM
+			| AC97_SCAP_AUDIO /* we support audio! */
+			| AC97_SCAP_NO_SPDIF;
+	ac97.private_data = chip;
+	ac97.pci = chip->pci;
+
+	/*
+	 * ALSA's AC97 layer has terrible init crackling issues,
+	 * unfortunately, and since it makes use of AC97_RESET,
+	 * there's no use trying to mute Master Playback proactively.
+	 */
+
+	rc = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
+	if (!rc)
+		rc = snd_ac97_mixer(bus, &ac97, &chip->ac97);
+		/*
+		 * Make sure to complain loudly in case of AC97 init failure,
+		 * since failure may happen quite often,
+		 * due to this card being a very quirky AC97 "lookalike".
+		 */
+	if (rc)
+		printk(KERN_ERR "azt3328: AC97 init failed, err %d!\n", rc);
+
+	/* If we return an error here, then snd_card_free() should
+	 * free up any ac97 codecs that got created, as well as the bus.
+	 */
+	return rc;
+}
+#else /* AZF_USE_AC97_LAYER */
 static void
 snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip,
 					 unsigned reg,
@@ -945,6 +1282,7 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
 	snd_azf3328_dbgcallleave();
 	return 0;
 }
+#endif /* AZF_USE_AC97_LAYER */
 
 static int
 snd_azf3328_hw_params(struct snd_pcm_substream *substream,
@@ -1233,8 +1571,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 			/* mute WaveOut (avoid clicking during setup) */
 			previously_muted =
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 1
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 1
 				);
 		}
 
@@ -1290,8 +1628,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 			/* now unmute WaveOut */
 			if (!previously_muted)
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 0
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 0
 				);
 		}
 
@@ -1315,8 +1653,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 			/* mute WaveOut (avoid clicking during setup) */
 			previously_muted =
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 1
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 1
 				);
 		}
 
@@ -1341,8 +1679,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 			/* now unmute WaveOut */
 			if (!previously_muted)
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 0
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 0
 				);
 		}
 
@@ -2050,11 +2388,7 @@ snd_azf3328_free(struct snd_azf3328 *chip)
 	if (chip->irq < 0)
 		goto __end_hw;
 
-	/* reset (close) mixer:
-	 * first mute master volume, then reset
-	 */
-	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
-	snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
+	snd_azf3328_mixer_reset(chip);
 
 	snd_azf3328_timer_stop(chip->timer);
 	snd_azf3328_gameport_free(chip);
@@ -2407,6 +2741,55 @@ snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs)
 	}
 }
 
+static inline void
+snd_azf3328_resume_regs(const u32 *saved_regs,
+			unsigned long io_addr,
+			unsigned count
+)
+{
+	unsigned reg;
+
+	for (reg = 0; reg < count; ++reg) {
+		outl(*saved_regs, io_addr);
+		snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n",
+			io_addr, *saved_regs, inl(io_addr));
+		++saved_regs;
+		io_addr += sizeof(*saved_regs);
+	}
+}
+
+static inline void
+snd_azf3328_suspend_ac97(struct snd_azf3328 *chip)
+{
+#ifdef AZF_USE_AC97_LAYER
+	snd_ac97_suspend(chip->ac97);
+#else
+	snd_azf3328_suspend_regs(chip->mixer_io,
+		ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer);
+
+	/* make sure to disable master volume etc. to prevent looping sound */
+	snd_azf3328_mixer_mute_control_master(chip, 1);
+	snd_azf3328_mixer_mute_control_pcm(chip, 1);
+#endif /* AZF_USE_AC97_LAYER */
+}
+
+static inline void
+snd_azf3328_resume_ac97(const struct snd_azf3328 *chip)
+{
+#ifdef AZF_USE_AC97_LAYER
+	snd_ac97_resume(chip->ac97);
+#else
+	snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io,
+					ARRAY_SIZE(chip->saved_regs_mixer));
+
+	/* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02)
+	   and IDX_MIXER_RESET (offset 0x00) get touched at the same time,
+	   resulting in a mixer reset condition persisting until _after_
+	   master vol was restored. Thus master vol needs an extra restore. */
+	outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2);
+#endif /* AZF_USE_AC97_LAYER */
+}
+
 static int
 snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 {
@@ -2420,12 +2803,7 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 	snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
 	snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
 
-	snd_azf3328_suspend_regs(chip->mixer_io,
-		ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer);
-
-	/* make sure to disable master volume etc. to prevent looping sound */
-	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
-	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+	snd_azf3328_suspend_ac97(chip);
 
 	snd_azf3328_suspend_regs(chip->ctrl_io,
 		ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl);
@@ -2447,23 +2825,6 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 	return 0;
 }
 
-static inline void
-snd_azf3328_resume_regs(const u32 *saved_regs,
-			unsigned long io_addr,
-			unsigned count
-)
-{
-	unsigned reg;
-
-	for (reg = 0; reg < count; ++reg) {
-		outl(*saved_regs, io_addr);
-		snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n",
-			io_addr, *saved_regs, inl(io_addr));
-		++saved_regs;
-		io_addr += sizeof(*saved_regs);
-	}
-}
-
 static int
 snd_azf3328_resume(struct pci_dev *pci)
 {
@@ -2487,14 +2848,7 @@ snd_azf3328_resume(struct pci_dev *pci)
 	snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io,
 					ARRAY_SIZE(chip->saved_regs_opl3));
 
-	snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io,
-					ARRAY_SIZE(chip->saved_regs_mixer));
-
-	/* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02)
-	   and IDX_MIXER_RESET (offset 0x00) get touched at the same time,
-	   resulting in a mixer reset condition persisting until _after_
-	   master vol was restored. Thus master vol needs an extra restore. */
-	outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2);
+	snd_azf3328_resume_ac97(chip);
 
 	snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io,
 					ARRAY_SIZE(chip->saved_regs_ctrl));
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index 1bff80c..b932154 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -869,7 +869,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 	mutex_lock(&atc->atc_mutex);
 	dao->ops->get_spos(dao, &status);
 	if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
-		status &= ((~IEC958_AES3_CON_FS) << 24);
+		status &= ~(IEC958_AES3_CON_FS << 24);
 		status |= (iec958_con_fs << 24);
 		dao->ops->set_spos(dao, status);
 		dao->ops->commit_write(dao);
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index af56eb9..47d9ea9 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -176,6 +176,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input)
 	if (!entry)
 		return -ENOMEM;
 
+	dao->ops->clear_left_input(dao);
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	daio->rscl.ops->master(&daio->rscl);
@@ -204,6 +205,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input)
 	if (!entry)
 		return -ENOMEM;
 
+	dao->ops->clear_right_input(dao);
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	daio->rscr.ops->master(&daio->rscr);
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c
index b6b11bf..5364164 100644
--- a/sound/pci/ctxfi/cthw20k2.c
+++ b/sound/pci/ctxfi/cthw20k2.c
@@ -1307,10 +1307,10 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr)
 	set_field(&pllctl, PLLCTL_B, 0);
 	if (48000 == rsr) {
 		set_field(&pllctl, PLLCTL_FD, 16 - 2);
-		set_field(&pllctl, PLLCTL_RD, 1 - 1);
+		set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */
 	} else { /* 44100 */
 		set_field(&pllctl, PLLCTL_FD, 147 - 2);
-		set_field(&pllctl, PLLCTL_RD, 10 - 1);
+		set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */
 	}
 	hw_write_20kx(hw, PLL_CTL, pllctl);
 	mdelay(40);
@@ -1740,6 +1740,10 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
 	return data;
 }
 
+#define MIC_BOOST_0DB 0xCF
+#define MIC_BOOST_STEPS_PER_DB 2
+#define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB)
+
 static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 {
 	u32 data;
@@ -1751,10 +1755,12 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 		hw_write_20kx(hw, GPIO_DATA, data);
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
 				MAKE_WM8775_DATA(0x101)); /* Mic-in */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
 		break;
 	case ADC_LINEIN:
 		data &= ~(0x1 << 14);
@@ -1827,10 +1833,12 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
 
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
 				MAKE_WM8775_DATA(0x101)); /* Mic-in */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
 	} else if (mux == 2) {
 		/* Configures GPIO data to select Line-in */
 		data &= ~(0x1 << 14);
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index 15c1e72..c3519ff 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -566,19 +566,6 @@ static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
-
-	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
-	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
-	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
-	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
-
-	return 0;
-}
-
 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 {
@@ -586,6 +573,10 @@ static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 	unsigned int status;
 
 	atc->spdif_out_get_status(atc, &status);
+
+	if (status == 0)
+		status = SNDRV_PCM_DEFAULT_CON_SPDIF;
+
 	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
@@ -629,7 +620,7 @@ static struct snd_kcontrol_new iec958_default_ctl = {
 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 	.count		= 1,
 	.info		= ct_spdif_info,
-	.get		= ct_spdif_default_get,
+	.get		= ct_spdif_get,
 	.put		= ct_spdif_put,
 	.private_value	= MIXER_IEC958_DEFAULT
 };
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c
index 65da6e4..b78f3fc 100644
--- a/sound/pci/ctxfi/ctvmem.c
+++ b/sound/pci/ctxfi/ctvmem.c
@@ -52,8 +52,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
 
 	if (entry->size == size) {
 		/* Move the vm node from unused list to used list directly */
-		list_del(&entry->list);
-		list_add(&entry->list, &vm->used);
+		list_move(&entry->list, &vm->used);
 		vm->size -= size;
 		block = entry;
 		goto out;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 66c7fb3..5e619a8 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -926,7 +926,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
 	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19);
 	/* Unknown. */
 	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c);
-	/* IRQ Enable: Alll on */
+	/* IRQ Enable: All on */
 	/* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
 	/* IRQ Enable: All off */
 	snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index ae5c5d5e..2c79e96 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -29,6 +29,7 @@
 #include <sound/asoundef.h>
 #include <sound/tlv.h>
 #include <sound/initval.h>
+#include <sound/jack.h>
 #include "hda_local.h"
 #include "hda_beep.h"
 #include <sound/hda_hwdep.h>
@@ -4959,5 +4960,109 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
 }
 EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
 
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+/*
+ * Input-jack notification support
+ */
+struct hda_jack_item {
+	hda_nid_t nid;
+	int type;
+	struct snd_jack *jack;
+};
+
+static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid,
+					 int type)
+{
+	switch (type) {
+	case SND_JACK_HEADPHONE:
+		return "Headphone";
+	case SND_JACK_MICROPHONE:
+		return "Mic";
+	case SND_JACK_LINEOUT:
+		return "Line-out";
+	case SND_JACK_HEADSET:
+		return "Headset";
+	default:
+		return "Misc";
+	}
+}
+
+static void hda_free_jack_priv(struct snd_jack *jack)
+{
+	struct hda_jack_item *jacks = jack->private_data;
+	jacks->nid = 0;
+	jacks->jack = NULL;
+}
+
+int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
+			   const char *name)
+{
+	struct hda_jack_item *jack;
+	int err;
+
+	snd_array_init(&codec->jacks, sizeof(*jack), 32);
+	jack = snd_array_new(&codec->jacks);
+	if (!jack)
+		return -ENOMEM;
+
+	jack->nid = nid;
+	jack->type = type;
+	if (!name)
+		name = get_jack_default_name(codec, nid, type);
+	err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
+	if (err < 0) {
+		jack->nid = 0;
+		return err;
+	}
+	jack->jack->private_data = jack;
+	jack->jack->private_free = hda_free_jack_priv;
+	return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);
+
+void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct hda_jack_item *jacks = codec->jacks.list;
+	int i;
+
+	if (!jacks)
+		return;
+
+	for (i = 0; i < codec->jacks.used; i++, jacks++) {
+		unsigned int pin_ctl;
+		unsigned int present;
+		int type;
+
+		if (jacks->nid != nid)
+			continue;
+		present = snd_hda_jack_detect(codec, nid);
+		type = jacks->type;
+		if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) {
+			pin_ctl = snd_hda_codec_read(codec, nid, 0,
+					     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+			type = (pin_ctl & AC_PINCTL_HP_EN) ?
+				SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
+		}
+		snd_jack_report(jacks->jack, present ? type : 0);
+	}
+}
+EXPORT_SYMBOL_HDA(snd_hda_input_jack_report);
+
+/* free jack instances manually when clearing/reconfiguring */
+void snd_hda_input_jack_free(struct hda_codec *codec)
+{
+	if (!codec->bus->shutdown && codec->jacks.list) {
+		struct hda_jack_item *jacks = codec->jacks.list;
+		int i;
+		for (i = 0; i < codec->jacks.used; i++, jacks++) {
+			if (jacks->jack)
+				snd_device_free(codec->bus->card, jacks->jack);
+		}
+	}
+	snd_array_free(&codec->jacks);
+}
+EXPORT_SYMBOL_HDA(snd_hda_input_jack_free);
+#endif /* CONFIG_SND_HDA_INPUT_JACK */
+
 MODULE_DESCRIPTION("HDA codec core");
 MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index fdf8d44..e46d542 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -866,6 +866,11 @@ struct hda_codec {
 	/* codec-specific additional proc output */
 	void (*proc_widget_hook)(struct snd_info_buffer *buffer,
 				 struct hda_codec *codec, hda_nid_t nid);
+
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+	/* jack detection */
+	struct snd_array jacks;
+#endif
 };
 
 /* direction */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index fcedad9..70a9d32 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1052,9 +1052,12 @@ static void azx_init_pci(struct azx *chip)
 	/* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
 	 * TCSEL == Traffic Class Select Register, which sets PCI express QOS
 	 * Ensuring these bits are 0 clears playback static on some HD Audio
-	 * codecs
+	 * codecs.
+	 * The PCI register TCSEL is defined in the Intel manuals.
 	 */
-	update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
+	if (chip->driver_type != AZX_DRIVER_ATI &&
+	    chip->driver_type != AZX_DRIVER_ATIHDMI)
+		update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
 
 	switch (chip->driver_type) {
 	case AZX_DRIVER_ATI:
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 3ab5e7a..ff5e2ac 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -656,4 +656,28 @@ static inline void snd_hda_eld_proc_free(struct hda_codec *codec,
 #define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
 
+/*
+ * Input-jack notification support
+ */
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
+			   const char *name);
+void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid);
+void snd_hda_input_jack_free(struct hda_codec *codec);
+#else /* CONFIG_SND_HDA_INPUT_JACK */
+static inline int snd_hda_input_jack_add(struct hda_codec *codec,
+					 hda_nid_t nid, int type,
+					 const char *name)
+{
+	return 0;
+}
+static inline void snd_hda_input_jack_report(struct hda_codec *codec,
+					     hda_nid_t nid)
+{
+}
+static inline void snd_hda_input_jack_free(struct hda_codec *codec)
+{
+}
+#endif /* CONFIG_SND_HDA_INPUT_JACK */
+
 #endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 8dabab7..734c6ee 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -30,10 +30,10 @@
 #include "hda_beep.h"
 
 struct ad198x_spec {
-	struct snd_kcontrol_new *mixers[5];
+	struct snd_kcontrol_new *mixers[6];
 	int num_mixers;
 	unsigned int beep_amp;	/* beep amp value, set via set_beep_amp() */
-	const struct hda_verb *init_verbs[5];	/* initialization verbs
+	const struct hda_verb *init_verbs[6];	/* initialization verbs
 						 * don't forget NULL termination!
 						 */
 	unsigned int num_init_verbs;
@@ -331,36 +331,11 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
 	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
 }
 
-static int ad198x_alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-				struct hda_codec *codec,
-				unsigned int stream_tag,
-				unsigned int format,
-				struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->alt_dac_nid[0], stream_tag,
-					0, format);
-	return 0;
-}
-
-static int ad198x_alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				struct hda_codec *codec,
-				struct snd_pcm_substream *substream)
-{
-	struct ad198x_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->alt_dac_nid[0]);
-	return 0;
-}
-
 static struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
 	/* NID is set in ad198x_build_pcms */
-	.ops = {
-		.prepare = ad198x_alt_playback_pcm_prepare,
-		.cleanup = ad198x_alt_playback_pcm_cleanup
-	},
 };
 
 /*
@@ -2239,29 +2214,6 @@ static struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
 static struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
 
-	HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x27, 2, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x28, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Headphone Playback Switch", 0x22, 2, HDA_INPUT),
-	HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x6, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x4, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Analog Mix Playback Volume", 0x21, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Analog Mix Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
-	HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
-
 	{ } /* end */
 };
 
@@ -2545,11 +2497,6 @@ static struct hda_verb ad1988_6stack_init_verbs[] = {
 };
 
 static struct hda_verb ad1988_6stack_fp_init_verbs[] = {
-	/* Front, Surround, CLFE, side DAC; unmute as default */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* Headphone; unmute as default */
 	{0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* Port-A front headphon path */
@@ -2558,50 +2505,6 @@ static struct hda_verb ad1988_6stack_fp_init_verbs[] = {
 	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	/* Port-D line-out path */
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-F surround path */
-	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x2a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-G CLFE path */
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Port-H side path */
-	{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x28, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	/* Mono out path */
-	{0x36, AC_VERB_SET_CONNECT_SEL, 0x1}, /* DAC1:04h */
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb01f}, /* unmute, 0dB */
-	/* Port-B front mic-in path */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	/* Port-C line-in path */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x33, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Port-E mic-in path */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-	{0x34, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* Analog CD Input */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	/* Analog Mix output amp */
-	{0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */
 
 	{ }
 };
@@ -3316,20 +3219,20 @@ static int patch_ad1988(struct hda_codec *codec)
 			spec->mixers[0] = ad1988_6stack_mixers1_rev2;
 		else
 			spec->mixers[0] = ad1988_6stack_mixers1;
+		spec->mixers[1] = ad1988_6stack_mixers2;
+		spec->num_init_verbs = 1;
+		spec->init_verbs[0] = ad1988_6stack_init_verbs;
 		if (board_config == AD1988_6STACK_DIG_FP) {
-			spec->mixers[1] = ad1988_6stack_fp_mixers;
+			spec->num_mixers++;
+			spec->mixers[2] = ad1988_6stack_fp_mixers;
+			spec->num_init_verbs++;
+			spec->init_verbs[1] = ad1988_6stack_fp_init_verbs;
 			spec->slave_vols = ad1988_6stack_fp_slave_vols;
 			spec->slave_sws = ad1988_6stack_fp_slave_sws;
 			spec->alt_dac_nid = ad1988_alt_dac_nid;
 			spec->stream_analog_alt_playback =
 				&ad198x_pcm_analog_alt_playback;
-		} else
-			spec->mixers[1] = ad1988_6stack_mixers2;
-		spec->num_init_verbs = 1;
-		if (board_config == AD1988_6STACK_DIG_FP)
-			spec->init_verbs[0] = ad1988_6stack_fp_init_verbs;
-		else
-			spec->init_verbs[0] = ad1988_6stack_init_verbs;
+		}
 		if ((board_config == AD1988_6STACK_DIG) ||
 			(board_config == AD1988_6STACK_DIG_FP)) {
 			spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 4d5004e..d08cf31 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -49,14 +49,6 @@
 #define AUTO_MIC_PORTB		(1 << 1)
 #define AUTO_MIC_PORTC		(1 << 2)
 
-struct conexant_jack {
-
-	hda_nid_t nid;
-	int type;
-	struct snd_jack *jack;
-
-};
-
 struct pin_dac_pair {
 	hda_nid_t pin;
 	hda_nid_t dac;
@@ -111,9 +103,6 @@ struct conexant_spec {
 
 	unsigned int spdif_route;
 
-	/* jack detection */
-	struct snd_array jacks;
-
 	/* dynamic controls, init_verbs and input_mux */
 	struct auto_pin_cfg autocfg;
 	struct hda_input_mux private_imux;
@@ -393,71 +382,9 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
 				     &spec->cur_mux[adc_idx]);
 }
 
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-static void conexant_free_jack_priv(struct snd_jack *jack)
-{
-	struct conexant_jack *jacks = jack->private_data;
-	jacks->nid = 0;
-	jacks->jack = NULL;
-}
-
-static int conexant_add_jack(struct hda_codec *codec,
-		hda_nid_t nid, int type)
-{
-	struct conexant_spec *spec;
-	struct conexant_jack *jack;
-	const char *name;
-	int i, err;
-
-	spec = codec->spec;
-	snd_array_init(&spec->jacks, sizeof(*jack), 32);
-
-	jack = spec->jacks.list;
-	for (i = 0; i < spec->jacks.used; i++, jack++)
-		if (jack->nid == nid)
-			return 0 ; /* already present */
-
-	jack = snd_array_new(&spec->jacks);
-	name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
-
-	if (!jack)
-		return -ENOMEM;
-
-	jack->nid = nid;
-	jack->type = type;
-
-	err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
-	if (err < 0)
-		return err;
-	jack->jack->private_data = jack;
-	jack->jack->private_free = conexant_free_jack_priv;
-	return 0;
-}
-
-static void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct conexant_spec *spec = codec->spec;
-	struct conexant_jack *jacks = spec->jacks.list;
-
-	if (jacks) {
-		int i;
-		for (i = 0; i < spec->jacks.used; i++) {
-			if (jacks->nid == nid) {
-				unsigned int present;
-				present = snd_hda_jack_detect(codec, nid);
-
-				present = (present) ? jacks->type : 0 ;
-
-				snd_jack_report(jacks->jack,
-						present);
-			}
-			jacks++;
-		}
-	}
-}
-
 static int conexant_init_jacks(struct hda_codec *codec)
 {
+#ifdef CONFIG_SND_HDA_INPUT_JACK
 	struct conexant_spec *spec = codec->spec;
 	int i;
 
@@ -469,15 +396,15 @@ static int conexant_init_jacks(struct hda_codec *codec)
 			int err = 0;
 			switch (hv->param ^ AC_USRSP_EN) {
 			case CONEXANT_HP_EVENT:
-				err = conexant_add_jack(codec, hv->nid,
-						SND_JACK_HEADPHONE);
-				conexant_report_jack(codec, hv->nid);
+				err = snd_hda_input_jack_add(codec, hv->nid,
+						SND_JACK_HEADPHONE, NULL);
+				snd_hda_input_jack_report(codec, hv->nid);
 				break;
 			case CXT5051_PORTC_EVENT:
 			case CONEXANT_MIC_EVENT:
-				err = conexant_add_jack(codec, hv->nid,
-						SND_JACK_MICROPHONE);
-				conexant_report_jack(codec, hv->nid);
+				err = snd_hda_input_jack_add(codec, hv->nid,
+						SND_JACK_MICROPHONE, NULL);
+				snd_hda_input_jack_report(codec, hv->nid);
 				break;
 			}
 			if (err < 0)
@@ -485,19 +412,9 @@ static int conexant_init_jacks(struct hda_codec *codec)
 			++hv;
 		}
 	}
-	return 0;
-
-}
-#else
-static inline void conexant_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
-}
-
-static inline int conexant_init_jacks(struct hda_codec *codec)
-{
+#endif /* CONFIG_SND_HDA_INPUT_JACK */
 	return 0;
 }
-#endif
 
 static int conexant_init(struct hda_codec *codec)
 {
@@ -511,18 +428,7 @@ static int conexant_init(struct hda_codec *codec)
 
 static void conexant_free(struct hda_codec *codec)
 {
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-	struct conexant_spec *spec = codec->spec;
-	if (spec->jacks.list) {
-		struct conexant_jack *jacks = spec->jacks.list;
-		int i;
-		for (i = 0; i < spec->jacks.used; i++, jacks++) {
-			if (jacks->jack)
-				snd_device_free(codec->bus->card, jacks->jack);
-		}
-		snd_array_free(&spec->jacks);
-	}
-#endif
+	snd_hda_input_jack_free(codec);
 	snd_hda_detach_beep_device(codec);
 	kfree(codec->spec);
 }
@@ -1787,7 +1693,7 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
 		cxt5051_portc_automic(codec);
 		break;
 	}
-	conexant_report_jack(codec, nid);
+	snd_hda_input_jack_report(codec, nid);
 }
 
 static struct snd_kcontrol_new cxt5051_playback_mixers[] = {
@@ -1959,10 +1865,8 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
 	snd_hda_codec_write(codec, nid, 0,
 			    AC_VERB_SET_UNSOLICITED_ENABLE,
 			    AC_USRSP_EN | event);
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-	conexant_add_jack(codec, nid, SND_JACK_MICROPHONE);
-	conexant_report_jack(codec, nid);
-#endif
+	snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL);
+	snd_hda_input_jack_report(codec, nid);
 }
 
 static struct hda_verb cxt5051_ideapad_init_verbs[] = {
@@ -3477,11 +3381,11 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
 	switch (res >> 26) {
 	case CONEXANT_HP_EVENT:
 		cx_auto_hp_automute(codec);
-		conexant_report_jack(codec, nid);
+		snd_hda_input_jack_report(codec, nid);
 		break;
 	case CONEXANT_MIC_EVENT:
 		cx_auto_automic(codec);
-		conexant_report_jack(codec, nid);
+		snd_hda_input_jack_report(codec, nid);
 		break;
 	}
 }
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index ec0fa2d..251773e 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -110,6 +110,12 @@ struct dp_audio_infoframe {
 	u8 LFEPBL01_LSV36_DM_INH7;
 };
 
+union audio_infoframe {
+	struct hdmi_audio_infoframe hdmi;
+	struct dp_audio_infoframe dp;
+	u8 bytes[0];
+};
+
 /*
  * CEA speaker placement:
  *
@@ -620,8 +626,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
 	int channels = substream->runtime->channels;
 	int ca;
 	int i;
-	u8 ai[max(sizeof(struct hdmi_audio_infoframe),
-		  sizeof(struct dp_audio_infoframe))];
+	union audio_infoframe ai;
 
 	ca = hdmi_channel_allocation(codec, nid, channels);
 
@@ -633,11 +638,10 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
 
 		pin_nid = spec->pin[i];
 
-		memset(ai, 0, sizeof(ai));
+		memset(&ai, 0, sizeof(ai));
 		if (spec->sink_eld[i].conn_type == 0) { /* HDMI */
-			struct hdmi_audio_infoframe *hdmi_ai;
+			struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi;
 
-			hdmi_ai = (struct hdmi_audio_infoframe *)ai;
 			hdmi_ai->type		= 0x84;
 			hdmi_ai->ver		= 0x01;
 			hdmi_ai->len		= 0x0a;
@@ -645,9 +649,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
 			hdmi_ai->CA		= ca;
 			hdmi_checksum_audio_infoframe(hdmi_ai);
 		} else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */
-			struct dp_audio_infoframe *dp_ai;
+			struct dp_audio_infoframe *dp_ai = &ai.dp;
 
-			dp_ai = (struct dp_audio_infoframe *)ai;
 			dp_ai->type		= 0x84;
 			dp_ai->len		= 0x1b;
 			dp_ai->ver		= 0x11 << 2;
@@ -664,7 +667,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
 		 * sizeof(*dp_ai) to avoid partial match/update problems when
 		 * the user switches between HDMI/DP monitors.
 		 */
-		if (!hdmi_infoframe_uptodate(codec, pin_nid, ai, sizeof(ai))) {
+		if (!hdmi_infoframe_uptodate(codec, pin_nid, ai.bytes,
+					     sizeof(ai))) {
 			snd_printdd("hdmi_setup_audio_infoframe: "
 				    "cvt=%d pin=%d channels=%d\n",
 				    nid, pin_nid,
@@ -672,7 +676,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
 			hdmi_setup_channel_mapping(codec, pin_nid, ca);
 			hdmi_stop_infoframe_trans(codec, pin_nid);
 			hdmi_fill_audio_infoframe(codec, pin_nid,
-						  ai, sizeof(ai));
+						  ai.bytes, sizeof(ai));
 			hdmi_start_infoframe_trans(codec, pin_nid);
 		}
 	}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4261bb8..5d582de 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -282,12 +282,6 @@ struct alc_mic_route {
 	unsigned char amix_idx;
 };
 
-struct alc_jack {
-	hda_nid_t nid;
-	int type;
-	struct snd_jack *jack;
-};
-
 #define MUX_IDX_UNDEF	((unsigned char)-1)
 
 struct alc_customize_define {
@@ -366,9 +360,6 @@ struct alc_spec {
 	/* PCM information */
 	struct hda_pcm pcm_rec[3];	/* used in alc_build_pcms() */
 
-	/* jack detection */
-	struct snd_array jacks;
-
 	/* dynamic controls, init_verbs and input_mux */
 	struct auto_pin_cfg autocfg;
 	struct alc_customize_define cdefine;
@@ -394,6 +385,7 @@ struct alc_spec {
 	/* other flags */
 	unsigned int no_analog :1; /* digital I/O only */
 	unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
+	unsigned int single_input_src:1;
 	int init_amp;
 	int codec_variant;	/* flag for other variants */
 
@@ -1032,94 +1024,32 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
 	alc_fix_pll(codec);
 }
 
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-static void alc_free_jack_priv(struct snd_jack *jack)
-{
-	struct alc_jack *jacks = jack->private_data;
-	jacks->nid = 0;
-	jacks->jack = NULL;
-}
-
-static int alc_add_jack(struct hda_codec *codec,
-		hda_nid_t nid, int type)
-{
-	struct alc_spec *spec;
-	struct alc_jack *jack;
-	const char *name;
-	int err;
-
-	spec = codec->spec;
-	snd_array_init(&spec->jacks, sizeof(*jack), 32);
-	jack = snd_array_new(&spec->jacks);
-	if (!jack)
-		return -ENOMEM;
-
-	jack->nid = nid;
-	jack->type = type;
-	name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
-
-	err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
-	if (err < 0)
-		return err;
-	jack->jack->private_data = jack;
-	jack->jack->private_free = alc_free_jack_priv;
-	return 0;
-}
-
-static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct alc_spec *spec = codec->spec;
-	struct alc_jack *jacks = spec->jacks.list;
-
-	if (jacks) {
-		int i;
-		for (i = 0; i < spec->jacks.used; i++) {
-			if (jacks->nid == nid) {
-				unsigned int present;
-				present = snd_hda_jack_detect(codec, nid);
-
-				present = (present) ? jacks->type : 0;
-
-				snd_jack_report(jacks->jack, present);
-			}
-			jacks++;
-		}
-	}
-}
-
 static int alc_init_jacks(struct hda_codec *codec)
 {
+#ifdef CONFIG_SND_HDA_INPUT_JACK
 	struct alc_spec *spec = codec->spec;
 	int err;
 	unsigned int hp_nid = spec->autocfg.hp_pins[0];
 	unsigned int mic_nid = spec->ext_mic.pin;
 
 	if (hp_nid) {
-		err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE);
+		err = snd_hda_input_jack_add(codec, hp_nid,
+					     SND_JACK_HEADPHONE, NULL);
 		if (err < 0)
 			return err;
-		alc_report_jack(codec, hp_nid);
+		snd_hda_input_jack_report(codec, hp_nid);
 	}
 
 	if (mic_nid) {
-		err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE);
+		err = snd_hda_input_jack_add(codec, mic_nid,
+					     SND_JACK_MICROPHONE, NULL);
 		if (err < 0)
 			return err;
-		alc_report_jack(codec, mic_nid);
+		snd_hda_input_jack_report(codec, mic_nid);
 	}
-
-	return 0;
-}
-#else
-static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
-}
-
-static inline int alc_init_jacks(struct hda_codec *codec)
-{
+#endif /* CONFIG_SND_HDA_INPUT_JACK */
 	return 0;
 }
-#endif
 
 static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
 {
@@ -1133,7 +1063,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
 		nid = spec->autocfg.hp_pins[i];
 		if (!nid)
 			break;
-		alc_report_jack(codec, nid);
+		snd_hda_input_jack_report(codec, nid);
 		spec->jack_present |= snd_hda_jack_detect(codec, nid);
 	}
 
@@ -1240,7 +1170,7 @@ static void alc_mic_automute(struct hda_codec *codec)
 					  AC_VERB_SET_CONNECT_SEL,
 					  alive->mux_idx);
 	}
-	alc_report_jack(codec, spec->ext_mic.pin);
+	snd_hda_input_jack_report(codec, spec->ext_mic.pin);
 
 	/* FIXME: analog mixer */
 }
@@ -1335,6 +1265,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
 		case 0x10ec0660:
 		case 0x10ec0662:
 		case 0x10ec0663:
+		case 0x10ec0665:
 		case 0x10ec0862:
 		case 0x10ec0889:
 			set_eapd(codec, 0x14, 1);
@@ -2292,13 +2223,13 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0f, 2, 0x0,
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
 		HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0f, 2, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
-	HDA_BIND_MUTE("Side Playback Switch", 0x0e, 2, HDA_INPUT),
+	HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
+	HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -2309,7 +2240,6 @@ static struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
 	{ } /* end */
 };
 
-
 static struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
@@ -3919,6 +3849,8 @@ static struct hda_amp_list alc880_lg_loopbacks[] = {
  * Common callbacks
  */
 
+static void alc_init_special_input_src(struct hda_codec *codec);
+
 static int alc_init(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -3929,6 +3861,7 @@ static int alc_init(struct hda_codec *codec)
 
 	for (i = 0; i < spec->num_init_verbs; i++)
 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
+	alc_init_special_input_src(codec);
 
 	if (spec->init_hook)
 		spec->init_hook(codec);
@@ -4284,6 +4217,7 @@ static void alc_free(struct hda_codec *codec)
 		return;
 
 	alc_shutup(codec);
+	snd_hda_input_jack_free(codec);
 	alc_free_kctls(codec);
 	kfree(spec);
 	snd_hda_detach_beep_device(codec);
@@ -4307,6 +4241,7 @@ static void alc_power_eapd(struct hda_codec *codec)
 	case 0x10ec0660:
 	case 0x10ec0662:
 	case 0x10ec0663:
+	case 0x10ec0665:
 	case 0x10ec0862:
 	case 0x10ec0889:
 		set_eapd(codec, 0x14, 0);
@@ -4702,7 +4637,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
 	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
-	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
+	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
 	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
 	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
 	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
@@ -5151,7 +5086,9 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
 
 	switch (cfg->line_out_type) {
 	case AUTO_PIN_SPEAKER_OUT:
-		return "Speaker";
+		if (cfg->line_outs == 1)
+			return "Speaker";
+		break;
 	case AUTO_PIN_HP_OUT:
 		return "Headphone";
 	default:
@@ -5205,16 +5142,19 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
+				index = 0;
+			}
 			err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-						name, i,
+						name, index,
 					  HDA_COMPOSE_AMP_VAL(nid, 3, 0,
 							      HDA_OUTPUT));
 			if (err < 0)
 				return err;
 			err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					       name, i,
+					       name, index,
 					  HDA_COMPOSE_AMP_VAL(nid, 3, 2,
 							      HDA_INPUT));
 			if (err < 0)
@@ -5585,6 +5525,7 @@ static void fixup_single_adc(struct hda_codec *codec)
 			spec->capsrc_nids += i;
 		spec->adc_nids += i;
 		spec->num_adc_nids = 1;
+		spec->single_input_src = 1;
 	}
 }
 
@@ -5596,6 +5537,16 @@ static void fixup_dual_adc_switch(struct hda_codec *codec)
 	init_capsrc_for_pin(codec, spec->int_mic.pin);
 }
 
+/* initialize some special cases for input sources */
+static void alc_init_special_input_src(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	if (spec->dual_adc_switch)
+		fixup_dual_adc_switch(codec);
+	else if (spec->single_input_src)
+		init_capsrc_for_pin(codec, spec->autocfg.inputs[0].pin);
+}
+
 static void set_capture_mixer(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -5611,7 +5562,7 @@ static void set_capture_mixer(struct hda_codec *codec)
 		int mux = 0;
 		int num_adcs = spec->num_adc_nids;
 		if (spec->dual_adc_switch)
-			fixup_dual_adc_switch(codec);
+			num_adcs = 1;
 		else if (spec->auto_mic)
 			fixup_automic_adc(codec);
 		else if (spec->input_mux) {
@@ -5620,8 +5571,6 @@ static void set_capture_mixer(struct hda_codec *codec)
 			else if (spec->input_mux->num_items == 1)
 				fixup_single_adc(codec);
 		}
-		if (spec->dual_adc_switch)
-			num_adcs = 1;
 		spec->cap_mixer = caps[mux][num_adcs - 1];
 	}
 }
@@ -10748,6 +10697,7 @@ static struct alc_config_preset alc882_presets[] = {
  */
 enum {
 	PINFIX_ABIT_AW9D_MAX,
+	PINFIX_LENOVO_Y530,
 	PINFIX_PB_M5210,
 	PINFIX_ACER_ASPIRE_7736,
 };
@@ -10762,6 +10712,14 @@ static const struct alc_fixup alc882_fixups[] = {
 			{ }
 		}
 	},
+	[PINFIX_LENOVO_Y530] = {
+		.type = ALC_FIXUP_PINS,
+		.v.pins = (const struct alc_pincfg[]) {
+			{ 0x15, 0x99130112 }, /* rear int speakers */
+			{ 0x16, 0x99130111 }, /* subwoofer */
+			{ }
+		}
+	},
 	[PINFIX_PB_M5210] = {
 		.type = ALC_FIXUP_VERBS,
 		.v.verbs = (const struct hda_verb[]) {
@@ -10777,6 +10735,7 @@ static const struct alc_fixup alc882_fixups[] = {
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
+	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
 	SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
 	SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
 	{}
@@ -10829,23 +10788,28 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
 	hda_nid_t pin, dac;
 	int i;
 
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
-		pin = spec->autocfg.hp_pins[i];
-		if (!pin)
-			break;
-		dac = spec->multiout.hp_nid;
-		if (!dac)
-			dac = spec->multiout.dac_nids[0]; /* to front */
-		alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT) {
+		for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
+			pin = spec->autocfg.hp_pins[i];
+			if (!pin)
+				break;
+			dac = spec->multiout.hp_nid;
+			if (!dac)
+				dac = spec->multiout.dac_nids[0]; /* to front */
+			alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
+		}
 	}
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
-		pin = spec->autocfg.speaker_pins[i];
-		if (!pin)
-			break;
-		dac = spec->multiout.extra_out_nid[0];
-		if (!dac)
-			dac = spec->multiout.dac_nids[0]; /* to front */
-		alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+
+	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT) {
+		for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
+			pin = spec->autocfg.speaker_pins[i];
+			if (!pin)
+				break;
+			dac = spec->multiout.extra_out_nid[0];
+			if (!dac)
+				dac = spec->multiout.dac_nids[0]; /* to front */
+			alc882_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
+		}
 	}
 }
 
@@ -13796,6 +13760,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
 }
 
 #define alc268_auto_init_analog_input	alc882_auto_init_analog_input
+#define alc268_auto_init_input_src	alc882_auto_init_input_src
 
 /* init callback for auto-configuration model -- overriding the default init */
 static void alc268_auto_init(struct hda_codec *codec)
@@ -13805,6 +13770,7 @@ static void alc268_auto_init(struct hda_codec *codec)
 	alc268_auto_init_hp_out(codec);
 	alc268_auto_init_mono_speaker_out(codec);
 	alc268_auto_init_analog_input(codec);
+	alc268_auto_init_input_src(codec);
 	alc_auto_init_digital(codec);
 	if (spec->unsol_event)
 		alc_inithook(codec);
@@ -14092,7 +14058,6 @@ static int patch_alc268(struct hda_codec *codec)
 	if (!spec->no_analog && !spec->adc_nids && spec->input_mux) {
 		/* check whether NID 0x07 is valid */
 		unsigned int wcap = get_wcaps(codec, 0x07);
-		int i;
 
 		spec->capsrc_nids = alc268_capsrc_nids;
 		/* get type */
@@ -14112,13 +14077,6 @@ static int patch_alc268(struct hda_codec *codec)
 			spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
 			add_mixer(spec, alc268_capture_mixer);
 		}
-		/* set default input source */
-		for (i = 0; i < spec->num_adc_nids; i++)
-			snd_hda_codec_write_cache(codec, alc268_capsrc_nids[i],
-				0, AC_VERB_SET_CONNECT_SEL,
-				i < spec->num_mux_defs ?
-				spec->input_mux[i].items[0].index :
-				spec->input_mux->items[0].index);
 	}
 
 	spec->vmaster_nid = 0x02;
@@ -14495,7 +14453,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
 				 HDA_AMP_MUTE, bits);
 	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
 				 HDA_AMP_MUTE, bits);
-	alc_report_jack(codec, nid);
+	snd_hda_input_jack_report(codec, nid);
 }
 
 /* unsolicited event for HP jack sensing */
@@ -14807,11 +14765,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
 		fillup_priv_adc_nids(codec, alc269_adc_candidates,
 				     sizeof(alc269_adc_candidates));
 
-	/* set default input source */
-	if (!spec->dual_adc_switch)
-		select_or_unmute_capsrc(codec, spec->capsrc_nids[0],
-					spec->input_mux->items[0].index);
-
 	err = alc_auto_add_mic_boost(codec);
 	if (err < 0)
 		return err;
@@ -14825,6 +14778,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
 #define alc269_auto_init_multi_out	alc268_auto_init_multi_out
 #define alc269_auto_init_hp_out		alc268_auto_init_hp_out
 #define alc269_auto_init_analog_input	alc882_auto_init_analog_input
+#define alc269_auto_init_input_src	alc882_auto_init_input_src
 
 
 /* init callback for auto-configuration model -- overriding the default init */
@@ -14834,6 +14788,8 @@ static void alc269_auto_init(struct hda_codec *codec)
 	alc269_auto_init_multi_out(codec);
 	alc269_auto_init_hp_out(codec);
 	alc269_auto_init_analog_input(codec);
+	if (!spec->dual_adc_switch)
+		alc269_auto_init_input_src(codec);
 	alc_auto_init_digital(codec);
 	if (spec->unsol_event)
 		alc_inithook(codec);
@@ -16052,9 +16008,12 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
-			err = __alc861_create_out_sw(codec, name, nid, i, 3);
+				index = 0;
+			}
+			err = __alc861_create_out_sw(codec, name, nid, index, 3);
 			if (err < 0)
 				return err;
 		}
@@ -17205,16 +17164,19 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
+				index = 0;
+			}
 			err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL,
-						name, i,
+						name, index,
 					  HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
 							      HDA_OUTPUT));
 			if (err < 0)
 				return err;
 			err = __add_pb_sw_ctrl(spec, ALC_CTL_BIND_MUTE,
-					       name, i,
+					       name, index,
 					  HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
 							      HDA_INPUT));
 			if (err < 0)
@@ -19263,12 +19225,15 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
 				return err;
 		} else {
 			const char *name = pfx;
-			if (!name)
+			int index = i;
+			if (!name) {
 				name = chname[i];
-			err = __alc662_add_vol_ctl(spec, name, nid, i, 3);
+				index = 0;
+			}
+			err = __alc662_add_vol_ctl(spec, name, nid, index, 3);
 			if (err < 0)
 				return err;
-			err = __alc662_add_sw_ctl(spec, name, mix, i, 3);
+			err = __alc662_add_sw_ctl(spec, name, mix, index, 3);
 			if (err < 0)
 				return err;
 		}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index bd7b123..05fcd60 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -180,18 +180,16 @@ struct sigmatel_event {
 	int data;
 };
 
-struct sigmatel_jack {
-	hda_nid_t nid;
-	int type;
-	struct snd_jack *jack;
-};
-
 struct sigmatel_mic_route {
 	hda_nid_t pin;
 	signed char mux_idx;
 	signed char dmux_idx;
 };
 
+#define MAX_PINS_NUM 16
+#define MAX_ADCS_NUM 4
+#define MAX_DMICS_NUM 4
+
 struct sigmatel_spec {
 	struct snd_kcontrol_new *mixers[4];
 	unsigned int num_mixers;
@@ -229,9 +227,6 @@ struct sigmatel_spec {
 	hda_nid_t *pwr_nids;
 	hda_nid_t *dac_list;
 
-	/* jack detection */
-	struct snd_array jacks;
-
 	/* events */
 	struct snd_array events;
 
@@ -309,6 +304,17 @@ struct sigmatel_spec {
 	struct hda_input_mux private_imux;
 	struct hda_input_mux private_smux;
 	struct hda_input_mux private_mono_mux;
+
+	/* auto spec */
+	unsigned auto_pin_cnt;
+	hda_nid_t auto_pin_nids[MAX_PINS_NUM];
+	unsigned auto_adc_cnt;
+	hda_nid_t auto_adc_nids[MAX_ADCS_NUM];
+	hda_nid_t auto_mux_nids[MAX_ADCS_NUM];
+	hda_nid_t auto_dmux_nids[MAX_ADCS_NUM];
+	unsigned long auto_capvols[MAX_ADCS_NUM];
+	unsigned auto_dmic_cnt;
+	hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
 };
 
 static hda_nid_t stac9200_adc_nids[1] = {
@@ -364,14 +370,6 @@ static unsigned long stac92hd73xx_capvols[] = {
 
 #define STAC92HD83_DAC_COUNT 3
 
-static hda_nid_t stac92hd83xxx_mux_nids[2] = {
-	0x17, 0x18,
-};
-
-static hda_nid_t stac92hd83xxx_adc_nids[2] = {
-	0x15, 0x16,
-};
-
 static hda_nid_t stac92hd83xxx_pwr_nids[4] = {
 	0xa, 0xb, 0xd, 0xe,
 };
@@ -384,25 +382,9 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = {
 	0x03, 0x0c, 0x20, 0x40,
 };
 
-#define STAC92HD83XXX_NUM_DMICS	 2
-static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
-	0x11, 0x20, 0
-};
-
-#define STAC92HD88XXX_NUM_DMICS	STAC92HD83XXX_NUM_DMICS
-#define stac92hd88xxx_dmic_nids	stac92hd83xxx_dmic_nids
-
-#define STAC92HD87B_NUM_DMICS	 1
-static hda_nid_t stac92hd87b_dmic_nids[STAC92HD87B_NUM_DMICS + 1] = {
-	0x11, 0
-};
-
-#define STAC92HD83XXX_NUM_CAPS	2
-static unsigned long stac92hd83xxx_capvols[] = {
-	HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
-	HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_OUTPUT),
+static hda_nid_t stac92hd83xxx_dmic_nids[] = {
+		0x11, 0x20,
 };
-#define stac92hd83xxx_capsws	stac92hd83xxx_capvols
 
 static hda_nid_t stac92hd71bxx_pwr_nids[3] = {
 	0x0a, 0x0d, 0x0f
@@ -581,21 +563,6 @@ static hda_nid_t stac92hd73xx_pin_nids[13] = {
 	0x14, 0x22, 0x23
 };
 
-static hda_nid_t stac92hd83xxx_pin_nids[10] = {
-	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
-	0x0f, 0x10, 0x11, 0x1f, 0x20,
-};
-
-static hda_nid_t stac92hd87xxx_pin_nids[6] = {
-	0x0a, 0x0b, 0x0c, 0x0d,
-	0x0f, 0x11,
-};
-
-static hda_nid_t stac92hd88xxx_pin_nids[8] = {
-	0x0a, 0x0b, 0x0c, 0x0d,
-	0x0f, 0x11, 0x1f, 0x20,
-};
-
 #define STAC92HD71BXX_NUM_PINS 13
 static hda_nid_t stac92hd71bxx_pin_nids_4port[STAC92HD71BXX_NUM_PINS] = {
 	0x0a, 0x0b, 0x0c, 0x0d, 0x00,
@@ -757,7 +724,7 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 	struct sigmatel_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	const struct hda_input_mux *imux = spec->input_mux;
-	unsigned int idx, prev_idx;
+	unsigned int idx, prev_idx, didx;
 
 	idx = ucontrol->value.enumerated.item[0];
 	if (idx >= imux->num_items)
@@ -769,7 +736,8 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 		snd_hda_codec_write_cache(codec, spec->mux_nids[adc_idx], 0,
 					  AC_VERB_SET_CONNECT_SEL,
 					  imux->items[idx].index);
-		if (prev_idx >= spec->num_analog_muxes) {
+		if (prev_idx >= spec->num_analog_muxes &&
+		    spec->mux_nids[adc_idx] != spec->dmux_nids[adc_idx]) {
 			imux = spec->dinput_mux;
 			/* 0 = analog */
 			snd_hda_codec_write_cache(codec,
@@ -779,9 +747,13 @@ static int stac92xx_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
 		}
 	} else {
 		imux = spec->dinput_mux;
+		/* first dimux item is hardcoded to select analog imux,
+		 * so lets skip it
+		 */
+		didx = idx - spec->num_analog_muxes + 1;
 		snd_hda_codec_write_cache(codec, spec->dmux_nids[adc_idx], 0,
 					  AC_VERB_SET_CONNECT_SEL,
-					  imux->items[idx - 1].index);
+					  imux->items[didx].index);
 	}
 	spec->cur_mux[adc_idx] = idx;
 	return 1;
@@ -3419,6 +3391,17 @@ static const char * const stac92xx_dmic_labels[5] = {
 	"Digital Mic 3", "Digital Mic 4"
 };
 
+static hda_nid_t get_connected_node(struct hda_codec *codec, hda_nid_t mux,
+				    int idx)
+{
+	hda_nid_t conn[HDA_MAX_NUM_INPUTS];
+	int nums;
+	nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
+	if (idx >= 0 && idx < nums)
+		return conn[idx];
+	return 0;
+}
+
 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
 				hda_nid_t nid)
 {
@@ -3429,6 +3412,15 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
 	for (i = 0; i < nums; i++)
 		if (conn[i] == nid)
 			return i;
+
+	for (i = 0; i < nums; i++) {
+		unsigned int wid_caps = get_wcaps(codec, conn[i]);
+		unsigned int wid_type = get_wcaps_type(wid_caps);
+
+		if (wid_type != AC_WID_PIN && wid_type != AC_WID_AUD_MIX)
+			if (get_connection_index(codec, conn[i], nid) >= 0)
+				return i;
+	}
 	return -1;
 }
 
@@ -3501,6 +3493,16 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
 						      type_idx, HDA_OUTPUT);
 			if (err < 0)
 				return err;
+			if (!err) {
+				nid = get_connected_node(codec,
+						spec->dmux_nids[0], index);
+				if (nid)
+					err = create_elem_capture_vol(codec,
+							nid, label,
+							type_idx, HDA_INPUT);
+				if (err < 0)
+					return err;
+			}
 		}
 	}
 
@@ -4054,21 +4056,10 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
 			   AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
 }
 
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-static void stac92xx_free_jack_priv(struct snd_jack *jack)
-{
-	struct sigmatel_jack *jacks = jack->private_data;
-	jacks->nid = 0;
-	jacks->jack = NULL;
-}
-#endif
-
 static int stac92xx_add_jack(struct hda_codec *codec,
 		hda_nid_t nid, int type)
 {
 #ifdef CONFIG_SND_HDA_INPUT_JACK
-	struct sigmatel_spec *spec = codec->spec;
-	struct sigmatel_jack *jack;
 	int def_conf = snd_hda_codec_get_pincfg(codec, nid);
 	int connectivity = get_defcfg_connect(def_conf);
 	char name[32];
@@ -4077,26 +4068,15 @@ static int stac92xx_add_jack(struct hda_codec *codec,
 	if (connectivity && connectivity != AC_JACK_PORT_FIXED)
 		return 0;
 
-	snd_array_init(&spec->jacks, sizeof(*jack), 32);
-	jack = snd_array_new(&spec->jacks);
-	if (!jack)
-		return -ENOMEM;
-	jack->nid = nid;
-	jack->type = type;
-
 	snprintf(name, sizeof(name), "%s at %s %s Jack",
 		snd_hda_get_jack_type(def_conf),
 		snd_hda_get_jack_connectivity(def_conf),
 		snd_hda_get_jack_location(def_conf));
 
-	err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
-	if (err < 0) {
-		jack->nid = 0;
+	err = snd_hda_input_jack_add(codec, nid, type, name);
+	if (err < 0)
 		return err;
-	}
-	jack->jack->private_data = jack;
-	jack->jack->private_free = stac92xx_free_jack_priv;
-#endif
+#endif /* CONFIG_SND_HDA_INPUT_JACK */
 	return 0;
 }
 
@@ -4399,23 +4379,6 @@ static int stac92xx_init(struct hda_codec *codec)
 	return 0;
 }
 
-static void stac92xx_free_jacks(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-	/* free jack instances manually when clearing/reconfiguring */
-	struct sigmatel_spec *spec = codec->spec;
-	if (!codec->bus->shutdown && spec->jacks.list) {
-		struct sigmatel_jack *jacks = spec->jacks.list;
-		int i;
-		for (i = 0; i < spec->jacks.used; i++, jacks++) {
-			if (jacks->jack)
-				snd_device_free(codec->bus->card, jacks->jack);
-		}
-	}
-	snd_array_free(&spec->jacks);
-#endif
-}
-
 static void stac92xx_free_kctls(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -4449,7 +4412,7 @@ static void stac92xx_free(struct hda_codec *codec)
 		return;
 
 	stac92xx_shutup(codec);
-	stac92xx_free_jacks(codec);
+	snd_hda_input_jack_free(codec);
 	snd_array_free(&spec->events);
 
 	kfree(spec);
@@ -4667,33 +4630,6 @@ static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
 	stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
 }
 
-static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
-	struct sigmatel_spec *spec = codec->spec;
-	struct sigmatel_jack *jacks = spec->jacks.list;
-
-	if (jacks) {
-		int i;
-		for (i = 0; i < spec->jacks.used; i++) {
-			if (jacks->nid == nid) {
-				unsigned int pin_ctl =
-					snd_hda_codec_read(codec, nid,
-					0, AC_VERB_GET_PIN_WIDGET_CONTROL,
-					 0x00);
-				int type = jacks->type;
-				if (type == (SND_JACK_LINEOUT
-						| SND_JACK_HEADPHONE))
-					type = (pin_ctl & AC_PINCTL_HP_EN)
-					? SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
-				snd_jack_report(jacks->jack,
-					get_pin_presence(codec, nid)
-					? type : 0);
-			}
-			jacks++;
-		}
-	}
-}
-
 /* get the pin connection (fixed, none, etc) */
 static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
 {
@@ -4782,7 +4718,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
 	case STAC_PWR_EVENT:
 		if (spec->num_pwrs > 0)
 			stac92xx_pin_sense(codec, event->nid);
-		stac92xx_report_jack(codec, event->nid);
+		snd_hda_input_jack_report(codec, event->nid);
 
 		switch (codec->subsystem_id) {
 		case 0x103c308f:
@@ -5378,6 +5314,105 @@ static int hp_bnb2011_with_dock(struct hda_codec *codec)
 	return 0;
 }
 
+static void stac92hd8x_add_pin(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+	int i;
+
+	spec->auto_pin_nids[spec->auto_pin_cnt] = nid;
+	spec->auto_pin_cnt++;
+
+	if (get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
+	    get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) {
+		for (i = 0; i < ARRAY_SIZE(stac92hd83xxx_dmic_nids); i++) {
+			if (nid == stac92hd83xxx_dmic_nids[i]) {
+				spec->auto_dmic_nids[spec->auto_dmic_cnt] = nid;
+				spec->auto_dmic_cnt++;
+			}
+		}
+	}
+}
+
+static void stac92hd8x_add_adc(struct hda_codec *codec, hda_nid_t nid)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	spec->auto_adc_nids[spec->auto_adc_cnt] = nid;
+	spec->auto_adc_cnt++;
+}
+
+static void stac92hd8x_add_mux(struct hda_codec *codec, hda_nid_t nid)
+{
+	int i, j;
+	struct sigmatel_spec *spec = codec->spec;
+
+	for (i = 0; i < spec->auto_adc_cnt; i++) {
+		if (get_connection_index(codec,
+				spec->auto_adc_nids[i], nid) >= 0) {
+			/* mux and volume for adc_nids[i] */
+			if (!spec->auto_mux_nids[i]) {
+				spec->auto_mux_nids[i] = nid;
+				/* 92hd codecs capture volume is in mux */
+				spec->auto_capvols[i] = HDA_COMPOSE_AMP_VAL(nid,
+							3, 0, HDA_OUTPUT);
+			}
+			for (j = 0; j < spec->auto_dmic_cnt; j++) {
+				if (get_connection_index(codec, nid,
+						spec->auto_dmic_nids[j]) >= 0) {
+					/* dmux for adc_nids[i] */
+					if (!spec->auto_dmux_nids[i])
+						spec->auto_dmux_nids[i] = nid;
+					break;
+				}
+			}
+			break;
+		}
+	}
+}
+
+static void stac92hd8x_fill_auto_spec(struct hda_codec *codec)
+{
+	hda_nid_t nid, end_nid;
+	unsigned int wid_caps, wid_type;
+	struct sigmatel_spec *spec = codec->spec;
+
+	end_nid = codec->start_nid + codec->num_nodes;
+
+	for (nid = codec->start_nid; nid < end_nid; nid++) {
+		wid_caps = get_wcaps(codec, nid);
+		wid_type = get_wcaps_type(wid_caps);
+
+		if (wid_type == AC_WID_PIN)
+			stac92hd8x_add_pin(codec, nid);
+
+		if (wid_type == AC_WID_AUD_IN && !(wid_caps & AC_WCAP_DIGITAL))
+			stac92hd8x_add_adc(codec, nid);
+	}
+
+	for (nid = codec->start_nid; nid < end_nid; nid++) {
+		wid_caps = get_wcaps(codec, nid);
+		wid_type = get_wcaps_type(wid_caps);
+
+		if (wid_type == AC_WID_AUD_SEL)
+			stac92hd8x_add_mux(codec, nid);
+	}
+
+	spec->pin_nids = spec->auto_pin_nids;
+	spec->num_pins = spec->auto_pin_cnt;
+	spec->adc_nids = spec->auto_adc_nids;
+	spec->num_adcs = spec->auto_adc_cnt;
+	spec->capvols = spec->auto_capvols;
+	spec->capsws = spec->auto_capvols;
+	spec->num_caps = spec->auto_adc_cnt;
+	spec->mux_nids = spec->auto_mux_nids;
+	spec->num_muxes = spec->auto_adc_cnt;
+	spec->dmux_nids = spec->auto_dmux_nids;
+	spec->num_dmuxes = spec->auto_adc_cnt;
+	spec->dmic_nids = spec->auto_dmic_nids;
+	spec->num_dmics = spec->auto_dmic_cnt;
+}
+
 static int patch_stac92hd83xxx(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec;
@@ -5399,26 +5434,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
 	snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);
 	codec->no_trigger_sense = 1;
 	codec->spec = spec;
+
+	stac92hd8x_fill_auto_spec(codec);
+
 	spec->linear_tone_beep = 0;
 	codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
 	spec->digbeep_nid = 0x21;
-	spec->dmic_nids = stac92hd83xxx_dmic_nids;
-	spec->dmux_nids = stac92hd83xxx_mux_nids;
-	spec->mux_nids = stac92hd83xxx_mux_nids;
-	spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids);
-	spec->adc_nids = stac92hd83xxx_adc_nids;
-	spec->num_adcs = ARRAY_SIZE(stac92hd83xxx_adc_nids);
 	spec->pwr_nids = stac92hd83xxx_pwr_nids;
 	spec->pwr_mapping = stac92hd83xxx_pwr_mapping;
 	spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
 	spec->multiout.dac_nids = spec->dac_nids;
-
 	spec->init = stac92hd83xxx_core_init;
-	spec->num_pins = ARRAY_SIZE(stac92hd83xxx_pin_nids);
-	spec->pin_nids = stac92hd83xxx_pin_nids;
-	spec->num_caps = STAC92HD83XXX_NUM_CAPS;
-	spec->capvols = stac92hd83xxx_capvols;
-	spec->capsws = stac92hd83xxx_capsws;
 
 	spec->board_config = snd_hda_check_board_config(codec,
 							STAC_92HD83XXX_MODELS,
@@ -5436,28 +5462,11 @@ again:
 	case 0x111d76d1:
 	case 0x111d76d9:
 	case 0x111d76e5:
-		spec->dmic_nids = stac92hd87b_dmic_nids;
-		spec->num_dmics = stac92xx_connected_ports(codec,
-				stac92hd87b_dmic_nids,
-				STAC92HD87B_NUM_DMICS);
-		spec->num_pins = ARRAY_SIZE(stac92hd87xxx_pin_nids);
-		spec->pin_nids = stac92hd87xxx_pin_nids;
-		spec->mono_nid = 0;
-		spec->num_pwrs = 0;
-		break;
 	case 0x111d7666:
 	case 0x111d7667:
 	case 0x111d7668:
 	case 0x111d7669:
 	case 0x111d76e3:
-		spec->num_dmics = stac92xx_connected_ports(codec,
-				stac92hd88xxx_dmic_nids,
-				STAC92HD88XXX_NUM_DMICS);
-		spec->num_pins = ARRAY_SIZE(stac92hd88xxx_pin_nids);
-		spec->pin_nids = stac92hd88xxx_pin_nids;
-		spec->mono_nid = 0;
-		spec->num_pwrs = 0;
-		break;
 	case 0x111d7604:
 	case 0x111d76d4:
 	case 0x111d7605:
@@ -5466,9 +5475,6 @@ again:
 		if (spec->board_config == STAC_92HD83XXX_PWR_REF)
 			break;
 		spec->num_pwrs = 0;
-		spec->num_dmics = stac92xx_connected_ports(codec,
-				stac92hd83xxx_dmic_nids,
-				STAC92HD83XXX_NUM_DMICS);
 		break;
 	}
 
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 63b0054..1371b57 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -159,6 +159,7 @@ struct via_spec {
 #endif
 };
 
+static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec);
 static struct via_spec * via_new_spec(struct hda_codec *codec)
 {
 	struct via_spec *spec;
@@ -169,6 +170,10 @@ static struct via_spec * via_new_spec(struct hda_codec *codec)
 
 	codec->spec = spec;
 	spec->codec = codec;
+	spec->codec_type = get_codec_type(codec);
+	/* VT1708BCE & VT1708S are almost same */
+	if (spec->codec_type == VT1708BCE)
+		spec->codec_type = VT1708S;
 	return spec;
 }
 
@@ -1101,6 +1106,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct via_spec *spec = codec->spec;
 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	int ret;
 
 	if (!spec->mux_nids[adc_idx])
 		return -EINVAL;
@@ -1109,12 +1115,14 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
 			       AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
 		snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
 				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
-	/* update jack power state */
-	set_jack_power_state(codec);
 
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+	ret = snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
 				     spec->mux_nids[adc_idx],
 				     &spec->cur_mux[adc_idx]);
+	/* update jack power state */
+	set_jack_power_state(codec);
+
+	return ret;
 }
 
 static int via_independent_hp_info(struct snd_kcontrol *kcontrol,
@@ -1188,8 +1196,16 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
 	/* Get Independent Mode index of headphone pin widget */
 	spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel
 		? 1 : 0;
-	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, pinsel);
+	if (spec->codec_type == VT1718S)
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
+	else
+		snd_hda_codec_write(codec, nid, 0,
+				    AC_VERB_SET_CONNECT_SEL, pinsel);
 
+	if (spec->codec_type == VT1812)
+		snd_hda_codec_write(codec, 0x35, 0,
+				    AC_VERB_SET_CONNECT_SEL, pinsel);
 	if (spec->multiout.hp_nid && spec->multiout.hp_nid
 	    != spec->multiout.dac_nids[HDA_FRONT])
 		snd_hda_codec_setup_stream(codec, spec->multiout.hp_nid,
@@ -1208,6 +1224,8 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
 		activate_ctl(codec, "Headphone Playback Switch",
 			     spec->hp_independent_mode);
 	}
+	/* update jack power state */
+	set_jack_power_state(codec);
 	return 0;
 }
 
@@ -1248,9 +1266,12 @@ static int via_hp_build(struct hda_codec *codec)
 		break;
 	}
 
-	nums = snd_hda_get_connections(codec, nid, conn, HDA_MAX_CONNECTIONS);
-	if (nums <= 1)
-		return 0;
+	if (spec->codec_type != VT1708) {
+		nums = snd_hda_get_connections(codec, nid,
+					       conn, HDA_MAX_CONNECTIONS);
+		if (nums <= 1)
+			return 0;
+	}
 
 	knew = via_clone_control(spec, &via_hp_mixer[0]);
 	if (knew == NULL)
@@ -1310,6 +1331,11 @@ static void mute_aa_path(struct hda_codec *codec, int mute)
 		start_idx = 2;
 		end_idx = 4;
 		break;
+	case VT1718S:
+		nid_mixer = 0x21;
+		start_idx = 1;
+		end_idx = 3;
+		break;
 	default:
 		return;
 	}
@@ -2185,10 +2211,6 @@ static int via_init(struct hda_codec *codec)
 	for (i = 0; i < spec->num_iverbs; i++)
 		snd_hda_sequence_write(codec, spec->init_verbs[i]);
 
-	spec->codec_type = get_codec_type(codec);
-	if (spec->codec_type == VT1708BCE)
-		spec->codec_type = VT1708S; /* VT1708BCE & VT1708S are almost
-					       same */
 	/* Lydia Add for EAPD enable */
 	if (!spec->dig_in_nid) { /* No Digital In connection */
 		if (spec->dig_in_pin) {
@@ -2438,7 +2460,14 @@ static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
 		else
 			type_idx = 0;
 		label = hda_get_autocfg_input_label(codec, cfg, i);
-		err = via_new_analog_input(spec, label, type_idx, idx, cap_nid);
+		if (spec->codec_type == VT1708S ||
+		    spec->codec_type == VT1702 ||
+		    spec->codec_type == VT1716S)
+			err = via_new_analog_input(spec, label, type_idx,
+						   idx+1, cap_nid);
+		else
+			err = via_new_analog_input(spec, label, type_idx,
+						   idx, cap_nid);
 		if (err < 0)
 			return err;
 		snd_hda_add_imux_item(imux, label, idx, NULL);
@@ -4147,6 +4176,11 @@ static int patch_vt1708S(struct hda_codec *codec)
 		spec->stream_name_analog = "VT1708BCE Analog";
 		spec->stream_name_digital = "VT1708BCE Digital";
 	}
+	/* correct names for VT1818S */
+	if (codec->vendor_id == 0x11060440) {
+		spec->stream_name_analog = "VT1818S Analog";
+		spec->stream_name_digital = "VT1818S Digital";
+	}
 	return 0;
 }
 
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 13cec1e..2ae8d29 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -341,9 +341,9 @@ static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int co
 	return -EBUSY;
 }
  
-static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
-				     unsigned short reg,
-				     unsigned short val)
+static void snd_intel8x0m_codec_write(struct snd_ac97 *ac97,
+				      unsigned short reg,
+				      unsigned short val)
 {
 	struct intel8x0m *chip = ac97->private_data;
 	
@@ -354,8 +354,8 @@ static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
 	iaputword(chip, reg + ac97->num * 0x80, val);
 }
 
-static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
-					      unsigned short reg)
+static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97,
+					       unsigned short reg)
 {
 	struct intel8x0m *chip = ac97->private_data;
 	unsigned short res;
@@ -385,7 +385,7 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
 /*
  * DMA I/O
  */
-static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev) 
+static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev)
 {
 	int idx;
 	u32 *bdbar = ichdev->bdbar;
@@ -437,7 +437,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic
  *  Interrupt handler
  */
 
-static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ichdev)
+static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *ichdev)
 {
 	unsigned long port = ichdev->reg_offset;
 	int civ, i, step;
@@ -489,7 +489,7 @@ static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ic
 	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
 }
 
-static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
+static irqreturn_t snd_intel8x0m_interrupt(int irq, void *dev_id)
 {
 	struct intel8x0m *chip = dev_id;
 	struct ichdev *ichdev;
@@ -512,7 +512,7 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
 	for (i = 0; i < chip->bdbars_count; i++) {
 		ichdev = &chip->ichd[i];
 		if (status & ichdev->int_sta_mask)
-			snd_intel8x0_update(chip, ichdev);
+			snd_intel8x0m_update(chip, ichdev);
 	}
 
 	/* ack them */
@@ -526,7 +526,7 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
  *  PCM part
  */
 
-static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+static int snd_intel8x0m_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct intel8x0m *chip = snd_pcm_substream_chip(substream);
 	struct ichdev *ichdev = get_ichdev(substream);
@@ -561,18 +561,18 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
 	return 0;
 }
 
-static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
+static int snd_intel8x0m_hw_params(struct snd_pcm_substream *substream,
 				  struct snd_pcm_hw_params *hw_params)
 {
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 }
 
-static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
+static int snd_intel8x0m_hw_free(struct snd_pcm_substream *substream)
 {
 	return snd_pcm_lib_free_pages(substream);
 }
 
-static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream)
+static snd_pcm_uframes_t snd_intel8x0m_pcm_pointer(struct snd_pcm_substream *substream)
 {
 	struct intel8x0m *chip = snd_pcm_substream_chip(substream);
 	struct ichdev *ichdev = get_ichdev(substream);
@@ -600,7 +600,7 @@ static int snd_intel8x0m_pcm_prepare(struct snd_pcm_substream *substream)
 	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
 	snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate);
 	snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0);
-	snd_intel8x0_setup_periods(chip, ichdev);
+	snd_intel8x0m_setup_periods(chip, ichdev);
 	return 0;
 }
 
@@ -682,22 +682,22 @@ static struct snd_pcm_ops snd_intel8x0m_playback_ops = {
 	.open =		snd_intel8x0m_playback_open,
 	.close =	snd_intel8x0m_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
-	.hw_params =	snd_intel8x0_hw_params,
-	.hw_free =	snd_intel8x0_hw_free,
+	.hw_params =	snd_intel8x0m_hw_params,
+	.hw_free =	snd_intel8x0m_hw_free,
 	.prepare =	snd_intel8x0m_pcm_prepare,
-	.trigger =	snd_intel8x0_pcm_trigger,
-	.pointer =	snd_intel8x0_pcm_pointer,
+	.trigger =	snd_intel8x0m_pcm_trigger,
+	.pointer =	snd_intel8x0m_pcm_pointer,
 };
 
 static struct snd_pcm_ops snd_intel8x0m_capture_ops = {
 	.open =		snd_intel8x0m_capture_open,
 	.close =	snd_intel8x0m_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
-	.hw_params =	snd_intel8x0_hw_params,
-	.hw_free =	snd_intel8x0_hw_free,
+	.hw_params =	snd_intel8x0m_hw_params,
+	.hw_free =	snd_intel8x0m_hw_free,
 	.prepare =	snd_intel8x0m_pcm_prepare,
-	.trigger =	snd_intel8x0_pcm_trigger,
-	.pointer =	snd_intel8x0_pcm_pointer,
+	.trigger =	snd_intel8x0m_pcm_trigger,
+	.pointer =	snd_intel8x0m_pcm_pointer,
 };
 
 
@@ -710,7 +710,7 @@ struct ich_pcm_table {
 	int ac97_idx;
 };
 
-static int __devinit snd_intel8x0_pcm1(struct intel8x0m *chip, int device,
+static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
 				       struct ich_pcm_table *rec)
 {
 	struct snd_pcm *pcm;
@@ -759,7 +759,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
 	},
 };
 
-static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
+static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip)
 {
 	int i, tblsize, device, err;
 	struct ich_pcm_table *tbl, *rec;
@@ -791,7 +791,7 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
 			if (! chip->ichd[rec->ac97_idx].ac97)
 				continue;
 		}
-		err = snd_intel8x0_pcm1(chip, device, rec);
+		err = snd_intel8x0m_pcm1(chip, device, rec);
 		if (err < 0)
 			return err;
 		device++;
@@ -806,20 +806,20 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
  *  Mixer part
  */
 
-static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
+static void snd_intel8x0m_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
 {
 	struct intel8x0m *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 }
 
-static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
+static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97)
 {
 	struct intel8x0m *chip = ac97->private_data;
 	chip->ac97 = NULL;
 }
 
 
-static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
+static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
 {
 	struct snd_ac97_bus *pbus;
 	struct snd_ac97_template ac97;
@@ -827,22 +827,22 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
 	int err;
 	unsigned int glob_sta = 0;
 	static struct snd_ac97_bus_ops ops = {
-		.write = snd_intel8x0_codec_write,
-		.read = snd_intel8x0_codec_read,
+		.write = snd_intel8x0m_codec_write,
+		.read = snd_intel8x0m_codec_read,
 	};
 
 	chip->in_ac97_init = 1;
 	
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
-	ac97.private_free = snd_intel8x0_mixer_free_ac97;
+	ac97.private_free = snd_intel8x0m_mixer_free_ac97;
 	ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
 
 	glob_sta = igetdword(chip, ICHREG(GLOB_STA));
 
 	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 		goto __err;
-	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
+	pbus->private_free = snd_intel8x0m_mixer_free_ac97_bus;
 	if (ac97_clock >= 8000 && ac97_clock <= 48000)
 		pbus->clock = ac97_clock;
 	chip->ac97_bus = pbus;
@@ -894,7 +894,8 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
 	/* finish cold or do warm reset */
 	cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
 	iputdword(chip, ICHREG(GLOB_CNT), cnt);
-	end_time = (jiffies + (HZ / 4)) + 1;
+	usleep_range(500, 1000); /* give warm reset some time */
+	end_time = jiffies + HZ / 4;
 	do {
 		if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
 			goto __ok;
@@ -959,7 +960,7 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
       	return 0;
 }
 
-static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing)
+static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing)
 {
 	unsigned int i;
 	int err;
@@ -980,7 +981,7 @@ static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing)
 	return 0;
 }
 
-static int snd_intel8x0_free(struct intel8x0m *chip)
+static int snd_intel8x0m_free(struct intel8x0m *chip)
 {
 	unsigned int i;
 
@@ -1045,7 +1046,7 @@ static int intel8x0m_resume(struct pci_dev *pci)
 		return -EIO;
 	}
 	pci_set_master(pci);
-	if (request_irq(pci->irq, snd_intel8x0_interrupt,
+	if (request_irq(pci->irq, snd_intel8x0m_interrupt,
 			IRQF_SHARED, card->shortname, chip)) {
 		printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "
 		       "disabling device\n", pci->irq);
@@ -1053,7 +1054,7 @@ static int intel8x0m_resume(struct pci_dev *pci)
 		return -EIO;
 	}
 	chip->irq = pci->irq;
-	snd_intel8x0_chip_init(chip, 0);
+	snd_intel8x0m_chip_init(chip, 0);
 	snd_ac97_resume(chip->ac97);
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1094,10 +1095,10 @@ static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
 #endif /* CONFIG_PROC_FS */
 
 
-static int snd_intel8x0_dev_free(struct snd_device *device)
+static int snd_intel8x0m_dev_free(struct snd_device *device)
 {
 	struct intel8x0m *chip = device->device_data;
-	return snd_intel8x0_free(chip);
+	return snd_intel8x0m_free(chip);
 }
 
 struct ich_reg_info {
@@ -1108,7 +1109,7 @@ struct ich_reg_info {
 static int __devinit snd_intel8x0m_create(struct snd_card *card,
 					 struct pci_dev *pci,
 					 unsigned long device_type,
-					 struct intel8x0m ** r_intel8x0)
+					 struct intel8x0m **r_intel8x0m)
 {
 	struct intel8x0m *chip;
 	int err;
@@ -1116,7 +1117,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	unsigned int int_sta_masks;
 	struct ichdev *ichdev;
 	static struct snd_device_ops ops = {
-		.dev_free =	snd_intel8x0_dev_free,
+		.dev_free =	snd_intel8x0m_dev_free,
 	};
 	static struct ich_reg_info intel_regs[2] = {
 		{ ICH_MIINT, 0 },
@@ -1124,7 +1125,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	};
 	struct ich_reg_info *tbl;
 
-	*r_intel8x0 = NULL;
+	*r_intel8x0m = NULL;
 
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
@@ -1158,7 +1159,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 		chip->addr = pci_iomap(pci, 0, 0);
 	if (!chip->addr) {
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -EIO;
 	}
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
@@ -1167,15 +1168,15 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 		chip->bmaddr = pci_iomap(pci, 1, 0);
 	if (!chip->bmaddr) {
 		snd_printk(KERN_ERR "Controller space ioremap problem\n");
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -EIO;
 	}
 
  port_inited:
-	if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED,
+	if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED,
 			card->shortname, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -EBUSY;
 	}
 	chip->irq = pci->irq;
@@ -1210,7 +1211,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
 				&chip->bdbars) < 0) {
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -ENOMEM;
 	}
 	/* tables must be aligned to 8 bytes here, but the kernel pages
@@ -1225,19 +1226,19 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	chip->int_sta_reg = ICH_REG_GLOB_STA;
 	chip->int_sta_mask = int_sta_masks;
 
-	if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) {
-		snd_intel8x0_free(chip);
+	if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) {
+		snd_intel8x0m_free(chip);
 		return err;
 	}
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return err;
 	}
 
 	snd_card_set_dev(card, &pci->dev);
 
-	*r_intel8x0 = chip;
+	*r_intel8x0m = chip;
 	return 0;
 }
 
@@ -1295,11 +1296,11 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
 	}
 	card->private_data = chip;
 
-	if ((err = snd_intel8x0_mixer(chip, ac97_clock)) < 0) {
+	if ((err = snd_intel8x0m_mixer(chip, ac97_clock)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = snd_intel8x0_pcm(chip)) < 0) {
+	if ((err = snd_intel8x0m_pcm(chip)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index f5eadfc..a323eaf 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -8,6 +8,21 @@
  *      Modified 2006-06-01 for AES32 support by Remy Bruno
  *                                               <remy.bruno@trinnov.com>
  *
+ *      Modified 2009-04-13 for proper metering by Florian Faber
+ *                                               <faber@faberman.de>
+ *
+ *      Modified 2009-04-14 for native float support by Florian Faber
+ *                                               <faber@faberman.de>
+ *
+ *      Modified 2009-04-26 fixed bug in rms metering by Florian Faber
+ *                                               <faber@faberman.de>
+ *
+ *      Modified 2009-04-30 added hw serial number support by Florian Faber
+ *
+ *      Modified 2011-01-14 added S/PDIF input on RayDATs by Adrian Knoth
+ *
+ *	Modified 2011-01-25 variable period sizes on RayDAT/AIO by Adrian Knoth
+ *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
  *   the Free Software Foundation; either version 2 of the License, or
@@ -35,6 +50,7 @@
 #include <sound/core.h>
 #include <sound/control.h>
 #include <sound/pcm.h>
+#include <sound/pcm_params.h>
 #include <sound/info.h>
 #include <sound/asoundef.h>
 #include <sound/rawmidi.h>
@@ -47,15 +63,6 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	  /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	  /* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
 
-/* Disable precise pointer at start */
-static int precise_ptr[SNDRV_CARDS];
-
-/* Send all playback to line outs */
-static int line_outs_monitor[SNDRV_CARDS];
-
-/* Enable Analog Outs on Channel 63/64 by default */
-static int enable_monitor[SNDRV_CARDS];
-
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
 
@@ -65,42 +72,39 @@ MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
 
-module_param_array(precise_ptr, bool, NULL, 0444);
-MODULE_PARM_DESC(precise_ptr, "Enable or disable precise pointer.");
-
-module_param_array(line_outs_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(line_outs_monitor,
-		 "Send playback streams to analog outs by default.");
-
-module_param_array(enable_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(enable_monitor,
-		 "Enable Analog Out on Channel 63/64 by default.");
 
 MODULE_AUTHOR
-      ("Winfried Ritsch <ritsch_AT_iem.at>, "
-       "Paul Davis <paul@linuxaudiosystems.com>, "
-       "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
-       "Remy Bruno <remy.bruno@trinnov.com>");
+(
+	"Winfried Ritsch <ritsch_AT_iem.at>, "
+	"Paul Davis <paul@linuxaudiosystems.com>, "
+	"Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
+	"Remy Bruno <remy.bruno@trinnov.com>, "
+	"Florian Faber <faberman@linuxproaudio.org>, "
+	"Adrian Knoth <adi@drcomp.erfurt.thur.de>"
+);
 MODULE_DESCRIPTION("RME HDSPM");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 
-/* --- Write registers. --- 
+/* --- Write registers. ---
   These are defined as byte-offsets from the iobase value.  */
 
+#define HDSPM_WR_SETTINGS             0
+#define HDSPM_outputBufferAddress    32
+#define HDSPM_inputBufferAddress     36
 #define HDSPM_controlRegister	     64
 #define HDSPM_interruptConfirmation  96
 #define HDSPM_control2Reg	     256  /* not in specs ???????? */
 #define HDSPM_freqReg                256  /* for AES32 */
-#define HDSPM_midiDataOut0  	     352  /* just believe in old code */
-#define HDSPM_midiDataOut1  	     356
+#define HDSPM_midiDataOut0	     352  /* just believe in old code */
+#define HDSPM_midiDataOut1	     356
 #define HDSPM_eeprom_wr		     384  /* for AES32 */
 
 /* DMA enable for 64 channels, only Bit 0 is relevant */
-#define HDSPM_outputEnableBase       512  /* 512-767  input  DMA */ 
+#define HDSPM_outputEnableBase       512  /* 512-767  input  DMA */
 #define HDSPM_inputEnableBase        768  /* 768-1023 output DMA */
 
-/* 16 page addresses for each of the 64 channels DMA buffer in and out 
+/* 16 page addresses for each of the 64 channels DMA buffer in and out
    (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
 #define HDSPM_pageAddressBufferOut       8192
 #define HDSPM_pageAddressBufferIn        (HDSPM_pageAddressBufferOut+64*16*4)
@@ -119,22 +123,84 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_statusRegister2  192
 #define HDSPM_timecodeRegister 128
 
+/* AIO, RayDAT */
+#define HDSPM_RD_STATUS_0 0
+#define HDSPM_RD_STATUS_1 64
+#define HDSPM_RD_STATUS_2 128
+#define HDSPM_RD_STATUS_3 192
+
+#define HDSPM_RD_TCO           256
+#define HDSPM_RD_PLL_FREQ      512
+#define HDSPM_WR_TCO           128
+
+#define HDSPM_TCO1_TCO_lock			0x00000001
+#define HDSPM_TCO1_WCK_Input_Range_LSB		0x00000002
+#define HDSPM_TCO1_WCK_Input_Range_MSB		0x00000004
+#define HDSPM_TCO1_LTC_Input_valid		0x00000008
+#define HDSPM_TCO1_WCK_Input_valid		0x00000010
+#define HDSPM_TCO1_Video_Input_Format_NTSC	0x00000020
+#define HDSPM_TCO1_Video_Input_Format_PAL	0x00000040
+
+#define HDSPM_TCO1_set_TC			0x00000100
+#define HDSPM_TCO1_set_drop_frame_flag		0x00000200
+#define HDSPM_TCO1_LTC_Format_LSB		0x00000400
+#define HDSPM_TCO1_LTC_Format_MSB		0x00000800
+
+#define HDSPM_TCO2_TC_run			0x00010000
+#define HDSPM_TCO2_WCK_IO_ratio_LSB		0x00020000
+#define HDSPM_TCO2_WCK_IO_ratio_MSB		0x00040000
+#define HDSPM_TCO2_set_num_drop_frames_LSB	0x00080000
+#define HDSPM_TCO2_set_num_drop_frames_MSB	0x00100000
+#define HDSPM_TCO2_set_jam_sync			0x00200000
+#define HDSPM_TCO2_set_flywheel			0x00400000
+
+#define HDSPM_TCO2_set_01_4			0x01000000
+#define HDSPM_TCO2_set_pull_down		0x02000000
+#define HDSPM_TCO2_set_pull_up			0x04000000
+#define HDSPM_TCO2_set_freq			0x08000000
+#define HDSPM_TCO2_set_term_75R			0x10000000
+#define HDSPM_TCO2_set_input_LSB		0x20000000
+#define HDSPM_TCO2_set_input_MSB		0x40000000
+#define HDSPM_TCO2_set_freq_from_app		0x80000000
+
+
+#define HDSPM_midiDataOut0    352
+#define HDSPM_midiDataOut1    356
+#define HDSPM_midiDataOut2    368
+
 #define HDSPM_midiDataIn0     360
 #define HDSPM_midiDataIn1     364
+#define HDSPM_midiDataIn2     372
+#define HDSPM_midiDataIn3     376
 
 /* status is data bytes in MIDI-FIFO (0-128) */
-#define HDSPM_midiStatusOut0  384	
-#define HDSPM_midiStatusOut1  388	
-#define HDSPM_midiStatusIn0   392	
-#define HDSPM_midiStatusIn1   396	
+#define HDSPM_midiStatusOut0  384
+#define HDSPM_midiStatusOut1  388
+#define HDSPM_midiStatusOut2  400
+
+#define HDSPM_midiStatusIn0   392
+#define HDSPM_midiStatusIn1   396
+#define HDSPM_midiStatusIn2   404
+#define HDSPM_midiStatusIn3   408
 
 
 /* the meters are regular i/o-mapped registers, but offset
    considerably from the rest. the peak registers are reset
-   when read; the least-significant 4 bits are full-scale counters; 
+   when read; the least-significant 4 bits are full-scale counters;
    the actual peak value is in the most-significant 24 bits.
 */
-#define HDSPM_MADI_peakrmsbase 	4096	/* 4096-8191 2x64x32Bit Meters */
+
+#define HDSPM_MADI_INPUT_PEAK		4096
+#define HDSPM_MADI_PLAYBACK_PEAK	4352
+#define HDSPM_MADI_OUTPUT_PEAK		4608
+
+#define HDSPM_MADI_INPUT_RMS_L		6144
+#define HDSPM_MADI_PLAYBACK_RMS_L	6400
+#define HDSPM_MADI_OUTPUT_RMS_L		6656
+
+#define HDSPM_MADI_INPUT_RMS_H		7168
+#define HDSPM_MADI_PLAYBACK_RMS_H	7424
+#define HDSPM_MADI_OUTPUT_RMS_H		7680
 
 /* --- Control Register bits --------- */
 #define HDSPM_Start                (1<<0) /* start engine */
@@ -143,7 +209,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_Latency1             (1<<2) /* where n is defined */
 #define HDSPM_Latency2             (1<<3) /* by Latency{2,1,0} */
 
-#define HDSPM_ClockModeMaster      (1<<4) /* 1=Master, 0=Slave/Autosync */
+#define HDSPM_ClockModeMaster      (1<<4) /* 1=Master, 0=Autosync */
+#define HDSPM_c0Master		0x1    /* Master clock bit in settings
+					  register [RayDAT, AIO] */
 
 #define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
 
@@ -157,7 +225,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 				     56channelMODE=0 */ /* MADI ONLY*/
 #define HDSPM_Emphasis    (1<<10) /* Emphasis */ /* AES32 ONLY */
 
-#define HDSPM_AutoInp     (1<<11) /* Auto Input (takeover) == Safe Mode, 
+#define HDSPM_AutoInp     (1<<11) /* Auto Input (takeover) == Safe Mode,
                                      0=off, 1=on  */ /* MADI ONLY */
 #define HDSPM_Dolby       (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
 
@@ -166,22 +234,23 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 				    */
 #define HDSPM_InputSelect1 (1<<15) /* should be 0 */
 
-#define HDSPM_SyncRef0     (1<<16) /* 0=WOrd, 1=MADI */
-#define HDSPM_SyncRef1     (1<<17) /* for AES32: SyncRefN codes the AES # */
 #define HDSPM_SyncRef2     (1<<13)
 #define HDSPM_SyncRef3     (1<<25)
 
 #define HDSPM_SMUX         (1<<18) /* Frame ??? */ /* MADI ONY */
-#define HDSPM_clr_tms      (1<<19) /* clear track marker, do not use 
+#define HDSPM_clr_tms      (1<<19) /* clear track marker, do not use
                                       AES additional bits in
 				      lower 5 Audiodatabits ??? */
 #define HDSPM_taxi_reset   (1<<20) /* ??? */ /* MADI ONLY ? */
 #define HDSPM_WCK48        (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
 
-#define HDSPM_Midi0InterruptEnable (1<<22)
-#define HDSPM_Midi1InterruptEnable (1<<23)
+#define HDSPM_Midi0InterruptEnable 0x0400000
+#define HDSPM_Midi1InterruptEnable 0x0800000
+#define HDSPM_Midi2InterruptEnable 0x0200000
+#define HDSPM_Midi3InterruptEnable 0x4000000
 
 #define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
+#define HDSPe_FLOAT_FORMAT         0x2000000
 
 #define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
 #define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
@@ -198,11 +267,18 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_InputCoaxial   (HDSPM_InputSelect0)
 #define HDSPM_SyncRefMask    (HDSPM_SyncRef0|HDSPM_SyncRef1|\
 			      HDSPM_SyncRef2|HDSPM_SyncRef3)
-#define HDSPM_SyncRef_Word   0
-#define HDSPM_SyncRef_MADI   (HDSPM_SyncRef0)
 
-#define HDSPM_SYNC_FROM_WORD 0	/* Preferred sync reference */
-#define HDSPM_SYNC_FROM_MADI 1	/* choices - used by "pref_sync_ref" */
+#define HDSPM_c0_SyncRef0      0x2
+#define HDSPM_c0_SyncRef1      0x4
+#define HDSPM_c0_SyncRef2      0x8
+#define HDSPM_c0_SyncRef3      0x10
+#define HDSPM_c0_SyncRefMask   (HDSPM_c0_SyncRef0 | HDSPM_c0_SyncRef1 |\
+				HDSPM_c0_SyncRef2 | HDSPM_c0_SyncRef3)
+
+#define HDSPM_SYNC_FROM_WORD    0	/* Preferred sync reference */
+#define HDSPM_SYNC_FROM_MADI    1	/* choices - used by "pref_sync_ref" */
+#define HDSPM_SYNC_FROM_TCO     2
+#define HDSPM_SYNC_FROM_SYNC_IN 3
 
 #define HDSPM_Frequency32KHz    HDSPM_Frequency0
 #define HDSPM_Frequency44_1KHz  HDSPM_Frequency1
@@ -216,17 +292,6 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_Frequency192KHz   (HDSPM_QuadSpeed|HDSPM_Frequency1|\
 				 HDSPM_Frequency0)
 
-/* --- for internal discrimination */
-#define HDSPM_CLOCK_SOURCE_AUTOSYNC          0	/* Sample Clock Sources */
-#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ    1
-#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ  2
-#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ    3
-#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ    4
-#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ  5
-#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ    6
-#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ   7
-#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
-#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ   9
 
 /* Synccheck Status */
 #define HDSPM_SYNC_CHECK_NO_LOCK 0
@@ -236,14 +301,16 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 /* AutoSync References - used by "autosync_ref" control switch */
 #define HDSPM_AUTOSYNC_FROM_WORD      0
 #define HDSPM_AUTOSYNC_FROM_MADI      1
-#define HDSPM_AUTOSYNC_FROM_NONE      2
+#define HDSPM_AUTOSYNC_FROM_TCO       2
+#define HDSPM_AUTOSYNC_FROM_SYNC_IN   3
+#define HDSPM_AUTOSYNC_FROM_NONE      4
 
 /* Possible sources of MADI input */
 #define HDSPM_OPTICAL 0		/* optical   */
 #define HDSPM_COAXIAL 1		/* BNC */
 
 #define hdspm_encode_latency(x)       (((x)<<1) & HDSPM_LatencyMask)
-#define hdspm_decode_latency(x)       (((x) & HDSPM_LatencyMask)>>1)
+#define hdspm_decode_latency(x)       ((((x) & HDSPM_LatencyMask)>>1))
 
 #define hdspm_encode_in(x) (((x)&0x3)<<14)
 #define hdspm_decode_in(x) (((x)>>14)&0x3)
@@ -270,13 +337,21 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_AB_int             (1<<2)	/* InputChannel Opt=0, Coax=1
 					 * (like inp0)
 					 */
+
 #define HDSPM_madiLock           (1<<3)	/* MADI Locked =1, no=0 */
+#define HDSPM_madiSync          (1<<18) /* MADI is in sync */
+
+#define HDSPM_tcoLock    0x00000020 /* Optional TCO locked status FOR HDSPe MADI! */
+#define HDSPM_tcoSync    0x10000000 /* Optional TCO sync status */
+
+#define HDSPM_syncInLock 0x00010000 /* Sync In lock status FOR HDSPe MADI! */
+#define HDSPM_syncInSync 0x00020000 /* Sync In sync status FOR HDSPe MADI! */
 
 #define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
-                                           /* since 64byte accurate last 6 bits 
-                                              are not used */
+			/* since 64byte accurate, last 6 bits are not used */
+
+
 
-#define HDSPM_madiSync          (1<<18) /* MADI is in sync */
 #define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
 
 #define HDSPM_madiFreq0         (1<<22)	/* system freq 0=error */
@@ -287,8 +362,19 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_BufferID          (1<<26)	/* (Double)Buffer ID toggles with
 					 * Interrupt
 					 */
-#define HDSPM_midi0IRQPending   (1<<30)	/* MIDI IRQ is pending  */
-#define HDSPM_midi1IRQPending   (1<<31)	/* and aktiv */
+#define HDSPM_tco_detect         0x08000000
+#define HDSPM_tco_lock	         0x20000000
+
+#define HDSPM_s2_tco_detect      0x00000040
+#define HDSPM_s2_AEBO_D          0x00000080
+#define HDSPM_s2_AEBI_D          0x00000100
+
+
+#define HDSPM_midi0IRQPending    0x40000000
+#define HDSPM_midi1IRQPending    0x80000000
+#define HDSPM_midi2IRQPending    0x20000000
+#define HDSPM_midi2IRQPendingAES 0x00000020
+#define HDSPM_midi3IRQPending    0x00200000
 
 /* --- status bit helpers */
 #define HDSPM_madiFreqMask  (HDSPM_madiFreq0|HDSPM_madiFreq1|\
@@ -317,7 +403,10 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_wc_freq2 (1<<7)	/* 100=64, 101=88.2, 110=96, */
 /* missing Bit   for               111=128, 1000=176.4, 1001=192 */
 
-#define HDSPM_SelSyncRef0 (1<<8)	/* Sync Source in slave mode */
+#define HDSPM_SyncRef0 0x10000  /* Sync Reference */
+#define HDSPM_SyncRef1 0x20000
+
+#define HDSPM_SelSyncRef0 (1<<8)	/* AutoSync Source */
 #define HDSPM_SelSyncRef1 (1<<9)	/* 000=word, 001=MADI, */
 #define HDSPM_SelSyncRef2 (1<<10)	/* 111=no valid signal */
 
@@ -331,11 +420,19 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_wcFreq88_2  (HDSPM_wc_freq0|HDSPM_wc_freq2)
 #define HDSPM_wcFreq96    (HDSPM_wc_freq1|HDSPM_wc_freq2)
 
+#define HDSPM_status1_F_0 0x0400000
+#define HDSPM_status1_F_1 0x0800000
+#define HDSPM_status1_F_2 0x1000000
+#define HDSPM_status1_F_3 0x2000000
+#define HDSPM_status1_freqMask (HDSPM_status1_F_0|HDSPM_status1_F_1|HDSPM_status1_F_2|HDSPM_status1_F_3)
+
 
 #define HDSPM_SelSyncRefMask       (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
 				    HDSPM_SelSyncRef2)
 #define HDSPM_SelSyncRef_WORD      0
 #define HDSPM_SelSyncRef_MADI      (HDSPM_SelSyncRef0)
+#define HDSPM_SelSyncRef_TCO       (HDSPM_SelSyncRef1)
+#define HDSPM_SelSyncRef_SyncIn    (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1)
 #define HDSPM_SelSyncRef_NVALID    (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|\
 				    HDSPM_SelSyncRef2)
 
@@ -345,7 +442,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 /* status */
 #define HDSPM_AES32_wcLock	0x0200000
 #define HDSPM_AES32_wcFreq_bit  22
-/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function 
+/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
   HDSPM_bit2freq */
 #define HDSPM_AES32_syncref_bit  16
 /* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
@@ -398,28 +495,348 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define MADI_DS_CHANNELS       32
 #define MADI_QS_CHANNELS       16
 
+#define RAYDAT_SS_CHANNELS     36
+#define RAYDAT_DS_CHANNELS     20
+#define RAYDAT_QS_CHANNELS     12
+
+#define AIO_IN_SS_CHANNELS        14
+#define AIO_IN_DS_CHANNELS        10
+#define AIO_IN_QS_CHANNELS        8
+#define AIO_OUT_SS_CHANNELS        16
+#define AIO_OUT_DS_CHANNELS        12
+#define AIO_OUT_QS_CHANNELS        10
+
+#define AES32_CHANNELS		16
+
 /* the size of a substream (1 mono data stream) */
 #define HDSPM_CHANNEL_BUFFER_SAMPLES  (16*1024)
 #define HDSPM_CHANNEL_BUFFER_BYTES    (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
 
 /* the size of the area we need to allocate for DMA transfers. the
    size is the same regardless of the number of channels, and
-   also the latency to use. 
+   also the latency to use.
    for one direction !!!
 */
 #define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
 /* revisions >= 230 indicate AES32 card */
-#define HDSPM_AESREVISION 230
+#define HDSPM_MADI_REV		210
+#define HDSPM_RAYDAT_REV	211
+#define HDSPM_AIO_REV		212
+#define HDSPM_MADIFACE_REV	213
+#define HDSPM_AES_REV		240
+#define HDSPM_AES32_REV		234
+#define HDSPM_AES32_OLD_REV	233
 
 /* speed factor modes */
 #define HDSPM_SPEED_SINGLE 0
 #define HDSPM_SPEED_DOUBLE 1
 #define HDSPM_SPEED_QUAD   2
+
 /* names for speed modes */
 static char *hdspm_speed_names[] = { "single", "double", "quad" };
 
+static char *texts_autosync_aes_tco[] = { "Word Clock",
+					  "AES1", "AES2", "AES3", "AES4",
+					  "AES5", "AES6", "AES7", "AES8",
+					  "TCO" };
+static char *texts_autosync_aes[] = { "Word Clock",
+				      "AES1", "AES2", "AES3", "AES4",
+				      "AES5", "AES6", "AES7", "AES8" };
+static char *texts_autosync_madi_tco[] = { "Word Clock",
+					   "MADI", "TCO", "Sync In" };
+static char *texts_autosync_madi[] = { "Word Clock",
+				       "MADI", "Sync In" };
+
+static char *texts_autosync_raydat_tco[] = {
+	"Word Clock",
+	"ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
+	"AES", "SPDIF", "TCO", "Sync In"
+};
+static char *texts_autosync_raydat[] = {
+	"Word Clock",
+	"ADAT 1", "ADAT 2", "ADAT 3", "ADAT 4",
+	"AES", "SPDIF", "Sync In"
+};
+static char *texts_autosync_aio_tco[] = {
+	"Word Clock",
+	"ADAT", "AES", "SPDIF", "TCO", "Sync In"
+};
+static char *texts_autosync_aio[] = { "Word Clock",
+				      "ADAT", "AES", "SPDIF", "Sync In" };
+
+static char *texts_freq[] = {
+	"No Lock",
+	"32 kHz",
+	"44.1 kHz",
+	"48 kHz",
+	"64 kHz",
+	"88.2 kHz",
+	"96 kHz",
+	"128 kHz",
+	"176.4 kHz",
+	"192 kHz"
+};
+
+static char *texts_ports_madi[] = {
+	"MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
+	"MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
+	"MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
+	"MADI.19", "MADI.20", "MADI.21", "MADI.22", "MADI.23", "MADI.24",
+	"MADI.25", "MADI.26", "MADI.27", "MADI.28", "MADI.29", "MADI.30",
+	"MADI.31", "MADI.32", "MADI.33", "MADI.34", "MADI.35", "MADI.36",
+	"MADI.37", "MADI.38", "MADI.39", "MADI.40", "MADI.41", "MADI.42",
+	"MADI.43", "MADI.44", "MADI.45", "MADI.46", "MADI.47", "MADI.48",
+	"MADI.49", "MADI.50", "MADI.51", "MADI.52", "MADI.53", "MADI.54",
+	"MADI.55", "MADI.56", "MADI.57", "MADI.58", "MADI.59", "MADI.60",
+	"MADI.61", "MADI.62", "MADI.63", "MADI.64",
+};
+
+
+static char *texts_ports_raydat_ss[] = {
+	"ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
+	"ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
+	"ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
+	"ADAT3.3", "ADAT3.4", "ADAT3.5", "ADAT3.6", "ADAT3.7", "ADAT3.8",
+	"ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4", "ADAT4.5", "ADAT4.6",
+	"ADAT4.7", "ADAT4.8",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R"
+};
+
+static char *texts_ports_raydat_ds[] = {
+	"ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
+	"ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
+	"ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
+	"ADAT4.1", "ADAT4.2", "ADAT4.3", "ADAT4.4",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R"
+};
+
+static char *texts_ports_raydat_qs[] = {
+	"ADAT1.1", "ADAT1.2",
+	"ADAT2.1", "ADAT2.2",
+	"ADAT3.1", "ADAT3.2",
+	"ADAT4.1", "ADAT4.2",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R"
+};
+
+
+static char *texts_ports_aio_in_ss[] = {
+	"Analogue.L", "Analogue.R",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R",
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
+	"ADAT.7", "ADAT.8"
+};
+
+static char *texts_ports_aio_out_ss[] = {
+	"Analogue.L", "Analogue.R",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R",
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4", "ADAT.5", "ADAT.6",
+	"ADAT.7", "ADAT.8",
+	"Phone.L", "Phone.R"
+};
+
+static char *texts_ports_aio_in_ds[] = {
+	"Analogue.L", "Analogue.R",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R",
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
+};
+
+static char *texts_ports_aio_out_ds[] = {
+	"Analogue.L", "Analogue.R",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R",
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
+	"Phone.L", "Phone.R"
+};
+
+static char *texts_ports_aio_in_qs[] = {
+	"Analogue.L", "Analogue.R",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R",
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4"
+};
+
+static char *texts_ports_aio_out_qs[] = {
+	"Analogue.L", "Analogue.R",
+	"AES.L", "AES.R",
+	"SPDIF.L", "SPDIF.R",
+	"ADAT.1", "ADAT.2", "ADAT.3", "ADAT.4",
+	"Phone.L", "Phone.R"
+};
+
+static char *texts_ports_aes32[] = {
+	"AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
+	"AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
+	"AES.15", "AES.16"
+};
+
+/* These tables map the ALSA channels 1..N to the channels that we
+   need to use in order to find the relevant channel buffer. RME
+   refers to this kind of mapping as between "the ADAT channel and
+   the DMA channel." We index it using the logical audio channel,
+   and the value is the DMA channel (i.e. channel buffer number)
+   where the data for that channel can be read/written from/to.
+*/
+
+static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
+	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, 57, 58, 59, 60, 61, 62, 63
+};
+
+static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
+	4, 5, 6, 7, 8, 9, 10, 11,	/* ADAT 1 */
+	12, 13, 14, 15, 16, 17, 18, 19,	/* ADAT 2 */
+	20, 21, 22, 23, 24, 25, 26, 27,	/* ADAT 3 */
+	28, 29, 30, 31, 32, 33, 34, 35,	/* ADAT 4 */
+	0, 1,			/* AES */
+	2, 3,			/* SPDIF */
+	-1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
+	4, 5, 6, 7,		/* ADAT 1 */
+	8, 9, 10, 11,		/* ADAT 2 */
+	12, 13, 14, 15,		/* ADAT 3 */
+	16, 17, 18, 19,		/* ADAT 4 */
+	0, 1,			/* AES */
+	2, 3,			/* SPDIF */
+	-1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
+	4, 5,			/* ADAT 1 */
+	6, 7,			/* ADAT 2 */
+	8, 9,			/* ADAT 3 */
+	10, 11,			/* ADAT 4 */
+	0, 1,			/* AES */
+	2, 3,			/* SPDIF */
+	-1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
+	0, 1,			/* line in */
+	8, 9,			/* aes in, */
+	10, 11,			/* spdif in */
+	12, 13, 14, 15, 16, 17, 18, 19,	/* ADAT in */
+	-1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
+	0, 1,			/* line out */
+	8, 9,			/* aes out */
+	10, 11,			/* spdif out */
+	12, 13, 14, 15, 16, 17, 18, 19,	/* ADAT out */
+	6, 7,			/* phone out */
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
+	0, 1,			/* line in */
+	8, 9,			/* aes in */
+	10, 11,			/* spdif in */
+	12, 14, 16, 18,		/* adat in */
+	-1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
+	0, 1,			/* line out */
+	8, 9,			/* aes out */
+	10, 11,			/* spdif out */
+	12, 14, 16, 18,		/* adat out */
+	6, 7,			/* phone out */
+	-1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
+	0, 1,			/* line in */
+	8, 9,			/* aes in */
+	10, 11,			/* spdif in */
+	12, 16,			/* adat in */
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
+	0, 1,			/* line out */
+	8, 9,			/* aes out */
+	10, 11,			/* spdif out */
+	12, 16,			/* adat out */
+	6, 7,			/* phone out */
+	-1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
+	0, 1, 2, 3, 4, 5, 6, 7,
+	8, 9, 10, 11, 12, 13, 14, 15,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
 struct hdspm_midi {
 	struct hdspm *hdspm;
 	int id;
@@ -430,6 +847,21 @@ struct hdspm_midi {
 	struct timer_list timer;
 	spinlock_t lock;
 	int pending;
+	int dataIn;
+	int statusIn;
+	int dataOut;
+	int statusOut;
+	int ie;
+	int irq;
+};
+
+struct hdspm_tco {
+	int input;
+	int framerate;
+	int wordclock;
+	int samplerate;
+	int pull;
+	int term; /* 0 = off, 1 = on */
 };
 
 struct hdspm {
@@ -441,21 +873,39 @@ struct hdspm {
 	char *card_name;	     /* for procinfo */
 	unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
 
-	unsigned char is_aes32;    /* indicates if card is AES32 */
+	uint8_t io_type;
 
-	int precise_ptr;	/* use precise pointers, to be tested */
 	int monitor_outs;	/* set up monitoring outs init flag */
 
 	u32 control_register;	/* cached value */
 	u32 control2_register;	/* cached value */
+	u32 settings_register;
 
-	struct hdspm_midi midi[2];
+	struct hdspm_midi midi[4];
 	struct tasklet_struct midi_tasklet;
 
 	size_t period_bytes;
-	unsigned char ss_channels;	/* channels of card in single speed */
-	unsigned char ds_channels;	/* Double Speed */
-	unsigned char qs_channels;	/* Quad Speed */
+	unsigned char ss_in_channels;
+	unsigned char ds_in_channels;
+	unsigned char qs_in_channels;
+	unsigned char ss_out_channels;
+	unsigned char ds_out_channels;
+	unsigned char qs_out_channels;
+
+	unsigned char max_channels_in;
+	unsigned char max_channels_out;
+
+	char *channel_map_in;
+	char *channel_map_out;
+
+	char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
+	char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
+
+	char **port_names_in;
+	char **port_names_out;
+
+	char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
+	char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
 
 	unsigned char *playback_buffer;	/* suitably aligned address */
 	unsigned char *capture_buffer;	/* suitably aligned address */
@@ -468,14 +918,13 @@ struct hdspm {
 	int last_internal_sample_rate;
 	int system_sample_rate;
 
-	char *channel_map;	/* channel map for DS and Quadspeed */
-
 	int dev;		/* Hardware vars... */
 	int irq;
 	unsigned long port;
 	void __iomem *iobase;
 
 	int irq_count;		/* for debug */
+	int midiPorts;
 
 	struct snd_card *card;	/* one card */
 	struct snd_pcm *pcm;		/* has one pcm */
@@ -487,28 +936,17 @@ struct hdspm {
 	struct snd_kcontrol *playback_mixer_ctls[HDSPM_MAX_CHANNELS];
 	/* but input to much, so not used */
 	struct snd_kcontrol *input_mixer_ctls[HDSPM_MAX_CHANNELS];
-	/* full mixer accessible over mixer ioctl or hwdep-device */
+	/* full mixer accessable over mixer ioctl or hwdep-device */
 	struct hdspm_mixer *mixer;
 
-};
+	struct hdspm_tco *tco;  /* NULL if no TCO detected */
 
-/* These tables map the ALSA channels 1..N to the channels that we
-   need to use in order to find the relevant channel buffer. RME
-   refer to this kind of mapping as between "the ADAT channel and
-   the DMA channel." We index it using the logical audio channel,
-   and the value is the DMA channel (i.e. channel buffer number)
-   where the data for that channel can be read/written from/to.
-*/
+	char **texts_autosync;
+	int texts_autosync_items;
+
+	cycles_t last_interrupt;
 
-static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
-   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, 57, 58, 59, 60, 61, 62, 63
+	struct hdspm_peak_rms peak_rms;
 };
 
 
@@ -532,11 +970,11 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
 static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
 					  struct hdspm * hdspm);
 
-static inline void snd_hdspm_initialize_midi_flush(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);
-static void hdspm_set_sgbuf(struct hdspm * hdspm,
+static inline void snd_hdspm_initialize_midi_flush(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);
+static void hdspm_set_sgbuf(struct hdspm *hdspm,
 			    struct snd_pcm_substream *substream,
 			     unsigned int reg, int channels);
 
@@ -550,7 +988,7 @@ static inline int HDSPM_bit2freq(int n)
 	return bit2freq_tab[n];
 }
 
-/* Write/read to/from HDSPM with Addresses in Bytes
+/* Write/read to/from HDSPM with Adresses in Bytes
    not words but only 32Bit writes are allowed */
 
 static inline void hdspm_write(struct hdspm * hdspm, unsigned int reg,
@@ -564,8 +1002,8 @@ static inline unsigned int hdspm_read(struct hdspm * hdspm, unsigned int reg)
 	return readl(hdspm->iobase + reg);
 }
 
-/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader 
-   mixer is write only on hardware so we have to cache him for read 
+/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
+   mixer is write only on hardware so we have to cache him for read
    each fader is a u32, but uses only the first 16 bit */
 
 static inline int hdspm_read_in_gain(struct hdspm * hdspm, unsigned int chan,
@@ -641,30 +1079,67 @@ static int snd_hdspm_use_is_exclusive(struct hdspm *hdspm)
 /* check for external sample rate */
 static int hdspm_external_sample_rate(struct hdspm *hdspm)
 {
-	if (hdspm->is_aes32) {
-		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
-		unsigned int timecode =
-			hdspm_read(hdspm, HDSPM_timecodeRegister);
+	unsigned int status, status2, timecode;
+	int syncref, rate = 0, rate_bits;
 
-		int syncref = hdspm_autosync_ref(hdspm);
+	switch (hdspm->io_type) {
+	case AES32:
+		status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+		status = hdspm_read(hdspm, HDSPM_statusRegister);
+		timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
+
+		syncref = hdspm_autosync_ref(hdspm);
 
 		if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
 				status & HDSPM_AES32_wcLock)
-			return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit)
-					      & 0xF);
+			return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
+
 		if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
-			syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
-			status2 & (HDSPM_LockAES >>
-			          (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
-			return HDSPM_bit2freq((timecode >>
-			  (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
+				syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
+				status2 & (HDSPM_LockAES >>
+				(syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
+			return HDSPM_bit2freq((timecode >> (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
 		return 0;
-	} else {
-		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
-		unsigned int rate_bits;
-		int rate = 0;
+		break;
+
+	case MADIface:
+		status = hdspm_read(hdspm, HDSPM_statusRegister);
+
+		if (!(status & HDSPM_madiLock)) {
+			rate = 0;  /* no lock */
+		} else {
+			switch (status & (HDSPM_status1_freqMask)) {
+			case HDSPM_status1_F_0*1:
+				rate = 32000; break;
+			case HDSPM_status1_F_0*2:
+				rate = 44100; break;
+			case HDSPM_status1_F_0*3:
+				rate = 48000; break;
+			case HDSPM_status1_F_0*4:
+				rate = 64000; break;
+			case HDSPM_status1_F_0*5:
+				rate = 88200; break;
+			case HDSPM_status1_F_0*6:
+				rate = 96000; break;
+			case HDSPM_status1_F_0*7:
+				rate = 128000; break;
+			case HDSPM_status1_F_0*8:
+				rate = 176400; break;
+			case HDSPM_status1_F_0*9:
+				rate = 192000; break;
+			default:
+				rate = 0; break;
+			}
+		}
+
+		break;
+
+	case MADI:
+	case AIO:
+	case RayDAT:
+		status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+		status = hdspm_read(hdspm, HDSPM_statusRegister);
+		rate = 0;
 
 		/* if wordclock has synced freq and wordclock is valid */
 		if ((status2 & HDSPM_wcLock) != 0 &&
@@ -672,6 +1147,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 
 			rate_bits = status2 & HDSPM_wcFreqMask;
 
+
 			switch (rate_bits) {
 			case HDSPM_wcFreq32:
 				rate = 32000;
@@ -691,7 +1167,6 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 			case HDSPM_wcFreq96:
 				rate = 96000;
 				break;
-				/* Quadspeed Bit missing ???? */
 			default:
 				rate = 0;
 				break;
@@ -702,10 +1177,10 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 		 * word has priority to MADI
 		 */
 		if (rate != 0 &&
-	            (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
+		(status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
 			return rate;
 
-		/* maby a madi input (which is taken if sel sync is madi) */
+		/* maybe a madi input (which is taken if sel sync is madi) */
 		if (status & HDSPM_madiLock) {
 			rate_bits = status & HDSPM_madiFreqMask;
 
@@ -742,36 +1217,35 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 				break;
 			}
 		}
-		return rate;
+		break;
 	}
+
+	return rate;
 }
 
 /* Latency function */
-static inline void hdspm_compute_period_size(struct hdspm * hdspm)
+static inline void hdspm_compute_period_size(struct hdspm *hdspm)
 {
-	hdspm->period_bytes =
-	    1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+	hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
 }
 
-static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm * hdspm)
+
+static snd_pcm_uframes_t hdspm_hw_pointer(struct hdspm *hdspm)
 {
 	int position;
 
 	position = hdspm_read(hdspm, HDSPM_statusRegister);
 
-	if (!hdspm->precise_ptr)
-		return (position & HDSPM_BufferID) ?
+	switch (hdspm->io_type) {
+	case RayDAT:
+	case AIO:
+		position &= HDSPM_BufferPositionMask;
+		position /= 4; /* Bytes per sample */
+		break;
+	default:
+		position = (position & HDSPM_BufferID) ?
 			(hdspm->period_bytes / 4) : 0;
-
-	/* hwpointer comes in bytes and is 64Bytes accurate (by docu since
-	   PCI Burst)
-	   i have experimented that it is at most 64 Byte to much for playing 
-	   so substraction of 64 byte should be ok for ALSA, but use it only
-	   for application where you know what you do since if you come to
-	   near with record pointer it can be a disaster */
-
-	position &= HDSPM_BufferPositionMask;
-	position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
+	}
 
 	return position;
 }
@@ -805,7 +1279,7 @@ static void hdspm_silence_playback(struct hdspm *hdspm)
 	}
 }
 
-static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
+static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
 {
 	int n;
 
@@ -829,21 +1303,53 @@ static int hdspm_set_interrupt_interval(struct hdspm * s, unsigned int frames)
 	return 0;
 }
 
+static u64 hdspm_calc_dds_value(struct hdspm *hdspm, u64 period)
+{
+	u64 freq_const;
+
+	if (period == 0)
+		return 0;
+
+	switch (hdspm->io_type) {
+	case MADI:
+	case AES32:
+		freq_const = 110069313433624ULL;
+		break;
+	case RayDAT:
+	case AIO:
+		freq_const = 104857600000000ULL;
+		break;
+	case MADIface:
+		freq_const = 131072000000000ULL;
+	}
+
+	return div_u64(freq_const, period);
+}
+
+
 static void hdspm_set_dds_value(struct hdspm *hdspm, int rate)
 {
 	u64 n;
-	
+
 	if (rate >= 112000)
 		rate /= 4;
 	else if (rate >= 56000)
 		rate /= 2;
 
-	/* RME says n = 104857600000000, but in the windows MADI driver, I see:
-//	return 104857600000000 / rate; // 100 MHz
-	return 110100480000000 / rate; // 105 MHz
-        */	   
-	/* n = 104857600000000ULL; */ /*  =  2^20 * 10^8 */
-	n = 110100480000000ULL;    /* Value checked for AES32 and MADI */
+	switch (hdspm->io_type) {
+	case MADIface:
+	  n = 131072000000000ULL;  /* 125 MHz */
+	  break;
+	case MADI:
+	case AES32:
+	  n = 110069313433624ULL;  /* 105 MHz */
+	  break;
+	case RayDAT:
+	case AIO:
+	  n = 104857600000000ULL;  /* 100 MHz */
+	  break;
+	}
+
 	n = div_u64(n, rate);
 	/* n should be less than 2^32 for being written to FREQ register */
 	snd_BUG_ON(n >> 32);
@@ -864,13 +1370,13 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
 
 	if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
 
-	        /* SLAVE --- */ 
+		/* SLAVE --- */
 		if (called_internally) {
 
-        	  /* request from ctl or card initialization 
-	             just make a warning an remember setting 
-		     for future master mode switching */
-    
+			/* request from ctl or card initialization
+			   just make a warning an remember setting
+			   for future master mode switching */
+
 			snd_printk(KERN_WARNING "HDSPM: "
 				   "Warning: device is not running "
 				   "as a clock master.\n");
@@ -907,7 +1413,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
 
 	   Note that a similar but essentially insoluble problem exists for
 	   externally-driven rate changes. All we can do is to flag rate
-	   changes in the read/write routines.  
+	   changes in the read/write routines.
 	 */
 
 	if (current_rate <= 48000)
@@ -975,16 +1481,35 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
 	/* For AES32, need to set DDS value in FREQ register
 	   For MADI, also apparently */
 	hdspm_set_dds_value(hdspm, rate);
-	
-	if (hdspm->is_aes32 && rate != current_rate)
+
+	if (AES32 == hdspm->io_type && rate != current_rate)
 		hdspm_write(hdspm, HDSPM_eeprom_wr, 0);
-	
-	/* For AES32 and for MADI (at least rev 204), channel_map needs to
-	 * always be channel_map_madi_ss, whatever the sample rate */
-	hdspm->channel_map = channel_map_madi_ss;
 
 	hdspm->system_sample_rate = rate;
 
+	if (rate <= 48000) {
+		hdspm->channel_map_in = hdspm->channel_map_in_ss;
+		hdspm->channel_map_out = hdspm->channel_map_out_ss;
+		hdspm->max_channels_in = hdspm->ss_in_channels;
+		hdspm->max_channels_out = hdspm->ss_out_channels;
+		hdspm->port_names_in = hdspm->port_names_in_ss;
+		hdspm->port_names_out = hdspm->port_names_out_ss;
+	} else if (rate <= 96000) {
+		hdspm->channel_map_in = hdspm->channel_map_in_ds;
+		hdspm->channel_map_out = hdspm->channel_map_out_ds;
+		hdspm->max_channels_in = hdspm->ds_in_channels;
+		hdspm->max_channels_out = hdspm->ds_out_channels;
+		hdspm->port_names_in = hdspm->port_names_in_ds;
+		hdspm->port_names_out = hdspm->port_names_out_ds;
+	} else {
+		hdspm->channel_map_in = hdspm->channel_map_in_qs;
+		hdspm->channel_map_out = hdspm->channel_map_out_qs;
+		hdspm->max_channels_in = hdspm->qs_in_channels;
+		hdspm->max_channels_out = hdspm->qs_out_channels;
+		hdspm->port_names_in = hdspm->port_names_in_qs;
+		hdspm->port_names_out = hdspm->port_names_out_qs;
+	}
+
 	if (not_set != 0)
 		return -1;
 
@@ -1019,39 +1544,26 @@ static inline unsigned char snd_hdspm_midi_read_byte (struct hdspm *hdspm,
 						      int id)
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
-	if (id)
-		return hdspm_read(hdspm, HDSPM_midiDataIn1);
-	else
-		return hdspm_read(hdspm, HDSPM_midiDataIn0);
+	return hdspm_read(hdspm, hdspm->midi[id].dataIn);
 }
 
 static inline void snd_hdspm_midi_write_byte (struct hdspm *hdspm, int id,
 					      int val)
 {
 	/* the hardware already does the relevant bit-mask with 0xff */
-	if (id)
-		hdspm_write(hdspm, HDSPM_midiDataOut1, val);
-	else
-		hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+	return hdspm_write(hdspm, hdspm->midi[id].dataOut, val);
 }
 
 static inline int snd_hdspm_midi_input_available (struct hdspm *hdspm, int id)
 {
-	if (id)
-		return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
-	else
-		return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
+	return hdspm_read(hdspm, hdspm->midi[id].statusIn) & 0xFF;
 }
 
 static inline int snd_hdspm_midi_output_possible (struct hdspm *hdspm, int id)
 {
 	int fifo_bytes_used;
 
-	if (id)
-		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1);
-	else
-		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0);
-	fifo_bytes_used &= 0xff;
+	fifo_bytes_used = hdspm_read(hdspm, hdspm->midi[id].statusOut) & 0xFF;
 
 	if (fifo_bytes_used < 128)
 		return  128 - fifo_bytes_used;
@@ -1074,7 +1586,7 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
 	unsigned char buf[128];
 
 	/* Output is not interrupt driven */
-		
+
 	spin_lock_irqsave (&hmidi->lock, flags);
 	if (hmidi->output &&
 	    !snd_rawmidi_transmit_empty (hmidi->output)) {
@@ -1083,11 +1595,11 @@ static int snd_hdspm_midi_output_write (struct hdspm_midi *hmidi)
 		if (n_pending > 0) {
 			if (n_pending > (int)sizeof (buf))
 				n_pending = sizeof (buf);
-		
+
 			to_write = snd_rawmidi_transmit (hmidi->output, buf,
 							 n_pending);
 			if (to_write > 0) {
-				for (i = 0; i < to_write; ++i) 
+				for (i = 0; i < to_write; ++i)
 					snd_hdspm_midi_write_byte (hmidi->hdspm,
 								   hmidi->id,
 								   buf[i]);
@@ -1127,12 +1639,11 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
 		}
 	}
 	hmidi->pending = 0;
-	if (hmidi->id)
-		hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
-	else
-		hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
+
+	hmidi->hdspm->control_register |= hmidi->ie;
 	hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
 		    hmidi->hdspm->control_register);
+
 	spin_unlock_irqrestore (&hmidi->lock, flags);
 	return snd_hdspm_midi_output_write (hmidi);
 }
@@ -1143,20 +1654,18 @@ snd_hdspm_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
 	struct hdspm *hdspm;
 	struct hdspm_midi *hmidi;
 	unsigned long flags;
-	u32 ie;
 
 	hmidi = substream->rmidi->private_data;
 	hdspm = hmidi->hdspm;
-	ie = hmidi->id ?
-		HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
+
 	spin_lock_irqsave (&hdspm->lock, flags);
 	if (up) {
-		if (!(hdspm->control_register & ie)) {
+		if (!(hdspm->control_register & hmidi->ie)) {
 			snd_hdspm_flush_midi_input (hdspm, hmidi->id);
-			hdspm->control_register |= ie;
+			hdspm->control_register |= hmidi->ie;
 		}
 	} else {
-		hdspm->control_register &= ~ie;
+		hdspm->control_register &= ~hmidi->ie;
 	}
 
 	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
@@ -1167,14 +1676,14 @@ static void snd_hdspm_midi_output_timer(unsigned long data)
 {
 	struct hdspm_midi *hmidi = (struct hdspm_midi *) data;
 	unsigned long flags;
-	
+
 	snd_hdspm_midi_output_write(hmidi);
 	spin_lock_irqsave (&hmidi->lock, flags);
 
 	/* this does not bump hmidi->istimer, because the
 	   kernel automatically removed the timer when it
 	   expired, and we are now adding it back, thus
-	   leaving istimer wherever it was set before.  
+	   leaving istimer wherever it was set before.
 	*/
 
 	if (hmidi->istimer) {
@@ -1288,22 +1797,103 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card,
 	hdspm->midi[id].hdspm = hdspm;
 	spin_lock_init (&hdspm->midi[id].lock);
 
-	sprintf (buf, "%s MIDI %d", card->shortname, id+1);
-	err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi);
-	if (err < 0)
-		return err;
+	if (0 == id) {
+		if (MADIface == hdspm->io_type) {
+			/* MIDI-over-MADI on HDSPe MADIface */
+			hdspm->midi[0].dataIn = HDSPM_midiDataIn2;
+			hdspm->midi[0].statusIn = HDSPM_midiStatusIn2;
+			hdspm->midi[0].dataOut = HDSPM_midiDataOut2;
+			hdspm->midi[0].statusOut = HDSPM_midiStatusOut2;
+			hdspm->midi[0].ie = HDSPM_Midi2InterruptEnable;
+			hdspm->midi[0].irq = HDSPM_midi2IRQPending;
+		} else {
+			hdspm->midi[0].dataIn = HDSPM_midiDataIn0;
+			hdspm->midi[0].statusIn = HDSPM_midiStatusIn0;
+			hdspm->midi[0].dataOut = HDSPM_midiDataOut0;
+			hdspm->midi[0].statusOut = HDSPM_midiStatusOut0;
+			hdspm->midi[0].ie = HDSPM_Midi0InterruptEnable;
+			hdspm->midi[0].irq = HDSPM_midi0IRQPending;
+		}
+	} else if (1 == id) {
+		hdspm->midi[1].dataIn = HDSPM_midiDataIn1;
+		hdspm->midi[1].statusIn = HDSPM_midiStatusIn1;
+		hdspm->midi[1].dataOut = HDSPM_midiDataOut1;
+		hdspm->midi[1].statusOut = HDSPM_midiStatusOut1;
+		hdspm->midi[1].ie = HDSPM_Midi1InterruptEnable;
+		hdspm->midi[1].irq = HDSPM_midi1IRQPending;
+	} else if ((2 == id) && (MADI == hdspm->io_type)) {
+		/* MIDI-over-MADI on HDSPe MADI */
+		hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
+		hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
+		hdspm->midi[2].dataOut = HDSPM_midiDataOut2;
+		hdspm->midi[2].statusOut = HDSPM_midiStatusOut2;
+		hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
+		hdspm->midi[2].irq = HDSPM_midi2IRQPending;
+	} else if (2 == id) {
+		/* TCO MTC, read only */
+		hdspm->midi[2].dataIn = HDSPM_midiDataIn2;
+		hdspm->midi[2].statusIn = HDSPM_midiStatusIn2;
+		hdspm->midi[2].dataOut = -1;
+		hdspm->midi[2].statusOut = -1;
+		hdspm->midi[2].ie = HDSPM_Midi2InterruptEnable;
+		hdspm->midi[2].irq = HDSPM_midi2IRQPendingAES;
+	} else if (3 == id) {
+		/* TCO MTC on HDSPe MADI */
+		hdspm->midi[3].dataIn = HDSPM_midiDataIn3;
+		hdspm->midi[3].statusIn = HDSPM_midiStatusIn3;
+		hdspm->midi[3].dataOut = -1;
+		hdspm->midi[3].statusOut = -1;
+		hdspm->midi[3].ie = HDSPM_Midi3InterruptEnable;
+		hdspm->midi[3].irq = HDSPM_midi3IRQPending;
+	}
+
+	if ((id < 2) || ((2 == id) && ((MADI == hdspm->io_type) ||
+					(MADIface == hdspm->io_type)))) {
+		if ((id == 0) && (MADIface == hdspm->io_type)) {
+			sprintf(buf, "%s MIDIoverMADI", card->shortname);
+		} else if ((id == 2) && (MADI == hdspm->io_type)) {
+			sprintf(buf, "%s MIDIoverMADI", card->shortname);
+		} else {
+			sprintf(buf, "%s MIDI %d", card->shortname, id+1);
+		}
+		err = snd_rawmidi_new(card, buf, id, 1, 1,
+				&hdspm->midi[id].rmidi);
+		if (err < 0)
+			return err;
+
+		sprintf(hdspm->midi[id].rmidi->name, "%s MIDI %d",
+				card->id, id+1);
+		hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
+
+		snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
+				SNDRV_RAWMIDI_STREAM_OUTPUT,
+				&snd_hdspm_midi_output);
+		snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
+				SNDRV_RAWMIDI_STREAM_INPUT,
+				&snd_hdspm_midi_input);
+
+		hdspm->midi[id].rmidi->info_flags |=
+			SNDRV_RAWMIDI_INFO_OUTPUT |
+			SNDRV_RAWMIDI_INFO_INPUT |
+			SNDRV_RAWMIDI_INFO_DUPLEX;
+	} else {
+		/* TCO MTC, read only */
+		sprintf(buf, "%s MTC %d", card->shortname, id+1);
+		err = snd_rawmidi_new(card, buf, id, 1, 1,
+				&hdspm->midi[id].rmidi);
+		if (err < 0)
+			return err;
 
-	sprintf(hdspm->midi[id].rmidi->name, "HDSPM MIDI %d", id+1);
-	hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
+		sprintf(hdspm->midi[id].rmidi->name,
+				"%s MTC %d", card->id, id+1);
+		hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
 
-	snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
-			    &snd_hdspm_midi_output);
-	snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
-			    &snd_hdspm_midi_input);
+		snd_rawmidi_set_ops(hdspm->midi[id].rmidi,
+				SNDRV_RAWMIDI_STREAM_INPUT,
+				&snd_hdspm_midi_input);
 
-	hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
-		SNDRV_RAWMIDI_INFO_INPUT |
-		SNDRV_RAWMIDI_INFO_DUPLEX;
+		hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+	}
 
 	return 0;
 }
@@ -1312,12 +1902,15 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card,
 static void hdspm_midi_tasklet(unsigned long arg)
 {
 	struct hdspm *hdspm = (struct hdspm *)arg;
-	
-	if (hdspm->midi[0].pending)
-		snd_hdspm_midi_input_read (&hdspm->midi[0]);
-	if (hdspm->midi[1].pending)
-		snd_hdspm_midi_input_read (&hdspm->midi[1]);
-} 
+	int i = 0;
+
+	while (i < hdspm->midiPorts) {
+		if (hdspm->midi[i].pending)
+			snd_hdspm_midi_input_read(&hdspm->midi[i]);
+
+		i++;
+	}
+}
 
 
 /*-----------------------------------------------------------------------------
@@ -1326,6 +1919,22 @@ static void hdspm_midi_tasklet(unsigned long arg)
 
 /* get the system sample rate which is set */
 
+
+/**
+ * Calculate the real sample rate from the
+ * current DDS value.
+ **/
+static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
+{
+	unsigned int period, rate;
+
+	period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
+	rate = hdspm_calc_dds_value(hdspm, period);
+
+	return rate;
+}
+
+
 #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -1340,112 +1949,274 @@ static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
+	uinfo->value.integer.min = 27000;
+	uinfo->value.integer.max = 207000;
+	uinfo->value.integer.step = 1;
 	return 0;
 }
 
+
 static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_value *
 					    ucontrol)
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
+	ucontrol->value.integer.value[0] = hdspm_get_system_sample_rate(hdspm);
 	return 0;
 }
 
+
+/**
+ * Returns the WordClock sample rate class for the given card.
+ **/
+static int hdspm_get_wc_sample_rate(struct hdspm *hdspm)
+{
+	int status;
+
+	switch (hdspm->io_type) {
+	case RayDAT:
+	case AIO:
+		status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
+		return (status >> 16) & 0xF;
+		break;
+	default:
+		break;
+	}
+
+
+	return 0;
+}
+
+
+/**
+ * Returns the TCO sample rate class for the given card.
+ **/
+static int hdspm_get_tco_sample_rate(struct hdspm *hdspm)
+{
+	int status;
+
+	if (hdspm->tco) {
+		switch (hdspm->io_type) {
+		case RayDAT:
+		case AIO:
+			status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
+			return (status >> 20) & 0xF;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+ * Returns the SYNC_IN sample rate class for the given card.
+ **/
+static int hdspm_get_sync_in_sample_rate(struct hdspm *hdspm)
+{
+	int status;
+
+	if (hdspm->tco) {
+		switch (hdspm->io_type) {
+		case RayDAT:
+		case AIO:
+			status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
+			return (status >> 12) & 0xF;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+ * Returns the sample rate class for input source <idx> for
+ * 'new style' cards like the AIO and RayDAT.
+ **/
+static int hdspm_get_s1_sample_rate(struct hdspm *hdspm, unsigned int idx)
+{
+	int status = hdspm_read(hdspm, HDSPM_RD_STATUS_2);
+
+	return (status >> (idx*4)) & 0xF;
+}
+
+
+
 #define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_autosync_sample_rate, \
-  .get = snd_hdspm_get_autosync_sample_rate \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.private_value = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READ, \
+	.info = snd_hdspm_info_autosync_sample_rate, \
+	.get = snd_hdspm_get_autosync_sample_rate \
 }
 
+
 static int snd_hdspm_info_autosync_sample_rate(struct snd_kcontrol *kcontrol,
 					       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "32000", "44100", "48000",
-		"64000", "88200", "96000",
-		"128000", "176400", "192000",
-		"None"
-	};
 	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;
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
 	strcpy(uinfo->value.enumerated.name,
-	       texts[uinfo->value.enumerated.item]);
+			texts_freq[uinfo->value.enumerated.item]);
 	return 0;
 }
 
+
 static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
 					      struct snd_ctl_elem_value *
 					      ucontrol)
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	switch (hdspm_external_sample_rate(hdspm)) {
-	case 32000:
-		ucontrol->value.enumerated.item[0] = 0;
-		break;
-	case 44100:
-		ucontrol->value.enumerated.item[0] = 1;
-		break;
-	case 48000:
-		ucontrol->value.enumerated.item[0] = 2;
-		break;
-	case 64000:
-		ucontrol->value.enumerated.item[0] = 3;
-		break;
-	case 88200:
-		ucontrol->value.enumerated.item[0] = 4;
-		break;
-	case 96000:
-		ucontrol->value.enumerated.item[0] = 5;
-		break;
-	case 128000:
-		ucontrol->value.enumerated.item[0] = 6;
-		break;
-	case 176400:
-		ucontrol->value.enumerated.item[0] = 7;
-		break;
-	case 192000:
-		ucontrol->value.enumerated.item[0] = 8;
-		break;
+	switch (hdspm->io_type) {
+	case RayDAT:
+		switch (kcontrol->private_value) {
+		case 0:
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_wc_sample_rate(hdspm);
+			break;
+		case 7:
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_tco_sample_rate(hdspm);
+			break;
+		case 8:
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_sync_in_sample_rate(hdspm);
+			break;
+		default:
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_s1_sample_rate(hdspm,
+						kcontrol->private_value-1);
+		}
+
+	case AIO:
+		switch (kcontrol->private_value) {
+		case 0: /* WC */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_wc_sample_rate(hdspm);
+			break;
+		case 4: /* TCO */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_tco_sample_rate(hdspm);
+			break;
+		case 5: /* SYNC_IN */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_sync_in_sample_rate(hdspm);
+			break;
+		default:
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_s1_sample_rate(hdspm,
+						ucontrol->id.index-1);
+		}
+
+	case AES32:
+
+		switch (kcontrol->private_value) {
+		case 0: /* WC */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_wc_sample_rate(hdspm);
+			break;
+		case 9: /* TCO */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_tco_sample_rate(hdspm);
+			break;
+		case 10: /* SYNC_IN */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_sync_in_sample_rate(hdspm);
+			break;
+		default: /* AES1 to AES8 */
+			ucontrol->value.enumerated.item[0] =
+				hdspm_get_s1_sample_rate(hdspm,
+						kcontrol->private_value-1);
+			break;
 
+		}
 	default:
-		ucontrol->value.enumerated.item[0] = 9;
+		break;
 	}
+
 	return 0;
 }
 
+
 #define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_system_clock_mode, \
-  .get = snd_hdspm_get_system_clock_mode, \
-}
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_system_clock_mode, \
+	.get = snd_hdspm_get_system_clock_mode, \
+	.put = snd_hdspm_put_system_clock_mode, \
+}
+
+
+/**
+ * Returns the system clock mode for the given card.
+ * @returns 0 - master, 1 - slave
+ **/
+static int hdspm_system_clock_mode(struct hdspm *hdspm)
+{
+	switch (hdspm->io_type) {
+	case AIO:
+	case RayDAT:
+		if (hdspm->settings_register & HDSPM_c0Master)
+			return 0;
+		break;
+
+	default:
+		if (hdspm->control_register & HDSPM_ClockModeMaster)
+			return 0;
+	}
 
+	return 1;
+}
 
 
-static int hdspm_system_clock_mode(struct hdspm * hdspm)
+/**
+ * Sets the system clock mode.
+ * @param mode 0 - master, 1 - slave
+ **/
+static void hdspm_set_system_clock_mode(struct hdspm *hdspm, int mode)
 {
-        /* Always reflect the hardware info, rme is never wrong !!!! */
+	switch (hdspm->io_type) {
+	case AIO:
+	case RayDAT:
+		if (0 == mode)
+			hdspm->settings_register |= HDSPM_c0Master;
+		else
+			hdspm->settings_register &= ~HDSPM_c0Master;
 
-	if (hdspm->control_register & HDSPM_ClockModeMaster)
-		return 0;
-	return 1;
+		hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
+		break;
+
+	default:
+		if (0 == mode)
+			hdspm->control_register |= HDSPM_ClockModeMaster;
+		else
+			hdspm->control_register &= ~HDSPM_ClockModeMaster;
+
+		hdspm_write(hdspm, HDSPM_controlRegister,
+				hdspm->control_register);
+	}
 }
 
+
 static int snd_hdspm_info_system_clock_mode(struct snd_kcontrol *kcontrol,
 					    struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "Master", "Slave" };
+	static char *texts[] = { "Master", "AutoSync" };
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
@@ -1463,96 +2234,83 @@ static int snd_hdspm_get_system_clock_mode(struct snd_kcontrol *kcontrol,
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	ucontrol->value.enumerated.item[0] =
-	    hdspm_system_clock_mode(hdspm);
+	ucontrol->value.enumerated.item[0] = hdspm_system_clock_mode(hdspm);
 	return 0;
 }
 
-#define HDSPM_CLOCK_SOURCE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_clock_source, \
-  .get = snd_hdspm_get_clock_source, \
-  .put = snd_hdspm_put_clock_source \
+static int snd_hdspm_put_system_clock_mode(struct snd_kcontrol *kcontrol,
+					   struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+
+	val = ucontrol->value.enumerated.item[0];
+	if (val < 0)
+		val = 0;
+	else if (val > 1)
+		val = 1;
+
+	hdspm_set_system_clock_mode(hdspm, val);
+
+	return 0;
+}
+
+
+#define HDSPM_INTERNAL_CLOCK(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.info = snd_hdspm_info_clock_source, \
+	.get = snd_hdspm_get_clock_source, \
+	.put = snd_hdspm_put_clock_source \
 }
 
+
 static int hdspm_clock_source(struct hdspm * hdspm)
 {
-	if (hdspm->control_register & HDSPM_ClockModeMaster) {
-		switch (hdspm->system_sample_rate) {
-		case 32000:
-			return 1;
-		case 44100:
-			return 2;
-		case 48000:
-			return 3;
-		case 64000:
-			return 4;
-		case 88200:
-			return 5;
-		case 96000:
-			return 6;
-		case 128000:
-			return 7;
-		case 176400:
-			return 8;
-		case 192000:
-			return 9;
-		default:
-			return 3;
-		}
-	} else {
-		return 0;
+	switch (hdspm->system_sample_rate) {
+	case 32000: return 0;
+	case 44100: return 1;
+	case 48000: return 2;
+	case 64000: return 3;
+	case 88200: return 4;
+	case 96000: return 5;
+	case 128000: return 6;
+	case 176400: return 7;
+	case 192000: return 8;
 	}
+
+	return -1;
 }
 
 static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
 {
 	int rate;
 	switch (mode) {
-
-	case HDSPM_CLOCK_SOURCE_AUTOSYNC:
-		if (hdspm_external_sample_rate(hdspm) != 0) {
-			hdspm->control_register &= ~HDSPM_ClockModeMaster;
-			hdspm_write(hdspm, HDSPM_controlRegister,
-				    hdspm->control_register);
-			return 0;
-		}
-		return -1;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
-		rate = 32000;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
-		rate = 44100;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
-		rate = 48000;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
-		rate = 64000;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
-		rate = 88200;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
-		rate = 96000;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
-		rate = 128000;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
-		rate = 176400;
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
-		rate = 192000;
-		break;
-
+	case 0:
+		rate = 32000; break;
+	case 1:
+		rate = 44100; break;
+	case 2:
+		rate = 48000; break;
+	case 3:
+		rate = 64000; break;
+	case 4:
+		rate = 88200; break;
+	case 5:
+		rate = 96000; break;
+	case 6:
+		rate = 128000; break;
+	case 7:
+		rate = 176400; break;
+	case 8:
+		rate = 192000; break;
 	default:
-		rate = 44100;
+		rate = 48000;
 	}
-	hdspm->control_register |= HDSPM_ClockModeMaster;
-	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 	hdspm_set_rate(hdspm, rate, 1);
 	return 0;
 }
@@ -1560,25 +2318,16 @@ static int hdspm_set_clock_source(struct hdspm * hdspm, int mode)
 static int snd_hdspm_info_clock_source(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
-	static char *texts[] = { "AutoSync",
-		"Internal 32.0 kHz", "Internal 44.1 kHz",
-		    "Internal 48.0 kHz",
-		"Internal 64.0 kHz", "Internal 88.2 kHz",
-		    "Internal 96.0 kHz",
-		"Internal 128.0 kHz", "Internal 176.4 kHz",
-		    "Internal 192.0 kHz"
-	};
-
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 10;
+	uinfo->value.enumerated.items = 9;
 
 	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]);
+	       texts_freq[uinfo->value.enumerated.item+1]);
 
 	return 0;
 }
@@ -1615,134 +2364,301 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-#define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_pref_sync_ref, \
-  .get = snd_hdspm_get_pref_sync_ref, \
-  .put = snd_hdspm_put_pref_sync_ref \
-}
 
+#define HDSPM_PREF_SYNC_REF(xname, xindex) \
+{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+			SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_pref_sync_ref, \
+	.get = snd_hdspm_get_pref_sync_ref, \
+	.put = snd_hdspm_put_pref_sync_ref \
+}
+
+
+/**
+ * Returns the current preferred sync reference setting.
+ * The semantics of the return value are depending on the
+ * card, please see the comments for clarification.
+ **/
 static int hdspm_pref_sync_ref(struct hdspm * hdspm)
 {
-	/* Notice that this looks at the requested sync source,
-	   not the one actually in use.
-	 */
-	if (hdspm->is_aes32) {
+	switch (hdspm->io_type) {
+	case AES32:
 		switch (hdspm->control_register & HDSPM_SyncRefMask) {
-		/* number gives AES index, except for 0 which
-		   corresponds to WordClock */
-		case 0: return 0;
-		case HDSPM_SyncRef0: return 1;
-		case HDSPM_SyncRef1: return 2;
-		case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
-		case HDSPM_SyncRef2: return 4;
-		case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
-		case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
-		case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
-		case HDSPM_SyncRef3: return 8;
+		case 0: return 0;  /* WC */
+		case HDSPM_SyncRef0: return 1; /* AES 1 */
+		case HDSPM_SyncRef1: return 2; /* AES 2 */
+		case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3; /* AES 3 */
+		case HDSPM_SyncRef2: return 4; /* AES 4 */
+		case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5; /* AES 5 */
+		case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6; /* AES 6 */
+		case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0:
+						    return 7; /* AES 7 */
+		case HDSPM_SyncRef3: return 8; /* AES 8 */
+		case HDSPM_SyncRef3+HDSPM_SyncRef0: return 9; /* TCO */
 		}
-	} else {
-		switch (hdspm->control_register & HDSPM_SyncRefMask) {
-		case HDSPM_SyncRef_Word:
-			return HDSPM_SYNC_FROM_WORD;
-		case HDSPM_SyncRef_MADI:
-			return HDSPM_SYNC_FROM_MADI;
+		break;
+
+	case MADI:
+	case MADIface:
+		if (hdspm->tco) {
+			switch (hdspm->control_register & HDSPM_SyncRefMask) {
+			case 0: return 0;  /* WC */
+			case HDSPM_SyncRef0: return 1;  /* MADI */
+			case HDSPM_SyncRef1: return 2;  /* TCO */
+			case HDSPM_SyncRef1+HDSPM_SyncRef0:
+					     return 3;  /* SYNC_IN */
+			}
+		} else {
+			switch (hdspm->control_register & HDSPM_SyncRefMask) {
+			case 0: return 0;  /* WC */
+			case HDSPM_SyncRef0: return 1;  /* MADI */
+			case HDSPM_SyncRef1+HDSPM_SyncRef0:
+					     return 2;  /* SYNC_IN */
+			}
+		}
+		break;
+
+	case RayDAT:
+		if (hdspm->tco) {
+			switch ((hdspm->settings_register &
+				HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
+			case 0: return 0;  /* WC */
+			case 3: return 1;  /* ADAT 1 */
+			case 4: return 2;  /* ADAT 2 */
+			case 5: return 3;  /* ADAT 3 */
+			case 6: return 4;  /* ADAT 4 */
+			case 1: return 5;  /* AES */
+			case 2: return 6;  /* SPDIF */
+			case 9: return 7;  /* TCO */
+			case 10: return 8; /* SYNC_IN */
+			}
+		} else {
+			switch ((hdspm->settings_register &
+				HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
+			case 0: return 0;  /* WC */
+			case 3: return 1;  /* ADAT 1 */
+			case 4: return 2;  /* ADAT 2 */
+			case 5: return 3;  /* ADAT 3 */
+			case 6: return 4;  /* ADAT 4 */
+			case 1: return 5;  /* AES */
+			case 2: return 6;  /* SPDIF */
+			case 10: return 7; /* SYNC_IN */
+			}
 		}
+
+		break;
+
+	case AIO:
+		if (hdspm->tco) {
+			switch ((hdspm->settings_register &
+				HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
+			case 0: return 0;  /* WC */
+			case 3: return 1;  /* ADAT */
+			case 1: return 2;  /* AES */
+			case 2: return 3;  /* SPDIF */
+			case 9: return 4;  /* TCO */
+			case 10: return 5; /* SYNC_IN */
+			}
+		} else {
+			switch ((hdspm->settings_register &
+				HDSPM_c0_SyncRefMask) / HDSPM_c0_SyncRef0) {
+			case 0: return 0;  /* WC */
+			case 3: return 1;  /* ADAT */
+			case 1: return 2;  /* AES */
+			case 2: return 3;  /* SPDIF */
+			case 10: return 4; /* SYNC_IN */
+			}
+		}
+
+		break;
 	}
 
-	return HDSPM_SYNC_FROM_WORD;
+	return -1;
 }
 
+
+/**
+ * Set the preferred sync reference to <pref>. The semantics
+ * of <pref> are depending on the card type, see the comments
+ * for clarification.
+ **/
 static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
 {
-	hdspm->control_register &= ~HDSPM_SyncRefMask;
+	int p = 0;
 
-	if (hdspm->is_aes32) {
-		switch (pref) {
-		case 0:
-		       hdspm->control_register |= 0;
-		       break;
-		case 1:
-		       hdspm->control_register |= HDSPM_SyncRef0;
-		       break;
-		case 2:
-		       hdspm->control_register |= HDSPM_SyncRef1;
-		       break;
-		case 3:
-		       hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
-		       break;
-		case 4:
-		       hdspm->control_register |= HDSPM_SyncRef2;
-		       break;
-		case 5:
-		       hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
-		       break;
-		case 6:
-		       hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
-		       break;
-		case 7:
-		       hdspm->control_register |=
-			       HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
-		       break;
-		case 8:
-		       hdspm->control_register |= HDSPM_SyncRef3;
-		       break;
-		default:
-		       return -1;
-		}
-	} else {
+	switch (hdspm->io_type) {
+	case AES32:
+		hdspm->control_register &= ~HDSPM_SyncRefMask;
 		switch (pref) {
-		case HDSPM_SYNC_FROM_MADI:
-			hdspm->control_register |= HDSPM_SyncRef_MADI;
+		case 0: /* WC  */
+			break;
+		case 1: /* AES 1 */
+			hdspm->control_register |= HDSPM_SyncRef0;
+			break;
+		case 2: /* AES 2 */
+			hdspm->control_register |= HDSPM_SyncRef1;
+			break;
+		case 3: /* AES 3 */
+			hdspm->control_register |=
+				HDSPM_SyncRef1+HDSPM_SyncRef0;
+			break;
+		case 4: /* AES 4 */
+			hdspm->control_register |= HDSPM_SyncRef2;
+			break;
+		case 5: /* AES 5 */
+			hdspm->control_register |=
+				HDSPM_SyncRef2+HDSPM_SyncRef0;
+			break;
+		case 6: /* AES 6 */
+			hdspm->control_register |=
+				HDSPM_SyncRef2+HDSPM_SyncRef1;
+			break;
+		case 7: /* AES 7 */
+			hdspm->control_register |=
+				HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
 			break;
-		case HDSPM_SYNC_FROM_WORD:
-			hdspm->control_register |= HDSPM_SyncRef_Word;
+		case 8: /* AES 8 */
+			hdspm->control_register |= HDSPM_SyncRef3;
+			break;
+		case 9: /* TCO */
+			hdspm->control_register |=
+				HDSPM_SyncRef3+HDSPM_SyncRef0;
 			break;
 		default:
 			return -1;
 		}
+
+		break;
+
+	case MADI:
+	case MADIface:
+		hdspm->control_register &= ~HDSPM_SyncRefMask;
+		if (hdspm->tco) {
+			switch (pref) {
+			case 0: /* WC */
+				break;
+			case 1: /* MADI */
+				hdspm->control_register |= HDSPM_SyncRef0;
+				break;
+			case 2: /* TCO */
+				hdspm->control_register |= HDSPM_SyncRef1;
+				break;
+			case 3: /* SYNC_IN */
+				hdspm->control_register |=
+					HDSPM_SyncRef0+HDSPM_SyncRef1;
+				break;
+			default:
+				return -1;
+			}
+		} else {
+			switch (pref) {
+			case 0: /* WC */
+				break;
+			case 1: /* MADI */
+				hdspm->control_register |= HDSPM_SyncRef0;
+				break;
+			case 2: /* SYNC_IN */
+				hdspm->control_register |=
+					HDSPM_SyncRef0+HDSPM_SyncRef1;
+				break;
+			default:
+				return -1;
+			}
+		}
+
+		break;
+
+	case RayDAT:
+		if (hdspm->tco) {
+			switch (pref) {
+			case 0: p = 0; break;  /* WC */
+			case 1: p = 3; break;  /* ADAT 1 */
+			case 2: p = 4; break;  /* ADAT 2 */
+			case 3: p = 5; break;  /* ADAT 3 */
+			case 4: p = 6; break;  /* ADAT 4 */
+			case 5: p = 1; break;  /* AES */
+			case 6: p = 2; break;  /* SPDIF */
+			case 7: p = 9; break;  /* TCO */
+			case 8: p = 10; break; /* SYNC_IN */
+			default: return -1;
+			}
+		} else {
+			switch (pref) {
+			case 0: p = 0; break;  /* WC */
+			case 1: p = 3; break;  /* ADAT 1 */
+			case 2: p = 4; break;  /* ADAT 2 */
+			case 3: p = 5; break;  /* ADAT 3 */
+			case 4: p = 6; break;  /* ADAT 4 */
+			case 5: p = 1; break;  /* AES */
+			case 6: p = 2; break;  /* SPDIF */
+			case 7: p = 10; break; /* SYNC_IN */
+			default: return -1;
+			}
+		}
+		break;
+
+	case AIO:
+		if (hdspm->tco) {
+			switch (pref) {
+			case 0: p = 0; break;  /* WC */
+			case 1: p = 3; break;  /* ADAT */
+			case 2: p = 1; break;  /* AES */
+			case 3: p = 2; break;  /* SPDIF */
+			case 4: p = 9; break;  /* TCO */
+			case 5: p = 10; break; /* SYNC_IN */
+			default: return -1;
+			}
+		} else {
+			switch (pref) {
+			case 0: p = 0; break;  /* WC */
+			case 1: p = 3; break;  /* ADAT */
+			case 2: p = 1; break;  /* AES */
+			case 3: p = 2; break;  /* SPDIF */
+			case 4: p = 10; break; /* SYNC_IN */
+			default: return -1;
+			}
+		}
+		break;
 	}
-	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	switch (hdspm->io_type) {
+	case RayDAT:
+	case AIO:
+		hdspm->settings_register &= ~HDSPM_c0_SyncRefMask;
+		hdspm->settings_register |= HDSPM_c0_SyncRef0 * p;
+		hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
+		break;
+
+	case MADI:
+	case MADIface:
+	case AES32:
+		hdspm_write(hdspm, HDSPM_controlRegister,
+				hdspm->control_register);
+	}
+
 	return 0;
 }
 
+
 static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_info *uinfo)
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	if (hdspm->is_aes32) {
-		static char *texts[] = { "Word", "AES1", "AES2", "AES3",
-			"AES4", "AES5",	"AES6", "AES7", "AES8" };
-
-		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-		uinfo->count = 1;
-
-		uinfo->value.enumerated.items = 9;
-
-		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]);
-	} else {
-		static char *texts[] = { "Word", "MADI" };
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = hdspm->texts_autosync_items;
 
-		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-		uinfo->count = 1;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+			uinfo->value.enumerated.items - 1;
 
-		uinfo->value.enumerated.items = 2;
+	strcpy(uinfo->value.enumerated.name,
+			hdspm->texts_autosync[uinfo->value.enumerated.item]);
 
-		if (uinfo->value.enumerated.item >=
-		    uinfo->value.enumerated.items)
-			uinfo->value.enumerated.item =
-				uinfo->value.enumerated.items - 1;
-		strcpy(uinfo->value.enumerated.name,
-				texts[uinfo->value.enumerated.item]);
-	}
 	return 0;
 }
 
@@ -1750,32 +2666,41 @@ static int snd_hdspm_get_pref_sync_ref(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int psf = hdspm_pref_sync_ref(hdspm);
 
-	ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
-	return 0;
+	if (psf >= 0) {
+		ucontrol->value.enumerated.item[0] = psf;
+		return 0;
+	}
+
+	return -1;
 }
 
 static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_value *ucontrol)
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
-	int change, max;
-	unsigned int val;
-
-	max = hdspm->is_aes32 ? 9 : 2;
+	int val, change = 0;
 
 	if (!snd_hdspm_use_is_exclusive(hdspm))
 		return -EBUSY;
 
-	val = ucontrol->value.enumerated.item[0] % max;
+	val = ucontrol->value.enumerated.item[0];
+
+	if (val < 0)
+		val = 0;
+	else if (val >= hdspm->texts_autosync_items)
+		val = hdspm->texts_autosync_items-1;
 
 	spin_lock_irq(&hdspm->lock);
-	change = (int) val != hdspm_pref_sync_ref(hdspm);
-	hdspm_set_pref_sync_ref(hdspm, val);
+	if (val != hdspm_pref_sync_ref(hdspm))
+		change = (0 == hdspm_set_pref_sync_ref(hdspm, val)) ? 1 : 0;
+
 	spin_unlock_irq(&hdspm->lock);
 	return change;
 }
 
+
 #define HDSPM_AUTOSYNC_REF(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -1785,18 +2710,18 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
   .get = snd_hdspm_get_autosync_ref, \
 }
 
-static int hdspm_autosync_ref(struct hdspm * hdspm)
+static int hdspm_autosync_ref(struct hdspm *hdspm)
 {
-	if (hdspm->is_aes32) {
+	if (AES32 == hdspm->io_type) {
 		unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
-		unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) &
-			0xF;
+		unsigned int syncref =
+			(status >> HDSPM_AES32_syncref_bit) & 0xF;
 		if (syncref == 0)
 			return HDSPM_AES32_AUTOSYNC_FROM_WORD;
 		if (syncref <= 8)
 			return syncref;
 		return HDSPM_AES32_AUTOSYNC_FROM_NONE;
-	} else {
+	} else if (MADI == hdspm->io_type) {
 		/* This looks at the autosync selected sync reference */
 		unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
 
@@ -1805,22 +2730,27 @@ static int hdspm_autosync_ref(struct hdspm * hdspm)
 			return HDSPM_AUTOSYNC_FROM_WORD;
 		case HDSPM_SelSyncRef_MADI:
 			return HDSPM_AUTOSYNC_FROM_MADI;
+		case HDSPM_SelSyncRef_TCO:
+			return HDSPM_AUTOSYNC_FROM_TCO;
+		case HDSPM_SelSyncRef_SyncIn:
+			return HDSPM_AUTOSYNC_FROM_SYNC_IN;
 		case HDSPM_SelSyncRef_NVALID:
 			return HDSPM_AUTOSYNC_FROM_NONE;
 		default:
 			return 0;
 		}
 
-		return 0;
 	}
+	return 0;
 }
 
+
 static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	if (hdspm->is_aes32) {
+	if (AES32 == hdspm->io_type) {
 		static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
 			"AES4",	"AES5", "AES6", "AES7", "AES8", "None"};
 
@@ -1833,14 +2763,15 @@ static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
 				uinfo->value.enumerated.items - 1;
 		strcpy(uinfo->value.enumerated.name,
 				texts[uinfo->value.enumerated.item]);
-	} else {
-		static char *texts[] = { "WordClock", "MADI", "None" };
+	} else if (MADI == hdspm->io_type) {
+		static char *texts[] = {"Word Clock", "MADI", "TCO",
+			"Sync In", "None" };
 
 		uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 		uinfo->count = 1;
-		uinfo->value.enumerated.items = 3;
+		uinfo->value.enumerated.items = 5;
 		if (uinfo->value.enumerated.item >=
-		    uinfo->value.enumerated.items)
+				uinfo->value.enumerated.items)
 			uinfo->value.enumerated.item =
 				uinfo->value.enumerated.items - 1;
 		strcpy(uinfo->value.enumerated.name,
@@ -1858,6 +2789,7 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+
 #define HDSPM_LINE_OUT(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -1914,6 +2846,7 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_TX_64(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -1969,6 +2902,7 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_C_TMS(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2024,6 +2958,7 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_SAFE_MODE(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2079,6 +3014,7 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_EMPHASIS(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2134,6 +3070,7 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_DOLBY(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2189,6 +3126,7 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_PROFESSIONAL(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2315,6 +3253,7 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_DS_WIRE(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2386,6 +3325,7 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
+
 #define HDSPM_QS_WIRE(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
   .name = xname, \
@@ -2472,15 +3412,6 @@ static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
 	return change;
 }
 
-/*           Simple Mixer
-  deprecated since to much faders ???
-  MIXER interface says output (source, destination, value)
-   where source > MAX_channels are playback channels 
-   on MADICARD 
-  - playback mixer matrix: [channelout+64] [output] [value]
-  - input(thru) mixer matrix: [channelin] [output] [value]
-  (better do 2 kontrols for separation ?)
-*/
 
 #define HDSPM_MIXER(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
@@ -2586,7 +3517,7 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
 
 /* The simple mixer control(s) provide gain control for the
    basic 1:1 mappings of playback streams to output
-   streams. 
+   streams.
 */
 
 #define HDSPM_PLAYBACK_MIXER \
@@ -2604,7 +3535,7 @@ static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 65536;
+	uinfo->value.integer.max = 64;
 	uinfo->value.integer.step = 1;
 	return 0;
 }
@@ -2614,28 +3545,17 @@ static int snd_hdspm_get_playback_mixer(struct snd_kcontrol *kcontrol,
 {
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 	int channel;
-	int mapped_channel;
 
 	channel = ucontrol->id.index - 1;
 
 	if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
 		return -EINVAL;
 
-	mapped_channel = hdspm->channel_map[channel];
-	if (mapped_channel < 0)
-		return -EINVAL;
-
 	spin_lock_irq(&hdspm->lock);
 	ucontrol->value.integer.value[0] =
-	    hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
+	  (hdspm_read_pb_gain(hdspm, channel, channel)*64)/UNITY_GAIN;
 	spin_unlock_irq(&hdspm->lock);
 
-	/*
-	snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, "
-		    "value %d\n",
-		    ucontrol->id.index, channel, mapped_channel,
-		    ucontrol->value.integer.value[0]); 
-	*/
 	return 0;
 }
 
@@ -2645,7 +3565,6 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 	int change;
 	int channel;
-	int mapped_channel;
 	int gain;
 
 	if (!snd_hdspm_use_is_exclusive(hdspm))
@@ -2656,59 +3575,60 @@ static int snd_hdspm_put_playback_mixer(struct snd_kcontrol *kcontrol,
 	if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
 		return -EINVAL;
 
-	mapped_channel = hdspm->channel_map[channel];
-	if (mapped_channel < 0)
-		return -EINVAL;
-
-	gain = ucontrol->value.integer.value[0];
+	gain = ucontrol->value.integer.value[0]*UNITY_GAIN/64;
 
 	spin_lock_irq(&hdspm->lock);
 	change =
-	    gain != hdspm_read_pb_gain(hdspm, mapped_channel,
-				       mapped_channel);
+	    gain != hdspm_read_pb_gain(hdspm, channel,
+				       channel);
 	if (change)
-		hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
+		hdspm_write_pb_gain(hdspm, channel, channel,
 				    gain);
 	spin_unlock_irq(&hdspm->lock);
 	return change;
 }
 
-#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_sync_check, \
-  .get = snd_hdspm_get_wc_sync_check \
+#define HDSPM_SYNC_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_info_sync_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" };
+	static char *texts[] = { "No Lock", "Lock", "Sync", "N/A" };
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
+	uinfo->value.enumerated.items = 4;
 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
 		uinfo->value.enumerated.item =
-		    uinfo->value.enumerated.items - 1;
+			uinfo->value.enumerated.items - 1;
 	strcpy(uinfo->value.enumerated.name,
-	       texts[uinfo->value.enumerated.item]);
+			texts[uinfo->value.enumerated.item]);
 	return 0;
 }
 
-static int hdspm_wc_sync_check(struct hdspm * hdspm)
+static int hdspm_wc_sync_check(struct hdspm *hdspm)
 {
-	if (hdspm->is_aes32) {
-		int status = hdspm_read(hdspm, HDSPM_statusRegister);
-		if (status & HDSPM_AES32_wcLock) {
-			/* I don't know how to differenciate sync from lock.
-			   Doing as if sync for now */
+	int status, status2;
+
+	switch (hdspm->io_type) {
+	case AES32:
+		status = hdspm_read(hdspm, HDSPM_statusRegister);
+		if (status & HDSPM_wcSync)
 			return 2;
-		}
+		else if (status & HDSPM_wcLock)
+			return 1;
 		return 0;
-	} else {
-		int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+		break;
+
+	case MADI:
+		status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
 		if (status2 & HDSPM_wcLock) {
 			if (status2 & HDSPM_wcSync)
 				return 2;
@@ -2716,29 +3636,30 @@ static int hdspm_wc_sync_check(struct hdspm * hdspm)
 				return 1;
 		}
 		return 0;
-	}
-}
+		break;
 
-static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
-				       struct snd_ctl_elem_value *ucontrol)
-{
-	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	case RayDAT:
+	case AIO:
+		status = hdspm_read(hdspm, HDSPM_statusRegister);
 
-	ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
-	return 0;
-}
+		if (status & 0x2000000)
+			return 2;
+		else if (status & 0x1000000)
+			return 1;
+		return 0;
 
+		break;
 
-#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_sync_check, \
-  .get = snd_hdspm_get_madisync_sync_check \
+	case MADIface:
+		break;
+	}
+
+
+	return 3;
 }
 
-static int hdspm_madisync_sync_check(struct hdspm * hdspm)
+
+static int hdspm_madi_sync_check(struct hdspm *hdspm)
 {
 	int status = hdspm_read(hdspm, HDSPM_statusRegister);
 	if (status & HDSPM_madiLock) {
@@ -2750,89 +3671,726 @@ static int hdspm_madisync_sync_check(struct hdspm * hdspm)
 	return 0;
 }
 
-static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
-					     struct snd_ctl_elem_value *
-					     ucontrol)
+
+static int hdspm_s1_sync_check(struct hdspm *hdspm, int idx)
 {
-	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int status, lock, sync;
 
-	ucontrol->value.enumerated.item[0] =
-	    hdspm_madisync_sync_check(hdspm);
+	status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
+
+	lock = (status & (0x1<<idx)) ? 1 : 0;
+	sync = (status & (0x100<<idx)) ? 1 : 0;
+
+	if (lock && sync)
+		return 2;
+	else if (lock)
+		return 1;
 	return 0;
 }
 
 
-#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_sync_check, \
-  .get = snd_hdspm_get_aes_sync_check \
+static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
+{
+	int status, lock = 0, sync = 0;
+
+	switch (hdspm->io_type) {
+	case RayDAT:
+	case AIO:
+		status = hdspm_read(hdspm, HDSPM_RD_STATUS_3);
+		lock = (status & 0x400) ? 1 : 0;
+		sync = (status & 0x800) ? 1 : 0;
+		break;
+
+	case MADI:
+	case AES32:
+		status = hdspm_read(hdspm, HDSPM_statusRegister2);
+		lock = (status & HDSPM_syncInLock) ? 1 : 0;
+		sync = (status & HDSPM_syncInSync) ? 1 : 0;
+		break;
+
+	case MADIface:
+		break;
+	}
+
+	if (lock && sync)
+		return 2;
+	else if (lock)
+		return 1;
+
+	return 0;
 }
 
-static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
+static int hdspm_aes_sync_check(struct hdspm *hdspm, int idx)
 {
-	int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
-	if (status2 & (HDSPM_LockAES >> idx)) {
-		/* I don't know how to differenciate sync from lock.
-		   Doing as if sync for now */
+	int status2, lock, sync;
+	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+	lock = (status2 & (0x0080 >> idx)) ? 1 : 0;
+	sync = (status2 & (0x8000 >> idx)) ? 1 : 0;
+
+	if (sync)
 		return 2;
+	else if (lock)
+		return 1;
+	return 0;
+}
+
+
+static int hdspm_tco_sync_check(struct hdspm *hdspm)
+{
+	int status;
+
+	if (hdspm->tco) {
+		switch (hdspm->io_type) {
+		case MADI:
+		case AES32:
+			status = hdspm_read(hdspm, HDSPM_statusRegister);
+			if (status & HDSPM_tcoLock) {
+				if (status & HDSPM_tcoSync)
+					return 2;
+				else
+					return 1;
+			}
+			return 0;
+
+			break;
+
+		case RayDAT:
+		case AIO:
+			status = hdspm_read(hdspm, HDSPM_RD_STATUS_1);
+
+			if (status & 0x8000000)
+				return 2; /* Sync */
+			if (status & 0x4000000)
+				return 1; /* Lock */
+			return 0; /* No signal */
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return 3; /* N/A */
+}
+
+
+static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+	int val = -1;
+
+	switch (hdspm->io_type) {
+	case RayDAT:
+		switch (kcontrol->private_value) {
+		case 0: /* WC */
+			val = hdspm_wc_sync_check(hdspm); break;
+		case 7: /* TCO */
+			val = hdspm_tco_sync_check(hdspm); break;
+		case 8: /* SYNC IN */
+			val = hdspm_sync_in_sync_check(hdspm); break;
+		default:
+			val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
+		}
+
+	case AIO:
+		switch (kcontrol->private_value) {
+		case 0: /* WC */
+			val = hdspm_wc_sync_check(hdspm); break;
+		case 4: /* TCO */
+			val = hdspm_tco_sync_check(hdspm); break;
+		case 5: /* SYNC IN */
+			val = hdspm_sync_in_sync_check(hdspm); break;
+		default:
+			val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
+		}
+
+	case MADI:
+		switch (kcontrol->private_value) {
+		case 0: /* WC */
+			val = hdspm_wc_sync_check(hdspm); break;
+		case 1: /* MADI */
+			val = hdspm_madi_sync_check(hdspm); break;
+		case 2: /* TCO */
+			val = hdspm_tco_sync_check(hdspm); break;
+		case 3: /* SYNC_IN */
+			val = hdspm_sync_in_sync_check(hdspm); break;
+		}
+
+	case MADIface:
+		val = hdspm_madi_sync_check(hdspm); /* MADI */
+		break;
+
+	case AES32:
+		switch (kcontrol->private_value) {
+		case 0: /* WC */
+			val = hdspm_wc_sync_check(hdspm); break;
+		case 9: /* TCO */
+			val = hdspm_tco_sync_check(hdspm); break;
+		case 10 /* SYNC IN */:
+			val = hdspm_sync_in_sync_check(hdspm); break;
+		default: /* AES1 to AES8 */
+			 val = hdspm_aes_sync_check(hdspm,
+					 kcontrol->private_value-1);
+		}
+
+	}
+
+	if (-1 == val)
+		val = 3;
+
+	ucontrol->value.enumerated.item[0] = val;
+	return 0;
+}
+
+
+
+/**
+ * TCO controls
+ **/
+static void hdspm_tco_write(struct hdspm *hdspm)
+{
+	unsigned int tc[4] = { 0, 0, 0, 0};
+
+	switch (hdspm->tco->input) {
+	case 0:
+		tc[2] |= HDSPM_TCO2_set_input_MSB;
+		break;
+	case 1:
+		tc[2] |= HDSPM_TCO2_set_input_LSB;
+		break;
+	default:
+		break;
+	}
+
+	switch (hdspm->tco->framerate) {
+	case 1:
+		tc[1] |= HDSPM_TCO1_LTC_Format_LSB;
+		break;
+	case 2:
+		tc[1] |= HDSPM_TCO1_LTC_Format_MSB;
+		break;
+	case 3:
+		tc[1] |= HDSPM_TCO1_LTC_Format_MSB +
+			HDSPM_TCO1_set_drop_frame_flag;
+		break;
+	case 4:
+		tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
+			HDSPM_TCO1_LTC_Format_MSB;
+		break;
+	case 5:
+		tc[1] |= HDSPM_TCO1_LTC_Format_LSB +
+			HDSPM_TCO1_LTC_Format_MSB +
+			HDSPM_TCO1_set_drop_frame_flag;
+		break;
+	default:
+		break;
+	}
+
+	switch (hdspm->tco->wordclock) {
+	case 1:
+		tc[2] |= HDSPM_TCO2_WCK_IO_ratio_LSB;
+		break;
+	case 2:
+		tc[2] |= HDSPM_TCO2_WCK_IO_ratio_MSB;
+		break;
+	default:
+		break;
+	}
+
+	switch (hdspm->tco->samplerate) {
+	case 1:
+		tc[2] |= HDSPM_TCO2_set_freq;
+		break;
+	case 2:
+		tc[2] |= HDSPM_TCO2_set_freq_from_app;
+		break;
+	default:
+		break;
 	}
+
+	switch (hdspm->tco->pull) {
+	case 1:
+		tc[2] |= HDSPM_TCO2_set_pull_up;
+		break;
+	case 2:
+		tc[2] |= HDSPM_TCO2_set_pull_down;
+		break;
+	case 3:
+		tc[2] |= HDSPM_TCO2_set_pull_up + HDSPM_TCO2_set_01_4;
+		break;
+	case 4:
+		tc[2] |= HDSPM_TCO2_set_pull_down + HDSPM_TCO2_set_01_4;
+		break;
+	default:
+		break;
+	}
+
+	if (1 == hdspm->tco->term) {
+		tc[2] |= HDSPM_TCO2_set_term_75R;
+	}
+
+	hdspm_write(hdspm, HDSPM_WR_TCO, tc[0]);
+	hdspm_write(hdspm, HDSPM_WR_TCO+4, tc[1]);
+	hdspm_write(hdspm, HDSPM_WR_TCO+8, tc[2]);
+	hdspm_write(hdspm, HDSPM_WR_TCO+12, tc[3]);
+}
+
+
+#define HDSPM_TCO_SAMPLE_RATE(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_sample_rate, \
+	.get = snd_hdspm_get_tco_sample_rate, \
+	.put = snd_hdspm_put_tco_sample_rate \
+}
+
+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]);
+
 	return 0;
 }
 
-static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
+static int snd_hdspm_get_tco_sample_rate(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm->tco->samplerate;
+
+	return 0;
+}
+
+static int snd_hdspm_put_tco_sample_rate(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	if (hdspm->tco->samplerate != ucontrol->value.enumerated.item[0]) {
+		hdspm->tco->samplerate = ucontrol->value.enumerated.item[0];
+
+		hdspm_tco_write(hdspm);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+
+#define HDSPM_TCO_PULL(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+		SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_pull, \
+	.get = snd_hdspm_get_tco_pull, \
+	.put = snd_hdspm_put_tco_pull \
+}
+
+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]);
+
+	return 0;
+}
+
+static int snd_hdspm_get_tco_pull(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm->tco->pull;
+
+	return 0;
+}
+
+static int snd_hdspm_put_tco_pull(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	if (hdspm->tco->pull != ucontrol->value.enumerated.item[0]) {
+		hdspm->tco->pull = ucontrol->value.enumerated.item[0];
+
+		hdspm_tco_write(hdspm);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+#define HDSPM_TCO_WCK_CONVERSION(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+			SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_wck_conversion, \
+	.get = snd_hdspm_get_tco_wck_conversion, \
+	.put = snd_hdspm_put_tco_wck_conversion \
+}
+
+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]);
+
+	return 0;
+}
+
+static int snd_hdspm_get_tco_wck_conversion(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm->tco->wordclock;
+
+	return 0;
+}
+
+static int snd_hdspm_put_tco_wck_conversion(struct snd_kcontrol *kcontrol,
+					    struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	if (hdspm->tco->wordclock != ucontrol->value.enumerated.item[0]) {
+		hdspm->tco->wordclock = ucontrol->value.enumerated.item[0];
+
+		hdspm_tco_write(hdspm);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+
+#define HDSPM_TCO_FRAME_RATE(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+			SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_frame_rate, \
+	.get = snd_hdspm_get_tco_frame_rate, \
+	.put = snd_hdspm_put_tco_frame_rate \
+}
+
+static int snd_hdspm_info_tco_frame_rate(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_info *uinfo)
+{
+	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]);
+
+	return 0;
+}
+
+static int snd_hdspm_get_tco_frame_rate(struct snd_kcontrol *kcontrol,
 					struct snd_ctl_elem_value *ucontrol)
 {
-	int offset;
 	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
 
-	offset = ucontrol->id.index - 1;
-	if (offset < 0 || offset >= 8)
-		return -EINVAL;
+	ucontrol->value.enumerated.item[0] = hdspm->tco->framerate;
 
-	ucontrol->value.enumerated.item[0] =
-		hdspm_aes_sync_check(hdspm, offset);
 	return 0;
 }
 
+static int snd_hdspm_put_tco_frame_rate(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	if (hdspm->tco->framerate != ucontrol->value.enumerated.item[0]) {
+		hdspm->tco->framerate = ucontrol->value.enumerated.item[0];
 
-static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
+		hdspm_tco_write(hdspm);
 
-	HDSPM_MIXER("Mixer", 0),
-/* 'Sample Clock Source' complies with the alsa control naming scheme */
-	HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
+		return 1;
+	}
+
+	return 0;
+}
+
+
+#define HDSPM_TCO_SYNC_SOURCE(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+			SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_sync_source, \
+	.get = snd_hdspm_get_tco_sync_source, \
+	.put = snd_hdspm_put_tco_sync_source \
+}
+
+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]);
+
+	return 0;
+}
+
+static int snd_hdspm_get_tco_sync_source(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm->tco->input;
+
+	return 0;
+}
+
+static int snd_hdspm_put_tco_sync_source(struct snd_kcontrol *kcontrol,
+					 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	if (hdspm->tco->input != ucontrol->value.enumerated.item[0]) {
+		hdspm->tco->input = ucontrol->value.enumerated.item[0];
+
+		hdspm_tco_write(hdspm);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+
+#define HDSPM_TCO_WORD_TERM(xname, xindex) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+	.name = xname, \
+	.index = xindex, \
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+			SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+	.info = snd_hdspm_info_tco_word_term, \
+	.get = snd_hdspm_get_tco_word_term, \
+	.put = snd_hdspm_put_tco_word_term \
+}
+
+static int snd_hdspm_info_tco_word_term(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+
+	return 0;
+}
+
+
+static int snd_hdspm_get_tco_word_term(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm->tco->term;
+
+	return 0;
+}
+
+
+static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *ucontrol)
+{
+	struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+	if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
+		hdspm->tco->term = ucontrol->value.enumerated.item[0];
+
+		hdspm_tco_write(hdspm);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+
+
+
+static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
+	HDSPM_MIXER("Mixer", 0),
+	HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
 	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
 	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
 	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
 	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
-/* 'External Rate' complies with the alsa control naming scheme */
-	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
-	HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
-	HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
+	HDSPM_SYNC_CHECK("WC SyncCheck", 0),
+	HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
+	HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
+	HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
 	HDSPM_LINE_OUT("Line Out", 0),
 	HDSPM_TX_64("TX 64 channels mode", 0),
 	HDSPM_C_TMS("Clear Track Marker", 0),
 	HDSPM_SAFE_MODE("Safe Mode", 0),
-	HDSPM_INPUT_SELECT("Input Select", 0),
+	HDSPM_INPUT_SELECT("Input Select", 0)
 };
 
-static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
 
+static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
 	HDSPM_MIXER("Mixer", 0),
-/* 'Sample Clock Source' complies with the alsa control naming scheme */
-	HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
+	HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
+	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
+	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+	HDSPM_SYNC_CHECK("MADI SyncCheck", 0),
+	HDSPM_TX_64("TX 64 channels mode", 0),
+	HDSPM_C_TMS("Clear Track Marker", 0),
+	HDSPM_SAFE_MODE("Safe Mode", 0)
+};
 
+static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
+	HDSPM_MIXER("Mixer", 0),
+	HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
 	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
 	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
 	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
 	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
-/* 'External Rate' complies with the alsa control naming scheme */
 	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
-	HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
-/*	HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
+	HDSPM_SYNC_CHECK("WC SyncCheck", 0),
+	HDSPM_SYNC_CHECK("AES SyncCheck", 1),
+	HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
+	HDSPM_SYNC_CHECK("ADAT SyncCheck", 3),
+	HDSPM_SYNC_CHECK("TCO SyncCheck", 4),
+	HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 5),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT Frequency", 3),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 4),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 5)
+
+		/*
+		   HDSPM_INPUT_SELECT("Input Select", 0),
+		   HDSPM_SPDIF_OPTICAL("SPDIF Out Optical", 0),
+		   HDSPM_PROFESSIONAL("SPDIF Out Professional", 0);
+		   HDSPM_SPDIF_IN("SPDIF In", 0);
+		   HDSPM_BREAKOUT_CABLE("Breakout Cable", 0);
+		   HDSPM_INPUT_LEVEL("Input Level", 0);
+		   HDSPM_OUTPUT_LEVEL("Output Level", 0);
+		   HDSPM_PHONES("Phones", 0);
+		   */
+};
+
+static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
+	HDSPM_MIXER("Mixer", 0),
+	HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
+	HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
+	HDSPM_PREF_SYNC_REF("Pref Sync Ref", 0),
+	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+	HDSPM_SYNC_CHECK("WC SyncCheck", 0),
+	HDSPM_SYNC_CHECK("AES SyncCheck", 1),
+	HDSPM_SYNC_CHECK("SPDIF SyncCheck", 2),
+	HDSPM_SYNC_CHECK("ADAT1 SyncCheck", 3),
+	HDSPM_SYNC_CHECK("ADAT2 SyncCheck", 4),
+	HDSPM_SYNC_CHECK("ADAT3 SyncCheck", 5),
+	HDSPM_SYNC_CHECK("ADAT4 SyncCheck", 6),
+	HDSPM_SYNC_CHECK("TCO SyncCheck", 7),
+	HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 8),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES Frequency", 1),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SPDIF Frequency", 2),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT1 Frequency", 3),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT2 Frequency", 4),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT3 Frequency", 5),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("ADAT4 Frequency", 6),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 7),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 8)
+};
+
+static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
+	HDSPM_MIXER("Mixer", 0),
+	HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
+	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
+	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
+	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
+	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+	HDSPM_SYNC_CHECK("WC Sync Check", 0),
+	HDSPM_SYNC_CHECK("AES1 Sync Check", 1),
+	HDSPM_SYNC_CHECK("AES2 Sync Check", 2),
+	HDSPM_SYNC_CHECK("AES3 Sync Check", 3),
+	HDSPM_SYNC_CHECK("AES4 Sync Check", 4),
+	HDSPM_SYNC_CHECK("AES5 Sync Check", 5),
+	HDSPM_SYNC_CHECK("AES6 Sync Check", 6),
+	HDSPM_SYNC_CHECK("AES7 Sync Check", 7),
+	HDSPM_SYNC_CHECK("AES8 Sync Check", 8),
+	HDSPM_SYNC_CHECK("TCO Sync Check", 9),
+	HDSPM_SYNC_CHECK("SYNC IN Sync Check", 10),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("WC Frequency", 0),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES1 Frequency", 1),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES2 Frequency", 2),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES3 Frequency", 3),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES4 Frequency", 4),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES5 Frequency", 5),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES6 Frequency", 6),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES7 Frequency", 7),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("AES8 Frequency", 8),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("TCO Frequency", 9),
+	HDSPM_AUTOSYNC_SAMPLE_RATE("SYNC IN Frequency", 10),
 	HDSPM_LINE_OUT("Line Out", 0),
 	HDSPM_EMPHASIS("Emphasis", 0),
 	HDSPM_DOLBY("Non Audio", 0),
@@ -2842,6 +4400,19 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
 	HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
 };
 
+
+
+/* Control elements for the optional TCO module */
+static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
+	HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
+	HDSPM_TCO_PULL("TCO Pull", 0),
+	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)
+};
+
+
 static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
 
 
@@ -2849,78 +4420,76 @@ static int hdspm_update_simple_mixer_controls(struct hdspm * hdspm)
 {
 	int i;
 
-	for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
+	for (i = hdspm->ds_out_channels; i < hdspm->ss_out_channels; ++i) {
 		if (hdspm->system_sample_rate > 48000) {
 			hdspm->playback_mixer_ctls[i]->vd[0].access =
-			    SNDRV_CTL_ELEM_ACCESS_INACTIVE |
-			    SNDRV_CTL_ELEM_ACCESS_READ |
-			    SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+				SNDRV_CTL_ELEM_ACCESS_INACTIVE |
+				SNDRV_CTL_ELEM_ACCESS_READ |
+				SNDRV_CTL_ELEM_ACCESS_VOLATILE;
 		} else {
 			hdspm->playback_mixer_ctls[i]->vd[0].access =
-			    SNDRV_CTL_ELEM_ACCESS_READWRITE |
-			    SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+				SNDRV_CTL_ELEM_ACCESS_READWRITE |
+				SNDRV_CTL_ELEM_ACCESS_VOLATILE;
 		}
 		snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
-			       SNDRV_CTL_EVENT_MASK_INFO,
-			       &hdspm->playback_mixer_ctls[i]->id);
+				SNDRV_CTL_EVENT_MASK_INFO,
+				&hdspm->playback_mixer_ctls[i]->id);
 	}
 
 	return 0;
 }
 
 
-static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm)
+static int snd_hdspm_create_controls(struct snd_card *card,
+					struct hdspm *hdspm)
 {
 	unsigned int idx, limit;
 	int err;
 	struct snd_kcontrol *kctl;
+	struct snd_kcontrol_new *list = NULL;
 
-	/* add control list first */
-	if (hdspm->is_aes32) {
-		struct snd_kcontrol_new aes_sync_ctl =
-			HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
+	switch (hdspm->io_type) {
+	case MADI:
+		list = snd_hdspm_controls_madi;
+		limit = ARRAY_SIZE(snd_hdspm_controls_madi);
+		break;
+	case MADIface:
+		list = snd_hdspm_controls_madiface;
+		limit = ARRAY_SIZE(snd_hdspm_controls_madiface);
+		break;
+	case AIO:
+		list = snd_hdspm_controls_aio;
+		limit = ARRAY_SIZE(snd_hdspm_controls_aio);
+		break;
+	case RayDAT:
+		list = snd_hdspm_controls_raydat;
+		limit = ARRAY_SIZE(snd_hdspm_controls_raydat);
+		break;
+	case AES32:
+		list = snd_hdspm_controls_aes32;
+		limit = ARRAY_SIZE(snd_hdspm_controls_aes32);
+		break;
+	}
 
-		for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
-		     idx++) {
-			err = snd_ctl_add(card,
-					  snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
-						       hdspm));
-			if (err < 0)
-				return err;
-		}
-		for (idx = 1; idx <= 8; idx++) {
-			aes_sync_ctl.index = idx;
-			err = snd_ctl_add(card,
-					  snd_ctl_new1(&aes_sync_ctl, hdspm));
-			if (err < 0)
-				return err;
-		}
-	} else {
-		for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
-		     idx++) {
+	if (NULL != list) {
+		for (idx = 0; idx < limit; idx++) {
 			err = snd_ctl_add(card,
-					  snd_ctl_new1(&snd_hdspm_controls_madi[idx],
-						       hdspm));
+					snd_ctl_new1(&list[idx], hdspm));
 			if (err < 0)
 				return err;
 		}
 	}
 
-	/* Channel playback mixer as default control 
-	   Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders,
-	   thats too * big for any alsamixer they are accessible via special
-	   IOCTL on hwdep and the mixer 2dimensional mixer control
-	*/
 
+	/* create simple 1:1 playback mixer controls */
 	snd_hdspm_playback_mixer.name = "Chn";
-	limit = HDSPM_MAX_CHANNELS;
-
-	/* The index values are one greater than the channel ID so that
-	 * alsamixer will display them correctly. We want to use the index
-	 * for fast lookup of the relevant channel, but if we use it at all,
-	 * most ALSA software does the wrong thing with it ...
-	 */
-
+	if (hdspm->system_sample_rate >= 128000) {
+		limit = hdspm->qs_out_channels;
+	} else if (hdspm->system_sample_rate >= 64000) {
+		limit = hdspm->ds_out_channels;
+	} else {
+		limit = hdspm->ss_out_channels;
+	}
 	for (idx = 0; idx < limit; ++idx) {
 		snd_hdspm_playback_mixer.index = idx + 1;
 		kctl = snd_ctl_new1(&snd_hdspm_playback_mixer, hdspm);
@@ -2930,11 +4499,24 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm
 		hdspm->playback_mixer_ctls[idx] = kctl;
 	}
 
+
+	if (hdspm->tco) {
+		/* add tco control elements */
+		list = snd_hdspm_controls_tco;
+		limit = ARRAY_SIZE(snd_hdspm_controls_tco);
+		for (idx = 0; idx < limit; idx++) {
+			err = snd_ctl_add(card,
+					snd_ctl_new1(&list[idx], hdspm));
+			if (err < 0)
+				return err;
+		}
+	}
+
 	return 0;
 }
 
 /*------------------------------------------------------------
-   /proc interface 
+   /proc interface
  ------------------------------------------------------------*/
 
 static void
@@ -2942,72 +4524,178 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 			 struct snd_info_buffer *buffer)
 {
 	struct hdspm *hdspm = entry->private_data;
-	unsigned int status;
-	unsigned int status2;
+	unsigned int status, status2, control, freq;
+
 	char *pref_sync_ref;
 	char *autosync_ref;
 	char *system_clock_mode;
-	char *clock_source;
 	char *insel;
-	char *syncref;
 	int x, x2;
 
+	/* TCO stuff */
+	int a, ltc, frames, seconds, minutes, hours;
+	unsigned int period;
+	u64 freq_const = 0;
+	u32 rate;
+
 	status = hdspm_read(hdspm, HDSPM_statusRegister);
 	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	control = hdspm->control_register;
+	freq = hdspm_read(hdspm, HDSPM_timecodeRegister);
 
 	snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
-		    hdspm->card_name, hdspm->card->number + 1,
-		    hdspm->firmware_rev,
-		    (status2 & HDSPM_version0) |
-		    (status2 & HDSPM_version1) | (status2 &
-						  HDSPM_version2));
+			hdspm->card_name, hdspm->card->number + 1,
+			hdspm->firmware_rev,
+			(status2 & HDSPM_version0) |
+			(status2 & HDSPM_version1) | (status2 &
+				HDSPM_version2));
+
+	snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
+			(hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
+			(hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
 
 	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
-		    hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
+			hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
 
 	snd_iprintf(buffer, "--- System ---\n");
 
 	snd_iprintf(buffer,
-		    "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
-		    status & HDSPM_audioIRQPending,
-		    (status & HDSPM_midi0IRQPending) ? 1 : 0,
-		    (status & HDSPM_midi1IRQPending) ? 1 : 0,
-		    hdspm->irq_count);
+		"IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
+		status & HDSPM_audioIRQPending,
+		(status & HDSPM_midi0IRQPending) ? 1 : 0,
+		(status & HDSPM_midi1IRQPending) ? 1 : 0,
+		hdspm->irq_count);
 	snd_iprintf(buffer,
-		    "HW pointer: id = %d, rawptr = %d (%d->%d) "
-		    "estimated= %ld (bytes)\n",
-		    ((status & HDSPM_BufferID) ? 1 : 0),
-		    (status & HDSPM_BufferPositionMask),
-		    (status & HDSPM_BufferPositionMask) %
-		    (2 * (int)hdspm->period_bytes),
-		    ((status & HDSPM_BufferPositionMask) - 64) %
-		    (2 * (int)hdspm->period_bytes),
-		    (long) hdspm_hw_pointer(hdspm) * 4);
+		"HW pointer: id = %d, rawptr = %d (%d->%d) "
+		"estimated= %ld (bytes)\n",
+		((status & HDSPM_BufferID) ? 1 : 0),
+		(status & HDSPM_BufferPositionMask),
+		(status & HDSPM_BufferPositionMask) %
+		(2 * (int)hdspm->period_bytes),
+		((status & HDSPM_BufferPositionMask) - 64) %
+		(2 * (int)hdspm->period_bytes),
+		(long) hdspm_hw_pointer(hdspm) * 4);
 
 	snd_iprintf(buffer,
-		    "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
-		    hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
-		    hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
-		    hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
-		    hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
+		"MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
+		hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
 	snd_iprintf(buffer,
-		    "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
-		    "status2=0x%x\n",
-		    hdspm->control_register, hdspm->control2_register,
-		    status, status2);
+		"MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
+		hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
+		hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
+	snd_iprintf(buffer,
+		"Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
+		"status2=0x%x\n",
+		hdspm->control_register, hdspm->control2_register,
+		status, status2);
+	if (status & HDSPM_tco_detect) {
+		snd_iprintf(buffer, "TCO module detected.\n");
+		a = hdspm_read(hdspm, HDSPM_RD_TCO+4);
+		if (a & HDSPM_TCO1_LTC_Input_valid) {
+			snd_iprintf(buffer, "  LTC valid, ");
+			switch (a & (HDSPM_TCO1_LTC_Format_LSB |
+						HDSPM_TCO1_LTC_Format_MSB)) {
+			case 0:
+				snd_iprintf(buffer, "24 fps, ");
+				break;
+			case HDSPM_TCO1_LTC_Format_LSB:
+				snd_iprintf(buffer, "25 fps, ");
+				break;
+			case HDSPM_TCO1_LTC_Format_MSB:
+				snd_iprintf(buffer, "29.97 fps, ");
+				break;
+			default:
+				snd_iprintf(buffer, "30 fps, ");
+				break;
+			}
+			if (a & HDSPM_TCO1_set_drop_frame_flag) {
+				snd_iprintf(buffer, "drop frame\n");
+			} else {
+				snd_iprintf(buffer, "full frame\n");
+			}
+		} else {
+			snd_iprintf(buffer, "  no LTC\n");
+		}
+		if (a & HDSPM_TCO1_Video_Input_Format_NTSC) {
+			snd_iprintf(buffer, "  Video: NTSC\n");
+		} else if (a & HDSPM_TCO1_Video_Input_Format_PAL) {
+			snd_iprintf(buffer, "  Video: PAL\n");
+		} else {
+			snd_iprintf(buffer, "  No video\n");
+		}
+		if (a & HDSPM_TCO1_TCO_lock) {
+			snd_iprintf(buffer, "  Sync: lock\n");
+		} else {
+			snd_iprintf(buffer, "  Sync: no lock\n");
+		}
+
+		switch (hdspm->io_type) {
+		case MADI:
+		case AES32:
+			freq_const = 110069313433624ULL;
+			break;
+		case RayDAT:
+		case AIO:
+			freq_const = 104857600000000ULL;
+			break;
+		case MADIface:
+			break; /* no TCO possible */
+		}
+
+		period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
+		snd_iprintf(buffer, "    period: %u\n", period);
+
+
+		/* rate = freq_const/period; */
+		rate = div_u64(freq_const, period);
+
+		if (control & HDSPM_QuadSpeed) {
+			rate *= 4;
+		} else if (control & HDSPM_DoubleSpeed) {
+			rate *= 2;
+		}
+
+		snd_iprintf(buffer, "  Frequency: %u Hz\n",
+				(unsigned int) rate);
+
+		ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
+		frames = ltc & 0xF;
+		ltc >>= 4;
+		frames += (ltc & 0x3) * 10;
+		ltc >>= 4;
+		seconds = ltc & 0xF;
+		ltc >>= 4;
+		seconds += (ltc & 0x7) * 10;
+		ltc >>= 4;
+		minutes = ltc & 0xF;
+		ltc >>= 4;
+		minutes += (ltc & 0x7) * 10;
+		ltc >>= 4;
+		hours = ltc & 0xF;
+		ltc >>= 4;
+		hours += (ltc & 0x3) * 10;
+		snd_iprintf(buffer,
+			"  LTC In: %02d:%02d:%02d:%02d\n",
+			hours, minutes, seconds, frames);
+
+	} else {
+		snd_iprintf(buffer, "No TCO module detected.\n");
+	}
 
 	snd_iprintf(buffer, "--- Settings ---\n");
 
 	x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
-					   HDSPM_LatencyMask));
+							HDSPM_LatencyMask));
 
 	snd_iprintf(buffer,
-		    "Size (Latency): %d samples (2 periods of %lu bytes)\n",
-		    x, (unsigned long) hdspm->period_bytes);
+		"Size (Latency): %d samples (2 periods of %lu bytes)\n",
+		x, (unsigned long) hdspm->period_bytes);
 
-	snd_iprintf(buffer, "Line out: %s,   Precise Pointer: %s\n",
-		    (hdspm->control_register & HDSPM_LineOut) ? "on " : "off",
-		    (hdspm->precise_ptr) ? "on" : "off");
+	snd_iprintf(buffer, "Line out: %s\n",
+		(hdspm->control_register & HDSPM_LineOut) ? "on " : "off");
 
 	switch (hdspm->control_register & HDSPM_InputMask) {
 	case HDSPM_InputOptical:
@@ -3017,63 +4705,22 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 		insel = "Coaxial";
 		break;
 	default:
-		insel = "Unknown";
-	}
-
-	switch (hdspm->control_register & HDSPM_SyncRefMask) {
-	case HDSPM_SyncRef_Word:
-		syncref = "WordClock";
-		break;
-	case HDSPM_SyncRef_MADI:
-		syncref = "MADI";
-		break;
-	default:
-		syncref = "Unknown";
+		insel = "Unkown";
 	}
-	snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
-		    syncref);
 
 	snd_iprintf(buffer,
-		    "ClearTrackMarker = %s, Transmit in %s Channel Mode, "
-		    "Auto Input %s\n",
-		    (hdspm->
-		     control_register & HDSPM_clr_tms) ? "on" : "off",
-		    (hdspm->
-		     control_register & HDSPM_TX_64ch) ? "64" : "56",
-		    (hdspm->
-		     control_register & HDSPM_AutoInp) ? "on" : "off");
+		"ClearTrackMarker = %s, Transmit in %s Channel Mode, "
+		"Auto Input %s\n",
+		(hdspm->control_register & HDSPM_clr_tms) ? "on" : "off",
+		(hdspm->control_register & HDSPM_TX_64ch) ? "64" : "56",
+		(hdspm->control_register & HDSPM_AutoInp) ? "on" : "off");
+
 
-	switch (hdspm_clock_source(hdspm)) {
-	case HDSPM_CLOCK_SOURCE_AUTOSYNC:
-		clock_source = "AutoSync";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
-		clock_source = "Internal 32 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
-		clock_source = "Internal 44.1 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
-		clock_source = "Internal 48 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
-		clock_source = "Internal 64 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
-		clock_source = "Internal 88.2 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
-		clock_source = "Internal 96 kHz";
-		break;
-	default:
-		clock_source = "Error";
-	}
-	snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
 	if (!(hdspm->control_register & HDSPM_ClockModeMaster))
-		system_clock_mode = "Slave";
+		system_clock_mode = "AutoSync";
 	else
 		system_clock_mode = "Master";
-	snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
+	snd_iprintf(buffer, "AutoSync Reference: %s\n", system_clock_mode);
 
 	switch (hdspm_pref_sync_ref(hdspm)) {
 	case HDSPM_SYNC_FROM_WORD:
@@ -3082,15 +4729,21 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 	case HDSPM_SYNC_FROM_MADI:
 		pref_sync_ref = "MADI Sync";
 		break;
+	case HDSPM_SYNC_FROM_TCO:
+		pref_sync_ref = "TCO";
+		break;
+	case HDSPM_SYNC_FROM_SYNC_IN:
+		pref_sync_ref = "Sync In";
+		break;
 	default:
 		pref_sync_ref = "XXXX Clock";
 		break;
 	}
 	snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
-		    pref_sync_ref);
+			pref_sync_ref);
 
 	snd_iprintf(buffer, "System Clock Frequency: %d\n",
-		    hdspm->system_sample_rate);
+			hdspm->system_sample_rate);
 
 
 	snd_iprintf(buffer, "--- Status:\n");
@@ -3099,12 +4752,18 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 	x2 = status2 & HDSPM_wcSync;
 
 	snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
-		    (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
-		    "NoLock",
-		    (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
-		    "NoLock");
+			(status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
+			"NoLock",
+			(status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
+			"NoLock");
 
 	switch (hdspm_autosync_ref(hdspm)) {
+	case HDSPM_AUTOSYNC_FROM_SYNC_IN:
+		autosync_ref = "Sync In";
+		break;
+	case HDSPM_AUTOSYNC_FROM_TCO:
+		autosync_ref = "TCO";
+		break;
 	case HDSPM_AUTOSYNC_FROM_WORD:
 		autosync_ref = "Word Clock";
 		break;
@@ -3119,15 +4778,15 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
 		break;
 	}
 	snd_iprintf(buffer,
-		    "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
-		    autosync_ref, hdspm_external_sample_rate(hdspm),
-		    (status & HDSPM_madiFreqMask) >> 22,
-		    (status2 & HDSPM_wcFreqMask) >> 5);
+		"AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
+		autosync_ref, hdspm_external_sample_rate(hdspm),
+		(status & HDSPM_madiFreqMask) >> 22,
+		(status2 & HDSPM_wcFreqMask) >> 5);
 
 	snd_iprintf(buffer, "Input: %s, Mode=%s\n",
-		    (status & HDSPM_AB_int) ? "Coax" : "Optical",
-		    (status & HDSPM_RX_64ch) ? "64 channels" :
-		    "56 channels");
+		(status & HDSPM_AB_int) ? "Coax" : "Optical",
+		(status & HDSPM_RX_64ch) ? "64 channels" :
+		"56 channels");
 
 	snd_iprintf(buffer, "\n");
 }
@@ -3142,8 +4801,6 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 	unsigned int timecode;
 	int pref_syncref;
 	char *autosync_ref;
-	char *system_clock_mode;
-	char *clock_source;
 	int x;
 
 	status = hdspm_read(hdspm, HDSPM_statusRegister);
@@ -3183,24 +4840,27 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 		    hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
 		    hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
 	snd_iprintf(buffer,
-		    "Register: ctrl1=0x%x, status1=0x%x, status2=0x%x, "
-		    "timecode=0x%x\n",
-		    hdspm->control_register,
-		    status, status2, timecode);
+		    "MIDIoverMADI FIFO: In=0x%x, Out=0x%x \n",
+		    hdspm_read(hdspm, HDSPM_midiStatusIn2) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusOut2) & 0xFF);
+	snd_iprintf(buffer,
+		    "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, "
+		    "status2=0x%x\n",
+		    hdspm->control_register, hdspm->control2_register,
+		    status, status2);
 
 	snd_iprintf(buffer, "--- Settings ---\n");
 
 	x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
-					   HDSPM_LatencyMask));
+				HDSPM_LatencyMask));
 
 	snd_iprintf(buffer,
 		    "Size (Latency): %d samples (2 periods of %lu bytes)\n",
 		    x, (unsigned long) hdspm->period_bytes);
 
-	snd_iprintf(buffer, "Line out: %s,   Precise Pointer: %s\n",
+	snd_iprintf(buffer, "Line out: %s\n",
 		    (hdspm->
-		     control_register & HDSPM_LineOut) ? "on " : "off",
-		    (hdspm->precise_ptr) ? "on" : "off");
+		     control_register & HDSPM_LineOut) ? "on " : "off");
 
 	snd_iprintf(buffer,
 		    "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
@@ -3211,46 +4871,6 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 		    (hdspm->
 		     control_register & HDSPM_Dolby) ? "on" : "off");
 
-	switch (hdspm_clock_source(hdspm)) {
-	case HDSPM_CLOCK_SOURCE_AUTOSYNC:
-		clock_source = "AutoSync";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
-		clock_source = "Internal 32 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
-		clock_source = "Internal 44.1 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
-		clock_source = "Internal 48 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
-		clock_source = "Internal 64 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
-		clock_source = "Internal 88.2 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
-		clock_source = "Internal 96 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
-		clock_source = "Internal 128 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
-		clock_source = "Internal 176.4 kHz";
-		break;
-	case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
-		clock_source = "Internal 192 kHz";
-		break;
-	default:
-		clock_source = "Error";
-	}
-	snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
-	if (!(hdspm->control_register & HDSPM_ClockModeMaster))
-		system_clock_mode = "Slave";
-	else
-		system_clock_mode = "Master";
-	snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
 
 	pref_syncref = hdspm_pref_sync_ref(hdspm);
 	if (pref_syncref == 0)
@@ -3274,38 +4894,108 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
 	snd_iprintf(buffer, "--- Status:\n");
 
 	snd_iprintf(buffer, "Word: %s  Frequency: %d\n",
-		    (status & HDSPM_AES32_wcLock)? "Sync   " : "No Lock",
+		    (status & HDSPM_AES32_wcLock) ? "Sync   " : "No Lock",
 		    HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
 
 	for (x = 0; x < 8; x++) {
 		snd_iprintf(buffer, "AES%d: %s  Frequency: %d\n",
 			    x+1,
 			    (status2 & (HDSPM_LockAES >> x)) ?
-			    "Sync   ": "No Lock",
+			    "Sync   " : "No Lock",
 			    HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
 	}
 
 	switch (hdspm_autosync_ref(hdspm)) {
-	case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
-	case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
-	default: autosync_ref = "---"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_NONE:
+		autosync_ref = "None"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_WORD:
+		autosync_ref = "Word Clock"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES1:
+		autosync_ref = "AES1"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES2:
+		autosync_ref = "AES2"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES3:
+		autosync_ref = "AES3"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES4:
+		autosync_ref = "AES4"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES5:
+		autosync_ref = "AES5"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES6:
+		autosync_ref = "AES6"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES7:
+		autosync_ref = "AES7"; break;
+	case HDSPM_AES32_AUTOSYNC_FROM_AES8:
+		autosync_ref = "AES8"; break;
+	default:
+		autosync_ref = "---"; break;
 	}
 	snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
 
 	snd_iprintf(buffer, "\n");
 }
 
+static void
+snd_hdspm_proc_read_raydat(struct snd_info_entry *entry,
+			 struct snd_info_buffer *buffer)
+{
+	struct hdspm *hdspm = entry->private_data;
+	unsigned int status1, status2, status3, control, i;
+	unsigned int lock, sync;
+
+	status1 = hdspm_read(hdspm, HDSPM_RD_STATUS_1); /* s1 */
+	status2 = hdspm_read(hdspm, HDSPM_RD_STATUS_2); /* freq */
+	status3 = hdspm_read(hdspm, HDSPM_RD_STATUS_3); /* s2 */
+
+	control = hdspm->control_register;
+
+	snd_iprintf(buffer, "STATUS1: 0x%08x\n", status1);
+	snd_iprintf(buffer, "STATUS2: 0x%08x\n", status2);
+	snd_iprintf(buffer, "STATUS3: 0x%08x\n", status3);
+
+
+	snd_iprintf(buffer, "\n*** CLOCK MODE\n\n");
+
+	snd_iprintf(buffer, "Clock mode      : %s\n",
+		(hdspm_system_clock_mode(hdspm) == 0) ? "master" : "slave");
+	snd_iprintf(buffer, "System frequency: %d Hz\n",
+		hdspm_get_system_sample_rate(hdspm));
+
+	snd_iprintf(buffer, "\n*** INPUT STATUS\n\n");
+
+	lock = 0x1;
+	sync = 0x100;
+
+	for (i = 0; i < 8; i++) {
+		snd_iprintf(buffer, "s1_input %d: Lock %d, Sync %d, Freq %s\n",
+				i,
+				(status1 & lock) ? 1 : 0,
+				(status1 & sync) ? 1 : 0,
+				texts_freq[(status2 >> (i * 4)) & 0xF]);
+
+		lock = lock<<1;
+		sync = sync<<1;
+	}
+
+	snd_iprintf(buffer, "WC input: Lock %d, Sync %d, Freq %s\n",
+			(status1 & 0x1000000) ? 1 : 0,
+			(status1 & 0x2000000) ? 1 : 0,
+			texts_freq[(status1 >> 16) & 0xF]);
+
+	snd_iprintf(buffer, "TCO input: Lock %d, Sync %d, Freq %s\n",
+			(status1 & 0x4000000) ? 1 : 0,
+			(status1 & 0x8000000) ? 1 : 0,
+			texts_freq[(status1 >> 20) & 0xF]);
+
+	snd_iprintf(buffer, "SYNC IN: Lock %d, Sync %d, Freq %s\n",
+			(status3 & 0x400) ? 1 : 0,
+			(status3 & 0x800) ? 1 : 0,
+			texts_freq[(status2 >> 12) & 0xF]);
+
+}
+
 #ifdef CONFIG_SND_DEBUG
 static void
-snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
+snd_hdspm_proc_read_debug(struct snd_info_entry *entry,
 			  struct snd_info_buffer *buffer)
 {
 	struct hdspm *hdspm = entry->private_data;
@@ -3322,16 +5012,68 @@ snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
 #endif
 
 
+static void snd_hdspm_proc_ports_in(struct snd_info_entry *entry,
+			  struct snd_info_buffer *buffer)
+{
+	struct hdspm *hdspm = entry->private_data;
+	int i;
+
+	snd_iprintf(buffer, "# generated by hdspm\n");
+
+	for (i = 0; i < hdspm->max_channels_in; i++) {
+		snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_in[i]);
+	}
+}
+
+static void snd_hdspm_proc_ports_out(struct snd_info_entry *entry,
+			  struct snd_info_buffer *buffer)
+{
+	struct hdspm *hdspm = entry->private_data;
+	int i;
+
+	snd_iprintf(buffer, "# generated by hdspm\n");
+
+	for (i = 0; i < hdspm->max_channels_out; i++) {
+		snd_iprintf(buffer, "%d=%s\n", i+1, hdspm->port_names_out[i]);
+	}
+}
+
 
-static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
+static void __devinit snd_hdspm_proc_init(struct hdspm *hdspm)
 {
 	struct snd_info_entry *entry;
 
-	if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
-		snd_info_set_text_ops(entry, hdspm,
-				      hdspm->is_aes32 ?
-				      snd_hdspm_proc_read_aes32 :
-				      snd_hdspm_proc_read_madi);
+	if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) {
+		switch (hdspm->io_type) {
+		case AES32:
+			snd_info_set_text_ops(entry, hdspm,
+					snd_hdspm_proc_read_aes32);
+			break;
+		case MADI:
+			snd_info_set_text_ops(entry, hdspm,
+					snd_hdspm_proc_read_madi);
+			break;
+		case MADIface:
+			/* snd_info_set_text_ops(entry, hdspm,
+			 snd_hdspm_proc_read_madiface); */
+			break;
+		case RayDAT:
+			snd_info_set_text_ops(entry, hdspm,
+					snd_hdspm_proc_read_raydat);
+			break;
+		case AIO:
+			break;
+		}
+	}
+
+	if (!snd_card_proc_new(hdspm->card, "ports.in", &entry)) {
+		snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_in);
+	}
+
+	if (!snd_card_proc_new(hdspm->card, "ports.out", &entry)) {
+		snd_info_set_text_ops(entry, hdspm, snd_hdspm_proc_ports_out);
+	}
+
 #ifdef CONFIG_SND_DEBUG
 	/* debug file to read all hdspm registers */
 	if (!snd_card_proc_new(hdspm->card, "debug", &entry))
@@ -3341,47 +5083,48 @@ static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
 }
 
 /*------------------------------------------------------------
-   hdspm intitialize 
+   hdspm intitialize
  ------------------------------------------------------------*/
 
 static int snd_hdspm_set_defaults(struct hdspm * hdspm)
 {
-	unsigned int i;
-
 	/* ASSUMPTION: hdspm->lock is either held, or there is no need to
 	   hold it (e.g. during module initialization).
-	 */
+	   */
 
 	/* set defaults:       */
 
-	if (hdspm->is_aes32)
+	hdspm->settings_register = 0;
+
+	switch (hdspm->io_type) {
+	case MADI:
+	case MADIface:
+		hdspm->control_register =
+			0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
+		break;
+
+	case RayDAT:
+	case AIO:
+		hdspm->settings_register = 0x1 + 0x1000;
+		/* Magic values are: LAT_0, LAT_2, Master, freq1, tx64ch, inp_0,
+		 * line_out */
+		hdspm->control_register =
+			0x2 + 0x8 + 0x10 + 0x80 + 0x400 + 0x4000 + 0x1000000;
+		break;
+
+	case AES32:
 		hdspm->control_register =
 			HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
-			hdspm_encode_latency(7) | /* latency maximum =
-						   * 8192 samples
-						   */
+			hdspm_encode_latency(7) | /* latency max=8192samples */
 			HDSPM_SyncRef0 |	/* AES1 is syncclock */
 			HDSPM_LineOut |	/* Analog output in */
 			HDSPM_Professional;  /* Professional mode */
-	else
-		hdspm->control_register =
-			HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
-			hdspm_encode_latency(7) | /* latency maximum =
-						   * 8192 samples
-						   */
-			HDSPM_InputCoaxial |	/* Input Coax not Optical */
-			HDSPM_SyncRef_MADI |	/* Madi is syncclock */
-			HDSPM_LineOut |	/* Analog output in */
-			HDSPM_TX_64ch |	/* transmit in 64ch mode */
-			HDSPM_AutoInp;	/* AutoInput chossing (takeover) */
-
-	/* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
-	/* !  HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
-	/* ! HDSPM_clr_tms = do not clear bits in track marks */
+		break;
+	}
 
 	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
 
-        if (!hdspm->is_aes32) {
+	if (AES32 == hdspm->io_type) {
 		/* No control2 register for AES32 */
 #ifdef SNDRV_BIG_ENDIAN
 		hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
@@ -3397,57 +5140,59 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
 
 	all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
 
-	if (line_outs_monitor[hdspm->dev]) {
-
-		snd_printk(KERN_INFO "HDSPM: "
-			   "sending all playback streams to line outs.\n");
-
-		for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
-			if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
-				return -EIO;
-		}
+	if (hdspm->io_type == AIO || hdspm->io_type == RayDAT) {
+		hdspm_write(hdspm, HDSPM_WR_SETTINGS, hdspm->settings_register);
 	}
 
 	/* set a default rate so that the channel map is set up. */
-	hdspm->channel_map = channel_map_madi_ss;
-	hdspm_set_rate(hdspm, 44100, 1);
+	hdspm_set_rate(hdspm, 48000, 1);
 
 	return 0;
 }
 
 
 /*------------------------------------------------------------
-   interrupt 
+   interrupt
  ------------------------------------------------------------*/
 
 static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
 {
 	struct hdspm *hdspm = (struct hdspm *) dev_id;
 	unsigned int status;
-	int audio;
-	int midi0;
-	int midi1;
-	unsigned int midi0status;
-	unsigned int midi1status;
-	int schedule = 0;
+	int i, audio, midi, schedule = 0;
+	/* cycles_t now; */
 
 	status = hdspm_read(hdspm, HDSPM_statusRegister);
 
 	audio = status & HDSPM_audioIRQPending;
-	midi0 = status & HDSPM_midi0IRQPending;
-	midi1 = status & HDSPM_midi1IRQPending;
+	midi = status & (HDSPM_midi0IRQPending | HDSPM_midi1IRQPending |
+			HDSPM_midi2IRQPending | HDSPM_midi3IRQPending);
+
+	/* now = get_cycles(); */
+	/**
+	 *   LAT_2..LAT_0 period  counter (win)  counter (mac)
+	 *          6       4096   ~256053425     ~514672358
+	 *          5       2048   ~128024983     ~257373821
+	 *          4       1024    ~64023706     ~128718089
+	 *          3        512    ~32005945      ~64385999
+	 *          2        256    ~16003039      ~32260176
+	 *          1        128     ~7998738      ~16194507
+	 *          0         64     ~3998231       ~8191558
+	 **/
+	/*
+	   snd_printk(KERN_INFO "snd_hdspm_interrupt %llu @ %llx\n",
+	   now-hdspm->last_interrupt, status & 0xFFC0);
+	   hdspm->last_interrupt = now;
+	*/
 
-	if (!audio && !midi0 && !midi1)
+	if (!audio && !midi)
 		return IRQ_NONE;
 
 	hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
 	hdspm->irq_count++;
 
-	midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
-	midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
 
 	if (audio) {
-
 		if (hdspm->capture_substream)
 			snd_pcm_period_elapsed(hdspm->capture_substream);
 
@@ -3455,118 +5200,44 @@ static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id)
 			snd_pcm_period_elapsed(hdspm->playback_substream);
 	}
 
-	if (midi0 && midi0status) {
-		/* we disable interrupts for this input until processing
-		 * is done
-		 */
-		hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
-		hdspm_write(hdspm, HDSPM_controlRegister,
-			    hdspm->control_register);
-		hdspm->midi[0].pending = 1;
-		schedule = 1;
-	}
-	if (midi1 && midi1status) {
-		/* we disable interrupts for this input until processing
-		 * is done
-		 */
-		hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
-		hdspm_write(hdspm, HDSPM_controlRegister,
-			    hdspm->control_register);
-		hdspm->midi[1].pending = 1;
-		schedule = 1;
+	if (midi) {
+		i = 0;
+		while (i < hdspm->midiPorts) {
+			if ((hdspm_read(hdspm,
+				hdspm->midi[i].statusIn) & 0xff) &&
+					(status & hdspm->midi[i].irq)) {
+				/* we disable interrupts for this input until
+				 * processing is done
+				 */
+				hdspm->control_register &= ~hdspm->midi[i].ie;
+				hdspm_write(hdspm, HDSPM_controlRegister,
+						hdspm->control_register);
+				hdspm->midi[i].pending = 1;
+				schedule = 1;
+			}
+
+			i++;
+		}
+
+		if (schedule)
+			tasklet_hi_schedule(&hdspm->midi_tasklet);
 	}
-	if (schedule)
-		tasklet_schedule(&hdspm->midi_tasklet);
+
 	return IRQ_HANDLED;
 }
 
 /*------------------------------------------------------------
-   pcm interface 
+   pcm interface
   ------------------------------------------------------------*/
 
 
-static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream *
-					      substream)
+static snd_pcm_uframes_t snd_hdspm_hw_pointer(struct snd_pcm_substream
+					      *substream)
 {
 	struct hdspm *hdspm = snd_pcm_substream_chip(substream);
 	return hdspm_hw_pointer(hdspm);
 }
 
-static char *hdspm_channel_buffer_location(struct hdspm * hdspm,
-					   int stream, int channel)
-{
-	int mapped_channel;
-
-	if (snd_BUG_ON(channel < 0 || channel >= HDSPM_MAX_CHANNELS))
-		return NULL;
-
-	mapped_channel = hdspm->channel_map[channel];
-	if (mapped_channel < 0)
-		return NULL;
-
-	if (stream == SNDRV_PCM_STREAM_CAPTURE)
-		return hdspm->capture_buffer +
-		    mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
-	else
-		return hdspm->playback_buffer +
-		    mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
-}
-
-
-/* dont know why need it ??? */
-static int snd_hdspm_playback_copy(struct snd_pcm_substream *substream,
-				   int channel, snd_pcm_uframes_t pos,
-				   void __user *src, snd_pcm_uframes_t count)
-{
-	struct hdspm *hdspm = snd_pcm_substream_chip(substream);
-	char *channel_buf;
-
-	if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4))
-		return -EINVAL;
-
-	channel_buf =
-		hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
-					      channel);
-
-	if (snd_BUG_ON(!channel_buf))
-		return -EIO;
-
-	return copy_from_user(channel_buf + pos * 4, src, count * 4);
-}
-
-static int snd_hdspm_capture_copy(struct snd_pcm_substream *substream,
-				  int channel, snd_pcm_uframes_t pos,
-				  void __user *dst, snd_pcm_uframes_t count)
-{
-	struct hdspm *hdspm = snd_pcm_substream_chip(substream);
-	char *channel_buf;
-
-	if (snd_BUG_ON(pos + count > HDSPM_CHANNEL_BUFFER_BYTES / 4))
-		return -EINVAL;
-
-	channel_buf =
-		hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
-					      channel);
-	if (snd_BUG_ON(!channel_buf))
-		return -EIO;
-	return copy_to_user(dst, channel_buf + pos * 4, count * 4);
-}
-
-static int snd_hdspm_hw_silence(struct snd_pcm_substream *substream,
-				int channel, snd_pcm_uframes_t pos,
-				snd_pcm_uframes_t count)
-{
-	struct hdspm *hdspm = snd_pcm_substream_chip(substream);
-	char *channel_buf;
-
-	channel_buf =
-		hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
-					      channel);
-	if (snd_BUG_ON(!channel_buf))
-		return -EIO;
-	memset(channel_buf + pos * 4, 0, count * 4);
-	return 0;
-}
 
 static int snd_hdspm_reset(struct snd_pcm_substream *substream)
 {
@@ -3589,7 +5260,7 @@ static int snd_hdspm_reset(struct snd_pcm_substream *substream)
 		snd_pcm_group_for_each_entry(s, substream) {
 			if (s == other) {
 				oruntime->status->hw_ptr =
-				    runtime->status->hw_ptr;
+					runtime->status->hw_ptr;
 				break;
 			}
 		}
@@ -3621,19 +5292,19 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 		/* The other stream is open, and not by the same
 		   task as this one. Make sure that the parameters
 		   that matter are the same.
-		 */
+		   */
 
 		if (params_rate(params) != hdspm->system_sample_rate) {
 			spin_unlock_irq(&hdspm->lock);
 			_snd_pcm_hw_param_setempty(params,
-						   SNDRV_PCM_HW_PARAM_RATE);
+					SNDRV_PCM_HW_PARAM_RATE);
 			return -EBUSY;
 		}
 
 		if (params_period_size(params) != hdspm->period_bytes / 4) {
 			spin_unlock_irq(&hdspm->lock);
 			_snd_pcm_hw_param_setempty(params,
-					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+					SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
 			return -EBUSY;
 		}
 
@@ -3646,18 +5317,20 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	spin_lock_irq(&hdspm->lock);
 	err = hdspm_set_rate(hdspm, params_rate(params), 0);
 	if (err < 0) {
+		snd_printk(KERN_INFO "err on hdspm_set_rate: %d\n", err);
 		spin_unlock_irq(&hdspm->lock);
 		_snd_pcm_hw_param_setempty(params,
-					   SNDRV_PCM_HW_PARAM_RATE);
+				SNDRV_PCM_HW_PARAM_RATE);
 		return err;
 	}
 	spin_unlock_irq(&hdspm->lock);
 
 	err = hdspm_set_interrupt_interval(hdspm,
-					   params_period_size(params));
+			params_period_size(params));
 	if (err < 0) {
+		snd_printk(KERN_INFO "err on hdspm_set_interrupt_interval: %d\n", err);
 		_snd_pcm_hw_param_setempty(params,
-					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+				SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
 		return err;
 	}
 
@@ -3667,10 +5340,13 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 	/* malloc all buffer even if not enabled to get sure */
 	/* Update for MADI rev 204: we need to allocate for all channels,
 	 * otherwise it doesn't work at 96kHz */
+
 	err =
-	    snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
-	if (err < 0)
+		snd_pcm_lib_malloc_pages(substream, HDSPM_DMA_AREA_BYTES);
+	if (err < 0) {
+		snd_printk(KERN_INFO "err on snd_pcm_lib_malloc_pages: %d\n", err);
 		return err;
+	}
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 
@@ -3681,7 +5357,7 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 			snd_hdspm_enable_out(hdspm, i, 1);
 
 		hdspm->playback_buffer =
-		    (unsigned char *) substream->runtime->dma_area;
+			(unsigned char *) substream->runtime->dma_area;
 		snd_printdd("Allocated sample buffer for playback at %p\n",
 				hdspm->playback_buffer);
 	} else {
@@ -3692,23 +5368,40 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
 			snd_hdspm_enable_in(hdspm, i, 1);
 
 		hdspm->capture_buffer =
-		    (unsigned char *) substream->runtime->dma_area;
+			(unsigned char *) substream->runtime->dma_area;
 		snd_printdd("Allocated sample buffer for capture at %p\n",
 				hdspm->capture_buffer);
 	}
+
 	/*
 	   snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
 	   substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 	   "playback" : "capture",
 	   snd_pcm_sgbuf_get_addr(substream, 0));
-	 */
+	   */
 	/*
-	snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
-			substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
-			  "playback" : "capture",
-			params_rate(params), params_channels(params),
-			params_buffer_size(params));
-	*/
+	   snd_printdd("set_hwparams: %s %d Hz, %d channels, bs = %d\n",
+	   substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+	   "playback" : "capture",
+	   params_rate(params), params_channels(params),
+	   params_buffer_size(params));
+	   */
+
+
+	/* Switch to native float format if requested */
+	if (SNDRV_PCM_FORMAT_FLOAT_LE == params_format(params)) {
+		if (!(hdspm->control_register & HDSPe_FLOAT_FORMAT))
+			snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE float format.\n");
+
+		hdspm->control_register |= HDSPe_FLOAT_FORMAT;
+	} else if (SNDRV_PCM_FORMAT_S32_LE == params_format(params)) {
+		if (hdspm->control_register & HDSPe_FLOAT_FORMAT)
+			snd_printk(KERN_INFO "hdspm: Switching to native 32bit LE integer format.\n");
+
+		hdspm->control_register &= ~HDSPe_FLOAT_FORMAT;
+	}
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
 	return 0;
 }
 
@@ -3719,14 +5412,14 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
 
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 
-		/* params_channels(params) should be enough, 
+		/* params_channels(params) should be enough,
 		   but to get sure in case of error */
-		for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+		for (i = 0; i < hdspm->max_channels_out; ++i)
 			snd_hdspm_enable_out(hdspm, i, 0);
 
 		hdspm->playback_buffer = NULL;
 	} else {
-		for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+		for (i = 0; i < hdspm->max_channels_in; ++i)
 			snd_hdspm_enable_in(hdspm, i, 0);
 
 		hdspm->capture_buffer = NULL;
@@ -3738,37 +5431,58 @@ static int snd_hdspm_hw_free(struct snd_pcm_substream *substream)
 	return 0;
 }
 
+
 static int snd_hdspm_channel_info(struct snd_pcm_substream *substream,
-				  struct snd_pcm_channel_info * info)
+		struct snd_pcm_channel_info *info)
 {
 	struct hdspm *hdspm = snd_pcm_substream_chip(substream);
-	int mapped_channel;
 
-	if (snd_BUG_ON(info->channel >= HDSPM_MAX_CHANNELS))
-		return -EINVAL;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) {
+			snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel out of range (%d)\n", info->channel);
+			return -EINVAL;
+		}
 
-	mapped_channel = hdspm->channel_map[info->channel];
-	if (mapped_channel < 0)
-		return -EINVAL;
+		if (hdspm->channel_map_out[info->channel] < 0) {
+			snd_printk(KERN_INFO "snd_hdspm_channel_info: output channel %d mapped out\n", info->channel);
+			return -EINVAL;
+		}
+
+		info->offset = hdspm->channel_map_out[info->channel] *
+			HDSPM_CHANNEL_BUFFER_BYTES;
+	} else {
+		if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) {
+			snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel out of range (%d)\n", info->channel);
+			return -EINVAL;
+		}
+
+		if (hdspm->channel_map_in[info->channel] < 0) {
+			snd_printk(KERN_INFO "snd_hdspm_channel_info: input channel %d mapped out\n", info->channel);
+			return -EINVAL;
+		}
+
+		info->offset = hdspm->channel_map_in[info->channel] *
+			HDSPM_CHANNEL_BUFFER_BYTES;
+	}
 
-	info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
 	info->first = 0;
 	info->step = 32;
 	return 0;
 }
 
+
 static int snd_hdspm_ioctl(struct snd_pcm_substream *substream,
-			   unsigned int cmd, void *arg)
+		unsigned int cmd, void *arg)
 {
 	switch (cmd) {
 	case SNDRV_PCM_IOCTL1_RESET:
 		return snd_hdspm_reset(substream);
 
 	case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
-	{
-		struct snd_pcm_channel_info *info = arg;
-		return snd_hdspm_channel_info(substream, info);
-	}
+		{
+			struct snd_pcm_channel_info *info = arg;
+			return snd_hdspm_channel_info(substream, info);
+		}
 	default:
 		break;
 	}
@@ -3815,19 +5529,19 @@ static int snd_hdspm_trigger(struct snd_pcm_substream *substream, int cmd)
 		}
 		if (cmd == SNDRV_PCM_TRIGGER_START) {
 			if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
-			    && substream->stream ==
-			    SNDRV_PCM_STREAM_CAPTURE)
+					&& substream->stream ==
+					SNDRV_PCM_STREAM_CAPTURE)
 				hdspm_silence_playback(hdspm);
 		} else {
 			if (running &&
-			    substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+				substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
 				hdspm_silence_playback(hdspm);
 		}
 	} else {
 		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 			hdspm_silence_playback(hdspm);
 	}
-      _ok:
+_ok:
 	snd_pcm_trigger_done(substream, substream);
 	if (!hdspm->running && running)
 		hdspm_start_audio(hdspm);
@@ -3844,8 +5558,18 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static unsigned int period_sizes[] =
-    { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
+static unsigned int period_sizes_old[] = {
+	64, 128, 256, 512, 1024, 2048, 4096
+};
+
+static unsigned int period_sizes_new[] = {
+	32, 64, 128, 256, 512, 1024, 2048, 4096
+};
+
+/* RayDAT and AIO always have a buffer of 16384 samples per channel */
+static unsigned int raydat_aio_buffer_sizes[] = {
+	16384
+};
 
 static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
 	.info = (SNDRV_PCM_INFO_MMAP |
@@ -3866,9 +5590,9 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
 	.buffer_bytes_max =
 	    HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
 	.period_bytes_min = (64 * 4),
-	.period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+	.period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
 	.periods_min = 2,
-	.periods_max = 2,
+	.periods_max = 512,
 	.fifo_size = 0
 };
 
@@ -3891,20 +5615,66 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
 	.buffer_bytes_max =
 	    HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
 	.period_bytes_min = (64 * 4),
-	.period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+	.period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
 	.periods_min = 2,
-	.periods_max = 2,
+	.periods_max = 512,
 	.fifo_size = 0
 };
 
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes = {
-	.count = ARRAY_SIZE(period_sizes),
-	.list = period_sizes,
+static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
+	.count = ARRAY_SIZE(period_sizes_old),
+	.list = period_sizes_old,
+	.mask = 0
+};
+
+static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
+	.count = ARRAY_SIZE(period_sizes_new),
+	.list = period_sizes_new,
 	.mask = 0
 };
 
+static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
+	.count = ARRAY_SIZE(raydat_aio_buffer_sizes),
+	.list = raydat_aio_buffer_sizes,
+	.mask = 0
+};
+
+static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
+					   struct snd_pcm_hw_rule *rule)
+{
+	struct hdspm *hdspm = rule->private;
+	struct snd_interval *c =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct snd_interval *r =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+	if (r->min > 96000 && r->max <= 192000) {
+		struct snd_interval t = {
+			.min = hdspm->qs_in_channels,
+			.max = hdspm->qs_in_channels,
+			.integer = 1,
+		};
+		return snd_interval_refine(c, &t);
+	} else if (r->min > 48000 && r->max <= 96000) {
+		struct snd_interval t = {
+			.min = hdspm->ds_in_channels,
+			.max = hdspm->ds_in_channels,
+			.integer = 1,
+		};
+		return snd_interval_refine(c, &t);
+	} else if (r->max < 64000) {
+		struct snd_interval t = {
+			.min = hdspm->ss_in_channels,
+			.max = hdspm->ss_in_channels,
+			.integer = 1,
+		};
+		return snd_interval_refine(c, &t);
+	}
 
-static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
+	return 0;
+}
+
+static int snd_hdspm_hw_rule_out_channels_rate(struct snd_pcm_hw_params *params,
 					   struct snd_pcm_hw_rule * rule)
 {
 	struct hdspm *hdspm = rule->private;
@@ -3913,25 +5683,33 @@ static int snd_hdspm_hw_rule_channels_rate(struct snd_pcm_hw_params *params,
 	struct snd_interval *r =
 	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 
-	if (r->min > 48000 && r->max <= 96000) {
+	if (r->min > 96000 && r->max <= 192000) {
+		struct snd_interval t = {
+			.min = hdspm->qs_out_channels,
+			.max = hdspm->qs_out_channels,
+			.integer = 1,
+		};
+		return snd_interval_refine(c, &t);
+	} else if (r->min > 48000 && r->max <= 96000) {
 		struct snd_interval t = {
-			.min = hdspm->ds_channels,
-			.max = hdspm->ds_channels,
+			.min = hdspm->ds_out_channels,
+			.max = hdspm->ds_out_channels,
 			.integer = 1,
 		};
 		return snd_interval_refine(c, &t);
 	} else if (r->max < 64000) {
 		struct snd_interval t = {
-			.min = hdspm->ss_channels,
-			.max = hdspm->ss_channels,
+			.min = hdspm->ss_out_channels,
+			.max = hdspm->ss_out_channels,
 			.integer = 1,
 		};
 		return snd_interval_refine(c, &t);
+	} else {
 	}
 	return 0;
 }
 
-static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
+static int snd_hdspm_hw_rule_rate_in_channels(struct snd_pcm_hw_params *params,
 					   struct snd_pcm_hw_rule * rule)
 {
 	struct hdspm *hdspm = rule->private;
@@ -3940,42 +5718,92 @@ static int snd_hdspm_hw_rule_rate_channels(struct snd_pcm_hw_params *params,
 	struct snd_interval *r =
 	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 
-	if (c->min >= hdspm->ss_channels) {
+	if (c->min >= hdspm->ss_in_channels) {
 		struct snd_interval t = {
 			.min = 32000,
 			.max = 48000,
 			.integer = 1,
 		};
 		return snd_interval_refine(r, &t);
-	} else if (c->max <= hdspm->ds_channels) {
+	} else if (c->max <= hdspm->qs_in_channels) {
+		struct snd_interval t = {
+			.min = 128000,
+			.max = 192000,
+			.integer = 1,
+		};
+		return snd_interval_refine(r, &t);
+	} else if (c->max <= hdspm->ds_in_channels) {
 		struct snd_interval t = {
 			.min = 64000,
 			.max = 96000,
 			.integer = 1,
 		};
+		return snd_interval_refine(r, &t);
+	}
+
+	return 0;
+}
+static int snd_hdspm_hw_rule_rate_out_channels(struct snd_pcm_hw_params *params,
+					   struct snd_pcm_hw_rule *rule)
+{
+	struct hdspm *hdspm = rule->private;
+	struct snd_interval *c =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	struct snd_interval *r =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
 
+	if (c->min >= hdspm->ss_out_channels) {
+		struct snd_interval t = {
+			.min = 32000,
+			.max = 48000,
+			.integer = 1,
+		};
+		return snd_interval_refine(r, &t);
+	} else if (c->max <= hdspm->qs_out_channels) {
+		struct snd_interval t = {
+			.min = 128000,
+			.max = 192000,
+			.integer = 1,
+		};
+		return snd_interval_refine(r, &t);
+	} else if (c->max <= hdspm->ds_out_channels) {
+		struct snd_interval t = {
+			.min = 64000,
+			.max = 96000,
+			.integer = 1,
+		};
 		return snd_interval_refine(r, &t);
 	}
+
 	return 0;
 }
 
-static int snd_hdspm_hw_rule_channels(struct snd_pcm_hw_params *params,
+static int snd_hdspm_hw_rule_in_channels(struct snd_pcm_hw_params *params,
 				      struct snd_pcm_hw_rule *rule)
 {
 	unsigned int list[3];
 	struct hdspm *hdspm = rule->private;
 	struct snd_interval *c = hw_param_interval(params,
 			SNDRV_PCM_HW_PARAM_CHANNELS);
-	if (hdspm->is_aes32) {
-		list[0] = hdspm->qs_channels;
-		list[1] = hdspm->ds_channels;
-		list[2] = hdspm->ss_channels;
-		return snd_interval_list(c, 3, list, 0);
-	} else {
-		list[0] = hdspm->ds_channels;
-		list[1] = hdspm->ss_channels;
-		return snd_interval_list(c, 2, list, 0);
-	}
+
+	list[0] = hdspm->qs_in_channels;
+	list[1] = hdspm->ds_in_channels;
+	list[2] = hdspm->ss_in_channels;
+	return snd_interval_list(c, 3, list, 0);
+}
+
+static int snd_hdspm_hw_rule_out_channels(struct snd_pcm_hw_params *params,
+				      struct snd_pcm_hw_rule *rule)
+{
+	unsigned int list[3];
+	struct hdspm *hdspm = rule->private;
+	struct snd_interval *c = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	list[0] = hdspm->qs_out_channels;
+	list[1] = hdspm->ds_out_channels;
+	list[2] = hdspm->ss_out_channels;
+	return snd_interval_list(c, 3, list, 0);
 }
 
 
@@ -3999,6 +5827,7 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
 
 	snd_pcm_set_sync(substream);
 
+
 	runtime->hw = snd_hdspm_playback_subinfo;
 
 	if (hdspm->capture_substream == NULL)
@@ -4011,25 +5840,41 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
 
-	snd_pcm_hw_constraint_list(runtime, 0,
-				   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-				   &hw_constraints_period_sizes);
+	switch (hdspm->io_type) {
+	case AIO:
+	case RayDAT:
+		snd_pcm_hw_constraint_list(runtime, 0,
+				SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+				&hw_constraints_period_sizes_new);
+		snd_pcm_hw_constraint_list(runtime, 0,
+				SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+				&hw_constraints_raydat_io_buffer);
+
+		break;
+
+	default:
+		snd_pcm_hw_constraint_list(runtime, 0,
+				SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+				&hw_constraints_period_sizes_old);
+	}
 
-	if (hdspm->is_aes32) {
+	if (AES32 == hdspm->io_type) {
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 				&hdspm_hw_constraints_aes32_sample_rates);
 	} else {
-		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-				     snd_hdspm_hw_rule_channels, hdspm,
-				     SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-				    snd_hdspm_hw_rule_channels_rate, hdspm,
-				    SNDRV_PCM_HW_PARAM_RATE, -1);
-
 		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-				    snd_hdspm_hw_rule_rate_channels, hdspm,
-				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+				snd_hdspm_hw_rule_rate_out_channels, hdspm,
+				SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 	}
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+			snd_hdspm_hw_rule_out_channels, hdspm,
+			SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+			snd_hdspm_hw_rule_out_channels_rate, hdspm,
+			SNDRV_PCM_HW_PARAM_RATE, -1);
+
 	return 0;
 }
 
@@ -4066,24 +5911,40 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
 	spin_unlock_irq(&hdspm->lock);
 
 	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
-	snd_pcm_hw_constraint_list(runtime, 0,
-				   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
-				   &hw_constraints_period_sizes);
-	if (hdspm->is_aes32) {
+	switch (hdspm->io_type) {
+	case AIO:
+	case RayDAT:
+	  snd_pcm_hw_constraint_list(runtime, 0,
+				     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+				     &hw_constraints_period_sizes_new);
+	  snd_pcm_hw_constraint_list(runtime, 0,
+				     SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+				     &hw_constraints_raydat_io_buffer);
+	  break;
+
+	default:
+	  snd_pcm_hw_constraint_list(runtime, 0,
+				     SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+				     &hw_constraints_period_sizes_old);
+	}
+
+	if (AES32 == hdspm->io_type) {
 		snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
 				&hdspm_hw_constraints_aes32_sample_rates);
 	} else {
-		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-				     snd_hdspm_hw_rule_channels, hdspm,
-				     SNDRV_PCM_HW_PARAM_CHANNELS, -1);
-		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
-				    snd_hdspm_hw_rule_channels_rate, hdspm,
-				    SNDRV_PCM_HW_PARAM_RATE, -1);
-
 		snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
-				    snd_hdspm_hw_rule_rate_channels, hdspm,
-				    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+				snd_hdspm_hw_rule_rate_in_channels, hdspm,
+				SNDRV_PCM_HW_PARAM_CHANNELS, -1);
 	}
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+			snd_hdspm_hw_rule_in_channels, hdspm,
+			SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+			snd_hdspm_hw_rule_in_channels_rate, hdspm,
+			SNDRV_PCM_HW_PARAM_RATE, -1);
+
 	return 0;
 }
 
@@ -4100,32 +5961,129 @@ static int snd_hdspm_capture_release(struct snd_pcm_substream *substream)
 	return 0;
 }
 
-static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
-				 unsigned int cmd, unsigned long arg)
+static int snd_hdspm_hwdep_dummy_op(struct snd_hwdep *hw, struct file *file)
+{
+	/* we have nothing to initialize but the call is required */
+	return 0;
+}
+
+static inline int copy_u32_le(void __user *dest, void __iomem *src)
+{
+	u32 val = readl(src);
+	return copy_to_user(dest, &val, 4);
+}
+
+static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
+		unsigned int cmd, unsigned long __user arg)
 {
+	void __user *argp = (void __user *)arg;
 	struct hdspm *hdspm = hw->private_data;
 	struct hdspm_mixer_ioctl mixer;
-	struct hdspm_config_info info;
+	struct hdspm_config info;
+	struct hdspm_status status;
 	struct hdspm_version hdspm_version;
-	struct hdspm_peak_rms_ioctl rms;
+	struct hdspm_peak_rms *levels;
+	struct hdspm_ltc ltc;
+	unsigned int statusregister;
+	long unsigned int s;
+	int i = 0;
 
 	switch (cmd) {
 
 	case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
-		if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
+		levels = &hdspm->peak_rms;
+		for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
+			levels->input_peaks[i] =
+				readl(hdspm->iobase +
+						HDSPM_MADI_INPUT_PEAK + i*4);
+			levels->playback_peaks[i] =
+				readl(hdspm->iobase +
+						HDSPM_MADI_PLAYBACK_PEAK + i*4);
+			levels->output_peaks[i] =
+				readl(hdspm->iobase +
+						HDSPM_MADI_OUTPUT_PEAK + i*4);
+
+			levels->input_rms[i] =
+				((uint64_t) readl(hdspm->iobase +
+					HDSPM_MADI_INPUT_RMS_H + i*4) << 32) |
+				(uint64_t) readl(hdspm->iobase +
+						HDSPM_MADI_INPUT_RMS_L + i*4);
+			levels->playback_rms[i] =
+				((uint64_t)readl(hdspm->iobase +
+					HDSPM_MADI_PLAYBACK_RMS_H+i*4) << 32) |
+				(uint64_t)readl(hdspm->iobase +
+					HDSPM_MADI_PLAYBACK_RMS_L + i*4);
+			levels->output_rms[i] =
+				((uint64_t)readl(hdspm->iobase +
+					HDSPM_MADI_OUTPUT_RMS_H + i*4) << 32) |
+				(uint64_t)readl(hdspm->iobase +
+						HDSPM_MADI_OUTPUT_RMS_L + i*4);
+		}
+
+		if (hdspm->system_sample_rate > 96000) {
+			levels->speed = qs;
+		} else if (hdspm->system_sample_rate > 48000) {
+			levels->speed = ds;
+		} else {
+			levels->speed = ss;
+		}
+		levels->status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+		s = copy_to_user(argp, levels, sizeof(struct hdspm_peak_rms));
+		if (0 != s) {
+			/* snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu
+			 [Levels]\n", sizeof(struct hdspm_peak_rms), s);
+			 */
 			return -EFAULT;
-		/* maybe there is a chance to memorymap in future
-		 * so dont touch just copy
-		 */
-		if(copy_to_user_fromio((void __user *)rms.peak,
-				       hdspm->iobase+HDSPM_MADI_peakrmsbase,
-				       sizeof(struct hdspm_peak_rms)) != 0 )
+		}
+		break;
+
+	case SNDRV_HDSPM_IOCTL_GET_LTC:
+		ltc.ltc = hdspm_read(hdspm, HDSPM_RD_TCO);
+		i = hdspm_read(hdspm, HDSPM_RD_TCO + 4);
+		if (i & HDSPM_TCO1_LTC_Input_valid) {
+			switch (i & (HDSPM_TCO1_LTC_Format_LSB |
+				HDSPM_TCO1_LTC_Format_MSB)) {
+			case 0:
+				ltc.format = fps_24;
+				break;
+			case HDSPM_TCO1_LTC_Format_LSB:
+				ltc.format = fps_25;
+				break;
+			case HDSPM_TCO1_LTC_Format_MSB:
+				ltc.format = fps_2997;
+				break;
+			default:
+				ltc.format = 30;
+				break;
+			}
+			if (i & HDSPM_TCO1_set_drop_frame_flag) {
+				ltc.frame = drop_frame;
+			} else {
+				ltc.frame = full_frame;
+			}
+		} else {
+			ltc.format = format_invalid;
+			ltc.frame = frame_invalid;
+		}
+		if (i & HDSPM_TCO1_Video_Input_Format_NTSC) {
+			ltc.input_format = ntsc;
+		} else if (i & HDSPM_TCO1_Video_Input_Format_PAL) {
+			ltc.input_format = pal;
+		} else {
+			ltc.input_format = no_video;
+		}
+
+		s = copy_to_user(argp, &ltc, sizeof(struct hdspm_ltc));
+		if (0 != s) {
+			/*
+			 snd_printk(KERN_ERR "copy_to_user(.., .., %lu): %lu [LTC]\n", sizeof(struct hdspm_ltc), s); */
 			return -EFAULT;
+		}
 
 		break;
-		
 
-	case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
+	case SNDRV_HDSPM_IOCTL_GET_CONFIG:
 
 		memset(&info, 0, sizeof(info));
 		spin_lock_irq(&hdspm->lock);
@@ -4134,7 +6092,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
 
 		info.system_sample_rate = hdspm->system_sample_rate;
 		info.autosync_sample_rate =
-		    hdspm_external_sample_rate(hdspm);
+			hdspm_external_sample_rate(hdspm);
 		info.system_clock_mode = hdspm_system_clock_mode(hdspm);
 		info.clock_source = hdspm_clock_source(hdspm);
 		info.autosync_ref = hdspm_autosync_ref(hdspm);
@@ -4145,10 +6103,58 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
 			return -EFAULT;
 		break;
 
+	case SNDRV_HDSPM_IOCTL_GET_STATUS:
+		status.card_type = hdspm->io_type;
+
+		status.autosync_source = hdspm_autosync_ref(hdspm);
+
+		status.card_clock = 110069313433624ULL;
+		status.master_period = hdspm_read(hdspm, HDSPM_RD_PLL_FREQ);
+
+		switch (hdspm->io_type) {
+		case MADI:
+		case MADIface:
+			status.card_specific.madi.sync_wc =
+				hdspm_wc_sync_check(hdspm);
+			status.card_specific.madi.sync_madi =
+				hdspm_madi_sync_check(hdspm);
+			status.card_specific.madi.sync_tco =
+				hdspm_tco_sync_check(hdspm);
+			status.card_specific.madi.sync_in =
+				hdspm_sync_in_sync_check(hdspm);
+
+			statusregister =
+				hdspm_read(hdspm, HDSPM_statusRegister);
+			status.card_specific.madi.madi_input =
+				(statusregister & HDSPM_AB_int) ? 1 : 0;
+			status.card_specific.madi.channel_format =
+				(statusregister & HDSPM_TX_64ch) ? 1 : 0;
+			/* TODO: Mac driver sets it when f_s>48kHz */
+			status.card_specific.madi.frame_format = 0;
+
+		default:
+			break;
+		}
+
+		if (copy_to_user((void __user *) arg, &status, sizeof(status)))
+			return -EFAULT;
+
+
+		break;
+
 	case SNDRV_HDSPM_IOCTL_GET_VERSION:
+		hdspm_version.card_type = hdspm->io_type;
+		strncpy(hdspm_version.cardname, hdspm->card_name,
+				sizeof(hdspm_version.cardname));
+		hdspm_version.serial = (hdspm_read(hdspm,
+					HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
 		hdspm_version.firmware_rev = hdspm->firmware_rev;
+		hdspm_version.addons = 0;
+		if (hdspm->tco)
+			hdspm_version.addons |= HDSPM_ADDON_TCO;
+
 		if (copy_to_user((void __user *) arg, &hdspm_version,
-				 sizeof(hdspm_version)))
+					sizeof(hdspm_version)))
 			return -EFAULT;
 		break;
 
@@ -4156,7 +6162,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep * hw, struct file *file,
 		if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
 			return -EFAULT;
 		if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
-				 sizeof(struct hdspm_mixer)))
+					sizeof(struct hdspm_mixer)))
 			return -EFAULT;
 		break;
 
@@ -4175,8 +6181,6 @@ static struct snd_pcm_ops snd_hdspm_playback_ops = {
 	.prepare = snd_hdspm_prepare,
 	.trigger = snd_hdspm_trigger,
 	.pointer = snd_hdspm_hw_pointer,
-	.copy = snd_hdspm_playback_copy,
-	.silence = snd_hdspm_hw_silence,
 	.page = snd_pcm_sgbuf_ops_page,
 };
 
@@ -4189,7 +6193,6 @@ static struct snd_pcm_ops snd_hdspm_capture_ops = {
 	.prepare = snd_hdspm_prepare,
 	.trigger = snd_hdspm_trigger,
 	.pointer = snd_hdspm_hw_pointer,
-	.copy = snd_hdspm_capture_copy,
 	.page = snd_pcm_sgbuf_ops_page,
 };
 
@@ -4207,16 +6210,18 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
 	hw->private_data = hdspm;
 	strcpy(hw->name, "HDSPM hwdep interface");
 
+	hw->ops.open = snd_hdspm_hwdep_dummy_op;
 	hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
+	hw->ops.release = snd_hdspm_hwdep_dummy_op;
 
 	return 0;
 }
 
 
 /*------------------------------------------------------------
-   memory interface 
+   memory interface
  ------------------------------------------------------------*/
-static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
+static int __devinit snd_hdspm_preallocate_memory(struct hdspm *hdspm)
 {
 	int err;
 	struct snd_pcm *pcm;
@@ -4228,7 +6233,7 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
 
 	err =
 	     snd_pcm_lib_preallocate_pages_for_all(pcm,
-	     					   SNDRV_DMA_TYPE_DEV_SG,
+						   SNDRV_DMA_TYPE_DEV_SG,
 						   snd_dma_pci_data(hdspm->pci),
 						   wanted,
 						   wanted);
@@ -4242,19 +6247,23 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
 	return 0;
 }
 
-static void hdspm_set_sgbuf(struct hdspm * hdspm,
+
+static void hdspm_set_sgbuf(struct hdspm *hdspm,
 			    struct snd_pcm_substream *substream,
 			     unsigned int reg, int channels)
 {
 	int i;
+
+	/* continuous memory segment */
 	for (i = 0; i < (channels * 16); i++)
 		hdspm_write(hdspm, reg + 4 * i,
-			    snd_pcm_sgbuf_get_addr(substream, 4096 * i));
+				snd_pcm_sgbuf_get_addr(substream, 4096 * i));
 }
 
+
 /* ------------- ALSA Devices ---------------------------- */
 static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
-					  struct hdspm * hdspm)
+					  struct hdspm *hdspm)
 {
 	struct snd_pcm *pcm;
 	int err;
@@ -4283,27 +6292,30 @@ static int __devinit snd_hdspm_create_pcm(struct snd_card *card,
 
 static inline void snd_hdspm_initialize_midi_flush(struct hdspm * hdspm)
 {
-	snd_hdspm_flush_midi_input(hdspm, 0);
-	snd_hdspm_flush_midi_input(hdspm, 1);
+	int i;
+
+	for (i = 0; i < hdspm->midiPorts; i++)
+		snd_hdspm_flush_midi_input(hdspm, i);
 }
 
 static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
 						   struct hdspm * hdspm)
 {
-	int err;
+	int err, i;
 
 	snd_printdd("Create card...\n");
 	err = snd_hdspm_create_pcm(card, hdspm);
 	if (err < 0)
 		return err;
 
-	err = snd_hdspm_create_midi(card, hdspm, 0);
-	if (err < 0)
-		return err;
-
-	err = snd_hdspm_create_midi(card, hdspm, 1);
-	if (err < 0)
-		return err;
+	i = 0;
+	while (i < hdspm->midiPorts) {
+		err = snd_hdspm_create_midi(card, hdspm, i);
+		if (err < 0) {
+			return err;
+		}
+		i++;
+	}
 
 	err = snd_hdspm_create_controls(card, hdspm);
 	if (err < 0)
@@ -4346,37 +6358,55 @@ static int __devinit snd_hdspm_create_alsa_devices(struct snd_card *card,
 }
 
 static int __devinit snd_hdspm_create(struct snd_card *card,
-				      struct hdspm *hdspm,
-				      int precise_ptr, int enable_monitor)
-{
+		struct hdspm *hdspm) {
+
 	struct pci_dev *pci = hdspm->pci;
 	int err;
 	unsigned long io_extent;
 
 	hdspm->irq = -1;
-
-	spin_lock_init(&hdspm->midi[0].lock);
-	spin_lock_init(&hdspm->midi[1].lock);
-
 	hdspm->card = card;
 
 	spin_lock_init(&hdspm->lock);
 
-	tasklet_init(&hdspm->midi_tasklet,
-		     hdspm_midi_tasklet, (unsigned long) hdspm);
-
 	pci_read_config_word(hdspm->pci,
-			     PCI_CLASS_REVISION, &hdspm->firmware_rev);
-
-	hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
+			PCI_CLASS_REVISION, &hdspm->firmware_rev);
 
 	strcpy(card->mixername, "Xilinx FPGA");
-	if (hdspm->is_aes32) {
-		strcpy(card->driver, "HDSPAES32");
-		hdspm->card_name = "RME HDSPM AES32";
-	} else {
-		strcpy(card->driver, "HDSPM");
-		hdspm->card_name = "RME HDSPM MADI";
+	strcpy(card->driver, "HDSPM");
+
+	switch (hdspm->firmware_rev) {
+	case HDSPM_MADI_REV:
+		hdspm->io_type = MADI;
+		hdspm->card_name = "RME MADI";
+		hdspm->midiPorts = 3;
+		break;
+	case HDSPM_RAYDAT_REV:
+		hdspm->io_type = RayDAT;
+		hdspm->card_name = "RME RayDAT";
+		hdspm->midiPorts = 2;
+		break;
+	case HDSPM_AIO_REV:
+		hdspm->io_type = AIO;
+		hdspm->card_name = "RME AIO";
+		hdspm->midiPorts = 1;
+		break;
+	case HDSPM_MADIFACE_REV:
+		hdspm->io_type = MADIface;
+		hdspm->card_name = "RME MADIface";
+		hdspm->midiPorts = 1;
+		break;
+	case HDSPM_AES_REV:
+	case HDSPM_AES32_REV:
+	case HDSPM_AES32_OLD_REV:
+		hdspm->io_type = AES32;
+		hdspm->card_name = "RME AES32";
+		hdspm->midiPorts = 2;
+		break;
+	default:
+		snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
+				hdspm->firmware_rev);
+		return -ENODEV;
 	}
 
 	err = pci_enable_device(pci);
@@ -4393,22 +6423,21 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
 	io_extent = pci_resource_len(pci, 0);
 
 	snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
-		   hdspm->port, hdspm->port + io_extent - 1);
-
+			hdspm->port, hdspm->port + io_extent - 1);
 
 	hdspm->iobase = ioremap_nocache(hdspm->port, io_extent);
 	if (!hdspm->iobase) {
 		snd_printk(KERN_ERR "HDSPM: "
-			   "unable to remap region 0x%lx-0x%lx\n",
-			   hdspm->port, hdspm->port + io_extent - 1);
+				"unable to remap region 0x%lx-0x%lx\n",
+				hdspm->port, hdspm->port + io_extent - 1);
 		return -EBUSY;
 	}
 	snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
-		   (unsigned long)hdspm->iobase, hdspm->port,
-		   hdspm->port + io_extent - 1);
+			(unsigned long)hdspm->iobase, hdspm->port,
+			hdspm->port + io_extent - 1);
 
 	if (request_irq(pci->irq, snd_hdspm_interrupt,
-			IRQF_SHARED, "hdspm", hdspm)) {
+				IRQF_SHARED, "hdspm", hdspm)) {
 		snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
@@ -4416,23 +6445,219 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
 	snd_printdd("use IRQ %d\n", pci->irq);
 
 	hdspm->irq = pci->irq;
-	hdspm->precise_ptr = precise_ptr;
-
-	hdspm->monitor_outs = enable_monitor;
 
 	snd_printdd("kmalloc Mixer memory of %zd Bytes\n",
-		   sizeof(struct hdspm_mixer));
+			sizeof(struct hdspm_mixer));
 	hdspm->mixer = kzalloc(sizeof(struct hdspm_mixer), GFP_KERNEL);
 	if (!hdspm->mixer) {
 		snd_printk(KERN_ERR "HDSPM: "
-			   "unable to kmalloc Mixer memory of %d Bytes\n",
-			   (int)sizeof(struct hdspm_mixer));
+				"unable to kmalloc Mixer memory of %d Bytes\n",
+				(int)sizeof(struct hdspm_mixer));
 		return err;
 	}
 
-	hdspm->ss_channels = MADI_SS_CHANNELS;
-	hdspm->ds_channels = MADI_DS_CHANNELS;
-	hdspm->qs_channels = MADI_QS_CHANNELS;
+	hdspm->port_names_in = NULL;
+	hdspm->port_names_out = NULL;
+
+	switch (hdspm->io_type) {
+	case AES32:
+		hdspm->ss_in_channels = hdspm->ss_out_channels = AES32_CHANNELS;
+		hdspm->ds_in_channels = hdspm->ds_out_channels = AES32_CHANNELS;
+		hdspm->qs_in_channels = hdspm->qs_out_channels = AES32_CHANNELS;
+
+		hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
+			channel_map_aes32;
+		hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
+			channel_map_aes32;
+		hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
+			channel_map_aes32;
+		hdspm->port_names_in_ss = hdspm->port_names_out_ss =
+			texts_ports_aes32;
+		hdspm->port_names_in_ds = hdspm->port_names_out_ds =
+			texts_ports_aes32;
+		hdspm->port_names_in_qs = hdspm->port_names_out_qs =
+			texts_ports_aes32;
+
+		hdspm->max_channels_out = hdspm->max_channels_in =
+			AES32_CHANNELS;
+		hdspm->port_names_in = hdspm->port_names_out =
+			texts_ports_aes32;
+		hdspm->channel_map_in = hdspm->channel_map_out =
+			channel_map_aes32;
+
+		break;
+
+	case MADI:
+	case MADIface:
+		hdspm->ss_in_channels = hdspm->ss_out_channels =
+			MADI_SS_CHANNELS;
+		hdspm->ds_in_channels = hdspm->ds_out_channels =
+			MADI_DS_CHANNELS;
+		hdspm->qs_in_channels = hdspm->qs_out_channels =
+			MADI_QS_CHANNELS;
+
+		hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
+			channel_map_unity_ss;
+		hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
+			channel_map_unity_ss;
+		hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
+			channel_map_unity_ss;
+
+		hdspm->port_names_in_ss = hdspm->port_names_out_ss =
+			texts_ports_madi;
+		hdspm->port_names_in_ds = hdspm->port_names_out_ds =
+			texts_ports_madi;
+		hdspm->port_names_in_qs = hdspm->port_names_out_qs =
+			texts_ports_madi;
+		break;
+
+	case AIO:
+		if (0 == (hdspm_read(hdspm, HDSPM_statusRegister2) & HDSPM_s2_AEBI_D)) {
+			snd_printk(KERN_INFO "HDSPM: AEB input board found, but not supported\n");
+		}
+
+		hdspm->ss_in_channels = AIO_IN_SS_CHANNELS;
+		hdspm->ds_in_channels = AIO_IN_DS_CHANNELS;
+		hdspm->qs_in_channels = AIO_IN_QS_CHANNELS;
+		hdspm->ss_out_channels = AIO_OUT_SS_CHANNELS;
+		hdspm->ds_out_channels = AIO_OUT_DS_CHANNELS;
+		hdspm->qs_out_channels = AIO_OUT_QS_CHANNELS;
+
+		hdspm->channel_map_out_ss = channel_map_aio_out_ss;
+		hdspm->channel_map_out_ds = channel_map_aio_out_ds;
+		hdspm->channel_map_out_qs = channel_map_aio_out_qs;
+
+		hdspm->channel_map_in_ss = channel_map_aio_in_ss;
+		hdspm->channel_map_in_ds = channel_map_aio_in_ds;
+		hdspm->channel_map_in_qs = channel_map_aio_in_qs;
+
+		hdspm->port_names_in_ss = texts_ports_aio_in_ss;
+		hdspm->port_names_out_ss = texts_ports_aio_out_ss;
+		hdspm->port_names_in_ds = texts_ports_aio_in_ds;
+		hdspm->port_names_out_ds = texts_ports_aio_out_ds;
+		hdspm->port_names_in_qs = texts_ports_aio_in_qs;
+		hdspm->port_names_out_qs = texts_ports_aio_out_qs;
+
+		break;
+
+	case RayDAT:
+		hdspm->ss_in_channels = hdspm->ss_out_channels =
+			RAYDAT_SS_CHANNELS;
+		hdspm->ds_in_channels = hdspm->ds_out_channels =
+			RAYDAT_DS_CHANNELS;
+		hdspm->qs_in_channels = hdspm->qs_out_channels =
+			RAYDAT_QS_CHANNELS;
+
+		hdspm->max_channels_in = RAYDAT_SS_CHANNELS;
+		hdspm->max_channels_out = RAYDAT_SS_CHANNELS;
+
+		hdspm->channel_map_in_ss = hdspm->channel_map_out_ss =
+			channel_map_raydat_ss;
+		hdspm->channel_map_in_ds = hdspm->channel_map_out_ds =
+			channel_map_raydat_ds;
+		hdspm->channel_map_in_qs = hdspm->channel_map_out_qs =
+			channel_map_raydat_qs;
+		hdspm->channel_map_in = hdspm->channel_map_out =
+			channel_map_raydat_ss;
+
+		hdspm->port_names_in_ss = hdspm->port_names_out_ss =
+			texts_ports_raydat_ss;
+		hdspm->port_names_in_ds = hdspm->port_names_out_ds =
+			texts_ports_raydat_ds;
+		hdspm->port_names_in_qs = hdspm->port_names_out_qs =
+			texts_ports_raydat_qs;
+
+
+		break;
+
+	}
+
+	/* TCO detection */
+	switch (hdspm->io_type) {
+	case AIO:
+	case RayDAT:
+		if (hdspm_read(hdspm, HDSPM_statusRegister2) &
+				HDSPM_s2_tco_detect) {
+			hdspm->midiPorts++;
+			hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
+					GFP_KERNEL);
+			if (NULL != hdspm->tco) {
+				hdspm_tco_write(hdspm);
+			}
+			snd_printk(KERN_INFO "HDSPM: AIO/RayDAT TCO module found\n");
+		} else {
+			hdspm->tco = NULL;
+		}
+		break;
+
+	case MADI:
+		if (hdspm_read(hdspm, HDSPM_statusRegister) & HDSPM_tco_detect) {
+			hdspm->midiPorts++;
+			hdspm->tco = kzalloc(sizeof(struct hdspm_tco),
+					GFP_KERNEL);
+			if (NULL != hdspm->tco) {
+				hdspm_tco_write(hdspm);
+			}
+			snd_printk(KERN_INFO "HDSPM: MADI TCO module found\n");
+		} else {
+			hdspm->tco = NULL;
+		}
+		break;
+
+	default:
+		hdspm->tco = NULL;
+	}
+
+	/* texts */
+	switch (hdspm->io_type) {
+	case AES32:
+		if (hdspm->tco) {
+			hdspm->texts_autosync = texts_autosync_aes_tco;
+			hdspm->texts_autosync_items = 10;
+		} else {
+			hdspm->texts_autosync = texts_autosync_aes;
+			hdspm->texts_autosync_items = 9;
+		}
+		break;
+
+	case MADI:
+		if (hdspm->tco) {
+			hdspm->texts_autosync = texts_autosync_madi_tco;
+			hdspm->texts_autosync_items = 4;
+		} else {
+			hdspm->texts_autosync = texts_autosync_madi;
+			hdspm->texts_autosync_items = 3;
+		}
+		break;
+
+	case MADIface:
+
+		break;
+
+	case RayDAT:
+		if (hdspm->tco) {
+			hdspm->texts_autosync = texts_autosync_raydat_tco;
+			hdspm->texts_autosync_items = 9;
+		} else {
+			hdspm->texts_autosync = texts_autosync_raydat;
+			hdspm->texts_autosync_items = 8;
+		}
+		break;
+
+	case AIO:
+		if (hdspm->tco) {
+			hdspm->texts_autosync = texts_autosync_aio_tco;
+			hdspm->texts_autosync_items = 6;
+		} else {
+			hdspm->texts_autosync = texts_autosync_aio;
+			hdspm->texts_autosync_items = 5;
+		}
+		break;
+
+	}
+
+	tasklet_init(&hdspm->midi_tasklet,
+			hdspm_midi_tasklet, (unsigned long) hdspm);
 
 	snd_printdd("create alsa devices.\n");
 	err = snd_hdspm_create_alsa_devices(card, hdspm);
@@ -4444,6 +6669,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
 	return 0;
 }
 
+
 static int snd_hdspm_free(struct hdspm * hdspm)
 {
 
@@ -4452,7 +6678,8 @@ static int snd_hdspm_free(struct hdspm * hdspm)
 		/* stop th audio, and cancel all interrupts */
 		hdspm->control_register &=
 		    ~(HDSPM_Start | HDSPM_AudioInterruptEnable |
-		      HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable);
+		      HDSPM_Midi0InterruptEnable | HDSPM_Midi1InterruptEnable |
+		      HDSPM_Midi2InterruptEnable | HDSPM_Midi3InterruptEnable);
 		hdspm_write(hdspm, HDSPM_controlRegister,
 			    hdspm->control_register);
 	}
@@ -4472,6 +6699,7 @@ static int snd_hdspm_free(struct hdspm * hdspm)
 	return 0;
 }
 
+
 static void snd_hdspm_card_free(struct snd_card *card)
 {
 	struct hdspm *hdspm = card->private_data;
@@ -4480,6 +6708,7 @@ static void snd_hdspm_card_free(struct snd_card *card)
 		snd_hdspm_free(hdspm);
 }
 
+
 static int __devinit snd_hdspm_probe(struct pci_dev *pci,
 				     const struct pci_device_id *pci_id)
 {
@@ -4496,7 +6725,7 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
 	}
 
 	err = snd_card_create(index[dev], id[dev],
-			      THIS_MODULE, sizeof(struct hdspm), &card);
+			THIS_MODULE, sizeof(struct hdspm), &card);
 	if (err < 0)
 		return err;
 
@@ -4507,16 +6736,25 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
 
 	snd_card_set_dev(card, &pci->dev);
 
-	err = snd_hdspm_create(card, hdspm, precise_ptr[dev],
-			       enable_monitor[dev]);
+	err = snd_hdspm_create(card, hdspm);
 	if (err < 0) {
 		snd_card_free(card);
 		return err;
 	}
 
-	strcpy(card->shortname, "HDSPM MADI");
-	sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
-		hdspm->port, hdspm->irq);
+	if (hdspm->io_type != MADIface) {
+		sprintf(card->shortname, "%s_%x",
+			hdspm->card_name,
+			(hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
+		sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
+			hdspm->card_name,
+			(hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
+			hdspm->port, hdspm->irq);
+	} else {
+		sprintf(card->shortname, "%s", hdspm->card_name);
+		sprintf(card->longname, "%s at 0x%lx, irq %d",
+				hdspm->card_name, hdspm->port, hdspm->irq);
+	}
 
 	err = snd_card_register(card);
 	if (err < 0) {
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index b47cfd4..3ecbd67 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -1034,7 +1034,11 @@ static int __devinit snd_pmac_detect(struct snd_pmac *chip)
 	if (of_device_is_compatible(sound, "tumbler")) {
 		chip->model = PMAC_TUMBLER;
 		chip->can_capture = of_machine_is_compatible("PowerMac4,2")
-				|| of_machine_is_compatible("PowerBook4,1");
+				|| of_machine_is_compatible("PowerBook3,2")
+				|| of_machine_is_compatible("PowerBook3,3")
+				|| of_machine_is_compatible("PowerBook4,1")
+				|| of_machine_is_compatible("PowerBook4,2")
+				|| of_machine_is_compatible("PowerBook4,3");
 		chip->can_duplex = 0;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
 		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index a3efc52..8224db5 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -50,10 +50,12 @@ source "sound/soc/jz4740/Kconfig"
 source "sound/soc/nuc900/Kconfig"
 source "sound/soc/omap/Kconfig"
 source "sound/soc/kirkwood/Kconfig"
+source "sound/soc/mid-x86/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/s6000/Kconfig"
 source "sound/soc/sh/Kconfig"
+source "sound/soc/tegra/Kconfig"
 source "sound/soc/txx9/Kconfig"
 
 # Supported codecs
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index ce913bf..1ed61c5 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SND_SOC)	+= ep93xx/
 obj-$(CONFIG_SND_SOC)	+= fsl/
 obj-$(CONFIG_SND_SOC)   += imx/
 obj-$(CONFIG_SND_SOC)	+= jz4740/
+obj-$(CONFIG_SND_SOC)	+= mid-x86/
 obj-$(CONFIG_SND_SOC)	+= nuc900/
 obj-$(CONFIG_SND_SOC)	+= omap/
 obj-$(CONFIG_SND_SOC)	+= kirkwood/
@@ -17,4 +18,5 @@ obj-$(CONFIG_SND_SOC)	+= pxa/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= sh/
+obj-$(CONFIG_SND_SOC)	+= tegra/
 obj-$(CONFIG_SND_SOC)	+= txx9/
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index c48b23c..d63c175 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -26,17 +26,24 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
 	select SND_SOC_CS42L51 if I2C
 	select SND_SOC_CS4270 if I2C
+	select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_CX20442
 	select SND_SOC_DA7210 if I2C
+	select SND_SOC_DFBMCS320
 	select SND_SOC_JZ4740_CODEC if SOC_JZ4740
+	select SND_SOC_LM4857 if I2C
 	select SND_SOC_MAX98088 if I2C
+	select SND_SOC_MAX9850 if I2C
 	select SND_SOC_MAX9877 if I2C
 	select SND_SOC_PCM3008
+	select SND_SOC_SGTL5000 if I2C
+	select SND_SOC_SN95031 if INTEL_SCU_IPC
 	select SND_SOC_SPDIF
 	select SND_SOC_SSM2602 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_TLV320AIC23 if I2C
 	select SND_SOC_TLV320AIC26 if SPI_MASTER
+	select SND_SOC_TVL320AIC32X4 if I2C
 	select SND_SOC_TLV320AIC3X if I2C
 	select SND_SOC_TPA6130A2 if I2C
 	select SND_SOC_TLV320DAC33 if I2C
@@ -76,6 +83,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_WM8990 if I2C
+	select SND_SOC_WM8991 if I2C
 	select SND_SOC_WM8993 if I2C
 	select SND_SOC_WM8994 if MFD_WM8994
 	select SND_SOC_WM8995 if SND_SOC_I2C_AND_SPI
@@ -155,6 +163,9 @@ config SND_SOC_CS4270_VD33_ERRATA
 	bool
 	depends on SND_SOC_CS4270
 
+config SND_SOC_CS4271
+	tristate
+
 config SND_SOC_CX20442
 	tristate
 
@@ -167,15 +178,28 @@ config SND_SOC_L3
 config SND_SOC_DA7210
         tristate
 
+config SND_SOC_DFBMCS320
+	tristate
+
 config SND_SOC_DMIC
 	tristate
 
 config SND_SOC_MAX98088
        tristate
 
+config SND_SOC_MAX9850
+	tristate
+
 config SND_SOC_PCM3008
        tristate
 
+#Freescale sgtl5000 codec
+config SND_SOC_SGTL5000
+	tristate
+
+config SND_SOC_SN95031
+	tristate
+
 config SND_SOC_SPDIF
 	tristate
 
@@ -192,6 +216,9 @@ config SND_SOC_TLV320AIC26
 	tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
 	depends on SPI
 
+config SND_SOC_TVL320AIC32X4
+	tristate
+
 config SND_SOC_TLV320AIC3X
 	tristate
 
@@ -304,6 +331,9 @@ config SND_SOC_WM8988
 config SND_SOC_WM8990
 	tristate
 
+config SND_SOC_WM8991
+	tristate
+
 config SND_SOC_WM8993
 	tristate
 
@@ -326,6 +356,9 @@ config SND_SOC_WM9713
 	tristate
 
 # Amp
+config SND_SOC_LM4857
+	tristate
+
 config SND_SOC_MAX9877
 	tristate
 
@@ -337,4 +370,3 @@ config SND_SOC_WM2000
 
 config SND_SOC_WM9090
 	tristate
-
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 579af9c..379bc55 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -12,19 +12,25 @@ snd-soc-ak4671-objs := ak4671.o
 snd-soc-cq93vc-objs := cq93vc.o
 snd-soc-cs42l51-objs := cs42l51.o
 snd-soc-cs4270-objs := cs4270.o
+snd-soc-cs4271-objs := cs4271.o
 snd-soc-cx20442-objs := cx20442.o
 snd-soc-da7210-objs := da7210.o
+snd-soc-dfbmcs320-objs := dfbmcs320.o
 snd-soc-dmic-objs := dmic.o
 snd-soc-l3-objs := l3.o
 snd-soc-max98088-objs := max98088.o
+snd-soc-max9850-objs := max9850.o
 snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
+snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-objs := spdif_transciever.o
 snd-soc-ssm2602-objs := ssm2602.o
 snd-soc-stac9766-objs := stac9766.o
 snd-soc-tlv320aic23-objs := tlv320aic23.o
 snd-soc-tlv320aic26-objs := tlv320aic26.o
 snd-soc-tlv320aic3x-objs := tlv320aic3x.o
+snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o
 snd-soc-tlv320dac33-objs := tlv320dac33.o
 snd-soc-twl4030-objs := twl4030.o
 snd-soc-twl6040-objs := twl6040.o
@@ -61,6 +67,7 @@ snd-soc-wm8978-objs := wm8978.o
 snd-soc-wm8985-objs := wm8985.o
 snd-soc-wm8988-objs := wm8988.o
 snd-soc-wm8990-objs := wm8990.o
+snd-soc-wm8991-objs := wm8991.o
 snd-soc-wm8993-objs := wm8993.o
 snd-soc-wm8994-objs := wm8994.o wm8994-tables.o
 snd-soc-wm8995-objs := wm8995.o
@@ -72,6 +79,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
 snd-soc-jz4740-codec-objs := jz4740.o
 
 # Amp
+snd-soc-lm4857-objs := lm4857.o
 snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
 snd-soc-wm2000-objs := wm2000.o
@@ -88,23 +96,29 @@ obj-$(CONFIG_SND_SOC_AK4104)	+= snd-soc-ak4104.o
 obj-$(CONFIG_SND_SOC_AK4535)	+= snd-soc-ak4535.o
 obj-$(CONFIG_SND_SOC_AK4642)	+= snd-soc-ak4642.o
 obj-$(CONFIG_SND_SOC_AK4671)	+= snd-soc-ak4671.o
+obj-$(CONFIG_SND_SOC_ALC5623)    += snd-soc-alc5623.o
 obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
 obj-$(CONFIG_SND_SOC_CS42L51)	+= snd-soc-cs42l51.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
+obj-$(CONFIG_SND_SOC_CS4271)	+= snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CX20442)	+= snd-soc-cx20442.o
 obj-$(CONFIG_SND_SOC_DA7210)	+= snd-soc-da7210.o
+obj-$(CONFIG_SND_SOC_DFBMCS320)	+= snd-soc-dfbmcs320.o
 obj-$(CONFIG_SND_SOC_DMIC)	+= snd-soc-dmic.o
 obj-$(CONFIG_SND_SOC_L3)	+= snd-soc-l3.o
 obj-$(CONFIG_SND_SOC_JZ4740_CODEC)	+= snd-soc-jz4740-codec.o
 obj-$(CONFIG_SND_SOC_MAX98088)	+= snd-soc-max98088.o
+obj-$(CONFIG_SND_SOC_MAX9850)	+= snd-soc-max9850.o
 obj-$(CONFIG_SND_SOC_PCM3008)	+= snd-soc-pcm3008.o
-obj-$(CONFIG_SND_SOC_ALC5623)    += snd-soc-alc5623.o
+obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
+obj-$(CONFIG_SND_SOC_SN95031)	+=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.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
+obj-$(CONFIG_SND_SOC_TVL320AIC32X4)     += snd-soc-tlv320aic32x4.o
 obj-$(CONFIG_SND_SOC_TLV320DAC33)	+= snd-soc-tlv320dac33.o
 obj-$(CONFIG_SND_SOC_TWL4030)	+= snd-soc-twl4030.o
 obj-$(CONFIG_SND_SOC_TWL6040)	+= snd-soc-twl6040.o
@@ -141,6 +155,7 @@ obj-$(CONFIG_SND_SOC_WM8978)	+= snd-soc-wm8978.o
 obj-$(CONFIG_SND_SOC_WM8985)	+= snd-soc-wm8985.o
 obj-$(CONFIG_SND_SOC_WM8988)	+= snd-soc-wm8988.o
 obj-$(CONFIG_SND_SOC_WM8990)	+= snd-soc-wm8990.o
+obj-$(CONFIG_SND_SOC_WM8991)	+= snd-soc-wm8991.o
 obj-$(CONFIG_SND_SOC_WM8993)	+= snd-soc-wm8993.o
 obj-$(CONFIG_SND_SOC_WM8994)	+= snd-soc-wm8994.o
 obj-$(CONFIG_SND_SOC_WM8995)	+= snd-soc-wm8995.o
@@ -151,6 +166,7 @@ obj-$(CONFIG_SND_SOC_WM9713)	+= snd-soc-wm9713.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)	+= snd-soc-wm-hubs.o
 
 # Amp
+obj-$(CONFIG_SND_SOC_LM4857)	+= snd-soc-lm4857.o
 obj-$(CONFIG_SND_SOC_MAX9877)	+= snd-soc-max9877.o
 obj-$(CONFIG_SND_SOC_TPA6130A2)	+= snd-soc-tpa6130a2.o
 obj-$(CONFIG_SND_SOC_WM2000)	+= snd-soc-wm2000.o
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index c27f8f5..cbf0b6d 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -294,7 +294,6 @@ static struct spi_driver ak4104_spi_driver = {
 
 static int __init ak4104_init(void)
 {
-	pr_info("Asahi Kasei AK4104 ALSA SoC Codec Driver\n");
 	return spi_register_driver(&ak4104_spi_driver);
 }
 module_init(ak4104_init);
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index f00eba3..4be0570 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -116,6 +116,12 @@
 #define BCKO_MASK	(1 << 3)
 #define BCKO_64		BCKO_MASK
 
+#define DIF_MASK	(3 << 0)
+#define DSP		(0 << 0)
+#define RIGHT_J		(1 << 0)
+#define LEFT_J		(2 << 0)
+#define I2S		(3 << 0)
+
 /* MD_CTL2 */
 #define FS0		(1 << 0)
 #define FS1		(1 << 1)
@@ -354,6 +360,24 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 	snd_soc_update_bits(codec, PW_MGMT2, MS, data);
 	snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
 
+	/* format type */
+	data = 0;
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_LEFT_J:
+		data = LEFT_J;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		data = I2S;
+		break;
+	/* FIXME
+	 * Please add RIGHT_J / DSP support here
+	 */
+	default:
+		return -EINVAL;
+		break;
+	}
+	snd_soc_update_bits(codec, MD_CTL1, DIF_MASK, data);
+
 	return 0;
 }
 
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 8b51245..0206a17 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -193,12 +193,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = {
 /* The number of MCLK/LRCK ratios supported by the CS4270 */
 #define NUM_MCLK_RATIOS		ARRAY_SIZE(cs4270_mode_ratios)
 
-static int cs4270_reg_is_readable(unsigned int reg)
+static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg)
 {
 	return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG);
 }
 
-static int cs4270_reg_is_volatile(unsigned int reg)
+static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg)
 {
 	/* Unreadable registers are considered volatile */
 	if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG))
@@ -719,7 +719,7 @@ static int cs4270_i2c_remove(struct i2c_client *i2c_client)
 /*
  * cs4270_id - I2C device IDs supported by this driver
  */
-static struct i2c_device_id cs4270_id[] = {
+static const struct i2c_device_id cs4270_id[] = {
 	{"cs4270", 0},
 	{}
 };
@@ -743,8 +743,6 @@ static struct i2c_driver cs4270_i2c_driver = {
 
 static int __init cs4270_init(void)
 {
-	pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
-
 	return i2c_add_driver(&cs4270_i2c_driver);
 }
 module_init(cs4270_init);
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
new file mode 100644
index 0000000..083aab9
--- /dev/null
+++ b/sound/soc/codecs/cs4271.c
@@ -0,0 +1,667 @@
+/*
+ * CS4271 ASoC codec driver
+ *
+ * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 support CS4271 codec being master or slave, working
+ * in control port mode, connected either via SPI or I2C.
+ * The data format accepted is I2S or left-justified.
+ * DAPM support not implemented.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <sound/cs4271.h>
+
+#define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+			    SNDRV_PCM_FMTBIT_S24_LE | \
+			    SNDRV_PCM_FMTBIT_S32_LE)
+#define CS4271_PCM_RATES SNDRV_PCM_RATE_8000_192000
+
+/*
+ * 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_FIRSTREG	CS4271_MODE1
+#define CS4271_LASTREG	CS4271_MODE2
+#define CS4271_NR_REGS	((CS4271_LASTREG & 0xFF) + 1)
+
+/* Bit masks for the CS4271 registers */
+#define CS4271_MODE1_MODE_MASK	0xC0
+#define CS4271_MODE1_MODE_1X	0x00
+#define CS4271_MODE1_MODE_2X	0x80
+#define CS4271_MODE1_MODE_4X	0xC0
+
+#define CS4271_MODE1_DIV_MASK	0x30
+#define CS4271_MODE1_DIV_1	0x00
+#define CS4271_MODE1_DIV_15	0x10
+#define CS4271_MODE1_DIV_2	0x20
+#define CS4271_MODE1_DIV_3	0x30
+
+#define CS4271_MODE1_MASTER	0x08
+
+#define CS4271_MODE1_DAC_DIF_MASK	0x07
+#define CS4271_MODE1_DAC_DIF_LJ		0x00
+#define CS4271_MODE1_DAC_DIF_I2S	0x01
+#define CS4271_MODE1_DAC_DIF_RJ16	0x02
+#define CS4271_MODE1_DAC_DIF_RJ24	0x03
+#define CS4271_MODE1_DAC_DIF_RJ20	0x04
+#define CS4271_MODE1_DAC_DIF_RJ18	0x05
+
+#define CS4271_DACCTL_AMUTE	0x80
+#define CS4271_DACCTL_IF_SLOW	0x40
+
+#define CS4271_DACCTL_DEM_MASK	0x30
+#define CS4271_DACCTL_DEM_DIS	0x00
+#define CS4271_DACCTL_DEM_441	0x10
+#define CS4271_DACCTL_DEM_48	0x20
+#define CS4271_DACCTL_DEM_32	0x30
+
+#define CS4271_DACCTL_SVRU	0x08
+#define CS4271_DACCTL_SRD	0x04
+#define CS4271_DACCTL_INVA	0x02
+#define CS4271_DACCTL_INVB	0x01
+
+#define CS4271_DACVOL_BEQUA	0x40
+#define CS4271_DACVOL_SOFT	0x20
+#define CS4271_DACVOL_ZEROC	0x10
+
+#define CS4271_DACVOL_ATAPI_MASK	0x0F
+#define CS4271_DACVOL_ATAPI_M_M		0x00
+#define CS4271_DACVOL_ATAPI_M_BR	0x01
+#define CS4271_DACVOL_ATAPI_M_BL	0x02
+#define CS4271_DACVOL_ATAPI_M_BLR2	0x03
+#define CS4271_DACVOL_ATAPI_AR_M	0x04
+#define CS4271_DACVOL_ATAPI_AR_BR	0x05
+#define CS4271_DACVOL_ATAPI_AR_BL	0x06
+#define CS4271_DACVOL_ATAPI_AR_BLR2	0x07
+#define CS4271_DACVOL_ATAPI_AL_M	0x08
+#define CS4271_DACVOL_ATAPI_AL_BR	0x09
+#define CS4271_DACVOL_ATAPI_AL_BL	0x0A
+#define CS4271_DACVOL_ATAPI_AL_BLR2	0x0B
+#define CS4271_DACVOL_ATAPI_ALR2_M	0x0C
+#define CS4271_DACVOL_ATAPI_ALR2_BR	0x0D
+#define CS4271_DACVOL_ATAPI_ALR2_BL	0x0E
+#define CS4271_DACVOL_ATAPI_ALR2_BLR2	0x0F
+
+#define CS4271_VOLA_MUTE	0x80
+#define CS4271_VOLA_VOL_MASK	0x7F
+#define CS4271_VOLB_MUTE	0x80
+#define CS4271_VOLB_VOL_MASK	0x7F
+
+#define CS4271_ADCCTL_DITHER16	0x20
+
+#define CS4271_ADCCTL_ADC_DIF_MASK	0x10
+#define CS4271_ADCCTL_ADC_DIF_LJ	0x00
+#define CS4271_ADCCTL_ADC_DIF_I2S	0x10
+
+#define CS4271_ADCCTL_MUTEA	0x08
+#define CS4271_ADCCTL_MUTEB	0x04
+#define CS4271_ADCCTL_HPFDA	0x02
+#define CS4271_ADCCTL_HPFDB	0x01
+
+#define CS4271_MODE2_LOOP	0x10
+#define CS4271_MODE2_MUTECAEQUB	0x08
+#define CS4271_MODE2_FREEZE	0x04
+#define CS4271_MODE2_CPEN	0x02
+#define CS4271_MODE2_PDN	0x01
+
+#define CS4271_CHIPID_PART_MASK	0xF0
+#define CS4271_CHIPID_REV_MASK	0x0F
+
+/*
+ * Default CS4271 power-up configuration
+ * Array contains non-existing in hw register at address 0
+ * 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,
+};
+
+struct cs4271_private {
+	/* SND_SOC_I2C or SND_SOC_SPI */
+	enum snd_soc_control_type	bus_type;
+	void				*control_data;
+	unsigned int			mclk;
+	bool				master;
+	bool				deemph;
+	/* Current sample rate for de-emphasis control */
+	int				rate;
+	/* GPIO driving Reset pin, if any */
+	int				gpio_nreset;
+	/* GPIO that disable serial bus, if any */
+	int				gpio_disable;
+};
+
+/*
+ * @freq is the desired MCLK rate
+ * MCLK rate should (c) be the sample rate, multiplied by one of the
+ * ratios listed in cs4271_mclk_fs_ratios table
+ */
+static int cs4271_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 cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+
+	cs4271->mclk = freq;
+	return 0;
+}
+
+static int cs4271_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int format)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+	unsigned int val = 0;
+	int ret;
+
+	switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		cs4271->master = 0;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		cs4271->master = 1;
+		val |= CS4271_MODE1_MASTER;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI format\n");
+		return -EINVAL;
+	}
+
+	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,
+			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,
+			CS4271_ADCCTL_ADC_DIF_MASK, CS4271_ADCCTL_ADC_DIF_I2S);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+		dev_err(codec->dev, "Invalid DAI format\n");
+		return -EINVAL;
+	}
+
+	ret = snd_soc_update_bits(codec, CS4271_MODE1,
+		CS4271_MODE1_DAC_DIF_MASK | CS4271_MODE1_MASTER, val);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int cs4271_deemph[] = {0, 44100, 48000, 32000};
+
+static int cs4271_set_deemph(struct snd_soc_codec *codec)
+{
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+	int i, ret;
+	int val = CS4271_DACCTL_DEM_DIS;
+
+	if (cs4271->deemph) {
+		/* Find closest de-emphasis freq */
+		val = 1;
+		for (i = 2; i < ARRAY_SIZE(cs4271_deemph); i++)
+			if (abs(cs4271_deemph[i] - cs4271->rate) <
+			    abs(cs4271_deemph[val] - cs4271->rate))
+				val = i;
+		val <<= 4;
+	}
+
+	ret = snd_soc_update_bits(codec, CS4271_DACCTL,
+		CS4271_DACCTL_DEM_MASK, val);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int cs4271_get_deemph(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.enumerated.item[0] = cs4271->deemph;
+	return 0;
+}
+
+static int cs4271_put_deemph(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+
+	cs4271->deemph = ucontrol->value.enumerated.item[0];
+	return cs4271_set_deemph(codec);
+}
+
+struct cs4271_clk_cfg {
+	bool		master;		/* codec mode */
+	u8		speed_mode;	/* codec speed mode: 1x, 2x, 4x */
+	unsigned short	ratio;		/* MCLK / sample rate */
+	u8		ratio_mask;	/* ratio bit mask for Master mode */
+};
+
+static struct cs4271_clk_cfg cs4271_clk_tab[] = {
+	{1, CS4271_MODE1_MODE_1X, 256,  CS4271_MODE1_DIV_1},
+	{1, CS4271_MODE1_MODE_1X, 384,  CS4271_MODE1_DIV_15},
+	{1, CS4271_MODE1_MODE_1X, 512,  CS4271_MODE1_DIV_2},
+	{1, CS4271_MODE1_MODE_1X, 768,  CS4271_MODE1_DIV_3},
+	{1, CS4271_MODE1_MODE_2X, 128,  CS4271_MODE1_DIV_1},
+	{1, CS4271_MODE1_MODE_2X, 192,  CS4271_MODE1_DIV_15},
+	{1, CS4271_MODE1_MODE_2X, 256,  CS4271_MODE1_DIV_2},
+	{1, CS4271_MODE1_MODE_2X, 384,  CS4271_MODE1_DIV_3},
+	{1, CS4271_MODE1_MODE_4X, 64,   CS4271_MODE1_DIV_1},
+	{1, CS4271_MODE1_MODE_4X, 96,   CS4271_MODE1_DIV_15},
+	{1, CS4271_MODE1_MODE_4X, 128,  CS4271_MODE1_DIV_2},
+	{1, CS4271_MODE1_MODE_4X, 192,  CS4271_MODE1_DIV_3},
+	{0, CS4271_MODE1_MODE_1X, 256,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_1X, 384,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_1X, 512,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_1X, 768,  CS4271_MODE1_DIV_2},
+	{0, CS4271_MODE1_MODE_1X, 1024, CS4271_MODE1_DIV_2},
+	{0, CS4271_MODE1_MODE_2X, 128,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_2X, 192,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_2X, 256,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_2X, 384,  CS4271_MODE1_DIV_2},
+	{0, CS4271_MODE1_MODE_2X, 512,  CS4271_MODE1_DIV_2},
+	{0, CS4271_MODE1_MODE_4X, 64,   CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_4X, 96,   CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_4X, 128,  CS4271_MODE1_DIV_1},
+	{0, CS4271_MODE1_MODE_4X, 192,  CS4271_MODE1_DIV_2},
+	{0, CS4271_MODE1_MODE_4X, 256,  CS4271_MODE1_DIV_2},
+};
+
+#define CS4171_NR_RATIOS ARRAY_SIZE(cs4271_clk_tab)
+
+static int cs4271_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params,
+			    struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+	int i, ret;
+	unsigned int ratio, val;
+
+	cs4271->rate = params_rate(params);
+
+	/* Configure DAC */
+	if (cs4271->rate < 50000)
+		val = CS4271_MODE1_MODE_1X;
+	else if (cs4271->rate < 100000)
+		val = CS4271_MODE1_MODE_2X;
+	else
+		val = CS4271_MODE1_MODE_4X;
+
+	ratio = cs4271->mclk / cs4271->rate;
+	for (i = 0; i < CS4171_NR_RATIOS; i++)
+		if ((cs4271_clk_tab[i].master == cs4271->master) &&
+		    (cs4271_clk_tab[i].speed_mode == val) &&
+		    (cs4271_clk_tab[i].ratio == ratio))
+			break;
+
+	if (i == CS4171_NR_RATIOS) {
+		dev_err(codec->dev, "Invalid sample rate\n");
+		return -EINVAL;
+	}
+
+	val |= cs4271_clk_tab[i].ratio_mask;
+
+	ret = snd_soc_update_bits(codec, CS4271_MODE1,
+		CS4271_MODE1_MODE_MASK | CS4271_MODE1_DIV_MASK, val);
+	if (ret < 0)
+		return ret;
+
+	return cs4271_set_deemph(codec);
+}
+
+static int cs4271_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	int ret;
+	int val_a = 0;
+	int val_b = 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);
+	if (ret < 0)
+		return ret;
+	ret = snd_soc_update_bits(codec, CS4271_VOLB, CS4271_VOLB_MUTE, val_b);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* CS4271 controls */
+static DECLARE_TLV_DB_SCALE(cs4271_dac_tlv, -12700, 100, 0);
+
+static const struct snd_kcontrol_new cs4271_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("Master Playback Volume", CS4271_VOLA, CS4271_VOLB,
+		0, 0x7F, 1, cs4271_dac_tlv),
+	SOC_SINGLE("Digital Loopback Switch", CS4271_MODE2, 4, 1, 0),
+	SOC_SINGLE("Soft Ramp Switch", CS4271_DACVOL, 5, 1, 0),
+	SOC_SINGLE("Zero Cross Switch", CS4271_DACVOL, 4, 1, 0),
+	SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
+		cs4271_get_deemph, cs4271_put_deemph),
+	SOC_SINGLE("Auto-Mute Switch", CS4271_DACCTL, 7, 1, 0),
+	SOC_SINGLE("Slow Roll Off Filter Switch", CS4271_DACCTL, 6, 1, 0),
+	SOC_SINGLE("Soft Volume Ramp-Up Switch", CS4271_DACCTL, 3, 1, 0),
+	SOC_SINGLE("Soft Ramp-Down Switch", CS4271_DACCTL, 2, 1, 0),
+	SOC_SINGLE("Left Channel Inversion Switch", CS4271_DACCTL, 1, 1, 0),
+	SOC_SINGLE("Right Channel Inversion Switch", CS4271_DACCTL, 0, 1, 0),
+	SOC_DOUBLE("Master Capture Switch", CS4271_ADCCTL, 3, 2, 1, 1),
+	SOC_SINGLE("Dither 16-Bit Data Switch", CS4271_ADCCTL, 5, 1, 0),
+	SOC_DOUBLE("High Pass Filter Switch", CS4271_ADCCTL, 1, 0, 1, 1),
+	SOC_DOUBLE_R("Master Playback Switch", CS4271_VOLA, CS4271_VOLB,
+		7, 1, 1),
+};
+
+static 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,
+};
+
+static struct snd_soc_dai_driver cs4271_dai = {
+	.name = "cs4271-hifi",
+	.playback = {
+		.stream_name	= "Playback",
+		.channels_min	= 2,
+		.channels_max	= 2,
+		.rates		= CS4271_PCM_RATES,
+		.formats	= CS4271_PCM_FORMATS,
+	},
+	.capture = {
+		.stream_name	= "Capture",
+		.channels_min	= 2,
+		.channels_max	= 2,
+		.rates		= CS4271_PCM_RATES,
+		.formats	= CS4271_PCM_FORMATS,
+	},
+	.ops = &cs4271_dai_ops,
+	.symmetric_rates = 1,
+};
+
+#ifdef CONFIG_PM
+static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+{
+	int ret;
+	/* Set power-down bit */
+	ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static int cs4271_soc_resume(struct snd_soc_codec *codec)
+{
+	int ret;
+	/* Restore codec state */
+	ret = snd_soc_cache_sync(codec);
+	if (ret < 0)
+		return ret;
+	/* then disable the power-down bit */
+	ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+#else
+#define cs4271_soc_suspend	NULL
+#define cs4271_soc_resume	NULL
+#endif /* CONFIG_PM */
+
+static int cs4271_probe(struct snd_soc_codec *codec)
+{
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+	struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
+	int ret;
+	int gpio_nreset = -EINVAL;
+
+	codec->control_data = cs4271->control_data;
+
+	if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
+		gpio_nreset = cs4271plat->gpio_nreset;
+
+	if (gpio_nreset >= 0)
+		if (gpio_request(gpio_nreset, "CS4271 Reset"))
+			gpio_nreset = -EINVAL;
+	if (gpio_nreset >= 0) {
+		/* Reset codec */
+		gpio_direction_output(gpio_nreset, 0);
+		udelay(1);
+		gpio_set_value(gpio_nreset, 1);
+		/* Give the codec time to wake up */
+		udelay(1);
+	}
+
+	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, 0,
+		CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
+	if (ret < 0)
+		return ret;
+	ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
+	if (ret < 0)
+		return ret;
+	/* Power-up sequence requires 85 uS */
+	udelay(85);
+
+	return snd_soc_add_controls(codec, cs4271_snd_controls,
+		ARRAY_SIZE(cs4271_snd_controls));
+}
+
+static int cs4271_remove(struct snd_soc_codec *codec)
+{
+	struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
+	int gpio_nreset;
+
+	gpio_nreset = cs4271->gpio_nreset;
+
+	if (gpio_is_valid(gpio_nreset)) {
+		/* Set codec to the reset state */
+		gpio_set_value(gpio_nreset, 0);
+		gpio_free(gpio_nreset);
+	}
+
+	return 0;
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_cs4271 = {
+	.probe			= cs4271_probe,
+	.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 int __devinit cs4271_spi_probe(struct spi_device *spi)
+{
+	struct cs4271_private *cs4271;
+
+	cs4271 = devm_kzalloc(&spi->dev, sizeof(*cs4271), GFP_KERNEL);
+	if (!cs4271)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, cs4271);
+	cs4271->control_data = spi;
+	cs4271->bus_type = SND_SOC_SPI;
+
+	return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
+		&cs4271_dai, 1);
+}
+
+static int __devexit cs4271_spi_remove(struct spi_device *spi)
+{
+	snd_soc_unregister_codec(&spi->dev);
+	return 0;
+}
+
+static struct spi_driver cs4271_spi_driver = {
+	.driver = {
+		.name	= "cs4271",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= cs4271_spi_probe,
+	.remove		= __devexit_p(cs4271_spi_remove),
+};
+#endif /* defined(CONFIG_SPI_MASTER) */
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct i2c_device_id cs4271_i2c_id[] = {
+	{"cs4271", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
+
+static int __devinit cs4271_i2c_probe(struct i2c_client *client,
+				      const struct i2c_device_id *id)
+{
+	struct cs4271_private *cs4271;
+
+	cs4271 = devm_kzalloc(&client->dev, sizeof(*cs4271), GFP_KERNEL);
+	if (!cs4271)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, cs4271);
+	cs4271->control_data = client;
+	cs4271->bus_type = SND_SOC_I2C;
+
+	return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
+		&cs4271_dai, 1);
+}
+
+static int __devexit cs4271_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static struct i2c_driver cs4271_i2c_driver = {
+	.driver = {
+		.name	= "cs4271",
+		.owner	= THIS_MODULE,
+	},
+	.id_table	= cs4271_i2c_id,
+	.probe		= cs4271_i2c_probe,
+	.remove		= __devexit_p(cs4271_i2c_remove),
+};
+#endif /* defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) */
+
+/*
+ * We only register our serial bus driver here without
+ * assignment to particular chip. So if any of the below
+ * fails, there is some problem with I2C or SPI subsystem.
+ * In most cases this module will be compiled with support
+ * of only one serial bus.
+ */
+static int __init cs4271_modinit(void)
+{
+	int ret;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	ret = i2c_add_driver(&cs4271_i2c_driver);
+	if (ret) {
+		pr_err("Failed to register CS4271 I2C driver: %d\n", ret);
+		return ret;
+	}
+#endif
+
+#if defined(CONFIG_SPI_MASTER)
+	ret = spi_register_driver(&cs4271_spi_driver);
+	if (ret) {
+		pr_err("Failed to register CS4271 SPI driver: %d\n", ret);
+		return ret;
+	}
+#endif
+
+	return 0;
+}
+module_init(cs4271_modinit);
+
+static void __exit cs4271_modexit(void)
+{
+#if defined(CONFIG_SPI_MASTER)
+	spi_unregister_driver(&cs4271_spi_driver);
+#endif
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+	i2c_del_driver(&cs4271_i2c_driver);
+#endif
+}
+module_exit(cs4271_modexit);
+
+MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
+MODULE_DESCRIPTION("Cirrus Logic CS4271 ALSA SoC Codec Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c
new file mode 100644
index 0000000..704bbde
--- /dev/null
+++ b/sound/soc/codecs/dfbmcs320.c
@@ -0,0 +1,72 @@
+/*
+ * Driver for the DFBM-CS320 bluetooth module
+ * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <sound/soc.h>
+
+static struct snd_soc_dai_driver dfbmcs320_dai = {
+	.name = "dfbmcs320-pcm",
+	.playback = {
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SNDRV_PCM_RATE_8000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SNDRV_PCM_RATE_8000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+	},
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_dfbmcs320;
+
+static int __devinit dfbmcs320_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_dfbmcs320,
+			&dfbmcs320_dai, 1);
+}
+
+static int __devexit dfbmcs320_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_codec(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver dfmcs320_driver = {
+	.driver = {
+		.name = "dfbmcs320",
+		.owner = THIS_MODULE,
+	},
+	.probe = dfbmcs320_probe,
+	.remove = __devexit_p(dfbmcs320_remove),
+};
+
+static int __init dfbmcs320_init(void)
+{
+	return platform_driver_register(&dfmcs320_driver);
+}
+module_init(dfbmcs320_init);
+
+static void __exit dfbmcs320_exit(void)
+{
+	platform_driver_unregister(&dfmcs320_driver);
+}
+module_exit(dfbmcs320_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
new file mode 100644
index 0000000..72de47e
--- /dev/null
+++ b/sound/soc/codecs/lm4857.c
@@ -0,0 +1,276 @@
+/*
+ * LM4857 AMP driver
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+struct lm4857 {
+	struct i2c_client *i2c;
+	uint8_t mode;
+};
+
+static const uint8_t lm4857_default_regs[] = {
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/* The register offsets in the cache array */
+#define LM4857_MVOL 0
+#define LM4857_LVOL 1
+#define LM4857_RVOL 2
+#define LM4857_CTRL 3
+
+/* the shifts required to set these bits */
+#define LM4857_3D 5
+#define LM4857_WAKEUP 5
+#define LM4857_EPGAIN 4
+
+static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg,
+		unsigned int value)
+{
+	uint8_t data;
+	int ret;
+
+	ret = snd_soc_cache_write(codec, reg, value);
+	if (ret < 0)
+		return ret;
+
+	data = (reg << 6) | value;
+	ret = i2c_master_send(codec->control_data, &data, 1);
+	if (ret != 1) {
+		dev_err(codec->dev, "Failed to write register: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned int lm4857_read(struct snd_soc_codec *codec,
+		unsigned int reg)
+{
+	unsigned int val;
+	int ret;
+
+	ret = snd_soc_cache_read(codec, reg, &val);
+	if (ret)
+		return -1;
+
+	return val;
+}
+
+static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = lm4857->mode;
+
+	return 0;
+}
+
+static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
+	uint8_t value = ucontrol->value.integer.value[0];
+
+	lm4857->mode = value;
+
+	if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+		snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6);
+
+	return 1;
+}
+
+static int lm4857_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0);
+		break;
+	default:
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+
+	return 0;
+}
+
+static const char *lm4857_mode[] = {
+	"Earpiece",
+	"Loudspeaker",
+	"Loudspeaker + Headphone",
+	"Headphone",
+};
+
+static const struct soc_enum lm4857_mode_enum =
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode);
+
+static const struct snd_soc_dapm_widget lm4857_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("IN"),
+
+	SND_SOC_DAPM_OUTPUT("LS"),
+	SND_SOC_DAPM_OUTPUT("HP"),
+	SND_SOC_DAPM_OUTPUT("EP"),
+};
+
+static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
+static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
+
+static const struct snd_kcontrol_new lm4857_controls[] = {
+	SOC_SINGLE_TLV("Left Playback Volume", LM4857_LVOL, 0, 31, 0,
+		stereo_tlv),
+	SOC_SINGLE_TLV("Right Playback Volume", LM4857_RVOL, 0, 31, 0,
+		stereo_tlv),
+	SOC_SINGLE_TLV("Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
+		mono_tlv),
+	SOC_SINGLE("Spk 3D Playback Switch", LM4857_LVOL, LM4857_3D, 1, 0),
+	SOC_SINGLE("HP 3D Playback Switch", LM4857_RVOL, LM4857_3D, 1, 0),
+	SOC_SINGLE("Fast Wakeup Playback Switch", LM4857_CTRL,
+		LM4857_WAKEUP, 1, 0),
+	SOC_SINGLE("Earpiece 6dB Playback Switch", LM4857_CTRL,
+		LM4857_EPGAIN, 1, 0),
+
+	SOC_ENUM_EXT("Mode", lm4857_mode_enum,
+		lm4857_get_mode, lm4857_set_mode),
+};
+
+/* There is a demux inbetween the the input signal and the output signals.
+ * Currently there is no easy way to model it in ASoC and since it does not make
+ * much of a difference in practice simply connect the input direclty to the
+ * outputs. */
+static const struct snd_soc_dapm_route lm4857_routes[] = {
+	{"LS", NULL, "IN"},
+	{"HP", NULL, "IN"},
+	{"EP", NULL, "IN"},
+};
+
+static int lm4857_probe(struct snd_soc_codec *codec)
+{
+	struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec);
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	codec->control_data = lm4857->i2c;
+
+	ret = snd_soc_add_controls(codec, lm4857_controls,
+			ARRAY_SIZE(lm4857_controls));
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets,
+			ARRAY_SIZE(lm4857_dapm_widgets));
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_add_routes(dapm, lm4857_routes,
+			ARRAY_SIZE(lm4857_routes));
+	if (ret)
+		return ret;
+
+	snd_soc_dapm_new_widgets(dapm);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_lm4857 = {
+	.write = lm4857_write,
+	.read = lm4857_read,
+	.probe = lm4857_probe,
+	.reg_cache_size = ARRAY_SIZE(lm4857_default_regs),
+	.reg_word_size = sizeof(uint8_t),
+	.reg_cache_default = lm4857_default_regs,
+	.set_bias_level = lm4857_set_bias_level,
+};
+
+static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
+	const struct i2c_device_id *id)
+{
+	struct lm4857 *lm4857;
+	int ret;
+
+	lm4857 = kzalloc(sizeof(*lm4857), GFP_KERNEL);
+	if (!lm4857)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, lm4857);
+
+	lm4857->i2c = i2c;
+
+	ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
+
+	if (ret) {
+		kfree(lm4857);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
+{
+	struct lm4857 *lm4857 = i2c_get_clientdata(i2c);
+
+	snd_soc_unregister_codec(&i2c->dev);
+	kfree(lm4857);
+
+	return 0;
+}
+
+static const struct i2c_device_id lm4857_i2c_id[] = {
+	{ "lm4857", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id);
+
+static struct i2c_driver lm4857_i2c_driver = {
+	.driver = {
+		.name = "lm4857",
+		.owner = THIS_MODULE,
+	},
+	.probe = lm4857_i2c_probe,
+	.remove = __devexit_p(lm4857_i2c_remove),
+	.id_table = lm4857_i2c_id,
+};
+
+static int __init lm4857_init(void)
+{
+	return i2c_add_driver(&lm4857_i2c_driver);
+}
+module_init(lm4857_init);
+
+static void __exit lm4857_exit(void)
+{
+	i2c_del_driver(&lm4857_i2c_driver);
+}
+module_exit(lm4857_exit);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("LM4857 amplifier driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 89498f9..bd0517c 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -608,7 +608,7 @@ static struct {
        { 0xFF, 0x00, 1 }, /* FF */
 };
 
-static int max98088_volatile_register(unsigned int reg)
+static int max98088_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
        return max98088_access[reg].vol;
 }
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
new file mode 100644
index 0000000..208d2ee
--- /dev/null
+++ b/sound/soc/codecs/max9850.c
@@ -0,0 +1,389 @@
+/*
+ * max9850.c  --  codec driver for max9850
+ *
+ * Copyright (C) 2011 taskit GmbH
+ *
+ * Author: Christian Glindkamp <christian.glindkamp@taskit.de>
+ *
+ * Initial development of this code was funded by
+ * MICRONIC Computer Systeme GmbH, http://www.mcsberlin.de/
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+
+#include "max9850.h"
+
+struct max9850_priv {
+	unsigned int sysclk;
+};
+
+/* max9850 register cache */
+static const u8 max9850_reg[MAX9850_CACHEREGNUM] = {
+	0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* these registers are not used at the moment but provided for the sake of
+ * completeness */
+static int max9850_volatile_register(struct snd_soc_codec *codec,
+		unsigned int reg)
+{
+	switch (reg) {
+	case MAX9850_STATUSA:
+	case MAX9850_STATUSB:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static const unsigned int max9850_tlv[] = {
+	TLV_DB_RANGE_HEAD(4),
+	0x18, 0x1f, TLV_DB_SCALE_ITEM(-7450, 400, 0),
+	0x20, 0x33, TLV_DB_SCALE_ITEM(-4150, 200, 0),
+	0x34, 0x37, TLV_DB_SCALE_ITEM(-150, 100, 0),
+	0x38, 0x3f, TLV_DB_SCALE_ITEM(250, 50, 0),
+};
+
+static const struct snd_kcontrol_new max9850_controls[] = {
+SOC_SINGLE_TLV("Headphone Volume", MAX9850_VOLUME, 0, 0x3f, 1, max9850_tlv),
+SOC_SINGLE("Headphone Switch", MAX9850_VOLUME, 7, 1, 1),
+SOC_SINGLE("Mono Switch", MAX9850_GENERAL_PURPOSE, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new max9850_mixer_controls[] = {
+	SOC_DAPM_SINGLE("Line In Switch", MAX9850_ENABLE, 1, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget max9850_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("Charge Pump 1", MAX9850_ENABLE, 4, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("Charge Pump 2", MAX9850_ENABLE, 5, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MCLK", MAX9850_ENABLE, 6, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("SHDN", MAX9850_ENABLE, 7, 0, NULL, 0),
+SND_SOC_DAPM_MIXER_NAMED_CTL("Output Mixer", MAX9850_ENABLE, 2, 0,
+		&max9850_mixer_controls[0],
+		ARRAY_SIZE(max9850_mixer_controls)),
+SND_SOC_DAPM_PGA("Headphone Output", MAX9850_ENABLE, 3, 0, NULL, 0),
+SND_SOC_DAPM_DAC("DAC", "HiFi Playback", MAX9850_ENABLE, 0, 0),
+SND_SOC_DAPM_OUTPUT("OUTL"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("OUTR"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_MIXER("Line Input", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_INPUT("INL"),
+SND_SOC_DAPM_INPUT("INR"),
+};
+
+static const struct snd_soc_dapm_route intercon[] = {
+	/* output mixer */
+	{"Output Mixer", NULL, "DAC"},
+	{"Output Mixer", "Line In Switch", "Line Input"},
+
+	/* outputs */
+	{"Headphone Output", NULL, "Output Mixer"},
+	{"HPL", NULL, "Headphone Output"},
+	{"HPR", NULL, "Headphone Output"},
+	{"OUTL", NULL, "Output Mixer"},
+	{"OUTR", NULL, "Output Mixer"},
+
+	/* inputs */
+	{"Line Input", NULL, "INL"},
+	{"Line Input", NULL, "INR"},
+
+	/* supplies */
+	{"Output Mixer", NULL, "Charge Pump 1"},
+	{"Output Mixer", NULL, "Charge Pump 2"},
+	{"Output Mixer", NULL, "SHDN"},
+	{"DAC", NULL, "MCLK"},
+};
+
+static int max9850_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 max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
+	u64 lrclk_div;
+	u8 sf, da;
+
+	if (!max9850->sysclk)
+		return -EINVAL;
+
+	/* lrclk_div = 2^22 * rate / iclk with iclk = mclk / sf */
+	sf = (snd_soc_read(codec, MAX9850_CLOCK) >> 2) + 1;
+	lrclk_div = (1 << 22);
+	lrclk_div *= params_rate(params);
+	lrclk_div *= sf;
+	do_div(lrclk_div, max9850->sysclk);
+
+	snd_soc_write(codec, MAX9850_LRCLK_MSB, (lrclk_div >> 8) & 0x7f);
+	snd_soc_write(codec, MAX9850_LRCLK_LSB, lrclk_div & 0xff);
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		da = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		da = 0x2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		da = 0x3;
+		break;
+	default:
+		return -EINVAL;
+	}
+	snd_soc_update_bits(codec, MAX9850_DIGITAL_AUDIO, 0x3, da);
+
+	return 0;
+}
+
+static int max9850_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 max9850_priv *max9850 = snd_soc_codec_get_drvdata(codec);
+
+	/* calculate mclk -> iclk divider */
+	if (freq <= 13000000)
+		snd_soc_write(codec, MAX9850_CLOCK, 0x0);
+	else if (freq <= 26000000)
+		snd_soc_write(codec, MAX9850_CLOCK, 0x4);
+	else if (freq <= 40000000)
+		snd_soc_write(codec, MAX9850_CLOCK, 0x8);
+	else
+		return -EINVAL;
+
+	max9850->sysclk = freq;
+	return 0;
+}
+
+static int max9850_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u8 da = 0;
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		da |= MAX9850_MASTER;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		da |= MAX9850_DLY;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		da |= MAX9850_RTJ;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_IF:
+		da |= MAX9850_BCINV | MAX9850_INV;
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		da |= MAX9850_BCINV;
+		break;
+	case SND_SOC_DAIFMT_NB_IF:
+		da |= MAX9850_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set da */
+	snd_soc_write(codec, MAX9850_DIGITAL_AUDIO, da);
+
+	return 0;
+}
+
+static int max9850_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	int ret;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = snd_soc_cache_sync(codec);
+			if (ret) {
+				dev_err(codec->dev,
+					"Failed to sync cache: %d\n", ret);
+				return ret;
+			}
+		}
+		break;
+	case SND_SOC_BIAS_OFF:
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#define MAX9850_RATES SNDRV_PCM_RATE_8000_48000
+
+#define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+	SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops max9850_dai_ops = {
+	.hw_params	= max9850_hw_params,
+	.set_sysclk	= max9850_set_dai_sysclk,
+	.set_fmt	= max9850_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver max9850_dai = {
+	.name = "max9850-hifi",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = MAX9850_RATES,
+		.formats = MAX9850_FORMATS
+	},
+	.ops = &max9850_dai_ops,
+};
+
+#ifdef CONFIG_PM
+static int max9850_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	max9850_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+static int max9850_resume(struct snd_soc_codec *codec)
+{
+	max9850_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	return 0;
+}
+#else
+#define max9850_suspend NULL
+#define max9850_resume NULL
+#endif
+
+static int max9850_probe(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	/* enable zero-detect */
+	snd_soc_update_bits(codec, MAX9850_GENERAL_PURPOSE, 1, 1);
+	/* enable slew-rate control */
+	snd_soc_update_bits(codec, MAX9850_VOLUME, 0x40, 0x40);
+	/* set slew-rate 125ms */
+	snd_soc_update_bits(codec, MAX9850_CHARGE_PUMP, 0xff, 0xc0);
+
+	snd_soc_dapm_new_controls(dapm, max9850_dapm_widgets,
+				  ARRAY_SIZE(max9850_dapm_widgets));
+	snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
+
+	snd_soc_add_controls(codec, max9850_controls,
+			ARRAY_SIZE(max9850_controls));
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
+	.probe =	max9850_probe,
+	.suspend =	max9850_suspend,
+	.resume =	max9850_resume,
+	.set_bias_level = max9850_set_bias_level,
+	.reg_cache_size = ARRAY_SIZE(max9850_reg),
+	.reg_word_size = sizeof(u8),
+	.reg_cache_default = max9850_reg,
+	.volatile_register = max9850_volatile_register,
+};
+
+static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
+		const struct i2c_device_id *id)
+{
+	struct max9850_priv *max9850;
+	int ret;
+
+	max9850 = kzalloc(sizeof(struct max9850_priv), GFP_KERNEL);
+	if (max9850 == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, max9850);
+
+	ret = snd_soc_register_codec(&i2c->dev,
+			&soc_codec_dev_max9850, &max9850_dai, 1);
+	if (ret < 0)
+		kfree(max9850);
+	return ret;
+}
+
+static __devexit int max9850_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id max9850_i2c_id[] = {
+	{ "max9850", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max9850_i2c_id);
+
+static struct i2c_driver max9850_i2c_driver = {
+	.driver = {
+		.name = "max9850",
+		.owner = THIS_MODULE,
+	},
+	.probe = max9850_i2c_probe,
+	.remove = __devexit_p(max9850_i2c_remove),
+	.id_table = max9850_i2c_id,
+};
+
+static int __init max9850_init(void)
+{
+	return i2c_add_driver(&max9850_i2c_driver);
+}
+module_init(max9850_init);
+
+static void __exit max9850_exit(void)
+{
+	i2c_del_driver(&max9850_i2c_driver);
+}
+module_exit(max9850_exit);
+
+MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>");
+MODULE_DESCRIPTION("ASoC MAX9850 codec driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max9850.h b/sound/soc/codecs/max9850.h
new file mode 100644
index 0000000..72b1ddb
--- /dev/null
+++ b/sound/soc/codecs/max9850.h
@@ -0,0 +1,38 @@
+/*
+ * max9850.h  --  codec driver for max9850
+ *
+ * Copyright (C) 2011 taskit GmbH
+ * Author: Christian Glindkamp <christian.glindkamp@taskit.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.
+ *
+ */
+
+#ifndef _MAX9850_H
+#define _MAX9850_H
+
+#define MAX9850_STATUSA			0x00
+#define MAX9850_STATUSB			0x01
+#define MAX9850_VOLUME			0x02
+#define MAX9850_GENERAL_PURPOSE		0x03
+#define MAX9850_INTERRUPT		0x04
+#define MAX9850_ENABLE			0x05
+#define MAX9850_CLOCK			0x06
+#define MAX9850_CHARGE_PUMP		0x07
+#define MAX9850_LRCLK_MSB		0x08
+#define MAX9850_LRCLK_LSB		0x09
+#define MAX9850_DIGITAL_AUDIO		0x0a
+
+#define MAX9850_CACHEREGNUM 11
+
+/* MAX9850_DIGITAL_AUDIO */
+#define MAX9850_MASTER			(1<<7)
+#define MAX9850_INV			(1<<6)
+#define MAX9850_BCINV			(1<<5)
+#define MAX9850_DLY			(1<<3)
+#define MAX9850_RTJ			(1<<2)
+
+#endif
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
new file mode 100644
index 0000000..ff29380
--- /dev/null
+++ b/sound/soc/codecs/sgtl5000.c
@@ -0,0 +1,1527 @@
+/*
+ * sgtl5000.c  --  SGTL5000 ALSA SoC Audio driver
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <sound/core.h>
+#include <sound/tlv.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+
+#include "sgtl5000.h"
+
+#define SGTL5000_DAP_REG_OFFSET	0x0100
+#define SGTL5000_MAX_REG_OFFSET	0x013A
+
+/* default value of sgtl5000 registers except DAP */
+static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET >> 1] =  {
+	0xa011, /* 0x0000, CHIP_ID. 11 stand for revison 17 */
+	0x0000, /* 0x0002, CHIP_DIG_POWER. */
+	0x0008, /* 0x0004, CHIP_CKL_CTRL */
+	0x0010, /* 0x0006, CHIP_I2S_CTRL */
+	0x0000, /* 0x0008, reserved */
+	0x0008, /* 0x000A, CHIP_SSS_CTRL */
+	0x0000, /* 0x000C, reserved */
+	0x020c, /* 0x000E, CHIP_ADCDAC_CTRL */
+	0x3c3c, /* 0x0010, CHIP_DAC_VOL */
+	0x0000, /* 0x0012, reserved */
+	0x015f, /* 0x0014, CHIP_PAD_STRENGTH */
+	0x0000, /* 0x0016, reserved */
+	0x0000, /* 0x0018, reserved */
+	0x0000, /* 0x001A, reserved */
+	0x0000, /* 0x001E, reserved */
+	0x0000, /* 0x0020, CHIP_ANA_ADC_CTRL */
+	0x1818, /* 0x0022, CHIP_ANA_HP_CTRL */
+	0x0111, /* 0x0024, CHIP_ANN_CTRL */
+	0x0000, /* 0x0026, CHIP_LINREG_CTRL */
+	0x0000, /* 0x0028, CHIP_REF_CTRL */
+	0x0000, /* 0x002A, CHIP_MIC_CTRL */
+	0x0000, /* 0x002C, CHIP_LINE_OUT_CTRL */
+	0x0404, /* 0x002E, CHIP_LINE_OUT_VOL */
+	0x7060, /* 0x0030, CHIP_ANA_POWER */
+	0x5000, /* 0x0032, CHIP_PLL_CTRL */
+	0x0000, /* 0x0034, CHIP_CLK_TOP_CTRL */
+	0x0000, /* 0x0036, CHIP_ANA_STATUS */
+	0x0000, /* 0x0038, reserved */
+	0x0000, /* 0x003A, CHIP_ANA_TEST2 */
+	0x0000, /* 0x003C, CHIP_SHORT_CTRL */
+	0x0000, /* reserved */
+};
+
+/* default value of dap registers */
+static const u16 sgtl5000_dap_regs[] = {
+	0x0000, /* 0x0100, DAP_CONTROL */
+	0x0000, /* 0x0102, DAP_PEQ */
+	0x0040, /* 0x0104, DAP_BASS_ENHANCE */
+	0x051f, /* 0x0106, DAP_BASS_ENHANCE_CTRL */
+	0x0000, /* 0x0108, DAP_AUDIO_EQ */
+	0x0040, /* 0x010A, DAP_SGTL_SURROUND */
+	0x0000, /* 0x010C, DAP_FILTER_COEF_ACCESS */
+	0x0000, /* 0x010E, DAP_COEF_WR_B0_MSB */
+	0x0000, /* 0x0110, DAP_COEF_WR_B0_LSB */
+	0x0000, /* 0x0112, reserved */
+	0x0000, /* 0x0114, reserved */
+	0x002f, /* 0x0116, DAP_AUDIO_EQ_BASS_BAND0 */
+	0x002f, /* 0x0118, DAP_AUDIO_EQ_BAND0 */
+	0x002f, /* 0x011A, DAP_AUDIO_EQ_BAND2 */
+	0x002f, /* 0x011C, DAP_AUDIO_EQ_BAND3 */
+	0x002f, /* 0x011E, DAP_AUDIO_EQ_TREBLE_BAND4 */
+	0x8000, /* 0x0120, DAP_MAIN_CHAN */
+	0x0000, /* 0x0122, DAP_MIX_CHAN */
+	0x0510, /* 0x0124, DAP_AVC_CTRL */
+	0x1473, /* 0x0126, DAP_AVC_THRESHOLD */
+	0x0028, /* 0x0128, DAP_AVC_ATTACK */
+	0x0050, /* 0x012A, DAP_AVC_DECAY */
+	0x0000, /* 0x012C, DAP_COEF_WR_B1_MSB */
+	0x0000, /* 0x012E, DAP_COEF_WR_B1_LSB */
+	0x0000, /* 0x0130, DAP_COEF_WR_B2_MSB */
+	0x0000, /* 0x0132, DAP_COEF_WR_B2_LSB */
+	0x0000, /* 0x0134, DAP_COEF_WR_A1_MSB */
+	0x0000, /* 0x0136, DAP_COEF_WR_A1_LSB */
+	0x0000, /* 0x0138, DAP_COEF_WR_A2_MSB */
+	0x0000, /* 0x013A, DAP_COEF_WR_A2_LSB */
+};
+
+/* regulator supplies for sgtl5000, VDDD is an optional external supply */
+enum sgtl5000_regulator_supplies {
+	VDDA,
+	VDDIO,
+	VDDD,
+	SGTL5000_SUPPLY_NUM
+};
+
+/* vddd is optional supply */
+static const char *supply_names[SGTL5000_SUPPLY_NUM] = {
+	"VDDA",
+	"VDDIO",
+	"VDDD"
+};
+
+#define LDO_CONSUMER_NAME	"VDDD_LDO"
+#define LDO_VOLTAGE		1200000
+
+static struct regulator_consumer_supply ldo_consumer[] = {
+	REGULATOR_SUPPLY(LDO_CONSUMER_NAME, NULL),
+};
+
+static struct regulator_init_data ldo_init_data = {
+	.constraints = {
+		.min_uV                 = 850000,
+		.max_uV                 = 1600000,
+		.valid_modes_mask       = REGULATOR_MODE_NORMAL,
+		.valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &ldo_consumer[0],
+};
+
+/*
+ * sgtl5000 internal ldo regulator,
+ * enabled when VDDD not provided
+ */
+struct ldo_regulator {
+	struct regulator_desc desc;
+	struct regulator_dev *dev;
+	int voltage;
+	void *codec_data;
+	bool enabled;
+};
+
+/* sgtl5000 private structure in codec */
+struct sgtl5000_priv {
+	int sysclk;	/* sysclk rate */
+	int master;	/* i2s master or not */
+	int fmt;	/* i2s data format */
+	struct regulator_bulk_data supplies[SGTL5000_SUPPLY_NUM];
+	struct ldo_regulator *ldo;
+};
+
+/*
+ * mic_bias power on/off share the same register bits with
+ * output impedance of mic bias, when power on mic bias, we
+ * need reclaim it to impedance value.
+ * 0x0 = Powered off
+ * 0x1 = 2Kohm
+ * 0x2 = 4Kohm
+ * 0x3 = 8Kohm
+ */
+static int mic_bias_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/* change mic bias resistor to 4Kohm */
+		snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
+				SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		/*
+		 * SGTL5000_BIAS_R_8k as mask to clean the two bits
+		 * of mic bias and output impedance
+		 */
+		snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
+				SGTL5000_BIAS_R_8k, 0);
+		break;
+	}
+	return 0;
+}
+
+/*
+ * using codec assist to small pop, hp_powerup or lineout_powerup
+ * should stay setting until vag_powerup is fully ramped down,
+ * vag fully ramped down require 400ms.
+ */
+static int small_pop_event(struct snd_soc_dapm_widget *w,
+	struct snd_kcontrol *kcontrol, int event)
+{
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
+			SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
+			SGTL5000_VAG_POWERUP, 0);
+		msleep(400);
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* input sources for ADC */
+static const char *adc_mux_text[] = {
+	"MIC_IN", "LINE_IN"
+};
+
+static const struct soc_enum adc_enum =
+SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text);
+
+static const struct snd_kcontrol_new adc_mux =
+SOC_DAPM_ENUM("Capture Mux", adc_enum);
+
+/* input sources for DAC */
+static const char *dac_mux_text[] = {
+	"DAC", "LINE_IN"
+};
+
+static const struct soc_enum dac_enum =
+SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text);
+
+static const struct snd_kcontrol_new dac_mux =
+SOC_DAPM_ENUM("Headphone Mux", dac_enum);
+
+static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
+	SND_SOC_DAPM_INPUT("LINE_IN"),
+	SND_SOC_DAPM_INPUT("MIC_IN"),
+
+	SND_SOC_DAPM_OUTPUT("HP_OUT"),
+	SND_SOC_DAPM_OUTPUT("LINE_OUT"),
+
+	SND_SOC_DAPM_MICBIAS_E("Mic Bias", SGTL5000_CHIP_MIC_CTRL, 8, 0,
+				mic_bias_event,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_PGA_E("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0,
+			small_pop_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+	SND_SOC_DAPM_PGA_E("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0,
+			small_pop_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
+
+	SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
+	SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux),
+
+	/* aif for i2s input */
+	SND_SOC_DAPM_AIF_IN("AIFIN", "Playback",
+				0, SGTL5000_CHIP_DIG_POWER,
+				0, 0),
+
+	/* aif for i2s output */
+	SND_SOC_DAPM_AIF_OUT("AIFOUT", "Capture",
+				0, SGTL5000_CHIP_DIG_POWER,
+				1, 0),
+
+	SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
+
+	SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0),
+};
+
+/* routes for sgtl5000 */
+static const struct snd_soc_dapm_route audio_map[] = {
+	{"Capture Mux", "LINE_IN", "LINE_IN"},	/* line_in --> adc_mux */
+	{"Capture Mux", "MIC_IN", "MIC_IN"},	/* mic_in --> adc_mux */
+
+	{"ADC", NULL, "Capture Mux"},		/* adc_mux --> adc */
+	{"AIFOUT", NULL, "ADC"},		/* adc --> i2s_out */
+
+	{"DAC", NULL, "AIFIN"},			/* i2s-->dac,skip audio mux */
+	{"Headphone Mux", "DAC", "DAC"},	/* dac --> hp_mux */
+	{"LO", NULL, "DAC"},			/* dac --> line_out */
+
+	{"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */
+	{"HP", NULL, "Headphone Mux"},		/* hp_mux --> hp */
+
+	{"LINE_OUT", NULL, "LO"},
+	{"HP_OUT", NULL, "HP"},
+};
+
+/* custom function to fetch info of PCM playback volume */
+static int dac_info_volsw(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xfc - 0x3c;
+	return 0;
+}
+
+/*
+ * custom function to get of PCM playback volume
+ *
+ * dac volume register
+ * 15-------------8-7--------------0
+ * | R channel vol | L channel vol |
+ *  -------------------------------
+ *
+ * PCM volume with 0.5017 dB steps from 0 to -90 dB
+ *
+ * register values map to dB
+ * 0x3B and less = Reserved
+ * 0x3C = 0 dB
+ * 0x3D = -0.5 dB
+ * 0xF0 = -90 dB
+ * 0xFC and greater = Muted
+ *
+ * register value map to userspace value
+ *
+ * register value	0x3c(0dB)	  0xf0(-90dB)0xfc
+ *			------------------------------
+ * userspace value	0xc0			     0
+ */
+static int dac_get_volsw(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg;
+	int l;
+	int r;
+
+	reg = snd_soc_read(codec, SGTL5000_CHIP_DAC_VOL);
+
+	/* get left channel volume */
+	l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT;
+
+	/* get right channel volume */
+	r = (reg & SGTL5000_DAC_VOL_RIGHT_MASK) >> SGTL5000_DAC_VOL_RIGHT_SHIFT;
+
+	/* make sure value fall in (0x3c,0xfc) */
+	l = clamp(l, 0x3c, 0xfc);
+	r = clamp(r, 0x3c, 0xfc);
+
+	/* invert it and map to userspace value */
+	l = 0xfc - l;
+	r = 0xfc - r;
+
+	ucontrol->value.integer.value[0] = l;
+	ucontrol->value.integer.value[1] = r;
+
+	return 0;
+}
+
+/*
+ * custom function to put of PCM playback volume
+ *
+ * dac volume register
+ * 15-------------8-7--------------0
+ * | R channel vol | L channel vol |
+ *  -------------------------------
+ *
+ * PCM volume with 0.5017 dB steps from 0 to -90 dB
+ *
+ * register values map to dB
+ * 0x3B and less = Reserved
+ * 0x3C = 0 dB
+ * 0x3D = -0.5 dB
+ * 0xF0 = -90 dB
+ * 0xFC and greater = Muted
+ *
+ * userspace value map to register value
+ *
+ * userspace value	0xc0			     0
+ *			------------------------------
+ * register value	0x3c(0dB)	0xf0(-90dB)0xfc
+ */
+static int dac_put_volsw(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg;
+	int l;
+	int r;
+
+	l = ucontrol->value.integer.value[0];
+	r = ucontrol->value.integer.value[1];
+
+	/* make sure userspace volume fall in (0, 0xfc-0x3c) */
+	l = clamp(l, 0, 0xfc - 0x3c);
+	r = clamp(r, 0, 0xfc - 0x3c);
+
+	/* invert it, get the value can be set to register */
+	l = 0xfc - l;
+	r = 0xfc - r;
+
+	/* shift to get the register value */
+	reg = l << SGTL5000_DAC_VOL_LEFT_SHIFT |
+		r << SGTL5000_DAC_VOL_RIGHT_SHIFT;
+
+	snd_soc_write(codec, SGTL5000_CHIP_DAC_VOL, reg);
+
+	return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0);
+
+/* tlv for mic gain, 0db 20db 30db 40db */
+static const unsigned int mic_gain_tlv[] = {
+	TLV_DB_RANGE_HEAD(4),
+	0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+	1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
+};
+
+/* tlv for hp volume, -51.5db to 12.0db, step .5db */
+static const DECLARE_TLV_DB_SCALE(headphone_volume, -5150, 50, 0);
+
+static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
+	/* SOC_DOUBLE_S8_TLV with invert */
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "PCM Playback Volume",
+		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+			SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = dac_info_volsw,
+		.get = dac_get_volsw,
+		.put = dac_put_volsw,
+	},
+
+	SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0),
+	SOC_SINGLE_TLV("Capture Attenuate Switch (-6dB)",
+			SGTL5000_CHIP_ANA_ADC_CTRL,
+			8, 2, 0, capture_6db_attenuate),
+	SOC_SINGLE("Capture ZC Switch", SGTL5000_CHIP_ANA_CTRL, 1, 1, 0),
+
+	SOC_DOUBLE_TLV("Headphone Playback Volume",
+			SGTL5000_CHIP_ANA_HP_CTRL,
+			0, 8,
+			0x7f, 1,
+			headphone_volume),
+	SOC_SINGLE("Headphone Playback ZC Switch", SGTL5000_CHIP_ANA_CTRL,
+			5, 1, 0),
+
+	SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL,
+			0, 4, 0, mic_gain_tlv),
+};
+
+/* mute the codec used by alsa core */
+static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 adcdac_ctrl = SGTL5000_DAC_MUTE_LEFT | SGTL5000_DAC_MUTE_RIGHT;
+
+	snd_soc_update_bits(codec, SGTL5000_CHIP_ADCDAC_CTRL,
+			adcdac_ctrl, mute ? adcdac_ctrl : 0);
+
+	return 0;
+}
+
+/* set codec format */
+static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+	u16 i2sctl = 0;
+
+	sgtl5000->master = 0;
+	/*
+	 * i2s clock and frame master setting.
+	 * ONLY support:
+	 *  - clock and frame slave,
+	 *  - clock and frame master
+	 */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		i2sctl |= SGTL5000_I2S_MASTER;
+		sgtl5000->master = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* setting i2s data format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		i2sctl |= SGTL5000_I2S_MODE_PCM;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		i2sctl |= SGTL5000_I2S_MODE_PCM;
+		i2sctl |= SGTL5000_I2S_LRALIGN;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		i2sctl |= SGTL5000_I2S_MODE_I2S_LJ;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		i2sctl |= SGTL5000_I2S_MODE_RJ;
+		i2sctl |= SGTL5000_I2S_LRPOL;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		i2sctl |= SGTL5000_I2S_MODE_I2S_LJ;
+		i2sctl |= SGTL5000_I2S_LRALIGN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	sgtl5000->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+
+	/* Clock inversion */
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	case SND_SOC_DAIFMT_IB_NF:
+		i2sctl |= SGTL5000_I2S_SCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, SGTL5000_CHIP_I2S_CTRL, i2sctl);
+
+	return 0;
+}
+
+/* set codec sysclk */
+static int sgtl5000_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 sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+
+	switch (clk_id) {
+	case SGTL5000_SYSCLK:
+		sgtl5000->sysclk = freq;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * set clock according to i2s frame clock,
+ * sgtl5000 provide 2 clock sources.
+ * 1. sys_mclk. sample freq can only configure to
+ *	1/256, 1/384, 1/512 of sys_mclk.
+ * 2. pll. can derive any audio clocks.
+ *
+ * clock setting rules:
+ * 1. in slave mode, only sys_mclk can use.
+ * 2. as constraint by sys_mclk, sample freq should
+ *	set to 32k, 44.1k and above.
+ * 3. using sys_mclk prefer to pll to save power.
+ */
+static int sgtl5000_set_clock(struct snd_soc_codec *codec, int frame_rate)
+{
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+	int clk_ctl = 0;
+	int sys_fs;	/* sample freq */
+
+	/*
+	 * sample freq should be divided by frame clock,
+	 * if frame clock lower than 44.1khz, sample feq should set to
+	 * 32khz or 44.1khz.
+	 */
+	switch (frame_rate) {
+	case 8000:
+	case 16000:
+		sys_fs = 32000;
+		break;
+	case 11025:
+	case 22050:
+		sys_fs = 44100;
+		break;
+	default:
+		sys_fs = frame_rate;
+		break;
+	}
+
+	/* set divided factor of frame clock */
+	switch (sys_fs / frame_rate) {
+	case 4:
+		clk_ctl |= SGTL5000_RATE_MODE_DIV_4 << SGTL5000_RATE_MODE_SHIFT;
+		break;
+	case 2:
+		clk_ctl |= SGTL5000_RATE_MODE_DIV_2 << SGTL5000_RATE_MODE_SHIFT;
+		break;
+	case 1:
+		clk_ctl |= SGTL5000_RATE_MODE_DIV_1 << SGTL5000_RATE_MODE_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* set the sys_fs according to frame rate */
+	switch (sys_fs) {
+	case 32000:
+		clk_ctl |= SGTL5000_SYS_FS_32k << SGTL5000_SYS_FS_SHIFT;
+		break;
+	case 44100:
+		clk_ctl |= SGTL5000_SYS_FS_44_1k << SGTL5000_SYS_FS_SHIFT;
+		break;
+	case 48000:
+		clk_ctl |= SGTL5000_SYS_FS_48k << SGTL5000_SYS_FS_SHIFT;
+		break;
+	case 96000:
+		clk_ctl |= SGTL5000_SYS_FS_96k << SGTL5000_SYS_FS_SHIFT;
+		break;
+	default:
+		dev_err(codec->dev, "frame rate %d not supported\n",
+			frame_rate);
+		return -EINVAL;
+	}
+
+	/*
+	 * calculate the divider of mclk/sample_freq,
+	 * factor of freq =96k can only be 256, since mclk in range (12m,27m)
+	 */
+	switch (sgtl5000->sysclk / sys_fs) {
+	case 256:
+		clk_ctl |= SGTL5000_MCLK_FREQ_256FS <<
+			SGTL5000_MCLK_FREQ_SHIFT;
+		break;
+	case 384:
+		clk_ctl |= SGTL5000_MCLK_FREQ_384FS <<
+			SGTL5000_MCLK_FREQ_SHIFT;
+		break;
+	case 512:
+		clk_ctl |= SGTL5000_MCLK_FREQ_512FS <<
+			SGTL5000_MCLK_FREQ_SHIFT;
+		break;
+	default:
+		/* if mclk not satisify the divider, use pll */
+		if (sgtl5000->master) {
+			clk_ctl |= SGTL5000_MCLK_FREQ_PLL <<
+				SGTL5000_MCLK_FREQ_SHIFT;
+		} else {
+			dev_err(codec->dev,
+				"PLL not supported in slave mode\n");
+			return -EINVAL;
+		}
+	}
+
+	/* if using pll, please check manual 6.4.2 for detail */
+	if ((clk_ctl & SGTL5000_MCLK_FREQ_MASK) == SGTL5000_MCLK_FREQ_PLL) {
+		u64 out, t;
+		int div2;
+		int pll_ctl;
+		unsigned int in, int_div, frac_div;
+
+		if (sgtl5000->sysclk > 17000000) {
+			div2 = 1;
+			in = sgtl5000->sysclk / 2;
+		} else {
+			div2 = 0;
+			in = sgtl5000->sysclk;
+		}
+		if (sys_fs == 44100)
+			out = 180633600;
+		else
+			out = 196608000;
+		t = do_div(out, in);
+		int_div = out;
+		t *= 2048;
+		do_div(t, in);
+		frac_div = t;
+		pll_ctl = int_div << SGTL5000_PLL_INT_DIV_SHIFT |
+		    frac_div << SGTL5000_PLL_FRAC_DIV_SHIFT;
+
+		snd_soc_write(codec, SGTL5000_CHIP_PLL_CTRL, pll_ctl);
+		if (div2)
+			snd_soc_update_bits(codec,
+				SGTL5000_CHIP_CLK_TOP_CTRL,
+				SGTL5000_INPUT_FREQ_DIV2,
+				SGTL5000_INPUT_FREQ_DIV2);
+		else
+			snd_soc_update_bits(codec,
+				SGTL5000_CHIP_CLK_TOP_CTRL,
+				SGTL5000_INPUT_FREQ_DIV2,
+				0);
+
+		/* power up pll */
+		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
+			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP);
+	} else {
+		/* power down pll */
+		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+			SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP,
+			0);
+	}
+
+	/* if using pll, clk_ctrl must be set after pll power up */
+	snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
+
+	return 0;
+}
+
+/*
+ * Set PCM DAI bit size and sample rate.
+ * input: params_rate, params_fmt
+ */
+static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
+				  struct snd_pcm_hw_params *params,
+				  struct snd_soc_dai *dai)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+	int channels = params_channels(params);
+	int i2s_ctl = 0;
+	int stereo;
+	int ret;
+
+	/* sysclk should already set */
+	if (!sgtl5000->sysclk) {
+		dev_err(codec->dev, "%s: set sysclk first!\n", __func__);
+		return -EFAULT;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		stereo = SGTL5000_DAC_STEREO;
+	else
+		stereo = SGTL5000_ADC_STEREO;
+
+	/* set mono to save power */
+	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, stereo,
+			channels == 1 ? 0 : stereo);
+
+	/* set codec clock base on lrclk */
+	ret = sgtl5000_set_clock(codec, params_rate(params));
+	if (ret)
+		return ret;
+
+	/* set i2s data format */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
+			return -EINVAL;
+		i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT;
+		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS <<
+		    SGTL5000_I2S_SCLKFREQ_SHIFT;
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT;
+		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
+		    SGTL5000_I2S_SCLKFREQ_SHIFT;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT;
+		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
+		    SGTL5000_I2S_SCLKFREQ_SHIFT;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
+			return -EINVAL;
+		i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT;
+		i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
+		    SGTL5000_I2S_SCLKFREQ_SHIFT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl);
+
+	return 0;
+}
+
+#ifdef CONFIG_REGULATOR
+static int ldo_regulator_is_enabled(struct regulator_dev *dev)
+{
+	struct ldo_regulator *ldo = rdev_get_drvdata(dev);
+
+	return ldo->enabled;
+}
+
+static int ldo_regulator_enable(struct regulator_dev *dev)
+{
+	struct ldo_regulator *ldo = rdev_get_drvdata(dev);
+	struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data;
+	int reg;
+
+	if (ldo_regulator_is_enabled(dev))
+		return 0;
+
+	/* set regulator value firstly */
+	reg = (1600 - ldo->voltage / 1000) / 50;
+	reg = clamp(reg, 0x0, 0xf);
+
+	/* amend the voltage value, unit: uV */
+	ldo->voltage = (1600 - reg * 50) * 1000;
+
+	/* set voltage to register */
+	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
+				(0x1 << 4) - 1, reg);
+
+	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_LINEREG_D_POWERUP,
+				SGTL5000_LINEREG_D_POWERUP);
+
+	/* when internal ldo enabled, simple digital power can be disabled */
+	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_LINREG_SIMPLE_POWERUP,
+				0);
+
+	ldo->enabled = 1;
+	return 0;
+}
+
+static int ldo_regulator_disable(struct regulator_dev *dev)
+{
+	struct ldo_regulator *ldo = rdev_get_drvdata(dev);
+	struct snd_soc_codec *codec = (struct snd_soc_codec *)ldo->codec_data;
+
+	snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_LINEREG_D_POWERUP,
+				0);
+
+	/* clear voltage info */
+	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
+				(0x1 << 4) - 1, 0);
+
+	ldo->enabled = 0;
+
+	return 0;
+}
+
+static int ldo_regulator_get_voltage(struct regulator_dev *dev)
+{
+	struct ldo_regulator *ldo = rdev_get_drvdata(dev);
+
+	return ldo->voltage;
+}
+
+static struct regulator_ops ldo_regulator_ops = {
+	.is_enabled = ldo_regulator_is_enabled,
+	.enable = ldo_regulator_enable,
+	.disable = ldo_regulator_disable,
+	.get_voltage = ldo_regulator_get_voltage,
+};
+
+static int ldo_regulator_register(struct snd_soc_codec *codec,
+				struct regulator_init_data *init_data,
+				int voltage)
+{
+	struct ldo_regulator *ldo;
+
+	ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
+
+	if (!ldo) {
+		dev_err(codec->dev, "failed to allocate ldo_regulator\n");
+		return -ENOMEM;
+	}
+
+	ldo->desc.name = kstrdup(dev_name(codec->dev), GFP_KERNEL);
+	if (!ldo->desc.name) {
+		kfree(ldo);
+		dev_err(codec->dev, "failed to allocate decs name memory\n");
+		return -ENOMEM;
+	}
+
+	ldo->desc.type  = REGULATOR_VOLTAGE;
+	ldo->desc.owner = THIS_MODULE;
+	ldo->desc.ops   = &ldo_regulator_ops;
+	ldo->desc.n_voltages = 1;
+
+	ldo->codec_data = codec;
+	ldo->voltage = voltage;
+
+	ldo->dev = regulator_register(&ldo->desc, codec->dev,
+					  init_data, ldo);
+	if (IS_ERR(ldo->dev)) {
+		int ret = PTR_ERR(ldo->dev);
+
+		dev_err(codec->dev, "failed to register regulator\n");
+		kfree(ldo->desc.name);
+		kfree(ldo);
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ldo_regulator_remove(struct snd_soc_codec *codec)
+{
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+	struct ldo_regulator *ldo = sgtl5000->ldo;
+
+	if (!ldo)
+		return 0;
+
+	regulator_unregister(ldo->dev);
+	kfree(ldo->desc.name);
+	kfree(ldo);
+
+	return 0;
+}
+#else
+static int ldo_regulator_register(struct snd_soc_codec *codec,
+				struct regulator_init_data *init_data,
+				int voltage)
+{
+	return -EINVAL;
+}
+
+static int ldo_regulator_remove(struct snd_soc_codec *codec)
+{
+	return 0;
+}
+#endif
+
+/*
+ * set dac bias
+ * common state changes:
+ * startup:
+ * off --> standby --> prepare --> on
+ * standby --> prepare --> on
+ *
+ * stop:
+ * on --> prepare --> standby
+ */
+static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
+				   enum snd_soc_bias_level level)
+{
+	int ret;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = regulator_bulk_enable(
+						ARRAY_SIZE(sgtl5000->supplies),
+						sgtl5000->supplies);
+			if (ret)
+				return ret;
+			udelay(10);
+		}
+
+		break;
+	case SND_SOC_BIAS_OFF:
+		regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+					sgtl5000->supplies);
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#define SGTL5000_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S24_LE |\
+			SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops sgtl5000_ops = {
+	.hw_params = sgtl5000_pcm_hw_params,
+	.digital_mute = sgtl5000_digital_mute,
+	.set_fmt = sgtl5000_set_dai_fmt,
+	.set_sysclk = sgtl5000_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver sgtl5000_dai = {
+	.name = "sgtl5000",
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		/*
+		 * only support 8~48K + 96K,
+		 * TODO modify hw_param to support more
+		 */
+		.rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_96000,
+		.formats = SGTL5000_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_96000,
+		.formats = SGTL5000_FORMATS,
+	},
+	.ops = &sgtl5000_ops,
+	.symmetric_rates = 1,
+};
+
+static int sgtl5000_volatile_register(struct snd_soc_codec *codec,
+					unsigned int reg)
+{
+	switch (reg) {
+	case SGTL5000_CHIP_ID:
+	case SGTL5000_CHIP_ADCDAC_CTRL:
+	case SGTL5000_CHIP_ANA_STATUS:
+		return 1;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_SUSPEND
+static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+/*
+ * restore all sgtl5000 registers,
+ * since a big hole between dap and regular registers,
+ * we will restore them respectively.
+ */
+static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
+{
+	u16 *cache = codec->reg_cache;
+	int i;
+	int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1;
+
+	/* restore regular registers */
+	for (i = 0; i < regular_regs; i++) {
+		int reg = i << 1;
+
+		/* this regs depends on the others */
+		if (reg == SGTL5000_CHIP_ANA_POWER ||
+			reg == SGTL5000_CHIP_CLK_CTRL ||
+			reg == SGTL5000_CHIP_LINREG_CTRL ||
+			reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
+			reg == SGTL5000_CHIP_CLK_CTRL)
+			continue;
+
+		snd_soc_write(codec, reg, cache[i]);
+	}
+
+	/* restore dap registers */
+	for (i = SGTL5000_DAP_REG_OFFSET >> 1;
+			i < SGTL5000_MAX_REG_OFFSET >> 1; i++) {
+		int reg = i << 1;
+
+		snd_soc_write(codec, reg, cache[i]);
+	}
+
+	/*
+	 * restore power and other regs according
+	 * to set_power() and set_clock()
+	 */
+	snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
+			cache[SGTL5000_CHIP_LINREG_CTRL >> 1]);
+
+	snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER,
+			cache[SGTL5000_CHIP_ANA_POWER >> 1]);
+
+	snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL,
+			cache[SGTL5000_CHIP_CLK_CTRL >> 1]);
+
+	snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL,
+			cache[SGTL5000_CHIP_REF_CTRL >> 1]);
+
+	snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
+			cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]);
+	return 0;
+}
+
+static int sgtl5000_resume(struct snd_soc_codec *codec)
+{
+	/* Bring the codec back up to standby to enable regulators */
+	sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	/* Restore registers by cached in memory */
+	sgtl5000_restore_regs(codec);
+	return 0;
+}
+#else
+#define sgtl5000_suspend NULL
+#define sgtl5000_resume  NULL
+#endif	/* CONFIG_SUSPEND */
+
+/*
+ * sgtl5000 has 3 internal power supplies:
+ * 1. VAG, normally set to vdda/2
+ * 2. chargepump, set to different value
+ *	according to voltage of vdda and vddio
+ * 3. line out VAG, normally set to vddio/2
+ *
+ * and should be set according to:
+ * 1. vddd provided by external or not
+ * 2. vdda and vddio voltage value. > 3.1v or not
+ * 3. chip revision >=0x11 or not. If >=0x11, not use external vddd.
+ */
+static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
+{
+	int vddd;
+	int vdda;
+	int vddio;
+	u16 ana_pwr;
+	u16 lreg_ctrl;
+	int vag;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+
+	vdda  = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer);
+	vddio = regulator_get_voltage(sgtl5000->supplies[VDDIO].consumer);
+	vddd  = regulator_get_voltage(sgtl5000->supplies[VDDD].consumer);
+
+	vdda  = vdda / 1000;
+	vddio = vddio / 1000;
+	vddd  = vddd / 1000;
+
+	if (vdda <= 0 || vddio <= 0 || vddd < 0) {
+		dev_err(codec->dev, "regulator voltage not set correctly\n");
+
+		return -EINVAL;
+	}
+
+	/* according to datasheet, maximum voltage of supplies */
+	if (vdda > 3600 || vddio > 3600 || vddd > 1980) {
+		dev_err(codec->dev,
+			"exceed max voltage vdda %dmv vddio %dma vddd %dma\n",
+			vdda, vddio, vddd);
+
+		return -EINVAL;
+	}
+
+	/* reset value */
+	ana_pwr = snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER);
+	ana_pwr |= SGTL5000_DAC_STEREO |
+			SGTL5000_ADC_STEREO |
+			SGTL5000_REFTOP_POWERUP;
+	lreg_ctrl = snd_soc_read(codec, SGTL5000_CHIP_LINREG_CTRL);
+
+	if (vddio < 3100 && vdda < 3100) {
+		/* enable internal oscillator used for charge pump */
+		snd_soc_update_bits(codec, SGTL5000_CHIP_CLK_TOP_CTRL,
+					SGTL5000_INT_OSC_EN,
+					SGTL5000_INT_OSC_EN);
+		/* Enable VDDC charge pump */
+		ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP;
+	} else if (vddio >= 3100 && vdda >= 3100) {
+		/*
+		 * if vddio and vddd > 3.1v,
+		 * charge pump should be clean before set ana_pwr
+		 */
+		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_VDDC_CHRGPMP_POWERUP, 0);
+
+		/* VDDC use VDDIO rail */
+		lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
+		lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO <<
+			    SGTL5000_VDDC_MAN_ASSN_SHIFT;
+	}
+
+	snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl);
+
+	snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, ana_pwr);
+
+	/* set voltage to register */
+	snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
+				(0x1 << 4) - 1, 0x8);
+
+	/*
+	 * if vddd linear reg has been enabled,
+	 * simple digital supply should be clear to get
+	 * proper VDDD voltage.
+	 */
+	if (ana_pwr & SGTL5000_LINEREG_D_POWERUP)
+		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_LINREG_SIMPLE_POWERUP,
+				0);
+	else
+		snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
+				SGTL5000_LINREG_SIMPLE_POWERUP |
+				SGTL5000_STARTUP_POWERUP,
+				0);
+
+	/*
+	 * set ADC/DAC VAG to vdda / 2,
+	 * should stay in range (0.8v, 1.575v)
+	 */
+	vag = vdda / 2;
+	if (vag <= SGTL5000_ANA_GND_BASE)
+		vag = 0;
+	else if (vag >= SGTL5000_ANA_GND_BASE + SGTL5000_ANA_GND_STP *
+		 (SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT))
+		vag = SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT;
+	else
+		vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
+
+	snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
+			vag << SGTL5000_ANA_GND_SHIFT,
+			vag << SGTL5000_ANA_GND_SHIFT);
+
+	/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
+	vag = vddio / 2;
+	if (vag <= SGTL5000_LINE_OUT_GND_BASE)
+		vag = 0;
+	else if (vag >= SGTL5000_LINE_OUT_GND_BASE +
+		SGTL5000_LINE_OUT_GND_STP * SGTL5000_LINE_OUT_GND_MAX)
+		vag = SGTL5000_LINE_OUT_GND_MAX;
+	else
+		vag = (vag - SGTL5000_LINE_OUT_GND_BASE) /
+		    SGTL5000_LINE_OUT_GND_STP;
+
+	snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
+			vag << SGTL5000_LINE_OUT_GND_SHIFT |
+			SGTL5000_LINE_OUT_CURRENT_360u <<
+				SGTL5000_LINE_OUT_CURRENT_SHIFT,
+			vag << SGTL5000_LINE_OUT_GND_SHIFT |
+			SGTL5000_LINE_OUT_CURRENT_360u <<
+				SGTL5000_LINE_OUT_CURRENT_SHIFT);
+
+	return 0;
+}
+
+static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
+{
+	u16 reg;
+	int ret;
+	int rev;
+	int i;
+	int external_vddd = 0;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+
+	for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++)
+		sgtl5000->supplies[i].supply = supply_names[i];
+
+	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+	if (!ret)
+		external_vddd = 1;
+	else {
+		/* set internal ldo to 1.2v */
+		int voltage = LDO_VOLTAGE;
+
+		ret = ldo_regulator_register(codec, &ldo_init_data, voltage);
+		if (ret) {
+			dev_err(codec->dev,
+			"Failed to register vddd internal supplies: %d\n",
+				ret);
+			return ret;
+		}
+
+		sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
+
+		ret = regulator_bulk_get(codec->dev,
+				ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+
+		if (ret) {
+			ldo_regulator_remove(codec);
+			dev_err(codec->dev,
+				"Failed to request supplies: %d\n", ret);
+
+			return ret;
+		}
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
+					sgtl5000->supplies);
+	if (ret)
+		goto err_regulator_free;
+
+	/* wait for all power rails bring up */
+	udelay(10);
+
+	/* read chip information */
+	reg = snd_soc_read(codec, SGTL5000_CHIP_ID);
+	if (((reg & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
+	    SGTL5000_PARTID_PART_ID) {
+		dev_err(codec->dev,
+			"Device with ID register %x is not a sgtl5000\n", reg);
+		ret = -ENODEV;
+		goto err_regulator_disable;
+	}
+
+	rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
+	dev_info(codec->dev, "sgtl5000 revision %d\n", rev);
+
+	/*
+	 * workaround for revision 0x11 and later,
+	 * roll back to use internal LDO
+	 */
+	if (external_vddd && rev >= 0x11) {
+		int voltage = LDO_VOLTAGE;
+		/* disable all regulator first */
+		regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+					sgtl5000->supplies);
+		/* free VDDD regulator */
+		regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+					sgtl5000->supplies);
+
+		ret = ldo_regulator_register(codec, &ldo_init_data, voltage);
+		if (ret)
+			return ret;
+
+		sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
+
+		ret = regulator_bulk_get(codec->dev,
+				ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+		if (ret) {
+			ldo_regulator_remove(codec);
+			dev_err(codec->dev,
+				"Failed to request supplies: %d\n", ret);
+
+			return ret;
+		}
+
+		ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
+						sgtl5000->supplies);
+		if (ret)
+			goto err_regulator_free;
+
+		/* wait for all power rails bring up */
+		udelay(10);
+	}
+
+	return 0;
+
+err_regulator_disable:
+	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+err_regulator_free:
+	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+	if (external_vddd)
+		ldo_regulator_remove(codec);
+	return ret;
+
+}
+
+static int sgtl5000_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+
+	/* setup i2c data ops */
+	ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+		return ret;
+	}
+
+	ret = sgtl5000_enable_regulators(codec);
+	if (ret)
+		return ret;
+
+	/* power up sgtl5000 */
+	ret = sgtl5000_set_power_regs(codec);
+	if (ret)
+		goto err;
+
+	/* enable small pop, introduce 400ms delay in turning off */
+	snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
+				SGTL5000_SMALL_POP,
+				SGTL5000_SMALL_POP);
+
+	/* disable short cut detector */
+	snd_soc_write(codec, SGTL5000_CHIP_SHORT_CTRL, 0);
+
+	/*
+	 * set i2s as default input of sound switch
+	 * TODO: add sound switch to control and dapm widge.
+	 */
+	snd_soc_write(codec, SGTL5000_CHIP_SSS_CTRL,
+			SGTL5000_DAC_SEL_I2S_IN << SGTL5000_DAC_SEL_SHIFT);
+	snd_soc_write(codec, SGTL5000_CHIP_DIG_POWER,
+			SGTL5000_ADC_EN | SGTL5000_DAC_EN);
+
+	/* enable dac volume ramp by default */
+	snd_soc_write(codec, SGTL5000_CHIP_ADCDAC_CTRL,
+			SGTL5000_DAC_VOL_RAMP_EN |
+			SGTL5000_DAC_MUTE_RIGHT |
+			SGTL5000_DAC_MUTE_LEFT);
+
+	snd_soc_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f);
+
+	snd_soc_write(codec, SGTL5000_CHIP_ANA_CTRL,
+			SGTL5000_HP_ZCD_EN |
+			SGTL5000_ADC_ZCD_EN);
+
+	snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0);
+
+	/*
+	 * disable DAP
+	 * TODO:
+	 * Enable DAP in kcontrol and dapm.
+	 */
+	snd_soc_write(codec, SGTL5000_DAP_CTRL, 0);
+
+	/* leading to standby state */
+	ret = sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	if (ret)
+		goto err;
+
+	snd_soc_add_controls(codec, sgtl5000_snd_controls,
+			     ARRAY_SIZE(sgtl5000_snd_controls));
+
+	snd_soc_dapm_new_controls(&codec->dapm, sgtl5000_dapm_widgets,
+				  ARRAY_SIZE(sgtl5000_dapm_widgets));
+
+	snd_soc_dapm_add_routes(&codec->dapm, audio_map,
+				ARRAY_SIZE(audio_map));
+
+	snd_soc_dapm_new_widgets(&codec->dapm);
+
+	return 0;
+
+err:
+	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+						sgtl5000->supplies);
+	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+	ldo_regulator_remove(codec);
+
+	return ret;
+}
+
+static int sgtl5000_remove(struct snd_soc_codec *codec)
+{
+	struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
+
+	sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+	regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
+						sgtl5000->supplies);
+	regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
+				sgtl5000->supplies);
+	ldo_regulator_remove(codec);
+
+	return 0;
+}
+
+static struct snd_soc_codec_driver sgtl5000_driver = {
+	.probe = sgtl5000_probe,
+	.remove = sgtl5000_remove,
+	.suspend = sgtl5000_suspend,
+	.resume = sgtl5000_resume,
+	.set_bias_level = sgtl5000_set_bias_level,
+	.reg_cache_size = ARRAY_SIZE(sgtl5000_regs),
+	.reg_word_size = sizeof(u16),
+	.reg_cache_step = 2,
+	.reg_cache_default = sgtl5000_regs,
+	.volatile_register = sgtl5000_volatile_register,
+};
+
+static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	struct sgtl5000_priv *sgtl5000;
+	int ret;
+
+	sgtl5000 = kzalloc(sizeof(struct sgtl5000_priv), GFP_KERNEL);
+	if (!sgtl5000)
+		return -ENOMEM;
+
+	/*
+	 * copy DAP default values to default value array.
+	 * sgtl5000 register space has a big hole, merge it
+	 * at init phase makes life easy.
+	 * FIXME: should we drop 'const' of sgtl5000_regs?
+	 */
+	memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)),
+			sgtl5000_dap_regs,
+			SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET);
+
+	i2c_set_clientdata(client, sgtl5000);
+
+	ret = snd_soc_register_codec(&client->dev,
+			&sgtl5000_driver, &sgtl5000_dai, 1);
+	if (ret) {
+		dev_err(&client->dev, "Failed to register codec: %d\n", ret);
+		kfree(sgtl5000);
+		return ret;
+	}
+
+	return 0;
+}
+
+static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
+{
+	struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client);
+
+	snd_soc_unregister_codec(&client->dev);
+
+	kfree(sgtl5000);
+	return 0;
+}
+
+static const struct i2c_device_id sgtl5000_id[] = {
+	{"sgtl5000", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
+
+static struct i2c_driver sgtl5000_i2c_driver = {
+	.driver = {
+		   .name = "sgtl5000",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = sgtl5000_i2c_probe,
+	.remove = __devexit_p(sgtl5000_i2c_remove),
+	.id_table = sgtl5000_id,
+};
+
+static int __init sgtl5000_modinit(void)
+{
+	return i2c_add_driver(&sgtl5000_i2c_driver);
+}
+module_init(sgtl5000_modinit);
+
+static void __exit sgtl5000_exit(void)
+{
+	i2c_del_driver(&sgtl5000_i2c_driver);
+}
+module_exit(sgtl5000_exit);
+
+MODULE_DESCRIPTION("Freescale SGTL5000 ALSA SoC Codec Driver");
+MODULE_AUTHOR("Zeng Zhaoming <zhaoming.zeng@freescale.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
new file mode 100644
index 0000000..eec3ab3
--- /dev/null
+++ b/sound/soc/codecs/sgtl5000.h
@@ -0,0 +1,400 @@
+/*
+ * sgtl5000.h - SGTL5000 audio codec interface
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _SGTL5000_H
+#define _SGTL5000_H
+
+/*
+ * Register values.
+ */
+#define SGTL5000_CHIP_ID			0x0000
+#define SGTL5000_CHIP_DIG_POWER			0x0002
+#define SGTL5000_CHIP_CLK_CTRL			0x0004
+#define SGTL5000_CHIP_I2S_CTRL			0x0006
+#define SGTL5000_CHIP_SSS_CTRL			0x000a
+#define SGTL5000_CHIP_ADCDAC_CTRL		0x000e
+#define SGTL5000_CHIP_DAC_VOL			0x0010
+#define SGTL5000_CHIP_PAD_STRENGTH		0x0014
+#define SGTL5000_CHIP_ANA_ADC_CTRL		0x0020
+#define SGTL5000_CHIP_ANA_HP_CTRL		0x0022
+#define SGTL5000_CHIP_ANA_CTRL			0x0024
+#define SGTL5000_CHIP_LINREG_CTRL		0x0026
+#define SGTL5000_CHIP_REF_CTRL			0x0028
+#define SGTL5000_CHIP_MIC_CTRL			0x002a
+#define SGTL5000_CHIP_LINE_OUT_CTRL		0x002c
+#define SGTL5000_CHIP_LINE_OUT_VOL		0x002e
+#define SGTL5000_CHIP_ANA_POWER			0x0030
+#define SGTL5000_CHIP_PLL_CTRL			0x0032
+#define SGTL5000_CHIP_CLK_TOP_CTRL		0x0034
+#define SGTL5000_CHIP_ANA_STATUS		0x0036
+#define SGTL5000_CHIP_SHORT_CTRL		0x003c
+#define SGTL5000_CHIP_ANA_TEST2			0x003a
+#define SGTL5000_DAP_CTRL			0x0100
+#define SGTL5000_DAP_PEQ			0x0102
+#define SGTL5000_DAP_BASS_ENHANCE		0x0104
+#define SGTL5000_DAP_BASS_ENHANCE_CTRL		0x0106
+#define SGTL5000_DAP_AUDIO_EQ			0x0108
+#define SGTL5000_DAP_SURROUND			0x010a
+#define SGTL5000_DAP_FLT_COEF_ACCESS		0x010c
+#define SGTL5000_DAP_COEF_WR_B0_MSB		0x010e
+#define SGTL5000_DAP_COEF_WR_B0_LSB		0x0110
+#define SGTL5000_DAP_EQ_BASS_BAND0		0x0116
+#define SGTL5000_DAP_EQ_BASS_BAND1		0x0118
+#define SGTL5000_DAP_EQ_BASS_BAND2		0x011a
+#define SGTL5000_DAP_EQ_BASS_BAND3		0x011c
+#define SGTL5000_DAP_EQ_BASS_BAND4		0x011e
+#define SGTL5000_DAP_MAIN_CHAN			0x0120
+#define SGTL5000_DAP_MIX_CHAN			0x0122
+#define SGTL5000_DAP_AVC_CTRL			0x0124
+#define SGTL5000_DAP_AVC_THRESHOLD		0x0126
+#define SGTL5000_DAP_AVC_ATTACK			0x0128
+#define SGTL5000_DAP_AVC_DECAY			0x012a
+#define SGTL5000_DAP_COEF_WR_B1_MSB		0x012c
+#define SGTL5000_DAP_COEF_WR_B1_LSB		0x012e
+#define SGTL5000_DAP_COEF_WR_B2_MSB		0x0130
+#define SGTL5000_DAP_COEF_WR_B2_LSB		0x0132
+#define SGTL5000_DAP_COEF_WR_A1_MSB		0x0134
+#define SGTL5000_DAP_COEF_WR_A1_LSB		0x0136
+#define SGTL5000_DAP_COEF_WR_A2_MSB		0x0138
+#define SGTL5000_DAP_COEF_WR_A2_LSB		0x013a
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * SGTL5000_CHIP_ID
+ */
+#define SGTL5000_PARTID_MASK			0xff00
+#define SGTL5000_PARTID_SHIFT			8
+#define SGTL5000_PARTID_WIDTH			8
+#define SGTL5000_PARTID_PART_ID			0xa0
+#define SGTL5000_REVID_MASK			0x00ff
+#define SGTL5000_REVID_SHIFT			0
+#define SGTL5000_REVID_WIDTH			8
+
+/*
+ * SGTL5000_CHIP_DIG_POWER
+ */
+#define SGTL5000_ADC_EN				0x0040
+#define SGTL5000_DAC_EN				0x0020
+#define SGTL5000_DAP_POWERUP			0x0010
+#define SGTL5000_I2S_OUT_POWERUP		0x0002
+#define SGTL5000_I2S_IN_POWERUP			0x0001
+
+/*
+ * SGTL5000_CHIP_CLK_CTRL
+ */
+#define SGTL5000_RATE_MODE_MASK			0x0030
+#define SGTL5000_RATE_MODE_SHIFT		4
+#define SGTL5000_RATE_MODE_WIDTH		2
+#define SGTL5000_RATE_MODE_DIV_1		0
+#define SGTL5000_RATE_MODE_DIV_2		1
+#define SGTL5000_RATE_MODE_DIV_4		2
+#define SGTL5000_RATE_MODE_DIV_6		3
+#define SGTL5000_SYS_FS_MASK			0x000c
+#define SGTL5000_SYS_FS_SHIFT			2
+#define SGTL5000_SYS_FS_WIDTH			2
+#define SGTL5000_SYS_FS_32k			0x0
+#define SGTL5000_SYS_FS_44_1k			0x1
+#define SGTL5000_SYS_FS_48k			0x2
+#define SGTL5000_SYS_FS_96k			0x3
+#define SGTL5000_MCLK_FREQ_MASK			0x0003
+#define SGTL5000_MCLK_FREQ_SHIFT		0
+#define SGTL5000_MCLK_FREQ_WIDTH		2
+#define SGTL5000_MCLK_FREQ_256FS		0x0
+#define SGTL5000_MCLK_FREQ_384FS		0x1
+#define SGTL5000_MCLK_FREQ_512FS		0x2
+#define SGTL5000_MCLK_FREQ_PLL			0x3
+
+/*
+ * SGTL5000_CHIP_I2S_CTRL
+ */
+#define SGTL5000_I2S_SCLKFREQ_MASK		0x0100
+#define SGTL5000_I2S_SCLKFREQ_SHIFT		8
+#define SGTL5000_I2S_SCLKFREQ_WIDTH		1
+#define SGTL5000_I2S_SCLKFREQ_64FS		0x0
+#define SGTL5000_I2S_SCLKFREQ_32FS		0x1	/* Not for RJ mode */
+#define SGTL5000_I2S_MASTER			0x0080
+#define SGTL5000_I2S_SCLK_INV			0x0040
+#define SGTL5000_I2S_DLEN_MASK			0x0030
+#define SGTL5000_I2S_DLEN_SHIFT			4
+#define SGTL5000_I2S_DLEN_WIDTH			2
+#define SGTL5000_I2S_DLEN_32			0x0
+#define SGTL5000_I2S_DLEN_24			0x1
+#define SGTL5000_I2S_DLEN_20			0x2
+#define SGTL5000_I2S_DLEN_16			0x3
+#define SGTL5000_I2S_MODE_MASK			0x000c
+#define SGTL5000_I2S_MODE_SHIFT			2
+#define SGTL5000_I2S_MODE_WIDTH			2
+#define SGTL5000_I2S_MODE_I2S_LJ		0x0
+#define SGTL5000_I2S_MODE_RJ			0x1
+#define SGTL5000_I2S_MODE_PCM			0x2
+#define SGTL5000_I2S_LRALIGN			0x0002
+#define SGTL5000_I2S_LRPOL			0x0001	/* set for which mode */
+
+/*
+ * SGTL5000_CHIP_SSS_CTRL
+ */
+#define SGTL5000_DAP_MIX_LRSWAP			0x4000
+#define SGTL5000_DAP_LRSWAP			0x2000
+#define SGTL5000_DAC_LRSWAP			0x1000
+#define SGTL5000_I2S_OUT_LRSWAP			0x0400
+#define SGTL5000_DAP_MIX_SEL_MASK		0x0300
+#define SGTL5000_DAP_MIX_SEL_SHIFT		8
+#define SGTL5000_DAP_MIX_SEL_WIDTH		2
+#define SGTL5000_DAP_MIX_SEL_ADC		0x0
+#define SGTL5000_DAP_MIX_SEL_I2S_IN		0x1
+#define SGTL5000_DAP_SEL_MASK			0x00c0
+#define SGTL5000_DAP_SEL_SHIFT			6
+#define SGTL5000_DAP_SEL_WIDTH			2
+#define SGTL5000_DAP_SEL_ADC			0x0
+#define SGTL5000_DAP_SEL_I2S_IN			0x1
+#define SGTL5000_DAC_SEL_MASK			0x0030
+#define SGTL5000_DAC_SEL_SHIFT			4
+#define SGTL5000_DAC_SEL_WIDTH			2
+#define SGTL5000_DAC_SEL_ADC			0x0
+#define SGTL5000_DAC_SEL_I2S_IN			0x1
+#define SGTL5000_DAC_SEL_DAP			0x3
+#define SGTL5000_I2S_OUT_SEL_MASK		0x0003
+#define SGTL5000_I2S_OUT_SEL_SHIFT		0
+#define SGTL5000_I2S_OUT_SEL_WIDTH		2
+#define SGTL5000_I2S_OUT_SEL_ADC		0x0
+#define SGTL5000_I2S_OUT_SEL_I2S_IN		0x1
+#define SGTL5000_I2S_OUT_SEL_DAP		0x3
+
+/*
+ * SGTL5000_CHIP_ADCDAC_CTRL
+ */
+#define SGTL5000_VOL_BUSY_DAC_RIGHT		0x2000
+#define SGTL5000_VOL_BUSY_DAC_LEFT		0x1000
+#define SGTL5000_DAC_VOL_RAMP_EN		0x0200
+#define SGTL5000_DAC_VOL_RAMP_EXPO		0x0100
+#define SGTL5000_DAC_MUTE_RIGHT			0x0008
+#define SGTL5000_DAC_MUTE_LEFT			0x0004
+#define SGTL5000_ADC_HPF_FREEZE			0x0002
+#define SGTL5000_ADC_HPF_BYPASS			0x0001
+
+/*
+ * SGTL5000_CHIP_DAC_VOL
+ */
+#define SGTL5000_DAC_VOL_RIGHT_MASK		0xff00
+#define SGTL5000_DAC_VOL_RIGHT_SHIFT		8
+#define SGTL5000_DAC_VOL_RIGHT_WIDTH		8
+#define SGTL5000_DAC_VOL_LEFT_MASK		0x00ff
+#define SGTL5000_DAC_VOL_LEFT_SHIFT		0
+#define SGTL5000_DAC_VOL_LEFT_WIDTH		8
+
+/*
+ * SGTL5000_CHIP_PAD_STRENGTH
+ */
+#define SGTL5000_PAD_I2S_LRCLK_MASK		0x0300
+#define SGTL5000_PAD_I2S_LRCLK_SHIFT		8
+#define SGTL5000_PAD_I2S_LRCLK_WIDTH		2
+#define SGTL5000_PAD_I2S_SCLK_MASK		0x00c0
+#define SGTL5000_PAD_I2S_SCLK_SHIFT		6
+#define SGTL5000_PAD_I2S_SCLK_WIDTH		2
+#define SGTL5000_PAD_I2S_DOUT_MASK		0x0030
+#define SGTL5000_PAD_I2S_DOUT_SHIFT		4
+#define SGTL5000_PAD_I2S_DOUT_WIDTH		2
+#define SGTL5000_PAD_I2C_SDA_MASK		0x000c
+#define SGTL5000_PAD_I2C_SDA_SHIFT		2
+#define SGTL5000_PAD_I2C_SDA_WIDTH		2
+#define SGTL5000_PAD_I2C_SCL_MASK		0x0003
+#define SGTL5000_PAD_I2C_SCL_SHIFT		0
+#define SGTL5000_PAD_I2C_SCL_WIDTH		2
+
+/*
+ * SGTL5000_CHIP_ANA_ADC_CTRL
+ */
+#define SGTL5000_ADC_VOL_M6DB			0x0100
+#define SGTL5000_ADC_VOL_RIGHT_MASK		0x00f0
+#define SGTL5000_ADC_VOL_RIGHT_SHIFT		4
+#define SGTL5000_ADC_VOL_RIGHT_WIDTH		4
+#define SGTL5000_ADC_VOL_LEFT_MASK		0x000f
+#define SGTL5000_ADC_VOL_LEFT_SHIFT		0
+#define SGTL5000_ADC_VOL_LEFT_WIDTH		4
+
+/*
+ * SGTL5000_CHIP_ANA_HP_CTRL
+ */
+#define SGTL5000_HP_VOL_RIGHT_MASK		0x7f00
+#define SGTL5000_HP_VOL_RIGHT_SHIFT		8
+#define SGTL5000_HP_VOL_RIGHT_WIDTH		7
+#define SGTL5000_HP_VOL_LEFT_MASK		0x007f
+#define SGTL5000_HP_VOL_LEFT_SHIFT		0
+#define SGTL5000_HP_VOL_LEFT_WIDTH		7
+
+/*
+ * SGTL5000_CHIP_ANA_CTRL
+ */
+#define SGTL5000_LINE_OUT_MUTE			0x0100
+#define SGTL5000_HP_SEL_MASK			0x0040
+#define SGTL5000_HP_SEL_SHIFT			6
+#define SGTL5000_HP_SEL_WIDTH			1
+#define SGTL5000_HP_SEL_DAC			0x0
+#define SGTL5000_HP_SEL_LINE_IN			0x1
+#define SGTL5000_HP_ZCD_EN			0x0020
+#define SGTL5000_HP_MUTE			0x0010
+#define SGTL5000_ADC_SEL_MASK			0x0004
+#define SGTL5000_ADC_SEL_SHIFT			2
+#define SGTL5000_ADC_SEL_WIDTH			1
+#define SGTL5000_ADC_SEL_MIC			0x0
+#define SGTL5000_ADC_SEL_LINE_IN		0x1
+#define SGTL5000_ADC_ZCD_EN			0x0002
+#define SGTL5000_ADC_MUTE			0x0001
+
+/*
+ * SGTL5000_CHIP_LINREG_CTRL
+ */
+#define SGTL5000_VDDC_MAN_ASSN_MASK		0x0040
+#define SGTL5000_VDDC_MAN_ASSN_SHIFT		6
+#define SGTL5000_VDDC_MAN_ASSN_WIDTH		1
+#define SGTL5000_VDDC_MAN_ASSN_VDDA		0x0
+#define SGTL5000_VDDC_MAN_ASSN_VDDIO		0x1
+#define SGTL5000_VDDC_ASSN_OVRD			0x0020
+#define SGTL5000_LINREG_VDDD_MASK		0x000f
+#define SGTL5000_LINREG_VDDD_SHIFT		0
+#define SGTL5000_LINREG_VDDD_WIDTH		4
+
+/*
+ * SGTL5000_CHIP_REF_CTRL
+ */
+#define SGTL5000_ANA_GND_MASK			0x01f0
+#define SGTL5000_ANA_GND_SHIFT			4
+#define SGTL5000_ANA_GND_WIDTH			5
+#define SGTL5000_ANA_GND_BASE			800	/* mv */
+#define SGTL5000_ANA_GND_STP			25	/*mv */
+#define SGTL5000_BIAS_CTRL_MASK			0x000e
+#define SGTL5000_BIAS_CTRL_SHIFT		1
+#define SGTL5000_BIAS_CTRL_WIDTH		3
+#define SGTL5000_SMALL_POP			0x0001
+
+/*
+ * SGTL5000_CHIP_MIC_CTRL
+ */
+#define SGTL5000_BIAS_R_MASK			0x0200
+#define SGTL5000_BIAS_R_SHIFT			8
+#define SGTL5000_BIAS_R_WIDTH			2
+#define SGTL5000_BIAS_R_off			0x0
+#define SGTL5000_BIAS_R_2K			0x1
+#define SGTL5000_BIAS_R_4k			0x2
+#define SGTL5000_BIAS_R_8k			0x3
+#define SGTL5000_BIAS_VOLT_MASK			0x0070
+#define SGTL5000_BIAS_VOLT_SHIFT		4
+#define SGTL5000_BIAS_VOLT_WIDTH		3
+#define SGTL5000_MIC_GAIN_MASK			0x0003
+#define SGTL5000_MIC_GAIN_SHIFT			0
+#define SGTL5000_MIC_GAIN_WIDTH			2
+
+/*
+ * SGTL5000_CHIP_LINE_OUT_CTRL
+ */
+#define SGTL5000_LINE_OUT_CURRENT_MASK		0x0f00
+#define SGTL5000_LINE_OUT_CURRENT_SHIFT		8
+#define SGTL5000_LINE_OUT_CURRENT_WIDTH		4
+#define SGTL5000_LINE_OUT_CURRENT_180u		0x0
+#define SGTL5000_LINE_OUT_CURRENT_270u		0x1
+#define SGTL5000_LINE_OUT_CURRENT_360u		0x3
+#define SGTL5000_LINE_OUT_CURRENT_450u		0x7
+#define SGTL5000_LINE_OUT_CURRENT_540u		0xf
+#define SGTL5000_LINE_OUT_GND_MASK		0x003f
+#define SGTL5000_LINE_OUT_GND_SHIFT		0
+#define SGTL5000_LINE_OUT_GND_WIDTH		6
+#define SGTL5000_LINE_OUT_GND_BASE		800	/* mv */
+#define SGTL5000_LINE_OUT_GND_STP		25
+#define SGTL5000_LINE_OUT_GND_MAX		0x23
+
+/*
+ * SGTL5000_CHIP_LINE_OUT_VOL
+ */
+#define SGTL5000_LINE_OUT_VOL_RIGHT_MASK	0x1f00
+#define SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT	8
+#define SGTL5000_LINE_OUT_VOL_RIGHT_WIDTH	5
+#define SGTL5000_LINE_OUT_VOL_LEFT_MASK		0x001f
+#define SGTL5000_LINE_OUT_VOL_LEFT_SHIFT	0
+#define SGTL5000_LINE_OUT_VOL_LEFT_WIDTH	5
+
+/*
+ * SGTL5000_CHIP_ANA_POWER
+ */
+#define SGTL5000_DAC_STEREO			0x4000
+#define SGTL5000_LINREG_SIMPLE_POWERUP		0x2000
+#define SGTL5000_STARTUP_POWERUP		0x1000
+#define SGTL5000_VDDC_CHRGPMP_POWERUP		0x0800
+#define SGTL5000_PLL_POWERUP			0x0400
+#define SGTL5000_LINEREG_D_POWERUP		0x0200
+#define SGTL5000_VCOAMP_POWERUP			0x0100
+#define SGTL5000_VAG_POWERUP			0x0080
+#define SGTL5000_ADC_STEREO			0x0040
+#define SGTL5000_REFTOP_POWERUP			0x0020
+#define SGTL5000_HP_POWERUP			0x0010
+#define SGTL5000_DAC_POWERUP			0x0008
+#define SGTL5000_CAPLESS_HP_POWERUP		0x0004
+#define SGTL5000_ADC_POWERUP			0x0002
+#define SGTL5000_LINE_OUT_POWERUP		0x0001
+
+/*
+ * SGTL5000_CHIP_PLL_CTRL
+ */
+#define SGTL5000_PLL_INT_DIV_MASK		0xf800
+#define SGTL5000_PLL_INT_DIV_SHIFT		11
+#define SGTL5000_PLL_INT_DIV_WIDTH		5
+#define SGTL5000_PLL_FRAC_DIV_MASK		0x0700
+#define SGTL5000_PLL_FRAC_DIV_SHIFT		0
+#define SGTL5000_PLL_FRAC_DIV_WIDTH		11
+
+/*
+ * SGTL5000_CHIP_CLK_TOP_CTRL
+ */
+#define SGTL5000_INT_OSC_EN			0x0800
+#define SGTL5000_INPUT_FREQ_DIV2		0x0008
+
+/*
+ * SGTL5000_CHIP_ANA_STATUS
+ */
+#define SGTL5000_HP_LRSHORT			0x0200
+#define SGTL5000_CAPLESS_SHORT			0x0100
+#define SGTL5000_PLL_LOCKED			0x0010
+
+/*
+ * SGTL5000_CHIP_SHORT_CTRL
+ */
+#define SGTL5000_LVLADJR_MASK			0x7000
+#define SGTL5000_LVLADJR_SHIFT			12
+#define SGTL5000_LVLADJR_WIDTH			3
+#define SGTL5000_LVLADJL_MASK			0x0700
+#define SGTL5000_LVLADJL_SHIFT			8
+#define SGTL5000_LVLADJL_WIDTH			3
+#define SGTL5000_LVLADJC_MASK			0x0070
+#define SGTL5000_LVLADJC_SHIFT			4
+#define SGTL5000_LVLADJC_WIDTH			3
+#define SGTL5000_LR_SHORT_MOD_MASK		0x000c
+#define SGTL5000_LR_SHORT_MOD_SHIFT		2
+#define SGTL5000_LR_SHORT_MOD_WIDTH		2
+#define SGTL5000_CM_SHORT_MOD_MASK		0x0003
+#define SGTL5000_CM_SHORT_MOD_SHIFT		0
+#define SGTL5000_CM_SHORT_MOD_WIDTH		2
+
+/*
+ *SGTL5000_CHIP_ANA_TEST2
+ */
+#define SGTL5000_MONO_DAC			0x1000
+
+/*
+ * SGTL5000_DAP_CTRL
+ */
+#define SGTL5000_DAP_MIX_EN			0x0010
+#define SGTL5000_DAP_EN				0x0001
+
+#define SGTL5000_SYSCLK				0x00
+#define SGTL5000_LRCLK				0x01
+
+#endif
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
new file mode 100644
index 0000000..2a30eae
--- /dev/null
+++ b/sound/soc/codecs/sn95031.c
@@ -0,0 +1,949 @@
+/*
+ *  sn95031.c -  TI sn95031 Codec driver
+ *
+ *  Copyright (C) 2010 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@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; 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <asm/intel_scu_ipc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/jack.h>
+#include "sn95031.h"
+
+#define SN95031_RATES (SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100)
+#define SN95031_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
+
+/* adc helper functions */
+
+/* enables mic bias voltage */
+static void sn95031_enable_mic_bias(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SN95031_VAUD, BIT(2)|BIT(1)|BIT(0));
+	snd_soc_update_bits(codec, SN95031_MICBIAS, BIT(2), BIT(2));
+}
+
+/* Enable/Disable the ADC depending on the argument */
+static void configure_adc(struct snd_soc_codec *sn95031_codec, int val)
+{
+	int value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
+
+	if (val) {
+		/* Enable and start the ADC */
+		value |= (SN95031_ADC_ENBL | SN95031_ADC_START);
+		value &= (~SN95031_ADC_NO_LOOP);
+	} else {
+		/* Just stop the ADC */
+		value &= (~SN95031_ADC_START);
+	}
+	snd_soc_write(sn95031_codec, SN95031_ADC1CNTL1, value);
+}
+
+/*
+ * finds an empty channel for conversion
+ * If the ADC is not enabled then start using 0th channel
+ * itself. Otherwise find an empty channel by looking for a
+ * channel in which the stopbit is set to 1. returns the index
+ * of the first free channel if succeeds or an error code.
+ *
+ * Context: can sleep
+ *
+ */
+static int find_free_channel(struct snd_soc_codec *sn95031_codec)
+{
+	int ret = 0, i, value;
+
+	/* check whether ADC is enabled */
+	value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
+
+	if ((value & SN95031_ADC_ENBL) == 0)
+		return 0;
+
+	/* ADC is already enabled; Looking for an empty channel */
+	for (i = 0; i <	SN95031_ADC_CHANLS_MAX; i++) {
+		value = snd_soc_read(sn95031_codec,
+				SN95031_ADC_CHNL_START_ADDR + i);
+		if (value & SN95031_STOPBIT_MASK) {
+			ret = i;
+			break;
+		}
+	}
+	return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret;
+}
+
+/* Initialize the ADC for reading micbias values. Can sleep. */
+static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
+{
+	int base_addr, chnl_addr;
+	int value;
+	static int channel_index;
+
+	/* Index of the first channel in which the stop bit is set */
+	channel_index = find_free_channel(sn95031_codec);
+	if (channel_index < 0) {
+		pr_err("No free ADC channels");
+		return channel_index;
+	}
+
+	base_addr = SN95031_ADC_CHNL_START_ADDR + channel_index;
+
+	if (!(channel_index == 0 || channel_index ==  SN95031_ADC_LOOP_MAX)) {
+		/* Reset stop bit for channels other than 0 and 12 */
+		value = snd_soc_read(sn95031_codec, base_addr);
+		/* Set the stop bit to zero */
+		snd_soc_write(sn95031_codec, base_addr, value & 0xEF);
+		/* Index of the first free channel */
+		base_addr++;
+		channel_index++;
+	}
+
+	/* Since this is the last channel, set the stop bit
+	   to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
+	snd_soc_write(sn95031_codec, base_addr,
+				SN95031_AUDIO_DETECT_CODE | 0x10);
+
+	chnl_addr = SN95031_ADC_DATA_START_ADDR + 2 * channel_index;
+	pr_debug("mid_initialize : %x", chnl_addr);
+	configure_adc(sn95031_codec, 1);
+	return chnl_addr;
+}
+
+
+/* reads the ADC registers and gets the mic bias value in mV. */
+static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
+{
+	u16 adc_adr = sn95031_initialize_adc(codec);
+	u16 adc_val1, adc_val2;
+	unsigned int mic_bias;
+
+	sn95031_enable_mic_bias(codec);
+
+	/* Enable the sound card for conversion before reading */
+	snd_soc_write(codec, SN95031_ADC1CNTL3, 0x05);
+	/* Re-toggle the RRDATARD bit */
+	snd_soc_write(codec, SN95031_ADC1CNTL3, 0x04);
+
+	/* Read the higher bits of data */
+	msleep(1000);
+	adc_val1 = snd_soc_read(codec, adc_adr);
+	adc_adr++;
+	adc_val2 = snd_soc_read(codec, adc_adr);
+
+	/* Adding lower two bits to the higher bits */
+	mic_bias = (adc_val1 << 2) + (adc_val2 & 3);
+	mic_bias = (mic_bias * SN95031_ADC_ONE_LSB_MULTIPLIER) / 1000;
+	pr_debug("mic bias = %dmV\n", mic_bias);
+	return mic_bias;
+}
+EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
+/*end - adc helper functions */
+
+static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
+			unsigned int reg)
+{
+	u8 value = 0;
+	int ret;
+
+	ret = intel_scu_ipc_ioread8(reg, &value);
+	if (ret)
+		pr_err("read of %x failed, err %d\n", reg, ret);
+	return value;
+
+}
+
+static inline int sn95031_write(struct snd_soc_codec *codec,
+			unsigned int reg, unsigned int value)
+{
+	int ret;
+
+	ret = intel_scu_ipc_iowrite8(reg, value);
+	if (ret)
+		pr_err("write of %x failed, err %d\n", reg, ret);
+	return ret;
+}
+
+static int sn95031_set_vaud_bias(struct snd_soc_codec *codec,
+		enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
+			pr_debug("vaud_bias powering up pll\n");
+			/* power up the pll */
+			snd_soc_write(codec, SN95031_AUDPLLCTRL, BIT(5));
+			/* enable pcm 2 */
+			snd_soc_update_bits(codec, SN95031_PCM2C2,
+					BIT(0), BIT(0));
+		}
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			pr_debug("vaud_bias power up rail\n");
+			/* power up the rail */
+			snd_soc_write(codec, SN95031_VAUD,
+					BIT(2)|BIT(1)|BIT(0));
+			msleep(1);
+		} else if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) {
+			/* turn off pcm */
+			pr_debug("vaud_bias power dn pcm\n");
+			snd_soc_update_bits(codec, SN95031_PCM2C2, BIT(0), 0);
+			snd_soc_write(codec, SN95031_AUDPLLCTRL, 0);
+		}
+		break;
+
+
+	case SND_SOC_BIAS_OFF:
+		pr_debug("vaud_bias _OFF doing rail shutdown\n");
+		snd_soc_write(codec, SN95031_VAUD, BIT(3));
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+static int sn95031_vhs_event(struct snd_soc_dapm_widget *w,
+		    struct snd_kcontrol *kcontrol, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		pr_debug("VHS SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
+		/* power up the rail */
+		snd_soc_write(w->codec, SN95031_VHSP, 0x3D);
+		snd_soc_write(w->codec, SN95031_VHSN, 0x3F);
+		msleep(1);
+	} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		pr_debug("VHS SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
+		snd_soc_write(w->codec, SN95031_VHSP, 0xC4);
+		snd_soc_write(w->codec, SN95031_VHSN, 0x04);
+	}
+	return 0;
+}
+
+static int sn95031_vihf_event(struct snd_soc_dapm_widget *w,
+		    struct snd_kcontrol *kcontrol, int event)
+{
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		pr_debug("VIHF SND_SOC_DAPM_EVENT_ON doing rail startup now\n");
+		/* power up the rail */
+		snd_soc_write(w->codec, SN95031_VIHF, 0x27);
+		msleep(1);
+	} else if (SND_SOC_DAPM_EVENT_OFF(event)) {
+		pr_debug("VIHF SND_SOC_DAPM_EVENT_OFF doing rail shutdown\n");
+		snd_soc_write(w->codec, SN95031_VIHF, 0x24);
+	}
+	return 0;
+}
+
+static int sn95031_dmic12_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *k, int event)
+{
+	unsigned int ldo = 0, clk_dir = 0, data_dir = 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		ldo = BIT(5)|BIT(4);
+		clk_dir = BIT(0);
+		data_dir = BIT(7);
+	}
+	/* program DMIC LDO, clock and set clock */
+	snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
+	snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(0), clk_dir);
+	snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(7), data_dir);
+	return 0;
+}
+
+static int sn95031_dmic34_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *k, int event)
+{
+	unsigned int ldo = 0, clk_dir = 0, data_dir = 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event)) {
+		ldo = BIT(5)|BIT(4);
+		clk_dir = BIT(2);
+		data_dir = BIT(1);
+	}
+	/* program DMIC LDO, clock and set clock */
+	snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(5)|BIT(4), ldo);
+	snd_soc_update_bits(w->codec, SN95031_DMICBUF0123, BIT(2), clk_dir);
+	snd_soc_update_bits(w->codec, SN95031_DMICBUF45, BIT(1), data_dir);
+	return 0;
+}
+
+static int sn95031_dmic56_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *k, int event)
+{
+	unsigned int ldo = 0;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		ldo = BIT(7)|BIT(6);
+
+	/* program DMIC LDO */
+	snd_soc_update_bits(w->codec, SN95031_MICBIAS, BIT(7)|BIT(6), ldo);
+	return 0;
+}
+
+/* mux controls */
+static const char *sn95031_mic_texts[] = { "AMIC", "LineIn" };
+
+static const struct soc_enum sn95031_micl_enum =
+	SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 1, 2, sn95031_mic_texts);
+
+static const struct snd_kcontrol_new sn95031_micl_mux_control =
+	SOC_DAPM_ENUM("Route", sn95031_micl_enum);
+
+static const struct soc_enum sn95031_micr_enum =
+	SOC_ENUM_SINGLE(SN95031_ADCCONFIG, 3, 2, sn95031_mic_texts);
+
+static const struct snd_kcontrol_new sn95031_micr_mux_control =
+	SOC_DAPM_ENUM("Route", sn95031_micr_enum);
+
+static const char *sn95031_input_texts[] = {	"DMIC1", "DMIC2", "DMIC3",
+						"DMIC4", "DMIC5", "DMIC6",
+						"ADC Left", "ADC Right" };
+
+static const struct soc_enum sn95031_input1_enum =
+	SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 0, 8, sn95031_input_texts);
+
+static const struct snd_kcontrol_new sn95031_input1_mux_control =
+	SOC_DAPM_ENUM("Route", sn95031_input1_enum);
+
+static const struct soc_enum sn95031_input2_enum =
+	SOC_ENUM_SINGLE(SN95031_AUDIOMUX12, 4, 8, sn95031_input_texts);
+
+static const struct snd_kcontrol_new sn95031_input2_mux_control =
+	SOC_DAPM_ENUM("Route", sn95031_input2_enum);
+
+static const struct soc_enum sn95031_input3_enum =
+	SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 0, 8, sn95031_input_texts);
+
+static const struct snd_kcontrol_new sn95031_input3_mux_control =
+	SOC_DAPM_ENUM("Route", sn95031_input3_enum);
+
+static const struct soc_enum sn95031_input4_enum =
+	SOC_ENUM_SINGLE(SN95031_AUDIOMUX34, 4, 8, sn95031_input_texts);
+
+static const struct snd_kcontrol_new sn95031_input4_mux_control =
+	SOC_DAPM_ENUM("Route", sn95031_input4_enum);
+
+/* capture path controls */
+
+static const char *sn95031_micmode_text[] = {"Single Ended", "Differential"};
+
+/* 0dB to 30dB in 10dB steps */
+static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 10, 0);
+
+static const struct soc_enum sn95031_micmode1_enum =
+	SOC_ENUM_SINGLE(SN95031_MICAMP1, 1, 2, sn95031_micmode_text);
+static const struct soc_enum sn95031_micmode2_enum =
+	SOC_ENUM_SINGLE(SN95031_MICAMP2, 1, 2, sn95031_micmode_text);
+
+static const char *sn95031_dmic_cfg_text[] = {"GPO", "DMIC"};
+
+static const struct soc_enum sn95031_dmic12_cfg_enum =
+	SOC_ENUM_SINGLE(SN95031_DMICMUX, 0, 2, sn95031_dmic_cfg_text);
+static const struct soc_enum sn95031_dmic34_cfg_enum =
+	SOC_ENUM_SINGLE(SN95031_DMICMUX, 1, 2, sn95031_dmic_cfg_text);
+static const struct soc_enum sn95031_dmic56_cfg_enum =
+	SOC_ENUM_SINGLE(SN95031_DMICMUX, 2, 2, sn95031_dmic_cfg_text);
+
+static const struct snd_kcontrol_new sn95031_snd_controls[] = {
+	SOC_ENUM("Mic1Mode Capture Route", sn95031_micmode1_enum),
+	SOC_ENUM("Mic2Mode Capture Route", sn95031_micmode2_enum),
+	SOC_ENUM("DMIC12 Capture Route", sn95031_dmic12_cfg_enum),
+	SOC_ENUM("DMIC34 Capture Route", sn95031_dmic34_cfg_enum),
+	SOC_ENUM("DMIC56 Capture Route", sn95031_dmic56_cfg_enum),
+	SOC_SINGLE_TLV("Mic1 Capture Volume", SN95031_MICAMP1,
+			2, 4, 0, mic_tlv),
+	SOC_SINGLE_TLV("Mic2 Capture Volume", SN95031_MICAMP2,
+			2, 4, 0, mic_tlv),
+};
+
+/* DAPM widgets */
+static const struct snd_soc_dapm_widget sn95031_dapm_widgets[] = {
+
+	/* all end points mic, hs etc */
+	SND_SOC_DAPM_OUTPUT("HPOUTL"),
+	SND_SOC_DAPM_OUTPUT("HPOUTR"),
+	SND_SOC_DAPM_OUTPUT("EPOUT"),
+	SND_SOC_DAPM_OUTPUT("IHFOUTL"),
+	SND_SOC_DAPM_OUTPUT("IHFOUTR"),
+	SND_SOC_DAPM_OUTPUT("LINEOUTL"),
+	SND_SOC_DAPM_OUTPUT("LINEOUTR"),
+	SND_SOC_DAPM_OUTPUT("VIB1OUT"),
+	SND_SOC_DAPM_OUTPUT("VIB2OUT"),
+
+	SND_SOC_DAPM_INPUT("AMIC1"), /* headset mic */
+	SND_SOC_DAPM_INPUT("AMIC2"),
+	SND_SOC_DAPM_INPUT("DMIC1"),
+	SND_SOC_DAPM_INPUT("DMIC2"),
+	SND_SOC_DAPM_INPUT("DMIC3"),
+	SND_SOC_DAPM_INPUT("DMIC4"),
+	SND_SOC_DAPM_INPUT("DMIC5"),
+	SND_SOC_DAPM_INPUT("DMIC6"),
+	SND_SOC_DAPM_INPUT("LINEINL"),
+	SND_SOC_DAPM_INPUT("LINEINR"),
+
+	SND_SOC_DAPM_MICBIAS("AMIC1Bias", SN95031_MICBIAS, 2, 0),
+	SND_SOC_DAPM_MICBIAS("AMIC2Bias", SN95031_MICBIAS, 3, 0),
+	SND_SOC_DAPM_MICBIAS("DMIC12Bias", SN95031_DMICMUX, 3, 0),
+	SND_SOC_DAPM_MICBIAS("DMIC34Bias", SN95031_DMICMUX, 4, 0),
+	SND_SOC_DAPM_MICBIAS("DMIC56Bias", SN95031_DMICMUX, 5, 0),
+
+	SND_SOC_DAPM_SUPPLY("DMIC12supply", SN95031_DMICLK, 0, 0,
+				sn95031_dmic12_event,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("DMIC34supply", SN95031_DMICLK, 1, 0,
+				sn95031_dmic34_event,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("DMIC56supply", SN95031_DMICLK, 2, 0,
+				sn95031_dmic56_event,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_AIF_OUT("PCM_Out", "Capture", 0,
+			SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_SUPPLY("Headset Rail", SND_SOC_NOPM, 0, 0,
+			sn95031_vhs_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("Speaker Rail", SND_SOC_NOPM, 0, 0,
+			sn95031_vihf_event,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* playback path driver enables */
+	SND_SOC_DAPM_PGA("Headset Left Playback",
+			SN95031_DRIVEREN, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Headset Right Playback",
+			SN95031_DRIVEREN, 1, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Speaker Left Playback",
+			SN95031_DRIVEREN, 2, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Speaker Right Playback",
+			SN95031_DRIVEREN, 3, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Vibra1 Playback",
+			SN95031_DRIVEREN, 4, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Vibra2 Playback",
+			SN95031_DRIVEREN, 5, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Earpiece Playback",
+			SN95031_DRIVEREN, 6, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Lineout Left Playback",
+			SN95031_LOCTL, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Lineout Right Playback",
+			SN95031_LOCTL, 4, 0, NULL, 0),
+
+	/* playback path filter enable */
+	SND_SOC_DAPM_PGA("Headset Left Filter",
+			SN95031_HSEPRXCTRL, 4, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("Headset Right Filter",
+			SN95031_HSEPRXCTRL, 5, 0,  NULL, 0),
+	SND_SOC_DAPM_PGA("Speaker Left Filter",
+			SN95031_IHFRXCTRL, 0, 0,  NULL, 0),
+	SND_SOC_DAPM_PGA("Speaker Right Filter",
+			SN95031_IHFRXCTRL, 1, 0,  NULL, 0),
+
+	/* DACs */
+	SND_SOC_DAPM_DAC("HSDAC Left", "Headset",
+			SN95031_DACCONFIG, 0, 0),
+	SND_SOC_DAPM_DAC("HSDAC Right", "Headset",
+			SN95031_DACCONFIG, 1, 0),
+	SND_SOC_DAPM_DAC("IHFDAC Left", "Speaker",
+			SN95031_DACCONFIG, 2, 0),
+	SND_SOC_DAPM_DAC("IHFDAC Right", "Speaker",
+			SN95031_DACCONFIG, 3, 0),
+	SND_SOC_DAPM_DAC("Vibra1 DAC", "Vibra1",
+			SN95031_VIB1C5, 1, 0),
+	SND_SOC_DAPM_DAC("Vibra2 DAC", "Vibra2",
+			SN95031_VIB2C5, 1, 0),
+
+	/* capture widgets */
+	SND_SOC_DAPM_PGA("LineIn Enable Left", SN95031_MICAMP1,
+				7, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("LineIn Enable Right", SN95031_MICAMP2,
+				7, 0, NULL, 0),
+
+	SND_SOC_DAPM_PGA("MIC1 Enable", SN95031_MICAMP1, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("MIC2 Enable", SN95031_MICAMP2, 0, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TX1 Enable", SN95031_AUDIOTXEN, 2, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TX2 Enable", SN95031_AUDIOTXEN, 3, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TX3 Enable", SN95031_AUDIOTXEN, 4, 0, NULL, 0),
+	SND_SOC_DAPM_PGA("TX4 Enable", SN95031_AUDIOTXEN, 5, 0, NULL, 0),
+
+	/* ADC have null stream as they will be turned ON by TX path */
+	SND_SOC_DAPM_ADC("ADC Left", NULL,
+			SN95031_ADCCONFIG, 0, 0),
+	SND_SOC_DAPM_ADC("ADC Right", NULL,
+			SN95031_ADCCONFIG, 2, 0),
+
+	SND_SOC_DAPM_MUX("Mic_InputL Capture Route",
+			SND_SOC_NOPM, 0, 0, &sn95031_micl_mux_control),
+	SND_SOC_DAPM_MUX("Mic_InputR Capture Route",
+			SND_SOC_NOPM, 0, 0, &sn95031_micr_mux_control),
+
+	SND_SOC_DAPM_MUX("Txpath1 Capture Route",
+			SND_SOC_NOPM, 0, 0, &sn95031_input1_mux_control),
+	SND_SOC_DAPM_MUX("Txpath2 Capture Route",
+			SND_SOC_NOPM, 0, 0, &sn95031_input2_mux_control),
+	SND_SOC_DAPM_MUX("Txpath3 Capture Route",
+			SND_SOC_NOPM, 0, 0, &sn95031_input3_mux_control),
+	SND_SOC_DAPM_MUX("Txpath4 Capture Route",
+			SND_SOC_NOPM, 0, 0, &sn95031_input4_mux_control),
+
+};
+
+static const struct snd_soc_dapm_route sn95031_audio_map[] = {
+	/* headset and earpiece map */
+	{ "HPOUTL", NULL, "Headset Rail"},
+	{ "HPOUTR", NULL, "Headset Rail"},
+	{ "HPOUTL", NULL, "Headset Left Playback" },
+	{ "HPOUTR", NULL, "Headset Right Playback" },
+	{ "EPOUT", NULL, "Earpiece Playback" },
+	{ "Headset Left Playback", NULL, "Headset Left Filter"},
+	{ "Headset Right Playback", NULL, "Headset Right Filter"},
+	{ "Earpiece Playback", NULL, "Headset Left Filter"},
+	{ "Headset Left Filter", NULL, "HSDAC Left"},
+	{ "Headset Right Filter", NULL, "HSDAC Right"},
+
+	/* speaker map */
+	{ "IHFOUTL", NULL, "Speaker Rail"},
+	{ "IHFOUTR", NULL, "Speaker Rail"},
+	{ "IHFOUTL", "NULL", "Speaker Left Playback"},
+	{ "IHFOUTR", "NULL", "Speaker Right Playback"},
+	{ "Speaker Left Playback", NULL, "Speaker Left Filter"},
+	{ "Speaker Right Playback", NULL, "Speaker Right Filter"},
+	{ "Speaker Left Filter", NULL, "IHFDAC Left"},
+	{ "Speaker Right Filter", NULL, "IHFDAC Right"},
+
+	/* vibra map */
+	{ "VIB1OUT", NULL, "Vibra1 Playback"},
+	{ "Vibra1 Playback", NULL, "Vibra1 DAC"},
+
+	{ "VIB2OUT", NULL, "Vibra2 Playback"},
+	{ "Vibra2 Playback", NULL, "Vibra2 DAC"},
+
+	/* lineout */
+	{ "LINEOUTL", NULL, "Lineout Left Playback"},
+	{ "LINEOUTR", NULL, "Lineout Right Playback"},
+	{ "Lineout Left Playback", NULL, "Headset Left Filter"},
+	{ "Lineout Left Playback", NULL, "Speaker Left Filter"},
+	{ "Lineout Left Playback", NULL, "Vibra1 DAC"},
+	{ "Lineout Right Playback", NULL, "Headset Right Filter"},
+	{ "Lineout Right Playback", NULL, "Speaker Right Filter"},
+	{ "Lineout Right Playback", NULL, "Vibra2 DAC"},
+
+	/* Headset (AMIC1) mic */
+	{ "AMIC1Bias", NULL, "AMIC1"},
+	{ "MIC1 Enable", NULL, "AMIC1Bias"},
+	{ "Mic_InputL Capture Route", "AMIC", "MIC1 Enable"},
+
+	/* AMIC2 */
+	{ "AMIC2Bias", NULL, "AMIC2"},
+	{ "MIC2 Enable", NULL, "AMIC2Bias"},
+	{ "Mic_InputR Capture Route", "AMIC", "MIC2 Enable"},
+
+
+	/* Linein */
+	{ "LineIn Enable Left", NULL, "LINEINL"},
+	{ "LineIn Enable Right", NULL, "LINEINR"},
+	{ "Mic_InputL Capture Route", "LineIn", "LineIn Enable Left"},
+	{ "Mic_InputR Capture Route", "LineIn", "LineIn Enable Right"},
+
+	/* ADC connection */
+	{ "ADC Left", NULL, "Mic_InputL Capture Route"},
+	{ "ADC Right", NULL, "Mic_InputR Capture Route"},
+
+	/*DMIC connections */
+	{ "DMIC1", NULL, "DMIC12supply"},
+	{ "DMIC2", NULL, "DMIC12supply"},
+	{ "DMIC3", NULL, "DMIC34supply"},
+	{ "DMIC4", NULL, "DMIC34supply"},
+	{ "DMIC5", NULL, "DMIC56supply"},
+	{ "DMIC6", NULL, "DMIC56supply"},
+
+	{ "DMIC12Bias", NULL, "DMIC1"},
+	{ "DMIC12Bias", NULL, "DMIC2"},
+	{ "DMIC34Bias", NULL, "DMIC3"},
+	{ "DMIC34Bias", NULL, "DMIC4"},
+	{ "DMIC56Bias", NULL, "DMIC5"},
+	{ "DMIC56Bias", NULL, "DMIC6"},
+
+	/*TX path inputs*/
+	{ "Txpath1 Capture Route", "ADC Left", "ADC Left"},
+	{ "Txpath2 Capture Route", "ADC Left", "ADC Left"},
+	{ "Txpath3 Capture Route", "ADC Left", "ADC Left"},
+	{ "Txpath4 Capture Route", "ADC Left", "ADC Left"},
+	{ "Txpath1 Capture Route", "ADC Right", "ADC Right"},
+	{ "Txpath2 Capture Route", "ADC Right", "ADC Right"},
+	{ "Txpath3 Capture Route", "ADC Right", "ADC Right"},
+	{ "Txpath4 Capture Route", "ADC Right", "ADC Right"},
+	{ "Txpath1 Capture Route", "DMIC1", "DMIC1"},
+	{ "Txpath2 Capture Route", "DMIC1", "DMIC1"},
+	{ "Txpath3 Capture Route", "DMIC1", "DMIC1"},
+	{ "Txpath4 Capture Route", "DMIC1", "DMIC1"},
+	{ "Txpath1 Capture Route", "DMIC2", "DMIC2"},
+	{ "Txpath2 Capture Route", "DMIC2", "DMIC2"},
+	{ "Txpath3 Capture Route", "DMIC2", "DMIC2"},
+	{ "Txpath4 Capture Route", "DMIC2", "DMIC2"},
+	{ "Txpath1 Capture Route", "DMIC3", "DMIC3"},
+	{ "Txpath2 Capture Route", "DMIC3", "DMIC3"},
+	{ "Txpath3 Capture Route", "DMIC3", "DMIC3"},
+	{ "Txpath4 Capture Route", "DMIC3", "DMIC3"},
+	{ "Txpath1 Capture Route", "DMIC4", "DMIC4"},
+	{ "Txpath2 Capture Route", "DMIC4", "DMIC4"},
+	{ "Txpath3 Capture Route", "DMIC4", "DMIC4"},
+	{ "Txpath4 Capture Route", "DMIC4", "DMIC4"},
+	{ "Txpath1 Capture Route", "DMIC5", "DMIC5"},
+	{ "Txpath2 Capture Route", "DMIC5", "DMIC5"},
+	{ "Txpath3 Capture Route", "DMIC5", "DMIC5"},
+	{ "Txpath4 Capture Route", "DMIC5", "DMIC5"},
+	{ "Txpath1 Capture Route", "DMIC6", "DMIC6"},
+	{ "Txpath2 Capture Route", "DMIC6", "DMIC6"},
+	{ "Txpath3 Capture Route", "DMIC6", "DMIC6"},
+	{ "Txpath4 Capture Route", "DMIC6", "DMIC6"},
+
+	/* tx path */
+	{ "TX1 Enable", NULL, "Txpath1 Capture Route"},
+	{ "TX2 Enable", NULL, "Txpath2 Capture Route"},
+	{ "TX3 Enable", NULL, "Txpath3 Capture Route"},
+	{ "TX4 Enable", NULL, "Txpath4 Capture Route"},
+	{ "PCM_Out", NULL, "TX1 Enable"},
+	{ "PCM_Out", NULL, "TX2 Enable"},
+	{ "PCM_Out", NULL, "TX3 Enable"},
+	{ "PCM_Out", NULL, "TX4 Enable"},
+
+};
+
+/* speaker and headset mutes, for audio pops and clicks */
+static int sn95031_pcm_hs_mute(struct snd_soc_dai *dai, int mute)
+{
+	snd_soc_update_bits(dai->codec,
+			SN95031_HSLVOLCTRL, BIT(7), (!mute << 7));
+	snd_soc_update_bits(dai->codec,
+			SN95031_HSRVOLCTRL, BIT(7), (!mute << 7));
+	return 0;
+}
+
+static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute)
+{
+	snd_soc_update_bits(dai->codec,
+			SN95031_IHFLVOLCTRL, BIT(7), (!mute << 7));
+	snd_soc_update_bits(dai->codec,
+			SN95031_IHFRVOLCTRL, BIT(7), (!mute << 7));
+	return 0;
+}
+
+int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	unsigned int format, rate;
+
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		format = BIT(4)|BIT(5);
+		break;
+
+	case SNDRV_PCM_FORMAT_S24_LE:
+		format = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	snd_soc_update_bits(dai->codec, SN95031_PCM2C2,
+			BIT(4)|BIT(5), format);
+
+	switch (params_rate(params)) {
+	case 48000:
+		pr_debug("RATE_48000\n");
+		rate = 0;
+		break;
+
+	case 44100:
+		pr_debug("RATE_44100\n");
+		rate = BIT(7);
+		break;
+
+	default:
+		pr_err("ERR rate %d\n", params_rate(params));
+		return -EINVAL;
+	}
+	snd_soc_update_bits(dai->codec, SN95031_PCM1C1, BIT(7), rate);
+
+	return 0;
+}
+
+/* Codec DAI section */
+static struct snd_soc_dai_ops sn95031_headset_dai_ops = {
+	.digital_mute	= sn95031_pcm_hs_mute,
+	.hw_params	= sn95031_pcm_hw_params,
+};
+
+static struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
+	.digital_mute	= sn95031_pcm_spkr_mute,
+	.hw_params	= sn95031_pcm_hw_params,
+};
+
+static struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
+	.hw_params	= sn95031_pcm_hw_params,
+};
+
+static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
+	.hw_params	= sn95031_pcm_hw_params,
+};
+
+struct snd_soc_dai_driver sn95031_dais[] = {
+{
+	.name = "SN95031 Headset",
+	.playback = {
+		.stream_name = "Headset",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SN95031_RATES,
+		.formats = SN95031_FORMATS,
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 5,
+		.rates = SN95031_RATES,
+		.formats = SN95031_FORMATS,
+	},
+	.ops = &sn95031_headset_dai_ops,
+},
+{	.name = "SN95031 Speaker",
+	.playback = {
+		.stream_name = "Speaker",
+		.channels_min = 2,
+		.channels_max = 2,
+		.rates = SN95031_RATES,
+		.formats = SN95031_FORMATS,
+	},
+	.ops = &sn95031_speaker_dai_ops,
+},
+{	.name = "SN95031 Vibra1",
+	.playback = {
+		.stream_name = "Vibra1",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SN95031_RATES,
+		.formats = SN95031_FORMATS,
+	},
+	.ops = &sn95031_vib1_dai_ops,
+},
+{	.name = "SN95031 Vibra2",
+	.playback = {
+		.stream_name = "Vibra2",
+		.channels_min = 1,
+		.channels_max = 1,
+		.rates = SN95031_RATES,
+		.formats = SN95031_FORMATS,
+	},
+	.ops = &sn95031_vib2_dai_ops,
+},
+};
+
+static inline void sn95031_disable_jack_btn(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SN95031_BTNCTRL2, 0x00);
+}
+
+static inline void sn95031_enable_jack_btn(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, SN95031_BTNCTRL1, 0x77);
+	snd_soc_write(codec, SN95031_BTNCTRL2, 0x01);
+}
+
+static int sn95031_get_headset_state(struct snd_soc_jack *mfld_jack)
+{
+	int micbias = sn95031_get_mic_bias(mfld_jack->codec);
+
+	int jack_type = snd_soc_jack_get_type(mfld_jack, micbias);
+
+	pr_debug("jack type detected = %d\n", jack_type);
+	if (jack_type == SND_JACK_HEADSET)
+		sn95031_enable_jack_btn(mfld_jack->codec);
+	return jack_type;
+}
+
+void sn95031_jack_detection(struct mfld_jack_data *jack_data)
+{
+	unsigned int status;
+	unsigned int mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_HEADSET;
+
+	pr_debug("interrupt id read in sram = 0x%x\n", jack_data->intr_id);
+	if (jack_data->intr_id & 0x1) {
+		pr_debug("short_push detected\n");
+		status = SND_JACK_HEADSET | SND_JACK_BTN_0;
+	} else if (jack_data->intr_id & 0x2) {
+		pr_debug("long_push detected\n");
+		status = SND_JACK_HEADSET | SND_JACK_BTN_1;
+	} else if (jack_data->intr_id & 0x4) {
+		pr_debug("headset or headphones inserted\n");
+		status = sn95031_get_headset_state(jack_data->mfld_jack);
+	} else if (jack_data->intr_id & 0x8) {
+		pr_debug("headset or headphones removed\n");
+		status = 0;
+		sn95031_disable_jack_btn(jack_data->mfld_jack->codec);
+	} else {
+		pr_err("unidentified interrupt\n");
+		return;
+	}
+
+	snd_soc_jack_report(jack_data->mfld_jack, status, mask);
+	/*button pressed and released so we send explicit button release */
+	if ((status & SND_JACK_BTN_0) | (status & SND_JACK_BTN_1))
+		snd_soc_jack_report(jack_data->mfld_jack,
+				SND_JACK_HEADSET, mask);
+}
+EXPORT_SYMBOL_GPL(sn95031_jack_detection);
+
+/* codec registration */
+static int sn95031_codec_probe(struct snd_soc_codec *codec)
+{
+	int ret;
+
+	pr_debug("codec_probe called\n");
+
+	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+	codec->dapm.idle_bias_off = 1;
+
+	/* PCM interface config
+	 * This sets the pcm rx slot conguration to max 6 slots
+	 * for max 4 dais (2 stereo and 2 mono)
+	 */
+	snd_soc_write(codec, SN95031_PCM2RXSLOT01, 0x10);
+	snd_soc_write(codec, SN95031_PCM2RXSLOT23, 0x32);
+	snd_soc_write(codec, SN95031_PCM2RXSLOT45, 0x54);
+	snd_soc_write(codec, SN95031_PCM2TXSLOT01, 0x10);
+	snd_soc_write(codec, SN95031_PCM2TXSLOT23, 0x32);
+	/* pcm port setting
+	 * This sets the pcm port to slave and clock at 19.2Mhz which
+	 * can support 6slots, sampling rate set per stream in hw-params
+	 */
+	snd_soc_write(codec, SN95031_PCM1C1, 0x00);
+	snd_soc_write(codec, SN95031_PCM2C1, 0x01);
+	snd_soc_write(codec, SN95031_PCM2C2, 0x0A);
+	snd_soc_write(codec, SN95031_HSMIXER, BIT(0)|BIT(4));
+	/* vendor vibra workround, the vibras are muted by
+	 * custom register so unmute them
+	 */
+	snd_soc_write(codec, SN95031_SSR5, 0x80);
+	snd_soc_write(codec, SN95031_SSR6, 0x80);
+	snd_soc_write(codec, SN95031_VIB1C5, 0x00);
+	snd_soc_write(codec, SN95031_VIB2C5, 0x00);
+	/* configure vibras for pcm port */
+	snd_soc_write(codec, SN95031_VIB1C3, 0x00);
+	snd_soc_write(codec, SN95031_VIB2C3, 0x00);
+
+	/* soft mute ramp time */
+	snd_soc_write(codec, SN95031_SOFTMUTE, 0x3);
+	/* fix the initial volume at 1dB,
+	 * default in +9dB,
+	 * 1dB give optimal swing on DAC, amps
+	 */
+	snd_soc_write(codec, SN95031_HSLVOLCTRL, 0x08);
+	snd_soc_write(codec, SN95031_HSRVOLCTRL, 0x08);
+	snd_soc_write(codec, SN95031_IHFLVOLCTRL, 0x08);
+	snd_soc_write(codec, SN95031_IHFRVOLCTRL, 0x08);
+	/* dac mode and lineout workaround */
+	snd_soc_write(codec, SN95031_SSR2, 0x10);
+	snd_soc_write(codec, SN95031_SSR3, 0x40);
+
+	snd_soc_add_controls(codec, sn95031_snd_controls,
+			     ARRAY_SIZE(sn95031_snd_controls));
+
+	ret = snd_soc_dapm_new_controls(&codec->dapm, sn95031_dapm_widgets,
+				ARRAY_SIZE(sn95031_dapm_widgets));
+	if (ret)
+		pr_err("soc_dapm_new_control failed %d", ret);
+	ret = snd_soc_dapm_add_routes(&codec->dapm, sn95031_audio_map,
+				ARRAY_SIZE(sn95031_audio_map));
+	if (ret)
+		pr_err("soc_dapm_add_routes failed %d", ret);
+
+	return ret;
+}
+
+static int sn95031_codec_remove(struct snd_soc_codec *codec)
+{
+	pr_debug("codec_remove called\n");
+	sn95031_set_vaud_bias(codec, SND_SOC_BIAS_OFF);
+
+	return 0;
+}
+
+struct snd_soc_codec_driver sn95031_codec = {
+	.probe		= sn95031_codec_probe,
+	.remove		= sn95031_codec_remove,
+	.read		= sn95031_read,
+	.write		= sn95031_write,
+	.set_bias_level	= sn95031_set_vaud_bias,
+};
+
+static int __devinit sn95031_device_probe(struct platform_device *pdev)
+{
+	pr_debug("codec device probe called for %s\n", dev_name(&pdev->dev));
+	return snd_soc_register_codec(&pdev->dev, &sn95031_codec,
+			sn95031_dais, ARRAY_SIZE(sn95031_dais));
+}
+
+static int __devexit sn95031_device_remove(struct platform_device *pdev)
+{
+	pr_debug("codec device remove called\n");
+	snd_soc_unregister_codec(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver sn95031_codec_driver = {
+	.driver		= {
+		.name		= "sn95031",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= sn95031_device_probe,
+	.remove		= sn95031_device_remove,
+};
+
+static int __init sn95031_init(void)
+{
+	pr_debug("driver init called\n");
+	return platform_driver_register(&sn95031_codec_driver);
+}
+module_init(sn95031_init);
+
+static void __exit sn95031_exit(void)
+{
+	pr_debug("driver exit called\n");
+	platform_driver_unregister(&sn95031_codec_driver);
+}
+module_exit(sn95031_exit);
+
+MODULE_DESCRIPTION("ASoC TI SN95031 codec driver");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sn95031");
diff --git a/sound/soc/codecs/sn95031.h b/sound/soc/codecs/sn95031.h
new file mode 100644
index 0000000..20376d2
--- /dev/null
+++ b/sound/soc/codecs/sn95031.h
@@ -0,0 +1,132 @@
+/*
+ *  sn95031.h - TI sn95031 Codec driver
+ *
+ *  Copyright (C) 2010 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@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; 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 _SN95031_H
+#define _SN95031_H
+
+/*register map*/
+#define SN95031_VAUD			0xDB
+#define SN95031_VHSP			0xDC
+#define SN95031_VHSN			0xDD
+#define SN95031_VIHF			0xC9
+
+#define SN95031_AUDPLLCTRL		0x240
+#define SN95031_DMICBUF0123		0x241
+#define SN95031_DMICBUF45		0x242
+#define SN95031_DMICGPO			0x244
+#define SN95031_DMICMUX			0x245
+#define SN95031_DMICLK			0x246
+#define SN95031_MICBIAS			0x247
+#define SN95031_ADCCONFIG		0x248
+#define SN95031_MICAMP1			0x249
+#define SN95031_MICAMP2			0x24A
+#define SN95031_NOISEMUX		0x24B
+#define SN95031_AUDIOMUX12		0x24C
+#define SN95031_AUDIOMUX34		0x24D
+#define SN95031_AUDIOSINC		0x24E
+#define SN95031_AUDIOTXEN		0x24F
+#define SN95031_HSEPRXCTRL		0x250
+#define SN95031_IHFRXCTRL		0x251
+#define SN95031_HSMIXER			0x256
+#define SN95031_DACCONFIG		0x257
+#define SN95031_SOFTMUTE		0x258
+#define SN95031_HSLVOLCTRL		0x259
+#define SN95031_HSRVOLCTRL		0x25A
+#define SN95031_IHFLVOLCTRL		0x25B
+#define SN95031_IHFRVOLCTRL		0x25C
+#define SN95031_DRIVEREN		0x25D
+#define SN95031_LOCTL			0x25E
+#define SN95031_VIB1C1			0x25F
+#define SN95031_VIB1C2			0x260
+#define SN95031_VIB1C3			0x261
+#define SN95031_VIB1SPIPCM1		0x262
+#define SN95031_VIB1SPIPCM2		0x263
+#define SN95031_VIB1C5			0x264
+#define SN95031_VIB2C1			0x265
+#define SN95031_VIB2C2			0x266
+#define SN95031_VIB2C3			0x267
+#define SN95031_VIB2SPIPCM1		0x268
+#define SN95031_VIB2SPIPCM2		0x269
+#define SN95031_VIB2C5			0x26A
+#define SN95031_BTNCTRL1		0x26B
+#define SN95031_BTNCTRL2		0x26C
+#define SN95031_PCM1TXSLOT01		0x26D
+#define SN95031_PCM1TXSLOT23		0x26E
+#define SN95031_PCM1TXSLOT45		0x26F
+#define SN95031_PCM1RXSLOT0_3		0x270
+#define SN95031_PCM1RXSLOT45		0x271
+#define SN95031_PCM2TXSLOT01		0x272
+#define SN95031_PCM2TXSLOT23		0x273
+#define SN95031_PCM2TXSLOT45		0x274
+#define SN95031_PCM2RXSLOT01		0x275
+#define SN95031_PCM2RXSLOT23		0x276
+#define SN95031_PCM2RXSLOT45		0x277
+#define SN95031_PCM1C1			0x278
+#define SN95031_PCM1C2			0x279
+#define SN95031_PCM1C3			0x27A
+#define SN95031_PCM2C1			0x27B
+#define SN95031_PCM2C2			0x27C
+/*end codec register defn*/
+
+/*vendor defn these are not part of avp*/
+#define SN95031_SSR2			0x381
+#define SN95031_SSR3			0x382
+#define SN95031_SSR5			0x384
+#define SN95031_SSR6			0x385
+
+/* ADC registers */
+
+#define SN95031_ADC1CNTL1 0x1C0
+#define SN95031_ADC_ENBL 0x10
+#define SN95031_ADC_START 0x08
+#define SN95031_ADC1CNTL3 0x1C2
+#define SN95031_ADCTHERM_ENBL 0x04
+#define SN95031_ADCRRDATA_ENBL 0x05
+#define SN95031_STOPBIT_MASK 16
+#define SN95031_ADCTHERM_MASK 4
+#define SN95031_ADC_CHANLS_MAX 15 /* Number of ADC channels */
+#define SN95031_ADC_LOOP_MAX (SN95031_ADC_CHANLS_MAX - 1)
+#define SN95031_ADC_NO_LOOP 0x07
+#define SN95031_AUDIO_GPIO_CTRL 0x070
+
+/* ADC channel code values */
+#define SN95031_AUDIO_DETECT_CODE 0x06
+
+/* ADC base addresses */
+#define SN95031_ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
+#define SN95031_ADC_DATA_START_ADDR 0x1D4  /* increments by 2 */
+/* multipier to convert to mV */
+#define SN95031_ADC_ONE_LSB_MULTIPLIER 2346
+
+
+struct mfld_jack_data {
+	int intr_id;
+	int micbias_vol;
+	struct snd_soc_jack *mfld_jack;
+};
+
+extern void sn95031_jack_detection(struct mfld_jack_data *jack_data);
+
+#endif
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
new file mode 100644
index 0000000..e93b9d1
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -0,0 +1,794 @@
+/*
+ * linux/sound/soc/codecs/tlv320aic32x4.c
+ *
+ * Copyright 2011 Vista Silicon S.L.
+ *
+ * Author: Javier Martin <javier.martin@vista-silicon.com>
+ *
+ * Based on sound/soc/codecs/wm8974 and TI driver for kernel 2.6.27.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+
+#include <sound/tlv320aic32x4.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "tlv320aic32x4.h"
+
+struct aic32x4_rate_divs {
+	u32 mclk;
+	u32 rate;
+	u8 p_val;
+	u8 pll_j;
+	u16 pll_d;
+	u16 dosr;
+	u8 ndac;
+	u8 mdac;
+	u8 aosr;
+	u8 nadc;
+	u8 madc;
+	u8 blck_N;
+};
+
+struct aic32x4_priv {
+	u32 sysclk;
+	s32 master;
+	u8 page_no;
+	void *control_data;
+	u32 power_cfg;
+	u32 micpga_routing;
+	bool swapdacs;
+};
+
+/* 0dB min, 1dB steps */
+static DECLARE_TLV_DB_SCALE(tlv_step_1, 0, 100, 0);
+/* 0dB min, 0.5dB steps */
+static DECLARE_TLV_DB_SCALE(tlv_step_0_5, 0, 50, 0);
+
+static const struct snd_kcontrol_new aic32x4_snd_controls[] = {
+	SOC_DOUBLE_R_TLV("PCM Playback Volume", AIC32X4_LDACVOL,
+			AIC32X4_RDACVOL, 0, 0x30, 0, tlv_step_0_5),
+	SOC_DOUBLE_R_TLV("HP Driver Gain Volume", AIC32X4_HPLGAIN,
+			AIC32X4_HPRGAIN, 0, 0x1D, 0, tlv_step_1),
+	SOC_DOUBLE_R_TLV("LO Driver Gain Volume", AIC32X4_LOLGAIN,
+			AIC32X4_LORGAIN, 0, 0x1D, 0, tlv_step_1),
+	SOC_DOUBLE_R("HP DAC Playback Switch", AIC32X4_HPLGAIN,
+			AIC32X4_HPRGAIN, 6, 0x01, 1),
+	SOC_DOUBLE_R("LO DAC Playback Switch", AIC32X4_LOLGAIN,
+			AIC32X4_LORGAIN, 6, 0x01, 1),
+	SOC_DOUBLE_R("Mic PGA Switch", AIC32X4_LMICPGAVOL,
+			AIC32X4_RMICPGAVOL, 7, 0x01, 1),
+
+	SOC_SINGLE("ADCFGA Left Mute Switch", AIC32X4_ADCFGA, 7, 1, 0),
+	SOC_SINGLE("ADCFGA Right Mute Switch", AIC32X4_ADCFGA, 3, 1, 0),
+
+	SOC_DOUBLE_R_TLV("ADC Level Volume", AIC32X4_LADCVOL,
+			AIC32X4_RADCVOL, 0, 0x28, 0, tlv_step_0_5),
+	SOC_DOUBLE_R_TLV("PGA Level Volume", AIC32X4_LMICPGAVOL,
+			AIC32X4_RMICPGAVOL, 0, 0x5f, 0, tlv_step_0_5),
+
+	SOC_SINGLE("Auto-mute Switch", AIC32X4_DACMUTE, 4, 7, 0),
+
+	SOC_SINGLE("AGC Left Switch", AIC32X4_LAGC1, 7, 1, 0),
+	SOC_SINGLE("AGC Right Switch", AIC32X4_RAGC1, 7, 1, 0),
+	SOC_DOUBLE_R("AGC Target Level", AIC32X4_LAGC1, AIC32X4_RAGC1,
+			4, 0x07, 0),
+	SOC_DOUBLE_R("AGC Gain Hysteresis", AIC32X4_LAGC1, AIC32X4_RAGC1,
+			0, 0x03, 0),
+	SOC_DOUBLE_R("AGC Hysteresis", AIC32X4_LAGC2, AIC32X4_RAGC2,
+			6, 0x03, 0),
+	SOC_DOUBLE_R("AGC Noise Threshold", AIC32X4_LAGC2, AIC32X4_RAGC2,
+			1, 0x1F, 0),
+	SOC_DOUBLE_R("AGC Max PGA", AIC32X4_LAGC3, AIC32X4_RAGC3,
+			0, 0x7F, 0),
+	SOC_DOUBLE_R("AGC Attack Time", AIC32X4_LAGC4, AIC32X4_RAGC4,
+			3, 0x1F, 0),
+	SOC_DOUBLE_R("AGC Decay Time", AIC32X4_LAGC5, AIC32X4_RAGC5,
+			3, 0x1F, 0),
+	SOC_DOUBLE_R("AGC Noise Debounce", AIC32X4_LAGC6, AIC32X4_RAGC6,
+			0, 0x1F, 0),
+	SOC_DOUBLE_R("AGC Signal Debounce", AIC32X4_LAGC7, AIC32X4_RAGC7,
+			0, 0x0F, 0),
+};
+
+static const struct aic32x4_rate_divs aic32x4_divs[] = {
+	/* 8k rate */
+	{AIC32X4_FREQ_12000000, 8000, 1, 7, 6800, 768, 5, 3, 128, 5, 18, 24},
+	{AIC32X4_FREQ_24000000, 8000, 2, 7, 6800, 768, 15, 1, 64, 45, 4, 24},
+	{AIC32X4_FREQ_25000000, 8000, 2, 7, 3728, 768, 15, 1, 64, 45, 4, 24},
+	/* 11.025k rate */
+	{AIC32X4_FREQ_12000000, 11025, 1, 7, 5264, 512, 8, 2, 128, 8, 8, 16},
+	{AIC32X4_FREQ_24000000, 11025, 2, 7, 5264, 512, 16, 1, 64, 32, 4, 16},
+	/* 16k rate */
+	{AIC32X4_FREQ_12000000, 16000, 1, 7, 6800, 384, 5, 3, 128, 5, 9, 12},
+	{AIC32X4_FREQ_24000000, 16000, 2, 7, 6800, 384, 15, 1, 64, 18, 5, 12},
+	{AIC32X4_FREQ_25000000, 16000, 2, 7, 3728, 384, 15, 1, 64, 18, 5, 12},
+	/* 22.05k rate */
+	{AIC32X4_FREQ_12000000, 22050, 1, 7, 5264, 256, 4, 4, 128, 4, 8, 8},
+	{AIC32X4_FREQ_24000000, 22050, 2, 7, 5264, 256, 16, 1, 64, 16, 4, 8},
+	{AIC32X4_FREQ_25000000, 22050, 2, 7, 2253, 256, 16, 1, 64, 16, 4, 8},
+	/* 32k rate */
+	{AIC32X4_FREQ_12000000, 32000, 1, 7, 1680, 192, 2, 7, 64, 2, 21, 6},
+	{AIC32X4_FREQ_24000000, 32000, 2, 7, 1680, 192, 7, 2, 64, 7, 6, 6},
+	/* 44.1k rate */
+	{AIC32X4_FREQ_12000000, 44100, 1, 7, 5264, 128, 2, 8, 128, 2, 8, 4},
+	{AIC32X4_FREQ_24000000, 44100, 2, 7, 5264, 128, 8, 2, 64, 8, 4, 4},
+	{AIC32X4_FREQ_25000000, 44100, 2, 7, 2253, 128, 8, 2, 64, 8, 4, 4},
+	/* 48k rate */
+	{AIC32X4_FREQ_12000000, 48000, 1, 8, 1920, 128, 2, 8, 128, 2, 8, 4},
+	{AIC32X4_FREQ_24000000, 48000, 2, 8, 1920, 128, 8, 2, 64, 8, 4, 4},
+	{AIC32X4_FREQ_25000000, 48000, 2, 7, 8643, 128, 8, 2, 64, 8, 4, 4}
+};
+
+static const struct snd_kcontrol_new hpl_output_mixer_controls[] = {
+	SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_HPLROUTE, 3, 1, 0),
+	SOC_DAPM_SINGLE("IN1_L Switch", AIC32X4_HPLROUTE, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new hpr_output_mixer_controls[] = {
+	SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_HPRROUTE, 3, 1, 0),
+	SOC_DAPM_SINGLE("IN1_R Switch", AIC32X4_HPRROUTE, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new lol_output_mixer_controls[] = {
+	SOC_DAPM_SINGLE("L_DAC Switch", AIC32X4_LOLROUTE, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new lor_output_mixer_controls[] = {
+	SOC_DAPM_SINGLE("R_DAC Switch", AIC32X4_LORROUTE, 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new left_input_mixer_controls[] = {
+	SOC_DAPM_SINGLE("IN1_L P Switch", AIC32X4_LMICPGAPIN, 6, 1, 0),
+	SOC_DAPM_SINGLE("IN2_L P Switch", AIC32X4_LMICPGAPIN, 4, 1, 0),
+	SOC_DAPM_SINGLE("IN3_L P Switch", AIC32X4_LMICPGAPIN, 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new right_input_mixer_controls[] = {
+	SOC_DAPM_SINGLE("IN1_R P Switch", AIC32X4_RMICPGAPIN, 6, 1, 0),
+	SOC_DAPM_SINGLE("IN2_R P Switch", AIC32X4_RMICPGAPIN, 4, 1, 0),
+	SOC_DAPM_SINGLE("IN3_R P Switch", AIC32X4_RMICPGAPIN, 2, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
+	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", AIC32X4_DACSETUP, 7, 0),
+	SND_SOC_DAPM_MIXER("HPL Output Mixer", SND_SOC_NOPM, 0, 0,
+			   &hpl_output_mixer_controls[0],
+			   ARRAY_SIZE(hpl_output_mixer_controls)),
+	SND_SOC_DAPM_PGA("HPL Power", AIC32X4_OUTPWRCTL, 5, 0, NULL, 0),
+
+	SND_SOC_DAPM_MIXER("LOL Output Mixer", SND_SOC_NOPM, 0, 0,
+			   &lol_output_mixer_controls[0],
+			   ARRAY_SIZE(lol_output_mixer_controls)),
+	SND_SOC_DAPM_PGA("LOL Power", AIC32X4_OUTPWRCTL, 3, 0, NULL, 0),
+
+	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", AIC32X4_DACSETUP, 6, 0),
+	SND_SOC_DAPM_MIXER("HPR Output Mixer", SND_SOC_NOPM, 0, 0,
+			   &hpr_output_mixer_controls[0],
+			   ARRAY_SIZE(hpr_output_mixer_controls)),
+	SND_SOC_DAPM_PGA("HPR Power", AIC32X4_OUTPWRCTL, 4, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("LOR Output Mixer", SND_SOC_NOPM, 0, 0,
+			   &lor_output_mixer_controls[0],
+			   ARRAY_SIZE(lor_output_mixer_controls)),
+	SND_SOC_DAPM_PGA("LOR Power", AIC32X4_OUTPWRCTL, 2, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("Left Input Mixer", SND_SOC_NOPM, 0, 0,
+			   &left_input_mixer_controls[0],
+			   ARRAY_SIZE(left_input_mixer_controls)),
+	SND_SOC_DAPM_MIXER("Right Input Mixer", SND_SOC_NOPM, 0, 0,
+			   &right_input_mixer_controls[0],
+			   ARRAY_SIZE(right_input_mixer_controls)),
+	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", AIC32X4_ADCSETUP, 7, 0),
+	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", AIC32X4_ADCSETUP, 6, 0),
+	SND_SOC_DAPM_MICBIAS("Mic Bias", AIC32X4_MICBIAS, 6, 0),
+
+	SND_SOC_DAPM_OUTPUT("HPL"),
+	SND_SOC_DAPM_OUTPUT("HPR"),
+	SND_SOC_DAPM_OUTPUT("LOL"),
+	SND_SOC_DAPM_OUTPUT("LOR"),
+	SND_SOC_DAPM_INPUT("IN1_L"),
+	SND_SOC_DAPM_INPUT("IN1_R"),
+	SND_SOC_DAPM_INPUT("IN2_L"),
+	SND_SOC_DAPM_INPUT("IN2_R"),
+	SND_SOC_DAPM_INPUT("IN3_L"),
+	SND_SOC_DAPM_INPUT("IN3_R"),
+};
+
+static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
+	/* Left Output */
+	{"HPL Output Mixer", "L_DAC Switch", "Left DAC"},
+	{"HPL Output Mixer", "IN1_L Switch", "IN1_L"},
+
+	{"HPL Power", NULL, "HPL Output Mixer"},
+	{"HPL", NULL, "HPL Power"},
+
+	{"LOL Output Mixer", "L_DAC Switch", "Left DAC"},
+
+	{"LOL Power", NULL, "LOL Output Mixer"},
+	{"LOL", NULL, "LOL Power"},
+
+	/* Right Output */
+	{"HPR Output Mixer", "R_DAC Switch", "Right DAC"},
+	{"HPR Output Mixer", "IN1_R Switch", "IN1_R"},
+
+	{"HPR Power", NULL, "HPR Output Mixer"},
+	{"HPR", NULL, "HPR Power"},
+
+	{"LOR Output Mixer", "R_DAC Switch", "Right DAC"},
+
+	{"LOR Power", NULL, "LOR Output Mixer"},
+	{"LOR", NULL, "LOR Power"},
+
+	/* Left input */
+	{"Left Input Mixer", "IN1_L P Switch", "IN1_L"},
+	{"Left Input Mixer", "IN2_L P Switch", "IN2_L"},
+	{"Left Input Mixer", "IN3_L P Switch", "IN3_L"},
+
+	{"Left ADC", NULL, "Left Input Mixer"},
+
+	/* Right Input */
+	{"Right Input Mixer", "IN1_R P Switch", "IN1_R"},
+	{"Right Input Mixer", "IN2_R P Switch", "IN2_R"},
+	{"Right Input Mixer", "IN3_R P Switch", "IN3_R"},
+
+	{"Right ADC", NULL, "Right Input Mixer"},
+};
+
+static inline int aic32x4_change_page(struct snd_soc_codec *codec,
+					unsigned int new_page)
+{
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	u8 data[2];
+	int ret;
+
+	data[0] = 0x00;
+	data[1] = new_page & 0xff;
+
+	ret = codec->hw_write(codec->control_data, data, 2);
+	if (ret == 2) {
+		aic32x4->page_no = new_page;
+		return 0;
+	} else {
+		return ret;
+	}
+}
+
+static int aic32x4_write(struct snd_soc_codec *codec, unsigned int reg,
+				unsigned int val)
+{
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	unsigned int page = reg / 128;
+	unsigned int fixed_reg = reg % 128;
+	u8 data[2];
+	int ret;
+
+	/* A write to AIC32X4_PSEL is really a non-explicit page change */
+	if (reg == AIC32X4_PSEL)
+		return aic32x4_change_page(codec, val);
+
+	if (aic32x4->page_no != page) {
+		ret = aic32x4_change_page(codec, page);
+		if (ret != 0)
+			return ret;
+	}
+
+	data[0] = fixed_reg & 0xff;
+	data[1] = val & 0xff;
+
+	if (codec->hw_write(codec->control_data, data, 2) == 2)
+		return 0;
+	else
+		return -EIO;
+}
+
+static unsigned int aic32x4_read(struct snd_soc_codec *codec, unsigned int reg)
+{
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	unsigned int page = reg / 128;
+	unsigned int fixed_reg = reg % 128;
+	int ret;
+
+	if (aic32x4->page_no != page) {
+		ret = aic32x4_change_page(codec, page);
+		if (ret != 0)
+			return ret;
+	}
+	return i2c_smbus_read_byte_data(codec->control_data, fixed_reg & 0xff);
+}
+
+static inline int aic32x4_get_divs(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(aic32x4_divs); i++) {
+		if ((aic32x4_divs[i].rate == rate)
+		    && (aic32x4_divs[i].mclk == mclk)) {
+			return i;
+		}
+	}
+	printk(KERN_ERR "aic32x4: master clock and sample rate is not supported\n");
+	return -EINVAL;
+}
+
+static int aic32x4_add_widgets(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_new_controls(&codec->dapm, aic32x4_dapm_widgets,
+				  ARRAY_SIZE(aic32x4_dapm_widgets));
+
+	snd_soc_dapm_add_routes(&codec->dapm, aic32x4_dapm_routes,
+				ARRAY_SIZE(aic32x4_dapm_routes));
+
+	snd_soc_dapm_new_widgets(&codec->dapm);
+	return 0;
+}
+
+static int aic32x4_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 aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+
+	switch (freq) {
+	case AIC32X4_FREQ_12000000:
+	case AIC32X4_FREQ_24000000:
+	case AIC32X4_FREQ_25000000:
+		aic32x4->sysclk = freq;
+		return 0;
+	}
+	printk(KERN_ERR "aic32x4: invalid frequency to set DAI system clock\n");
+	return -EINVAL;
+}
+
+static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	u8 iface_reg_1;
+	u8 iface_reg_2;
+	u8 iface_reg_3;
+
+	iface_reg_1 = snd_soc_read(codec, AIC32X4_IFACE1);
+	iface_reg_1 = iface_reg_1 & ~(3 << 6 | 3 << 2);
+	iface_reg_2 = snd_soc_read(codec, AIC32X4_IFACE2);
+	iface_reg_2 = 0;
+	iface_reg_3 = snd_soc_read(codec, AIC32X4_IFACE3);
+	iface_reg_3 = iface_reg_3 & ~(1 << 3);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		aic32x4->master = 1;
+		iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		aic32x4->master = 0;
+		break;
+	default:
+		printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
+		return -EINVAL;
+	}
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		iface_reg_1 |= (AIC32X4_DSP_MODE << AIC32X4_PLLJ_SHIFT);
+		iface_reg_3 |= (1 << 3); /* invert bit clock */
+		iface_reg_2 = 0x01; /* add offset 1 */
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		iface_reg_1 |= (AIC32X4_DSP_MODE << AIC32X4_PLLJ_SHIFT);
+		iface_reg_3 |= (1 << 3); /* invert bit clock */
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		iface_reg_1 |=
+			(AIC32X4_RIGHT_JUSTIFIED_MODE << AIC32X4_PLLJ_SHIFT);
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface_reg_1 |=
+			(AIC32X4_LEFT_JUSTIFIED_MODE << AIC32X4_PLLJ_SHIFT);
+		break;
+	default:
+		printk(KERN_ERR "aic32x4: invalid DAI interface format\n");
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, AIC32X4_IFACE1, iface_reg_1);
+	snd_soc_write(codec, AIC32X4_IFACE2, iface_reg_2);
+	snd_soc_write(codec, AIC32X4_IFACE3, iface_reg_3);
+	return 0;
+}
+
+static int aic32x4_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 aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	u8 data;
+	int i;
+
+	i = aic32x4_get_divs(aic32x4->sysclk, params_rate(params));
+	if (i < 0) {
+		printk(KERN_ERR "aic32x4: sampling rate not supported\n");
+		return i;
+	}
+
+	/* Use PLL as CODEC_CLKIN and DAC_MOD_CLK as BDIV_CLKIN */
+	snd_soc_write(codec, AIC32X4_CLKMUX, AIC32X4_PLLCLKIN);
+	snd_soc_write(codec, AIC32X4_IFACE3, AIC32X4_DACMOD2BCLK);
+
+	/* We will fix R value to 1 and will make P & J=K.D as varialble */
+	data = snd_soc_read(codec, AIC32X4_PLLPR);
+	data &= ~(7 << 4);
+	snd_soc_write(codec, AIC32X4_PLLPR,
+		      (data | (aic32x4_divs[i].p_val << 4) | 0x01));
+
+	snd_soc_write(codec, AIC32X4_PLLJ, aic32x4_divs[i].pll_j);
+
+	snd_soc_write(codec, AIC32X4_PLLDMSB, (aic32x4_divs[i].pll_d >> 8));
+	snd_soc_write(codec, AIC32X4_PLLDLSB,
+		      (aic32x4_divs[i].pll_d & 0xff));
+
+	/* NDAC divider value */
+	data = snd_soc_read(codec, AIC32X4_NDAC);
+	data &= ~(0x7f);
+	snd_soc_write(codec, AIC32X4_NDAC, data | aic32x4_divs[i].ndac);
+
+	/* MDAC divider value */
+	data = snd_soc_read(codec, AIC32X4_MDAC);
+	data &= ~(0x7f);
+	snd_soc_write(codec, AIC32X4_MDAC, data | aic32x4_divs[i].mdac);
+
+	/* DOSR MSB & LSB values */
+	snd_soc_write(codec, AIC32X4_DOSRMSB, aic32x4_divs[i].dosr >> 8);
+	snd_soc_write(codec, AIC32X4_DOSRLSB,
+		      (aic32x4_divs[i].dosr & 0xff));
+
+	/* NADC divider value */
+	data = snd_soc_read(codec, AIC32X4_NADC);
+	data &= ~(0x7f);
+	snd_soc_write(codec, AIC32X4_NADC, data | aic32x4_divs[i].nadc);
+
+	/* MADC divider value */
+	data = snd_soc_read(codec, AIC32X4_MADC);
+	data &= ~(0x7f);
+	snd_soc_write(codec, AIC32X4_MADC, data | aic32x4_divs[i].madc);
+
+	/* AOSR value */
+	snd_soc_write(codec, AIC32X4_AOSR, aic32x4_divs[i].aosr);
+
+	/* BCLK N divider */
+	data = snd_soc_read(codec, AIC32X4_BCLKN);
+	data &= ~(0x7f);
+	snd_soc_write(codec, AIC32X4_BCLKN, data | aic32x4_divs[i].blck_N);
+
+	data = snd_soc_read(codec, AIC32X4_IFACE1);
+	data = data & ~(3 << 4);
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		data |= (AIC32X4_WORD_LEN_20BITS << AIC32X4_DOSRMSB_SHIFT);
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		data |= (AIC32X4_WORD_LEN_24BITS << AIC32X4_DOSRMSB_SHIFT);
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		data |= (AIC32X4_WORD_LEN_32BITS << AIC32X4_DOSRMSB_SHIFT);
+		break;
+	}
+	snd_soc_write(codec, AIC32X4_IFACE1, data);
+
+	return 0;
+}
+
+static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u8 dac_reg;
+
+	dac_reg = snd_soc_read(codec, AIC32X4_DACMUTE) & ~AIC32X4_MUTEON;
+	if (mute)
+		snd_soc_write(codec, AIC32X4_DACMUTE, dac_reg | AIC32X4_MUTEON);
+	else
+		snd_soc_write(codec, AIC32X4_DACMUTE, dac_reg);
+	return 0;
+}
+
+static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
+				  enum snd_soc_bias_level level)
+{
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	u8 value;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		if (aic32x4->master) {
+			/* Switch on PLL */
+			value = snd_soc_read(codec, AIC32X4_PLLPR);
+			snd_soc_write(codec, AIC32X4_PLLPR,
+				      (value | AIC32X4_PLLEN));
+
+			/* Switch on NDAC Divider */
+			value = snd_soc_read(codec, AIC32X4_NDAC);
+			snd_soc_write(codec, AIC32X4_NDAC,
+				      value | AIC32X4_NDACEN);
+
+			/* Switch on MDAC Divider */
+			value = snd_soc_read(codec, AIC32X4_MDAC);
+			snd_soc_write(codec, AIC32X4_MDAC,
+				      value | AIC32X4_MDACEN);
+
+			/* Switch on NADC Divider */
+			value = snd_soc_read(codec, AIC32X4_NADC);
+			snd_soc_write(codec, AIC32X4_NADC,
+				      value | AIC32X4_MDACEN);
+
+			/* Switch on MADC Divider */
+			value = snd_soc_read(codec, AIC32X4_MADC);
+			snd_soc_write(codec, AIC32X4_MADC,
+				      value | AIC32X4_MDACEN);
+
+			/* Switch on BCLK_N Divider */
+			value = snd_soc_read(codec, AIC32X4_BCLKN);
+			snd_soc_write(codec, AIC32X4_BCLKN,
+				      value | AIC32X4_BCLKEN);
+		}
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		if (aic32x4->master) {
+			/* Switch off PLL */
+			value = snd_soc_read(codec, AIC32X4_PLLPR);
+			snd_soc_write(codec, AIC32X4_PLLPR,
+				      (value & ~AIC32X4_PLLEN));
+
+			/* Switch off NDAC Divider */
+			value = snd_soc_read(codec, AIC32X4_NDAC);
+			snd_soc_write(codec, AIC32X4_NDAC,
+				      value & ~AIC32X4_NDACEN);
+
+			/* Switch off MDAC Divider */
+			value = snd_soc_read(codec, AIC32X4_MDAC);
+			snd_soc_write(codec, AIC32X4_MDAC,
+				      value & ~AIC32X4_MDACEN);
+
+			/* Switch off NADC Divider */
+			value = snd_soc_read(codec, AIC32X4_NADC);
+			snd_soc_write(codec, AIC32X4_NADC,
+				      value & ~AIC32X4_NDACEN);
+
+			/* Switch off MADC Divider */
+			value = snd_soc_read(codec, AIC32X4_MADC);
+			snd_soc_write(codec, AIC32X4_MADC,
+				      value & ~AIC32X4_MDACEN);
+			value = snd_soc_read(codec, AIC32X4_BCLKN);
+
+			/* Switch off BCLK_N Divider */
+			snd_soc_write(codec, AIC32X4_BCLKN,
+				      value & ~AIC32X4_BCLKEN);
+		}
+		break;
+	case SND_SOC_BIAS_OFF:
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#define AIC32X4_RATES	SNDRV_PCM_RATE_8000_48000
+#define AIC32X4_FORMATS	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
+			 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_ops aic32x4_ops = {
+	.hw_params = aic32x4_hw_params,
+	.digital_mute = aic32x4_mute,
+	.set_fmt = aic32x4_set_dai_fmt,
+	.set_sysclk = aic32x4_set_dai_sysclk,
+};
+
+static struct snd_soc_dai_driver aic32x4_dai = {
+	.name = "tlv320aic32x4-hifi",
+	.playback = {
+		     .stream_name = "Playback",
+		     .channels_min = 1,
+		     .channels_max = 2,
+		     .rates = AIC32X4_RATES,
+		     .formats = AIC32X4_FORMATS,},
+	.capture = {
+		    .stream_name = "Capture",
+		    .channels_min = 1,
+		    .channels_max = 2,
+		    .rates = AIC32X4_RATES,
+		    .formats = AIC32X4_FORMATS,},
+	.ops = &aic32x4_ops,
+	.symmetric_rates = 1,
+};
+
+static int aic32x4_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int aic32x4_resume(struct snd_soc_codec *codec)
+{
+	aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+
+static int aic32x4_probe(struct snd_soc_codec *codec)
+{
+	struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
+	u32 tmp_reg;
+
+	codec->hw_write = (hw_write_t) i2c_master_send;
+	codec->control_data = aic32x4->control_data;
+
+	snd_soc_write(codec, AIC32X4_RESET, 0x01);
+
+	/* Power platform configuration */
+	if (aic32x4->power_cfg & AIC32X4_PWR_MICBIAS_2075_LDOIN) {
+		snd_soc_write(codec, AIC32X4_MICBIAS, AIC32X4_MICBIAS_LDOIN |
+						      AIC32X4_MICBIAS_2075V);
+	}
+	if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
+		snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
+	}
+	if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
+		snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN);
+	}
+	tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
+	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
+		tmp_reg |= AIC32X4_LDOIN_18_36;
+	}
+	if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_HP_LDOIN_POWERED) {
+		tmp_reg |= AIC32X4_LDOIN2HP;
+	}
+	snd_soc_write(codec, AIC32X4_CMMODE, tmp_reg);
+
+	/* Do DACs need to be swapped? */
+	if (aic32x4->swapdacs) {
+		snd_soc_write(codec, AIC32X4_DACSETUP, AIC32X4_LDAC2RCHN | AIC32X4_RDAC2LCHN);
+	} else {
+		snd_soc_write(codec, AIC32X4_DACSETUP, AIC32X4_LDAC2LCHN | AIC32X4_RDAC2RCHN);
+	}
+
+	/* Mic PGA routing */
+	if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
+		snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
+	}
+	if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
+		snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
+	}
+
+	aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	snd_soc_add_controls(codec, aic32x4_snd_controls,
+			     ARRAY_SIZE(aic32x4_snd_controls));
+	aic32x4_add_widgets(codec);
+
+	return 0;
+}
+
+static int aic32x4_remove(struct snd_soc_codec *codec)
+{
+	aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_aic32x4 = {
+	.read = aic32x4_read,
+	.write = aic32x4_write,
+	.probe = aic32x4_probe,
+	.remove = aic32x4_remove,
+	.suspend = aic32x4_suspend,
+	.resume = aic32x4_resume,
+	.set_bias_level = aic32x4_set_bias_level,
+};
+
+static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct aic32x4_pdata *pdata = i2c->dev.platform_data;
+	struct aic32x4_priv *aic32x4;
+	int ret;
+
+	aic32x4 = kzalloc(sizeof(struct aic32x4_priv), GFP_KERNEL);
+	if (aic32x4 == NULL)
+		return -ENOMEM;
+
+	aic32x4->control_data = i2c;
+	i2c_set_clientdata(i2c, aic32x4);
+
+	if (pdata) {
+		aic32x4->power_cfg = pdata->power_cfg;
+		aic32x4->swapdacs = pdata->swapdacs;
+		aic32x4->micpga_routing = pdata->micpga_routing;
+	} else {
+		aic32x4->power_cfg = 0;
+		aic32x4->swapdacs = false;
+		aic32x4->micpga_routing = 0;
+	}
+
+	ret = snd_soc_register_codec(&i2c->dev,
+			&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
+	if (ret < 0)
+		kfree(aic32x4);
+	return ret;
+}
+
+static __devexit int aic32x4_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id aic32x4_i2c_id[] = {
+	{ "tlv320aic32x4", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
+
+static struct i2c_driver aic32x4_i2c_driver = {
+	.driver = {
+		.name = "tlv320aic32x4",
+		.owner = THIS_MODULE,
+	},
+	.probe =    aic32x4_i2c_probe,
+	.remove =   __devexit_p(aic32x4_i2c_remove),
+	.id_table = aic32x4_i2c_id,
+};
+
+static int __init aic32x4_modinit(void)
+{
+	int ret = 0;
+
+	ret = i2c_add_driver(&aic32x4_i2c_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n",
+		       ret);
+	}
+	return ret;
+}
+module_init(aic32x4_modinit);
+
+static void __exit aic32x4_exit(void)
+{
+	i2c_del_driver(&aic32x4_i2c_driver);
+}
+module_exit(aic32x4_exit);
+
+MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver");
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h
new file mode 100644
index 0000000..aae2b24
--- /dev/null
+++ b/sound/soc/codecs/tlv320aic32x4.h
@@ -0,0 +1,143 @@
+/*
+ * tlv320aic32x4.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#ifndef _TLV320AIC32X4_H
+#define _TLV320AIC32X4_H
+
+/* tlv320aic32x4 register space (in decimal to match datasheet) */
+
+#define AIC32X4_PAGE1		128
+
+#define	AIC32X4_PSEL		0
+#define	AIC32X4_RESET		1
+#define	AIC32X4_CLKMUX		4
+#define	AIC32X4_PLLPR		5
+#define	AIC32X4_PLLJ		6
+#define	AIC32X4_PLLDMSB		7
+#define	AIC32X4_PLLDLSB		8
+#define	AIC32X4_NDAC		11
+#define	AIC32X4_MDAC		12
+#define AIC32X4_DOSRMSB		13
+#define AIC32X4_DOSRLSB		14
+#define	AIC32X4_NADC		18
+#define	AIC32X4_MADC		19
+#define AIC32X4_AOSR		20
+#define AIC32X4_CLKMUX2		25
+#define AIC32X4_CLKOUTM		26
+#define AIC32X4_IFACE1		27
+#define AIC32X4_IFACE2		28
+#define AIC32X4_IFACE3		29
+#define AIC32X4_BCLKN		30
+#define AIC32X4_IFACE4		31
+#define AIC32X4_IFACE5		32
+#define AIC32X4_IFACE6		33
+#define AIC32X4_DOUTCTL		53
+#define AIC32X4_DINCTL		54
+#define AIC32X4_DACSPB		60
+#define AIC32X4_ADCSPB		61
+#define AIC32X4_DACSETUP	63
+#define AIC32X4_DACMUTE		64
+#define AIC32X4_LDACVOL		65
+#define AIC32X4_RDACVOL		66
+#define AIC32X4_ADCSETUP	81
+#define	AIC32X4_ADCFGA		82
+#define AIC32X4_LADCVOL		83
+#define AIC32X4_RADCVOL		84
+#define AIC32X4_LAGC1		86
+#define AIC32X4_LAGC2		87
+#define AIC32X4_LAGC3		88
+#define AIC32X4_LAGC4		89
+#define AIC32X4_LAGC5		90
+#define AIC32X4_LAGC6		91
+#define AIC32X4_LAGC7		92
+#define AIC32X4_RAGC1		94
+#define AIC32X4_RAGC2		95
+#define AIC32X4_RAGC3		96
+#define AIC32X4_RAGC4		97
+#define AIC32X4_RAGC5		98
+#define AIC32X4_RAGC6		99
+#define AIC32X4_RAGC7		100
+#define AIC32X4_PWRCFG		(AIC32X4_PAGE1 + 1)
+#define AIC32X4_LDOCTL		(AIC32X4_PAGE1 + 2)
+#define AIC32X4_OUTPWRCTL	(AIC32X4_PAGE1 + 9)
+#define AIC32X4_CMMODE		(AIC32X4_PAGE1 + 10)
+#define AIC32X4_HPLROUTE	(AIC32X4_PAGE1 + 12)
+#define AIC32X4_HPRROUTE	(AIC32X4_PAGE1 + 13)
+#define AIC32X4_LOLROUTE	(AIC32X4_PAGE1 + 14)
+#define AIC32X4_LORROUTE	(AIC32X4_PAGE1 + 15)
+#define	AIC32X4_HPLGAIN		(AIC32X4_PAGE1 + 16)
+#define	AIC32X4_HPRGAIN		(AIC32X4_PAGE1 + 17)
+#define	AIC32X4_LOLGAIN		(AIC32X4_PAGE1 + 18)
+#define	AIC32X4_LORGAIN		(AIC32X4_PAGE1 + 19)
+#define AIC32X4_HEADSTART	(AIC32X4_PAGE1 + 20)
+#define AIC32X4_MICBIAS		(AIC32X4_PAGE1 + 51)
+#define AIC32X4_LMICPGAPIN	(AIC32X4_PAGE1 + 52)
+#define AIC32X4_LMICPGANIN	(AIC32X4_PAGE1 + 54)
+#define AIC32X4_RMICPGAPIN	(AIC32X4_PAGE1 + 55)
+#define AIC32X4_RMICPGANIN	(AIC32X4_PAGE1 + 57)
+#define AIC32X4_FLOATINGINPUT	(AIC32X4_PAGE1 + 58)
+#define AIC32X4_LMICPGAVOL	(AIC32X4_PAGE1 + 59)
+#define AIC32X4_RMICPGAVOL	(AIC32X4_PAGE1 + 60)
+
+#define AIC32X4_FREQ_12000000 12000000
+#define AIC32X4_FREQ_24000000 24000000
+#define AIC32X4_FREQ_25000000 25000000
+
+#define AIC32X4_WORD_LEN_16BITS		0x00
+#define AIC32X4_WORD_LEN_20BITS		0x01
+#define AIC32X4_WORD_LEN_24BITS		0x02
+#define AIC32X4_WORD_LEN_32BITS		0x03
+
+#define AIC32X4_I2S_MODE		0x00
+#define AIC32X4_DSP_MODE		0x01
+#define AIC32X4_RIGHT_JUSTIFIED_MODE	0x02
+#define AIC32X4_LEFT_JUSTIFIED_MODE	0x03
+
+#define AIC32X4_AVDDWEAKDISABLE		0x08
+#define AIC32X4_LDOCTLEN		0x01
+
+#define AIC32X4_LDOIN_18_36		0x01
+#define AIC32X4_LDOIN2HP		0x02
+
+#define AIC32X4_DACSPBLOCK_MASK		0x1f
+#define AIC32X4_ADCSPBLOCK_MASK		0x1f
+
+#define AIC32X4_PLLJ_SHIFT		6
+#define AIC32X4_DOSRMSB_SHIFT		4
+
+#define AIC32X4_PLLCLKIN		0x03
+
+#define AIC32X4_MICBIAS_LDOIN		0x08
+#define AIC32X4_MICBIAS_2075V		0x60
+
+#define AIC32X4_LMICPGANIN_IN2R_10K	0x10
+#define AIC32X4_RMICPGANIN_IN1L_10K	0x10
+
+#define AIC32X4_LMICPGAVOL_NOGAIN	0x80
+#define AIC32X4_RMICPGAVOL_NOGAIN	0x80
+
+#define AIC32X4_BCLKMASTER		0x08
+#define AIC32X4_WCLKMASTER		0x04
+#define AIC32X4_PLLEN			(0x01 << 7)
+#define AIC32X4_NDACEN			(0x01 << 7)
+#define AIC32X4_MDACEN			(0x01 << 7)
+#define AIC32X4_NADCEN			(0x01 << 7)
+#define AIC32X4_MADCEN			(0x01 << 7)
+#define AIC32X4_BCLKEN			(0x01 << 7)
+#define AIC32X4_DACEN			(0x03 << 6)
+#define AIC32X4_RDAC2LCHN		(0x02 << 2)
+#define AIC32X4_LDAC2RCHN		(0x02 << 4)
+#define AIC32X4_LDAC2LCHN		(0x01 << 4)
+#define AIC32X4_RDAC2RCHN		(0x01 << 2)
+
+#define AIC32X4_SSTEP2WCLK		0x01
+#define AIC32X4_MUTEON			0x0C
+#define	AIC32X4_DACMOD2BCLK		0x01
+
+#endif				/* _TLV320AIC32X4_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 71d7be8..00b6d87 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -1615,6 +1615,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {
 	},
 	{ },
 };
+MODULE_DEVICE_TABLE(i2c, tlv320dac33_i2c_id);
 
 static struct i2c_driver tlv320dac33_i2c_driver = {
 	.driver = {
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 4bbf1b1..482fcdb 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -724,8 +724,8 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
-void twl6040_hs_jack_report(struct snd_soc_codec *codec,
-				struct snd_soc_jack *jack, int report)
+static void twl6040_hs_jack_report(struct snd_soc_codec *codec,
+				   struct snd_soc_jack *jack, int report)
 {
 	struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
 	int status;
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index e76847a..48ffd40 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -486,7 +486,8 @@ static struct snd_soc_dai_driver uda134x_dai = {
 static int uda134x_soc_probe(struct snd_soc_codec *codec)
 {
 	struct uda134x_priv *uda134x;
-	struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev);
+	struct uda134x_platform_data *pd = codec->card->dev->platform_data;
+
 	int ret;
 
 	printk(KERN_INFO "UDA134X SoC Audio Codec\n");
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 80ddf4f..a3b9cbb 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -836,24 +836,25 @@ static void wm2000_i2c_shutdown(struct i2c_client *i2c)
 }
 
 #ifdef CONFIG_PM
-static int wm2000_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg)
+static int wm2000_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *i2c = to_i2c_client(dev);
 	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
 	return wm2000_anc_transition(wm2000, ANC_OFF);
 }
 
-static int wm2000_i2c_resume(struct i2c_client *i2c)
+static int wm2000_i2c_resume(struct device *dev)
 {
+	struct i2c_client *i2c = to_i2c_client(dev);
 	struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
 
 	return wm2000_anc_set_mode(wm2000);
 }
-#else
-#define wm2000_i2c_suspend NULL
-#define wm2000_i2c_resume NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(wm2000_pm, wm2000_i2c_suspend, wm2000_i2c_resume);
+
 static const struct i2c_device_id wm2000_i2c_id[] = {
 	{ "wm2000", 0 },
 	{ }
@@ -864,11 +865,10 @@ static struct i2c_driver wm2000_i2c_driver = {
 	.driver = {
 		.name = "wm2000",
 		.owner = THIS_MODULE,
+		.pm = &wm2000_pm,
 	},
 	.probe = wm2000_i2c_probe,
 	.remove = __devexit_p(wm2000_i2c_remove),
-	.suspend = wm2000_i2c_suspend,
-	.resume = wm2000_i2c_resume,
 	.shutdown = wm2000_i2c_shutdown,
 	.id_table = wm2000_i2c_id,
 };
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 5eb2f50..4fd4d8d 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -58,7 +58,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
 	0x0000,     /* R8 - ZERO_DETECT */
 };
 
-static int wm8523_volatile_register(unsigned int reg)
+static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8523_DEVICE_ID:
@@ -414,7 +414,6 @@ static int wm8523_resume(struct snd_soc_codec *codec)
 static int wm8523_probe(struct snd_soc_codec *codec)
 {
 	struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = codec->reg_cache;
 	int ret, i;
 
 	codec->hw_write = (hw_write_t)i2c_master_send;
@@ -471,8 +470,9 @@ static int wm8523_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Change some default settings - latch VU and enable ZC */
-	reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
-	reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
+	snd_soc_update_bits(codec, WM8523_DAC_GAINR,
+			    WM8523_DACR_VU, WM8523_DACR_VU);
+	snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC);
 
 	wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 494f2d3..25af901 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -421,7 +421,6 @@ static int wm8741_resume(struct snd_soc_codec *codec)
 static int wm8741_probe(struct snd_soc_codec *codec)
 {
 	struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = codec->reg_cache;
 	int ret = 0;
 
 	ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
@@ -437,10 +436,14 @@ static int wm8741_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Change some default settings - latch VU */
-	reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
-	reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
-	reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
-	reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
+	snd_soc_update_bits(codec, WM8741_DACLLSB_ATTENUATION,
+			    WM8741_UPDATELL, WM8741_UPDATELL);
+	snd_soc_update_bits(codec, WM8741_DACLMSB_ATTENUATION,
+			    WM8741_UPDATELM, WM8741_UPDATELM);
+	snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
+			    WM8741_UPDATERL, WM8741_UPDATERL);
+	snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
+			    WM8741_UPDATERM, WM8741_UPDATERM);
 
 	snd_soc_add_controls(codec, wm8741_snd_controls,
 			     ARRAY_SIZE(wm8741_snd_controls));
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 79b02ae..3f09dee 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -55,8 +55,10 @@ static int caps_charge = 2000;
 module_param(caps_charge, int, 0);
 MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
 
-static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
-		struct snd_soc_dai *dai, unsigned int hifi);
+static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec,
+		unsigned int fmt);
+static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec,
+		unsigned int fmt);
 
 /*
  * wm8753 register cache
@@ -87,6 +89,10 @@ struct wm8753_priv {
 	enum snd_soc_control_type control_type;
 	unsigned int sysclk;
 	unsigned int pcmclk;
+
+	unsigned int voice_fmt;
+	unsigned int hifi_fmt;
+
 	int dai_func;
 };
 
@@ -170,9 +176,9 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-	int mode = snd_soc_read(codec, WM8753_IOCTL);
+	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
-	ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
+	ucontrol->value.integer.value[0] = wm8753->dai_func;
 	return 0;
 }
 
@@ -180,16 +186,26 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-	int mode = snd_soc_read(codec, WM8753_IOCTL);
 	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+	u16 ioctl;
+
+	if (codec->active)
+		return -EBUSY;
+
+	ioctl = snd_soc_read(codec, WM8753_IOCTL);
+
+	wm8753->dai_func = ucontrol->value.integer.value[0];
+
+	if (((ioctl >> 2) & 0x3) == wm8753->dai_func)
+		return 1;
+
+	ioctl = (ioctl & 0x1f3) | (wm8753->dai_func << 2);
+	snd_soc_write(codec, WM8753_IOCTL, ioctl);
 
-	if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
-		return 0;
 
-	mode &= 0xfff3;
-	mode |= (ucontrol->value.integer.value[0] << 2);
+	wm8753_hifi_write_dai_fmt(codec, wm8753->hifi_fmt);
+	wm8753_voice_write_dai_fmt(codec, wm8753->voice_fmt);
 
-	wm8753->dai_func =  ucontrol->value.integer.value[0];
 	return 1;
 }
 
@@ -828,10 +844,9 @@ static int wm8753_set_dai_sysclk(struct snd_soc_dai *codec_dai,
 /*
  * Set's ADC and Voice DAC format.
  */
-static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;
 
 	/* interface format */
@@ -858,13 +873,6 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
-static int wm8753_pcm_startup(struct snd_pcm_substream *substream,
-				struct snd_soc_dai *dai)
-{
-	wm8753_set_dai_mode(dai->codec, dai, 0);
-	return 0;
-}
-
 /*
  * Set PCM DAI bit size and sample rate.
  */
@@ -905,10 +913,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
 /*
  * Set's PCM dai fmt and BCLK.
  */
-static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_pcm_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 voice, ioctl;
 
 	voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
@@ -999,10 +1006,9 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 /*
  * Set's HiFi DAC format.
  */
-static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_hdac_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;
 
 	/* interface format */
@@ -1032,10 +1038,9 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
 /*
  * Set's I2S DAI format.
  */
-static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_i2s_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 ioctl, hifi;
 
 	hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
@@ -1098,13 +1103,6 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
 	return 0;
 }
 
-static int wm8753_i2s_startup(struct snd_pcm_substream *substream,
-				struct snd_soc_dai *dai)
-{
-	wm8753_set_dai_mode(dai->codec, dai, 1);
-	return 0;
-}
-
 /*
  * Set PCM DAI bit size and sample rate.
  */
@@ -1147,61 +1145,117 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
 	return 0;
 }
 
-static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_mode1v_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 clock;
 
 	/* set clk source as pcmclk */
 	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
 	snd_soc_write(codec, WM8753_CLOCK, clock);
 
-	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
-		return -EINVAL;
-	return wm8753_pcm_set_dai_fmt(codec_dai, fmt);
+	return wm8753_vdac_adc_set_dai_fmt(codec, fmt);
 }
 
-static int wm8753_mode1h_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_mode1h_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
-		return -EINVAL;
-	return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
+	return wm8753_hdac_set_dai_fmt(codec, fmt);
 }
 
-static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_mode2_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 clock;
 
 	/* set clk source as pcmclk */
 	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
 	snd_soc_write(codec, WM8753_CLOCK, clock);
 
-	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
-		return -EINVAL;
-	return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
+	return wm8753_vdac_adc_set_dai_fmt(codec, fmt);
 }
 
-static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
+static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_codec *codec,
 		unsigned int fmt)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	u16 clock;
 
 	/* set clk source as mclk */
 	clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
 	snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);
 
-	if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
+	if (wm8753_hdac_set_dai_fmt(codec, fmt) < 0)
 		return -EINVAL;
-	if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
-		return -EINVAL;
-	return wm8753_i2s_set_dai_fmt(codec_dai, fmt);
+	return wm8753_vdac_adc_set_dai_fmt(codec, fmt);
 }
 
+static int wm8753_hifi_write_dai_fmt(struct snd_soc_codec *codec,
+		unsigned int fmt)
+{
+	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
+
+	switch (wm8753->dai_func) {
+	case 0:
+		ret = wm8753_mode1h_set_dai_fmt(codec, fmt);
+		break;
+	case 1:
+		ret = wm8753_mode2_set_dai_fmt(codec, fmt);
+		break;
+	case 2:
+	case 3:
+		ret = wm8753_mode3_4_set_dai_fmt(codec, fmt);
+		break;
+	default:
+		 break;
+	}
+	if (ret)
+		return ret;
+
+	return wm8753_i2s_set_dai_fmt(codec, fmt);
+}
+
+static int wm8753_hifi_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+
+	wm8753->hifi_fmt = fmt;
+
+	return wm8753_hifi_write_dai_fmt(codec, fmt);
+};
+
+static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec,
+		unsigned int fmt)
+{
+	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+	int ret = 0;
+
+	if (wm8753->dai_func != 0)
+		return 0;
+
+	ret = wm8753_mode1v_set_dai_fmt(codec, fmt);
+	if (ret)
+		return ret;
+	ret = wm8753_pcm_set_dai_fmt(codec, fmt);
+	if (ret)
+		return ret;
+
+	return 0;
+};
+
+static int wm8753_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
+		unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
+
+	wm8753->voice_fmt = fmt;
+
+	return wm8753_voice_write_dai_fmt(codec, fmt);
+};
+
 static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 {
 	struct snd_soc_codec *codec = dai->codec;
@@ -1268,57 +1322,25 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
  * 3. Voice disabled - HIFI over HIFI
  * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
  */
-static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
-	.startup = wm8753_i2s_startup,
+static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
 	.hw_params	= wm8753_i2s_hw_params,
 	.digital_mute	= wm8753_mute,
-	.set_fmt	= wm8753_mode1h_set_dai_fmt,
-	.set_clkdiv	= wm8753_set_dai_clkdiv,
-	.set_pll	= wm8753_set_dai_pll,
-	.set_sysclk	= wm8753_set_dai_sysclk,
-};
-
-static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
-	.startup = wm8753_pcm_startup,
-	.hw_params	= wm8753_pcm_hw_params,
-	.digital_mute	= wm8753_mute,
-	.set_fmt	= wm8753_mode1v_set_dai_fmt,
+	.set_fmt	= wm8753_hifi_set_dai_fmt,
 	.set_clkdiv	= wm8753_set_dai_clkdiv,
 	.set_pll	= wm8753_set_dai_pll,
 	.set_sysclk	= wm8753_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
-	.startup = wm8753_pcm_startup,
+static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
 	.hw_params	= wm8753_pcm_hw_params,
 	.digital_mute	= wm8753_mute,
-	.set_fmt	= wm8753_mode2_set_dai_fmt,
-	.set_clkdiv	= wm8753_set_dai_clkdiv,
-	.set_pll	= wm8753_set_dai_pll,
-	.set_sysclk	= wm8753_set_dai_sysclk,
-};
-
-static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3	= {
-	.startup = wm8753_i2s_startup,
-	.hw_params	= wm8753_i2s_hw_params,
-	.digital_mute	= wm8753_mute,
-	.set_fmt	= wm8753_mode3_4_set_dai_fmt,
-	.set_clkdiv	= wm8753_set_dai_clkdiv,
-	.set_pll	= wm8753_set_dai_pll,
-	.set_sysclk	= wm8753_set_dai_sysclk,
-};
-
-static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4	= {
-	.startup = wm8753_i2s_startup,
-	.hw_params	= wm8753_i2s_hw_params,
-	.digital_mute	= wm8753_mute,
-	.set_fmt	= wm8753_mode3_4_set_dai_fmt,
+	.set_fmt	= wm8753_voice_set_dai_fmt,
 	.set_clkdiv	= wm8753_set_dai_clkdiv,
 	.set_pll	= wm8753_set_dai_pll,
 	.set_sysclk	= wm8753_set_dai_sysclk,
 };
 
-static struct snd_soc_dai_driver wm8753_all_dai[] = {
+static struct snd_soc_dai_driver wm8753_dai[] = {
 /* DAI HiFi mode 1 */
 {	.name = "wm8753-hifi",
 	.playback = {
@@ -1326,14 +1348,16 @@ static struct snd_soc_dai_driver wm8753_all_dai[] = {
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS},
+		.formats = WM8753_FORMATS
+	},
 	.capture = { /* dummy for fast DAI switching */
 		.stream_name = "Capture",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS},
-	.ops = &wm8753_dai_ops_hifi_mode1,
+		.formats = WM8753_FORMATS
+	},
+	.ops = &wm8753_dai_ops_hifi_mode,
 },
 /* DAI Voice mode 1 */
 {	.name = "wm8753-voice",
@@ -1342,97 +1366,19 @@ static struct snd_soc_dai_driver wm8753_all_dai[] = {
 		.channels_min = 1,
 		.channels_max = 1,
 		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.ops = &wm8753_dai_ops_voice_mode1,
-},
-/* DAI HiFi mode 2 - dummy */
-{	.name = "wm8753-hifi",
-},
-/* DAI Voice mode 2 */
-{	.name = "wm8753-voice",
-	.playback = {
-		.stream_name = "Voice Playback",
-		.channels_min = 1,
-		.channels_max = 1,
-		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.ops = &wm8753_dai_ops_voice_mode2,
-},
-/* DAI HiFi mode 3 */
-{	.name = "wm8753-hifi",
-	.playback = {
-		.stream_name = "HiFi Playback",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.capture = {
-		.stream_name = "Capture",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.ops = &wm8753_dai_ops_hifi_mode3,
-},
-/* DAI Voice mode 3 - dummy */
-{	.name = "wm8753-voice",
-},
-/* DAI HiFi mode 4 */
-{	.name = "wm8753-hifi",
-	.playback = {
-		.stream_name = "HiFi Playback",
-		.channels_min = 1,
-		.channels_max = 2,
-		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
+		.formats = WM8753_FORMATS,
+	},
 	.capture = {
 		.stream_name = "Capture",
 		.channels_min = 1,
 		.channels_max = 2,
 		.rates = WM8753_RATES,
-		.formats = WM8753_FORMATS,},
-	.ops = &wm8753_dai_ops_hifi_mode4,
-},
-/* DAI Voice mode 4 - dummy */
-{	.name = "wm8753-voice",
-},
-};
-
-static struct snd_soc_dai_driver wm8753_dai[] = {
-	{
-		.name = "wm8753-aif0",
-	},
-	{
-		.name = "wm8753-aif1",
+		.formats = WM8753_FORMATS,
 	},
+	.ops = &wm8753_dai_ops_voice_mode,
+},
 };
 
-static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
-		struct snd_soc_dai *dai, unsigned int hifi)
-{
-	struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-
-	if (wm8753->dai_func < 4) {
-		if (hifi)
-			dai->driver = &wm8753_all_dai[wm8753->dai_func << 1];
-		else
-			dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
-	}
-	snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);
-}
-
 static void wm8753_work(struct work_struct *work)
 {
 	struct snd_soc_dapm_context *dapm =
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 6dae1b4..6785688 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -175,7 +175,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
-static int wm8804_volatile(unsigned int reg)
+static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8804_RST_DEVID1:
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index cd09599..449ea09 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -180,7 +180,7 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
 	/* Remaining registers all zero */
 };
 
-static int wm8900_volatile_register(unsigned int reg)
+static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8900_REG_ID:
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 017d99c..ae1cadf 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -2,6 +2,7 @@
  * wm8903.c  --  WM8903 ALSA SoC Audio driver
  *
  * Copyright 2008 Wolfson Microelectronics
+ * Copyright 2011 NVIDIA, Inc.
  *
  * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
  *
@@ -19,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
@@ -213,6 +215,7 @@ static u16 wm8903_reg_defaults[] = {
 };
 
 struct wm8903_priv {
+	struct snd_soc_codec *codec;
 
 	int sysclk;
 	int irq;
@@ -220,25 +223,36 @@ struct wm8903_priv {
 	int fs;
 	int deemph;
 
+	int dcs_pending;
+	int dcs_cache[4];
+
 	/* Reference count */
 	int class_w_users;
 
-	struct completion wseq;
-
 	struct snd_soc_jack *mic_jack;
 	int mic_det;
 	int mic_short;
 	int mic_last_report;
 	int mic_delay;
+
+#ifdef CONFIG_GPIOLIB
+	struct gpio_chip gpio_chip;
+#endif
 };
 
-static int wm8903_volatile_register(unsigned int reg)
+static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8903_SW_RESET_AND_ID:
 	case WM8903_REVISION_NUMBER:
 	case WM8903_INTERRUPT_STATUS_1:
 	case WM8903_WRITE_SEQUENCER_4:
+	case WM8903_POWER_MANAGEMENT_3:
+	case WM8903_POWER_MANAGEMENT_2:
+	case WM8903_DC_SERVO_READBACK_1:
+	case WM8903_DC_SERVO_READBACK_2:
+	case WM8903_DC_SERVO_READBACK_3:
+	case WM8903_DC_SERVO_READBACK_4:
 		return 1;
 
 	default:
@@ -246,50 +260,6 @@ static int wm8903_volatile_register(unsigned int reg)
 	}
 }
 
-static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
-{
-	u16 reg[5];
-	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
-
-	BUG_ON(start > 48);
-
-	/* Enable the sequencer if it's not already on */
-	reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0);
-	snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
-		      reg[0] | WM8903_WSEQ_ENA);
-
-	dev_dbg(codec->dev, "Starting sequence at %d\n", start);
-
-	snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
-		     start | WM8903_WSEQ_START);
-
-	/* Wait for it to complete.  If we have the interrupt wired up then
-	 * that will break us out of the poll early.
-	 */
-	do {
-		wait_for_completion_timeout(&wm8903->wseq,
-					    msecs_to_jiffies(10));
-
-		reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
-	} while (reg[4] & WM8903_WSEQ_BUSY);
-
-	dev_dbg(codec->dev, "Sequence complete\n");
-
-	/* Disable the sequencer again if we enabled it */
-	snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
-
-	return 0;
-}
-
-static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
-{
-	int i;
-
-	/* There really ought to be something better we can do here :/ */
-	for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
-		cache[i] = codec->hw_read(codec, i);
-}
-
 static void wm8903_reset(struct snd_soc_codec *codec)
 {
 	snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
@@ -297,11 +267,6 @@ static void wm8903_reset(struct snd_soc_codec *codec)
 	       sizeof(wm8903_reg_defaults));
 }
 
-#define WM8903_OUTPUT_SHORT 0x8
-#define WM8903_OUTPUT_OUT   0x4
-#define WM8903_OUTPUT_INT   0x2
-#define WM8903_OUTPUT_IN    0x1
-
 static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
 			   struct snd_kcontrol *kcontrol, int event)
 {
@@ -311,97 +276,101 @@ static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
-/*
- * Event for headphone and line out amplifier power changes.  Special
- * power up/down sequences are required in order to maximise pop/click
- * performance.
- */
-static int wm8903_output_event(struct snd_soc_dapm_widget *w,
-			       struct snd_kcontrol *kcontrol, int event)
+static int wm8903_dcs_event(struct snd_soc_dapm_widget *w,
+			    struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	u16 val;
-	u16 reg;
-	u16 dcs_reg;
-	u16 dcs_bit;
-	int shift;
+	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
 
-	switch (w->reg) {
-	case WM8903_POWER_MANAGEMENT_2:
-		reg = WM8903_ANALOGUE_HP_0;
-		dcs_bit = 0 + w->shift;
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		wm8903->dcs_pending |= 1 << w->shift;
 		break;
-	case WM8903_POWER_MANAGEMENT_3:
-		reg = WM8903_ANALOGUE_LINEOUT_0;
-		dcs_bit = 2 + w->shift;
+	case SND_SOC_DAPM_PRE_PMD:
+		snd_soc_update_bits(codec, WM8903_DC_SERVO_0,
+				    1 << w->shift, 0);
 		break;
-	default:
-		BUG();
-		return -EINVAL;  /* Spurious warning from some compilers */
 	}
 
-	switch (w->shift) {
-	case 0:
-		shift = 0;
-		break;
-	case 1:
-		shift = 4;
-		break;
-	default:
-		BUG();
-		return -EINVAL;  /* Spurious warning from some compilers */
-	}
+	return 0;
+}
 
-	if (event & SND_SOC_DAPM_PRE_PMU) {
-		val = snd_soc_read(codec, reg);
+#define WM8903_DCS_MODE_WRITE_STOP 0
+#define WM8903_DCS_MODE_START_STOP 2
 
-		/* Short the output */
-		val &= ~(WM8903_OUTPUT_SHORT << shift);
-		snd_soc_write(codec, reg, val);
-	}
+static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
+				enum snd_soc_dapm_type event, int subseq)
+{
+	struct snd_soc_codec *codec = container_of(dapm,
+						   struct snd_soc_codec, dapm);
+	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+	int dcs_mode = WM8903_DCS_MODE_WRITE_STOP;
+	int i, val;
 
-	if (event & SND_SOC_DAPM_POST_PMU) {
-		val = snd_soc_read(codec, reg);
+	/* Complete any pending DC servo starts */
+	if (wm8903->dcs_pending) {
+		dev_dbg(codec->dev, "Starting DC servo for %x\n",
+			wm8903->dcs_pending);
 
-		val |= (WM8903_OUTPUT_IN << shift);
-		snd_soc_write(codec, reg, val);
+		/* If we've no cached values then we need to do startup */
+		for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) {
+			if (!(wm8903->dcs_pending & (1 << i)))
+				continue;
 
-		val |= (WM8903_OUTPUT_INT << shift);
-		snd_soc_write(codec, reg, val);
+			if (wm8903->dcs_cache[i]) {
+				dev_dbg(codec->dev,
+					"Restore DC servo %d value %x\n",
+					3 - i, wm8903->dcs_cache[i]);
+
+				snd_soc_write(codec, WM8903_DC_SERVO_4 + i,
+					      wm8903->dcs_cache[i] & 0xff);
+			} else {
+				dev_dbg(codec->dev,
+					"Calibrate DC servo %d\n", 3 - i);
+				dcs_mode = WM8903_DCS_MODE_START_STOP;
+			}
+		}
 
-		/* Turn on the output ENA_OUTP */
-		val |= (WM8903_OUTPUT_OUT << shift);
-		snd_soc_write(codec, reg, val);
+		/* Don't trust the cache for analogue */
+		if (wm8903->class_w_users)
+			dcs_mode = WM8903_DCS_MODE_START_STOP;
 
-		/* Enable the DC servo */
-		dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
-		dcs_reg |= dcs_bit;
-		snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+		snd_soc_update_bits(codec, WM8903_DC_SERVO_2,
+				    WM8903_DCS_MODE_MASK, dcs_mode);
 
-		/* Remove the short */
-		val |= (WM8903_OUTPUT_SHORT << shift);
-		snd_soc_write(codec, reg, val);
-	}
+		snd_soc_update_bits(codec, WM8903_DC_SERVO_0,
+				    WM8903_DCS_ENA_MASK, wm8903->dcs_pending);
 
-	if (event & SND_SOC_DAPM_PRE_PMD) {
-		val = snd_soc_read(codec, reg);
+		switch (dcs_mode) {
+		case WM8903_DCS_MODE_WRITE_STOP:
+			break;
 
-		/* Short the output */
-		val &= ~(WM8903_OUTPUT_SHORT << shift);
-		snd_soc_write(codec, reg, val);
+		case WM8903_DCS_MODE_START_STOP:
+			msleep(270);
 
-		/* Disable the DC servo */
-		dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0);
-		dcs_reg &= ~dcs_bit;
-		snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg);
+			/* Cache the measured offsets for digital */
+			if (wm8903->class_w_users)
+				break;
 
-		/* Then disable the intermediate and output stages */
-		val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT |
-			  WM8903_OUTPUT_IN) << shift);
-		snd_soc_write(codec, reg, val);
-	}
+			for (i = 0; i < ARRAY_SIZE(wm8903->dcs_cache); i++) {
+				if (!(wm8903->dcs_pending & (1 << i)))
+					continue;
 
-	return 0;
+				val = snd_soc_read(codec,
+						   WM8903_DC_SERVO_READBACK_1 + i);
+				dev_dbg(codec->dev, "DC servo %d: %x\n",
+					3 - i, val);
+				wm8903->dcs_cache[i] = val;
+			}
+			break;
+
+		default:
+			pr_warn("DCS mode %d delay not set\n", dcs_mode);
+			break;
+		}
+
+		wm8903->dcs_pending = 0;
+	}
 }
 
 /*
@@ -667,6 +636,22 @@ static const struct soc_enum lsidetone_enum =
 static const struct soc_enum rsidetone_enum =
 	SOC_ENUM_SINGLE(WM8903_DAC_DIGITAL_0, 0, 3, sidetone_text);
 
+static const char *aif_text[] = {
+	"Left", "Right"
+};
+
+static const struct soc_enum lcapture_enum =
+	SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 7, 2, aif_text);
+
+static const struct soc_enum rcapture_enum =
+	SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 6, 2, aif_text);
+
+static const struct soc_enum lplay_enum =
+	SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 5, 2, aif_text);
+
+static const struct soc_enum rplay_enum =
+	SOC_ENUM_SINGLE(WM8903_AUDIO_INTERFACE_0, 4, 2, aif_text);
+
 static const struct snd_kcontrol_new wm8903_snd_controls[] = {
 
 /* Input PGAs - No TLV since the scale depends on PGA mode */
@@ -784,6 +769,18 @@ static const struct snd_kcontrol_new lsidetone_mux =
 static const struct snd_kcontrol_new rsidetone_mux =
 	SOC_DAPM_ENUM("DACR Sidetone Mux", rsidetone_enum);
 
+static const struct snd_kcontrol_new lcapture_mux =
+	SOC_DAPM_ENUM("Left Capture Mux", lcapture_enum);
+
+static const struct snd_kcontrol_new rcapture_mux =
+	SOC_DAPM_ENUM("Right Capture Mux", rcapture_enum);
+
+static const struct snd_kcontrol_new lplay_mux =
+	SOC_DAPM_ENUM("Left Playback Mux", lplay_enum);
+
+static const struct snd_kcontrol_new rplay_mux =
+	SOC_DAPM_ENUM("Right Playback Mux", rplay_enum);
+
 static const struct snd_kcontrol_new left_output_mixer[] = {
 SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
 SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
@@ -847,14 +844,26 @@ SND_SOC_DAPM_MUX("Right Input Mode Mux", SND_SOC_NOPM, 0, 0, &rinput_mode_mux),
 SND_SOC_DAPM_PGA("Left Input PGA", WM8903_POWER_MANAGEMENT_0, 1, 0, NULL, 0),
 SND_SOC_DAPM_PGA("Right Input PGA", WM8903_POWER_MANAGEMENT_0, 0, 0, NULL, 0),
 
-SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8903_POWER_MANAGEMENT_6, 1, 0),
-SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8903_POWER_MANAGEMENT_6, 0, 0),
+SND_SOC_DAPM_ADC("ADCL", NULL, WM8903_POWER_MANAGEMENT_6, 1, 0),
+SND_SOC_DAPM_ADC("ADCR", NULL, WM8903_POWER_MANAGEMENT_6, 0, 0),
+
+SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lcapture_mux),
+SND_SOC_DAPM_MUX("Right Capture Mux", SND_SOC_NOPM, 0, 0, &rcapture_mux),
+
+SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
 
 SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &lsidetone_mux),
 SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &rsidetone_mux),
 
-SND_SOC_DAPM_DAC("DACL", "Left Playback", WM8903_POWER_MANAGEMENT_6, 3, 0),
-SND_SOC_DAPM_DAC("DACR", "Right Playback", WM8903_POWER_MANAGEMENT_6, 2, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXL", "Left Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXR", "Right Playback", 0, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_MUX("Left Playback Mux", SND_SOC_NOPM, 0, 0, &lplay_mux),
+SND_SOC_DAPM_MUX("Right Playback Mux", SND_SOC_NOPM, 0, 0, &rplay_mux),
+
+SND_SOC_DAPM_DAC("DACL", NULL, WM8903_POWER_MANAGEMENT_6, 3, 0),
+SND_SOC_DAPM_DAC("DACR", NULL, WM8903_POWER_MANAGEMENT_6, 2, 0),
 
 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8903_POWER_MANAGEMENT_1, 1, 0,
 		   left_output_mixer, ARRAY_SIZE(left_output_mixer)),
@@ -866,23 +875,45 @@ SND_SOC_DAPM_MIXER("Left Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 1, 0,
 SND_SOC_DAPM_MIXER("Right Speaker Mixer", WM8903_POWER_MANAGEMENT_4, 0, 0,
 		   right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)),
 
-SND_SOC_DAPM_PGA_E("Left Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
-		   1, 0, NULL, 0, wm8903_output_event,
-		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-		   SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_PGA_E("Right Headphone Output PGA", WM8903_POWER_MANAGEMENT_2,
-		   0, 0, NULL, 0, wm8903_output_event,
-		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-		   SND_SOC_DAPM_PRE_PMD),
-
-SND_SOC_DAPM_PGA_E("Left Line Output PGA", WM8903_POWER_MANAGEMENT_3, 1, 0,
-		   NULL, 0, wm8903_output_event,
-		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-		   SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_PGA_E("Right Line Output PGA", WM8903_POWER_MANAGEMENT_3, 0, 0,
-		   NULL, 0, wm8903_output_event,
-		   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-		   SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_S("Left Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0,
+		   4, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("Right Headphone Output PGA", 0, WM8903_ANALOGUE_HP_0,
+		   0, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("Left Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 4, 0,
+		   NULL, 0),
+SND_SOC_DAPM_PGA_S("Right Line Output PGA", 0, WM8903_ANALOGUE_LINEOUT_0, 0, 0,
+		   NULL, 0),
+
+SND_SOC_DAPM_PGA_S("HPL_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPL_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPL_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPR_RMV_SHORT", 4, WM8903_ANALOGUE_HP_0, 3, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPR_ENA_OUTP", 3, WM8903_ANALOGUE_HP_0, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPR_ENA_DLY", 1, WM8903_ANALOGUE_HP_0, 1, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("LINEOUTL_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 7, 0,
+		   NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 6, 0,
+		   NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTL_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 5, 0,
+		   NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTR_RMV_SHORT", 4, WM8903_ANALOGUE_LINEOUT_0, 3, 0,
+		   NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_OUTP", 3, WM8903_ANALOGUE_LINEOUT_0, 2, 0,
+		   NULL, 0),
+SND_SOC_DAPM_PGA_S("LINEOUTR_ENA_DLY", 1, WM8903_ANALOGUE_LINEOUT_0, 1, 0,
+		   NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("DCS Master", WM8903_DC_SERVO_0, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("HPL_DCS", 3, SND_SOC_NOPM, 3, 0, wm8903_dcs_event,
+		   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_S("HPR_DCS", 3, SND_SOC_NOPM, 2, 0, wm8903_dcs_event,
+		   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_S("LINEOUTL_DCS", 3, SND_SOC_NOPM, 1, 0, wm8903_dcs_event,
+		   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA_S("LINEOUTR_DCS", 3, SND_SOC_NOPM, 0, 0, wm8903_dcs_event,
+		   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
 SND_SOC_DAPM_PGA("Left Speaker PGA", WM8903_POWER_MANAGEMENT_5, 1, 0,
 		 NULL, 0),
@@ -892,10 +923,18 @@ SND_SOC_DAPM_PGA("Right Speaker PGA", WM8903_POWER_MANAGEMENT_5, 0, 0,
 SND_SOC_DAPM_SUPPLY("Charge Pump", WM8903_CHARGE_PUMP_0, 0, 0,
 		    wm8903_cp_event, SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8903_CLOCK_RATES_2, 1, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0),
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
 
+	{ "CLK_DSP", NULL, "CLK_SYS" },
+	{ "Mic Bias", NULL, "CLK_SYS" },
+	{ "HPL_DCS", NULL, "CLK_SYS" },
+	{ "HPR_DCS", NULL, "CLK_SYS" },
+	{ "LINEOUTL_DCS", NULL, "CLK_SYS" },
+	{ "LINEOUTR_DCS", NULL, "CLK_SYS" },
+
 	{ "Left Input Mux", "IN1L", "IN1L" },
 	{ "Left Input Mux", "IN2L", "IN2L" },
 	{ "Left Input Mux", "IN3L", "IN3L" },
@@ -936,18 +975,36 @@ static const struct snd_soc_dapm_route intercon[] = {
 	{ "Left Input PGA", NULL, "Left Input Mode Mux" },
 	{ "Right Input PGA", NULL, "Right Input Mode Mux" },
 
+	{ "Left Capture Mux", "Left", "ADCL" },
+	{ "Left Capture Mux", "Right", "ADCR" },
+
+	{ "Right Capture Mux", "Left", "ADCL" },
+	{ "Right Capture Mux", "Right", "ADCR" },
+
+	{ "AIFTXL", NULL, "Left Capture Mux" },
+	{ "AIFTXR", NULL, "Right Capture Mux" },
+
 	{ "ADCL", NULL, "Left Input PGA" },
 	{ "ADCL", NULL, "CLK_DSP" },
 	{ "ADCR", NULL, "Right Input PGA" },
 	{ "ADCR", NULL, "CLK_DSP" },
 
+	{ "Left Playback Mux", "Left", "AIFRXL" },
+	{ "Left Playback Mux", "Right", "AIFRXR" },
+
+	{ "Right Playback Mux", "Left", "AIFRXL" },
+	{ "Right Playback Mux", "Right", "AIFRXR" },
+
 	{ "DACL Sidetone", "Left", "ADCL" },
 	{ "DACL Sidetone", "Right", "ADCR" },
 	{ "DACR Sidetone", "Left", "ADCL" },
 	{ "DACR Sidetone", "Right", "ADCR" },
 
+	{ "DACL", NULL, "Left Playback Mux" },
 	{ "DACL", NULL, "DACL Sidetone" },
 	{ "DACL", NULL, "CLK_DSP" },
+
+	{ "DACR", NULL, "Right Playback Mux" },
 	{ "DACR", NULL, "DACR Sidetone" },
 	{ "DACR", NULL, "CLK_DSP" },
 
@@ -980,11 +1037,35 @@ static const struct snd_soc_dapm_route intercon[] = {
 	{ "Left Speaker PGA", NULL, "Left Speaker Mixer" },
 	{ "Right Speaker PGA", NULL, "Right Speaker Mixer" },
 
-	{ "HPOUTL", NULL, "Left Headphone Output PGA" },
-	{ "HPOUTR", NULL, "Right Headphone Output PGA" },
+	{ "HPL_ENA_DLY", NULL, "Left Headphone Output PGA" },
+	{ "HPR_ENA_DLY", NULL, "Right Headphone Output PGA" },
+	{ "LINEOUTL_ENA_DLY", NULL, "Left Line Output PGA" },
+	{ "LINEOUTR_ENA_DLY", NULL, "Right Line Output PGA" },
+
+	{ "HPL_DCS", NULL, "DCS Master" },
+	{ "HPR_DCS", NULL, "DCS Master" },
+	{ "LINEOUTL_DCS", NULL, "DCS Master" },
+	{ "LINEOUTR_DCS", NULL, "DCS Master" },
+
+	{ "HPL_DCS", NULL, "HPL_ENA_DLY" },
+	{ "HPR_DCS", NULL, "HPR_ENA_DLY" },
+	{ "LINEOUTL_DCS", NULL, "LINEOUTL_ENA_DLY" },
+	{ "LINEOUTR_DCS", NULL, "LINEOUTR_ENA_DLY" },
 
-	{ "LINEOUTL", NULL, "Left Line Output PGA" },
-	{ "LINEOUTR", NULL, "Right Line Output PGA" },
+	{ "HPL_ENA_OUTP", NULL, "HPL_DCS" },
+	{ "HPR_ENA_OUTP", NULL, "HPR_DCS" },
+	{ "LINEOUTL_ENA_OUTP", NULL, "LINEOUTL_DCS" },
+	{ "LINEOUTR_ENA_OUTP", NULL, "LINEOUTR_DCS" },
+
+	{ "HPL_RMV_SHORT", NULL, "HPL_ENA_OUTP" },
+	{ "HPR_RMV_SHORT", NULL, "HPR_ENA_OUTP" },
+	{ "LINEOUTL_RMV_SHORT", NULL, "LINEOUTL_ENA_OUTP" },
+	{ "LINEOUTR_RMV_SHORT", NULL, "LINEOUTR_ENA_OUTP" },
+
+	{ "HPOUTL", NULL, "HPL_RMV_SHORT" },
+	{ "HPOUTR", NULL, "HPR_RMV_SHORT" },
+	{ "LINEOUTL", NULL, "LINEOUTL_RMV_SHORT" },
+	{ "LINEOUTR", NULL, "LINEOUTR_RMV_SHORT" },
 
 	{ "LOP", NULL, "Left Speaker PGA" },
 	{ "LON", NULL, "Left Speaker PGA" },
@@ -1012,29 +1093,71 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)
 static int wm8903_set_bias_level(struct snd_soc_codec *codec,
 				 enum snd_soc_bias_level level)
 {
-	u16 reg;
-
 	switch (level) {
 	case SND_SOC_BIAS_ON:
+		break;
+
 	case SND_SOC_BIAS_PREPARE:
-		reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
-		reg &= ~(WM8903_VMID_RES_MASK);
-		reg |= WM8903_VMID_RES_50K;
-		snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
+		snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+				    WM8903_VMID_RES_MASK,
+				    WM8903_VMID_RES_50K);
 		break;
 
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
-			snd_soc_write(codec, WM8903_CLOCK_RATES_2,
-				     WM8903_CLK_SYS_ENA);
-
-			/* Change DC servo dither level in startup sequence */
-			snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11);
-			snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257);
-			snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2);
-
-			wm8903_run_sequence(codec, 0);
-			wm8903_sync_reg_cache(codec, codec->reg_cache);
+			snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0,
+					    WM8903_POBCTRL | WM8903_ISEL_MASK |
+					    WM8903_STARTUP_BIAS_ENA |
+					    WM8903_BIAS_ENA,
+					    WM8903_POBCTRL |
+					    (2 << WM8903_ISEL_SHIFT) |
+					    WM8903_STARTUP_BIAS_ENA);
+
+			snd_soc_update_bits(codec,
+					    WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0,
+					    WM8903_SPK_DISCHARGE,
+					    WM8903_SPK_DISCHARGE);
+
+			msleep(33);
+
+			snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5,
+					    WM8903_SPKL_ENA | WM8903_SPKR_ENA,
+					    WM8903_SPKL_ENA | WM8903_SPKR_ENA);
+
+			snd_soc_update_bits(codec,
+					    WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0,
+					    WM8903_SPK_DISCHARGE, 0);
+
+			snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+					    WM8903_VMID_TIE_ENA |
+					    WM8903_BUFIO_ENA |
+					    WM8903_VMID_IO_ENA |
+					    WM8903_VMID_SOFT_MASK |
+					    WM8903_VMID_RES_MASK |
+					    WM8903_VMID_BUF_ENA,
+					    WM8903_VMID_TIE_ENA |
+					    WM8903_BUFIO_ENA |
+					    WM8903_VMID_IO_ENA |
+					    (2 << WM8903_VMID_SOFT_SHIFT) |
+					    WM8903_VMID_RES_250K |
+					    WM8903_VMID_BUF_ENA);
+
+			msleep(129);
+
+			snd_soc_update_bits(codec, WM8903_POWER_MANAGEMENT_5,
+					    WM8903_SPKL_ENA | WM8903_SPKR_ENA,
+					    0);
+
+			snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+					    WM8903_VMID_SOFT_MASK, 0);
+
+			snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+					    WM8903_VMID_RES_MASK,
+					    WM8903_VMID_RES_50K);
+
+			snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0,
+					    WM8903_BIAS_ENA | WM8903_POBCTRL,
+					    WM8903_BIAS_ENA);
 
 			/* By default no bypass paths are enabled so
 			 * enable Class W support.
@@ -1047,17 +1170,32 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
 					    WM8903_CP_DYN_V);
 		}
 
-		reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0);
-		reg &= ~(WM8903_VMID_RES_MASK);
-		reg |= WM8903_VMID_RES_250K;
-		snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg);
+		snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+				    WM8903_VMID_RES_MASK,
+				    WM8903_VMID_RES_250K);
 		break;
 
 	case SND_SOC_BIAS_OFF:
-		wm8903_run_sequence(codec, 32);
-		reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2);
-		reg &= ~WM8903_CLK_SYS_ENA;
-		snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg);
+		snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0,
+				    WM8903_BIAS_ENA, 0);
+
+		snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+				    WM8903_VMID_SOFT_MASK,
+				    2 << WM8903_VMID_SOFT_SHIFT);
+
+		snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+				    WM8903_VMID_BUF_ENA, 0);
+
+		msleep(290);
+
+		snd_soc_update_bits(codec, WM8903_VMID_CONTROL_0,
+				    WM8903_VMID_TIE_ENA | WM8903_BUFIO_ENA |
+				    WM8903_VMID_IO_ENA | WM8903_VMID_RES_MASK |
+				    WM8903_VMID_SOFT_MASK |
+				    WM8903_VMID_BUF_ENA, 0);
+
+		snd_soc_update_bits(codec, WM8903_BIAS_CONTROL_0,
+				    WM8903_STARTUP_BIAS_ENA, 0);
 		break;
 	}
 
@@ -1510,8 +1648,7 @@ static irqreturn_t wm8903_irq(int irq, void *data)
 	int_val = snd_soc_read(codec, WM8903_INTERRUPT_STATUS_1) & mask;
 
 	if (int_val & WM8903_WSEQ_BUSY_EINT) {
-		dev_dbg(codec->dev, "Write sequencer done\n");
-		complete(&wm8903->wseq);
+		dev_warn(codec->dev, "Write sequencer done\n");
 	}
 
 	/*
@@ -1635,6 +1772,120 @@ static int wm8903_resume(struct snd_soc_codec *codec)
 	return 0;
 }
 
+#ifdef CONFIG_GPIOLIB
+static inline struct wm8903_priv *gpio_to_wm8903(struct gpio_chip *chip)
+{
+	return container_of(chip, struct wm8903_priv, gpio_chip);
+}
+
+static int wm8903_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset >= WM8903_NUM_GPIO)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
+	struct snd_soc_codec *codec = wm8903->codec;
+	unsigned int mask, val;
+
+	mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK;
+	val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) |
+		WM8903_GP1_DIR;
+
+	return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
+				   mask, val);
+}
+
+static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
+	struct snd_soc_codec *codec = wm8903->codec;
+	int reg;
+
+	reg = snd_soc_read(codec, WM8903_GPIO_CONTROL_1 + offset);
+
+	return (reg & WM8903_GP1_LVL_MASK) >> WM8903_GP1_LVL_SHIFT;
+}
+
+static int wm8903_gpio_direction_out(struct gpio_chip *chip,
+				     unsigned offset, int value)
+{
+	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
+	struct snd_soc_codec *codec = wm8903->codec;
+	unsigned int mask, val;
+
+	mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK | WM8903_GP1_LVL_MASK;
+	val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) |
+		(value << WM8903_GP2_LVL_SHIFT);
+
+	return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
+				   mask, val);
+}
+
+static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
+	struct snd_soc_codec *codec = wm8903->codec;
+
+	snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
+			    WM8903_GP1_LVL_MASK,
+			    !!value << WM8903_GP1_LVL_SHIFT);
+}
+
+static struct gpio_chip wm8903_template_chip = {
+	.label			= "wm8903",
+	.owner			= THIS_MODULE,
+	.request		= wm8903_gpio_request,
+	.direction_input	= wm8903_gpio_direction_in,
+	.get			= wm8903_gpio_get,
+	.direction_output	= wm8903_gpio_direction_out,
+	.set			= wm8903_gpio_set,
+	.can_sleep		= 1,
+};
+
+static void wm8903_init_gpio(struct snd_soc_codec *codec)
+{
+	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+	struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
+	int ret;
+
+	wm8903->gpio_chip = wm8903_template_chip;
+	wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
+	wm8903->gpio_chip.dev = codec->dev;
+
+	if (pdata && pdata->gpio_base)
+		wm8903->gpio_chip.base = pdata->gpio_base;
+	else
+		wm8903->gpio_chip.base = -1;
+
+	ret = gpiochip_add(&wm8903->gpio_chip);
+	if (ret != 0)
+		dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm8903_free_gpio(struct snd_soc_codec *codec)
+{
+	struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+	int ret;
+
+	ret = gpiochip_remove(&wm8903->gpio_chip);
+	if (ret != 0)
+		dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm8903_init_gpio(struct snd_soc_codec *codec)
+{
+}
+
+static void wm8903_free_gpio(struct snd_soc_codec *codec)
+{
+}
+#endif
+
 static int wm8903_probe(struct snd_soc_codec *codec)
 {
 	struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
@@ -1643,7 +1894,7 @@ static int wm8903_probe(struct snd_soc_codec *codec)
 	int trigger, irq_pol;
 	u16 val;
 
-	init_completion(&wm8903->wseq);
+	wm8903->codec = codec;
 
 	ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
 	if (ret != 0) {
@@ -1659,19 +1910,33 @@ static int wm8903_probe(struct snd_soc_codec *codec)
 	}
 
 	val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
-	dev_info(codec->dev, "WM8903 revision %d\n",
-		 val & WM8903_CHIP_REV_MASK);
+	dev_info(codec->dev, "WM8903 revision %c\n",
+		 (val & WM8903_CHIP_REV_MASK) + 'A');
 
 	wm8903_reset(codec);
 
 	/* Set up GPIOs and microphone detection */
 	if (pdata) {
+		bool mic_gpio = false;
+
 		for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
-			if (!pdata->gpio_cfg[i])
+			if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG)
 				continue;
 
 			snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
 				      pdata->gpio_cfg[i] & 0xffff);
+
+			val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
+				>> WM8903_GP1_FN_SHIFT;
+
+			switch (val) {
+			case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
+			case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
+				mic_gpio = true;
+				break;
+			default:
+				break;
+			}
 		}
 
 		snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
@@ -1682,6 +1947,14 @@ static int wm8903_probe(struct snd_soc_codec *codec)
 			snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
 					    WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
 
+		/* If microphone detection is enabled by pdata but
+		 * detected via IRQ then interrupts can be lost before
+		 * the machine driver has set up microphone detection
+		 * IRQs as the IRQs are clear on read.  The detection
+		 * will be enabled when the machine driver configures.
+		 */
+		WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
+
 		wm8903->mic_delay = pdata->micdet_delay;
 	}
 	
@@ -1741,20 +2014,23 @@ static int wm8903_probe(struct snd_soc_codec *codec)
 	snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val);
 
 	/* Enable DAC soft mute by default */
-	val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
-	val |= WM8903_DAC_MUTEMODE;
-	snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
+	snd_soc_update_bits(codec, WM8903_DAC_DIGITAL_1,
+			    WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
+			    WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
 
 	snd_soc_add_controls(codec, wm8903_snd_controls,
 				ARRAY_SIZE(wm8903_snd_controls));
 	wm8903_add_widgets(codec);
 
+	wm8903_init_gpio(codec);
+
 	return ret;
 }
 
 /* power down chip */
 static int wm8903_remove(struct snd_soc_codec *codec)
 {
+	wm8903_free_gpio(codec);
 	wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
 	return 0;
 }
@@ -1769,6 +2045,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm8903_reg_defaults,
 	.volatile_register = wm8903_volatile_register,
+	.seq_notifier = wm8903_seq_notifier,
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -1807,7 +2084,7 @@ MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
 
 static struct i2c_driver wm8903_i2c_driver = {
 	.driver = {
-		.name = "wm8903-codec",
+		.name = "wm8903",
 		.owner = THIS_MODULE,
 	},
 	.probe =    wm8903_i2c_probe,
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index e3ec243..db94931 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -75,6 +75,14 @@ extern int wm8903_mic_detect(struct snd_soc_codec *codec,
 #define WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0    0x41
 #define WM8903_DC_SERVO_0                       0x43
 #define WM8903_DC_SERVO_2                       0x45
+#define WM8903_DC_SERVO_4			0x47
+#define WM8903_DC_SERVO_5			0x48
+#define WM8903_DC_SERVO_6			0x49
+#define WM8903_DC_SERVO_7			0x4A
+#define WM8903_DC_SERVO_READBACK_1		0x51
+#define WM8903_DC_SERVO_READBACK_2		0x52
+#define WM8903_DC_SERVO_READBACK_3		0x53
+#define WM8903_DC_SERVO_READBACK_4		0x54
 #define WM8903_ANALOGUE_HP_0                    0x5A
 #define WM8903_ANALOGUE_LINEOUT_0               0x5E
 #define WM8903_CHARGE_PUMP_0                    0x62
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 9de44a4..443ae58 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -596,7 +596,7 @@ static struct {
 	{ 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
 };
 
-static int wm8904_volatile_register(unsigned int reg)
+static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	return wm8904_access[reg].vol;
 }
@@ -2436,19 +2436,28 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Change some default settings - latch VU and enable ZC */
-	reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
-	reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
-	reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
-	reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
-	reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
-		WM8904_HPOUTLZC;
-	reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
-		WM8904_HPOUTRZC;
-	reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
-		WM8904_LINEOUTLZC;
-	reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
-		WM8904_LINEOUTRZC;
-	reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
+	snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_LEFT,
+			    WM8904_ADC_VU, WM8904_ADC_VU);
+	snd_soc_update_bits(codec, WM8904_ADC_DIGITAL_VOLUME_RIGHT,
+			    WM8904_ADC_VU, WM8904_ADC_VU);
+	snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_LEFT,
+			    WM8904_DAC_VU, WM8904_DAC_VU);
+	snd_soc_update_bits(codec, WM8904_DAC_DIGITAL_VOLUME_RIGHT,
+			    WM8904_DAC_VU, WM8904_DAC_VU);
+	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_LEFT,
+			    WM8904_HPOUT_VU | WM8904_HPOUTLZC,
+			    WM8904_HPOUT_VU | WM8904_HPOUTLZC);
+	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT1_RIGHT,
+			    WM8904_HPOUT_VU | WM8904_HPOUTRZC,
+			    WM8904_HPOUT_VU | WM8904_HPOUTRZC);
+	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_LEFT,
+			    WM8904_LINEOUT_VU | WM8904_LINEOUTLZC,
+			    WM8904_LINEOUT_VU | WM8904_LINEOUTLZC);
+	snd_soc_update_bits(codec, WM8904_ANALOGUE_OUT2_RIGHT,
+			    WM8904_LINEOUT_VU | WM8904_LINEOUTRZC,
+			    WM8904_LINEOUT_VU | WM8904_LINEOUTRZC);
+	snd_soc_update_bits(codec, WM8904_CLOCK_RATES_0,
+			    WM8904_SR_MODE, 0);
 
 	/* Apply configuration from the platform data. */
 	if (wm8904->pdata) {
@@ -2469,10 +2478,12 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 	/* Set Class W by default - this will be managed by the Class
 	 * G widget at runtime where bypass paths are available.
 	 */
-	reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
+	snd_soc_update_bits(codec, WM8904_CLASS_W_0,
+			    WM8904_CP_DYN_PWR, WM8904_CP_DYN_PWR);
 
 	/* Use normal bias source */
-	reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
+	snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
+			    WM8904_POBCTRL, 0);
 
 	wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 7167dfc..5e0214d 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -934,16 +934,27 @@ static int wm8955_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Change some default settings - latch VU and enable ZC */
-	reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
-	reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
-	reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
-	reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
-	reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
-	reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
-	reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
+	snd_soc_update_bits(codec, WM8955_LEFT_DAC_VOLUME,
+			    WM8955_LDVU, WM8955_LDVU);
+	snd_soc_update_bits(codec, WM8955_RIGHT_DAC_VOLUME,
+			    WM8955_RDVU, WM8955_RDVU);
+	snd_soc_update_bits(codec, WM8955_LOUT1_VOLUME,
+			    WM8955_LO1VU | WM8955_LO1ZC,
+			    WM8955_LO1VU | WM8955_LO1ZC);
+	snd_soc_update_bits(codec, WM8955_ROUT1_VOLUME,
+			    WM8955_RO1VU | WM8955_RO1ZC,
+			    WM8955_RO1VU | WM8955_RO1ZC);
+	snd_soc_update_bits(codec, WM8955_LOUT2_VOLUME,
+			    WM8955_LO2VU | WM8955_LO2ZC,
+			    WM8955_LO2VU | WM8955_LO2ZC);
+	snd_soc_update_bits(codec, WM8955_ROUT2_VOLUME,
+			    WM8955_RO2VU | WM8955_RO2ZC,
+			    WM8955_RO2VU | WM8955_RO2ZC);
+	snd_soc_update_bits(codec, WM8955_MONOOUT_VOLUME,
+			    WM8955_MOZC, WM8955_MOZC);
 
 	/* Also enable adaptive bass boost by default */
-	reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
+	snd_soc_update_bits(codec, WM8955_BASS_CONTROL, WM8955_BB, WM8955_BB);
 
 	/* Set platform data values */
 	if (pdata) {
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 55252e7..cdee810 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -291,7 +291,7 @@ struct wm8961_priv {
 	int sysclk;
 };
 
-static int wm8961_volatile_register(unsigned int reg)
+static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8961_SOFTWARE_RESET:
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index b9cb1fc..3b71dd6 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -1938,7 +1938,7 @@ static const struct wm8962_reg_access {
 	[21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
 };
 
-static int wm8962_volatile_register(unsigned int reg)
+static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	if (wm8962_reg_access[reg].vol)
 		return 1;
@@ -1946,7 +1946,7 @@ static int wm8962_volatile_register(unsigned int reg)
 		return 0;
 }
 
-static int wm8962_readable_register(unsigned int reg)
+static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	if (wm8962_reg_access[reg].read)
 		return 1;
@@ -3635,7 +3635,7 @@ static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	struct snd_soc_codec *codec = wm8962->codec;
 
 	snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
-			    WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT);
+			    WM8962_GP2_LVL, !!value << WM8962_GP2_LVL_SHIFT);
 }
 
 static int wm8962_gpio_direction_out(struct gpio_chip *chip,
@@ -3822,16 +3822,26 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 	}
 
 	/* Latch volume update bits */
-	reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
-	reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
-	reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
-	reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
-	reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
-	reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
-	reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
-	reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
-	reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
-	reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
+	snd_soc_update_bits(codec, WM8962_LEFT_INPUT_VOLUME,
+			    WM8962_IN_VU, WM8962_IN_VU);
+	snd_soc_update_bits(codec, WM8962_RIGHT_INPUT_VOLUME,
+			    WM8962_IN_VU, WM8962_IN_VU);
+	snd_soc_update_bits(codec, WM8962_LEFT_ADC_VOLUME,
+			    WM8962_ADC_VU, WM8962_ADC_VU);
+	snd_soc_update_bits(codec, WM8962_RIGHT_ADC_VOLUME,
+			    WM8962_ADC_VU, WM8962_ADC_VU);
+	snd_soc_update_bits(codec, WM8962_LEFT_DAC_VOLUME,
+			    WM8962_DAC_VU, WM8962_DAC_VU);
+	snd_soc_update_bits(codec, WM8962_RIGHT_DAC_VOLUME,
+			    WM8962_DAC_VU, WM8962_DAC_VU);
+	snd_soc_update_bits(codec, WM8962_SPKOUTL_VOLUME,
+			    WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
+	snd_soc_update_bits(codec, WM8962_SPKOUTR_VOLUME,
+			    WM8962_SPKOUT_VU, WM8962_SPKOUT_VU);
+	snd_soc_update_bits(codec, WM8962_HPOUTL_VOLUME,
+			    WM8962_HPOUT_VU, WM8962_HPOUT_VU);
+	snd_soc_update_bits(codec, WM8962_HPOUTR_VOLUME,
+			    WM8962_HPOUT_VU, WM8962_HPOUT_VU);
 
 	wm8962_add_widgets(codec);
 
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 8dfb0a0..85e3e63 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -93,6 +93,7 @@ static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0);
 static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0);
 static const DECLARE_TLV_DB_SCALE(boost_tlv, -1500, 300, 1);
+static const DECLARE_TLV_DB_SCALE(limiter_tlv, 0, 100, 0);
 
 static const struct snd_kcontrol_new wm8978_snd_controls[] = {
 
@@ -144,8 +145,8 @@ static const struct snd_kcontrol_new wm8978_snd_controls[] = {
 
 	SOC_SINGLE("DAC Playback Limiter Threshold",
 		WM8978_DAC_LIMITER_2, 4, 7, 0),
-	SOC_SINGLE("DAC Playback Limiter Boost",
-		WM8978_DAC_LIMITER_2, 0, 12, 0),
+	SOC_SINGLE_TLV("DAC Playback Limiter Volume",
+		WM8978_DAC_LIMITER_2, 0, 12, 0, limiter_tlv),
 
 	SOC_ENUM("ALC Enable Switch", alc1),
 	SOC_SINGLE("ALC Capture Min Gain", WM8978_ALC_CONTROL_1, 0, 7, 0),
@@ -967,7 +968,7 @@ static int wm8978_probe(struct snd_soc_codec *codec)
 	 * written.
 	 */
 	for (i = 0; i < ARRAY_SIZE(update_reg); i++)
-		((u16 *)codec->reg_cache)[update_reg[i]] |= 0x100;
+		snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100);
 
 	/* Reset the codec */
 	ret = snd_soc_write(codec, WM8978_RESET, 0);
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
new file mode 100644
index 0000000..28fdfd6
--- /dev/null
+++ b/sound/soc/codecs/wm8991.c
@@ -0,0 +1,1427 @@
+/*
+ * wm8991.c  --  WM8991 ALSA Soc Audio driver
+ *
+ * Copyright 2007-2010 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ *         linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <asm/div64.h>
+
+#include "wm8991.h"
+
+struct wm8991_priv {
+	enum snd_soc_control_type control_type;
+	unsigned int pcmclk;
+};
+
+static const u16 wm8991_reg_defs[] = {
+	0x8991,     /* R0  - Reset */
+	0x0000,     /* R1  - Power Management (1) */
+	0x6000,     /* R2  - Power Management (2) */
+	0x0000,     /* R3  - Power Management (3) */
+	0x4050,     /* R4  - Audio Interface (1) */
+	0x4000,     /* R5  - Audio Interface (2) */
+	0x01C8,     /* R6  - Clocking (1) */
+	0x0000,     /* R7  - Clocking (2) */
+	0x0040,     /* R8  - Audio Interface (3) */
+	0x0040,     /* R9  - Audio Interface (4) */
+	0x0004,     /* R10 - DAC CTRL */
+	0x00C0,     /* R11 - Left DAC Digital Volume */
+	0x00C0,     /* R12 - Right DAC Digital Volume */
+	0x0000,     /* R13 - Digital Side Tone */
+	0x0100,     /* R14 - ADC CTRL */
+	0x00C0,     /* R15 - Left ADC Digital Volume */
+	0x00C0,     /* R16 - Right ADC Digital Volume */
+	0x0000,     /* R17 */
+	0x0000,     /* R18 - GPIO CTRL 1 */
+	0x1000,     /* R19 - GPIO1 & GPIO2 */
+	0x1010,     /* R20 - GPIO3 & GPIO4 */
+	0x1010,     /* R21 - GPIO5 & GPIO6 */
+	0x8000,     /* R22 - GPIOCTRL 2 */
+	0x0800,     /* R23 - GPIO_POL */
+	0x008B,     /* R24 - Left Line Input 1&2 Volume */
+	0x008B,     /* R25 - Left Line Input 3&4 Volume */
+	0x008B,     /* R26 - Right Line Input 1&2 Volume */
+	0x008B,     /* R27 - Right Line Input 3&4 Volume */
+	0x0000,     /* R28 - Left Output Volume */
+	0x0000,     /* R29 - Right Output Volume */
+	0x0066,     /* R30 - Line Outputs Volume */
+	0x0022,     /* R31 - Out3/4 Volume */
+	0x0079,     /* R32 - Left OPGA Volume */
+	0x0079,     /* R33 - Right OPGA Volume */
+	0x0003,     /* R34 - Speaker Volume */
+	0x0003,     /* R35 - ClassD1 */
+	0x0000,     /* R36 */
+	0x0100,     /* R37 - ClassD3 */
+	0x0000,     /* R38 */
+	0x0000,     /* R39 - Input Mixer1 */
+	0x0000,     /* R40 - Input Mixer2 */
+	0x0000,     /* R41 - Input Mixer3 */
+	0x0000,     /* R42 - Input Mixer4 */
+	0x0000,     /* R43 - Input Mixer5 */
+	0x0000,     /* R44 - Input Mixer6 */
+	0x0000,     /* R45 - Output Mixer1 */
+	0x0000,     /* R46 - Output Mixer2 */
+	0x0000,     /* R47 - Output Mixer3 */
+	0x0000,     /* R48 - Output Mixer4 */
+	0x0000,     /* R49 - Output Mixer5 */
+	0x0000,     /* R50 - Output Mixer6 */
+	0x0180,     /* R51 - Out3/4 Mixer */
+	0x0000,     /* R52 - Line Mixer1 */
+	0x0000,     /* R53 - Line Mixer2 */
+	0x0000,     /* R54 - Speaker Mixer */
+	0x0000,     /* R55 - Additional Control */
+	0x0000,     /* R56 - AntiPOP1 */
+	0x0000,     /* R57 - AntiPOP2 */
+	0x0000,     /* R58 - MICBIAS */
+	0x0000,     /* R59 */
+	0x0008,     /* R60 - PLL1 */
+	0x0031,     /* R61 - PLL2 */
+	0x0026,     /* R62 - PLL3 */
+};
+
+#define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0)
+
+static const unsigned int rec_mix_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 7, TLV_DB_LINEAR_ITEM(-1500, 600),
+};
+
+static const unsigned int in_pga_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 0x1F, TLV_DB_LINEAR_ITEM(-1650, 3000),
+};
+
+static const unsigned int out_mix_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 7, TLV_DB_LINEAR_ITEM(0, -2100),
+};
+
+static const unsigned int out_pga_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 127, TLV_DB_LINEAR_ITEM(-7300, 600),
+};
+
+static const unsigned int out_omix_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 7, TLV_DB_LINEAR_ITEM(-600, 0),
+};
+
+static const unsigned int out_dac_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 255, TLV_DB_LINEAR_ITEM(-7163, 0),
+};
+
+static const unsigned int in_adc_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 255, TLV_DB_LINEAR_ITEM(-7163, 1763),
+};
+
+static const unsigned int out_sidetone_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 31, TLV_DB_LINEAR_ITEM(-3600, 0),
+};
+
+static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int reg = kcontrol->private_value & 0xff;
+	int ret;
+	u16 val;
+
+	ret = snd_soc_put_volsw(kcontrol, ucontrol);
+	if (ret < 0)
+		return ret;
+
+	/* now hit the volume update bits (always bit 8) */
+	val = snd_soc_read(codec, reg);
+	return snd_soc_write(codec, reg, val | 0x0100);
+}
+
+static const char *wm8991_digital_sidetone[] =
+{"None", "Left ADC", "Right ADC", "Reserved"};
+
+static const struct soc_enum wm8991_left_digital_sidetone_enum =
+	SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
+			WM8991_ADC_TO_DACL_SHIFT,
+			WM8991_ADC_TO_DACL_MASK,
+			wm8991_digital_sidetone);
+
+static const struct soc_enum wm8991_right_digital_sidetone_enum =
+	SOC_ENUM_SINGLE(WM8991_DIGITAL_SIDE_TONE,
+			WM8991_ADC_TO_DACR_SHIFT,
+			WM8991_ADC_TO_DACR_MASK,
+			wm8991_digital_sidetone);
+
+static const char *wm8991_adcmode[] =
+{"Hi-fi mode", "Voice mode 1", "Voice mode 2", "Voice mode 3"};
+
+static const struct soc_enum wm8991_right_adcmode_enum =
+	SOC_ENUM_SINGLE(WM8991_ADC_CTRL,
+			WM8991_ADC_HPF_CUT_SHIFT,
+			WM8991_ADC_HPF_CUT_MASK,
+			wm8991_adcmode);
+
+static const struct snd_kcontrol_new wm8991_snd_controls[] = {
+	/* INMIXL */
+	SOC_SINGLE("LIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L12MNBST_BIT, 1, 0),
+	SOC_SINGLE("LIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_L34MNBST_BIT, 1, 0),
+	/* INMIXR */
+	SOC_SINGLE("RIN12 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R12MNBST_BIT, 1, 0),
+	SOC_SINGLE("RIN34 PGA Boost", WM8991_INPUT_MIXER3, WM8991_R34MNBST_BIT, 1, 0),
+
+	/* LOMIX */
+	SOC_SINGLE_TLV("LOMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER3,
+		WM8991_LLI3LOVOL_SHIFT, WM8991_LLI3LOVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("LOMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3,
+		WM8991_LR12LOVOL_SHIFT, WM8991_LR12LOVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("LOMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER3,
+		WM8991_LL12LOVOL_SHIFT, WM8991_LL12LOVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("LOMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER5,
+		WM8991_LRI3LOVOL_SHIFT, WM8991_LRI3LOVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("LOMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER5,
+		WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("LOMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER5,
+		WM8991_LRBLOVOL_SHIFT, WM8991_LRBLOVOL_MASK, 1, out_mix_tlv),
+
+	/* ROMIX */
+	SOC_SINGLE_TLV("ROMIX RIN3 Bypass Volume", WM8991_OUTPUT_MIXER4,
+		WM8991_RRI3ROVOL_SHIFT, WM8991_RRI3ROVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("ROMIX LIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4,
+		WM8991_RL12ROVOL_SHIFT, WM8991_RL12ROVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("ROMIX RIN12 PGA Bypass Volume", WM8991_OUTPUT_MIXER4,
+		WM8991_RR12ROVOL_SHIFT, WM8991_RR12ROVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("ROMIX LIN3 Bypass Volume", WM8991_OUTPUT_MIXER6,
+		WM8991_RLI3ROVOL_SHIFT, WM8991_RLI3ROVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("ROMIX AINLMUX Bypass Volume", WM8991_OUTPUT_MIXER6,
+		WM8991_RLBROVOL_SHIFT, WM8991_RLBROVOL_MASK, 1, out_mix_tlv),
+	SOC_SINGLE_TLV("ROMIX AINRMUX Bypass Volume", WM8991_OUTPUT_MIXER6,
+		WM8991_RRBROVOL_SHIFT, WM8991_RRBROVOL_MASK, 1, out_mix_tlv),
+
+	/* LOUT */
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOUT Volume", WM8991_LEFT_OUTPUT_VOLUME,
+		WM8991_LOUTVOL_SHIFT, WM8991_LOUTVOL_MASK, 0, out_pga_tlv),
+	SOC_SINGLE("LOUT ZC", WM8991_LEFT_OUTPUT_VOLUME, WM8991_LOZC_BIT, 1, 0),
+
+	/* ROUT */
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROUT Volume", WM8991_RIGHT_OUTPUT_VOLUME,
+		WM8991_ROUTVOL_SHIFT, WM8991_ROUTVOL_MASK, 0, out_pga_tlv),
+	SOC_SINGLE("ROUT ZC", WM8991_RIGHT_OUTPUT_VOLUME, WM8991_ROZC_BIT, 1, 0),
+
+	/* LOPGA */
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("LOPGA Volume", WM8991_LEFT_OPGA_VOLUME,
+		WM8991_LOPGAVOL_SHIFT, WM8991_LOPGAVOL_MASK, 0, out_pga_tlv),
+	SOC_SINGLE("LOPGA ZC Switch", WM8991_LEFT_OPGA_VOLUME,
+		WM8991_LOPGAZC_BIT, 1, 0),
+
+	/* ROPGA */
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("ROPGA Volume", WM8991_RIGHT_OPGA_VOLUME,
+		WM8991_ROPGAVOL_SHIFT, WM8991_ROPGAVOL_MASK, 0, out_pga_tlv),
+	SOC_SINGLE("ROPGA ZC Switch", WM8991_RIGHT_OPGA_VOLUME,
+		WM8991_ROPGAZC_BIT, 1, 0),
+
+	SOC_SINGLE("LON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
+		WM8991_LONMUTE_BIT, 1, 0),
+	SOC_SINGLE("LOP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
+		WM8991_LOPMUTE_BIT, 1, 0),
+	SOC_SINGLE("LOP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME,
+		WM8991_LOATTN_BIT, 1, 0),
+	SOC_SINGLE("RON Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
+		WM8991_RONMUTE_BIT, 1, 0),
+	SOC_SINGLE("ROP Mute Switch", WM8991_LINE_OUTPUTS_VOLUME,
+		WM8991_ROPMUTE_BIT, 1, 0),
+	SOC_SINGLE("ROP Attenuation Switch", WM8991_LINE_OUTPUTS_VOLUME,
+		WM8991_ROATTN_BIT, 1, 0),
+
+	SOC_SINGLE("OUT3 Mute Switch", WM8991_OUT3_4_VOLUME,
+		WM8991_OUT3MUTE_BIT, 1, 0),
+	SOC_SINGLE("OUT3 Attenuation Switch", WM8991_OUT3_4_VOLUME,
+		WM8991_OUT3ATTN_BIT, 1, 0),
+
+	SOC_SINGLE("OUT4 Mute Switch", WM8991_OUT3_4_VOLUME,
+		WM8991_OUT4MUTE_BIT, 1, 0),
+	SOC_SINGLE("OUT4 Attenuation Switch", WM8991_OUT3_4_VOLUME,
+		WM8991_OUT4ATTN_BIT, 1, 0),
+
+	SOC_SINGLE("Speaker Mode Switch", WM8991_CLASSD1,
+		WM8991_CDMODE_BIT, 1, 0),
+
+	SOC_SINGLE("Speaker Output Attenuation Volume", WM8991_SPEAKER_VOLUME,
+		WM8991_SPKVOL_SHIFT, WM8991_SPKVOL_MASK, 0),
+	SOC_SINGLE("Speaker DC Boost Volume", WM8991_CLASSD3,
+		WM8991_DCGAIN_SHIFT, WM8991_DCGAIN_MASK, 0),
+	SOC_SINGLE("Speaker AC Boost Volume", WM8991_CLASSD3,
+		WM8991_ACGAIN_SHIFT, WM8991_ACGAIN_MASK, 0),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left DAC Digital Volume",
+		WM8991_LEFT_DAC_DIGITAL_VOLUME,
+		WM8991_DACL_VOL_SHIFT,
+		WM8991_DACL_VOL_MASK,
+		0,
+		out_dac_tlv),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right DAC Digital Volume",
+		WM8991_RIGHT_DAC_DIGITAL_VOLUME,
+		WM8991_DACR_VOL_SHIFT,
+		WM8991_DACR_VOL_MASK,
+		0,
+		out_dac_tlv),
+
+	SOC_ENUM("Left Digital Sidetone", wm8991_left_digital_sidetone_enum),
+	SOC_ENUM("Right Digital Sidetone", wm8991_right_digital_sidetone_enum),
+
+	SOC_SINGLE_TLV("Left Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE,
+		WM8991_ADCL_DAC_SVOL_SHIFT, WM8991_ADCL_DAC_SVOL_MASK, 0,
+		out_sidetone_tlv),
+	SOC_SINGLE_TLV("Right Digital Sidetone Volume", WM8991_DIGITAL_SIDE_TONE,
+		WM8991_ADCR_DAC_SVOL_SHIFT, WM8991_ADCR_DAC_SVOL_MASK, 0,
+		out_sidetone_tlv),
+
+	SOC_SINGLE("ADC Digital High Pass Filter Switch", WM8991_ADC_CTRL,
+		WM8991_ADC_HPF_ENA_BIT, 1, 0),
+
+	SOC_ENUM("ADC HPF Mode", wm8991_right_adcmode_enum),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("Left ADC Digital Volume",
+		WM8991_LEFT_ADC_DIGITAL_VOLUME,
+		WM8991_ADCL_VOL_SHIFT,
+		WM8991_ADCL_VOL_MASK,
+		0,
+		in_adc_tlv),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("Right ADC Digital Volume",
+		WM8991_RIGHT_ADC_DIGITAL_VOLUME,
+		WM8991_ADCR_VOL_SHIFT,
+		WM8991_ADCR_VOL_MASK,
+		0,
+		in_adc_tlv),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN12 Volume",
+		WM8991_LEFT_LINE_INPUT_1_2_VOLUME,
+		WM8991_LIN12VOL_SHIFT,
+		WM8991_LIN12VOL_MASK,
+		0,
+		in_pga_tlv),
+
+	SOC_SINGLE("LIN12 ZC Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME,
+		WM8991_LI12ZC_BIT, 1, 0),
+
+	SOC_SINGLE("LIN12 Mute Switch", WM8991_LEFT_LINE_INPUT_1_2_VOLUME,
+		WM8991_LI12MUTE_BIT, 1, 0),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("LIN34 Volume",
+		WM8991_LEFT_LINE_INPUT_3_4_VOLUME,
+		WM8991_LIN34VOL_SHIFT,
+		WM8991_LIN34VOL_MASK,
+		0,
+		in_pga_tlv),
+
+	SOC_SINGLE("LIN34 ZC Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME,
+		WM8991_LI34ZC_BIT, 1, 0),
+
+	SOC_SINGLE("LIN34 Mute Switch", WM8991_LEFT_LINE_INPUT_3_4_VOLUME,
+		WM8991_LI34MUTE_BIT, 1, 0),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN12 Volume",
+		WM8991_RIGHT_LINE_INPUT_1_2_VOLUME,
+		WM8991_RIN12VOL_SHIFT,
+		WM8991_RIN12VOL_MASK,
+		0,
+		in_pga_tlv),
+
+	SOC_SINGLE("RIN12 ZC Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME,
+		WM8991_RI12ZC_BIT, 1, 0),
+
+	SOC_SINGLE("RIN12 Mute Switch", WM8991_RIGHT_LINE_INPUT_1_2_VOLUME,
+		WM8991_RI12MUTE_BIT, 1, 0),
+
+	SOC_WM899X_OUTPGA_SINGLE_R_TLV("RIN34 Volume",
+		WM8991_RIGHT_LINE_INPUT_3_4_VOLUME,
+		WM8991_RIN34VOL_SHIFT,
+		WM8991_RIN34VOL_MASK,
+		0,
+		in_pga_tlv),
+
+	SOC_SINGLE("RIN34 ZC Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME,
+		WM8991_RI34ZC_BIT, 1, 0),
+
+	SOC_SINGLE("RIN34 Mute Switch", WM8991_RIGHT_LINE_INPUT_3_4_VOLUME,
+		WM8991_RI34MUTE_BIT, 1, 0),
+};
+
+/*
+ * _DAPM_ Controls
+ */
+static int inmixer_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol, int event)
+{
+	u16 reg, fakepower;
+
+	reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2);
+	fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS);
+
+	if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) |
+			 (1 << WM8991_AINLMUX_PWR_BIT)))
+		reg |= WM8991_AINL_ENA;
+	else
+		reg &= ~WM8991_AINL_ENA;
+
+	if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) |
+			 (1 << WM8991_AINRMUX_PWR_BIT)))
+		reg |= WM8991_AINR_ENA;
+	else
+		reg &= ~WM8991_AINL_ENA;
+
+	snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
+	return 0;
+}
+
+static int outmixer_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol, int event)
+{
+	u32 reg_shift = kcontrol->private_value & 0xfff;
+	int ret = 0;
+	u16 reg;
+
+	switch (reg_shift) {
+	case WM8991_SPEAKER_MIXER | (WM8991_LDSPK_BIT << 8):
+		reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER1);
+		if (reg & WM8991_LDLO) {
+			printk(KERN_WARNING
+			       "Cannot set as Output Mixer 1 LDLO Set\n");
+			ret = -1;
+		}
+		break;
+
+	case WM8991_SPEAKER_MIXER | (WM8991_RDSPK_BIT << 8):
+		reg = snd_soc_read(w->codec, WM8991_OUTPUT_MIXER2);
+		if (reg & WM8991_RDRO) {
+			printk(KERN_WARNING
+			       "Cannot set as Output Mixer 2 RDRO Set\n");
+			ret = -1;
+		}
+		break;
+
+	case WM8991_OUTPUT_MIXER1 | (WM8991_LDLO_BIT << 8):
+		reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER);
+		if (reg & WM8991_LDSPK) {
+			printk(KERN_WARNING
+			       "Cannot set as Speaker Mixer LDSPK Set\n");
+			ret = -1;
+		}
+		break;
+
+	case WM8991_OUTPUT_MIXER2 | (WM8991_RDRO_BIT << 8):
+		reg = snd_soc_read(w->codec, WM8991_SPEAKER_MIXER);
+		if (reg & WM8991_RDSPK) {
+			printk(KERN_WARNING
+			       "Cannot set as Speaker Mixer RDSPK Set\n");
+			ret = -1;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+/* INMIX dB values */
+static const unsigned int in_mix_tlv[] = {
+	TLV_DB_RANGE_HEAD(1),
+	0, 7, TLV_DB_LINEAR_ITEM(-1200, 600),
+};
+
+/* Left In PGA Connections */
+static const struct snd_kcontrol_new wm8991_dapm_lin12_pga_controls[] = {
+	SOC_DAPM_SINGLE("LIN1 Switch", WM8991_INPUT_MIXER2, WM8991_LMN1_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LIN2 Switch", WM8991_INPUT_MIXER2, WM8991_LMP2_BIT, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8991_dapm_lin34_pga_controls[] = {
+	SOC_DAPM_SINGLE("LIN3 Switch", WM8991_INPUT_MIXER2, WM8991_LMN3_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LIN4 Switch", WM8991_INPUT_MIXER2, WM8991_LMP4_BIT, 1, 0),
+};
+
+/* Right In PGA Connections */
+static const struct snd_kcontrol_new wm8991_dapm_rin12_pga_controls[] = {
+	SOC_DAPM_SINGLE("RIN1 Switch", WM8991_INPUT_MIXER2, WM8991_RMN1_BIT, 1, 0),
+	SOC_DAPM_SINGLE("RIN2 Switch", WM8991_INPUT_MIXER2, WM8991_RMP2_BIT, 1, 0),
+};
+
+static const struct snd_kcontrol_new wm8991_dapm_rin34_pga_controls[] = {
+	SOC_DAPM_SINGLE("RIN3 Switch", WM8991_INPUT_MIXER2, WM8991_RMN3_BIT, 1, 0),
+	SOC_DAPM_SINGLE("RIN4 Switch", WM8991_INPUT_MIXER2, WM8991_RMP4_BIT, 1, 0),
+};
+
+/* INMIXL */
+static const struct snd_kcontrol_new wm8991_dapm_inmixl_controls[] = {
+	SOC_DAPM_SINGLE_TLV("Record Left Volume", WM8991_INPUT_MIXER3,
+		WM8991_LDBVOL_SHIFT, WM8991_LDBVOL_MASK, 0, in_mix_tlv),
+	SOC_DAPM_SINGLE_TLV("LIN2 Volume", WM8991_INPUT_MIXER5, WM8991_LI2BVOL_SHIFT,
+		7, 0, in_mix_tlv),
+	SOC_DAPM_SINGLE("LINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT,
+		1, 0),
+	SOC_DAPM_SINGLE("LINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT,
+		1, 0),
+};
+
+/* INMIXR */
+static const struct snd_kcontrol_new wm8991_dapm_inmixr_controls[] = {
+	SOC_DAPM_SINGLE_TLV("Record Right Volume", WM8991_INPUT_MIXER4,
+		WM8991_RDBVOL_SHIFT, WM8991_RDBVOL_MASK, 0, in_mix_tlv),
+	SOC_DAPM_SINGLE_TLV("RIN2 Volume", WM8991_INPUT_MIXER6, WM8991_RI2BVOL_SHIFT,
+		7, 0, in_mix_tlv),
+	SOC_DAPM_SINGLE("RINPGA12 Switch", WM8991_INPUT_MIXER3, WM8991_L12MNB_BIT,
+		1, 0),
+	SOC_DAPM_SINGLE("RINPGA34 Switch", WM8991_INPUT_MIXER3, WM8991_L34MNB_BIT,
+		1, 0),
+};
+
+/* AINLMUX */
+static const char *wm8991_ainlmux[] =
+{"INMIXL Mix", "RXVOICE Mix", "DIFFINL Mix"};
+
+static const struct soc_enum wm8991_ainlmux_enum =
+	SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINLMODE_SHIFT,
+			ARRAY_SIZE(wm8991_ainlmux), wm8991_ainlmux);
+
+static const struct snd_kcontrol_new wm8991_dapm_ainlmux_controls =
+	SOC_DAPM_ENUM("Route", wm8991_ainlmux_enum);
+
+/* DIFFINL */
+
+/* AINRMUX */
+static const char *wm8991_ainrmux[] =
+{"INMIXR Mix", "RXVOICE Mix", "DIFFINR Mix"};
+
+static const struct soc_enum wm8991_ainrmux_enum =
+	SOC_ENUM_SINGLE(WM8991_INPUT_MIXER1, WM8991_AINRMODE_SHIFT,
+			ARRAY_SIZE(wm8991_ainrmux), wm8991_ainrmux);
+
+static const struct snd_kcontrol_new wm8991_dapm_ainrmux_controls =
+	SOC_DAPM_ENUM("Route", wm8991_ainrmux_enum);
+
+/* RXVOICE */
+static const struct snd_kcontrol_new wm8991_dapm_rxvoice_controls[] = {
+	SOC_DAPM_SINGLE_TLV("LIN4RXN", WM8991_INPUT_MIXER5, WM8991_LR4BVOL_SHIFT,
+		WM8991_LR4BVOL_MASK, 0, in_mix_tlv),
+	SOC_DAPM_SINGLE_TLV("RIN4RXP", WM8991_INPUT_MIXER6, WM8991_RL4BVOL_SHIFT,
+		WM8991_RL4BVOL_MASK, 0, in_mix_tlv),
+};
+
+/* LOMIX */
+static const struct snd_kcontrol_new wm8991_dapm_lomix_controls[] = {
+	SOC_DAPM_SINGLE("LOMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LRBLO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LLBLO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LRI3LO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LLI3LO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LR12LO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LL12LO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOMIX Left DAC Switch", WM8991_OUTPUT_MIXER1,
+		WM8991_LDLO_BIT, 1, 0),
+};
+
+/* ROMIX */
+static const struct snd_kcontrol_new wm8991_dapm_romix_controls[] = {
+	SOC_DAPM_SINGLE("ROMIX Left ADC Bypass Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RLBRO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROMIX Right ADC Bypass Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RRBRO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROMIX LIN3 Bypass Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RLI3RO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROMIX RIN3 Bypass Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RRI3RO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROMIX LIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RL12RO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROMIX RIN12 PGA Bypass Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RR12RO_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROMIX Right DAC Switch", WM8991_OUTPUT_MIXER2,
+		WM8991_RDRO_BIT, 1, 0),
+};
+
+/* LONMIX */
+static const struct snd_kcontrol_new wm8991_dapm_lonmix_controls[] = {
+	SOC_DAPM_SINGLE("LONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1,
+		WM8991_LLOPGALON_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER1,
+		WM8991_LROPGALON_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LONMIX Inverted LOP Switch", WM8991_LINE_MIXER1,
+		WM8991_LOPLON_BIT, 1, 0),
+};
+
+/* LOPMIX */
+static const struct snd_kcontrol_new wm8991_dapm_lopmix_controls[] = {
+	SOC_DAPM_SINGLE("LOPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER1,
+		WM8991_LR12LOP_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER1,
+		WM8991_LL12LOP_BIT, 1, 0),
+	SOC_DAPM_SINGLE("LOPMIX Left Mixer PGA Switch", WM8991_LINE_MIXER1,
+		WM8991_LLOPGALOP_BIT, 1, 0),
+};
+
+/* RONMIX */
+static const struct snd_kcontrol_new wm8991_dapm_ronmix_controls[] = {
+	SOC_DAPM_SINGLE("RONMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2,
+		WM8991_RROPGARON_BIT, 1, 0),
+	SOC_DAPM_SINGLE("RONMIX Left Mixer PGA Switch", WM8991_LINE_MIXER2,
+		WM8991_RLOPGARON_BIT, 1, 0),
+	SOC_DAPM_SINGLE("RONMIX Inverted ROP Switch", WM8991_LINE_MIXER2,
+		WM8991_ROPRON_BIT, 1, 0),
+};
+
+/* ROPMIX */
+static const struct snd_kcontrol_new wm8991_dapm_ropmix_controls[] = {
+	SOC_DAPM_SINGLE("ROPMIX Left Mic Bypass Switch", WM8991_LINE_MIXER2,
+		WM8991_RL12ROP_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROPMIX Right Mic Bypass Switch", WM8991_LINE_MIXER2,
+		WM8991_RR12ROP_BIT, 1, 0),
+	SOC_DAPM_SINGLE("ROPMIX Right Mixer PGA Switch", WM8991_LINE_MIXER2,
+		WM8991_RROPGAROP_BIT, 1, 0),
+};
+
+/* OUT3MIX */
+static const struct snd_kcontrol_new wm8991_dapm_out3mix_controls[] = {
+	SOC_DAPM_SINGLE("OUT3MIX LIN4RXN Bypass Switch", WM8991_OUT3_4_MIXER,
+		WM8991_LI4O3_BIT, 1, 0),
+	SOC_DAPM_SINGLE("OUT3MIX Left Out PGA Switch", WM8991_OUT3_4_MIXER,
+		WM8991_LPGAO3_BIT, 1, 0),
+};
+
+/* OUT4MIX */
+static const struct snd_kcontrol_new wm8991_dapm_out4mix_controls[] = {
+	SOC_DAPM_SINGLE("OUT4MIX Right Out PGA Switch", WM8991_OUT3_4_MIXER,
+		WM8991_RPGAO4_BIT, 1, 0),
+	SOC_DAPM_SINGLE("OUT4MIX RIN4RXP Bypass Switch", WM8991_OUT3_4_MIXER,
+		WM8991_RI4O4_BIT, 1, 0),
+};
+
+/* SPKMIX */
+static const struct snd_kcontrol_new wm8991_dapm_spkmix_controls[] = {
+	SOC_DAPM_SINGLE("SPKMIX LIN2 Bypass Switch", WM8991_SPEAKER_MIXER,
+		WM8991_LI2SPK_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX LADC Bypass Switch", WM8991_SPEAKER_MIXER,
+		WM8991_LB2SPK_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX Left Mixer PGA Switch", WM8991_SPEAKER_MIXER,
+		WM8991_LOPGASPK_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX Left DAC Switch", WM8991_SPEAKER_MIXER,
+		WM8991_LDSPK_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX Right DAC Switch", WM8991_SPEAKER_MIXER,
+		WM8991_RDSPK_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX Right Mixer PGA Switch", WM8991_SPEAKER_MIXER,
+		WM8991_ROPGASPK_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX RADC Bypass Switch", WM8991_SPEAKER_MIXER,
+		WM8991_RL12ROP_BIT, 1, 0),
+	SOC_DAPM_SINGLE("SPKMIX RIN2 Bypass Switch", WM8991_SPEAKER_MIXER,
+		WM8991_RI2SPK_BIT, 1, 0),
+};
+
+static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
+	/* Input Side */
+	/* Input Lines */
+	SND_SOC_DAPM_INPUT("LIN1"),
+	SND_SOC_DAPM_INPUT("LIN2"),
+	SND_SOC_DAPM_INPUT("LIN3"),
+	SND_SOC_DAPM_INPUT("LIN4RXN"),
+	SND_SOC_DAPM_INPUT("RIN3"),
+	SND_SOC_DAPM_INPUT("RIN4RXP"),
+	SND_SOC_DAPM_INPUT("RIN1"),
+	SND_SOC_DAPM_INPUT("RIN2"),
+	SND_SOC_DAPM_INPUT("Internal ADC Source"),
+
+	/* DACs */
+	SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2,
+		WM8991_ADCL_ENA_BIT, 0),
+	SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8991_POWER_MANAGEMENT_2,
+		WM8991_ADCR_ENA_BIT, 0),
+
+	/* Input PGAs */
+	SND_SOC_DAPM_MIXER("LIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN12_ENA_BIT,
+		0, &wm8991_dapm_lin12_pga_controls[0],
+		ARRAY_SIZE(wm8991_dapm_lin12_pga_controls)),
+	SND_SOC_DAPM_MIXER("LIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_LIN34_ENA_BIT,
+		0, &wm8991_dapm_lin34_pga_controls[0],
+		ARRAY_SIZE(wm8991_dapm_lin34_pga_controls)),
+	SND_SOC_DAPM_MIXER("RIN12 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN12_ENA_BIT,
+		0, &wm8991_dapm_rin12_pga_controls[0],
+		ARRAY_SIZE(wm8991_dapm_rin12_pga_controls)),
+	SND_SOC_DAPM_MIXER("RIN34 PGA", WM8991_POWER_MANAGEMENT_2, WM8991_RIN34_ENA_BIT,
+		0, &wm8991_dapm_rin34_pga_controls[0],
+		ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)),
+
+	/* INMIXL */
+	SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0,
+		&wm8991_dapm_inmixl_controls[0],
+		ARRAY_SIZE(wm8991_dapm_inmixl_controls),
+		inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* AINLMUX */
+	SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0,
+		&wm8991_dapm_ainlmux_controls, inmixer_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* INMIXR */
+	SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0,
+		&wm8991_dapm_inmixr_controls[0],
+		ARRAY_SIZE(wm8991_dapm_inmixr_controls),
+		inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* AINRMUX */
+	SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0,
+		&wm8991_dapm_ainrmux_controls, inmixer_event,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+	/* Output Side */
+	/* DACs */
+	SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8991_POWER_MANAGEMENT_3,
+		WM8991_DACL_ENA_BIT, 0),
+	SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8991_POWER_MANAGEMENT_3,
+		WM8991_DACR_ENA_BIT, 0),
+
+	/* LOMIX */
+	SND_SOC_DAPM_MIXER_E("LOMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOMIX_ENA_BIT,
+		0, &wm8991_dapm_lomix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_lomix_controls),
+		outmixer_event, SND_SOC_DAPM_PRE_REG),
+
+	/* LONMIX */
+	SND_SOC_DAPM_MIXER("LONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LON_ENA_BIT, 0,
+		&wm8991_dapm_lonmix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_lonmix_controls)),
+
+	/* LOPMIX */
+	SND_SOC_DAPM_MIXER("LOPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_LOP_ENA_BIT, 0,
+		&wm8991_dapm_lopmix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_lopmix_controls)),
+
+	/* OUT3MIX */
+	SND_SOC_DAPM_MIXER("OUT3MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT3_ENA_BIT, 0,
+		&wm8991_dapm_out3mix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_out3mix_controls)),
+
+	/* SPKMIX */
+	SND_SOC_DAPM_MIXER_E("SPKMIX", WM8991_POWER_MANAGEMENT_1, WM8991_SPK_ENA_BIT, 0,
+		&wm8991_dapm_spkmix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_spkmix_controls), outmixer_event,
+		SND_SOC_DAPM_PRE_REG),
+
+	/* OUT4MIX */
+	SND_SOC_DAPM_MIXER("OUT4MIX", WM8991_POWER_MANAGEMENT_1, WM8991_OUT4_ENA_BIT, 0,
+		&wm8991_dapm_out4mix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_out4mix_controls)),
+
+	/* ROPMIX */
+	SND_SOC_DAPM_MIXER("ROPMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROP_ENA_BIT, 0,
+		&wm8991_dapm_ropmix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_ropmix_controls)),
+
+	/* RONMIX */
+	SND_SOC_DAPM_MIXER("RONMIX", WM8991_POWER_MANAGEMENT_3, WM8991_RON_ENA_BIT, 0,
+		&wm8991_dapm_ronmix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_ronmix_controls)),
+
+	/* ROMIX */
+	SND_SOC_DAPM_MIXER_E("ROMIX", WM8991_POWER_MANAGEMENT_3, WM8991_ROMIX_ENA_BIT,
+		0, &wm8991_dapm_romix_controls[0],
+		ARRAY_SIZE(wm8991_dapm_romix_controls),
+		outmixer_event, SND_SOC_DAPM_PRE_REG),
+
+	/* LOUT PGA */
+	SND_SOC_DAPM_PGA("LOUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_LOUT_ENA_BIT, 0,
+		NULL, 0),
+
+	/* ROUT PGA */
+	SND_SOC_DAPM_PGA("ROUT PGA", WM8991_POWER_MANAGEMENT_1, WM8991_ROUT_ENA_BIT, 0,
+		NULL, 0),
+
+	/* LOPGA */
+	SND_SOC_DAPM_PGA("LOPGA", WM8991_POWER_MANAGEMENT_3, WM8991_LOPGA_ENA_BIT, 0,
+		NULL, 0),
+
+	/* ROPGA */
+	SND_SOC_DAPM_PGA("ROPGA", WM8991_POWER_MANAGEMENT_3, WM8991_ROPGA_ENA_BIT, 0,
+		NULL, 0),
+
+	/* MICBIAS */
+	SND_SOC_DAPM_MICBIAS("MICBIAS", WM8991_POWER_MANAGEMENT_1,
+		WM8991_MICBIAS_ENA_BIT, 0),
+
+	SND_SOC_DAPM_OUTPUT("LON"),
+	SND_SOC_DAPM_OUTPUT("LOP"),
+	SND_SOC_DAPM_OUTPUT("OUT3"),
+	SND_SOC_DAPM_OUTPUT("LOUT"),
+	SND_SOC_DAPM_OUTPUT("SPKN"),
+	SND_SOC_DAPM_OUTPUT("SPKP"),
+	SND_SOC_DAPM_OUTPUT("ROUT"),
+	SND_SOC_DAPM_OUTPUT("OUT4"),
+	SND_SOC_DAPM_OUTPUT("ROP"),
+	SND_SOC_DAPM_OUTPUT("RON"),
+	SND_SOC_DAPM_OUTPUT("OUT"),
+
+	SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+	/* Make DACs turn on when playing even if not mixed into any outputs */
+	{"Internal DAC Sink", NULL, "Left DAC"},
+	{"Internal DAC Sink", NULL, "Right DAC"},
+
+	/* Make ADCs turn on when recording even if not mixed from any inputs */
+	{"Left ADC", NULL, "Internal ADC Source"},
+	{"Right ADC", NULL, "Internal ADC Source"},
+
+	/* Input Side */
+	/* LIN12 PGA */
+	{"LIN12 PGA", "LIN1 Switch", "LIN1"},
+	{"LIN12 PGA", "LIN2 Switch", "LIN2"},
+	/* LIN34 PGA */
+	{"LIN34 PGA", "LIN3 Switch", "LIN3"},
+	{"LIN34 PGA", "LIN4 Switch", "LIN4RXN"},
+	/* INMIXL */
+	{"INMIXL", "Record Left Volume", "LOMIX"},
+	{"INMIXL", "LIN2 Volume", "LIN2"},
+	{"INMIXL", "LINPGA12 Switch", "LIN12 PGA"},
+	{"INMIXL", "LINPGA34 Switch", "LIN34 PGA"},
+	/* AINLMUX */
+	{"AINLMUX", "INMIXL Mix", "INMIXL"},
+	{"AINLMUX", "DIFFINL Mix", "LIN12 PGA"},
+	{"AINLMUX", "DIFFINL Mix", "LIN34 PGA"},
+	{"AINLMUX", "RXVOICE Mix", "LIN4RXN"},
+	{"AINLMUX", "RXVOICE Mix", "RIN4RXP"},
+	/* ADC */
+	{"Left ADC", NULL, "AINLMUX"},
+
+	/* RIN12 PGA */
+	{"RIN12 PGA", "RIN1 Switch", "RIN1"},
+	{"RIN12 PGA", "RIN2 Switch", "RIN2"},
+	/* RIN34 PGA */
+	{"RIN34 PGA", "RIN3 Switch", "RIN3"},
+	{"RIN34 PGA", "RIN4 Switch", "RIN4RXP"},
+	/* INMIXL */
+	{"INMIXR", "Record Right Volume", "ROMIX"},
+	{"INMIXR", "RIN2 Volume", "RIN2"},
+	{"INMIXR", "RINPGA12 Switch", "RIN12 PGA"},
+	{"INMIXR", "RINPGA34 Switch", "RIN34 PGA"},
+	/* AINRMUX */
+	{"AINRMUX", "INMIXR Mix", "INMIXR"},
+	{"AINRMUX", "DIFFINR Mix", "RIN12 PGA"},
+	{"AINRMUX", "DIFFINR Mix", "RIN34 PGA"},
+	{"AINRMUX", "RXVOICE Mix", "LIN4RXN"},
+	{"AINRMUX", "RXVOICE Mix", "RIN4RXP"},
+	/* ADC */
+	{"Right ADC", NULL, "AINRMUX"},
+
+	/* LOMIX */
+	{"LOMIX", "LOMIX RIN3 Bypass Switch", "RIN3"},
+	{"LOMIX", "LOMIX LIN3 Bypass Switch", "LIN3"},
+	{"LOMIX", "LOMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
+	{"LOMIX", "LOMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
+	{"LOMIX", "LOMIX Right ADC Bypass Switch", "AINRMUX"},
+	{"LOMIX", "LOMIX Left ADC Bypass Switch", "AINLMUX"},
+	{"LOMIX", "LOMIX Left DAC Switch", "Left DAC"},
+
+	/* ROMIX */
+	{"ROMIX", "ROMIX RIN3 Bypass Switch", "RIN3"},
+	{"ROMIX", "ROMIX LIN3 Bypass Switch", "LIN3"},
+	{"ROMIX", "ROMIX LIN12 PGA Bypass Switch", "LIN12 PGA"},
+	{"ROMIX", "ROMIX RIN12 PGA Bypass Switch", "RIN12 PGA"},
+	{"ROMIX", "ROMIX Right ADC Bypass Switch", "AINRMUX"},
+	{"ROMIX", "ROMIX Left ADC Bypass Switch", "AINLMUX"},
+	{"ROMIX", "ROMIX Right DAC Switch", "Right DAC"},
+
+	/* SPKMIX */
+	{"SPKMIX", "SPKMIX LIN2 Bypass Switch", "LIN2"},
+	{"SPKMIX", "SPKMIX RIN2 Bypass Switch", "RIN2"},
+	{"SPKMIX", "SPKMIX LADC Bypass Switch", "AINLMUX"},
+	{"SPKMIX", "SPKMIX RADC Bypass Switch", "AINRMUX"},
+	{"SPKMIX", "SPKMIX Left Mixer PGA Switch", "LOPGA"},
+	{"SPKMIX", "SPKMIX Right Mixer PGA Switch", "ROPGA"},
+	{"SPKMIX", "SPKMIX Right DAC Switch", "Right DAC"},
+	{"SPKMIX", "SPKMIX Left DAC Switch", "Right DAC"},
+
+	/* LONMIX */
+	{"LONMIX", "LONMIX Left Mixer PGA Switch", "LOPGA"},
+	{"LONMIX", "LONMIX Right Mixer PGA Switch", "ROPGA"},
+	{"LONMIX", "LONMIX Inverted LOP Switch", "LOPMIX"},
+
+	/* LOPMIX */
+	{"LOPMIX", "LOPMIX Right Mic Bypass Switch", "RIN12 PGA"},
+	{"LOPMIX", "LOPMIX Left Mic Bypass Switch", "LIN12 PGA"},
+	{"LOPMIX", "LOPMIX Left Mixer PGA Switch", "LOPGA"},
+
+	/* OUT3MIX */
+	{"OUT3MIX", "OUT3MIX LIN4RXN Bypass Switch", "LIN4RXN"},
+	{"OUT3MIX", "OUT3MIX Left Out PGA Switch", "LOPGA"},
+
+	/* OUT4MIX */
+	{"OUT4MIX", "OUT4MIX Right Out PGA Switch", "ROPGA"},
+	{"OUT4MIX", "OUT4MIX RIN4RXP Bypass Switch", "RIN4RXP"},
+
+	/* RONMIX */
+	{"RONMIX", "RONMIX Right Mixer PGA Switch", "ROPGA"},
+	{"RONMIX", "RONMIX Left Mixer PGA Switch", "LOPGA"},
+	{"RONMIX", "RONMIX Inverted ROP Switch", "ROPMIX"},
+
+	/* ROPMIX */
+	{"ROPMIX", "ROPMIX Left Mic Bypass Switch", "LIN12 PGA"},
+	{"ROPMIX", "ROPMIX Right Mic Bypass Switch", "RIN12 PGA"},
+	{"ROPMIX", "ROPMIX Right Mixer PGA Switch", "ROPGA"},
+
+	/* Out Mixer PGAs */
+	{"LOPGA", NULL, "LOMIX"},
+	{"ROPGA", NULL, "ROMIX"},
+
+	{"LOUT PGA", NULL, "LOMIX"},
+	{"ROUT PGA", NULL, "ROMIX"},
+
+	/* Output Pins */
+	{"LON", NULL, "LONMIX"},
+	{"LOP", NULL, "LOPMIX"},
+	{"OUT", NULL, "OUT3MIX"},
+	{"LOUT", NULL, "LOUT PGA"},
+	{"SPKN", NULL, "SPKMIX"},
+	{"ROUT", NULL, "ROUT PGA"},
+	{"OUT4", NULL, "OUT4MIX"},
+	{"ROP", NULL, "ROPMIX"},
+	{"RON", NULL, "RONMIX"},
+};
+
+/* PLL divisors */
+struct _pll_div {
+	u32 div2;
+	u32 n;
+	u32 k;
+};
+
+/* The size in bits of the pll divide multiplied by 10
+ * to allow rounding later */
+#define FIXED_PLL_SIZE ((1 << 16) * 10)
+
+static void pll_factors(struct _pll_div *pll_div, unsigned int target,
+			unsigned int source)
+{
+	u64 Kpart;
+	unsigned int K, Ndiv, Nmod;
+
+
+	Ndiv = target / source;
+	if (Ndiv < 6) {
+		source >>= 1;
+		pll_div->div2 = 1;
+		Ndiv = target / source;
+	} else
+		pll_div->div2 = 0;
+
+	if ((Ndiv < 6) || (Ndiv > 12))
+		printk(KERN_WARNING
+		       "WM8991 N value outwith recommended range! N = %d\n", Ndiv);
+
+	pll_div->n = Ndiv;
+	Nmod = target % source;
+	Kpart = FIXED_PLL_SIZE * (long long)Nmod;
+
+	do_div(Kpart, source);
+
+	K = Kpart & 0xFFFFFFFF;
+
+	/* Check if we need to round */
+	if ((K % 10) >= 5)
+		K += 5;
+
+	/* Move down to proper range now rounding is done */
+	K /= 10;
+
+	pll_div->k = K;
+}
+
+static int wm8991_set_dai_pll(struct snd_soc_dai *codec_dai,
+			      int pll_id, int src, unsigned int freq_in, unsigned int freq_out)
+{
+	u16 reg;
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct _pll_div pll_div;
+
+	if (freq_in && freq_out) {
+		pll_factors(&pll_div, freq_out * 4, freq_in);
+
+		/* Turn on PLL */
+		reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
+		reg |= WM8991_PLL_ENA;
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg);
+
+		/* sysclk comes from PLL */
+		reg = snd_soc_read(codec, WM8991_CLOCKING_2);
+		snd_soc_write(codec, WM8991_CLOCKING_2, reg | WM8991_SYSCLK_SRC);
+
+		/* set up N , fractional mode and pre-divisor if neccessary */
+		snd_soc_write(codec, WM8991_PLL1, pll_div.n | WM8991_SDM |
+			      (pll_div.div2 ? WM8991_PRESCALE : 0));
+		snd_soc_write(codec, WM8991_PLL2, (u8)(pll_div.k>>8));
+		snd_soc_write(codec, WM8991_PLL3, (u8)(pll_div.k & 0xFF));
+	} else {
+		/* Turn on PLL */
+		reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
+		reg &= ~WM8991_PLL_ENA;
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg);
+	}
+	return 0;
+}
+
+/*
+ * Set's ADC and Voice DAC format.
+ */
+static int wm8991_set_dai_fmt(struct snd_soc_dai *codec_dai,
+			      unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 audio1, audio3;
+
+	audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1);
+	audio3 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_3);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		audio3 &= ~WM8991_AIF_MSTR1;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		audio3 |= WM8991_AIF_MSTR1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	audio1 &= ~WM8991_AIF_FMT_MASK;
+
+	/* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		audio1 |= WM8991_AIF_TMF_I2S;
+		audio1 &= ~WM8991_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		audio1 |= WM8991_AIF_TMF_RIGHTJ;
+		audio1 &= ~WM8991_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		audio1 |= WM8991_AIF_TMF_LEFTJ;
+		audio1 &= ~WM8991_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		audio1 |= WM8991_AIF_TMF_DSP;
+		audio1 &= ~WM8991_AIF_LRCLK_INV;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		audio1 |= WM8991_AIF_TMF_DSP | WM8991_AIF_LRCLK_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1);
+	snd_soc_write(codec, WM8991_AUDIO_INTERFACE_3, audio3);
+	return 0;
+}
+
+static int wm8991_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
+				 int div_id, int div)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	u16 reg;
+
+	switch (div_id) {
+	case WM8991_MCLK_DIV:
+		reg = snd_soc_read(codec, WM8991_CLOCKING_2) &
+		      ~WM8991_MCLK_DIV_MASK;
+		snd_soc_write(codec, WM8991_CLOCKING_2, reg | div);
+		break;
+	case WM8991_DACCLK_DIV:
+		reg = snd_soc_read(codec, WM8991_CLOCKING_2) &
+		      ~WM8991_DAC_CLKDIV_MASK;
+		snd_soc_write(codec, WM8991_CLOCKING_2, reg | div);
+		break;
+	case WM8991_ADCCLK_DIV:
+		reg = snd_soc_read(codec, WM8991_CLOCKING_2) &
+		      ~WM8991_ADC_CLKDIV_MASK;
+		snd_soc_write(codec, WM8991_CLOCKING_2, reg | div);
+		break;
+	case WM8991_BCLK_DIV:
+		reg = snd_soc_read(codec, WM8991_CLOCKING_1) &
+		      ~WM8991_BCLK_DIV_MASK;
+		snd_soc_write(codec, WM8991_CLOCKING_1, reg | div);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Set PCM DAI bit size and sample rate.
+ */
+static int wm8991_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;
+	u16 audio1 = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_1);
+
+	audio1 &= ~WM8991_AIF_WL_MASK;
+	/* bit size */
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		break;
+	case SNDRV_PCM_FORMAT_S20_3LE:
+		audio1 |= WM8991_AIF_WL_20BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		audio1 |= WM8991_AIF_WL_24BITS;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		audio1 |= WM8991_AIF_WL_32BITS;
+		break;
+	}
+
+	snd_soc_write(codec, WM8991_AUDIO_INTERFACE_1, audio1);
+	return 0;
+}
+
+static int wm8991_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	u16 val;
+
+	val  = snd_soc_read(codec, WM8991_DAC_CTRL) & ~WM8991_DAC_MUTE;
+	if (mute)
+		snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE);
+	else
+		snd_soc_write(codec, WM8991_DAC_CTRL, val);
+	return 0;
+}
+
+static int wm8991_set_bias_level(struct snd_soc_codec *codec,
+				 enum snd_soc_bias_level level)
+{
+	u16 val;
+
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+
+	case SND_SOC_BIAS_PREPARE:
+		/* VMID=2*50k */
+		val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) &
+		      ~WM8991_VMID_MODE_MASK;
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x2);
+		break;
+
+	case SND_SOC_BIAS_STANDBY:
+		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			snd_soc_cache_sync(codec);
+			/* Enable all output discharge bits */
+			snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE |
+				      WM8991_DIS_RLINE | WM8991_DIS_OUT3 |
+				      WM8991_DIS_OUT4 | WM8991_DIS_LOUT |
+				      WM8991_DIS_ROUT);
+
+			/* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
+			snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
+				      WM8991_BUFDCOPEN | WM8991_POBCTRL |
+				      WM8991_VMIDTOG);
+
+			/* Delay to allow output caps to discharge */
+			msleep(300);
+
+			/* Disable VMIDTOG */
+			snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
+				      WM8991_BUFDCOPEN | WM8991_POBCTRL);
+
+			/* disable all output discharge bits */
+			snd_soc_write(codec, WM8991_ANTIPOP1, 0);
+
+			/* Enable outputs */
+			snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1b00);
+
+			msleep(50);
+
+			/* Enable VMID at 2x50k */
+			snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f02);
+
+			msleep(100);
+
+			/* Enable VREF */
+			snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03);
+
+			msleep(600);
+
+			/* Enable BUFIOEN */
+			snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
+				      WM8991_BUFDCOPEN | WM8991_POBCTRL |
+				      WM8991_BUFIOEN);
+
+			/* Disable outputs */
+			snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x3);
+
+			/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+			snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_BUFIOEN);
+		}
+
+		/* VMID=2*250k */
+		val = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1) &
+		      ~WM8991_VMID_MODE_MASK;
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, val | 0x4);
+		break;
+
+	case SND_SOC_BIAS_OFF:
+		/* Enable POBCTRL and SOFT_ST */
+		snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
+			      WM8991_POBCTRL | WM8991_BUFIOEN);
+
+		/* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
+		snd_soc_write(codec, WM8991_ANTIPOP2, WM8991_SOFTST |
+			      WM8991_BUFDCOPEN | WM8991_POBCTRL |
+			      WM8991_BUFIOEN);
+
+		/* mute DAC */
+		val = snd_soc_read(codec, WM8991_DAC_CTRL);
+		snd_soc_write(codec, WM8991_DAC_CTRL, val | WM8991_DAC_MUTE);
+
+		/* Enable any disabled outputs */
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f03);
+
+		/* Disable VMID */
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x1f01);
+
+		msleep(300);
+
+		/* Enable all output discharge bits */
+		snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE |
+			      WM8991_DIS_RLINE | WM8991_DIS_OUT3 |
+			      WM8991_DIS_OUT4 | WM8991_DIS_LOUT |
+			      WM8991_DIS_ROUT);
+
+		/* Disable VREF */
+		snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, 0x0);
+
+		/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
+		snd_soc_write(codec, WM8991_ANTIPOP2, 0x0);
+		codec->cache_sync = 1;
+		break;
+	}
+
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+static int wm8991_suspend(struct snd_soc_codec *codec, pm_message_t state)
+{
+	wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int wm8991_resume(struct snd_soc_codec *codec)
+{
+	wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+	return 0;
+}
+
+/* power down chip */
+static int wm8991_remove(struct snd_soc_codec *codec)
+{
+	wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
+	return 0;
+}
+
+static int wm8991_probe(struct snd_soc_codec *codec)
+{
+	struct wm8991_priv *wm8991;
+	int ret;
+	unsigned int reg;
+
+	wm8991 = snd_soc_codec_get_drvdata(codec);
+
+	ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
+		return ret;
+	}
+
+	ret = wm8991_reset(codec);
+	if (ret < 0) {
+		dev_err(codec->dev, "Failed to issue reset\n");
+		return ret;
+	}
+
+	wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+	reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4);
+	snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1);
+
+	reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) &
+	      ~WM8991_GPIO1_SEL_MASK;
+	snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1);
+
+	reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1);
+	snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA|
+		      WM8991_VMID_MODE_MASK);
+
+	reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
+	snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA);
+
+	snd_soc_write(codec, WM8991_DAC_CTRL, 0);
+	snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
+	snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
+
+	snd_soc_add_controls(codec, wm8991_snd_controls,
+			     ARRAY_SIZE(wm8991_snd_controls));
+
+	snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
+				  ARRAY_SIZE(wm8991_dapm_widgets));
+	snd_soc_dapm_add_routes(&codec->dapm, audio_map,
+				ARRAY_SIZE(audio_map));
+	return 0;
+}
+
+#define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+			SNDRV_PCM_FMTBIT_S24_LE)
+
+static struct snd_soc_dai_ops wm8991_ops = {
+	.hw_params = wm8991_hw_params,
+	.digital_mute = wm8991_mute,
+	.set_fmt = wm8991_set_dai_fmt,
+	.set_clkdiv = wm8991_set_dai_clkdiv,
+	.set_pll = wm8991_set_dai_pll
+};
+
+/*
+ * The WM8991 supports 2 different and mutually exclusive DAI
+ * configurations.
+ *
+ * 1. ADC/DAC on Primary Interface
+ * 2. ADC on Primary Interface/DAC on secondary
+ */
+static struct snd_soc_dai_driver wm8991_dai = {
+	/* ADC/DAC on primary */
+	.name = "wm8991",
+	.id = 1,
+	.playback = {
+		.stream_name = "Playback",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = WM8991_FORMATS
+	},
+	.capture = {
+		.stream_name = "Capture",
+		.channels_min = 1,
+		.channels_max = 2,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = WM8991_FORMATS
+	},
+	.ops = &wm8991_ops
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_wm8991 = {
+	.probe = wm8991_probe,
+	.remove = wm8991_remove,
+	.suspend = wm8991_suspend,
+	.resume = wm8991_resume,
+	.set_bias_level = wm8991_set_bias_level,
+	.reg_cache_size = WM8991_MAX_REGISTER + 1,
+	.reg_word_size = sizeof(u16),
+	.reg_cache_default = wm8991_reg_defs
+};
+
+static __devinit int wm8991_i2c_probe(struct i2c_client *i2c,
+				      const struct i2c_device_id *id)
+{
+	struct wm8991_priv *wm8991;
+	int ret;
+
+	wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL);
+	if (!wm8991)
+		return -ENOMEM;
+
+	wm8991->control_type = SND_SOC_I2C;
+	i2c_set_clientdata(i2c, wm8991);
+
+	ret = snd_soc_register_codec(&i2c->dev,
+				     &soc_codec_dev_wm8991, &wm8991_dai, 1);
+	if (ret < 0)
+		kfree(wm8991);
+	return ret;
+}
+
+static __devexit int wm8991_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id wm8991_i2c_id[] = {
+	{ "wm8991", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id);
+
+static struct i2c_driver wm8991_i2c_driver = {
+	.driver = {
+		.name = "wm8991",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm8991_i2c_probe,
+	.remove = __devexit_p(wm8991_i2c_remove),
+	.id_table = wm8991_i2c_id,
+};
+
+static int __init wm8991_modinit(void)
+{
+	int ret;
+	ret = i2c_add_driver(&wm8991_i2c_driver);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n",
+		       ret);
+	}
+	return 0;
+}
+module_init(wm8991_modinit);
+
+static void __exit wm8991_exit(void)
+{
+	i2c_del_driver(&wm8991_i2c_driver);
+}
+module_exit(wm8991_exit);
+
+MODULE_DESCRIPTION("ASoC WM8991 driver");
+MODULE_AUTHOR("Graeme Gregory");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8991.h b/sound/soc/codecs/wm8991.h
new file mode 100644
index 0000000..8a942ef
--- /dev/null
+++ b/sound/soc/codecs/wm8991.h
@@ -0,0 +1,833 @@
+/*
+ * wm8991.h  --  audio driver for WM8991
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef _WM8991_H
+#define _WM8991_H
+
+/*
+ * Register values.
+ */
+#define WM8991_RESET                            0x00
+#define WM8991_POWER_MANAGEMENT_1               0x01
+#define WM8991_POWER_MANAGEMENT_2               0x02
+#define WM8991_POWER_MANAGEMENT_3               0x03
+#define WM8991_AUDIO_INTERFACE_1                0x04
+#define WM8991_AUDIO_INTERFACE_2                0x05
+#define WM8991_CLOCKING_1                       0x06
+#define WM8991_CLOCKING_2                       0x07
+#define WM8991_AUDIO_INTERFACE_3                0x08
+#define WM8991_AUDIO_INTERFACE_4                0x09
+#define WM8991_DAC_CTRL                         0x0A
+#define WM8991_LEFT_DAC_DIGITAL_VOLUME          0x0B
+#define WM8991_RIGHT_DAC_DIGITAL_VOLUME         0x0C
+#define WM8991_DIGITAL_SIDE_TONE                0x0D
+#define WM8991_ADC_CTRL                         0x0E
+#define WM8991_LEFT_ADC_DIGITAL_VOLUME          0x0F
+#define WM8991_RIGHT_ADC_DIGITAL_VOLUME         0x10
+#define WM8991_GPIO_CTRL_1                      0x12
+#define WM8991_GPIO1_GPIO2                      0x13
+#define WM8991_GPIO3_GPIO4                      0x14
+#define WM8991_GPIO5_GPIO6                      0x15
+#define WM8991_GPIOCTRL_2                       0x16
+#define WM8991_GPIO_POL                         0x17
+#define WM8991_LEFT_LINE_INPUT_1_2_VOLUME       0x18
+#define WM8991_LEFT_LINE_INPUT_3_4_VOLUME       0x19
+#define WM8991_RIGHT_LINE_INPUT_1_2_VOLUME      0x1A
+#define WM8991_RIGHT_LINE_INPUT_3_4_VOLUME      0x1B
+#define WM8991_LEFT_OUTPUT_VOLUME               0x1C
+#define WM8991_RIGHT_OUTPUT_VOLUME              0x1D
+#define WM8991_LINE_OUTPUTS_VOLUME              0x1E
+#define WM8991_OUT3_4_VOLUME                    0x1F
+#define WM8991_LEFT_OPGA_VOLUME                 0x20
+#define WM8991_RIGHT_OPGA_VOLUME                0x21
+#define WM8991_SPEAKER_VOLUME                   0x22
+#define WM8991_CLASSD1                          0x23
+#define WM8991_CLASSD3                          0x25
+#define WM8991_INPUT_MIXER1                     0x27
+#define WM8991_INPUT_MIXER2                     0x28
+#define WM8991_INPUT_MIXER3                     0x29
+#define WM8991_INPUT_MIXER4                     0x2A
+#define WM8991_INPUT_MIXER5                     0x2B
+#define WM8991_INPUT_MIXER6                     0x2C
+#define WM8991_OUTPUT_MIXER1                    0x2D
+#define WM8991_OUTPUT_MIXER2                    0x2E
+#define WM8991_OUTPUT_MIXER3                    0x2F
+#define WM8991_OUTPUT_MIXER4                    0x30
+#define WM8991_OUTPUT_MIXER5                    0x31
+#define WM8991_OUTPUT_MIXER6                    0x32
+#define WM8991_OUT3_4_MIXER                     0x33
+#define WM8991_LINE_MIXER1                      0x34
+#define WM8991_LINE_MIXER2                      0x35
+#define WM8991_SPEAKER_MIXER                    0x36
+#define WM8991_ADDITIONAL_CONTROL               0x37
+#define WM8991_ANTIPOP1                         0x38
+#define WM8991_ANTIPOP2                         0x39
+#define WM8991_MICBIAS                          0x3A
+#define WM8991_PLL1                             0x3C
+#define WM8991_PLL2                             0x3D
+#define WM8991_PLL3                             0x3E
+#define WM8991_INTDRIVBITS			0x3F
+
+#define WM8991_REGISTER_COUNT                   60
+#define WM8991_MAX_REGISTER                     0x3F
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Reset
+ */
+#define WM8991_SW_RESET_CHIP_ID_MASK            0xFFFF  /* SW_RESET_CHIP_ID - [15:0] */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8991_SPK_ENA                          0x1000  /* SPK_ENA */
+#define WM8991_SPK_ENA_BIT			12
+#define WM8991_OUT3_ENA                         0x0800  /* OUT3_ENA */
+#define WM8991_OUT3_ENA_BIT			11
+#define WM8991_OUT4_ENA                         0x0400  /* OUT4_ENA */
+#define WM8991_OUT4_ENA_BIT			10
+#define WM8991_LOUT_ENA                         0x0200  /* LOUT_ENA */
+#define WM8991_LOUT_ENA_BIT			9
+#define WM8991_ROUT_ENA                         0x0100  /* ROUT_ENA */
+#define WM8991_ROUT_ENA_BIT			8
+#define WM8991_MICBIAS_ENA                      0x0010  /* MICBIAS_ENA */
+#define WM8991_MICBIAS_ENA_BIT			4
+#define WM8991_VMID_MODE_MASK                   0x0006  /* VMID_MODE - [2:1] */
+#define WM8991_VREF_ENA                         0x0001  /* VREF_ENA */
+#define WM8991_VREF_ENA_BIT			0
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8991_PLL_ENA                          0x8000  /* PLL_ENA */
+#define WM8991_PLL_ENA_BIT			15
+#define WM8991_TSHUT_ENA                        0x4000  /* TSHUT_ENA */
+#define WM8991_TSHUT_ENA_BIT			14
+#define WM8991_TSHUT_OPDIS                      0x2000  /* TSHUT_OPDIS */
+#define WM8991_TSHUT_OPDIS_BIT			13
+#define WM8991_OPCLK_ENA                        0x0800  /* OPCLK_ENA */
+#define WM8991_OPCLK_ENA_BIT			11
+#define WM8991_AINL_ENA                         0x0200  /* AINL_ENA */
+#define WM8991_AINL_ENA_BIT			9
+#define WM8991_AINR_ENA                         0x0100  /* AINR_ENA */
+#define WM8991_AINR_ENA_BIT			8
+#define WM8991_LIN34_ENA                        0x0080  /* LIN34_ENA */
+#define WM8991_LIN34_ENA_BIT			7
+#define WM8991_LIN12_ENA                        0x0040  /* LIN12_ENA */
+#define WM8991_LIN12_ENA_BIT			6
+#define WM8991_RIN34_ENA                        0x0020  /* RIN34_ENA */
+#define WM8991_RIN34_ENA_BIT			5
+#define WM8991_RIN12_ENA                        0x0010  /* RIN12_ENA */
+#define WM8991_RIN12_ENA_BIT			4
+#define WM8991_ADCL_ENA                         0x0002  /* ADCL_ENA */
+#define WM8991_ADCL_ENA_BIT			1
+#define WM8991_ADCR_ENA                         0x0001  /* ADCR_ENA */
+#define WM8991_ADCR_ENA_BIT			0
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8991_LON_ENA                          0x2000  /* LON_ENA */
+#define WM8991_LON_ENA_BIT			13
+#define WM8991_LOP_ENA                          0x1000  /* LOP_ENA */
+#define WM8991_LOP_ENA_BIT			12
+#define WM8991_RON_ENA                          0x0800  /* RON_ENA */
+#define WM8991_RON_ENA_BIT			11
+#define WM8991_ROP_ENA                          0x0400  /* ROP_ENA */
+#define WM8991_ROP_ENA_BIT			10
+#define WM8991_LOPGA_ENA                        0x0080  /* LOPGA_ENA */
+#define WM8991_LOPGA_ENA_BIT			7
+#define WM8991_ROPGA_ENA                        0x0040  /* ROPGA_ENA */
+#define WM8991_ROPGA_ENA_BIT			6
+#define WM8991_LOMIX_ENA                        0x0020  /* LOMIX_ENA */
+#define WM8991_LOMIX_ENA_BIT			5
+#define WM8991_ROMIX_ENA                        0x0010  /* ROMIX_ENA */
+#define WM8991_ROMIX_ENA_BIT			4
+#define WM8991_DACL_ENA                         0x0002  /* DACL_ENA */
+#define WM8991_DACL_ENA_BIT			1
+#define WM8991_DACR_ENA                         0x0001  /* DACR_ENA */
+#define WM8991_DACR_ENA_BIT			0
+
+/*
+ * R4 (0x04) - Audio Interface (1)
+ */
+#define WM8991_AIFADCL_SRC                      0x8000  /* AIFADCL_SRC */
+#define WM8991_AIFADCR_SRC                      0x4000  /* AIFADCR_SRC */
+#define WM8991_AIFADC_TDM                       0x2000  /* AIFADC_TDM */
+#define WM8991_AIFADC_TDM_CHAN                  0x1000  /* AIFADC_TDM_CHAN */
+#define WM8991_AIF_BCLK_INV                     0x0100  /* AIF_BCLK_INV */
+#define WM8991_AIF_LRCLK_INV                    0x0080  /* AIF_LRCLK_INV */
+#define WM8991_AIF_WL_MASK                      0x0060  /* AIF_WL - [6:5] */
+#define WM8991_AIF_WL_16BITS			(0 << 5)
+#define WM8991_AIF_WL_20BITS			(1 << 5)
+#define WM8991_AIF_WL_24BITS			(2 << 5)
+#define WM8991_AIF_WL_32BITS			(3 << 5)
+#define WM8991_AIF_FMT_MASK                     0x0018  /* AIF_FMT - [4:3] */
+#define WM8991_AIF_TMF_RIGHTJ			(0 << 3)
+#define WM8991_AIF_TMF_LEFTJ			(1 << 3)
+#define WM8991_AIF_TMF_I2S			(2 << 3)
+#define WM8991_AIF_TMF_DSP			(3 << 3)
+
+/*
+ * R5 (0x05) - Audio Interface (2)
+ */
+#define WM8991_DACL_SRC                         0x8000  /* DACL_SRC */
+#define WM8991_DACR_SRC                         0x4000  /* DACR_SRC */
+#define WM8991_AIFDAC_TDM                       0x2000  /* AIFDAC_TDM */
+#define WM8991_AIFDAC_TDM_CHAN                  0x1000  /* AIFDAC_TDM_CHAN */
+#define WM8991_DAC_BOOST_MASK                   0x0C00  /* DAC_BOOST - [11:10] */
+#define WM8991_DAC_COMP                         0x0010  /* DAC_COMP */
+#define WM8991_DAC_COMPMODE                     0x0008  /* DAC_COMPMODE */
+#define WM8991_ADC_COMP                         0x0004  /* ADC_COMP */
+#define WM8991_ADC_COMPMODE                     0x0002  /* ADC_COMPMODE */
+#define WM8991_LOOPBACK                         0x0001  /* LOOPBACK */
+
+/*
+ * R6 (0x06) - Clocking (1)
+ */
+#define WM8991_TOCLK_RATE                       0x8000  /* TOCLK_RATE */
+#define WM8991_TOCLK_ENA                        0x4000  /* TOCLK_ENA */
+#define WM8991_OPCLKDIV_MASK                    0x1E00  /* OPCLKDIV - [12:9] */
+#define WM8991_DCLKDIV_MASK                     0x01C0  /* DCLKDIV - [8:6] */
+#define WM8991_BCLK_DIV_MASK                    0x001E  /* BCLK_DIV - [4:1] */
+#define WM8991_BCLK_DIV_1			(0x0 << 1)
+#define WM8991_BCLK_DIV_1_5			(0x1 << 1)
+#define WM8991_BCLK_DIV_2			(0x2 << 1)
+#define WM8991_BCLK_DIV_3			(0x3 << 1)
+#define WM8991_BCLK_DIV_4			(0x4 << 1)
+#define WM8991_BCLK_DIV_5_5			(0x5 << 1)
+#define WM8991_BCLK_DIV_6			(0x6 << 1)
+#define WM8991_BCLK_DIV_8			(0x7 << 1)
+#define WM8991_BCLK_DIV_11			(0x8 << 1)
+#define WM8991_BCLK_DIV_12			(0x9 << 1)
+#define WM8991_BCLK_DIV_16			(0xA << 1)
+#define WM8991_BCLK_DIV_22			(0xB << 1)
+#define WM8991_BCLK_DIV_24			(0xC << 1)
+#define WM8991_BCLK_DIV_32			(0xD << 1)
+#define WM8991_BCLK_DIV_44			(0xE << 1)
+#define WM8991_BCLK_DIV_48			(0xF << 1)
+
+/*
+ * R7 (0x07) - Clocking (2)
+ */
+#define WM8991_MCLK_SRC                         0x8000  /* MCLK_SRC */
+#define WM8991_SYSCLK_SRC                       0x4000  /* SYSCLK_SRC */
+#define WM8991_CLK_FORCE                        0x2000  /* CLK_FORCE */
+#define WM8991_MCLK_DIV_MASK                    0x1800  /* MCLK_DIV - [12:11] */
+#define WM8991_MCLK_DIV_1			(0 << 11)
+#define WM8991_MCLK_DIV_2			( 2 << 11)
+#define WM8991_MCLK_INV                         0x0400  /* MCLK_INV */
+#define WM8991_ADC_CLKDIV_MASK                  0x00E0  /* ADC_CLKDIV - [7:5] */
+#define WM8991_ADC_CLKDIV_1			(0 << 5)
+#define WM8991_ADC_CLKDIV_1_5			(1 << 5)
+#define WM8991_ADC_CLKDIV_2			(2 << 5)
+#define WM8991_ADC_CLKDIV_3			(3 << 5)
+#define WM8991_ADC_CLKDIV_4			(4 << 5)
+#define WM8991_ADC_CLKDIV_5_5			(5 << 5)
+#define WM8991_ADC_CLKDIV_6			(6 << 5)
+#define WM8991_DAC_CLKDIV_MASK                  0x001C  /* DAC_CLKDIV - [4:2] */
+#define WM8991_DAC_CLKDIV_1			(0 << 2)
+#define WM8991_DAC_CLKDIV_1_5			(1 << 2)
+#define WM8991_DAC_CLKDIV_2			(2 << 2)
+#define WM8991_DAC_CLKDIV_3			(3 << 2)
+#define WM8991_DAC_CLKDIV_4			(4 << 2)
+#define WM8991_DAC_CLKDIV_5_5			(5 << 2)
+#define WM8991_DAC_CLKDIV_6			(6 << 2)
+
+/*
+ * R8 (0x08) - Audio Interface (3)
+ */
+#define WM8991_AIF_MSTR1                        0x8000  /* AIF_MSTR1 */
+#define WM8991_AIF_MSTR2                        0x4000  /* AIF_MSTR2 */
+#define WM8991_AIF_SEL                          0x2000  /* AIF_SEL */
+#define WM8991_ADCLRC_DIR                       0x0800  /* ADCLRC_DIR */
+#define WM8991_ADCLRC_RATE_MASK                 0x07FF  /* ADCLRC_RATE - [10:0] */
+
+/*
+ * R9 (0x09) - Audio Interface (4)
+ */
+#define WM8991_ALRCGPIO1                        0x8000  /* ALRCGPIO1 */
+#define WM8991_ALRCBGPIO6                       0x4000  /* ALRCBGPIO6 */
+#define WM8991_AIF_TRIS                         0x2000  /* AIF_TRIS */
+#define WM8991_DACLRC_DIR                       0x0800  /* DACLRC_DIR */
+#define WM8991_DACLRC_RATE_MASK                 0x07FF  /* DACLRC_RATE - [10:0] */
+
+/*
+ * R10 (0x0A) - DAC CTRL
+ */
+#define WM8991_AIF_LRCLKRATE                    0x0400  /* AIF_LRCLKRATE */
+#define WM8991_DAC_MONO                         0x0200  /* DAC_MONO */
+#define WM8991_DAC_SB_FILT                      0x0100  /* DAC_SB_FILT */
+#define WM8991_DAC_MUTERATE                     0x0080  /* DAC_MUTERATE */
+#define WM8991_DAC_MUTEMODE                     0x0040  /* DAC_MUTEMODE */
+#define WM8991_DEEMP_MASK                       0x0030  /* DEEMP - [5:4] */
+#define WM8991_DAC_MUTE                         0x0004  /* DAC_MUTE */
+#define WM8991_DACL_DATINV                      0x0002  /* DACL_DATINV */
+#define WM8991_DACR_DATINV                      0x0001  /* DACR_DATINV */
+
+/*
+ * R11 (0x0B) - Left DAC Digital Volume
+ */
+#define WM8991_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8991_DACL_VOL_MASK                    0x00FF  /* DACL_VOL - [7:0] */
+#define WM8991_DACL_VOL_SHIFT			0
+/*
+ * R12 (0x0C) - Right DAC Digital Volume
+ */
+#define WM8991_DAC_VU                           0x0100  /* DAC_VU */
+#define WM8991_DACR_VOL_MASK                    0x00FF  /* DACR_VOL - [7:0] */
+#define WM8991_DACR_VOL_SHIFT			0
+/*
+ * R13 (0x0D) - Digital Side Tone
+ */
+#define WM8991_ADCL_DAC_SVOL_MASK               0x0F  /* ADCL_DAC_SVOL - [12:9] */
+#define WM8991_ADCL_DAC_SVOL_SHIFT		9
+#define WM8991_ADCR_DAC_SVOL_MASK               0x0F  /* ADCR_DAC_SVOL - [8:5] */
+#define WM8991_ADCR_DAC_SVOL_SHIFT		5
+#define WM8991_ADC_TO_DACL_MASK                 0x03  /* ADC_TO_DACL - [3:2] */
+#define WM8991_ADC_TO_DACL_SHIFT		2
+#define WM8991_ADC_TO_DACR_MASK                 0x03  /* ADC_TO_DACR - [1:0] */
+#define WM8991_ADC_TO_DACR_SHIFT		0
+
+/*
+ * R14 (0x0E) - ADC CTRL
+ */
+#define WM8991_ADC_HPF_ENA                      0x0100  /* ADC_HPF_ENA */
+#define WM8991_ADC_HPF_ENA_BIT			8
+#define WM8991_ADC_HPF_CUT_MASK                 0x03  /* ADC_HPF_CUT - [6:5] */
+#define WM8991_ADC_HPF_CUT_SHIFT		5
+#define WM8991_ADCL_DATINV                      0x0002  /* ADCL_DATINV */
+#define WM8991_ADCL_DATINV_BIT			1
+#define WM8991_ADCR_DATINV                      0x0001  /* ADCR_DATINV */
+#define WM8991_ADCR_DATINV_BIT			0
+
+/*
+ * R15 (0x0F) - Left ADC Digital Volume
+ */
+#define WM8991_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8991_ADCL_VOL_MASK                    0x00FF  /* ADCL_VOL - [7:0] */
+#define WM8991_ADCL_VOL_SHIFT			0
+
+/*
+ * R16 (0x10) - Right ADC Digital Volume
+ */
+#define WM8991_ADC_VU                           0x0100  /* ADC_VU */
+#define WM8991_ADCR_VOL_MASK                    0x00FF  /* ADCR_VOL - [7:0] */
+#define WM8991_ADCR_VOL_SHIFT			0
+
+/*
+ * R18 (0x12) - GPIO CTRL 1
+ */
+#define WM8991_IRQ                              0x1000  /* IRQ */
+#define WM8991_TEMPOK                           0x0800  /* TEMPOK */
+#define WM8991_MICSHRT                          0x0400  /* MICSHRT */
+#define WM8991_MICDET                           0x0200  /* MICDET */
+#define WM8991_PLL_LCK                          0x0100  /* PLL_LCK */
+#define WM8991_GPI8_STATUS                      0x0080  /* GPI8_STATUS */
+#define WM8991_GPI7_STATUS                      0x0040  /* GPI7_STATUS */
+#define WM8991_GPIO6_STATUS                     0x0020  /* GPIO6_STATUS */
+#define WM8991_GPIO5_STATUS                     0x0010  /* GPIO5_STATUS */
+#define WM8991_GPIO4_STATUS                     0x0008  /* GPIO4_STATUS */
+#define WM8991_GPIO3_STATUS                     0x0004  /* GPIO3_STATUS */
+#define WM8991_GPIO2_STATUS                     0x0002  /* GPIO2_STATUS */
+#define WM8991_GPIO1_STATUS                     0x0001  /* GPIO1_STATUS */
+
+/*
+ * R19 (0x13) - GPIO1 & GPIO2
+ */
+#define WM8991_GPIO2_DEB_ENA                    0x8000  /* GPIO2_DEB_ENA */
+#define WM8991_GPIO2_IRQ_ENA                    0x4000  /* GPIO2_IRQ_ENA */
+#define WM8991_GPIO2_PU                         0x2000  /* GPIO2_PU */
+#define WM8991_GPIO2_PD                         0x1000  /* GPIO2_PD */
+#define WM8991_GPIO2_SEL_MASK                   0x0F00  /* GPIO2_SEL - [11:8] */
+#define WM8991_GPIO1_DEB_ENA                    0x0080  /* GPIO1_DEB_ENA */
+#define WM8991_GPIO1_IRQ_ENA                    0x0040  /* GPIO1_IRQ_ENA */
+#define WM8991_GPIO1_PU                         0x0020  /* GPIO1_PU */
+#define WM8991_GPIO1_PD                         0x0010  /* GPIO1_PD */
+#define WM8991_GPIO1_SEL_MASK                   0x000F  /* GPIO1_SEL - [3:0] */
+
+/*
+ * R20 (0x14) - GPIO3 & GPIO4
+ */
+#define WM8991_GPIO4_DEB_ENA                    0x8000  /* GPIO4_DEB_ENA */
+#define WM8991_GPIO4_IRQ_ENA                    0x4000  /* GPIO4_IRQ_ENA */
+#define WM8991_GPIO4_PU                         0x2000  /* GPIO4_PU */
+#define WM8991_GPIO4_PD                         0x1000  /* GPIO4_PD */
+#define WM8991_GPIO4_SEL_MASK                   0x0F00  /* GPIO4_SEL - [11:8] */
+#define WM8991_GPIO3_DEB_ENA                    0x0080  /* GPIO3_DEB_ENA */
+#define WM8991_GPIO3_IRQ_ENA                    0x0040  /* GPIO3_IRQ_ENA */
+#define WM8991_GPIO3_PU                         0x0020  /* GPIO3_PU */
+#define WM8991_GPIO3_PD                         0x0010  /* GPIO3_PD */
+#define WM8991_GPIO3_SEL_MASK                   0x000F  /* GPIO3_SEL - [3:0] */
+
+/*
+ * R21 (0x15) - GPIO5 & GPIO6
+ */
+#define WM8991_GPIO6_DEB_ENA                    0x8000  /* GPIO6_DEB_ENA */
+#define WM8991_GPIO6_IRQ_ENA                    0x4000  /* GPIO6_IRQ_ENA */
+#define WM8991_GPIO6_PU                         0x2000  /* GPIO6_PU */
+#define WM8991_GPIO6_PD                         0x1000  /* GPIO6_PD */
+#define WM8991_GPIO6_SEL_MASK                   0x0F00  /* GPIO6_SEL - [11:8] */
+#define WM8991_GPIO5_DEB_ENA                    0x0080  /* GPIO5_DEB_ENA */
+#define WM8991_GPIO5_IRQ_ENA                    0x0040  /* GPIO5_IRQ_ENA */
+#define WM8991_GPIO5_PU                         0x0020  /* GPIO5_PU */
+#define WM8991_GPIO5_PD                         0x0010  /* GPIO5_PD */
+#define WM8991_GPIO5_SEL_MASK                   0x000F  /* GPIO5_SEL - [3:0] */
+
+/*
+ * R22 (0x16) - GPIOCTRL 2
+ */
+#define WM8991_RD_3W_ENA                        0x8000  /* RD_3W_ENA */
+#define WM8991_MODE_3W4W                        0x4000  /* MODE_3W4W */
+#define WM8991_TEMPOK_IRQ_ENA                   0x0800  /* TEMPOK_IRQ_ENA */
+#define WM8991_MICSHRT_IRQ_ENA                  0x0400  /* MICSHRT_IRQ_ENA */
+#define WM8991_MICDET_IRQ_ENA                   0x0200  /* MICDET_IRQ_ENA */
+#define WM8991_PLL_LCK_IRQ_ENA                  0x0100  /* PLL_LCK_IRQ_ENA */
+#define WM8991_GPI8_DEB_ENA                     0x0080  /* GPI8_DEB_ENA */
+#define WM8991_GPI8_IRQ_ENA                     0x0040  /* GPI8_IRQ_ENA */
+#define WM8991_GPI8_ENA                         0x0010  /* GPI8_ENA */
+#define WM8991_GPI7_DEB_ENA                     0x0008  /* GPI7_DEB_ENA */
+#define WM8991_GPI7_IRQ_ENA                     0x0004  /* GPI7_IRQ_ENA */
+#define WM8991_GPI7_ENA                         0x0001  /* GPI7_ENA */
+
+/*
+ * R23 (0x17) - GPIO_POL
+ */
+#define WM8991_IRQ_INV                          0x1000  /* IRQ_INV */
+#define WM8991_TEMPOK_POL                       0x0800  /* TEMPOK_POL */
+#define WM8991_MICSHRT_POL                      0x0400  /* MICSHRT_POL */
+#define WM8991_MICDET_POL                       0x0200  /* MICDET_POL */
+#define WM8991_PLL_LCK_POL                      0x0100  /* PLL_LCK_POL */
+#define WM8991_GPI8_POL                         0x0080  /* GPI8_POL */
+#define WM8991_GPI7_POL                         0x0040  /* GPI7_POL */
+#define WM8991_GPIO6_POL                        0x0020  /* GPIO6_POL */
+#define WM8991_GPIO5_POL                        0x0010  /* GPIO5_POL */
+#define WM8991_GPIO4_POL                        0x0008  /* GPIO4_POL */
+#define WM8991_GPIO3_POL                        0x0004  /* GPIO3_POL */
+#define WM8991_GPIO2_POL                        0x0002  /* GPIO2_POL */
+#define WM8991_GPIO1_POL                        0x0001  /* GPIO1_POL */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8991_IPVU                             0x0100  /* IPVU */
+#define WM8991_LI12MUTE                         0x0080  /* LI12MUTE */
+#define WM8991_LI12MUTE_BIT			7
+#define WM8991_LI12ZC                           0x0040  /* LI12ZC */
+#define WM8991_LI12ZC_BIT			6
+#define WM8991_LIN12VOL_MASK                    0x001F  /* LIN12VOL - [4:0] */
+#define WM8991_LIN12VOL_SHIFT			0
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8991_IPVU                             0x0100  /* IPVU */
+#define WM8991_LI34MUTE                         0x0080  /* LI34MUTE */
+#define WM8991_LI34MUTE_BIT			7
+#define WM8991_LI34ZC                           0x0040  /* LI34ZC */
+#define WM8991_LI34ZC_BIT			6
+#define WM8991_LIN34VOL_MASK                    0x001F  /* LIN34VOL - [4:0] */
+#define WM8991_LIN34VOL_SHIFT			0
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8991_IPVU                             0x0100  /* IPVU */
+#define WM8991_RI12MUTE                         0x0080  /* RI12MUTE */
+#define WM8991_RI12MUTE_BIT			7
+#define WM8991_RI12ZC                           0x0040  /* RI12ZC */
+#define WM8991_RI12ZC_BIT			6
+#define WM8991_RIN12VOL_MASK                    0x001F  /* RIN12VOL - [4:0] */
+#define WM8991_RIN12VOL_SHIFT			0
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8991_IPVU                             0x0100  /* IPVU */
+#define WM8991_RI34MUTE                         0x0080  /* RI34MUTE */
+#define WM8991_RI34MUTE_BIT			7
+#define WM8991_RI34ZC                           0x0040  /* RI34ZC */
+#define WM8991_RI34ZC_BIT			6
+#define WM8991_RIN34VOL_MASK                    0x001F  /* RIN34VOL - [4:0] */
+#define WM8991_RIN34VOL_SHIFT			0
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8991_OPVU                             0x0100  /* OPVU */
+#define WM8991_LOZC                             0x0080  /* LOZC */
+#define WM8991_LOZC_BIT				7
+#define WM8991_LOUTVOL_MASK                     0x007F  /* LOUTVOL - [6:0] */
+#define WM8991_LOUTVOL_SHIFT			0
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8991_OPVU                             0x0100  /* OPVU */
+#define WM8991_ROZC                             0x0080  /* ROZC */
+#define WM8991_ROZC_BIT				7
+#define WM8991_ROUTVOL_MASK                     0x007F  /* ROUTVOL - [6:0] */
+#define WM8991_ROUTVOL_SHIFT			0
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8991_LONMUTE                          0x0040  /* LONMUTE */
+#define WM8991_LONMUTE_BIT			6
+#define WM8991_LOPMUTE                          0x0020  /* LOPMUTE */
+#define WM8991_LOPMUTE_BIT			5
+#define WM8991_LOATTN                           0x0010  /* LOATTN */
+#define WM8991_LOATTN_BIT			4
+#define WM8991_RONMUTE                          0x0004  /* RONMUTE */
+#define WM8991_RONMUTE_BIT			2
+#define WM8991_ROPMUTE                          0x0002  /* ROPMUTE */
+#define WM8991_ROPMUTE_BIT			1
+#define WM8991_ROATTN                           0x0001  /* ROATTN */
+#define WM8991_ROATTN_BIT			0
+
+/*
+ * R31 (0x1F) - Out3/4 Volume
+ */
+#define WM8991_OUT3MUTE                         0x0020  /* OUT3MUTE */
+#define WM8991_OUT3MUTE_BIT			5
+#define WM8991_OUT3ATTN                         0x0010  /* OUT3ATTN */
+#define WM8991_OUT3ATTN_BIT			4
+#define WM8991_OUT4MUTE                         0x0002  /* OUT4MUTE */
+#define WM8991_OUT4MUTE_BIT			1
+#define WM8991_OUT4ATTN                         0x0001  /* OUT4ATTN */
+#define WM8991_OUT4ATTN_BIT			0
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8991_OPVU                             0x0100  /* OPVU */
+#define WM8991_LOPGAZC                          0x0080  /* LOPGAZC */
+#define WM8991_LOPGAZC_BIT			7
+#define WM8991_LOPGAVOL_MASK                    0x007F  /* LOPGAVOL - [6:0] */
+#define WM8991_LOPGAVOL_SHIFT			0
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8991_OPVU                             0x0100  /* OPVU */
+#define WM8991_ROPGAZC                          0x0080  /* ROPGAZC */
+#define WM8991_ROPGAZC_BIT			7
+#define WM8991_ROPGAVOL_MASK                    0x007F  /* ROPGAVOL - [6:0] */
+#define WM8991_ROPGAVOL_SHIFT			0
+/*
+ * R34 (0x22) - Speaker Volume
+ */
+#define WM8991_SPKVOL_MASK                      0x0003  /* SPKVOL - [1:0] */
+#define WM8991_SPKVOL_SHIFT			0
+
+/*
+ * R35 (0x23) - ClassD1
+ */
+#define WM8991_CDMODE                           0x0100  /* CDMODE */
+#define WM8991_CDMODE_BIT			8
+
+/*
+ * R37 (0x25) - ClassD3
+ */
+#define WM8991_DCGAIN_MASK                      0x0007  /* DCGAIN - [5:3] */
+#define WM8991_DCGAIN_SHIFT			3
+#define WM8991_ACGAIN_MASK                      0x0007  /* ACGAIN - [2:0] */
+#define WM8991_ACGAIN_SHIFT			0
+/*
+ * R39 (0x27) - Input Mixer1
+ */
+#define WM8991_AINLMODE_MASK                    0x000C  /* AINLMODE - [3:2] */
+#define WM8991_AINLMODE_SHIFT			2
+#define WM8991_AINRMODE_MASK                    0x0003  /* AINRMODE - [1:0] */
+#define WM8991_AINRMODE_SHIFT			0
+
+/*
+ * R40 (0x28) - Input Mixer2
+ */
+#define WM8991_LMP4								0x0080	/* LMP4 */
+#define WM8991_LMP4_BIT                         7		/* LMP4 */
+#define WM8991_LMN3                             0x0040  /* LMN3 */
+#define WM8991_LMN3_BIT                         6       /* LMN3 */
+#define WM8991_LMP2                             0x0020  /* LMP2 */
+#define WM8991_LMP2_BIT                         5       /* LMP2 */
+#define WM8991_LMN1                             0x0010  /* LMN1 */
+#define WM8991_LMN1_BIT                         4       /* LMN1 */
+#define WM8991_RMP4                             0x0008  /* RMP4 */
+#define WM8991_RMP4_BIT                         3       /* RMP4 */
+#define WM8991_RMN3                             0x0004  /* RMN3 */
+#define WM8991_RMN3_BIT                         2       /* RMN3 */
+#define WM8991_RMP2                             0x0002  /* RMP2 */
+#define WM8991_RMP2_BIT                         1       /* RMP2 */
+#define WM8991_RMN1                             0x0001  /* RMN1 */
+#define WM8991_RMN1_BIT                         0       /* RMN1 */
+
+/*
+ * R41 (0x29) - Input Mixer3
+ */
+#define WM8991_L34MNB                           0x0100  /* L34MNB */
+#define WM8991_L34MNB_BIT			8
+#define WM8991_L34MNBST                         0x0080  /* L34MNBST */
+#define WM8991_L34MNBST_BIT			7
+#define WM8991_L12MNB                           0x0020  /* L12MNB */
+#define WM8991_L12MNB_BIT			5
+#define WM8991_L12MNBST                         0x0010  /* L12MNBST */
+#define WM8991_L12MNBST_BIT			4
+#define WM8991_LDBVOL_MASK                      0x0007  /* LDBVOL - [2:0] */
+#define WM8991_LDBVOL_SHIFT			0
+
+/*
+ * R42 (0x2A) - Input Mixer4
+ */
+#define WM8991_R34MNB                           0x0100  /* R34MNB */
+#define WM8991_R34MNB_BIT			8
+#define WM8991_R34MNBST                         0x0080  /* R34MNBST */
+#define WM8991_R34MNBST_BIT			7
+#define WM8991_R12MNB                           0x0020  /* R12MNB */
+#define WM8991_R12MNB_BIT			5
+#define WM8991_R12MNBST                         0x0010  /* R12MNBST */
+#define WM8991_R12MNBST_BIT			4
+#define WM8991_RDBVOL_MASK                      0x0007  /* RDBVOL - [2:0] */
+#define WM8991_RDBVOL_SHIFT			0
+
+/*
+ * R43 (0x2B) - Input Mixer5
+ */
+#define WM8991_LI2BVOL_MASK                     0x07  /* LI2BVOL - [8:6] */
+#define WM8991_LI2BVOL_SHIFT			6
+#define WM8991_LR4BVOL_MASK                     0x07  /* LR4BVOL - [5:3] */
+#define WM8991_LR4BVOL_SHIFT			3
+#define WM8991_LL4BVOL_MASK                     0x07  /* LL4BVOL - [2:0] */
+#define WM8991_LL4BVOL_SHIFT			0
+
+/*
+ * R44 (0x2C) - Input Mixer6
+ */
+#define WM8991_RI2BVOL_MASK                     0x07  /* RI2BVOL - [8:6] */
+#define WM8991_RI2BVOL_SHIFT			6
+#define WM8991_RL4BVOL_MASK                     0x07  /* RL4BVOL - [5:3] */
+#define WM8991_RL4BVOL_SHIFT			3
+#define WM8991_RR4BVOL_MASK                     0x07  /* RR4BVOL - [2:0] */
+#define WM8991_RR4BVOL_SHIFT			0
+
+/*
+ * R45 (0x2D) - Output Mixer1
+ */
+#define WM8991_LRBLO                            0x0080  /* LRBLO */
+#define WM8991_LRBLO_BIT			7
+#define WM8991_LLBLO                            0x0040  /* LLBLO */
+#define WM8991_LLBLO_BIT			6
+#define WM8991_LRI3LO                           0x0020  /* LRI3LO */
+#define WM8991_LRI3LO_BIT			5
+#define WM8991_LLI3LO                           0x0010  /* LLI3LO */
+#define WM8991_LLI3LO_BIT			4
+#define WM8991_LR12LO                           0x0008  /* LR12LO */
+#define WM8991_LR12LO_BIT			3
+#define WM8991_LL12LO                           0x0004  /* LL12LO */
+#define WM8991_LL12LO_BIT			2
+#define WM8991_LDLO                             0x0001  /* LDLO */
+#define WM8991_LDLO_BIT				0
+
+/*
+ * R46 (0x2E) - Output Mixer2
+ */
+#define WM8991_RLBRO                            0x0080  /* RLBRO */
+#define WM8991_RLBRO_BIT			7
+#define WM8991_RRBRO                            0x0040  /* RRBRO */
+#define WM8991_RRBRO_BIT			6
+#define WM8991_RLI3RO                           0x0020  /* RLI3RO */
+#define WM8991_RLI3RO_BIT			5
+#define WM8991_RRI3RO                           0x0010  /* RRI3RO */
+#define WM8991_RRI3RO_BIT			4
+#define WM8991_RL12RO                           0x0008  /* RL12RO */
+#define WM8991_RL12RO_BIT			3
+#define WM8991_RR12RO                           0x0004  /* RR12RO */
+#define WM8991_RR12RO_BIT			2
+#define WM8991_RDRO                             0x0001  /* RDRO */
+#define WM8991_RDRO_BIT				0
+
+/*
+ * R47 (0x2F) - Output Mixer3
+ */
+#define WM8991_LLI3LOVOL_MASK                   0x07  /* LLI3LOVOL - [8:6] */
+#define WM8991_LLI3LOVOL_SHIFT			6
+#define WM8991_LR12LOVOL_MASK                   0x07  /* LR12LOVOL - [5:3] */
+#define WM8991_LR12LOVOL_SHIFT			3
+#define WM8991_LL12LOVOL_MASK                   0x07  /* LL12LOVOL - [2:0] */
+#define WM8991_LL12LOVOL_SHIFT			0
+
+/*
+ * R48 (0x30) - Output Mixer4
+ */
+#define WM8991_RRI3ROVOL_MASK                   0x07  /* RRI3ROVOL - [8:6] */
+#define WM8991_RRI3ROVOL_SHIFT			6
+#define WM8991_RL12ROVOL_MASK                   0x07  /* RL12ROVOL - [5:3] */
+#define WM8991_RL12ROVOL_SHIFT			3
+#define WM8991_RR12ROVOL_MASK                   0x07  /* RR12ROVOL - [2:0] */
+#define WM8991_RR12ROVOL_SHIFT			0
+
+/*
+ * R49 (0x31) - Output Mixer5
+ */
+#define WM8991_LRI3LOVOL_MASK                   0x07  /* LRI3LOVOL - [8:6] */
+#define WM8991_LRI3LOVOL_SHIFT			6
+#define WM8991_LRBLOVOL_MASK                    0x07  /* LRBLOVOL - [5:3] */
+#define WM8991_LRBLOVOL_SHIFT			3
+#define WM8991_LLBLOVOL_MASK                    0x07  /* LLBLOVOL - [2:0] */
+#define WM8991_LLBLOVOL_SHIFT			0
+
+/*
+ * R50 (0x32) - Output Mixer6
+ */
+#define WM8991_RLI3ROVOL_MASK                   0x07  /* RLI3ROVOL - [8:6] */
+#define WM8991_RLI3ROVOL_SHIFT			6
+#define WM8991_RLBROVOL_MASK                    0x07  /* RLBROVOL - [5:3] */
+#define WM8991_RLBROVOL_SHIFT			3
+#define WM8991_RRBROVOL_MASK                    0x07  /* RRBROVOL - [2:0] */
+#define WM8991_RRBROVOL_SHIFT			0
+
+/*
+ * R51 (0x33) - Out3/4 Mixer
+ */
+#define WM8991_VSEL_MASK                        0x0180  /* VSEL - [8:7] */
+#define WM8991_LI4O3                            0x0020  /* LI4O3 */
+#define WM8991_LI4O3_BIT			5
+#define WM8991_LPGAO3                           0x0010  /* LPGAO3 */
+#define WM8991_LPGAO3_BIT			4
+#define WM8991_RI4O4                            0x0002  /* RI4O4 */
+#define WM8991_RI4O4_BIT			1
+#define WM8991_RPGAO4                           0x0001  /* RPGAO4 */
+#define WM8991_RPGAO4_BIT			0
+/*
+ * R52 (0x34) - Line Mixer1
+ */
+#define WM8991_LLOPGALON                        0x0040  /* LLOPGALON */
+#define WM8991_LLOPGALON_BIT			6
+#define WM8991_LROPGALON                        0x0020  /* LROPGALON */
+#define WM8991_LROPGALON_BIT			5
+#define WM8991_LOPLON                           0x0010  /* LOPLON */
+#define WM8991_LOPLON_BIT			4
+#define WM8991_LR12LOP                          0x0004  /* LR12LOP */
+#define WM8991_LR12LOP_BIT			2
+#define WM8991_LL12LOP                          0x0002  /* LL12LOP */
+#define WM8991_LL12LOP_BIT			1
+#define WM8991_LLOPGALOP                        0x0001  /* LLOPGALOP */
+#define WM8991_LLOPGALOP_BIT			0
+/*
+ * R53 (0x35) - Line Mixer2
+ */
+#define WM8991_RROPGARON                        0x0040  /* RROPGARON */
+#define WM8991_RROPGARON_BIT			6
+#define WM8991_RLOPGARON                        0x0020  /* RLOPGARON */
+#define WM8991_RLOPGARON_BIT			5
+#define WM8991_ROPRON                           0x0010  /* ROPRON */
+#define WM8991_ROPRON_BIT			4
+#define WM8991_RL12ROP                          0x0004  /* RL12ROP */
+#define WM8991_RL12ROP_BIT			2
+#define WM8991_RR12ROP                          0x0002  /* RR12ROP */
+#define WM8991_RR12ROP_BIT			1
+#define WM8991_RROPGAROP                        0x0001  /* RROPGAROP */
+#define WM8991_RROPGAROP_BIT			0
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8991_LB2SPK                           0x0080  /* LB2SPK */
+#define WM8991_LB2SPK_BIT			7
+#define WM8991_RB2SPK                           0x0040  /* RB2SPK */
+#define WM8991_RB2SPK_BIT			6
+#define WM8991_LI2SPK                           0x0020  /* LI2SPK */
+#define WM8991_LI2SPK_BIT			5
+#define WM8991_RI2SPK                           0x0010  /* RI2SPK */
+#define WM8991_RI2SPK_BIT			4
+#define WM8991_LOPGASPK                         0x0008  /* LOPGASPK */
+#define WM8991_LOPGASPK_BIT			3
+#define WM8991_ROPGASPK                         0x0004  /* ROPGASPK */
+#define WM8991_ROPGASPK_BIT			2
+#define WM8991_LDSPK                            0x0002  /* LDSPK */
+#define WM8991_LDSPK_BIT			1
+#define WM8991_RDSPK                            0x0001  /* RDSPK */
+#define WM8991_RDSPK_BIT			0
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8991_VROI                             0x0001  /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP1
+ */
+#define WM8991_DIS_LLINE                        0x0020  /* DIS_LLINE */
+#define WM8991_DIS_RLINE                        0x0010  /* DIS_RLINE */
+#define WM8991_DIS_OUT3                         0x0008  /* DIS_OUT3 */
+#define WM8991_DIS_OUT4                         0x0004  /* DIS_OUT4 */
+#define WM8991_DIS_LOUT                         0x0002  /* DIS_LOUT */
+#define WM8991_DIS_ROUT                         0x0001  /* DIS_ROUT */
+
+/*
+ * R57 (0x39) - AntiPOP2
+ */
+#define WM8991_SOFTST                           0x0040  /* SOFTST */
+#define WM8991_BUFIOEN                          0x0008  /* BUFIOEN */
+#define WM8991_BUFDCOPEN                        0x0004  /* BUFDCOPEN */
+#define WM8991_POBCTRL                          0x0002  /* POBCTRL */
+#define WM8991_VMIDTOG                          0x0001  /* VMIDTOG */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8991_MCDSCTH_MASK                     0x00C0  /* MCDSCTH - [7:6] */
+#define WM8991_MCDTHR_MASK                      0x0038  /* MCDTHR - [5:3] */
+#define WM8991_MCD                              0x0004  /* MCD */
+#define WM8991_MBSEL                            0x0001  /* MBSEL */
+
+/*
+ * R60 (0x3C) - PLL1
+ */
+#define WM8991_SDM                              0x0080  /* SDM */
+#define WM8991_PRESCALE                         0x0040  /* PRESCALE */
+#define WM8991_PLLN_MASK                        0x000F  /* PLLN - [3:0] */
+
+/*
+ * R61 (0x3D) - PLL2
+ */
+#define WM8991_PLLK1_MASK                       0x00FF  /* PLLK1 - [7:0] */
+
+/*
+ * R62 (0x3E) - PLL3
+ */
+#define WM8991_PLLK2_MASK                       0x00FF  /* PLLK2 - [7:0] */
+
+/*
+ * R63 (0x3F) - Internal Driver Bits
+ */
+#define WM8991_INMIXL_PWR_BIT			0
+#define WM8991_AINLMUX_PWR_BIT			1
+#define WM8991_INMIXR_PWR_BIT			2
+#define WM8991_AINRMUX_PWR_BIT			3
+
+#define WM8991_MCLK_DIV 0
+#define WM8991_DACCLK_DIV 1
+#define WM8991_ADCCLK_DIV 2
+#define WM8991_BCLK_DIV 3
+
+#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
+					 tlv_array) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
+		 SNDRV_CTL_ELEM_ACCESS_READWRITE,\
+	.tlv.p = (tlv_array), \
+	.info = snd_soc_info_volsw, \
+	.get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \
+	.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
+
+#endif /* _WM8991_H */
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 18c0d9c..379fa22 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -242,7 +242,7 @@ struct wm8993_priv {
 	int fll_src;
 };
 
-static int wm8993_volatile(unsigned int reg)
+static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8993_SOFTWARE_RESET:
diff --git a/sound/soc/codecs/wm8994-tables.c b/sound/soc/codecs/wm8994-tables.c
index 68e9b02..a87adbd 100644
--- a/sound/soc/codecs/wm8994-tables.c
+++ b/sound/soc/codecs/wm8994-tables.c
@@ -62,8 +62,8 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
 	{ 0x00FF, 0x00FF }, /* R58    - MICBIAS */
 	{ 0x000F, 0x000F }, /* R59    - LDO 1 */
 	{ 0x0007, 0x0007 }, /* R60    - LDO 2 */
-	{ 0x0000, 0x0000 }, /* R61 */
-	{ 0x0000, 0x0000 }, /* R62 */
+	{ 0xFFFF, 0xFFFF }, /* R61 */
+	{ 0xFFFF, 0xFFFF }, /* R62 */
 	{ 0x0000, 0x0000 }, /* R63 */
 	{ 0x0000, 0x0000 }, /* R64 */
 	{ 0x0000, 0x0000 }, /* R65 */
@@ -209,9 +209,9 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
 	{ 0x0000, 0x0000 }, /* R205 */
 	{ 0x0000, 0x0000 }, /* R206 */
 	{ 0x0000, 0x0000 }, /* R207 */
-	{ 0x0000, 0x0000 }, /* R208 */
-	{ 0x0000, 0x0000 }, /* R209 */
-	{ 0x0000, 0x0000 }, /* R210 */
+	{ 0xFFFF, 0xFFFF }, /* R208 */
+	{ 0xFFFF, 0xFFFF }, /* R209 */
+	{ 0xFFFF, 0xFFFF }, /* R210 */
 	{ 0x0000, 0x0000 }, /* R211 */
 	{ 0x0000, 0x0000 }, /* R212 */
 	{ 0x0000, 0x0000 }, /* R213 */
@@ -1573,7 +1573,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
 	{ 0x03C3, 0x03C3 }, /* R1569  - Sidetone */
 };
 
-const __devinitdata u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
+const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
 	0x8994,     /* R0     - Software Reset */
 	0x0000,     /* R1     - Power Management (1) */
 	0x6000,     /* R2     - Power Management (2) */
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index c6c958e..3dc64c8 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -102,8 +102,7 @@ struct wm8994_priv {
 
 	wm8958_micdet_cb jack_cb;
 	void *jack_cb_data;
-	bool jack_is_mic;
-	bool jack_is_video;
+	int micdet_irq;
 
 	int revision;
 	struct wm8994_pdata *pdata;
@@ -115,7 +114,7 @@ struct wm8994_priv {
 	unsigned int aif2clk_disable:1;
 };
 
-static int wm8994_readable(unsigned int reg)
+static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM8994_GPIO_1:
@@ -142,7 +141,7 @@ static int wm8994_readable(unsigned int reg)
 	return wm8994_access_masks[reg].readable != 0;
 }
 
-static int wm8994_volatile(unsigned int reg)
+static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
 {
 	if (reg >= WM8994_CACHE_SIZE)
 		return 1;
@@ -170,7 +169,7 @@ static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
 
 	BUG_ON(reg > WM8994_MAX_REGISTER);
 
-	if (!wm8994_volatile(reg)) {
+	if (!wm8994_volatile(codec, reg)) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret != 0)
 			dev_err(codec->dev, "Cache write to %x failed: %d\n",
@@ -188,7 +187,7 @@ static unsigned int wm8994_read(struct snd_soc_codec *codec,
 
 	BUG_ON(reg > WM8994_MAX_REGISTER);
 
-	if (!wm8994_volatile(reg) && wm8994_readable(reg) &&
+	if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) &&
 	    reg < codec->driver->reg_cache_size) {
 		ret = snd_soc_cache_read(codec, reg, &val);
 		if (ret >= 0)
@@ -529,7 +528,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol)
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec);
+	struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 	int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
 
 	ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block];
@@ -1103,6 +1102,13 @@ static int adc_mux_ev(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int micbias_ev(struct snd_soc_dapm_widget *w,
+		      struct snd_kcontrol *kcontrol, int event)
+{
+	late_enable_ev(w, kcontrol, event);
+	return 0;
+}
+
 static int dac_ev(struct snd_soc_dapm_widget *w,
 		  struct snd_kcontrol *kcontrol, int event)
 {
@@ -1440,6 +1446,10 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"),
 SND_SOC_DAPM_INPUT("DMIC2DAT"),
 SND_SOC_DAPM_INPUT("Clock"),
 
+SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0),
+SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev,
+		      SND_SOC_DAPM_PRE_PMU),
+
 SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
 		    SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 
@@ -1755,6 +1765,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
 	{ "AIF2DACDAT", NULL, "AIF1DACDAT" },
 	{ "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
 	{ "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
+	{ "MICBIAS", NULL, "CLK_SYS" },
+	{ "MICBIAS", NULL, "MICBIAS Supply" },
 };
 
 static const struct snd_soc_dapm_route wm8994_intercon[] = {
@@ -2883,6 +2895,13 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
 	else
 		snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
 				     ARRAY_SIZE(wm8994_eq_controls));
+
+	for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
+		if (pdata->micbias[i]) {
+			snd_soc_write(codec, WM8958_MICBIAS1 + i,
+				pdata->micbias[i] & 0xffff);
+		}
+	}
 }
 
 /**
@@ -2993,46 +3012,18 @@ static void wm8958_default_micdet(u16 status, void *data)
 	int report = 0;
 
 	/* If nothing present then clear our statuses */
-	if (!(status & WM8958_MICD_STS)) {
-		wm8994->jack_is_video = false;
-		wm8994->jack_is_mic = false;
+	if (!(status & WM8958_MICD_STS))
 		goto done;
-	}
 
-	/* Assume anything over 475 ohms is a microphone and remember
-	 * that we've seen one (since buttons override it) */
-	if (status & 0x600)
-		wm8994->jack_is_mic = true;
-	if (wm8994->jack_is_mic)
-		report |= SND_JACK_MICROPHONE;
-
-	/* Video has an impedence of approximately 75 ohms; assume
-	 * this isn't used as a button and remember it since buttons
-	 * override it. */
-	if (status & 0x40)
-		wm8994->jack_is_video = true;
-	if (wm8994->jack_is_video)
-		report |= SND_JACK_VIDEOOUT;
+	report = SND_JACK_MICROPHONE;
 
 	/* Everything else is buttons; just assign slots */
-	if (status & 0x4)
+	if (status & 0x1c0)
 		report |= SND_JACK_BTN_0;
-	if (status & 0x8)
-		report |= SND_JACK_BTN_1;
-	if (status & 0x10)
-		report |= SND_JACK_BTN_2;
-	if (status & 0x20)
-		report |= SND_JACK_BTN_3;
-	if (status & 0x80)
-		report |= SND_JACK_BTN_4;
-	if (status & 0x100)
-		report |= SND_JACK_BTN_5;
 
 done:
 	snd_soc_jack_report(wm8994->micdet[0].jack, report,
-			    SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 |
-			    SND_JACK_BTN_3 | SND_JACK_BTN_4 | SND_JACK_BTN_5 |
-			    SND_JACK_MICROPHONE | SND_JACK_VIDEOOUT);
+			    SND_JACK_BTN_0 | SND_JACK_MICROPHONE);
 }
 
 /**
@@ -3131,13 +3122,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 	wm8994->pdata = dev_get_platdata(codec->dev->parent);
 	wm8994->codec = codec;
 
+	if (wm8994->pdata && wm8994->pdata->micdet_irq)
+		wm8994->micdet_irq = wm8994->pdata->micdet_irq;
+	else if (wm8994->pdata && wm8994->pdata->irq_base)
+		wm8994->micdet_irq = wm8994->pdata->irq_base +
+				     WM8994_IRQ_MIC1_DET;
+
 	pm_runtime_enable(codec->dev);
 	pm_runtime_resume(codec->dev);
 
 	/* Read our current status back from the chip - we don't want to
 	 * reset as this may interfere with the GPIO or LDO operation. */
 	for (i = 0; i < WM8994_CACHE_SIZE; i++) {
-		if (!wm8994_readable(i) || wm8994_volatile(i))
+		if (!wm8994_readable(codec, i) || wm8994_volatile(codec, i))
 			continue;
 
 		ret = wm8994_reg_read(codec->control_data, i);
@@ -3179,14 +3176,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 
 	switch (control->type) {
 	case WM8994:
-		ret = wm8994_request_irq(codec->control_data,
-					 WM8994_IRQ_MIC1_DET,
-					 wm8994_mic_irq, "Mic 1 detect",
-					 wm8994);
-		if (ret != 0)
-			dev_warn(codec->dev,
-				 "Failed to request Mic1 detect IRQ: %d\n",
-				 ret);
+		if (wm8994->micdet_irq) {
+			ret = request_threaded_irq(wm8994->micdet_irq, NULL,
+						   wm8994_mic_irq,
+						   IRQF_TRIGGER_RISING,
+						   "Mic1 detect",
+						   wm8994);
+			if (ret != 0)
+				dev_warn(codec->dev,
+					 "Failed to request Mic1 detect IRQ: %d\n",
+					 ret);
+		}
 
 		ret = wm8994_request_irq(codec->control_data,
 					 WM8994_IRQ_MIC1_SHRT,
@@ -3217,15 +3217,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
 		break;
 
 	case WM8958:
-		ret = wm8994_request_irq(codec->control_data,
-					 WM8994_IRQ_MIC1_DET,
-					 wm8958_mic_irq, "Mic detect",
-					 wm8994);
-		if (ret != 0)
-			dev_warn(codec->dev,
-				 "Failed to request Mic detect IRQ: %d\n",
-				 ret);
-		break;
+		if (wm8994->micdet_irq) {
+			ret = request_threaded_irq(wm8994->micdet_irq, NULL,
+						   wm8958_mic_irq,
+						   IRQF_TRIGGER_RISING,
+						   "Mic detect",
+						   wm8994);
+			if (ret != 0)
+				dev_warn(codec->dev,
+					 "Failed to request Mic detect IRQ: %d\n",
+					 ret);
+		}
 	}
 
 	/* Remember if AIFnLRCLK is configured as a GPIO.  This should be
@@ -3369,7 +3371,8 @@ err_irq:
 	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
 	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
 	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
-	wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
+	if (wm8994->micdet_irq)
+		free_irq(wm8994->micdet_irq, wm8994);
 err:
 	kfree(wm8994);
 	return ret;
@@ -3386,8 +3389,8 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 
 	switch (control->type) {
 	case WM8994:
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
-				wm8994);
+		if (wm8994->micdet_irq)
+			free_irq(wm8994->micdet_irq, wm8994);
 		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
 				wm8994);
 		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
@@ -3397,8 +3400,8 @@ static int  wm8994_codec_remove(struct snd_soc_codec *codec)
 		break;
 
 	case WM8958:
-		wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
-				wm8994);
+		if (wm8994->micdet_irq)
+			free_irq(wm8994->micdet_irq, wm8994);
 		break;
 	}
 	kfree(wm8994->retune_mobile_texts);
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 0c355bf..999b885 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -43,6 +43,6 @@ struct wm8994_access_mask {
 };
 
 extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE];
-extern const __devinitdata  u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
+extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
 
 #endif
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 608c84c..67eaaec 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -19,6 +19,7 @@
 #include <linux/pm.h>
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
+#include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -30,6 +31,18 @@
 
 #include "wm8995.h"
 
+#define WM8995_NUM_SUPPLIES 8
+static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = {
+	"DCVDD",
+	"DBVDD1",
+	"DBVDD2",
+	"DBVDD3",
+	"AVDD1",
+	"AVDD2",
+	"CPVDD",
+	"MICVDD"
+};
+
 static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = {
 	[0]     = 0x8995, [5]     = 0x0100, [16]    = 0x000b, [17]    = 0x000b,
 	[24]    = 0x02c0, [25]    = 0x02c0, [26]    = 0x02c0, [27]    = 0x02c0,
@@ -126,8 +139,37 @@ struct wm8995_priv {
 	int mclk[2];
 	int aifclk[2];
 	struct fll_config fll[2], fll_suspend[2];
+	struct regulator_bulk_data supplies[WM8995_NUM_SUPPLIES];
+	struct notifier_block disable_nb[WM8995_NUM_SUPPLIES];
+	struct snd_soc_codec *codec;
 };
 
+/*
+ * We can't use the same notifier block for more than one supply and
+ * there's no way I can see to get from a callback to the caller
+ * except container_of().
+ */
+#define WM8995_REGULATOR_EVENT(n) \
+static int wm8995_regulator_event_##n(struct notifier_block *nb, \
+				      unsigned long event, void *data)    \
+{ \
+	struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \
+				     disable_nb[n]); \
+	if (event & REGULATOR_EVENT_DISABLE) { \
+		wm8995->codec->cache_sync = 1; \
+	} \
+	return 0; \
+}
+
+WM8995_REGULATOR_EVENT(0)
+WM8995_REGULATOR_EVENT(1)
+WM8995_REGULATOR_EVENT(2)
+WM8995_REGULATOR_EVENT(3)
+WM8995_REGULATOR_EVENT(4)
+WM8995_REGULATOR_EVENT(5)
+WM8995_REGULATOR_EVENT(6)
+WM8995_REGULATOR_EVENT(7)
+
 static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
 static const DECLARE_TLV_DB_SCALE(in1lr_pga_tlv, -1650, 150, 0);
 static const DECLARE_TLV_DB_SCALE(in1l_boost_tlv, 0, 600, 0);
@@ -909,7 +951,7 @@ static const struct snd_soc_dapm_route wm8995_intercon[] = {
 	{ "SPK2R", NULL, "SPK2R Driver" }
 };
 
-static int wm8995_volatile(unsigned int reg)
+static int wm8995_volatile(struct snd_soc_codec *codec, unsigned int reg)
 {
 	/* out of bounds registers are generally considered
 	 * volatile to support register banks that are partially
@@ -1483,6 +1525,11 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
 		break;
 	case SND_SOC_BIAS_STANDBY:
 		if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+			ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies),
+						    wm8995->supplies);
+			if (ret)
+				return ret;
+
 			ret = snd_soc_cache_sync(codec);
 			if (ret) {
 				dev_err(codec->dev,
@@ -1492,12 +1539,13 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
 
 			snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1,
 					    WM8995_BG_ENA_MASK, WM8995_BG_ENA);
-
 		}
 		break;
 	case SND_SOC_BIAS_OFF:
 		snd_soc_update_bits(codec, WM8995_POWER_MANAGEMENT_1,
 				    WM8995_BG_ENA_MASK, 0);
+		regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies),
+				       wm8995->supplies);
 		break;
 	}
 
@@ -1536,10 +1584,12 @@ static int wm8995_remove(struct snd_soc_codec *codec)
 static int wm8995_probe(struct snd_soc_codec *codec)
 {
 	struct wm8995_priv *wm8995;
+	int i;
 	int ret;
 
 	codec->dapm.idle_bias_off = 1;
 	wm8995 = snd_soc_codec_get_drvdata(codec);
+	wm8995->codec = codec;
 
 	ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type);
 	if (ret < 0) {
@@ -1547,21 +1597,58 @@ static int wm8995_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++)
+		wm8995->supplies[i].supply = wm8995_supply_names[i];
+
+	ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8995->supplies),
+				 wm8995->supplies);
+	if (ret) {
+		dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+		return ret;
+	}
+
+	wm8995->disable_nb[0].notifier_call = wm8995_regulator_event_0;
+	wm8995->disable_nb[1].notifier_call = wm8995_regulator_event_1;
+	wm8995->disable_nb[2].notifier_call = wm8995_regulator_event_2;
+	wm8995->disable_nb[3].notifier_call = wm8995_regulator_event_3;
+	wm8995->disable_nb[4].notifier_call = wm8995_regulator_event_4;
+	wm8995->disable_nb[5].notifier_call = wm8995_regulator_event_5;
+	wm8995->disable_nb[6].notifier_call = wm8995_regulator_event_6;
+	wm8995->disable_nb[7].notifier_call = wm8995_regulator_event_7;
+
+	/* This should really be moved into the regulator core */
+	for (i = 0; i < ARRAY_SIZE(wm8995->supplies); i++) {
+		ret = regulator_register_notifier(wm8995->supplies[i].consumer,
+						  &wm8995->disable_nb[i]);
+		if (ret) {
+			dev_err(codec->dev,
+				"Failed to register regulator notifier: %d\n",
+				ret);
+		}
+	}
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(wm8995->supplies),
+				    wm8995->supplies);
+	if (ret) {
+		dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+		goto err_reg_get;
+	}
+
 	ret = snd_soc_read(codec, WM8995_SOFTWARE_RESET);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to read device ID: %d\n", ret);
-		return ret;
+		goto err_reg_enable;
 	}
 
 	if (ret != 0x8995) {
 		dev_err(codec->dev, "Invalid device ID: %#x\n", ret);
-		return -EINVAL;
+		goto err_reg_enable;
 	}
 
 	ret = snd_soc_write(codec, WM8995_SOFTWARE_RESET, 0);
 	if (ret < 0) {
 		dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
-		return ret;
+		goto err_reg_enable;
 	}
 
 	wm8995_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1596,6 +1683,12 @@ static int wm8995_probe(struct snd_soc_codec *codec)
 				ARRAY_SIZE(wm8995_intercon));
 
 	return 0;
+
+err_reg_enable:
+	regulator_bulk_disable(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
+err_reg_get:
+	regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
+	return ret;
 }
 
 #define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index cce704c..55cdf29 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -167,10 +167,10 @@ struct wm9081_priv {
 	int fll_fref;
 	int fll_fout;
 	int tdm_width;
-	struct wm9081_retune_mobile_config *retune;
+	struct wm9081_pdata pdata;
 };
 
-static int wm9081_volatile_register(unsigned int reg)
+static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM9081_SOFTWARE_RESET:
@@ -389,27 +389,6 @@ SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0),
 SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0),
 };
 
-static int speaker_event(struct snd_soc_dapm_widget *w,
-			 struct snd_kcontrol *kcontrol, int event)
-{
-	struct snd_soc_codec *codec = w->codec;
-	unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT);
-
-	switch (event) {
-	case SND_SOC_DAPM_POST_PMU:
-		reg |= WM9081_SPK_ENA;
-		break;
-
-	case SND_SOC_DAPM_PRE_PMD:
-		reg &= ~WM9081_SPK_ENA;
-		break;
-	}
-
-	snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg);
-
-	return 0;
-}
-
 struct _fll_div {
 	u16 fll_fratio;
 	u16 fll_outdiv;
@@ -747,9 +726,8 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0,
 
 SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0),
 
-SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0,
-		   speaker_event,
-		   SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0),
 
 SND_SOC_DAPM_OUTPUT("LINEOUT"),
 SND_SOC_DAPM_OUTPUT("SPKN"),
@@ -762,7 +740,7 @@ SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
 };
 
 
-static const struct snd_soc_dapm_route audio_paths[] = {
+static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
 	{ "DAC", NULL, "CLK_SYS" },
 	{ "DAC", NULL, "CLK_DSP" },
 
@@ -780,8 +758,10 @@ static const struct snd_soc_dapm_route audio_paths[] = {
 	{ "Speaker PGA", NULL, "TOCLK" },
 	{ "Speaker PGA", NULL, "CLK_SYS" },
 
-	{ "SPKN", NULL, "Speaker PGA" },
-	{ "SPKP", NULL, "Speaker PGA" },
+	{ "Speaker", NULL, "Speaker PGA" },
+
+	{ "SPKN", NULL, "Speaker" },
+	{ "SPKP", NULL, "Speaker" },
 };
 
 static int wm9081_set_bias_level(struct snd_soc_codec *codec,
@@ -1082,21 +1062,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
 	aif4 |= wm9081->bclk / wm9081->fs;
 
 	/* Apply a ReTune Mobile configuration if it's in use */
-	if (wm9081->retune) {
-		struct wm9081_retune_mobile_config *retune = wm9081->retune;
+	if (wm9081->pdata.num_retune_configs) {
+		struct wm9081_pdata *pdata = &wm9081->pdata;
 		struct wm9081_retune_mobile_setting *s;
 		int eq1;
 
 		best = 0;
-		best_val = abs(retune->configs[0].rate - wm9081->fs);
-		for (i = 0; i < retune->num_configs; i++) {
-			cur_val = abs(retune->configs[i].rate - wm9081->fs);
+		best_val = abs(pdata->retune_configs[0].rate - wm9081->fs);
+		for (i = 0; i < pdata->num_retune_configs; i++) {
+			cur_val = abs(pdata->retune_configs[i].rate -
+				      wm9081->fs);
 			if (cur_val < best_val) {
 				best_val = cur_val;
 				best = i;
 			}
 		}
-		s = &retune->configs[best];
+		s = &pdata->retune_configs[best];
 
 		dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n",
 			s->name, s->rate);
@@ -1139,10 +1120,9 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 	return 0;
 }
 
-static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai,
+static int wm9081_set_sysclk(struct snd_soc_codec *codec,
 			     int clk_id, unsigned int freq, int dir)
 {
-	struct snd_soc_codec *codec = codec_dai->codec;
 	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
 
 	switch (clk_id) {
@@ -1207,7 +1187,6 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
 
 static struct snd_soc_dai_ops wm9081_dai_ops = {
 	.hw_params = wm9081_hw_params,
-	.set_sysclk = wm9081_set_sysclk,
 	.set_fmt = wm9081_set_dai_fmt,
 	.digital_mute = wm9081_digital_mute,
 	.set_tdm_slot = wm9081_set_tdm_slot,
@@ -1231,7 +1210,6 @@ static struct snd_soc_dai_driver wm9081_dai = {
 static int wm9081_probe(struct snd_soc_codec *codec)
 {
 	struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
 	int ret;
 	u16 reg;
 
@@ -1255,6 +1233,14 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 		return ret;
 	}
 
+	reg = 0;
+	if (wm9081->pdata.irq_high)
+		reg |= WM9081_IRQ_POL;
+	if (!wm9081->pdata.irq_cmos)
+		reg |= WM9081_IRQ_OP_CTRL;
+	snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL,
+			    WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
+
 	wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
 	/* Enable zero cross by default */
@@ -1266,17 +1252,13 @@ static int wm9081_probe(struct snd_soc_codec *codec)
 
 	snd_soc_add_controls(codec, wm9081_snd_controls,
 			     ARRAY_SIZE(wm9081_snd_controls));
-	if (!wm9081->retune) {
+	if (!wm9081->pdata.num_retune_configs) {
 		dev_dbg(codec->dev,
 			"No ReTune Mobile data, using normal EQ\n");
 		snd_soc_add_controls(codec, wm9081_eq_controls,
 				     ARRAY_SIZE(wm9081_eq_controls));
 	}
 
-	snd_soc_dapm_new_controls(dapm, wm9081_dapm_widgets,
-				  ARRAY_SIZE(wm9081_dapm_widgets));
-	snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
-
 	return ret;
 }
 
@@ -1320,11 +1302,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
 	.remove = 	wm9081_remove,
 	.suspend =	wm9081_suspend,
 	.resume =	wm9081_resume,
+
+	.set_sysclk = wm9081_set_sysclk,
 	.set_bias_level = wm9081_set_bias_level,
+
 	.reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
 	.reg_word_size = sizeof(u16),
 	.reg_cache_default = wm9081_reg_defaults,
 	.volatile_register = wm9081_volatile_register,
+
+	.dapm_widgets	  = wm9081_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets),
+	.dapm_routes     = wm9081_audio_paths,
+	.num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths),
 };
 
 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -1343,8 +1333,8 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
 	wm9081->control_data = i2c;
 
 	if (dev_get_platdata(&i2c->dev))
-		memcpy(&wm9081->retune, dev_get_platdata(&i2c->dev),
-		       sizeof(wm9081->retune));
+		memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
+		       sizeof(wm9081->pdata));
 
 	ret = snd_soc_register_codec(&i2c->dev,
 			&soc_codec_dev_wm9081, &wm9081_dai, 1);
@@ -1368,7 +1358,7 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
 
 static struct i2c_driver wm9081_i2c_driver = {
 	.driver = {
-		.name = "wm9081-codec",
+		.name = "wm9081",
 		.owner = THIS_MODULE,
 	},
 	.probe =    wm9081_i2c_probe,
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index a788c42..4de1220 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -144,7 +144,7 @@ struct wm9090_priv {
 	void *control_data;
 };
 
-static int wm9090_volatile(unsigned int reg)
+static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
 {
 	switch (reg) {
 	case WM9090_SOFTWARE_RESET:
@@ -518,7 +518,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 			for (i = 1; i < codec->driver->reg_cache_size; i++) {
 				if (reg_cache[i] == wm9090_reg_defaults[i])
 					continue;
-				if (wm9090_volatile(i))
+				if (wm9090_volatile(codec, i))
 					continue;
 
 				ret = snd_soc_write(codec, i, reg_cache[i]);
@@ -551,7 +551,6 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
 	struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
-	u16 *reg_cache = codec->reg_cache;
 	int ret;
 
 	codec->control_data = wm9090->control_data;
@@ -576,22 +575,30 @@ static int wm9090_probe(struct snd_soc_codec *codec)
 	/* Configure some defaults; they will be written out when we
 	 * bring the bias up.
 	 */
-	reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
-		| WM9090_IN1A_ZC;
-	reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
-		| WM9090_IN1B_ZC;
-	reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
-		| WM9090_IN2A_ZC;
-	reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
-		| WM9090_IN2B_ZC;
-	reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
-		WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
-	reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
-		WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
-	reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
-		WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
-
-	reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+	snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_A_VOLUME,
+			    WM9090_IN1_VU | WM9090_IN1A_ZC,
+			    WM9090_IN1_VU | WM9090_IN1A_ZC);
+	snd_soc_update_bits(codec, WM9090_IN1_LINE_INPUT_B_VOLUME,
+			    WM9090_IN1_VU | WM9090_IN1B_ZC,
+			    WM9090_IN1_VU | WM9090_IN1B_ZC);
+	snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_A_VOLUME,
+			    WM9090_IN2_VU | WM9090_IN2A_ZC,
+			    WM9090_IN2_VU | WM9090_IN2A_ZC);
+	snd_soc_update_bits(codec, WM9090_IN2_LINE_INPUT_B_VOLUME,
+			    WM9090_IN2_VU | WM9090_IN2B_ZC,
+			    WM9090_IN2_VU | WM9090_IN2B_ZC);
+	snd_soc_update_bits(codec, WM9090_SPEAKER_VOLUME_LEFT,
+			    WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC,
+			    WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC);
+	snd_soc_update_bits(codec, WM9090_LEFT_OUTPUT_VOLUME,
+			    WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC,
+			    WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC);
+	snd_soc_update_bits(codec, WM9090_RIGHT_OUTPUT_VOLUME,
+			    WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC,
+			    WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC);
+
+	snd_soc_update_bits(codec, WM9090_CLOCKING_1,
+			    WM9090_TOCLK_ENA, WM9090_TOCLK_ENA);
 
 	wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 5168927..7b6b3c1 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -82,7 +82,8 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
 	} while (reg & op && count < 400);
 
 	if (reg & op)
-		dev_err(codec->dev, "Timed out waiting for DC Servo\n");
+		dev_err(codec->dev, "Timed out waiting for DC Servo %x\n",
+			op);
 }
 
 /*
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 9e0e565..d0d60b8 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -658,7 +658,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+	ioarea = request_mem_region(mem->start, resource_size(mem),
 				    pdev->name);
 	if (!ioarea) {
 		dev_err(&pdev->dev, "McBSP region already claimed\n");
@@ -694,20 +694,25 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 	}
 	clk_enable(dev->clk);
 
-	dev->base = (void __iomem *)IO_ADDRESS(mem->start);
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (!dev->base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_release_clk;
+	}
 
 	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].dma_addr =
-	    (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG);
+	    (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG);
 
 	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
-	    (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG);
+	    (dma_addr_t)(mem->start + DAVINCI_MCBSP_DRR_REG);
 
 	/* first TX, then RX */
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "no DMA resource\n");
 		ret = -ENXIO;
-		goto err_free_mem;
+		goto err_iounmap;
 	}
 	dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start;
 
@@ -715,7 +720,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 	if (!res) {
 		dev_err(&pdev->dev, "no DMA resource\n");
 		ret = -ENXIO;
-		goto err_free_mem;
+		goto err_iounmap;
 	}
 	dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
 	dev->dev = &pdev->dev;
@@ -724,14 +729,19 @@ static int davinci_i2s_probe(struct platform_device *pdev)
 
 	ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);
 	if (ret != 0)
-		goto err_free_mem;
+		goto err_iounmap;
 
 	return 0;
 
+err_iounmap:
+	iounmap(dev->base);
+err_release_clk:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
 err_free_mem:
 	kfree(dev);
 err_release_region:
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 
 	return ret;
 }
@@ -747,7 +757,7 @@ static int davinci_i2s_remove(struct platform_device *pdev)
 	dev->clk = NULL;
 	kfree(dev);
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 
 	return 0;
 }
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index fb55d2c..a5af834 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -868,7 +868,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	}
 
 	ioarea = request_mem_region(mem->start,
-			(mem->end - mem->start) + 1, pdev->name);
+			resource_size(mem), pdev->name);
 	if (!ioarea) {
 		dev_err(&pdev->dev, "Audio region already claimed\n");
 		ret = -EBUSY;
@@ -885,7 +885,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	clk_enable(dev->clk);
 	dev->clk_active = 1;
 
-	dev->base = (void __iomem *)IO_ADDRESS(mem->start);
+	dev->base = ioremap(mem->start, resource_size(mem));
+	if (!dev->base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_release_clk;
+	}
+
 	dev->op_mode = pdata->op_mode;
 	dev->tdm_slots = pdata->tdm_slots;
 	dev->num_serializer = pdata->num_serializer;
@@ -899,14 +905,14 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	dma_data->asp_chan_q = pdata->asp_chan_q;
 	dma_data->ram_chan_q = pdata->ram_chan_q;
 	dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
-							io_v2p(dev->base));
+							mem->start);
 
 	/* first TX, then RX */
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "no DMA resource\n");
 		ret = -ENODEV;
-		goto err_release_region;
+		goto err_iounmap;
 	}
 
 	dma_data->channel = res->start;
@@ -915,13 +921,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	dma_data->asp_chan_q = pdata->asp_chan_q;
 	dma_data->ram_chan_q = pdata->ram_chan_q;
 	dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
-							io_v2p(dev->base));
+							mem->start);
 
 	res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 	if (!res) {
 		dev_err(&pdev->dev, "no DMA resource\n");
 		ret = -ENODEV;
-		goto err_release_region;
+		goto err_iounmap;
 	}
 
 	dma_data->channel = res->start;
@@ -929,11 +935,16 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
 	ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
 
 	if (ret != 0)
-		goto err_release_region;
+		goto err_iounmap;
 	return 0;
 
+err_iounmap:
+	iounmap(dev->base);
+err_release_clk:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
 err_release_region:
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 err_release_data:
 	kfree(dev);
 
@@ -951,7 +962,7 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
 	dev->clk = NULL;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	release_mem_region(mem->start, resource_size(mem));
 
 	kfree(dev);
 
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index 5742904..91a28de 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -30,3 +30,12 @@ config SND_EP93XX_SOC_SIMONE
 	help
 	  Say Y or M here if you want to add support for AC97 audio on the
 	  Simplemachines Sim.One board.
+
+config SND_EP93XX_SOC_EDB93XX
+	tristate "SoC Audio support for Cirrus Logic EDB93xx boards"
+	depends on SND_EP93XX_SOC && (MACH_EDB9301 || MACH_EDB9302 || MACH_EDB9302A || MACH_EDB9307A || MACH_EDB9315A)
+	select SND_EP93XX_SOC_I2S
+	select SND_SOC_CS4271
+	help
+	  Say Y or M here if you want to add support for I2S audio on the
+	  Cirrus Logic EDB93xx boards.
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile
index 8e7977f..5514146 100644
--- a/sound/soc/ep93xx/Makefile
+++ b/sound/soc/ep93xx/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_SND_EP93XX_SOC_AC97)		+= snd-soc-ep93xx-ac97.o
 # EP93XX Machine Support
 snd-soc-snappercl15-objs			:= snappercl15.o
 snd-soc-simone-objs				:= simone.o
+snd-soc-edb93xx-objs				:= edb93xx.o
 
 obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15)	+= snd-soc-snappercl15.o
 obj-$(CONFIG_SND_EP93XX_SOC_SIMONE)		+= snd-soc-simone.o
+obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX)		+= snd-soc-edb93xx.o
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
new file mode 100644
index 0000000..d3aa151
--- /dev/null
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -0,0 +1,142 @@
+/*
+ * SoC audio for EDB93xx
+ *
+ * Copyright (c) 2010 Alexander Sverdlin <subaparts@yandex.ru>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 support CS4271 codec being master or slave, working
+ * in control port mode, connected either via SPI or I2C.
+ * The data format accepted is I2S or left-justified.
+ * DAPM support not implemented.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include "ep93xx-pcm.h"
+
+#define edb93xx_has_audio() (machine_is_edb9301() ||	\
+			     machine_is_edb9302() ||	\
+			     machine_is_edb9302a() ||	\
+			     machine_is_edb9307a() ||	\
+			     machine_is_edb9315a())
+
+static int edb93xx_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int err;
+	unsigned int mclk_rate;
+	unsigned int rate = params_rate(params);
+
+	/*
+	 * According to CS4271 datasheet we use MCLK/LRCK=256 for
+	 * rates below 50kHz and 128 for higher sample rates
+	 */
+	if (rate < 50000)
+		mclk_rate = rate * 64 * 4;
+	else
+		mclk_rate = rate * 64 * 2;
+
+	err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+				  SND_SOC_DAIFMT_NB_IF |
+				  SND_SOC_DAIFMT_CBS_CFS);
+	if (err)
+		return err;
+
+	err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+				  SND_SOC_DAIFMT_NB_IF |
+				  SND_SOC_DAIFMT_CBS_CFS);
+	if (err)
+		return err;
+
+	err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate,
+				     SND_SOC_CLOCK_IN);
+	if (err)
+		return err;
+
+	return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate,
+				      SND_SOC_CLOCK_OUT);
+}
+
+static struct snd_soc_ops edb93xx_ops = {
+	.hw_params	= edb93xx_hw_params,
+};
+
+static struct snd_soc_dai_link edb93xx_dai = {
+	.name		= "CS4271",
+	.stream_name	= "CS4271 HiFi",
+	.platform_name	= "ep93xx-pcm-audio",
+	.cpu_dai_name	= "ep93xx-i2s",
+	.codec_name	= "spi0.0",
+	.codec_dai_name	= "cs4271-hifi",
+	.ops		= &edb93xx_ops,
+};
+
+static struct snd_soc_card snd_soc_edb93xx = {
+	.name		= "EDB93XX",
+	.dai_link	= &edb93xx_dai,
+	.num_links	= 1,
+};
+
+static struct platform_device *edb93xx_snd_device;
+
+static int __init edb93xx_init(void)
+{
+	int ret;
+
+	if (!edb93xx_has_audio())
+		return -ENODEV;
+
+	ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
+				 EP93XX_SYSCON_I2SCLKDIV_ORIDE |
+				 EP93XX_SYSCON_I2SCLKDIV_SPOL);
+	if (ret)
+		return ret;
+
+	edb93xx_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!edb93xx_snd_device) {
+		ret = -ENOMEM;
+		goto free_i2s;
+	}
+
+	platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx);
+	ret = platform_device_add(edb93xx_snd_device);
+	if (ret)
+		goto device_put;
+
+	return 0;
+
+device_put:
+	platform_device_put(edb93xx_snd_device);
+free_i2s:
+	ep93xx_i2s_release();
+	return ret;
+}
+module_init(edb93xx_init);
+
+static void __exit edb93xx_exit(void)
+{
+	platform_device_unregister(edb93xx_snd_device);
+	ep93xx_i2s_release();
+}
+module_exit(edb93xx_exit);
+
+MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
+MODULE_DESCRIPTION("ALSA SoC EDB93xx");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
index 68a0bae..104e95c 100644
--- a/sound/soc/ep93xx/ep93xx-ac97.c
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -253,7 +253,6 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
 	struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
 	unsigned v = 0;
 
-
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index fff579a..042f4e9 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -242,7 +242,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
 {
 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
 	unsigned word_len, div, sdiv, lrdiv;
-	int found = 0, err;
+	int err;
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
@@ -275,15 +275,14 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
 	 * the codec uses.
 	 */
 	div = clk_get_rate(info->mclk) / params_rate(params);
-	for (sdiv = 2; sdiv <= 4; sdiv += 2)
-		for (lrdiv = 64; lrdiv <= 128; lrdiv <<= 1)
-			if (sdiv * lrdiv == div) {
-				found = 1;
-				goto out;
-			}
-out:
-	if (!found)
-		return -EINVAL;
+	sdiv = 4;
+	if (div > (256 + 512) / 2) {
+		lrdiv = 128;
+	} else {
+		lrdiv = 64;
+		if (div < (128 + 256) / 2)
+			sdiv = 2;
+	}
 
 	err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
 	if (err)
@@ -314,10 +313,12 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
 
 	if (!dai->active)
-		return;
+		return 0;
 
 	ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
 	ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
+
+	return 0;
 }
 
 static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
@@ -325,10 +326,12 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
 	struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
 
 	if (!dai->active)
-		return;
+		return 0;
 
 	ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
 	ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
+
+	return 0;
 }
 #else
 #define ep93xx_i2s_suspend	NULL
@@ -352,13 +355,13 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
 	.playback	= {
 		.channels_min	= 2,
 		.channels_max	= 2,
-		.rates		= SNDRV_PCM_RATE_8000_96000,
+		.rates		= SNDRV_PCM_RATE_8000_192000,
 		.formats	= EP93XX_I2S_FORMATS,
 	},
 	.capture	= {
 		 .channels_min	= 2,
 		 .channels_max	= 2,
-		 .rates		= SNDRV_PCM_RATE_8000_96000,
+		 .rates		= SNDRV_PCM_RATE_8000_192000,
 		 .formats	= EP93XX_I2S_FORMATS,
 	},
 	.ops		= &ep93xx_i2s_dai_ops,
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index 0667077..a456e49 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -35,9 +35,9 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
 				   SNDRV_PCM_INFO_INTERLEAVED	|
 				   SNDRV_PCM_INFO_BLOCK_TRANSFER),
 				   
-	.rates			= SNDRV_PCM_RATE_8000_96000,
+	.rates			= SNDRV_PCM_RATE_8000_192000,
 	.rate_min		= SNDRV_PCM_RATE_8000,
-	.rate_max		= SNDRV_PCM_RATE_96000,
+	.rate_max		= SNDRV_PCM_RATE_192000,
 	
 	.formats		= (SNDRV_PCM_FMTBIT_S16_LE |
 				   SNDRV_PCM_FMTBIT_S24_LE |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 4cf98c0..15dac0f 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -896,8 +896,7 @@ static struct snd_pcm_ops fsl_dma_ops = {
 	.pointer	= fsl_dma_pointer,
 };
 
-static int __devinit fsl_soc_dma_probe(struct platform_device *pdev,
-				       const struct of_device_id *match)
+static int __devinit fsl_soc_dma_probe(struct platform_device *pdev)
  {
 	struct dma_object *dma;
 	struct device_node *np = pdev->dev.of_node;
@@ -979,7 +978,7 @@ static const struct of_device_id fsl_soc_dma_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids);
 
-static struct of_platform_driver fsl_soc_dma_driver = {
+static struct platform_driver fsl_soc_dma_driver = {
 	.driver = {
 		.name = "fsl-pcm-audio",
 		.owner = THIS_MODULE,
@@ -993,12 +992,12 @@ static int __init fsl_soc_dma_init(void)
 {
 	pr_info("Freescale Elo DMA ASoC PCM Driver\n");
 
-	return of_register_platform_driver(&fsl_soc_dma_driver);
+	return platform_driver_register(&fsl_soc_dma_driver);
 }
 
 static void __exit fsl_soc_dma_exit(void)
 {
-	of_unregister_platform_driver(&fsl_soc_dma_driver);
+	platform_driver_unregister(&fsl_soc_dma_driver);
 }
 
 module_init(fsl_soc_dma_init);
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 4cc167a..313e0cc 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -624,8 +624,7 @@ static void make_lowercase(char *s)
 	}
 }
 
-static int __devinit fsl_ssi_probe(struct platform_device *pdev,
-				   const struct of_device_id *match)
+static int __devinit fsl_ssi_probe(struct platform_device *pdev)
 {
 	struct fsl_ssi_private *ssi_private;
 	int ret = 0;
@@ -774,7 +773,7 @@ static const struct of_device_id fsl_ssi_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
 
-static struct of_platform_driver fsl_ssi_driver = {
+static struct platform_driver fsl_ssi_driver = {
 	.driver = {
 		.name = "fsl-ssi-dai",
 		.owner = THIS_MODULE,
@@ -788,12 +787,12 @@ static int __init fsl_ssi_init(void)
 {
 	printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
 
-	return of_register_platform_driver(&fsl_ssi_driver);
+	return platform_driver_register(&fsl_ssi_driver);
 }
 
 static void __exit fsl_ssi_exit(void)
 {
-	of_unregister_platform_driver(&fsl_ssi_driver);
+	platform_driver_unregister(&fsl_ssi_driver);
 }
 
 module_init(fsl_ssi_init);
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index f92dca0..fff695c 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -368,8 +368,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = {
 	.pcm_free	= &psc_dma_free,
 };
 
-static int mpc5200_hpcd_probe(struct of_device *op,
-		const struct of_device_id *match)
+static int mpc5200_hpcd_probe(struct of_device *op)
 {
 	phys_addr_t fifo;
 	struct psc_dma *psc_dma;
@@ -511,32 +510,31 @@ static int mpc5200_hpcd_remove(struct of_device *op)
 }
 
 static struct of_device_id mpc5200_hpcd_match[] = {
-	{
-		.compatible = "fsl,mpc5200-pcm",
-	},
+	{ .compatible = "fsl,mpc5200-pcm", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match);
 
-static struct of_platform_driver mpc5200_hpcd_of_driver = {
-	.owner		= THIS_MODULE,
-	.name		= "mpc5200-pcm-audio",
-	.match_table    = mpc5200_hpcd_match,
+static struct platform_driver mpc5200_hpcd_of_driver = {
 	.probe		= mpc5200_hpcd_probe,
 	.remove		= mpc5200_hpcd_remove,
+	.dev = {
+		.owner		= THIS_MODULE,
+		.name		= "mpc5200-pcm-audio",
+		.of_match_table    = mpc5200_hpcd_match,
+	}
 };
 
 static int __init mpc5200_hpcd_init(void)
 {
-	return of_register_platform_driver(&mpc5200_hpcd_of_driver);
+	return platform_driver_register(&mpc5200_hpcd_of_driver);
 }
+module_init(mpc5200_hpcd_init);
 
 static void __exit mpc5200_hpcd_exit(void)
 {
-	of_unregister_platform_driver(&mpc5200_hpcd_of_driver);
+	platform_driver_unregister(&mpc5200_hpcd_of_driver);
 }
-
-module_init(mpc5200_hpcd_init);
 module_exit(mpc5200_hpcd_exit);
 
 MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 40acc8e..ad36b09 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -272,8 +272,7 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = {
  * - Probe/remove operations
  * - OF device match table
  */
-static int __devinit psc_ac97_of_probe(struct platform_device *op,
-				      const struct of_device_id *match)
+static int __devinit psc_ac97_of_probe(struct platform_device *op)
 {
 	int rc;
 	struct snd_ac97 ac97;
@@ -316,7 +315,7 @@ static struct of_device_id psc_ac97_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, psc_ac97_match);
 
-static struct of_platform_driver psc_ac97_driver = {
+static struct platform_driver psc_ac97_driver = {
 	.probe = psc_ac97_of_probe,
 	.remove = __devexit_p(psc_ac97_of_remove),
 	.driver = {
@@ -332,13 +331,13 @@ static struct of_platform_driver psc_ac97_driver = {
  */
 static int __init psc_ac97_init(void)
 {
-	return of_register_platform_driver(&psc_ac97_driver);
+	return platform_driver_register(&psc_ac97_driver);
 }
 module_init(psc_ac97_init);
 
 static void __exit psc_ac97_exit(void)
 {
-	of_unregister_platform_driver(&psc_ac97_driver);
+	platform_driver_unregister(&psc_ac97_driver);
 }
 module_exit(psc_ac97_exit);
 
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 9018fa5..87cf2a5 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -150,8 +150,7 @@ static struct snd_soc_dai_driver psc_i2s_dai[] = {{
  * - Probe/remove operations
  * - OF device match table
  */
-static int __devinit psc_i2s_of_probe(struct platform_device *op,
-				      const struct of_device_id *match)
+static int __devinit psc_i2s_of_probe(struct platform_device *op)
 {
 	int rc;
 	struct psc_dma *psc_dma;
@@ -213,7 +212,7 @@ static struct of_device_id psc_i2s_match[] __devinitdata = {
 };
 MODULE_DEVICE_TABLE(of, psc_i2s_match);
 
-static struct of_platform_driver psc_i2s_driver = {
+static struct platform_driver psc_i2s_driver = {
 	.probe = psc_i2s_of_probe,
 	.remove = __devexit_p(psc_i2s_of_remove),
 	.driver = {
@@ -229,13 +228,13 @@ static struct of_platform_driver psc_i2s_driver = {
  */
 static int __init psc_i2s_init(void)
 {
-	return of_register_platform_driver(&psc_i2s_driver);
+	return platform_driver_register(&psc_i2s_driver);
 }
 module_init(psc_i2s_init);
 
 static void __exit psc_i2s_exit(void)
 {
-	of_unregister_platform_driver(&psc_i2s_driver);
+	platform_driver_unregister(&psc_i2s_driver);
 }
 module_exit(psc_i2s_exit);
 
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 7d7847a..c16c6b2 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -53,9 +53,8 @@ struct mpc8610_hpcd_data {
  *
  * Here we program the DMACR and PMUXCR registers.
  */
-static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
+static int mpc8610_hpcd_machine_probe(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card = platform_get_drvdata(sound_device);
 	struct mpc8610_hpcd_data *machine_data =
 		container_of(card, struct mpc8610_hpcd_data, card);
 	struct ccsr_guts_86xx __iomem *guts;
@@ -138,9 +137,8 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
  * This function is called to remove the sound device for one SSI.  We
  * de-program the DMACR and PMUXCR register.
  */
-static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
+static int mpc8610_hpcd_machine_remove(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card = platform_get_drvdata(sound_device);
 	struct mpc8610_hpcd_data *machine_data =
 		container_of(card, struct mpc8610_hpcd_data, card);
 	struct ccsr_guts_86xx __iomem *guts;
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 026b756..66e0b68 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -85,9 +85,8 @@ struct machine_data {
  *
  * Here we program the DMACR and PMUXCR registers.
  */
-static int p1022_ds_machine_probe(struct platform_device *sound_device)
+static int p1022_ds_machine_probe(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card = platform_get_drvdata(sound_device);
 	struct machine_data *mdata =
 		container_of(card, struct machine_data, card);
 	struct ccsr_guts_85xx __iomem *guts;
@@ -160,9 +159,8 @@ static int p1022_ds_startup(struct snd_pcm_substream *substream)
  * This function is called to remove the sound device for one SSI.  We
  * de-program the DMACR and PMUXCR register.
  */
-static int p1022_ds_machine_remove(struct platform_device *sound_device)
+static int p1022_ds_machine_remove(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card = platform_get_drvdata(sound_device);
 	struct machine_data *mdata =
 		container_of(card, struct machine_data, card);
 	struct ccsr_guts_85xx __iomem *guts;
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 642270a..d8f130d 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -30,6 +30,16 @@ config SND_MXC_SOC_WM1133_EV1
 	  Enable support for audio on the i.MX31ADS with the WM1133-EV1
 	  PMIC board with WM8835x fitted.
 
+config SND_SOC_MX27VIS_AIC32X4
+	tristate "SoC audio support for Visstrim M10 boards"
+	depends on MACH_IMX27_VISSTRIM_M10
+	select SND_SOC_TVL320AIC32X4
+	select SND_MXC_SOC_SSI
+	select SND_MXC_SOC_MX2
+	help
+	  Say Y if you want to add support for SoC audio on Visstrim SM10
+	  board with TLV320AIC32X4 codec.
+
 config SND_SOC_PHYCORE_AC97
 	tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
 	depends on MACH_PCM043 || MACH_PCA100
@@ -44,7 +54,8 @@ config SND_SOC_EUKREA_TLV320
 	tristate "Eukrea TLV320"
 	depends on MACH_EUKREA_MBIMX27_BASEBOARD \
 		|| MACH_EUKREA_MBIMXSD25_BASEBOARD \
-		|| MACH_EUKREA_MBIMXSD35_BASEBOARD
+		|| MACH_EUKREA_MBIMXSD35_BASEBOARD \
+		|| MACH_EUKREA_MBIMXSD51_BASEBOARD
 	select SND_SOC_TLV320AIC23
 	select SND_MXC_SOC_SSI
 	select SND_MXC_SOC_FIQ
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index b67fc02..d6d609b 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -10,8 +10,10 @@ obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
 snd-soc-phycore-ac97-objs := phycore-ac97.o
+snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
 snd-soc-wm1133-ev1-objs := wm1133-ev1.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
+obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
 obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index 1e9bcca..75fb4b8 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -98,7 +98,8 @@ static int __init eukrea_tlv320_init(void)
 	int ret;
 
 	if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd()
-		&& !machine_is_eukrea_cpuimx35sd())
+		&& !machine_is_eukrea_cpuimx35sd()
+		&& !machine_is_eukrea_cpuimx51sd())
 		/* return happy. We might run on a totally different machine */
 		return 0;
 
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 30894ea..bc92ec6 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -108,7 +108,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 		break;
 	case SND_SOC_DAIFMT_DSP_B:
 		/* data on rising edge of bclk, frame high with data */
-		strcr |= SSI_STCR_TFSL;
+		strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0;
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
 		/* data on rising edge of bclk, frame high 1clk before data */
@@ -656,6 +656,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
 	ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0;
 	ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
 
+	ssi->dma_params_tx.burstsize = 4;
+	ssi->dma_params_rx.burstsize = 4;
+
 	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
 	if (res)
 		ssi->dma_params_tx.dma = res->start;
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c
new file mode 100644
index 0000000..054110b
--- /dev/null
+++ b/sound/soc/imx/mx27vis-aic32x4.c
@@ -0,0 +1,137 @@
+/*
+ * mx27vis-aic32x4.c
+ *
+ * Copyright 2011 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 as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+#include <mach/audmux.h>
+
+#include "../codecs/tlv320aic32x4.h"
+#include "imx-ssi.h"
+
+static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret;
+	u32 dai_format;
+
+	dai_format = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+		SND_SOC_DAIFMT_CBM_CFM;
+
+	/* set codec DAI configuration */
+	snd_soc_dai_set_fmt(codec_dai, dai_format);
+
+	/* set cpu DAI configuration */
+	snd_soc_dai_set_fmt(cpu_dai, dai_format);
+
+	ret = snd_soc_dai_set_sysclk(codec_dai, 0,
+				     25000000, SND_SOC_CLOCK_OUT);
+	if (ret) {
+		pr_err("%s: failed setting codec sysclk\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0,
+				SND_SOC_CLOCK_IN);
+	if (ret) {
+		pr_err("can't set CPU system clock IMX_SSP_SYS_CLK\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops mx27vis_aic32x4_snd_ops = {
+	.hw_params	= mx27vis_aic32x4_hw_params,
+};
+
+static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
+	.name		= "tlv320aic32x4",
+	.stream_name	= "TLV320AIC32X4",
+	.codec_dai_name	= "tlv320aic32x4-hifi",
+	.platform_name	= "imx-pcm-audio.0",
+	.codec_name	= "tlv320aic32x4.0-0018",
+	.cpu_dai_name	= "imx-ssi.0",
+	.ops		= &mx27vis_aic32x4_snd_ops,
+};
+
+static struct snd_soc_card mx27vis_aic32x4 = {
+	.name		= "visstrim_m10-audio",
+	.dai_link	= &mx27vis_aic32x4_dai,
+	.num_links	= 1,
+};
+
+static struct platform_device *mx27vis_aic32x4_snd_device;
+
+static int __init mx27vis_aic32x4_init(void)
+{
+	int ret;
+
+	mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1);
+	if (!mx27vis_aic32x4_snd_device)
+		return -ENOMEM;
+
+	platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4);
+	ret = platform_device_add(mx27vis_aic32x4_snd_device);
+
+	if (ret) {
+		printk(KERN_ERR "ASoC: Platform device allocation failed\n");
+		platform_device_put(mx27vis_aic32x4_snd_device);
+	}
+
+	/* Connect SSI0 as clock slave to SSI1 external pins */
+	mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+			MXC_AUDMUX_V1_PCR_SYN |
+			MXC_AUDMUX_V1_PCR_TFSDIR |
+			MXC_AUDMUX_V1_PCR_TCLKDIR |
+			MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
+			MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
+	);
+	mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
+			MXC_AUDMUX_V1_PCR_SYN |
+			MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+	);
+
+	return ret;
+}
+
+static void __exit mx27vis_aic32x4_exit(void)
+{
+	platform_device_unregister(mx27vis_aic32x4_snd_device);
+}
+
+module_init(mx27vis_aic32x4_init);
+module_exit(mx27vis_aic32x4_exit);
+
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
+MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/mid-x86/Kconfig b/sound/soc/mid-x86/Kconfig
new file mode 100644
index 0000000..2935042
--- /dev/null
+++ b/sound/soc/mid-x86/Kconfig
@@ -0,0 +1,14 @@
+config SND_MFLD_MACHINE
+	tristate "SOC Machine Audio driver for Intel Medfield MID platform"
+	depends on INTEL_SCU_IPC
+	depends on SND_INTEL_SST
+	select SND_SOC_SN95031
+	select SND_SST_PLATFORM
+	help
+          This adds support for ASoC machine driver for Intel(R) MID Medfield platform
+          used as alsa device in audio substem in Intel(R) MID devices
+          Say Y if you have such a device
+          If unsure select "N".
+
+config SND_SST_PLATFORM
+	tristate
diff --git a/sound/soc/mid-x86/Makefile b/sound/soc/mid-x86/Makefile
new file mode 100644
index 0000000..6398833
--- /dev/null
+++ b/sound/soc/mid-x86/Makefile
@@ -0,0 +1,5 @@
+snd-soc-sst-platform-objs := sst_platform.o
+snd-soc-mfld-machine-objs := mfld_machine.o
+
+obj-$(CONFIG_SND_SST_PLATFORM) += snd-soc-sst-platform.o
+obj-$(CONFIG_SND_MFLD_MACHINE) += snd-soc-mfld-machine.o
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
new file mode 100644
index 0000000..429aa1b
--- /dev/null
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -0,0 +1,452 @@
+/*
+ *  mfld_machine.c - ASoc Machine driver for Intel Medfield MID platform
+ *
+ *  Copyright (C) 2010 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@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; 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include "../codecs/sn95031.h"
+
+#define MID_MONO 1
+#define MID_STEREO 2
+#define MID_MAX_CAP 5
+#define MFLD_JACK_INSERT 0x04
+
+enum soc_mic_bias_zones {
+	MFLD_MV_START = 0,
+	/* mic bias volutage range for Headphones*/
+	MFLD_MV_HP = 400,
+	/* mic bias volutage range for American Headset*/
+	MFLD_MV_AM_HS = 650,
+	/* mic bias volutage range for Headset*/
+	MFLD_MV_HS = 2000,
+	MFLD_MV_UNDEFINED,
+};
+
+static unsigned int	hs_switch;
+static unsigned int	lo_dac;
+
+struct mfld_mc_private {
+	struct platform_device *socdev;
+	void __iomem *int_base;
+	struct snd_soc_codec *codec;
+	u8 interrupt_status;
+};
+
+struct snd_soc_jack mfld_jack;
+
+/*Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin mfld_jack_pins[] = {
+	{
+		.pin = "Headphones",
+		.mask = SND_JACK_HEADPHONE,
+	},
+	{
+		.pin = "AMIC1",
+		.mask = SND_JACK_MICROPHONE,
+	},
+};
+
+/* jack detection voltage zones */
+static struct snd_soc_jack_zone mfld_zones[] = {
+	{MFLD_MV_START, MFLD_MV_AM_HS, SND_JACK_HEADPHONE},
+	{MFLD_MV_AM_HS, MFLD_MV_HS, SND_JACK_HEADSET},
+};
+
+/* sound card controls */
+static const char *headset_switch_text[] = {"Earpiece", "Headset"};
+
+static const char *lo_text[] = {"Vibra", "Headset", "IHF", "None"};
+
+static const struct soc_enum headset_enum =
+	SOC_ENUM_SINGLE_EXT(2, headset_switch_text);
+
+static const struct soc_enum lo_enum =
+	SOC_ENUM_SINGLE_EXT(4, lo_text);
+
+static int headset_get_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = hs_switch;
+	return 0;
+}
+
+static int headset_set_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0] == hs_switch)
+		return 0;
+
+	if (ucontrol->value.integer.value[0]) {
+		pr_debug("hs_set HS path\n");
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
+		snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
+	} else {
+		pr_debug("hs_set EP path\n");
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
+		snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
+	}
+	snd_soc_dapm_sync(&codec->dapm);
+	hs_switch = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
+static void lo_enable_out_pins(struct snd_soc_codec *codec)
+{
+	snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTL");
+	snd_soc_dapm_enable_pin(&codec->dapm, "IHFOUTR");
+	snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTL");
+	snd_soc_dapm_enable_pin(&codec->dapm, "LINEOUTR");
+	snd_soc_dapm_enable_pin(&codec->dapm, "VIB1OUT");
+	snd_soc_dapm_enable_pin(&codec->dapm, "VIB2OUT");
+	if (hs_switch) {
+		snd_soc_dapm_enable_pin(&codec->dapm, "Headphones");
+		snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
+	} else {
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
+		snd_soc_dapm_enable_pin(&codec->dapm, "EPOUT");
+	}
+}
+
+static int lo_get_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = lo_dac;
+	return 0;
+}
+
+static int lo_set_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.integer.value[0] == lo_dac)
+		return 0;
+
+	/* we dont want to work with last state of lineout so just enable all
+	 * pins and then disable pins not required
+	 */
+	lo_enable_out_pins(codec);
+	switch (ucontrol->value.integer.value[0]) {
+	case 0:
+		pr_debug("set vibra path\n");
+		snd_soc_dapm_disable_pin(&codec->dapm, "VIB1OUT");
+		snd_soc_dapm_disable_pin(&codec->dapm, "VIB2OUT");
+		snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0);
+		break;
+
+	case 1:
+		pr_debug("set hs  path\n");
+		snd_soc_dapm_disable_pin(&codec->dapm, "Headphones");
+		snd_soc_dapm_disable_pin(&codec->dapm, "EPOUT");
+		snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x22);
+		break;
+
+	case 2:
+		pr_debug("set spkr path\n");
+		snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTL");
+		snd_soc_dapm_disable_pin(&codec->dapm, "IHFOUTR");
+		snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x44);
+		break;
+
+	case 3:
+		pr_debug("set null path\n");
+		snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTL");
+		snd_soc_dapm_disable_pin(&codec->dapm, "LINEOUTR");
+		snd_soc_update_bits(codec, SN95031_LOCTL, 0x66, 0x66);
+		break;
+	}
+	snd_soc_dapm_sync(&codec->dapm);
+	lo_dac = ucontrol->value.integer.value[0];
+	return 0;
+}
+
+static const struct snd_kcontrol_new mfld_snd_controls[] = {
+	SOC_ENUM_EXT("Playback Switch", headset_enum,
+			headset_get_switch, headset_set_switch),
+	SOC_ENUM_EXT("Lineout Mux", lo_enum,
+			lo_get_switch, lo_set_switch),
+};
+
+static const struct snd_soc_dapm_widget mfld_widgets[] = {
+	SND_SOC_DAPM_HP("Headphones", NULL),
+	SND_SOC_DAPM_MIC("Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route mfld_map[] = {
+	{"Headphones", NULL, "HPOUTR"},
+	{"Headphones", NULL, "HPOUTL"},
+	{"Mic", NULL, "AMIC1"},
+};
+
+static void mfld_jack_check(unsigned int intr_status)
+{
+	struct mfld_jack_data jack_data;
+
+	jack_data.mfld_jack = &mfld_jack;
+	jack_data.intr_id = intr_status;
+
+	sn95031_jack_detection(&jack_data);
+	/* TODO: add american headset detection post gpiolib support */
+}
+
+static int mfld_init(struct snd_soc_pcm_runtime *runtime)
+{
+	struct snd_soc_codec *codec = runtime->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret_val;
+
+	/* Add jack sense widgets */
+	snd_soc_dapm_new_controls(dapm, mfld_widgets, ARRAY_SIZE(mfld_widgets));
+
+	/* Set up the map */
+	snd_soc_dapm_add_routes(dapm, mfld_map, ARRAY_SIZE(mfld_map));
+
+	/* always connected */
+	snd_soc_dapm_enable_pin(dapm, "Headphones");
+	snd_soc_dapm_enable_pin(dapm, "Mic");
+	snd_soc_dapm_sync(dapm);
+
+	ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
+				ARRAY_SIZE(mfld_snd_controls));
+	if (ret_val) {
+		pr_err("soc_add_controls failed %d", ret_val);
+		return ret_val;
+	}
+	/* default is earpiece pin, userspace sets it explcitly */
+	snd_soc_dapm_disable_pin(dapm, "Headphones");
+	/* default is lineout NC, userspace sets it explcitly */
+	snd_soc_dapm_disable_pin(dapm, "LINEOUTL");
+	snd_soc_dapm_disable_pin(dapm, "LINEOUTR");
+	lo_dac = 3;
+	hs_switch = 0;
+	/* we dont use linein in this so set to NC */
+	snd_soc_dapm_disable_pin(dapm, "LINEINL");
+	snd_soc_dapm_disable_pin(dapm, "LINEINR");
+	snd_soc_dapm_sync(dapm);
+
+	/* Headset and button jack detection */
+	ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
+			SND_JACK_HEADSET | SND_JACK_BTN_0 |
+			SND_JACK_BTN_1, &mfld_jack);
+	if (ret_val) {
+		pr_err("jack creation failed\n");
+		return ret_val;
+	}
+
+	ret_val = snd_soc_jack_add_pins(&mfld_jack,
+			ARRAY_SIZE(mfld_jack_pins), mfld_jack_pins);
+	if (ret_val) {
+		pr_err("adding jack pins failed\n");
+		return ret_val;
+	}
+	ret_val = snd_soc_jack_add_zones(&mfld_jack,
+			ARRAY_SIZE(mfld_zones), mfld_zones);
+	if (ret_val) {
+		pr_err("adding jack zones failed\n");
+		return ret_val;
+	}
+
+	/* we want to check if anything is inserted at boot,
+	 * so send a fake event to codec and it will read adc
+	 * to find if anything is there or not */
+	mfld_jack_check(MFLD_JACK_INSERT);
+	return ret_val;
+}
+
+struct snd_soc_dai_link mfld_msic_dailink[] = {
+	{
+		.name = "Medfield Headset",
+		.stream_name = "Headset",
+		.cpu_dai_name = "Headset-cpu-dai",
+		.codec_dai_name = "SN95031 Headset",
+		.codec_name = "sn95031",
+		.platform_name = "sst-platform",
+		.init = mfld_init,
+	},
+	{
+		.name = "Medfield Speaker",
+		.stream_name = "Speaker",
+		.cpu_dai_name = "Speaker-cpu-dai",
+		.codec_dai_name = "SN95031 Speaker",
+		.codec_name = "sn95031",
+		.platform_name = "sst-platform",
+		.init = NULL,
+	},
+	{
+		.name = "Medfield Vibra",
+		.stream_name = "Vibra1",
+		.cpu_dai_name = "Vibra1-cpu-dai",
+		.codec_dai_name = "SN95031 Vibra1",
+		.codec_name = "sn95031",
+		.platform_name = "sst-platform",
+		.init = NULL,
+	},
+	{
+		.name = "Medfield Haptics",
+		.stream_name = "Vibra2",
+		.cpu_dai_name = "Vibra2-cpu-dai",
+		.codec_dai_name = "SN95031 Vibra2",
+		.codec_name = "sn95031",
+		.platform_name = "sst-platform",
+		.init = NULL,
+	},
+};
+
+/* SoC card */
+static struct snd_soc_card snd_soc_card_mfld = {
+	.name = "medfield_audio",
+	.dai_link = mfld_msic_dailink,
+	.num_links = ARRAY_SIZE(mfld_msic_dailink),
+};
+
+static irqreturn_t snd_mfld_jack_intr_handler(int irq, void *dev)
+{
+	struct mfld_mc_private *mc_private = (struct mfld_mc_private *) dev;
+
+	memcpy_fromio(&mc_private->interrupt_status,
+			((void *)(mc_private->int_base)),
+			sizeof(u8));
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t snd_mfld_jack_detection(int irq, void *data)
+{
+	struct mfld_mc_private *mc_drv_ctx = (struct mfld_mc_private *) data;
+
+	if (mfld_jack.codec == NULL)
+		return IRQ_HANDLED;
+	mfld_jack_check(mc_drv_ctx->interrupt_status);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit snd_mfld_mc_probe(struct platform_device *pdev)
+{
+	int ret_val = 0, irq;
+	struct mfld_mc_private *mc_drv_ctx;
+	struct resource *irq_mem;
+
+	pr_debug("snd_mfld_mc_probe called\n");
+
+	/* retrive the irq number */
+	irq = platform_get_irq(pdev, 0);
+
+	/* audio interrupt base of SRAM location where
+	 * interrupts are stored by System FW */
+	mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC);
+	if (!mc_drv_ctx) {
+		pr_err("allocation failed\n");
+		return -ENOMEM;
+	}
+
+	irq_mem = platform_get_resource_byname(
+				pdev, IORESOURCE_MEM, "IRQ_BASE");
+	if (!irq_mem) {
+		pr_err("no mem resource given\n");
+		ret_val = -ENODEV;
+		goto unalloc;
+	}
+	mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start,
+					resource_size(irq_mem));
+	if (!mc_drv_ctx->int_base) {
+		pr_err("Mapping of cache failed\n");
+		ret_val = -ENOMEM;
+		goto unalloc;
+	}
+	/* register for interrupt */
+	ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler,
+			snd_mfld_jack_detection,
+			IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx);
+	if (ret_val) {
+		pr_err("cannot register IRQ\n");
+		goto unalloc;
+	}
+	/* register the soc card */
+	snd_soc_card_mfld.dev = &pdev->dev;
+	ret_val = snd_soc_register_card(&snd_soc_card_mfld);
+	if (ret_val) {
+		pr_debug("snd_soc_register_card failed %d\n", ret_val);
+		goto freeirq;
+	}
+	platform_set_drvdata(pdev, mc_drv_ctx);
+	pr_debug("successfully exited probe\n");
+	return ret_val;
+
+freeirq:
+	free_irq(irq, mc_drv_ctx);
+unalloc:
+	kfree(mc_drv_ctx);
+	return ret_val;
+}
+
+static int __devexit snd_mfld_mc_remove(struct platform_device *pdev)
+{
+	struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev);
+
+	pr_debug("snd_mfld_mc_remove called\n");
+	free_irq(platform_get_irq(pdev, 0), mc_drv_ctx);
+	snd_soc_unregister_card(&snd_soc_card_mfld);
+	kfree(mc_drv_ctx);
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver snd_mfld_mc_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "msic_audio",
+	},
+	.probe = snd_mfld_mc_probe,
+	.remove = __devexit_p(snd_mfld_mc_remove),
+};
+
+static int __init snd_mfld_driver_init(void)
+{
+	pr_debug("snd_mfld_driver_init called\n");
+	return platform_driver_register(&snd_mfld_mc_driver);
+}
+module_init(snd_mfld_driver_init);
+
+static void __exit snd_mfld_driver_exit(void)
+{
+	pr_debug("snd_mfld_driver_exit called\n");
+	platform_driver_unregister(&snd_mfld_mc_driver);
+}
+module_exit(snd_mfld_driver_exit);
+
+MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:msic-audio");
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
new file mode 100644
index 0000000..ee2c224
--- /dev/null
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -0,0 +1,474 @@
+/*
+ *  sst_platform.c - Intel MID Platform driver
+ *
+ *  Copyright (C) 2010 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@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; 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include "../../../drivers/staging/intel_sst/intel_sst_ioctl.h"
+#include "../../../drivers/staging/intel_sst/intel_sst.h"
+#include "sst_platform.h"
+
+static struct snd_pcm_hardware sst_platform_pcm_hw = {
+	.info =	(SNDRV_PCM_INFO_INTERLEAVED |
+			SNDRV_PCM_INFO_DOUBLE |
+			SNDRV_PCM_INFO_PAUSE |
+			SNDRV_PCM_INFO_RESUME |
+			SNDRV_PCM_INFO_MMAP|
+			SNDRV_PCM_INFO_MMAP_VALID |
+			SNDRV_PCM_INFO_BLOCK_TRANSFER |
+			SNDRV_PCM_INFO_SYNC_START),
+	.formats = (SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_U16 |
+			SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_U24 |
+			SNDRV_PCM_FMTBIT_S32 | SNDRV_PCM_FMTBIT_U32),
+	.rates = (SNDRV_PCM_RATE_8000|
+			SNDRV_PCM_RATE_44100 |
+			SNDRV_PCM_RATE_48000),
+	.rate_min = SST_MIN_RATE,
+	.rate_max = SST_MAX_RATE,
+	.channels_min =	SST_MIN_CHANNEL,
+	.channels_max =	SST_MAX_CHANNEL,
+	.buffer_bytes_max = SST_MAX_BUFFER,
+	.period_bytes_min = SST_MIN_PERIOD_BYTES,
+	.period_bytes_max = SST_MAX_PERIOD_BYTES,
+	.periods_min = SST_MIN_PERIODS,
+	.periods_max = SST_MAX_PERIODS,
+	.fifo_size = SST_FIFO_SIZE,
+};
+
+/* MFLD - MSIC */
+struct snd_soc_dai_driver sst_platform_dai[] = {
+{
+	.name = "Headset-cpu-dai",
+	.id = 0,
+	.playback = {
+		.channels_min = SST_STEREO,
+		.channels_max = SST_STEREO,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S24_LE,
+	},
+	.capture = {
+		.channels_min = 1,
+		.channels_max = 5,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S24_LE,
+	},
+},
+{
+	.name = "Speaker-cpu-dai",
+	.id = 1,
+	.playback = {
+		.channels_min = SST_MONO,
+		.channels_max = SST_STEREO,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S24_LE,
+	},
+},
+{
+	.name = "Vibra1-cpu-dai",
+	.id = 2,
+	.playback = {
+		.channels_min = SST_MONO,
+		.channels_max = SST_MONO,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S24_LE,
+	},
+},
+{
+	.name = "Vibra2-cpu-dai",
+	.id = 3,
+	.playback = {
+		.channels_min = SST_MONO,
+		.channels_max = SST_STEREO,
+		.rates = SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S24_LE,
+	},
+},
+};
+
+/* helper functions */
+static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
+					int state)
+{
+	spin_lock(&stream->status_lock);
+	stream->stream_status = state;
+	spin_unlock(&stream->status_lock);
+}
+
+static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
+{
+	int state;
+
+	spin_lock(&stream->status_lock);
+	state = stream->stream_status;
+	spin_unlock(&stream->status_lock);
+	return state;
+}
+
+static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
+				struct snd_sst_stream_params *param)
+{
+
+	param->uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
+	param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
+	param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
+	param->uc.pcm_params.reserved = 0;
+	param->uc.pcm_params.sfreq = substream->runtime->rate;
+	param->uc.pcm_params.ring_buffer_size =
+					snd_pcm_lib_buffer_bytes(substream);
+	param->uc.pcm_params.period_count = substream->runtime->period_size;
+	param->uc.pcm_params.ring_buffer_addr =
+				virt_to_phys(substream->dma_buffer.area);
+	pr_debug("period_cnt = %d\n", param->uc.pcm_params.period_count);
+	pr_debug("sfreq= %d, wd_sz = %d\n",
+		 param->uc.pcm_params.sfreq, param->uc.pcm_params.pcm_wd_sz);
+}
+
+static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
+{
+	struct sst_runtime_stream *stream =
+			substream->runtime->private_data;
+	struct snd_sst_stream_params param = {{{0,},},};
+	struct snd_sst_params str_params = {0};
+	int ret_val;
+
+	/* set codec params and inform SST driver the same */
+	sst_fill_pcm_params(substream, &param);
+	substream->runtime->dma_area = substream->dma_buffer.area;
+	str_params.sparams = param;
+	str_params.codec =  param.uc.pcm_params.codec;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		str_params.ops = STREAM_OPS_PLAYBACK;
+		str_params.device_type = substream->pcm->device + 1;
+		pr_debug("Playbck stream,Device %d\n",
+					substream->pcm->device);
+	} else {
+		str_params.ops = STREAM_OPS_CAPTURE;
+		str_params.device_type = SND_SST_DEVICE_CAPTURE;
+		pr_debug("Capture stream,Device %d\n",
+					substream->pcm->device);
+	}
+	ret_val = stream->sstdrv_ops->pcm_control->open(&str_params);
+	pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
+	if (ret_val < 0)
+		return ret_val;
+
+	stream->stream_info.str_id = ret_val;
+	pr_debug("str id :  %d\n", stream->stream_info.str_id);
+	return ret_val;
+}
+
+static void sst_period_elapsed(void *mad_substream)
+{
+	struct snd_pcm_substream *substream = mad_substream;
+	struct sst_runtime_stream *stream;
+	int status;
+
+	if (!substream || !substream->runtime)
+		return;
+	stream = substream->runtime->private_data;
+	if (!stream)
+		return;
+	status = sst_get_stream_status(stream);
+	if (status != SST_PLATFORM_RUNNING)
+		return;
+	snd_pcm_period_elapsed(substream);
+}
+
+static int sst_platform_init_stream(struct snd_pcm_substream *substream)
+{
+	struct sst_runtime_stream *stream =
+			substream->runtime->private_data;
+	int ret_val;
+
+	pr_debug("setting buffer ptr param\n");
+	sst_set_stream_status(stream, SST_PLATFORM_INIT);
+	stream->stream_info.period_elapsed = sst_period_elapsed;
+	stream->stream_info.mad_substream = substream;
+	stream->stream_info.buffer_ptr = 0;
+	stream->stream_info.sfreq = substream->runtime->rate;
+	ret_val = stream->sstdrv_ops->pcm_control->device_control(
+			SST_SND_STREAM_INIT, &stream->stream_info);
+	if (ret_val)
+		pr_err("control_set ret error %d\n", ret_val);
+	return ret_val;
+
+}
+/* end -- helper functions */
+
+static int sst_platform_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime;
+	struct sst_runtime_stream *stream;
+	int ret_val = 0;
+
+	pr_debug("sst_platform_open called\n");
+	runtime = substream->runtime;
+	runtime->hw = sst_platform_pcm_hw;
+	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+	if (!stream)
+		return -ENOMEM;
+	spin_lock_init(&stream->status_lock);
+	stream->stream_info.str_id = 0;
+	sst_set_stream_status(stream, SST_PLATFORM_INIT);
+	stream->stream_info.mad_substream = substream;
+	/* allocate memory for SST API set */
+	stream->sstdrv_ops = kzalloc(sizeof(*stream->sstdrv_ops),
+							GFP_KERNEL);
+	if (!stream->sstdrv_ops) {
+		pr_err("sst: mem allocation for ops fail\n");
+		kfree(stream);
+		return -ENOMEM;
+	}
+	stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID;
+	/* registering with SST driver to get access to SST APIs to use */
+	ret_val = register_sst_card(stream->sstdrv_ops);
+	if (ret_val) {
+		pr_err("sst: sst card registration failed\n");
+		return ret_val;
+	}
+	runtime->private_data = stream;
+	return snd_pcm_hw_constraint_integer(runtime,
+			 SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
+static int sst_platform_close(struct snd_pcm_substream *substream)
+{
+	struct sst_runtime_stream *stream;
+	int ret_val = 0, str_id;
+
+	pr_debug("sst_platform_close called\n");
+	stream = substream->runtime->private_data;
+	str_id = stream->stream_info.str_id;
+	if (str_id)
+		ret_val = stream->sstdrv_ops->pcm_control->close(str_id);
+	kfree(stream->sstdrv_ops);
+	kfree(stream);
+	return ret_val;
+}
+
+static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
+{
+	struct sst_runtime_stream *stream;
+	int ret_val = 0, str_id;
+
+	pr_debug("sst_platform_pcm_prepare called\n");
+	stream = substream->runtime->private_data;
+	str_id = stream->stream_info.str_id;
+	if (stream->stream_info.str_id) {
+		ret_val = stream->sstdrv_ops->pcm_control->device_control(
+					SST_SND_DROP, &str_id);
+		return ret_val;
+	}
+
+	ret_val = sst_platform_alloc_stream(substream);
+	if (ret_val < 0)
+		return ret_val;
+	snprintf(substream->pcm->id, sizeof(substream->pcm->id),
+			"%d", stream->stream_info.str_id);
+
+	ret_val = sst_platform_init_stream(substream);
+	if (ret_val)
+		return ret_val;
+	substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
+	return ret_val;
+}
+
+static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
+					int cmd)
+{
+	int ret_val = 0, str_id;
+	struct sst_runtime_stream *stream;
+	int str_cmd, status;
+
+	pr_debug("sst_platform_pcm_trigger called\n");
+	stream = substream->runtime->private_data;
+	str_id = stream->stream_info.str_id;
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		pr_debug("sst: Trigger Start\n");
+		str_cmd = SST_SND_START;
+		status = SST_PLATFORM_RUNNING;
+		stream->stream_info.mad_substream = substream;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		pr_debug("sst: in stop\n");
+		str_cmd = SST_SND_DROP;
+		status = SST_PLATFORM_DROPPED;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		pr_debug("sst: in pause\n");
+		str_cmd = SST_SND_PAUSE;
+		status = SST_PLATFORM_PAUSED;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		pr_debug("sst: in pause release\n");
+		str_cmd = SST_SND_RESUME;
+		status = SST_PLATFORM_RUNNING;
+		break;
+	default:
+		return -EINVAL;
+	}
+	ret_val = stream->sstdrv_ops->pcm_control->device_control(str_cmd,
+								&str_id);
+	if (!ret_val)
+		sst_set_stream_status(stream, status);
+
+	return ret_val;
+}
+
+
+static snd_pcm_uframes_t sst_platform_pcm_pointer
+			(struct snd_pcm_substream *substream)
+{
+	struct sst_runtime_stream *stream;
+	int ret_val, status;
+	struct pcm_stream_info *str_info;
+
+	stream = substream->runtime->private_data;
+	status = sst_get_stream_status(stream);
+	if (status == SST_PLATFORM_INIT)
+		return 0;
+	str_info = &stream->stream_info;
+	ret_val = stream->sstdrv_ops->pcm_control->device_control(
+				SST_SND_BUFFER_POINTER, str_info);
+	if (ret_val) {
+		pr_err("sst: error code = %d\n", ret_val);
+		return ret_val;
+	}
+	return stream->stream_info.buffer_ptr;
+}
+
+static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params)
+{
+	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+	memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
+
+	return 0;
+}
+
+static struct snd_pcm_ops sst_platform_ops = {
+	.open = sst_platform_open,
+	.close = sst_platform_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.prepare = sst_platform_pcm_prepare,
+	.trigger = sst_platform_pcm_trigger,
+	.pointer = sst_platform_pcm_pointer,
+	.hw_params = sst_platform_pcm_hw_params,
+};
+
+static void sst_pcm_free(struct snd_pcm *pcm)
+{
+	pr_debug("sst_pcm_free called\n");
+	snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+int sst_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+			struct snd_pcm *pcm)
+{
+	int retval = 0;
+
+	pr_debug("sst_pcm_new called\n");
+	if (dai->driver->playback.channels_min ||
+			dai->driver->capture.channels_min) {
+		retval =  snd_pcm_lib_preallocate_pages_for_all(pcm,
+			SNDRV_DMA_TYPE_CONTINUOUS,
+			snd_dma_continuous_data(GFP_KERNEL),
+			SST_MIN_BUFFER, SST_MAX_BUFFER);
+		if (retval) {
+			pr_err("dma buffer allocationf fail\n");
+			return retval;
+		}
+	}
+	return retval;
+}
+struct snd_soc_platform_driver sst_soc_platform_drv = {
+	.ops		= &sst_platform_ops,
+	.pcm_new	= sst_pcm_new,
+	.pcm_free	= sst_pcm_free,
+};
+
+static int sst_platform_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	pr_debug("sst_platform_probe called\n");
+	ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
+	if (ret) {
+		pr_err("registering soc platform failed\n");
+		return ret;
+	}
+
+	ret = snd_soc_register_dais(&pdev->dev,
+				sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
+	if (ret) {
+		pr_err("registering cpu dais failed\n");
+		snd_soc_unregister_platform(&pdev->dev);
+	}
+	return ret;
+}
+
+static int sst_platform_remove(struct platform_device *pdev)
+{
+
+	snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sst_platform_dai));
+	snd_soc_unregister_platform(&pdev->dev);
+	pr_debug("sst_platform_remove sucess\n");
+	return 0;
+}
+
+static struct platform_driver sst_platform_driver = {
+	.driver		= {
+		.name		= "sst-platform",
+		.owner		= THIS_MODULE,
+	},
+	.probe		= sst_platform_probe,
+	.remove		= sst_platform_remove,
+};
+
+static int __init sst_soc_platform_init(void)
+{
+	pr_debug("sst_soc_platform_init called\n");
+	return  platform_driver_register(&sst_platform_driver);
+}
+module_init(sst_soc_platform_init);
+
+static void __exit sst_soc_platform_exit(void)
+{
+	platform_driver_unregister(&sst_platform_driver);
+	pr_debug("sst_soc_platform_exit sucess\n");
+}
+module_exit(sst_soc_platform_exit);
+
+MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
+MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sst-platform");
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h
new file mode 100644
index 0000000..df37028
--- /dev/null
+++ b/sound/soc/mid-x86/sst_platform.h
@@ -0,0 +1,63 @@
+/*
+ *  sst_platform.h - Intel MID Platform driver header file
+ *
+ *  Copyright (C) 2010 Intel Corp
+ *  Author: Vinod Koul <vinod.koul@intel.com>
+ *  Author: Harsha Priya <priya.harsha@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; 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 __SST_PLATFORMDRV_H__
+#define __SST_PLATFORMDRV_H__
+
+#define SST_MONO		1
+#define SST_STEREO		2
+#define SST_MAX_CAP		5
+
+#define SST_MIN_RATE		8000
+#define SST_MAX_RATE		48000
+#define SST_MIN_CHANNEL		1
+#define SST_MAX_CHANNEL		5
+#define SST_MAX_BUFFER		(800*1024)
+#define SST_MIN_BUFFER		(800*1024)
+#define SST_MIN_PERIOD_BYTES	32
+#define SST_MAX_PERIOD_BYTES	SST_MAX_BUFFER
+#define SST_MIN_PERIODS		2
+#define SST_MAX_PERIODS		(1024*2)
+#define SST_FIFO_SIZE		0
+#define SST_CARD_NAMES		"intel_mid_card"
+#define MSIC_VENDOR_ID		3
+
+struct sst_runtime_stream {
+	int     stream_status;
+	struct pcm_stream_info stream_info;
+	struct intel_sst_card_ops *sstdrv_ops;
+	spinlock_t	status_lock;
+};
+
+enum sst_drv_status {
+	SST_PLATFORM_INIT = 1,
+	SST_PLATFORM_STARTED,
+	SST_PLATFORM_RUNNING,
+	SST_PLATFORM_PAUSED,
+	SST_PLATFORM_DROPPED,
+};
+
+#endif
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index a088db6..b592298 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -24,6 +24,7 @@ config SND_OMAP_SOC_RX51
 	select OMAP_MCBSP
 	select SND_OMAP_SOC_MCBSP
 	select SND_SOC_TLV320AIC3X
+	select SND_SOC_TPA6130A2
 	help
 	  Say Y if you want to add support for SoC audio on Nokia RX-51
 	  hardware. This is also known as Nokia N900 product.
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index d203f4d..2175f09 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -69,110 +69,6 @@ static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
  */
 static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
 
-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
-static const int omap1_dma_reqs[][2] = {
-	{ OMAP_DMA_MCBSP1_TX, OMAP_DMA_MCBSP1_RX },
-	{ OMAP_DMA_MCBSP2_TX, OMAP_DMA_MCBSP2_RX },
-	{ OMAP_DMA_MCBSP3_TX, OMAP_DMA_MCBSP3_RX },
-};
-static const unsigned long omap1_mcbsp_port[][2] = {
-	{ OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
-	  OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
-	{ OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
-	  OMAP1510_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
-	{ OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DXR1,
-	  OMAP1510_MCBSP3_BASE + OMAP_MCBSP_REG_DRR1 },
-};
-#else
-static const int omap1_dma_reqs[][2] = {};
-static const unsigned long omap1_mcbsp_port[][2] = {};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-static const int omap24xx_dma_reqs[][2] = {
-	{ OMAP24XX_DMA_MCBSP1_TX, OMAP24XX_DMA_MCBSP1_RX },
-	{ OMAP24XX_DMA_MCBSP2_TX, OMAP24XX_DMA_MCBSP2_RX },
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
-	{ OMAP24XX_DMA_MCBSP3_TX, OMAP24XX_DMA_MCBSP3_RX },
-	{ OMAP24XX_DMA_MCBSP4_TX, OMAP24XX_DMA_MCBSP4_RX },
-	{ OMAP24XX_DMA_MCBSP5_TX, OMAP24XX_DMA_MCBSP5_RX },
-#endif
-};
-#else
-static const int omap24xx_dma_reqs[][2] = {};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-static const int omap44xx_dma_reqs[][2] = {
-	{ OMAP44XX_DMA_MCBSP1_TX, OMAP44XX_DMA_MCBSP1_RX },
-	{ OMAP44XX_DMA_MCBSP2_TX, OMAP44XX_DMA_MCBSP2_RX },
-	{ OMAP44XX_DMA_MCBSP3_TX, OMAP44XX_DMA_MCBSP3_RX },
-	{ OMAP44XX_DMA_MCBSP4_TX, OMAP44XX_DMA_MCBSP4_RX },
-};
-#else
-static const int omap44xx_dma_reqs[][2] = {};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2420)
-static const unsigned long omap2420_mcbsp_port[][2] = {
-	{ OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1,
-	  OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1 },
-	{ OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1,
-	  OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1 },
-};
-#else
-static const unsigned long omap2420_mcbsp_port[][2] = {};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2430)
-static const unsigned long omap2430_mcbsp_port[][2] = {
-	{ OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP24XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP2430_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP2430_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP2430_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
-};
-#else
-static const unsigned long omap2430_mcbsp_port[][2] = {};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-static const unsigned long omap34xx_mcbsp_port[][2] = {
-	{ OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP34XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP34XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP34XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP34XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP34XX_MCBSP5_BASE + OMAP_MCBSP_REG_DRR },
-};
-#else
-static const unsigned long omap34xx_mcbsp_port[][2] = {};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-static const unsigned long omap44xx_mcbsp_port[][2] = {
-	{ OMAP44XX_MCBSP1_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP44XX_MCBSP1_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP44XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP44XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP44XX_MCBSP3_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP44XX_MCBSP3_BASE + OMAP_MCBSP_REG_DRR },
-	{ OMAP44XX_MCBSP4_BASE + OMAP_MCBSP_REG_DXR,
-	  OMAP44XX_MCBSP4_BASE + OMAP_MCBSP_REG_DRR },
-};
-#else
-static const unsigned long omap44xx_mcbsp_port[][2] = {};
-#endif
-
 static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -346,24 +242,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
 	unsigned int format, div, framesize, master;
 
 	dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
-	if (cpu_class_is_omap1()) {
-		dma = omap1_dma_reqs[bus_id][substream->stream];
-		port = omap1_mcbsp_port[bus_id][substream->stream];
-	} else if (cpu_is_omap2420()) {
-		dma = omap24xx_dma_reqs[bus_id][substream->stream];
-		port = omap2420_mcbsp_port[bus_id][substream->stream];
-	} else if (cpu_is_omap2430()) {
-		dma = omap24xx_dma_reqs[bus_id][substream->stream];
-		port = omap2430_mcbsp_port[bus_id][substream->stream];
-	} else if (cpu_is_omap343x()) {
-		dma = omap24xx_dma_reqs[bus_id][substream->stream];
-		port = omap34xx_mcbsp_port[bus_id][substream->stream];
-	 } else if (cpu_is_omap44xx()) {
-		dma = omap44xx_dma_reqs[bus_id][substream->stream];
-		port = omap44xx_mcbsp_port[bus_id][substream->stream];
-	} else {
-		return -ENODEV;
-	}
+
+	dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream);
+	port = omap_mcbsp_dma_reg_params(bus_id, substream->stream);
+
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
 		dma_data->data_type = OMAP_DMA_DATA_TYPE_S16;
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 110c106..37dc721 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -43,7 +43,7 @@ enum omap_mcbsp_div {
 	OMAP_MCBSP_CLKGDV,		/* Sample rate generator divider */
 };
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 #define NUM_LINKS	2
 #endif
 #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
@@ -54,7 +54,7 @@ enum omap_mcbsp_div {
 #undef  NUM_LINKS
 #define NUM_LINKS	4
 #endif
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430)
 #undef  NUM_LINKS
 #define NUM_LINKS	5
 #endif
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 09fb0df..d098622 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -31,6 +31,7 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 #include <plat/mcbsp.h>
+#include "../codecs/tpa6130a2.h"
 
 #include <asm/mach-types.h>
 
@@ -39,6 +40,7 @@
 
 #define RX51_TVOUT_SEL_GPIO		40
 #define RX51_JACK_DETECT_GPIO		177
+#define RX51_ECI_SW_GPIO		182
 /*
  * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This
  * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -47,7 +49,9 @@
 
 enum {
 	RX51_JACK_DISABLED,
-	RX51_JACK_TVOUT,		/* tv-out */
+	RX51_JACK_TVOUT,		/* tv-out with stereo output */
+	RX51_JACK_HP,			/* headphone: stereo output, no mic */
+	RX51_JACK_HS,			/* headset: stereo output with mic */
 };
 
 static int rx51_spk_func;
@@ -57,6 +61,19 @@ static int rx51_jack_func;
 static void rx51_ext_control(struct snd_soc_codec *codec)
 {
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int hp = 0, hs = 0, tvout = 0;
+
+	switch (rx51_jack_func) {
+	case RX51_JACK_TVOUT:
+		tvout = 1;
+		hp = 1;
+		break;
+	case RX51_JACK_HS:
+		hs = 1;
+	case RX51_JACK_HP:
+		hp = 1;
+		break;
+	}
 
 	if (rx51_spk_func)
 		snd_soc_dapm_enable_pin(dapm, "Ext Spk");
@@ -66,9 +83,16 @@ static void rx51_ext_control(struct snd_soc_codec *codec)
 		snd_soc_dapm_enable_pin(dapm, "DMic");
 	else
 		snd_soc_dapm_disable_pin(dapm, "DMic");
+	if (hp)
+		snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
+	else
+		snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
+	if (hs)
+		snd_soc_dapm_enable_pin(dapm, "HS Mic");
+	else
+		snd_soc_dapm_disable_pin(dapm, "HS Mic");
 
-	gpio_set_value(RX51_TVOUT_SEL_GPIO,
-		       rx51_jack_func == RX51_JACK_TVOUT);
+	gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
 
 	snd_soc_dapm_sync(dapm);
 }
@@ -153,6 +177,19 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int rx51_hp_event(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_codec *codec = w->dapm->codec;
+
+	if (SND_SOC_DAPM_EVENT_ON(event))
+		tpa6130a2_stereo_enable(codec, 1);
+	else
+		tpa6130a2_stereo_enable(codec, 0);
+
+	return 0;
+}
+
 static int rx51_get_input(struct snd_kcontrol *kcontrol,
 			  struct snd_ctl_elem_value *ucontrol)
 {
@@ -203,7 +240,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
 	{
 		.gpio = RX51_JACK_DETECT_GPIO,
 		.name = "avdet-gpio",
-		.report = SND_JACK_VIDEOOUT,
+		.report = SND_JACK_HEADSET,
 		.invert = 1,
 		.debounce_time = 200,
 	},
@@ -212,19 +249,38 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
 static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
 	SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
 	SND_SOC_DAPM_MIC("DMic", NULL),
+	SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
+	SND_SOC_DAPM_MIC("HS Mic", NULL),
+	SND_SOC_DAPM_LINE("FM Transmitter", NULL),
+};
+
+static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = {
+	SND_SOC_DAPM_SPK("Earphone", NULL),
 };
 
 static const struct snd_soc_dapm_route audio_map[] = {
 	{"Ext Spk", NULL, "HPLOUT"},
 	{"Ext Spk", NULL, "HPROUT"},
+	{"Headphone Jack", NULL, "LLOUT"},
+	{"Headphone Jack", NULL, "RLOUT"},
+	{"FM Transmitter", NULL, "LLOUT"},
+	{"FM Transmitter", NULL, "RLOUT"},
 
 	{"DMic Rate 64", NULL, "Mic Bias 2V"},
 	{"Mic Bias 2V", NULL, "DMic"},
 };
 
+static const struct snd_soc_dapm_route audio_mapb[] = {
+	{"b LINE2R", NULL, "MONO_LOUT"},
+	{"Earphone", NULL, "b HPLOUT"},
+
+	{"LINE1L", NULL, "b Mic Bias 2.5V"},
+	{"b Mic Bias 2.5V", NULL, "HS Mic"}
+};
+
 static const char *spk_function[] = {"Off", "On"};
 static const char *input_function[] = {"ADC", "Digital Mic"};
-static const char *jack_function[] = {"Off", "TV-OUT"};
+static const char *jack_function[] = {"Off", "TV-OUT", "Headphone", "Headset"};
 
 static const struct soc_enum rx51_enum[] = {
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
@@ -239,6 +295,11 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
 		     rx51_get_input, rx51_set_input),
 	SOC_ENUM_EXT("Jack Function", rx51_enum[2],
 		     rx51_get_jack, rx51_set_jack),
+	SOC_DAPM_PIN_SWITCH("FM Transmitter"),
+};
+
+static const struct snd_kcontrol_new aic34_rx51_controlsb[] = {
+	SOC_DAPM_PIN_SWITCH("Earphone"),
 };
 
 static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
@@ -265,11 +326,21 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	/* Set up RX-51 specific audio path audio_map */
 	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
 
+	err = tpa6130a2_add_controls(codec);
+	if (err < 0)
+		return err;
+	snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
+
+	err = omap_mcbsp_st_add_controls(codec, 1);
+	if (err < 0)
+		return err;
+
 	snd_soc_dapm_sync(dapm);
 
 	/* AV jack detection */
 	err = snd_soc_jack_new(codec, "AV Jack",
-			       SND_JACK_VIDEOOUT, &rx51_av_jack);
+			       SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
+			       &rx51_av_jack);
 	if (err)
 		return err;
 	err = snd_soc_jack_add_gpios(&rx51_av_jack,
@@ -279,6 +350,24 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
 	return err;
 }
 
+static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
+{
+	int err;
+
+	err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
+				   ARRAY_SIZE(aic34_rx51_controlsb));
+	if (err < 0)
+		return err;
+
+	err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb,
+					ARRAY_SIZE(aic34_dapm_widgetsb));
+	if (err < 0)
+		return 0;
+
+	return snd_soc_dapm_add_routes(dapm, audio_mapb,
+				       ARRAY_SIZE(audio_mapb));
+}
+
 /* Digital audio interface glue - connects codec <--> CPU */
 static struct snd_soc_dai_link rx51_dai[] = {
 	{
@@ -293,11 +382,30 @@ static struct snd_soc_dai_link rx51_dai[] = {
 	},
 };
 
+struct snd_soc_aux_dev rx51_aux_dev[] = {
+	{
+		.name = "TLV320AIC34b",
+		.codec_name = "tlv320aic3x-codec.2-0019",
+		.init = rx51_aic34b_init,
+	},
+};
+
+static struct snd_soc_codec_conf rx51_codec_conf[] = {
+	{
+		.dev_name = "tlv320aic3x-codec.2-0019",
+		.name_prefix = "b",
+	},
+};
+
 /* Audio card */
 static struct snd_soc_card rx51_sound_card = {
 	.name = "RX-51",
 	.dai_link = rx51_dai,
 	.num_links = ARRAY_SIZE(rx51_dai),
+	.aux_dev = rx51_aux_dev,
+	.num_aux_devs = ARRAY_SIZE(rx51_aux_dev),
+	.codec_conf = rx51_codec_conf,
+	.num_configs = ARRAY_SIZE(rx51_codec_conf),
 };
 
 static struct platform_device *rx51_snd_device;
@@ -309,10 +417,14 @@ static int __init rx51_soc_init(void)
 	if (!machine_is_nokia_rx51())
 		return -ENODEV;
 
-	err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel");
+	err = gpio_request_one(RX51_TVOUT_SEL_GPIO,
+			       GPIOF_DIR_OUT | GPIOF_INIT_LOW, "tvout_sel");
 	if (err)
 		goto err_gpio_tvout_sel;
-	gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0);
+	err = gpio_request_one(RX51_ECI_SW_GPIO,
+			       GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "eci_sw");
+	if (err)
+		goto err_gpio_eci_sw;
 
 	rx51_snd_device = platform_device_alloc("soc-audio", -1);
 	if (!rx51_snd_device) {
@@ -330,6 +442,8 @@ static int __init rx51_soc_init(void)
 err2:
 	platform_device_put(rx51_snd_device);
 err1:
+	gpio_free(RX51_ECI_SW_GPIO);
+err_gpio_eci_sw:
 	gpio_free(RX51_TVOUT_SEL_GPIO);
 err_gpio_tvout_sel:
 
@@ -342,6 +456,7 @@ static void __exit rx51_soc_exit(void)
 				rx51_av_jack_gpios);
 
 	platform_device_unregister(rx51_snd_device);
+	gpio_free(RX51_ECI_SW_GPIO);
 	gpio_free(RX51_TVOUT_SEL_GPIO);
 }
 
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
index 0fd60f4..2afabaf 100644
--- a/sound/soc/pxa/raumfeld.c
+++ b/sound/soc/pxa/raumfeld.c
@@ -151,13 +151,13 @@ static struct snd_soc_ops raumfeld_cs4270_ops = {
 	.hw_params = raumfeld_cs4270_hw_params,
 };
 
-static int raumfeld_line_suspend(struct platform_device *pdev, pm_message_t state)
+static int raumfeld_line_suspend(struct snd_soc_card *card)
 {
 	raumfeld_enable_audio(false);
 	return 0;
 }
 
-static int raumfeld_line_resume(struct platform_device *pdev)
+static int raumfeld_line_resume(struct snd_soc_card *card)
 {
 	raumfeld_enable_audio(true);
 	return 0;
@@ -229,19 +229,19 @@ static struct snd_soc_dai_link raumfeld_dai[] = {
 {
 	.name		= "ak4104",
 	.stream_name	= "Playback",
-	.cpu_dai_name = "pxa-ssp-dai.1",
-	.codec_dai_name = "ak4104-hifi",
-	.platform_name = "pxa-pcm-audio",
+	.cpu_dai_name	= "pxa-ssp-dai.1",
+	.codec_dai_name	= "ak4104-hifi",
+	.platform_name	= "pxa-pcm-audio",
 	.ops		= &raumfeld_ak4104_ops,
-	.codec_name = "ak4104-codec.0",
+	.codec_name	= "ak4104-codec.0",
 },
 {
 	.name		= "CS4270",
 	.stream_name	= "CS4270",
-	.cpu_dai_name = "pxa-ssp-dai.0",
-	.platform_name = "pxa-pcm-audio",
-	.codec_dai_name = "cs4270-hifi",
-	.codec_name = "cs4270-codec.0-0048",
+	.cpu_dai_name	= "pxa-ssp-dai.0",
+	.platform_name	= "pxa-pcm-audio",
+	.codec_dai_name	= "cs4270-hifi",
+	.codec_name	= "cs4270-codec.0-0048",
 	.ops		= &raumfeld_cs4270_ops,
 },};
 
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 4b6e5d6..9a23513 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -237,7 +237,7 @@ static struct snd_soc_dai_link tosa_dai[] = {
 },
 };
 
-static int tosa_probe(struct platform_device *dev)
+static int tosa_probe(struct snd_soc_card *card)
 {
 	int ret;
 
@@ -251,7 +251,7 @@ static int tosa_probe(struct platform_device *dev)
 	return ret;
 }
 
-static int tosa_remove(struct platform_device *dev)
+static int tosa_remove(struct snd_soc_card *card)
 {
 	gpio_free(TOSA_GPIO_L_MUTE);
 	return 0;
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c
index 3ceaef6..d69d9fc 100644
--- a/sound/soc/pxa/z2.c
+++ b/sound/soc/pxa/z2.c
@@ -95,6 +95,11 @@ static struct snd_soc_jack_pin hs_jack_pins[] = {
 		.pin	= "Headphone Jack",
 		.mask	= SND_JACK_HEADPHONE,
 	},
+	{
+		.pin    = "Ext Spk",
+		.mask   = SND_JACK_HEADPHONE,
+		.invert = 1
+	},
 };
 
 /* Headset jack detection gpios */
@@ -147,7 +152,7 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
 	snd_soc_dapm_disable_pin(dapm, "LINPUT3");
 	snd_soc_dapm_disable_pin(dapm, "RINPUT3");
 	snd_soc_dapm_disable_pin(dapm, "OUT3");
-	snd_soc_dapm_disable_pin(dapm, "MONO");
+	snd_soc_dapm_disable_pin(dapm, "MONO1");
 
 	/* Add z2 specific widgets */
 	snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index 25bba10..ac57726 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -189,7 +189,7 @@ static struct snd_soc_dai_link zylonite_dai[] = {
 },
 };
 
-static int zylonite_probe(struct platform_device *pdev)
+static int zylonite_probe(struct snd_soc_card *card)
 {
 	int ret;
 
@@ -216,7 +216,7 @@ static int zylonite_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int zylonite_remove(struct platform_device *pdev)
+static int zylonite_remove(struct snd_soc_card *card)
 {
 	if (clk_pout) {
 		clk_disable(pout);
@@ -226,8 +226,7 @@ static int zylonite_remove(struct platform_device *pdev)
 	return 0;
 }
 
-static int zylonite_suspend_post(struct platform_device *pdev,
-				 pm_message_t state)
+static int zylonite_suspend_post(struct snd_soc_card *card)
 {
 	if (clk_pout)
 		clk_disable(pout);
@@ -235,7 +234,7 @@ static int zylonite_suspend_post(struct platform_device *pdev,
 	return 0;
 }
 
-static int zylonite_resume_pre(struct platform_device *pdev)
+static int zylonite_resume_pre(struct snd_soc_card *card)
 {
 	int ret = 0;
 
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index a6a6b5f..a3fdfb6 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -1,6 +1,6 @@
 config SND_SOC_SAMSUNG
 	tristate "ASoC support for Samsung"
-	depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PV310
+	depends on ARCH_S3C2410 || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_EXYNOS4
 	select S3C64XX_DMA if ARCH_S3C64XX
 	select S3C2410_DMA if ARCH_S3C2410
 	help
@@ -35,23 +35,16 @@ config SND_SAMSUNG_I2S
 	tristate
 
 config SND_SOC_SAMSUNG_NEO1973_WM8753
-	tristate "SoC I2S Audio support for NEO1973 - WM8753"
-	depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA01
+	tristate "Audio support for Openmoko Neo1973 Smartphones (GTA01/GTA02)"
+	depends on SND_SOC_SAMSUNG && (MACH_NEO1973_GTA01 || 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 if you want to add support for SoC audio on smdk2440
-	  with the WM8753.
+	  Say Y here to enable audio support for the Openmoko Neo1973
+	  Smartphones.
 
-config SND_SOC_SAMSUNG_NEO1973_GTA02_WM8753
-	tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)"
-	depends on SND_SOC_SAMSUNG && MACH_NEO1973_GTA02
-	select SND_S3C24XX_I2S
-	select SND_SOC_WM8753
-	help
-	  This driver provides audio support for the Openmoko Neo FreeRunner
-	  smartphone.
-	  
 config SND_SOC_SAMSUNG_JIVE_WM8750
 	tristate "SoC I2S Audio support for Jive"
 	depends on SND_SOC_SAMSUNG && MACH_JIVE
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 705d4e8..294dec0 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o
 # S3C24XX Machine Support
 snd-soc-jive-wm8750-objs := jive_wm8750.o
 snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
-snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
 snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
 snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
 snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
@@ -38,7 +37,6 @@ snd-soc-smdk-spdif-objs := smdk_spdif.o
 
 obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
-obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
 obj-$(CONFIG_SND_SOC_SAMSUNG_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 4770a95..f97110e 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -12,24 +12,24 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 
 #include <sound/soc.h>
 
-#include <plat/regs-ac97.h>
 #include <mach/dma.h>
+#include <plat/regs-ac97.h>
 #include <plat/audio.h>
 
 #include "dma.h"
-#include "ac97.h"
 
 #define AC_CMD_ADDR(x) (x << 16)
 #define AC_CMD_DATA(x) (x & 0xffff)
 
+#define S3C_AC97_DAI_PCM 0
+#define S3C_AC97_DAI_MIC 1
+
 struct s3c_ac97_info {
 	struct clk         *ac97_clk;
 	void __iomem	   *regs;
diff --git a/sound/soc/samsung/ac97.h b/sound/soc/samsung/ac97.h
deleted file mode 100644
index 0d0e1b5..0000000
--- a/sound/soc/samsung/ac97.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* sound/soc/samsung/ac97.h
- *
- * ALSA SoC Audio Layer - S3C AC97 Controller driver
- *	Evolved from s3c2443-ac97.h
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Author: Jaswinder Singh <jassi.brar@samsung.com>
- *	Credits: Graeme Gregory, Sean Choi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S3C_AC97_H_
-#define __S3C_AC97_H_
-
-#define S3C_AC97_DAI_PCM 0
-#define S3C_AC97_DAI_MIC 1
-
-#endif /* __S3C_AC97_H_ */
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 2124019..5cb3b88 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -14,17 +14,11 @@
  *  option) any later version.
  */
 
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
 #include <asm/dma.h>
 #include <mach/hardware.h>
@@ -32,6 +26,9 @@
 
 #include "dma.h"
 
+#define ST_RUNNING		(1<<0)
+#define ST_OPENED		(1<<1)
+
 static const struct snd_pcm_hardware dma_hardware = {
 	.info			= SNDRV_PCM_INFO_INTERLEAVED |
 				    SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -313,7 +310,7 @@ dma_pointer(struct snd_pcm_substream *substream)
 	/* we seem to be getting the odd error from the pcm library due
 	 * to out-of-bounds pointers. this is maybe due to the dma engine
 	 * not having loaded the new values for the channel before being
-	 * callled... (todo - fix )
+	 * called... (todo - fix )
 	 */
 
 	if (res >= snd_pcm_lib_buffer_bytes(substream)) {
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index f8cd2b4..c506592 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -12,9 +12,6 @@
 #ifndef _S3C_AUDIO_H
 #define _S3C_AUDIO_H
 
-#define ST_RUNNING		(1<<0)
-#define ST_OPENED		(1<<1)
-
 struct s3c_dma_params {
 	struct s3c2410_dma_client *client;	/* stream identifier */
 	int channel;				/* Channel ID */
@@ -22,9 +19,4 @@ struct s3c_dma_params {
 	int dma_size;			/* Size of the DMA transfer */
 };
 
-#define S3C24XX_DAI_I2S			0
-
-/* platform data */
-extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
-
 #endif
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index 34dd9ef..f6b3a3c 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -11,21 +11,13 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
 #include <sound/soc.h>
 #include <sound/jack.h>
+
 #include <asm/mach-types.h>
 #include <mach/gpio.h>
-#include <mach/regs-clock.h>
 
-#include <linux/mfd/wm8994/core.h>
-#include <linux/mfd/wm8994/registers.h>
 #include "../codecs/wm8994.h"
-#include "dma.h"
-#include "i2s.h"
 
 #define MACHINE_NAME	0
 #define CPU_VOICE_DAI	1
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index c45f7ce..241f55d 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -13,25 +13,16 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
 #include <linux/gpio.h>
 
 #include <sound/soc.h>
-#include <sound/uda1380.h>
 #include <sound/jack.h>
 
 #include <plat/regs-iis.h>
-
 #include <mach/h1940-latch.h>
-
 #include <asm/mach-types.h>
 
-#include "dma.h"
 #include "s3c24xx-i2s.h"
-#include "../codecs/uda1380.h"
 
 static unsigned int rates[] = {
 	11025,
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index d00ac3a..ffa09b3 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -15,9 +15,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
 #include <plat/audio.h>
 
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c
index 0880252..3b53ad5 100644
--- a/sound/soc/samsung/jive_wm8750.c
+++ b/sound/soc/samsung/jive_wm8750.c
@@ -11,22 +11,11 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
 
-#include "dma.h"
 #include "s3c2412-i2s.h"
-
 #include "../codecs/wm8750.h"
 
 static const struct snd_soc_dapm_route audio_map[] = {
diff --git a/sound/soc/samsung/lm4857.h b/sound/soc/samsung/lm4857.h
deleted file mode 100644
index 0cf5b70..0000000
--- a/sound/soc/samsung/lm4857.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * lm4857.h  --  ALSA Soc Audio Layer
- *
- * Copyright 2007 Wolfson Microelectronics PLC.
- * Author: Graeme Gregory
- *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  Revision history
- *    18th Jun 2007   Initial version.
- */
-
-#ifndef LM4857_H_
-#define LM4857_H_
-
-/* The register offsets in the cache array */
-#define LM4857_MVOL 0
-#define LM4857_LVOL 1
-#define LM4857_RVOL 2
-#define LM4857_CTRL 3
-
-/* the shifts required to set these bits */
-#define LM4857_3D 5
-#define LM4857_WAKEUP 5
-#define LM4857_EPGAIN 4
-
-#endif /*LM4857_H_*/
-
diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c
index a2bb34d..bd91c19 100644
--- a/sound/soc/samsung/ln2440sbc_alc650.c
+++ b/sound/soc/samsung/ln2440sbc_alc650.c
@@ -16,15 +16,8 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
 #include <sound/soc.h>
 
-#include "dma.h"
-#include "ac97.h"
-
 static struct snd_soc_card ln2440sbc;
 
 static struct snd_soc_dai_link ln2440sbc_dai[] = {
diff --git a/sound/soc/samsung/neo1973_gta02_wm8753.c b/sound/soc/samsung/neo1973_gta02_wm8753.c
deleted file mode 100644
index 0d0ae2b..0000000
--- a/sound/soc/samsung/neo1973_gta02_wm8753.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * neo1973_gta02_wm8753.c  --  SoC audio for Openmoko Freerunner(GTA02)
- *
- * Copyright 2007 Openmoko Inc
- * Author: Graeme Gregory <graeme@openmoko.org>
- * Copyright 2007 Wolfson Microelectronics PLC.
- * Author: Graeme Gregory <linux@wolfsonmicro.com>
- * Copyright 2009 Wolfson Microelectronics
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-
-#include <asm/mach-types.h>
-
-#include <plat/regs-iis.h>
-
-#include <mach/regs-clock.h>
-#include <asm/io.h>
-#include <mach/gta02.h>
-#include "../codecs/wm8753.h"
-#include "dma.h"
-#include "s3c24xx-i2s.h"
-
-static struct snd_soc_card neo1973_gta02;
-
-static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
-	unsigned int pll_out = 0, bclk = 0;
-	int ret = 0;
-	unsigned long iis_clkrate;
-
-	iis_clkrate = s3c24xx_i2s_get_clockrate();
-
-	switch (params_rate(params)) {
-	case 8000:
-	case 16000:
-		pll_out = 12288000;
-		break;
-	case 48000:
-		bclk = WM8753_BCLK_DIV_4;
-		pll_out = 12288000;
-		break;
-	case 96000:
-		bclk = WM8753_BCLK_DIV_2;
-		pll_out = 12288000;
-		break;
-	case 11025:
-		bclk = WM8753_BCLK_DIV_16;
-		pll_out = 11289600;
-		break;
-	case 22050:
-		bclk = WM8753_BCLK_DIV_8;
-		pll_out = 11289600;
-		break;
-	case 44100:
-		bclk = WM8753_BCLK_DIV_4;
-		pll_out = 11289600;
-		break;
-	case 88200:
-		bclk = WM8753_BCLK_DIV_2;
-		pll_out = 11289600;
-		break;
-	}
-
-	/* set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai,
-		SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-		SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	/* set cpu DAI configuration */
-	ret = snd_soc_dai_set_fmt(cpu_dai,
-		SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
-		SND_SOC_DAIFMT_CBM_CFM);
-	if (ret < 0)
-		return ret;
-
-	/* set the codec system clock for DAC and ADC */
-	ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
-		SND_SOC_CLOCK_IN);
-	if (ret < 0)
-		return ret;
-
-	/* set MCLK division for sample rate */
-	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
-		S3C2410_IISMOD_32FS);
-	if (ret < 0)
-		return ret;
-
-	/* set codec BCLK division for sample rate */
-	ret = snd_soc_dai_set_clkdiv(codec_dai,
-					WM8753_BCLKDIV, bclk);
-	if (ret < 0)
-		return ret;
-
-	/* set prescaler division for sample rate */
-	ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
-		S3C24XX_PRESCALE(4, 4));
-	if (ret < 0)
-		return ret;
-
-	/* codec PLL input is PCLK/4 */
-	ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
-		iis_clkrate / 4, pll_out);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-
-	/* disable the PLL */
-	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
-}
-
-/*
- * Neo1973 WM8753 HiFi DAI opserations.
- */
-static struct snd_soc_ops neo1973_gta02_hifi_ops = {
-	.hw_params = neo1973_gta02_hifi_hw_params,
-	.hw_free = neo1973_gta02_hifi_hw_free,
-};
-
-static int neo1973_gta02_voice_hw_params(
-	struct snd_pcm_substream *substream,
-	struct snd_pcm_hw_params *params)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-	unsigned int pcmdiv = 0;
-	int ret = 0;
-	unsigned long iis_clkrate;
-
-	iis_clkrate = s3c24xx_i2s_get_clockrate();
-
-	if (params_rate(params) != 8000)
-		return -EINVAL;
-	if (params_channels(params) != 1)
-		return -EINVAL;
-
-	pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
-
-	/* todo: gg check mode (DSP_B) against CSR datasheet */
-	/* set codec DAI configuration */
-	ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
-		SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
-	if (ret < 0)
-		return ret;
-
-	/* set the codec system clock for DAC and ADC */
-	ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
-		12288000, SND_SOC_CLOCK_IN);
-	if (ret < 0)
-		return ret;
-
-	/* set codec PCM division for sample rate */
-	ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
-					pcmdiv);
-	if (ret < 0)
-		return ret;
-
-	/* configure and enable PLL for 12.288MHz output */
-	ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
-		iis_clkrate / 4, 12288000);
-	if (ret < 0)
-		return ret;
-
-	return 0;
-}
-
-static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
-{
-	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_dai *codec_dai = rtd->codec_dai;
-
-	/* disable the PLL */
-	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
-}
-
-static struct snd_soc_ops neo1973_gta02_voice_ops = {
-	.hw_params = neo1973_gta02_voice_hw_params,
-	.hw_free = neo1973_gta02_voice_hw_free,
-};
-
-#define LM4853_AMP 1
-#define LM4853_SPK 2
-
-static u8 lm4853_state;
-
-/* This has no effect, it exists only to maintain compatibility with
- * existing ALSA state files.
- */
-static int lm4853_set_state(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	int val = ucontrol->value.integer.value[0];
-
-	if (val)
-		lm4853_state |= LM4853_AMP;
-	else
-		lm4853_state &= ~LM4853_AMP;
-
-	return 0;
-}
-
-static int lm4853_get_state(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
-
-	return 0;
-}
-
-static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	int val = ucontrol->value.integer.value[0];
-
-	if (val) {
-		lm4853_state |= LM4853_SPK;
-		gpio_set_value(GTA02_GPIO_HP_IN, 0);
-	} else {
-		lm4853_state &= ~LM4853_SPK;
-		gpio_set_value(GTA02_GPIO_HP_IN, 1);
-	}
-
-	return 0;
-}
-
-static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
-
-	return 0;
-}
-
-static int lm4853_event(struct snd_soc_dapm_widget *w,
-			struct snd_kcontrol *k,
-			int event)
-{
-	gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
-
-	return 0;
-}
-
-static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
-	SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
-	SND_SOC_DAPM_LINE("GSM Line Out", NULL),
-	SND_SOC_DAPM_LINE("GSM Line In", NULL),
-	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-	SND_SOC_DAPM_MIC("Handset Mic", NULL),
-	SND_SOC_DAPM_SPK("Handset Spk", NULL),
-};
-
-
-/* example machine audio_mapnections */
-static const struct snd_soc_dapm_route audio_map[] = {
-
-	/* Connections to the lm4853 amp */
-	{"Stereo Out", NULL, "LOUT1"},
-	{"Stereo Out", NULL, "ROUT1"},
-
-	/* Connections to the GSM Module */
-	{"GSM Line Out", NULL, "MONO1"},
-	{"GSM Line Out", NULL, "MONO2"},
-	{"RXP", NULL, "GSM Line In"},
-	{"RXN", NULL, "GSM Line In"},
-
-	/* Connections to Headset */
-	{"MIC1", NULL, "Mic Bias"},
-	{"Mic Bias", NULL, "Headset Mic"},
-
-	/* Call Mic */
-	{"MIC2", NULL, "Mic Bias"},
-	{"MIC2N", NULL, "Mic Bias"},
-	{"Mic Bias", NULL, "Handset Mic"},
-
-	/* Call Speaker */
-	{"Handset Spk", NULL, "LOUT2"},
-	{"Handset Spk", NULL, "ROUT2"},
-
-	/* Connect the ALC pins */
-	{"ACIN", NULL, "ACOP"},
-};
-
-static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
-	SOC_DAPM_PIN_SWITCH("Stereo Out"),
-	SOC_DAPM_PIN_SWITCH("GSM Line Out"),
-	SOC_DAPM_PIN_SWITCH("GSM Line In"),
-	SOC_DAPM_PIN_SWITCH("Headset Mic"),
-	SOC_DAPM_PIN_SWITCH("Handset Mic"),
-	SOC_DAPM_PIN_SWITCH("Handset Spk"),
-
-	/* This has no effect, it exists only to maintain compatibility with
-	 * existing ALSA state files.
-	 */
-	SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
-		lm4853_get_state,
-		lm4853_set_state),
-	SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
-		lm4853_get_spk,
-		lm4853_set_spk),
-};
-
-/*
- * This is an example machine initialisation for a wm8753 connected to a
- * neo1973 GTA02.
- */
-static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd)
-{
-	struct snd_soc_codec *codec = rtd->codec;
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int err;
-
-	/* set up NC codec pins */
-	snd_soc_dapm_nc_pin(dapm, "OUT3");
-	snd_soc_dapm_nc_pin(dapm, "OUT4");
-	snd_soc_dapm_nc_pin(dapm, "LINE1");
-	snd_soc_dapm_nc_pin(dapm, "LINE2");
-
-	/* Add neo1973 gta02 specific widgets */
-	snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
-				  ARRAY_SIZE(wm8753_dapm_widgets));
-
-	/* add neo1973 gta02 specific controls */
-	err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls,
-		ARRAY_SIZE(wm8753_neo1973_gta02_controls));
-
-	if (err < 0)
-		return err;
-
-	/* set up neo1973 gta02 specific audio path audio_map */
-	snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
-	/* set endpoints to default off mode */
-	snd_soc_dapm_disable_pin(dapm, "Stereo Out");
-	snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-	snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-	snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-	snd_soc_dapm_disable_pin(dapm, "Handset Mic");
-	snd_soc_dapm_disable_pin(dapm, "Handset Spk");
-
-	/* allow audio paths from the GSM modem to run during suspend */
-	snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
-	snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
-	snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
-	snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
-	snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
-	snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
-
-	snd_soc_dapm_sync(dapm);
-
-	return 0;
-}
-
-/*
- * BT Codec DAI
- */
-static struct snd_soc_dai_driver bt_dai = {
-	.name = "bluetooth-dai",
-	.playback = {
-		.channels_min = 1,
-		.channels_max = 1,
-		.rates = SNDRV_PCM_RATE_8000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.capture = {
-		.channels_min = 1,
-		.channels_max = 1,
-		.rates = SNDRV_PCM_RATE_8000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-};
-
-static struct snd_soc_dai_link neo1973_gta02_dai[] = {
-{ /* Hifi Playback - for similatious use with voice below */
-	.name = "WM8753",
-	.stream_name = "WM8753 HiFi",
-	.cpu_dai_name = "s3c24xx-iis",
-	.codec_dai_name = "wm8753-hifi",
-	.init = neo1973_gta02_wm8753_init,
-	.platform_name = "samsung-audio",
-	.codec_name = "wm8753-codec.0-001a",
-	.ops = &neo1973_gta02_hifi_ops,
-},
-{ /* Voice via BT */
-	.name = "Bluetooth",
-	.stream_name = "Voice",
-	.cpu_dai_name = "bluetooth-dai",
-	.codec_dai_name = "wm8753-voice",
-	.ops = &neo1973_gta02_voice_ops,
-	.codec_name = "wm8753-codec.0-001a",
-	.platform_name = "samsung-audio",
-},
-};
-
-static struct snd_soc_card neo1973_gta02 = {
-	.name = "neo1973-gta02",
-	.dai_link = neo1973_gta02_dai,
-	.num_links = ARRAY_SIZE(neo1973_gta02_dai),
-};
-
-static struct platform_device *neo1973_gta02_snd_device;
-
-static int __init neo1973_gta02_init(void)
-{
-	int ret;
-
-	if (!machine_is_neo1973_gta02()) {
-		printk(KERN_INFO
-		       "Only GTA02 is supported by this ASoC driver\n");
-		return -ENODEV;
-	}
-
-	neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!neo1973_gta02_snd_device)
-		return -ENOMEM;
-
-	/* register bluetooth DAI here */
-	ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, &bt_dai);
-	if (ret)
-		goto err_put_device;
-
-	platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02);
-	ret = platform_device_add(neo1973_gta02_snd_device);
-
-	if (ret)
-		goto err_unregister_dai;
-
-	/* Initialise GPIOs used by amp */
-	ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN");
-	if (ret) {
-		pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN);
-		goto err_del_device;
-	}
-
-	ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1);
-	if (ret) {
-		pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
-		goto err_free_gpio_hp_in;
-	}
-
-	ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT");
-	if (ret) {
-		pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT);
-		goto err_free_gpio_hp_in;
-	}
-
-	ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1);
-	if (ret) {
-		pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT);
-		goto err_free_gpio_amp_shut;
-	}
-
-	return 0;
-
-err_free_gpio_amp_shut:
-	gpio_free(GTA02_GPIO_AMP_SHUT);
-err_free_gpio_hp_in:
-	gpio_free(GTA02_GPIO_HP_IN);
-err_del_device:
-	platform_device_del(neo1973_gta02_snd_device);
-err_unregister_dai:
-	snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev);
-err_put_device:
-	platform_device_put(neo1973_gta02_snd_device);
-	return ret;
-}
-module_init(neo1973_gta02_init);
-
-static void __exit neo1973_gta02_exit(void)
-{
-	snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev);
-	platform_device_unregister(neo1973_gta02_snd_device);
-	gpio_free(GTA02_GPIO_HP_IN);
-	gpio_free(GTA02_GPIO_AMP_SHUT);
-}
-module_exit(neo1973_gta02_exit);
-
-/* Module information */
-MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
-MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index d20815d..78bfdb3 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -1,57 +1,32 @@
 /*
- * neo1973_wm8753.c  --  SoC audio for Neo1973
+ * neo1973_wm8753.c  --  SoC audio for Openmoko Neo1973 and Freerunner devices
  *
+ * Copyright 2007 Openmoko Inc
+ * Author: Graeme Gregory <graeme@openmoko.org>
  * Copyright 2007 Wolfson Microelectronics PLC.
  * Author: Graeme Gregory
  *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ * Copyright 2009 Wolfson Microelectronics
  *
  *  This program is free software; you can redistribute  it and/or modify it
  *  under  the terms of  the GNU General  Public License as published by the
  *  Free Software Foundation;  either version 2 of the  License, or (at your
  *  option) any later version.
- *
  */
 
 #include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
+#include <linux/gpio.h>
+
 #include <sound/soc.h>
-#include <sound/tlv.h>
 
 #include <asm/mach-types.h>
-#include <asm/hardware/scoop.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-gpio.h>
-#include <mach/hardware.h>
-#include <linux/io.h>
-#include <mach/spi-gpio.h>
-
 #include <plat/regs-iis.h>
+#include <mach/gta02.h>
 
 #include "../codecs/wm8753.h"
-#include "lm4857.h"
-#include "dma.h"
 #include "s3c24xx-i2s.h"
 
-/* define the scenarios */
-#define NEO_AUDIO_OFF			0
-#define NEO_GSM_CALL_AUDIO_HANDSET	1
-#define NEO_GSM_CALL_AUDIO_HEADSET	2
-#define NEO_GSM_CALL_AUDIO_BLUETOOTH	3
-#define NEO_STEREO_TO_SPEAKERS		4
-#define NEO_STEREO_TO_HEADPHONES	5
-#define NEO_CAPTURE_HANDSET		6
-#define NEO_CAPTURE_HEADSET		7
-#define NEO_CAPTURE_BLUETOOTH		8
-
-static struct snd_soc_card neo1973;
-static struct i2c_client *i2c;
-
 static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
 	struct snd_pcm_hw_params *params)
 {
@@ -62,8 +37,6 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
 	int ret = 0;
 	unsigned long iis_clkrate;
 
-	pr_debug("Entered %s\n", __func__);
-
 	iis_clkrate = s3c24xx_i2s_get_clockrate();
 
 	switch (params_rate(params)) {
@@ -148,8 +121,6 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
-	pr_debug("Entered %s\n", __func__);
-
 	/* disable the PLL */
 	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
 }
@@ -171,8 +142,6 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
 	int ret = 0;
 	unsigned long iis_clkrate;
 
-	pr_debug("Entered %s\n", __func__);
-
 	iis_clkrate = s3c24xx_i2s_get_clockrate();
 
 	if (params_rate(params) != 8000)
@@ -214,8 +183,6 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 
-	pr_debug("Entered %s\n", __func__);
-
 	/* disable the PLL */
 	return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
 }
@@ -225,335 +192,232 @@ static struct snd_soc_ops neo1973_voice_ops = {
 	.hw_free = neo1973_voice_hw_free,
 };
 
-static int neo1973_scenario;
-
-static int neo1973_get_scenario(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	ucontrol->value.integer.value[0] = neo1973_scenario;
-	return 0;
-}
-
-static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario)
-{
-	struct snd_soc_dapm_context *dapm = &codec->dapm;
-
-	pr_debug("Entered %s\n", __func__);
-
-	switch (neo1973_scenario) {
-	case NEO_AUDIO_OFF:
-		snd_soc_dapm_disable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	case NEO_GSM_CALL_AUDIO_HANDSET:
-		snd_soc_dapm_enable_pin(dapm, "Audio Out");
-		snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_enable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_enable_pin(dapm, "Call Mic");
-		break;
-	case NEO_GSM_CALL_AUDIO_HEADSET:
-		snd_soc_dapm_enable_pin(dapm, "Audio Out");
-		snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_enable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_enable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	case NEO_GSM_CALL_AUDIO_BLUETOOTH:
-		snd_soc_dapm_disable_pin(dapm, "Audio Out");
-		snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_enable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	case NEO_STEREO_TO_SPEAKERS:
-		snd_soc_dapm_enable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	case NEO_STEREO_TO_HEADPHONES:
-		snd_soc_dapm_enable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	case NEO_CAPTURE_HANDSET:
-		snd_soc_dapm_disable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_enable_pin(dapm, "Call Mic");
-		break;
-	case NEO_CAPTURE_HEADSET:
-		snd_soc_dapm_disable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_enable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	case NEO_CAPTURE_BLUETOOTH:
-		snd_soc_dapm_disable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-		break;
-	default:
-		snd_soc_dapm_disable_pin(dapm, "Audio Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
-		snd_soc_dapm_disable_pin(dapm, "GSM Line In");
-		snd_soc_dapm_disable_pin(dapm, "Headset Mic");
-		snd_soc_dapm_disable_pin(dapm, "Call Mic");
-	}
+/* Shared routes and controls */
 
-	snd_soc_dapm_sync(dapm);
+static const struct snd_soc_dapm_widget neo1973_wm8753_dapm_widgets[] = {
+	SND_SOC_DAPM_LINE("GSM Line Out", NULL),
+	SND_SOC_DAPM_LINE("GSM Line In", NULL),
+	SND_SOC_DAPM_MIC("Headset Mic", NULL),
+	SND_SOC_DAPM_MIC("Handset Mic", NULL),
+};
 
-	return 0;
-}
+static const struct snd_soc_dapm_route neo1973_wm8753_routes[] = {
+	/* Connections to the GSM Module */
+	{"GSM Line Out", NULL, "MONO1"},
+	{"GSM Line Out", NULL, "MONO2"},
+	{"RXP", NULL, "GSM Line In"},
+	{"RXN", NULL, "GSM Line In"},
 
-static int neo1973_set_scenario(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	/* Connections to Headset */
+	{"MIC1", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Headset Mic"},
 
-	pr_debug("Entered %s\n", __func__);
+	/* Call Mic */
+	{"MIC2", NULL, "Mic Bias"},
+	{"MIC2N", NULL, "Mic Bias"},
+	{"Mic Bias", NULL, "Handset Mic"},
 
-	if (neo1973_scenario == ucontrol->value.integer.value[0])
-		return 0;
+	/* Connect the ALC pins */
+	{"ACIN", NULL, "ACOP"},
+};
 
-	neo1973_scenario = ucontrol->value.integer.value[0];
-	set_scenario_endpoints(codec, neo1973_scenario);
-	return 1;
-}
+static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
+	SOC_DAPM_PIN_SWITCH("GSM Line Out"),
+	SOC_DAPM_PIN_SWITCH("GSM Line In"),
+	SOC_DAPM_PIN_SWITCH("Headset Mic"),
+	SOC_DAPM_PIN_SWITCH("Handset Mic"),
+};
 
-static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0};
+/* GTA02 specific routes and controlls */
 
-static void lm4857_write_regs(void)
-{
-	pr_debug("Entered %s\n", __func__);
+#ifdef CONFIG_MACH_NEO1973_GTA02
 
-	if (i2c_master_send(i2c, lm4857_regs, 4) != 4)
-		printk(KERN_ERR "lm4857: i2c write failed\n");
-}
+static int gta02_speaker_enabled;
 
-static int lm4857_get_reg(struct snd_kcontrol *kcontrol,
+static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	int reg = mc->reg;
-	int shift = mc->shift;
-	int mask = mc->max;
+	gta02_speaker_enabled = ucontrol->value.integer.value[0];
 
-	pr_debug("Entered %s\n", __func__);
+	gpio_set_value(GTA02_GPIO_HP_IN, !gta02_speaker_enabled);
 
-	ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask;
 	return 0;
 }
 
-static int lm4857_set_reg(struct snd_kcontrol *kcontrol,
+static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
-	struct soc_mixer_control *mc =
-		(struct soc_mixer_control *)kcontrol->private_value;
-	int reg = mc->reg;
-	int shift = mc->shift;
-	int mask = mc->max;
-
-	if (((lm4857_regs[reg] >> shift) & mask) ==
-		ucontrol->value.integer.value[0])
-		return 0;
-
-	lm4857_regs[reg] &= ~(mask << shift);
-	lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift;
-	lm4857_write_regs();
-	return 1;
+	ucontrol->value.integer.value[0] = gta02_speaker_enabled;
+	return 0;
 }
 
-static int lm4857_get_mode(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
+static int lm4853_event(struct snd_soc_dapm_widget *w,
+			struct snd_kcontrol *k, int event)
 {
-	u8 value = lm4857_regs[LM4857_CTRL] & 0x0F;
-
-	pr_debug("Entered %s\n", __func__);
-
-	if (value)
-		value -= 5;
+	gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
 
-	ucontrol->value.integer.value[0] = value;
 	return 0;
 }
 
-static int lm4857_set_mode(struct snd_kcontrol *kcontrol,
-	struct snd_ctl_elem_value *ucontrol)
-{
-	u8 value = ucontrol->value.integer.value[0];
-
-	pr_debug("Entered %s\n", __func__);
-
-	if (value)
-		value += 5;
-
-	if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value)
-		return 0;
-
-	lm4857_regs[LM4857_CTRL] &= 0xF0;
-	lm4857_regs[LM4857_CTRL] |= value;
-	lm4857_write_regs();
-	return 1;
-}
+static const struct snd_soc_dapm_route neo1973_gta02_routes[] = {
+	/* Connections to the amp */
+	{"Stereo Out", NULL, "LOUT1"},
+	{"Stereo Out", NULL, "ROUT1"},
 
-static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
-	SND_SOC_DAPM_LINE("Audio Out", NULL),
-	SND_SOC_DAPM_LINE("GSM Line Out", NULL),
-	SND_SOC_DAPM_LINE("GSM Line In", NULL),
-	SND_SOC_DAPM_MIC("Headset Mic", NULL),
-	SND_SOC_DAPM_MIC("Call Mic", NULL),
+	/* Call Speaker */
+	{"Handset Spk", NULL, "LOUT2"},
+	{"Handset Spk", NULL, "ROUT2"},
 };
 
+static const struct snd_kcontrol_new neo1973_gta02_wm8753_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Handset Spk"),
+	SOC_DAPM_PIN_SWITCH("Stereo Out"),
 
-static const struct snd_soc_dapm_route dapm_routes[] = {
-
-	/* Connections to the lm4857 amp */
-	{"Audio Out", NULL, "LOUT1"},
-	{"Audio Out", NULL, "ROUT1"},
-
-	/* Connections to the GSM Module */
-	{"GSM Line Out", NULL, "MONO1"},
-	{"GSM Line Out", NULL, "MONO2"},
-	{"RXP", NULL, "GSM Line In"},
-	{"RXN", NULL, "GSM Line In"},
+	SOC_SINGLE_BOOL_EXT("Amp Spk Switch", 0,
+		lm4853_get_spk,
+		lm4853_set_spk),
+};
 
-	/* Connections to Headset */
-	{"MIC1", NULL, "Mic Bias"},
-	{"Mic Bias", NULL, "Headset Mic"},
+static const struct snd_soc_dapm_widget neo1973_gta02_wm8753_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Handset Spk", NULL),
+	SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
+};
 
-	/* Call Mic */
-	{"MIC2", NULL, "Mic Bias"},
-	{"MIC2N", NULL, "Mic Bias"},
-	{"Mic Bias", NULL, "Call Mic"},
+static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
+{
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	int ret;
 
-	/* Connect the ALC pins */
-	{"ACIN", NULL, "ACOP"},
-};
+	ret = snd_soc_dapm_new_controls(dapm, neo1973_gta02_wm8753_dapm_widgets,
+			ARRAY_SIZE(neo1973_gta02_wm8753_dapm_widgets));
+	if (ret)
+		return ret;
 
-static const char *lm4857_mode[] = {
-	"Off",
-	"Call Speaker",
-	"Stereo Speakers",
-	"Stereo Speakers + Headphones",
-	"Headphones"
-};
+	ret = snd_soc_dapm_add_routes(dapm, neo1973_gta02_routes,
+			ARRAY_SIZE(neo1973_gta02_routes));
+	if (ret)
+		return ret;
 
-static const struct soc_enum lm4857_mode_enum[] = {
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode),
-};
+	ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
+			ARRAY_SIZE(neo1973_gta02_wm8753_controls));
+	if (ret)
+		return ret;
 
-static const char *neo_scenarios[] = {
-	"Off",
-	"GSM Handset",
-	"GSM Headset",
-	"GSM Bluetooth",
-	"Speakers",
-	"Headphones",
-	"Capture Handset",
-	"Capture Headset",
-	"Capture Bluetooth"
-};
+	snd_soc_dapm_disable_pin(dapm, "Stereo Out");
+	snd_soc_dapm_disable_pin(dapm, "Handset Spk");
+	snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
+	snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
 
-static const struct soc_enum neo_scenario_enum[] = {
-	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios), neo_scenarios),
-};
+	return 0;
+}
 
-static const DECLARE_TLV_DB_SCALE(stereo_tlv, -4050, 150, 0);
-static const DECLARE_TLV_DB_SCALE(mono_tlv, -3450, 150, 0);
-
-static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
-	SOC_SINGLE_EXT_TLV("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0,
-		lm4857_get_reg, lm4857_set_reg, stereo_tlv),
-	SOC_SINGLE_EXT_TLV("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0,
-		lm4857_get_reg, lm4857_set_reg, stereo_tlv),
-	SOC_SINGLE_EXT_TLV("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0,
-		lm4857_get_reg, lm4857_set_reg, mono_tlv),
-	SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0],
-		lm4857_get_mode, lm4857_set_mode),
-	SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0],
-		neo1973_get_scenario, neo1973_set_scenario),
-	SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0,
-		lm4857_get_reg, lm4857_set_reg),
-	SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0,
-		lm4857_get_reg, lm4857_set_reg),
-	SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0,
-		lm4857_get_reg, lm4857_set_reg),
-	SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0,
-		lm4857_get_reg, lm4857_set_reg),
-};
+#else
+static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
+#endif
 
-/*
- * This is an example machine initialisation for a wm8753 connected to a
- * neo1973 II. It is missing logic to detect hp/mic insertions and logic
- * to re-route the audio in such an event.
- */
 static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_soc_codec *codec = rtd->codec;
 	struct snd_soc_dapm_context *dapm = &codec->dapm;
-	int err;
-
-	pr_debug("Entered %s\n", __func__);
+	int ret;
 
 	/* set up NC codec pins */
-	snd_soc_dapm_nc_pin(dapm, "LOUT2");
-	snd_soc_dapm_nc_pin(dapm, "ROUT2");
+	if (machine_is_neo1973_gta01()) {
+		snd_soc_dapm_nc_pin(dapm, "LOUT2");
+		snd_soc_dapm_nc_pin(dapm, "ROUT2");
+	}
 	snd_soc_dapm_nc_pin(dapm, "OUT3");
 	snd_soc_dapm_nc_pin(dapm, "OUT4");
 	snd_soc_dapm_nc_pin(dapm, "LINE1");
 	snd_soc_dapm_nc_pin(dapm, "LINE2");
 
 	/* Add neo1973 specific widgets */
-	snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
-				  ARRAY_SIZE(wm8753_dapm_widgets));
-
-	/* set endpoints to default mode */
-	set_scenario_endpoints(codec, NEO_AUDIO_OFF);
+	ret = snd_soc_dapm_new_controls(dapm, neo1973_wm8753_dapm_widgets,
+			ARRAY_SIZE(neo1973_wm8753_dapm_widgets));
+	if (ret)
+		return ret;
 
 	/* add neo1973 specific controls */
-	err = snd_soc_add_controls(codec, wm8753_neo1973_controls,
-				ARRAY_SIZE(8753_neo1973_controls));
-	if (err < 0)
-		return err;
+	ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
+			ARRAY_SIZE(neo1973_wm8753_controls));
+	if (ret)
+		return ret;
 
 	/* set up neo1973 specific audio routes */
-	err = snd_soc_dapm_add_routes(dapm, dapm_routes,
-				      ARRAY_SIZE(dapm_routes));
+	ret = snd_soc_dapm_add_routes(dapm, neo1973_wm8753_routes,
+			ARRAY_SIZE(neo1973_wm8753_routes));
+	if (ret)
+		return ret;
+
+	/* set endpoints to default off mode */
+	snd_soc_dapm_disable_pin(dapm, "GSM Line Out");
+	snd_soc_dapm_disable_pin(dapm, "GSM Line In");
+	snd_soc_dapm_disable_pin(dapm, "Headset Mic");
+	snd_soc_dapm_disable_pin(dapm, "Handset Mic");
+
+	/* allow audio paths from the GSM modem to run during suspend */
+	snd_soc_dapm_ignore_suspend(dapm, "GSM Line Out");
+	snd_soc_dapm_ignore_suspend(dapm, "GSM Line In");
+	snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+	snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
+
+	if (machine_is_neo1973_gta02()) {
+		ret = neo1973_gta02_wm8753_init(codec);
+		if (ret)
+			return ret;
+	}
 
 	snd_soc_dapm_sync(dapm);
+
 	return 0;
 }
 
-/*
- * BT Codec DAI
- */
-static struct snd_soc_dai bt_dai = {
-	.name = "bluetooth-dai",
-	.playback = {
-		.channels_min = 1,
-		.channels_max = 1,
-		.rates = SNDRV_PCM_RATE_8000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
-	.capture = {
-		.channels_min = 1,
-		.channels_max = 1,
-		.rates = SNDRV_PCM_RATE_8000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE,},
+/* GTA01 specific controlls */
+
+#ifdef CONFIG_MACH_NEO1973_GTA01
+
+static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
+	{"Amp IN", NULL, "ROUT1"},
+	{"Amp IN", NULL, "LOUT1"},
+
+	{"Handset Spk", NULL, "Amp EP"},
+	{"Stereo Out", NULL, "Amp LS"},
+	{"Headphone", NULL, "Amp HP"},
+};
+
+static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Handset Spk", NULL),
+	SND_SOC_DAPM_SPK("Stereo Out", NULL),
+	SND_SOC_DAPM_HP("Headphone", NULL),
 };
 
+static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
+{
+	int ret;
+
+	ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
+			ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
+	if (ret)
+		return ret;
+
+	ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
+			ARRAY_SIZE(neo1973_lm4857_routes));
+	if (ret)
+		return ret;
+
+	snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
+	snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
+	snd_soc_dapm_ignore_suspend(dapm, "Headphone");
+
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+#else
+static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
+#endif
+
 static struct snd_soc_dai_link neo1973_dai[] = {
 { /* Hifi Playback - for similatious use with voice below */
 	.name = "WM8753",
@@ -569,90 +433,49 @@ static struct snd_soc_dai_link neo1973_dai[] = {
 	.name = "Bluetooth",
 	.stream_name = "Voice",
 	.platform_name = "samsung-audio",
-	.cpu_dai_name = "bluetooth-dai",
+	.cpu_dai_name = "dfbmcs320-pcm",
 	.codec_dai_name = "wm8753-voice",
 	.codec_name = "wm8753-codec.0-001a",
 	.ops = &neo1973_voice_ops,
 },
 };
 
-static struct snd_soc_card neo1973 = {
-	.name = "neo1973",
-	.dai_link = neo1973_dai,
-	.num_links = ARRAY_SIZE(neo1973_dai),
+static struct snd_soc_aux_dev neo1973_aux_devs[] = {
+	{
+		.name = "dfbmcs320",
+		.codec_name = "dfbmcs320.0",
+	},
+	{
+		.name = "lm4857",
+		.codec_name = "lm4857.0-007c",
+		.init = neo1973_lm4857_init,
+	},
 };
 
-static int lm4857_i2c_probe(struct i2c_client *client,
-			    const struct i2c_device_id *id)
-{
-	pr_debug("Entered %s\n", __func__);
-
-	i2c = client;
-
-	lm4857_write_regs();
-	return 0;
-}
-
-static int lm4857_i2c_remove(struct i2c_client *client)
-{
-	pr_debug("Entered %s\n", __func__);
-
-	i2c = NULL;
-
-	return 0;
-}
-
-static u8 lm4857_state;
-
-static int lm4857_suspend(struct i2c_client *dev, pm_message_t state)
-{
-	pr_debug("Entered %s\n", __func__);
-
-	dev_dbg(&dev->dev, "lm4857_suspend\n");
-	lm4857_state = lm4857_regs[LM4857_CTRL] & 0xf;
-	if (lm4857_state) {
-		lm4857_regs[LM4857_CTRL] &= 0xf0;
-		lm4857_write_regs();
-	}
-	return 0;
-}
-
-static int lm4857_resume(struct i2c_client *dev)
-{
-	pr_debug("Entered %s\n", __func__);
-
-	if (lm4857_state) {
-		lm4857_regs[LM4857_CTRL] |= (lm4857_state & 0x0f);
-		lm4857_write_regs();
-	}
-	return 0;
-}
-
-static void lm4857_shutdown(struct i2c_client *dev)
-{
-	pr_debug("Entered %s\n", __func__);
-
-	dev_dbg(&dev->dev, "lm4857_shutdown\n");
-	lm4857_regs[LM4857_CTRL] &= 0xf0;
-	lm4857_write_regs();
-}
+static struct snd_soc_codec_conf neo1973_codec_conf[] = {
+	{
+		.dev_name = "lm4857.0-007c",
+		.name_prefix = "Amp",
+	},
+};
 
-static const struct i2c_device_id lm4857_i2c_id[] = {
-	{ "neo1973_lm4857", 0 },
-	{ }
+#ifdef CONFIG_MACH_NEO1973_GTA02
+static const struct gpio neo1973_gta02_gpios[] = {
+	{ GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
+	{ GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
 };
+#else
+static const struct gpio neo1973_gta02_gpios[] = {};
+#endif
 
-static struct i2c_driver lm4857_i2c_driver = {
-	.driver = {
-		.name = "LM4857 I2C Amp",
-		.owner = THIS_MODULE,
-	},
-	.suspend =        lm4857_suspend,
-	.resume	=         lm4857_resume,
-	.shutdown =       lm4857_shutdown,
-	.probe =          lm4857_i2c_probe,
-	.remove =         lm4857_i2c_remove,
-	.id_table =       lm4857_i2c_id,
+static struct snd_soc_card neo1973 = {
+	.name = "neo1973",
+	.dai_link = neo1973_dai,
+	.num_links = ARRAY_SIZE(neo1973_dai),
+	.aux_dev = neo1973_aux_devs,
+	.num_aux_devs = ARRAY_SIZE(neo1973_aux_devs),
+	.codec_conf = neo1973_codec_conf,
+	.num_configs = ARRAY_SIZE(neo1973_codec_conf),
 };
 
 static struct platform_device *neo1973_snd_device;
@@ -661,46 +484,56 @@ static int __init neo1973_init(void)
 {
 	int ret;
 
-	pr_debug("Entered %s\n", __func__);
-
-	if (!machine_is_neo1973_gta01()) {
-		printk(KERN_INFO
-			"Only GTA01 hardware supported by ASoC driver\n");
+	if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
 		return -ENODEV;
+
+	if (machine_is_neo1973_gta02()) {
+		neo1973.name = "neo1973gta02";
+		neo1973.num_aux_devs = 1;
+
+		ret = gpio_request_array(neo1973_gta02_gpios,
+				ARRAY_SIZE(neo1973_gta02_gpios));
+		if (ret)
+			return ret;
 	}
 
 	neo1973_snd_device = platform_device_alloc("soc-audio", -1);
-	if (!neo1973_snd_device)
-		return -ENOMEM;
+	if (!neo1973_snd_device) {
+		ret = -ENOMEM;
+		goto err_gpio_free;
+	}
 
 	platform_set_drvdata(neo1973_snd_device, &neo1973);
 	ret = platform_device_add(neo1973_snd_device);
 
-	if (ret) {
-		platform_device_put(neo1973_snd_device);
-		return ret;
-	}
-
-	ret = i2c_add_driver(&lm4857_i2c_driver);
+	if (ret)
+		goto err_put_device;
 
-	if (ret != 0)
-		platform_device_unregister(neo1973_snd_device);
+	return 0;
 
+err_put_device:
+	platform_device_put(neo1973_snd_device);
+err_gpio_free:
+	if (machine_is_neo1973_gta02()) {
+		gpio_free_array(neo1973_gta02_gpios,
+				ARRAY_SIZE(neo1973_gta02_gpios));
+	}
 	return ret;
 }
+module_init(neo1973_init);
 
 static void __exit neo1973_exit(void)
 {
-	pr_debug("Entered %s\n", __func__);
-
-	i2c_del_driver(&lm4857_i2c_driver);
 	platform_device_unregister(neo1973_snd_device);
-}
 
-module_init(neo1973_init);
+	if (machine_is_neo1973_gta02()) {
+		gpio_free_array(neo1973_gta02_gpios,
+				ARRAY_SIZE(neo1973_gta02_gpios));
+	}
+}
 module_exit(neo1973_exit);
 
 /* Module information */
 MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org, www.openmoko.org");
-MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973");
+MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 and Frerunner");
 MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 48d0b75..38aac7d 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -11,20 +11,11 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/delay.h>
 #include <linux/clk.h>
-#include <linux/kernel.h>
-#include <linux/gpio.h>
 #include <linux/io.h>
 
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
 #include <plat/audio.h>
 #include <plat/dma.h>
@@ -32,6 +23,113 @@
 #include "dma.h"
 #include "pcm.h"
 
+/*Register Offsets */
+#define S3C_PCM_CTL		0x00
+#define S3C_PCM_CLKCTL		0x04
+#define S3C_PCM_TXFIFO		0x08
+#define S3C_PCM_RXFIFO		0x0C
+#define S3C_PCM_IRQCTL		0x10
+#define S3C_PCM_IRQSTAT		0x14
+#define S3C_PCM_FIFOSTAT	0x18
+#define S3C_PCM_CLRINT		0x20
+
+/* PCM_CTL Bit-Fields */
+#define S3C_PCM_CTL_TXDIPSTICK_MASK	0x3f
+#define S3C_PCM_CTL_TXDIPSTICK_SHIFT	13
+#define S3C_PCM_CTL_RXDIPSTICK_MASK	0x3f
+#define S3C_PCM_CTL_RXDIPSTICK_SHIFT	7
+#define S3C_PCM_CTL_TXDMA_EN		(0x1 << 6)
+#define S3C_PCM_CTL_RXDMA_EN		(0x1 << 5)
+#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC	(0x1 << 4)
+#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC	(0x1 << 3)
+#define S3C_PCM_CTL_TXFIFO_EN		(0x1 << 2)
+#define S3C_PCM_CTL_RXFIFO_EN		(0x1 << 1)
+#define S3C_PCM_CTL_ENABLE		(0x1 << 0)
+
+/* PCM_CLKCTL Bit-Fields */
+#define S3C_PCM_CLKCTL_SERCLK_EN	(0x1 << 19)
+#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK	(0x1 << 18)
+#define S3C_PCM_CLKCTL_SCLKDIV_MASK	0x1ff
+#define S3C_PCM_CLKCTL_SYNCDIV_MASK	0x1ff
+#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT	9
+#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT	0
+
+/* PCM_TXFIFO Bit-Fields */
+#define S3C_PCM_TXFIFO_DVALID	(0x1 << 16)
+#define S3C_PCM_TXFIFO_DATA_MSK	(0xffff << 0)
+
+/* PCM_RXFIFO Bit-Fields */
+#define S3C_PCM_RXFIFO_DVALID	(0x1 << 16)
+#define S3C_PCM_RXFIFO_DATA_MSK	(0xffff << 0)
+
+/* PCM_IRQCTL Bit-Fields */
+#define S3C_PCM_IRQCTL_IRQEN		(0x1 << 14)
+#define S3C_PCM_IRQCTL_WRDEN		(0x1 << 12)
+#define S3C_PCM_IRQCTL_TXEMPTYEN	(0x1 << 11)
+#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN	(0x1 << 10)
+#define S3C_PCM_IRQCTL_TXFULLEN		(0x1 << 9)
+#define S3C_PCM_IRQCTL_TXALMSTFULLEN	(0x1 << 8)
+#define S3C_PCM_IRQCTL_TXSTARVEN	(0x1 << 7)
+#define S3C_PCM_IRQCTL_TXERROVRFLEN	(0x1 << 6)
+#define S3C_PCM_IRQCTL_RXEMPTEN		(0x1 << 5)
+#define S3C_PCM_IRQCTL_RXALMSTEMPTEN	(0x1 << 4)
+#define S3C_PCM_IRQCTL_RXFULLEN		(0x1 << 3)
+#define S3C_PCM_IRQCTL_RXALMSTFULLEN	(0x1 << 2)
+#define S3C_PCM_IRQCTL_RXSTARVEN	(0x1 << 1)
+#define S3C_PCM_IRQCTL_RXERROVRFLEN	(0x1 << 0)
+
+/* PCM_IRQSTAT Bit-Fields */
+#define S3C_PCM_IRQSTAT_IRQPND		(0x1 << 13)
+#define S3C_PCM_IRQSTAT_WRD_XFER	(0x1 << 12)
+#define S3C_PCM_IRQSTAT_TXEMPTY		(0x1 << 11)
+#define S3C_PCM_IRQSTAT_TXALMSTEMPTY	(0x1 << 10)
+#define S3C_PCM_IRQSTAT_TXFULL		(0x1 << 9)
+#define S3C_PCM_IRQSTAT_TXALMSTFULL	(0x1 << 8)
+#define S3C_PCM_IRQSTAT_TXSTARV		(0x1 << 7)
+#define S3C_PCM_IRQSTAT_TXERROVRFL	(0x1 << 6)
+#define S3C_PCM_IRQSTAT_RXEMPT		(0x1 << 5)
+#define S3C_PCM_IRQSTAT_RXALMSTEMPT	(0x1 << 4)
+#define S3C_PCM_IRQSTAT_RXFULL		(0x1 << 3)
+#define S3C_PCM_IRQSTAT_RXALMSTFULL	(0x1 << 2)
+#define S3C_PCM_IRQSTAT_RXSTARV		(0x1 << 1)
+#define S3C_PCM_IRQSTAT_RXERROVRFL	(0x1 << 0)
+
+/* PCM_FIFOSTAT Bit-Fields */
+#define S3C_PCM_FIFOSTAT_TXCNT_MSK		(0x3f << 14)
+#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY		(0x1 << 13)
+#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY	(0x1 << 12)
+#define S3C_PCM_FIFOSTAT_TXFIFOFULL		(0x1 << 11)
+#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL	(0x1 << 10)
+#define S3C_PCM_FIFOSTAT_RXCNT_MSK		(0x3f << 4)
+#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY		(0x1 << 3)
+#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY	(0x1 << 2)
+#define S3C_PCM_FIFOSTAT_RXFIFOFULL		(0x1 << 1)
+#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL	(0x1 << 0)
+
+/**
+ * struct s3c_pcm_info - S3C PCM Controller information
+ * @dev: The parent device passed to use from the probe.
+ * @regs: The pointer to the device register block.
+ * @dma_playback: DMA information for playback channel.
+ * @dma_capture: DMA information for capture channel.
+ */
+struct s3c_pcm_info {
+	spinlock_t lock;
+	struct device	*dev;
+	void __iomem	*regs;
+
+	unsigned int sclk_per_fs;
+
+	/* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
+	unsigned int idleclk;
+
+	struct clk	*pclk;
+	struct clk	*cclk;
+
+	struct s3c_dma_params	*dma_playback;
+	struct s3c_dma_params	*dma_capture;
+};
+
 static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
 	.name		= "PCM Stereo out"
 };
diff --git a/sound/soc/samsung/pcm.h b/sound/soc/samsung/pcm.h
index 03393dc..726baf8 100644
--- a/sound/soc/samsung/pcm.h
+++ b/sound/soc/samsung/pcm.h
@@ -9,116 +9,9 @@
 #ifndef __S3C_PCM_H
 #define __S3C_PCM_H __FILE__
 
-/*Register Offsets */
-#define S3C_PCM_CTL	(0x00)
-#define S3C_PCM_CLKCTL	(0x04)
-#define S3C_PCM_TXFIFO	(0x08)
-#define S3C_PCM_RXFIFO	(0x0C)
-#define S3C_PCM_IRQCTL	(0x10)
-#define S3C_PCM_IRQSTAT	(0x14)
-#define S3C_PCM_FIFOSTAT	(0x18)
-#define S3C_PCM_CLRINT	(0x20)
-
-/* PCM_CTL Bit-Fields */
-#define S3C_PCM_CTL_TXDIPSTICK_MASK		(0x3f)
-#define S3C_PCM_CTL_TXDIPSTICK_SHIFT	(13)
-#define S3C_PCM_CTL_RXDIPSTICK_MASK		(0x3f)
-#define S3C_PCM_CTL_RXDIPSTICK_SHIFT	(7)
-#define S3C_PCM_CTL_TXDMA_EN		(0x1<<6)
-#define S3C_PCM_CTL_RXDMA_EN		(0x1<<5)
-#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC	(0x1<<4)
-#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC	(0x1<<3)
-#define S3C_PCM_CTL_TXFIFO_EN		(0x1<<2)
-#define S3C_PCM_CTL_RXFIFO_EN		(0x1<<1)
-#define S3C_PCM_CTL_ENABLE			(0x1<<0)
-
-/* PCM_CLKCTL Bit-Fields */
-#define S3C_PCM_CLKCTL_SERCLK_EN		(0x1<<19)
-#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK	(0x1<<18)
-#define S3C_PCM_CLKCTL_SCLKDIV_MASK		(0x1ff)
-#define S3C_PCM_CLKCTL_SYNCDIV_MASK		(0x1ff)
-#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT	(9)
-#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT	(0)
-
-/* PCM_TXFIFO Bit-Fields */
-#define S3C_PCM_TXFIFO_DVALID	(0x1<<16)
-#define S3C_PCM_TXFIFO_DATA_MSK	(0xffff<<0)
-
-/* PCM_RXFIFO Bit-Fields */
-#define S3C_PCM_RXFIFO_DVALID	(0x1<<16)
-#define S3C_PCM_RXFIFO_DATA_MSK	(0xffff<<0)
-
-/* PCM_IRQCTL Bit-Fields */
-#define S3C_PCM_IRQCTL_IRQEN		(0x1<<14)
-#define S3C_PCM_IRQCTL_WRDEN		(0x1<<12)
-#define S3C_PCM_IRQCTL_TXEMPTYEN		(0x1<<11)
-#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN	(0x1<<10)
-#define S3C_PCM_IRQCTL_TXFULLEN		(0x1<<9)
-#define S3C_PCM_IRQCTL_TXALMSTFULLEN	(0x1<<8)
-#define S3C_PCM_IRQCTL_TXSTARVEN		(0x1<<7)
-#define S3C_PCM_IRQCTL_TXERROVRFLEN		(0x1<<6)
-#define S3C_PCM_IRQCTL_RXEMPTEN		(0x1<<5)
-#define S3C_PCM_IRQCTL_RXALMSTEMPTEN	(0x1<<4)
-#define S3C_PCM_IRQCTL_RXFULLEN		(0x1<<3)
-#define S3C_PCM_IRQCTL_RXALMSTFULLEN	(0x1<<2)
-#define S3C_PCM_IRQCTL_RXSTARVEN		(0x1<<1)
-#define S3C_PCM_IRQCTL_RXERROVRFLEN		(0x1<<0)
-
-/* PCM_IRQSTAT Bit-Fields */
-#define S3C_PCM_IRQSTAT_IRQPND		(0x1<<13)
-#define S3C_PCM_IRQSTAT_WRD_XFER		(0x1<<12)
-#define S3C_PCM_IRQSTAT_TXEMPTY		(0x1<<11)
-#define S3C_PCM_IRQSTAT_TXALMSTEMPTY	(0x1<<10)
-#define S3C_PCM_IRQSTAT_TXFULL		(0x1<<9)
-#define S3C_PCM_IRQSTAT_TXALMSTFULL		(0x1<<8)
-#define S3C_PCM_IRQSTAT_TXSTARV		(0x1<<7)
-#define S3C_PCM_IRQSTAT_TXERROVRFL		(0x1<<6)
-#define S3C_PCM_IRQSTAT_RXEMPT		(0x1<<5)
-#define S3C_PCM_IRQSTAT_RXALMSTEMPT		(0x1<<4)
-#define S3C_PCM_IRQSTAT_RXFULL		(0x1<<3)
-#define S3C_PCM_IRQSTAT_RXALMSTFULL		(0x1<<2)
-#define S3C_PCM_IRQSTAT_RXSTARV		(0x1<<1)
-#define S3C_PCM_IRQSTAT_RXERROVRFL		(0x1<<0)
-
-/* PCM_FIFOSTAT Bit-Fields */
-#define S3C_PCM_FIFOSTAT_TXCNT_MSK		(0x3f<<14)
-#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY	(0x1<<13)
-#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY	(0x1<<12)
-#define S3C_PCM_FIFOSTAT_TXFIFOFULL		(0x1<<11)
-#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL	(0x1<<10)
-#define S3C_PCM_FIFOSTAT_RXCNT_MSK		(0x3f<<4)
-#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY	(0x1<<3)
-#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY	(0x1<<2)
-#define S3C_PCM_FIFOSTAT_RXFIFOFULL		(0x1<<1)
-#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL	(0x1<<0)
-
 #define S3C_PCM_CLKSRC_PCLK	0
 #define S3C_PCM_CLKSRC_MUX	1
 
 #define S3C_PCM_SCLK_PER_FS	0
 
-/**
- * struct s3c_pcm_info - S3C PCM Controller information
- * @dev: The parent device passed to use from the probe.
- * @regs: The pointer to the device register block.
- * @dma_playback: DMA information for playback channel.
- * @dma_capture: DMA information for capture channel.
- */
-struct s3c_pcm_info {
-	spinlock_t lock;
-	struct device	*dev;
-	void __iomem	*regs;
-
-	unsigned int sclk_per_fs;
-
-	/* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
-	unsigned int idleclk;
-
-	struct clk	*pclk;
-	struct clk	*cclk;
-
-	struct s3c_dma_params	*dma_playback;
-	struct s3c_dma_params	*dma_capture;
-};
-
 #endif /* __S3C_PCM_H */
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index f400274..1e574a5 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -17,26 +17,15 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
 #include <linux/gpio.h>
-#include <linux/clk.h>
 
 #include <sound/soc.h>
-#include <sound/uda1380.h>
 #include <sound/jack.h>
 
 #include <plat/regs-iis.h>
-
-#include <mach/regs-clock.h>
-
 #include <asm/mach-types.h>
 
-#include "dma.h"
 #include "s3c24xx-i2s.h"
-#include "../codecs/uda1380.h"
 
 static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd);
 static int rx1950_startup(struct snd_pcm_substream *substream);
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 094f36e..52074a2b 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -20,9 +20,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
 #include <mach/dma.h>
 
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 7ea8378..841ab14 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -16,21 +16,13 @@
  * option) any later version.
  */
 
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
-#include <linux/kernel.h>
 #include <linux/io.h>
 
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
 #include <sound/soc.h>
-#include <mach/hardware.h>
+#include <sound/pcm_params.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/dma.h>
@@ -39,8 +31,6 @@
 #include "regs-i2s-v2.h"
 #include "s3c2412-i2s.h"
 
-#define S3C2412_I2S_DEBUG 0
-
 static struct s3c2410_dma_client s3c2412_dma_client_out = {
 	.name		= "I2S PCM Stereo out"
 };
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 13e41ed..63d8849 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -14,28 +14,16 @@
  *  option) any later version.
  */
 
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
-#include <linux/jiffies.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
-#include <mach/hardware.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-clock.h>
-
-#include <asm/dma.h>
 #include <mach/dma.h>
-
 #include <plat/regs-iis.h>
 
 #include "dma.h"
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index a434032d..349566f 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -7,20 +7,13 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
-#include <linux/i2c.h>
 
-#include <sound/core.h>
-#include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <plat/audio-simtec.h>
 
-#include "dma.h"
 #include "s3c24xx-i2s.h"
 #include "s3c24xx_simtec.h"
 
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
index 08fcaaa..ce6aef6 100644
--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
+++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
@@ -7,18 +7,8 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
 #include <sound/soc.h>
 
-#include <plat/audio-simtec.h>
-
-#include "dma.h"
-#include "s3c24xx-i2s.h"
 #include "s3c24xx_simtec.h"
 
 static const struct snd_soc_dapm_widget dapm_widgets[] = {
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
index 116e3e6..a7ef7db 100644
--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
@@ -7,22 +7,10 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
 #include <sound/soc.h>
 
-#include <plat/audio-simtec.h>
-
-#include "dma.h"
-#include "s3c24xx-i2s.h"
 #include "s3c24xx_simtec.h"
 
-#include "../codecs/tlv320aic23.h"
-
 /* supported machines:
  *
  * Machine	Connections		AMP
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c
index 2c09e93..dc9d551 100644
--- a/sound/soc/samsung/s3c24xx_uda134x.c
+++ b/sound/soc/samsung/s3c24xx_uda134x.c
@@ -11,22 +11,15 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/clk.h>
-#include <linux/mutex.h>
 #include <linux/gpio.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
+
 #include <sound/soc.h>
 #include <sound/s3c24xx_uda134x.h>
-#include <sound/uda134x.h>
 
 #include <plat/regs-iis.h>
 
-#include "dma.h"
 #include "s3c24xx-i2s.h"
-#include "../codecs/uda134x.h"
-
 
 /* #define ENFORCE_RATES 1 */
 /*
@@ -226,7 +219,7 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = {
 static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
 	.name = "UDA134X",
 	.stream_name = "UDA134X",
-	.codec_name = "uda134x-hifi",
+	.codec_name = "uda134x-codec",
 	.codec_dai_name = "uda134x-hifi",
 	.cpu_dai_name = "s3c24xx-iis",
 	.ops = &s3c24xx_uda134x_ops,
@@ -321,6 +314,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(s3c24xx_uda134x_snd_device,
 			     &snd_soc_s3c24xx_uda134x);
+	platform_device_add_data(s3c24xx_uda134x_snd_device, &s3c24xx_uda134x, sizeof(s3c24xx_uda134x));
 	ret = platform_device_add(s3c24xx_uda134x_snd_device);
 	if (ret) {
 		printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index 61e2b52..0a2c4f2 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -13,20 +13,14 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/platform_device.h>
 #include <linux/gpio.h>
 
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
 #include <sound/jack.h>
 
 #include <asm/mach-types.h>
 
-#include "dma.h"
 #include "i2s.h"
-
 #include "../codecs/wm8750.h"
 
 /*
diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c
index 3be7e7e..3a0dbfc 100644
--- a/sound/soc/samsung/smdk2443_wm9710.c
+++ b/sound/soc/samsung/smdk2443_wm9710.c
@@ -12,15 +12,8 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
 #include <sound/soc.h>
 
-#include "dma.h"
-#include "ac97.h"
-
 static struct snd_soc_card smdk2443;
 
 static struct snd_soc_dai_link smdk2443_dai[] = {
diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c
index b5c3fad..e8ac961 100644
--- a/sound/soc/samsung/smdk_spdif.c
+++ b/sound/soc/samsung/smdk_spdif.c
@@ -10,15 +10,10 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/device.h>
 #include <linux/clk.h>
 
-#include <plat/devs.h>
-
 #include <sound/soc.h>
 
-#include "dma.h"
 #include "spdif.h"
 
 /* Audio clock settings are belonged to board specific part. Every
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index b2cff1a..8aacf23 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -10,17 +10,12 @@
  *  option) any later version.
  */
 
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
 #include <asm/mach-types.h>
 
 #include "../codecs/wm8580.h"
-#include "dma.h"
 #include "i2s.h"
 
 /*
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index ae5fed6..fffe3c1 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -11,13 +11,8 @@
  *
  */
 
-#include <linux/module.h>
-#include <linux/device.h>
 #include <sound/soc.h>
 
-#include "dma.h"
-#include "ac97.h"
-
 static struct snd_soc_card smdk;
 
 /*
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index f081640..28c491d 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -13,9 +13,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 
 #include <plat/audio.h>
 #include <mach/dma.h>
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index a14820a..d6f4703 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -18,18 +18,26 @@ struct fsi_ak4642_data {
 	const char *cpu_dai;
 	const char *codec;
 	const char *platform;
+	int id;
 };
 
 static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_dai *dai = rtd->codec_dai;
+	struct snd_soc_dai *codec = rtd->codec_dai;
+	struct snd_soc_dai *cpu = rtd->cpu_dai;
 	int ret;
 
-	ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM);
+	ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J |
+					 SND_SOC_DAIFMT_CBM_CFM);
 	if (ret < 0)
 		return ret;
 
-	ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0);
+	ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
+				       SND_SOC_DAIFMT_CBS_CFS);
 
 	return ret;
 }
@@ -60,7 +68,7 @@ static int fsi_ak4642_probe(struct platform_device *pdev)
 
 	pdata = (struct fsi_ak4642_data *)id_entry->driver_data;
 
-	fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_A);
+	fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
 	if (!fsi_snd_device)
 		goto out;
 
@@ -93,6 +101,7 @@ static struct fsi_ak4642_data fsi_a_ak4642 = {
 	.cpu_dai	= "fsia-dai",
 	.codec		= "ak4642-codec.0-0012",
 	.platform	= "sh_fsi.0",
+	.id		= FSI_PORT_A,
 };
 
 static struct fsi_ak4642_data fsi_b_ak4642 = {
@@ -101,6 +110,7 @@ static struct fsi_ak4642_data fsi_b_ak4642 = {
 	.cpu_dai	= "fsib-dai",
 	.codec		= "ak4642-codec.0-0012",
 	.platform	= "sh_fsi.0",
+	.id		= FSI_PORT_B,
 };
 
 static struct fsi_ak4642_data fsi_a_ak4643 = {
@@ -109,6 +119,7 @@ static struct fsi_ak4642_data fsi_a_ak4643 = {
 	.cpu_dai	= "fsia-dai",
 	.codec		= "ak4642-codec.0-0013",
 	.platform	= "sh_fsi.0",
+	.id		= FSI_PORT_A,
 };
 
 static struct fsi_ak4642_data fsi_b_ak4643 = {
@@ -117,6 +128,7 @@ static struct fsi_ak4642_data fsi_b_ak4643 = {
 	.cpu_dai	= "fsib-dai",
 	.codec		= "ak4642-codec.0-0013",
 	.platform	= "sh_fsi.0",
+	.id		= FSI_PORT_B,
 };
 
 static struct fsi_ak4642_data fsi2_a_ak4642 = {
@@ -125,6 +137,7 @@ static struct fsi_ak4642_data fsi2_a_ak4642 = {
 	.cpu_dai	= "fsia-dai",
 	.codec		= "ak4642-codec.0-0012",
 	.platform	= "sh_fsi2",
+	.id		= FSI_PORT_A,
 };
 
 static struct fsi_ak4642_data fsi2_b_ak4642 = {
@@ -133,6 +146,7 @@ static struct fsi_ak4642_data fsi2_b_ak4642 = {
 	.cpu_dai	= "fsib-dai",
 	.codec		= "ak4642-codec.0-0012",
 	.platform	= "sh_fsi2",
+	.id		= FSI_PORT_B,
 };
 
 static struct fsi_ak4642_data fsi2_a_ak4643 = {
@@ -141,6 +155,7 @@ static struct fsi_ak4642_data fsi2_a_ak4643 = {
 	.cpu_dai	= "fsia-dai",
 	.codec		= "ak4642-codec.0-0013",
 	.platform	= "sh_fsi2",
+	.id		= FSI_PORT_A,
 };
 
 static struct fsi_ak4642_data fsi2_b_ak4643 = {
@@ -149,6 +164,7 @@ static struct fsi_ak4642_data fsi2_b_ak4643 = {
 	.cpu_dai	= "fsib-dai",
 	.codec		= "ak4642-codec.0-0013",
 	.platform	= "sh_fsi2",
+	.id		= FSI_PORT_B,
 };
 
 static struct platform_device_id fsi_id_table[] = {
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index e8df9da..dbafd7a 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -15,11 +15,20 @@
 
 static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
 {
-	struct snd_soc_dai *dai = rtd->codec_dai;
+	struct snd_soc_dai *codec = rtd->codec_dai;
+	struct snd_soc_dai *cpu = rtd->cpu_dai;
+	int ret;
 
-	return snd_soc_dai_set_fmt(dai,
+	ret = snd_soc_dai_set_fmt(codec,
 				   SND_SOC_DAIFMT_I2S |
 				   SND_SOC_DAIFMT_CBM_CFM);
+	if (ret < 0)
+		return ret;
+
+	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
+				       SND_SOC_DAIFMT_CBS_CFS);
+
+	return ret;
 }
 
 static struct snd_soc_dai_link fsi_da7210_dai = {
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
index a52dd8e..9719985 100644
--- a/sound/soc/sh/fsi-hdmi.c
+++ b/sound/soc/sh/fsi-hdmi.c
@@ -12,31 +12,59 @@
 #include <linux/platform_device.h>
 #include <sound/sh_fsi.h>
 
+struct fsi_hdmi_data {
+	const char *cpu_dai;
+	const char *card;
+	int id;
+};
+
+static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_dai *cpu = rtd->cpu_dai;
+	int ret;
+
+	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM);
+
+	return ret;
+}
+
 static struct snd_soc_dai_link fsi_dai_link = {
 	.name		= "HDMI",
 	.stream_name	= "HDMI",
-	.cpu_dai_name	= "fsib-dai", /* fsi B */
 	.codec_dai_name	= "sh_mobile_hdmi-hifi",
 	.platform_name	= "sh_fsi2",
 	.codec_name	= "sh-mobile-hdmi",
+	.init		= fsi_hdmi_dai_init,
 };
 
 static struct snd_soc_card fsi_soc_card  = {
-	.name		= "FSI (SH MOBILE HDMI)",
 	.dai_link	= &fsi_dai_link,
 	.num_links	= 1,
 };
 
 static struct platform_device *fsi_snd_device;
 
-static int __init fsi_hdmi_init(void)
+static int fsi_hdmi_probe(struct platform_device *pdev)
 {
 	int ret = -ENOMEM;
+	const struct platform_device_id	*id_entry;
+	struct fsi_hdmi_data *pdata;
+
+	id_entry = pdev->id_entry;
+	if (!id_entry) {
+		dev_err(&pdev->dev, "unknown fsi hdmi\n");
+		return -ENODEV;
+	}
 
-	fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
+	pdata = (struct fsi_hdmi_data *)id_entry->driver_data;
+
+	fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
 	if (!fsi_snd_device)
 		goto out;
 
+	fsi_dai_link.cpu_dai_name	= pdata->cpu_dai;
+	fsi_soc_card.name		= pdata->card;
+
 	platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
 	ret = platform_device_add(fsi_snd_device);
 
@@ -47,9 +75,48 @@ out:
 	return ret;
 }
 
-static void __exit fsi_hdmi_exit(void)
+static int fsi_hdmi_remove(struct platform_device *pdev)
 {
 	platform_device_unregister(fsi_snd_device);
+	return 0;
+}
+
+static struct fsi_hdmi_data fsi2_a_hdmi = {
+	.cpu_dai	= "fsia-dai",
+	.card		= "FSI2A (SH MOBILE HDMI)",
+	.id		= FSI_PORT_A,
+};
+
+static struct fsi_hdmi_data fsi2_b_hdmi = {
+	.cpu_dai	= "fsib-dai",
+	.card		= "FSI2B (SH MOBILE HDMI)",
+	.id		= FSI_PORT_B,
+};
+
+static struct platform_device_id fsi_id_table[] = {
+	/* FSI 2 */
+	{ "sh_fsi2_a_hdmi",	(kernel_ulong_t)&fsi2_a_hdmi },
+	{ "sh_fsi2_b_hdmi",	(kernel_ulong_t)&fsi2_b_hdmi },
+	{},
+};
+
+static struct platform_driver fsi_hdmi = {
+	.driver = {
+		.name	= "fsi-hdmi-audio",
+	},
+	.probe		= fsi_hdmi_probe,
+	.remove		= fsi_hdmi_remove,
+	.id_table	= fsi_id_table,
+};
+
+static int __init fsi_hdmi_init(void)
+{
+	return platform_driver_register(&fsi_hdmi);
+}
+
+static void __exit fsi_hdmi_exit(void)
+{
+	platform_driver_unregister(&fsi_hdmi);
 }
 
 module_init(fsi_hdmi_init);
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 2b06402..0c9997e 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -78,6 +78,8 @@
 /* CKG1 */
 #define ACKMD_MASK	0x00007000
 #define BPFMD_MASK	0x00000700
+#define DIMD		(1 << 4)
+#define DOMD		(1 << 0)
 
 /* A/B MST_CTLR */
 #define BP	(1 << 4)	/* Fix the signal of Biphase output */
@@ -111,6 +113,8 @@
 
 #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
 
+typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable);
+
 /*
  * FSI driver use below type name for variable
  *
@@ -128,7 +132,6 @@ struct fsi_stream {
 	struct snd_pcm_substream *substream;
 
 	int fifo_max_num;
-	int chan_num;
 
 	int buff_offset;
 	int buff_len;
@@ -143,6 +146,7 @@ struct fsi_priv {
 	void __iomem *base;
 	struct fsi_master *master;
 
+	int chan_num;
 	struct fsi_stream playback;
 	struct fsi_stream capture;
 
@@ -252,9 +256,8 @@ static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
 	return  rtd->cpu_dai;
 }
 
-static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
+static struct fsi_priv *fsi_get_priv_frm_dai(struct snd_soc_dai *dai)
 {
-	struct snd_soc_dai *dai = fsi_get_dai(substream);
 	struct fsi_master *master = snd_soc_dai_get_drvdata(dai);
 
 	if (dai->id == 0)
@@ -263,11 +266,27 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
 		return &master->fsib;
 }
 
+static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
+{
+	return fsi_get_priv_frm_dai(fsi_get_dai(substream));
+}
+
+static set_rate_func fsi_get_info_set_rate(struct fsi_master *master)
+{
+	if (!master->info)
+		return NULL;
+
+	return master->info->set_rate;
+}
+
 static u32 fsi_get_info_flags(struct fsi_priv *fsi)
 {
 	int is_porta = fsi_is_port_a(fsi);
 	struct fsi_master *master = fsi_get_master(fsi);
 
+	if (!master->info)
+		return 0;
+
 	return is_porta ? master->info->porta_flags :
 		master->info->portb_flags;
 }
@@ -288,21 +307,6 @@ static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
 	return is_play ? &fsi->playback : &fsi->capture;
 }
 
-static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
-{
-	u32 mode;
-	u32 flags = fsi_get_info_flags(fsi);
-
-	mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE;
-
-	/* return
-	 * 1 : master mode
-	 * 0 : slave mode
-	 */
-
-	return (mode & flags) != mode;
-}
-
 static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
 {
 	int is_porta = fsi_is_port_a(fsi);
@@ -357,7 +361,6 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
 static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play)
 {
 	u32 status;
-	struct fsi_stream *io = fsi_get_stream(fsi, is_play);
 	int data_num;
 
 	status = is_play ?
@@ -365,7 +368,7 @@ static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play)
 		fsi_reg_read(fsi, DIFF_ST);
 
 	data_num = 0x1ff & (status >> 8);
-	data_num *= io->chan_num;
+	data_num *= fsi->chan_num;
 
 	return data_num;
 }
@@ -387,7 +390,7 @@ static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play)
 	struct snd_pcm_substream *substream = io->substream;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	return frames_to_bytes(runtime, 1) / io->chan_num;
+	return frames_to_bytes(runtime, 1) / fsi->chan_num;
 }
 
 static void fsi_count_fifo_err(struct fsi_priv *fsi)
@@ -580,10 +583,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi,
 	 * 7 channels:  32 ( 32 x 7 = 224)
 	 * 8 channels:  32 ( 32 x 8 = 256)
 	 */
-	for (i = 1; i < io->chan_num; i <<= 1)
+	for (i = 1; i < fsi->chan_num; i <<= 1)
 		io->fifo_max_num >>= 1;
 	dev_dbg(dai->dev, "%d channel %d store\n",
-		io->chan_num, io->fifo_max_num);
+		fsi->chan_num, io->fifo_max_num);
 
 	/*
 	 * set interrupt generation factor
@@ -659,7 +662,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
 		 * data_num_max	: number of FSI fifo free space
 		 * data_num	: number of ALSA residue data
 		 */
-		data_num_max  = io->fifo_max_num * io->chan_num;
+		data_num_max  = io->fifo_max_num * fsi->chan_num;
 		data_num_max -= fsi_get_fifo_data_num(fsi, is_play);
 
 		data_num = data_residue_num;
@@ -754,25 +757,12 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	struct fsi_master *master = fsi_get_master(fsi);
-	struct fsi_stream *io;
 	u32 flags = fsi_get_info_flags(fsi);
-	u32 fmt;
 	u32 data;
 	int is_play = fsi_is_play(substream);
-	int is_master;
-
-	io = fsi_get_stream(fsi, is_play);
 
 	pm_runtime_get_sync(dai->dev);
 
-	/* CKG1 */
-	data = is_play ? (1 << 0) : (1 << 4);
-	is_master = fsi_is_master_mode(fsi, is_play);
-	if (is_master)
-		fsi_reg_mask_set(fsi, CKG1, data, data);
-	else
-		fsi_reg_mask_set(fsi, CKG1, data, 0);
 
 	/* clock inversion (CKG2) */
 	data = 0;
@@ -787,54 +777,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 
 	fsi_reg_write(fsi, CKG2, data);
 
-	/* do fmt, di fmt */
-	data = 0;
-	fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
-	switch (fmt) {
-	case SH_FSI_FMT_MONO:
-		data = CR_MONO;
-		io->chan_num = 1;
-		break;
-	case SH_FSI_FMT_MONO_DELAY:
-		data = CR_MONO_D;
-		io->chan_num = 1;
-		break;
-	case SH_FSI_FMT_PCM:
-		data = CR_PCM;
-		io->chan_num = 2;
-		break;
-	case SH_FSI_FMT_I2S:
-		data = CR_I2S;
-		io->chan_num = 2;
-		break;
-	case SH_FSI_FMT_TDM:
-		io->chan_num = is_play ?
-			SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
-		data = CR_TDM | (io->chan_num - 1);
-		break;
-	case SH_FSI_FMT_TDM_DELAY:
-		io->chan_num = is_play ?
-			SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
-		data = CR_TDM_D | (io->chan_num - 1);
-		break;
-	case SH_FSI_FMT_SPDIF:
-		if (master->core->ver < 2) {
-			dev_err(dai->dev, "This FSI can not use SPDIF\n");
-			return -EINVAL;
-		}
-		data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
-		io->chan_num = 2;
-		fsi_spdif_clk_ctrl(fsi, 1);
-		fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
-		break;
-	default:
-		dev_err(dai->dev, "unknown format.\n");
-		return -EINVAL;
-	}
-	is_play ?
-		fsi_reg_write(fsi, DO_FMT, data) :
-		fsi_reg_write(fsi, DI_FMT, data);
-
 	/* irq clear */
 	fsi_irq_disable(fsi, is_play);
 	fsi_irq_clear_status(fsi);
@@ -851,12 +793,12 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
 	struct fsi_priv *fsi = fsi_get_priv(substream);
 	int is_play = fsi_is_play(substream);
 	struct fsi_master *master = fsi_get_master(fsi);
-	int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
+	set_rate_func set_rate;
 
 	fsi_irq_disable(fsi, is_play);
 	fsi_clk_ctrl(fsi, 0);
 
-	set_rate = master->info->set_rate;
+	set_rate = fsi_get_info_set_rate(master);
 	if (set_rate && fsi->rate)
 		set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0);
 	fsi->rate = 0;
@@ -889,18 +831,100 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 	return ret;
 }
 
+static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
+{
+	u32 data = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		data = CR_I2S;
+		fsi->chan_num = 2;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		data = CR_PCM;
+		fsi->chan_num = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	fsi_reg_write(fsi, DO_FMT, data);
+	fsi_reg_write(fsi, DI_FMT, data);
+
+	return 0;
+}
+
+static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
+{
+	struct fsi_master *master = fsi_get_master(fsi);
+	u32 data = 0;
+
+	if (master->core->ver < 2)
+		return -EINVAL;
+
+	data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
+	fsi->chan_num = 2;
+	fsi_spdif_clk_ctrl(fsi, 1);
+	fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
+
+	fsi_reg_write(fsi, DO_FMT, data);
+	fsi_reg_write(fsi, DI_FMT, data);
+
+	return 0;
+}
+
+static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
+	u32 flags = fsi_get_info_flags(fsi);
+	u32 data = 0;
+	int ret;
+
+	pm_runtime_get_sync(dai->dev);
+
+	/* set master/slave audio interface */
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		data = DIMD | DOMD;
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		break;
+	default:
+		ret = -EINVAL;
+		goto set_fmt_exit;
+	}
+	fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
+
+	/* set format */
+	switch (flags & SH_FSI_FMT_MASK) {
+	case SH_FSI_FMT_DAI:
+		ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		break;
+	case SH_FSI_FMT_SPDIF:
+		ret = fsi_set_fmt_spdif(fsi);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+set_fmt_exit:
+	pm_runtime_put_sync(dai->dev);
+
+	return ret;
+}
+
 static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *params,
 			     struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
 	struct fsi_master *master = fsi_get_master(fsi);
-	int (*set_rate)(struct device *dev, int is_porta, int rate, int enable);
+	set_rate_func set_rate;
 	int fsi_ver = master->core->ver;
 	long rate = params_rate(params);
 	int ret;
 
-	set_rate = master->info->set_rate;
+	set_rate = fsi_get_info_set_rate(master);
 	if (!set_rate)
 		return 0;
 
@@ -975,6 +999,7 @@ static struct snd_soc_dai_ops fsi_dai_ops = {
 	.startup	= fsi_dai_startup,
 	.shutdown	= fsi_dai_shutdown,
 	.trigger	= fsi_dai_trigger,
+	.set_fmt	= fsi_dai_set_fmt,
 	.hw_params	= fsi_dai_hw_params,
 };
 
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 8c2a21a..5d76da4 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -18,6 +18,8 @@
 #include <linux/bitmap.h>
 #include <linux/rbtree.h>
 
+#include <trace/events/asoc.h>
+
 static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
 				     unsigned int reg)
 {
@@ -25,7 +27,8 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
 	unsigned int val;
 
 	if (reg >= codec->driver->reg_cache_size ||
-		snd_soc_codec_volatile_register(codec, reg)) {
+		snd_soc_codec_volatile_register(codec, reg) ||
+		codec->cache_bypass) {
 			if (codec->cache_only)
 				return -1;
 
@@ -49,7 +52,8 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[1] = value & 0x00ff;
 
 	if (!snd_soc_codec_volatile_register(codec, reg) &&
-		reg < codec->driver->reg_cache_size) {
+		reg < codec->driver->reg_cache_size &&
+		!codec->cache_bypass) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret < 0)
 			return -1;
@@ -106,7 +110,8 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
 	unsigned int val;
 
 	if (reg >= codec->driver->reg_cache_size ||
-		snd_soc_codec_volatile_register(codec, reg)) {
+		snd_soc_codec_volatile_register(codec, reg) ||
+		codec->cache_bypass) {
 			if (codec->cache_only)
 				return -1;
 
@@ -130,7 +135,8 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[1] = value & 0x00ff;
 
 	if (!snd_soc_codec_volatile_register(codec, reg) &&
-		reg < codec->driver->reg_cache_size) {
+		reg < codec->driver->reg_cache_size &&
+		!codec->cache_bypass) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret < 0)
 			return -1;
@@ -191,7 +197,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[1] = value & 0xff;
 
 	if (!snd_soc_codec_volatile_register(codec, reg) &&
-		reg < codec->driver->reg_cache_size) {
+		reg < codec->driver->reg_cache_size &&
+		!codec->cache_bypass) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret < 0)
 			return -1;
@@ -216,7 +223,8 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
 
 	reg &= 0xff;
 	if (reg >= codec->driver->reg_cache_size ||
-		snd_soc_codec_volatile_register(codec, reg)) {
+		snd_soc_codec_volatile_register(codec, reg) ||
+		codec->cache_bypass) {
 			if (codec->cache_only)
 				return -1;
 
@@ -271,7 +279,8 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[2] = value & 0xff;
 
 	if (!snd_soc_codec_volatile_register(codec, reg) &&
-		reg < codec->driver->reg_cache_size) {
+		reg < codec->driver->reg_cache_size &&
+		!codec->cache_bypass) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret < 0)
 			return -1;
@@ -295,7 +304,8 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
 	unsigned int val;
 
 	if (reg >= codec->driver->reg_cache_size ||
-	    snd_soc_codec_volatile_register(codec, reg)) {
+	    snd_soc_codec_volatile_register(codec, reg) ||
+	    codec->cache_bypass) {
 		if (codec->cache_only)
 			return -1;
 
@@ -450,7 +460,8 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
 
 	reg &= 0xff;
 	if (reg >= codec->driver->reg_cache_size ||
-		snd_soc_codec_volatile_register(codec, reg)) {
+		snd_soc_codec_volatile_register(codec, reg) ||
+		codec->cache_bypass) {
 			if (codec->cache_only)
 				return -1;
 
@@ -476,7 +487,8 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
 
 	reg &= 0xff;
 	if (!snd_soc_codec_volatile_register(codec, reg) &&
-		reg < codec->driver->reg_cache_size) {
+		reg < codec->driver->reg_cache_size &&
+		!codec->cache_bypass) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret < 0)
 			return -1;
@@ -568,7 +580,8 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
 	unsigned int val;
 
 	if (reg >= codec->driver->reg_cache_size ||
-	    snd_soc_codec_volatile_register(codec, reg)) {
+	    snd_soc_codec_volatile_register(codec, reg) ||
+	    codec->cache_bypass) {
 		if (codec->cache_only)
 			return -1;
 
@@ -595,7 +608,8 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
 	data[3] = value & 0xff;
 
 	if (!snd_soc_codec_volatile_register(codec, reg) &&
-		reg < codec->driver->reg_cache_size) {
+		reg < codec->driver->reg_cache_size &&
+		!codec->cache_bypass) {
 		ret = snd_soc_cache_write(codec, reg, value);
 		if (ret < 0)
 			return -1;
@@ -761,6 +775,49 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
 
+static bool snd_soc_set_cache_val(void *base, unsigned int idx,
+				  unsigned int val, unsigned int word_size)
+{
+	switch (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;
+	}
+	default:
+		BUG();
+	}
+	return false;
+}
+
+static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
+		unsigned int word_size)
+{
+	switch (word_size) {
+	case 1: {
+		const u8 *cache = base;
+		return cache[idx];
+	}
+	case 2: {
+		const u16 *cache = base;
+		return cache[idx];
+	}
+	default:
+		BUG();
+	}
+	/* unreachable */
+	return -1;
+}
+
 struct snd_soc_rbtree_node {
 	struct rb_node node;
 	unsigned int reg;
@@ -835,7 +892,9 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
 		ret = snd_soc_cache_read(codec, rbnode->reg, &val);
 		if (ret)
 			return ret;
+		codec->cache_bypass = 1;
 		ret = snd_soc_write(codec, rbnode->reg, val);
+		codec->cache_bypass = 0;
 		if (ret)
 			return ret;
 		dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
@@ -924,7 +983,12 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
 
 static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
 {
+	struct snd_soc_rbtree_node *rbtree_node;
 	struct snd_soc_rbtree_ctx *rbtree_ctx;
+	unsigned int val;
+	unsigned int word_size;
+	int i;
+	int ret;
 
 	codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
 	if (!codec->reg_cache)
@@ -936,53 +1000,25 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
 	if (!codec->reg_def_copy)
 		return 0;
 
-/*
- * populate the rbtree with the initialized registers.  All other
- * registers will be inserted into the tree when they are first written.
- *
- * The reasoning behind this, is that we need to step through and
- * dereference the cache in u8/u16 increments without sacrificing
- * portability.  This could also be done using memcpy() but that would
- * be slightly more cryptic.
- */
-#define snd_soc_rbtree_populate(cache)					\
-({									\
-	int ret, i;							\
-	struct snd_soc_rbtree_node *rbtree_node;			\
-									\
-	ret = 0;							\
-	cache = codec->reg_def_copy;					\
-	for (i = 0; i < codec->driver->reg_cache_size; ++i) {		\
-		if (!cache[i])						\
-			continue;					\
-		rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);	\
-		if (!rbtree_node) {					\
-			ret = -ENOMEM;					\
-			snd_soc_cache_exit(codec);			\
-			break;						\
-		}							\
-		rbtree_node->reg = i;					\
-		rbtree_node->value = cache[i];				\
-		rbtree_node->defval = cache[i];				\
-		snd_soc_rbtree_insert(&rbtree_ctx->root,		\
-				      rbtree_node);			\
-	}								\
-	ret;								\
-})
-
-	switch (codec->driver->reg_word_size) {
-	case 1: {
-		const u8 *cache;
-
-		return snd_soc_rbtree_populate(cache);
-	}
-	case 2: {
-		const u16 *cache;
-
-		return snd_soc_rbtree_populate(cache);
-	}
-	default:
-		BUG();
+	/*
+	 * populate the rbtree with the initialized registers.  All other
+	 * registers will be inserted when they are first modified.
+	 */
+	word_size = codec->driver->reg_word_size;
+	for (i = 0; i < codec->driver->reg_cache_size; ++i) {
+		val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
+		if (!val)
+			continue;
+		rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
+		if (!rbtree_node) {
+			ret = -ENOMEM;
+			snd_soc_cache_exit(codec);
+			break;
+		}
+		rbtree_node->reg = i;
+		rbtree_node->value = val;
+		rbtree_node->defval = val;
+		snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node);
 	}
 
 	return 0;
@@ -1080,34 +1116,28 @@ static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
 		unsigned int reg)
 {
 	const struct snd_soc_codec_driver *codec_drv;
-	size_t reg_size;
 
 	codec_drv = codec->driver;
-	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
 	return (reg * codec_drv->reg_word_size) /
-	       DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count());
+	       DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
 }
 
 static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
 		unsigned int reg)
 {
 	const struct snd_soc_codec_driver *codec_drv;
-	size_t reg_size;
 
 	codec_drv = codec->driver;
-	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
-	return reg % (DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()) /
+	return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
 		      codec_drv->reg_word_size);
 }
 
 static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
 {
 	const struct snd_soc_codec_driver *codec_drv;
-	size_t reg_size;
 
 	codec_drv = codec->driver;
-	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
-	return DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count());
+	return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
 }
 
 static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
@@ -1122,7 +1152,9 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
 		ret = snd_soc_cache_read(codec, i, &val);
 		if (ret)
 			return ret;
+		codec->cache_bypass = 1;
 		ret = snd_soc_write(codec, i, val);
+		codec->cache_bypass = 0;
 		if (ret)
 			return ret;
 		dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
@@ -1165,29 +1197,10 @@ static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
 	}
 
 	/* write the new value to the cache */
-	switch (codec->driver->reg_word_size) {
-	case 1: {
-		u8 *cache;
-		cache = lzo_block->dst;
-		if (cache[blkpos] == value) {
-			kfree(lzo_block->dst);
-			goto out;
-		}
-		cache[blkpos] = value;
-	}
-	break;
-	case 2: {
-		u16 *cache;
-		cache = lzo_block->dst;
-		if (cache[blkpos] == value) {
-			kfree(lzo_block->dst);
-			goto out;
-		}
-		cache[blkpos] = value;
-	}
-	break;
-	default:
-		BUG();
+	if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
+				  codec->driver->reg_word_size)) {
+		kfree(lzo_block->dst);
+		goto out;
 	}
 
 	/* prepare the source to be the decompressed block */
@@ -1241,25 +1254,10 @@ static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
 
 	/* decompress the block */
 	ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
-	if (ret >= 0) {
+	if (ret >= 0)
 		/* fetch the value from the cache */
-		switch (codec->driver->reg_word_size) {
-		case 1: {
-			u8 *cache;
-			cache = lzo_block->dst;
-			*value = cache[blkpos];
-		}
-		break;
-		case 2: {
-			u16 *cache;
-			cache = lzo_block->dst;
-			*value = cache[blkpos];
-		}
-		break;
-		default:
-			BUG();
-		}
-	}
+		*value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
+					       codec->driver->reg_word_size);
 
 	kfree(lzo_block->dst);
 	/* restore the pointer and length of the compressed block */
@@ -1301,7 +1299,7 @@ static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
 static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
 {
 	struct snd_soc_lzo_ctx **lzo_blocks;
-	size_t reg_size, bmp_size;
+	size_t bmp_size;
 	const struct snd_soc_codec_driver *codec_drv;
 	int ret, tofree, i, blksize, blkcount;
 	const char *p, *end;
@@ -1309,7 +1307,6 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
 
 	ret = 0;
 	codec_drv = codec->driver;
-	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
 
 	/*
 	 * If we have not been given a default register cache
@@ -1321,8 +1318,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
 		tofree = 1;
 
 	if (!codec->reg_def_copy) {
-		codec->reg_def_copy = kzalloc(reg_size,
-						       GFP_KERNEL);
+		codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
 		if (!codec->reg_def_copy)
 			return -ENOMEM;
 	}
@@ -1370,7 +1366,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
 
 	blksize = snd_soc_lzo_get_blksize(codec);
 	p = codec->reg_def_copy;
-	end = codec->reg_def_copy + reg_size;
+	end = codec->reg_def_copy + codec->reg_size;
 	/* compress the register map and fill the lzo blocks */
 	for (i = 0; i < blkcount; ++i, p += blksize) {
 		lzo_blocks[i]->src = p;
@@ -1414,28 +1410,10 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 		ret = snd_soc_cache_read(codec, i, &val);
 		if (ret)
 			return ret;
-		if (codec_drv->reg_cache_default) {
-			switch (codec_drv->reg_word_size) {
-			case 1: {
-				const u8 *cache;
-
-				cache = codec_drv->reg_cache_default;
-				if (cache[i] == val)
-					continue;
-			}
-			break;
-			case 2: {
-				const u16 *cache;
-
-				cache = codec_drv->reg_cache_default;
-				if (cache[i] == val)
-					continue;
-			}
-			break;
-			default:
-				BUG();
-			}
-		}
+		if (codec->reg_def_copy)
+			if (snd_soc_get_cache_val(codec->reg_def_copy,
+						  i, codec_drv->reg_word_size) == val)
+				continue;
 		ret = snd_soc_write(codec, i, val);
 		if (ret)
 			return ret;
@@ -1448,50 +1426,16 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
 static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
 				    unsigned int reg, unsigned int value)
 {
-	switch (codec->driver->reg_word_size) {
-	case 1: {
-		u8 *cache;
-
-		cache = codec->reg_cache;
-		cache[reg] = value;
-	}
-	break;
-	case 2: {
-		u16 *cache;
-
-		cache = codec->reg_cache;
-		cache[reg] = value;
-	}
-	break;
-	default:
-		BUG();
-	}
-
+	snd_soc_set_cache_val(codec->reg_cache, reg, value,
+			      codec->driver->reg_word_size);
 	return 0;
 }
 
 static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
 				   unsigned int reg, unsigned int *value)
 {
-	switch (codec->driver->reg_word_size) {
-	case 1: {
-		u8 *cache;
-
-		cache = codec->reg_cache;
-		*value = cache[reg];
-	}
-	break;
-	case 2: {
-		u16 *cache;
-
-		cache = codec->reg_cache;
-		*value = cache[reg];
-	}
-	break;
-	default:
-		BUG();
-	}
-
+	*value = snd_soc_get_cache_val(codec->reg_cache, reg,
+				       codec->driver->reg_word_size);
 	return 0;
 }
 
@@ -1507,24 +1451,14 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
 static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
 {
 	const struct snd_soc_codec_driver *codec_drv;
-	size_t reg_size;
 
 	codec_drv = codec->driver;
-	reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
 
-	/*
-	 * for flat compression, we don't need to keep a copy of the
-	 * original defaults register cache as it will definitely not
-	 * be marked as __devinitconst
-	 */
-	kfree(codec->reg_def_copy);
-	codec->reg_def_copy = NULL;
-
-	if (codec_drv->reg_cache_default)
-		codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
-					   reg_size, GFP_KERNEL);
+	if (codec->reg_def_copy)
+		codec->reg_cache = kmemdup(codec->reg_def_copy,
+					   codec->reg_size, GFP_KERNEL);
 	else
-		codec->reg_cache = kzalloc(reg_size, GFP_KERNEL);
+		codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
 	if (!codec->reg_cache)
 		return -ENOMEM;
 
@@ -1669,21 +1603,77 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write);
 int snd_soc_cache_sync(struct snd_soc_codec *codec)
 {
 	int ret;
+	const char *name;
 
 	if (!codec->cache_sync) {
 		return 0;
 	}
 
-	if (codec->cache_ops && codec->cache_ops->sync) {
-		if (codec->cache_ops->name)
-			dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
-				codec->cache_ops->name, codec->name);
-		ret = codec->cache_ops->sync(codec);
-		if (!ret)
-			codec->cache_sync = 0;
-		return ret;
-	}
+	if (!codec->cache_ops || !codec->cache_ops->sync)
+		return -EINVAL;
 
-	return -EINVAL;
+	if (codec->cache_ops->name)
+		name = codec->cache_ops->name;
+	else
+		name = "unknown";
+
+	if (codec->cache_ops->name)
+		dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
+			codec->cache_ops->name, codec->name);
+	trace_snd_soc_cache_sync(codec, name, "start");
+	ret = codec->cache_ops->sync(codec);
+	if (!ret)
+		codec->cache_sync = 0;
+	trace_snd_soc_cache_sync(codec, name, "end");
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
+
+static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
+					unsigned int reg)
+{
+	const struct snd_soc_codec_driver *codec_drv;
+	unsigned int min, max, index;
+
+	codec_drv = codec->driver;
+	min = 0;
+	max = codec_drv->reg_access_size - 1;
+	do {
+		index = (min + max) / 2;
+		if (codec_drv->reg_access_default[index].reg == reg)
+			return index;
+		if (codec_drv->reg_access_default[index].reg < reg)
+			min = index + 1;
+		else
+			max = index;
+	} while (min <= max);
+	return -1;
+}
+
+int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
+				      unsigned int reg)
+{
+	int index;
+
+	if (reg >= codec->driver->reg_cache_size)
+		return 1;
+	index = snd_soc_get_reg_access_index(codec, reg);
+	if (index < 0)
+		return 0;
+	return codec->driver->reg_access_default[index].vol;
+}
+EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
+
+int snd_soc_default_readable_register(struct snd_soc_codec *codec,
+				      unsigned int reg)
+{
+	int index;
+
+	if (reg >= codec->driver->reg_cache_size)
+		return 1;
+	index = snd_soc_get_reg_access_index(codec, reg);
+	if (index < 0)
+		return 0;
+	return codec->driver->reg_access_default[index].read;
+}
+EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index c3f6f1e..4dda589 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -48,7 +48,8 @@ static DEFINE_MUTEX(pcm_mutex);
 static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
 
 #ifdef CONFIG_DEBUG_FS
-static struct dentry *debugfs_root;
+struct dentry *snd_soc_debugfs_root;
+EXPORT_SYMBOL_GPL(snd_soc_debugfs_root);
 #endif
 
 static DEFINE_MUTEX(client_mutex);
@@ -57,8 +58,6 @@ static LIST_HEAD(dai_list);
 static LIST_HEAD(platform_list);
 static LIST_HEAD(codec_list);
 
-static int snd_soc_register_card(struct snd_soc_card *card);
-static int snd_soc_unregister_card(struct snd_soc_card *card);
 static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
 
 /*
@@ -70,10 +69,73 @@ static int pmdown_time = 5000;
 module_param(pmdown_time, int, 0);
 MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
 
+/* returns the minimum number of bytes needed to represent
+ * a particular given value */
+static int min_bytes_needed(unsigned long val)
+{
+	int c = 0;
+	int i;
+
+	for (i = (sizeof val * 8) - 1; i >= 0; --i, ++c)
+		if (val & (1UL << i))
+			break;
+	c = (sizeof val * 8) - c;
+	if (!c || (c % 8))
+		c = (c + 8) / 8;
+	else
+		c /= 8;
+	return c;
+}
+
+/* fill buf which is 'len' bytes with a formatted
+ * string of the form 'reg: value\n' */
+static int format_register_str(struct snd_soc_codec *codec,
+			       unsigned int reg, char *buf, size_t len)
+{
+	int wordsize = codec->driver->reg_word_size * 2;
+	int regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
+	int ret;
+	char tmpbuf[len + 1];
+	char regbuf[regsize + 1];
+
+	/* since tmpbuf is allocated on the stack, warn the callers if they
+	 * try to abuse this function */
+	WARN_ON(len > 63);
+
+	/* +2 for ': ' and + 1 for '\n' */
+	if (wordsize + regsize + 2 + 1 != len)
+		return -EINVAL;
+
+	ret = snd_soc_read(codec , reg);
+	if (ret < 0) {
+		memset(regbuf, 'X', regsize);
+		regbuf[regsize] = '\0';
+	} else {
+		snprintf(regbuf, regsize + 1, "%.*x", regsize, ret);
+	}
+
+	/* prepare the buffer */
+	snprintf(tmpbuf, len + 1, "%.*x: %s\n", wordsize, reg, regbuf);
+	/* copy it back to the caller without the '\0' */
+	memcpy(buf, tmpbuf, len);
+
+	return 0;
+}
+
 /* codec register dump */
-static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
+static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
+				  size_t count, loff_t pos)
 {
-	int ret, i, step = 1, count = 0;
+	int i, step = 1;
+	int wordsize, regsize;
+	int len;
+	size_t total = 0;
+	loff_t p = 0;
+
+	wordsize = codec->driver->reg_word_size * 2;
+	regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
+
+	len = wordsize + regsize + 2 + 1;
 
 	if (!codec->driver->reg_cache_size)
 		return 0;
@@ -81,55 +143,37 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
 	if (codec->driver->reg_cache_step)
 		step = codec->driver->reg_cache_step;
 
-	count += sprintf(buf, "%s registers\n", codec->name);
 	for (i = 0; i < codec->driver->reg_cache_size; i += step) {
-		if (codec->driver->readable_register && !codec->driver->readable_register(i))
+		if (codec->readable_register && !codec->readable_register(codec, i))
 			continue;
-
-		count += sprintf(buf + count, "%2x: ", i);
-		if (count >= PAGE_SIZE - 1)
-			break;
-
 		if (codec->driver->display_register) {
 			count += codec->driver->display_register(codec, buf + count,
 							 PAGE_SIZE - count, i);
 		} else {
-			/* If the read fails it's almost certainly due to
-			 * the register being volatile and the device being
-			 * powered off.
-			 */
-			ret = snd_soc_read(codec, i);
-			if (ret >= 0)
-				count += snprintf(buf + count,
-						  PAGE_SIZE - count,
-						  "%4x", ret);
-			else
-				count += snprintf(buf + count,
-						  PAGE_SIZE - count,
-						  "<no data: %d>", ret);
+			/* only support larger than PAGE_SIZE bytes debugfs
+			 * entries for the default case */
+			if (p >= pos) {
+				if (total + len >= count - 1)
+					break;
+				format_register_str(codec, i, buf + total, len);
+				total += len;
+			}
+			p += len;
 		}
-
-		if (count >= PAGE_SIZE - 1)
-			break;
-
-		count += snprintf(buf + count, PAGE_SIZE - count, "\n");
-		if (count >= PAGE_SIZE - 1)
-			break;
 	}
 
-	/* Truncate count; min() would cause a warning */
-	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE - 1;
+	total = min(total, count - 1);
 
-	return count;
+	return total;
 }
+
 static ssize_t codec_reg_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
 	struct snd_soc_pcm_runtime *rtd =
 			container_of(dev, struct snd_soc_pcm_runtime, dev);
 
-	return soc_codec_reg_show(rtd->codec, buf);
+	return soc_codec_reg_show(rtd->codec, buf, PAGE_SIZE, 0);
 }
 
 static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
@@ -168,16 +212,28 @@ static int codec_reg_open_file(struct inode *inode, struct file *file)
 }
 
 static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
-			       size_t count, loff_t *ppos)
+				   size_t count, loff_t *ppos)
 {
 	ssize_t ret;
 	struct snd_soc_codec *codec = file->private_data;
-	char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	char *buf;
+
+	if (*ppos < 0 || !count)
+		return -EINVAL;
+
+	buf = kmalloc(count, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
-	ret = soc_codec_reg_show(codec, buf);
-	if (ret >= 0)
-		ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+	ret = soc_codec_reg_show(codec, buf, count, *ppos);
+	if (ret >= 0) {
+		if (copy_to_user(user_buf, buf, ret)) {
+			kfree(buf);
+			return -EFAULT;
+		}
+		*ppos += ret;
+	}
+
 	kfree(buf);
 	return ret;
 }
@@ -203,12 +259,14 @@ static ssize_t codec_reg_write_file(struct file *file,
 	while (*start == ' ')
 		start++;
 	reg = simple_strtoul(start, &start, 16);
-	if ((reg >= codec->driver->reg_cache_size) || (reg % step))
-		return -EINVAL;
 	while (*start == ' ')
 		start++;
 	if (strict_strtoul(start, 16, &value))
 		return -EINVAL;
+
+	/* Userspace has been fiddling around behind the kernel's back */
+	add_taint(TAINT_USER);
+
 	snd_soc_write(codec, reg, value);
 	return buf_size;
 }
@@ -232,6 +290,11 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
 		return;
 	}
 
+	debugfs_create_bool("cache_sync", 0444, codec->debugfs_codec_root,
+			    &codec->cache_sync);
+	debugfs_create_bool("cache_only", 0444, codec->debugfs_codec_root,
+			    &codec->cache_only);
+
 	codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
 						 codec->debugfs_codec_root,
 						 codec, &codec_reg_fops);
@@ -356,7 +419,7 @@ static const struct file_operations platform_list_fops = {
 static void soc_init_card_debugfs(struct snd_soc_card *card)
 {
 	card->debugfs_card_root = debugfs_create_dir(card->name,
-						     debugfs_root);
+						     snd_soc_debugfs_root);
 	if (!card->debugfs_card_root) {
 		dev_warn(card->dev,
 			 "ASoC: Failed to create codec debugfs directory\n");
@@ -435,20 +498,30 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	int ret;
 
-	if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates ||
-			rtd->dai_link->symmetric_rates) {
-		dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n",
-				rtd->rate);
+	if (!codec_dai->driver->symmetric_rates &&
+	    !cpu_dai->driver->symmetric_rates &&
+	    !rtd->dai_link->symmetric_rates)
+		return 0;
 
-		ret = snd_pcm_hw_constraint_minmax(substream->runtime,
-						   SNDRV_PCM_HW_PARAM_RATE,
-						   rtd->rate,
-						   rtd->rate);
-		if (ret < 0) {
-			dev_err(&rtd->dev,
-				"Unable to apply rate symmetry constraint: %d\n", ret);
-			return ret;
-		}
+	/* This can happen if multiple streams are starting simultaneously -
+	 * the second can need to get its constraints before the first has
+	 * picked a rate.  Complain and allow the application to carry on.
+	 */
+	if (!rtd->rate) {
+		dev_warn(&rtd->dev,
+			 "Not enforcing symmetric_rates due to race\n");
+		return 0;
+	}
+
+	dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+
+	ret = snd_pcm_hw_constraint_minmax(substream->runtime,
+					   SNDRV_PCM_HW_PARAM_RATE,
+					   rtd->rate, rtd->rate);
+	if (ret < 0) {
+		dev_err(&rtd->dev,
+			"Unable to apply rate symmetry constraint: %d\n", ret);
+		return ret;
 	}
 
 	return 0;
@@ -962,12 +1035,11 @@ static struct snd_pcm_ops soc_pcm_ops = {
 	.pointer	= soc_pcm_pointer,
 };
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 /* powers down audio subsystem for suspend */
-static int soc_suspend(struct device *dev)
+int snd_soc_suspend(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct snd_soc_card *card = dev_get_drvdata(dev);
 	struct snd_soc_codec *codec;
 	int i;
 
@@ -1008,7 +1080,7 @@ static int soc_suspend(struct device *dev)
 	}
 
 	if (card->suspend_pre)
-		card->suspend_pre(pdev, PMSG_SUSPEND);
+		card->suspend_pre(card);
 
 	for (i = 0; i < card->num_rtd; i++) {
 		struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
@@ -1075,10 +1147,11 @@ static int soc_suspend(struct device *dev)
 	}
 
 	if (card->suspend_post)
-		card->suspend_post(pdev, PMSG_SUSPEND);
+		card->suspend_post(card);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_suspend);
 
 /* deferred resume work, so resume can complete before we finished
  * setting our codec back up, which can be very slow on I2C
@@ -1087,7 +1160,6 @@ static void soc_resume_deferred(struct work_struct *work)
 {
 	struct snd_soc_card *card =
 			container_of(work, struct snd_soc_card, deferred_resume_work);
-	struct platform_device *pdev = to_platform_device(card->dev);
 	struct snd_soc_codec *codec;
 	int i;
 
@@ -1101,7 +1173,7 @@ static void soc_resume_deferred(struct work_struct *work)
 	snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
 
 	if (card->resume_pre)
-		card->resume_pre(pdev);
+		card->resume_pre(card);
 
 	/* resume AC97 DAIs */
 	for (i = 0; i < card->num_rtd; i++) {
@@ -1176,7 +1248,7 @@ static void soc_resume_deferred(struct work_struct *work)
 	}
 
 	if (card->resume_post)
-		card->resume_post(pdev);
+		card->resume_post(card);
 
 	dev_dbg(card->dev, "resume work completed\n");
 
@@ -1185,10 +1257,9 @@ static void soc_resume_deferred(struct work_struct *work)
 }
 
 /* powers up audio subsystem after a suspend */
-static int soc_resume(struct device *dev)
+int snd_soc_resume(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct snd_soc_card *card = dev_get_drvdata(dev);
 	int i;
 
 	/* AC97 devices might have other drivers hanging off them so
@@ -1210,9 +1281,10 @@ static int soc_resume(struct device *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_resume);
 #else
-#define soc_suspend	NULL
-#define soc_resume	NULL
+#define snd_soc_suspend NULL
+#define snd_soc_resume NULL
 #endif
 
 static struct snd_soc_dai_ops null_dai_ops = {
@@ -1400,31 +1472,44 @@ static int soc_probe_codec(struct snd_soc_card *card,
 			   struct snd_soc_codec *codec)
 {
 	int ret = 0;
+	const struct snd_soc_codec_driver *driver = codec->driver;
 
 	codec->card = card;
 	codec->dapm.card = card;
 	soc_set_name_prefix(card, codec);
 
-	if (codec->driver->probe) {
-		ret = codec->driver->probe(codec);
+	if (!try_module_get(codec->dev->driver->owner))
+		return -ENODEV;
+
+	if (driver->probe) {
+		ret = driver->probe(codec);
 		if (ret < 0) {
 			dev_err(codec->dev,
 				"asoc: failed to probe CODEC %s: %d\n",
 				codec->name, ret);
-			return ret;
+			goto err_probe;
 		}
 	}
 
+	if (driver->dapm_widgets)
+		snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
+					  driver->num_dapm_widgets);
+	if (driver->dapm_routes)
+		snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
+					driver->num_dapm_routes);
+
 	soc_init_codec_debugfs(codec);
 
 	/* mark codec as probed and add to card codec list */
-	if (!try_module_get(codec->dev->driver->owner))
-		return -ENODEV;
-
 	codec->probed = 1;
 	list_add(&codec->card_list, &card->codec_dev_list);
 	list_add(&codec->dapm.list, &card->dapm_list);
 
+	return 0;
+
+err_probe:
+	module_put(codec->dev->driver->owner);
+
 	return ret;
 }
 
@@ -1468,7 +1553,6 @@ static int soc_post_component_init(struct snd_soc_card *card,
 
 	/* Make sure all DAPM widgets are instantiated */
 	snd_soc_dapm_new_widgets(&codec->dapm);
-	snd_soc_dapm_sync(&codec->dapm);
 
 	/* register the rtd device */
 	rtd->codec = codec;
@@ -1543,19 +1627,19 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num)
 
 	/* probe the platform */
 	if (!platform->probed) {
+		if (!try_module_get(platform->dev->driver->owner))
+			return -ENODEV;
+
 		if (platform->driver->probe) {
 			ret = platform->driver->probe(platform);
 			if (ret < 0) {
 				printk(KERN_ERR "asoc: failed to probe platform %s\n",
 						platform->name);
+				module_put(platform->dev->driver->owner);
 				return ret;
 			}
 		}
 		/* mark platform as probed and add to card platform list */
-
-		if (!try_module_get(platform->dev->driver->owner))
-			return -ENODEV;
-
 		platform->probed = 1;
 		list_add(&platform->card_list, &card->platform_dev_list);
 	}
@@ -1713,7 +1797,6 @@ static int snd_soc_init_codec_cache(struct snd_soc_codec *codec,
 
 static void snd_soc_instantiate_card(struct snd_soc_card *card)
 {
-	struct platform_device *pdev = to_platform_device(card->dev);
 	struct snd_soc_codec *codec;
 	struct snd_soc_codec_conf *codec_conf;
 	enum snd_soc_compress_type compress_type;
@@ -1740,6 +1823,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 	list_for_each_entry(codec, &codec_list, list) {
 		if (codec->cache_init)
 			continue;
+		/* by default we don't override the compress_type */
+		compress_type = 0;
 		/* check to see if we need to override the compress_type */
 		for (i = 0; i < card->num_configs; ++i) {
 			codec_conf = &card->codec_conf[i];
@@ -1750,18 +1835,6 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 					break;
 			}
 		}
-		if (i == card->num_configs) {
-			/* no need to override the compress_type so
-			 * go ahead and do the standard thing */
-			ret = snd_soc_init_codec_cache(codec, 0);
-			if (ret < 0) {
-				mutex_unlock(&card->mutex);
-				return;
-			}
-			continue;
-		}
-		/* override the compress_type with the one supplied in
-		 * the machine driver */
 		ret = snd_soc_init_codec_cache(codec, compress_type);
 		if (ret < 0) {
 			mutex_unlock(&card->mutex);
@@ -1780,14 +1853,19 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 	}
 	card->snd_card->dev = card->dev;
 
-#ifdef CONFIG_PM
+	card->dapm.bias_level = SND_SOC_BIAS_OFF;
+	card->dapm.dev = card->dev;
+	card->dapm.card = card;
+	list_add(&card->dapm.list, &card->dapm_list);
+
+#ifdef CONFIG_PM_SLEEP
 	/* deferred resume work */
 	INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
 #endif
 
 	/* initialise the sound card only once */
 	if (card->probe) {
-		ret = card->probe(pdev);
+		ret = card->probe(card);
 		if (ret < 0)
 			goto card_probe_error;
 	}
@@ -1810,11 +1888,37 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
 		}
 	}
 
+	if (card->dapm_widgets)
+		snd_soc_dapm_new_controls(&card->dapm, card->dapm_widgets,
+					  card->num_dapm_widgets);
+	if (card->dapm_routes)
+		snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
+					card->num_dapm_routes);
+
+#ifdef CONFIG_DEBUG_FS
+	card->dapm.debugfs_dapm = debugfs_create_dir("dapm",
+						     card->debugfs_card_root);
+	if (!card->dapm.debugfs_dapm)
+		printk(KERN_WARNING
+		       "Failed to create card DAPM debugfs directory\n");
+
+	snd_soc_dapm_debugfs_init(&card->dapm);
+#endif
+
 	snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
 		 "%s",  card->name);
 	snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
 		 "%s", card->name);
 
+	if (card->late_probe) {
+		ret = card->late_probe(card);
+		if (ret < 0) {
+			dev_err(card->dev, "%s late_probe() failed: %d\n",
+				card->name, ret);
+			goto probe_aux_dev_err;
+		}
+	}
+
 	ret = snd_card_register(card->snd_card);
 	if (ret < 0) {
 		printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
@@ -1848,7 +1952,7 @@ probe_dai_err:
 
 card_probe_error:
 	if (card->remove)
-		card->remove(pdev);
+		card->remove(card);
 
 	snd_card_free(card->snd_card);
 
@@ -1872,16 +1976,15 @@ static int soc_probe(struct platform_device *pdev)
 	struct snd_soc_card *card = platform_get_drvdata(pdev);
 	int ret = 0;
 
+	/*
+	 * no card, so machine driver should be registering card
+	 * we should not be here in that case so ret error
+	 */
+	if (!card)
+		return -EINVAL;
+
 	/* Bodge while we unpick instantiation */
 	card->dev = &pdev->dev;
-	INIT_LIST_HEAD(&card->dai_dev_list);
-	INIT_LIST_HEAD(&card->codec_dev_list);
-	INIT_LIST_HEAD(&card->platform_dev_list);
-	INIT_LIST_HEAD(&card->widgets);
-	INIT_LIST_HEAD(&card->paths);
-	INIT_LIST_HEAD(&card->dapm_list);
-
-	soc_init_card_debugfs(card);
 
 	ret = snd_soc_register_card(card);
 	if (ret != 0) {
@@ -1892,45 +1995,48 @@ static int soc_probe(struct platform_device *pdev)
 	return 0;
 }
 
-/* removes a socdev */
-static int soc_remove(struct platform_device *pdev)
+static int soc_cleanup_card_resources(struct snd_soc_card *card)
 {
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
 	int i;
 
-		if (card->instantiated) {
+	/* make sure any delayed work runs */
+	for (i = 0; i < card->num_rtd; i++) {
+		struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
+		flush_delayed_work_sync(&rtd->delayed_work);
+	}
 
-		/* make sure any delayed work runs */
-		for (i = 0; i < card->num_rtd; i++) {
-			struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
-			flush_delayed_work_sync(&rtd->delayed_work);
-		}
+	/* remove auxiliary devices */
+	for (i = 0; i < card->num_aux_devs; i++)
+		soc_remove_aux_dev(card, i);
 
-		/* remove auxiliary devices */
-		for (i = 0; i < card->num_aux_devs; i++)
-			soc_remove_aux_dev(card, i);
+	/* remove and free each DAI */
+	for (i = 0; i < card->num_rtd; i++)
+		soc_remove_dai_link(card, i);
 
-		/* remove and free each DAI */
-		for (i = 0; i < card->num_rtd; i++)
-			soc_remove_dai_link(card, i);
+	soc_cleanup_card_debugfs(card);
 
-		soc_cleanup_card_debugfs(card);
+	/* remove the card */
+	if (card->remove)
+		card->remove(card);
+
+	kfree(card->rtd);
+	snd_card_free(card->snd_card);
+	return 0;
 
-		/* remove the card */
-		if (card->remove)
-			card->remove(pdev);
+}
+
+/* removes a socdev */
+static int soc_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
 
-		kfree(card->rtd);
-		snd_card_free(card->snd_card);
-	}
 	snd_soc_unregister_card(card);
 	return 0;
 }
 
-static int soc_poweroff(struct device *dev)
+int snd_soc_poweroff(struct device *dev)
 {
-	struct platform_device *pdev = to_platform_device(dev);
-	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct snd_soc_card *card = dev_get_drvdata(dev);
 	int i;
 
 	if (!card->instantiated)
@@ -1947,11 +2053,12 @@ static int soc_poweroff(struct device *dev)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_poweroff);
 
-static const struct dev_pm_ops soc_pm_ops = {
-	.suspend = soc_suspend,
-	.resume = soc_resume,
-	.poweroff = soc_poweroff,
+const struct dev_pm_ops snd_soc_pm_ops = {
+	.suspend = snd_soc_suspend,
+	.resume = snd_soc_resume,
+	.poweroff = snd_soc_poweroff,
 };
 
 /* ASoC platform driver */
@@ -1959,7 +2066,7 @@ static struct platform_driver soc_driver = {
 	.driver		= {
 		.name		= "soc-audio",
 		.owner		= THIS_MODULE,
-		.pm		= &soc_pm_ops,
+		.pm		= &snd_soc_pm_ops,
 	},
 	.probe		= soc_probe,
 	.remove		= soc_remove,
@@ -2029,10 +2136,11 @@ static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
  *
  * Boolean function indiciating if a CODEC register is volatile.
  */
-int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
+int snd_soc_codec_volatile_register(struct snd_soc_codec *codec,
+				    unsigned int reg)
 {
-	if (codec->driver->volatile_register)
-		return codec->driver->volatile_register(reg);
+	if (codec->volatile_register)
+		return codec->volatile_register(codec, reg);
 	else
 		return 0;
 }
@@ -2129,19 +2237,27 @@ EXPORT_SYMBOL_GPL(snd_soc_write);
  *
  * Writes new register value.
  *
- * Returns 1 for change else 0.
+ * Returns 1 for change, 0 for no change, or negative error code.
  */
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
 				unsigned int mask, unsigned int value)
 {
 	int change;
 	unsigned int old, new;
+	int ret;
 
-	old = snd_soc_read(codec, reg);
+	ret = snd_soc_read(codec, reg);
+	if (ret < 0)
+		return ret;
+
+	old = ret;
 	new = (old & ~mask) | value;
 	change = old != new;
-	if (change)
-		snd_soc_write(codec, reg, new);
+	if (change) {
+		ret = snd_soc_write(codec, reg, new);
+		if (ret < 0)
+			return ret;
+	}
 
 	return change;
 }
@@ -2226,22 +2342,45 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
  * @_template: control template
  * @data: control private data
  * @long_name: control long name
+ * @prefix: control name prefix
  *
  * Create a new mixer control from a template control.
  *
  * Returns 0 for success, else error.
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
-	void *data, char *long_name)
+				  void *data, char *long_name,
+				  const char *prefix)
 {
 	struct snd_kcontrol_new template;
+	struct snd_kcontrol *kcontrol;
+	char *name = NULL;
+	int name_len;
 
 	memcpy(&template, _template, sizeof(template));
-	if (long_name)
-		template.name = long_name;
 	template.index = 0;
 
-	return snd_ctl_new1(&template, data);
+	if (!long_name)
+		long_name = template.name;
+
+	if (prefix) {
+		name_len = strlen(long_name) + strlen(prefix) + 2;
+		name = kmalloc(name_len, GFP_ATOMIC);
+		if (!name)
+			return NULL;
+
+		snprintf(name, name_len, "%s %s", prefix, long_name);
+
+		template.name = name;
+	} else {
+		template.name = long_name;
+	}
+
+	kcontrol = snd_ctl_new1(&template, data);
+
+	kfree(name);
+
+	return kcontrol;
 }
 EXPORT_SYMBOL_GPL(snd_soc_cnew);
 
@@ -2260,22 +2399,16 @@ int snd_soc_add_controls(struct snd_soc_codec *codec,
 	const struct snd_kcontrol_new *controls, int num_controls)
 {
 	struct snd_card *card = codec->card->snd_card;
-	char prefixed_name[44], *name;
 	int err, i;
 
 	for (i = 0; i < num_controls; i++) {
 		const struct snd_kcontrol_new *control = &controls[i];
-		if (codec->name_prefix) {
-			snprintf(prefixed_name, sizeof(prefixed_name), "%s %s",
-				 codec->name_prefix, control->name);
-			name = prefixed_name;
-		} else {
-			name = control->name;
-		}
-		err = snd_ctl_add(card, snd_soc_cnew(control, codec, name));
+		err = snd_ctl_add(card, snd_soc_cnew(control, codec,
+						     control->name,
+						     codec->name_prefix));
 		if (err < 0) {
 			dev_err(codec->dev, "%s: Failed to add %s: %d\n",
-				codec->name, name, err);
+				codec->name, control->name, err);
 			return err;
 		}
 	}
@@ -2956,12 +3089,34 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
 {
 	if (dai->driver && dai->driver->ops->set_sysclk)
 		return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
+	else if (dai->codec && dai->codec->driver->set_sysclk)
+		return dai->codec->driver->set_sysclk(dai->codec, clk_id,
+						      freq, dir);
 	else
 		return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
 
 /**
+ * snd_soc_codec_set_sysclk - configure CODEC system or master clock.
+ * @codec: CODEC
+ * @clk_id: DAI specific clock ID
+ * @freq: new clock frequency in Hz
+ * @dir: new clock direction - input/output.
+ *
+ * Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
+ */
+int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+	unsigned int freq, int dir)
+{
+	if (codec->driver->set_sysclk)
+		return codec->driver->set_sysclk(codec, clk_id, freq, dir);
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_set_sysclk);
+
+/**
  * snd_soc_dai_set_clkdiv - configure DAI clock dividers.
  * @dai: DAI
  * @div_id: DAI specific clock divider ID
@@ -2997,11 +3152,35 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
 	if (dai->driver && dai->driver->ops->set_pll)
 		return dai->driver->ops->set_pll(dai, pll_id, source,
 					 freq_in, freq_out);
+	else if (dai->codec && dai->codec->driver->set_pll)
+		return dai->codec->driver->set_pll(dai->codec, pll_id, source,
+						   freq_in, freq_out);
 	else
 		return -EINVAL;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
 
+/*
+ * snd_soc_codec_set_pll - configure codec PLL.
+ * @codec: CODEC
+ * @pll_id: DAI specific PLL ID
+ * @source: DAI specific source for the PLL
+ * @freq_in: PLL input clock frequency in Hz
+ * @freq_out: requested PLL output clock frequency in Hz
+ *
+ * Configures and enables PLL to generate output clock based on input clock.
+ */
+int snd_soc_codec_set_pll(struct snd_soc_codec *codec, int pll_id, int source,
+			  unsigned int freq_in, unsigned int freq_out)
+{
+	if (codec->driver->set_pll)
+		return codec->driver->set_pll(codec, pll_id, source,
+					      freq_in, freq_out);
+	else
+		return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
+
 /**
  * snd_soc_dai_set_fmt - configure DAI hardware audio format.
  * @dai: DAI
@@ -3101,17 +3280,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
  *
  * @card: Card to register
  *
- * Note that currently this is an internal only function: it will be
- * exposed to machine drivers after further backporting of ASoC v2
- * registration APIs.
  */
-static int snd_soc_register_card(struct snd_soc_card *card)
+int snd_soc_register_card(struct snd_soc_card *card)
 {
 	int i;
 
 	if (!card->name || !card->dev)
 		return -EINVAL;
 
+	snd_soc_initialize_card_lists(card);
+
+	soc_init_card_debugfs(card);
+
 	card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *
 			    (card->num_links + card->num_aux_devs),
 			    GFP_KERNEL);
@@ -3135,18 +3315,18 @@ static int snd_soc_register_card(struct snd_soc_card *card)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_register_card);
 
 /**
  * snd_soc_unregister_card - Unregister a card with the ASoC core
  *
  * @card: Card to unregister
  *
- * Note that currently this is an internal only function: it will be
- * exposed to machine drivers after further backporting of ASoC v2
- * registration APIs.
  */
-static int snd_soc_unregister_card(struct snd_soc_card *card)
+int snd_soc_unregister_card(struct snd_soc_card *card)
 {
+	if (card->instantiated)
+		soc_cleanup_card_resources(card);
 	mutex_lock(&client_mutex);
 	list_del(&card->list);
 	mutex_unlock(&client_mutex);
@@ -3154,6 +3334,7 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_soc_unregister_card);
 
 /*
  * Simplify DAI link configuration by removing ".-1" from device names
@@ -3483,9 +3664,12 @@ int snd_soc_register_codec(struct device *dev,
 
 	codec->write = codec_drv->write;
 	codec->read = codec_drv->read;
+	codec->volatile_register = codec_drv->volatile_register;
+	codec->readable_register = codec_drv->readable_register;
 	codec->dapm.bias_level = SND_SOC_BIAS_OFF;
 	codec->dapm.dev = dev;
 	codec->dapm.codec = codec;
+	codec->dapm.seq_notifier = codec_drv->seq_notifier;
 	codec->dev = dev;
 	codec->driver = codec_drv;
 	codec->num_dai = num_dai;
@@ -3494,20 +3678,30 @@ int snd_soc_register_codec(struct device *dev,
 	/* allocate CODEC register cache */
 	if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
 		reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
+		codec->reg_size = reg_size;
 		/* it is necessary to make a copy of the default register cache
 		 * because in the case of using a compression type that requires
 		 * the default register cache to be marked as __devinitconst the
 		 * kernel might have freed the array by the time we initialize
 		 * the cache.
 		 */
-		codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
-					      reg_size, GFP_KERNEL);
-		if (!codec->reg_def_copy) {
-			ret = -ENOMEM;
-			goto fail;
+		if (codec_drv->reg_cache_default) {
+			codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default,
+						      reg_size, GFP_KERNEL);
+			if (!codec->reg_def_copy) {
+				ret = -ENOMEM;
+				goto fail;
+			}
 		}
 	}
 
+	if (codec_drv->reg_access_size && codec_drv->reg_access_default) {
+		if (!codec->volatile_register)
+			codec->volatile_register = snd_soc_default_volatile_register;
+		if (!codec->readable_register)
+			codec->readable_register = snd_soc_default_readable_register;
+	}
+
 	for (i = 0; i < num_dai; i++) {
 		fixup_codec_formats(&dai_drv[i].playback);
 		fixup_codec_formats(&dai_drv[i].capture);
@@ -3574,22 +3768,22 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
 static int __init snd_soc_init(void)
 {
 #ifdef CONFIG_DEBUG_FS
-	debugfs_root = debugfs_create_dir("asoc", NULL);
-	if (IS_ERR(debugfs_root) || !debugfs_root) {
+	snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
+	if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
 		printk(KERN_WARNING
 		       "ASoC: Failed to create debugfs directory\n");
-		debugfs_root = NULL;
+		snd_soc_debugfs_root = NULL;
 	}
 
-	if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL,
+	if (!debugfs_create_file("codecs", 0444, snd_soc_debugfs_root, NULL,
 				 &codec_list_fops))
 		pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
 
-	if (!debugfs_create_file("dais", 0444, debugfs_root, NULL,
+	if (!debugfs_create_file("dais", 0444, snd_soc_debugfs_root, NULL,
 				 &dai_list_fops))
 		pr_warn("ASoC: Failed to create DAI list debugfs file\n");
 
-	if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL,
+	if (!debugfs_create_file("platforms", 0444, snd_soc_debugfs_root, NULL,
 				 &platform_list_fops))
 		pr_warn("ASoC: Failed to create platform list debugfs file\n");
 #endif
@@ -3601,7 +3795,7 @@ module_init(snd_soc_init);
 static void __exit snd_soc_exit(void)
 {
 #ifdef CONFIG_DEBUG_FS
-	debugfs_remove_recursive(debugfs_root);
+	debugfs_remove_recursive(snd_soc_debugfs_root);
 #endif
 	platform_driver_unregister(&soc_driver);
 }
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1790f83..81c4052 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
+#include <linux/async.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/bitops.h>
@@ -125,17 +126,17 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
 
 /**
  * snd_soc_dapm_set_bias_level - set the bias level for the system
- * @card: audio device
+ * @dapm: DAPM context
  * @level: level to configure
  *
  * Configure the bias (power) levels for the SoC audio device.
  *
  * Returns 0 for success else error.
  */
-static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card,
-				       struct snd_soc_dapm_context *dapm,
+static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
 				       enum snd_soc_bias_level level)
 {
+	struct snd_soc_card *card = dapm->card;
 	int ret = 0;
 
 	switch (level) {
@@ -365,9 +366,20 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
 	struct snd_soc_dapm_widget *w)
 {
 	int i, ret = 0;
-	size_t name_len;
+	size_t name_len, prefix_len;
 	struct snd_soc_dapm_path *path;
-	struct snd_card *card = dapm->codec->card->snd_card;
+	struct snd_card *card = dapm->card->snd_card;
+	const char *prefix;
+
+	if (dapm->codec)
+		prefix = dapm->codec->name_prefix;
+	else
+		prefix = NULL;
+
+	if (prefix)
+		prefix_len = strlen(prefix) + 1;
+	else
+		prefix_len = 0;
 
 	/* add kcontrol */
 	for (i = 0; i < w->num_kcontrols; i++) {
@@ -396,8 +408,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
 
 			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(path->long_name, name_len, "%s %s",
-					 w->name, w->kcontrols[i].name);
+					 w->name + prefix_len,
+					 w->kcontrols[i].name);
 				break;
 			case snd_soc_dapm_mixer_named_ctl:
 				snprintf(path->long_name, name_len, "%s",
@@ -408,7 +427,7 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
 			path->long_name[name_len - 1] = '\0';
 
 			path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
-				path->long_name);
+						      path->long_name, prefix);
 			ret = snd_ctl_add(card, path->kcontrol);
 			if (ret < 0) {
 				dev_err(dapm->dev,
@@ -429,7 +448,9 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
 {
 	struct snd_soc_dapm_path *path = NULL;
 	struct snd_kcontrol *kcontrol;
-	struct snd_card *card = dapm->codec->card->snd_card;
+	struct snd_card *card = dapm->card->snd_card;
+	const char *prefix;
+	size_t prefix_len;
 	int ret = 0;
 
 	if (!w->num_kcontrols) {
@@ -437,7 +458,22 @@ static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
 		return -EINVAL;
 	}
 
-	kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
+	if (dapm->codec)
+		prefix = dapm->codec->name_prefix;
+	else
+		prefix = NULL;
+
+	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->kcontrols[0], w, w->name + prefix_len,
+				prefix);
 	ret = snd_ctl_add(card, kcontrol);
 
 	if (ret < 0)
@@ -479,7 +515,7 @@ static inline void dapm_clear_walk(struct snd_soc_dapm_context *dapm)
  */
 static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
 {
-	int level = snd_power_get_state(widget->dapm->codec->card->snd_card);
+	int level = snd_power_get_state(widget->dapm->card->snd_card);
 
 	switch (level) {
 	case SNDRV_CTL_POWER_D3hot:
@@ -734,10 +770,23 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
 
 static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
 			    struct snd_soc_dapm_widget *b,
-			    int sort[])
+			    bool power_up)
 {
+	int *sort;
+
+	if (power_up)
+		sort = dapm_up_seq;
+	else
+		sort = dapm_down_seq;
+
 	if (sort[a->id] != sort[b->id])
 		return sort[a->id] - sort[b->id];
+	if (a->subseq != b->subseq) {
+		if (power_up)
+			return a->subseq - b->subseq;
+		else
+			return b->subseq - a->subseq;
+	}
 	if (a->reg != b->reg)
 		return a->reg - b->reg;
 	if (a->dapm != b->dapm)
@@ -749,12 +798,12 @@ static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
 /* Insert a widget in order into a DAPM power sequence. */
 static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
 			    struct list_head *list,
-			    int sort[])
+			    bool power_up)
 {
 	struct snd_soc_dapm_widget *w;
 
 	list_for_each_entry(w, list, power_list)
-		if (dapm_seq_compare(new_widget, w, sort) < 0) {
+		if (dapm_seq_compare(new_widget, w, power_up) < 0) {
 			list_add_tail(&new_widget->power_list, &w->power_list);
 			return;
 		}
@@ -865,26 +914,42 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
  * handled.
  */
 static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
-			 struct list_head *list, int event, int sort[])
+			 struct list_head *list, int event, bool power_up)
 {
 	struct snd_soc_dapm_widget *w, *n;
 	LIST_HEAD(pending);
 	int cur_sort = -1;
+	int cur_subseq = -1;
 	int cur_reg = SND_SOC_NOPM;
 	struct snd_soc_dapm_context *cur_dapm = NULL;
-	int ret;
+	int ret, i;
+	int *sort;
+
+	if (power_up)
+		sort = dapm_up_seq;
+	else
+		sort = dapm_down_seq;
 
 	list_for_each_entry_safe(w, n, list, power_list) {
 		ret = 0;
 
 		/* Do we need to apply any queued changes? */
 		if (sort[w->id] != cur_sort || w->reg != cur_reg ||
-		    w->dapm != cur_dapm) {
+		    w->dapm != cur_dapm || w->subseq != cur_subseq) {
 			if (!list_empty(&pending))
 				dapm_seq_run_coalesced(cur_dapm, &pending);
 
+			if (cur_dapm && cur_dapm->seq_notifier) {
+				for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
+					if (sort[i] == cur_sort)
+						cur_dapm->seq_notifier(cur_dapm,
+								       i,
+								       cur_subseq);
+			}
+
 			INIT_LIST_HEAD(&pending);
 			cur_sort = -1;
+			cur_subseq = -1;
 			cur_reg = SND_SOC_NOPM;
 			cur_dapm = NULL;
 		}
@@ -929,6 +994,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 		default:
 			/* Queue it up for application */
 			cur_sort = sort[w->id];
+			cur_subseq = w->subseq;
 			cur_reg = w->reg;
 			cur_dapm = w->dapm;
 			list_move(&w->power_list, &pending);
@@ -942,6 +1008,13 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
 
 	if (!list_empty(&pending))
 		dapm_seq_run_coalesced(cur_dapm, &pending);
+
+	if (cur_dapm && cur_dapm->seq_notifier) {
+		for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++)
+			if (sort[i] == cur_sort)
+				cur_dapm->seq_notifier(cur_dapm,
+						       i, cur_subseq);
+	}
 }
 
 static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
@@ -977,7 +1050,62 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
 	}
 }
 
+/* Async callback run prior to DAPM sequences - brings to _PREPARE if
+ * they're changing state.
+ */
+static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
+{
+	struct snd_soc_dapm_context *d = data;
+	int ret;
 
+	if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) {
+		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
+		if (ret != 0)
+			dev_err(d->dev,
+				"Failed to turn on bias: %d\n", ret);
+	}
+
+	/* If we're changing to all on or all off then prepare */
+	if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) ||
+	    (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) {
+		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_PREPARE);
+		if (ret != 0)
+			dev_err(d->dev,
+				"Failed to prepare bias: %d\n", ret);
+	}
+}
+
+/* Async callback run prior to DAPM sequences - brings to their final
+ * state.
+ */
+static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
+{
+	struct snd_soc_dapm_context *d = data;
+	int ret;
+
+	/* If we just powered the last thing off drop to standby bias */
+	if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) {
+		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
+		if (ret != 0)
+			dev_err(d->dev, "Failed to apply standby bias: %d\n",
+				ret);
+	}
+
+	/* If we're in standby and can support bias off then do that */
+	if (d->bias_level == SND_SOC_BIAS_STANDBY && d->idle_bias_off) {
+		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
+		if (ret != 0)
+			dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
+	}
+
+	/* If we just powered up then move to active bias */
+	if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) {
+		ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_ON);
+		if (ret != 0)
+			dev_err(d->dev, "Failed to apply active bias: %d\n",
+				ret);
+	}
+}
 
 /*
  * Scan each dapm widget for complete audio path.
@@ -990,12 +1118,12 @@ static void dapm_widget_update(struct snd_soc_dapm_context *dapm)
  */
 static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 {
-	struct snd_soc_card *card = dapm->codec->card;
+	struct snd_soc_card *card = dapm->card;
 	struct snd_soc_dapm_widget *w;
 	struct snd_soc_dapm_context *d;
 	LIST_HEAD(up_list);
 	LIST_HEAD(down_list);
-	int ret = 0;
+	LIST_HEAD(async_domain);
 	int power;
 
 	trace_snd_soc_dapm_start(card);
@@ -1010,10 +1138,10 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 	list_for_each_entry(w, &card->widgets, list) {
 		switch (w->id) {
 		case snd_soc_dapm_pre:
-			dapm_seq_insert(w, &down_list, dapm_down_seq);
+			dapm_seq_insert(w, &down_list, false);
 			break;
 		case snd_soc_dapm_post:
-			dapm_seq_insert(w, &up_list, dapm_up_seq);
+			dapm_seq_insert(w, &up_list, true);
 			break;
 
 		default:
@@ -1033,9 +1161,9 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 			trace_snd_soc_dapm_widget_power(w, power);
 
 			if (power)
-				dapm_seq_insert(w, &up_list, dapm_up_seq);
+				dapm_seq_insert(w, &up_list, true);
 			else
-				dapm_seq_insert(w, &down_list, dapm_down_seq);
+				dapm_seq_insert(w, &down_list, false);
 
 			w->power = power;
 			break;
@@ -1073,65 +1201,25 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
 		}
 	}
 
-	list_for_each_entry(d, &dapm->card->dapm_list, list) {
-		if (d->dev_power && d->bias_level == SND_SOC_BIAS_OFF) {
-			ret = snd_soc_dapm_set_bias_level(card, d,
-							  SND_SOC_BIAS_STANDBY);
-			if (ret != 0)
-				dev_err(d->dev,
-					"Failed to turn on bias: %d\n", ret);
-		}
-
-		/* If we're changing to all on or all off then prepare */
-		if ((d->dev_power && d->bias_level == SND_SOC_BIAS_STANDBY) ||
-		    (!d->dev_power && d->bias_level == SND_SOC_BIAS_ON)) {
-			ret = snd_soc_dapm_set_bias_level(card, d,
-							  SND_SOC_BIAS_PREPARE);
-			if (ret != 0)
-				dev_err(d->dev,
-					"Failed to prepare bias: %d\n", ret);
-		}
-	}
+	/* Run all the bias changes in parallel */
+	list_for_each_entry(d, &dapm->card->dapm_list, list)
+		async_schedule_domain(dapm_pre_sequence_async, d,
+					&async_domain);
+	async_synchronize_full_domain(&async_domain);
 
 	/* Power down widgets first; try to avoid amplifying pops. */
-	dapm_seq_run(dapm, &down_list, event, dapm_down_seq);
+	dapm_seq_run(dapm, &down_list, event, false);
 
 	dapm_widget_update(dapm);
 
 	/* Now power up. */
-	dapm_seq_run(dapm, &up_list, event, dapm_up_seq);
-
-	list_for_each_entry(d, &dapm->card->dapm_list, list) {
-		/* If we just powered the last thing off drop to standby bias */
-		if (d->bias_level == SND_SOC_BIAS_PREPARE && !d->dev_power) {
-			ret = snd_soc_dapm_set_bias_level(card, d,
-							  SND_SOC_BIAS_STANDBY);
-			if (ret != 0)
-				dev_err(d->dev,
-					"Failed to apply standby bias: %d\n",
-					ret);
-		}
+	dapm_seq_run(dapm, &up_list, event, true);
 
-		/* If we're in standby and can support bias off then do that */
-		if (d->bias_level == SND_SOC_BIAS_STANDBY &&
-		    d->idle_bias_off) {
-			ret = snd_soc_dapm_set_bias_level(card, d,
-							  SND_SOC_BIAS_OFF);
-			if (ret != 0)
-				dev_err(d->dev,
-					"Failed to turn off bias: %d\n", ret);
-		}
-
-		/* If we just powered up then move to active bias */
-		if (d->bias_level == SND_SOC_BIAS_PREPARE && d->dev_power) {
-			ret = snd_soc_dapm_set_bias_level(card, d,
-							  SND_SOC_BIAS_ON);
-			if (ret != 0)
-				dev_err(d->dev,
-					"Failed to apply active bias: %d\n",
-					ret);
-		}
-	}
+	/* Run all the bias changes in parallel */
+	list_for_each_entry(d, &dapm->card->dapm_list, list)
+		async_schedule_domain(dapm_post_sequence_async, d,
+					&async_domain);
+	async_synchronize_full_domain(&async_domain);
 
 	pop_dbg(dapm->dev, card->pop_time,
 		"DAPM sequencing finished, waiting %dms\n", card->pop_time);
@@ -1189,7 +1277,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 
 		if (p->connect)
 			ret += snprintf(buf + ret, PAGE_SIZE - ret,
-					" in  %s %s\n",
+					" in  \"%s\" \"%s\"\n",
 					p->name ? p->name : "static",
 					p->source->name);
 	}
@@ -1199,7 +1287,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
 
 		if (p->connect)
 			ret += snprintf(buf + ret, PAGE_SIZE - ret,
-					" out %s %s\n",
+					" out \"%s\" \"%s\"\n",
 					p->name ? p->name : "static",
 					p->sink->name);
 	}
@@ -1464,7 +1552,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
 	char prefixed_source[80];
 	int ret = 0;
 
-	if (dapm->codec->name_prefix) {
+	if (dapm->codec && dapm->codec->name_prefix) {
 		snprintf(prefixed_sink, sizeof(prefixed_sink), "%s %s",
 			 dapm->codec->name_prefix, route->sink);
 		sink = prefixed_sink;
@@ -2114,14 +2202,14 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
 		return -ENOMEM;
 
 	name_len = strlen(widget->name) + 1;
-	if (dapm->codec->name_prefix)
+	if (dapm->codec && dapm->codec->name_prefix)
 		name_len += 1 + strlen(dapm->codec->name_prefix);
 	w->name = kmalloc(name_len, GFP_KERNEL);
 	if (w->name == NULL) {
 		kfree(w);
 		return -ENOMEM;
 	}
-	if (dapm->codec->name_prefix)
+	if (dapm->codec && dapm->codec->name_prefix)
 		snprintf(w->name, name_len, "%s %s",
 			dapm->codec->name_prefix, widget->name);
 	else
@@ -2226,7 +2314,6 @@ int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
 	mutex_unlock(&codec->mutex);
 	return 0;
 }
-EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
 
 /**
  * snd_soc_dapm_enable_pin - enable pin.
@@ -2393,7 +2480,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
 		if (w->dapm != dapm)
 			continue;
 		if (w->power) {
-			dapm_seq_insert(w, &down_list, dapm_down_seq);
+			dapm_seq_insert(w, &down_list, false);
 			w->power = 0;
 			powerdown = 1;
 		}
@@ -2403,9 +2490,9 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
 	 * standby.
 	 */
 	if (powerdown) {
-		snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_PREPARE);
-		dapm_seq_run(dapm, &down_list, 0, dapm_down_seq);
-		snd_soc_dapm_set_bias_level(NULL, dapm, SND_SOC_BIAS_STANDBY);
+		snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE);
+		dapm_seq_run(dapm, &down_list, 0, false);
+		snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY);
 	}
 }
 
@@ -2418,7 +2505,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
 
 	list_for_each_entry(codec, &card->codec_dev_list, list) {
 		soc_dapm_shutdown_codec(&codec->dapm);
-		snd_soc_dapm_set_bias_level(card, &codec->dapm, SND_SOC_BIAS_OFF);
+		snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF);
 	}
 }
 
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index ac5a5bc..fcab80b 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -37,6 +37,7 @@ int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
 {
 	jack->codec = codec;
 	INIT_LIST_HEAD(&jack->pins);
+	INIT_LIST_HEAD(&jack->jack_zones);
 	BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
 
 	return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);
@@ -100,7 +101,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
 	}
 
 	/* Report before the DAPM sync to help users updating micbias status */
-	blocking_notifier_call_chain(&jack->notifier, status, NULL);
+	blocking_notifier_call_chain(&jack->notifier, status, jack);
 
 	snd_soc_dapm_sync(dapm);
 
@@ -112,6 +113,51 @@ out:
 EXPORT_SYMBOL_GPL(snd_soc_jack_report);
 
 /**
+ * snd_soc_jack_add_zones - Associate voltage zones with jack
+ *
+ * @jack:  ASoC jack
+ * @count: Number of zones
+ * @zone:  Array of zones
+ *
+ * After this function has been called the zones specified in the
+ * array will be associated with the jack.
+ */
+int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count,
+			  struct snd_soc_jack_zone *zones)
+{
+	int i;
+
+	for (i = 0; i < count; i++) {
+		INIT_LIST_HEAD(&zones[i].list);
+		list_add(&(zones[i].list), &jack->jack_zones);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones);
+
+/**
+ * snd_soc_jack_get_type - Based on the mic bias value, this function returns
+ * the type of jack from the zones delcared in the jack type
+ *
+ * @micbias_voltage:  mic bias voltage at adc channel when jack is plugged in
+ *
+ * Based on the mic bias value passed, this function helps identify
+ * the type of jack from the already delcared jack zones
+ */
+int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage)
+{
+	struct snd_soc_jack_zone *zone;
+
+	list_for_each_entry(zone, &jack->jack_zones, list) {
+		if (micbias_voltage >= zone->min_mv &&
+			micbias_voltage < zone->max_mv)
+				return zone->jack_type;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_jack_get_type);
+
+/**
  * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack
  *
  * @jack:  ASoC jack
@@ -194,7 +240,7 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
 	int enable;
 	int report;
 
-	enable = gpio_get_value(gpio->gpio);
+	enable = gpio_get_value_cansleep(gpio->gpio);
 	if (gpio->invert)
 		enable = !enable;
 
@@ -284,6 +330,14 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
 		if (ret)
 			goto err;
 
+		if (gpios[i].wake) {
+			ret = set_irq_wake(gpio_to_irq(gpios[i].gpio), 1);
+			if (ret != 0)
+				printk(KERN_ERR
+				  "Failed to mark GPIO %d as wake source: %d\n",
+					gpios[i].gpio, ret);
+		}
+
 #ifdef CONFIG_GPIO_SYSFS
 		/* Expose GPIO value over sysfs for diagnostic purposes */
 		gpio_export(gpios[i].gpio, false);
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index 1d07b93..3f45e6a 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -28,26 +28,9 @@ int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params)
 {
 	int sample_size;
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
-	case SNDRV_PCM_FORMAT_S16_BE:
-		sample_size = 16;
-		break;
-	case SNDRV_PCM_FORMAT_S20_3LE:
-	case SNDRV_PCM_FORMAT_S20_3BE:
-		sample_size = 20;
-		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
-	case SNDRV_PCM_FORMAT_S24_BE:
-		sample_size = 24;
-		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
-	case SNDRV_PCM_FORMAT_S32_BE:
-		sample_size = 32;
-		break;
-	default:
-		return -ENOTSUPP;
-	}
+	sample_size = snd_pcm_format_width(params_format(params));
+	if (sample_size < 0)
+		return sample_size;
 
 	return snd_soc_calc_frame_size(sample_size, params_channels(params),
 				       1);
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
new file mode 100644
index 0000000..66b504f
--- /dev/null
+++ b/sound/soc/tegra/Kconfig
@@ -0,0 +1,26 @@
+config SND_TEGRA_SOC
+	tristate "SoC Audio for the Tegra System-on-Chip"
+	depends on ARCH_TEGRA && TEGRA_SYSTEM_DMA
+	default m
+	help
+	  Say Y or M here if you want support for SoC audio on Tegra.
+
+config SND_TEGRA_SOC_I2S
+	tristate
+	depends on SND_TEGRA_SOC
+	default m
+	help
+	  Say Y or M if you want to add support for codecs attached to the
+	  Tegra I2S interface. You will also need to select the individual
+	  machine drivers to support below.
+
+config SND_TEGRA_SOC_HARMONY
+	tristate "SoC Audio support for Tegra Harmony reference board"
+	depends on SND_TEGRA_SOC && MACH_HARMONY && I2C
+	default m
+	select SND_TEGRA_SOC_I2S
+	select SND_SOC_WM8903
+	help
+	  Say Y or M here if you want to add support for SoC audio on the
+	  Tegra Harmony reference board.
+
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
new file mode 100644
index 0000000..fd183d3
--- /dev/null
+++ b/sound/soc/tegra/Makefile
@@ -0,0 +1,15 @@
+# Tegra platform Support
+snd-soc-tegra-das-objs := tegra_das.o
+snd-soc-tegra-pcm-objs := tegra_pcm.o
+snd-soc-tegra-i2s-objs := tegra_i2s.o
+snd-soc-tegra-utils-objs += tegra_asoc_utils.o
+
+obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-utils.o
+obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-das.o
+obj-$(CONFIG_SND_TEGRA_SOC) += snd-soc-tegra-pcm.o
+obj-$(CONFIG_SND_TEGRA_SOC_I2S) += snd-soc-tegra-i2s.o
+
+# Tegra machine Support
+snd-soc-tegra-harmony-objs := harmony.o
+
+obj-$(CONFIG_SND_TEGRA_SOC_HARMONY) += snd-soc-tegra-harmony.o
diff --git a/sound/soc/tegra/harmony.c b/sound/soc/tegra/harmony.c
new file mode 100644
index 0000000..8585957
--- /dev/null
+++ b/sound/soc/tegra/harmony.c
@@ -0,0 +1,393 @@
+/*
+ * harmony.c - Harmony machine ASoC driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010-2011 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * (c) 2009, 2010 Nvidia Graphics Pvt. Ltd.
+ *
+ * Copyright 2007 Wolfson Microelectronics PLC.
+ * Author: Graeme Gregory
+ *         graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have 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 <asm/mach-types.h>
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+#include <mach/harmony_audio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "../codecs/wm8903.h"
+
+#include "tegra_das.h"
+#include "tegra_i2s.h"
+#include "tegra_pcm.h"
+#include "tegra_asoc_utils.h"
+
+#define DRV_NAME "tegra-snd-harmony"
+
+#define GPIO_SPKR_EN    BIT(0)
+#define GPIO_INT_MIC_EN BIT(1)
+#define GPIO_EXT_MIC_EN BIT(2)
+
+struct tegra_harmony {
+	struct tegra_asoc_utils_data util_data;
+	struct harmony_audio_platform_data *pdata;
+	int gpio_requested;
+};
+
+static int harmony_asoc_hw_params(struct snd_pcm_substream *substream,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_card *card = codec->card;
+	struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
+	int srate, mclk, mclk_change;
+	int err;
+
+	srate = params_rate(params);
+	switch (srate) {
+	case 64000:
+	case 88200:
+	case 96000:
+		mclk = 128 * srate;
+		break;
+	default:
+		mclk = 256 * srate;
+		break;
+	}
+	/* FIXME: Codec only requires >= 3MHz if OSR==0 */
+	while (mclk < 6000000)
+		mclk *= 2;
+
+	err = tegra_asoc_utils_set_rate(&harmony->util_data, srate, mclk,
+					&mclk_change);
+	if (err < 0) {
+		dev_err(card->dev, "Can't configure clocks\n");
+		return err;
+	}
+
+	err = snd_soc_dai_set_fmt(codec_dai,
+					SND_SOC_DAIFMT_I2S |
+					SND_SOC_DAIFMT_NB_NF |
+					SND_SOC_DAIFMT_CBS_CFS);
+	if (err < 0) {
+		dev_err(card->dev, "codec_dai fmt not set\n");
+		return err;
+	}
+
+	err = snd_soc_dai_set_fmt(cpu_dai,
+					SND_SOC_DAIFMT_I2S |
+					SND_SOC_DAIFMT_NB_NF |
+					SND_SOC_DAIFMT_CBS_CFS);
+	if (err < 0) {
+		dev_err(card->dev, "cpu_dai fmt not set\n");
+		return err;
+	}
+
+	if (mclk_change) {
+		err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+					     SND_SOC_CLOCK_IN);
+		if (err < 0) {
+			dev_err(card->dev, "codec_dai clock not set\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static struct snd_soc_ops harmony_asoc_ops = {
+	.hw_params = harmony_asoc_hw_params,
+};
+
+static struct snd_soc_jack harmony_hp_jack;
+
+static struct snd_soc_jack_pin harmony_hp_jack_pins[] = {
+	{
+		.pin = "Headphone Jack",
+		.mask = SND_JACK_HEADPHONE,
+	},
+};
+
+static struct snd_soc_jack_gpio harmony_hp_jack_gpios[] = {
+	{
+		.name = "headphone detect",
+		.report = SND_JACK_HEADPHONE,
+		.debounce_time = 150,
+		.invert = 1,
+	}
+};
+
+static struct snd_soc_jack harmony_mic_jack;
+
+static struct snd_soc_jack_pin harmony_mic_jack_pins[] = {
+	{
+		.pin = "Mic Jack",
+		.mask = SND_JACK_MICROPHONE,
+	},
+};
+
+static int harmony_event_int_spk(struct snd_soc_dapm_widget *w,
+					struct snd_kcontrol *k, int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct snd_soc_card *card = codec->card;
+	struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
+	struct harmony_audio_platform_data *pdata = harmony->pdata;
+
+	gpio_set_value_cansleep(pdata->gpio_spkr_en,
+				SND_SOC_DAPM_EVENT_ON(event));
+
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget harmony_dapm_widgets[] = {
+	SND_SOC_DAPM_SPK("Int Spk", harmony_event_int_spk),
+	SND_SOC_DAPM_HP("Headphone Jack", NULL),
+	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 Bias", NULL, "Mic Jack"},
+	{"IN1L", NULL, "Mic Bias"},
+};
+
+static const struct snd_kcontrol_new harmony_controls[] = {
+	SOC_DAPM_PIN_SWITCH("Int Spk"),
+};
+
+static int harmony_asoc_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_codec *codec = rtd->codec;
+	struct snd_soc_dapm_context *dapm = &codec->dapm;
+	struct snd_soc_card *card = codec->card;
+	struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
+	struct harmony_audio_platform_data *pdata = harmony->pdata;
+	int ret;
+
+	ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
+	if (ret) {
+		dev_err(card->dev, "cannot get spkr_en gpio\n");
+		return ret;
+	}
+	harmony->gpio_requested |= GPIO_SPKR_EN;
+
+	gpio_direction_output(pdata->gpio_spkr_en, 0);
+
+	ret = gpio_request(pdata->gpio_int_mic_en, "int_mic_en");
+	if (ret) {
+		dev_err(card->dev, "cannot get int_mic_en gpio\n");
+		return ret;
+	}
+	harmony->gpio_requested |= GPIO_INT_MIC_EN;
+
+	/* Disable int mic; enable signal is active-high */
+	gpio_direction_output(pdata->gpio_int_mic_en, 0);
+
+	ret = gpio_request(pdata->gpio_ext_mic_en, "ext_mic_en");
+	if (ret) {
+		dev_err(card->dev, "cannot get ext_mic_en gpio\n");
+		return ret;
+	}
+	harmony->gpio_requested |= GPIO_EXT_MIC_EN;
+
+	/* Enable ext mic; enable signal is active-low */
+	gpio_direction_output(pdata->gpio_ext_mic_en, 0);
+
+	ret = snd_soc_add_controls(codec, harmony_controls,
+				   ARRAY_SIZE(harmony_controls));
+	if (ret < 0)
+		return ret;
+
+	snd_soc_dapm_new_controls(dapm, harmony_dapm_widgets,
+					ARRAY_SIZE(harmony_dapm_widgets));
+
+	snd_soc_dapm_add_routes(dapm, harmony_audio_map,
+				ARRAY_SIZE(harmony_audio_map));
+
+	harmony_hp_jack_gpios[0].gpio = pdata->gpio_hp_det;
+	snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
+			 &harmony_hp_jack);
+	snd_soc_jack_add_pins(&harmony_hp_jack,
+			      ARRAY_SIZE(harmony_hp_jack_pins),
+			      harmony_hp_jack_pins);
+	snd_soc_jack_add_gpios(&harmony_hp_jack,
+			       ARRAY_SIZE(harmony_hp_jack_gpios),
+			       harmony_hp_jack_gpios);
+
+	snd_soc_jack_new(codec, "Mic Jack", SND_JACK_MICROPHONE,
+			 &harmony_mic_jack);
+	snd_soc_jack_add_pins(&harmony_mic_jack,
+			      ARRAY_SIZE(harmony_mic_jack_pins),
+			      harmony_mic_jack_pins);
+	wm8903_mic_detect(codec, &harmony_mic_jack, SND_JACK_MICROPHONE, 0);
+
+	snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
+
+	snd_soc_dapm_nc_pin(dapm, "IN3L");
+	snd_soc_dapm_nc_pin(dapm, "IN3R");
+	snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
+	snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
+
+	snd_soc_dapm_sync(dapm);
+
+	return 0;
+}
+
+static struct snd_soc_dai_link harmony_wm8903_dai = {
+	.name = "WM8903",
+	.stream_name = "WM8903 PCM",
+	.codec_name = "wm8903.0-001a",
+	.platform_name = "tegra-pcm-audio",
+	.cpu_dai_name = "tegra-i2s.0",
+	.codec_dai_name = "wm8903-hifi",
+	.init = harmony_asoc_init,
+	.ops = &harmony_asoc_ops,
+};
+
+static struct snd_soc_card snd_soc_harmony = {
+	.name = "tegra-harmony",
+	.dai_link = &harmony_wm8903_dai,
+	.num_links = 1,
+};
+
+static __devinit int tegra_snd_harmony_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = &snd_soc_harmony;
+	struct tegra_harmony *harmony;
+	struct harmony_audio_platform_data *pdata;
+	int ret;
+
+	if (!machine_is_harmony()) {
+		dev_err(&pdev->dev, "Not running on Tegra Harmony!\n");
+		return -ENODEV;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data supplied\n");
+		return -EINVAL;
+	}
+
+	harmony = kzalloc(sizeof(struct tegra_harmony), GFP_KERNEL);
+	if (!harmony) {
+		dev_err(&pdev->dev, "Can't allocate tegra_harmony\n");
+		return -ENOMEM;
+	}
+
+	harmony->pdata = pdata;
+
+	ret = tegra_asoc_utils_init(&harmony->util_data, &pdev->dev);
+	if (ret)
+		goto err_free_harmony;
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, harmony);
+
+	ret = snd_soc_register_card(card);
+	if (ret) {
+		dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+			ret);
+		goto err_clear_drvdata;
+	}
+
+	return 0;
+
+err_clear_drvdata:
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+	tegra_asoc_utils_fini(&harmony->util_data);
+err_free_harmony:
+	kfree(harmony);
+	return ret;
+}
+
+static int __devexit tegra_snd_harmony_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	struct tegra_harmony *harmony = snd_soc_card_get_drvdata(card);
+	struct harmony_audio_platform_data *pdata = harmony->pdata;
+
+	snd_soc_unregister_card(card);
+
+	snd_soc_card_set_drvdata(card, NULL);
+	platform_set_drvdata(pdev, NULL);
+	card->dev = NULL;
+
+	tegra_asoc_utils_fini(&harmony->util_data);
+
+	if (harmony->gpio_requested & GPIO_EXT_MIC_EN)
+		gpio_free(pdata->gpio_ext_mic_en);
+	if (harmony->gpio_requested & GPIO_INT_MIC_EN)
+		gpio_free(pdata->gpio_int_mic_en);
+	if (harmony->gpio_requested & GPIO_SPKR_EN)
+		gpio_free(pdata->gpio_spkr_en);
+
+	kfree(harmony);
+
+	return 0;
+}
+
+static struct platform_driver tegra_snd_harmony_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = tegra_snd_harmony_probe,
+	.remove = __devexit_p(tegra_snd_harmony_remove),
+};
+
+static int __init snd_tegra_harmony_init(void)
+{
+	return platform_driver_register(&tegra_snd_harmony_driver);
+}
+module_init(snd_tegra_harmony_init);
+
+static void __exit snd_tegra_harmony_exit(void)
+{
+	platform_driver_unregister(&tegra_snd_harmony_driver);
+}
+module_exit(snd_tegra_harmony_exit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Harmony machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
new file mode 100644
index 0000000..52f0a3f
--- /dev/null
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -0,0 +1,155 @@
+/*
+ * tegra_asoc_utils.c - Harmony machine ASoC driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#include "tegra_asoc_utils.h"
+
+int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
+			      int mclk, int *mclk_change)
+{
+	int new_baseclock;
+	int err;
+
+	switch (srate) {
+	case 11025:
+	case 22050:
+	case 44100:
+	case 88200:
+		new_baseclock = 56448000;
+		break;
+	case 8000:
+	case 16000:
+	case 32000:
+	case 48000:
+	case 64000:
+	case 96000:
+		new_baseclock = 73728000;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*mclk_change = ((new_baseclock != data->set_baseclock) ||
+			(mclk != data->set_mclk));
+	if (!*mclk_change)
+	    return 0;
+
+	data->set_baseclock = 0;
+	data->set_mclk = 0;
+
+	clk_disable(data->clk_cdev1);
+	clk_disable(data->clk_pll_a_out0);
+	clk_disable(data->clk_pll_a);
+
+	err = clk_set_rate(data->clk_pll_a, new_baseclock);
+	if (err) {
+		dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
+		return err;
+	}
+
+	err = clk_set_rate(data->clk_pll_a_out0, mclk);
+	if (err) {
+		dev_err(data->dev, "Can't set pll_a_out0 rate: %d\n", err);
+		return err;
+	}
+
+	/* Don't set cdev1 rate; its locked to pll_a_out0 */
+
+	err = clk_enable(data->clk_pll_a);
+	if (err) {
+		dev_err(data->dev, "Can't enable pll_a: %d\n", err);
+		return err;
+	}
+
+	err = clk_enable(data->clk_pll_a_out0);
+	if (err) {
+		dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err);
+		return err;
+	}
+
+	err = clk_enable(data->clk_cdev1);
+	if (err) {
+		dev_err(data->dev, "Can't enable cdev1: %d\n", err);
+		return err;
+	}
+
+	data->set_baseclock = new_baseclock;
+	data->set_mclk = mclk;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_utils_set_rate);
+
+int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
+			  struct device *dev)
+{
+	int ret;
+
+	data->dev = dev;
+
+	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 (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;
+	}
+
+	data->clk_cdev1 = clk_get_sys(NULL, "cdev1");
+	if (IS_ERR(data->clk_cdev1)) {
+		dev_err(data->dev, "Can't retrieve clk cdev1\n");
+		ret = PTR_ERR(data->clk_cdev1);
+		goto err_put_pll_a_out0;
+	}
+
+	return 0;
+
+err_put_pll_a_out0:
+	clk_put(data->clk_pll_a_out0);
+err_put_pll_a:
+	clk_put(data->clk_pll_a);
+err:
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_utils_init);
+
+void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
+{
+	clk_put(data->clk_cdev1);
+	clk_put(data->clk_pll_a_out0);
+	clk_put(data->clk_pll_a);
+}
+EXPORT_SYMBOL_GPL(tegra_asoc_utils_fini);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra ASoC utility code");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/tegra/tegra_asoc_utils.h b/sound/soc/tegra/tegra_asoc_utils.h
new file mode 100644
index 0000000..bbba7af
--- /dev/null
+++ b/sound/soc/tegra/tegra_asoc_utils.h
@@ -0,0 +1,45 @@
+/*
+ * tegra_asoc_utils.h - Definitions for Tegra DAS driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TEGRA_ASOC_UTILS_H__
+#define __TEGRA_ASOC_UTILS_H_
+
+struct clk;
+struct device;
+
+struct tegra_asoc_utils_data {
+	struct device *dev;
+	struct clk *clk_pll_a;
+	struct clk *clk_pll_a_out0;
+	struct clk *clk_cdev1;
+	int set_baseclock;
+	int set_mclk;
+};
+
+int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
+			      int mclk, int *mclk_change);
+int tegra_asoc_utils_init(struct tegra_asoc_utils_data *data,
+			  struct device *dev);
+void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data);
+
+#endif
+
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
new file mode 100644
index 0000000..9f24ef7
--- /dev/null
+++ b/sound/soc/tegra/tegra_das.c
@@ -0,0 +1,265 @@
+/*
+ * tegra_das.c - Tegra DAS driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <mach/iomap.h>
+#include <sound/soc.h>
+#include "tegra_das.h"
+
+#define DRV_NAME "tegra-das"
+
+static struct tegra_das *das;
+
+static inline void tegra_das_write(u32 reg, u32 val)
+{
+	__raw_writel(val, das->regs + reg);
+}
+
+static inline u32 tegra_das_read(u32 reg)
+{
+	return __raw_readl(das->regs + reg);
+}
+
+int tegra_das_connect_dap_to_dac(int dap, int dac)
+{
+	u32 addr;
+	u32 reg;
+
+	if (!das)
+		return -ENODEV;
+
+	addr = TEGRA_DAS_DAP_CTRL_SEL +
+		(dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
+	reg = dac << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P;
+
+	tegra_das_write(addr, reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dac);
+
+int tegra_das_connect_dap_to_dap(int dap, int otherdap, int master,
+					int sdata1rx, int sdata2rx)
+{
+	u32 addr;
+	u32 reg;
+
+	if (!das)
+		return -ENODEV;
+
+	addr = TEGRA_DAS_DAP_CTRL_SEL +
+		(dap * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
+	reg = otherdap << TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P |
+		!!sdata2rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P |
+		!!sdata1rx << TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P |
+		!!master << TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P;
+
+	tegra_das_write(addr, reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_das_connect_dap_to_dap);
+
+int tegra_das_connect_dac_to_dap(int dac, int dap)
+{
+	u32 addr;
+	u32 reg;
+
+	if (!das)
+		return -ENODEV;
+
+	addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
+		(dac * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
+	reg = dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P |
+		dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P |
+		dap << TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P;
+
+	tegra_das_write(addr, reg);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tegra_das_connect_dac_to_dap);
+
+#ifdef CONFIG_DEBUG_FS
+static int tegra_das_show(struct seq_file *s, void *unused)
+{
+	int i;
+	u32 addr;
+	u32 reg;
+
+	for (i = 0; i < TEGRA_DAS_DAP_CTRL_SEL_COUNT; i++) {
+		addr = TEGRA_DAS_DAP_CTRL_SEL +
+			(i * TEGRA_DAS_DAP_CTRL_SEL_STRIDE);
+		reg = tegra_das_read(addr);
+		seq_printf(s, "TEGRA_DAS_DAP_CTRL_SEL[%d] = %08x\n", i, reg);
+	}
+
+	for (i = 0; i < TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT; i++) {
+		addr = TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL +
+			(i * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE);
+		reg = tegra_das_read(addr);
+		seq_printf(s, "TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL[%d] = %08x\n",
+				 i, reg);
+	}
+
+	return 0;
+}
+
+static int tegra_das_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tegra_das_show, inode->i_private);
+}
+
+static const struct file_operations tegra_das_debug_fops = {
+	.open    = tegra_das_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+static void tegra_das_debug_add(struct tegra_das *das)
+{
+	das->debug = debugfs_create_file(DRV_NAME, S_IRUGO,
+					 snd_soc_debugfs_root, das,
+					 &tegra_das_debug_fops);
+}
+
+static void tegra_das_debug_remove(struct tegra_das *das)
+{
+	if (das->debug)
+		debugfs_remove(das->debug);
+}
+#else
+static inline void tegra_das_debug_add(struct tegra_das *das)
+{
+}
+
+static inline void tegra_das_debug_remove(struct tegra_das *das)
+{
+}
+#endif
+
+static int __devinit tegra_das_probe(struct platform_device *pdev)
+{
+	struct resource *res, *region;
+	int ret = 0;
+
+	if (das)
+		return -ENODEV;
+
+	das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL);
+	if (!das) {
+		dev_err(&pdev->dev, "Can't allocate tegra_das\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+	das->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No memory resource\n");
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	region = request_mem_region(res->start, resource_size(res),
+					pdev->name);
+	if (!region) {
+		dev_err(&pdev->dev, "Memory region already claimed\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	das->regs = ioremap(res->start, resource_size(res));
+	if (!das->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_release;
+	}
+
+	tegra_das_debug_add(das);
+
+	platform_set_drvdata(pdev, das);
+
+	return 0;
+
+err_release:
+	release_mem_region(res->start, resource_size(res));
+err_free:
+	kfree(das);
+	das = 0;
+exit:
+	return ret;
+}
+
+static int __devexit tegra_das_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	if (!das)
+		return -ENODEV;
+
+	platform_set_drvdata(pdev, NULL);
+
+	tegra_das_debug_remove(das);
+
+	iounmap(das->regs);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(das);
+	das = 0;
+
+	return 0;
+}
+
+static struct platform_driver tegra_das_driver = {
+	.probe = tegra_das_probe,
+	.remove = __devexit_p(tegra_das_remove),
+	.driver = {
+		.name = DRV_NAME,
+	},
+};
+
+static int __init tegra_das_modinit(void)
+{
+	return platform_driver_register(&tegra_das_driver);
+}
+module_init(tegra_das_modinit);
+
+static void __exit tegra_das_modexit(void)
+{
+	platform_driver_unregister(&tegra_das_driver);
+}
+module_exit(tegra_das_modexit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra DAS driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_das.h b/sound/soc/tegra/tegra_das.h
new file mode 100644
index 0000000..2c96c7b
--- /dev/null
+++ b/sound/soc/tegra/tegra_das.h
@@ -0,0 +1,135 @@
+/*
+ * tegra_das.h - Definitions for Tegra DAS driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __TEGRA_DAS_H__
+#define __TEGRA_DAS_H__
+
+/* Register TEGRA_DAS_DAP_CTRL_SEL */
+#define TEGRA_DAS_DAP_CTRL_SEL				0x00
+#define TEGRA_DAS_DAP_CTRL_SEL_COUNT			5
+#define TEGRA_DAS_DAP_CTRL_SEL_STRIDE			4
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P		31
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_MS_SEL_S		1
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P	30
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_S	1
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P	29
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_S	1
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P		0
+#define TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_S		5
+
+/* Values for field TEGRA_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL */
+#define TEGRA_DAS_DAP_SEL_DAC1	0
+#define TEGRA_DAS_DAP_SEL_DAC2	1
+#define TEGRA_DAS_DAP_SEL_DAC3	2
+#define TEGRA_DAS_DAP_SEL_DAP1	16
+#define TEGRA_DAS_DAP_SEL_DAP2	17
+#define TEGRA_DAS_DAP_SEL_DAP3	18
+#define TEGRA_DAS_DAP_SEL_DAP4	19
+#define TEGRA_DAS_DAP_SEL_DAP5	20
+
+/* Register TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL */
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL			0x40
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_COUNT			3
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_STRIDE			4
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_P	28
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL_S	4
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_P	24
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL_S	4
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_P		0
+#define TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL_S		4
+
+/*
+ * Values for:
+ * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA2_SEL
+ * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_SDATA1_SEL
+ * TEGRA_DAS_DAC_INPUT_DATA_CLK_SEL_DAC_CLK_SEL
+ */
+#define TEGRA_DAS_DAC_SEL_DAP1	0
+#define TEGRA_DAS_DAC_SEL_DAP2	1
+#define TEGRA_DAS_DAC_SEL_DAP3	2
+#define TEGRA_DAS_DAC_SEL_DAP4	3
+#define TEGRA_DAS_DAC_SEL_DAP5	4
+
+/*
+ * Names/IDs of the DACs/DAPs.
+ */
+
+#define TEGRA_DAS_DAP_ID_1 0
+#define TEGRA_DAS_DAP_ID_2 1
+#define TEGRA_DAS_DAP_ID_3 2
+#define TEGRA_DAS_DAP_ID_4 3
+#define TEGRA_DAS_DAP_ID_5 4
+
+#define TEGRA_DAS_DAC_ID_1 0
+#define TEGRA_DAS_DAC_ID_2 1
+#define TEGRA_DAS_DAC_ID_3 2
+
+struct tegra_das {
+	struct device *dev;
+	void __iomem *regs;
+	struct dentry *debug;
+};
+
+/*
+ * Terminology:
+ * DAS: Digital audio switch (HW module controlled by this driver)
+ * DAP: Digital audio port (port/pins on Tegra device)
+ * DAC: Digital audio controller (e.g. I2S or AC97 controller elsewhere)
+ * 
+ * The Tegra DAS is a mux/cross-bar which can connect each DAP to a specific
+ * DAC, or another DAP. When DAPs are connected, one must be the master and
+ * one the slave. Each DAC allows selection of a specific DAP for input, to
+ * cater for the case where N DAPs are connected to 1 DAC for broadcast
+ * output.
+ *
+ * This driver is dumb; no attempt is made to ensure that a valid routing
+ * configuration is programmed.
+ */
+
+/*
+ * Connect a DAP to to a DAC
+ * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
+ * dac_sel: DAC to connect to: TEGRA_DAS_DAP_SEL_DAC*
+ */
+extern int tegra_das_connect_dap_to_dac(int dap_id, int dac_sel);
+
+/*
+ * Connect a DAP to to another DAP
+ * dap_id: DAP to connect: TEGRA_DAS_DAP_ID_*
+ * other_dap_sel: DAP to connect to: TEGRA_DAS_DAP_SEL_DAP*
+ * master: Is this DAP the master (1) or slave (0)
+ * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0)
+ * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0)
+ */
+extern int tegra_das_connect_dap_to_dap(int dap_id, int other_dap_sel,
+					int master, int sdata1rx,
+					int sdata2rx);
+
+/*
+ * Connect a DAC's input to a DAP
+ * (DAC outputs are selected by the DAP)
+ * dac_id: DAC ID to connect: TEGRA_DAS_DAC_ID_*
+ * dap_sel: DAP to receive input from: TEGRA_DAS_DAC_SEL_DAP*
+ */
+extern int tegra_das_connect_dac_to_dap(int dac_id, int dap_sel);
+
+#endif
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
new file mode 100644
index 0000000..4f5e2c9
--- /dev/null
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -0,0 +1,503 @@
+/*
+ * tegra_i2s.c - Tegra I2S driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.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/clk.h>
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <mach/iomap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_das.h"
+#include "tegra_i2s.h"
+
+#define DRV_NAME "tegra-i2s"
+
+static inline void tegra_i2s_write(struct tegra_i2s *i2s, u32 reg, u32 val)
+{
+	__raw_writel(val, i2s->regs + reg);
+}
+
+static inline u32 tegra_i2s_read(struct tegra_i2s *i2s, u32 reg)
+{
+	return __raw_readl(i2s->regs + reg);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int tegra_i2s_show(struct seq_file *s, void *unused)
+{
+#define REG(r) { r, #r }
+	static const struct {
+		int offset;
+		const char *name;
+	} regs[] = {
+		REG(TEGRA_I2S_CTRL),
+		REG(TEGRA_I2S_STATUS),
+		REG(TEGRA_I2S_TIMING),
+		REG(TEGRA_I2S_FIFO_SCR),
+		REG(TEGRA_I2S_PCM_CTRL),
+		REG(TEGRA_I2S_NW_CTRL),
+		REG(TEGRA_I2S_TDM_CTRL),
+		REG(TEGRA_I2S_TDM_TX_RX_CTRL),
+	};
+#undef REG
+
+	struct tegra_i2s *i2s = s->private;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++) {
+		u32 val = tegra_i2s_read(i2s, regs[i].offset);
+		seq_printf(s, "%s = %08x\n", regs[i].name, val);
+	}
+
+	return 0;
+}
+
+static int tegra_i2s_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tegra_i2s_show, inode->i_private);
+}
+
+static const struct file_operations tegra_i2s_debug_fops = {
+	.open    = tegra_i2s_debug_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = single_release,
+};
+
+static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
+{
+	char name[] = DRV_NAME ".0";
+
+	snprintf(name, sizeof(name), DRV_NAME".%1d", id);
+	i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
+						i2s, &tegra_i2s_debug_fops);
+}
+
+static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
+{
+	if (i2s->debug)
+		debugfs_remove(i2s->debug);
+}
+#else
+static inline void tegra_i2s_debug_add(struct tegra_i2s *i2s)
+{
+}
+
+static inline void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
+{
+}
+#endif
+
+static int tegra_i2s_set_fmt(struct snd_soc_dai *dai,
+				unsigned int fmt)
+{
+	struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+	case SND_SOC_DAIFMT_NB_NF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_MASTER_ENABLE;
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBS_CFS:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_MASTER_ENABLE;
+		break;
+	case SND_SOC_DAIFMT_CBM_CFM:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	i2s->reg_ctrl &= ~(TEGRA_I2S_CTRL_BIT_FORMAT_MASK | 
+				TEGRA_I2S_CTRL_LRCK_MASK);
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_DSP_A:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
+		break;
+	case SND_SOC_DAIFMT_DSP_B:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_DSP;
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_R_LOW;
+		break;
+	case SND_SOC_DAIFMT_I2S:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_I2S;
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_RJM;
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_FORMAT_LJM;
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_LRCK_L_LOW;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_i2s_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params,
+				struct snd_soc_dai *dai)
+{
+        struct device *dev = substream->pcm->card->dev;
+	struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+	u32 reg;
+	int ret, sample_size, srate, i2sclock, bitcnt;
+
+	i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK;
+	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16;
+		sample_size = 16;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24;
+		sample_size = 24;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32;
+		sample_size = 32;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	srate = params_rate(params);
+
+	/* Final "* 2" required by Tegra hardware */
+	i2sclock = srate * params_channels(params) * sample_size * 2;
+
+	ret = clk_set_rate(i2s->clk_i2s, i2sclock);
+	if (ret) {
+		dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
+		return ret;
+	}
+
+	bitcnt = (i2sclock / (2 * srate)) - 1;
+	if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US)
+		return -EINVAL;
+	reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
+
+	if (i2sclock % (2 * srate))
+		reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE;
+
+	tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg);
+
+	tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR,
+		TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS |
+		TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS);
+
+	return 0;
+}
+
+static void tegra_i2s_start_playback(struct tegra_i2s *i2s)
+{
+	i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO1_ENABLE;
+	tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra_i2s_stop_playback(struct tegra_i2s *i2s)
+{
+	i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE;
+	tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra_i2s_start_capture(struct tegra_i2s *i2s)
+{
+	i2s->reg_ctrl |= TEGRA_I2S_CTRL_FIFO2_ENABLE;
+	tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static void tegra_i2s_stop_capture(struct tegra_i2s *i2s)
+{
+	i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE;
+	tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl);
+}
+
+static int tegra_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
+				struct snd_soc_dai *dai)
+{
+	struct tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (!i2s->clk_refs)
+			clk_enable(i2s->clk_i2s);
+		i2s->clk_refs++;
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			tegra_i2s_start_playback(i2s);
+		else
+			tegra_i2s_start_capture(i2s);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			tegra_i2s_stop_playback(i2s);
+		else
+			tegra_i2s_stop_capture(i2s);
+		i2s->clk_refs--;
+		if (!i2s->clk_refs)
+			clk_disable(i2s->clk_i2s);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_i2s_probe(struct snd_soc_dai *dai)
+{
+	struct tegra_i2s * i2s = snd_soc_dai_get_drvdata(dai);
+
+	dai->capture_dma_data = &i2s->capture_dma_data;
+	dai->playback_dma_data = &i2s->playback_dma_data;
+
+	return 0;
+}
+
+static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
+	.set_fmt	= tegra_i2s_set_fmt,
+	.hw_params	= tegra_i2s_hw_params,
+	.trigger	= tegra_i2s_trigger,
+};
+
+struct snd_soc_dai_driver tegra_i2s_dai[] = {
+	{
+		.name = DRV_NAME ".0",
+		.probe = tegra_i2s_probe,
+		.playback = {
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.capture = {
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &tegra_i2s_dai_ops,
+		.symmetric_rates = 1,
+	},
+	{
+		.name = DRV_NAME ".1",
+		.probe = tegra_i2s_probe,
+		.playback = {
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.capture = {
+			.channels_min = 2,
+			.channels_max = 2,
+			.rates = SNDRV_PCM_RATE_8000_96000,
+			.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		},
+		.ops = &tegra_i2s_dai_ops,
+		.symmetric_rates = 1,
+	},
+};
+
+static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
+{
+	struct tegra_i2s * i2s;
+	char clk_name[12]; /* tegra-i2s.0 */
+	struct resource *mem, *memregion, *dmareq;
+	int ret;
+
+	if ((pdev->id < 0) ||
+		(pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) {
+		dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
+		return -EINVAL;
+	}
+
+	/*
+	 * FIXME: Until a codec driver exists for the tegra DAS, hard-code a
+	 * 1:1 mapping between audio controllers and audio ports.
+	 */
+	ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id,
+					TEGRA_DAS_DAP_SEL_DAC1 + pdev->id);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't set up DAP connection\n");
+		return ret;
+	}
+	ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id,
+					TEGRA_DAS_DAC_SEL_DAP1 + pdev->id);
+	if (ret) {
+		dev_err(&pdev->dev, "Can't set up DAC connection\n");
+		return ret;
+	}
+
+	i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL);
+	if (!i2s) {
+		dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+	dev_set_drvdata(&pdev->dev, i2s);
+
+	snprintf(clk_name, sizeof(clk_name), DRV_NAME ".%d", pdev->id);
+	i2s->clk_i2s = clk_get_sys(clk_name, NULL);
+	if (IS_ERR(i2s->clk_i2s)) {
+		dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
+		ret = PTR_ERR(i2s->clk_i2s);
+		goto err_free;
+	}
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "No memory resource\n");
+		ret = -ENODEV;
+		goto err_clk_put;
+	}
+
+	dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	if (!dmareq) {
+		dev_err(&pdev->dev, "No DMA resource\n");
+		ret = -ENODEV;
+		goto err_clk_put;
+	}
+
+	memregion = request_mem_region(mem->start, resource_size(mem),
+					DRV_NAME);
+	if (!memregion) {
+		dev_err(&pdev->dev, "Memory region already claimed\n");
+		ret = -EBUSY;
+		goto err_clk_put;
+	}
+
+	i2s->regs = ioremap(mem->start, resource_size(mem));
+	if (!i2s->regs) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_release;
+	}
+
+	i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
+	i2s->capture_dma_data.wrap = 4;
+	i2s->capture_dma_data.width = 32;
+	i2s->capture_dma_data.req_sel = dmareq->start;
+
+	i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
+	i2s->playback_dma_data.wrap = 4;
+	i2s->playback_dma_data.width = 32;
+	i2s->playback_dma_data.req_sel = dmareq->start;
+
+	i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
+
+	ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]);
+	if (ret) {
+		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
+		ret = -ENOMEM;
+		goto err_unmap;
+	}
+
+	tegra_i2s_debug_add(i2s, pdev->id);
+
+	return 0;
+
+err_unmap:
+	iounmap(i2s->regs);
+err_release:
+	release_mem_region(mem->start, resource_size(mem));
+err_clk_put:
+	clk_put(i2s->clk_i2s);
+err_free:
+	kfree(i2s);
+exit:
+	return ret;
+}
+
+static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
+{
+	struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
+	struct resource *res;
+
+	snd_soc_unregister_dai(&pdev->dev);
+
+	tegra_i2s_debug_remove(i2s);
+
+	iounmap(i2s->regs);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	clk_put(i2s->clk_i2s);
+
+	kfree(i2s);
+
+	return 0;
+}
+
+static struct platform_driver tegra_i2s_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = tegra_i2s_platform_probe,
+	.remove = __devexit_p(tegra_i2s_platform_remove),
+};
+
+static int __init snd_tegra_i2s_init(void)
+{
+	return platform_driver_register(&tegra_i2s_driver);
+}
+module_init(snd_tegra_i2s_init);
+
+static void __exit snd_tegra_i2s_exit(void)
+{
+	platform_driver_unregister(&tegra_i2s_driver);
+}
+module_exit(snd_tegra_i2s_exit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra I2S ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h
new file mode 100644
index 0000000..2b38a09
--- /dev/null
+++ b/sound/soc/tegra/tegra_i2s.h
@@ -0,0 +1,165 @@
+/*
+ * tegra_i2s.h - Definitions for Tegra I2S driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.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 __TEGRA_I2S_H__
+#define __TEGRA_I2S_H__
+
+#include "tegra_pcm.h"
+
+/* Register offsets from TEGRA_I2S1_BASE and TEGRA_I2S2_BASE */
+
+#define TEGRA_I2S_CTRL					0x00
+#define TEGRA_I2S_STATUS				0x04
+#define TEGRA_I2S_TIMING				0x08
+#define TEGRA_I2S_FIFO_SCR				0x0c
+#define TEGRA_I2S_PCM_CTRL				0x10
+#define TEGRA_I2S_NW_CTRL				0x14
+#define TEGRA_I2S_TDM_CTRL				0x20
+#define TEGRA_I2S_TDM_TX_RX_CTRL			0x24
+#define TEGRA_I2S_FIFO1					0x40
+#define TEGRA_I2S_FIFO2					0x80
+
+/* Fields in TEGRA_I2S_CTRL */
+
+#define TEGRA_I2S_CTRL_FIFO2_TX_ENABLE			(1 << 30)
+#define TEGRA_I2S_CTRL_FIFO1_ENABLE			(1 << 29)
+#define TEGRA_I2S_CTRL_FIFO2_ENABLE			(1 << 28)
+#define TEGRA_I2S_CTRL_FIFO1_RX_ENABLE			(1 << 27)
+#define TEGRA_I2S_CTRL_FIFO_LPBK_ENABLE			(1 << 26)
+#define TEGRA_I2S_CTRL_MASTER_ENABLE			(1 << 25)
+
+#define TEGRA_I2S_LRCK_LEFT_LOW				0
+#define TEGRA_I2S_LRCK_RIGHT_LOW			1
+
+#define TEGRA_I2S_CTRL_LRCK_SHIFT			24
+#define TEGRA_I2S_CTRL_LRCK_MASK			(1                        << TEGRA_I2S_CTRL_LRCK_SHIFT)
+#define TEGRA_I2S_CTRL_LRCK_L_LOW			(TEGRA_I2S_LRCK_LEFT_LOW  << TEGRA_I2S_CTRL_LRCK_SHIFT)
+#define TEGRA_I2S_CTRL_LRCK_R_LOW			(TEGRA_I2S_LRCK_RIGHT_LOW << TEGRA_I2S_CTRL_LRCK_SHIFT)
+
+#define TEGRA_I2S_BIT_FORMAT_I2S			0
+#define TEGRA_I2S_BIT_FORMAT_RJM			1
+#define TEGRA_I2S_BIT_FORMAT_LJM			2
+#define TEGRA_I2S_BIT_FORMAT_DSP			3
+
+#define TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT			10
+#define TEGRA_I2S_CTRL_BIT_FORMAT_MASK			(3                        << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_FORMAT_I2S			(TEGRA_I2S_BIT_FORMAT_I2S << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_FORMAT_RJM			(TEGRA_I2S_BIT_FORMAT_RJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_FORMAT_LJM			(TEGRA_I2S_BIT_FORMAT_LJM << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_FORMAT_DSP			(TEGRA_I2S_BIT_FORMAT_DSP << TEGRA_I2S_CTRL_BIT_FORMAT_SHIFT)
+
+#define TEGRA_I2S_BIT_SIZE_16				0
+#define TEGRA_I2S_BIT_SIZE_20				1
+#define TEGRA_I2S_BIT_SIZE_24				2
+#define TEGRA_I2S_BIT_SIZE_32				3
+
+#define TEGRA_I2S_CTRL_BIT_SIZE_SHIFT			8
+#define TEGRA_I2S_CTRL_BIT_SIZE_MASK			(3                     << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_SIZE_16			(TEGRA_I2S_BIT_SIZE_16 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_SIZE_20			(TEGRA_I2S_BIT_SIZE_20 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_SIZE_24			(TEGRA_I2S_BIT_SIZE_24 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
+#define TEGRA_I2S_CTRL_BIT_SIZE_32			(TEGRA_I2S_BIT_SIZE_32 << TEGRA_I2S_CTRL_BIT_SIZE_SHIFT)
+
+#define TEGRA_I2S_FIFO_16_LSB				0
+#define TEGRA_I2S_FIFO_20_LSB				1
+#define TEGRA_I2S_FIFO_24_LSB				2
+#define TEGRA_I2S_FIFO_32				3
+#define TEGRA_I2S_FIFO_PACKED				7
+
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT		4
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_MASK			(7                     << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_16_LSB		(TEGRA_I2S_FIFO_16_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_20_LSB		(TEGRA_I2S_FIFO_20_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_24_LSB		(TEGRA_I2S_FIFO_24_LSB << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_32			(TEGRA_I2S_FIFO_32     << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
+#define TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED		(TEGRA_I2S_FIFO_PACKED << TEGRA_I2S_CTRL_FIFO_FORMAT_SHIFT)
+
+#define TEGRA_I2S_CTRL_IE_FIFO1_ERR			(1 << 3)
+#define TEGRA_I2S_CTRL_IE_FIFO2_ERR			(1 << 2)
+#define TEGRA_I2S_CTRL_QE_FIFO1				(1 << 1)
+#define TEGRA_I2S_CTRL_QE_FIFO2				(1 << 0)
+
+/* Fields in TEGRA_I2S_STATUS */
+
+#define TEGRA_I2S_STATUS_FIFO1_RDY			(1 << 31)
+#define TEGRA_I2S_STATUS_FIFO2_RDY			(1 << 30)
+#define TEGRA_I2S_STATUS_FIFO1_BSY			(1 << 29)
+#define TEGRA_I2S_STATUS_FIFO2_BSY			(1 << 28)
+#define TEGRA_I2S_STATUS_FIFO1_ERR			(1 << 3)
+#define TEGRA_I2S_STATUS_FIFO2_ERR			(1 << 2)
+#define TEGRA_I2S_STATUS_QS_FIFO1			(1 << 1)
+#define TEGRA_I2S_STATUS_QS_FIFO2			(1 << 0)
+
+/* Fields in TEGRA_I2S_TIMING */
+
+#define TEGRA_I2S_TIMING_NON_SYM_ENABLE			(1 << 12)
+#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT	0
+#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US	0x7fff
+#define TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK		(TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT)
+
+/* Fields in TEGRA_I2S_FIFO_SCR */
+
+#define TEGRA_I2S_FIFO_SCR_FIFO2_FULL_EMPTY_COUNT_SHIFT	24
+#define TEGRA_I2S_FIFO_SCR_FIFO1_FULL_EMPTY_COUNT_SHIFT	16
+#define TEGRA_I2S_FIFO_SCR_FIFO_FULL_EMPTY_COUNT_MASK	0x3f
+
+#define TEGRA_I2S_FIFO_SCR_FIFO2_CLR			(1 << 12)
+#define TEGRA_I2S_FIFO_SCR_FIFO1_CLR			(1 << 8)
+
+#define TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT			0
+#define TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS		1
+#define TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS		2
+#define TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS		3
+
+#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT		4
+#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_MASK		(3 << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_ONE_SLOT	(TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT     << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS   << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_EIGHT_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS  << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_TWELVE_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_SHIFT)
+
+#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT		0
+#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_MASK		(3 << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_ONE_SLOT	(TEGRA_I2S_FIFO_ATN_LVL_ONE_SLOT     << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_FOUR_SLOTS   << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_EIGHT_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_EIGHT_SLOTS  << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS	(TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
+
+struct tegra_i2s {
+	struct clk *clk_i2s;
+	int clk_refs;
+	struct tegra_pcm_dma_params capture_dma_data;
+	struct tegra_pcm_dma_params playback_dma_data;
+	void __iomem *regs;
+	struct dentry *debug;
+	u32 reg_ctrl;
+};
+
+#endif
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
new file mode 100644
index 0000000..3c271f9
--- /dev/null
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -0,0 +1,404 @@
+/*
+ * tegra_pcm.c - Tegra PCM driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ * Vijay Mali <vmali@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.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/dma-mapping.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "tegra_pcm.h"
+
+#define DRV_NAME "tegra-pcm-audio"
+
+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,
+	.channels_max		= 2,
+	.period_bytes_min	= 1024,
+	.period_bytes_max	= PAGE_SIZE,
+	.periods_min		= 2,
+	.periods_max		= 8,
+	.buffer_bytes_max	= PAGE_SIZE * 8,
+	.fifo_size		= 4,
+};
+
+static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
+{
+	struct snd_pcm_substream *substream = prtd->substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	struct tegra_dma_req *dma_req;
+	unsigned long addr;
+
+	dma_req = &prtd->dma_req[prtd->dma_req_idx];
+	prtd->dma_req_idx = 1 - prtd->dma_req_idx;
+
+	addr = buf->addr + prtd->dma_pos;
+	prtd->dma_pos += dma_req->size;
+	if (prtd->dma_pos >= prtd->dma_pos_end)
+		prtd->dma_pos = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		dma_req->source_addr = addr;
+	else
+		dma_req->dest_addr = addr;
+
+	tegra_dma_enqueue_req(prtd->dma_chan, dma_req);
+}
+
+static void dma_complete_callback(struct tegra_dma_req *req)
+{
+	struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev;
+	struct snd_pcm_substream *substream = prtd->substream;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	spin_lock(&prtd->lock);
+
+	if (!prtd->running) {
+		spin_unlock(&prtd->lock);
+		return;
+	}
+
+	if (++prtd->period_index >= runtime->periods)
+		prtd->period_index = 0;
+
+	tegra_pcm_queue_dma(prtd);
+
+	spin_unlock(&prtd->lock);
+
+	snd_pcm_period_elapsed(substream);
+}
+
+static void setup_dma_tx_request(struct tegra_dma_req *req,
+					struct tegra_pcm_dma_params * dmap)
+{
+	req->complete = dma_complete_callback;
+	req->to_memory = false;
+	req->dest_addr = dmap->addr;
+	req->dest_wrap = dmap->wrap;
+	req->source_bus_width = 32;
+	req->source_wrap = 0;
+	req->dest_bus_width = dmap->width;
+	req->req_sel = dmap->req_sel;
+}
+
+static void setup_dma_rx_request(struct tegra_dma_req *req,
+					struct tegra_pcm_dma_params * dmap)
+{
+	req->complete = dma_complete_callback;
+	req->to_memory = true;
+	req->source_addr = dmap->addr;
+	req->dest_wrap = 0;
+	req->source_bus_width = dmap->width;
+	req->source_wrap = dmap->wrap;
+	req->dest_bus_width = 32;
+	req->req_sel = dmap->req_sel;
+}
+
+static int tegra_pcm_open(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct tegra_runtime_data *prtd;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct tegra_pcm_dma_params * dmap;
+	int ret = 0;
+
+	prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL);
+	if (prtd == NULL)
+		return -ENOMEM;
+
+	runtime->private_data = prtd;
+	prtd->substream = substream;
+
+	spin_lock_init(&prtd->lock);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+		setup_dma_tx_request(&prtd->dma_req[0], dmap);
+		setup_dma_tx_request(&prtd->dma_req[1], dmap);
+	} else {
+		dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+		setup_dma_rx_request(&prtd->dma_req[0], dmap);
+		setup_dma_rx_request(&prtd->dma_req[1], dmap);
+	}
+
+	prtd->dma_req[0].dev = prtd;
+	prtd->dma_req[1].dev = prtd;
+
+	prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
+	if (prtd->dma_chan == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	/* Set HW params now that initialization is complete */
+	snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
+
+	/* 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)
+		goto err;
+
+	return 0;
+
+err:
+	if (prtd->dma_chan) {
+		tegra_dma_free_channel(prtd->dma_chan);
+	}
+
+	kfree(prtd);
+
+	return ret;
+}
+
+static int tegra_pcm_close(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct tegra_runtime_data *prtd = runtime->private_data;
+
+	tegra_dma_free_channel(prtd->dma_chan);
+
+	kfree(prtd);
+
+	return 0;
+}
+
+static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct tegra_runtime_data *prtd = runtime->private_data;
+
+	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+	prtd->dma_req[0].size = params_period_bytes(params);
+	prtd->dma_req[1].size = prtd->dma_req[0].size;
+
+	return 0;
+}
+
+static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+	snd_pcm_set_runtime_buffer(substream, NULL);
+
+	return 0;
+}
+
+static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct tegra_runtime_data *prtd = runtime->private_data;
+	unsigned long flags;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		prtd->dma_pos = 0;
+		prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
+		prtd->period_index = 0;
+		prtd->dma_req_idx = 0;
+		/* Fall-through */
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		spin_lock_irqsave(&prtd->lock, flags);
+		prtd->running = 1;
+		spin_unlock_irqrestore(&prtd->lock, flags);
+		tegra_pcm_queue_dma(prtd);
+		tegra_pcm_queue_dma(prtd);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		spin_lock_irqsave(&prtd->lock, flags);
+		prtd->running = 0;
+		spin_unlock_irqrestore(&prtd->lock, flags);
+		tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
+		tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct tegra_runtime_data *prtd = runtime->private_data;
+
+	return prtd->period_index * runtime->period_size;
+}
+
+
+static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
+				struct vm_area_struct *vma)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+					runtime->dma_area,
+					runtime->dma_addr,
+					runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops tegra_pcm_ops = {
+	.open		= tegra_pcm_open,
+	.close		= tegra_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= tegra_pcm_hw_params,
+	.hw_free	= tegra_pcm_hw_free,
+	.trigger	= tegra_pcm_trigger,
+	.pointer	= tegra_pcm_pointer,
+	.mmap		= tegra_pcm_mmap,
+};
+
+static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+	size_t size = tegra_pcm_hardware.buffer_bytes_max;
+
+	buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+						&buf->addr, GFP_KERNEL);
+	if (!buf->area)
+		return -ENOMEM;
+
+	buf->dev.type = SNDRV_DMA_TYPE_DEV;
+	buf->dev.dev = pcm->card->dev;
+	buf->private_data = NULL;
+	buf->bytes = size;
+
+	return 0;
+}
+
+static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+	struct snd_dma_buffer *buf = &substream->dma_buffer;
+
+	if (!buf->area)
+		return;
+
+	dma_free_writecombine(pcm->card->dev, buf->bytes,
+				buf->area, buf->addr);
+	buf->area = NULL;
+}
+
+static u64 tegra_dma_mask = DMA_BIT_MASK(32);
+
+static int tegra_pcm_new(struct snd_card *card,
+				struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+	int ret = 0;
+
+	if (!card->dev->dma_mask)
+		card->dev->dma_mask = &tegra_dma_mask;
+	if (!card->dev->coherent_dma_mask)
+		card->dev->coherent_dma_mask = 0xffffffff;
+
+	if (dai->driver->playback.channels_min) {
+		ret = tegra_pcm_preallocate_dma_buffer(pcm,
+						SNDRV_PCM_STREAM_PLAYBACK);
+		if (ret)
+			goto err;
+	}
+
+	if (dai->driver->capture.channels_min) {
+		ret = tegra_pcm_preallocate_dma_buffer(pcm,
+						SNDRV_PCM_STREAM_CAPTURE);
+		if (ret)
+			goto err_free_play;
+	}
+
+	return 0;
+
+err_free_play:
+	tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
+err:
+	return ret;
+}
+
+static void tegra_pcm_free(struct snd_pcm *pcm)
+{
+	tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
+	tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
+}
+
+struct snd_soc_platform_driver tegra_pcm_platform = {
+	.ops		= &tegra_pcm_ops,
+	.pcm_new	= tegra_pcm_new,
+	.pcm_free	= tegra_pcm_free,
+};
+
+static int __devinit tegra_pcm_platform_probe(struct platform_device *pdev)
+{
+	return snd_soc_register_platform(&pdev->dev, &tegra_pcm_platform);
+}
+
+static int __devexit tegra_pcm_platform_remove(struct platform_device *pdev)
+{
+	snd_soc_unregister_platform(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver tegra_pcm_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = tegra_pcm_platform_probe,
+	.remove = __devexit_p(tegra_pcm_platform_remove),
+};
+
+static int __init snd_tegra_pcm_init(void)
+{
+	return platform_driver_register(&tegra_pcm_driver);
+}
+module_init(snd_tegra_pcm_init);
+
+static void __exit snd_tegra_pcm_exit(void)
+{
+	platform_driver_unregister(&tegra_pcm_driver);
+}
+module_exit(snd_tegra_pcm_exit);
+
+MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
+MODULE_DESCRIPTION("Tegra PCM ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/tegra/tegra_pcm.h b/sound/soc/tegra/tegra_pcm.h
new file mode 100644
index 0000000..dbb9033
--- /dev/null
+++ b/sound/soc/tegra/tegra_pcm.h
@@ -0,0 +1,55 @@
+/*
+ * tegra_pcm.h - Definitions for Tegra PCM driver
+ *
+ * Author: Stephen Warren <swarren@nvidia.com>
+ * Copyright (C) 2010 - NVIDIA, Inc.
+ *
+ * Based on code copyright/by:
+ *
+ * Copyright (c) 2009-2010, NVIDIA Corporation.
+ * Scott Peterson <speterson@nvidia.com>
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Iliyan Malchev <malchev@google.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 __TEGRA_PCM_H__
+#define __TEGRA_PCM_H__
+
+#include <mach/dma.h>
+
+struct tegra_pcm_dma_params {
+	unsigned long addr;
+	unsigned long wrap;
+	unsigned long width;
+	unsigned long req_sel;
+};
+
+struct tegra_runtime_data {
+	struct snd_pcm_substream *substream;
+	spinlock_t lock;
+	int running;
+	int dma_pos;
+	int dma_pos_end;
+	int period_index;
+	int dma_req_idx;
+	struct tegra_dma_req dma_req[2];
+	struct tegra_dma_channel *dma_chan;
+};
+
+#endif
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 5580ace..6ce2778 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -384,6 +384,9 @@ int register_sound_special_device(const struct file_operations *fops, int unit,
 	    case 4:
 		name = "audio";
 		break;
+	    case 5:
+		name = "dspW";
+		break;
 	    case 8:
 		name = "sequencer2";
 		if (unit >= SOUND_STEP)
diff --git a/sound/sound_firmware.c b/sound/sound_firmware.c
index 340a0bc..7e96249 100644
--- a/sound/sound_firmware.c
+++ b/sound/sound_firmware.c
@@ -19,7 +19,7 @@ static int do_mod_firmware_load(const char *fn, char **fp)
 		printk(KERN_INFO "Unable to load '%s'.\n", fn);
 		return 0;
 	}
-	l = filp->f_path.dentry->d_inode->i_size;
+	l = i_size_read(filp->f_path.dentry->d_inode);
 	if (l <= 0 || l > 131072)
 	{
 		printk(KERN_INFO "Invalid firmware '%s'\n", fn);
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index f8bcfc3..ad7d4d7 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -1002,7 +1002,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card,
 	return 0;
 }
 
-static int __devinit amd7930_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit amd7930_sbus_probe(struct platform_device *op)
 {
 	struct resource *rp = &op->resource[0];
 	static int dev_num;
@@ -1064,7 +1064,7 @@ static const struct of_device_id amd7930_match[] = {
 	{},
 };
 
-static struct of_platform_driver amd7930_sbus_driver = {
+static struct platform_driver amd7930_sbus_driver = {
 	.driver = {
 		.name = "audio",
 		.owner = THIS_MODULE,
@@ -1075,7 +1075,7 @@ static struct of_platform_driver amd7930_sbus_driver = {
 
 static int __init amd7930_init(void)
 {
-	return of_register_platform_driver(&amd7930_sbus_driver);
+	return platform_driver_register(&amd7930_sbus_driver);
 }
 
 static void __exit amd7930_exit(void)
@@ -1092,7 +1092,7 @@ static void __exit amd7930_exit(void)
 
 	amd7930_list = NULL;
 
-	of_unregister_platform_driver(&amd7930_sbus_driver);
+	platform_driver_unregister(&amd7930_sbus_driver);
 }
 
 module_init(amd7930_init);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index c276086..0e618f8 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -1856,7 +1856,7 @@ static int __devinit snd_cs4231_sbus_create(struct snd_card *card,
 	return 0;
 }
 
-static int __devinit cs4231_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit cs4231_sbus_probe(struct platform_device *op)
 {
 	struct resource *rp = &op->resource[0];
 	struct snd_card *card;
@@ -2048,7 +2048,7 @@ static int __devinit snd_cs4231_ebus_create(struct snd_card *card,
 	return 0;
 }
 
-static int __devinit cs4231_ebus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit cs4231_ebus_probe(struct platform_device *op)
 {
 	struct snd_card *card;
 	int err;
@@ -2072,16 +2072,16 @@ static int __devinit cs4231_ebus_probe(struct platform_device *op, const struct
 }
 #endif
 
-static int __devinit cs4231_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit cs4231_probe(struct platform_device *op)
 {
 #ifdef EBUS_SUPPORT
 	if (!strcmp(op->dev.of_node->parent->name, "ebus"))
-		return cs4231_ebus_probe(op, match);
+		return cs4231_ebus_probe(op);
 #endif
 #ifdef SBUS_SUPPORT
 	if (!strcmp(op->dev.of_node->parent->name, "sbus") ||
 	    !strcmp(op->dev.of_node->parent->name, "sbi"))
-		return cs4231_sbus_probe(op, match);
+		return cs4231_sbus_probe(op);
 #endif
 	return -ENODEV;
 }
@@ -2108,7 +2108,7 @@ static const struct of_device_id cs4231_match[] = {
 
 MODULE_DEVICE_TABLE(of, cs4231_match);
 
-static struct of_platform_driver cs4231_driver = {
+static struct platform_driver cs4231_driver = {
 	.driver = {
 		.name = "audio",
 		.owner = THIS_MODULE,
@@ -2120,12 +2120,12 @@ static struct of_platform_driver cs4231_driver = {
 
 static int __init cs4231_init(void)
 {
-	return of_register_platform_driver(&cs4231_driver);
+	return platform_driver_register(&cs4231_driver);
 }
 
 static void __exit cs4231_exit(void)
 {
-	of_unregister_platform_driver(&cs4231_driver);
+	platform_driver_unregister(&cs4231_driver);
 }
 
 module_init(cs4231_init);
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 39cd5d6..73f9cba 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -2592,7 +2592,7 @@ static void snd_dbri_free(struct snd_dbri *dbri)
 				  (void *)dbri->dma, dbri->dma_dvma);
 }
 
-static int __devinit dbri_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit dbri_probe(struct platform_device *op)
 {
 	struct snd_dbri *dbri;
 	struct resource *rp;
@@ -2686,7 +2686,7 @@ static const struct of_device_id dbri_match[] = {
 
 MODULE_DEVICE_TABLE(of, dbri_match);
 
-static struct of_platform_driver dbri_sbus_driver = {
+static struct platform_driver dbri_sbus_driver = {
 	.driver = {
 		.name = "dbri",
 		.owner = THIS_MODULE,
@@ -2699,12 +2699,12 @@ static struct of_platform_driver dbri_sbus_driver = {
 /* Probe for the dbri chip and then attach the driver. */
 static int __init dbri_init(void)
 {
-	return of_register_platform_driver(&dbri_sbus_driver);
+	return platform_driver_register(&dbri_sbus_driver);
 }
 
 static void __exit dbri_exit(void)
 {
-	of_unregister_platform_driver(&dbri_sbus_driver);
+	platform_driver_unregister(&dbri_sbus_driver);
 }
 
 module_init(dbri_init);
diff --git a/sound/usb/6fire/Makefile b/sound/usb/6fire/Makefile
new file mode 100644
index 0000000..dfce6ec
--- /dev/null
+++ b/sound/usb/6fire/Makefile
@@ -0,0 +1,3 @@
+snd-usb-6fire-objs += chip.o comm.o midi.o control.o firmware.o pcm.o
+obj-$(CONFIG_SND_USB_6FIRE) += snd-usb-6fire.o
+
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
new file mode 100644
index 0000000..c7dca7b
--- /dev/null
+++ b/sound/usb/6fire/chip.c
@@ -0,0 +1,232 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Main routines and module definitions.
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "chip.h"
+#include "firmware.h"
+#include "pcm.h"
+#include "control.h"
+#include "comm.h"
+#include "midi.h"
+
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
+MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
+MODULE_LICENSE("GPL v2");
+MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
+static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the 6fire sound device");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the 6fire sound device.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable the 6fire sound device.");
+
+static DEFINE_MUTEX(register_mutex);
+
+static void usb6fire_chip_abort(struct sfire_chip *chip)
+{
+	if (chip) {
+		if (chip->pcm)
+			usb6fire_pcm_abort(chip);
+		if (chip->midi)
+			usb6fire_midi_abort(chip);
+		if (chip->comm)
+			usb6fire_comm_abort(chip);
+		if (chip->control)
+			usb6fire_control_abort(chip);
+		if (chip->card) {
+			snd_card_disconnect(chip->card);
+			snd_card_free_when_closed(chip->card);
+			chip->card = NULL;
+		}
+	}
+}
+
+static void usb6fire_chip_destroy(struct sfire_chip *chip)
+{
+	if (chip) {
+		if (chip->pcm)
+			usb6fire_pcm_destroy(chip);
+		if (chip->midi)
+			usb6fire_midi_destroy(chip);
+		if (chip->comm)
+			usb6fire_comm_destroy(chip);
+		if (chip->control)
+			usb6fire_control_destroy(chip);
+		if (chip->card)
+			snd_card_free(chip->card);
+	}
+}
+
+static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
+		const struct usb_device_id *usb_id)
+{
+	int ret;
+	int i;
+	struct sfire_chip *chip = NULL;
+	struct usb_device *device = interface_to_usbdev(intf);
+	int regidx = -1; /* index in module parameter array */
+	struct snd_card *card = NULL;
+
+	/* look if we already serve this card and return if so */
+	mutex_lock(&register_mutex);
+	for (i = 0; i < SNDRV_CARDS; i++) {
+		if (devices[i] == device) {
+			if (chips[i])
+				chips[i]->intf_count++;
+			usb_set_intfdata(intf, chips[i]);
+			mutex_unlock(&register_mutex);
+			return 0;
+		} else if (regidx < 0)
+			regidx = i;
+	}
+	if (regidx < 0) {
+		mutex_unlock(&register_mutex);
+		snd_printk(KERN_ERR PREFIX "too many cards registered.\n");
+		return -ENODEV;
+	}
+	devices[regidx] = device;
+	mutex_unlock(&register_mutex);
+
+	/* check, if firmware is present on device, upload it if not */
+	ret = usb6fire_fw_init(intf);
+	if (ret < 0)
+		return ret;
+	else if (ret == FW_NOT_READY) /* firmware update performed */
+		return 0;
+
+	/* if we are here, card can be registered in alsa. */
+	if (usb_set_interface(device, 0, 0) != 0) {
+		snd_printk(KERN_ERR PREFIX "can't set first interface.\n");
+		return -EIO;
+	}
+	ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE,
+			sizeof(struct sfire_chip), &card);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n");
+		return ret;
+	}
+	strcpy(card->driver, "6FireUSB");
+	strcpy(card->shortname, "TerraTec DMX6FireUSB");
+	sprintf(card->longname, "%s at %d:%d", card->shortname,
+			device->bus->busnum, device->devnum);
+	snd_card_set_dev(card, &intf->dev);
+
+	chip = card->private_data;
+	chips[regidx] = chip;
+	chip->dev = device;
+	chip->regidx = regidx;
+	chip->intf_count = 1;
+	chip->card = card;
+
+	ret = usb6fire_comm_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = usb6fire_midi_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = usb6fire_pcm_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = usb6fire_control_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = snd_card_register(card);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "cannot register card.");
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+	usb_set_intfdata(intf, chip);
+	return 0;
+}
+
+static void usb6fire_chip_disconnect(struct usb_interface *intf)
+{
+	struct sfire_chip *chip;
+	struct snd_card *card;
+
+	chip = usb_get_intfdata(intf);
+	if (chip) { /* if !chip, fw upload has been performed */
+		card = chip->card;
+		chip->intf_count--;
+		if (!chip->intf_count) {
+			mutex_lock(&register_mutex);
+			devices[chip->regidx] = NULL;
+			chips[chip->regidx] = NULL;
+			mutex_unlock(&register_mutex);
+
+			chip->shutdown = true;
+			usb6fire_chip_abort(chip);
+			usb6fire_chip_destroy(chip);
+		}
+	}
+}
+
+static struct usb_device_id device_table[] = {
+	{
+		.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor = 0x0ccd,
+		.idProduct = 0x0080
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static struct usb_driver driver = {
+	.name = "snd-usb-6fire",
+	.probe = usb6fire_chip_probe,
+	.disconnect = usb6fire_chip_disconnect,
+	.id_table = device_table,
+};
+
+static int __init usb6fire_chip_init(void)
+{
+	return usb_register(&driver);
+}
+
+static void __exit usb6fire_chip_cleanup(void)
+{
+	usb_deregister(&driver);
+}
+
+module_init(usb6fire_chip_init);
+module_exit(usb6fire_chip_cleanup);
diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h
new file mode 100644
index 0000000..d11e5cb
--- /dev/null
+++ b/sound/usb/6fire/chip.h
@@ -0,0 +1,32 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_CHIP_H
+#define USB6FIRE_CHIP_H
+
+#include "common.h"
+
+struct sfire_chip {
+	struct usb_device *dev;
+	struct snd_card *card;
+	int intf_count; /* number of registered interfaces */
+	int regidx; /* index in module parameter arrays */
+	bool shutdown;
+
+	struct midi_runtime *midi;
+	struct pcm_runtime *pcm;
+	struct control_runtime *control;
+	struct comm_runtime *comm;
+};
+#endif /* USB6FIRE_CHIP_H */
+
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
new file mode 100644
index 0000000..c994daa
--- /dev/null
+++ b/sound/usb/6fire/comm.c
@@ -0,0 +1,176 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Device communications
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "comm.h"
+#include "chip.h"
+#include "midi.h"
+
+enum {
+	COMM_EP = 1,
+	COMM_FPGA_EP = 2
+};
+
+static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb,
+		u8 *buffer, void *context, void(*handler)(struct urb *urb))
+{
+	usb_init_urb(urb);
+	urb->transfer_buffer = buffer;
+	urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP);
+	urb->complete = handler;
+	urb->context = context;
+	urb->interval = 1;
+	urb->dev = rt->chip->dev;
+}
+
+static void usb6fire_comm_receiver_handler(struct urb *urb)
+{
+	struct comm_runtime *rt = urb->context;
+	struct midi_runtime *midi_rt = rt->chip->midi;
+
+	if (!urb->status) {
+		if (rt->receiver_buffer[0] == 0x10) /* midi in event */
+			if (midi_rt)
+				midi_rt->in_received(midi_rt,
+						rt->receiver_buffer + 2,
+						rt->receiver_buffer[1]);
+	}
+
+	if (!rt->chip->shutdown) {
+		urb->status = 0;
+		urb->actual_length = 0;
+		if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+			snd_printk(KERN_WARNING PREFIX
+					"comm data receiver aborted.\n");
+	}
+}
+
+static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request,
+		u8 reg, u8 vl, u8 vh)
+{
+	buffer[0] = 0x01;
+	buffer[2] = request;
+	buffer[3] = id;
+	switch (request) {
+	case 0x02:
+		buffer[1] = 0x05; /* length (starting at buffer[2]) */
+		buffer[4] = reg;
+		buffer[5] = vl;
+		buffer[6] = vh;
+		break;
+
+	case 0x12:
+		buffer[1] = 0x0b; /* length (starting at buffer[2]) */
+		buffer[4] = 0x00;
+		buffer[5] = 0x18;
+		buffer[6] = 0x05;
+		buffer[7] = 0x00;
+		buffer[8] = 0x01;
+		buffer[9] = 0x00;
+		buffer[10] = 0x9e;
+		buffer[11] = reg;
+		buffer[12] = vl;
+		break;
+
+	case 0x20:
+	case 0x21:
+	case 0x22:
+		buffer[1] = 0x04;
+		buffer[4] = reg;
+		buffer[5] = vl;
+		break;
+	}
+}
+
+static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
+{
+	int ret;
+	int actual_len;
+
+	ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
+			buffer, buffer[1] + 2, &actual_len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (actual_len != buffer[1] + 2)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
+		u8 reg, u8 value)
+{
+	u8 buffer[13]; /* 13: maximum length of message */
+
+	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
+	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+}
+
+static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
+		u8 reg, u8 vl, u8 vh)
+{
+	u8 buffer[13]; /* 13: maximum length of message */
+
+	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
+	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+}
+
+int __devinit usb6fire_comm_init(struct sfire_chip *chip)
+{
+	struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
+			GFP_KERNEL);
+	struct urb *urb = &rt->receiver;
+	int ret;
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->serial = 1;
+	rt->chip = chip;
+	usb_init_urb(urb);
+	rt->init_urb = usb6fire_comm_init_urb;
+	rt->write8 = usb6fire_comm_write8;
+	rt->write16 = usb6fire_comm_write16;
+
+	/* submit an urb that receives communication data from device */
+	urb->transfer_buffer = rt->receiver_buffer;
+	urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
+	urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
+	urb->dev = chip->dev;
+	urb->complete = usb6fire_comm_receiver_handler;
+	urb->context = rt;
+	urb->interval = 1;
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret < 0) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
+		return ret;
+	}
+	chip->comm = rt;
+	return 0;
+}
+
+void usb6fire_comm_abort(struct sfire_chip *chip)
+{
+	struct comm_runtime *rt = chip->comm;
+
+	if (rt)
+		usb_poison_urb(&rt->receiver);
+}
+
+void usb6fire_comm_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->comm);
+	chip->comm = NULL;
+}
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
new file mode 100644
index 0000000..edc5dc8
--- /dev/null
+++ b/sound/usb/6fire/comm.h
@@ -0,0 +1,44 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_COMM_H
+#define USB6FIRE_COMM_H
+
+#include "common.h"
+
+enum /* settings for comm */
+{
+	COMM_RECEIVER_BUFSIZE = 64,
+};
+
+struct comm_runtime {
+	struct sfire_chip *chip;
+
+	struct urb receiver;
+	u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
+
+	u8 serial; /* urb serial */
+
+	void (*init_urb)(struct comm_runtime *rt, struct urb *urb, u8 *buffer,
+			void *context, void(*handler)(struct urb *urb));
+	/* writes control data to the device */
+	int (*write8)(struct comm_runtime *rt, u8 request, u8 reg, u8 value);
+	int (*write16)(struct comm_runtime *rt, u8 request, u8 reg,
+			u8 vh, u8 vl);
+};
+
+int __devinit usb6fire_comm_init(struct sfire_chip *chip);
+void usb6fire_comm_abort(struct sfire_chip *chip);
+void usb6fire_comm_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_COMM_H */
+
diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h
new file mode 100644
index 0000000..7dbeb4a
--- /dev/null
+++ b/sound/usb/6fire/common.h
@@ -0,0 +1,30 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_COMMON_H
+#define USB6FIRE_COMMON_H
+
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+
+#define PREFIX "6fire: "
+
+struct sfire_chip;
+struct midi_runtime;
+struct pcm_runtime;
+struct control_runtime;
+struct comm_runtime;
+#endif /* USB6FIRE_COMMON_H */
+
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
new file mode 100644
index 0000000..2484635
--- /dev/null
+++ b/sound/usb/6fire/control.c
@@ -0,0 +1,275 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Mixer control
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/interrupt.h>
+#include <sound/control.h>
+
+#include "control.h"
+#include "comm.h"
+#include "chip.h"
+
+static char *opt_coax_texts[2] = { "Optical", "Coax" };
+static char *line_phono_texts[2] = { "Line", "Phono" };
+
+/*
+ * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$
+ * this is done because the linear values cause rapid degredation
+ * of volume in the uppermost region.
+ */
+static const u8 log_volume_table[128] = {
+	0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34,
+	0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43,
+	0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+	0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56,
+	0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
+	0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62,
+	0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+	0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c,
+	0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+	0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75,
+	0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79,
+	0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
+	0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f };
+
+/*
+ * data that needs to be sent to device. sets up card internal stuff.
+ * values dumped from windows driver and filtered by trial'n'error.
+ */
+static const struct {
+	u8 type;
+	u8 reg;
+	u8 value;
+}
+init_data[] = {
+	{ 0x22, 0x00, 0x00 }, { 0x20, 0x00, 0x08 }, { 0x22, 0x01, 0x01 },
+	{ 0x20, 0x01, 0x08 }, { 0x22, 0x02, 0x00 }, { 0x20, 0x02, 0x08 },
+	{ 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
+	{ 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
+	{ 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
+	{ 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
+	{ 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
+	{ 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
+	{ 0 } /* TERMINATING ENTRY */
+};
+
+static void usb6fire_control_master_vol_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	if (comm_rt) {
+		/* set volume */
+		comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f -
+				log_volume_table[rt->master_vol]);
+		 /* unmute */
+		comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00);
+	}
+}
+
+static void usb6fire_control_line_phono_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	if (comm_rt) {
+		comm_rt->write8(comm_rt, 0x22, 0x02, rt->line_phono_switch);
+		comm_rt->write8(comm_rt, 0x21, 0x02, rt->line_phono_switch);
+	}
+}
+
+static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	if (comm_rt) {
+		comm_rt->write8(comm_rt, 0x22, 0x00, rt->opt_coax_switch);
+		comm_rt->write8(comm_rt, 0x21, 0x00, rt->opt_coax_switch);
+	}
+}
+
+static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 127;
+	return 0;
+}
+
+static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	if (rt->master_vol != ucontrol->value.integer.value[0]) {
+		rt->master_vol = ucontrol->value.integer.value[0];
+		usb6fire_control_master_vol_update(rt);
+		changed = 1;
+	}
+	return changed;
+}
+
+static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = rt->master_vol;
+	return 0;
+}
+
+static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name,
+			line_phono_texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	if (rt->line_phono_switch != ucontrol->value.integer.value[0]) {
+		rt->line_phono_switch = ucontrol->value.integer.value[0];
+		usb6fire_control_line_phono_update(rt);
+		changed = 1;
+	}
+	return changed;
+}
+
+static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = rt->line_phono_switch;
+	return 0;
+}
+
+static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name,
+			opt_coax_texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+
+	if (rt->opt_coax_switch != ucontrol->value.enumerated.item[0]) {
+		rt->opt_coax_switch = ucontrol->value.enumerated.item[0];
+		usb6fire_control_opt_coax_update(rt);
+		changed = 1;
+	}
+	return changed;
+}
+
+static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = rt->opt_coax_switch;
+	return 0;
+}
+
+static struct __devinitdata snd_kcontrol_new elements[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = usb6fire_control_master_vol_info,
+		.get = usb6fire_control_master_vol_get,
+		.put = usb6fire_control_master_vol_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line/Phono Capture Route",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = usb6fire_control_line_phono_info,
+		.get = usb6fire_control_line_phono_get,
+		.put = usb6fire_control_line_phono_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Opt/Coax Capture Route",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = usb6fire_control_opt_coax_info,
+		.get = usb6fire_control_opt_coax_get,
+		.put = usb6fire_control_opt_coax_put
+	},
+	{}
+};
+
+int __devinit usb6fire_control_init(struct sfire_chip *chip)
+{
+	int i;
+	int ret;
+	struct control_runtime *rt = kzalloc(sizeof(struct control_runtime),
+			GFP_KERNEL);
+	struct comm_runtime *comm_rt = chip->comm;
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->chip = chip;
+
+	i = 0;
+	while (init_data[i].type) {
+		comm_rt->write8(comm_rt, init_data[i].type, init_data[i].reg,
+				init_data[i].value);
+		i++;
+	}
+
+	usb6fire_control_opt_coax_update(rt);
+	usb6fire_control_line_phono_update(rt);
+	usb6fire_control_master_vol_update(rt);
+
+	i = 0;
+	while (elements[i].name) {
+		ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
+		if (ret < 0) {
+			kfree(rt);
+			snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+			return ret;
+		}
+		i++;
+	}
+
+	chip->control = rt;
+	return 0;
+}
+
+void usb6fire_control_abort(struct sfire_chip *chip)
+{}
+
+void usb6fire_control_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->control);
+	chip->control = NULL;
+}
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
new file mode 100644
index 0000000..b534c77
--- /dev/null
+++ b/sound/usb/6fire/control.h
@@ -0,0 +1,37 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_CONTROL_H
+#define USB6FIRE_CONTROL_H
+
+#include "common.h"
+
+enum {
+	CONTROL_MAX_ELEMENTS = 32
+};
+
+struct control_runtime {
+	struct sfire_chip *chip;
+
+	struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS];
+	bool opt_coax_switch;
+	bool line_phono_switch;
+	u8 master_vol;
+};
+
+int __devinit usb6fire_control_init(struct sfire_chip *chip);
+void usb6fire_control_abort(struct sfire_chip *chip);
+void usb6fire_control_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_CONTROL_H */
+
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
new file mode 100644
index 0000000..9081a54
--- /dev/null
+++ b/sound/usb/6fire/firmware.c
@@ -0,0 +1,426 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Firmware loader
+ *
+ * Currently not working for all devices. To be able to use the device
+ * in linux, it is also possible to let the windows driver upload the firmware.
+ * For that, start the computer in windows and reboot.
+ * As long as the device is connected to the power supply, no firmware reload
+ * needs to be performed.
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/firmware.h>
+
+#include "firmware.h"
+#include "chip.h"
+
+MODULE_FIRMWARE("6fire/dmx6firel2.ihx");
+MODULE_FIRMWARE("6fire/dmx6fireap.ihx");
+MODULE_FIRMWARE("6fire/dmx6firecf.bin");
+
+enum {
+	FPGA_BUFSIZE = 512, FPGA_EP = 2
+};
+
+static const u8 BIT_REVERSE_TABLE[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50,
+	0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8,
+	0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04,
+	0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4,
+	0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c,
+	0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82,
+	0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32,
+	0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46,
+	0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6,
+	0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e,
+	0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
+	0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71,
+	0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99,
+	0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25,
+	0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d,
+	0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3,
+	0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b,
+	0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb,
+	0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67,
+	0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f,
+	0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f,
+	0xbf, 0x7f, 0xff };
+
+/*
+ * wMaxPacketSize of pcm endpoints.
+ * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c
+ * fpp: frames per isopacket
+ *
+ * CAUTION: keep sizeof <= buffer[] in usb6fire_fw_init
+ */
+static const u8 ep_w_max_packet_size[] = {
+	0xe4, 0x00, 0xe4, 0x00, /* alt 1: 228 EP2 and EP6 (7 fpp) */
+	0xa4, 0x01, 0xa4, 0x01, /* alt 2: 420 EP2 and EP6 (13 fpp)*/
+	0x94, 0x01, 0x5c, 0x02  /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
+};
+
+struct ihex_record {
+	u16 address;
+	u8 len;
+	u8 data[256];
+	char error; /* true if an error occured parsing this record */
+
+	u8 max_len; /* maximum record length in whole ihex */
+
+	/* private */
+	const char *txt_data;
+	unsigned int txt_length;
+	unsigned int txt_offset; /* current position in txt_data */
+};
+
+static u8 usb6fire_fw_ihex_nibble(const u8 n)
+{
+	if (n >= '0' && n <= '9')
+		return n - '0';
+	else if (n >= 'A' && n <= 'F')
+		return n - ('A' - 10);
+	else if (n >= 'a' && n <= 'f')
+		return n - ('a' - 10);
+	return 0;
+}
+
+static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc)
+{
+	u8 val = (usb6fire_fw_ihex_nibble(data[0]) << 4) |
+			usb6fire_fw_ihex_nibble(data[1]);
+	*crc += val;
+	return val;
+}
+
+/*
+ * returns true if record is available, false otherwise.
+ * iff an error occured, false will be returned and record->error will be true.
+ */
+static bool usb6fire_fw_ihex_next_record(struct ihex_record *record)
+{
+	u8 crc = 0;
+	u8 type;
+	int i;
+
+	record->error = false;
+
+	/* find begin of record (marked by a colon) */
+	while (record->txt_offset < record->txt_length
+			&& record->txt_data[record->txt_offset] != ':')
+		record->txt_offset++;
+	if (record->txt_offset == record->txt_length)
+		return false;
+
+	/* number of characters needed for len, addr and type entries */
+	record->txt_offset++;
+	if (record->txt_offset + 8 > record->txt_length) {
+		record->error = true;
+		return false;
+	}
+
+	record->len = usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc);
+	record->txt_offset += 2;
+	record->address = usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc) << 8;
+	record->txt_offset += 2;
+	record->address |= usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc);
+	record->txt_offset += 2;
+	type = usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc);
+	record->txt_offset += 2;
+
+	/* number of characters needed for data and crc entries */
+	if (record->txt_offset + 2 * (record->len + 1) > record->txt_length) {
+		record->error = true;
+		return false;
+	}
+	for (i = 0; i < record->len; i++) {
+		record->data[i] = usb6fire_fw_ihex_hex(record->txt_data
+				+ record->txt_offset, &crc);
+		record->txt_offset += 2;
+	}
+	usb6fire_fw_ihex_hex(record->txt_data + record->txt_offset, &crc);
+	if (crc) {
+		record->error = true;
+		return false;
+	}
+
+	if (type == 1 || !record->len) /* eof */
+		return false;
+	else if (type == 0)
+		return true;
+	else {
+		record->error = true;
+		return false;
+	}
+}
+
+static int usb6fire_fw_ihex_init(const struct firmware *fw,
+		struct ihex_record *record)
+{
+	record->txt_data = fw->data;
+	record->txt_length = fw->size;
+	record->txt_offset = 0;
+	record->max_len = 0;
+	/* read all records, if loop ends, record->error indicates,
+	 * whether ihex is valid. */
+	while (usb6fire_fw_ihex_next_record(record))
+		record->max_len = max(record->len, record->max_len);
+	if (record->error)
+		return -EINVAL;
+	record->txt_offset = 0;
+	return 0;
+}
+
+static int usb6fire_fw_ezusb_write(struct usb_device *device,
+		int type, int value, char *data, int len)
+{
+	int ret;
+
+	ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value, 0, data, len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (ret != len)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_fw_ezusb_read(struct usb_device *device,
+		int type, int value, char *data, int len)
+{
+	int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
+			0, data, len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (ret != len)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_fw_fpga_write(struct usb_device *device,
+		char *data, int len)
+{
+	int actual_len;
+	int ret;
+
+	ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len,
+			&actual_len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (actual_len != len)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_fw_ezusb_upload(
+		struct usb_interface *intf, const char *fwname,
+		unsigned int postaddr, u8 *postdata, unsigned int postlen)
+{
+	int ret;
+	u8 data;
+	struct usb_device *device = interface_to_usbdev(intf);
+	const struct firmware *fw = 0;
+	struct ihex_record *rec = kmalloc(sizeof(struct ihex_record),
+			GFP_KERNEL);
+
+	if (!rec)
+		return -ENOMEM;
+
+	ret = request_firmware(&fw, fwname, &device->dev);
+	if (ret < 0) {
+		kfree(rec);
+		snd_printk(KERN_ERR PREFIX "error requesting ezusb "
+				"firmware %s.\n", fwname);
+		return ret;
+	}
+	ret = usb6fire_fw_ihex_init(fw, rec);
+	if (ret < 0) {
+		kfree(rec);
+		snd_printk(KERN_ERR PREFIX "error validating ezusb "
+				"firmware %s.\n", fwname);
+		return ret;
+	}
+	/* upload firmware image */
+	data = 0x01; /* stop ezusb cpu */
+	ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
+	if (ret < 0) {
+		kfree(rec);
+		release_firmware(fw);
+		snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+				"firmware %s: begin message.\n", fwname);
+		return ret;
+	}
+
+	while (usb6fire_fw_ihex_next_record(rec)) { /* write firmware */
+		ret = usb6fire_fw_ezusb_write(device, 0xa0, rec->address,
+				rec->data, rec->len);
+		if (ret < 0) {
+			kfree(rec);
+			release_firmware(fw);
+			snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+					"firmware %s: data urb.\n", fwname);
+			return ret;
+		}
+	}
+
+	release_firmware(fw);
+	kfree(rec);
+	if (postdata) { /* write data after firmware has been uploaded */
+		ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr,
+				postdata, postlen);
+		if (ret < 0) {
+			snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+					"firmware %s: post urb.\n", fwname);
+			return ret;
+		}
+	}
+
+	data = 0x00; /* resume ezusb cpu */
+	ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
+	if (ret < 0) {
+		release_firmware(fw);
+		snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+				"firmware %s: end message.\n", fwname);
+		return ret;
+	}
+	return 0;
+}
+
+static int usb6fire_fw_fpga_upload(
+		struct usb_interface *intf, const char *fwname)
+{
+	int ret;
+	int i;
+	struct usb_device *device = interface_to_usbdev(intf);
+	u8 *buffer = kmalloc(FPGA_BUFSIZE, GFP_KERNEL);
+	const char *c;
+	const char *end;
+	const struct firmware *fw;
+
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = request_firmware(&fw, fwname, &device->dev);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n",
+				fwname);
+		kfree(buffer);
+		return -EIO;
+	}
+
+	c = fw->data;
+	end = fw->data + fw->size;
+
+	ret = usb6fire_fw_ezusb_write(device, 8, 0, NULL, 0);
+	if (ret < 0) {
+		kfree(buffer);
+		release_firmware(fw);
+		snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
+				"begin urb.\n");
+		return ret;
+	}
+
+	while (c != end) {
+		for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++)
+			buffer[i] = BIT_REVERSE_TABLE[(u8) *c];
+
+		ret = usb6fire_fw_fpga_write(device, buffer, i);
+		if (ret < 0) {
+			release_firmware(fw);
+			kfree(buffer);
+			snd_printk(KERN_ERR PREFIX "unable to upload fpga "
+					"firmware: fw urb.\n");
+			return ret;
+		}
+	}
+	release_firmware(fw);
+	kfree(buffer);
+
+	ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
+				"end urb.\n");
+		return ret;
+	}
+	return 0;
+}
+
+int usb6fire_fw_init(struct usb_interface *intf)
+{
+	int i;
+	int ret;
+	struct usb_device *device = interface_to_usbdev(intf);
+	/* buffer: 8 receiving bytes from device and
+	 * sizeof(EP_W_MAX_PACKET_SIZE) bytes for non-const copy */
+	u8 buffer[12];
+
+	ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "unable to receive device "
+				"firmware state.\n");
+		return ret;
+	}
+	if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55
+			|| buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7]
+			!= 0x00) {
+		snd_printk(KERN_ERR PREFIX "unknown device firmware state "
+				"received from device: ");
+		for (i = 0; i < 8; i++)
+			snd_printk("%02x ", buffer[i]);
+		snd_printk("\n");
+		return -EIO;
+	}
+	/* do we need fpga loader ezusb firmware? */
+	if (buffer[3] == 0x01 && buffer[6] == 0x19) {
+		ret = usb6fire_fw_ezusb_upload(intf,
+				"6fire/dmx6firel2.ihx", 0, NULL, 0);
+		if (ret < 0)
+			return ret;
+		return FW_NOT_READY;
+	}
+	/* do we need fpga firmware and application ezusb firmware? */
+	else if (buffer[3] == 0x02 && buffer[6] == 0x0b) {
+		ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
+		if (ret < 0)
+			return ret;
+		memcpy(buffer, ep_w_max_packet_size,
+				sizeof(ep_w_max_packet_size));
+		ret = usb6fire_fw_ezusb_upload(intf, "6fire/dmx6fireap.ihx",
+				0x0003,	buffer, sizeof(ep_w_max_packet_size));
+		if (ret < 0)
+			return ret;
+		return FW_NOT_READY;
+	}
+	/* all fw loaded? */
+	else if (buffer[3] == 0x03 && buffer[6] == 0x0b)
+		return 0;
+	/* unknown data? */
+	else {
+		snd_printk(KERN_ERR PREFIX "unknown device firmware state "
+				"received from device: ");
+		for (i = 0; i < 8; i++)
+			snd_printk("%02x ", buffer[i]);
+		snd_printk("\n");
+		return -EIO;
+	}
+	return 0;
+}
+
diff --git a/sound/usb/6fire/firmware.h b/sound/usb/6fire/firmware.h
new file mode 100644
index 0000000..0085698
--- /dev/null
+++ b/sound/usb/6fire/firmware.h
@@ -0,0 +1,27 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author: Torsten Schenk
+ * Created: Jan 01, 2011
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_FIRMWARE_H
+#define USB6FIRE_FIRMWARE_H
+
+#include "common.h"
+
+enum /* firmware state of device */
+{
+	FW_READY = 0,
+	FW_NOT_READY = 1
+};
+
+int __devinit usb6fire_fw_init(struct usb_interface *intf);
+#endif /* USB6FIRE_FIRMWARE_H */
+
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
new file mode 100644
index 0000000..13f4509
--- /dev/null
+++ b/sound/usb/6fire/midi.c
@@ -0,0 +1,203 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Rawmidi driver
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <sound/rawmidi.h>
+
+#include "midi.h"
+#include "chip.h"
+#include "comm.h"
+
+static void usb6fire_midi_out_handler(struct urb *urb)
+{
+	struct midi_runtime *rt = urb->context;
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->out_lock, flags);
+
+	if (rt->out) {
+		ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4,
+				MIDI_BUFSIZE - 4);
+		if (ret > 0) { /* more data available, send next packet */
+			rt->out_buffer[1] = ret + 2;
+			rt->out_buffer[3] = rt->out_serial++;
+			urb->transfer_buffer_length = ret + 4;
+
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret < 0)
+				snd_printk(KERN_ERR PREFIX "midi out urb "
+						"submit failed: %d\n", ret);
+		} else /* no more data to transmit */
+			rt->out = NULL;
+	}
+	spin_unlock_irqrestore(&rt->out_lock, flags);
+}
+
+static void usb6fire_midi_in_received(
+		struct midi_runtime *rt, u8 *data, int length)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->in_lock, flags);
+	if (rt->in)
+		snd_rawmidi_receive(rt->in, data, length);
+	spin_unlock_irqrestore(&rt->in_lock, flags);
+}
+
+static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static int usb6fire_midi_out_close(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static void usb6fire_midi_out_trigger(
+		struct snd_rawmidi_substream *alsa_sub, int up)
+{
+	struct midi_runtime *rt = alsa_sub->rmidi->private_data;
+	struct urb *urb = &rt->out_urb;
+	__s8 ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->out_lock, flags);
+	if (up) { /* start transfer */
+		if (rt->out) { /* we are already transmitting so just return */
+			spin_unlock_irqrestore(&rt->out_lock, flags);
+			return;
+		}
+
+		ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4,
+				MIDI_BUFSIZE - 4);
+		if (ret > 0) {
+			rt->out_buffer[1] = ret + 2;
+			rt->out_buffer[3] = rt->out_serial++;
+			urb->transfer_buffer_length = ret + 4;
+
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret < 0)
+				snd_printk(KERN_ERR PREFIX "midi out urb "
+						"submit failed: %d\n", ret);
+			else
+				rt->out = alsa_sub;
+		}
+	} else if (rt->out == alsa_sub)
+		rt->out = NULL;
+	spin_unlock_irqrestore(&rt->out_lock, flags);
+}
+
+static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub)
+{
+	struct midi_runtime *rt = alsa_sub->rmidi->private_data;
+	int retry = 0;
+
+	while (rt->out && retry++ < 100)
+		msleep(10);
+}
+
+static int usb6fire_midi_in_open(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static int usb6fire_midi_in_close(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static void usb6fire_midi_in_trigger(
+		struct snd_rawmidi_substream *alsa_sub, int up)
+{
+	struct midi_runtime *rt = alsa_sub->rmidi->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->in_lock, flags);
+	if (up)
+		rt->in = alsa_sub;
+	else
+		rt->in = NULL;
+	spin_unlock_irqrestore(&rt->in_lock, flags);
+}
+
+static struct snd_rawmidi_ops out_ops = {
+	.open = usb6fire_midi_out_open,
+	.close = usb6fire_midi_out_close,
+	.trigger = usb6fire_midi_out_trigger,
+	.drain = usb6fire_midi_out_drain
+};
+
+static struct snd_rawmidi_ops in_ops = {
+	.open = usb6fire_midi_in_open,
+	.close = usb6fire_midi_in_close,
+	.trigger = usb6fire_midi_in_trigger
+};
+
+int __devinit usb6fire_midi_init(struct sfire_chip *chip)
+{
+	int ret;
+	struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime),
+			GFP_KERNEL);
+	struct comm_runtime *comm_rt = chip->comm;
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->chip = chip;
+	rt->in_received = usb6fire_midi_in_received;
+	rt->out_buffer[0] = 0x80; /* 'send midi' command */
+	rt->out_buffer[1] = 0x00; /* size of data */
+	rt->out_buffer[2] = 0x00; /* always 0 */
+	spin_lock_init(&rt->in_lock);
+	spin_lock_init(&rt->out_lock);
+
+	comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt,
+			usb6fire_midi_out_handler);
+
+	ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
+	if (ret < 0) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
+		return ret;
+	}
+	rt->instance->private_data = rt;
+	strcpy(rt->instance->name, "DMX6FireUSB MIDI");
+	rt->instance->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+			SNDRV_RAWMIDI_INFO_INPUT |
+			SNDRV_RAWMIDI_INFO_DUPLEX;
+	snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_OUTPUT,
+			&out_ops);
+	snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_INPUT,
+			&in_ops);
+
+	chip->midi = rt;
+	return 0;
+}
+
+void usb6fire_midi_abort(struct sfire_chip *chip)
+{
+	struct midi_runtime *rt = chip->midi;
+
+	if (rt)
+		usb_poison_urb(&rt->out_urb);
+}
+
+void usb6fire_midi_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->midi);
+	chip->midi = NULL;
+}
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
new file mode 100644
index 0000000..97a7bf6
--- /dev/null
+++ b/sound/usb/6fire/midi.h
@@ -0,0 +1,46 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_MIDI_H
+#define USB6FIRE_MIDI_H
+
+#include "common.h"
+
+enum {
+	MIDI_BUFSIZE = 64
+};
+
+struct midi_runtime {
+	struct sfire_chip *chip;
+	struct snd_rawmidi *instance;
+
+	struct snd_rawmidi_substream *in;
+	char in_active;
+
+	spinlock_t in_lock;
+	spinlock_t out_lock;
+	struct snd_rawmidi_substream *out;
+	struct urb out_urb;
+	u8 out_serial; /* serial number of out packet */
+	u8 out_buffer[MIDI_BUFSIZE];
+	int buffer_offset;
+
+	void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
+};
+
+int __devinit usb6fire_midi_init(struct sfire_chip *chip);
+void usb6fire_midi_abort(struct sfire_chip *chip);
+void usb6fire_midi_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_MIDI_H */
+
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
new file mode 100644
index 0000000..ba62c74
--- /dev/null
+++ b/sound/usb/6fire/pcm.c
@@ -0,0 +1,688 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * PCM driver
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "pcm.h"
+#include "chip.h"
+#include "comm.h"
+
+enum {
+	OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
+};
+
+/* keep next two synced with
+ * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */
+static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 };
+static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
+static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
+static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
+static const int rates_alsaid[] = {
+	SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
+	SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
+	SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 };
+
+/* values to write to soundcard register for all samplerates */
+static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
+
+enum { /* settings for pcm */
+	OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
+};
+
+enum { /* pcm streaming states */
+	STREAM_DISABLED, /* no pcm streaming */
+	STREAM_STARTING, /* pcm streaming requested, waiting to become ready */
+	STREAM_RUNNING, /* pcm streaming running */
+	STREAM_STOPPING
+};
+
+enum { /* pcm sample rates (also index into RATES_XXX[]) */
+	RATE_44KHZ,
+	RATE_48KHZ,
+	RATE_88KHZ,
+	RATE_96KHZ,
+	RATE_176KHZ,
+	RATE_192KHZ
+};
+
+static const struct snd_pcm_hardware pcm_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_BATCH,
+
+	.formats = SNDRV_PCM_FMTBIT_S24_LE,
+
+	.rates = SNDRV_PCM_RATE_44100 |
+		SNDRV_PCM_RATE_48000 |
+		SNDRV_PCM_RATE_88200 |
+		SNDRV_PCM_RATE_96000 |
+		SNDRV_PCM_RATE_176400 |
+		SNDRV_PCM_RATE_192000,
+
+	.rate_min = 44100,
+	.rate_max = 192000,
+	.channels_min = 1,
+	.channels_max = 0, /* set in pcm_open, depending on capture/playback */
+	.buffer_bytes_max = MAX_BUFSIZE,
+	.period_bytes_min = PCM_N_PACKETS_PER_URB * (PCM_MAX_PACKET_SIZE - 4),
+	.period_bytes_max = MAX_BUFSIZE,
+	.periods_min = 2,
+	.periods_max = 1024
+};
+
+static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
+{
+	int ret;
+	struct usb_device *device = rt->chip->dev;
+	struct comm_runtime *comm_rt = rt->chip->comm;
+
+	if (rt->rate >= ARRAY_SIZE(rates))
+		return -EINVAL;
+	/* disable streaming */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error stopping streaming while "
+				"setting samplerate %d.\n", rates[rt->rate]);
+		return ret;
+	}
+
+	ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error setting interface "
+				"altsetting %d for samplerate %d.\n",
+				rates_altsetting[rt->rate], rates[rt->rate]);
+		return ret;
+	}
+
+	/* set soundcard clock */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate],
+			rates_6fire_vh[rt->rate]);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
+				rates[rt->rate]);
+		return ret;
+	}
+
+	/* enable analog inputs and outputs
+	 * (one bit per stereo-channel) */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x02,
+			(1 << (OUT_N_CHANNELS / 2)) - 1,
+			(1 << (IN_N_CHANNELS / 2)) - 1);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error initializing analog channels "
+				"while setting samplerate %d.\n",
+				rates[rt->rate]);
+		return ret;
+	}
+	/* disable digital inputs and outputs */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error initializing digital "
+				"channels while setting samplerate %d.\n",
+				rates[rt->rate]);
+		return ret;
+	}
+
+	ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error starting streaming while "
+				"setting samplerate %d.\n", rates[rt->rate]);
+		return ret;
+	}
+
+	rt->in_n_analog = IN_N_CHANNELS;
+	rt->out_n_analog = OUT_N_CHANNELS;
+	rt->in_packet_size = rates_in_packet_size[rt->rate];
+	rt->out_packet_size = rates_out_packet_size[rt->rate];
+	return 0;
+}
+
+static struct pcm_substream *usb6fire_pcm_get_substream(
+		struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+
+	if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return &rt->playback;
+	else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE)
+		return &rt->capture;
+	snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n");
+	return NULL;
+}
+
+/* call with stream_mutex locked */
+static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
+{
+	int i;
+
+	if (rt->stream_state != STREAM_DISABLED) {
+		for (i = 0; i < PCM_N_URBS; i++) {
+			usb_kill_urb(&rt->in_urbs[i].instance);
+			usb_kill_urb(&rt->out_urbs[i].instance);
+		}
+		rt->stream_state = STREAM_DISABLED;
+	}
+}
+
+/* call with stream_mutex locked */
+static int usb6fire_pcm_stream_start(struct pcm_runtime *rt)
+{
+	int ret;
+	int i;
+	int k;
+	struct usb_iso_packet_descriptor *packet;
+
+	if (rt->stream_state == STREAM_DISABLED) {
+		/* submit our in urbs */
+		rt->stream_wait_cond = false;
+		rt->stream_state = STREAM_STARTING;
+		for (i = 0; i < PCM_N_URBS; i++) {
+			for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) {
+				packet = &rt->in_urbs[i].packets[k];
+				packet->offset = k * rt->in_packet_size;
+				packet->length = rt->in_packet_size;
+				packet->actual_length = 0;
+				packet->status = 0;
+			}
+			ret = usb_submit_urb(&rt->in_urbs[i].instance,
+					GFP_ATOMIC);
+			if (ret) {
+				usb6fire_pcm_stream_stop(rt);
+				return ret;
+			}
+		}
+
+		/* wait for first out urb to return (sent in in urb handler) */
+		wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
+				HZ);
+		if (rt->stream_wait_cond)
+			rt->stream_state = STREAM_RUNNING;
+		else {
+			usb6fire_pcm_stream_stop(rt);
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* call with substream locked */
+static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
+{
+	int i;
+	int frame;
+	int frame_count;
+	unsigned int total_length = 0;
+	struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
+	struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
+	u32 *src = (u32 *) urb->buffer;
+	u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
+			* (alsa_rt->frame_bits >> 3));
+	u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
+			* (alsa_rt->frame_bits >> 3));
+	int bytes_per_frame = alsa_rt->channels << 2;
+
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
+		/* at least 4 header bytes for valid packet.
+		 * after that: 32 bits per sample for analog channels */
+		if (urb->packets[i].actual_length > 4)
+			frame_count = (urb->packets[i].actual_length - 4)
+					/ (rt->in_n_analog << 2);
+		else
+			frame_count = 0;
+
+		src = (u32 *) (urb->buffer + total_length);
+		src++; /* skip leading 4 bytes of every packet */
+		total_length += urb->packets[i].length;
+		for (frame = 0; frame < frame_count; frame++) {
+			memcpy(dest, src, bytes_per_frame);
+			dest += alsa_rt->channels;
+			src += rt->in_n_analog;
+			sub->dma_off++;
+			sub->period_off++;
+			if (dest == dest_end) {
+				sub->dma_off = 0;
+				dest = (u32 *) alsa_rt->dma_area;
+			}
+		}
+	}
+}
+
+/* call with substream locked */
+static void usb6fire_pcm_playback(struct pcm_substream *sub,
+		struct pcm_urb *urb)
+{
+	int i;
+	int frame;
+	int frame_count;
+	struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
+	struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
+	u32 *src = (u32 *) (alsa_rt->dma_area + sub->dma_off
+			* (alsa_rt->frame_bits >> 3));
+	u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
+			* (alsa_rt->frame_bits >> 3));
+	u32 *dest = (u32 *) urb->buffer;
+	int bytes_per_frame = alsa_rt->channels << 2;
+
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
+		/* at least 4 header bytes for valid packet.
+		 * after that: 32 bits per sample for analog channels */
+		if (urb->packets[i].length > 4)
+			frame_count = (urb->packets[i].length - 4)
+					/ (rt->out_n_analog << 2);
+		else
+			frame_count = 0;
+		dest++; /* skip leading 4 bytes of every frame */
+		for (frame = 0; frame < frame_count; frame++) {
+			memcpy(dest, src, bytes_per_frame);
+			src += alsa_rt->channels;
+			dest += rt->out_n_analog;
+			sub->dma_off++;
+			sub->period_off++;
+			if (src == src_end) {
+				src = (u32 *) alsa_rt->dma_area;
+				sub->dma_off = 0;
+			}
+		}
+	}
+}
+
+static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
+{
+	struct pcm_urb *in_urb = usb_urb->context;
+	struct pcm_urb *out_urb = in_urb->peer;
+	struct pcm_runtime *rt = in_urb->chip->pcm;
+	struct pcm_substream *sub;
+	unsigned long flags;
+	int total_length = 0;
+	int frame_count;
+	int frame;
+	int channel;
+	int i;
+	u8 *dest;
+
+	if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING)
+		return;
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
+		if (in_urb->packets[i].status) {
+			rt->panic = true;
+			return;
+		}
+
+	if (rt->stream_state == STREAM_DISABLED) {
+		snd_printk(KERN_ERR PREFIX "internal error: "
+				"stream disabled in in-urb handler.\n");
+		return;
+	}
+
+	/* receive our capture data */
+	sub = &rt->capture;
+	spin_lock_irqsave(&sub->lock, flags);
+	if (sub->active) {
+		usb6fire_pcm_capture(sub, in_urb);
+		if (sub->period_off >= sub->instance->runtime->period_size) {
+			sub->period_off %= sub->instance->runtime->period_size;
+			spin_unlock_irqrestore(&sub->lock, flags);
+			snd_pcm_period_elapsed(sub->instance);
+		} else
+			spin_unlock_irqrestore(&sub->lock, flags);
+	} else
+		spin_unlock_irqrestore(&sub->lock, flags);
+
+	/* setup out urb structure */
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
+		out_urb->packets[i].offset = total_length;
+		out_urb->packets[i].length = (in_urb->packets[i].actual_length
+				- 4) / (rt->in_n_analog << 2)
+				* (rt->out_n_analog << 2) + 4;
+		out_urb->packets[i].status = 0;
+		total_length += out_urb->packets[i].length;
+	}
+	memset(out_urb->buffer, 0, total_length);
+
+	/* now send our playback data (if a free out urb was found) */
+	sub = &rt->playback;
+	spin_lock_irqsave(&sub->lock, flags);
+	if (sub->active) {
+		usb6fire_pcm_playback(sub, out_urb);
+		if (sub->period_off >= sub->instance->runtime->period_size) {
+			sub->period_off %= sub->instance->runtime->period_size;
+			spin_unlock_irqrestore(&sub->lock, flags);
+			snd_pcm_period_elapsed(sub->instance);
+		} else
+			spin_unlock_irqrestore(&sub->lock, flags);
+	} else
+		spin_unlock_irqrestore(&sub->lock, flags);
+
+	/* setup the 4th byte of each sample (0x40 for analog channels) */
+	dest = out_urb->buffer;
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
+		if (out_urb->packets[i].length >= 4) {
+			frame_count = (out_urb->packets[i].length - 4)
+					/ (rt->out_n_analog << 2);
+			*(dest++) = 0xaa;
+			*(dest++) = 0xaa;
+			*(dest++) = frame_count;
+			*(dest++) = 0x00;
+			for (frame = 0; frame < frame_count; frame++)
+				for (channel = 0;
+						channel < rt->out_n_analog;
+						channel++) {
+					dest += 3; /* skip sample data */
+					*(dest++) = 0x40;
+				}
+		}
+	usb_submit_urb(&out_urb->instance, GFP_ATOMIC);
+	usb_submit_urb(&in_urb->instance, GFP_ATOMIC);
+}
+
+static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb)
+{
+	struct pcm_urb *urb = usb_urb->context;
+	struct pcm_runtime *rt = urb->chip->pcm;
+
+	if (rt->stream_state == STREAM_STARTING) {
+		rt->stream_wait_cond = true;
+		wake_up(&rt->stream_wait_queue);
+	}
+}
+
+static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	struct pcm_substream *sub = NULL;
+	struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
+
+	if (rt->panic)
+		return -EPIPE;
+
+	mutex_lock(&rt->stream_mutex);
+	alsa_rt->hw = pcm_hw;
+
+	if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (rt->rate >= 0)
+			alsa_rt->hw.rates = rates_alsaid[rt->rate];
+		alsa_rt->hw.channels_max = OUT_N_CHANNELS;
+		sub = &rt->playback;
+	} else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (rt->rate >= 0)
+			alsa_rt->hw.rates = rates_alsaid[rt->rate];
+		alsa_rt->hw.channels_max = IN_N_CHANNELS;
+		sub = &rt->capture;
+	}
+
+	if (!sub) {
+		mutex_unlock(&rt->stream_mutex);
+		snd_printk(KERN_ERR PREFIX "invalid stream type.\n");
+		return -EINVAL;
+	}
+
+	sub->instance = alsa_sub;
+	sub->active = false;
+	mutex_unlock(&rt->stream_mutex);
+	return 0;
+}
+
+static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	unsigned long flags;
+
+	if (rt->panic)
+		return 0;
+
+	mutex_lock(&rt->stream_mutex);
+	if (sub) {
+		/* deactivate substream */
+		spin_lock_irqsave(&sub->lock, flags);
+		sub->instance = NULL;
+		sub->active = false;
+		spin_unlock_irqrestore(&sub->lock, flags);
+
+		/* all substreams closed? if so, stop streaming */
+		if (!rt->playback.instance && !rt->capture.instance) {
+			usb6fire_pcm_stream_stop(rt);
+			rt->rate = -1;
+		}
+	}
+	mutex_unlock(&rt->stream_mutex);
+	return 0;
+}
+
+static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
+		struct snd_pcm_hw_params *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(alsa_sub,
+			params_buffer_bytes(hw_params));
+}
+
+static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
+{
+	return snd_pcm_lib_free_pages(alsa_sub);
+}
+
+static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
+	int i;
+	int ret;
+
+	if (rt->panic)
+		return -EPIPE;
+	if (!sub)
+		return -ENODEV;
+
+	mutex_lock(&rt->stream_mutex);
+	sub->dma_off = 0;
+	sub->period_off = 0;
+
+	if (rt->stream_state == STREAM_DISABLED) {
+		for (i = 0; i < ARRAY_SIZE(rates); i++)
+			if (alsa_rt->rate == rates[i]) {
+				rt->rate = i;
+				break;
+			}
+		if (i == ARRAY_SIZE(rates)) {
+			mutex_unlock(&rt->stream_mutex);
+			snd_printk("invalid rate %d in prepare.\n",
+					alsa_rt->rate);
+			return -EINVAL;
+		}
+
+		ret = usb6fire_pcm_set_rate(rt);
+		if (ret) {
+			mutex_unlock(&rt->stream_mutex);
+			return ret;
+		}
+		ret = usb6fire_pcm_stream_start(rt);
+		if (ret) {
+			mutex_unlock(&rt->stream_mutex);
+			snd_printk(KERN_ERR PREFIX
+					"could not start pcm stream.\n");
+			return ret;
+		}
+	}
+	mutex_unlock(&rt->stream_mutex);
+	return 0;
+}
+
+static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd)
+{
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	unsigned long flags;
+
+	if (rt->panic)
+		return -EPIPE;
+	if (!sub)
+		return -ENODEV;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		spin_lock_irqsave(&sub->lock, flags);
+		sub->active = true;
+		spin_unlock_irqrestore(&sub->lock, flags);
+		return 0;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		spin_lock_irqsave(&sub->lock, flags);
+		sub->active = false;
+		spin_unlock_irqrestore(&sub->lock, flags);
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static snd_pcm_uframes_t usb6fire_pcm_pointer(
+		struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	unsigned long flags;
+	snd_pcm_uframes_t ret;
+
+	if (rt->panic || !sub)
+		return SNDRV_PCM_STATE_XRUN;
+
+	spin_lock_irqsave(&sub->lock, flags);
+	ret = sub->dma_off;
+	spin_unlock_irqrestore(&sub->lock, flags);
+	return ret;
+}
+
+static struct snd_pcm_ops pcm_ops = {
+	.open = usb6fire_pcm_open,
+	.close = usb6fire_pcm_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = usb6fire_pcm_hw_params,
+	.hw_free = usb6fire_pcm_hw_free,
+	.prepare = usb6fire_pcm_prepare,
+	.trigger = usb6fire_pcm_trigger,
+	.pointer = usb6fire_pcm_pointer,
+};
+
+static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
+		struct sfire_chip *chip, bool in, int ep,
+		void (*handler)(struct urb *))
+{
+	urb->chip = chip;
+	usb_init_urb(&urb->instance);
+	urb->instance.transfer_buffer = urb->buffer;
+	urb->instance.transfer_buffer_length =
+			PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE;
+	urb->instance.dev = chip->dev;
+	urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep)
+			: usb_sndisocpipe(chip->dev, ep);
+	urb->instance.interval = 1;
+	urb->instance.transfer_flags = URB_ISO_ASAP;
+	urb->instance.complete = handler;
+	urb->instance.context = urb;
+	urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
+}
+
+int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
+{
+	int i;
+	int ret;
+	struct snd_pcm *pcm;
+	struct pcm_runtime *rt =
+			kzalloc(sizeof(struct pcm_runtime), GFP_KERNEL);
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->chip = chip;
+	rt->stream_state = STREAM_DISABLED;
+	rt->rate = -1;
+	init_waitqueue_head(&rt->stream_wait_queue);
+	mutex_init(&rt->stream_mutex);
+
+	spin_lock_init(&rt->playback.lock);
+	spin_lock_init(&rt->capture.lock);
+
+	for (i = 0; i < PCM_N_URBS; i++) {
+		usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP,
+				usb6fire_pcm_in_urb_handler);
+		usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP,
+				usb6fire_pcm_out_urb_handler);
+
+		rt->in_urbs[i].peer = &rt->out_urbs[i];
+		rt->out_urbs[i].peer = &rt->in_urbs[i];
+	}
+
+	ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
+	if (ret < 0) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
+		return ret;
+	}
+
+	pcm->private_data = rt;
+	strcpy(pcm->name, "DMX 6Fire USB");
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
+
+	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
+			SNDRV_DMA_TYPE_CONTINUOUS,
+			snd_dma_continuous_data(GFP_KERNEL),
+			MAX_BUFSIZE, MAX_BUFSIZE);
+	if (ret) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX
+				"error preallocating pcm buffers.\n");
+		return ret;
+	}
+	rt->instance = pcm;
+
+	chip->pcm = rt;
+	return 0;
+}
+
+void usb6fire_pcm_abort(struct sfire_chip *chip)
+{
+	struct pcm_runtime *rt = chip->pcm;
+	int i;
+
+	if (rt) {
+		rt->panic = true;
+
+		if (rt->playback.instance)
+			snd_pcm_stop(rt->playback.instance,
+					SNDRV_PCM_STATE_XRUN);
+		if (rt->capture.instance)
+			snd_pcm_stop(rt->capture.instance,
+					SNDRV_PCM_STATE_XRUN);
+
+		for (i = 0; i < PCM_N_URBS; i++) {
+			usb_poison_urb(&rt->in_urbs[i].instance);
+			usb_poison_urb(&rt->out_urbs[i].instance);
+		}
+
+	}
+}
+
+void usb6fire_pcm_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->pcm);
+	chip->pcm = NULL;
+}
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
new file mode 100644
index 0000000..2bee813
--- /dev/null
+++ b/sound/usb/6fire/pcm.h
@@ -0,0 +1,76 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 USB6FIRE_PCM_H
+#define USB6FIRE_PCM_H
+
+#include <sound/pcm.h>
+#include <linux/mutex.h>
+
+#include "common.h"
+
+enum /* settings for pcm */
+{
+	/* maximum of EP_W_MAX_PACKET_SIZE[] (see firmware.c) */
+	PCM_N_URBS = 16, PCM_N_PACKETS_PER_URB = 8, PCM_MAX_PACKET_SIZE = 604
+};
+
+struct pcm_urb {
+	struct sfire_chip *chip;
+
+	/* BEGIN DO NOT SEPARATE */
+	struct urb instance;
+	struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB];
+	/* END DO NOT SEPARATE */
+	u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE];
+
+	struct pcm_urb *peer;
+};
+
+struct pcm_substream {
+	spinlock_t lock;
+	struct snd_pcm_substream *instance;
+
+	bool active;
+
+	snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */
+	snd_pcm_uframes_t period_off; /* current position in current period */
+};
+
+struct pcm_runtime {
+	struct sfire_chip *chip;
+	struct snd_pcm *instance;
+
+	struct pcm_substream playback;
+	struct pcm_substream capture;
+	bool panic; /* if set driver won't do anymore pcm on device */
+
+	struct pcm_urb in_urbs[PCM_N_URBS];
+	struct pcm_urb out_urbs[PCM_N_URBS];
+	int in_packet_size;
+	int out_packet_size;
+	int in_n_analog; /* number of analog channels soundcard sends */
+	int out_n_analog; /* number of analog channels soundcard receives */
+
+	struct mutex stream_mutex;
+	u8 stream_state; /* one of STREAM_XXX (pcm.c) */
+	u8 rate; /* one of PCM_RATE_XXX */
+	wait_queue_head_t stream_wait_queue;
+	bool stream_wait_cond;
+};
+
+int __devinit usb6fire_pcm_init(struct sfire_chip *chip);
+void usb6fire_pcm_abort(struct sfire_chip *chip);
+void usb6fire_pcm_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_PCM_H */
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 112984f..97724d8 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -62,6 +62,7 @@ config SND_USB_CAIAQ
 	    * Native Instruments Audio 2 DJ
 	    * Native Instruments Audio 4 DJ
 	    * Native Instruments Audio 8 DJ
+	    * Native Instruments Traktor Audio 2
 	    * Native Instruments Guitar Rig Session I/O
 	    * Native Instruments Guitar Rig mobile
 	    * Native Instruments Traktor Kontrol X1
@@ -97,5 +98,21 @@ config SND_USB_US122L
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-us122l.
 
+config SND_USB_6FIRE
+        tristate "TerraTec DMX 6Fire USB"
+        depends on EXPERIMENTAL
+        select FW_LOADER
+        select SND_RAWMIDI
+        select SND_PCM
+        help
+          Say Y here to include support for TerraTec 6fire DMX USB interface.
+
+          You will need firmware files in order to be able to use the device
+          after it has been coldstarted. This driver currently does not support
+          firmware loading for all devices. If you own such a device,
+          you could start windows and let the windows driver upload
+          the firmware. As long as you do not unplug your device from power,
+          it should be usable.
+
 endif	# SND_USB
 
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index 1e362bf..cf9ed66 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
 
-obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/
+obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 66eabaf..d0d493c 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -805,6 +805,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
 	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;
 		break;
 	}
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 6480c32..45bc4a2 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -46,6 +46,7 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, Audio 2 DJ},"
 			 "{Native Instruments, Audio 4 DJ},"
 			 "{Native Instruments, Audio 8 DJ},"
+			 "{Native Instruments, Traktor Audio 2},"
 			 "{Native Instruments, Session I/O},"
 			 "{Native Instruments, GuitarRig mobile}"
 			 "{Native Instruments, Traktor Kontrol X1}"
@@ -140,6 +141,11 @@ static struct usb_device_id snd_usb_id_table[] = {
 		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
 		.idProduct =    USB_PID_TRAKTORKONTROLS4
 	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_TRAKTORAUDIO2
+	},
 	{ /* terminator */ }
 };
 
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index e3d8a3e..b2b3101 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -17,6 +17,7 @@
 #define USB_PID_GUITARRIGMOBILE		0x0d8d
 #define USB_PID_TRAKTORKONTROLX1	0x2305
 #define USB_PID_TRAKTORKONTROLS4	0xbaff
+#define USB_PID_TRAKTORAUDIO2		0x041d
 
 #define EP1_BUFSIZE 64
 #define EP4_BUFSIZE 512
diff --git a/sound/usb/card.c b/sound/usb/card.c
index c0f8270..a90662a 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -41,6 +41,7 @@
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/ctype.h>
 #include <linux/usb.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
@@ -65,6 +66,7 @@
 #include "pcm.h"
 #include "urb.h"
 #include "format.h"
+#include "power.h"
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
@@ -282,6 +284,15 @@ static int snd_usb_audio_dev_free(struct snd_device *device)
 	return snd_usb_audio_free(chip);
 }
 
+static void remove_trailing_spaces(char *str)
+{
+	char *p;
+
+	if (!*str)
+		return;
+	for (p = str + strlen(str) - 1; p >= str && isspace(*p); p--)
+		*p = 0;
+}
 
 /*
  * create a chip instance and set its names.
@@ -330,6 +341,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 	chip->setup = device_setup[idx];
 	chip->nrpacks = nrpacks;
 	chip->async_unlink = async_unlink;
+	chip->probing = 1;
 
 	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 			      le16_to_cpu(dev->descriptor.idProduct));
@@ -349,7 +361,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 	snd_component_add(card, component);
 
 	/* retrieve the device string as shortname */
-	if (quirk && quirk->product_name) {
+	if (quirk && quirk->product_name && *quirk->product_name) {
 		strlcpy(card->shortname, quirk->product_name, sizeof(card->shortname));
 	} else {
 		if (!dev->descriptor.iProduct ||
@@ -361,9 +373,10 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 				USB_ID_PRODUCT(chip->usb_id));
 		}
 	}
+	remove_trailing_spaces(card->shortname);
 
 	/* retrieve the vendor and device strings as longname */
-	if (quirk && quirk->vendor_name) {
+	if (quirk && quirk->vendor_name && *quirk->vendor_name) {
 		len = strlcpy(card->longname, quirk->vendor_name, sizeof(card->longname));
 	} else {
 		if (dev->descriptor.iManufacturer)
@@ -373,8 +386,11 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 			len = 0;
 		/* we don't really care if there isn't any vendor string */
 	}
-	if (len > 0)
-		strlcat(card->longname, " ", sizeof(card->longname));
+	if (len > 0) {
+		remove_trailing_spaces(card->longname);
+		if (*card->longname)
+			strlcat(card->longname, " ", sizeof(card->longname));
+	}
 
 	strlcat(card->longname, card->shortname, sizeof(card->longname));
 
@@ -451,6 +467,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 				goto __error;
 			}
 			chip = usb_chip[i];
+			chip->probing = 1;
 			break;
 		}
 	}
@@ -466,6 +483,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 					goto __error;
 				}
 				snd_card_set_dev(chip->card, &intf->dev);
+				chip->pm_intf = intf;
 				break;
 			}
 		if (!chip) {
@@ -505,6 +523,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 
 	usb_chip[chip->index] = chip;
 	chip->num_interfaces++;
+	chip->probing = 0;
 	mutex_unlock(&register_mutex);
 	return chip;
 
@@ -581,29 +600,61 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 }
 
 #ifdef CONFIG_PM
+
+int snd_usb_autoresume(struct snd_usb_audio *chip)
+{
+	int err = -ENODEV;
+
+	if (!chip->shutdown && !chip->probing)
+		err = usb_autopm_get_interface(chip->pm_intf);
+
+	return err;
+}
+
+void snd_usb_autosuspend(struct snd_usb_audio *chip)
+{
+	if (!chip->shutdown && !chip->probing)
+		usb_autopm_put_interface(chip->pm_intf);
+}
+
 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;
 
 	if (chip == (void *)-1L)
 		return 0;
 
-	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);
-			snd_pcm_suspend_all(as->pcm);
-		}
+	if (!(message.event & PM_EVENT_AUTO)) {
+		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);
+				snd_pcm_suspend_all(as->pcm);
+			}
+ 		}
+	} else {
+		/*
+		 * otherwise we keep the rest of the system in the dark
+		 * to keep this transparent
+		 */
+		if (!chip->num_suspended_intf++)
+			chip->autosuspended = 1;
 	}
 
+	list_for_each_entry(mixer, &chip->mixer_list, list)
+		snd_usb_mixer_inactivate(mixer);
+
 	return 0;
 }
 
 static int usb_audio_resume(struct usb_interface *intf)
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
+	struct usb_mixer_interface *mixer;
+	int err = 0;
 
 	if (chip == (void *)-1L)
 		return 0;
@@ -611,12 +662,20 @@ static int usb_audio_resume(struct usb_interface *intf)
 		return 0;
 	/*
 	 * ALSA leaves material resumption to user space
-	 * we just notify
+	 * we just notify and restart the mixers
 	 */
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+		err = snd_usb_mixer_activate(mixer);
+		if (err < 0)
+			goto err_out;
+	}
 
-	snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+	if (!chip->autosuspended)
+		snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+	chip->autosuspended = 0;
 
-	return 0;
+err_out:
+	return err;
 }
 #else
 #define usb_audio_suspend	NULL
@@ -644,6 +703,7 @@ static struct usb_driver usb_audio_driver = {
 	.suspend =	usb_audio_suspend,
 	.resume =	usb_audio_resume,
 	.id_table =	usb_audio_ids,
+	.supports_autosuspend = 1,
 };
 
 static int __init snd_usb_audio_init(void)
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index db2dc5f..b4b39c0 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -54,6 +54,7 @@
 #include <sound/asequencer.h>
 #include "usbaudio.h"
 #include "midi.h"
+#include "power.h"
 #include "helper.h"
 
 /*
@@ -1044,6 +1045,7 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
 	struct usbmidi_out_port* port = NULL;
 	int i, j;
+	int err;
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
 		if (umidi->endpoints[i].out)
@@ -1056,6 +1058,9 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 		snd_BUG();
 		return -ENXIO;
 	}
+	err = usb_autopm_get_interface(umidi->iface);
+	if (err < 0)
+		return -EIO;
 	substream->runtime->private_data = port;
 	port->state = STATE_UNKNOWN;
 	substream_open(substream, 1);
@@ -1064,7 +1069,10 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
+	struct snd_usb_midi* umidi = substream->rmidi->private_data;
+
 	substream_open(substream, 0);
+	usb_autopm_put_interface(umidi->iface);
 	return 0;
 }
 
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 85af605..5e47757 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -61,6 +61,7 @@
 #include "mixer.h"
 #include "helper.h"
 #include "mixer_quirks.h"
+#include "power.h"
 
 #define MAX_ID_ELEMS	256
 
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
 	unsigned char buf[2];
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int timeout = 10;
+	int err;
 
+	err = snd_usb_autoresume(cval->mixer->chip);
+	if (err < 0)
+		return -EIO;
 	while (timeout-- > 0) {
 		if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 				    buf, val_len, 100) >= val_len) {
 			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
+			snd_usb_autosuspend(cval->mixer->chip);
 			return 0;
 		}
 	}
+	snd_usb_autosuspend(cval->mixer->chip);
 	snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
 		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 	return -EINVAL;
@@ -328,12 +335,18 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
 
 	memset(buf, 0, sizeof(buf));
 
+	ret = snd_usb_autoresume(chip) ? -EIO : 0;
+	if (ret)
+		goto error;
+
 	ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
 			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 			      validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 			      buf, size, 1000);
+	snd_usb_autosuspend(chip);
 
 	if (ret < 0) {
+error:
 		snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
 			   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 		return ret;
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 {
 	struct snd_usb_audio *chip = cval->mixer->chip;
 	unsigned char buf[2];
-	int val_len, timeout = 10;
+	int val_len, err, timeout = 10;
 
 	if (cval->mixer->protocol == UAC_VERSION_1) {
 		val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 	value_set = convert_bytes_value(cval, value_set);
 	buf[0] = value_set & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
+	err = snd_usb_autoresume(chip);
+	if (err < 0)
+		return -EIO;
 	while (timeout-- > 0)
 		if (snd_usb_ctl_msg(chip->dev,
 				    usb_sndctrlpipe(chip->dev, 0), request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-				    buf, val_len, 100) >= 0)
+				    buf, val_len, 100) >= 0) {
+			snd_usb_autosuspend(chip);
 			return 0;
+		}
+	snd_usb_autosuspend(chip);
 	snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
 		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
 	return -EINVAL;
@@ -987,6 +1006,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 	struct snd_kcontrol *kctl;
 	struct usb_mixer_elem_info *cval;
 	const struct usbmix_name_map *map;
+	unsigned int range;
 
 	control++; /* change from zero-based to 1-based value */
 
@@ -1121,6 +1141,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 		}
 		break;
 
+	case USB_ID(0x046d, 0x0808):
 	case USB_ID(0x046d, 0x0809):
 	case USB_ID(0x046d, 0x0991):
 	/* Most audio usb devices lie about volume resolution.
@@ -1136,6 +1157,21 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 
 	}
 
+	range = (cval->max - cval->min) / cval->res;
+	/* Are there devices with volume range more than 255? I use a bit more
+	 * to be sure. 384 is a resolution magic number found on Logitech
+	 * devices. It will definitively catch all buggy Logitech devices.
+	 */
+	if (range > 384) {
+		snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big "
+			   "volume range (=%u), cval->res is probably wrong.",
+			   range);
+		snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, "
+			   "val = %d/%d/%d", cval->id,
+			   kctl->id.name, cval->channels,
+			   cval->min, cval->max, cval->res);
+	}
+
 	snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
 		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
 	add_control_to_empty(state, kctl);
@@ -2058,8 +2094,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
 {
 	struct usb_mixer_interface *mixer = urb->context;
 	int len = urb->actual_length;
+	int ustatus = urb->status;
 
-	if (urb->status != 0)
+	if (ustatus != 0)
 		goto requeue;
 
 	if (mixer->protocol == UAC_VERSION_1) {
@@ -2100,12 +2137,32 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
 	}
 
 requeue:
-	if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
+	if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) {
 		urb->dev = mixer->chip->dev;
 		usb_submit_urb(urb, GFP_ATOMIC);
 	}
 }
 
+/* stop any bus activity of a mixer */
+void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
+{
+	usb_kill_urb(mixer->urb);
+	usb_kill_urb(mixer->rc_urb);
+}
+
+int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
+{
+	int err;
+
+	if (mixer->urb) {
+		err = usb_submit_urb(mixer->urb, GFP_NOIO);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
 /* create the handler for the optional status interrupt endpoint */
 static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 {
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index 26c636c..b4a2c81 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -52,5 +52,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
 
 int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 				int request, int validx, int value_set);
+void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
+int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
 
 #endif /* __USBMIXER_H */
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 782f741..73dcc82 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -346,6 +346,141 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
 	return 0;
 }
 
+/* Native Instruments device quirks */
+
+#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
+
+static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	struct usb_device *dev = mixer->chip->dev;
+	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
+	u16 wIndex = kcontrol->private_value & 0xffff;
+	u8 tmp;
+
+	int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+				  0, cpu_to_le16(wIndex),
+				  &tmp, sizeof(tmp), 1000);
+
+	if (ret < 0) {
+		snd_printk(KERN_ERR
+			   "unable to issue vendor read request (ret = %d)", ret);
+		return ret;
+	}
+
+	ucontrol->value.integer.value[0] = tmp;
+
+	return 0;
+}
+
+static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	struct usb_device *dev = mixer->chip->dev;
+	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
+	u16 wIndex = kcontrol->private_value & 0xffff;
+	u16 wValue = ucontrol->value.integer.value[0];
+
+	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
+				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+				  cpu_to_le16(wValue), cpu_to_le16(wIndex),
+				  NULL, 0, 1000);
+
+	if (ret < 0) {
+		snd_printk(KERN_ERR
+			   "unable to issue vendor write request (ret = %d)", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
+	{
+		.name = "Direct Thru Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x03),
+	},
+	{
+		.name = "Direct Thru Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x05),
+	},
+	{
+		.name = "Phono Input Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x03),
+	},
+	{
+		.name = "Phono Input Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x05),
+	},
+};
+
+static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
+	{
+		.name = "Direct Thru Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x03),
+	},
+	{
+		.name = "Direct Thru Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x05),
+	},
+	{
+		.name = "Direct Thru Channel C",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x07),
+	},
+	{
+		.name = "Direct Thru Channel D",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x09),
+	},
+	{
+		.name = "Phono Input Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x03),
+	},
+	{
+		.name = "Phono Input Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x05),
+	},
+	{
+		.name = "Phono Input Channel C",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x07),
+	},
+	{
+		.name = "Phono Input Channel D",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x09),
+	},
+};
+
+static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
+					      const struct snd_kcontrol_new *kc,
+					      unsigned int count)
+{
+	int i, err = 0;
+	struct snd_kcontrol_new template = {
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.get = snd_nativeinstruments_control_get,
+		.put = snd_nativeinstruments_control_put,
+		.info = snd_ctl_boolean_mono_info,
+	};
+
+	for (i = 0; i < count; i++) {
+		struct snd_kcontrol *c;
+
+		template.name = kc[i].name;
+		template.private_value = kc[i].private_value;
+
+		c = snd_ctl_new1(&template, mixer);
+		err = snd_ctl_add(mixer->chip->card, c);
+
+		if (err < 0)
+			break;
+	}
+
+	return err;
+}
+
 void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 			       unsigned char samplerate_id)
 {
@@ -367,31 +502,44 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
 {
-	int err;
+	int err = 0;
 	struct snd_info_entry *entry;
 
 	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
 		return err;
 
-	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
-		if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
-			return err;
+	switch (mixer->chip->usb_id) {
+	case USB_ID(0x041e, 0x3020):
+	case USB_ID(0x041e, 0x3040):
+	case USB_ID(0x041e, 0x3042):
+	case USB_ID(0x041e, 0x3048):
+		err = snd_audigy2nx_controls_create(mixer);
+		if (err < 0)
+			break;
 		if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
 			snd_info_set_text_ops(entry, mixer,
 					      snd_audigy2nx_proc_read);
-	}
+		break;
 
-	if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) ||
-	    mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) {
+	case USB_ID(0x0b05, 0x1739):
+	case USB_ID(0x0b05, 0x1743):
 		err = snd_xonar_u1_controls_create(mixer);
-		if (err < 0)
-			return err;
+		break;
+
+	case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
+		err = snd_nativeinstruments_create_mixer(mixer,
+				snd_nativeinstruments_ta6_mixers,
+				ARRAY_SIZE(snd_nativeinstruments_ta6_mixers));
+		break;
+
+	case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */
+		err = snd_nativeinstruments_create_mixer(mixer,
+				snd_nativeinstruments_ta10_mixers,
+				ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
+		break;
 	}
 
-	return 0;
+	return err;
 }
 
 void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index e3f6805..b8dcbf4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -32,6 +32,7 @@
 #include "helper.h"
 #include "pcm.h"
 #include "clock.h"
+#include "power.h"
 
 /*
  * return the current pcm pointer.  just based on the hwptr_done value.
@@ -739,6 +740,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 		pt = 125 * (1 << fp->datainterval);
 		ptmin = min(ptmin, pt);
 	}
+	err = snd_usb_autoresume(subs->stream->chip);
+	if (err < 0)
+		return err;
 
 	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
 	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -756,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 				       SNDRV_PCM_HW_PARAM_CHANNELS,
 				       param_period_time_if_needed,
 				       -1)) < 0)
-		return err;
+		goto rep_err;
 	if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 				       hw_rule_channels, subs,
 				       SNDRV_PCM_HW_PARAM_FORMAT,
 				       SNDRV_PCM_HW_PARAM_RATE,
 				       param_period_time_if_needed,
 				       -1)) < 0)
-		return err;
+		goto rep_err;
 	if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
 				       hw_rule_format, subs,
 				       SNDRV_PCM_HW_PARAM_RATE,
 				       SNDRV_PCM_HW_PARAM_CHANNELS,
 				       param_period_time_if_needed,
 				       -1)) < 0)
-		return err;
+		goto rep_err;
 	if (param_period_time_if_needed >= 0) {
 		err = snd_pcm_hw_rule_add(runtime, 0,
 					  SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -780,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 					  SNDRV_PCM_HW_PARAM_RATE,
 					  -1);
 		if (err < 0)
-			return err;
+			goto rep_err;
 	}
 	if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
-		return err;
+		goto rep_err;
 	return 0;
+
+rep_err:
+	snd_usb_autosuspend(subs->stream->chip);
+	return err;
 }
 
 static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
@@ -798,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 	runtime->hw = snd_usb_hardware;
 	runtime->private_data = subs;
 	subs->pcm_substream = substream;
+	/* runtime PM is also done there */
 	return setup_hw_info(runtime, subs);
 }
 
@@ -811,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
 		subs->interface = -1;
 	}
 	subs->pcm_substream = NULL;
+	snd_usb_autosuspend(subs->stream->chip);
 	return 0;
 }
 
diff --git a/sound/usb/power.h b/sound/usb/power.h
new file mode 100644
index 0000000..48ee51d
--- /dev/null
+++ b/sound/usb/power.h
@@ -0,0 +1,17 @@
+#ifndef __USBAUDIO_POWER_H
+#define __USBAUDIO_POWER_H
+
+#ifdef CONFIG_PM
+int snd_usb_autoresume(struct snd_usb_audio *chip);
+void snd_usb_autosuspend(struct snd_usb_audio *chip);
+#else
+static inline int snd_usb_autoresume(struct snd_usb_audio *chip)
+{
+	return 0;
+}
+static inline void snd_usb_autosuspend(struct snd_usb_audio *chip)
+{
+}
+#endif
+
+#endif /* __USBAUDIO_POWER_H */
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 921a86f..c0dcfca 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2290,6 +2290,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 },
 
+/* Native Instruments MK2 series */
+{
+	/* Traktor Audio 6 */
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor = 0x17cc,
+	.idProduct = 0x1010,
+},
+{
+	/* Traktor Audio 10 */
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor = 0x17cc,
+	.idProduct = 0x1020,
+},
+
 /* Miditech devices */
 {
 	USB_DEVICE(0x4752, 0x0011),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e314cdb..355759b 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -425,6 +425,34 @@ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
 }
 
 /*
+ * Some sound cards from Native Instruments are in fact compliant to the USB
+ * audio standard of version 2 and other approved USB standards, even though
+ * they come up as vendor-specific device when first connected.
+ *
+ * However, they can be told to come up with a new set of descriptors
+ * upon their next enumeration, and the interfaces announced by the new
+ * descriptors will then be handled by the kernel's class drivers. As the
+ * product ID will also change, no further checks are required.
+ */
+
+static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
+{
+	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				  0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				  cpu_to_le16(1), 0, NULL, 0, 1000);
+
+	if (ret < 0)
+		return ret;
+
+	usb_reset_device(dev);
+
+	/* return -EAGAIN, so the creation of an audio interface for this
+	 * temporary device is aborted. The device will reconnect with a
+	 * new product ID */
+	return -EAGAIN;
+}
+
+/*
  * Setup quirks
  */
 #define AUDIOPHILE_SET			0x01 /* if set, parse device_setup */
@@ -489,27 +517,33 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 			le16_to_cpu(dev->descriptor.idProduct));
 
-	/* SB Extigy needs special boot-up sequence */
-	/* if more models come, this will go to the quirk list. */
-	if (id == USB_ID(0x041e, 0x3000))
+	switch (id) {
+	case USB_ID(0x041e, 0x3000):
+		/* SB Extigy needs special boot-up sequence */
+		/* if more models come, this will go to the quirk list. */
 		return snd_usb_extigy_boot_quirk(dev, intf);
 
-	/* SB Audigy 2 NX needs its own boot-up magic, too */
-	if (id == USB_ID(0x041e, 0x3020))
+	case USB_ID(0x041e, 0x3020):
+		/* SB Audigy 2 NX needs its own boot-up magic, too */
 		return snd_usb_audigy2nx_boot_quirk(dev);
 
-	/* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
-	if (id == USB_ID(0x10f5, 0x0200))
+	case USB_ID(0x10f5, 0x0200):
+		/* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
 		return snd_usb_cm106_boot_quirk(dev);
 
-	/* C-Media CM6206 / CM106-Like Sound Device */
-	if (id == USB_ID(0x0d8c, 0x0102))
+	case USB_ID(0x0d8c, 0x0102):
+		/* C-Media CM6206 / CM106-Like Sound Device */
 		return snd_usb_cm6206_boot_quirk(dev);
 
-	/* Access Music VirusTI Desktop */
-	if (id == USB_ID(0x133e, 0x0815))
+	case USB_ID(0x133e, 0x0815):
+		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
 
+	case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
+	case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
+		return snd_usb_nativeinstruments_boot_quirk(dev);
+	}
+
 	return 0;
 }
 
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 6e66fff..32f2a97 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -34,10 +34,14 @@ struct snd_usb_audio {
 	int index;
 	struct usb_device *dev;
 	struct snd_card *card;
+	struct usb_interface *pm_intf;
 	u32 usb_id;
-	int shutdown;
 	struct mutex shutdown_mutex;
+	unsigned int shutdown:1;
+	unsigned int probing:1;
+	unsigned int autosuspended:1;	
 	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
+	
 	int num_interfaces;
 	int num_suspended_intf;
 
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index cb43289..416684b 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -1,4 +1,3 @@
-PERF-BUILD-OPTIONS
 PERF-CFLAGS
 PERF-GUI-VARS
 PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile
index bd498d4..4626a39 100644
--- a/tools/perf/Documentation/Makefile
+++ b/tools/perf/Documentation/Makefile
@@ -178,8 +178,8 @@ install-pdf: pdf
 	$(INSTALL) -d -m 755 $(DESTDIR)$(pdfdir)
 	$(INSTALL) -m 644 user-manual.pdf $(DESTDIR)$(pdfdir)
 
-install-html: html
-	'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
+#install-html: html
+#	'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(DESTDIR)$(htmldir)
 
 ../PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
 	$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) PERF-VERSION-FILE
@@ -288,15 +288,16 @@ $(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
 	sed -e '1,/^$$/d' $< | $(ASCIIDOC) -b xhtml11 - >$@+ && \
 	mv $@+ $@
 
-install-webdoc : html
-	'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST)
+# UNIMPLEMENTED
+#install-webdoc : html
+#	'$(SHELL_PATH_SQ)' ./install-webdoc.sh $(WEBDOC_DEST)
 
-quick-install: quick-install-man
+# quick-install: quick-install-man
 
-quick-install-man:
-	'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
+# quick-install-man:
+#	'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(DOC_REF) $(DESTDIR)$(mandir)
 
-quick-install-html:
-	'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
+#quick-install-html:
+#	'$(SHELL_PATH_SQ)' ./install-doc-quick.sh $(HTML_REF) $(DESTDIR)$(htmldir)
 
 .PHONY: .FORCE-PERF-VERSION-FILE
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
new file mode 100644
index 0000000..0cada9e
--- /dev/null
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -0,0 +1,26 @@
+perf-evlist(1)
+==============
+
+NAME
+----
+perf-evlist - List the event names in a perf.data file
+
+SYNOPSIS
+--------
+[verse]
+'perf evlist <options>'
+
+DESCRIPTION
+-----------
+This command displays the names of events sampled in a perf.data file.
+
+OPTIONS
+-------
+-i::
+--input=::
+        Input file name. (default: perf.data)
+
+SEE ALSO
+--------
+linkperf:perf-record[1], linkperf:perf-list[1],
+linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 399751b..7a527f7 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
 SYNOPSIS
 --------
 [verse]
-'perf list'
+'perf list' [hw|sw|cache|tracepoint|event_glob]
 
 DESCRIPTION
 -----------
@@ -63,7 +63,26 @@ details. Some of them are referenced in the SEE ALSO section below.
 
 OPTIONS
 -------
-None
+
+Without options all known events will be listed.
+
+To limit the list use:
+
+. 'hw' or 'hardware' to list hardware events such as cache-misses, etc.
+
+. 'sw' or 'software' to list software events such as context switches, etc.
+
+. 'cache' or 'hwcache' to list hardware cache events such as L1-dcache-loads, etc.
+
+. 'tracepoint' to list all tracepoint events, alternatively use
+  'subsys_glob:event_glob' to filter by tracepoint subsystems such as sched,
+  block, etc.
+
+. If none of the above is matched, it will apply the supplied glob to all
+  events, printing the ones that match.
+
+One or more types can be used at the same time, listing the events for the
+types specified.
 
 SEE ALSO
 --------
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index 921de25..4a26a2f 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -24,8 +24,8 @@ and statistics with this 'perf lock' command.
 
   'perf lock report' reports statistical data.
 
-OPTIONS
--------
+COMMON OPTIONS
+--------------
 
 -i::
 --input=<file>::
@@ -39,6 +39,14 @@ OPTIONS
 --dump-raw-trace::
         Dump raw trace in ASCII.
 
+REPORT OPTIONS
+--------------
+
+-k::
+--key=<value>::
+        Sorting key. Possible values: acquired (default), contended,
+        wait_total, wait_max, wait_min.
+
 SEE ALSO
 --------
 linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 86b797a..02bafce 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -16,7 +16,7 @@ or
 or
 'perf probe' --list
 or
-'perf probe' [options] --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
+'perf probe' [options] --line='LINE'
 or
 'perf probe' [options] --vars='PROBEPOINT'
 
@@ -73,6 +73,17 @@ OPTIONS
 	(Only for --vars) Show external defined variables in addition to local
 	variables.
 
+-F::
+--funcs::
+	Show available functions in given module or kernel.
+
+--filter=FILTER::
+	(Only for --vars and --funcs) Set filter. FILTER is a combination of glob
+	pattern, see FILTER PATTERN for detail.
+	Default FILTER is "!__k???tab_* & !__crc_*" for --vars, and "!_*"
+	for --funcs.
+	If several filters are specified, only the last filter is used.
+
 -f::
 --force::
 	Forcibly add events with existing name.
@@ -117,13 +128,14 @@ LINE SYNTAX
 -----------
 Line range is described by following syntax.
 
- "FUNC[:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
+ "FUNC[@SRC][:RLN[+NUM|-RLN2]]|SRC[:ALN[+NUM|-ALN2]]"
 
 FUNC specifies the function name of showing lines. 'RLN' is the start line
 number from function entry line, and 'RLN2' is the end line number. As same as
 probe syntax, 'SRC' means the source file path, 'ALN' is start line number,
 and 'ALN2' is end line number in the file. It is also possible to specify how
-many lines to show by using 'NUM'.
+many lines to show by using 'NUM'. Moreover, 'FUNC@SRC' combination is good
+for searching a specific function when several functions share same name.
 So, "source.c:100-120" shows lines between 100th to l20th in source.c file. And "func:10+20" shows 20 lines from 10th line of func function.
 
 LAZY MATCHING
@@ -135,6 +147,14 @@ e.g.
 
 This provides some sort of flexibility and robustness to probe point definitions against minor code changes. For example, actual 10th line of schedule() can be moved easily by modifying schedule(), but the same line matching 'rq=cpu_rq*' may still exist in the function.)
 
+FILTER PATTERN
+--------------
+ The filter pattern is a glob matching pattern(s) to filter variables.
+ In addition, you can use "!" for specifying filter-out rule. You also can give several rules combined with "&" or "|", and fold those rules as one rule by using "(" ")".
+
+e.g.
+ With --filter "foo* | bar*", perf probe -V shows variables which start with "foo" or "bar".
+ With --filter "!foo* & *bar", perf probe -V shows variables which don't start with "foo" and end with "bar", like "fizzbar". But "foobar" is filtered out.
 
 EXAMPLES
 --------
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index e032716..5a520f8 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -137,6 +137,17 @@ Do not update the builid cache. This saves some overhead in situations
 where the information in the perf.data file (which includes buildids)
 is sufficient.
 
+-G name,...::
+--cgroup name,...::
+monitor only in the container (cgroup) called "name". This option is available only
+in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
+container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
+can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
+to first event, second cgroup to second event and so on. It is possible to provide
+an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
+corresponding events, i.e., they always refer to events defined earlier on the command
+line.
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 29ad942..66f040b 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -112,6 +112,28 @@ OPTIONS
 --debug-mode::
         Do various checks like samples ordering and lost events.
 
+-f::
+--fields
+        Comma separated list of fields to print. Options are:
+        comm, tid, pid, time, cpu, event, trace, sym. Field
+        list must be prepended with the type, trace, sw or hw,
+        to indicate to which event type the field list applies.
+        e.g., -f sw:comm,tid,time,sym  and -f trace:time,cpu,trace
+
+-k::
+--vmlinux=<file>::
+        vmlinux pathname
+
+--kallsyms=<file>::
+        kallsyms pathname
+
+--symfs=<directory>::
+        Look for files with symbols relative to this directory.
+
+-G::
+--hide-call-graph::
+        When printing symbols do not display call chain.
+
 SEE ALSO
 --------
 linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index b6da7af..918cc38 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -83,6 +83,17 @@ This option is only valid in system-wide mode.
 print counts using a CSV-style output to make it easy to import directly into
 spreadsheets. Columns are separated by the string specified in SEP.
 
+-G name::
+--cgroup name::
+monitor only in the container (cgroup) called "name". This option is available only
+in per-cpu mode. The cgroup filesystem must be mounted. All threads belonging to
+container "name" are monitored when they run on the monitored CPUs. Multiple cgroups
+can be provided. Each cgroup is applied to the corresponding event, i.e., first cgroup
+to first event, second cgroup to second event and so on. It is possible to provide
+an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must have
+corresponding events, i.e., they always refer to events defined earlier on the command
+line.
+
 EXAMPLES
 --------
 
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 7141c42..158c30e 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -3,7 +3,7 @@ ifeq ("$(origin O)", "command line")
 endif
 
 # The default target of this Makefile is...
-all::
+all:
 
 ifneq ($(OUTPUT),)
 # check that the output directory actually exists
@@ -11,152 +11,12 @@ OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
 $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
 endif
 
-# Define V=1 to have a more verbose compile.
-# Define V=2 to have an even more verbose compile.
-#
-# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
-# or vsnprintf() return -1 instead of number of characters which would
-# have been written to the final string if enough space had been available.
-#
-# Define FREAD_READS_DIRECTORIES if your are on a system which succeeds
-# when attempting to read from an fopen'ed directory.
-#
-# Define NO_OPENSSL environment variable if you do not have OpenSSL.
-# This also implies MOZILLA_SHA1.
-#
-# Define CURLDIR=/foo/bar if your curl header and library files are in
-# /foo/bar/include and /foo/bar/lib directories.
-#
-# Define EXPATDIR=/foo/bar if your expat header and library files are in
-# /foo/bar/include and /foo/bar/lib directories.
-#
-# Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
-#
-# Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
-# d_type in struct dirent (latest Cygwin -- will be fixed soonish).
-#
-# Define NO_C99_FORMAT if your formatted IO functions (printf/scanf et.al.)
-# do not support the 'size specifiers' introduced by C99, namely ll, hh,
-# j, z, t. (representing long long int, char, intmax_t, size_t, ptrdiff_t).
-# some C compilers supported these specifiers prior to C99 as an extension.
-#
-# Define NO_STRCASESTR if you don't have strcasestr.
-#
-# Define NO_MEMMEM if you don't have memmem.
-#
-# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
-# If your compiler also does not support long long or does not have
-# strtoull, define NO_STRTOULL.
-#
-# Define NO_SETENV if you don't have setenv in the C library.
-#
-# Define NO_UNSETENV if you don't have unsetenv in the C library.
-#
-# Define NO_MKDTEMP if you don't have mkdtemp in the C library.
-#
-# Define NO_SYS_SELECT_H if you don't have sys/select.h.
-#
-# Define NO_SYMLINK_HEAD if you never want .perf/HEAD to be a symbolic link.
-# Enable it on Windows.  By default, symrefs are still used.
-#
-# Define NO_SVN_TESTS if you want to skip time-consuming SVN interoperability
-# tests.  These tests take up a significant amount of the total test time
-# but are not needed unless you plan to talk to SVN repos.
-#
-# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
-# installed in /sw, but don't want PERF to link against any libraries
-# installed there.  If defined you may specify your own (or Fink's)
-# include directories and library directories by defining CFLAGS
-# and LDFLAGS appropriately.
-#
-# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
-# have DarwinPorts installed in /opt/local, but don't want PERF to
-# link against any libraries installed there.  If defined you may
-# specify your own (or DarwinPort's) include directories and
-# library directories by defining CFLAGS and LDFLAGS appropriately.
-#
-# Define PPC_SHA1 environment variable when running make to make use of
-# a bundled SHA1 routine optimized for PowerPC.
-#
-# Define ARM_SHA1 environment variable when running make to make use of
-# a bundled SHA1 routine optimized for ARM.
-#
-# Define MOZILLA_SHA1 environment variable when running make to make use of
-# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
-# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
-# choice) has very fast version optimized for i586.
-#
-# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
-#
-# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
-#
-# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
-# Patrick Mauritz).
-#
-# Define NO_MMAP if you want to avoid mmap.
-#
-# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
-#
-# Define NO_PREAD if you have a problem with pread() system call (e.g.
-# cygwin.dll before v1.5.22).
-#
-# Define NO_FAST_WORKING_DIRECTORY if accessing objects in pack files is
-# generally faster on your platform than accessing the working directory.
-#
-# Define NO_TRUSTABLE_FILEMODE if your filesystem may claim to support
-# the executable mode bit, but doesn't really do so.
-#
-# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
-#
-# Define NO_SOCKADDR_STORAGE if your platform does not have struct
-# sockaddr_storage.
-#
-# Define NO_ICONV if your libc does not properly support iconv.
-#
-# Define OLD_ICONV if your library has an old iconv(), where the second
-# (input buffer pointer) parameter is declared with type (const char **).
-#
-# Define NO_DEFLATE_BOUND if your zlib does not have deflateBound.
-#
-# Define NO_R_TO_GCC_LINKER if your gcc does not like "-R/path/lib"
-# that tells runtime paths to dynamic libraries;
-# "-Wl,-rpath=/path/lib" is used instead.
-#
-# Define USE_NSEC below if you want perf to care about sub-second file mtimes
-# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
-# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
-# randomly break unless your underlying filesystem supports those sub-second
-# times (my ext3 doesn't).
-#
-# Define USE_ST_TIMESPEC if your "struct stat" uses "st_ctimespec" instead of
-# "st_ctim"
-#
-# Define NO_NSEC if your "struct stat" does not have "st_ctim.tv_nsec"
-# available.  This automatically turns USE_NSEC off.
-#
-# Define USE_STDEV below if you want perf to care about the underlying device
-# change being considered an inode change from the update-index perspective.
-#
-# Define NO_ST_BLOCKS_IN_STRUCT_STAT if your platform does not have st_blocks
-# field that counts the on-disk footprint in 512-byte blocks.
+# Define V to have a more verbose compile.
 #
 # Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8
 #
 # Define DOCBOOK_XSL_172 if you want to format man pages with DocBook XSL v1.72.
 #
-# Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
-# MakeMaker (e.g. using ActiveState under Cygwin).
-#
-# Define NO_PERL if you do not want Perl scripts or libraries at all.
-#
-# Define INTERNAL_QSORT to use Git's implementation of qsort(), which
-# is a simplified version of the merge sort used in glibc. This is
-# recommended if Git triggers O(n^2) behavior in your platform's qsort().
-#
-# Define NO_EXTERNAL_GREP if you don't want "perf grep" to ever call
-# your external grep (e.g., if your system lacks grep, if its grep is
-# broken, or spawning external process is slower than built-in grep perf has).
-#
 # Define LDFLAGS=-static to build a static binary.
 #
 # Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
@@ -167,12 +27,7 @@ $(OUTPUT)PERF-VERSION-FILE: .FORCE-PERF-VERSION-FILE
 	@$(SHELL_PATH) util/PERF-VERSION-GEN $(OUTPUT)
 -include $(OUTPUT)PERF-VERSION-FILE
 
-uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
-uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
-uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
-uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
-uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
-uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
+uname_M := $(shell uname -m 2>/dev/null || echo not)
 
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
 				  -e s/arm.*/arm/ -e s/sa110/arm/ \
@@ -191,8 +46,6 @@ ifeq ($(ARCH),x86_64)
 	ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S
 endif
 
-# CFLAGS and LDFLAGS are for the users to override from the command line.
-
 #
 # Include saner warnings here, which can catch bugs:
 #
@@ -270,22 +123,13 @@ CC = $(CROSS_COMPILE)gcc
 AR = $(CROSS_COMPILE)ar
 RM = rm -f
 MKDIR = mkdir
-TAR = tar
 FIND = find
 INSTALL = install
-RPMBUILD = rpmbuild
-PTHREAD_LIBS = -lpthread
 
 # sparse is architecture-neutral, which means that we need to tell it
 # explicitly what architecture to check for. Fix this up for yours..
 SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__
 
-ifeq ($(V), 2)
-	QUIET_STDERR = ">/dev/null"
-else
-	QUIET_STDERR = ">/dev/null 2>&1"
-endif
-
 -include feature-tests.mak
 
 ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
@@ -310,49 +154,37 @@ BASIC_LDFLAGS =
 
 # Guard against environment variables
 BUILTIN_OBJS =
-BUILT_INS =
-COMPAT_CFLAGS =
-COMPAT_OBJS =
 LIB_H =
 LIB_OBJS =
-SCRIPT_PERL =
+PYRF_OBJS =
 SCRIPT_SH =
-TEST_PROGRAMS =
 
 SCRIPT_SH += perf-archive.sh
 
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
 
+$(OUTPUT)python/perf.so: $(PYRF_OBJS)
+	$(QUIET_GEN)python util/setup.py --quiet  build_ext --build-lib='$(OUTPUT)python' \
+						--build-temp='$(OUTPUT)python/temp'
 #
 # No Perl scripts right now:
 #
 
-# SCRIPT_PERL += perf-add--interactive.perl
-
-SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
-	  $(patsubst %.perl,%,$(SCRIPT_PERL))
-
-# Empty...
-EXTRA_PROGRAMS =
-
-# ... and all the rest that could be moved out of bindir to perfexecdir
-PROGRAMS += $(EXTRA_PROGRAMS)
+SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
 
 #
 # Single 'perf' binary right now:
 #
 PROGRAMS += $(OUTPUT)perf
 
-# List built-in command $C whose implementation cmd_$C() is not in
-# builtin-$C.o but is linked in as part of some other command.
-#
+LANG_BINDINGS =
 
 # what 'all' will build and 'install' will install, in perfexecdir
 ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
 
 # what 'all' will build but not install in perfexecdir
-OTHER_PROGRAMS = $(OUTPUT)perf$X
+OTHER_PROGRAMS = $(OUTPUT)perf
 
 # Set paths to tools early so that they can be used for version tests.
 ifndef SHELL_PATH
@@ -395,6 +227,7 @@ LIB_H += util/include/dwarf-regs.h
 LIB_H += util/include/asm/dwarf2.h
 LIB_H += util/include/asm/cpufeature.h
 LIB_H += perf.h
+LIB_H += util/annotate.h
 LIB_H += util/cache.h
 LIB_H += util/callchain.h
 LIB_H += util/build-id.h
@@ -402,6 +235,7 @@ LIB_H += util/debug.h
 LIB_H += util/debugfs.h
 LIB_H += util/event.h
 LIB_H += util/evsel.h
+LIB_H += util/evlist.h
 LIB_H += util/exec_cmd.h
 LIB_H += util/types.h
 LIB_H += util/levenshtein.h
@@ -416,6 +250,7 @@ LIB_H += util/help.h
 LIB_H += util/session.h
 LIB_H += util/strbuf.h
 LIB_H += util/strlist.h
+LIB_H += util/strfilter.h
 LIB_H += util/svghelper.h
 LIB_H += util/run-command.h
 LIB_H += util/sigchain.h
@@ -425,21 +260,26 @@ LIB_H += util/values.h
 LIB_H += util/sort.h
 LIB_H += util/hist.h
 LIB_H += util/thread.h
+LIB_H += util/thread_map.h
 LIB_H += util/trace-event.h
 LIB_H += util/probe-finder.h
 LIB_H += util/probe-event.h
 LIB_H += util/pstack.h
 LIB_H += util/cpumap.h
+LIB_H += util/top.h
 LIB_H += $(ARCH_INCLUDE)
+LIB_H += util/cgroup.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
+LIB_OBJS += $(OUTPUT)util/annotate.o
 LIB_OBJS += $(OUTPUT)util/build-id.o
 LIB_OBJS += $(OUTPUT)util/config.o
 LIB_OBJS += $(OUTPUT)util/ctype.o
 LIB_OBJS += $(OUTPUT)util/debugfs.o
 LIB_OBJS += $(OUTPUT)util/environment.o
 LIB_OBJS += $(OUTPUT)util/event.o
+LIB_OBJS += $(OUTPUT)util/evlist.o
 LIB_OBJS += $(OUTPUT)util/evsel.o
 LIB_OBJS += $(OUTPUT)util/exec_cmd.o
 LIB_OBJS += $(OUTPUT)util/help.o
@@ -455,6 +295,8 @@ LIB_OBJS += $(OUTPUT)util/quote.o
 LIB_OBJS += $(OUTPUT)util/strbuf.o
 LIB_OBJS += $(OUTPUT)util/string.o
 LIB_OBJS += $(OUTPUT)util/strlist.o
+LIB_OBJS += $(OUTPUT)util/strfilter.o
+LIB_OBJS += $(OUTPUT)util/top.o
 LIB_OBJS += $(OUTPUT)util/usage.o
 LIB_OBJS += $(OUTPUT)util/wrapper.o
 LIB_OBJS += $(OUTPUT)util/sigchain.o
@@ -469,6 +311,7 @@ LIB_OBJS += $(OUTPUT)util/map.o
 LIB_OBJS += $(OUTPUT)util/pstack.o
 LIB_OBJS += $(OUTPUT)util/session.o
 LIB_OBJS += $(OUTPUT)util/thread.o
+LIB_OBJS += $(OUTPUT)util/thread_map.o
 LIB_OBJS += $(OUTPUT)util/trace-event-parse.o
 LIB_OBJS += $(OUTPUT)util/trace-event-read.o
 LIB_OBJS += $(OUTPUT)util/trace-event-info.o
@@ -480,6 +323,7 @@ LIB_OBJS += $(OUTPUT)util/probe-event.o
 LIB_OBJS += $(OUTPUT)util/util.o
 LIB_OBJS += $(OUTPUT)util/xyarray.o
 LIB_OBJS += $(OUTPUT)util/cpumap.o
+LIB_OBJS += $(OUTPUT)util/cgroup.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 
@@ -494,6 +338,7 @@ endif
 BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
+BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
 BUILTIN_OBJS += $(OUTPUT)builtin-help.o
 BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
 BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
@@ -514,6 +359,20 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 
 PERFLIBS = $(LIB_FILE)
 
+# Files needed for the python binding, perf.so
+# pyrf is just an internal name needed for all those wrappers.
+# This has to be in sync with what is in the 'sources' variable in
+# tools/perf/util/setup.py
+
+PYRF_OBJS += $(OUTPUT)util/cpumap.o
+PYRF_OBJS += $(OUTPUT)util/ctype.o
+PYRF_OBJS += $(OUTPUT)util/evlist.o
+PYRF_OBJS += $(OUTPUT)util/evsel.o
+PYRF_OBJS += $(OUTPUT)util/python.o
+PYRF_OBJS += $(OUTPUT)util/thread_map.o
+PYRF_OBJS += $(OUTPUT)util/util.o
+PYRF_OBJS += $(OUTPUT)util/xyarray.o
+
 #
 # Platform specific tweaks
 #
@@ -535,22 +394,6 @@ endif # NO_DWARF
 
 -include arch/$(ARCH)/Makefile
 
-ifeq ($(uname_S),Darwin)
-	ifndef NO_FINK
-		ifeq ($(shell test -d /sw/lib && echo y),y)
-			BASIC_CFLAGS += -I/sw/include
-			BASIC_LDFLAGS += -L/sw/lib
-		endif
-	endif
-	ifndef NO_DARWIN_PORTS
-		ifeq ($(shell test -d /opt/local/lib && echo y),y)
-			BASIC_CFLAGS += -I/opt/local/include
-			BASIC_LDFLAGS += -L/opt/local/lib
-		endif
-	endif
-	PTHREAD_LIBS =
-endif
-
 ifneq ($(OUTPUT),)
 	BASIC_CFLAGS += -I$(OUTPUT)
 endif
@@ -595,6 +438,7 @@ else
 		LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
 		LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
 		LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
+		LIB_OBJS += $(OUTPUT)util/ui/browsers/top.o
 		LIB_OBJS += $(OUTPUT)util/ui/helpline.o
 		LIB_OBJS += $(OUTPUT)util/ui/progress.o
 		LIB_OBJS += $(OUTPUT)util/ui/util.o
@@ -604,6 +448,7 @@ else
 		LIB_H += util/ui/libslang.h
 		LIB_H += util/ui/progress.h
 		LIB_H += util/ui/util.h
+		LIB_H += util/ui/ui.h
 	endif
 endif
 
@@ -635,12 +480,14 @@ else
 	PYTHON_EMBED_CCOPTS = `python-config --cflags 2>/dev/null`
 	FLAGS_PYTHON_EMBED=$(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
 	ifneq ($(call try-cc,$(SOURCE_PYTHON_EMBED),$(FLAGS_PYTHON_EMBED)),y)
+		msg := $(warning No Python.h found, install python-dev[el] to have python support in 'perf script' and to build the python bindings)
 		BASIC_CFLAGS += -DNO_LIBPYTHON
 	else
                ALL_LDFLAGS += $(PYTHON_EMBED_LDFLAGS)
                EXTLIBS += $(PYTHON_EMBED_LIBADD)
 		LIB_OBJS += $(OUTPUT)util/scripting-engines/trace-event-python.o
 		LIB_OBJS += $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o
+		LANG_BINDINGS += $(OUTPUT)python/perf.so
 	endif
 endif
 
@@ -690,201 +537,13 @@ else
 	endif
 endif
 
-ifndef CC_LD_DYNPATH
-	ifdef NO_R_TO_GCC_LINKER
-		# Some gcc does not accept and pass -R to the linker to specify
-		# the runtime dynamic library path.
-		CC_LD_DYNPATH = -Wl,-rpath,
-	else
-		CC_LD_DYNPATH = -R
-	endif
-endif
-
-ifdef NEEDS_SOCKET
-	EXTLIBS += -lsocket
-endif
-ifdef NEEDS_NSL
-	EXTLIBS += -lnsl
-endif
-ifdef NO_D_TYPE_IN_DIRENT
-	BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
-endif
-ifdef NO_D_INO_IN_DIRENT
-	BASIC_CFLAGS += -DNO_D_INO_IN_DIRENT
-endif
-ifdef NO_ST_BLOCKS_IN_STRUCT_STAT
-	BASIC_CFLAGS += -DNO_ST_BLOCKS_IN_STRUCT_STAT
-endif
-ifdef USE_NSEC
-	BASIC_CFLAGS += -DUSE_NSEC
-endif
-ifdef USE_ST_TIMESPEC
-	BASIC_CFLAGS += -DUSE_ST_TIMESPEC
-endif
-ifdef NO_NSEC
-	BASIC_CFLAGS += -DNO_NSEC
-endif
-ifdef NO_C99_FORMAT
-	BASIC_CFLAGS += -DNO_C99_FORMAT
-endif
-ifdef SNPRINTF_RETURNS_BOGUS
-	COMPAT_CFLAGS += -DSNPRINTF_RETURNS_BOGUS
-	COMPAT_OBJS += $(OUTPUT)compat/snprintf.o
-endif
-ifdef FREAD_READS_DIRECTORIES
-	COMPAT_CFLAGS += -DFREAD_READS_DIRECTORIES
-	COMPAT_OBJS += $(OUTPUT)compat/fopen.o
-endif
-ifdef NO_SYMLINK_HEAD
-	BASIC_CFLAGS += -DNO_SYMLINK_HEAD
-endif
-ifdef NO_STRCASESTR
-	COMPAT_CFLAGS += -DNO_STRCASESTR
-	COMPAT_OBJS += $(OUTPUT)compat/strcasestr.o
-endif
-ifdef NO_STRTOUMAX
-	COMPAT_CFLAGS += -DNO_STRTOUMAX
-	COMPAT_OBJS += $(OUTPUT)compat/strtoumax.o
-endif
-ifdef NO_STRTOULL
-	COMPAT_CFLAGS += -DNO_STRTOULL
-endif
-ifdef NO_SETENV
-	COMPAT_CFLAGS += -DNO_SETENV
-	COMPAT_OBJS += $(OUTPUT)compat/setenv.o
-endif
-ifdef NO_MKDTEMP
-	COMPAT_CFLAGS += -DNO_MKDTEMP
-	COMPAT_OBJS += $(OUTPUT)compat/mkdtemp.o
-endif
-ifdef NO_UNSETENV
-	COMPAT_CFLAGS += -DNO_UNSETENV
-	COMPAT_OBJS += $(OUTPUT)compat/unsetenv.o
-endif
-ifdef NO_SYS_SELECT_H
-	BASIC_CFLAGS += -DNO_SYS_SELECT_H
-endif
-ifdef NO_MMAP
-	COMPAT_CFLAGS += -DNO_MMAP
-	COMPAT_OBJS += $(OUTPUT)compat/mmap.o
-else
-	ifdef USE_WIN32_MMAP
-		COMPAT_CFLAGS += -DUSE_WIN32_MMAP
-		COMPAT_OBJS += $(OUTPUT)compat/win32mmap.o
-	endif
-endif
-ifdef NO_PREAD
-	COMPAT_CFLAGS += -DNO_PREAD
-	COMPAT_OBJS += $(OUTPUT)compat/pread.o
-endif
-ifdef NO_FAST_WORKING_DIRECTORY
-	BASIC_CFLAGS += -DNO_FAST_WORKING_DIRECTORY
-endif
-ifdef NO_TRUSTABLE_FILEMODE
-	BASIC_CFLAGS += -DNO_TRUSTABLE_FILEMODE
-endif
-ifdef NO_IPV6
-	BASIC_CFLAGS += -DNO_IPV6
-endif
-ifdef NO_UINTMAX_T
-	BASIC_CFLAGS += -Duintmax_t=uint32_t
-endif
-ifdef NO_SOCKADDR_STORAGE
-ifdef NO_IPV6
-	BASIC_CFLAGS += -Dsockaddr_storage=sockaddr_in
-else
-	BASIC_CFLAGS += -Dsockaddr_storage=sockaddr_in6
-endif
-endif
-ifdef NO_INET_NTOP
-	LIB_OBJS += $(OUTPUT)compat/inet_ntop.o
-endif
-ifdef NO_INET_PTON
-	LIB_OBJS += $(OUTPUT)compat/inet_pton.o
-endif
-
-ifdef NO_ICONV
-	BASIC_CFLAGS += -DNO_ICONV
-endif
-
-ifdef OLD_ICONV
-	BASIC_CFLAGS += -DOLD_ICONV
-endif
-
-ifdef NO_DEFLATE_BOUND
-	BASIC_CFLAGS += -DNO_DEFLATE_BOUND
-endif
-
-ifdef PPC_SHA1
-	SHA1_HEADER = "ppc/sha1.h"
-	LIB_OBJS += $(OUTPUT)ppc/sha1.o ppc/sha1ppc.o
-else
-ifdef ARM_SHA1
-	SHA1_HEADER = "arm/sha1.h"
-	LIB_OBJS += $(OUTPUT)arm/sha1.o $(OUTPUT)arm/sha1_arm.o
-else
-ifdef MOZILLA_SHA1
-	SHA1_HEADER = "mozilla-sha1/sha1.h"
-	LIB_OBJS += $(OUTPUT)mozilla-sha1/sha1.o
-else
-	SHA1_HEADER = <openssl/sha.h>
-	EXTLIBS += $(LIB_4_CRYPTO)
-endif
-endif
-endif
-ifdef NO_PERL_MAKEMAKER
-	export NO_PERL_MAKEMAKER
-endif
-ifdef NO_HSTRERROR
-	COMPAT_CFLAGS += -DNO_HSTRERROR
-	COMPAT_OBJS += $(OUTPUT)compat/hstrerror.o
-endif
-ifdef NO_MEMMEM
-	COMPAT_CFLAGS += -DNO_MEMMEM
-	COMPAT_OBJS += $(OUTPUT)compat/memmem.o
-endif
-ifdef INTERNAL_QSORT
-	COMPAT_CFLAGS += -DINTERNAL_QSORT
-	COMPAT_OBJS += $(OUTPUT)compat/qsort.o
-endif
-ifdef RUNTIME_PREFIX
-	COMPAT_CFLAGS += -DRUNTIME_PREFIX
-endif
-
-ifdef DIR_HAS_BSD_GROUP_SEMANTICS
-	COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS
-endif
-ifdef NO_EXTERNAL_GREP
-	BASIC_CFLAGS += -DNO_EXTERNAL_GREP
-endif
-
-ifeq ($(PERL_PATH),)
-NO_PERL=NoThanks
-endif
-
-QUIET_SUBDIR0  = +$(MAKE) -C # space to separate -C and subdir
-QUIET_SUBDIR1  =
-
-ifneq ($(findstring $(MAKEFLAGS),w),w)
-PRINT_DIR = --no-print-directory
-else # "make -w"
-NO_SUBDIR = :
-endif
-
 ifneq ($(findstring $(MAKEFLAGS),s),s)
 ifndef V
 	QUIET_CC       = @echo '   ' CC $@;
 	QUIET_AR       = @echo '   ' AR $@;
 	QUIET_LINK     = @echo '   ' LINK $@;
 	QUIET_MKDIR    = @echo '   ' MKDIR $@;
-	QUIET_BUILT_IN = @echo '   ' BUILTIN $@;
 	QUIET_GEN      = @echo '   ' GEN $@;
-	QUIET_SUBDIR0  = +@subdir=
-	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
-			 $(MAKE) $(PRINT_DIR) -C $$subdir
-	export V
-	export QUIET_GEN
-	export QUIET_BUILT_IN
 endif
 endif
 
@@ -894,7 +553,6 @@ endif
 
 # Shell quote (do not use $(call) to accommodate ancient setups);
 
-SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
 ETC_PERFCONFIG_SQ = $(subst ','\'',$(ETC_PERFCONFIG))
 
 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
@@ -908,46 +566,36 @@ htmldir_SQ = $(subst ','\'',$(htmldir))
 prefix_SQ = $(subst ','\'',$(prefix))
 
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
-PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
 
 LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
 
-BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
-	$(COMPAT_CFLAGS)
-LIB_OBJS += $(COMPAT_OBJS)
-
 ALL_CFLAGS += $(BASIC_CFLAGS)
 ALL_CFLAGS += $(ARCH_CFLAGS)
 ALL_LDFLAGS += $(BASIC_LDFLAGS)
 
-export TAR INSTALL DESTDIR SHELL_PATH
+export INSTALL SHELL_PATH
 
 
 ### Build rules
 
 SHELL = $(SHELL_PATH)
 
-all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) $(OUTPUT)PERF-BUILD-OPTIONS
-ifneq (,$X)
-	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) perf$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
-endif
-
-all::
+all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
 
 please_set_SHELL_PATH_to_a_more_modern_shell:
 	@$$(:)
 
 shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
 
-strip: $(PROGRAMS) $(OUTPUT)perf$X
-	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf$X
+strip: $(PROGRAMS) $(OUTPUT)perf
+	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) $(OUTPUT)perf
 
 $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -DPERF_VERSION='"$(PERF_VERSION)"' \
 		'-DPERF_HTML_PATH="$(htmldir_SQ)"' \
 		$(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
 
-$(OUTPUT)perf$X: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
+$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
                $(BUILTIN_OBJS) $(LIBS) -o $@
 
@@ -963,39 +611,17 @@ $(OUTPUT)builtin-timechart.o: builtin-timechart.c $(OUTPUT)common-cmds.h $(OUTPU
 		'-DPERF_MAN_PATH="$(mandir_SQ)"' \
 		'-DPERF_INFO_PATH="$(infodir_SQ)"' $<
 
-$(BUILT_INS): $(OUTPUT)perf$X
-	$(QUIET_BUILT_IN)$(RM) $@ && \
-	ln perf$X $@ 2>/dev/null || \
-	ln -s perf$X $@ 2>/dev/null || \
-	cp perf$X $@
-
 $(OUTPUT)common-cmds.h: util/generate-cmdlist.sh command-list.txt
 
 $(OUTPUT)common-cmds.h: $(wildcard Documentation/perf-*.txt)
 	$(QUIET_GEN). util/generate-cmdlist.sh > $@+ && mv $@+ $@
 
-$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
-	$(QUIET_GEN)$(RM) $(OUTPUT)$@ $(OUTPUT)$@+ && \
-	sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
-	    -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
-	    -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
-	    -e 's/@@PERF_VERSION@@/$(PERF_VERSION)/g' \
-	    -e 's/@@NO_CURL@@/$(NO_CURL)/g' \
-	    $@.sh > $(OUTPUT)$@+ && \
-	chmod +x $(OUTPUT)$@+ && \
-	mv $(OUTPUT)$@+ $(OUTPUT)$@
-
-configure: configure.ac
-	$(QUIET_GEN)$(RM) $@ $<+ && \
-	sed -e 's/@@PERF_VERSION@@/$(PERF_VERSION)/g' \
-	    $< > $<+ && \
-	autoconf -o $@ $<+ && \
-	$(RM) $<+
+$(SCRIPTS) : % : %.sh
+	$(QUIET_GEN)$(INSTALL) '$@.sh' '$(OUTPUT)$@'
 
 # These can record PERF_VERSION
 $(OUTPUT)perf.o perf.spec \
-	$(patsubst %.sh,%,$(SCRIPT_SH)) \
-	$(patsubst %.perl,%,$(SCRIPT_PERL)) \
+	$(SCRIPTS) \
 	: $(OUTPUT)PERF-VERSION-FILE
 
 $(OUTPUT)%.o: %.c $(OUTPUT)PERF-CFLAGS
@@ -1012,9 +638,6 @@ $(OUTPUT)util/exec_cmd.o: util/exec_cmd.c $(OUTPUT)PERF-CFLAGS
 		'-DPREFIX="$(prefix_SQ)"' \
 		$<
 
-$(OUTPUT)builtin-init-db.o: builtin-init-db.c $(OUTPUT)PERF-CFLAGS
-	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DDEFAULT_PERF_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
-
 $(OUTPUT)util/config.o: util/config.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
 
@@ -1024,6 +647,9 @@ $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
 $(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
 
+$(OUTPUT)util/ui/browsers/top.o: util/ui/browsers/top.c $(OUTPUT)PERF-CFLAGS
+	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
+
 $(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
 
@@ -1045,12 +671,11 @@ $(OUTPUT)util/scripting-engines/trace-event-python.o: util/scripting-engines/tra
 $(OUTPUT)scripts/python/Perf-Trace-Util/Context.o: scripts/python/Perf-Trace-Util/Context.c $(OUTPUT)PERF-CFLAGS
 	$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs $<
 
-$(OUTPUT)perf-%$X: %.o $(PERFLIBS)
+$(OUTPUT)perf-%: %.o $(PERFLIBS)
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
 
 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
-$(patsubst perf-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
-builtin-revert.o wt-status.o: wt-status.h
+$(patsubst perf-%,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 
 # we compile into subdirectories. if the target directory is not the source directory, they might not exists. So
 # we depend the various files onto their directories.
@@ -1063,6 +688,36 @@ $(sort $(dir $(DIRECTORY_DEPS))):
 $(LIB_FILE): $(LIB_OBJS)
 	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
 
+help:
+	@echo 'Perf make targets:'
+	@echo '  doc		- make *all* documentation (see below)'
+	@echo '  man		- make manpage documentation (access with man <foo>)'
+	@echo '  html		- make html documentation'
+	@echo '  info		- make GNU info documentation (access with info <foo>)'
+	@echo '  pdf		- make pdf documentation'
+	@echo '  TAGS		- use etags to make tag information for source browsing'
+	@echo '  tags		- use ctags to make tag information for source browsing'
+	@echo '  cscope	- use cscope to make interactive browsing database'
+	@echo ''
+	@echo 'Perf install targets:'
+	@echo '  NOTE: documentation build requires asciidoc, xmlto packages to be installed'
+	@echo '  HINT: use "make prefix=<path> <install target>" to install to a particular'
+	@echo '        path like make prefix=/usr/local install install-doc'
+	@echo '  install	- install compiled binaries'
+	@echo '  install-doc	- install *all* documentation'
+	@echo '  install-man	- install manpage documentation'
+	@echo '  install-html	- install html documentation'
+	@echo '  install-info	- install GNU info documentation'
+	@echo '  install-pdf	- install pdf documentation'
+	@echo ''
+	@echo '  quick-install-doc	- alias for quick-install-man'
+	@echo '  quick-install-man	- install the documentation quickly'
+	@echo '  quick-install-html	- install the html documentation quickly'
+	@echo ''
+	@echo 'Perf maintainer targets:'
+	@echo '  distclean		- alias to clean'
+	@echo '  clean			- clean all binary objects and build output'
+
 doc:
 	$(MAKE) -C Documentation all
 
@@ -1101,30 +756,12 @@ $(OUTPUT)PERF-CFLAGS: .FORCE-PERF-CFLAGS
 		echo "$$FLAGS" >$(OUTPUT)PERF-CFLAGS; \
             fi
 
-# We need to apply sq twice, once to protect from the shell
-# that runs $(OUTPUT)PERF-BUILD-OPTIONS, and then again to protect it
-# and the first level quoting from the shell that runs "echo".
-$(OUTPUT)PERF-BUILD-OPTIONS: .FORCE-PERF-BUILD-OPTIONS
-	@echo SHELL_PATH=\''$(subst ','\'',$(SHELL_PATH_SQ))'\' >$@
-	@echo TAR=\''$(subst ','\'',$(subst ','\'',$(TAR)))'\' >>$@
-	@echo NO_CURL=\''$(subst ','\'',$(subst ','\'',$(NO_CURL)))'\' >>$@
-	@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@
-
 ### Testing rules
 
-#
-# None right now:
-#
-# TEST_PROGRAMS += test-something$X
-
-all:: $(TEST_PROGRAMS)
-
 # GNU make supports exporting all variables by "export" without parameters.
 # However, the environment gets quite big, and some programs have problems
 # with that.
 
-export NO_SVN_TESTS
-
 check: $(OUTPUT)common-cmds.h
 	if sparse; \
 	then \
@@ -1133,33 +770,21 @@ check: $(OUTPUT)common-cmds.h
 			sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; \
 		done; \
 	else \
-		echo 2>&1 "Did you mean 'make test'?"; \
 		exit 1; \
 	fi
 
-remove-dashes:
-	./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
-
 ### Installation rules
 
-ifneq ($(filter /%,$(firstword $(template_dir))),)
-template_instdir = $(template_dir)
-else
-template_instdir = $(prefix)/$(template_dir)
-endif
-export template_instdir
-
 ifneq ($(filter /%,$(firstword $(perfexecdir))),)
 perfexec_instdir = $(perfexecdir)
 else
 perfexec_instdir = $(prefix)/$(perfexecdir)
 endif
 perfexec_instdir_SQ = $(subst ','\'',$(perfexec_instdir))
-export perfexec_instdir
 
 install: all
 	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)'
-	$(INSTALL) $(OUTPUT)perf$X '$(DESTDIR_SQ)$(bindir_SQ)'
+	$(INSTALL) $(OUTPUT)perf '$(DESTDIR_SQ)$(bindir_SQ)'
 	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'
 	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/bin'
 	$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
@@ -1172,14 +797,6 @@ install: all
 	$(INSTALL) scripts/python/*.py -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python'
 	$(INSTALL) scripts/python/bin/* -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/python/bin'
 
-ifdef BUILT_INS
-	$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
-	$(INSTALL) $(BUILT_INS) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
-ifneq (,$X)
-	$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) $(OUTPUT)perf$X)), $(RM) '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/$p';)
-endif
-endif
-
 install-doc:
 	$(MAKE) -C Documentation install
 
@@ -1204,104 +821,17 @@ quick-install-man:
 quick-install-html:
 	$(MAKE) -C Documentation quick-install-html
 
-
-### Maintainer's dist rules
-#
-# None right now
-#
-#
-# perf.spec: perf.spec.in
-#	sed -e 's/@@VERSION@@/$(PERF_VERSION)/g' < $< > $@+
-#	mv $@+ $@
-#
-# PERF_TARNAME=perf-$(PERF_VERSION)
-# dist: perf.spec perf-archive$(X) configure
-#	./perf-archive --format=tar \
-#		--prefix=$(PERF_TARNAME)/ HEAD^{tree} > $(PERF_TARNAME).tar
-#	@mkdir -p $(PERF_TARNAME)
-#	@cp perf.spec configure $(PERF_TARNAME)
-#	@echo $(PERF_VERSION) > $(PERF_TARNAME)/version
-#	$(TAR) rf $(PERF_TARNAME).tar \
-#		$(PERF_TARNAME)/perf.spec \
-#		$(PERF_TARNAME)/configure \
-#		$(PERF_TARNAME)/version
-#	@$(RM) -r $(PERF_TARNAME)
-#	gzip -f -9 $(PERF_TARNAME).tar
-#
-# htmldocs = perf-htmldocs-$(PERF_VERSION)
-# manpages = perf-manpages-$(PERF_VERSION)
-# dist-doc:
-#	$(RM) -r .doc-tmp-dir
-#	mkdir .doc-tmp-dir
-#	$(MAKE) -C Documentation WEBDOC_DEST=../.doc-tmp-dir install-webdoc
-#	cd .doc-tmp-dir && $(TAR) cf ../$(htmldocs).tar .
-#	gzip -n -9 -f $(htmldocs).tar
-#	:
-#	$(RM) -r .doc-tmp-dir
-#	mkdir -p .doc-tmp-dir/man1 .doc-tmp-dir/man5 .doc-tmp-dir/man7
-#	$(MAKE) -C Documentation DESTDIR=./ \
-#		man1dir=../.doc-tmp-dir/man1 \
-#		man5dir=../.doc-tmp-dir/man5 \
-#		man7dir=../.doc-tmp-dir/man7 \
-#		install
-#	cd .doc-tmp-dir && $(TAR) cf ../$(manpages).tar .
-#	gzip -n -9 -f $(manpages).tar
-#	$(RM) -r .doc-tmp-dir
-#
-# rpm: dist
-#	$(RPMBUILD) -ta $(PERF_TARNAME).tar.gz
-
 ### Cleaning rules
 
-distclean: clean
-#	$(RM) configure
-
 clean:
-	$(RM) *.o */*.o */*/*.o */*/*/*.o $(LIB_FILE)
-	$(RM) $(ALL_PROGRAMS) $(BUILT_INS) perf$X
-	$(RM) $(TEST_PROGRAMS)
+	$(RM) $(OUTPUT){*.o,*/*.o,*/*/*.o,*/*/*/*.o,$(LIB_FILE),perf-archive}
+	$(RM) $(ALL_PROGRAMS) perf
 	$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
-	$(RM) -r autom4te.cache
-	$(RM) config.log config.mak.autogen config.mak.append config.status config.cache
-	$(RM) -r $(PERF_TARNAME) .doc-tmp-dir
-	$(RM) $(PERF_TARNAME).tar.gz perf-core_$(PERF_VERSION)-*.tar.gz
-	$(RM) $(htmldocs).tar.gz $(manpages).tar.gz
 	$(MAKE) -C Documentation/ clean
-	$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-BUILD-OPTIONS
+	$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
+	@python util/setup.py clean --build-lib='$(OUTPUT)python' \
+				   --build-temp='$(OUTPUT)python/temp'
 
 .PHONY: all install clean strip
 .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
 .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
-.PHONY: .FORCE-PERF-BUILD-OPTIONS
-
-### Make sure built-ins do not have dups and listed in perf.c
-#
-check-builtins::
-	./check-builtins.sh
-
-### Test suite coverage testing
-#
-# None right now
-#
-# .PHONY: coverage coverage-clean coverage-build coverage-report
-#
-# coverage:
-#	$(MAKE) coverage-build
-#	$(MAKE) coverage-report
-#
-# coverage-clean:
-#	rm -f *.gcda *.gcno
-#
-# COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
-# COVERAGE_LDFLAGS = $(CFLAGS)  -O0 -lgcov
-#
-# coverage-build: coverage-clean
-#	$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
-#	$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \
-#		-j1 test
-#
-# coverage-report:
-#	gcov -b *.c */*.c
-#	grep '^function.*called 0 ' *.c.gcov */*.c.gcov \
-#		| sed -e 's/\([^:]*\)\.gcov: *function \([^ ]*\) called.*/\1: \2/' \
-#		| tee coverage-untested-functions
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index d9ab3ce..0c7454f 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -55,7 +55,7 @@ int bench_sched_pipe(int argc, const char **argv,
 	 * discarding returned value of read(), write()
 	 * causes error in building environment for perf
 	 */
-	int ret, wait_stat;
+	int __used ret, wait_stat;
 	pid_t pid, retpid;
 
 	argc = parse_options(argc, argv, options,
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 8879463..695de4b 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -9,6 +9,7 @@
 
 #include "util/util.h"
 
+#include "util/util.h"
 #include "util/color.h"
 #include <linux/list.h>
 #include "util/cache.h"
@@ -18,6 +19,9 @@
 #include "perf.h"
 #include "util/debug.h"
 
+#include "util/evlist.h"
+#include "util/evsel.h"
+#include "util/annotate.h"
 #include "util/event.h"
 #include "util/parse-options.h"
 #include "util/parse-events.h"
@@ -36,9 +40,13 @@ static bool		print_line;
 
 static const char *sym_hist_filter;
 
-static int hists__add_entry(struct hists *self, struct addr_location *al)
+static int perf_evlist__add_sample(struct perf_evlist *evlist,
+				   struct perf_sample *sample,
+				   struct addr_location *al)
 {
+	struct perf_evsel *evsel;
 	struct hist_entry *he;
+	int ret;
 
 	if (sym_hist_filter != NULL &&
 	    (al->sym == NULL || strcmp(sym_hist_filter, al->sym->name) != 0)) {
@@ -51,25 +59,51 @@ static int hists__add_entry(struct hists *self, struct addr_location *al)
 		return 0;
 	}
 
-	he = __hists__add_entry(self, al, NULL, 1);
+	evsel = perf_evlist__id2evsel(evlist, sample->id);
+	if (evsel == NULL) {
+		/*
+		 * FIXME: Propagate this back, but at least we're in a builtin,
+		 * where exit() is allowed. ;-)
+		 */
+		ui__warning("Invalid %s file, contains samples with id not in "
+			    "its header!\n", input_name);
+		exit_browser(0);
+		exit(1);
+	}
+
+	he = __hists__add_entry(&evsel->hists, al, NULL, 1);
 	if (he == NULL)
 		return -ENOMEM;
 
-	return hist_entry__inc_addr_samples(he, al->addr);
+	ret = 0;
+	if (he->ms.sym != NULL) {
+		struct annotation *notes = symbol__annotation(he->ms.sym);
+		if (notes->src == NULL &&
+		    symbol__alloc_hist(he->ms.sym, evlist->nr_entries) < 0)
+			return -ENOMEM;
+
+		ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+	}
+
+	evsel->hists.stats.total_period += sample->period;
+	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
+	return ret;
 }
 
-static int process_sample_event(event_t *event, struct sample_data *sample,
+static int process_sample_event(union perf_event *event,
+				struct perf_sample *sample,
 				struct perf_session *session)
 {
 	struct addr_location al;
 
-	if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
+	if (perf_event__preprocess_sample(event, session, &al, sample,
+					  symbol__annotate_init) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
 			   event->header.type);
 		return -1;
 	}
 
-	if (!al.filtered && hists__add_entry(&session->hists, &al)) {
+	if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) {
 		pr_warning("problem incrementing symbol count, "
 			   "skipping event\n");
 		return -1;
@@ -78,261 +112,26 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
 	return 0;
 }
 
-static int objdump_line__print(struct objdump_line *self,
-			       struct list_head *head,
-			       struct hist_entry *he, u64 len)
-{
-	struct symbol *sym = he->ms.sym;
-	static const char *prev_line;
-	static const char *prev_color;
-
-	if (self->offset != -1) {
-		const char *path = NULL;
-		unsigned int hits = 0;
-		double percent = 0.0;
-		const char *color;
-		struct sym_priv *priv = symbol__priv(sym);
-		struct sym_ext *sym_ext = priv->ext;
-		struct sym_hist *h = priv->hist;
-		s64 offset = self->offset;
-		struct objdump_line *next = objdump__get_next_ip_line(head, self);
-
-		while (offset < (s64)len &&
-		       (next == NULL || offset < next->offset)) {
-			if (sym_ext) {
-				if (path == NULL)
-					path = sym_ext[offset].path;
-				percent += sym_ext[offset].percent;
-			} else
-				hits += h->ip[offset];
-
-			++offset;
-		}
-
-		if (sym_ext == NULL && h->sum)
-			percent = 100.0 * hits / h->sum;
-
-		color = get_percent_color(percent);
-
-		/*
-		 * Also color the filename and line if needed, with
-		 * the same color than the percentage. Don't print it
-		 * twice for close colored ip with the same filename:line
-		 */
-		if (path) {
-			if (!prev_line || strcmp(prev_line, path)
-				       || color != prev_color) {
-				color_fprintf(stdout, color, " %s", path);
-				prev_line = path;
-				prev_color = color;
-			}
-		}
-
-		color_fprintf(stdout, color, " %7.2f", percent);
-		printf(" :	");
-		color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", self->line);
-	} else {
-		if (!*self->line)
-			printf("         :\n");
-		else
-			printf("         :	%s\n", self->line);
-	}
-
-	return 0;
-}
-
-static struct rb_root root_sym_ext;
-
-static void insert_source_line(struct sym_ext *sym_ext)
-{
-	struct sym_ext *iter;
-	struct rb_node **p = &root_sym_ext.rb_node;
-	struct rb_node *parent = NULL;
-
-	while (*p != NULL) {
-		parent = *p;
-		iter = rb_entry(parent, struct sym_ext, node);
-
-		if (sym_ext->percent > iter->percent)
-			p = &(*p)->rb_left;
-		else
-			p = &(*p)->rb_right;
-	}
-
-	rb_link_node(&sym_ext->node, parent, p);
-	rb_insert_color(&sym_ext->node, &root_sym_ext);
-}
-
-static void free_source_line(struct hist_entry *he, int len)
-{
-	struct sym_priv *priv = symbol__priv(he->ms.sym);
-	struct sym_ext *sym_ext = priv->ext;
-	int i;
-
-	if (!sym_ext)
-		return;
-
-	for (i = 0; i < len; i++)
-		free(sym_ext[i].path);
-	free(sym_ext);
-
-	priv->ext = NULL;
-	root_sym_ext = RB_ROOT;
-}
-
-/* Get the filename:line for the colored entries */
-static void
-get_source_line(struct hist_entry *he, int len, const char *filename)
-{
-	struct symbol *sym = he->ms.sym;
-	u64 start;
-	int i;
-	char cmd[PATH_MAX * 2];
-	struct sym_ext *sym_ext;
-	struct sym_priv *priv = symbol__priv(sym);
-	struct sym_hist *h = priv->hist;
-
-	if (!h->sum)
-		return;
-
-	sym_ext = priv->ext = calloc(len, sizeof(struct sym_ext));
-	if (!priv->ext)
-		return;
-
-	start = he->ms.map->unmap_ip(he->ms.map, sym->start);
-
-	for (i = 0; i < len; i++) {
-		char *path = NULL;
-		size_t line_len;
-		u64 offset;
-		FILE *fp;
-
-		sym_ext[i].percent = 100.0 * h->ip[i] / h->sum;
-		if (sym_ext[i].percent <= 0.5)
-			continue;
-
-		offset = start + i;
-		sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
-		fp = popen(cmd, "r");
-		if (!fp)
-			continue;
-
-		if (getline(&path, &line_len, fp) < 0 || !line_len)
-			goto next;
-
-		sym_ext[i].path = malloc(sizeof(char) * line_len + 1);
-		if (!sym_ext[i].path)
-			goto next;
-
-		strcpy(sym_ext[i].path, path);
-		insert_source_line(&sym_ext[i]);
-
-	next:
-		pclose(fp);
-	}
-}
-
-static void print_summary(const char *filename)
-{
-	struct sym_ext *sym_ext;
-	struct rb_node *node;
-
-	printf("\nSorted summary for file %s\n", filename);
-	printf("----------------------------------------------\n\n");
-
-	if (RB_EMPTY_ROOT(&root_sym_ext)) {
-		printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
-		return;
-	}
-
-	node = rb_first(&root_sym_ext);
-	while (node) {
-		double percent;
-		const char *color;
-		char *path;
-
-		sym_ext = rb_entry(node, struct sym_ext, node);
-		percent = sym_ext->percent;
-		color = get_percent_color(percent);
-		path = sym_ext->path;
-
-		color_fprintf(stdout, color, " %7.2f %s", percent, path);
-		node = rb_next(node);
-	}
-}
-
-static void hist_entry__print_hits(struct hist_entry *self)
-{
-	struct symbol *sym = self->ms.sym;
-	struct sym_priv *priv = symbol__priv(sym);
-	struct sym_hist *h = priv->hist;
-	u64 len = sym->end - sym->start, offset;
-
-	for (offset = 0; offset < len; ++offset)
-		if (h->ip[offset] != 0)
-			printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
-			       sym->start + offset, h->ip[offset]);
-	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
-}
-
-static int hist_entry__tty_annotate(struct hist_entry *he)
+static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
 {
-	struct map *map = he->ms.map;
-	struct dso *dso = map->dso;
-	struct symbol *sym = he->ms.sym;
-	const char *filename = dso->long_name, *d_filename;
-	u64 len;
-	LIST_HEAD(head);
-	struct objdump_line *pos, *n;
-
-	if (hist_entry__annotate(he, &head, 0) < 0)
-		return -1;
-
-	if (full_paths)
-		d_filename = filename;
-	else
-		d_filename = basename(filename);
-
-	len = sym->end - sym->start;
-
-	if (print_line) {
-		get_source_line(he, len, filename);
-		print_summary(filename);
-	}
-
-	printf("\n\n------------------------------------------------\n");
-	printf(" Percent |	Source code & Disassembly of %s\n", d_filename);
-	printf("------------------------------------------------\n");
-
-	if (verbose)
-		hist_entry__print_hits(he);
-
-	list_for_each_entry_safe(pos, n, &head, node) {
-		objdump_line__print(pos, &head, he, len);
-		list_del(&pos->node);
-		objdump_line__free(pos);
-	}
-
-	if (print_line)
-		free_source_line(he, len);
-
-	return 0;
+	return symbol__tty_annotate(he->ms.sym, he->ms.map, evidx,
+				    print_line, full_paths, 0, 0);
 }
 
-static void hists__find_annotations(struct hists *self)
+static void hists__find_annotations(struct hists *self, int evidx)
 {
 	struct rb_node *nd = rb_first(&self->entries), *next;
 	int key = KEY_RIGHT;
 
 	while (nd) {
 		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
-		struct sym_priv *priv;
+		struct annotation *notes;
 
 		if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned)
 			goto find_next;
 
-		priv = symbol__priv(he->ms.sym);
-		if (priv->hist == NULL) {
+		notes = symbol__annotation(he->ms.sym);
+		if (notes->src == NULL) {
 find_next:
 			if (key == KEY_LEFT)
 				nd = rb_prev(nd);
@@ -342,7 +141,7 @@ find_next:
 		}
 
 		if (use_browser > 0) {
-			key = hist_entry__tui_annotate(he);
+			key = hist_entry__tui_annotate(he, evidx);
 			switch (key) {
 			case KEY_RIGHT:
 				next = rb_next(nd);
@@ -357,24 +156,24 @@ find_next:
 			if (next != NULL)
 				nd = next;
 		} else {
-			hist_entry__tty_annotate(he);
+			hist_entry__tty_annotate(he, evidx);
 			nd = rb_next(nd);
 			/*
 			 * Since we have a hist_entry per IP for the same
-			 * symbol, free he->ms.sym->hist to signal we already
+			 * symbol, free he->ms.sym->src to signal we already
 			 * processed this symbol.
 			 */
-			free(priv->hist);
-			priv->hist = NULL;
+			free(notes->src);
+			notes->src = NULL;
 		}
 	}
 }
 
 static struct perf_event_ops event_ops = {
 	.sample	= process_sample_event,
-	.mmap	= event__process_mmap,
-	.comm	= event__process_comm,
-	.fork	= event__process_task,
+	.mmap	= perf_event__process_mmap,
+	.comm	= perf_event__process_comm,
+	.fork	= perf_event__process_task,
 	.ordered_samples = true,
 	.ordering_requires_timestamps = true,
 };
@@ -383,6 +182,8 @@ static int __cmd_annotate(void)
 {
 	int ret;
 	struct perf_session *session;
+	struct perf_evsel *pos;
+	u64 total_nr_samples;
 
 	session = perf_session__new(input_name, O_RDONLY, force, false, &event_ops);
 	if (session == NULL)
@@ -403,12 +204,36 @@ static int __cmd_annotate(void)
 	if (verbose > 2)
 		perf_session__fprintf_dsos(session, stdout);
 
-	hists__collapse_resort(&session->hists);
-	hists__output_resort(&session->hists);
-	hists__find_annotations(&session->hists);
-out_delete:
-	perf_session__delete(session);
+	total_nr_samples = 0;
+	list_for_each_entry(pos, &session->evlist->entries, node) {
+		struct hists *hists = &pos->hists;
+		u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
+
+		if (nr_samples > 0) {
+			total_nr_samples += nr_samples;
+			hists__collapse_resort(hists);
+			hists__output_resort(hists);
+			hists__find_annotations(hists, pos->idx);
+		}
+	}
 
+	if (total_nr_samples == 0) {
+		ui__warning("The %s file has no samples!\n", input_name);
+		goto out_delete;
+	}
+out_delete:
+	/*
+	 * Speed up the exit process, for large files this can
+	 * take quite a while.
+	 *
+	 * XXX Enable this when using valgrind or if we ever
+	 * librarize this command.
+	 *
+	 * Also experiment with obstacks to see how much speed
+	 * up we'll get here.
+	 *
+	 * perf_session__delete(session);
+	 */
 	return ret;
 }
 
@@ -451,9 +276,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
 	else if (use_tui)
 		use_browser = 1;
 
-	setup_browser();
+	setup_browser(true);
 
-	symbol_conf.priv_size = sizeof(struct sym_priv);
+	symbol_conf.priv_size = sizeof(struct annotation);
 	symbol_conf.try_vmlinux_path = true;
 
 	if (symbol__init() < 0)
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 3153e49..6b7d911 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -30,13 +30,13 @@ static int hists__add_entry(struct hists *self,
 	return -ENOMEM;
 }
 
-static int diff__process_sample_event(event_t *event,
-				      struct sample_data *sample,
+static int diff__process_sample_event(union perf_event *event,
+				      struct perf_sample *sample,
 				      struct perf_session *session)
 {
 	struct addr_location al;
 
-	if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
+	if (perf_event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
 		pr_warning("problem processing %d event, skipping it.\n",
 			   event->header.type);
 		return -1;
@@ -56,11 +56,11 @@ static int diff__process_sample_event(event_t *event,
 
 static struct perf_event_ops event_ops = {
 	.sample	= diff__process_sample_event,
-	.mmap	= event__process_mmap,
-	.comm	= event__process_comm,
-	.exit	= event__process_task,
-	.fork	= event__process_task,
-	.lost	= event__process_lost,
+	.mmap	= perf_event__process_mmap,
+	.comm	= perf_event__process_comm,
+	.exit	= perf_event__process_task,
+	.fork	= perf_event__process_task,
+	.lost	= perf_event__process_lost,
 	.ordered_samples = true,
 	.ordering_requires_timestamps = true,
 };
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
new file mode 100644
index 0000000..4c5e9e0
--- /dev/null
+++ b/tools/perf/builtin-evlist.c
@@ -0,0 +1,54 @@
+/*
+ * Builtin evlist command: Show the list of event selectors present
+ * in a perf.data file.
+ */
+#include "builtin.h"
+
+#include "util/util.h"
+
+#include <linux/list.h>
+
+#include "perf.h"
+#include "util/evlist.h"
+#include "util/evsel.h"
+#include "util/parse-events.h"
+#include "util/parse-options.h"
+#include "util/session.h"
+
+static char const *input_name = "perf.data";
+
+static int __cmd_evlist(void)
+{
+	struct perf_session *session;
+	struct perf_evsel *pos;
+
+	session = perf_session__new(input_name, O_RDONLY, 0, false, NULL);
+	if (session == NULL)
+		return -ENOMEM;
+
+	list_for_each_entry(pos, &session->evlist->entries, node)
+		printf("%s\n", event_name(pos));
+
+	perf_session__delete(session);
+	return 0;
+}
+
+static const char * const evlist_usage[] = {
+	"perf evlist [<options>]",
+	NULL
+};
+
+static const struct option options[] = {
+	OPT_STRING('i', "input", &input_name, "file",
+		    "input file name"),
+	OPT_END()
+};
+
+int cmd_evlist(int argc, const char **argv, const char *prefix __used)
+{
+	argc = parse_options(argc, argv, options, evlist_usage, 0);
+	if (argc)
+		usage_with_options(evlist_usage, options);
+
+	return __cmd_evlist();
+}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 0c78ffa..e29f04e 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -16,8 +16,8 @@
 static char		const *input_name = "-";
 static bool		inject_build_ids;
 
-static int event__repipe_synth(event_t *event,
-			       struct perf_session *session __used)
+static int perf_event__repipe_synth(union perf_event *event,
+				    struct perf_session *session __used)
 {
 	uint32_t size;
 	void *buf = event;
@@ -36,41 +36,44 @@ static int event__repipe_synth(event_t *event,
 	return 0;
 }
 
-static int event__repipe(event_t *event, struct sample_data *sample __used,
-			 struct perf_session *session)
+static int perf_event__repipe(union perf_event *event,
+			      struct perf_sample *sample __used,
+			      struct perf_session *session)
 {
-	return event__repipe_synth(event, session);
+	return perf_event__repipe_synth(event, session);
 }
 
-static int event__repipe_mmap(event_t *self, struct sample_data *sample,
-			      struct perf_session *session)
+static int perf_event__repipe_mmap(union perf_event *event,
+				   struct perf_sample *sample,
+				   struct perf_session *session)
 {
 	int err;
 
-	err = event__process_mmap(self, sample, session);
-	event__repipe(self, sample, session);
+	err = perf_event__process_mmap(event, sample, session);
+	perf_event__repipe(event, sample, session);
 
 	return err;
 }
 
-static int event__repipe_task(event_t *self, struct sample_data *sample,
-			      struct perf_session *session)
+static int perf_event__repipe_task(union perf_event *event,
+				   struct perf_sample *sample,
+				   struct perf_session *session)
 {
 	int err;
 
-	err = event__process_task(self, sample, session);
-	event__repipe(self, sample, session);
+	err = perf_event__process_task(event, sample, session);
+	perf_event__repipe(event, sample, session);
 
 	return err;
 }
 
-static int event__repipe_tracing_data(event_t *self,
-				      struct perf_session *session)
+static int perf_event__repipe_tracing_data(union perf_event *event,
+					   struct perf_session *session)
 {
 	int err;
 
-	event__repipe_synth(self, session);
-	err = event__process_tracing_data(self, session);
+	perf_event__repipe_synth(event, session);
+	err = perf_event__process_tracing_data(event, session);
 
 	return err;
 }
@@ -109,8 +112,8 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
 	if (self->kernel)
 		misc = PERF_RECORD_MISC_KERNEL;
 
-	err = event__synthesize_build_id(self, misc, event__repipe,
-					 machine, session);
+	err = perf_event__synthesize_build_id(self, misc, perf_event__repipe,
+					      machine, session);
 	if (err) {
 		pr_err("Can't synthesize build_id event for %s\n", self->long_name);
 		return -1;
@@ -119,8 +122,9 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session)
 	return 0;
 }
 
-static int event__inject_buildid(event_t *event, struct sample_data *sample,
-				 struct perf_session *session)
+static int perf_event__inject_buildid(union perf_event *event,
+				      struct perf_sample *sample,
+				      struct perf_session *session)
 {
 	struct addr_location al;
 	struct thread *thread;
@@ -155,24 +159,24 @@ static int event__inject_buildid(event_t *event, struct sample_data *sample,
 	}
 
 repipe:
-	event__repipe(event, sample, session);
+	perf_event__repipe(event, sample, session);
 	return 0;
 }
 
 struct perf_event_ops inject_ops = {
-	.sample		= event__repipe,
-	.mmap		= event__repipe,
-	.comm		= event__repipe,
-	.fork		= event__repipe,
-	.exit		= event__repipe,
-	.lost		= event__repipe,
-	.read		= event__repipe,
-	.throttle	= event__repipe,
-	.unthrottle	= event__repipe,
-	.attr		= event__repipe_synth,
-	.event_type 	= event__repipe_synth,
-	.tracing_data 	= event__repipe_synth,
-	.build_id 	= event__repipe_synth,
+	.sample		= perf_event__repipe,
+	.mmap		= perf_event__repipe,
+	.comm		= perf_event__repipe,
+	.fork		= perf_event__repipe,
+	.exit		= perf_event__repipe,
+	.lost		= perf_event__repipe,
+	.read		= perf_event__repipe,
+	.throttle	= perf_event__repipe,
+	.unthrottle	= perf_event__repipe,
+	.attr		= perf_event__repipe_synth,
+	.event_type 	= perf_event__repipe_synth,
+	.tracing_data 	= perf_event__repipe_synth,
+	.build_id 	= perf_event__repipe_synth,
 };
 
 extern volatile int session_done;
@@ -190,10 +194,10 @@ static int __cmd_inject(void)
 	signal(SIGINT, sig_handler);
 
 	if (inject_build_ids) {
-		inject_ops.sample	= event__inject_buildid;
-		inject_ops.mmap		= event__repipe_mmap;
-		inject_ops.fork		= event__repipe_task;
-		inject_ops.tracing_data	= event__repipe_tracing_data;
+		inject_ops.sample	= perf_event__inject_buildid;
+		inject_ops.mmap		= perf_event__repipe_mmap;
+		inject_ops.fork		= perf_event__repipe_task;
+		inject_ops.tracing_data	= perf_event__repipe_tracing_data;
 	}
 
 	session = perf_session__new(input_name, O_RDONLY, false, true, &inject_ops);
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index d97256d..7f618f4 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -275,9 +275,8 @@ static void process_free_event(void *data,
 	s_alloc->alloc_cpu = -1;
 }
 
-static void
-process_raw_event(event_t *raw_event __used, void *data,
-		  int cpu, u64 timestamp, struct thread *thread)
+static void process_raw_event(union perf_event *raw_event __used, void *data,
+			      int cpu, u64 timestamp, struct thread *thread)
 {
 	struct event *event;
 	int type;
@@ -304,7 +303,8 @@ process_raw_event(event_t *raw_event __used, void *data,
 	}
 }
 
-static int process_sample_event(event_t *event, struct sample_data *sample,
+static int process_sample_event(union perf_event *event,
+				struct perf_sample *sample,
 				struct perf_session *session)
 {
 	struct thread *thread = perf_session__findnew(session, event->ip.pid);
@@ -325,7 +325,7 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
 
 static struct perf_event_ops event_ops = {
 	.sample			= process_sample_event,
-	.comm			= event__process_comm,
+	.comm			= perf_event__process_comm,
 	.ordered_samples	= true,
 };
 
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index d88c696..6313b6e 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -5,6 +5,7 @@
  *
  * Copyright (C) 2009, Thomas Gleixner <tglx@linutronix.de>
  * Copyright (C) 2008-2009, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
  */
 #include "builtin.h"
 
@@ -13,9 +14,47 @@
 #include "util/parse-events.h"
 #include "util/cache.h"
 
-int cmd_list(int argc __used, const char **argv __used, const char *prefix __used)
+int cmd_list(int argc, const char **argv, const char *prefix __used)
 {
 	setup_pager();
-	print_events();
+
+	if (argc == 1)
+		print_events(NULL);
+	else {
+		int i;
+
+		for (i = 1; i < argc; ++i) {
+			if (i > 1)
+				putchar('\n');
+			if (strncmp(argv[i], "tracepoint", 10) == 0)
+				print_tracepoint_events(NULL, NULL);
+			else if (strcmp(argv[i], "hw") == 0 ||
+				 strcmp(argv[i], "hardware") == 0)
+				print_events_type(PERF_TYPE_HARDWARE);
+			else if (strcmp(argv[i], "sw") == 0 ||
+				 strcmp(argv[i], "software") == 0)
+				print_events_type(PERF_TYPE_SOFTWARE);
+			else if (strcmp(argv[i], "cache") == 0 ||
+				 strcmp(argv[i], "hwcache") == 0)
+				print_hwcache_events(NULL);
+			else {
+				char *sep = strchr(argv[i], ':'), *s;
+				int sep_idx;
+
+				if (sep == NULL) {
+					print_events(argv[i]);
+					continue;
+				}
+				sep_idx = sep - argv[i];
+				s = strdup(argv[i]);
+				if (s == NULL)
+					return -1;
+
+				s[sep_idx] = '\0';
+				print_tracepoint_events(s, s + sep_idx + 1);
+				free(s);
+			}
+		}
+	}
 	return 0;
 }
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 2b36def..7a2a79d 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -202,9 +202,20 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid)
 SINGLE_KEY(nr_acquired)
 SINGLE_KEY(nr_contended)
 SINGLE_KEY(wait_time_total)
-SINGLE_KEY(wait_time_min)
 SINGLE_KEY(wait_time_max)
 
+static int lock_stat_key_wait_time_min(struct lock_stat *one,
+					struct lock_stat *two)
+{
+	u64 s1 = one->wait_time_min;
+	u64 s2 = two->wait_time_min;
+	if (s1 == ULLONG_MAX)
+		s1 = 0;
+	if (s2 == ULLONG_MAX)
+		s2 = 0;
+	return s1 > s2;
+}
+
 struct lock_key {
 	/*
 	 * name: the value for specify by user
@@ -834,14 +845,14 @@ static void dump_info(void)
 		die("Unknown type of information\n");
 }
 
-static int process_sample_event(event_t *self, struct sample_data *sample,
+static int process_sample_event(union perf_event *event, struct perf_sample *sample,
 				struct perf_session *s)
 {
 	struct thread *thread = perf_session__findnew(s, sample->tid);
 
 	if (thread == NULL) {
 		pr_debug("problem processing %d event, skipping it.\n",
-			self->header.type);
+			event->header.type);
 		return -1;
 	}
 
@@ -852,7 +863,7 @@ static int process_sample_event(event_t *self, struct sample_data *sample,
 
 static struct perf_event_ops eops = {
 	.sample			= process_sample_event,
-	.comm			= event__process_comm,
+	.comm			= perf_event__process_comm,
 	.ordered_samples	= true,
 };
 
@@ -893,7 +904,7 @@ static const char * const report_usage[] = {
 
 static const struct option report_options[] = {
 	OPT_STRING('k', "key", &sort_key, "acquired",
-		    "key for sorting"),
+		    "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
 	/* TODO: type */
 	OPT_END()
 };
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index add163c..2c0e64d 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -36,6 +36,7 @@
 #include "builtin.h"
 #include "util/util.h"
 #include "util/strlist.h"
+#include "util/strfilter.h"
 #include "util/symbol.h"
 #include "util/debug.h"
 #include "util/debugfs.h"
@@ -43,6 +44,8 @@
 #include "util/probe-finder.h"
 #include "util/probe-event.h"
 
+#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
+#define DEFAULT_FUNC_FILTER "!_*"
 #define MAX_PATH_LEN 256
 
 /* Session management structure */
@@ -52,6 +55,7 @@ static struct {
 	bool show_lines;
 	bool show_vars;
 	bool show_ext_vars;
+	bool show_funcs;
 	bool mod_events;
 	int nevents;
 	struct perf_probe_event events[MAX_PROBES];
@@ -59,6 +63,7 @@ static struct {
 	struct line_range line_range;
 	const char *target_module;
 	int max_probe_points;
+	struct strfilter *filter;
 } params;
 
 /* Parse an event definition. Note that any error must die. */
@@ -157,6 +162,27 @@ static int opt_show_vars(const struct option *opt __used,
 }
 #endif
 
+static int opt_set_filter(const struct option *opt __used,
+			  const char *str, int unset __used)
+{
+	const char *err;
+
+	if (str) {
+		pr_debug2("Set filter: %s\n", str);
+		if (params.filter)
+			strfilter__delete(params.filter);
+		params.filter = strfilter__new(str, &err);
+		if (!params.filter) {
+			pr_err("Filter parse error at %td.\n", err - str + 1);
+			pr_err("Source: \"%s\"\n", str);
+			pr_err("         %*c\n", (int)(err - str + 1), '^');
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
 static const char * const probe_usage[] = {
 	"perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
 	"perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
@@ -221,6 +247,13 @@ static const struct option options[] = {
 	OPT__DRY_RUN(&probe_event_dry_run),
 	OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
 		 "Set how many probe points can be found for a probe."),
+	OPT_BOOLEAN('F', "funcs", &params.show_funcs,
+		    "Show potential probe-able functions."),
+	OPT_CALLBACK('\0', "filter", NULL,
+		     "[!]FILTER", "Set a filter (with --vars/funcs only)\n"
+		     "\t\t\t(default: \"" DEFAULT_VAR_FILTER "\" for --vars,\n"
+		     "\t\t\t \"" DEFAULT_FUNC_FILTER "\" for --funcs)",
+		     opt_set_filter),
 	OPT_END()
 };
 
@@ -246,7 +279,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 		params.max_probe_points = MAX_PROBES;
 
 	if ((!params.nevents && !params.dellist && !params.list_events &&
-	     !params.show_lines))
+	     !params.show_lines && !params.show_funcs))
 		usage_with_options(probe_usage, options);
 
 	/*
@@ -267,12 +300,41 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 			pr_err(" Error: Don't use --list with --vars.\n");
 			usage_with_options(probe_usage, options);
 		}
+		if (params.show_funcs) {
+			pr_err("  Error: Don't use --list with --funcs.\n");
+			usage_with_options(probe_usage, options);
+		}
 		ret = show_perf_probe_events();
 		if (ret < 0)
 			pr_err("  Error: Failed to show event list. (%d)\n",
 			       ret);
 		return ret;
 	}
+	if (params.show_funcs) {
+		if (params.nevents != 0 || params.dellist) {
+			pr_err("  Error: Don't use --funcs with"
+			       " --add/--del.\n");
+			usage_with_options(probe_usage, options);
+		}
+		if (params.show_lines) {
+			pr_err("  Error: Don't use --funcs with --line.\n");
+			usage_with_options(probe_usage, options);
+		}
+		if (params.show_vars) {
+			pr_err("  Error: Don't use --funcs with --vars.\n");
+			usage_with_options(probe_usage, options);
+		}
+		if (!params.filter)
+			params.filter = strfilter__new(DEFAULT_FUNC_FILTER,
+						       NULL);
+		ret = show_available_funcs(params.target_module,
+					   params.filter);
+		strfilter__delete(params.filter);
+		if (ret < 0)
+			pr_err("  Error: Failed to show functions."
+			       " (%d)\n", ret);
+		return ret;
+	}
 
 #ifdef DWARF_SUPPORT
 	if (params.show_lines) {
@@ -297,10 +359,16 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
 			       " --add/--del.\n");
 			usage_with_options(probe_usage, options);
 		}
+		if (!params.filter)
+			params.filter = strfilter__new(DEFAULT_VAR_FILTER,
+						       NULL);
+
 		ret = show_available_vars(params.events, params.nevents,
 					  params.max_probe_points,
 					  params.target_module,
+					  params.filter,
 					  params.show_ext_vars);
+		strfilter__delete(params.filter);
 		if (ret < 0)
 			pr_err("  Error: Failed to show vars. (%d)\n", ret);
 		return ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 60cac6f..6febcc1 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -18,11 +18,13 @@
 
 #include "util/header.h"
 #include "util/event.h"
+#include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/debug.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/cpumap.h"
+#include "util/thread_map.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -37,16 +39,14 @@ enum write_mode_t {
 
 static u64			user_interval			= ULLONG_MAX;
 static u64			default_interval		=      0;
-static u64			sample_type;
 
-static struct cpu_map		*cpus;
 static unsigned int		page_size;
 static unsigned int		mmap_pages			=    128;
 static unsigned int		user_freq 			= UINT_MAX;
 static int			freq				=   1000;
 static int			output;
 static int			pipe_output			=      0;
-static const char		*output_name			= "perf.data";
+static const char		*output_name			= NULL;
 static int			group				=      0;
 static int			realtime_prio			=      0;
 static bool			nodelay				=  false;
@@ -55,7 +55,6 @@ static bool			sample_id_all_avail		=   true;
 static bool			system_wide			=  false;
 static pid_t			target_pid			=     -1;
 static pid_t			target_tid			=     -1;
-static struct thread_map	*threads;
 static pid_t			child_pid			=     -1;
 static bool			no_inherit			=  false;
 static enum write_mode_t	write_mode			= WRITE_FORCE;
@@ -66,51 +65,17 @@ static bool			sample_address			=  false;
 static bool			sample_time			=  false;
 static bool			no_buildid			=  false;
 static bool			no_buildid_cache		=  false;
+static struct perf_evlist	*evsel_list;
 
 static long			samples				=      0;
 static u64			bytes_written			=      0;
 
-static struct pollfd		*event_array;
-
-static int			nr_poll				=      0;
-static int			nr_cpu				=      0;
-
 static int			file_new			=      1;
 static off_t			post_processing_offset;
 
 static struct perf_session	*session;
 static const char		*cpu_list;
 
-struct mmap_data {
-	void			*base;
-	unsigned int		mask;
-	unsigned int		prev;
-};
-
-static struct mmap_data		mmap_array[MAX_NR_CPUS];
-
-static unsigned long mmap_read_head(struct mmap_data *md)
-{
-	struct perf_event_mmap_page *pc = md->base;
-	long head;
-
-	head = pc->data_head;
-	rmb();
-
-	return head;
-}
-
-static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
-{
-	struct perf_event_mmap_page *pc = md->base;
-
-	/*
-	 * ensure all reads are done before we write the tail out.
-	 */
-	/* mb(); */
-	pc->data_tail = tail;
-}
-
 static void advance_output(size_t size)
 {
 	bytes_written += size;
@@ -131,42 +96,26 @@ static void write_output(void *buf, size_t size)
 	}
 }
 
-static int process_synthesized_event(event_t *event,
-				     struct sample_data *sample __used,
+static int process_synthesized_event(union perf_event *event,
+				     struct perf_sample *sample __used,
 				     struct perf_session *self __used)
 {
 	write_output(event, event->header.size);
 	return 0;
 }
 
-static void mmap_read(struct mmap_data *md)
+static void mmap_read(struct perf_mmap *md)
 {
-	unsigned int head = mmap_read_head(md);
+	unsigned int head = perf_mmap__read_head(md);
 	unsigned int old = md->prev;
 	unsigned char *data = md->base + page_size;
 	unsigned long size;
 	void *buf;
-	int diff;
 
-	/*
-	 * If we're further behind than half the buffer, there's a chance
-	 * the writer will bite our tail and mess up the samples under us.
-	 *
-	 * If we somehow ended up ahead of the head, we got messed up.
-	 *
-	 * In either case, truncate and restart at head.
-	 */
-	diff = head - old;
-	if (diff < 0) {
-		fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
-		/*
-		 * head points to a known good entry, start there.
-		 */
-		old = head;
-	}
+	if (old == head)
+		return;
 
-	if (old != head)
-		samples++;
+	samples++;
 
 	size = head - old;
 
@@ -185,7 +134,7 @@ static void mmap_read(struct mmap_data *md)
 	write_output(buf, size);
 
 	md->prev = old;
-	mmap_write_tail(md, old);
+	perf_mmap__write_tail(md, old);
 }
 
 static volatile int done = 0;
@@ -209,53 +158,10 @@ static void sig_atexit(void)
 	kill(getpid(), signr);
 }
 
-static int group_fd;
-
-static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
-{
-	struct perf_header_attr *h_attr;
-
-	if (nr < session->header.attrs) {
-		h_attr = session->header.attr[nr];
-	} else {
-		h_attr = perf_header_attr__new(a);
-		if (h_attr != NULL)
-			if (perf_header__add_attr(&session->header, h_attr) < 0) {
-				perf_header_attr__delete(h_attr);
-				h_attr = NULL;
-			}
-	}
-
-	return h_attr;
-}
-
-static void create_counter(struct perf_evsel *evsel, int cpu)
+static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
 {
-	char *filter = evsel->filter;
 	struct perf_event_attr *attr = &evsel->attr;
-	struct perf_header_attr *h_attr;
 	int track = !evsel->idx; /* only the first counter needs these */
-	int thread_index;
-	int ret;
-	struct {
-		u64 count;
-		u64 time_enabled;
-		u64 time_running;
-		u64 id;
-	} read_data;
-	/*
- 	 * Check if parse_single_tracepoint_event has already asked for
- 	 * PERF_SAMPLE_TIME.
- 	 *
-	 * XXX this is kludgy but short term fix for problems introduced by
-	 * eac23d1c that broke 'perf script' by having different sample_types
-	 * when using multiple tracepoint events when we use a perf binary
-	 * that tries to use sample_id_all on an older kernel.
- 	 *
- 	 * We need to move counter creation to perf_session, support
- 	 * different sample_types, etc.
- 	 */
-	bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
 
 	attr->read_format	= PERF_FORMAT_TOTAL_TIME_ENABLED |
 				  PERF_FORMAT_TOTAL_TIME_RUNNING |
@@ -263,7 +169,7 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
 
 	attr->sample_type	|= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
-	if (nr_counters > 1)
+	if (evlist->nr_entries > 1)
 		attr->sample_type |= PERF_SAMPLE_ID;
 
 	/*
@@ -315,19 +221,58 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
 
 	attr->mmap		= track;
 	attr->comm		= track;
-	attr->inherit		= !no_inherit;
+
 	if (target_pid == -1 && target_tid == -1 && !system_wide) {
 		attr->disabled = 1;
 		attr->enable_on_exec = 1;
 	}
-retry_sample_id:
-	attr->sample_id_all = sample_id_all_avail ? 1 : 0;
+}
 
-	for (thread_index = 0; thread_index < threads->nr; thread_index++) {
-try_again:
-		FD(evsel, nr_cpu, thread_index) = sys_perf_event_open(attr, threads->map[thread_index], cpu, group_fd, 0);
+static bool perf_evlist__equal(struct perf_evlist *evlist,
+			       struct perf_evlist *other)
+{
+	struct perf_evsel *pos, *pair;
+
+	if (evlist->nr_entries != other->nr_entries)
+		return false;
+
+	pair = list_entry(other->entries.next, struct perf_evsel, node);
 
-		if (FD(evsel, nr_cpu, thread_index) < 0) {
+	list_for_each_entry(pos, &evlist->entries, node) {
+		if (memcmp(&pos->attr, &pair->attr, sizeof(pos->attr) != 0))
+			return false;
+		pair = list_entry(pair->node.next, struct perf_evsel, node);
+	}
+
+	return true;
+}
+
+static void open_counters(struct perf_evlist *evlist)
+{
+	struct perf_evsel *pos;
+
+	list_for_each_entry(pos, &evlist->entries, node) {
+		struct perf_event_attr *attr = &pos->attr;
+		/*
+		 * Check if parse_single_tracepoint_event has already asked for
+		 * PERF_SAMPLE_TIME.
+		 *
+		 * XXX this is kludgy but short term fix for problems introduced by
+		 * eac23d1c that broke 'perf script' by having different sample_types
+		 * when using multiple tracepoint events when we use a perf binary
+		 * that tries to use sample_id_all on an older kernel.
+		 *
+		 * We need to move counter creation to perf_session, support
+		 * different sample_types, etc.
+		 */
+		bool time_needed = attr->sample_type & PERF_SAMPLE_TIME;
+
+		config_attr(pos, evlist);
+retry_sample_id:
+		attr->sample_id_all = sample_id_all_avail ? 1 : 0;
+try_again:
+		if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
+				     !no_inherit) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES)
@@ -364,7 +309,7 @@ try_again:
 			}
 			printf("\n");
 			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
-			      FD(evsel, nr_cpu, thread_index), strerror(err));
+			      err, strerror(err));
 
 #if defined(__i386__) || defined(__x86_64__)
 			if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
@@ -375,90 +320,28 @@ try_again:
 #endif
 
 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
-			exit(-1);
 		}
+	}
 
-		h_attr = get_header_attr(attr, evsel->idx);
-		if (h_attr == NULL)
-			die("nomem\n");
+	if (perf_evlist__set_filters(evlist)) {
+		error("failed to set filter with %d (%s)\n", errno,
+			strerror(errno));
+		exit(-1);
+	}
 
-		if (!file_new) {
-			if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
-				fprintf(stderr, "incompatible append\n");
-				exit(-1);
-			}
-		}
+	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
+		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 
-		if (read(FD(evsel, nr_cpu, thread_index), &read_data, sizeof(read_data)) == -1) {
-			perror("Unable to read perf file descriptor");
+	if (file_new)
+		session->evlist = evlist;
+	else {
+		if (!perf_evlist__equal(session->evlist, evlist)) {
+			fprintf(stderr, "incompatible append\n");
 			exit(-1);
 		}
+ 	}
 
-		if (perf_header_attr__add_id(h_attr, read_data.id) < 0) {
-			pr_warning("Not enough memory to add id\n");
-			exit(-1);
-		}
-
-		assert(FD(evsel, nr_cpu, thread_index) >= 0);
-		fcntl(FD(evsel, nr_cpu, thread_index), F_SETFL, O_NONBLOCK);
-
-		/*
-		 * First counter acts as the group leader:
-		 */
-		if (group && group_fd == -1)
-			group_fd = FD(evsel, nr_cpu, thread_index);
-
-		if (evsel->idx || thread_index) {
-			struct perf_evsel *first;
-			first = list_entry(evsel_list.next, struct perf_evsel, node);
-			ret = ioctl(FD(evsel, nr_cpu, thread_index),
-				    PERF_EVENT_IOC_SET_OUTPUT,
-				    FD(first, nr_cpu, 0));
-			if (ret) {
-				error("failed to set output: %d (%s)\n", errno,
-						strerror(errno));
-				exit(-1);
-			}
-		} else {
-			mmap_array[nr_cpu].prev = 0;
-			mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
-			mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
-				PROT_READ | PROT_WRITE, MAP_SHARED, FD(evsel, nr_cpu, thread_index), 0);
-			if (mmap_array[nr_cpu].base == MAP_FAILED) {
-				error("failed to mmap with %d (%s)\n", errno, strerror(errno));
-				exit(-1);
-			}
-
-			event_array[nr_poll].fd = FD(evsel, nr_cpu, thread_index);
-			event_array[nr_poll].events = POLLIN;
-			nr_poll++;
-		}
-
-		if (filter != NULL) {
-			ret = ioctl(FD(evsel, nr_cpu, thread_index),
-				    PERF_EVENT_IOC_SET_FILTER, filter);
-			if (ret) {
-				error("failed to set filter with %d (%s)\n", errno,
-						strerror(errno));
-				exit(-1);
-			}
-		}
-	}
-
-	if (!sample_type)
-		sample_type = attr->sample_type;
-}
-
-static void open_counters(int cpu)
-{
-	struct perf_evsel *pos;
-
-	group_fd = -1;
-
-	list_for_each_entry(pos, &evsel_list, node)
-		create_counter(pos, cpu);
-
-	nr_cpu++;
+	perf_session__update_sample_type(session);
 }
 
 static int process_buildids(void)
@@ -481,14 +364,14 @@ static void atexit_header(void)
 
 		if (!no_buildid)
 			process_buildids();
-		perf_header__write(&session->header, output, true);
+		perf_session__write_header(session, evsel_list, output, true);
 		perf_session__delete(session);
-		perf_evsel_list__delete();
+		perf_evlist__delete(evsel_list);
 		symbol__exit();
 	}
 }
 
-static void event__synthesize_guest_os(struct machine *machine, void *data)
+static void perf_event__synthesize_guest_os(struct machine *machine, void *data)
 {
 	int err;
 	struct perf_session *psession = data;
@@ -504,8 +387,8 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
 	 *method is used to avoid symbol missing when the first addr is
 	 *in module instead of in guest kernel.
 	 */
-	err = event__synthesize_modules(process_synthesized_event,
-					psession, machine);
+	err = perf_event__synthesize_modules(process_synthesized_event,
+					     psession, machine);
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
 		       " relocation symbol.\n", machine->pid);
@@ -514,11 +397,12 @@ static void event__synthesize_guest_os(struct machine *machine, void *data)
 	 * We use _stext for guest kernel because guest kernel's /proc/kallsyms
 	 * have no _text sometimes.
 	 */
-	err = event__synthesize_kernel_mmap(process_synthesized_event,
-					    psession, machine, "_text");
+	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+						 psession, machine, "_text");
 	if (err < 0)
-		err = event__synthesize_kernel_mmap(process_synthesized_event,
-						    psession, machine, "_stext");
+		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+							 psession, machine,
+							 "_stext");
 	if (err < 0)
 		pr_err("Couldn't record guest kernel [%d]'s reference"
 		       " relocation symbol.\n", machine->pid);
@@ -533,9 +417,9 @@ static void mmap_read_all(void)
 {
 	int i;
 
-	for (i = 0; i < nr_cpu; i++) {
-		if (mmap_array[i].base)
-			mmap_read(&mmap_array[i]);
+	for (i = 0; i < evsel_list->cpus->nr; i++) {
+		if (evsel_list->mmap[i].base)
+			mmap_read(&evsel_list->mmap[i]);
 	}
 
 	if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
@@ -566,18 +450,26 @@ static int __cmd_record(int argc, const char **argv)
 		exit(-1);
 	}
 
-	if (!strcmp(output_name, "-"))
-		pipe_output = 1;
-	else if (!stat(output_name, &st) && st.st_size) {
-		if (write_mode == WRITE_FORCE) {
-			char oldname[PATH_MAX];
-			snprintf(oldname, sizeof(oldname), "%s.old",
-				 output_name);
-			unlink(oldname);
-			rename(output_name, oldname);
+	if (!output_name) {
+		if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
+			pipe_output = 1;
+		else
+			output_name = "perf.data";
+	}
+	if (output_name) {
+		if (!strcmp(output_name, "-"))
+			pipe_output = 1;
+		else if (!stat(output_name, &st) && st.st_size) {
+			if (write_mode == WRITE_FORCE) {
+				char oldname[PATH_MAX];
+				snprintf(oldname, sizeof(oldname), "%s.old",
+					 output_name);
+				unlink(oldname);
+				rename(output_name, oldname);
+			}
+		} else if (write_mode == WRITE_APPEND) {
+			write_mode = WRITE_FORCE;
 		}
-	} else if (write_mode == WRITE_APPEND) {
-		write_mode = WRITE_FORCE;
 	}
 
 	flags = O_CREAT|O_RDWR;
@@ -606,19 +498,14 @@ static int __cmd_record(int argc, const char **argv)
 		perf_header__set_feat(&session->header, HEADER_BUILD_ID);
 
 	if (!file_new) {
-		err = perf_header__read(session, output);
+		err = perf_session__read_header(session, output);
 		if (err < 0)
 			goto out_delete_session;
 	}
 
-	if (have_tracepoints(&evsel_list))
+	if (have_tracepoints(&evsel_list->entries))
 		perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
 
-	/*
- 	 * perf_session__delete(session) will be called at atexit_header()
-	 */
-	atexit(atexit_header);
-
 	if (forks) {
 		child_pid = fork();
 		if (child_pid < 0) {
@@ -659,7 +546,7 @@ static int __cmd_record(int argc, const char **argv)
 		}
 
 		if (!system_wide && target_tid == -1 && target_pid == -1)
-			threads->map[0] = child_pid;
+			evsel_list->threads->map[0] = child_pid;
 
 		close(child_ready_pipe[1]);
 		close(go_pipe[0]);
@@ -673,46 +560,42 @@ static int __cmd_record(int argc, const char **argv)
 		close(child_ready_pipe[0]);
 	}
 
-	if (!system_wide && no_inherit && !cpu_list) {
-		open_counters(-1);
-	} else {
-		for (i = 0; i < cpus->nr; i++)
-			open_counters(cpus->map[i]);
-	}
+	open_counters(evsel_list);
 
-	perf_session__set_sample_type(session, sample_type);
+	/*
+	 * perf_session__delete(session) will be called at atexit_header()
+	 */
+	atexit(atexit_header);
 
 	if (pipe_output) {
 		err = perf_header__write_pipe(output);
 		if (err < 0)
 			return err;
 	} else if (file_new) {
-		err = perf_header__write(&session->header, output, false);
+		err = perf_session__write_header(session, evsel_list,
+						 output, false);
 		if (err < 0)
 			return err;
 	}
 
 	post_processing_offset = lseek(output, 0, SEEK_CUR);
 
-	perf_session__set_sample_id_all(session, sample_id_all_avail);
-
 	if (pipe_output) {
-		err = event__synthesize_attrs(&session->header,
-					      process_synthesized_event,
-					      session);
+		err = perf_session__synthesize_attrs(session,
+						     process_synthesized_event);
 		if (err < 0) {
 			pr_err("Couldn't synthesize attrs.\n");
 			return err;
 		}
 
-		err = event__synthesize_event_types(process_synthesized_event,
-						    session);
+		err = perf_event__synthesize_event_types(process_synthesized_event,
+							 session);
 		if (err < 0) {
 			pr_err("Couldn't synthesize event_types.\n");
 			return err;
 		}
 
-		if (have_tracepoints(&evsel_list)) {
+		if (have_tracepoints(&evsel_list->entries)) {
 			/*
 			 * FIXME err <= 0 here actually means that
 			 * there were no tracepoints so its not really
@@ -721,9 +604,9 @@ static int __cmd_record(int argc, const char **argv)
 			 * return this more properly and also
 			 * propagate errors that now are calling die()
 			 */
-			err = event__synthesize_tracing_data(output, &evsel_list,
-							     process_synthesized_event,
-							     session);
+			err = perf_event__synthesize_tracing_data(output, evsel_list,
+								  process_synthesized_event,
+								  session);
 			if (err <= 0) {
 				pr_err("Couldn't record tracing data.\n");
 				return err;
@@ -738,31 +621,34 @@ static int __cmd_record(int argc, const char **argv)
 		return -1;
 	}
 
-	err = event__synthesize_kernel_mmap(process_synthesized_event,
-					    session, machine, "_text");
+	err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+						 session, machine, "_text");
 	if (err < 0)
-		err = event__synthesize_kernel_mmap(process_synthesized_event,
-						    session, machine, "_stext");
+		err = perf_event__synthesize_kernel_mmap(process_synthesized_event,
+							 session, machine, "_stext");
 	if (err < 0)
 		pr_err("Couldn't record kernel reference relocation symbol\n"
 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
 		       "Check /proc/kallsyms permission or run as root.\n");
 
-	err = event__synthesize_modules(process_synthesized_event,
-					session, machine);
+	err = perf_event__synthesize_modules(process_synthesized_event,
+					     session, machine);
 	if (err < 0)
 		pr_err("Couldn't record kernel module information.\n"
 		       "Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
 		       "Check /proc/modules permission or run as root.\n");
 
 	if (perf_guest)
-		perf_session__process_machines(session, event__synthesize_guest_os);
+		perf_session__process_machines(session,
+					       perf_event__synthesize_guest_os);
 
 	if (!system_wide)
-		event__synthesize_thread_map(threads, process_synthesized_event,
-					     session);
+		perf_event__synthesize_thread_map(evsel_list->threads,
+						  process_synthesized_event,
+						  session);
 	else
-		event__synthesize_threads(process_synthesized_event, session);
+		perf_event__synthesize_threads(process_synthesized_event,
+					       session);
 
 	if (realtime_prio) {
 		struct sched_param param;
@@ -789,17 +675,17 @@ static int __cmd_record(int argc, const char **argv)
 		if (hits == samples) {
 			if (done)
 				break;
-			err = poll(event_array, nr_poll, -1);
+			err = poll(evsel_list->pollfd, evsel_list->nr_fds, -1);
 			waking++;
 		}
 
 		if (done) {
-			for (i = 0; i < nr_cpu; i++) {
+			for (i = 0; i < evsel_list->cpus->nr; i++) {
 				struct perf_evsel *pos;
 
-				list_for_each_entry(pos, &evsel_list, node) {
+				list_for_each_entry(pos, &evsel_list->entries, node) {
 					for (thread = 0;
-						thread < threads->nr;
+						thread < evsel_list->threads->nr;
 						thread++)
 						ioctl(FD(pos, i, thread),
 							PERF_EVENT_IOC_DISABLE);
@@ -838,10 +724,10 @@ static const char * const record_usage[] = {
 static bool force, append_file;
 
 const struct option record_options[] = {
-	OPT_CALLBACK('e', "event", NULL, "event",
+	OPT_CALLBACK('e', "event", &evsel_list, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events),
-	OPT_CALLBACK(0, "filter", NULL, "filter",
+	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
 		     "event filter", parse_filter),
 	OPT_INTEGER('p', "pid", &target_pid,
 		    "record events on existing process id"),
@@ -884,6 +770,9 @@ const struct option record_options[] = {
 		    "do not update the buildid cache"),
 	OPT_BOOLEAN('B', "no-buildid", &no_buildid,
 		    "do not collect buildids in perf.data"),
+	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+		     "monitor event in cgroup name only",
+		     parse_cgroups),
 	OPT_END()
 };
 
@@ -892,6 +781,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 	int err = -ENOMEM;
 	struct perf_evsel *pos;
 
+	evsel_list = perf_evlist__new(NULL, NULL);
+	if (evsel_list == NULL)
+		return -ENOMEM;
+
 	argc = parse_options(argc, argv, record_options, record_usage,
 			    PARSE_OPT_STOP_AT_NON_OPTION);
 	if (!argc && target_pid == -1 && target_tid == -1 &&
@@ -908,12 +801,19 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 		write_mode = WRITE_FORCE;
 	}
 
+	if (nr_cgroups && !system_wide) {
+		fprintf(stderr, "cgroup monitoring only available in"
+			" system-wide mode\n");
+		usage_with_options(record_usage, record_options);
+	}
+
 	symbol__init();
 
 	if (no_buildid_cache || no_buildid)
 		disable_buildid_cache();
 
-	if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) {
+	if (evsel_list->nr_entries == 0 &&
+	    perf_evlist__add_default(evsel_list) < 0) {
 		pr_err("Not enough memory for event selector list\n");
 		goto out_symbol_exit;
 	}
@@ -921,27 +821,19 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 	if (target_pid != -1)
 		target_tid = target_pid;
 
-	threads = thread_map__new(target_pid, target_tid);
-	if (threads == NULL) {
-		pr_err("Problems finding threads of monitor\n");
+	if (perf_evlist__create_maps(evsel_list, target_pid,
+				     target_tid, cpu_list) < 0)
 		usage_with_options(record_usage, record_options);
-	}
 
-	cpus = cpu_map__new(cpu_list);
-	if (cpus == NULL) {
-		perror("failed to parse CPUs map");
-		return -1;
-	}
-
-	list_for_each_entry(pos, &evsel_list, node) {
-		if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
+	list_for_each_entry(pos, &evsel_list->entries, node) {
+		if (perf_evsel__alloc_fd(pos, evsel_list->cpus->nr,
+					 evsel_list->threads->nr) < 0)
 			goto out_free_fd;
 		if (perf_header__push_event(pos->attr.config, event_name(pos)))
 			goto out_free_fd;
 	}
-	event_array = malloc((sizeof(struct pollfd) * MAX_NR_CPUS *
-			      MAX_COUNTERS * threads->nr));
-	if (!event_array)
+
+	if (perf_evlist__alloc_pollfd(evsel_list) < 0)
 		goto out_free_fd;
 
 	if (user_interval != ULLONG_MAX)
@@ -959,16 +851,12 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
 	} else {
 		fprintf(stderr, "frequency and count are zero, aborting\n");
 		err = -EINVAL;
-		goto out_free_event_array;
+		goto out_free_fd;
 	}
 
 	err = __cmd_record(argc, argv);
-
-out_free_event_array:
-	free(event_array);
 out_free_fd:
-	thread_map__delete(threads);
-	threads = NULL;
+	perf_evlist__delete_maps(evsel_list);
 out_symbol_exit:
 	symbol__exit();
 	return err;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index c27e31f..b1b8200 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -9,6 +9,7 @@
 
 #include "util/util.h"
 
+#include "util/annotate.h"
 #include "util/color.h"
 #include <linux/list.h>
 #include "util/cache.h"
@@ -20,6 +21,8 @@
 
 #include "perf.h"
 #include "util/debug.h"
+#include "util/evlist.h"
+#include "util/evsel.h"
 #include "util/header.h"
 #include "util/session.h"
 
@@ -43,120 +46,79 @@ static const char	default_pretty_printing_style[] = "normal";
 static const char	*pretty_printing_style = default_pretty_printing_style;
 
 static char		callchain_default_opt[] = "fractal,0.5";
+static symbol_filter_t	annotate_init;
 
-static struct hists *perf_session__hists_findnew(struct perf_session *self,
-						 u64 event_stream, u32 type,
-						 u64 config)
-{
-	struct rb_node **p = &self->hists_tree.rb_node;
-	struct rb_node *parent = NULL;
-	struct hists *iter, *new;
-
-	while (*p != NULL) {
-		parent = *p;
-		iter = rb_entry(parent, struct hists, rb_node);
-		if (iter->config == config)
-			return iter;
-
-
-		if (config > iter->config)
-			p = &(*p)->rb_right;
-		else
-			p = &(*p)->rb_left;
-	}
-
-	new = malloc(sizeof(struct hists));
-	if (new == NULL)
-		return NULL;
-	memset(new, 0, sizeof(struct hists));
-	new->event_stream = event_stream;
-	new->config = config;
-	new->type = type;
-	rb_link_node(&new->rb_node, parent, p);
-	rb_insert_color(&new->rb_node, &self->hists_tree);
-	return new;
-}
-
-static int perf_session__add_hist_entry(struct perf_session *self,
+static int perf_session__add_hist_entry(struct perf_session *session,
 					struct addr_location *al,
-					struct sample_data *data)
+					struct perf_sample *sample)
 {
-	struct map_symbol *syms = NULL;
 	struct symbol *parent = NULL;
-	int err = -ENOMEM;
+	int err = 0;
 	struct hist_entry *he;
-	struct hists *hists;
-	struct perf_event_attr *attr;
-
-	if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) {
-		syms = perf_session__resolve_callchain(self, al->thread,
-						       data->callchain, &parent);
-		if (syms == NULL)
-			return -ENOMEM;
+	struct perf_evsel *evsel;
+
+	if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
+		err = perf_session__resolve_callchain(session, al->thread,
+						      sample->callchain, &parent);
+		if (err)
+			return err;
 	}
 
-	attr = perf_header__find_attr(data->id, &self->header);
-	if (attr)
-		hists = perf_session__hists_findnew(self, data->id, attr->type, attr->config);
-	else
-		hists = perf_session__hists_findnew(self, data->id, 0, 0);
-	if (hists == NULL)
-		goto out_free_syms;
-	he = __hists__add_entry(hists, al, parent, data->period);
+	evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+	if (evsel == NULL) {
+		/*
+		 * FIXME: Propagate this back, but at least we're in a builtin,
+		 * where exit() is allowed. ;-)
+		 */
+		ui__warning("Invalid %s file, contains samples with id %" PRIu64 " not in "
+			    "its header!\n", input_name, sample->id);
+		exit_browser(0);
+		exit(1);
+	}
+
+	he = __hists__add_entry(&evsel->hists, al, parent, sample->period);
 	if (he == NULL)
-		goto out_free_syms;
-	err = 0;
+		return -ENOMEM;
+
 	if (symbol_conf.use_callchain) {
-		err = callchain_append(he->callchain, data->callchain, syms,
-				       data->period);
+		err = callchain_append(he->callchain, &session->callchain_cursor,
+				       sample->period);
 		if (err)
-			goto out_free_syms;
+			return err;
 	}
 	/*
 	 * Only in the newt browser we are doing integrated annotation,
 	 * so we don't allocated the extra space needed because the stdio
 	 * code will not use it.
 	 */
-	if (use_browser > 0)
-		err = hist_entry__inc_addr_samples(he, al->addr);
-out_free_syms:
-	free(syms);
-	return err;
-}
+	if (al->sym != NULL && use_browser > 0) {
+		struct annotation *notes = symbol__annotation(he->ms.sym);
 
-static int add_event_total(struct perf_session *session,
-			   struct sample_data *data,
-			   struct perf_event_attr *attr)
-{
-	struct hists *hists;
+		assert(evsel != NULL);
 
-	if (attr)
-		hists = perf_session__hists_findnew(session, data->id,
-						    attr->type, attr->config);
-	else
-		hists = perf_session__hists_findnew(session, data->id, 0, 0);
+		err = -ENOMEM;
+		if (notes->src == NULL &&
+		    symbol__alloc_hist(he->ms.sym, session->evlist->nr_entries) < 0)
+			goto out;
 
-	if (!hists)
-		return -ENOMEM;
+		err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
+	}
 
-	hists->stats.total_period += data->period;
-	/*
-	 * FIXME: add_event_total should be moved from here to
-	 * perf_session__process_event so that the proper hist is passed to
-	 * the event_op methods.
-	 */
-	hists__inc_nr_events(hists, PERF_RECORD_SAMPLE);
-	session->hists.stats.total_period += data->period;
-	return 0;
+	evsel->hists.stats.total_period += sample->period;
+	hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
+out:
+	return err;
 }
 
-static int process_sample_event(event_t *event, struct sample_data *sample,
+
+static int process_sample_event(union perf_event *event,
+				struct perf_sample *sample,
 				struct perf_session *session)
 {
 	struct addr_location al;
-	struct perf_event_attr *attr;
 
-	if (event__preprocess_sample(event, session, &al, sample, NULL) < 0) {
+	if (perf_event__preprocess_sample(event, session, &al, sample,
+					  annotate_init) < 0) {
 		fprintf(stderr, "problem processing %d event, skipping it.\n",
 			event->header.type);
 		return -1;
@@ -170,26 +132,17 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
 		return -1;
 	}
 
-	attr = perf_header__find_attr(sample->id, &session->header);
-
-	if (add_event_total(session, sample, attr)) {
-		pr_debug("problem adding event period\n");
-		return -1;
-	}
-
 	return 0;
 }
 
-static int process_read_event(event_t *event, struct sample_data *sample __used,
-			      struct perf_session *session __used)
+static int process_read_event(union perf_event *event,
+			      struct perf_sample *sample __used,
+			      struct perf_session *session)
 {
-	struct perf_event_attr *attr;
-
-	attr = perf_header__find_attr(event->read.id, &session->header);
-
+	struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist,
+							 event->read.id);
 	if (show_threads) {
-		const char *name = attr ? __event_name(attr->type, attr->config)
-				   : "unknown";
+		const char *name = evsel ? event_name(evsel) : "unknown";
 		perf_read_values_add_value(&show_threads_values,
 					   event->read.pid, event->read.tid,
 					   event->read.id,
@@ -198,7 +151,7 @@ static int process_read_event(event_t *event, struct sample_data *sample __used,
 	}
 
 	dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
-		    attr ? __event_name(attr->type, attr->config) : "FAIL",
+		    evsel ? event_name(evsel) : "FAIL",
 		    event->read.value);
 
 	return 0;
@@ -222,7 +175,7 @@ static int perf_session__setup_sample_type(struct perf_session *self)
 	} else if (!dont_use_callchains && callchain_param.mode != CHAIN_NONE &&
 		   !symbol_conf.use_callchain) {
 			symbol_conf.use_callchain = true;
-			if (register_callchain_param(&callchain_param) < 0) {
+			if (callchain_register_param(&callchain_param) < 0) {
 				fprintf(stderr, "Can't register callchain"
 						" params\n");
 				return -EINVAL;
@@ -233,17 +186,17 @@ static int perf_session__setup_sample_type(struct perf_session *self)
 }
 
 static struct perf_event_ops event_ops = {
-	.sample	= process_sample_event,
-	.mmap	= event__process_mmap,
-	.comm	= event__process_comm,
-	.exit	= event__process_task,
-	.fork	= event__process_task,
-	.lost	= event__process_lost,
-	.read	= process_read_event,
-	.attr	= event__process_attr,
-	.event_type = event__process_event_type,
-	.tracing_data = event__process_tracing_data,
-	.build_id = event__process_build_id,
+	.sample		 = process_sample_event,
+	.mmap		 = perf_event__process_mmap,
+	.comm		 = perf_event__process_comm,
+	.exit		 = perf_event__process_task,
+	.fork		 = perf_event__process_task,
+	.lost		 = perf_event__process_lost,
+	.read		 = process_read_event,
+	.attr		 = perf_event__process_attr,
+	.event_type	 = perf_event__process_event_type,
+	.tracing_data	 = perf_event__process_tracing_data,
+	.build_id	 = perf_event__process_build_id,
 	.ordered_samples = true,
 	.ordering_requires_timestamps = true,
 };
@@ -269,21 +222,21 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self,
 	return ret + fprintf(fp, "\n#\n");
 }
 
-static int hists__tty_browse_tree(struct rb_root *tree, const char *help)
+static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
+					 const char *help)
 {
-	struct rb_node *next = rb_first(tree);
+	struct perf_evsel *pos;
 
-	while (next) {
-		struct hists *hists = rb_entry(next, struct hists, rb_node);
+	list_for_each_entry(pos, &evlist->entries, node) {
+		struct hists *hists = &pos->hists;
 		const char *evname = NULL;
 
 		if (rb_first(&hists->entries) != rb_last(&hists->entries))
-			evname = __event_name(hists->type, hists->config);
+			evname = event_name(pos);
 
 		hists__fprintf_nr_sample_events(hists, evname, stdout);
 		hists__fprintf(hists, NULL, false, stdout);
 		fprintf(stdout, "\n\n");
-		next = rb_next(&hists->rb_node);
 	}
 
 	if (sort_order == default_sort_order &&
@@ -304,8 +257,9 @@ static int hists__tty_browse_tree(struct rb_root *tree, const char *help)
 static int __cmd_report(void)
 {
 	int ret = -EINVAL;
+	u64 nr_samples;
 	struct perf_session *session;
-	struct rb_node *next;
+	struct perf_evsel *pos;
 	const char *help = "For a higher level overview, try: perf report --sort comm,dso";
 
 	signal(SIGINT, sig_handler);
@@ -336,20 +290,24 @@ static int __cmd_report(void)
 	if (verbose > 2)
 		perf_session__fprintf_dsos(session, stdout);
 
-	next = rb_first(&session->hists_tree);
-	while (next) {
-		struct hists *hists;
+	nr_samples = 0;
+	list_for_each_entry(pos, &session->evlist->entries, node) {
+		struct hists *hists = &pos->hists;
 
-		hists = rb_entry(next, struct hists, rb_node);
 		hists__collapse_resort(hists);
 		hists__output_resort(hists);
-		next = rb_next(&hists->rb_node);
+		nr_samples += hists->stats.nr_events[PERF_RECORD_SAMPLE];
+	}
+
+	if (nr_samples == 0) {
+		ui__warning("The %s file has no samples!\n", input_name);
+		goto out_delete;
 	}
 
 	if (use_browser > 0)
-		hists__tui_browse_tree(&session->hists_tree, help);
+		perf_evlist__tui_browse_hists(session->evlist, help);
 	else
-		hists__tty_browse_tree(&session->hists_tree, help);
+		perf_evlist__tty_browse_hists(session->evlist, help);
 
 out_delete:
 	/*
@@ -424,7 +382,7 @@ parse_callchain_opt(const struct option *opt __used, const char *arg,
 	if (tok2)
 		callchain_param.print_limit = strtod(tok2, &endptr);
 setup:
-	if (register_callchain_param(&callchain_param) < 0) {
+	if (callchain_register_param(&callchain_param) < 0) {
 		fprintf(stderr, "Can't register callchain params\n");
 		return -1;
 	}
@@ -498,7 +456,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 		use_browser = 1;
 
 	if (strcmp(input_name, "-") != 0)
-		setup_browser();
+		setup_browser(true);
 	else
 		use_browser = 0;
 	/*
@@ -507,7 +465,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
 	 * implementation.
 	 */
 	if (use_browser > 0) {
-		symbol_conf.priv_size = sizeof(struct sym_priv);
+		symbol_conf.priv_size = sizeof(struct annotation);
+		annotate_init	      = symbol__annotate_init;
 		/*
  		 * For searching by name on the "Browse map details".
  		 * providing it only in verbose mode not to bloat too
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 29acb89..a32f411 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -369,11 +369,6 @@ static void
 process_sched_event(struct task_desc *this_task __used, struct sched_atom *atom)
 {
 	int ret = 0;
-	u64 now;
-	long long delta;
-
-	now = get_nsecs();
-	delta = start_time + atom->timestamp - now;
 
 	switch (atom->type) {
 		case SCHED_EVENT_RUN:
@@ -562,7 +557,7 @@ static void wait_for_tasks(void)
 
 static void run_one_test(void)
 {
-	u64 T0, T1, delta, avg_delta, fluct, std_dev;
+	u64 T0, T1, delta, avg_delta, fluct;
 
 	T0 = get_nsecs();
 	wait_for_tasks();
@@ -578,7 +573,6 @@ static void run_one_test(void)
 	else
 		fluct = delta - avg_delta;
 	sum_fluct += fluct;
-	std_dev = sum_fluct / nr_runs / sqrt(nr_runs);
 	if (!run_avg)
 		run_avg = delta;
 	run_avg = (run_avg*9 + delta)/10;
@@ -799,7 +793,7 @@ replay_switch_event(struct trace_switch_event *switch_event,
 		    u64 timestamp,
 		    struct thread *thread __used)
 {
-	struct task_desc *prev, *next;
+	struct task_desc *prev, __used *next;
 	u64 timestamp0;
 	s64 delta;
 
@@ -1404,7 +1398,7 @@ map_switch_event(struct trace_switch_event *switch_event,
 		 u64 timestamp,
 		 struct thread *thread __used)
 {
-	struct thread *sched_out, *sched_in;
+	struct thread *sched_out __used, *sched_in;
 	int new_shortname;
 	u64 timestamp0;
 	s64 delta;
@@ -1580,9 +1574,9 @@ process_sched_migrate_task_event(void *data, struct perf_session *session,
 						 event, cpu, timestamp, thread);
 }
 
-static void
-process_raw_event(event_t *raw_event __used, struct perf_session *session,
-		  void *data, int cpu, u64 timestamp, struct thread *thread)
+static void process_raw_event(union perf_event *raw_event __used,
+			      struct perf_session *session, void *data, int cpu,
+			      u64 timestamp, struct thread *thread)
 {
 	struct event *event;
 	int type;
@@ -1607,7 +1601,8 @@ process_raw_event(event_t *raw_event __used, struct perf_session *session,
 		process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread);
 }
 
-static int process_sample_event(event_t *event, struct sample_data *sample,
+static int process_sample_event(union perf_event *event,
+				struct perf_sample *sample,
 				struct perf_session *session)
 {
 	struct thread *thread;
@@ -1635,9 +1630,9 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
 
 static struct perf_event_ops event_ops = {
 	.sample			= process_sample_event,
-	.comm			= event__process_comm,
-	.lost			= event__process_lost,
-	.fork			= event__process_task,
+	.comm			= perf_event__process_comm,
+	.lost			= perf_event__process_lost,
+	.fork			= perf_event__process_task,
 	.ordered_samples	= true,
 };
 
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index b766c2a..9f5fc54 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -12,6 +12,8 @@
 #include "util/trace-event.h"
 #include "util/parse-options.h"
 #include "util/util.h"
+#include "util/evlist.h"
+#include "util/evsel.h"
 
 static char const		*script_name;
 static char const		*generate_script_lang;
@@ -19,6 +21,183 @@ static bool			debug_mode;
 static u64			last_timestamp;
 static u64			nr_unordered;
 extern const struct option	record_options[];
+static bool			no_callchain;
+
+enum perf_output_field {
+	PERF_OUTPUT_COMM            = 1U << 0,
+	PERF_OUTPUT_TID             = 1U << 1,
+	PERF_OUTPUT_PID             = 1U << 2,
+	PERF_OUTPUT_TIME            = 1U << 3,
+	PERF_OUTPUT_CPU             = 1U << 4,
+	PERF_OUTPUT_EVNAME          = 1U << 5,
+	PERF_OUTPUT_TRACE           = 1U << 6,
+	PERF_OUTPUT_SYM             = 1U << 7,
+};
+
+struct output_option {
+	const char *str;
+	enum perf_output_field field;
+} all_output_options[] = {
+	{.str = "comm",  .field = PERF_OUTPUT_COMM},
+	{.str = "tid",   .field = PERF_OUTPUT_TID},
+	{.str = "pid",   .field = PERF_OUTPUT_PID},
+	{.str = "time",  .field = PERF_OUTPUT_TIME},
+	{.str = "cpu",   .field = PERF_OUTPUT_CPU},
+	{.str = "event", .field = PERF_OUTPUT_EVNAME},
+	{.str = "trace", .field = PERF_OUTPUT_TRACE},
+	{.str = "sym",   .field = PERF_OUTPUT_SYM},
+};
+
+/* default set to maintain compatibility with current format */
+static u64 output_fields[PERF_TYPE_MAX] = {
+	[PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
+			       PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
+			       PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+
+	[PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
+			       PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
+			       PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
+
+	[PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
+				 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
+				 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
+};
+
+static bool output_set_by_user;
+
+#define PRINT_FIELD(x)  (output_fields[attr->type] & PERF_OUTPUT_##x)
+
+static int perf_session__check_attr(struct perf_session *session,
+				    struct perf_event_attr *attr)
+{
+	if (PRINT_FIELD(TRACE) &&
+		!perf_session__has_traces(session, "record -R"))
+		return -EINVAL;
+
+	if (PRINT_FIELD(SYM)) {
+		if (!(session->sample_type & PERF_SAMPLE_IP)) {
+			pr_err("Samples do not contain IP data.\n");
+			return -EINVAL;
+		}
+		if (!no_callchain &&
+		    !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
+			symbol_conf.use_callchain = false;
+	}
+
+	if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
+		!(session->sample_type & PERF_SAMPLE_TID)) {
+		pr_err("Samples do not contain TID/PID data.\n");
+		return -EINVAL;
+	}
+
+	if (PRINT_FIELD(TIME) &&
+		!(session->sample_type & PERF_SAMPLE_TIME)) {
+		pr_err("Samples do not contain timestamps.\n");
+		return -EINVAL;
+	}
+
+	if (PRINT_FIELD(CPU) &&
+		!(session->sample_type & PERF_SAMPLE_CPU)) {
+		pr_err("Samples do not contain cpu.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void print_sample_start(struct perf_sample *sample,
+			       struct thread *thread,
+			       struct perf_event_attr *attr)
+{
+	int type;
+	struct event *event;
+	const char *evname = NULL;
+	unsigned long secs;
+	unsigned long usecs;
+	unsigned long long nsecs;
+
+	if (PRINT_FIELD(COMM)) {
+		if (latency_format)
+			printf("%8.8s ", thread->comm);
+		else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
+			printf("%s ", thread->comm);
+		else
+			printf("%16s ", thread->comm);
+	}
+
+	if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
+		printf("%5d/%-5d ", sample->pid, sample->tid);
+	else if (PRINT_FIELD(PID))
+		printf("%5d ", sample->pid);
+	else if (PRINT_FIELD(TID))
+		printf("%5d ", sample->tid);
+
+	if (PRINT_FIELD(CPU)) {
+		if (latency_format)
+			printf("%3d ", sample->cpu);
+		else
+			printf("[%03d] ", sample->cpu);
+	}
+
+	if (PRINT_FIELD(TIME)) {
+		nsecs = sample->time;
+		secs = nsecs / NSECS_PER_SEC;
+		nsecs -= secs * NSECS_PER_SEC;
+		usecs = nsecs / NSECS_PER_USEC;
+		printf("%5lu.%06lu: ", secs, usecs);
+	}
+
+	if (PRINT_FIELD(EVNAME)) {
+		if (attr->type == PERF_TYPE_TRACEPOINT) {
+			type = trace_parse_common_type(sample->raw_data);
+			event = trace_find_event(type);
+			if (event)
+				evname = event->name;
+		} else
+			evname = __event_name(attr->type, attr->config);
+
+		printf("%s: ", evname ? evname : "(unknown)");
+	}
+}
+
+static void process_event(union perf_event *event __unused,
+			  struct perf_sample *sample,
+			  struct perf_session *session,
+			  struct thread *thread)
+{
+	struct perf_event_attr *attr;
+	struct perf_evsel *evsel;
+
+	evsel = perf_evlist__id2evsel(session->evlist, sample->id);
+	if (evsel == NULL) {
+		pr_err("Invalid data. Contains samples with id not in "
+		       "its header!\n");
+		return;
+	}
+	attr = &evsel->attr;
+
+	if (output_fields[attr->type] == 0)
+		return;
+
+	if (perf_session__check_attr(session, attr) < 0)
+		return;
+
+	print_sample_start(sample, thread, attr);
+
+	if (PRINT_FIELD(TRACE))
+		print_trace_event(sample->cpu, sample->raw_data,
+				  sample->raw_size);
+
+	if (PRINT_FIELD(SYM)) {
+		if (!symbol_conf.use_callchain)
+			printf(" ");
+		else
+			printf("\n");
+		perf_session__print_symbols(event, sample, session);
+	}
+
+	printf("\n");
+}
 
 static int default_start_script(const char *script __unused,
 				int argc __unused,
@@ -40,7 +219,7 @@ static int default_generate_script(const char *outfile __unused)
 static struct scripting_ops default_scripting_ops = {
 	.start_script		= default_start_script,
 	.stop_script		= default_stop_script,
-	.process_event		= print_event,
+	.process_event		= process_event,
 	.generate_script	= default_generate_script,
 };
 
@@ -63,7 +242,8 @@ static int cleanup_scripting(void)
 
 static char const		*input_name = "perf.data";
 
-static int process_sample_event(event_t *event, struct sample_data *sample,
+static int process_sample_event(union perf_event *event,
+				struct perf_sample *sample,
 				struct perf_session *session)
 {
 	struct thread *thread = perf_session__findnew(session, event->ip.pid);
@@ -74,40 +254,34 @@ static int process_sample_event(event_t *event, struct sample_data *sample,
 		return -1;
 	}
 
-	if (session->sample_type & PERF_SAMPLE_RAW) {
-		if (debug_mode) {
-			if (sample->time < last_timestamp) {
-				pr_err("Samples misordered, previous: %" PRIu64
-					" this: %" PRIu64 "\n", last_timestamp,
-					sample->time);
-				nr_unordered++;
-			}
-			last_timestamp = sample->time;
-			return 0;
+	if (debug_mode) {
+		if (sample->time < last_timestamp) {
+			pr_err("Samples misordered, previous: %" PRIu64
+				" this: %" PRIu64 "\n", last_timestamp,
+				sample->time);
+			nr_unordered++;
 		}
-		/*
-		 * FIXME: better resolve from pid from the struct trace_entry
-		 * field, although it should be the same than this perf
-		 * event pid
-		 */
-		scripting_ops->process_event(sample->cpu, sample->raw_data,
-					     sample->raw_size,
-					     sample->time, thread->comm);
+		last_timestamp = sample->time;
+		return 0;
 	}
+	scripting_ops->process_event(event, sample, session, thread);
 
 	session->hists.stats.total_period += sample->period;
 	return 0;
 }
 
 static struct perf_event_ops event_ops = {
-	.sample	= process_sample_event,
-	.comm	= event__process_comm,
-	.attr	= event__process_attr,
-	.event_type = event__process_event_type,
-	.tracing_data = event__process_tracing_data,
-	.build_id = event__process_build_id,
-	.ordering_requires_timestamps = true,
+	.sample		 = process_sample_event,
+	.mmap		 = perf_event__process_mmap,
+	.comm		 = perf_event__process_comm,
+	.exit		 = perf_event__process_task,
+	.fork		 = perf_event__process_task,
+	.attr		 = perf_event__process_attr,
+	.event_type	 = perf_event__process_event_type,
+	.tracing_data	 = perf_event__process_tracing_data,
+	.build_id	 = perf_event__process_build_id,
 	.ordered_samples = true,
+	.ordering_requires_timestamps = true,
 };
 
 extern volatile int session_done;
@@ -279,6 +453,68 @@ static int parse_scriptname(const struct option *opt __used,
 	return 0;
 }
 
+static int parse_output_fields(const struct option *opt __used,
+			    const char *arg, int unset __used)
+{
+	char *tok;
+	int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
+	int rc = 0;
+	char *str = strdup(arg);
+	int type = -1;
+
+	if (!str)
+		return -ENOMEM;
+
+	tok = strtok(str, ":");
+	if (!tok) {
+		fprintf(stderr,
+			"Invalid field string - not prepended with type.");
+		return -EINVAL;
+	}
+
+	/* first word should state which event type user
+	 * is specifying the fields
+	 */
+	if (!strcmp(tok, "hw"))
+		type = PERF_TYPE_HARDWARE;
+	else if (!strcmp(tok, "sw"))
+		type = PERF_TYPE_SOFTWARE;
+	else if (!strcmp(tok, "trace"))
+		type = PERF_TYPE_TRACEPOINT;
+	else {
+		fprintf(stderr, "Invalid event type in field string.");
+		return -EINVAL;
+	}
+
+	output_fields[type] = 0;
+	while (1) {
+		tok = strtok(NULL, ",");
+		if (!tok)
+			break;
+		for (i = 0; i < imax; ++i) {
+			if (strcmp(tok, all_output_options[i].str) == 0) {
+				output_fields[type] |= all_output_options[i].field;
+				break;
+			}
+		}
+		if (i == imax) {
+			fprintf(stderr, "Invalid field requested.");
+			rc = -EINVAL;
+			break;
+		}
+	}
+
+	if (output_fields[type] == 0) {
+		pr_debug("No fields requested for %s type. "
+			 "Events will not be displayed\n", event_type(type));
+	}
+
+	output_set_by_user = true;
+
+	free(str);
+	return rc;
+}
+
 /* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
 static int is_directory(const char *base_path, const struct dirent *dent)
 {
@@ -591,6 +827,17 @@ static const struct option options[] = {
 		    "input file name"),
 	OPT_BOOLEAN('d', "debug-mode", &debug_mode,
 		   "do various checks like samples ordering and lost events"),
+	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
+		   "file", "vmlinux pathname"),
+	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
+		   "file", "kallsyms pathname"),
+	OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
+		    "When printing symbols do not display call chain"),
+	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
+		    "Look for files with symbols relative to this directory"),
+	OPT_CALLBACK('f', "fields", NULL, "str",
+		     "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym",
+		     parse_output_fields),
 
 	OPT_END()
 };
@@ -771,14 +1018,22 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
 	if (session == NULL)
 		return -ENOMEM;
 
-	if (strcmp(input_name, "-") &&
-	    !perf_session__has_traces(session, "record -R"))
-		return -EINVAL;
+	if (!no_callchain)
+		symbol_conf.use_callchain = true;
+	else
+		symbol_conf.use_callchain = false;
 
 	if (generate_script_lang) {
 		struct stat perf_stat;
+		int input;
+
+		if (output_set_by_user) {
+			fprintf(stderr,
+				"custom fields not supported for generated scripts");
+			return -1;
+		}
 
-		int input = open(input_name, O_RDONLY);
+		input = open(input_name, O_RDONLY);
 		if (input < 0) {
 			perror("failed to open file");
 			exit(-1);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a482a19..e2109f9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -43,11 +43,13 @@
 #include "util/parse-options.h"
 #include "util/parse-events.h"
 #include "util/event.h"
+#include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/debug.h"
 #include "util/header.h"
 #include "util/cpumap.h"
 #include "util/thread.h"
+#include "util/thread_map.h"
 
 #include <sys/prctl.h>
 #include <math.h>
@@ -71,8 +73,9 @@ static struct perf_event_attr default_attrs[] = {
 
 };
 
+struct perf_evlist		*evsel_list;
+
 static bool			system_wide			=  false;
-static struct cpu_map		*cpus;
 static int			run_idx				=  0;
 
 static int			run_count			=  1;
@@ -81,7 +84,6 @@ static bool			scale				=  true;
 static bool			no_aggr				= false;
 static pid_t			target_pid			= -1;
 static pid_t			target_tid			= -1;
-static struct thread_map	*threads;
 static pid_t			child_pid			= -1;
 static bool			null_run			=  false;
 static bool			big_num				=  true;
@@ -166,7 +168,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 				    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
 	if (system_wide)
-		return perf_evsel__open_per_cpu(evsel, cpus);
+		return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);
 
 	attr->inherit = !no_inherit;
 	if (target_pid == -1 && target_tid == -1) {
@@ -174,7 +176,7 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
 		attr->enable_on_exec = 1;
 	}
 
-	return perf_evsel__open_per_thread(evsel, threads);
+	return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
 }
 
 /*
@@ -199,7 +201,8 @@ static int read_counter_aggr(struct perf_evsel *counter)
 	u64 *count = counter->counts->aggr.values;
 	int i;
 
-	if (__perf_evsel__read(counter, cpus->nr, threads->nr, scale) < 0)
+	if (__perf_evsel__read(counter, evsel_list->cpus->nr,
+			       evsel_list->threads->nr, scale) < 0)
 		return -1;
 
 	for (i = 0; i < 3; i++)
@@ -232,7 +235,7 @@ static int read_counter(struct perf_evsel *counter)
 	u64 *count;
 	int cpu;
 
-	for (cpu = 0; cpu < cpus->nr; cpu++) {
+	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
 		if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
 			return -1;
 
@@ -297,7 +300,7 @@ static int run_perf_stat(int argc __used, const char **argv)
 		}
 
 		if (target_tid == -1 && target_pid == -1 && !system_wide)
-			threads->map[0] = child_pid;
+			evsel_list->threads->map[0] = child_pid;
 
 		/*
 		 * Wait for the child to be ready to exec.
@@ -309,7 +312,7 @@ static int run_perf_stat(int argc __used, const char **argv)
 		close(child_ready_pipe[0]);
 	}
 
-	list_for_each_entry(counter, &evsel_list, node) {
+	list_for_each_entry(counter, &evsel_list->entries, node) {
 		if (create_perf_stat_counter(counter) < 0) {
 			if (errno == -EPERM || errno == -EACCES) {
 				error("You may not have permission to collect %sstats.\n"
@@ -330,6 +333,12 @@ static int run_perf_stat(int argc __used, const char **argv)
 		}
 	}
 
+	if (perf_evlist__set_filters(evsel_list)) {
+		error("failed to set filter with %d (%s)\n", errno,
+			strerror(errno));
+		return -1;
+	}
+
 	/*
 	 * Enable counters and exec the command:
 	 */
@@ -347,14 +356,15 @@ static int run_perf_stat(int argc __used, const char **argv)
 	update_stats(&walltime_nsecs_stats, t1 - t0);
 
 	if (no_aggr) {
-		list_for_each_entry(counter, &evsel_list, node) {
+		list_for_each_entry(counter, &evsel_list->entries, node) {
 			read_counter(counter);
-			perf_evsel__close_fd(counter, cpus->nr, 1);
+			perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
 		}
 	} else {
-		list_for_each_entry(counter, &evsel_list, node) {
+		list_for_each_entry(counter, &evsel_list->entries, node) {
 			read_counter_aggr(counter);
-			perf_evsel__close_fd(counter, cpus->nr, threads->nr);
+			perf_evsel__close_fd(counter, evsel_list->cpus->nr,
+					     evsel_list->threads->nr);
 		}
 	}
 
@@ -382,10 +392,13 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
 	if (no_aggr)
 		sprintf(cpustr, "CPU%*d%s",
 			csv_output ? 0 : -4,
-			cpus->map[cpu], csv_sep);
+			evsel_list->cpus->map[cpu], csv_sep);
 
 	fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel));
 
+	if (evsel->cgrp)
+		fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
+
 	if (csv_output)
 		return;
 
@@ -410,12 +423,15 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
 	if (no_aggr)
 		sprintf(cpustr, "CPU%*d%s",
 			csv_output ? 0 : -4,
-			cpus->map[cpu], csv_sep);
+			evsel_list->cpus->map[cpu], csv_sep);
 	else
 		cpu = 0;
 
 	fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel));
 
+	if (evsel->cgrp)
+		fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
+
 	if (csv_output)
 		return;
 
@@ -456,9 +472,17 @@ static void print_counter_aggr(struct perf_evsel *counter)
 	int scaled = counter->counts->scaled;
 
 	if (scaled == -1) {
-		fprintf(stderr, "%*s%s%-24s\n",
+		fprintf(stderr, "%*s%s%*s",
 			csv_output ? 0 : 18,
-			"<not counted>", csv_sep, event_name(counter));
+			"<not counted>",
+			csv_sep,
+			csv_output ? 0 : -24,
+			event_name(counter));
+
+		if (counter->cgrp)
+			fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
+
+		fputc('\n', stderr);
 		return;
 	}
 
@@ -483,7 +507,6 @@ static void print_counter_aggr(struct perf_evsel *counter)
 		fprintf(stderr, "  (scaled from %.2f%%)",
 				100 * avg_running / avg_enabled);
 	}
-
 	fprintf(stderr, "\n");
 }
 
@@ -496,19 +519,23 @@ static void print_counter(struct perf_evsel *counter)
 	u64 ena, run, val;
 	int cpu;
 
-	for (cpu = 0; cpu < cpus->nr; cpu++) {
+	for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
 		val = counter->counts->cpu[cpu].val;
 		ena = counter->counts->cpu[cpu].ena;
 		run = counter->counts->cpu[cpu].run;
 		if (run == 0 || ena == 0) {
-			fprintf(stderr, "CPU%*d%s%*s%s%-24s",
+			fprintf(stderr, "CPU%*d%s%*s%s%*s",
 				csv_output ? 0 : -4,
-				cpus->map[cpu], csv_sep,
+				evsel_list->cpus->map[cpu], csv_sep,
 				csv_output ? 0 : 18,
 				"<not counted>", csv_sep,
+				csv_output ? 0 : -24,
 				event_name(counter));
 
-			fprintf(stderr, "\n");
+			if (counter->cgrp)
+				fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name);
+
+			fputc('\n', stderr);
 			continue;
 		}
 
@@ -525,7 +552,7 @@ static void print_counter(struct perf_evsel *counter)
 					100.0 * run / ena);
 			}
 		}
-		fprintf(stderr, "\n");
+		fputc('\n', stderr);
 	}
 }
 
@@ -555,10 +582,10 @@ static void print_stat(int argc, const char **argv)
 	}
 
 	if (no_aggr) {
-		list_for_each_entry(counter, &evsel_list, node)
+		list_for_each_entry(counter, &evsel_list->entries, node)
 			print_counter(counter);
 	} else {
-		list_for_each_entry(counter, &evsel_list, node)
+		list_for_each_entry(counter, &evsel_list->entries, node)
 			print_counter_aggr(counter);
 	}
 
@@ -610,9 +637,11 @@ static int stat__set_big_num(const struct option *opt __used,
 }
 
 static const struct option options[] = {
-	OPT_CALLBACK('e', "event", NULL, "event",
+	OPT_CALLBACK('e', "event", &evsel_list, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events),
+	OPT_CALLBACK(0, "filter", &evsel_list, "filter",
+		     "event filter", parse_filter),
 	OPT_BOOLEAN('i', "no-inherit", &no_inherit,
 		    "child tasks do not inherit counters"),
 	OPT_INTEGER('p', "pid", &target_pid,
@@ -638,6 +667,9 @@ static const struct option options[] = {
 		    "disable CPU count aggregation"),
 	OPT_STRING('x', "field-separator", &csv_sep, "separator",
 		   "print counts with custom separator"),
+	OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
+		     "monitor event in cgroup name only",
+		     parse_cgroups),
 	OPT_END()
 };
 
@@ -648,6 +680,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
 
 	setlocale(LC_ALL, "");
 
+	evsel_list = perf_evlist__new(NULL, NULL);
+	if (evsel_list == NULL)
+		return -ENOMEM;
+
 	argc = parse_options(argc, argv, options, stat_usage,
 		PARSE_OPT_STOP_AT_NON_OPTION);
 
@@ -674,49 +710,50 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
 	if (run_count <= 0)
 		usage_with_options(stat_usage, options);
 
-	/* no_aggr is for system-wide only */
-	if (no_aggr && !system_wide)
+	/* no_aggr, cgroup are for system-wide only */
+	if ((no_aggr || nr_cgroups) && !system_wide) {
+		fprintf(stderr, "both cgroup and no-aggregation "
+			"modes only available in system-wide mode\n");
+
 		usage_with_options(stat_usage, options);
+	}
 
 	/* Set attrs and nr_counters if no event is selected and !null_run */
-	if (!null_run && !nr_counters) {
+	if (!null_run && !evsel_list->nr_entries) {
 		size_t c;
 
-		nr_counters = ARRAY_SIZE(default_attrs);
-
 		for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
-			pos = perf_evsel__new(&default_attrs[c],
-					      nr_counters);
+			pos = perf_evsel__new(&default_attrs[c], c);
 			if (pos == NULL)
 				goto out;
-			list_add(&pos->node, &evsel_list);
+			perf_evlist__add(evsel_list, pos);
 		}
 	}
 
 	if (target_pid != -1)
 		target_tid = target_pid;
 
-	threads = thread_map__new(target_pid, target_tid);
-	if (threads == NULL) {
+	evsel_list->threads = thread_map__new(target_pid, target_tid);
+	if (evsel_list->threads == NULL) {
 		pr_err("Problems finding threads of monitor\n");
 		usage_with_options(stat_usage, options);
 	}
 
 	if (system_wide)
-		cpus = cpu_map__new(cpu_list);
+		evsel_list->cpus = cpu_map__new(cpu_list);
 	else
-		cpus = cpu_map__dummy_new();
+		evsel_list->cpus = cpu_map__dummy_new();
 
-	if (cpus == NULL) {
+	if (evsel_list->cpus == NULL) {
 		perror("failed to parse CPUs map");
 		usage_with_options(stat_usage, options);
 		return -1;
 	}
 
-	list_for_each_entry(pos, &evsel_list, node) {
+	list_for_each_entry(pos, &evsel_list->entries, node) {
 		if (perf_evsel__alloc_stat_priv(pos) < 0 ||
-		    perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
-		    perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
+		    perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0 ||
+		    perf_evsel__alloc_fd(pos, evsel_list->cpus->nr, evsel_list->threads->nr) < 0)
 			goto out_free_fd;
 	}
 
@@ -741,11 +778,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
 	if (status != -1)
 		print_stat(argc, argv);
 out_free_fd:
-	list_for_each_entry(pos, &evsel_list, node)
+	list_for_each_entry(pos, &evsel_list->entries, node)
 		perf_evsel__free_stat_priv(pos);
-	perf_evsel_list__delete();
+	perf_evlist__delete_maps(evsel_list);
 out:
-	thread_map__delete(threads);
-	threads = NULL;
+	perf_evlist__delete(evsel_list);
 	return status;
 }
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 5dcdba6..1b2106c 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -7,10 +7,11 @@
 
 #include "util/cache.h"
 #include "util/debug.h"
+#include "util/evlist.h"
 #include "util/parse-options.h"
-#include "util/session.h"
+#include "util/parse-events.h"
 #include "util/symbol.h"
-#include "util/thread.h"
+#include "util/thread_map.h"
 
 static long page_size;
 
@@ -238,14 +239,14 @@ out:
 #include "util/evsel.h"
 #include <sys/types.h>
 
-static int trace_event__id(const char *event_name)
+static int trace_event__id(const char *evname)
 {
 	char *filename;
 	int err = -1, fd;
 
 	if (asprintf(&filename,
 		     "/sys/kernel/debug/tracing/events/syscalls/%s/id",
-		     event_name) < 0)
+		     evname) < 0)
 		return -1;
 
 	fd = open(filename, O_RDONLY);
@@ -289,7 +290,7 @@ static int test__open_syscall_event(void)
 		goto out_thread_map_delete;
 	}
 
-	if (perf_evsel__open_per_thread(evsel, threads) < 0) {
+	if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) {
 		pr_debug("failed to open counter: %s, "
 			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
 			 strerror(errno));
@@ -347,9 +348,9 @@ static int test__open_syscall_event_on_all_cpus(void)
 	}
 
 	cpus = cpu_map__new(NULL);
-	if (threads == NULL) {
-		pr_debug("thread_map__new\n");
-		return -1;
+	if (cpus == NULL) {
+		pr_debug("cpu_map__new\n");
+		goto out_thread_map_delete;
 	}
 
 
@@ -364,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
 		goto out_thread_map_delete;
 	}
 
-	if (perf_evsel__open(evsel, cpus, threads) < 0) {
+	if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) {
 		pr_debug("failed to open counter: %s, "
 			 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
 			 strerror(errno));
@@ -408,6 +409,8 @@ static int test__open_syscall_event_on_all_cpus(void)
 		goto out_close_fd;
 	}
 
+	err = 0;
+
 	for (cpu = 0; cpu < cpus->nr; ++cpu) {
 		unsigned int expected;
 
@@ -416,18 +419,18 @@ static int test__open_syscall_event_on_all_cpus(void)
 
 		if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
 			pr_debug("perf_evsel__open_read_on_cpu\n");
-			goto out_close_fd;
+			err = -1;
+			break;
 		}
 
 		expected = nr_open_calls + cpu;
 		if (evsel->counts->cpu[cpu].val != expected) {
 			pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
 				 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
-			goto out_close_fd;
+			err = -1;
 		}
 	}
 
-	err = 0;
 out_close_fd:
 	perf_evsel__close_fd(evsel, 1, threads->nr);
 out_evsel_delete:
@@ -437,6 +440,159 @@ out_thread_map_delete:
 	return err;
 }
 
+/*
+ * This test will generate random numbers of calls to some getpid syscalls,
+ * then establish an mmap for a group of events that are created to monitor
+ * the syscalls.
+ *
+ * It will receive the events, using mmap, use its PERF_SAMPLE_ID generated
+ * sample.id field to map back to its respective perf_evsel instance.
+ *
+ * Then it checks if the number of syscalls reported as perf events by
+ * the kernel corresponds to the number of syscalls made.
+ */
+static int test__basic_mmap(void)
+{
+	int err = -1;
+	union perf_event *event;
+	struct thread_map *threads;
+	struct cpu_map *cpus;
+	struct perf_evlist *evlist;
+	struct perf_event_attr attr = {
+		.type		= PERF_TYPE_TRACEPOINT,
+		.read_format	= PERF_FORMAT_ID,
+		.sample_type	= PERF_SAMPLE_ID,
+		.watermark	= 0,
+	};
+	cpu_set_t cpu_set;
+	const char *syscall_names[] = { "getsid", "getppid", "getpgrp",
+					"getpgid", };
+	pid_t (*syscalls[])(void) = { (void *)getsid, getppid, getpgrp,
+				      (void*)getpgid };
+#define nsyscalls ARRAY_SIZE(syscall_names)
+	int ids[nsyscalls];
+	unsigned int nr_events[nsyscalls],
+		     expected_nr_events[nsyscalls], i, j;
+	struct perf_evsel *evsels[nsyscalls], *evsel;
+
+	for (i = 0; i < nsyscalls; ++i) {
+		char name[64];
+
+		snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
+		ids[i] = trace_event__id(name);
+		if (ids[i] < 0) {
+			pr_debug("Is debugfs mounted on /sys/kernel/debug?\n");
+			return -1;
+		}
+		nr_events[i] = 0;
+		expected_nr_events[i] = random() % 257;
+	}
+
+	threads = thread_map__new(-1, getpid());
+	if (threads == NULL) {
+		pr_debug("thread_map__new\n");
+		return -1;
+	}
+
+	cpus = cpu_map__new(NULL);
+	if (cpus == NULL) {
+		pr_debug("cpu_map__new\n");
+		goto out_free_threads;
+	}
+
+	CPU_ZERO(&cpu_set);
+	CPU_SET(cpus->map[0], &cpu_set);
+	sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+	if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
+		pr_debug("sched_setaffinity() failed on CPU %d: %s ",
+			 cpus->map[0], strerror(errno));
+		goto out_free_cpus;
+	}
+
+	evlist = perf_evlist__new(cpus, threads);
+	if (evlist == NULL) {
+		pr_debug("perf_evlist__new\n");
+		goto out_free_cpus;
+	}
+
+	/* anonymous union fields, can't be initialized above */
+	attr.wakeup_events = 1;
+	attr.sample_period = 1;
+
+	for (i = 0; i < nsyscalls; ++i) {
+		attr.config = ids[i];
+		evsels[i] = perf_evsel__new(&attr, i);
+		if (evsels[i] == NULL) {
+			pr_debug("perf_evsel__new\n");
+			goto out_free_evlist;
+		}
+
+		perf_evlist__add(evlist, evsels[i]);
+
+		if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) {
+			pr_debug("failed to open counter: %s, "
+				 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
+				 strerror(errno));
+			goto out_close_fd;
+		}
+	}
+
+	if (perf_evlist__mmap(evlist, 128, true) < 0) {
+		pr_debug("failed to mmap events: %d (%s)\n", errno,
+			 strerror(errno));
+		goto out_close_fd;
+	}
+
+	for (i = 0; i < nsyscalls; ++i)
+		for (j = 0; j < expected_nr_events[i]; ++j) {
+			int foo = syscalls[i]();
+			++foo;
+		}
+
+	while ((event = perf_evlist__read_on_cpu(evlist, 0)) != NULL) {
+		struct perf_sample sample;
+
+		if (event->header.type != PERF_RECORD_SAMPLE) {
+			pr_debug("unexpected %s event\n",
+				 perf_event__name(event->header.type));
+			goto out_munmap;
+		}
+
+		perf_event__parse_sample(event, attr.sample_type, false, &sample);
+		evsel = perf_evlist__id2evsel(evlist, sample.id);
+		if (evsel == NULL) {
+			pr_debug("event with id %" PRIu64
+				 " doesn't map to an evsel\n", sample.id);
+			goto out_munmap;
+		}
+		nr_events[evsel->idx]++;
+	}
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
+			pr_debug("expected %d %s events, got %d\n",
+				 expected_nr_events[evsel->idx],
+				 event_name(evsel), nr_events[evsel->idx]);
+			goto out_munmap;
+		}
+	}
+
+	err = 0;
+out_munmap:
+	perf_evlist__munmap(evlist);
+out_close_fd:
+	for (i = 0; i < nsyscalls; ++i)
+		perf_evsel__close_fd(evsels[i], 1, threads->nr);
+out_free_evlist:
+	perf_evlist__delete(evlist);
+out_free_cpus:
+	cpu_map__delete(cpus);
+out_free_threads:
+	thread_map__delete(threads);
+	return err;
+#undef nsyscalls
+}
+
 static struct test {
 	const char *desc;
 	int (*func)(void);
@@ -454,6 +610,10 @@ static struct test {
 		.func = test__open_syscall_event_on_all_cpus,
 	},
 	{
+		.desc = "read samples using the mmap interface",
+		.func = test__basic_mmap,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 0ace786..67c0459 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -273,21 +273,24 @@ static int cpus_cstate_state[MAX_CPUS];
 static u64 cpus_pstate_start_times[MAX_CPUS];
 static u64 cpus_pstate_state[MAX_CPUS];
 
-static int process_comm_event(event_t *event, struct sample_data *sample __used,
+static int process_comm_event(union perf_event *event,
+			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
 	pid_set_comm(event->comm.tid, event->comm.comm);
 	return 0;
 }
 
-static int process_fork_event(event_t *event, struct sample_data *sample __used,
+static int process_fork_event(union perf_event *event,
+			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
 	pid_fork(event->fork.pid, event->fork.ppid, event->fork.time);
 	return 0;
 }
 
-static int process_exit_event(event_t *event, struct sample_data *sample __used,
+static int process_exit_event(union perf_event *event,
+			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
 	pid_exit(event->fork.pid, event->fork.time);
@@ -483,8 +486,8 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te)
 }
 
 
-static int process_sample_event(event_t *event __used,
-				struct sample_data *sample,
+static int process_sample_event(union perf_event *event __used,
+				struct perf_sample *sample,
 				struct perf_session *session)
 {
 	struct trace_entry *te;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 5a29d9c..70f1075 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -20,11 +20,16 @@
 
 #include "perf.h"
 
+#include "util/annotate.h"
+#include "util/cache.h"
 #include "util/color.h"
+#include "util/evlist.h"
 #include "util/evsel.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
+#include "util/thread_map.h"
+#include "util/top.h"
 #include "util/util.h"
 #include <linux/rbtree.h>
 #include "util/parse-options.h"
@@ -45,7 +50,6 @@
 #include <errno.h>
 #include <time.h>
 #include <sched.h>
-#include <pthread.h>
 
 #include <sys/syscall.h>
 #include <sys/ioctl.h>
@@ -60,85 +64,42 @@
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 
+static struct perf_top top = {
+	.count_filter		= 5,
+	.delay_secs		= 2,
+	.display_weighted	= -1,
+	.target_pid		= -1,
+	.target_tid		= -1,
+	.active_symbols		= LIST_HEAD_INIT(top.active_symbols),
+	.active_symbols_lock	= PTHREAD_MUTEX_INITIALIZER,
+	.active_symbols_cond	= PTHREAD_COND_INITIALIZER,
+	.freq			= 1000, /* 1 KHz */
+};
+
 static bool			system_wide			=  false;
 
-static int			default_interval		=      0;
+static bool			use_tui, use_stdio;
 
-static int			count_filter			=      5;
-static int			print_entries;
+static int			default_interval		=      0;
 
-static int			target_pid			=     -1;
-static int			target_tid			=     -1;
-static struct thread_map	*threads;
 static bool			inherit				=  false;
-static struct cpu_map		*cpus;
 static int			realtime_prio			=      0;
 static bool			group				=  false;
 static unsigned int		page_size;
-static unsigned int		mmap_pages			=     16;
-static int			freq				=   1000; /* 1 KHz */
+static unsigned int		mmap_pages			=    128;
 
-static int			delay_secs			=      2;
-static bool			zero                            =  false;
 static bool			dump_symtab                     =  false;
 
-static bool			hide_kernel_symbols		=  false;
-static bool			hide_user_symbols		=  false;
 static struct winsize		winsize;
 
-/*
- * Source
- */
-
-struct source_line {
-	u64			eip;
-	unsigned long		count[MAX_COUNTERS];
-	char			*line;
-	struct source_line	*next;
-};
-
 static const char		*sym_filter			=   NULL;
-struct sym_entry		*sym_filter_entry		=   NULL;
 struct sym_entry		*sym_filter_entry_sched		=   NULL;
 static int			sym_pcnt_filter			=      5;
-static int			sym_counter			=      0;
-static struct perf_evsel	*sym_evsel			=   NULL;
-static int			display_weighted		=     -1;
-static const char		*cpu_list;
-
-/*
- * Symbols
- */
-
-struct sym_entry_source {
-	struct source_line	*source;
-	struct source_line	*lines;
-	struct source_line	**lines_tail;
-	pthread_mutex_t		lock;
-};
-
-struct sym_entry {
-	struct rb_node		rb_node;
-	struct list_head	node;
-	unsigned long		snap_count;
-	double			weight;
-	int			skip;
-	u16			name_len;
-	u8			origin;
-	struct map		*map;
-	struct sym_entry_source	*src;
-	unsigned long		count[0];
-};
 
 /*
  * Source functions
  */
 
-static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
-{
-       return ((void *)self) + symbol_conf.priv_size;
-}
-
 void get_term_dimensions(struct winsize *ws)
 {
 	char *s = getenv("LINES");
@@ -163,10 +124,10 @@ void get_term_dimensions(struct winsize *ws)
 
 static void update_print_entries(struct winsize *ws)
 {
-	print_entries = ws->ws_row;
+	top.print_entries = ws->ws_row;
 
-	if (print_entries > 9)
-		print_entries -= 9;
+	if (top.print_entries > 9)
+		top.print_entries -= 9;
 }
 
 static void sig_winch_handler(int sig __used)
@@ -178,12 +139,9 @@ static void sig_winch_handler(int sig __used)
 static int parse_source(struct sym_entry *syme)
 {
 	struct symbol *sym;
-	struct sym_entry_source *source;
+	struct annotation *notes;
 	struct map *map;
-	FILE *file;
-	char command[PATH_MAX*2];
-	const char *path;
-	u64 len;
+	int err = -1;
 
 	if (!syme)
 		return -1;
@@ -194,411 +152,137 @@ static int parse_source(struct sym_entry *syme)
 	/*
 	 * We can't annotate with just /proc/kallsyms
 	 */
-	if (map->dso->origin == DSO__ORIG_KERNEL)
+	if (map->dso->symtab_type == SYMTAB__KALLSYMS) {
+		pr_err("Can't annotate %s: No vmlinux file was found in the "
+		       "path\n", sym->name);
+		sleep(1);
 		return -1;
-
-	if (syme->src == NULL) {
-		syme->src = zalloc(sizeof(*source));
-		if (syme->src == NULL)
-			return -1;
-		pthread_mutex_init(&syme->src->lock, NULL);
 	}
 
-	source = syme->src;
-
-	if (source->lines) {
-		pthread_mutex_lock(&source->lock);
+	notes = symbol__annotation(sym);
+	if (notes->src != NULL) {
+		pthread_mutex_lock(&notes->lock);
 		goto out_assign;
 	}
-	path = map->dso->long_name;
-
-	len = sym->end - sym->start;
-
-	sprintf(command,
-		"objdump --start-address=%#0*" PRIx64 " --stop-address=%#0*" PRIx64 " -dS %s",
-		BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
-		BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
-
-	file = popen(command, "r");
-	if (!file)
-		return -1;
 
-	pthread_mutex_lock(&source->lock);
-	source->lines_tail = &source->lines;
-	while (!feof(file)) {
-		struct source_line *src;
-		size_t dummy = 0;
-		char *c, *sep;
+	pthread_mutex_lock(&notes->lock);
 
-		src = malloc(sizeof(struct source_line));
-		assert(src != NULL);
-		memset(src, 0, sizeof(struct source_line));
-
-		if (getline(&src->line, &dummy, file) < 0)
-			break;
-		if (!src->line)
-			break;
-
-		c = strchr(src->line, '\n');
-		if (c)
-			*c = 0;
-
-		src->next = NULL;
-		*source->lines_tail = src;
-		source->lines_tail = &src->next;
-
-		src->eip = strtoull(src->line, &sep, 16);
-		if (*sep == ':')
-			src->eip = map__objdump_2ip(map, src->eip);
-		else /* this line has no ip info (e.g. source line) */
-			src->eip = 0;
+	if (symbol__alloc_hist(sym, top.evlist->nr_entries) < 0) {
+		pthread_mutex_unlock(&notes->lock);
+		pr_err("Not enough memory for annotating '%s' symbol!\n",
+		       sym->name);
+		sleep(1);
+		return err;
 	}
-	pclose(file);
+
+	err = symbol__annotate(sym, syme->map, 0);
+	if (err == 0) {
 out_assign:
-	sym_filter_entry = syme;
-	pthread_mutex_unlock(&source->lock);
-	return 0;
+		top.sym_filter_entry = syme;
+	}
+
+	pthread_mutex_unlock(&notes->lock);
+	return err;
 }
 
 static void __zero_source_counters(struct sym_entry *syme)
 {
-	int i;
-	struct source_line *line;
-
-	line = syme->src->lines;
-	while (line) {
-		for (i = 0; i < nr_counters; i++)
-			line->count[i] = 0;
-		line = line->next;
-	}
+	struct symbol *sym = sym_entry__symbol(syme);
+	symbol__annotate_zero_histograms(sym);
 }
 
 static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
 {
-	struct source_line *line;
-
-	if (syme != sym_filter_entry)
-		return;
+	struct annotation *notes;
+	struct symbol *sym;
 
-	if (pthread_mutex_trylock(&syme->src->lock))
+	if (syme != top.sym_filter_entry)
 		return;
 
-	if (syme->src == NULL || syme->src->source == NULL)
-		goto out_unlock;
-
-	for (line = syme->src->lines; line; line = line->next) {
-		/* skip lines without IP info */
-		if (line->eip == 0)
-			continue;
-		if (line->eip == ip) {
-			line->count[counter]++;
-			break;
-		}
-		if (line->eip > ip)
-			break;
-	}
-out_unlock:
-	pthread_mutex_unlock(&syme->src->lock);
-}
-
-#define PATTERN_LEN		(BITS_PER_LONG / 4 + 2)
-
-static void lookup_sym_source(struct sym_entry *syme)
-{
-	struct symbol *symbol = sym_entry__symbol(syme);
-	struct source_line *line;
-	char pattern[PATTERN_LEN + 1];
-
-	sprintf(pattern, "%0*" PRIx64 " <", BITS_PER_LONG / 4,
-		map__rip_2objdump(syme->map, symbol->start));
-
-	pthread_mutex_lock(&syme->src->lock);
-	for (line = syme->src->lines; line; line = line->next) {
-		if (memcmp(line->line, pattern, PATTERN_LEN) == 0) {
-			syme->src->source = line;
-			break;
-		}
-	}
-	pthread_mutex_unlock(&syme->src->lock);
-}
+	sym = sym_entry__symbol(syme);
+	notes = symbol__annotation(sym);
 
-static void show_lines(struct source_line *queue, int count, int total)
-{
-	int i;
-	struct source_line *line;
+	if (pthread_mutex_trylock(&notes->lock))
+		return;
 
-	line = queue;
-	for (i = 0; i < count; i++) {
-		float pcnt = 100.0*(float)line->count[sym_counter]/(float)total;
+	ip = syme->map->map_ip(syme->map, ip);
+	symbol__inc_addr_samples(sym, syme->map, counter, ip);
 
-		printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line);
-		line = line->next;
-	}
+	pthread_mutex_unlock(&notes->lock);
 }
 
-#define TRACE_COUNT     3
-
 static void show_details(struct sym_entry *syme)
 {
+	struct annotation *notes;
 	struct symbol *symbol;
-	struct source_line *line;
-	struct source_line *line_queue = NULL;
-	int displayed = 0;
-	int line_queue_count = 0, total = 0, more = 0;
+	int more;
 
 	if (!syme)
 		return;
 
-	if (!syme->src->source)
-		lookup_sym_source(syme);
-
-	if (!syme->src->source)
-		return;
-
 	symbol = sym_entry__symbol(syme);
-	printf("Showing %s for %s\n", event_name(sym_evsel), symbol->name);
-	printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
-
-	pthread_mutex_lock(&syme->src->lock);
-	line = syme->src->source;
-	while (line) {
-		total += line->count[sym_counter];
-		line = line->next;
-	}
-
-	line = syme->src->source;
-	while (line) {
-		float pcnt = 0.0;
-
-		if (!line_queue_count)
-			line_queue = line;
-		line_queue_count++;
-
-		if (line->count[sym_counter])
-			pcnt = 100.0 * line->count[sym_counter] / (float)total;
-		if (pcnt >= (float)sym_pcnt_filter) {
-			if (displayed <= print_entries)
-				show_lines(line_queue, line_queue_count, total);
-			else more++;
-			displayed += line_queue_count;
-			line_queue_count = 0;
-			line_queue = NULL;
-		} else if (line_queue_count > TRACE_COUNT) {
-			line_queue = line_queue->next;
-			line_queue_count--;
-		}
-
-		line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
-		line = line->next;
-	}
-	pthread_mutex_unlock(&syme->src->lock);
-	if (more)
-		printf("%d lines not displayed, maybe increase display entries [e]\n", more);
-}
-
-/*
- * Symbols will be added here in event__process_sample and will get out
- * after decayed.
- */
-static LIST_HEAD(active_symbols);
-static pthread_mutex_t active_symbols_lock = PTHREAD_MUTEX_INITIALIZER;
+	notes = symbol__annotation(symbol);
 
-/*
- * Ordering weight: count-1 * count-2 * ... / count-n
- */
-static double sym_weight(const struct sym_entry *sym)
-{
-	double weight = sym->snap_count;
-	int counter;
+	pthread_mutex_lock(&notes->lock);
 
-	if (!display_weighted)
-		return weight;
-
-	for (counter = 1; counter < nr_counters-1; counter++)
-		weight *= sym->count[counter];
+	if (notes->src == NULL)
+		goto out_unlock;
 
-	weight /= (sym->count[counter] + 1);
+	printf("Showing %s for %s\n", event_name(top.sym_evsel), symbol->name);
+	printf("  Events  Pcnt (>=%d%%)\n", sym_pcnt_filter);
 
-	return weight;
+	more = symbol__annotate_printf(symbol, syme->map, top.sym_evsel->idx,
+				       0, sym_pcnt_filter, top.print_entries, 4);
+	if (top.zero)
+		symbol__annotate_zero_histogram(symbol, top.sym_evsel->idx);
+	else
+		symbol__annotate_decay_histogram(symbol, top.sym_evsel->idx);
+	if (more != 0)
+		printf("%d lines not displayed, maybe increase display entries [e]\n", more);
+out_unlock:
+	pthread_mutex_unlock(&notes->lock);
 }
 
-static long			samples;
-static long			kernel_samples, us_samples;
-static long			exact_samples;
-static long			guest_us_samples, guest_kernel_samples;
 static const char		CONSOLE_CLEAR[] = "[H[2J";
 
 static void __list_insert_active_sym(struct sym_entry *syme)
 {
-	list_add(&syme->node, &active_symbols);
+	list_add(&syme->node, &top.active_symbols);
 }
 
-static void list_remove_active_sym(struct sym_entry *syme)
+static void print_sym_table(struct perf_session *session)
 {
-	pthread_mutex_lock(&active_symbols_lock);
-	list_del_init(&syme->node);
-	pthread_mutex_unlock(&active_symbols_lock);
-}
-
-static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
-{
-	struct rb_node **p = &tree->rb_node;
-	struct rb_node *parent = NULL;
-	struct sym_entry *iter;
-
-	while (*p != NULL) {
-		parent = *p;
-		iter = rb_entry(parent, struct sym_entry, rb_node);
-
-		if (se->weight > iter->weight)
-			p = &(*p)->rb_left;
-		else
-			p = &(*p)->rb_right;
-	}
-
-	rb_link_node(&se->rb_node, parent, p);
-	rb_insert_color(&se->rb_node, tree);
-}
-
-static void print_sym_table(void)
-{
-	int printed = 0, j;
-	struct perf_evsel *counter;
-	int snap = !display_weighted ? sym_counter : 0;
-	float samples_per_sec = samples/delay_secs;
-	float ksamples_per_sec = kernel_samples/delay_secs;
-	float us_samples_per_sec = (us_samples)/delay_secs;
-	float guest_kernel_samples_per_sec = (guest_kernel_samples)/delay_secs;
-	float guest_us_samples_per_sec = (guest_us_samples)/delay_secs;
-	float esamples_percent = (100.0*exact_samples)/samples;
-	float sum_ksamples = 0.0;
-	struct sym_entry *syme, *n;
-	struct rb_root tmp = RB_ROOT;
+	char bf[160];
+	int printed = 0;
 	struct rb_node *nd;
-	int sym_width = 0, dso_width = 0, dso_short_width = 0;
+	struct sym_entry *syme;
+	struct rb_root tmp = RB_ROOT;
 	const int win_width = winsize.ws_col - 1;
-
-	samples = us_samples = kernel_samples = exact_samples = 0;
-	guest_kernel_samples = guest_us_samples = 0;
-
-	/* Sort the active symbols */
-	pthread_mutex_lock(&active_symbols_lock);
-	syme = list_entry(active_symbols.next, struct sym_entry, node);
-	pthread_mutex_unlock(&active_symbols_lock);
-
-	list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
-		syme->snap_count = syme->count[snap];
-		if (syme->snap_count != 0) {
-
-			if ((hide_user_symbols &&
-			     syme->origin == PERF_RECORD_MISC_USER) ||
-			    (hide_kernel_symbols &&
-			     syme->origin == PERF_RECORD_MISC_KERNEL)) {
-				list_remove_active_sym(syme);
-				continue;
-			}
-			syme->weight = sym_weight(syme);
-			rb_insert_active_sym(&tmp, syme);
-			sum_ksamples += syme->snap_count;
-
-			for (j = 0; j < nr_counters; j++)
-				syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
-		} else
-			list_remove_active_sym(syme);
-	}
+	int sym_width, dso_width, dso_short_width;
+	float sum_ksamples = perf_top__decay_samples(&top, &tmp);
 
 	puts(CONSOLE_CLEAR);
 
-	printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
-	if (!perf_guest) {
-		printf("   PerfTop:%8.0f irqs/sec  kernel:%4.1f%%"
-			"  exact: %4.1f%% [",
-			samples_per_sec,
-			100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
-					 samples_per_sec)),
-			esamples_percent);
-	} else {
-		printf("   PerfTop:%8.0f irqs/sec  kernel:%4.1f%% us:%4.1f%%"
-			" guest kernel:%4.1f%% guest us:%4.1f%%"
-			" exact: %4.1f%% [",
-			samples_per_sec,
-			100.0 - (100.0 * ((samples_per_sec-ksamples_per_sec) /
-					  samples_per_sec)),
-			100.0 - (100.0 * ((samples_per_sec-us_samples_per_sec) /
-					  samples_per_sec)),
-			100.0 - (100.0 * ((samples_per_sec -
-						guest_kernel_samples_per_sec) /
-					  samples_per_sec)),
-			100.0 - (100.0 * ((samples_per_sec -
-					   guest_us_samples_per_sec) /
-					  samples_per_sec)),
-			esamples_percent);
-	}
-
-	if (nr_counters == 1 || !display_weighted) {
-		struct perf_evsel *first;
-		first = list_entry(evsel_list.next, struct perf_evsel, node);
-		printf("%" PRIu64, (uint64_t)first->attr.sample_period);
-		if (freq)
-			printf("Hz ");
-		else
-			printf(" ");
-	}
-
-	if (!display_weighted)
-		printf("%s", event_name(sym_evsel));
-	else list_for_each_entry(counter, &evsel_list, node) {
-		if (counter->idx)
-			printf("/");
-
-		printf("%s", event_name(counter));
-	}
+	perf_top__header_snprintf(&top, bf, sizeof(bf));
+	printf("%s\n", bf);
 
-	printf( "], ");
-
-	if (target_pid != -1)
-		printf(" (target_pid: %d", target_pid);
-	else if (target_tid != -1)
-		printf(" (target_tid: %d", target_tid);
-	else
-		printf(" (all");
-
-	if (cpu_list)
-		printf(", CPU%s: %s)\n", cpus->nr > 1 ? "s" : "", cpu_list);
-	else {
-		if (target_tid != -1)
-			printf(")\n");
-		else
-			printf(", %d CPU%s)\n", cpus->nr, cpus->nr > 1 ? "s" : "");
-	}
+	perf_top__reset_sample_counters(&top);
 
 	printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
 
-	if (sym_filter_entry) {
-		show_details(sym_filter_entry);
-		return;
+	if (session->hists.stats.total_lost != 0) {
+		color_fprintf(stdout, PERF_COLOR_RED, "WARNING:");
+		printf(" LOST %" PRIu64 " events, Check IO/CPU overload\n",
+		       session->hists.stats.total_lost);
 	}
 
-	/*
-	 * Find the longest symbol name that will be displayed
-	 */
-	for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
-		syme = rb_entry(nd, struct sym_entry, rb_node);
-		if (++printed > print_entries ||
-		    (int)syme->snap_count < count_filter)
-			continue;
-
-		if (syme->map->dso->long_name_len > dso_width)
-			dso_width = syme->map->dso->long_name_len;
-
-		if (syme->map->dso->short_name_len > dso_short_width)
-			dso_short_width = syme->map->dso->short_name_len;
-
-		if (syme->name_len > sym_width)
-			sym_width = syme->name_len;
+	if (top.sym_filter_entry) {
+		show_details(top.sym_filter_entry);
+		return;
 	}
 
-	printed = 0;
+	perf_top__find_widths(&top, &tmp, &dso_width, &dso_short_width,
+			      &sym_width);
 
 	if (sym_width + dso_width > winsize.ws_col - 29) {
 		dso_width = dso_short_width;
@@ -606,7 +290,7 @@ static void print_sym_table(void)
 			sym_width = winsize.ws_col - dso_width - 29;
 	}
 	putchar('\n');
-	if (nr_counters == 1)
+	if (top.evlist->nr_entries == 1)
 		printf("             samples  pcnt");
 	else
 		printf("   weight    samples  pcnt");
@@ -615,7 +299,7 @@ static void print_sym_table(void)
 		printf("         RIP       ");
 	printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
 	printf("   %s    _______ _____",
-	       nr_counters == 1 ? "      " : "______");
+	       top.evlist->nr_entries == 1 ? "      " : "______");
 	if (verbose)
 		printf(" ________________");
 	printf(" %-*.*s", sym_width, sym_width, graph_line);
@@ -628,13 +312,14 @@ static void print_sym_table(void)
 
 		syme = rb_entry(nd, struct sym_entry, rb_node);
 		sym = sym_entry__symbol(syme);
-		if (++printed > print_entries || (int)syme->snap_count < count_filter)
+		if (++printed > top.print_entries ||
+		    (int)syme->snap_count < top.count_filter)
 			continue;
 
 		pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
 					 sum_ksamples));
 
-		if (nr_counters == 1 || !display_weighted)
+		if (top.evlist->nr_entries == 1 || !top.display_weighted)
 			printf("%20.2f ", syme->weight);
 		else
 			printf("%9.1f %10ld ", syme->weight, syme->snap_count);
@@ -693,10 +378,8 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
 
 	/* zero counters of active symbol */
 	if (syme) {
-		pthread_mutex_lock(&syme->src->lock);
 		__zero_source_counters(syme);
 		*target = NULL;
-		pthread_mutex_unlock(&syme->src->lock);
 	}
 
 	fprintf(stdout, "\n%s: ", msg);
@@ -707,11 +390,11 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
 	if (p)
 		*p = 0;
 
-	pthread_mutex_lock(&active_symbols_lock);
-	syme = list_entry(active_symbols.next, struct sym_entry, node);
-	pthread_mutex_unlock(&active_symbols_lock);
+	pthread_mutex_lock(&top.active_symbols_lock);
+	syme = list_entry(top.active_symbols.next, struct sym_entry, node);
+	pthread_mutex_unlock(&top.active_symbols_lock);
 
-	list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
+	list_for_each_entry_safe_from(syme, n, &top.active_symbols, node) {
 		struct symbol *sym = sym_entry__symbol(syme);
 
 		if (!strcmp(buf, sym->name)) {
@@ -735,34 +418,34 @@ static void print_mapped_keys(void)
 {
 	char *name = NULL;
 
-	if (sym_filter_entry) {
-		struct symbol *sym = sym_entry__symbol(sym_filter_entry);
+	if (top.sym_filter_entry) {
+		struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
 		name = sym->name;
 	}
 
 	fprintf(stdout, "\nMapped keys:\n");
-	fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", delay_secs);
-	fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", print_entries);
+	fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", top.delay_secs);
+	fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", top.print_entries);
 
-	if (nr_counters > 1)
-		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(sym_evsel));
+	if (top.evlist->nr_entries > 1)
+		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(top.sym_evsel));
 
-	fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", count_filter);
+	fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top.count_filter);
 
 	fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
 	fprintf(stdout, "\t[s]     annotate symbol.                   \t(%s)\n", name?: "NULL");
 	fprintf(stdout, "\t[S]     stop annotation.\n");
 
-	if (nr_counters > 1)
-		fprintf(stdout, "\t[w]     toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
+	if (top.evlist->nr_entries > 1)
+		fprintf(stdout, "\t[w]     toggle display weighted/count[E]r. \t(%d)\n", top.display_weighted ? 1 : 0);
 
 	fprintf(stdout,
 		"\t[K]     hide kernel_symbols symbols.     \t(%s)\n",
-		hide_kernel_symbols ? "yes" : "no");
+		top.hide_kernel_symbols ? "yes" : "no");
 	fprintf(stdout,
 		"\t[U]     hide user symbols.               \t(%s)\n",
-		hide_user_symbols ? "yes" : "no");
-	fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", zero ? 1 : 0);
+		top.hide_user_symbols ? "yes" : "no");
+	fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", top.zero ? 1 : 0);
 	fprintf(stdout, "\t[qQ]    quit.\n");
 }
 
@@ -783,7 +466,7 @@ static int key_mapped(int c)
 			return 1;
 		case 'E':
 		case 'w':
-			return nr_counters > 1 ? 1 : 0;
+			return top.evlist->nr_entries > 1 ? 1 : 0;
 		default:
 			break;
 	}
@@ -818,47 +501,48 @@ static void handle_keypress(struct perf_session *session, int c)
 
 	switch (c) {
 		case 'd':
-			prompt_integer(&delay_secs, "Enter display delay");
-			if (delay_secs < 1)
-				delay_secs = 1;
+			prompt_integer(&top.delay_secs, "Enter display delay");
+			if (top.delay_secs < 1)
+				top.delay_secs = 1;
 			break;
 		case 'e':
-			prompt_integer(&print_entries, "Enter display entries (lines)");
-			if (print_entries == 0) {
+			prompt_integer(&top.print_entries, "Enter display entries (lines)");
+			if (top.print_entries == 0) {
 				sig_winch_handler(SIGWINCH);
 				signal(SIGWINCH, sig_winch_handler);
 			} else
 				signal(SIGWINCH, SIG_DFL);
 			break;
 		case 'E':
-			if (nr_counters > 1) {
+			if (top.evlist->nr_entries > 1) {
+				int counter;
 				fprintf(stderr, "\nAvailable events:");
 
-				list_for_each_entry(sym_evsel, &evsel_list, node)
-					fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
+				list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
+					fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel));
 
-				prompt_integer(&sym_counter, "Enter details event counter");
+				prompt_integer(&counter, "Enter details event counter");
 
-				if (sym_counter >= nr_counters) {
-					sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
-					sym_counter = 0;
-					fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
+				if (counter >= top.evlist->nr_entries) {
+					top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
+					fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel));
 					sleep(1);
 					break;
 				}
-				list_for_each_entry(sym_evsel, &evsel_list, node)
-					if (sym_evsel->idx == sym_counter)
+				list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
+					if (top.sym_evsel->idx == counter)
 						break;
-			} else sym_counter = 0;
+			} else
+				top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
 			break;
 		case 'f':
-			prompt_integer(&count_filter, "Enter display event count filter");
+			prompt_integer(&top.count_filter, "Enter display event count filter");
 			break;
 		case 'F':
 			prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
 			break;
 		case 'K':
-			hide_kernel_symbols = !hide_kernel_symbols;
+			top.hide_kernel_symbols = !top.hide_kernel_symbols;
 			break;
 		case 'q':
 		case 'Q':
@@ -867,34 +551,50 @@ static void handle_keypress(struct perf_session *session, int c)
 				perf_session__fprintf_dsos(session, stderr);
 			exit(0);
 		case 's':
-			prompt_symbol(&sym_filter_entry, "Enter details symbol");
+			prompt_symbol(&top.sym_filter_entry, "Enter details symbol");
 			break;
 		case 'S':
-			if (!sym_filter_entry)
+			if (!top.sym_filter_entry)
 				break;
 			else {
-				struct sym_entry *syme = sym_filter_entry;
+				struct sym_entry *syme = top.sym_filter_entry;
 
-				pthread_mutex_lock(&syme->src->lock);
-				sym_filter_entry = NULL;
+				top.sym_filter_entry = NULL;
 				__zero_source_counters(syme);
-				pthread_mutex_unlock(&syme->src->lock);
 			}
 			break;
 		case 'U':
-			hide_user_symbols = !hide_user_symbols;
+			top.hide_user_symbols = !top.hide_user_symbols;
 			break;
 		case 'w':
-			display_weighted = ~display_weighted;
+			top.display_weighted = ~top.display_weighted;
 			break;
 		case 'z':
-			zero = !zero;
+			top.zero = !top.zero;
 			break;
 		default:
 			break;
 	}
 }
 
+static void *display_thread_tui(void *arg __used)
+{
+	int err = 0;
+	pthread_mutex_lock(&top.active_symbols_lock);
+	while (list_empty(&top.active_symbols)) {
+		err = pthread_cond_wait(&top.active_symbols_cond,
+					&top.active_symbols_lock);
+		if (err)
+			break;
+	}
+	pthread_mutex_unlock(&top.active_symbols_lock);
+	if (!err)
+		perf_top__tui_browser(&top);
+	exit_browser(0);
+	exit(0);
+	return NULL;
+}
+
 static void *display_thread(void *arg __used)
 {
 	struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
@@ -909,13 +609,13 @@ static void *display_thread(void *arg __used)
 	tc.c_cc[VTIME] = 0;
 
 repeat:
-	delay_msecs = delay_secs * 1000;
+	delay_msecs = top.delay_secs * 1000;
 	tcsetattr(0, TCSANOW, &tc);
 	/* trash return*/
 	getc(stdin);
 
 	do {
-		print_sym_table();
+		print_sym_table(session);
 	} while (!poll(&stdin_poll, 1, delay_msecs) == 1);
 
 	c = getc(stdin);
@@ -930,6 +630,7 @@ repeat:
 /* Tag samples to be skipped. */
 static const char *skip_symbols[] = {
 	"default_idle",
+	"native_safe_halt",
 	"cpu_idle",
 	"enter_idle",
 	"exit_idle",
@@ -965,9 +666,9 @@ static int symbol_filter(struct map *map, struct symbol *sym)
 
 	syme = symbol__priv(sym);
 	syme->map = map;
-	syme->src = NULL;
+	symbol__annotate_init(map, sym);
 
-	if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
+	if (!top.sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
 		/* schedule initial sym_filter_entry setup */
 		sym_filter_entry_sched = syme;
 		sym_filter = NULL;
@@ -975,49 +676,45 @@ static int symbol_filter(struct map *map, struct symbol *sym)
 
 	for (i = 0; skip_symbols[i]; i++) {
 		if (!strcmp(skip_symbols[i], name)) {
-			syme->skip = 1;
+			sym->ignore = true;
 			break;
 		}
 	}
 
-	if (!syme->skip)
-		syme->name_len = strlen(sym->name);
-
 	return 0;
 }
 
-static void event__process_sample(const event_t *self,
-				  struct sample_data *sample,
-				  struct perf_session *session,
-				  struct perf_evsel *evsel)
+static void perf_event__process_sample(const union perf_event *event,
+				       struct perf_sample *sample,
+				       struct perf_session *session)
 {
-	u64 ip = self->ip.ip;
+	u64 ip = event->ip.ip;
 	struct sym_entry *syme;
 	struct addr_location al;
 	struct machine *machine;
-	u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	u8 origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 
-	++samples;
+	++top.samples;
 
 	switch (origin) {
 	case PERF_RECORD_MISC_USER:
-		++us_samples;
-		if (hide_user_symbols)
+		++top.us_samples;
+		if (top.hide_user_symbols)
 			return;
 		machine = perf_session__find_host_machine(session);
 		break;
 	case PERF_RECORD_MISC_KERNEL:
-		++kernel_samples;
-		if (hide_kernel_symbols)
+		++top.kernel_samples;
+		if (top.hide_kernel_symbols)
 			return;
 		machine = perf_session__find_host_machine(session);
 		break;
 	case PERF_RECORD_MISC_GUEST_KERNEL:
-		++guest_kernel_samples;
-		machine = perf_session__find_machine(session, self->ip.pid);
+		++top.guest_kernel_samples;
+		machine = perf_session__find_machine(session, event->ip.pid);
 		break;
 	case PERF_RECORD_MISC_GUEST_USER:
-		++guest_us_samples;
+		++top.guest_us_samples;
 		/*
 		 * TODO: we don't process guest user from host side
 		 * except simple counting.
@@ -1029,15 +726,15 @@ static void event__process_sample(const event_t *self,
 
 	if (!machine && perf_guest) {
 		pr_err("Can't find guest [%d]'s kernel information\n",
-			self->ip.pid);
+			event->ip.pid);
 		return;
 	}
 
-	if (self->header.misc & PERF_RECORD_MISC_EXACT_IP)
-		exact_samples++;
+	if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
+		top.exact_samples++;
 
-	if (event__preprocess_sample(self, session, &al, sample,
-				     symbol_filter) < 0 ||
+	if (perf_event__preprocess_sample(event, session, &al, sample,
+					  symbol_filter) < 0 ||
 	    al.filtered)
 		return;
 
@@ -1055,8 +752,9 @@ static void event__process_sample(const event_t *self,
 		 */
 		if (al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
 		    RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
-			pr_err("The %s file can't be used\n",
-			       symbol_conf.vmlinux_name);
+			ui__warning("The %s file can't be used\n",
+				    symbol_conf.vmlinux_name);
+			exit_browser(0);
 			exit(1);
 		}
 
@@ -1065,13 +763,13 @@ static void event__process_sample(const event_t *self,
 
 	/* let's see, whether we need to install initial sym_filter_entry */
 	if (sym_filter_entry_sched) {
-		sym_filter_entry = sym_filter_entry_sched;
+		top.sym_filter_entry = sym_filter_entry_sched;
 		sym_filter_entry_sched = NULL;
-		if (parse_source(sym_filter_entry) < 0) {
-			struct symbol *sym = sym_entry__symbol(sym_filter_entry);
+		if (parse_source(top.sym_filter_entry) < 0) {
+			struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
 
 			pr_err("Can't annotate %s", sym->name);
-			if (sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) {
+			if (top.sym_filter_entry->map->dso->symtab_type == SYMTAB__KALLSYMS) {
 				pr_err(": No vmlinux file was found in the path:\n");
 				machine__fprintf_vmlinux_path(machine, stderr);
 			} else
@@ -1081,167 +779,73 @@ static void event__process_sample(const event_t *self,
 	}
 
 	syme = symbol__priv(al.sym);
-	if (!syme->skip) {
+	if (!al.sym->ignore) {
+		struct perf_evsel *evsel;
+
+		evsel = perf_evlist__id2evsel(top.evlist, sample->id);
+		assert(evsel != NULL);
 		syme->count[evsel->idx]++;
-		syme->origin = origin;
 		record_precise_ip(syme, evsel->idx, ip);
-		pthread_mutex_lock(&active_symbols_lock);
-		if (list_empty(&syme->node) || !syme->node.next)
+		pthread_mutex_lock(&top.active_symbols_lock);
+		if (list_empty(&syme->node) || !syme->node.next) {
+			static bool first = true;
 			__list_insert_active_sym(syme);
-		pthread_mutex_unlock(&active_symbols_lock);
+			if (first) {
+				pthread_cond_broadcast(&top.active_symbols_cond);
+				first = false;
+			}
+		}
+		pthread_mutex_unlock(&top.active_symbols_lock);
 	}
 }
 
-struct mmap_data {
-	void			*base;
-	int			mask;
-	unsigned int		prev;
-};
-
-static int perf_evsel__alloc_mmap_per_thread(struct perf_evsel *evsel,
-					     int ncpus, int nthreads)
-{
-	evsel->priv = xyarray__new(ncpus, nthreads, sizeof(struct mmap_data));
-	return evsel->priv != NULL ? 0 : -ENOMEM;
-}
-
-static void perf_evsel__free_mmap(struct perf_evsel *evsel)
-{
-	xyarray__delete(evsel->priv);
-	evsel->priv = NULL;
-}
-
-static unsigned int mmap_read_head(struct mmap_data *md)
-{
-	struct perf_event_mmap_page *pc = md->base;
-	int head;
-
-	head = pc->data_head;
-	rmb();
-
-	return head;
-}
-
-static void perf_session__mmap_read_counter(struct perf_session *self,
-					    struct perf_evsel *evsel,
-					    int cpu, int thread_idx)
+static void perf_session__mmap_read_cpu(struct perf_session *self, int cpu)
 {
-	struct xyarray *mmap_array = evsel->priv;
-	struct mmap_data *md = xyarray__entry(mmap_array, cpu, thread_idx);
-	unsigned int head = mmap_read_head(md);
-	unsigned int old = md->prev;
-	unsigned char *data = md->base + page_size;
-	struct sample_data sample;
-	int diff;
-
-	/*
-	 * If we're further behind than half the buffer, there's a chance
-	 * the writer will bite our tail and mess up the samples under us.
-	 *
-	 * If we somehow ended up ahead of the head, we got messed up.
-	 *
-	 * In either case, truncate and restart at head.
-	 */
-	diff = head - old;
-	if (diff > md->mask / 2 || diff < 0) {
-		fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
-
-		/*
-		 * head points to a known good entry, start there.
-		 */
-		old = head;
-	}
-
-	for (; old != head;) {
-		event_t *event = (event_t *)&data[old & md->mask];
-
-		event_t event_copy;
+	struct perf_sample sample;
+	union perf_event *event;
 
-		size_t size = event->header.size;
+	while ((event = perf_evlist__read_on_cpu(top.evlist, cpu)) != NULL) {
+		perf_session__parse_sample(self, event, &sample);
 
-		/*
-		 * Event straddles the mmap boundary -- header should always
-		 * be inside due to u64 alignment of output.
-		 */
-		if ((old & md->mask) + size != ((old + size) & md->mask)) {
-			unsigned int offset = old;
-			unsigned int len = min(sizeof(*event), size), cpy;
-			void *dst = &event_copy;
-
-			do {
-				cpy = min(md->mask + 1 - (offset & md->mask), len);
-				memcpy(dst, &data[offset & md->mask], cpy);
-				offset += cpy;
-				dst += cpy;
-				len -= cpy;
-			} while (len);
-
-			event = &event_copy;
-		}
-
-		event__parse_sample(event, self, &sample);
 		if (event->header.type == PERF_RECORD_SAMPLE)
-			event__process_sample(event, &sample, self, evsel);
+			perf_event__process_sample(event, &sample, self);
 		else
-			event__process(event, &sample, self);
-		old += size;
+			perf_event__process(event, &sample, self);
 	}
-
-	md->prev = old;
 }
 
-static struct pollfd *event_array;
-
 static void perf_session__mmap_read(struct perf_session *self)
 {
-	struct perf_evsel *counter;
-	int i, thread_index;
-
-	for (i = 0; i < cpus->nr; i++) {
-		list_for_each_entry(counter, &evsel_list, node) {
-			for (thread_index = 0;
-				thread_index < threads->nr;
-				thread_index++) {
-				perf_session__mmap_read_counter(self,
-					counter, i, thread_index);
-			}
-		}
-	}
-}
+	int i;
 
-int nr_poll;
-int group_fd;
+	for (i = 0; i < top.evlist->cpus->nr; i++)
+		perf_session__mmap_read_cpu(self, i);
+}
 
-static void start_counter(int i, struct perf_evsel *evsel)
+static void start_counters(struct perf_evlist *evlist)
 {
-	struct xyarray *mmap_array = evsel->priv;
-	struct mmap_data *mm;
-	struct perf_event_attr *attr;
-	int cpu = -1;
-	int thread_index;
-
-	if (target_tid == -1)
-		cpu = cpus->map[i];
+	struct perf_evsel *counter;
 
-	attr = &evsel->attr;
+	list_for_each_entry(counter, &evlist->entries, node) {
+		struct perf_event_attr *attr = &counter->attr;
 
-	attr->sample_type	= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
+		attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
-	if (freq) {
-		attr->sample_type	|= PERF_SAMPLE_PERIOD;
-		attr->freq		= 1;
-		attr->sample_freq	= freq;
-	}
+		if (top.freq) {
+			attr->sample_type |= PERF_SAMPLE_PERIOD;
+			attr->freq	  = 1;
+			attr->sample_freq = top.freq;
+		}
 
-	attr->inherit		= (cpu < 0) && inherit;
-	attr->mmap		= 1;
+		if (evlist->nr_entries > 1) {
+			attr->sample_type |= PERF_SAMPLE_ID;
+			attr->read_format |= PERF_FORMAT_ID;
+		}
 
-	for (thread_index = 0; thread_index < threads->nr; thread_index++) {
+		attr->mmap = 1;
 try_again:
-		FD(evsel, i, thread_index) = sys_perf_event_open(attr,
-				threads->map[thread_index], cpu, group_fd, 0);
-
-		if (FD(evsel, i, thread_index) < 0) {
+		if (perf_evsel__open(counter, top.evlist->cpus,
+				     top.evlist->threads, group, inherit) < 0) {
 			int err = errno;
 
 			if (err == EPERM || err == EACCES)
@@ -1253,8 +857,8 @@ try_again:
 			 * based cpu-clock-tick sw counter, which
 			 * is always available even if no PMU support:
 			 */
-			if (attr->type == PERF_TYPE_HARDWARE
-					&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {
+			if (attr->type == PERF_TYPE_HARDWARE &&
+			    attr->config == PERF_COUNT_HW_CPU_CYCLES) {
 
 				if (verbose)
 					warning(" ... trying to fall back to cpu-clock-ticks\n");
@@ -1264,39 +868,22 @@ try_again:
 				goto try_again;
 			}
 			printf("\n");
-			error("sys_perf_event_open() syscall returned with %d (%s).  /bin/dmesg may provide additional information.\n",
-					FD(evsel, i, thread_index), strerror(err));
+			error("sys_perf_event_open() syscall returned with %d "
+			      "(%s).  /bin/dmesg may provide additional information.\n",
+			      err, strerror(err));
 			die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
 			exit(-1);
 		}
-		assert(FD(evsel, i, thread_index) >= 0);
-		fcntl(FD(evsel, i, thread_index), F_SETFL, O_NONBLOCK);
-
-		/*
-		 * First counter acts as the group leader:
-		 */
-		if (group && group_fd == -1)
-			group_fd = FD(evsel, i, thread_index);
-
-		event_array[nr_poll].fd = FD(evsel, i, thread_index);
-		event_array[nr_poll].events = POLLIN;
-		nr_poll++;
-
-		mm = xyarray__entry(mmap_array, i, thread_index);
-		mm->prev = 0;
-		mm->mask = mmap_pages*page_size - 1;
-		mm->base = mmap(NULL, (mmap_pages+1)*page_size,
-				PROT_READ, MAP_SHARED, FD(evsel, i, thread_index), 0);
-		if (mm->base == MAP_FAILED)
-			die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 	}
+
+	if (perf_evlist__mmap(evlist, mmap_pages, false) < 0)
+		die("failed to mmap with %d (%s)\n", errno, strerror(errno));
 }
 
 static int __cmd_top(void)
 {
 	pthread_t thread;
-	struct perf_evsel *counter;
-	int i, ret;
+	int ret __used;
 	/*
 	 * FIXME: perf_session__new should allow passing a O_MMAP, so that all this
 	 * mmap reading, etc is encapsulated in it. Use O_WRONLY for now.
@@ -1305,23 +892,23 @@ static int __cmd_top(void)
 	if (session == NULL)
 		return -ENOMEM;
 
-	if (target_tid != -1)
-		event__synthesize_thread_map(threads, event__process, session);
+	if (top.target_tid != -1)
+		perf_event__synthesize_thread_map(top.evlist->threads,
+						  perf_event__process, session);
 	else
-		event__synthesize_threads(event__process, session);
+		perf_event__synthesize_threads(perf_event__process, session);
 
-	for (i = 0; i < cpus->nr; i++) {
-		group_fd = -1;
-		list_for_each_entry(counter, &evsel_list, node)
-			start_counter(i, counter);
-	}
+	start_counters(top.evlist);
+	session->evlist = top.evlist;
+	perf_session__update_sample_type(session);
 
 	/* Wait for a minimal set of events before starting the snapshot */
-	poll(&event_array[0], nr_poll, 100);
+	poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
 
 	perf_session__mmap_read(session);
 
-	if (pthread_create(&thread, NULL, display_thread, session)) {
+	if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
+							     display_thread), session)) {
 		printf("Could not create display thread.\n");
 		exit(-1);
 	}
@@ -1337,12 +924,12 @@ static int __cmd_top(void)
 	}
 
 	while (1) {
-		int hits = samples;
+		u64 hits = top.samples;
 
 		perf_session__mmap_read(session);
 
-		if (hits == samples)
-			ret = poll(event_array, nr_poll, 100);
+		if (hits == top.samples)
+			ret = poll(top.evlist->pollfd, top.evlist->nr_fds, 100);
 	}
 
 	return 0;
@@ -1354,31 +941,31 @@ static const char * const top_usage[] = {
 };
 
 static const struct option options[] = {
-	OPT_CALLBACK('e', "event", NULL, "event",
+	OPT_CALLBACK('e', "event", &top.evlist, "event",
 		     "event selector. use 'perf list' to list available events",
 		     parse_events),
 	OPT_INTEGER('c', "count", &default_interval,
 		    "event period to sample"),
-	OPT_INTEGER('p', "pid", &target_pid,
+	OPT_INTEGER('p', "pid", &top.target_pid,
 		    "profile events on existing process id"),
-	OPT_INTEGER('t', "tid", &target_tid,
+	OPT_INTEGER('t', "tid", &top.target_tid,
 		    "profile events on existing thread id"),
 	OPT_BOOLEAN('a', "all-cpus", &system_wide,
 			    "system-wide collection from all CPUs"),
-	OPT_STRING('C', "cpu", &cpu_list, "cpu",
+	OPT_STRING('C', "cpu", &top.cpu_list, "cpu",
 		    "list of cpus to monitor"),
 	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
 		   "file", "vmlinux pathname"),
-	OPT_BOOLEAN('K', "hide_kernel_symbols", &hide_kernel_symbols,
+	OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
 		    "hide kernel symbols"),
 	OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
 	OPT_INTEGER('r', "realtime", &realtime_prio,
 		    "collect data with this RT SCHED_FIFO priority"),
-	OPT_INTEGER('d', "delay", &delay_secs,
+	OPT_INTEGER('d', "delay", &top.delay_secs,
 		    "number of seconds to delay between refreshes"),
 	OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
 			    "dump the symbol table used for profiling"),
-	OPT_INTEGER('f', "count-filter", &count_filter,
+	OPT_INTEGER('f', "count-filter", &top.count_filter,
 		    "only display functions with more events than this"),
 	OPT_BOOLEAN('g', "group", &group,
 			    "put the counters into a counter group"),
@@ -1386,14 +973,16 @@ static const struct option options[] = {
 		    "child tasks inherit counters"),
 	OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
 		    "symbol to annotate"),
-	OPT_BOOLEAN('z', "zero", &zero,
+	OPT_BOOLEAN('z', "zero", &top.zero,
 		    "zero history across updates"),
-	OPT_INTEGER('F', "freq", &freq,
+	OPT_INTEGER('F', "freq", &top.freq,
 		    "profile at this frequency"),
-	OPT_INTEGER('E', "entries", &print_entries,
+	OPT_INTEGER('E', "entries", &top.print_entries,
 		    "display this many functions"),
-	OPT_BOOLEAN('U', "hide_user_symbols", &hide_user_symbols,
+	OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
 		    "hide user symbols"),
+	OPT_BOOLEAN(0, "tui", &use_tui, "Use the TUI interface"),
+	OPT_BOOLEAN(0, "stdio", &use_stdio, "Use the stdio interface"),
 	OPT_INCR('v', "verbose", &verbose,
 		    "be more verbose (show counter open errors, etc)"),
 	OPT_END()
@@ -1404,64 +993,68 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 	struct perf_evsel *pos;
 	int status = -ENOMEM;
 
+	top.evlist = perf_evlist__new(NULL, NULL);
+	if (top.evlist == NULL)
+		return -ENOMEM;
+
 	page_size = sysconf(_SC_PAGE_SIZE);
 
 	argc = parse_options(argc, argv, options, top_usage, 0);
 	if (argc)
 		usage_with_options(top_usage, options);
 
-	if (target_pid != -1)
-		target_tid = target_pid;
+	/*
+ 	 * XXX For now start disabled, only using TUI if explicitely asked for.
+ 	 * Change that when handle_keys equivalent gets written, live annotation
+ 	 * done, etc.
+ 	 */
+	use_browser = 0;
 
-	threads = thread_map__new(target_pid, target_tid);
-	if (threads == NULL) {
-		pr_err("Problems finding threads of monitor\n");
-		usage_with_options(top_usage, options);
-	}
+	if (use_stdio)
+		use_browser = 0;
+	else if (use_tui)
+		use_browser = 1;
 
-	event_array = malloc((sizeof(struct pollfd) *
-			      MAX_NR_CPUS * MAX_COUNTERS * threads->nr));
-	if (!event_array)
-		return -ENOMEM;
+	setup_browser(false);
 
 	/* CPU and PID are mutually exclusive */
-	if (target_tid > 0 && cpu_list) {
+	if (top.target_tid > 0 && top.cpu_list) {
 		printf("WARNING: PID switch overriding CPU\n");
 		sleep(1);
-		cpu_list = NULL;
+		top.cpu_list = NULL;
 	}
 
-	if (!nr_counters && perf_evsel_list__create_default() < 0) {
+	if (top.target_pid != -1)
+		top.target_tid = top.target_pid;
+
+	if (perf_evlist__create_maps(top.evlist, top.target_pid,
+				     top.target_tid, top.cpu_list) < 0)
+		usage_with_options(top_usage, options);
+
+	if (!top.evlist->nr_entries &&
+	    perf_evlist__add_default(top.evlist) < 0) {
 		pr_err("Not enough memory for event selector list\n");
 		return -ENOMEM;
 	}
 
-	if (delay_secs < 1)
-		delay_secs = 1;
+	if (top.delay_secs < 1)
+		top.delay_secs = 1;
 
 	/*
 	 * User specified count overrides default frequency.
 	 */
 	if (default_interval)
-		freq = 0;
-	else if (freq) {
-		default_interval = freq;
+		top.freq = 0;
+	else if (top.freq) {
+		default_interval = top.freq;
 	} else {
 		fprintf(stderr, "frequency and count are zero, aborting\n");
 		exit(EXIT_FAILURE);
 	}
 
-	if (target_tid != -1)
-		cpus = cpu_map__dummy_new();
-	else
-		cpus = cpu_map__new(cpu_list);
-
-	if (cpus == NULL)
-		usage_with_options(top_usage, options);
-
-	list_for_each_entry(pos, &evsel_list, node) {
-		if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
-		    perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
+	list_for_each_entry(pos, &top.evlist->entries, node) {
+		if (perf_evsel__alloc_fd(pos, top.evlist->cpus->nr,
+					 top.evlist->threads->nr) < 0)
 			goto out_free_fd;
 		/*
 		 * Fill in the ones not specifically initialized via -c:
@@ -1472,26 +1065,28 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
 		pos->attr.sample_period = default_interval;
 	}
 
-	sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
+	if (perf_evlist__alloc_pollfd(top.evlist) < 0 ||
+	    perf_evlist__alloc_mmap(top.evlist) < 0)
+		goto out_free_fd;
+
+	top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
 
-	symbol_conf.priv_size = (sizeof(struct sym_entry) +
-				 (nr_counters + 1) * sizeof(unsigned long));
+	symbol_conf.priv_size = (sizeof(struct sym_entry) + sizeof(struct annotation) +
+				 (top.evlist->nr_entries + 1) * sizeof(unsigned long));
 
 	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
 	if (symbol__init() < 0)
 		return -1;
 
 	get_term_dimensions(&winsize);
-	if (print_entries == 0) {
+	if (top.print_entries == 0) {
 		update_print_entries(&winsize);
 		signal(SIGWINCH, sig_winch_handler);
 	}
 
 	status = __cmd_top();
 out_free_fd:
-	list_for_each_entry(pos, &evsel_list, node)
-		perf_evsel__free_mmap(pos);
-	perf_evsel_list__delete();
+	perf_evlist__delete(top.evlist);
 
 	return status;
 }
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index c7798c7..4702e24 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -19,6 +19,7 @@ extern int cmd_bench(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
 extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
 extern int cmd_diff(int argc, const char **argv, const char *prefix);
+extern int cmd_evlist(int argc, const char **argv, const char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
 extern int cmd_sched(int argc, const char **argv, const char *prefix);
 extern int cmd_list(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 16b5088..d695fe4 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -8,6 +8,7 @@ perf-bench			mainporcelain common
 perf-buildid-cache		mainporcelain common
 perf-buildid-list		mainporcelain common
 perf-diff			mainporcelain common
+perf-evlist			mainporcelain common
 perf-inject			mainporcelain common
 perf-list			mainporcelain common
 perf-sched			mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 595d0f4..ec635b7 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -313,6 +313,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "buildid-cache", cmd_buildid_cache, 0 },
 		{ "buildid-list", cmd_buildid_list, 0 },
 		{ "diff",	cmd_diff,	0 },
+		{ "evlist",	cmd_evlist,	0 },
 		{ "help",	cmd_help,	0 },
 		{ "list",	cmd_list,	0 },
 		{ "record",	cmd_record,	0 },
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 95aaf56..a5fc660 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -94,6 +94,32 @@ void get_term_dimensions(struct winsize *ws);
 #include "util/types.h"
 #include <stdbool.h>
 
+struct perf_mmap {
+	void			*base;
+	int			mask;
+	unsigned int		prev;
+};
+
+static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm)
+{
+	struct perf_event_mmap_page *pc = mm->base;
+	int head = pc->data_head;
+	rmb();
+	return head;
+}
+
+static inline void perf_mmap__write_tail(struct perf_mmap *md,
+					 unsigned long tail)
+{
+	struct perf_event_mmap_page *pc = md->base;
+
+	/*
+	 * ensure all reads are done before we write the tail out.
+	 */
+	/* mb(); */
+	pc->data_tail = tail;
+}
+
 /*
  * prctl(PR_TASK_PERF_EVENTS_DISABLE) will (cheaply) disable all
  * counters in the current task.
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
new file mode 100755
index 0000000..df638c4
--- /dev/null
+++ b/tools/perf/python/twatch.py
@@ -0,0 +1,41 @@
+#! /usr/bin/python
+# -*- python -*-
+# -*- coding: utf-8 -*-
+#   twatch - Experimental use of the perf python interface
+#   Copyright (C) 2011 Arnaldo Carvalho de Melo <acme@redhat.com>
+#
+#   This application is free software; 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 application is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#   General Public License for more details.
+
+import perf
+
+def main():
+	cpus = perf.cpu_map()
+	threads = perf.thread_map()
+	evsel = perf.evsel(task = 1, comm = 1, mmap = 0,
+			   wakeup_events = 1, sample_period = 1,
+			   sample_id_all = 1,
+			   sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID)
+	evsel.open(cpus = cpus, threads = threads);
+	evlist = perf.evlist(cpus, threads)
+	evlist.add(evsel)
+	evlist.mmap()
+	while True:
+		evlist.poll(timeout = -1)
+		for cpu in cpus:
+			event = evlist.read_on_cpu(cpu)
+			if not event:
+				continue
+			print "cpu: %2d, pid: %4d, tid: %4d" % (event.sample_cpu,
+								event.sample_pid,
+								event.sample_tid),
+			print event
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 97d7656..26d4d3f 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -23,10 +23,10 @@ if test -d ../../.git -o -f ../../.git &&
 then
 	VN=$(echo "$VN" | sed -e 's/-/./g');
 else
-	eval `grep '^VERSION\s*=' ../../Makefile|tr -d ' '`
-	eval `grep '^PATCHLEVEL\s*=' ../../Makefile|tr -d ' '`
-	eval `grep '^SUBLEVEL\s*=' ../../Makefile|tr -d ' '`
-	eval `grep '^EXTRAVERSION\s*=' ../../Makefile|tr -d ' '`
+	eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
+	eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
+	eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
+	eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
 
 	VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
 fi
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
new file mode 100644
index 0000000..e01af2b
--- /dev/null
+++ b/tools/perf/util/annotate.c
@@ -0,0 +1,605 @@
+/*
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Parts came from builtin-annotate.c, see those files for further
+ * copyright notes.
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "util.h"
+#include "build-id.h"
+#include "color.h"
+#include "cache.h"
+#include "symbol.h"
+#include "debug.h"
+#include "annotate.h"
+#include <pthread.h>
+
+int symbol__annotate_init(struct map *map __used, struct symbol *sym)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	pthread_mutex_init(&notes->lock, NULL);
+	return 0;
+}
+
+int symbol__alloc_hist(struct symbol *sym, int nevents)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	size_t sizeof_sym_hist = (sizeof(struct sym_hist) +
+				  (sym->end - sym->start) * sizeof(u64));
+
+	notes->src = zalloc(sizeof(*notes->src) + nevents * sizeof_sym_hist);
+	if (notes->src == NULL)
+		return -1;
+	notes->src->sizeof_sym_hist = sizeof_sym_hist;
+	notes->src->nr_histograms   = nevents;
+	INIT_LIST_HEAD(&notes->src->source);
+	return 0;
+}
+
+void symbol__annotate_zero_histograms(struct symbol *sym)
+{
+	struct annotation *notes = symbol__annotation(sym);
+
+	pthread_mutex_lock(&notes->lock);
+	if (notes->src != NULL)
+		memset(notes->src->histograms, 0,
+		       notes->src->nr_histograms * notes->src->sizeof_sym_hist);
+	pthread_mutex_unlock(&notes->lock);
+}
+
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+			     int evidx, u64 addr)
+{
+	unsigned offset;
+	struct annotation *notes;
+	struct sym_hist *h;
+
+	notes = symbol__annotation(sym);
+	if (notes->src == NULL)
+		return -ENOMEM;
+
+	pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
+
+	if (addr >= sym->end)
+		return 0;
+
+	offset = addr - sym->start;
+	h = annotation__histogram(notes, evidx);
+	h->sum++;
+	h->addr[offset]++;
+
+	pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
+		  ", evidx=%d] => %" PRIu64 "\n", sym->start, sym->name,
+		  addr, addr - sym->start, evidx, h->addr[offset]);
+	return 0;
+}
+
+static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
+{
+	struct objdump_line *self = malloc(sizeof(*self) + privsize);
+
+	if (self != NULL) {
+		self->offset = offset;
+		self->line = line;
+	}
+
+	return self;
+}
+
+void objdump_line__free(struct objdump_line *self)
+{
+	free(self->line);
+	free(self);
+}
+
+static void objdump__add_line(struct list_head *head, struct objdump_line *line)
+{
+	list_add_tail(&line->node, head);
+}
+
+struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
+					       struct objdump_line *pos)
+{
+	list_for_each_entry_continue(pos, head, node)
+		if (pos->offset >= 0)
+			return pos;
+
+	return NULL;
+}
+
+static int objdump_line__print(struct objdump_line *oline, struct symbol *sym,
+			       int evidx, u64 len, int min_pcnt,
+			       int printed, int max_lines,
+			       struct objdump_line *queue)
+{
+	static const char *prev_line;
+	static const char *prev_color;
+
+	if (oline->offset != -1) {
+		const char *path = NULL;
+		unsigned int hits = 0;
+		double percent = 0.0;
+		const char *color;
+		struct annotation *notes = symbol__annotation(sym);
+		struct source_line *src_line = notes->src->lines;
+		struct sym_hist *h = annotation__histogram(notes, evidx);
+		s64 offset = oline->offset;
+		struct objdump_line *next;
+
+		next = objdump__get_next_ip_line(&notes->src->source, oline);
+
+		while (offset < (s64)len &&
+		       (next == NULL || offset < next->offset)) {
+			if (src_line) {
+				if (path == NULL)
+					path = src_line[offset].path;
+				percent += src_line[offset].percent;
+			} else
+				hits += h->addr[offset];
+
+			++offset;
+		}
+
+		if (src_line == NULL && h->sum)
+			percent = 100.0 * hits / h->sum;
+
+		if (percent < min_pcnt)
+			return -1;
+
+		if (max_lines && printed >= max_lines)
+			return 1;
+
+		if (queue != NULL) {
+			list_for_each_entry_from(queue, &notes->src->source, node) {
+				if (queue == oline)
+					break;
+				objdump_line__print(queue, sym, evidx, len,
+						    0, 0, 1, NULL);
+			}
+		}
+
+		color = get_percent_color(percent);
+
+		/*
+		 * Also color the filename and line if needed, with
+		 * the same color than the percentage. Don't print it
+		 * twice for close colored addr with the same filename:line
+		 */
+		if (path) {
+			if (!prev_line || strcmp(prev_line, path)
+				       || color != prev_color) {
+				color_fprintf(stdout, color, " %s", path);
+				prev_line = path;
+				prev_color = color;
+			}
+		}
+
+		color_fprintf(stdout, color, " %7.2f", percent);
+		printf(" :	");
+		color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", oline->line);
+	} else if (max_lines && printed >= max_lines)
+		return 1;
+	else {
+		if (queue)
+			return -1;
+
+		if (!*oline->line)
+			printf("         :\n");
+		else
+			printf("         :	%s\n", oline->line);
+	}
+
+	return 0;
+}
+
+static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
+				      FILE *file, size_t privsize)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct objdump_line *objdump_line;
+	char *line = NULL, *tmp, *tmp2, *c;
+	size_t line_len;
+	s64 line_ip, offset = -1;
+
+	if (getline(&line, &line_len, file) < 0)
+		return -1;
+
+	if (!line)
+		return -1;
+
+	while (line_len != 0 && isspace(line[line_len - 1]))
+		line[--line_len] = '\0';
+
+	c = strchr(line, '\n');
+	if (c)
+		*c = 0;
+
+	line_ip = -1;
+
+	/*
+	 * Strip leading spaces:
+	 */
+	tmp = line;
+	while (*tmp) {
+		if (*tmp != ' ')
+			break;
+		tmp++;
+	}
+
+	if (*tmp) {
+		/*
+		 * Parse hexa addresses followed by ':'
+		 */
+		line_ip = strtoull(tmp, &tmp2, 16);
+		if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
+			line_ip = -1;
+	}
+
+	if (line_ip != -1) {
+		u64 start = map__rip_2objdump(map, sym->start),
+		    end = map__rip_2objdump(map, sym->end);
+
+		offset = line_ip - start;
+		if (offset < 0 || (u64)line_ip > end)
+			offset = -1;
+	}
+
+	objdump_line = objdump_line__new(offset, line, privsize);
+	if (objdump_line == NULL) {
+		free(line);
+		return -1;
+	}
+	objdump__add_line(&notes->src->source, objdump_line);
+
+	return 0;
+}
+
+int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
+{
+	struct dso *dso = map->dso;
+	char *filename = dso__build_id_filename(dso, NULL, 0);
+	bool free_filename = true;
+	char command[PATH_MAX * 2];
+	FILE *file;
+	int err = 0;
+	char symfs_filename[PATH_MAX];
+
+	if (filename) {
+		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+			 symbol_conf.symfs, filename);
+	}
+
+	if (filename == NULL) {
+		if (dso->has_build_id) {
+			pr_err("Can't annotate %s: not enough memory\n",
+			       sym->name);
+			return -ENOMEM;
+		}
+		goto fallback;
+	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
+		   strstr(command, "[kernel.kallsyms]") ||
+		   access(symfs_filename, R_OK)) {
+		free(filename);
+fallback:
+		/*
+		 * If we don't have build-ids or the build-id file isn't in the
+		 * cache, or is just a kallsyms file, well, lets hope that this
+		 * DSO is the same as when 'perf record' ran.
+		 */
+		filename = dso->long_name;
+		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
+			 symbol_conf.symfs, filename);
+		free_filename = false;
+	}
+
+	if (dso->symtab_type == SYMTAB__KALLSYMS) {
+		char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
+		char *build_id_msg = NULL;
+
+		if (dso->annotate_warned)
+			goto out_free_filename;
+
+		if (dso->has_build_id) {
+			build_id__sprintf(dso->build_id,
+					  sizeof(dso->build_id), bf + 15);
+			build_id_msg = bf;
+		}
+		err = -ENOENT;
+		dso->annotate_warned = 1;
+		pr_err("Can't annotate %s: No vmlinux file%s was found in the "
+		       "path.\nPlease use 'perf buildid-cache -av vmlinux' or "
+		       "--vmlinux vmlinux.\n",
+		       sym->name, build_id_msg ?: "");
+		goto out_free_filename;
+	}
+
+	pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
+		 filename, sym->name, map->unmap_ip(map, sym->start),
+		 map->unmap_ip(map, sym->end));
+
+	pr_debug("annotating [%p] %30s : [%p] %30s\n",
+		 dso, dso->long_name, sym, sym->name);
+
+	snprintf(command, sizeof(command),
+		 "objdump --start-address=0x%016" PRIx64
+		 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
+		 map__rip_2objdump(map, sym->start),
+		 map__rip_2objdump(map, sym->end),
+		 symfs_filename, filename);
+
+	pr_debug("Executing: %s\n", command);
+
+	file = popen(command, "r");
+	if (!file)
+		goto out_free_filename;
+
+	while (!feof(file))
+		if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
+			break;
+
+	pclose(file);
+out_free_filename:
+	if (free_filename)
+		free(filename);
+	return err;
+}
+
+static void insert_source_line(struct rb_root *root, struct source_line *src_line)
+{
+	struct source_line *iter;
+	struct rb_node **p = &root->rb_node;
+	struct rb_node *parent = NULL;
+
+	while (*p != NULL) {
+		parent = *p;
+		iter = rb_entry(parent, struct source_line, node);
+
+		if (src_line->percent > iter->percent)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+
+	rb_link_node(&src_line->node, parent, p);
+	rb_insert_color(&src_line->node, root);
+}
+
+static void symbol__free_source_line(struct symbol *sym, int len)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct source_line *src_line = notes->src->lines;
+	int i;
+
+	for (i = 0; i < len; i++)
+		free(src_line[i].path);
+
+	free(src_line);
+	notes->src->lines = NULL;
+}
+
+/* Get the filename:line for the colored entries */
+static int symbol__get_source_line(struct symbol *sym, struct map *map,
+				   int evidx, struct rb_root *root, int len,
+				   const char *filename)
+{
+	u64 start;
+	int i;
+	char cmd[PATH_MAX * 2];
+	struct source_line *src_line;
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = annotation__histogram(notes, evidx);
+
+	if (!h->sum)
+		return 0;
+
+	src_line = notes->src->lines = calloc(len, sizeof(struct source_line));
+	if (!notes->src->lines)
+		return -1;
+
+	start = map->unmap_ip(map, sym->start);
+
+	for (i = 0; i < len; i++) {
+		char *path = NULL;
+		size_t line_len;
+		u64 offset;
+		FILE *fp;
+
+		src_line[i].percent = 100.0 * h->addr[i] / h->sum;
+		if (src_line[i].percent <= 0.5)
+			continue;
+
+		offset = start + i;
+		sprintf(cmd, "addr2line -e %s %016" PRIx64, filename, offset);
+		fp = popen(cmd, "r");
+		if (!fp)
+			continue;
+
+		if (getline(&path, &line_len, fp) < 0 || !line_len)
+			goto next;
+
+		src_line[i].path = malloc(sizeof(char) * line_len + 1);
+		if (!src_line[i].path)
+			goto next;
+
+		strcpy(src_line[i].path, path);
+		insert_source_line(root, &src_line[i]);
+
+	next:
+		pclose(fp);
+	}
+
+	return 0;
+}
+
+static void print_summary(struct rb_root *root, const char *filename)
+{
+	struct source_line *src_line;
+	struct rb_node *node;
+
+	printf("\nSorted summary for file %s\n", filename);
+	printf("----------------------------------------------\n\n");
+
+	if (RB_EMPTY_ROOT(root)) {
+		printf(" Nothing higher than %1.1f%%\n", MIN_GREEN);
+		return;
+	}
+
+	node = rb_first(root);
+	while (node) {
+		double percent;
+		const char *color;
+		char *path;
+
+		src_line = rb_entry(node, struct source_line, node);
+		percent = src_line->percent;
+		color = get_percent_color(percent);
+		path = src_line->path;
+
+		color_fprintf(stdout, color, " %7.2f %s", percent, path);
+		node = rb_next(node);
+	}
+}
+
+static void symbol__annotate_hits(struct symbol *sym, int evidx)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = annotation__histogram(notes, evidx);
+	u64 len = sym->end - sym->start, offset;
+
+	for (offset = 0; offset < len; ++offset)
+		if (h->addr[offset] != 0)
+			printf("%*" PRIx64 ": %" PRIu64 "\n", BITS_PER_LONG / 2,
+			       sym->start + offset, h->addr[offset]);
+	printf("%*s: %" PRIu64 "\n", BITS_PER_LONG / 2, "h->sum", h->sum);
+}
+
+int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
+			    bool full_paths, int min_pcnt, int max_lines,
+			    int context)
+{
+	struct dso *dso = map->dso;
+	const char *filename = dso->long_name, *d_filename;
+	struct annotation *notes = symbol__annotation(sym);
+	struct objdump_line *pos, *queue = NULL;
+	int printed = 2, queue_len = 0;
+	int more = 0;
+	u64 len;
+
+	if (full_paths)
+		d_filename = filename;
+	else
+		d_filename = basename(filename);
+
+	len = sym->end - sym->start;
+
+	printf(" Percent |	Source code & Disassembly of %s\n", d_filename);
+	printf("------------------------------------------------\n");
+
+	if (verbose)
+		symbol__annotate_hits(sym, evidx);
+
+	list_for_each_entry(pos, &notes->src->source, node) {
+		if (context && queue == NULL) {
+			queue = pos;
+			queue_len = 0;
+		}
+
+		switch (objdump_line__print(pos, sym, evidx, len, min_pcnt,
+					    printed, max_lines, queue)) {
+		case 0:
+			++printed;
+			if (context) {
+				printed += queue_len;
+				queue = NULL;
+				queue_len = 0;
+			}
+			break;
+		case 1:
+			/* filtered by max_lines */
+			++more;
+			break;
+		case -1:
+		default:
+			/*
+			 * Filtered by min_pcnt or non IP lines when
+			 * context != 0
+			 */
+			if (!context)
+				break;
+			if (queue_len == context)
+				queue = list_entry(queue->node.next, typeof(*queue), node);
+			else
+				++queue_len;
+			break;
+		}
+	}
+
+	return more;
+}
+
+void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = annotation__histogram(notes, evidx);
+
+	memset(h, 0, notes->src->sizeof_sym_hist);
+}
+
+void symbol__annotate_decay_histogram(struct symbol *sym, int evidx)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct sym_hist *h = annotation__histogram(notes, evidx);
+	struct objdump_line *pos;
+	int len = sym->end - sym->start;
+
+	h->sum = 0;
+
+	list_for_each_entry(pos, &notes->src->source, node) {
+		if (pos->offset != -1 && pos->offset < len) {
+			h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
+			h->sum += h->addr[pos->offset];
+		}
+	}
+}
+
+void objdump_line_list__purge(struct list_head *head)
+{
+	struct objdump_line *pos, *n;
+
+	list_for_each_entry_safe(pos, n, head, node) {
+		list_del(&pos->node);
+		objdump_line__free(pos);
+	}
+}
+
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
+			 bool print_lines, bool full_paths, int min_pcnt,
+			 int max_lines)
+{
+	struct dso *dso = map->dso;
+	const char *filename = dso->long_name;
+	struct rb_root source_line = RB_ROOT;
+	u64 len;
+
+	if (symbol__annotate(sym, map, 0) < 0)
+		return -1;
+
+	len = sym->end - sym->start;
+
+	if (print_lines) {
+		symbol__get_source_line(sym, map, evidx, &source_line,
+					len, filename);
+		print_summary(&source_line, filename);
+	}
+
+	symbol__annotate_printf(sym, map, evidx, full_paths,
+				min_pcnt, max_lines, 0);
+	if (print_lines)
+		symbol__free_source_line(sym, len);
+
+	objdump_line_list__purge(&symbol__annotation(sym)->src->source);
+
+	return 0;
+}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
new file mode 100644
index 0000000..c2c2868
--- /dev/null
+++ b/tools/perf/util/annotate.h
@@ -0,0 +1,103 @@
+#ifndef __PERF_ANNOTATE_H
+#define __PERF_ANNOTATE_H
+
+#include <stdbool.h>
+#include "types.h"
+#include "symbol.h"
+#include <linux/list.h>
+#include <linux/rbtree.h>
+
+struct objdump_line {
+	struct list_head node;
+	s64		 offset;
+	char		 *line;
+};
+
+void objdump_line__free(struct objdump_line *self);
+struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
+					       struct objdump_line *pos);
+
+struct sym_hist {
+	u64		sum;
+	u64		addr[0];
+};
+
+struct source_line {
+	struct rb_node	node;
+	double		percent;
+	char		*path;
+};
+
+/** struct annotated_source - symbols with hits have this attached as in sannotation
+ *
+ * @histogram: Array of addr hit histograms per event being monitored
+ * @lines: If 'print_lines' is specified, per source code line percentages
+ * @source: source parsed from objdump -dS
+ *
+ * lines is allocated, percentages calculated and all sorted by percentage
+ * when the annotation is about to be presented, so the percentages are for
+ * one of the entries in the histogram array, i.e. for the event/counter being
+ * presented. It is deallocated right after symbol__{tui,tty,etc}_annotate
+ * returns.
+ */
+struct annotated_source {
+	struct list_head   source;
+	struct source_line *lines;
+	int    		   nr_histograms;
+	int    		   sizeof_sym_hist;
+	struct sym_hist	   histograms[0];
+};
+
+struct annotation {
+	pthread_mutex_t		lock;
+	struct annotated_source *src;
+};
+
+struct sannotation {
+	struct annotation annotation;
+	struct symbol	  symbol;
+};
+
+static inline struct sym_hist *annotation__histogram(struct annotation *notes, int idx)
+{
+	return (((void *)&notes->src->histograms) +
+	 	(notes->src->sizeof_sym_hist * idx));
+}
+
+static inline struct annotation *symbol__annotation(struct symbol *sym)
+{
+	struct sannotation *a = container_of(sym, struct sannotation, symbol);
+	return &a->annotation;
+}
+
+int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
+			     int evidx, u64 addr);
+int symbol__alloc_hist(struct symbol *sym, int nevents);
+void symbol__annotate_zero_histograms(struct symbol *sym);
+
+int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize);
+int symbol__annotate_init(struct map *map __used, struct symbol *sym);
+int symbol__annotate_printf(struct symbol *sym, struct map *map, int evidx,
+			    bool full_paths, int min_pcnt, int max_lines,
+			    int context);
+void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
+void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
+void objdump_line_list__purge(struct list_head *head);
+
+int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx,
+			 bool print_lines, bool full_paths, int min_pcnt,
+			 int max_lines);
+
+#ifdef NO_NEWT_SUPPORT
+static inline int symbol__tui_annotate(struct symbol *sym __used,
+				       struct map *map __used,
+				       int evidx __used, int refresh __used)
+{
+	return 0;
+}
+#else
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+			 int refresh);
+#endif
+
+#endif	/* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index deffb8c..31f934a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -14,8 +14,8 @@
 #include <linux/kernel.h>
 #include "debug.h"
 
-static int build_id__mark_dso_hit(event_t *event,
-				  struct sample_data *sample __used,
+static int build_id__mark_dso_hit(union perf_event *event,
+				  struct perf_sample *sample __used,
 				  struct perf_session *session)
 {
 	struct addr_location al;
@@ -37,13 +37,14 @@ static int build_id__mark_dso_hit(event_t *event,
 	return 0;
 }
 
-static int event__exit_del_thread(event_t *self, struct sample_data *sample __used,
-				  struct perf_session *session)
+static int perf_event__exit_del_thread(union perf_event *event,
+				       struct perf_sample *sample __used,
+				       struct perf_session *session)
 {
-	struct thread *thread = perf_session__findnew(session, self->fork.tid);
+	struct thread *thread = perf_session__findnew(session, event->fork.tid);
 
-	dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
-		    self->fork.ppid, self->fork.ptid);
+	dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
+		    event->fork.ppid, event->fork.ptid);
 
 	if (thread) {
 		rb_erase(&thread->rb_node, &session->threads);
@@ -56,9 +57,9 @@ static int event__exit_del_thread(event_t *self, struct sample_data *sample __us
 
 struct perf_event_ops build_id__mark_dso_hit_ops = {
 	.sample	= build_id__mark_dso_hit,
-	.mmap	= event__process_mmap,
-	.fork	= event__process_task,
-	.exit	= event__exit_del_thread,
+	.mmap	= perf_event__process_mmap,
+	.fork	= perf_event__process_task,
+	.exit	= perf_event__exit_del_thread,
 };
 
 char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index a772979..fc5e5a0 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -34,13 +34,14 @@ extern int pager_use_color;
 extern int use_browser;
 
 #ifdef NO_NEWT_SUPPORT
-static inline void setup_browser(void)
+static inline void setup_browser(bool fallback_to_pager)
 {
-	setup_pager();
+	if (fallback_to_pager)
+		setup_pager();
 }
 static inline void exit_browser(bool wait_for_ok __used) {}
 #else
-void setup_browser(void);
+void setup_browser(bool fallback_to_pager);
 void exit_browser(bool wait_for_ok);
 #endif
 
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index e12d539..9f7106a 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010, Frederic Weisbecker <fweisbec@gmail.com>
+ * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
  *
  * Handle the callchains from the stream in an ad-hoc radix tree and then
  * sort them in an rbtree.
@@ -18,7 +18,8 @@
 #include "util.h"
 #include "callchain.h"
 
-bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event)
+bool ip_callchain__valid(struct ip_callchain *chain,
+			 const union perf_event *event)
 {
 	unsigned int chain_size = event->header.size;
 	chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event;
@@ -26,10 +27,10 @@ bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event)
 }
 
 #define chain_for_each_child(child, parent)	\
-	list_for_each_entry(child, &parent->children, brothers)
+	list_for_each_entry(child, &parent->children, siblings)
 
 #define chain_for_each_child_safe(child, next, parent)	\
-	list_for_each_entry_safe(child, next, &parent->children, brothers)
+	list_for_each_entry_safe(child, next, &parent->children, siblings)
 
 static void
 rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
@@ -38,14 +39,14 @@ rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
 	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
 	struct callchain_node *rnode;
-	u64 chain_cumul = cumul_hits(chain);
+	u64 chain_cumul = callchain_cumul_hits(chain);
 
 	while (*p) {
 		u64 rnode_cumul;
 
 		parent = *p;
 		rnode = rb_entry(parent, struct callchain_node, rb_node);
-		rnode_cumul = cumul_hits(rnode);
+		rnode_cumul = callchain_cumul_hits(rnode);
 
 		switch (mode) {
 		case CHAIN_FLAT:
@@ -104,7 +105,7 @@ static void __sort_chain_graph_abs(struct callchain_node *node,
 
 	chain_for_each_child(child, node) {
 		__sort_chain_graph_abs(child, min_hit);
-		if (cumul_hits(child) >= min_hit)
+		if (callchain_cumul_hits(child) >= min_hit)
 			rb_insert_callchain(&node->rb_root, child,
 					    CHAIN_GRAPH_ABS);
 	}
@@ -129,7 +130,7 @@ static void __sort_chain_graph_rel(struct callchain_node *node,
 
 	chain_for_each_child(child, node) {
 		__sort_chain_graph_rel(child, min_percent);
-		if (cumul_hits(child) >= min_hit)
+		if (callchain_cumul_hits(child) >= min_hit)
 			rb_insert_callchain(&node->rb_root, child,
 					    CHAIN_GRAPH_REL);
 	}
@@ -143,7 +144,7 @@ sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
 	rb_root->rb_node = chain_root->node.rb_root.rb_node;
 }
 
-int register_callchain_param(struct callchain_param *param)
+int callchain_register_param(struct callchain_param *param)
 {
 	switch (param->mode) {
 	case CHAIN_GRAPH_ABS:
@@ -189,32 +190,27 @@ create_child(struct callchain_node *parent, bool inherit_children)
 		chain_for_each_child(next, new)
 			next->parent = new;
 	}
-	list_add_tail(&new->brothers, &parent->children);
+	list_add_tail(&new->siblings, &parent->children);
 
 	return new;
 }
 
 
-struct resolved_ip {
-	u64		  ip;
-	struct map_symbol ms;
-};
-
-struct resolved_chain {
-	u64			nr;
-	struct resolved_ip	ips[0];
-};
-
-
 /*
  * Fill the node with callchain values
  */
 static void
-fill_node(struct callchain_node *node, struct resolved_chain *chain, int start)
+fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
 {
-	unsigned int i;
+	struct callchain_cursor_node *cursor_node;
+
+	node->val_nr = cursor->nr - cursor->pos;
+	if (!node->val_nr)
+		pr_warning("Warning: empty node in callchain tree\n");
 
-	for (i = start; i < chain->nr; i++) {
+	cursor_node = callchain_cursor_current(cursor);
+
+	while (cursor_node) {
 		struct callchain_list *call;
 
 		call = zalloc(sizeof(*call));
@@ -222,23 +218,25 @@ fill_node(struct callchain_node *node, struct resolved_chain *chain, int start)
 			perror("not enough memory for the code path tree");
 			return;
 		}
-		call->ip = chain->ips[i].ip;
-		call->ms = chain->ips[i].ms;
+		call->ip = cursor_node->ip;
+		call->ms.sym = cursor_node->sym;
+		call->ms.map = cursor_node->map;
 		list_add_tail(&call->list, &node->val);
+
+		callchain_cursor_advance(cursor);
+		cursor_node = callchain_cursor_current(cursor);
 	}
-	node->val_nr = chain->nr - start;
-	if (!node->val_nr)
-		pr_warning("Warning: empty node in callchain tree\n");
 }
 
 static void
-add_child(struct callchain_node *parent, struct resolved_chain *chain,
-	  int start, u64 period)
+add_child(struct callchain_node *parent,
+	  struct callchain_cursor *cursor,
+	  u64 period)
 {
 	struct callchain_node *new;
 
 	new = create_child(parent, false);
-	fill_node(new, chain, start);
+	fill_node(new, cursor);
 
 	new->children_hit = 0;
 	new->hit = period;
@@ -250,9 +248,10 @@ add_child(struct callchain_node *parent, struct resolved_chain *chain,
  * Then create another child to host the given callchain of new branch
  */
 static void
-split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
-		struct callchain_list *to_split, int idx_parents, int idx_local,
-		u64 period)
+split_add_child(struct callchain_node *parent,
+		struct callchain_cursor *cursor,
+		struct callchain_list *to_split,
+		u64 idx_parents, u64 idx_local, u64 period)
 {
 	struct callchain_node *new;
 	struct list_head *old_tail;
@@ -272,14 +271,14 @@ split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
 	/* split the hits */
 	new->hit = parent->hit;
 	new->children_hit = parent->children_hit;
-	parent->children_hit = cumul_hits(new);
+	parent->children_hit = callchain_cumul_hits(new);
 	new->val_nr = parent->val_nr - idx_local;
 	parent->val_nr = idx_local;
 
 	/* create a new child for the new branch if any */
-	if (idx_total < chain->nr) {
+	if (idx_total < cursor->nr) {
 		parent->hit = 0;
-		add_child(parent, chain, idx_total, period);
+		add_child(parent, cursor, period);
 		parent->children_hit += period;
 	} else {
 		parent->hit = period;
@@ -287,36 +286,41 @@ split_add_child(struct callchain_node *parent, struct resolved_chain *chain,
 }
 
 static int
-append_chain(struct callchain_node *root, struct resolved_chain *chain,
-	     unsigned int start, u64 period);
+append_chain(struct callchain_node *root,
+	     struct callchain_cursor *cursor,
+	     u64 period);
 
 static void
-append_chain_children(struct callchain_node *root, struct resolved_chain *chain,
-		      unsigned int start, u64 period)
+append_chain_children(struct callchain_node *root,
+		      struct callchain_cursor *cursor,
+		      u64 period)
 {
 	struct callchain_node *rnode;
 
 	/* lookup in childrens */
 	chain_for_each_child(rnode, root) {
-		unsigned int ret = append_chain(rnode, chain, start, period);
+		unsigned int ret = append_chain(rnode, cursor, period);
 
 		if (!ret)
 			goto inc_children_hit;
 	}
 	/* nothing in children, add to the current node */
-	add_child(root, chain, start, period);
+	add_child(root, cursor, period);
 
 inc_children_hit:
 	root->children_hit += period;
 }
 
 static int
-append_chain(struct callchain_node *root, struct resolved_chain *chain,
-	     unsigned int start, u64 period)
+append_chain(struct callchain_node *root,
+	     struct callchain_cursor *cursor,
+	     u64 period)
 {
+	struct callchain_cursor_node *curr_snap = cursor->curr;
 	struct callchain_list *cnode;
-	unsigned int i = start;
+	u64 start = cursor->pos;
 	bool found = false;
+	u64 matches;
 
 	/*
 	 * Lookup in the current node
@@ -324,141 +328,134 @@ append_chain(struct callchain_node *root, struct resolved_chain *chain,
 	 * anywhere inside a function.
 	 */
 	list_for_each_entry(cnode, &root->val, list) {
+		struct callchain_cursor_node *node;
 		struct symbol *sym;
 
-		if (i == chain->nr)
+		node = callchain_cursor_current(cursor);
+		if (!node)
 			break;
 
-		sym = chain->ips[i].ms.sym;
+		sym = node->sym;
 
 		if (cnode->ms.sym && sym) {
 			if (cnode->ms.sym->start != sym->start)
 				break;
-		} else if (cnode->ip != chain->ips[i].ip)
+		} else if (cnode->ip != node->ip)
 			break;
 
 		if (!found)
 			found = true;
-		i++;
+
+		callchain_cursor_advance(cursor);
 	}
 
 	/* matches not, relay on the parent */
-	if (!found)
+	if (!found) {
+		cursor->curr = curr_snap;
+		cursor->pos = start;
 		return -1;
+	}
+
+	matches = cursor->pos - start;
 
 	/* we match only a part of the node. Split it and add the new chain */
-	if (i - start < root->val_nr) {
-		split_add_child(root, chain, cnode, start, i - start, period);
+	if (matches < root->val_nr) {
+		split_add_child(root, cursor, cnode, start, matches, period);
 		return 0;
 	}
 
 	/* we match 100% of the path, increment the hit */
-	if (i - start == root->val_nr && i == chain->nr) {
+	if (matches == root->val_nr && cursor->pos == cursor->nr) {
 		root->hit += period;
 		return 0;
 	}
 
 	/* We match the node and still have a part remaining */
-	append_chain_children(root, chain, i, period);
+	append_chain_children(root, cursor, period);
 
 	return 0;
 }
 
-static void filter_context(struct ip_callchain *old, struct resolved_chain *new,
-			   struct map_symbol *syms)
-{
-	int i, j = 0;
-
-	for (i = 0; i < (int)old->nr; i++) {
-		if (old->ips[i] >= PERF_CONTEXT_MAX)
-			continue;
-
-		new->ips[j].ip = old->ips[i];
-		new->ips[j].ms = syms[i];
-		j++;
-	}
-
-	new->nr = j;
-}
-
-
-int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
-		     struct map_symbol *syms, u64 period)
+int callchain_append(struct callchain_root *root,
+		     struct callchain_cursor *cursor,
+		     u64 period)
 {
-	struct resolved_chain *filtered;
-
-	if (!chain->nr)
+	if (!cursor->nr)
 		return 0;
 
-	filtered = zalloc(sizeof(*filtered) +
-			  chain->nr * sizeof(struct resolved_ip));
-	if (!filtered)
-		return -ENOMEM;
-
-	filter_context(chain, filtered, syms);
-
-	if (!filtered->nr)
-		goto end;
+	callchain_cursor_commit(cursor);
 
-	append_chain_children(&root->node, filtered, 0, period);
+	append_chain_children(&root->node, cursor, period);
 
-	if (filtered->nr > root->max_depth)
-		root->max_depth = filtered->nr;
-end:
-	free(filtered);
+	if (cursor->nr > root->max_depth)
+		root->max_depth = cursor->nr;
 
 	return 0;
 }
 
 static int
-merge_chain_branch(struct callchain_node *dst, struct callchain_node *src,
-		   struct resolved_chain *chain)
+merge_chain_branch(struct callchain_cursor *cursor,
+		   struct callchain_node *dst, struct callchain_node *src)
 {
+	struct callchain_cursor_node **old_last = cursor->last;
 	struct callchain_node *child, *next_child;
 	struct callchain_list *list, *next_list;
-	int old_pos = chain->nr;
+	int old_pos = cursor->nr;
 	int err = 0;
 
 	list_for_each_entry_safe(list, next_list, &src->val, list) {
-		chain->ips[chain->nr].ip = list->ip;
-		chain->ips[chain->nr].ms = list->ms;
-		chain->nr++;
+		callchain_cursor_append(cursor, list->ip,
+					list->ms.map, list->ms.sym);
 		list_del(&list->list);
 		free(list);
 	}
 
-	if (src->hit)
-		append_chain_children(dst, chain, 0, src->hit);
+	if (src->hit) {
+		callchain_cursor_commit(cursor);
+		append_chain_children(dst, cursor, src->hit);
+	}
 
 	chain_for_each_child_safe(child, next_child, src) {
-		err = merge_chain_branch(dst, child, chain);
+		err = merge_chain_branch(cursor, dst, child);
 		if (err)
 			break;
 
-		list_del(&child->brothers);
+		list_del(&child->siblings);
 		free(child);
 	}
 
-	chain->nr = old_pos;
+	cursor->nr = old_pos;
+	cursor->last = old_last;
 
 	return err;
 }
 
-int callchain_merge(struct callchain_root *dst, struct callchain_root *src)
+int callchain_merge(struct callchain_cursor *cursor,
+		    struct callchain_root *dst, struct callchain_root *src)
+{
+	return merge_chain_branch(cursor, &dst->node, &src->node);
+}
+
+int callchain_cursor_append(struct callchain_cursor *cursor,
+			    u64 ip, struct map *map, struct symbol *sym)
 {
-	struct resolved_chain *chain;
-	int err;
+	struct callchain_cursor_node *node = *cursor->last;
 
-	chain = malloc(sizeof(*chain) +
-		       src->max_depth * sizeof(struct resolved_ip));
-	if (!chain)
-		return -ENOMEM;
+	if (!node) {
+		node = calloc(sizeof(*node), 1);
+		if (!node)
+			return -ENOMEM;
 
-	chain->nr = 0;
+		*cursor->last = node;
+	}
 
-	err = merge_chain_branch(&dst->node, &src->node, chain);
+	node->ip = ip;
+	node->map = map;
+	node->sym = sym;
 
-	free(chain);
+	cursor->nr++;
 
-	return err;
+	cursor->last = &node->next;
+
+	return 0;
 }
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index c15fb8c..1a79df9 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -16,7 +16,7 @@ enum chain_mode {
 
 struct callchain_node {
 	struct callchain_node	*parent;
-	struct list_head	brothers;
+	struct list_head	siblings;
 	struct list_head	children;
 	struct list_head	val;
 	struct rb_node		rb_node; /* to sort nodes in an rbtree */
@@ -49,9 +49,30 @@ struct callchain_list {
 	struct list_head	list;
 };
 
+/*
+ * A callchain cursor is a single linked list that
+ * let one feed a callchain progressively.
+ * It keeps persitent allocated entries to minimize
+ * allocations.
+ */
+struct callchain_cursor_node {
+	u64				ip;
+	struct map			*map;
+	struct symbol			*sym;
+	struct callchain_cursor_node	*next;
+};
+
+struct callchain_cursor {
+	u64				nr;
+	struct callchain_cursor_node	*first;
+	struct callchain_cursor_node	**last;
+	u64				pos;
+	struct callchain_cursor_node	*curr;
+};
+
 static inline void callchain_init(struct callchain_root *root)
 {
-	INIT_LIST_HEAD(&root->node.brothers);
+	INIT_LIST_HEAD(&root->node.siblings);
 	INIT_LIST_HEAD(&root->node.children);
 	INIT_LIST_HEAD(&root->node.val);
 
@@ -61,15 +82,54 @@ static inline void callchain_init(struct callchain_root *root)
 	root->max_depth = 0;
 }
 
-static inline u64 cumul_hits(struct callchain_node *node)
+static inline u64 callchain_cumul_hits(struct callchain_node *node)
 {
 	return node->hit + node->children_hit;
 }
 
-int register_callchain_param(struct callchain_param *param);
-int callchain_append(struct callchain_root *root, struct ip_callchain *chain,
-		     struct map_symbol *syms, u64 period);
-int callchain_merge(struct callchain_root *dst, struct callchain_root *src);
+int callchain_register_param(struct callchain_param *param);
+int callchain_append(struct callchain_root *root,
+		     struct callchain_cursor *cursor,
+		     u64 period);
+
+int callchain_merge(struct callchain_cursor *cursor,
+		    struct callchain_root *dst, struct callchain_root *src);
+
+bool ip_callchain__valid(struct ip_callchain *chain,
+			 const union perf_event *event);
+/*
+ * Initialize a cursor before adding entries inside, but keep
+ * the previously allocated entries as a cache.
+ */
+static inline void callchain_cursor_reset(struct callchain_cursor *cursor)
+{
+	cursor->nr = 0;
+	cursor->last = &cursor->first;
+}
+
+int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip,
+			    struct map *map, struct symbol *sym);
 
-bool ip_callchain__valid(struct ip_callchain *chain, const event_t *event);
+/* Close a cursor writing session. Initialize for the reader */
+static inline void callchain_cursor_commit(struct callchain_cursor *cursor)
+{
+	cursor->curr = cursor->first;
+	cursor->pos = 0;
+}
+
+/* Cursor reading iteration helpers */
+static inline struct callchain_cursor_node *
+callchain_cursor_current(struct callchain_cursor *cursor)
+{
+	if (cursor->pos == cursor->nr)
+		return NULL;
+
+	return cursor->curr;
+}
+
+static inline void callchain_cursor_advance(struct callchain_cursor *cursor)
+{
+	cursor->curr = cursor->curr->next;
+	cursor->pos++;
+}
 #endif	/* __PERF_CALLCHAIN_H */
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
new file mode 100644
index 0000000..9fea755
--- /dev/null
+++ b/tools/perf/util/cgroup.c
@@ -0,0 +1,178 @@
+#include "util.h"
+#include "../perf.h"
+#include "parse-options.h"
+#include "evsel.h"
+#include "cgroup.h"
+#include "debugfs.h" /* MAX_PATH, STR() */
+#include "evlist.h"
+
+int nr_cgroups;
+
+static int
+cgroupfs_find_mountpoint(char *buf, size_t maxlen)
+{
+	FILE *fp;
+	char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1];
+	char *token, *saved_ptr;
+	int found = 0;
+
+	fp = fopen("/proc/mounts", "r");
+	if (!fp)
+		return -1;
+
+	/*
+	 * in order to handle split hierarchy, we need to scan /proc/mounts
+	 * and inspect every cgroupfs mount point to find one that has
+	 * perf_event subsystem
+	 */
+	while (fscanf(fp, "%*s %"STR(MAX_PATH)"s %"STR(MAX_PATH)"s %"
+				STR(MAX_PATH)"s %*d %*d\n",
+				mountpoint, type, tokens) == 3) {
+
+		if (!strcmp(type, "cgroup")) {
+
+			token = strtok_r(tokens, ",", &saved_ptr);
+
+			while (token != NULL) {
+				if (!strcmp(token, "perf_event")) {
+					found = 1;
+					break;
+				}
+				token = strtok_r(NULL, ",", &saved_ptr);
+			}
+		}
+		if (found)
+			break;
+	}
+	fclose(fp);
+	if (!found)
+		return -1;
+
+	if (strlen(mountpoint) < maxlen) {
+		strcpy(buf, mountpoint);
+		return 0;
+	}
+	return -1;
+}
+
+static int open_cgroup(char *name)
+{
+	char path[MAX_PATH+1];
+	char mnt[MAX_PATH+1];
+	int fd;
+
+
+	if (cgroupfs_find_mountpoint(mnt, MAX_PATH+1))
+		return -1;
+
+	snprintf(path, MAX_PATH, "%s/%s", mnt, name);
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1)
+		fprintf(stderr, "no access to cgroup %s\n", path);
+
+	return fd;
+}
+
+static int add_cgroup(struct perf_evlist *evlist, char *str)
+{
+	struct perf_evsel *counter;
+	struct cgroup_sel *cgrp = NULL;
+	int n;
+	/*
+	 * check if cgrp is already defined, if so we reuse it
+	 */
+	list_for_each_entry(counter, &evlist->entries, node) {
+		cgrp = counter->cgrp;
+		if (!cgrp)
+			continue;
+		if (!strcmp(cgrp->name, str))
+			break;
+
+		cgrp = NULL;
+	}
+
+	if (!cgrp) {
+		cgrp = zalloc(sizeof(*cgrp));
+		if (!cgrp)
+			return -1;
+
+		cgrp->name = str;
+
+		cgrp->fd = open_cgroup(str);
+		if (cgrp->fd == -1) {
+			free(cgrp);
+			return -1;
+		}
+	}
+
+	/*
+	 * find corresponding event
+	 * if add cgroup N, then need to find event N
+	 */
+	n = 0;
+	list_for_each_entry(counter, &evlist->entries, node) {
+		if (n == nr_cgroups)
+			goto found;
+		n++;
+	}
+	if (cgrp->refcnt == 0)
+		free(cgrp);
+
+	return -1;
+found:
+	cgrp->refcnt++;
+	counter->cgrp = cgrp;
+	return 0;
+}
+
+void close_cgroup(struct cgroup_sel *cgrp)
+{
+	if (!cgrp)
+		return;
+
+	/* XXX: not reentrant */
+	if (--cgrp->refcnt == 0) {
+		close(cgrp->fd);
+		free(cgrp->name);
+		free(cgrp);
+	}
+}
+
+int parse_cgroups(const struct option *opt __used, const char *str,
+		  int unset __used)
+{
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
+	const char *p, *e, *eos = str + strlen(str);
+	char *s;
+	int ret;
+
+	if (list_empty(&evlist->entries)) {
+		fprintf(stderr, "must define events before cgroups\n");
+		return -1;
+	}
+
+	for (;;) {
+		p = strchr(str, ',');
+		e = p ? p : eos;
+
+		/* allow empty cgroups, i.e., skip */
+		if (e - str) {
+			/* termination added */
+			s = strndup(str, e - str);
+			if (!s)
+				return -1;
+			ret = add_cgroup(evlist, s);
+			if (ret) {
+				free(s);
+				return -1;
+			}
+		}
+		/* nr_cgroups is increased een for empty cgroups */
+		nr_cgroups++;
+		if (!p)
+			break;
+		str = p+1;
+	}
+	return 0;
+}
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h
new file mode 100644
index 0000000..89acd6d
--- /dev/null
+++ b/tools/perf/util/cgroup.h
@@ -0,0 +1,17 @@
+#ifndef __CGROUP_H__
+#define __CGROUP_H__
+
+struct option;
+
+struct cgroup_sel {
+	char *name;
+	int fd;
+	int refcnt;
+};
+
+
+extern int nr_cgroups; /* number of explicit cgroups defined */
+extern void close_cgroup(struct cgroup_sel *cgrp);
+extern int parse_cgroups(const struct option *opt, const char *str, int unset);
+
+#endif /* __CGROUP_H__ */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 3ccaa10..6893eec 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -177,3 +177,8 @@ struct cpu_map *cpu_map__dummy_new(void)
 
 	return cpus;
 }
+
+void cpu_map__delete(struct cpu_map *map)
+{
+	free(map);
+}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index f7a4f42..072c0a3 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -8,6 +8,6 @@ struct cpu_map {
 
 struct cpu_map *cpu_map__new(const char *cpu_list);
 struct cpu_map *cpu_map__dummy_new(void);
-void *cpu_map__delete(struct cpu_map *map);
+void cpu_map__delete(struct cpu_map *map);
 
 #endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 01bbe8e..d4536a9 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -57,7 +57,7 @@ void ui__warning(const char *format, ...)
 }
 #endif
 
-void trace_event(event_t *event)
+void trace_event(union perf_event *event)
 {
 	unsigned char *raw_event = (void *)event;
 	const char *color = PERF_COLOR_BLUE;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index ca35fd6..93516cf4 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -9,7 +9,7 @@ extern int verbose;
 extern bool quiet, dump_trace;
 
 int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
-void trace_event(event_t *event);
+void trace_event(union perf_event *event);
 
 struct ui_progress;
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 50d0a93..2b15c36 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -6,8 +6,9 @@
 #include "string.h"
 #include "strlist.h"
 #include "thread.h"
+#include "thread_map.h"
 
-static const char *event__name[] = {
+static const char *perf_event__names[] = {
 	[0]			 = "TOTAL",
 	[PERF_RECORD_MMAP]	 = "MMAP",
 	[PERF_RECORD_LOST]	 = "LOST",
@@ -25,16 +26,16 @@ static const char *event__name[] = {
 	[PERF_RECORD_FINISHED_ROUND]	 = "FINISHED_ROUND",
 };
 
-const char *event__get_event_name(unsigned int id)
+const char *perf_event__name(unsigned int id)
 {
-	if (id >= ARRAY_SIZE(event__name))
+	if (id >= ARRAY_SIZE(perf_event__names))
 		return "INVALID";
-	if (!event__name[id])
+	if (!perf_event__names[id])
 		return "UNKNOWN";
-	return event__name[id];
+	return perf_event__names[id];
 }
 
-static struct sample_data synth_sample = {
+static struct perf_sample synth_sample = {
 	.pid	   = -1,
 	.tid	   = -1,
 	.time	   = -1,
@@ -43,9 +44,9 @@ static struct sample_data synth_sample = {
 	.period	   = 1,
 };
 
-static pid_t event__synthesize_comm(event_t *event, pid_t pid, int full,
-				    event__handler_t process,
-				    struct perf_session *session)
+static pid_t perf_event__synthesize_comm(union perf_event *event, pid_t pid,
+					 int full, perf_event__handler_t process,
+					 struct perf_session *session)
 {
 	char filename[PATH_MAX];
 	char bf[BUFSIZ];
@@ -126,9 +127,10 @@ out:
 	return tgid;
 }
 
-static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
-					 event__handler_t process,
-					 struct perf_session *session)
+static int perf_event__synthesize_mmap_events(union perf_event *event,
+					      pid_t pid, pid_t tgid,
+					      perf_event__handler_t process,
+					      struct perf_session *session)
 {
 	char filename[PATH_MAX];
 	FILE *fp;
@@ -199,14 +201,14 @@ static int event__synthesize_mmap_events(event_t *event, pid_t pid, pid_t tgid,
 	return 0;
 }
 
-int event__synthesize_modules(event__handler_t process,
-			      struct perf_session *session,
-			      struct machine *machine)
+int perf_event__synthesize_modules(perf_event__handler_t process,
+				   struct perf_session *session,
+				   struct machine *machine)
 {
 	struct rb_node *nd;
 	struct map_groups *kmaps = &machine->kmaps;
-	event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
-
+	union perf_event *event = zalloc((sizeof(event->mmap) +
+					  session->id_hdr_size));
 	if (event == NULL) {
 		pr_debug("Not enough memory synthesizing mmap event "
 			 "for kernel modules\n");
@@ -251,23 +253,24 @@ int event__synthesize_modules(event__handler_t process,
 	return 0;
 }
 
-static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event,
-				      pid_t pid, event__handler_t process,
+static int __event__synthesize_thread(union perf_event *comm_event,
+				      union perf_event *mmap_event,
+				      pid_t pid, perf_event__handler_t process,
 				      struct perf_session *session)
 {
-	pid_t tgid = event__synthesize_comm(comm_event, pid, 1, process,
+	pid_t tgid = perf_event__synthesize_comm(comm_event, pid, 1, process,
 					    session);
 	if (tgid == -1)
 		return -1;
-	return event__synthesize_mmap_events(mmap_event, pid, tgid,
+	return perf_event__synthesize_mmap_events(mmap_event, pid, tgid,
 					     process, session);
 }
 
-int event__synthesize_thread_map(struct thread_map *threads,
-				 event__handler_t process,
-				 struct perf_session *session)
+int perf_event__synthesize_thread_map(struct thread_map *threads,
+				      perf_event__handler_t process,
+				      struct perf_session *session)
 {
-	event_t *comm_event, *mmap_event;
+	union perf_event *comm_event, *mmap_event;
 	int err = -1, thread;
 
 	comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
@@ -294,12 +297,12 @@ out:
 	return err;
 }
 
-int event__synthesize_threads(event__handler_t process,
-			      struct perf_session *session)
+int perf_event__synthesize_threads(perf_event__handler_t process,
+				   struct perf_session *session)
 {
 	DIR *proc;
 	struct dirent dirent, *next;
-	event_t *comm_event, *mmap_event;
+	union perf_event *comm_event, *mmap_event;
 	int err = -1;
 
 	comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size);
@@ -357,10 +360,10 @@ static int find_symbol_cb(void *arg, const char *name, char type,
 	return 1;
 }
 
-int event__synthesize_kernel_mmap(event__handler_t process,
-				  struct perf_session *session,
-				  struct machine *machine,
-				  const char *symbol_name)
+int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
+				       struct perf_session *session,
+				       struct machine *machine,
+				       const char *symbol_name)
 {
 	size_t size;
 	const char *filename, *mmap_name;
@@ -374,8 +377,8 @@ int event__synthesize_kernel_mmap(event__handler_t process,
 	 * kernels.
 	 */
 	struct process_symbol_args args = { .name = symbol_name, };
-	event_t *event = zalloc(sizeof(event->mmap) + session->id_hdr_size);
-
+	union perf_event *event = zalloc((sizeof(event->mmap) +
+					  session->id_hdr_size));
 	if (event == NULL) {
 		pr_debug("Not enough memory synthesizing mmap event "
 			 "for kernel modules\n");
@@ -421,42 +424,15 @@ int event__synthesize_kernel_mmap(event__handler_t process,
 	return err;
 }
 
-static void thread__comm_adjust(struct thread *self, struct hists *hists)
-{
-	char *comm = self->comm;
-
-	if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
-	    (!symbol_conf.comm_list ||
-	     strlist__has_entry(symbol_conf.comm_list, comm))) {
-		u16 slen = strlen(comm);
-
-		if (hists__new_col_len(hists, HISTC_COMM, slen))
-			hists__set_col_len(hists, HISTC_THREAD, slen + 6);
-	}
-}
-
-static int thread__set_comm_adjust(struct thread *self, const char *comm,
-				   struct hists *hists)
+int perf_event__process_comm(union perf_event *event,
+			     struct perf_sample *sample __used,
+			     struct perf_session *session)
 {
-	int ret = thread__set_comm(self, comm);
-
-	if (ret)
-		return ret;
-
-	thread__comm_adjust(self, hists);
+	struct thread *thread = perf_session__findnew(session, event->comm.tid);
 
-	return 0;
-}
+	dump_printf(": %s:%d\n", event->comm.comm, event->comm.tid);
 
-int event__process_comm(event_t *self, struct sample_data *sample __used,
-			struct perf_session *session)
-{
-	struct thread *thread = perf_session__findnew(session, self->comm.tid);
-
-	dump_printf(": %s:%d\n", self->comm.comm, self->comm.tid);
-
-	if (thread == NULL || thread__set_comm_adjust(thread, self->comm.comm,
-						      &session->hists)) {
+	if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
 		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
 		return -1;
 	}
@@ -464,19 +440,21 @@ int event__process_comm(event_t *self, struct sample_data *sample __used,
 	return 0;
 }
 
-int event__process_lost(event_t *self, struct sample_data *sample __used,
-			struct perf_session *session)
+int perf_event__process_lost(union perf_event *event,
+			     struct perf_sample *sample __used,
+			     struct perf_session *session)
 {
 	dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
-		    self->lost.id, self->lost.lost);
-	session->hists.stats.total_lost += self->lost.lost;
+		    event->lost.id, event->lost.lost);
+	session->hists.stats.total_lost += event->lost.lost;
 	return 0;
 }
 
-static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
+static void perf_event__set_kernel_mmap_len(union perf_event *event,
+					    struct map **maps)
 {
-	maps[MAP__FUNCTION]->start = self->mmap.start;
-	maps[MAP__FUNCTION]->end   = self->mmap.start + self->mmap.len;
+	maps[MAP__FUNCTION]->start = event->mmap.start;
+	maps[MAP__FUNCTION]->end   = event->mmap.start + event->mmap.len;
 	/*
 	 * Be a bit paranoid here, some perf.data file came with
 	 * a zero sized synthesized MMAP event for the kernel.
@@ -485,8 +463,8 @@ static void event_set_kernel_mmap_len(struct map **maps, event_t *self)
 		maps[MAP__FUNCTION]->end = ~0ULL;
 }
 
-static int event__process_kernel_mmap(event_t *self,
-			struct perf_session *session)
+static int perf_event__process_kernel_mmap(union perf_event *event,
+					   struct perf_session *session)
 {
 	struct map *map;
 	char kmmap_prefix[PATH_MAX];
@@ -494,9 +472,9 @@ static int event__process_kernel_mmap(event_t *self,
 	enum dso_kernel_type kernel_type;
 	bool is_kernel_mmap;
 
-	machine = perf_session__findnew_machine(session, self->mmap.pid);
+	machine = perf_session__findnew_machine(session, event->mmap.pid);
 	if (!machine) {
-		pr_err("Can't find id %d's machine\n", self->mmap.pid);
+		pr_err("Can't find id %d's machine\n", event->mmap.pid);
 		goto out_problem;
 	}
 
@@ -506,17 +484,17 @@ static int event__process_kernel_mmap(event_t *self,
 	else
 		kernel_type = DSO_TYPE_GUEST_KERNEL;
 
-	is_kernel_mmap = memcmp(self->mmap.filename,
+	is_kernel_mmap = memcmp(event->mmap.filename,
 				kmmap_prefix,
 				strlen(kmmap_prefix)) == 0;
-	if (self->mmap.filename[0] == '/' ||
-	    (!is_kernel_mmap && self->mmap.filename[0] == '[')) {
+	if (event->mmap.filename[0] == '/' ||
+	    (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
 
 		char short_module_name[1024];
 		char *name, *dot;
 
-		if (self->mmap.filename[0] == '/') {
-			name = strrchr(self->mmap.filename, '/');
+		if (event->mmap.filename[0] == '/') {
+			name = strrchr(event->mmap.filename, '/');
 			if (name == NULL)
 				goto out_problem;
 
@@ -528,10 +506,10 @@ static int event__process_kernel_mmap(event_t *self,
 					"[%.*s]", (int)(dot - name), name);
 			strxfrchar(short_module_name, '-', '_');
 		} else
-			strcpy(short_module_name, self->mmap.filename);
+			strcpy(short_module_name, event->mmap.filename);
 
-		map = machine__new_module(machine, self->mmap.start,
-					  self->mmap.filename);
+		map = machine__new_module(machine, event->mmap.start,
+					  event->mmap.filename);
 		if (map == NULL)
 			goto out_problem;
 
@@ -541,9 +519,9 @@ static int event__process_kernel_mmap(event_t *self,
 
 		map->dso->short_name = name;
 		map->dso->sname_alloc = 1;
-		map->end = map->start + self->mmap.len;
+		map->end = map->start + event->mmap.len;
 	} else if (is_kernel_mmap) {
-		const char *symbol_name = (self->mmap.filename +
+		const char *symbol_name = (event->mmap.filename +
 				strlen(kmmap_prefix));
 		/*
 		 * Should be there already, from the build-id table in
@@ -558,10 +536,10 @@ static int event__process_kernel_mmap(event_t *self,
 		if (__machine__create_kernel_maps(machine, kernel) < 0)
 			goto out_problem;
 
-		event_set_kernel_mmap_len(machine->vmlinux_maps, self);
+		perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
 		perf_session__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
 							 symbol_name,
-							 self->mmap.pgoff);
+							 event->mmap.pgoff);
 		if (machine__is_default_guest(machine)) {
 			/*
 			 * preload dso of guest kernel and modules
@@ -575,22 +553,23 @@ out_problem:
 	return -1;
 }
 
-int event__process_mmap(event_t *self, struct sample_data *sample __used,
-			struct perf_session *session)
+int perf_event__process_mmap(union perf_event *event,
+			     struct perf_sample *sample __used,
+			     struct perf_session *session)
 {
 	struct machine *machine;
 	struct thread *thread;
 	struct map *map;
-	u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
 	int ret = 0;
 
 	dump_printf(" %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
-			self->mmap.pid, self->mmap.tid, self->mmap.start,
-			self->mmap.len, self->mmap.pgoff, self->mmap.filename);
+			event->mmap.pid, event->mmap.tid, event->mmap.start,
+			event->mmap.len, event->mmap.pgoff, event->mmap.filename);
 
 	if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
 	    cpumode == PERF_RECORD_MISC_KERNEL) {
-		ret = event__process_kernel_mmap(self, session);
+		ret = perf_event__process_kernel_mmap(event, session);
 		if (ret < 0)
 			goto out_problem;
 		return 0;
@@ -599,12 +578,12 @@ int event__process_mmap(event_t *self, struct sample_data *sample __used,
 	machine = perf_session__find_host_machine(session);
 	if (machine == NULL)
 		goto out_problem;
-	thread = perf_session__findnew(session, self->mmap.pid);
+	thread = perf_session__findnew(session, event->mmap.pid);
 	if (thread == NULL)
 		goto out_problem;
-	map = map__new(&machine->user_dsos, self->mmap.start,
-			self->mmap.len, self->mmap.pgoff,
-			self->mmap.pid, self->mmap.filename,
+	map = map__new(&machine->user_dsos, event->mmap.start,
+			event->mmap.len, event->mmap.pgoff,
+			event->mmap.pid, event->mmap.filename,
 			MAP__FUNCTION);
 	if (map == NULL)
 		goto out_problem;
@@ -617,16 +596,17 @@ out_problem:
 	return 0;
 }
 
-int event__process_task(event_t *self, struct sample_data *sample __used,
-			struct perf_session *session)
+int perf_event__process_task(union perf_event *event,
+			     struct perf_sample *sample __used,
+			     struct perf_session *session)
 {
-	struct thread *thread = perf_session__findnew(session, self->fork.tid);
-	struct thread *parent = perf_session__findnew(session, self->fork.ptid);
+	struct thread *thread = perf_session__findnew(session, event->fork.tid);
+	struct thread *parent = perf_session__findnew(session, event->fork.ptid);
 
-	dump_printf("(%d:%d):(%d:%d)\n", self->fork.pid, self->fork.tid,
-		    self->fork.ppid, self->fork.ptid);
+	dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
+		    event->fork.ppid, event->fork.ptid);
 
-	if (self->header.type == PERF_RECORD_EXIT) {
+	if (event->header.type == PERF_RECORD_EXIT) {
 		perf_session__remove_thread(session, thread);
 		return 0;
 	}
@@ -640,20 +620,22 @@ int event__process_task(event_t *self, struct sample_data *sample __used,
 	return 0;
 }
 
-int event__process(event_t *event, struct sample_data *sample,
-		   struct perf_session *session)
+int perf_event__process(union perf_event *event, struct perf_sample *sample,
+			struct perf_session *session)
 {
 	switch (event->header.type) {
 	case PERF_RECORD_COMM:
-		event__process_comm(event, sample, session);
+		perf_event__process_comm(event, sample, session);
 		break;
 	case PERF_RECORD_MMAP:
-		event__process_mmap(event, sample, session);
+		perf_event__process_mmap(event, sample, session);
 		break;
 	case PERF_RECORD_FORK:
 	case PERF_RECORD_EXIT:
-		event__process_task(event, sample, session);
+		perf_event__process_task(event, sample, session);
 		break;
+	case PERF_RECORD_LOST:
+		perf_event__process_lost(event, sample, session);
 	default:
 		break;
 	}
@@ -750,24 +732,14 @@ void thread__find_addr_location(struct thread *self,
 		al->sym = NULL;
 }
 
-static void dso__calc_col_width(struct dso *self, struct hists *hists)
-{
-	if (!symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
-	    (!symbol_conf.dso_list ||
-	     strlist__has_entry(symbol_conf.dso_list, self->name))) {
-		u16 slen = dso__name_len(self);
-		hists__new_col_len(hists, HISTC_DSO, slen);
-	}
-
-	self->slen_calculated = 1;
-}
-
-int event__preprocess_sample(const event_t *self, struct perf_session *session,
-			     struct addr_location *al, struct sample_data *data,
-			     symbol_filter_t filter)
+int perf_event__preprocess_sample(const union perf_event *event,
+				  struct perf_session *session,
+				  struct addr_location *al,
+				  struct perf_sample *sample,
+				  symbol_filter_t filter)
 {
-	u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
-	struct thread *thread = perf_session__findnew(session, self->ip.pid);
+	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+	struct thread *thread = perf_session__findnew(session, event->ip.pid);
 
 	if (thread == NULL)
 		return -1;
@@ -789,12 +761,12 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
 		machine__create_kernel_maps(&session->host_machine);
 
 	thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
-			      self->ip.pid, self->ip.ip, al);
+			      event->ip.pid, event->ip.ip, al);
 	dump_printf(" ...... dso: %s\n",
 		    al->map ? al->map->dso->long_name :
 			al->level == 'H' ? "[hypervisor]" : "<not found>");
 	al->sym = NULL;
-	al->cpu = data->cpu;
+	al->cpu = sample->cpu;
 
 	if (al->map) {
 		if (symbol_conf.dso_list &&
@@ -805,23 +777,8 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
 			strlist__has_entry(symbol_conf.dso_list,
 					   al->map->dso->long_name)))))
 			goto out_filtered;
-		/*
-		 * We have to do this here as we may have a dso with no symbol
-		 * hit that has a name longer than the ones with symbols
-		 * sampled.
-		 */
-		if (!sort_dso.elide && !al->map->dso->slen_calculated)
-			dso__calc_col_width(al->map->dso, &session->hists);
 
 		al->sym = map__find_symbol(al->map, al->addr, filter);
-	} else {
-		const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
-
-		if (hists__col_len(&session->hists, HISTC_DSO) < unresolved_col_width &&
-		    !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
-		    !symbol_conf.dso_list)
-			hists__set_col_len(&session->hists, HISTC_DSO,
-					   unresolved_col_width);
 	}
 
 	if (symbol_conf.sym_list && al->sym &&
@@ -834,128 +791,3 @@ out_filtered:
 	al->filtered = true;
 	return 0;
 }
-
-static int event__parse_id_sample(const event_t *event,
-				  struct perf_session *session,
-				  struct sample_data *sample)
-{
-	const u64 *array;
-	u64 type;
-
-	sample->cpu = sample->pid = sample->tid = -1;
-	sample->stream_id = sample->id = sample->time = -1ULL;
-
-	if (!session->sample_id_all)
-		return 0;
-
-	array = event->sample.array;
-	array += ((event->header.size -
-		   sizeof(event->header)) / sizeof(u64)) - 1;
-	type = session->sample_type;
-
-	if (type & PERF_SAMPLE_CPU) {
-		u32 *p = (u32 *)array;
-		sample->cpu = *p;
-		array--;
-	}
-
-	if (type & PERF_SAMPLE_STREAM_ID) {
-		sample->stream_id = *array;
-		array--;
-	}
-
-	if (type & PERF_SAMPLE_ID) {
-		sample->id = *array;
-		array--;
-	}
-
-	if (type & PERF_SAMPLE_TIME) {
-		sample->time = *array;
-		array--;
-	}
-
-	if (type & PERF_SAMPLE_TID) {
-		u32 *p = (u32 *)array;
-		sample->pid = p[0];
-		sample->tid = p[1];
-	}
-
-	return 0;
-}
-
-int event__parse_sample(const event_t *event, struct perf_session *session,
-			struct sample_data *data)
-{
-	const u64 *array;
-	u64 type;
-
-	if (event->header.type != PERF_RECORD_SAMPLE)
-		return event__parse_id_sample(event, session, data);
-
-	array = event->sample.array;
-	type = session->sample_type;
-
-	if (type & PERF_SAMPLE_IP) {
-		data->ip = event->ip.ip;
-		array++;
-	}
-
-	if (type & PERF_SAMPLE_TID) {
-		u32 *p = (u32 *)array;
-		data->pid = p[0];
-		data->tid = p[1];
-		array++;
-	}
-
-	if (type & PERF_SAMPLE_TIME) {
-		data->time = *array;
-		array++;
-	}
-
-	if (type & PERF_SAMPLE_ADDR) {
-		data->addr = *array;
-		array++;
-	}
-
-	data->id = -1ULL;
-	if (type & PERF_SAMPLE_ID) {
-		data->id = *array;
-		array++;
-	}
-
-	if (type & PERF_SAMPLE_STREAM_ID) {
-		data->stream_id = *array;
-		array++;
-	}
-
-	if (type & PERF_SAMPLE_CPU) {
-		u32 *p = (u32 *)array;
-		data->cpu = *p;
-		array++;
-	} else
-		data->cpu = -1;
-
-	if (type & PERF_SAMPLE_PERIOD) {
-		data->period = *array;
-		array++;
-	}
-
-	if (type & PERF_SAMPLE_READ) {
-		pr_debug("PERF_SAMPLE_READ is unsuported for now\n");
-		return -1;
-	}
-
-	if (type & PERF_SAMPLE_CALLCHAIN) {
-		data->callchain = (struct ip_callchain *)array;
-		array += 1 + data->callchain->nr;
-	}
-
-	if (type & PERF_SAMPLE_RAW) {
-		u32 *p = (u32 *)array;
-		data->raw_size = *p;
-		p++;
-		data->raw_data = p;
-	}
-
-	return 0;
-}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index cc7b52f..9c35170 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -61,7 +61,7 @@ struct sample_event {
 	u64 array[];
 };
 
-struct sample_data {
+struct perf_sample {
 	u64 ip;
 	u32 pid, tid;
 	u64 time;
@@ -117,7 +117,7 @@ struct tracing_data_event {
 	u32 size;
 };
 
-typedef union event_union {
+union perf_event {
 	struct perf_event_header	header;
 	struct ip_event			ip;
 	struct mmap_event		mmap;
@@ -130,50 +130,54 @@ typedef union event_union {
 	struct event_type_event		event_type;
 	struct tracing_data_event	tracing_data;
 	struct build_id_event		build_id;
-} event_t;
+};
 
-void event__print_totals(void);
+void perf_event__print_totals(void);
 
 struct perf_session;
 struct thread_map;
 
-typedef int (*event__handler_synth_t)(event_t *event, 
+typedef int (*perf_event__handler_synth_t)(union perf_event *event, 
+					   struct perf_session *session);
+typedef int (*perf_event__handler_t)(union perf_event *event,
+				     struct perf_sample *sample,
 				      struct perf_session *session);
-typedef int (*event__handler_t)(event_t *event, struct sample_data *sample,
-				struct perf_session *session);
-
-int event__synthesize_thread_map(struct thread_map *threads,
-				 event__handler_t process,
-				 struct perf_session *session);
-int event__synthesize_threads(event__handler_t process,
-			      struct perf_session *session);
-int event__synthesize_kernel_mmap(event__handler_t process,
-				struct perf_session *session,
-				struct machine *machine,
-				const char *symbol_name);
-
-int event__synthesize_modules(event__handler_t process,
-			      struct perf_session *session,
-			      struct machine *machine);
-
-int event__process_comm(event_t *self, struct sample_data *sample,
-			struct perf_session *session);
-int event__process_lost(event_t *self, struct sample_data *sample,
-			struct perf_session *session);
-int event__process_mmap(event_t *self, struct sample_data *sample,
-			struct perf_session *session);
-int event__process_task(event_t *self, struct sample_data *sample,
+
+int perf_event__synthesize_thread_map(struct thread_map *threads,
+				      perf_event__handler_t process,
+				      struct perf_session *session);
+int perf_event__synthesize_threads(perf_event__handler_t process,
+				   struct perf_session *session);
+int perf_event__synthesize_kernel_mmap(perf_event__handler_t process,
+				       struct perf_session *session,
+				       struct machine *machine,
+				       const char *symbol_name);
+
+int perf_event__synthesize_modules(perf_event__handler_t process,
+				   struct perf_session *session,
+				   struct machine *machine);
+
+int perf_event__process_comm(union perf_event *event, struct perf_sample *sample,
+			     struct perf_session *session);
+int perf_event__process_lost(union perf_event *event, struct perf_sample *sample,
+			     struct perf_session *session);
+int perf_event__process_mmap(union perf_event *event, struct perf_sample *sample,
+			     struct perf_session *session);
+int perf_event__process_task(union perf_event *event, struct perf_sample *sample,
+			     struct perf_session *session);
+int perf_event__process(union perf_event *event, struct perf_sample *sample,
 			struct perf_session *session);
-int event__process(event_t *event, struct sample_data *sample,
-		   struct perf_session *session);
 
 struct addr_location;
-int event__preprocess_sample(const event_t *self, struct perf_session *session,
-			     struct addr_location *al, struct sample_data *data,
-			     symbol_filter_t filter);
-int event__parse_sample(const event_t *event, struct perf_session *session,
-			struct sample_data *sample);
+int perf_event__preprocess_sample(const union perf_event *self,
+				  struct perf_session *session,
+				  struct addr_location *al,
+				  struct perf_sample *sample,
+				  symbol_filter_t filter);
+
+const char *perf_event__name(unsigned int id);
 
-const char *event__get_event_name(unsigned int id);
+int perf_event__parse_sample(const union perf_event *event, u64 type,
+			     bool sample_id_all, struct perf_sample *sample);
 
 #endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
new file mode 100644
index 0000000..d852cef
--- /dev/null
+++ b/tools/perf/util/evlist.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Parts came from builtin-{top,stat,record}.c, see those files for further
+ * copyright notes.
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+#include <poll.h>
+#include "cpumap.h"
+#include "thread_map.h"
+#include "evlist.h"
+#include "evsel.h"
+#include "util.h"
+
+#include <sys/mman.h>
+
+#include <linux/bitops.h>
+#include <linux/hash.h>
+
+#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
+
+void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
+		       struct thread_map *threads)
+{
+	int i;
+
+	for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i)
+		INIT_HLIST_HEAD(&evlist->heads[i]);
+	INIT_LIST_HEAD(&evlist->entries);
+	perf_evlist__set_maps(evlist, cpus, threads);
+}
+
+struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
+				     struct thread_map *threads)
+{
+	struct perf_evlist *evlist = zalloc(sizeof(*evlist));
+
+	if (evlist != NULL)
+		perf_evlist__init(evlist, cpus, threads);
+
+	return evlist;
+}
+
+static void perf_evlist__purge(struct perf_evlist *evlist)
+{
+	struct perf_evsel *pos, *n;
+
+	list_for_each_entry_safe(pos, n, &evlist->entries, node) {
+		list_del_init(&pos->node);
+		perf_evsel__delete(pos);
+	}
+
+	evlist->nr_entries = 0;
+}
+
+void perf_evlist__exit(struct perf_evlist *evlist)
+{
+	free(evlist->mmap);
+	free(evlist->pollfd);
+	evlist->mmap = NULL;
+	evlist->pollfd = NULL;
+}
+
+void perf_evlist__delete(struct perf_evlist *evlist)
+{
+	perf_evlist__purge(evlist);
+	perf_evlist__exit(evlist);
+	free(evlist);
+}
+
+void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
+{
+	list_add_tail(&entry->node, &evlist->entries);
+	++evlist->nr_entries;
+}
+
+int perf_evlist__add_default(struct perf_evlist *evlist)
+{
+	struct perf_event_attr attr = {
+		.type = PERF_TYPE_HARDWARE,
+		.config = PERF_COUNT_HW_CPU_CYCLES,
+	};
+	struct perf_evsel *evsel = perf_evsel__new(&attr, 0);
+
+	if (evsel == NULL)
+		return -ENOMEM;
+
+	perf_evlist__add(evlist, evsel);
+	return 0;
+}
+
+int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
+{
+	int nfds = evlist->cpus->nr * evlist->threads->nr * evlist->nr_entries;
+	evlist->pollfd = malloc(sizeof(struct pollfd) * nfds);
+	return evlist->pollfd != NULL ? 0 : -ENOMEM;
+}
+
+void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
+{
+	fcntl(fd, F_SETFL, O_NONBLOCK);
+	evlist->pollfd[evlist->nr_fds].fd = fd;
+	evlist->pollfd[evlist->nr_fds].events = POLLIN;
+	evlist->nr_fds++;
+}
+
+static void perf_evlist__id_hash(struct perf_evlist *evlist,
+				 struct perf_evsel *evsel,
+				 int cpu, int thread, u64 id)
+{
+	int hash;
+	struct perf_sample_id *sid = SID(evsel, cpu, thread);
+
+	sid->id = id;
+	sid->evsel = evsel;
+	hash = hash_64(sid->id, PERF_EVLIST__HLIST_BITS);
+	hlist_add_head(&sid->node, &evlist->heads[hash]);
+}
+
+void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
+			 int cpu, int thread, u64 id)
+{
+	perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
+	evsel->id[evsel->ids++] = id;
+}
+
+static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+				  struct perf_evsel *evsel,
+				  int cpu, int thread, int fd)
+{
+	u64 read_data[4] = { 0, };
+	int id_idx = 1; /* The first entry is the counter value */
+
+	if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
+	    read(fd, &read_data, sizeof(read_data)) == -1)
+		return -1;
+
+	if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
+		++id_idx;
+	if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
+		++id_idx;
+
+	perf_evlist__id_add(evlist, evsel, cpu, thread, read_data[id_idx]);
+	return 0;
+}
+
+struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
+{
+	struct hlist_head *head;
+	struct hlist_node *pos;
+	struct perf_sample_id *sid;
+	int hash;
+
+	if (evlist->nr_entries == 1)
+		return list_entry(evlist->entries.next, struct perf_evsel, node);
+
+	hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
+	head = &evlist->heads[hash];
+
+	hlist_for_each_entry(sid, pos, head, node)
+		if (sid->id == id)
+			return sid->evsel;
+	return NULL;
+}
+
+union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *evlist, int cpu)
+{
+	/* XXX Move this to perf.c, making it generally available */
+	unsigned int page_size = sysconf(_SC_PAGE_SIZE);
+	struct perf_mmap *md = &evlist->mmap[cpu];
+	unsigned int head = perf_mmap__read_head(md);
+	unsigned int old = md->prev;
+	unsigned char *data = md->base + page_size;
+	union perf_event *event = NULL;
+
+	if (evlist->overwrite) {
+		/*
+		 * If we're further behind than half the buffer, there's a chance
+		 * the writer will bite our tail and mess up the samples under us.
+		 *
+		 * If we somehow ended up ahead of the head, we got messed up.
+		 *
+		 * In either case, truncate and restart at head.
+		 */
+		int diff = head - old;
+		if (diff > md->mask / 2 || diff < 0) {
+			fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
+
+			/*
+			 * head points to a known good entry, start there.
+			 */
+			old = head;
+		}
+	}
+
+	if (old != head) {
+		size_t size;
+
+		event = (union perf_event *)&data[old & md->mask];
+		size = event->header.size;
+
+		/*
+		 * Event straddles the mmap boundary -- header should always
+		 * be inside due to u64 alignment of output.
+		 */
+		if ((old & md->mask) + size != ((old + size) & md->mask)) {
+			unsigned int offset = old;
+			unsigned int len = min(sizeof(*event), size), cpy;
+			void *dst = &evlist->event_copy;
+
+			do {
+				cpy = min(md->mask + 1 - (offset & md->mask), len);
+				memcpy(dst, &data[offset & md->mask], cpy);
+				offset += cpy;
+				dst += cpy;
+				len -= cpy;
+			} while (len);
+
+			event = &evlist->event_copy;
+		}
+
+		old += size;
+	}
+
+	md->prev = old;
+
+	if (!evlist->overwrite)
+		perf_mmap__write_tail(md, old);
+
+	return event;
+}
+
+void perf_evlist__munmap(struct perf_evlist *evlist)
+{
+	int cpu;
+
+	for (cpu = 0; cpu < evlist->cpus->nr; cpu++) {
+		if (evlist->mmap[cpu].base != NULL) {
+			munmap(evlist->mmap[cpu].base, evlist->mmap_len);
+			evlist->mmap[cpu].base = NULL;
+		}
+	}
+}
+
+int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
+{
+	evlist->mmap = zalloc(evlist->cpus->nr * sizeof(struct perf_mmap));
+	return evlist->mmap != NULL ? 0 : -ENOMEM;
+}
+
+static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot,
+			       int mask, int fd)
+{
+	evlist->mmap[cpu].prev = 0;
+	evlist->mmap[cpu].mask = mask;
+	evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
+				      MAP_SHARED, fd, 0);
+	if (evlist->mmap[cpu].base == MAP_FAILED)
+		return -1;
+
+	perf_evlist__add_pollfd(evlist, fd);
+	return 0;
+}
+
+/** perf_evlist__mmap - Create per cpu maps to receive events
+ *
+ * @evlist - list of events
+ * @pages - map length in pages
+ * @overwrite - overwrite older events?
+ *
+ * If overwrite is false the user needs to signal event consuption using:
+ *
+ *	struct perf_mmap *m = &evlist->mmap[cpu];
+ *	unsigned int head = perf_mmap__read_head(m);
+ *
+ *	perf_mmap__write_tail(m, head)
+ *
+ * Using perf_evlist__read_on_cpu does this automatically.
+ */
+int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
+{
+	unsigned int page_size = sysconf(_SC_PAGE_SIZE);
+	int mask = pages * page_size - 1, cpu;
+	struct perf_evsel *first_evsel, *evsel;
+	const struct cpu_map *cpus = evlist->cpus;
+	const struct thread_map *threads = evlist->threads;
+	int thread, prot = PROT_READ | (overwrite ? 0 : PROT_WRITE);
+
+	if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0)
+		return -ENOMEM;
+
+	if (evlist->pollfd == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
+		return -ENOMEM;
+
+	evlist->overwrite = overwrite;
+	evlist->mmap_len = (pages + 1) * page_size;
+	first_evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+		    evsel->sample_id == NULL &&
+		    perf_evsel__alloc_id(evsel, cpus->nr, threads->nr) < 0)
+			return -ENOMEM;
+
+		for (cpu = 0; cpu < cpus->nr; cpu++) {
+			for (thread = 0; thread < threads->nr; thread++) {
+				int fd = FD(evsel, cpu, thread);
+
+				if (evsel->idx || thread) {
+					if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
+						  FD(first_evsel, cpu, 0)) != 0)
+						goto out_unmap;
+				} else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0)
+					goto out_unmap;
+
+				if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
+				    perf_evlist__id_add_fd(evlist, evsel, cpu, thread, fd) < 0)
+					goto out_unmap;
+			}
+		}
+	}
+
+	return 0;
+
+out_unmap:
+	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		if (evlist->mmap[cpu].base != NULL) {
+			munmap(evlist->mmap[cpu].base, evlist->mmap_len);
+			evlist->mmap[cpu].base = NULL;
+		}
+	}
+	return -1;
+}
+
+int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
+			     pid_t target_tid, const char *cpu_list)
+{
+	evlist->threads = thread_map__new(target_pid, target_tid);
+
+	if (evlist->threads == NULL)
+		return -1;
+
+	if (target_tid != -1)
+		evlist->cpus = cpu_map__dummy_new();
+	else
+		evlist->cpus = cpu_map__new(cpu_list);
+
+	if (evlist->cpus == NULL)
+		goto out_delete_threads;
+
+	return 0;
+
+out_delete_threads:
+	thread_map__delete(evlist->threads);
+	return -1;
+}
+
+void perf_evlist__delete_maps(struct perf_evlist *evlist)
+{
+	cpu_map__delete(evlist->cpus);
+	thread_map__delete(evlist->threads);
+	evlist->cpus	= NULL;
+	evlist->threads = NULL;
+}
+
+int perf_evlist__set_filters(struct perf_evlist *evlist)
+{
+	const struct thread_map *threads = evlist->threads;
+	const struct cpu_map *cpus = evlist->cpus;
+	struct perf_evsel *evsel;
+	char *filter;
+	int thread;
+	int cpu;
+	int err;
+	int fd;
+
+	list_for_each_entry(evsel, &evlist->entries, node) {
+		filter = evsel->filter;
+		if (!filter)
+			continue;
+		for (cpu = 0; cpu < cpus->nr; cpu++) {
+			for (thread = 0; thread < threads->nr; thread++) {
+				fd = FD(evsel, cpu, thread);
+				err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter);
+				if (err)
+					return err;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
new file mode 100644
index 0000000..8b1cb7a
--- /dev/null
+++ b/tools/perf/util/evlist.h
@@ -0,0 +1,68 @@
+#ifndef __PERF_EVLIST_H
+#define __PERF_EVLIST_H 1
+
+#include <linux/list.h>
+#include "../perf.h"
+#include "event.h"
+
+struct pollfd;
+struct thread_map;
+struct cpu_map;
+
+#define PERF_EVLIST__HLIST_BITS 8
+#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
+
+struct perf_evlist {
+	struct list_head entries;
+	struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
+	int		 nr_entries;
+	int		 nr_fds;
+	int		 mmap_len;
+	bool		 overwrite;
+	union perf_event event_copy;
+	struct perf_mmap *mmap;
+	struct pollfd	 *pollfd;
+	struct thread_map *threads;
+	struct cpu_map	  *cpus;
+};
+
+struct perf_evsel;
+
+struct perf_evlist *perf_evlist__new(struct cpu_map *cpus,
+				     struct thread_map *threads);
+void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
+		       struct thread_map *threads);
+void perf_evlist__exit(struct perf_evlist *evlist);
+void perf_evlist__delete(struct perf_evlist *evlist);
+
+void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
+int perf_evlist__add_default(struct perf_evlist *evlist);
+
+void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
+			 int cpu, int thread, u64 id);
+
+int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
+void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
+
+struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
+
+union perf_event *perf_evlist__read_on_cpu(struct perf_evlist *self, int cpu);
+
+int perf_evlist__alloc_mmap(struct perf_evlist *evlist);
+int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite);
+void perf_evlist__munmap(struct perf_evlist *evlist);
+
+static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
+					 struct cpu_map *cpus,
+					 struct thread_map *threads)
+{
+	evlist->cpus	= cpus;
+	evlist->threads	= threads;
+}
+
+int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
+			     pid_t target_tid, const char *cpu_list);
+void perf_evlist__delete_maps(struct perf_evlist *evlist);
+int perf_evlist__set_filters(struct perf_evlist *evlist);
+
+#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d8575d3..662596a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1,20 +1,34 @@
+/*
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Parts came from builtin-{top,stat,record}.c, see those files for further
+ * copyright notes.
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
 #include "evsel.h"
-#include "../perf.h"
+#include "evlist.h"
 #include "util.h"
 #include "cpumap.h"
-#include "thread.h"
+#include "thread_map.h"
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 
+void perf_evsel__init(struct perf_evsel *evsel,
+		      struct perf_event_attr *attr, int idx)
+{
+	evsel->idx	   = idx;
+	evsel->attr	   = *attr;
+	INIT_LIST_HEAD(&evsel->node);
+}
+
 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
 {
 	struct perf_evsel *evsel = zalloc(sizeof(*evsel));
 
-	if (evsel != NULL) {
-		evsel->idx	   = idx;
-		evsel->attr	   = *attr;
-		INIT_LIST_HEAD(&evsel->node);
-	}
+	if (evsel != NULL)
+		perf_evsel__init(evsel, attr, idx);
 
 	return evsel;
 }
@@ -25,6 +39,22 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 	return evsel->fd != NULL ? 0 : -ENOMEM;
 }
 
+int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
+{
+	evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
+	if (evsel->sample_id == NULL)
+		return -ENOMEM;
+
+	evsel->id = zalloc(ncpus * nthreads * sizeof(u64));
+	if (evsel->id == NULL) {
+		xyarray__delete(evsel->sample_id);
+		evsel->sample_id = NULL;
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
 {
 	evsel->counts = zalloc((sizeof(*evsel->counts) +
@@ -38,6 +68,14 @@ void perf_evsel__free_fd(struct perf_evsel *evsel)
 	evsel->fd = NULL;
 }
 
+void perf_evsel__free_id(struct perf_evsel *evsel)
+{
+	xyarray__delete(evsel->sample_id);
+	evsel->sample_id = NULL;
+	free(evsel->id);
+	evsel->id = NULL;
+}
+
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 {
 	int cpu, thread;
@@ -49,10 +87,19 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 		}
 }
 
-void perf_evsel__delete(struct perf_evsel *evsel)
+void perf_evsel__exit(struct perf_evsel *evsel)
 {
 	assert(list_empty(&evsel->node));
 	xyarray__delete(evsel->fd);
+	xyarray__delete(evsel->sample_id);
+	free(evsel->id);
+}
+
+void perf_evsel__delete(struct perf_evsel *evsel)
+{
+	perf_evsel__exit(evsel);
+	close_cgroup(evsel->cgrp);
+	free(evsel->name);
 	free(evsel);
 }
 
@@ -128,21 +175,51 @@ int __perf_evsel__read(struct perf_evsel *evsel,
 }
 
 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-			      struct thread_map *threads)
+			      struct thread_map *threads, bool group, bool inherit)
 {
 	int cpu, thread;
+	unsigned long flags = 0;
+	int pid = -1;
 
 	if (evsel->fd == NULL &&
 	    perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
 		return -1;
 
+	if (evsel->cgrp) {
+		flags = PERF_FLAG_PID_CGROUP;
+		pid = evsel->cgrp->fd;
+	}
+
 	for (cpu = 0; cpu < cpus->nr; cpu++) {
+		int group_fd = -1;
+		/*
+		 * Don't allow mmap() of inherited per-task counters. This
+		 * would create a performance issue due to all children writing
+		 * to the same buffer.
+		 *
+		 * FIXME:
+		 * Proper fix is not to pass 'inherit' to perf_evsel__open*,
+		 * but a 'flags' parameter, with 'group' folded there as well,
+		 * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if
+		 * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is
+		 * set. Lets go for the minimal fix first tho.
+		 */
+		evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit;
+
 		for (thread = 0; thread < threads->nr; thread++) {
+
+			if (!evsel->cgrp)
+				pid = threads->map[thread];
+
 			FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr,
-								     threads->map[thread],
-								     cpus->map[cpu], -1, 0);
+								     pid,
+								     cpus->map[cpu],
+								     group_fd, flags);
 			if (FD(evsel, cpu, thread) < 0)
 				goto out_close;
+
+			if (group && group_fd == -1)
+				group_fd = FD(evsel, cpu, thread);
 		}
 	}
 
@@ -175,10 +252,9 @@ static struct {
 	.threads = { -1, },
 };
 
-int perf_evsel__open(struct perf_evsel *evsel,
-		     struct cpu_map *cpus, struct thread_map *threads)
+int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
+		     struct thread_map *threads, bool group, bool inherit)
 {
-
 	if (cpus == NULL) {
 		/* Work around old compiler warnings about strict aliasing */
 		cpus = &empty_cpu_map.map;
@@ -187,15 +263,135 @@ int perf_evsel__open(struct perf_evsel *evsel,
 	if (threads == NULL)
 		threads = &empty_thread_map.map;
 
-	return __perf_evsel__open(evsel, cpus, threads);
+	return __perf_evsel__open(evsel, cpus, threads, group, inherit);
 }
 
-int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus)
+int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
+			     struct cpu_map *cpus, bool group, bool inherit)
 {
-	return __perf_evsel__open(evsel, cpus, &empty_thread_map.map);
+	return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit);
+}
+
+int perf_evsel__open_per_thread(struct perf_evsel *evsel,
+				struct thread_map *threads, bool group, bool inherit)
+{
+	return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit);
+}
+
+static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
+				       struct perf_sample *sample)
+{
+	const u64 *array = event->sample.array;
+
+	array += ((event->header.size -
+		   sizeof(event->header)) / sizeof(u64)) - 1;
+
+	if (type & PERF_SAMPLE_CPU) {
+		u32 *p = (u32 *)array;
+		sample->cpu = *p;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_STREAM_ID) {
+		sample->stream_id = *array;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_ID) {
+		sample->id = *array;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_TIME) {
+		sample->time = *array;
+		array--;
+	}
+
+	if (type & PERF_SAMPLE_TID) {
+		u32 *p = (u32 *)array;
+		sample->pid = p[0];
+		sample->tid = p[1];
+	}
+
+	return 0;
 }
 
-int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads)
+int perf_event__parse_sample(const union perf_event *event, u64 type,
+			     bool sample_id_all, struct perf_sample *data)
 {
-	return __perf_evsel__open(evsel, &empty_cpu_map.map, threads);
+	const u64 *array;
+
+	data->cpu = data->pid = data->tid = -1;
+	data->stream_id = data->id = data->time = -1ULL;
+
+	if (event->header.type != PERF_RECORD_SAMPLE) {
+		if (!sample_id_all)
+			return 0;
+		return perf_event__parse_id_sample(event, type, data);
+	}
+
+	array = event->sample.array;
+
+	if (type & PERF_SAMPLE_IP) {
+		data->ip = event->ip.ip;
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_TID) {
+		u32 *p = (u32 *)array;
+		data->pid = p[0];
+		data->tid = p[1];
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_TIME) {
+		data->time = *array;
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_ADDR) {
+		data->addr = *array;
+		array++;
+	}
+
+	data->id = -1ULL;
+	if (type & PERF_SAMPLE_ID) {
+		data->id = *array;
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_STREAM_ID) {
+		data->stream_id = *array;
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_CPU) {
+		u32 *p = (u32 *)array;
+		data->cpu = *p;
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_PERIOD) {
+		data->period = *array;
+		array++;
+	}
+
+	if (type & PERF_SAMPLE_READ) {
+		fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n");
+		return -1;
+	}
+
+	if (type & PERF_SAMPLE_CALLCHAIN) {
+		data->callchain = (struct ip_callchain *)array;
+		array += 1 + data->callchain->nr;
+	}
+
+	if (type & PERF_SAMPLE_RAW) {
+		u32 *p = (u32 *)array;
+		data->raw_size = *p;
+		p++;
+		data->raw_data = p;
+	}
+
+	return 0;
 }
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b2d755f..6710ab5 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -6,6 +6,8 @@
 #include "../../../include/linux/perf_event.h"
 #include "types.h"
 #include "xyarray.h"
+#include "cgroup.h"
+#include "hist.h"
  
 struct perf_counts_values {
 	union {
@@ -24,31 +26,66 @@ struct perf_counts {
 	struct perf_counts_values cpu[];
 };
 
+struct perf_evsel;
+
+/*
+ * Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are
+ * more than one entry in the evlist.
+ */
+struct perf_sample_id {
+	struct hlist_node 	node;
+	u64		 	id;
+	struct perf_evsel	*evsel;
+};
+
+/** struct perf_evsel - event selector
+ *
+ * @name - Can be set to retain the original event name passed by the user,
+ *         so that when showing results in tools such as 'perf stat', we
+ *         show the name used, not some alias.
+ */
 struct perf_evsel {
 	struct list_head	node;
 	struct perf_event_attr	attr;
 	char			*filter;
 	struct xyarray		*fd;
+	struct xyarray		*sample_id;
+	u64			*id;
 	struct perf_counts	*counts;
 	int			idx;
-	void			*priv;
+	int			ids;
+	struct hists		hists;
+	char			*name;
+	union {
+		void		*priv;
+		off_t		id_offset;
+	};
+	struct cgroup_sel	*cgrp;
 };
 
 struct cpu_map;
 struct thread_map;
+struct perf_evlist;
 
 struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx);
+void perf_evsel__init(struct perf_evsel *evsel,
+		      struct perf_event_attr *attr, int idx);
+void perf_evsel__exit(struct perf_evsel *evsel);
 void perf_evsel__delete(struct perf_evsel *evsel);
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
+int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
 void perf_evsel__free_fd(struct perf_evsel *evsel);
+void perf_evsel__free_id(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
-int perf_evsel__open_per_cpu(struct perf_evsel *evsel, struct cpu_map *cpus);
-int perf_evsel__open_per_thread(struct perf_evsel *evsel, struct thread_map *threads);
-int perf_evsel__open(struct perf_evsel *evsel, 
-		     struct cpu_map *cpus, struct thread_map *threads);
+int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
+			     struct cpu_map *cpus, bool group, bool inherit);
+int perf_evsel__open_per_thread(struct perf_evsel *evsel,
+				struct thread_map *threads, bool group, bool inherit);
+int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
+		     struct thread_map *threads, bool group, bool inherit);
 
 #define perf_evsel__match(evsel, t, c)		\
 	(evsel->attr.type == PERF_TYPE_##t &&	\
diff --git a/tools/perf/util/exec_cmd.c b/tools/perf/util/exec_cmd.c
index 67eeff5..7adf4ad 100644
--- a/tools/perf/util/exec_cmd.c
+++ b/tools/perf/util/exec_cmd.c
@@ -11,31 +11,12 @@ static const char *argv0_path;
 
 const char *system_path(const char *path)
 {
-#ifdef RUNTIME_PREFIX
-	static const char *prefix;
-#else
 	static const char *prefix = PREFIX;
-#endif
 	struct strbuf d = STRBUF_INIT;
 
 	if (is_absolute_path(path))
 		return path;
 
-#ifdef RUNTIME_PREFIX
-	assert(argv0_path);
-	assert(is_absolute_path(argv0_path));
-
-	if (!prefix &&
-	    !(prefix = strip_path_suffix(argv0_path, PERF_EXEC_PATH)) &&
-	    !(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
-	    !(prefix = strip_path_suffix(argv0_path, "perf"))) {
-		prefix = PREFIX;
-		fprintf(stderr, "RUNTIME_PREFIX requested, "
-				"but prefix computation failed.  "
-				"Using static fallback '%s'.\n", prefix);
-	}
-#endif
-
 	strbuf_addf(&d, "%s/%s", prefix, path);
 	path = strbuf_detach(&d, NULL);
 	return path;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 0866bcd..e5230c0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,8 @@
 #include <linux/list.h>
 #include <linux/kernel.h>
 
+#include "evlist.h"
+#include "evsel.h"
 #include "util.h"
 #include "header.h"
 #include "../perf.h"
@@ -18,89 +20,6 @@
 
 static bool no_buildid_cache = false;
 
-/*
- * Create new perf.data header attribute:
- */
-struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr)
-{
-	struct perf_header_attr *self = malloc(sizeof(*self));
-
-	if (self != NULL) {
-		self->attr = *attr;
-		self->ids  = 0;
-		self->size = 1;
-		self->id   = malloc(sizeof(u64));
-		if (self->id == NULL) {
-			free(self);
-			self = NULL;
-		}
-	}
-
-	return self;
-}
-
-void perf_header_attr__delete(struct perf_header_attr *self)
-{
-	free(self->id);
-	free(self);
-}
-
-int perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
-{
-	int pos = self->ids;
-
-	self->ids++;
-	if (self->ids > self->size) {
-		int nsize = self->size * 2;
-		u64 *nid = realloc(self->id, nsize * sizeof(u64));
-
-		if (nid == NULL)
-			return -1;
-
-		self->size = nsize;
-		self->id = nid;
-	}
-	self->id[pos] = id;
-	return 0;
-}
-
-int perf_header__init(struct perf_header *self)
-{
-	self->size = 1;
-	self->attr = malloc(sizeof(void *));
-	return self->attr == NULL ? -ENOMEM : 0;
-}
-
-void perf_header__exit(struct perf_header *self)
-{
-	int i;
-	for (i = 0; i < self->attrs; ++i)
-                perf_header_attr__delete(self->attr[i]);
-	free(self->attr);
-}
-
-int perf_header__add_attr(struct perf_header *self,
-			  struct perf_header_attr *attr)
-{
-	if (self->frozen)
-		return -1;
-
-	if (self->attrs == self->size) {
-		int nsize = self->size * 2;
-		struct perf_header_attr **nattr;
-
-		nattr = realloc(self->attr, nsize * sizeof(void *));
-		if (nattr == NULL)
-			return -1;
-
-		self->size = nsize;
-		self->attr = nattr;
-	}
-
-	self->attr[self->attrs++] = attr;
-	return 0;
-}
-
 static int event_count;
 static struct perf_trace_event_type *events;
 
@@ -147,19 +66,19 @@ struct perf_file_attr {
 	struct perf_file_section	ids;
 };
 
-void perf_header__set_feat(struct perf_header *self, int feat)
+void perf_header__set_feat(struct perf_header *header, int feat)
 {
-	set_bit(feat, self->adds_features);
+	set_bit(feat, header->adds_features);
 }
 
-void perf_header__clear_feat(struct perf_header *self, int feat)
+void perf_header__clear_feat(struct perf_header *header, int feat)
 {
-	clear_bit(feat, self->adds_features);
+	clear_bit(feat, header->adds_features);
 }
 
-bool perf_header__has_feat(const struct perf_header *self, int feat)
+bool perf_header__has_feat(const struct perf_header *header, int feat)
 {
-	return test_bit(feat, self->adds_features);
+	return test_bit(feat, header->adds_features);
 }
 
 static int do_write(int fd, const void *buf, size_t size)
@@ -228,22 +147,22 @@ static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
 	return 0;
 }
 
-static int machine__write_buildid_table(struct machine *self, int fd)
+static int machine__write_buildid_table(struct machine *machine, int fd)
 {
 	int err;
 	u16 kmisc = PERF_RECORD_MISC_KERNEL,
 	    umisc = PERF_RECORD_MISC_USER;
 
-	if (!machine__is_host(self)) {
+	if (!machine__is_host(machine)) {
 		kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
 		umisc = PERF_RECORD_MISC_GUEST_USER;
 	}
 
-	err = __dsos__write_buildid_table(&self->kernel_dsos, self->pid,
+	err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
 					  kmisc, fd);
 	if (err == 0)
-		err = __dsos__write_buildid_table(&self->user_dsos,
-						  self->pid, umisc, fd);
+		err = __dsos__write_buildid_table(&machine->user_dsos,
+						  machine->pid, umisc, fd);
 	return err;
 }
 
@@ -366,12 +285,12 @@ out_free:
 	return err;
 }
 
-static int dso__cache_build_id(struct dso *self, const char *debugdir)
+static int dso__cache_build_id(struct dso *dso, const char *debugdir)
 {
-	bool is_kallsyms = self->kernel && self->long_name[0] != '/';
+	bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
 
-	return build_id_cache__add_b(self->build_id, sizeof(self->build_id),
-				     self->long_name, debugdir, is_kallsyms);
+	return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
+				     dso->long_name, debugdir, is_kallsyms);
 }
 
 static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
@@ -386,14 +305,14 @@ static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
 	return err;
 }
 
-static int machine__cache_build_ids(struct machine *self, const char *debugdir)
+static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
 {
-	int ret = __dsos__cache_build_ids(&self->kernel_dsos, debugdir);
-	ret |= __dsos__cache_build_ids(&self->user_dsos, debugdir);
+	int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
+	ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
 	return ret;
 }
 
-static int perf_session__cache_build_ids(struct perf_session *self)
+static int perf_session__cache_build_ids(struct perf_session *session)
 {
 	struct rb_node *nd;
 	int ret;
@@ -404,28 +323,28 @@ static int perf_session__cache_build_ids(struct perf_session *self)
 	if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
 		return -1;
 
-	ret = machine__cache_build_ids(&self->host_machine, debugdir);
+	ret = machine__cache_build_ids(&session->host_machine, debugdir);
 
-	for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) {
+	for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
 		struct machine *pos = rb_entry(nd, struct machine, rb_node);
 		ret |= machine__cache_build_ids(pos, debugdir);
 	}
 	return ret ? -1 : 0;
 }
 
-static bool machine__read_build_ids(struct machine *self, bool with_hits)
+static bool machine__read_build_ids(struct machine *machine, bool with_hits)
 {
-	bool ret = __dsos__read_build_ids(&self->kernel_dsos, with_hits);
-	ret |= __dsos__read_build_ids(&self->user_dsos, with_hits);
+	bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
+	ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
 	return ret;
 }
 
-static bool perf_session__read_build_ids(struct perf_session *self, bool with_hits)
+static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
 {
 	struct rb_node *nd;
-	bool ret = machine__read_build_ids(&self->host_machine, with_hits);
+	bool ret = machine__read_build_ids(&session->host_machine, with_hits);
 
-	for (nd = rb_first(&self->machines); nd; nd = rb_next(nd)) {
+	for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
 		struct machine *pos = rb_entry(nd, struct machine, rb_node);
 		ret |= machine__read_build_ids(pos, with_hits);
 	}
@@ -433,7 +352,8 @@ static bool perf_session__read_build_ids(struct perf_session *self, bool with_hi
 	return ret;
 }
 
-static int perf_header__adds_write(struct perf_header *self, int fd)
+static int perf_header__adds_write(struct perf_header *header,
+				   struct perf_evlist *evlist, int fd)
 {
 	int nr_sections;
 	struct perf_session *session;
@@ -442,13 +362,13 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
 	u64 sec_start;
 	int idx = 0, err;
 
-	session = container_of(self, struct perf_session, header);
+	session = container_of(header, struct perf_session, header);
 
-	if (perf_header__has_feat(self, HEADER_BUILD_ID &&
+	if (perf_header__has_feat(header, HEADER_BUILD_ID &&
 	    !perf_session__read_build_ids(session, true)))
-		perf_header__clear_feat(self, HEADER_BUILD_ID);
+		perf_header__clear_feat(header, HEADER_BUILD_ID);
 
-	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
+	nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
 	if (!nr_sections)
 		return 0;
 
@@ -458,28 +378,28 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
 
 	sec_size = sizeof(*feat_sec) * nr_sections;
 
-	sec_start = self->data_offset + self->data_size;
+	sec_start = header->data_offset + header->data_size;
 	lseek(fd, sec_start + sec_size, SEEK_SET);
 
-	if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
+	if (perf_header__has_feat(header, HEADER_TRACE_INFO)) {
 		struct perf_file_section *trace_sec;
 
 		trace_sec = &feat_sec[idx++];
 
 		/* Write trace info */
 		trace_sec->offset = lseek(fd, 0, SEEK_CUR);
-		read_tracing_data(fd, &evsel_list);
+		read_tracing_data(fd, &evlist->entries);
 		trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
 	}
 
-	if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
+	if (perf_header__has_feat(header, HEADER_BUILD_ID)) {
 		struct perf_file_section *buildid_sec;
 
 		buildid_sec = &feat_sec[idx++];
 
 		/* Write build-ids */
 		buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
-		err = dsos__write_buildid_table(self, fd);
+		err = dsos__write_buildid_table(header, fd);
 		if (err < 0) {
 			pr_debug("failed to write buildid table\n");
 			goto out_free;
@@ -518,32 +438,41 @@ int perf_header__write_pipe(int fd)
 	return 0;
 }
 
-int perf_header__write(struct perf_header *self, int fd, bool at_exit)
+int perf_session__write_header(struct perf_session *session,
+			       struct perf_evlist *evlist,
+			       int fd, bool at_exit)
 {
 	struct perf_file_header f_header;
 	struct perf_file_attr   f_attr;
-	struct perf_header_attr	*attr;
-	int i, err;
+	struct perf_header *header = &session->header;
+	struct perf_evsel *attr, *pair = NULL;
+	int err;
 
 	lseek(fd, sizeof(f_header), SEEK_SET);
 
-	for (i = 0; i < self->attrs; i++) {
-		attr = self->attr[i];
+	if (session->evlist != evlist)
+		pair = list_entry(session->evlist->entries.next, struct perf_evsel, node);
 
+	list_for_each_entry(attr, &evlist->entries, node) {
 		attr->id_offset = lseek(fd, 0, SEEK_CUR);
 		err = do_write(fd, attr->id, attr->ids * sizeof(u64));
 		if (err < 0) {
+out_err_write:
 			pr_debug("failed to write perf header\n");
 			return err;
 		}
+		if (session->evlist != evlist) {
+			err = do_write(fd, pair->id, pair->ids * sizeof(u64));
+			if (err < 0)
+				goto out_err_write;
+			attr->ids += pair->ids;
+			pair = list_entry(pair->node.next, struct perf_evsel, node);
+		}
 	}
 
+	header->attr_offset = lseek(fd, 0, SEEK_CUR);
 
-	self->attr_offset = lseek(fd, 0, SEEK_CUR);
-
-	for (i = 0; i < self->attrs; i++) {
-		attr = self->attr[i];
-
+	list_for_each_entry(attr, &evlist->entries, node) {
 		f_attr = (struct perf_file_attr){
 			.attr = attr->attr,
 			.ids  = {
@@ -558,20 +487,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
 		}
 	}
 
-	self->event_offset = lseek(fd, 0, SEEK_CUR);
-	self->event_size = event_count * sizeof(struct perf_trace_event_type);
+	header->event_offset = lseek(fd, 0, SEEK_CUR);
+	header->event_size = event_count * sizeof(struct perf_trace_event_type);
 	if (events) {
-		err = do_write(fd, events, self->event_size);
+		err = do_write(fd, events, header->event_size);
 		if (err < 0) {
 			pr_debug("failed to write perf header events\n");
 			return err;
 		}
 	}
 
-	self->data_offset = lseek(fd, 0, SEEK_CUR);
+	header->data_offset = lseek(fd, 0, SEEK_CUR);
 
 	if (at_exit) {
-		err = perf_header__adds_write(self, fd);
+		err = perf_header__adds_write(header, evlist, fd);
 		if (err < 0)
 			return err;
 	}
@@ -581,20 +510,20 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
 		.size	   = sizeof(f_header),
 		.attr_size = sizeof(f_attr),
 		.attrs = {
-			.offset = self->attr_offset,
-			.size   = self->attrs * sizeof(f_attr),
+			.offset = header->attr_offset,
+			.size   = evlist->nr_entries * sizeof(f_attr),
 		},
 		.data = {
-			.offset = self->data_offset,
-			.size	= self->data_size,
+			.offset = header->data_offset,
+			.size	= header->data_size,
 		},
 		.event_types = {
-			.offset = self->event_offset,
-			.size	= self->event_size,
+			.offset = header->event_offset,
+			.size	= header->event_size,
 		},
 	};
 
-	memcpy(&f_header.adds_features, &self->adds_features, sizeof(self->adds_features));
+	memcpy(&f_header.adds_features, &header->adds_features, sizeof(header->adds_features));
 
 	lseek(fd, 0, SEEK_SET);
 	err = do_write(fd, &f_header, sizeof(f_header));
@@ -602,26 +531,26 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
 		pr_debug("failed to write perf header\n");
 		return err;
 	}
-	lseek(fd, self->data_offset + self->data_size, SEEK_SET);
+	lseek(fd, header->data_offset + header->data_size, SEEK_SET);
 
-	self->frozen = 1;
+	header->frozen = 1;
 	return 0;
 }
 
-static int perf_header__getbuffer64(struct perf_header *self,
+static int perf_header__getbuffer64(struct perf_header *header,
 				    int fd, void *buf, size_t size)
 {
 	if (readn(fd, buf, size) <= 0)
 		return -1;
 
-	if (self->needs_swap)
+	if (header->needs_swap)
 		mem_bswap_64(buf, size);
 
 	return 0;
 }
 
-int perf_header__process_sections(struct perf_header *self, int fd,
-				  int (*process)(struct perf_file_section *self,
+int perf_header__process_sections(struct perf_header *header, int fd,
+				  int (*process)(struct perf_file_section *section,
 						 struct perf_header *ph,
 						 int feat, int fd))
 {
@@ -631,7 +560,7 @@ int perf_header__process_sections(struct perf_header *self, int fd,
 	int idx = 0;
 	int err = -1, feat = 1;
 
-	nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
+	nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
 	if (!nr_sections)
 		return 0;
 
@@ -641,17 +570,17 @@ int perf_header__process_sections(struct perf_header *self, int fd,
 
 	sec_size = sizeof(*feat_sec) * nr_sections;
 
-	lseek(fd, self->data_offset + self->data_size, SEEK_SET);
+	lseek(fd, header->data_offset + header->data_size, SEEK_SET);
 
-	if (perf_header__getbuffer64(self, fd, feat_sec, sec_size))
+	if (perf_header__getbuffer64(header, fd, feat_sec, sec_size))
 		goto out_free;
 
 	err = 0;
 	while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
-		if (perf_header__has_feat(self, feat)) {
+		if (perf_header__has_feat(header, feat)) {
 			struct perf_file_section *sec = &feat_sec[idx++];
 
-			err = process(sec, self, feat, fd);
+			err = process(sec, header, feat, fd);
 			if (err < 0)
 				break;
 		}
@@ -662,35 +591,35 @@ out_free:
 	return err;
 }
 
-int perf_file_header__read(struct perf_file_header *self,
+int perf_file_header__read(struct perf_file_header *header,
 			   struct perf_header *ph, int fd)
 {
 	lseek(fd, 0, SEEK_SET);
 
-	if (readn(fd, self, sizeof(*self)) <= 0 ||
-	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
+	if (readn(fd, header, sizeof(*header)) <= 0 ||
+	    memcmp(&header->magic, __perf_magic, sizeof(header->magic)))
 		return -1;
 
-	if (self->attr_size != sizeof(struct perf_file_attr)) {
-		u64 attr_size = bswap_64(self->attr_size);
+	if (header->attr_size != sizeof(struct perf_file_attr)) {
+		u64 attr_size = bswap_64(header->attr_size);
 
 		if (attr_size != sizeof(struct perf_file_attr))
 			return -1;
 
-		mem_bswap_64(self, offsetof(struct perf_file_header,
+		mem_bswap_64(header, offsetof(struct perf_file_header,
 					    adds_features));
 		ph->needs_swap = true;
 	}
 
-	if (self->size != sizeof(*self)) {
+	if (header->size != sizeof(*header)) {
 		/* Support the previous format */
-		if (self->size == offsetof(typeof(*self), adds_features))
-			bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
+		if (header->size == offsetof(typeof(*header), adds_features))
+			bitmap_zero(header->adds_features, HEADER_FEAT_BITS);
 		else
 			return -1;
 	}
 
-	memcpy(&ph->adds_features, &self->adds_features,
+	memcpy(&ph->adds_features, &header->adds_features,
 	       sizeof(ph->adds_features));
 	/*
 	 * FIXME: hack that assumes that if we need swap the perf.data file
@@ -704,10 +633,10 @@ int perf_file_header__read(struct perf_file_header *self,
 		perf_header__set_feat(ph, HEADER_BUILD_ID);
 	}
 
-	ph->event_offset = self->event_types.offset;
-	ph->event_size   = self->event_types.size;
-	ph->data_offset  = self->data.offset;
-	ph->data_size	 = self->data.size;
+	ph->event_offset = header->event_types.offset;
+	ph->event_size   = header->event_types.size;
+	ph->data_offset  = header->data.offset;
+	ph->data_size	 = header->data.size;
 	return 0;
 }
 
@@ -766,11 +695,10 @@ out:
 	return err;
 }
 
-static int perf_header__read_build_ids(struct perf_header *self,
-			int input, u64 offset, u64 size)
+static int perf_header__read_build_ids(struct perf_header *header,
+				       int input, u64 offset, u64 size)
 {
-	struct perf_session *session = container_of(self,
-			struct perf_session, header);
+	struct perf_session *session = container_of(header, struct perf_session, header);
 	struct build_id_event bev;
 	char filename[PATH_MAX];
 	u64 limit = offset + size;
@@ -782,7 +710,7 @@ static int perf_header__read_build_ids(struct perf_header *self,
 		if (read(input, &bev, sizeof(bev)) != sizeof(bev))
 			goto out;
 
-		if (self->needs_swap)
+		if (header->needs_swap)
 			perf_event_header__bswap(&bev.header);
 
 		len = bev.header.size - sizeof(bev);
@@ -798,13 +726,13 @@ out:
 	return err;
 }
 
-static int perf_file_section__process(struct perf_file_section *self,
+static int perf_file_section__process(struct perf_file_section *section,
 				      struct perf_header *ph,
 				      int feat, int fd)
 {
-	if (lseek(fd, self->offset, SEEK_SET) == (off_t)-1) {
+	if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
 		pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
-			  "%d, continuing...\n", self->offset, feat);
+			  "%d, continuing...\n", section->offset, feat);
 		return 0;
 	}
 
@@ -814,7 +742,7 @@ static int perf_file_section__process(struct perf_file_section *self,
 		break;
 
 	case HEADER_BUILD_ID:
-		if (perf_header__read_build_ids(ph, fd, self->offset, self->size))
+		if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
 			pr_debug("Failed to read buildids, continuing...\n");
 		break;
 	default:
@@ -824,21 +752,21 @@ static int perf_file_section__process(struct perf_file_section *self,
 	return 0;
 }
 
-static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
+static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
 				       struct perf_header *ph, int fd,
 				       bool repipe)
 {
-	if (readn(fd, self, sizeof(*self)) <= 0 ||
-	    memcmp(&self->magic, __perf_magic, sizeof(self->magic)))
+	if (readn(fd, header, sizeof(*header)) <= 0 ||
+	    memcmp(&header->magic, __perf_magic, sizeof(header->magic)))
 		return -1;
 
-	if (repipe && do_write(STDOUT_FILENO, self, sizeof(*self)) < 0)
+	if (repipe && do_write(STDOUT_FILENO, header, sizeof(*header)) < 0)
 		return -1;
 
-	if (self->size != sizeof(*self)) {
-		u64 size = bswap_64(self->size);
+	if (header->size != sizeof(*header)) {
+		u64 size = bswap_64(header->size);
 
-		if (size != sizeof(*self))
+		if (size != sizeof(*header))
 			return -1;
 
 		ph->needs_swap = true;
@@ -849,10 +777,10 @@ static int perf_file_header__read_pipe(struct perf_pipe_file_header *self,
 
 static int perf_header__read_pipe(struct perf_session *session, int fd)
 {
-	struct perf_header *self = &session->header;
+	struct perf_header *header = &session->header;
 	struct perf_pipe_file_header f_header;
 
-	if (perf_file_header__read_pipe(&f_header, self, fd,
+	if (perf_file_header__read_pipe(&f_header, header, fd,
 					session->repipe) < 0) {
 		pr_debug("incompatible file format\n");
 		return -EINVAL;
@@ -863,18 +791,22 @@ static int perf_header__read_pipe(struct perf_session *session, int fd)
 	return 0;
 }
 
-int perf_header__read(struct perf_session *session, int fd)
+int perf_session__read_header(struct perf_session *session, int fd)
 {
-	struct perf_header *self = &session->header;
+	struct perf_header *header = &session->header;
 	struct perf_file_header	f_header;
 	struct perf_file_attr	f_attr;
 	u64			f_id;
 	int nr_attrs, nr_ids, i, j;
 
+	session->evlist = perf_evlist__new(NULL, NULL);
+	if (session->evlist == NULL)
+		return -ENOMEM;
+
 	if (session->fd_pipe)
 		return perf_header__read_pipe(session, fd);
 
-	if (perf_file_header__read(&f_header, self, fd) < 0) {
+	if (perf_file_header__read(&f_header, header, fd) < 0) {
 		pr_debug("incompatible file format\n");
 		return -EINVAL;
 	}
@@ -883,33 +815,39 @@ int perf_header__read(struct perf_session *session, int fd)
 	lseek(fd, f_header.attrs.offset, SEEK_SET);
 
 	for (i = 0; i < nr_attrs; i++) {
-		struct perf_header_attr *attr;
+		struct perf_evsel *evsel;
 		off_t tmp;
 
-		if (perf_header__getbuffer64(self, fd, &f_attr, sizeof(f_attr)))
+		if (perf_header__getbuffer64(header, fd, &f_attr, sizeof(f_attr)))
 			goto out_errno;
 
 		tmp = lseek(fd, 0, SEEK_CUR);
+		evsel = perf_evsel__new(&f_attr.attr, i);
 
-		attr = perf_header_attr__new(&f_attr.attr);
-		if (attr == NULL)
-			 return -ENOMEM;
+		if (evsel == NULL)
+			goto out_delete_evlist;
+		/*
+		 * Do it before so that if perf_evsel__alloc_id fails, this
+		 * entry gets purged too at perf_evlist__delete().
+		 */
+		perf_evlist__add(session->evlist, evsel);
 
 		nr_ids = f_attr.ids.size / sizeof(u64);
+		/*
+		 * We don't have the cpu and thread maps on the header, so
+		 * for allocating the perf_sample_id table we fake 1 cpu and
+		 * hattr->ids threads.
+		 */
+		if (perf_evsel__alloc_id(evsel, 1, nr_ids))
+			goto out_delete_evlist;
+
 		lseek(fd, f_attr.ids.offset, SEEK_SET);
 
 		for (j = 0; j < nr_ids; j++) {
-			if (perf_header__getbuffer64(self, fd, &f_id, sizeof(f_id)))
+			if (perf_header__getbuffer64(header, fd, &f_id, sizeof(f_id)))
 				goto out_errno;
 
-			if (perf_header_attr__add_id(attr, f_id) < 0) {
-				perf_header_attr__delete(attr);
-				return -ENOMEM;
-			}
-		}
-		if (perf_header__add_attr(self, attr) < 0) {
-			perf_header_attr__delete(attr);
-			return -ENOMEM;
+			perf_evlist__id_add(session->evlist, evsel, 0, j, f_id);
 		}
 
 		lseek(fd, tmp, SEEK_SET);
@@ -920,93 +858,63 @@ int perf_header__read(struct perf_session *session, int fd)
 		events = malloc(f_header.event_types.size);
 		if (events == NULL)
 			return -ENOMEM;
-		if (perf_header__getbuffer64(self, fd, events,
+		if (perf_header__getbuffer64(header, fd, events,
 					     f_header.event_types.size))
 			goto out_errno;
 		event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
 	}
 
-	perf_header__process_sections(self, fd, perf_file_section__process);
+	perf_header__process_sections(header, fd, perf_file_section__process);
 
-	lseek(fd, self->data_offset, SEEK_SET);
+	lseek(fd, header->data_offset, SEEK_SET);
 
-	self->frozen = 1;
+	header->frozen = 1;
 	return 0;
 out_errno:
 	return -errno;
+
+out_delete_evlist:
+	perf_evlist__delete(session->evlist);
+	session->evlist = NULL;
+	return -ENOMEM;
 }
 
-u64 perf_header__sample_type(struct perf_header *header)
+u64 perf_evlist__sample_type(struct perf_evlist *evlist)
 {
+	struct perf_evsel *pos;
 	u64 type = 0;
-	int i;
-
-	for (i = 0; i < header->attrs; i++) {
-		struct perf_header_attr *attr = header->attr[i];
 
+	list_for_each_entry(pos, &evlist->entries, node) {
 		if (!type)
-			type = attr->attr.sample_type;
-		else if (type != attr->attr.sample_type)
+			type = pos->attr.sample_type;
+		else if (type != pos->attr.sample_type)
 			die("non matching sample_type");
 	}
 
 	return type;
 }
 
-bool perf_header__sample_id_all(const struct perf_header *header)
+bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
 {
 	bool value = false, first = true;
-	int i;
-
-	for (i = 0; i < header->attrs; i++) {
-		struct perf_header_attr *attr = header->attr[i];
+	struct perf_evsel *pos;
 
+	list_for_each_entry(pos, &evlist->entries, node) {
 		if (first) {
-			value = attr->attr.sample_id_all;
+			value = pos->attr.sample_id_all;
 			first = false;
-		} else if (value != attr->attr.sample_id_all)
+		} else if (value != pos->attr.sample_id_all)
 			die("non matching sample_id_all");
 	}
 
 	return value;
 }
 
-struct perf_event_attr *
-perf_header__find_attr(u64 id, struct perf_header *header)
-{
-	int i;
-
-	/*
-	 * We set id to -1 if the data file doesn't contain sample
-	 * ids. This can happen when the data file contains one type
-	 * of event and in that case, the header can still store the
-	 * event attribute information. Check for this and avoid
-	 * walking through the entire list of ids which may be large.
-	 */
-	if (id == -1ULL) {
-		if (header->attrs > 0)
-			return &header->attr[0]->attr;
-		return NULL;
-	}
-
-	for (i = 0; i < header->attrs; i++) {
-		struct perf_header_attr *attr = header->attr[i];
-		int j;
-
-		for (j = 0; j < attr->ids; j++) {
-			if (attr->id[j] == id)
-				return &attr->attr;
-		}
-	}
-
-	return NULL;
-}
-
-int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
-			   event__handler_t process,
-			   struct perf_session *session)
+int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
+				perf_event__handler_t process,
+				struct perf_session *session)
 {
-	event_t *ev;
+	union perf_event *ev;
 	size_t size;
 	int err;
 
@@ -1033,17 +941,15 @@ int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
 	return err;
 }
 
-int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
-			    struct perf_session *session)
+int perf_session__synthesize_attrs(struct perf_session *session,
+				   perf_event__handler_t process)
 {
-	struct perf_header_attr	*attr;
-	int i, err = 0;
-
-	for (i = 0; i < self->attrs; i++) {
-		attr = self->attr[i];
+	struct perf_evsel *attr;
+	int err = 0;
 
-		err = event__synthesize_attr(&attr->attr, attr->ids, attr->id,
-					     process, session);
+	list_for_each_entry(attr, &session->evlist->entries, node) {
+		err = perf_event__synthesize_attr(&attr->attr, attr->ids,
+						  attr->id, process, session);
 		if (err) {
 			pr_debug("failed to create perf header attribute\n");
 			return err;
@@ -1053,29 +959,39 @@ int event__synthesize_attrs(struct perf_header *self, event__handler_t process,
 	return err;
 }
 
-int event__process_attr(event_t *self, struct perf_session *session)
+int perf_event__process_attr(union perf_event *event,
+			     struct perf_session *session)
 {
-	struct perf_header_attr *attr;
 	unsigned int i, ids, n_ids;
+	struct perf_evsel *evsel;
 
-	attr = perf_header_attr__new(&self->attr.attr);
-	if (attr == NULL)
+	if (session->evlist == NULL) {
+		session->evlist = perf_evlist__new(NULL, NULL);
+		if (session->evlist == NULL)
+			return -ENOMEM;
+	}
+
+	evsel = perf_evsel__new(&event->attr.attr,
+				session->evlist->nr_entries);
+	if (evsel == NULL)
 		return -ENOMEM;
 
-	ids = self->header.size;
-	ids -= (void *)&self->attr.id - (void *)self;
+	perf_evlist__add(session->evlist, evsel);
+
+	ids = event->header.size;
+	ids -= (void *)&event->attr.id - (void *)event;
 	n_ids = ids / sizeof(u64);
+	/*
+	 * We don't have the cpu and thread maps on the header, so
+	 * for allocating the perf_sample_id table we fake 1 cpu and
+	 * hattr->ids threads.
+	 */
+	if (perf_evsel__alloc_id(evsel, 1, n_ids))
+		return -ENOMEM;
 
 	for (i = 0; i < n_ids; i++) {
-		if (perf_header_attr__add_id(attr, self->attr.id[i]) < 0) {
-			perf_header_attr__delete(attr);
-			return -ENOMEM;
-		}
-	}
-
-	if (perf_header__add_attr(&session->header, attr) < 0) {
-		perf_header_attr__delete(attr);
-		return -ENOMEM;
+		perf_evlist__id_add(session->evlist, evsel, 0, i,
+				    event->attr.id[i]);
 	}
 
 	perf_session__update_sample_type(session);
@@ -1083,11 +999,11 @@ int event__process_attr(event_t *self, struct perf_session *session)
 	return 0;
 }
 
-int event__synthesize_event_type(u64 event_id, char *name,
-				 event__handler_t process,
-				 struct perf_session *session)
+int perf_event__synthesize_event_type(u64 event_id, char *name,
+				      perf_event__handler_t process,
+				      struct perf_session *session)
 {
-	event_t ev;
+	union perf_event ev;
 	size_t size = 0;
 	int err = 0;
 
@@ -1108,8 +1024,8 @@ int event__synthesize_event_type(u64 event_id, char *name,
 	return err;
 }
 
-int event__synthesize_event_types(event__handler_t process,
-				  struct perf_session *session)
+int perf_event__synthesize_event_types(perf_event__handler_t process,
+				       struct perf_session *session)
 {
 	struct perf_trace_event_type *type;
 	int i, err = 0;
@@ -1117,8 +1033,9 @@ int event__synthesize_event_types(event__handler_t process,
 	for (i = 0; i < event_count; i++) {
 		type = &events[i];
 
-		err = event__synthesize_event_type(type->event_id, type->name,
-						   process, session);
+		err = perf_event__synthesize_event_type(type->event_id,
+							type->name, process,
+							session);
 		if (err) {
 			pr_debug("failed to create perf header event type\n");
 			return err;
@@ -1128,28 +1045,28 @@ int event__synthesize_event_types(event__handler_t process,
 	return err;
 }
 
-int event__process_event_type(event_t *self,
-			      struct perf_session *session __unused)
+int perf_event__process_event_type(union perf_event *event,
+				   struct perf_session *session __unused)
 {
-	if (perf_header__push_event(self->event_type.event_type.event_id,
-				    self->event_type.event_type.name) < 0)
+	if (perf_header__push_event(event->event_type.event_type.event_id,
+				    event->event_type.event_type.name) < 0)
 		return -ENOMEM;
 
 	return 0;
 }
 
-int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
-				   event__handler_t process,
+int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
+					 perf_event__handler_t process,
 				   struct perf_session *session __unused)
 {
-	event_t ev;
+	union perf_event ev;
 	ssize_t size = 0, aligned_size = 0, padding;
-	int err = 0;
+	int err __used = 0;
 
 	memset(&ev, 0, sizeof(ev));
 
 	ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
-	size = read_tracing_data_size(fd, pattrs);
+	size = read_tracing_data_size(fd, &evlist->entries);
 	if (size <= 0)
 		return size;
 	aligned_size = ALIGN(size, sizeof(u64));
@@ -1159,16 +1076,16 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
 
 	process(&ev, NULL, session);
 
-	err = read_tracing_data(fd, pattrs);
+	err = read_tracing_data(fd, &evlist->entries);
 	write_padded(fd, NULL, 0, padding);
 
 	return aligned_size;
 }
 
-int event__process_tracing_data(event_t *self,
-				struct perf_session *session)
+int perf_event__process_tracing_data(union perf_event *event,
+				     struct perf_session *session)
 {
-	ssize_t size_read, padding, size = self->tracing_data.size;
+	ssize_t size_read, padding, size = event->tracing_data.size;
 	off_t offset = lseek(session->fd, 0, SEEK_CUR);
 	char buf[BUFSIZ];
 
@@ -1194,12 +1111,12 @@ int event__process_tracing_data(event_t *self,
 	return size_read + padding;
 }
 
-int event__synthesize_build_id(struct dso *pos, u16 misc,
-			       event__handler_t process,
-			       struct machine *machine,
-			       struct perf_session *session)
+int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
+				    perf_event__handler_t process,
+				    struct machine *machine,
+				    struct perf_session *session)
 {
-	event_t ev;
+	union perf_event ev;
 	size_t len;
 	int err = 0;
 
@@ -1222,11 +1139,11 @@ int event__synthesize_build_id(struct dso *pos, u16 misc,
 	return err;
 }
 
-int event__process_build_id(event_t *self,
-			    struct perf_session *session)
+int perf_event__process_build_id(union perf_event *event,
+				 struct perf_session *session)
 {
-	__event_process_build_id(&self->build_id,
-				 self->build_id.filename,
+	__event_process_build_id(&event->build_id,
+				 event->build_id.filename,
 				 session);
 	return 0;
 }
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 33f16be..456661d 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -9,13 +9,6 @@
 
 #include <linux/bitmap.h>
 
-struct perf_header_attr {
-	struct perf_event_attr attr;
-	int ids, size;
-	u64 *id;
-	off_t id_offset;
-};
-
 enum {
 	HEADER_TRACE_INFO = 1,
 	HEADER_BUILD_ID,
@@ -46,14 +39,12 @@ struct perf_pipe_file_header {
 
 struct perf_header;
 
-int perf_file_header__read(struct perf_file_header *self,
+int perf_file_header__read(struct perf_file_header *header,
 			   struct perf_header *ph, int fd);
 
 struct perf_header {
 	int			frozen;
-	int			attrs, size;
 	bool			needs_swap;
-	struct perf_header_attr **attr;
 	s64			attr_offset;
 	u64			data_offset;
 	u64			data_size;
@@ -62,34 +53,25 @@ struct perf_header {
 	DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
 };
 
-int perf_header__init(struct perf_header *self);
-void perf_header__exit(struct perf_header *self);
+struct perf_evlist;
 
-int perf_header__read(struct perf_session *session, int fd);
-int perf_header__write(struct perf_header *self, int fd, bool at_exit);
+int perf_session__read_header(struct perf_session *session, int fd);
+int perf_session__write_header(struct perf_session *session,
+			       struct perf_evlist *evlist,
+			       int fd, bool at_exit);
 int perf_header__write_pipe(int fd);
 
-int perf_header__add_attr(struct perf_header *self,
-			  struct perf_header_attr *attr);
-
 int perf_header__push_event(u64 id, const char *name);
 char *perf_header__find_event(u64 id);
 
-struct perf_header_attr *perf_header_attr__new(struct perf_event_attr *attr);
-void perf_header_attr__delete(struct perf_header_attr *self);
+u64 perf_evlist__sample_type(struct perf_evlist *evlist);
+bool perf_evlist__sample_id_all(const struct perf_evlist *evlist);
+void perf_header__set_feat(struct perf_header *header, int feat);
+void perf_header__clear_feat(struct perf_header *header, int feat);
+bool perf_header__has_feat(const struct perf_header *header, int feat);
 
-int perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
-
-u64 perf_header__sample_type(struct perf_header *header);
-bool perf_header__sample_id_all(const struct perf_header *header);
-struct perf_event_attr *
-perf_header__find_attr(u64 id, struct perf_header *header);
-void perf_header__set_feat(struct perf_header *self, int feat);
-void perf_header__clear_feat(struct perf_header *self, int feat);
-bool perf_header__has_feat(const struct perf_header *self, int feat);
-
-int perf_header__process_sections(struct perf_header *self, int fd,
-				  int (*process)(struct perf_file_section *self,
+int perf_header__process_sections(struct perf_header *header, int fd,
+				  int (*process)(struct perf_file_section *section,
 						 struct perf_header *ph,
 						 int feat, int fd));
 
@@ -97,32 +79,31 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
 			  const char *name, bool is_kallsyms);
 int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir);
 
-int event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
-			   event__handler_t process,
-			   struct perf_session *session);
-int event__synthesize_attrs(struct perf_header *self,
-			    event__handler_t process,
-			    struct perf_session *session);
-int event__process_attr(event_t *self, struct perf_session *session);
-
-int event__synthesize_event_type(u64 event_id, char *name,
-				 event__handler_t process,
-				 struct perf_session *session);
-int event__synthesize_event_types(event__handler_t process,
-				  struct perf_session *session);
-int event__process_event_type(event_t *self,
-			      struct perf_session *session);
-
-int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
-				   event__handler_t process,
-				   struct perf_session *session);
-int event__process_tracing_data(event_t *self,
+int perf_event__synthesize_attr(struct perf_event_attr *attr, u16 ids, u64 *id,
+				perf_event__handler_t process,
 				struct perf_session *session);
+int perf_session__synthesize_attrs(struct perf_session *session,
+				   perf_event__handler_t process);
+int perf_event__process_attr(union perf_event *event, struct perf_session *session);
+
+int perf_event__synthesize_event_type(u64 event_id, char *name,
+				      perf_event__handler_t process,
+				      struct perf_session *session);
+int perf_event__synthesize_event_types(perf_event__handler_t process,
+				       struct perf_session *session);
+int perf_event__process_event_type(union perf_event *event,
+				   struct perf_session *session);
 
-int event__synthesize_build_id(struct dso *pos, u16 misc,
-			       event__handler_t process,
-			       struct machine *machine,
-			       struct perf_session *session);
-int event__process_build_id(event_t *self, struct perf_session *session);
-
+int perf_event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
+					perf_event__handler_t process,
+					struct perf_session *session);
+int perf_event__process_tracing_data(union perf_event *event,
+				     struct perf_session *session);
+
+int perf_event__synthesize_build_id(struct dso *pos, u16 misc,
+				    perf_event__handler_t process,
+				    struct machine *machine,
+				    struct perf_session *session);
+int perf_event__process_build_id(union perf_event *event,
+				 struct perf_session *session);
 #endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index df51560..627a02e 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -1,3 +1,4 @@
+#include "annotate.h"
 #include "util.h"
 #include "build-id.h"
 #include "hist.h"
@@ -49,6 +50,15 @@ static void hists__calc_col_len(struct hists *self, struct hist_entry *h)
 
 	if (h->ms.sym)
 		hists__new_col_len(self, HISTC_SYMBOL, h->ms.sym->namelen);
+	else {
+		const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
+
+		if (hists__col_len(self, HISTC_DSO) < unresolved_col_width &&
+		    !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
+		    !symbol_conf.dso_list)
+			hists__set_col_len(self, HISTC_DSO,
+					   unresolved_col_width);
+	}
 
 	len = thread__comm_len(h->thread);
 	if (hists__new_col_len(self, HISTC_COMM, len))
@@ -211,7 +221,9 @@ void hist_entry__free(struct hist_entry *he)
  * collapse the histogram
  */
 
-static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
+static bool hists__collapse_insert_entry(struct hists *self,
+					 struct rb_root *root,
+					 struct hist_entry *he)
 {
 	struct rb_node **p = &root->rb_node;
 	struct rb_node *parent = NULL;
@@ -226,8 +238,11 @@ static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
 
 		if (!cmp) {
 			iter->period += he->period;
-			if (symbol_conf.use_callchain)
-				callchain_merge(iter->callchain, he->callchain);
+			if (symbol_conf.use_callchain) {
+				callchain_cursor_reset(&self->callchain_cursor);
+				callchain_merge(&self->callchain_cursor, iter->callchain,
+						he->callchain);
+			}
 			hist_entry__free(he);
 			return false;
 		}
@@ -262,7 +277,7 @@ void hists__collapse_resort(struct hists *self)
 		next = rb_next(&n->rb_node);
 
 		rb_erase(&n->rb_node, &self->entries);
-		if (collapse__insert_entry(&tmp, n))
+		if (hists__collapse_insert_entry(self, &tmp, n))
 			hists__inc_nr_entries(self, n);
 	}
 
@@ -425,7 +440,7 @@ static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
 		u64 cumul;
 
 		child = rb_entry(node, struct callchain_node, rb_node);
-		cumul = cumul_hits(child);
+		cumul = callchain_cumul_hits(child);
 		remaining -= cumul;
 
 		/*
@@ -947,225 +962,14 @@ void hists__filter_by_thread(struct hists *self, const struct thread *thread)
 	}
 }
 
-static int symbol__alloc_hist(struct symbol *self)
-{
-	struct sym_priv *priv = symbol__priv(self);
-	const int size = (sizeof(*priv->hist) +
-			  (self->end - self->start) * sizeof(u64));
-
-	priv->hist = zalloc(size);
-	return priv->hist == NULL ? -1 : 0;
-}
-
-int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
-{
-	unsigned int sym_size, offset;
-	struct symbol *sym = self->ms.sym;
-	struct sym_priv *priv;
-	struct sym_hist *h;
-
-	if (!sym || !self->ms.map)
-		return 0;
-
-	priv = symbol__priv(sym);
-	if (priv->hist == NULL && symbol__alloc_hist(sym) < 0)
-		return -ENOMEM;
-
-	sym_size = sym->end - sym->start;
-	offset = ip - sym->start;
-
-	pr_debug3("%s: ip=%#" PRIx64 "\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip));
-
-	if (offset >= sym_size)
-		return 0;
-
-	h = priv->hist;
-	h->sum++;
-	h->ip[offset]++;
-
-	pr_debug3("%#" PRIx64 " %s: period++ [ip: %#" PRIx64 ", %#" PRIx64
-		  "] => %" PRIu64 "\n", self->ms.sym->start, self->ms.sym->name,
-		  ip, ip - self->ms.sym->start, h->ip[offset]);
-	return 0;
-}
-
-static struct objdump_line *objdump_line__new(s64 offset, char *line, size_t privsize)
-{
-	struct objdump_line *self = malloc(sizeof(*self) + privsize);
-
-	if (self != NULL) {
-		self->offset = offset;
-		self->line = line;
-	}
-
-	return self;
-}
-
-void objdump_line__free(struct objdump_line *self)
-{
-	free(self->line);
-	free(self);
-}
-
-static void objdump__add_line(struct list_head *head, struct objdump_line *line)
-{
-	list_add_tail(&line->node, head);
-}
-
-struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
-					       struct objdump_line *pos)
-{
-	list_for_each_entry_continue(pos, head, node)
-		if (pos->offset >= 0)
-			return pos;
-
-	return NULL;
-}
-
-static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
-					  struct list_head *head, size_t privsize)
+int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
 {
-	struct symbol *sym = self->ms.sym;
-	struct objdump_line *objdump_line;
-	char *line = NULL, *tmp, *tmp2, *c;
-	size_t line_len;
-	s64 line_ip, offset = -1;
-
-	if (getline(&line, &line_len, file) < 0)
-		return -1;
-
-	if (!line)
-		return -1;
-
-	while (line_len != 0 && isspace(line[line_len - 1]))
-		line[--line_len] = '\0';
-
-	c = strchr(line, '\n');
-	if (c)
-		*c = 0;
-
-	line_ip = -1;
-
-	/*
-	 * Strip leading spaces:
-	 */
-	tmp = line;
-	while (*tmp) {
-		if (*tmp != ' ')
-			break;
-		tmp++;
-	}
-
-	if (*tmp) {
-		/*
-		 * Parse hexa addresses followed by ':'
-		 */
-		line_ip = strtoull(tmp, &tmp2, 16);
-		if (*tmp2 != ':' || tmp == tmp2 || tmp2[1] == '\0')
-			line_ip = -1;
-	}
-
-	if (line_ip != -1) {
-		u64 start = map__rip_2objdump(self->ms.map, sym->start),
-		    end = map__rip_2objdump(self->ms.map, sym->end);
-
-		offset = line_ip - start;
-		if (offset < 0 || (u64)line_ip > end)
-			offset = -1;
-	}
-
-	objdump_line = objdump_line__new(offset, line, privsize);
-	if (objdump_line == NULL) {
-		free(line);
-		return -1;
-	}
-	objdump__add_line(head, objdump_line);
-
-	return 0;
+	return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
 }
 
-int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
-			 size_t privsize)
+int hist_entry__annotate(struct hist_entry *he, size_t privsize)
 {
-	struct symbol *sym = self->ms.sym;
-	struct map *map = self->ms.map;
-	struct dso *dso = map->dso;
-	char *filename = dso__build_id_filename(dso, NULL, 0);
-	bool free_filename = true;
-	char command[PATH_MAX * 2];
-	FILE *file;
-	int err = 0;
-	u64 len;
-	char symfs_filename[PATH_MAX];
-
-	if (filename) {
-		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
-			 symbol_conf.symfs, filename);
-	}
-
-	if (filename == NULL) {
-		if (dso->has_build_id) {
-			pr_err("Can't annotate %s: not enough memory\n",
-			       sym->name);
-			return -ENOMEM;
-		}
-		goto fallback;
-	} else if (readlink(symfs_filename, command, sizeof(command)) < 0 ||
-		   strstr(command, "[kernel.kallsyms]") ||
-		   access(symfs_filename, R_OK)) {
-		free(filename);
-fallback:
-		/*
-		 * If we don't have build-ids or the build-id file isn't in the
-		 * cache, or is just a kallsyms file, well, lets hope that this
-		 * DSO is the same as when 'perf record' ran.
-		 */
-		filename = dso->long_name;
-		snprintf(symfs_filename, sizeof(symfs_filename), "%s%s",
-			 symbol_conf.symfs, filename);
-		free_filename = false;
-	}
-
-	if (dso->origin == DSO__ORIG_KERNEL) {
-		if (dso->annotate_warned)
-			goto out_free_filename;
-		err = -ENOENT;
-		dso->annotate_warned = 1;
-		pr_err("Can't annotate %s: No vmlinux file was found in the "
-		       "path\n", sym->name);
-		goto out_free_filename;
-	}
-
-	pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
-		 filename, sym->name, map->unmap_ip(map, sym->start),
-		 map->unmap_ip(map, sym->end));
-
-	len = sym->end - sym->start;
-
-	pr_debug("annotating [%p] %30s : [%p] %30s\n",
-		 dso, dso->long_name, sym, sym->name);
-
-	snprintf(command, sizeof(command),
-		 "objdump --start-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand",
-		 map__rip_2objdump(map, sym->start),
-		 map__rip_2objdump(map, sym->end),
-		 symfs_filename, filename);
-
-	pr_debug("Executing: %s\n", command);
-
-	file = popen(command, "r");
-	if (!file)
-		goto out_free_filename;
-
-	while (!feof(file))
-		if (hist_entry__parse_objdump_line(self, file, head, privsize) < 0)
-			break;
-
-	pclose(file);
-out_free_filename:
-	if (free_filename)
-		free(filename);
-	return err;
+	return symbol__annotate(he->ms.sym, he->ms.map, privsize);
 }
 
 void hists__inc_nr_events(struct hists *self, u32 type)
@@ -1180,8 +984,12 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
 	size_t ret = 0;
 
 	for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
-		const char *name = event__get_event_name(i);
+		const char *name;
+
+		if (self->stats.nr_events[i] == 0)
+			continue;
 
+		name = perf_event__name(i);
 		if (!strcmp(name, "UNKNOWN"))
 			continue;
 
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ee78985..cb6858a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -9,33 +9,6 @@ extern struct callchain_param callchain_param;
 struct hist_entry;
 struct addr_location;
 struct symbol;
-struct rb_root;
-
-struct objdump_line {
-	struct list_head node;
-	s64		 offset;
-	char		 *line;
-};
-
-void objdump_line__free(struct objdump_line *self);
-struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
-					       struct objdump_line *pos);
-
-struct sym_hist {
-	u64		sum;
-	u64		ip[0];
-};
-
-struct sym_ext {
-	struct rb_node	node;
-	double		percent;
-	char		*path;
-};
-
-struct sym_priv {
-	struct sym_hist	*hist;
-	struct sym_ext	*ext;
-};
 
 /*
  * The kernel collects the number of events it couldn't send in a stretch and
@@ -69,14 +42,13 @@ enum hist_column {
 };
 
 struct hists {
-	struct rb_node		rb_node;
 	struct rb_root		entries;
 	u64			nr_entries;
 	struct events_stats	stats;
-	u64			config;
 	u64			event_stream;
-	u32			type;
 	u16			col_len[HISTC_NR_COLS];
+	/* Best would be to reuse the session callchain cursor */
+	struct callchain_cursor	callchain_cursor;
 };
 
 struct hist_entry *__hists__add_entry(struct hists *self,
@@ -102,9 +74,8 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
 size_t hists__fprintf(struct hists *self, struct hists *pair,
 		      bool show_displacement, FILE *fp);
 
-int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip);
-int hist_entry__annotate(struct hist_entry *self, struct list_head *head,
-			 size_t privsize);
+int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
+int hist_entry__annotate(struct hist_entry *self, size_t privsize);
 
 void hists__filter_by_dso(struct hists *self, const struct dso *dso);
 void hists__filter_by_thread(struct hists *self, const struct thread *thread);
@@ -113,21 +84,18 @@ u16 hists__col_len(struct hists *self, enum hist_column col);
 void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
 bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
 
-#ifdef NO_NEWT_SUPPORT
-static inline int hists__browse(struct hists *self __used,
-				const char *helpline __used,
-				const char *ev_name __used)
-{
-	return 0;
-}
+struct perf_evlist;
 
-static inline int hists__tui_browse_tree(struct rb_root *self __used,
-					 const char *help __used)
+#ifdef NO_NEWT_SUPPORT
+static inline
+int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __used,
+				  const char *help __used)
 {
 	return 0;
 }
 
-static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
+static inline int hist_entry__tui_annotate(struct hist_entry *self __used,
+					   int evidx __used)
 {
 	return 0;
 }
@@ -135,14 +103,12 @@ static inline int hist_entry__tui_annotate(struct hist_entry *self __used)
 #define KEY_RIGHT -2
 #else
 #include <newt.h>
-int hists__browse(struct hists *self, const char *helpline,
-		  const char *ev_name);
-int hist_entry__tui_annotate(struct hist_entry *self);
+int hist_entry__tui_annotate(struct hist_entry *self, int evidx);
 
 #define KEY_LEFT NEWT_KEY_LEFT
 #define KEY_RIGHT NEWT_KEY_RIGHT
 
-int hists__tui_browse_tree(struct rb_root *self, const char *help);
+int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help);
 #endif
 
 unsigned int hists__sort_list_width(struct hists *self);
diff --git a/tools/perf/util/include/linux/list.h b/tools/perf/util/include/linux/list.h
index f5ca26e..356c7e4 100644
--- a/tools/perf/util/include/linux/list.h
+++ b/tools/perf/util/include/linux/list.h
@@ -1,3 +1,4 @@
+#include <linux/kernel.h>
 #include "../../../../include/linux/list.h"
 
 #ifndef PERF_LIST_H
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 135f69b..952b4ae 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1,6 +1,7 @@
 #include "../../../include/linux/hw_breakpoint.h"
 #include "util.h"
 #include "../perf.h"
+#include "evlist.h"
 #include "evsel.h"
 #include "parse-options.h"
 #include "parse-events.h"
@@ -11,10 +12,6 @@
 #include "header.h"
 #include "debugfs.h"
 
-int				nr_counters;
-
-LIST_HEAD(evsel_list);
-
 struct event_symbol {
 	u8		type;
 	u64		config;
@@ -266,11 +263,36 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
 	return name;
 }
 
+const char *event_type(int type)
+{
+	switch (type) {
+	case PERF_TYPE_HARDWARE:
+		return "hardware";
+
+	case PERF_TYPE_SOFTWARE:
+		return "software";
+
+	case PERF_TYPE_TRACEPOINT:
+		return "tracepoint";
+
+	case PERF_TYPE_HW_CACHE:
+		return "hardware-cache";
+
+	default:
+		break;
+	}
+
+	return "unknown";
+}
+
 const char *event_name(struct perf_evsel *evsel)
 {
 	u64 config = evsel->attr.config;
 	int type = evsel->attr.type;
 
+	if (evsel->name)
+		return evsel->name;
+
 	return __event_name(type, config);
 }
 
@@ -449,8 +471,8 @@ parse_single_tracepoint_event(char *sys_name,
 /* sys + ':' + event + ':' + flags*/
 #define MAX_EVOPT_LEN	(MAX_EVENT_LENGTH * 2 + 2 + 128)
 static enum event_result
-parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
-				char *flags)
+parse_multiple_tracepoint_event(const struct option *opt, char *sys_name,
+				const char *evt_exp, char *flags)
 {
 	char evt_path[MAXPATHLEN];
 	struct dirent *evt_ent;
@@ -483,15 +505,16 @@ parse_multiple_tracepoint_event(char *sys_name, const char *evt_exp,
 		if (len < 0)
 			return EVT_FAILED;
 
-		if (parse_events(NULL, event_opt, 0))
+		if (parse_events(opt, event_opt, 0))
 			return EVT_FAILED;
 	}
 
 	return EVT_HANDLED_ALL;
 }
 
-static enum event_result parse_tracepoint_event(const char **strp,
-				    struct perf_event_attr *attr)
+static enum event_result
+parse_tracepoint_event(const struct option *opt, const char **strp,
+		       struct perf_event_attr *attr)
 {
 	const char *evt_name;
 	char *flags = NULL, *comma_loc;
@@ -530,7 +553,7 @@ static enum event_result parse_tracepoint_event(const char **strp,
 		return EVT_FAILED;
 	if (strpbrk(evt_name, "*?")) {
 		*strp += strlen(sys_name) + evt_length + 1; /* 1 == the ':' */
-		return parse_multiple_tracepoint_event(sys_name, evt_name,
+		return parse_multiple_tracepoint_event(opt, sys_name, evt_name,
 						       flags);
 	} else {
 		return parse_single_tracepoint_event(sys_name, evt_name,
@@ -740,11 +763,12 @@ parse_event_modifier(const char **strp, struct perf_event_attr *attr)
  * Symbolic names are (almost) exactly matched.
  */
 static enum event_result
-parse_event_symbols(const char **str, struct perf_event_attr *attr)
+parse_event_symbols(const struct option *opt, const char **str,
+		    struct perf_event_attr *attr)
 {
 	enum event_result ret;
 
-	ret = parse_tracepoint_event(str, attr);
+	ret = parse_tracepoint_event(opt, str, attr);
 	if (ret != EVT_FAILED)
 		goto modifier;
 
@@ -778,14 +802,17 @@ modifier:
 	return ret;
 }
 
-int parse_events(const struct option *opt __used, const char *str, int unset __used)
+int parse_events(const struct option *opt, const char *str, int unset __used)
 {
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 	struct perf_event_attr attr;
 	enum event_result ret;
+	const char *ostr;
 
 	for (;;) {
+		ostr = str;
 		memset(&attr, 0, sizeof(attr));
-		ret = parse_event_symbols(&str, &attr);
+		ret = parse_event_symbols(opt, &str, &attr);
 		if (ret == EVT_FAILED)
 			return -1;
 
@@ -794,12 +821,15 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
 
 		if (ret != EVT_HANDLED_ALL) {
 			struct perf_evsel *evsel;
-			evsel = perf_evsel__new(&attr,
-						nr_counters);
+			evsel = perf_evsel__new(&attr, evlist->nr_entries);
 			if (evsel == NULL)
 				return -1;
-			list_add_tail(&evsel->node, &evsel_list);
-			++nr_counters;
+			perf_evlist__add(evlist, evsel);
+
+			evsel->name = calloc(str - ostr + 1, 1);
+			if (!evsel->name)
+				return -1;
+			strncpy(evsel->name, ostr, str - ostr);
 		}
 
 		if (*str == 0)
@@ -813,13 +843,14 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
 	return 0;
 }
 
-int parse_filter(const struct option *opt __used, const char *str,
+int parse_filter(const struct option *opt, const char *str,
 		 int unset __used)
 {
+	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 	struct perf_evsel *last = NULL;
 
-	if (!list_empty(&evsel_list))
-		last = list_entry(evsel_list.prev, struct perf_evsel, node);
+	if (evlist->nr_entries > 0)
+		last = list_entry(evlist->entries.prev, struct perf_evsel, node);
 
 	if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
 		fprintf(stderr,
@@ -849,7 +880,7 @@ static const char * const event_type_descriptors[] = {
  * Print the events from <debugfs_mount_point>/tracing/events
  */
 
-static void print_tracepoint_events(void)
+void print_tracepoint_events(const char *subsys_glob, const char *event_glob)
 {
 	DIR *sys_dir, *evt_dir;
 	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
@@ -864,6 +895,9 @@ static void print_tracepoint_events(void)
 		return;
 
 	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
+		if (subsys_glob != NULL && 
+		    !strglobmatch(sys_dirent.d_name, subsys_glob))
+			continue;
 
 		snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path,
 			 sys_dirent.d_name);
@@ -872,6 +906,10 @@ static void print_tracepoint_events(void)
 			continue;
 
 		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
+			if (event_glob != NULL && 
+			    !strglobmatch(evt_dirent.d_name, event_glob))
+				continue;
+
 			snprintf(evt_path, MAXPATHLEN, "%s:%s",
 				 sys_dirent.d_name, evt_dirent.d_name);
 			printf("  %-42s [%s]\n", evt_path,
@@ -923,13 +961,61 @@ int is_valid_tracepoint(const char *event_string)
 	return 0;
 }
 
+void print_events_type(u8 type)
+{
+	struct event_symbol *syms = event_symbols;
+	unsigned int i;
+	char name[64];
+
+	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
+		if (type != syms->type)
+			continue;
+
+		if (strlen(syms->alias))
+			snprintf(name, sizeof(name),  "%s OR %s",
+				 syms->symbol, syms->alias);
+		else
+			snprintf(name, sizeof(name), "%s", syms->symbol);
+
+		printf("  %-42s [%s]\n", name,
+			event_type_descriptors[type]);
+	}
+}
+
+int print_hwcache_events(const char *event_glob)
+{
+	unsigned int type, op, i, printed = 0;
+
+	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
+		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
+			/* skip invalid cache type */
+			if (!is_cache_op_valid(type, op))
+				continue;
+
+			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
+				char *name = event_cache_name(type, op, i);
+
+				if (event_glob != NULL && 
+				    !strglobmatch(name, event_glob))
+					continue;
+
+				printf("  %-42s [%s]\n", name,
+					event_type_descriptors[PERF_TYPE_HW_CACHE]);
+				++printed;
+			}
+		}
+	}
+
+	return printed;
+}
+
 /*
  * Print the help text for the event symbols:
  */
-void print_events(void)
+void print_events(const char *event_glob)
 {
 	struct event_symbol *syms = event_symbols;
-	unsigned int i, type, op, prev_type = -1;
+	unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
 	char name[40];
 
 	printf("\n");
@@ -938,8 +1024,16 @@ void print_events(void)
 	for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
 		type = syms->type;
 
-		if (type != prev_type)
+		if (type != prev_type && printed) {
 			printf("\n");
+			printed = 0;
+			ntypes_printed++;
+		}
+
+		if (event_glob != NULL && 
+		    !(strglobmatch(syms->symbol, event_glob) ||
+		      (syms->alias && strglobmatch(syms->alias, event_glob))))
+			continue;
 
 		if (strlen(syms->alias))
 			sprintf(name, "%s OR %s", syms->symbol, syms->alias);
@@ -949,22 +1043,17 @@ void print_events(void)
 			event_type_descriptors[type]);
 
 		prev_type = type;
+		++printed;
 	}
 
-	printf("\n");
-	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
-		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
-			/* skip invalid cache type */
-			if (!is_cache_op_valid(type, op))
-				continue;
-
-			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
-				printf("  %-42s [%s]\n",
-					event_cache_name(type, op, i),
-					event_type_descriptors[PERF_TYPE_HW_CACHE]);
-			}
-		}
+	if (ntypes_printed) {
+		printed = 0;
+		printf("\n");
 	}
+	print_hwcache_events(event_glob);
+
+	if (event_glob != NULL)
+		return;
 
 	printf("\n");
 	printf("  %-42s [%s]\n",
@@ -977,37 +1066,7 @@ void print_events(void)
 			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
 	printf("\n");
 
-	print_tracepoint_events();
+	print_tracepoint_events(NULL, NULL);
 
 	exit(129);
 }
-
-int perf_evsel_list__create_default(void)
-{
-	struct perf_evsel *evsel;
-	struct perf_event_attr attr;
-
-	memset(&attr, 0, sizeof(attr));
-	attr.type = PERF_TYPE_HARDWARE;
-	attr.config = PERF_COUNT_HW_CPU_CYCLES;
-
-	evsel = perf_evsel__new(&attr, 0);
-
-	if (evsel == NULL)
-		return -ENOMEM;
-
-	list_add(&evsel->node, &evsel_list);
-	++nr_counters;
-	return 0;
-}
-
-void perf_evsel_list__delete(void)
-{
-	struct perf_evsel *pos, *n;
-
-	list_for_each_entry_safe(pos, n, &evsel_list, node) {
-		list_del_init(&pos->node);
-		perf_evsel__delete(pos);
-	}
-	nr_counters = 0;
-}
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 458e3ec..746d3fc 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -9,11 +9,6 @@
 struct list_head;
 struct perf_evsel;
 
-extern struct list_head evsel_list;
-
-int perf_evsel_list__create_default(void);
-void perf_evsel_list__delete(void);
-
 struct option;
 
 struct tracepoint_path {
@@ -25,8 +20,7 @@ struct tracepoint_path {
 extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
 extern bool have_tracepoints(struct list_head *evlist);
 
-extern int			nr_counters;
-
+const char *event_type(int type);
 const char *event_name(struct perf_evsel *event);
 extern const char *__event_name(int type, u64 config);
 
@@ -35,7 +29,10 @@ extern int parse_filter(const struct option *opt, const char *str, int unset);
 
 #define EVENTS_HELP_MAX (128*1024)
 
-extern void print_events(void);
+void print_events(const char *event_glob);
+void print_events_type(u8 type);
+void print_tracepoint_events(const char *subsys_glob, const char *event_glob);
+int print_hwcache_events(const char *event_glob);
 extern int is_valid_tracepoint(const char *event_string);
 
 extern char debugfs_path[];
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6e29d9c..5ddee66 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -31,6 +31,7 @@
 #include <string.h>
 #include <stdarg.h>
 #include <limits.h>
+#include <elf.h>
 
 #undef _GNU_SOURCE
 #include "util.h"
@@ -111,7 +112,25 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
 						     NULL);
 }
 
-const char *kernel_get_module_path(const char *module)
+static struct map *kernel_get_module_map(const char *module)
+{
+	struct rb_node *nd;
+	struct map_groups *grp = &machine.kmaps;
+
+	if (!module)
+		module = "kernel";
+
+	for (nd = rb_first(&grp->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
+		struct map *pos = rb_entry(nd, struct map, rb_node);
+		if (strncmp(pos->dso->short_name + 1, module,
+			    pos->dso->short_name_len - 2) == 0) {
+			return pos;
+		}
+	}
+	return NULL;
+}
+
+static struct dso *kernel_get_module_dso(const char *module)
 {
 	struct dso *dso;
 	struct map *map;
@@ -141,7 +160,13 @@ const char *kernel_get_module_path(const char *module)
 		}
 	}
 found:
-	return dso->long_name;
+	return dso;
+}
+
+const char *kernel_get_module_path(const char *module)
+{
+	struct dso *dso = kernel_get_module_dso(module);
+	return (dso) ? dso->long_name : NULL;
 }
 
 #ifdef DWARF_SUPPORT
@@ -384,7 +409,7 @@ int show_line_range(struct line_range *lr, const char *module)
 	setup_pager();
 
 	if (lr->function)
-		fprintf(stdout, "<%s:%d>\n", lr->function,
+		fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
 			lr->start - lr->offset);
 	else
 		fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
@@ -426,12 +451,14 @@ end:
 }
 
 static int show_available_vars_at(int fd, struct perf_probe_event *pev,
-				  int max_vls, bool externs)
+				  int max_vls, struct strfilter *_filter,
+				  bool externs)
 {
 	char *buf;
-	int ret, i;
+	int ret, i, nvars;
 	struct str_node *node;
 	struct variable_list *vls = NULL, *vl;
+	const char *var;
 
 	buf = synthesize_perf_probe_point(&pev->point);
 	if (!buf)
@@ -439,36 +466,45 @@ static int show_available_vars_at(int fd, struct perf_probe_event *pev,
 	pr_debug("Searching variables at %s\n", buf);
 
 	ret = find_available_vars_at(fd, pev, &vls, max_vls, externs);
-	if (ret > 0) {
-		/* Some variables were found */
-		fprintf(stdout, "Available variables at %s\n", buf);
-		for (i = 0; i < ret; i++) {
-			vl = &vls[i];
-			/*
-			 * A probe point might be converted to
-			 * several trace points.
-			 */
-			fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
-				vl->point.offset);
-			free(vl->point.symbol);
-			if (vl->vars) {
-				strlist__for_each(node, vl->vars)
+	if (ret <= 0) {
+		pr_err("Failed to find variables at %s (%d)\n", buf, ret);
+		goto end;
+	}
+	/* Some variables are found */
+	fprintf(stdout, "Available variables at %s\n", buf);
+	for (i = 0; i < ret; i++) {
+		vl = &vls[i];
+		/*
+		 * A probe point might be converted to
+		 * several trace points.
+		 */
+		fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
+			vl->point.offset);
+		free(vl->point.symbol);
+		nvars = 0;
+		if (vl->vars) {
+			strlist__for_each(node, vl->vars) {
+				var = strchr(node->s, '\t') + 1;
+				if (strfilter__compare(_filter, var)) {
 					fprintf(stdout, "\t\t%s\n", node->s);
-				strlist__delete(vl->vars);
-			} else
-				fprintf(stdout, "(No variables)\n");
+					nvars++;
+				}
+			}
+			strlist__delete(vl->vars);
 		}
-		free(vls);
-	} else
-		pr_err("Failed to find variables at %s (%d)\n", buf, ret);
-
+		if (nvars == 0)
+			fprintf(stdout, "\t\t(No matched variables)\n");
+	}
+	free(vls);
+end:
 	free(buf);
 	return ret;
 }
 
 /* Show available variables on given probe point */
 int show_available_vars(struct perf_probe_event *pevs, int npevs,
-			int max_vls, const char *module, bool externs)
+			int max_vls, const char *module,
+			struct strfilter *_filter, bool externs)
 {
 	int i, fd, ret = 0;
 
@@ -485,7 +521,8 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
 	setup_pager();
 
 	for (i = 0; i < npevs && ret >= 0; i++)
-		ret = show_available_vars_at(fd, &pevs[i], max_vls, externs);
+		ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
+					     externs);
 
 	close(fd);
 	return ret;
@@ -531,7 +568,9 @@ int show_line_range(struct line_range *lr __unused, const char *module __unused)
 
 int show_available_vars(struct perf_probe_event *pevs __unused,
 			int npevs __unused, int max_vls __unused,
-			const char *module __unused, bool externs __unused)
+			const char *module __unused,
+			struct strfilter *filter __unused,
+			bool externs __unused)
 {
 	pr_warning("Debuginfo-analysis is not supported.\n");
 	return -ENOSYS;
@@ -556,11 +595,11 @@ static int parse_line_num(char **ptr, int *val, const char *what)
  * The line range syntax is described by:
  *
  *         SRC[:SLN[+NUM|-ELN]]
- *         FNC[:SLN[+NUM|-ELN]]
+ *         FNC[@SRC][:SLN[+NUM|-ELN]]
  */
 int parse_line_range_desc(const char *arg, struct line_range *lr)
 {
-	char *range, *name = strdup(arg);
+	char *range, *file, *name = strdup(arg);
 	int err;
 
 	if (!name)
@@ -610,7 +649,16 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
 		}
 	}
 
-	if (strchr(name, '.'))
+	file = strchr(name, '@');
+	if (file) {
+		*file = '\0';
+		lr->file = strdup(++file);
+		if (lr->file == NULL) {
+			err = -ENOMEM;
+			goto err;
+		}
+		lr->function = name;
+	} else if (strchr(name, '.'))
 		lr->file = name;
 	else
 		lr->function = name;
@@ -1784,9 +1832,12 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
 	}
 
 	/* Loop 2: add all events */
-	for (i = 0; i < npevs && ret >= 0; i++)
+	for (i = 0; i < npevs; i++) {
 		ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
 						pkgs[i].ntevs, force_add);
+		if (ret < 0)
+			break;
+	}
 end:
 	/* Loop 3: cleanup and free trace events  */
 	for (i = 0; i < npevs; i++) {
@@ -1912,4 +1963,46 @@ int del_perf_probe_events(struct strlist *dellist)
 
 	return ret;
 }
+/* TODO: don't use a global variable for filter ... */
+static struct strfilter *available_func_filter;
+
+/*
+ * If a symbol corresponds to a function with global binding and
+ * matches filter return 0. For all others return 1.
+ */
+static int filter_available_functions(struct map *map __unused,
+				      struct symbol *sym)
+{
+	if (sym->binding == STB_GLOBAL &&
+	    strfilter__compare(available_func_filter, sym->name))
+		return 0;
+	return 1;
+}
+
+int show_available_funcs(const char *module, struct strfilter *_filter)
+{
+	struct map *map;
+	int ret;
+
+	setup_pager();
+
+	ret = init_vmlinux();
+	if (ret < 0)
+		return ret;
 
+	map = kernel_get_module_map(module);
+	if (!map) {
+		pr_err("Failed to find %s map.\n", (module) ? : "kernel");
+		return -EINVAL;
+	}
+	available_func_filter = _filter;
+	if (map__load(map, filter_available_functions)) {
+		pr_err("Failed to load map.\n");
+		return -EINVAL;
+	}
+	if (!dso__sorted_by_name(map->dso, map->type))
+		dso__sort_by_name(map->dso, map->type);
+
+	dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
+	return 0;
+}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5accbed..3434fc9 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 #include "strlist.h"
+#include "strfilter.h"
 
 extern bool probe_event_dry_run;
 
@@ -126,7 +127,8 @@ extern int show_perf_probe_events(void);
 extern int show_line_range(struct line_range *lr, const char *module);
 extern int show_available_vars(struct perf_probe_event *pevs, int npevs,
 			       int max_probe_points, const char *module,
-			       bool externs);
+			       struct strfilter *filter, bool externs);
+extern int show_available_funcs(const char *module, struct strfilter *filter);
 
 
 /* Maximum index number of event-name postfix */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ab83b6a..194f9e2 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -33,6 +33,7 @@
 #include <ctype.h>
 #include <dwarf-regs.h>
 
+#include <linux/bitops.h>
 #include "event.h"
 #include "debug.h"
 #include "util.h"
@@ -280,6 +281,19 @@ static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
 	return name ? (strcmp(tname, name) == 0) : false;
 }
 
+/* Get callsite line number of inline-function instance */
+static int die_get_call_lineno(Dwarf_Die *in_die)
+{
+	Dwarf_Attribute attr;
+	Dwarf_Word ret;
+
+	if (!dwarf_attr(in_die, DW_AT_call_line, &attr))
+		return -ENOENT;
+
+	dwarf_formudata(&attr, &ret);
+	return (int)ret;
+}
+
 /* Get type die */
 static Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
 {
@@ -320,13 +334,23 @@ static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
 	return vr_die;
 }
 
-static bool die_is_signed_type(Dwarf_Die *tp_die)
+static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name,
+			      Dwarf_Word *result)
 {
 	Dwarf_Attribute attr;
+
+	if (dwarf_attr(tp_die, attr_name, &attr) == NULL ||
+	    dwarf_formudata(&attr, result) != 0)
+		return -ENOENT;
+
+	return 0;
+}
+
+static bool die_is_signed_type(Dwarf_Die *tp_die)
+{
 	Dwarf_Word ret;
 
-	if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL ||
-	    dwarf_formudata(&attr, &ret) != 0)
+	if (die_get_attr_udata(tp_die, DW_AT_encoding, &ret))
 		return false;
 
 	return (ret == DW_ATE_signed_char || ret == DW_ATE_signed ||
@@ -335,11 +359,29 @@ static bool die_is_signed_type(Dwarf_Die *tp_die)
 
 static int die_get_byte_size(Dwarf_Die *tp_die)
 {
-	Dwarf_Attribute attr;
 	Dwarf_Word ret;
 
-	if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL ||
-	    dwarf_formudata(&attr, &ret) != 0)
+	if (die_get_attr_udata(tp_die, DW_AT_byte_size, &ret))
+		return 0;
+
+	return (int)ret;
+}
+
+static int die_get_bit_size(Dwarf_Die *tp_die)
+{
+	Dwarf_Word ret;
+
+	if (die_get_attr_udata(tp_die, DW_AT_bit_size, &ret))
+		return 0;
+
+	return (int)ret;
+}
+
+static int die_get_bit_offset(Dwarf_Die *tp_die)
+{
+	Dwarf_Word ret;
+
+	if (die_get_attr_udata(tp_die, DW_AT_bit_offset, &ret))
 		return 0;
 
 	return (int)ret;
@@ -458,6 +500,151 @@ static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
 	return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem);
 }
 
+/* Walker on lines (Note: line number will not be sorted) */
+typedef int (* line_walk_handler_t) (const char *fname, int lineno,
+				     Dwarf_Addr addr, void *data);
+
+struct __line_walk_param {
+	const char *fname;
+	line_walk_handler_t handler;
+	void *data;
+	int retval;
+};
+
+static int __die_walk_funclines_cb(Dwarf_Die *in_die, void *data)
+{
+	struct __line_walk_param *lw = data;
+	Dwarf_Addr addr;
+	int lineno;
+
+	if (dwarf_tag(in_die) == DW_TAG_inlined_subroutine) {
+		lineno = die_get_call_lineno(in_die);
+		if (lineno > 0 && dwarf_entrypc(in_die, &addr) == 0) {
+			lw->retval = lw->handler(lw->fname, lineno, addr,
+						 lw->data);
+			if (lw->retval != 0)
+				return DIE_FIND_CB_FOUND;
+		}
+	}
+	return DIE_FIND_CB_SIBLING;
+}
+
+/* Walk on lines of blocks included in given DIE */
+static int __die_walk_funclines(Dwarf_Die *sp_die,
+				line_walk_handler_t handler, void *data)
+{
+	struct __line_walk_param lw = {
+		.handler = handler,
+		.data = data,
+		.retval = 0,
+	};
+	Dwarf_Die die_mem;
+	Dwarf_Addr addr;
+	int lineno;
+
+	/* Handle function declaration line */
+	lw.fname = dwarf_decl_file(sp_die);
+	if (lw.fname && dwarf_decl_line(sp_die, &lineno) == 0 &&
+	    dwarf_entrypc(sp_die, &addr) == 0) {
+		lw.retval = handler(lw.fname, lineno, addr, data);
+		if (lw.retval != 0)
+			goto done;
+	}
+	die_find_child(sp_die, __die_walk_funclines_cb, &lw, &die_mem);
+done:
+	return lw.retval;
+}
+
+static int __die_walk_culines_cb(Dwarf_Die *sp_die, void *data)
+{
+	struct __line_walk_param *lw = data;
+
+	lw->retval = __die_walk_funclines(sp_die, lw->handler, lw->data);
+	if (lw->retval != 0)
+		return DWARF_CB_ABORT;
+
+	return DWARF_CB_OK;
+}
+
+/*
+ * Walk on lines inside given PDIE. If the PDIE is subprogram, walk only on
+ * the lines inside the subprogram, otherwise PDIE must be a CU DIE.
+ */
+static int die_walk_lines(Dwarf_Die *pdie, line_walk_handler_t handler,
+			  void *data)
+{
+	Dwarf_Lines *lines;
+	Dwarf_Line *line;
+	Dwarf_Addr addr;
+	const char *fname;
+	int lineno, ret = 0;
+	Dwarf_Die die_mem, *cu_die;
+	size_t nlines, i;
+
+	/* Get the CU die */
+	if (dwarf_tag(pdie) == DW_TAG_subprogram)
+		cu_die = dwarf_diecu(pdie, &die_mem, NULL, NULL);
+	else
+		cu_die = pdie;
+	if (!cu_die) {
+		pr_debug2("Failed to get CU from subprogram\n");
+		return -EINVAL;
+	}
+
+	/* Get lines list in the CU */
+	if (dwarf_getsrclines(cu_die, &lines, &nlines) != 0) {
+		pr_debug2("Failed to get source lines on this CU.\n");
+		return -ENOENT;
+	}
+	pr_debug2("Get %zd lines from this CU\n", nlines);
+
+	/* Walk on the lines on lines list */
+	for (i = 0; i < nlines; i++) {
+		line = dwarf_onesrcline(lines, i);
+		if (line == NULL ||
+		    dwarf_lineno(line, &lineno) != 0 ||
+		    dwarf_lineaddr(line, &addr) != 0) {
+			pr_debug2("Failed to get line info. "
+				  "Possible error in debuginfo.\n");
+			continue;
+		}
+		/* Filter lines based on address */
+		if (pdie != cu_die)
+			/*
+			 * Address filtering
+			 * The line is included in given function, and
+			 * no inline block includes it.
+			 */
+			if (!dwarf_haspc(pdie, addr) ||
+			    die_find_inlinefunc(pdie, addr, &die_mem))
+				continue;
+		/* Get source line */
+		fname = dwarf_linesrc(line, NULL, NULL);
+
+		ret = handler(fname, lineno, addr, data);
+		if (ret != 0)
+			return ret;
+	}
+
+	/*
+	 * Dwarf lines doesn't include function declarations and inlined
+	 * subroutines. We have to check functions list or given function.
+	 */
+	if (pdie != cu_die)
+		ret = __die_walk_funclines(pdie, handler, data);
+	else {
+		struct __line_walk_param param = {
+			.handler = handler,
+			.data = data,
+			.retval = 0,
+		};
+		dwarf_getfuncs(cu_die, __die_walk_culines_cb, &param, 0);
+		ret = param.retval;
+	}
+
+	return ret;
+}
+
 struct __find_variable_param {
 	const char *name;
 	Dwarf_Addr addr;
@@ -669,6 +856,8 @@ static_var:
 	return 0;
 }
 
+#define BYTES_TO_BITS(nb)	((nb) * BITS_PER_LONG / sizeof(long))
+
 static int convert_variable_type(Dwarf_Die *vr_die,
 				 struct probe_trace_arg *tvar,
 				 const char *cast)
@@ -685,6 +874,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
 		return (tvar->type == NULL) ? -ENOMEM : 0;
 	}
 
+	if (die_get_bit_size(vr_die) != 0) {
+		/* This is a bitfield */
+		ret = snprintf(buf, 16, "b%d@%d/%zd", die_get_bit_size(vr_die),
+				die_get_bit_offset(vr_die),
+				BYTES_TO_BITS(die_get_byte_size(vr_die)));
+		goto formatted;
+	}
+
 	if (die_get_real_type(vr_die, &type) == NULL) {
 		pr_warning("Failed to get a type information of %s.\n",
 			   dwarf_diename(vr_die));
@@ -729,29 +926,31 @@ static int convert_variable_type(Dwarf_Die *vr_die,
 		return (tvar->type == NULL) ? -ENOMEM : 0;
 	}
 
-	ret = die_get_byte_size(&type) * 8;
-	if (ret) {
-		/* Check the bitwidth */
-		if (ret > MAX_BASIC_TYPE_BITS) {
-			pr_info("%s exceeds max-bitwidth."
-				" Cut down to %d bits.\n",
-				dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
-			ret = MAX_BASIC_TYPE_BITS;
-		}
+	ret = BYTES_TO_BITS(die_get_byte_size(&type));
+	if (!ret)
+		/* No size ... try to use default type */
+		return 0;
 
-		ret = snprintf(buf, 16, "%c%d",
-			       die_is_signed_type(&type) ? 's' : 'u', ret);
-		if (ret < 0 || ret >= 16) {
-			if (ret >= 16)
-				ret = -E2BIG;
-			pr_warning("Failed to convert variable type: %s\n",
-				   strerror(-ret));
-			return ret;
-		}
-		tvar->type = strdup(buf);
-		if (tvar->type == NULL)
-			return -ENOMEM;
+	/* Check the bitwidth */
+	if (ret > MAX_BASIC_TYPE_BITS) {
+		pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n",
+			dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
+		ret = MAX_BASIC_TYPE_BITS;
+	}
+	ret = snprintf(buf, 16, "%c%d",
+		       die_is_signed_type(&type) ? 's' : 'u', ret);
+
+formatted:
+	if (ret < 0 || ret >= 16) {
+		if (ret >= 16)
+			ret = -E2BIG;
+		pr_warning("Failed to convert variable type: %s\n",
+			   strerror(-ret));
+		return ret;
 	}
+	tvar->type = strdup(buf);
+	if (tvar->type == NULL)
+		return -ENOMEM;
 	return 0;
 }
 
@@ -1050,157 +1249,102 @@ static int call_probe_finder(Dwarf_Die *sp_die, struct probe_finder *pf)
 	return ret;
 }
 
-/* Find probe point from its line number */
-static int find_probe_point_by_line(struct probe_finder *pf)
+static int probe_point_line_walker(const char *fname, int lineno,
+				   Dwarf_Addr addr, void *data)
 {
-	Dwarf_Lines *lines;
-	Dwarf_Line *line;
-	size_t nlines, i;
-	Dwarf_Addr addr;
-	int lineno;
-	int ret = 0;
-
-	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
-		pr_warning("No source lines found.\n");
-		return -ENOENT;
-	}
+	struct probe_finder *pf = data;
+	int ret;
 
-	for (i = 0; i < nlines && ret == 0; i++) {
-		line = dwarf_onesrcline(lines, i);
-		if (dwarf_lineno(line, &lineno) != 0 ||
-		    lineno != pf->lno)
-			continue;
+	if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0)
+		return 0;
 
-		/* TODO: Get fileno from line, but how? */
-		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
-			continue;
+	pf->addr = addr;
+	ret = call_probe_finder(NULL, pf);
 
-		if (dwarf_lineaddr(line, &addr) != 0) {
-			pr_warning("Failed to get the address of the line.\n");
-			return -ENOENT;
-		}
-		pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
-			 (int)i, lineno, (uintmax_t)addr);
-		pf->addr = addr;
+	/* Continue if no error, because the line will be in inline function */
+	return ret < 0 ? ret : 0;
+}
 
-		ret = call_probe_finder(NULL, pf);
-		/* Continuing, because target line might be inlined. */
-	}
-	return ret;
+/* Find probe point from its line number */
+static int find_probe_point_by_line(struct probe_finder *pf)
+{
+	return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf);
 }
 
 /* Find lines which match lazy pattern */
 static int find_lazy_match_lines(struct list_head *head,
 				 const char *fname, const char *pat)
 {
-	char *fbuf, *p1, *p2;
-	int fd, line, nlines = -1;
-	struct stat st;
-
-	fd = open(fname, O_RDONLY);
-	if (fd < 0) {
-		pr_warning("Failed to open %s: %s\n", fname, strerror(-fd));
+	FILE *fp;
+	char *line = NULL;
+	size_t line_len;
+	ssize_t len;
+	int count = 0, linenum = 1;
+
+	fp = fopen(fname, "r");
+	if (!fp) {
+		pr_warning("Failed to open %s: %s\n", fname, strerror(errno));
 		return -errno;
 	}
 
-	if (fstat(fd, &st) < 0) {
-		pr_warning("Failed to get the size of %s: %s\n",
-			   fname, strerror(errno));
-		nlines = -errno;
-		goto out_close;
-	}
-
-	nlines = -ENOMEM;
-	fbuf = malloc(st.st_size + 2);
-	if (fbuf == NULL)
-		goto out_close;
-	if (read(fd, fbuf, st.st_size) < 0) {
-		pr_warning("Failed to read %s: %s\n", fname, strerror(errno));
-		nlines = -errno;
-		goto out_free_fbuf;
-	}
-	fbuf[st.st_size] = '\n';	/* Dummy line */
-	fbuf[st.st_size + 1] = '\0';
-	p1 = fbuf;
-	line = 1;
-	nlines = 0;
-	while ((p2 = strchr(p1, '\n')) != NULL) {
-		*p2 = '\0';
-		if (strlazymatch(p1, pat)) {
-			line_list__add_line(head, line);
-			nlines++;
+	while ((len = getline(&line, &line_len, fp)) > 0) {
+
+		if (line[len - 1] == '\n')
+			line[len - 1] = '\0';
+
+		if (strlazymatch(line, pat)) {
+			line_list__add_line(head, linenum);
+			count++;
 		}
-		line++;
-		p1 = p2 + 1;
+		linenum++;
 	}
-out_free_fbuf:
-	free(fbuf);
-out_close:
-	close(fd);
-	return nlines;
+
+	if (ferror(fp))
+		count = -errno;
+	free(line);
+	fclose(fp);
+
+	if (count == 0)
+		pr_debug("No matched lines found in %s.\n", fname);
+	return count;
+}
+
+static int probe_point_lazy_walker(const char *fname, int lineno,
+				   Dwarf_Addr addr, void *data)
+{
+	struct probe_finder *pf = data;
+	int ret;
+
+	if (!line_list__has_line(&pf->lcache, lineno) ||
+	    strtailcmp(fname, pf->fname) != 0)
+		return 0;
+
+	pr_debug("Probe line found: line:%d addr:0x%llx\n",
+		 lineno, (unsigned long long)addr);
+	pf->addr = addr;
+	ret = call_probe_finder(NULL, pf);
+
+	/*
+	 * Continue if no error, because the lazy pattern will match
+	 * to other lines
+	 */
+	return ret < 0 ? ret : 0;
 }
 
 /* Find probe points from lazy pattern  */
 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
-	Dwarf_Lines *lines;
-	Dwarf_Line *line;
-	size_t nlines, i;
-	Dwarf_Addr addr;
-	Dwarf_Die die_mem;
-	int lineno;
 	int ret = 0;
 
 	if (list_empty(&pf->lcache)) {
 		/* Matching lazy line pattern */
 		ret = find_lazy_match_lines(&pf->lcache, pf->fname,
 					    pf->pev->point.lazy_line);
-		if (ret == 0) {
-			pr_debug("No matched lines found in %s.\n", pf->fname);
-			return 0;
-		} else if (ret < 0)
+		if (ret <= 0)
 			return ret;
 	}
 
-	if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) {
-		pr_warning("No source lines found.\n");
-		return -ENOENT;
-	}
-
-	for (i = 0; i < nlines && ret >= 0; i++) {
-		line = dwarf_onesrcline(lines, i);
-
-		if (dwarf_lineno(line, &lineno) != 0 ||
-		    !line_list__has_line(&pf->lcache, lineno))
-			continue;
-
-		/* TODO: Get fileno from line, but how? */
-		if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
-			continue;
-
-		if (dwarf_lineaddr(line, &addr) != 0) {
-			pr_debug("Failed to get the address of line %d.\n",
-				 lineno);
-			continue;
-		}
-		if (sp_die) {
-			/* Address filtering 1: does sp_die include addr? */
-			if (!dwarf_haspc(sp_die, addr))
-				continue;
-			/* Address filtering 2: No child include addr? */
-			if (die_find_inlinefunc(sp_die, addr, &die_mem))
-				continue;
-		}
-
-		pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n",
-			 (int)i, lineno, (unsigned long long)addr);
-		pf->addr = addr;
-
-		ret = call_probe_finder(sp_die, pf);
-		/* Continuing, because target line might be inlined. */
-	}
-	/* TODO: deallocate lines, but how? */
-	return ret;
+	return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
 }
 
 /* Callback parameter with return value */
@@ -1318,8 +1462,7 @@ static int find_probes(int fd, struct probe_finder *pf)
 	off = 0;
 	line_list__init(&pf->lcache);
 	/* Loop on CUs (Compilation Unit) */
-	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) &&
-	       ret >= 0) {
+	while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
 		/* Get the DIE(Debugging Information Entry) of this CU */
 		diep = dwarf_offdie(dbg, off + cuhl, &pf->cu_die);
 		if (!diep)
@@ -1340,6 +1483,8 @@ static int find_probes(int fd, struct probe_finder *pf)
 				pf->lno = pp->line;
 				ret = find_probe_point_by_line(pf);
 			}
+			if (ret < 0)
+				break;
 		}
 		off = noff;
 	}
@@ -1644,91 +1789,28 @@ static int line_range_add_line(const char *src, unsigned int lineno,
 	return line_list__add_line(&lr->line_list, lineno);
 }
 
-/* Search function declaration lines */
-static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data)
+static int line_range_walk_cb(const char *fname, int lineno,
+			      Dwarf_Addr addr __used,
+			      void *data)
 {
-	struct dwarf_callback_param *param = data;
-	struct line_finder *lf = param->data;
-	const char *src;
-	int lineno;
+	struct line_finder *lf = data;
 
-	src = dwarf_decl_file(sp_die);
-	if (src && strtailcmp(src, lf->fname) != 0)
-		return DWARF_CB_OK;
-
-	if (dwarf_decl_line(sp_die, &lineno) != 0 ||
+	if ((strtailcmp(fname, lf->fname) != 0) ||
 	    (lf->lno_s > lineno || lf->lno_e < lineno))
-		return DWARF_CB_OK;
+		return 0;
 
-	param->retval = line_range_add_line(src, lineno, lf->lr);
-	if (param->retval < 0)
-		return DWARF_CB_ABORT;
-	return DWARF_CB_OK;
-}
+	if (line_range_add_line(fname, lineno, lf->lr) < 0)
+		return -EINVAL;
 
-static int find_line_range_func_decl_lines(struct line_finder *lf)
-{
-	struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
-	dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, &param, 0);
-	return param.retval;
+	return 0;
 }
 
 /* Find line range from its line number */
 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf)
 {
-	Dwarf_Lines *lines;
-	Dwarf_Line *line;
-	size_t nlines, i;
-	Dwarf_Addr addr;
-	int lineno, ret = 0;
-	const char *src;
-	Dwarf_Die die_mem;
-
-	line_list__init(&lf->lr->line_list);
-	if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) {
-		pr_warning("No source lines found.\n");
-		return -ENOENT;
-	}
-
-	/* Search probable lines on lines list */
-	for (i = 0; i < nlines; i++) {
-		line = dwarf_onesrcline(lines, i);
-		if (dwarf_lineno(line, &lineno) != 0 ||
-		    (lf->lno_s > lineno || lf->lno_e < lineno))
-			continue;
-
-		if (sp_die) {
-			/* Address filtering 1: does sp_die include addr? */
-			if (dwarf_lineaddr(line, &addr) != 0 ||
-			    !dwarf_haspc(sp_die, addr))
-				continue;
-
-			/* Address filtering 2: No child include addr? */
-			if (die_find_inlinefunc(sp_die, addr, &die_mem))
-				continue;
-		}
-
-		/* TODO: Get fileno from line, but how? */
-		src = dwarf_linesrc(line, NULL, NULL);
-		if (strtailcmp(src, lf->fname) != 0)
-			continue;
-
-		ret = line_range_add_line(src, lineno, lf->lr);
-		if (ret < 0)
-			return ret;
-	}
+	int ret;
 
-	/*
-	 * Dwarf lines doesn't include function declarations. We have to
-	 * check functions list or given function.
-	 */
-	if (sp_die) {
-		src = dwarf_decl_file(sp_die);
-		if (src && dwarf_decl_line(sp_die, &lineno) == 0 &&
-		    (lf->lno_s <= lineno && lf->lno_e >= lineno))
-			ret = line_range_add_line(src, lineno, lf->lr);
-	} else
-		ret = find_line_range_func_decl_lines(lf);
+	ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf);
 
 	/* Update status */
 	if (ret >= 0)
@@ -1758,9 +1840,6 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
 	struct line_finder *lf = param->data;
 	struct line_range *lr = lf->lr;
 
-	pr_debug("find (%llx) %s\n",
-		 (unsigned long long)dwarf_dieoffset(sp_die),
-		 dwarf_diename(sp_die));
 	if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
 	    die_compare_name(sp_die, lr->function)) {
 		lf->fname = dwarf_decl_file(sp_die);
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
new file mode 100644
index 0000000..a9f2d7e
--- /dev/null
+++ b/tools/perf/util/python.c
@@ -0,0 +1,896 @@
+#include <Python.h>
+#include <structmember.h>
+#include <inttypes.h>
+#include <poll.h>
+#include "evlist.h"
+#include "evsel.h"
+#include "event.h"
+#include "cpumap.h"
+#include "thread_map.h"
+
+/* Define PyVarObject_HEAD_INIT for python 2.5 */
+#ifndef PyVarObject_HEAD_INIT
+# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
+#endif
+
+struct throttle_event {
+	struct perf_event_header header;
+	u64			 time;
+	u64			 id;
+	u64			 stream_id;
+};
+
+PyMODINIT_FUNC initperf(void);
+
+#define member_def(type, member, ptype, help) \
+	{ #member, ptype, \
+	  offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
+	  0, help }
+
+#define sample_member_def(name, member, ptype, help) \
+	{ #name, ptype, \
+	  offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
+	  0, help }
+
+struct pyrf_event {
+	PyObject_HEAD
+	struct perf_sample sample;
+	union perf_event   event;
+};
+
+#define sample_members \
+	sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"),			 \
+	sample_member_def(sample_pid, pid, T_INT, "event pid"),			 \
+	sample_member_def(sample_tid, tid, T_INT, "event tid"),			 \
+	sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"),		 \
+	sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"),		 \
+	sample_member_def(sample_id, id, T_ULONGLONG, "event id"),			 \
+	sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
+	sample_member_def(sample_period, period, T_ULONGLONG, "event period"),		 \
+	sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
+
+static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
+
+static PyMemberDef pyrf_mmap_event__members[] = {
+	sample_members
+	member_def(perf_event_header, type, T_UINT, "event type"),
+	member_def(mmap_event, pid, T_UINT, "event pid"),
+	member_def(mmap_event, tid, T_UINT, "event tid"),
+	member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
+	member_def(mmap_event, len, T_ULONGLONG, "map length"),
+	member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
+	member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
+	{ .name = NULL, },
+};
+
+static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
+{
+	PyObject *ret;
+	char *s;
+
+	if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
+			 "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
+			 "filename: %s }",
+		     pevent->event.mmap.pid, pevent->event.mmap.tid,
+		     pevent->event.mmap.start, pevent->event.mmap.len,
+		     pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
+		ret = PyErr_NoMemory();
+	} else {
+		ret = PyString_FromString(s);
+		free(s);
+	}
+	return ret;
+}
+
+static PyTypeObject pyrf_mmap_event__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.mmap_event",
+	.tp_basicsize	= sizeof(struct pyrf_event),
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_mmap_event__doc,
+	.tp_members	= pyrf_mmap_event__members,
+	.tp_repr	= (reprfunc)pyrf_mmap_event__repr,
+};
+
+static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
+
+static PyMemberDef pyrf_task_event__members[] = {
+	sample_members
+	member_def(perf_event_header, type, T_UINT, "event type"),
+	member_def(fork_event, pid, T_UINT, "event pid"),
+	member_def(fork_event, ppid, T_UINT, "event ppid"),
+	member_def(fork_event, tid, T_UINT, "event tid"),
+	member_def(fork_event, ptid, T_UINT, "event ptid"),
+	member_def(fork_event, time, T_ULONGLONG, "timestamp"),
+	{ .name = NULL, },
+};
+
+static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
+{
+	return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
+				   "ptid: %u, time: %" PRIu64 "}",
+				   pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
+				   pevent->event.fork.pid,
+				   pevent->event.fork.ppid,
+				   pevent->event.fork.tid,
+				   pevent->event.fork.ptid,
+				   pevent->event.fork.time);
+}
+
+static PyTypeObject pyrf_task_event__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.task_event",
+	.tp_basicsize	= sizeof(struct pyrf_event),
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_task_event__doc,
+	.tp_members	= pyrf_task_event__members,
+	.tp_repr	= (reprfunc)pyrf_task_event__repr,
+};
+
+static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
+
+static PyMemberDef pyrf_comm_event__members[] = {
+	sample_members
+	member_def(perf_event_header, type, T_UINT, "event type"),
+	member_def(comm_event, pid, T_UINT, "event pid"),
+	member_def(comm_event, tid, T_UINT, "event tid"),
+	member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
+	{ .name = NULL, },
+};
+
+static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
+{
+	return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
+				   pevent->event.comm.pid,
+				   pevent->event.comm.tid,
+				   pevent->event.comm.comm);
+}
+
+static PyTypeObject pyrf_comm_event__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.comm_event",
+	.tp_basicsize	= sizeof(struct pyrf_event),
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_comm_event__doc,
+	.tp_members	= pyrf_comm_event__members,
+	.tp_repr	= (reprfunc)pyrf_comm_event__repr,
+};
+
+static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
+
+static PyMemberDef pyrf_throttle_event__members[] = {
+	sample_members
+	member_def(perf_event_header, type, T_UINT, "event type"),
+	member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
+	member_def(throttle_event, id, T_ULONGLONG, "event id"),
+	member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
+	{ .name = NULL, },
+};
+
+static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
+{
+	struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
+
+	return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
+				   ", stream_id: %" PRIu64 " }",
+				   pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
+				   te->time, te->id, te->stream_id);
+}
+
+static PyTypeObject pyrf_throttle_event__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.throttle_event",
+	.tp_basicsize	= sizeof(struct pyrf_event),
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_throttle_event__doc,
+	.tp_members	= pyrf_throttle_event__members,
+	.tp_repr	= (reprfunc)pyrf_throttle_event__repr,
+};
+
+static int pyrf_event__setup_types(void)
+{
+	int err;
+	pyrf_mmap_event__type.tp_new =
+	pyrf_task_event__type.tp_new =
+	pyrf_comm_event__type.tp_new =
+	pyrf_throttle_event__type.tp_new = PyType_GenericNew;
+	err = PyType_Ready(&pyrf_mmap_event__type);
+	if (err < 0)
+		goto out;
+	err = PyType_Ready(&pyrf_task_event__type);
+	if (err < 0)
+		goto out;
+	err = PyType_Ready(&pyrf_comm_event__type);
+	if (err < 0)
+		goto out;
+	err = PyType_Ready(&pyrf_throttle_event__type);
+	if (err < 0)
+		goto out;
+out:
+	return err;
+}
+
+static PyTypeObject *pyrf_event__type[] = {
+	[PERF_RECORD_MMAP]	 = &pyrf_mmap_event__type,
+	[PERF_RECORD_LOST]	 = &pyrf_mmap_event__type,
+	[PERF_RECORD_COMM]	 = &pyrf_comm_event__type,
+	[PERF_RECORD_EXIT]	 = &pyrf_task_event__type,
+	[PERF_RECORD_THROTTLE]	 = &pyrf_throttle_event__type,
+	[PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
+	[PERF_RECORD_FORK]	 = &pyrf_task_event__type,
+	[PERF_RECORD_READ]	 = &pyrf_mmap_event__type,
+	[PERF_RECORD_SAMPLE]	 = &pyrf_mmap_event__type,
+};
+
+static PyObject *pyrf_event__new(union perf_event *event)
+{
+	struct pyrf_event *pevent;
+	PyTypeObject *ptype;
+
+	if (event->header.type < PERF_RECORD_MMAP ||
+	    event->header.type > PERF_RECORD_SAMPLE)
+		return NULL;
+
+	ptype = pyrf_event__type[event->header.type];
+	pevent = PyObject_New(struct pyrf_event, ptype);
+	if (pevent != NULL)
+		memcpy(&pevent->event, event, event->header.size);
+	return (PyObject *)pevent;
+}
+
+struct pyrf_cpu_map {
+	PyObject_HEAD
+
+	struct cpu_map *cpus;
+};
+
+static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
+			      PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = { "cpustr", NULL, NULL, };
+	char *cpustr = NULL;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
+					 kwlist, &cpustr))
+		return -1;
+
+	pcpus->cpus = cpu_map__new(cpustr);
+	if (pcpus->cpus == NULL)
+		return -1;
+	return 0;
+}
+
+static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
+{
+	cpu_map__delete(pcpus->cpus);
+	pcpus->ob_type->tp_free((PyObject*)pcpus);
+}
+
+static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
+{
+	struct pyrf_cpu_map *pcpus = (void *)obj;
+
+	return pcpus->cpus->nr;
+}
+
+static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
+{
+	struct pyrf_cpu_map *pcpus = (void *)obj;
+
+	if (i >= pcpus->cpus->nr)
+		return NULL;
+
+	return Py_BuildValue("i", pcpus->cpus->map[i]);
+}
+
+static PySequenceMethods pyrf_cpu_map__sequence_methods = {
+	.sq_length = pyrf_cpu_map__length,
+	.sq_item   = pyrf_cpu_map__item,
+};
+
+static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
+
+static PyTypeObject pyrf_cpu_map__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.cpu_map",
+	.tp_basicsize	= sizeof(struct pyrf_cpu_map),
+	.tp_dealloc	= (destructor)pyrf_cpu_map__delete,
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_cpu_map__doc,
+	.tp_as_sequence	= &pyrf_cpu_map__sequence_methods,
+	.tp_init	= (initproc)pyrf_cpu_map__init,
+};
+
+static int pyrf_cpu_map__setup_types(void)
+{
+	pyrf_cpu_map__type.tp_new = PyType_GenericNew;
+	return PyType_Ready(&pyrf_cpu_map__type);
+}
+
+struct pyrf_thread_map {
+	PyObject_HEAD
+
+	struct thread_map *threads;
+};
+
+static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
+				 PyObject *args, PyObject *kwargs)
+{
+	static char *kwlist[] = { "pid", "tid", NULL, NULL, };
+	int pid = -1, tid = -1;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
+					 kwlist, &pid, &tid))
+		return -1;
+
+	pthreads->threads = thread_map__new(pid, tid);
+	if (pthreads->threads == NULL)
+		return -1;
+	return 0;
+}
+
+static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
+{
+	thread_map__delete(pthreads->threads);
+	pthreads->ob_type->tp_free((PyObject*)pthreads);
+}
+
+static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
+{
+	struct pyrf_thread_map *pthreads = (void *)obj;
+
+	return pthreads->threads->nr;
+}
+
+static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
+{
+	struct pyrf_thread_map *pthreads = (void *)obj;
+
+	if (i >= pthreads->threads->nr)
+		return NULL;
+
+	return Py_BuildValue("i", pthreads->threads->map[i]);
+}
+
+static PySequenceMethods pyrf_thread_map__sequence_methods = {
+	.sq_length = pyrf_thread_map__length,
+	.sq_item   = pyrf_thread_map__item,
+};
+
+static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
+
+static PyTypeObject pyrf_thread_map__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.thread_map",
+	.tp_basicsize	= sizeof(struct pyrf_thread_map),
+	.tp_dealloc	= (destructor)pyrf_thread_map__delete,
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_thread_map__doc,
+	.tp_as_sequence	= &pyrf_thread_map__sequence_methods,
+	.tp_init	= (initproc)pyrf_thread_map__init,
+};
+
+static int pyrf_thread_map__setup_types(void)
+{
+	pyrf_thread_map__type.tp_new = PyType_GenericNew;
+	return PyType_Ready(&pyrf_thread_map__type);
+}
+
+struct pyrf_evsel {
+	PyObject_HEAD
+
+	struct perf_evsel evsel;
+};
+
+static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
+			    PyObject *args, PyObject *kwargs)
+{
+	struct perf_event_attr attr = {
+		.type = PERF_TYPE_HARDWARE,
+		.config = PERF_COUNT_HW_CPU_CYCLES,
+		.sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
+	};
+	static char *kwlist[] = {
+		"type",
+		"config",
+		"sample_freq",
+		"sample_period",
+		"sample_type",
+		"read_format",
+		"disabled",
+		"inherit",
+		"pinned",
+		"exclusive",
+		"exclude_user",
+		"exclude_kernel",
+		"exclude_hv",
+		"exclude_idle",
+		"mmap",
+		"comm",
+		"freq",
+		"inherit_stat",
+		"enable_on_exec",
+		"task",
+		"watermark",
+		"precise_ip",
+		"mmap_data",
+		"sample_id_all",
+		"wakeup_events",
+		"bp_type",
+		"bp_addr",
+		"bp_len", NULL, NULL, };
+	u64 sample_period = 0;
+	u32 disabled = 0,
+	    inherit = 0,
+	    pinned = 0,
+	    exclusive = 0,
+	    exclude_user = 0,
+	    exclude_kernel = 0,
+	    exclude_hv = 0,
+	    exclude_idle = 0,
+	    mmap = 0,
+	    comm = 0,
+	    freq = 1,
+	    inherit_stat = 0,
+	    enable_on_exec = 0,
+	    task = 0,
+	    watermark = 0,
+	    precise_ip = 0,
+	    mmap_data = 0,
+	    sample_id_all = 1;
+	int idx = 0;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
+					 &attr.type, &attr.config, &attr.sample_freq,
+					 &sample_period, &attr.sample_type,
+					 &attr.read_format, &disabled, &inherit,
+					 &pinned, &exclusive, &exclude_user,
+					 &exclude_kernel, &exclude_hv, &exclude_idle,
+					 &mmap, &comm, &freq, &inherit_stat,
+					 &enable_on_exec, &task, &watermark,
+					 &precise_ip, &mmap_data, &sample_id_all,
+					 &attr.wakeup_events, &attr.bp_type,
+					 &attr.bp_addr, &attr.bp_len, &idx))
+		return -1;
+
+	/* union... */
+	if (sample_period != 0) {
+		if (attr.sample_freq != 0)
+			return -1; /* FIXME: throw right exception */
+		attr.sample_period = sample_period;
+	}
+
+	/* Bitfields */
+	attr.disabled	    = disabled;
+	attr.inherit	    = inherit;
+	attr.pinned	    = pinned;
+	attr.exclusive	    = exclusive;
+	attr.exclude_user   = exclude_user;
+	attr.exclude_kernel = exclude_kernel;
+	attr.exclude_hv	    = exclude_hv;
+	attr.exclude_idle   = exclude_idle;
+	attr.mmap	    = mmap;
+	attr.comm	    = comm;
+	attr.freq	    = freq;
+	attr.inherit_stat   = inherit_stat;
+	attr.enable_on_exec = enable_on_exec;
+	attr.task	    = task;
+	attr.watermark	    = watermark;
+	attr.precise_ip	    = precise_ip;
+	attr.mmap_data	    = mmap_data;
+	attr.sample_id_all  = sample_id_all;
+
+	perf_evsel__init(&pevsel->evsel, &attr, idx);
+	return 0;
+}
+
+static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
+{
+	perf_evsel__exit(&pevsel->evsel);
+	pevsel->ob_type->tp_free((PyObject*)pevsel);
+}
+
+static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
+				  PyObject *args, PyObject *kwargs)
+{
+	struct perf_evsel *evsel = &pevsel->evsel;
+	struct cpu_map *cpus = NULL;
+	struct thread_map *threads = NULL;
+	PyObject *pcpus = NULL, *pthreads = NULL;
+	int group = 0, overwrite = 0;
+	static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
+					 &pcpus, &pthreads, &group, &overwrite))
+		return NULL;
+
+	if (pthreads != NULL)
+		threads = ((struct pyrf_thread_map *)pthreads)->threads;
+
+	if (pcpus != NULL)
+		cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
+
+	if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMethodDef pyrf_evsel__methods[] = {
+	{
+		.ml_name  = "open",
+		.ml_meth  = (PyCFunction)pyrf_evsel__open,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("open the event selector file descriptor table.")
+	},
+	{ .ml_name = NULL, }
+};
+
+static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
+
+static PyTypeObject pyrf_evsel__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.evsel",
+	.tp_basicsize	= sizeof(struct pyrf_evsel),
+	.tp_dealloc	= (destructor)pyrf_evsel__delete,
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_doc		= pyrf_evsel__doc,
+	.tp_methods	= pyrf_evsel__methods,
+	.tp_init	= (initproc)pyrf_evsel__init,
+};
+
+static int pyrf_evsel__setup_types(void)
+{
+	pyrf_evsel__type.tp_new = PyType_GenericNew;
+	return PyType_Ready(&pyrf_evsel__type);
+}
+
+struct pyrf_evlist {
+	PyObject_HEAD
+
+	struct perf_evlist evlist;
+};
+
+static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
+			     PyObject *args, PyObject *kwargs __used)
+{
+	PyObject *pcpus = NULL, *pthreads = NULL;
+	struct cpu_map *cpus;
+	struct thread_map *threads;
+
+	if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
+		return -1;
+
+	threads = ((struct pyrf_thread_map *)pthreads)->threads;
+	cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
+	perf_evlist__init(&pevlist->evlist, cpus, threads);
+	return 0;
+}
+
+static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
+{
+	perf_evlist__exit(&pevlist->evlist);
+	pevlist->ob_type->tp_free((PyObject*)pevlist);
+}
+
+static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
+				   PyObject *args, PyObject *kwargs)
+{
+	struct perf_evlist *evlist = &pevlist->evlist;
+	static char *kwlist[] = {"pages", "overwrite",
+				  NULL, NULL};
+	int pages = 128, overwrite = false;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
+					 &pages, &overwrite))
+		return NULL;
+
+	if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
+				   PyObject *args, PyObject *kwargs)
+{
+	struct perf_evlist *evlist = &pevlist->evlist;
+	static char *kwlist[] = {"timeout", NULL, NULL};
+	int timeout = -1, n;
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
+		return NULL;
+
+	n = poll(evlist->pollfd, evlist->nr_fds, timeout);
+	if (n < 0) {
+		PyErr_SetFromErrno(PyExc_OSError);
+		return NULL;
+	}
+
+	return Py_BuildValue("i", n);
+}
+
+static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
+					 PyObject *args __used, PyObject *kwargs __used)
+{
+	struct perf_evlist *evlist = &pevlist->evlist;
+        PyObject *list = PyList_New(0);
+	int i;
+
+	for (i = 0; i < evlist->nr_fds; ++i) {
+		PyObject *file;
+		FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
+
+		if (fp == NULL)
+			goto free_list;
+
+		file = PyFile_FromFile(fp, "perf", "r", NULL);
+		if (file == NULL)
+			goto free_list;
+
+		if (PyList_Append(list, file) != 0) {
+			Py_DECREF(file);
+			goto free_list;
+		}
+			
+		Py_DECREF(file);
+	}
+
+	return list;
+free_list:
+	return PyErr_NoMemory();
+}
+
+
+static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
+				  PyObject *args, PyObject *kwargs __used)
+{
+	struct perf_evlist *evlist = &pevlist->evlist;
+	PyObject *pevsel;
+	struct perf_evsel *evsel;
+
+	if (!PyArg_ParseTuple(args, "O", &pevsel))
+		return NULL;
+
+	Py_INCREF(pevsel);
+	evsel = &((struct pyrf_evsel *)pevsel)->evsel;
+	evsel->idx = evlist->nr_entries;
+	perf_evlist__add(evlist, evsel);
+
+	return Py_BuildValue("i", evlist->nr_entries);
+}
+
+static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
+					  PyObject *args, PyObject *kwargs)
+{
+	struct perf_evlist *evlist = &pevlist->evlist;
+	union perf_event *event;
+	int sample_id_all = 1, cpu;
+	static char *kwlist[] = {"sample_id_all", NULL, NULL};
+
+	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
+					 &cpu, &sample_id_all))
+		return NULL;
+
+	event = perf_evlist__read_on_cpu(evlist, cpu);
+	if (event != NULL) {
+		struct perf_evsel *first;
+		PyObject *pyevent = pyrf_event__new(event);
+		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
+
+		if (pyevent == NULL)
+			return PyErr_NoMemory();
+
+		first = list_entry(evlist->entries.next, struct perf_evsel, node);
+		perf_event__parse_sample(event, first->attr.sample_type, sample_id_all,
+					 &pevent->sample);
+		return pyevent;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMethodDef pyrf_evlist__methods[] = {
+	{
+		.ml_name  = "mmap",
+		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("mmap the file descriptor table.")
+	},
+	{
+		.ml_name  = "poll",
+		.ml_meth  = (PyCFunction)pyrf_evlist__poll,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("poll the file descriptor table.")
+	},
+	{
+		.ml_name  = "get_pollfd",
+		.ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("get the poll file descriptor table.")
+	},
+	{
+		.ml_name  = "add",
+		.ml_meth  = (PyCFunction)pyrf_evlist__add,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("adds an event selector to the list.")
+	},
+	{
+		.ml_name  = "read_on_cpu",
+		.ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
+		.ml_flags = METH_VARARGS | METH_KEYWORDS,
+		.ml_doc	  = PyDoc_STR("reads an event.")
+	},
+	{ .ml_name = NULL, }
+};
+
+static Py_ssize_t pyrf_evlist__length(PyObject *obj)
+{
+	struct pyrf_evlist *pevlist = (void *)obj;
+
+	return pevlist->evlist.nr_entries;
+}
+
+static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
+{
+	struct pyrf_evlist *pevlist = (void *)obj;
+	struct perf_evsel *pos;
+
+	if (i >= pevlist->evlist.nr_entries)
+		return NULL;
+
+	list_for_each_entry(pos, &pevlist->evlist.entries, node)
+		if (i-- == 0)
+			break;
+
+	return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
+}
+
+static PySequenceMethods pyrf_evlist__sequence_methods = {
+	.sq_length = pyrf_evlist__length,
+	.sq_item   = pyrf_evlist__item,
+};
+
+static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
+
+static PyTypeObject pyrf_evlist__type = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	.tp_name	= "perf.evlist",
+	.tp_basicsize	= sizeof(struct pyrf_evlist),
+	.tp_dealloc	= (destructor)pyrf_evlist__delete,
+	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+	.tp_as_sequence	= &pyrf_evlist__sequence_methods,
+	.tp_doc		= pyrf_evlist__doc,
+	.tp_methods	= pyrf_evlist__methods,
+	.tp_init	= (initproc)pyrf_evlist__init,
+};
+
+static int pyrf_evlist__setup_types(void)
+{
+	pyrf_evlist__type.tp_new = PyType_GenericNew;
+	return PyType_Ready(&pyrf_evlist__type);
+}
+
+static struct {
+	const char *name;
+	int	    value;
+} perf__constants[] = {
+	{ "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
+	{ "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
+	{ "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
+	{ "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
+	{ "TYPE_RAW",	     PERF_TYPE_RAW },
+	{ "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
+
+	{ "COUNT_HW_CPU_CYCLES",	  PERF_COUNT_HW_CPU_CYCLES },
+	{ "COUNT_HW_INSTRUCTIONS",	  PERF_COUNT_HW_INSTRUCTIONS },
+	{ "COUNT_HW_CACHE_REFERENCES",	  PERF_COUNT_HW_CACHE_REFERENCES },
+	{ "COUNT_HW_CACHE_MISSES",	  PERF_COUNT_HW_CACHE_MISSES },
+	{ "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
+	{ "COUNT_HW_BRANCH_MISSES",	  PERF_COUNT_HW_BRANCH_MISSES },
+	{ "COUNT_HW_BUS_CYCLES",	  PERF_COUNT_HW_BUS_CYCLES },
+	{ "COUNT_HW_CACHE_L1D",		  PERF_COUNT_HW_CACHE_L1D },
+	{ "COUNT_HW_CACHE_L1I",		  PERF_COUNT_HW_CACHE_L1I },
+	{ "COUNT_HW_CACHE_LL",	  	  PERF_COUNT_HW_CACHE_LL },
+	{ "COUNT_HW_CACHE_DTLB",	  PERF_COUNT_HW_CACHE_DTLB },
+	{ "COUNT_HW_CACHE_ITLB",	  PERF_COUNT_HW_CACHE_ITLB },
+	{ "COUNT_HW_CACHE_BPU",		  PERF_COUNT_HW_CACHE_BPU },
+	{ "COUNT_HW_CACHE_OP_READ",	  PERF_COUNT_HW_CACHE_OP_READ },
+	{ "COUNT_HW_CACHE_OP_WRITE",	  PERF_COUNT_HW_CACHE_OP_WRITE },
+	{ "COUNT_HW_CACHE_OP_PREFETCH",	  PERF_COUNT_HW_CACHE_OP_PREFETCH },
+	{ "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
+	{ "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
+
+	{ "COUNT_SW_CPU_CLOCK",	       PERF_COUNT_SW_CPU_CLOCK },
+	{ "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
+	{ "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
+	{ "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
+	{ "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
+	{ "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
+	{ "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
+	{ "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
+	{ "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
+
+	{ "SAMPLE_IP",	      PERF_SAMPLE_IP },
+	{ "SAMPLE_TID",	      PERF_SAMPLE_TID },
+	{ "SAMPLE_TIME",      PERF_SAMPLE_TIME },
+	{ "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
+	{ "SAMPLE_READ",      PERF_SAMPLE_READ },
+	{ "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
+	{ "SAMPLE_ID",	      PERF_SAMPLE_ID },
+	{ "SAMPLE_CPU",	      PERF_SAMPLE_CPU },
+	{ "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
+	{ "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
+	{ "SAMPLE_RAW",	      PERF_SAMPLE_RAW },
+
+	{ "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
+	{ "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
+	{ "FORMAT_ID",		       PERF_FORMAT_ID },
+	{ "FORMAT_GROUP",	       PERF_FORMAT_GROUP },
+
+	{ "RECORD_MMAP",       PERF_RECORD_MMAP },
+	{ "RECORD_LOST",       PERF_RECORD_LOST },
+	{ "RECORD_COMM",       PERF_RECORD_COMM },
+	{ "RECORD_EXIT",       PERF_RECORD_EXIT },
+	{ "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
+	{ "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
+	{ "RECORD_FORK",       PERF_RECORD_FORK },
+	{ "RECORD_READ",       PERF_RECORD_READ },
+	{ "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
+	{ .name = NULL, },
+};
+
+static PyMethodDef perf__methods[] = {
+	{ .ml_name = NULL, }
+};
+
+PyMODINIT_FUNC initperf(void)
+{
+	PyObject *obj;
+	int i;
+	PyObject *dict, *module = Py_InitModule("perf", perf__methods);
+
+	if (module == NULL ||
+	    pyrf_event__setup_types() < 0 ||
+	    pyrf_evlist__setup_types() < 0 ||
+	    pyrf_evsel__setup_types() < 0 ||
+	    pyrf_thread_map__setup_types() < 0 ||
+	    pyrf_cpu_map__setup_types() < 0)
+		return;
+
+	Py_INCREF(&pyrf_evlist__type);
+	PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
+
+	Py_INCREF(&pyrf_evsel__type);
+	PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
+
+	Py_INCREF(&pyrf_thread_map__type);
+	PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
+
+	Py_INCREF(&pyrf_cpu_map__type);
+	PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
+
+	dict = PyModule_GetDict(module);
+	if (dict == NULL)
+		goto error;
+
+	for (i = 0; perf__constants[i].name != NULL; i++) {
+		obj = PyInt_FromLong(perf__constants[i].value);
+		if (obj == NULL)
+			goto error;
+		PyDict_SetItemString(dict, perf__constants[i].name, obj);
+		Py_DECREF(obj);
+	}
+
+error:
+	if (PyErr_Occurred())
+		PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
+}
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 9368081..6214272 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -245,9 +245,10 @@ static inline struct event *find_cache_event(int type)
 	return event;
 }
 
-static void perl_process_event(int cpu, void *data,
-			       int size __unused,
-			       unsigned long long nsecs, char *comm)
+static void perl_process_event(union perf_event *pevent __unused,
+			       struct perf_sample *sample,
+			       struct perf_session *session __unused,
+			       struct thread *thread)
 {
 	struct format_field *field;
 	static char handler[256];
@@ -256,6 +257,10 @@ static void perl_process_event(int cpu, void *data,
 	struct event *event;
 	int type;
 	int pid;
+	int cpu = sample->cpu;
+	void *data = sample->raw_data;
+	unsigned long long nsecs = sample->time;
+	char *comm = thread->comm;
 
 	dSP;
 
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index c6d9933..1b85d60 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -204,9 +204,10 @@ static inline struct event *find_cache_event(int type)
 	return event;
 }
 
-static void python_process_event(int cpu, void *data,
-				 int size __unused,
-				 unsigned long long nsecs, char *comm)
+static void python_process_event(union perf_event *pevent __unused,
+				 struct perf_sample *sample,
+				 struct perf_session *session __unused,
+				 struct thread *thread)
 {
 	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
 	static char handler_name[256];
@@ -217,6 +218,10 @@ static void python_process_event(int cpu, void *data,
 	unsigned n = 0;
 	int type;
 	int pid;
+	int cpu = sample->cpu;
+	void *data = sample->raw_data;
+	unsigned long long nsecs = sample->time;
+	char *comm = thread->comm;
 
 	t = PyTuple_New(MAX_FIELDS);
 	if (!t)
@@ -248,8 +253,7 @@ static void python_process_event(int cpu, void *data,
 	context = PyCObject_FromVoidPtr(scripting_context, NULL);
 
 	PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
-	PyTuple_SetItem(t, n++,
-			PyCObject_FromVoidPtr(scripting_context, NULL));
+	PyTuple_SetItem(t, n++, context);
 
 	if (handler) {
 		PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 105f00b..c68cf40 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -7,6 +7,8 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 
+#include "evlist.h"
+#include "evsel.h"
 #include "session.h"
 #include "sort.h"
 #include "util.h"
@@ -19,7 +21,7 @@ static int perf_session__open(struct perf_session *self, bool force)
 		self->fd_pipe = true;
 		self->fd = STDIN_FILENO;
 
-		if (perf_header__read(self, self->fd) < 0)
+		if (perf_session__read_header(self, self->fd) < 0)
 			pr_err("incompatible file format");
 
 		return 0;
@@ -51,7 +53,7 @@ static int perf_session__open(struct perf_session *self, bool force)
 		goto out_close;
 	}
 
-	if (perf_header__read(self, self->fd) < 0) {
+	if (perf_session__read_header(self, self->fd) < 0) {
 		pr_err("incompatible file format");
 		goto out_close;
 	}
@@ -67,7 +69,7 @@ out_close:
 
 static void perf_session__id_header_size(struct perf_session *session)
 {
-       struct sample_data *data;
+       struct perf_sample *data;
        u64 sample_type = session->sample_type;
        u16 size = 0;
 
@@ -92,21 +94,10 @@ out:
        session->id_hdr_size = size;
 }
 
-void perf_session__set_sample_id_all(struct perf_session *session, bool value)
-{
-	session->sample_id_all = value;
-	perf_session__id_header_size(session);
-}
-
-void perf_session__set_sample_type(struct perf_session *session, u64 type)
-{
-	session->sample_type = type;
-}
-
 void perf_session__update_sample_type(struct perf_session *self)
 {
-	self->sample_type = perf_header__sample_type(&self->header);
-	self->sample_id_all = perf_header__sample_id_all(&self->header);
+	self->sample_type = perf_evlist__sample_type(self->evlist);
+	self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
 	perf_session__id_header_size(self);
 }
 
@@ -135,13 +126,9 @@ struct perf_session *perf_session__new(const char *filename, int mode,
 	if (self == NULL)
 		goto out;
 
-	if (perf_header__init(&self->header) < 0)
-		goto out_free;
-
 	memcpy(self->filename, filename, len);
 	self->threads = RB_ROOT;
 	INIT_LIST_HEAD(&self->dead_threads);
-	self->hists_tree = RB_ROOT;
 	self->last_match = NULL;
 	/*
 	 * On 64bit we can mmap the data file in one go. No need for tiny mmap
@@ -162,17 +149,16 @@ struct perf_session *perf_session__new(const char *filename, int mode,
 	if (mode == O_RDONLY) {
 		if (perf_session__open(self, force) < 0)
 			goto out_delete;
+		perf_session__update_sample_type(self);
 	} else if (mode == O_WRONLY) {
 		/*
 		 * In O_RDONLY mode this will be performed when reading the
-		 * kernel MMAP event, in event__process_mmap().
+		 * kernel MMAP event, in perf_event__process_mmap().
 		 */
 		if (perf_session__create_kernel_maps(self) < 0)
 			goto out_delete;
 	}
 
-	perf_session__update_sample_type(self);
-
 	if (ops && ops->ordering_requires_timestamps &&
 	    ops->ordered_samples && !self->sample_id_all) {
 		dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
@@ -181,9 +167,6 @@ struct perf_session *perf_session__new(const char *filename, int mode,
 
 out:
 	return self;
-out_free:
-	free(self);
-	return NULL;
 out_delete:
 	perf_session__delete(self);
 	return NULL;
@@ -214,7 +197,6 @@ static void perf_session__delete_threads(struct perf_session *self)
 
 void perf_session__delete(struct perf_session *self)
 {
-	perf_header__exit(&self->header);
 	perf_session__destroy_kernel_maps(self);
 	perf_session__delete_dead_threads(self);
 	perf_session__delete_threads(self);
@@ -242,17 +224,16 @@ static bool symbol__match_parent_regex(struct symbol *sym)
 	return 0;
 }
 
-struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
-						   struct thread *thread,
-						   struct ip_callchain *chain,
-						   struct symbol **parent)
+int perf_session__resolve_callchain(struct perf_session *self,
+				    struct thread *thread,
+				    struct ip_callchain *chain,
+				    struct symbol **parent)
 {
 	u8 cpumode = PERF_RECORD_MISC_USER;
 	unsigned int i;
-	struct map_symbol *syms = calloc(chain->nr, sizeof(*syms));
+	int err;
 
-	if (!syms)
-		return NULL;
+	callchain_cursor_reset(&self->callchain_cursor);
 
 	for (i = 0; i < chain->nr; i++) {
 		u64 ip = chain->ips[i];
@@ -281,30 +262,33 @@ struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
 				*parent = al.sym;
 			if (!symbol_conf.use_callchain)
 				break;
-			syms[i].map = al.map;
-			syms[i].sym = al.sym;
 		}
+
+		err = callchain_cursor_append(&self->callchain_cursor,
+					      ip, al.map, al.sym);
+		if (err)
+			return err;
 	}
 
-	return syms;
+	return 0;
 }
 
-static int process_event_synth_stub(event_t *event __used,
+static int process_event_synth_stub(union perf_event *event __used,
 				    struct perf_session *session __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
 }
 
-static int process_event_stub(event_t *event __used,
-			      struct sample_data *sample __used,
+static int process_event_stub(union perf_event *event __used,
+			      struct perf_sample *sample __used,
 			      struct perf_session *session __used)
 {
 	dump_printf(": unhandled!\n");
 	return 0;
 }
 
-static int process_finished_round_stub(event_t *event __used,
+static int process_finished_round_stub(union perf_event *event __used,
 				       struct perf_session *session __used,
 				       struct perf_event_ops *ops __used)
 {
@@ -312,7 +296,7 @@ static int process_finished_round_stub(event_t *event __used,
 	return 0;
 }
 
-static int process_finished_round(event_t *event,
+static int process_finished_round(union perf_event *event,
 				  struct perf_session *session,
 				  struct perf_event_ops *ops);
 
@@ -329,7 +313,7 @@ static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
 	if (handler->exit == NULL)
 		handler->exit = process_event_stub;
 	if (handler->lost == NULL)
-		handler->lost = event__process_lost;
+		handler->lost = perf_event__process_lost;
 	if (handler->read == NULL)
 		handler->read = process_event_stub;
 	if (handler->throttle == NULL)
@@ -363,98 +347,98 @@ void mem_bswap_64(void *src, int byte_size)
 	}
 }
 
-static void event__all64_swap(event_t *self)
+static void perf_event__all64_swap(union perf_event *event)
 {
-	struct perf_event_header *hdr = &self->header;
-	mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr));
+	struct perf_event_header *hdr = &event->header;
+	mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr));
 }
 
-static void event__comm_swap(event_t *self)
+static void perf_event__comm_swap(union perf_event *event)
 {
-	self->comm.pid = bswap_32(self->comm.pid);
-	self->comm.tid = bswap_32(self->comm.tid);
+	event->comm.pid = bswap_32(event->comm.pid);
+	event->comm.tid = bswap_32(event->comm.tid);
 }
 
-static void event__mmap_swap(event_t *self)
+static void perf_event__mmap_swap(union perf_event *event)
 {
-	self->mmap.pid	 = bswap_32(self->mmap.pid);
-	self->mmap.tid	 = bswap_32(self->mmap.tid);
-	self->mmap.start = bswap_64(self->mmap.start);
-	self->mmap.len	 = bswap_64(self->mmap.len);
-	self->mmap.pgoff = bswap_64(self->mmap.pgoff);
+	event->mmap.pid	  = bswap_32(event->mmap.pid);
+	event->mmap.tid	  = bswap_32(event->mmap.tid);
+	event->mmap.start = bswap_64(event->mmap.start);
+	event->mmap.len	  = bswap_64(event->mmap.len);
+	event->mmap.pgoff = bswap_64(event->mmap.pgoff);
 }
 
-static void event__task_swap(event_t *self)
+static void perf_event__task_swap(union perf_event *event)
 {
-	self->fork.pid	= bswap_32(self->fork.pid);
-	self->fork.tid	= bswap_32(self->fork.tid);
-	self->fork.ppid	= bswap_32(self->fork.ppid);
-	self->fork.ptid	= bswap_32(self->fork.ptid);
-	self->fork.time	= bswap_64(self->fork.time);
+	event->fork.pid	 = bswap_32(event->fork.pid);
+	event->fork.tid	 = bswap_32(event->fork.tid);
+	event->fork.ppid = bswap_32(event->fork.ppid);
+	event->fork.ptid = bswap_32(event->fork.ptid);
+	event->fork.time = bswap_64(event->fork.time);
 }
 
-static void event__read_swap(event_t *self)
+static void perf_event__read_swap(union perf_event *event)
 {
-	self->read.pid		= bswap_32(self->read.pid);
-	self->read.tid		= bswap_32(self->read.tid);
-	self->read.value	= bswap_64(self->read.value);
-	self->read.time_enabled	= bswap_64(self->read.time_enabled);
-	self->read.time_running	= bswap_64(self->read.time_running);
-	self->read.id		= bswap_64(self->read.id);
+	event->read.pid		 = bswap_32(event->read.pid);
+	event->read.tid		 = bswap_32(event->read.tid);
+	event->read.value	 = bswap_64(event->read.value);
+	event->read.time_enabled = bswap_64(event->read.time_enabled);
+	event->read.time_running = bswap_64(event->read.time_running);
+	event->read.id		 = bswap_64(event->read.id);
 }
 
-static void event__attr_swap(event_t *self)
+static void perf_event__attr_swap(union perf_event *event)
 {
 	size_t size;
 
-	self->attr.attr.type		= bswap_32(self->attr.attr.type);
-	self->attr.attr.size		= bswap_32(self->attr.attr.size);
-	self->attr.attr.config		= bswap_64(self->attr.attr.config);
-	self->attr.attr.sample_period	= bswap_64(self->attr.attr.sample_period);
-	self->attr.attr.sample_type	= bswap_64(self->attr.attr.sample_type);
-	self->attr.attr.read_format	= bswap_64(self->attr.attr.read_format);
-	self->attr.attr.wakeup_events	= bswap_32(self->attr.attr.wakeup_events);
-	self->attr.attr.bp_type		= bswap_32(self->attr.attr.bp_type);
-	self->attr.attr.bp_addr		= bswap_64(self->attr.attr.bp_addr);
-	self->attr.attr.bp_len		= bswap_64(self->attr.attr.bp_len);
-
-	size = self->header.size;
-	size -= (void *)&self->attr.id - (void *)self;
-	mem_bswap_64(self->attr.id, size);
+	event->attr.attr.type		= bswap_32(event->attr.attr.type);
+	event->attr.attr.size		= bswap_32(event->attr.attr.size);
+	event->attr.attr.config		= bswap_64(event->attr.attr.config);
+	event->attr.attr.sample_period	= bswap_64(event->attr.attr.sample_period);
+	event->attr.attr.sample_type	= bswap_64(event->attr.attr.sample_type);
+	event->attr.attr.read_format	= bswap_64(event->attr.attr.read_format);
+	event->attr.attr.wakeup_events	= bswap_32(event->attr.attr.wakeup_events);
+	event->attr.attr.bp_type	= bswap_32(event->attr.attr.bp_type);
+	event->attr.attr.bp_addr	= bswap_64(event->attr.attr.bp_addr);
+	event->attr.attr.bp_len		= bswap_64(event->attr.attr.bp_len);
+
+	size = event->header.size;
+	size -= (void *)&event->attr.id - (void *)event;
+	mem_bswap_64(event->attr.id, size);
 }
 
-static void event__event_type_swap(event_t *self)
+static void perf_event__event_type_swap(union perf_event *event)
 {
-	self->event_type.event_type.event_id =
-		bswap_64(self->event_type.event_type.event_id);
+	event->event_type.event_type.event_id =
+		bswap_64(event->event_type.event_type.event_id);
 }
 
-static void event__tracing_data_swap(event_t *self)
+static void perf_event__tracing_data_swap(union perf_event *event)
 {
-	self->tracing_data.size = bswap_32(self->tracing_data.size);
+	event->tracing_data.size = bswap_32(event->tracing_data.size);
 }
 
-typedef void (*event__swap_op)(event_t *self);
-
-static event__swap_op event__swap_ops[] = {
-	[PERF_RECORD_MMAP]   = event__mmap_swap,
-	[PERF_RECORD_COMM]   = event__comm_swap,
-	[PERF_RECORD_FORK]   = event__task_swap,
-	[PERF_RECORD_EXIT]   = event__task_swap,
-	[PERF_RECORD_LOST]   = event__all64_swap,
-	[PERF_RECORD_READ]   = event__read_swap,
-	[PERF_RECORD_SAMPLE] = event__all64_swap,
-	[PERF_RECORD_HEADER_ATTR]   = event__attr_swap,
-	[PERF_RECORD_HEADER_EVENT_TYPE]   = event__event_type_swap,
-	[PERF_RECORD_HEADER_TRACING_DATA]   = event__tracing_data_swap,
-	[PERF_RECORD_HEADER_BUILD_ID]   = NULL,
-	[PERF_RECORD_HEADER_MAX]    = NULL,
+typedef void (*perf_event__swap_op)(union perf_event *event);
+
+static perf_event__swap_op perf_event__swap_ops[] = {
+	[PERF_RECORD_MMAP]		  = perf_event__mmap_swap,
+	[PERF_RECORD_COMM]		  = perf_event__comm_swap,
+	[PERF_RECORD_FORK]		  = perf_event__task_swap,
+	[PERF_RECORD_EXIT]		  = perf_event__task_swap,
+	[PERF_RECORD_LOST]		  = perf_event__all64_swap,
+	[PERF_RECORD_READ]		  = perf_event__read_swap,
+	[PERF_RECORD_SAMPLE]		  = perf_event__all64_swap,
+	[PERF_RECORD_HEADER_ATTR]	  = perf_event__attr_swap,
+	[PERF_RECORD_HEADER_EVENT_TYPE]	  = perf_event__event_type_swap,
+	[PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap,
+	[PERF_RECORD_HEADER_BUILD_ID]	  = NULL,
+	[PERF_RECORD_HEADER_MAX]	  = NULL,
 };
 
 struct sample_queue {
 	u64			timestamp;
 	u64			file_offset;
-	event_t			*event;
+	union perf_event	*event;
 	struct list_head	list;
 };
 
@@ -472,8 +456,8 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
 }
 
 static int perf_session_deliver_event(struct perf_session *session,
-				      event_t *event,
-				      struct sample_data *sample,
+				      union perf_event *event,
+				      struct perf_sample *sample,
 				      struct perf_event_ops *ops,
 				      u64 file_offset);
 
@@ -483,7 +467,7 @@ static void flush_sample_queue(struct perf_session *s,
 	struct ordered_samples *os = &s->ordered_samples;
 	struct list_head *head = &os->samples;
 	struct sample_queue *tmp, *iter;
-	struct sample_data sample;
+	struct perf_sample sample;
 	u64 limit = os->next_flush;
 	u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL;
 
@@ -494,7 +478,7 @@ static void flush_sample_queue(struct perf_session *s,
 		if (iter->timestamp > limit)
 			break;
 
-		event__parse_sample(iter->event, s, &sample);
+		perf_session__parse_sample(s, iter->event, &sample);
 		perf_session_deliver_event(s, iter->event, &sample, ops,
 					   iter->file_offset);
 
@@ -550,7 +534,7 @@ static void flush_sample_queue(struct perf_session *s,
  *      Flush every events below timestamp 7
  *      etc...
  */
-static int process_finished_round(event_t *event __used,
+static int process_finished_round(union perf_event *event __used,
 				  struct perf_session *session,
 				  struct perf_event_ops *ops)
 {
@@ -607,12 +591,12 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
 
 #define MAX_SAMPLE_BUFFER	(64 * 1024 / sizeof(struct sample_queue))
 
-static int perf_session_queue_event(struct perf_session *s, event_t *event,
-				    struct sample_data *data, u64 file_offset)
+static int perf_session_queue_event(struct perf_session *s, union perf_event *event,
+				    struct perf_sample *sample, u64 file_offset)
 {
 	struct ordered_samples *os = &s->ordered_samples;
 	struct list_head *sc = &os->sample_cache;
-	u64 timestamp = data->time;
+	u64 timestamp = sample->time;
 	struct sample_queue *new;
 
 	if (!timestamp || timestamp == ~0ULL)
@@ -648,7 +632,7 @@ static int perf_session_queue_event(struct perf_session *s, event_t *event,
 	return 0;
 }
 
-static void callchain__printf(struct sample_data *sample)
+static void callchain__printf(struct perf_sample *sample)
 {
 	unsigned int i;
 
@@ -660,8 +644,8 @@ static void callchain__printf(struct sample_data *sample)
 }
 
 static void perf_session__print_tstamp(struct perf_session *session,
-				       event_t *event,
-				       struct sample_data *sample)
+				       union perf_event *event,
+				       struct perf_sample *sample)
 {
 	if (event->header.type != PERF_RECORD_SAMPLE &&
 	    !session->sample_id_all) {
@@ -676,8 +660,8 @@ static void perf_session__print_tstamp(struct perf_session *session,
 		printf("%" PRIu64 " ", sample->time);
 }
 
-static void dump_event(struct perf_session *session, event_t *event,
-		       u64 file_offset, struct sample_data *sample)
+static void dump_event(struct perf_session *session, union perf_event *event,
+		       u64 file_offset, struct perf_sample *sample)
 {
 	if (!dump_trace)
 		return;
@@ -691,11 +675,11 @@ static void dump_event(struct perf_session *session, event_t *event,
 		perf_session__print_tstamp(session, event, sample);
 
 	printf("%#" PRIx64 " [%#x]: PERF_RECORD_%s", file_offset,
-	       event->header.size, event__get_event_name(event->header.type));
+	       event->header.size, perf_event__name(event->header.type));
 }
 
-static void dump_sample(struct perf_session *session, event_t *event,
-			struct sample_data *sample)
+static void dump_sample(struct perf_session *session, union perf_event *event,
+			struct perf_sample *sample)
 {
 	if (!dump_trace)
 		return;
@@ -709,8 +693,8 @@ static void dump_sample(struct perf_session *session, event_t *event,
 }
 
 static int perf_session_deliver_event(struct perf_session *session,
-				      event_t *event,
-				      struct sample_data *sample,
+				      union perf_event *event,
+				      struct perf_sample *sample,
 				      struct perf_event_ops *ops,
 				      u64 file_offset)
 {
@@ -743,7 +727,7 @@ static int perf_session_deliver_event(struct perf_session *session,
 }
 
 static int perf_session__preprocess_sample(struct perf_session *session,
-					   event_t *event, struct sample_data *sample)
+					   union perf_event *event, struct perf_sample *sample)
 {
 	if (event->header.type != PERF_RECORD_SAMPLE ||
 	    !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
@@ -758,7 +742,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,
 	return 0;
 }
 
-static int perf_session__process_user_event(struct perf_session *session, event_t *event,
+static int perf_session__process_user_event(struct perf_session *session, union perf_event *event,
 					    struct perf_event_ops *ops, u64 file_offset)
 {
 	dump_event(session, event, file_offset, NULL);
@@ -783,15 +767,16 @@ static int perf_session__process_user_event(struct perf_session *session, event_
 }
 
 static int perf_session__process_event(struct perf_session *session,
-				       event_t *event,
+				       union perf_event *event,
 				       struct perf_event_ops *ops,
 				       u64 file_offset)
 {
-	struct sample_data sample;
+	struct perf_sample sample;
 	int ret;
 
-	if (session->header.needs_swap && event__swap_ops[event->header.type])
-		event__swap_ops[event->header.type](event);
+	if (session->header.needs_swap &&
+	    perf_event__swap_ops[event->header.type])
+		perf_event__swap_ops[event->header.type](event);
 
 	if (event->header.type >= PERF_RECORD_HEADER_MAX)
 		return -EINVAL;
@@ -804,7 +789,7 @@ static int perf_session__process_event(struct perf_session *session,
 	/*
 	 * For all kernel events we get the sample data
 	 */
-	event__parse_sample(event, session, &sample);
+	perf_session__parse_sample(session, event, &sample);
 
 	/* Preprocess sample records - precheck callchains */
 	if (perf_session__preprocess_sample(session, event, &sample))
@@ -843,7 +828,7 @@ static struct thread *perf_session__register_idle_thread(struct perf_session *se
 static void perf_session__warn_about_errors(const struct perf_session *session,
 					    const struct perf_event_ops *ops)
 {
-	if (ops->lost == event__process_lost &&
+	if (ops->lost == perf_event__process_lost &&
 	    session->hists.stats.total_lost != 0) {
 		ui__warning("Processed %" PRIu64 " events and LOST %" PRIu64
 			    "!\n\nCheck IO/CPU overload!\n\n",
@@ -875,7 +860,7 @@ volatile int session_done;
 static int __perf_session__process_pipe_events(struct perf_session *self,
 					       struct perf_event_ops *ops)
 {
-	event_t event;
+	union perf_event event;
 	uint32_t size;
 	int skip = 0;
 	u64 head;
@@ -956,7 +941,7 @@ int __perf_session__process_events(struct perf_session *session,
 	struct ui_progress *progress;
 	size_t	page_size, mmap_size;
 	char *buf, *mmaps[8];
-	event_t *event;
+	union perf_event *event;
 	uint32_t size;
 
 	perf_event_ops__fill_defaults(ops);
@@ -1001,7 +986,7 @@ remap:
 	file_pos = file_offset + head;
 
 more:
-	event = (event_t *)(buf + head);
+	event = (union perf_event *)(buf + head);
 
 	if (session->header.needs_swap)
 		perf_event_header__bswap(&event->header);
@@ -1134,3 +1119,79 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
 	size_t ret = machine__fprintf_dsos_buildid(&self->host_machine, fp, with_hits);
 	return ret + machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
 }
+
+size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
+{
+	struct perf_evsel *pos;
+	size_t ret = fprintf(fp, "Aggregated stats:\n");
+
+	ret += hists__fprintf_nr_events(&session->hists, fp);
+
+	list_for_each_entry(pos, &session->evlist->entries, node) {
+		ret += fprintf(fp, "%s stats:\n", event_name(pos));
+		ret += hists__fprintf_nr_events(&pos->hists, fp);
+	}
+
+	return ret;
+}
+
+void perf_session__print_symbols(union perf_event *event,
+				struct perf_sample *sample,
+				struct perf_session *session)
+{
+	struct addr_location al;
+	const char *symname, *dsoname;
+	struct callchain_cursor *cursor = &session->callchain_cursor;
+	struct callchain_cursor_node *node;
+
+	if (perf_event__preprocess_sample(event, session, &al, sample,
+					  NULL) < 0) {
+		error("problem processing %d event, skipping it.\n",
+			event->header.type);
+		return;
+	}
+
+	if (symbol_conf.use_callchain && sample->callchain) {
+
+		if (perf_session__resolve_callchain(session, al.thread,
+						sample->callchain, NULL) != 0) {
+			if (verbose)
+				error("Failed to resolve callchain. Skipping\n");
+			return;
+		}
+		callchain_cursor_commit(cursor);
+
+		while (1) {
+			node = callchain_cursor_current(cursor);
+			if (!node)
+				break;
+
+			if (node->sym && node->sym->name)
+				symname = node->sym->name;
+			else
+				symname = "";
+
+			if (node->map && node->map->dso && node->map->dso->name)
+				dsoname = node->map->dso->name;
+			else
+				dsoname = "";
+
+			printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
+
+			callchain_cursor_advance(cursor);
+		}
+
+	} else {
+		if (al.sym && al.sym->name)
+			symname = al.sym->name;
+		else
+			symname = "";
+
+		if (al.map && al.map->dso && al.map->dso->name)
+			dsoname = al.map->dso->name;
+		else
+			dsoname = "";
+
+		printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
+	}
+}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index decd83f..0b3c9af 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -34,12 +34,12 @@ struct perf_session {
 	struct thread		*last_match;
 	struct machine		host_machine;
 	struct rb_root		machines;
-	struct rb_root		hists_tree;
+	struct perf_evlist	*evlist;
 	/*
-	 * FIXME: should point to the first entry in hists_tree and
-	 *        be a hists instance. Right now its only 'report'
-	 *        that is using ->hists_tree while all the rest use
-	 *        ->hists.
+	 * FIXME: Need to split this up further, we need global
+	 *	  stats + per event stats. 'perf diff' also needs
+	 *	  to properly support multiple events in a single
+	 *	  perf.data file.
 	 */
 	struct hists		hists;
 	u64			sample_type;
@@ -51,15 +51,17 @@ struct perf_session {
 	int			cwdlen;
 	char			*cwd;
 	struct ordered_samples	ordered_samples;
-	char filename[0];
+	struct callchain_cursor	callchain_cursor;
+	char			filename[0];
 };
 
 struct perf_event_ops;
 
-typedef int (*event_op)(event_t *self, struct sample_data *sample,
+typedef int (*event_op)(union perf_event *self, struct perf_sample *sample,
 			struct perf_session *session);
-typedef int (*event_synth_op)(event_t *self, struct perf_session *session);
-typedef int (*event_op2)(event_t *self, struct perf_session *session,
+typedef int (*event_synth_op)(union perf_event *self,
+			      struct perf_session *session);
+typedef int (*event_op2)(union perf_event *self, struct perf_session *session,
 			 struct perf_event_ops *ops);
 
 struct perf_event_ops {
@@ -94,10 +96,10 @@ int __perf_session__process_events(struct perf_session *self,
 int perf_session__process_events(struct perf_session *self,
 				 struct perf_event_ops *event_ops);
 
-struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
-						   struct thread *thread,
-						   struct ip_callchain *chain,
-						   struct symbol **parent);
+int perf_session__resolve_callchain(struct perf_session *self,
+				    struct thread *thread,
+				    struct ip_callchain *chain,
+				    struct symbol **parent);
 
 bool perf_session__has_traces(struct perf_session *self, const char *msg);
 
@@ -110,8 +112,6 @@ void mem_bswap_64(void *src, int byte_size);
 int perf_session__create_kernel_maps(struct perf_session *self);
 
 void perf_session__update_sample_type(struct perf_session *self);
-void perf_session__set_sample_id_all(struct perf_session *session, bool value);
-void perf_session__set_sample_type(struct perf_session *session, u64 type);
 void perf_session__remove_thread(struct perf_session *self, struct thread *th);
 
 static inline
@@ -149,9 +149,18 @@ size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
 size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
 					  FILE *fp, bool with_hits);
 
-static inline
-size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp)
+size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
+
+static inline int perf_session__parse_sample(struct perf_session *session,
+					     const union perf_event *event,
+					     struct perf_sample *sample)
 {
-	return hists__fprintf_nr_events(&self->hists, fp);
+	return perf_event__parse_sample(event, session->sample_type,
+					session->sample_id_all, sample);
 }
+
+void perf_session__print_symbols(union perf_event *event,
+				 struct perf_sample *sample,
+				 struct perf_session *session);
+
 #endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
new file mode 100644
index 0000000..e24ffad
--- /dev/null
+++ b/tools/perf/util/setup.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python2
+
+from distutils.core import setup, Extension
+
+perf = Extension('perf',
+		  sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
+			     'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
+			     'util/util.c', 'util/xyarray.c', 'util/cgroup.c'],
+		  include_dirs = ['util/include'],
+		  extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings'])
+
+setup(name='perf',
+      version='0.1',
+      description='Interface with the Linux profiling infrastructure',
+      author='Arnaldo Carvalho de Melo',
+      author_email='acme@redhat.com',
+      license='GPLv2',
+      url='http://perf.wiki.kernel.org',
+      ext_modules=[perf])
diff --git a/tools/perf/util/strfilter.c b/tools/perf/util/strfilter.c
new file mode 100644
index 0000000..834c8eb
--- /dev/null
+++ b/tools/perf/util/strfilter.c
@@ -0,0 +1,199 @@
+#include "util.h"
+#include "string.h"
+#include "strfilter.h"
+
+/* Operators */
+static const char *OP_and	= "&";	/* Logical AND */
+static const char *OP_or	= "|";	/* Logical OR */
+static const char *OP_not	= "!";	/* Logical NOT */
+
+#define is_operator(c)	((c) == '|' || (c) == '&' || (c) == '!')
+#define is_separator(c)	(is_operator(c) || (c) == '(' || (c) == ')')
+
+static void strfilter_node__delete(struct strfilter_node *self)
+{
+	if (self) {
+		if (self->p && !is_operator(*self->p))
+			free((char *)self->p);
+		strfilter_node__delete(self->l);
+		strfilter_node__delete(self->r);
+		free(self);
+	}
+}
+
+void strfilter__delete(struct strfilter *self)
+{
+	if (self) {
+		strfilter_node__delete(self->root);
+		free(self);
+	}
+}
+
+static const char *get_token(const char *s, const char **e)
+{
+	const char *p;
+
+	while (isspace(*s))	/* Skip spaces */
+		s++;
+
+	if (*s == '\0') {
+		p = s;
+		goto end;
+	}
+
+	p = s + 1;
+	if (!is_separator(*s)) {
+		/* End search */
+retry:
+		while (*p && !is_separator(*p) && !isspace(*p))
+			p++;
+		/* Escape and special case: '!' is also used in glob pattern */
+		if (*(p - 1) == '\\' || (*p == '!' && *(p - 1) == '[')) {
+			p++;
+			goto retry;
+		}
+	}
+end:
+	*e = p;
+	return s;
+}
+
+static struct strfilter_node *strfilter_node__alloc(const char *op,
+						    struct strfilter_node *l,
+						    struct strfilter_node *r)
+{
+	struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node));
+
+	if (ret) {
+		ret->p = op;
+		ret->l = l;
+		ret->r = r;
+	}
+
+	return ret;
+}
+
+static struct strfilter_node *strfilter_node__new(const char *s,
+						  const char **ep)
+{
+	struct strfilter_node root, *cur, *last_op;
+	const char *e;
+
+	if (!s)
+		return NULL;
+
+	memset(&root, 0, sizeof(root));
+	last_op = cur = &root;
+
+	s = get_token(s, &e);
+	while (*s != '\0' && *s != ')') {
+		switch (*s) {
+		case '&':	/* Exchg last OP->r with AND */
+			if (!cur->r || !last_op->r)
+				goto error;
+			cur = strfilter_node__alloc(OP_and, last_op->r, NULL);
+			if (!cur)
+				goto nomem;
+			last_op->r = cur;
+			last_op = cur;
+			break;
+		case '|':	/* Exchg the root with OR */
+			if (!cur->r || !root.r)
+				goto error;
+			cur = strfilter_node__alloc(OP_or, root.r, NULL);
+			if (!cur)
+				goto nomem;
+			root.r = cur;
+			last_op = cur;
+			break;
+		case '!':	/* Add NOT as a leaf node */
+			if (cur->r)
+				goto error;
+			cur->r = strfilter_node__alloc(OP_not, NULL, NULL);
+			if (!cur->r)
+				goto nomem;
+			cur = cur->r;
+			break;
+		case '(':	/* Recursively parses inside the parenthesis */
+			if (cur->r)
+				goto error;
+			cur->r = strfilter_node__new(s + 1, &s);
+			if (!s)
+				goto nomem;
+			if (!cur->r || *s != ')')
+				goto error;
+			e = s + 1;
+			break;
+		default:
+			if (cur->r)
+				goto error;
+			cur->r = strfilter_node__alloc(NULL, NULL, NULL);
+			if (!cur->r)
+				goto nomem;
+			cur->r->p = strndup(s, e - s);
+			if (!cur->r->p)
+				goto nomem;
+		}
+		s = get_token(e, &e);
+	}
+	if (!cur->r)
+		goto error;
+	*ep = s;
+	return root.r;
+nomem:
+	s = NULL;
+error:
+	*ep = s;
+	strfilter_node__delete(root.r);
+	return NULL;
+}
+
+/*
+ * Parse filter rule and return new strfilter.
+ * Return NULL if fail, and *ep == NULL if memory allocation failed.
+ */
+struct strfilter *strfilter__new(const char *rules, const char **err)
+{
+	struct strfilter *ret = zalloc(sizeof(struct strfilter));
+	const char *ep = NULL;
+
+	if (ret)
+		ret->root = strfilter_node__new(rules, &ep);
+
+	if (!ret || !ret->root || *ep != '\0') {
+		if (err)
+			*err = ep;
+		strfilter__delete(ret);
+		ret = NULL;
+	}
+
+	return ret;
+}
+
+static bool strfilter_node__compare(struct strfilter_node *self,
+				    const char *str)
+{
+	if (!self || !self->p)
+		return false;
+
+	switch (*self->p) {
+	case '|':	/* OR */
+		return strfilter_node__compare(self->l, str) ||
+			strfilter_node__compare(self->r, str);
+	case '&':	/* AND */
+		return strfilter_node__compare(self->l, str) &&
+			strfilter_node__compare(self->r, str);
+	case '!':	/* NOT */
+		return !strfilter_node__compare(self->r, str);
+	default:
+		return strglobmatch(str, self->p);
+	}
+}
+
+/* Return true if STR matches the filter rules */
+bool strfilter__compare(struct strfilter *self, const char *str)
+{
+	if (!self)
+		return false;
+	return strfilter_node__compare(self->root, str);
+}
diff --git a/tools/perf/util/strfilter.h b/tools/perf/util/strfilter.h
new file mode 100644
index 0000000..00f58a7
--- /dev/null
+++ b/tools/perf/util/strfilter.h
@@ -0,0 +1,48 @@
+#ifndef __PERF_STRFILTER_H
+#define __PERF_STRFILTER_H
+/* General purpose glob matching filter */
+
+#include <linux/list.h>
+#include <stdbool.h>
+
+/* A node of string filter */
+struct strfilter_node {
+	struct strfilter_node *l;	/* Tree left branche (for &,|) */
+	struct strfilter_node *r;	/* Tree right branche (for !,&,|) */
+	const char *p;		/* Operator or rule */
+};
+
+/* String filter */
+struct strfilter {
+	struct strfilter_node *root;
+};
+
+/**
+ * strfilter__new - Create a new string filter
+ * @rules: Filter rule, which is a combination of glob expressions.
+ * @err: Pointer which points an error detected on @rules
+ *
+ * Parse @rules and return new strfilter. Return NULL if an error detected.
+ * In that case, *@err will indicate where it is detected, and *@err is NULL
+ * if a memory allocation is failed.
+ */
+struct strfilter *strfilter__new(const char *rules, const char **err);
+
+/**
+ * strfilter__compare - compare given string and a string filter
+ * @self: String filter
+ * @str: target string
+ *
+ * Compare @str and @self. Return true if the str match the rule
+ */
+bool strfilter__compare(struct strfilter *self, const char *str);
+
+/**
+ * strfilter__delete - delete a string filter
+ * @self: String filter to delete
+ *
+ * Delete @self.
+ */
+void strfilter__delete(struct strfilter *self);
+
+#endif
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b1bf490..651dbfe 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -207,8 +207,7 @@ struct dso *dso__new(const char *name)
 		dso__set_short_name(self, self->name);
 		for (i = 0; i < MAP__NR_TYPES; ++i)
 			self->symbols[i] = self->symbol_names[i] = RB_ROOT;
-		self->slen_calculated = 0;
-		self->origin = DSO__ORIG_NOT_FOUND;
+		self->symtab_type = SYMTAB__NOT_FOUND;
 		self->loaded = 0;
 		self->sorted_by_name = 0;
 		self->has_build_id = 0;
@@ -681,9 +680,9 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
 		return -1;
 
 	if (self->kernel == DSO_TYPE_GUEST_KERNEL)
-		self->origin = DSO__ORIG_GUEST_KERNEL;
+		self->symtab_type = SYMTAB__GUEST_KALLSYMS;
 	else
-		self->origin = DSO__ORIG_KERNEL;
+		self->symtab_type = SYMTAB__KALLSYMS;
 
 	return dso__split_kallsyms(self, map, filter);
 }
@@ -1205,7 +1204,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
 				}
 				curr_map->map_ip = identity__map_ip;
 				curr_map->unmap_ip = identity__map_ip;
-				curr_dso->origin = self->origin;
+				curr_dso->symtab_type = self->symtab_type;
 				map_groups__insert(kmap->kmaps, curr_map);
 				dsos__add(&self->node, curr_dso);
 				dso__set_loaded(curr_dso, map->type);
@@ -1431,21 +1430,21 @@ out:
 char dso__symtab_origin(const struct dso *self)
 {
 	static const char origin[] = {
-		[DSO__ORIG_KERNEL] =   'k',
-		[DSO__ORIG_JAVA_JIT] = 'j',
-		[DSO__ORIG_BUILD_ID_CACHE] = 'B',
-		[DSO__ORIG_FEDORA] =   'f',
-		[DSO__ORIG_UBUNTU] =   'u',
-		[DSO__ORIG_BUILDID] =  'b',
-		[DSO__ORIG_DSO] =      'd',
-		[DSO__ORIG_KMODULE] =  'K',
-		[DSO__ORIG_GUEST_KERNEL] =  'g',
-		[DSO__ORIG_GUEST_KMODULE] =  'G',
+		[SYMTAB__KALLSYMS]	      = 'k',
+		[SYMTAB__JAVA_JIT]	      = 'j',
+		[SYMTAB__BUILD_ID_CACHE]      = 'B',
+		[SYMTAB__FEDORA_DEBUGINFO]    = 'f',
+		[SYMTAB__UBUNTU_DEBUGINFO]    = 'u',
+		[SYMTAB__BUILDID_DEBUGINFO]   = 'b',
+		[SYMTAB__SYSTEM_PATH_DSO]     = 'd',
+		[SYMTAB__SYSTEM_PATH_KMODULE] = 'K',
+		[SYMTAB__GUEST_KALLSYMS]      =  'g',
+		[SYMTAB__GUEST_KMODULE]	      =  'G',
 	};
 
-	if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND)
+	if (self == NULL || self->symtab_type == SYMTAB__NOT_FOUND)
 		return '!';
-	return origin[self->origin];
+	return origin[self->symtab_type];
 }
 
 int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
@@ -1478,8 +1477,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
 
 	if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
 		ret = dso__load_perf_map(self, map, filter);
-		self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT :
-					 DSO__ORIG_NOT_FOUND;
+		self->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
+					      SYMTAB__NOT_FOUND;
 		return ret;
 	}
 
@@ -1487,26 +1486,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
 	 * On the first pass, only load images if they have a full symtab.
 	 * Failing that, do a second pass where we accept .dynsym also
 	 */
-	for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1;
-	     self->origin != DSO__ORIG_NOT_FOUND;
-	     self->origin++) {
-		switch (self->origin) {
-		case DSO__ORIG_BUILD_ID_CACHE:
+	for (self->symtab_type = SYMTAB__BUILD_ID_CACHE, want_symtab = 1;
+	     self->symtab_type != SYMTAB__NOT_FOUND;
+	     self->symtab_type++) {
+		switch (self->symtab_type) {
+		case SYMTAB__BUILD_ID_CACHE:
 			/* skip the locally configured cache if a symfs is given */
 			if (symbol_conf.symfs[0] ||
 			    (dso__build_id_filename(self, name, size) == NULL)) {
 				continue;
 			}
 			break;
-		case DSO__ORIG_FEDORA:
+		case SYMTAB__FEDORA_DEBUGINFO:
 			snprintf(name, size, "%s/usr/lib/debug%s.debug",
 				 symbol_conf.symfs, self->long_name);
 			break;
-		case DSO__ORIG_UBUNTU:
+		case SYMTAB__UBUNTU_DEBUGINFO:
 			snprintf(name, size, "%s/usr/lib/debug%s",
 				 symbol_conf.symfs, self->long_name);
 			break;
-		case DSO__ORIG_BUILDID: {
+		case SYMTAB__BUILDID_DEBUGINFO: {
 			char build_id_hex[BUILD_ID_SIZE * 2 + 1];
 
 			if (!self->has_build_id)
@@ -1520,20 +1519,20 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
 				 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
 			}
 			break;
-		case DSO__ORIG_DSO:
+		case SYMTAB__SYSTEM_PATH_DSO:
 			snprintf(name, size, "%s%s",
 			     symbol_conf.symfs, self->long_name);
 			break;
-		case DSO__ORIG_GUEST_KMODULE:
-			if (map->groups && map->groups->machine)
-				root_dir = map->groups->machine->root_dir;
+		case SYMTAB__GUEST_KMODULE:
+			if (map->groups && machine)
+				root_dir = machine->root_dir;
 			else
 				root_dir = "";
 			snprintf(name, size, "%s%s%s", symbol_conf.symfs,
 				 root_dir, self->long_name);
 			break;
 
-		case DSO__ORIG_KMODULE:
+		case SYMTAB__SYSTEM_PATH_KMODULE:
 			snprintf(name, size, "%s%s", symbol_conf.symfs,
 				 self->long_name);
 			break;
@@ -1545,7 +1544,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
 			 */
 			if (want_symtab) {
 				want_symtab = 0;
-				self->origin = DSO__ORIG_BUILD_ID_CACHE;
+				self->symtab_type = SYMTAB__BUILD_ID_CACHE;
 			} else
 				continue;
 		}
@@ -1758,9 +1757,9 @@ struct map *machine__new_module(struct machine *self, u64 start,
 		return NULL;
 
 	if (machine__is_host(self))
-		dso->origin = DSO__ORIG_KMODULE;
+		dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE;
 	else
-		dso->origin = DSO__ORIG_GUEST_KMODULE;
+		dso->symtab_type = SYMTAB__GUEST_KMODULE;
 	map_groups__insert(&self->kmaps, map);
 	return map;
 }
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 670cd1c..713b0b4 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -48,12 +48,17 @@ char *strxfrchar(char *s, char from, char to);
 
 #define BUILD_ID_SIZE 20
 
+/** struct symbol - symtab entry
+ *
+ * @ignore - resolvable but tools ignore it (e.g. idle routines)
+ */
 struct symbol {
 	struct rb_node	rb_node;
 	u64		start;
 	u64		end;
 	u16		namelen;
 	u8		binding;
+	bool		ignore;
 	char		name[0];
 };
 
@@ -132,13 +137,12 @@ struct dso {
 	struct rb_root	 symbol_names[MAP__NR_TYPES];
 	enum dso_kernel_type	kernel;
 	u8		 adjust_symbols:1;
-	u8		 slen_calculated:1;
 	u8		 has_build_id:1;
 	u8		 hit:1;
 	u8		 annotate_warned:1;
 	u8		 sname_alloc:1;
 	u8		 lname_alloc:1;
-	unsigned char	 origin;
+	unsigned char	 symtab_type;
 	u8		 sorted_by_name;
 	u8		 loaded;
 	u8		 build_id[BUILD_ID_SIZE];
@@ -189,18 +193,18 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
 size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp);
 size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
 
-enum dso_origin {
-	DSO__ORIG_KERNEL = 0,
-	DSO__ORIG_GUEST_KERNEL,
-	DSO__ORIG_JAVA_JIT,
-	DSO__ORIG_BUILD_ID_CACHE,
-	DSO__ORIG_FEDORA,
-	DSO__ORIG_UBUNTU,
-	DSO__ORIG_BUILDID,
-	DSO__ORIG_DSO,
-	DSO__ORIG_GUEST_KMODULE,
-	DSO__ORIG_KMODULE,
-	DSO__ORIG_NOT_FOUND,
+enum symtab_type {
+	SYMTAB__KALLSYMS = 0,
+	SYMTAB__GUEST_KALLSYMS,
+	SYMTAB__JAVA_JIT,
+	SYMTAB__BUILD_ID_CACHE,
+	SYMTAB__FEDORA_DEBUGINFO,
+	SYMTAB__UBUNTU_DEBUGINFO,
+	SYMTAB__BUILDID_DEBUGINFO,
+	SYMTAB__SYSTEM_PATH_DSO,
+	SYMTAB__GUEST_KMODULE,
+	SYMTAB__SYSTEM_PATH_KMODULE,
+	SYMTAB__NOT_FOUND,
 };
 
 char dso__symtab_origin(const struct dso *self);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 00f4ead..d5d3b22 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,61 +7,6 @@
 #include "util.h"
 #include "debug.h"
 
-/* Skip "." and ".." directories */
-static int filter(const struct dirent *dir)
-{
-	if (dir->d_name[0] == '.')
-		return 0;
-	else
-		return 1;
-}
-
-struct thread_map *thread_map__new_by_pid(pid_t pid)
-{
-	struct thread_map *threads;
-	char name[256];
-	int items;
-	struct dirent **namelist = NULL;
-	int i;
-
-	sprintf(name, "/proc/%d/task", pid);
-	items = scandir(name, &namelist, filter, NULL);
-	if (items <= 0)
-                return NULL;
-
-	threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
-	if (threads != NULL) {
-		for (i = 0; i < items; i++)
-			threads->map[i] = atoi(namelist[i]->d_name);
-		threads->nr = items;
-	}
-
-	for (i=0; i<items; i++)
-		free(namelist[i]);
-	free(namelist);
-
-	return threads;
-}
-
-struct thread_map *thread_map__new_by_tid(pid_t tid)
-{
-	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
-
-	if (threads != NULL) {
-		threads->map[0] = tid;
-		threads->nr	= 1;
-	}
-
-	return threads;
-}
-
-struct thread_map *thread_map__new(pid_t pid, pid_t tid)
-{
-	if (pid != -1)
-		return thread_map__new_by_pid(pid);
-	return thread_map__new_by_tid(tid);
-}
-
 static struct thread *thread__new(pid_t pid)
 {
 	struct thread *self = zalloc(sizeof(*self));
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index d757410..e5f2401 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -18,24 +18,10 @@ struct thread {
 	int			comm_len;
 };
 
-struct thread_map {
-	int nr;
-	int map[];
-};
-
 struct perf_session;
 
 void thread__delete(struct thread *self);
 
-struct thread_map *thread_map__new_by_pid(pid_t pid);
-struct thread_map *thread_map__new_by_tid(pid_t tid);
-struct thread_map *thread_map__new(pid_t pid, pid_t tid);
-
-static inline void thread_map__delete(struct thread_map *threads)
-{
-	free(threads);
-}
-
 int thread__set_comm(struct thread *self, const char *comm);
 int thread__comm_len(struct thread *self);
 struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
new file mode 100644
index 0000000..a5df131
--- /dev/null
+++ b/tools/perf/util/thread_map.c
@@ -0,0 +1,64 @@
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "thread_map.h"
+
+/* Skip "." and ".." directories */
+static int filter(const struct dirent *dir)
+{
+	if (dir->d_name[0] == '.')
+		return 0;
+	else
+		return 1;
+}
+
+struct thread_map *thread_map__new_by_pid(pid_t pid)
+{
+	struct thread_map *threads;
+	char name[256];
+	int items;
+	struct dirent **namelist = NULL;
+	int i;
+
+	sprintf(name, "/proc/%d/task", pid);
+	items = scandir(name, &namelist, filter, NULL);
+	if (items <= 0)
+                return NULL;
+
+	threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
+	if (threads != NULL) {
+		for (i = 0; i < items; i++)
+			threads->map[i] = atoi(namelist[i]->d_name);
+		threads->nr = items;
+	}
+
+	for (i=0; i<items; i++)
+		free(namelist[i]);
+	free(namelist);
+
+	return threads;
+}
+
+struct thread_map *thread_map__new_by_tid(pid_t tid)
+{
+	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
+
+	if (threads != NULL) {
+		threads->map[0] = tid;
+		threads->nr	= 1;
+	}
+
+	return threads;
+}
+
+struct thread_map *thread_map__new(pid_t pid, pid_t tid)
+{
+	if (pid != -1)
+		return thread_map__new_by_pid(pid);
+	return thread_map__new_by_tid(tid);
+}
+
+void thread_map__delete(struct thread_map *threads)
+{
+	free(threads);
+}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
new file mode 100644
index 0000000..3cb9073
--- /dev/null
+++ b/tools/perf/util/thread_map.h
@@ -0,0 +1,15 @@
+#ifndef __PERF_THREAD_MAP_H
+#define __PERF_THREAD_MAP_H
+
+#include <sys/types.h>
+
+struct thread_map {
+	int nr;
+	int map[];
+};
+
+struct thread_map *thread_map__new_by_pid(pid_t pid);
+struct thread_map *thread_map__new_by_tid(pid_t tid);
+struct thread_map *thread_map__new(pid_t pid, pid_t tid);
+void thread_map__delete(struct thread_map *threads);
+#endif	/* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
new file mode 100644
index 0000000..a11f607
--- /dev/null
+++ b/tools/perf/util/top.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Refactored from builtin-top.c, see that files for further copyright notes.
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+
+#include "cpumap.h"
+#include "event.h"
+#include "evlist.h"
+#include "evsel.h"
+#include "parse-events.h"
+#include "symbol.h"
+#include "top.h"
+#include <inttypes.h>
+
+/*
+ * Ordering weight: count-1 * count-2 * ... / count-n
+ */
+static double sym_weight(const struct sym_entry *sym, struct perf_top *top)
+{
+	double weight = sym->snap_count;
+	int counter;
+
+	if (!top->display_weighted)
+		return weight;
+
+	for (counter = 1; counter < top->evlist->nr_entries - 1; counter++)
+		weight *= sym->count[counter];
+
+	weight /= (sym->count[counter] + 1);
+
+	return weight;
+}
+
+static void perf_top__remove_active_sym(struct perf_top *top, struct sym_entry *syme)
+{
+	pthread_mutex_lock(&top->active_symbols_lock);
+	list_del_init(&syme->node);
+	pthread_mutex_unlock(&top->active_symbols_lock);
+}
+
+static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
+{
+	struct rb_node **p = &tree->rb_node;
+	struct rb_node *parent = NULL;
+	struct sym_entry *iter;
+
+	while (*p != NULL) {
+		parent = *p;
+		iter = rb_entry(parent, struct sym_entry, rb_node);
+
+		if (se->weight > iter->weight)
+			p = &(*p)->rb_left;
+		else
+			p = &(*p)->rb_right;
+	}
+
+	rb_link_node(&se->rb_node, parent, p);
+	rb_insert_color(&se->rb_node, tree);
+}
+
+#define SNPRINTF(buf, size, fmt, args...) \
+({ \
+	size_t r = snprintf(buf, size, fmt, ## args); \
+	r > size ?  size : r; \
+})
+
+size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
+{
+	struct perf_evsel *counter;
+	float samples_per_sec = top->samples / top->delay_secs;
+	float ksamples_per_sec = top->kernel_samples / top->delay_secs;
+	float esamples_percent = (100.0 * top->exact_samples) / top->samples;
+	size_t ret = 0;
+
+	if (!perf_guest) {
+		ret = SNPRINTF(bf, size,
+			       "   PerfTop:%8.0f irqs/sec  kernel:%4.1f%%"
+			       "  exact: %4.1f%% [", samples_per_sec,
+			       100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
+					samples_per_sec)),
+				esamples_percent);
+	} else {
+		float us_samples_per_sec = top->us_samples / top->delay_secs;
+		float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs;
+		float guest_us_samples_per_sec = top->guest_us_samples / top->delay_secs;
+
+		ret = SNPRINTF(bf, size,
+			       "   PerfTop:%8.0f irqs/sec  kernel:%4.1f%% us:%4.1f%%"
+			       " guest kernel:%4.1f%% guest us:%4.1f%%"
+			       " exact: %4.1f%% [", samples_per_sec,
+			       100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) /
+						 samples_per_sec)),
+			       100.0 - (100.0 * ((samples_per_sec - us_samples_per_sec) /
+						 samples_per_sec)),
+			       100.0 - (100.0 * ((samples_per_sec -
+						  guest_kernel_samples_per_sec) /
+						 samples_per_sec)),
+			       100.0 - (100.0 * ((samples_per_sec -
+						  guest_us_samples_per_sec) /
+						 samples_per_sec)),
+			       esamples_percent);
+	}
+
+	if (top->evlist->nr_entries == 1 || !top->display_weighted) {
+		struct perf_evsel *first;
+		first = list_entry(top->evlist->entries.next, struct perf_evsel, node);
+		ret += SNPRINTF(bf + ret, size - ret, "%" PRIu64 "%s ",
+				(uint64_t)first->attr.sample_period,
+				top->freq ? "Hz" : "");
+	}
+
+	if (!top->display_weighted) {
+		ret += SNPRINTF(bf + ret, size - ret, "%s",
+				event_name(top->sym_evsel));
+	} else {
+		/*
+		 * Don't let events eat all the space. Leaving 30 bytes
+		 * for the rest should be enough.
+		 */
+		size_t last_pos = size - 30;
+
+		list_for_each_entry(counter, &top->evlist->entries, node) {
+			ret += SNPRINTF(bf + ret, size - ret, "%s%s",
+					counter->idx ? "/" : "",
+					event_name(counter));
+			if (ret > last_pos) {
+				sprintf(bf + last_pos - 3, "..");
+				ret = last_pos - 1;
+				break;
+			}
+		}
+	}
+
+	ret += SNPRINTF(bf + ret, size - ret, "], ");
+
+	if (top->target_pid != -1)
+		ret += SNPRINTF(bf + ret, size - ret, " (target_pid: %d",
+				top->target_pid);
+	else if (top->target_tid != -1)
+		ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d",
+				top->target_tid);
+	else
+		ret += SNPRINTF(bf + ret, size - ret, " (all");
+
+	if (top->cpu_list)
+		ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
+				top->evlist->cpus->nr > 1 ? "s" : "", top->cpu_list);
+	else {
+		if (top->target_tid != -1)
+			ret += SNPRINTF(bf + ret, size - ret, ")");
+		else
+			ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
+					top->evlist->cpus->nr,
+					top->evlist->cpus->nr > 1 ? "s" : "");
+	}
+
+	return ret;
+}
+
+void perf_top__reset_sample_counters(struct perf_top *top)
+{
+	top->samples = top->us_samples = top->kernel_samples =
+	top->exact_samples = top->guest_kernel_samples =
+	top->guest_us_samples = 0;
+}
+
+float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
+{
+	struct sym_entry *syme, *n;
+	float sum_ksamples = 0.0;
+	int snap = !top->display_weighted ? top->sym_evsel->idx : 0, j;
+
+	/* Sort the active symbols */
+	pthread_mutex_lock(&top->active_symbols_lock);
+	syme = list_entry(top->active_symbols.next, struct sym_entry, node);
+	pthread_mutex_unlock(&top->active_symbols_lock);
+
+	top->rb_entries = 0;
+	list_for_each_entry_safe_from(syme, n, &top->active_symbols, node) {
+		syme->snap_count = syme->count[snap];
+		if (syme->snap_count != 0) {
+
+			if ((top->hide_user_symbols &&
+			     syme->map->dso->kernel == DSO_TYPE_USER) ||
+			    (top->hide_kernel_symbols &&
+			     syme->map->dso->kernel == DSO_TYPE_KERNEL)) {
+				perf_top__remove_active_sym(top, syme);
+				continue;
+			}
+			syme->weight = sym_weight(syme, top);
+
+			if ((int)syme->snap_count >= top->count_filter) {
+				rb_insert_active_sym(root, syme);
+				++top->rb_entries;
+			}
+			sum_ksamples += syme->snap_count;
+
+			for (j = 0; j < top->evlist->nr_entries; j++)
+				syme->count[j] = top->zero ? 0 : syme->count[j] * 7 / 8;
+		} else
+			perf_top__remove_active_sym(top, syme);
+	}
+
+	return sum_ksamples;
+}
+
+/*
+ * Find the longest symbol name that will be displayed
+ */
+void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
+			   int *dso_width, int *dso_short_width, int *sym_width)
+{
+	struct rb_node *nd;
+	int printed = 0;
+
+	*sym_width = *dso_width = *dso_short_width = 0;
+
+	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
+		struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
+		struct symbol *sym = sym_entry__symbol(syme);
+
+		if (++printed > top->print_entries ||
+		    (int)syme->snap_count < top->count_filter)
+			continue;
+
+		if (syme->map->dso->long_name_len > *dso_width)
+			*dso_width = syme->map->dso->long_name_len;
+
+		if (syme->map->dso->short_name_len > *dso_short_width)
+			*dso_short_width = syme->map->dso->short_name_len;
+
+		if (sym->namelen > *sym_width)
+			*sym_width = sym->namelen;
+	}
+}
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
new file mode 100644
index 0000000..bfbf95b
--- /dev/null
+++ b/tools/perf/util/top.h
@@ -0,0 +1,64 @@
+#ifndef __PERF_TOP_H
+#define __PERF_TOP_H 1
+
+#include "types.h"
+#include "../perf.h"
+#include <stddef.h>
+#include <pthread.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+
+struct perf_evlist;
+struct perf_evsel;
+
+struct sym_entry {
+	struct rb_node		rb_node;
+	struct list_head	node;
+	unsigned long		snap_count;
+	double			weight;
+	struct map		*map;
+	unsigned long		count[0];
+};
+
+static inline struct symbol *sym_entry__symbol(struct sym_entry *self)
+{
+       return ((void *)self) + symbol_conf.priv_size;
+}
+
+struct perf_top {
+	struct perf_evlist *evlist;
+	/*
+	 * Symbols will be added here in perf_event__process_sample and will
+	 * get out after decayed.
+	 */
+	struct list_head   active_symbols;
+	pthread_mutex_t	   active_symbols_lock;
+	pthread_cond_t	   active_symbols_cond;
+	u64		   samples;
+	u64		   kernel_samples, us_samples;
+	u64		   exact_samples;
+	u64		   guest_us_samples, guest_kernel_samples;
+	int		   print_entries, count_filter, delay_secs;
+	int		   display_weighted, freq, rb_entries;
+	pid_t		   target_pid, target_tid;
+	bool		   hide_kernel_symbols, hide_user_symbols, zero;
+	const char	   *cpu_list;
+	struct sym_entry   *sym_filter_entry;
+	struct perf_evsel  *sym_evsel;
+};
+
+size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
+void perf_top__reset_sample_counters(struct perf_top *top);
+float perf_top__decay_samples(struct perf_top *top, struct rb_root *root);
+void perf_top__find_widths(struct perf_top *top, struct rb_root *root,
+			   int *dso_width, int *dso_short_width, int *sym_width);
+
+#ifdef NO_NEWT_SUPPORT
+static inline int perf_top__tui_browser(struct perf_top *top __used)
+{
+	return 0;
+}
+#else
+int perf_top__tui_browser(struct perf_top *top);
+#endif
+#endif /* __PERF_TOP_H */
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 73a0222..0a7ed5b 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -153,7 +153,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
 	char *next = NULL;
 	char *addr_str;
 	char ch;
-	int ret;
+	int ret __used;
 	int i;
 
 	line = strtok_r(file, "\n", &next);
@@ -2643,68 +2643,13 @@ static void print_lat_fmt(void *data, int size __unused)
 		printf(".");
 
 	if (lock_depth < 0)
-		printf(".");
+		printf(". ");
 	else
-		printf("%d", lock_depth);
-}
-
-/* taken from Linux, written by Frederic Weisbecker */
-static void print_graph_cpu(int cpu)
-{
-	int i;
-	int log10_this = log10_cpu(cpu);
-	int log10_all = log10_cpu(cpus);
-
-
-	/*
-	 * Start with a space character - to make it stand out
-	 * to the right a bit when trace output is pasted into
-	 * email:
-	 */
-	printf(" ");
-
-	/*
-	 * Tricky - we space the CPU field according to the max
-	 * number of online CPUs. On a 2-cpu system it would take
-	 * a maximum of 1 digit - on a 128 cpu system it would
-	 * take up to 3 digits:
-	 */
-	for (i = 0; i < log10_all - log10_this; i++)
-		printf(" ");
-
-	printf("%d) ", cpu);
+		printf("%d ", lock_depth);
 }
 
-#define TRACE_GRAPH_PROCINFO_LENGTH	14
 #define TRACE_GRAPH_INDENT	2
 
-static void print_graph_proc(int pid, const char *comm)
-{
-	/* sign + log10(MAX_INT) + '\0' */
-	char pid_str[11];
-	int spaces = 0;
-	int len;
-	int i;
-
-	sprintf(pid_str, "%d", pid);
-
-	/* 1 stands for the "-" character */
-	len = strlen(comm) + strlen(pid_str) + 1;
-
-	if (len < TRACE_GRAPH_PROCINFO_LENGTH)
-		spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
-
-	/* First spaces to align center */
-	for (i = 0; i < spaces / 2; i++)
-		printf(" ");
-
-	printf("%s-%s", comm, pid_str);
-
-	/* Last spaces to align center */
-	for (i = 0; i < spaces - (spaces / 2); i++)
-		printf(" ");
-}
-
 static struct record *
 get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
 		    struct record *next)
@@ -2876,21 +2821,13 @@ static void print_graph_nested(struct event *event, void *data)
 
 static void
 pretty_print_func_ent(void *data, int size, struct event *event,
-		      int cpu, int pid, const char *comm,
-		      unsigned long secs, unsigned long usecs)
+		      int cpu, int pid)
 {
 	struct format_field *field;
 	struct record *rec;
 	void *copy_data;
 	unsigned long val;
 
-	printf("%5lu.%06lu |  ", secs, usecs);
-
-	print_graph_cpu(cpu);
-	print_graph_proc(pid, comm);
-
-	printf(" | ");
-
 	if (latency_format) {
 		print_lat_fmt(data, size);
 		printf(" | ");
@@ -2923,22 +2860,13 @@ out_free:
 }
 
 static void
-pretty_print_func_ret(void *data, int size __unused, struct event *event,
-		      int cpu, int pid, const char *comm,
-		      unsigned long secs, unsigned long usecs)
+pretty_print_func_ret(void *data, int size __unused, struct event *event)
 {
 	unsigned long long rettime, calltime;
 	unsigned long long duration, depth;
 	struct format_field *field;
 	int i;
 
-	printf("%5lu.%06lu |  ", secs, usecs);
-
-	print_graph_cpu(cpu);
-	print_graph_proc(pid, comm);
-
-	printf(" | ");
-
 	if (latency_format) {
 		print_lat_fmt(data, size);
 		printf(" | ");
@@ -2976,31 +2904,21 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event,
 
 static void
 pretty_print_func_graph(void *data, int size, struct event *event,
-			int cpu, int pid, const char *comm,
-			unsigned long secs, unsigned long usecs)
+			int cpu, int pid)
 {
 	if (event->flags & EVENT_FL_ISFUNCENT)
-		pretty_print_func_ent(data, size, event,
-				      cpu, pid, comm, secs, usecs);
+		pretty_print_func_ent(data, size, event, cpu, pid);
 	else if (event->flags & EVENT_FL_ISFUNCRET)
-		pretty_print_func_ret(data, size, event,
-				      cpu, pid, comm, secs, usecs);
+		pretty_print_func_ret(data, size, event);
 	printf("\n");
 }
 
-void print_event(int cpu, void *data, int size, unsigned long long nsecs,
-		  char *comm)
+void print_trace_event(int cpu, void *data, int size)
 {
 	struct event *event;
-	unsigned long secs;
-	unsigned long usecs;
 	int type;
 	int pid;
 
-	secs = nsecs / NSECS_PER_SEC;
-	nsecs -= secs * NSECS_PER_SEC;
-	usecs = nsecs / NSECS_PER_USEC;
-
 	type = trace_parse_common_type(data);
 
 	event = trace_find_event(type);
@@ -3012,17 +2930,10 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
 	pid = trace_parse_common_pid(data);
 
 	if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
-		return pretty_print_func_graph(data, size, event, cpu,
-					       pid, comm, secs, usecs);
+		return pretty_print_func_graph(data, size, event, cpu, pid);
 
-	if (latency_format) {
-		printf("%8.8s-%-5d %3d",
-		       comm, pid, cpu);
+	if (latency_format)
 		print_lat_fmt(data, size);
-	} else
-		printf("%16s-%-5d [%03d]", comm, pid,  cpu);
-
-	printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);
 
 	if (event->flags & EVENT_FL_FAILED) {
 		printf("EVENT '%s' FAILED TO PARSE\n",
@@ -3031,7 +2942,6 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
 	}
 
 	pretty_print(data, size, event);
-	printf("\n");
 }
 
 static void print_fields(struct print_flag_sym *field)
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index f7af2fc..66f4b78 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -36,11 +36,10 @@ static int stop_script_unsupported(void)
 	return 0;
 }
 
-static void process_event_unsupported(int cpu __unused,
-				      void *data __unused,
-				      int size __unused,
-				      unsigned long long nsecs __unused,
-				      char *comm __unused)
+static void process_event_unsupported(union perf_event *event __unused,
+				      struct perf_sample *sample __unused,
+				      struct perf_session *session __unused,
+				      struct thread *thread __unused)
 {
 }
 
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b5f12ca..b04da57 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,6 +3,7 @@
 
 #include <stdbool.h>
 #include "parse-events.h"
+#include "session.h"
 
 #define __unused __attribute__((unused))
 
@@ -176,8 +177,7 @@ void print_printk(void);
 
 int parse_ftrace_file(char *buf, unsigned long size);
 int parse_event_file(char *buf, unsigned long size, char *sys);
-void print_event(int cpu, void *data, int size, unsigned long long nsecs,
-		  char *comm);
+void print_trace_event(int cpu, void *data, int size);
 
 extern int file_bigendian;
 extern int host_bigendian;
@@ -278,8 +278,10 @@ struct scripting_ops {
 	const char *name;
 	int (*start_script) (const char *script, int argc, const char **argv);
 	int (*stop_script) (void);
-	void (*process_event) (int cpu, void *data, int size,
-			       unsigned long long nsecs, char *comm);
+	void (*process_event) (union perf_event *event,
+			       struct perf_sample *sample,
+			       struct perf_session *session,
+			       struct thread *thread);
 	int (*generate_script) (const char *outfile);
 };
 
diff --git a/tools/perf/util/ui/browser.c b/tools/perf/util/ui/browser.c
index 8bc010e..611219f 100644
--- a/tools/perf/util/ui/browser.c
+++ b/tools/perf/util/ui/browser.c
@@ -1,4 +1,5 @@
 #include "libslang.h"
+#include "ui.h"
 #include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
@@ -156,6 +157,20 @@ void ui_browser__add_exit_keys(struct ui_browser *self, int keys[])
 	}
 }
 
+void __ui_browser__show_title(struct ui_browser *browser, const char *title)
+{
+	SLsmg_gotorc(0, 0);
+	ui_browser__set_color(browser, NEWT_COLORSET_ROOT);
+	slsmg_write_nstring(title, browser->width);
+}
+
+void ui_browser__show_title(struct ui_browser *browser, const char *title)
+{
+	pthread_mutex_lock(&ui__lock);
+	__ui_browser__show_title(browser, title);
+	pthread_mutex_unlock(&ui__lock);
+}
+
 int ui_browser__show(struct ui_browser *self, const char *title,
 		     const char *helpline, ...)
 {
@@ -178,9 +193,8 @@ int ui_browser__show(struct ui_browser *self, const char *title,
 	if (self->sb == NULL)
 		return -1;
 
-	SLsmg_gotorc(0, 0);
-	ui_browser__set_color(self, NEWT_COLORSET_ROOT);
-	slsmg_write_nstring(title, self->width);
+	pthread_mutex_lock(&ui__lock);
+	__ui_browser__show_title(self, title);
 
 	ui_browser__add_exit_keys(self, keys);
 	newtFormAddComponent(self->form, self->sb);
@@ -188,25 +202,30 @@ int ui_browser__show(struct ui_browser *self, const char *title,
 	va_start(ap, helpline);
 	ui_helpline__vpush(helpline, ap);
 	va_end(ap);
+	pthread_mutex_unlock(&ui__lock);
 	return 0;
 }
 
 void ui_browser__hide(struct ui_browser *self)
 {
+	pthread_mutex_lock(&ui__lock);
 	newtFormDestroy(self->form);
 	self->form = NULL;
 	ui_helpline__pop();
+	pthread_mutex_unlock(&ui__lock);
 }
 
 int ui_browser__refresh(struct ui_browser *self)
 {
 	int row;
 
+	pthread_mutex_lock(&ui__lock);
 	newtScrollbarSet(self->sb, self->index, self->nr_entries - 1);
 	row = self->refresh(self);
 	ui_browser__set_color(self, HE_COLORSET_NORMAL);
 	SLsmg_fill_region(self->y + row, self->x,
 			  self->height - row, self->width, ' ');
+	pthread_mutex_unlock(&ui__lock);
 
 	return 0;
 }
diff --git a/tools/perf/util/ui/browser.h b/tools/perf/util/ui/browser.h
index 0dc7e4d..fc63dda 100644
--- a/tools/perf/util/ui/browser.h
+++ b/tools/perf/util/ui/browser.h
@@ -24,7 +24,6 @@ struct ui_browser {
 	u32	      nr_entries;
 };
 
-
 void ui_browser__set_color(struct ui_browser *self, int color);
 void ui_browser__set_percent_color(struct ui_browser *self,
 				   double percent, bool current);
@@ -35,6 +34,8 @@ void ui_browser__reset_index(struct ui_browser *self);
 void ui_browser__gotorc(struct ui_browser *self, int y, int x);
 void ui_browser__add_exit_key(struct ui_browser *self, int key);
 void ui_browser__add_exit_keys(struct ui_browser *self, int keys[]);
+void __ui_browser__show_title(struct ui_browser *browser, const char *title);
+void ui_browser__show_title(struct ui_browser *browser, const char *title);
 int ui_browser__show(struct ui_browser *self, const char *title,
 		     const char *helpline, ...);
 void ui_browser__hide(struct ui_browser *self);
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 82b78f9..8c17a87 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -1,9 +1,12 @@
 #include "../browser.h"
 #include "../helpline.h"
 #include "../libslang.h"
+#include "../../annotate.h"
 #include "../../hist.h"
 #include "../../sort.h"
 #include "../../symbol.h"
+#include "../../annotate.h"
+#include <pthread.h>
 
 static void ui__error_window(const char *fmt, ...)
 {
@@ -42,8 +45,6 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
 		struct objdump_line_rb_node *olrb = objdump_line__rb(ol);
 		ui_browser__set_percent_color(self, olrb->percent, current_entry);
 		slsmg_printf(" %7.2f ", olrb->percent);
-		if (!current_entry)
-			ui_browser__set_color(self, HE_COLORSET_CODE);
 	} else {
 		ui_browser__set_percent_color(self, 0, current_entry);
 		slsmg_write_nstring(" ", 9);
@@ -55,35 +56,40 @@ static void annotate_browser__write(struct ui_browser *self, void *entry, int ro
 		slsmg_write_nstring(" ", width - 18);
 	else
 		slsmg_write_nstring(ol->line, width - 18);
+
+	if (!current_entry)
+		ui_browser__set_color(self, HE_COLORSET_CODE);
 }
 
 static double objdump_line__calc_percent(struct objdump_line *self,
-					 struct list_head *head,
-					 struct symbol *sym)
+					 struct symbol *sym, int evidx)
 {
 	double percent = 0.0;
 
 	if (self->offset != -1) {
 		int len = sym->end - sym->start;
 		unsigned int hits = 0;
-		struct sym_priv *priv = symbol__priv(sym);
-		struct sym_ext *sym_ext = priv->ext;
-		struct sym_hist *h = priv->hist;
+		struct annotation *notes = symbol__annotation(sym);
+		struct source_line *src_line = notes->src->lines;
+		struct sym_hist *h = annotation__histogram(notes, evidx);
 		s64 offset = self->offset;
-		struct objdump_line *next = objdump__get_next_ip_line(head, self);
-
+		struct objdump_line *next;
 
+		next = objdump__get_next_ip_line(&notes->src->source, self);
 		while (offset < (s64)len &&
 		       (next == NULL || offset < next->offset)) {
-			if (sym_ext) {
-				percent += sym_ext[offset].percent;
+			if (src_line) {
+				percent += src_line[offset].percent;
 			} else
-				hits += h->ip[offset];
+				hits += h->addr[offset];
 
 			++offset;
 		}
-
-		if (sym_ext == NULL && h->sum)
+		/*
+ 		 * If the percentage wasn't already calculated in
+ 		 * symbol__get_source_line, do it now:
+ 		 */
+		if (src_line == NULL && h->sum)
 			percent = 100.0 * hits / h->sum;
 	}
 
@@ -133,103 +139,161 @@ static void annotate_browser__set_top(struct annotate_browser *self,
 	self->curr_hot = nd;
 }
 
-static int annotate_browser__run(struct annotate_browser *self)
+static void annotate_browser__calc_percent(struct annotate_browser *browser,
+					   int evidx)
 {
-	struct rb_node *nd;
-	struct hist_entry *he = self->b.priv;
-	int key;
+	struct symbol *sym = browser->b.priv;
+	struct annotation *notes = symbol__annotation(sym);
+	struct objdump_line *pos;
 
-	if (ui_browser__show(&self->b, he->ms.sym->name,
-			     "<-, -> or ESC: exit, TAB/shift+TAB: cycle thru samples") < 0)
-		return -1;
+	browser->entries = RB_ROOT;
+
+	pthread_mutex_lock(&notes->lock);
+
+	list_for_each_entry(pos, &notes->src->source, node) {
+		struct objdump_line_rb_node *rbpos = objdump_line__rb(pos);
+		rbpos->percent = objdump_line__calc_percent(pos, sym, evidx);
+		if (rbpos->percent < 0.01) {
+			RB_CLEAR_NODE(&rbpos->rb_node);
+			continue;
+		}
+		objdump__insert_line(&browser->entries, rbpos);
+	}
+	pthread_mutex_unlock(&notes->lock);
+
+	browser->curr_hot = rb_last(&browser->entries);
+}
+
+static int annotate_browser__run(struct annotate_browser *self, int evidx,
+				 int refresh)
+{
+	struct rb_node *nd = NULL;
+	struct symbol *sym = self->b.priv;
 	/*
-	 * To allow builtin-annotate to cycle thru multiple symbols by
+	 * RIGHT To allow builtin-annotate to cycle thru multiple symbols by
 	 * examining the exit key for this function.
 	 */
-	ui_browser__add_exit_key(&self->b, NEWT_KEY_RIGHT);
+	int exit_keys[] = { 'H', NEWT_KEY_TAB, NEWT_KEY_UNTAB,
+			    NEWT_KEY_RIGHT, 0 };
+	int key;
+
+	if (ui_browser__show(&self->b, sym->name,
+			     "<-, -> or ESC: exit, TAB/shift+TAB: "
+			     "cycle hottest lines, H: Hottest") < 0)
+		return -1;
+
+	ui_browser__add_exit_keys(&self->b, exit_keys);
+	annotate_browser__calc_percent(self, evidx);
+
+	if (self->curr_hot)
+		annotate_browser__set_top(self, self->curr_hot);
 
 	nd = self->curr_hot;
-	if (nd) {
-		int tabs[] = { NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0 };
-		ui_browser__add_exit_keys(&self->b, tabs);
-	}
+
+	if (refresh != 0)
+		newtFormSetTimer(self->b.form, refresh);
 
 	while (1) {
 		key = ui_browser__run(&self->b);
 
+		if (refresh != 0) {
+			annotate_browser__calc_percent(self, evidx);
+			/*
+			 * Current line focus got out of the list of most active
+			 * lines, NULL it so that if TAB|UNTAB is pressed, we
+			 * move to curr_hot (current hottest line).
+			 */
+			if (nd != NULL && RB_EMPTY_NODE(nd))
+				nd = NULL;
+		}
+
 		switch (key) {
+		case -1:
+			/*
+ 			 * FIXME we need to check if it was
+ 			 * es.reason == NEWT_EXIT_TIMER
+ 			 */
+			if (refresh != 0)
+				symbol__annotate_decay_histogram(sym, evidx);
+			continue;
 		case NEWT_KEY_TAB:
-			nd = rb_prev(nd);
-			if (nd == NULL)
-				nd = rb_last(&self->entries);
-			annotate_browser__set_top(self, nd);
+			if (nd != NULL) {
+				nd = rb_prev(nd);
+				if (nd == NULL)
+					nd = rb_last(&self->entries);
+			} else
+				nd = self->curr_hot;
 			break;
 		case NEWT_KEY_UNTAB:
-			nd = rb_next(nd);
-			if (nd == NULL)
-				nd = rb_first(&self->entries);
-			annotate_browser__set_top(self, nd);
+			if (nd != NULL)
+				nd = rb_next(nd);
+				if (nd == NULL)
+					nd = rb_first(&self->entries);
+			else
+				nd = self->curr_hot;
+			break;
+		case 'H':
+			nd = self->curr_hot;
 			break;
 		default:
 			goto out;
 		}
+
+		if (nd != NULL)
+			annotate_browser__set_top(self, nd);
 	}
 out:
 	ui_browser__hide(&self->b);
 	return key;
 }
 
-int hist_entry__tui_annotate(struct hist_entry *self)
+int hist_entry__tui_annotate(struct hist_entry *he, int evidx)
+{
+	return symbol__tui_annotate(he->ms.sym, he->ms.map, evidx, 0);
+}
+
+int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
+			 int refresh)
 {
 	struct objdump_line *pos, *n;
-	struct objdump_line_rb_node *rbpos;
-	LIST_HEAD(head);
+	struct annotation *notes = symbol__annotation(sym);
 	struct annotate_browser browser = {
 		.b = {
-			.entries = &head,
+			.entries = &notes->src->source,
 			.refresh = ui_browser__list_head_refresh,
 			.seek	 = ui_browser__list_head_seek,
 			.write	 = annotate_browser__write,
-			.priv	 = self,
+			.priv	 = sym,
 		},
 	};
 	int ret;
 
-	if (self->ms.sym == NULL)
+	if (sym == NULL)
 		return -1;
 
-	if (self->ms.map->dso->annotate_warned)
+	if (map->dso->annotate_warned)
 		return -1;
 
-	if (hist_entry__annotate(self, &head, sizeof(*rbpos)) < 0) {
+	if (symbol__annotate(sym, map, sizeof(struct objdump_line_rb_node)) < 0) {
 		ui__error_window(ui_helpline__last_msg);
 		return -1;
 	}
 
 	ui_helpline__push("Press <- or ESC to exit");
 
-	list_for_each_entry(pos, &head, node) {
+	list_for_each_entry(pos, &notes->src->source, node) {
+		struct objdump_line_rb_node *rbpos;
 		size_t line_len = strlen(pos->line);
+
 		if (browser.b.width < line_len)
 			browser.b.width = line_len;
 		rbpos = objdump_line__rb(pos);
 		rbpos->idx = browser.b.nr_entries++;
-		rbpos->percent = objdump_line__calc_percent(pos, &head, self->ms.sym);
-		if (rbpos->percent < 0.01)
-			continue;
-		objdump__insert_line(&browser.entries, rbpos);
 	}
 
-	/*
-	 * Position the browser at the hottest line.
-	 */
-	browser.curr_hot = rb_last(&browser.entries);
-	if (browser.curr_hot)
-		annotate_browser__set_top(&browser, browser.curr_hot);
-
 	browser.b.width += 18; /* Percentage */
-	ret = annotate_browser__run(&browser);
-	list_for_each_entry_safe(pos, n, &head, node) {
+	ret = annotate_browser__run(&browser, evidx, refresh);
+	list_for_each_entry_safe(pos, n, &notes->src->source, node) {
 		list_del(&pos->node);
 		objdump_line__free(pos);
 	}
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 60c463c..798efdc 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -7,6 +7,8 @@
 #include <newt.h>
 #include <linux/rbtree.h>
 
+#include "../../evsel.h"
+#include "../../evlist.h"
 #include "../../hist.h"
 #include "../../pstack.h"
 #include "../../sort.h"
@@ -292,7 +294,8 @@ static int hist_browser__run(struct hist_browser *self, const char *title)
 {
 	int key;
 	int exit_keys[] = { 'a', '?', 'h', 'C', 'd', 'D', 'E', 't',
-			    NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT, 0, };
+			    NEWT_KEY_ENTER, NEWT_KEY_RIGHT, NEWT_KEY_LEFT,
+			    NEWT_KEY_TAB, NEWT_KEY_UNTAB, 0, };
 
 	self->b.entries = &self->hists->entries;
 	self->b.nr_entries = self->hists->nr_entries;
@@ -377,7 +380,7 @@ static int hist_browser__show_callchain_node_rb_tree(struct hist_browser *self,
 	while (node) {
 		struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
 		struct rb_node *next = rb_next(node);
-		u64 cumul = cumul_hits(child);
+		u64 cumul = callchain_cumul_hits(child);
 		struct callchain_list *chain;
 		char folded_sign = ' ';
 		int first = true;
@@ -638,6 +641,9 @@ static void ui_browser__hists_seek(struct ui_browser *self,
 	struct rb_node *nd;
 	bool first = true;
 
+	if (self->nr_entries == 0)
+		return;
+
 	switch (whence) {
 	case SEEK_SET:
 		nd = hists__filter_entries(rb_first(self->entries));
@@ -797,8 +803,11 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
 	return printed;
 }
 
-int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
+static int perf_evsel__hists_browse(struct perf_evsel *evsel,
+				    const char *helpline, const char *ev_name,
+				    bool left_exits)
 {
+	struct hists *self = &evsel->hists;
 	struct hist_browser *browser = hist_browser__new(self);
 	struct pstack *fstack;
 	const struct thread *thread_filter = NULL;
@@ -818,8 +827,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 	hists__browser_title(self, msg, sizeof(msg), ev_name,
 			     dso_filter, thread_filter);
 	while (1) {
-		const struct thread *thread;
-		const struct dso *dso;
+		const struct thread *thread = NULL;
+		const struct dso *dso = NULL;
 		char *options[16];
 		int nr_options = 0, choice = 0, i,
 		    annotate = -2, zoom_dso = -2, zoom_thread = -2,
@@ -827,8 +836,10 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 
 		key = hist_browser__run(browser, msg);
 
-		thread = hist_browser__selected_thread(browser);
-		dso = browser->selection->map ? browser->selection->map->dso : NULL;
+		if (browser->he_selection != NULL) {
+			thread = hist_browser__selected_thread(browser);
+			dso = browser->selection->map ? browser->selection->map->dso : NULL;
+		}
 
 		switch (key) {
 		case NEWT_KEY_TAB:
@@ -839,7 +850,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 			 */
 			goto out_free_stack;
 		case 'a':
-			if (browser->selection->map == NULL &&
+			if (browser->selection == NULL ||
+			    browser->selection->map == NULL ||
 			    browser->selection->map->dso->annotate_warned)
 				continue;
 			goto do_annotate;
@@ -858,6 +870,7 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 					"E         Expand all callchains\n"
 					"d         Zoom into current DSO\n"
 					"t         Zoom into current Thread\n"
+					"TAB/UNTAB Switch events\n"
 					"q/CTRL+C  Exit browser");
 			continue;
 		case NEWT_KEY_ENTER:
@@ -867,8 +880,14 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 		case NEWT_KEY_LEFT: {
 			const void *top;
 
-			if (pstack__empty(fstack))
+			if (pstack__empty(fstack)) {
+				/*
+				 * Go back to the perf_evsel_menu__run or other user
+				 */
+				if (left_exits)
+					goto out_free_stack;
 				continue;
+			}
 			top = pstack__pop(fstack);
 			if (top == &dso_filter)
 				goto zoom_out_dso;
@@ -877,14 +896,16 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 			continue;
 		}
 		case NEWT_KEY_ESCAPE:
-			if (!ui__dialog_yesno("Do you really want to exit?"))
+			if (!left_exits &&
+			    !ui__dialog_yesno("Do you really want to exit?"))
 				continue;
 			/* Fall thru */
 		default:
 			goto out_free_stack;
 		}
 
-		if (browser->selection->sym != NULL &&
+		if (browser->selection != NULL &&
+		    browser->selection->sym != NULL &&
 		    !browser->selection->map->dso->annotate_warned &&
 		    asprintf(&options[nr_options], "Annotate %s",
 			     browser->selection->sym->name) > 0)
@@ -903,7 +924,8 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 			     (dso->kernel ? "the Kernel" : dso->short_name)) > 0)
 			zoom_dso = nr_options++;
 
-		if (browser->selection->map != NULL &&
+		if (browser->selection != NULL &&
+		    browser->selection->map != NULL &&
 		    asprintf(&options[nr_options], "Browse map details") > 0)
 			browse_map = nr_options++;
 
@@ -923,19 +945,11 @@ int hists__browse(struct hists *self, const char *helpline, const char *ev_name)
 		if (choice == annotate) {
 			struct hist_entry *he;
 do_annotate:
-			if (browser->selection->map->dso->origin == DSO__ORIG_KERNEL) {
-				browser->selection->map->dso->annotate_warned = 1;
-				ui_helpline__puts("No vmlinux file found, can't "
-						 "annotate with just a "
-						 "kallsyms file");
-				continue;
-			}
-
 			he = hist_browser__selected_entry(browser);
 			if (he == NULL)
 				continue;
 
-			hist_entry__tui_annotate(he);
+			hist_entry__tui_annotate(he, evsel->idx);
 		} else if (choice == browse_map)
 			map__browse(browser->selection->map);
 		else if (choice == zoom_dso) {
@@ -984,30 +998,141 @@ out:
 	return key;
 }
 
-int hists__tui_browse_tree(struct rb_root *self, const char *help)
+struct perf_evsel_menu {
+	struct ui_browser b;
+	struct perf_evsel *selection;
+};
+
+static void perf_evsel_menu__write(struct ui_browser *browser,
+				   void *entry, int row)
+{
+	struct perf_evsel_menu *menu = container_of(browser,
+						    struct perf_evsel_menu, b);
+	struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
+	bool current_entry = ui_browser__is_current_entry(browser, row);
+	unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+	const char *ev_name = event_name(evsel);
+	char bf[256], unit;
+
+	ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+						       HE_COLORSET_NORMAL);
+
+	nr_events = convert_unit(nr_events, &unit);
+	snprintf(bf, sizeof(bf), "%lu%c%s%s", nr_events,
+		 unit, unit == ' ' ? "" : " ", ev_name);
+	slsmg_write_nstring(bf, browser->width);
+
+	if (current_entry)
+		menu->selection = evsel;
+}
+
+static int perf_evsel_menu__run(struct perf_evsel_menu *menu, const char *help)
 {
-	struct rb_node *first = rb_first(self), *nd = first, *next;
-	int key = 0;
+	int exit_keys[] = { NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
+	struct perf_evlist *evlist = menu->b.priv;
+	struct perf_evsel *pos;
+	const char *ev_name, *title = "Available samples";
+	int key;
+
+	if (ui_browser__show(&menu->b, title,
+			     "ESC: exit, ENTER|->: Browse histograms") < 0)
+		return -1;
+
+	ui_browser__add_exit_keys(&menu->b, exit_keys);
 
-	while (nd) {
-		struct hists *hists = rb_entry(nd, struct hists, rb_node);
-		const char *ev_name = __event_name(hists->type, hists->config);
+	while (1) {
+		key = ui_browser__run(&menu->b);
 
-		key = hists__browse(hists, help, ev_name);
 		switch (key) {
-		case NEWT_KEY_TAB:
-			next = rb_next(nd);
-			if (next)
-				nd = next;
+		case NEWT_KEY_RIGHT:
+		case NEWT_KEY_ENTER:
+			if (!menu->selection)
+				continue;
+			pos = menu->selection;
+browse_hists:
+			ev_name = event_name(pos);
+			key = perf_evsel__hists_browse(pos, help, ev_name, true);
+			ui_browser__show_title(&menu->b, title);
 			break;
-		case NEWT_KEY_UNTAB:
-			if (nd == first)
+		case NEWT_KEY_LEFT:
+			continue;
+		case NEWT_KEY_ESCAPE:
+			if (!ui__dialog_yesno("Do you really want to exit?"))
 				continue;
-			nd = rb_prev(nd);
+			/* Fall thru */
+		default:
+			goto out;
+		}
+
+		switch (key) {
+		case NEWT_KEY_TAB:
+			if (pos->node.next == &evlist->entries)
+				pos = list_entry(evlist->entries.next, struct perf_evsel, node);
+			else
+				pos = list_entry(pos->node.next, struct perf_evsel, node);
+			goto browse_hists;
+		case NEWT_KEY_UNTAB:
+			if (pos->node.prev == &evlist->entries)
+				pos = list_entry(evlist->entries.prev, struct perf_evsel, node);
+			else
+				pos = list_entry(pos->node.prev, struct perf_evsel, node);
+			goto browse_hists;
+		case 'q':
+		case CTRL('c'):
+			goto out;
 		default:
-			return key;
+			break;
 		}
 	}
 
+out:
+	ui_browser__hide(&menu->b);
 	return key;
 }
+
+static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
+					   const char *help)
+{
+	struct perf_evsel *pos;
+	struct perf_evsel_menu menu = {
+		.b = {
+			.entries    = &evlist->entries,
+			.refresh    = ui_browser__list_head_refresh,
+			.seek	    = ui_browser__list_head_seek,
+			.write	    = perf_evsel_menu__write,
+			.nr_entries = evlist->nr_entries,
+			.priv	    = evlist,
+		},
+	};
+
+	ui_helpline__push("Press ESC to exit");
+
+	list_for_each_entry(pos, &evlist->entries, node) {
+		const char *ev_name = event_name(pos);
+		size_t line_len = strlen(ev_name) + 7;
+
+		if (menu.b.width < line_len)
+			menu.b.width = line_len;
+		/*
+		 * Cache the evsel name, tracepoints have a _high_ cost per
+		 * event_name() call.
+		 */
+		if (pos->name == NULL)
+			pos->name = strdup(ev_name);
+	}
+
+	return perf_evsel_menu__run(&menu, help);
+}
+
+int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help)
+{
+
+	if (evlist->nr_entries == 1) {
+		struct perf_evsel *first = list_entry(evlist->entries.next,
+						      struct perf_evsel, node);
+		const char *ev_name = event_name(first);
+		return perf_evsel__hists_browse(first, help, ev_name, false);
+	}
+
+	return __perf_evlist__tui_browse_hists(evlist, help);
+}
diff --git a/tools/perf/util/ui/browsers/map.c b/tools/perf/util/ui/browsers/map.c
index e515836..8462bff 100644
--- a/tools/perf/util/ui/browsers/map.c
+++ b/tools/perf/util/ui/browsers/map.c
@@ -41,7 +41,7 @@ static int ui_entry__read(const char *title, char *bf, size_t size, int width)
 out_free_form:
 	newtPopWindow();
 	newtFormDestroy(form);
-	return 0;
+	return err;
 }
 
 struct map_browser {
diff --git a/tools/perf/util/ui/browsers/top.c b/tools/perf/util/ui/browsers/top.c
new file mode 100644
index 0000000..5a06538
--- /dev/null
+++ b/tools/perf/util/ui/browsers/top.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+ *
+ * Parts came from builtin-{top,stat,record}.c, see those files for further
+ * copyright notes.
+ *
+ * Released under the GPL v2. (and only v2, not any later version)
+ */
+#include "../browser.h"
+#include "../../annotate.h"
+#include "../helpline.h"
+#include "../libslang.h"
+#include "../util.h"
+#include "../../evlist.h"
+#include "../../hist.h"
+#include "../../sort.h"
+#include "../../symbol.h"
+#include "../../top.h"
+
+struct perf_top_browser {
+	struct ui_browser b;
+	struct rb_root	  root;
+	struct sym_entry  *selection;
+	float		  sum_ksamples;
+	int		  dso_width;
+	int		  dso_short_width;
+	int		  sym_width;
+};
+
+static void perf_top_browser__write(struct ui_browser *browser, void *entry, int row)
+{
+	struct perf_top_browser *top_browser = container_of(browser, struct perf_top_browser, b);
+	struct sym_entry *syme = rb_entry(entry, struct sym_entry, rb_node);
+	bool current_entry = ui_browser__is_current_entry(browser, row);
+	struct symbol *symbol = sym_entry__symbol(syme);
+	struct perf_top *top = browser->priv;
+	int width = browser->width;
+	double pcnt;
+
+	pcnt = 100.0 - (100.0 * ((top_browser->sum_ksamples - syme->snap_count) /
+				 top_browser->sum_ksamples));
+	ui_browser__set_percent_color(browser, pcnt, current_entry);
+
+	if (top->evlist->nr_entries == 1 || !top->display_weighted) {
+		slsmg_printf("%20.2f ", syme->weight);
+		width -= 24;
+	} else {
+		slsmg_printf("%9.1f %10ld ", syme->weight, syme->snap_count);
+		width -= 23;
+	}
+
+	slsmg_printf("%4.1f%%", pcnt);
+	width -= 7;
+
+	if (verbose) {
+		slsmg_printf(" %016" PRIx64, symbol->start);
+		width -= 17;
+	}
+
+	slsmg_printf(" %-*.*s ", top_browser->sym_width, top_browser->sym_width,
+		     symbol->name);
+	width -= top_browser->sym_width;
+	slsmg_write_nstring(width >= syme->map->dso->long_name_len ?
+				syme->map->dso->long_name :
+				syme->map->dso->short_name, width);
+
+	if (current_entry)
+		top_browser->selection = syme;
+}
+
+static void perf_top_browser__update_rb_tree(struct perf_top_browser *browser)
+{
+	struct perf_top *top = browser->b.priv;
+	u64 top_idx = browser->b.top_idx;
+
+	browser->root = RB_ROOT;
+	browser->b.top = NULL;
+	browser->sum_ksamples = perf_top__decay_samples(top, &browser->root);
+	/*
+ 	 * No active symbols
+ 	 */
+	if (top->rb_entries == 0)
+		return;
+
+	perf_top__find_widths(top, &browser->root, &browser->dso_width,
+			      &browser->dso_short_width,
+                              &browser->sym_width);
+	if (browser->sym_width + browser->dso_width > browser->b.width - 29) {
+		browser->dso_width = browser->dso_short_width;
+		if (browser->sym_width + browser->dso_width > browser->b.width - 29)
+			browser->sym_width = browser->b.width - browser->dso_width - 29;
+	}
+
+	/*
+	 * Adjust the ui_browser indexes since the entries in the browser->root
+	 * rb_tree may have changed, then seek it from start, so that we get a
+	 * possible new top of the screen.
+ 	 */
+	browser->b.nr_entries = top->rb_entries;
+
+	if (top_idx >= browser->b.nr_entries) {
+		if (browser->b.height >= browser->b.nr_entries)
+			top_idx = browser->b.nr_entries - browser->b.height;
+		else
+			top_idx = 0;
+	}
+
+	if (browser->b.index >= top_idx + browser->b.height)
+		browser->b.index = top_idx + browser->b.index - browser->b.top_idx;
+
+	if (browser->b.index >= browser->b.nr_entries)
+		browser->b.index = browser->b.nr_entries - 1;
+
+	browser->b.top_idx = top_idx;
+	browser->b.seek(&browser->b, top_idx, SEEK_SET);
+}
+
+static void perf_top_browser__annotate(struct perf_top_browser *browser)
+{
+	struct sym_entry *syme = browser->selection;
+	struct symbol *sym = sym_entry__symbol(syme);
+	struct annotation *notes = symbol__annotation(sym);
+	struct perf_top *top = browser->b.priv;
+
+	if (notes->src != NULL)
+		goto do_annotation;
+
+	pthread_mutex_lock(&notes->lock);
+
+	top->sym_filter_entry = NULL;
+
+	if (symbol__alloc_hist(sym, top->evlist->nr_entries) < 0) {
+		pr_err("Not enough memory for annotating '%s' symbol!\n",
+		       sym->name);
+		pthread_mutex_unlock(&notes->lock);
+		return;
+	}
+
+	top->sym_filter_entry = syme;
+
+	pthread_mutex_unlock(&notes->lock);
+do_annotation:
+	symbol__tui_annotate(sym, syme->map, 0, top->delay_secs * 1000);
+}
+
+static int perf_top_browser__run(struct perf_top_browser *browser)
+{
+	int key;
+	char title[160];
+	struct perf_top *top = browser->b.priv;
+	int delay_msecs = top->delay_secs * 1000;
+	int exit_keys[] = { 'a', NEWT_KEY_ENTER, NEWT_KEY_RIGHT, 0, };
+
+	perf_top_browser__update_rb_tree(browser);
+        perf_top__header_snprintf(top, title, sizeof(title));
+        perf_top__reset_sample_counters(top);
+
+	if (ui_browser__show(&browser->b, title,
+			     "ESC: exit, ENTER|->|a: Live Annotate") < 0)
+		return -1;
+
+	newtFormSetTimer(browser->b.form, delay_msecs);
+	ui_browser__add_exit_keys(&browser->b, exit_keys);
+
+	while (1) {
+		key = ui_browser__run(&browser->b);
+
+		switch (key) {
+		case -1:
+			/* FIXME we need to check if it was es.reason == NEWT_EXIT_TIMER */
+			perf_top_browser__update_rb_tree(browser);
+			perf_top__header_snprintf(top, title, sizeof(title));
+			perf_top__reset_sample_counters(top);
+			ui_browser__set_color(&browser->b, NEWT_COLORSET_ROOT);
+			SLsmg_gotorc(0, 0);
+			slsmg_write_nstring(title, browser->b.width);
+			break;
+		case 'a':
+		case NEWT_KEY_RIGHT:
+		case NEWT_KEY_ENTER:
+			if (browser->selection)
+				perf_top_browser__annotate(browser);
+			break;
+		case NEWT_KEY_LEFT:
+			continue;
+		case NEWT_KEY_ESCAPE:
+			if (!ui__dialog_yesno("Do you really want to exit?"))
+				continue;
+			/* Fall thru */
+		default:
+			goto out;
+		}
+	}
+out:
+	ui_browser__hide(&browser->b);
+	return key;
+}
+
+int perf_top__tui_browser(struct perf_top *top)
+{
+	struct perf_top_browser browser = {
+		.b = {
+			.entries = &browser.root,
+			.refresh = ui_browser__rb_tree_refresh,
+			.seek	 = ui_browser__rb_tree_seek,
+			.write	 = perf_top_browser__write,
+			.priv	 = top,
+		},
+	};
+
+	ui_helpline__push("Press <- or ESC to exit");
+	return perf_top_browser__run(&browser);
+}
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index 8d79daa..f36d2ff 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -5,6 +5,7 @@
 
 #include "../debug.h"
 #include "helpline.h"
+#include "ui.h"
 
 void ui_helpline__pop(void)
 {
@@ -55,7 +56,8 @@ int ui_helpline__show_help(const char *format, va_list ap)
 	int ret;
 	static int backlog;
 
-        ret = vsnprintf(ui_helpline__last_msg + backlog,
+	pthread_mutex_lock(&ui__lock);
+	ret = vsnprintf(ui_helpline__last_msg + backlog,
 			sizeof(ui_helpline__last_msg) - backlog, format, ap);
 	backlog += ret;
 
@@ -64,6 +66,7 @@ int ui_helpline__show_help(const char *format, va_list ap)
 		newtRefresh();
 		backlog = 0;
 	}
+	pthread_mutex_unlock(&ui__lock);
 
 	return ret;
 }
diff --git a/tools/perf/util/ui/libslang.h b/tools/perf/util/ui/libslang.h
index 5623da8..2b63e1c 100644
--- a/tools/perf/util/ui/libslang.h
+++ b/tools/perf/util/ui/libslang.h
@@ -13,11 +13,11 @@
 
 #if SLANG_VERSION < 20104
 #define slsmg_printf(msg, args...) \
-	SLsmg_printf((char *)msg, ##args)
+	SLsmg_printf((char *)(msg), ##args)
 #define slsmg_write_nstring(msg, len) \
-	SLsmg_write_nstring((char *)msg, len)
+	SLsmg_write_nstring((char *)(msg), len)
 #define sltt_set_color(obj, name, fg, bg) \
-	SLtt_set_color(obj,(char *)name, (char *)fg, (char *)bg)
+	SLtt_set_color(obj,(char *)(name), (char *)(fg), (char *)(bg))
 #else
 #define slsmg_printf SLsmg_printf
 #define slsmg_write_nstring SLsmg_write_nstring
diff --git a/tools/perf/util/ui/setup.c b/tools/perf/util/ui/setup.c
index 6620850..ee46d67 100644
--- a/tools/perf/util/ui/setup.c
+++ b/tools/perf/util/ui/setup.c
@@ -6,6 +6,9 @@
 #include "../debug.h"
 #include "browser.h"
 #include "helpline.h"
+#include "ui.h"
+
+pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 
 static void newt_suspend(void *d __used)
 {
@@ -14,11 +17,12 @@ static void newt_suspend(void *d __used)
 	newtResume();
 }
 
-void setup_browser(void)
+void setup_browser(bool fallback_to_pager)
 {
 	if (!isatty(1) || !use_browser || dump_trace) {
 		use_browser = 0;
-		setup_pager();
+		if (fallback_to_pager)
+			setup_pager();
 		return;
 	}
 
diff --git a/tools/perf/util/ui/ui.h b/tools/perf/util/ui/ui.h
new file mode 100644
index 0000000..d264e05
--- /dev/null
+++ b/tools/perf/util/ui/ui.h
@@ -0,0 +1,8 @@
+#ifndef _PERF_UI_H_
+#define _PERF_UI_H_ 1
+
+#include <pthread.h>
+
+extern pthread_mutex_t ui__lock;
+
+#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/ui/util.c b/tools/perf/util/ui/util.c
index 7b5a892..fdf1fc8 100644
--- a/tools/perf/util/ui/util.c
+++ b/tools/perf/util/ui/util.c
@@ -9,6 +9,7 @@
 #include "../debug.h"
 #include "browser.h"
 #include "helpline.h"
+#include "ui.h"
 #include "util.h"
 
 static void newt_form__set_exit_keys(newtComponent self)
@@ -118,10 +119,12 @@ void ui__warning(const char *format, ...)
 	va_list args;
 
 	va_start(args, format);
-	if (use_browser > 0)
+	if (use_browser > 0) {
+		pthread_mutex_lock(&ui__lock);
 		newtWinMessagev((char *)warning_str, (char *)ok,
 				(char *)format, args);
-	else
+		pthread_mutex_unlock(&ui__lock);
+	} else
 		vfprintf(stderr, format, args);
 	va_end(args);
 }
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index e833f26..fc78428 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -70,9 +70,7 @@
 #include <sys/poll.h>
 #include <sys/socket.h>
 #include <sys/ioctl.h>
-#ifndef NO_SYS_SELECT_H
 #include <sys/select.h>
-#endif
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
@@ -83,10 +81,6 @@
 #include "types.h"
 #include <sys/ttydefaults.h>
 
-#ifndef NO_ICONV
-#include <iconv.h>
-#endif
-
 extern const char *graph_line;
 extern const char *graph_dotted_line;
 extern char buildid_dir[];
@@ -236,26 +230,6 @@ static inline int sane_case(int x, int high)
 	return x;
 }
 
-#ifndef DIR_HAS_BSD_GROUP_SEMANTICS
-# define FORCE_DIR_SET_GID S_ISGID
-#else
-# define FORCE_DIR_SET_GID 0
-#endif
-
-#ifdef NO_NSEC
-#undef USE_NSEC
-#define ST_CTIME_NSEC(st) 0
-#define ST_MTIME_NSEC(st) 0
-#else
-#ifdef USE_ST_TIMESPEC
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctimespec.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtimespec.tv_nsec))
-#else
-#define ST_CTIME_NSEC(st) ((unsigned int)((st).st_ctim.tv_nsec))
-#define ST_MTIME_NSEC(st) ((unsigned int)((st).st_mtim.tv_nsec))
-#endif
-#endif
-
 int mkdir_p(char *path, mode_t mode);
 int copyfile(const char *from, const char *to);
 
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index e1c62ee..8ce792e 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# Copywrite 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
+# Copyright 2010 - Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
 # Licensed under the terms of the GNU GPL License version 2
 #
 
@@ -37,6 +37,8 @@ $default{"POWEROFF_ON_SUCCESS"}	= 0;
 $default{"BUILD_OPTIONS"}	= "";
 $default{"BISECT_SLEEP_TIME"}	= 60;   # sleep time between bisects
 $default{"CLEAR_LOG"}		= 0;
+$default{"BISECT_MANUAL"}	= 0;
+$default{"BISECT_SKIP"}		= 1;
 $default{"SUCCESS_LINE"}	= "login:";
 $default{"BOOTED_TIMEOUT"}	= 1;
 $default{"DIE_ON_FAILURE"}	= 1;
@@ -45,6 +47,7 @@ $default{"SCP_TO_TARGET"}	= "scp \$SRC_FILE \$SSH_USER\@\$MACHINE:\$DST_FILE";
 $default{"REBOOT"}		= "ssh \$SSH_USER\@\$MACHINE reboot";
 $default{"STOP_AFTER_SUCCESS"}	= 10;
 $default{"STOP_AFTER_FAILURE"}	= 60;
+$default{"STOP_TEST_AFTER"}	= 600;
 $default{"LOCALVERSION"}	= "-test";
 
 my $ktest_config;
@@ -81,6 +84,8 @@ my $addconfig;
 my $in_bisect = 0;
 my $bisect_bad = "";
 my $reverse_bisect;
+my $bisect_manual;
+my $bisect_skip;
 my $in_patchcheck = 0;
 my $run_test;
 my $redirect;
@@ -98,6 +103,7 @@ my $console;
 my $success_line;
 my $stop_after_success;
 my $stop_after_failure;
+my $stop_test_after;
 my $build_target;
 my $target_image;
 my $localversion;
@@ -462,6 +468,10 @@ sub dodie {
 	`$power_off`;
     }
 
+    if (defined($opt{"LOG_FILE"})) {
+	print " See $opt{LOG_FILE} for more info.\n";
+    }
+
     die @_, "\n";
 }
 
@@ -760,8 +770,10 @@ sub monitor {
 
     my $success_start;
     my $failure_start;
+    my $monitor_start = time;
+    my $done = 0;
 
-    for (;;) {
+    while (!$done) {
 
 	if ($booted) {
 	    $line = wait_for_input($monitor_fp, $booted_timeout);
@@ -796,7 +808,7 @@ sub monitor {
 	}
 
 	if ($full_line =~ /call trace:/i) {
-	    if (!$skip_call_trace) {
+	    if (!$bug && !$skip_call_trace) {
 		$bug = 1;
 		$failure_start = time;
 	    }
@@ -816,12 +828,19 @@ sub monitor {
 	}
 
 	if ($full_line =~ /Kernel panic -/) {
+	    $failure_start = time;
 	    $bug = 1;
 	}
 
 	if ($line =~ /\n/) {
 	    $full_line = "";
 	}
+
+	if ($stop_test_after > 0 && !$booted && !$bug) {
+	    if (time - $monitor_start > $stop_test_after) {
+		$done = 1;
+	    }
+	}
     }
 
     close(DMESG);
@@ -925,6 +944,18 @@ sub check_buildlog {
     return 1;
 }
 
+sub make_oldconfig {
+    my ($defconfig) = @_;
+
+    if (!run_command "$defconfig $make oldnoconfig") {
+	# Perhaps oldnoconfig doesn't exist in this version of the kernel
+	# try a yes '' | oldconfig
+	doprint "oldnoconfig failed, trying yes '' | make oldconfig\n";
+	run_command "yes '' | $defconfig $make oldconfig" or
+	    dodie "failed make config oldconfig";
+    }
+}
+
 sub build {
     my ($type) = @_;
     my $defconfig = "";
@@ -970,8 +1001,12 @@ sub build {
 	$defconfig = "KCONFIG_ALLCONFIG=$minconfig";
     }
 
-    run_command "$defconfig $make $type" or
-	dodie "failed make config";
+    if ($type eq "oldnoconfig") {
+	make_oldconfig $defconfig;
+    } else {
+	run_command "$defconfig $make $type" or
+	    dodie "failed make config";
+    }
 
     $redirect = "$buildlog";
     if (!run_command "$make $build_options") {
@@ -1025,6 +1060,21 @@ sub get_version {
     doprint "$version\n";
 }
 
+sub answer_bisect {
+    for (;;) {
+	doprint "Pass or fail? [p/f]";
+	my $ans = <STDIN>;
+	chomp $ans;
+	if ($ans eq "p" || $ans eq "P") {
+	    return 1;
+	} elsif ($ans eq "f" || $ans eq "F") {
+	    return 0;
+	} else {
+	    print "Please answer 'P' or 'F'\n";
+	}
+    }
+}
+
 sub child_run_test {
     my $failed = 0;
 
@@ -1070,6 +1120,7 @@ sub do_run_test {
 
 	    # we are not guaranteed to get a full line
 	    $full_line .= $line;
+	    doprint $line;
 
 	    if ($full_line =~ /call trace:/i) {
 		$bug = 1;
@@ -1086,6 +1137,19 @@ sub do_run_test {
     } while (!$child_done && !$bug);
 
     if ($bug) {
+	my $failure_start = time;
+	my $now;
+	do {
+	    $line = wait_for_input($monitor_fp, 1);
+	    if (defined($line)) {
+		doprint $line;
+	    }
+	    $now = time;
+	    if ($now - $failure_start >= $stop_after_failure) {
+		last;
+	    }
+	} while (defined($line));
+
 	doprint "Detected kernel crash!\n";
 	# kill the child with extreme prejudice
 	kill 9, $child_pid;
@@ -1131,7 +1195,15 @@ sub run_git_bisect {
     return 1;
 }
 
-# returns 1 on success, 0 on failure
+sub bisect_reboot {
+    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
+    reboot;
+    start_monitor;
+    wait_for_monitor $bisect_sleep_time;
+    end_monitor;
+}
+
+# returns 1 on success, 0 on failure, -1 on skip
 sub run_bisect_test {
     my ($type, $buildtype) = @_;
 
@@ -1145,6 +1217,10 @@ sub run_bisect_test {
     build $buildtype or $failed = 1;
 
     if ($type ne "build") {
+	if ($failed && $bisect_skip) {
+	    $in_bisect = 0;
+	    return -1;
+	}
 	dodie "Failed on build" if $failed;
 
 	# Now boot the box
@@ -1156,6 +1232,12 @@ sub run_bisect_test {
 	monitor or $failed = 1;
 
 	if ($type ne "boot") {
+	    if ($failed && $bisect_skip) {
+		end_monitor;
+		bisect_reboot;
+		$in_bisect = 0;
+		return -1;
+	    }
 	    dodie "Failed on boot" if $failed;
 
 	    do_run_test or $failed = 1;
@@ -1168,11 +1250,7 @@ sub run_bisect_test {
 
 	# reboot the box to a good kernel
 	if ($type ne "build") {
-	    doprint "Reboot and sleep $bisect_sleep_time seconds\n";
-	    reboot;
-	    start_monitor;
-	    wait_for_monitor $bisect_sleep_time;
-	    end_monitor;
+	    bisect_reboot;
 	}
     } else {
 	$result = 1;
@@ -1193,16 +1271,22 @@ sub run_bisect {
 
     my $ret = run_bisect_test $type, $buildtype;
 
+    if ($bisect_manual) {
+	$ret = answer_bisect;
+    }
 
     # Are we looking for where it worked, not failed?
     if ($reverse_bisect) {
 	$ret = !$ret;
     }
 
-    if ($ret) {
+    if ($ret > 0) {
 	return "good";
-    } else {
+    } elsif ($ret == 0) {
 	return  "bad";
+    } elsif ($bisect_skip) {
+	doprint "HIT A BAD COMMIT ... SKIPPING\n";
+	return "skip";
     }
 }
 
@@ -1220,6 +1304,13 @@ sub bisect {
     my $type = $opt{"BISECT_TYPE[$i]"};
     my $start = $opt{"BISECT_START[$i]"};
     my $replay = $opt{"BISECT_REPLAY[$i]"};
+    my $start_files = $opt{"BISECT_FILES[$i]"};
+
+    if (defined($start_files)) {
+	$start_files = " -- " . $start_files;
+    } else {
+	$start_files = "";
+    }
 
     # convert to true sha1's
     $good = get_sha1($good);
@@ -1273,7 +1364,7 @@ sub bisect {
 	    die "Failed to checkout $head";
     }
 
-    run_command "git bisect start" or
+    run_command "git bisect start$start_files" or
 	dodie "could not start bisect";
 
     run_command "git bisect good $good" or
@@ -1390,9 +1481,7 @@ sub create_config {
     close(OUT);
 
 #    exit;
-    run_command "$make oldnoconfig" or
-	dodie "failed make config oldconfig";
-
+    make_oldconfig "";
 }
 
 sub compare_configs {
@@ -1505,7 +1594,9 @@ sub run_config_bisect {
 	}
 
 	$ret = run_config_bisect_test $type;
-
+	if ($bisect_manual) {
+	    $ret = answer_bisect;
+	}
 	if ($ret) {
 	    process_passed %current_config;
 	    return 0;
@@ -1536,7 +1627,13 @@ sub run_config_bisect {
 	$half = int($#start_list / 2);
     } while ($half > 0);
 
-    # we found a single config, try it again
+    # we found a single config, try it again unless we are running manually
+
+    if ($bisect_manual) {
+	process_failed $start_list[0];
+	return 1;
+    }
+
     my @tophalf = @start_list[0 .. 0];
 
     $ret = run_config_bisect_test $type;
@@ -1594,8 +1691,7 @@ sub config_bisect {
     close(IN);
 
     # Now run oldconfig with the minconfig (and addconfigs)
-    run_command "$defconfig $make oldnoconfig" or
-	dodie "failed make config oldconfig";
+    make_oldconfig $defconfig;
 
     # check to see what we lost (or gained)
     open (IN, $output_config)
@@ -1907,6 +2003,8 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $poweroff_after_halt = set_test_option("POWEROFF_AFTER_HALT", $i);
     $sleep_time = set_test_option("SLEEP_TIME", $i);
     $bisect_sleep_time = set_test_option("BISECT_SLEEP_TIME", $i);
+    $bisect_manual = set_test_option("BISECT_MANUAL", $i);
+    $bisect_skip = set_test_option("BISECT_SKIP", $i);
     $store_failures = set_test_option("STORE_FAILURES", $i);
     $timeout = set_test_option("TIMEOUT", $i);
     $booted_timeout = set_test_option("BOOTED_TIMEOUT", $i);
@@ -1914,6 +2012,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $success_line = set_test_option("SUCCESS_LINE", $i);
     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
+    $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
     $build_target = set_test_option("BUILD_TARGET", $i);
     $ssh_exec = set_test_option("SSH_EXEC", $i);
     $scp_to_target = set_test_option("SCP_TO_TARGET", $i);
diff --git a/tools/testing/ktest/sample.conf b/tools/testing/ktest/sample.conf
index 3408c59..4c5d6bd 100644
--- a/tools/testing/ktest/sample.conf
+++ b/tools/testing/ktest/sample.conf
@@ -306,6 +306,14 @@
 # (default 60)
 #STOP_AFTER_FAILURE = 60
 
+# In case the console constantly fills the screen, having
+# a specified time to stop the test if it never succeeds nor fails
+# is recommended.
+# Note: this is ignored if a success or failure is detected.
+# (in seconds)
+# (default 600, -1 is to never stop)
+#STOP_TEST_AFTER = 600
+
 # Stop testing if a build fails. If set, the script will end if
 # a failure is detected, otherwise it will save off the .config,
 # dmesg and bootlog in a directory called
@@ -519,6 +527,24 @@
 #   git bisect good, git bisect bad, and running the git bisect replay
 #   if the BISECT_REPLAY is set.
 #
+# BISECT_SKIP = 1 (optional, default 0)
+#
+#   If BISECT_TYPE is set to test but the build fails, ktest will
+#   simply fail the test and end their. You could use BISECT_REPLAY
+#   and BISECT_START to resume after you found a new starting point,
+#   or you could set BISECT_SKIP to 1. If BISECT_SKIP is set to 1,
+#   when something other than the BISECT_TYPE fails, ktest.pl will
+#   run "git bisect skip" and try again.
+#
+# BISECT_FILES = <path> (optional, default undefined)
+#
+#   To just run the git bisect on a specific path, set BISECT_FILES.
+#   For example:
+#
+#     BISECT_FILES = arch/x86 kernel/time
+#
+#   Will run the bisect with "git bisect start -- arch/x86 kernel/time"
+#
 # BISECT_REVERSE = 1 (optional, default 0)
 #
 #   In those strange instances where it was broken forever
@@ -528,6 +554,15 @@
 #   With BISECT_REVERSE = 1, The test will consider failures as
 #   good, and success as bad.
 #
+# BISECT_MANUAL = 1 (optional, default 0)
+#
+#   In case there's a problem with automating the bisect for
+#   whatever reason. (Can't reboot, want to inspect each iteration)
+#   Doing a BISECT_MANUAL will have the test wait for you to
+#   tell it if the test passed or failed after each iteration.
+#   This is basicall the same as running git bisect yourself
+#   but ktest will rebuild and install the kernel for you.
+#
 # BISECT_CHECK = 1 (optional, default 0)
 #
 #   Just to be sure the good is good and bad is bad, setting
@@ -613,10 +648,17 @@
 #
 #   CONFIG_BISECT is the config that failed to boot
 #
+#   If BISECT_MANUAL is set, it will pause between iterations.
+#   This is useful to use just ktest.pl just for the config bisect.
+#   If you set it to build, it will run the bisect and you can
+#   control what happens in between iterations. It will ask you if
+#   the test succeeded or not and continue the config bisect.
+#
 # Example:
 #   TEST_START
 #   TEST_TYPE = config_bisect
 #   CONFIG_BISECT_TYPE = build
 #   CONFIG_BISECT = /home/test/˘onfig-bad
 #   MIN_CONFIG = /home/test/config-min
+#   BISECT_MANUAL = 1
 #
diff --git a/tools/usb/Makefile b/tools/usb/Makefile
new file mode 100644
index 0000000..8b704af
--- /dev/null
+++ b/tools/usb/Makefile
@@ -0,0 +1,13 @@
+# Makefile for USB tools
+
+CC = $(CROSS_COMPILE)gcc
+PTHREAD_LIBS = -lpthread
+WARNINGS = -Wall -Wextra
+CFLAGS = $(WARNINGS) -g $(PTHREAD_LIBS)
+
+all: testusb ffs-test
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $^
+
+clean:
+	$(RM) testusb ffs-test
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index bbe2e3a..b9c7986 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -37,7 +37,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <linux/usb/functionfs.h>
+#include "../../include/linux/usb/functionfs.h"
 
 
 /******************** Little Endian Handling ********************************/
@@ -450,7 +450,7 @@ invalid:
 		    len, expected, *p);
 		for (p = buf, len = 0; len < nbytes; ++p, ++len) {
 			if (0 == (len % 32))
-				fprintf(stderr, "%4d:", len);
+				fprintf(stderr, "%4zd:", len);
 			fprintf(stderr, " %02x", *p);
 			if (31 == (len % 32))
 				fprintf(stderr, "\n");
diff --git a/tools/usb/hcd-tests.sh b/tools/usb/hcd-tests.sh
new file mode 100644
index 0000000..b30b3dc
--- /dev/null
+++ b/tools/usb/hcd-tests.sh
@@ -0,0 +1,275 @@
+#!/bin/sh
+#
+# test types can be passed on the command line:
+#
+# - control: any device can do this
+# - out, in:  out needs 'bulk sink' firmware, in needs 'bulk src'
+# - iso-out, iso-in:  out needs 'iso sink' firmware, in needs 'iso src'
+# - halt: needs bulk sink+src, tests halt set/clear from host
+# - unlink: needs bulk sink and/or src, test HCD unlink processing
+# - loop: needs firmware that will buffer N transfers
+#
+# run it for hours, days, weeks.
+#
+
+#
+# this default provides a steady test load for a bulk device
+#
+TYPES='control out in'
+#TYPES='control out in halt'
+
+#
+# to test HCD code
+#
+#  - include unlink tests
+#  - add some ${RANDOM}ness
+#  - connect several devices concurrently (same HC)
+#  - keep HC's IRQ lines busy with unrelated traffic (IDE, net, ...)
+#  - add other concurrent system loads
+#
+
+declare -i COUNT BUFLEN
+
+COUNT=50000
+BUFLEN=2048
+
+# NOTE:  the 'in' and 'out' cases are usually bulk, but can be
+# set up to use interrupt transfers by 'usbtest' module options
+
+
+if [ "$DEVICE" = "" ]; then
+	echo "testing ALL recognized usbtest devices"
+	echo ""
+	TEST_ARGS="-a"
+else
+	TEST_ARGS=""
+fi
+
+do_test ()
+{
+    if ! ./testusb $TEST_ARGS -s $BUFLEN -c $COUNT $* 2>/dev/null
+    then
+	echo "FAIL"
+	exit 1
+    fi
+}
+
+ARGS="$*"
+
+if [ "$ARGS" = "" ];
+then
+    ARGS="$TYPES"
+fi
+
+# FIXME use /sys/bus/usb/device/$THIS/bConfigurationValue to
+# check and change configs
+
+CONFIG=''
+
+check_config ()
+{
+    if [ "$CONFIG" = "" ]; then
+	CONFIG=$1
+	echo "assuming $CONFIG configuration"
+	return
+    fi
+    if [ "$CONFIG" = $1 ]; then
+	return
+    fi
+
+    echo "** device must be in $1 config, but it's $CONFIG instead"
+    exit 1
+}
+
+
+echo "TESTING:  $ARGS"
+
+while : true
+do
+    echo $(date)
+
+    for TYPE in $ARGS
+    do
+	# restore defaults
+	COUNT=5000
+	BUFLEN=2048
+
+	# FIXME automatically multiply COUNT by 10 when
+	# /sys/bus/usb/device/$THIS/speed == "480"
+
+#	COUNT=50000
+
+	case $TYPE in
+	control)
+	    # any device, in any configuration, can use this.
+	    echo '** Control test cases:'
+
+	    echo "test 9: ch9 postconfig"
+	    do_test -t 9 -c 5000
+	    echo "test 10: control queueing"
+	    do_test -t 10 -c 5000
+
+	    # this relies on some vendor-specific commands
+	    echo "test 14: control writes"
+	    do_test -t 14 -c 15000 -s 256 -v 1
+
+	    echo "test 21: control writes, unaligned"
+	    do_test -t 21 -c 100 -s 256 -v 1
+
+	    ;;
+
+	out)
+	    check_config sink-src
+	    echo '** Host Write (OUT) test cases:'
+
+	    echo "test 1: $COUNT transfers, same size"
+	    do_test -t 1
+	    echo "test 3: $COUNT transfers, variable/short size"
+	    do_test -t 3 -v 421
+
+	    COUNT=100
+	    echo "test 17: $COUNT transfers, unaligned DMA map by core"
+	    do_test -t 17
+
+	    echo "test 19: $COUNT transfers, unaligned DMA map by usb_alloc_coherent"
+	    do_test -t 19
+
+	    COUNT=2000
+	    echo "test 5: $COUNT scatterlists, same size entries"
+	    do_test -t 5
+
+	    # try to trigger short OUT processing bugs
+	    echo "test 7a: $COUNT scatterlists, variable size/short entries"
+	    do_test -t 7 -v 579
+	    BUFLEN=4096
+	    echo "test 7b: $COUNT scatterlists, variable size/bigger entries"
+	    do_test -t 7 -v 41
+	    BUFLEN=64
+	    echo "test 7c: $COUNT scatterlists, variable size/micro entries"
+	    do_test -t 7 -v 63
+	    ;;
+
+	iso-out)
+	    check_config sink-src
+	    echo '** Host ISOCHRONOUS Write (OUT) test cases:'
+
+	    # at peak iso transfer rates:
+	    # - usb 2.0 high bandwidth, this is one frame.
+	    # - usb 1.1, it's twenty-four frames.
+	    BUFLEN=24500
+
+	    COUNT=1000
+
+# COUNT=10000
+
+	    echo "test 15: $COUNT transfers, same size"
+	    # do_test -t 15 -g 3 -v 0
+	    BUFLEN=32768
+	    do_test -t 15 -g 8 -v 0
+
+	    # FIXME it'd make sense to have an iso OUT test issuing
+	    # short writes on more packets than the last one
+
+	    COUNT=100
+	    echo "test 22: $COUNT transfers, non aligned"
+	    do_test -t 22 -g 8 -v 0
+
+	    ;;
+
+	in)
+	    check_config sink-src
+	    echo '** Host Read (IN) test cases:'
+
+	    # NOTE:  these "variable size" reads are just multiples
+	    # of 512 bytes, no EOVERFLOW testing is done yet
+
+	    echo "test 2: $COUNT transfers, same size"
+	    do_test -t 2
+	    echo "test 4: $COUNT transfers, variable size"
+	    do_test -t 4
+
+	    COUNT=100
+	    echo "test 18: $COUNT transfers, unaligned DMA map by core"
+	    do_test -t 18
+
+	    echo "test 20: $COUNT transfers, unaligned DMA map by usb_alloc_coherent"
+	    do_test -t 20
+
+	    COUNT=2000
+	    echo "test 6: $COUNT scatterlists, same size entries"
+	    do_test -t 6
+	    echo "test 8: $COUNT scatterlists, variable size entries"
+	    do_test -t 8
+	    ;;
+
+	iso-in)
+	    check_config sink-src
+	    echo '** Host ISOCHRONOUS Read (IN) test cases:'
+
+	    # at peak iso transfer rates:
+	    # - usb 2.0 high bandwidth, this is one frame.
+	    # - usb 1.1, it's twenty-four frames.
+	    BUFLEN=24500
+
+	    COUNT=1000
+
+# COUNT=10000
+
+	    echo "test 16: $COUNT transfers, same size"
+	    # do_test -t 16 -g 3 -v 0
+	    BUFLEN=32768
+	    do_test -t 16 -g 8 -v 0
+
+	    # FIXME since iso expects faults, it'd make sense
+	    # to have an iso IN test issuing short reads ...
+
+	    COUNT=100
+	    echo "test 23: $COUNT transfers, unaligned"
+	    do_test -t 23 -g 8 -v 0
+
+	    ;;
+
+	halt)
+	    # NOTE:  sometimes hardware doesn't cooperate well with halting
+	    # endpoints from the host side.  so long as mass-storage class
+	    # firmware can halt them from the device, don't worry much if
+	    # you can't make this test work on your device.
+	    COUNT=2000
+	    echo "test 13: $COUNT halt set/clear"
+	    do_test -t 13
+	    ;;
+
+	unlink)
+	    COUNT=2000
+	    echo "test 11: $COUNT read unlinks"
+	    do_test -t 11
+
+	    echo "test 12: $COUNT write unlinks"
+	    do_test -t 12
+	    ;;
+
+	loop)
+	    # defaults need too much buffering for ez-usb devices
+	    BUFLEN=2048
+	    COUNT=32
+
+	    # modprobe g_zero qlen=$COUNT buflen=$BUFLEN loopdefault
+	    check_config loopback
+
+	    # FIXME someone needs to write and merge a version of this
+
+	    echo "write $COUNT buffers of $BUFLEN bytes, read them back"
+
+	    echo "write $COUNT variable size buffers, read them back"
+
+	    ;;
+
+	*)
+	    echo "Don't understand test type $TYPE"
+	    exit 1;
+	esac
+	echo ''
+    done
+done
+
+# vim: sw=4
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 2ca4535..3656849 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -313,8 +313,9 @@ kvm_irqfd_deassign(struct kvm *kvm, int fd, int gsi)
 		if (irqfd->eventfd == eventfd && irqfd->gsi == gsi) {
 			/*
 			 * This rcu_assign_pointer is needed for when
-			 * another thread calls kvm_irqfd_update before
-			 * we flush workqueue below.
+			 * another thread calls kvm_irq_routing_update before
+			 * we flush workqueue below (we synchronize with
+			 * kvm_irq_routing_update using irqfds.lock).
 			 * It is paired with synchronize_rcu done by caller
 			 * of that function.
 			 */
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index f29abeb..1fa0d29 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -69,7 +69,7 @@ MODULE_LICENSE("GPL");
  * 		kvm->lock --> kvm->slots_lock --> kvm->irq_lock
  */
 
-DEFINE_SPINLOCK(kvm_lock);
+DEFINE_RAW_SPINLOCK(kvm_lock);
 LIST_HEAD(vm_list);
 
 static cpumask_var_t cpus_hardware_enabled;
@@ -137,6 +137,14 @@ void vcpu_load(struct kvm_vcpu *vcpu)
 	int cpu;
 
 	mutex_lock(&vcpu->mutex);
+	if (unlikely(vcpu->pid != current->pids[PIDTYPE_PID].pid)) {
+		/* The thread running this VCPU changed. */
+		struct pid *oldpid = vcpu->pid;
+		struct pid *newpid = get_task_pid(current, PIDTYPE_PID);
+		rcu_assign_pointer(vcpu->pid, newpid);
+		synchronize_rcu();
+		put_pid(oldpid);
+	}
 	cpu = get_cpu();
 	preempt_notifier_register(&vcpu->preempt_notifier);
 	kvm_arch_vcpu_load(vcpu, cpu);
@@ -165,13 +173,16 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
 
 	zalloc_cpumask_var(&cpus, GFP_ATOMIC);
 
-	raw_spin_lock(&kvm->requests_lock);
-	me = smp_processor_id();
+	me = get_cpu();
 	kvm_for_each_vcpu(i, vcpu, kvm) {
-		if (kvm_make_check_request(req, vcpu))
-			continue;
+		kvm_make_request(req, vcpu);
 		cpu = vcpu->cpu;
-		if (cpus != NULL && cpu != -1 && cpu != me)
+
+		/* Set ->requests bit before we read ->mode */
+		smp_mb();
+
+		if (cpus != NULL && cpu != -1 && cpu != me &&
+		      kvm_vcpu_exiting_guest_mode(vcpu) != OUTSIDE_GUEST_MODE)
 			cpumask_set_cpu(cpu, cpus);
 	}
 	if (unlikely(cpus == NULL))
@@ -180,7 +191,7 @@ static bool make_all_cpus_request(struct kvm *kvm, unsigned int req)
 		smp_call_function_many(cpus, ack_flush, NULL, 1);
 	else
 		called = false;
-	raw_spin_unlock(&kvm->requests_lock);
+	put_cpu();
 	free_cpumask_var(cpus);
 	return called;
 }
@@ -209,6 +220,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id)
 	vcpu->cpu = -1;
 	vcpu->kvm = kvm;
 	vcpu->vcpu_id = id;
+	vcpu->pid = NULL;
 	init_waitqueue_head(&vcpu->wq);
 	kvm_async_pf_vcpu_init(vcpu);
 
@@ -233,6 +245,7 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_init);
 
 void kvm_vcpu_uninit(struct kvm_vcpu *vcpu)
 {
+	put_pid(vcpu->pid);
 	kvm_arch_vcpu_uninit(vcpu);
 	free_page((unsigned long)vcpu->run);
 }
@@ -463,15 +476,14 @@ static struct kvm *kvm_create_vm(void)
 	kvm->mm = current->mm;
 	atomic_inc(&kvm->mm->mm_count);
 	spin_lock_init(&kvm->mmu_lock);
-	raw_spin_lock_init(&kvm->requests_lock);
 	kvm_eventfd_init(kvm);
 	mutex_init(&kvm->lock);
 	mutex_init(&kvm->irq_lock);
 	mutex_init(&kvm->slots_lock);
 	atomic_set(&kvm->users_count, 1);
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	list_add(&kvm->vm_list, &vm_list);
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 
 	return kvm;
 
@@ -544,9 +556,9 @@ static void kvm_destroy_vm(struct kvm *kvm)
 	struct mm_struct *mm = kvm->mm;
 
 	kvm_arch_sync_events(kvm);
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	list_del(&kvm->vm_list);
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 	kvm_free_irq_routing(kvm);
 	for (i = 0; i < KVM_NR_BUSES; i++)
 		kvm_io_bus_destroy(kvm->buses[i]);
@@ -588,6 +600,7 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
 	return 0;
 }
 
+#ifndef CONFIG_S390
 /*
  * Allocation size is twice as large as the actual dirty bitmap size.
  * This makes it possible to do double buffering: see x86's
@@ -608,6 +621,7 @@ static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
 	memslot->dirty_bitmap_head = memslot->dirty_bitmap;
 	return 0;
 }
+#endif /* !CONFIG_S390 */
 
 /*
  * Allocate some memory and give it an address in the guest physical address
@@ -621,7 +635,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
 			    struct kvm_userspace_memory_region *mem,
 			    int user_alloc)
 {
-	int r, flush_shadow = 0;
+	int r;
 	gfn_t base_gfn;
 	unsigned long npages;
 	unsigned long i;
@@ -741,8 +755,6 @@ skip_lpage:
 		if (kvm_create_dirty_bitmap(&new) < 0)
 			goto out_free;
 		/* destroy any largepage mappings for dirty tracking */
-		if (old.npages)
-			flush_shadow = 1;
 	}
 #else  /* not defined CONFIG_S390 */
 	new.user_alloc = user_alloc;
@@ -813,9 +825,6 @@ skip_lpage:
 	kvm_free_physmem_slot(&old, &new);
 	kfree(old_memslots);
 
-	if (flush_shadow)
-		kvm_arch_flush_shadow(kvm);
-
 	return 0;
 
 out_free:
@@ -1029,6 +1038,15 @@ static pfn_t get_fault_pfn(void)
 	return fault_pfn;
 }
 
+static inline int check_user_page_hwpoison(unsigned long addr)
+{
+	int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE;
+
+	rc = __get_user_pages(current, current->mm, addr, 1,
+			      flags, NULL, NULL, NULL);
+	return rc == -EHWPOISON;
+}
+
 static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
 			bool *async, bool write_fault, bool *writable)
 {
@@ -1076,7 +1094,7 @@ static pfn_t hva_to_pfn(struct kvm *kvm, unsigned long addr, bool atomic,
 			return get_fault_pfn();
 
 		down_read(&current->mm->mmap_sem);
-		if (is_hwpoison_address(addr)) {
+		if (check_user_page_hwpoison(addr)) {
 			up_read(&current->mm->mmap_sem);
 			get_page(hwpoison_page);
 			return page_to_pfn(hwpoison_page);
@@ -1466,18 +1484,55 @@ void kvm_resched(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_resched);
 
-void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu)
+void kvm_vcpu_on_spin(struct kvm_vcpu *me)
 {
-	ktime_t expires;
-	DEFINE_WAIT(wait);
-
-	prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
-
-	/* Sleep for 100 us, and hope lock-holder got scheduled */
-	expires = ktime_add_ns(ktime_get(), 100000UL);
-	schedule_hrtimeout(&expires, HRTIMER_MODE_ABS);
+	struct kvm *kvm = me->kvm;
+	struct kvm_vcpu *vcpu;
+	int last_boosted_vcpu = me->kvm->last_boosted_vcpu;
+	int yielded = 0;
+	int pass;
+	int i;
 
-	finish_wait(&vcpu->wq, &wait);
+	/*
+	 * We boost the priority of a VCPU that is runnable but not
+	 * currently running, because it got preempted by something
+	 * else and called schedule in __vcpu_run.  Hopefully that
+	 * VCPU is holding the lock that we need and will release it.
+	 * We approximate round-robin by starting at the last boosted VCPU.
+	 */
+	for (pass = 0; pass < 2 && !yielded; pass++) {
+		kvm_for_each_vcpu(i, vcpu, kvm) {
+			struct task_struct *task = NULL;
+			struct pid *pid;
+			if (!pass && i < last_boosted_vcpu) {
+				i = last_boosted_vcpu;
+				continue;
+			} else if (pass && i > last_boosted_vcpu)
+				break;
+			if (vcpu == me)
+				continue;
+			if (waitqueue_active(&vcpu->wq))
+				continue;
+			rcu_read_lock();
+			pid = rcu_dereference(vcpu->pid);
+			if (pid)
+				task = get_pid_task(vcpu->pid, PIDTYPE_PID);
+			rcu_read_unlock();
+			if (!task)
+				continue;
+			if (task->flags & PF_VCPU) {
+				put_task_struct(task);
+				continue;
+			}
+			if (yield_to(task, 1)) {
+				put_task_struct(task);
+				kvm->last_boosted_vcpu = i;
+				yielded = 1;
+				break;
+			}
+			put_task_struct(task);
+		}
+	}
 }
 EXPORT_SYMBOL_GPL(kvm_vcpu_on_spin);
 
@@ -2122,9 +2177,9 @@ static void hardware_enable_nolock(void *junk)
 
 static void hardware_enable(void *junk)
 {
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	hardware_enable_nolock(junk);
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 }
 
 static void hardware_disable_nolock(void *junk)
@@ -2139,9 +2194,9 @@ static void hardware_disable_nolock(void *junk)
 
 static void hardware_disable(void *junk)
 {
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	hardware_disable_nolock(junk);
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 }
 
 static void hardware_disable_all_nolock(void)
@@ -2155,16 +2210,16 @@ static void hardware_disable_all_nolock(void)
 
 static void hardware_disable_all(void)
 {
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	hardware_disable_all_nolock();
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 }
 
 static int hardware_enable_all(void)
 {
 	int r = 0;
 
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 
 	kvm_usage_count++;
 	if (kvm_usage_count == 1) {
@@ -2177,7 +2232,7 @@ static int hardware_enable_all(void)
 		}
 	}
 
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 
 	return r;
 }
@@ -2339,10 +2394,10 @@ static int vm_stat_get(void *_offset, u64 *val)
 	struct kvm *kvm;
 
 	*val = 0;
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	list_for_each_entry(kvm, &vm_list, vm_list)
 		*val += *(u32 *)((void *)kvm + offset);
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 	return 0;
 }
 
@@ -2356,12 +2411,12 @@ static int vcpu_stat_get(void *_offset, u64 *val)
 	int i;
 
 	*val = 0;
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	list_for_each_entry(kvm, &vm_list, vm_list)
 		kvm_for_each_vcpu(i, vcpu, kvm)
 			*val += *(u32 *)((void *)vcpu + offset);
 
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 	return 0;
 }
 
@@ -2402,7 +2457,7 @@ static int kvm_suspend(struct sys_device *dev, pm_message_t state)
 static int kvm_resume(struct sys_device *dev)
 {
 	if (kvm_usage_count) {
-		WARN_ON(spin_is_locked(&kvm_lock));
+		WARN_ON(raw_spin_is_locked(&kvm_lock));
 		hardware_enable_nolock(NULL);
 	}
 	return 0;
